[
  {
    "path": ".gitattributes",
    "content": "# Treat all files in this repo as binary, with no git magic updating\n# line endings. Windows users contributing to Go will need to use a\n# modern version of git and editors capable of LF line endings.\n#\n# We'll prevent accidental CRLF line endings from entering the repo\n# via the git-review gofmt checks.\n#\n# See golang.org/issue/9281\n\n* -text\n"
  },
  {
    "path": ".gitignore",
    "content": "# Add no patterns to .gitignore except for files generated by the build.\nlast-change\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"es5\"\n}"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Go\n\nGo is an open source project.\n\nIt is the work of hundreds of contributors. We appreciate your help!\n\n## Filing issues\n\nWhen [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:\n\n1.  What version of Go are you using (`go version`)?\n2.  What operating system and processor architecture are you using?\n3.  What did you do?\n4.  What did you expect to see?\n5.  What did you see instead?\n\nGeneral questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.\nThe gophers there will answer or ask you to file an issue if you've tripped over a bug.\n\n## Contributing code\n\nPlease read the [Contribution Guidelines](https://golang.org/doc/contribute.html)\nbefore sending patches.\n\nUnless otherwise noted, the Go source files are distributed under\nthe BSD-style license found in the LICENSE file.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright 2009 The Go Authors.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google LLC nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "PATENTS",
    "content": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part of the Go project.\n\nGoogle hereby grants to You a perpetual, worldwide, non-exclusive,\nno-charge, royalty-free, irrevocable (except as stated in this section)\npatent license to make, have made, use, offer to sell, sell, import,\ntransfer and otherwise run, modify and propagate the contents of this\nimplementation of Go, where such license applies only to those patent\nclaims, both currently owned or controlled by Google and acquired in\nthe future, licensable by Google that are necessarily infringed by this\nimplementation of Go.  This grant does not include claims that would be\ninfringed only as a consequence of further modification of this\nimplementation.  If you or your agent or exclusive licensee institute or\norder or agree to the institution of patent litigation against any\nentity (including a cross-claim or counterclaim in a lawsuit) alleging\nthat this implementation of Go or any code incorporated within this\nimplementation of Go constitutes direct or contributory patent\ninfringement, or inducement of patent infringement, then any patent\nrights granted to you under this License for this implementation of Go\nshall terminate as of the date such litigation is filed.\n"
  },
  {
    "path": "README.md",
    "content": "# Go Tools\n\n[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools)](https://pkg.go.dev/golang.org/x/tools)\n\nThis repository provides the `golang.org/x/tools` module, comprising\nvarious tools and packages mostly for static analysis of Go programs,\nsome of which are listed below.\nUse the \"Go reference\" link above for more information about any package.\n\nIt also contains the\n[`golang.org/x/tools/gopls`](https://pkg.go.dev/golang.org/x/tools/gopls)\nmodule, whose root package is a language-server protocol (LSP) server for Go.\nAn LSP server analyses the source code of a project and\nresponds to requests from a wide range of editors such as VSCode and\nVim, allowing them to support IDE-like functionality.\n\n<!-- List only packages of general interest below. -->\n\nSelected commands:\n\n- `cmd/goimports` formats a Go program like `go fmt` and additionally\n  inserts import statements for any packages required by the file\n  after it is edited.\n- `cmd/callgraph` prints the call graph of a Go program.\n- `cmd/digraph` is a utility for manipulating directed graphs in textual notation.\n- `cmd/stringer` generates declarations (including a `String` method) for \"enum\" types.\n- `cmd/toolstash` is a utility to simplify working with multiple versions of the Go toolchain.\n\nThese commands may be fetched with a command such as\n```\ngo install golang.org/x/tools/cmd/goimports@latest\n```\n\nSelected packages:\n\n- `go/ssa` provides a static single-assignment form (SSA) intermediate\n  representation (IR) for Go programs, similar to a typical compiler,\n  for use by analysis tools.\n\n- `go/packages` provides a simple interface for loading, parsing, and\n  type checking a complete Go program from source code.\n\n- `go/analysis` provides a framework for modular static analysis of Go\n  programs.\n\n- `go/callgraph` provides call graphs of Go programs using a variety\n  of algorithms with different trade-offs.\n\n- `go/ast/inspector` provides an optimized means of traversing a Go\n  parse tree for use in analysis tools.\n\n- `go/cfg` provides a simple control-flow graph (CFG) for a Go function.\n\n- `go/gcexportdata` and `go/gccgoexportdata` read and write the binary\n  files containing type information used by the standard and `gccgo` compilers.\n\n- `go/types/objectpath` provides a stable naming scheme for named\n  entities (\"objects\") in the `go/types` API.\n\nNumerous other packages provide more esoteric functionality.\n\n<!-- Some that didn't make the cut:\n\ngolang.org/x/tools/benchmark/parse\ngolang.org/x/tools/go/ast/astutil\ngolang.org/x/tools/go/types/typeutil\ngolang.org/x/tools/playground\ngolang.org/x/tools/present\ngolang.org/x/tools/refactor/importgraph\ngolang.org/x/tools/refactor/rename\ngolang.org/x/tools/refactor/satisfy\ngolang.org/x/tools/txtar\n\n-->\n\n## Contributing\n\nThis repository uses Gerrit for code changes.\nTo learn how to submit changes, see https://go.dev/doc/contribute.\n\nThe git repository is https://go.googlesource.com/tools.\n\nThe main issue tracker for the tools repository is located at\nhttps://go.dev/issues. Prefix your issue with \"x/tools/(your\nsubdir):\" in the subject line, so it is easy to find.\n\n### JavaScript and CSS Formatting\n\nThis repository uses [prettier](https://prettier.io/) to format JS and CSS files.\n\nThe version of `prettier` used is 1.18.2.\n\nIt is encouraged that all JS and CSS code be run through this before submitting\na change. However, it is not a strict requirement enforced by CI.\n"
  },
  {
    "path": "benchmark/parse/parse.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package parse provides support for parsing benchmark results as\n// generated by 'go test -bench'.\npackage parse // import \"golang.org/x/tools/benchmark/parse\"\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Flags used by Benchmark.Measured to indicate\n// which measurements a Benchmark contains.\nconst (\n\tNsPerOp = 1 << iota\n\tMBPerS\n\tAllocedBytesPerOp\n\tAllocsPerOp\n)\n\n// Benchmark is one run of a single benchmark.\ntype Benchmark struct {\n\tName              string  // benchmark name\n\tN                 int     // number of iterations\n\tNsPerOp           float64 // nanoseconds per iteration\n\tAllocedBytesPerOp uint64  // bytes allocated per iteration\n\tAllocsPerOp       uint64  // allocs per iteration\n\tMBPerS            float64 // MB processed per second\n\tMeasured          int     // which measurements were recorded\n\tOrd               int     // ordinal position within a benchmark run\n}\n\n// ParseLine extracts a Benchmark from a single line of testing.B\n// output.\nfunc ParseLine(line string) (*Benchmark, error) {\n\tfields := strings.Fields(line)\n\n\t// Two required, positional fields: Name and iterations.\n\tif len(fields) < 2 {\n\t\treturn nil, fmt.Errorf(\"two fields required, have %d\", len(fields))\n\t}\n\tif !strings.HasPrefix(fields[0], \"Benchmark\") {\n\t\treturn nil, fmt.Errorf(`first field does not start with \"Benchmark\"`)\n\t}\n\tn, err := strconv.Atoi(fields[1])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tb := &Benchmark{Name: fields[0], N: n}\n\n\t// Parse any remaining pairs of fields; we've parsed one pair already.\n\tfor i := 1; i < len(fields)/2; i++ {\n\t\tb.parseMeasurement(fields[i*2], fields[i*2+1])\n\t}\n\treturn b, nil\n}\n\nfunc (b *Benchmark) parseMeasurement(quant string, unit string) {\n\tswitch unit {\n\tcase \"ns/op\":\n\t\tif f, err := strconv.ParseFloat(quant, 64); err == nil {\n\t\t\tb.NsPerOp = f\n\t\t\tb.Measured |= NsPerOp\n\t\t}\n\tcase \"MB/s\":\n\t\tif f, err := strconv.ParseFloat(quant, 64); err == nil {\n\t\t\tb.MBPerS = f\n\t\t\tb.Measured |= MBPerS\n\t\t}\n\tcase \"B/op\":\n\t\tif i, err := strconv.ParseUint(quant, 10, 64); err == nil {\n\t\t\tb.AllocedBytesPerOp = i\n\t\t\tb.Measured |= AllocedBytesPerOp\n\t\t}\n\tcase \"allocs/op\":\n\t\tif i, err := strconv.ParseUint(quant, 10, 64); err == nil {\n\t\t\tb.AllocsPerOp = i\n\t\t\tb.Measured |= AllocsPerOp\n\t\t}\n\t}\n}\n\nfunc (b *Benchmark) String() string {\n\tbuf := new(bytes.Buffer)\n\tfmt.Fprintf(buf, \"%s %d\", b.Name, b.N)\n\tif (b.Measured & NsPerOp) != 0 {\n\t\tfmt.Fprintf(buf, \" %.2f ns/op\", b.NsPerOp)\n\t}\n\tif (b.Measured & MBPerS) != 0 {\n\t\tfmt.Fprintf(buf, \" %.2f MB/s\", b.MBPerS)\n\t}\n\tif (b.Measured & AllocedBytesPerOp) != 0 {\n\t\tfmt.Fprintf(buf, \" %d B/op\", b.AllocedBytesPerOp)\n\t}\n\tif (b.Measured & AllocsPerOp) != 0 {\n\t\tfmt.Fprintf(buf, \" %d allocs/op\", b.AllocsPerOp)\n\t}\n\treturn buf.String()\n}\n\n// Set is a collection of benchmarks from one\n// testing.B run, keyed by name to facilitate comparison.\ntype Set map[string][]*Benchmark\n\n// ParseSet extracts a Set from testing.B output.\n// ParseSet preserves the order of benchmarks that have identical\n// names.\nfunc ParseSet(r io.Reader) (Set, error) {\n\tbb := make(Set)\n\tscan := bufio.NewScanner(r)\n\tord := 0\n\tfor scan.Scan() {\n\t\tif b, err := ParseLine(scan.Text()); err == nil {\n\t\t\tb.Ord = ord\n\t\t\tord++\n\t\t\tbb[b.Name] = append(bb[b.Name], b)\n\t\t}\n\t}\n\n\tif err := scan.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn bb, nil\n}\n"
  },
  {
    "path": "benchmark/parse/parse_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage parse\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestParseLine(t *testing.T) {\n\tcases := []struct {\n\t\tline string\n\t\twant *Benchmark\n\t\terr  bool // expect an error\n\t}{\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\t100000000\t        19.6 ns/op\",\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6,\n\t\t\t\tMeasured: NsPerOp,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\t100000000\t        19.6 ns/op\t 817.77 MB/s\",\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6, MBPerS: 817.77,\n\t\t\t\tMeasured: NsPerOp | MBPerS,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\t100000000\t        19.6 ns/op\t 817.77\",\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6,\n\t\t\t\tMeasured: NsPerOp,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\t100000000\t        19.6 ns/op\t 817.77 MB/s\t       5 allocs/op\",\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocsPerOp: 5,\n\t\t\t\tMeasured: NsPerOp | MBPerS | AllocsPerOp,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\t100000000\t        19.6 ns/op\t 817.77 MB/s\t       3 B/op\t       5 allocs/op\",\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocedBytesPerOp: 3, AllocsPerOp: 5,\n\t\t\t\tMeasured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,\n\t\t\t},\n\t\t},\n\t\t// error handling cases\n\t\t{\n\t\t\tline: \"BenchPress\t100\t        19.6 ns/op\", // non-benchmark\n\t\t\terr:  true,\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkEncrypt\tlots\t        19.6 ns/op\", // non-int iterations\n\t\t\terr:  true,\n\t\t},\n\t\t{\n\t\t\tline: \"BenchmarkBridge\t100000000\t        19.6 smoots\", // unknown unit\n\t\t\twant: &Benchmark{\n\t\t\t\tName: \"BenchmarkBridge\",\n\t\t\t\tN:    100000000,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tline: \"PASS\",\n\t\t\terr:  true,\n\t\t},\n\t}\n\n\tfor _, tt := range cases {\n\t\thave, err := ParseLine(tt.line)\n\t\tif tt.err && err == nil {\n\t\t\tt.Errorf(\"parsing line %q should have failed\", tt.line)\n\t\t\tcontinue\n\t\t}\n\t\tif !reflect.DeepEqual(have, tt.want) {\n\t\t\tt.Errorf(\"parsed line %q incorrectly, want %v have %v\", tt.line, tt.want, have)\n\t\t}\n\t}\n}\n\nfunc TestParseSet(t *testing.T) {\n\t// Test two things:\n\t// 1. The noise that can accompany testing.B output gets ignored.\n\t// 2. Benchmarks with the same name have their order preserved.\n\tin := `\n\t\t?   \tcrypto\t[no test files]\n\t\tPASS\n\t\t\t\tpem_decrypt_test.go:17: test 4. %!s(x509.PEMCipher=5)\n\t\t\t... [output truncated]\n\n\t\tBenchmarkEncrypt\t100000000\t        19.6 ns/op\n\t\tBenchmarkEncrypt\t 5000000\t       517 ns/op\n\t\t=== RUN TestChunk\n\t\t--- PASS: TestChunk (0.00 seconds)\n\t\t--- SKIP: TestLinuxSendfile (0.00 seconds)\n\t\t\tfs_test.go:716: skipping; linux-only test\n\t\tBenchmarkReadRequestApachebench\t 1000000\t      2960 ns/op\t  27.70 MB/s\t     839 B/op\t       9 allocs/op\n\t\tBenchmarkClientServerParallel64\t   50000\t     59192 ns/op\t    7028 B/op\t      60 allocs/op\n\t\tok  \tnet/http\t95.783s\n\t`\n\n\twant := Set{\n\t\t\"BenchmarkReadRequestApachebench\": []*Benchmark{\n\t\t\t{\n\t\t\t\tName: \"BenchmarkReadRequestApachebench\",\n\t\t\t\tN:    1000000, NsPerOp: 2960, MBPerS: 27.70, AllocedBytesPerOp: 839, AllocsPerOp: 9,\n\t\t\t\tMeasured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,\n\t\t\t\tOrd:      2,\n\t\t\t},\n\t\t},\n\t\t\"BenchmarkClientServerParallel64\": []*Benchmark{\n\t\t\t{\n\t\t\t\tName: \"BenchmarkClientServerParallel64\",\n\t\t\t\tN:    50000, NsPerOp: 59192, AllocedBytesPerOp: 7028, AllocsPerOp: 60,\n\t\t\t\tMeasured: NsPerOp | AllocedBytesPerOp | AllocsPerOp,\n\t\t\t\tOrd:      3,\n\t\t\t},\n\t\t},\n\t\t\"BenchmarkEncrypt\": []*Benchmark{\n\t\t\t{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6,\n\t\t\t\tMeasured: NsPerOp,\n\t\t\t\tOrd:      0,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"BenchmarkEncrypt\",\n\t\t\t\tN:    5000000, NsPerOp: 517,\n\t\t\t\tMeasured: NsPerOp,\n\t\t\t\tOrd:      1,\n\t\t\t},\n\t\t},\n\t}\n\n\thave, err := ParseSet(strings.NewReader(in))\n\tif err != nil {\n\t\tt.Fatalf(\"unexpected err during ParseSet: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, have) {\n\t\tt.Errorf(\"parsed bench set incorrectly, want %v have %v\", want, have)\n\t}\n}\n\nfunc TestString(t *testing.T) {\n\ttests := []struct {\n\t\tname   string\n\t\tinput  *Benchmark\n\t\twanted string\n\t}{\n\t\t{\n\t\t\tname: \"nsTest\",\n\t\t\tinput: &Benchmark{\n\t\t\t\tName: \"BenchmarkTest\",\n\t\t\t\tN:    100000000, NsPerOp: 19.6,\n\t\t\t\tMeasured: NsPerOp,\n\t\t\t},\n\t\t\twanted: \"BenchmarkTest 100000000 19.60 ns/op\",\n\t\t},\n\t\t{\n\t\t\tname: \"mbTest\",\n\t\t\tinput: &Benchmark{\n\t\t\t\tName: \"BenchmarkTest\",\n\t\t\t\tN:    100000000, MBPerS: 19.6,\n\t\t\t\tMeasured: MBPerS,\n\t\t\t},\n\t\t\twanted: \"BenchmarkTest 100000000 19.60 MB/s\",\n\t\t},\n\t\t{\n\t\t\tname: \"allocatedBytesTest\",\n\t\t\tinput: &Benchmark{\n\t\t\t\tName: \"BenchmarkTest\",\n\t\t\t\tN:    100000000, AllocedBytesPerOp: 5,\n\t\t\t\tMeasured: AllocedBytesPerOp,\n\t\t\t},\n\t\t\twanted: \"BenchmarkTest 100000000 5 B/op\",\n\t\t},\n\t\t{\n\t\t\tname: \"allocsTest\",\n\t\t\tinput: &Benchmark{\n\t\t\t\tName: \"BenchmarkTest\",\n\t\t\t\tN:    100000000, AllocsPerOp: 5,\n\t\t\t\tMeasured: AllocsPerOp,\n\t\t\t},\n\t\t\twanted: \"BenchmarkTest 100000000 5 allocs/op\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tresult := tt.input.String()\n\t\t\tif result != tt.wanted {\n\t\t\t\tt.Errorf(\"String() is called, want %q, have %q\", tt.wanted, result)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "blog/atom/atom.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Adapted from encoding/xml/read_test.go.\n\n// Package atom defines XML data structures for an Atom feed.\npackage atom // import \"golang.org/x/tools/blog/atom\"\n\nimport (\n\t\"encoding/xml\"\n\t\"time\"\n)\n\ntype Feed struct {\n\tXMLName xml.Name `xml:\"http://www.w3.org/2005/Atom feed\"`\n\tTitle   string   `xml:\"title\"`\n\tID      string   `xml:\"id\"`\n\tLink    []Link   `xml:\"link\"`\n\tUpdated TimeStr  `xml:\"updated\"`\n\tAuthor  *Person  `xml:\"author\"`\n\tEntry   []*Entry `xml:\"entry\"`\n}\n\ntype Entry struct {\n\tTitle     string  `xml:\"title\"`\n\tID        string  `xml:\"id\"`\n\tLink      []Link  `xml:\"link\"`\n\tPublished TimeStr `xml:\"published\"`\n\tUpdated   TimeStr `xml:\"updated\"`\n\tAuthor    *Person `xml:\"author\"`\n\tSummary   *Text   `xml:\"summary\"`\n\tContent   *Text   `xml:\"content\"`\n}\n\ntype Link struct {\n\tRel      string `xml:\"rel,attr,omitempty\"`\n\tHref     string `xml:\"href,attr\"`\n\tType     string `xml:\"type,attr,omitempty\"`\n\tHrefLang string `xml:\"hreflang,attr,omitempty\"`\n\tTitle    string `xml:\"title,attr,omitempty\"`\n\tLength   uint   `xml:\"length,attr,omitempty\"`\n}\n\ntype Person struct {\n\tName     string `xml:\"name\"`\n\tURI      string `xml:\"uri,omitempty\"`\n\tEmail    string `xml:\"email,omitempty\"`\n\tInnerXML string `xml:\",innerxml\"`\n}\n\ntype Text struct {\n\tType string `xml:\"type,attr\"`\n\tBody string `xml:\",chardata\"`\n}\n\ntype TimeStr string\n\nfunc Time(t time.Time) TimeStr {\n\treturn TimeStr(t.Format(\"2006-01-02T15:04:05-07:00\"))\n}\n"
  },
  {
    "path": "blog/blog.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package blog implements a web server for articles written in present format.\npackage blog // import \"golang.org/x/tools/blog\"\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/blog/atom\"\n\t\"golang.org/x/tools/present\"\n)\n\nvar (\n\tvalidJSONPFunc = regexp.MustCompile(`(?i)^[a-z_][a-z0-9_.]*$`)\n\t// used to serve relative paths when ServeLocalLinks is enabled.\n\tgolangOrgAbsLinkReplacer = strings.NewReplacer(\n\t\t`href=\"https://golang.org/pkg`, `href=\"/pkg`,\n\t\t`href=\"https://golang.org/cmd`, `href=\"/cmd`,\n\t)\n)\n\n// Config specifies Server configuration values.\ntype Config struct {\n\tContentPath  string // Relative or absolute location of article files and related content.\n\tTemplatePath string // Relative or absolute location of template files.\n\n\tBaseURL       string        // Absolute base URL (for permalinks; no trailing slash).\n\tBasePath      string        // Base URL path relative to server root (no trailing slash).\n\tGodocURL      string        // The base URL of godoc (for menu bar; no trailing slash).\n\tHostname      string        // Server host name, used for rendering ATOM feeds.\n\tAnalyticsHTML template.HTML // Optional analytics HTML to insert at the beginning of <head>.\n\n\tHomeArticles int    // Articles to display on the home page.\n\tFeedArticles int    // Articles to include in Atom and JSON feeds.\n\tFeedTitle    string // The title of the Atom XML feed\n\n\tPlayEnabled     bool\n\tServeLocalLinks bool // rewrite golang.org/{pkg,cmd} links to host-less, relative paths.\n}\n\n// Doc represents an article adorned with presentation data.\ntype Doc struct {\n\t*present.Doc\n\tPermalink string        // Canonical URL for this document.\n\tPath      string        // Path relative to server root (including base).\n\tHTML      template.HTML // rendered article\n\n\tRelated      []*Doc\n\tNewer, Older *Doc\n}\n\n// Server implements an http.Handler that serves blog articles.\ntype Server struct {\n\tcfg       Config\n\tdocs      []*Doc\n\tredirects map[string]string\n\ttags      []string\n\tdocPaths  map[string]*Doc // key is path without BasePath.\n\tdocTags   map[string][]*Doc\n\ttemplate  struct {\n\t\thome, index, article, doc *template.Template\n\t}\n\tatomFeed []byte // pre-rendered Atom feed\n\tjsonFeed []byte // pre-rendered JSON feed\n\tcontent  http.Handler\n}\n\n// NewServer constructs a new Server using the specified config.\nfunc NewServer(cfg Config) (*Server, error) {\n\tpresent.PlayEnabled = cfg.PlayEnabled\n\n\tif notExist(cfg.TemplatePath) {\n\t\treturn nil, fmt.Errorf(\"template directory not found: %s\", cfg.TemplatePath)\n\t}\n\troot := filepath.Join(cfg.TemplatePath, \"root.tmpl\")\n\tparse := func(name string) (*template.Template, error) {\n\t\tpath := filepath.Join(cfg.TemplatePath, name)\n\t\tif notExist(path) {\n\t\t\treturn nil, fmt.Errorf(\"template %s was not found in %s\", name, cfg.TemplatePath)\n\t\t}\n\t\tt := template.New(\"\").Funcs(funcMap)\n\t\treturn t.ParseFiles(root, path)\n\t}\n\n\ts := &Server{cfg: cfg}\n\n\t// Parse templates.\n\tvar err error\n\ts.template.home, err = parse(\"home.tmpl\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.template.index, err = parse(\"index.tmpl\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.template.article, err = parse(\"article.tmpl\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tp := present.Template().Funcs(funcMap)\n\ts.template.doc, err = p.ParseFiles(filepath.Join(cfg.TemplatePath, \"doc.tmpl\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Load content.\n\tcontent := filepath.Clean(cfg.ContentPath)\n\terr = s.loadDocs(content)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = s.renderAtomFeed()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = s.renderJSONFeed()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Set up content file server.\n\ts.content = http.StripPrefix(s.cfg.BasePath, http.FileServer(http.Dir(cfg.ContentPath)))\n\n\treturn s, nil\n}\n\nvar funcMap = template.FuncMap{\n\t\"sectioned\": sectioned,\n\t\"authors\":   authors,\n}\n\n// sectioned returns true if the provided Doc contains more than one section.\n// This is used to control whether to display the table of contents and headings.\nfunc sectioned(d *present.Doc) bool {\n\treturn len(d.Sections) > 1\n}\n\n// authors returns a comma-separated list of author names.\nfunc authors(authors []present.Author) string {\n\tvar b bytes.Buffer\n\tlast := len(authors) - 1\n\tfor i, a := range authors {\n\t\tif i > 0 {\n\t\t\tif i == last {\n\t\t\t\tif len(authors) > 2 {\n\t\t\t\t\tb.WriteString(\",\")\n\t\t\t\t}\n\t\t\t\tb.WriteString(\" and \")\n\t\t\t} else {\n\t\t\t\tb.WriteString(\", \")\n\t\t\t}\n\t\t}\n\t\tb.WriteString(authorName(a))\n\t}\n\treturn b.String()\n}\n\n// authorName returns the first line of the Author text: the author's name.\nfunc authorName(a present.Author) string {\n\tel := a.TextElem()\n\tif len(el) == 0 {\n\t\treturn \"\"\n\t}\n\ttext, ok := el[0].(present.Text)\n\tif !ok || len(text.Lines) == 0 {\n\t\treturn \"\"\n\t}\n\treturn text.Lines[0]\n}\n\n// loadDocs reads all content from the provided file system root, renders all\n// the articles it finds, adds them to the Server's docs field, computes the\n// denormalized docPaths, docTags, and tags fields, and populates the various\n// helper fields (Next, Previous, Related) for each Doc.\nfunc (s *Server) loadDocs(root string) error {\n\t// Read content into docs field.\n\tconst ext = \".article\"\n\tfn := func(p string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif filepath.Ext(p) != ext {\n\t\t\treturn nil\n\t\t}\n\t\tf, err := os.Open(p)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer f.Close()\n\t\td, err := present.Parse(f, p, 0)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar html bytes.Buffer\n\t\terr = d.Render(&html, s.template.doc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tp = p[len(root) : len(p)-len(ext)] // trim root and extension\n\t\tp = filepath.ToSlash(p)\n\t\ts.docs = append(s.docs, &Doc{\n\t\t\tDoc:       d,\n\t\t\tPath:      s.cfg.BasePath + p,\n\t\t\tPermalink: s.cfg.BaseURL + p,\n\t\t\tHTML:      template.HTML(html.String()),\n\t\t})\n\t\treturn nil\n\t}\n\terr := filepath.Walk(root, fn)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsort.Sort(docsByTime(s.docs))\n\n\t// Pull out doc paths and tags and put in reverse-associating maps.\n\ts.docPaths = make(map[string]*Doc)\n\ts.docTags = make(map[string][]*Doc)\n\ts.redirects = make(map[string]string)\n\tfor _, d := range s.docs {\n\t\ts.docPaths[strings.TrimPrefix(d.Path, s.cfg.BasePath)] = d\n\t\tfor _, t := range d.Tags {\n\t\t\ts.docTags[t] = append(s.docTags[t], d)\n\t\t}\n\t}\n\tfor _, d := range s.docs {\n\t\tfor _, old := range d.OldURL {\n\t\t\tif !strings.HasPrefix(old, \"/\") {\n\t\t\t\told = \"/\" + old\n\t\t\t}\n\t\t\tif _, ok := s.docPaths[old]; ok {\n\t\t\t\treturn fmt.Errorf(\"redirect %s -> %s conflicts with document %s\", old, d.Path, old)\n\t\t\t}\n\t\t\tif new, ok := s.redirects[old]; ok {\n\t\t\t\treturn fmt.Errorf(\"redirect %s -> %s conflicts with redirect %s -> %s\", old, d.Path, old, new)\n\t\t\t}\n\t\t\ts.redirects[old] = d.Path\n\t\t}\n\t}\n\n\t// Pull out unique sorted list of tags.\n\tfor t := range s.docTags {\n\t\ts.tags = append(s.tags, t)\n\t}\n\tsort.Strings(s.tags)\n\n\t// Set up presentation-related fields, Newer, Older, and Related.\n\tfor _, doc := range s.docs {\n\t\t// Newer, Older: docs adjacent to doc\n\t\tfor i := range s.docs {\n\t\t\tif s.docs[i] != doc {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif i > 0 {\n\t\t\t\tdoc.Newer = s.docs[i-1]\n\t\t\t}\n\t\t\tif i+1 < len(s.docs) {\n\t\t\t\tdoc.Older = s.docs[i+1]\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\t// Related: all docs that share tags with doc.\n\t\trelated := make(map[*Doc]bool)\n\t\tfor _, t := range doc.Tags {\n\t\t\tfor _, d := range s.docTags[t] {\n\t\t\t\tif d != doc {\n\t\t\t\t\trelated[d] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor d := range related {\n\t\t\tdoc.Related = append(doc.Related, d)\n\t\t}\n\t\tsort.Sort(docsByTime(doc.Related))\n\t}\n\n\treturn nil\n}\n\n// renderAtomFeed generates an XML Atom feed and stores it in the Server's\n// atomFeed field.\nfunc (s *Server) renderAtomFeed() error {\n\tvar updated time.Time\n\tif len(s.docs) > 0 {\n\t\tupdated = s.docs[0].Time\n\t}\n\tfeed := atom.Feed{\n\t\tTitle:   s.cfg.FeedTitle,\n\t\tID:      \"tag:\" + s.cfg.Hostname + \",2013:\" + s.cfg.Hostname,\n\t\tUpdated: atom.Time(updated),\n\t\tLink: []atom.Link{{\n\t\t\tRel:  \"self\",\n\t\t\tHref: s.cfg.BaseURL + \"/feed.atom\",\n\t\t}},\n\t}\n\tfor i, doc := range s.docs {\n\t\tif i >= s.cfg.FeedArticles {\n\t\t\tbreak\n\t\t}\n\n\t\t// Use original article path as ID in atom feed\n\t\t// to avoid articles being treated as new when renamed.\n\t\tidPath := doc.Path\n\t\tif len(doc.OldURL) > 0 {\n\t\t\told := doc.OldURL[0]\n\t\t\tif !strings.HasPrefix(old, \"/\") {\n\t\t\t\told = \"/\" + old\n\t\t\t}\n\t\t\tidPath = old\n\t\t}\n\n\t\te := &atom.Entry{\n\t\t\tTitle: doc.Title,\n\t\t\tID:    feed.ID + idPath,\n\t\t\tLink: []atom.Link{{\n\t\t\t\tRel:  \"alternate\",\n\t\t\t\tHref: doc.Permalink,\n\t\t\t}},\n\t\t\tPublished: atom.Time(doc.Time),\n\t\t\tUpdated:   atom.Time(doc.Time),\n\t\t\tSummary: &atom.Text{\n\t\t\t\tType: \"html\",\n\t\t\t\tBody: summary(doc),\n\t\t\t},\n\t\t\tContent: &atom.Text{\n\t\t\t\tType: \"html\",\n\t\t\t\tBody: string(doc.HTML),\n\t\t\t},\n\t\t\tAuthor: &atom.Person{\n\t\t\t\tName: authors(doc.Authors),\n\t\t\t},\n\t\t}\n\t\tfeed.Entry = append(feed.Entry, e)\n\t}\n\tdata, err := xml.Marshal(&feed)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts.atomFeed = data\n\treturn nil\n}\n\ntype jsonItem struct {\n\tTitle   string\n\tLink    string\n\tTime    time.Time\n\tSummary string\n\tContent string\n\tAuthor  string\n}\n\n// renderJSONFeed generates a JSON feed and stores it in the Server's jsonFeed\n// field.\nfunc (s *Server) renderJSONFeed() error {\n\tvar feed []jsonItem\n\tfor i, doc := range s.docs {\n\t\tif i >= s.cfg.FeedArticles {\n\t\t\tbreak\n\t\t}\n\t\titem := jsonItem{\n\t\t\tTitle:   doc.Title,\n\t\t\tLink:    doc.Permalink,\n\t\t\tTime:    doc.Time,\n\t\t\tSummary: summary(doc),\n\t\t\tContent: string(doc.HTML),\n\t\t\tAuthor:  authors(doc.Authors),\n\t\t}\n\t\tfeed = append(feed, item)\n\t}\n\tdata, err := json.Marshal(feed)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts.jsonFeed = data\n\treturn nil\n}\n\n// summary returns the first paragraph of text from the provided Doc.\nfunc summary(d *Doc) string {\n\tif len(d.Sections) == 0 {\n\t\treturn \"\"\n\t}\n\tfor _, elem := range d.Sections[0].Elem {\n\t\ttext, ok := elem.(present.Text)\n\t\tif !ok || text.Pre {\n\t\t\t// skip everything but non-text elements\n\t\t\tcontinue\n\t\t}\n\t\tvar buf bytes.Buffer\n\t\tfor _, s := range text.Lines {\n\t\t\tbuf.WriteString(string(present.Style(s)))\n\t\t\tbuf.WriteByte('\\n')\n\t\t}\n\t\treturn buf.String()\n\t}\n\treturn \"\"\n}\n\n// rootData encapsulates data destined for the root template.\ntype rootData struct {\n\tDoc           *Doc\n\tBasePath      string\n\tGodocURL      string\n\tAnalyticsHTML template.HTML\n\tData          any\n}\n\n// ServeHTTP serves the front, index, and article pages\n// as well as the ATOM and JSON feeds.\nfunc (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tvar (\n\t\td = rootData{\n\t\t\tBasePath:      s.cfg.BasePath,\n\t\t\tGodocURL:      s.cfg.GodocURL,\n\t\t\tAnalyticsHTML: s.cfg.AnalyticsHTML,\n\t\t}\n\t\tt *template.Template\n\t)\n\tswitch p := strings.TrimPrefix(r.URL.Path, s.cfg.BasePath); p {\n\tcase \"/\":\n\t\td.Data = s.docs\n\t\tif len(s.docs) > s.cfg.HomeArticles {\n\t\t\td.Data = s.docs[:s.cfg.HomeArticles]\n\t\t}\n\t\tt = s.template.home\n\tcase \"/index\":\n\t\td.Data = s.docs\n\t\tt = s.template.index\n\tcase \"/feed.atom\", \"/feeds/posts/default\":\n\t\tw.Header().Set(\"Content-type\", \"application/atom+xml; charset=utf-8\")\n\t\tw.Write(s.atomFeed)\n\t\treturn\n\tcase \"/.json\":\n\t\tif p := r.FormValue(\"jsonp\"); validJSONPFunc.MatchString(p) {\n\t\t\tw.Header().Set(\"Content-type\", \"application/javascript; charset=utf-8\")\n\t\t\tfmt.Fprintf(w, \"%v(%s)\", p, s.jsonFeed)\n\t\t\treturn\n\t\t}\n\t\tw.Header().Set(\"Content-type\", \"application/json; charset=utf-8\")\n\t\tw.Write(s.jsonFeed)\n\t\treturn\n\tdefault:\n\t\tif redir, ok := s.redirects[p]; ok {\n\t\t\thttp.Redirect(w, r, redir, http.StatusMovedPermanently)\n\t\t\treturn\n\t\t}\n\t\tdoc, ok := s.docPaths[p]\n\t\tif !ok {\n\t\t\t// Not a doc; try to just serve static content.\n\t\t\ts.content.ServeHTTP(w, r)\n\t\t\treturn\n\t\t}\n\t\td.Doc = doc\n\t\tt = s.template.article\n\t}\n\tvar err error\n\tif s.cfg.ServeLocalLinks {\n\t\tvar buf bytes.Buffer\n\t\terr = t.ExecuteTemplate(&buf, \"root\", d)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\t_, err = golangOrgAbsLinkReplacer.WriteString(w, buf.String())\n\t} else {\n\t\terr = t.ExecuteTemplate(w, \"root\", d)\n\t}\n\tif err != nil {\n\t\tlog.Println(err)\n\t}\n}\n\n// docsByTime implements sort.Interface, sorting Docs by their Time field.\ntype docsByTime []*Doc\n\nfunc (s docsByTime) Len() int           { return len(s) }\nfunc (s docsByTime) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }\nfunc (s docsByTime) Less(i, j int) bool { return s[i].Time.After(s[j].Time) }\n\n// notExist reports whether the path exists or not.\nfunc notExist(path string) bool {\n\t_, err := os.Stat(path)\n\treturn os.IsNotExist(err)\n}\n"
  },
  {
    "path": "blog/blog_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage blog\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n)\n\nfunc TestLinkRewrite(t *testing.T) {\n\ttests := []struct {\n\t\tinput  string\n\t\toutput string\n\t}{\n\t\t{\n\t\t\t`For instance, the <a href=\"https://golang.org/pkg/bytes/\" target=\"_blank\">bytes package</a> from the standard library exports the <code>Buffer</code> type.`,\n\t\t\t`For instance, the <a href=\"/pkg/bytes/\" target=\"_blank\">bytes package</a> from the standard library exports the <code>Buffer</code> type.`},\n\t\t{\n\t\t\t`(The <a href=\"https://golang.org/cmd/gofmt/\" target=\"_blank\">gofmt command</a> has a <code>-r</code> flag that provides a syntax-aware search and replace, making large-scale refactoring easier.)`,\n\t\t\t`(The <a href=\"/cmd/gofmt/\" target=\"_blank\">gofmt command</a> has a <code>-r</code> flag that provides a syntax-aware search and replace, making large-scale refactoring easier.)`,\n\t\t},\n\t\t{\n\t\t\t`<a href=\"//golang.org/LICENSE\">BSD license</a>.<br> <a href=\"//golang.org/doc/tos.html\">Terms of Service</a> `,\n\t\t\t`<a href=\"//golang.org/LICENSE\">BSD license</a>.<br> <a href=\"//golang.org/doc/tos.html\">Terms of Service</a> `,\n\t\t},\n\t\t{\n\t\t\t`For instance, the <code>websocket</code> package from the <code>go.net</code> sub-repository has an import path of <code>&#34;golang.org/x/net/websocket&#34;</code>.`,\n\t\t\t`For instance, the <code>websocket</code> package from the <code>go.net</code> sub-repository has an import path of <code>&#34;golang.org/x/net/websocket&#34;</code>.`,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tvar buf bytes.Buffer\n\t\t_, err := golangOrgAbsLinkReplacer.WriteString(&buf, test.input)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"unexpected error during replacing links. Got: %#v, Want: nil.\\n\", err)\n\t\t\tcontinue\n\t\t}\n\t\tif got, want := buf.String(), test.output; got != want {\n\t\t\tt.Errorf(\"WriteString(%q) = %q. Expected: %q\", test.input, got, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/benchcmp/benchcmp.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"text/tabwriter\"\n\n\t\"golang.org/x/tools/benchmark/parse\"\n)\n\nvar (\n\tchangedOnly = flag.Bool(\"changed\", false, \"show only benchmarks that have changed\")\n\tmagSort     = flag.Bool(\"mag\", false, \"sort benchmarks by magnitude of change\")\n\tbest        = flag.Bool(\"best\", false, \"compare best times from old and new\")\n)\n\nconst usageFooter = `\nEach input file should be from:\n\tgo test -run=NONE -bench=. > [old,new].txt\n\nBenchcmp compares old and new for each benchmark.\n\nIf -test.benchmem=true is added to the \"go test\" command\nbenchcmp will also compare memory allocations.\n`\n\nfunc main() {\n\tfmt.Fprintf(os.Stderr, \"benchcmp is deprecated in favor of benchstat: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat\\n\")\n\tflag.Usage = func() {\n\t\tfmt.Fprintf(os.Stderr, \"usage: %s old.txt new.txt\\n\\n\", os.Args[0])\n\t\tflag.PrintDefaults()\n\t\tfmt.Fprint(os.Stderr, usageFooter)\n\t\tos.Exit(2)\n\t}\n\tflag.Parse()\n\tif flag.NArg() != 2 {\n\t\tflag.Usage()\n\t}\n\n\tbefore := parseFile(flag.Arg(0))\n\tafter := parseFile(flag.Arg(1))\n\n\tcmps, warnings := Correlate(before, after)\n\n\tfor _, warn := range warnings {\n\t\tfmt.Fprintln(os.Stderr, warn)\n\t}\n\n\tif len(cmps) == 0 {\n\t\tfatal(\"benchcmp: no repeated benchmarks\")\n\t}\n\n\tw := new(tabwriter.Writer)\n\tw.Init(os.Stdout, 0, 0, 5, ' ', 0)\n\tdefer w.Flush()\n\n\tvar header bool // Has the header has been displayed yet for a given block?\n\n\tif *magSort {\n\t\tsort.Sort(ByDeltaNsPerOp(cmps))\n\t} else {\n\t\tsort.Sort(ByParseOrder(cmps))\n\t}\n\tfor _, cmp := range cmps {\n\t\tif !cmp.Measured(parse.NsPerOp) {\n\t\t\tcontinue\n\t\t}\n\t\tif delta := cmp.DeltaNsPerOp(); !*changedOnly || delta.Changed() {\n\t\t\tif !header {\n\t\t\t\tfmt.Fprint(w, \"benchmark\\told ns/op\\tnew ns/op\\tdelta\\n\")\n\t\t\t\theader = true\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s\\t%s\\t%s\\t%s\\n\", cmp.Name(), formatNs(cmp.Before.NsPerOp), formatNs(cmp.After.NsPerOp), delta.Percent())\n\t\t}\n\t}\n\n\theader = false\n\tif *magSort {\n\t\tsort.Sort(ByDeltaMBPerS(cmps))\n\t}\n\tfor _, cmp := range cmps {\n\t\tif !cmp.Measured(parse.MBPerS) {\n\t\t\tcontinue\n\t\t}\n\t\tif delta := cmp.DeltaMBPerS(); !*changedOnly || delta.Changed() {\n\t\t\tif !header {\n\t\t\t\tfmt.Fprint(w, \"\\nbenchmark\\told MB/s\\tnew MB/s\\tspeedup\\n\")\n\t\t\t\theader = true\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s\\t%.2f\\t%.2f\\t%s\\n\", cmp.Name(), cmp.Before.MBPerS, cmp.After.MBPerS, delta.Multiple())\n\t\t}\n\t}\n\n\theader = false\n\tif *magSort {\n\t\tsort.Sort(ByDeltaAllocsPerOp(cmps))\n\t}\n\tfor _, cmp := range cmps {\n\t\tif !cmp.Measured(parse.AllocsPerOp) {\n\t\t\tcontinue\n\t\t}\n\t\tif delta := cmp.DeltaAllocsPerOp(); !*changedOnly || delta.Changed() {\n\t\t\tif !header {\n\t\t\t\tfmt.Fprint(w, \"\\nbenchmark\\told allocs\\tnew allocs\\tdelta\\n\")\n\t\t\t\theader = true\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s\\t%d\\t%d\\t%s\\n\", cmp.Name(), cmp.Before.AllocsPerOp, cmp.After.AllocsPerOp, delta.Percent())\n\t\t}\n\t}\n\n\theader = false\n\tif *magSort {\n\t\tsort.Sort(ByDeltaAllocedBytesPerOp(cmps))\n\t}\n\tfor _, cmp := range cmps {\n\t\tif !cmp.Measured(parse.AllocedBytesPerOp) {\n\t\t\tcontinue\n\t\t}\n\t\tif delta := cmp.DeltaAllocedBytesPerOp(); !*changedOnly || delta.Changed() {\n\t\t\tif !header {\n\t\t\t\tfmt.Fprint(w, \"\\nbenchmark\\told bytes\\tnew bytes\\tdelta\\n\")\n\t\t\t\theader = true\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s\\t%d\\t%d\\t%s\\n\", cmp.Name(), cmp.Before.AllocedBytesPerOp, cmp.After.AllocedBytesPerOp, cmp.DeltaAllocedBytesPerOp().Percent())\n\t\t}\n\t}\n}\n\nfunc fatal(msg any) {\n\tfmt.Fprintln(os.Stderr, msg)\n\tos.Exit(1)\n}\n\nfunc parseFile(path string) parse.Set {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\tfatal(err)\n\t}\n\tdefer f.Close()\n\tbb, err := parse.ParseSet(f)\n\tif err != nil {\n\t\tfatal(err)\n\t}\n\tif *best {\n\t\tselectBest(bb)\n\t}\n\treturn bb\n}\n\nfunc selectBest(bs parse.Set) {\n\tfor name, bb := range bs {\n\t\tif len(bb) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\tord := bb[0].Ord\n\t\tbest := bb[0]\n\t\tfor _, b := range bb {\n\t\t\tif b.NsPerOp < best.NsPerOp {\n\t\t\t\tb.Ord = ord\n\t\t\t\tbest = b\n\t\t\t}\n\t\t}\n\t\tbs[name] = []*parse.Benchmark{best}\n\t}\n}\n\n// formatNs formats ns measurements to expose a useful amount of\n// precision. It mirrors the ns precision logic of testing.B.\nfunc formatNs(ns float64) string {\n\tprec := 0\n\tswitch {\n\tcase ns < 10:\n\t\tprec = 2\n\tcase ns < 100:\n\t\tprec = 1\n\t}\n\treturn strconv.FormatFloat(ns, 'f', prec, 64)\n}\n"
  },
  {
    "path": "cmd/benchcmp/benchcmp_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/benchmark/parse\"\n)\n\nfunc TestSelectBest(t *testing.T) {\n\thave := parse.Set{\n\t\t\"Benchmark1\": []*parse.Benchmark{\n\t\t\t{\n\t\t\t\tName: \"Benchmark1\",\n\t\t\t\tN:    10, NsPerOp: 100, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"Benchmark1\",\n\t\t\t\tN:    10, NsPerOp: 50, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 3,\n\t\t\t},\n\t\t},\n\t\t\"Benchmark2\": []*parse.Benchmark{\n\t\t\t{\n\t\t\t\tName: \"Benchmark2\",\n\t\t\t\tN:    10, NsPerOp: 60, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"Benchmark2\",\n\t\t\t\tN:    10, NsPerOp: 500, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 2,\n\t\t\t},\n\t\t},\n\t}\n\n\twant := parse.Set{\n\t\t\"Benchmark1\": []*parse.Benchmark{\n\t\t\t{\n\t\t\t\tName: \"Benchmark1\",\n\t\t\t\tN:    10, NsPerOp: 50, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 0,\n\t\t\t},\n\t\t},\n\t\t\"Benchmark2\": []*parse.Benchmark{\n\t\t\t{\n\t\t\t\tName: \"Benchmark2\",\n\t\t\t\tN:    10, NsPerOp: 60, Measured: parse.NsPerOp,\n\t\t\t\tOrd: 1,\n\t\t\t},\n\t\t},\n\t}\n\n\tselectBest(have)\n\tif !reflect.DeepEqual(want, have) {\n\t\tt.Errorf(\"filtered bench set incorrectly, want %v have %v\", want, have)\n\t}\n}\n\nfunc TestFormatNs(t *testing.T) {\n\ttests := []struct {\n\t\tinput    float64\n\t\texpected string\n\t}{\n\t\t{input: 0, expected: \"0.00\"},\n\t\t{input: 0.2, expected: \"0.20\"},\n\t\t{input: 2, expected: \"2.00\"},\n\t\t{input: 2.2, expected: \"2.20\"},\n\t\t{input: 4, expected: \"4.00\"},\n\t\t{input: 16, expected: \"16.0\"},\n\t\t{input: 16.08, expected: \"16.1\"},\n\t\t{input: 128, expected: \"128\"},\n\t\t{input: 256.2, expected: \"256\"},\n\t}\n\n\tfor _, tt := range tests {\n\t\tactual := formatNs(tt.input)\n\t\tif actual != tt.expected {\n\t\t\tt.Fatalf(\"%f. got %q, want %q\", tt.input, actual, tt.expected)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/benchcmp/compare.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\n\t\"golang.org/x/tools/benchmark/parse\"\n)\n\n// BenchCmp is a pair of benchmarks.\ntype BenchCmp struct {\n\tBefore *parse.Benchmark\n\tAfter  *parse.Benchmark\n}\n\n// Correlate correlates benchmarks from two BenchSets.\nfunc Correlate(before, after parse.Set) (cmps []BenchCmp, warnings []string) {\n\tcmps = make([]BenchCmp, 0, len(after))\n\tfor name, beforebb := range before {\n\t\tafterbb := after[name]\n\t\tif len(beforebb) != len(afterbb) {\n\t\t\twarnings = append(warnings, fmt.Sprintf(\"ignoring %s: before has %d instances, after has %d\", name, len(beforebb), len(afterbb)))\n\t\t\tcontinue\n\t\t}\n\t\tfor i, beforeb := range beforebb {\n\t\t\tafterb := afterbb[i]\n\t\t\tcmps = append(cmps, BenchCmp{beforeb, afterb})\n\t\t}\n\t}\n\treturn\n}\n\nfunc (c BenchCmp) Name() string           { return c.Before.Name }\nfunc (c BenchCmp) String() string         { return fmt.Sprintf(\"<%s, %s>\", c.Before, c.After) }\nfunc (c BenchCmp) Measured(flag int) bool { return (c.Before.Measured & c.After.Measured & flag) != 0 }\nfunc (c BenchCmp) DeltaNsPerOp() Delta    { return Delta{c.Before.NsPerOp, c.After.NsPerOp} }\nfunc (c BenchCmp) DeltaMBPerS() Delta     { return Delta{c.Before.MBPerS, c.After.MBPerS} }\nfunc (c BenchCmp) DeltaAllocedBytesPerOp() Delta {\n\treturn Delta{float64(c.Before.AllocedBytesPerOp), float64(c.After.AllocedBytesPerOp)}\n}\nfunc (c BenchCmp) DeltaAllocsPerOp() Delta {\n\treturn Delta{float64(c.Before.AllocsPerOp), float64(c.After.AllocsPerOp)}\n}\n\n// Delta is the before and after value for a benchmark measurement.\n// Both must be non-negative.\ntype Delta struct {\n\tBefore float64\n\tAfter  float64\n}\n\n// mag calculates the magnitude of a change, regardless of the direction of\n// the change. mag is intended for sorting and has no independent meaning.\nfunc (d Delta) mag() float64 {\n\tswitch {\n\tcase d.Before != 0 && d.After != 0 && d.Before >= d.After:\n\t\treturn d.After / d.Before\n\tcase d.Before != 0 && d.After != 0 && d.Before < d.After:\n\t\treturn d.Before / d.After\n\tcase d.Before == 0 && d.After == 0:\n\t\treturn 1\n\tdefault:\n\t\t// 0 -> 1 or 1 -> 0\n\t\t// These are significant changes and worth surfacing.\n\t\treturn math.Inf(1)\n\t}\n}\n\n// Changed reports whether the benchmark quantities are different.\nfunc (d Delta) Changed() bool { return d.Before != d.After }\n\n// Float64 returns After / Before. If Before is 0, Float64 returns\n// 1 if After is also 0, and +Inf otherwise.\nfunc (d Delta) Float64() float64 {\n\tswitch {\n\tcase d.Before != 0:\n\t\treturn d.After / d.Before\n\tcase d.After == 0:\n\t\treturn 1\n\tdefault:\n\t\treturn math.Inf(1)\n\t}\n}\n\n// Percent formats a Delta as a percent change, ranging from -100% up.\nfunc (d Delta) Percent() string {\n\treturn fmt.Sprintf(\"%+.2f%%\", 100*d.Float64()-100)\n}\n\n// Multiple formats a Delta as a multiplier, ranging from 0.00x up.\nfunc (d Delta) Multiple() string {\n\treturn fmt.Sprintf(\"%.2fx\", d.Float64())\n}\n\nfunc (d Delta) String() string {\n\treturn fmt.Sprintf(\"Δ(%f, %f)\", d.Before, d.After)\n}\n\n// ByParseOrder sorts BenchCmps to match the order in\n// which the Before benchmarks were presented to Parse.\ntype ByParseOrder []BenchCmp\n\nfunc (x ByParseOrder) Len() int           { return len(x) }\nfunc (x ByParseOrder) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\nfunc (x ByParseOrder) Less(i, j int) bool { return x[i].Before.Ord < x[j].Before.Ord }\n\n// lessByDelta provides lexicographic ordering:\n//   - largest delta by magnitude\n//   - alphabetic by name\nfunc lessByDelta(i, j BenchCmp, calcDelta func(BenchCmp) Delta) bool {\n\tiDelta, jDelta := calcDelta(i).mag(), calcDelta(j).mag()\n\tif iDelta != jDelta {\n\t\treturn iDelta < jDelta\n\t}\n\treturn i.Name() < j.Name()\n}\n\n// ByDeltaNsPerOp sorts BenchCmps lexicographically by change\n// in ns/op, descending, then by benchmark name.\ntype ByDeltaNsPerOp []BenchCmp\n\nfunc (x ByDeltaNsPerOp) Len() int           { return len(x) }\nfunc (x ByDeltaNsPerOp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\nfunc (x ByDeltaNsPerOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsPerOp) }\n\n// ByDeltaMBPerS sorts BenchCmps lexicographically by change\n// in MB/s, descending, then by benchmark name.\ntype ByDeltaMBPerS []BenchCmp\n\nfunc (x ByDeltaMBPerS) Len() int           { return len(x) }\nfunc (x ByDeltaMBPerS) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\nfunc (x ByDeltaMBPerS) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMBPerS) }\n\n// ByDeltaAllocedBytesPerOp sorts BenchCmps lexicographically by change\n// in B/op, descending, then by benchmark name.\ntype ByDeltaAllocedBytesPerOp []BenchCmp\n\nfunc (x ByDeltaAllocedBytesPerOp) Len() int      { return len(x) }\nfunc (x ByDeltaAllocedBytesPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }\nfunc (x ByDeltaAllocedBytesPerOp) Less(i, j int) bool {\n\treturn lessByDelta(x[i], x[j], BenchCmp.DeltaAllocedBytesPerOp)\n}\n\n// ByDeltaAllocsPerOp sorts BenchCmps lexicographically by change\n// in allocs/op, descending, then by benchmark name.\ntype ByDeltaAllocsPerOp []BenchCmp\n\nfunc (x ByDeltaAllocsPerOp) Len() int      { return len(x) }\nfunc (x ByDeltaAllocsPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }\nfunc (x ByDeltaAllocsPerOp) Less(i, j int) bool {\n\treturn lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsPerOp)\n}\n"
  },
  {
    "path": "cmd/benchcmp/compare_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/benchmark/parse\"\n)\n\nfunc TestDelta(t *testing.T) {\n\tcases := []struct {\n\t\tbefore  float64\n\t\tafter   float64\n\t\tmag     float64\n\t\tf       float64\n\t\tchanged bool\n\t\tpct     string\n\t\tmult    string\n\t}{\n\t\t{before: 1, after: 1, mag: 1, f: 1, changed: false, pct: \"+0.00%\", mult: \"1.00x\"},\n\t\t{before: 1, after: 2, mag: 0.5, f: 2, changed: true, pct: \"+100.00%\", mult: \"2.00x\"},\n\t\t{before: 2, after: 1, mag: 0.5, f: 0.5, changed: true, pct: \"-50.00%\", mult: \"0.50x\"},\n\t\t{before: 0, after: 0, mag: 1, f: 1, changed: false, pct: \"+0.00%\", mult: \"1.00x\"},\n\t\t{before: 1, after: 0, mag: math.Inf(1), f: 0, changed: true, pct: \"-100.00%\", mult: \"0.00x\"},\n\t\t{before: 0, after: 1, mag: math.Inf(1), f: math.Inf(1), changed: true, pct: \"+Inf%\", mult: \"+Infx\"},\n\t}\n\tfor _, tt := range cases {\n\t\td := Delta{tt.before, tt.after}\n\t\tif want, have := tt.mag, d.mag(); want != have {\n\t\t\tt.Errorf(\"%s.mag(): want %f have %f\", d, want, have)\n\t\t}\n\t\tif want, have := tt.f, d.Float64(); want != have {\n\t\t\tt.Errorf(\"%s.Float64(): want %f have %f\", d, want, have)\n\t\t}\n\t\tif want, have := tt.changed, d.Changed(); want != have {\n\t\t\tt.Errorf(\"%s.Changed(): want %t have %t\", d, want, have)\n\t\t}\n\t\tif want, have := tt.pct, d.Percent(); want != have {\n\t\t\tt.Errorf(\"%s.Percent(): want %q have %q\", d, want, have)\n\t\t}\n\t\tif want, have := tt.mult, d.Multiple(); want != have {\n\t\t\tt.Errorf(\"%s.Multiple(): want %q have %q\", d, want, have)\n\t\t}\n\t}\n}\n\nfunc TestCorrelate(t *testing.T) {\n\t// Benches that are going to be successfully correlated get N thus:\n\t//   0x<counter><num benches><b = before | a = after>\n\t// Read this: \"<counter> of <num benches>, from <before|after>\".\n\tbefore := parse.Set{\n\t\t\"BenchmarkOneEach\":   []*parse.Benchmark{{Name: \"BenchmarkOneEach\", N: 0x11b}},\n\t\t\"BenchmarkOneToNone\": []*parse.Benchmark{{Name: \"BenchmarkOneToNone\"}},\n\t\t\"BenchmarkOneToTwo\":  []*parse.Benchmark{{Name: \"BenchmarkOneToTwo\"}},\n\t\t\"BenchmarkTwoToOne\": []*parse.Benchmark{\n\t\t\t{Name: \"BenchmarkTwoToOne\"},\n\t\t\t{Name: \"BenchmarkTwoToOne\"},\n\t\t},\n\t\t\"BenchmarkTwoEach\": []*parse.Benchmark{\n\t\t\t{Name: \"BenchmarkTwoEach\", N: 0x12b},\n\t\t\t{Name: \"BenchmarkTwoEach\", N: 0x22b},\n\t\t},\n\t}\n\n\tafter := parse.Set{\n\t\t\"BenchmarkOneEach\":   []*parse.Benchmark{{Name: \"BenchmarkOneEach\", N: 0x11a}},\n\t\t\"BenchmarkNoneToOne\": []*parse.Benchmark{{Name: \"BenchmarkNoneToOne\"}},\n\t\t\"BenchmarkTwoToOne\":  []*parse.Benchmark{{Name: \"BenchmarkTwoToOne\"}},\n\t\t\"BenchmarkOneToTwo\": []*parse.Benchmark{\n\t\t\t{Name: \"BenchmarkOneToTwo\"},\n\t\t\t{Name: \"BenchmarkOneToTwo\"},\n\t\t},\n\t\t\"BenchmarkTwoEach\": []*parse.Benchmark{\n\t\t\t{Name: \"BenchmarkTwoEach\", N: 0x12a},\n\t\t\t{Name: \"BenchmarkTwoEach\", N: 0x22a},\n\t\t},\n\t}\n\n\tpairs, errs := Correlate(before, after)\n\n\t// Fail to match: BenchmarkOneToNone, BenchmarkOneToTwo, BenchmarkTwoToOne.\n\t// Correlate does not notice BenchmarkNoneToOne.\n\tif len(errs) != 3 {\n\t\tt.Errorf(\"Correlated expected 4 errors, got %d: %v\", len(errs), errs)\n\t}\n\n\t// Want three correlated pairs: one BenchmarkOneEach, two BenchmarkTwoEach.\n\tif len(pairs) != 3 {\n\t\tt.Fatalf(\"Correlated expected 3 pairs, got %v\", pairs)\n\t}\n\n\tfor _, pair := range pairs {\n\t\tif pair.Before.N&0xF != 0xb {\n\t\t\tt.Errorf(\"unexpected Before in pair %s\", pair)\n\t\t}\n\t\tif pair.After.N&0xF != 0xa {\n\t\t\tt.Errorf(\"unexpected After in pair %s\", pair)\n\t\t}\n\t\tif pair.Before.N>>4 != pair.After.N>>4 {\n\t\t\tt.Errorf(\"mismatched pair %s\", pair)\n\t\t}\n\t}\n}\n\nfunc TestBenchCmpSorting(t *testing.T) {\n\tc := []BenchCmp{\n\t\t{&parse.Benchmark{Name: \"BenchmarkMuchFaster\", NsPerOp: 10, Ord: 3}, &parse.Benchmark{Name: \"BenchmarkMuchFaster\", NsPerOp: 1}},\n\t\t{&parse.Benchmark{Name: \"BenchmarkSameB\", NsPerOp: 5, Ord: 1}, &parse.Benchmark{Name: \"BenchmarkSameB\", NsPerOp: 5}},\n\t\t{&parse.Benchmark{Name: \"BenchmarkSameA\", NsPerOp: 5, Ord: 2}, &parse.Benchmark{Name: \"BenchmarkSameA\", NsPerOp: 5}},\n\t\t{&parse.Benchmark{Name: \"BenchmarkSlower\", NsPerOp: 10, Ord: 0}, &parse.Benchmark{Name: \"BenchmarkSlower\", NsPerOp: 11}},\n\t}\n\n\t// Test just one magnitude-based sort order; they are symmetric.\n\tsort.Sort(ByDeltaNsPerOp(c))\n\twant := []string{\"BenchmarkMuchFaster\", \"BenchmarkSlower\", \"BenchmarkSameA\", \"BenchmarkSameB\"}\n\thave := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}\n\tif !reflect.DeepEqual(want, have) {\n\t\tt.Errorf(\"ByDeltaNsOp incorrect sorting: want %v have %v\", want, have)\n\t}\n\n\tsort.Sort(ByParseOrder(c))\n\twant = []string{\"BenchmarkSlower\", \"BenchmarkSameB\", \"BenchmarkSameA\", \"BenchmarkMuchFaster\"}\n\thave = []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}\n\tif !reflect.DeepEqual(want, have) {\n\t\tt.Errorf(\"ByParseOrder incorrect sorting: want %v have %v\", want, have)\n\t}\n}\n"
  },
  {
    "path": "cmd/benchcmp/doc.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nDeprecated: benchcmp is deprecated in favor of benchstat: golang.org/x/perf/cmd/benchstat\n\nThe benchcmp command displays performance changes between benchmarks.\n\nBenchcmp parses the output of two 'go test' benchmark runs,\ncorrelates the results per benchmark, and displays the deltas.\n\nTo measure the performance impact of a change, use 'go test'\nto run benchmarks before and after the change:\n\n\tgo test -run=NONE -bench=. ./... > old.txt\n\t# make changes\n\tgo test -run=NONE -bench=. ./... > new.txt\n\nThen feed the benchmark results to benchcmp:\n\n\tbenchcmp old.txt new.txt\n\nBenchcmp will summarize and display the performance changes,\nin a format like this:\n\n\t$ benchcmp old.txt new.txt\n\tbenchmark           old ns/op     new ns/op     delta\n\tBenchmarkConcat     523           68.6          -86.88%\n\n\tbenchmark           old allocs     new allocs     delta\n\tBenchmarkConcat     3              1              -66.67%\n\n\tbenchmark           old bytes     new bytes     delta\n\tBenchmarkConcat     80            48            -40.00%\n*/\npackage main // import \"golang.org/x/tools/cmd/benchcmp\"\n"
  },
  {
    "path": "cmd/bisect/go120.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"time\"\n)\n\nfunc cmdInterrupt(cmd *exec.Cmd) {\n\tcmd.Cancel = func() error {\n\t\t// On timeout, send interrupt,\n\t\t// in hopes of shutting down process tree.\n\t\t// Ignore errors sending signal; it's all best effort\n\t\t// and not even implemented on Windows.\n\t\t// TODO(rsc): Maybe use a new process group and kill the whole group?\n\t\tcmd.Process.Signal(os.Interrupt)\n\t\treturn nil\n\t}\n\tcmd.WaitDelay = 2 * time.Second\n}\n"
  },
  {
    "path": "cmd/bisect/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Bisect finds changes responsible for causing a failure.\n// A typical use is to identify the source locations in a program\n// that are miscompiled by a given compiler optimization.\n//\n// Usage:\n//\n//\tbisect [flags] [var=value...] command [arguments...]\n//\n// Bisect operates on a target command line – the target – that can be\n// run with various changes individually enabled or disabled. With none\n// of the changes enabled, the target is known to succeed (exit with exit\n// code zero). With all the changes enabled, the target is known to fail\n// (exit any other way). Bisect repeats the target with different sets of\n// changes enabled, using binary search to find (non-overlapping) minimal\n// change sets that provoke the failure.\n//\n// The target must cooperate with bisect by accepting a change pattern\n// and then enabling and reporting the changes that match that pattern.\n// The change pattern is passed to the target by substituting it anywhere\n// the string PATTERN appears in the environment values or the command\n// arguments. For each change that matches the pattern, the target must\n// enable that change and also print one or more “match lines”\n// (to standard output or standard error) describing the change.\n// The [golang.org/x/tools/internal/bisect] package provides functions to help\n// targets implement this protocol. We plan to publish that package\n// in a non-internal location after finalizing its API.\n//\n// Bisect starts by running the target with no changes enabled and then\n// with all changes enabled. It expects the former to succeed and the latter to fail,\n// and then it will search for the minimal set of changes that must be enabled\n// to provoke the failure. If the situation is reversed – the target fails with no\n// changes enabled and succeeds with all changes enabled – then bisect\n// automatically runs in reverse as well, searching for the minimal set of changes\n// that must be disabled to provoke the failure.\n//\n// Bisect prints tracing logs to standard error and the minimal change sets\n// to standard output.\n//\n// # Command Line Flags\n//\n// Bisect supports the following command-line flags:\n//\n//\t-max=M\n//\n// Stop after finding M minimal change sets. The default is no maximum, meaning to run until\n// all changes that provoke a failure have been identified.\n//\n//\t-maxset=S\n//\n// Disallow change sets larger than S elements. The default is no maximum.\n//\n//\t-timeout=D\n//\n// If the target runs for longer than duration D, stop the target and interpret that as a failure.\n// The default is no timeout.\n//\n//\t-count=N\n//\n// Run each trial N times (default 2), checking for consistency.\n//\n//\t-v\n//\n// Print verbose output, showing each run and its match lines.\n//\n// In addition to these general flags,\n// bisect supports a few “shortcut” flags that make it more convenient\n// to use with specific targets.\n//\n//\t-compile=<rewrite>\n//\n// This flag is equivalent to adding an environment variable\n// “GOCOMPILEDEBUG=<rewrite>hash=PATTERN”,\n// which, as discussed in more detail in the example below,\n// allows bisect to identify the specific source locations where the\n// compiler rewrite causes the target to fail.\n//\n//\t-godebug=<name>=<value>\n//\n// This flag is equivalent to adding an environment variable\n// “GODEBUG=<name>=<value>#PATTERN”,\n// which allows bisect to identify the specific call stacks where\n// the changed [GODEBUG setting] value causes the target to fail.\n//\n// # Example\n//\n// The Go compiler provides support for enabling or disabling certain rewrites\n// and optimizations to allow bisect to identify specific source locations where\n// the rewrite causes the program to fail. For example, to bisect a failure caused\n// by the new loop variable semantics:\n//\n//\tbisect go test -gcflags=all=-d=loopvarhash=PATTERN\n//\n// The -gcflags=all= instructs the go command to pass the -d=... to the Go compiler\n// when compiling all packages. Bisect varies PATTERN to determine the minimal set of changes\n// needed to reproduce the failure.\n//\n// The go command also checks the GOCOMPILEDEBUG environment variable for flags\n// to pass to the compiler, so the above command is equivalent to:\n//\n//\tbisect GOCOMPILEDEBUG=loopvarhash=PATTERN go test\n//\n// Finally, as mentioned earlier, the -compile flag allows shortening this command further:\n//\n//\tbisect -compile=loopvar go test\n//\n// # Defeating Build Caches\n//\n// Build systems cache build results, to avoid repeating the same compilations\n// over and over. When using a cached build result, the go command (correctly)\n// reprints the cached standard output and standard error associated with that\n// command invocation. (This makes commands like 'go build -gcflags=-S' for\n// printing an assembly listing work reliably.)\n//\n// Unfortunately, most build systems, including Bazel, are not as careful\n// as the go command about reprinting compiler output. If the compiler is\n// what prints match lines, a build system that suppresses compiler\n// output when using cached compiler results will confuse bisect.\n// To defeat such build caches, bisect replaces the literal text “RANDOM”\n// in environment values and command arguments with a random 64-bit value\n// during each invocation. The Go compiler conveniently accepts a\n// -d=ignore=... debug flag that ignores its argument, so to run the\n// previous example using Bazel, the invocation is:\n//\n//\tbazel test --define=gc_goopts=-d=loopvarhash=PATTERN,unused=RANDOM //path/to:test\n//\n// [GODEBUG setting]: https://tip.golang.org/doc/godebug\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"math/bits\"\n\t\"math/rand\"\n\t\"os\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/bisect\"\n)\n\n// Preserve import of bisect, to allow [bisect.Match] in the doc comment.\nvar _ bisect.Matcher\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: bisect [flags] [var=value...] command [arguments...]\\n\")\n\tflag.PrintDefaults()\n\tos.Exit(2)\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"bisect: \")\n\n\tvar b Bisect\n\tb.Stdout = os.Stdout\n\tb.Stderr = os.Stderr\n\tflag.IntVar(&b.Max, \"max\", 0, \"stop after finding `m` failing change sets\")\n\tflag.IntVar(&b.MaxSet, \"maxset\", 0, \"do not search for change sets larger than `s` elements\")\n\tflag.DurationVar(&b.Timeout, \"timeout\", 0, \"stop target and consider failed after duration `d`\")\n\tflag.IntVar(&b.Count, \"count\", 2, \"run target `n` times for each trial\")\n\tflag.BoolVar(&b.Verbose, \"v\", false, \"enable verbose output\")\n\n\tenv := \"\"\n\tenvFlag := \"\"\n\tflag.Func(\"compile\", \"bisect source locations affected by Go compiler `rewrite` (fma, loopvar, ...)\", func(value string) error {\n\t\tif envFlag != \"\" {\n\t\t\treturn fmt.Errorf(\"cannot use -%s and -compile\", envFlag)\n\t\t}\n\t\tenvFlag = \"compile\"\n\t\tenv = \"GOCOMPILEDEBUG=\" + value + \"hash=PATTERN\"\n\t\treturn nil\n\t})\n\tflag.Func(\"godebug\", \"bisect call stacks affected by GODEBUG setting `name=value`\", func(value string) error {\n\t\tif envFlag != \"\" {\n\t\t\treturn fmt.Errorf(\"cannot use -%s and -godebug\", envFlag)\n\t\t}\n\t\tenvFlag = \"godebug\"\n\t\tenv = \"GODEBUG=\" + value + \"#PATTERN\"\n\t\treturn nil\n\t})\n\n\tflag.Usage = usage\n\tflag.Parse()\n\targs := flag.Args()\n\n\t// Split command line into env settings, command name, args.\n\ti := 0\n\tfor i < len(args) && strings.Contains(args[i], \"=\") {\n\t\ti++\n\t}\n\tif i == len(args) {\n\t\tusage()\n\t}\n\tb.Env, b.Cmd, b.Args = args[:i], args[i], args[i+1:]\n\tif env != \"\" {\n\t\tb.Env = append([]string{env}, b.Env...)\n\t}\n\n\t// Check that PATTERN is available for us to vary.\n\tfound := false\n\tfor _, e := range b.Env {\n\t\tif _, v, _ := strings.Cut(e, \"=\"); strings.Contains(v, \"PATTERN\") {\n\t\t\tfound = true\n\t\t}\n\t}\n\tfor _, a := range b.Args {\n\t\tif strings.Contains(a, \"PATTERN\") {\n\t\t\tfound = true\n\t\t}\n\t}\n\tif !found {\n\t\tlog.Fatalf(\"no PATTERN in target environment or args\")\n\t}\n\n\tif !b.Search() {\n\t\tos.Exit(1)\n\t}\n}\n\n// A Bisect holds the state for a bisect invocation.\ntype Bisect struct {\n\t// Env is the additional environment variables for the command.\n\t// PATTERN and RANDOM are substituted in the values, but not the names.\n\tEnv []string\n\n\t// Cmd is the command (program name) to run.\n\t// PATTERN and RANDOM are not substituted.\n\tCmd string\n\n\t// Args is the command arguments.\n\t// PATTERN and RANDOM are substituted anywhere they appear.\n\tArgs []string\n\n\t// Command-line flags controlling bisect behavior.\n\tMax     int           // maximum number of sets to report (0 = unlimited)\n\tMaxSet  int           // maximum number of elements in a set (0 = unlimited)\n\tTimeout time.Duration // kill target and assume failed after this duration (0 = unlimited)\n\tCount   int           // run target this many times for each trial and give up if flaky (min 1 assumed; default 2 on command line set in main)\n\tVerbose bool          // print long output about each trial (only useful for debugging bisect itself)\n\n\t// State for running bisect, replaced during testing.\n\t// Failing change sets are printed to Stdout; all other output goes to Stderr.\n\tStdout  io.Writer                                                             // where to write standard output (usually os.Stdout)\n\tStderr  io.Writer                                                             // where to write standard error (usually os.Stderr)\n\tTestRun func(env []string, cmd string, args []string) (out []byte, err error) // if non-nil, used instead of exec.Command\n\n\t// State maintained by Search.\n\n\t// By default, Search looks for a minimal set of changes that cause a failure when enabled.\n\t// If Disable is true, the search is inverted and seeks a minimal set of changes that\n\t// cause a failure when disabled. In this case, the search proceeds as normal except that\n\t// each pattern starts with a !.\n\tDisable bool\n\n\t// SkipHexDigits is the number of hex digits to use in skip messages.\n\t// If the set of available changes is the same in each run, as it should be,\n\t// then this doesn't matter: we'll only exclude suffixes that uniquely identify\n\t// a given change. But for some programs, especially bisecting runtime\n\t// behaviors, sometimes enabling one change unlocks questions about other\n\t// changes. Strictly speaking this is a misuse of bisect, but just to make\n\t// bisect more robust, we use the y and n runs to create an estimate of the\n\t// number of bits needed for a unique suffix, and then we round it up to\n\t// a number of hex digits, with one extra digit for good measure, and then\n\t// we always use that many hex digits for skips.\n\tSkipHexDigits int\n\n\t// Add is a list of suffixes to add to every trial, because they\n\t// contain changes that are necessary for a group we are assembling.\n\tAdd []string\n\n\t// Skip is a list of suffixes that uniquely identify changes to exclude from every trial,\n\t// because they have already been used in failing change sets.\n\t// Suffixes later in the list may only be unique after removing\n\t// the ones earlier in the list.\n\t// Skip applies after Add.\n\tSkip []string\n}\n\n// A Result holds the result of a single target trial.\ntype Result struct {\n\tSuccess bool   // whether the target succeeded (exited with zero status)\n\tCmd     string // full target command line\n\tOut     string // full target output (stdout and stderr combined)\n\n\tSuffix    string   // the suffix used for collecting MatchIDs, MatchText, and MatchFull\n\tMatchIDs  []uint64 // match IDs enabled during this trial\n\tMatchText []string // match reports for the IDs, with match markers removed\n\tMatchFull []string // full match lines for the IDs, with match markers kept\n}\n\n// &searchFatal is a special panic value to signal that Search failed.\n// This lets us unwind the search recursion on a fatal error\n// but have Search return normally.\nvar searchFatal int\n\n// Search runs a bisect search according to the configuration in b.\n// It reports whether any failing change sets were found.\nfunc (b *Bisect) Search() bool {\n\tdefer func() {\n\t\t// Recover from panic(&searchFatal), implicitly returning false from Search.\n\t\t// Re-panic on any other panic.\n\t\tif e := recover(); e != nil && e != &searchFatal {\n\t\t\tpanic(e)\n\t\t}\n\t}()\n\n\t// Run with no changes and all changes, to figure out which direction we're searching.\n\t// The goal is to find the minimal set of changes to toggle\n\t// starting with the state where everything works.\n\t// If \"no changes\" succeeds and \"all changes\" fails,\n\t// we're looking for a minimal set of changes to enable to provoke the failure\n\t// (broken = runY, b.Negate = false)\n\t// If \"no changes\" fails and \"all changes\" succeeds,\n\t// we're looking for a minimal set of changes to disable to provoke the failure\n\t// (broken = runN, b.Negate = true).\n\n\tb.Logf(\"checking target with all changes disabled\")\n\trunN := b.Run(\"n\")\n\n\tb.Logf(\"checking target with all changes enabled\")\n\trunY := b.Run(\"y\")\n\n\tvar broken *Result\n\tswitch {\n\tcase runN.Success && !runY.Success:\n\t\tb.Logf(\"target succeeds with no changes, fails with all changes\")\n\t\tb.Logf(\"searching for minimal set of enabled changes causing failure\")\n\t\tbroken = runY\n\t\tb.Disable = false\n\n\tcase !runN.Success && runY.Success:\n\t\tb.Logf(\"target fails with no changes, succeeds with all changes\")\n\t\tb.Logf(\"searching for minimal set of disabled changes causing failure\")\n\t\tbroken = runN\n\t\tb.Disable = true\n\n\tcase runN.Success && runY.Success:\n\t\tb.Fatalf(\"target succeeds with no changes and all changes\")\n\n\tcase !runN.Success && !runY.Success:\n\t\tb.Fatalf(\"target fails with no changes and all changes\")\n\t}\n\n\t// Compute minimum number of bits needed to distinguish\n\t// all the changes we saw during N and all the changes we saw during Y.\n\tb.SkipHexDigits = skipHexDigits(runN.MatchIDs, runY.MatchIDs)\n\n\t// Loop finding and printing change sets, until none remain.\n\tfound := 0\n\tfor {\n\t\t// Find set.\n\t\tbad := b.search(broken)\n\t\tif bad == nil {\n\t\t\tif found == 0 {\n\t\t\t\tb.Fatalf(\"cannot find any failing change sets of size ≤ %d\", b.MaxSet)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\t// Confirm that set really does fail, to avoid false accusations.\n\t\t// Also asking for user-visible output; earlier runs did not.\n\t\tb.Logf(\"confirming failing change set\")\n\t\tb.Add = append(b.Add[:0], bad...)\n\t\tbroken = b.Run(\"v\")\n\t\tif broken.Success {\n\t\t\tb.Logf(\"confirmation run succeeded unexpectedly\")\n\t\t}\n\t\tb.Add = b.Add[:0]\n\n\t\t// Print confirmed change set.\n\t\tfound++\n\t\tb.Logf(\"FOUND failing change set\")\n\t\tdesc := \"(enabling changes causes failure)\"\n\t\tif b.Disable {\n\t\t\tdesc = \"(disabling changes causes failure)\"\n\t\t}\n\t\tfmt.Fprintf(b.Stdout, \"--- change set #%d %s\\n%s\\n---\\n\", found, desc, strings.Join(broken.MatchText, \"\\n\"))\n\n\t\t// Stop if we've found enough change sets.\n\t\tif b.Max > 0 && found >= b.Max {\n\t\t\tbreak\n\t\t}\n\n\t\t// If running bisect target | tee bad.txt, prints to stdout and stderr\n\t\t// both appear on the terminal, but the ones to stdout go through tee\n\t\t// and can take a little bit of extra time. Sleep 1 millisecond to give\n\t\t// tee time to catch up, so that its stdout print does not get interlaced\n\t\t// with the stderr print from the next b.Log message.\n\t\ttime.Sleep(1 * time.Millisecond)\n\n\t\t// Disable the now-known-bad changes and see if any failures remain.\n\t\tb.Logf(\"checking for more failures\")\n\t\tb.Skip = append(bad, b.Skip...)\n\t\tbroken = b.Run(\"\")\n\t\tif broken.Success {\n\t\t\twhat := \"enabled\"\n\t\t\tif b.Disable {\n\t\t\t\twhat = \"disabled\"\n\t\t\t}\n\t\t\tb.Logf(\"target succeeds with all remaining changes %s\", what)\n\t\t\tbreak\n\t\t}\n\t\tb.Logf(\"target still fails; searching for more bad changes\")\n\t}\n\treturn true\n}\n\n// Fatalf prints a message to standard error and then panics,\n// causing Search to return false.\nfunc (b *Bisect) Fatalf(format string, args ...any) {\n\ts := fmt.Sprintf(\"bisect: fatal error: \"+format, args...)\n\tif !strings.HasSuffix(s, \"\\n\") {\n\t\ts += \"\\n\"\n\t}\n\tb.Stderr.Write([]byte(s))\n\tpanic(&searchFatal)\n}\n\n// Logf prints a message to standard error.\nfunc (b *Bisect) Logf(format string, args ...any) {\n\ts := fmt.Sprintf(\"bisect: \"+format, args...)\n\tif !strings.HasSuffix(s, \"\\n\") {\n\t\ts += \"\\n\"\n\t}\n\tb.Stderr.Write([]byte(s))\n}\n\nfunc skipHexDigits(idY, idN []uint64) int {\n\tvar all []uint64\n\tseen := make(map[uint64]bool)\n\tfor _, x := range idY {\n\t\tseen[x] = true\n\t\tall = append(all, x)\n\t}\n\tfor _, x := range idN {\n\t\tif !seen[x] {\n\t\t\tseen[x] = true\n\t\t\tall = append(all, x)\n\t\t}\n\t}\n\tsort.Slice(all, func(i, j int) bool { return bits.Reverse64(all[i]) < bits.Reverse64(all[j]) })\n\tdigits := sort.Search(64/4, func(digits int) bool {\n\t\tmask := uint64(1)<<(4*digits) - 1\n\t\tfor i := 0; i+1 < len(all); i++ {\n\t\t\tif all[i]&mask == all[i+1]&mask {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\tif digits < 64/4 {\n\t\tdigits++\n\t}\n\treturn digits\n}\n\n// search searches for a single locally minimal change set.\n//\n// Invariant: r describes the result of r.Suffix + b.Add, which failed.\n// (There's an implicit -b.Skip everywhere here. b.Skip does not change.)\n// We want to extend r.Suffix to preserve the failure, working toward\n// a suffix that identifies a single change.\nfunc (b *Bisect) search(r *Result) []string {\n\t// The caller should be passing in a failure result that we diagnose.\n\tif r.Success {\n\t\tb.Fatalf(\"internal error: unexpected success\") // mistake by caller\n\t}\n\n\t// If the failure reported no changes, the target is misbehaving.\n\tif len(r.MatchIDs) == 0 {\n\t\tb.Fatalf(\"failure with no reported changes:\\n\\n$ %s\\n%s\\n\", r.Cmd, r.Out)\n\t}\n\n\t// If there's one matching change, that's the one we're looking for.\n\tif len(r.MatchIDs) == 1 {\n\t\treturn []string{fmt.Sprintf(\"x%0*x\", b.SkipHexDigits, r.MatchIDs[0]&(1<<(4*b.SkipHexDigits)-1))}\n\t}\n\n\t// If the suffix we were tracking in the trial is already 64 bits,\n\t// either the target is bad or bisect itself is buggy.\n\tif len(r.Suffix) >= 64 {\n\t\tb.Fatalf(\"failed to isolate a single change with very long suffix\")\n\t}\n\n\t// We want to split the current matchIDs by left-extending the suffix with 0 and 1.\n\t// If all the matches have the same next bit, that won't cause a split, which doesn't\n\t// break the algorithm but does waste time. Avoid wasting time by left-extending\n\t// the suffix to the longest suffix shared by all the current match IDs\n\t// before adding 0 or 1.\n\tsuffix := commonSuffix(r.MatchIDs)\n\tif !strings.HasSuffix(suffix, r.Suffix) {\n\t\tb.Fatalf(\"internal error: invalid common suffix\") // bug in commonSuffix\n\t}\n\n\t// Run 0suffix and 1suffix. If one fails, chase down the failure in that half.\n\tr0 := b.Run(\"0\" + suffix)\n\tif !r0.Success {\n\t\treturn b.search(r0)\n\t}\n\tr1 := b.Run(\"1\" + suffix)\n\tif !r1.Success {\n\t\treturn b.search(r1)\n\t}\n\n\t// suffix failed, but 0suffix and 1suffix succeeded.\n\t// Assuming the target isn't flaky, this means we need\n\t// at least one change from 0suffix AND at least one from 1suffix.\n\t// We are already tracking N = len(b.Add) other changes and are\n\t// allowed to build sets of size at least 1+N (or we shouldn't be here at all).\n\t// If we aren't allowed to build sets of size 2+N, give up this branch.\n\tif b.MaxSet > 0 && 2+len(b.Add) > b.MaxSet {\n\t\treturn nil\n\t}\n\n\t// Adding all matches for 1suffix, recurse to narrow down 0suffix.\n\told := len(b.Add)\n\tb.Add = append(b.Add, \"1\"+suffix)\n\tr0 = b.Run(\"0\" + suffix)\n\tif r0.Success {\n\t\t// 0suffix + b.Add + 1suffix = suffix + b.Add is what r describes, and it failed.\n\t\tb.Fatalf(\"target fails inconsistently\")\n\t}\n\tbad0 := b.search(r0)\n\tif bad0 == nil {\n\t\t// Search failed due to MaxSet limit.\n\t\treturn nil\n\t}\n\tb.Add = b.Add[:old]\n\n\t// Adding the specific match we found in 0suffix, recurse to narrow down 1suffix.\n\tb.Add = append(b.Add[:old], bad0...)\n\tr1 = b.Run(\"1\" + suffix)\n\tif r1.Success {\n\t\t// 1suffix + b.Add + bad0 = bad0 + b.Add + 1suffix is what b.search(r0) reported as a failure.\n\t\tb.Fatalf(\"target fails inconsistently\")\n\t}\n\tbad1 := b.search(r1)\n\tif bad1 == nil {\n\t\t// Search failed due to MaxSet limit.\n\t\treturn nil\n\t}\n\tb.Add = b.Add[:old]\n\n\t// bad0 and bad1 together provoke the failure.\n\treturn append(bad0, bad1...)\n}\n\n// Run runs a set of trials selecting changes with the given suffix,\n// plus the ones in b.Add and not the ones in b.Skip.\n// The returned result's MatchIDs, MatchText, and MatchFull\n// only list the changes that match suffix.\n// When b.Count > 1, Run runs b.Count trials and requires\n// that they all succeed or they all fail. If not, it calls b.Fatalf.\nfunc (b *Bisect) Run(suffix string) *Result {\n\tout := b.run(suffix)\n\tfor i := 1; i < b.Count; i++ {\n\t\tr := b.run(suffix)\n\t\tif r.Success != out.Success {\n\t\t\tb.Fatalf(\"target fails inconsistently\")\n\t\t}\n\t}\n\treturn out\n}\n\n// run runs a single trial for Run.\nfunc (b *Bisect) run(suffix string) *Result {\n\trandom := fmt.Sprint(rand.Uint64())\n\n\t// Accept suffix == \"v\" to mean we need user-visible output.\n\tvisible := \"\"\n\tif suffix == \"v\" {\n\t\tvisible = \"v\"\n\t\tsuffix = \"\"\n\t}\n\n\t// Construct change ID pattern.\n\tvar pattern string\n\tif suffix == \"y\" || suffix == \"n\" {\n\t\tpattern = suffix\n\t\tsuffix = \"\"\n\t} else {\n\t\tvar elem []string\n\t\tif suffix != \"\" {\n\t\t\telem = append(elem, \"+\", suffix)\n\t\t}\n\t\tfor _, x := range b.Add {\n\t\t\telem = append(elem, \"+\", x)\n\t\t}\n\t\tfor _, x := range b.Skip {\n\t\t\telem = append(elem, \"-\", x)\n\t\t}\n\t\tpattern = strings.Join(elem, \"\")\n\t\tif pattern == \"\" {\n\t\t\tpattern = \"y\"\n\t\t}\n\t}\n\tif b.Disable {\n\t\tpattern = \"!\" + pattern\n\t}\n\tpattern = visible + pattern\n\n\t// Construct substituted env and args.\n\tenv := make([]string, len(b.Env))\n\tfor i, x := range b.Env {\n\t\tk, v, _ := strings.Cut(x, \"=\")\n\t\tenv[i] = k + \"=\" + replace(v, pattern, random)\n\t}\n\targs := make([]string, len(b.Args))\n\tfor i, x := range b.Args {\n\t\targs[i] = replace(x, pattern, random)\n\t}\n\n\t// Construct and log command line.\n\t// There is no newline in the log print.\n\t// The line will be completed when the command finishes.\n\tcmdText := strings.Join(append(append(env, b.Cmd), args...), \" \")\n\tfmt.Fprintf(b.Stderr, \"bisect: run: %s...\", cmdText)\n\n\t// Run command with args and env.\n\tvar out []byte\n\tvar err error\n\tif b.TestRun != nil {\n\t\tout, err = b.TestRun(env, b.Cmd, args)\n\t} else {\n\t\tctx := context.Background()\n\t\tif b.Timeout != 0 {\n\t\t\tvar cancel context.CancelFunc\n\t\t\tctx, cancel = context.WithTimeout(ctx, b.Timeout)\n\t\t\tdefer cancel()\n\t\t}\n\t\tcmd := exec.CommandContext(ctx, b.Cmd, args...)\n\t\tcmd.Env = append(os.Environ(), env...)\n\t\t// Set up cmd.Cancel, cmd.WaitDelay on Go 1.20 and later\n\t\t// TODO(rsc): Inline go120.go's cmdInterrupt once we stop supporting Go 1.19.\n\t\tcmdInterrupt(cmd)\n\t\tout, err = cmd.CombinedOutput()\n\t}\n\n\t// Parse output to construct result.\n\tr := &Result{\n\t\tSuffix:  suffix,\n\t\tSuccess: err == nil,\n\t\tCmd:     cmdText,\n\t\tOut:     string(out),\n\t}\n\n\t// Calculate bits, mask to identify suffix matches.\n\tvar bits, mask uint64\n\tif suffix != \"\" && suffix != \"y\" && suffix != \"n\" && suffix != \"v\" {\n\t\tvar err error\n\t\tbits, err = strconv.ParseUint(suffix, 2, 64)\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"internal error: bad suffix\")\n\t\t}\n\t\tmask = uint64(1<<len(suffix)) - 1\n\t}\n\n\t// Process output, collecting match reports for suffix.\n\thave := make(map[uint64]bool)\n\tall := r.Out\n\tfor all != \"\" {\n\t\tvar line string\n\t\tline, all, _ = strings.Cut(all, \"\\n\")\n\t\tshort, id, ok := bisect.CutMarker(line)\n\t\tif !ok || (id&mask) != bits {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !have[id] {\n\t\t\thave[id] = true\n\t\t\tr.MatchIDs = append(r.MatchIDs, id)\n\t\t}\n\t\tr.MatchText = append(r.MatchText, short)\n\t\tr.MatchFull = append(r.MatchFull, line)\n\t}\n\n\t// Finish log print from above, describing the command's completion.\n\tif err == nil {\n\t\tfmt.Fprintf(b.Stderr, \" ok (%d matches)\\n\", len(r.MatchIDs))\n\t} else {\n\t\tfmt.Fprintf(b.Stderr, \" FAIL (%d matches)\\n\", len(r.MatchIDs))\n\t}\n\n\tif err != nil && len(r.MatchIDs) == 0 {\n\t\tb.Fatalf(\"target failed without printing any matches\\n%s\", r.Out)\n\t}\n\n\t// In verbose mode, print extra debugging: all the lines with match markers.\n\tif b.Verbose {\n\t\tb.Logf(\"matches:\\n%s\", strings.Join(r.MatchFull, \"\\n\\t\"))\n\t}\n\n\treturn r\n}\n\n// replace returns x with literal text PATTERN and RANDOM replaced by pattern and random.\nfunc replace(x, pattern, random string) string {\n\tx = strings.ReplaceAll(x, \"PATTERN\", pattern)\n\tx = strings.ReplaceAll(x, \"RANDOM\", random)\n\treturn x\n}\n\n// commonSuffix returns the longest common binary suffix shared by all uint64s in list.\n// If list is empty, commonSuffix returns an empty string.\nfunc commonSuffix(list []uint64) string {\n\tif len(list) == 0 {\n\t\treturn \"\"\n\t}\n\tb := list[0]\n\tn := 64\n\tfor _, x := range list {\n\t\tfor x&((1<<n)-1) != b {\n\t\t\tn--\n\t\t\tb &= (1 << n) - 1\n\t\t}\n\t}\n\ts := make([]byte, n)\n\tfor i := n - 1; i >= 0; i-- {\n\t\ts[i] = '0' + byte(b&1)\n\t\tb >>= 1\n\t}\n\treturn string(s[:])\n}\n"
  },
  {
    "path": "cmd/bisect/main_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build/constraint\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/bisect\"\n\t\"golang.org/x/tools/internal/diffp\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nvar update = flag.Bool(\"update\", false, \"update testdata with new stdout/stderr\")\n\nfunc Test(t *testing.T) {\n\tfiles, err := filepath.Glob(\"testdata/*.txt\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, file := range files {\n\t\tt.Run(strings.TrimSuffix(filepath.Base(file), \".txt\"), func(t *testing.T) {\n\t\t\tdata, err := os.ReadFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\ta := txtar.Parse(data)\n\t\t\tvar wantStdout, wantStderr []byte\n\t\t\tfiles := a.Files\n\t\t\tif len(files) > 0 && files[0].Name == \"stdout\" {\n\t\t\t\twantStdout = files[0].Data\n\t\t\t\tfiles = files[1:]\n\t\t\t}\n\t\t\tif len(files) > 0 && files[0].Name == \"stderr\" {\n\t\t\t\twantStderr = files[0].Data\n\t\t\t\tfiles = files[1:]\n\t\t\t}\n\t\t\tif len(files) > 0 {\n\t\t\t\tt.Fatalf(\"unexpected txtar entry: %s\", files[0].Name)\n\t\t\t}\n\n\t\t\tvar tt struct {\n\t\t\t\tFail   string\n\t\t\t\tBisect Bisect\n\t\t\t}\n\t\t\tif err := json.Unmarshal(a.Comment, &tt); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\texpr, err := constraint.Parse(\"//go:build \" + tt.Fail)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"invalid Cmd: %v\", err)\n\t\t\t}\n\n\t\t\trnd := rand.New(rand.NewSource(1))\n\t\t\tb := &tt.Bisect\n\t\t\tb.Cmd = \"test\"\n\t\t\tb.Args = []string{\"PATTERN\"}\n\t\t\tvar stdout, stderr bytes.Buffer\n\t\t\tb.Stdout = &stdout\n\t\t\tb.Stderr = &stderr\n\t\t\tb.TestRun = func(env []string, cmd string, args []string) (out []byte, err error) {\n\t\t\t\tpattern := args[0]\n\t\t\t\tm, err := bisect.New(pattern)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\thave := make(map[string]bool)\n\t\t\t\tfor i, color := range colors {\n\t\t\t\t\tif m.ShouldEnable(uint64(i)) {\n\t\t\t\t\t\thave[color] = true\n\t\t\t\t\t}\n\t\t\t\t\tif m.ShouldReport(uint64(i)) {\n\t\t\t\t\t\tout = fmt.Appendf(out, \"%s %s\\n\", color, bisect.Marker(uint64(i)))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\terr = nil\n\t\t\t\tif eval(rnd, expr, have) {\n\t\t\t\t\terr = fmt.Errorf(\"failed\")\n\t\t\t\t}\n\t\t\t\treturn out, err\n\t\t\t}\n\n\t\t\tif !b.Search() {\n\t\t\t\tstderr.WriteString(\"<bisect failed>\\n\")\n\t\t\t}\n\t\t\trewrite := false\n\t\t\tif !bytes.Equal(stdout.Bytes(), wantStdout) {\n\t\t\t\tif *update {\n\t\t\t\t\trewrite = true\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"incorrect stdout: %s\", diffp.Diff(\"have\", stdout.Bytes(), \"want\", wantStdout))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !bytes.Equal(stderr.Bytes(), wantStderr) {\n\t\t\t\tif *update {\n\t\t\t\t\trewrite = true\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"incorrect stderr: %s\", diffp.Diff(\"have\", stderr.Bytes(), \"want\", wantStderr))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif rewrite {\n\t\t\t\ta.Files = []txtar.File{{Name: \"stdout\", Data: stdout.Bytes()}, {Name: \"stderr\", Data: stderr.Bytes()}}\n\t\t\t\terr := os.WriteFile(file, txtar.Format(a), 0666)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tt.Logf(\"updated %s\", file)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc eval(rnd *rand.Rand, z constraint.Expr, have map[string]bool) bool {\n\tswitch z := z.(type) {\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected type %T\", z))\n\tcase *constraint.NotExpr:\n\t\treturn !eval(rnd, z.X, have)\n\tcase *constraint.AndExpr:\n\t\treturn eval(rnd, z.X, have) && eval(rnd, z.Y, have)\n\tcase *constraint.OrExpr:\n\t\treturn eval(rnd, z.X, have) || eval(rnd, z.Y, have)\n\tcase *constraint.TagExpr:\n\t\tif z.Tag == \"random\" {\n\t\t\treturn rnd.Intn(2) == 1\n\t\t}\n\t\treturn have[z.Tag]\n\t}\n}\n\nvar colors = strings.Fields(`\n\taliceblue\n\tamaranth\n\tamber\n\tamethyst\n\tapplegreen\n\tapplered\n\tapricot\n\taquamarine\n\tazure\n\tbabyblue\n\tbeige\n\tbrickred\n\tblack\n\tblue\n\tbluegreen\n\tblueviolet\n\tblush\n\tbronze\n\tbrown\n\tburgundy\n\tbyzantium\n\tcarmine\n\tcerise\n\tcerulean\n\tchampagne\n\tchartreusegreen\n\tchocolate\n\tcobaltblue\n\tcoffee\n\tcopper\n\tcoral\n\tcrimson\n\tcyan\n\tdesertsand\n\telectricblue\n\temerald\n\terin\n\tgold\n\tgray\n\tgreen\n\tharlequin\n\tindigo\n\tivory\n\tjade\n\tjunglegreen\n\tlavender\n\tlemon\n\tlilac\n\tlime\n\tmagenta\n\tmagentarose\n\tmaroon\n\tmauve\n\tnavyblue\n\tochre\n\tolive\n\torange\n\torangered\n\torchid\n\tpeach\n\tpear\n\tperiwinkle\n\tpersianblue\n\tpink\n\tplum\n\tprussianblue\n\tpuce\n\tpurple\n\traspberry\n\tred\n\tredviolet\n\trose\n\truby\n\tsalmon\n\tsangria\n\tsapphire\n\tscarlet\n\tsilver\n\tslategray\n\tspringbud\n\tspringgreen\n\ttan\n\ttaupe\n\tteal\n\tturquoise\n\tultramarine\n\tviolet\n\tviridian\n\twhite\n\tyellow\n`)\n"
  },
  {
    "path": "cmd/bisect/testdata/README.md",
    "content": "This directory contains test inputs for the bisect command.\n\nEach text file is a txtar archive (see <https://pkg.go.dev/golang.org/x/tools/txtar>\nor `go doc txtar`).\n\nThe comment at the top of the archive is a JSON object describing a\ntarget behavior. Specifically, the Fail key gives a boolean expression\nthat should provoke a failure. Bisect's job is to discover this\ncondition.\n\nThe Bisect key describes settings in the Bisect struct that we want to\nchange, to simulate the use of various command-line options.\n\nThe txtar archive files should be \"stdout\" and \"stderr\", giving the\nexpected standard output and standard error. If the bisect command\nshould exit with a non-zero status, the stderr in the archive will end\nwith the line \"<bisect failed>\".\n\nRunning `go test -update` will rewrite the stdout and stderr files in\neach testdata archive to match the current state of the tool. This is\na useful command when the logging prints from bisect change or when\nwriting a new test.\n\nTo use `go test -update` to write a new test:\n\n - Create a new .txt file with just a JSON object at the top,\n   specifying what you want to test.\n - Run `go test -update`.\n - Reload the .txt file and read the stdout and stderr to see if you agree.\n"
  },
  {
    "path": "cmd/bisect/testdata/basic.txt",
    "content": "{\"Fail\": \"amber || apricot\"}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\napricot\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... FAIL (44 matches)\nbisect: run: test +00-x002... ok (23 matches)\nbisect: run: test +10-x002... FAIL (21 matches)\nbisect: run: test +010-x002... ok (10 matches)\nbisect: run: test +110-x002... FAIL (11 matches)\nbisect: run: test +0110-x002... FAIL (6 matches)\nbisect: run: test +00110-x002... FAIL (3 matches)\nbisect: run: test +000110-x002... FAIL (2 matches)\nbisect: run: test +0000110-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x006-x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x006-x002... ok (88 matches)\nbisect: target succeeds with all remaining changes enabled\n"
  },
  {
    "path": "cmd/bisect/testdata/count2.txt",
    "content": "{\"Fail\": \"amber || apricot\", \"Bisect\": {\"Count\": 2}}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\napricot\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... FAIL (44 matches)\nbisect: run: test +0-x002... FAIL (44 matches)\nbisect: run: test +00-x002... ok (23 matches)\nbisect: run: test +00-x002... ok (23 matches)\nbisect: run: test +10-x002... FAIL (21 matches)\nbisect: run: test +10-x002... FAIL (21 matches)\nbisect: run: test +010-x002... ok (10 matches)\nbisect: run: test +010-x002... ok (10 matches)\nbisect: run: test +110-x002... FAIL (11 matches)\nbisect: run: test +110-x002... FAIL (11 matches)\nbisect: run: test +0110-x002... FAIL (6 matches)\nbisect: run: test +0110-x002... FAIL (6 matches)\nbisect: run: test +00110-x002... FAIL (3 matches)\nbisect: run: test +00110-x002... FAIL (3 matches)\nbisect: run: test +000110-x002... FAIL (2 matches)\nbisect: run: test +000110-x002... FAIL (2 matches)\nbisect: run: test +0000110-x002... FAIL (1 matches)\nbisect: run: test +0000110-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x006-x002... FAIL (1 matches)\nbisect: run: test v+x006-x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x006-x002... ok (88 matches)\nbisect: run: test -x006-x002... ok (88 matches)\nbisect: target succeeds with all remaining changes enabled\n"
  },
  {
    "path": "cmd/bisect/testdata/double.txt",
    "content": "{\"Fail\": \"amber || apricot && peach\"}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\napricot\npeach\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... ok (44 matches)\nbisect: run: test +1-x002... ok (45 matches)\nbisect: run: test +0+1-x002... FAIL (44 matches)\nbisect: run: test +00+1-x002... ok (23 matches)\nbisect: run: test +10+1-x002... FAIL (21 matches)\nbisect: run: test +010+1-x002... ok (10 matches)\nbisect: run: test +110+1-x002... FAIL (11 matches)\nbisect: run: test +0110+1-x002... FAIL (6 matches)\nbisect: run: test +00110+1-x002... FAIL (3 matches)\nbisect: run: test +000110+1-x002... FAIL (2 matches)\nbisect: run: test +0000110+1-x002... FAIL (1 matches)\nbisect: run: test +1+x006-x002... FAIL (45 matches)\nbisect: run: test +01+x006-x002... ok (23 matches)\nbisect: run: test +11+x006-x002... FAIL (22 matches)\nbisect: run: test +011+x006-x002... FAIL (11 matches)\nbisect: run: test +0011+x006-x002... ok (6 matches)\nbisect: run: test +1011+x006-x002... FAIL (5 matches)\nbisect: run: test +01011+x006-x002... ok (3 matches)\nbisect: run: test +11011+x006-x002... FAIL (2 matches)\nbisect: run: test +011011+x006-x002... ok (1 matches)\nbisect: run: test +111011+x006-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x006+x03b-x002... FAIL (2 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x006-x03b-x002... ok (87 matches)\nbisect: target succeeds with all remaining changes enabled\n"
  },
  {
    "path": "cmd/bisect/testdata/max1.txt",
    "content": "{\"Fail\": \"amber || apricot && peach\", \"Bisect\": {\"Max\": 1}}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\n"
  },
  {
    "path": "cmd/bisect/testdata/max2.txt",
    "content": "{\"Fail\": \"amber || apricot && peach || red && green && blue || cyan && magenta && yellow && black\", \"Bisect\": {\"Max\": 2}}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\nblue\ngreen\nred\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... ok (44 matches)\nbisect: run: test +1-x002... FAIL (45 matches)\nbisect: run: test +01-x002... ok (23 matches)\nbisect: run: test +11-x002... ok (22 matches)\nbisect: run: test +01+11-x002... FAIL (23 matches)\nbisect: run: test +001+11-x002... ok (12 matches)\nbisect: run: test +101+11-x002... FAIL (11 matches)\nbisect: run: test +0101+11-x002... ok (6 matches)\nbisect: run: test +1101+11-x002... ok (5 matches)\nbisect: run: test +0101+11+1101-x002... FAIL (6 matches)\nbisect: run: test +00101+11+1101-x002... FAIL (3 matches)\nbisect: run: test +000101+11+1101-x002... FAIL (2 matches)\nbisect: run: test +0000101+11+1101-x002... ok (1 matches)\nbisect: run: test +1000101+11+1101-x002... FAIL (1 matches)\nbisect: run: test +1101+11+x045-x002... FAIL (5 matches)\nbisect: run: test +01101+11+x045-x002... FAIL (3 matches)\nbisect: run: test +001101+11+x045-x002... FAIL (2 matches)\nbisect: run: test +0001101+11+x045-x002... FAIL (1 matches)\nbisect: run: test +11+x045+x00d-x002... FAIL (22 matches)\nbisect: run: test +011+x045+x00d-x002... ok (11 matches)\nbisect: run: test +111+x045+x00d-x002... FAIL (11 matches)\nbisect: run: test +0111+x045+x00d-x002... FAIL (6 matches)\nbisect: run: test +00111+x045+x00d-x002... FAIL (3 matches)\nbisect: run: test +000111+x045+x00d-x002... ok (2 matches)\nbisect: run: test +100111+x045+x00d-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x045+x00d+x027-x002... FAIL (3 matches)\nbisect: FOUND failing change set\n"
  },
  {
    "path": "cmd/bisect/testdata/maxset.txt",
    "content": "{\"Fail\": \"amber || apricot && peach || red && green && blue || cyan && magenta && yellow && black\", \"Bisect\": {\"MaxSet\": 3}}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\nblue\ngreen\nred\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... ok (44 matches)\nbisect: run: test +1-x002... FAIL (45 matches)\nbisect: run: test +01-x002... ok (23 matches)\nbisect: run: test +11-x002... ok (22 matches)\nbisect: run: test +01+11-x002... FAIL (23 matches)\nbisect: run: test +001+11-x002... ok (12 matches)\nbisect: run: test +101+11-x002... FAIL (11 matches)\nbisect: run: test +0101+11-x002... ok (6 matches)\nbisect: run: test +1101+11-x002... ok (5 matches)\nbisect: run: test +0101+11+1101-x002... FAIL (6 matches)\nbisect: run: test +00101+11+1101-x002... FAIL (3 matches)\nbisect: run: test +000101+11+1101-x002... FAIL (2 matches)\nbisect: run: test +0000101+11+1101-x002... ok (1 matches)\nbisect: run: test +1000101+11+1101-x002... FAIL (1 matches)\nbisect: run: test +1101+11+x045-x002... FAIL (5 matches)\nbisect: run: test +01101+11+x045-x002... FAIL (3 matches)\nbisect: run: test +001101+11+x045-x002... FAIL (2 matches)\nbisect: run: test +0001101+11+x045-x002... FAIL (1 matches)\nbisect: run: test +11+x045+x00d-x002... FAIL (22 matches)\nbisect: run: test +011+x045+x00d-x002... ok (11 matches)\nbisect: run: test +111+x045+x00d-x002... FAIL (11 matches)\nbisect: run: test +0111+x045+x00d-x002... FAIL (6 matches)\nbisect: run: test +00111+x045+x00d-x002... FAIL (3 matches)\nbisect: run: test +000111+x045+x00d-x002... ok (2 matches)\nbisect: run: test +100111+x045+x00d-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x045+x00d+x027-x002... FAIL (3 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x045-x00d-x027-x002... FAIL (86 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x045-x00d-x027-x002... ok (44 matches)\nbisect: run: test +1-x045-x00d-x027-x002... ok (42 matches)\nbisect: run: test +0+1-x045-x00d-x027-x002... FAIL (44 matches)\nbisect: run: test +00+1-x045-x00d-x027-x002... FAIL (23 matches)\nbisect: run: test +000+1-x045-x00d-x027-x002... ok (12 matches)\nbisect: run: test +100+1-x045-x00d-x027-x002... ok (11 matches)\nbisect: run: test +000+1+100-x045-x00d-x027-x002... FAIL (12 matches)\nbisect: run: test +0000+1+100-x045-x00d-x027-x002... FAIL (6 matches)\nbisect: run: test +00000+1+100-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +000000+1+100-x045-x00d-x027-x002... ok (2 matches)\nbisect: run: test +100000+1+100-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +100+1+x020-x045-x00d-x027-x002... FAIL (11 matches)\nbisect: run: test +0100+1+x020-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +1100+1+x020-x045-x00d-x027-x002... FAIL (5 matches)\nbisect: run: test +01100+1+x020-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +001100+1+x020-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: run: test +0001100+1+x020-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +1+x020+x00c-x045-x00d-x027-x002... FAIL (42 matches)\nbisect: run: test +01+x020+x00c-x045-x00d-x027-x002... FAIL (21 matches)\nbisect: run: test +001+x020+x00c-x045-x00d-x027-x002... FAIL (12 matches)\nbisect: run: test +0001+x020+x00c-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +1001+x020+x00c-x045-x00d-x027-x002... ok (6 matches)\n"
  },
  {
    "path": "cmd/bisect/testdata/maxset1.txt",
    "content": "{\"Fail\": \"apricot && peach\", \"Bisect\": {\"MaxSet\": 1}}\n-- stdout --\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... ok (45 matches)\nbisect: run: test +1... ok (45 matches)\nbisect: fatal error: cannot find any failing change sets of size ≤ 1\n<bisect failed>\n"
  },
  {
    "path": "cmd/bisect/testdata/maxset4.txt",
    "content": "{\"Fail\": \"amber || apricot && peach || red && green && blue || cyan && magenta && yellow && black\", \"Bisect\": {\"MaxSet\": 4}}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\nblue\ngreen\nred\n---\n--- change set #3 (enabling changes causes failure)\nblack\ncyan\nmagenta\nyellow\n---\n--- change set #4 (enabling changes causes failure)\napricot\npeach\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... ok (44 matches)\nbisect: run: test +1-x002... FAIL (45 matches)\nbisect: run: test +01-x002... ok (23 matches)\nbisect: run: test +11-x002... ok (22 matches)\nbisect: run: test +01+11-x002... FAIL (23 matches)\nbisect: run: test +001+11-x002... ok (12 matches)\nbisect: run: test +101+11-x002... FAIL (11 matches)\nbisect: run: test +0101+11-x002... ok (6 matches)\nbisect: run: test +1101+11-x002... ok (5 matches)\nbisect: run: test +0101+11+1101-x002... FAIL (6 matches)\nbisect: run: test +00101+11+1101-x002... FAIL (3 matches)\nbisect: run: test +000101+11+1101-x002... FAIL (2 matches)\nbisect: run: test +0000101+11+1101-x002... ok (1 matches)\nbisect: run: test +1000101+11+1101-x002... FAIL (1 matches)\nbisect: run: test +1101+11+x045-x002... FAIL (5 matches)\nbisect: run: test +01101+11+x045-x002... FAIL (3 matches)\nbisect: run: test +001101+11+x045-x002... FAIL (2 matches)\nbisect: run: test +0001101+11+x045-x002... FAIL (1 matches)\nbisect: run: test +11+x045+x00d-x002... FAIL (22 matches)\nbisect: run: test +011+x045+x00d-x002... ok (11 matches)\nbisect: run: test +111+x045+x00d-x002... FAIL (11 matches)\nbisect: run: test +0111+x045+x00d-x002... FAIL (6 matches)\nbisect: run: test +00111+x045+x00d-x002... FAIL (3 matches)\nbisect: run: test +000111+x045+x00d-x002... ok (2 matches)\nbisect: run: test +100111+x045+x00d-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x045+x00d+x027-x002... FAIL (3 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x045-x00d-x027-x002... FAIL (86 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x045-x00d-x027-x002... ok (44 matches)\nbisect: run: test +1-x045-x00d-x027-x002... ok (42 matches)\nbisect: run: test +0+1-x045-x00d-x027-x002... FAIL (44 matches)\nbisect: run: test +00+1-x045-x00d-x027-x002... FAIL (23 matches)\nbisect: run: test +000+1-x045-x00d-x027-x002... ok (12 matches)\nbisect: run: test +100+1-x045-x00d-x027-x002... ok (11 matches)\nbisect: run: test +000+1+100-x045-x00d-x027-x002... FAIL (12 matches)\nbisect: run: test +0000+1+100-x045-x00d-x027-x002... FAIL (6 matches)\nbisect: run: test +00000+1+100-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +000000+1+100-x045-x00d-x027-x002... ok (2 matches)\nbisect: run: test +100000+1+100-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +100+1+x020-x045-x00d-x027-x002... FAIL (11 matches)\nbisect: run: test +0100+1+x020-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +1100+1+x020-x045-x00d-x027-x002... FAIL (5 matches)\nbisect: run: test +01100+1+x020-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +001100+1+x020-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: run: test +0001100+1+x020-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +1+x020+x00c-x045-x00d-x027-x002... FAIL (42 matches)\nbisect: run: test +01+x020+x00c-x045-x00d-x027-x002... FAIL (21 matches)\nbisect: run: test +001+x020+x00c-x045-x00d-x027-x002... FAIL (12 matches)\nbisect: run: test +0001+x020+x00c-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +1001+x020+x00c-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +0001+x020+x00c+1001-x045-x00d-x027-x002... FAIL (6 matches)\nbisect: run: test +00001+x020+x00c+1001-x045-x00d-x027-x002... ok (3 matches)\nbisect: run: test +10001+x020+x00c+1001-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +010001+x020+x00c+1001-x045-x00d-x027-x002... ok (2 matches)\nbisect: run: test +110001+x020+x00c+1001-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +1001+x020+x00c+x031-x045-x00d-x027-x002... FAIL (6 matches)\nbisect: run: test +01001+x020+x00c+x031-x045-x00d-x027-x002... ok (3 matches)\nbisect: run: test +11001+x020+x00c+x031-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +011001+x020+x00c+x031-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: run: test +0011001+x020+x00c+x031-x045-x00d-x027-x002... ok (1 matches)\nbisect: run: test +1011001+x020+x00c+x031-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x020+x00c+x031+x059-x045-x00d-x027-x002... FAIL (4 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (82 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (42 matches)\nbisect: run: test +1-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (40 matches)\nbisect: run: test +0+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (42 matches)\nbisect: run: test +00+1-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (21 matches)\nbisect: run: test +10+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (21 matches)\nbisect: run: test +010+1-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (10 matches)\nbisect: run: test +110+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (11 matches)\nbisect: run: test +0110+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (6 matches)\nbisect: run: test +00110+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (3 matches)\nbisect: run: test +000110+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: run: test +0000110+1-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: run: test +1+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (40 matches)\nbisect: run: test +01+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (19 matches)\nbisect: run: test +11+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (21 matches)\nbisect: run: test +011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (11 matches)\nbisect: run: test +0011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (6 matches)\nbisect: run: test +1011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (5 matches)\nbisect: run: test +01011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (3 matches)\nbisect: run: test +11011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: run: test +011011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (1 matches)\nbisect: run: test +111011+x006-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x006+x03b-x020-x00c-x031-x059-x045-x00d-x027-x002... FAIL (2 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x006-x03b-x020-x00c-x031-x059-x045-x00d-x027-x002... ok (80 matches)\nbisect: target succeeds with all remaining changes enabled\n"
  },
  {
    "path": "cmd/bisect/testdata/negate.txt",
    "content": "{\"Fail\": \"!amber || !apricot && !peach\"}\n-- stdout --\n--- change set #1 (disabling changes causes failure)\namber\n---\n--- change set #2 (disabling changes causes failure)\napricot\npeach\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... FAIL (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... ok (90 matches)\nbisect: target fails with no changes, succeeds with all changes\nbisect: searching for minimal set of disabled changes causing failure\nbisect: run: test !+0... FAIL (45 matches)\nbisect: run: test !+00... ok (23 matches)\nbisect: run: test !+10... FAIL (22 matches)\nbisect: run: test !+010... FAIL (11 matches)\nbisect: run: test !+0010... FAIL (6 matches)\nbisect: run: test !+00010... FAIL (3 matches)\nbisect: run: test !+000010... FAIL (2 matches)\nbisect: run: test !+0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v!+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test !-x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test !+0-x002... ok (44 matches)\nbisect: run: test !+1-x002... ok (45 matches)\nbisect: run: test !+0+1-x002... FAIL (44 matches)\nbisect: run: test !+00+1-x002... ok (23 matches)\nbisect: run: test !+10+1-x002... FAIL (21 matches)\nbisect: run: test !+010+1-x002... ok (10 matches)\nbisect: run: test !+110+1-x002... FAIL (11 matches)\nbisect: run: test !+0110+1-x002... FAIL (6 matches)\nbisect: run: test !+00110+1-x002... FAIL (3 matches)\nbisect: run: test !+000110+1-x002... FAIL (2 matches)\nbisect: run: test !+0000110+1-x002... FAIL (1 matches)\nbisect: run: test !+1+x006-x002... FAIL (45 matches)\nbisect: run: test !+01+x006-x002... ok (23 matches)\nbisect: run: test !+11+x006-x002... FAIL (22 matches)\nbisect: run: test !+011+x006-x002... FAIL (11 matches)\nbisect: run: test !+0011+x006-x002... ok (6 matches)\nbisect: run: test !+1011+x006-x002... FAIL (5 matches)\nbisect: run: test !+01011+x006-x002... ok (3 matches)\nbisect: run: test !+11011+x006-x002... FAIL (2 matches)\nbisect: run: test !+011011+x006-x002... ok (1 matches)\nbisect: run: test !+111011+x006-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v!+x006+x03b-x002... FAIL (2 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test !-x006-x03b-x002... ok (87 matches)\nbisect: target succeeds with all remaining changes disabled\n"
  },
  {
    "path": "cmd/bisect/testdata/rand.txt",
    "content": "{\"Fail\": \"amber || apricot || blue && random\"}\n-- stdout --\n--- change set #1 (enabling changes causes failure)\namber\n---\n--- change set #2 (enabling changes causes failure)\napricot\n---\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... FAIL (45 matches)\nbisect: run: test +00... ok (23 matches)\nbisect: run: test +10... FAIL (22 matches)\nbisect: run: test +010... FAIL (11 matches)\nbisect: run: test +0010... FAIL (6 matches)\nbisect: run: test +00010... FAIL (3 matches)\nbisect: run: test +000010... FAIL (2 matches)\nbisect: run: test +0000010... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x002... FAIL (89 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x002... FAIL (44 matches)\nbisect: run: test +00-x002... ok (23 matches)\nbisect: run: test +10-x002... FAIL (21 matches)\nbisect: run: test +010-x002... ok (10 matches)\nbisect: run: test +110-x002... FAIL (11 matches)\nbisect: run: test +0110-x002... FAIL (6 matches)\nbisect: run: test +00110-x002... FAIL (3 matches)\nbisect: run: test +000110-x002... FAIL (2 matches)\nbisect: run: test +0000110-x002... FAIL (1 matches)\nbisect: confirming failing change set\nbisect: run: test v+x006-x002... FAIL (1 matches)\nbisect: FOUND failing change set\nbisect: checking for more failures\nbisect: run: test -x006-x002... FAIL (88 matches)\nbisect: target still fails; searching for more bad changes\nbisect: run: test +0-x006-x002... ok (43 matches)\nbisect: run: test +1-x006-x002... FAIL (45 matches)\nbisect: run: test +01-x006-x002... FAIL (23 matches)\nbisect: run: test +001-x006-x002... ok (12 matches)\nbisect: run: test +101-x006-x002... FAIL (11 matches)\nbisect: run: test +0101-x006-x002... ok (6 matches)\nbisect: run: test +1101-x006-x002... FAIL (5 matches)\nbisect: run: test +01101-x006-x002... ok (3 matches)\nbisect: run: test +11101-x006-x002... ok (2 matches)\nbisect: run: test +01101+11101-x006-x002... FAIL (3 matches)\nbisect: run: test +001101+11101-x006-x002... ok (2 matches)\nbisect: run: test +101101+11101-x006-x002... ok (1 matches)\nbisect: run: test +001101+11101+101101-x006-x002... ok (2 matches)\nbisect: fatal error: target fails inconsistently\n<bisect failed>\n"
  },
  {
    "path": "cmd/bisect/testdata/rand1.txt",
    "content": "{\"Fail\": \"blue && random\"}\n-- stdout --\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... ok (45 matches)\nbisect: run: test +1... FAIL (45 matches)\nbisect: run: test +01... FAIL (23 matches)\nbisect: run: test +001... ok (12 matches)\nbisect: run: test +101... FAIL (11 matches)\nbisect: run: test +0101... ok (6 matches)\nbisect: run: test +1101... FAIL (5 matches)\nbisect: run: test +01101... ok (3 matches)\nbisect: run: test +11101... ok (2 matches)\nbisect: run: test +01101+11101... FAIL (3 matches)\nbisect: run: test +001101+11101... ok (2 matches)\nbisect: run: test +101101+11101... ok (1 matches)\nbisect: run: test +001101+11101+101101... ok (2 matches)\nbisect: fatal error: target fails inconsistently\n<bisect failed>\n"
  },
  {
    "path": "cmd/bisect/testdata/rand2.txt",
    "content": "{\"Fail\": \"blue && random\", \"Bisect\": {\"Count\": 2}}\n-- stdout --\n-- stderr --\nbisect: checking target with all changes disabled\nbisect: run: test n... ok (90 matches)\nbisect: run: test n... ok (90 matches)\nbisect: checking target with all changes enabled\nbisect: run: test y... FAIL (90 matches)\nbisect: run: test y... FAIL (90 matches)\nbisect: target succeeds with no changes, fails with all changes\nbisect: searching for minimal set of enabled changes causing failure\nbisect: run: test +0... ok (45 matches)\nbisect: run: test +0... ok (45 matches)\nbisect: run: test +1... FAIL (45 matches)\nbisect: run: test +1... FAIL (45 matches)\nbisect: run: test +01... FAIL (23 matches)\nbisect: run: test +01... ok (23 matches)\nbisect: fatal error: target fails inconsistently\n<bisect failed>\n"
  },
  {
    "path": "cmd/bundle/.gitignore",
    "content": "testdata/out.got\n"
  },
  {
    "path": "cmd/bundle/main.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Bundle creates a single-source-file version of a source package\n// suitable for inclusion in a particular target package.\n//\n// Usage:\n//\n//\tbundle [-o file] [-dst path] [-pkg name] [-prefix p] [-import old=new] [-tags build_constraints] <src>\n//\n// The src argument specifies the import path of the package to bundle.\n// The bundling of a directory of source files into a single source file\n// necessarily imposes a number of constraints.\n// The package being bundled must not use cgo; must not use conditional\n// file compilation, whether with build tags or system-specific file names\n// like code_amd64.go; must not depend on any special comments, which\n// may not be preserved; must not use any assembly sources;\n// must not use renaming imports; and must not use reflection-based APIs\n// that depend on the specific names of types or struct fields.\n//\n// By default, bundle writes the bundled code to standard output.\n// If the -o argument is given, bundle writes to the named file\n// and also includes a “//go:generate” comment giving the exact\n// command line used, for regenerating the file with “go generate.”\n//\n// Bundle customizes its output for inclusion in a particular package, the destination package.\n// By default bundle assumes the destination is the package in the current directory,\n// but the destination package can be specified explicitly using the -dst option,\n// which takes an import path as its argument.\n// If the source package imports the destination package, bundle will remove\n// those imports and rewrite any references to use direct references to the\n// corresponding symbols.\n// Bundle also must write a package declaration in the output and must\n// choose a name to use in that declaration.\n// If the -pkg option is given, bundle uses that name.\n// Otherwise, the name of the destination package is used.\n// Build constraints for the generated file can be specified using the -tags option.\n//\n// To avoid collisions, bundle inserts a prefix at the beginning of\n// every package-level const, func, type, and var identifier in src's code,\n// updating references accordingly. The default prefix is the package name\n// of the source package followed by an underscore. The -prefix option\n// specifies an alternate prefix.\n//\n// Occasionally it is necessary to rewrite imports during the bundling\n// process. The -import option, which may be repeated, specifies that\n// an import of \"old\" should be rewritten to import \"new\" instead.\n//\n// # Example\n//\n// Bundle archive/zip for inclusion in cmd/dist:\n//\n//\tcd $GOROOT/src/cmd/dist\n//\tbundle -o zip.go archive/zip\n//\n// Bundle golang.org/x/net/http2 for inclusion in net/http,\n// prefixing all identifiers by \"http2\" instead of \"http2_\", and\n// including a \"!nethttpomithttp2\" build constraint:\n//\n//\tcd $GOROOT/src/net/http\n//\tbundle -o h2_bundle.go -prefix http2 -tags '!nethttpomithttp2' golang.org/x/net/http2\n//\n// Update the http2 bundle in net/http:\n//\n//\tgo generate net/http\n//\n// Update all bundles in the standard library:\n//\n//\tgo generate -run bundle std\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\nvar (\n\toutputFile = flag.String(\"o\", \"\", \"write output to `file` (default standard output)\")\n\tdstPath    = flag.String(\"dst\", \".\", \"set destination import `path`\")\n\tpkgName    = flag.String(\"pkg\", \"\", \"set destination package `name`\")\n\tprefix     = flag.String(\"prefix\", \"&_\", \"set bundled identifier prefix to `p` (default is \\\"&_\\\", where & stands for the original name)\")\n\tbuildTags  = flag.String(\"tags\", \"\", \"the build constraints to be inserted into the generated file\")\n\n\timportMap = map[string]string{}\n)\n\nfunc init() {\n\tflag.Var(flagFunc(addImportMap), \"import\", \"rewrite import using `map`, of form old=new (can be repeated)\")\n}\n\nfunc addImportMap(s string) {\n\tif strings.Count(s, \"=\") != 1 {\n\t\tlog.Fatal(\"-import argument must be of the form old=new\")\n\t}\n\ti := strings.Index(s, \"=\")\n\told, new := s[:i], s[i+1:]\n\tif old == \"\" || new == \"\" {\n\t\tlog.Fatal(\"-import argument must be of the form old=new; old and new must be non-empty\")\n\t}\n\timportMap[old] = new\n}\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"Usage: bundle [options] <src>\\n\")\n\tflag.PrintDefaults()\n}\n\nfunc main() {\n\tlog.SetPrefix(\"bundle: \")\n\tlog.SetFlags(0)\n\n\tflag.Usage = usage\n\tflag.Parse()\n\targs := flag.Args()\n\tif len(args) != 1 {\n\t\tusage()\n\t\tos.Exit(2)\n\t}\n\n\tcfg := &packages.Config{Mode: packages.NeedName}\n\tpkgs, err := packages.Load(cfg, *dstPath)\n\tif err != nil {\n\t\tlog.Fatalf(\"cannot load destination package: %v\", err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {\n\t\tlog.Fatalf(\"failed to load destination package\")\n\t}\n\tif *pkgName == \"\" {\n\t\t*pkgName = pkgs[0].Name\n\t}\n\n\tcode, err := bundle(args[0], pkgs[0].PkgPath, *pkgName, *prefix, *buildTags)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif *outputFile != \"\" {\n\t\terr := os.WriteFile(*outputFile, code, 0666)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t} else {\n\t\t_, err := os.Stdout.Write(code)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n\n// isStandardImportPath is copied from cmd/go in the standard library.\nfunc isStandardImportPath(path string) bool {\n\ti := strings.Index(path, \"/\")\n\tif i < 0 {\n\t\ti = len(path)\n\t}\n\telem := path[:i]\n\treturn !strings.Contains(elem, \".\")\n}\n\nvar testingOnlyPackagesConfig *packages.Config\n\nfunc bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {\n\t// Load the initial package.\n\tcfg := &packages.Config{}\n\tif testingOnlyPackagesConfig != nil {\n\t\t*cfg = *testingOnlyPackagesConfig\n\t} else {\n\t\t// Bypass default vendor mode, as we need a package not available in the\n\t\t// std module vendor folder.\n\t\tcfg.Env = append(os.Environ(), \"GOFLAGS=-mod=mod\")\n\t}\n\tcfg.Mode = packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo\n\tpkgs, err := packages.Load(cfg, src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {\n\t\treturn nil, fmt.Errorf(\"failed to load source package\")\n\t}\n\tpkg := pkgs[0]\n\n\tif strings.Contains(prefix, \"&\") {\n\t\tprefix = strings.Replace(prefix, \"&\", pkg.Syntax[0].Name.Name, -1)\n\t}\n\n\tobjsToUpdate := make(map[types.Object]bool)\n\tvar rename func(from types.Object)\n\trename = func(from types.Object) {\n\t\tif !objsToUpdate[from] {\n\t\t\tobjsToUpdate[from] = true\n\n\t\t\t// Renaming a type that is used as an embedded field\n\t\t\t// requires renaming the field too. e.g.\n\t\t\t// \ttype T int // if we rename this to U..\n\t\t\t// \tvar s struct {T}\n\t\t\t// \tprint(s.T) // ...this must change too\n\t\t\tif _, ok := from.(*types.TypeName); ok {\n\t\t\t\tfor id, obj := range pkg.TypesInfo.Uses {\n\t\t\t\t\tif obj == from {\n\t\t\t\t\t\tif field := pkg.TypesInfo.Defs[id]; field != nil {\n\t\t\t\t\t\t\trename(field)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Rename each package-level object.\n\tscope := pkg.Types.Scope()\n\tfor _, name := range scope.Names() {\n\t\trename(scope.Lookup(name))\n\t}\n\n\tvar out bytes.Buffer\n\tif buildTags != \"\" {\n\t\tfmt.Fprintf(&out, \"//go:build %s\\n\", buildTags)\n\t}\n\n\tfmt.Fprintf(&out, \"// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.\\n\")\n\tif *outputFile != \"\" && buildTags == \"\" {\n\t\tfmt.Fprintf(&out, \"//go:generate bundle %s\\n\", strings.Join(quoteArgs(os.Args[1:]), \" \"))\n\t} else {\n\t\tfmt.Fprintf(&out, \"//   $ bundle %s\\n\", strings.Join(os.Args[1:], \" \"))\n\t}\n\tfmt.Fprintf(&out, \"\\n\")\n\n\t// Concatenate package comments from all files...\n\tfor _, f := range pkg.Syntax {\n\t\tif doc := f.Doc.Text(); strings.TrimSpace(doc) != \"\" {\n\t\t\tfor line := range strings.SplitSeq(doc, \"\\n\") {\n\t\t\t\tfmt.Fprintf(&out, \"// %s\\n\", line)\n\t\t\t}\n\t\t}\n\t}\n\t// ...but don't let them become the actual package comment.\n\tfmt.Fprintln(&out)\n\n\tfmt.Fprintf(&out, \"package %s\\n\\n\", dstpkg)\n\n\t// BUG(adonovan,shurcooL): bundle may generate incorrect code\n\t// due to shadowing between identifiers and imported package names.\n\t//\n\t// The generated code will either fail to compile or\n\t// (unlikely) compile successfully but have different behavior\n\t// than the original package. The risk of this happening is higher\n\t// when the original package has renamed imports (they're typically\n\t// renamed in order to resolve a shadow inside that particular .go file).\n\n\t// TODO(adonovan,shurcooL):\n\t// - detect shadowing issues, and either return error or resolve them\n\t// - preserve comments from the original import declarations.\n\n\t// pkgStd and pkgExt are sets of printed import specs. This is done\n\t// to deduplicate instances of the same import name and path.\n\tvar pkgStd = make(map[string]bool)\n\tvar pkgExt = make(map[string]bool)\n\tfor _, f := range pkg.Syntax {\n\t\tfor _, imp := range f.Imports {\n\t\t\tpath, err := strconv.Unquote(imp.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"invalid import path string: %v\", err) // Shouldn't happen here since packages.Load succeeded.\n\t\t\t}\n\t\t\tif path == dst {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif newPath, ok := importMap[path]; ok {\n\t\t\t\tpath = newPath\n\t\t\t}\n\n\t\t\tvar name string\n\t\t\tif imp.Name != nil {\n\t\t\t\tname = imp.Name.Name\n\t\t\t}\n\t\t\tspec := fmt.Sprintf(\"%s %q\", name, path)\n\t\t\tif isStandardImportPath(path) {\n\t\t\t\tpkgStd[spec] = true\n\t\t\t} else {\n\t\t\t\tpkgExt[spec] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Print a single declaration that imports all necessary packages.\n\tfmt.Fprintln(&out, \"import (\")\n\tfor p := range pkgStd {\n\t\tfmt.Fprintf(&out, \"\\t%s\\n\", p)\n\t}\n\tif len(pkgExt) > 0 {\n\t\tfmt.Fprintln(&out)\n\t}\n\tfor p := range pkgExt {\n\t\tfmt.Fprintf(&out, \"\\t%s\\n\", p)\n\t}\n\tfmt.Fprint(&out, \")\\n\\n\")\n\n\t// Modify and print each file.\n\tfor _, f := range pkg.Syntax {\n\t\t// Update renamed identifiers.\n\t\tfor id, obj := range pkg.TypesInfo.Defs {\n\t\t\tif objsToUpdate[obj] {\n\t\t\t\tid.Name = prefix + obj.Name()\n\t\t\t}\n\t\t}\n\t\tfor id, obj := range pkg.TypesInfo.Uses {\n\t\t\tif objsToUpdate[obj] {\n\t\t\t\tid.Name = prefix + obj.Name()\n\t\t\t}\n\t\t}\n\n\t\t// For each qualified identifier that refers to the\n\t\t// destination package, remove the qualifier.\n\t\t// The \"@@@.\" strings are removed in postprocessing.\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif sel, ok := n.(*ast.SelectorExpr); ok {\n\t\t\t\tif id, ok := sel.X.(*ast.Ident); ok {\n\t\t\t\t\tif obj, ok := pkg.TypesInfo.Uses[id].(*types.PkgName); ok {\n\t\t\t\t\t\tif obj.Imported().Path() == dst {\n\t\t\t\t\t\t\tid.Name = \"@@@\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\n\t\tlast := f.Package\n\t\tif len(f.Imports) > 0 {\n\t\t\timp := f.Imports[len(f.Imports)-1]\n\t\t\tlast = imp.End()\n\t\t\tif imp.Comment != nil {\n\t\t\t\tif e := imp.Comment.End(); e > last {\n\t\t\t\t\tlast = e\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Pretty-print package-level declarations.\n\t\t// but no package or import declarations.\n\t\tvar buf bytes.Buffer\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tbeg, end := sourceRange(decl)\n\n\t\t\tprintComments(&out, f.Comments, last, beg)\n\n\t\t\tbuf.Reset()\n\t\t\tformat.Node(&buf, pkg.Fset, &printer.CommentedNode{Node: decl, Comments: f.Comments})\n\t\t\t// Remove each \"@@@.\" in the output.\n\t\t\t// TODO(adonovan): not hygienic.\n\t\t\tout.Write(bytes.Replace(buf.Bytes(), []byte(\"@@@.\"), nil, -1))\n\n\t\t\tlast = printSameLineComment(&out, f.Comments, pkg.Fset, end)\n\n\t\t\tout.WriteString(\"\\n\\n\")\n\t\t}\n\n\t\tprintLastComments(&out, f.Comments, last)\n\t}\n\n\t// Now format the entire thing.\n\tresult, err := format.Source(out.Bytes())\n\tif err != nil {\n\t\tlog.Fatalf(\"formatting failed: %v\", err)\n\t}\n\n\treturn result, nil\n}\n\n// sourceRange returns the [beg, end) interval of source code\n// belonging to decl (incl. associated comments).\nfunc sourceRange(decl ast.Decl) (beg, end token.Pos) {\n\tbeg = decl.Pos()\n\tend = decl.End()\n\n\tvar doc, com *ast.CommentGroup\n\n\tswitch d := decl.(type) {\n\tcase *ast.GenDecl:\n\t\tdoc = d.Doc\n\t\tif len(d.Specs) > 0 {\n\t\t\tswitch spec := d.Specs[len(d.Specs)-1].(type) {\n\t\t\tcase *ast.ValueSpec:\n\t\t\t\tcom = spec.Comment\n\t\t\tcase *ast.TypeSpec:\n\t\t\t\tcom = spec.Comment\n\t\t\t}\n\t\t}\n\tcase *ast.FuncDecl:\n\t\tdoc = d.Doc\n\t}\n\n\tif doc != nil {\n\t\tbeg = doc.Pos()\n\t}\n\tif com != nil && com.End() > end {\n\t\tend = com.End()\n\t}\n\n\treturn beg, end\n}\n\nfunc printComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos, end token.Pos) {\n\tfor _, cg := range comments {\n\t\tif pos <= cg.Pos() && cg.Pos() < end {\n\t\t\tfor _, c := range cg.List {\n\t\t\t\tfmt.Fprintln(out, c.Text)\n\t\t\t}\n\t\t\tfmt.Fprintln(out)\n\t\t}\n\t}\n}\n\nconst infinity = 1 << 30\n\nfunc printLastComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos token.Pos) {\n\tprintComments(out, comments, pos, infinity)\n}\n\nfunc printSameLineComment(out *bytes.Buffer, comments []*ast.CommentGroup, fset *token.FileSet, pos token.Pos) token.Pos {\n\ttf := fset.File(pos)\n\tfor _, cg := range comments {\n\t\tif pos <= cg.Pos() && tf.Line(cg.Pos()) == tf.Line(pos) {\n\t\t\tfor _, c := range cg.List {\n\t\t\t\tfmt.Fprintln(out, c.Text)\n\t\t\t}\n\t\t\treturn cg.End()\n\t\t}\n\t}\n\treturn pos\n}\n\nfunc quoteArgs(ss []string) []string {\n\t// From go help generate:\n\t//\n\t// > The arguments to the directive are space-separated tokens or\n\t// > double-quoted strings passed to the generator as individual\n\t// > arguments when it is run.\n\t//\n\t// > Quoted strings use Go syntax and are evaluated before execution; a\n\t// > quoted string appears as a single argument to the generator.\n\t//\n\tvar qs []string\n\tfor _, s := range ss {\n\t\tif s == \"\" || containsSpace(s) {\n\t\t\ts = strconv.Quote(s)\n\t\t}\n\t\tqs = append(qs, s)\n\t}\n\treturn qs\n}\n\nfunc containsSpace(s string) bool {\n\tfor _, r := range s {\n\t\tif unicode.IsSpace(r) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\ntype flagFunc func(string)\n\nfunc (f flagFunc) Set(s string) error {\n\tf(s)\n\treturn nil\n}\n\nfunc (f flagFunc) String() string { return \"\" }\n"
  },
  {
    "path": "cmd/bundle/main_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestBundle(t *testing.T) { packagestest.TestAll(t, testBundle) }\nfunc testBundle(t *testing.T, x packagestest.Exporter) {\n\tload := func(name string) string {\n\t\tdata, err := os.ReadFile(name)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\treturn string(data)\n\t}\n\n\te := packagestest.Export(t, x, []packagestest.Module{\n\t\t{\n\t\t\tName: \"initial\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"a.go\": load(\"testdata/src/initial/a.go\"),\n\t\t\t\t\"b.go\": load(\"testdata/src/initial/b.go\"),\n\t\t\t\t\"c.go\": load(\"testdata/src/initial/c.go\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"domain.name/importdecl\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"p.go\": load(\"testdata/src/domain.name/importdecl/p.go\"),\n\t\t\t},\n\t\t},\n\t})\n\tdefer e.Cleanup()\n\ttestingOnlyPackagesConfig = e.Config\n\n\tos.Args = os.Args[:1] // avoid e.g. -test=short in the output\n\tout, err := bundle(\"initial\", \"github.com/dest\", \"dest\", \"prefix\", \"tag\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif got, want := string(out), load(\"testdata/out.golden\"); got != want {\n\t\tt.Errorf(\"-- got --\\n%s\\n-- want --\\n%s\\n-- diff --\", got, want)\n\n\t\tif err := os.WriteFile(\"testdata/out.got\", out, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tt.Log(diff(\"testdata/out.golden\", \"testdata/out.got\"))\n\t}\n}\n\nfunc diff(a, b string) string {\n\tvar cmd *exec.Cmd\n\tswitch runtime.GOOS {\n\tcase \"plan9\":\n\t\tcmd = exec.Command(\"/bin/diff\", \"-c\", a, b)\n\tdefault:\n\t\tcmd = exec.Command(\"/usr/bin/diff\", \"-u\", a, b)\n\t}\n\tvar out bytes.Buffer\n\tcmd.Stdout = &out\n\tcmd.Stderr = &out\n\tcmd.Run() // nonzero exit is expected\n\tif out.Len() == 0 {\n\t\treturn \"(failed to compute diff)\"\n\t}\n\treturn out.String()\n}\n"
  },
  {
    "path": "cmd/bundle/testdata/out.golden",
    "content": "//go:build tag\n\n// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.\n//   $ bundle\n\n// The package doc comment\n//\n\npackage dest\n\nimport (\n\t\"fmt\"\n\t. \"fmt\"\n\t_ \"fmt\"\n\trenamedfmt \"fmt\"\n\trenamedfmt2 \"fmt\"\n\n\t\"domain.name/importdecl\"\n)\n\n// init functions are not renamed\nfunc init() { prefixfoo() }\n\n// Type S.\ntype prefixS struct {\n\tprefixt\n\tu int\n} /* multi-line\ncomment\n*/\n\n// non-associated comment\n\n/*\n\tnon-associated comment2\n*/\n\n// Function bar.\nfunc prefixbar(s *prefixS) {\n\tfmt.Println(s.prefixt, s.u) // comment inside function\n}\n\n// file-end comment\n\ntype prefixt int // type1\n\n// const1\nconst prefixc = 1 // const2\n\nfunc prefixfoo() {\n\tfmt.Println(importdecl.F())\n}\n\n// zinit\nconst (\n\tprefixz1 = iota // z1\n\tprefixz2        // z2\n) // zend\n\nfunc prefixbaz() {\n\trenamedfmt.Println()\n\trenamedfmt2.Println()\n\tPrintln()\n}\n"
  },
  {
    "path": "cmd/bundle/testdata/src/domain.name/importdecl/p.go",
    "content": "package importdecl\n\nfunc F() int { return 1 }\n"
  },
  {
    "path": "cmd/bundle/testdata/src/initial/a.go",
    "content": "package initial\n\nimport \"fmt\" // this comment should not be visible\n\n// init functions are not renamed\nfunc init() { foo() }\n\n// Type S.\ntype S struct {\n\tt\n\tu int\n} /* multi-line\ncomment\n*/\n\n// non-associated comment\n\n/*\n\tnon-associated comment2\n*/\n\n// Function bar.\nfunc bar(s *S) {\n\tfmt.Println(s.t, s.u) // comment inside function\n}\n\n// file-end comment\n"
  },
  {
    "path": "cmd/bundle/testdata/src/initial/b.go",
    "content": "// The package doc comment\npackage initial\n\nimport (\n\t\"fmt\"\n\n\t\"domain.name/importdecl\"\n)\n\ntype t int // type1\n\n// const1\nconst c = 1 // const2\n\nfunc foo() {\n\tfmt.Println(importdecl.F())\n}\n\n// zinit\nconst (\n\tz1 = iota // z1\n\tz2        // z2\n) // zend\n"
  },
  {
    "path": "cmd/bundle/testdata/src/initial/c.go",
    "content": "package initial\n\nimport _ \"fmt\"\nimport renamedfmt \"fmt\"\nimport renamedfmt2 \"fmt\"\nimport . \"fmt\"\n\nfunc baz() {\n\trenamedfmt.Println()\n\trenamedfmt2.Println()\n\tPrintln()\n}\n"
  },
  {
    "path": "cmd/callgraph/main.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// callgraph: a tool for reporting the call graph of a Go program.\n// See Usage for details, or run with -help.\npackage main // import \"golang.org/x/tools/cmd/callgraph\"\n\n// TODO(adonovan):\n//\n// Features:\n// - restrict graph to a single package\n// - output\n//   - functions reachable from root (use digraph tool?)\n//   - unreachable functions (use digraph tool?)\n//   - dynamic (runtime) types\n//   - indexed output (numbered nodes)\n//   - JSON output\n//   - additional template fields:\n//     callee file/line/col\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\t\"os\"\n\t\"runtime\"\n\t\"text/template\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/cha\"\n\t\"golang.org/x/tools/go/callgraph/rta\"\n\t\"golang.org/x/tools/go/callgraph/static\"\n\t\"golang.org/x/tools/go/callgraph/vta\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\n// flags\nvar (\n\talgoFlag = flag.String(\"algo\", \"rta\",\n\t\t`Call graph construction algorithm (static, cha, rta, vta)`)\n\n\ttestFlag = flag.Bool(\"test\", false,\n\t\t\"Loads test code (*_test.go) for imported packages\")\n\n\tformatFlag = flag.String(\"format\",\n\t\t\"{{.Caller}}\\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\\t{{.Callee}}\",\n\t\t\"A template expression specifying how to format an edge\")\n\n\ttagsFlag = flag.String(\"tags\", \"\", \"comma-separated list of extra build tags (see: go help buildconstraint)\")\n)\n\nconst Usage = `callgraph: display the call graph of a Go program.\n\nUsage:\n\n  callgraph [-algo=static|cha|rta|vta] [-test] [-format=...] package...\n\nFlags:\n\n-algo      Specifies the call-graph construction algorithm, one of:\n\n            static      static calls only (unsound)\n            cha         Class Hierarchy Analysis\n            rta         Rapid Type Analysis\n            vta         Variable Type Analysis\n\n           The algorithms are ordered by increasing precision in their\n           treatment of dynamic calls (and thus also computational cost).\n           RTA requires a whole program (main or test), and\n           include only functions reachable from main.\n\n-test      Include the package's tests in the analysis.\n\n-format    Specifies the format in which each call graph edge is displayed.\n           One of:\n\n            digraph     output suitable for input to\n                        golang.org/x/tools/cmd/digraph.\n            graphviz    output in AT&T GraphViz (.dot) format.\n\n           All other values are interpreted using text/template syntax.\n           The default value is:\n\n            {{.Caller}}\\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\\t{{.Callee}}\n\n           The structure passed to the template is (effectively):\n\n                   type Edge struct {\n                           Caller      *ssa.Function // calling function\n                           Callee      *ssa.Function // called function\n\n                           // Call site:\n                           Filename    string // containing file\n                           Offset      int    // offset within file of '('\n                           Line        int    // line number\n                           Column      int    // column number of call\n                           Dynamic     string // \"static\" or \"dynamic\"\n                           Description string // e.g. \"static method call\"\n                   }\n\n           Caller and Callee are *ssa.Function values, which print as\n           \"(*sync/atomic.Mutex).Lock\", but other attributes may be\n           derived from them. For example:\n\n           - {{.Caller.Pkg.Pkg.Path}} yields the import path of the\n             enclosing package; and\n\n           - {{(.Caller.Prog.Fset.Position .Caller.Pos).Filename}}\n             yields the name of the file that declares the caller.\n\n           - The 'posn' template function returns the token.Position\n             of an ssa.Function, so the previous example can be\n             reduced to {{(posn .Caller).Filename}}.\n\n           Consult the documentation for go/token, text/template, and\n           golang.org/x/tools/go/ssa for more detail.\n\nExamples:\n\n  Show the call graph of the trivial web server application:\n\n    callgraph -format digraph $GOROOT/src/net/http/triv.go\n\n  Same, but show only the packages of each function:\n\n    callgraph -format '{{.Caller.Pkg.Pkg.Path}} -> {{.Callee.Pkg.Pkg.Path}}' \\\n      $GOROOT/src/net/http/triv.go | sort | uniq\n\n  Show functions that make dynamic calls into the 'fmt' test package,\n  using the Rapid Type Analysis algorithm:\n\n    callgraph -format='{{.Caller}} -{{.Dynamic}}-> {{.Callee}}' -test -algo=rta fmt |\n      sed -ne 's/-dynamic-/--/p' |\n      sed -ne 's/-->.*fmt_test.*$//p' | sort | uniq\n\n  Show all functions directly called by the callgraph tool's main function:\n\n    callgraph -format=digraph golang.org/x/tools/cmd/callgraph |\n      digraph succs golang.org/x/tools/cmd/callgraph.main\n`\n\nfunc init() {\n\t// If $GOMAXPROCS isn't set, use the full capacity of the machine.\n\t// For small machines, use at least 4 threads.\n\tif os.Getenv(\"GOMAXPROCS\") == \"\" {\n\t\tn := max(runtime.NumCPU(), 4)\n\t\truntime.GOMAXPROCS(n)\n\t}\n}\n\nfunc main() {\n\tflag.Parse()\n\tif err := doCallgraph(\"\", \"\", *algoFlag, *formatFlag, *testFlag, flag.Args()); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"callgraph: %s\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\nvar stdout io.Writer = os.Stdout\n\nfunc doCallgraph(dir, gopath, algo, format string, tests bool, args []string) error {\n\tif len(args) == 0 {\n\t\tfmt.Fprint(os.Stderr, Usage)\n\t\treturn nil\n\t}\n\n\tcfg := &packages.Config{\n\t\tMode:       packages.LoadAllSyntax,\n\t\tBuildFlags: []string{\"-tags=\" + *tagsFlag},\n\t\tTests:      tests,\n\t\tDir:        dir,\n\t}\n\tif gopath != \"\" {\n\t\tcfg.Env = append(os.Environ(), \"GOPATH=\"+gopath) // to enable testing\n\t}\n\tinitial, err := packages.Load(cfg, args...)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif packages.PrintErrors(initial) > 0 {\n\t\treturn fmt.Errorf(\"packages contain errors\")\n\t}\n\n\t// Create and build SSA-form program representation.\n\tmode := ssa.InstantiateGenerics // instantiate generics by default for soundness\n\tprog, pkgs := ssautil.AllPackages(initial, mode)\n\tprog.Build()\n\n\t// -- call graph construction ------------------------------------------\n\n\tvar cg *callgraph.Graph\n\n\tswitch algo {\n\tcase \"static\":\n\t\tcg = static.CallGraph(prog)\n\n\tcase \"cha\":\n\t\tcg = cha.CallGraph(prog)\n\n\tcase \"pta\":\n\t\treturn fmt.Errorf(\"pointer analysis is no longer supported (see Go issue #59676)\")\n\n\tcase \"rta\":\n\t\tmains, err := mainPackages(pkgs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar roots []*ssa.Function\n\t\tfor _, main := range mains {\n\t\t\troots = append(roots, main.Func(\"init\"), main.Func(\"main\"))\n\t\t}\n\t\trtares := rta.Analyze(roots, true)\n\t\tcg = rtares.CallGraph\n\n\t\t// NB: RTA gives us Reachable and RuntimeTypes too.\n\n\tcase \"vta\":\n\t\tcg = vta.CallGraph(ssautil.AllFunctions(prog), nil)\n\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown algorithm: %s\", algo)\n\t}\n\n\tcg.DeleteSyntheticNodes()\n\n\t// -- output------------------------------------------------------------\n\n\tvar before, after string\n\n\t// Pre-canned formats.\n\tswitch format {\n\tcase \"digraph\":\n\t\tformat = `{{printf \"%q %q\" .Caller .Callee}}`\n\n\tcase \"graphviz\":\n\t\tbefore = \"digraph callgraph {\\n\"\n\t\tafter = \"}\\n\"\n\t\tformat = `  {{printf \"%q\" .Caller}} -> {{printf \"%q\" .Callee}}`\n\t}\n\n\tfuncMap := template.FuncMap{\n\t\t\"posn\": func(f *ssa.Function) token.Position {\n\t\t\treturn f.Prog.Fset.Position(f.Pos())\n\t\t},\n\t}\n\ttmpl, err := template.New(\"-format\").Funcs(funcMap).Parse(format)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid -format template: %v\", err)\n\t}\n\n\t// Allocate these once, outside the traversal.\n\tvar buf bytes.Buffer\n\tdata := Edge{fset: prog.Fset}\n\n\tfmt.Fprint(stdout, before)\n\tif err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {\n\t\tdata.position.Offset = -1\n\t\tdata.edge = edge\n\t\tdata.Caller = edge.Caller.Func\n\t\tdata.Callee = edge.Callee.Func\n\n\t\tbuf.Reset()\n\t\tif err := tmpl.Execute(&buf, &data); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstdout.Write(buf.Bytes())\n\t\tif len := buf.Len(); len == 0 || buf.Bytes()[len-1] != '\\n' {\n\t\t\tfmt.Fprintln(stdout)\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn err\n\t}\n\tfmt.Fprint(stdout, after)\n\treturn nil\n}\n\n// mainPackages returns the main packages to analyze.\n// Each resulting package is named \"main\" and has a main function.\nfunc mainPackages(pkgs []*ssa.Package) ([]*ssa.Package, error) {\n\tvar mains []*ssa.Package\n\tfor _, p := range pkgs {\n\t\tif p != nil && p.Pkg.Name() == \"main\" && p.Func(\"main\") != nil {\n\t\t\tmains = append(mains, p)\n\t\t}\n\t}\n\tif len(mains) == 0 {\n\t\treturn nil, fmt.Errorf(\"no main packages\")\n\t}\n\treturn mains, nil\n}\n\ntype Edge struct {\n\tCaller *ssa.Function\n\tCallee *ssa.Function\n\n\tedge     *callgraph.Edge\n\tfset     *token.FileSet\n\tposition token.Position // initialized lazily\n}\n\nfunc (e *Edge) pos() *token.Position {\n\tif e.position.Offset == -1 {\n\t\te.position = e.fset.Position(e.edge.Pos()) // called lazily\n\t}\n\treturn &e.position\n}\n\nfunc (e *Edge) Filename() string { return e.pos().Filename }\nfunc (e *Edge) Column() int      { return e.pos().Column }\nfunc (e *Edge) Line() int        { return e.pos().Line }\nfunc (e *Edge) Offset() int      { return e.pos().Offset }\n\nfunc (e *Edge) Dynamic() string {\n\tif e.edge.Site != nil && e.edge.Site.Common().StaticCallee() == nil {\n\t\treturn \"dynamic\"\n\t}\n\treturn \"static\"\n}\n\nfunc (e *Edge) Description() string { return e.edge.Description() }\n"
  },
  {
    "path": "cmd/callgraph/main_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android && go1.11\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc init() {\n\t// This test currently requires GOPATH mode.\n\t// Explicitly disabling module mode should suffix, but\n\t// we'll also turn off GOPROXY just for good measure.\n\tif err := os.Setenv(\"GO111MODULE\", \"off\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.Setenv(\"GOPROXY\", \"off\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc TestCallgraph(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tgopath, err := filepath.Abs(\"testdata\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\talgo  string\n\t\ttests bool\n\t\twant  []string\n\t}{\n\t\t{\"rta\", false, []string{\n\t\t\t// rta imprecisely shows cross product of {main,main2} x {C,D}\n\t\t\t`pkg.main --> (pkg.C).f`,\n\t\t\t`pkg.main --> (pkg.D).f`,\n\t\t\t`pkg.main --> pkg.main2`,\n\t\t\t`pkg.main2 --> (pkg.C).f`,\n\t\t\t`pkg.main2 --> (pkg.D).f`,\n\t\t}},\n\t\t{\"vta\", false, []string{\n\t\t\t// vta distinguishes main->C, main2->D.\n\t\t\t\"pkg.main --> (pkg.C).f\",\n\t\t\t\"pkg.main --> pkg.main2\",\n\t\t\t\"pkg.main2 --> (pkg.D).f\",\n\t\t}},\n\t\t// tests: both the package's main and the test's main are called.\n\t\t// The callgraph includes all the guts of the \"testing\" package.\n\t\t{\"rta\", true, []string{\n\t\t\t`pkg.test.main --> testing.MainStart`,\n\t\t\t`testing.runExample --> pkg.Example`,\n\t\t\t`pkg.Example --> (pkg.C).f`,\n\t\t\t`pkg.main --> (pkg.C).f`,\n\t\t}},\n\t\t{\"vta\", true, []string{\n\t\t\t`pkg.test.main --> testing.MainStart`,\n\t\t\t`testing.runExample --> pkg.Example`,\n\t\t\t`pkg.Example --> (pkg.C).f`,\n\t\t\t`pkg.main --> (pkg.C).f`,\n\t\t}},\n\t} {\n\t\tconst format = \"{{.Caller}} --> {{.Callee}}\"\n\t\tstdout = new(bytes.Buffer)\n\t\tif err := doCallgraph(\"testdata/src\", gopath, test.algo, format, test.tests, []string{\"pkg\"}); err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\n\t\tedges := make(map[string]bool)\n\t\tfor _, line := range strings.Split(fmt.Sprint(stdout), \"\\n\") {\n\t\t\tedges[line] = true\n\t\t}\n\t\tok := true\n\t\tfor _, edge := range test.want {\n\t\t\tif !edges[edge] {\n\t\t\t\tok = false\n\t\t\t\tt.Errorf(\"callgraph(%q, %t): missing edge: %s\",\n\t\t\t\t\ttest.algo, test.tests, edge)\n\t\t\t}\n\t\t}\n\t\tif !ok {\n\t\t\tt.Log(\"got:\\n\", stdout)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/callgraph/testdata/src/pkg/pkg.go",
    "content": "package main\n\ntype I interface {\n\tf()\n}\n\ntype C int\n\nfunc (C) f() {}\n\ntype D int\n\nfunc (D) f() {}\n\nfunc main() {\n\tvar i I = C(0)\n\ti.f() // dynamic call\n\n\tmain2()\n}\n\nfunc main2() {\n\tvar i I = D(0)\n\ti.f() // dynamic call\n}\n"
  },
  {
    "path": "cmd/callgraph/testdata/src/pkg/pkg_test.go",
    "content": "package main\n\n// An Example function must have an \"Output:\" comment for the go build\n// system to generate a call to it from the test main package.\n\nfunc Example() {\n\tC(0).f()\n\n\t// Output:\n}\n"
  },
  {
    "path": "cmd/compilebench/main.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Compilebench benchmarks the speed of the Go compiler.\n//\n// Usage:\n//\n//\tcompilebench [options]\n//\n// It times the compilation of various packages and prints results in\n// the format used by package testing (and expected by golang.org/x/perf/cmd/benchstat).\n//\n// The options are:\n//\n//\t-alloc\n//\t\tReport allocations.\n//\n//\t-compile exe\n//\t\tUse exe as the path to the cmd/compile binary.\n//\n//\t-compileflags 'list'\n//\t\tPass the space-separated list of flags to the compilation.\n//\n//\t-link exe\n//\t\tUse exe as the path to the cmd/link binary.\n//\n//\t-linkflags 'list'\n//\t\tPass the space-separated list of flags to the linker.\n//\n//\t-count n\n//\t\tRun each benchmark n times (default 1).\n//\n//\t-cpuprofile file\n//\t\tWrite a CPU profile of the compiler to file.\n//\n//\t-go path\n//\t\tPath to \"go\" command (default \"go\").\n//\n//\t-memprofile file\n//\t\tWrite a memory profile of the compiler to file.\n//\n//\t-memprofilerate rate\n//\t\tSet runtime.MemProfileRate during compilation.\n//\n//\t-obj\n//\t\tReport object file statistics.\n//\n//\t-pkg pkg\n//\t\tBenchmark compiling a single package.\n//\n//\t-run regexp\n//\t\tOnly run benchmarks with names matching regexp.\n//\n//\t-short\n//\t\tSkip long-running benchmarks.\n//\n// Although -cpuprofile and -memprofile are intended to write a\n// combined profile for all the executed benchmarks to file,\n// today they write only the profile for the last benchmark executed.\n//\n// The default memory profiling rate is one profile sample per 512 kB\n// allocated (see “go doc runtime.MemProfileRate”).\n// Lowering the rate (for example, -memprofilerate 64000) produces\n// a more fine-grained and therefore accurate profile, but it also incurs\n// execution cost. For benchmark comparisons, never use timings\n// obtained with a low -memprofilerate option.\n//\n// # Example\n//\n// Assuming the base version of the compiler has been saved with\n// “toolstash save,” this sequence compares the old and new compiler:\n//\n//\tcompilebench -count 10 -compile $(toolstash -n compile) >old.txt\n//\tcompilebench -count 10 >new.txt\n//\tbenchstat old.txt new.txt\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar (\n\tgoroot                   string\n\tcompiler                 string\n\tassembler                string\n\tlinker                   string\n\trunRE                    *regexp.Regexp\n\tis6g                     bool\n\tneedCompilingRuntimeFlag bool\n)\n\nvar (\n\tflagGoCmd          = flag.String(\"go\", \"go\", \"path to \\\"go\\\" command\")\n\tflagAlloc          = flag.Bool(\"alloc\", false, \"report allocations\")\n\tflagObj            = flag.Bool(\"obj\", false, \"report object file stats\")\n\tflagCompiler       = flag.String(\"compile\", \"\", \"use `exe` as the cmd/compile binary\")\n\tflagAssembler      = flag.String(\"asm\", \"\", \"use `exe` as the cmd/asm binary\")\n\tflagCompilerFlags  = flag.String(\"compileflags\", \"\", \"additional `flags` to pass to compile\")\n\tflagLinker         = flag.String(\"link\", \"\", \"use `exe` as the cmd/link binary\")\n\tflagLinkerFlags    = flag.String(\"linkflags\", \"\", \"additional `flags` to pass to link\")\n\tflagRun            = flag.String(\"run\", \"\", \"run benchmarks matching `regexp`\")\n\tflagCount          = flag.Int(\"count\", 1, \"run benchmarks `n` times\")\n\tflagCpuprofile     = flag.String(\"cpuprofile\", \"\", \"write CPU profile to `file`\")\n\tflagMemprofile     = flag.String(\"memprofile\", \"\", \"write memory profile to `file`\")\n\tflagMemprofilerate = flag.Int64(\"memprofilerate\", -1, \"set memory profile `rate`\")\n\tflagPackage        = flag.String(\"pkg\", \"\", \"if set, benchmark the package at path `pkg`\")\n\tflagShort          = flag.Bool(\"short\", false, \"skip long-running benchmarks\")\n\tflagTrace          = flag.Bool(\"trace\", false, \"debug tracing of builds\")\n)\n\ntype test struct {\n\tname string\n\tr    runner\n}\n\ntype runner interface {\n\tlong() bool\n\trun(name string, count int) error\n}\n\nvar tests = []test{\n\t{\"BenchmarkTemplate\", compile{\"html/template\"}},\n\t{\"BenchmarkUnicode\", compile{\"unicode\"}},\n\t{\"BenchmarkGoTypes\", compile{\"go/types\"}},\n\t{\"BenchmarkCompiler\", compile{\"cmd/compile/internal/gc\"}},\n\t{\"BenchmarkSSA\", compile{\"cmd/compile/internal/ssa\"}},\n\t{\"BenchmarkFlate\", compile{\"compress/flate\"}},\n\t{\"BenchmarkGoParser\", compile{\"go/parser\"}},\n\t{\"BenchmarkReflect\", compile{\"reflect\"}},\n\t{\"BenchmarkTar\", compile{\"archive/tar\"}},\n\t{\"BenchmarkXML\", compile{\"encoding/xml\"}},\n\t{\"BenchmarkLinkCompiler\", link{\"cmd/compile\", \"\"}},\n\t{\"BenchmarkExternalLinkCompiler\", link{\"cmd/compile\", \"-linkmode=external\"}},\n\t{\"BenchmarkLinkWithoutDebugCompiler\", link{\"cmd/compile\", \"-w\"}},\n\t{\"BenchmarkStdCmd\", goBuild{[]string{\"std\", \"cmd\"}}},\n\t{\"BenchmarkHelloSize\", size{\"$GOROOT/test/helloworld.go\", false}},\n\t{\"BenchmarkCmdGoSize\", size{\"cmd/go\", true}},\n}\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: compilebench [options]\\n\")\n\tfmt.Fprintf(os.Stderr, \"options:\\n\")\n\tflag.PrintDefaults()\n\tos.Exit(2)\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"compilebench: \")\n\tflag.Usage = usage\n\tflag.Parse()\n\tif flag.NArg() != 0 {\n\t\tusage()\n\t}\n\n\ts, err := exec.Command(*flagGoCmd, \"env\", \"GOROOT\").CombinedOutput()\n\tif err != nil {\n\t\tlog.Fatalf(\"%s env GOROOT: %v\", *flagGoCmd, err)\n\t}\n\tgoroot = strings.TrimSpace(string(s))\n\tos.Setenv(\"GOROOT\", goroot) // for any subcommands\n\n\tcompiler = *flagCompiler\n\tif compiler == \"\" {\n\t\tvar foundTool string\n\t\tfoundTool, compiler = toolPath(\"compile\", \"6g\")\n\t\tif foundTool == \"6g\" {\n\t\t\tis6g = true\n\t\t}\n\t}\n\tassembler = *flagAssembler\n\tif assembler == \"\" {\n\t\t_, assembler = toolPath(\"asm\")\n\t}\n\tif err := checkCompilingRuntimeFlag(assembler); err != nil {\n\t\tlog.Fatalf(\"checkCompilingRuntimeFlag: %v\", err)\n\t}\n\n\tlinker = *flagLinker\n\tif linker == \"\" && !is6g { // TODO: Support 6l\n\t\t_, linker = toolPath(\"link\")\n\t}\n\n\tif is6g {\n\t\t*flagMemprofilerate = -1\n\t\t*flagAlloc = false\n\t\t*flagCpuprofile = \"\"\n\t\t*flagMemprofile = \"\"\n\t}\n\n\tif *flagRun != \"\" {\n\t\tr, err := regexp.Compile(*flagRun)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"invalid -run argument: %v\", err)\n\t\t}\n\t\trunRE = r\n\t}\n\n\tif *flagPackage != \"\" {\n\t\ttests = []test{\n\t\t\t{\"BenchmarkPkg\", compile{*flagPackage}},\n\t\t\t{\"BenchmarkPkgLink\", link{*flagPackage, \"\"}},\n\t\t}\n\t\trunRE = nil\n\t}\n\n\tfor i := 0; i < *flagCount; i++ {\n\t\tfor _, tt := range tests {\n\t\t\tif tt.r.long() && *flagShort {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif runRE == nil || runRE.MatchString(tt.name) {\n\t\t\t\tif err := tt.r.run(tt.name, i); err != nil {\n\t\t\t\t\tlog.Printf(\"%s: %v\", tt.name, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc toolPath(names ...string) (found, path string) {\n\tvar out1 []byte\n\tvar err1 error\n\tfor i, name := range names {\n\t\tout, err := exec.Command(*flagGoCmd, \"tool\", \"-n\", name).CombinedOutput()\n\t\tif err == nil {\n\t\t\treturn name, strings.TrimSpace(string(out))\n\t\t}\n\t\tif i == 0 {\n\t\t\tout1, err1 = out, err\n\t\t}\n\t}\n\tlog.Fatalf(\"go tool -n %s: %v\\n%s\", names[0], err1, out1)\n\treturn \"\", \"\"\n}\n\ntype Pkg struct {\n\tImportPath string\n\tDir        string\n\tGoFiles    []string\n\tSFiles     []string\n}\n\nfunc goList(dir string) (*Pkg, error) {\n\tvar pkg Pkg\n\tout, err := exec.Command(*flagGoCmd, \"list\", \"-json\", dir).Output()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"go list -json %s: %v\", dir, err)\n\t}\n\tif err := json.Unmarshal(out, &pkg); err != nil {\n\t\treturn nil, fmt.Errorf(\"go list -json %s: unmarshal: %v\", dir, err)\n\t}\n\treturn &pkg, nil\n}\n\nfunc runCmd(name string, cmd *exec.Cmd) error {\n\tstart := time.Now()\n\tout, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v\\n%s\", err, out)\n\t}\n\tfmt.Printf(\"%s 1 %d ns/op\\n\", name, time.Since(start).Nanoseconds())\n\treturn nil\n}\n\ntype goBuild struct{ pkgs []string }\n\nfunc (goBuild) long() bool { return true }\n\nfunc (r goBuild) run(name string, count int) error {\n\targs := []string{\"build\", \"-a\"}\n\tif *flagCompilerFlags != \"\" {\n\t\targs = append(args, \"-gcflags\", *flagCompilerFlags)\n\t}\n\targs = append(args, r.pkgs...)\n\tcmd := exec.Command(*flagGoCmd, args...)\n\tcmd.Dir = filepath.Join(goroot, \"src\")\n\treturn runCmd(name, cmd)\n}\n\ntype size struct {\n\t// path is either a path to a file (\"$GOROOT/test/helloworld.go\") or a package path (\"cmd/go\").\n\tpath   string\n\tisLong bool\n}\n\nfunc (r size) long() bool { return r.isLong }\n\nfunc (r size) run(name string, count int) error {\n\tif strings.HasPrefix(r.path, \"$GOROOT/\") {\n\t\tr.path = goroot + \"/\" + r.path[len(\"$GOROOT/\"):]\n\t}\n\n\tcmd := exec.Command(*flagGoCmd, \"build\", \"-o\", \"_compilebenchout_\", r.path)\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn err\n\t}\n\tdefer os.Remove(\"_compilebenchout_\")\n\tinfo, err := os.Stat(\"_compilebenchout_\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tout, err := exec.Command(\"size\", \"_compilebenchout_\").CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"size: %v\\n%s\", err, out)\n\t}\n\tlines := strings.Split(string(out), \"\\n\")\n\tif len(lines) < 2 {\n\t\treturn fmt.Errorf(\"not enough output from size: %s\", out)\n\t}\n\tf := strings.Fields(lines[1])\n\tif strings.HasPrefix(lines[0], \"__TEXT\") && len(f) >= 2 { // OS X\n\t\tfmt.Printf(\"%s 1 %s text-bytes %s data-bytes %v exe-bytes\\n\", name, f[0], f[1], info.Size())\n\t} else if strings.Contains(lines[0], \"bss\") && len(f) >= 3 {\n\t\tfmt.Printf(\"%s 1 %s text-bytes %s data-bytes %s bss-bytes %v exe-bytes\\n\", name, f[0], f[1], f[2], info.Size())\n\t}\n\treturn nil\n}\n\ntype compile struct{ dir string }\n\nfunc (compile) long() bool { return false }\n\nfunc (c compile) run(name string, count int) error {\n\t// Make sure dependencies needed by go tool compile are built.\n\tout, err := exec.Command(*flagGoCmd, \"build\", c.dir).CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"go build %s: %v\\n%s\", c.dir, err, out)\n\t}\n\n\t// Find dir and source file list.\n\tpkg, err := goList(c.dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\timportcfg, err := genImportcfgFile(c.dir, \"\", false) // TODO: pass compiler flags?\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If this package has assembly files, we'll need to pass a symabis\n\t// file to the compiler; call a helper to invoke the assembler\n\t// to do that.\n\tvar symAbisFile string\n\tvar asmIncFile string\n\tif len(pkg.SFiles) != 0 {\n\t\tsymAbisFile = filepath.Join(pkg.Dir, \"symabis\")\n\t\tasmIncFile = filepath.Join(pkg.Dir, \"go_asm.h\")\n\t\tcontent := \"\\n\"\n\t\tif err := os.WriteFile(asmIncFile, []byte(content), 0666); err != nil {\n\t\t\treturn fmt.Errorf(\"os.WriteFile(%s) failed: %v\", asmIncFile, err)\n\t\t}\n\t\tdefer os.Remove(symAbisFile)\n\t\tdefer os.Remove(asmIncFile)\n\t\tif err := genSymAbisFile(pkg, symAbisFile, pkg.Dir); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\targs := []string{\"-o\", \"_compilebench_.o\", \"-p\", pkg.ImportPath}\n\targs = append(args, strings.Fields(*flagCompilerFlags)...)\n\tif symAbisFile != \"\" {\n\t\targs = append(args, \"-symabis\", symAbisFile)\n\t}\n\tif importcfg != \"\" {\n\t\targs = append(args, \"-importcfg\", importcfg)\n\t\tdefer os.Remove(importcfg)\n\t}\n\targs = append(args, pkg.GoFiles...)\n\tif err := runBuildCmd(name, count, pkg.Dir, compiler, args); err != nil {\n\t\treturn err\n\t}\n\n\topath := pkg.Dir + \"/_compilebench_.o\"\n\tif *flagObj {\n\t\t// TODO(josharian): object files are big; just read enough to find what we seek.\n\t\tdata, err := os.ReadFile(opath)\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t}\n\t\t// Find start of export data.\n\t\ti := bytes.Index(data, []byte(\"\\n$$B\\n\")) + len(\"\\n$$B\\n\")\n\t\t// Count bytes to end of export data.\n\t\tnexport := bytes.Index(data[i:], []byte(\"\\n$$\\n\"))\n\t\tfmt.Printf(\" %d object-bytes %d export-bytes\", len(data), nexport)\n\t}\n\tfmt.Println()\n\n\tos.Remove(opath)\n\treturn nil\n}\n\ntype link struct{ dir, flags string }\n\nfunc (link) long() bool { return false }\n\nfunc (r link) run(name string, count int) error {\n\tif linker == \"\" {\n\t\t// No linker. Skip the test.\n\t\treturn nil\n\t}\n\n\t// Build dependencies.\n\tldflags := *flagLinkerFlags\n\tif r.flags != \"\" {\n\t\tif ldflags != \"\" {\n\t\t\tldflags += \" \"\n\t\t}\n\t\tldflags += r.flags\n\t}\n\tout, err := exec.Command(*flagGoCmd, \"build\", \"-o\", \"/dev/null\", \"-ldflags=\"+ldflags, r.dir).CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"go build -a %s: %v\\n%s\", r.dir, err, out)\n\t}\n\n\timportcfg, err := genImportcfgFile(r.dir, \"-ldflags=\"+ldflags, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.Remove(importcfg)\n\n\t// Build the main package.\n\tpkg, err := goList(r.dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\targs := []string{\"-o\", \"_compilebench_.o\", \"-importcfg\", importcfg}\n\targs = append(args, pkg.GoFiles...)\n\tif *flagTrace {\n\t\tfmt.Fprintf(os.Stderr, \"running: %s %+v\\n\",\n\t\t\tcompiler, args)\n\t}\n\tcmd := exec.Command(compiler, args...)\n\tcmd.Dir = pkg.Dir\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\terr = cmd.Run()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"compiling: %v\", err)\n\t}\n\tdefer os.Remove(pkg.Dir + \"/_compilebench_.o\")\n\n\t// Link the main package.\n\targs = []string{\"-o\", \"_compilebench_.exe\", \"-importcfg\", importcfg}\n\targs = append(args, strings.Fields(*flagLinkerFlags)...)\n\targs = append(args, strings.Fields(r.flags)...)\n\targs = append(args, \"_compilebench_.o\")\n\tif err := runBuildCmd(name, count, pkg.Dir, linker, args); err != nil {\n\t\treturn err\n\t}\n\tfmt.Println()\n\tdefer os.Remove(pkg.Dir + \"/_compilebench_.exe\")\n\n\treturn err\n}\n\n// runBuildCmd runs \"tool args...\" in dir, measures standard build\n// tool metrics, and prints a benchmark line. The caller may print\n// additional metrics and then must print a newline.\n//\n// This assumes tool accepts standard build tool flags like\n// -memprofilerate, -memprofile, and -cpuprofile.\nfunc runBuildCmd(name string, count int, dir, tool string, args []string) error {\n\tvar preArgs []string\n\tif *flagMemprofilerate >= 0 {\n\t\tpreArgs = append(preArgs, \"-memprofilerate\", fmt.Sprint(*flagMemprofilerate))\n\t}\n\tif *flagAlloc || *flagCpuprofile != \"\" || *flagMemprofile != \"\" {\n\t\tif *flagAlloc || *flagMemprofile != \"\" {\n\t\t\tpreArgs = append(preArgs, \"-memprofile\", \"_compilebench_.memprof\")\n\t\t}\n\t\tif *flagCpuprofile != \"\" {\n\t\t\tpreArgs = append(preArgs, \"-cpuprofile\", \"_compilebench_.cpuprof\")\n\t\t}\n\t}\n\tif *flagTrace {\n\t\tfmt.Fprintf(os.Stderr, \"running: %s %+v\\n\",\n\t\t\ttool, append(preArgs, args...))\n\t}\n\tcmd := exec.Command(tool, append(preArgs, args...)...)\n\tcmd.Dir = dir\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\tstart := time.Now()\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn err\n\t}\n\tend := time.Now()\n\n\thaveAllocs, haveRSS := false, false\n\tvar allocs, allocbytes, rssbytes int64\n\tif *flagAlloc || *flagMemprofile != \"\" {\n\t\tout, err := os.ReadFile(dir + \"/_compilebench_.memprof\")\n\t\tif err != nil {\n\t\t\tlog.Print(\"cannot find memory profile after compilation\")\n\t\t}\n\t\tfor line := range strings.SplitSeq(string(out), \"\\n\") {\n\t\t\tf := strings.Fields(line)\n\t\t\tif len(f) < 4 || f[0] != \"#\" || f[2] != \"=\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tval, err := strconv.ParseInt(f[3], 0, 64)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\thaveAllocs = true\n\t\t\tswitch f[1] {\n\t\t\tcase \"TotalAlloc\":\n\t\t\t\tallocbytes = val\n\t\t\tcase \"Mallocs\":\n\t\t\t\tallocs = val\n\t\t\tcase \"MaxRSS\":\n\t\t\t\thaveRSS = true\n\t\t\t\trssbytes = val\n\t\t\t}\n\t\t}\n\t\tif !haveAllocs {\n\t\t\tlog.Println(\"missing stats in memprof (golang.org/issue/18641)\")\n\t\t}\n\n\t\tif *flagMemprofile != \"\" {\n\t\t\toutpath := *flagMemprofile\n\t\t\tif *flagCount != 1 {\n\t\t\t\toutpath = fmt.Sprintf(\"%s_%d\", outpath, count)\n\t\t\t}\n\t\t\tif err := os.WriteFile(outpath, out, 0666); err != nil {\n\t\t\t\tlog.Print(err)\n\t\t\t}\n\t\t}\n\t\tos.Remove(dir + \"/_compilebench_.memprof\")\n\t}\n\n\tif *flagCpuprofile != \"\" {\n\t\tout, err := os.ReadFile(dir + \"/_compilebench_.cpuprof\")\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t}\n\t\toutpath := *flagCpuprofile\n\t\tif *flagCount != 1 {\n\t\t\toutpath = fmt.Sprintf(\"%s_%d\", outpath, count)\n\t\t}\n\t\tif err := os.WriteFile(outpath, out, 0666); err != nil {\n\t\t\tlog.Print(err)\n\t\t}\n\t\tos.Remove(dir + \"/_compilebench_.cpuprof\")\n\t}\n\n\twallns := end.Sub(start).Nanoseconds()\n\tuserns := cmd.ProcessState.UserTime().Nanoseconds()\n\n\tfmt.Printf(\"%s 1 %d ns/op %d user-ns/op\", name, wallns, userns)\n\tif haveAllocs {\n\t\tfmt.Printf(\" %d B/op %d allocs/op\", allocbytes, allocs)\n\t}\n\tif haveRSS {\n\t\tfmt.Printf(\" %d maxRSS/op\", rssbytes)\n\t}\n\n\treturn nil\n}\n\nfunc checkCompilingRuntimeFlag(assembler string) error {\n\ttd, err := os.MkdirTemp(\"\", \"asmsrcd\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"MkdirTemp failed: %v\", err)\n\t}\n\tdefer os.RemoveAll(td)\n\tsrc := filepath.Join(td, \"asm.s\")\n\tobj := filepath.Join(td, \"asm.o\")\n\tconst code = `\nTEXT ·foo(SB),$0-0\nRET\n`\n\tif err := os.WriteFile(src, []byte(code), 0644); err != nil {\n\t\treturn fmt.Errorf(\"writing %s failed: %v\", src, err)\n\t}\n\n\t// Try compiling the assembly source file passing\n\t// -compiling-runtime; if it succeeds, then we'll need it\n\t// when doing assembly of the reflect package later on.\n\t// If it does not succeed, the assumption is that it's not\n\t// needed.\n\targs := []string{\"-o\", obj, \"-p\", \"reflect\", \"-compiling-runtime\", src}\n\tcmd := exec.Command(assembler, args...)\n\tcmd.Dir = td\n\tout, aerr := cmd.CombinedOutput()\n\tif aerr != nil {\n\t\tif strings.Contains(string(out), \"flag provided but not defined: -compiling-runtime\") {\n\t\t\t// flag not defined: assume we're using a recent assembler, so\n\t\t\t// don't use -compiling-runtime.\n\t\t\treturn nil\n\t\t}\n\t\t// error is not flag-related; report it.\n\t\treturn fmt.Errorf(\"problems invoking assembler with args %+v: error %v\\n%s\\n\", args, aerr, out)\n\t}\n\t// asm invocation succeeded -- assume we need the flag.\n\tneedCompilingRuntimeFlag = true\n\treturn nil\n}\n\n// genSymAbisFile runs the assembler on the target package asm files\n// with \"-gensymabis\" to produce a symabis file that will feed into\n// the Go source compilation. This is fairly hacky in that if the\n// asm invocation convention changes it will need to be updated\n// (hopefully that will not be needed too frequently).\nfunc genSymAbisFile(pkg *Pkg, symAbisFile, incdir string) error {\n\targs := []string{\"-gensymabis\", \"-o\", symAbisFile,\n\t\t\"-p\", pkg.ImportPath,\n\t\t\"-I\", filepath.Join(goroot, \"pkg\", \"include\"),\n\t\t\"-I\", incdir,\n\t\t\"-D\", \"GOOS_\" + runtime.GOOS,\n\t\t\"-D\", \"GOARCH_\" + runtime.GOARCH}\n\tif pkg.ImportPath == \"reflect\" && needCompilingRuntimeFlag {\n\t\targs = append(args, \"-compiling-runtime\")\n\t}\n\targs = append(args, pkg.SFiles...)\n\tif *flagTrace {\n\t\tfmt.Fprintf(os.Stderr, \"running: %s %+v\\n\",\n\t\t\tassembler, args)\n\t}\n\tcmd := exec.Command(assembler, args...)\n\tcmd.Dir = pkg.Dir\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"assembling to produce symabis file: %v\", err)\n\t}\n\treturn nil\n}\n\n// genImportcfgFile generates an importcfg file for building package\n// dir. Returns the generated importcfg file path (or empty string\n// if the package has no dependency).\nfunc genImportcfgFile(dir string, flags string, full bool) (string, error) {\n\tneed := \"{{.Imports}}\"\n\tif full {\n\t\t// for linking, we need transitive dependencies\n\t\tneed = \"{{.Deps}}\"\n\t}\n\n\tif flags == \"\" {\n\t\tflags = \"--\" // passing \"\" to go list, it will match to the current directory\n\t}\n\n\t// find imported/dependent packages\n\tcmd := exec.Command(*flagGoCmd, \"list\", \"-f\", need, flags, dir)\n\tcmd.Stderr = os.Stderr\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"go list -f %s %s: %v\", need, dir, err)\n\t}\n\t// trim [ ]\\n\n\tif len(out) < 3 || out[0] != '[' || out[len(out)-2] != ']' || out[len(out)-1] != '\\n' {\n\t\treturn \"\", fmt.Errorf(\"unexpected output from go list -f %s %s: %s\", need, dir, out)\n\t}\n\tout = out[1 : len(out)-2]\n\tif len(out) == 0 {\n\t\treturn \"\", nil\n\t}\n\n\t// build importcfg for imported packages\n\tcmd = exec.Command(*flagGoCmd, \"list\", \"-export\", \"-f\", \"{{if .Export}}packagefile {{.ImportPath}}={{.Export}}{{end}}\", flags)\n\tcmd.Args = append(cmd.Args, strings.Fields(string(out))...)\n\tcmd.Stderr = os.Stderr\n\tout, err = cmd.Output()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"generating importcfg for %s: %s: %v\", dir, cmd, err)\n\t}\n\n\tf, err := os.CreateTemp(\"\", \"importcfg\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"creating tmp importcfg file failed: %v\", err)\n\t}\n\tdefer f.Close()\n\tif _, err := f.Write(out); err != nil {\n\t\treturn \"\", fmt.Errorf(\"writing importcfg file %s failed: %v\", f.Name(), err)\n\t}\n\treturn f.Name(), nil\n}\n"
  },
  {
    "path": "cmd/deadcode/deadcode.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"golang.org/x/telemetry\"\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/rta\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\n// flags\nvar (\n\ttestFlag = flag.Bool(\"test\", false, \"include implicit test packages and executables\")\n\ttagsFlag = flag.String(\"tags\", \"\", \"comma-separated list of extra build tags (see: go help buildconstraint)\")\n\n\tfilterFlag    = flag.String(\"filter\", \"<module>\", \"report only packages matching this regular expression (default: module of first package)\")\n\tgeneratedFlag = flag.Bool(\"generated\", false, \"include dead functions in generated Go files\")\n\twhyLiveFlag   = flag.String(\"whylive\", \"\", \"show a path from main to the named function\")\n\tformatFlag    = flag.String(\"f\", \"\", \"format output records using template\")\n\tjsonFlag      = flag.Bool(\"json\", false, \"output JSON records\")\n\tcpuProfile    = flag.String(\"cpuprofile\", \"\", \"write CPU profile to this file\")\n\tmemProfile    = flag.String(\"memprofile\", \"\", \"write memory profile to this file\")\n)\n\nfunc usage() {\n\t// Extract the content of the /* ... */ comment in doc.go.\n\t_, after, _ := strings.Cut(doc, \"/*\\n\")\n\tdoc, _, _ := strings.Cut(after, \"*/\")\n\tio.WriteString(flag.CommandLine.Output(), doc+`\nFlags:\n\n`)\n\tflag.PrintDefaults()\n}\n\nfunc main() {\n\ttelemetry.Start(telemetry.Config{ReportCrashes: true})\n\n\tlog.SetPrefix(\"deadcode: \")\n\tlog.SetFlags(0) // no time prefix\n\n\tflag.Usage = usage\n\tflag.Parse()\n\tif len(flag.Args()) == 0 {\n\t\tusage()\n\t\tos.Exit(2)\n\t}\n\n\tif *cpuProfile != \"\" {\n\t\tf, err := os.Create(*cpuProfile)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif err := pprof.StartCPUProfile(f); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// NB: profile won't be written in case of error.\n\t\tdefer pprof.StopCPUProfile()\n\t}\n\n\tif *memProfile != \"\" {\n\t\tf, err := os.Create(*memProfile)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// NB: profile won't be written in case of error.\n\t\tdefer func() {\n\t\t\truntime.GC() // get up-to-date statistics\n\t\t\tif err := pprof.WriteHeapProfile(f); err != nil {\n\t\t\t\tlog.Fatalf(\"Writing memory profile: %v\", err)\n\t\t\t}\n\t\t\tf.Close()\n\t\t}()\n\t}\n\n\t// Reject bad output options early.\n\tif *formatFlag != \"\" {\n\t\tif *jsonFlag {\n\t\t\tlog.Fatalf(\"you cannot specify both -f=template and -json\")\n\t\t}\n\t\tif _, err := template.New(\"deadcode\").Parse(*formatFlag); err != nil {\n\t\t\tlog.Fatalf(\"invalid -f: %v\", err)\n\t\t}\n\t}\n\n\t// Load, parse, and type-check the complete program(s).\n\tcfg := &packages.Config{\n\t\tBuildFlags: []string{\"-tags=\" + *tagsFlag},\n\t\tMode:       packages.LoadAllSyntax | packages.NeedModule,\n\t\tTests:      *testFlag,\n\t}\n\tinitial, err := packages.Load(cfg, flag.Args()...)\n\tif err != nil {\n\t\tlog.Fatalf(\"Load: %v\", err)\n\t}\n\tif len(initial) == 0 {\n\t\tlog.Fatalf(\"no packages\")\n\t}\n\tif packages.PrintErrors(initial) > 0 {\n\t\tlog.Fatalf(\"packages contain errors\")\n\t}\n\n\t// If -filter is unset, use first module (if available).\n\tif *filterFlag == \"<module>\" {\n\t\tseen := make(map[string]bool)\n\t\tvar patterns []string\n\t\tfor _, pkg := range initial {\n\t\t\tif pkg.Module != nil && pkg.Module.Path != \"\" && !seen[pkg.Module.Path] {\n\t\t\t\tseen[pkg.Module.Path] = true\n\t\t\t\tpatterns = append(patterns, regexp.QuoteMeta(pkg.Module.Path))\n\t\t\t}\n\t\t}\n\n\t\tif patterns != nil {\n\t\t\t*filterFlag = \"^(\" + strings.Join(patterns, \"|\") + \")\\\\b\"\n\t\t} else {\n\t\t\t*filterFlag = \"\" // match any\n\t\t}\n\t}\n\tfilter, err := regexp.Compile(*filterFlag)\n\tif err != nil {\n\t\tlog.Fatalf(\"-filter: %v\", err)\n\t}\n\n\t// Create SSA-form program representation\n\t// and find main packages.\n\tprog, pkgs := ssautil.AllPackages(initial, ssa.InstantiateGenerics)\n\tprog.Build()\n\n\tmains := ssautil.MainPackages(pkgs)\n\tif len(mains) == 0 {\n\t\tlog.Fatalf(\"no main packages\")\n\t}\n\tvar roots []*ssa.Function\n\tfor _, main := range mains {\n\t\troots = append(roots, main.Func(\"init\"), main.Func(\"main\"))\n\t}\n\n\t// Gather all source-level functions,\n\t// as the user interface is expressed in terms of them.\n\t//\n\t// We ignore synthetic wrappers, and nested functions. Literal\n\t// functions passed as arguments to other functions are of\n\t// course address-taken and there exists a dynamic call of\n\t// that signature, so when they are unreachable, it is\n\t// invariably because the parent is unreachable.\n\tvar (\n\t\tsourceFuncs    []*ssa.Function\n\t\tgenerated      = make(map[string]bool)\n\t\tinterfaceTypes = make(map[*types.Package][]*types.Interface)\n\t)\n\tpackages.Visit(initial, nil, func(p *packages.Package) {\n\t\t// Collect interfaces by package for marker method identification.\n\t\tvar interfaces []*types.Interface\n\t\tscope := p.Types.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\tif typeName, ok := scope.Lookup(name).(*types.TypeName); ok &&\n\t\t\t\ttypes.IsInterface(typeName.Type()) {\n\t\t\t\tinterfaces = append(interfaces, typeName.Type().Underlying().(*types.Interface))\n\t\t\t}\n\t\t}\n\t\tinterfaceTypes[p.Types] = interfaces\n\n\t\tfor _, file := range p.Syntax {\n\t\t\tfor _, decl := range file.Decls {\n\t\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\t\tobj := p.TypesInfo.Defs[decl.Name].(*types.Func)\n\t\t\t\t\tfn := prog.FuncValue(obj)\n\t\t\t\t\tsourceFuncs = append(sourceFuncs, fn)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ast.IsGenerated(file) {\n\t\t\t\tgenerated[p.Fset.File(file.Pos()).Name()] = true\n\t\t\t}\n\t\t}\n\t})\n\n\t// Compute the reachabilty from main.\n\t// (Build a call graph only for -whylive.)\n\tres := rta.Analyze(roots, *whyLiveFlag != \"\")\n\n\t// Subtle: the -test flag causes us to analyze test variants\n\t// such as \"package p as compiled for p.test\" or even \"for q.test\".\n\t// This leads to multiple distinct ssa.Function instances that\n\t// represent the same source declaration, and it is essentially\n\t// impossible to discover this from the SSA representation\n\t// (since it has lost the connection to go/packages.Package.ID).\n\t//\n\t// So, we de-duplicate such variants by position:\n\t// if any one of them is live, we consider all of them live.\n\t// (We use Position not Pos to avoid assuming that files common\n\t// to packages \"p\" and \"p [p.test]\" were parsed only once.)\n\treachablePosn := make(map[token.Position]bool)\n\tfor fn := range res.Reachable {\n\t\tif fn.Pos().IsValid() || fn.Name() == \"init\" {\n\t\t\treachablePosn[prog.Fset.Position(fn.Pos())] = true\n\t\t}\n\t}\n\n\t// The -whylive=fn flag causes deadcode to explain why a function\n\t// is not dead, by showing a path to it from some root.\n\tif *whyLiveFlag != \"\" {\n\t\ttargets := make(map[*ssa.Function]bool)\n\t\tfor _, fn := range sourceFuncs {\n\t\t\tif prettyName(fn, true) == *whyLiveFlag {\n\t\t\t\ttargets[fn] = true\n\t\t\t}\n\t\t}\n\t\tif len(targets) == 0 {\n\t\t\t// Function is not part of the program.\n\t\t\t//\n\t\t\t// TODO(adonovan): improve the UX here in case\n\t\t\t// of spelling or syntax mistakes. Some ideas:\n\t\t\t// - a cmd/callgraph command to enumerate\n\t\t\t//   available functions.\n\t\t\t// - a deadcode -live flag to compute the complement.\n\t\t\t// - a syntax hint: example.com/pkg.Func or (example.com/pkg.Type).Method\n\t\t\t// - report the element of AllFunctions with the smallest\n\t\t\t//   Levenshtein distance from *whyLiveFlag.\n\t\t\t// - permit -whylive=regexp. But beware of spurious\n\t\t\t//   matches (e.g. fmt.Print matches fmt.Println)\n\t\t\t//   and the annoyance of having to quote parens (*T).f.\n\t\t\tlog.Fatalf(\"function %q not found in program\", *whyLiveFlag)\n\t\t}\n\n\t\t// Opt: remove the unreachable ones.\n\t\tfor fn := range targets {\n\t\t\tif !reachablePosn[prog.Fset.Position(fn.Pos())] {\n\t\t\t\tdelete(targets, fn)\n\t\t\t}\n\t\t}\n\t\tif len(targets) == 0 {\n\t\t\tlog.Fatalf(\"function %s is dead code\", *whyLiveFlag)\n\t\t}\n\n\t\tres.CallGraph.DeleteSyntheticNodes() // inline synthetic wrappers (except inits)\n\t\troot, path := pathSearch(roots, res, targets)\n\t\tif root == nil {\n\t\t\t// RTA doesn't add callgraph edges for reflective calls.\n\t\t\tlog.Fatalf(\"%s is reachable only through reflection\", *whyLiveFlag)\n\t\t}\n\t\tif len(path) == 0 {\n\t\t\t// No edges => one of the targets is a root.\n\t\t\t// Rather than (confusingly) print nothing, make this an error.\n\t\t\tlog.Fatalf(\"%s is a root\", root.Func)\n\t\t}\n\n\t\t// Build a list of jsonEdge records\n\t\t// to print as -json or -f=template.\n\t\tvar edges []any\n\t\tfor _, edge := range path {\n\t\t\tedges = append(edges, jsonEdge{\n\t\t\t\tInitial:  cond(len(edges) == 0, prettyName(edge.Caller.Func, true), \"\"),\n\t\t\t\tKind:     cond(isStaticCall(edge), \"static\", \"dynamic\"),\n\t\t\t\tPosition: toJSONPosition(prog.Fset.Position(edge.Pos())),\n\t\t\t\tCallee:   prettyName(edge.Callee.Func, true),\n\t\t\t})\n\t\t}\n\t\tformat := `{{if .Initial}}{{printf \"%19s%s\\n\" \"\" .Initial}}{{end}}{{printf \"%8s@L%.4d --> %s\" .Kind .Position.Line .Callee}}`\n\t\tif *formatFlag != \"\" {\n\t\t\tformat = *formatFlag\n\t\t}\n\t\tprintObjects(format, edges)\n\t\treturn\n\t}\n\n\t// Group unreachable functions by package path.\n\tbyPkgPath := make(map[string]map[*ssa.Function]bool)\n\tfor _, fn := range sourceFuncs {\n\t\tposn := prog.Fset.Position(fn.Pos())\n\n\t\tif !reachablePosn[posn] {\n\t\t\treachablePosn[posn] = true // suppress dups with same pos\n\n\t\t\tpkgpath := fn.Pkg.Pkg.Path()\n\t\t\tm, ok := byPkgPath[pkgpath]\n\t\t\tif !ok {\n\t\t\t\tm = make(map[*ssa.Function]bool)\n\t\t\t\tbyPkgPath[pkgpath] = m\n\t\t\t}\n\t\t\tm[fn] = true\n\t\t}\n\t}\n\n\t// Build array of jsonPackage objects.\n\tvar packages []any\n\tfor _, pkgpath := range slices.Sorted(maps.Keys(byPkgPath)) {\n\t\tif !filter.MatchString(pkgpath) {\n\t\t\tcontinue\n\t\t}\n\n\t\tm := byPkgPath[pkgpath]\n\n\t\t// Print functions that appear within the same file in\n\t\t// declaration order. This tends to keep related\n\t\t// methods such as (T).Marshal and (*T).Unmarshal\n\t\t// together better than sorting.\n\t\tfns := slices.Collect(maps.Keys(m))\n\t\tsort.Slice(fns, func(i, j int) bool {\n\t\t\txposn := prog.Fset.Position(fns[i].Pos())\n\t\t\typosn := prog.Fset.Position(fns[j].Pos())\n\t\t\tif xposn.Filename != yposn.Filename {\n\t\t\t\treturn xposn.Filename < yposn.Filename\n\t\t\t}\n\t\t\treturn xposn.Line < yposn.Line\n\t\t})\n\n\t\tvar functions []jsonFunction\n\t\tfor _, fn := range fns {\n\t\t\tposn := prog.Fset.Position(fn.Pos())\n\n\t\t\t// Without -generated, skip functions declared in\n\t\t\t// generated Go files.\n\t\t\t// (Functions called by them may still be reported.)\n\t\t\tgen := generated[posn.Filename]\n\t\t\tif gen && !*generatedFlag {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Marker methods should not be reported\n\t\t\tmarker := isMarkerMethod(fn, interfaceTypes[fn.Pkg.Pkg])\n\t\t\tif marker {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfunctions = append(functions, jsonFunction{\n\t\t\t\tName:      prettyName(fn, false),\n\t\t\t\tPosition:  toJSONPosition(posn),\n\t\t\t\tGenerated: gen,\n\t\t\t\tMarker:    marker,\n\t\t\t})\n\t\t}\n\t\tif len(functions) > 0 {\n\t\t\tpackages = append(packages, jsonPackage{\n\t\t\t\tName:  fns[0].Pkg.Pkg.Name(),\n\t\t\t\tPath:  pkgpath,\n\t\t\t\tFuncs: functions,\n\t\t\t})\n\t\t}\n\t}\n\n\t// Default line-oriented format: \"a/b/c.go:1:2: unreachable func: T.f\"\n\tformat := `{{range .Funcs}}{{printf \"%s: unreachable func: %s\\n\" .Position .Name}}{{end}}`\n\tif *formatFlag != \"\" {\n\t\tformat = *formatFlag\n\t}\n\tprintObjects(format, packages)\n}\n\n// prettyName is a fork of Function.String designed to reduce\n// go/ssa's fussy punctuation symbols, e.g. \"(*pkg.T).F\" -> \"pkg.T.F\".\n//\n// It only works for functions that remain after\n// callgraph.Graph.DeleteSyntheticNodes: source-level named functions\n// and methods, their anonymous functions, and synthetic package\n// initializers.\nfunc prettyName(fn *ssa.Function, qualified bool) string {\n\tvar buf strings.Builder\n\n\t// optional package qualifier\n\tif qualified && fn.Pkg != nil {\n\t\tfmt.Fprintf(&buf, \"%s.\", fn.Pkg.Pkg.Path())\n\t}\n\n\tvar format func(*ssa.Function)\n\tformat = func(fn *ssa.Function) {\n\t\t// anonymous?\n\t\tif fn.Parent() != nil {\n\t\t\tformat(fn.Parent())\n\t\t\ti := slices.Index(fn.Parent().AnonFuncs, fn)\n\t\t\tfmt.Fprintf(&buf, \"$%d\", i+1)\n\t\t\treturn\n\t\t}\n\n\t\t// method receiver?\n\t\tif recv := fn.Signature.Recv(); recv != nil {\n\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\tbuf.WriteString(named.Obj().Name())\n\t\t\tbuf.WriteByte('.')\n\t\t}\n\n\t\t// function/method name\n\t\tbuf.WriteString(fn.Name())\n\t}\n\tformat(fn)\n\n\treturn buf.String()\n}\n\n// printObjects formats an array of objects, either as JSON or using a\n// template, following the manner of 'go list (-json|-f=template)'.\nfunc printObjects(format string, objects []any) {\n\tif *jsonFlag {\n\t\tout, err := json.MarshalIndent(objects, \"\", \"\\t\")\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"internal error: %v\", err)\n\t\t}\n\t\tos.Stdout.Write(out)\n\t\treturn\n\t}\n\n\t// -f=template. Parse can't fail: we checked it earlier.\n\ttmpl := template.Must(template.New(\"deadcode\").Parse(format))\n\tfor _, object := range objects {\n\t\tvar buf bytes.Buffer\n\t\tif err := tmpl.Execute(&buf, object); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif n := buf.Len(); n == 0 || buf.Bytes()[n-1] != '\\n' {\n\t\t\tbuf.WriteByte('\\n')\n\t\t}\n\t\tos.Stdout.Write(buf.Bytes())\n\t}\n}\n\n// pathSearch returns the shortest path from one of the roots to one\n// of the targets (along with the root itself), or zero if no path was found.\nfunc pathSearch(roots []*ssa.Function, res *rta.Result, targets map[*ssa.Function]bool) (*callgraph.Node, []*callgraph.Edge) {\n\t// Search breadth-first (for shortest path) from the root.\n\t//\n\t// We don't use the virtual CallGraph.Root node as we wish to\n\t// choose the order in which we search entrypoints:\n\t// non-test packages before test packages,\n\t// main functions before init functions.\n\n\t// Sort roots into preferred order.\n\timportsTesting := func(fn *ssa.Function) bool {\n\t\tisTesting := func(p *types.Package) bool { return p.Path() == \"testing\" }\n\t\treturn slices.ContainsFunc(fn.Pkg.Pkg.Imports(), isTesting)\n\t}\n\tsort.Slice(roots, func(i, j int) bool {\n\t\tx, y := roots[i], roots[j]\n\t\txtest := importsTesting(x)\n\t\tytest := importsTesting(y)\n\t\tif xtest != ytest {\n\t\t\treturn !xtest // non-tests before tests\n\t\t}\n\t\txinit := x.Name() == \"init\"\n\t\tyinit := y.Name() == \"init\"\n\t\tif xinit != yinit {\n\t\t\treturn !xinit // mains before inits\n\t\t}\n\t\treturn false\n\t})\n\n\tsearch := func(allowDynamic bool) (*callgraph.Node, []*callgraph.Edge) {\n\t\t// seen maps each encountered node to its predecessor on the\n\t\t// path to a root node, or to nil for root itself.\n\t\tseen := make(map[*callgraph.Node]*callgraph.Edge)\n\t\tbfs := func(root *callgraph.Node) []*callgraph.Edge {\n\t\t\tqueue := []*callgraph.Node{root}\n\t\t\tseen[root] = nil\n\t\t\tfor len(queue) > 0 {\n\t\t\t\tnode := queue[0]\n\t\t\t\tqueue = queue[1:]\n\n\t\t\t\t// found a path?\n\t\t\t\tif targets[node.Func] {\n\t\t\t\t\tpath := []*callgraph.Edge{} // non-nil in case len(path)=0\n\t\t\t\t\tfor {\n\t\t\t\t\t\tedge := seen[node]\n\t\t\t\t\t\tif edge == nil {\n\t\t\t\t\t\t\tslices.Reverse(path)\n\t\t\t\t\t\t\treturn path\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpath = append(path, edge)\n\t\t\t\t\t\tnode = edge.Caller\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor _, edge := range node.Out {\n\t\t\t\t\tif allowDynamic || isStaticCall(edge) {\n\t\t\t\t\t\tif _, ok := seen[edge.Callee]; !ok {\n\t\t\t\t\t\t\tseen[edge.Callee] = edge\n\t\t\t\t\t\t\tqueue = append(queue, edge.Callee)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\tfor _, rootFn := range roots {\n\t\t\troot := res.CallGraph.Nodes[rootFn]\n\t\t\tif root == nil {\n\t\t\t\t// Missing call graph node for root.\n\t\t\t\t// TODO(adonovan): seems like a bug in rta.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif path := bfs(root); path != nil {\n\t\t\t\treturn root, path\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\t}\n\n\tfor _, allowDynamic := range []bool{false, true} {\n\t\tif root, path := search(allowDynamic); path != nil {\n\t\t\treturn root, path\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\n// -- utilities --\n\nfunc isStaticCall(edge *callgraph.Edge) bool {\n\treturn edge.Site != nil && edge.Site.Common().StaticCallee() != nil\n}\n\nvar cwd, _ = os.Getwd()\n\nfunc toJSONPosition(posn token.Position) jsonPosition {\n\t// Use cwd-relative filename if possible.\n\tfilename := posn.Filename\n\tif rel, err := filepath.Rel(cwd, filename); err == nil && !strings.HasPrefix(rel, \"..\") {\n\t\tfilename = rel\n\t}\n\n\treturn jsonPosition{filename, posn.Line, posn.Column}\n}\n\nfunc cond[T any](cond bool, t, f T) T {\n\tif cond {\n\t\treturn t\n\t} else {\n\t\treturn f\n\t}\n}\n\n// isMarkerMethod reports whether fn is a marker method:\n// an unexported, empty-bodied method with no parameters or results\n// that implements some named interface type in the same package.\nfunc isMarkerMethod(fn *ssa.Function, interfaceTypes []*types.Interface) bool {\n\t// Is it an unexported method of no params/results?\n\tif !(fn.Signature.Recv() != nil &&\n\t\t!ast.IsExported(fn.Name()) &&\n\t\tfn.Signature.Params() == nil &&\n\t\tfn.Signature.Results() == nil) {\n\t\treturn false\n\t}\n\n\t// Does the method have an empty body?\n\tbody := fn.Syntax().(*ast.FuncDecl).Body\n\tif body == nil || len(body.List) > 0 {\n\t\treturn false\n\t}\n\n\t// Does it implement some named interface type in this package?\n\treturn slices.ContainsFunc(interfaceTypes, func(iface *types.Interface) bool {\n\t\treturn types.Implements(fn.Signature.Recv().Type(), iface)\n\t})\n}\n\n// -- output protocol (for JSON or text/template) --\n\n// Keep in sync with doc comment!\n\ntype jsonFunction struct {\n\tName      string       // name (sans package qualifier)\n\tPosition  jsonPosition // file/line/column of declaration\n\tGenerated bool         // function is declared in a generated .go file\n\tMarker    bool         // function is a marker interface method\n}\n\nfunc (f jsonFunction) String() string { return f.Name }\n\ntype jsonPackage struct {\n\tName  string         // declared name\n\tPath  string         // full import path\n\tFuncs []jsonFunction // non-empty list of package's dead functions\n}\n\nfunc (p jsonPackage) String() string { return p.Path }\n\n// The Initial and Callee names are package-qualified.\ntype jsonEdge struct {\n\tInitial  string `json:\",omitempty\"` // initial entrypoint (main or init); first edge only\n\tKind     string // = static | dynamic\n\tPosition jsonPosition\n\tCallee   string\n}\n\ntype jsonPosition struct {\n\tFile      string\n\tLine, Col int\n}\n\nfunc (p jsonPosition) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d\", p.File, p.Line, p.Col)\n}\n"
  },
  {
    "path": "cmd/deadcode/deadcode_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// Test runs the deadcode command on each scenario\n// described by a testdata/*.txtar file.\nfunc Test(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\n\texe := buildDeadcode(t)\n\n\tmatches, err := filepath.Glob(\"testdata/*.txtar\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, filename := range matches {\n\t\tt.Run(filename, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tar, err := txtar.ParseFile(filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Write the archive files to the temp directory.\n\t\t\ttmpdir := t.TempDir()\n\t\t\tfor _, f := range ar.Files {\n\t\t\t\tfilename := filepath.Join(tmpdir, f.Name)\n\t\t\t\tif err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif err := os.WriteFile(filename, f.Data, 0666); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse archive comment as directives of these forms:\n\t\t\t//\n\t\t\t//  [!]deadcode args...\tcommand-line arguments\n\t\t\t//  [!]want arg\t\texpected/unwanted string in output (or stderr)\n\t\t\t//\n\t\t\t// Args may be Go-quoted strings.\n\t\t\ttype testcase struct {\n\t\t\t\tlinenum int\n\t\t\t\targs    []string\n\t\t\t\twantErr bool\n\t\t\t\twant    map[string]bool // string -> sense\n\t\t\t}\n\t\t\tvar cases []*testcase\n\t\t\tvar current *testcase\n\t\t\tfor i, line := range strings.Split(string(ar.Comment), \"\\n\") {\n\t\t\t\tline = strings.TrimSpace(line)\n\t\t\t\tif line == \"\" || line[0] == '#' {\n\t\t\t\t\tcontinue // skip blanks and comments\n\t\t\t\t}\n\n\t\t\t\twords, err := words(line)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"cannot break line into words: %v (%s)\", err, line)\n\t\t\t\t}\n\t\t\t\tswitch kind := words[0]; kind {\n\t\t\t\tcase \"deadcode\", \"!deadcode\":\n\t\t\t\t\tcurrent = &testcase{\n\t\t\t\t\t\tlinenum: i + 1,\n\t\t\t\t\t\twant:    make(map[string]bool),\n\t\t\t\t\t\targs:    words[1:],\n\t\t\t\t\t\twantErr: kind[0] == '!',\n\t\t\t\t\t}\n\t\t\t\t\tcases = append(cases, current)\n\t\t\t\tcase \"want\", \"!want\":\n\t\t\t\t\tif current == nil {\n\t\t\t\t\t\tt.Fatalf(\"'want' directive must be after 'deadcode'\")\n\t\t\t\t\t}\n\t\t\t\t\tif len(words) != 2 {\n\t\t\t\t\t\tt.Fatalf(\"'want' directive needs argument <<%s>>\", line)\n\t\t\t\t\t}\n\t\t\t\t\tcurrent.want[words[1]] = kind[0] != '!'\n\t\t\t\tdefault:\n\t\t\t\t\tt.Fatalf(\"%s: invalid directive %q\", filename, kind)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, tc := range cases {\n\t\t\t\tt.Run(fmt.Sprintf(\"L%d\", tc.linenum), func(t *testing.T) {\n\t\t\t\t\t// Run the command.\n\t\t\t\t\tcmd := exec.Command(exe, tc.args...)\n\t\t\t\t\tcmd.Stdout = new(bytes.Buffer)\n\t\t\t\t\tcmd.Stderr = new(bytes.Buffer)\n\t\t\t\t\tcmd.Dir = tmpdir\n\t\t\t\t\tcmd.Env = append(os.Environ(), \"GOPROXY=\", \"GO111MODULE=on\")\n\t\t\t\t\tvar got string\n\t\t\t\t\tif err := cmd.Run(); err != nil {\n\t\t\t\t\t\tif !tc.wantErr {\n\t\t\t\t\t\t\tt.Fatalf(\"deadcode failed: %v (stderr=%s)\", err, cmd.Stderr)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgot = fmt.Sprint(cmd.Stderr)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif tc.wantErr {\n\t\t\t\t\t\t\tt.Fatalf(\"deadcode succeeded unexpectedly (stdout=%s)\", cmd.Stdout)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgot = fmt.Sprint(cmd.Stdout)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check each want directive.\n\t\t\t\t\tfor str, sense := range tc.want {\n\t\t\t\t\t\tok := true\n\t\t\t\t\t\tif strings.Contains(got, str) != sense {\n\t\t\t\t\t\t\tif sense {\n\t\t\t\t\t\t\t\tt.Errorf(\"missing %q\", str)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt.Errorf(\"unwanted %q\", str)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tok = false\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tt.Errorf(\"got: <<%s>>\", got)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\n// buildDeadcode builds the deadcode executable.\n// It returns its path, and a cleanup function.\nfunc buildDeadcode(t *testing.T) string {\n\tbin := filepath.Join(t.TempDir(), \"deadcode\")\n\tif runtime.GOOS == \"windows\" {\n\t\tbin += \".exe\"\n\t}\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", bin)\n\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"Building deadcode: %v\\n%s\", err, out)\n\t}\n\treturn bin\n}\n\n// words breaks a string into words, respecting\n// Go string quotations around words with spaces.\nfunc words(s string) ([]string, error) {\n\tvar words []string\n\tfor s != \"\" {\n\t\ts = strings.TrimSpace(s)\n\t\tvar word string\n\t\tif s[0] == '\"' || s[0] == '`' {\n\t\t\tprefix, err := strconv.QuotedPrefix(s)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ts = s[len(prefix):]\n\t\t\tword, _ = strconv.Unquote(prefix)\n\t\t} else {\n\t\t\tprefix, rest, _ := strings.Cut(s, \" \")\n\t\t\ts = rest\n\t\t\tword = prefix\n\t\t}\n\t\twords = append(words, word)\n\t}\n\treturn words, nil\n}\n"
  },
  {
    "path": "cmd/deadcode/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nThe deadcode command reports unreachable functions in Go programs.\n\n\tUsage: deadcode [flags] package...\n\nThe deadcode command loads a Go program from source then uses Rapid\nType Analysis (RTA) to build a call graph of all the functions\nreachable from the program's main function. Any functions that are not\nreachable are reported as dead code, grouped by package.\n\nPackages are expressed in the notation of 'go list' (or other\nunderlying build system if you are using an alternative\ngolang.org/x/go/packages driver). Only executable (main) packages are\nconsidered starting points for the analysis.\n\nThe -test flag causes it to analyze test executables too. Tests\nsometimes make use of functions that would otherwise appear to be dead\ncode, and public API functions reported as dead with -test indicate\npossible gaps in your test coverage. Bear in mind that an Example test\nfunction without an \"Output:\" comment is merely documentation:\nit is dead code, and does not contribute coverage.\n\nThe -filter flag restricts results to packages that match the provided\nregular expression; its default value matches the listed packages and any other\npackages belonging to the same modules. Use -filter= to display all results.\n\nExample: show all dead code within the gopls module:\n\n\t$ deadcode -test golang.org/x/tools/gopls/...\n\nThe analysis can soundly analyze dynamic calls though func values,\ninterface methods, and reflection. However, it does not currently\nunderstand the aliasing created by //go:linkname directives, so it\nwill fail to recognize that calls to a linkname-annotated function\nwith no body in fact dispatch to the function named in the annotation.\nThis may result in the latter function being spuriously reported as dead.\n\nBy default, the tool does not report dead functions in generated files,\nas determined by the special comment described in\nhttps://go.dev/s/generatedcode. Use the -generated flag to include them.\n\nThe tool also does not report marker interface methods by default.\nMarker interface methods are typically used to create compile-time constraints\nto ensure that only specific types can implement a particular interface.\nThese methods have no other functionality (empty function body) and are never invoked.\nAlthough marker interface methods are technically unreachable, removing them would break\nthe interface implementation. Hence, the tool excludes them from the report.\n\nIn any case, just because a function is reported as dead does not mean\nit is unconditionally safe to delete it. For example, a dead function\nmay be referenced by another dead function, and a dead method may be\nrequired to satisfy an interface that is never called.\nSome judgement is required.\n\nThe analysis is valid only for a single GOOS/GOARCH/-tags configuration,\nso a function reported as dead may be live in a different configuration.\nConsider running the tool once for each configuration of interest.\nConsider using a line-oriented output format (see below) to make it\neasier to compute the intersection of results across all runs.\n\n# Output\n\nThe command supports three output formats.\n\nWith no flags, the command prints the name and location of each dead\nfunction in the form of a typical compiler diagnostic, for example:\n\n\t$ deadcode -f='{{range .Funcs}}{{println .Position}}{{end}}' -test ./gopls/...\n\tgopls/internal/protocol/command.go:1206:6: unreachable func: openClientEditor\n\tgopls/internal/template/parse.go:414:18: unreachable func: Parsed.WriteNode\n\tgopls/internal/template/parse.go:419:18: unreachable func: wrNode.writeNode\n\nWith the -json flag, the command prints an array of Package\nobjects, as defined by the JSON schema (see below).\n\nWith the -f=template flag, the command executes the specified template\non each Package record. So, this template shows dead functions grouped\nby package:\n\n\t$ deadcode -f='{{println .Path}}{{range .Funcs}}{{printf \"\\t%s\\n\" .Name}}{{end}}{{println}}' -test ./gopls/...\n\tgolang.org/x/tools/gopls/internal/lsp\n\t\topenClientEditor\n\n\tgolang.org/x/tools/gopls/internal/template\n\t\tParsed.WriteNode\n\t\twrNode.writeNode\n\n# Why is a function not dead?\n\nThe -whylive=function flag explain why the named function is not dead\nby showing an arbitrary shortest path to it from one of the main functions.\n(To enumerate the functions in a program, or for more sophisticated\ncall graph queries, use golang.org/x/tools/cmd/callgraph.)\n\nFully static call paths are preferred over paths involving dynamic\nedges, even if longer. Paths starting from a non-test package are\npreferred over those from tests. Paths from main functions are\npreferred over paths from init functions.\n\nThe result is a list of Edge objects (see JSON schema below).\nAgain, the -json and -f=template flags may be used to control\nthe formatting of the list of Edge objects.\nThe default format shows, for each edge in the path, whether the call\nis static or dynamic, and its source line number. For example:\n\n\t$ deadcode -whylive=bytes.Buffer.String -test ./cmd/deadcode/...\n\t                 golang.org/x/tools/cmd/deadcode.main\n\tstatic@L0117 --> golang.org/x/tools/go/packages.Load\n\tstatic@L0262 --> golang.org/x/tools/go/packages.defaultDriver\n\tstatic@L0305 --> golang.org/x/tools/go/packages.goListDriver\n\tstatic@L0153 --> golang.org/x/tools/go/packages.goListDriver$1\n\tstatic@L0154 --> golang.org/x/tools/go/internal/packagesdriver.GetSizesForArgsGolist\n\tstatic@L0044 --> bytes.Buffer.String\n\n# JSON schema\n\n\ttype Package struct {\n\t\tName  string       // declared name\n\t\tPath  string       // full import path\n\t\tFuncs []Function   // list of dead functions within it\n\t}\n\n\ttype Function struct {\n\t\tName      string   // name (sans package qualifier)\n\t\tPosition  Position // file/line/column of function declaration\n\t\tGenerated bool     // function is declared in a generated .go file\n\t\tMarker    bool     // function is a marker interface method\n\t}\n\n\ttype Edge struct {\n\t\tInitial  string    // initial entrypoint (main or init); first edge only\n\t\tKind     string    // = static | dynamic\n\t\tPosition Position  // file/line/column of call site\n\t\tCallee   string    // target of the call\n\t}\n\n\ttype Position struct {\n\t\tFile      string   // name of file\n\t\tLine, Col int      // line and byte index, both 1-based\n\t}\n*/\npackage main\n"
  },
  {
    "path": "cmd/deadcode/testdata/basic.txtar",
    "content": "# Test of basic functionality.\n\n deadcode -filter= example.com\n\n want \"T.Goodbye\"\n want \"T.Goodbye2\"\n want \"T.Goodbye3\"\n!want \"T.Hello\"\n want \"unreferenced\"\n\n want \"Scanf\"\n want \"Printf\"\n!want \"Println\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\ntype T int\n\nfunc main() {\n\tvar x T\n\tx.Hello()\n}\n\nfunc (T) Hello() { fmt.Println(\"hello\") }\nfunc (T) Goodbye() { fmt.Println(\"goodbye\") }\nfunc (*T) Goodbye2() { fmt.Println(\"goodbye2\") }\nfunc (*A) Goodbye3() { fmt.Println(\"goodbye3\") }\n\ntype A = T\n\nfunc unreferenced() {}"
  },
  {
    "path": "cmd/deadcode/testdata/filterflag.txtar",
    "content": "# Test of -filter flag.\n\n deadcode -filter=other.net example.com\n\n want `other.net`\n want `Dead`\n!want `Live`\n\n!want `example.com`\n!want `unreferenced`\n\n-- go.work --\nuse example.com\nuse other.net\n\n-- example.com/go.mod --\nmodule example.com\ngo 1.18\n\n-- example.com/main.go --\npackage main\n\nimport \"other.net\"\n\nfunc main() {\n\tother.Live()\n}\n\nfunc unreferenced() {}\n\n-- other.net/go.mod --\nmodule other.net\ngo 1.18\n\n-- other.net/other.go --\npackage other\n\nfunc Live() {}\nfunc Dead() {}\n"
  },
  {
    "path": "cmd/deadcode/testdata/generated.txtar",
    "content": "# Test of -generated flag output.\n\n deadcode \"-f={{range .Funcs}}{{$.Name}}.{{.Name}}{{end}}\" example.com\n!want \"main.main\"\n want \"main.Dead1\"\n!want \"main.Dead2\"\n\n deadcode \"-f={{range .Funcs}}{{$.Name}}.{{.Name}}{{end}}\" -generated example.com\n!want \"main.main\"\n want \"main.Dead1\"\n want \"main.Dead2\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\nfunc main() {}\nfunc Dead1() {}\n\n-- gen.go --\n// Code generated by hand. DO NOT EDIT.\n\npackage main\n\nfunc Dead2() {}"
  },
  {
    "path": "cmd/deadcode/testdata/issue65915.txtar",
    "content": "# Regression test for issue 65915: the enumeration of source-level\n# functions used the flawed ssautil.AllFunctions, causing it to\n# miss some unexported ones.\n\n deadcode -filter= example.com\n\n want \"unreachable func: example.UnUsed\"\n want \"unreachable func: example.unUsed\"\n want \"unreachable func: PublicExample.UnUsed\"\n want \"unreachable func: PublicExample.unUsed\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\ntype example struct{}\n\nfunc (e example) UnUsed() {}\n\nfunc (e example) Used() {}\n\nfunc (e example) unUsed() {}\n\nfunc (e example) used() {}\n\ntype PublicExample struct{}\n\nfunc (p PublicExample) UnUsed() {}\n\nfunc (p PublicExample) Used() {}\n\nfunc (p PublicExample) unUsed() {}\n\nfunc (p PublicExample) used() {}\n\nfunc main() {\n\texample{}.Used()\n\texample{}.used()\n\tPublicExample{}.Used()\n\tPublicExample{}.used()\n}\n"
  },
  {
    "path": "cmd/deadcode/testdata/issue67915.txt",
    "content": "# Test of -whylive with reflective call\n# (regression test for golang/go#67915).\n\n# The live function is reached via reflection:\n\n deadcode example.com\n want \"unreachable func: dead\"\n!want \"unreachable func: live\"\n\n# Reflective calls have Edge.Site=nil, which formerly led to a crash\n# when -whylive would compute its position. Now it has NoPos.\n\n deadcode -whylive=example.com.live example.com\n want \"                  example.com.main\"\n want \" static@L0006 --> reflect.Value.Call\"\n want \"dynamic@L0000 --> example.com.live\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\nimport \"reflect\"\n\nfunc main() {\n\treflect.ValueOf(live).Call(nil)\n}\n\nfunc live() {\n\tprintln(\"hello\")\n}\n\nfunc dead() {\n\tprintln(\"goodbye\")\n}\n"
  },
  {
    "path": "cmd/deadcode/testdata/issue73652.txtar",
    "content": "# Test deadcode usage under go.work.\n\n deadcode ./svc/... ./lib/...\n want \"unreachable func: A\"\n\n# different order of path under the same go.work should behave the same.\n\n deadcode ./svc/... ./lib/...\n want \"unreachable func: A\"\n\n\n-- go.work --\ngo 1.18\n\nuse (\n\t./lib\n\t./svc\n)\n\n-- lib/go.mod --\nmodule lib.com\n\ngo 1.18\n\n-- lib/a/a.go --\npackage a\n\nfunc A() {}\n\n-- svc/go.mod --\nmodule svc.com\n\ngo 1.18\n\n-- svc/s/main.go --\npackage main\n\nfunc main() { println(\"main\") }\n\n"
  },
  {
    "path": "cmd/deadcode/testdata/jsonflag.txtar",
    "content": "# Very minimal test of -json flag.\n\ndeadcode -json example.com/p\n\n want `\"Path\": \"example.com/p\",`\n want `\"Name\": \"DeadFunc\",`\n want `\"Generated\": false`\n want `\"Line\": 5,`\n want `\"Col\": 6`\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- p/p.go --\npackage main\n\nfunc main() {}\n\nfunc DeadFunc() {}\n\ntype T int\nfunc (*T) DeadMethod() {}"
  },
  {
    "path": "cmd/deadcode/testdata/lineflag.txtar",
    "content": "# Test of line-oriented output.\n\n deadcode `-f={{range .Funcs}}{{printf \"%s: %s.%s\\n\" .Position $.Path .Name}}{{end}}` -filter= example.com\n\n want \"main.go:13:10: example.com.T.Goodbye\"\n!want \"example.com.T.Hello\"\n want \"main.go:15:6: example.com.unreferenced\"\n\n want \"fmt.Scanf\"\n want \"fmt.Printf\"\n!want \"fmt.Println\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\ntype T int\n\nfunc main() {\n\tvar x T\n\tx.Hello()\n}\n\nfunc (T) Hello() { fmt.Println(\"hello\") }\nfunc (T) Goodbye() { fmt.Println(\"goodbye\") }\n\nfunc unreferenced() {}"
  },
  {
    "path": "cmd/deadcode/testdata/marker.txtar",
    "content": "# Test of marker suppression functionality.\n# Deadcode should not identify marker interface methods as unreachable\n\n deadcode -filter= example.com\n!want \"T.isMarker\"\nwant \"R.isNotMarker\"\n!want \"P.greet\"\nwant \"Q.greet\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\nimport \"fmt\"\n\n// Marker method: implements interface, unexported, no params, no results, empty body\ntype Marker interface {\n    isMarker()\n}\ntype T struct{}\n\nfunc (t *T) isMarker() {}\n\n// Not marker method: does not implement interface\ntype R struct {}\nfunc (r *R) isNotMarker() {}\n\n// Ensure that it still reports valid interface methods\n// when unused\ntype Greeter interface {\n    greet()\n}\ntype P struct {}\nfunc (p *P) greet() {fmt.Println(\"P: hello\")}\ntype Q struct {}\nfunc (q *Q) greet() {fmt.Println(\"Q: hello\")} // this method should be reported\n\nfunc main () {\n    var p P\n    p.greet()\n}"
  },
  {
    "path": "cmd/deadcode/testdata/testflag.txtar",
    "content": "# Test of -test flag.\n\ndeadcode -test -filter=example.com example.com/p\n\n want \"Dead\"\n!want \"Live1\"\n!want \"Live2\"\n\n want \"ExampleDead\"\n!want \"ExampleLive\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- p/p.go --\npackage p\n\nfunc Live1() {}\nfunc Live2() {}\nfunc Dead() {}\n\n-- p/p_test.go --\npackage p_test\n\nimport \"example.com/p\"\n\nimport \"testing\"\n\nfunc Test(t *testing.T) {\n\tp.Live1()\n}\n\nfunc ExampleLive() {\n\tp.Live2()\n\t// Output:\n}\n\n// A test Example function without an \"Output:\" comment is never executed.\nfunc ExampleDead() {\n\tp.Dead()\n}"
  },
  {
    "path": "cmd/deadcode/testdata/whylive.txtar",
    "content": "# Test of -whylive flag.\n\n# The -whylive argument must be live.\n\n!deadcode -whylive=example.com.d example.com\n want \"function example.com.d is dead code\"\n\n# A fully static path is preferred, even if longer.\n\n deadcode -whylive=example.com.c example.com\n want \"                  example.com.main\"\n want \" static@L0004 --> example.com.a\"\n want \" static@L0009 --> example.com.b\"\n want \" static@L0012 --> example.com.c\"\n\n# Dynamic edges are followed if necessary.\n# (Note that main is preferred over init.)\n\n deadcode -whylive=example.com.f example.com\n want \"                  example.com.main\"\n want \"dynamic@L0006 --> example.com.e\"\n want \" static@L0017 --> example.com.f\"\n\n# Degenerate case where target is itself a root.\n\n!deadcode -whylive=example.com.main example.com\n want \"example.com.main is a root\"\n\n# Test of path through (*T).m method wrapper.\n\n deadcode -whylive=example.com/p.live example.com/p\n want \"                 example.com/p.main\"\n want \"static@L0006 --> example.com/p.E.Error\"\n want \"static@L0010 --> example.com/p.live\"\n\n# Test of path through (I).m interface method wrapper (thunk).\n\n deadcode -whylive=example.com/q.live example.com/q\n want \"                 example.com/q.main\"\n want \"static@L0006 --> example.com/q.E.Error\"\n want \"static@L0010 --> example.com/q.live\"\n\n# Test of path through synthetic package initializer,\n# a declared package initializer, and its anonymous function.\n\n deadcode -whylive=example.com/q.live2 example.com/q\n want \"                 example.com/q.init\"\n want \"static@L0000 --> example.com/q.init#1\"\n want \"static@L0016 --> example.com/q.init#1$1\"\n want \"static@L0015 --> example.com/q.live2\"\n\n# Test of path through synthetic package initializer,\n# and a global var initializer.\n\n deadcode -whylive=example.com/r.live example.com/r\n want \"                 example.com/r.init\"\n want \"static@L0007 --> example.com/r.init$1\"\n want \"static@L0006 --> example.com/r.live\"\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- main.go --\npackage main\n\nfunc main() {\n\ta()\n\tprintln(c, e) // c, e are address-taken\n\t(func ())(nil)() // potential dynamic call to c, e\n}\nfunc a() {\n\tb()\n}\nfunc b() {\n\tc()\n}\nfunc c()\nfunc d()\nfunc e() {\n\tf()\n}\nfunc f()\n\nfunc init() {\n     (func ())(nil)() // potential dynamic call to c, e\n}\n\n-- p/p.go --\npackage main\n\nfunc main() {\n\tf := (*E).Error\n\tvar e E\n\tf(&e)\n}\n\ntype E int\nfunc (E) Error() string { return live() }\n\nfunc live() string\n\n-- q/q.go --\npackage main\n\nfunc main() {\n\tf := error.Error\n\tvar e E\n\tf(e)\n}\n\ntype E int\nfunc (E) Error() string { return live() }\n\nfunc live() string\n\nfunc init() {\n\tf := func() { live2() }\n\tf()\n}\n\nfunc live2()\n\n-- r/r.go --\npackage main\n\nfunc main() {}\n\nvar x = func() int {\n\treturn live()\n}()\n\nfunc live() int\n"
  },
  {
    "path": "cmd/digraph/digraph.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main // import \"golang.org/x/tools/cmd/digraph\"\n\n// TODO(adonovan):\n// - support input files other than stdin\n// - support alternative formats (AT&T GraphViz, CSV, etc),\n//   a comment syntax, etc.\n// - allow queries to nest, like Blaze query language.\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t_ \"embed\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n)\n\nfunc usage() {\n\t// Extract the content of the /* ... */ comment in doc.go.\n\t_, after, _ := strings.Cut(doc, \"/*\")\n\tdoc, _, _ := strings.Cut(after, \"*/\")\n\tio.WriteString(flag.CommandLine.Output(), doc)\n\tflag.PrintDefaults()\n\n\tos.Exit(2)\n}\n\n//go:embed doc.go\nvar doc string\n\nfunc main() {\n\tflag.Usage = usage\n\tflag.Parse()\n\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\tusage()\n\t}\n\n\tif err := digraph(args[0], args[1:]); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"digraph: %s\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\ntype nodelist []string\n\nfunc (l nodelist) println(sep string) {\n\tfor i, node := range l {\n\t\tif i > 0 {\n\t\t\tfmt.Fprint(stdout, sep)\n\t\t}\n\t\tfmt.Fprint(stdout, node)\n\t}\n\tfmt.Fprintln(stdout)\n}\n\ntype nodeset map[string]bool\n\nfunc singleton(x string) nodeset { return nodeset{x: true} }\n\nfunc (s nodeset) sort() nodelist {\n\tnodes := make(nodelist, len(s))\n\tvar i int\n\tfor node := range s {\n\t\tnodes[i] = node\n\t\ti++\n\t}\n\tsort.Strings(nodes)\n\treturn nodes\n}\n\nfunc (s nodeset) addAll(x nodeset) {\n\tfor node := range x {\n\t\ts[node] = true\n\t}\n}\n\n// A graph maps nodes to the non-nil set of their immediate successors.\ntype graph map[string]nodeset\n\nfunc (g graph) addNode(node string) nodeset {\n\tedges := g[node]\n\tif edges == nil {\n\t\tedges = make(nodeset)\n\t\tg[node] = edges\n\t}\n\treturn edges\n}\n\nfunc (g graph) addEdges(from string, to ...string) {\n\tedges := g.addNode(from)\n\tfor _, to := range to {\n\t\tg.addNode(to)\n\t\tedges[to] = true\n\t}\n}\n\nfunc (g graph) nodelist() nodelist {\n\tnodes := make(nodeset)\n\tfor node := range g {\n\t\tnodes[node] = true\n\t}\n\treturn nodes.sort()\n}\n\nfunc (g graph) reachableFrom(roots nodeset) nodeset {\n\tseen := make(nodeset)\n\tvar visit func(node string)\n\tvisit = func(node string) {\n\t\tif !seen[node] {\n\t\t\tseen[node] = true\n\t\t\tfor e := range g[node] {\n\t\t\t\tvisit(e)\n\t\t\t}\n\t\t}\n\t}\n\tfor root := range roots {\n\t\tvisit(root)\n\t}\n\treturn seen\n}\n\nfunc (g graph) transpose() graph {\n\trev := make(graph)\n\tfor node, edges := range g {\n\t\trev.addNode(node)\n\t\tfor succ := range edges {\n\t\t\trev.addEdges(succ, node)\n\t\t}\n\t}\n\treturn rev\n}\n\nfunc (g graph) sccs() []nodeset {\n\t// Kosaraju's algorithm---Tarjan is overkill here.\n\n\t// Forward pass.\n\tS := make(nodelist, 0, len(g)) // postorder stack\n\tseen := make(nodeset)\n\tvar visit func(node string)\n\tvisit = func(node string) {\n\t\tif !seen[node] {\n\t\t\tseen[node] = true\n\t\t\tfor e := range g[node] {\n\t\t\t\tvisit(e)\n\t\t\t}\n\t\t\tS = append(S, node)\n\t\t}\n\t}\n\tfor node := range g {\n\t\tvisit(node)\n\t}\n\n\t// Reverse pass.\n\trev := g.transpose()\n\tvar scc nodeset\n\tseen = make(nodeset)\n\tvar rvisit func(node string)\n\trvisit = func(node string) {\n\t\tif !seen[node] {\n\t\t\tseen[node] = true\n\t\t\tscc[node] = true\n\t\t\tfor e := range rev[node] {\n\t\t\t\trvisit(e)\n\t\t\t}\n\t\t}\n\t}\n\tvar sccs []nodeset\n\tfor len(S) > 0 {\n\t\ttop := S[len(S)-1]\n\t\tS = S[:len(S)-1] // pop\n\t\tif !seen[top] {\n\t\t\tscc = make(nodeset)\n\t\t\trvisit(top)\n\t\t\tif len(scc) == 1 && !g[top][top] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsccs = append(sccs, scc)\n\t\t}\n\t}\n\treturn sccs\n}\n\nfunc (g graph) allpaths(from, to string) error {\n\t// We intersect the forward closure of 'from' with\n\t// the reverse closure of 'to'. This is not the most\n\t// efficient implementation, but it's the clearest,\n\t// and the previous one had bugs.\n\tseen := g.reachableFrom(singleton(from))\n\trev := g.transpose().reachableFrom(singleton(to))\n\tfor n := range seen {\n\t\tif !rev[n] {\n\t\t\tdelete(seen, n)\n\t\t}\n\t}\n\n\t// For each marked node, collect its marked successors.\n\tvar edges []string\n\tfor n := range seen {\n\t\tfor succ := range g[n] {\n\t\t\tif seen[succ] {\n\t\t\t\tedges = append(edges, n+\" \"+succ)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Sort (so that this method is deterministic) and print edges.\n\tsort.Strings(edges)\n\tfor _, e := range edges {\n\t\tfmt.Fprintln(stdout, e)\n\t}\n\n\treturn nil\n}\n\nfunc (g graph) somepath(from, to string) error {\n\t// Search breadth-first so that we return a minimal path.\n\n\t// A path is a linked list whose head is a candidate \"to\" node\n\t// and whose tail is the path ending in the \"from\" node.\n\ttype path struct {\n\t\tnode string\n\t\ttail *path\n\t}\n\n\tseen := singleton(from)\n\n\tvar queue []*path\n\tqueue = append(queue, &path{node: from, tail: nil})\n\tfor len(queue) > 0 {\n\t\tp := queue[0]\n\t\tqueue = queue[1:]\n\n\t\tif p.node == to {\n\t\t\t// Found a path. Print, tail first.\n\t\t\tvar print func(p *path)\n\t\t\tprint = func(p *path) {\n\t\t\t\tif p.tail != nil {\n\t\t\t\t\tprint(p.tail)\n\t\t\t\t\tfmt.Fprintln(stdout, p.tail.node+\" \"+p.node)\n\t\t\t\t}\n\t\t\t}\n\t\t\tprint(p)\n\t\t\treturn nil\n\t\t}\n\n\t\tfor succ := range g[p.node] {\n\t\t\tif !seen[succ] {\n\t\t\t\tseen[succ] = true\n\t\t\t\tqueue = append(queue, &path{node: succ, tail: p})\n\t\t\t}\n\t\t}\n\t}\n\treturn fmt.Errorf(\"no path from %q to %q\", from, to)\n}\n\nfunc (g graph) toDot(w *bytes.Buffer) {\n\tfmt.Fprintln(w, \"digraph {\")\n\tfor _, src := range g.nodelist() {\n\t\tfor _, dst := range g[src].sort() {\n\t\t\t// Dot's quoting rules appear to align with Go's for escString,\n\t\t\t// which is the syntax of node IDs. Labels require significantly\n\t\t\t// more quoting, but that appears not to be necessary if the node ID\n\t\t\t// is implicitly used as the label.\n\t\t\tfmt.Fprintf(w, \"\\t%q -> %q;\\n\", src, dst)\n\t\t}\n\t}\n\tfmt.Fprintln(w, \"}\")\n}\n\nfunc parse(rd io.Reader) (graph, error) {\n\tg := make(graph)\n\n\tvar linenum int\n\t// We avoid bufio.Scanner as it imposes a (configurable) limit\n\t// on line length, whereas Reader.ReadString does not.\n\tin := bufio.NewReader(rd)\n\tfor {\n\t\tlinenum++\n\t\tline, err := in.ReadString('\\n')\n\t\teof := false\n\t\tif err == io.EOF {\n\t\t\teof = true\n\t\t} else if err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Split into words, honoring double-quotes per Go spec.\n\t\twords, err := split(line)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"at line %d: %v\", linenum, err)\n\t\t}\n\t\tif len(words) > 0 {\n\t\t\tg.addEdges(words[0], words[1:]...)\n\t\t}\n\t\tif eof {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn g, nil\n}\n\n// Overridable for redirection.\nvar stdin io.Reader = os.Stdin\nvar stdout io.Writer = os.Stdout\n\nfunc digraph(cmd string, args []string) error {\n\t// Parse the input graph.\n\tg, err := parse(stdin)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Parse the command line.\n\tswitch cmd {\n\tcase \"nodes\":\n\t\tif len(args) != 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph nodes\")\n\t\t}\n\t\tg.nodelist().println(\"\\n\")\n\n\tcase \"degree\":\n\t\tif len(args) != 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph degree\")\n\t\t}\n\t\tnodes := make(nodeset)\n\t\tfor node := range g {\n\t\t\tnodes[node] = true\n\t\t}\n\t\trev := g.transpose()\n\t\tfor _, node := range nodes.sort() {\n\t\t\tfmt.Fprintf(stdout, \"%d\\t%d\\t%s\\n\", len(rev[node]), len(g[node]), node)\n\t\t}\n\n\tcase \"transpose\":\n\t\tif len(args) != 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph transpose\")\n\t\t}\n\t\tvar revEdges []string\n\t\tfor node, succs := range g.transpose() {\n\t\t\tfor succ := range succs {\n\t\t\t\trevEdges = append(revEdges, fmt.Sprintf(\"%s %s\", node, succ))\n\t\t\t}\n\t\t}\n\t\tsort.Strings(revEdges) // make output deterministic\n\t\tfor _, e := range revEdges {\n\t\t\tfmt.Fprintln(stdout, e)\n\t\t}\n\n\tcase \"succs\", \"preds\":\n\t\tif len(args) == 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph %s <node> ... \", cmd)\n\t\t}\n\t\tg := g\n\t\tif cmd == \"preds\" {\n\t\t\tg = g.transpose()\n\t\t}\n\t\tresult := make(nodeset)\n\t\tfor _, root := range args {\n\t\t\tedges := g[root]\n\t\t\tif edges == nil {\n\t\t\t\treturn fmt.Errorf(\"no such node %q\", root)\n\t\t\t}\n\t\t\tresult.addAll(edges)\n\t\t}\n\t\tresult.sort().println(\"\\n\")\n\n\tcase \"forward\", \"reverse\":\n\t\tif len(args) == 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph %s <node> ... \", cmd)\n\t\t}\n\t\troots := make(nodeset)\n\t\tfor _, root := range args {\n\t\t\tif g[root] == nil {\n\t\t\t\treturn fmt.Errorf(\"no such node %q\", root)\n\t\t\t}\n\t\t\troots[root] = true\n\t\t}\n\t\tg := g\n\t\tif cmd == \"reverse\" {\n\t\t\tg = g.transpose()\n\t\t}\n\t\tg.reachableFrom(roots).sort().println(\"\\n\")\n\n\tcase \"somepath\":\n\t\tif len(args) != 2 {\n\t\t\treturn fmt.Errorf(\"usage: digraph somepath <from> <to>\")\n\t\t}\n\t\tfrom, to := args[0], args[1]\n\t\tif g[from] == nil {\n\t\t\treturn fmt.Errorf(\"no such 'from' node %q\", from)\n\t\t}\n\t\tif g[to] == nil {\n\t\t\treturn fmt.Errorf(\"no such 'to' node %q\", to)\n\t\t}\n\t\tif err := g.somepath(from, to); err != nil {\n\t\t\treturn err\n\t\t}\n\n\tcase \"allpaths\":\n\t\tif len(args) != 2 {\n\t\t\treturn fmt.Errorf(\"usage: digraph allpaths <from> <to>\")\n\t\t}\n\t\tfrom, to := args[0], args[1]\n\t\tif g[from] == nil {\n\t\t\treturn fmt.Errorf(\"no such 'from' node %q\", from)\n\t\t}\n\t\tif g[to] == nil {\n\t\t\treturn fmt.Errorf(\"no such 'to' node %q\", to)\n\t\t}\n\t\tif err := g.allpaths(from, to); err != nil {\n\t\t\treturn err\n\t\t}\n\n\tcase \"sccs\":\n\t\tif len(args) != 0 {\n\t\t\treturn fmt.Errorf(\"usage: digraph sccs\")\n\t\t}\n\t\tbuf := new(bytes.Buffer)\n\t\toldStdout := stdout\n\t\tstdout = buf\n\t\tfor _, scc := range g.sccs() {\n\t\t\tscc.sort().println(\" \")\n\t\t}\n\t\tlines := strings.SplitAfter(buf.String(), \"\\n\")\n\t\tsort.Strings(lines)\n\t\tstdout = oldStdout\n\t\tio.WriteString(stdout, strings.Join(lines, \"\"))\n\n\tcase \"scc\":\n\t\tif len(args) != 1 {\n\t\t\treturn fmt.Errorf(\"usage: digraph scc <node>\")\n\t\t}\n\t\tnode := args[0]\n\t\tif g[node] == nil {\n\t\t\treturn fmt.Errorf(\"no such node %q\", node)\n\t\t}\n\t\tfor _, scc := range g.sccs() {\n\t\t\tif scc[node] {\n\t\t\t\tscc.sort().println(\"\\n\")\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\tcase \"focus\":\n\t\tif len(args) != 1 {\n\t\t\treturn fmt.Errorf(\"usage: digraph focus <node>\")\n\t\t}\n\t\tnode := args[0]\n\t\tif g[node] == nil {\n\t\t\treturn fmt.Errorf(\"no such node %q\", node)\n\t\t}\n\n\t\tedges := make(map[string]struct{})\n\t\tfor from := range g.reachableFrom(singleton(node)) {\n\t\t\tfor to := range g[from] {\n\t\t\t\tedges[fmt.Sprintf(\"%s %s\", from, to)] = struct{}{}\n\t\t\t}\n\t\t}\n\n\t\tgtrans := g.transpose()\n\t\tfor from := range gtrans.reachableFrom(singleton(node)) {\n\t\t\tfor to := range gtrans[from] {\n\t\t\t\tedges[fmt.Sprintf(\"%s %s\", to, from)] = struct{}{}\n\t\t\t}\n\t\t}\n\n\t\tedgesSorted := make([]string, 0, len(edges))\n\t\tfor e := range edges {\n\t\t\tedgesSorted = append(edgesSorted, e)\n\t\t}\n\t\tsort.Strings(edgesSorted)\n\t\tfmt.Fprintln(stdout, strings.Join(edgesSorted, \"\\n\"))\n\n\tcase \"to\":\n\t\tif len(args) != 1 || args[0] != \"dot\" {\n\t\t\treturn fmt.Errorf(\"usage: digraph to dot\")\n\t\t}\n\t\tvar b bytes.Buffer\n\t\tg.toDot(&b)\n\t\tstdout.Write(b.Bytes())\n\n\tdefault:\n\t\treturn fmt.Errorf(\"no such command %q\", cmd)\n\t}\n\n\treturn nil\n}\n\n// -- Utilities --------------------------------------------------------\n\n// split splits a line into words, which are generally separated by\n// spaces, but Go-style double-quoted string literals are also supported.\n// (This approximates the behaviour of the Bourne shell.)\n//\n//\t`one \"two three\"` -> [\"one\" \"two three\"]\n//\t`a\"\\n\"b` -> [\"a\\nb\"]\nfunc split(line string) ([]string, error) {\n\tvar (\n\t\twords   []string\n\t\tinWord  bool\n\t\tcurrent bytes.Buffer\n\t)\n\n\tfor len(line) > 0 {\n\t\tr, size := utf8.DecodeRuneInString(line)\n\t\tif unicode.IsSpace(r) {\n\t\t\tif inWord {\n\t\t\t\twords = append(words, current.String())\n\t\t\t\tcurrent.Reset()\n\t\t\t\tinWord = false\n\t\t\t}\n\t\t} else if r == '\"' {\n\t\t\tvar ok bool\n\t\t\tsize, ok = quotedLength(line)\n\t\t\tif !ok {\n\t\t\t\treturn nil, errors.New(\"invalid quotation\")\n\t\t\t}\n\t\t\ts, err := strconv.Unquote(line[:size])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcurrent.WriteString(s)\n\t\t\tinWord = true\n\t\t} else {\n\t\t\tcurrent.WriteRune(r)\n\t\t\tinWord = true\n\t\t}\n\t\tline = line[size:]\n\t}\n\tif inWord {\n\t\twords = append(words, current.String())\n\t}\n\treturn words, nil\n}\n\n// quotedLength returns the length in bytes of the prefix of input that\n// contain a possibly-valid double-quoted Go string literal.\n//\n// On success, n is at least two (\"\"); input[:n] may be passed to\n// strconv.Unquote to interpret its value, and input[n:] contains the\n// rest of the input.\n//\n// On failure, quotedLength returns false, and the entire input can be\n// passed to strconv.Unquote if an informative error message is desired.\n//\n// quotedLength does not and need not detect all errors, such as\n// invalid hex or octal escape sequences, since it assumes\n// strconv.Unquote will be applied to the prefix.  It guarantees only\n// that if there is a prefix of input containing a valid string literal,\n// its length is returned.\n//\n// TODO(adonovan): move this into a strconv-like utility package.\nfunc quotedLength(input string) (n int, ok bool) {\n\tvar offset int\n\n\t// next returns the rune at offset, or -1 on EOF.\n\t// offset advances to just after that rune.\n\tnext := func() rune {\n\t\tif offset < len(input) {\n\t\t\tr, size := utf8.DecodeRuneInString(input[offset:])\n\t\t\toffset += size\n\t\t\treturn r\n\t\t}\n\t\treturn -1\n\t}\n\n\tif next() != '\"' {\n\t\treturn // error: not a quotation\n\t}\n\n\tfor {\n\t\tr := next()\n\t\tif r == '\\n' || r < 0 {\n\t\t\treturn // error: string literal not terminated\n\t\t}\n\t\tif r == '\"' {\n\t\t\treturn offset, true // success\n\t\t}\n\t\tif r == '\\\\' {\n\t\t\tvar skip int\n\t\t\tswitch next() {\n\t\t\tcase 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\\\', '\"':\n\t\t\t\tskip = 0\n\t\t\tcase '0', '1', '2', '3', '4', '5', '6', '7':\n\t\t\t\tskip = 2\n\t\t\tcase 'x':\n\t\t\t\tskip = 2\n\t\t\tcase 'u':\n\t\t\t\tskip = 4\n\t\t\tcase 'U':\n\t\t\t\tskip = 8\n\t\t\tdefault:\n\t\t\t\treturn // error: invalid escape\n\t\t\t}\n\n\t\t\tfor i := 0; i < skip; i++ {\n\t\t\t\tnext()\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/digraph/digraph_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestDigraph(t *testing.T) {\n\tconst g1 = `\nsocks shoes\nshorts pants\npants belt shoes\nshirt tie sweater\nsweater jacket\nhat\n`\n\n\tconst g2 = `\na b c\nb d\nc d\nd c\ne e\n`\n\n\tfor _, test := range []struct {\n\t\tname  string\n\t\tinput string\n\t\tcmd   string\n\t\targs  []string\n\t\twant  string\n\t}{\n\t\t{\"nodes\", g1, \"nodes\", nil, \"belt\\nhat\\njacket\\npants\\nshirt\\nshoes\\nshorts\\nsocks\\nsweater\\ntie\\n\"},\n\t\t{\"reverse\", g1, \"reverse\", []string{\"jacket\"}, \"jacket\\nshirt\\nsweater\\n\"},\n\t\t{\"transpose\", g1, \"transpose\", nil, \"belt pants\\njacket sweater\\npants shorts\\nshoes pants\\nshoes socks\\nsweater shirt\\ntie shirt\\n\"},\n\t\t{\"forward\", g1, \"forward\", []string{\"socks\"}, \"shoes\\nsocks\\n\"},\n\t\t{\"forward multiple args\", g1, \"forward\", []string{\"socks\", \"sweater\"}, \"jacket\\nshoes\\nsocks\\nsweater\\n\"},\n\t\t{\"scss\", g2, \"sccs\", nil, \"c d\\ne\\n\"},\n\t\t{\"scc\", g2, \"scc\", []string{\"d\"}, \"c\\nd\\n\"},\n\t\t{\"succs\", g2, \"succs\", []string{\"a\"}, \"b\\nc\\n\"},\n\t\t{\"succs-long-token\", g2 + \"x \" + strings.Repeat(\"x\", 96*1024), \"succs\", []string{\"x\"}, strings.Repeat(\"x\", 96*1024) + \"\\n\"},\n\t\t{\"preds\", g2, \"preds\", []string{\"c\"}, \"a\\nd\\n\"},\n\t\t{\"preds multiple args\", g2, \"preds\", []string{\"c\", \"d\"}, \"a\\nb\\nc\\nd\\n\"},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tstdin = strings.NewReader(test.input)\n\t\t\tstdout = new(bytes.Buffer)\n\t\t\tif err := digraph(test.cmd, test.args); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tgot := stdout.(fmt.Stringer).String()\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"digraph(%s, %s) = got %q, want %q\", test.cmd, test.args, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n\n\t// TODO(adonovan):\n\t// - test errors\n}\n\nfunc TestAllpaths(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname string\n\t\tin   string\n\t\tto   string // from is always \"A\"\n\t\twant string\n\t}{\n\t\t{\n\t\t\tname: \"Basic\",\n\t\t\tin:   \"A B\\nB C\",\n\t\t\tto:   \"B\",\n\t\t\twant: \"A B\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Long\",\n\t\t\tin:   \"A B\\nB C\\n\",\n\t\t\tto:   \"C\",\n\t\t\twant: \"A B\\nB C\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Cycle Basic\",\n\t\t\tin:   \"A B\\nB A\",\n\t\t\tto:   \"B\",\n\t\t\twant: \"A B\\nB A\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Cycle Path Out\",\n\t\t\t// A <-> B -> C -> D\n\t\t\tin:   \"A B\\nB A\\nB C\\nC D\",\n\t\t\tto:   \"C\",\n\t\t\twant: \"A B\\nB A\\nB C\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Cycle Path Out Further Out\",\n\t\t\t// A -> B <-> C -> D -> E\n\t\t\tin:   \"A B\\nB C\\nC D\\nC B\\nD E\",\n\t\t\tto:   \"D\",\n\t\t\twant: \"A B\\nB C\\nC B\\nC D\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Two Paths Basic\",\n\t\t\t//           /-> C --\\\n\t\t\t// A -> B --          -> E -> F\n\t\t\t//           \\-> D --/\n\t\t\tin:   \"A B\\nB C\\nC E\\nB D\\nD E\\nE F\",\n\t\t\tto:   \"E\",\n\t\t\twant: \"A B\\nB C\\nB D\\nC E\\nD E\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Two Paths With One Immediately From Start\",\n\t\t\t//      /-> B -+ -> D\n\t\t\t// A --        |\n\t\t\t//      \\-> C <+\n\t\t\tin:   \"A B\\nA C\\nB C\\nB D\",\n\t\t\tto:   \"C\",\n\t\t\twant: \"A B\\nA C\\nB C\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Two Paths Further Up\",\n\t\t\t//      /-> B --\\\n\t\t\t// A --          -> D -> E -> F\n\t\t\t//      \\-> C --/\n\t\t\tin:   \"A B\\nA C\\nB D\\nC D\\nD E\\nE F\",\n\t\t\tto:   \"E\",\n\t\t\twant: \"A B\\nA C\\nB D\\nC D\\nD E\\n\",\n\t\t},\n\t\t{\n\t\t\t// We should include A - C  - D even though it's further up the\n\t\t\t// second path than D (which would already be in the graph by\n\t\t\t// the time we get around to integrating the second path).\n\t\t\tname: \"Two Splits\",\n\t\t\t//      /-> B --\\         /-> E --\\\n\t\t\t// A --           -> D --          -> G -> H\n\t\t\t//      \\-> C --/         \\-> F --/\n\t\t\tin:   \"A B\\nA C\\nB D\\nC D\\nD E\\nD F\\nE G\\nF G\\nG H\",\n\t\t\tto:   \"G\",\n\t\t\twant: \"A B\\nA C\\nB D\\nC D\\nD E\\nD F\\nE G\\nF G\\n\",\n\t\t},\n\t\t{\n\t\t\t// D - E should not be duplicated.\n\t\t\tname: \"Two Paths - Two Splits With Gap\",\n\t\t\t//      /-> B --\\              /-> F --\\\n\t\t\t// A --           -> D -> E --          -> H -> I\n\t\t\t//      \\-> C --/              \\-> G --/\n\t\t\tin:   \"A B\\nA C\\nB D\\nC D\\nD E\\nE F\\nE G\\nF H\\nG H\\nH I\",\n\t\t\tto:   \"H\",\n\t\t\twant: \"A B\\nA C\\nB D\\nC D\\nD E\\nE F\\nE G\\nF H\\nG H\\n\",\n\t\t},\n\t\t{\n\t\t\t// C <--> B --> A --> D <--> E\n\t\t\t//        ⋃\n\t\t\tname: \"non-regression test for #74842\",\n\t\t\tin:   \"A D\\nB A\\nB B\\nB C\\nC B\\nD E\\nE D\",\n\t\t\tto:   \"D\",\n\t\t\twant: \"A D\\nD E\\nE D\\n\",\n\t\t},\n\t\t{\n\t\t\t// A --> B --> D\n\t\t\t//       ^\n\t\t\t//       v\n\t\t\t//       C[123]\n\t\t\tname: \"regression test for #74842\",\n\t\t\tin:   \"A B\\nB C1\\nB C2\\nB C3\\nB D\\nC1 B\\nC2 B\\nC3 B\\n\",\n\t\t\tto:   \"D\",\n\t\t\twant: \"A B\\nB C1\\nB C2\\nB C3\\nB D\\nC1 B\\nC2 B\\nC3 B\\n\",\n\t\t},\n\t\t{\n\t\t\t// A -------> B --> D\n\t\t\t//  \\--> C ---^     |\n\t\t\t//       ^----------+\n\t\t\tname: \"another regression test for #74842\",\n\t\t\tin:   \"A B\\nA C\\nB D\\nC B\\nD C\\n\",\n\t\t\tto:   \"D\",\n\t\t\twant: \"A B\\nA C\\nB D\\nC B\\nD C\\n\",\n\t\t},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tstdin = strings.NewReader(test.in)\n\t\t\tstdout = new(bytes.Buffer)\n\t\t\tif err := digraph(\"allpaths\", []string{\"A\", test.to}); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tgot := stdout.(fmt.Stringer).String()\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"digraph(allpaths, A, %s) = got %q, want %q\", test.to, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSomepath(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname string\n\t\tin   string\n\t\tto   string\n\t\t// somepath is non-deterministic, so we have to provide all the\n\t\t// possible options. Each option is separated with |.\n\t\twantAnyOf string\n\t}{\n\t\t{\n\t\t\tname:      \"Basic\",\n\t\t\tin:        \"A B\\n\",\n\t\t\tto:        \"B\",\n\t\t\twantAnyOf: \"A B\",\n\t\t},\n\t\t{\n\t\t\tname:      \"Basic With Cycle\",\n\t\t\tin:        \"A B\\nB A\",\n\t\t\tto:        \"B\",\n\t\t\twantAnyOf: \"A B\",\n\t\t},\n\t\t{\n\t\t\tname: \"Two Paths\",\n\t\t\t//      /-> B --\\\n\t\t\t// A --          -> D\n\t\t\t//      \\-> C --/\n\t\t\tin:        \"A B\\nA C\\nB D\\nC D\",\n\t\t\tto:        \"D\",\n\t\t\twantAnyOf: \"A B\\nB D|A C\\nC D\",\n\t\t},\n\t\t{\n\t\t\tname: \"Printed path is minimal\",\n\t\t\t// A -> B1->B2->B3 -> E\n\t\t\t// A -> C1->C2 -> E\n\t\t\t// A -> D -> E\n\t\t\tin:        \"A D C1 B1\\nD E\\nC1 C2\\nC2 E\\nB1 B2\\nB2 B3\\nB3 E\",\n\t\t\tto:        \"E\",\n\t\t\twantAnyOf: \"A D\\nD E\",\n\t\t},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tstdin = strings.NewReader(test.in)\n\t\t\tstdout = new(bytes.Buffer)\n\t\t\tif err := digraph(\"somepath\", []string{\"A\", test.to}); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tgot := stdout.(fmt.Stringer).String()\n\t\t\tlines := strings.Split(got, \"\\n\")\n\t\t\tsort.Strings(lines)\n\t\t\tgot = strings.Join(lines[1:], \"\\n\")\n\n\t\t\tvar oneMatch bool\n\t\t\tfor want := range strings.SplitSeq(test.wantAnyOf, \"|\") {\n\t\t\t\tif got == want {\n\t\t\t\t\toneMatch = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !oneMatch {\n\t\t\t\tt.Errorf(\"digraph(somepath, A, %s) = got %q, want any of\\n%s\", test.to, got, test.wantAnyOf)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSplit(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tline string\n\t\twant []string\n\t}{\n\t\t{`one \"2a 2b\" three`, []string{\"one\", \"2a 2b\", \"three\"}},\n\t\t{`one tw\"\\n\\x0a\\u000a\\012\"o three`, []string{\"one\", \"tw\\n\\n\\n\\no\", \"three\"}},\n\t} {\n\t\tgot, err := split(test.line)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"split(%s) failed: %v\", test.line, err)\n\t\t}\n\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\tt.Errorf(\"split(%s) = %v, want %v\", test.line, got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestQuotedLength(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tinput string\n\t\twant  int\n\t}{\n\t\t{`\"abc\"`, 5},\n\t\t{`\"abc\"def`, 5},\n\t\t{`\"abc\\\"d\"ef`, 8}, // \"abc\\\"d\" is consumed, ef is residue\n\t\t{`\"\\012\\n\\x0a\\u000a\\U0000000a\"`, 28},\n\t\t{\"\\\"\\xff\\\"\", 3}, // bad UTF-8 is ok\n\t\t{`\"\\xff\"`, 6},   // hex escape for bad UTF-8 is ok\n\t} {\n\t\tgot, ok := quotedLength(test.input)\n\t\tif !ok {\n\t\t\tgot = 0\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"quotedLength(%s) = %d, want %d\", test.input, got, test.want)\n\t\t}\n\t}\n\n\t// errors\n\tfor _, input := range []string{\n\t\t``,            // not a quotation\n\t\t`a`,           // not a quotation\n\t\t`'a'`,         // not a quotation\n\t\t`\"a`,          // not terminated\n\t\t`\"\\0\"`,        // short octal escape\n\t\t`\"\\x1\"`,       // short hex escape\n\t\t`\"\\u000\"`,     // short \\u escape\n\t\t`\"\\U0000000\"`, // short \\U escape\n\t\t`\"\\k\"`,        // invalid escape\n\t\t\"\\\"ab\\nc\\\"\",   // newline\n\t} {\n\t\tif n, ok := quotedLength(input); ok {\n\t\t\tt.Errorf(\"quotedLength(%s) = %d, want !ok\", input, n)\n\t\t}\n\t}\n}\n\nfunc TestFocus(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname  string\n\t\tin    string\n\t\tfocus string\n\t\twant  string\n\t}{\n\t\t{\n\t\t\tname:  \"Basic\",\n\t\t\tin:    \"A B\",\n\t\t\tfocus: \"B\",\n\t\t\twant:  \"A B\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Some Nodes Not Included\",\n\t\t\t// C does not have a path involving B, and should not be included\n\t\t\t// in the output.\n\t\t\tin:    \"A B\\nA C\",\n\t\t\tfocus: \"B\",\n\t\t\twant:  \"A B\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Cycle In Path\",\n\t\t\t// A <-> B -> C\n\t\t\tin:    \"A B\\nB A\\nB C\",\n\t\t\tfocus: \"C\",\n\t\t\twant:  \"A B\\nB A\\nB C\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Cycle Out Of Path\",\n\t\t\t// C <- A <->B\n\t\t\tin:    \"A B\\nB A\\nB C\",\n\t\t\tfocus: \"C\",\n\t\t\twant:  \"A B\\nB A\\nB C\\n\",\n\t\t},\n\t\t{\n\t\t\tname: \"Complex\",\n\t\t\t// Paths in and out from focus.\n\t\t\t//                   /-> F\n\t\t\t//      /-> B -> D --\n\t\t\t// A --              \\-> E\n\t\t\t//      \\-> C\n\t\t\tin:    \"A B\\nA C\\nB D\\nD F\\nD E\",\n\t\t\tfocus: \"D\",\n\t\t\twant:  \"A B\\nB D\\nD E\\nD F\\n\",\n\t\t},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tstdin = strings.NewReader(test.in)\n\t\t\tstdout = new(bytes.Buffer)\n\t\t\tif err := digraph(\"focus\", []string{test.focus}); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tgot := stdout.(fmt.Stringer).String()\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"digraph(focus, %s) = got %q, want %q\", test.focus, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestToDot(t *testing.T) {\n\tin := `a b c\nb \"d\\\"\\\\d\"\nc \"d\\\"\\\\d\"`\n\twant := `digraph {\n\t\"a\" -> \"b\";\n\t\"a\" -> \"c\";\n\t\"b\" -> \"d\\\"\\\\d\";\n\t\"c\" -> \"d\\\"\\\\d\";\n}\n`\n\tdefer func(in io.Reader, out io.Writer) { stdin, stdout = in, out }(stdin, stdout)\n\tstdin = strings.NewReader(in)\n\tstdout = new(bytes.Buffer)\n\tif err := digraph(\"to\", []string{\"dot\"}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := stdout.(fmt.Stringer).String()\n\tif got != want {\n\t\tt.Errorf(\"digraph(to, dot) = got %q, want %q\", got, want)\n\t}\n\n}\n"
  },
  {
    "path": "cmd/digraph/doc.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nThe digraph command performs queries over unlabelled directed graphs\nrepresented in text form.  It is intended to integrate nicely with\ntypical UNIX command pipelines.\n\nUsage:\n\n\tyour-application | digraph [command]\n\nThe supported commands are:\n\n\tnodes\n\t\tthe set of all nodes\n\tdegree\n\t\tthe in-degree and out-degree of each node\n\ttranspose\n\t\tthe reverse of the input edges\n\tpreds <node> ...\n\t\tthe set of immediate predecessors of the specified nodes\n\tsuccs <node> ...\n\t\tthe set of immediate successors of the specified nodes\n\tforward <node> ...\n\t\tthe set of nodes transitively reachable from the specified nodes\n\treverse <node> ...\n\t\tthe set of nodes that transitively reach the specified nodes\n\tsomepath <node> <node>\n\t\tthe list of edges on some arbitrary path from the first node to the second\n\tallpaths <node> <node>\n\t\tthe set of edges on all paths from the first node to the second\n\tsccs\n\t\tall strongly connected components (one per line)\n\tscc <node>\n\t\tthe set of nodes strongly connected to the specified one\n\tfocus <node>\n\t\tthe subgraph containing all directed paths that pass through the specified node\n\tto dot\n\t\tprint the graph in Graphviz dot format (other formats may be supported in the future)\n\nInput format:\n\nEach line contains zero or more words. Words are separated by unquoted\nwhitespace; words may contain Go-style double-quoted portions, allowing spaces\nand other characters to be expressed.\n\nEach word declares a node, and if there are more than one, an edge from the\nfirst to each subsequent one. The graph is provided on the standard input.\n\nFor instance, the following (acyclic) graph specifies a partial order among the\nsubtasks of getting dressed:\n\n\t$ cat clothes.txt\n\tsocks shoes\n\t\"boxer shorts\" pants\n\tpants belt shoes\n\tshirt tie sweater\n\tsweater jacket\n\that\n\nThe line \"shirt tie sweater\" indicates the two edges shirt -> tie and\nshirt -> sweater, not shirt -> tie -> sweater.\n\nExample usage:\n\nShow which clothes (see above) must be donned before a jacket:\n\n\t$ digraph reverse jacket\n\nMany tools can be persuaded to produce output in digraph format,\nas in the following examples.\n\nUsing an import graph produced by go list, show a path that indicates\nwhy the gopls application depends on the cmp package:\n\n\t$ go list -f '{{.ImportPath}} {{join .Imports \" \"}}' -deps golang.org/x/tools/gopls |\n\t\tdigraph somepath golang.org/x/tools/gopls github.com/google/go-cmp/cmp\n\nShow which packages in x/tools depend, perhaps indirectly, on the callgraph package:\n\n\t$ go list -f '{{.ImportPath}} {{join .Imports \" \"}}' -deps golang.org/x/tools/... |\n\t\tdigraph reverse golang.org/x/tools/go/callgraph\n\nVisualize the package dependency graph of the current package:\n\n\t$ go list -f '{{.ImportPath}} {{join .Imports \" \"}}' -deps |\n\t\tdigraph to dot | dot -Tpng -o x.png\n\nUsing a module graph produced by go mod, show all dependencies of the current module:\n\n\t$ go mod graph | digraph forward $(go list -m)\n*/\npackage main\n"
  },
  {
    "path": "cmd/eg/eg.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The eg command performs example-based refactoring.\n// For documentation, run the command, or see Help in\n// golang.org/x/tools/refactor/eg.\npackage main // import \"golang.org/x/tools/cmd/eg\"\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/refactor/eg\"\n)\n\nvar (\n\tbeforeeditFlag = flag.String(\"beforeedit\", \"\", \"A command to exec before each file is edited (e.g. chmod, checkout).  Whitespace delimits argument words.  The string '{}' is replaced by the file name.\")\n\thelpFlag       = flag.Bool(\"help\", false, \"show detailed help message\")\n\ttagsFlag       = flag.String(\"tags\", \"\", \"comma-separated list of build tags to apply (see: go help buildconstraint)\")\n\ttemplateFlag   = flag.String(\"t\", \"\", \"template.go file specifying the refactoring\")\n\ttransitiveFlag = flag.Bool(\"transitive\", false, \"apply refactoring to all dependencies too\")\n\twriteFlag      = flag.Bool(\"w\", false, \"rewrite input files in place (by default, the results are printed to standard output)\")\n\tverboseFlag    = flag.Bool(\"v\", false, \"show verbose matcher diagnostics\")\n)\n\nconst usage = `eg: an example-based refactoring tool.\n\nUsage: eg -t template.go [-w] [-transitive] [-tags=tag,...] <packages>\n\n-help            show detailed help message\n-t template.go   specifies the template file (use -help to see explanation)\n-w               causes files to be re-written in place.\n-transitive      causes all dependencies to be refactored too.\n-v               show verbose matcher diagnostics\n-tags tag,...    comma-separated list of build tags to apply (see: go help buildconstraint)\n-beforeedit cmd  a command to exec before each file is modified.\n                 \"{}\" represents the name of the file.\n`\n\nfunc main() {\n\tif err := doMain(); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"eg: %s\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc doMain() error {\n\tflag.Parse()\n\targs := flag.Args()\n\n\tif *helpFlag {\n\t\thelp := eg.Help // hide %s from vet\n\t\tfmt.Fprint(os.Stderr, help)\n\t\tos.Exit(2)\n\t}\n\n\tif len(args) == 0 {\n\t\tfmt.Fprint(os.Stderr, usage)\n\t\tos.Exit(1)\n\t}\n\n\tif *templateFlag == \"\" {\n\t\treturn fmt.Errorf(\"no -t template.go file specified\")\n\t}\n\n\ttAbs, err := filepath.Abs(*templateFlag)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttemplate, err := os.ReadFile(tAbs)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcfg := &packages.Config{\n\t\tBuildFlags: []string{\"-tags=\" + *tagsFlag},\n\t\tFset:       token.NewFileSet(),\n\t\tMode:       packages.NeedTypesInfo | packages.NeedName | packages.NeedTypes | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps | packages.NeedCompiledGoFiles,\n\t\tTests:      true,\n\t}\n\n\tpkgs, err := packages.Load(cfg, args...)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttFile, err := parser.ParseFile(cfg.Fset, tAbs, template, parser.ParseComments)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Type-check the template.\n\ttInfo := types.Info{\n\t\tTypes:      make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:       make(map[*ast.Ident]types.Object),\n\t\tUses:       make(map[*ast.Ident]types.Object),\n\t\tImplicits:  make(map[ast.Node]types.Object),\n\t\tSelections: make(map[*ast.SelectorExpr]*types.Selection),\n\t\tScopes:     make(map[ast.Node]*types.Scope),\n\t}\n\tconf := types.Config{\n\t\tImporter: pkgsImporter(pkgs),\n\t}\n\ttPkg, err := conf.Check(\"egtemplate\", cfg.Fset, []*ast.File{tFile}, &tInfo)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Analyze the template.\n\txform, err := eg.NewTransformer(cfg.Fset, tPkg, tFile, &tInfo, *verboseFlag)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Apply it to the input packages.\n\tvar all []*packages.Package\n\tif *transitiveFlag {\n\t\tpackages.Visit(pkgs, nil, func(p *packages.Package) { all = append(all, p) })\n\t} else {\n\t\tall = pkgs\n\t}\n\tvar hadErrors bool\n\tfor _, pkg := range pkgs {\n\t\tfor i, filename := range pkg.CompiledGoFiles {\n\t\t\tif filename == tAbs {\n\t\t\t\t// Don't rewrite the template file.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfile := pkg.Syntax[i]\n\t\t\tn := xform.Transform(pkg.TypesInfo, pkg.Types, file)\n\t\t\tif n == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Fprintf(os.Stderr, \"=== %s (%d matches)\\n\", filename, n)\n\t\t\tif *writeFlag {\n\t\t\t\t// Run the before-edit command (e.g. \"chmod +w\",  \"checkout\") if any.\n\t\t\t\tif *beforeeditFlag != \"\" {\n\t\t\t\t\targs := strings.Fields(*beforeeditFlag)\n\t\t\t\t\t// Replace \"{}\" with the filename, like find(1).\n\t\t\t\t\tfor i := range args {\n\t\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\t\targs[i] = strings.Replace(args[i], \"{}\", filename, -1)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcmd := exec.Command(args[0], args[1:]...)\n\t\t\t\t\tcmd.Stdout = os.Stdout\n\t\t\t\t\tcmd.Stderr = os.Stderr\n\t\t\t\t\tif err := cmd.Run(); err != nil {\n\t\t\t\t\t\tfmt.Fprintf(os.Stderr, \"Warning: edit hook %q failed (%s)\\n\",\n\t\t\t\t\t\t\targs, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif err := eg.WriteAST(cfg.Fset, filename, file); err != nil {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"eg: %s\\n\", err)\n\t\t\t\t\thadErrors = true\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tformat.Node(os.Stdout, cfg.Fset, file)\n\t\t\t}\n\t\t}\n\t}\n\tif hadErrors {\n\t\tos.Exit(1)\n\t}\n\n\treturn nil\n}\n\ntype pkgsImporter []*packages.Package\n\nfunc (p pkgsImporter) Import(path string) (tpkg *types.Package, err error) {\n\tpackages.Visit([]*packages.Package(p), func(pkg *packages.Package) bool {\n\t\tif pkg.PkgPath == path {\n\t\t\ttpkg = pkg.Types\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t}, nil)\n\tif tpkg != nil {\n\t\treturn tpkg, nil\n\t}\n\treturn nil, fmt.Errorf(\"package %q not found\", path)\n}\n"
  },
  {
    "path": "cmd/file2fuzz/main.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// file2fuzz converts binary files, such as those used by go-fuzz, to the Go\n// fuzzing corpus format.\n//\n// Usage:\n//\n//\tfile2fuzz [-o output] [input...]\n//\n// The default behavior is to read input from stdin and write the converted\n// output to stdout. If any position arguments are provided stdin is ignored\n// and the arguments are assumed to be input files to convert.\n//\n// The -o flag provides a path to write output files to. If only one positional\n// argument is specified it may be a file path or an existing directory, if there are\n// multiple inputs specified it must be a directory. If a directory is provided\n// the name of the file will be the SHA-256 hash of its contents.\npackage main\n\nimport (\n\t\"crypto/sha256\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\n// encVersion1 is version 1 Go fuzzer corpus encoding.\nvar encVersion1 = \"go test fuzz v1\"\n\nfunc encodeByteSlice(b []byte) []byte {\n\treturn fmt.Appendf(nil, \"%s\\n[]byte(%q)\", encVersion1, b)\n}\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: file2fuzz [-o output] [input...]\\nconverts files to Go fuzzer corpus format\\n\")\n\tfmt.Fprintf(os.Stderr, \"\\tinput: files to convert\\n\")\n\tfmt.Fprintf(os.Stderr, \"\\t-o: where to write converted file(s)\\n\")\n\tos.Exit(2)\n}\nfunc dirWriter(dir string) func([]byte) error {\n\treturn func(b []byte) error {\n\t\tsum := fmt.Sprintf(\"%x\", sha256.Sum256(b))\n\t\tname := filepath.Join(dir, sum)\n\t\tif err := os.MkdirAll(dir, 0777); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := os.WriteFile(name, b, 0666); err != nil {\n\t\t\tos.Remove(name)\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n}\n\nfunc convert(inputArgs []string, outputArg string) error {\n\tvar input []io.Reader\n\tif args := inputArgs; len(args) == 0 {\n\t\tinput = []io.Reader{os.Stdin}\n\t} else {\n\t\tfor _, a := range args {\n\t\t\tf, err := os.Open(a)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"unable to open %q: %s\", a, err)\n\t\t\t}\n\t\t\tdefer f.Close()\n\t\t\tif fi, err := f.Stat(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"unable to open %q: %s\", a, err)\n\t\t\t} else if fi.IsDir() {\n\t\t\t\treturn fmt.Errorf(\"%q is a directory, not a file\", a)\n\t\t\t}\n\t\t\tinput = append(input, f)\n\t\t}\n\t}\n\n\tvar output func([]byte) error\n\tif outputArg == \"\" {\n\t\tif len(inputArgs) > 1 {\n\t\t\treturn errors.New(\"-o required with multiple input files\")\n\t\t}\n\t\toutput = func(b []byte) error {\n\t\t\t_, err := os.Stdout.Write(b)\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif len(inputArgs) > 1 {\n\t\t\toutput = dirWriter(outputArg)\n\t\t} else {\n\t\t\tif fi, err := os.Stat(outputArg); err != nil && !os.IsNotExist(err) {\n\t\t\t\treturn fmt.Errorf(\"unable to open %q for writing: %s\", outputArg, err)\n\t\t\t} else if err == nil && fi.IsDir() {\n\t\t\t\toutput = dirWriter(outputArg)\n\t\t\t} else {\n\t\t\t\toutput = func(b []byte) error {\n\t\t\t\t\treturn os.WriteFile(outputArg, b, 0666)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, f := range input {\n\t\tb, err := io.ReadAll(f)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to read input: %s\", err)\n\t\t}\n\t\tif err := output(encodeByteSlice(b)); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to write output: %s\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"file2fuzz: \")\n\n\toutput := flag.String(\"o\", \"\", \"where to write converted file(s)\")\n\tflag.Usage = usage\n\tflag.Parse()\n\n\tif err := convert(flag.Args(), *output); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "cmd/file2fuzz/main_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\tif os.Getenv(\"GO_FILE2FUZZ_TEST_IS_FILE2FUZZ\") != \"\" {\n\t\tmain()\n\t\tos.Exit(0)\n\t}\n\n\tos.Exit(m.Run())\n}\n\nvar f2f struct {\n\tonce sync.Once\n\tpath string\n\terr  error\n}\n\nfunc file2fuzz(t *testing.T, dir string, args []string, stdin string) (string, bool) {\n\ttestenv.NeedsExec(t)\n\n\tf2f.once.Do(func() {\n\t\tf2f.path, f2f.err = os.Executable()\n\t})\n\tif f2f.err != nil {\n\t\tt.Fatal(f2f.err)\n\t}\n\n\tcmd := exec.Command(f2f.path, args...)\n\tcmd.Dir = dir\n\tcmd.Env = append(os.Environ(), \"PWD=\"+dir, \"GO_FILE2FUZZ_TEST_IS_FILE2FUZZ=1\")\n\tif stdin != \"\" {\n\t\tcmd.Stdin = strings.NewReader(stdin)\n\t}\n\tout, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn string(out), true\n\t}\n\treturn string(out), false\n}\n\nfunc TestFile2Fuzz(t *testing.T) {\n\ttype file struct {\n\t\tname    string\n\t\tdir     bool\n\t\tcontent string\n\t}\n\ttests := []struct {\n\t\tname           string\n\t\targs           []string\n\t\tstdin          string\n\t\tinputFiles     []file\n\t\texpectedStdout string\n\t\texpectedFiles  []file\n\t\texpectedError  string\n\t}{\n\t\t{\n\t\t\tname:           \"stdin, stdout\",\n\t\t\tstdin:          \"hello\",\n\t\t\texpectedStdout: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\",\n\t\t},\n\t\t{\n\t\t\tname:          \"stdin, output file\",\n\t\t\tstdin:         \"hello\",\n\t\t\targs:          []string{\"-o\", \"output\"},\n\t\t\texpectedFiles: []file{{name: \"output\", content: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\"}},\n\t\t},\n\t\t{\n\t\t\tname:          \"stdin, output directory\",\n\t\t\tstdin:         \"hello\",\n\t\t\targs:          []string{\"-o\", \"output\"},\n\t\t\tinputFiles:    []file{{name: \"output\", dir: true}},\n\t\t\texpectedFiles: []file{{name: \"output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b\", content: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\"}},\n\t\t},\n\t\t{\n\t\t\tname:          \"input file, output file\",\n\t\t\targs:          []string{\"-o\", \"output\", \"input\"},\n\t\t\tinputFiles:    []file{{name: \"input\", content: \"hello\"}},\n\t\t\texpectedFiles: []file{{name: \"output\", content: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\"}},\n\t\t},\n\t\t{\n\t\t\tname:          \"input file, output directory\",\n\t\t\targs:          []string{\"-o\", \"output\", \"input\"},\n\t\t\tinputFiles:    []file{{name: \"output\", dir: true}, {name: \"input\", content: \"hello\"}},\n\t\t\texpectedFiles: []file{{name: \"output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b\", content: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\"}},\n\t\t},\n\t\t{\n\t\t\tname:       \"input files, output directory\",\n\t\t\targs:       []string{\"-o\", \"output\", \"input\", \"input-2\"},\n\t\t\tinputFiles: []file{{name: \"output\", dir: true}, {name: \"input\", content: \"hello\"}, {name: \"input-2\", content: \"hello :)\"}},\n\t\t\texpectedFiles: []file{\n\t\t\t\t{name: \"output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b\", content: \"go test fuzz v1\\n[]byte(\\\"hello\\\")\"},\n\t\t\t\t{name: \"output/28059db30ce420ff65b2c29b749804c69c601aeca21b3cbf0644244ff080d7a5\", content: \"go test fuzz v1\\n[]byte(\\\"hello :)\\\")\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:          \"input files, no output\",\n\t\t\targs:          []string{\"input\", \"input-2\"},\n\t\t\tinputFiles:    []file{{name: \"output\", dir: true}, {name: \"input\", content: \"hello\"}, {name: \"input-2\", content: \"hello :)\"}},\n\t\t\texpectedError: \"file2fuzz: -o required with multiple input files\\n\",\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\ttmp, err := os.MkdirTemp(os.TempDir(), \"file2fuzz\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"os.MkdirTemp failed: %s\", err)\n\t\t\t}\n\t\t\tdefer os.RemoveAll(tmp)\n\t\t\tfor _, f := range tc.inputFiles {\n\t\t\t\tif f.dir {\n\t\t\t\t\tif err := os.Mkdir(filepath.Join(tmp, f.name), 0777); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"failed to create test directory: %s\", err)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif err := os.WriteFile(filepath.Join(tmp, f.name), []byte(f.content), 0666); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"failed to create test input file: %s\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tout, failed := file2fuzz(t, tmp, tc.args, tc.stdin)\n\t\t\tif failed && tc.expectedError == \"\" {\n\t\t\t\tt.Fatalf(\"file2fuzz failed unexpectedly: %s\", out)\n\t\t\t} else if failed && out != tc.expectedError {\n\t\t\t\tt.Fatalf(\"file2fuzz returned unexpected error: got %q, want %q\", out, tc.expectedError)\n\t\t\t}\n\t\t\tif !failed && out != tc.expectedStdout {\n\t\t\t\tt.Fatalf(\"file2fuzz unexpected stdout: got %q, want %q\", out, tc.expectedStdout)\n\t\t\t}\n\n\t\t\tfor _, f := range tc.expectedFiles {\n\t\t\t\tc, err := os.ReadFile(filepath.Join(tmp, f.name))\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"failed to read expected output file %q: %s\", f.name, err)\n\t\t\t\t}\n\t\t\t\tif string(c) != f.content {\n\t\t\t\t\tt.Fatalf(\"expected output file %q contains unexpected content: got %s, want %s\", f.name, string(c), f.content)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "cmd/fiximports/main.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The fiximports command fixes import declarations to use the canonical\n// import path for packages that have an \"import comment\" as defined by\n// https://golang.org/s/go14customimport.\n//\n// # Background\n//\n// The Go 1 custom import path mechanism lets the maintainer of a\n// package give it a stable name by which clients may import and \"go\n// get\" it, independent of the underlying version control system (such\n// as Git) or server (such as github.com) that hosts it.  Requests for\n// the custom name are redirected to the underlying name.  This allows\n// packages to be migrated from one underlying server or system to\n// another without breaking existing clients.\n//\n// Because this redirect mechanism creates aliases for existing\n// packages, it's possible for a single program to import the same\n// package by its canonical name and by an alias.  The resulting\n// executable will contain two copies of the package, which is wasteful\n// at best and incorrect at worst.\n//\n// To avoid this, \"go build\" reports an error if it encounters a special\n// comment like the one below, and if the import path in the comment\n// does not match the path of the enclosing package relative to\n// GOPATH/src:\n//\n//\t     $ grep ^package $GOPATH/src/github.com/bob/vanity/foo/foo.go\n//\t\tpackage foo // import \"vanity.com/foo\"\n//\n// The error from \"go build\" indicates that the package canonically\n// known as \"vanity.com/foo\" is locally installed under the\n// non-canonical name \"github.com/bob/vanity/foo\".\n//\n// # Usage\n//\n// When a package that you depend on introduces a custom import comment,\n// and your workspace imports it by the non-canonical name, your build\n// will stop working as soon as you update your copy of that package\n// using \"go get -u\".\n//\n// The purpose of the fiximports tool is to fix up all imports of the\n// non-canonical path within a Go workspace, replacing them with imports\n// of the canonical path.  Following a run of fiximports, the workspace\n// will no longer depend on the non-canonical copy of the package, so it\n// should be safe to delete.  It may be necessary to run \"go get -u\"\n// again to ensure that the package is locally installed under its\n// canonical path, if it was not already.\n//\n// The fiximports tool operates locally; it does not make HTTP requests\n// and does not discover new custom import comments.  It only operates\n// on non-canonical packages present in your workspace.\n//\n// The -baddomains flag is a list of domain names that should always be\n// considered non-canonical.  You can use this if you wish to make sure\n// that you no longer have any dependencies on packages from that\n// domain, even those that do not yet provide a canonical import path\n// comment.  For example, the default value of -baddomains includes the\n// moribund code hosting site code.google.com, so fiximports will report\n// an error for each import of a package from this domain remaining\n// after canonicalization.\n//\n// To see the changes fiximports would make without applying them, use\n// the -n flag.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// flags\nvar (\n\tdryrun     = flag.Bool(\"n\", false, \"dry run: show changes, but don't apply them\")\n\tbadDomains = flag.String(\"baddomains\", \"code.google.com\",\n\t\t\"a comma-separated list of domains from which packages should not be imported\")\n\treplaceFlag = flag.String(\"replace\", \"\",\n\t\t\"a comma-separated list of noncanonical=canonical pairs of package paths.  If both items in a pair end with '...', they are treated as path prefixes.\")\n)\n\n// seams for testing\nvar (\n\tstderr    io.Writer = os.Stderr\n\twriteFile           = os.WriteFile\n)\n\nconst usage = `fiximports: rewrite import paths to use canonical package names.\n\nUsage: fiximports [-n] package...\n\nThe package... arguments specify a list of packages\nin the style of the go tool; see \"go help packages\".\nHint: use \"all\" or \"...\" to match the entire workspace.\n\nFor details, see https://pkg.go.dev/golang.org/x/tools/cmd/fiximports\n\nFlags:\n  -n:\t       dry run: show changes, but don't apply them\n  -baddomains  a comma-separated list of domains from which packages\n               should not be imported\n`\n\nfunc main() {\n\tflag.Parse()\n\n\tif len(flag.Args()) == 0 {\n\t\tfmt.Fprint(stderr, usage)\n\t\tos.Exit(1)\n\t}\n\tif !fiximports(flag.Args()...) {\n\t\tos.Exit(1)\n\t}\n}\n\ntype canonicalName struct{ path, name string }\n\n// fiximports fixes imports in the specified packages.\n// Invariant: a false result implies an error was already printed.\nfunc fiximports(packages ...string) bool {\n\t// importedBy is the transpose of the package import graph.\n\timportedBy := make(map[string]map[*listPackage]bool)\n\n\t// addEdge adds an edge to the import graph.\n\taddEdge := func(from *listPackage, to string) {\n\t\tif to == \"C\" || to == \"unsafe\" {\n\t\t\treturn // fake\n\t\t}\n\t\tpkgs := importedBy[to]\n\t\tif pkgs == nil {\n\t\t\tpkgs = make(map[*listPackage]bool)\n\t\t\timportedBy[to] = pkgs\n\t\t}\n\t\tpkgs[from] = true\n\t}\n\n\t// List metadata for all packages in the workspace.\n\tpkgs, err := list(\"...\")\n\tif err != nil {\n\t\tfmt.Fprintf(stderr, \"importfix: %v\\n\", err)\n\t\treturn false\n\t}\n\n\t// packageName maps each package's path to its name.\n\tpackageName := make(map[string]string)\n\tfor _, p := range pkgs {\n\t\tpackageName[p.ImportPath] = p.Name\n\t}\n\n\t// canonical maps each non-canonical package path to\n\t// its canonical path and name.\n\t// A present nil value indicates that the canonical package\n\t// is unknown: hosted on a bad domain with no redirect.\n\tcanonical := make(map[string]canonicalName)\n\tdomains := strings.Split(*badDomains, \",\")\n\n\ttype replaceItem struct {\n\t\told, new    string\n\t\tmatchPrefix bool\n\t}\n\tvar replace []replaceItem\n\tfor pair := range strings.SplitSeq(*replaceFlag, \",\") {\n\t\tif pair == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\twords := strings.Split(pair, \"=\")\n\t\tif len(words) != 2 {\n\t\t\tfmt.Fprintf(stderr, \"importfix: -replace: %q is not of the form \\\"canonical=noncanonical\\\".\\n\", pair)\n\t\t\treturn false\n\t\t}\n\t\treplace = append(replace, replaceItem{\n\t\t\told: strings.TrimSuffix(words[0], \"...\"),\n\t\t\tnew: strings.TrimSuffix(words[1], \"...\"),\n\t\t\tmatchPrefix: strings.HasSuffix(words[0], \"...\") &&\n\t\t\t\tstrings.HasSuffix(words[1], \"...\"),\n\t\t})\n\t}\n\n\t// Find non-canonical packages and populate importedBy graph.\n\tfor _, p := range pkgs {\n\t\tif p.Error != nil {\n\t\t\tmsg := p.Error.Err\n\t\t\tif strings.Contains(msg, \"code in directory\") &&\n\t\t\t\tstrings.Contains(msg, \"expects import\") {\n\t\t\t\t// don't show the very errors we're trying to fix\n\t\t\t} else {\n\t\t\t\tfmt.Fprintln(stderr, p.Error)\n\t\t\t}\n\t\t}\n\n\t\tfor _, imp := range p.Imports {\n\t\t\taddEdge(p, imp)\n\t\t}\n\t\tfor _, imp := range p.TestImports {\n\t\t\taddEdge(p, imp)\n\t\t}\n\t\tfor _, imp := range p.XTestImports {\n\t\t\taddEdge(p, imp)\n\t\t}\n\n\t\t// Does package have an explicit import comment?\n\t\tif p.ImportComment != \"\" {\n\t\t\tif p.ImportComment != p.ImportPath {\n\t\t\t\tcanonical[p.ImportPath] = canonicalName{\n\t\t\t\t\tpath: p.ImportComment,\n\t\t\t\t\tname: p.Name,\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Is package matched by a -replace item?\n\t\t\tvar newPath string\n\t\t\tfor _, item := range replace {\n\t\t\t\tif item.matchPrefix {\n\t\t\t\t\tif strings.HasPrefix(p.ImportPath, item.old) {\n\t\t\t\t\t\tnewPath = item.new + p.ImportPath[len(item.old):]\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t} else if p.ImportPath == item.old {\n\t\t\t\t\tnewPath = item.new\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif newPath != \"\" {\n\t\t\t\tnewName := packageName[newPath]\n\t\t\t\tif newName == \"\" {\n\t\t\t\t\tnewName = filepath.Base(newPath) // a guess\n\t\t\t\t}\n\t\t\t\tcanonical[p.ImportPath] = canonicalName{\n\t\t\t\t\tpath: newPath,\n\t\t\t\t\tname: newName,\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Is package matched by a -baddomains item?\n\t\t\tfor _, domain := range domains {\n\t\t\t\tslash := strings.Index(p.ImportPath, \"/\")\n\t\t\t\tif slash < 0 {\n\t\t\t\t\tcontinue // no slash: standard package\n\t\t\t\t}\n\t\t\t\tif p.ImportPath[:slash] == domain {\n\t\t\t\t\t// Package comes from bad domain and has no import comment.\n\t\t\t\t\t// Report an error each time this package is imported.\n\t\t\t\t\tcanonical[p.ImportPath] = canonicalName{}\n\n\t\t\t\t\t// TODO(adonovan): should we make an HTTP request to\n\t\t\t\t\t// see if there's an HTTP redirect, a \"go-import\" meta tag,\n\t\t\t\t\t// or an import comment in the latest revision?\n\t\t\t\t\t// It would duplicate a lot of logic from \"go get\".\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find all clients (direct importers) of canonical packages.\n\t// These are the packages that need fixing up.\n\tclients := make(map[*listPackage]bool)\n\tfor path := range canonical {\n\t\tfor client := range importedBy[path] {\n\t\t\tclients[client] = true\n\t\t}\n\t}\n\n\t// Restrict rewrites to the set of packages specified by the user.\n\tif len(packages) == 1 && (packages[0] == \"all\" || packages[0] == \"...\") {\n\t\t// no restriction\n\t} else {\n\t\tpkgs, err := list(packages...)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(stderr, \"importfix: %v\\n\", err)\n\t\t\treturn false\n\t\t}\n\t\tseen := make(map[string]bool)\n\t\tfor _, p := range pkgs {\n\t\t\tseen[p.ImportPath] = true\n\t\t}\n\t\tfor client := range clients {\n\t\t\tif !seen[client.ImportPath] {\n\t\t\t\tdelete(clients, client)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Rewrite selected client packages.\n\tok := true\n\tfor client := range clients {\n\t\tif !rewritePackage(client, canonical) {\n\t\t\tok = false\n\n\t\t\t// There were errors.\n\t\t\t// Show direct and indirect imports of client.\n\t\t\tseen := make(map[string]bool)\n\t\t\tvar direct, indirect []string\n\t\t\tfor p := range importedBy[client.ImportPath] {\n\t\t\t\tdirect = append(direct, p.ImportPath)\n\t\t\t\tseen[p.ImportPath] = true\n\t\t\t}\n\n\t\t\tvar visit func(path string)\n\t\t\tvisit = func(path string) {\n\t\t\t\tfor q := range importedBy[path] {\n\t\t\t\t\tqpath := q.ImportPath\n\t\t\t\t\tif !seen[qpath] {\n\t\t\t\t\t\tseen[qpath] = true\n\t\t\t\t\t\tindirect = append(indirect, qpath)\n\t\t\t\t\t\tvisit(qpath)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif direct != nil {\n\t\t\t\tfmt.Fprintf(stderr, \"\\timported directly by:\\n\")\n\t\t\t\tsort.Strings(direct)\n\t\t\t\tfor _, path := range direct {\n\t\t\t\t\tfmt.Fprintf(stderr, \"\\t\\t%s\\n\", path)\n\t\t\t\t\tvisit(path)\n\t\t\t\t}\n\n\t\t\t\tif indirect != nil {\n\t\t\t\t\tfmt.Fprintf(stderr, \"\\timported indirectly by:\\n\")\n\t\t\t\t\tsort.Strings(indirect)\n\t\t\t\t\tfor _, path := range indirect {\n\t\t\t\t\t\tfmt.Fprintf(stderr, \"\\t\\t%s\\n\", path)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ok\n}\n\n// Invariant: false result => error already printed.\nfunc rewritePackage(client *listPackage, canonical map[string]canonicalName) bool {\n\tok := true\n\n\tused := make(map[string]bool)\n\tvar filenames []string\n\tfilenames = append(filenames, client.GoFiles...)\n\tfilenames = append(filenames, client.TestGoFiles...)\n\tfilenames = append(filenames, client.XTestGoFiles...)\n\tvar first bool\n\tfor _, filename := range filenames {\n\t\tif !first {\n\t\t\tfirst = true\n\t\t\tfmt.Fprintf(stderr, \"%s\\n\", client.ImportPath)\n\t\t}\n\t\terr := rewriteFile(filepath.Join(client.Dir, filename), canonical, used)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(stderr, \"\\tERROR: %v\\n\", err)\n\t\t\tok = false\n\t\t}\n\t}\n\n\t// Show which imports were renamed in this package.\n\tvar keys []string\n\tfor key := range used {\n\t\tkeys = append(keys, key)\n\t}\n\tsort.Strings(keys)\n\tfor _, key := range keys {\n\t\tif p := canonical[key]; p.path != \"\" {\n\t\t\tfmt.Fprintf(stderr, \"\\tfixed: %s -> %s\\n\", key, p.path)\n\t\t} else {\n\t\t\tfmt.Fprintf(stderr, \"\\tERROR: %s has no import comment\\n\", key)\n\t\t\tok = false\n\t\t}\n\t}\n\n\treturn ok\n}\n\n// rewriteFile reads, modifies, and writes filename, replacing all imports\n// of packages P in canonical by canonical[P].\n// It records in used which canonical packages were imported.\n// used[P]==\"\" indicates that P was imported but its canonical path is unknown.\nfunc rewriteFile(filename string, canonical map[string]canonicalName, used map[string]bool) error {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar changed bool\n\tfor _, imp := range f.Imports {\n\t\timpPath, err := strconv.Unquote(imp.Path.Value)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"%s: bad import spec %q: %v\",\n\t\t\t\tfset.Position(imp.Pos()), imp.Path.Value, err)\n\t\t\tcontinue\n\t\t}\n\t\tcanon, ok := canonical[impPath]\n\t\tif !ok {\n\t\t\tcontinue // import path is canonical\n\t\t}\n\n\t\tused[impPath] = true\n\n\t\tif canon.path == \"\" {\n\t\t\t// The canonical path is unknown (a -baddomain).\n\t\t\t// Show the offending import.\n\t\t\t// TODO(adonovan): should we show the actual source text?\n\t\t\tfmt.Fprintf(stderr, \"\\t%s:%d: import %q\\n\",\n\t\t\t\tshortPath(filename),\n\t\t\t\tfset.Position(imp.Pos()).Line, impPath)\n\t\t\tcontinue\n\t\t}\n\n\t\tchanged = true\n\n\t\timp.Path.Value = strconv.Quote(canon.path)\n\n\t\t// Add a renaming import if necessary.\n\t\t//\n\t\t// This is a guess at best.  We can't see whether a 'go\n\t\t// get' of the canonical import path would have the same\n\t\t// name or not.  Assume it's the last segment.\n\t\tnewBase := path.Base(canon.path)\n\t\tif imp.Name == nil && newBase != canon.name {\n\t\t\timp.Name = &ast.Ident{Name: canon.name}\n\t\t}\n\t}\n\n\tif changed && !*dryrun {\n\t\tvar buf bytes.Buffer\n\t\tif err := format.Node(&buf, fset, f); err != nil {\n\t\t\treturn fmt.Errorf(\"%s: couldn't format file: %v\", filename, err)\n\t\t}\n\t\treturn writeFile(filename, buf.Bytes(), 0644)\n\t}\n\n\treturn nil\n}\n\n// listPackage corresponds to the output of go list -json,\n// but only the fields we need.\ntype listPackage struct {\n\tName          string\n\tDir           string\n\tImportPath    string\n\tGoFiles       []string\n\tTestGoFiles   []string\n\tXTestGoFiles  []string\n\tImports       []string\n\tTestImports   []string\n\tXTestImports  []string\n\tImportComment string\n\tError         *packageError // error loading package\n}\n\n// A packageError describes an error loading information about a package.\ntype packageError struct {\n\tImportStack []string // shortest path from package named on command line to this one\n\tPos         string   // position of error\n\tErr         string   // the error itself\n}\n\nfunc (e packageError) Error() string {\n\tif e.Pos != \"\" {\n\t\treturn e.Pos + \": \" + e.Err\n\t}\n\treturn e.Err\n}\n\n// list runs 'go list' with the specified arguments and returns the\n// metadata for matching packages.\nfunc list(args ...string) ([]*listPackage, error) {\n\tcmd := exec.Command(\"go\", append([]string{\"list\", \"-e\", \"-json\"}, args...)...)\n\tcmd.Stdout = new(bytes.Buffer)\n\tcmd.Stderr = stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tdec := json.NewDecoder(cmd.Stdout.(io.Reader))\n\tvar pkgs []*listPackage\n\tfor {\n\t\tvar p listPackage\n\t\tif err := dec.Decode(&p); err == io.EOF {\n\t\t\tbreak\n\t\t} else if err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpkgs = append(pkgs, &p)\n\t}\n\treturn pkgs, nil\n}\n\n// cwd contains the current working directory of the tool.\n//\n// It is initialized directly so that its value will be set for any other\n// package variables or init functions that depend on it, such as the gopath\n// variable in main_test.go.\nvar cwd string = func() string {\n\tcwd, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatalf(\"os.Getwd: %v\", err)\n\t}\n\treturn cwd\n}()\n\n// shortPath returns an absolute or relative name for path, whatever is shorter.\n// Plundered from $GOROOT/src/cmd/go/build.go.\nfunc shortPath(path string) string {\n\tif rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {\n\t\treturn rel\n\t}\n\treturn path\n}\n"
  },
  {
    "path": "cmd/fiximports/main_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TODO(adonovan):\n// - test introduction of renaming imports.\n// - test induced failures of rewriteFile.\n\n// Guide to the test packages:\n//\n// new.com/one\t\t-- canonical name for old.com/one\n// old.com/one\t\t-- non-canonical; has import comment \"new.com/one\"\n// old.com/bad\t\t-- has a parse error\n// fruit.io/orange\t\\\n// fruit.io/banana\t } orange -> pear -> banana -> titanic.biz/bar\n// fruit.io/pear\t/\n// titanic.biz/bar\t-- domain is sinking; package has jumped ship to new.com/bar\n// titanic.biz/foo\t-- domain is sinking but package has no import comment yet\n\nvar gopath = filepath.Join(cwd, \"testdata\")\n\nfunc init() {\n\tif err := os.Setenv(\"GOPATH\", gopath); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// This test currently requires GOPATH mode.\n\t// Explicitly disabling module mode should suffix, but\n\t// we'll also turn off GOPROXY just for good measure.\n\tif err := os.Setenv(\"GO111MODULE\", \"off\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.Setenv(\"GOPROXY\", \"off\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc TestFixImports(t *testing.T) {\n\tif os.Getenv(\"GO_BUILDER_NAME\") == \"plan9-arm\" {\n\t\tt.Skipf(\"skipping test that times out on plan9-arm; see https://go.dev/issue/50775\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\tdefer func() {\n\t\tstderr = os.Stderr\n\t\t*badDomains = \"code.google.com\"\n\t\t*replaceFlag = \"\"\n\t}()\n\n\tfor i, test := range []struct {\n\t\tpackages    []string // packages to rewrite, \"go list\" syntax\n\t\tbadDomains  string   // -baddomains flag\n\t\treplaceFlag string   // -replace flag\n\t\twantOK      bool\n\t\twantStderr  string\n\t\twantRewrite map[string]string\n\t}{\n\t\t// #0. No errors.\n\t\t{\n\t\t\tpackages:   []string{\"all\"},\n\t\t\tbadDomains: \"code.google.com\",\n\t\t\twantOK:     true,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\nfruit.io/banana\n\tfixed: old.com/one -> new.com/one\n\tfixed: titanic.biz/bar -> new.com/bar\n`,\n\t\t\twantRewrite: map[string]string{\n\t\t\t\t\"$GOPATH/src/fruit.io/banana/banana.go\": `package banana\n\nimport (\n\t_ \"new.com/bar\"\n\t_ \"new.com/one\"\n\t_ \"titanic.biz/foo\"\n)`,\n\t\t\t},\n\t\t},\n\t\t// #1. No packages needed rewriting.\n\t\t{\n\t\t\tpackages:   []string{\"titanic.biz/...\", \"old.com/...\", \"new.com/...\"},\n\t\t\tbadDomains: \"code.google.com\",\n\t\t\twantOK:     true,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\n`,\n\t\t},\n\t\t// #2. Some packages without import comments matched bad domains.\n\t\t{\n\t\t\tpackages:   []string{\"all\"},\n\t\t\tbadDomains: \"titanic.biz\",\n\t\t\twantOK:     false,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\nfruit.io/banana\n\ttestdata/src/fruit.io/banana/banana.go:6: import \"titanic.biz/foo\"\n\tfixed: old.com/one -> new.com/one\n\tfixed: titanic.biz/bar -> new.com/bar\n\tERROR: titanic.biz/foo has no import comment\n\timported directly by:\n\t\tfruit.io/pear\n\timported indirectly by:\n\t\tfruit.io/orange\n`,\n\t\t\twantRewrite: map[string]string{\n\t\t\t\t\"$GOPATH/src/fruit.io/banana/banana.go\": `package banana\n\nimport (\n\t_ \"new.com/bar\"\n\t_ \"new.com/one\"\n\t_ \"titanic.biz/foo\"\n)`,\n\t\t\t},\n\t\t},\n\t\t// #3. The -replace flag lets user supply missing import comments.\n\t\t{\n\t\t\tpackages:    []string{\"all\"},\n\t\t\treplaceFlag: \"titanic.biz/foo=new.com/foo\",\n\t\t\twantOK:      true,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\nfruit.io/banana\n\tfixed: old.com/one -> new.com/one\n\tfixed: titanic.biz/bar -> new.com/bar\n\tfixed: titanic.biz/foo -> new.com/foo\n`,\n\t\t\twantRewrite: map[string]string{\n\t\t\t\t\"$GOPATH/src/fruit.io/banana/banana.go\": `package banana\n\nimport (\n\t_ \"new.com/bar\"\n\t_ \"new.com/foo\"\n\t_ \"new.com/one\"\n)`,\n\t\t\t},\n\t\t},\n\t\t// #4. The -replace flag supports wildcards.\n\t\t//     An explicit import comment takes precedence.\n\t\t{\n\t\t\tpackages:    []string{\"all\"},\n\t\t\treplaceFlag: \"titanic.biz/...=new.com/...\",\n\t\t\twantOK:      true,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\nfruit.io/banana\n\tfixed: old.com/one -> new.com/one\n\tfixed: titanic.biz/bar -> new.com/bar\n\tfixed: titanic.biz/foo -> new.com/foo\n`,\n\t\t\twantRewrite: map[string]string{\n\t\t\t\t\"$GOPATH/src/fruit.io/banana/banana.go\": `package banana\n\nimport (\n\t_ \"new.com/bar\"\n\t_ \"new.com/foo\"\n\t_ \"new.com/one\"\n)`,\n\t\t\t},\n\t\t},\n\t\t// #5. The -replace flag trumps -baddomains.\n\t\t{\n\t\t\tpackages:    []string{\"all\"},\n\t\t\tbadDomains:  \"titanic.biz\",\n\t\t\treplaceFlag: \"titanic.biz/foo=new.com/foo\",\n\t\t\twantOK:      true,\n\t\t\twantStderr: `\ntestdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'\nfruit.io/banana\n\tfixed: old.com/one -> new.com/one\n\tfixed: titanic.biz/bar -> new.com/bar\n\tfixed: titanic.biz/foo -> new.com/foo\n`,\n\t\t\twantRewrite: map[string]string{\n\t\t\t\t\"$GOPATH/src/fruit.io/banana/banana.go\": `package banana\n\nimport (\n\t_ \"new.com/bar\"\n\t_ \"new.com/foo\"\n\t_ \"new.com/one\"\n)`,\n\t\t\t},\n\t\t},\n\t} {\n\t\t*badDomains = test.badDomains\n\t\t*replaceFlag = test.replaceFlag\n\n\t\tstderr = new(bytes.Buffer)\n\t\tgotRewrite := make(map[string]string)\n\t\twriteFile = func(filename string, content []byte, mode os.FileMode) error {\n\t\t\tfilename = strings.Replace(filename, gopath, \"$GOPATH\", 1)\n\t\t\tfilename = filepath.ToSlash(filename)\n\t\t\tgotRewrite[filename] = string(bytes.TrimSpace(content))\n\t\t\treturn nil\n\t\t}\n\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\ttest.wantStderr = strings.Replace(test.wantStderr, `testdata/src/old.com/bad/bad.go`, `testdata\\src\\old.com\\bad\\bad.go`, -1)\n\t\t\ttest.wantStderr = strings.Replace(test.wantStderr, `testdata/src/fruit.io/banana/banana.go`, `testdata\\src\\fruit.io\\banana\\banana.go`, -1)\n\t\t}\n\t\ttest.wantStderr = strings.TrimSpace(test.wantStderr)\n\n\t\t// Check status code.\n\t\tif fiximports(test.packages...) != test.wantOK {\n\t\t\tt.Errorf(\"#%d. fiximports() = %t\", i, !test.wantOK)\n\t\t}\n\n\t\t// Compare stderr output.\n\t\tif got := strings.TrimSpace(stderr.(*bytes.Buffer).String()); got != test.wantStderr {\n\t\t\tif strings.Contains(got, \"vendor/golang_org/x/text/unicode/norm\") {\n\t\t\t\tt.Skip(\"skipping known-broken test; see golang.org/issue/17417\")\n\t\t\t}\n\t\t\tt.Errorf(\"#%d. stderr: got <<\\n%s\\n>>, want <<\\n%s\\n>>\",\n\t\t\t\ti, got, test.wantStderr)\n\t\t}\n\n\t\t// Compare rewrites.\n\t\tfor k, v := range gotRewrite {\n\t\t\tif test.wantRewrite[k] != v {\n\t\t\t\tt.Errorf(\"#%d. rewrite[%s] = <<%s>>, want <<%s>>\",\n\t\t\t\t\ti, k, v, test.wantRewrite[k])\n\t\t\t}\n\t\t\tdelete(test.wantRewrite, k)\n\t\t}\n\t\tfor k, v := range test.wantRewrite {\n\t\t\tt.Errorf(\"#%d. rewrite[%s] missing, want <<%s>>\", i, k, v)\n\t\t}\n\t}\n}\n\n// TestDryRun tests that the -n flag suppresses calls to writeFile.\nfunc TestDryRun(t *testing.T) {\n\tif os.Getenv(\"GO_BUILDER_NAME\") == \"plan9-arm\" {\n\t\tt.Skipf(\"skipping test that times out on plan9-arm; see https://go.dev/issue/50775\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\t*dryrun = true\n\tdefer func() { *dryrun = false }() // restore\n\tstderr = new(bytes.Buffer)\n\twriteFile = func(filename string, content []byte, mode os.FileMode) error {\n\t\tt.Fatalf(\"writeFile(%s) called in dryrun mode\", filename)\n\t\treturn nil\n\t}\n\n\tif !fiximports(\"all\") {\n\t\tt.Fatalf(\"fiximports failed: %s\", stderr)\n\t}\n}\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/fruit.io/banana/banana.go",
    "content": "package banana\n\nimport (\n\t_ \"old.com/one\"\n\t_ \"titanic.biz/bar\"\n\t_ \"titanic.biz/foo\"\n)\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/fruit.io/orange/orange.go",
    "content": "package orange\n\nimport _ \"fruit.io/pear\"\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/fruit.io/pear/pear.go",
    "content": "package pear\n\nimport _ \"fruit.io/banana\"\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/new.com/one/one.go",
    "content": "package one // import \"new.com/one\"\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/old.com/bad/bad.go",
    "content": "// This ill-formed Go source file is here to ensure the tool is robust\n// against bad packages in the workspace.\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/old.com/one/one.go",
    "content": "package one // import \"new.com/one\"\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/titanic.biz/bar/bar.go",
    "content": "// This package is moving to new.com too.\npackage bar // import \"new.com/bar\"\n"
  },
  {
    "path": "cmd/fiximports/testdata/src/titanic.biz/foo/foo.go",
    "content": "// This package hasn't jumped ship yet.\npackage foo\n"
  },
  {
    "path": "cmd/go-contrib-init/contrib.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The go-contrib-init command helps new Go contributors get their development\n// environment set up for the Go contribution process.\n//\n// It aims to be a complement or alternative to https://golang.org/doc/contribute.html.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n)\n\nvar (\n\trepo = flag.String(\"repo\", detectrepo(), \"Which go repo you want to contribute to. Use \\\"go\\\" for the core, or e.g. \\\"net\\\" for golang.org/x/net/*\")\n\tdry  = flag.Bool(\"dry-run\", false, \"Fail with problems instead of trying to fix things.\")\n)\n\nfunc main() {\n\tlog.SetFlags(0)\n\tflag.Parse()\n\n\tcheckCLA()\n\tcheckGoroot()\n\tcheckWorkingDir()\n\tcheckGitOrigin()\n\tcheckGitCodeReview()\n\tfmt.Print(\"All good. Happy hacking!\\n\" +\n\t\t\"Remember to squash your revised commits and preserve the magic Change-Id lines.\\n\" +\n\t\t\"Next steps: https://golang.org/doc/contribute.html#commit_changes\\n\")\n}\n\nfunc detectrepo() string {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn \"go\"\n\t}\n\n\tfor _, path := range filepath.SplitList(build.Default.GOPATH) {\n\t\trightdir := filepath.Join(path, \"src\", \"golang.org\", \"x\") + string(os.PathSeparator)\n\t\tif strings.HasPrefix(wd, rightdir) {\n\t\t\ttail := wd[len(rightdir):]\n\t\t\tend := strings.Index(tail, string(os.PathSeparator))\n\t\t\tif end > 0 {\n\t\t\t\trepo := tail[:end]\n\t\t\t\treturn repo\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"go\"\n}\n\nvar googleSourceRx = regexp.MustCompile(`(?m)^(go|go-review)?\\.googlesource.com\\b`)\n\nfunc checkCLA() {\n\tslurp, err := os.ReadFile(cookiesFile())\n\tif err != nil && !os.IsNotExist(err) {\n\t\tlog.Fatal(err)\n\t}\n\tif googleSourceRx.Match(slurp) {\n\t\t// Probably good.\n\t\treturn\n\t}\n\tlog.Fatal(\"Your .gitcookies file isn't configured.\\n\" +\n\t\t\"Next steps:\\n\" +\n\t\t\"  * Submit a CLA (https://golang.org/doc/contribute.html#cla) if not done\\n\" +\n\t\t\"  * Go to https://go.googlesource.com/ and click \\\"Generate Password\\\" at the top,\\n\" +\n\t\t\"    then follow instructions.\\n\" +\n\t\t\"  * Run go-contrib-init again.\\n\")\n}\n\nfunc expandUser(s string) string {\n\tenv := \"HOME\"\n\tif runtime.GOOS == \"windows\" {\n\t\tenv = \"USERPROFILE\"\n\t} else if runtime.GOOS == \"plan9\" {\n\t\tenv = \"home\"\n\t}\n\thome := os.Getenv(env)\n\tif home == \"\" {\n\t\treturn s\n\t}\n\n\tif len(s) >= 2 && s[0] == '~' && os.IsPathSeparator(s[1]) {\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\ts = filepath.ToSlash(filepath.Join(home, s[2:]))\n\t\t} else {\n\t\t\ts = filepath.Join(home, s[2:])\n\t\t}\n\t}\n\treturn os.Expand(s, func(env string) string {\n\t\tif env == \"HOME\" {\n\t\t\treturn home\n\t\t}\n\t\treturn os.Getenv(env)\n\t})\n}\n\nfunc cookiesFile() string {\n\tout, _ := exec.Command(\"git\", \"config\", \"http.cookiefile\").Output()\n\tif s := strings.TrimSpace(string(out)); s != \"\" {\n\t\tif strings.HasPrefix(s, \"~\") {\n\t\t\ts = expandUser(s)\n\t\t}\n\t\treturn s\n\t}\n\tif runtime.GOOS == \"windows\" {\n\t\treturn filepath.Join(os.Getenv(\"USERPROFILE\"), \".gitcookies\")\n\t}\n\treturn filepath.Join(os.Getenv(\"HOME\"), \".gitcookies\")\n}\n\nfunc checkGoroot() {\n\tv := os.Getenv(\"GOROOT\")\n\tif v == \"\" {\n\t\treturn\n\t}\n\tif *repo == \"go\" {\n\t\tif strings.HasPrefix(v, \"/usr/\") {\n\t\t\tlog.Fatalf(\"Your GOROOT environment variable is set to %q\\n\"+\n\t\t\t\t\"This is almost certainly not what you want. Either unset\\n\"+\n\t\t\t\t\"your GOROOT or set it to the path of your development version\\n\"+\n\t\t\t\t\"of Go.\", v)\n\t\t}\n\t\tslurp, err := os.ReadFile(filepath.Join(v, \"VERSION\"))\n\t\tif err == nil {\n\t\t\tslurp = bytes.TrimSpace(slurp)\n\t\t\tlog.Fatalf(\"Your GOROOT environment variable is set to %q\\n\"+\n\t\t\t\t\"But that path is to a binary release of Go, with VERSION file %q.\\n\"+\n\t\t\t\t\"You should hack on Go in a fresh checkout of Go. Fix or unset your GOROOT.\\n\",\n\t\t\t\tv, slurp)\n\t\t}\n\t}\n}\n\nfunc checkWorkingDir() {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif *repo == \"go\" {\n\t\tif inGoPath(wd) {\n\t\t\tlog.Fatalf(`You can't work on Go from within your GOPATH. Please checkout Go outside of your GOPATH\n\nCurrent directory: %s\nGOPATH: %s\n`, wd, os.Getenv(\"GOPATH\"))\n\t\t}\n\t\treturn\n\t}\n}\n\nfunc inGoPath(wd string) bool {\n\tif os.Getenv(\"GOPATH\") == \"\" {\n\t\treturn false\n\t}\n\n\tfor _, path := range filepath.SplitList(os.Getenv(\"GOPATH\")) {\n\t\tif strings.HasPrefix(wd, filepath.Join(path, \"src\")) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// mostly check that they didn't clone from github\nfunc checkGitOrigin() {\n\tif _, err := exec.LookPath(\"git\"); err != nil {\n\t\tlog.Fatalf(\"You don't appear to have git installed. Do that.\")\n\t}\n\twantRemote := \"https://go.googlesource.com/\" + *repo\n\tremotes, err := exec.Command(\"git\", \"remote\", \"-v\").Output()\n\tif err != nil {\n\t\tmsg := cmdErr(err)\n\t\tif strings.Contains(msg, \"Not a git repository\") {\n\t\t\tlog.Fatalf(\"Your current directory is not in a git checkout of %s\", wantRemote)\n\t\t}\n\t\tlog.Fatalf(\"Error running git remote -v: %v\", msg)\n\t}\n\tmatches := 0\n\tfor line := range strings.SplitSeq(string(remotes), \"\\n\") {\n\t\tline = strings.TrimSpace(line)\n\t\tif !strings.HasPrefix(line, \"origin\") {\n\t\t\tcontinue\n\t\t}\n\t\tif !strings.Contains(line, wantRemote) {\n\t\t\tcurRemote := strings.Fields(strings.TrimPrefix(line, \"origin\"))[0]\n\t\t\t// TODO: if not in dryRun mode, just fix it?\n\t\t\tlog.Fatalf(\"Current directory's git was cloned from %q; origin should be %q\", curRemote, wantRemote)\n\t\t}\n\t\tmatches++\n\t}\n\tif matches == 0 {\n\t\tlog.Fatalf(\"git remote -v output didn't contain expected %q. Got:\\n%s\", wantRemote, remotes)\n\t}\n}\n\nfunc cmdErr(err error) string {\n\tif ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {\n\t\treturn fmt.Sprintf(\"%s: %s\", err, ee.Stderr)\n\t}\n\treturn fmt.Sprint(err)\n}\n\nfunc checkGitCodeReview() {\n\tif _, err := exec.LookPath(\"git-codereview\"); err != nil {\n\t\tif *dry {\n\t\t\tlog.Fatalf(\"You don't appear to have git-codereview tool. While this is technically optional,\\n\" +\n\t\t\t\t\"almost all Go contributors use it. Our documentation and this tool assume it is used.\\n\" +\n\t\t\t\t\"To install it, run:\\n\\n\\t$ go get golang.org/x/review/git-codereview\\n\\n(Then run go-contrib-init again)\")\n\t\t}\n\t\terr := exec.Command(\"go\", \"get\", \"golang.org/x/review/git-codereview\").Run()\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Error running go get golang.org/x/review/git-codereview: %v\", cmdErr(err))\n\t\t}\n\t\tlog.Printf(\"Installed git-codereview (ran `go get golang.org/x/review/git-codereview`)\")\n\t}\n\tmissing := false\n\tfor _, cmd := range []string{\"change\", \"gofmt\", \"mail\", \"pending\", \"submit\", \"sync\"} {\n\t\tv, _ := exec.Command(\"git\", \"config\", \"alias.\"+cmd).Output()\n\t\tif strings.Contains(string(v), \"codereview\") {\n\t\t\tcontinue\n\t\t}\n\t\tif *dry {\n\t\t\tlog.Printf(\"Missing alias. Run:\\n\\t$ git config alias.%s \\\"codereview %s\\\"\", cmd, cmd)\n\t\t\tmissing = true\n\t\t} else {\n\t\t\terr := exec.Command(\"git\", \"config\", \"alias.\"+cmd, \"codereview \"+cmd).Run()\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"Error setting alias.%s: %v\", cmd, cmdErr(err))\n\t\t\t}\n\t\t}\n\t}\n\tif missing {\n\t\tlog.Fatalf(\"Missing aliases. (While optional, this tool assumes you use them.)\")\n\t}\n}\n"
  },
  {
    "path": "cmd/go-contrib-init/contrib_test.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestExpandUser(t *testing.T) {\n\tenv := \"HOME\"\n\tif runtime.GOOS == \"windows\" {\n\t\tenv = \"USERPROFILE\"\n\t} else if runtime.GOOS == \"plan9\" {\n\t\tenv = \"home\"\n\t}\n\n\toldenv := os.Getenv(env)\n\tos.Setenv(env, \"/home/gopher\")\n\tdefer os.Setenv(env, oldenv)\n\n\ttests := []struct {\n\t\tinput string\n\t\twant  string\n\t}{\n\t\t{input: \"~/foo\", want: \"/home/gopher/foo\"},\n\t\t{input: \"${HOME}/foo\", want: \"/home/gopher/foo\"},\n\t\t{input: \"/~/foo\", want: \"/~/foo\"},\n\t}\n\tfor _, tt := range tests {\n\t\tgot := expandUser(tt.input)\n\t\tif got != tt.want {\n\t\t\tt.Fatalf(\"want %q, but %q\", tt.want, got)\n\t\t}\n\t}\n}\n\nfunc TestCmdErr(t *testing.T) {\n\ttests := []struct {\n\t\tinput error\n\t\twant  string\n\t}{\n\t\t{input: errors.New(\"cmd error\"), want: \"cmd error\"},\n\t\t{input: &exec.ExitError{ProcessState: nil, Stderr: nil}, want: \"<nil>\"},\n\t\t{input: &exec.ExitError{ProcessState: nil, Stderr: []byte(\"test\")}, want: \"<nil>: test\"},\n\t}\n\n\tfor i, tt := range tests {\n\t\tgot := cmdErr(tt.input)\n\t\tif got != tt.want {\n\t\t\tt.Fatalf(\"%d. got %q, want %q\", i, got, tt.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/godex/doc.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The godex command prints (dumps) exported information of packages\n// or selected package objects.\n//\n// In contrast to godoc, godex extracts this information from compiled\n// object files. Hence the exported data is truly what a compiler will\n// see, at the cost of missing commentary.\n//\n// Usage: godex [flags] {path[.name]}\n//\n// Each argument must be a (possibly partial) package path, optionally\n// followed by a dot and the name of a package object:\n//\n//\tgodex math\n//\tgodex math.Sin\n//\tgodex math.Sin fmt.Printf\n//\tgodex go/types\n//\n// godex automatically tries all possible package path prefixes if only a\n// partial package path is given. For instance, for the path \"go/types\",\n// godex prepends \"golang.org/x/tools\".\n//\n// The prefixes are computed by searching the directories specified by\n// the GOROOT and GOPATH environment variables (and by excluding the\n// build OS- and architecture-specific directory names from the path).\n// The search order is depth-first and alphabetic; for a partial path\n// \"foo\", a package \"a/foo\" is found before \"b/foo\".\n//\n// Absolute and relative paths may be provided, which disable automatic\n// prefix generation:\n//\n//\tgodex $GOROOT/pkg/darwin_amd64/sort\n//\tgodex ./sort\n//\n// All but the last path element may contain dots; a dot in the last path\n// element separates the package path from the package object name. If the\n// last path element contains a dot, terminate the argument with another\n// dot (indicating an empty object name). For instance, the path for a\n// package foo.bar would be specified as in:\n//\n//\tgodex foo.bar.\n//\n// The flags are:\n//\n//\t-s=\"\"\n//\t\tonly consider packages from src, where src is one of the supported compilers\n//\t-v=false\n//\t\tverbose mode\n//\n// The following sources (-s arguments) are supported:\n//\n//\tgc\n//\t\tgc-generated object files\n//\tgccgo\n//\t\tgccgo-generated object files\n//\tgccgo-new\n//\t\tgccgo-generated object files using a condensed format (experimental)\n//\tsource\n//\t\t(uncompiled) source code (not yet implemented)\n//\n// If no -s argument is provided, godex will try to find a matching source.\npackage main // import \"golang.org/x/tools/cmd/godex\"\n\n// BUG(gri): support for -s=source is not yet implemented\n// BUG(gri): gccgo-importing appears to have occasional problems stalling godex; try -s=gc as work-around\n"
  },
  {
    "path": "cmd/godex/gc.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements access to gc-generated export data.\n\npackage main\n\nimport (\n\t\"go/importer\"\n\t\"go/token\"\n)\n\nfunc init() {\n\tregister(\"gc\", importer.ForCompiler(token.NewFileSet(), \"gc\", nil))\n}\n"
  },
  {
    "path": "cmd/godex/gccgo.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements access to gccgo-generated export data.\n\npackage main\n\nimport (\n\t\"go/importer\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\nfunc init() {\n\tregister(\"gccgo\", importer.ForCompiler(token.NewFileSet(), \"gccgo\", nil))\n}\n\n// Print the extra gccgo compiler data for this package, if it exists.\nfunc (p *printer) printGccgoExtra(pkg *types.Package) {\n\t// Disabled for now.\n\t// TODO(gri) address this at some point.\n\n\t// if initdata, ok := initmap[pkg]; ok {\n\t// \tp.printf(\"/*\\npriority %d\\n\", initdata.Priority)\n\n\t// \tp.printDecl(\"init\", len(initdata.Inits), func() {\n\t// \t\tfor _, init := range initdata.Inits {\n\t// \t\t\tp.printf(\"%s %s %d\\n\", init.Name, init.InitFunc, init.Priority)\n\t// \t\t}\n\t// \t})\n\n\t// \tp.print(\"*/\\n\")\n\t// }\n}\n"
  },
  {
    "path": "cmd/godex/godex.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nvar (\n\tsource  = flag.String(\"s\", \"\", \"only consider packages from src, where src is one of the supported compilers\")\n\tverbose = flag.Bool(\"v\", false, \"verbose mode\")\n)\n\n// lists of registered sources and corresponding importers\nvar (\n\tsources         []string\n\timporters       []types.Importer\n\terrImportFailed = errors.New(\"import failed\")\n)\n\nfunc usage() {\n\tfmt.Fprintln(os.Stderr, \"usage: godex [flags] {path|qualifiedIdent}\")\n\tflag.PrintDefaults()\n\tos.Exit(2)\n}\n\nfunc report(msg string) {\n\tfmt.Fprintln(os.Stderr, \"error: \"+msg)\n\tos.Exit(2)\n}\n\nfunc main() {\n\tflag.Usage = usage\n\tflag.Parse()\n\n\tif flag.NArg() == 0 {\n\t\treport(\"no package name, path, or file provided\")\n\t}\n\n\tvar imp types.Importer = new(tryImporters)\n\tif *source != \"\" {\n\t\timp = lookup(*source)\n\t\tif imp == nil {\n\t\t\treport(\"source (-s argument) must be one of: \" + strings.Join(sources, \", \"))\n\t\t}\n\t}\n\n\tfor _, arg := range flag.Args() {\n\t\tpath, name := splitPathIdent(arg)\n\t\tlogf(\"\\tprocessing %q: path = %q, name = %s\\n\", arg, path, name)\n\n\t\t// generate possible package path prefixes\n\t\t// (at the moment we do this for each argument - should probably cache the generated prefixes)\n\t\tprefixes := make(chan string)\n\t\tgo genPrefixes(prefixes, !filepath.IsAbs(path) && !build.IsLocalImport(path))\n\n\t\t// import package\n\t\tpkg, err := tryPrefixes(prefixes, path, imp)\n\t\tif err != nil {\n\t\t\tlogf(\"\\t=> ignoring %q: %s\\n\", path, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// filter objects if needed\n\t\tvar filter func(types.Object) bool\n\t\tif name != \"\" {\n\t\t\tfilter = func(obj types.Object) bool {\n\t\t\t\t// TODO(gri) perhaps use regular expression matching here?\n\t\t\t\treturn obj.Name() == name\n\t\t\t}\n\t\t}\n\n\t\t// print contents\n\t\tprint(os.Stdout, pkg, filter)\n\t}\n}\n\nfunc logf(format string, args ...any) {\n\tif *verbose {\n\t\tfmt.Fprintf(os.Stderr, format, args...)\n\t}\n}\n\n// splitPathIdent splits a path.name argument into its components.\n// All but the last path element may contain dots.\nfunc splitPathIdent(arg string) (path, name string) {\n\tif i := strings.LastIndex(arg, \".\"); i >= 0 {\n\t\tif j := strings.LastIndex(arg, \"/\"); j < i {\n\t\t\t// '.' is not part of path\n\t\t\tpath = arg[:i]\n\t\t\tname = arg[i+1:]\n\t\t\treturn\n\t\t}\n\t}\n\tpath = arg\n\treturn\n}\n\n// tryPrefixes tries to import the package given by (the possibly partial) path using the given importer imp\n// by prepending all possible prefixes to path. It returns with the first package that it could import, or\n// with an error.\nfunc tryPrefixes(prefixes chan string, path string, imp types.Importer) (pkg *types.Package, err error) {\n\tfor prefix := range prefixes {\n\t\tactual := path\n\t\tif prefix == \"\" {\n\t\t\t// don't use filepath.Join as it will sanitize the path and remove\n\t\t\t// a leading dot and then the path is not recognized as a relative\n\t\t\t// package path by the importers anymore\n\t\t\tlogf(\"\\ttrying no prefix\\n\")\n\t\t} else {\n\t\t\tactual = filepath.Join(prefix, path)\n\t\t\tlogf(\"\\ttrying prefix %q\\n\", prefix)\n\t\t}\n\t\tpkg, err = imp.Import(actual)\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t\tlogf(\"\\t=> importing %q failed: %s\\n\", actual, err)\n\t}\n\treturn\n}\n\n// tryImporters is an importer that tries all registered importers\n// successively until one of them succeeds or all of them failed.\ntype tryImporters struct{}\n\nfunc (t *tryImporters) Import(path string) (pkg *types.Package, err error) {\n\tfor i, imp := range importers {\n\t\tlogf(\"\\t\\ttrying %s import\\n\", sources[i])\n\t\tpkg, err = imp.Import(path)\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t\tlogf(\"\\t\\t=> %s import failed: %s\\n\", sources[i], err)\n\t}\n\treturn\n}\n\ntype protector struct {\n\timp types.Importer\n}\n\nfunc (p *protector) Import(path string) (pkg *types.Package, err error) {\n\tdefer func() {\n\t\tif recover() != nil {\n\t\t\tpkg = nil\n\t\t\terr = errImportFailed\n\t\t}\n\t}()\n\treturn p.imp.Import(path)\n}\n\n// protect protects an importer imp from panics and returns the protected importer.\nfunc protect(imp types.Importer) types.Importer {\n\treturn &protector{imp}\n}\n\n// register registers an importer imp for a given source src.\nfunc register(src string, imp types.Importer) {\n\tif lookup(src) != nil {\n\t\tpanic(src + \" importer already registered\")\n\t}\n\tsources = append(sources, src)\n\timporters = append(importers, protect(imp))\n}\n\n// lookup returns the importer imp for a given source src.\nfunc lookup(src string) types.Importer {\n\tfor i, s := range sources {\n\t\tif s == src {\n\t\t\treturn importers[i]\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc genPrefixes(out chan string, all bool) {\n\tout <- \"\"\n\tif all {\n\t\tplatform := build.Default.GOOS + \"_\" + build.Default.GOARCH\n\t\tdirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)\n\t\tfor _, dirname := range dirnames {\n\t\t\twalkDir(filepath.Join(dirname, \"pkg\", platform), \"\", out)\n\t\t}\n\t}\n\tclose(out)\n}\n\nfunc walkDir(dirname, prefix string, out chan string) {\n\tfiList, err := os.ReadDir(dirname)\n\tif err != nil {\n\t\treturn\n\t}\n\tfor _, fi := range fiList {\n\t\tif fi.IsDir() && !strings.HasPrefix(fi.Name(), \".\") {\n\t\t\tprefix := filepath.Join(prefix, fi.Name())\n\t\t\tout <- prefix\n\t\t\twalkDir(filepath.Join(dirname, fi.Name()), prefix, out)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/godex/isAlias18.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.9\n\npackage main\n\nimport \"go/types\"\n\nfunc isAlias(obj *types.TypeName) bool {\n\treturn false // there are no type aliases before Go 1.9\n}\n"
  },
  {
    "path": "cmd/godex/isAlias19.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.9\n\npackage main\n\nimport \"go/types\"\n\nfunc isAlias(obj *types.TypeName) bool {\n\treturn obj.IsAlias()\n}\n"
  },
  {
    "path": "cmd/godex/print.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"math/big\"\n)\n\n// TODO(gri) use tabwriter for alignment?\n\nfunc print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {\n\tvar p printer\n\tp.pkg = pkg\n\tp.printPackage(pkg, filter)\n\tp.printGccgoExtra(pkg)\n\tio.Copy(w, &p.buf)\n}\n\ntype printer struct {\n\tpkg    *types.Package\n\tbuf    bytes.Buffer\n\tindent int  // current indentation level\n\tlast   byte // last byte written\n}\n\nfunc (p *printer) print(s string) {\n\t// Write the string one byte at a time. We care about the presence of\n\t// newlines for indentation which we will see even in the presence of\n\t// (non-corrupted) Unicode; no need to read one rune at a time.\n\tfor i := 0; i < len(s); i++ {\n\t\tch := s[i]\n\t\tif ch != '\\n' && p.last == '\\n' {\n\t\t\t// Note: This could lead to a range overflow for very large\n\t\t\t// indentations, but it's extremely unlikely to happen for\n\t\t\t// non-pathological code.\n\t\t\tp.buf.WriteString(\"\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\"[:p.indent])\n\t\t}\n\t\tp.buf.WriteByte(ch)\n\t\tp.last = ch\n\t}\n}\n\nfunc (p *printer) printf(format string, args ...any) {\n\tp.print(fmt.Sprintf(format, args...))\n}\n\n// methodsFor returns the named type and corresponding methods if the type\n// denoted by obj is not an interface and has methods. Otherwise it returns\n// the zero value.\nfunc methodsFor(obj *types.TypeName) (*types.Named, []*types.Selection) {\n\tnamed, _ := types.Unalias(obj.Type()).(*types.Named)\n\tif named == nil {\n\t\t// A type name's type can also be the\n\t\t// exported basic type unsafe.Pointer.\n\t\treturn nil, nil\n\t}\n\tif _, ok := named.Underlying().(*types.Interface); ok {\n\t\t// ignore interfaces\n\t\treturn nil, nil\n\t}\n\tmethods := combinedMethodSet(named)\n\tif len(methods) == 0 {\n\t\treturn nil, nil\n\t}\n\treturn named, methods\n}\n\nfunc (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {\n\t// collect objects by kind\n\tvar (\n\t\tconsts   []*types.Const\n\t\ttypem    []*types.Named    // non-interface types with methods\n\t\ttypez    []*types.TypeName // interfaces or types without methods\n\t\tvars     []*types.Var\n\t\tfuncs    []*types.Func\n\t\tbuiltins []*types.Builtin\n\t\tmethods  = make(map[*types.Named][]*types.Selection) // method sets for named types\n\t)\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif obj.Exported() {\n\t\t\t// collect top-level exported and possibly filtered objects\n\t\t\tif filter == nil || filter(obj) {\n\t\t\t\tswitch obj := obj.(type) {\n\t\t\t\tcase *types.Const:\n\t\t\t\t\tconsts = append(consts, obj)\n\t\t\t\tcase *types.TypeName:\n\t\t\t\t\t// group into types with methods and types without\n\t\t\t\t\tif named, m := methodsFor(obj); named != nil {\n\t\t\t\t\t\ttypem = append(typem, named)\n\t\t\t\t\t\tmethods[named] = m\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttypez = append(typez, obj)\n\t\t\t\t\t}\n\t\t\t\tcase *types.Var:\n\t\t\t\t\tvars = append(vars, obj)\n\t\t\t\tcase *types.Func:\n\t\t\t\t\tfuncs = append(funcs, obj)\n\t\t\t\tcase *types.Builtin:\n\t\t\t\t\t// for unsafe.Sizeof, etc.\n\t\t\t\t\tbuiltins = append(builtins, obj)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if filter == nil {\n\t\t\t// no filtering: collect top-level unexported types with methods\n\t\t\tif obj, _ := obj.(*types.TypeName); obj != nil {\n\t\t\t\t// see case *types.TypeName above\n\t\t\t\tif named, m := methodsFor(obj); named != nil {\n\t\t\t\t\ttypem = append(typem, named)\n\t\t\t\t\tmethods[named] = m\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tp.printf(\"package %s  // %q\\n\", pkg.Name(), pkg.Path())\n\n\tp.printDecl(\"const\", len(consts), func() {\n\t\tfor _, obj := range consts {\n\t\t\tp.printObj(obj)\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t})\n\n\tp.printDecl(\"var\", len(vars), func() {\n\t\tfor _, obj := range vars {\n\t\t\tp.printObj(obj)\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t})\n\n\tp.printDecl(\"type\", len(typez), func() {\n\t\tfor _, obj := range typez {\n\t\t\tp.printf(\"%s \", obj.Name())\n\t\t\ttyp := obj.Type()\n\t\t\tif isAlias(obj) {\n\t\t\t\tp.print(\"= \")\n\t\t\t\tp.writeType(p.pkg, typ)\n\t\t\t} else {\n\t\t\t\tp.writeType(p.pkg, typ.Underlying())\n\t\t\t}\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t})\n\n\t// non-interface types with methods\n\tfor _, named := range typem {\n\t\tfirst := true\n\t\tif obj := named.Obj(); obj.Exported() {\n\t\t\tif first {\n\t\t\t\tp.print(\"\\n\")\n\t\t\t\tfirst = false\n\t\t\t}\n\t\t\tp.printf(\"type %s \", obj.Name())\n\t\t\tp.writeType(p.pkg, named.Underlying())\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t\tfor _, m := range methods[named] {\n\t\t\tif obj := m.Obj(); obj.Exported() {\n\t\t\t\tif first {\n\t\t\t\t\tp.print(\"\\n\")\n\t\t\t\t\tfirst = false\n\t\t\t\t}\n\t\t\t\tp.printFunc(m.Recv(), obj.(*types.Func))\n\t\t\t\tp.print(\"\\n\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(funcs) > 0 {\n\t\tp.print(\"\\n\")\n\t\tfor _, obj := range funcs {\n\t\t\tp.printFunc(nil, obj)\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t}\n\n\t// TODO(gri) better handling of builtins (package unsafe only)\n\tif len(builtins) > 0 {\n\t\tp.print(\"\\n\")\n\t\tfor _, obj := range builtins {\n\t\t\tp.printf(\"func %s() // builtin\\n\", obj.Name())\n\t\t}\n\t}\n\n\tp.print(\"\\n\")\n}\n\nfunc (p *printer) printDecl(keyword string, n int, printGroup func()) {\n\tswitch n {\n\tcase 0:\n\t\t// nothing to do\n\tcase 1:\n\t\tp.printf(\"\\n%s \", keyword)\n\t\tprintGroup()\n\tdefault:\n\t\tp.printf(\"\\n%s (\\n\", keyword)\n\t\tp.indent++\n\t\tprintGroup()\n\t\tp.indent--\n\t\tp.print(\")\\n\")\n\t}\n}\n\n// absInt returns the absolute value of v as a *big.Int.\n// v must be a numeric value.\nfunc absInt(v constant.Value) *big.Int {\n\t// compute big-endian representation of v\n\tb := constant.Bytes(v) // little-endian\n\tfor i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {\n\t\tb[i], b[j] = b[j], b[i]\n\t}\n\treturn new(big.Int).SetBytes(b)\n}\n\nvar (\n\tone = big.NewRat(1, 1)\n\tten = big.NewRat(10, 1)\n)\n\n// floatString returns the string representation for a\n// numeric value v in normalized floating-point format.\nfunc floatString(v constant.Value) string {\n\tif constant.Sign(v) == 0 {\n\t\treturn \"0.0\"\n\t}\n\t// x != 0\n\n\t// convert |v| into a big.Rat x\n\tx := new(big.Rat).SetFrac(absInt(constant.Num(v)), absInt(constant.Denom(v)))\n\n\t// normalize x and determine exponent e\n\t// (This is not very efficient, but also not speed-critical.)\n\tvar e int\n\tfor x.Cmp(ten) >= 0 {\n\t\tx.Quo(x, ten)\n\t\te++\n\t}\n\tfor x.Cmp(one) < 0 {\n\t\tx.Mul(x, ten)\n\t\te--\n\t}\n\n\t// TODO(gri) Values such as 1/2 are easier to read in form 0.5\n\t// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as\n\t// 10.0. Fine-tune best exponent range for readability.\n\n\ts := x.FloatString(100) // good-enough precision\n\n\t// trim trailing 0's\n\ti := len(s)\n\tfor i > 0 && s[i-1] == '0' {\n\t\ti--\n\t}\n\ts = s[:i]\n\n\t// add a 0 if the number ends in decimal point\n\tif len(s) > 0 && s[len(s)-1] == '.' {\n\t\ts += \"0\"\n\t}\n\n\t// add exponent and sign\n\tif e != 0 {\n\t\ts += fmt.Sprintf(\"e%+d\", e)\n\t}\n\tif constant.Sign(v) < 0 {\n\t\ts = \"-\" + s\n\t}\n\n\t// TODO(gri) If v is a \"small\" fraction (i.e., numerator and denominator\n\t// are just a small number of decimal digits), add the exact fraction as\n\t// a comment. For instance: 3.3333...e-1 /* = 1/3 */\n\n\treturn s\n}\n\n// valString returns the string representation for the value v.\n// Setting floatFmt forces an integer value to be formatted in\n// normalized floating-point format.\n// TODO(gri) Move this code into package constant.\nfunc valString(v constant.Value, floatFmt bool) string {\n\tswitch v.Kind() {\n\tcase constant.Int:\n\t\tif floatFmt {\n\t\t\treturn floatString(v)\n\t\t}\n\tcase constant.Float:\n\t\treturn floatString(v)\n\tcase constant.Complex:\n\t\tre := constant.Real(v)\n\t\tim := constant.Imag(v)\n\t\tvar s string\n\t\tif constant.Sign(re) != 0 {\n\t\t\ts = floatString(re)\n\t\t\tif constant.Sign(im) >= 0 {\n\t\t\t\ts += \" + \"\n\t\t\t} else {\n\t\t\t\ts += \" - \"\n\t\t\t\tim = constant.UnaryOp(token.SUB, im, 0) // negate im\n\t\t\t}\n\t\t}\n\t\t// im != 0, otherwise v would be constant.Int or constant.Float\n\t\treturn s + floatString(im) + \"i\"\n\t}\n\treturn v.String()\n}\n\nfunc (p *printer) printObj(obj types.Object) {\n\tp.print(obj.Name())\n\n\ttyp, basic := obj.Type().Underlying().(*types.Basic)\n\tif basic && typ.Info()&types.IsUntyped != 0 {\n\t\t// don't write untyped types\n\t} else {\n\t\tp.print(\" \")\n\t\tp.writeType(p.pkg, obj.Type())\n\t}\n\n\tif obj, ok := obj.(*types.Const); ok {\n\t\tfloatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0\n\t\tp.print(\" = \")\n\t\tp.print(valString(obj.Val(), floatFmt))\n\t}\n}\n\nfunc (p *printer) printFunc(recvType types.Type, obj *types.Func) {\n\tp.print(\"func \")\n\tsig := obj.Type().(*types.Signature)\n\tif recvType != nil {\n\t\tp.print(\"(\")\n\t\tp.writeType(p.pkg, recvType)\n\t\tp.print(\") \")\n\t}\n\tp.print(obj.Name())\n\tp.writeSignature(p.pkg, sig)\n}\n\n// combinedMethodSet returns the method set for a named type T\n// merged with all the methods of *T that have different names than\n// the methods of T.\n//\n// combinedMethodSet is analogous to types/typeutil.IntuitiveMethodSet\n// but doesn't require a MethodSetCache.\n// TODO(gri) If this functionality doesn't change over time, consider\n// just calling IntuitiveMethodSet eventually.\nfunc combinedMethodSet(T *types.Named) []*types.Selection {\n\t// method set for T\n\tmset := types.NewMethodSet(T)\n\tvar res []*types.Selection\n\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\tres = append(res, mset.At(i))\n\t}\n\n\t// add all *T methods with names different from T methods\n\tpmset := types.NewMethodSet(types.NewPointer(T))\n\tfor i, n := 0, pmset.Len(); i < n; i++ {\n\t\tpm := pmset.At(i)\n\t\tif obj := pm.Obj(); mset.Lookup(obj.Pkg(), obj.Name()) == nil {\n\t\t\tres = append(res, pm)\n\t\t}\n\t}\n\n\treturn res\n}\n"
  },
  {
    "path": "cmd/godex/source.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements access to export data from source.\n\npackage main\n\nimport \"go/types\"\n\nfunc init() {\n\tregister(\"source\", sourceImporter{})\n}\n\ntype sourceImporter struct{}\n\nfunc (sourceImporter) Import(path string) (*types.Package, error) {\n\tpanic(\"unimplemented\")\n}\n"
  },
  {
    "path": "cmd/godex/writetype.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements writing of types. The functionality is lifted\n// directly from go/types, but now contains various modifications for\n// nicer output.\n//\n// TODO(gri) back-port once we have a fixed interface and once the\n// go/types API is not frozen anymore for the 1.3 release; and remove\n// this implementation if possible.\n\npackage main\n\nimport (\n\t\"go/types\"\n\t\"slices\"\n)\n\nfunc (p *printer) writeType(this *types.Package, typ types.Type) {\n\tp.writeTypeInternal(this, typ, make([]types.Type, 8))\n}\n\n// From go/types - leave for now to ease back-porting this code.\nconst GcCompatibilityMode = false\n\nfunc (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {\n\t// Theoretically, this is a quadratic lookup algorithm, but in\n\t// practice deeply nested composite types with unnamed component\n\t// types are uncommon. This code is likely more efficient than\n\t// using a map.\n\tif slices.Contains(visited, typ) {\n\t\tp.printf(\"○%T\", typ) // cycle to typ\n\t\treturn\n\t}\n\tvisited = append(visited, typ)\n\n\tswitch t := typ.(type) {\n\tcase nil:\n\t\tp.print(\"<nil>\")\n\n\tcase *types.Basic:\n\t\tif t.Kind() == types.UnsafePointer {\n\t\t\tp.print(\"unsafe.\")\n\t\t}\n\t\tif GcCompatibilityMode {\n\t\t\t// forget the alias names\n\t\t\tswitch t.Kind() {\n\t\t\tcase types.Byte:\n\t\t\t\tt = types.Typ[types.Uint8]\n\t\t\tcase types.Rune:\n\t\t\t\tt = types.Typ[types.Int32]\n\t\t\t}\n\t\t}\n\t\tp.print(t.Name())\n\n\tcase *types.Array:\n\t\tp.printf(\"[%d]\", t.Len())\n\t\tp.writeTypeInternal(this, t.Elem(), visited)\n\n\tcase *types.Slice:\n\t\tp.print(\"[]\")\n\t\tp.writeTypeInternal(this, t.Elem(), visited)\n\n\tcase *types.Struct:\n\t\tn := t.NumFields()\n\t\tif n == 0 {\n\t\t\tp.print(\"struct{}\")\n\t\t\treturn\n\t\t}\n\n\t\tp.print(\"struct {\\n\")\n\t\tp.indent++\n\t\tfor i := range n {\n\t\t\tf := t.Field(i)\n\t\t\tif !f.Anonymous() {\n\t\t\t\tp.printf(\"%s \", f.Name())\n\t\t\t}\n\t\t\tp.writeTypeInternal(this, f.Type(), visited)\n\t\t\tif tag := t.Tag(i); tag != \"\" {\n\t\t\t\tp.printf(\" %q\", tag)\n\t\t\t}\n\t\t\tp.print(\"\\n\")\n\t\t}\n\t\tp.indent--\n\t\tp.print(\"}\")\n\n\tcase *types.Pointer:\n\t\tp.print(\"*\")\n\t\tp.writeTypeInternal(this, t.Elem(), visited)\n\n\tcase *types.Tuple:\n\t\tp.writeTuple(this, t, false, visited)\n\n\tcase *types.Signature:\n\t\tp.print(\"func\")\n\t\tp.writeSignatureInternal(this, t, visited)\n\n\tcase *types.Interface:\n\t\t// We write the source-level methods and embedded types rather\n\t\t// than the actual method set since resolved method signatures\n\t\t// may have non-printable cycles if parameters have anonymous\n\t\t// interface types that (directly or indirectly) embed the\n\t\t// current interface. For instance, consider the result type\n\t\t// of m:\n\t\t//\n\t\t//     type T interface{\n\t\t//         m() interface{ T }\n\t\t//     }\n\t\t//\n\t\tn := t.NumMethods()\n\t\tif n == 0 {\n\t\t\tp.print(\"any\")\n\t\t\treturn\n\t\t}\n\n\t\tp.print(\"interface {\\n\")\n\t\tp.indent++\n\t\tif GcCompatibilityMode {\n\t\t\t// print flattened interface\n\t\t\t// (useful to compare against gc-generated interfaces)\n\t\t\tfor i := range n {\n\t\t\t\tm := t.Method(i)\n\t\t\t\tp.print(m.Name())\n\t\t\t\tp.writeSignatureInternal(this, m.Type().(*types.Signature), visited)\n\t\t\t\tp.print(\"\\n\")\n\t\t\t}\n\t\t} else {\n\t\t\t// print explicit interface methods and embedded types\n\t\t\tfor i, n := 0, t.NumExplicitMethods(); i < n; i++ {\n\t\t\t\tm := t.ExplicitMethod(i)\n\t\t\t\tp.print(m.Name())\n\t\t\t\tp.writeSignatureInternal(this, m.Type().(*types.Signature), visited)\n\t\t\t\tp.print(\"\\n\")\n\t\t\t}\n\t\t\tfor i, n := 0, t.NumEmbeddeds(); i < n; i++ {\n\t\t\t\ttyp := t.EmbeddedType(i)\n\t\t\t\tp.writeTypeInternal(this, typ, visited)\n\t\t\t\tp.print(\"\\n\")\n\t\t\t}\n\t\t}\n\t\tp.indent--\n\t\tp.print(\"}\")\n\n\tcase *types.Map:\n\t\tp.print(\"map[\")\n\t\tp.writeTypeInternal(this, t.Key(), visited)\n\t\tp.print(\"]\")\n\t\tp.writeTypeInternal(this, t.Elem(), visited)\n\n\tcase *types.Chan:\n\t\tvar s string\n\t\tvar parens bool\n\t\tswitch t.Dir() {\n\t\tcase types.SendRecv:\n\t\t\ts = \"chan \"\n\t\t\t// chan (<-chan T) requires parentheses\n\t\t\tif c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {\n\t\t\t\tparens = true\n\t\t\t}\n\t\tcase types.SendOnly:\n\t\t\ts = \"chan<- \"\n\t\tcase types.RecvOnly:\n\t\t\ts = \"<-chan \"\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t\tp.print(s)\n\t\tif parens {\n\t\t\tp.print(\"(\")\n\t\t}\n\t\tp.writeTypeInternal(this, t.Elem(), visited)\n\t\tif parens {\n\t\t\tp.print(\")\")\n\t\t}\n\n\tcase *types.Alias:\n\t\t// TODO(adonovan): display something aliasy.\n\t\tp.writeTypeInternal(this, types.Unalias(t), visited)\n\n\tcase *types.Named:\n\t\ts := \"<Named w/o object>\"\n\t\tif obj := t.Obj(); obj != nil {\n\t\t\tif pkg := obj.Pkg(); pkg != nil {\n\t\t\t\tif pkg != this {\n\t\t\t\t\tp.print(pkg.Path())\n\t\t\t\t\tp.print(\".\")\n\t\t\t\t}\n\t\t\t\t// TODO(gri): function-local named types should be displayed\n\t\t\t\t// differently from named types at package level to avoid\n\t\t\t\t// ambiguity.\n\t\t\t}\n\t\t\ts = obj.Name()\n\t\t}\n\t\tp.print(s)\n\n\tdefault:\n\t\t// For externally defined implementations of Type.\n\t\tp.print(t.String())\n\t}\n}\n\nfunc (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {\n\tp.print(\"(\")\n\tfor i, n := 0, tup.Len(); i < n; i++ {\n\t\tif i > 0 {\n\t\t\tp.print(\", \")\n\t\t}\n\t\tv := tup.At(i)\n\t\tif name := v.Name(); name != \"\" {\n\t\t\tp.print(name)\n\t\t\tp.print(\" \")\n\t\t}\n\t\ttyp := v.Type()\n\t\tif variadic && i == n-1 {\n\t\t\tp.print(\"...\")\n\t\t\ttyp = typ.(*types.Slice).Elem()\n\t\t}\n\t\tp.writeTypeInternal(this, typ, visited)\n\t}\n\tp.print(\")\")\n}\n\nfunc (p *printer) writeSignature(this *types.Package, sig *types.Signature) {\n\tp.writeSignatureInternal(this, sig, make([]types.Type, 8))\n}\n\nfunc (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {\n\tp.writeTuple(this, sig.Params(), sig.Variadic(), visited)\n\n\tres := sig.Results()\n\tn := res.Len()\n\tif n == 0 {\n\t\t// no result\n\t\treturn\n\t}\n\n\tp.print(\" \")\n\tif n == 1 && res.At(0).Name() == \"\" {\n\t\t// single unnamed result\n\t\tp.writeTypeInternal(this, res.At(0).Type(), visited)\n\t\treturn\n\t}\n\n\t// multiple or named result(s)\n\tp.writeTuple(this, res, false, visited)\n}\n"
  },
  {
    "path": "cmd/goimports/doc.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nCommand goimports updates your Go import lines,\nadding missing ones and removing unreferenced ones.\n\n\t$ go install golang.org/x/tools/cmd/goimports@latest\n\nIn addition to fixing imports, goimports also formats\nyour code in the same style as gofmt so it can be used\nas a replacement for your editor's gofmt-on-save hook.\n\nFor emacs, make sure you have the latest go-mode.el:\n\n\thttps://github.com/dominikh/go-mode.el\n\nThen in your .emacs file:\n\n\t(setq gofmt-command \"goimports\")\n\t(add-hook 'before-save-hook 'gofmt-before-save)\n\nFor vim, set \"gofmt_command\" to \"goimports\":\n\n\thttps://golang.org/change/39c724dd7f252\n\thttps://golang.org/wiki/IDEsAndTextEditorPlugins\n\tetc\n\nFor GoSublime, follow the steps described here:\n\n\thttp://michaelwhatcott.com/gosublime-goimports/\n\nFor other editors, you probably know what to do.\n\nTo exclude directories in your $GOPATH from being scanned for Go\nfiles, goimports respects a configuration file at\n$GOPATH/src/.goimportsignore which may contain blank lines, comment\nlines (beginning with '#'), or lines naming a directory relative to\nthe configuration file to ignore when scanning. No globbing or regex\npatterns are allowed. Use the \"-v\" verbose flag to verify it's\nworking and see what goimports is doing.\n\nFile bugs or feature requests at:\n\n\thttps://golang.org/issues/new?title=x/tools/cmd/goimports:+\n\nHappy hacking!\n*/\npackage main // import \"golang.org/x/tools/cmd/goimports\"\n"
  },
  {
    "path": "cmd/goimports/goimports.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/scanner\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"strings\"\n\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\nvar (\n\t// main operation modes\n\tlist   = flag.Bool(\"l\", false, \"list files whose formatting differs from goimport's\")\n\twrite  = flag.Bool(\"w\", false, \"write result to (source) file instead of stdout\")\n\tdoDiff = flag.Bool(\"d\", false, \"display diffs instead of rewriting files\")\n\tsrcdir = flag.String(\"srcdir\", \"\", \"choose imports as if source code is from `dir`. When operating on a single file, dir may instead be the complete file name.\")\n\n\tverbose bool // verbose logging\n\n\tcpuProfile     = flag.String(\"cpuprofile\", \"\", \"CPU profile output\")\n\tmemProfile     = flag.String(\"memprofile\", \"\", \"memory profile output\")\n\tmemProfileRate = flag.Int(\"memrate\", 0, \"if > 0, sets runtime.MemProfileRate\")\n\n\toptions = &imports.Options{\n\t\tTabWidth:  8,\n\t\tTabIndent: true,\n\t\tComments:  true,\n\t\tFragment:  true,\n\t\tEnv: &imports.ProcessEnv{\n\t\t\tGocmdRunner: &gocommand.Runner{},\n\t\t},\n\t}\n\texitCode = 0\n)\n\nfunc init() {\n\tflag.BoolVar(&options.AllErrors, \"e\", false, \"report all errors (not just the first 10 on different lines)\")\n\tflag.StringVar(&options.LocalPrefix, \"local\", \"\", \"put imports beginning with this string after 3rd-party packages; comma-separated list\")\n\tflag.BoolVar(&options.FormatOnly, \"format-only\", false, \"if true, don't fix imports and only format. In this mode, goimports is effectively gofmt, with the addition that imports are grouped into sections.\")\n}\n\nfunc report(err error) {\n\tscanner.PrintError(os.Stderr, err)\n\texitCode = 2\n}\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: goimports [flags] [path ...]\\n\")\n\tflag.PrintDefaults()\n\tos.Exit(2)\n}\n\nfunc isGoFile(f os.FileInfo) bool {\n\t// ignore non-Go files\n\tname := f.Name()\n\treturn !f.IsDir() && !strings.HasPrefix(name, \".\") && strings.HasSuffix(name, \".go\")\n}\n\n// argumentType is which mode goimports was invoked as.\ntype argumentType int\n\nconst (\n\t// fromStdin means the user is piping their source into goimports.\n\tfromStdin argumentType = iota\n\n\t// singleArg is the common case from editors, when goimports is run on\n\t// a single file.\n\tsingleArg\n\n\t// multipleArg is when the user ran \"goimports file1.go file2.go\"\n\t// or ran goimports on a directory tree.\n\tmultipleArg\n)\n\nfunc processFile(filename string, in io.Reader, out io.Writer, argType argumentType) error {\n\topt := options\n\tif argType == fromStdin {\n\t\tnopt := *options\n\t\tnopt.Fragment = true\n\t\topt = &nopt\n\t}\n\n\tif in == nil {\n\t\tf, err := os.Open(filename)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer f.Close()\n\t\tin = f\n\t}\n\n\tsrc, err := io.ReadAll(in)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttarget := filename\n\tif *srcdir != \"\" {\n\t\t// Determine whether the provided -srcdirc is a directory or file\n\t\t// and then use it to override the target.\n\t\t//\n\t\t// See https://github.com/dominikh/go-mode.el/issues/146\n\t\tif isFile(*srcdir) {\n\t\t\tif argType == multipleArg {\n\t\t\t\treturn errors.New(\"-srcdir value can't be a file when passing multiple arguments or when walking directories\")\n\t\t\t}\n\t\t\ttarget = *srcdir\n\t\t} else if argType == singleArg && strings.HasSuffix(*srcdir, \".go\") && !isDir(*srcdir) {\n\t\t\t// For a file which doesn't exist on disk yet, but might shortly.\n\t\t\t// e.g. user in editor opens $DIR/newfile.go and newfile.go doesn't yet exist on disk.\n\t\t\t// The goimports on-save hook writes the buffer to a temp file\n\t\t\t// first and runs goimports before the actual save to newfile.go.\n\t\t\t// The editor's buffer is named \"newfile.go\" so that is passed to goimports as:\n\t\t\t//      goimports -srcdir=/gopath/src/pkg/newfile.go /tmp/gofmtXXXXXXXX.go\n\t\t\t// and then the editor reloads the result from the tmp file and writes\n\t\t\t// it to newfile.go.\n\t\t\ttarget = *srcdir\n\t\t} else {\n\t\t\t// Pretend that file is from *srcdir in order to decide\n\t\t\t// visible imports correctly.\n\t\t\ttarget = filepath.Join(*srcdir, filepath.Base(filename))\n\t\t}\n\t}\n\n\tres, err := imports.Process(target, src, opt)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !bytes.Equal(src, res) {\n\t\t// formatting has changed\n\t\tif *list {\n\t\t\tfmt.Fprintln(out, filename)\n\t\t}\n\t\tif *write {\n\t\t\tif argType == fromStdin {\n\t\t\t\t// filename is \"<standard input>\"\n\t\t\t\treturn errors.New(\"can't use -w on stdin\")\n\t\t\t}\n\t\t\t// On Windows, we need to re-set the permissions from the file. See golang/go#38225.\n\t\t\tvar perms os.FileMode\n\t\t\tif fi, err := os.Stat(filename); err == nil {\n\t\t\t\tperms = fi.Mode() & os.ModePerm\n\t\t\t}\n\t\t\terr = os.WriteFile(filename, res, perms)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif *doDiff {\n\t\t\tif argType == fromStdin {\n\t\t\t\tfilename = \"stdin.go\" // because <standard input>.orig looks silly\n\t\t\t}\n\t\t\tdata, err := diff(src, res, filename)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"computing diff: %s\", err)\n\t\t\t}\n\t\t\tfmt.Printf(\"diff -u %s %s\\n\", filepath.ToSlash(filename+\".orig\"), filepath.ToSlash(filename))\n\t\t\tout.Write(data)\n\t\t}\n\t}\n\n\tif !*list && !*write && !*doDiff {\n\t\t_, err = out.Write(res)\n\t}\n\n\treturn err\n}\n\nfunc visitFile(path string, f os.FileInfo, err error) error {\n\tif err == nil && isGoFile(f) {\n\t\terr = processFile(path, nil, os.Stdout, multipleArg)\n\t}\n\tif err != nil {\n\t\treport(err)\n\t}\n\treturn nil\n}\n\nfunc walkDir(path string) {\n\tfilepath.Walk(path, visitFile)\n}\n\nfunc main() {\n\t// is anyone using this command?\n\tcounter.Open()\n\tcounter.Inc(\"tools/cmd:goimports\")\n\truntime.GOMAXPROCS(runtime.NumCPU())\n\n\t// call gofmtMain in a separate function\n\t// so that it can use defer and have them\n\t// run before the exit.\n\tgofmtMain()\n\tos.Exit(exitCode)\n}\n\n// parseFlags parses command line flags and returns the paths to process.\n// It's a var so that custom implementations can replace it in other files.\nvar parseFlags = func() []string {\n\tflag.BoolVar(&verbose, \"v\", false, \"verbose logging\")\n\n\tflag.Parse()\n\treturn flag.Args()\n}\n\nfunc bufferedFileWriter(dest string) (w io.Writer, close func()) {\n\tf, err := os.Create(dest)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tbw := bufio.NewWriter(f)\n\treturn bw, func() {\n\t\tif err := bw.Flush(); err != nil {\n\t\t\tlog.Fatalf(\"error flushing %v: %v\", dest, err)\n\t\t}\n\t\tif err := f.Close(); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc gofmtMain() {\n\tflag.Usage = usage\n\tpaths := parseFlags()\n\n\tif *cpuProfile != \"\" {\n\t\tbw, flush := bufferedFileWriter(*cpuProfile)\n\t\tpprof.StartCPUProfile(bw)\n\t\tdefer flush()\n\t\tdefer pprof.StopCPUProfile()\n\t}\n\t// doTrace is a conditionally compiled wrapper around runtime/trace. It is\n\t// used to allow goimports to compile under gccgo, which does not support\n\t// runtime/trace. See https://golang.org/issue/15544.\n\tdefer doTrace()()\n\tif *memProfileRate > 0 {\n\t\truntime.MemProfileRate = *memProfileRate\n\t\tbw, flush := bufferedFileWriter(*memProfile)\n\t\tdefer func() {\n\t\t\truntime.GC() // materialize all statistics\n\t\t\tif err := pprof.WriteHeapProfile(bw); err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t\tflush()\n\t\t}()\n\t}\n\n\tif verbose {\n\t\tlog.SetFlags(log.LstdFlags | log.Lmicroseconds)\n\t\toptions.Env.Logf = log.Printf\n\t}\n\tif options.TabWidth < 0 {\n\t\tfmt.Fprintf(os.Stderr, \"negative tabwidth %d\\n\", options.TabWidth)\n\t\texitCode = 2\n\t\treturn\n\t}\n\n\tif len(paths) == 0 {\n\t\tif err := processFile(\"<standard input>\", os.Stdin, os.Stdout, fromStdin); err != nil {\n\t\t\treport(err)\n\t\t}\n\t\treturn\n\t}\n\n\targType := singleArg\n\tif len(paths) > 1 {\n\t\targType = multipleArg\n\t}\n\n\tfor _, path := range paths {\n\t\tswitch dir, err := os.Stat(path); {\n\t\tcase err != nil:\n\t\t\treport(err)\n\t\tcase dir.IsDir():\n\t\t\twalkDir(path)\n\t\tdefault:\n\t\t\tif err := processFile(path, nil, os.Stdout, argType); err != nil {\n\t\t\t\treport(err)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc writeTempFile(dir, prefix string, data []byte) (string, error) {\n\tfile, err := os.CreateTemp(dir, prefix)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t_, err = file.Write(data)\n\tif err1 := file.Close(); err == nil {\n\t\terr = err1\n\t}\n\tif err != nil {\n\t\tos.Remove(file.Name())\n\t\treturn \"\", err\n\t}\n\treturn file.Name(), nil\n}\n\nfunc diff(b1, b2 []byte, filename string) (data []byte, err error) {\n\tf1, err := writeTempFile(\"\", \"gofmt\", b1)\n\tif err != nil {\n\t\treturn\n\t}\n\tdefer os.Remove(f1)\n\n\tf2, err := writeTempFile(\"\", \"gofmt\", b2)\n\tif err != nil {\n\t\treturn\n\t}\n\tdefer os.Remove(f2)\n\n\tcmd := \"diff\"\n\tif runtime.GOOS == \"plan9\" {\n\t\tcmd = \"/bin/ape/diff\"\n\t}\n\n\tdata, err = exec.Command(cmd, \"-u\", f1, f2).CombinedOutput()\n\tif len(data) > 0 {\n\t\t// diff exits with a non-zero status when the files don't match.\n\t\t// Ignore that failure as long as we get output.\n\t\treturn replaceTempFilename(data, filename)\n\t}\n\treturn\n}\n\n// replaceTempFilename replaces temporary filenames in diff with actual one.\n//\n// --- /tmp/gofmt316145376\t2017-02-03 19:13:00.280468375 -0500\n// +++ /tmp/gofmt617882815\t2017-02-03 19:13:00.280468375 -0500\n// ...\n// ->\n// --- path/to/file.go.orig\t2017-02-03 19:13:00.280468375 -0500\n// +++ path/to/file.go\t2017-02-03 19:13:00.280468375 -0500\n// ...\nfunc replaceTempFilename(diff []byte, filename string) ([]byte, error) {\n\tbs := bytes.SplitN(diff, []byte{'\\n'}, 3)\n\tif len(bs) < 3 {\n\t\treturn nil, fmt.Errorf(\"got unexpected diff for %s\", filename)\n\t}\n\t// Preserve timestamps.\n\tvar t0, t1 []byte\n\tif i := bytes.LastIndexByte(bs[0], '\\t'); i != -1 {\n\t\tt0 = bs[0][i:]\n\t}\n\tif i := bytes.LastIndexByte(bs[1], '\\t'); i != -1 {\n\t\tt1 = bs[1][i:]\n\t}\n\t// Always print filepath with slash separator.\n\tf := filepath.ToSlash(filename)\n\tbs[0] = fmt.Appendf(nil, \"--- %s%s\", f+\".orig\", t0)\n\tbs[1] = fmt.Appendf(nil, \"+++ %s%s\", f, t1)\n\treturn bytes.Join(bs, []byte{'\\n'}), nil\n}\n\n// isFile reports whether name is a file.\nfunc isFile(name string) bool {\n\tfi, err := os.Stat(name)\n\treturn err == nil && fi.Mode().IsRegular()\n}\n\n// isDir reports whether name is a directory.\nfunc isDir(name string) bool {\n\tfi, err := os.Stat(name)\n\treturn err == nil && fi.IsDir()\n}\n"
  },
  {
    "path": "cmd/goimports/goimports_gc.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build gc\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"runtime/trace\"\n)\n\nvar traceProfile = flag.String(\"trace\", \"\", \"trace profile output\")\n\nfunc doTrace() func() {\n\tif *traceProfile != \"\" {\n\t\tbw, flush := bufferedFileWriter(*traceProfile)\n\t\ttrace.Start(bw)\n\t\treturn func() {\n\t\t\ttrace.Stop()\n\t\t\tflush()\n\t\t}\n\t}\n\treturn func() {}\n}\n"
  },
  {
    "path": "cmd/goimports/goimports_not_gc.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !gc\n\npackage main\n\nfunc doTrace() func() {\n\treturn func() {}\n}\n"
  },
  {
    "path": "cmd/gomvpkg/main.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The gomvpkg command moves go packages, updating import declarations.\n// See the -help message or Usage constant for details.\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/refactor/rename\"\n)\n\nvar (\n\tfromFlag     = flag.String(\"from\", \"\", \"Import path of package to be moved\")\n\ttoFlag       = flag.String(\"to\", \"\", \"Destination import path for package\")\n\tvcsMvCmdFlag = flag.String(\"vcs_mv_cmd\", \"\", `A template for the version control system's \"move directory\" command, e.g. \"git mv {{.Src}} {{.Dst}}\"`)\n\thelpFlag     = flag.Bool(\"help\", false, \"show usage message\")\n)\n\nfunc init() {\n\tflag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), \"tags\", buildutil.TagsFlagDoc)\n}\n\nconst Usage = `gomvpkg: moves a package, updating import declarations\n\nUsage:\n\n gomvpkg -from <path> -to <path> [-vcs_mv_cmd <template>]\n\nFlags:\n\n-from        specifies the import path of the package to be moved\n\n-to          specifies the destination import path\n\n-vcs_mv_cmd  specifies a shell command to inform the version control system of a\n             directory move.  The argument is a template using the syntax of the\n             text/template package. It has two fields: Src and Dst, the absolute\n             paths of the directories.\n\n             For example: \"git mv {{.Src}} {{.Dst}}\"\n\ngomvpkg determines the set of packages that might be affected, including all\npackages importing the 'from' package and any of its subpackages. It will move\nthe 'from' package and all its subpackages to the destination path and update all\nimports of those packages to point to its new import path.\n\ngomvpkg rejects moves in which a package already exists at the destination import\npath, or in which a directory already exists at the location the package would be\nmoved to.\n\ngomvpkg will not always be able to rename imports when a package's name is changed.\nImport statements may want further cleanup.\n\ngomvpkg's behavior is not defined if any of the packages to be moved are\nimported using dot imports.\n\nExamples:\n\n% gomvpkg -from myproject/foo -to myproject/bar\n\n  Move the package with import path \"myproject/foo\" to the new path\n  \"myproject/bar\".\n\n% gomvpkg -from myproject/foo -to myproject/bar -vcs_mv_cmd \"git mv {{.Src}} {{.Dst}}\"\n\n  Move the package with import path \"myproject/foo\" to the new path\n  \"myproject/bar\" using \"git mv\" to execute the directory move.\n`\n\nfunc main() {\n\tflag.Parse()\n\n\tif len(flag.Args()) > 0 {\n\t\tfmt.Fprintln(os.Stderr, \"gomvpkg: surplus arguments.\")\n\t\tos.Exit(1)\n\t}\n\n\tif *helpFlag || *fromFlag == \"\" || *toFlag == \"\" {\n\t\tfmt.Print(Usage)\n\t\treturn\n\t}\n\n\tif err := rename.Move(&build.Default, *fromFlag, *toFlag, *vcsMvCmdFlag); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"gomvpkg: %s.\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/gonew/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Gonew starts a new Go module by copying a template module.\n//\n// Usage:\n//\n//\tgonew srcmod[@version] [dstmod [dir]]\n//\n// Gonew makes a copy of the srcmod module, changing its module path to dstmod.\n// It writes that new module to a new directory named by dir.\n// If dir already exists, it must be an empty directory.\n// If dir is omitted, gonew uses ./elem where elem is the final path element of dstmod.\n//\n// This command is highly experimental and subject to change.\n//\n// # Example\n//\n// To install gonew:\n//\n//\tgo install golang.org/x/tools/cmd/gonew@latest\n//\n// To clone the basic command-line program template golang.org/x/example/hello\n// as your.domain/myprog, in the directory ./myprog:\n//\n//\tgonew golang.org/x/example/hello your.domain/myprog\n//\n// To clone the latest copy of the rsc.io/quote module, keeping that module path,\n// into ./quote:\n//\n//\tgonew rsc.io/quote\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io/fs\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/internal/edit\"\n)\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: gonew srcmod[@version] [dstmod [dir]]\\n\")\n\tfmt.Fprintf(os.Stderr, \"See https://pkg.go.dev/golang.org/x/tools/cmd/gonew.\\n\")\n\tos.Exit(2)\n}\n\nfunc main() {\n\tlog.SetPrefix(\"gonew: \")\n\tlog.SetFlags(0)\n\tflag.Usage = usage\n\tflag.Parse()\n\targs := flag.Args()\n\n\tif len(args) < 1 || len(args) > 3 {\n\t\tusage()\n\t}\n\n\tsrcMod := args[0]\n\tsrcModVers := srcMod\n\tif !strings.Contains(srcModVers, \"@\") {\n\t\tsrcModVers += \"@latest\"\n\t}\n\tsrcMod, _, _ = strings.Cut(srcMod, \"@\")\n\tif err := module.CheckPath(srcMod); err != nil {\n\t\tlog.Fatalf(\"invalid source module name: %v\", err)\n\t}\n\n\tdstMod := srcMod\n\tif len(args) >= 2 {\n\t\tdstMod = args[1]\n\t\tif err := module.CheckPath(dstMod); err != nil {\n\t\t\tlog.Fatalf(\"invalid destination module name: %v\", err)\n\t\t}\n\t}\n\n\tvar dir string\n\tif len(args) == 3 {\n\t\tdir = args[2]\n\t} else {\n\t\tdir = \".\" + string(filepath.Separator) + path.Base(dstMod)\n\t}\n\n\t// Dir must not exist or must be an empty directory.\n\tde, err := os.ReadDir(dir)\n\tif err == nil && len(de) > 0 {\n\t\tlog.Fatalf(\"target directory %s exists and is non-empty\", dir)\n\t}\n\tneedMkdir := err != nil\n\n\tvar stdout, stderr bytes.Buffer\n\tcmd := exec.Command(\"go\", \"mod\", \"download\", \"-json\", srcModVers)\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\tif err := cmd.Run(); err != nil {\n\t\tlog.Fatalf(\"go mod download -json %s: %v\\n%s%s\", srcModVers, err, stderr.Bytes(), stdout.Bytes())\n\t}\n\n\tvar info struct {\n\t\tDir string\n\t}\n\tif err := json.Unmarshal(stdout.Bytes(), &info); err != nil {\n\t\tlog.Fatalf(\"go mod download -json %s: invalid JSON output: %v\\n%s%s\", srcMod, err, stderr.Bytes(), stdout.Bytes())\n\t}\n\n\tif needMkdir {\n\t\tif err := os.MkdirAll(dir, 0777); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Copy from module cache into new directory, making edits as needed.\n\tfilepath.WalkDir(info.Dir, func(src string, d fs.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\trel, err := filepath.Rel(info.Dir, src)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tdst := filepath.Join(dir, rel)\n\t\tif d.IsDir() {\n\t\t\tif err := os.MkdirAll(dst, 0777); err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\tdata, err := os.ReadFile(src)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\n\t\tisRoot := !strings.Contains(rel, string(filepath.Separator))\n\t\tif strings.HasSuffix(rel, \".go\") {\n\t\t\tdata = fixGo(data, rel, srcMod, dstMod, isRoot)\n\t\t}\n\t\tif rel == \"go.mod\" {\n\t\t\tdata = fixGoMod(data, dstMod)\n\t\t}\n\n\t\tif err := os.WriteFile(dst, data, 0666); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\treturn nil\n\t})\n\n\tlog.Printf(\"initialized %s in %s\", dstMod, dir)\n}\n\n// fixGo rewrites the Go source in data to replace srcMod with dstMod.\n// isRoot indicates whether the file is in the root directory of the module,\n// in which case we also update the package name.\nfunc fixGo(data []byte, file string, srcMod, dstMod string, isRoot bool) []byte {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, file, data, parser.ImportsOnly)\n\tif err != nil {\n\t\tlog.Fatalf(\"parsing source module:\\n%s\", err)\n\t}\n\n\tbuf := edit.NewBuffer(data)\n\tat := func(p token.Pos) int {\n\t\treturn fset.File(p).Offset(p)\n\t}\n\n\tsrcName := path.Base(srcMod)\n\tdstName := path.Base(dstMod)\n\tif isRoot {\n\t\tif name := f.Name.Name; name == srcName || name == srcName+\"_test\" {\n\t\t\tdname := dstName + strings.TrimPrefix(name, srcName)\n\t\t\tif !token.IsIdentifier(dname) {\n\t\t\t\tlog.Fatalf(\"%s: cannot rename package %s to package %s: invalid package name\", file, name, dname)\n\t\t\t}\n\t\t\tbuf.Replace(at(f.Name.Pos()), at(f.Name.End()), dname)\n\t\t}\n\t}\n\n\tfor _, spec := range f.Imports {\n\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif path == srcMod {\n\t\t\tif srcName != dstName && spec.Name == nil {\n\t\t\t\t// Add package rename because source code uses original name.\n\t\t\t\t// The renaming looks strange, but template authors are unlikely to\n\t\t\t\t// create a template where the root package is imported by packages\n\t\t\t\t// in subdirectories, and the renaming at least keeps the code working.\n\t\t\t\t// A more sophisticated approach would be to rename the uses of\n\t\t\t\t// the package identifier in the file too, but then you have to worry about\n\t\t\t\t// name collisions, and given how unlikely this is, it doesn't seem worth\n\t\t\t\t// trying to clean up the file that way.\n\t\t\t\tbuf.Insert(at(spec.Path.Pos()), srcName+\" \")\n\t\t\t}\n\t\t\t// Change import path to dstMod\n\t\t\tbuf.Replace(at(spec.Path.Pos()), at(spec.Path.End()), strconv.Quote(dstMod))\n\t\t}\n\t\tif strings.HasPrefix(path, srcMod+\"/\") {\n\t\t\t// Change import path to begin with dstMod\n\t\t\tbuf.Replace(at(spec.Path.Pos()), at(spec.Path.End()), strconv.Quote(strings.Replace(path, srcMod, dstMod, 1)))\n\t\t}\n\t}\n\treturn buf.Bytes()\n}\n\n// fixGoMod rewrites the go.mod content in data to add a module\n// statement for dstMod.\nfunc fixGoMod(data []byte, dstMod string) []byte {\n\tf, err := modfile.ParseLax(\"go.mod\", data, nil)\n\tif err != nil {\n\t\tlog.Fatalf(\"parsing source module:\\n%s\", err)\n\t}\n\tf.AddModuleStmt(dstMod)\n\tnew, err := f.Format()\n\tif err != nil {\n\t\treturn data\n\t}\n\treturn new\n}\n"
  },
  {
    "path": "cmd/gonew/main_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/diffp\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc init() {\n\tif os.Getenv(\"TestGonewMain\") == \"1\" {\n\t\tmain()\n\t\tos.Exit(0)\n\t}\n}\n\nfunc Test(t *testing.T) {\n\tif !testenv.HasExec() {\n\t\tt.Skipf(\"skipping test: exec not supported on %s/%s\", runtime.GOOS, runtime.GOARCH)\n\t}\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Each file in testdata is a txtar file with the command to run,\n\t// the contents of modules to initialize in a fake proxy,\n\t// the expected stdout and stderr, and the expected file contents.\n\tfiles, err := filepath.Glob(\"testdata/*.txt\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(files) == 0 {\n\t\tt.Fatal(\"no test cases\")\n\t}\n\n\tfor _, file := range files {\n\t\tt.Run(filepath.Base(file), func(t *testing.T) {\n\t\t\tdata, err := os.ReadFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tar := txtar.Parse(data)\n\n\t\t\t// If the command begins with ! it means it should fail.\n\t\t\t// After the optional ! the first argument must be 'gonew'\n\t\t\t// followed by the arguments to gonew.\n\t\t\targs := strings.Fields(string(ar.Comment))\n\t\t\twantFail := false\n\t\t\tif len(args) > 0 && args[0] == \"!\" {\n\t\t\t\twantFail = true\n\t\t\t\targs = args[1:]\n\t\t\t}\n\t\t\tif len(args) == 0 || args[0] != \"gonew\" {\n\t\t\t\tt.Fatalf(\"invalid command comment\")\n\t\t\t}\n\n\t\t\t// Collect modules into proxy tree and store in temp directory.\n\t\t\tdir := t.TempDir()\n\t\t\tproxyDir := filepath.Join(dir, \"proxy\")\n\t\t\twriteProxyFiles(t, proxyDir, ar)\n\t\t\textra := \"\"\n\t\t\tif runtime.GOOS == \"windows\" {\n\t\t\t\t// Windows absolute paths don't start with / so we need one more.\n\t\t\t\textra = \"/\"\n\t\t\t}\n\t\t\tproxyURL := \"file://\" + extra + filepath.ToSlash(proxyDir)\n\n\t\t\t// Run gonew in a fresh 'out' directory.\n\t\t\tout := filepath.Join(dir, \"out\")\n\t\t\tif err := os.Mkdir(out, 0777); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tcmd := exec.Command(exe, args[1:]...)\n\t\t\tcmd.Dir = out\n\t\t\tcmd.Env = append(os.Environ(), \"TestGonewMain=1\", \"GOPROXY=\"+proxyURL, \"GOSUMDB=off\")\n\t\t\tvar stdout bytes.Buffer\n\t\t\tvar stderr bytes.Buffer\n\t\t\tcmd.Stdout = &stdout\n\t\t\tcmd.Stderr = &stderr\n\t\t\tif err := cmd.Run(); err == nil && wantFail {\n\t\t\t\tt.Errorf(\"unexpected success exit\")\n\t\t\t} else if err != nil && !wantFail {\n\t\t\t\tt.Errorf(\"unexpected failure exit\")\n\t\t\t}\n\n\t\t\t// Collect the expected output from the txtar.\n\t\t\twant := make(map[string]txtar.File)\n\t\t\tfor _, f := range ar.Files {\n\t\t\t\tif f.Name == \"stdout\" || f.Name == \"stderr\" || strings.HasPrefix(f.Name, \"out/\") {\n\t\t\t\t\twant[f.Name] = f\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check stdout and stderr.\n\t\t\t// Change \\ to / so Windows output looks like Unix output.\n\t\t\tstdoutBuf := bytes.ReplaceAll(stdout.Bytes(), []byte(`\\`), []byte(\"/\"))\n\t\t\tstderrBuf := bytes.ReplaceAll(stderr.Bytes(), []byte(`\\`), []byte(\"/\"))\n\t\t\t// Note that stdout and stderr can be omitted from the archive if empty.\n\t\t\tif !bytes.Equal(stdoutBuf, want[\"stdout\"].Data) {\n\t\t\t\tt.Errorf(\"wrong stdout: %s\", diffp.Diff(\"want\", want[\"stdout\"].Data, \"have\", stdoutBuf))\n\t\t\t}\n\t\t\tif !bytes.Equal(stderrBuf, want[\"stderr\"].Data) {\n\t\t\t\tt.Errorf(\"wrong stderr: %s\", diffp.Diff(\"want\", want[\"stderr\"].Data, \"have\", stderrBuf))\n\t\t\t}\n\t\t\tdelete(want, \"stdout\")\n\t\t\tdelete(want, \"stderr\")\n\n\t\t\t// Check remaining expected outputs.\n\t\t\terr = filepath.WalkDir(out, func(name string, info fs.DirEntry, err error) error {\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif info.IsDir() {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata, err := os.ReadFile(name)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tshort := \"out\" + filepath.ToSlash(strings.TrimPrefix(name, out))\n\t\t\t\tf, ok := want[short]\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Errorf(\"unexpected file %s:\\n%s\", short, data)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdelete(want, short)\n\t\t\t\tif !bytes.Equal(data, f.Data) {\n\t\t\t\t\tt.Errorf(\"wrong %s: %s\", short, diffp.Diff(\"want\", f.Data, \"have\", data))\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfor name := range want {\n\t\t\t\tt.Errorf(\"missing file %s\", name)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// A Zip is a zip file being written.\ntype Zip struct {\n\tbuf bytes.Buffer\n\tw   *zip.Writer\n}\n\n// writeProxyFiles collects all the module content from ar and writes\n// files in the format of the proxy URL space, so that the 'proxy' directory\n// can be used in a GOPROXY=file:/// URL.\nfunc writeProxyFiles(t *testing.T, proxy string, ar *txtar.Archive) {\n\tzips := make(map[string]*Zip)\n\tothers := make(map[string]string)\n\tfor _, f := range ar.Files {\n\t\ti := strings.Index(f.Name, \"@\")\n\t\tif i < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tj := strings.Index(f.Name[i:], \"/\")\n\t\tif j < 0 {\n\t\t\tt.Fatalf(\"unexpected archive file %s\", f.Name)\n\t\t}\n\t\tj += i\n\t\tmod, vers, file := f.Name[:i], f.Name[i+1:j], f.Name[j+1:]\n\t\tzipName := mod + \"/@v/\" + vers + \".zip\"\n\t\tz := zips[zipName]\n\t\tif z == nil {\n\t\t\tothers[mod+\"/@v/list\"] += vers + \"\\n\"\n\t\t\tothers[mod+\"/@v/\"+vers+\".info\"] = fmt.Sprintf(\"{%q: %q}\\n\", \"Version\", vers)\n\t\t\tz = new(Zip)\n\t\t\tz.w = zip.NewWriter(&z.buf)\n\t\t\tzips[zipName] = z\n\t\t}\n\t\tif file == \"go.mod\" {\n\t\t\tothers[mod+\"/@v/\"+vers+\".mod\"] = string(f.Data)\n\t\t}\n\t\tw, err := z.w.Create(f.Name)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif _, err := w.Write(f.Data); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tfor name, z := range zips {\n\t\tif err := z.w.Close(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.MkdirAll(filepath.Dir(filepath.Join(proxy, name)), 0777); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(filepath.Join(proxy, name), z.buf.Bytes(), 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tfor name, data := range others {\n\t\t// zip loop already created directory\n\t\tif err := os.WriteFile(filepath.Join(proxy, name), []byte(data), 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/gonew/testdata/quote.txt",
    "content": "gonew example.com/quote my.com/test\n\n-- example.com/quote@v1.5.2/go.mod --\nmodule example.com/quote\n-- example.com/quote@v1.5.2/quote.go --\npackage quote\n\nimport (\n\t\"example.com/quote/bar\"\n)\n\nfunc Quote() {}\n-- example.com/quote@v1.5.2/quote/another.go --\npackage quote // another package quote!\n-- stderr --\ngonew: initialized my.com/test in ./test\n-- out/test/go.mod --\nmodule my.com/test\n-- out/test/quote.go --\npackage test\n\nimport (\n\t\"my.com/test/bar\"\n)\n\nfunc Quote() {}\n-- out/test/quote/another.go --\npackage quote // another package quote!\n"
  },
  {
    "path": "cmd/gotype/gotype.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// gotype.go is a copy of the original source maintained\n// in $GOROOT/src/go/types/gotype.go, but with the call\n// to types.SizesFor factored out so we can provide a local\n// implementation when compiling against Go 1.8 and earlier.\n//\n// This code is here for the sole purpose of satisfying historic\n// references to this location, and for making gotype accessible\n// via 'go get'.\n//\n// Do NOT make changes to this version as they will not be maintained\n// (and possibly overwritten). Any changes should be made to the original\n// and then ported to here.\n\n/*\nThe gotype command, like the front-end of a Go compiler, parses and\ntype-checks a single Go package. Errors are reported if the analysis\nfails; otherwise gotype is quiet (unless -v is set).\n\nWithout a list of paths, gotype reads from standard input, which\nmust provide a single Go source file defining a complete package.\n\nWith a single directory argument, gotype checks the Go files in\nthat directory, comprising a single package. Use -t to include the\n(in-package) _test.go files. Use -x to type check only external\ntest files.\n\nOtherwise, each path must be the filename of a Go file belonging\nto the same package.\n\nImports are processed by importing directly from the source of\nimported packages (default), or by importing from compiled and\ninstalled packages (by setting -c to the respective compiler).\n\nThe -c flag must be set to a compiler (\"gc\", \"gccgo\") when type-\nchecking packages containing imports with relative import paths\n(import \"./mypkg\") because the source importer cannot know which\nfiles to include for such packages.\n\nUsage:\n\n\tgotype [flags] [path...]\n\nThe flags are:\n\n\t-t\n\t\tinclude local test files in a directory (ignored if -x is provided)\n\t-x\n\t\tconsider only external test files in a directory\n\t-e\n\t\treport all errors (not just the first 10)\n\t-v\n\t\tverbose mode\n\t-c\n\t\tcompiler used for installed packages (gc, gccgo, or source); default: source\n\nFlags controlling additional output:\n\n\t-ast\n\t\tprint AST (forces -seq)\n\t-trace\n\t\tprint parse trace (forces -seq)\n\t-comments\n\t\tparse comments (ignored unless -ast or -trace is provided)\n\nExamples:\n\nTo check the files a.go, b.go, and c.go:\n\n\tgotype a.go b.go c.go\n\nTo check an entire package including (in-package) tests in the directory dir and print the processed files:\n\n\tgotype -t -v dir\n\nTo check the external test package (if any) in the current directory, based on installed packages compiled with\ncmd/compile:\n\n\tgotype -c=gc -x .\n\nTo verify the output of a pipe:\n\n\techo \"package foo\" | gotype\n*/\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\t// main operation modes\n\ttestFiles  = flag.Bool(\"t\", false, \"include in-package test files in a directory\")\n\txtestFiles = flag.Bool(\"x\", false, \"consider only external test files in a directory\")\n\tallErrors  = flag.Bool(\"e\", false, \"report all errors, not just the first 10\")\n\tverbose    = flag.Bool(\"v\", false, \"verbose mode\")\n\tcompiler   = flag.String(\"c\", defaultCompiler, \"compiler used for installed packages (gc, gccgo, or source)\")\n\n\t// additional output control\n\tprintAST      = flag.Bool(\"ast\", false, \"print AST (forces -seq)\")\n\tprintTrace    = flag.Bool(\"trace\", false, \"print parse trace (forces -seq)\")\n\tparseComments = flag.Bool(\"comments\", false, \"parse comments (ignored unless -ast or -trace is provided)\")\n)\n\nvar (\n\tfset       = token.NewFileSet()\n\terrorCount = 0\n\tsequential = false\n\tparserMode parser.Mode\n)\n\nfunc initParserMode() {\n\tif *allErrors {\n\t\tparserMode |= parser.AllErrors\n\t}\n\tif *printAST {\n\t\tsequential = true\n\t}\n\tif *printTrace {\n\t\tparserMode |= parser.Trace\n\t\tsequential = true\n\t}\n\tif *parseComments && (*printAST || *printTrace) {\n\t\tparserMode |= parser.ParseComments\n\t}\n}\n\nconst usageString = `usage: gotype [flags] [path ...]\n\nThe gotype command, like the front-end of a Go compiler, parses and\ntype-checks a single Go package. Errors are reported if the analysis\nfails; otherwise gotype is quiet (unless -v is set).\n\nWithout a list of paths, gotype reads from standard input, which\nmust provide a single Go source file defining a complete package.\n\nWith a single directory argument, gotype checks the Go files in\nthat directory, comprising a single package. Use -t to include the\n(in-package) _test.go files. Use -x to type check only external\ntest files.\n\nOtherwise, each path must be the filename of a Go file belonging\nto the same package.\n\nImports are processed by importing directly from the source of\nimported packages (default), or by importing from compiled and\ninstalled packages (by setting -c to the respective compiler).\n\nThe -c flag must be set to a compiler (\"gc\", \"gccgo\") when type-\nchecking packages containing imports with relative import paths\n(import \"./mypkg\") because the source importer cannot know which\nfiles to include for such packages.\n`\n\nfunc usage() {\n\tfmt.Fprint(os.Stderr, usageString)\n\tfmt.Fprintln(os.Stderr)\n\tflag.PrintDefaults()\n\tos.Exit(2)\n}\n\nfunc report(err error) {\n\tscanner.PrintError(os.Stderr, err)\n\tif list, ok := err.(scanner.ErrorList); ok {\n\t\terrorCount += len(list)\n\t\treturn\n\t}\n\terrorCount++\n}\n\n// parse may be called concurrently\nfunc parse(filename string, src any) (*ast.File, error) {\n\tif *verbose {\n\t\tfmt.Println(filename)\n\t}\n\tfile, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently\n\tif *printAST {\n\t\tast.Print(fset, file)\n\t}\n\treturn file, err\n}\n\nfunc parseStdin() (*ast.File, error) {\n\tsrc, err := io.ReadAll(os.Stdin)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn parse(\"<standard input>\", src)\n}\n\nfunc parseFiles(dir string, filenames []string) ([]*ast.File, error) {\n\tfiles := make([]*ast.File, len(filenames))\n\terrors := make([]error, len(filenames))\n\n\tvar wg sync.WaitGroup\n\tfor i, filename := range filenames {\n\t\twg.Add(1)\n\t\tgo func(i int, filepath string) {\n\t\t\tdefer wg.Done()\n\t\t\tfiles[i], errors[i] = parse(filepath, nil)\n\t\t}(i, filepath.Join(dir, filename))\n\t\tif sequential {\n\t\t\twg.Wait()\n\t\t}\n\t}\n\twg.Wait()\n\n\t// if there are errors, return the first one for deterministic results\n\tfor _, err := range errors {\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn files, nil\n}\n\nfunc parseDir(dir string) ([]*ast.File, error) {\n\tctxt := build.Default\n\tpkginfo, err := ctxt.ImportDir(dir, 0)\n\tif _, nogo := err.(*build.NoGoError); err != nil && !nogo {\n\t\treturn nil, err\n\t}\n\n\tif *xtestFiles {\n\t\treturn parseFiles(dir, pkginfo.XTestGoFiles)\n\t}\n\n\tfilenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)\n\tif *testFiles {\n\t\tfilenames = append(filenames, pkginfo.TestGoFiles...)\n\t}\n\treturn parseFiles(dir, filenames)\n}\n\nfunc getPkgFiles(args []string) ([]*ast.File, error) {\n\tif len(args) == 0 {\n\t\t// stdin\n\t\tfile, err := parseStdin()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn []*ast.File{file}, nil\n\t}\n\n\tif len(args) == 1 {\n\t\t// possibly a directory\n\t\tpath := args[0]\n\t\tinfo, err := os.Stat(path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif info.IsDir() {\n\t\t\treturn parseDir(path)\n\t\t}\n\t}\n\n\t// list of files\n\treturn parseFiles(\"\", args)\n}\n\nfunc checkPkgFiles(files []*ast.File) {\n\ttype bailout struct{}\n\n\t// if checkPkgFiles is called multiple times, set up conf only once\n\tconf := types.Config{\n\t\tFakeImportC: true,\n\t\tError: func(err error) {\n\t\t\tif !*allErrors && errorCount >= 10 {\n\t\t\t\tpanic(bailout{})\n\t\t\t}\n\t\t\treport(err)\n\t\t},\n\t\tImporter: importer.ForCompiler(fset, *compiler, nil),\n\t\tSizes:    SizesFor(build.Default.Compiler, build.Default.GOARCH),\n\t}\n\n\tdefer func() {\n\t\tswitch p := recover().(type) {\n\t\tcase nil, bailout:\n\t\t\t// normal return or early exit\n\t\tdefault:\n\t\t\t// re-panic\n\t\t\tpanic(p)\n\t\t}\n\t}()\n\n\tconst path = \"pkg\" // any non-empty string will do for now\n\tconf.Check(path, fset, files, nil)\n}\n\nfunc printStats(d time.Duration) {\n\tfileCount := 0\n\tlineCount := 0\n\tfset.Iterate(func(f *token.File) bool {\n\t\tfileCount++\n\t\tlineCount += f.LineCount()\n\t\treturn true\n\t})\n\n\tfmt.Printf(\n\t\t\"%s (%d files, %d lines, %d lines/s)\\n\",\n\t\td, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),\n\t)\n}\n\nfunc main() {\n\tflag.Usage = usage\n\tflag.Parse()\n\tinitParserMode()\n\n\tstart := time.Now()\n\n\tfiles, err := getPkgFiles(flag.Args())\n\tif err != nil {\n\t\treport(err)\n\t\tos.Exit(2)\n\t}\n\n\tcheckPkgFiles(files)\n\tif errorCount > 0 {\n\t\tos.Exit(2)\n\t}\n\n\tif *verbose {\n\t\tprintStats(time.Since(start))\n\t}\n}\n"
  },
  {
    "path": "cmd/gotype/sizesFor18.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.9\n\n// This file contains a copy of the implementation of types.SizesFor\n// since this function is not available in go/types before Go 1.9.\n\npackage main\n\nimport \"go/types\"\n\nconst defaultCompiler = \"gc\"\n\nvar gcArchSizes = map[string]*types.StdSizes{\n\t\"386\":      {4, 4},\n\t\"arm\":      {4, 4},\n\t\"arm64\":    {8, 8},\n\t\"amd64\":    {8, 8},\n\t\"amd64p32\": {4, 8},\n\t\"mips\":     {4, 4},\n\t\"mipsle\":   {4, 4},\n\t\"mips64\":   {8, 8},\n\t\"mips64le\": {8, 8},\n\t\"ppc64\":    {8, 8},\n\t\"ppc64le\":  {8, 8},\n\t\"s390x\":    {8, 8},\n}\n\nfunc SizesFor(compiler, arch string) types.Sizes {\n\tif compiler != \"gc\" {\n\t\treturn nil\n\t}\n\ts, ok := gcArchSizes[arch]\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "cmd/gotype/sizesFor19.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.9\n\npackage main\n\nimport \"go/types\"\n\nconst defaultCompiler = \"source\"\n\nfunc SizesFor(compiler, arch string) types.Sizes {\n\treturn types.SizesFor(compiler, arch)\n}\n"
  },
  {
    "path": "cmd/goyacc/doc.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nGoyacc is a version of yacc for Go.\nIt is written in Go and generates parsers written in Go.\n\nUsage:\n\n\tgoyacc args...\n\nIt is largely transliterated from the Inferno version written in Limbo\nwhich in turn was largely transliterated from the Plan 9 version\nwritten in C and documented at\n\n\thttps://9p.io/magic/man2html/1/yacc\n\nAdepts of the original yacc will have no trouble adapting to this\nform of the tool.\n\nThe directory $GOPATH/src/golang.org/x/tools/cmd/goyacc/testdata/expr\nis a yacc program for a very simple expression parser. See expr.y and\nmain.go in that directory for examples of how to write and build\ngoyacc programs.\n\nThe generated parser is reentrant. The parsing function yyParse expects\nto be given an argument that conforms to the following interface:\n\n\ttype yyLexer interface {\n\t\tLex(lval *yySymType) int\n\t\tError(e string)\n\t}\n\nLex should return the token identifier, and place other token\ninformation in lval (which replaces the usual yylval).\nError is equivalent to yyerror in the original yacc.\n\nCode inside the grammar actions may refer to the variable yylex,\nwhich holds the yyLexer passed to yyParse.\n\nClients that need to understand more about the parser state can\ncreate the parser separately from invoking it. The function yyNewParser\nreturns a yyParser conforming to the following interface:\n\n\ttype yyParser interface {\n\t\tParse(yyLex) int\n\t\tLookahead() int\n\t}\n\nParse runs the parser; the top-level call yyParse(yylex) is equivalent\nto yyNewParser().Parse(yylex).\n\nLookahead can be called during grammar actions to read (but not consume)\nthe value of the current lookahead token, as returned by yylex.Lex.\nIf there is no current lookahead token (because the parser has not called Lex\nor has consumed the token returned by the most recent call to Lex),\nLookahead returns -1. Calling Lookahead is equivalent to reading\nyychar from within in a grammar action.\n\nMultiple grammars compiled into a single program should be placed in\ndistinct packages.  If that is impossible, the \"-p prefix\" flag to\ngoyacc sets the prefix, by default yy, that begins the names of\nsymbols, including types, the parser, and the lexer, generated and\nreferenced by yacc's generated code.  Setting it to distinct values\nallows multiple grammars to be placed in a single package.\n*/\npackage main\n"
  },
  {
    "path": "cmd/goyacc/testdata/expr/README",
    "content": "This directory contains a simple program demonstrating how to use\nthe Go version of yacc.\n\nTo build it:\n\n\t$ go generate\n\t$ go build\n\nor\n\n\t$ go generate\n\t$ go run expr.go\n\nThe file main.go contains the \"go generate\" command to run yacc to\ncreate expr.go from expr.y. It also has the package doc comment,\nas godoc will not scan the .y file.\n\nThe actual implementation is in expr.y.\n\nThe program is not installed in the binary distributions of Go.\n"
  },
  {
    "path": "cmd/goyacc/testdata/expr/expr.y",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is an example of a goyacc program.\n// To build it:\n// goyacc -p \"expr\" expr.y (produces y.go)\n// go build -o expr y.go\n// expr\n// > <type an expression>\n\n%{\n\npackage main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"math/big\"\n\t\"os\"\n\t\"unicode/utf8\"\n)\n\n%}\n\n%union {\n\tnum *big.Rat\n}\n\n%type\t<num>\texpr expr1 expr2 expr3\n\n%token '+' '-' '*' '/' '(' ')'\n\n%token\t<num>\tNUM\n\n%%\n\ntop:\n\texpr\n\t{\n\t\tif $1.IsInt() {\n\t\t\tfmt.Println($1.Num().String())\n\t\t} else {\n\t\t\tfmt.Println($1.String())\n\t\t}\n\t}\n\nexpr:\n\texpr1\n|\t'+' expr\n\t{\n\t\t$$ = $2\n\t}\n|\t'-' expr\n\t{\n\t\t$$ = $2.Neg($2)\n\t}\n\nexpr1:\n\texpr2\n|\texpr1 '+' expr2\n\t{\n\t\t$$ = $1.Add($1, $3)\n\t}\n|\texpr1 '-' expr2\n\t{\n\t\t$$ = $1.Sub($1, $3)\n\t}\n\nexpr2:\n\texpr3\n|\texpr2 '*' expr3\n\t{\n\t\t$$ = $1.Mul($1, $3)\n\t}\n|\texpr2 '/' expr3\n\t{\n\t\t$$ = $1.Quo($1, $3)\n\t}\n\nexpr3:\n\tNUM\n|\t'(' expr ')'\n\t{\n\t\t$$ = $2\n\t}\n\n\n%%\n\n// The parser expects the lexer to return 0 on EOF.  Give it a name\n// for clarity.\nconst eof = 0\n\n// The parser uses the type <prefix>Lex as a lexer. It must provide\n// the methods Lex(*<prefix>SymType) int and Error(string).\ntype exprLex struct {\n\tline []byte\n\tpeek rune\n}\n\n// The parser calls this method to get each new token. This\n// implementation returns operators and NUM.\nfunc (x *exprLex) Lex(yylval *exprSymType) int {\n\tfor {\n\t\tc := x.next()\n\t\tswitch c {\n\t\tcase eof:\n\t\t\treturn eof\n\t\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\t\treturn x.num(c, yylval)\n\t\tcase '+', '-', '*', '/', '(', ')':\n\t\t\treturn int(c)\n\n\t\t// Recognize Unicode multiplication and division\n\t\t// symbols, returning what the parser expects.\n\t\tcase '×':\n\t\t\treturn '*'\n\t\tcase '÷':\n\t\t\treturn '/'\n\n\t\tcase ' ', '\\t', '\\n', '\\r':\n\t\tdefault:\n\t\t\tlog.Printf(\"unrecognized character %q\", c)\n\t\t}\n\t}\n}\n\n// Lex a number.\nfunc (x *exprLex) num(c rune, yylval *exprSymType) int {\n\tadd := func(b *bytes.Buffer, c rune) {\n\t\tif _, err := b.WriteRune(c); err != nil {\n\t\t\tlog.Fatalf(\"WriteRune: %s\", err)\n\t\t}\n\t}\n\tvar b bytes.Buffer\n\tadd(&b, c)\n\tL: for {\n\t\tc = x.next()\n\t\tswitch c {\n\t\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E':\n\t\t\tadd(&b, c)\n\t\tdefault:\n\t\t\tbreak L\n\t\t}\n\t}\n\tif c != eof {\n\t\tx.peek = c\n\t}\n\tyylval.num = &big.Rat{}\n\t_, ok := yylval.num.SetString(b.String())\n\tif !ok {\n\t\tlog.Printf(\"bad number %q\", b.String())\n\t\treturn eof\n\t}\n\treturn NUM\n}\n\n// Return the next rune for the lexer.\nfunc (x *exprLex) next() rune {\n\tif x.peek != eof {\n\t\tr := x.peek\n\t\tx.peek = eof\n\t\treturn r\n\t}\n\tif len(x.line) == 0 {\n\t\treturn eof\n\t}\n\tc, size := utf8.DecodeRune(x.line)\n\tx.line = x.line[size:]\n\tif c == utf8.RuneError && size == 1 {\n\t\tlog.Print(\"invalid utf8\")\n\t\treturn x.next()\n\t}\n\treturn c\n}\n\n// The parser calls this method on a parse error.\nfunc (x *exprLex) Error(s string) {\n\tlog.Printf(\"parse error: %s\", s)\n}\n\nfunc main() {\n\tin := bufio.NewReader(os.Stdin)\n\tfor {\n\t\tif _, err := os.Stdout.WriteString(\"> \"); err != nil {\n\t\t\tlog.Fatalf(\"WriteString: %s\", err)\n\t\t}\n\t\tline, err := in.ReadBytes('\\n')\n\t\tif err == io.EOF {\n\t\t\treturn\n\t\t}\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"ReadBytes: %s\", err)\n\t\t}\n\n\t\texprParse(&exprLex{line: line})\n\t}\n}\n"
  },
  {
    "path": "cmd/goyacc/testdata/expr/main.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file holds the go generate command to run yacc on the grammar in expr.y.\n// To build expr:\n//\t% go generate\n//\t% go build\n\n//go:generate goyacc -o expr.go -p \"expr\" expr.y\n\n// Expr is a simple expression evaluator that serves as a working example of\n// how to use Go's yacc implementation.\npackage main\n"
  },
  {
    "path": "cmd/goyacc/yacc.go",
    "content": "/*\nDerived from Inferno's utils/iyacc/yacc.c\nhttp://code.google.com/p/inferno-os/source/browse/utils/iyacc/yacc.c\n\nThis copyright NOTICE applies to all files in this directory and\nsubdirectories, unless another copyright notice appears in a given\nfile or subdirectory.  If you take substantial code from this software to use in\nother programs, you must somehow include with it an appropriate\ncopyright notice that includes the copyright notice and the other\nnotices below.  It is fine (and often tidier) to do that in a separate\nfile such as NOTICE, LICENCE or COPYING.\n\n\tCopyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.\n\tPortions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)\n\tPortions Copyright © 1997-1999 Vita Nuova Limited\n\tPortions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)\n\tPortions Copyright © 2004,2006 Bruce Ellis\n\tPortions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)\n\tRevisions Copyright © 2000-2007 Lucent Technologies Inc. and others\n\tPortions Copyright © 2009 The Go Authors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\npackage main\n\n// yacc\n// major difference is lack of stem (\"y\" variable)\n//\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/format\"\n\t\"math\"\n\t\"os\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n)\n\n// the following are adjustable\n// according to memory size\nconst (\n\tACTSIZE  = 240000\n\tNSTATES  = 16000\n\tTEMPSIZE = 16000\n\n\tSYMINC   = 50  // increase for non-term or term\n\tRULEINC  = 50  // increase for max rule length prodptr[i]\n\tPRODINC  = 100 // increase for productions     prodptr\n\tWSETINC  = 50  // increase for working sets    wsets\n\tSTATEINC = 200 // increase for states          statemem\n\n\tPRIVATE = 0xE000 // unicode private use\n\n\t// relationships which must hold:\n\t//\tTEMPSIZE >= NTERMS + NNONTERM + 1;\n\t//\tTEMPSIZE >= NSTATES;\n\t//\n\n\tNTBASE     = 010000\n\tERRCODE    = 8190\n\tACCEPTCODE = 8191\n\tYYLEXUNK   = 3\n\tTOKSTART   = 4 //index of first defined token\n)\n\n// no, left, right, binary assoc.\nconst (\n\tNOASC = iota\n\tLASC\n\tRASC\n\tBASC\n)\n\n// flags for state generation\nconst (\n\tDONE = iota\n\tMUSTDO\n\tMUSTLOOKAHEAD\n)\n\n// flags for a rule having an action, and being reduced\nconst (\n\tACTFLAG = 1 << (iota + 2)\n\tREDFLAG\n)\n\n// output parser flags\nconst yyFlag = -1000\n\n// parse tokens\nconst (\n\tIDENTIFIER = PRIVATE + iota\n\tMARK\n\tTERM\n\tLEFT\n\tRIGHT\n\tBINARY\n\tPREC\n\tLCURLY\n\tIDENTCOLON\n\tNUMBER\n\tSTART\n\tTYPEDEF\n\tTYPENAME\n\tUNION\n\tERROR\n)\n\nconst ENDFILE = 0\nconst EMPTY = 1\nconst WHOKNOWS = 0\nconst OK = 1\nconst NOMORE = -1000\n\n// macros for getting associativity and precedence levels\nfunc ASSOC(i int) int { return i & 3 }\n\nfunc PLEVEL(i int) int { return (i >> 4) & 077 }\n\nfunc TYPE(i int) int { return (i >> 10) & 077 }\n\n// macros for setting associativity and precedence levels\nfunc SETASC(i, j int) int { return i | j }\n\nfunc SETPLEV(i, j int) int { return i | (j << 4) }\n\nfunc SETTYPE(i, j int) int { return i | (j << 10) }\n\n// I/O descriptors\nvar finput *bufio.Reader // input file\nvar stderr *bufio.Writer\nvar ftable *bufio.Writer    // y.go file\nvar fcode = &bytes.Buffer{} // saved code\nvar foutput *bufio.Writer   // y.output file\n\nvar fmtImported bool // output file has recorded an import of \"fmt\"\n\nvar oflag string  // -o [y.go]\t\t- y.go file\nvar vflag string  // -v [y.output]\t- y.output file\nvar lflag bool    // -l\t\t\t- disable line directives\nvar prefix string // name prefix for identifiers, default yy\n\nfunc init() {\n\tflag.StringVar(&oflag, \"o\", \"y.go\", \"parser output\")\n\tflag.StringVar(&prefix, \"p\", \"yy\", \"name prefix to use in generated code\")\n\tflag.StringVar(&vflag, \"v\", \"y.output\", \"create parsing tables\")\n\tflag.BoolVar(&lflag, \"l\", false, \"disable line directives\")\n}\n\nvar initialstacksize = 16\n\n// communication variables between various I/O routines\nvar infile string  // input file name\nvar numbval int    // value of an input number\nvar tokname string // input token name, slop for runes and 0\nvar tokflag = false\n\n// structure declarations\ntype Lkset []int\n\ntype Pitem struct {\n\tprod   []int\n\toff    int // offset within the production\n\tfirst  int // first term or non-term in item\n\tprodno int // production number for sorting\n}\n\ntype Item struct {\n\tpitem Pitem\n\tlook  Lkset\n}\n\ntype Symb struct {\n\tname    string\n\tnoconst bool\n\tvalue   int\n}\n\ntype Wset struct {\n\tpitem Pitem\n\tflag  int\n\tws    Lkset\n}\n\n// storage of types\nvar ntypes int                     // number of types defined\nvar typeset = make(map[int]string) // pointers to type tags\n\n// token information\n\nvar ntokens = 0 // number of tokens\nvar tokset []Symb\nvar toklev []int // vector with the precedence of the terminals\n\n// nonterminal information\n\nvar nnonter = -1 // the number of nonterminals\nvar nontrst []Symb\nvar start int // start symbol\n\n// state information\n\nvar nstate = 0                      // number of states\nvar pstate = make([]int, NSTATES+2) // index into statemem to the descriptions of the states\nvar statemem []Item\nvar tystate = make([]int, NSTATES) // contains type information about the states\nvar tstates []int                  // states generated by terminal gotos\nvar ntstates []int                 // states generated by nonterminal gotos\nvar mstates = make([]int, NSTATES) // chain of overflows of term/nonterm generation lists\nvar lastred int                    // number of last reduction of a state\nvar defact = make([]int, NSTATES)  // default actions of states\n\n// lookahead set information\n\nvar nolook = 0  // flag to turn off lookahead computations\nvar tbitset = 0 // size of lookahead sets\nvar clset Lkset // temporary storage for lookahead computations\n\n// working set information\n\nvar wsets []Wset\nvar cwp int\n\n// storage for action table\n\nvar amem []int                   // action table storage\nvar memp int                     // next free action table position\nvar indgo = make([]int, NSTATES) // index to the stored goto table\n\n// temporary vector, indexable by states, terms, or ntokens\n\nvar temp1 = make([]int, TEMPSIZE) // temporary storage, indexed by terms + ntokens or states\nvar lineno = 1                    // current input line number\nvar fatfl = 1                     // if on, error is fatal\nvar nerrors = 0                   // number of errors\n\n// assigned token type values\n\nvar extval = 0\n\n// grammar rule information\n\nvar nprod = 1      // number of productions\nvar prdptr [][]int // pointers to descriptions of productions\nvar levprd []int   // precedence levels for the productions\nvar rlines []int   // line number for this rule\n\n// statistics collection variables\n\nvar zzgoent = 0\nvar zzgobest = 0\nvar zzacent = 0\nvar zzexcp = 0\nvar zzclose = 0\nvar zzrrconf = 0\nvar zzsrconf = 0\nvar zzstate = 0\n\n// optimizer arrays\n\nvar yypgo [][]int\nvar optst [][]int\nvar ggreed []int\nvar pgo []int\n\nvar maxspr int // maximum spread of any entry\nvar maxoff int // maximum offset into a array\nvar maxa int\n\n// storage for information about the nonterminals\n\nvar pres [][][]int // vector of pointers to productions yielding each nonterminal\nvar pfirst []Lkset\nvar pempty []int // vector of nonterminals nontrivially deriving e\n\n// random stuff picked out from between functions\n\nvar indebug = 0 // debugging flag for cpfir\nvar pidebug = 0 // debugging flag for putitem\nvar gsdebug = 0 // debugging flag for stagen\nvar cldebug = 0 // debugging flag for closure\nvar pkdebug = 0 // debugging flag for apack\nvar g2debug = 0 // debugging for go2gen\nvar adb = 0     // debugging for callopt\n\ntype Resrv struct {\n\tname  string\n\tvalue int\n}\n\nvar resrv = []Resrv{\n\t{\"binary\", BINARY},\n\t{\"left\", LEFT},\n\t{\"nonassoc\", BINARY},\n\t{\"prec\", PREC},\n\t{\"right\", RIGHT},\n\t{\"start\", START},\n\t{\"term\", TERM},\n\t{\"token\", TERM},\n\t{\"type\", TYPEDEF},\n\t{\"union\", UNION},\n\t{\"struct\", UNION},\n\t{\"error\", ERROR},\n}\n\ntype Error struct {\n\tlineno int\n\ttokens []string\n\tmsg    string\n}\n\nvar errors []Error\n\ntype Row struct {\n\tactions       []int\n\tdefaultAction int\n}\n\nvar stateTable []Row\n\nvar zznewstate = 0\n\nconst EOF = -1\n\nfunc main() {\n\n\tsetup() // initialize and read productions\n\n\ttbitset = (ntokens + 32) / 32\n\tcpres()  // make table of which productions yield a given nonterminal\n\tcempty() // make a table of which nonterminals can match the empty string\n\tcpfir()  // make a table of firsts of nonterminals\n\n\tstagen() // generate the states\n\n\tyypgo = make([][]int, nnonter+1)\n\toptst = make([][]int, nstate)\n\toutput() // write the states and the tables\n\tgo2out()\n\n\thideprod()\n\tsummary()\n\n\tcallopt()\n\n\tothers()\n\n\texit(0)\n}\n\nfunc setup() {\n\tvar j, ty int\n\n\tstderr = bufio.NewWriter(os.Stderr)\n\tfoutput = nil\n\n\tflag.Parse()\n\tif flag.NArg() != 1 {\n\t\tusage()\n\t}\n\tif initialstacksize < 1 {\n\t\t// never set so cannot happen\n\t\tfmt.Fprintf(stderr, \"yacc: stack size too small\\n\")\n\t\tusage()\n\t}\n\tyaccpar = strings.Replace(yaccpartext, \"$$\", prefix, -1)\n\topenup()\n\n\tfmt.Fprintf(ftable, \"// Code generated by goyacc %s. DO NOT EDIT.\\n\", strings.Join(os.Args[1:], \" \"))\n\n\tdefin(0, \"$end\")\n\textval = PRIVATE // tokens start in unicode 'private use'\n\tdefin(0, \"error\")\n\tdefin(1, \"$accept\")\n\tdefin(0, \"$unk\")\n\ti := 0\n\n\tt := gettok()\n\nouter:\n\tfor {\n\t\tswitch t {\n\t\tdefault:\n\t\t\terrorf(\"syntax error tok=%v\", t-PRIVATE)\n\n\t\tcase MARK, ENDFILE:\n\t\t\tbreak outer\n\n\t\tcase ';':\n\t\t\t// Do nothing.\n\n\t\tcase START:\n\t\t\tt = gettok()\n\t\t\tif t != IDENTIFIER {\n\t\t\t\terrorf(\"bad %%start construction\")\n\t\t\t}\n\t\t\tstart = chfind(1, tokname)\n\n\t\tcase ERROR:\n\t\t\tlno := lineno\n\t\t\tvar tokens []string\n\t\t\tfor {\n\t\t\t\tt := gettok()\n\t\t\t\tif t == ':' {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif t != IDENTIFIER && t != IDENTCOLON {\n\t\t\t\t\terrorf(\"bad syntax in %%error\")\n\t\t\t\t}\n\t\t\t\ttokens = append(tokens, tokname)\n\t\t\t\tif t == IDENTCOLON {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif gettok() != IDENTIFIER {\n\t\t\t\terrorf(\"bad syntax in %%error\")\n\t\t\t}\n\t\t\terrors = append(errors, Error{lno, tokens, tokname})\n\n\t\tcase TYPEDEF:\n\t\t\tt = gettok()\n\t\t\tif t != TYPENAME {\n\t\t\t\terrorf(\"bad syntax in %%type\")\n\t\t\t}\n\t\t\tty = numbval\n\t\t\tfor {\n\t\t\t\tt = gettok()\n\t\t\t\tswitch t {\n\t\t\t\tcase IDENTIFIER:\n\t\t\t\t\tt = chfind(1, tokname)\n\t\t\t\t\tif t < NTBASE {\n\t\t\t\t\t\tj = TYPE(toklev[t])\n\t\t\t\t\t\tif j != 0 && j != ty {\n\t\t\t\t\t\t\terrorf(\"type redeclaration of token %s\",\n\t\t\t\t\t\t\t\ttokset[t].name)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoklev[t] = SETTYPE(toklev[t], ty)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tj = nontrst[t-NTBASE].value\n\t\t\t\t\t\tif j != 0 && j != ty {\n\t\t\t\t\t\t\terrorf(\"type redeclaration of nonterminal %v\",\n\t\t\t\t\t\t\t\tnontrst[t-NTBASE].name)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnontrst[t-NTBASE].value = ty\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase ',':\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcontinue\n\n\t\tcase UNION:\n\t\t\tcpyunion()\n\n\t\tcase LEFT, BINARY, RIGHT, TERM:\n\t\t\t// nonzero means new prec. and assoc.\n\t\t\tlev := t - TERM\n\t\t\tif lev != 0 {\n\t\t\t\ti++\n\t\t\t}\n\t\t\tty = 0\n\n\t\t\t// get identifiers so defined\n\t\t\tt = gettok()\n\n\t\t\t// there is a type defined\n\t\t\tif t == TYPENAME {\n\t\t\t\tty = numbval\n\t\t\t\tt = gettok()\n\t\t\t}\n\t\t\tfor {\n\t\t\t\tswitch t {\n\t\t\t\tcase ',':\n\t\t\t\t\tt = gettok()\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase ';':\n\t\t\t\t\t// Do nothing.\n\n\t\t\t\tcase IDENTIFIER:\n\t\t\t\t\tj = chfind(0, tokname)\n\t\t\t\t\tif j >= NTBASE {\n\t\t\t\t\t\terrorf(\"%v defined earlier as nonterminal\", tokname)\n\t\t\t\t\t}\n\t\t\t\t\tif lev != 0 {\n\t\t\t\t\t\tif ASSOC(toklev[j]) != 0 {\n\t\t\t\t\t\t\terrorf(\"redeclaration of precedence of %v\", tokname)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttoklev[j] = SETASC(toklev[j], lev)\n\t\t\t\t\t\ttoklev[j] = SETPLEV(toklev[j], i)\n\t\t\t\t\t}\n\t\t\t\t\tif ty != 0 {\n\t\t\t\t\t\tif TYPE(toklev[j]) != 0 {\n\t\t\t\t\t\t\terrorf(\"redeclaration of type of %v\", tokname)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttoklev[j] = SETTYPE(toklev[j], ty)\n\t\t\t\t\t}\n\t\t\t\t\tt = gettok()\n\t\t\t\t\tif t == NUMBER {\n\t\t\t\t\t\ttokset[j].value = numbval\n\t\t\t\t\t\tt = gettok()\n\t\t\t\t\t}\n\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcontinue\n\n\t\tcase LCURLY:\n\t\t\tcpycode()\n\t\t}\n\t\tt = gettok()\n\t}\n\n\tif t == ENDFILE {\n\t\terrorf(\"unexpected EOF before %%\")\n\t}\n\n\tfmt.Fprintf(fcode, \"switch %snt {\\n\", prefix)\n\n\tmoreprod()\n\tprdptr[0] = []int{NTBASE, start, 1, 0}\n\n\tnprod = 1\n\tcurprod := make([]int, RULEINC)\n\tt = gettok()\n\tif t != IDENTCOLON {\n\t\terrorf(\"bad syntax on first rule\")\n\t}\n\n\tif start == 0 {\n\t\tprdptr[0][1] = chfind(1, tokname)\n\t}\n\n\t// read rules\n\t// put into prdptr array in the format\n\t// target\n\t// followed by id's of terminals and non-terminals\n\t// followed by -nprod\n\n\tfor t != MARK && t != ENDFILE {\n\t\tmem := 0\n\n\t\t// process a rule\n\t\trlines[nprod] = lineno\n\t\truleline := lineno\n\t\tif t == '|' {\n\t\t\tcurprod[mem] = prdptr[nprod-1][0]\n\t\t\tmem++\n\t\t} else if t == IDENTCOLON {\n\t\t\tcurprod[mem] = chfind(1, tokname)\n\t\t\tif curprod[mem] < NTBASE {\n\t\t\t\tlerrorf(ruleline, \"token illegal on LHS of grammar rule\")\n\t\t\t}\n\t\t\tmem++\n\t\t} else {\n\t\t\tlerrorf(ruleline, \"illegal rule: missing semicolon or | ?\")\n\t\t}\n\n\t\t// read rule body\n\t\tt = gettok()\n\t\tfor {\n\t\t\tfor t == IDENTIFIER {\n\t\t\t\tcurprod[mem] = chfind(1, tokname)\n\t\t\t\tif curprod[mem] < NTBASE {\n\t\t\t\t\tlevprd[nprod] = toklev[curprod[mem]]\n\t\t\t\t}\n\t\t\t\tmem++\n\t\t\t\tif mem >= len(curprod) {\n\t\t\t\t\tncurprod := make([]int, mem+RULEINC)\n\t\t\t\t\tcopy(ncurprod, curprod)\n\t\t\t\t\tcurprod = ncurprod\n\t\t\t\t}\n\t\t\t\tt = gettok()\n\t\t\t}\n\t\t\tif t == PREC {\n\t\t\t\tif gettok() != IDENTIFIER {\n\t\t\t\t\tlerrorf(ruleline, \"illegal %%prec syntax\")\n\t\t\t\t}\n\t\t\t\tj = chfind(2, tokname)\n\t\t\t\tif j >= NTBASE {\n\t\t\t\t\tlerrorf(ruleline, \"nonterminal %s illegal after %%prec\", nontrst[j-NTBASE].name)\n\t\t\t\t}\n\t\t\t\tlevprd[nprod] = toklev[j]\n\t\t\t\tt = gettok()\n\t\t\t}\n\t\t\tif t != '=' {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlevprd[nprod] |= ACTFLAG\n\t\t\tfmt.Fprintf(fcode, \"\\n\\tcase %v:\", nprod)\n\t\t\tfmt.Fprintf(fcode, \"\\n\\t\\t%sDollar = %sS[%spt-%v:%spt+1]\", prefix, prefix, prefix, mem-1, prefix)\n\t\t\tcpyact(curprod, mem)\n\n\t\t\t// action within rule...\n\t\t\tt = gettok()\n\t\t\tif t == IDENTIFIER {\n\t\t\t\t// make it a nonterminal\n\t\t\t\tj = chfind(1, fmt.Sprintf(\"$$%v\", nprod))\n\n\t\t\t\t//\n\t\t\t\t// the current rule will become rule number nprod+1\n\t\t\t\t// enter null production for action\n\t\t\t\t//\n\t\t\t\tprdptr[nprod] = make([]int, 2)\n\t\t\t\tprdptr[nprod][0] = j\n\t\t\t\tprdptr[nprod][1] = -nprod\n\n\t\t\t\t// update the production information\n\t\t\t\tnprod++\n\t\t\t\tmoreprod()\n\t\t\t\tlevprd[nprod] = levprd[nprod-1] & ^ACTFLAG\n\t\t\t\tlevprd[nprod-1] = ACTFLAG\n\t\t\t\trlines[nprod] = lineno\n\n\t\t\t\t// make the action appear in the original rule\n\t\t\t\tcurprod[mem] = j\n\t\t\t\tmem++\n\t\t\t\tif mem >= len(curprod) {\n\t\t\t\t\tncurprod := make([]int, mem+RULEINC)\n\t\t\t\t\tcopy(ncurprod, curprod)\n\t\t\t\t\tcurprod = ncurprod\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor t == ';' {\n\t\t\tt = gettok()\n\t\t}\n\t\tcurprod[mem] = -nprod\n\t\tmem++\n\n\t\t// check that default action is reasonable\n\t\tif ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 &&\n\t\t\tnontrst[curprod[0]-NTBASE].value != 0 {\n\t\t\t// no explicit action, LHS has value\n\t\t\ttempty := curprod[1]\n\t\t\tif tempty < 0 {\n\t\t\t\tlerrorf(ruleline, \"must return a value, since LHS has a type\")\n\t\t\t}\n\t\t\tif tempty >= NTBASE {\n\t\t\t\ttempty = nontrst[tempty-NTBASE].value\n\t\t\t} else {\n\t\t\t\ttempty = TYPE(toklev[tempty])\n\t\t\t}\n\t\t\tif tempty != nontrst[curprod[0]-NTBASE].value {\n\t\t\t\tlerrorf(ruleline, \"default action causes potential type clash\")\n\t\t\t}\n\t\t}\n\t\tmoreprod()\n\t\tprdptr[nprod] = make([]int, mem)\n\t\tcopy(prdptr[nprod], curprod)\n\t\tnprod++\n\t\tmoreprod()\n\t\tlevprd[nprod] = 0\n\t}\n\n\tif TEMPSIZE < ntokens+nnonter+1 {\n\t\terrorf(\"too many tokens (%d) or non-terminals (%d)\", ntokens, nnonter)\n\t}\n\n\t//\n\t// end of all rules\n\t// dump out the prefix code\n\t//\n\n\tfmt.Fprintf(fcode, \"\\n\\t}\")\n\n\t// put out non-literal terminals\n\tfor i := TOKSTART; i <= ntokens; i++ {\n\t\t// non-literals\n\t\tif !tokset[i].noconst {\n\t\t\tfmt.Fprintf(ftable, \"const %v = %v\\n\", tokset[i].name, tokset[i].value)\n\t\t}\n\t}\n\n\t// put out names of tokens\n\tftable.WriteRune('\\n')\n\tfmt.Fprintf(ftable, \"var %sToknames = [...]string{\\n\", prefix)\n\tfor i := 1; i <= ntokens; i++ {\n\t\tfmt.Fprintf(ftable, \"\\t%q,\\n\", tokset[i].name)\n\t}\n\tfmt.Fprintf(ftable, \"}\\n\")\n\n\t// put out names of states.\n\t// commented out to avoid a huge table just for debugging.\n\t// re-enable to have the names in the binary.\n\tftable.WriteRune('\\n')\n\tfmt.Fprintf(ftable, \"var %sStatenames = [...]string{\\n\", prefix)\n\t//\tfor i:=TOKSTART; i<=ntokens; i++ {\n\t//\t\tfmt.Fprintf(ftable, \"\\t%q,\\n\", tokset[i].name);\n\t//\t}\n\tfmt.Fprintf(ftable, \"}\\n\")\n\n\tftable.WriteRune('\\n')\n\tfmt.Fprintf(ftable, \"const %sEofCode = 1\\n\", prefix)\n\tfmt.Fprintf(ftable, \"const %sErrCode = 2\\n\", prefix)\n\tfmt.Fprintf(ftable, \"const %sInitialStackSize = %v\\n\", prefix, initialstacksize)\n\n\t//\n\t// copy any postfix code\n\t//\n\tif t == MARK {\n\t\tif !lflag {\n\t\t\tfmt.Fprintf(ftable, \"\\n//line %v:%v\\n\", infile, lineno)\n\t\t}\n\t\tfor {\n\t\t\tc := getrune(finput)\n\t\t\tif c == EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tftable.WriteRune(c)\n\t\t}\n\t}\n}\n\n// allocate enough room to hold another production\nfunc moreprod() {\n\tn := len(prdptr)\n\tif nprod >= n {\n\t\tnn := n + PRODINC\n\t\taprod := make([][]int, nn)\n\t\talevprd := make([]int, nn)\n\t\tarlines := make([]int, nn)\n\n\t\tcopy(aprod, prdptr)\n\t\tcopy(alevprd, levprd)\n\t\tcopy(arlines, rlines)\n\n\t\tprdptr = aprod\n\t\tlevprd = alevprd\n\t\trlines = arlines\n\t}\n}\n\n// define s to be a terminal if nt==0\n// or a nonterminal if nt==1\nfunc defin(nt int, s string) int {\n\tval := 0\n\tif nt != 0 {\n\t\tnnonter++\n\t\tif nnonter >= len(nontrst) {\n\t\t\tanontrst := make([]Symb, nnonter+SYMINC)\n\t\t\tcopy(anontrst, nontrst)\n\t\t\tnontrst = anontrst\n\t\t}\n\t\tnontrst[nnonter] = Symb{name: s}\n\t\treturn NTBASE + nnonter\n\t}\n\n\t// must be a token\n\tntokens++\n\tif ntokens >= len(tokset) {\n\t\tnn := ntokens + SYMINC\n\t\tatokset := make([]Symb, nn)\n\t\tatoklev := make([]int, nn)\n\n\t\tcopy(atoklev, toklev)\n\t\tcopy(atokset, tokset)\n\n\t\ttokset = atokset\n\t\ttoklev = atoklev\n\t}\n\ttokset[ntokens].name = s\n\ttoklev[ntokens] = 0\n\n\t// establish value for token\n\t// single character literal\n\tif s[0] == '\\'' || s[0] == '\"' {\n\t\tq, err := strconv.Unquote(s)\n\t\tif err != nil {\n\t\t\terrorf(\"invalid token: %s\", err)\n\t\t}\n\t\trq := []rune(q)\n\t\tif len(rq) != 1 {\n\t\t\terrorf(\"character token too long: %s\", s)\n\t\t}\n\t\tval = int(rq[0])\n\t\tif val == 0 {\n\t\t\terrorf(\"token value 0 is illegal\")\n\t\t}\n\t\ttokset[ntokens].noconst = true\n\t} else {\n\t\tval = extval\n\t\textval++\n\t\tif s[0] == '$' {\n\t\t\ttokset[ntokens].noconst = true\n\t\t}\n\t}\n\n\ttokset[ntokens].value = val\n\treturn ntokens\n}\n\nvar peekline = 0\n\nfunc gettok() int {\n\tvar i int\n\tvar match, c rune\n\n\ttokname = \"\"\n\tfor {\n\t\tlineno += peekline\n\t\tpeekline = 0\n\t\tc = getrune(finput)\n\t\tfor c == ' ' || c == '\\n' || c == '\\t' || c == '\\v' || c == '\\r' {\n\t\t\tif c == '\\n' {\n\t\t\t\tlineno++\n\t\t\t}\n\t\t\tc = getrune(finput)\n\t\t}\n\n\t\t// skip comment -- fix\n\t\tif c != '/' {\n\t\t\tbreak\n\t\t}\n\t\tlineno += skipcom()\n\t}\n\n\tswitch c {\n\tcase EOF:\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> ENDFILE %v\\n\", lineno)\n\t\t}\n\t\treturn ENDFILE\n\n\tcase '{':\n\t\tungetrune(finput, c)\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> ={ %v\\n\", lineno)\n\t\t}\n\t\treturn '='\n\n\tcase '<':\n\t\t// get, and look up, a type name (union member name)\n\t\tc = getrune(finput)\n\t\tfor c != '>' && c != EOF && c != '\\n' {\n\t\t\ttokname += string(c)\n\t\t\tc = getrune(finput)\n\t\t}\n\n\t\tif c != '>' {\n\t\t\terrorf(\"unterminated < ... > clause\")\n\t\t}\n\n\t\tfor i = 1; i <= ntypes; i++ {\n\t\t\tif typeset[i] == tokname {\n\t\t\t\tnumbval = i\n\t\t\t\tif tokflag {\n\t\t\t\t\tfmt.Printf(\">>> TYPENAME old <%v> %v\\n\", tokname, lineno)\n\t\t\t\t}\n\t\t\t\treturn TYPENAME\n\t\t\t}\n\t\t}\n\t\tntypes++\n\t\tnumbval = ntypes\n\t\ttypeset[numbval] = tokname\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> TYPENAME new <%v> %v\\n\", tokname, lineno)\n\t\t}\n\t\treturn TYPENAME\n\n\tcase '\"', '\\'':\n\t\tmatch = c\n\t\ttokname = string(c)\n\t\tfor {\n\t\t\tc = getrune(finput)\n\t\t\tif c == '\\n' || c == EOF {\n\t\t\t\terrorf(\"illegal or missing ' or \\\"\")\n\t\t\t}\n\t\t\tif c == '\\\\' {\n\t\t\t\ttokname += string('\\\\')\n\t\t\t\tc = getrune(finput)\n\t\t\t} else if c == match {\n\t\t\t\tif tokflag {\n\t\t\t\t\tfmt.Printf(\">>> IDENTIFIER \\\"%v\\\" %v\\n\", tokname, lineno)\n\t\t\t\t}\n\t\t\t\ttokname += string(c)\n\t\t\t\treturn IDENTIFIER\n\t\t\t}\n\t\t\ttokname += string(c)\n\t\t}\n\n\tcase '%':\n\t\tc = getrune(finput)\n\t\tswitch c {\n\t\tcase '%':\n\t\t\tif tokflag {\n\t\t\t\tfmt.Printf(\">>> MARK %%%% %v\\n\", lineno)\n\t\t\t}\n\t\t\treturn MARK\n\t\tcase '=':\n\t\t\tif tokflag {\n\t\t\t\tfmt.Printf(\">>> PREC %%= %v\\n\", lineno)\n\t\t\t}\n\t\t\treturn PREC\n\t\tcase '{':\n\t\t\tif tokflag {\n\t\t\t\tfmt.Printf(\">>> LCURLY %%{ %v\\n\", lineno)\n\t\t\t}\n\t\t\treturn LCURLY\n\t\t}\n\n\t\tgetword(c)\n\t\t// find a reserved word\n\t\tfor i := range resrv {\n\t\t\tif tokname == resrv[i].name {\n\t\t\t\tif tokflag {\n\t\t\t\t\tfmt.Printf(\">>> %%%v %v %v\\n\", tokname,\n\t\t\t\t\t\tresrv[i].value-PRIVATE, lineno)\n\t\t\t\t}\n\t\t\t\treturn resrv[i].value\n\t\t\t}\n\t\t}\n\t\terrorf(\"invalid escape, or illegal reserved word: %v\", tokname)\n\n\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\tnumbval = int(c - '0')\n\t\tfor {\n\t\t\tc = getrune(finput)\n\t\t\tif !isdigit(c) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tnumbval = numbval*10 + int(c-'0')\n\t\t}\n\t\tungetrune(finput, c)\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> NUMBER %v %v\\n\", numbval, lineno)\n\t\t}\n\t\treturn NUMBER\n\n\tdefault:\n\t\tif isword(c) || c == '.' || c == '$' {\n\t\t\tgetword(c)\n\t\t\tbreak\n\t\t}\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> OPERATOR %v %v\\n\", string(c), lineno)\n\t\t}\n\t\treturn int(c)\n\t}\n\n\t// look ahead to distinguish IDENTIFIER from IDENTCOLON\n\tc = getrune(finput)\n\tfor c == ' ' || c == '\\t' || c == '\\n' || c == '\\v' || c == '\\r' || c == '/' {\n\t\tif c == '\\n' {\n\t\t\tpeekline++\n\t\t}\n\t\t// look for comments\n\t\tif c == '/' {\n\t\t\tpeekline += skipcom()\n\t\t}\n\t\tc = getrune(finput)\n\t}\n\tif c == ':' {\n\t\tif tokflag {\n\t\t\tfmt.Printf(\">>> IDENTCOLON %v: %v\\n\", tokname, lineno)\n\t\t}\n\t\treturn IDENTCOLON\n\t}\n\n\tungetrune(finput, c)\n\tif tokflag {\n\t\tfmt.Printf(\">>> IDENTIFIER %v %v\\n\", tokname, lineno)\n\t}\n\treturn IDENTIFIER\n}\n\nfunc getword(c rune) {\n\ttokname = \"\"\n\tfor isword(c) || isdigit(c) || c == '.' || c == '$' {\n\t\ttokname += string(c)\n\t\tc = getrune(finput)\n\t}\n\tungetrune(finput, c)\n}\n\n// determine the type of a symbol\nfunc fdtype(t int) int {\n\tvar v int\n\tvar s string\n\n\tif t >= NTBASE {\n\t\tv = nontrst[t-NTBASE].value\n\t\ts = nontrst[t-NTBASE].name\n\t} else {\n\t\tv = TYPE(toklev[t])\n\t\ts = tokset[t].name\n\t}\n\tif v <= 0 {\n\t\terrorf(\"must specify type for %v\", s)\n\t}\n\treturn v\n}\n\nfunc chfind(t int, s string) int {\n\tif s[0] == '\"' || s[0] == '\\'' {\n\t\tt = 0\n\t}\n\tfor i := 0; i <= ntokens; i++ {\n\t\tif s == tokset[i].name {\n\t\t\treturn i\n\t\t}\n\t}\n\tfor i := 0; i <= nnonter; i++ {\n\t\tif s == nontrst[i].name {\n\t\t\treturn NTBASE + i\n\t\t}\n\t}\n\n\t// cannot find name\n\tif t > 1 {\n\t\terrorf(\"%v should have been defined earlier\", s)\n\t}\n\treturn defin(t, s)\n}\n\n// copy the union declaration to the output, and the define file if present\nfunc cpyunion() {\n\n\tif !lflag {\n\t\tfmt.Fprintf(ftable, \"\\n//line %v:%v\\n\", infile, lineno)\n\t}\n\tfmt.Fprintf(ftable, \"type %sSymType struct\", prefix)\n\n\tlevel := 0\n\nout:\n\tfor {\n\t\tc := getrune(finput)\n\t\tif c == EOF {\n\t\t\terrorf(\"EOF encountered while processing %%union\")\n\t\t}\n\t\tftable.WriteRune(c)\n\t\tswitch c {\n\t\tcase '\\n':\n\t\t\tlineno++\n\t\tcase '{':\n\t\t\tif level == 0 {\n\t\t\t\tfmt.Fprintf(ftable, \"\\n\\tyys int\")\n\t\t\t}\n\t\t\tlevel++\n\t\tcase '}':\n\t\t\tlevel--\n\t\t\tif level == 0 {\n\t\t\t\tbreak out\n\t\t\t}\n\t\t}\n\t}\n\tfmt.Fprintf(ftable, \"\\n\\n\")\n}\n\n// saves code between %{ and %}\n// adds an import for __fmt__ the first time\nfunc cpycode() {\n\tlno := lineno\n\n\tc := getrune(finput)\n\tif c == '\\n' {\n\t\tc = getrune(finput)\n\t\tlineno++\n\t}\n\tif !lflag {\n\t\tfmt.Fprintf(ftable, \"\\n//line %v:%v\\n\", infile, lineno)\n\t}\n\t// accumulate until %}\n\tcode := make([]rune, 0, 1024)\n\tfor c != EOF {\n\t\tif c == '%' {\n\t\t\tc = getrune(finput)\n\t\t\tif c == '}' {\n\t\t\t\temitcode(code, lno+1)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcode = append(code, '%')\n\t\t}\n\t\tcode = append(code, c)\n\t\tif c == '\\n' {\n\t\t\tlineno++\n\t\t}\n\t\tc = getrune(finput)\n\t}\n\tlineno = lno\n\terrorf(\"eof before %%}\")\n}\n\n// emits code saved up from between %{ and %}\n// called by cpycode\n// adds an import for __yyfmt__ after the package clause\nfunc emitcode(code []rune, lineno int) {\n\tfor i, line := range lines(code) {\n\t\twritecode(line)\n\t\tif !fmtImported && isPackageClause(line) {\n\t\t\tfmt.Fprintln(ftable, `import __yyfmt__ \"fmt\"`)\n\t\t\tif !lflag {\n\t\t\t\tfmt.Fprintf(ftable, \"//line %v:%v\\n\\t\\t\", infile, lineno+i)\n\t\t\t}\n\t\t\tfmtImported = true\n\t\t}\n\t}\n}\n\n// does this line look like a package clause?  not perfect: might be confused by early comments.\nfunc isPackageClause(line []rune) bool {\n\tline = skipspace(line)\n\n\t// must be big enough.\n\tif len(line) < len(\"package X\\n\") {\n\t\treturn false\n\t}\n\n\t// must start with \"package\"\n\tfor i, r := range []rune(\"package\") {\n\t\tif line[i] != r {\n\t\t\treturn false\n\t\t}\n\t}\n\tline = skipspace(line[len(\"package\"):])\n\n\t// must have another identifier.\n\tif len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {\n\t\treturn false\n\t}\n\tfor len(line) > 0 {\n\t\tif !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {\n\t\t\tbreak\n\t\t}\n\t\tline = line[1:]\n\t}\n\tline = skipspace(line)\n\n\t// eol, newline, or comment must follow\n\tif len(line) == 0 {\n\t\treturn true\n\t}\n\tif line[0] == '\\r' || line[0] == '\\n' {\n\t\treturn true\n\t}\n\tif len(line) >= 2 {\n\t\treturn line[0] == '/' && (line[1] == '/' || line[1] == '*')\n\t}\n\treturn false\n}\n\n// skip initial spaces\nfunc skipspace(line []rune) []rune {\n\tfor len(line) > 0 {\n\t\tif line[0] != ' ' && line[0] != '\\t' {\n\t\t\tbreak\n\t\t}\n\t\tline = line[1:]\n\t}\n\treturn line\n}\n\n// break code into lines\nfunc lines(code []rune) [][]rune {\n\tl := make([][]rune, 0, 100)\n\tfor len(code) > 0 {\n\t\t// one line per loop\n\t\tvar i int\n\t\tfor i = range code {\n\t\t\tif code[i] == '\\n' {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tl = append(l, code[:i+1])\n\t\tcode = code[i+1:]\n\t}\n\treturn l\n}\n\n// writes code to ftable\nfunc writecode(code []rune) {\n\tfor _, r := range code {\n\t\tftable.WriteRune(r)\n\t}\n}\n\n// skip over comments\n// skipcom is called after reading a '/'\nfunc skipcom() int {\n\tc := getrune(finput)\n\tif c == '/' {\n\t\tfor c != EOF {\n\t\t\tif c == '\\n' {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tc = getrune(finput)\n\t\t}\n\t\terrorf(\"EOF inside comment\")\n\t\treturn 0\n\t}\n\tif c != '*' {\n\t\terrorf(\"illegal comment\")\n\t}\n\n\tnl := 0 // lines skipped\n\tc = getrune(finput)\n\nl1:\n\tswitch c {\n\tcase '*':\n\t\tc = getrune(finput)\n\t\tif c == '/' {\n\t\t\tbreak\n\t\t}\n\t\tgoto l1\n\n\tcase '\\n':\n\t\tnl++\n\t\tfallthrough\n\n\tdefault:\n\t\tc = getrune(finput)\n\t\tgoto l1\n\t}\n\treturn nl\n}\n\n// copy action to the next ; or closing }\nfunc cpyact(curprod []int, max int) {\n\n\tif !lflag {\n\t\tfmt.Fprintf(fcode, \"\\n//line %v:%v\", infile, lineno)\n\t}\n\tfmt.Fprint(fcode, \"\\n\\t\\t\")\n\n\tlno := lineno\n\tbrac := 0\n\nloop:\n\tfor {\n\t\tc := getrune(finput)\n\n\tswt:\n\t\tswitch c {\n\t\tcase ';':\n\t\t\tif brac == 0 {\n\t\t\t\tfcode.WriteRune(c)\n\t\t\t\treturn\n\t\t\t}\n\n\t\tcase '{':\n\t\t\tbrac++\n\n\t\tcase '$':\n\t\t\ts := 1\n\t\t\ttok := -1\n\t\t\tc = getrune(finput)\n\n\t\t\t// type description\n\t\t\tif c == '<' {\n\t\t\t\tungetrune(finput, c)\n\t\t\t\tif gettok() != TYPENAME {\n\t\t\t\t\terrorf(\"bad syntax on $<ident> clause\")\n\t\t\t\t}\n\t\t\t\ttok = numbval\n\t\t\t\tc = getrune(finput)\n\t\t\t}\n\t\t\tif c == '$' {\n\t\t\t\tfmt.Fprintf(fcode, \"%sVAL\", prefix)\n\n\t\t\t\t// put out the proper tag...\n\t\t\t\tif ntypes != 0 {\n\t\t\t\t\tif tok < 0 {\n\t\t\t\t\t\ttok = fdtype(curprod[0])\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(fcode, \".%v\", typeset[tok])\n\t\t\t\t}\n\t\t\t\tcontinue loop\n\t\t\t}\n\t\t\tif c == '-' {\n\t\t\t\ts = -s\n\t\t\t\tc = getrune(finput)\n\t\t\t}\n\t\t\tj := 0\n\t\t\tif isdigit(c) {\n\t\t\t\tfor isdigit(c) {\n\t\t\t\t\tj = j*10 + int(c-'0')\n\t\t\t\t\tc = getrune(finput)\n\t\t\t\t}\n\t\t\t\tungetrune(finput, c)\n\t\t\t\tj = j * s\n\t\t\t\tif j >= max {\n\t\t\t\t\terrorf(\"Illegal use of $%v\", j)\n\t\t\t\t}\n\t\t\t} else if isword(c) || c == '.' {\n\t\t\t\t// look for $name\n\t\t\t\tungetrune(finput, c)\n\t\t\t\tif gettok() != IDENTIFIER {\n\t\t\t\t\terrorf(\"$ must be followed by an identifier\")\n\t\t\t\t}\n\t\t\t\ttokn := chfind(2, tokname)\n\t\t\t\tfnd := -1\n\t\t\t\tc = getrune(finput)\n\t\t\t\tif c != '@' {\n\t\t\t\t\tungetrune(finput, c)\n\t\t\t\t} else if gettok() != NUMBER {\n\t\t\t\t\terrorf(\"@ must be followed by number\")\n\t\t\t\t} else {\n\t\t\t\t\tfnd = numbval\n\t\t\t\t}\n\t\t\t\tfor j = 1; j < max; j++ {\n\t\t\t\t\tif tokn == curprod[j] {\n\t\t\t\t\t\tfnd--\n\t\t\t\t\t\tif fnd <= 0 {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif j >= max {\n\t\t\t\t\terrorf(\"$name or $name@number not found\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfcode.WriteRune('$')\n\t\t\t\tif s < 0 {\n\t\t\t\t\tfcode.WriteRune('-')\n\t\t\t\t}\n\t\t\t\tungetrune(finput, c)\n\t\t\t\tcontinue loop\n\t\t\t}\n\t\t\tfmt.Fprintf(fcode, \"%sDollar[%v]\", prefix, j)\n\n\t\t\t// put out the proper tag\n\t\t\tif ntypes != 0 {\n\t\t\t\tif j <= 0 && tok < 0 {\n\t\t\t\t\terrorf(\"must specify type of $%v\", j)\n\t\t\t\t}\n\t\t\t\tif tok < 0 {\n\t\t\t\t\ttok = fdtype(curprod[j])\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(fcode, \".%v\", typeset[tok])\n\t\t\t}\n\t\t\tcontinue loop\n\n\t\tcase '}':\n\t\t\tbrac--\n\t\t\tif brac != 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tfcode.WriteRune(c)\n\t\t\treturn\n\n\t\tcase '/':\n\t\t\tnc := getrune(finput)\n\t\t\tif nc != '/' && nc != '*' {\n\t\t\t\tungetrune(finput, nc)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// a comment\n\t\t\tfcode.WriteRune(c)\n\t\t\tfcode.WriteRune(nc)\n\t\t\tc = getrune(finput)\n\t\t\tfor c != EOF {\n\t\t\t\tswitch {\n\t\t\t\tcase c == '\\n':\n\t\t\t\t\tlineno++\n\t\t\t\t\tif nc == '/' { // end of // comment\n\t\t\t\t\t\tbreak swt\n\t\t\t\t\t}\n\t\t\t\tcase c == '*' && nc == '*': // end of /* comment?\n\t\t\t\t\tnnc := getrune(finput)\n\t\t\t\t\tif nnc == '/' {\n\t\t\t\t\t\tfcode.WriteRune('*')\n\t\t\t\t\t\tfcode.WriteRune('/')\n\t\t\t\t\t\tcontinue loop\n\t\t\t\t\t}\n\t\t\t\t\tungetrune(finput, nnc)\n\t\t\t\t}\n\t\t\t\tfcode.WriteRune(c)\n\t\t\t\tc = getrune(finput)\n\t\t\t}\n\t\t\terrorf(\"EOF inside comment\")\n\n\t\tcase '\\'', '\"':\n\t\t\t// character string or constant\n\t\t\tmatch := c\n\t\t\tfcode.WriteRune(c)\n\t\t\tc = getrune(finput)\n\t\t\tfor c != EOF {\n\t\t\t\tif c == '\\\\' {\n\t\t\t\t\tfcode.WriteRune(c)\n\t\t\t\t\tc = getrune(finput)\n\t\t\t\t\tif c == '\\n' {\n\t\t\t\t\t\tlineno++\n\t\t\t\t\t}\n\t\t\t\t} else if c == match {\n\t\t\t\t\tbreak swt\n\t\t\t\t}\n\t\t\t\tif c == '\\n' {\n\t\t\t\t\terrorf(\"newline in string or char const\")\n\t\t\t\t}\n\t\t\t\tfcode.WriteRune(c)\n\t\t\t\tc = getrune(finput)\n\t\t\t}\n\t\t\terrorf(\"EOF in string or character constant\")\n\n\t\tcase EOF:\n\t\t\tlineno = lno\n\t\t\terrorf(\"action does not terminate\")\n\n\t\tcase '\\n':\n\t\t\tfmt.Fprint(fcode, \"\\n\\t\")\n\t\t\tlineno++\n\t\t\tcontinue loop\n\t\t}\n\n\t\tfcode.WriteRune(c)\n\t}\n}\n\nfunc openup() {\n\tinfile = flag.Arg(0)\n\tfinput = open(infile)\n\tif finput == nil {\n\t\terrorf(\"cannot open %v\", infile)\n\t}\n\n\tfoutput = nil\n\tif vflag != \"\" {\n\t\tfoutput = create(vflag)\n\t\tif foutput == nil {\n\t\t\terrorf(\"can't create file %v\", vflag)\n\t\t}\n\t}\n\n\tftable = nil\n\tif oflag == \"\" {\n\t\toflag = \"y.go\"\n\t}\n\tftable = create(oflag)\n\tif ftable == nil {\n\t\terrorf(\"can't create file %v\", oflag)\n\t}\n\n}\n\n// return a pointer to the name of symbol i\nfunc symnam(i int) string {\n\tvar s string\n\n\tif i >= NTBASE {\n\t\ts = nontrst[i-NTBASE].name\n\t} else {\n\t\ts = tokset[i].name\n\t}\n\treturn s\n}\n\n// set elements 0 through n-1 to c\nfunc aryfil(v []int, n, c int) {\n\tfor i := range n {\n\t\tv[i] = c\n\t}\n}\n\n// compute an array with the beginnings of productions yielding given nonterminals\n// The array pres points to these lists\n// the array pyield has the lists: the total size is only NPROD+1\nfunc cpres() {\n\tpres = make([][][]int, nnonter+1)\n\tcurres := make([][]int, nprod)\n\n\tif false {\n\t\tfor j := 0; j <= nnonter; j++ {\n\t\t\tfmt.Printf(\"nnonter[%v] = %v\\n\", j, nontrst[j].name)\n\t\t}\n\t\tfor j := 0; j < nprod; j++ {\n\t\t\tfmt.Printf(\"prdptr[%v][0] = %v+NTBASE\\n\", j, prdptr[j][0]-NTBASE)\n\t\t}\n\t}\n\n\tfatfl = 0 // make undefined symbols nonfatal\n\tfor i := 0; i <= nnonter; i++ {\n\t\tn := 0\n\t\tc := i + NTBASE\n\t\tfor j := 0; j < nprod; j++ {\n\t\t\tif prdptr[j][0] == c {\n\t\t\t\tcurres[n] = prdptr[j][1:]\n\t\t\t\tn++\n\t\t\t}\n\t\t}\n\t\tif n == 0 {\n\t\t\terrorf(\"nonterminal %v not defined\", nontrst[i].name)\n\t\t\tcontinue\n\t\t}\n\t\tpres[i] = make([][]int, n)\n\t\tcopy(pres[i], curres)\n\t}\n\tfatfl = 1\n\tif nerrors != 0 {\n\t\tsummary()\n\t\texit(1)\n\t}\n}\n\n// mark nonterminals which derive the empty string\n// also, look for nonterminals which don't derive any token strings\nfunc cempty() {\n\tvar i, p, np int\n\tvar prd []int\n\n\tpempty = make([]int, nnonter+1)\n\n\t// first, use the array pempty to detect productions that can never be reduced\n\t// set pempty to WHONOWS\n\taryfil(pempty, nnonter+1, WHOKNOWS)\n\n\t// now, look at productions, marking nonterminals which derive something\nmore:\n\tfor {\n\t\tfor i = 0; i < nprod; i++ {\n\t\t\tprd = prdptr[i]\n\t\t\tif pempty[prd[0]-NTBASE] != 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnp = len(prd) - 1\n\t\t\tfor p = 1; p < np; p++ {\n\t\t\t\tif prd[p] >= NTBASE && pempty[prd[p]-NTBASE] == WHOKNOWS {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\t// production can be derived\n\t\t\tif p == np {\n\t\t\t\tpempty[prd[0]-NTBASE] = OK\n\t\t\t\tcontinue more\n\t\t\t}\n\t\t}\n\t\tbreak\n\t}\n\n\t// now, look at the nonterminals, to see if they are all OK\n\tfor i = 0; i <= nnonter; i++ {\n\t\t// the added production rises or falls as the start symbol ...\n\t\tif i == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif pempty[i] != OK {\n\t\t\tfatfl = 0\n\t\t\terrorf(\"nonterminal %s never derives any token string\", nontrst[i].name)\n\t\t}\n\t}\n\n\tif nerrors != 0 {\n\t\tsummary()\n\t\texit(1)\n\t}\n\n\t// now, compute the pempty array, to see which nonterminals derive the empty string\n\t// set pempty to WHOKNOWS\n\taryfil(pempty, nnonter+1, WHOKNOWS)\n\n\t// loop as long as we keep finding empty nonterminals\n\nagain:\n\tfor {\n\tnext:\n\t\tfor i = 1; i < nprod; i++ {\n\t\t\t// not known to be empty\n\t\t\tprd = prdptr[i]\n\t\t\tif pempty[prd[0]-NTBASE] != WHOKNOWS {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnp = len(prd) - 1\n\t\t\tfor p = 1; p < np; p++ {\n\t\t\t\tif prd[p] < NTBASE || pempty[prd[p]-NTBASE] != EMPTY {\n\t\t\t\t\tcontinue next\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// we have a nontrivially empty nonterminal\n\t\t\tpempty[prd[0]-NTBASE] = EMPTY\n\n\t\t\t// got one ... try for another\n\t\t\tcontinue again\n\t\t}\n\t\treturn\n\t}\n}\n\n// compute an array with the first of nonterminals\nfunc cpfir() {\n\tvar s, n, p, np, ch, i int\n\tvar curres [][]int\n\tvar prd []int\n\n\twsets = make([]Wset, nnonter+WSETINC)\n\tpfirst = make([]Lkset, nnonter+1)\n\tfor i = 0; i <= nnonter; i++ {\n\t\twsets[i].ws = mkset()\n\t\tpfirst[i] = mkset()\n\t\tcurres = pres[i]\n\t\tn = len(curres)\n\n\t\t// initially fill the sets\n\t\tfor s = 0; s < n; s++ {\n\t\t\tprd = curres[s]\n\t\t\tnp = len(prd) - 1\n\t\t\tfor p = 0; p < np; p++ {\n\t\t\t\tch = prd[p]\n\t\t\t\tif ch < NTBASE {\n\t\t\t\t\tsetbit(pfirst[i], ch)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif pempty[ch-NTBASE] == 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// now, reflect transitivity\n\tchanges := 1\n\tfor changes != 0 {\n\t\tchanges = 0\n\t\tfor i = 0; i <= nnonter; i++ {\n\t\t\tcurres = pres[i]\n\t\t\tn = len(curres)\n\t\t\tfor s = 0; s < n; s++ {\n\t\t\t\tprd = curres[s]\n\t\t\t\tnp = len(prd) - 1\n\t\t\t\tfor p = 0; p < np; p++ {\n\t\t\t\t\tch = prd[p] - NTBASE\n\t\t\t\t\tif ch < 0 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tchanges |= setunion(pfirst[i], pfirst[ch])\n\t\t\t\t\tif pempty[ch] == 0 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif indebug == 0 {\n\t\treturn\n\t}\n\tif foutput != nil {\n\t\tfor i = 0; i <= nnonter; i++ {\n\t\t\tfmt.Fprintf(foutput, \"\\n%v: %v %v\\n\",\n\t\t\t\tnontrst[i].name, pfirst[i], pempty[i])\n\t\t}\n\t}\n}\n\n// generate the states\nfunc stagen() {\n\t// initialize\n\tnstate = 0\n\ttstates = make([]int, ntokens+1)  // states generated by terminal gotos\n\tntstates = make([]int, nnonter+1) // states generated by nonterminal gotos\n\tamem = make([]int, ACTSIZE)\n\tmemp = 0\n\n\tclset = mkset()\n\tpstate[0] = 0\n\tpstate[1] = 0\n\taryfil(clset, tbitset, 0)\n\tputitem(Pitem{prdptr[0], 0, 0, 0}, clset)\n\ttystate[0] = MUSTDO\n\tnstate = 1\n\tpstate[2] = pstate[1]\n\n\t//\n\t// now, the main state generation loop\n\t// first pass generates all of the states\n\t// later passes fix up lookahead\n\t// could be sped up a lot by remembering\n\t// results of the first pass rather than recomputing\n\t//\n\tfirst := 1\n\tfor more := 1; more != 0; first = 0 {\n\t\tmore = 0\n\t\tfor i := 0; i < nstate; i++ {\n\t\t\tif tystate[i] != MUSTDO {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttystate[i] = DONE\n\t\t\taryfil(temp1, nnonter+1, 0)\n\n\t\t\t// take state i, close it, and do gotos\n\t\t\tclosure(i)\n\n\t\t\t// generate goto's\n\t\t\tfor p := 0; p < cwp; p++ {\n\t\t\t\tpi := wsets[p]\n\t\t\t\tif pi.flag != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\twsets[p].flag = 1\n\t\t\t\tc := pi.pitem.first\n\t\t\t\tif c <= 1 {\n\t\t\t\t\tif pstate[i+1]-pstate[i] <= p {\n\t\t\t\t\t\ttystate[i] = MUSTLOOKAHEAD\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// do a goto on c\n\t\t\t\tputitem(wsets[p].pitem, wsets[p].ws)\n\t\t\t\tfor q := p + 1; q < cwp; q++ {\n\t\t\t\t\t// this item contributes to the goto\n\t\t\t\t\tif c == wsets[q].pitem.first {\n\t\t\t\t\t\tputitem(wsets[q].pitem, wsets[q].ws)\n\t\t\t\t\t\twsets[q].flag = 1\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif c < NTBASE {\n\t\t\t\t\tstate(c) // register new state\n\t\t\t\t} else {\n\t\t\t\t\ttemp1[c-NTBASE] = state(c)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif gsdebug != 0 && foutput != nil {\n\t\t\t\tfmt.Fprintf(foutput, \"%v: \", i)\n\t\t\t\tfor j := 0; j <= nnonter; j++ {\n\t\t\t\t\tif temp1[j] != 0 {\n\t\t\t\t\t\tfmt.Fprintf(foutput, \"%v %v,\", nontrst[j].name, temp1[j])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(foutput, \"\\n\")\n\t\t\t}\n\n\t\t\tif first != 0 {\n\t\t\t\tindgo[i] = apack(temp1[1:], nnonter-1) - 1\n\t\t\t}\n\n\t\t\tmore++\n\t\t}\n\t}\n}\n\n// generate the closure of state i\nfunc closure(i int) {\n\tzzclose++\n\n\t// first, copy kernel of state i to wsets\n\tcwp = 0\n\tq := pstate[i+1]\n\tfor p := pstate[i]; p < q; p++ {\n\t\twsets[cwp].pitem = statemem[p].pitem\n\t\twsets[cwp].flag = 1 // this item must get closed\n\t\tcopy(wsets[cwp].ws, statemem[p].look)\n\t\tcwp++\n\t}\n\n\t// now, go through the loop, closing each item\n\twork := 1\n\tfor work != 0 {\n\t\twork = 0\n\t\tfor u := 0; u < cwp; u++ {\n\t\t\tif wsets[u].flag == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// dot is before c\n\t\t\tc := wsets[u].pitem.first\n\t\t\tif c < NTBASE {\n\t\t\t\twsets[u].flag = 0\n\t\t\t\t// only interesting case is where . is before nonterminal\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// compute the lookahead\n\t\t\taryfil(clset, tbitset, 0)\n\n\t\t\t// find items involving c\n\t\t\tfor v := u; v < cwp; v++ {\n\t\t\t\tif wsets[v].flag != 1 || wsets[v].pitem.first != c {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tpi := wsets[v].pitem.prod\n\t\t\t\tipi := wsets[v].pitem.off + 1\n\n\t\t\t\twsets[v].flag = 0\n\t\t\t\tif nolook != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tch := pi[ipi]\n\t\t\t\tipi++\n\t\t\t\tfor ch > 0 {\n\t\t\t\t\t// terminal symbol\n\t\t\t\t\tif ch < NTBASE {\n\t\t\t\t\t\tsetbit(clset, ch)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\n\t\t\t\t\t// nonterminal symbol\n\t\t\t\t\tsetunion(clset, pfirst[ch-NTBASE])\n\t\t\t\t\tif pempty[ch-NTBASE] == 0 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tch = pi[ipi]\n\t\t\t\t\tipi++\n\t\t\t\t}\n\t\t\t\tif ch <= 0 {\n\t\t\t\t\tsetunion(clset, wsets[v].ws)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//\n\t\t\t// now loop over productions derived from c\n\t\t\t//\n\t\t\tcurres := pres[c-NTBASE]\n\t\t\tn := len(curres)\n\n\t\tnexts:\n\t\t\t// initially fill the sets\n\t\t\tfor s := range n {\n\t\t\t\tprd := curres[s]\n\n\t\t\t\t//\n\t\t\t\t// put these items into the closure\n\t\t\t\t// is the item there\n\t\t\t\t//\n\t\t\t\tfor v := 0; v < cwp; v++ {\n\t\t\t\t\t// yes, it is there\n\t\t\t\t\tif wsets[v].pitem.off == 0 &&\n\t\t\t\t\t\taryeq(wsets[v].pitem.prod, prd) != 0 {\n\t\t\t\t\t\tif nolook == 0 &&\n\t\t\t\t\t\t\tsetunion(wsets[v].ws, clset) != 0 {\n\t\t\t\t\t\t\twsets[v].flag = 1\n\t\t\t\t\t\t\twork = 1\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue nexts\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//  not there; make a new entry\n\t\t\t\tif cwp >= len(wsets) {\n\t\t\t\t\tawsets := make([]Wset, cwp+WSETINC)\n\t\t\t\t\tcopy(awsets, wsets)\n\t\t\t\t\twsets = awsets\n\t\t\t\t}\n\t\t\t\twsets[cwp].pitem = Pitem{prd, 0, prd[0], -prd[len(prd)-1]}\n\t\t\t\twsets[cwp].flag = 1\n\t\t\t\twsets[cwp].ws = mkset()\n\t\t\t\tif nolook == 0 {\n\t\t\t\t\twork = 1\n\t\t\t\t\tcopy(wsets[cwp].ws, clset)\n\t\t\t\t}\n\t\t\t\tcwp++\n\t\t\t}\n\t\t}\n\t}\n\n\t// have computed closure; flags are reset; return\n\tif cldebug != 0 && foutput != nil {\n\t\tfmt.Fprintf(foutput, \"\\nState %v, nolook = %v\\n\", i, nolook)\n\t\tfor u := 0; u < cwp; u++ {\n\t\t\tif wsets[u].flag != 0 {\n\t\t\t\tfmt.Fprintf(foutput, \"flag set\\n\")\n\t\t\t}\n\t\t\twsets[u].flag = 0\n\t\t\tfmt.Fprintf(foutput, \"\\t%v\", writem(wsets[u].pitem))\n\t\t\tprlook(wsets[u].ws)\n\t\t\tfmt.Fprintf(foutput, \"\\n\")\n\t\t}\n\t}\n}\n\n// sorts last state,and sees if it equals earlier ones. returns state number\nfunc state(c int) int {\n\tzzstate++\n\tp1 := pstate[nstate]\n\tp2 := pstate[nstate+1]\n\tif p1 == p2 {\n\t\treturn 0 // null state\n\t}\n\n\t// sort the items\n\tvar k, l int\n\tfor k = p1 + 1; k < p2; k++ { // make k the biggest\n\t\tfor l = k; l > p1; l-- {\n\t\t\tif statemem[l].pitem.prodno < statemem[l-1].pitem.prodno ||\n\t\t\t\tstatemem[l].pitem.prodno == statemem[l-1].pitem.prodno &&\n\t\t\t\t\tstatemem[l].pitem.off < statemem[l-1].pitem.off {\n\t\t\t\ts := statemem[l]\n\t\t\t\tstatemem[l] = statemem[l-1]\n\t\t\t\tstatemem[l-1] = s\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tsize1 := p2 - p1 // size of state\n\n\tvar i int\n\tif c >= NTBASE {\n\t\ti = ntstates[c-NTBASE]\n\t} else {\n\t\ti = tstates[c]\n\t}\n\nlook:\n\tfor ; i != 0; i = mstates[i] {\n\t\t// get ith state\n\t\tq1 := pstate[i]\n\t\tq2 := pstate[i+1]\n\t\tsize2 := q2 - q1\n\t\tif size1 != size2 {\n\t\t\tcontinue\n\t\t}\n\t\tk = p1\n\t\tfor l = q1; l < q2; l++ {\n\t\t\tif aryeq(statemem[l].pitem.prod, statemem[k].pitem.prod) == 0 ||\n\t\t\t\tstatemem[l].pitem.off != statemem[k].pitem.off {\n\t\t\t\tcontinue look\n\t\t\t}\n\t\t\tk++\n\t\t}\n\n\t\t// found it\n\t\tpstate[nstate+1] = pstate[nstate] // delete last state\n\n\t\t// fix up lookaheads\n\t\tif nolook != 0 {\n\t\t\treturn i\n\t\t}\n\t\tk = p1\n\t\tfor l = q1; l < q2; l++ {\n\t\t\tif setunion(statemem[l].look, statemem[k].look) != 0 {\n\t\t\t\ttystate[i] = MUSTDO\n\t\t\t}\n\t\t\tk++\n\t\t}\n\t\treturn i\n\t}\n\n\t// state is new\n\tzznewstate++\n\tif nolook != 0 {\n\t\terrorf(\"yacc state/nolook error\")\n\t}\n\tpstate[nstate+2] = p2\n\tif nstate+1 >= NSTATES {\n\t\terrorf(\"too many states\")\n\t}\n\tif c >= NTBASE {\n\t\tmstates[nstate] = ntstates[c-NTBASE]\n\t\tntstates[c-NTBASE] = nstate\n\t} else {\n\t\tmstates[nstate] = tstates[c]\n\t\ttstates[c] = nstate\n\t}\n\ttystate[nstate] = MUSTDO\n\tnstate++\n\treturn nstate - 1\n}\n\nfunc putitem(p Pitem, set Lkset) {\n\tp.off++\n\tp.first = p.prod[p.off]\n\n\tif pidebug != 0 && foutput != nil {\n\t\tfmt.Fprintf(foutput, \"putitem(%v), state %v\\n\", writem(p), nstate)\n\t}\n\tj := pstate[nstate+1]\n\tif j >= len(statemem) {\n\t\tasm := make([]Item, j+STATEINC)\n\t\tcopy(asm, statemem)\n\t\tstatemem = asm\n\t}\n\tstatemem[j].pitem = p\n\tif nolook == 0 {\n\t\ts := mkset()\n\t\tcopy(s, set)\n\t\tstatemem[j].look = s\n\t}\n\tj++\n\tpstate[nstate+1] = j\n}\n\n// creates output string for item pointed to by pp\nfunc writem(pp Pitem) string {\n\tvar i int\n\n\tp := pp.prod\n\tvar q strings.Builder\n\tq.WriteString(chcopy(nontrst[prdptr[pp.prodno][0]-NTBASE].name))\n\tq.WriteString(\": \")\n\tnpi := pp.off\n\n\tpi := aryeq(p, prdptr[pp.prodno])\n\n\tfor {\n\t\tc := ' '\n\t\tif pi == npi {\n\t\t\tc = '.'\n\t\t}\n\t\tq.WriteByte(byte(c))\n\n\t\ti = p[pi]\n\t\tpi++\n\t\tif i <= 0 {\n\t\t\tbreak\n\t\t}\n\t\tq.WriteString(chcopy(symnam(i)))\n\t}\n\n\t// an item calling for a reduction\n\ti = p[npi]\n\tif i < 0 {\n\t\tfmt.Fprintf(&q, \"    (%v)\", -i)\n\t}\n\n\treturn q.String()\n}\n\n// pack state i from temp1 into amem\nfunc apack(p []int, n int) int {\n\t//\n\t// we don't need to worry about checking because\n\t// we will only look at entries known to be there...\n\t// eliminate leading and trailing 0's\n\t//\n\toff := 0\n\tpp := 0\n\tfor ; pp <= n && p[pp] == 0; pp++ {\n\t\toff--\n\t}\n\n\t// no actions\n\tif pp > n {\n\t\treturn 0\n\t}\n\tfor ; n > pp && p[n] == 0; n-- {\n\t}\n\tp = p[pp : n+1]\n\n\t// now, find a place for the elements from p to q, inclusive\n\tr := len(amem) - len(p)\n\nnextk:\n\tfor rr := 0; rr <= r; rr++ {\n\t\tqq := rr\n\t\tfor pp = 0; pp < len(p); pp++ {\n\t\t\tif p[pp] != 0 {\n\t\t\t\tif p[pp] != amem[qq] && amem[qq] != 0 {\n\t\t\t\t\tcontinue nextk\n\t\t\t\t}\n\t\t\t}\n\t\t\tqq++\n\t\t}\n\n\t\t// we have found an acceptable k\n\t\tif pkdebug != 0 && foutput != nil {\n\t\t\tfmt.Fprintf(foutput, \"off = %v, k = %v\\n\", off+rr, rr)\n\t\t}\n\t\tqq = rr\n\t\tfor pp = 0; pp < len(p); pp++ {\n\t\t\tif p[pp] != 0 {\n\t\t\t\tif qq > memp {\n\t\t\t\t\tmemp = qq\n\t\t\t\t}\n\t\t\t\tamem[qq] = p[pp]\n\t\t\t}\n\t\t\tqq++\n\t\t}\n\t\tif pkdebug != 0 && foutput != nil {\n\t\t\tfor pp = 0; pp <= memp; pp += 10 {\n\t\t\t\tfmt.Fprintf(foutput, \"\\n\")\n\t\t\t\tfor qq = pp; qq <= pp+9; qq++ {\n\t\t\t\t\tfmt.Fprintf(foutput, \"%v \", amem[qq])\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(foutput, \"\\n\")\n\t\t\t}\n\t\t}\n\t\treturn off + rr\n\t}\n\terrorf(\"no space in action table\")\n\treturn 0\n}\n\n// print the output for the states\nfunc output() {\n\tvar c, u, v int\n\n\tif !lflag {\n\t\tfmt.Fprintf(ftable, \"\\n//line yacctab:1\")\n\t}\n\tvar actions []int\n\n\tif len(errors) > 0 {\n\t\tstateTable = make([]Row, nstate)\n\t}\n\n\tnoset := mkset()\n\n\t// output the stuff for state i\n\tfor i := 0; i < nstate; i++ {\n\t\tnolook = 0\n\t\tif tystate[i] != MUSTLOOKAHEAD {\n\t\t\tnolook = 1\n\t\t}\n\t\tclosure(i)\n\n\t\t// output actions\n\t\tnolook = 1\n\t\taryfil(temp1, ntokens+nnonter+1, 0)\n\t\tfor u = 0; u < cwp; u++ {\n\t\t\tc = wsets[u].pitem.first\n\t\t\tif c > 1 && c < NTBASE && temp1[c] == 0 {\n\t\t\t\tfor v = u; v < cwp; v++ {\n\t\t\t\t\tif c == wsets[v].pitem.first {\n\t\t\t\t\t\tputitem(wsets[v].pitem, noset)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttemp1[c] = state(c)\n\t\t\t} else if c > NTBASE {\n\t\t\t\tc -= NTBASE\n\t\t\t\tif temp1[c+ntokens] == 0 {\n\t\t\t\t\ttemp1[c+ntokens] = amem[indgo[i]+c]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif i == 1 {\n\t\t\ttemp1[1] = ACCEPTCODE\n\t\t}\n\n\t\t// now, we have the shifts; look at the reductions\n\t\tlastred = 0\n\t\tfor u = 0; u < cwp; u++ {\n\t\t\tc = wsets[u].pitem.first\n\n\t\t\t// reduction\n\t\t\tif c > 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlastred = -c\n\t\t\tus := wsets[u].ws\n\t\t\tfor k := 0; k <= ntokens; k++ {\n\t\t\t\tif bitset(us, k) == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif temp1[k] == 0 {\n\t\t\t\t\ttemp1[k] = c\n\t\t\t\t} else if temp1[k] < 0 { // reduce/reduce conflict\n\t\t\t\t\tif foutput != nil {\n\t\t\t\t\t\tfmt.Fprintf(foutput,\n\t\t\t\t\t\t\t\"\\n %v: reduce/reduce conflict  (red'ns \"+\n\t\t\t\t\t\t\t\t\"%v and %v) on %v\",\n\t\t\t\t\t\t\ti, -temp1[k], lastred, symnam(k))\n\t\t\t\t\t}\n\t\t\t\t\tif -temp1[k] > lastred {\n\t\t\t\t\t\ttemp1[k] = -lastred\n\t\t\t\t\t}\n\t\t\t\t\tzzrrconf++\n\t\t\t\t} else {\n\t\t\t\t\t// potential shift/reduce conflict\n\t\t\t\t\tprecftn(lastred, k, i)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tactions = addActions(actions, i)\n\t}\n\n\tarrayOutColumns(\"Exca\", actions, 2, false)\n\tfmt.Fprintf(ftable, \"\\n\")\n\tftable.WriteRune('\\n')\n\tfmt.Fprintf(ftable, \"const %sPrivate = %v\\n\", prefix, PRIVATE)\n}\n\n// decide a shift/reduce conflict by precedence.\n// r is a rule number, t a token number\n// the conflict is in state s\n// temp1[t] is changed to reflect the action\nfunc precftn(r, t, s int) {\n\taction := NOASC\n\n\tlp := levprd[r]\n\tlt := toklev[t]\n\tif PLEVEL(lt) == 0 || PLEVEL(lp) == 0 {\n\t\t// conflict\n\t\tif foutput != nil {\n\t\t\tfmt.Fprintf(foutput,\n\t\t\t\t\"\\n%v: shift/reduce conflict (shift %v(%v), red'n %v(%v)) on %v\",\n\t\t\t\ts, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t))\n\t\t}\n\t\tzzsrconf++\n\t\treturn\n\t}\n\tif PLEVEL(lt) == PLEVEL(lp) {\n\t\taction = ASSOC(lt)\n\t} else if PLEVEL(lt) > PLEVEL(lp) {\n\t\taction = RASC // shift\n\t} else {\n\t\taction = LASC\n\t} // reduce\n\tswitch action {\n\tcase BASC: // error action\n\t\ttemp1[t] = ERRCODE\n\tcase LASC: // reduce\n\t\ttemp1[t] = -r\n\t}\n}\n\n// output state i\n// temp1 has the actions, lastred the default\nfunc addActions(act []int, i int) []int {\n\tvar p, p1 int\n\n\t// find the best choice for lastred\n\tlastred = 0\n\tntimes := 0\n\tfor j := 0; j <= ntokens; j++ {\n\t\tif temp1[j] >= 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif temp1[j]+lastred == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// count the number of appearances of temp1[j]\n\t\tcount := 0\n\t\ttred := -temp1[j]\n\t\tlevprd[tred] |= REDFLAG\n\t\tfor p = 0; p <= ntokens; p++ {\n\t\t\tif temp1[p]+tred == 0 {\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t\tif count > ntimes {\n\t\t\tlastred = tred\n\t\t\tntimes = count\n\t\t}\n\t}\n\n\t//\n\t// for error recovery, arrange that, if there is a shift on the\n\t// error recovery token, `error', that the default be the error action\n\t//\n\tif temp1[2] > 0 {\n\t\tlastred = 0\n\t}\n\n\t// clear out entries in temp1 which equal lastred\n\t// count entries in optst table\n\tn := 0\n\tfor p = 0; p <= ntokens; p++ {\n\t\tp1 = temp1[p]\n\t\tif p1+lastred == 0 {\n\t\t\ttemp1[p] = 0\n\t\t\tp1 = 0\n\t\t}\n\t\tif p1 > 0 && p1 != ACCEPTCODE && p1 != ERRCODE {\n\t\t\tn++\n\t\t}\n\t}\n\n\twrstate(i)\n\tdefact[i] = lastred\n\tflag := 0\n\tos := make([]int, n*2)\n\tn = 0\n\tfor p = 0; p <= ntokens; p++ {\n\t\tp1 = temp1[p]\n\t\tif p1 != 0 {\n\t\t\tif p1 < 0 {\n\t\t\t\tp1 = -p1\n\t\t\t} else if p1 == ACCEPTCODE {\n\t\t\t\tp1 = -1\n\t\t\t} else if p1 == ERRCODE {\n\t\t\t\tp1 = 0\n\t\t\t} else {\n\t\t\t\tos[n] = p\n\t\t\t\tn++\n\t\t\t\tos[n] = p1\n\t\t\t\tn++\n\t\t\t\tzzacent++\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif flag == 0 {\n\t\t\t\tact = append(act, -1, i)\n\t\t\t}\n\t\t\tflag++\n\t\t\tact = append(act, p, p1)\n\t\t\tzzexcp++\n\t\t}\n\t}\n\tif flag != 0 {\n\t\tdefact[i] = -2\n\t\tact = append(act, -2, lastred)\n\t}\n\toptst[i] = os\n\treturn act\n}\n\n// writes state i\nfunc wrstate(i int) {\n\tvar j0, j1, u int\n\tvar pp, qq int\n\n\tif len(errors) > 0 {\n\t\tactions := slices.Clone(temp1)\n\t\tdefaultAction := ERRCODE\n\t\tif lastred != 0 {\n\t\t\tdefaultAction = -lastred\n\t\t}\n\t\tstateTable[i] = Row{actions, defaultAction}\n\t}\n\n\tif foutput == nil {\n\t\treturn\n\t}\n\tfmt.Fprintf(foutput, \"\\nstate %v\\n\", i)\n\tqq = pstate[i+1]\n\tfor pp = pstate[i]; pp < qq; pp++ {\n\t\tfmt.Fprintf(foutput, \"\\t%v\\n\", writem(statemem[pp].pitem))\n\t}\n\tif tystate[i] == MUSTLOOKAHEAD {\n\t\t// print out empty productions in closure\n\t\tfor u = pstate[i+1] - pstate[i]; u < cwp; u++ {\n\t\t\tif wsets[u].pitem.first < 0 {\n\t\t\t\tfmt.Fprintf(foutput, \"\\t%v\\n\", writem(wsets[u].pitem))\n\t\t\t}\n\t\t}\n\t}\n\n\t// check for state equal to another\n\tfor j0 = 0; j0 <= ntokens; j0++ {\n\t\tj1 = temp1[j0]\n\t\tif j1 != 0 {\n\t\t\tfmt.Fprintf(foutput, \"\\n\\t%v  \", symnam(j0))\n\n\t\t\t// shift, error, or accept\n\t\t\tif j1 > 0 {\n\t\t\t\tif j1 == ACCEPTCODE {\n\t\t\t\t\tfmt.Fprintf(foutput, \"accept\")\n\t\t\t\t} else if j1 == ERRCODE {\n\t\t\t\t\tfmt.Fprintf(foutput, \"error\")\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Fprintf(foutput, \"shift %v\", j1)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(foutput, \"reduce %v (src line %v)\", -j1, rlines[-j1])\n\t\t\t}\n\t\t}\n\t}\n\n\t// output the final production\n\tif lastred != 0 {\n\t\tfmt.Fprintf(foutput, \"\\n\\t.  reduce %v (src line %v)\\n\\n\",\n\t\t\tlastred, rlines[lastred])\n\t} else {\n\t\tfmt.Fprintf(foutput, \"\\n\\t.  error\\n\\n\")\n\t}\n\n\t// now, output nonterminal actions\n\tj1 = ntokens\n\tfor j0 = 1; j0 <= nnonter; j0++ {\n\t\tj1++\n\t\tif temp1[j1] != 0 {\n\t\t\tfmt.Fprintf(foutput, \"\\t%v  goto %v\\n\", symnam(j0+NTBASE), temp1[j1])\n\t\t}\n\t}\n}\n\n// output the gotos for the nontermninals\nfunc go2out() {\n\tfor i := 1; i <= nnonter; i++ {\n\t\tgo2gen(i)\n\n\t\t// find the best one to make default\n\t\tbest := -1\n\t\ttimes := 0\n\n\t\t// is j the most frequent\n\t\tfor j := 0; j < nstate; j++ {\n\t\t\tif tystate[j] == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif tystate[j] == best {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// is tystate[j] the most frequent\n\t\t\tcount := 0\n\t\t\tcbest := tystate[j]\n\t\t\tfor k := j; k < nstate; k++ {\n\t\t\t\tif tystate[k] == cbest {\n\t\t\t\t\tcount++\n\t\t\t\t}\n\t\t\t}\n\t\t\tif count > times {\n\t\t\t\tbest = cbest\n\t\t\t\ttimes = count\n\t\t\t}\n\t\t}\n\n\t\t// best is now the default entry\n\t\tzzgobest += times - 1\n\t\tn := 0\n\t\tfor j := 0; j < nstate; j++ {\n\t\t\tif tystate[j] != 0 && tystate[j] != best {\n\t\t\t\tn++\n\t\t\t}\n\t\t}\n\t\tgoent := make([]int, 2*n+1)\n\t\tn = 0\n\t\tfor j := 0; j < nstate; j++ {\n\t\t\tif tystate[j] != 0 && tystate[j] != best {\n\t\t\t\tgoent[n] = j\n\t\t\t\tn++\n\t\t\t\tgoent[n] = tystate[j]\n\t\t\t\tn++\n\t\t\t\tzzgoent++\n\t\t\t}\n\t\t}\n\n\t\t// now, the default\n\t\tif best == -1 {\n\t\t\tbest = 0\n\t\t}\n\n\t\tzzgoent++\n\t\tgoent[n] = best\n\t\tyypgo[i] = goent\n\t}\n}\n\n// output the gotos for nonterminal c\nfunc go2gen(c int) {\n\tvar i, cc, p, q int\n\n\t// first, find nonterminals with gotos on c\n\taryfil(temp1, nnonter+1, 0)\n\ttemp1[c] = 1\n\twork := 1\n\tfor work != 0 {\n\t\twork = 0\n\t\tfor i = 0; i < nprod; i++ {\n\t\t\t// cc is a nonterminal with a goto on c\n\t\t\tcc = prdptr[i][1] - NTBASE\n\t\t\tif cc >= 0 && temp1[cc] != 0 {\n\t\t\t\t// thus, the left side of production i does too\n\t\t\t\tcc = prdptr[i][0] - NTBASE\n\t\t\t\tif temp1[cc] == 0 {\n\t\t\t\t\twork = 1\n\t\t\t\t\ttemp1[cc] = 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// now, we have temp1[c] = 1 if a goto on c in closure of cc\n\tif g2debug != 0 && foutput != nil {\n\t\tfmt.Fprintf(foutput, \"%v: gotos on \", nontrst[c].name)\n\t\tfor i = 0; i <= nnonter; i++ {\n\t\t\tif temp1[i] != 0 {\n\t\t\t\tfmt.Fprintf(foutput, \"%v \", nontrst[i].name)\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(foutput, \"\\n\")\n\t}\n\n\t// now, go through and put gotos into tystate\n\taryfil(tystate, nstate, 0)\n\tfor i = 0; i < nstate; i++ {\n\t\tq = pstate[i+1]\n\t\tfor p = pstate[i]; p < q; p++ {\n\t\t\tcc = statemem[p].pitem.first\n\t\t\tif cc >= NTBASE {\n\t\t\t\t// goto on c is possible\n\t\t\t\tif temp1[cc-NTBASE] != 0 {\n\t\t\t\t\ttystate[i] = amem[indgo[i]+c]\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// in order to free up the mem and amem arrays for the optimizer,\n// and still be able to output yyr1, etc., after the sizes of\n// the action array is known, we hide the nonterminals\n// derived by productions in levprd.\nfunc hideprod() {\n\tnred := 0\n\tlevprd[0] = 0\n\tfor i := 1; i < nprod; i++ {\n\t\tif (levprd[i] & REDFLAG) == 0 {\n\t\t\tif foutput != nil {\n\t\t\t\tfmt.Fprintf(foutput, \"Rule not reduced: %v\\n\",\n\t\t\t\t\twritem(Pitem{prdptr[i], 0, 0, i}))\n\t\t\t}\n\t\t\tfmt.Printf(\"rule %v never reduced\\n\", writem(Pitem{prdptr[i], 0, 0, i}))\n\t\t\tnred++\n\t\t}\n\t\tlevprd[i] = prdptr[i][0] - NTBASE\n\t}\n\tif nred != 0 {\n\t\tfmt.Printf(\"%v rules never reduced\\n\", nred)\n\t}\n}\n\nfunc callopt() {\n\tvar j, k, p, q, i int\n\tvar v []int\n\n\tpgo = make([]int, nnonter+1)\n\tpgo[0] = 0\n\tmaxoff = 0\n\tmaxspr = 0\n\tfor i = 0; i < nstate; i++ {\n\t\tk = 32000\n\t\tj = 0\n\t\tv = optst[i]\n\t\tq = len(v)\n\t\tfor p = 0; p < q; p += 2 {\n\t\t\tif v[p] > j {\n\t\t\t\tj = v[p]\n\t\t\t}\n\t\t\tif v[p] < k {\n\t\t\t\tk = v[p]\n\t\t\t}\n\t\t}\n\n\t\t// nontrivial situation\n\t\tif k <= j {\n\t\t\t// j is now the range\n\t\t\t//\t\t\tj -= k;\t\t\t// call scj\n\t\t\tif k > maxoff {\n\t\t\t\tmaxoff = k\n\t\t\t}\n\t\t}\n\t\ttystate[i] = q + 2*j\n\t\tif j > maxspr {\n\t\t\tmaxspr = j\n\t\t}\n\t}\n\n\t// initialize ggreed table\n\tggreed = make([]int, nnonter+1)\n\tfor i = 1; i <= nnonter; i++ {\n\t\tggreed[i] = 1\n\t\tj = 0\n\n\t\t// minimum entry index is always 0\n\t\tv = yypgo[i]\n\t\tq = len(v) - 1\n\t\tfor p = 0; p < q; p += 2 {\n\t\t\tggreed[i] += 2\n\t\t\tif v[p] > j {\n\t\t\t\tj = v[p]\n\t\t\t}\n\t\t}\n\t\tggreed[i] = ggreed[i] + 2*j\n\t\tif j > maxoff {\n\t\t\tmaxoff = j\n\t\t}\n\t}\n\n\t// now, prepare to put the shift actions into the amem array\n\tfor i = 0; i < ACTSIZE; i++ {\n\t\tamem[i] = 0\n\t}\n\tmaxa = 0\n\tfor i = 0; i < nstate; i++ {\n\t\tif tystate[i] == 0 && adb > 1 {\n\t\t\tfmt.Fprintf(ftable, \"State %v: null\\n\", i)\n\t\t}\n\t\tindgo[i] = yyFlag\n\t}\n\n\ti = nxti()\n\tfor i != NOMORE {\n\t\tif i >= 0 {\n\t\t\tstin(i)\n\t\t} else {\n\t\t\tgin(-i)\n\t\t}\n\t\ti = nxti()\n\t}\n\n\t// print amem array\n\tif adb > 2 {\n\t\tfor p = 0; p <= maxa; p += 10 {\n\t\t\tfmt.Fprintf(ftable, \"%v  \", p)\n\t\t\tfor i = range 10 {\n\t\t\t\tfmt.Fprintf(ftable, \"%v  \", amem[p+i])\n\t\t\t}\n\t\t\tftable.WriteRune('\\n')\n\t\t}\n\t}\n\n\taoutput()\n\tosummary()\n}\n\n// finds the next i\nfunc nxti() int {\n\tmax := 0\n\tmaxi := 0\n\tfor i := 1; i <= nnonter; i++ {\n\t\tif ggreed[i] >= max {\n\t\t\tmax = ggreed[i]\n\t\t\tmaxi = -i\n\t\t}\n\t}\n\tfor i := 0; i < nstate; i++ {\n\t\tif tystate[i] >= max {\n\t\t\tmax = tystate[i]\n\t\t\tmaxi = i\n\t\t}\n\t}\n\tif max == 0 {\n\t\treturn NOMORE\n\t}\n\treturn maxi\n}\n\nfunc gin(i int) {\n\tvar s int\n\n\t// enter gotos on nonterminal i into array amem\n\tggreed[i] = 0\n\n\tq := yypgo[i]\n\tnq := len(q) - 1\n\n\t// now, find amem place for it\nnextgp:\n\tfor p := range ACTSIZE {\n\t\tif amem[p] != 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor r := 0; r < nq; r += 2 {\n\t\t\ts = p + q[r] + 1\n\t\t\tif s > maxa {\n\t\t\t\tmaxa = s\n\t\t\t\tif maxa >= ACTSIZE {\n\t\t\t\t\terrorf(\"a array overflow\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tif amem[s] != 0 {\n\t\t\t\tcontinue nextgp\n\t\t\t}\n\t\t}\n\n\t\t// we have found amem spot\n\t\tamem[p] = q[nq]\n\t\tif p > maxa {\n\t\t\tmaxa = p\n\t\t}\n\t\tfor r := 0; r < nq; r += 2 {\n\t\t\ts = p + q[r] + 1\n\t\t\tamem[s] = q[r+1]\n\t\t}\n\t\tpgo[i] = p\n\t\tif adb > 1 {\n\t\t\tfmt.Fprintf(ftable, \"Nonterminal %v, entry at %v\\n\", i, pgo[i])\n\t\t}\n\t\treturn\n\t}\n\terrorf(\"cannot place goto %v\\n\", i)\n}\n\nfunc stin(i int) {\n\tvar s int\n\n\ttystate[i] = 0\n\n\t// enter state i into the amem array\n\tq := optst[i]\n\tnq := len(q)\n\nnextn:\n\t// find an acceptable place\n\tfor n := -maxoff; n < ACTSIZE; n++ {\n\t\tflag := 0\n\t\tfor r := 0; r < nq; r += 2 {\n\t\t\ts = q[r] + n\n\t\t\tif s < 0 || s > ACTSIZE {\n\t\t\t\tcontinue nextn\n\t\t\t}\n\t\t\tif amem[s] == 0 {\n\t\t\t\tflag++\n\t\t\t} else if amem[s] != q[r+1] {\n\t\t\t\tcontinue nextn\n\t\t\t}\n\t\t}\n\n\t\t// check the position equals another only if the states are identical\n\t\tfor j := 0; j < nstate; j++ {\n\t\t\tif indgo[j] == n {\n\n\t\t\t\t// we have some disagreement\n\t\t\t\tif flag != 0 {\n\t\t\t\t\tcontinue nextn\n\t\t\t\t}\n\t\t\t\tif nq == len(optst[j]) {\n\n\t\t\t\t\t// states are equal\n\t\t\t\t\tindgo[i] = n\n\t\t\t\t\tif adb > 1 {\n\t\t\t\t\t\tfmt.Fprintf(ftable, \"State %v: entry at\"+\n\t\t\t\t\t\t\t\"%v equals state %v\\n\",\n\t\t\t\t\t\t\ti, n, j)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// we have some disagreement\n\t\t\t\tcontinue nextn\n\t\t\t}\n\t\t}\n\n\t\tfor r := 0; r < nq; r += 2 {\n\t\t\ts = q[r] + n\n\t\t\tif s > maxa {\n\t\t\t\tmaxa = s\n\t\t\t}\n\t\t\tif amem[s] != 0 && amem[s] != q[r+1] {\n\t\t\t\terrorf(\"clobber of a array, pos'n %v, by %v\", s, q[r+1])\n\t\t\t}\n\t\t\tamem[s] = q[r+1]\n\t\t}\n\t\tindgo[i] = n\n\t\tif adb > 1 {\n\t\t\tfmt.Fprintf(ftable, \"State %v: entry at %v\\n\", i, indgo[i])\n\t\t}\n\t\treturn\n\t}\n\terrorf(\"Error; failure to place state %v\", i)\n}\n\n// this version is for limbo\n// write out the optimized parser\nfunc aoutput() {\n\tftable.WriteRune('\\n')\n\tfmt.Fprintf(ftable, \"const %sLast = %v\\n\", prefix, maxa+1)\n\tarout(\"Act\", amem, maxa+1)\n\tarout(\"Pact\", indgo, nstate)\n\tarout(\"Pgo\", pgo, nnonter+1)\n}\n\n// put out other arrays, copy the parsers\nfunc others() {\n\tvar i, j int\n\n\tarout(\"R1\", levprd, nprod)\n\taryfil(temp1, nprod, 0)\n\n\t//\n\t//yyr2 is the number of rules for each production\n\t//\n\tfor i = 1; i < nprod; i++ {\n\t\ttemp1[i] = len(prdptr[i]) - 2\n\t}\n\tarout(\"R2\", temp1, nprod)\n\n\taryfil(temp1, nstate, -1000)\n\tfor i = 0; i <= ntokens; i++ {\n\t\tfor j := tstates[i]; j != 0; j = mstates[j] {\n\t\t\ttemp1[j] = i\n\t\t}\n\t}\n\tfor i = 0; i <= nnonter; i++ {\n\t\tfor j = ntstates[i]; j != 0; j = mstates[j] {\n\t\t\ttemp1[j] = -i\n\t\t}\n\t}\n\tarout(\"Chk\", temp1, nstate)\n\tarrayOutColumns(\"Def\", defact[:nstate], 10, false)\n\n\t// put out token translation tables\n\t// table 1 has 0-256\n\taryfil(temp1, 256, 0)\n\tc := 0\n\tfor i = 1; i <= ntokens; i++ {\n\t\tj = tokset[i].value\n\t\tif j >= 0 && j < 256 {\n\t\t\tif temp1[j] != 0 {\n\t\t\t\tfmt.Print(\"yacc bug -- cannot have 2 different Ts with same value\\n\")\n\t\t\t\tfmt.Printf(\"\t%s and %s\\n\", tokset[i].name, tokset[temp1[j]].name)\n\t\t\t\tnerrors++\n\t\t\t}\n\t\t\ttemp1[j] = i\n\t\t\tif j > c {\n\t\t\t\tc = j\n\t\t\t}\n\t\t}\n\t}\n\tfor i = 0; i <= c; i++ {\n\t\tif temp1[i] == 0 {\n\t\t\ttemp1[i] = YYLEXUNK\n\t\t}\n\t}\n\tarout(\"Tok1\", temp1, c+1)\n\n\t// table 2 has PRIVATE-PRIVATE+256\n\taryfil(temp1, 256, 0)\n\tc = 0\n\tfor i = 1; i <= ntokens; i++ {\n\t\tj = tokset[i].value - PRIVATE\n\t\tif j >= 0 && j < 256 {\n\t\t\tif temp1[j] != 0 {\n\t\t\t\tfmt.Print(\"yacc bug -- cannot have 2 different Ts with same value\\n\")\n\t\t\t\tfmt.Printf(\"\t%s and %s\\n\", tokset[i].name, tokset[temp1[j]].name)\n\t\t\t\tnerrors++\n\t\t\t}\n\t\t\ttemp1[j] = i\n\t\t\tif j > c {\n\t\t\t\tc = j\n\t\t\t}\n\t\t}\n\t}\n\tarout(\"Tok2\", temp1, c+1)\n\n\t// table 3 has everything else\n\tftable.WriteRune('\\n')\n\tvar v []int\n\tfor i = 1; i <= ntokens; i++ {\n\t\tj = tokset[i].value\n\t\tif j >= 0 && j < 256 {\n\t\t\tcontinue\n\t\t}\n\t\tif j >= PRIVATE && j < 256+PRIVATE {\n\t\t\tcontinue\n\t\t}\n\n\t\tv = append(v, j, i)\n\t}\n\tv = append(v, 0)\n\tarout(\"Tok3\", v, len(v))\n\tfmt.Fprintf(ftable, \"\\n\")\n\n\t// Custom error messages.\n\tfmt.Fprintf(ftable, \"\\n\")\n\tfmt.Fprintf(ftable, \"var %sErrorMessages = [...]struct {\\n\", prefix)\n\tfmt.Fprintf(ftable, \"\\tstate int\\n\")\n\tfmt.Fprintf(ftable, \"\\ttoken int\\n\")\n\tfmt.Fprintf(ftable, \"\\tmsg   string\\n\")\n\tfmt.Fprintf(ftable, \"}{\\n\")\n\tfor _, error := range errors {\n\t\tlineno = error.lineno\n\t\tstate, token := runMachine(error.tokens)\n\t\tfmt.Fprintf(ftable, \"\\t{%v, %v, %s},\\n\", state, token, error.msg)\n\t}\n\tfmt.Fprintf(ftable, \"}\\n\")\n\n\t// copy parser text\n\tch := getrune(finput)\n\tfor ch != EOF {\n\t\tftable.WriteRune(ch)\n\t\tch = getrune(finput)\n\t}\n\n\t// copy yaccpar\n\tif !lflag {\n\t\tfmt.Fprintf(ftable, \"\\n//line yaccpar:1\\n\")\n\t}\n\n\tparts := strings.SplitN(yaccpar, prefix+\"run()\", 2)\n\tfmt.Fprintf(ftable, \"%v\", parts[0])\n\tftable.Write(fcode.Bytes())\n\tfmt.Fprintf(ftable, \"%v\", parts[1])\n}\n\nfunc runMachine(tokens []string) (state, token int) {\n\tvar stack []int\n\ti := 0\n\ttoken = -1\n\nLoop:\n\tif token < 0 {\n\t\ttoken = chfind(2, tokens[i])\n\t\ti++\n\t}\n\n\trow := stateTable[state]\n\n\tc := token\n\tif token >= NTBASE {\n\t\tc = token - NTBASE + ntokens\n\t}\n\taction := row.actions[c]\n\tif action == 0 {\n\t\taction = row.defaultAction\n\t}\n\n\tswitch {\n\tcase action == ACCEPTCODE:\n\t\terrorf(\"tokens are accepted\")\n\t\treturn\n\tcase action == ERRCODE:\n\t\tif token >= NTBASE {\n\t\t\terrorf(\"error at non-terminal token %s\", symnam(token))\n\t\t}\n\t\treturn\n\tcase action > 0:\n\t\t// Shift to state action.\n\t\tstack = append(stack, state)\n\t\tstate = action\n\t\ttoken = -1\n\t\tgoto Loop\n\tdefault:\n\t\t// Reduce by production -action.\n\t\tprod := prdptr[-action]\n\t\tif rhsLen := len(prod) - 2; rhsLen > 0 {\n\t\t\tn := len(stack) - rhsLen\n\t\t\tstate = stack[n]\n\t\t\tstack = stack[:n]\n\t\t}\n\t\tif token >= 0 {\n\t\t\ti--\n\t\t}\n\t\ttoken = prod[0]\n\t\tgoto Loop\n\t}\n}\n\nfunc minMax(v []int) (min, max int) {\n\tif len(v) == 0 {\n\t\treturn\n\t}\n\tmin = v[0]\n\tmax = v[0]\n\tfor _, i := range v {\n\t\tif i < min {\n\t\t\tmin = i\n\t\t}\n\t\tif i > max {\n\t\t\tmax = i\n\t\t}\n\t}\n\treturn\n}\n\n// return the smaller integral base type to store the values in v\nfunc minType(v []int, allowUnsigned bool) (typ string) {\n\ttyp = \"int\"\n\ttypeLen := 8\n\tmin, max := minMax(v)\n\tcheckType := func(name string, size, minType, maxType int) {\n\t\tif min >= minType && max <= maxType && typeLen > size {\n\t\t\ttyp = name\n\t\t\ttypeLen = size\n\t\t}\n\t}\n\tcheckType(\"int32\", 4, math.MinInt32, math.MaxInt32)\n\tcheckType(\"int16\", 2, math.MinInt16, math.MaxInt16)\n\tcheckType(\"int8\", 1, math.MinInt8, math.MaxInt8)\n\tif allowUnsigned {\n\t\t// Do not check for uint32, not worth and won't compile on 32 bit systems\n\t\tcheckType(\"uint16\", 2, 0, math.MaxUint16)\n\t\tcheckType(\"uint8\", 1, 0, math.MaxUint8)\n\t}\n\treturn\n}\n\nfunc arrayOutColumns(s string, v []int, columns int, allowUnsigned bool) {\n\ts = prefix + s\n\tftable.WriteRune('\\n')\n\tminType := minType(v, allowUnsigned)\n\tfmt.Fprintf(ftable, \"var %v = [...]%s{\", s, minType)\n\tfor i, val := range v {\n\t\tif i%columns == 0 {\n\t\t\tfmt.Fprintf(ftable, \"\\n\\t\")\n\t\t} else {\n\t\t\tftable.WriteRune(' ')\n\t\t}\n\t\tfmt.Fprintf(ftable, \"%d,\", val)\n\t}\n\tfmt.Fprintf(ftable, \"\\n}\\n\")\n}\n\nfunc arout(s string, v []int, n int) {\n\tarrayOutColumns(s, v[:n], 10, true)\n}\n\n// output the summary on y.output\nfunc summary() {\n\tif foutput != nil {\n\t\tfmt.Fprintf(foutput, \"\\n%v terminals, %v nonterminals\\n\", ntokens, nnonter+1)\n\t\tfmt.Fprintf(foutput, \"%v grammar rules, %v/%v states\\n\", nprod, nstate, NSTATES)\n\t\tfmt.Fprintf(foutput, \"%v shift/reduce, %v reduce/reduce conflicts reported\\n\", zzsrconf, zzrrconf)\n\t\tfmt.Fprintf(foutput, \"%v working sets used\\n\", len(wsets))\n\t\tfmt.Fprintf(foutput, \"memory: parser %v/%v\\n\", memp, ACTSIZE)\n\t\tfmt.Fprintf(foutput, \"%v extra closures\\n\", zzclose-2*nstate)\n\t\tfmt.Fprintf(foutput, \"%v shift entries, %v exceptions\\n\", zzacent, zzexcp)\n\t\tfmt.Fprintf(foutput, \"%v goto entries\\n\", zzgoent)\n\t\tfmt.Fprintf(foutput, \"%v entries saved by goto default\\n\", zzgobest)\n\t}\n\tif zzsrconf != 0 || zzrrconf != 0 {\n\t\tfmt.Printf(\"\\nconflicts: \")\n\t\tif zzsrconf != 0 {\n\t\t\tfmt.Printf(\"%v shift/reduce\", zzsrconf)\n\t\t}\n\t\tif zzsrconf != 0 && zzrrconf != 0 {\n\t\t\tfmt.Printf(\", \")\n\t\t}\n\t\tif zzrrconf != 0 {\n\t\t\tfmt.Printf(\"%v reduce/reduce\", zzrrconf)\n\t\t}\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\n\n// write optimizer summary\nfunc osummary() {\n\tif foutput == nil {\n\t\treturn\n\t}\n\ti := 0\n\tfor p := maxa; p >= 0; p-- {\n\t\tif amem[p] == 0 {\n\t\t\ti++\n\t\t}\n\t}\n\n\tfmt.Fprintf(foutput, \"Optimizer space used: output %v/%v\\n\", maxa+1, ACTSIZE)\n\tfmt.Fprintf(foutput, \"%v table entries, %v zero\\n\", maxa+1, i)\n\tfmt.Fprintf(foutput, \"maximum spread: %v, maximum offset: %v\\n\", maxspr, maxoff)\n}\n\n// copies and protects \"'s in q\nfunc chcopy(q string) string {\n\tvar s strings.Builder\n\ti := 0\n\tj := 0\n\tfor i = 0; i < len(q); i++ {\n\t\tif q[i] == '\"' {\n\t\t\ts.WriteString(q[j:i])\n\t\t\ts.WriteByte('\\\\')\n\t\t\tj = i\n\t\t}\n\t}\n\ts.WriteString(q[j:i])\n\treturn s.String()\n}\n\nfunc usage() {\n\tfmt.Fprintf(stderr, \"usage: yacc [-o output] [-v parsetable] input\\n\")\n\texit(1)\n}\n\nfunc bitset(set Lkset, bit int) int { return set[bit>>5] & (1 << uint(bit&31)) }\n\nfunc setbit(set Lkset, bit int) { set[bit>>5] |= (1 << uint(bit&31)) }\n\nfunc mkset() Lkset { return make([]int, tbitset) }\n\n// set a to the union of a and b\n// return 1 if b is not a subset of a, 0 otherwise\nfunc setunion(a, b []int) int {\n\tsub := 0\n\tfor i := 0; i < tbitset; i++ {\n\t\tx := a[i]\n\t\ty := x | b[i]\n\t\ta[i] = y\n\t\tif y != x {\n\t\t\tsub = 1\n\t\t}\n\t}\n\treturn sub\n}\n\nfunc prlook(p Lkset) {\n\tif p == nil {\n\t\tfmt.Fprintf(foutput, \"\\tNULL\")\n\t\treturn\n\t}\n\tfmt.Fprintf(foutput, \" { \")\n\tfor j := 0; j <= ntokens; j++ {\n\t\tif bitset(p, j) != 0 {\n\t\t\tfmt.Fprintf(foutput, \"%v \", symnam(j))\n\t\t}\n\t}\n\tfmt.Fprintf(foutput, \"}\")\n}\n\n// utility routines\nvar peekrune rune\n\nfunc isdigit(c rune) bool { return c >= '0' && c <= '9' }\n\nfunc isword(c rune) bool {\n\treturn c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')\n}\n\n// return 1 if 2 arrays are equal\n// return 0 if not equal\nfunc aryeq(a []int, b []int) int {\n\tn := len(a)\n\tif len(b) != n {\n\t\treturn 0\n\t}\n\tfor ll := range n {\n\t\tif a[ll] != b[ll] {\n\t\t\treturn 0\n\t\t}\n\t}\n\treturn 1\n}\n\nfunc getrune(f *bufio.Reader) rune {\n\tvar r rune\n\n\tif peekrune != 0 {\n\t\tif peekrune == EOF {\n\t\t\treturn EOF\n\t\t}\n\t\tr = peekrune\n\t\tpeekrune = 0\n\t\treturn r\n\t}\n\n\tc, n, err := f.ReadRune()\n\tif n == 0 {\n\t\treturn EOF\n\t}\n\tif err != nil {\n\t\terrorf(\"read error: %v\", err)\n\t}\n\t//fmt.Printf(\"rune = %v n=%v\\n\", string(c), n);\n\treturn c\n}\n\nfunc ungetrune(f *bufio.Reader, c rune) {\n\tif f != finput {\n\t\tpanic(\"ungetc - not finput\")\n\t}\n\tif peekrune != 0 {\n\t\tpanic(\"ungetc - 2nd unget\")\n\t}\n\tpeekrune = c\n}\n\nfunc open(s string) *bufio.Reader {\n\tfi, err := os.Open(s)\n\tif err != nil {\n\t\terrorf(\"error opening %v: %v\", s, err)\n\t}\n\t//fmt.Printf(\"open %v\\n\", s);\n\treturn bufio.NewReader(fi)\n}\n\nfunc create(s string) *bufio.Writer {\n\tfo, err := os.Create(s)\n\tif err != nil {\n\t\terrorf(\"error creating %v: %v\", s, err)\n\t}\n\t//fmt.Printf(\"create %v mode %v\\n\", s);\n\treturn bufio.NewWriter(fo)\n}\n\n// write out error comment\nfunc lerrorf(lineno int, s string, v ...any) {\n\tnerrors++\n\tfmt.Fprintf(stderr, s, v...)\n\tfmt.Fprintf(stderr, \": %v:%v\\n\", infile, lineno)\n\tif fatfl != 0 {\n\t\tsummary()\n\t\texit(1)\n\t}\n}\n\nfunc errorf(s string, v ...any) {\n\tlerrorf(lineno, s, v...)\n}\n\nfunc exit(status int) {\n\tif ftable != nil {\n\t\tftable.Flush()\n\t\tftable = nil\n\t\tgofmt()\n\t}\n\tif foutput != nil {\n\t\tfoutput.Flush()\n\t\tfoutput = nil\n\t}\n\tif stderr != nil {\n\t\tstderr.Flush()\n\t\tstderr = nil\n\t}\n\tos.Exit(status)\n}\n\nfunc gofmt() {\n\tsrc, err := os.ReadFile(oflag)\n\tif err != nil {\n\t\treturn\n\t}\n\tsrc, err = format.Source(src)\n\tif err != nil {\n\t\treturn\n\t}\n\tos.WriteFile(oflag, src, 0666)\n}\n\nvar yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g\nvar yaccpartext = `\n/*\tparser for yacc output\t*/\n\nvar (\n\t$$Debug        = 0\n\t$$ErrorVerbose = false\n)\n\ntype $$Lexer interface {\n\tLex(lval *$$SymType) int\n\tError(s string)\n}\n\ntype $$Parser interface {\n\tParse($$Lexer) int\n\tLookahead() int\n}\n\ntype $$ParserImpl struct {\n\tlval  $$SymType\n\tstack [$$InitialStackSize]$$SymType\n\tchar  int\n}\n\nfunc (p *$$ParserImpl) Lookahead() int {\n\treturn p.char\n}\n\nfunc $$NewParser() $$Parser {\n\treturn &$$ParserImpl{}\n}\n\nconst $$Flag = -1000\n\nfunc $$Tokname(c int) string {\n\tif c >= 1 && c-1 < len($$Toknames) {\n\t\tif $$Toknames[c-1] != \"\" {\n\t\t\treturn $$Toknames[c-1]\n\t\t}\n\t}\n\treturn __yyfmt__.Sprintf(\"tok-%v\", c)\n}\n\nfunc $$Statname(s int) string {\n\tif s >= 0 && s < len($$Statenames) {\n\t\tif $$Statenames[s] != \"\" {\n\t\t\treturn $$Statenames[s]\n\t\t}\n\t}\n\treturn __yyfmt__.Sprintf(\"state-%v\", s)\n}\n\nfunc $$ErrorMessage(state, lookAhead int) string {\n\tconst TOKSTART = 4\n\n\tif !$$ErrorVerbose {\n\t\treturn \"syntax error\"\n\t}\n\n\tfor _, e := range $$ErrorMessages {\n\t\tif e.state == state && e.token == lookAhead {\n\t\t\treturn \"syntax error: \" + e.msg\n\t\t}\n\t}\n\n\tres := \"syntax error: unexpected \" + $$Tokname(lookAhead)\n\n\t// To match Bison, suggest at most four expected tokens.\n\texpected := make([]int, 0, 4)\n\n\t// Look for shiftable tokens.\n\tbase := int($$Pact[state])\n\tfor tok := TOKSTART; tok-1 < len($$Toknames); tok++ {\n\t\tif n := base + tok; n >= 0 && n < $$Last && int($$Chk[int($$Act[n])]) == tok {\n\t\t\tif len(expected) == cap(expected) {\n\t\t\t\treturn res\n\t\t\t}\n\t\t\texpected = append(expected, tok)\n\t\t}\n\t}\n\n\tif $$Def[state] == -2 {\n\t\ti := 0\n\t\tfor $$Exca[i] != -1 || int($$Exca[i+1]) != state {\n\t\t\ti += 2\n\t\t}\n\n\t\t// Look for tokens that we accept or reduce.\n\t\tfor i += 2; $$Exca[i] >= 0; i += 2 {\n\t\t\ttok := int($$Exca[i])\n\t\t\tif tok < TOKSTART || $$Exca[i+1] == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(expected) == cap(expected) {\n\t\t\t\treturn res\n\t\t\t}\n\t\t\texpected = append(expected, tok)\n\t\t}\n\n\t\t// If the default action is to accept or reduce, give up.\n\t\tif $$Exca[i+1] != 0 {\n\t\t\treturn res\n\t\t}\n\t}\n\n\tfor i, tok := range expected {\n\t\tif i == 0 {\n\t\t\tres += \", expecting \"\n\t\t} else {\n\t\t\tres += \" or \"\n\t\t}\n\t\tres += $$Tokname(tok)\n\t}\n\treturn res\n}\n\nfunc $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) {\n\ttoken = 0\n\tchar = lex.Lex(lval)\n\tif char <= 0 {\n\t\ttoken = int($$Tok1[0])\n\t\tgoto out\n\t}\n\tif char < len($$Tok1) {\n\t\ttoken = int($$Tok1[char])\n\t\tgoto out\n\t}\n\tif char >= $$Private {\n\t\tif char < $$Private+len($$Tok2) {\n\t\t\ttoken = int($$Tok2[char-$$Private])\n\t\t\tgoto out\n\t\t}\n\t}\n\tfor i := 0; i < len($$Tok3); i += 2 {\n\t\ttoken = int($$Tok3[i+0])\n\t\tif token == char {\n\t\t\ttoken = int($$Tok3[i+1])\n\t\t\tgoto out\n\t\t}\n\t}\n\nout:\n\tif token == 0 {\n\t\ttoken = int($$Tok2[1]) /* unknown char */\n\t}\n\tif $$Debug >= 3 {\n\t\t__yyfmt__.Printf(\"lex %s(%d)\\n\", $$Tokname(token), uint(char))\n\t}\n\treturn char, token\n}\n\nfunc $$Parse($$lex $$Lexer) int {\n\treturn $$NewParser().Parse($$lex)\n}\n\nfunc ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {\n\tvar $$n int\n\tvar $$VAL $$SymType\n\tvar $$Dollar []$$SymType\n\t_ = $$Dollar // silence set and not used\n\t$$S := $$rcvr.stack[:]\n\n\tNerrs := 0   /* number of errors */\n\tErrflag := 0 /* error recovery flag */\n\t$$state := 0\n\t$$rcvr.char = -1\n\t$$token := -1 // $$rcvr.char translated into internal numbering\n\tdefer func() {\n\t\t// Make sure we report no lookahead when not parsing.\n\t\t$$state = -1\n\t\t$$rcvr.char = -1\n\t\t$$token = -1\n\t}()\n\t$$p := -1\n\tgoto $$stack\n\nret0:\n\treturn 0\n\nret1:\n\treturn 1\n\n$$stack:\n\t/* put a state and value onto the stack */\n\tif $$Debug >= 4 {\n\t\t__yyfmt__.Printf(\"char %v in %v\\n\", $$Tokname($$token), $$Statname($$state))\n\t}\n\n\t$$p++\n\tif $$p >= len($$S) {\n\t\tnyys := make([]$$SymType, len($$S)*2)\n\t\tcopy(nyys, $$S)\n\t\t$$S = nyys\n\t}\n\t$$S[$$p] = $$VAL\n\t$$S[$$p].yys = $$state\n\n$$newstate:\n\t$$n = int($$Pact[$$state])\n\tif $$n <= $$Flag {\n\t\tgoto $$default /* simple state */\n\t}\n\tif $$rcvr.char < 0 {\n\t\t$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)\n\t}\n\t$$n += $$token\n\tif $$n < 0 || $$n >= $$Last {\n\t\tgoto $$default\n\t}\n\t$$n = int($$Act[$$n])\n\tif int($$Chk[$$n]) == $$token { /* valid shift */\n\t\t$$rcvr.char = -1\n\t\t$$token = -1\n\t\t$$VAL = $$rcvr.lval\n\t\t$$state = $$n\n\t\tif Errflag > 0 {\n\t\t\tErrflag--\n\t\t}\n\t\tgoto $$stack\n\t}\n\n$$default:\n\t/* default state action */\n\t$$n = int($$Def[$$state])\n\tif $$n == -2 {\n\t\tif $$rcvr.char < 0 {\n\t\t\t$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)\n\t\t}\n\n\t\t/* look through exception table */\n\t\txi := 0\n\t\tfor {\n\t\t\tif $$Exca[xi+0] == -1 && int($$Exca[xi+1]) == $$state {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\txi += 2\n\t\t}\n\t\tfor xi += 2; ; xi += 2 {\n\t\t\t$$n = int($$Exca[xi+0])\n\t\t\tif $$n < 0 || $$n == $$token {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t$$n = int($$Exca[xi+1])\n\t\tif $$n < 0 {\n\t\t\tgoto ret0\n\t\t}\n\t}\n\tif $$n == 0 {\n\t\t/* error ... attempt to resume parsing */\n\t\tswitch Errflag {\n\t\tcase 0: /* brand new error */\n\t\t\t$$lex.Error($$ErrorMessage($$state, $$token))\n\t\t\tNerrs++\n\t\t\tif $$Debug >= 1 {\n\t\t\t\t__yyfmt__.Printf(\"%s\", $$Statname($$state))\n\t\t\t\t__yyfmt__.Printf(\" saw %s\\n\", $$Tokname($$token))\n\t\t\t}\n\t\t\tfallthrough\n\n\t\tcase 1, 2: /* incompletely recovered error ... try again */\n\t\t\tErrflag = 3\n\n\t\t\t/* find a state where \"error\" is a legal shift action */\n\t\t\tfor $$p >= 0 {\n\t\t\t\t$$n = int($$Pact[$$S[$$p].yys]) + $$ErrCode\n\t\t\t\tif $$n >= 0 && $$n < $$Last {\n\t\t\t\t\t$$state = int($$Act[$$n]) /* simulate a shift of \"error\" */\n\t\t\t\t\tif int($$Chk[$$state]) == $$ErrCode {\n\t\t\t\t\t\tgoto $$stack\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* the current p has no shift on \"error\", pop stack */\n\t\t\t\tif $$Debug >= 2 {\n\t\t\t\t\t__yyfmt__.Printf(\"error recovery pops state %d\\n\", $$S[$$p].yys)\n\t\t\t\t}\n\t\t\t\t$$p--\n\t\t\t}\n\t\t\t/* there is no state on the stack with an error shift ... abort */\n\t\t\tgoto ret1\n\n\t\tcase 3: /* no shift yet; clobber input char */\n\t\t\tif $$Debug >= 2 {\n\t\t\t\t__yyfmt__.Printf(\"error recovery discards %s\\n\", $$Tokname($$token))\n\t\t\t}\n\t\t\tif $$token == $$EofCode {\n\t\t\t\tgoto ret1\n\t\t\t}\n\t\t\t$$rcvr.char = -1\n\t\t\t$$token = -1\n\t\t\tgoto $$newstate /* try again in the same state */\n\t\t}\n\t}\n\n\t/* reduction by production $$n */\n\tif $$Debug >= 2 {\n\t\t__yyfmt__.Printf(\"reduce %v in:\\n\\t%v\\n\", $$n, $$Statname($$state))\n\t}\n\n\t$$nt := $$n\n\t$$pt := $$p\n\t_ = $$pt // guard against \"declared and not used\"\n\n\t$$p -= int($$R2[$$n])\n\t// $$p is now the index of $0. Perform the default action. Iff the\n\t// reduced production is ε, $1 is possibly out of range.\n\tif $$p+1 >= len($$S) {\n\t\tnyys := make([]$$SymType, len($$S)*2)\n\t\tcopy(nyys, $$S)\n\t\t$$S = nyys\n\t}\n\t$$VAL = $$S[$$p+1]\n\n\t/* consult goto table to find next state */\n\t$$n = int($$R1[$$n])\n\t$$g := int($$Pgo[$$n])\n\t$$j := $$g + $$S[$$p].yys + 1\n\n\tif $$j >= $$Last {\n\t\t$$state = int($$Act[$$g])\n\t} else {\n\t\t$$state = int($$Act[$$j])\n\t\tif int($$Chk[$$state]) != -$$n {\n\t\t\t$$state = int($$Act[$$g])\n\t\t}\n\t}\n\t// dummy call; replaced with literal code\n\t$$run()\n\tgoto $$stack /* stack new state and value */\n}\n`\n"
  },
  {
    "path": "cmd/html2article/conv.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This program takes an HTML file and outputs a corresponding article file in\n// present format. See: golang.org/x/tools/present\npackage main // import \"golang.org/x/tools/cmd/html2article\"\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/url\"\n\t\"os\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/net/html\"\n\t\"golang.org/x/net/html/atom\"\n)\n\nfunc main() {\n\tflag.Parse()\n\n\terr := convert(os.Stdout, os.Stdin)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc convert(w io.Writer, r io.Reader) error {\n\troot, err := html.Parse(r)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstyle := find(root, isTag(atom.Style))\n\tif err := parseStyles(style); err != nil {\n\t\tlog.Printf(\"couldn't parse all styles: %v\", err)\n\t}\n\n\tbody := find(root, isTag(atom.Body))\n\tif body == nil {\n\t\treturn errors.New(\"couldn't find body\")\n\t}\n\tarticle := limitNewlineRuns(makeHeadings(strings.TrimSpace(text(body))))\n\t_, err = fmt.Fprintf(w, \"Title\\n\\n%s\", article)\n\treturn err\n}\n\ntype Style string\n\nconst (\n\tBold   Style = \"*\"\n\tItalic Style = \"_\"\n\tCode   Style = \"`\"\n)\n\nvar cssRules = make(map[string]Style)\n\nfunc parseStyles(style *html.Node) error {\n\tif style == nil || style.FirstChild == nil {\n\t\treturn errors.New(\"couldn't find styles\")\n\t}\n\n\tstyles := style.FirstChild.Data\n\treadUntil := func(end rune) (string, bool) {\n\t\ti := strings.IndexRune(styles, end)\n\t\tif i < 0 {\n\t\t\treturn \"\", false\n\t\t}\n\t\ts := styles[:i]\n\t\tstyles = styles[i:]\n\t\treturn s, true\n\t}\n\n\tfor {\n\t\tsel, ok := readUntil('{')\n\t\tif !ok && sel == \"\" {\n\t\t\tbreak\n\t\t} else if !ok {\n\t\t\treturn fmt.Errorf(\"could not parse selector %q\", styles)\n\t\t}\n\n\t\tvalue, ok := readUntil('}')\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"couldn't parse style body for %s\", sel)\n\t\t}\n\t\tswitch {\n\t\tcase strings.Contains(value, \"italic\"):\n\t\t\tcssRules[sel] = Italic\n\t\tcase strings.Contains(value, \"bold\"):\n\t\t\tcssRules[sel] = Bold\n\t\tcase strings.Contains(value, \"Consolas\") || strings.Contains(value, \"Courier New\"):\n\t\t\tcssRules[sel] = Code\n\t\t}\n\t}\n\treturn nil\n}\n\nvar newlineRun = regexp.MustCompile(`\\n\\n+`)\n\nfunc limitNewlineRuns(s string) string {\n\treturn newlineRun.ReplaceAllString(s, \"\\n\\n\")\n}\n\nfunc makeHeadings(body string) string {\n\tbuf := new(bytes.Buffer)\n\tlines := strings.Split(body, \"\\n\")\n\tfor i, s := range lines {\n\t\tif i == 0 && !isBoldTitle(s) {\n\t\t\tbuf.WriteString(\"* Introduction\\n\\n\")\n\t\t}\n\t\tif isBoldTitle(s) {\n\t\t\ts = strings.TrimSpace(strings.Replace(s, \"*\", \" \", -1))\n\t\t\ts = \"* \" + s\n\t\t}\n\t\tbuf.WriteString(s)\n\t\tbuf.WriteByte('\\n')\n\t}\n\treturn buf.String()\n}\n\nfunc isBoldTitle(s string) bool {\n\treturn !strings.Contains(s, \" \") &&\n\t\tstrings.HasPrefix(s, \"*\") &&\n\t\tstrings.HasSuffix(s, \"*\")\n}\n\nfunc indent(buf *bytes.Buffer, s string) {\n\tfor l := range strings.SplitSeq(s, \"\\n\") {\n\t\tif l != \"\" {\n\t\t\tbuf.WriteByte('\\t')\n\t\t\tbuf.WriteString(l)\n\t\t}\n\t\tbuf.WriteByte('\\n')\n\t}\n}\n\nfunc unwrap(buf *bytes.Buffer, s string) {\n\tvar cont bool\n\tfor l := range strings.SplitSeq(s, \"\\n\") {\n\t\tl = strings.TrimSpace(l)\n\t\tif len(l) == 0 {\n\t\t\tif cont {\n\t\t\t\tbuf.WriteByte('\\n')\n\t\t\t\tbuf.WriteByte('\\n')\n\t\t\t}\n\t\t\tcont = false\n\t\t} else {\n\t\t\tif cont {\n\t\t\t\tbuf.WriteByte(' ')\n\t\t\t}\n\t\t\tbuf.WriteString(l)\n\t\t\tcont = true\n\t\t}\n\t}\n}\n\nfunc text(n *html.Node) string {\n\tvar buf bytes.Buffer\n\twalk(n, func(n *html.Node) bool {\n\t\tswitch n.Type {\n\t\tcase html.TextNode:\n\t\t\tbuf.WriteString(n.Data)\n\t\t\treturn false\n\t\tcase html.ElementNode:\n\t\t\t// no-op\n\t\tdefault:\n\t\t\treturn true\n\t\t}\n\t\ta := n.DataAtom\n\t\tif a == atom.Span {\n\t\t\tswitch {\n\t\t\tcase hasStyle(Code)(n):\n\t\t\t\ta = atom.Code\n\t\t\tcase hasStyle(Bold)(n):\n\t\t\t\ta = atom.B\n\t\t\tcase hasStyle(Italic)(n):\n\t\t\t\ta = atom.I\n\t\t\t}\n\t\t}\n\t\tswitch a {\n\t\tcase atom.Br:\n\t\t\tbuf.WriteByte('\\n')\n\t\tcase atom.P:\n\t\t\tunwrap(&buf, childText(n))\n\t\t\tbuf.WriteString(\"\\n\\n\")\n\t\tcase atom.Li:\n\t\t\tbuf.WriteString(\"- \")\n\t\t\tunwrap(&buf, childText(n))\n\t\t\tbuf.WriteByte('\\n')\n\t\tcase atom.Pre:\n\t\t\tindent(&buf, childText(n))\n\t\t\tbuf.WriteByte('\\n')\n\t\tcase atom.A:\n\t\t\thref, text := attr(n, \"href\"), childText(n)\n\t\t\t// Skip links with no text.\n\t\t\tif strings.TrimSpace(text) == \"\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// Don't emit empty links.\n\t\t\tif strings.TrimSpace(href) == \"\" {\n\t\t\t\tbuf.WriteString(text)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// Use original url for Google Docs redirections.\n\t\t\tif u, err := url.Parse(href); err != nil {\n\t\t\t\tlog.Printf(\"parsing url %q: %v\", href, err)\n\t\t\t} else if u.Host == \"www.google.com\" && u.Path == \"/url\" {\n\t\t\t\thref = u.Query().Get(\"q\")\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"[[%s][%s]]\", href, text)\n\t\tcase atom.Code:\n\t\t\tbuf.WriteString(highlight(n, \"`\"))\n\t\tcase atom.B:\n\t\t\tbuf.WriteString(highlight(n, \"*\"))\n\t\tcase atom.I:\n\t\t\tbuf.WriteString(highlight(n, \"_\"))\n\t\tcase atom.Img:\n\t\t\tsrc := attr(n, \"src\")\n\t\t\tfmt.Fprintf(&buf, \".image %s\\n\", src)\n\t\tcase atom.Iframe:\n\t\t\tsrc, w, h := attr(n, \"src\"), attr(n, \"width\"), attr(n, \"height\")\n\t\t\tfmt.Fprintf(&buf, \"\\n.iframe %s %s %s\\n\", src, h, w)\n\t\tcase atom.Param:\n\t\t\tif attr(n, \"name\") == \"movie\" {\n\t\t\t\t// Old style YouTube embed.\n\t\t\t\tu := attr(n, \"value\")\n\t\t\t\tu = strings.Replace(u, \"/v/\", \"/embed/\", 1)\n\t\t\t\tif i := strings.Index(u, \"&\"); i >= 0 {\n\t\t\t\t\tu = u[:i]\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&buf, \"\\n.iframe %s 540 304\\n\", u)\n\t\t\t}\n\t\tcase atom.Title:\n\t\tdefault:\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t})\n\treturn buf.String()\n}\n\nfunc childText(node *html.Node) string {\n\tvar buf bytes.Buffer\n\tfor n := node.FirstChild; n != nil; n = n.NextSibling {\n\t\tfmt.Fprint(&buf, text(n))\n\t}\n\treturn buf.String()\n}\n\nfunc highlight(node *html.Node, char string) string {\n\tt := strings.Replace(childText(node), \" \", char, -1)\n\treturn fmt.Sprintf(\"%s%s%s\", char, t, char)\n}\n\ntype selector func(*html.Node) bool\n\nfunc isTag(a atom.Atom) selector {\n\treturn func(n *html.Node) bool {\n\t\treturn n.DataAtom == a\n\t}\n}\n\nfunc hasClass(name string) selector {\n\treturn func(n *html.Node) bool {\n\t\tfor _, a := range n.Attr {\n\t\t\tif a.Key == \"class\" {\n\t\t\t\tif slices.Contains(strings.Fields(a.Val), name) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n}\n\nfunc hasStyle(s Style) selector {\n\treturn func(n *html.Node) bool {\n\t\tfor rule, s2 := range cssRules {\n\t\t\tif s2 != s {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif strings.HasPrefix(rule, \".\") && hasClass(rule[1:])(n) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif n.DataAtom.String() == rule {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n}\n\nfunc attr(node *html.Node, key string) (value string) {\n\tfor _, attr := range node.Attr {\n\t\tif attr.Key == key {\n\t\t\treturn attr.Val\n\t\t}\n\t}\n\treturn \"\"\n}\n\nfunc find(n *html.Node, fn selector) *html.Node {\n\tvar result *html.Node\n\twalk(n, func(n *html.Node) bool {\n\t\tif result != nil {\n\t\t\treturn false\n\t\t}\n\t\tif fn(n) {\n\t\t\tresult = n\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\treturn result\n}\n\nfunc walk(n *html.Node, fn selector) {\n\tif fn(n) {\n\t\tfor c := n.FirstChild; c != nil; c = c.NextSibling {\n\t\t\twalk(c, fn)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/present/dir.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"html/template\"\n\t\"io\"\n\t\"io/fs\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/present\"\n)\n\nfunc init() {\n\thttp.HandleFunc(\"/\", dirHandler)\n}\n\n// dirHandler serves a directory listing for the requested path, rooted at *contentPath.\nfunc dirHandler(w http.ResponseWriter, r *http.Request) {\n\tif r.URL.Path == \"/favicon.ico\" {\n\t\thttp.NotFound(w, r)\n\t\treturn\n\t}\n\tname := filepath.Join(*contentPath, r.URL.Path)\n\tif isDoc(name) {\n\t\terr := renderDoc(w, name)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t}\n\t\treturn\n\t}\n\tif isDir, err := dirList(w, name); err != nil {\n\t\taddr, _, e := net.SplitHostPort(r.RemoteAddr)\n\t\tif e != nil {\n\t\t\taddr = r.RemoteAddr\n\t\t}\n\t\tlog.Printf(\"request from %s: %s\", addr, err)\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t} else if isDir {\n\t\treturn\n\t}\n\thttp.FileServer(http.Dir(*contentPath)).ServeHTTP(w, r)\n}\n\nfunc isDoc(path string) bool {\n\t_, ok := contentTemplate[filepath.Ext(path)]\n\treturn ok\n}\n\nvar (\n\t// dirListTemplate holds the front page template.\n\tdirListTemplate *template.Template\n\n\t// contentTemplate maps the presentable file extensions to the\n\t// template to be executed.\n\tcontentTemplate map[string]*template.Template\n)\n\nfunc initTemplates(fsys fs.FS) error {\n\t// Locate the template file.\n\tactionTmpl := \"templates/action.tmpl\"\n\n\tcontentTemplate = make(map[string]*template.Template)\n\n\tfor ext, contentTmpl := range map[string]string{\n\t\t\".slide\":   \"slides.tmpl\",\n\t\t\".article\": \"article.tmpl\",\n\t} {\n\t\tcontentTmpl = \"templates/\" + contentTmpl\n\n\t\t// Read and parse the input.\n\t\ttmpl := present.Template()\n\t\ttmpl = tmpl.Funcs(template.FuncMap{\"playable\": playable})\n\t\tif _, err := tmpl.ParseFS(fsys, actionTmpl, contentTmpl); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcontentTemplate[ext] = tmpl\n\t}\n\n\tvar err error\n\tdirListTemplate, err = template.ParseFS(fsys, \"templates/dir.tmpl\")\n\treturn err\n}\n\n// renderDoc reads the present file, gets its template representation,\n// and executes the template, sending output to w.\nfunc renderDoc(w io.Writer, docFile string) error {\n\t// Read the input and build the doc structure.\n\tdoc, err := parse(docFile, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Find which template should be executed.\n\ttmpl := contentTemplate[filepath.Ext(docFile)]\n\n\t// Execute the template.\n\treturn doc.Render(w, tmpl)\n}\n\nfunc parse(name string, mode present.ParseMode) (*present.Doc, error) {\n\tf, err := os.Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\treturn present.Parse(f, name, mode)\n}\n\n// dirList scans the given path and writes a directory listing to w.\n// It parses the first part of each .slide file it encounters to display the\n// presentation title in the listing.\n// If the given path is not a directory, it returns (isDir == false, err == nil)\n// and writes nothing to w.\nfunc dirList(w io.Writer, name string) (isDir bool, err error) {\n\tf, err := os.Open(name)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tdefer f.Close()\n\tfi, err := f.Stat()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif isDir = fi.IsDir(); !isDir {\n\t\treturn false, nil\n\t}\n\tfis, err := f.Readdir(0)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tstrippedPath := strings.TrimPrefix(name, filepath.Clean(*contentPath))\n\tstrippedPath = strings.TrimPrefix(strippedPath, \"/\")\n\td := &dirListData{Path: strippedPath}\n\tfor _, fi := range fis {\n\t\t// skip the golang.org directory\n\t\tif name == \".\" && fi.Name() == \"golang.org\" {\n\t\t\tcontinue\n\t\t}\n\t\te := dirEntry{\n\t\t\tName: fi.Name(),\n\t\t\tPath: filepath.ToSlash(filepath.Join(strippedPath, fi.Name())),\n\t\t}\n\t\tif fi.IsDir() && showDir(e.Name) {\n\t\t\td.Dirs = append(d.Dirs, e)\n\t\t\tcontinue\n\t\t}\n\t\tif isDoc(e.Name) {\n\t\t\tfn := filepath.ToSlash(filepath.Join(name, fi.Name()))\n\t\t\tif p, err := parse(fn, present.TitlesOnly); err != nil {\n\t\t\t\tlog.Printf(\"parse(%q, present.TitlesOnly): %v\", fn, err)\n\t\t\t} else {\n\t\t\t\te.Title = p.Title\n\t\t\t}\n\t\t\tswitch filepath.Ext(e.Path) {\n\t\t\tcase \".article\":\n\t\t\t\td.Articles = append(d.Articles, e)\n\t\t\tcase \".slide\":\n\t\t\t\td.Slides = append(d.Slides, e)\n\t\t\t}\n\t\t} else if showFile(e.Name) {\n\t\t\td.Other = append(d.Other, e)\n\t\t}\n\t}\n\tif d.Path == \".\" {\n\t\td.Path = \"\"\n\t}\n\tsort.Sort(d.Dirs)\n\tsort.Sort(d.Slides)\n\tsort.Sort(d.Articles)\n\tsort.Sort(d.Other)\n\treturn true, dirListTemplate.Execute(w, d)\n}\n\n// showFile reports whether the given file should be displayed in the list.\nfunc showFile(n string) bool {\n\tswitch filepath.Ext(n) {\n\tcase \".pdf\":\n\tcase \".html\":\n\tcase \".go\":\n\tdefault:\n\t\treturn isDoc(n)\n\t}\n\treturn true\n}\n\n// showDir reports whether the given directory should be displayed in the list.\nfunc showDir(n string) bool {\n\tif len(n) > 0 && (n[0] == '.' || n[0] == '_') || n == \"present\" {\n\t\treturn false\n\t}\n\treturn true\n}\n\ntype dirListData struct {\n\tPath                          string\n\tDirs, Slides, Articles, Other dirEntrySlice\n}\n\ntype dirEntry struct {\n\tName, Path, Title string\n}\n\ntype dirEntrySlice []dirEntry\n\nfunc (s dirEntrySlice) Len() int           { return len(s) }\nfunc (s dirEntrySlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }\nfunc (s dirEntrySlice) Less(i, j int) bool { return s[i].Name < s[j].Name }\n"
  },
  {
    "path": "cmd/present/doc.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPresent displays slide presentations and articles. It runs a web server that\npresents slide and article files from the current directory.\n\nIt may be run as a stand-alone command or an App Engine app.\n\nTo use with App Engine, copy the files in the tools/cmd/present directory to the\nroot of your application and create an app.yaml file similar to this:\n\n\truntime: go111\n\n\thandlers:\n\t- url: /favicon.ico\n\t  static_files: static/favicon.ico\n\t  upload: static/favicon.ico\n\t- url: /static\n\t  static_dir: static\n\t- url: /.*\n\t  script: auto\n\n\t# nobuild_files is a regexp that identifies which files to not build.  It\n\t# is useful for embedding static assets like code snippets and preventing\n\t# them from producing build errors for your project.\n\tnobuild_files: [path regexp for talk materials]\n\nWhen running on App Engine, content will be served from the ./content/\nsubdirectory.\n\nPresent then can be tested in a local App Engine environment with\n\n\tGAE_ENV=standard go run .\n\nAnd deployed using\n\n\tgcloud app deploy\n\nInput files are named foo.extension, where \"extension\" defines the format of\nthe generated output. The supported formats are:\n\n\t.slide        // HTML5 slide presentation\n\t.article      // article format, such as a blog post\n\nThe present file format is documented by the present package:\nhttps://pkg.go.dev/golang.org/x/tools/present\n*/\npackage main\n"
  },
  {
    "path": "cmd/present/main.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"embed\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/present\"\n)\n\nvar (\n\thttpAddr      = flag.String(\"http\", \"127.0.0.1:3999\", \"HTTP service address (e.g., '127.0.0.1:3999')\")\n\toriginHost    = flag.String(\"orighost\", \"\", \"host component of web origin URL (e.g., 'localhost')\")\n\tbasePath      = flag.String(\"base\", \"\", \"base path for slide template and static resources\")\n\tcontentPath   = flag.String(\"content\", \".\", \"base path for presentation content\")\n\tusePlayground = flag.Bool(\"use_playground\", false, \"run code snippets using play.golang.org; if false, run them locally and deliver results by WebSocket transport\")\n)\n\n//go:embed static templates\nvar embedFS embed.FS\n\nfunc main() {\n\tflag.BoolVar(&present.PlayEnabled, \"play\", true, \"enable playground (permit execution of arbitrary user code)\")\n\tflag.BoolVar(&present.NotesEnabled, \"notes\", false, \"enable presenter notes (press 'N' from the browser to display them)\")\n\tflag.Parse()\n\n\tif os.Getenv(\"GAE_ENV\") == \"standard\" {\n\t\tlog.Print(\"Configuring for App Engine Standard\")\n\t\tport := os.Getenv(\"PORT\")\n\t\tif port == \"\" {\n\t\t\tport = \"8080\"\n\t\t}\n\t\t*httpAddr = fmt.Sprintf(\"0.0.0.0:%s\", port)\n\t\tpwd, err := os.Getwd()\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Couldn't get pwd: %v\\n\", err)\n\t\t}\n\t\t*basePath = pwd\n\t\t*usePlayground = true\n\t\t*contentPath = \"./content/\"\n\t}\n\n\tvar fsys fs.FS = embedFS\n\tif *basePath != \"\" {\n\t\tfsys = os.DirFS(*basePath)\n\t}\n\terr := initTemplates(fsys)\n\tif err != nil {\n\t\tlog.Fatalf(\"Failed to parse templates: %v\", err)\n\t}\n\n\tln, err := net.Listen(\"tcp\", *httpAddr)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer ln.Close()\n\n\t_, port, err := net.SplitHostPort(ln.Addr().String())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\torigin := &url.URL{Scheme: \"http\"}\n\tif *originHost != \"\" {\n\t\tif after, ok := strings.CutPrefix(*originHost, \"https://\"); ok {\n\t\t\t*originHost = after\n\t\t\torigin.Scheme = \"https\"\n\t\t}\n\t\t*originHost = strings.TrimPrefix(*originHost, \"http://\")\n\t\torigin.Host = net.JoinHostPort(*originHost, port)\n\t} else if ln.Addr().(*net.TCPAddr).IP.IsUnspecified() {\n\t\tname, _ := os.Hostname()\n\t\torigin.Host = net.JoinHostPort(name, port)\n\t} else {\n\t\treqHost, reqPort, err := net.SplitHostPort(*httpAddr)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif reqPort == \"0\" {\n\t\t\torigin.Host = net.JoinHostPort(reqHost, port)\n\t\t} else {\n\t\t\torigin.Host = *httpAddr\n\t\t}\n\t}\n\n\tinitPlayground(fsys, origin)\n\thttp.Handle(\"/static/\", http.FileServer(http.FS(fsys)))\n\n\tif !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&\n\t\tpresent.PlayEnabled && !*usePlayground {\n\t\tlog.Print(localhostWarning)\n\t}\n\n\tlog.Printf(\"Open your web browser and visit %s\", origin.String())\n\tif present.NotesEnabled {\n\t\tlog.Println(\"Notes are enabled, press 'N' from the browser to display them.\")\n\t}\n\tlog.Fatal(http.Serve(ln, nil))\n}\n\nconst localhostWarning = `\nWARNING!  WARNING!  WARNING!\n\nThe present server appears to be listening on an address that is not localhost\nand is configured to run code snippets locally. Anyone with access to this address\nand port will have access to this machine as the user running present.\n\nTo avoid this message, listen on localhost, run with -play=false, or run with\n-play_socket=false.\n\nIf you don't understand this message, hit Control-C to terminate this process.\n\nWARNING!  WARNING!  WARNING!\n`\n"
  },
  {
    "path": "cmd/present/play.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"golang.org/x/tools/playground/socket\"\n\t\"golang.org/x/tools/present\"\n\n\t// This will register a handler at /compile that will proxy to the\n\t// respective endpoints at play.golang.org. This allows the frontend to call\n\t// these endpoints without needing cross-origin request sharing (CORS).\n\t// Note that this is imported regardless of whether the endpoints are used or\n\t// not (in the case of a local socket connection, they are not called).\n\t_ \"golang.org/x/tools/playground\"\n)\n\nvar scripts = []string{\"jquery.js\", \"jquery-ui.js\", \"playground.js\", \"play.js\"}\n\n// playScript registers an HTTP handler at /play.js that serves all the\n// scripts specified by the variable above, and appends a line that\n// initializes the playground with the specified transport.\nfunc playScript(fsys fs.FS, transport string) {\n\tmodTime := time.Now()\n\tvar buf bytes.Buffer\n\tfor _, p := range scripts {\n\t\tb, err := fs.ReadFile(fsys, \"static/\"+p)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tbuf.Write(b)\n\t}\n\tfmt.Fprintf(&buf, \"\\ninitPlayground(new %v());\\n\", transport)\n\tb := buf.Bytes()\n\thttp.HandleFunc(\"/play.js\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-type\", \"application/javascript\")\n\t\thttp.ServeContent(w, r, \"\", modTime, bytes.NewReader(b))\n\t})\n}\n\nfunc initPlayground(fsys fs.FS, origin *url.URL) {\n\tif !present.PlayEnabled {\n\t\treturn\n\t}\n\tif *usePlayground {\n\t\tplayScript(fsys, \"HTTPTransport\")\n\t\treturn\n\t}\n\n\tplayScript(fsys, \"SocketTransport\")\n\thttp.Handle(\"/socket\", socket.NewHandler(origin))\n}\n\nfunc playable(c present.Code) bool {\n\tplay := present.PlayEnabled && c.Play\n\n\t// Restrict playable files to only Go source files when using play.golang.org,\n\t// since there is no method to execute shell scripts there.\n\tif *usePlayground {\n\t\treturn play && c.Ext == \".go\"\n\t}\n\treturn play\n}\n"
  },
  {
    "path": "cmd/present/static/article.css",
    "content": "body {\n  margin: 0;\n  font-family: Helvetica, Arial, sans-serif;\n  font-size: 16px;\n}\npre,\ncode {\n  font-family: Menlo, monospace;\n  font-size: 14px;\n}\npre {\n  line-height: 18px;\n  margin: 0;\n  padding: 0;\n}\na {\n  color: #375eab;\n  text-decoration: none;\n}\na:hover {\n  text-decoration: underline;\n}\np,\nul,\nol {\n  margin: 20px;\n}\n\nh1,\nh2,\nh3,\nh4 {\n  margin: 20px 0;\n  padding: 0;\n  color: #375eab;\n  font-weight: bold;\n}\nh1 {\n  font-size: 18px;\n  padding: 2px 5px;\n}\nh2 {\n  font-size: 16px;\n}\nh3 {\n  font-size: 16px;\n}\nh3,\nh4 {\n  margin: 20px 5px;\n}\nh4 {\n  font-size: 16px;\n}\n\ndiv#heading {\n  margin: 0 0 10px 0;\n  padding: 21px 0;\n  font-size: 20px;\n  font-weight: bold;\n}\n\ndiv#heading .author {\n  padding-top: 10px;\n  font-size: 14px;\n  font-weight: normal;\n}\n\ndiv#topbar {\n}\n\nbody {\n  text-align: center;\n}\ndiv#page {\n  width: 100%;\n}\ndiv#page > .container,\ndiv#topbar > .container {\n  text-align: left;\n  margin-left: auto;\n  margin-right: auto;\n  padding: 0 20px;\n  width: 900px;\n}\ndiv#page.wide > .container,\ndiv#topbar.wide > .container {\n  width: auto;\n}\n\ndiv#footer {\n  text-align: center;\n  color: #666;\n  font-size: 14px;\n  margin: 40px 0;\n}\n\n.author p {\n  margin: 0;\n  padding: 0 20px;\n}\n\ndiv.code,\ndiv.output {\n  margin: 0;\n}\n\npre {\n  margin: 20px 20px 20px 40px;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n\ndiv.output pre {\n  padding: 10px;\n}\n\npre {\n  background: white;\n}\ndiv.output pre {\n  background: black;\n}\ndiv.output .stdout pre {\n  color: #e6e6e6;\n}\ndiv.output .stderr pre {\n  color: rgb(244, 74, 63);\n}\ndiv.output .system pre {\n  color: rgb(255, 209, 77);\n}\n\n.buttons {\n  margin-left: 20px;\n}\ndiv.output .buttons {\n  margin-left: 0;\n  margin-bottom: 10px;\n}\n\n#toc {\n  float: right;\n  margin: 0px 10px;\n  padding: 10px;\n  border: 1px solid #e5ecf9;\n  background-color: #eee;\n  box-shadow: 3px 3px 2px #888888;\n\n  max-width: 33%;\n\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n\n#tochead {\n  font-weight: bold;\n  font-variant: small-caps;\n  font-size: 100%;\n  text-align: center;\n  padding-bottom: 5px;\n}\n\n#toc ul,\n#toc a {\n  list-style-type: none;\n  padding-left: 0px;\n  color: black;\n  margin: 0px;\n}\n\nul.toc-inner a {\n  padding-left: 10px !important;\n}\n\n@media print {\n  .no-print,\n  .no-print * {\n    display: none !important;\n  }\n}\n"
  },
  {
    "path": "cmd/present/static/dir.css",
    "content": "/* copied from $GOROOT/doc/style.css */\n\nbody {\n  margin: 0;\n  font-family: Helvetica, Arial, sans-serif;\n  font-size: 16px;\n}\npre,\ncode {\n  font-family: Menlo, monospace;\n  font-size: 14px;\n}\npre {\n  line-height: 18px;\n}\npre .comment {\n  color: #375eab;\n}\npre .highlight,\npre .highlight-comment,\npre .selection-highlight,\npre .selection-highlight-comment {\n  background: #ffff00;\n}\npre .selection,\npre .selection-comment {\n  background: #ff9632;\n}\npre .ln {\n  color: #999;\n}\nbody {\n  color: #222;\n}\na,\n.exampleHeading .text {\n  color: #375eab;\n  text-decoration: none;\n}\na:hover,\n.exampleHeading .text:hover {\n  text-decoration: underline;\n}\np,\npre,\nul,\nol {\n  margin: 20px;\n}\npre {\n  background: #e9e9e9;\n  padding: 10px;\n\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n\nh1,\nh2,\nh3,\nh4,\n.rootHeading {\n  margin: 20px 0;\n  padding: 0;\n  color: #375eab;\n  font-weight: bold;\n}\nh1 {\n  font-size: 24px;\n}\nh2 {\n  font-size: 20px;\n  background: #e0ebf5;\n  padding: 2px 5px;\n}\nh3 {\n  font-size: 20px;\n}\nh3,\nh4 {\n  margin: 20px 5px;\n}\nh4 {\n  font-size: 16px;\n}\n\ndl {\n  margin: 20px;\n}\ndd {\n  margin: 2px 20px;\n}\ndl,\ndd {\n  font-size: 14px;\n}\ndiv#nav table td {\n  vertical-align: top;\n}\n\ndiv#heading {\n  float: left;\n  margin: 0 0 10px 0;\n  padding: 21px 0;\n  font-size: 20px;\n  font-weight: normal;\n}\ndiv#heading a {\n  color: #222;\n  text-decoration: none;\n}\n\ndiv#topbar {\n  background: #e0ebf5;\n  height: 64px;\n}\n\nbody {\n  text-align: center;\n}\ndiv#page,\ndiv#topbar > .container {\n  clear: both;\n  text-align: left;\n  margin-left: auto;\n  margin-right: auto;\n  padding: 0 20px;\n  width: 900px;\n}\ndiv#page.wide,\ndiv#topbar > .wide {\n  width: auto;\n}\ndiv#plusone {\n  float: right;\n}\n\ndiv#footer {\n  color: #666;\n  font-size: 14px;\n  margin: 40px 0;\n}\n\ndiv#menu > a,\ndiv#menu > input {\n  padding: 10px;\n\n  text-decoration: none;\n  font-size: 16px;\n\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\ndiv#menu > a,\ndiv#menu > input {\n  border: 1px solid #375eab;\n}\ndiv#menu > a {\n  color: white;\n  background: #375eab;\n}\n\ndiv#menu {\n  float: right;\n  min-width: 590px;\n  padding: 10px 0;\n  text-align: right;\n}\ndiv#menu > a {\n  margin-right: 5px;\n  margin-bottom: 10px;\n\n  padding: 10px;\n}\ndiv#menu > input {\n  position: relative;\n  top: 1px;\n  width: 60px;\n  background: white;\n  color: #222;\n}\ndiv#menu > input.inactive {\n  color: #999;\n}\n"
  },
  {
    "path": "cmd/present/static/dir.js",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// copied from $GOROOT/doc/godocs.js\n\nfunction bindEvent(el, e, fn) {\n  if (el.addEventListener) {\n    el.addEventListener(e, fn, false);\n  } else if (el.attachEvent) {\n    el.attachEvent('on' + e, fn);\n  }\n}\n\nfunction godocs_bindSearchEvents() {\n  var search = document.getElementById('search');\n  if (!search) {\n    // no search box (index disabled)\n    return;\n  }\n  function clearInactive() {\n    if (search.className == 'inactive') {\n      search.value = '';\n      search.className = '';\n    }\n  }\n  function restoreInactive() {\n    if (search.value !== '') {\n      return;\n    }\n    if (search.type != 'search') {\n      search.value = search.getAttribute('placeholder');\n    }\n    search.className = 'inactive';\n  }\n  restoreInactive();\n  bindEvent(search, 'focus', clearInactive);\n  bindEvent(search, 'blur', restoreInactive);\n}\n\nbindEvent(window, 'load', godocs_bindSearchEvents);\n"
  },
  {
    "path": "cmd/present/static/jquery-ui.js",
    "content": "/*! jQuery UI - v1.10.2 - 2013-03-20\n* http://jqueryui.com\n* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js\n* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */\n\n(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return\"area\"===o?(a=t.parentNode,n=a.name,t.href&&n&&\"map\"===a.nodeName.toLowerCase()?(r=e(\"img[usemap=#\"+n+\"]\")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:\"a\"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return\"hidden\"===e.css(this,\"visibility\")}).length}var a=0,n=/^ui-id-\\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:\"1.10.2\",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return\"number\"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css(\"position\"))||/absolute/.test(this.css(\"position\"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,\"position\"))&&/(auto|scroll)/.test(e.css(this,\"overflow\")+e.css(this,\"overflow-y\")+e.css(this,\"overflow-x\"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,\"overflow\")+e.css(this,\"overflow-y\")+e.css(this,\"overflow-x\"))}).eq(0),/fixed/.test(this.css(\"position\"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css(\"zIndex\",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css(\"position\"),(\"absolute\"===s||\"relative\"===s||\"fixed\"===s)&&(a=parseInt(n.css(\"zIndex\"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id=\"ui-id-\"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr(\"id\")})}}),e.extend(e.expr[\":\"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,\"tabindex\")))},tabbable:function(t){var s=e.attr(t,\"tabindex\"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e(\"<a>\").outerWidth(1).jquery||e.each([\"Width\",\"Height\"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,\"padding\"+this))||0,s&&(i-=parseFloat(e.css(t,\"border\"+this+\"Width\"))||0),a&&(i-=parseFloat(e.css(t,\"margin\"+this))||0)}),i}var n=\"Width\"===s?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn[\"inner\"+s]=function(i){return i===t?o[\"inner\"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+\"px\")})},e.fn[\"outer\"+s]=function(t,i){return\"number\"!=typeof t?o[\"outer\"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+\"px\")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e(\"<a>\").data(\"a-b\",\"a\").removeData(\"a-b\").data(\"a-b\")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart=\"onselectstart\"in document.createElement(\"div\"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?\"selectstart\":\"mousedown\")+\".ui-disableSelection\",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(\".ui-disableSelection\")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if(\"hidden\"===e(t).css(\"overflow\"))return!1;var s=i&&\"left\"===i?\"scrollLeft\":\"scrollTop\",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler(\"remove\")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(\".\")[0];i=i.split(\".\")[1],a=u+\"-\"+i,n||(n=s,s=e.Widget),e.expr[\":\"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+\".\"+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o=\"string\"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&\"_\"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error(\"no such method '\"+r+\"' for \"+i+\" widget instance\"):e.error(\"cannot call methods on \"+i+\" prior to initialization; \"+\"attempted to call method '\"+r+\"'\")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:\"widget\",widgetEventPrefix:\"\",defaultElement:\"<div>\",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace=\".\"+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger(\"create\",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr(\"aria-disabled\").removeClass(this.widgetFullName+\"-disabled \"+\"ui-state-disabled\"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass(\"ui-state-hover\"),this.focusable.removeClass(\"ui-state-focus\")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if(\"string\"==typeof i)if(o={},n=i.split(\".\"),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,\"disabled\"===e&&(this.widget().toggleClass(this.widgetFullName+\"-disabled ui-state-disabled\",!!t).attr(\"aria-disabled\",t),this.hoverable.removeClass(\"ui-state-hover\"),this.focusable.removeClass(\"ui-state-focus\")),this},enable:function(){return this._setOption(\"disabled\",!1)},disable:function(){return this._setOption(\"disabled\",!0)},_on:function(i,s,n){var a,r=this;\"boolean\"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass(\"ui-state-disabled\")?(\"string\"==typeof o?r[o]:o).apply(r,arguments):t}\"string\"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\\w+)\\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||\"\").split(\" \").join(this.eventNamespace+\" \")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return(\"string\"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass(\"ui-state-hover\")},mouseleave:function(t){e(t.currentTarget).removeClass(\"ui-state-hover\")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass(\"ui-state-focus\")},focusout:function(t){e(t.currentTarget).removeClass(\"ui-state-focus\")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:\"fadeIn\",hide:\"fadeOut\"},function(t,i){e.Widget.prototype[\"_\"+t]=function(s,n,a){\"string\"==typeof n&&(n={effect:n});var r,o=n?n===!0||\"number\"==typeof n?i:n.effect||i:t;n=n||{},\"number\"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget(\"ui.mouse\",{version:\"1.10.2\",options:{cancel:\"input,textarea,button,select,option\",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind(\"mousedown.\"+this.widgetName,function(e){return t._mouseDown(e)}).bind(\"click.\"+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+\".preventClickEvent\")?(e.removeData(i.target,t.widgetName+\".preventClickEvent\"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind(\".\"+this.widgetName),this._mouseMoveDelegate&&e(document).unbind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).unbind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a=\"string\"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+\".preventClickEvent\")&&e.removeData(i.target,this.widgetName+\".preventClickEvent\"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).bind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).unbind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+\".preventClickEvent\",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget(\"ui.resizable\",e.ui.mouse,{version:\"1.10.2\",widgetEventPrefix:\"resize\",options:{alsoResize:!1,animate:!1,animateDuration:\"slow\",animateEasing:\"swing\",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:\"e,s,se\",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass(\"ui-resizable\"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||\"ui-resizable-helper\":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e(\"<div class='ui-wrapper' style='overflow: hidden;'></div>\").css({position:this.element.css(\"position\"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css(\"top\"),left:this.element.css(\"left\")})),this.element=this.element.parent().data(\"ui-resizable\",this.element.data(\"ui-resizable\")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css(\"marginLeft\"),marginTop:this.originalElement.css(\"marginTop\"),marginRight:this.originalElement.css(\"marginRight\"),marginBottom:this.originalElement.css(\"marginBottom\")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css(\"resize\"),this.originalElement.css(\"resize\",\"none\"),this._proportionallyResizeElements.push(this.originalElement.css({position:\"static\",zoom:1,display:\"block\"})),this.originalElement.css({margin:this.originalElement.css(\"margin\")}),this._proportionallyResize()),this.handles=r.handles||(e(\".ui-resizable-handle\",this.element).length?{n:\".ui-resizable-n\",e:\".ui-resizable-e\",s:\".ui-resizable-s\",w:\".ui-resizable-w\",se:\".ui-resizable-se\",sw:\".ui-resizable-sw\",ne:\".ui-resizable-ne\",nw:\".ui-resizable-nw\"}:\"e,s,se\"),this.handles.constructor===String)for(\"all\"===this.handles&&(this.handles=\"n,e,s,w,se,sw,ne,nw\"),t=this.handles.split(\",\"),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a=\"ui-resizable-\"+s,n=e(\"<div class='ui-resizable-handle \"+a+\"'></div>\"),n.css({zIndex:r.zIndex}),\"se\"===s&&n.addClass(\"ui-icon ui-icon-gripsmall-diagonal-se\"),this.handles[s]=\".ui-resizable-\"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=[\"padding\",/ne|nw|n/.test(i)?\"Top\":/se|sw|s/.test(i)?\"Bottom\":/^e$/.test(i)?\"Right\":\"Left\"].join(\"\"),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(\".ui-resizable-handle\",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:\"se\")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass(\"ui-resizable-autohide\").mouseenter(function(){r.disabled||(e(this).removeClass(\"ui-resizable-autohide\"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass(\"ui-resizable-autohide\"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass(\"ui-resizable ui-resizable-disabled ui-resizable-resizing\").removeData(\"resizable\").removeData(\"ui-resizable\").unbind(\".resizable\").find(\".ui-resizable-handle\").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css(\"position\"),width:t.outerWidth(),height:t.outerHeight(),top:t.css(\"top\"),left:t.css(\"left\")}).insertAfter(t),t.remove()),this.originalElement.css(\"resize\",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css(\"position\"))?h.css({position:\"absolute\",top:h.css(\"top\"),left:h.css(\"left\")}):h.is(\".ui-draggable\")&&h.css({position:\"absolute\",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css(\"left\")),n=t(this.helper.css(\"top\")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio=\"number\"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(\".ui-resizable-\"+this.axis).css(\"cursor\"),e(\"body\").css(\"cursor\",\"auto\"===a?this.axis+\"-resize\":a),h.addClass(\"ui-resizable-resizing\"),this._propagate(\"start\",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate(\"resize\",t),this.position.top!==r&&(n.top=this.position.top+\"px\"),this.position.left!==h&&(n.left=this.position.left+\"px\"),this.size.width!==l&&(n.width=this.size.width+\"px\"),this.size.height!==u&&(n.height=this.size.height+\"px\"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger(\"resize\",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],\"left\")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css(\"left\"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css(\"top\"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e(\"body\").css(\"cursor\",\"auto\"),this.element.removeClass(\"ui-resizable-resizing\"),this._propagate(\"stop\",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),\"sw\"===n&&(e.left=t.left+(s.width-e.width),e.top=null),\"nw\"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidth<e.width,a=i(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=i(e.width)&&t.minWidth&&t.minWidth>e.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css(\"borderTopWidth\"),n.css(\"borderRightWidth\"),n.css(\"borderBottomWidth\"),n.css(\"borderLeftWidth\")],s=[n.css(\"paddingTop\"),n.css(\"paddingRight\"),n.css(\"paddingBottom\"),n.css(\"paddingLeft\")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e(\"<div style='overflow:hidden;'></div>\"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:\"absolute\",left:this.elementOffset.left+\"px\",top:this.elementOffset.top+\"px\",zIndex:++i.zIndex}),this.helper.appendTo(\"body\").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),\"resize\"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add(\"resizable\",\"animate\",{stop:function(t){var i=e(this).data(\"ui-resizable\"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],\"left\")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css(\"left\"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css(\"top\"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css(\"width\"),10),height:parseInt(i.element.css(\"height\"),10),top:parseInt(i.element.css(\"top\"),10),left:parseInt(i.element.css(\"left\"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate(\"resize\",t)}})}}),e.ui.plugin.add(\"resizable\",\"containment\",{start:function(){var i,s,n,a,o,r,h,l=e(this).data(\"ui-resizable\"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e([\"Top\",\"Right\",\"Left\",\"Bottom\"]).each(function(e,n){s[e]=t(i.css(\"padding\"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,\"left\")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data(\"ui-resizable\"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css(\"position\"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css(\"position\")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data(\"ui-resizable\"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css(\"position\"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css(\"position\"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add(\"resizable\",\"alsoResize\",{start:function(){var t=e(this).data(\"ui-resizable\"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data(\"ui-resizable-alsoresize\",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css(\"left\"),10),top:parseInt(t.css(\"top\"),10)})})};\"object\"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data(\"ui-resizable\"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data(\"ui-resizable-alsoresize\"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?[\"width\",\"height\"]:[\"width\",\"height\",\"top\",\"left\"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};\"object\"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData(\"resizable-alsoresize\")}}),e.ui.plugin.add(\"resizable\",\"ghost\",{start:function(){var t=e(this).data(\"ui-resizable\"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:\"block\",position:\"relative\",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass(\"ui-resizable-ghost\").addClass(\"string\"==typeof i.ghost?i.ghost:\"\"),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data(\"ui-resizable\");t.ghost&&t.ghost.css({position:\"relative\",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data(\"ui-resizable\");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add(\"resizable\",\"grid\",{resize:function(){var t=e(this).data(\"ui-resizable\"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r=\"number\"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);"
  },
  {
    "path": "cmd/present/static/jquery.js",
    "content": "/*! jQuery v1.8.2 jquery.com | jquery.org/license */\n(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e=\"data-\"+c.replace(I,\"-$1\").toLowerCase();d=a.getAttribute(e);if(typeof d==\"string\"){try{d=d===\"true\"?!0:d===\"false\"?!1:d===\"null\"?null:+d+\"\"===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b===\"data\"&&p.isEmptyObject(a[b]))continue;if(b!==\"toJSON\")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b==\"string\"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split(\"|\"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c===\"object\"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c===\"input\"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c===\"option\"?b.selected=a.defaultSelected:c===\"input\"||c===\"textarea\"?b.defaultValue=a.defaultValue:c===\"script\"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!=\"undefined\"?a.getElementsByTagName(\"*\"):typeof a.querySelectorAll!=\"undefined\"?a.querySelectorAll(\"*\"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,\"display\")===\"none\"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,\"olddisplay\"),b?(!e[f]&&c.style.display===\"none\"&&(c.style.display=\"\"),c.style.display===\"\"&&bZ(c)&&(e[f]=p._data(c,\"olddisplay\",cc(c.nodeName)))):(d=bH(c,\"display\"),!e[f]&&d!==\"none\"&&p._data(c,\"olddisplay\",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display===\"none\"||c.style.display===\"\")c.style.display=b?e[f]||\"\":\"none\"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||\"px\"):b}function ca(a,b,c,d){var e=c===(d?\"border\":\"content\")?4:b===\"width\"?1:0,f=0;for(;e<4;e+=2)c===\"margin\"&&(f+=p.css(a,c+bV[e],!0)),d?(c===\"content\"&&(f-=parseFloat(bH(a,\"padding\"+bV[e]))||0),c!==\"margin\"&&(f-=parseFloat(bH(a,\"border\"+bV[e]+\"Width\"))||0)):(f+=parseFloat(bH(a,\"padding\"+bV[e]))||0,c!==\"padding\"&&(f+=parseFloat(bH(a,\"border\"+bV[e]+\"Width\"))||0));return f}function cb(a,b,c){var d=b===\"width\"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,\"boxSizing\")===\"border-box\";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?\"border\":\"content\"),e)+\"px\"}function cc(a){if(bS[a])return bS[a];var b=p(\"<\"+a+\">\").appendTo(e.body),c=b.css(\"display\");b.remove();if(c===\"none\"||c===\"\"){bI=e.body.appendChild(bI||p.extend(e.createElement(\"iframe\"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(\"<!doctype html><html><body>\"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,\"display\"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+\"[\"+(typeof e==\"object\"?b:\"\")+\"]\",e,c,d)});else if(!c&&p.type(b)===\"object\")for(e in b)ci(a+\"[\"+e+\"]\",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!=\"string\"&&(c=b,b=\"*\");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\\+/.test(d),f&&(d=d.substr(1)||\"*\"),e=a[d]=a[d]||[],e[f?\"unshift\":\"push\"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h==\"string\"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g[\"*\"]&&(h=cA(a,c,d,e,\"*\",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]===\"*\")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader(\"content-type\"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+\" \"+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!==\"*\"){if(h!==\"*\"&&h!==e){c=i[h+\" \"+e]||i[\"* \"+e];if(!c)for(d in i){f=d.split(\" \");if(f[1]===e){c=i[h+\" \"+f[0]]||i[\"* \"+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a[\"throws\"])b=c(b);else try{b=c(b)}catch(k){return{state:\"parsererror\",error:c?k:\"No conversion from \"+h+\" to \"+e}}}h=e}return{state:\"success\",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT[\"*\"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&\"expand\"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,\"fx\"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,\"fx\").length||j.empty.fire()})})),a.nodeType===1&&(\"height\"in b||\"width\"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,\"display\")===\"inline\"&&p.css(a,\"float\")===\"none\"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)===\"inline\"?m.display=\"inline-block\":m.zoom=1)),c.overflow&&(m.overflow=\"hidden\",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?\"hide\":\"show\"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,\"fxshow\")||p._data(a,\"fxshow\",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,\"fxshow\",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e===\"width\"||e===\"height\"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d[\"margin\"+c]=d[\"padding\"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source,r=/\\S/,s=/\\s+/,t=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,u=/^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,v=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,w=/^[\\],:{}\\s]*$/,x=/(?:^|:|,)(?:\\s*\\[)+/g,y=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,z=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/g,A=/^-ms-/,B=/-([\\da-z])/gi,C=function(a,b){return(b+\"\").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener(\"DOMContentLoaded\",D,!1),p.ready()):e.readyState===\"complete\"&&(e.detachEvent(\"onreadystatechange\",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a==\"string\"){a.charAt(0)===\"<\"&&a.charAt(a.length-1)===\">\"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:\"\",jquery:\"1.8.2\",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b===\"find\"?d.selector=this.selector+(this.selector?\" \":\"\")+c:b&&(d.selector=this.selector+\".\"+b+\"(\"+c+\")\"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),\"slice\",k.call(arguments).join(\",\"))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h==\"boolean\"&&(k=h,h=arguments[1]||{},i=2),typeof h!=\"object\"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger(\"ready\").off(\"ready\")},isFunction:function(a){return p.type(a)===\"function\"},isArray:Array.isArray||function(a){return p.type(a)===\"array\"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||\"object\"},isPlainObject:function(a){if(!a||p.type(a)!==\"object\"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,\"constructor\")&&!n.call(a.constructor.prototype,\"isPrototypeOf\"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!=\"string\"?null:(typeof b==\"boolean\"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!=\"string\")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,\"@\").replace(z,\"]\").replace(x,\"\")))return(new Function(\"return \"+b))();p.error(\"Invalid JSON: \"+b)},parseXML:function(c){var d,e;if(!c||typeof c!=\"string\")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,\"text/xml\")):(d=new ActiveXObject(\"Microsoft.XMLDOM\"),d.async=\"false\",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName(\"parsererror\").length)&&p.error(\"Invalid XML: \"+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,\"ms-\").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(\"﻿ \")?function(a){return a==null?\"\":o.call(a)}:function(a){return a==null?\"\":(a+\"\").replace(t,\"\")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c===\"string\"||c===\"function\"||c===\"regexp\"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d==\"number\")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i==\"number\"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c==\"string\"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d==\"object\"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState===\"complete\")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener(\"DOMContentLoaded\",D,!1),a.addEventListener(\"load\",p.ready,!1);else{e.attachEvent(\"onreadystatechange\",D),a.attachEvent(\"onload\",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll(\"left\")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"),function(a,b){E[\"[object \"+b+\"]\"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a==\"string\"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e===\"function\"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!==\"string\"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[[\"resolve\",\"done\",p.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",p.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",p.Callbacks(\"memory\")]],c=\"pending\",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+\"With\"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+\"With\"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement(\"div\");n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",c=n.getElementsByTagName(\"*\"),d=n.getElementsByTagName(\"a\")[0],d.style.cssText=\"top:1px;float:left;opacity:.5\";if(!c||!c.length)return{};f=e.createElement(\"select\"),g=f.appendChild(e.createElement(\"option\")),h=n.getElementsByTagName(\"input\")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName(\"tbody\").length,htmlSerialize:!!n.getElementsByTagName(\"link\").length,style:/top/.test(d.getAttribute(\"style\")),hrefNormalized:d.getAttribute(\"href\")===\"/a\",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value===\"on\",optSelected:g.selected,getSetAttribute:n.className!==\"t\",enctype:!!e.createElement(\"form\").enctype,html5Clone:e.createElement(\"nav\").cloneNode(!0).outerHTML!==\"<:nav></:nav>\",boxModel:e.compatMode===\"CSS1Compat\",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent(\"onclick\",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent(\"onclick\"),n.detachEvent(\"onclick\",m)),h=e.createElement(\"input\"),h.value=\"t\",h.setAttribute(\"type\",\"radio\"),b.radioValue=h.value===\"t\",h.setAttribute(\"checked\",\"checked\"),h.setAttribute(\"name\",\"t\"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j=\"on\"+k,l=j in n,l||(n.setAttribute(j,\"return;\"),l=typeof n[j]==\"function\"),b[k+\"Bubbles\"]=l;return p(function(){var c,d,f,g,h=\"padding:0;margin:0;border:0;display:block;overflow:hidden;\",i=e.getElementsByTagName(\"body\")[0];if(!i)return;c=e.createElement(\"div\"),c.style.cssText=\"visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px\",i.insertBefore(c,i.firstChild),d=e.createElement(\"div\"),c.appendChild(d),d.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",f=d.getElementsByTagName(\"td\"),f[0].style.cssText=\"padding:0;margin:0;border:0;display:none\",l=f[0].offsetHeight===0,f[0].style.display=\"\",f[1].style.display=\"none\",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML=\"\",d.style.cssText=\"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!==\"1%\",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:\"4px\"}).width===\"4px\",g=e.createElement(\"div\"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width=\"0\",d.style.width=\"1px\",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!=\"undefined\"&&(d.innerHTML=\"\",d.style.cssText=h+\"width:1px;padding:1px;display:inline;zoom:1\",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display=\"block\",d.style.overflow=\"visible\",d.innerHTML=\"<div></div>\",d.firstChild.style.width=\"5px\",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:\"jQuery\"+(p.fn.jquery+Math.random()).replace(/\\D/g,\"\"),noData:{embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c==\"string\",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c==\"object\"||typeof c==\"function\")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(\" \")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute(\"classid\")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,\"parsedAttrs\")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf(\"data-\")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,\"parsedAttrs\",!0)}}return k}return typeof a==\"object\"?this.each(function(){p.data(this,a)}):(d=a.split(\".\",2),d[1]=d[1]?\".\"+d[1]:\"\",e=d[1]+\"!\",p.access(this,function(c){if(c===b)return k=this.triggerHandler(\"getData\"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler(\"setData\"+e,d),p.data(this,a,c),b.triggerHandler(\"changeData\"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||\"fx\")+\"queue\",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||\"fx\";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e===\"inprogress\"&&(e=c.shift(),d--),e&&(b===\"fx\"&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks(\"once memory\").add(function(){p.removeData(a,b+\"queue\",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!=\"string\"&&(c=a,a=\"fx\",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a===\"fx\"&&b[0]!==\"inprogress\"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||\"fx\",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!=\"string\"&&(c=a,a=b),a=a||\"fx\";while(h--)d=p._data(g[h],a+\"queueHooks\"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\\t\\r\\n]/g,P=/\\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=\" \"+e.className+\" \";for(g=0,h=b.length;g<h;g++)f.indexOf(\" \"+b[g]+\" \")<0&&(f+=b[g]+\" \");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"||a===b){c=(a||\"\").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(\" \"+e.className+\" \").replace(O,\" \");for(f=0,g=c.length;f<g;f++)while(d.indexOf(\" \"+c[f]+\" \")>=0)d=d.replace(\" \"+c[f]+\" \",\" \");e.className=a?p.trim(d):\"\"}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b==\"boolean\";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c===\"string\"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?\"addClass\":\"removeClass\"](e)}else if(c===\"undefined\"||c===\"boolean\")this.className&&p._data(this,\"__className__\",this.className),this.className=this.className||a===!1?\"\":p._data(this,\"__className__\")||\"\"})},hasClass:function(a){var b=\" \"+a+\" \",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(\" \"+this[c].className+\" \").replace(O,\" \").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&\"get\"in c&&(d=c.get(f,\"value\"))!==b?d:(d=f.value,typeof d==\"string\"?d.replace(P,\"\"):d==null?\"\":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f=\"\":typeof f==\"number\"?f+=\"\":p.isArray(f)&&(f=p.map(f,function(a){return a==null?\"\":a+\"\"})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!(\"set\"in c)||c.set(this,f,\"value\")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type===\"select-one\";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute(\"disabled\")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,\"optgroup\"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find(\"option\").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute==\"undefined\")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&\"set\"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+\"\"),d)}return g&&\"get\"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,\"\"),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error(\"type property can't be changed\");else if(!p.support.radioValue&&b===\"radio\"&&p.nodeName(a,\"input\")){var c=a.value;return a.setAttribute(\"type\",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,\"button\")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,\"button\"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&\"set\"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&\"get\"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode(\"tabindex\");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!=\"boolean\"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!==\"\":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+\"\"}},p.each([\"width\",\"height\"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c===\"\")return a.setAttribute(b,\"auto\"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===\"\"&&(b=\"false\"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each([\"href\",\"src\",\"width\",\"height\"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+\"\"}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype=\"encoding\"),p.support.checkOn||p.each([\"radio\",\"checkbox\"],function(){p.valHooks[this]={get:function(a){return a.getAttribute(\"value\")===null?\"on\":a.value}}}),p.each([\"radio\",\"checkbox\"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\\.]*|)(?:\\.(.+)|)$/,X=/(?:^|\\s)hover(\\.\\S+|)\\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,\"mouseenter$1 mouseleave$1\")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!=\"undefined\"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(\" \");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||\"\").split(\".\").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(\".\")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent(\"on\"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||\"\")).split(\" \");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp(\"(^|\\\\.)\"+j.split(\".\").sort().join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d===\"**\"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,\"events\",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf(\"!\")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(\".\")>=0&&(t=s.split(\".\"),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c==\"object\"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join(\".\"),c.namespace_re=c.namespace?new RegExp(\"(^|\\\\.)\"+t.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,m=s.indexOf(\":\")<0?\"on\"+s:\"\";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,\"events\")||{})[c.type]&&p._data(k,\"handle\"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!==\"click\"||!p.nodeName(f,\"a\"))&&p.acceptData(f)&&m&&f[s]&&(s!==\"focus\"&&s!==\"blur\"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,\"events\")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!==\"click\"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!==\"click\"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:\"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:\"focusin\"},blur:{delegateType:\"focusout\"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d=\"on\"+b;a.detachEvent&&(typeof a[d]==\"undefined\"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,\"form\"))return!1;p.event.add(this,\"click._submit keypress._submit\",function(a){var c=a.target,d=p.nodeName(c,\"input\")||p.nodeName(c,\"button\")?c.form:b;d&&!p._data(d,\"_submit_attached\")&&(p.event.add(d,\"submit._submit\",function(a){a._submit_bubble=!0}),p._data(d,\"_submit_attached\",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate(\"submit\",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,\"form\"))return!1;p.event.remove(this,\"._submit\")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type===\"checkbox\"||this.type===\"radio\")p.event.add(this,\"propertychange._change\",function(a){a.originalEvent.propertyName===\"checked\"&&(this._just_changed=!0)}),p.event.add(this,\"click._change\",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate(\"change\",this,a,!0)});return!1}p.event.add(this,\"beforeactivate._change\",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,\"_change_attached\")&&(p.event.add(b,\"change._change\",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate(\"change\",this.parentNode,a,!0)}),p._data(b,\"_change_attached\",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!==\"radio\"&&b.type!==\"checkbox\")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,\"._change\"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a==\"object\"){typeof c!=\"string\"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c==\"string\"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+\".\"+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a==\"object\"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c==\"function\")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||\"**\",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,\"**\"):this.off(b,a||\"**\",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,\"lastToggle\"+a.guid)||0)%d;return p._data(this,\"lastToggle\"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!=\"string\")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,\"$1\"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c===\"input\"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c===\"input\"||c===\"button\")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L,\" \");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir===\"parentNode\",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+\" \"+g+\" \",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i==\"string\"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||\"*\",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[\" \"],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join(\"\").replace(L,\"$1\"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(\"\"))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u=\"0\",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG(\"*\",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type===\"ID\"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,\"\"),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,\"\"),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join(\"\");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n=\"undefined\",o=(\"sizcache\"+Math.random()).replace(\".\",\"\"),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",F=\"(?:\\\\\\\\.|[-\\\\w]|[^\\\\x00-\\\\xa0])+\",G=F.replace(\"w\",\"w#\"),H=\"([*^$|!~]?=)\",I=\"\\\\[\"+E+\"*(\"+F+\")\"+E+\"*(?:\"+H+E+\"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\"+G+\")|)|)\"+E+\"*\\\\]\",J=\":(\"+F+\")(?:\\\\((?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\2|([^()[\\\\]]*|(?:(?:\"+I+\")|[^:]|\\\\\\\\.)*|.*))\\\\)|)\",K=\":(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+E+\"*((?:-\\\\d)?\\\\d*)\"+E+\"*\\\\)|)(?=[^-]|$)\",L=new RegExp(\"^\"+E+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+E+\"+$\",\"g\"),M=new RegExp(\"^\"+E+\"*,\"+E+\"*\"),N=new RegExp(\"^\"+E+\"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\"+E+\"*\"),O=new RegExp(J),P=/^(?:#([\\w\\-]+)|(\\w+)|\\.([\\w\\-]+))$/,Q=/^:not/,R=/[\\x20\\t\\r\\n\\f]*[+~]/,S=/:not\\($/,T=/h\\d/i,U=/input|select|textarea|button/i,V=/\\\\(?!\\\\)/g,W={ID:new RegExp(\"^#(\"+F+\")\"),CLASS:new RegExp(\"^\\\\.(\"+F+\")\"),NAME:new RegExp(\"^\\\\[name=['\\\"]?(\"+F+\")['\\\"]?\\\\]\"),TAG:new RegExp(\"^(\"+F.replace(\"w\",\"w*\")+\")\"),ATTR:new RegExp(\"^\"+I),PSEUDO:new RegExp(\"^\"+J),POS:new RegExp(K,\"i\"),CHILD:new RegExp(\"^:(only|nth|first|last)-child(?:\\\\(\"+E+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+E+\"*(?:([+-]|)\"+E+\"*(\\\\d+)|))\"+E+\"*\\\\)|)\",\"i\"),needsContext:new RegExp(\"^\"+E+\"*[>+~]|\"+K,\"i\")},X=function(a){var b=r.createElement(\"div\");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment(\"\")),!a.getElementsByTagName(\"*\").length}),Z=X(function(a){return a.innerHTML=\"<a href='#'></a>\",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute(\"href\")===\"#\"}),$=X(function(a){a.innerHTML=\"<select></select>\";var b=typeof a.lastChild.getAttribute(\"multiple\");return b!==\"boolean\"&&b!==\"string\"}),_=X(function(a){return a.innerHTML=\"<div class='hidden e'></div><div class='hidden'></div>\",!a.getElementsByClassName||!a.getElementsByClassName(\"e\").length?!1:(a.lastChild.className=\"e\",a.getElementsByClassName(\"e\").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML=\"<a name='\"+o+\"'></a><div name='\"+o+\"'></div>\",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c=\"\",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent==\"string\")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!==\"HTML\":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]==\"boolean\"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute(\"href\",2)},type:function(a){return a.getAttribute(\"type\")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode(\"id\").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a===\"*\"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,\"\"),a[3]=(a[4]||a[5]||\"\").replace(V,\"\"),a[2]===\"~=\"&&(a[3]=\" \"+a[3]+\" \"),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]===\"nth\"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]===\"even\"||a[2]===\"odd\")),a[4]=+(a[6]+a[7]||a[2]===\"odd\")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(\")\",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,\"\"),function(b){return b.getAttribute(\"id\")===a}}:function(a){return a=a.replace(V,\"\"),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode(\"id\");return c&&c.value===a}},TAG:function(a){return a===\"*\"?function(){return!0}:(a=a.replace(V,\"\").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp(\"(^|\"+E+\")\"+a+\"(\"+E+\"|$)\"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute(\"class\")||\"\")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b===\"!=\":b?(f+=\"\",b===\"=\"?f===c:b===\"!=\"?f!==c:b===\"^=\"?c&&f.indexOf(c)===0:b===\"*=\"?c&&f.indexOf(c)>-1:b===\"$=\"?c&&f.substr(f.length-c.length)===c:b===\"~=\"?(\" \"+f+\" \").indexOf(c)>-1:b===\"|=\"?f===c||f.substr(0,c.length+1)===c+\"-\":!1):!0}},CHILD:function(a,b,c,d){return a===\"nth\"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case\"only\":case\"first\":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a===\"first\")return!0;c=b;case\"last\":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error(\"unsupported pseudo: \"+a);return d[o]?d(b):d.length>1?(c=[a,a,\"\",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,\"$1\"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b===\"input\"&&!!a.checked||b===\"option\"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>\"@\"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()===\"input\"&&(b=a.type)===\"text\"&&((c=a.getAttribute(\"type\"))==null||c.toLowerCase()===b)},radio:bd(\"radio\"),checkbox:bd(\"checkbox\"),file:bd(\"file\"),password:bd(\"password\"),image:bd(\"image\"),submit:be(\"submit\"),reset:be(\"reset\"),button:function(a){var b=a.nodeName.toLowerCase();return b===\"input\"&&a.type===\"button\"||b===\"button\"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\\\/g,d=/\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,e=[\":focus\"],f=[\":active\",\":focus\"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML=\"<select><option selected=''></option></select>\",a.querySelectorAll(\"[selected]\").length||e.push(\"\\\\[\"+E+\"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\"),a.querySelectorAll(\":checked\").length||e.push(\":checked\")}),X(function(a){a.innerHTML=\"<p test=''></p>\",a.querySelectorAll(\"[test^='']\").length&&e.push(\"[*^$]=\"+E+\"*(?:\\\"\\\"|'')\"),a.innerHTML=\"<input type='hidden'/>\",a.querySelectorAll(\":enabled\").length||e.push(\":enabled\",\":disabled\")}),e=new RegExp(e.join(\"|\")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!==\"object\"){i=bh(a),(k=d.getAttribute(\"id\"))?l=k.replace(c,\"\\\\$&\"):d.setAttribute(\"id\",l),l=\"[id='\"+l+\"'] \",j=i.length;while(j--)i[j]=l+i[j].join(\"\");m=R.test(a)&&d.parentNode||d,n=i.join(\",\")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute(\"id\")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,\"div\");try{h.call(b,\"[test!='']:sizzle\"),f.push(\"!=\",J)}catch(c){}}),f=new RegExp(f.join(\"|\")),bc.matchesSelector=function(b,c){c=c.replace(d,\"='$1']\");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[\":\"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\\[\\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!=\"string\")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack(\"\",\"find\",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),\"not\",a)},filter:function(a){return this.pushStack(bj(this,a,!0),\"filter\",a)},is:function(a){return!!a&&(typeof a==\"string\"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!=\"string\"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,\"closest\",a)},index:function(a){return a?typeof a==\"string\"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a==\"string\"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return p.dir(a,\"parentNode\",c)},next:function(a){return bi(a,\"nextSibling\")},prev:function(a){return bi(a,\"previousSibling\")},nextAll:function(a){return p.dir(a,\"nextSibling\")},prevAll:function(a){return p.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return p.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return p.dir(a,\"previousSibling\",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,\"iframe\")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d==\"string\"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(\",\"))}}),p.extend({filter:function(a,b,c){return c&&(a=\":not(\"+a+\")\"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",bm=/ jQuery\\d+=\"(?:null|\\d+)\"/g,bn=/^\\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,bp=/<([\\w:]+)/,bq=/<tbody/i,br=/<|&#?\\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp(\"<(?:\"+bl+\")[\\\\s/>]\",\"i\"),bv=/^(?:checkbox|radio)$/,bw=/checked\\s*(?:[^=]|=\\s*.checked.)/i,bx=/\\/(java|ecma)script/i,by=/^\\s*<!(?:\\[CDATA\\[|\\-\\-)|[\\]\\-]{2}>\\s*$/g,bz={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],area:[1,\"<map>\",\"</map>\"],_default:[0,\"\",\"\"]},bA=bk(e),bB=bA.appendChild(e.createElement(\"div\"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,\"X<div>\",\"</div>\"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,\"body\")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),\"before\",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),\"after\",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName(\"*\")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName(\"*\"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,\"\"):b;if(typeof a==\"string\"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(bo,\"<$1></$2>\");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName(\"*\")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),\"replaceWith\",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!=\"string\"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j==\"string\"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,\"tr\");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],\"table\")?bC(this[i],\"tbody\"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0}):p.error(\"no ajax\"):p.globalEval((b.text||b.textContent||b.innerHTML||\"\").replace(by,\"\")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i==\"string\"&&i.length<512&&c===e&&i.charAt(0)===\"<\"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test(\"<\"+a.nodeName+\">\")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment==\"undefined\")b=e;for(f=0;(h=a[f])!=null;f++){typeof h==\"number\"&&(h+=\"\");if(!h)continue;if(typeof h==\"string\")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement(\"div\"),s.appendChild(l),h=h.replace(bo,\"<$1></$2>\"),i=(bp.exec(h)||[\"\",\"\"])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i===\"table\"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===\"<table>\"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],\"tbody\")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,\"input\")?bG(h):typeof h.getElementsByTagName!=\"undefined\"&&p.grep(h.getElementsByTagName(\"input\"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,\"script\")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!=\"undefined\"&&(r=p.grep(p.merge([],h.getElementsByTagName(\"script\")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \\/]([\\w.]+)/.exec(a)||/(webkit)[ \\/]([\\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec(a)||/(msie) ([\\w.]+)/.exec(a)||a.indexOf(\"compatible\")<0&&/(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(a)||[];return{browser:b[1]||\"\",version:b[2]||\"0\"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\\([^)]*\\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp(\"^(\"+q+\")(.*)$\",\"i\"),bQ=new RegExp(\"^(\"+q+\")(?!px)[a-z%]+$\",\"i\"),bR=new RegExp(\"^([-+])=(\"+q+\")\",\"i\"),bS={},bT={position:\"absolute\",visibility:\"hidden\",display:\"block\"},bU={letterSpacing:0,fontWeight:400},bV=[\"Top\",\"Right\",\"Bottom\",\"Left\"],bW=[\"Webkit\",\"O\",\"Moz\",\"ms\"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a==\"boolean\";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,\"opacity\");return c===\"\"?\"1\":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":p.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&\"get\"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g===\"string\"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g=\"number\");if(d==null||g===\"number\"&&isNaN(d))return;g===\"number\"&&!p.cssNumber[i]&&(d+=\"px\");if(!h||!(\"set\"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&\"get\"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f===\"normal\"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===\"\"&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b===\"fontSize\"?\"1em\":e,e=f.pixelLeft+\"px\",f.left=c,d&&(a.runtimeStyle.left=d)),e===\"\"?\"auto\":e}),p.each([\"height\",\"width\"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,\"display\"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,\"boxSizing\")===\"border-box\"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||\"\")?.01*parseFloat(RegExp.$1)+\"\":b?\"1\":\"\"},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?\"alpha(opacity=\"+b*100+\")\":\"\",f=d&&d.filter||c.filter||\"\";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,\"\"))===\"\"&&c.removeAttribute){c.removeAttribute(\"filter\");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+\" \"+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:\"inline-block\"},function(){if(b)return bH(a,\"marginRight\")})}}),!p.support.pixelPosition&&p.fn.position&&p.each([\"top\",\"left\"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+\"px\":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,\"display\"))===\"none\"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c==\"string\"?c.split(\" \"):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\\[\\]$/,cf=/\\r?\\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,\"\\r\\n\")}}):{name:b.name,value:c.replace(cf,\"\\r\\n\")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?\"\":b,e[e.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join(\"&\").replace(cd,\"+\")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,cn=/^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\\/\\//,cq=/\\?/,cr=/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=[\"*/\"]+[\"*\"];try{ck=f.href}catch(cy){ck=e.createElement(\"a\"),ck.href=\"\",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!=\"string\"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(\" \");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c==\"object\"&&(f=\"POST\"),p.ajax({url:a,type:f,dataType:\"html\",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p(\"<div>\").append(a.replace(cr,\"\")).find(e):a)}),this},p.each(\"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split(\" \"),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each([\"get\",\"post\"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,\"script\")},getJSON:function(a,b,c){return p.get(a,b,c,\"json\")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:\"GET\",contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",processData:!0,async:!0,accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",text:\"text/plain\",json:\"application/json, text/javascript\",\"*\":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\"},converters:{\"* text\":a.String,\"text html\":!0,\"text json\":p.parseJSON,\"text xml\":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||\"\",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader(\"Last-Modified\"),w&&(p.lastModified[d]=w),w=x.getResponseHeader(\"Etag\"),w&&(p.etag[d]=w)),a===304?(y=\"notmodified\",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y=\"error\",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+\"\",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger(\"ajax\"+(k?\"Success\":\"Error\"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger(\"ajaxComplete\",[x,l]),--p.active||p.event.trigger(\"ajaxStop\"))}typeof a==\"object\"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks(\"once memory\"),r=l.statusCode||{},t={},u={},v=0,w=\"canceled\",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+\"\").replace(cl,\"\").replace(cp,cj[1]+\"//\"),l.dataTypes=p.trim(l.dataType||\"*\").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(\":\")+(i[3]?\"\":i[1]===\"http:\"?80:443)!==cj.join(\":\")+(cj[3]?\"\":cj[1]===\"http:\"?80:443)),l.data&&l.processData&&typeof l.data!=\"string\"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger(\"ajaxStart\");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?\"&\":\"?\")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,\"$1_=\"+z);l.url=A+(A===l.url?(cq.test(l.url)?\"&\":\"?\")+\"_=\"+z:\"\")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader(\"Content-Type\",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader(\"If-Modified-Since\",p.lastModified[d]),p.etag[d]&&x.setRequestHeader(\"If-None-Match\",p.etag[d])),x.setRequestHeader(\"Accept\",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!==\"*\"?\", \"+cx+\"; q=0.01\":\"\"):l.accepts[\"*\"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w=\"abort\";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,\"No Transport\");else{x.readyState=1,j&&n.trigger(\"ajaxSend\",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort(\"timeout\")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\\?/,cG=/(=)\\?(?=&|$)|\\?\\?/,cH=p.now();p.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var a=cE.pop()||p.expando+\"_\"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter(\"json jsonp\",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i==\"string\"&&!(c.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&cG.test(i);if(c.dataTypes[0]===\"jsonp\"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,\"$1\"+f):m?c.data=i.replace(cG,\"$1\"+f):k&&(c.url+=(cF.test(j)?\"&\":\"?\")+c.jsonp+\"=\"+f),c.converters[\"script json\"]=function(){return h||p.error(f+\" was not called\"),h[0]},c.dataTypes[0]=\"json\",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),\"script\"}),p.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/javascript|ecmascript/},converters:{\"text script\":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter(\"script\",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\",a.global=!1)}),p.ajaxTransport(\"script\",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName(\"head\")[0]||e.documentElement;return{send:function(f,g){c=e.createElement(\"script\"),c.async=\"async\",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,\"success\")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&\"withCredentials\"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e[\"X-Requested-With\"]&&(e[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=\"\"}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp(\"^(?:([-+])=|)(\"+q+\")([a-z%]*)$\",\"i\"),cR=/queueHooks$/,cS=[cY],cT={\"*\":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?\"\":\"px\");if(d!==\"px\"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||\".5\",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=[\"*\"]):a=a.split(\" \");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||\"swing\",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?\"\":\"px\")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,\"\"),!b||b===\"auto\"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each([\"toggle\",\"show\",\"hide\"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d==\"boolean\"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!=\"string\"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||\"fx\",[]),this.each(function(){var b=!0,c=a!=null&&a+\"queueHooks\",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$(\"show\"),slideUp:c$(\"hide\"),slideToggle:c$(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a==\"object\"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration==\"number\"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue=\"fx\";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!=\"undefined\"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,\"marginTop\"))||0,c+=parseFloat(p.css(a,\"marginLeft\"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,\"position\");d===\"static\"&&(a.style.position=\"relative\");var e=p(a),f=e.offset(),g=p.css(a,\"top\"),h=p.css(a,\"left\"),i=(d===\"absolute\"||d===\"fixed\")&&p.inArray(\"auto\",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),\"using\"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,\"marginTop\"))||0,c.left-=parseFloat(p.css(a,\"marginLeft\"))||0,d.top+=parseFloat(p.css(b[0],\"borderTopWidth\"))||0,d.left+=parseFloat(p.css(b[0],\"borderLeftWidth\"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,\"position\")===\"static\")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:\"height\",Width:\"width\"},function(a,c){p.each({padding:\"inner\"+a,content:c,\"\":\"outer\"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!=\"boolean\"),h=d||(e===!0||f===!0?\"margin\":\"border\");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement[\"client\"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body[\"scroll\"+a],f[\"scroll\"+a],c.body[\"offset\"+a],f[\"offset\"+a],f[\"client\"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define==\"function\"&&define.amd&&define.amd.jQuery&&define(\"jquery\",[],function(){return p})})(window);"
  },
  {
    "path": "cmd/present/static/notes.css",
    "content": "p {\n  margin: 10px;\n}\n\n#presenter-slides {\n  display: block;\n  margin-top: -10px;\n  margin-left: -17px;\n  position: fixed;\n  border: 0;\n  width: 146%;\n  height: 750px;\n\n  transform: scale(0.7, 0.7);\n  transform-origin: top left;\n  -moz-transform: scale(0.7);\n  -moz-transform-origin: top left;\n  -o-transform: scale(0.7);\n  -o-transform-origin: top left;\n  -webkit-transform: scale(0.7);\n  -webkit-transform-origin: top left;\n}\n\n#presenter-notes {\n  margin-top: -180px;\n  font-family: 'Open Sans', Arial, sans-serif;\n  height: 30%;\n  width: 100%;\n  overflow: scroll;\n  position: fixed;\n  top: 706px;\n}\n"
  },
  {
    "path": "cmd/present/static/notes.js",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Store child window object which will display slides with notes\nvar notesWindow = null;\n\nvar isParentWindow = window.parent == window;\n\n// When parent window closes, clear storage and close child window\nif (isParentWindow) {\n  window.onbeforeunload = function() {\n    localStorage.clear();\n    if (notesWindow) notesWindow.close();\n  };\n}\n\nfunction toggleNotesWindow() {\n  if (!isParentWindow) return;\n  if (notesWindow) {\n    notesWindow.close();\n    notesWindow = null;\n    return;\n  }\n\n  initNotes();\n}\n\n// Create a unique key for the local storage so we don't mix the\n// destSlide of different presentations. For golang.org/issue/24688.\nfunction destSlideKey() {\n  var key = '';\n  if (notesWindow) {\n    var slides = notesWindow.document.getElementById('presenter-slides');\n    key = slides.src.split('#')[0];\n  } else {\n    key = window.location.href.split('#')[0];\n  }\n  return 'destSlide:' + key;\n}\n\nfunction initNotes() {\n  notesWindow = window.open('', '', 'width=1000,height=700');\n  var w = notesWindow;\n  var slidesUrl = window.location.href;\n\n  // Hack to apply css. Requires existing html on notesWindow.\n  w.document.write(\"<div style='display:none;'></div>\");\n\n  w.document.title = window.document.title;\n\n  var slides = w.document.createElement('iframe');\n  slides.id = 'presenter-slides';\n  slides.src = slidesUrl;\n  w.document.body.appendChild(slides);\n\n  var curSlide = parseInt(localStorage.getItem(destSlideKey()), 10);\n  var formattedNotes = '';\n  var section = sections[curSlide - 1];\n  // curSlide is 0 when initialized from the first page of slides.\n  // Check if section is valid before retrieving Notes.\n  if (section) {\n    formattedNotes = formatNotes(section.Notes);\n  } else if (curSlide == 0) {\n    formattedNotes = formatNotes(titleNotes);\n  }\n\n  // setTimeout needed for Firefox\n  setTimeout(function() {\n    slides.focus();\n  }, 100);\n\n  var notes = w.document.createElement('div');\n  notes.id = 'presenter-notes';\n  notes.innerHTML = formattedNotes;\n  w.document.body.appendChild(notes);\n\n  w.document.close();\n\n  function addPresenterNotesStyle() {\n    var el = w.document.createElement('link');\n    el.rel = 'stylesheet';\n    el.type = 'text/css';\n    el.href = PERMANENT_URL_PREFIX + 'notes.css';\n    w.document.body.appendChild(el);\n    w.document.querySelector('head').appendChild(el);\n  }\n\n  addPresenterNotesStyle();\n\n  // Add listener on notesWindow to update notes when triggered from\n  // parent window\n  w.addEventListener('storage', updateNotes, false);\n}\n\nfunction formatNotes(notes) {\n  var formattedNotes = '';\n  if (notes) {\n    for (var i = 0; i < notes.length; i++) {\n      formattedNotes = formattedNotes + '<p>' + notes[i] + '</p>';\n    }\n  }\n  return formattedNotes;\n}\n\nfunction updateNotes() {\n  // When triggered from parent window, notesWindow is null\n  // The storage event listener on notesWindow will update notes\n  if (!notesWindow) return;\n  var destSlide = parseInt(localStorage.getItem(destSlideKey()), 10);\n  var section = sections[destSlide - 1];\n  var el = notesWindow.document.getElementById('presenter-notes');\n\n  if (!el) return;\n\n  if (section && section.Notes) {\n    el.innerHTML = formatNotes(section.Notes);\n  } else if (destSlide == 0) {\n    el.innerHTML = formatNotes(titleNotes);\n  } else {\n    el.innerHTML = '';\n  }\n}\n\n/* Playground syncing */\n\n// When presenter notes are enabled, playground click handlers are\n// stored here to sync click events on the correct playground\nvar playgroundHandlers = { onRun: [], onKill: [], onClose: [] };\n\nfunction updatePlay(e) {\n  var i = localStorage.getItem('play-index');\n\n  switch (e.key) {\n    case 'play-index':\n      return;\n    case 'play-action':\n      // Sync 'run', 'kill', 'close' actions\n      var action = localStorage.getItem('play-action');\n      playgroundHandlers[action][i](e);\n      return;\n    case 'play-code':\n      // Sync code editing\n      var play = document.querySelectorAll('div.playground')[i];\n      play.innerHTML = localStorage.getItem('play-code');\n      return;\n    case 'output-style':\n      // Sync resizing of playground output\n      var out = document.querySelectorAll('.output')[i];\n      out.style = localStorage.getItem('output-style');\n      return;\n  }\n}\n\n// Reset 'run', 'kill', 'close' storage items when synced\n// so that successive actions can be synced correctly\nfunction updatePlayStorage(action, index, e) {\n  localStorage.setItem('play-index', index);\n\n  if (localStorage.getItem('play-action') === action) {\n    // We're the receiving window, and the message has been received\n    localStorage.removeItem('play-action');\n  } else {\n    // We're the triggering window, send the message\n    localStorage.setItem('play-action', action);\n  }\n\n  if (action === 'onRun') {\n    if (localStorage.getItem('play-shiftKey') === 'true') {\n      localStorage.removeItem('play-shiftKey');\n    } else if (e.shiftKey) {\n      localStorage.setItem('play-shiftKey', e.shiftKey);\n    }\n  }\n}\n"
  },
  {
    "path": "cmd/present/static/play.js",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nfunction initPlayground(transport) {\n  'use strict';\n\n  function text(node) {\n    var s = '';\n    for (var i = 0; i < node.childNodes.length; i++) {\n      var n = node.childNodes[i];\n      if (n.nodeType === 1) {\n        if (n.tagName === 'BUTTON') continue;\n        if (n.tagName === 'SPAN' && n.className === 'number') continue;\n        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {\n          s += '\\n';\n        }\n        s += text(n);\n        continue;\n      }\n      if (n.nodeType === 3) {\n        s += n.nodeValue;\n      }\n    }\n    return s.replace('\\xA0', ' '); // replace non-breaking spaces\n  }\n\n  // When presenter notes are enabled, the index passed\n  // here will identify the playground to be synced\n  function init(code, index) {\n    var output = document.createElement('div');\n    var outpre = document.createElement('pre');\n    var running;\n\n    if ($ && $(output).resizable) {\n      $(output).resizable({\n        handles: 'n,w,nw',\n        minHeight: 27,\n        minWidth: 135,\n        maxHeight: 608,\n        maxWidth: 990,\n      });\n    }\n\n    function onKill() {\n      if (running) running.Kill();\n      if (window.notesEnabled) updatePlayStorage('onKill', index);\n    }\n\n    function onRun(e) {\n      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';\n      if (running) running.Kill();\n      output.style.display = 'block';\n      outpre.textContent = '';\n      run1.style.display = 'none';\n      var options = { Race: sk };\n      running = transport.Run(text(code), PlaygroundOutput(outpre), options);\n      if (window.notesEnabled) updatePlayStorage('onRun', index, e);\n    }\n\n    function onClose() {\n      if (running) running.Kill();\n      output.style.display = 'none';\n      run1.style.display = 'inline-block';\n      if (window.notesEnabled) updatePlayStorage('onClose', index);\n    }\n\n    if (window.notesEnabled) {\n      playgroundHandlers.onRun.push(onRun);\n      playgroundHandlers.onClose.push(onClose);\n      playgroundHandlers.onKill.push(onKill);\n    }\n\n    var run1 = document.createElement('button');\n    run1.textContent = 'Run';\n    run1.className = 'run';\n    run1.addEventListener('click', onRun, false);\n    var run2 = document.createElement('button');\n    run2.className = 'run';\n    run2.textContent = 'Run';\n    run2.addEventListener('click', onRun, false);\n    var kill = document.createElement('button');\n    kill.className = 'kill';\n    kill.textContent = 'Kill';\n    kill.addEventListener('click', onKill, false);\n    var close = document.createElement('button');\n    close.className = 'close';\n    close.textContent = 'Close';\n    close.addEventListener('click', onClose, false);\n\n    var button = document.createElement('div');\n    button.classList.add('buttons');\n    button.appendChild(run1);\n    // Hack to simulate insertAfter\n    code.parentNode.insertBefore(button, code.nextSibling);\n\n    var buttons = document.createElement('div');\n    buttons.classList.add('buttons');\n    buttons.appendChild(run2);\n    buttons.appendChild(kill);\n    buttons.appendChild(close);\n\n    output.classList.add('output');\n    output.appendChild(buttons);\n    output.appendChild(outpre);\n    output.style.display = 'none';\n    code.parentNode.insertBefore(output, button.nextSibling);\n  }\n\n  var play = document.querySelectorAll('div.playground');\n  for (var i = 0; i < play.length; i++) {\n    init(play[i], i);\n  }\n}\n"
  },
  {
    "path": "cmd/present/static/playground.js",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nIn the absence of any formal way to specify interfaces in JavaScript,\nhere's a skeleton implementation of a playground transport.\n\n        function Transport() {\n                // Set up any transport state (eg, make a websocket connection).\n                return {\n                        Run: function(body, output, options) {\n                                // Compile and run the program 'body' with 'options'.\n\t\t\t\t// Call the 'output' callback to display program output.\n                                return {\n                                        Kill: function() {\n                                                // Kill the running program.\n                                        }\n                                };\n                        }\n                };\n        }\n\n\t// The output callback is called multiple times, and each time it is\n\t// passed an object of this form.\n        var write = {\n                Kind: 'string', // 'start', 'stdout', 'stderr', 'end'\n                Body: 'string'  // content of write or end status message\n        }\n\n\t// The first call must be of Kind 'start' with no body.\n\t// Subsequent calls may be of Kind 'stdout' or 'stderr'\n\t// and must have a non-null Body string.\n\t// The final call should be of Kind 'end' with an optional\n\t// Body string, signifying a failure (\"killed\", for example).\n\n\t// The output callback must be of this form.\n\t// See PlaygroundOutput (below) for an implementation.\n        function outputCallback(write) {\n        }\n*/\n\n// HTTPTransport is the default transport.\n// enableVet enables running vet if a program was compiled and ran successfully.\n// If vet returned any errors, display them before the output of a program.\nfunction HTTPTransport(enableVet) {\n  'use strict';\n\n  function playback(output, data) {\n    // Backwards compatibility: default values do not affect the output.\n    var events = data.Events || [];\n    var errors = data.Errors || '';\n    var status = data.Status || 0;\n    var isTest = data.IsTest || false;\n    var testsFailed = data.TestsFailed || 0;\n\n    var timeout;\n    output({ Kind: 'start' });\n    function next() {\n      if (!events || events.length === 0) {\n        if (isTest) {\n          if (testsFailed > 0) {\n            output({\n              Kind: 'system',\n              Body:\n                '\\n' +\n                testsFailed +\n                ' test' +\n                (testsFailed > 1 ? 's' : '') +\n                ' failed.',\n            });\n          } else {\n            output({ Kind: 'system', Body: '\\nAll tests passed.' });\n          }\n        } else {\n          if (status > 0) {\n            output({ Kind: 'end', Body: 'status ' + status + '.' });\n          } else {\n            if (errors !== '') {\n              // errors are displayed only in the case of timeout.\n              output({ Kind: 'end', Body: errors + '.' });\n            } else {\n              output({ Kind: 'end' });\n            }\n          }\n        }\n        return;\n      }\n      var e = events.shift();\n      if (e.Delay === 0) {\n        output({ Kind: e.Kind, Body: e.Message });\n        next();\n        return;\n      }\n      timeout = setTimeout(function() {\n        output({ Kind: e.Kind, Body: e.Message });\n        next();\n      }, e.Delay / 1000000);\n    }\n    next();\n    return {\n      Stop: function() {\n        clearTimeout(timeout);\n      },\n    };\n  }\n\n  function error(output, msg) {\n    output({ Kind: 'start' });\n    output({ Kind: 'stderr', Body: msg });\n    output({ Kind: 'end' });\n  }\n\n  function buildFailed(output, msg) {\n    output({ Kind: 'start' });\n    output({ Kind: 'stderr', Body: msg });\n    output({ Kind: 'system', Body: '\\nGo build failed.' });\n  }\n\n  var seq = 0;\n  return {\n    Run: function(body, output, options) {\n      seq++;\n      var cur = seq;\n      var playing;\n      $.ajax('/compile', {\n        type: 'POST',\n        data: { version: 2, body: body, withVet: enableVet },\n        dataType: 'json',\n        success: function(data) {\n          if (seq != cur) return;\n          if (!data) return;\n          if (playing != null) playing.Stop();\n          if (data.Errors) {\n            if (data.Errors === 'process took too long') {\n              // Playback the output that was captured before the timeout.\n              playing = playback(output, data);\n            } else {\n              buildFailed(output, data.Errors);\n            }\n            return;\n          }\n          if (!data.Events) {\n            data.Events = [];\n          }\n          if (data.VetErrors) {\n            // Inject errors from the vet as the first events in the output.\n            data.Events.unshift({\n              Message: 'Go vet exited.\\n\\n',\n              Kind: 'system',\n              Delay: 0,\n            });\n            data.Events.unshift({\n              Message: data.VetErrors,\n              Kind: 'stderr',\n              Delay: 0,\n            });\n          }\n\n          if (!enableVet || data.VetOK || data.VetErrors) {\n            playing = playback(output, data);\n            return;\n          }\n\n          // In case the server support doesn't support\n          // compile+vet in same request signaled by the\n          // 'withVet' parameter above, also try the old way.\n          // TODO: remove this when it falls out of use.\n          // It is 2019-05-13 now.\n          $.ajax('/vet', {\n            data: { body: body },\n            type: 'POST',\n            dataType: 'json',\n            success: function(dataVet) {\n              if (dataVet.Errors) {\n                // inject errors from the vet as the first events in the output\n                data.Events.unshift({\n                  Message: 'Go vet exited.\\n\\n',\n                  Kind: 'system',\n                  Delay: 0,\n                });\n                data.Events.unshift({\n                  Message: dataVet.Errors,\n                  Kind: 'stderr',\n                  Delay: 0,\n                });\n              }\n              playing = playback(output, data);\n            },\n            error: function() {\n              playing = playback(output, data);\n            },\n          });\n        },\n        error: function() {\n          error(output, 'Error communicating with remote server.');\n        },\n      });\n      return {\n        Kill: function() {\n          if (playing != null) playing.Stop();\n          output({ Kind: 'end', Body: 'killed' });\n        },\n      };\n    },\n  };\n}\n\nfunction SocketTransport() {\n  'use strict';\n\n  var id = 0;\n  var outputs = {};\n  var started = {};\n  var websocket;\n  if (window.location.protocol == 'http:') {\n    websocket = new WebSocket('ws://' + window.location.host + '/socket');\n  } else if (window.location.protocol == 'https:') {\n    websocket = new WebSocket('wss://' + window.location.host + '/socket');\n  }\n\n  websocket.onclose = function() {\n    console.log('websocket connection closed');\n  };\n\n  websocket.onmessage = function(e) {\n    var m = JSON.parse(e.data);\n    var output = outputs[m.Id];\n    if (output === null) return;\n    if (!started[m.Id]) {\n      output({ Kind: 'start' });\n      started[m.Id] = true;\n    }\n    output({ Kind: m.Kind, Body: m.Body });\n  };\n\n  function send(m) {\n    websocket.send(JSON.stringify(m));\n  }\n\n  return {\n    Run: function(body, output, options) {\n      var thisID = id + '';\n      id++;\n      outputs[thisID] = output;\n      send({ Id: thisID, Kind: 'run', Body: body, Options: options });\n      return {\n        Kill: function() {\n          send({ Id: thisID, Kind: 'kill' });\n        },\n      };\n    },\n  };\n}\n\nfunction PlaygroundOutput(el) {\n  'use strict';\n\n  return function(write) {\n    if (write.Kind == 'start') {\n      el.innerHTML = '';\n      return;\n    }\n\n    var cl = 'system';\n    if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind;\n\n    var m = write.Body;\n    if (write.Kind == 'end') {\n      m = '\\nProgram exited' + (m ? ': ' + m : '.');\n    }\n\n    if (m.indexOf('IMAGE:') === 0) {\n      // TODO(adg): buffer all writes before creating image\n      var url = 'data:image/png;base64,' + m.substr(6);\n      var img = document.createElement('img');\n      img.src = url;\n      el.appendChild(img);\n      return;\n    }\n\n    // ^L clears the screen.\n    var s = m.split('\\x0c');\n    if (s.length > 1) {\n      el.innerHTML = '';\n      m = s.pop();\n    }\n\n    m = m.replace(/&/g, '&amp;');\n    m = m.replace(/</g, '&lt;');\n    m = m.replace(/>/g, '&gt;');\n\n    var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight;\n\n    var span = document.createElement('span');\n    span.className = cl;\n    span.innerHTML = m;\n    el.appendChild(span);\n\n    if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight;\n  };\n}\n\n(function() {\n  function lineHighlight(error) {\n    var regex = /prog.go:([0-9]+)/g;\n    var r = regex.exec(error);\n    while (r) {\n      $('.lines div')\n        .eq(r[1] - 1)\n        .addClass('lineerror');\n      r = regex.exec(error);\n    }\n  }\n  function highlightOutput(wrappedOutput) {\n    return function(write) {\n      if (write.Body) lineHighlight(write.Body);\n      wrappedOutput(write);\n    };\n  }\n  function lineClear() {\n    $('.lineerror').removeClass('lineerror');\n  }\n\n  // opts is an object with these keys\n  //  codeEl - code editor element\n  //  outputEl - program output element\n  //  runEl - run button element\n  //  fmtEl - fmt button element (optional)\n  //  fmtImportEl - fmt \"imports\" checkbox element (optional)\n  //  shareEl - share button element (optional)\n  //  shareURLEl - share URL text input element (optional)\n  //  shareRedirect - base URL to redirect to on share (optional)\n  //  toysEl - toys select element (optional)\n  //  enableHistory - enable using HTML5 history API (optional)\n  //  transport - playground transport to use (default is HTTPTransport)\n  //  enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false)\n  //  enableVet - enable running vet and displaying its errors\n  function playground(opts) {\n    var code = $(opts.codeEl);\n    var transport = opts['transport'] || new HTTPTransport(opts['enableVet']);\n    var running;\n\n    // autoindent helpers.\n    function insertTabs(n) {\n      // find the selection start and end\n      var start = code[0].selectionStart;\n      var end = code[0].selectionEnd;\n      // split the textarea content into two, and insert n tabs\n      var v = code[0].value;\n      var u = v.substr(0, start);\n      for (var i = 0; i < n; i++) {\n        u += '\\t';\n      }\n      u += v.substr(end);\n      // set revised content\n      code[0].value = u;\n      // reset caret position after inserted tabs\n      code[0].selectionStart = start + n;\n      code[0].selectionEnd = start + n;\n    }\n    function autoindent(el) {\n      var curpos = el.selectionStart;\n      var tabs = 0;\n      while (curpos > 0) {\n        curpos--;\n        if (el.value[curpos] == '\\t') {\n          tabs++;\n        } else if (tabs > 0 || el.value[curpos] == '\\n') {\n          break;\n        }\n      }\n      setTimeout(function() {\n        insertTabs(tabs);\n      }, 1);\n    }\n\n    // NOTE(cbro): e is a jQuery event, not a DOM event.\n    function handleSaveShortcut(e) {\n      if (e.isDefaultPrevented()) return false;\n      if (!e.metaKey && !e.ctrlKey) return false;\n      if (e.key != 'S' && e.key != 's') return false;\n\n      e.preventDefault();\n\n      // Share and save\n      share(function(url) {\n        window.location.href = url + '.go?download=true';\n      });\n\n      return true;\n    }\n\n    function keyHandler(e) {\n      if (opts.enableShortcuts && handleSaveShortcut(e)) return;\n\n      if (e.keyCode == 9 && !e.ctrlKey) {\n        // tab (but not ctrl-tab)\n        insertTabs(1);\n        e.preventDefault();\n        return false;\n      }\n      if (e.keyCode == 13) {\n        // enter\n        if (e.shiftKey) {\n          // +shift\n          run();\n          e.preventDefault();\n          return false;\n        }\n        if (e.ctrlKey) {\n          // +control\n          fmt();\n          e.preventDefault();\n        } else {\n          autoindent(e.target);\n        }\n      }\n      return true;\n    }\n    code.unbind('keydown').bind('keydown', keyHandler);\n    var outdiv = $(opts.outputEl).empty();\n    var output = $('<pre/>').appendTo(outdiv);\n\n    function body() {\n      return $(opts.codeEl).val();\n    }\n    function setBody(text) {\n      $(opts.codeEl).val(text);\n    }\n    function origin(href) {\n      return ('' + href)\n        .split('/')\n        .slice(0, 3)\n        .join('/');\n    }\n\n    var pushedEmpty = window.location.pathname == '/';\n    function inputChanged() {\n      if (pushedEmpty) {\n        return;\n      }\n      pushedEmpty = true;\n      $(opts.shareURLEl).hide();\n      window.history.pushState(null, '', '/');\n    }\n    function popState(e) {\n      if (e === null) {\n        return;\n      }\n      if (e && e.state && e.state.code) {\n        setBody(e.state.code);\n      }\n    }\n    var rewriteHistory = false;\n    if (\n      window.history &&\n      window.history.pushState &&\n      window.addEventListener &&\n      opts.enableHistory\n    ) {\n      rewriteHistory = true;\n      code[0].addEventListener('input', inputChanged);\n      window.addEventListener('popstate', popState);\n    }\n\n    function setError(error) {\n      if (running) running.Kill();\n      lineClear();\n      lineHighlight(error);\n      output\n        .empty()\n        .addClass('error')\n        .text(error);\n    }\n    function loading() {\n      lineClear();\n      if (running) running.Kill();\n      output.removeClass('error').text('Waiting for remote server...');\n    }\n    function run() {\n      loading();\n      running = transport.Run(\n        body(),\n        highlightOutput(PlaygroundOutput(output[0]))\n      );\n    }\n\n    function fmt() {\n      loading();\n      var data = { body: body() };\n      if ($(opts.fmtImportEl).is(':checked')) {\n        data['imports'] = 'true';\n      }\n      $.ajax('/fmt', {\n        data: data,\n        type: 'POST',\n        dataType: 'json',\n        success: function(data) {\n          if (data.Error) {\n            setError(data.Error);\n          } else {\n            setBody(data.Body);\n            setError('');\n          }\n        },\n      });\n    }\n\n    var shareURL; // jQuery element to show the shared URL.\n    var sharing = false; // true if there is a pending request.\n    var shareCallbacks = [];\n    function share(opt_callback) {\n      if (opt_callback) shareCallbacks.push(opt_callback);\n\n      if (sharing) return;\n      sharing = true;\n\n      var sharingData = body();\n      $.ajax('https://play.golang.org/share', {\n        processData: false,\n        data: sharingData,\n        type: 'POST',\n        contentType: 'text/plain; charset=utf-8',\n        complete: function(xhr) {\n          sharing = false;\n          if (xhr.status != 200) {\n            alert('Server error; try again.');\n            return;\n          }\n          if (opts.shareRedirect) {\n            window.location = opts.shareRedirect + xhr.responseText;\n          }\n          var path = '/p/' + xhr.responseText;\n          var url = origin(window.location) + path;\n\n          for (var i = 0; i < shareCallbacks.length; i++) {\n            shareCallbacks[i](url);\n          }\n          shareCallbacks = [];\n\n          if (shareURL) {\n            shareURL\n              .show()\n              .val(url)\n              .focus()\n              .select();\n\n            if (rewriteHistory) {\n              var historyData = { code: sharingData };\n              window.history.pushState(historyData, '', path);\n              pushedEmpty = false;\n            }\n          }\n        },\n      });\n    }\n\n    $(opts.runEl).click(run);\n    $(opts.fmtEl).click(fmt);\n\n    if (\n      opts.shareEl !== null &&\n      (opts.shareURLEl !== null || opts.shareRedirect !== null)\n    ) {\n      if (opts.shareURLEl) {\n        shareURL = $(opts.shareURLEl).hide();\n      }\n      $(opts.shareEl).click(function() {\n        share();\n      });\n    }\n\n    if (opts.toysEl !== null) {\n      $(opts.toysEl).bind('change', function() {\n        var toy = $(this).val();\n        $.ajax('/doc/play/' + toy, {\n          processData: false,\n          type: 'GET',\n          complete: function(xhr) {\n            if (xhr.status != 200) {\n              alert('Server error; try again.');\n              return;\n            }\n            setBody(xhr.responseText);\n          },\n        });\n      });\n    }\n  }\n\n  window.playground = playground;\n})();\n"
  },
  {
    "path": "cmd/present/static/slides.js",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nvar PERMANENT_URL_PREFIX = '/static/';\n\nvar SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];\n\nvar PM_TOUCH_SENSITIVITY = 15;\n\nvar curSlide;\n\n/* ---------------------------------------------------------------------- */\n/* classList polyfill by Eli Grey\n * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */\n\nif (\n  typeof document !== 'undefined' &&\n  !('classList' in document.createElement('a'))\n) {\n  (function(view) {\n    var classListProp = 'classList',\n      protoProp = 'prototype',\n      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],\n      objCtr = Object;\n    (strTrim =\n      String[protoProp].trim ||\n      function() {\n        return this.replace(/^\\s+|\\s+$/g, '');\n      }),\n      (arrIndexOf =\n        Array[protoProp].indexOf ||\n        function(item) {\n          for (var i = 0, len = this.length; i < len; i++) {\n            if (i in this && this[i] === item) {\n              return i;\n            }\n          }\n          return -1;\n        }),\n      // Vendors: please allow content code to instantiate DOMExceptions\n      (DOMEx = function(type, message) {\n        this.name = type;\n        this.code = DOMException[type];\n        this.message = message;\n      }),\n      (checkTokenAndGetIndex = function(classList, token) {\n        if (token === '') {\n          throw new DOMEx(\n            'SYNTAX_ERR',\n            'An invalid or illegal string was specified'\n          );\n        }\n        if (/\\s/.test(token)) {\n          throw new DOMEx(\n            'INVALID_CHARACTER_ERR',\n            'String contains an invalid character'\n          );\n        }\n        return arrIndexOf.call(classList, token);\n      }),\n      (ClassList = function(elem) {\n        var trimmedClasses = strTrim.call(elem.className),\n          classes = trimmedClasses ? trimmedClasses.split(/\\s+/) : [];\n        for (var i = 0, len = classes.length; i < len; i++) {\n          this.push(classes[i]);\n        }\n        this._updateClassName = function() {\n          elem.className = this.toString();\n        };\n      }),\n      (classListProto = ClassList[protoProp] = []),\n      (classListGetter = function() {\n        return new ClassList(this);\n      });\n    // Most DOMException implementations don't allow calling DOMException's toString()\n    // on non-DOMExceptions. Error's toString() is sufficient here.\n    DOMEx[protoProp] = Error[protoProp];\n    classListProto.item = function(i) {\n      return this[i] || null;\n    };\n    classListProto.contains = function(token) {\n      token += '';\n      return checkTokenAndGetIndex(this, token) !== -1;\n    };\n    classListProto.add = function(token) {\n      token += '';\n      if (checkTokenAndGetIndex(this, token) === -1) {\n        this.push(token);\n        this._updateClassName();\n      }\n    };\n    classListProto.remove = function(token) {\n      token += '';\n      var index = checkTokenAndGetIndex(this, token);\n      if (index !== -1) {\n        this.splice(index, 1);\n        this._updateClassName();\n      }\n    };\n    classListProto.toggle = function(token) {\n      token += '';\n      if (checkTokenAndGetIndex(this, token) === -1) {\n        this.add(token);\n      } else {\n        this.remove(token);\n      }\n    };\n    classListProto.toString = function() {\n      return this.join(' ');\n    };\n\n    if (objCtr.defineProperty) {\n      var classListPropDesc = {\n        get: classListGetter,\n        enumerable: true,\n        configurable: true,\n      };\n      try {\n        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);\n      } catch (ex) {\n        // IE 8 doesn't support enumerable:true\n        if (ex.number === -0x7ff5ec54) {\n          classListPropDesc.enumerable = false;\n          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);\n        }\n      }\n    } else if (objCtr[protoProp].__defineGetter__) {\n      elemCtrProto.__defineGetter__(classListProp, classListGetter);\n    }\n  })(self);\n}\n/* ---------------------------------------------------------------------- */\n\n/* Slide movement */\n\nfunction hideHelpText() {\n  document.getElementById('help').style.display = 'none';\n}\n\nfunction getSlideEl(no) {\n  if (no < 0 || no >= slideEls.length) {\n    return null;\n  } else {\n    return slideEls[no];\n  }\n}\n\nfunction updateSlideClass(slideNo, className) {\n  var el = getSlideEl(slideNo);\n\n  if (!el) {\n    return;\n  }\n\n  if (className) {\n    el.classList.add(className);\n  }\n\n  for (var i in SLIDE_CLASSES) {\n    if (className != SLIDE_CLASSES[i]) {\n      el.classList.remove(SLIDE_CLASSES[i]);\n    }\n  }\n}\n\nfunction updateSlides() {\n  if (window.trackPageview) window.trackPageview();\n\n  for (var i = 0; i < slideEls.length; i++) {\n    switch (i) {\n      case curSlide - 2:\n        updateSlideClass(i, 'far-past');\n        break;\n      case curSlide - 1:\n        updateSlideClass(i, 'past');\n        break;\n      case curSlide:\n        updateSlideClass(i, 'current');\n        break;\n      case curSlide + 1:\n        updateSlideClass(i, 'next');\n        break;\n      case curSlide + 2:\n        updateSlideClass(i, 'far-next');\n        break;\n      default:\n        updateSlideClass(i);\n        break;\n    }\n  }\n\n  triggerLeaveEvent(curSlide - 1);\n  triggerEnterEvent(curSlide);\n\n  window.setTimeout(function() {\n    // Hide after the slide\n    disableSlideFrames(curSlide - 2);\n  }, 301);\n\n  enableSlideFrames(curSlide - 1);\n  enableSlideFrames(curSlide + 2);\n\n  updateHash();\n}\n\nfunction prevSlide() {\n  hideHelpText();\n  if (curSlide > 0) {\n    curSlide--;\n\n    updateSlides();\n  }\n\n  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);\n}\n\nfunction nextSlide() {\n  hideHelpText();\n  if (curSlide < slideEls.length - 1) {\n    curSlide++;\n\n    updateSlides();\n  }\n\n  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);\n}\n\n/* Slide events */\n\nfunction triggerEnterEvent(no) {\n  var el = getSlideEl(no);\n  if (!el) {\n    return;\n  }\n\n  var onEnter = el.getAttribute('onslideenter');\n  if (onEnter) {\n    new Function(onEnter).call(el);\n  }\n\n  var evt = document.createEvent('Event');\n  evt.initEvent('slideenter', true, true);\n  evt.slideNumber = no + 1; // Make it readable\n\n  el.dispatchEvent(evt);\n}\n\nfunction triggerLeaveEvent(no) {\n  var el = getSlideEl(no);\n  if (!el) {\n    return;\n  }\n\n  var onLeave = el.getAttribute('onslideleave');\n  if (onLeave) {\n    new Function(onLeave).call(el);\n  }\n\n  var evt = document.createEvent('Event');\n  evt.initEvent('slideleave', true, true);\n  evt.slideNumber = no + 1; // Make it readable\n\n  el.dispatchEvent(evt);\n}\n\n/* Touch events */\n\nfunction handleTouchStart(event) {\n  if (event.touches.length == 1) {\n    touchDX = 0;\n    touchDY = 0;\n\n    touchStartX = event.touches[0].pageX;\n    touchStartY = event.touches[0].pageY;\n\n    document.body.addEventListener('touchmove', handleTouchMove, true);\n    document.body.addEventListener('touchend', handleTouchEnd, true);\n  }\n}\n\nfunction handleTouchMove(event) {\n  if (event.touches.length > 1) {\n    cancelTouch();\n  } else {\n    touchDX = event.touches[0].pageX - touchStartX;\n    touchDY = event.touches[0].pageY - touchStartY;\n    event.preventDefault();\n  }\n}\n\nfunction handleTouchEnd(event) {\n  var dx = Math.abs(touchDX);\n  var dy = Math.abs(touchDY);\n\n  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {\n    if (touchDX > 0) {\n      prevSlide();\n    } else {\n      nextSlide();\n    }\n  }\n\n  cancelTouch();\n}\n\nfunction cancelTouch() {\n  document.body.removeEventListener('touchmove', handleTouchMove, true);\n  document.body.removeEventListener('touchend', handleTouchEnd, true);\n}\n\n/* Preloading frames */\n\nfunction disableSlideFrames(no) {\n  var el = getSlideEl(no);\n  if (!el) {\n    return;\n  }\n\n  var frames = el.getElementsByTagName('iframe');\n  for (var i = 0, frame; (frame = frames[i]); i++) {\n    disableFrame(frame);\n  }\n}\n\nfunction enableSlideFrames(no) {\n  var el = getSlideEl(no);\n  if (!el) {\n    return;\n  }\n\n  var frames = el.getElementsByTagName('iframe');\n  for (var i = 0, frame; (frame = frames[i]); i++) {\n    enableFrame(frame);\n  }\n}\n\nfunction disableFrame(frame) {\n  frame.src = 'about:blank';\n}\n\nfunction enableFrame(frame) {\n  var src = frame._src;\n\n  if (frame.src != src && src != 'about:blank') {\n    frame.src = src;\n  }\n}\n\nfunction setupFrames() {\n  var frames = document.querySelectorAll('iframe');\n  for (var i = 0, frame; (frame = frames[i]); i++) {\n    frame._src = frame.src;\n    disableFrame(frame);\n  }\n\n  enableSlideFrames(curSlide);\n  enableSlideFrames(curSlide + 1);\n  enableSlideFrames(curSlide + 2);\n}\n\nfunction setupInteraction() {\n  /* Clicking and tapping */\n\n  var el = document.createElement('div');\n  el.className = 'slide-area';\n  el.id = 'prev-slide-area';\n  el.addEventListener('click', prevSlide, false);\n  document.querySelector('section.slides').appendChild(el);\n\n  var el = document.createElement('div');\n  el.className = 'slide-area';\n  el.id = 'next-slide-area';\n  el.addEventListener('click', nextSlide, false);\n  document.querySelector('section.slides').appendChild(el);\n\n  /* Swiping */\n\n  document.body.addEventListener('touchstart', handleTouchStart, false);\n}\n\n/* Hash functions */\n\nfunction getCurSlideFromHash() {\n  var slideNo = parseInt(location.hash.substr(1));\n\n  if (slideNo) {\n    curSlide = slideNo - 1;\n  } else {\n    curSlide = 0;\n  }\n}\n\nfunction updateHash() {\n  location.replace('#' + (curSlide + 1));\n}\n\n/* Event listeners */\n\nfunction handleBodyKeyDown(event) {\n  // If we're in a code element, only handle pgup/down.\n  var inCode = event.target.classList.contains('code');\n\n  switch (event.keyCode) {\n    case 78: // 'N' opens presenter notes window\n      if (!inCode && notesEnabled) toggleNotesWindow();\n      break;\n    case 72: // 'H' hides the help text\n    case 27: // escape key\n      if (!inCode) hideHelpText();\n      break;\n\n    case 39: // right arrow\n    case 13: // Enter\n    case 32: // space\n      if (inCode) break;\n    case 34: // PgDn\n      nextSlide();\n      event.preventDefault();\n      break;\n\n    case 37: // left arrow\n    case 8: // Backspace\n      if (inCode) break;\n    case 33: // PgUp\n      prevSlide();\n      event.preventDefault();\n      break;\n\n    case 40: // down arrow\n      if (inCode) break;\n      nextSlide();\n      event.preventDefault();\n      break;\n\n    case 38: // up arrow\n      if (inCode) break;\n      prevSlide();\n      event.preventDefault();\n      break;\n  }\n}\n\nfunction scaleSmallViewports() {\n  var el = document.querySelector('section.slides');\n  var transform = '';\n  var sWidthPx = 1250;\n  var sHeightPx = 750;\n  var sAspectRatio = sWidthPx / sHeightPx;\n  var wAspectRatio = window.innerWidth / window.innerHeight;\n\n  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {\n    transform = 'scale(' + window.innerWidth / sWidthPx + ')';\n  } else if (window.innerHeight < sHeightPx) {\n    transform = 'scale(' + window.innerHeight / sHeightPx + ')';\n  }\n  el.style.transform = transform;\n}\n\nfunction addEventListeners() {\n  document.addEventListener('keydown', handleBodyKeyDown, false);\n  var resizeTimeout;\n  window.addEventListener('resize', function() {\n    // throttle resize events\n    window.clearTimeout(resizeTimeout);\n    resizeTimeout = window.setTimeout(function() {\n      resizeTimeout = null;\n      scaleSmallViewports();\n    }, 50);\n  });\n\n  // Force reset transform property of section.slides when printing page.\n  // Use both onbeforeprint and matchMedia for compatibility with different browsers.\n  var beforePrint = function() {\n    var el = document.querySelector('section.slides');\n    el.style.transform = '';\n  };\n  window.onbeforeprint = beforePrint;\n  if (window.matchMedia) {\n    var mediaQueryList = window.matchMedia('print');\n    mediaQueryList.addListener(function(mql) {\n      if (mql.matches) beforePrint();\n    });\n  }\n}\n\n/* Initialization */\n\nfunction addFontStyle() {\n  var el = document.createElement('link');\n  el.rel = 'stylesheet';\n  el.type = 'text/css';\n  el.href =\n    '//fonts.googleapis.com/css?family=' +\n    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';\n\n  document.body.appendChild(el);\n}\n\nfunction addGeneralStyle() {\n  var el = document.createElement('link');\n  el.rel = 'stylesheet';\n  el.type = 'text/css';\n  el.href = PERMANENT_URL_PREFIX + 'styles.css';\n  document.body.appendChild(el);\n\n  var el = document.createElement('meta');\n  el.name = 'viewport';\n  el.content = 'width=device-width,height=device-height,initial-scale=1';\n  document.querySelector('head').appendChild(el);\n\n  var el = document.createElement('meta');\n  el.name = 'apple-mobile-web-app-capable';\n  el.content = 'yes';\n  document.querySelector('head').appendChild(el);\n\n  scaleSmallViewports();\n}\n\nfunction handleDomLoaded() {\n  slideEls = document.querySelectorAll('section.slides > article');\n\n  setupFrames();\n\n  addFontStyle();\n  addGeneralStyle();\n  addEventListeners();\n\n  updateSlides();\n\n  setupInteraction();\n\n  if (\n    window.location.hostname == 'localhost' ||\n    window.location.hostname == '127.0.0.1' ||\n    window.location.hostname == '::1'\n  ) {\n    hideHelpText();\n  }\n\n  document.body.classList.add('loaded');\n\n  setupNotesSync();\n}\n\nfunction initialize() {\n  getCurSlideFromHash();\n\n  if (window['_DEBUG']) {\n    PERMANENT_URL_PREFIX = '../';\n  }\n\n  if (window['_DCL']) {\n    handleDomLoaded();\n  } else {\n    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);\n  }\n}\n\n// If ?debug exists then load the script relative instead of absolute\nif (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {\n  document.addEventListener(\n    'DOMContentLoaded',\n    function() {\n      // Avoid missing the DomContentLoaded event\n      window['_DCL'] = true;\n    },\n    false\n  );\n\n  window['_DEBUG'] = true;\n  var script = document.createElement('script');\n  script.type = 'text/javascript';\n  script.src = '../slides.js';\n  var s = document.getElementsByTagName('script')[0];\n  s.parentNode.insertBefore(script, s);\n\n  // Remove this script\n  s.parentNode.removeChild(s);\n} else {\n  initialize();\n}\n\n/* Synchronize windows when notes are enabled */\n\nfunction setupNotesSync() {\n  if (!notesEnabled) return;\n\n  function setupPlayResizeSync() {\n    var out = document.getElementsByClassName('output');\n    for (var i = 0; i < out.length; i++) {\n      $(out[i]).bind('resize', function(event) {\n        if ($(event.target).hasClass('ui-resizable')) {\n          localStorage.setItem('play-index', i);\n          localStorage.setItem('output-style', out[i].style.cssText);\n        }\n      });\n    }\n  }\n  function setupPlayCodeSync() {\n    var play = document.querySelectorAll('div.playground');\n    for (var i = 0; i < play.length; i++) {\n      play[i].addEventListener('input', inputHandler, false);\n\n      function inputHandler(e) {\n        localStorage.setItem('play-index', i);\n        localStorage.setItem('play-code', e.target.innerHTML);\n      }\n    }\n  }\n\n  setupPlayCodeSync();\n  setupPlayResizeSync();\n  localStorage.setItem(destSlideKey(), curSlide);\n  window.addEventListener('storage', updateOtherWindow, false);\n}\n\n// An update to local storage is caught only by the other window\n// The triggering window does not handle any sync actions\nfunction updateOtherWindow(e) {\n  // Ignore remove storage events which are not meant to update the other window\n  var isRemoveStorageEvent = !e.newValue;\n  if (isRemoveStorageEvent) return;\n\n  var destSlide = localStorage.getItem(destSlideKey());\n  while (destSlide > curSlide) {\n    nextSlide();\n  }\n  while (destSlide < curSlide) {\n    prevSlide();\n  }\n\n  updatePlay(e);\n  updateNotes();\n}\n"
  },
  {
    "path": "cmd/present/static/styles.css",
    "content": "@media screen {\n  /* Framework */\n  html {\n    height: 100%;\n  }\n\n  body {\n    margin: 0;\n    padding: 0;\n\n    display: block !important;\n\n    height: 100%;\n    height: 100vh;\n\n    overflow: hidden;\n\n    background: rgb(215, 215, 215);\n    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));\n    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));\n    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));\n    background: -webkit-gradient(\n      radial,\n      50% 50%,\n      0,\n      50% 50%,\n      500,\n      from(rgb(240, 240, 240)),\n      to(rgb(190, 190, 190))\n    );\n\n    -webkit-font-smoothing: antialiased;\n  }\n\n  .slides {\n    width: 100%;\n    height: 100%;\n    left: 0;\n    top: 0;\n\n    position: absolute;\n\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n\n  .slides > article {\n    display: block;\n\n    position: absolute;\n    overflow: hidden;\n\n    width: 900px;\n    height: 700px;\n\n    left: 50%;\n    top: 50%;\n\n    margin-left: -450px;\n    margin-top: -350px;\n\n    padding: 40px 60px;\n\n    box-sizing: border-box;\n    -o-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    border-radius: 10px;\n    -o-border-radius: 10px;\n    -moz-border-radius: 10px;\n    -webkit-border-radius: 10px;\n\n    background-color: white;\n\n    border: 1px solid rgba(0, 0, 0, 0.3);\n\n    transition: transform 0.3s ease-out;\n    -o-transition: -o-transform 0.3s ease-out;\n    -moz-transition: -moz-transform 0.3s ease-out;\n    -webkit-transition: -webkit-transform 0.3s ease-out;\n  }\n  .slides.layout-widescreen > article {\n    margin-left: -550px;\n    width: 1100px;\n  }\n  .slides.layout-faux-widescreen > article {\n    margin-left: -550px;\n    width: 1100px;\n\n    padding: 40px 160px;\n  }\n\n  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),\n  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {\n    background-position-x: 0, 840px;\n  }\n\n  /* Clickable/tappable areas */\n\n  .slide-area {\n    z-index: 1000;\n\n    position: absolute;\n    left: 0;\n    top: 0;\n    width: 150px;\n    height: 700px;\n\n    left: 50%;\n    top: 50%;\n\n    cursor: pointer;\n    margin-top: -350px;\n\n    tap-highlight-color: transparent;\n    -o-tap-highlight-color: transparent;\n    -moz-tap-highlight-color: transparent;\n    -webkit-tap-highlight-color: transparent;\n  }\n  #prev-slide-area {\n    margin-left: -550px;\n  }\n  #next-slide-area {\n    margin-left: 400px;\n  }\n  .slides.layout-widescreen #prev-slide-area,\n  .slides.layout-faux-widescreen #prev-slide-area {\n    margin-left: -650px;\n  }\n  .slides.layout-widescreen #next-slide-area,\n  .slides.layout-faux-widescreen #next-slide-area {\n    margin-left: 500px;\n  }\n\n  /* Slides */\n\n  .slides > article {\n    display: none;\n  }\n  .slides > article.far-past {\n    display: block;\n    transform: translate(-2040px);\n    -o-transform: translate(-2040px);\n    -moz-transform: translate(-2040px);\n    -webkit-transform: translate3d(-2040px, 0, 0);\n  }\n  .slides > article.past {\n    display: block;\n    transform: translate(-1020px);\n    -o-transform: translate(-1020px);\n    -moz-transform: translate(-1020px);\n    -webkit-transform: translate3d(-1020px, 0, 0);\n  }\n  .slides > article.current {\n    display: block;\n    transform: translate(0);\n    -o-transform: translate(0);\n    -moz-transform: translate(0);\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n  .slides > article.next {\n    display: block;\n    transform: translate(1020px);\n    -o-transform: translate(1020px);\n    -moz-transform: translate(1020px);\n    -webkit-transform: translate3d(1020px, 0, 0);\n  }\n  .slides > article.far-next {\n    display: block;\n    transform: translate(2040px);\n    -o-transform: translate(2040px);\n    -moz-transform: translate(2040px);\n    -webkit-transform: translate3d(2040px, 0, 0);\n  }\n\n  .slides.layout-widescreen > article.far-past,\n  .slides.layout-faux-widescreen > article.far-past {\n    display: block;\n    transform: translate(-2260px);\n    -o-transform: translate(-2260px);\n    -moz-transform: translate(-2260px);\n    -webkit-transform: translate3d(-2260px, 0, 0);\n  }\n  .slides.layout-widescreen > article.past,\n  .slides.layout-faux-widescreen > article.past {\n    display: block;\n    transform: translate(-1130px);\n    -o-transform: translate(-1130px);\n    -moz-transform: translate(-1130px);\n    -webkit-transform: translate3d(-1130px, 0, 0);\n  }\n  .slides.layout-widescreen > article.current,\n  .slides.layout-faux-widescreen > article.current {\n    display: block;\n    transform: translate(0);\n    -o-transform: translate(0);\n    -moz-transform: translate(0);\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n  .slides.layout-widescreen > article.next,\n  .slides.layout-faux-widescreen > article.next {\n    display: block;\n    transform: translate(1130px);\n    -o-transform: translate(1130px);\n    -moz-transform: translate(1130px);\n    -webkit-transform: translate3d(1130px, 0, 0);\n  }\n  .slides.layout-widescreen > article.far-next,\n  .slides.layout-faux-widescreen > article.far-next {\n    display: block;\n    transform: translate(2260px);\n    -o-transform: translate(2260px);\n    -moz-transform: translate(2260px);\n    -webkit-transform: translate3d(2260px, 0, 0);\n  }\n}\n\n@media print {\n  /* Set page layout */\n  @page {\n    size: A4 landscape;\n  }\n\n  body {\n    display: block !important;\n  }\n\n  .slides > article {\n    display: block;\n\n    position: relative;\n\n    page-break-inside: never;\n    page-break-after: always;\n\n    overflow: hidden;\n  }\n\n  h2 {\n    position: static !important;\n    margin-top: 400px !important;\n    margin-bottom: 100px !important;\n  }\n\n  pre {\n    background: rgb(240, 240, 240);\n  }\n\n  /* Add explicit links */\n  a:link:after,\n  a:visited:after {\n    content: ' (' attr(href) ') ';\n    font-size: 50%;\n  }\n\n  #help {\n    display: none;\n    visibility: hidden;\n  }\n}\n\n/* Styles for slides */\n\n.slides > article {\n  font-family: 'Open Sans', Arial, sans-serif;\n\n  color: black;\n  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n\n  font-size: 26px;\n  line-height: 36px;\n\n  letter-spacing: -1px;\n}\n\nb {\n  font-weight: 600;\n}\n\na {\n  color: rgb(0, 102, 204);\n  text-decoration: none;\n}\na:visited {\n  color: rgba(0, 102, 204, 0.75);\n}\na:hover {\n  color: black;\n}\n\np {\n  margin: 0;\n  padding: 0;\n\n  margin-top: 20px;\n}\np:first-child {\n  margin-top: 0;\n}\n\nh1 {\n  font-size: 60px;\n  line-height: 60px;\n\n  padding: 0;\n  margin: 0;\n  margin-top: 200px;\n  margin-bottom: 5px;\n  padding-right: 40px;\n\n  font-weight: 600;\n\n  letter-spacing: -3px;\n\n  color: rgb(51, 51, 51);\n}\n\nh2 {\n  font-size: 45px;\n  line-height: 45px;\n\n  position: absolute;\n  bottom: 150px;\n\n  padding: 0;\n  margin: 0;\n  padding-right: 40px;\n\n  font-weight: 600;\n\n  letter-spacing: -2px;\n\n  color: rgb(51, 51, 51);\n}\n\nh3 {\n  font-size: 30px;\n  line-height: 36px;\n\n  padding: 0;\n  margin: 0;\n  padding-right: 40px;\n\n  font-weight: 600;\n\n  letter-spacing: -1px;\n\n  color: rgb(51, 51, 51);\n}\n\nul {\n  margin: 0;\n  padding: 0;\n  margin-top: 20px;\n  margin-left: 1.5em;\n}\nli {\n  padding: 0;\n  margin: 0 0 0.5em 0;\n}\n\ndiv.code, div.output {\n  margin: 0;\n  padding: 0;\n}\n\npre {\n  padding: 5px 10px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n\n  background: rgb(240, 240, 240);\n  border: 1px solid rgb(224, 224, 224);\n\n  font-family: 'Droid Sans Mono', 'Courier New', monospace;\n  font-size: 18px;\n  line-height: 24px;\n  letter-spacing: -1px;\n\n  color: black;\n}\n\npre.numbers span:before {\n  content: attr(num);\n  margin-right: 1em;\n  display: inline-block;\n}\n\ncode {\n  font-size: 95%;\n  font-family: 'Droid Sans Mono', 'Courier New', monospace;\n\n  color: black;\n}\n\npre code {\n  font-size: 100%;\n}\n\narticle > .image,\narticle > .video {\n  text-align: center;\n  margin-top: 40px;\n}\n\narticle.background {\n  background-size: contain;\n  background-repeat: round;\n}\n\ntable {\n  width: 100%;\n  border-collapse: collapse;\n  margin-top: 40px;\n}\nth {\n  font-weight: 600;\n  text-align: left;\n}\ntd,\nth {\n  border: 1px solid rgb(224, 224, 224);\n  padding: 5px 10px;\n  vertical-align: top;\n}\n\np.link {\n  margin-left: 20px;\n}\n\n.pagenumber {\n  color: #8c8c8c;\n  font-size: 75%;\n  position: absolute;\n  bottom: 0px;\n  right: 10px;\n}\n\n/* Code */\npre {\n  outline: 0px solid transparent;\n}\ndiv.playground {\n  position: relative;\n}\ndiv.output {\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  right: 40px;\n  bottom: 40px;\n  background: #202020;\n  padding: 5px 10px;\n  z-index: 2;\n\n  border-radius: 10px;\n  -o-border-radius: 10px;\n  -moz-border-radius: 10px;\n  -webkit-border-radius: 10px;\n}\ndiv.output pre {\n  margin: 0;\n  padding: 0;\n  background: none;\n  border: none;\n  width: 100%;\n  height: 100%;\n  overflow: auto;\n}\ndiv.output .stdout,\ndiv.output pre {\n  color: #e6e6e6;\n}\ndiv.output .stderr,\ndiv.output .error {\n  color: rgb(255, 200, 200);\n}\ndiv.output .system,\ndiv.output .exit {\n  color: rgb(255, 230, 120);\n}\n.buttons {\n  position: relative;\n  float: right;\n  top: -60px;\n  right: 10px;\n}\ndiv.output .buttons {\n  position: absolute;\n  float: none;\n  top: auto;\n  right: 5px;\n  bottom: 5px;\n}\n\n/* Presenter details */\n.presenter {\n  margin-top: 20px;\n}\n.presenter p,\n.presenter .link {\n  margin: 0;\n  font-size: 28px;\n  line-height: 1.2em;\n}\n\n/* Output resize details */\n.ui-resizable-handle {\n  position: absolute;\n}\n.ui-resizable-n {\n  cursor: n-resize;\n  height: 7px;\n  width: 100%;\n  top: -5px;\n  left: 0;\n}\n.ui-resizable-w {\n  cursor: w-resize;\n  width: 7px;\n  left: -5px;\n  top: 0;\n  height: 100%;\n}\n.ui-resizable-nw {\n  cursor: nw-resize;\n  width: 9px;\n  height: 9px;\n  left: -5px;\n  top: -5px;\n}\niframe {\n  border: none;\n}\nfigcaption {\n  color: #666;\n  text-align: center;\n  font-size: 0.75em;\n}\n\n#help {\n  font-family: 'Open Sans', Arial, sans-serif;\n  text-align: center;\n  color: white;\n  background: #000;\n  opacity: 0.5;\n  position: fixed;\n  bottom: 25px;\n  left: 50px;\n  right: 50px;\n  padding: 20px;\n\n  border-radius: 10px;\n  -o-border-radius: 10px;\n  -moz-border-radius: 10px;\n  -webkit-border-radius: 10px;\n}\n"
  },
  {
    "path": "cmd/present/templates/action.tmpl",
    "content": "{/*\nThis is the action template.\nIt determines how the formatting actions are rendered.\n*/}\n\n{{define \"section\"}}\n  <h{{len .Number}} id=\"TOC_{{.FormattedNumber}}\">{{.FormattedNumber}} {{.Title}}</h{{len .Number}}>\n  {{range .Elem}}{{elem $.Template .}}{{end}}\n{{end}}\n\n{{define \"list\"}}\n  <ul>\n  {{range .Bullet}}\n    <li>{{style .}}</li>\n  {{end}}\n  </ul>\n{{end}}\n\n{{define \"text\"}}\n  {{if .Pre}}\n  <div class=\"code\"><pre>{{range .Lines}}{{.}}{{end}}</pre></div>\n  {{else}}\n  <p>\n    {{range $i, $l := .Lines}}{{if $i}}{{template \"newline\"}}\n    {{end}}{{style $l}}{{end}}\n  </p>\n  {{end}}\n{{end}}\n\n{{define \"code\"}}\n  <div class=\"code{{if playable .}} playground{{end}}\" {{if .Edit}}contenteditable=\"true\" spellcheck=\"false\"{{end}}>{{.Text}}</div>\n{{end}}\n\n{{define \"image\"}}\n<div class=\"image\">\n  <img src=\"{{.URL}}\"{{with .Height}} height=\"{{.}}\"{{end}}{{with .Width}} width=\"{{.}}\"{{end}}>\n</div>\n{{end}}\n\n{{define \"video\"}}\n<div class=\"video\">\n  <video {{with .Height}} height=\"{{.}}\"{{end}}{{with .Width}} width=\"{{.}}\"{{end}} controls>\n    <source src=\"{{.URL}}\" type=\"{{.SourceType}}\">\n  </video>\n</div>\n{{end}}\n\n{{define \"background\"}}\n<div class=\"background\">\n  <img src=\"{{.URL}}\">\n</div>\n{{end}}\n\n{{define \"iframe\"}}\n<iframe src=\"{{.URL}}\"{{with .Height}} height=\"{{.}}\"{{end}}{{with .Width}} width=\"{{.}}\"{{end}}></iframe>\n{{end}}\n\n{{define \"link\"}}<p class=\"link\"><a href=\"{{.URL}}\" target=\"_blank\">{{style .Label}}</a></p>{{end}}\n\n{{define \"html\"}}{{.HTML}}{{end}}\n\n{{define \"caption\"}}<figcaption>{{style .Text}}</figcaption>{{end}}\n"
  },
  {
    "path": "cmd/present/templates/article.tmpl",
    "content": "{/* This is the article template. It defines how articles are formatted. */}\n\n{{define \"root\"}}\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>{{.Title}}</title>\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"/static/article.css\">\n    <meta charset='utf-8'>\n    <script>\n      // Initialize Google Analytics tracking code on production site only.\n      if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n        var _gaq = _gaq || [];\n        _gaq.push([\"_setAccount\", \"UA-11222381-6\"]);\n        _gaq.push([\"b._setAccount\", \"UA-49880327-6\"]);\n        window.trackPageview = function() {\n          _gaq.push([\"_trackPageview\", location.pathname+location.hash]);\n          _gaq.push([\"b._trackPageview\", location.pathname+location.hash]);\n        };\n        window.trackPageview();\n        window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {\n          _gaq.push([\"_trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n          _gaq.push([\"b._trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n        };\n      }\n    </script>\n  </head>\n\n  <body>\n    <div id=\"topbar\" class=\"wide\">\n      <div class=\"container\">\n        <div id=\"heading\">{{.Title}}\n          {{with .Subtitle}}{{.}}{{end}}\n          {{if .Authors}}\n            {{range .Authors}}\n              <div class=\"author\">\n                {{range .Elem}}{{elem $.Template .}}{{end}}\n              </div>\n            {{end}}\n          {{end}}\n        </div>\n      </div>\n    </div>\n    <div id=\"page\" class=\"wide\">\n      <div class=\"container\">\n        {{with .Sections}}\n          <div id=\"toc\" class=\"no-print\">\n            <div id=\"tochead\">Contents</div>\n            {{template \"TOC\" .}}\n          </div>\n        {{end}}\n\n        {{range .Sections}}\n          {{elem $.Template .}}\n        {{end}}{{/* of Section block */}}\n\n      </div>\n    </div>\n\n    {{if .PlayEnabled}}\n    <script src='/play.js'></script>\n    {{end}}\n\n    <script>\n      (function() {\n        // Load Google Analytics tracking code on production site only.\n        if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n          var ga = document.createElement(\"script\"); ga.type = \"text/javascript\"; ga.async = true;\n          ga.src = (\"https:\" == document.location.protocol ? \"https://ssl\" : \"http://www\") + \".google-analytics.com/ga.js\";\n          var s = document.getElementsByTagName(\"script\")[0]; s.parentNode.insertBefore(ga, s);\n        }\n      })();\n    </script>\n  </body>\n</html>\n{{end}}\n\n{{define \"TOC\"}}\n  <ul class=\"toc-outer\">\n  {{range .}}\n    <li><a href=\"#TOC_{{.FormattedNumber}}\">{{.Title}}</a></li>\n    {{with .Sections}}{{template \"TOC-Inner\" .}}{{end}}\n  {{end}}\n  </ul>\n{{end}}\n\n{{define \"TOC-Inner\"}}\n  <ul class=\"toc-inner\">\n  {{range .}}\n    <li><a href=\"#TOC_{{.FormattedNumber}}\">{{.Title}}</a></li>\n    {{with .Sections}}{{template \"TOC-Inner\" .}}{{end}}\n  {{end}}\n  </ul>\n{{end}}\n\n{{define \"newline\"}}\n{{/* No automatic line break. Paragraphs are free-form. */}}\n{{end}}\n"
  },
  {
    "path": "cmd/present/templates/dir.tmpl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n  <title>Talks - The Go Programming Language</title>\n  <link type=\"text/css\" rel=\"stylesheet\" href=\"/static/dir.css\">\n  <script src=\"/static/dir.js\"></script>\n  <script>\n    // Initialize Google Analytics tracking code on production site only.\n    if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n      var _gaq = _gaq || [];\n      _gaq.push([\"_setAccount\", \"UA-11222381-6\"]);\n      _gaq.push([\"b._setAccount\", \"UA-49880327-6\"]);\n      window.trackPageview = function() {\n        _gaq.push([\"_trackPageview\", location.pathname+location.hash]);\n        _gaq.push([\"b._trackPageview\", location.pathname+location.hash]);\n      };\n      window.trackPageview();\n      window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {\n        _gaq.push([\"_trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n        _gaq.push([\"b._trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n      };\n    }\n  </script>\n</head>\n<body>\n\n<div id=\"topbar\"><div class=\"container\">\n\n<form method=\"GET\" action=\"//golang.org/search\">\n<div id=\"menu\">\n<a href=\"http://golang.org/doc/\">Documents</a>\n<a href=\"http://golang.org/ref\">References</a>\n<a href=\"http://golang.org/pkg/\">Packages</a>\n<a href=\"http://golang.org/project/\">The Project</a>\n<a href=\"http://golang.org/help/\">Help</a>\n<input type=\"text\" id=\"search\" name=\"q\" class=\"inactive\" value=\"Search\">\n</div>\n<div id=\"heading\"><a href=\"/\">The Go Programming Language</a></div>\n</form>\n\n</div></div>\n\n<div id=\"page\">\n\n  <h1>Go talks</h1>\n\n  {{with .Path}}<h2>{{.}}</h2>{{end}}\n\n  {{with .Articles}}\n  <h4>Articles:</h4>\n  <dl>\n  {{range .}}\n  <dd><a href=\"/{{.Path}}\">{{.Name}}</a>: {{.Title}}</dd>\n  {{end}}\n  </dl>\n  {{end}}\n\n  {{with .Slides}}\n  <h4>Slide decks:</h4>\n  <dl>\n  {{range .}}\n  <dd><a href=\"/{{.Path}}\">{{.Name}}</a>: {{.Title}}</dd>\n  {{end}}\n  </dl>\n  {{end}}\n\n  {{with .Other}}\n  <h4>Files:</h4>\n  <dl>\n  {{range .}}\n  <dd><a href=\"/{{.Path}}\">{{.Name}}</a></dd>\n  {{end}}\n  </dl>\n  {{end}}\n\n  {{with .Dirs}}\n  <h4>Sub-directories:</h4>\n  <dl>\n  {{range .}}\n  <dd><a href=\"/{{.Path}}\">{{.Name}}</a></dd>\n  {{end}}\n  </dl>\n  {{end}}\n\n</div>\n\n<div id=\"footer\">\nExcept as <a href=\"https://developers.google.com/site-policies#restrictions\">noted</a>,\nthe content of this page is licensed under the\nCreative Commons Attribution 3.0 License,\nand code is licensed under a <a href=\"http://golang.org/LICENSE\">BSD license</a>.<br>\n<a href=\"http://golang.org/doc/tos.html\">Terms of Service</a> |\n<a href=\"http://www.google.com/intl/en/policies/privacy/\">Privacy Policy</a>\n</div>\n\n<script>\n  (function() {\n    // Load Google Analytics tracking code on production site only.\n    if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n      var ga = document.createElement(\"script\"); ga.type = \"text/javascript\"; ga.async = true;\n      ga.src = (\"https:\" == document.location.protocol ? \"https://ssl\" : \"http://www\") + \".google-analytics.com/ga.js\";\n      var s = document.getElementsByTagName(\"script\")[0]; s.parentNode.insertBefore(ga, s);\n    }\n  })();\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "cmd/present/templates/slides.tmpl",
    "content": "{/* This is the slide template. It defines how presentations are formatted. */}\n\n{{define \"root\"}}\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>{{.Title}}</title>\n    <meta charset='utf-8'>\n    <script>\n      var notesEnabled = {{.NotesEnabled}};\n    </script>\n    <script src='/static/slides.js'></script>\n\n    {{if .NotesEnabled}}\n    <script>\n      var sections = {{.Sections}};\n      var titleNotes = {{.TitleNotes}}\n    </script>\n    <script src='/static/notes.js'></script>\n    {{end}}\n\n    <script>\n      // Initialize Google Analytics tracking code on production site only.\n      if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n        var _gaq = _gaq || [];\n        _gaq.push([\"_setAccount\", \"UA-11222381-6\"]);\n        _gaq.push([\"b._setAccount\", \"UA-49880327-6\"]);\n        window.trackPageview = function() {\n          _gaq.push([\"_trackPageview\", location.pathname+location.hash]);\n          _gaq.push([\"b._trackPageview\", location.pathname+location.hash]);\n        };\n        window.trackPageview();\n        window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {\n          _gaq.push([\"_trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n          _gaq.push([\"b._trackEvent\", category, action, opt_label, opt_value, opt_noninteraction]);\n        };\n      }\n    </script>\n  </head>\n\n  <body style='display: none'>\n\n    <section class='slides layout-widescreen'>\n\n      <article>\n        <h1>{{.Title}}</h1>\n        {{with .Subtitle}}<h3>{{.}}</h3>{{end}}\n        {{if not .Time.IsZero}}<h3>{{.Time.Format \"2 January 2006\"}}</h3>{{end}}\n        {{range .Authors}}\n          <div class=\"presenter\">\n            {{range .TextElem}}{{elem $.Template .}}{{end}}\n          </div>\n        {{end}}\n      </article>\n\n  {{range $i, $s := .Sections}}\n  <!-- start of slide {{$s.Number}} -->\n      <article {{$s.HTMLAttributes}}>\n      {{if $s.Elem}}\n        <h3>{{$s.Title}}</h3>\n        {{range $s.Elem}}{{elem $.Template .}}{{end}}\n      {{else}}\n        <h2>{{$s.Title}}</h2>\n      {{end}}\n      <span class=\"pagenumber\">{{pagenum $s 1}}</span>\n      </article>\n  <!-- end of slide {{$s.Number}} -->\n  {{end}}{{/* of Slide block */}}\n\n      <article>\n        <h3>Thank you</h3>\n        {{range .Authors}}\n          <div class=\"presenter\">\n            {{range .Elem}}{{elem $.Template .}}{{end}}\n          </div>\n        {{end}}\n      </article>\n\n    </section>\n\n    <div id=\"help\">\n      Use the left and right arrow keys or click the left and right\n      edges of the page to navigate between slides.<br>\n      (Press 'H' or navigate to hide this message.)\n    </div>\n\n    {{if .PlayEnabled}}\n    <script src='/play.js'></script>\n    {{end}}\n\n    <script>\n      (function() {\n        // Load Google Analytics tracking code on production site only.\n        if (window[\"location\"] && window[\"location\"][\"hostname\"] == \"talks.golang.org\") {\n          var ga = document.createElement(\"script\"); ga.type = \"text/javascript\"; ga.async = true;\n          ga.src = (\"https:\" == document.location.protocol ? \"https://ssl\" : \"http://www\") + \".google-analytics.com/ga.js\";\n          var s = document.getElementsByTagName(\"script\")[0]; s.parentNode.insertBefore(ga, s);\n        }\n      })();\n    </script>\n  </body>\n</html>\n{{end}}\n\n{{define \"newline\"}}\n<br>\n{{end}}\n"
  },
  {
    "path": "cmd/present2md/main.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Present2md converts legacy-syntax present files to Markdown-syntax present files.\n//\n// Usage:\n//\n//\tpresent2md [-w] [file ...]\n//\n// By default, present2md prints the Markdown-syntax form of each input file to standard output.\n// If no input file is listed, standard input is used.\n//\n// The -w flag causes present2md to update the files in place, overwriting each with its\n// Markdown-syntax equivalent.\n//\n// Examples\n//\n//\tpresent2md your.article\n//\tpresent2md -w *.article\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/url\"\n\t\"os\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/present\"\n)\n\nfunc usage() {\n\tfmt.Fprintf(os.Stderr, \"usage: present2md [-w] [file ...]\\n\")\n\tos.Exit(2)\n}\n\nvar (\n\twriteBack  = flag.Bool(\"w\", false, \"write conversions back to original files\")\n\texitStatus = 0\n)\n\nfunc main() {\n\tlog.SetPrefix(\"present2md: \")\n\tlog.SetFlags(0)\n\tflag.Usage = usage\n\tflag.Parse()\n\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\tif *writeBack {\n\t\t\tlog.Fatalf(\"cannot use -w with standard input\")\n\t\t}\n\t\tconvert(os.Stdin, \"stdin\", false)\n\t\treturn\n\t}\n\n\tfor _, arg := range args {\n\t\tf, err := os.Open(arg)\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t\texitStatus = 1\n\t\t\tcontinue\n\t\t}\n\t\terr = convert(f, arg, *writeBack)\n\t\tf.Close()\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t\texitStatus = 1\n\t\t}\n\t}\n\tos.Exit(exitStatus)\n}\n\n// convert reads the data from r, parses it as legacy present,\n// and converts it to Markdown-enabled present.\n// If any errors occur, the data is reported as coming from file.\n// If writeBack is true, the converted version is written back to file.\n// If writeBack is false, the converted version is printed to standard output.\nfunc convert(r io.Reader, file string, writeBack bool) error {\n\tdata, err := io.ReadAll(r)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif bytes.HasPrefix(data, []byte(\"# \")) {\n\t\treturn fmt.Errorf(\"%v: already markdown\", file)\n\t}\n\n\t// Convert all comments before parsing the document.\n\t// The '//' comment is treated as normal text and so\n\t// is passed through the translation unaltered.\n\tdata = bytes.Replace(data, []byte(\"\\n#\"), []byte(\"\\n//\"), -1)\n\n\tdoc, err := present.Parse(bytes.NewReader(data), file, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Title and Subtitle, Time, Tags.\n\tvar md bytes.Buffer\n\tfmt.Fprintf(&md, \"# %s\\n\", doc.Title)\n\tif doc.Subtitle != \"\" {\n\t\tfmt.Fprintf(&md, \"%s\\n\", doc.Subtitle)\n\t}\n\tif !doc.Time.IsZero() {\n\t\tfmt.Fprintf(&md, \"%s\\n\", doc.Time.Format(\"2 Jan 2006\"))\n\t}\n\tif len(doc.Tags) > 0 {\n\t\tfmt.Fprintf(&md, \"Tags: %s\\n\", strings.Join(doc.Tags, \", \"))\n\t}\n\n\t// Summary, defaulting to first paragraph of section.\n\t// (Summaries must be explicit for Markdown-enabled present,\n\t// and the expectation is that they will be shorter than the\n\t// whole first paragraph. But this is what the blog does today.)\n\tif strings.HasSuffix(file, \".article\") && len(doc.Sections) > 0 {\n\t\tfor _, elem := range doc.Sections[0].Elem {\n\t\t\ttext, ok := elem.(present.Text)\n\t\t\tif !ok || text.Pre {\n\t\t\t\t// skip everything but non-text elements\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Fprintf(&md, \"Summary:\")\n\t\t\tfor _, line := range text.Lines {\n\t\t\t\tfmt.Fprintf(&md, \" \")\n\t\t\t\tprintStyled(&md, line)\n\t\t\t}\n\t\t\tfmt.Fprintf(&md, \"\\n\")\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Authors\n\tfor _, a := range doc.Authors {\n\t\tfmt.Fprintf(&md, \"\\n\")\n\t\tfor _, elem := range a.Elem {\n\t\t\tswitch elem := elem.(type) {\n\t\t\tdefault:\n\t\t\t\t// Can only happen if this type switch is incomplete, which is a bug.\n\t\t\t\tlog.Fatalf(\"%s: unexpected author type %T\", file, elem)\n\t\t\tcase present.Text:\n\t\t\t\tfor _, line := range elem.Lines {\n\t\t\t\t\tfmt.Fprintf(&md, \"%s\\n\", markdownEscape(line))\n\t\t\t\t}\n\t\t\tcase present.Link:\n\t\t\t\tfmt.Fprintf(&md, \"%s\\n\", markdownEscape(elem.Label))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Invariant: the output ends in non-blank line now,\n\t// and after printing any piece of the file below,\n\t// the output should still end in a non-blank line.\n\t// If a blank line separator is needed, it should be printed\n\t// before the block that needs separating, not after.\n\n\tif len(doc.TitleNotes) > 0 {\n\t\tfmt.Fprintf(&md, \"\\n\")\n\t\tfor _, line := range doc.TitleNotes {\n\t\t\tfmt.Fprintf(&md, \": %s\\n\", line)\n\t\t}\n\t}\n\n\tif len(doc.Sections) == 1 && strings.HasSuffix(file, \".article\") {\n\t\t// Blog drops section headers when there is only one section.\n\t\t// Don't print a title in this case, to make clear that it's being dropped.\n\t\tfmt.Fprintf(&md, \"\\n##\\n\")\n\t\tprintSectionBody(file, 1, &md, doc.Sections[0].Elem)\n\t} else {\n\t\tfor _, s := range doc.Sections {\n\t\t\tfmt.Fprintf(&md, \"\\n\")\n\t\t\tfmt.Fprintf(&md, \"## %s\\n\", markdownEscape(s.Title))\n\t\t\tprintSectionBody(file, 1, &md, s.Elem)\n\t\t}\n\t}\n\n\tif !writeBack {\n\t\tos.Stdout.Write(md.Bytes())\n\t\treturn nil\n\t}\n\treturn os.WriteFile(file, md.Bytes(), 0666)\n}\n\nfunc printSectionBody(file string, depth int, w *bytes.Buffer, elems []present.Elem) {\n\tfor _, elem := range elems {\n\t\tswitch elem := elem.(type) {\n\t\tdefault:\n\t\t\t// Can only happen if this type switch is incomplete, which is a bug.\n\t\t\tlog.Fatalf(\"%s: unexpected present element type %T\", file, elem)\n\n\t\tcase present.Text:\n\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\tlines := elem.Lines\n\t\t\tfor len(lines) > 0 && lines[0] == \"\" {\n\t\t\t\tlines = lines[1:]\n\t\t\t}\n\t\t\tif elem.Pre {\n\t\t\t\tfor line := range strings.SplitSeq(strings.TrimRight(elem.Raw, \"\\n\"), \"\\n\") {\n\t\t\t\t\tif line == \"\" {\n\t\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfmt.Fprintf(w, \"\\t%s\\n\", line)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor _, line := range elem.Lines {\n\t\t\t\t\tprintStyled(w, line)\n\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase present.List:\n\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\tfor _, item := range elem.Bullet {\n\t\t\t\tfmt.Fprintf(w, \"  - \")\n\t\t\t\tfor i, line := range strings.Split(item, \"\\n\") {\n\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\tfmt.Fprintf(w, \"    \")\n\t\t\t\t\t}\n\t\t\t\t\tprintStyled(w, line)\n\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase present.Section:\n\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\tsep := \" \"\n\t\t\tif elem.Title == \"\" {\n\t\t\t\tsep = \"\"\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s%s%s\\n\", strings.Repeat(\"#\", depth+2), sep, markdownEscape(elem.Title))\n\t\t\tprintSectionBody(file, depth+1, w, elem.Elem)\n\n\t\tcase interface{ PresentCmd() string }:\n\t\t\t// If there are multiple present commands in a row, don't print a blank line before the second etc.\n\t\t\tb := w.Bytes()\n\t\t\tsep := \"\\n\"\n\t\t\tif len(b) > 0 {\n\t\t\t\ti := bytes.LastIndexByte(b[:len(b)-1], '\\n')\n\t\t\t\tif b[i+1] == '.' {\n\t\t\t\t\tsep = \"\"\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"%s%s\\n\", sep, elem.PresentCmd())\n\t\t}\n\t}\n}\n\nfunc markdownEscape(s string) string {\n\tvar b strings.Builder\n\tfor i, r := range s {\n\t\tswitch {\n\t\tcase r == '#' && i == 0,\n\t\t\tr == '*',\n\t\t\tr == '_',\n\t\t\tr == '<' && (i == 0 || s[i-1] != ' ') && i+1 < len(s) && s[i+1] != ' ',\n\t\t\tr == '[' && strings.Contains(s[i:], \"](\"):\n\t\t\tb.WriteRune('\\\\')\n\t\t}\n\t\tb.WriteRune(r)\n\t}\n\treturn b.String()\n}\n\n// Copy of ../../present/style.go adjusted to produce Markdown instead of HTML.\n\n/*\n\tFonts are demarcated by an initial and final char bracketing a\n\tspace-delimited word, plus possibly some terminal punctuation.\n\tThe chars are\n\t\t_ for italic\n\t\t* for bold\n\t\t` (back quote) for fixed width.\n\tInner appearances of the char become spaces. For instance,\n\t\t_this_is_italic_!\n\tbecomes\n\t\t<i>this is italic</i>!\n*/\n\nfunc printStyled(w *bytes.Buffer, text string) {\n\tw.WriteString(font(text))\n}\n\n// font returns s with font indicators turned into HTML font tags.\nfunc font(s string) string {\n\tif !strings.ContainsAny(s, \"[`_*\") {\n\t\treturn markdownEscape(s)\n\t}\n\twords := split(s)\n\tvar b bytes.Buffer\nWord:\n\tfor w, word := range words {\n\t\twords[w] = markdownEscape(word) // for all the continue Word\n\t\tif len(word) < 2 {\n\t\t\tcontinue Word\n\t\t}\n\t\tif link, _ := parseInlineLink(word); link != \"\" {\n\t\t\twords[w] = link\n\t\t\tcontinue Word\n\t\t}\n\t\tconst marker = \"_*`\"\n\t\t// Initial punctuation is OK but must be peeled off.\n\t\tfirst := strings.IndexAny(word, marker)\n\t\tif first == -1 {\n\t\t\tcontinue Word\n\t\t}\n\t\t// Opening marker must be at the beginning of the token or else preceded by punctuation.\n\t\tif first != 0 {\n\t\t\tr, _ := utf8.DecodeLastRuneInString(word[:first])\n\t\t\tif !unicode.IsPunct(r) {\n\t\t\t\tcontinue Word\n\t\t\t}\n\t\t}\n\t\topen, word := markdownEscape(word[:first]), word[first:]\n\t\tchar := word[0] // ASCII is OK.\n\t\tclose := \"\"\n\t\tswitch char {\n\t\tdefault:\n\t\t\tcontinue Word\n\t\tcase '_':\n\t\t\topen += \"_\"\n\t\t\tclose = \"_\"\n\t\tcase '*':\n\t\t\topen += \"**\"\n\t\t\tclose = \"**\"\n\t\tcase '`':\n\t\t\topen += \"`\"\n\t\t\tclose = \"`\"\n\t\t}\n\t\t// Closing marker must be at the end of the token or else followed by punctuation.\n\t\tlast := strings.LastIndex(word, word[:1])\n\t\tif last == 0 {\n\t\t\tcontinue Word\n\t\t}\n\t\tif last+1 != len(word) {\n\t\t\tr, _ := utf8.DecodeRuneInString(word[last+1:])\n\t\t\tif !unicode.IsPunct(r) {\n\t\t\t\tcontinue Word\n\t\t\t}\n\t\t}\n\t\thead, tail := word[:last+1], word[last+1:]\n\t\tb.Reset()\n\t\tvar wid int\n\t\tfor i := 1; i < len(head)-1; i += wid {\n\t\t\tvar r rune\n\t\t\tr, wid = utf8.DecodeRuneInString(head[i:])\n\t\t\tif r != rune(char) {\n\t\t\t\t// Ordinary character.\n\t\t\t\tb.WriteRune(r)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif head[i+1] != char {\n\t\t\t\t// Inner char becomes space.\n\t\t\t\tb.WriteRune(' ')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Doubled char becomes real char.\n\t\t\t// Not worth worrying about \"_x__\".\n\t\t\tb.WriteByte(char)\n\t\t\twid++ // Consumed two chars, both ASCII.\n\t\t}\n\t\ttext := b.String()\n\t\tif close == \"`\" {\n\t\t\tfor strings.Contains(text, close) {\n\t\t\t\topen += \"`\"\n\t\t\t\tclose += \"`\"\n\t\t\t}\n\t\t} else {\n\t\t\ttext = markdownEscape(text)\n\t\t}\n\t\twords[w] = open + text + close + tail\n\t}\n\treturn strings.Join(words, \"\")\n}\n\n// split is like strings.Fields but also returns the runs of spaces\n// and treats inline links as distinct words.\nfunc split(s string) []string {\n\tvar (\n\t\twords = make([]string, 0, 10)\n\t\tstart = 0\n\t)\n\n\t// appendWord appends the string s[start:end] to the words slice.\n\t// If the word contains the beginning of a link, the non-link portion\n\t// of the word and the entire link are appended as separate words,\n\t// and the start index is advanced to the end of the link.\n\tappendWord := func(end int) {\n\t\tif j := strings.Index(s[start:end], \"[[\"); j > -1 {\n\t\t\tif _, l := parseInlineLink(s[start+j:]); l > 0 {\n\t\t\t\t// Append portion before link, if any.\n\t\t\t\tif j > 0 {\n\t\t\t\t\twords = append(words, s[start:start+j])\n\t\t\t\t}\n\t\t\t\t// Append link itself.\n\t\t\t\twords = append(words, s[start+j:start+j+l])\n\t\t\t\t// Advance start index to end of link.\n\t\t\t\tstart = start + j + l\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\t// No link; just add the word.\n\t\twords = append(words, s[start:end])\n\t\tstart = end\n\t}\n\n\twasSpace := false\n\tfor i, r := range s {\n\t\tisSpace := unicode.IsSpace(r)\n\t\tif i > start && isSpace != wasSpace {\n\t\t\tappendWord(i)\n\t\t}\n\t\twasSpace = isSpace\n\t}\n\tfor start < len(s) {\n\t\tappendWord(len(s))\n\t}\n\treturn words\n}\n\n// parseInlineLink parses an inline link at the start of s, and returns\n// a rendered Markdown link and the total length of the raw inline link.\n// If no inline link is present, it returns all zeroes.\nfunc parseInlineLink(s string) (link string, length int) {\n\tif !strings.HasPrefix(s, \"[[\") {\n\t\treturn\n\t}\n\tend := strings.Index(s, \"]]\")\n\tif end == -1 {\n\t\treturn\n\t}\n\turlEnd := strings.Index(s, \"]\")\n\trawURL := s[2:urlEnd]\n\tconst badURLChars = `<>\"{}|\\^[] ` + \"`\" // per RFC2396 section 2.4.3\n\tif strings.ContainsAny(rawURL, badURLChars) {\n\t\treturn\n\t}\n\tif urlEnd == end {\n\t\tsimpleURL := \"\"\n\t\turl, err := url.Parse(rawURL)\n\t\tif err == nil {\n\t\t\t// If the URL is http://foo.com, drop the http://\n\t\t\t// In other words, render [[http://golang.org]] as:\n\t\t\t//   <a href=\"http://golang.org\">golang.org</a>\n\t\t\tif after, ok := strings.CutPrefix(rawURL, url.Scheme+\"://\"); ok {\n\t\t\t\tsimpleURL = after\n\t\t\t} else if after, ok := strings.CutPrefix(rawURL, url.Scheme+\":\"); ok {\n\t\t\t\tsimpleURL = after\n\t\t\t}\n\t\t}\n\t\treturn renderLink(rawURL, simpleURL), end + 2\n\t}\n\tif s[urlEnd:urlEnd+2] != \"][\" {\n\t\treturn\n\t}\n\ttext := s[urlEnd+2 : end]\n\treturn renderLink(rawURL, text), end + 2\n}\n\nfunc renderLink(href, text string) string {\n\ttext = font(text)\n\tif text == \"\" {\n\t\ttext = markdownEscape(href)\n\t}\n\treturn \"[\" + text + \"](\" + href + \")\"\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/README.md",
    "content": "# signature-fuzzer\n\nThis directory contains utilities for fuzz testing of Go function signatures, for use in developing/testing a Go compiler.\n\nThe basic idea of the fuzzer is that it emits source code for a stand-alone Go program; this generated program is a series of pairs of functions, a \"Caller\" function and a \"Checker\" function. The signature of the Checker function is generated randomly (random number of parameters and returns, each with randomly chosen types). The \"Caller\" func contains invocations of the \"Checker\" function, each passing randomly chosen values to the params of the \"Checker\", then the caller verifies that expected values are returned correctly. The \"Checker\" function in turn has code to verify that the expected values (more details below).\n\nThere are three main parts to the fuzzer: a generator package, a driver package, and a runner package.\n\nThe \"generator\" contains the guts of the fuzzer, the bits that actually emit the random code.\n\nThe \"driver\" is a stand-alone program that invokes the generator to create a single test program. It is not terribly useful on its own (since it doesn't actually build or run the generated program), but it is handy for debugging the generator or looking at examples of the emitted code.\n\nThe \"runner\" is a more complete test harness; it repeatedly runs the generator to create a new test program, builds the test program, then runs it (checking for errors along the way). If at any point a build or test fails, the \"runner\" harness attempts a minimization process to try to narrow down the failure to a single package and/or function.\n\n## What the generated code looks like\n\nGenerated Go functions will have an \"interesting\" set of signatures (mix of\narrays, scalars, structs), intended to pick out corner cases and odd bits in the\nGo compiler's code that handles function calls and returns.\n\nThe first generated file is genChecker.go, which contains function that look something\nlike this (simplified):\n\n```\ntype StructF4S0 struct {\nF0 float64\nF1 int16\nF2 uint16\n}\n\n// 0 returns 2 params\nfunc Test4(p0 int8, p1 StructF4S0)  {\n  c0 := int8(-1)\n  if p0 != c0 {\n    NoteFailure(4, \"parm\", 0)\n  }\n  c1 := StructF4S0{float64(2), int16(-3), uint16(4)}\n  if p1 != c1 {\n    NoteFailure(4, \"parm\", 1)\n  }\n  return\n}\n```\n\nHere the test generator has randomly selected 0 return values and 2 params, then randomly generated types for the params.\n\nThe generator then emits code on the calling side into the file \"genCaller.go\", which might look like:\n\n```\nfunc Caller4() {\nvar p0 int8\np0 = int8(-1)\nvar p1 StructF4S0\np1 = StructF4S0{float64(2), int16(-3), uint16(4)}\n// 0 returns 2 params\nTest4(p0, p1)\n}\n```\n\nThe generator then emits some utility functions (ex: NoteFailure) and a main routine that cycles through all of the tests.\n\n## Trying a single run of the generator\n\nTo generate a set of source files just to see what they look like, you can build and run the test generator as follows. This creates a new directory \"cabiTest\" containing generated test files:\n\n```\n$ git clone https://golang.org/x/tools\n$ cd tools/cmd/signature-fuzzer/fuzz-driver\n$ go build .\n$ ./fuzz-driver -numpkgs 3 -numfcns 5 -seed 12345 -outdir /tmp/sigfuzzTest -pkgpath foobar\n$ cd /tmp/sigfuzzTest\n$ find . -type f -print\n./genCaller1/genCaller1.go\n./genUtils/genUtils.go\n./genChecker1/genChecker1.go\n./genChecker0/genChecker0.go\n./genCaller2/genCaller2.go\n./genCaller0/genCaller0.go\n./genMain.go\n./go.mod\n./genChecker2/genChecker2.go\n$\n```\n\nYou can build and run the generated files in the usual way:\n\n```\n$ cd /tmp/sigfuzzTest\n$ go build .\n$ ./foobar\nstarting main\nfinished 15 tests\n$\n\n```\n\n## Example usage for the test runner\n\nThe test runner orchestrates multiple runs of the fuzzer, iteratively emitting code, building it, and testing the resulting binary. To use the runner, build and invoke it with a specific number of iterations; it will select a new random seed on each invocation. The runner will terminate as soon as it finds a failure. Example:\n\n```\n$ git clone https://golang.org/x/tools\n$ cd tools/cmd/signature-fuzzer/fuzz-runner\n$ go build .\n$ ./fuzz-runner -numit=3\n... begin iteration 0 with current seed 67104558\nstarting main\nfinished 1000 tests\n... begin iteration 1 with current seed 67104659\nstarting main\nfinished 1000 tests\n... begin iteration 2 with current seed 67104760\nstarting main\nfinished 1000 tests\n$\n```\n\nIf the runner encounters a failure, it will try to perform test-case \"minimization\", e.g. attempt to isolate the failure\n\n```\n$ cd tools/cmd/signature-fuzzer/fuzz-runner\n$ go build .\n$ ./fuzz-runner -n=10\n./fuzz-runner -n=10\n... begin iteration 0 with current seed 40661762\nError: fail [reflect] |20|3|1| =Checker3.Test1= return 1\nerror executing cmd ./fzTest: exit status 1\n... starting minimization for failed directory /tmp/fuzzrun1005327337/fuzzTest\npackage minimization succeeded: found bad pkg 3\nfunction minimization succeeded: found bad fcn 1\n$\n```\n\nHere the runner has generates a failure, minimized it down to a single function and package, and left the resulting program in the output directory /tmp/fuzzrun1005327337/fuzzTest.\n\n## Limitations, future work\n\nNo support yet for variadic functions.\n\nThe set of generated types is still a bit thin; it has fairly limited support for interface values, and doesn't include channels.\n\nTodos:\n\n- better interface value coverage\n\n- implement testing of reflect.MakeFunc\n\n- extend to work with generic code of various types\n\n- extend to work in a debugging scenario (e.g. instead of just emitting code,\n  emit a script of debugger commands to run the program with expected\n  responses from the debugger)\n\n- rework things so that instead of always checking all of a given parameter\n  value, we sometimes skip over elements (or just check the length of a slice\n  or string as opposed to looking at its value)\n\n- consider adding runtime.GC() calls at some points in the generated code\n\n"
  },
  {
    "path": "cmd/signature-fuzzer/fuzz-driver/driver.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Stand-alone driver for emitting function-signature test code.  This\n// program is mainly just a wrapper around the code that lives in the\n// fuzz-generator package; it is useful for generating a specific bad\n// code scenario for a given seed, or for doing development on the\n// fuzzer, but for doing actual fuzz testing, better to use\n// fuzz-runner.\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"os\"\n\t\"time\"\n\n\tgenerator \"golang.org/x/tools/cmd/signature-fuzzer/internal/fuzz-generator\"\n)\n\n// Basic options\nvar numfcnflag = flag.Int(\"numfcns\", 10, \"Number of test func pairs to emit in each package\")\nvar numpkgflag = flag.Int(\"numpkgs\", 1, \"Number of test packages to emit\")\nvar seedflag = flag.Int64(\"seed\", -1, \"Random seed\")\nvar tagflag = flag.String(\"tag\", \"gen\", \"Prefix name of go files/pkgs to generate\")\nvar outdirflag = flag.String(\"outdir\", \"\", \"Output directory for generated files\")\nvar pkgpathflag = flag.String(\"pkgpath\", \"gen\", \"Base package path for generated files\")\n\n// Options used for test case minimization.\nvar fcnmaskflag = flag.String(\"fcnmask\", \"\", \"Mask containing list of fcn numbers to emit\")\nvar pkmaskflag = flag.String(\"pkgmask\", \"\", \"Mask containing list of pkg numbers to emit\")\n\n// Options used to control which features are used in the generated code.\nvar reflectflag = flag.Bool(\"reflect\", true, \"Include testing of reflect.Call.\")\nvar deferflag = flag.Bool(\"defer\", true, \"Include testing of defer stmts.\")\nvar recurflag = flag.Bool(\"recur\", true, \"Include testing of recursive calls.\")\nvar takeaddrflag = flag.Bool(\"takeaddr\", true, \"Include functions that take the address of their parameters and results.\")\nvar methodflag = flag.Bool(\"method\", true, \"Include testing of method calls.\")\nvar inlimitflag = flag.Int(\"inmax\", -1, \"Max number of input params.\")\nvar outlimitflag = flag.Int(\"outmax\", -1, \"Max number of input params.\")\nvar pragmaflag = flag.String(\"pragma\", \"\", \"Tag generated test routines with pragma //go:<value>.\")\nvar maxfailflag = flag.Int(\"maxfail\", 10, \"Maximum runtime failures before test self-terminates\")\nvar stackforceflag = flag.Bool(\"forcestackgrowth\", true, \"Use hooks to force stack growth.\")\n\n// Debugging options\nvar verbflag = flag.Int(\"v\", 0, \"Verbose trace output level\")\n\n// Debugging/testing options. These tell the generator to emit \"bad\" code so as to\n// test the logic for detecting errors and/or minimization (in the fuzz runner).\nvar emitbadflag = flag.Int(\"emitbad\", 0, \"[Testing only] force generator to emit 'bad' code.\")\nvar selbadpkgflag = flag.Int(\"badpkgidx\", 0, \"[Testing only] select index of bad package (used with -emitbad)\")\nvar selbadfcnflag = flag.Int(\"badfcnidx\", 0, \"[Testing only] select index of bad function (used with -emitbad)\")\n\n// Misc options\nvar goimpflag = flag.Bool(\"goimports\", false, \"Run 'goimports' on generated code.\")\nvar randctlflag = flag.Int(\"randctl\", generator.RandCtlChecks|generator.RandCtlPanic, \"Wraprand control flag\")\n\nfunc verb(vlevel int, s string, a ...any) {\n\tif *verbflag >= vlevel {\n\t\tfmt.Printf(s, a...)\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\n\nfunc usage(msg string) {\n\tif len(msg) > 0 {\n\t\tfmt.Fprintf(os.Stderr, \"error: %s\\n\", msg)\n\t}\n\tfmt.Fprintf(os.Stderr, \"usage: fuzz-driver [flags]\\n\\n\")\n\tflag.PrintDefaults()\n\tfmt.Fprintf(os.Stderr, \"Example:\\n\\n\")\n\tfmt.Fprintf(os.Stderr, \"  fuzz-driver -numpkgs=23 -numfcns=19 -seed 10101 -outdir gendir\\n\\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\tgenerates a Go program with 437 test cases (23 packages, each \\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\twith 19 functions, for a total of 437 funcs total) into a set of\\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\tsub-directories in 'gendir', using random see 10101\\n\")\n\n\tos.Exit(2)\n}\n\nfunc setupTunables() {\n\ttunables := generator.DefaultTunables()\n\tif !*reflectflag {\n\t\ttunables.DisableReflectionCalls()\n\t}\n\tif !*deferflag {\n\t\ttunables.DisableDefer()\n\t}\n\tif !*recurflag {\n\t\ttunables.DisableRecursiveCalls()\n\t}\n\tif !*takeaddrflag {\n\t\ttunables.DisableTakeAddr()\n\t}\n\tif !*methodflag {\n\t\ttunables.DisableMethodCalls()\n\t}\n\tif *inlimitflag != -1 {\n\t\ttunables.LimitInputs(*inlimitflag)\n\t}\n\tif *outlimitflag != -1 {\n\t\ttunables.LimitOutputs(*outlimitflag)\n\t}\n\tgenerator.SetTunables(tunables)\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"fuzz-driver: \")\n\tflag.Parse()\n\tgenerator.Verbctl = *verbflag\n\tif *outdirflag == \"\" {\n\t\tusage(\"select an output directory with -o flag\")\n\t}\n\tverb(1, \"in main verblevel=%d\", *verbflag)\n\tif *seedflag == -1 {\n\t\t// user has not selected a specific seed -- pick one.\n\t\tnow := time.Now()\n\t\t*seedflag = now.UnixNano() % 123456789\n\t\tverb(0, \"selected seed: %d\", *seedflag)\n\t}\n\trand.Seed(*seedflag)\n\tif flag.NArg() != 0 {\n\t\tusage(\"unknown extra arguments\")\n\t}\n\tverb(1, \"tag is %s\", *tagflag)\n\n\tfcnmask, err := generator.ParseMaskString(*fcnmaskflag, \"fcn\")\n\tif err != nil {\n\t\tusage(fmt.Sprintf(\"mangled fcn mask arg: %v\", err))\n\t}\n\tpkmask, err := generator.ParseMaskString(*pkmaskflag, \"pkg\")\n\tif err != nil {\n\t\tusage(fmt.Sprintf(\"mangled pkg mask arg: %v\", err))\n\t}\n\tverb(2, \"pkg mask is %v\", pkmask)\n\tverb(2, \"fn mask is %v\", fcnmask)\n\n\tverb(1, \"starting generation\")\n\tsetupTunables()\n\tconfig := generator.GenConfig{\n\t\tPkgPath:          *pkgpathflag,\n\t\tTag:              *tagflag,\n\t\tOutDir:           *outdirflag,\n\t\tNumTestPackages:  *numpkgflag,\n\t\tNumTestFunctions: *numfcnflag,\n\t\tSeed:             *seedflag,\n\t\tPragma:           *pragmaflag,\n\t\tFcnMask:          fcnmask,\n\t\tPkgMask:          pkmask,\n\t\tMaxFail:          *maxfailflag,\n\t\tForceStackGrowth: *stackforceflag,\n\t\tRandCtl:          *randctlflag,\n\t\tRunGoImports:     *goimpflag,\n\t\tEmitBad:          *emitbadflag,\n\t\tBadPackageIdx:    *selbadpkgflag,\n\t\tBadFuncIdx:       *selbadfcnflag,\n\t}\n\terrs := generator.Generate(config)\n\tif errs != 0 {\n\t\tlog.Fatal(\"errors during generation\")\n\t}\n\tverb(1, \"... files written to directory %s\", *outdirflag)\n\tverb(1, \"leaving main\")\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/fuzz-driver/drv_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// buildDriver builds the fuzz-driver executable, returning its path.\nfunc buildDriver(t *testing.T) string {\n\tt.Helper()\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t\treturn \"\"\n\t}\n\tbindir := filepath.Join(t.TempDir(), \"bin\")\n\terr := os.Mkdir(bindir, os.ModePerm)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tbinary := filepath.Join(bindir, \"driver\")\n\tif runtime.GOOS == \"windows\" {\n\t\tbinary += \".exe\"\n\t}\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", binary)\n\tif err := cmd.Run(); err != nil {\n\t\tt.Fatalf(\"Building fuzz-driver: %v\", err)\n\t}\n\treturn binary\n}\n\nfunc TestEndToEndIntegration(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\ttd := t.TempDir()\n\n\t// Build the fuzz-driver binary.\n\t// Note: if more tests are added to this package, move this to single setup fcn, so\n\t// that we don't have to redo the build each time.\n\tbinary := buildDriver(t)\n\n\t// Kick off a run.\n\tgendir := filepath.Join(td, \"gen\")\n\targs := []string{\"-numfcns\", \"3\", \"-numpkgs\", \"1\", \"-seed\", \"101\", \"-outdir\", gendir}\n\tc := exec.Command(binary, args...)\n\tb, err := c.CombinedOutput()\n\tif err != nil {\n\t\tt.Fatalf(\"error invoking fuzz-driver: %v\\n%s\", err, b)\n\t}\n\n\tfound := \"\"\n\twalker := func(path string, info os.FileInfo, err error) error {\n\t\tfound = found + \":\" + info.Name()\n\t\treturn nil\n\t}\n\n\t// Make sure it emits something.\n\terr2 := filepath.Walk(gendir, walker)\n\tif err2 != nil {\n\t\tt.Fatalf(\"error from filepath.Walk: %v\", err2)\n\t}\n\tconst expected = \":gen:genCaller0:genCaller0.go:genChecker0:genChecker0.go:genMain.go:genUtils:genUtils.go:go.mod\"\n\tif found != expected {\n\t\tt.Errorf(\"walk of generated code: got %s want %s\", found, expected)\n\t}\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/fuzz-runner/rnr_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc canRace() bool {\n\t_, err := exec.Command(\"go\", \"run\", \"-race\", \"./testdata/himom.go\").CombinedOutput()\n\treturn err == nil\n}\n\n// buildRunner builds the fuzz-runner executable, returning its path.\nfunc buildRunner(t *testing.T) string {\n\tbindir := filepath.Join(t.TempDir(), \"bin\")\n\terr := os.Mkdir(bindir, os.ModePerm)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tbinary := filepath.Join(bindir, \"runner\")\n\tif runtime.GOOS == \"windows\" {\n\t\tbinary += \".exe\"\n\t}\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", binary)\n\tif err := cmd.Run(); err != nil {\n\t\tt.Fatalf(\"Building fuzz-runner: %v\", err)\n\t}\n\treturn binary\n}\n\n// TestRunner builds the binary, then kicks off a collection of sub-tests that invoke it.\nfunc TestRunner(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\tbinaryPath := buildRunner(t)\n\n\t// Sub-tests using the binary built above.\n\tt.Run(\"Basic\", func(t *testing.T) { testBasic(t, binaryPath) })\n\tt.Run(\"Race\", func(t *testing.T) { testRace(t, binaryPath) })\n\tt.Run(\"Minimization1\", func(t *testing.T) { testMinimization1(t, binaryPath) })\n\tt.Run(\"Minimization2\", func(t *testing.T) { testMinimization2(t, binaryPath) })\n}\n\nfunc testBasic(t *testing.T, binaryPath string) {\n\tt.Parallel()\n\targs := []string{\"-numit=1\", \"-numfcns=1\", \"-numpkgs=1\", \"-seed=103\", \"-cleancache=0\"}\n\tc := exec.Command(binaryPath, args...)\n\tb, err := c.CombinedOutput()\n\tt.Logf(\"%s\\n\", b)\n\tif err != nil {\n\t\tt.Fatalf(\"error invoking fuzz-runner: %v\", err)\n\t}\n}\n\nfunc testRace(t *testing.T, binaryPath string) {\n\tt.Parallel()\n\t// For this test to work, the current test platform has to support the\n\t// race detector. Check to see if that is the case by running a very\n\t// simple Go program through it.\n\tif !canRace() {\n\t\tt.Skip(\"current platform does not appear to support the race detector\")\n\t}\n\n\targs := []string{\"-v=1\", \"-numit=1\", \"-race\", \"-numfcns=3\", \"-numpkgs=3\", \"-seed=987\", \"-cleancache=0\"}\n\tc := exec.Command(binaryPath, args...)\n\tb, err := c.CombinedOutput()\n\tt.Logf(\"%s\\n\", b)\n\tif err != nil {\n\t\tt.Fatalf(\"error invoking fuzz-runner: %v\", err)\n\t}\n}\n\nfunc testMinimization1(t *testing.T, binaryPath string) {\n\tif binaryPath == \"\" {\n\t\tt.Skipf(\"No runner binary\")\n\t}\n\tt.Parallel()\n\t// Fire off the runner passing it -emitbad=1, so that the generated code\n\t// contains illegal Go code (which will force the build to fail). Verify that\n\t// it does fail, that the error reflects the nature of the failure, and that\n\t// we can minimize the error down to a single package.\n\targs := []string{\"-emitbad=1\", \"-badfcnidx=2\", \"-badpkgidx=2\",\n\t\t\"-forcetmpclean\", \"-cleancache=0\",\n\t\t\"-numit=1\", \"-numfcns=3\", \"-numpkgs=3\", \"-seed=909\"}\n\tinvocation := fmt.Sprintf(\"%s %v\", binaryPath, args)\n\tc := exec.Command(binaryPath, args...)\n\tb, err := c.CombinedOutput()\n\tt.Logf(\"%s\\n\", b)\n\tif err == nil {\n\t\tt.Fatalf(\"unexpected pass of fuzz-runner (invocation %q): %v\", invocation, err)\n\t}\n\tresult := string(b)\n\tif !strings.Contains(result, \"syntax error\") {\n\t\tt.Fatalf(\"-emitbad=1 did not trigger syntax error (invocation %q): output: %s\", invocation, result)\n\t}\n\tif !strings.Contains(result, \"package minimization succeeded: found bad pkg 2\") {\n\t\tt.Fatalf(\"failed to minimize package (invocation %q): output: %s\", invocation, result)\n\t}\n\tif !strings.Contains(result, \"function minimization succeeded: found bad fcn 2\") {\n\t\tt.Fatalf(\"failed to minimize package (invocation %q): output: %s\", invocation, result)\n\t}\n}\n\nfunc testMinimization2(t *testing.T, binaryPath string) {\n\tif binaryPath == \"\" {\n\t\tt.Skipf(\"No runner binary\")\n\t}\n\tt.Parallel()\n\t// Fire off the runner passing it -emitbad=2, so that the\n\t// generated code forces a runtime error. Verify that it does\n\t// fail, and that the error is reflective.\n\targs := []string{\"-emitbad=2\", \"-badfcnidx=1\", \"-badpkgidx=1\",\n\t\t\"-forcetmpclean\", \"-cleancache=0\",\n\t\t\"-numit=1\", \"-numfcns=3\", \"-numpkgs=3\", \"-seed=55909\"}\n\tinvocation := fmt.Sprintf(\"%s %v\", binaryPath, args)\n\tc := exec.Command(binaryPath, args...)\n\tb, err := c.CombinedOutput()\n\tt.Logf(\"%s\\n\", b)\n\tif err == nil {\n\t\tt.Fatalf(\"unexpected pass of fuzz-runner (invocation %q): %v\", invocation, err)\n\t}\n\tresult := string(b)\n\tif !strings.Contains(result, \"Error: fail\") || !strings.Contains(result, \"Checker1.Test1\") {\n\t\tt.Fatalf(\"-emitbad=2 did not trigger runtime error (invocation %q): output: %s\", invocation, result)\n\t}\n\tif !strings.Contains(result, \"package minimization succeeded: found bad pkg 1\") {\n\t\tt.Fatalf(\"failed to minimize package (invocation %q): output: %s\", invocation, result)\n\t}\n\tif !strings.Contains(result, \"function minimization succeeded: found bad fcn 1\") {\n\t\tt.Fatalf(\"failed to minimize package (invocation %q): output: %s\", invocation, result)\n\t}\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/fuzz-runner/runner.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Program for performing test runs using \"fuzz-driver\".\n// Main loop iteratively runs \"fuzz-driver\" to create a corpus,\n// then builds and runs the code. If a failure in the run is\n// detected, then a testcase minimization phase kicks in.\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\tgenerator \"golang.org/x/tools/cmd/signature-fuzzer/internal/fuzz-generator\"\n)\n\nconst pkName = \"fzTest\"\n\n// Basic options\nvar verbflag = flag.Int(\"v\", 0, \"Verbose trace output level\")\nvar loopitflag = flag.Int(\"numit\", 10, \"Number of main loop iterations to run\")\nvar seedflag = flag.Int64(\"seed\", -1, \"Random seed\")\nvar execflag = flag.Bool(\"execdriver\", false, \"Exec fuzz-driver binary instead of invoking generator directly\")\nvar numpkgsflag = flag.Int(\"numpkgs\", 50, \"Number of test packages\")\nvar numfcnsflag = flag.Int(\"numfcns\", 20, \"Number of test functions per package.\")\n\n// Debugging/testing options. These tell the generator to emit \"bad\" code so as to\n// test the logic for detecting errors and/or minimization.\nvar emitbadflag = flag.Int(\"emitbad\", -1, \"[Testing only] force generator to emit 'bad' code.\")\nvar selbadpkgflag = flag.Int(\"badpkgidx\", 0, \"[Testing only] select index of bad package (used with -emitbad)\")\nvar selbadfcnflag = flag.Int(\"badfcnidx\", 0, \"[Testing only] select index of bad function (used with -emitbad)\")\nvar forcetmpcleanflag = flag.Bool(\"forcetmpclean\", false, \"[Testing only] force cleanup of temp dir\")\nvar cleancacheflag = flag.Bool(\"cleancache\", true, \"[Testing only] don't clean the go cache\")\nvar raceflag = flag.Bool(\"race\", false, \"[Testing only] build generated code with -race\")\n\nfunc verb(vlevel int, s string, a ...any) {\n\tif *verbflag >= vlevel {\n\t\tfmt.Printf(s, a...)\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\n\nfunc warn(s string, a ...any) {\n\tfmt.Fprintf(os.Stderr, s, a...)\n\tfmt.Fprintf(os.Stderr, \"\\n\")\n}\n\nfunc fatal(s string, a ...any) {\n\tfmt.Fprintf(os.Stderr, s, a...)\n\tfmt.Fprintf(os.Stderr, \"\\n\")\n\tos.Exit(1)\n}\n\ntype config struct {\n\tgenerator.GenConfig\n\ttmpdir       string\n\tgendir       string\n\tbuildOutFile string\n\trunOutFile   string\n\tgcflags      string\n\tnerrors      int\n}\n\nfunc usage(msg string) {\n\tif len(msg) > 0 {\n\t\tfmt.Fprintf(os.Stderr, \"error: %s\\n\", msg)\n\t}\n\tfmt.Fprintf(os.Stderr, \"usage: fuzz-runner [flags]\\n\\n\")\n\tflag.PrintDefaults()\n\tfmt.Fprintf(os.Stderr, \"Example:\\n\\n\")\n\tfmt.Fprintf(os.Stderr, \"  fuzz-runner -numit=500 -numpkgs=11 -numfcns=13 -seed=10101\\n\\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\tRuns 500 rounds of test case generation\\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\tusing random see 10101, in each round emitting\\n\")\n\tfmt.Fprintf(os.Stderr, \"  \\t11 packages each with 13 function pairs.\\n\")\n\n\tos.Exit(2)\n}\n\n// docmd executes the specified command in the dir given and pipes the\n// output to stderr. return status is 0 if command passed, 1\n// otherwise.\nfunc docmd(cmd []string, dir string) int {\n\tverb(2, \"docmd: %s\", strings.Join(cmd, \" \"))\n\tc := exec.Command(cmd[0], cmd[1:]...)\n\tif dir != \"\" {\n\t\tc.Dir = dir\n\t}\n\tb, err := c.CombinedOutput()\n\tst := 0\n\tif err != nil {\n\t\twarn(\"error executing cmd %s: %v\",\n\t\t\tstrings.Join(cmd, \" \"), err)\n\t\tst = 1\n\t}\n\tos.Stderr.Write(b)\n\treturn st\n}\n\n// docmdout forks and execs command 'cmd' in dir 'dir', redirecting\n// stderr and stdout from the execution to file 'outfile'.\nfunc docmdout(cmd []string, dir string, outfile string) int {\n\tof, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)\n\tif err != nil {\n\t\tfatal(\"opening outputfile %s: %v\", outfile, err)\n\t}\n\tc := exec.Command(cmd[0], cmd[1:]...)\n\tdefer of.Close()\n\tif dir != \"\" {\n\t\tverb(2, \"setting cmd.Dir to %s\", dir)\n\t\tc.Dir = dir\n\t}\n\tverb(2, \"docmdout: %s > %s\", strings.Join(cmd, \" \"), outfile)\n\tc.Stdout = of\n\tc.Stderr = of\n\terr = c.Run()\n\tst := 0\n\tif err != nil {\n\t\twarn(\"error executing cmd %s: %v\",\n\t\t\tstrings.Join(cmd, \" \"), err)\n\t\tst = 1\n\t}\n\treturn st\n}\n\n// gen is the main hook for kicking off code generation. For\n// non-minimization runs, 'singlepk' and 'singlefn' will both be -1\n// (indicating that we want all functions and packages to be\n// generated).  If 'singlepk' is set to a non-negative value, then\n// code generation will be restricted to the single package with that\n// index (as a try at minimization), similarly with 'singlefn'\n// restricting the codegen to a single specified function.\nfunc (c *config) gen(singlepk int, singlefn int) {\n\n\t// clean the output dir\n\tverb(2, \"cleaning outdir %s\", c.gendir)\n\tif err := os.RemoveAll(c.gendir); err != nil {\n\t\tfatal(\"error cleaning gen dir %s: %v\", c.gendir, err)\n\t}\n\n\t// emit code into the output dir. Here we either invoke the\n\t// generator directly, or invoke fuzz-driver if -execflag is\n\t// set.  If the code generation process itself fails, this is\n\t// typically a bug in the fuzzer itself, so it gets reported\n\t// as a fatal error.\n\tif *execflag {\n\t\targs := []string{\"fuzz-driver\",\n\t\t\t\"-numpkgs\", strconv.Itoa(c.NumTestPackages),\n\t\t\t\"-numfcns\", strconv.Itoa(c.NumTestFunctions),\n\t\t\t\"-seed\", strconv.Itoa(int(c.Seed)),\n\t\t\t\"-outdir\", c.OutDir,\n\t\t\t\"-pkgpath\", pkName,\n\t\t\t\"-maxfail\", strconv.Itoa(c.MaxFail)}\n\t\tif singlepk != -1 {\n\t\t\targs = append(args, \"-pkgmask\", strconv.Itoa(singlepk))\n\t\t}\n\t\tif singlefn != -1 {\n\t\t\targs = append(args, \"-fcnmask\", strconv.Itoa(singlefn))\n\t\t}\n\t\tif *emitbadflag != 0 {\n\t\t\targs = append(args, \"-emitbad\", strconv.Itoa(*emitbadflag),\n\t\t\t\t\"-badpkgidx\", strconv.Itoa(*selbadpkgflag),\n\t\t\t\t\"-badfcnidx\", strconv.Itoa(*selbadfcnflag))\n\t\t}\n\t\tverb(1, \"invoking fuzz-driver with args: %v\", args)\n\t\tst := docmd(args, \"\")\n\t\tif st != 0 {\n\t\t\tfatal(\"fatal error: generation failed, cmd was: %v\", args)\n\t\t}\n\t} else {\n\t\tif singlepk != -1 {\n\t\t\tc.PkgMask = map[int]int{singlepk: 1}\n\t\t}\n\t\tif singlefn != -1 {\n\t\t\tc.FcnMask = map[int]int{singlefn: 1}\n\t\t}\n\t\tverb(1, \"invoking generator.Generate with config: %v\", c.GenConfig)\n\t\terrs := generator.Generate(c.GenConfig)\n\t\tif errs != 0 {\n\t\t\tlog.Fatal(\"errors during generation\")\n\t\t}\n\t}\n}\n\n// action performs a selected action/command in the generated code dir.\nfunc (c *config) action(cmd []string, outfile string, emitout bool) int {\n\tst := docmdout(cmd, c.gendir, outfile)\n\tif emitout {\n\t\tcontent, err := os.ReadFile(outfile)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Fprintf(os.Stderr, \"%s\", content)\n\t}\n\treturn st\n}\n\nfunc binaryName() string {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn pkName + \".exe\"\n\t} else {\n\t\treturn \"./\" + pkName\n\t}\n}\n\n// build builds a generated corpus of Go code. If 'emitout' is set, then dump out the\n// results of the build after it completes (during minimization emitout is set to false,\n// since there is no need to see repeated errors).\nfunc (c *config) build(emitout bool) int {\n\t// Issue a build of the generated code.\n\tc.buildOutFile = filepath.Join(c.tmpdir, \"build.err.txt\")\n\tcmd := []string{\"go\", \"build\", \"-o\", binaryName()}\n\tif c.gcflags != \"\" {\n\t\tcmd = append(cmd, \"-gcflags=all=\"+c.gcflags)\n\t}\n\tif *raceflag {\n\t\tcmd = append(cmd, \"-race\")\n\t}\n\tcmd = append(cmd, \".\")\n\tverb(1, \"build command is: %v\", cmd)\n\treturn c.action(cmd, c.buildOutFile, emitout)\n}\n\n// run invokes a binary built from a generated corpus of Go code. If\n// 'emitout' is set, then dump out the results of the run after it\n// completes.\nfunc (c *config) run(emitout bool) int {\n\t// Issue a run of the generated code.\n\tc.runOutFile = filepath.Join(c.tmpdir, \"run.err.txt\")\n\tcmd := []string{filepath.Join(c.gendir, binaryName())}\n\tverb(1, \"run command is: %v\", cmd)\n\treturn c.action(cmd, c.runOutFile, emitout)\n}\n\ntype minimizeMode int\n\nconst (\n\tminimizeBuildFailure = iota\n\tminimizeRuntimeFailure\n)\n\n// minimize tries to minimize a failing scenario down to a single\n// package and/or function if possible. This is done using an\n// iterative search. Here 'minimizeMode' tells us whether we're\n// looking for a compile-time error or a runtime error.\nfunc (c *config) minimize(mode minimizeMode) int {\n\n\tverb(0, \"... starting minimization for failed directory %s\", c.gendir)\n\n\tfoundPkg := -1\n\tfoundFcn := -1\n\n\t// Locate bad package. Uses brute-force linear search, could do better...\n\tfor pidx := 0; pidx < c.NumTestPackages; pidx++ {\n\t\tverb(1, \"minimization: trying package %d\", pidx)\n\t\tc.gen(pidx, -1)\n\t\tst := c.build(false)\n\t\tif mode == minimizeBuildFailure {\n\t\t\tif st != 0 {\n\t\t\t\t// Found.\n\t\t\t\tfoundPkg = pidx\n\t\t\t\tc.nerrors++\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\tif st != 0 {\n\t\t\t\twarn(\"run minimization: unexpected build failed while searching for bad pkg\")\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tst := c.run(false)\n\t\t\tif st != 0 {\n\t\t\t\t// Found.\n\t\t\t\tc.nerrors++\n\t\t\t\tverb(1, \"run minimization found bad package: %d\", pidx)\n\t\t\t\tfoundPkg = pidx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tif foundPkg == -1 {\n\t\tverb(0, \"** minimization failed, could not locate bad package\")\n\t\treturn 1\n\t}\n\twarn(\"package minimization succeeded: found bad pkg %d\", foundPkg)\n\n\t// clean unused packages\n\tfor pidx := 0; pidx < c.NumTestPackages; pidx++ {\n\t\tif pidx != foundPkg {\n\t\t\tchp := filepath.Join(c.gendir, fmt.Sprintf(\"%s%s%d\", c.Tag, generator.CheckerName, pidx))\n\t\t\tif err := os.RemoveAll(chp); err != nil {\n\t\t\t\tfatal(\"failed to clean pkg subdir %s: %v\", chp, err)\n\t\t\t}\n\t\t\tclp := filepath.Join(c.gendir, fmt.Sprintf(\"%s%s%d\", c.Tag, generator.CallerName, pidx))\n\t\t\tif err := os.RemoveAll(clp); err != nil {\n\t\t\t\tfatal(\"failed to clean pkg subdir %s: %v\", clp, err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Locate bad function. Again, brute force.\n\tfor fidx := 0; fidx < c.NumTestFunctions; fidx++ {\n\t\tc.gen(foundPkg, fidx)\n\t\tst := c.build(false)\n\t\tif mode == minimizeBuildFailure {\n\t\t\tif st != 0 {\n\t\t\t\t// Found.\n\t\t\t\tverb(1, \"build minimization found bad function: %d\", fidx)\n\t\t\t\tfoundFcn = fidx\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\tif st != 0 {\n\t\t\t\twarn(\"run minimization: unexpected build failed while searching for bad fcn\")\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tst := c.run(false)\n\t\t\tif st != 0 {\n\t\t\t\t// Found.\n\t\t\t\tverb(1, \"run minimization found bad function: %d\", fidx)\n\t\t\t\tfoundFcn = fidx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t// not the function we want ... continue the hunt\n\t}\n\tif foundFcn == -1 {\n\t\tverb(0, \"** function minimization failed, could not locate bad function\")\n\t\treturn 1\n\t}\n\twarn(\"function minimization succeeded: found bad fcn %d\", foundFcn)\n\n\treturn 0\n}\n\n// cleanTemp removes the temp dir we've been working with.\nfunc (c *config) cleanTemp() {\n\tif !*forcetmpcleanflag {\n\t\tif c.nerrors != 0 {\n\t\t\tverb(1, \"preserving temp dir %s\", c.tmpdir)\n\t\t\treturn\n\t\t}\n\t}\n\tverb(1, \"cleaning temp dir %s\", c.tmpdir)\n\tos.RemoveAll(c.tmpdir)\n}\n\n// perform is the top level driver routine for the program, containing the\n// main loop. Each iteration of the loop performs a generate/build/run\n// sequence, and then updates the seed afterwards if no failure is found.\n// If a failure is detected, we try to minimize it and then return without\n// attempting any additional tests.\nfunc (c *config) perform() int {\n\tdefer c.cleanTemp()\n\n\t// Main loop\n\tfor iter := 0; iter < *loopitflag; iter++ {\n\t\tif iter != 0 && iter%50 == 0 {\n\t\t\t// Note: cleaning the Go cache periodically is\n\t\t\t// pretty much a requirement if you want to do\n\t\t\t// things like overnight runs of the fuzzer,\n\t\t\t// but it is also a very unfriendly thing do\n\t\t\t// to if we're executing as part of a unit\n\t\t\t// test run (in which case there may be other\n\t\t\t// tests running in parallel with this\n\t\t\t// one). Check the \"cleancache\" flag before\n\t\t\t// doing this.\n\t\t\tif *cleancacheflag {\n\t\t\t\tdocmd([]string{\"go\", \"clean\", \"-cache\"}, \"\")\n\t\t\t}\n\t\t}\n\t\tverb(0, \"... begin iteration %d with current seed %d\", iter, c.Seed)\n\t\tc.gen(-1, -1)\n\t\tst := c.build(true)\n\t\tif st != 0 {\n\t\t\tc.minimize(minimizeBuildFailure)\n\t\t\treturn 1\n\t\t}\n\t\tst = c.run(true)\n\t\tif st != 0 {\n\t\t\tc.minimize(minimizeRuntimeFailure)\n\t\t\treturn 1\n\t\t}\n\t\t// update seed so that we get different code on the next iter.\n\t\tc.Seed += 101\n\t}\n\treturn 0\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"fuzz-runner: \")\n\tflag.Parse()\n\tif flag.NArg() != 0 {\n\t\tusage(\"unknown extra arguments\")\n\t}\n\tverb(1, \"in main, verblevel=%d\", *verbflag)\n\n\ttmpdir, err := os.MkdirTemp(\"\", \"fuzzrun\")\n\tif err != nil {\n\t\tfatal(\"creation of tempdir failed: %v\", err)\n\t}\n\tgendir := filepath.Join(tmpdir, \"fuzzTest\")\n\n\t// select starting seed\n\tif *seedflag == -1 {\n\t\tnow := time.Now()\n\t\t*seedflag = now.UnixNano() % 123456789\n\t}\n\n\t// set up params for this run\n\tc := &config{\n\t\tGenConfig: generator.GenConfig{\n\t\t\tNumTestPackages:  *numpkgsflag, // 100\n\t\t\tNumTestFunctions: *numfcnsflag, // 20\n\t\t\tSeed:             *seedflag,\n\t\t\tOutDir:           gendir,\n\t\t\tPragma:           \"-maxfail=9999\",\n\t\t\tPkgPath:          pkName,\n\t\t\tEmitBad:          *emitbadflag,\n\t\t\tBadPackageIdx:    *selbadpkgflag,\n\t\t\tBadFuncIdx:       *selbadfcnflag,\n\t\t},\n\t\ttmpdir: tmpdir,\n\t\tgendir: gendir,\n\t}\n\n\t// kick off the main loop.\n\tst := c.perform()\n\n\t// done\n\tverb(1, \"leaving main, num errors=%d\", c.nerrors)\n\tos.Exit(st)\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/fuzz-runner/testdata/himom.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nfunc main() {\n\tprintln(\"hi mom!\")\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/arrayparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// arrayparm describes a parameter of array type; it implements the\n// \"parm\" interface.\ntype arrayparm struct {\n\taname     string\n\tqname     string\n\tnelements uint8\n\teltype    parm\n\tslice     bool\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p arrayparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p arrayparm) TypeName() string {\n\treturn p.aname\n}\n\nfunc (p arrayparm) QualName() string {\n\treturn p.qname\n}\n\nfunc (p arrayparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s %s%s\", prefix, n, suffix))\n}\n\nfunc (p arrayparm) String() string {\n\treturn fmt.Sprintf(\"%s %d-element array of %s\", p.aname, p.nelements, p.eltype.String())\n}\n\nfunc (p arrayparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tvar buf bytes.Buffer\n\n\tverb(5, \"arrayparm.GenValue(%d)\", value)\n\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tbuf.WriteString(fmt.Sprintf(\"%s{\", n))\n\tfor i := 0; i < int(p.nelements); i++ {\n\t\tvar valstr string\n\t\tvalstr, value = s.GenValue(f, p.eltype, value, caller)\n\t\twriteCom(&buf, i)\n\t\tbuf.WriteString(valstr)\n\t}\n\tbuf.WriteString(\"}\")\n\treturn buf.String(), value\n}\n\nfunc (p arrayparm) GenElemRef(elidx int, path string) (string, parm) {\n\tene := p.eltype.NumElements()\n\tverb(4, \"begin GenElemRef(%d,%s) on %s ene %d\", elidx, path, p.String(), ene)\n\n\t// For empty arrays, convention is to return empty string\n\tif ene == 0 {\n\t\treturn \"\", &p\n\t}\n\n\t// Find slot within array of element of interest\n\tslot := elidx / ene\n\n\t// If this is the element we're interested in, return it\n\tif ene == 1 {\n\t\tverb(4, \"hit scalar element\")\n\t\tepath := fmt.Sprintf(\"%s[%d]\", path, slot)\n\t\tif path == \"_\" || p.IsBlank() {\n\t\t\tepath = \"_\"\n\t\t}\n\t\treturn epath, p.eltype\n\t}\n\n\tverb(4, \"recur slot=%d GenElemRef(%d,...)\", slot, elidx-(slot*ene))\n\n\t// Otherwise our victim is somewhere inside the slot\n\tppath := fmt.Sprintf(\"%s[%d]\", path, slot)\n\tif p.IsBlank() {\n\t\tppath = \"_\"\n\t}\n\treturn p.eltype.GenElemRef(elidx-(slot*ene), ppath)\n}\n\nfunc (p arrayparm) NumElements() int {\n\treturn p.eltype.NumElements() * int(p.nelements)\n}\n\nfunc (p arrayparm) HasPointer() bool {\n\treturn p.eltype.HasPointer() || p.slice\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/gen_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc mkGenState() *genstate {\n\n\treturn &genstate{\n\t\tGenConfig: GenConfig{\n\t\t\tTag:              \"gen\",\n\t\t\tOutDir:           \"/tmp\",\n\t\t\tNumTestPackages:  1,\n\t\t\tNumTestFunctions: 10,\n\t\t},\n\t\tipref:       \"foo/\",\n\t\tderefFuncs:  make(map[string]string),\n\t\tassignFuncs: make(map[string]string),\n\t\tallocFuncs:  make(map[string]string),\n\t\tglobVars:    make(map[string]string),\n\t}\n}\n\nfunc TestBasic(t *testing.T) {\n\tcheckTunables(tunables)\n\ts := mkGenState()\n\tfor i := range 1000 {\n\t\ts.wr = NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\tfp := s.GenFunc(i, i)\n\t\tvar buf bytes.Buffer\n\t\tvar b *bytes.Buffer = &buf\n\t\twr := NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\ts.wr = wr\n\t\ts.emitCaller(fp, b, i)\n\t\ts.wr = NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\ts.emitChecker(fp, b, i, true)\n\t\twr.Check(s.wr)\n\t}\n\tif s.errs != 0 {\n\t\tt.Errorf(\"%d errors during Generate\", s.errs)\n\t}\n}\n\nfunc TestMoreComplicated(t *testing.T) {\n\tsaveit := tunables\n\tdefer func() { tunables = saveit }()\n\n\tcheckTunables(tunables)\n\ts := mkGenState()\n\tfor i := range 10000 {\n\t\ts.wr = NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\tfp := s.GenFunc(i, i)\n\t\tvar buf bytes.Buffer\n\t\tvar b *bytes.Buffer = &buf\n\t\twr := NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\ts.wr = wr\n\t\ts.emitCaller(fp, b, i)\n\t\tverb(1, \"finished iter %d caller\", i)\n\t\ts.wr = NewWrapRand(int64(i), RandCtlChecks|RandCtlPanic)\n\t\ts.emitChecker(fp, b, i, true)\n\t\tverb(1, \"finished iter %d checker\", i)\n\t\twr.Check(s.wr)\n\t\tif s.errs != 0 {\n\t\t\tt.Errorf(\"%d errors during Generate iter %d\", s.errs, i)\n\t\t}\n\t}\n}\n\nfunc TestIsBuildable(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\n\ttd := t.TempDir()\n\tverb(1, \"generating into temp dir %s\", td)\n\tcheckTunables(tunables)\n\tpack := filepath.Base(td)\n\ts := GenConfig{\n\t\tTag:              \"x\",\n\t\tOutDir:           td,\n\t\tPkgPath:          pack,\n\t\tNumTestFunctions: 10,\n\t\tNumTestPackages:  10,\n\t\tMaxFail:          10,\n\t\tRandCtl:          RandCtlChecks | RandCtlPanic,\n\t}\n\terrs := Generate(s)\n\tif errs != 0 {\n\t\tt.Errorf(\"%d errors during Generate\", errs)\n\t}\n\n\tverb(1, \"building %s\\n\", td)\n\n\tcmd := exec.Command(\"go\", \"run\", \".\")\n\tcmd.Dir = td\n\tcoutput, cerr := cmd.CombinedOutput()\n\tif cerr != nil {\n\t\tt.Errorf(\"go build command failed: %s\\n\", string(coutput))\n\t}\n\tverb(1, \"output is: %s\\n\", string(coutput))\n}\n\n// TestExhaustive does a series of code generation runs, starting with\n// (relatively) simple code and then getting progressively more\n// complex (more params, deeper structs, turning on additional\n// features such as address-taken vars and reflect testing). The\n// intent here is mainly to insure that the tester still works if you\n// turn things on and off, e.g. that each feature is separately\n// controllable and not linked to other things.\nfunc TestExhaustive(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\n\tif testing.Short() {\n\t\tt.Skip(\"skipping test in short mode.\")\n\t}\n\n\ttd := t.TempDir()\n\tverb(1, \"generating into temp dir %s\", td)\n\n\tscenarios := []struct {\n\t\tname     string\n\t\tadjuster func()\n\t}{\n\t\t{\n\t\t\t\"minimal\",\n\t\t\tfunc() {\n\t\t\t\ttunables.nParmRange = 3\n\t\t\t\ttunables.nReturnRange = 3\n\t\t\t\ttunables.structDepth = 1\n\t\t\t\ttunables.recurPerc = 0\n\t\t\t\ttunables.methodPerc = 0\n\t\t\t\ttunables.doReflectCall = false\n\t\t\t\ttunables.doDefer = false\n\t\t\t\ttunables.takeAddress = false\n\t\t\t\ttunables.doFuncCallValues = false\n\t\t\t\ttunables.doSkipCompare = false\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"moreparms\",\n\t\t\tfunc() {\n\t\t\t\ttunables.nParmRange = 15\n\t\t\t\ttunables.nReturnRange = 7\n\t\t\t\ttunables.structDepth = 3\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addrecur\",\n\t\t\tfunc() {\n\t\t\t\ttunables.recurPerc = 20\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addmethod\",\n\t\t\tfunc() {\n\t\t\t\ttunables.methodPerc = 25\n\t\t\t\ttunables.pointerMethodCallPerc = 30\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addtakeaddr\",\n\t\t\tfunc() {\n\t\t\t\ttunables.takeAddress = true\n\t\t\t\ttunables.takenFraction = 20\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addreflect\",\n\t\t\tfunc() {\n\t\t\t\ttunables.doReflectCall = true\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"adddefer\",\n\t\t\tfunc() {\n\t\t\t\ttunables.doDefer = true\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addfuncval\",\n\t\t\tfunc() {\n\t\t\t\ttunables.doFuncCallValues = true\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"addfuncval\",\n\t\t\tfunc() {\n\t\t\t\ttunables.doSkipCompare = true\n\t\t\t\tcheckTunables(tunables)\n\t\t\t},\n\t\t},\n\t}\n\n\t// Loop over scenarios and make sure each one works properly.\n\tfor i, s := range scenarios {\n\t\tt.Logf(\"running %s\\n\", s.name)\n\t\ts.adjuster()\n\t\tos.RemoveAll(td)\n\t\tpack := filepath.Base(td)\n\t\tc := GenConfig{\n\t\t\tTag:              \"x\",\n\t\t\tOutDir:           td,\n\t\t\tPkgPath:          pack,\n\t\t\tNumTestFunctions: 10,\n\t\t\tNumTestPackages:  10,\n\t\t\tSeed:             int64(i + 9),\n\t\t\tMaxFail:          10,\n\t\t\tRandCtl:          RandCtlChecks | RandCtlPanic,\n\t\t}\n\t\terrs := Generate(c)\n\t\tif errs != 0 {\n\t\t\tt.Errorf(\"%d errors during scenarios %q Generate\", errs, s.name)\n\t\t}\n\t\tcmd := exec.Command(\"go\", \"run\", \".\")\n\t\tcmd.Dir = td\n\t\tcoutput, cerr := cmd.CombinedOutput()\n\t\tif cerr != nil {\n\t\t\tt.Fatalf(\"run failed for scenario %q:  %s\\n\", s.name, string(coutput))\n\t\t}\n\t\tverb(1, \"output is: %s\\n\", string(coutput))\n\t}\n}\n\nfunc TestEmitBadBuildFailure(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\n\ttd := t.TempDir()\n\tverb(1, \"generating into temp dir %s\", td)\n\n\tcheckTunables(tunables)\n\tpack := filepath.Base(td)\n\ts := GenConfig{\n\t\tTag:              \"x\",\n\t\tOutDir:           td,\n\t\tPkgPath:          pack,\n\t\tNumTestFunctions: 10,\n\t\tNumTestPackages:  10,\n\t\tMaxFail:          10,\n\t\tRandCtl:          RandCtlChecks | RandCtlPanic,\n\t\tEmitBad:          1,\n\t}\n\terrs := Generate(s)\n\tif errs != 0 {\n\t\tt.Errorf(\"%d errors during Generate\", errs)\n\t}\n\n\tcmd := exec.Command(\"go\", \"build\", \".\")\n\tcmd.Dir = td\n\tcoutput, cerr := cmd.CombinedOutput()\n\tif cerr == nil {\n\t\tt.Errorf(\"go build command passed, expected failure. output: %s\\n\", string(coutput))\n\t}\n}\n\nfunc TestEmitBadRunFailure(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the dependencies are not available on android\")\n\t}\n\n\ttd := t.TempDir()\n\tverb(1, \"generating into temp dir %s\", td)\n\n\tcheckTunables(tunables)\n\tpack := filepath.Base(td)\n\ts := GenConfig{\n\t\tTag:              \"x\",\n\t\tOutDir:           td,\n\t\tPkgPath:          pack,\n\t\tNumTestFunctions: 10,\n\t\tNumTestPackages:  10,\n\t\tMaxFail:          10,\n\t\tRandCtl:          RandCtlChecks | RandCtlPanic,\n\t\tEmitBad:          2,\n\t}\n\terrs := Generate(s)\n\tif errs != 0 {\n\t\tt.Errorf(\"%d errors during Generate\", errs)\n\t}\n\n\t// build\n\tcmd := exec.Command(\"go\", \"build\", \".\")\n\tcmd.Dir = td\n\tcoutput, cerr := cmd.CombinedOutput()\n\tif cerr != nil {\n\t\tt.Fatalf(\"build failed: %s\\n\", string(coutput))\n\t}\n\n\t// run\n\tcmd = exec.Command(\"./\" + pack)\n\tcmd.Dir = td\n\tcoutput, cerr = cmd.CombinedOutput()\n\tif cerr == nil {\n\t\tt.Fatalf(\"run passed, expected failure -- run output: %s\", string(coutput))\n\t}\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/generator.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This package generates source code for a stand-alone Go program\n// useful for function signature fuzzing. The generated program is a\n// series of function pairs, a \"Caller\" function and a \"Checker\"\n// function. The signature of the Checker function is generated\n// randomly (random number of parameters and returns, each with\n// randomly chosen types). The \"Caller\" func contains invocations of\n// the \"Checker\" function, each passing randomly chosen values to the\n// params of the \"Checker\", then the caller verifies that expected\n// values are returned correctly.  The \"Checker\" function in turn has\n// code to verify that the expected values arrive correctly, and so\n// on.\n//\n// The main exported items of interest for this package are:\n//\n// - the Generate function, which takes a GenConfig object and emits\n//   code according to the config's specification\n//\n// - the GenConfig struct, which is basically a large collection of\n//   knobs/switches to control the mechanics of how/where code is\n//   generated\n//\n// - the TunableParams struct, which controls the nature of the\n//   generated code (for example, the maximum number of function\n//   parameters, etc), and the SetTunables func which tells the\n//   package what tunable parameters to use.\n\n// Notes for posterity:\n// - many parts of this package would have been better off being written\n//   using text/template instead of generating code directly; perhaps\n//   at some point it could be converted over (big job).\n// - for the various 'fractions' fields in the TunableParams struct,\n//   it would be good to have a named type of some sort, with methods\n//   for managing things like checking to make sure values sum to 100.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha1\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// GenConfig contains configuration parameters relating to the\n// mechanics of the code generation, e.g. how many packages/functions\n// to emit, path to a directory into which we place the generated\n// code, prefixes/packagenames for the generate code, and so on.\ntype GenConfig struct {\n\t// Tag is a string prefix prepended to functions within\n\t// the generated code.\n\tTag string\n\n\t// Output directory in to which we'll emit generated code.\n\t// This will be created if it does not exist.\n\tOutDir string\n\n\t// Packagepath prefix given to the generated code.\n\tPkgPath string\n\n\t// Number of test packages created within the generated corpus.\n\t// Each test package is essentially an independent collection\n\t// generated code; the point of having multiple packages is to\n\t// be able to get faster builds (more parallelism), and to avoid\n\t// the compile time issues that crop up with 'giant' packages.\n\tNumTestPackages int\n\n\t// Number of test function pairs within each generated test package.\n\t// Each pair consists of a \"caller\" function and  \"callee\" function.\n\tNumTestFunctions int\n\n\t// Seed for random number generator.\n\tSeed int64\n\n\t// Pragma is a \"// go:...\" compiler directive to apply to the\n\t// callee function as part of a generated function pair.\n\tPragma string\n\n\t// Function and package mask used for minimization purposes.\n\t// If a given mask is non-nil, then the generator will only\n\t// emit code for a given func or package if its index is\n\t// present in the mask map.\n\tFcnMask map[int]int\n\tPkgMask map[int]int\n\n\t// Maximum number of failures to encounter before bailing out.\n\tMaxFail int\n\n\t// forcestackgrowth if set tells the generator to insert\n\t// calls to runtime.gcTestMoveStackOnNextCall at various points\n\t// in the generated code.\n\tForceStackGrowth bool\n\n\t// Random number generator control flag (debugging)\n\tRandCtl int\n\n\t// Tells the generator to run \"goimports\" on the emitted code.\n\tRunGoImports bool\n\n\t// Debugging/testing hook. If set to 1, emit code that will cause the\n\t// build to fail; if set to 2, emit code that will cause a test to fail.\n\tEmitBad int\n\n\t// If EmitBad above is set, then these can be used to select the ID of\n\t// a specific bad func/package.\n\tBadPackageIdx int\n\tBadFuncIdx    int\n}\n\nconst CallerName = \"Caller\"\nconst CheckerName = \"Checker\"\n\n// TunableParams contains configuration parameters that control the\n// flavor of code generated for a given test function. This includes\n// things like the number of params/returns, the percentages of types\n// (int, struct, etc) of the params/returns, and so on.\ntype TunableParams struct {\n\t// between 0 and N params\n\tnParmRange uint8\n\n\t// between 0 and N returns\n\tnReturnRange uint8\n\n\t// structs have between 0 and N members\n\tnStructFields uint8\n\n\t// arrays/slices have between 0 and N elements\n\tnArrayElements uint8\n\n\t// fraction of slices vs arrays. This is a value between 0 and 100 (0 meaning\n\t// no slices [only arrays] and 100 meaning all slices, no arrays).\n\tsliceFraction uint8\n\n\t// Controls how often \"int\" vars wind up as 8/16/32/64, should\n\t// add up to 100. Ex: 100 0 0 0 means all ints are 8 bit, 25\n\t// 25 25 25 means equal likelihood of all types.\n\tintBitRanges [4]uint8\n\n\t// Similar to the above but for 32/64 float types\n\tfloatBitRanges [2]uint8\n\n\t// Similar to the above but for unsigned, signed ints.\n\tunsignedRanges [2]uint8\n\n\t// Percentage of params, struct fields that should be \"_\". Ranges\n\t// from 0 to 100.\n\tblankPerc uint8\n\n\t// How deeply structs are allowed to be nested (ranges from 0 to N).\n\tstructDepth uint8\n\n\t// Fraction of param and return types assigned to each of:\n\t// struct/array/map/pointer/int/float/complex/byte/string at the\n\t// top level. If nesting precludes using a struct, other types\n\t// are chosen from instead according to same proportions. The sum\n\t// of typeFractions values should add up to 100.\n\ttypeFractions [9]uint8\n\n\t// Percentage of the time we'll emit recursive calls, from 0 to 100.\n\trecurPerc uint8\n\n\t// Percentage of time that we turn the test function into a method,\n\t// and if it is a method, fraction of time that we use a pointer\n\t// method call vs value method call. Each range from 0 to 100.\n\tmethodPerc            uint8\n\tpointerMethodCallPerc uint8\n\n\t// If true, test reflect.Call path as well.\n\tdoReflectCall bool\n\n\t// If true, then randomly take addresses of params/returns.\n\ttakeAddress bool\n\n\t// Fraction of the time that any params/returns are address taken.\n\t// Ranges from 0 to 100.\n\ttakenFraction uint8\n\n\t// For a given address-taken param or return, controls the\n\t// manner in which the indirect read or write takes\n\t// place. This is a set of percentages for\n\t// not/simple/passed/heap, where \"not\" means not address\n\t// taken, \"simple\" means a simple read or write, \"passed\"\n\t// means that the address is passed to a well-behaved\n\t// function, and \"heap\" means that the address is assigned to\n\t// a global. Values in addrFractions should add up to 100.\n\taddrFractions [4]uint8\n\n\t// If true, then perform testing of go/defer statements.\n\tdoDefer bool\n\n\t// fraction of test functions for which we emit a defer. Ranges from 0 to 100.\n\tdeferFraction uint8\n\n\t// If true, randomly pick between emitting a value by literal\n\t// (e.g. \"int(1)\" vs emitting a call to a function that\n\t// will produce the same value (e.g. \"myHelperEmitsInt1()\").\n\tdoFuncCallValues bool\n\n\t// Fraction of the time that we emit a function call to create\n\t// a param value vs emitting a literal. Ranges from 0 to 100.\n\tfuncCallValFraction uint8\n\n\t// If true, randomly decide to not check selected components of\n\t// a composite value (e.g. for a struct, check field F1 but not F2).\n\t// The intent is to generate partially live values.\n\tdoSkipCompare bool\n\n\t// Fraction of the time that we decided to skip sub-components of\n\t// composite values. Ranges from 0 to 100.\n\tskipCompareFraction uint8\n}\n\n// SetTunables accepts a TunableParams object, checks to make sure\n// that the settings in it are sane/logical, and applies the\n// parameters for any subsequent calls to the Generate function. This\n// function will issue a fatal error if any of the tunable params are\n// incorrect/insane (for example, a 'percentage' value outside the\n// range of 0-100).\nfunc SetTunables(t TunableParams) {\n\tcheckTunables(t)\n\ttunables = t\n}\n\nvar defaultTypeFractions = [9]uint8{\n\t10, // struct\n\t10, // array\n\t10, // map\n\t15, // pointer\n\t20, // numeric\n\t15, // float\n\t5,  // complex\n\t5,  // byte\n\t10, // string\n}\n\nconst (\n\t// Param not address taken.\n\tStructTfIdx = iota\n\tArrayTfIdx\n\tMapTfIdx\n\tPointerTfIdx\n\tNumericTfIdx\n\tFloatTfIdx\n\tComplexTfIdx\n\tByteTfIdx\n\tStringTfIdx\n)\n\nvar tunables = TunableParams{\n\tnParmRange:            15,\n\tnReturnRange:          7,\n\tnStructFields:         7,\n\tnArrayElements:        5,\n\tsliceFraction:         50,\n\tintBitRanges:          [4]uint8{30, 20, 20, 30},\n\tfloatBitRanges:        [2]uint8{50, 50},\n\tunsignedRanges:        [2]uint8{50, 50},\n\tblankPerc:             15,\n\tstructDepth:           3,\n\ttypeFractions:         defaultTypeFractions,\n\trecurPerc:             20,\n\tmethodPerc:            10,\n\tpointerMethodCallPerc: 50,\n\tdoReflectCall:         true,\n\tdoDefer:               true,\n\ttakeAddress:           true,\n\tdoFuncCallValues:      true,\n\ttakenFraction:         20,\n\tdeferFraction:         30,\n\tfuncCallValFraction:   5,\n\tdoSkipCompare:         true,\n\tskipCompareFraction:   10,\n\taddrFractions:         [4]uint8{50, 25, 15, 10},\n}\n\nfunc DefaultTunables() TunableParams {\n\treturn tunables\n}\n\nfunc checkTunables(t TunableParams) {\n\tvar s int = 0\n\n\tfor _, v := range t.intBitRanges {\n\t\ts += int(v)\n\t}\n\tif s != 100 {\n\t\tlog.Fatal(errors.New(\"intBitRanges tunable does not sum to 100\"))\n\t}\n\n\ts = 0\n\tfor _, v := range t.unsignedRanges {\n\t\ts += int(v)\n\t}\n\tif s != 100 {\n\t\tlog.Fatal(errors.New(\"unsignedRanges tunable does not sum to 100\"))\n\t}\n\n\tif t.blankPerc > 100 {\n\t\tlog.Fatal(errors.New(\"blankPerc bad value, over 100\"))\n\t}\n\tif t.recurPerc > 100 {\n\t\tlog.Fatal(errors.New(\"recurPerc bad value, over 100\"))\n\t}\n\tif t.methodPerc > 100 {\n\t\tlog.Fatal(errors.New(\"methodPerc bad value, over 100\"))\n\t}\n\tif t.pointerMethodCallPerc > 100 {\n\t\tlog.Fatal(errors.New(\"pointerMethodCallPerc bad value, over 100\"))\n\t}\n\n\ts = 0\n\tfor _, v := range t.floatBitRanges {\n\t\ts += int(v)\n\t}\n\tif s != 100 {\n\t\tlog.Fatal(errors.New(\"floatBitRanges tunable does not sum to 100\"))\n\t}\n\n\ts = 0\n\tfor _, v := range t.typeFractions {\n\t\ts += int(v)\n\t}\n\tif s != 100 {\n\t\tpanic(errors.New(\"typeFractions tunable does not sum to 100\"))\n\t}\n\n\ts = 0\n\tfor _, v := range t.addrFractions {\n\t\ts += int(v)\n\t}\n\tif s != 100 {\n\t\tlog.Fatal(errors.New(\"addrFractions tunable does not sum to 100\"))\n\t}\n\tif t.takenFraction > 100 {\n\t\tlog.Fatal(errors.New(\"takenFraction not between 0 and 100\"))\n\t}\n\tif t.deferFraction > 100 {\n\t\tlog.Fatal(errors.New(\"deferFraction not between 0 and 100\"))\n\t}\n\tif t.sliceFraction > 100 {\n\t\tlog.Fatal(errors.New(\"sliceFraction not between 0 and 100\"))\n\t}\n\tif t.skipCompareFraction > 100 {\n\t\tlog.Fatal(errors.New(\"skipCompareFraction not between 0 and 100\"))\n\t}\n}\n\nfunc (t *TunableParams) DisableReflectionCalls() {\n\tt.doReflectCall = false\n}\n\nfunc (t *TunableParams) DisableRecursiveCalls() {\n\tt.recurPerc = 0\n}\n\nfunc (t *TunableParams) DisableMethodCalls() {\n\tt.methodPerc = 0\n}\n\nfunc (t *TunableParams) DisableTakeAddr() {\n\tt.takeAddress = false\n}\n\nfunc (t *TunableParams) DisableDefer() {\n\tt.doDefer = false\n}\n\nfunc (t *TunableParams) LimitInputs(n int) error {\n\tif n > 100 {\n\t\treturn fmt.Errorf(\"value %d passed to LimitInputs is too large *(max 100)\", n)\n\t}\n\tif n < 0 {\n\t\treturn fmt.Errorf(\"value %d passed to LimitInputs is invalid\", n)\n\t}\n\tt.nParmRange = uint8(n)\n\treturn nil\n}\n\nfunc (t *TunableParams) LimitOutputs(n int) error {\n\tif n > 100 {\n\t\treturn fmt.Errorf(\"value %d passed to LimitOutputs is too large *(max 100)\", n)\n\t}\n\tif n < 0 {\n\t\treturn fmt.Errorf(\"value %d passed to LimitOutputs is invalid\", n)\n\t}\n\tt.nReturnRange = uint8(n)\n\treturn nil\n}\n\n// ParseMaskString parses a string of the form K,J,...,M-N,Q-R,...,Z\n// e.g. comma-separated integers or ranges of integers, returning the\n// result in a form suitable for FcnMask or PkgMask fields in a\n// Config. Here \"tag\" holds the mask flavor (fcn or pkg) and \"arg\" is\n// the string argument to be parsed.\nfunc ParseMaskString(arg string, tag string) (map[int]int, error) {\n\tif arg == \"\" {\n\t\treturn nil, nil\n\t}\n\tverb(1, \"%s mask is %s\", tag, arg)\n\tm := make(map[int]int)\n\tfor s := range strings.SplitSeq(arg, \":\") {\n\t\tif strings.Contains(s, \"-\") {\n\t\t\trng := strings.Split(s, \"-\")\n\t\t\tif len(rng) != 2 {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed range %s in %s mask arg\", s, tag)\n\t\t\t}\n\t\t\ti, err := strconv.Atoi(rng[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed range value %s in %s mask arg\", rng[0], tag)\n\t\t\t}\n\t\t\tj, err2 := strconv.Atoi(rng[1])\n\t\t\tif err2 != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed range value %s in %s mask arg\", rng[1], tag)\n\t\t\t}\n\t\t\tfor k := i; k < j; k++ {\n\t\t\t\tm[k] = 1\n\t\t\t}\n\t\t} else {\n\t\t\ti, err := strconv.Atoi(s)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed value %s in %s mask arg\", s, tag)\n\t\t\t}\n\t\t\tm[i] = 1\n\t\t}\n\t}\n\treturn m, nil\n}\n\nfunc writeCom(b *bytes.Buffer, i int) {\n\tif i != 0 {\n\t\tb.WriteString(\", \")\n\t}\n}\n\nvar Verbctl int = 0\n\nfunc verb(vlevel int, s string, a ...any) {\n\tif Verbctl >= vlevel {\n\t\tfmt.Printf(s, a...)\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\n\ntype funcdef struct {\n\tidx         int\n\tstructdefs  []structparm\n\tarraydefs   []arrayparm\n\ttypedefs    []typedefparm\n\tmapdefs     []mapparm\n\tmapkeytypes []parm\n\tmapkeytmps  []string\n\tmapkeyts    string\n\treceiver    parm\n\tparams      []parm\n\treturns     []parm\n\tvalues      []int\n\tdodefc      uint8\n\tdodefp      []uint8\n\trstack      int\n\trecur       bool\n\tisMethod    bool\n}\n\ntype genstate struct {\n\tGenConfig\n\tipref string\n\t//tag            string\n\t//numtpk         int\n\tpkidx int\n\terrs  int\n\t//pragma         string\n\t//sforce         bool\n\t//randctl        int\n\ttunables       TunableParams\n\ttstack         []TunableParams\n\tderefFuncs     map[string]string\n\tnewDerefFuncs  []funcdesc\n\tassignFuncs    map[string]string\n\tnewAssignFuncs []funcdesc\n\tallocFuncs     map[string]string\n\tnewAllocFuncs  []funcdesc\n\tgenvalFuncs    map[string]string\n\tnewGenvalFuncs []funcdesc\n\tglobVars       map[string]string\n\tnewGlobVars    []funcdesc\n\twr             *wraprand\n}\n\nfunc (s *genstate) intFlavor() string {\n\twhich := uint8(s.wr.Intn(100))\n\tif which < s.tunables.unsignedRanges[0] {\n\t\treturn \"uint\"\n\t}\n\treturn \"int\"\n}\n\nfunc (s *genstate) intBits() uint32 {\n\twhich := uint8(s.wr.Intn(100))\n\tvar t uint8 = 0\n\tvar bits uint32 = 8\n\tfor _, v := range s.tunables.intBitRanges {\n\t\tt += v\n\t\tif which < t {\n\t\t\treturn bits\n\t\t}\n\t\tbits *= 2\n\t}\n\treturn uint32(s.tunables.intBitRanges[3])\n}\n\nfunc (s *genstate) floatBits() uint32 {\n\twhich := uint8(s.wr.Intn(100))\n\tif which < s.tunables.floatBitRanges[0] {\n\t\treturn uint32(32)\n\t}\n\treturn uint32(64)\n}\n\nfunc (s *genstate) genAddrTaken() addrTakenHow {\n\twhich := uint8(s.wr.Intn(100))\n\tres := notAddrTaken\n\tvar t uint8 = 0\n\tfor _, v := range s.tunables.addrFractions {\n\t\tt += v\n\t\tif which < t {\n\t\t\treturn res\n\t\t}\n\t\tres++\n\t}\n\treturn notAddrTaken\n}\n\nfunc (s *genstate) pushTunables() {\n\ts.tstack = append(s.tstack, s.tunables)\n}\n\nfunc (s *genstate) popTunables() {\n\tif len(s.tstack) == 0 {\n\t\tpanic(\"untables stack underflow\")\n\t}\n\ts.tunables = s.tstack[0]\n\ts.tstack = s.tstack[1:]\n}\n\n// redistributeFraction accepts a value 'toIncorporate' and updates\n// 'typeFraction' to add in the values from 'toIncorporate' equally to\n// all slots not in 'avoid'. This is done by successively walking\n// through 'typeFraction' adding 1 to each non-avoid slot, then\n// repeating until we've added a total of 'toIncorporate' elements.\n// See precludeSelectedTypes below for more info.\nfunc (s *genstate) redistributeFraction(toIncorporate uint8, avoid []int) {\n\tinavoid := func(j int) bool {\n\t\treturn slices.Contains(avoid, j)\n\t}\n\n\tdoredis := func() {\n\t\tfor {\n\t\t\tfor i := range s.tunables.typeFractions {\n\t\t\t\tif inavoid(i) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\ts.tunables.typeFractions[i]++\n\t\t\t\ttoIncorporate--\n\t\t\t\tif toIncorporate == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tdoredis()\n\tcheckTunables(s.tunables)\n}\n\n// precludeSelectedTypes accepts a set of values (t, t2, ...)\n// corresponding to slots in 'typeFractions', sums up the values from\n// the slots, zeroes out the slots, and finally takes the values and\n// redistributes them equally to the other slots.  For example,\n// suppose 'typeFractions' starts as [10, 10, 10, 15, 20, 15, 5, 5, 10],\n// then we decide we want to eliminate or 'knock out' map types and\n// pointer types (slots 2 and 3 in the array above) going forward.  To\n// restore the invariant that values in 'typeFractions' sum to 100, we\n// take the values from slots 2 and 3 (a total of 25) and evenly\n// distribute those values to the other slots in the array.\nfunc (s *genstate) precludeSelectedTypes(t int, t2 ...int) {\n\tavoid := []int{t}\n\tavoid = append(avoid, t2...)\n\tf := uint8(0)\n\tfor _, idx := range avoid {\n\t\tf += s.tunables.typeFractions[idx]\n\t\ts.tunables.typeFractions[idx] = 0\n\t}\n\ts.redistributeFraction(f, avoid)\n}\n\nfunc (s *genstate) GenMapKeyType(f *funcdef, depth int, pidx int) parm {\n\ts.pushTunables()\n\tdefer s.popTunables()\n\t// maps we can't allow at all; pointers might be possible but\n\t//  would be too much work to arrange. Avoid slices as well.\n\ts.tunables.sliceFraction = 0\n\ts.precludeSelectedTypes(MapTfIdx, PointerTfIdx)\n\treturn s.GenParm(f, depth+1, false, pidx)\n}\n\nfunc (s *genstate) GenParm(f *funcdef, depth int, mkctl bool, pidx int) parm {\n\n\t// Enforcement for struct/array/map/pointer array nesting depth.\n\ttoodeep := depth >= int(s.tunables.structDepth)\n\tif toodeep {\n\t\ts.pushTunables()\n\t\tdefer s.popTunables()\n\t\ts.precludeSelectedTypes(StructTfIdx, ArrayTfIdx, MapTfIdx, PointerTfIdx)\n\t}\n\n\t// Convert tf into a cumulative sum\n\ttf := s.tunables.typeFractions\n\tsum := uint8(0)\n\tfor i := range len(tf) {\n\t\tsum += tf[i]\n\t\ttf[i] = sum\n\t}\n\n\tisblank := uint8(s.wr.Intn(100)) < s.tunables.blankPerc\n\taddrTaken := notAddrTaken\n\tif depth == 0 && tunables.takeAddress && !isblank {\n\t\taddrTaken = s.genAddrTaken()\n\t}\n\tisGenValFunc := tunables.doFuncCallValues &&\n\t\tuint8(s.wr.Intn(100)) < s.tunables.funcCallValFraction\n\n\t// Make adjusted selection (pick a bucket within tf)\n\twhich := uint8(s.wr.Intn(100))\n\tverb(3, \"which=%d\", which)\n\tvar retval parm\n\tswitch {\n\tcase which < tf[StructTfIdx]:\n\t\t{\n\t\t\tif toodeep {\n\t\t\t\tpanic(\"should not be here\")\n\t\t\t}\n\t\t\tvar sp structparm\n\t\t\tns := len(f.structdefs)\n\t\t\tsp.sname = fmt.Sprintf(\"StructF%dS%d\", f.idx, ns)\n\t\t\tsp.qname = fmt.Sprintf(\"%s.StructF%dS%d\",\n\t\t\t\ts.checkerPkg(pidx), f.idx, ns)\n\t\t\tf.structdefs = append(f.structdefs, sp)\n\t\t\ttnf := int64(s.tunables.nStructFields) / int64(depth+1)\n\t\t\tnf := int(s.wr.Intn(tnf))\n\t\t\tfor range nf {\n\t\t\t\tfp := s.GenParm(f, depth+1, false, pidx)\n\t\t\t\tskComp := tunables.doSkipCompare &&\n\t\t\t\t\tuint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction\n\t\t\t\tif skComp && checkableElements(fp) != 0 {\n\t\t\t\t\tfp.SetSkipCompare(SkipAll)\n\t\t\t\t}\n\t\t\t\tsp.fields = append(sp.fields, fp)\n\t\t\t}\n\t\t\tf.structdefs[ns] = sp\n\t\t\tretval = &sp\n\t\t}\n\tcase which < tf[ArrayTfIdx]:\n\t\t{\n\t\t\tif toodeep {\n\t\t\t\tpanic(\"should not be here\")\n\t\t\t}\n\t\t\tvar ap arrayparm\n\t\t\tns := len(f.arraydefs)\n\t\t\tnel := uint8(s.wr.Intn(int64(s.tunables.nArrayElements)))\n\t\t\tissl := uint8(s.wr.Intn(100)) < s.tunables.sliceFraction\n\t\t\tap.aname = fmt.Sprintf(\"ArrayF%dS%dE%d\", f.idx, ns, nel)\n\t\t\tap.qname = fmt.Sprintf(\"%s.ArrayF%dS%dE%d\", s.checkerPkg(pidx),\n\t\t\t\tf.idx, ns, nel)\n\t\t\tf.arraydefs = append(f.arraydefs, ap)\n\t\t\tap.nelements = nel\n\t\t\tap.slice = issl\n\t\t\tap.eltype = s.GenParm(f, depth+1, false, pidx)\n\t\t\tap.eltype.SetBlank(false)\n\t\t\tskComp := tunables.doSkipCompare &&\n\t\t\t\tuint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction\n\t\t\tif skComp && checkableElements(ap.eltype) != 0 {\n\t\t\t\tif issl {\n\t\t\t\t\tap.SetSkipCompare(SkipPayload)\n\t\t\t\t}\n\t\t\t}\n\t\t\tf.arraydefs[ns] = ap\n\t\t\tretval = &ap\n\t\t}\n\tcase which < tf[MapTfIdx]:\n\t\t{\n\t\t\tif toodeep {\n\t\t\t\tpanic(\"should not be here\")\n\t\t\t}\n\t\t\tvar mp mapparm\n\t\t\tns := len(f.mapdefs)\n\n\t\t\t// append early, since calls below might also append\n\t\t\tf.mapdefs = append(f.mapdefs, mp)\n\t\t\tf.mapkeytmps = append(f.mapkeytmps, \"\")\n\t\t\tf.mapkeytypes = append(f.mapkeytypes, mp.keytype)\n\t\t\tmp.aname = fmt.Sprintf(\"MapF%dM%d\", f.idx, ns)\n\t\t\tif f.mapkeyts == \"\" {\n\t\t\t\tf.mapkeyts = fmt.Sprintf(\"MapKeysF%d\", f.idx)\n\t\t\t}\n\t\t\tmp.qname = fmt.Sprintf(\"%s.MapF%dM%d\", s.checkerPkg(pidx),\n\t\t\t\tf.idx, ns)\n\t\t\tmkt := fmt.Sprintf(\"Mk%dt%d\", f.idx, ns)\n\t\t\tmp.keytmp = mkt\n\t\t\tmk := s.GenMapKeyType(f, depth+1, pidx)\n\t\t\tmp.keytype = mk\n\t\t\tmp.valtype = s.GenParm(f, depth+1, false, pidx)\n\t\t\tmp.valtype.SetBlank(false)\n\t\t\tmp.keytype.SetBlank(false)\n\t\t\t// now update the previously appended placeholders\n\t\t\tf.mapdefs[ns] = mp\n\t\t\tf.mapkeytypes[ns] = mk\n\t\t\tf.mapkeytmps[ns] = mkt\n\t\t\tretval = &mp\n\t\t}\n\tcase which < tf[PointerTfIdx]:\n\t\t{\n\t\t\tif toodeep {\n\t\t\t\tpanic(\"should not be here\")\n\t\t\t}\n\t\t\tpp := mkPointerParm(s.GenParm(f, depth+1, false, pidx))\n\t\t\tretval = &pp\n\t\t}\n\tcase which < tf[NumericTfIdx]:\n\t\t{\n\t\t\tvar ip numparm\n\t\t\tip.tag = s.intFlavor()\n\t\t\tip.widthInBits = s.intBits()\n\t\t\tif mkctl {\n\t\t\t\tip.ctl = true\n\t\t\t}\n\t\t\tretval = &ip\n\t\t}\n\tcase which < tf[FloatTfIdx]:\n\t\t{\n\t\t\tvar fp numparm\n\t\t\tfp.tag = \"float\"\n\t\t\tfp.widthInBits = s.floatBits()\n\t\t\tretval = &fp\n\t\t}\n\tcase which < tf[ComplexTfIdx]:\n\t\t{\n\t\t\tvar fp numparm\n\t\t\tfp.tag = \"complex\"\n\t\t\tfp.widthInBits = s.floatBits() * 2\n\t\t\tretval = &fp\n\t\t}\n\tcase which < tf[ByteTfIdx]:\n\t\t{\n\t\t\tvar bp numparm\n\t\t\tbp.tag = \"byte\"\n\t\t\tbp.widthInBits = 8\n\t\t\tretval = &bp\n\t\t}\n\tcase which < tf[StringTfIdx]:\n\t\t{\n\t\t\tvar sp stringparm\n\t\t\tsp.tag = \"string\"\n\t\t\tskComp := tunables.doSkipCompare &&\n\t\t\t\tuint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction\n\t\t\tif skComp {\n\t\t\t\tsp.SetSkipCompare(SkipPayload)\n\t\t\t}\n\t\t\tretval = &sp\n\t\t}\n\tdefault:\n\t\t{\n\t\t\t// fallback\n\t\t\tvar ip numparm\n\t\t\tip.tag = \"uint\"\n\t\t\tip.widthInBits = 8\n\t\t\tretval = &ip\n\t\t}\n\t}\n\tif !mkctl {\n\t\tretval.SetBlank(isblank)\n\t}\n\tretval.SetAddrTaken(addrTaken)\n\tretval.SetIsGenVal(isGenValFunc)\n\treturn retval\n}\n\nfunc (s *genstate) GenReturn(f *funcdef, depth int, pidx int) parm {\n\treturn s.GenParm(f, depth, false, pidx)\n}\n\n// GenFunc cooks up the random signature (and other attributes) of a\n// given checker function, returning a funcdef object that describes\n// the new fcn.\nfunc (s *genstate) GenFunc(fidx int, pidx int) *funcdef {\n\tf := new(funcdef)\n\tf.idx = fidx\n\tnumParams := int(s.wr.Intn(int64(1 + int(s.tunables.nParmRange))))\n\tnumReturns := int(s.wr.Intn(int64(1 + int(s.tunables.nReturnRange))))\n\tf.recur = uint8(s.wr.Intn(100)) < s.tunables.recurPerc\n\tf.isMethod = uint8(s.wr.Intn(100)) < s.tunables.methodPerc\n\tgenReceiverType := func() {\n\t\t// Receiver type can't be pointer type. Temporarily update\n\t\t// tunables to eliminate that possibility.\n\t\ts.pushTunables()\n\t\tdefer s.popTunables()\n\t\ts.precludeSelectedTypes(PointerTfIdx)\n\t\ttarget := s.GenParm(f, 0, false, pidx)\n\t\ttarget.SetBlank(false)\n\t\tf.receiver = s.makeTypedefParm(f, target, pidx)\n\t\tif f.receiver.IsBlank() {\n\t\t\tf.recur = false\n\t\t}\n\t}\n\tif f.isMethod {\n\t\tgenReceiverType()\n\t}\n\tneedControl := f.recur\n\tf.dodefc = uint8(s.wr.Intn(100))\n\tpTaken := uint8(s.wr.Intn(100)) < s.tunables.takenFraction\n\tfor range numParams {\n\t\tnewparm := s.GenParm(f, 0, needControl, pidx)\n\t\tif !pTaken {\n\t\t\tnewparm.SetAddrTaken(notAddrTaken)\n\t\t}\n\t\tif newparm.IsControl() {\n\t\t\tneedControl = false\n\t\t}\n\t\tf.params = append(f.params, newparm)\n\t\tf.dodefp = append(f.dodefp, uint8(s.wr.Intn(100)))\n\t}\n\tif f.recur && needControl {\n\t\tf.recur = false\n\t}\n\n\trTaken := uint8(s.wr.Intn(100)) < s.tunables.takenFraction\n\tfor range numReturns {\n\t\tr := s.GenReturn(f, 0, pidx)\n\t\tif !rTaken {\n\t\t\tr.SetAddrTaken(notAddrTaken)\n\t\t}\n\t\tf.returns = append(f.returns, r)\n\t}\n\tspw := uint(s.wr.Intn(11))\n\trstack := max(1<<spw, 4)\n\tf.rstack = rstack\n\treturn f\n}\n\nfunc genDeref(p parm) (parm, string) {\n\tcurp := p\n\tvar star strings.Builder\n\tfor {\n\t\tif pp, ok := curp.(*pointerparm); ok {\n\t\t\tstar.WriteString(\"*\")\n\t\t\tcurp = pp.totype\n\t\t} else {\n\t\t\treturn curp, star.String()\n\t\t}\n\t}\n}\n\nfunc (s *genstate) eqFuncRef(f *funcdef, t parm, caller bool) string {\n\tcp := \"\"\n\tif f.mapkeyts != \"\" {\n\t\tcp = \"mkt.\"\n\t} else if caller {\n\t\tcp = s.checkerPkg(s.pkidx) + \".\"\n\t}\n\treturn cp + \"Equal\" + t.TypeName()\n}\n\n// emitCompareFunc creates an 'equals' function for a specific\n// generated type (this is basically a way to compare objects that\n// contain pointer fields / pointery things).\nfunc (s *genstate) emitCompareFunc(f *funcdef, b *bytes.Buffer, p parm) {\n\tif !p.HasPointer() {\n\t\treturn\n\t}\n\n\ttn := p.TypeName()\n\tb.WriteString(fmt.Sprintf(\"// equal func for %s\\n\", tn))\n\tb.WriteString(\"//go:noinline\\n\")\n\trcvr := \"\"\n\tif f.mapkeyts != \"\" {\n\t\trcvr = fmt.Sprintf(\"(mkt *%s) \", f.mapkeyts)\n\t}\n\tb.WriteString(fmt.Sprintf(\"func %sEqual%s(left %s, right %s) bool {\\n\", rcvr, tn, tn, tn))\n\tb.WriteString(\"  return \")\n\tnumel := p.NumElements()\n\tncmp := 0\n\tfor i := range numel {\n\t\tlelref, lelparm := p.GenElemRef(i, \"left\")\n\t\trelref, _ := p.GenElemRef(i, \"right\")\n\t\tif lelref == \"\" || lelref == \"_\" {\n\t\t\tcontinue\n\t\t}\n\t\tbasep, star := genDeref(lelparm)\n\t\t// Handle *p where p is an empty struct.\n\t\tif basep.NumElements() == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif ncmp != 0 {\n\t\t\tb.WriteString(\"  && \")\n\t\t}\n\t\tncmp++\n\t\tif basep.HasPointer() {\n\t\t\tefn := s.eqFuncRef(f, basep, false)\n\t\t\tb.WriteString(fmt.Sprintf(\" %s(%s%s, %s%s)\", efn, star, lelref, star, relref))\n\t\t} else {\n\t\t\tb.WriteString(fmt.Sprintf(\"%s%s == %s%s\", star, lelref, star, relref))\n\t\t}\n\t}\n\tif ncmp == 0 {\n\t\tb.WriteString(\"true\")\n\t}\n\tb.WriteString(\"\\n}\\n\\n\")\n}\n\n// emitStructAndArrayDefs writes out definitions of the random types\n// we happened to cook up while generating code for a specific\n// function pair.\nfunc (s *genstate) emitStructAndArrayDefs(f *funcdef, b *bytes.Buffer) {\n\tfor _, str := range f.structdefs {\n\t\tb.WriteString(fmt.Sprintf(\"type %s struct {\\n\", str.sname))\n\t\tfor fi, sp := range str.fields {\n\t\t\tsp.Declare(b, \"  \"+str.FieldName(fi), \"\\n\", false)\n\t\t}\n\t\tb.WriteString(\"}\\n\\n\")\n\t\ts.emitCompareFunc(f, b, &str)\n\t}\n\tfor _, a := range f.arraydefs {\n\t\telems := fmt.Sprintf(\"%d\", a.nelements)\n\t\tif a.slice {\n\t\t\telems = \"\"\n\t\t}\n\t\tb.WriteString(fmt.Sprintf(\"type %s [%s]%s\\n\\n\", a.aname,\n\t\t\telems, a.eltype.TypeName()))\n\t\ts.emitCompareFunc(f, b, &a)\n\t}\n\tfor _, a := range f.mapdefs {\n\t\tb.WriteString(fmt.Sprintf(\"type %s map[%s]%s\\n\\n\", a.aname,\n\t\t\ta.keytype.TypeName(), a.valtype.TypeName()))\n\t\ts.emitCompareFunc(f, b, &a)\n\t}\n\tfor _, td := range f.typedefs {\n\t\tb.WriteString(fmt.Sprintf(\"type %s %s\\n\\n\", td.aname,\n\t\t\ttd.target.TypeName()))\n\t\ts.emitCompareFunc(f, b, &td)\n\t}\n\tif f.mapkeyts != \"\" {\n\t\tb.WriteString(fmt.Sprintf(\"type %s struct {\\n\", f.mapkeyts))\n\t\tfor i := range f.mapkeytypes {\n\t\t\tf.mapkeytypes[i].Declare(b, \"  \"+f.mapkeytmps[i], \"\\n\", false)\n\t\t}\n\t\tb.WriteString(\"}\\n\\n\")\n\t}\n}\n\n// GenValue method of genstate wraps the parm method of the same\n// name, but optionally returns a call to a function to produce\n// the value as opposed to a literal value.\nfunc (s *genstate) GenValue(f *funcdef, p parm, value int, caller bool) (string, int) {\n\tvar valstr string\n\tvalstr, value = p.GenValue(s, f, value, caller)\n\tif !s.tunables.doFuncCallValues || !p.IsGenVal() || caller {\n\t\treturn valstr, value\n\t}\n\n\tmkInvoc := func(fname string) string {\n\t\tmeth := \"\"\n\t\tif f.mapkeyts != \"\" {\n\t\t\tmeth = \"mkt.\"\n\t\t}\n\t\treturn fmt.Sprintf(\"%s%s()\", meth, fname)\n\t}\n\n\tb := bytes.NewBuffer(nil)\n\tp.Declare(b, \"x\", \"\", false)\n\th := sha1.New()\n\th.Write([]byte(valstr))\n\th.Write(b.Bytes())\n\tif f.mapkeyts != \"\" {\n\t\th.Write([]byte(f.mapkeyts))\n\t}\n\th.Write(b.Bytes())\n\tbs := h.Sum(nil)\n\thashstr := fmt.Sprintf(\"%x\", bs)\n\tb.WriteString(hashstr)\n\ttag := b.String()\n\tfname, ok := s.genvalFuncs[tag]\n\tif ok {\n\t\treturn mkInvoc(fname), value\n\t}\n\n\tfname = fmt.Sprintf(\"genval_%d\", len(s.genvalFuncs))\n\ts.newGenvalFuncs = append(s.newGenvalFuncs, funcdesc{p: p, name: fname, tag: tag, payload: valstr})\n\ts.genvalFuncs[tag] = fname\n\treturn mkInvoc(fname), value\n}\n\nfunc (s *genstate) emitMapKeyTmps(f *funcdef, b *bytes.Buffer, pidx int, value int, caller bool) int {\n\tif f.mapkeyts == \"\" {\n\t\treturn value\n\t}\n\t// map key tmps\n\tcp := \"\"\n\tif caller {\n\t\tcp = s.checkerPkg(pidx) + \".\"\n\t}\n\tb.WriteString(\"  var mkt \" + cp + f.mapkeyts + \"\\n\")\n\tfor i, t := range f.mapkeytypes {\n\t\tvar keystr string\n\t\tkeystr, value = s.GenValue(f, t, value, caller)\n\t\ttname := f.mapkeytmps[i]\n\t\tb.WriteString(fmt.Sprintf(\"  %s := %s\\n\", tname, keystr))\n\t\tb.WriteString(fmt.Sprintf(\"  mkt.%s = %s\\n\", tname, tname))\n\t}\n\treturn value\n}\n\nfunc (s *genstate) emitCheckReturnsInCaller(f *funcdef, b *bytes.Buffer, pidx int, reflectCall bool) {\n\tcm := f.complexityMeasure()\n\trvalp := func(ri int) string {\n\t\tif reflectCall {\n\t\t\treturn fmt.Sprintf(\"rr%dv\", ri)\n\t\t}\n\t\treturn fmt.Sprintf(\"r%d\", ri)\n\t}\n\tfailTag := \"\\\"return\\\"\"\n\tif reflectCall {\n\t\tfailTag = \"\\\"reflect return\\\"\"\n\t}\n\tfor ri, rp := range f.returns {\n\t\tif reflectCall {\n\t\t\tb.WriteString(fmt.Sprintf(\"  rr%di := rvslice[%d].Interface()\\n\", ri, ri))\n\t\t\tb.WriteString(fmt.Sprintf(\"  rr%dv:= rr%di.(\", ri, ri))\n\t\t\trp.Declare(b, \"\", \"\", true)\n\t\t\tb.WriteString(\")\\n\")\n\t\t}\n\t\tpfc := \"\"\n\t\tcurp, star := genDeref(rp)\n\t\t// Handle *p where p is an empty struct.\n\t\tif curp.NumElements() == 0 {\n\t\t\tb.WriteString(fmt.Sprintf(\"  _, _ = %s, c%d // zero size\\n\", rvalp(ri), ri))\n\t\t\tcontinue\n\t\t}\n\t\tif star != \"\" {\n\t\t\tpfc = fmt.Sprintf(\"ParamFailCount[%d] == 0 && \", pidx)\n\t\t}\n\t\tif curp.HasPointer() {\n\t\t\tefn := \"!\" + s.eqFuncRef(f, curp, true)\n\t\t\tb.WriteString(fmt.Sprintf(\"  if %s%s(%s%s, %sc%d) {\\n\", pfc, efn, star, rvalp(ri), star, ri))\n\t\t} else {\n\t\t\tb.WriteString(fmt.Sprintf(\"  if %s%s%s != %sc%d {\\n\", pfc, star, rvalp(ri), star, ri))\n\t\t}\n\t\tb.WriteString(fmt.Sprintf(\"    NoteFailure(%d, %d, %d, \\\"%s\\\", %s, %d, true, uint64(0))\\n\", cm, pidx, f.idx, s.checkerPkg(pidx), failTag, ri))\n\t\tb.WriteString(\"  }\\n\")\n\t}\n}\n\nfunc (s *genstate) emitCaller(f *funcdef, b *bytes.Buffer, pidx int) {\n\n\tb.WriteString(fmt.Sprintf(\"func %s%d(mode string) {\\n\", CallerName, f.idx))\n\n\tb.WriteString(fmt.Sprintf(\"  BeginFcn(%d)\\n\", pidx))\n\n\tif s.EmitBad == 1 {\n\t\tif s.BadPackageIdx == pidx && s.BadFuncIdx == f.idx {\n\t\t\tb.WriteString(\"  bad code here, should cause build failure <<==\\n\")\n\t\t}\n\t}\n\n\tvar value int = 1\n\n\ts.wr.Checkpoint(\"before mapkeytmps\")\n\tvalue = s.emitMapKeyTmps(f, b, pidx, value, true)\n\n\t// generate return constants\n\ts.wr.Checkpoint(\"before return constants\")\n\tfor ri, r := range f.returns {\n\t\trc := fmt.Sprintf(\"c%d\", ri)\n\t\tvalue = s.emitVarAssign(f, b, r, rc, value, true)\n\t}\n\n\t// generate param constants\n\ts.wr.Checkpoint(\"before param constants\")\n\tfor pi, p := range f.params {\n\t\tverb(4, \"emitCaller gen p%d value=%d\", pi, value)\n\t\tif p.IsControl() {\n\t\t\t_ = uint8(s.wr.Intn(100)) < 50\n\t\t\tp.Declare(b, fmt.Sprintf(\"  var p%d \", pi), \" = 10\\n\", true)\n\t\t} else {\n\t\t\tpc := fmt.Sprintf(\"p%d\", pi)\n\t\t\tvalue = s.emitVarAssign(f, b, p, pc, value, true)\n\t\t}\n\t\tf.values = append(f.values, value)\n\t}\n\n\t// generate receiver constant if applicable\n\tif f.isMethod {\n\t\ts.wr.Checkpoint(\"before receiver constant\")\n\t\tf.receiver.Declare(b, \"  var rcvr\", \"\\n\", true)\n\t\tvalstr, value := s.GenValue(f, f.receiver, value, true)\n\t\tb.WriteString(fmt.Sprintf(\"  rcvr = %s\\n\", valstr))\n\t\tf.values = append(f.values, value)\n\t}\n\n\tb.WriteString(fmt.Sprintf(\"  Mode[%d] = \\\"\\\"\\n\", pidx))\n\n\t// calling code\n\tb.WriteString(fmt.Sprintf(\"  // %d returns %d params\\n\",\n\t\tlen(f.returns), len(f.params)))\n\tif s.ForceStackGrowth {\n\t\tb.WriteString(\"  hackStack() // force stack growth on next call\\n\")\n\t}\n\tb.WriteString(\"  if mode == \\\"normal\\\" {\\n\")\n\tb.WriteString(\"  \")\n\tfor ri := range f.returns {\n\t\twriteCom(b, ri)\n\t\tb.WriteString(fmt.Sprintf(\"r%d\", ri))\n\t}\n\tif len(f.returns) > 0 {\n\t\tb.WriteString(\" := \")\n\t}\n\tpref := s.checkerPkg(pidx)\n\tif f.isMethod {\n\t\tpref = \"rcvr\"\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s.Test%d(\", pref, f.idx))\n\tfor pi := range f.params {\n\t\twriteCom(b, pi)\n\t\tb.WriteString(fmt.Sprintf(\"p%d\", pi))\n\t}\n\tb.WriteString(\")\\n\")\n\n\t// check values returned (normal call case)\n\ts.emitCheckReturnsInCaller(f, b, pidx, false /* not a reflect call */)\n\tb.WriteString(\"  }\") // end of 'if normal call' block\n\tif s.tunables.doReflectCall {\n\t\tb.WriteString(\"else {\\n\") // beginning of reflect call block\n\t\t// now make the same call via reflection\n\t\tb.WriteString(\"  // same call via reflection\\n\")\n\t\tb.WriteString(fmt.Sprintf(\"  Mode[%d] = \\\"reflect\\\"\\n\", pidx))\n\t\tif f.isMethod {\n\t\t\tb.WriteString(\"  rcv := reflect.ValueOf(rcvr)\\n\")\n\t\t\tb.WriteString(fmt.Sprintf(\"  rc := rcv.MethodByName(\\\"Test%d\\\")\\n\", f.idx))\n\t\t} else {\n\t\t\tb.WriteString(fmt.Sprintf(\"  rc := reflect.ValueOf(%s.Test%d)\\n\",\n\t\t\t\ts.checkerPkg(pidx), f.idx))\n\t\t}\n\t\tb.WriteString(\"  \")\n\t\tif len(f.returns) > 0 {\n\t\t\tb.WriteString(\"rvslice := \")\n\t\t}\n\t\tb.WriteString(\"  rc.Call([]reflect.Value{\")\n\t\tfor pi := range f.params {\n\t\t\twriteCom(b, pi)\n\t\t\tb.WriteString(fmt.Sprintf(\"reflect.ValueOf(p%d)\", pi))\n\t\t}\n\t\tb.WriteString(\"})\\n\")\n\n\t\t// check values returned (reflect call case)\n\t\ts.emitCheckReturnsInCaller(f, b, pidx, true /* is a reflect call */)\n\t\tb.WriteString(\"}\\n\") // end of reflect call block\n\t}\n\n\tb.WriteString(fmt.Sprintf(\"\\n  EndFcn(%d)\\n\", pidx))\n\n\tb.WriteString(\"}\\n\\n\")\n}\n\nfunc checkableElements(p parm) int {\n\tif p.IsBlank() {\n\t\treturn 0\n\t}\n\tsp, isstruct := p.(*structparm)\n\tif isstruct {\n\t\ts := 0\n\t\tfor fi := range sp.fields {\n\t\t\ts += checkableElements(sp.fields[fi])\n\t\t}\n\t\treturn s\n\t}\n\tap, isarray := p.(*arrayparm)\n\tif isarray {\n\t\tif ap.nelements == 0 {\n\t\t\treturn 0\n\t\t}\n\t\treturn int(ap.nelements) * checkableElements(ap.eltype)\n\t}\n\treturn 1\n}\n\n// funcdesc describes an auto-generated helper function or global\n// variable, such as an allocation function (returns new(T)) or a\n// pointer assignment function (assigns value of T to type *T). Here\n// 'p' is a param type T, 'pp' is a pointer type *T, 'name' is the\n// name within the generated code of the function or variable and\n// 'tag' is a descriptive tag used to look up the entity in a map (so\n// that we don't have to emit multiple copies of a function that\n// assigns int to *int, for example).\ntype funcdesc struct {\n\tp       parm\n\tpp      parm\n\tname    string\n\ttag     string\n\tpayload string\n}\n\nfunc (s *genstate) emitDerefFuncs(b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// dereference helpers\\n\")\n\tfor _, fd := range s.newDerefFuncs {\n\t\tif !emit {\n\t\t\tb.WriteString(fmt.Sprintf(\"\\n// skip derefunc %s\\n\", fd.name))\n\t\t\tdelete(s.derefFuncs, fd.tag)\n\t\t\tcontinue\n\t\t}\n\t\tb.WriteString(\"\\n//go:noinline\\n\")\n\t\tb.WriteString(fmt.Sprintf(\"func %s(\", fd.name))\n\t\tfd.pp.Declare(b, \"x\", \"\", false)\n\t\tb.WriteString(\") \")\n\t\tfd.p.Declare(b, \"\", \"\", false)\n\t\tb.WriteString(\" {\\n\")\n\t\tb.WriteString(\"  return *x\\n\")\n\t\tb.WriteString(\"}\\n\")\n\t}\n\ts.newDerefFuncs = nil\n}\n\nfunc (s *genstate) emitAssignFuncs(b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// assign helpers\\n\")\n\tfor _, fd := range s.newAssignFuncs {\n\t\tif !emit {\n\t\t\tb.WriteString(fmt.Sprintf(\"\\n// skip assignfunc %s\\n\", fd.name))\n\t\t\tdelete(s.assignFuncs, fd.tag)\n\t\t\tcontinue\n\t\t}\n\t\tb.WriteString(\"\\n//go:noinline\\n\")\n\t\tb.WriteString(fmt.Sprintf(\"func %s(\", fd.name))\n\t\tfd.pp.Declare(b, \"x\", \"\", false)\n\t\tb.WriteString(\", \")\n\t\tfd.p.Declare(b, \"v\", \"\", false)\n\t\tb.WriteString(\") {\\n\")\n\t\tb.WriteString(\"  *x = v\\n\")\n\t\tb.WriteString(\"}\\n\")\n\t}\n\ts.newAssignFuncs = nil\n}\n\nfunc (s *genstate) emitNewFuncs(b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// 'new' funcs\\n\")\n\tfor _, fd := range s.newAllocFuncs {\n\t\tif !emit {\n\t\t\tb.WriteString(fmt.Sprintf(\"\\n// skip newfunc %s\\n\", fd.name))\n\t\t\tdelete(s.allocFuncs, fd.tag)\n\t\t\tcontinue\n\t\t}\n\t\tb.WriteString(\"\\n//go:noinline\\n\")\n\t\tb.WriteString(fmt.Sprintf(\"func %s(\", fd.name))\n\t\tfd.p.Declare(b, \"i\", \"\", false)\n\t\tb.WriteString(\") \")\n\t\tfd.pp.Declare(b, \"\", \"\", false)\n\t\tb.WriteString(\" {\\n\")\n\t\tb.WriteString(\"  x := new(\")\n\t\tfd.p.Declare(b, \"\", \"\", false)\n\t\tb.WriteString(\")\\n\")\n\t\tb.WriteString(\"  *x = i\\n\")\n\t\tb.WriteString(\"  return x\\n\")\n\t\tb.WriteString(\"}\\n\\n\")\n\t}\n\ts.newAllocFuncs = nil\n}\n\nfunc (s *genstate) emitGlobalVars(b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// global vars\\n\")\n\tfor _, fd := range s.newGlobVars {\n\t\tif !emit {\n\t\t\tb.WriteString(fmt.Sprintf(\"\\n// skip gvar %s\\n\", fd.name))\n\t\t\tdelete(s.globVars, fd.tag)\n\t\t\tcontinue\n\t\t}\n\t\tb.WriteString(\"var \")\n\t\tfd.pp.Declare(b, fd.name, \"\", false)\n\t\tb.WriteString(\"\\n\")\n\t}\n\ts.newGlobVars = nil\n\tb.WriteString(\"\\n\")\n}\n\nfunc (s *genstate) emitGenValFuncs(f *funcdef, b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// genval helpers\\n\")\n\tfor _, fd := range s.newGenvalFuncs {\n\t\tif !emit {\n\t\t\tb.WriteString(fmt.Sprintf(\"\\n// skip genvalfunc %s\\n\", fd.name))\n\t\t\tdelete(s.genvalFuncs, fd.tag)\n\t\t\tcontinue\n\t\t}\n\t\tb.WriteString(\"\\n//go:noinline\\n\")\n\t\trcvr := \"\"\n\t\tif f.mapkeyts != \"\" {\n\t\t\trcvr = fmt.Sprintf(\"(mkt *%s) \", f.mapkeyts)\n\t\t}\n\t\tb.WriteString(fmt.Sprintf(\"func %s%s() \", rcvr, fd.name))\n\t\tfd.p.Declare(b, \"\", \"\", false)\n\t\tb.WriteString(\" {\\n\")\n\t\tif f.mapkeyts != \"\" {\n\t\t\tcontained := containedParms(fd.p)\n\t\t\tfor _, cp := range contained {\n\t\t\t\tmp, ismap := cp.(*mapparm)\n\t\t\t\tif ismap {\n\t\t\t\t\tb.WriteString(fmt.Sprintf(\"  %s := mkt.%s\\n\",\n\t\t\t\t\t\tmp.keytmp, mp.keytmp))\n\t\t\t\t\tb.WriteString(fmt.Sprintf(\"  _ = %s\\n\", mp.keytmp))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tb.WriteString(fmt.Sprintf(\"  return %s\\n\", fd.payload))\n\t\tb.WriteString(\"}\\n\")\n\t}\n\ts.newGenvalFuncs = nil\n}\n\nfunc (s *genstate) emitAddrTakenHelpers(f *funcdef, b *bytes.Buffer, emit bool) {\n\tb.WriteString(\"// begin addr taken helpers\\n\")\n\ts.emitDerefFuncs(b, emit)\n\ts.emitAssignFuncs(b, emit)\n\ts.emitNewFuncs(b, emit)\n\ts.emitGlobalVars(b, emit)\n\ts.emitGenValFuncs(f, b, emit)\n\tb.WriteString(\"// end addr taken helpers\\n\")\n}\n\nfunc (s *genstate) genGlobVar(p parm) string {\n\tvar pp parm\n\tppp := mkPointerParm(p)\n\tpp = &ppp\n\tb := bytes.NewBuffer(nil)\n\tpp.Declare(b, \"gv\", \"\", false)\n\ttag := b.String()\n\tgv, ok := s.globVars[tag]\n\tif ok {\n\t\treturn gv\n\t}\n\tgv = fmt.Sprintf(\"gvar_%d\", len(s.globVars))\n\ts.newGlobVars = append(s.newGlobVars, funcdesc{pp: pp, p: p, name: gv, tag: tag})\n\ts.globVars[tag] = gv\n\treturn gv\n}\n\nfunc (s *genstate) genParamDerefFunc(p parm) string {\n\tvar pp parm\n\tppp := mkPointerParm(p)\n\tpp = &ppp\n\tb := bytes.NewBuffer(nil)\n\tpp.Declare(b, \"x\", \"\", false)\n\ttag := b.String()\n\tf, ok := s.derefFuncs[tag]\n\tif ok {\n\t\treturn f\n\t}\n\tf = fmt.Sprintf(\"deref_%d\", len(s.derefFuncs))\n\ts.newDerefFuncs = append(s.newDerefFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})\n\ts.derefFuncs[tag] = f\n\treturn f\n}\n\nfunc (s *genstate) genAssignFunc(p parm) string {\n\tvar pp parm\n\tppp := mkPointerParm(p)\n\tpp = &ppp\n\tb := bytes.NewBuffer(nil)\n\tpp.Declare(b, \"x\", \"\", false)\n\ttag := b.String()\n\tf, ok := s.assignFuncs[tag]\n\tif ok {\n\t\treturn f\n\t}\n\tf = fmt.Sprintf(\"retassign_%d\", len(s.assignFuncs))\n\ts.newAssignFuncs = append(s.newAssignFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})\n\ts.assignFuncs[tag] = f\n\treturn f\n}\n\nfunc (s *genstate) genAllocFunc(p parm) string {\n\tvar pp parm\n\tppp := mkPointerParm(p)\n\tpp = &ppp\n\tb := bytes.NewBuffer(nil)\n\tpp.Declare(b, \"x\", \"\", false)\n\ttag := b.String()\n\tf, ok := s.allocFuncs[tag]\n\tif ok {\n\t\treturn f\n\t}\n\tf = fmt.Sprintf(\"New_%d\", len(s.allocFuncs))\n\ts.newAllocFuncs = append(s.newAllocFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})\n\ts.allocFuncs[tag] = f\n\treturn f\n}\n\nfunc (s *genstate) genParamRef(p parm, idx int) string {\n\tswitch p.AddrTaken() {\n\tcase notAddrTaken:\n\t\treturn fmt.Sprintf(\"p%d\", idx)\n\tcase addrTakenSimple, addrTakenHeap:\n\t\treturn fmt.Sprintf(\"(*ap%d)\", idx)\n\tcase addrTakenPassed:\n\t\tf := s.genParamDerefFunc(p)\n\t\treturn fmt.Sprintf(\"%s(ap%d)\", f, idx)\n\tdefault:\n\t\tpanic(\"bad\")\n\t}\n}\n\nfunc (s *genstate) genReturnAssign(b *bytes.Buffer, r parm, idx int, val string) {\n\tswitch r.AddrTaken() {\n\tcase notAddrTaken:\n\t\tb.WriteString(fmt.Sprintf(\"  r%d = %s\\n\", idx, val))\n\tcase addrTakenSimple, addrTakenHeap:\n\t\tb.WriteString(fmt.Sprintf(\"  (*ar%d) = %v\\n\", idx, val))\n\tcase addrTakenPassed:\n\t\tf := s.genAssignFunc(r)\n\t\tb.WriteString(fmt.Sprintf(\"  %s(ar%d, %v)\\n\", f, idx, val))\n\tdefault:\n\t\tpanic(\"bad\")\n\t}\n}\n\nfunc (s *genstate) emitParamElemCheck(f *funcdef, b *bytes.Buffer, p parm, pvar string, cvar string, paramidx int, elemidx int) {\n\tif p.SkipCompare() == SkipAll {\n\t\tb.WriteString(fmt.Sprintf(\"  // selective skip of %s\\n\", pvar))\n\t\tb.WriteString(fmt.Sprintf(\"  _ = %s\\n\", cvar))\n\t\treturn\n\t} else if p.SkipCompare() == SkipPayload {\n\t\tswitch p.(type) {\n\t\tcase *stringparm, *arrayparm:\n\t\t\tb.WriteString(fmt.Sprintf(\"  if len(%s) != len(%s) { // skip payload\\n\",\n\t\t\t\tpvar, cvar))\n\t\tdefault:\n\t\t\tpanic(\"should never happen\")\n\t\t}\n\t} else {\n\t\tbasep, star := genDeref(p)\n\t\t// Handle *p where p is an empty struct.\n\t\tif basep.NumElements() == 0 {\n\t\t\treturn\n\t\t}\n\t\tif basep.HasPointer() {\n\t\t\tefn := s.eqFuncRef(f, basep, false)\n\t\t\tb.WriteString(fmt.Sprintf(\"  if !%s(%s%s, %s%s) {\\n\",\n\t\t\t\tefn, star, pvar, star, cvar))\n\t\t} else {\n\t\t\tb.WriteString(fmt.Sprintf(\"  if %s%s != %s%s {\\n\",\n\t\t\t\tstar, pvar, star, cvar))\n\t\t}\n\t}\n\tcm := f.complexityMeasure()\n\tb.WriteString(fmt.Sprintf(\"    NoteFailureElem(%d, %d, %d, \\\"%s\\\", \\\"parm\\\", %d, %d, false, pad[0])\\n\", cm, s.pkidx, f.idx, s.checkerPkg(s.pkidx), paramidx, elemidx))\n\tb.WriteString(\"    return\\n\")\n\tb.WriteString(\"  }\\n\")\n}\n\nfunc (s *genstate) emitParamChecks(f *funcdef, b *bytes.Buffer, pidx int, value int) (int, bool) {\n\tvar valstr string\n\thaveControl := false\n\tdangling := []int{}\n\tfor pi, p := range f.params {\n\t\tverb(4, \"emitting parmcheck p%d numel=%d pt=%s value=%d\",\n\t\t\tpi, p.NumElements(), p.TypeName(), value)\n\t\t// To balance code in caller\n\t\t_ = uint8(s.wr.Intn(100)) < 50\n\t\tif p.IsControl() {\n\t\t\tb.WriteString(fmt.Sprintf(\"  if %s == 0 {\\n\",\n\t\t\t\ts.genParamRef(p, pi)))\n\t\t\ts.emitReturn(f, b, false)\n\t\t\tb.WriteString(\"  }\\n\")\n\t\t\thaveControl = true\n\n\t\t} else if p.IsBlank() {\n\t\t\tvalstr, value = s.GenValue(f, p, value, false)\n\t\t\tif f.recur {\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  brc%d := %s\\n\", pi, valstr))\n\t\t\t} else {\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  _ = %s\\n\", valstr))\n\t\t\t}\n\t\t} else {\n\t\t\tnumel := p.NumElements()\n\t\t\tcel := checkableElements(p)\n\t\t\tfor i := range numel {\n\t\t\t\tverb(4, \"emitting check-code for p%d el %d value=%d\", pi, i, value)\n\t\t\t\telref, elparm := p.GenElemRef(i, s.genParamRef(p, pi))\n\t\t\t\tvalstr, value = s.GenValue(f, elparm, value, false)\n\t\t\t\tif elref == \"\" || elref == \"_\" || cel == 0 {\n\t\t\t\t\tb.WriteString(fmt.Sprintf(\"  // blank skip: %s\\n\", valstr))\n\t\t\t\t\tcontinue\n\t\t\t\t} else {\n\t\t\t\t\tbasep, _ := genDeref(elparm)\n\t\t\t\t\t// Handle *p where p is an empty struct.\n\t\t\t\t\tif basep.NumElements() == 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tcvar := fmt.Sprintf(\"p%df%dc\", pi, i)\n\t\t\t\t\tb.WriteString(fmt.Sprintf(\"  %s := %s\\n\", cvar, valstr))\n\t\t\t\t\ts.emitParamElemCheck(f, b, elparm, elref, cvar, pi, i)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif p.AddrTaken() != notAddrTaken {\n\t\t\t\tdangling = append(dangling, pi)\n\t\t\t}\n\t\t}\n\t\tif value != f.values[pi] {\n\t\t\tfmt.Fprintf(os.Stderr, \"internal error: checker/caller value mismatch after emitting param %d func Test%d pkg %s: caller %d checker %d\\n\", pi, f.idx, s.checkerPkg(pidx), f.values[pi], value)\n\t\t\ts.errs++\n\t\t}\n\t}\n\tfor _, pi := range dangling {\n\t\tb.WriteString(fmt.Sprintf(\"  _ = ap%d // ref\\n\", pi))\n\t}\n\n\t// receiver value check\n\tif f.isMethod {\n\t\tnumel := f.receiver.NumElements()\n\t\tfor i := range numel {\n\t\t\tverb(4, \"emitting check-code for rcvr el %d value=%d\", i, value)\n\t\t\telref, elparm := f.receiver.GenElemRef(i, \"rcvr\")\n\t\t\tvalstr, value = s.GenValue(f, elparm, value, false)\n\t\t\tif elref == \"\" || strings.HasPrefix(elref, \"_\") || f.receiver.IsBlank() {\n\t\t\t\tverb(4, \"empty skip rcvr el %d\", i)\n\t\t\t\tcontinue\n\t\t\t} else {\n\n\t\t\t\tbasep, _ := genDeref(elparm)\n\t\t\t\t// Handle *p where p is an empty struct.\n\t\t\t\tif basep.NumElements() == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcvar := fmt.Sprintf(\"rcvrf%dc\", i)\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  %s := %s\\n\", cvar, valstr))\n\t\t\t\ts.emitParamElemCheck(f, b, elparm, elref, cvar, -1, i)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn value, haveControl\n}\n\n// emitDeferChecks creates code like\n//\n//\tdefer func(...args...) {\n//\t  check arg\n//\t  check param\n//\t}(...)\n//\n// where we randomly choose to either pass a param through to the\n// function literal, or have the param captured by the closure, then\n// check its value in the defer.\nfunc (s *genstate) emitDeferChecks(f *funcdef, b *bytes.Buffer, value int) int {\n\n\tif len(f.params) == 0 {\n\t\treturn value\n\t}\n\n\t// make a pass through the params and randomly decide which will be passed into the func.\n\tpassed := []bool{}\n\tfor i := range f.params {\n\t\tp := f.dodefp[i] < 50\n\t\tpassed = append(passed, p)\n\t}\n\n\tb.WriteString(\"  defer func(\")\n\tpc := 0\n\tfor pi, p := range f.params {\n\t\tif p.IsControl() || p.IsBlank() {\n\t\t\tcontinue\n\t\t}\n\t\tif passed[pi] {\n\t\t\twriteCom(b, pc)\n\t\t\tn := fmt.Sprintf(\"p%d\", pi)\n\t\t\tp.Declare(b, n, \"\", false)\n\t\t\tpc++\n\t\t}\n\t}\n\tb.WriteString(\") {\\n\")\n\n\tfor pi, p := range f.params {\n\t\tif p.IsControl() || p.IsBlank() {\n\t\t\tcontinue\n\t\t}\n\t\twhich := \"passed\"\n\t\tif !passed[pi] {\n\t\t\twhich = \"captured\"\n\t\t}\n\t\tb.WriteString(\"  // check parm \" + which + \"\\n\")\n\t\tnumel := p.NumElements()\n\t\tcel := checkableElements(p)\n\t\tfor i := range numel {\n\t\t\telref, elparm := p.GenElemRef(i, s.genParamRef(p, pi))\n\t\t\tif elref == \"\" || elref == \"_\" || cel == 0 {\n\t\t\t\tverb(4, \"empty skip p%d el %d\", pi, i)\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tbasep, _ := genDeref(elparm)\n\t\t\t\t// Handle *p where p is an empty struct.\n\t\t\t\tif basep.NumElements() == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcvar := fmt.Sprintf(\"p%df%dc\", pi, i)\n\t\t\t\ts.emitParamElemCheck(f, b, elparm, elref, cvar, pi, i)\n\t\t\t}\n\t\t}\n\t}\n\tb.WriteString(\"  } (\")\n\tpc = 0\n\tfor pi, p := range f.params {\n\t\tif p.IsControl() || p.IsBlank() {\n\t\t\tcontinue\n\t\t}\n\t\tif passed[pi] {\n\t\t\twriteCom(b, pc)\n\t\t\tb.WriteString(fmt.Sprintf(\"p%d\", pi))\n\t\t\tpc++\n\t\t}\n\t}\n\tb.WriteString(\")\\n\\n\")\n\n\treturn value\n}\n\nfunc (s *genstate) emitVarAssign(f *funcdef, b *bytes.Buffer, r parm, rname string, value int, caller bool) int {\n\tvar valstr string\n\tisassign := uint8(s.wr.Intn(100)) < 50\n\tif rmp, ismap := r.(*mapparm); ismap && isassign {\n\t\t// emit: var m ... ; m[k] = v\n\t\tr.Declare(b, \"  \"+rname+\" := make(\", \")\\n\", caller)\n\t\tvalstr, value = s.GenValue(f, rmp.valtype, value, caller)\n\t\tb.WriteString(fmt.Sprintf(\"  %s[mkt.%s] = %s\\n\",\n\t\t\trname, rmp.keytmp, valstr))\n\t} else {\n\t\t// emit r = c\n\t\tvalstr, value = s.GenValue(f, r, value, caller)\n\t\tb.WriteString(fmt.Sprintf(\"  %s := %s\\n\", rname, valstr))\n\t}\n\treturn value\n}\n\nfunc (s *genstate) emitChecker(f *funcdef, b *bytes.Buffer, pidx int, emit bool) {\n\tverb(4, \"emitting struct and array defs\")\n\ts.emitStructAndArrayDefs(f, b)\n\tb.WriteString(fmt.Sprintf(\"// %d returns %d params\\n\", len(f.returns), len(f.params)))\n\tif s.Pragma != \"\" {\n\t\tb.WriteString(\"//go:\" + s.Pragma + \"\\n\")\n\t}\n\tb.WriteString(\"//go:noinline\\n\")\n\n\tb.WriteString(\"func\")\n\n\tif f.isMethod {\n\t\tb.WriteString(\" (\")\n\t\tn := \"rcvr\"\n\t\tif f.receiver.IsBlank() {\n\t\t\tn = \"_\"\n\t\t}\n\t\tf.receiver.Declare(b, n, \"\", false)\n\t\tb.WriteString(\")\")\n\t}\n\n\tb.WriteString(fmt.Sprintf(\" Test%d(\", f.idx))\n\n\tverb(4, \"emitting checker p%d/Test%d\", pidx, f.idx)\n\n\t// params\n\tfor pi, p := range f.params {\n\t\twriteCom(b, pi)\n\t\tn := fmt.Sprintf(\"p%d\", pi)\n\t\tif p.IsBlank() {\n\t\t\tn = \"_\"\n\t\t}\n\t\tp.Declare(b, n, \"\", false)\n\t}\n\tb.WriteString(\") \")\n\n\t// returns\n\tif len(f.returns) > 0 {\n\t\tb.WriteString(\"(\")\n\t}\n\tfor ri, r := range f.returns {\n\t\twriteCom(b, ri)\n\t\tr.Declare(b, fmt.Sprintf(\"r%d\", ri), \"\", false)\n\t}\n\tif len(f.returns) > 0 {\n\t\tb.WriteString(\")\")\n\t}\n\tb.WriteString(\" {\\n\")\n\n\t// local storage\n\tb.WriteString(\"  // consume some stack space, so as to trigger morestack\\n\")\n\tb.WriteString(fmt.Sprintf(\"  var pad [%d]uint64\\n\", f.rstack))\n\tb.WriteString(fmt.Sprintf(\"  pad[FailCount[%d] & 0x1]++\\n\", pidx))\n\n\tvalue := 1\n\n\t// generate map key tmps\n\ts.wr.Checkpoint(\"before map key temps\")\n\tvalue = s.emitMapKeyTmps(f, b, pidx, value, false)\n\n\t// generate return constants\n\ts.wr.Checkpoint(\"before return constants\")\n\tfor ri, r := range f.returns {\n\t\trc := fmt.Sprintf(\"rc%d\", ri)\n\t\tvalue = s.emitVarAssign(f, b, r, rc, value, false)\n\t}\n\n\t// Prepare to reference params/returns by address.\n\tlists := [][]parm{f.params, f.returns}\n\tnames := []string{\"p\", \"r\"}\n\tvar aCounts [2]int\n\tfor i, lst := range lists {\n\t\tfor pi, p := range lst {\n\t\t\tif p.AddrTaken() == notAddrTaken {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\taCounts[i]++\n\t\t\tn := names[i]\n\t\t\tb.WriteString(fmt.Sprintf(\"  a%s%d := &%s%d\\n\", n, pi, n, pi))\n\t\t\tif p.AddrTaken() == addrTakenHeap {\n\t\t\t\tgv := s.genGlobVar(p)\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  %s = a%s%d\\n\", gv, n, pi))\n\t\t\t}\n\t\t}\n\t}\n\n\tif s.EmitBad == 2 {\n\t\tif s.BadPackageIdx == pidx && s.BadFuncIdx == f.idx {\n\t\t\tb.WriteString(\"  // force runtime failure here (debugging)\\n\")\n\t\t\tb.WriteString(fmt.Sprintf(\"    NoteFailure(%d, %d, %d, \\\"%s\\\", \\\"artificial\\\", %d, true, uint64(0))\\n\", f.complexityMeasure(), pidx, f.idx, s.checkerPkg(pidx), 0))\n\t\t}\n\t}\n\n\t// parameter checking code\n\tvar haveControl bool\n\ts.wr.Checkpoint(\"before param checks\")\n\tvalue, haveControl = s.emitParamChecks(f, b, pidx, value)\n\n\t// defer testing\n\tif s.tunables.doDefer && f.dodefc < s.tunables.deferFraction {\n\t\ts.wr.Checkpoint(\"before defer checks\")\n\t\t_ = s.emitDeferChecks(f, b, value)\n\t}\n\n\t// returns\n\ts.emitReturn(f, b, haveControl)\n\n\tb.WriteString(fmt.Sprintf(\"  // %d addr-taken params, %d addr-taken returns\\n\",\n\t\taCounts[0], aCounts[1]))\n\n\tb.WriteString(\"}\\n\\n\")\n\n\t// emit any new helper funcs referenced by this test function\n\ts.emitAddrTakenHelpers(f, b, emit)\n}\n\n// complexityMeasure returns an integer that estimates how complex a\n// given test function is relative to some other function. The more\n// parameters + returns and the more complicated the types of the\n// params/returns, the higher the number returned here. In theory this\n// could be worked into the minimization process (e.g. pick the least\n// complex func that reproduces the failure), but for now that isn't\n// wired up yet.\nfunc (f *funcdef) complexityMeasure() int {\n\tv := int(0)\n\tif f.isMethod {\n\t\tv += f.receiver.NumElements()\n\t}\n\tfor _, p := range f.params {\n\t\tv += p.NumElements()\n\t}\n\tfor _, r := range f.returns {\n\t\tv += r.NumElements()\n\t}\n\treturn v\n}\n\n// emitRecursiveCall generates a recursive call to the test function in question.\nfunc (s *genstate) emitRecursiveCall(f *funcdef) string {\n\tb := bytes.NewBuffer(nil)\n\trcvr := \"\"\n\tif f.isMethod {\n\t\trcvr = \"rcvr.\"\n\t}\n\tb.WriteString(fmt.Sprintf(\" %sTest%d(\", rcvr, f.idx))\n\tfor pi, p := range f.params {\n\t\twriteCom(b, pi)\n\t\tif p.IsControl() {\n\t\t\tb.WriteString(fmt.Sprintf(\" %s-1\", s.genParamRef(p, pi)))\n\t\t} else {\n\t\t\tif !p.IsBlank() {\n\t\t\t\tb.WriteString(fmt.Sprintf(\" %s\", s.genParamRef(p, pi)))\n\t\t\t} else {\n\t\t\t\tb.WriteString(fmt.Sprintf(\" brc%d\", pi))\n\t\t\t}\n\t\t}\n\t}\n\tb.WriteString(\")\")\n\treturn b.String()\n}\n\n// emitReturn generates a return sequence.\nfunc (s *genstate) emitReturn(f *funcdef, b *bytes.Buffer, doRecursiveCall bool) {\n\t// If any of the return values are address-taken, then instead of\n\t//\n\t//   return x, y, z\n\t//\n\t// we emit\n\t//\n\t//   r1 = ...\n\t//   r2 = ...\n\t//   ...\n\t//   return\n\t//\n\t// Make an initial pass through the returns to see if we need to do this.\n\t// Figure out the final return values in the process.\n\tindirectReturn := false\n\tretvals := []string{}\n\tfor ri, r := range f.returns {\n\t\tif r.AddrTaken() != notAddrTaken {\n\t\t\tindirectReturn = true\n\t\t}\n\t\tt := \"\"\n\t\tif doRecursiveCall {\n\t\t\tt = \"t\"\n\t\t}\n\t\tretvals = append(retvals, fmt.Sprintf(\"rc%s%d\", t, ri))\n\t}\n\n\t// generate the recursive call itself if applicable\n\tif doRecursiveCall {\n\t\tb.WriteString(\"  // recursive call\\n  \")\n\t\tif s.ForceStackGrowth {\n\t\t\tb.WriteString(\"  hackStack() // force stack growth on next call\\n\")\n\t\t}\n\t\trcall := s.emitRecursiveCall(f)\n\t\tif indirectReturn {\n\t\t\tfor ri := range f.returns {\n\t\t\t\twriteCom(b, ri)\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  rct%d\", ri))\n\t\t\t}\n\t\t\tb.WriteString(\" := \")\n\t\t\tb.WriteString(rcall)\n\t\t\tb.WriteString(\"\\n\")\n\t\t} else {\n\t\t\tif len(f.returns) == 0 {\n\t\t\t\tb.WriteString(fmt.Sprintf(\"%s\\n  return\\n\", rcall))\n\t\t\t} else {\n\t\t\t\tb.WriteString(fmt.Sprintf(\"  return %s\\n\", rcall))\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\t// now the actual return\n\tif indirectReturn {\n\t\tfor ri, r := range f.returns {\n\t\t\ts.genReturnAssign(b, r, ri, retvals[ri])\n\t\t}\n\t\tb.WriteString(\"  return\\n\")\n\t} else {\n\t\tb.WriteString(\"  return \")\n\t\tfor ri := range f.returns {\n\t\t\twriteCom(b, ri)\n\t\t\tb.WriteString(retvals[ri])\n\t\t}\n\t\tb.WriteString(\"\\n\")\n\t}\n}\n\nfunc (s *genstate) GenPair(calloutfile *os.File, checkoutfile *os.File, fidx int, pidx int, b *bytes.Buffer, seed int64, emit bool) int64 {\n\n\tverb(1, \"gen fidx %d pidx %d\", fidx, pidx)\n\n\tcheckTunables(tunables)\n\ts.tunables = tunables\n\n\t// Generate a function with a random number of params and returns\n\ts.wr = NewWrapRand(seed, s.RandCtl)\n\ts.wr.tag = \"genfunc\"\n\tfp := s.GenFunc(fidx, pidx)\n\n\t// Emit caller side\n\twrcaller := NewWrapRand(seed, s.RandCtl)\n\ts.wr = wrcaller\n\ts.wr.tag = \"caller\"\n\ts.emitCaller(fp, b, pidx)\n\tif emit {\n\t\tb.WriteTo(calloutfile)\n\t}\n\tb.Reset()\n\n\t// Emit checker side\n\twrchecker := NewWrapRand(seed, s.RandCtl)\n\ts.wr = wrchecker\n\ts.wr.tag = \"checker\"\n\ts.emitChecker(fp, b, pidx, emit)\n\tif emit {\n\t\tb.WriteTo(checkoutfile)\n\t}\n\tb.Reset()\n\twrchecker.Check(wrcaller)\n\n\treturn seed + 1\n}\n\nfunc (s *genstate) openOutputFile(filename string, pk string, imports []string, ipref string) *os.File {\n\tiprefix := func(f string) string {\n\t\tif ipref == \"\" {\n\t\t\treturn f\n\t\t}\n\t\treturn ipref + \"/\" + f\n\t}\n\tverb(1, \"opening %s\", filename)\n\toutf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\thaveunsafe := false\n\toutf.WriteString(fmt.Sprintf(\"package %s\\n\\n\", pk))\n\tfor _, imp := range imports {\n\t\tif imp == \"reflect\" {\n\t\t\toutf.WriteString(\"import \\\"reflect\\\"\\n\")\n\t\t\tcontinue\n\t\t}\n\t\tif imp == \"unsafe\" {\n\t\t\toutf.WriteString(\"import _ \\\"unsafe\\\"\\n\")\n\t\t\thaveunsafe = true\n\t\t\tcontinue\n\t\t}\n\t\tif imp == s.utilsPkg() {\n\n\t\t\toutf.WriteString(fmt.Sprintf(\"import . \\\"%s\\\"\\n\", iprefix(imp)))\n\t\t\tcontinue\n\t\t}\n\t\toutf.WriteString(fmt.Sprintf(\"import \\\"%s\\\"\\n\", iprefix(imp)))\n\t}\n\toutf.WriteString(\"\\n\")\n\tif s.ForceStackGrowth && haveunsafe {\n\t\toutf.WriteString(\"// Hack: reach into runtime to grab this testing hook.\\n\")\n\t\toutf.WriteString(\"//go:linkname hackStack runtime.gcTestMoveStackOnNextCall\\n\")\n\t\toutf.WriteString(\"func hackStack()\\n\\n\")\n\t}\n\treturn outf\n}\n\ntype miscVals struct {\n\tNumTpk   int\n\tMaxFail  int\n\tNumTests int\n}\n\nconst utilsTemplate = `\n\nimport (\n  \"fmt\"\n  \"os\"\n)\n\ntype UtilsType int\nvar ParamFailCount [{{.NumTpk}}]int\nvar ReturnFailCount [{{.NumTpk}}]int\nvar FailCount [{{.NumTpk}}]int\nvar Mode [{{.NumTpk}}]string\n\n//go:noinline\nfunc NoteFailure(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, isret bool, _ uint64) {\n\tif isret {\n\t\tif ParamFailCount[pidx] != 0 {\n\t\t\treturn\n\t\t}\n\t\tReturnFailCount[pidx]++\n\t} else {\n\t\tParamFailCount[pidx]++\n\t}\n\tfmt.Fprintf(os.Stderr, \"Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d\\n\", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo)\n\n\tif ParamFailCount[pidx]+FailCount[pidx]+ReturnFailCount[pidx] > {{.MaxFail}} {\n\t\tos.Exit(1)\n\t}\n}\n\n//go:noinline\nfunc NoteFailureElem(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, elem int, isret bool, _ uint64) {\n\n\tif isret {\n\t\tif ParamFailCount[pidx] != 0 {\n\t\t\treturn\n\t\t}\n\t\tReturnFailCount[pidx]++\n\t} else {\n\t\tParamFailCount[pidx]++\n\t}\n\tfmt.Fprintf(os.Stderr, \"Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d elem %d\\n\", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo, elem)\n\n\tif ParamFailCount[pidx]+FailCount[pidx]+ReturnFailCount[pidx] > {{.MaxFail}} {\n\t\tos.Exit(1)\n\t}\n}\n\nfunc BeginFcn(p int) {\n\tParamFailCount[p] = 0\n\tReturnFailCount[p] = 0\n}\n\nfunc EndFcn(p int) {\n\tFailCount[p] += ParamFailCount[p]\n\tFailCount[p] += ReturnFailCount[p]\n}\n`\n\nfunc (s *genstate) emitUtils(outf *os.File, maxfail int, numtpk int) {\n\tvals := miscVals{\n\t\tNumTpk:  numtpk,\n\t\tMaxFail: maxfail,\n\t}\n\tt := template.Must(template.New(\"utils\").Parse(utilsTemplate))\n\terr := t.Execute(outf, vals)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nconst mainPreamble = `\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() {\n  fmt.Fprintf(os.Stderr, \"starting main\\n\")\n`\n\nfunc (s *genstate) emitMain(outf *os.File, numit int, fcnmask map[int]int, pkmask map[int]int) {\n\tfmt.Fprintf(outf, \"%s\", mainPreamble)\n\tfmt.Fprintf(outf, \"  pch := make(chan bool, %d)\\n\", s.NumTestPackages)\n\tfor k := 0; k < s.NumTestPackages; k++ {\n\t\tcp := fmt.Sprintf(\"%s%s%d\", s.Tag, CallerName, k)\n\t\tfmt.Fprintf(outf, \"  go func(ch chan bool) {\\n\")\n\t\tfor i := range numit {\n\t\t\tif shouldEmitFP(i, k, fcnmask, pkmask) {\n\t\t\t\tfmt.Fprintf(outf, \"    %s.%s%d(\\\"normal\\\")\\n\", cp, CallerName, i)\n\t\t\t\tif s.tunables.doReflectCall {\n\t\t\t\t\tfmt.Fprintf(outf, \"    %s.%s%d(\\\"reflect\\\")\\n\", cp, CallerName, i)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(outf, \"    pch <- true\\n\")\n\t\tfmt.Fprintf(outf, \"  }(pch)\\n\")\n\t}\n\tfmt.Fprintf(outf, \"  for pidx := 0; pidx < %d; pidx++ {\\n\", s.NumTestPackages)\n\tfmt.Fprintf(outf, \"    _ = <- pch\\n\")\n\tfmt.Fprintf(outf, \"  }\\n\")\n\tfmt.Fprintf(outf, \"  tf := 0\\n\")\n\tfmt.Fprintf(outf, \"  for pidx := 0; pidx < %d; pidx++ {\\n\", s.NumTestPackages)\n\tfmt.Fprintf(outf, \"    tf += FailCount[pidx]\\n\")\n\tfmt.Fprintf(outf, \"  }\\n\")\n\tfmt.Fprintf(outf, \"  if tf != 0 {\\n\")\n\tfmt.Fprintf(outf, \"    fmt.Fprintf(os.Stderr, \\\"FAILURES: %%d\\\\n\\\", tf)\\n\")\n\tfmt.Fprintf(outf, \"    os.Exit(2)\\n\")\n\tfmt.Fprintf(outf, \"  }\\n\")\n\tfmt.Fprintf(outf, \"  fmt.Fprintf(os.Stderr, \\\"finished %d tests\\\\n\\\")\\n\", numit*s.NumTestPackages)\n\tfmt.Fprintf(outf, \"}\\n\")\n}\n\nfunc makeDir(d string) {\n\tfi, err := os.Stat(d)\n\tif err == nil && fi.IsDir() {\n\t\treturn\n\t}\n\tverb(1, \"creating %s\", d)\n\tif err := os.Mkdir(d, 0777); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc (s *genstate) callerPkg(which int) string {\n\treturn s.Tag + CallerName + strconv.Itoa(which)\n}\n\nfunc (s *genstate) callerFile(which int) string {\n\tcp := s.callerPkg(which)\n\treturn filepath.Join(s.OutDir, cp, cp+\".go\")\n}\n\nfunc (s *genstate) checkerPkg(which int) string {\n\treturn s.Tag + CheckerName + strconv.Itoa(which)\n}\n\nfunc (s *genstate) checkerFile(which int) string {\n\tcp := s.checkerPkg(which)\n\treturn filepath.Join(s.OutDir, cp, cp+\".go\")\n}\n\nfunc (s *genstate) utilsPkg() string {\n\treturn s.Tag + \"Utils\"\n}\n\nfunc (s *genstate) beginPackage(pkidx int) {\n\ts.pkidx = pkidx\n\ts.derefFuncs = make(map[string]string)\n\ts.assignFuncs = make(map[string]string)\n\ts.allocFuncs = make(map[string]string)\n\ts.globVars = make(map[string]string)\n\ts.genvalFuncs = make(map[string]string)\n}\n\nfunc runImports(files []string) {\n\tverb(1, \"... running goimports\")\n\targs := make([]string, 0, len(files)+1)\n\targs = append(args, \"-w\")\n\targs = append(args, files...)\n\tcmd := exec.Command(\"goimports\", args...)\n\tcoutput, cerr := cmd.CombinedOutput()\n\tif cerr != nil {\n\t\tlog.Fatalf(\"goimports command failed: %s\", string(coutput))\n\t}\n\tverb(1, \"... goimports run complete\")\n}\n\n// shouldEmitFP returns true if we should actually emit code for the function\n// with the specified package + fcn indices. For \"regular\" runs, fcnmask and pkmask\n// will be empty, meaning we want to emit every function in every package. The\n// fuzz-runner program also tries to do testcase \"minimization\", which means that it\n// will try to whittle down the set of packages and functions (by running the generator\n// using the fcnmask and pkmask options) to emit only specific packages or functions.\nfunc shouldEmitFP(fn int, pk int, fcnmask map[int]int, pkmask map[int]int) bool {\n\temitpk := true\n\temitfn := true\n\tif len(pkmask) != 0 {\n\t\temitpk = false\n\t\tif _, ok := pkmask[pk]; ok {\n\t\t\temitpk = true\n\t\t}\n\t}\n\tif len(fcnmask) != 0 {\n\t\temitfn = false\n\t\tif _, ok := fcnmask[fn]; ok {\n\t\t\temitfn = true\n\t\t}\n\t}\n\tdoemit := emitpk && emitfn\n\tverb(2, \"shouldEmitFP(F=%d,P=%d) returns %v\", fn, pk, doemit)\n\treturn doemit\n}\n\n// Generate is the top level code generation hook for this package.\n// Emits code according to the schema in config object 'c'.\nfunc Generate(c GenConfig) int {\n\tmainpkg := c.Tag + \"Main\"\n\n\tvar ipref string\n\tif len(c.PkgPath) > 0 {\n\t\tipref = c.PkgPath\n\t}\n\n\ts := genstate{\n\t\tGenConfig: c,\n\t\tipref:     ipref,\n\t}\n\n\tif s.OutDir != \".\" {\n\t\tverb(1, \"creating %s\", s.OutDir)\n\t\tmakeDir(s.OutDir)\n\t}\n\n\tmainimports := []string{}\n\tfor i := 0; i < s.NumTestPackages; i++ {\n\t\tif shouldEmitFP(-1, i, nil, s.PkgMask) {\n\t\t\tmakeDir(s.OutDir + \"/\" + s.callerPkg(i))\n\t\t\tmakeDir(s.OutDir + \"/\" + s.checkerPkg(i))\n\t\t\tmakeDir(s.OutDir + \"/\" + s.utilsPkg())\n\t\t\tmainimports = append(mainimports, s.callerPkg(i))\n\t\t}\n\t}\n\tmainimports = append(mainimports, s.utilsPkg())\n\n\t// Emit utils package.\n\tverb(1, \"emit utils\")\n\tutilsfile := s.OutDir + \"/\" + s.utilsPkg() + \"/\" + s.utilsPkg() + \".go\"\n\tutilsoutfile := s.openOutputFile(utilsfile, s.utilsPkg(), []string{}, \"\")\n\ts.emitUtils(utilsoutfile, s.MaxFail, s.NumTestPackages)\n\tutilsoutfile.Close()\n\n\tmainfile := s.OutDir + \"/\" + mainpkg + \".go\"\n\tmainoutfile := s.openOutputFile(mainfile, \"main\", mainimports, ipref)\n\n\tallfiles := []string{mainfile, utilsfile}\n\tfor k := 0; k < s.NumTestPackages; k++ {\n\t\tcallerImports := []string{s.checkerPkg(k), s.utilsPkg()}\n\t\tcheckerImports := []string{s.utilsPkg()}\n\t\tif tunables.doReflectCall {\n\t\t\tcallerImports = append(callerImports, \"reflect\")\n\t\t}\n\t\tif s.ForceStackGrowth {\n\t\t\tcallerImports = append(callerImports, \"unsafe\")\n\t\t\tcheckerImports = append(checkerImports, \"unsafe\")\n\t\t}\n\t\tvar calleroutfile, checkeroutfile *os.File\n\t\tif shouldEmitFP(-1, k, nil, s.PkgMask) {\n\t\t\tcalleroutfile = s.openOutputFile(s.callerFile(k), s.callerPkg(k),\n\t\t\t\tcallerImports, ipref)\n\t\t\tcheckeroutfile = s.openOutputFile(s.checkerFile(k), s.checkerPkg(k),\n\t\t\t\tcheckerImports, ipref)\n\t\t\tallfiles = append(allfiles, s.callerFile(k), s.checkerFile(k))\n\t\t}\n\n\t\ts.beginPackage(k)\n\n\t\tvar b bytes.Buffer\n\t\tfor i := 0; i < s.NumTestFunctions; i++ {\n\t\t\tdoemit := shouldEmitFP(i, k, s.FcnMask, s.PkgMask)\n\t\t\ts.Seed = s.GenPair(calleroutfile, checkeroutfile, i, k,\n\t\t\t\t&b, s.Seed, doemit)\n\t\t}\n\n\t\t// When minimization is in effect, we sometimes wind\n\t\t// up eliminating all refs to the utils package. Add a\n\t\t// dummy to help with this.\n\t\tfmt.Fprintf(calleroutfile, \"\\n// dummy\\nvar Dummy UtilsType\\n\")\n\t\tfmt.Fprintf(checkeroutfile, \"\\n// dummy\\nvar Dummy UtilsType\\n\")\n\t\tcalleroutfile.Close()\n\t\tcheckeroutfile.Close()\n\t}\n\ts.emitMain(mainoutfile, s.NumTestFunctions, s.FcnMask, s.PkgMask)\n\n\t// emit go.mod\n\tverb(1, \"opening go.mod\")\n\tfn := s.OutDir + \"/go.mod\"\n\toutf, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\toutf.WriteString(fmt.Sprintf(\"module %s\\n\\ngo 1.17\\n\", s.PkgPath))\n\toutf.Close()\n\n\tverb(1, \"closing files\")\n\tmainoutfile.Close()\n\n\tif s.errs == 0 && s.RunGoImports {\n\t\trunImports(allfiles)\n\t}\n\n\treturn s.errs\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/mapparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// mapparm describes a parameter of map type; it implements the\n// \"parm\" interface.\ntype mapparm struct {\n\taname   string\n\tqname   string\n\tkeytype parm\n\tvaltype parm\n\tkeytmp  string\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p mapparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p mapparm) TypeName() string {\n\treturn p.aname\n}\n\nfunc (p mapparm) QualName() string {\n\treturn p.qname\n}\n\nfunc (p mapparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s %s%s\", prefix, n, suffix))\n}\n\nfunc (p mapparm) String() string {\n\treturn fmt.Sprintf(\"%s map[%s]%s\", p.aname,\n\t\tp.keytype.String(), p.valtype.String())\n}\n\nfunc (p mapparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tvar buf bytes.Buffer\n\n\tverb(5, \"mapparm.GenValue(%d)\", value)\n\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tbuf.WriteString(fmt.Sprintf(\"%s{\", n))\n\tbuf.WriteString(p.keytmp + \": \")\n\n\tvar valstr string\n\tvalstr, value = s.GenValue(f, p.valtype, value, caller)\n\tbuf.WriteString(valstr + \"}\")\n\treturn buf.String(), value\n}\n\nfunc (p mapparm) GenElemRef(elidx int, path string) (string, parm) {\n\tvne := p.valtype.NumElements()\n\tverb(4, \"begin GenElemRef(%d,%s) on %s %d\", elidx, path, p.String(), vne)\n\n\tppath := fmt.Sprintf(\"%s[mkt.%s]\", path, p.keytmp)\n\n\t// otherwise dig into the value\n\tverb(4, \"recur GenElemRef(%d,...)\", elidx)\n\n\t// Otherwise our victim is somewhere inside the value\n\tif p.IsBlank() {\n\t\tppath = \"_\"\n\t}\n\treturn p.valtype.GenElemRef(elidx, ppath)\n}\n\nfunc (p mapparm) NumElements() int {\n\treturn p.valtype.NumElements()\n}\n\nfunc (p mapparm) HasPointer() bool {\n\treturn true\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/numparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"math\"\n)\n\n// numparm describes a numeric parameter type; it implements the\n// \"parm\" interface.\ntype numparm struct {\n\ttag         string\n\twidthInBits uint32\n\tctl         bool\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nvar f32parm *numparm = &numparm{\n\ttag:         \"float\",\n\twidthInBits: uint32(32),\n\tctl:         false,\n}\nvar f64parm *numparm = &numparm{\n\ttag:         \"float\",\n\twidthInBits: uint32(64),\n\tctl:         false,\n}\n\nfunc (p numparm) TypeName() string {\n\tif p.tag == \"byte\" {\n\t\treturn \"byte\"\n\t}\n\treturn fmt.Sprintf(\"%s%d\", p.tag, p.widthInBits)\n}\n\nfunc (p numparm) QualName() string {\n\treturn p.TypeName()\n}\n\nfunc (p numparm) String() string {\n\tif p.tag == \"byte\" {\n\t\treturn \"byte\"\n\t}\n\tctl := \"\"\n\tif p.ctl {\n\t\tctl = \" [ctl=yes]\"\n\t}\n\treturn fmt.Sprintf(\"%s%s\", p.TypeName(), ctl)\n}\n\nfunc (p numparm) NumElements() int {\n\treturn 1\n}\n\nfunc (p numparm) IsControl() bool {\n\treturn p.ctl\n}\n\nfunc (p numparm) GenElemRef(elidx int, path string) (string, parm) {\n\treturn path, &p\n}\n\nfunc (p numparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tt := fmt.Sprintf(\"%s%d%s\", p.tag, p.widthInBits, suffix)\n\tif p.tag == \"byte\" {\n\t\tt = fmt.Sprintf(\"%s%s\", p.tag, suffix)\n\t}\n\tb.WriteString(prefix + \" \" + t)\n}\n\nfunc (p numparm) genRandNum(s *genstate, value int) (string, int) {\n\twhich := uint8(s.wr.Intn(int64(100)))\n\tif p.tag == \"int\" {\n\t\tvar v int64\n\t\tif which < 3 {\n\t\t\t// max\n\t\t\tv = (1 << (p.widthInBits - 1)) - 1\n\n\t\t} else if which < 5 {\n\t\t\t// min\n\t\t\tv = (-1 << (p.widthInBits - 1))\n\t\t} else {\n\t\t\tnrange := int64(1 << (p.widthInBits - 2))\n\t\t\tv = s.wr.Intn(nrange)\n\t\t\tif value%2 != 0 {\n\t\t\t\tv = -v\n\t\t\t}\n\t\t}\n\t\treturn fmt.Sprintf(\"%s%d(%d)\", p.tag, p.widthInBits, v), value + 1\n\t}\n\tif p.tag == \"uint\" || p.tag == \"byte\" {\n\t\tnrange := int64(1 << (p.widthInBits - 2))\n\t\tv := s.wr.Intn(nrange)\n\t\tif p.tag == \"byte\" {\n\t\t\treturn fmt.Sprintf(\"%s(%d)\", p.tag, v), value + 1\n\t\t}\n\t\treturn fmt.Sprintf(\"%s%d(0x%x)\", p.tag, p.widthInBits, v), value + 1\n\t}\n\tif p.tag == \"float\" {\n\t\tif p.widthInBits == 32 {\n\t\t\trf := s.wr.Float32() * (math.MaxFloat32 / 4)\n\t\t\tif value%2 != 0 {\n\t\t\t\trf = -rf\n\t\t\t}\n\t\t\treturn fmt.Sprintf(\"%s%d(%v)\", p.tag, p.widthInBits, rf), value + 1\n\t\t}\n\t\tif p.widthInBits == 64 {\n\t\t\treturn fmt.Sprintf(\"%s%d(%v)\", p.tag, p.widthInBits,\n\t\t\t\ts.wr.NormFloat64()), value + 1\n\t\t}\n\t\tpanic(\"unknown float type\")\n\t}\n\tif p.tag == \"complex\" {\n\t\tif p.widthInBits == 64 {\n\t\t\tf1, v2 := f32parm.genRandNum(s, value)\n\t\t\tf2, v3 := f32parm.genRandNum(s, v2)\n\t\t\treturn fmt.Sprintf(\"complex(%s,%s)\", f1, f2), v3\n\t\t}\n\t\tif p.widthInBits == 128 {\n\t\t\tf1, v2 := f64parm.genRandNum(s, value)\n\t\t\tf2, v3 := f64parm.genRandNum(s, v2)\n\t\t\treturn fmt.Sprintf(\"complex(%v,%v)\", f1, f2), v3\n\t\t}\n\t\tpanic(\"unknown complex type\")\n\t}\n\tpanic(\"unknown numeric type\")\n}\n\nfunc (p numparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tr, nv := p.genRandNum(s, value)\n\tverb(5, \"numparm.GenValue(%d) = %s\", value, r)\n\treturn r, nv\n}\n\nfunc (p numparm) HasPointer() bool {\n\treturn false\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/parm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n)\n\n// parm is an interface describing an abstract parameter var or return\n// var; there will be concrete types of various sorts that implement\n// this interface.\ntype parm interface {\n\n\t// Declare emits text containing a declaration of this param\n\t// or return var into the specified buffer. Prefix is a tag to\n\t// prepend before the declaration (for example a variable\n\t// name) followed by a space; suffix is an arbitrary string to\n\t// tack onto the end of the param's type text. Here 'caller'\n\t// is set to true if we're emitting the caller part of a test\n\t// pair as opposed to the checker.\n\tDeclare(b *bytes.Buffer, prefix string, suffix string, caller bool)\n\n\t// GenElemRef returns a pair [X,Y] corresponding to a\n\t// component piece of some composite parm, where X is a string\n\t// forming the reference (ex: \".field\" if we're picking out a\n\t// struct field) and Y is a parm object corresponding to the\n\t// type of the element.\n\tGenElemRef(elidx int, path string) (string, parm)\n\n\t// GenValue constructs a new concrete random value appropriate\n\t// for the type in question and returns it, along with a\n\t// sequence number indicating how many random decisions we had\n\t// to make. Here \"s\" is the current generator state, \"f\" is\n\t// the current function we're emitting, value is a sequence\n\t// number indicating how many random decisions have been made\n\t// up until this point, and 'caller' is set to true if we're\n\t// emitting the caller part of a test pair as opposed to the\n\t// checker.  Return value is a pair [V,I] where V is the text\n\t// if the value, and I is a new sequence number reflecting any\n\t// additional random choices we had to make.  For example, if\n\t// the parm is something like \"type Foo struct { f1 int32; f2\n\t// float64 }\" then we might expect GenValue to emit something\n\t// like \"Foo{int32(-9), float64(123.123)}\".\n\tGenValue(s *genstate, f *funcdef, value int, caller bool) (string, int)\n\n\t// IsControl returns true if this specific param has been marked\n\t// as the single param that controls recursion for a recursive\n\t// checker function. The test code doesn't check this param for a specific\n\t// value, but instead returns early if it has value 0 or decrements it\n\t// on a recursive call.\n\tIsControl() bool\n\n\t// NumElements returns the total number of discrete elements contained\n\t// in this parm. For non-composite types, this will always be 1.\n\tNumElements() int\n\n\t// String returns a descriptive string for this parm.\n\tString() string\n\n\t// TypeName returns the non-qualified type name for this parm.\n\tTypeName() string\n\n\t// QualName returns a package-qualified type name for this parm.\n\tQualName() string\n\n\t// HasPointer returns true if this parm is of pointer type, or\n\t// if it is a composite that has a pointer element somewhere inside.\n\t// Strings and slices return true for this hook.\n\tHasPointer() bool\n\n\t// IsBlank() returns true if the name of this parm is \"_\" (that is,\n\t// if we randomly chose to make it a blank). SetBlank() is used\n\t// to set the 'blank' property for this parm.\n\tIsBlank() bool\n\tSetBlank(v bool)\n\n\t// AddrTaken() return a token indicating whether this parm should\n\t// be address taken or not, the nature of the address-taken-ness (see\n\t// below at the def of addrTakenHow). SetAddrTaken is used to set\n\t// the address taken property of the parm.\n\tAddrTaken() addrTakenHow\n\tSetAddrTaken(val addrTakenHow)\n\n\t// IsGenVal() returns true if the values of this type should\n\t// be obtained by calling a helper func, as opposed to\n\t// emitting code inline (as one would for things like numeric\n\t// types). SetIsGenVal is used to set the gen-val property of\n\t// the parm.\n\tIsGenVal() bool\n\tSetIsGenVal(val bool)\n\n\t// SkipCompare() returns true if we've randomly decided that\n\t// we don't want to compare the value for this param or\n\t// return.  SetSkipCompare is used to set the skip-compare\n\t// property of the parm.\n\tSkipCompare() skipCompare\n\tSetSkipCompare(val skipCompare)\n}\n\ntype addrTakenHow uint8\n\nconst (\n\t// Param not address taken.\n\tnotAddrTaken addrTakenHow = 0\n\n\t// Param address is taken and used for simple reads/writes.\n\taddrTakenSimple addrTakenHow = 1\n\n\t// Param address is taken and passed to a well-behaved function.\n\taddrTakenPassed addrTakenHow = 2\n\n\t// Param address is taken and stored to a global var.\n\taddrTakenHeap addrTakenHow = 3\n)\n\nfunc (a *addrTakenHow) AddrTaken() addrTakenHow {\n\treturn *a\n}\n\nfunc (a *addrTakenHow) SetAddrTaken(val addrTakenHow) {\n\t*a = val\n}\n\ntype isBlank bool\n\nfunc (b *isBlank) IsBlank() bool {\n\treturn bool(*b)\n}\n\nfunc (b *isBlank) SetBlank(val bool) {\n\t*b = isBlank(val)\n}\n\ntype isGenValFunc bool\n\nfunc (g *isGenValFunc) IsGenVal() bool {\n\treturn bool(*g)\n}\n\nfunc (g *isGenValFunc) SetIsGenVal(val bool) {\n\t*g = isGenValFunc(val)\n}\n\ntype skipCompare int\n\nconst (\n\t// Param not address taken.\n\tSkipAll     = -1\n\tSkipNone    = 0\n\tSkipPayload = 1\n)\n\nfunc (s *skipCompare) SkipCompare() skipCompare {\n\treturn skipCompare(*s)\n}\n\nfunc (s *skipCompare) SetSkipCompare(val skipCompare) {\n\t*s = skipCompare(val)\n}\n\n// containedParms takes an arbitrary param 'p' and returns a slice\n// with 'p' itself plus any component parms contained within 'p'.\nfunc containedParms(p parm) []parm {\n\tvisited := make(map[string]parm)\n\tworklist := []parm{p}\n\n\taddToWork := func(p parm) {\n\t\tif p == nil {\n\t\t\tpanic(\"not expected\")\n\t\t}\n\t\tif _, ok := visited[p.TypeName()]; !ok {\n\t\t\tworklist = append(worklist, p)\n\t\t}\n\t}\n\n\tfor len(worklist) != 0 {\n\t\tcp := worklist[0]\n\t\tworklist = worklist[1:]\n\t\tif _, ok := visited[cp.TypeName()]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tvisited[cp.TypeName()] = cp\n\t\tswitch x := cp.(type) {\n\t\tcase *mapparm:\n\t\t\taddToWork(x.keytype)\n\t\t\taddToWork(x.valtype)\n\t\tcase *structparm:\n\t\t\tfor _, fld := range x.fields {\n\t\t\t\taddToWork(fld)\n\t\t\t}\n\t\tcase *arrayparm:\n\t\t\taddToWork(x.eltype)\n\t\tcase *pointerparm:\n\t\t\taddToWork(x.totype)\n\t\tcase *typedefparm:\n\t\t\taddToWork(x.target)\n\t\t}\n\t}\n\trv := []parm{}\n\tfor _, v := range visited {\n\t\trv = append(rv, v)\n\t}\n\tsort.Slice(rv, func(i, j int) bool {\n\t\tif rv[i].TypeName() == rv[j].TypeName() {\n\t\t\tfmt.Fprintf(os.Stderr, \"%d %d %+v %+v %s %s\\n\", i, j, rv[i], rv[i].String(), rv[j], rv[j].String())\n\t\t\tpanic(\"unexpected\")\n\t\t}\n\t\treturn rv[i].TypeName() < rv[j].TypeName()\n\t})\n\treturn rv\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/pointerparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// pointerparm describes a parameter of pointer type; it implements the\n// \"parm\" interface.\ntype pointerparm struct {\n\ttag    string\n\ttotype parm\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p pointerparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tn := p.totype.TypeName()\n\tif caller {\n\t\tn = p.totype.QualName()\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s *%s%s\", prefix, n, suffix))\n}\n\nfunc (p pointerparm) GenElemRef(elidx int, path string) (string, parm) {\n\treturn path, &p\n}\n\nfunc (p pointerparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tpref := \"\"\n\tif caller {\n\t\tpref = s.checkerPkg(s.pkidx) + \".\"\n\t}\n\tvar valstr string\n\tvalstr, value = s.GenValue(f, p.totype, value, caller)\n\tfname := s.genAllocFunc(p.totype)\n\treturn fmt.Sprintf(\"%s%s(%s)\", pref, fname, valstr), value\n}\n\nfunc (p pointerparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p pointerparm) NumElements() int {\n\treturn 1\n}\n\nfunc (p pointerparm) String() string {\n\treturn fmt.Sprintf(\"*%s\", p.totype)\n}\n\nfunc (p pointerparm) TypeName() string {\n\treturn fmt.Sprintf(\"*%s\", p.totype.TypeName())\n}\n\nfunc (p pointerparm) QualName() string {\n\treturn fmt.Sprintf(\"*%s\", p.totype.QualName())\n}\n\nfunc mkPointerParm(to parm) pointerparm {\n\tvar pp pointerparm\n\tpp.tag = \"pointer\"\n\tpp.totype = to\n\treturn pp\n}\n\nfunc (p pointerparm) HasPointer() bool {\n\treturn true\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/stringparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n)\n\n// stringparm describes a parameter of string type; it implements the\n// \"parm\" interface\ntype stringparm struct {\n\ttag string\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p stringparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tb.WriteString(prefix + \" string\" + suffix)\n}\n\nfunc (p stringparm) GenElemRef(elidx int, path string) (string, parm) {\n\treturn path, &p\n}\n\nvar letters = []rune(\"�꿦3򂨃f6ꂅ8ˋ<􂊇񊶿(z̽|ϣᇊ񁗇򟄼q񧲥筁{ЂƜĽ\")\n\nfunc (p stringparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tns := len(letters) - 9\n\tnel := int(s.wr.Intn(8))\n\tst := int(s.wr.Intn(int64(ns)))\n\ten := min(st+nel, ns)\n\treturn \"\\\"\" + string(letters[st:en]) + \"\\\"\", value + 1\n}\n\nfunc (p stringparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p stringparm) NumElements() int {\n\treturn 1\n}\n\nfunc (p stringparm) String() string {\n\treturn \"string\"\n}\n\nfunc (p stringparm) TypeName() string {\n\treturn \"string\"\n}\n\nfunc (p stringparm) QualName() string {\n\treturn \"string\"\n}\n\nfunc (p stringparm) HasPointer() bool {\n\treturn false\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/structparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// structparm describes a parameter of struct type; it implements the\n// \"parm\" interface.\ntype structparm struct {\n\tsname  string\n\tqname  string\n\tfields []parm\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p structparm) TypeName() string {\n\treturn p.sname\n}\n\nfunc (p structparm) QualName() string {\n\treturn p.qname\n}\n\nfunc (p structparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tn := p.sname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s %s%s\", prefix, n, suffix))\n}\n\nfunc (p structparm) FieldName(i int) string {\n\tif p.fields[i].IsBlank() {\n\t\treturn \"_\"\n\t}\n\treturn fmt.Sprintf(\"F%d\", i)\n}\n\nfunc (p structparm) String() string {\n\tvar buf bytes.Buffer\n\n\tbuf.WriteString(fmt.Sprintf(\"struct %s {\\n\", p.sname))\n\tfor fi, f := range p.fields {\n\t\tbuf.WriteString(fmt.Sprintf(\"%s %s\\n\", p.FieldName(fi), f.String()))\n\t}\n\tbuf.WriteString(\"}\")\n\treturn buf.String()\n}\n\nfunc (p structparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tvar buf bytes.Buffer\n\n\tverb(5, \"structparm.GenValue(%d)\", value)\n\n\tn := p.sname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tbuf.WriteString(fmt.Sprintf(\"%s{\", n))\n\tnbfi := 0\n\tfor fi, fld := range p.fields {\n\t\tvar valstr string\n\t\tvalstr, value = s.GenValue(f, fld, value, caller)\n\t\tif p.fields[fi].IsBlank() {\n\t\t\tbuf.WriteString(\"/* \")\n\t\t\tvalstr = strings.ReplaceAll(valstr, \"/*\", \"[[\")\n\t\t\tvalstr = strings.ReplaceAll(valstr, \"*/\", \"]]\")\n\t\t} else {\n\t\t\twriteCom(&buf, nbfi)\n\t\t}\n\t\tbuf.WriteString(p.FieldName(fi) + \": \")\n\t\tbuf.WriteString(valstr)\n\t\tif p.fields[fi].IsBlank() {\n\t\t\tbuf.WriteString(\" */\")\n\t\t} else {\n\t\t\tnbfi++\n\t\t}\n\t}\n\tbuf.WriteString(\"}\")\n\treturn buf.String(), value\n}\n\nfunc (p structparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p structparm) NumElements() int {\n\tne := 0\n\tfor _, f := range p.fields {\n\t\tne += f.NumElements()\n\t}\n\treturn ne\n}\n\nfunc (p structparm) GenElemRef(elidx int, path string) (string, parm) {\n\tct := 0\n\tverb(4, \"begin GenElemRef(%d,%s) on %s\", elidx, path, p.String())\n\n\tfor fi, f := range p.fields {\n\t\tfne := f.NumElements()\n\n\t\t//verb(4, \"+ examining field %d fne %d ct %d\", fi, fne, ct)\n\n\t\t// Empty field. Continue on.\n\t\tif elidx == ct && fne == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Is this field the element we're interested in?\n\t\tif fne == 1 && elidx == ct {\n\n\t\t\t// The field in question may be a composite that has only\n\t\t\t// multiple elements but a single non-zero-sized element.\n\t\t\t// If this is the case, keep going.\n\t\t\tif sp, ok := f.(*structparm); ok {\n\t\t\t\tif len(sp.fields) > 1 {\n\t\t\t\t\tppath := fmt.Sprintf(\"%s.F%d\", path, fi)\n\t\t\t\t\tif p.fields[fi].IsBlank() || path == \"_\" {\n\t\t\t\t\t\tppath = \"_\"\n\t\t\t\t\t}\n\t\t\t\t\treturn f.GenElemRef(elidx-ct, ppath)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tverb(4, \"found field %d type %s in GenElemRef(%d,%s)\", fi, f.TypeName(), elidx, path)\n\t\t\tppath := fmt.Sprintf(\"%s.F%d\", path, fi)\n\t\t\tif p.fields[fi].IsBlank() || path == \"_\" {\n\t\t\t\tppath = \"_\"\n\t\t\t}\n\t\t\treturn ppath, f\n\t\t}\n\n\t\t// Is the element we want somewhere inside this field?\n\t\tif fne > 1 && elidx >= ct && elidx < ct+fne {\n\t\t\tppath := fmt.Sprintf(\"%s.F%d\", path, fi)\n\t\t\tif p.fields[fi].IsBlank() || path == \"_\" {\n\t\t\t\tppath = \"_\"\n\t\t\t}\n\t\t\treturn f.GenElemRef(elidx-ct, ppath)\n\t\t}\n\n\t\tct += fne\n\t}\n\tpanic(fmt.Sprintf(\"GenElemRef failed for struct %s elidx %d\", p.TypeName(), elidx))\n}\n\nfunc (p structparm) HasPointer() bool {\n\tfor _, f := range p.fields {\n\t\tif f.HasPointer() {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/typedefparm.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// typedefparm describes a parameter that is a typedef of some other\n// type; it implements the \"parm\" interface\ntype typedefparm struct {\n\taname  string\n\tqname  string\n\ttarget parm\n\tisBlank\n\taddrTakenHow\n\tisGenValFunc\n\tskipCompare\n}\n\nfunc (p typedefparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\tb.WriteString(fmt.Sprintf(\"%s %s%s\", prefix, n, suffix))\n}\n\nfunc (p typedefparm) GenElemRef(elidx int, path string) (string, parm) {\n\t_, isarr := p.target.(*arrayparm)\n\t_, isstruct := p.target.(*structparm)\n\t_, ismap := p.target.(*mapparm)\n\trv, rp := p.target.GenElemRef(elidx, path)\n\t// this is hacky, but I don't see a nicer way to do this\n\tif isarr || isstruct || ismap {\n\t\treturn rv, rp\n\t}\n\trp = &p\n\treturn rv, rp\n}\n\nfunc (p typedefparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {\n\tn := p.aname\n\tif caller {\n\t\tn = p.qname\n\t}\n\trv, v := s.GenValue(f, p.target, value, caller)\n\trv = n + \"(\" + rv + \")\"\n\treturn rv, v\n}\n\nfunc (p typedefparm) IsControl() bool {\n\treturn false\n}\n\nfunc (p typedefparm) NumElements() int {\n\treturn p.target.NumElements()\n}\n\nfunc (p typedefparm) String() string {\n\treturn fmt.Sprintf(\"%s typedef of %s\", p.aname, p.target.String())\n\n}\n\nfunc (p typedefparm) TypeName() string {\n\treturn p.aname\n\n}\n\nfunc (p typedefparm) QualName() string {\n\treturn p.qname\n}\n\nfunc (p typedefparm) HasPointer() bool {\n\treturn p.target.HasPointer()\n}\n\nfunc (s *genstate) makeTypedefParm(f *funcdef, target parm, pidx int) parm {\n\tvar tdp typedefparm\n\tns := len(f.typedefs)\n\ttdp.aname = fmt.Sprintf(\"MyTypeF%dS%d\", f.idx, ns)\n\ttdp.qname = fmt.Sprintf(\"%s.MyTypeF%dS%d\", s.checkerPkg(pidx), f.idx, ns)\n\ttdp.target = target\n\ttdp.SetBlank(uint8(s.wr.Intn(100)) < tunables.blankPerc)\n\tf.typedefs = append(f.typedefs, tdp)\n\treturn &tdp\n}\n"
  },
  {
    "path": "cmd/signature-fuzzer/internal/fuzz-generator/wraprand.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage generator\n\nimport (\n\t\"fmt\"\n\t\"math/rand/v2\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n)\n\nconst (\n\tRandCtlNochecks = 0\n\tRandCtlChecks   = 1 << iota\n\tRandCtlCapture\n\tRandCtlPanic\n)\n\nfunc NewWrapRand(seed int64, ctl int) *wraprand {\n\treturn &wraprand{seed: seed, ctl: ctl, rand: rand.New(rand.NewPCG(0, uint64(seed)))}\n}\n\ntype wraprand struct {\n\tf32calls  int\n\tf64calls  int\n\tintncalls int\n\tseed      int64\n\ttag       string\n\tcalls     []string\n\tctl       int\n\trand      *rand.Rand\n}\n\nfunc (w *wraprand) captureCall(tag string, val string) {\n\tvar call strings.Builder\n\tfmt.Fprintf(&call, \"%s: %s\\n\", tag, val)\n\tpc := make([]uintptr, 10)\n\tn := runtime.Callers(1, pc)\n\tif n == 0 {\n\t\tpanic(\"why?\")\n\t}\n\tpc = pc[:n] // pass only valid pcs to runtime.CallersFrames\n\tframes := runtime.CallersFrames(pc)\n\tfor {\n\t\tframe, more := frames.Next()\n\t\tif strings.Contains(frame.File, \"testing.\") {\n\t\t\tbreak\n\t\t}\n\t\tfmt.Fprintf(&call, \"%s %s:%d\\n\", frame.Function, frame.File, frame.Line)\n\t\tif !more {\n\t\t\tbreak\n\t\t}\n\n\t}\n\tw.calls = append(w.calls, call.String())\n}\n\nfunc (w *wraprand) Intn(n int64) int64 {\n\tw.intncalls++\n\trv := w.rand.Int64N(n)\n\tif w.ctl&RandCtlCapture != 0 {\n\t\tw.captureCall(\"Intn\", fmt.Sprintf(\"%d\", rv))\n\t}\n\treturn rv\n}\n\nfunc (w *wraprand) Float32() float32 {\n\tw.f32calls++\n\trv := w.rand.Float32()\n\tif w.ctl&RandCtlCapture != 0 {\n\t\tw.captureCall(\"Float32\", fmt.Sprintf(\"%f\", rv))\n\t}\n\treturn rv\n}\n\nfunc (w *wraprand) NormFloat64() float64 {\n\tw.f64calls++\n\trv := w.rand.NormFloat64()\n\tif w.ctl&RandCtlCapture != 0 {\n\t\tw.captureCall(\"NormFloat64\", fmt.Sprintf(\"%f\", rv))\n\t}\n\treturn rv\n}\n\nfunc (w *wraprand) emitCalls(fn string) {\n\toutf, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o666)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor _, c := range w.calls {\n\t\tfmt.Fprint(outf, c)\n\t}\n\toutf.Close()\n}\n\nfunc (w *wraprand) Equal(w2 *wraprand) bool {\n\treturn w.f32calls == w2.f32calls &&\n\t\tw.f64calls == w2.f64calls &&\n\t\tw.intncalls == w2.intncalls\n}\n\nfunc (w *wraprand) Check(w2 *wraprand) {\n\tif w.ctl != 0 && !w.Equal(w2) {\n\t\tfmt.Fprintf(os.Stderr, \"wraprand consistency check failed:\\n\")\n\t\tt := \"w\"\n\t\tif w.tag != \"\" {\n\t\t\tt = w.tag\n\t\t}\n\t\tt2 := \"w2\"\n\t\tif w2.tag != \"\" {\n\t\t\tt2 = w2.tag\n\t\t}\n\t\tfmt.Fprintf(os.Stderr, \" %s: {f32:%d f64:%d i:%d}\\n\", t,\n\t\t\tw.f32calls, w.f64calls, w.intncalls)\n\t\tfmt.Fprintf(os.Stderr, \" %s: {f32:%d f64:%d i:%d}\\n\", t2,\n\t\t\tw2.f32calls, w2.f64calls, w2.intncalls)\n\t\tif w.ctl&RandCtlCapture != 0 {\n\t\t\tf := fmt.Sprintf(\"/tmp/%s.txt\", t)\n\t\t\tf2 := fmt.Sprintf(\"/tmp/%s.txt\", t2)\n\t\t\tw.emitCalls(f)\n\t\t\tw2.emitCalls(f2)\n\t\t\tfmt.Fprintf(os.Stderr, \"=-= emitted calls to %s, %s\\n\", f, f2)\n\t\t}\n\t\tif w.ctl&RandCtlPanic != 0 {\n\t\t\tpanic(\"bad\")\n\t\t}\n\t}\n}\n\nfunc (w *wraprand) Checkpoint(tag string) {\n\tif w.ctl&RandCtlCapture != 0 {\n\t\tw.calls = append(w.calls, \"=-=\\n\"+tag+\"\\n=-=\\n\")\n\t}\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/fat.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage macho\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"os\"\n)\n\n// A FatFile is a Mach-O universal binary that contains at least one architecture.\ntype FatFile struct {\n\tMagic  uint32\n\tArches []FatArch\n\tcloser io.Closer\n}\n\n// A FatArchHeader represents a fat header for a specific image architecture.\ntype FatArchHeader struct {\n\tCpu    Cpu\n\tSubCpu uint32\n\tOffset uint32\n\tSize   uint32\n\tAlign  uint32\n}\n\nconst fatArchHeaderSize = 5 * 4\n\n// A FatArch is a Mach-O File inside a FatFile.\ntype FatArch struct {\n\tFatArchHeader\n\t*File\n}\n\n// NewFatFile creates a new FatFile for accessing all the Mach-O images in a\n// universal binary. The Mach-O binary is expected to start at position 0 in\n// the ReaderAt.\nfunc NewFatFile(r io.ReaderAt) (*FatFile, error) {\n\tvar ff FatFile\n\tsr := io.NewSectionReader(r, 0, 1<<63-1)\n\n\t// Read the fat_header struct, which is always in big endian.\n\t// Start with the magic number.\n\terr := binary.Read(sr, binary.BigEndian, &ff.Magic)\n\tif err != nil {\n\t\treturn nil, formatError(0, \"error reading magic number, %v\", err)\n\t} else if ff.Magic != MagicFat {\n\t\t// See if this is a Mach-O file via its magic number. The magic\n\t\t// must be converted to little endian first though.\n\t\tvar buf [4]byte\n\t\tbinary.BigEndian.PutUint32(buf[:], ff.Magic)\n\t\tleMagic := binary.LittleEndian.Uint32(buf[:])\n\t\tif leMagic == Magic32 || leMagic == Magic64 {\n\t\t\treturn nil, formatError(0, \"not a fat Mach-O file, leMagic=0x%x\", leMagic)\n\t\t} else {\n\t\t\treturn nil, formatError(0, \"invalid magic number, leMagic=0x%x\", leMagic)\n\t\t}\n\t}\n\toffset := int64(4)\n\n\t// Read the number of FatArchHeaders that come after the fat_header.\n\tvar narch uint32\n\terr = binary.Read(sr, binary.BigEndian, &narch)\n\tif err != nil {\n\t\treturn nil, formatError(offset, \"invalid fat_header %v\", err)\n\t}\n\toffset += 4\n\n\tif narch < 1 {\n\t\treturn nil, formatError(offset, \"file contains no images, narch=%d\", narch)\n\t}\n\n\t// Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure\n\t// there are not duplicate architectures.\n\tseenArches := make(map[uint64]bool, narch)\n\t// Make sure that all images are for the same MH_ type.\n\tvar machoType HdrType\n\n\t// Following the fat_header comes narch fat_arch structs that index\n\t// Mach-O images further in the file.\n\tff.Arches = make([]FatArch, narch)\n\tfor i := uint32(0); i < narch; i++ {\n\t\tfa := &ff.Arches[i]\n\t\terr = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader)\n\t\tif err != nil {\n\t\t\treturn nil, formatError(offset, \"invalid fat_arch header, %v\", err)\n\t\t}\n\t\toffset += fatArchHeaderSize\n\n\t\tfr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size))\n\t\tfa.File, err = NewFile(fr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Make sure the architecture for this image is not duplicate.\n\t\tseenArch := (uint64(fa.Cpu) << 32) | uint64(fa.SubCpu)\n\t\tif o, k := seenArches[seenArch]; o || k {\n\t\t\treturn nil, formatError(offset, \"duplicate architecture cpu=%v, subcpu=%#x\", fa.Cpu, fa.SubCpu)\n\t\t}\n\t\tseenArches[seenArch] = true\n\n\t\t// Make sure the Mach-O type matches that of the first image.\n\t\tif i == 0 {\n\t\t\tmachoType = HdrType(fa.Type)\n\t\t} else {\n\t\t\tif HdrType(fa.Type) != machoType {\n\t\t\t\treturn nil, formatError(offset, \"Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)\", i, fa.Type, machoType)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn &ff, nil\n}\n\n// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O\n// universal binary.\nfunc OpenFat(name string) (*FatFile, error) {\n\tf, err := os.Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tff, err := NewFatFile(f)\n\tif err != nil {\n\t\tf.Close()\n\t\treturn nil, err\n\t}\n\tff.closer = f\n\treturn ff, nil\n}\n\nfunc (ff *FatFile) Close() error {\n\tvar err error\n\tif ff.closer != nil {\n\t\terr = ff.closer.Close()\n\t\tff.closer = nil\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/file.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package macho implements access to Mach-O object files.\npackage macho\n\n// High level access to low level data structures.\n\nimport (\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"debug/dwarf\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"slices\"\n\t\"strings\"\n\t\"unsafe\"\n)\n\n// A File represents an open Mach-O file.\ntype File struct {\n\tFileTOC\n\n\tSymtab   *Symtab\n\tDysymtab *Dysymtab\n\n\tcloser io.Closer\n}\n\ntype FileTOC struct {\n\tFileHeader\n\tByteOrder binary.ByteOrder\n\tLoads     []Load\n\tSections  []*Section\n}\n\nfunc (t *FileTOC) AddLoad(l Load) {\n\tt.Loads = append(t.Loads, l)\n\tt.NCommands++\n\tt.SizeCommands += l.LoadSize(t)\n}\n\n// AddSegment adds segment s to the file table of contents,\n// and also zeroes out the segment information with the expectation\n// that this will be added next.\nfunc (t *FileTOC) AddSegment(s *Segment) {\n\tt.AddLoad(s)\n\ts.Nsect = 0\n\ts.Firstsect = 0\n}\n\n// Adds section to the most recently added Segment\nfunc (t *FileTOC) AddSection(s *Section) {\n\tg := t.Loads[len(t.Loads)-1].(*Segment)\n\tif g.Nsect == 0 {\n\t\tg.Firstsect = uint32(len(t.Sections))\n\t}\n\tg.Nsect++\n\tt.Sections = append(t.Sections, s)\n\tsectionsize := uint32(unsafe.Sizeof(Section32{}))\n\tif g.Command() == LcSegment64 {\n\t\tsectionsize = uint32(unsafe.Sizeof(Section64{}))\n\t}\n\tt.SizeCommands += sectionsize\n\tg.Len += sectionsize\n}\n\n// A Load represents any Mach-O load command.\ntype Load interface {\n\tString() string\n\tCommand() LoadCmd\n\tLoadSize(*FileTOC) uint32 // Need the TOC for alignment, sigh.\n\tPut([]byte, binary.ByteOrder) int\n\n\t// command LC_DYLD_INFO_ONLY contains offsets into __LINKEDIT\n\t// e.g., from \"otool -l a.out\"\n\t//\n\t// \tLoad command 3\n\t//       cmd LC_SEGMENT_64\n\t//   cmdsize 72\n\t//   segname __LINKEDIT\n\t//    vmaddr 0x0000000100002000\n\t//    vmsize 0x0000000000001000\n\t//   fileoff 8192\n\t//  filesize 520\n\t//   maxprot 0x00000007\n\t//  initprot 0x00000001\n\t//    nsects 0\n\t//     flags 0x0\n\t// Load command 4\n\t//             cmd LC_DYLD_INFO_ONLY\n\t//         cmdsize 48\n\t//      rebase_off 8192\n\t//     rebase_size 8\n\t//        bind_off 8200\n\t//       bind_size 24\n\t//   weak_bind_off 0\n\t//  weak_bind_size 0\n\t//   lazy_bind_off 8224\n\t//  lazy_bind_size 16\n\t//      export_off 8240\n\t//     export_size 48\n}\n\n// LoadBytes is the uninterpreted bytes of a Mach-O load command.\ntype LoadBytes []byte\n\n// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command.\ntype SegmentHeader struct {\n\tLoadCmd\n\tLen       uint32\n\tName      string // 16 characters or fewer\n\tAddr      uint64 // memory address\n\tMemsz     uint64 // memory size\n\tOffset    uint64 // file offset\n\tFilesz    uint64 // number of bytes starting at that file offset\n\tMaxprot   uint32\n\tProt      uint32\n\tNsect     uint32\n\tFlag      SegFlags\n\tFirstsect uint32\n}\n\n// A Segment represents a Mach-O 32-bit or 64-bit load segment command.\ntype Segment struct {\n\tSegmentHeader\n\n\t// Embed ReaderAt for ReadAt method.\n\t// Do not embed SectionReader directly\n\t// to avoid having Read and Seek.\n\t// If a client wants Read and Seek it must use\n\t// Open() to avoid fighting over the seek offset\n\t// with other clients.\n\tio.ReaderAt\n\tsr *io.SectionReader\n}\n\nfunc (s *Segment) Put32(b []byte, o binary.ByteOrder) int {\n\to.PutUint32(b[0*4:], uint32(s.LoadCmd))\n\to.PutUint32(b[1*4:], s.Len)\n\tputAtMost16Bytes(b[2*4:], s.Name)\n\to.PutUint32(b[6*4:], uint32(s.Addr))\n\to.PutUint32(b[7*4:], uint32(s.Memsz))\n\to.PutUint32(b[8*4:], uint32(s.Offset))\n\to.PutUint32(b[9*4:], uint32(s.Filesz))\n\to.PutUint32(b[10*4:], s.Maxprot)\n\to.PutUint32(b[11*4:], s.Prot)\n\to.PutUint32(b[12*4:], s.Nsect)\n\to.PutUint32(b[13*4:], uint32(s.Flag))\n\treturn 14 * 4\n}\n\nfunc (s *Segment) Put64(b []byte, o binary.ByteOrder) int {\n\to.PutUint32(b[0*4:], uint32(s.LoadCmd))\n\to.PutUint32(b[1*4:], s.Len)\n\tputAtMost16Bytes(b[2*4:], s.Name)\n\to.PutUint64(b[6*4+0*8:], s.Addr)\n\to.PutUint64(b[6*4+1*8:], s.Memsz)\n\to.PutUint64(b[6*4+2*8:], s.Offset)\n\to.PutUint64(b[6*4+3*8:], s.Filesz)\n\to.PutUint32(b[6*4+4*8:], s.Maxprot)\n\to.PutUint32(b[7*4+4*8:], s.Prot)\n\to.PutUint32(b[8*4+4*8:], s.Nsect)\n\to.PutUint32(b[9*4+4*8:], uint32(s.Flag))\n\treturn 10*4 + 4*8\n}\n\n// LoadCmdBytes is a command-tagged sequence of bytes.\n// This is used for Load Commands that are not (yet)\n// interesting to us, and to common up this behavior for\n// all those that are.\ntype LoadCmdBytes struct {\n\tLoadCmd\n\tLoadBytes\n}\n\ntype SectionHeader struct {\n\tName      string\n\tSeg       string\n\tAddr      uint64\n\tSize      uint64\n\tOffset    uint32\n\tAlign     uint32\n\tReloff    uint32\n\tNreloc    uint32\n\tFlags     SecFlags\n\tReserved1 uint32\n\tReserved2 uint32\n\tReserved3 uint32 // only present if original was 64-bit\n}\n\n// A Reloc represents a Mach-O relocation.\ntype Reloc struct {\n\tAddr  uint32\n\tValue uint32\n\t// when Scattered == false && Extern == true, Value is the symbol number.\n\t// when Scattered == false && Extern == false, Value is the section number.\n\t// when Scattered == true, Value is the value that this reloc refers to.\n\tType      uint8\n\tLen       uint8 // 0=byte, 1=word, 2=long, 3=quad\n\tPcrel     bool\n\tExtern    bool // valid if Scattered == false\n\tScattered bool\n}\n\ntype Section struct {\n\tSectionHeader\n\tRelocs []Reloc\n\n\t// Embed ReaderAt for ReadAt method.\n\t// Do not embed SectionReader directly\n\t// to avoid having Read and Seek.\n\t// If a client wants Read and Seek it must use\n\t// Open() to avoid fighting over the seek offset\n\t// with other clients.\n\tio.ReaderAt\n\tsr *io.SectionReader\n}\n\nfunc (s *Section) Put32(b []byte, o binary.ByteOrder) int {\n\tputAtMost16Bytes(b[0:], s.Name)\n\tputAtMost16Bytes(b[16:], s.Seg)\n\to.PutUint32(b[8*4:], uint32(s.Addr))\n\to.PutUint32(b[9*4:], uint32(s.Size))\n\to.PutUint32(b[10*4:], s.Offset)\n\to.PutUint32(b[11*4:], s.Align)\n\to.PutUint32(b[12*4:], s.Reloff)\n\to.PutUint32(b[13*4:], s.Nreloc)\n\to.PutUint32(b[14*4:], uint32(s.Flags))\n\to.PutUint32(b[15*4:], s.Reserved1)\n\to.PutUint32(b[16*4:], s.Reserved2)\n\ta := 17 * 4\n\treturn a + s.PutRelocs(b[a:], o)\n}\n\nfunc (s *Section) Put64(b []byte, o binary.ByteOrder) int {\n\tputAtMost16Bytes(b[0:], s.Name)\n\tputAtMost16Bytes(b[16:], s.Seg)\n\to.PutUint64(b[8*4+0*8:], s.Addr)\n\to.PutUint64(b[8*4+1*8:], s.Size)\n\to.PutUint32(b[8*4+2*8:], s.Offset)\n\to.PutUint32(b[9*4+2*8:], s.Align)\n\to.PutUint32(b[10*4+2*8:], s.Reloff)\n\to.PutUint32(b[11*4+2*8:], s.Nreloc)\n\to.PutUint32(b[12*4+2*8:], uint32(s.Flags))\n\to.PutUint32(b[13*4+2*8:], s.Reserved1)\n\to.PutUint32(b[14*4+2*8:], s.Reserved2)\n\to.PutUint32(b[15*4+2*8:], s.Reserved3)\n\ta := 16*4 + 2*8\n\treturn a + s.PutRelocs(b[a:], o)\n}\n\nfunc (s *Section) PutRelocs(b []byte, o binary.ByteOrder) int {\n\ta := 0\n\tfor _, r := range s.Relocs {\n\t\tvar ri relocInfo\n\t\ttyp := uint32(r.Type) & (1<<4 - 1)\n\t\tlen := uint32(r.Len) & (1<<2 - 1)\n\t\tpcrel := uint32(0)\n\t\tif r.Pcrel {\n\t\t\tpcrel = 1\n\t\t}\n\t\text := uint32(0)\n\t\tif r.Extern {\n\t\t\text = 1\n\t\t}\n\t\tswitch {\n\t\tcase r.Scattered:\n\t\t\tri.Addr = r.Addr&(1<<24-1) | typ<<24 | len<<28 | 1<<31 | pcrel<<30\n\t\t\tri.Symnum = r.Value\n\t\tcase o == binary.LittleEndian:\n\t\t\tri.Addr = r.Addr\n\t\t\tri.Symnum = r.Value&(1<<24-1) | pcrel<<24 | len<<25 | ext<<27 | typ<<28\n\t\tcase o == binary.BigEndian:\n\t\t\tri.Addr = r.Addr\n\t\t\tri.Symnum = r.Value<<8 | pcrel<<7 | len<<5 | ext<<4 | typ\n\t\t}\n\t\to.PutUint32(b, ri.Addr)\n\t\to.PutUint32(b[4:], ri.Symnum)\n\t\ta += 8\n\t\tb = b[8:]\n\t}\n\treturn a\n}\n\nfunc putAtMost16Bytes(b []byte, n string) {\n\tfor i := range n { // at most 16 bytes\n\t\tif i == 16 {\n\t\t\tbreak\n\t\t}\n\t\tb[i] = n[i]\n\t}\n}\n\n// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.\ntype Symbol struct {\n\tName  string\n\tType  uint8\n\tSect  uint8\n\tDesc  uint16\n\tValue uint64\n}\n\n/*\n * Mach-O reader\n */\n\n// FormatError is returned by some operations if the data does\n// not have the correct format for an object file.\ntype FormatError struct {\n\toff int64\n\tmsg string\n}\n\nfunc formatError(off int64, format string, data ...any) *FormatError {\n\treturn &FormatError{off, fmt.Sprintf(format, data...)}\n}\n\nfunc (e *FormatError) Error() string {\n\treturn e.msg + fmt.Sprintf(\" in record at byte %#x\", e.off)\n}\n\nfunc (e *FormatError) String() string {\n\treturn e.Error()\n}\n\n// DerivedCopy returns a modified copy of the TOC, with empty loads and sections,\n// and with the specified header type and flags.\nfunc (t *FileTOC) DerivedCopy(Type HdrType, Flags HdrFlags) *FileTOC {\n\th := t.FileHeader\n\th.NCommands, h.SizeCommands, h.Type, h.Flags = 0, 0, Type, Flags\n\n\treturn &FileTOC{FileHeader: h, ByteOrder: t.ByteOrder}\n}\n\n// TOCSize returns the size in bytes of the object file representation\n// of the header and Load Commands (including Segments and Sections, but\n// not their contents) at the beginning of a Mach-O file.  This typically\n// overlaps the text segment in the object file.\nfunc (t *FileTOC) TOCSize() uint32 {\n\treturn t.HdrSize() + t.LoadSize()\n}\n\n// LoadAlign returns the required alignment of Load commands in a binary.\n// This is used to add padding for necessary alignment.\nfunc (t *FileTOC) LoadAlign() uint64 {\n\tif t.Magic == Magic64 {\n\t\treturn 8\n\t}\n\treturn 4\n}\n\n// SymbolSize returns the size in bytes of a Symbol (Nlist32 or Nlist64)\nfunc (t *FileTOC) SymbolSize() uint32 {\n\tif t.Magic == Magic64 {\n\t\treturn uint32(unsafe.Sizeof(Nlist64{}))\n\t}\n\treturn uint32(unsafe.Sizeof(Nlist32{}))\n}\n\n// HdrSize returns the size in bytes of the Macho header for a given\n// magic number (where the magic number has been appropriately byte-swapped).\nfunc (t *FileTOC) HdrSize() uint32 {\n\tswitch t.Magic {\n\tcase Magic32:\n\t\treturn fileHeaderSize32\n\tcase Magic64:\n\t\treturn fileHeaderSize64\n\tcase MagicFat:\n\t\tpanic(\"MagicFat not handled yet\")\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"Unexpected magic number 0x%x, expected Mach-O object file\", t.Magic))\n\t}\n}\n\n// LoadSize returns the size of all the load commands in a file's table-of contents\n// (but not their associated data, e.g., sections and symbol tables)\nfunc (t *FileTOC) LoadSize() uint32 {\n\tcmdsz := uint32(0)\n\tfor _, l := range t.Loads {\n\t\ts := l.LoadSize(t)\n\t\tcmdsz += s\n\t}\n\treturn cmdsz\n}\n\n// FileSize returns the size in bytes of the header, load commands, and the\n// in-file contents of all the segments and sections included in those\n// load commands, accounting for their offsets within the file.\nfunc (t *FileTOC) FileSize() uint64 {\n\tsz := uint64(t.LoadSize()) // ought to be contained in text segment, but just in case.\n\tfor _, l := range t.Loads {\n\t\tif s, ok := l.(*Segment); ok {\n\t\t\tif m := s.Offset + s.Filesz; m > sz {\n\t\t\t\tsz = m\n\t\t\t}\n\t\t}\n\t}\n\treturn sz\n}\n\n// Put writes the header and all load commands to buffer, using\n// the byte ordering specified in FileTOC t.  For sections, this\n// writes the headers that come in-line with the segment Load commands,\n// but does not write the reference data for those sections.\nfunc (t *FileTOC) Put(buffer []byte) int {\n\tnext := t.FileHeader.Put(buffer, t.ByteOrder)\n\tfor _, l := range t.Loads {\n\t\tif s, ok := l.(*Segment); ok {\n\t\t\tswitch t.Magic {\n\t\t\tcase Magic64:\n\t\t\t\tnext += s.Put64(buffer[next:], t.ByteOrder)\n\t\t\t\tfor i := uint32(0); i < s.Nsect; i++ {\n\t\t\t\t\tc := t.Sections[i+s.Firstsect]\n\t\t\t\t\tnext += c.Put64(buffer[next:], t.ByteOrder)\n\t\t\t\t}\n\t\t\tcase Magic32:\n\t\t\t\tnext += s.Put32(buffer[next:], t.ByteOrder)\n\t\t\t\tfor i := uint32(0); i < s.Nsect; i++ {\n\t\t\t\t\tc := t.Sections[i+s.Firstsect]\n\t\t\t\t\tnext += c.Put32(buffer[next:], t.ByteOrder)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"Unexpected magic number 0x%x\", t.Magic))\n\t\t\t}\n\n\t\t} else {\n\t\t\tnext += l.Put(buffer[next:], t.ByteOrder)\n\t\t}\n\t}\n\treturn next\n}\n\n// UncompressedSize returns the size of the segment with its sections uncompressed, ignoring\n// its offset within the file.  The returned size is rounded up to the power of two in align.\nfunc (s *Segment) UncompressedSize(t *FileTOC, align uint64) uint64 {\n\tsz := uint64(0)\n\tfor j := uint32(0); j < s.Nsect; j++ {\n\t\tc := t.Sections[j+s.Firstsect]\n\t\tsz += c.UncompressedSize()\n\t}\n\treturn (sz + align - 1) & uint64(-int64(align))\n}\n\nfunc (s *Section) UncompressedSize() uint64 {\n\tif !strings.HasPrefix(s.Name, \"__z\") {\n\t\treturn s.Size\n\t}\n\tb := make([]byte, 12)\n\tn, err := s.sr.ReadAt(b, 0)\n\tif err != nil {\n\t\tpanic(\"Malformed object file\")\n\t}\n\tif n != len(b) {\n\t\treturn s.Size\n\t}\n\tif string(b[:4]) == \"ZLIB\" {\n\t\treturn binary.BigEndian.Uint64(b[4:12])\n\t}\n\treturn s.Size\n}\n\nfunc (s *Section) PutData(b []byte) {\n\tbb := b[0:s.Size]\n\tn, err := s.sr.ReadAt(bb, 0)\n\tif err != nil || uint64(n) != s.Size {\n\t\tpanic(\"Malformed object file (ReadAt error)\")\n\t}\n}\n\nfunc (s *Section) PutUncompressedData(b []byte) {\n\tif strings.HasPrefix(s.Name, \"__z\") {\n\t\tbb := make([]byte, 12)\n\t\tn, err := s.sr.ReadAt(bb, 0)\n\t\tif err != nil {\n\t\t\tpanic(\"Malformed object file\")\n\t\t}\n\t\tif n == len(bb) && string(bb[:4]) == \"ZLIB\" {\n\t\t\tsize := binary.BigEndian.Uint64(bb[4:12])\n\t\t\t// Decompress starting at b[12:]\n\t\t\tr, err := zlib.NewReader(io.NewSectionReader(s, 12, int64(size)-12))\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Malformed object file (zlib.NewReader error)\")\n\t\t\t}\n\t\t\tn, err := io.ReadFull(r, b[0:size])\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Malformed object file (ReadFull error)\")\n\t\t\t}\n\t\t\tif uint64(n) != size {\n\t\t\t\tpanic(fmt.Sprintf(\"PutUncompressedData, expected to read %d bytes, instead read %d\", size, n))\n\t\t\t}\n\t\t\tif err := r.Close(); err != nil {\n\t\t\t\tpanic(\"Malformed object file (Close error)\")\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\t// Not compressed\n\ts.PutData(b)\n}\n\nfunc (b LoadBytes) String() string {\n\tvar s strings.Builder\n\ts.WriteString(\"[\")\n\tfor i, a := range b {\n\t\tif i > 0 {\n\t\t\ts.WriteString(\" \")\n\t\t\tif len(b) > 48 && i >= 16 {\n\t\t\t\tfmt.Fprintf(&s, \"... (%d bytes)\", len(b))\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(&s, \"%x\", a)\n\t}\n\ts.WriteString(\"]\")\n\treturn s.String()\n}\n\nfunc (b LoadBytes) Raw() []byte                { return b }\nfunc (b LoadBytes) Copy() LoadBytes            { return LoadBytes(slices.Clone(b)) }\nfunc (b LoadBytes) LoadSize(t *FileTOC) uint32 { return uint32(len(b)) }\n\nfunc (lc LoadCmd) Put(b []byte, o binary.ByteOrder) int {\n\tpanic(fmt.Sprintf(\"Put not implemented for %s\", lc.String()))\n}\n\nfunc (s LoadCmdBytes) String() string {\n\treturn s.LoadCmd.String() + \": \" + s.LoadBytes.String()\n}\nfunc (s LoadCmdBytes) Copy() LoadCmdBytes {\n\treturn LoadCmdBytes{LoadCmd: s.LoadCmd, LoadBytes: s.LoadBytes.Copy()}\n}\n\nfunc (s *SegmentHeader) String() string {\n\treturn fmt.Sprintf(\n\t\t\"Seg %s, len=0x%x, addr=0x%x, memsz=0x%x, offset=0x%x, filesz=0x%x, maxprot=0x%x, prot=0x%x, nsect=%d, flag=0x%x, firstsect=%d\",\n\t\ts.Name, s.Len, s.Addr, s.Memsz, s.Offset, s.Filesz, s.Maxprot, s.Prot, s.Nsect, s.Flag, s.Firstsect)\n}\n\nfunc (s *Segment) String() string {\n\treturn fmt.Sprintf(\n\t\t\"Seg %s, len=0x%x, addr=0x%x, memsz=0x%x, offset=0x%x, filesz=0x%x, maxprot=0x%x, prot=0x%x, nsect=%d, flag=0x%x, firstsect=%d\",\n\t\ts.Name, s.Len, s.Addr, s.Memsz, s.Offset, s.Filesz, s.Maxprot, s.Prot, s.Nsect, s.Flag, s.Firstsect)\n}\n\n// Data reads and returns the contents of the segment.\nfunc (s *Segment) Data() ([]byte, error) {\n\tdat := make([]byte, s.sr.Size())\n\tn, err := s.sr.ReadAt(dat, 0)\n\tif n == len(dat) {\n\t\terr = nil\n\t}\n\treturn dat[0:n], err\n}\n\nfunc (s *Segment) Copy() *Segment {\n\tr := &Segment{SegmentHeader: s.SegmentHeader}\n\treturn r\n}\nfunc (s *Segment) CopyZeroed() *Segment {\n\tr := s.Copy()\n\tr.Filesz = 0\n\tr.Offset = 0\n\tr.Nsect = 0\n\tr.Firstsect = 0\n\tif s.Command() == LcSegment64 {\n\t\tr.Len = uint32(unsafe.Sizeof(Segment64{}))\n\t} else {\n\t\tr.Len = uint32(unsafe.Sizeof(Segment32{}))\n\t}\n\treturn r\n}\n\nfunc (s *Segment) LoadSize(t *FileTOC) uint32 {\n\tif s.Command() == LcSegment64 {\n\t\treturn uint32(unsafe.Sizeof(Segment64{})) + uint32(s.Nsect)*uint32(unsafe.Sizeof(Section64{}))\n\t}\n\treturn uint32(unsafe.Sizeof(Segment32{})) + uint32(s.Nsect)*uint32(unsafe.Sizeof(Section32{}))\n}\n\n// Open returns a new ReadSeeker reading the segment.\nfunc (s *Segment) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }\n\n// Data reads and returns the contents of the Mach-O section.\nfunc (s *Section) Data() ([]byte, error) {\n\tdat := make([]byte, s.sr.Size())\n\tn, err := s.sr.ReadAt(dat, 0)\n\tif n == len(dat) {\n\t\terr = nil\n\t}\n\treturn dat[0:n], err\n}\n\nfunc (s *Section) Copy() *Section {\n\treturn &Section{SectionHeader: s.SectionHeader}\n}\n\n// Open returns a new ReadSeeker reading the Mach-O section.\nfunc (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }\n\n// A Dylib represents a Mach-O load dynamic library command.\ntype Dylib struct {\n\tDylibCmd\n\tName           string\n\tTime           uint32\n\tCurrentVersion uint32\n\tCompatVersion  uint32\n}\n\nfunc (s *Dylib) String() string { return \"Dylib \" + s.Name }\nfunc (s *Dylib) Copy() *Dylib {\n\tr := *s\n\treturn &r\n}\nfunc (s *Dylib) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(RoundUp(uint64(unsafe.Sizeof(DylibCmd{}))+uint64(len(s.Name)), t.LoadAlign()))\n}\n\ntype Dylinker struct {\n\tDylinkerCmd // shared by 3 commands, need the LoadCmd\n\tName        string\n}\n\nfunc (s *Dylinker) String() string { return s.DylinkerCmd.LoadCmd.String() + \" \" + s.Name }\nfunc (s *Dylinker) Copy() *Dylinker {\n\treturn &Dylinker{DylinkerCmd: s.DylinkerCmd, Name: s.Name}\n}\nfunc (s *Dylinker) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(RoundUp(uint64(unsafe.Sizeof(DylinkerCmd{}))+uint64(len(s.Name)), t.LoadAlign()))\n}\n\n// A Symtab represents a Mach-O symbol table command.\ntype Symtab struct {\n\tSymtabCmd\n\tSyms []Symbol\n}\n\nfunc (s *Symtab) Put(b []byte, o binary.ByteOrder) int {\n\to.PutUint32(b[0*4:], uint32(s.LoadCmd))\n\to.PutUint32(b[1*4:], s.Len)\n\to.PutUint32(b[2*4:], s.Symoff)\n\to.PutUint32(b[3*4:], s.Nsyms)\n\to.PutUint32(b[4*4:], s.Stroff)\n\to.PutUint32(b[5*4:], s.Strsize)\n\treturn 6 * 4\n}\n\nfunc (s *Symtab) String() string { return fmt.Sprintf(\"Symtab %#v\", s.SymtabCmd) }\nfunc (s *Symtab) Copy() *Symtab {\n\treturn &Symtab{SymtabCmd: s.SymtabCmd, Syms: slices.Clone(s.Syms)}\n}\nfunc (s *Symtab) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(SymtabCmd{}))\n}\n\ntype LinkEditData struct {\n\tLinkEditDataCmd\n}\n\nfunc (s *LinkEditData) String() string { return \"LinkEditData \" + s.LoadCmd.String() }\nfunc (s *LinkEditData) Copy() *LinkEditData {\n\treturn &LinkEditData{LinkEditDataCmd: s.LinkEditDataCmd}\n}\nfunc (s *LinkEditData) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(LinkEditDataCmd{}))\n}\n\ntype Uuid struct {\n\tUuidCmd\n}\n\nfunc (s *Uuid) String() string {\n\treturn fmt.Sprintf(\"Uuid %X-%X-%X-%X-%X\",\n\t\ts.Id[0:4], s.Id[4:6], s.Id[6:8], s.Id[8:10], s.Id[10:16])\n} // 8-4-4-4-12\nfunc (s *Uuid) Copy() *Uuid {\n\treturn &Uuid{UuidCmd: s.UuidCmd}\n}\nfunc (s *Uuid) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(UuidCmd{}))\n}\nfunc (s *Uuid) Put(b []byte, o binary.ByteOrder) int {\n\to.PutUint32(b[0*4:], uint32(s.LoadCmd))\n\to.PutUint32(b[1*4:], s.Len)\n\tcopy(b[2*4:], s.Id[0:])\n\treturn int(s.Len)\n}\n\ntype DyldInfo struct {\n\tDyldInfoCmd\n}\n\nfunc (s *DyldInfo) String() string { return \"DyldInfo \" + s.LoadCmd.String() }\nfunc (s *DyldInfo) Copy() *DyldInfo {\n\treturn &DyldInfo{DyldInfoCmd: s.DyldInfoCmd}\n}\nfunc (s *DyldInfo) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(DyldInfoCmd{}))\n}\n\ntype EncryptionInfo struct {\n\tEncryptionInfoCmd\n}\n\nfunc (s *EncryptionInfo) String() string { return \"EncryptionInfo \" + s.LoadCmd.String() }\nfunc (s *EncryptionInfo) Copy() *EncryptionInfo {\n\treturn &EncryptionInfo{EncryptionInfoCmd: s.EncryptionInfoCmd}\n}\nfunc (s *EncryptionInfo) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(EncryptionInfoCmd{}))\n}\n\n// A Dysymtab represents a Mach-O dynamic symbol table command.\ntype Dysymtab struct {\n\tDysymtabCmd\n\tIndirectSyms []uint32 // indices into Symtab.Syms\n}\n\nfunc (s *Dysymtab) String() string { return fmt.Sprintf(\"Dysymtab %#v\", s.DysymtabCmd) }\nfunc (s *Dysymtab) Copy() *Dysymtab {\n\treturn &Dysymtab{DysymtabCmd: s.DysymtabCmd, IndirectSyms: slices.Clone(s.IndirectSyms)}\n}\nfunc (s *Dysymtab) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(unsafe.Sizeof(DysymtabCmd{}))\n}\n\n// A Rpath represents a Mach-O rpath command.\ntype Rpath struct {\n\tLoadCmd\n\tPath string\n}\n\nfunc (s *Rpath) String() string   { return \"Rpath \" + s.Path }\nfunc (s *Rpath) Command() LoadCmd { return LcRpath }\nfunc (s *Rpath) Copy() *Rpath {\n\treturn &Rpath{Path: s.Path}\n}\nfunc (s *Rpath) LoadSize(t *FileTOC) uint32 {\n\treturn uint32(RoundUp(uint64(unsafe.Sizeof(RpathCmd{}))+uint64(len(s.Path)), t.LoadAlign()))\n}\n\n// Open opens the named file using os.Open and prepares it for use as a Mach-O binary.\nfunc Open(name string) (*File, error) {\n\tf, err := os.Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tff, err := NewFile(f)\n\tif err != nil {\n\t\tf.Close()\n\t\treturn nil, err\n\t}\n\tff.closer = f\n\treturn ff, nil\n}\n\n// Close closes the File.\n// If the File was created using NewFile directly instead of Open,\n// Close has no effect.\nfunc (f *File) Close() error {\n\tvar err error\n\tif f.closer != nil {\n\t\terr = f.closer.Close()\n\t\tf.closer = nil\n\t}\n\treturn err\n}\n\n// NewFile creates a new File for accessing a Mach-O binary in an underlying reader.\n// The Mach-O binary is expected to start at position 0 in the ReaderAt.\nfunc NewFile(r io.ReaderAt) (*File, error) {\n\tf := new(File)\n\tsr := io.NewSectionReader(r, 0, 1<<63-1)\n\n\t// Read and decode Mach magic to determine byte order, size.\n\t// Magic32 and Magic64 differ only in the bottom bit.\n\tvar ident [4]byte\n\tif _, err := r.ReadAt(ident[0:], 0); err != nil {\n\t\treturn nil, err\n\t}\n\tbe := binary.BigEndian.Uint32(ident[0:])\n\tle := binary.LittleEndian.Uint32(ident[0:])\n\tswitch Magic32 &^ 1 {\n\tcase be &^ 1:\n\t\tf.ByteOrder = binary.BigEndian\n\t\tf.Magic = be\n\tcase le &^ 1:\n\t\tf.ByteOrder = binary.LittleEndian\n\t\tf.Magic = le\n\tdefault:\n\t\treturn nil, formatError(0, \"invalid magic number be=0x%x, le=0x%x\", be, le)\n\t}\n\n\t// Read entire file header.\n\tif err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Then load commands.\n\toffset := int64(fileHeaderSize32)\n\tif f.Magic == Magic64 {\n\t\toffset = fileHeaderSize64\n\t}\n\tdat := make([]byte, f.SizeCommands)\n\tif _, err := r.ReadAt(dat, offset); err != nil {\n\t\treturn nil, err\n\t}\n\tf.Loads = make([]Load, f.NCommands)\n\tbo := f.ByteOrder\n\tfor i := range f.Loads {\n\t\t// Each load command begins with uint32 command and length.\n\t\tif len(dat) < 8 {\n\t\t\treturn nil, formatError(offset, \"command block too small, len(dat) = %d\", len(dat))\n\t\t}\n\t\tcmd, siz := LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8])\n\t\tif siz < 8 || siz > uint32(len(dat)) {\n\t\t\treturn nil, formatError(offset, \"invalid command block size, len(dat)=%d, size=%d\", len(dat), siz)\n\t\t}\n\t\tvar cmddat []byte\n\t\tcmddat, dat = dat[0:siz], dat[siz:]\n\t\toffset += int64(siz)\n\t\tvar s *Segment\n\t\tswitch cmd {\n\t\tdefault:\n\t\t\tf.Loads[i] = LoadCmdBytes{LoadCmd(cmd), LoadBytes(cmddat)}\n\n\t\tcase LcUuid:\n\t\t\tvar hdr UuidCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := &Uuid{UuidCmd: hdr}\n\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcRpath:\n\t\t\tvar hdr RpathCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := &Rpath{LoadCmd: hdr.LoadCmd}\n\t\t\tif hdr.Path >= uint32(len(cmddat)) {\n\t\t\t\treturn nil, formatError(offset, \"invalid path in rpath command, len(cmddat)=%d, hdr.Path=%d\", len(cmddat), hdr.Path)\n\t\t\t}\n\t\t\tl.Path = cstring(cmddat[hdr.Path:])\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcLoadDylinker, LcIdDylinker, LcDyldEnvironment:\n\t\t\tvar hdr DylinkerCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := new(Dylinker)\n\t\t\tif hdr.Name >= uint32(len(cmddat)) {\n\t\t\t\treturn nil, formatError(offset, \"invalid name in dynamic linker command, hdr.Name=%d, len(cmddat)=%d\", hdr.Name, len(cmddat))\n\t\t\t}\n\t\t\tl.Name = cstring(cmddat[hdr.Name:])\n\t\t\tl.DylinkerCmd = hdr\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcDylib:\n\t\t\tvar hdr DylibCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := new(Dylib)\n\t\t\tif hdr.Name >= uint32(len(cmddat)) {\n\t\t\t\treturn nil, formatError(offset, \"invalid name in dynamic library command, hdr.Name=%d, len(cmddat)=%d\", hdr.Name, len(cmddat))\n\t\t\t}\n\t\t\tl.Name = cstring(cmddat[hdr.Name:])\n\t\t\tl.Time = hdr.Time\n\t\t\tl.CurrentVersion = hdr.CurrentVersion\n\t\t\tl.CompatVersion = hdr.CompatVersion\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcSymtab:\n\t\t\tvar hdr SymtabCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tstrtab := make([]byte, hdr.Strsize)\n\t\t\tif _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tvar symsz int\n\t\t\tif f.Magic == Magic64 {\n\t\t\t\tsymsz = 16\n\t\t\t} else {\n\t\t\t\tsymsz = 12\n\t\t\t}\n\t\t\tsymdat := make([]byte, int(hdr.Nsyms)*symsz)\n\t\t\tif _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tst, err := f.parseSymtab(symdat, strtab, &hdr, offset)\n\t\t\tst.SymtabCmd = hdr\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tf.Loads[i] = st\n\t\t\tf.Symtab = st\n\n\t\tcase LcDysymtab:\n\t\t\tvar hdr DysymtabCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdat := make([]byte, hdr.Nindirectsyms*4)\n\t\t\tif _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tx := make([]uint32, hdr.Nindirectsyms)\n\t\t\tif err := binary.Read(bytes.NewReader(dat), bo, x); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tst := new(Dysymtab)\n\t\t\tst.DysymtabCmd = hdr\n\t\t\tst.IndirectSyms = x\n\t\t\tf.Loads[i] = st\n\t\t\tf.Dysymtab = st\n\n\t\tcase LcSegment:\n\t\t\tvar seg32 Segment32\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &seg32); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ts = new(Segment)\n\t\t\ts.LoadCmd = cmd\n\t\t\ts.Len = siz\n\t\t\ts.Name = cstring(seg32.Name[0:])\n\t\t\ts.Addr = uint64(seg32.Addr)\n\t\t\ts.Memsz = uint64(seg32.Memsz)\n\t\t\ts.Offset = uint64(seg32.Offset)\n\t\t\ts.Filesz = uint64(seg32.Filesz)\n\t\t\ts.Maxprot = seg32.Maxprot\n\t\t\ts.Prot = seg32.Prot\n\t\t\ts.Nsect = seg32.Nsect\n\t\t\ts.Flag = seg32.Flag\n\t\t\ts.Firstsect = uint32(len(f.Sections))\n\t\t\tf.Loads[i] = s\n\t\t\tfor i := 0; i < int(s.Nsect); i++ {\n\t\t\t\tvar sh32 Section32\n\t\t\t\tif err := binary.Read(b, bo, &sh32); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tsh := new(Section)\n\t\t\t\tsh.Name = cstring(sh32.Name[0:])\n\t\t\t\tsh.Seg = cstring(sh32.Seg[0:])\n\t\t\t\tsh.Addr = uint64(sh32.Addr)\n\t\t\t\tsh.Size = uint64(sh32.Size)\n\t\t\t\tsh.Offset = sh32.Offset\n\t\t\t\tsh.Align = sh32.Align\n\t\t\t\tsh.Reloff = sh32.Reloff\n\t\t\t\tsh.Nreloc = sh32.Nreloc\n\t\t\t\tsh.Flags = sh32.Flags\n\t\t\t\tsh.Reserved1 = sh32.Reserve1\n\t\t\t\tsh.Reserved2 = sh32.Reserve2\n\t\t\t\tif err := f.pushSection(sh, r); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase LcSegment64:\n\t\t\tvar seg64 Segment64\n\t\t\tb := bytes.NewReader(cmddat)\n\t\t\tif err := binary.Read(b, bo, &seg64); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ts = new(Segment)\n\t\t\ts.LoadCmd = cmd\n\t\t\ts.Len = siz\n\t\t\ts.Name = cstring(seg64.Name[0:])\n\t\t\ts.Addr = seg64.Addr\n\t\t\ts.Memsz = seg64.Memsz\n\t\t\ts.Offset = seg64.Offset\n\t\t\ts.Filesz = seg64.Filesz\n\t\t\ts.Maxprot = seg64.Maxprot\n\t\t\ts.Prot = seg64.Prot\n\t\t\ts.Nsect = seg64.Nsect\n\t\t\ts.Flag = seg64.Flag\n\t\t\ts.Firstsect = uint32(len(f.Sections))\n\t\t\tf.Loads[i] = s\n\t\t\tfor i := 0; i < int(s.Nsect); i++ {\n\t\t\t\tvar sh64 Section64\n\t\t\t\tif err := binary.Read(b, bo, &sh64); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tsh := new(Section)\n\t\t\t\tsh.Name = cstring(sh64.Name[0:])\n\t\t\t\tsh.Seg = cstring(sh64.Seg[0:])\n\t\t\t\tsh.Addr = sh64.Addr\n\t\t\t\tsh.Size = sh64.Size\n\t\t\t\tsh.Offset = sh64.Offset\n\t\t\t\tsh.Align = sh64.Align\n\t\t\t\tsh.Reloff = sh64.Reloff\n\t\t\t\tsh.Nreloc = sh64.Nreloc\n\t\t\t\tsh.Flags = sh64.Flags\n\t\t\t\tsh.Reserved1 = sh64.Reserve1\n\t\t\t\tsh.Reserved2 = sh64.Reserve2\n\t\t\t\tsh.Reserved3 = sh64.Reserve3\n\t\t\t\tif err := f.pushSection(sh, r); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase LcCodeSignature, LcSegmentSplitInfo, LcFunctionStarts,\n\t\t\tLcDataInCode, LcDylibCodeSignDrs:\n\t\t\tvar hdr LinkEditDataCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := new(LinkEditData)\n\n\t\t\tl.LinkEditDataCmd = hdr\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcEncryptionInfo, LcEncryptionInfo64:\n\t\t\tvar hdr EncryptionInfoCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := new(EncryptionInfo)\n\n\t\t\tl.EncryptionInfoCmd = hdr\n\t\t\tf.Loads[i] = l\n\n\t\tcase LcDyldInfo, LcDyldInfoOnly:\n\t\t\tvar hdr DyldInfoCmd\n\t\t\tb := bytes.NewReader(cmddat)\n\n\t\t\tif err := binary.Read(b, bo, &hdr); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl := new(DyldInfo)\n\n\t\t\tl.DyldInfoCmd = hdr\n\t\t\tf.Loads[i] = l\n\t\t}\n\t\tif s != nil {\n\t\t\ts.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz))\n\t\t\ts.ReaderAt = s.sr\n\t\t}\n\t\tif f.Loads[i].LoadSize(&f.FileTOC) != siz {\n\t\t\tfmt.Printf(\"Oops, actual size was %d, calculated was %d, load was %s\\n\", siz, f.Loads[i].LoadSize(&f.FileTOC), f.Loads[i].String())\n\t\t\tpanic(\"oops\")\n\t\t}\n\t}\n\treturn f, nil\n}\n\nfunc (f *File) parseSymtab(symdat, strtab []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) {\n\tbo := f.ByteOrder\n\tsymtab := make([]Symbol, hdr.Nsyms)\n\tb := bytes.NewReader(symdat)\n\tfor i := range symtab {\n\t\tvar n Nlist64\n\t\tif f.Magic == Magic64 {\n\t\t\tif err := binary.Read(b, bo, &n); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t} else {\n\t\t\tvar n32 Nlist32\n\t\t\tif err := binary.Read(b, bo, &n32); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tn.Name = n32.Name\n\t\t\tn.Type = n32.Type\n\t\t\tn.Sect = n32.Sect\n\t\t\tn.Desc = n32.Desc\n\t\t\tn.Value = uint64(n32.Value)\n\t\t}\n\t\tsym := &symtab[i]\n\t\tif n.Name >= uint32(len(strtab)) {\n\t\t\treturn nil, formatError(offset, \"invalid name in symbol table, n.Name=%d, len(strtab)=%d\", n.Name, len(strtab))\n\t\t}\n\t\tsym.Name = cstring(strtab[n.Name:])\n\t\tsym.Type = n.Type\n\t\tsym.Sect = n.Sect\n\t\tsym.Desc = n.Desc\n\t\tsym.Value = n.Value\n\t}\n\tst := new(Symtab)\n\tst.Syms = symtab\n\treturn st, nil\n}\n\ntype relocInfo struct {\n\tAddr   uint32\n\tSymnum uint32\n}\n\nfunc (f *File) pushSection(sh *Section, r io.ReaderAt) error {\n\tf.Sections = append(f.Sections, sh)\n\tsh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size))\n\tsh.ReaderAt = sh.sr\n\n\tif sh.Nreloc > 0 {\n\t\treldat := make([]byte, int(sh.Nreloc)*8)\n\t\tif _, err := r.ReadAt(reldat, int64(sh.Reloff)); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tb := bytes.NewReader(reldat)\n\n\t\tbo := f.ByteOrder\n\n\t\tsh.Relocs = make([]Reloc, sh.Nreloc)\n\t\tfor i := range sh.Relocs {\n\t\t\trel := &sh.Relocs[i]\n\n\t\t\tvar ri relocInfo\n\t\t\tif err := binary.Read(b, bo, &ri); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif ri.Addr&(1<<31) != 0 { // scattered\n\t\t\t\trel.Addr = ri.Addr & (1<<24 - 1)\n\t\t\t\trel.Type = uint8((ri.Addr >> 24) & (1<<4 - 1))\n\t\t\t\trel.Len = uint8((ri.Addr >> 28) & (1<<2 - 1))\n\t\t\t\trel.Pcrel = ri.Addr&(1<<30) != 0\n\t\t\t\trel.Value = ri.Symnum\n\t\t\t\trel.Scattered = true\n\t\t\t} else {\n\t\t\t\tswitch bo {\n\t\t\t\tcase binary.LittleEndian:\n\t\t\t\t\trel.Addr = ri.Addr\n\t\t\t\t\trel.Value = ri.Symnum & (1<<24 - 1)\n\t\t\t\t\trel.Pcrel = ri.Symnum&(1<<24) != 0\n\t\t\t\t\trel.Len = uint8((ri.Symnum >> 25) & (1<<2 - 1))\n\t\t\t\t\trel.Extern = ri.Symnum&(1<<27) != 0\n\t\t\t\t\trel.Type = uint8((ri.Symnum >> 28) & (1<<4 - 1))\n\t\t\t\tcase binary.BigEndian:\n\t\t\t\t\trel.Addr = ri.Addr\n\t\t\t\t\trel.Value = ri.Symnum >> 8\n\t\t\t\t\trel.Pcrel = ri.Symnum&(1<<7) != 0\n\t\t\t\t\trel.Len = uint8((ri.Symnum >> 5) & (1<<2 - 1))\n\t\t\t\t\trel.Extern = ri.Symnum&(1<<4) != 0\n\t\t\t\t\trel.Type = uint8(ri.Symnum & (1<<4 - 1))\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"unreachable\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc cstring(b []byte) string {\n\ti := bytes.IndexByte(b, 0)\n\tif i == -1 {\n\t\ti = len(b)\n\t}\n\treturn string(b[0:i])\n}\n\n// Segment returns the first Segment with the given name, or nil if no such segment exists.\nfunc (f *File) Segment(name string) *Segment {\n\tfor _, l := range f.Loads {\n\t\tif s, ok := l.(*Segment); ok && s.Name == name {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\n// Section returns the first section with the given name, or nil if no such\n// section exists.\nfunc (f *File) Section(name string) *Section {\n\tfor _, s := range f.Sections {\n\t\tif s.Name == name {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\n// DWARF returns the DWARF debug information for the Mach-O file.\nfunc (f *File) DWARF() (*dwarf.Data, error) {\n\tdwarfSuffix := func(s *Section) string {\n\t\tswitch {\n\t\tcase strings.HasPrefix(s.Name, \"__debug_\"):\n\t\t\treturn s.Name[8:]\n\t\tcase strings.HasPrefix(s.Name, \"__zdebug_\"):\n\t\t\treturn s.Name[9:]\n\t\tdefault:\n\t\t\treturn \"\"\n\t\t}\n\n\t}\n\tsectionData := func(s *Section) ([]byte, error) {\n\t\tb, err := s.Data()\n\t\tif err != nil && uint64(len(b)) < s.Size {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif len(b) >= 12 && string(b[:4]) == \"ZLIB\" {\n\t\t\tdlen := binary.BigEndian.Uint64(b[4:12])\n\t\t\tdbuf := make([]byte, dlen)\n\t\t\tr, err := zlib.NewReader(bytes.NewBuffer(b[12:]))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif _, err := io.ReadFull(r, dbuf); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif err := r.Close(); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tb = dbuf\n\t\t}\n\t\treturn b, nil\n\t}\n\n\t// There are many other DWARF sections, but these\n\t// are the ones the debug/dwarf package uses.\n\t// Don't bother loading others.\n\tvar dat = map[string][]byte{\"abbrev\": nil, \"info\": nil, \"str\": nil, \"line\": nil, \"ranges\": nil}\n\tfor _, s := range f.Sections {\n\t\tsuffix := dwarfSuffix(s)\n\t\tif suffix == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif _, ok := dat[suffix]; !ok {\n\t\t\tcontinue\n\t\t}\n\t\tb, err := sectionData(s)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdat[suffix] = b\n\t}\n\n\td, err := dwarf.New(dat[\"abbrev\"], nil, nil, dat[\"info\"], dat[\"line\"], nil, dat[\"ranges\"], dat[\"str\"])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Look for DWARF4 .debug_types sections.\n\tfor i, s := range f.Sections {\n\t\tsuffix := dwarfSuffix(s)\n\t\tif suffix != \"types\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tb, err := sectionData(s)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\terr = d.AddTypes(fmt.Sprintf(\"types-%d\", i), b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn d, nil\n}\n\n// ImportedSymbols returns the names of all symbols\n// referred to by the binary f that are expected to be\n// satisfied by other libraries at dynamic load time.\nfunc (f *File) ImportedSymbols() ([]string, error) {\n\tif f.Dysymtab == nil || f.Symtab == nil {\n\t\treturn nil, formatError(0, \"missing symbol table, f.Dsymtab=%v, f.Symtab=%v\", f.Dysymtab, f.Symtab)\n\t}\n\n\tst := f.Symtab\n\tdt := f.Dysymtab\n\tvar all []string\n\tfor _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {\n\t\tall = append(all, s.Name)\n\t}\n\treturn all, nil\n}\n\n// ImportedLibraries returns the paths of all libraries\n// referred to by the binary f that are expected to be\n// linked with the binary at dynamic link time.\nfunc (f *File) ImportedLibraries() ([]string, error) {\n\tvar all []string\n\tfor _, l := range f.Loads {\n\t\tif lib, ok := l.(*Dylib); ok {\n\t\t\tall = append(all, lib.Name)\n\t\t}\n\t}\n\treturn all, nil\n}\n\nfunc RoundUp(x, align uint64) uint64 {\n\treturn uint64((x + align - 1) & -align)\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/file_test.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage macho\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\ntype fileTest struct {\n\tfile        string\n\thdr         FileHeader\n\tloads       []any\n\tsections    []*SectionHeader\n\trelocations map[string][]Reloc\n}\n\nvar fileTests = []fileTest{\n\t{\n\t\t\"testdata/gcc-386-darwin-exec\",\n\t\tFileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},\n\t\t[]any{\n\t\t\t&SegmentHeader{LcSegment, 0x38, \"__PAGEZERO\", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0},\n\t\t\t&SegmentHeader{LcSegment, 0xc0, \"__TEXT\", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0, 0},\n\t\t\t&SegmentHeader{LcSegment, 0xc0, \"__DATA\", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0, 2},\n\t\t\t&SegmentHeader{LcSegment, 0x7c, \"__IMPORT\", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0, 4},\n\t\t\t&SegmentHeader{LcSegment, 0x38, \"__LINKEDIT\", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0, 5},\n\t\t\tnil, // LC_SYMTAB\n\t\t\tnil, // LC_DYSYMTAB\n\t\t\tnil, // LC_LOAD_DYLINKER\n\t\t\tnil, // LC_UUID\n\t\t\tnil, // LC_UNIXTHREAD\n\t\t\t&Dylib{DylibCmd{}, \"/usr/lib/libgcc_s.1.dylib\", 0x2, 0x10000, 0x10000},\n\t\t\t&Dylib{DylibCmd{}, \"/usr/lib/libSystem.B.dylib\", 0x2, 0x6f0104, 0x10000},\n\t\t},\n\t\t[]*SectionHeader{\n\t\t\t{\"__text\", \"__TEXT\", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400, 0, 0, 0},\n\t\t\t{\"__cstring\", \"__TEXT\", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2, 0, 0, 0},\n\t\t\t{\"__data\", \"__DATA\", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__dyld\", \"__DATA\", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__jump_table\", \"__IMPORT\", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008, 0, 5, 0},\n\t\t},\n\t\tnil,\n\t},\n\t{\n\t\t\"testdata/gcc-amd64-darwin-exec\",\n\t\tFileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},\n\t\t[]any{\n\t\t\t&SegmentHeader{LcSegment64, 0x48, \"__PAGEZERO\", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0},\n\t\t\t&SegmentHeader{LcSegment64, 0x1d8, \"__TEXT\", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0, 0},\n\t\t\t&SegmentHeader{LcSegment64, 0x138, \"__DATA\", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0, 5},\n\t\t\t&SegmentHeader{LcSegment64, 0x48, \"__LINKEDIT\", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0, 8},\n\t\t\tnil, // LC_SYMTAB\n\t\t\tnil, // LC_DYSYMTAB\n\t\t\tnil, // LC_LOAD_DYLINKER\n\t\t\tnil, // LC_UUID\n\t\t\tnil, // LC_UNIXTHREAD\n\t\t\t&Dylib{DylibCmd{}, \"/usr/lib/libgcc_s.1.dylib\", 0x2, 0x10000, 0x10000},\n\t\t\t&Dylib{DylibCmd{}, \"/usr/lib/libSystem.B.dylib\", 0x2, 0x6f0104, 0x10000},\n\t\t},\n\t\t[]*SectionHeader{\n\t\t\t{\"__text\", \"__TEXT\", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400, 0, 0, 0},\n\t\t\t{\"__symbol_stub1\", \"__TEXT\", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408, 0, 6, 0},\n\t\t\t{\"__stub_helper\", \"__TEXT\", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__cstring\", \"__TEXT\", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2, 0, 0, 0},\n\t\t\t{\"__eh_frame\", \"__TEXT\", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b, 0, 0, 0},\n\t\t\t{\"__data\", \"__DATA\", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__dyld\", \"__DATA\", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__la_symbol_ptr\", \"__DATA\", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7, 2, 0, 0},\n\t\t},\n\t\tnil,\n\t},\n\t{\n\t\t\"testdata/gcc-amd64-darwin-exec-debug\",\n\t\tFileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},\n\t\t[]any{\n\t\t\tnil, // LC_UUID\n\t\t\t&SegmentHeader{LcSegment64, 0x1d8, \"__TEXT\", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0, 0},\n\t\t\t&SegmentHeader{LcSegment64, 0x138, \"__DATA\", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0, 5},\n\t\t\t&SegmentHeader{LcSegment64, 0x278, \"__DWARF\", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0, 8},\n\t\t},\n\t\t[]*SectionHeader{\n\t\t\t{\"__text\", \"__TEXT\", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400, 0, 0, 0},\n\t\t\t{\"__symbol_stub1\", \"__TEXT\", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408, 0, 6, 0},\n\t\t\t{\"__stub_helper\", \"__TEXT\", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__cstring\", \"__TEXT\", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0, 0, 0},\n\t\t\t{\"__eh_frame\", \"__TEXT\", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b, 0, 0, 0},\n\t\t\t{\"__data\", \"__DATA\", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__dyld\", \"__DATA\", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__la_symbol_ptr\", \"__DATA\", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7, 2, 0, 0},\n\t\t\t{\"__debug_abbrev\", \"__DWARF\", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_aranges\", \"__DWARF\", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_frame\", \"__DWARF\", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_info\", \"__DWARF\", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_line\", \"__DWARF\", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_pubnames\", \"__DWARF\", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t\t{\"__debug_str\", \"__DWARF\", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0, 0, 0, 0},\n\t\t},\n\t\tnil,\n\t},\n\t{\n\t\t\"testdata/clang-386-darwin-exec-with-rpath\",\n\t\tFileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0x10, 0x42c, 0x1200085},\n\t\t[]any{\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_DYLD_INFO_ONLY\n\t\t\tnil, // LC_SYMTAB\n\t\t\tnil, // LC_DYSYMTAB\n\t\t\tnil, // LC_LOAD_DYLINKER\n\t\t\tnil, // LC_UUID\n\t\t\tnil, // LC_VERSION_MIN_MACOSX\n\t\t\tnil, // LC_SOURCE_VERSION\n\t\t\tnil, // LC_MAIN\n\t\t\tnil, // LC_LOAD_DYLIB\n\t\t\t&Rpath{LcRpath, \"/my/rpath\"},\n\t\t\tnil, // LC_FUNCTION_STARTS\n\t\t\tnil, // LC_DATA_IN_CODE\n\t\t},\n\t\tnil,\n\t\tnil,\n\t},\n\t{\n\t\t\"testdata/clang-amd64-darwin-exec-with-rpath\",\n\t\tFileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0x10, 0x4c8, 0x200085},\n\t\t[]any{\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_SEGMENT\n\t\t\tnil, // LC_DYLD_INFO_ONLY\n\t\t\tnil, // LC_SYMTAB\n\t\t\tnil, // LC_DYSYMTAB\n\t\t\tnil, // LC_LOAD_DYLINKER\n\t\t\tnil, // LC_UUID\n\t\t\tnil, // LC_VERSION_MIN_MACOSX\n\t\t\tnil, // LC_SOURCE_VERSION\n\t\t\tnil, // LC_MAIN\n\t\t\tnil, // LC_LOAD_DYLIB\n\t\t\t&Rpath{LcRpath, \"/my/rpath\"},\n\t\t\tnil, // LC_FUNCTION_STARTS\n\t\t\tnil, // LC_DATA_IN_CODE\n\t\t},\n\t\tnil,\n\t\tnil,\n\t},\n\t{\n\t\t\"testdata/clang-386-darwin.obj\",\n\t\tFileHeader{0xfeedface, Cpu386, 0x3, 0x1, 0x4, 0x138, 0x2000},\n\t\tnil,\n\t\tnil,\n\t\tmap[string][]Reloc{\n\t\t\t\"__text\": {\n\t\t\t\t{\n\t\t\t\t\tAddr:      0x1d,\n\t\t\t\t\tType:      uint8(GENERIC_RELOC_VANILLA),\n\t\t\t\t\tLen:       2,\n\t\t\t\t\tPcrel:     true,\n\t\t\t\t\tExtern:    true,\n\t\t\t\t\tValue:     1,\n\t\t\t\t\tScattered: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tAddr:      0xe,\n\t\t\t\t\tType:      uint8(GENERIC_RELOC_LOCAL_SECTDIFF),\n\t\t\t\t\tLen:       2,\n\t\t\t\t\tPcrel:     false,\n\t\t\t\t\tValue:     0x2d,\n\t\t\t\t\tScattered: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tAddr:      0x0,\n\t\t\t\t\tType:      uint8(GENERIC_RELOC_PAIR),\n\t\t\t\t\tLen:       2,\n\t\t\t\t\tPcrel:     false,\n\t\t\t\t\tValue:     0xb,\n\t\t\t\t\tScattered: true,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\t\"testdata/clang-amd64-darwin.obj\",\n\t\tFileHeader{0xfeedfacf, CpuAmd64, 0x3, 0x1, 0x4, 0x200, 0x2000},\n\t\tnil,\n\t\tnil,\n\t\tmap[string][]Reloc{\n\t\t\t\"__text\": {\n\t\t\t\t{\n\t\t\t\t\tAddr:   0x19,\n\t\t\t\t\tType:   uint8(X86_64_RELOC_BRANCH),\n\t\t\t\t\tLen:    2,\n\t\t\t\t\tPcrel:  true,\n\t\t\t\t\tExtern: true,\n\t\t\t\t\tValue:  1,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tAddr:   0xb,\n\t\t\t\t\tType:   uint8(X86_64_RELOC_SIGNED),\n\t\t\t\t\tLen:    2,\n\t\t\t\t\tPcrel:  true,\n\t\t\t\t\tExtern: false,\n\t\t\t\t\tValue:  2,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"__compact_unwind\": {\n\t\t\t\t{\n\t\t\t\t\tAddr:   0x0,\n\t\t\t\t\tType:   uint8(X86_64_RELOC_UNSIGNED),\n\t\t\t\t\tLen:    3,\n\t\t\t\t\tPcrel:  false,\n\t\t\t\t\tExtern: false,\n\t\t\t\t\tValue:  1,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n\nfunc TestOpen(t *testing.T) {\n\tfor i := range fileTests {\n\t\ttt := &fileTests[i]\n\n\t\tf, err := Open(tt.file)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\t\tif !reflect.DeepEqual(f.FileHeader, tt.hdr) {\n\t\t\tt.Errorf(\"open %s:\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, f.FileHeader, tt.hdr)\n\t\t\tcontinue\n\t\t}\n\t\t// for i, l := range f.Loads {\n\t\t// \tif len(l.Raw()) < 8 {\n\t\t// \t\tt.Errorf(\"open %s, command %d:\\n\\tload command %T don't have enough data\\n\", tt.file, i, l)\n\t\t// \t}\n\t\t// }\n\t\tif tt.loads != nil {\n\t\t\tfor i, l := range f.Loads {\n\t\t\t\tif i >= len(tt.loads) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\twant := tt.loads[i]\n\t\t\t\tif want == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tswitch l := l.(type) {\n\t\t\t\tcase *Segment:\n\t\t\t\t\thave := &l.SegmentHeader\n\t\t\t\t\tif !reflect.DeepEqual(have, want) {\n\t\t\t\t\t\tt.Errorf(\"open %s, command %d:\\n\\thave %s\\n\\twant %s\\n\", tt.file, i, have.String(), want.(*SegmentHeader).String())\n\t\t\t\t\t}\n\t\t\t\tcase *Dylib:\n\t\t\t\t\t// have := l\n\t\t\t\t\t// have.LoadBytes = nil\n\t\t\t\t\t// if !reflect.DeepEqual(have, want) {\n\t\t\t\t\t// \tt.Errorf(\"open %s, command %d:\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, i, have, want)\n\t\t\t\t\t// }\n\t\t\t\tcase *Rpath:\n\t\t\t\t\t// have := l\n\t\t\t\t\t// have.LoadBytes = nil\n\t\t\t\t\t// if !reflect.DeepEqual(have, want) {\n\t\t\t\t\t// \tt.Errorf(\"open %s, command %d:\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, i, have, want)\n\t\t\t\t\t// }\n\t\t\t\tdefault:\n\t\t\t\t\tt.Errorf(\"open %s, command %d: unknown load command\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, i, l, want)\n\t\t\t\t}\n\t\t\t}\n\t\t\ttn := len(tt.loads)\n\t\t\tfn := len(f.Loads)\n\t\t\tif tn != fn {\n\t\t\t\tt.Errorf(\"open %s: len(Loads) = %d, want %d\", tt.file, fn, tn)\n\t\t\t}\n\t\t}\n\n\t\tif tt.sections != nil {\n\t\t\tfor i, sh := range f.Sections {\n\t\t\t\tif i >= len(tt.sections) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\thave := &sh.SectionHeader\n\t\t\t\twant := tt.sections[i]\n\t\t\t\tif !reflect.DeepEqual(have, want) {\n\t\t\t\t\tt.Errorf(\"open %s, section %d:\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, i, have, want)\n\t\t\t\t}\n\t\t\t}\n\t\t\ttn := len(tt.sections)\n\t\t\tfn := len(f.Sections)\n\t\t\tif tn != fn {\n\t\t\t\tt.Errorf(\"open %s: len(Sections) = %d, want %d\", tt.file, fn, tn)\n\t\t\t}\n\t\t}\n\n\t\tif tt.relocations != nil {\n\t\t\tfor i, sh := range f.Sections {\n\t\t\t\thave := sh.Relocs\n\t\t\t\twant := tt.relocations[sh.Name]\n\t\t\t\tif !reflect.DeepEqual(have, want) {\n\t\t\t\t\tt.Errorf(\"open %s, relocations in section %d (%s):\\n\\thave %#v\\n\\twant %#v\\n\", tt.file, i, sh.Name, have, want)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestOpenFailure(t *testing.T) {\n\tfilename := \"file.go\"    // not a Mach-O file\n\t_, err := Open(filename) // don't crash\n\tif err == nil {\n\t\tt.Errorf(\"open %s: succeeded unexpectedly\", filename)\n\t}\n}\n\nfunc TestOpenFat(t *testing.T) {\n\tff, err := OpenFat(\"testdata/fat-gcc-386-amd64-darwin-exec\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif ff.Magic != MagicFat {\n\t\tt.Errorf(\"OpenFat: got magic number %#x, want %#x\", ff.Magic, MagicFat)\n\t}\n\tif len(ff.Arches) != 2 {\n\t\tt.Errorf(\"OpenFat: got %d architectures, want 2\", len(ff.Arches))\n\t}\n\n\tfor i := range ff.Arches {\n\t\tarch := &ff.Arches[i]\n\t\tftArch := &fileTests[i]\n\n\t\tif arch.Cpu != ftArch.hdr.Cpu || arch.SubCpu != ftArch.hdr.SubCpu {\n\t\t\tt.Errorf(\"OpenFat: architecture #%d got cpu=%#x subtype=%#x, expected cpu=%#x, subtype=%#x\", i, arch.Cpu, arch.SubCpu, ftArch.hdr.Cpu, ftArch.hdr.SubCpu)\n\t\t}\n\n\t\tif !reflect.DeepEqual(arch.FileHeader, ftArch.hdr) {\n\t\t\tt.Errorf(\"OpenFat header:\\n\\tgot %#v\\n\\twant %#v\\n\", arch.FileHeader, ftArch.hdr)\n\t\t}\n\t}\n}\n\nfunc TestOpenFatFailure(t *testing.T) {\n\tfilename := \"file.go\" // not a Mach-O file\n\tif _, err := OpenFat(filename); err == nil {\n\t\tt.Errorf(\"OpenFat %s: succeeded unexpectedly\", filename)\n\t}\n\n\tfilename = \"testdata/gcc-386-darwin-exec\" // not a fat Mach-O\n\tff, err := OpenFat(filename)\n\tif err == nil {\n\t\tt.Errorf(\"OpenFat %s: expected error, got nil\", filename)\n\t}\n\tif _, ok := err.(*FormatError); !ok {\n\t\tt.Errorf(\"OpenFat %s: expected FormatError, got %v\", filename, err)\n\t}\n\n\tferr := err.(*FormatError)\n\tif !strings.Contains(ferr.String(), \"not a fat\") {\n\t\tt.Errorf(\"OpenFat %s: expected error containing 'not a fat', got %s\", filename, ferr.String())\n\t}\n\n\tif ff != nil {\n\t\tt.Errorf(\"OpenFat %s: got %v, want nil\", filename, ff)\n\t}\n}\n\nfunc TestRelocTypeString(t *testing.T) {\n\tif X86_64_RELOC_BRANCH.String() != \"X86_64_RELOC_BRANCH\" {\n\t\tt.Errorf(\"got %v, want %v\", X86_64_RELOC_BRANCH.String(), \"X86_64_RELOC_BRANCH\")\n\t}\n\tif X86_64_RELOC_BRANCH.GoString() != \"macho.X86_64_RELOC_BRANCH\" {\n\t\tt.Errorf(\"got %v, want %v\", X86_64_RELOC_BRANCH.GoString(), \"macho.X86_64_RELOC_BRANCH\")\n\t}\n}\n\nfunc TestTypeString(t *testing.T) {\n\tif MhExecute.String() != \"Exec\" {\n\t\tt.Errorf(\"got %v, want %v\", MhExecute.String(), \"Exec\")\n\t}\n\tif MhExecute.GoString() != \"macho.Exec\" {\n\t\tt.Errorf(\"got %v, want %v\", MhExecute.GoString(), \"macho.Exec\")\n\t}\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/macho.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Mach-O header data structures\n// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html\n\npackage macho\n\nimport (\n\t\"encoding/binary\"\n\t\"strconv\"\n)\n\n// A FileHeader represents a Mach-O file header.\ntype FileHeader struct {\n\tMagic        uint32\n\tCpu          Cpu\n\tSubCpu       uint32\n\tType         HdrType\n\tNCommands    uint32 // number of load commands\n\tSizeCommands uint32 // size of all the load commands, not including this header.\n\tFlags        HdrFlags\n}\n\nfunc (h *FileHeader) Put(b []byte, o binary.ByteOrder) int {\n\to.PutUint32(b[0:], h.Magic)\n\to.PutUint32(b[4:], uint32(h.Cpu))\n\to.PutUint32(b[8:], h.SubCpu)\n\to.PutUint32(b[12:], uint32(h.Type))\n\to.PutUint32(b[16:], h.NCommands)\n\to.PutUint32(b[20:], h.SizeCommands)\n\to.PutUint32(b[24:], uint32(h.Flags))\n\tif h.Magic == Magic32 {\n\t\treturn 28\n\t}\n\to.PutUint32(b[28:], 0)\n\treturn 32\n}\n\nconst (\n\tfileHeaderSize32 = 7 * 4\n\tfileHeaderSize64 = 8 * 4\n)\n\nconst (\n\tMagic32  uint32 = 0xfeedface\n\tMagic64  uint32 = 0xfeedfacf\n\tMagicFat uint32 = 0xcafebabe\n)\n\ntype HdrFlags uint32\ntype SegFlags uint32\ntype SecFlags uint32\n\n// A HdrType is the Mach-O file type, e.g. an object file, executable, or dynamic library.\ntype HdrType uint32\n\nconst ( // SNAKE_CASE to CamelCase translation from C names\n\tMhObject  HdrType = 1\n\tMhExecute HdrType = 2\n\tMhCore    HdrType = 4\n\tMhDylib   HdrType = 6\n\tMhBundle  HdrType = 8\n\tMhDsym    HdrType = 0xa\n)\n\nvar typeStrings = []intName{\n\t{uint32(MhObject), \"Obj\"},\n\t{uint32(MhExecute), \"Exec\"},\n\t{uint32(MhDylib), \"Dylib\"},\n\t{uint32(MhBundle), \"Bundle\"},\n\t{uint32(MhDsym), \"Dsym\"},\n}\n\nfunc (t HdrType) String() string   { return stringName(uint32(t), typeStrings, false) }\nfunc (t HdrType) GoString() string { return stringName(uint32(t), typeStrings, true) }\n\n// A Cpu is a Mach-O cpu type.\ntype Cpu uint32\n\nconst cpuArch64 = 0x01000000\n\nconst (\n\tCpu386   Cpu = 7\n\tCpuAmd64 Cpu = Cpu386 | cpuArch64\n\tCpuArm   Cpu = 12\n\tCpuArm64 Cpu = CpuArm | cpuArch64\n\tCpuPpc   Cpu = 18\n\tCpuPpc64 Cpu = CpuPpc | cpuArch64\n)\n\nvar cpuStrings = []intName{\n\t{uint32(Cpu386), \"Cpu386\"},\n\t{uint32(CpuAmd64), \"CpuAmd64\"},\n\t{uint32(CpuArm), \"CpuArm\"},\n\t{uint32(CpuArm64), \"CpuArm64\"},\n\t{uint32(CpuPpc), \"CpuPpc\"},\n\t{uint32(CpuPpc64), \"CpuPpc64\"},\n}\n\nfunc (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }\nfunc (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }\n\n// A LoadCmd is a Mach-O load command.\ntype LoadCmd uint32\n\nfunc (c LoadCmd) Command() LoadCmd { return c }\n\nconst ( // SNAKE_CASE to CamelCase translation from C names\n\t// Note 3 and 8 are obsolete\n\tLcSegment            LoadCmd = 0x1\n\tLcSymtab             LoadCmd = 0x2\n\tLcThread             LoadCmd = 0x4\n\tLcUnixthread         LoadCmd = 0x5 // thread+stack\n\tLcDysymtab           LoadCmd = 0xb\n\tLcDylib              LoadCmd = 0xc // load dylib command\n\tLcIdDylib            LoadCmd = 0xd // dynamically linked shared lib ident\n\tLcLoadDylinker       LoadCmd = 0xe // load a dynamic linker\n\tLcIdDylinker         LoadCmd = 0xf // id dylinker command (not load dylinker command)\n\tLcSegment64          LoadCmd = 0x19\n\tLcUuid               LoadCmd = 0x1b\n\tLcCodeSignature      LoadCmd = 0x1d\n\tLcSegmentSplitInfo   LoadCmd = 0x1e\n\tLcRpath              LoadCmd = 0x8000001c\n\tLcEncryptionInfo     LoadCmd = 0x21\n\tLcDyldInfo           LoadCmd = 0x22\n\tLcDyldInfoOnly       LoadCmd = 0x80000022\n\tLcVersionMinMacosx   LoadCmd = 0x24\n\tLcVersionMinIphoneos LoadCmd = 0x25\n\tLcFunctionStarts     LoadCmd = 0x26\n\tLcDyldEnvironment    LoadCmd = 0x27\n\tLcMain               LoadCmd = 0x80000028 // replacement for UnixThread\n\tLcDataInCode         LoadCmd = 0x29       // There are non-instructions in text\n\tLcSourceVersion      LoadCmd = 0x2a       // Source version used to build binary\n\tLcDylibCodeSignDrs   LoadCmd = 0x2b\n\tLcEncryptionInfo64   LoadCmd = 0x2c\n\tLcVersionMinTvos     LoadCmd = 0x2f\n\tLcVersionMinWatchos  LoadCmd = 0x30\n)\n\nvar cmdStrings = []intName{\n\t{uint32(LcSegment), \"LoadCmdSegment\"},\n\t{uint32(LcThread), \"LoadCmdThread\"},\n\t{uint32(LcUnixthread), \"LoadCmdUnixThread\"},\n\t{uint32(LcDylib), \"LoadCmdDylib\"},\n\t{uint32(LcIdDylib), \"LoadCmdIdDylib\"},\n\t{uint32(LcLoadDylinker), \"LoadCmdLoadDylinker\"},\n\t{uint32(LcIdDylinker), \"LoadCmdIdDylinker\"},\n\t{uint32(LcSegment64), \"LoadCmdSegment64\"},\n\t{uint32(LcUuid), \"LoadCmdUuid\"},\n\t{uint32(LcRpath), \"LoadCmdRpath\"},\n\t{uint32(LcDyldEnvironment), \"LoadCmdDyldEnv\"},\n\t{uint32(LcMain), \"LoadCmdMain\"},\n\t{uint32(LcDataInCode), \"LoadCmdDataInCode\"},\n\t{uint32(LcSourceVersion), \"LoadCmdSourceVersion\"},\n\t{uint32(LcDyldInfo), \"LoadCmdDyldInfo\"},\n\t{uint32(LcDyldInfoOnly), \"LoadCmdDyldInfoOnly\"},\n\t{uint32(LcVersionMinMacosx), \"LoadCmdMinOsx\"},\n\t{uint32(LcFunctionStarts), \"LoadCmdFunctionStarts\"},\n}\n\nfunc (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }\nfunc (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }\n\ntype (\n\t// A Segment32 is a 32-bit Mach-O segment load command.\n\tSegment32 struct {\n\t\tLoadCmd\n\t\tLen     uint32\n\t\tName    [16]byte\n\t\tAddr    uint32\n\t\tMemsz   uint32\n\t\tOffset  uint32\n\t\tFilesz  uint32\n\t\tMaxprot uint32\n\t\tProt    uint32\n\t\tNsect   uint32\n\t\tFlag    SegFlags\n\t}\n\n\t// A Segment64 is a 64-bit Mach-O segment load command.\n\tSegment64 struct {\n\t\tLoadCmd\n\t\tLen     uint32\n\t\tName    [16]byte\n\t\tAddr    uint64\n\t\tMemsz   uint64\n\t\tOffset  uint64\n\t\tFilesz  uint64\n\t\tMaxprot uint32\n\t\tProt    uint32\n\t\tNsect   uint32\n\t\tFlag    SegFlags\n\t}\n\n\t// A SymtabCmd is a Mach-O symbol table command.\n\tSymtabCmd struct {\n\t\tLoadCmd\n\t\tLen     uint32\n\t\tSymoff  uint32\n\t\tNsyms   uint32\n\t\tStroff  uint32\n\t\tStrsize uint32\n\t}\n\n\t// A DysymtabCmd is a Mach-O dynamic symbol table command.\n\tDysymtabCmd struct {\n\t\tLoadCmd\n\t\tLen            uint32\n\t\tIlocalsym      uint32\n\t\tNlocalsym      uint32\n\t\tIextdefsym     uint32\n\t\tNextdefsym     uint32\n\t\tIundefsym      uint32\n\t\tNundefsym      uint32\n\t\tTocoffset      uint32\n\t\tNtoc           uint32\n\t\tModtaboff      uint32\n\t\tNmodtab        uint32\n\t\tExtrefsymoff   uint32\n\t\tNextrefsyms    uint32\n\t\tIndirectsymoff uint32\n\t\tNindirectsyms  uint32\n\t\tExtreloff      uint32\n\t\tNextrel        uint32\n\t\tLocreloff      uint32\n\t\tNlocrel        uint32\n\t}\n\n\t// A DylibCmd is a Mach-O load dynamic library command.\n\tDylibCmd struct {\n\t\tLoadCmd\n\t\tLen            uint32\n\t\tName           uint32\n\t\tTime           uint32\n\t\tCurrentVersion uint32\n\t\tCompatVersion  uint32\n\t}\n\n\t// A DylinkerCmd is a Mach-O load dynamic linker or environment command.\n\tDylinkerCmd struct {\n\t\tLoadCmd\n\t\tLen  uint32\n\t\tName uint32\n\t}\n\n\t// A RpathCmd is a Mach-O rpath command.\n\tRpathCmd struct {\n\t\tLoadCmd\n\t\tLen  uint32\n\t\tPath uint32\n\t}\n\n\t// A Thread is a Mach-O thread state command.\n\tThread struct {\n\t\tLoadCmd\n\t\tLen  uint32\n\t\tType uint32\n\t\tData []uint32\n\t}\n\n\t// LC_DYLD_INFO, LC_DYLD_INFO_ONLY\n\tDyldInfoCmd struct {\n\t\tLoadCmd\n\t\tLen                      uint32\n\t\tRebaseOff, RebaseLen     uint32 // file offset and length; data contains segment indices\n\t\tBindOff, BindLen         uint32 // file offset and length; data contains segment indices\n\t\tWeakBindOff, WeakBindLen uint32 // file offset and length\n\t\tLazyBindOff, LazyBindLen uint32 // file offset and length\n\t\tExportOff, ExportLen     uint32 // file offset and length\n\t}\n\n\t// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS\n\tLinkEditDataCmd struct {\n\t\tLoadCmd\n\t\tLen              uint32\n\t\tDataOff, DataLen uint32 // file offset and length\n\t}\n\n\t// LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64\n\tEncryptionInfoCmd struct {\n\t\tLoadCmd\n\t\tLen                uint32\n\t\tCryptOff, CryptLen uint32 // file offset and length\n\t\tCryptId            uint32\n\t}\n\n\tUuidCmd struct {\n\t\tLoadCmd\n\t\tLen uint32\n\t\tId  [16]byte\n\t}\n\n\t// TODO Commands below not fully supported yet.\n\n\tEntryPointCmd struct {\n\t\tLoadCmd\n\t\tLen       uint32\n\t\tEntryOff  uint64 // file offset\n\t\tStackSize uint64 // if not zero, initial stack size\n\t}\n\n\tNoteCmd struct {\n\t\tLoadCmd\n\t\tLen            uint32\n\t\tName           [16]byte\n\t\tOffset, Filesz uint64 // file offset and length\n\t}\n)\n\nconst (\n\tFlagNoUndefs              HdrFlags = 0x1\n\tFlagIncrLink              HdrFlags = 0x2\n\tFlagDyldLink              HdrFlags = 0x4\n\tFlagBindAtLoad            HdrFlags = 0x8\n\tFlagPrebound              HdrFlags = 0x10\n\tFlagSplitSegs             HdrFlags = 0x20\n\tFlagLazyInit              HdrFlags = 0x40\n\tFlagTwoLevel              HdrFlags = 0x80\n\tFlagForceFlat             HdrFlags = 0x100\n\tFlagNoMultiDefs           HdrFlags = 0x200\n\tFlagNoFixPrebinding       HdrFlags = 0x400\n\tFlagPrebindable           HdrFlags = 0x800\n\tFlagAllModsBound          HdrFlags = 0x1000\n\tFlagSubsectionsViaSymbols HdrFlags = 0x2000\n\tFlagCanonical             HdrFlags = 0x4000\n\tFlagWeakDefines           HdrFlags = 0x8000\n\tFlagBindsToWeak           HdrFlags = 0x10000\n\tFlagAllowStackExecution   HdrFlags = 0x20000\n\tFlagRootSafe              HdrFlags = 0x40000\n\tFlagSetuidSafe            HdrFlags = 0x80000\n\tFlagNoReexportedDylibs    HdrFlags = 0x100000\n\tFlagPIE                   HdrFlags = 0x200000\n\tFlagDeadStrippableDylib   HdrFlags = 0x400000\n\tFlagHasTLVDescriptors     HdrFlags = 0x800000\n\tFlagNoHeapExecution       HdrFlags = 0x1000000\n\tFlagAppExtensionSafe      HdrFlags = 0x2000000\n)\n\n// A Section32 is a 32-bit Mach-O section header.\ntype Section32 struct {\n\tName     [16]byte\n\tSeg      [16]byte\n\tAddr     uint32\n\tSize     uint32\n\tOffset   uint32\n\tAlign    uint32\n\tReloff   uint32\n\tNreloc   uint32\n\tFlags    SecFlags\n\tReserve1 uint32\n\tReserve2 uint32\n}\n\n// A Section64 is a 64-bit Mach-O section header.\ntype Section64 struct {\n\tName     [16]byte\n\tSeg      [16]byte\n\tAddr     uint64\n\tSize     uint64\n\tOffset   uint32\n\tAlign    uint32\n\tReloff   uint32\n\tNreloc   uint32\n\tFlags    SecFlags\n\tReserve1 uint32\n\tReserve2 uint32\n\tReserve3 uint32\n}\n\n// An Nlist32 is a Mach-O 32-bit symbol table entry.\ntype Nlist32 struct {\n\tName  uint32\n\tType  uint8\n\tSect  uint8\n\tDesc  uint16\n\tValue uint32\n}\n\n// An Nlist64 is a Mach-O 64-bit symbol table entry.\ntype Nlist64 struct {\n\tName  uint32\n\tType  uint8\n\tSect  uint8\n\tDesc  uint16\n\tValue uint64\n}\n\nfunc (n *Nlist64) Put64(b []byte, o binary.ByteOrder) uint32 {\n\to.PutUint32(b[0:], n.Name)\n\tb[4] = byte(n.Type)\n\tb[5] = byte(n.Sect)\n\to.PutUint16(b[6:], n.Desc)\n\to.PutUint64(b[8:], n.Value)\n\treturn 8 + 8\n}\n\nfunc (n *Nlist64) Put32(b []byte, o binary.ByteOrder) uint32 {\n\to.PutUint32(b[0:], n.Name)\n\tb[4] = byte(n.Type)\n\tb[5] = byte(n.Sect)\n\to.PutUint16(b[6:], n.Desc)\n\to.PutUint32(b[8:], uint32(n.Value))\n\treturn 8 + 4\n}\n\n// Regs386 is the Mach-O 386 register structure.\ntype Regs386 struct {\n\tAX    uint32\n\tBX    uint32\n\tCX    uint32\n\tDX    uint32\n\tDI    uint32\n\tSI    uint32\n\tBP    uint32\n\tSP    uint32\n\tSS    uint32\n\tFLAGS uint32\n\tIP    uint32\n\tCS    uint32\n\tDS    uint32\n\tES    uint32\n\tFS    uint32\n\tGS    uint32\n}\n\n// RegsAMD64 is the Mach-O AMD64 register structure.\ntype RegsAMD64 struct {\n\tAX    uint64\n\tBX    uint64\n\tCX    uint64\n\tDX    uint64\n\tDI    uint64\n\tSI    uint64\n\tBP    uint64\n\tSP    uint64\n\tR8    uint64\n\tR9    uint64\n\tR10   uint64\n\tR11   uint64\n\tR12   uint64\n\tR13   uint64\n\tR14   uint64\n\tR15   uint64\n\tIP    uint64\n\tFLAGS uint64\n\tCS    uint64\n\tFS    uint64\n\tGS    uint64\n}\n\ntype intName struct {\n\ti uint32\n\ts string\n}\n\nfunc stringName(i uint32, names []intName, goSyntax bool) string {\n\tfor _, n := range names {\n\t\tif n.i == i {\n\t\t\tif goSyntax {\n\t\t\t\treturn \"macho.\" + n.s\n\t\t\t}\n\t\t\treturn n.s\n\t\t}\n\t}\n\treturn \"0x\" + strconv.FormatUint(uint64(i), 16)\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/reloctype.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage macho\n\n//go:generate stringer -type=RelocTypeGeneric,RelocTypeX86_64,RelocTypeARM,RelocTypeARM64 -output reloctype_string.go\n\ntype RelocTypeGeneric int\n\nconst (\n\tGENERIC_RELOC_VANILLA        RelocTypeGeneric = 0\n\tGENERIC_RELOC_PAIR           RelocTypeGeneric = 1\n\tGENERIC_RELOC_SECTDIFF       RelocTypeGeneric = 2\n\tGENERIC_RELOC_PB_LA_PTR      RelocTypeGeneric = 3\n\tGENERIC_RELOC_LOCAL_SECTDIFF RelocTypeGeneric = 4\n\tGENERIC_RELOC_TLV            RelocTypeGeneric = 5\n)\n\nfunc (r RelocTypeGeneric) GoString() string { return \"macho.\" + r.String() }\n\ntype RelocTypeX86_64 int\n\nconst (\n\tX86_64_RELOC_UNSIGNED   RelocTypeX86_64 = 0\n\tX86_64_RELOC_SIGNED     RelocTypeX86_64 = 1\n\tX86_64_RELOC_BRANCH     RelocTypeX86_64 = 2\n\tX86_64_RELOC_GOT_LOAD   RelocTypeX86_64 = 3\n\tX86_64_RELOC_GOT        RelocTypeX86_64 = 4\n\tX86_64_RELOC_SUBTRACTOR RelocTypeX86_64 = 5\n\tX86_64_RELOC_SIGNED_1   RelocTypeX86_64 = 6\n\tX86_64_RELOC_SIGNED_2   RelocTypeX86_64 = 7\n\tX86_64_RELOC_SIGNED_4   RelocTypeX86_64 = 8\n\tX86_64_RELOC_TLV        RelocTypeX86_64 = 9\n)\n\nfunc (r RelocTypeX86_64) GoString() string { return \"macho.\" + r.String() }\n\ntype RelocTypeARM int\n\nconst (\n\tARM_RELOC_VANILLA        RelocTypeARM = 0\n\tARM_RELOC_PAIR           RelocTypeARM = 1\n\tARM_RELOC_SECTDIFF       RelocTypeARM = 2\n\tARM_RELOC_LOCAL_SECTDIFF RelocTypeARM = 3\n\tARM_RELOC_PB_LA_PTR      RelocTypeARM = 4\n\tARM_RELOC_BR24           RelocTypeARM = 5\n\tARM_THUMB_RELOC_BR22     RelocTypeARM = 6\n\tARM_THUMB_32BIT_BRANCH   RelocTypeARM = 7\n\tARM_RELOC_HALF           RelocTypeARM = 8\n\tARM_RELOC_HALF_SECTDIFF  RelocTypeARM = 9\n)\n\nfunc (r RelocTypeARM) GoString() string { return \"macho.\" + r.String() }\n\ntype RelocTypeARM64 int\n\nconst (\n\tARM64_RELOC_UNSIGNED            RelocTypeARM64 = 0\n\tARM64_RELOC_SUBTRACTOR          RelocTypeARM64 = 1\n\tARM64_RELOC_BRANCH26            RelocTypeARM64 = 2\n\tARM64_RELOC_PAGE21              RelocTypeARM64 = 3\n\tARM64_RELOC_PAGEOFF12           RelocTypeARM64 = 4\n\tARM64_RELOC_GOT_LOAD_PAGE21     RelocTypeARM64 = 5\n\tARM64_RELOC_GOT_LOAD_PAGEOFF12  RelocTypeARM64 = 6\n\tARM64_RELOC_POINTER_TO_GOT      RelocTypeARM64 = 7\n\tARM64_RELOC_TLVP_LOAD_PAGE21    RelocTypeARM64 = 8\n\tARM64_RELOC_TLVP_LOAD_PAGEOFF12 RelocTypeARM64 = 9\n\tARM64_RELOC_ADDEND              RelocTypeARM64 = 10\n)\n\nfunc (r RelocTypeARM64) GoString() string { return \"macho.\" + r.String() }\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/reloctype_string.go",
    "content": "// Code generated by \"stringer -type=RelocTypeGeneric,RelocTypeX86_64,RelocTypeARM,RelocTypeARM64 -output reloctype_string.go\"; DO NOT EDIT.\n\npackage macho\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[GENERIC_RELOC_VANILLA-0]\n\t_ = x[GENERIC_RELOC_PAIR-1]\n\t_ = x[GENERIC_RELOC_SECTDIFF-2]\n\t_ = x[GENERIC_RELOC_PB_LA_PTR-3]\n\t_ = x[GENERIC_RELOC_LOCAL_SECTDIFF-4]\n\t_ = x[GENERIC_RELOC_TLV-5]\n}\n\nconst _RelocTypeGeneric_name = \"GENERIC_RELOC_VANILLAGENERIC_RELOC_PAIRGENERIC_RELOC_SECTDIFFGENERIC_RELOC_PB_LA_PTRGENERIC_RELOC_LOCAL_SECTDIFFGENERIC_RELOC_TLV\"\n\nvar _RelocTypeGeneric_index = [...]uint8{0, 21, 39, 61, 84, 112, 129}\n\nfunc (i RelocTypeGeneric) String() string {\n\tif i < 0 || i >= RelocTypeGeneric(len(_RelocTypeGeneric_index)-1) {\n\t\treturn \"RelocTypeGeneric(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _RelocTypeGeneric_name[_RelocTypeGeneric_index[i]:_RelocTypeGeneric_index[i+1]]\n}\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[X86_64_RELOC_UNSIGNED-0]\n\t_ = x[X86_64_RELOC_SIGNED-1]\n\t_ = x[X86_64_RELOC_BRANCH-2]\n\t_ = x[X86_64_RELOC_GOT_LOAD-3]\n\t_ = x[X86_64_RELOC_GOT-4]\n\t_ = x[X86_64_RELOC_SUBTRACTOR-5]\n\t_ = x[X86_64_RELOC_SIGNED_1-6]\n\t_ = x[X86_64_RELOC_SIGNED_2-7]\n\t_ = x[X86_64_RELOC_SIGNED_4-8]\n\t_ = x[X86_64_RELOC_TLV-9]\n}\n\nconst _RelocTypeX86_64_name = \"X86_64_RELOC_UNSIGNEDX86_64_RELOC_SIGNEDX86_64_RELOC_BRANCHX86_64_RELOC_GOT_LOADX86_64_RELOC_GOTX86_64_RELOC_SUBTRACTORX86_64_RELOC_SIGNED_1X86_64_RELOC_SIGNED_2X86_64_RELOC_SIGNED_4X86_64_RELOC_TLV\"\n\nvar _RelocTypeX86_64_index = [...]uint8{0, 21, 40, 59, 80, 96, 119, 140, 161, 182, 198}\n\nfunc (i RelocTypeX86_64) String() string {\n\tif i < 0 || i >= RelocTypeX86_64(len(_RelocTypeX86_64_index)-1) {\n\t\treturn \"RelocTypeX86_64(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _RelocTypeX86_64_name[_RelocTypeX86_64_index[i]:_RelocTypeX86_64_index[i+1]]\n}\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[ARM_RELOC_VANILLA-0]\n\t_ = x[ARM_RELOC_PAIR-1]\n\t_ = x[ARM_RELOC_SECTDIFF-2]\n\t_ = x[ARM_RELOC_LOCAL_SECTDIFF-3]\n\t_ = x[ARM_RELOC_PB_LA_PTR-4]\n\t_ = x[ARM_RELOC_BR24-5]\n\t_ = x[ARM_THUMB_RELOC_BR22-6]\n\t_ = x[ARM_THUMB_32BIT_BRANCH-7]\n\t_ = x[ARM_RELOC_HALF-8]\n\t_ = x[ARM_RELOC_HALF_SECTDIFF-9]\n}\n\nconst _RelocTypeARM_name = \"ARM_RELOC_VANILLAARM_RELOC_PAIRARM_RELOC_SECTDIFFARM_RELOC_LOCAL_SECTDIFFARM_RELOC_PB_LA_PTRARM_RELOC_BR24ARM_THUMB_RELOC_BR22ARM_THUMB_32BIT_BRANCHARM_RELOC_HALFARM_RELOC_HALF_SECTDIFF\"\n\nvar _RelocTypeARM_index = [...]uint8{0, 17, 31, 49, 73, 92, 106, 126, 148, 162, 185}\n\nfunc (i RelocTypeARM) String() string {\n\tif i < 0 || i >= RelocTypeARM(len(_RelocTypeARM_index)-1) {\n\t\treturn \"RelocTypeARM(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _RelocTypeARM_name[_RelocTypeARM_index[i]:_RelocTypeARM_index[i+1]]\n}\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[ARM64_RELOC_UNSIGNED-0]\n\t_ = x[ARM64_RELOC_SUBTRACTOR-1]\n\t_ = x[ARM64_RELOC_BRANCH26-2]\n\t_ = x[ARM64_RELOC_PAGE21-3]\n\t_ = x[ARM64_RELOC_PAGEOFF12-4]\n\t_ = x[ARM64_RELOC_GOT_LOAD_PAGE21-5]\n\t_ = x[ARM64_RELOC_GOT_LOAD_PAGEOFF12-6]\n\t_ = x[ARM64_RELOC_POINTER_TO_GOT-7]\n\t_ = x[ARM64_RELOC_TLVP_LOAD_PAGE21-8]\n\t_ = x[ARM64_RELOC_TLVP_LOAD_PAGEOFF12-9]\n\t_ = x[ARM64_RELOC_ADDEND-10]\n}\n\nconst _RelocTypeARM64_name = \"ARM64_RELOC_UNSIGNEDARM64_RELOC_SUBTRACTORARM64_RELOC_BRANCH26ARM64_RELOC_PAGE21ARM64_RELOC_PAGEOFF12ARM64_RELOC_GOT_LOAD_PAGE21ARM64_RELOC_GOT_LOAD_PAGEOFF12ARM64_RELOC_POINTER_TO_GOTARM64_RELOC_TLVP_LOAD_PAGE21ARM64_RELOC_TLVP_LOAD_PAGEOFF12ARM64_RELOC_ADDEND\"\n\nvar _RelocTypeARM64_index = [...]uint16{0, 20, 42, 62, 80, 101, 128, 158, 184, 212, 243, 261}\n\nfunc (i RelocTypeARM64) String() string {\n\tif i < 0 || i >= RelocTypeARM64(len(_RelocTypeARM64_index)-1) {\n\t\treturn \"RelocTypeARM64(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _RelocTypeARM64_name[_RelocTypeARM64_index[i]:_RelocTypeARM64_index[i+1]]\n}\n"
  },
  {
    "path": "cmd/splitdwarf/internal/macho/testdata/hello.c",
    "content": "#include <stdio.h>\n\nint\nmain(void)\n{\n\tprintf(\"hello, world\\n\");\n\treturn 0;\n}\n"
  },
  {
    "path": "cmd/splitdwarf/splitdwarf.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd\n\n/*\nSplitdwarf uncompresses and copies the DWARF segment of a Mach-O\nexecutable into the \"dSYM\" file expected by lldb and ports of gdb\non OSX.\n\nUsage: splitdwarf osxMachoFile [ osxDsymFile ]\n\nUnless a dSYM file name is provided on the command line,\nsplitdwarf will place it where the OSX tools expect it, in\n\"<osxMachoFile>.dSYM/Contents/Resources/DWARF/<osxMachoFile>\",\ncreating directories as necessary.\n*/\npackage main // import \"golang.org/x/tools/cmd/splitdwarf\"\n\nimport (\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"golang.org/x/tools/cmd/splitdwarf/internal/macho\"\n)\n\nconst (\n\tpageAlign = 12 // 4096 = 1 << 12\n)\n\nfunc note(format string, why ...any) {\n\tfmt.Fprintf(os.Stderr, format+\"\\n\", why...)\n}\n\nfunc fail(format string, why ...any) {\n\tnote(format, why...)\n\tos.Exit(1)\n}\n\n// splitdwarf inputexe [ outputdwarf ]\nfunc main() {\n\tif len(os.Args) < 2 || len(os.Args) > 3 {\n\t\tfmt.Printf(`\nUsage: %s input_exe [ output_dsym ]\nReads the executable input_exe, uncompresses and copies debugging\ninformation into output_dsym. If output_dsym is not specified,\nthe path\n      input_exe.dSYM/Contents/Resources/DWARF/input_exe\nis used instead.  That is the path that gdb and lldb expect\non OSX.  Input_exe needs a UUID segment; if that is missing,\nthen one is created and added.  In that case, the permissions\nfor input_exe need to allow writing.\n`, os.Args[0])\n\t\treturn\n\t}\n\n\t// Read input, find DWARF, be sure it looks right\n\tinputExe := os.Args[1]\n\texeFile, err := os.Open(inputExe)\n\tif err != nil {\n\t\tfail(\"%v\", err)\n\t}\n\texeMacho, err := macho.NewFile(exeFile)\n\tif err != nil {\n\t\tfail(\"(internal) Couldn't create macho, %v\", err)\n\t}\n\t// Postpone dealing with output till input is known-good\n\n\t// describe(&exeMacho.FileTOC)\n\n\t// Offsets into __LINKEDIT:\n\t//\n\t// Command LC_SYMTAB =\n\t//  (1) number of symbols at file offset (within link edit section) of 16-byte symbol table entries\n\t// struct {\n\t//  StringTableIndex uint32\n\t//  Type, SectionIndex uint8\n\t//  Description uint16\n\t//  Value uint64\n\t// }\n\t//\n\t// (2) string table offset and size.  Strings are zero-byte terminated.  First must be \" \".\n\t//\n\t// Command LC_DYSYMTAB = indices within symtab (above), except for IndSym\n\t//   IndSym Offset = file offset (within link edit section) of 4-byte indices within symtab.\n\t//\n\t// Section __TEXT.__symbol_stub1.\n\t//   Offset and size (Reserved2) locate and describe a table for this section.\n\t//   Symbols beginning at IndirectSymIndex (Reserved1) (see LC_DYSYMTAB.IndSymOffset) refer to this table.\n\t//   (These table entries are apparently PLTs [Procedure Linkage Table/Trampoline])\n\t//\n\t// Section __DATA.__nl_symbol_ptr.\n\t//   Reserved1 seems to be an index within the Indirect symbols (see LC_DYSYMTAB.IndSymOffset)\n\t//   Some of these symbols appear to be duplicates of other indirect symbols appearing early\n\t//\n\t// Section __DATA.__la_symbol_ptr.\n\t//   Reserved1 seems to be an index within the Indirect symbols (see LC_DYSYMTAB.IndSymOffset)\n\t//   Some of these symbols appear to be duplicates of other indirect symbols appearing early\n\t//\n\n\t// Create a File for the output dwarf.\n\t// Copy header, file type is MH_DSYM\n\t// Copy the relevant load commands\n\n\t// LoadCmdUuid\n\t// Symtab -- very abbreviated (Use DYSYMTAB Iextdefsym, Nextdefsym to identify these).\n\t// Segment __PAGEZERO\n\t// Segment __TEXT (zero the size, zero the offset of each section)\n\t// Segment __DATA (zero the size, zero the offset of each section)\n\t// Segment __LINKEDIT (contains the symbols and strings from Symtab)\n\t// Segment __DWARF (uncompressed)\n\n\tvar uuid *macho.Uuid\n\tfor _, l := range exeMacho.Loads {\n\t\tswitch l.Command() {\n\t\tcase macho.LcUuid:\n\t\t\tuuid = l.(*macho.Uuid)\n\t\t}\n\t}\n\n\t// Ensure a given load is not nil\n\tnonnilC := func(l macho.Load, s string) {\n\t\tif l == nil {\n\t\t\tfail(\"input file %s lacks load command %s\", inputExe, s)\n\t\t}\n\t}\n\n\t// Find a segment by name and ensure it is not nil\n\tnonnilS := func(s string) *macho.Segment {\n\t\tl := exeMacho.Segment(s)\n\t\tif l == nil {\n\t\t\tfail(\"input file %s lacks segment %s\", inputExe, s)\n\t\t}\n\t\treturn l\n\t}\n\n\tnewtoc := exeMacho.FileTOC.DerivedCopy(macho.MhDsym, 0)\n\n\tsymtab := exeMacho.Symtab\n\tdysymtab := exeMacho.Dysymtab // Not appearing in output, but necessary to construct output\n\tnonnilC(symtab, \"symtab\")\n\tnonnilC(dysymtab, \"dysymtab\")\n\ttext := nonnilS(\"__TEXT\")\n\tdata := nonnilS(\"__DATA\")\n\tlinkedit := nonnilS(\"__LINKEDIT\")\n\tpagezero := nonnilS(\"__PAGEZERO\")\n\n\tnewtext := text.CopyZeroed()\n\tnewdata := data.CopyZeroed()\n\tnewsymtab := symtab.Copy()\n\n\t// Linkedit segment contain symbols and strings;\n\t// Symtab refers to offsets into linkedit.\n\t// This next bit initializes newsymtab and sets up data structures for the linkedit segment\n\tlinkeditsyms := []macho.Nlist64{}\n\tlinkeditstrings := []string{}\n\n\t// Linkedit will begin at the second page, i.e., offset is one page from beginning\n\t// Symbols come first\n\tlinkeditsymbase := uint32(1) << pageAlign\n\n\t// Strings come second, offset by the number of symbols times their size.\n\t// Only those symbols from dysymtab.defsym are written into the debugging information.\n\tlinkeditstringbase := linkeditsymbase + exeMacho.FileTOC.SymbolSize()*dysymtab.Nextdefsym\n\n\t// The first two bytes of the strings are reserved for space, null (' ', \\000)\n\tlinkeditstringcur := uint32(2)\n\n\tnewsymtab.Syms = newsymtab.Syms[:0]\n\tnewsymtab.Symoff = linkeditsymbase\n\tnewsymtab.Stroff = linkeditstringbase\n\tnewsymtab.Nsyms = dysymtab.Nextdefsym\n\tfor i := uint32(0); i < dysymtab.Nextdefsym; i++ {\n\t\tii := i + dysymtab.Iextdefsym\n\t\toldsym := symtab.Syms[ii]\n\t\tnewsymtab.Syms = append(newsymtab.Syms, oldsym)\n\n\t\tlinkeditsyms = append(linkeditsyms, macho.Nlist64{Name: linkeditstringcur,\n\t\t\tType: oldsym.Type, Sect: oldsym.Sect, Desc: oldsym.Desc, Value: oldsym.Value})\n\t\tlinkeditstringcur += uint32(len(oldsym.Name)) + 1\n\t\tlinkeditstrings = append(linkeditstrings, oldsym.Name)\n\t}\n\tnewsymtab.Strsize = linkeditstringcur\n\n\texeNeedsUuid := uuid == nil\n\tif exeNeedsUuid {\n\t\tuuid = &macho.Uuid{UuidCmd: macho.UuidCmd{LoadCmd: macho.LcUuid}}\n\t\tuuid.Len = uuid.LoadSize(newtoc)\n\t\tcopy(uuid.Id[0:], contentuuid(&exeMacho.FileTOC)[0:16])\n\t\tuuid.Id[6] = uuid.Id[6]&^0xf0 | 0x40 // version 4 (pseudo-random); see section 4.1.3\n\t\tuuid.Id[8] = uuid.Id[8]&^0xc0 | 0x80 // variant bits; see section 4.1.1\n\t}\n\tnewtoc.AddLoad(uuid)\n\n\t// For the specified segment (assumed to be in exeMacho) make a copy of its\n\t// sections with appropriate fields zeroed out, and append them to the\n\t// currently-last segment in newtoc.\n\tcopyZOdSections := func(g *macho.Segment) {\n\t\tfor i := g.Firstsect; i < g.Firstsect+g.Nsect; i++ {\n\t\t\ts := exeMacho.Sections[i].Copy()\n\t\t\ts.Offset = 0\n\t\t\ts.Reloff = 0\n\t\t\ts.Nreloc = 0\n\t\t\tnewtoc.AddSection(s)\n\t\t}\n\t}\n\n\tnewtoc.AddLoad(newsymtab)\n\tnewtoc.AddSegment(pagezero)\n\tnewtoc.AddSegment(newtext)\n\tcopyZOdSections(text)\n\tnewtoc.AddSegment(newdata)\n\tcopyZOdSections(data)\n\n\tnewlinkedit := linkedit.Copy()\n\tnewlinkedit.Offset = uint64(linkeditsymbase)\n\tnewlinkedit.Filesz = uint64(linkeditstringcur)\n\tnewlinkedit.Addr = macho.RoundUp(newdata.Addr+newdata.Memsz, 1<<pageAlign) // Follows data sections in file\n\tnewlinkedit.Memsz = macho.RoundUp(newlinkedit.Filesz, 1<<pageAlign)\n\t// The rest should copy over fine.\n\tnewtoc.AddSegment(newlinkedit)\n\n\tdwarf := nonnilS(\"__DWARF\")\n\tnewdwarf := dwarf.CopyZeroed()\n\tnewdwarf.Offset = macho.RoundUp(newlinkedit.Offset+newlinkedit.Filesz, 1<<pageAlign)\n\tnewdwarf.Filesz = dwarf.UncompressedSize(&exeMacho.FileTOC, 1)\n\tnewdwarf.Addr = newlinkedit.Addr + newlinkedit.Memsz // Follows linkedit sections in file.\n\tnewdwarf.Memsz = macho.RoundUp(newdwarf.Filesz, 1<<pageAlign)\n\tnewtoc.AddSegment(newdwarf)\n\n\t// Map out Dwarf sections (that is, this is section descriptors, not their contents).\n\toffset := uint32(newdwarf.Offset)\n\tfor i := dwarf.Firstsect; i < dwarf.Firstsect+dwarf.Nsect; i++ {\n\t\to := exeMacho.Sections[i]\n\t\ts := o.Copy()\n\t\ts.Offset = offset\n\t\tus := o.UncompressedSize()\n\t\tif s.Size < us {\n\t\t\ts.Size = uint64(us)\n\t\t\ts.Align = 0 // This is apparently true for debugging sections; not sure if it generalizes.\n\t\t}\n\t\toffset += uint32(us)\n\t\tif strings.HasPrefix(s.Name, \"__z\") {\n\t\t\ts.Name = \"__\" + s.Name[3:] // remove \"z\"\n\t\t}\n\t\ts.Reloff = 0\n\t\ts.Nreloc = 0\n\t\tnewtoc.AddSection(s)\n\t}\n\n\t// Write segments/sections.\n\t// Only dwarf and linkedit contain anything interesting.\n\n\t// Memory map the output file to get the buffer directly.\n\toutDwarf := inputExe + \".dSYM/Contents/Resources/DWARF\"\n\tif len(os.Args) > 2 {\n\t\toutDwarf = os.Args[2]\n\t} else {\n\t\terr := os.MkdirAll(outDwarf, 0755)\n\t\tif err != nil {\n\t\t\tfail(\"%v\", err)\n\t\t}\n\t\toutDwarf = filepath.Join(outDwarf, filepath.Base(inputExe))\n\t}\n\tdwarfFile, buffer := CreateMmapFile(outDwarf, int64(newtoc.FileSize()))\n\n\t// (1) Linkedit segment\n\t// Symbol table\n\toffset = uint32(newlinkedit.Offset)\n\tfor i := range linkeditsyms {\n\t\tif exeMacho.Magic == macho.Magic64 {\n\t\t\toffset += linkeditsyms[i].Put64(buffer[offset:], newtoc.ByteOrder)\n\t\t} else {\n\t\t\toffset += linkeditsyms[i].Put32(buffer[offset:], newtoc.ByteOrder)\n\t\t}\n\t}\n\n\t// Initial two bytes of string table, followed by actual zero-terminated strings.\n\tbuffer[linkeditstringbase] = ' '\n\tbuffer[linkeditstringbase+1] = 0\n\toffset = linkeditstringbase + 2\n\tfor _, str := range linkeditstrings {\n\t\tfor i := 0; i < len(str); i++ {\n\t\t\tbuffer[offset] = str[i]\n\t\t\toffset++\n\t\t}\n\t\tbuffer[offset] = 0\n\t\toffset++\n\t}\n\n\t// (2) DWARF segment\n\tioff := newdwarf.Firstsect - dwarf.Firstsect\n\tfor i := dwarf.Firstsect; i < dwarf.Firstsect+dwarf.Nsect; i++ {\n\t\ts := exeMacho.Sections[i]\n\t\tj := i + ioff\n\t\ts.PutUncompressedData(buffer[newtoc.Sections[j].Offset:])\n\t}\n\n\t// Because \"text\" overlaps the header and the loads, write them afterwards, just in case.\n\t// Write header.\n\tnewtoc.Put(buffer)\n\n\terr = syscall.Munmap(buffer)\n\tif err != nil {\n\t\tfail(\"Munmap %s for dwarf output failed, %v\", outDwarf, err)\n\t}\n\terr = dwarfFile.Close()\n\tif err != nil {\n\t\tfail(\"Close %s for dwarf output after mmap/munmap failed, %v\", outDwarf, err)\n\t}\n\n\tif exeNeedsUuid { // Map the original exe, modify the header, and write the UUID command\n\t\thdr := exeMacho.FileTOC.FileHeader\n\t\toldCommandEnd := hdr.SizeCommands + newtoc.HdrSize()\n\t\thdr.NCommands += 1\n\t\thdr.SizeCommands += uuid.LoadSize(newtoc)\n\n\t\tmapf, err := os.OpenFile(inputExe, os.O_RDWR, 0)\n\t\tif err != nil {\n\t\t\tfail(\"Updating UUID in binary failed, %v\", err)\n\t\t}\n\t\texebuf, err := syscall.Mmap(int(mapf.Fd()), 0, int(macho.RoundUp(uint64(hdr.SizeCommands), 1<<pageAlign)),\n\t\t\tsyscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_FILE|syscall.MAP_SHARED)\n\t\tif err != nil {\n\t\t\tfail(\"Mmap of %s for UUID update failed, %v\", inputExe, err)\n\t\t}\n\t\t_ = hdr.Put(exebuf, newtoc.ByteOrder)\n\t\t_ = uuid.Put(exebuf[oldCommandEnd:], newtoc.ByteOrder)\n\t\terr = syscall.Munmap(exebuf)\n\t\tif err != nil {\n\t\t\tfail(\"Munmap of %s for UUID update failed, %v\", inputExe, err)\n\t\t}\n\t}\n}\n\n// CreateMmapFile creates the file 'outDwarf' of the specified size, mmaps that file,\n// and returns the file descriptor and mapped buffer.\nfunc CreateMmapFile(outDwarf string, size int64) (*os.File, []byte) {\n\tdwarfFile, err := os.OpenFile(outDwarf, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)\n\tif err != nil {\n\t\tfail(\"Open for mmap failed, %v\", err)\n\t}\n\terr = os.Truncate(outDwarf, size)\n\tif err != nil {\n\t\tfail(\"Truncate/extend of %s to %d bytes failed, %v\", dwarfFile, size, err)\n\t}\n\tbuffer, err := syscall.Mmap(int(dwarfFile.Fd()), 0, int(size), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_FILE|syscall.MAP_SHARED)\n\tif err != nil {\n\t\tfail(\"Mmap %s for dwarf output update failed, %v\", outDwarf, err)\n\t}\n\treturn dwarfFile, buffer\n}\n\n// (dead code; retained for debugging)\nfunc describe(exem *macho.FileTOC) {\n\tnote(\"Type = %s, Flags=0x%x\", exem.Type, uint32(exem.Flags))\n\tfor i, l := range exem.Loads {\n\t\tif s, ok := l.(*macho.Segment); ok {\n\t\t\tfmt.Printf(\"Load %d is Segment %s, offset=0x%x, filesz=%d, addr=0x%x, memsz=%d, nsect=%d\\n\", i, s.Name,\n\t\t\t\ts.Offset, s.Filesz, s.Addr, s.Memsz, s.Nsect)\n\t\t\tfor j := uint32(0); j < s.Nsect; j++ {\n\t\t\t\tc := exem.Sections[j+s.Firstsect]\n\t\t\t\tfmt.Printf(\"   Section %s, offset=0x%x, size=%d, addr=0x%x, flags=0x%x, nreloc=%d, res1=%d, res2=%d, res3=%d\\n\", c.Name, c.Offset, c.Size, c.Addr, c.Flags, c.Nreloc, c.Reserved1, c.Reserved2, c.Reserved3)\n\t\t\t}\n\t\t} else {\n\t\t\tfmt.Printf(\"Load %d is %v\\n\", i, l)\n\t\t}\n\t}\n\tif exem.SizeCommands != exem.LoadSize() {\n\t\tfail(\"recorded command size %d does not equal computed command size %d\", exem.SizeCommands, exem.LoadSize())\n\t} else {\n\t\tnote(\"recorded command size %d, computed command size %d\", exem.SizeCommands, exem.LoadSize())\n\t}\n\tnote(\"File size is %d\", exem.FileSize())\n}\n\n// contentuuid returns a UUID derived from (some of) the content of an executable.\n// specifically included are the non-DWARF sections, specifically excluded are things\n// that surely depend on the presence or absence of DWARF sections (e.g., section\n// numbers, positions with file, number of load commands).\n// (It was considered desirable if this was insensitive to the presence of the\n// __DWARF segment, however because it is not last, it moves other segments,\n// whose contents appear to contain file offset references.)\nfunc contentuuid(exem *macho.FileTOC) []byte {\n\th := sha256.New()\n\tfor _, l := range exem.Loads {\n\t\tif l.Command() == macho.LcUuid {\n\t\t\tcontinue\n\t\t}\n\t\tif s, ok := l.(*macho.Segment); ok {\n\t\t\tif s.Name == \"__DWARF\" || s.Name == \"__PAGEZERO\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor j := uint32(0); j < s.Nsect; j++ {\n\t\t\t\tc := exem.Sections[j+s.Firstsect]\n\t\t\t\tio.Copy(h, c.Open())\n\t\t\t}\n\t\t} // Getting dependence on other load commands right is fiddly.\n\t}\n\treturn h.Sum(nil)\n}\n"
  },
  {
    "path": "cmd/ssadump/main.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// ssadump: a tool for displaying and interpreting the SSA form of Go programs.\npackage main // import \"golang.org/x/tools/cmd/ssadump\"\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/types\"\n\t\"os\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/interp\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\n// flags\nvar (\n\tmode = ssa.BuilderMode(0)\n\n\ttestFlag = flag.Bool(\"test\", false, \"include implicit test packages and executables\")\n\n\trunFlag = flag.Bool(\"run\", false, \"interpret the SSA program\")\n\n\tinterpFlag = flag.String(\"interp\", \"\", `Options controlling the SSA test interpreter.\nThe value is a sequence of zero or more more of these letters:\nR\tdisable [R]ecover() from panic; show interpreter crash instead.\nT\t[T]race execution of the program.  Best for single-threaded programs!\n`)\n\n\tcpuprofile = flag.String(\"cpuprofile\", \"\", \"write cpu profile to file\")\n\n\targs stringListValue\n\n\ttagsFlag = flag.String(\"tags\", \"\", \"comma-separated list of extra build tags (see: go help buildconstraint)\")\n)\n\nfunc init() {\n\tflag.Var(&mode, \"build\", ssa.BuilderModeDoc)\n\tflag.Var(&args, \"arg\", \"add argument to interpreted program\")\n}\n\nconst usage = `SSA builder and interpreter.\nUsage: ssadump [-build=[DBCSNFLG]] [-test] [-run] [-interp=[TR]] [-arg=...] package...\nUse -help flag to display options.\n\nExamples:\n% ssadump -build=F hello.go              # dump SSA form of a single package\n% ssadump -build=F -test fmt             # dump SSA form of a package and its tests\n% ssadump -run -interp=T hello.go        # interpret a program, with tracing\n\nThe -run flag causes ssadump to build the code in a runnable form and run the first\npackage named main.\n\nInterpretation of the standard \"testing\" package is no longer supported.\n`\n\nfunc main() {\n\tif err := doMain(); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"ssadump: %s\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc doMain() error {\n\tflag.Parse()\n\tif len(flag.Args()) == 0 {\n\t\tfmt.Fprint(os.Stderr, usage)\n\t\tos.Exit(1)\n\t}\n\n\tcfg := &packages.Config{\n\t\tBuildFlags: []string{\"-tags=\" + *tagsFlag},\n\t\tMode:       packages.LoadSyntax,\n\t\tTests:      *testFlag,\n\t}\n\n\t// Choose types.Sizes from conf.Build.\n\t// TODO(adonovan): remove this when go/packages provides a better way.\n\tvar wordSize int64 = 8\n\tswitch build.Default.GOARCH {\n\tcase \"386\", \"arm\":\n\t\twordSize = 4\n\t}\n\tsizes := &types.StdSizes{\n\t\tMaxAlign: 8,\n\t\tWordSize: wordSize,\n\t}\n\n\tvar interpMode interp.Mode\n\tfor _, c := range *interpFlag {\n\t\tswitch c {\n\t\tcase 'T':\n\t\t\tinterpMode |= interp.EnableTracing\n\t\tcase 'R':\n\t\t\tinterpMode |= interp.DisableRecover\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown -interp option: '%c'\", c)\n\t\t}\n\t}\n\n\t// Profiling support.\n\tif *cpuprofile != \"\" {\n\t\tf, err := os.Create(*cpuprofile)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tpprof.StartCPUProfile(f)\n\t\tdefer pprof.StopCPUProfile()\n\t}\n\n\t// Load, parse and type-check the initial packages,\n\t// and, if -run, their dependencies.\n\tif *runFlag {\n\t\tcfg.Mode = packages.LoadAllSyntax\n\t}\n\tinitial, err := packages.Load(cfg, flag.Args()...)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(initial) == 0 {\n\t\treturn fmt.Errorf(\"no packages\")\n\t}\n\tif packages.PrintErrors(initial) > 0 {\n\t\treturn fmt.Errorf(\"packages contain errors\")\n\t}\n\n\tif !*runFlag {\n\t\t// Create (and display) SSA only for initial packages and wrappers.\n\t\t_, pkgs := ssautil.Packages(initial, mode)\n\t\tfor i, p := range pkgs {\n\t\t\tif p == nil {\n\t\t\t\treturn fmt.Errorf(\"cannot build SSA for package %s\", initial[i])\n\t\t\t}\n\t\t\tp.Build()\n\t\t}\n\n\t} else {\n\t\t// Create SSA for initial packages and all dependencies, instantiating generics.\n\t\tmode |= ssa.InstantiateGenerics\n\n\t\t// TODO(adonovan): opt: use noreturn analysis over transitive\n\t\t// dependencies to prune spurious control flow graph edges.\n\n\t\tprog, pkgs := ssautil.AllPackages(initial, mode)\n\t\tfor i, p := range pkgs {\n\t\t\tif p == nil {\n\t\t\t\treturn fmt.Errorf(\"cannot build SSA for package %s\", initial[i])\n\t\t\t}\n\t\t}\n\n\t\t// Run the interpreter.\n\t\t// Build SSA for all packages.\n\t\tprog.Build()\n\n\t\t// Earlier versions of the interpreter needed the runtime\n\t\t// package; however, interp cannot handle unsafe constructs\n\t\t// used during runtime's package initialization at the moment.\n\t\t// The key construct blocking support is:\n\t\t//    *((*T)(unsafe.Pointer(p)))\n\t\t// Unfortunately, this means only trivial programs can be\n\t\t// interpreted by ssadump.\n\t\tif prog.ImportedPackage(\"runtime\") != nil {\n\t\t\treturn fmt.Errorf(\"-run: program depends on runtime package (interpreter can run only trivial programs)\")\n\t\t}\n\n\t\tif runtime.GOARCH != build.Default.GOARCH {\n\t\t\treturn fmt.Errorf(\"cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)\",\n\t\t\t\tbuild.Default.GOARCH, runtime.GOARCH)\n\t\t}\n\n\t\t// Run first main package.\n\t\tfor _, main := range ssautil.MainPackages(pkgs) {\n\t\t\tfmt.Fprintf(os.Stderr, \"Running: %s\\n\", main.Pkg.Path())\n\t\t\tos.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))\n\t\t}\n\t\treturn fmt.Errorf(\"no main package\")\n\t}\n\treturn nil\n}\n\n// stringListValue is a flag.Value that accumulates strings.\n// e.g. --flag=one --flag=two would produce []string{\"one\", \"two\"}.\ntype stringListValue []string\n\nfunc (ss *stringListValue) Get() any { return []string(*ss) }\n\nfunc (ss *stringListValue) String() string { return fmt.Sprintf(\"%q\", *ss) }\n\nfunc (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }\n"
  },
  {
    "path": "cmd/stress/stress.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows\n\n// The stress utility is intended for catching sporadic failures.\n// It runs a given process in parallel in a loop and collects any failures.\n// Usage:\n//\n//\t$ stress ./fmt.test -test.run=TestSometing -test.cpu=10\n//\n// You can also specify a number of parallel processes with -p flag;\n// instruct the utility to not kill hanged processes for gdb attach;\n// or specify the failure output you are looking for (if you want to\n// ignore some other sporadic failures).\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"sync/atomic\"\n\t\"syscall\"\n\t\"time\"\n)\n\nvar (\n\tflagCount    = flag.Int(\"count\", 0, \"stop after `N` runs (default never stop)\")\n\tflagFailfast = flag.Bool(\"failfast\", false, \"exit on first failure and write failure output to stderr\")\n\tflagFailure  = flag.String(\"failure\", \"\", \"fail only if output matches `regexp`\")\n\tflagIgnore   = flag.String(\"ignore\", \"\", \"ignore failure if output matches `regexp`\")\n\tflagKill     = flag.Bool(\"kill\", true, \"kill timed out processes if true, otherwise just print pid (to attach with gdb)\")\n\tflagOutput   = flag.String(\"o\", defaultPrefix(), \"output failure logs to `path` plus a unique suffix\")\n\tflagP        = flag.Int(\"p\", runtime.NumCPU(), \"run `N` processes in parallel\")\n\tflagTimeout  = flag.Duration(\"timeout\", 10*time.Minute, \"timeout each process after `duration`\")\n)\n\nfunc init() {\n\tflag.Usage = func() {\n\t\tos.Stderr.WriteString(`The stress utility is intended for catching sporadic failures.\nIt runs a given process in parallel in a loop and collects any failures.\nUsage:\n\n\t$ stress ./fmt.test -test.run=TestSometing -test.cpu=10\n\n`)\n\t\tflag.PrintDefaults()\n\t}\n}\n\nfunc defaultPrefix() string {\n\tdate := time.Now().Format(\"go-stress-20060102T150405-\")\n\treturn filepath.Join(os.TempDir(), date)\n}\n\nfunc main() {\n\tflag.Parse()\n\tif *flagP <= 0 || *flagTimeout <= 0 || len(flag.Args()) == 0 {\n\t\tflag.Usage()\n\t\tos.Exit(1)\n\t}\n\tvar failureRe, ignoreRe *regexp.Regexp\n\tif *flagFailure != \"\" {\n\t\tvar err error\n\t\tif failureRe, err = regexp.Compile(*flagFailure); err != nil {\n\t\t\tfmt.Println(\"bad failure regexp:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\tif *flagIgnore != \"\" {\n\t\tvar err error\n\t\tif ignoreRe, err = regexp.Compile(*flagIgnore); err != nil {\n\t\t\tfmt.Println(\"bad ignore regexp:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\tres := make(chan []byte)\n\tvar started atomic.Int64\n\tfor i := 0; i < *flagP; i++ {\n\t\tgo func() {\n\t\t\tfor {\n\t\t\t\t// Note: Must started.Add(1) even if not using -count,\n\t\t\t\t// because it enables the '%d active' print below.\n\t\t\t\tif started.Add(1) > int64(*flagCount) && *flagCount > 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)\n\t\t\t\tvar buf bytes.Buffer\n\t\t\t\tcmd.Stdout = &buf\n\t\t\t\tcmd.Stderr = &buf\n\t\t\t\terr := cmd.Start() // make cmd.Process valid for timeout goroutine\n\t\t\t\tdone := make(chan bool)\n\t\t\t\tif err == nil && *flagTimeout > 0 {\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tselect {\n\t\t\t\t\t\tcase <-done:\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\tcase <-time.After(*flagTimeout):\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !*flagKill {\n\t\t\t\t\t\t\tfmt.Printf(\"process %v timed out\\n\", cmd.Process.Pid)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcmd.Process.Signal(syscall.SIGABRT)\n\t\t\t\t\t\tselect {\n\t\t\t\t\t\tcase <-done:\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\tcase <-time.After(10 * time.Second):\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcmd.Process.Kill()\n\t\t\t\t\t}()\n\t\t\t\t}\n\t\t\t\tif err == nil {\n\t\t\t\t\terr = cmd.Wait()\n\t\t\t\t}\n\t\t\t\tout := buf.Bytes()\n\t\t\t\tclose(done)\n\t\t\t\tif err != nil && (failureRe == nil || failureRe.Match(out)) && (ignoreRe == nil || !ignoreRe.Match(out)) {\n\t\t\t\t\tout = append(out, fmt.Sprintf(\"\\n\\nERROR: %v\\n\", err)...)\n\t\t\t\t} else {\n\t\t\t\t\tout = []byte{}\n\t\t\t\t}\n\t\t\t\tres <- out\n\t\t\t}\n\t\t}()\n\t}\n\truns, fails := 0, 0\n\tstart := time.Now()\n\tticker := time.NewTicker(5 * time.Second).C\n\tstatus := func(context string) {\n\t\telapsed := time.Since(start).Truncate(time.Second)\n\t\tvar pct string\n\t\tif fails > 0 {\n\t\t\tpct = fmt.Sprintf(\" (%0.2f%%)\", 100.0*float64(fails)/float64(runs))\n\t\t}\n\t\tvar active string\n\t\tn := started.Load() - int64(runs)\n\t\tif *flagCount > 0 {\n\t\t\t// started counts past *flagCount at end; do not count those\n\t\t\t// TODO: n = min(n, int64(*flagCount-runs))\n\t\t\tif x := int64(*flagCount - runs); n > x {\n\t\t\t\tn = x\n\t\t\t}\n\t\t}\n\t\tif n > 0 {\n\t\t\tactive = fmt.Sprintf(\", %d active\", n)\n\t\t}\n\t\tfmt.Printf(\"%v: %v runs %s, %v failures%s%s\\n\", elapsed, runs, context, fails, pct, active)\n\t}\n\tfor {\n\t\tselect {\n\t\tcase out := <-res:\n\t\t\truns++\n\t\t\tif len(out) > 0 {\n\t\t\t\tfails++\n\t\t\t\tif *flagFailfast {\n\t\t\t\t\tos.Stderr.Write(out)\n\t\t\t\t\tos.Exit(1)\n\t\t\t\t}\n\t\t\t\tdir, path := filepath.Split(*flagOutput)\n\t\t\t\tf, err := os.CreateTemp(dir, path)\n\t\t\t\tif err != nil {\n\t\t\t\t\tfmt.Printf(\"failed to create temp file: %v\\n\", err)\n\t\t\t\t\tos.Exit(1)\n\t\t\t\t}\n\t\t\t\tf.Write(out)\n\t\t\t\tf.Close()\n\t\t\t\tif len(out) > 2<<10 {\n\t\t\t\t\tout := out[:2<<10]\n\t\t\t\t\tfmt.Printf(\"\\n%s\\n%s\\n…\\n\", f.Name(), out)\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Printf(\"\\n%s\\n%s\\n\", f.Name(), out)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif *flagCount > 0 && runs >= *flagCount {\n\t\t\t\tstatus(\"total\")\n\t\t\t\tif fails > 0 {\n\t\t\t\t\tos.Exit(1)\n\t\t\t\t}\n\t\t\t\tos.Exit(0)\n\t\t\t}\n\t\tcase <-ticker:\n\t\t\tstatus(\"so far\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/endtoend_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go command is not available on android\n\n//go:build !android\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// This file contains a test that compiles and runs each program in testdata\n// after generating the string method for its type. The rule is that for testdata/x.go\n// we run stringer -type X and then compile and run the program. The resulting\n// binary panics if the String method for X is not correct, including for error cases.\n\nfunc TestMain(m *testing.M) {\n\tif os.Getenv(\"STRINGER_TEST_IS_STRINGER\") != \"\" {\n\t\tmain()\n\t\tos.Exit(0)\n\t}\n\n\t// Inform subprocesses that they should run the cmd/stringer main instead of\n\t// running tests. It's a close approximation to building and running the real\n\t// command, and much less complicated and expensive to build and clean up.\n\tos.Setenv(\"STRINGER_TEST_IS_STRINGER\", \"1\")\n\n\tflag.Parse()\n\tif testing.Verbose() {\n\t\tos.Setenv(\"GOPACKAGESDEBUG\", \"true\")\n\t}\n\n\tos.Exit(m.Run())\n}\n\nfunc TestEndToEnd(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tstringer := stringerPath(t)\n\t// Read the testdata directory.\n\tfd, err := os.Open(\"testdata\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer fd.Close()\n\tnames, err := fd.Readdirnames(-1)\n\tif err != nil {\n\t\tt.Fatalf(\"Readdirnames: %s\", err)\n\t}\n\t// Generate, compile, and run the test programs.\n\tfor _, name := range names {\n\t\tif name == \"typeparams\" {\n\t\t\t// ignore the directory containing the tests with type params\n\t\t\tcontinue\n\t\t}\n\t\tif !strings.HasSuffix(name, \".go\") {\n\t\t\tt.Errorf(\"%s is not a Go file\", name)\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(name, \"tag_\") || strings.HasPrefix(name, \"vary_\") {\n\t\t\t// This file is used for tag processing in TestTags or TestConstValueChange, below.\n\t\t\tcontinue\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tif name == \"cgo.go\" {\n\t\t\t\ttestenv.NeedsTool(t, \"cgo\")\n\t\t\t}\n\t\t\tstringerCompileAndRun(t, t.TempDir(), stringer, typeName(name), name)\n\t\t})\n\t}\n}\n\n// a type name for stringer. use the last component of the file name with the .go\nfunc typeName(fname string) string {\n\t// file names are known to be ascii and end .go\n\tbase := path.Base(fname)\n\treturn fmt.Sprintf(\"%c%s\", base[0]+'A'-'a', base[1:len(base)-len(\".go\")])\n}\n\n// TestTags verifies that the -tags flag works as advertised.\nfunc TestTags(t *testing.T) {\n\tstringer := stringerPath(t)\n\tdir := t.TempDir()\n\tvar (\n\t\tprotectedConst = []byte(\"TagProtected\")\n\t\toutput         = filepath.Join(dir, \"const_string.go\")\n\t)\n\tfor _, file := range []string{\"tag_main.go\", \"tag_tag.go\"} {\n\t\terr := copy(filepath.Join(dir, file), filepath.Join(\"testdata\", file))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\t// Run stringer in the directory that contains the module that contains the package files.\n\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), []byte(\"module test\\n\"), 0o600); err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr := runInDir(t, dir, stringer, \"-type\", \"Const\", \".\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tresult, err := os.ReadFile(output)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bytes.Contains(result, protectedConst) {\n\t\tt.Fatal(\"tagged variable appears in untagged run\")\n\t}\n\terr = os.Remove(output)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = runInDir(t, dir, stringer, \"-type\", \"Const\", \"-tags\", \"tag\", \".\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tresult, err = os.ReadFile(output)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !bytes.Contains(result, protectedConst) {\n\t\tt.Fatal(\"tagged variable does not appear in tagged run\")\n\t}\n}\n\n// TestConstValueChange verifies that if a constant value changes and\n// the stringer code is not regenerated, we'll get a compiler error.\nfunc TestConstValueChange(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tstringer := stringerPath(t)\n\tdir := t.TempDir()\n\tsource := filepath.Join(dir, \"day.go\")\n\terr := copy(source, filepath.Join(\"testdata\", \"day.go\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tstringSource := filepath.Join(dir, \"day_string.go\")\n\t// Run stringer in the directory that contains the module that contains the package files.\n\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), []byte(\"module test\\n\"), 0o600); err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = runInDir(t, dir, stringer, \"-type\", \"Day\", \"-output\", stringSource)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Run the binary in the temporary directory as a sanity check.\n\terr = run(t, \"go\", \"run\", stringSource, source)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Overwrite the source file with a version that has changed constants.\n\terr = copy(source, filepath.Join(\"testdata\", \"vary_day.go\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Unfortunately different compilers may give different error messages,\n\t// so there's no easy way to verify that the build failed specifically\n\t// because the constants changed rather than because the vary_day.go\n\t// file is invalid.\n\t//\n\t// Instead we'll just rely on manual inspection of the polluted test\n\t// output. An alternative might be to check that the error output\n\t// matches a set of possible error strings emitted by known\n\t// Go compilers.\n\tt.Logf(\"Note: the following messages should indicate an out-of-bounds compiler error\\n\")\n\terr = run(t, \"go\", \"build\", stringSource, source)\n\tif err == nil {\n\t\tt.Fatal(\"unexpected compiler success\")\n\t}\n}\n\nvar testfileSrcs = map[string]string{\n\t\"go.mod\": \"module foo\",\n\n\t// Normal file in the package.\n\t\"main.go\": `package foo\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)\n`,\n\n\t// Test file in the package.\n\t\"main_test.go\": `package foo\n\ntype Bar int\n\nconst (\n\tbarX Bar = iota\n\tbarY\n\tbarZ\n)\n`,\n\n\t// Test file in the test package.\n\t\"main_pkg_test.go\": `package foo_test\n\ntype Baz int\n\nconst (\n\tbazX Baz = iota\n\tbazY\n\tbazZ\n)\n`,\n}\n\n// Test stringer on types defined in different kinds of tests.\n// The generated code should not interfere between itself.\nfunc TestTestFiles(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tstringer := stringerPath(t)\n\n\tdir := t.TempDir()\n\tt.Logf(\"TestTestFiles in: %s \\n\", dir)\n\tfor name, src := range testfileSrcs {\n\t\tsource := filepath.Join(dir, name)\n\t\terr := os.WriteFile(source, []byte(src), 0666)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"write file: %s\", err)\n\t\t}\n\t}\n\n\t// Must run stringer in the temp directory, see TestTags.\n\terr := runInDir(t, dir, stringer, \"-type=Foo,Bar,Baz\", dir)\n\tif err != nil {\n\t\tt.Fatalf(\"run stringer: %s\", err)\n\t}\n\n\t// Check that stringer has created the expected files.\n\tcontent, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"read dir: %s\", err)\n\t}\n\tgotFiles := []string{}\n\tfor _, f := range content {\n\t\tif !f.IsDir() {\n\t\t\tgotFiles = append(gotFiles, f.Name())\n\t\t}\n\t}\n\twantFiles := []string{\n\t\t// Original.\n\t\t\"go.mod\",\n\t\t\"main.go\",\n\t\t\"main_test.go\",\n\t\t\"main_pkg_test.go\",\n\t\t// Generated.\n\t\t\"foo_string.go\",\n\t\t\"bar_string_test.go\",\n\t\t\"baz_string_test.go\",\n\t}\n\tslices.Sort(gotFiles)\n\tslices.Sort(wantFiles)\n\tif !reflect.DeepEqual(gotFiles, wantFiles) {\n\t\tt.Errorf(\"stringer generated files:\\n%s\\n\\nbut want:\\n%s\",\n\t\t\tstrings.Join(gotFiles, \"\\n\"),\n\t\t\tstrings.Join(wantFiles, \"\\n\"),\n\t\t)\n\t}\n\n\t// Run go test as a smoke test.\n\terr = runInDir(t, dir, \"go\", \"test\", \"-count=1\", \".\")\n\tif err != nil {\n\t\tt.Fatalf(\"go test: %s\", err)\n\t}\n}\n\n// The -output flag cannot be used in combination with matching types across multiple packages.\nfunc TestCollidingOutput(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tstringer := stringerPath(t)\n\n\tdir := t.TempDir()\n\tfor name, src := range testfileSrcs {\n\t\tsource := filepath.Join(dir, name)\n\t\terr := os.WriteFile(source, []byte(src), 0666)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"write file: %s\", err)\n\t\t}\n\t}\n\n\t// Must run stringer in the temp directory, see TestTags.\n\terr := runInDir(t, dir, stringer, \"-type=Foo,Bar,Baz\", \"-output=somefile.go\", dir)\n\tif err == nil {\n\t\tt.Fatal(\"unexpected stringer success\")\n\t}\n}\n\nvar exe struct {\n\tpath string\n\terr  error\n\tonce sync.Once\n}\n\nfunc stringerPath(t *testing.T) string {\n\ttestenv.NeedsExec(t)\n\n\texe.once.Do(func() {\n\t\texe.path, exe.err = os.Executable()\n\t})\n\tif exe.err != nil {\n\t\tt.Fatal(exe.err)\n\t}\n\treturn exe.path\n}\n\n// stringerCompileAndRun runs stringer for the named file and compiles and\n// runs the target binary in directory dir. That binary will panic if the String method is incorrect.\nfunc stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {\n\tt.Logf(\"run: %s %s\\n\", fileName, typeName)\n\tsource := filepath.Join(dir, path.Base(fileName))\n\terr := copy(source, filepath.Join(\"testdata\", fileName))\n\tif err != nil {\n\t\tt.Fatalf(\"copying file to temporary directory: %s\", err)\n\t}\n\tstringSource := filepath.Join(dir, typeName+\"_string.go\")\n\t// Run stringer in temporary directory.\n\terr = run(t, stringer, \"-type\", typeName, \"-output\", stringSource, source)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Run the binary in the temporary directory.\n\terr = run(t, \"go\", \"run\", stringSource, source)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\n// copy copies the from file to the to file.\nfunc copy(to, from string) error {\n\ttoFd, err := os.Create(to)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer toFd.Close()\n\tfromFd, err := os.Open(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer fromFd.Close()\n\t_, err = io.Copy(toFd, fromFd)\n\treturn err\n}\n\n// run runs a single command and returns an error if it does not succeed.\n// os/exec should have this function, to be honest.\nfunc run(t testing.TB, name string, arg ...string) error {\n\tt.Helper()\n\treturn runInDir(t, \".\", name, arg...)\n}\n\n// runInDir runs a single command in directory dir and returns an error if\n// it does not succeed.\nfunc runInDir(t testing.TB, dir, name string, arg ...string) error {\n\tt.Helper()\n\tcmd := testenv.Command(t, name, arg...)\n\tcmd.Dir = dir\n\tout, err := cmd.CombinedOutput()\n\tif len(out) > 0 {\n\t\tt.Logf(\"%s\", out)\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", cmd, err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "cmd/stringer/golden_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains simple golden tests for various examples.\n// Besides validating the results when the implementation changes,\n// it provides a way to look at the generated code without having\n// to execute the print statements in one's head.\n\npackage main\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// Golden represents a test case.\ntype Golden struct {\n\tname        string\n\ttrimPrefix  string\n\tlineComment bool\n\tinput       string // input; the package clause is provided when running the test.\n\toutput      string // expected output.\n}\n\nvar golden = []Golden{\n\t{\"day\", \"\", false, day_in, day_out},\n\t{\"offset\", \"\", false, offset_in, offset_out},\n\t{\"gap\", \"\", false, gap_in, gap_out},\n\t{\"num\", \"\", false, num_in, num_out},\n\t{\"unum\", \"\", false, unum_in, unum_out},\n\t{\"unumpos\", \"\", false, unumpos_in, unumpos_out},\n\t{\"prime\", \"\", false, prime_in, prime_out},\n\t{\"prefix\", \"Type\", false, prefix_in, prefix_out},\n\t{\"tokens\", \"\", true, tokens_in, tokens_out},\n\t{\"overflow8\", \"\", false, overflow8_in, overflow8_out},\n}\n\n// Each example starts with \"type XXX [u]int\", with a single space separating them.\n\n// Simple test: enumeration of type int starting at 0.\nconst day_in = `type Day int\nconst (\n\tMonday Day = iota\n\tTuesday\n\tWednesday\n\tThursday\n\tFriday\n\tSaturday\n\tSunday\n)\n`\n\nconst day_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[Monday-0]\n\t_ = x[Tuesday-1]\n\t_ = x[Wednesday-2]\n\t_ = x[Thursday-3]\n\t_ = x[Friday-4]\n\t_ = x[Saturday-5]\n\t_ = x[Sunday-6]\n}\n\nconst _Day_name = \"MondayTuesdayWednesdayThursdayFridaySaturdaySunday\"\n\nvar _Day_index = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}\n\nfunc (i Day) String() string {\n\tidx := int(i) - 0\n\tif i < 0 || idx >= len(_Day_index)-1 {\n\t\treturn \"Day(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Day_name[_Day_index[idx]:_Day_index[idx+1]]\n}\n`\n\n// Enumeration with an offset.\n// Also includes a duplicate.\nconst offset_in = `type Number int\nconst (\n\t_ Number = iota\n\tOne\n\tTwo\n\tThree\n\tAnotherOne = One  // Duplicate; note that AnotherOne doesn't appear below.\n)\n`\n\nconst offset_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[One-1]\n\t_ = x[Two-2]\n\t_ = x[Three-3]\n}\n\nconst _Number_name = \"OneTwoThree\"\n\nvar _Number_index = [...]uint8{0, 3, 6, 11}\n\nfunc (i Number) String() string {\n\tidx := int(i) - 1\n\tif i < 1 || idx >= len(_Number_index)-1 {\n\t\treturn \"Number(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Number_name[_Number_index[idx]:_Number_index[idx+1]]\n}\n`\n\n// Gaps and an offset.\nconst gap_in = `type Gap int\nconst (\n\tTwo Gap = 2\n\tThree Gap = 3\n\tFive Gap = 5\n\tSix Gap = 6\n\tSeven Gap = 7\n\tEight Gap = 8\n\tNine Gap = 9\n\tEleven Gap = 11\n)\n`\n\nconst gap_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[Two-2]\n\t_ = x[Three-3]\n\t_ = x[Five-5]\n\t_ = x[Six-6]\n\t_ = x[Seven-7]\n\t_ = x[Eight-8]\n\t_ = x[Nine-9]\n\t_ = x[Eleven-11]\n}\n\nconst (\n\t_Gap_name_0 = \"TwoThree\"\n\t_Gap_name_1 = \"FiveSixSevenEightNine\"\n\t_Gap_name_2 = \"Eleven\"\n)\n\nvar (\n\t_Gap_index_0 = [...]uint8{0, 3, 8}\n\t_Gap_index_1 = [...]uint8{0, 4, 7, 12, 17, 21}\n)\n\nfunc (i Gap) String() string {\n\tswitch {\n\tcase 2 <= i && i <= 3:\n\t\ti -= 2\n\t\treturn _Gap_name_0[_Gap_index_0[i]:_Gap_index_0[i+1]]\n\tcase 5 <= i && i <= 9:\n\t\ti -= 5\n\t\treturn _Gap_name_1[_Gap_index_1[i]:_Gap_index_1[i+1]]\n\tcase i == 11:\n\t\treturn _Gap_name_2\n\tdefault:\n\t\treturn \"Gap(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n}\n`\n\n// Signed integers spanning zero.\nconst num_in = `type Num int\nconst (\n\tm_2 Num = -2 + iota\n\tm_1\n\tm0\n\tm1\n\tm2\n)\n`\n\nconst num_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[m_2 - -2]\n\t_ = x[m_1 - -1]\n\t_ = x[m0-0]\n\t_ = x[m1-1]\n\t_ = x[m2-2]\n}\n\nconst _Num_name = \"m_2m_1m0m1m2\"\n\nvar _Num_index = [...]uint8{0, 3, 6, 8, 10, 12}\n\nfunc (i Num) String() string {\n\tidx := int(i) - -2\n\tif i < -2 || idx >= len(_Num_index)-1 {\n\t\treturn \"Num(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Num_name[_Num_index[idx]:_Num_index[idx+1]]\n}\n`\n\n// Unsigned integers spanning zero.\nconst unum_in = `type Unum uint\nconst (\n\tm_2 Unum = iota + 253\n\tm_1\n)\n\nconst (\n\tm0 Unum = iota\n\tm1\n\tm2\n)\n`\n\nconst unum_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[m_2-253]\n\t_ = x[m_1-254]\n\t_ = x[m0-0]\n\t_ = x[m1-1]\n\t_ = x[m2-2]\n}\n\nconst (\n\t_Unum_name_0 = \"m0m1m2\"\n\t_Unum_name_1 = \"m_2m_1\"\n)\n\nvar (\n\t_Unum_index_0 = [...]uint8{0, 2, 4, 6}\n\t_Unum_index_1 = [...]uint8{0, 3, 6}\n)\n\nfunc (i Unum) String() string {\n\tswitch {\n\tcase i <= 2:\n\t\treturn _Unum_name_0[_Unum_index_0[i]:_Unum_index_0[i+1]]\n\tcase 253 <= i && i <= 254:\n\t\ti -= 253\n\t\treturn _Unum_name_1[_Unum_index_1[i]:_Unum_index_1[i+1]]\n\tdefault:\n\t\treturn \"Unum(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n}\n`\n\n// Unsigned positive integers.\nconst unumpos_in = `type Unumpos uint\nconst (\n\tm253 Unumpos = iota + 253\n\tm254\n)\n\nconst (\n\tm1 Unumpos = iota + 1\n\tm2\n\tm3\n)\n`\n\nconst unumpos_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[m253-253]\n\t_ = x[m254-254]\n\t_ = x[m1-1]\n\t_ = x[m2-2]\n\t_ = x[m3-3]\n}\n\nconst (\n\t_Unumpos_name_0 = \"m1m2m3\"\n\t_Unumpos_name_1 = \"m253m254\"\n)\n\nvar (\n\t_Unumpos_index_0 = [...]uint8{0, 2, 4, 6}\n\t_Unumpos_index_1 = [...]uint8{0, 4, 8}\n)\n\nfunc (i Unumpos) String() string {\n\tswitch {\n\tcase 1 <= i && i <= 3:\n\t\ti -= 1\n\t\treturn _Unumpos_name_0[_Unumpos_index_0[i]:_Unumpos_index_0[i+1]]\n\tcase 253 <= i && i <= 254:\n\t\ti -= 253\n\t\treturn _Unumpos_name_1[_Unumpos_index_1[i]:_Unumpos_index_1[i+1]]\n\tdefault:\n\t\treturn \"Unumpos(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n}\n`\n\n// Enough gaps to trigger a map implementation of the method.\n// Also includes a duplicate to test that it doesn't cause problems\nconst prime_in = `type Prime int\nconst (\n\tp2 Prime = 2\n\tp3 Prime = 3\n\tp5 Prime = 5\n\tp7 Prime = 7\n\tp77 Prime = 7 // Duplicate; note that p77 doesn't appear below.\n\tp11 Prime = 11\n\tp13 Prime = 13\n\tp17 Prime = 17\n\tp19 Prime = 19\n\tp23 Prime = 23\n\tp29 Prime = 29\n\tp37 Prime = 31\n\tp41 Prime = 41\n\tp43 Prime = 43\n)\n`\n\nconst prime_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[p2-2]\n\t_ = x[p3-3]\n\t_ = x[p5-5]\n\t_ = x[p7-7]\n\t_ = x[p77-7]\n\t_ = x[p11-11]\n\t_ = x[p13-13]\n\t_ = x[p17-17]\n\t_ = x[p19-19]\n\t_ = x[p23-23]\n\t_ = x[p29-29]\n\t_ = x[p37-31]\n\t_ = x[p41-41]\n\t_ = x[p43-43]\n}\n\nconst _Prime_name = \"p2p3p5p7p11p13p17p19p23p29p37p41p43\"\n\nvar _Prime_map = map[Prime]string{\n\t2:  _Prime_name[0:2],\n\t3:  _Prime_name[2:4],\n\t5:  _Prime_name[4:6],\n\t7:  _Prime_name[6:8],\n\t11: _Prime_name[8:11],\n\t13: _Prime_name[11:14],\n\t17: _Prime_name[14:17],\n\t19: _Prime_name[17:20],\n\t23: _Prime_name[20:23],\n\t29: _Prime_name[23:26],\n\t31: _Prime_name[26:29],\n\t41: _Prime_name[29:32],\n\t43: _Prime_name[32:35],\n}\n\nfunc (i Prime) String() string {\n\tif str, ok := _Prime_map[i]; ok {\n\t\treturn str\n\t}\n\treturn \"Prime(\" + strconv.FormatInt(int64(i), 10) + \")\"\n}\n`\n\nconst prefix_in = `type Type int\nconst (\n\tTypeInt Type = iota\n\tTypeString\n\tTypeFloat\n\tTypeRune\n\tTypeByte\n\tTypeStruct\n\tTypeSlice\n)\n`\n\nconst prefix_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[TypeInt-0]\n\t_ = x[TypeString-1]\n\t_ = x[TypeFloat-2]\n\t_ = x[TypeRune-3]\n\t_ = x[TypeByte-4]\n\t_ = x[TypeStruct-5]\n\t_ = x[TypeSlice-6]\n}\n\nconst _Type_name = \"IntStringFloatRuneByteStructSlice\"\n\nvar _Type_index = [...]uint8{0, 3, 9, 14, 18, 22, 28, 33}\n\nfunc (i Type) String() string {\n\tidx := int(i) - 0\n\tif i < 0 || idx >= len(_Type_index)-1 {\n\t\treturn \"Type(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Type_name[_Type_index[idx]:_Type_index[idx+1]]\n}\n`\n\nconst tokens_in = `type Token int\nconst (\n\tAnd Token = iota // &\n\tOr               // |\n\tAdd              // +\n\tSub              // -\n\tIdent\n\tPeriod // .\n\n\t// not to be used\n\tSingleBefore\n\t// not to be used\n\tBeforeAndInline // inline\n\tInlineGeneral /* inline general */\n)\n`\n\nconst tokens_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[And-0]\n\t_ = x[Or-1]\n\t_ = x[Add-2]\n\t_ = x[Sub-3]\n\t_ = x[Ident-4]\n\t_ = x[Period-5]\n\t_ = x[SingleBefore-6]\n\t_ = x[BeforeAndInline-7]\n\t_ = x[InlineGeneral-8]\n}\n\nconst _Token_name = \"&|+-Ident.SingleBeforeinlineinline general\"\n\nvar _Token_index = [...]uint8{0, 1, 2, 3, 4, 9, 10, 22, 28, 42}\n\nfunc (i Token) String() string {\n\tidx := int(i) - 0\n\tif i < 0 || idx >= len(_Token_index)-1 {\n\t\treturn \"Token(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Token_name[_Token_index[idx]:_Token_index[idx+1]]\n}\n`\n\nconst overflow8_in = `type Overflow8 int8\nconst (\n\tO_128 Overflow8 = -128\n\tO_127 Overflow8 = -127\n\tO_126 Overflow8 = -126\n\tO_125 Overflow8 = -125\n\tO_124 Overflow8 = -124\n\tO_123 Overflow8 = -123\n\tO_122 Overflow8 = -122\n\tO_121 Overflow8 = -121\n\tO_120 Overflow8 = -120\n\tO_119 Overflow8 = -119\n\tO_118 Overflow8 = -118\n\tO_117 Overflow8 = -117\n\tO_116 Overflow8 = -116\n\tO_115 Overflow8 = -115\n\tO_114 Overflow8 = -114\n\tO_113 Overflow8 = -113\n\tO_112 Overflow8 = -112\n\tO_111 Overflow8 = -111\n\tO_110 Overflow8 = -110\n\tO_109 Overflow8 = -109\n\tO_108 Overflow8 = -108\n\tO_107 Overflow8 = -107\n\tO_106 Overflow8 = -106\n\tO_105 Overflow8 = -105\n\tO_104 Overflow8 = -104\n\tO_103 Overflow8 = -103\n\tO_102 Overflow8 = -102\n\tO_101 Overflow8 = -101\n\tO_100 Overflow8 = -100\n\tO_99 Overflow8 = -99\n\tO_98 Overflow8 = -98\n\tO_97 Overflow8 = -97\n\tO_96 Overflow8 = -96\n\tO_95 Overflow8 = -95\n\tO_94 Overflow8 = -94\n\tO_93 Overflow8 = -93\n\tO_92 Overflow8 = -92\n\tO_91 Overflow8 = -91\n\tO_90 Overflow8 = -90\n\tO_89 Overflow8 = -89\n\tO_88 Overflow8 = -88\n\tO_87 Overflow8 = -87\n\tO_86 Overflow8 = -86\n\tO_85 Overflow8 = -85\n\tO_84 Overflow8 = -84\n\tO_83 Overflow8 = -83\n\tO_82 Overflow8 = -82\n\tO_81 Overflow8 = -81\n\tO_80 Overflow8 = -80\n\tO_79 Overflow8 = -79\n\tO_78 Overflow8 = -78\n\tO_77 Overflow8 = -77\n\tO_76 Overflow8 = -76\n\tO_75 Overflow8 = -75\n\tO_74 Overflow8 = -74\n\tO_73 Overflow8 = -73\n\tO_72 Overflow8 = -72\n\tO_71 Overflow8 = -71\n\tO_70 Overflow8 = -70\n\tO_69 Overflow8 = -69\n\tO_68 Overflow8 = -68\n\tO_67 Overflow8 = -67\n\tO_66 Overflow8 = -66\n\tO_65 Overflow8 = -65\n\tO_64 Overflow8 = -64\n\tO_63 Overflow8 = -63\n\tO_62 Overflow8 = -62\n\tO_61 Overflow8 = -61\n\tO_60 Overflow8 = -60\n\tO_59 Overflow8 = -59\n\tO_58 Overflow8 = -58\n\tO_57 Overflow8 = -57\n\tO_56 Overflow8 = -56\n\tO_55 Overflow8 = -55\n\tO_54 Overflow8 = -54\n\tO_53 Overflow8 = -53\n\tO_52 Overflow8 = -52\n\tO_51 Overflow8 = -51\n\tO_50 Overflow8 = -50\n\tO_49 Overflow8 = -49\n\tO_48 Overflow8 = -48\n\tO_47 Overflow8 = -47\n\tO_46 Overflow8 = -46\n\tO_45 Overflow8 = -45\n\tO_44 Overflow8 = -44\n\tO_43 Overflow8 = -43\n\tO_42 Overflow8 = -42\n\tO_41 Overflow8 = -41\n\tO_40 Overflow8 = -40\n\tO_39 Overflow8 = -39\n\tO_38 Overflow8 = -38\n\tO_37 Overflow8 = -37\n\tO_36 Overflow8 = -36\n\tO_35 Overflow8 = -35\n\tO_34 Overflow8 = -34\n\tO_33 Overflow8 = -33\n\tO_32 Overflow8 = -32\n\tO_31 Overflow8 = -31\n\tO_30 Overflow8 = -30\n\tO_29 Overflow8 = -29\n\tO_28 Overflow8 = -28\n\tO_27 Overflow8 = -27\n\tO_26 Overflow8 = -26\n\tO_25 Overflow8 = -25\n\tO_24 Overflow8 = -24\n\tO_23 Overflow8 = -23\n\tO_22 Overflow8 = -22\n\tO_21 Overflow8 = -21\n\tO_20 Overflow8 = -20\n\tO_19 Overflow8 = -19\n\tO_18 Overflow8 = -18\n\tO_17 Overflow8 = -17\n\tO_16 Overflow8 = -16\n\tO_15 Overflow8 = -15\n\tO_14 Overflow8 = -14\n\tO_13 Overflow8 = -13\n\tO_12 Overflow8 = -12\n\tO_11 Overflow8 = -11\n\tO_10 Overflow8 = -10\n\tO_9 Overflow8 = -9\n\tO_8 Overflow8 = -8\n\tO_7 Overflow8 = -7\n\tO_6 Overflow8 = -6\n\tO_5 Overflow8 = -5\n\tO_4 Overflow8 = -4\n\tO_3 Overflow8 = -3\n\tO_2 Overflow8 = -2\n\tO_1 Overflow8 = -1\n\tO0 Overflow8 = 0\n\tO1 Overflow8 = 1\n\tO2 Overflow8 = 2\n\tO3 Overflow8 = 3\n\tO4 Overflow8 = 4\n\tO5 Overflow8 = 5\n\tO6 Overflow8 = 6\n\tO7 Overflow8 = 7\n\tO8 Overflow8 = 8\n\tO9 Overflow8 = 9\n\tO10 Overflow8 = 10\n\tO11 Overflow8 = 11\n\tO12 Overflow8 = 12\n\tO13 Overflow8 = 13\n\tO14 Overflow8 = 14\n\tO15 Overflow8 = 15\n\tO16 Overflow8 = 16\n\tO17 Overflow8 = 17\n\tO18 Overflow8 = 18\n\tO19 Overflow8 = 19\n\tO20 Overflow8 = 20\n\tO21 Overflow8 = 21\n\tO22 Overflow8 = 22\n\tO23 Overflow8 = 23\n\tO24 Overflow8 = 24\n\tO25 Overflow8 = 25\n\tO26 Overflow8 = 26\n\tO27 Overflow8 = 27\n\tO28 Overflow8 = 28\n\tO29 Overflow8 = 29\n\tO30 Overflow8 = 30\n\tO31 Overflow8 = 31\n\tO32 Overflow8 = 32\n\tO33 Overflow8 = 33\n\tO34 Overflow8 = 34\n\tO35 Overflow8 = 35\n\tO36 Overflow8 = 36\n\tO37 Overflow8 = 37\n\tO38 Overflow8 = 38\n\tO39 Overflow8 = 39\n\tO40 Overflow8 = 40\n\tO41 Overflow8 = 41\n\tO42 Overflow8 = 42\n\tO43 Overflow8 = 43\n\tO44 Overflow8 = 44\n\tO45 Overflow8 = 45\n\tO46 Overflow8 = 46\n\tO47 Overflow8 = 47\n\tO48 Overflow8 = 48\n\tO49 Overflow8 = 49\n\tO50 Overflow8 = 50\n\tO51 Overflow8 = 51\n\tO52 Overflow8 = 52\n\tO53 Overflow8 = 53\n\tO54 Overflow8 = 54\n\tO55 Overflow8 = 55\n\tO56 Overflow8 = 56\n\tO57 Overflow8 = 57\n\tO58 Overflow8 = 58\n\tO59 Overflow8 = 59\n\tO60 Overflow8 = 60\n\tO61 Overflow8 = 61\n\tO62 Overflow8 = 62\n\tO63 Overflow8 = 63\n\tO64 Overflow8 = 64\n\tO65 Overflow8 = 65\n\tO66 Overflow8 = 66\n\tO67 Overflow8 = 67\n\tO68 Overflow8 = 68\n\tO69 Overflow8 = 69\n\tO70 Overflow8 = 70\n\tO71 Overflow8 = 71\n\tO72 Overflow8 = 72\n\tO73 Overflow8 = 73\n\tO74 Overflow8 = 74\n\tO75 Overflow8 = 75\n\tO76 Overflow8 = 76\n\tO77 Overflow8 = 77\n\tO78 Overflow8 = 78\n\tO79 Overflow8 = 79\n\tO80 Overflow8 = 80\n\tO81 Overflow8 = 81\n\tO82 Overflow8 = 82\n\tO83 Overflow8 = 83\n\tO84 Overflow8 = 84\n\tO85 Overflow8 = 85\n\tO86 Overflow8 = 86\n\tO87 Overflow8 = 87\n\tO88 Overflow8 = 88\n\tO89 Overflow8 = 89\n\tO90 Overflow8 = 90\n\tO91 Overflow8 = 91\n\tO92 Overflow8 = 92\n\tO93 Overflow8 = 93\n\tO94 Overflow8 = 94\n\tO95 Overflow8 = 95\n\tO96 Overflow8 = 96\n\tO97 Overflow8 = 97\n\tO98 Overflow8 = 98\n\tO99 Overflow8 = 99\n\tO100 Overflow8 = 100\n\tO101 Overflow8 = 101\n\tO102 Overflow8 = 102\n\tO103 Overflow8 = 103\n\tO104 Overflow8 = 104\n\tO105 Overflow8 = 105\n\tO106 Overflow8 = 106\n\tO107 Overflow8 = 107\n\tO108 Overflow8 = 108\n\tO109 Overflow8 = 109\n\tO110 Overflow8 = 110\n\tO111 Overflow8 = 111\n\tO112 Overflow8 = 112\n\tO113 Overflow8 = 113\n\tO114 Overflow8 = 114\n\tO115 Overflow8 = 115\n\tO116 Overflow8 = 116\n\tO117 Overflow8 = 117\n\tO118 Overflow8 = 118\n\tO119 Overflow8 = 119\n\tO120 Overflow8 = 120\n\tO121 Overflow8 = 121\n\tO122 Overflow8 = 122\n\tO123 Overflow8 = 123\n\tO124 Overflow8 = 124\n\tO125 Overflow8 = 125\n\tO126 Overflow8 = 126\n\tO127 Overflow8 = 127\n)\n`\n\nconst overflow8_out = `func _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[O_128 - -128]\n\t_ = x[O_127 - -127]\n\t_ = x[O_126 - -126]\n\t_ = x[O_125 - -125]\n\t_ = x[O_124 - -124]\n\t_ = x[O_123 - -123]\n\t_ = x[O_122 - -122]\n\t_ = x[O_121 - -121]\n\t_ = x[O_120 - -120]\n\t_ = x[O_119 - -119]\n\t_ = x[O_118 - -118]\n\t_ = x[O_117 - -117]\n\t_ = x[O_116 - -116]\n\t_ = x[O_115 - -115]\n\t_ = x[O_114 - -114]\n\t_ = x[O_113 - -113]\n\t_ = x[O_112 - -112]\n\t_ = x[O_111 - -111]\n\t_ = x[O_110 - -110]\n\t_ = x[O_109 - -109]\n\t_ = x[O_108 - -108]\n\t_ = x[O_107 - -107]\n\t_ = x[O_106 - -106]\n\t_ = x[O_105 - -105]\n\t_ = x[O_104 - -104]\n\t_ = x[O_103 - -103]\n\t_ = x[O_102 - -102]\n\t_ = x[O_101 - -101]\n\t_ = x[O_100 - -100]\n\t_ = x[O_99 - -99]\n\t_ = x[O_98 - -98]\n\t_ = x[O_97 - -97]\n\t_ = x[O_96 - -96]\n\t_ = x[O_95 - -95]\n\t_ = x[O_94 - -94]\n\t_ = x[O_93 - -93]\n\t_ = x[O_92 - -92]\n\t_ = x[O_91 - -91]\n\t_ = x[O_90 - -90]\n\t_ = x[O_89 - -89]\n\t_ = x[O_88 - -88]\n\t_ = x[O_87 - -87]\n\t_ = x[O_86 - -86]\n\t_ = x[O_85 - -85]\n\t_ = x[O_84 - -84]\n\t_ = x[O_83 - -83]\n\t_ = x[O_82 - -82]\n\t_ = x[O_81 - -81]\n\t_ = x[O_80 - -80]\n\t_ = x[O_79 - -79]\n\t_ = x[O_78 - -78]\n\t_ = x[O_77 - -77]\n\t_ = x[O_76 - -76]\n\t_ = x[O_75 - -75]\n\t_ = x[O_74 - -74]\n\t_ = x[O_73 - -73]\n\t_ = x[O_72 - -72]\n\t_ = x[O_71 - -71]\n\t_ = x[O_70 - -70]\n\t_ = x[O_69 - -69]\n\t_ = x[O_68 - -68]\n\t_ = x[O_67 - -67]\n\t_ = x[O_66 - -66]\n\t_ = x[O_65 - -65]\n\t_ = x[O_64 - -64]\n\t_ = x[O_63 - -63]\n\t_ = x[O_62 - -62]\n\t_ = x[O_61 - -61]\n\t_ = x[O_60 - -60]\n\t_ = x[O_59 - -59]\n\t_ = x[O_58 - -58]\n\t_ = x[O_57 - -57]\n\t_ = x[O_56 - -56]\n\t_ = x[O_55 - -55]\n\t_ = x[O_54 - -54]\n\t_ = x[O_53 - -53]\n\t_ = x[O_52 - -52]\n\t_ = x[O_51 - -51]\n\t_ = x[O_50 - -50]\n\t_ = x[O_49 - -49]\n\t_ = x[O_48 - -48]\n\t_ = x[O_47 - -47]\n\t_ = x[O_46 - -46]\n\t_ = x[O_45 - -45]\n\t_ = x[O_44 - -44]\n\t_ = x[O_43 - -43]\n\t_ = x[O_42 - -42]\n\t_ = x[O_41 - -41]\n\t_ = x[O_40 - -40]\n\t_ = x[O_39 - -39]\n\t_ = x[O_38 - -38]\n\t_ = x[O_37 - -37]\n\t_ = x[O_36 - -36]\n\t_ = x[O_35 - -35]\n\t_ = x[O_34 - -34]\n\t_ = x[O_33 - -33]\n\t_ = x[O_32 - -32]\n\t_ = x[O_31 - -31]\n\t_ = x[O_30 - -30]\n\t_ = x[O_29 - -29]\n\t_ = x[O_28 - -28]\n\t_ = x[O_27 - -27]\n\t_ = x[O_26 - -26]\n\t_ = x[O_25 - -25]\n\t_ = x[O_24 - -24]\n\t_ = x[O_23 - -23]\n\t_ = x[O_22 - -22]\n\t_ = x[O_21 - -21]\n\t_ = x[O_20 - -20]\n\t_ = x[O_19 - -19]\n\t_ = x[O_18 - -18]\n\t_ = x[O_17 - -17]\n\t_ = x[O_16 - -16]\n\t_ = x[O_15 - -15]\n\t_ = x[O_14 - -14]\n\t_ = x[O_13 - -13]\n\t_ = x[O_12 - -12]\n\t_ = x[O_11 - -11]\n\t_ = x[O_10 - -10]\n\t_ = x[O_9 - -9]\n\t_ = x[O_8 - -8]\n\t_ = x[O_7 - -7]\n\t_ = x[O_6 - -6]\n\t_ = x[O_5 - -5]\n\t_ = x[O_4 - -4]\n\t_ = x[O_3 - -3]\n\t_ = x[O_2 - -2]\n\t_ = x[O_1 - -1]\n\t_ = x[O0-0]\n\t_ = x[O1-1]\n\t_ = x[O2-2]\n\t_ = x[O3-3]\n\t_ = x[O4-4]\n\t_ = x[O5-5]\n\t_ = x[O6-6]\n\t_ = x[O7-7]\n\t_ = x[O8-8]\n\t_ = x[O9-9]\n\t_ = x[O10-10]\n\t_ = x[O11-11]\n\t_ = x[O12-12]\n\t_ = x[O13-13]\n\t_ = x[O14-14]\n\t_ = x[O15-15]\n\t_ = x[O16-16]\n\t_ = x[O17-17]\n\t_ = x[O18-18]\n\t_ = x[O19-19]\n\t_ = x[O20-20]\n\t_ = x[O21-21]\n\t_ = x[O22-22]\n\t_ = x[O23-23]\n\t_ = x[O24-24]\n\t_ = x[O25-25]\n\t_ = x[O26-26]\n\t_ = x[O27-27]\n\t_ = x[O28-28]\n\t_ = x[O29-29]\n\t_ = x[O30-30]\n\t_ = x[O31-31]\n\t_ = x[O32-32]\n\t_ = x[O33-33]\n\t_ = x[O34-34]\n\t_ = x[O35-35]\n\t_ = x[O36-36]\n\t_ = x[O37-37]\n\t_ = x[O38-38]\n\t_ = x[O39-39]\n\t_ = x[O40-40]\n\t_ = x[O41-41]\n\t_ = x[O42-42]\n\t_ = x[O43-43]\n\t_ = x[O44-44]\n\t_ = x[O45-45]\n\t_ = x[O46-46]\n\t_ = x[O47-47]\n\t_ = x[O48-48]\n\t_ = x[O49-49]\n\t_ = x[O50-50]\n\t_ = x[O51-51]\n\t_ = x[O52-52]\n\t_ = x[O53-53]\n\t_ = x[O54-54]\n\t_ = x[O55-55]\n\t_ = x[O56-56]\n\t_ = x[O57-57]\n\t_ = x[O58-58]\n\t_ = x[O59-59]\n\t_ = x[O60-60]\n\t_ = x[O61-61]\n\t_ = x[O62-62]\n\t_ = x[O63-63]\n\t_ = x[O64-64]\n\t_ = x[O65-65]\n\t_ = x[O66-66]\n\t_ = x[O67-67]\n\t_ = x[O68-68]\n\t_ = x[O69-69]\n\t_ = x[O70-70]\n\t_ = x[O71-71]\n\t_ = x[O72-72]\n\t_ = x[O73-73]\n\t_ = x[O74-74]\n\t_ = x[O75-75]\n\t_ = x[O76-76]\n\t_ = x[O77-77]\n\t_ = x[O78-78]\n\t_ = x[O79-79]\n\t_ = x[O80-80]\n\t_ = x[O81-81]\n\t_ = x[O82-82]\n\t_ = x[O83-83]\n\t_ = x[O84-84]\n\t_ = x[O85-85]\n\t_ = x[O86-86]\n\t_ = x[O87-87]\n\t_ = x[O88-88]\n\t_ = x[O89-89]\n\t_ = x[O90-90]\n\t_ = x[O91-91]\n\t_ = x[O92-92]\n\t_ = x[O93-93]\n\t_ = x[O94-94]\n\t_ = x[O95-95]\n\t_ = x[O96-96]\n\t_ = x[O97-97]\n\t_ = x[O98-98]\n\t_ = x[O99-99]\n\t_ = x[O100-100]\n\t_ = x[O101-101]\n\t_ = x[O102-102]\n\t_ = x[O103-103]\n\t_ = x[O104-104]\n\t_ = x[O105-105]\n\t_ = x[O106-106]\n\t_ = x[O107-107]\n\t_ = x[O108-108]\n\t_ = x[O109-109]\n\t_ = x[O110-110]\n\t_ = x[O111-111]\n\t_ = x[O112-112]\n\t_ = x[O113-113]\n\t_ = x[O114-114]\n\t_ = x[O115-115]\n\t_ = x[O116-116]\n\t_ = x[O117-117]\n\t_ = x[O118-118]\n\t_ = x[O119-119]\n\t_ = x[O120-120]\n\t_ = x[O121-121]\n\t_ = x[O122-122]\n\t_ = x[O123-123]\n\t_ = x[O124-124]\n\t_ = x[O125-125]\n\t_ = x[O126-126]\n\t_ = x[O127-127]\n}\n\nconst _Overflow8_name = \"O_128O_127O_126O_125O_124O_123O_122O_121O_120O_119O_118O_117O_116O_115O_114O_113O_112O_111O_110O_109O_108O_107O_106O_105O_104O_103O_102O_101O_100O_99O_98O_97O_96O_95O_94O_93O_92O_91O_90O_89O_88O_87O_86O_85O_84O_83O_82O_81O_80O_79O_78O_77O_76O_75O_74O_73O_72O_71O_70O_69O_68O_67O_66O_65O_64O_63O_62O_61O_60O_59O_58O_57O_56O_55O_54O_53O_52O_51O_50O_49O_48O_47O_46O_45O_44O_43O_42O_41O_40O_39O_38O_37O_36O_35O_34O_33O_32O_31O_30O_29O_28O_27O_26O_25O_24O_23O_22O_21O_20O_19O_18O_17O_16O_15O_14O_13O_12O_11O_10O_9O_8O_7O_6O_5O_4O_3O_2O_1O0O1O2O3O4O5O6O7O8O9O10O11O12O13O14O15O16O17O18O19O20O21O22O23O24O25O26O27O28O29O30O31O32O33O34O35O36O37O38O39O40O41O42O43O44O45O46O47O48O49O50O51O52O53O54O55O56O57O58O59O60O61O62O63O64O65O66O67O68O69O70O71O72O73O74O75O76O77O78O79O80O81O82O83O84O85O86O87O88O89O90O91O92O93O94O95O96O97O98O99O100O101O102O103O104O105O106O107O108O109O110O111O112O113O114O115O116O117O118O119O120O121O122O123O124O125O126O127\"\n\nvar _Overflow8_index = [...]uint16{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 508, 511, 514, 517, 520, 523, 526, 529, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 555, 558, 561, 564, 567, 570, 573, 576, 579, 582, 585, 588, 591, 594, 597, 600, 603, 606, 609, 612, 615, 618, 621, 624, 627, 630, 633, 636, 639, 642, 645, 648, 651, 654, 657, 660, 663, 666, 669, 672, 675, 678, 681, 684, 687, 690, 693, 696, 699, 702, 705, 708, 711, 714, 717, 720, 723, 726, 729, 732, 735, 738, 741, 744, 747, 750, 753, 756, 759, 762, 765, 768, 771, 774, 777, 780, 783, 786, 789, 792, 795, 798, 801, 804, 807, 810, 813, 816, 819, 822, 826, 830, 834, 838, 842, 846, 850, 854, 858, 862, 866, 870, 874, 878, 882, 886, 890, 894, 898, 902, 906, 910, 914, 918, 922, 926, 930, 934}\n\nfunc (i Overflow8) String() string {\n\tidx := int(i) - -128\n\tif i < -128 || idx >= len(_Overflow8_index)-1 {\n\t\treturn \"Overflow8(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Overflow8_name[_Overflow8_index[idx]:_Overflow8_index[idx+1]]\n}\n`\n\nfunc TestGolden(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tdir := t.TempDir()\n\tfor _, test := range golden {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tinput := \"package test\\n\" + test.input\n\t\t\tfile := test.name + \".go\"\n\t\t\tabsFile := filepath.Join(dir, file)\n\t\t\terr := os.WriteFile(absFile, []byte(input), 0644)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tpkgs := loadPackages([]string{absFile}, nil, test.trimPrefix, test.lineComment, t.Logf)\n\t\t\tif len(pkgs) != 1 {\n\t\t\t\tt.Fatalf(\"got %d parsed packages but expected 1\", len(pkgs))\n\t\t\t}\n\t\t\t// Extract the name and type of the constant from the first line.\n\t\t\ttokens := strings.SplitN(test.input, \" \", 3)\n\t\t\tif len(tokens) != 3 {\n\t\t\t\tt.Fatalf(\"%s: need type declaration on first line\", test.name)\n\t\t\t}\n\n\t\t\tg := Generator{\n\t\t\t\tpkg:  pkgs[0],\n\t\t\t\tlogf: t.Logf,\n\t\t\t}\n\t\t\tg.generate(tokens[1], findValues(tokens[1], pkgs[0]))\n\t\t\tgot := string(g.format())\n\t\t\tif got != test.output {\n\t\t\t\tt.Errorf(\"%s: got(%d)\\n====\\n%q====\\nexpected(%d)\\n====\\n%q\", test.name, len(got), got, len(test.output), test.output)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/multifile_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go1.23 is required for os.CopyFS.\n// !android is required for compatibility with endtoend_test.go.\n//go:build go1.23 && !android\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/diffp\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// This file contains a test that checks the output files existence\n// and content when stringer has types from multiple different input\n// files to choose from.\n//\n// Input is specified in a txtar string.\n\n// Several tests expect the type Foo generated in some package.\nfunc expectFooString(pkg string) []byte {\n\treturn fmt.Appendf(nil, `\n// Header comment ignored.\n\npackage %s\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[fooX-0]\n\t_ = x[fooY-1]\n\t_ = x[fooZ-2]\n}\n\nconst _Foo_name = \"fooXfooYfooZ\"\n\nvar _Foo_index = [...]uint8{0, 4, 8, 12}\n\nfunc (i Foo) String() string {\n\tidx := int(i) - 0\n\tif i < 0 || idx >= len(_Foo_index)-1 {\n\t\treturn \"Foo(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Foo_name[_Foo_index[idx]:_Foo_index[idx+1]]\n}`, pkg)\n}\n\nfunc TestMultifileStringer(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\tstringer := stringerPath(t)\n\n\ttests := []struct {\n\t\tname        string\n\t\targs        []string\n\t\tarchive     []byte\n\t\texpectFiles map[string][]byte\n\t}{\n\t\t{\n\t\t\tname: \"package only\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"test package only\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\nfunc main() {}\n\n-- main_test.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string_test.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"x_test package only\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\nfunc main() {}\n\n-- main_test.go --\npackage main_test\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string_test.go\": expectFooString(\"main_test\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// Re-declaring the type in a less prioritized package does not change our output.\n\t\t\tname: \"package over test package\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)\n\n-- main_test.go --\npackage main\n\ntype Foo int\n\nconst (\n\totherX Foo = iota\n\totherY\n\totherZ\n)\n`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// Re-declaring the type in a less prioritized package does not change our output.\n\t\t\tname: \"package over x_test package\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)\n\n-- main_test.go --\npackage main_test\n\ntype Foo int\n\nconst (\n\totherX Foo = iota\n\totherY\n\totherZ\n)\n`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// Re-declaring the type in a less prioritized package does not change our output.\n\t\t\tname: \"test package over x_test package\",\n\t\t\targs: []string{\"-type=Foo\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\n-- main_test.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)\n\n-- main_pkg_test.go --\npackage main_test\n\ntype Foo int\n\nconst (\n\totherX Foo = iota\n\totherY\n\totherZ\n)`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string_test.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"unique type in each package variant\",\n\t\t\targs: []string{\"-type=Foo,Bar,Baz\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\ntype Foo int\n\nconst fooX Foo = 1\n\n-- main_test.go --\npackage main\n\ntype Bar int\n\nconst barX Bar = 1\n\n-- main_pkg_test.go --\npackage main_test\n\ntype Baz int\n\nconst bazX Baz = 1\n`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"foo_string.go\": []byte(`\n// Header comment ignored.\n\npackage main\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[fooX-1]\n}\n\nconst _Foo_name = \"fooX\"\n\nvar _Foo_index = [...]uint8{0, 4}\n\nfunc (i Foo) String() string {\n\tidx := int(i) - 1\n\tif i < 1 || idx >= len(_Foo_index)-1 {\n\t\treturn \"Foo(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Foo_name[_Foo_index[idx]:_Foo_index[idx+1]]\n}`),\n\n\t\t\t\t\"bar_string_test.go\": []byte(`\n// Header comment ignored.\n\npackage main\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[barX-1]\n}\n\nconst _Bar_name = \"barX\"\n\nvar _Bar_index = [...]uint8{0, 4}\n\nfunc (i Bar) String() string {\n\tidx := int(i) - 1\n\tif i < 1 || idx >= len(_Bar_index)-1 {\n\t\treturn \"Bar(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Bar_name[_Bar_index[idx]:_Bar_index[idx+1]]\n}`),\n\n\t\t\t\t\"baz_string_test.go\": []byte(`\n// Header comment ignored.\n\npackage main_test\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[bazX-1]\n}\n\nconst _Baz_name = \"bazX\"\n\nvar _Baz_index = [...]uint8{0, 4}\n\nfunc (i Baz) String() string {\n\tidx := int(i) - 1\n\tif i < 1 || idx >= len(_Baz_index)-1 {\n\t\treturn \"Baz(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _Baz_name[_Baz_index[idx]:_Baz_index[idx+1]]\n}`),\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\tname: \"package over test package with custom output\",\n\t\t\targs: []string{\"-type=Foo\", \"-output=custom_output.go\"},\n\t\t\tarchive: []byte(`\n-- go.mod --\nmodule foo\n\n-- main.go --\npackage main\n\ntype Foo int\n\nconst (\n\tfooX Foo = iota\n\tfooY\n\tfooZ\n)\n\n-- main_test.go --\npackage main\n\ntype Foo int\n\nconst (\n\totherX Foo = iota\n\totherY\n\totherZ\n)`),\n\t\t\texpectFiles: map[string][]byte{\n\t\t\t\t\"custom_output.go\": expectFooString(\"main\"),\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ttmpDir := t.TempDir()\n\n\t\t\tarFS, err := txtar.FS(txtar.Parse(tt.archive))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"txtar.FS: %s\", err)\n\t\t\t}\n\t\t\terr = os.CopyFS(tmpDir, arFS)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"copy fs: %s\", err)\n\t\t\t}\n\t\t\tbefore := dirContent(t, tmpDir)\n\n\t\t\t// Must run stringer in the temp directory, see TestTags.\n\t\t\targs := append(tt.args, tmpDir)\n\t\t\terr = runInDir(t, tmpDir, stringer, args...)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"run stringer: %s\", err)\n\t\t\t}\n\n\t\t\t// Check that all !path files have been created with the expected content.\n\t\t\tfor f, want := range tt.expectFiles {\n\t\t\t\tgot, err := os.ReadFile(filepath.Join(tmpDir, f))\n\t\t\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\t\t\tt.Errorf(\"expected file not written during test: %s\", f)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"read file %q: %s\", f, err)\n\t\t\t\t}\n\t\t\t\t// Trim data for more robust comparison.\n\t\t\t\tgot = trimHeader(bytes.TrimSpace(got))\n\t\t\t\twant = trimHeader(bytes.TrimSpace(want))\n\t\t\t\tif !bytes.Equal(want, got) {\n\t\t\t\t\tt.Errorf(\"file %s does not have the expected content:\\n%s\", f, diffp.Diff(\"want\", want, \"got\", got))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check that nothing else has been created.\n\t\t\tafter := dirContent(t, tmpDir)\n\t\t\tfor f := range after {\n\t\t\t\tif _, expected := tt.expectFiles[f]; !expected && !before[f] {\n\t\t\t\t\tt.Errorf(\"found %q in output directory, it is neither input or expected output\", f)\n\t\t\t\t}\n\t\t\t}\n\n\t\t})\n\t}\n}\n\nfunc dirContent(t *testing.T, dir string) map[string]bool {\n\tentries, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"read dir: %s\", err)\n\t}\n\n\tout := map[string]bool{}\n\tfor _, e := range entries {\n\t\tout[e.Name()] = true\n\t}\n\treturn out\n}\n\n// trimHeader that stringer puts in file.\n// It depends on location and interferes with comparing file content.\nfunc trimHeader(s []byte) []byte {\n\tif !bytes.HasPrefix(s, []byte(\"//\")) {\n\t\treturn s\n\t}\n\t_, after, ok := bytes.Cut(s, []byte{'\\n'})\n\tif ok {\n\t\treturn after\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "cmd/stringer/stringer.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer\n// interface. Given the name of a (signed or unsigned) integer type T that has constants\n// defined, stringer will create a new self-contained Go source file implementing\n//\n//\tfunc (t T) String() string\n//\n// The file is created in the same package and directory as the package that defines T.\n// It has helpful defaults designed for use with go generate.\n//\n// Stringer works best with constants that are consecutive values such as created using iota,\n// but creates good code regardless. In the future it might also provide custom support for\n// constant sets that are bit patterns.\n//\n// For example, given this snippet,\n//\n//\tpackage painkiller\n//\n//\ttype Pill int\n//\n//\tconst (\n//\t\tPlacebo Pill = iota\n//\t\tAspirin\n//\t\tIbuprofen\n//\t\tParacetamol\n//\t\tAcetaminophen = Paracetamol\n//\t)\n//\n// running this command\n//\n//\tstringer -type=Pill\n//\n// in the same directory will create the file pill_string.go, in package painkiller,\n// containing a definition of\n//\n//\tfunc (Pill) String() string\n//\n// That method will translate the value of a Pill constant to the string representation\n// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will\n// print the string \"Aspirin\".\n//\n// Typically this process would be run using go generate, like this:\n//\n//\t//go:generate stringer -type=Pill\n//\n// If multiple constants have the same value, the lexically first matching name will\n// be used (in the example, Acetaminophen will print as \"Paracetamol\").\n//\n// With no arguments, it processes the package in the current directory.\n// Otherwise, the arguments must name a single directory holding a Go package\n// or a set of Go source files that represent a single Go package.\n//\n// The -type flag accepts a comma-separated list of types so a single run can\n// generate methods for multiple types. The default output file is t_string.go,\n// where t is the lower-cased name of the first type listed. It can be overridden\n// with the -output flag.\n//\n// Types can also be declared in tests, in which case type declarations in the\n// non-test package or its test variant are preferred over types defined in the\n// package with suffix \"_test\".\n// The default output file for type declarations in tests is t_string_test.go with t picked as above.\n//\n// The -linecomment flag tells stringer to generate the text of any line comment, trimmed\n// of leading spaces, instead of the constant name. For instance, if the constants above had a\n// Pill prefix, one could write\n//\n//\tPillAspirin // Aspirin\n//\n// to suppress it in the output.\n//\n// The -trimprefix flag specifies a prefix to remove from the constant names\n// when generating the string representations. For instance, -trimprefix=Pill\n// would be an alternative way to ensure that PillAspirin.String() == \"Aspirin\".\npackage main // import \"golang.org/x/tools/cmd/stringer\"\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\nvar (\n\ttypeNames   = flag.String(\"type\", \"\", \"comma-separated list of type names; must be set\")\n\toutput      = flag.String(\"output\", \"\", \"output file name; default srcdir/<type>_string.go\")\n\ttrimprefix  = flag.String(\"trimprefix\", \"\", \"trim the `prefix` from the generated constant names\")\n\tlinecomment = flag.Bool(\"linecomment\", false, \"use line comment text as printed text when present\")\n\tbuildTags   = flag.String(\"tags\", \"\", \"comma-separated list of build tags to apply\")\n)\n\n// Usage is a replacement usage function for the flags package.\nfunc Usage() {\n\tfmt.Fprintf(os.Stderr, \"Usage of stringer:\\n\")\n\tfmt.Fprintf(os.Stderr, \"\\tstringer [flags] -type T [directory]\\n\")\n\tfmt.Fprintf(os.Stderr, \"\\tstringer [flags] -type T files... # Must be a single package\\n\")\n\tfmt.Fprintf(os.Stderr, \"For more information, see:\\n\")\n\tfmt.Fprintf(os.Stderr, \"\\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\\n\")\n\tfmt.Fprintf(os.Stderr, \"Flags:\\n\")\n\tflag.PrintDefaults()\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"stringer: \")\n\tflag.Usage = Usage\n\tflag.Parse()\n\tif len(*typeNames) == 0 {\n\t\tflag.Usage()\n\t\tos.Exit(2)\n\t}\n\ttypes := strings.Split(*typeNames, \",\")\n\tvar tags []string\n\tif len(*buildTags) > 0 {\n\t\ttags = strings.Split(*buildTags, \",\")\n\t}\n\n\t// We accept either one directory or a list of files. Which do we have?\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\t// Default: process whole package in current directory.\n\t\targs = []string{\".\"}\n\t}\n\n\t// Parse the package once.\n\tvar dir string\n\t// TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc).\n\tif len(args) == 1 && isDirectory(args[0]) {\n\t\tdir = args[0]\n\t} else {\n\t\tif len(tags) != 0 {\n\t\t\tlog.Fatal(\"-tags option applies only to directories, not when files are specified\")\n\t\t}\n\t\tdir = filepath.Dir(args[0])\n\t}\n\n\t// For each type, generate code in the first package where the type is declared.\n\t// The order of packages is as follows:\n\t// package x\n\t// package x compiled for tests\n\t// package x_test\n\t//\n\t// Each package pass could result in a separate generated file.\n\t// These files must have the same package and test/not-test nature as the types\n\t// from which they were generated.\n\t//\n\t// Types will be excluded when generated, to avoid repetitions.\n\tpkgs := loadPackages(args, tags, *trimprefix, *linecomment, nil /* logf */)\n\tsort.Slice(pkgs, func(i, j int) bool {\n\t\t// Put x_test packages last.\n\t\tiTest := strings.HasSuffix(pkgs[i].name, \"_test\")\n\t\tjTest := strings.HasSuffix(pkgs[j].name, \"_test\")\n\t\tif iTest != jTest {\n\t\t\treturn !iTest\n\t\t}\n\n\t\treturn len(pkgs[i].files) < len(pkgs[j].files)\n\t})\n\tfor _, pkg := range pkgs {\n\t\tg := Generator{\n\t\t\tpkg: pkg,\n\t\t}\n\n\t\t// Print the header and package clause.\n\t\tg.Printf(\"// Code generated by \\\"stringer %s\\\"; DO NOT EDIT.\\n\", strings.Join(os.Args[1:], \" \"))\n\t\tg.Printf(\"\\n\")\n\t\tg.Printf(\"package %s\", g.pkg.name)\n\t\tg.Printf(\"\\n\")\n\t\tg.Printf(\"import \\\"strconv\\\"\\n\") // Used by all methods.\n\n\t\t// Run generate for types that can be found. Keep the rest for the remainingTypes iteration.\n\t\tvar foundTypes, remainingTypes []string\n\t\tfor _, typeName := range types {\n\t\t\tvalues := findValues(typeName, pkg)\n\t\t\tif len(values) > 0 {\n\t\t\t\tg.generate(typeName, values)\n\t\t\t\tfoundTypes = append(foundTypes, typeName)\n\t\t\t} else {\n\t\t\t\tremainingTypes = append(remainingTypes, typeName)\n\t\t\t}\n\t\t}\n\t\tif len(foundTypes) == 0 {\n\t\t\t// This package didn't have any of the relevant types, skip writing a file.\n\t\t\tcontinue\n\t\t}\n\t\tif len(remainingTypes) > 0 && output != nil && *output != \"\" {\n\t\t\tlog.Fatalf(\"cannot write to single file (-output=%q) when matching types are found in multiple packages\", *output)\n\t\t}\n\t\ttypes = remainingTypes\n\n\t\t// Format the output.\n\t\tsrc := g.format()\n\n\t\t// Write to file.\n\t\toutputName := *output\n\t\tif outputName == \"\" {\n\t\t\t// Type names will be unique across packages since only the first\n\t\t\t// match is picked.\n\t\t\t// So there won't be collisions between a package compiled for tests\n\t\t\t// and the separate package of tests (package foo_test).\n\t\t\toutputName = filepath.Join(dir, baseName(pkg, foundTypes[0]))\n\t\t}\n\t\terr := os.WriteFile(outputName, src, 0o644)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"writing output: %s\", err)\n\t\t}\n\t}\n\n\tif len(types) > 0 {\n\t\tlog.Fatalf(\"no values defined for types: %s\", strings.Join(types, \",\"))\n\t}\n}\n\n// baseName that will put the generated code together with pkg.\nfunc baseName(pkg *Package, typename string) string {\n\tsuffix := \"string.go\"\n\tif pkg.hasTestFiles {\n\t\tsuffix = \"string_test.go\"\n\t}\n\treturn fmt.Sprintf(\"%s_%s\", strings.ToLower(typename), suffix)\n}\n\n// isDirectory reports whether the named file is a directory.\nfunc isDirectory(name string) bool {\n\tinfo, err := os.Stat(name)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn info.IsDir()\n}\n\n// Generator holds the state of the analysis. Primarily used to buffer\n// the output for format.Source.\ntype Generator struct {\n\tbuf bytes.Buffer // Accumulated output.\n\tpkg *Package     // Package we are scanning.\n\n\tlogf func(format string, args ...any) // test logging hook; nil when not testing\n}\n\nfunc (g *Generator) Printf(format string, args ...any) {\n\tfmt.Fprintf(&g.buf, format, args...)\n}\n\n// File holds a single parsed file and associated data.\ntype File struct {\n\tpkg  *Package  // Package to which this file belongs.\n\tfile *ast.File // Parsed AST.\n\t// These fields are reset for each type being generated.\n\ttypeName string  // Name of the constant type.\n\tvalues   []Value // Accumulator for constant values of that type.\n\n\ttrimPrefix  string\n\tlineComment bool\n}\n\ntype Package struct {\n\tname         string\n\tdefs         map[*ast.Ident]types.Object\n\tfiles        []*File\n\thasTestFiles bool\n}\n\n// loadPackages analyzes the single package constructed from the patterns and tags.\n// loadPackages exits if there is an error.\n//\n// Returns all variants (such as tests) of the package.\n//\n// logf is a test logging hook. It can be nil when not testing.\nfunc loadPackages(\n\tpatterns, tags []string,\n\ttrimPrefix string, lineComment bool,\n\tlogf func(format string, args ...any),\n) []*Package {\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedFiles,\n\t\t// Tests are included, let the caller decide how to fold them in.\n\t\tTests:      true,\n\t\tBuildFlags: []string{fmt.Sprintf(\"-tags=%s\", strings.Join(tags, \" \"))},\n\t\tLogf:       logf,\n\t}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif len(pkgs) == 0 {\n\t\tlog.Fatalf(\"error: no packages matching %v\", strings.Join(patterns, \" \"))\n\t}\n\n\tout := make([]*Package, len(pkgs))\n\tfor i, pkg := range pkgs {\n\t\tp := &Package{\n\t\t\tname:  pkg.Name,\n\t\t\tdefs:  pkg.TypesInfo.Defs,\n\t\t\tfiles: make([]*File, len(pkg.Syntax)),\n\t\t}\n\n\t\tfor j, file := range pkg.Syntax {\n\t\t\tp.files[j] = &File{\n\t\t\t\tfile: file,\n\t\t\t\tpkg:  p,\n\n\t\t\t\ttrimPrefix:  trimPrefix,\n\t\t\t\tlineComment: lineComment,\n\t\t\t}\n\t\t}\n\n\t\t// Keep track of test files, since we might want to generated\n\t\t// code that ends up in that kind of package.\n\t\t// Can be replaced once https://go.dev/issue/38445 lands.\n\t\tfor _, f := range pkg.GoFiles {\n\t\t\tif strings.HasSuffix(f, \"_test.go\") {\n\t\t\t\tp.hasTestFiles = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tout[i] = p\n\t}\n\treturn out\n}\n\nfunc findValues(typeName string, pkg *Package) []Value {\n\tvalues := make([]Value, 0, 100)\n\tfor _, file := range pkg.files {\n\t\t// Set the state for this run of the walker.\n\t\tfile.typeName = typeName\n\t\tfile.values = nil\n\t\tif file.file != nil {\n\t\t\tast.Inspect(file.file, file.genDecl)\n\t\t\tvalues = append(values, file.values...)\n\t\t}\n\t}\n\treturn values\n}\n\n// generate produces the String method for the named type.\nfunc (g *Generator) generate(typeName string, values []Value) {\n\t// Generate code that will fail if the constants change value.\n\tg.Printf(\"func _() {\\n\")\n\tg.Printf(\"\\t// An \\\"invalid array index\\\" compiler error signifies that the constant values have changed.\\n\")\n\tg.Printf(\"\\t// Re-run the stringer command to generate them again.\\n\")\n\tg.Printf(\"\\tvar x [1]struct{}\\n\")\n\tfor _, v := range values {\n\t\tg.Printf(\"\\t_ = x[%s - %s]\\n\", v.originalName, v.str)\n\t}\n\tg.Printf(\"}\\n\")\n\truns := splitIntoRuns(values)\n\t// The decision of which pattern to use depends on the number of\n\t// runs in the numbers. If there's only one, it's easy. For more than\n\t// one, there's a tradeoff between complexity and size of the data\n\t// and code vs. the simplicity of a map. A map takes more space,\n\t// but so does the code. The decision here (crossover at 10) is\n\t// arbitrary, but considers that for large numbers of runs the cost\n\t// of the linear scan in the switch might become important, and\n\t// rather than use yet another algorithm such as binary search,\n\t// we punt and use a map. In any case, the likelihood of a map\n\t// being necessary for any realistic example other than bitmasks\n\t// is very low. And bitmasks probably deserve their own analysis,\n\t// to be done some other day.\n\tswitch {\n\tcase len(runs) == 1:\n\t\tg.buildOneRun(runs, typeName)\n\tcase len(runs) <= 10:\n\t\tg.buildMultipleRuns(runs, typeName)\n\tdefault:\n\t\tg.buildMap(runs, typeName)\n\t}\n}\n\n// splitIntoRuns breaks the values into runs of contiguous sequences.\n// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.\n// The input slice is known to be non-empty.\nfunc splitIntoRuns(values []Value) [][]Value {\n\t// We use stable sort so the lexically first name is chosen for equal elements.\n\tsort.Stable(byValue(values))\n\t// Remove duplicates. Stable sort has put the one we want to print first,\n\t// so use that one. The String method won't care about which named constant\n\t// was the argument, so the first name for the given value is the only one to keep.\n\t// We need to do this because identical values would cause the switch or map\n\t// to fail to compile.\n\tj := 1\n\tfor i := 1; i < len(values); i++ {\n\t\tif values[i].value != values[i-1].value {\n\t\t\tvalues[j] = values[i]\n\t\t\tj++\n\t\t}\n\t}\n\tvalues = values[:j]\n\truns := make([][]Value, 0, 10)\n\tfor len(values) > 0 {\n\t\t// One contiguous sequence per outer loop.\n\t\ti := 1\n\t\tfor i < len(values) && values[i].value == values[i-1].value+1 {\n\t\t\ti++\n\t\t}\n\t\truns = append(runs, values[:i])\n\t\tvalues = values[i:]\n\t}\n\treturn runs\n}\n\n// format returns the gofmt-ed contents of the Generator's buffer.\nfunc (g *Generator) format() []byte {\n\tsrc, err := format.Source(g.buf.Bytes())\n\tif err != nil {\n\t\t// Should never happen, but can arise when developing this code.\n\t\t// The user can compile the output to see the error.\n\t\tlog.Printf(\"warning: internal error: invalid Go generated: %s\", err)\n\t\tlog.Printf(\"warning: compile the package to analyze the error\")\n\t\treturn g.buf.Bytes()\n\t}\n\treturn src\n}\n\n// Value represents a declared constant.\ntype Value struct {\n\toriginalName string // The name of the constant.\n\tname         string // The name with trimmed prefix.\n\t// The value is stored as a bit pattern alone. The boolean tells us\n\t// whether to interpret it as an int64 or a uint64; the only place\n\t// this matters is when sorting.\n\t// Much of the time the str field is all we need; it is printed\n\t// by Value.String.\n\tvalue  uint64 // Will be converted to int64 when needed.\n\tsigned bool   // Whether the constant is a signed type.\n\tstr    string // The string representation given by the \"go/constant\" package.\n}\n\nfunc (v *Value) String() string {\n\treturn v.str\n}\n\n// byValue lets us sort the constants into increasing order.\n// We take care in the Less method to sort in signed or unsigned order,\n// as appropriate.\ntype byValue []Value\n\nfunc (b byValue) Len() int      { return len(b) }\nfunc (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }\nfunc (b byValue) Less(i, j int) bool {\n\tif b[i].signed {\n\t\treturn int64(b[i].value) < int64(b[j].value)\n\t}\n\treturn b[i].value < b[j].value\n}\n\n// genDecl processes one declaration clause.\nfunc (f *File) genDecl(node ast.Node) bool {\n\tdecl, ok := node.(*ast.GenDecl)\n\tif !ok || decl.Tok != token.CONST {\n\t\t// We only care about const declarations.\n\t\treturn true\n\t}\n\t// The name of the type of the constants we are declaring.\n\t// Can change if this is a multi-element declaration.\n\ttyp := \"\"\n\t// Loop over the elements of the declaration. Each element is a ValueSpec:\n\t// a list of names possibly followed by a type, possibly followed by values.\n\t// If the type and value are both missing, we carry down the type (and value,\n\t// but the \"go/types\" package takes care of that).\n\tfor _, spec := range decl.Specs {\n\t\tvspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.\n\t\tif vspec.Type == nil && len(vspec.Values) > 0 {\n\t\t\t// \"X = 1\". With no type but a value. If the constant is untyped,\n\t\t\t// skip this vspec and reset the remembered type.\n\t\t\ttyp = \"\"\n\n\t\t\t// If this is a simple type conversion, remember the type.\n\t\t\t// We don't mind if this is actually a call; a qualified call won't\n\t\t\t// be matched (that will be SelectorExpr, not Ident), and only unusual\n\t\t\t// situations will result in a function call that appears to be\n\t\t\t// a type conversion.\n\t\t\tce, ok := vspec.Values[0].(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tid, ok := ce.Fun.(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttyp = id.Name\n\t\t}\n\t\tif vspec.Type != nil {\n\t\t\t// \"X T\". We have a type. Remember it.\n\t\t\tident, ok := vspec.Type.(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttyp = ident.Name\n\t\t}\n\t\tif typ != f.typeName {\n\t\t\t// This is not the type we're looking for.\n\t\t\tcontinue\n\t\t}\n\t\t// We now have a list of names (from one line of source code) all being\n\t\t// declared with the desired type.\n\t\t// Grab their names and actual values and store them in f.values.\n\t\tfor _, name := range vspec.Names {\n\t\t\tif name.Name == \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// This dance lets the type checker find the values for us. It's a\n\t\t\t// bit tricky: look up the object declared by the name, find its\n\t\t\t// types.Const, and extract its value.\n\t\t\tobj, ok := f.pkg.defs[name]\n\t\t\tif !ok {\n\t\t\t\tlog.Fatalf(\"no value for constant %s\", name)\n\t\t\t}\n\t\t\tinfo := obj.Type().Underlying().(*types.Basic).Info()\n\t\t\tif info&types.IsInteger == 0 {\n\t\t\t\tlog.Fatalf(\"can't handle non-integer constant type %s\", typ)\n\t\t\t}\n\t\t\tvalue := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.\n\t\t\tif value.Kind() != constant.Int {\n\t\t\t\tlog.Fatalf(\"can't happen: constant is not an integer %s\", name)\n\t\t\t}\n\t\t\ti64, isInt := constant.Int64Val(value)\n\t\t\tu64, isUint := constant.Uint64Val(value)\n\t\t\tif !isInt && !isUint {\n\t\t\t\tlog.Fatalf(\"internal error: value of %s is not an integer: %s\", name, value.String())\n\t\t\t}\n\t\t\tif !isInt {\n\t\t\t\tu64 = uint64(i64)\n\t\t\t}\n\t\t\tv := Value{\n\t\t\t\toriginalName: name.Name,\n\t\t\t\tvalue:        u64,\n\t\t\t\tsigned:       info&types.IsUnsigned == 0,\n\t\t\t\tstr:          value.String(),\n\t\t\t}\n\t\t\tif c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {\n\t\t\t\tv.name = strings.TrimSpace(c.Text())\n\t\t\t} else {\n\t\t\t\tv.name = strings.TrimPrefix(v.originalName, f.trimPrefix)\n\t\t\t}\n\t\t\tf.values = append(f.values, v)\n\t\t}\n\t}\n\treturn false\n}\n\n// Helpers\n\n// usize returns the number of bits of the smallest unsigned integer\n// type that will hold n. Used to create the smallest possible slice of\n// integers to use as indexes into the concatenated strings.\nfunc usize(n int) int {\n\tswitch {\n\tcase n < 1<<8:\n\t\treturn 8\n\tcase n < 1<<16:\n\t\treturn 16\n\tdefault:\n\t\t// 2^32 is enough constants for anyone.\n\t\treturn 32\n\t}\n}\n\n// declareIndexAndNameVars declares the index slices and concatenated names\n// strings representing the runs of values.\nfunc (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {\n\tvar indexes, names []string\n\tfor i, run := range runs {\n\t\tindex, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf(\"_%d\", i))\n\t\tif len(run) != 1 {\n\t\t\tindexes = append(indexes, index)\n\t\t}\n\t\tnames = append(names, name)\n\t}\n\tg.Printf(\"const (\\n\")\n\tfor _, name := range names {\n\t\tg.Printf(\"\\t%s\\n\", name)\n\t}\n\tg.Printf(\")\\n\\n\")\n\n\tif len(indexes) > 0 {\n\t\tg.Printf(\"var (\")\n\t\tfor _, index := range indexes {\n\t\t\tg.Printf(\"\\t%s\\n\", index)\n\t\t}\n\t\tg.Printf(\")\\n\\n\")\n\t}\n}\n\n// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars\nfunc (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {\n\tindex, name := g.createIndexAndNameDecl(run, typeName, \"\")\n\tg.Printf(\"const %s\\n\", name)\n\tg.Printf(\"var %s\\n\", index)\n}\n\n// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add \"const\" and \"var\".\nfunc (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {\n\tb := new(bytes.Buffer)\n\tindexes := make([]int, len(run))\n\tfor i := range run {\n\t\tb.WriteString(run[i].name)\n\t\tindexes[i] = b.Len()\n\t}\n\tnameConst := fmt.Sprintf(\"_%s_name%s = %q\", typeName, suffix, b.String())\n\tnameLen := b.Len()\n\tb.Reset()\n\tfmt.Fprintf(b, \"_%s_index%s = [...]uint%d{0, \", typeName, suffix, usize(nameLen))\n\tfor i, v := range indexes {\n\t\tif i > 0 {\n\t\t\tfmt.Fprintf(b, \", \")\n\t\t}\n\t\tfmt.Fprintf(b, \"%d\", v)\n\t}\n\tfmt.Fprintf(b, \"}\")\n\treturn b.String(), nameConst\n}\n\n// declareNameVars declares the concatenated names string representing all the values in the runs.\nfunc (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {\n\tg.Printf(\"const _%s_name%s = \\\"\", typeName, suffix)\n\tfor _, run := range runs {\n\t\tfor i := range run {\n\t\t\tg.Printf(\"%s\", run[i].name)\n\t\t}\n\t}\n\tg.Printf(\"\\\"\\n\")\n}\n\n// buildOneRun generates the variables and String method for a single run of contiguous values.\nfunc (g *Generator) buildOneRun(runs [][]Value, typeName string) {\n\tvalues := runs[0]\n\tg.Printf(\"\\n\")\n\tg.declareIndexAndNameVar(values, typeName)\n\tg.Printf(stringOneRun, typeName, values[0].String())\n}\n\n// Arguments to format are:\n//\n//\t[1]: type name\n//\t[2]: lowest defined value for type, as a string\nconst stringOneRun = `func (i %[1]s) String() string {\n\tidx := int(i) - %[2]s\n\tif i < %[2]s || idx >= len(_%[1]s_index)-1 {\n\t\treturn \"%[1]s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _%[1]s_name[_%[1]s_index[idx] : _%[1]s_index[idx+1]]\n}\n`\n\n// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.\n// For this pattern, a single Printf format won't do.\nfunc (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {\n\tg.Printf(\"\\n\")\n\tg.declareIndexAndNameVars(runs, typeName)\n\tg.Printf(\"func (i %s) String() string {\\n\", typeName)\n\tg.Printf(\"\\tswitch {\\n\")\n\tfor i, values := range runs {\n\t\tif len(values) == 1 {\n\t\t\tg.Printf(\"\\tcase i == %s:\\n\", &values[0])\n\t\t\tg.Printf(\"\\t\\treturn _%s_name_%d\\n\", typeName, i)\n\t\t\tcontinue\n\t\t}\n\t\tif values[0].value == 0 && !values[0].signed {\n\t\t\t// For an unsigned lower bound of 0, \"0 <= i\" would be redundant.\n\t\t\tg.Printf(\"\\tcase i <= %s:\\n\", &values[len(values)-1])\n\t\t} else {\n\t\t\tg.Printf(\"\\tcase %s <= i && i <= %s:\\n\", &values[0], &values[len(values)-1])\n\t\t}\n\t\tif values[0].value != 0 {\n\t\t\tg.Printf(\"\\t\\ti -= %s\\n\", &values[0])\n\t\t}\n\t\tg.Printf(\"\\t\\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\\n\",\n\t\t\ttypeName, i, typeName, i, typeName, i)\n\t}\n\tg.Printf(\"\\tdefault:\\n\")\n\tg.Printf(\"\\t\\treturn \\\"%s(\\\" + strconv.FormatInt(int64(i), 10) + \\\")\\\"\\n\", typeName)\n\tg.Printf(\"\\t}\\n\")\n\tg.Printf(\"}\\n\")\n}\n\n// buildMap handles the case where the space is so sparse a map is a reasonable fallback.\n// It's a rare situation but has simple code.\nfunc (g *Generator) buildMap(runs [][]Value, typeName string) {\n\tg.Printf(\"\\n\")\n\tg.declareNameVars(runs, typeName, \"\")\n\tg.Printf(\"\\nvar _%s_map = map[%s]string{\\n\", typeName, typeName)\n\tn := 0\n\tfor _, values := range runs {\n\t\tfor _, value := range values {\n\t\t\tg.Printf(\"\\t%s: _%s_name[%d:%d],\\n\", &value, typeName, n, n+len(value.name))\n\t\t\tn += len(value.name)\n\t\t}\n\t}\n\tg.Printf(\"}\\n\\n\")\n\tg.Printf(stringMap, typeName)\n}\n\n// Argument to format is the type name.\nconst stringMap = `func (i %[1]s) String() string {\n\tif str, ok := _%[1]s_map[i]; ok {\n\t\treturn str\n\t}\n\treturn \"%[1]s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n}\n`\n"
  },
  {
    "path": "cmd/stringer/testdata/cgo.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Import \"C\" shouldn't be imported.\n\npackage main\n\n/*\n#define HELLO 1\n*/\nimport \"C\"\n\nimport \"fmt\"\n\ntype Cgo uint32\n\nconst (\n\t// MustScanSubDirs indicates that events were coalesced hierarchically.\n\tMustScanSubDirs Cgo = 1 << iota\n)\n\nfunc main() {\n\t_ = C.HELLO\n\tck(MustScanSubDirs, \"MustScanSubDirs\")\n}\n\nfunc ck(day Cgo, str string) {\n\tif fmt.Sprint(day) != str {\n\t\tpanic(\"cgo.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/conv.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Check that constants defined as a conversion are accepted.\n\npackage main\n\nimport \"fmt\"\n\ntype Other int // Imagine this is in another package.\n\nconst (\n\talpha Other = iota\n\tbeta\n\tgamma\n\tdelta\n)\n\ntype Conv int\n\nconst (\n\tAlpha = Conv(alpha)\n\tBeta  = Conv(beta)\n\tGamma = Conv(gamma)\n\tDelta = Conv(delta)\n)\n\nfunc main() {\n\tck(Alpha, \"Alpha\")\n\tck(Beta, \"Beta\")\n\tck(Gamma, \"Gamma\")\n\tck(Delta, \"Delta\")\n\tck(42, \"Conv(42)\")\n}\n\nfunc ck(c Conv, str string) {\n\tif fmt.Sprint(c) != str {\n\t\tpanic(\"conv.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/conv2.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is a version of ../conv.go with type params\n\n// Check that constants defined as a conversion are accepted.\n\npackage main\n\nimport \"fmt\"\n\n// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).\n// type Other[T interface{ ~int | ~uint }] T // Imagine this is in another package.\ntype Other int\n\nconst (\n\t// alpha Other[int] = iota\n\talpha Other = iota\n\tbeta\n\tgamma\n\tdelta\n)\n\n// type Conv2 Other[int]\ntype Conv2 Other\n\nconst (\n\tAlpha = Conv2(alpha)\n\tBeta  = Conv2(beta)\n\tGamma = Conv2(gamma)\n\tDelta = Conv2(delta)\n)\n\nfunc main() {\n\tck(Alpha, \"Alpha\")\n\tck(Beta, \"Beta\")\n\tck(Gamma, \"Gamma\")\n\tck(Delta, \"Delta\")\n\tck(42, \"Conv2(42)\")\n}\n\nfunc ck(c Conv2, str string) {\n\tif fmt.Sprint(c) != str {\n\t\tpanic(\"conv2.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/day.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Simple test: enumeration of type int starting at 0.\n\npackage main\n\nimport \"fmt\"\n\ntype Day int\n\nconst (\n\tMonday Day = iota\n\tTuesday\n\tWednesday\n\tThursday\n\tFriday\n\tSaturday\n\tSunday\n)\n\nfunc main() {\n\tck(Monday, \"Monday\")\n\tck(Tuesday, \"Tuesday\")\n\tck(Wednesday, \"Wednesday\")\n\tck(Thursday, \"Thursday\")\n\tck(Friday, \"Friday\")\n\tck(Saturday, \"Saturday\")\n\tck(Sunday, \"Sunday\")\n\tck(-127, \"Day(-127)\")\n\tck(127, \"Day(127)\")\n}\n\nfunc ck(day Day, str string) {\n\tif fmt.Sprint(day) != str {\n\t\tpanic(\"day.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/gap.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Gaps and an offset.\n\npackage main\n\nimport \"fmt\"\n\ntype Gap int\n\nconst (\n\tTwo    Gap = 2\n\tThree  Gap = 3\n\tFive   Gap = 5\n\tSix    Gap = 6\n\tSeven  Gap = 7\n\tEight  Gap = 8\n\tNine   Gap = 9\n\tEleven Gap = 11\n)\n\nfunc main() {\n\tck(0, \"Gap(0)\")\n\tck(1, \"Gap(1)\")\n\tck(Two, \"Two\")\n\tck(Three, \"Three\")\n\tck(4, \"Gap(4)\")\n\tck(Five, \"Five\")\n\tck(Six, \"Six\")\n\tck(Seven, \"Seven\")\n\tck(Eight, \"Eight\")\n\tck(Nine, \"Nine\")\n\tck(10, \"Gap(10)\")\n\tck(Eleven, \"Eleven\")\n\tck(12, \"Gap(12)\")\n}\n\nfunc ck(gap Gap, str string) {\n\tif fmt.Sprint(gap) != str {\n\t\tpanic(\"gap.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/int8overflow.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Check that int8 bounds checking doesn't cause panics or compilation errors.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype Int8overflow int8\n\nconst (\n\tI_128 Int8overflow = -128\n\tI_127 Int8overflow = -127\n\tI_126 Int8overflow = -126\n\tI_125 Int8overflow = -125\n\tI_124 Int8overflow = -124\n\tI_123 Int8overflow = -123\n\tI_122 Int8overflow = -122\n\tI_121 Int8overflow = -121\n\tI_120 Int8overflow = -120\n\tI_119 Int8overflow = -119\n\tI_118 Int8overflow = -118\n\tI_117 Int8overflow = -117\n\tI_116 Int8overflow = -116\n\tI_115 Int8overflow = -115\n\tI_114 Int8overflow = -114\n\tI_113 Int8overflow = -113\n\tI_112 Int8overflow = -112\n\tI_111 Int8overflow = -111\n\tI_110 Int8overflow = -110\n\tI_109 Int8overflow = -109\n\tI_108 Int8overflow = -108\n\tI_107 Int8overflow = -107\n\tI_106 Int8overflow = -106\n\tI_105 Int8overflow = -105\n\tI_104 Int8overflow = -104\n\tI_103 Int8overflow = -103\n\tI_102 Int8overflow = -102\n\tI_101 Int8overflow = -101\n\tI_100 Int8overflow = -100\n\tI_99  Int8overflow = -99\n\tI_98  Int8overflow = -98\n\tI_97  Int8overflow = -97\n\tI_96  Int8overflow = -96\n\tI_95  Int8overflow = -95\n\tI_94  Int8overflow = -94\n\tI_93  Int8overflow = -93\n\tI_92  Int8overflow = -92\n\tI_91  Int8overflow = -91\n\tI_90  Int8overflow = -90\n\tI_89  Int8overflow = -89\n\tI_88  Int8overflow = -88\n\tI_87  Int8overflow = -87\n\tI_86  Int8overflow = -86\n\tI_85  Int8overflow = -85\n\tI_84  Int8overflow = -84\n\tI_83  Int8overflow = -83\n\tI_82  Int8overflow = -82\n\tI_81  Int8overflow = -81\n\tI_80  Int8overflow = -80\n\tI_79  Int8overflow = -79\n\tI_78  Int8overflow = -78\n\tI_77  Int8overflow = -77\n\tI_76  Int8overflow = -76\n\tI_75  Int8overflow = -75\n\tI_74  Int8overflow = -74\n\tI_73  Int8overflow = -73\n\tI_72  Int8overflow = -72\n\tI_71  Int8overflow = -71\n\tI_70  Int8overflow = -70\n\tI_69  Int8overflow = -69\n\tI_68  Int8overflow = -68\n\tI_67  Int8overflow = -67\n\tI_66  Int8overflow = -66\n\tI_65  Int8overflow = -65\n\tI_64  Int8overflow = -64\n\tI_63  Int8overflow = -63\n\tI_62  Int8overflow = -62\n\tI_61  Int8overflow = -61\n\tI_60  Int8overflow = -60\n\tI_59  Int8overflow = -59\n\tI_58  Int8overflow = -58\n\tI_57  Int8overflow = -57\n\tI_56  Int8overflow = -56\n\tI_55  Int8overflow = -55\n\tI_54  Int8overflow = -54\n\tI_53  Int8overflow = -53\n\tI_52  Int8overflow = -52\n\tI_51  Int8overflow = -51\n\tI_50  Int8overflow = -50\n\tI_49  Int8overflow = -49\n\tI_48  Int8overflow = -48\n\tI_47  Int8overflow = -47\n\tI_46  Int8overflow = -46\n\tI_45  Int8overflow = -45\n\tI_44  Int8overflow = -44\n\tI_43  Int8overflow = -43\n\tI_42  Int8overflow = -42\n\tI_41  Int8overflow = -41\n\tI_40  Int8overflow = -40\n\tI_39  Int8overflow = -39\n\tI_38  Int8overflow = -38\n\tI_37  Int8overflow = -37\n\tI_36  Int8overflow = -36\n\tI_35  Int8overflow = -35\n\tI_34  Int8overflow = -34\n\tI_33  Int8overflow = -33\n\tI_32  Int8overflow = -32\n\tI_31  Int8overflow = -31\n\tI_30  Int8overflow = -30\n\tI_29  Int8overflow = -29\n\tI_28  Int8overflow = -28\n\tI_27  Int8overflow = -27\n\tI_26  Int8overflow = -26\n\tI_25  Int8overflow = -25\n\tI_24  Int8overflow = -24\n\tI_23  Int8overflow = -23\n\tI_22  Int8overflow = -22\n\tI_21  Int8overflow = -21\n\tI_20  Int8overflow = -20\n\tI_19  Int8overflow = -19\n\tI_18  Int8overflow = -18\n\tI_17  Int8overflow = -17\n\tI_16  Int8overflow = -16\n\tI_15  Int8overflow = -15\n\tI_14  Int8overflow = -14\n\tI_13  Int8overflow = -13\n\tI_12  Int8overflow = -12\n\tI_11  Int8overflow = -11\n\tI_10  Int8overflow = -10\n\tI_9   Int8overflow = -9\n\tI_8   Int8overflow = -8\n\tI_7   Int8overflow = -7\n\tI_6   Int8overflow = -6\n\tI_5   Int8overflow = -5\n\tI_4   Int8overflow = -4\n\tI_3   Int8overflow = -3\n\tI_2   Int8overflow = -2\n\tI_1   Int8overflow = -1\n\tI0    Int8overflow = 0\n\tI1    Int8overflow = 1\n\tI2    Int8overflow = 2\n\tI3    Int8overflow = 3\n\tI4    Int8overflow = 4\n\tI5    Int8overflow = 5\n\tI6    Int8overflow = 6\n\tI7    Int8overflow = 7\n\tI8    Int8overflow = 8\n\tI9    Int8overflow = 9\n\tI10   Int8overflow = 10\n\tI11   Int8overflow = 11\n\tI12   Int8overflow = 12\n\tI13   Int8overflow = 13\n\tI14   Int8overflow = 14\n\tI15   Int8overflow = 15\n\tI16   Int8overflow = 16\n\tI17   Int8overflow = 17\n\tI18   Int8overflow = 18\n\tI19   Int8overflow = 19\n\tI20   Int8overflow = 20\n\tI21   Int8overflow = 21\n\tI22   Int8overflow = 22\n\tI23   Int8overflow = 23\n\tI24   Int8overflow = 24\n\tI25   Int8overflow = 25\n\tI26   Int8overflow = 26\n\tI27   Int8overflow = 27\n\tI28   Int8overflow = 28\n\tI29   Int8overflow = 29\n\tI30   Int8overflow = 30\n\tI31   Int8overflow = 31\n\tI32   Int8overflow = 32\n\tI33   Int8overflow = 33\n\tI34   Int8overflow = 34\n\tI35   Int8overflow = 35\n\tI36   Int8overflow = 36\n\tI37   Int8overflow = 37\n\tI38   Int8overflow = 38\n\tI39   Int8overflow = 39\n\tI40   Int8overflow = 40\n\tI41   Int8overflow = 41\n\tI42   Int8overflow = 42\n\tI43   Int8overflow = 43\n\tI44   Int8overflow = 44\n\tI45   Int8overflow = 45\n\tI46   Int8overflow = 46\n\tI47   Int8overflow = 47\n\tI48   Int8overflow = 48\n\tI49   Int8overflow = 49\n\tI50   Int8overflow = 50\n\tI51   Int8overflow = 51\n\tI52   Int8overflow = 52\n\tI53   Int8overflow = 53\n\tI54   Int8overflow = 54\n\tI55   Int8overflow = 55\n\tI56   Int8overflow = 56\n\tI57   Int8overflow = 57\n\tI58   Int8overflow = 58\n\tI59   Int8overflow = 59\n\tI60   Int8overflow = 60\n\tI61   Int8overflow = 61\n\tI62   Int8overflow = 62\n\tI63   Int8overflow = 63\n\tI64   Int8overflow = 64\n\tI65   Int8overflow = 65\n\tI66   Int8overflow = 66\n\tI67   Int8overflow = 67\n\tI68   Int8overflow = 68\n\tI69   Int8overflow = 69\n\tI70   Int8overflow = 70\n\tI71   Int8overflow = 71\n\tI72   Int8overflow = 72\n\tI73   Int8overflow = 73\n\tI74   Int8overflow = 74\n\tI75   Int8overflow = 75\n\tI76   Int8overflow = 76\n\tI77   Int8overflow = 77\n\tI78   Int8overflow = 78\n\tI79   Int8overflow = 79\n\tI80   Int8overflow = 80\n\tI81   Int8overflow = 81\n\tI82   Int8overflow = 82\n\tI83   Int8overflow = 83\n\tI84   Int8overflow = 84\n\tI85   Int8overflow = 85\n\tI86   Int8overflow = 86\n\tI87   Int8overflow = 87\n\tI88   Int8overflow = 88\n\tI89   Int8overflow = 89\n\tI90   Int8overflow = 90\n\tI91   Int8overflow = 91\n\tI92   Int8overflow = 92\n\tI93   Int8overflow = 93\n\tI94   Int8overflow = 94\n\tI95   Int8overflow = 95\n\tI96   Int8overflow = 96\n\tI97   Int8overflow = 97\n\tI98   Int8overflow = 98\n\tI99   Int8overflow = 99\n\tI100  Int8overflow = 100\n\tI101  Int8overflow = 101\n\tI102  Int8overflow = 102\n\tI103  Int8overflow = 103\n\tI104  Int8overflow = 104\n\tI105  Int8overflow = 105\n\tI106  Int8overflow = 106\n\tI107  Int8overflow = 107\n\tI108  Int8overflow = 108\n\tI109  Int8overflow = 109\n\tI110  Int8overflow = 110\n\tI111  Int8overflow = 111\n\tI112  Int8overflow = 112\n\tI113  Int8overflow = 113\n\tI114  Int8overflow = 114\n\tI115  Int8overflow = 115\n\tI116  Int8overflow = 116\n\tI117  Int8overflow = 117\n\tI118  Int8overflow = 118\n\tI119  Int8overflow = 119\n\tI120  Int8overflow = 120\n\tI121  Int8overflow = 121\n\tI122  Int8overflow = 122\n\tI123  Int8overflow = 123\n\tI124  Int8overflow = 124\n\tI125  Int8overflow = 125\n\tI126  Int8overflow = 126\n\tI127  Int8overflow = 127\n)\n\nfunc main() {\n\ttestValues := []Int8overflow{\n\t\tI_128,\n\t\tI_127,\n\t\tI_1,\n\t\tI0,\n\t\tI1,\n\t\tI126,\n\t\tI127,\n\t}\n\n\tfor _, val := range testValues {\n\t\twant := strings.ReplaceAll(fmt.Sprintf(\"I%d\", int(val)), \"-\", \"_\")\n\t\tresult := fmt.Sprint(val)\n\t\tif result != want {\n\t\t\tpanic(fmt.Sprintf(\"int8overflow.go: got %s, want %s for value %d\", result, want, int8(val)))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/num.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Signed integers spanning zero.\n\npackage main\n\nimport \"fmt\"\n\ntype Num int\n\nconst (\n\tm_2 Num = -2 + iota\n\tm_1\n\tm0\n\tm1\n\tm2\n)\n\nfunc main() {\n\tck(-3, \"Num(-3)\")\n\tck(m_2, \"m_2\")\n\tck(m_1, \"m_1\")\n\tck(m0, \"m0\")\n\tck(m1, \"m1\")\n\tck(m2, \"m2\")\n\tck(3, \"Num(3)\")\n}\n\nfunc ck(num Num, str string) {\n\tif fmt.Sprint(num) != str {\n\t\tpanic(\"num.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/number.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Enumeration with an offset.\n// Also includes a duplicate.\n\npackage main\n\nimport \"fmt\"\n\ntype Number int\n\nconst (\n\t_ Number = iota\n\tOne\n\tTwo\n\tThree\n\tAnotherOne = One // Duplicate; note that AnotherOne doesn't appear below.\n)\n\nfunc main() {\n\tck(One, \"One\")\n\tck(Two, \"Two\")\n\tck(Three, \"Three\")\n\tck(AnotherOne, \"One\")\n\tck(127, \"Number(127)\")\n}\n\nfunc ck(num Number, str string) {\n\tif fmt.Sprint(num) != str {\n\t\tpanic(\"number.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/prime.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Enough gaps to trigger a map implementation of the method.\n// Also includes a duplicate to test that it doesn't cause problems\n\npackage main\n\nimport \"fmt\"\n\ntype Prime int\n\nconst (\n\tp2  Prime = 2\n\tp3  Prime = 3\n\tp5  Prime = 5\n\tp7  Prime = 7\n\tp77 Prime = 7 // Duplicate; note that p77 doesn't appear below.\n\tp11 Prime = 11\n\tp13 Prime = 13\n\tp17 Prime = 17\n\tp19 Prime = 19\n\tp23 Prime = 23\n\tp29 Prime = 29\n\tp37 Prime = 31\n\tp41 Prime = 41\n\tp43 Prime = 43\n)\n\nfunc main() {\n\tck(0, \"Prime(0)\")\n\tck(1, \"Prime(1)\")\n\tck(p2, \"p2\")\n\tck(p3, \"p3\")\n\tck(4, \"Prime(4)\")\n\tck(p5, \"p5\")\n\tck(p7, \"p7\")\n\tck(p77, \"p7\")\n\tck(p11, \"p11\")\n\tck(p13, \"p13\")\n\tck(p17, \"p17\")\n\tck(p19, \"p19\")\n\tck(p23, \"p23\")\n\tck(p29, \"p29\")\n\tck(p37, \"p37\")\n\tck(p41, \"p41\")\n\tck(p43, \"p43\")\n\tck(44, \"Prime(44)\")\n}\n\nfunc ck(prime Prime, str string) {\n\tif fmt.Sprint(prime) != str {\n\t\tpanic(\"prime.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/prime2.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is a version of ../prime.go with type params\n\n// Enough gaps to trigger a map implementation of the method.\n// Also includes a duplicate to test that it doesn't cause problems\n\npackage main\n\nimport \"fmt\"\n\n// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).\n// type Likeint[T interface{ ~int | ~uint8 }] T\ntype Likeint int\n\n// type Prime2 Likeint[int]\ntype Prime2 Likeint\n\nconst (\n\tp2  Prime2 = 2\n\tp3  Prime2 = 3\n\tp5  Prime2 = 5\n\tp7  Prime2 = 7\n\tp77 Prime2 = 7 // Duplicate; note that p77 doesn't appear below.\n\tp11 Prime2 = 11\n\tp13 Prime2 = 13\n\tp17 Prime2 = 17\n\tp19 Prime2 = 19\n\tp23 Prime2 = 23\n\tp29 Prime2 = 29\n\tp37 Prime2 = 31\n\tp41 Prime2 = 41\n\tp43 Prime2 = 43\n)\n\nfunc main() {\n\tck(0, \"Prime2(0)\")\n\tck(1, \"Prime2(1)\")\n\tck(p2, \"p2\")\n\tck(p3, \"p3\")\n\tck(4, \"Prime2(4)\")\n\tck(p5, \"p5\")\n\tck(p7, \"p7\")\n\tck(p77, \"p7\")\n\tck(p11, \"p11\")\n\tck(p13, \"p13\")\n\tck(p17, \"p17\")\n\tck(p19, \"p19\")\n\tck(p23, \"p23\")\n\tck(p29, \"p29\")\n\tck(p37, \"p37\")\n\tck(p41, \"p41\")\n\tck(p43, \"p43\")\n\tck(44, \"Prime2(44)\")\n}\n\nfunc ck(prime Prime2, str string) {\n\tif fmt.Sprint(prime) != str {\n\t\tpanic(\"prime2.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/tag_main.go",
    "content": "// No build tag in this file.\n\npackage main\n\ntype Const int\n\nconst (\n\tA Const = iota\n\tB\n\tC\n)\n"
  },
  {
    "path": "cmd/stringer/testdata/tag_tag.go",
    "content": "// This file has a build tag \"tag\"\n\n// +build tag\n\npackage main\n\nconst TagProtected Const = C + 1\n"
  },
  {
    "path": "cmd/stringer/testdata/unum.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Unsigned integers spanning zero.\n\npackage main\n\nimport \"fmt\"\n\ntype Unum uint8\n\nconst (\n\tm_2 Unum = iota + 253\n\tm_1\n)\n\nconst (\n\tm0 Unum = iota\n\tm1\n\tm2\n)\n\nfunc main() {\n\tck(^Unum(0)-3, \"Unum(252)\")\n\tck(m_2, \"m_2\")\n\tck(m_1, \"m_1\")\n\tck(m0, \"m0\")\n\tck(m1, \"m1\")\n\tck(m2, \"m2\")\n\tck(3, \"Unum(3)\")\n}\n\nfunc ck(unum Unum, str string) {\n\tif fmt.Sprint(unum) != str {\n\t\tpanic(\"unum.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/unum2.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Unsigned integers - check maximum size\n\npackage main\n\nimport \"fmt\"\n\ntype Unum2 uint8\n\nconst (\n\tZero Unum2 = iota\n\tOne\n\tTwo\n)\n\nfunc main() {\n\tck(Zero, \"Zero\")\n\tck(One, \"One\")\n\tck(Two, \"Two\")\n\tck(3, \"Unum2(3)\")\n\tck(255, \"Unum2(255)\")\n}\n\nfunc ck(unum Unum2, str string) {\n\tif fmt.Sprint(unum) != str {\n\t\tpanic(\"unum.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/testdata/vary_day.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is the same as day.go except the constants have different values.\n\npackage main\n\nimport \"fmt\"\n\ntype Day int\n\nconst (\n\tSunday Day = iota\n\tMonday\n\tTuesday\n\tWednesday\n\tThursday\n\tFriday\n\tSaturday\n)\n\nfunc main() {\n\tck(Monday, \"Monday\")\n\tck(Tuesday, \"Tuesday\")\n\tck(Wednesday, \"Wednesday\")\n\tck(Thursday, \"Thursday\")\n\tck(Friday, \"Friday\")\n\tck(Saturday, \"Saturday\")\n\tck(Sunday, \"Sunday\")\n\tck(-127, \"Day(-127)\")\n\tck(127, \"Day(127)\")\n}\n\nfunc ck(day Day, str string) {\n\tif fmt.Sprint(day) != str {\n\t\tpanic(\"day.go: \" + str)\n\t}\n}\n"
  },
  {
    "path": "cmd/stringer/util_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for some of the internal functions.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\n// Helpers to save typing in the test cases.\ntype u []uint64\ntype uu [][]uint64\n\ntype SplitTest struct {\n\tinput  u\n\toutput uu\n\tsigned bool\n}\n\nvar (\n\tm2  = uint64(2)\n\tm1  = uint64(1)\n\tm0  = uint64(0)\n\tm_1 = ^uint64(0)     // -1 when signed.\n\tm_2 = ^uint64(0) - 1 // -2 when signed.\n)\n\nvar splitTests = []SplitTest{\n\t// No need for a test for the empty case; that's picked off before splitIntoRuns.\n\t// Single value.\n\t{u{1}, uu{u{1}}, false},\n\t// Out of order.\n\t{u{3, 2, 1}, uu{u{1, 2, 3}}, true},\n\t// Out of order.\n\t{u{3, 2, 1}, uu{u{1, 2, 3}}, false},\n\t// A gap at the beginning.\n\t{u{1, 33, 32, 31}, uu{u{1}, u{31, 32, 33}}, true},\n\t// A gap in the middle, in mixed order.\n\t{u{33, 7, 32, 31, 9, 8}, uu{u{7, 8, 9}, u{31, 32, 33}}, true},\n\t// Gaps throughout\n\t{u{33, 44, 1, 32, 45, 31}, uu{u{1}, u{31, 32, 33}, u{44, 45}}, true},\n\t// Unsigned values spanning 0.\n\t{u{m1, m0, m_1, m2, m_2}, uu{u{m0, m1, m2}, u{m_2, m_1}}, false},\n\t// Signed values spanning 0\n\t{u{m1, m0, m_1, m2, m_2}, uu{u{m_2, m_1, m0, m1, m2}}, true},\n}\n\nfunc TestSplitIntoRuns(t *testing.T) {\nOuter:\n\tfor n, test := range splitTests {\n\t\tvalues := make([]Value, len(test.input))\n\t\tfor i, v := range test.input {\n\t\t\tvalues[i] = Value{\"\", \"\", v, test.signed, fmt.Sprint(v)}\n\t\t}\n\t\truns := splitIntoRuns(values)\n\t\tif len(runs) != len(test.output) {\n\t\t\tt.Errorf(\"#%d: %v: got %d runs; expected %d\", n, test.input, len(runs), len(test.output))\n\t\t\tcontinue\n\t\t}\n\t\tfor i, run := range runs {\n\t\t\tif len(run) != len(test.output[i]) {\n\t\t\t\tt.Errorf(\"#%d: got %v; expected %v\", n, runs, test.output)\n\t\t\t\tcontinue Outer\n\t\t\t}\n\t\t\tfor j, v := range run {\n\t\t\t\tif v.value != test.output[i][j] {\n\t\t\t\t\tt.Errorf(\"#%d: got %v; expected %v\", n, runs, test.output)\n\t\t\t\t\tcontinue Outer\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/toolstash/buildall",
    "content": "#!/bin/bash\n\n# Usage: buildall [-e] [-nocmp] [-work]\n#\n# Builds everything (std) for every GOOS/GOARCH combination but installs nothing.\n#\n# By default, runs the builds with -toolexec 'toolstash -cmp', to test that the\n# toolchain is producing bit identical output to a previous known good toolchain.\n#\n# Options:\n#\t-e: stop at first failure\n#\t-nocmp: turn off toolstash -cmp; just check that ordinary builds succeed\n#\t-work: pass -work to go command\n\nsete=false\nif [ \"$1\" = \"-e\" ]; then\n\tsete=true\n\tshift\nfi\n\ncmp=true\nif [ \"$1\" = \"-nocmp\" ]; then\n\tcmp=false\n\tshift\nfi\n\nwork=\"\"\nif [ \"$1\" = \"-work\" ]; then\n\twork=\"-work\"\n\tshift\nfi\n\ncd $(go env GOROOT)/src\ngo install cmd/compile cmd/link cmd/asm || exit 1\npattern=\"$1\"\nif [ \"$pattern\" = \"\" ]; then\n\tpattern=.\nfi\n\ntargets=\"$(go tool dist list; echo linux/386/softfloat)\"\ntargets=\"$(echo \"$targets\" | tr '/' '-' | sort | grep -E \"$pattern\" | grep -E -v 'android-arm|darwin-arm')\"\n\n# put linux first in the target list to get all the architectures up front.\ntargets=\"$(echo \"$targets\" | grep -E 'linux') $(echo \"$targets\" | grep -E -v 'linux')\"\n\nif [ \"$sete\" = true ]; then\n\tset -e\nfi\nfor target in $targets\ndo\n\techo $target\n\texport GOOS=$(echo $target | sed 's/-.*//')\n\texport GOARCH=$(echo $target | sed 's/.*-//')\n\tunset GO386\n\tif [ \"$GOARCH\" = \"softfloat\" ]; then\n\t\texport GOARCH=386\n\t\texport GO386=softfloat\n\tfi\n\tif $cmp; then\n\t\tif [ \"$GOOS\" = \"android\" ]; then\n\t\t\tgo build $work -a -toolexec 'toolstash -cmp' std\n\t\telse\n\t\t\tgo build $work -a -toolexec 'toolstash -cmp' std cmd\n\t\tfi\n\telse\n\t\tgo build $work -a std\n\tfi\ndone\n"
  },
  {
    "path": "cmd/toolstash/cmp.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\thexDumpRE = regexp.MustCompile(`^\\t(0x[0-9a-f]{4,})(( ([0-9a-f]{2}|  )){16})  [ -\\x7F]{1,16}\\n`)\n\tlistingRE = regexp.MustCompile(`^\\t(0x[0-9a-f]{4,}) ([0-9]{4,}) \\(.*:[0-9]+\\)\\t`)\n)\n\n// okdiffs lists regular expressions for lines to consider minor mismatches.\n// If one of these regexps matches both of a pair of unequal lines, the mismatch\n// is reported but not treated as the one worth looking for.\n// For example, differences in the TEXT line are typically frame size\n// changes due to optimization decisions made in the body of the function.\n// Better to keep looking for the actual difference.\n// Similarly, forward jumps might have different offsets due to a\n// change in instruction encoding later on.\n// Better to find that change.\nvar okdiffs = []*regexp.Regexp{\n\tregexp.MustCompile(`\\)\tTEXT[ \t].*,\\$`),\n\tregexp.MustCompile(`\\)\tWORD[ \t].*,\\$`),\n\tregexp.MustCompile(`\\)\t(B|BR|JMP)\t`),\n\tregexp.MustCompile(`\\)\tFUNCDATA\t`),\n\tregexp.MustCompile(`\\\\(z|x00)`),\n\tregexp.MustCompile(`\\$\\([0-9]\\.[0-9]+e[+\\-][0-9]+\\)`),\n\tregexp.MustCompile(`size=.*value=.*args=.*locals=`),\n}\n\nfunc compareLogs(outfile string) string {\n\tf1, err := os.Open(outfile + \".log\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer f1.Close()\n\n\tf2, err := os.Open(outfile + \".stash.log\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer f2.Close()\n\n\tb1 := bufio.NewReader(f1)\n\tb2 := bufio.NewReader(f2)\n\n\toffset := int64(0)\n\ttextOffset := offset\n\ttextLineno := 0\n\tlineno := 0\n\tvar line1, line2 string\n\tvar prefix bytes.Buffer\nReading:\n\tfor {\n\t\tvar err1, err2 error\n\t\tline1, err1 = b1.ReadString('\\n')\n\t\tline2, err2 = b2.ReadString('\\n')\n\t\tif strings.Contains(line1, \")\\tTEXT\\t\") {\n\t\t\ttextOffset = offset\n\t\t\ttextLineno = lineno\n\t\t}\n\t\toffset += int64(len(line1))\n\t\tlineno++\n\t\tif err1 == io.EOF && err2 == io.EOF {\n\t\t\treturn \"no differences in debugging output\"\n\t\t}\n\n\t\tif lineno == 1 || line1 == line2 && err1 == nil && err2 == nil {\n\t\t\tcontinue\n\t\t}\n\t\t// Lines are inconsistent. Worth stopping?\n\t\tfor _, re := range okdiffs {\n\t\t\tif re.MatchString(line1) && re.MatchString(line2) {\n\t\t\t\tfmt.Fprintf(&prefix, \"inconsistent log line:\\n%s:%d:\\n\\t%s\\n%s:%d:\\n\\t%s\\n\\n\",\n\t\t\t\t\tf1.Name(), lineno, strings.TrimSuffix(line1, \"\\n\"),\n\t\t\t\t\tf2.Name(), lineno, strings.TrimSuffix(line2, \"\\n\"))\n\t\t\t\tcontinue Reading\n\t\t\t}\n\t\t}\n\n\t\tif err1 != nil {\n\t\t\tline1 = err1.Error()\n\t\t}\n\t\tif err2 != nil {\n\t\t\tline2 = err2.Error()\n\t\t}\n\t\tbreak\n\t}\n\n\tmsg := fmt.Sprintf(\"inconsistent log line:\\n%s:%d:\\n\\t%s\\n%s:%d:\\n\\t%s\",\n\t\tf1.Name(), lineno, strings.TrimSuffix(line1, \"\\n\"),\n\t\tf2.Name(), lineno, strings.TrimSuffix(line2, \"\\n\"))\n\n\tif m := hexDumpRE.FindStringSubmatch(line1); m != nil {\n\t\ttarget, err := strconv.ParseUint(m[1], 0, 64)\n\t\tif err != nil {\n\t\t\tgoto Skip\n\t\t}\n\n\t\tm2 := hexDumpRE.FindStringSubmatch(line2)\n\t\tif m2 == nil {\n\t\t\tgoto Skip\n\t\t}\n\n\t\tfields1 := strings.Fields(m[2])\n\t\tfields2 := strings.Fields(m2[2])\n\t\ti := 0\n\t\tfor i < len(fields1) && i < len(fields2) && fields1[i] == fields2[i] {\n\t\t\ti++\n\t\t}\n\t\ttarget += uint64(i)\n\n\t\tf1.Seek(textOffset, 0)\n\t\tb1 = bufio.NewReader(f1)\n\t\tlast := \"\"\n\t\tlineno := textLineno\n\t\tlimitAddr := uint64(0)\n\t\tlastAddr := uint64(0)\n\t\tfor {\n\t\t\tline1, err1 := b1.ReadString('\\n')\n\t\t\tif err1 != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlineno++\n\t\t\tif m := listingRE.FindStringSubmatch(line1); m != nil {\n\t\t\t\taddr, _ := strconv.ParseUint(m[1], 0, 64)\n\t\t\t\tif addr > target {\n\t\t\t\t\tlimitAddr = addr\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlast = line1\n\t\t\t\tlastAddr = addr\n\t\t\t} else if hexDumpRE.FindStringSubmatch(line1) != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif last != \"\" {\n\t\t\tmsg = fmt.Sprintf(\"assembly instruction at %#04x-%#04x:\\n%s:%d\\n\\t%s\\n\\n%s\",\n\t\t\t\tlastAddr, limitAddr, f1.Name(), lineno-1, strings.TrimSuffix(last, \"\\n\"), msg)\n\t\t}\n\t}\nSkip:\n\n\treturn prefix.String() + msg\n}\n"
  },
  {
    "path": "cmd/toolstash/main.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Toolstash provides a way to save, run, and restore a known good copy of the Go toolchain\n// and to compare the object files generated by two toolchains.\n//\n// Usage:\n//\n//\ttoolstash [-n] [-v] save [tool...]\n//\ttoolstash [-n] [-v] restore [tool...]\n//\ttoolstash [-n] [-v] [-t] go run x.go\n//\ttoolstash [-n] [-v] [-t] [-cmp] compile x.go\n//\n// The toolstash command manages a “stashed” copy of the Go toolchain\n// kept in $GOROOT/pkg/toolstash. In this case, the toolchain means the\n// tools available with the 'go tool' command as well as the go, godoc, and gofmt\n// binaries.\n//\n// The command “toolstash save”, typically run when the toolchain is known to be working,\n// copies the toolchain from its installed location to the toolstash directory.\n// Its inverse, “toolchain restore”, typically run when the toolchain is known to be broken,\n// copies the toolchain from the toolstash directory back to the installed locations.\n// If additional arguments are given, the save or restore applies only to the named tools.\n// Otherwise, it applies to all tools.\n//\n// Otherwise, toolstash's arguments should be a command line beginning with the\n// name of a toolchain binary, which may be a short name like compile or a complete path\n// to an installed binary. Toolstash runs the command line using the stashed\n// copy of the binary instead of the installed one.\n//\n// The -n flag causes toolstash to print the commands that would be executed\n// but not execute them. The combination -n -cmp shows the two commands\n// that would be compared and then exits successfully. A real -cmp run might\n// run additional commands for diagnosis of an output mismatch.\n//\n// The -v flag causes toolstash to print the commands being executed.\n//\n// The -t flag causes toolstash to print the time elapsed during while the\n// command ran.\n//\n// # Comparing\n//\n// The -cmp flag causes toolstash to run both the installed and the stashed\n// copy of an assembler or compiler and check that they produce identical\n// object files. If not, toolstash reports the mismatch and exits with a failure status.\n// As part of reporting the mismatch, toolstash reinvokes the command with\n// the -S=2 flag and identifies the first divergence in the assembly output.\n// If the command is a Go compiler, toolstash also determines whether the\n// difference is triggered by optimization passes.\n// On failure, toolstash leaves additional information in files named\n// similarly to the default output file. If the compilation would normally\n// produce a file x.6, the output from the stashed tool is left in x.6.stash\n// and the debugging traces are left in x.6.log and x.6.stash.log.\n//\n// The -cmp flag is a no-op when the command line is not invoking an\n// assembler or compiler.\n//\n// For example, when working on code cleanup that should not affect\n// compiler output, toolstash can be used to compare the old and new\n// compiler output:\n//\n//\ttoolstash save\n//\t<edit compiler sources>\n//\tgo tool dist install cmd/compile # install compiler only\n//\ttoolstash -cmp compile x.go\n//\n// # Go Command Integration\n//\n// The go command accepts a -toolexec flag that specifies a program\n// to use to run the build tools.\n//\n// To build with the stashed tools:\n//\n//\tgo build -toolexec toolstash x.go\n//\n// To build with the stashed go command and the stashed tools:\n//\n//\ttoolstash go build -toolexec toolstash x.go\n//\n// To verify that code cleanup in the compilers does not make any\n// changes to the objects being generated for the entire tree:\n//\n//\t# Build working tree and save tools.\n//\t./make.bash\n//\ttoolstash save\n//\n//\t<edit compiler sources>\n//\n//\t# Install new tools, but do not rebuild the rest of tree,\n//\t# since the compilers might generate buggy code.\n//\tgo tool dist install cmd/compile\n//\n//\t# Check that new tools behave identically to saved tools.\n//\tgo build -toolexec 'toolstash -cmp' -a std\n//\n//\t# If not, restore, in order to keep working on Go code.\n//\ttoolstash restore\n//\n// # Version Skew\n//\n// The Go tools write the current Go version to object files, and (outside\n// release branches) that version includes the hash and time stamp\n// of the most recent Git commit. Functionally equivalent\n// compilers built at different Git versions may produce object files that\n// differ only in the recorded version. Toolstash ignores version mismatches\n// when comparing object files, but the standard tools will refuse to compile\n// or link together packages with different object versions.\n//\n// For the full build in the final example above to work, both the stashed\n// and the installed tools must use the same version string.\n// One way to ensure this is not to commit any of the changes being\n// tested, so that the Git HEAD hash is the same for both builds.\n// A more robust way to force the tools to have the same version string\n// is to write a $GOROOT/VERSION file, which overrides the Git-based version\n// computation:\n//\n//\techo devel >$GOROOT/VERSION\n//\n// The version can be arbitrary text, but to pass all.bash's API check, it must\n// contain the substring “devel”. The VERSION file must be created before\n// building either version of the toolchain.\npackage main // import \"golang.org/x/tools/cmd/toolstash\"\n\nimport (\n\t\"bufio\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar usageMessage = `usage: toolstash [-n] [-v] [-cmp] command line\n\nExamples:\n\ttoolstash save\n\ttoolstash restore\n\ttoolstash go run x.go\n\ttoolstash compile x.go\n\ttoolstash -cmp compile x.go\n\nFor details, godoc golang.org/x/tools/cmd/toolstash\n`\n\nfunc usage() {\n\tfmt.Fprint(os.Stderr, usageMessage)\n\tos.Exit(2)\n}\n\nvar (\n\tgoCmd   = flag.String(\"go\", \"go\", \"path to \\\"go\\\" command\")\n\tnorun   = flag.Bool(\"n\", false, \"print but do not run commands\")\n\tverbose = flag.Bool(\"v\", false, \"print commands being run\")\n\tcmp     = flag.Bool(\"cmp\", false, \"compare tool object files\")\n\ttiming  = flag.Bool(\"t\", false, \"print time commands take\")\n)\n\nvar (\n\tcmd       []string\n\ttool      string // name of tool: \"go\", \"compile\", etc\n\ttoolStash string // path to stashed tool\n\n\tgoroot   string\n\ttoolDir  string\n\tstashDir string\n\tbinDir   string\n)\n\nfunc canCmp(name string, args []string) bool {\n\tswitch name {\n\tcase \"asm\", \"compile\", \"link\":\n\t\tif len(args) == 1 && (args[0] == \"-V\" || strings.HasPrefix(args[0], \"-V=\")) {\n\t\t\t// cmd/go uses \"compile -V=full\" to query the tool's build ID.\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t}\n\treturn len(name) == 2 && '0' <= name[0] && name[0] <= '9' && (name[1] == 'a' || name[1] == 'g' || name[1] == 'l')\n}\n\nvar binTools = []string{\"go\", \"godoc\", \"gofmt\"}\n\nfunc isBinTool(name string) bool {\n\treturn strings.HasPrefix(name, \"go\")\n}\n\nfunc main() {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(\"toolstash: \")\n\n\tflag.Usage = usage\n\tflag.Parse()\n\tcmd = flag.Args()\n\n\tif len(cmd) < 1 {\n\t\tusage()\n\t}\n\n\ts, err := exec.Command(*goCmd, \"env\", \"GOROOT\").CombinedOutput()\n\tif err != nil {\n\t\tlog.Fatalf(\"%s env GOROOT: %v\", *goCmd, err)\n\t}\n\tgoroot = strings.TrimSpace(string(s))\n\ttoolDir = filepath.Join(goroot, fmt.Sprintf(\"pkg/tool/%s_%s\", runtime.GOOS, runtime.GOARCH))\n\tstashDir = filepath.Join(goroot, \"pkg/toolstash\")\n\n\tbinDir = os.Getenv(\"GOBIN\")\n\tif binDir == \"\" {\n\t\tbinDir = filepath.Join(goroot, \"bin\")\n\t}\n\n\tswitch cmd[0] {\n\tcase \"save\":\n\t\tsave()\n\t\treturn\n\n\tcase \"restore\":\n\t\trestore()\n\t\treturn\n\t}\n\n\ttool = exeName(cmd[0])\n\tif i := strings.LastIndexAny(tool, `/\\`); i >= 0 {\n\t\ttool = tool[i+1:]\n\t}\n\n\tif !strings.HasPrefix(tool, \"a.out\") {\n\t\ttoolStash = filepath.Join(stashDir, tool)\n\t\tif _, err := os.Stat(toolStash); err != nil {\n\t\t\tlog.Print(err)\n\t\t\tos.Exit(2)\n\t\t}\n\n\t\tif *cmp && canCmp(tool, cmd[1:]) {\n\t\t\tcompareTool()\n\t\t\treturn\n\t\t}\n\t\tcmd[0] = toolStash\n\t}\n\n\tif *norun {\n\t\tfmt.Printf(\"%s\\n\", strings.Join(cmd, \" \"))\n\t\treturn\n\t}\n\tif *verbose {\n\t\tlog.Print(strings.Join(cmd, \" \"))\n\t}\n\txcmd := exec.Command(cmd[0], cmd[1:]...)\n\txcmd.Stdin = os.Stdin\n\txcmd.Stdout = os.Stdout\n\txcmd.Stderr = os.Stderr\n\terr = xcmd.Run()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tos.Exit(0)\n}\n\nfunc compareTool() {\n\tif !strings.Contains(cmd[0], \"/\") && !strings.Contains(cmd[0], `\\`) {\n\t\tcmd[0] = filepath.Join(toolDir, tool)\n\t}\n\n\toutfile, ok := cmpRun(false, cmd)\n\tif ok {\n\t\tos.Remove(outfile + \".stash\")\n\t\treturn\n\t}\n\n\textra := \"-S=2\"\n\tswitch {\n\tdefault:\n\t\tlog.Fatalf(\"unknown tool %s\", tool)\n\n\tcase tool == \"compile\" || strings.HasSuffix(tool, \"g\"): // compiler\n\t\tuseDashN := true\n\t\tdashcIndex := -1\n\t\tfor i, s := range cmd {\n\t\t\tif s == \"-+\" {\n\t\t\t\t// Compiling runtime. Don't use -N.\n\t\t\t\tuseDashN = false\n\t\t\t}\n\t\t\tif strings.HasPrefix(s, \"-c=\") {\n\t\t\t\tdashcIndex = i\n\t\t\t}\n\t\t}\n\t\tcmdN := injectflags(cmd, nil, useDashN)\n\t\t_, ok := cmpRun(false, cmdN)\n\t\tif !ok {\n\t\t\tif useDashN {\n\t\t\t\tlog.Printf(\"compiler output differs, with optimizers disabled (-N)\")\n\t\t\t} else {\n\t\t\t\tlog.Printf(\"compiler output differs\")\n\t\t\t}\n\t\t\tif dashcIndex >= 0 {\n\t\t\t\tcmd[dashcIndex] = \"-c=1\"\n\t\t\t}\n\t\t\tcmd = injectflags(cmd, []string{\"-v\", \"-m=2\"}, useDashN)\n\t\t\tbreak\n\t\t}\n\t\tif dashcIndex >= 0 {\n\t\t\tcmd[dashcIndex] = \"-c=1\"\n\t\t}\n\t\tcmd = injectflags(cmd, []string{\"-v\", \"-m=2\"}, false)\n\t\tlog.Printf(\"compiler output differs, only with optimizers enabled\")\n\n\tcase tool == \"asm\" || strings.HasSuffix(tool, \"a\"): // assembler\n\t\tlog.Printf(\"assembler output differs\")\n\n\tcase tool == \"link\" || strings.HasSuffix(tool, \"l\"): // linker\n\t\tlog.Printf(\"linker output differs\")\n\t\textra = \"-v=2\"\n\t}\n\n\tcmdS := injectflags(cmd, []string{extra}, false)\n\toutfile, _ = cmpRun(true, cmdS)\n\n\tfmt.Fprintf(os.Stderr, \"\\n%s\\n\", compareLogs(outfile))\n\tos.Exit(2)\n}\n\nfunc injectflags(cmd []string, extra []string, addDashN bool) []string {\n\tx := []string{cmd[0]}\n\tif addDashN {\n\t\tx = append(x, \"-N\")\n\t}\n\tx = append(x, extra...)\n\tx = append(x, cmd[1:]...)\n\treturn x\n}\n\nfunc cmpRun(keepLog bool, cmd []string) (outfile string, match bool) {\n\tcmdStash := make([]string, len(cmd))\n\tcopy(cmdStash, cmd)\n\tcmdStash[0] = toolStash\n\tfor i, arg := range cmdStash {\n\t\tif arg == \"-o\" {\n\t\t\toutfile = cmdStash[i+1]\n\t\t\tcmdStash[i+1] += \".stash\"\n\t\t\tbreak\n\t\t}\n\t\tif strings.HasSuffix(arg, \".s\") || strings.HasSuffix(arg, \".go\") && '0' <= tool[0] && tool[0] <= '9' {\n\t\t\toutfile = filepath.Base(arg[:strings.LastIndex(arg, \".\")] + \".\" + tool[:1])\n\t\t\tcmdStash = append([]string{cmdStash[0], \"-o\", outfile + \".stash\"}, cmdStash[1:]...)\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif outfile == \"\" {\n\t\tlog.Fatalf(\"cannot determine output file for command: %s\", strings.Join(cmd, \" \"))\n\t}\n\n\tif *norun {\n\t\tfmt.Printf(\"%s\\n\", strings.Join(cmd, \" \"))\n\t\tfmt.Printf(\"%s\\n\", strings.Join(cmdStash, \" \"))\n\t\tos.Exit(0)\n\t}\n\n\tout, err := runCmd(cmd, keepLog, outfile+\".log\")\n\tif err != nil {\n\t\tlog.Printf(\"running: %s\", strings.Join(cmd, \" \"))\n\t\tos.Stderr.Write(out)\n\t\tlog.Fatal(err)\n\t}\n\n\toutStash, err := runCmd(cmdStash, keepLog, outfile+\".stash.log\")\n\tif err != nil {\n\t\tlog.Printf(\"running: %s\", strings.Join(cmdStash, \" \"))\n\t\tlog.Printf(\"installed tool succeeded but stashed tool failed.\\n\")\n\t\tif len(out) > 0 {\n\t\t\tlog.Printf(\"installed tool output:\")\n\t\t\tos.Stderr.Write(out)\n\t\t}\n\t\tif len(outStash) > 0 {\n\t\t\tlog.Printf(\"stashed tool output:\")\n\t\t\tos.Stderr.Write(outStash)\n\t\t}\n\t\tlog.Fatal(err)\n\t}\n\n\treturn outfile, sameObject(outfile, outfile+\".stash\")\n}\n\nfunc sameObject(file1, file2 string) bool {\n\tf1, err := os.Open(file1)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer f1.Close()\n\n\tf2, err := os.Open(file2)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer f2.Close()\n\n\tb1 := bufio.NewReader(f1)\n\tb2 := bufio.NewReader(f2)\n\n\t// Go object files and archives contain lines of the form\n\t//\tgo object <goos> <goarch> <version>\n\t// By default, the version on development branches includes\n\t// the Git hash and time stamp for the most recent commit.\n\t// We allow the versions to differ.\n\tif !skipVersion(b1, b2, file1, file2) {\n\t\treturn false\n\t}\n\n\tlastByte := byte(0)\n\tfor {\n\t\tc1, err1 := b1.ReadByte()\n\t\tc2, err2 := b2.ReadByte()\n\t\tif err1 == io.EOF && err2 == io.EOF {\n\t\t\treturn true\n\t\t}\n\t\tif err1 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file1, err1)\n\t\t}\n\t\tif err2 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file2, err2)\n\t\t}\n\t\tif c1 != c2 {\n\t\t\treturn false\n\t\t}\n\t\tif lastByte == '`' && c1 == '\\n' {\n\t\t\tif !skipVersion(b1, b2, file1, file2) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tlastByte = c1\n\t}\n}\n\nfunc skipVersion(b1, b2 *bufio.Reader, file1, file2 string) bool {\n\t// Consume \"go object \" prefix, if there.\n\tprefix := \"go object \"\n\tfor i := 0; i < len(prefix); i++ {\n\t\tc1, err1 := b1.ReadByte()\n\t\tc2, err2 := b2.ReadByte()\n\t\tif err1 == io.EOF && err2 == io.EOF {\n\t\t\treturn true\n\t\t}\n\t\tif err1 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file1, err1)\n\t\t}\n\t\tif err2 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file2, err2)\n\t\t}\n\t\tif c1 != c2 {\n\t\t\treturn false\n\t\t}\n\t\tif c1 != prefix[i] {\n\t\t\treturn true // matching bytes, just not a version\n\t\t}\n\t}\n\n\t// Keep comparing until second space.\n\t// Must continue to match.\n\t// If we see a \\n, it's not a version string after all.\n\tfor numSpace := 0; numSpace < 2; {\n\t\tc1, err1 := b1.ReadByte()\n\t\tc2, err2 := b2.ReadByte()\n\t\tif err1 == io.EOF && err2 == io.EOF {\n\t\t\treturn true\n\t\t}\n\t\tif err1 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file1, err1)\n\t\t}\n\t\tif err2 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file2, err2)\n\t\t}\n\t\tif c1 != c2 {\n\t\t\treturn false\n\t\t}\n\t\tif c1 == '\\n' {\n\t\t\treturn true\n\t\t}\n\t\tif c1 == ' ' {\n\t\t\tnumSpace++\n\t\t}\n\t}\n\n\t// Have now seen 'go object goos goarch ' in both files.\n\t// Now they're allowed to diverge, until the \\n, which\n\t// must be present.\n\tfor {\n\t\tc1, err1 := b1.ReadByte()\n\t\tif err1 == io.EOF {\n\t\t\tlog.Fatalf(\"reading %s: unexpected EOF\", file1)\n\t\t}\n\t\tif err1 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file1, err1)\n\t\t}\n\t\tif c1 == '\\n' {\n\t\t\tbreak\n\t\t}\n\t}\n\tfor {\n\t\tc2, err2 := b2.ReadByte()\n\t\tif err2 == io.EOF {\n\t\t\tlog.Fatalf(\"reading %s: unexpected EOF\", file2)\n\t\t}\n\t\tif err2 != nil {\n\t\t\tlog.Fatalf(\"reading %s: %v\", file2, err2)\n\t\t}\n\t\tif c2 == '\\n' {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Consumed \"matching\" versions from both.\n\treturn true\n}\n\nfunc runCmd(cmd []string, keepLog bool, logName string) (output []byte, err error) {\n\tif *verbose {\n\t\tlog.Print(strings.Join(cmd, \" \"))\n\t}\n\n\tif *timing {\n\t\tt0 := time.Now()\n\t\tdefer func() {\n\t\t\tlog.Printf(\"%.3fs elapsed # %s\\n\", time.Since(t0).Seconds(), strings.Join(cmd, \" \"))\n\t\t}()\n\t}\n\n\txcmd := exec.Command(exeName(cmd[0]), cmd[1:]...)\n\tif !keepLog {\n\t\treturn xcmd.CombinedOutput()\n\t}\n\n\tf, err := os.Create(logName)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Fprintf(f, \"GOOS=%s GOARCH=%s %s\\n\", os.Getenv(\"GOOS\"), os.Getenv(\"GOARCH\"), strings.Join(cmd, \" \"))\n\txcmd.Stdout = f\n\txcmd.Stderr = f\n\tdefer f.Close()\n\treturn nil, xcmd.Run()\n}\n\nfunc save() {\n\tif err := os.MkdirAll(stashDir, 0777); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\ttoolDir := filepath.Join(goroot, fmt.Sprintf(\"pkg/tool/%s_%s\", runtime.GOOS, runtime.GOARCH))\n\tfiles, err := os.ReadDir(toolDir)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfor _, file := range files {\n\t\tinfo, err := file.Info()\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif shouldSave(file.Name()) && info.Mode().IsRegular() {\n\t\t\tcp(filepath.Join(toolDir, file.Name()), filepath.Join(stashDir, file.Name()))\n\t\t}\n\t}\n\n\tfor _, name := range binTools {\n\t\tif !shouldSave(name) {\n\t\t\tcontinue\n\t\t}\n\t\tbin := exeName(name)\n\t\tsrc := filepath.Join(binDir, bin)\n\t\tif _, err := os.Stat(src); err == nil {\n\t\t\tcp(src, filepath.Join(stashDir, bin))\n\t\t}\n\t}\n\n\tcheckShouldSave()\n}\n\nfunc restore() {\n\tfiles, err := os.ReadDir(stashDir)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfor _, file := range files {\n\t\tinfo, err := file.Info()\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif shouldSave(file.Name()) && info.Mode().IsRegular() {\n\t\t\ttarg := toolDir\n\t\t\tif isBinTool(file.Name()) {\n\t\t\t\ttarg = binDir\n\t\t\t}\n\t\t\tcp(filepath.Join(stashDir, file.Name()), filepath.Join(targ, file.Name()))\n\t\t}\n\t}\n\n\tcheckShouldSave()\n}\n\nfunc shouldSave(name string) bool {\n\tif len(cmd) == 1 {\n\t\treturn true\n\t}\n\tok := false\n\tfor i, arg := range cmd {\n\t\tif i > 0 && name == arg {\n\t\t\tok = true\n\t\t\tcmd[i] = \"DONE\"\n\t\t}\n\t}\n\treturn ok\n}\n\nfunc checkShouldSave() {\n\tvar missing []string\n\tfor _, arg := range cmd[1:] {\n\t\tif arg != \"DONE\" {\n\t\t\tmissing = append(missing, arg)\n\t\t}\n\t}\n\tif len(missing) > 0 {\n\t\tlog.Fatalf(\"%s did not find tools: %s\", cmd[0], strings.Join(missing, \" \"))\n\t}\n}\n\nfunc cp(src, dst string) {\n\tif *verbose {\n\t\tfmt.Printf(\"cp %s %s\\n\", src, dst)\n\t}\n\tdata, err := os.ReadFile(src)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.WriteFile(dst, data, 0777); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc exeName(name string) string {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn name + \".exe\"\n\t}\n\treturn name\n}\n"
  },
  {
    "path": "codereview.cfg",
    "content": "issuerepo: golang/go\n"
  },
  {
    "path": "container/intsets/export_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage intsets\n\n// Backdoor for testing.\nfunc (s *Sparse) Check() error { return s.check() }\n"
  },
  {
    "path": "container/intsets/sparse.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package intsets provides Sparse, a compact and fast representation\n// for sparse sets of int values.\n//\n// The time complexity of the operations Len, Insert, Remove and Has\n// is in O(n) but in practice those methods are faster and more\n// space-efficient than equivalent operations on sets based on the Go\n// map type.  The IsEmpty, Min, Max, Clear and TakeMin operations\n// require constant time.\npackage intsets // import \"golang.org/x/tools/container/intsets\"\n\n// TODO(adonovan):\n// - Add InsertAll(...int), RemoveAll(...int)\n// - Add 'bool changed' results for {Intersection,Difference}With too.\n//\n// TODO(adonovan): implement Dense, a dense bit vector with a similar API.\n// The space usage would be proportional to Max(), not Len(), and the\n// implementation would be based upon big.Int.\n//\n// TODO(adonovan): opt: make UnionWith and Difference faster.\n// These are the hot-spots for go/pointer.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"math/bits\"\n)\n\n// A Sparse is a set of int values.\n// Sparse operations (even queries) are not concurrency-safe.\n//\n// The zero value for Sparse is a valid empty set.\n//\n// Sparse sets must be copied using the Copy method, not by assigning\n// a Sparse value.\ntype Sparse struct {\n\t// An uninitialized Sparse represents an empty set.\n\t// An empty set may also be represented by\n\t//  root.next == root.prev == &root.\n\t//\n\t// The root is always the block with the smallest offset.\n\t// It can be empty, but only if it is the only block; in that case, offset is\n\t// MaxInt (which is not a valid offset).\n\troot block\n}\n\ntype word uintptr\n\nconst (\n\t_m            = ^word(0)\n\tbitsPerWord   = 8 << (_m>>8&1 + _m>>16&1 + _m>>32&1)\n\tbitsPerBlock  = 256 // optimal value for go/pointer solver performance\n\twordsPerBlock = bitsPerBlock / bitsPerWord\n)\n\n// Limit values of implementation-specific int type.\nconst (\n\tMaxInt = int(^uint(0) >> 1)\n\tMinInt = -MaxInt - 1\n)\n\n// popcount returns the number of set bits in w.\nfunc popcount(x word) int {\n\t// Avoid OnesCount(uint): don't assume uint = uintptr.\n\tif bitsPerWord == 32 {\n\t\treturn bits.OnesCount32(uint32(x))\n\t} else {\n\t\treturn bits.OnesCount64(uint64(x))\n\t}\n}\n\n// nlz returns the number of leading zeros of x.\nfunc nlz(x word) int {\n\t// Avoid LeadingZeros(uint): don't assume uint = uintptr.\n\tif bitsPerWord == 32 {\n\t\treturn bits.LeadingZeros32(uint32(x))\n\t} else {\n\t\treturn bits.LeadingZeros64(uint64(x))\n\t}\n}\n\n// ntz returns the number of trailing zeros of x.\nfunc ntz(x word) int {\n\t// Avoid TrailingZeros(uint): don't assume uint = uintptr.\n\tif bitsPerWord == 32 {\n\t\treturn bits.TrailingZeros32(uint32(x))\n\t} else {\n\t\treturn bits.TrailingZeros64(uint64(x))\n\t}\n}\n\n// -- block ------------------------------------------------------------\n\n// A set is represented as a circular doubly-linked list of blocks,\n// each containing an offset and a bit array of fixed size\n// bitsPerBlock; the blocks are ordered by increasing offset.\n//\n// The set contains an element x iff the block whose offset is x - (x\n// mod bitsPerBlock) has the bit (x mod bitsPerBlock) set, where mod\n// is the Euclidean remainder.\n//\n// A block may only be empty transiently.\ntype block struct {\n\toffset     int                 // offset mod bitsPerBlock == 0\n\tbits       [wordsPerBlock]word // contains at least one set bit\n\tnext, prev *block              // doubly-linked list of blocks\n}\n\n// wordMask returns the word index (in block.bits)\n// and single-bit mask for the block's ith bit.\nfunc wordMask(i uint) (w uint, mask word) {\n\tw = i / bitsPerWord\n\tmask = 1 << (i % bitsPerWord)\n\treturn\n}\n\n// insert sets the block b's ith bit and\n// returns true if it was not already set.\nfunc (b *block) insert(i uint) bool {\n\tw, mask := wordMask(i)\n\tif b.bits[w]&mask == 0 {\n\t\tb.bits[w] |= mask\n\t\treturn true\n\t}\n\treturn false\n}\n\n// remove clears the block's ith bit and\n// returns true if the bit was previously set.\n// NB: may leave the block empty.\nfunc (b *block) remove(i uint) bool {\n\tw, mask := wordMask(i)\n\tif b.bits[w]&mask != 0 {\n\t\tb.bits[w] &^= mask\n\t\treturn true\n\t}\n\treturn false\n}\n\n// has reports whether the block's ith bit is set.\nfunc (b *block) has(i uint) bool {\n\tw, mask := wordMask(i)\n\treturn b.bits[w]&mask != 0\n}\n\n// empty reports whether b.len()==0, but more efficiently.\nfunc (b *block) empty() bool {\n\tfor _, w := range b.bits {\n\t\tif w != 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// len returns the number of set bits in block b.\nfunc (b *block) len() int {\n\tvar l int\n\tfor _, w := range b.bits {\n\t\tl += popcount(w)\n\t}\n\treturn l\n}\n\n// max returns the maximum element of the block.\n// The block must not be empty.\nfunc (b *block) max() int {\n\tbi := b.offset + bitsPerBlock\n\t// Decrement bi by number of high zeros in last.bits.\n\tfor i := len(b.bits) - 1; i >= 0; i-- {\n\t\tif w := b.bits[i]; w != 0 {\n\t\t\treturn bi - nlz(w) - 1\n\t\t}\n\t\tbi -= bitsPerWord\n\t}\n\tpanic(\"BUG: empty block\")\n}\n\n// min returns the minimum element of the block,\n// and also removes it if take is set.\n// The block must not be initially empty.\n// NB: may leave the block empty.\nfunc (b *block) min(take bool) int {\n\tfor i, w := range b.bits {\n\t\tif w != 0 {\n\t\t\ttz := ntz(w)\n\t\t\tif take {\n\t\t\t\tb.bits[i] = w &^ (1 << uint(tz))\n\t\t\t}\n\t\t\treturn b.offset + i*bitsPerWord + tz\n\t\t}\n\t}\n\tpanic(\"BUG: empty block\")\n}\n\n// lowerBound returns the smallest element of the block that is greater than or\n// equal to the element corresponding to the ith bit. If there is no such\n// element, the second return value is false.\nfunc (b *block) lowerBound(i uint) (int, bool) {\n\tw := i / bitsPerWord\n\tbit := i % bitsPerWord\n\n\tif val := b.bits[w] >> bit; val != 0 {\n\t\treturn b.offset + int(i) + ntz(val), true\n\t}\n\n\tfor w++; w < wordsPerBlock; w++ {\n\t\tif val := b.bits[w]; val != 0 {\n\t\t\treturn b.offset + int(w*bitsPerWord) + ntz(val), true\n\t\t}\n\t}\n\n\treturn 0, false\n}\n\n// forEach calls f for each element of block b.\n// f must not mutate b's enclosing Sparse.\nfunc (b *block) forEach(f func(int)) {\n\tfor i, w := range b.bits {\n\t\toffset := b.offset + i*bitsPerWord\n\t\tfor bi := 0; w != 0 && bi < bitsPerWord; bi++ {\n\t\t\tif w&1 != 0 {\n\t\t\t\tf(offset)\n\t\t\t}\n\t\t\toffset++\n\t\t\tw >>= 1\n\t\t}\n\t}\n}\n\n// offsetAndBitIndex returns the offset of the block that would\n// contain x and the bit index of x within that block.\nfunc offsetAndBitIndex(x int) (int, uint) {\n\tmod := x % bitsPerBlock\n\tif mod < 0 {\n\t\t// Euclidean (non-negative) remainder\n\t\tmod += bitsPerBlock\n\t}\n\treturn x - mod, uint(mod)\n}\n\n// -- Sparse --------------------------------------------------------------\n\n// none is a shared, empty, sentinel block that indicates the end of a block\n// list.\nvar none block\n\n// Dummy type used to generate an implicit panic. This must be defined at the\n// package level; if it is defined inside a function, it prevents the inlining\n// of that function.\ntype to_copy_a_sparse_you_must_call_its_Copy_method struct{}\n\n// init ensures s is properly initialized.\nfunc (s *Sparse) init() {\n\troot := &s.root\n\tif root.next == nil {\n\t\troot.offset = MaxInt\n\t\troot.next = root\n\t\troot.prev = root\n\t} else if root.next.prev != root {\n\t\t// Copying a Sparse x leads to pernicious corruption: the\n\t\t// new Sparse y shares the old linked list, but iteration\n\t\t// on y will never encounter &y.root so it goes into a\n\t\t// loop.  Fail fast before this occurs.\n\t\t// We don't want to call panic here because it prevents the\n\t\t// inlining of this function.\n\t\t_ = (any(nil)).(to_copy_a_sparse_you_must_call_its_Copy_method)\n\t}\n}\n\nfunc (s *Sparse) first() *block {\n\ts.init()\n\tif s.root.offset == MaxInt {\n\t\treturn &none\n\t}\n\treturn &s.root\n}\n\n// next returns the next block in the list, or end if b is the last block.\nfunc (s *Sparse) next(b *block) *block {\n\tif b.next == &s.root {\n\t\treturn &none\n\t}\n\treturn b.next\n}\n\n// IsEmpty reports whether the set s is empty.\nfunc (s *Sparse) IsEmpty() bool {\n\treturn s.root.next == nil || s.root.offset == MaxInt\n}\n\n// Len returns the number of elements in the set s.\nfunc (s *Sparse) Len() int {\n\tvar l int\n\tfor b := s.first(); b != &none; b = s.next(b) {\n\t\tl += b.len()\n\t}\n\treturn l\n}\n\n// Max returns the maximum element of the set s, or MinInt if s is empty.\nfunc (s *Sparse) Max() int {\n\tif s.IsEmpty() {\n\t\treturn MinInt\n\t}\n\treturn s.root.prev.max()\n}\n\n// Min returns the minimum element of the set s, or MaxInt if s is empty.\nfunc (s *Sparse) Min() int {\n\tif s.IsEmpty() {\n\t\treturn MaxInt\n\t}\n\treturn s.root.min(false)\n}\n\n// LowerBound returns the smallest element >= x, or MaxInt if there is no such\n// element.\nfunc (s *Sparse) LowerBound(x int) int {\n\toffset, i := offsetAndBitIndex(x)\n\tfor b := s.first(); b != &none; b = s.next(b) {\n\t\tif b.offset > offset {\n\t\t\treturn b.min(false)\n\t\t}\n\t\tif b.offset == offset {\n\t\t\tif y, ok := b.lowerBound(i); ok {\n\t\t\t\treturn y\n\t\t\t}\n\t\t}\n\t}\n\treturn MaxInt\n}\n\n// block returns the block that would contain offset,\n// or nil if s contains no such block.\n// Precondition: offset is a multiple of bitsPerBlock.\nfunc (s *Sparse) block(offset int) *block {\n\tfor b := s.first(); b != &none && b.offset <= offset; b = s.next(b) {\n\t\tif b.offset == offset {\n\t\t\treturn b\n\t\t}\n\t}\n\treturn nil\n}\n\n// Insert adds x to the set s, and reports whether the set grew.\nfunc (s *Sparse) Insert(x int) bool {\n\toffset, i := offsetAndBitIndex(x)\n\n\tb := s.first()\n\tfor ; b != &none && b.offset <= offset; b = s.next(b) {\n\t\tif b.offset == offset {\n\t\t\treturn b.insert(i)\n\t\t}\n\t}\n\n\t// Insert new block before b.\n\tnew := s.insertBlockBefore(b)\n\tnew.offset = offset\n\treturn new.insert(i)\n}\n\n// removeBlock removes a block and returns the block that followed it (or end if\n// it was the last block).\nfunc (s *Sparse) removeBlock(b *block) *block {\n\tif b != &s.root {\n\t\tb.prev.next = b.next\n\t\tb.next.prev = b.prev\n\t\tif b.next == &s.root {\n\t\t\treturn &none\n\t\t}\n\t\treturn b.next\n\t}\n\n\tfirst := s.root.next\n\tif first == &s.root {\n\t\t// This was the only block.\n\t\ts.Clear()\n\t\treturn &none\n\t}\n\ts.root.offset = first.offset\n\ts.root.bits = first.bits\n\tif first.next == &s.root {\n\t\t// Single block remaining.\n\t\ts.root.next = &s.root\n\t\ts.root.prev = &s.root\n\t} else {\n\t\ts.root.next = first.next\n\t\tfirst.next.prev = &s.root\n\t}\n\treturn &s.root\n}\n\n// Remove removes x from the set s, and reports whether the set shrank.\nfunc (s *Sparse) Remove(x int) bool {\n\toffset, i := offsetAndBitIndex(x)\n\tif b := s.block(offset); b != nil {\n\t\tif !b.remove(i) {\n\t\t\treturn false\n\t\t}\n\t\tif b.empty() {\n\t\t\ts.removeBlock(b)\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Clear removes all elements from the set s.\nfunc (s *Sparse) Clear() {\n\ts.root = block{\n\t\toffset: MaxInt,\n\t\tnext:   &s.root,\n\t\tprev:   &s.root,\n\t}\n}\n\n// If set s is non-empty, TakeMin sets *p to the minimum element of\n// the set s, removes that element from the set and returns true.\n// Otherwise, it returns false and *p is undefined.\n//\n// This method may be used for iteration over a worklist like so:\n//\n//\tvar x int\n//\tfor worklist.TakeMin(&x) { use(x) }\nfunc (s *Sparse) TakeMin(p *int) bool {\n\tif s.IsEmpty() {\n\t\treturn false\n\t}\n\t*p = s.root.min(true)\n\tif s.root.empty() {\n\t\ts.removeBlock(&s.root)\n\t}\n\treturn true\n}\n\n// Has reports whether x is an element of the set s.\nfunc (s *Sparse) Has(x int) bool {\n\toffset, i := offsetAndBitIndex(x)\n\tif b := s.block(offset); b != nil {\n\t\treturn b.has(i)\n\t}\n\treturn false\n}\n\n// forEach applies function f to each element of the set s in order.\n//\n// f must not mutate s.  Consequently, forEach is not safe to expose\n// to clients.  In any case, using \"range s.AppendTo()\" allows more\n// natural control flow with continue/break/return.\nfunc (s *Sparse) forEach(f func(int)) {\n\tfor b := s.first(); b != &none; b = s.next(b) {\n\t\tb.forEach(f)\n\t}\n}\n\n// Copy sets s to the value of x.\nfunc (s *Sparse) Copy(x *Sparse) {\n\tif s == x {\n\t\treturn\n\t}\n\n\txb := x.first()\n\tsb := s.first()\n\tfor xb != &none {\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = xb.offset\n\t\tsb.bits = xb.bits\n\t\txb = x.next(xb)\n\t\tsb = s.next(sb)\n\t}\n\ts.discardTail(sb)\n}\n\n// insertBlockBefore returns a new block, inserting it before next.\n// If next is the root, the root is replaced. If next is end, the block is\n// inserted at the end.\nfunc (s *Sparse) insertBlockBefore(next *block) *block {\n\tif s.IsEmpty() {\n\t\tif next != &none {\n\t\t\tpanic(\"BUG: passed block with empty set\")\n\t\t}\n\t\treturn &s.root\n\t}\n\n\tif next == &s.root {\n\t\t// Special case: we need to create a new block that will become the root\n\t\t// block.The old root block becomes the second block.\n\t\tsecond := s.root\n\t\ts.root = block{\n\t\t\tnext: &second,\n\t\t}\n\t\tif second.next == &s.root {\n\t\t\ts.root.prev = &second\n\t\t} else {\n\t\t\ts.root.prev = second.prev\n\t\t\tsecond.next.prev = &second\n\t\t\tsecond.prev = &s.root\n\t\t}\n\t\treturn &s.root\n\t}\n\tif next == &none {\n\t\t// Insert before root.\n\t\tnext = &s.root\n\t}\n\tb := new(block)\n\tb.next = next\n\tb.prev = next.prev\n\tb.prev.next = b\n\tnext.prev = b\n\treturn b\n}\n\n// discardTail removes block b and all its successors from s.\nfunc (s *Sparse) discardTail(b *block) {\n\tif b != &none {\n\t\tif b == &s.root {\n\t\t\ts.Clear()\n\t\t} else {\n\t\t\tb.prev.next = &s.root\n\t\t\ts.root.prev = b.prev\n\t\t}\n\t}\n}\n\n// IntersectionWith sets s to the intersection s ∩ x.\nfunc (s *Sparse) IntersectionWith(x *Sparse) {\n\tif s == x {\n\t\treturn\n\t}\n\n\txb := x.first()\n\tsb := s.first()\n\tfor xb != &none && sb != &none {\n\t\tswitch {\n\t\tcase xb.offset < sb.offset:\n\t\t\txb = x.next(xb)\n\n\t\tcase xb.offset > sb.offset:\n\t\t\tsb = s.removeBlock(sb)\n\n\t\tdefault:\n\t\t\tvar sum word\n\t\t\tfor i := range sb.bits {\n\t\t\t\tr := xb.bits[i] & sb.bits[i]\n\t\t\t\tsb.bits[i] = r\n\t\t\t\tsum |= r\n\t\t\t}\n\t\t\tif sum != 0 {\n\t\t\t\tsb = s.next(sb)\n\t\t\t} else {\n\t\t\t\t// sb will be overwritten or removed\n\t\t\t}\n\n\t\t\txb = x.next(xb)\n\t\t}\n\t}\n\n\ts.discardTail(sb)\n}\n\n// Intersection sets s to the intersection x ∩ y.\nfunc (s *Sparse) Intersection(x, y *Sparse) {\n\tswitch {\n\tcase s == x:\n\t\ts.IntersectionWith(y)\n\t\treturn\n\tcase s == y:\n\t\ts.IntersectionWith(x)\n\t\treturn\n\tcase x == y:\n\t\ts.Copy(x)\n\t\treturn\n\t}\n\n\txb := x.first()\n\tyb := y.first()\n\tsb := s.first()\n\tfor xb != &none && yb != &none {\n\t\tswitch {\n\t\tcase xb.offset < yb.offset:\n\t\t\txb = x.next(xb)\n\t\t\tcontinue\n\t\tcase xb.offset > yb.offset:\n\t\t\tyb = y.next(yb)\n\t\t\tcontinue\n\t\t}\n\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = xb.offset\n\n\t\tvar sum word\n\t\tfor i := range sb.bits {\n\t\t\tr := xb.bits[i] & yb.bits[i]\n\t\t\tsb.bits[i] = r\n\t\t\tsum |= r\n\t\t}\n\t\tif sum != 0 {\n\t\t\tsb = s.next(sb)\n\t\t} else {\n\t\t\t// sb will be overwritten or removed\n\t\t}\n\n\t\txb = x.next(xb)\n\t\tyb = y.next(yb)\n\t}\n\n\ts.discardTail(sb)\n}\n\n// Intersects reports whether s ∩ x ≠ ∅.\nfunc (s *Sparse) Intersects(x *Sparse) bool {\n\tsb := s.first()\n\txb := x.first()\n\tfor sb != &none && xb != &none {\n\t\tswitch {\n\t\tcase xb.offset < sb.offset:\n\t\t\txb = x.next(xb)\n\t\tcase xb.offset > sb.offset:\n\t\t\tsb = s.next(sb)\n\t\tdefault:\n\t\t\tfor i := range sb.bits {\n\t\t\t\tif sb.bits[i]&xb.bits[i] != 0 {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb = s.next(sb)\n\t\t\txb = x.next(xb)\n\t\t}\n\t}\n\treturn false\n}\n\n// UnionWith sets s to the union s ∪ x, and reports whether s grew.\nfunc (s *Sparse) UnionWith(x *Sparse) bool {\n\tif s == x {\n\t\treturn false\n\t}\n\n\tvar changed bool\n\txb := x.first()\n\tsb := s.first()\n\tfor xb != &none {\n\t\tif sb != &none && sb.offset == xb.offset {\n\t\t\tfor i := range xb.bits {\n\t\t\t\tunion := sb.bits[i] | xb.bits[i]\n\t\t\t\tif sb.bits[i] != union {\n\t\t\t\t\tsb.bits[i] = union\n\t\t\t\t\tchanged = true\n\t\t\t\t}\n\t\t\t}\n\t\t\txb = x.next(xb)\n\t\t} else if sb == &none || sb.offset > xb.offset {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t\tsb.offset = xb.offset\n\t\t\tsb.bits = xb.bits\n\t\t\tchanged = true\n\n\t\t\txb = x.next(xb)\n\t\t}\n\t\tsb = s.next(sb)\n\t}\n\treturn changed\n}\n\n// Union sets s to the union x ∪ y.\nfunc (s *Sparse) Union(x, y *Sparse) {\n\tswitch {\n\tcase x == y:\n\t\ts.Copy(x)\n\t\treturn\n\tcase s == x:\n\t\ts.UnionWith(y)\n\t\treturn\n\tcase s == y:\n\t\ts.UnionWith(x)\n\t\treturn\n\t}\n\n\txb := x.first()\n\tyb := y.first()\n\tsb := s.first()\n\tfor xb != &none || yb != &none {\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tswitch {\n\t\tcase yb == &none || (xb != &none && xb.offset < yb.offset):\n\t\t\tsb.offset = xb.offset\n\t\t\tsb.bits = xb.bits\n\t\t\txb = x.next(xb)\n\n\t\tcase xb == &none || (yb != &none && yb.offset < xb.offset):\n\t\t\tsb.offset = yb.offset\n\t\t\tsb.bits = yb.bits\n\t\t\tyb = y.next(yb)\n\n\t\tdefault:\n\t\t\tsb.offset = xb.offset\n\t\t\tfor i := range xb.bits {\n\t\t\t\tsb.bits[i] = xb.bits[i] | yb.bits[i]\n\t\t\t}\n\t\t\txb = x.next(xb)\n\t\t\tyb = y.next(yb)\n\t\t}\n\t\tsb = s.next(sb)\n\t}\n\n\ts.discardTail(sb)\n}\n\n// DifferenceWith sets s to the difference s ∖ x.\nfunc (s *Sparse) DifferenceWith(x *Sparse) {\n\tif s == x {\n\t\ts.Clear()\n\t\treturn\n\t}\n\n\txb := x.first()\n\tsb := s.first()\n\tfor xb != &none && sb != &none {\n\t\tswitch {\n\t\tcase xb.offset > sb.offset:\n\t\t\tsb = s.next(sb)\n\n\t\tcase xb.offset < sb.offset:\n\t\t\txb = x.next(xb)\n\n\t\tdefault:\n\t\t\tvar sum word\n\t\t\tfor i := range sb.bits {\n\t\t\t\tr := sb.bits[i] & ^xb.bits[i]\n\t\t\t\tsb.bits[i] = r\n\t\t\t\tsum |= r\n\t\t\t}\n\t\t\tif sum == 0 {\n\t\t\t\tsb = s.removeBlock(sb)\n\t\t\t} else {\n\t\t\t\tsb = s.next(sb)\n\t\t\t}\n\t\t\txb = x.next(xb)\n\t\t}\n\t}\n}\n\n// Difference sets s to the difference x ∖ y.\nfunc (s *Sparse) Difference(x, y *Sparse) {\n\tswitch {\n\tcase x == y:\n\t\ts.Clear()\n\t\treturn\n\tcase s == x:\n\t\ts.DifferenceWith(y)\n\t\treturn\n\tcase s == y:\n\t\tvar y2 Sparse\n\t\ty2.Copy(y)\n\t\ts.Difference(x, &y2)\n\t\treturn\n\t}\n\n\txb := x.first()\n\tyb := y.first()\n\tsb := s.first()\n\tfor xb != &none && yb != &none {\n\t\tif xb.offset > yb.offset {\n\t\t\t// y has block, x has &none\n\t\t\tyb = y.next(yb)\n\t\t\tcontinue\n\t\t}\n\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = xb.offset\n\n\t\tswitch {\n\t\tcase xb.offset < yb.offset:\n\t\t\t// x has block, y has &none\n\t\t\tsb.bits = xb.bits\n\n\t\t\tsb = s.next(sb)\n\n\t\tdefault:\n\t\t\t// x and y have corresponding blocks\n\t\t\tvar sum word\n\t\t\tfor i := range sb.bits {\n\t\t\t\tr := xb.bits[i] & ^yb.bits[i]\n\t\t\t\tsb.bits[i] = r\n\t\t\t\tsum |= r\n\t\t\t}\n\t\t\tif sum != 0 {\n\t\t\t\tsb = s.next(sb)\n\t\t\t} else {\n\t\t\t\t// sb will be overwritten or removed\n\t\t\t}\n\n\t\t\tyb = y.next(yb)\n\t\t}\n\t\txb = x.next(xb)\n\t}\n\n\tfor xb != &none {\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = xb.offset\n\t\tsb.bits = xb.bits\n\t\tsb = s.next(sb)\n\n\t\txb = x.next(xb)\n\t}\n\n\ts.discardTail(sb)\n}\n\n// SymmetricDifferenceWith sets s to the symmetric difference s ∆ x.\nfunc (s *Sparse) SymmetricDifferenceWith(x *Sparse) {\n\tif s == x {\n\t\ts.Clear()\n\t\treturn\n\t}\n\n\tsb := s.first()\n\txb := x.first()\n\tfor xb != &none && sb != &none {\n\t\tswitch {\n\t\tcase sb.offset < xb.offset:\n\t\t\tsb = s.next(sb)\n\t\tcase xb.offset < sb.offset:\n\t\t\tnb := s.insertBlockBefore(sb)\n\t\t\tnb.offset = xb.offset\n\t\t\tnb.bits = xb.bits\n\t\t\txb = x.next(xb)\n\t\tdefault:\n\t\t\tvar sum word\n\t\t\tfor i := range sb.bits {\n\t\t\t\tr := sb.bits[i] ^ xb.bits[i]\n\t\t\t\tsb.bits[i] = r\n\t\t\t\tsum |= r\n\t\t\t}\n\t\t\tif sum == 0 {\n\t\t\t\tsb = s.removeBlock(sb)\n\t\t\t} else {\n\t\t\t\tsb = s.next(sb)\n\t\t\t}\n\t\t\txb = x.next(xb)\n\t\t}\n\t}\n\n\tfor xb != &none { // append the tail of x to s\n\t\tsb = s.insertBlockBefore(sb)\n\t\tsb.offset = xb.offset\n\t\tsb.bits = xb.bits\n\t\tsb = s.next(sb)\n\t\txb = x.next(xb)\n\t}\n}\n\n// SymmetricDifference sets s to the symmetric difference x ∆ y.\nfunc (s *Sparse) SymmetricDifference(x, y *Sparse) {\n\tswitch {\n\tcase x == y:\n\t\ts.Clear()\n\t\treturn\n\tcase s == x:\n\t\ts.SymmetricDifferenceWith(y)\n\t\treturn\n\tcase s == y:\n\t\ts.SymmetricDifferenceWith(x)\n\t\treturn\n\t}\n\n\tsb := s.first()\n\txb := x.first()\n\tyb := y.first()\n\tfor xb != &none && yb != &none {\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tswitch {\n\t\tcase yb.offset < xb.offset:\n\t\t\tsb.offset = yb.offset\n\t\t\tsb.bits = yb.bits\n\t\t\tsb = s.next(sb)\n\t\t\tyb = y.next(yb)\n\t\tcase xb.offset < yb.offset:\n\t\t\tsb.offset = xb.offset\n\t\t\tsb.bits = xb.bits\n\t\t\tsb = s.next(sb)\n\t\t\txb = x.next(xb)\n\t\tdefault:\n\t\t\tvar sum word\n\t\t\tfor i := range sb.bits {\n\t\t\t\tr := xb.bits[i] ^ yb.bits[i]\n\t\t\t\tsb.bits[i] = r\n\t\t\t\tsum |= r\n\t\t\t}\n\t\t\tif sum != 0 {\n\t\t\t\tsb.offset = xb.offset\n\t\t\t\tsb = s.next(sb)\n\t\t\t}\n\t\t\txb = x.next(xb)\n\t\t\tyb = y.next(yb)\n\t\t}\n\t}\n\n\tfor xb != &none { // append the tail of x to s\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = xb.offset\n\t\tsb.bits = xb.bits\n\t\tsb = s.next(sb)\n\t\txb = x.next(xb)\n\t}\n\n\tfor yb != &none { // append the tail of y to s\n\t\tif sb == &none {\n\t\t\tsb = s.insertBlockBefore(sb)\n\t\t}\n\t\tsb.offset = yb.offset\n\t\tsb.bits = yb.bits\n\t\tsb = s.next(sb)\n\t\tyb = y.next(yb)\n\t}\n\n\ts.discardTail(sb)\n}\n\n// SubsetOf reports whether s ∖ x = ∅.\nfunc (s *Sparse) SubsetOf(x *Sparse) bool {\n\tif s == x {\n\t\treturn true\n\t}\n\n\tsb := s.first()\n\txb := x.first()\n\tfor sb != &none {\n\t\tswitch {\n\t\tcase xb == &none || xb.offset > sb.offset:\n\t\t\treturn false\n\t\tcase xb.offset < sb.offset:\n\t\t\txb = x.next(xb)\n\t\tdefault:\n\t\t\tfor i := range sb.bits {\n\t\t\t\tif sb.bits[i]&^xb.bits[i] != 0 {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb = s.next(sb)\n\t\t\txb = x.next(xb)\n\t\t}\n\t}\n\treturn true\n}\n\n// Equals reports whether the sets s and t have the same elements.\nfunc (s *Sparse) Equals(t *Sparse) bool {\n\tif s == t {\n\t\treturn true\n\t}\n\tsb := s.first()\n\ttb := t.first()\n\tfor {\n\t\tswitch {\n\t\tcase sb == &none && tb == &none:\n\t\t\treturn true\n\t\tcase sb == &none || tb == &none:\n\t\t\treturn false\n\t\tcase sb.offset != tb.offset:\n\t\t\treturn false\n\t\tcase sb.bits != tb.bits:\n\t\t\treturn false\n\t\t}\n\n\t\tsb = s.next(sb)\n\t\ttb = t.next(tb)\n\t}\n}\n\n// String returns a human-readable description of the set s.\nfunc (s *Sparse) String() string {\n\tvar buf bytes.Buffer\n\tbuf.WriteByte('{')\n\ts.forEach(func(x int) {\n\t\tif buf.Len() > 1 {\n\t\t\tbuf.WriteByte(' ')\n\t\t}\n\t\tfmt.Fprintf(&buf, \"%d\", x)\n\t})\n\tbuf.WriteByte('}')\n\treturn buf.String()\n}\n\n// BitString returns the set as a string of 1s and 0s denoting the sum\n// of the i'th powers of 2, for each i in s.  A radix point, always\n// preceded by a digit, appears if the sum is non-integral.\n//\n// Examples:\n//\n//\t        {}.BitString() =      \"0\"\n//\t     {4,5}.BitString() = \"110000\"\n//\t      {-3}.BitString() =      \"0.001\"\n//\t{-3,0,4,5}.BitString() = \"110001.001\"\nfunc (s *Sparse) BitString() string {\n\tif s.IsEmpty() {\n\t\treturn \"0\"\n\t}\n\n\tmin, max := s.Min(), s.Max()\n\tvar nbytes int\n\tif max > 0 {\n\t\tnbytes = max\n\t}\n\tnbytes++ // zero bit\n\tradix := nbytes\n\tif min < 0 {\n\t\tnbytes += len(\".\") - min\n\t}\n\n\tb := make([]byte, nbytes)\n\tfor i := range b {\n\t\tb[i] = '0'\n\t}\n\tif radix < nbytes {\n\t\tb[radix] = '.'\n\t}\n\ts.forEach(func(x int) {\n\t\tif x >= 0 {\n\t\t\tx += len(\".\")\n\t\t}\n\t\tb[radix-x] = '1'\n\t})\n\treturn string(b)\n}\n\n// GoString returns a string showing the internal representation of\n// the set s.\nfunc (s *Sparse) GoString() string {\n\tvar buf bytes.Buffer\n\tfor b := s.first(); b != &none; b = s.next(b) {\n\t\tfmt.Fprintf(&buf, \"block %p {offset=%d next=%p prev=%p\",\n\t\t\tb, b.offset, b.next, b.prev)\n\t\tfor _, w := range b.bits {\n\t\t\tfmt.Fprintf(&buf, \" 0%016x\", w)\n\t\t}\n\t\tfmt.Fprintf(&buf, \"}\\n\")\n\t}\n\treturn buf.String()\n}\n\n// AppendTo returns the result of appending the elements of s to slice\n// in order.\nfunc (s *Sparse) AppendTo(slice []int) []int {\n\ts.forEach(func(x int) {\n\t\tslice = append(slice, x)\n\t})\n\treturn slice\n}\n\n// -- Testing/debugging ------------------------------------------------\n\n// check returns an error if the representation invariants of s are violated.\n// (unused; retained for debugging)\nfunc (s *Sparse) check() error {\n\ts.init()\n\tif s.root.empty() {\n\t\t// An empty set must have only the root block with offset MaxInt.\n\t\tif s.root.next != &s.root {\n\t\t\treturn fmt.Errorf(\"multiple blocks with empty root block\")\n\t\t}\n\t\tif s.root.offset != MaxInt {\n\t\t\treturn fmt.Errorf(\"empty set has offset %d, should be MaxInt\", s.root.offset)\n\t\t}\n\t\treturn nil\n\t}\n\tfor b := s.first(); ; b = s.next(b) {\n\t\tif b.offset%bitsPerBlock != 0 {\n\t\t\treturn fmt.Errorf(\"bad offset modulo: %d\", b.offset)\n\t\t}\n\t\tif b.empty() {\n\t\t\treturn fmt.Errorf(\"empty block\")\n\t\t}\n\t\tif b.prev.next != b {\n\t\t\treturn fmt.Errorf(\"bad prev.next link\")\n\t\t}\n\t\tif b.next.prev != b {\n\t\t\treturn fmt.Errorf(\"bad next.prev link\")\n\t\t}\n\t\tif b.next == &s.root {\n\t\t\tbreak\n\t\t}\n\t\tif b.offset >= b.next.offset {\n\t\t\treturn fmt.Errorf(\"bad offset order: b.offset=%d, b.next.offset=%d\",\n\t\t\t\tb.offset, b.next.offset)\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "container/intsets/sparse_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage intsets_test\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/container/intsets\"\n)\n\nfunc TestBasics(t *testing.T) {\n\tvar s intsets.Sparse\n\tif len := s.Len(); len != 0 {\n\t\tt.Errorf(\"Len({}): got %d, want 0\", len)\n\t}\n\tif s := s.String(); s != \"{}\" {\n\t\tt.Errorf(\"String({}): got %q, want \\\"{}\\\"\", s)\n\t}\n\tif s.Has(3) {\n\t\tt.Errorf(\"Has(3): got true, want false\")\n\t}\n\tif err := s.Check(); err != nil {\n\t\tt.Error(err)\n\t}\n\n\tif !s.Insert(3) {\n\t\tt.Errorf(\"Insert(3): got false, want true\")\n\t}\n\tif max := s.Max(); max != 3 {\n\t\tt.Errorf(\"Max: got %d, want 3\", max)\n\t}\n\n\tif !s.Insert(435) {\n\t\tt.Errorf(\"Insert(435): got false, want true\")\n\t}\n\tif s := s.String(); s != \"{3 435}\" {\n\t\tt.Errorf(\"String({3 435}): got %q, want \\\"{3 435}\\\"\", s)\n\t}\n\tif max := s.Max(); max != 435 {\n\t\tt.Errorf(\"Max: got %d, want 435\", max)\n\t}\n\tif len := s.Len(); len != 2 {\n\t\tt.Errorf(\"Len: got %d, want 2\", len)\n\t}\n\n\tif !s.Remove(435) {\n\t\tt.Errorf(\"Remove(435): got false, want true\")\n\t}\n\tif s := s.String(); s != \"{3}\" {\n\t\tt.Errorf(\"String({3}): got %q, want \\\"{3}\\\"\", s)\n\t}\n}\n\n// Insert, Len, IsEmpty, Hash, Clear, AppendTo.\nfunc TestMoreBasics(t *testing.T) {\n\tset := new(intsets.Sparse)\n\tset.Insert(456)\n\tset.Insert(123)\n\tset.Insert(789)\n\tif set.Len() != 3 {\n\t\tt.Errorf(\"%s.Len: got %d, want 3\", set, set.Len())\n\t}\n\tif set.IsEmpty() {\n\t\tt.Errorf(\"%s.IsEmpty: got true\", set)\n\t}\n\tif !set.Has(123) {\n\t\tt.Errorf(\"%s.Has(123): got false\", set)\n\t}\n\tif set.Has(1234) {\n\t\tt.Errorf(\"%s.Has(1234): got true\", set)\n\t}\n\tgot := set.AppendTo([]int{-1})\n\tif want := []int{-1, 123, 456, 789}; fmt.Sprint(got) != fmt.Sprint(want) {\n\t\tt.Errorf(\"%s.AppendTo: got %v, want %v\", set, got, want)\n\t}\n\n\tset.Clear()\n\n\tif set.Len() != 0 {\n\t\tt.Errorf(\"Clear: got %d, want 0\", set.Len())\n\t}\n\tif !set.IsEmpty() {\n\t\tt.Errorf(\"IsEmpty: got false\")\n\t}\n\tif set.Has(123) {\n\t\tt.Errorf(\"%s.Has: got false\", set)\n\t}\n}\n\nfunc TestTakeMin(t *testing.T) {\n\tvar set intsets.Sparse\n\tset.Insert(456)\n\tset.Insert(123)\n\tset.Insert(789)\n\tset.Insert(-123)\n\tvar got int\n\tfor i, want := range []int{-123, 123, 456, 789} {\n\t\tif !set.TakeMin(&got) || got != want {\n\t\t\tt.Errorf(\"TakeMin #%d: got %d, want %d\", i, got, want)\n\t\t}\n\t}\n\tif set.TakeMin(&got) {\n\t\tt.Errorf(\"%s.TakeMin returned true\", &set)\n\t}\n\tif err := set.Check(); err != nil {\n\t\tt.Fatalf(\"check: %s: %#v\", err, &set)\n\t}\n}\n\nfunc TestMinAndMax(t *testing.T) {\n\tvalues := []int{0, 456, 123, 789, -123} // elt 0 => empty set\n\twantMax := []int{intsets.MinInt, 456, 456, 789, 789}\n\twantMin := []int{intsets.MaxInt, 456, 123, 123, -123}\n\n\tvar set intsets.Sparse\n\tfor i, x := range values {\n\t\tif i != 0 {\n\t\t\tset.Insert(x)\n\t\t}\n\t\tif got, want := set.Min(), wantMin[i]; got != want {\n\t\t\tt.Errorf(\"Min #%d: got %d, want %d\", i, got, want)\n\t\t}\n\t\tif got, want := set.Max(), wantMax[i]; got != want {\n\t\t\tt.Errorf(\"Max #%d: got %d, want %d\", i, got, want)\n\t\t}\n\t}\n\n\tset.Insert(intsets.MinInt)\n\tif got, want := set.Min(), intsets.MinInt; got != want {\n\t\tt.Errorf(\"Min: got %d, want %d\", got, want)\n\t}\n\n\tset.Insert(intsets.MaxInt)\n\tif got, want := set.Max(), intsets.MaxInt; got != want {\n\t\tt.Errorf(\"Max: got %d, want %d\", got, want)\n\t}\n}\n\nfunc TestEquals(t *testing.T) {\n\tvar setX intsets.Sparse\n\tsetX.Insert(456)\n\tsetX.Insert(123)\n\tsetX.Insert(789)\n\n\tif !setX.Equals(&setX) {\n\t\tt.Errorf(\"Equals(%s, %s): got false\", &setX, &setX)\n\t}\n\n\tvar setY intsets.Sparse\n\tsetY.Insert(789)\n\tsetY.Insert(456)\n\tsetY.Insert(123)\n\n\tif !setX.Equals(&setY) {\n\t\tt.Errorf(\"Equals(%s, %s): got false\", &setX, &setY)\n\t}\n\n\tsetY.Insert(1)\n\tif setX.Equals(&setY) {\n\t\tt.Errorf(\"Equals(%s, %s): got true\", &setX, &setY)\n\t}\n\n\tvar empty intsets.Sparse\n\tif setX.Equals(&empty) {\n\t\tt.Errorf(\"Equals(%s, %s): got true\", &setX, &empty)\n\t}\n\n\t// Edge case: some block (with offset=0) appears in X but not Y.\n\tsetY.Remove(123)\n\tif setX.Equals(&setY) {\n\t\tt.Errorf(\"Equals(%s, %s): got true\", &setX, &setY)\n\t}\n}\n\n// A pset is a parallel implementation of a set using both an intsets.Sparse\n// and a built-in hash map.\ntype pset struct {\n\thash map[int]bool\n\tbits intsets.Sparse\n}\n\nfunc makePset() *pset {\n\treturn &pset{hash: make(map[int]bool)}\n}\n\nfunc (set *pset) add(n int) {\n\tprev := len(set.hash)\n\tset.hash[n] = true\n\tgrewA := len(set.hash) > prev\n\n\tgrewB := set.bits.Insert(n)\n\n\tif grewA != grewB {\n\t\tpanic(fmt.Sprintf(\"add(%d): grewA=%t grewB=%t\", n, grewA, grewB))\n\t}\n}\n\nfunc (set *pset) remove(n int) {\n\tprev := len(set.hash)\n\tdelete(set.hash, n)\n\tshrankA := len(set.hash) < prev\n\n\tshrankB := set.bits.Remove(n)\n\n\tif shrankA != shrankB {\n\t\tpanic(fmt.Sprintf(\"remove(%d): shrankA=%t shrankB=%t\", n, shrankA, shrankB))\n\t}\n}\n\nfunc (set *pset) check(t *testing.T, msg string) {\n\tvar eltsA []int\n\tfor elt := range set.hash {\n\t\teltsA = append(eltsA, int(elt))\n\t}\n\tsort.Ints(eltsA)\n\n\teltsB := set.bits.AppendTo(nil)\n\n\tif a, b := fmt.Sprint(eltsA), fmt.Sprint(eltsB); a != b {\n\t\tt.Errorf(\"check(%s): hash=%s bits=%s (%s)\", msg, a, b, &set.bits)\n\t}\n\n\tif err := set.bits.Check(); err != nil {\n\t\tt.Fatalf(\"Check(%s): %s: %#v\", msg, err, &set.bits)\n\t}\n}\n\n// randomPset returns a parallel set of random size and elements.\nfunc randomPset(prng *rand.Rand, maxSize int) *pset {\n\tset := makePset()\n\tsize := int(prng.Int()) % maxSize\n\tfor range size {\n\t\t// TODO(adonovan): benchmark how performance varies\n\t\t// with this sparsity parameter.\n\t\tn := int(prng.Int()) % 10000\n\t\tset.add(n)\n\t}\n\treturn set\n}\n\n// TestRandomMutations performs the same random adds/removes on two\n// set implementations and ensures that they compute the same result.\nfunc TestRandomMutations(t *testing.T) {\n\tconst debug = false\n\n\tset := makePset()\n\tprng := rand.New(rand.NewSource(0))\n\tfor i := range 10000 {\n\t\tn := int(prng.Int())%2000 - 1000\n\t\tif i%2 == 0 {\n\t\t\tif debug {\n\t\t\t\tlog.Printf(\"add %d\", n)\n\t\t\t}\n\t\t\tset.add(n)\n\t\t} else {\n\t\t\tif debug {\n\t\t\t\tlog.Printf(\"remove %d\", n)\n\t\t\t}\n\t\t\tset.remove(n)\n\t\t}\n\t\tif debug {\n\t\t\tset.check(t, \"post mutation\")\n\t\t}\n\t}\n\tset.check(t, \"final\")\n\tif debug {\n\t\tlog.Print(&set.bits)\n\t}\n}\n\nfunc TestLowerBound(t *testing.T) {\n\t// Use random sets of sizes from 0 to about 4000.\n\tprng := rand.New(rand.NewSource(0))\n\tfor i := range uint(12) {\n\t\tx := randomPset(prng, 1<<i)\n\t\tfor j := range 10000 {\n\t\t\tfound := intsets.MaxInt\n\t\t\tfor e := range x.hash {\n\t\t\t\tif e >= j && e < found {\n\t\t\t\t\tfound = e\n\t\t\t\t}\n\t\t\t}\n\t\t\tif res := x.bits.LowerBound(j); res != found {\n\t\t\t\tt.Errorf(\"%s: LowerBound(%d)=%d, expected %d\", &x.bits, j, res, found)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestSetOperations exercises classic set operations: ∩ , ∪, \\.\nfunc TestSetOperations(t *testing.T) {\n\tprng := rand.New(rand.NewSource(0))\n\n\t// Use random sets of sizes from 0 to about 4000.\n\t// For each operator, we test variations such as\n\t// Z.op(X, Y), Z.op(X, Z) and Z.op(Z, Y) to exercise\n\t// the degenerate cases of each method implementation.\n\tfor i := range uint(12) {\n\t\tX := randomPset(prng, 1<<i)\n\t\tY := randomPset(prng, 1<<i)\n\n\t\t// TODO(adonovan): minimise dependencies between stanzas below.\n\n\t\t// Copy(X)\n\t\tC := makePset()\n\t\tC.bits.Copy(&Y.bits) // no effect on result\n\t\tC.bits.Copy(&X.bits)\n\t\tC.hash = X.hash\n\t\tC.check(t, \"C.Copy(X)\")\n\t\tC.bits.Copy(&C.bits)\n\t\tC.check(t, \"C.Copy(C)\")\n\n\t\t// U.Union(X, Y)\n\t\tU := makePset()\n\t\tU.bits.Union(&X.bits, &Y.bits)\n\t\tfor n := range X.hash {\n\t\t\tU.hash[n] = true\n\t\t}\n\t\tfor n := range Y.hash {\n\t\t\tU.hash[n] = true\n\t\t}\n\t\tU.check(t, \"U.Union(X, Y)\")\n\n\t\t// U.Union(X, X)\n\t\tU.bits.Union(&X.bits, &X.bits)\n\t\tU.hash = X.hash\n\t\tU.check(t, \"U.Union(X, X)\")\n\n\t\t// U.Union(U, Y)\n\t\tU = makePset()\n\t\tU.bits.Copy(&X.bits)\n\t\tU.bits.Union(&U.bits, &Y.bits)\n\t\tfor n := range X.hash {\n\t\t\tU.hash[n] = true\n\t\t}\n\t\tfor n := range Y.hash {\n\t\t\tU.hash[n] = true\n\t\t}\n\t\tU.check(t, \"U.Union(U, Y)\")\n\n\t\t// U.Union(X, U)\n\t\tU.bits.Copy(&Y.bits)\n\t\tU.bits.Union(&X.bits, &U.bits)\n\t\tU.check(t, \"U.Union(X, U)\")\n\n\t\t// U.UnionWith(U)\n\t\tU.bits.UnionWith(&U.bits)\n\t\tU.check(t, \"U.UnionWith(U)\")\n\n\t\t// I.Intersection(X, Y)\n\t\tI := makePset()\n\t\tI.bits.Intersection(&X.bits, &Y.bits)\n\t\tfor n := range X.hash {\n\t\t\tif Y.hash[n] {\n\t\t\t\tI.hash[n] = true\n\t\t\t}\n\t\t}\n\t\tI.check(t, \"I.Intersection(X, Y)\")\n\n\t\t// I.Intersection(X, X)\n\t\tI.bits.Intersection(&X.bits, &X.bits)\n\t\tI.hash = X.hash\n\t\tI.check(t, \"I.Intersection(X, X)\")\n\n\t\t// I.Intersection(I, X)\n\t\tI.bits.Intersection(&I.bits, &X.bits)\n\t\tI.check(t, \"I.Intersection(I, X)\")\n\n\t\t// I.Intersection(X, I)\n\t\tI.bits.Intersection(&X.bits, &I.bits)\n\t\tI.check(t, \"I.Intersection(X, I)\")\n\n\t\t// I.Intersection(I, I)\n\t\tI.bits.Intersection(&I.bits, &I.bits)\n\t\tI.check(t, \"I.Intersection(I, I)\")\n\n\t\t// D.Difference(X, Y)\n\t\tD := makePset()\n\t\tD.bits.Difference(&X.bits, &Y.bits)\n\t\tfor n := range X.hash {\n\t\t\tif !Y.hash[n] {\n\t\t\t\tD.hash[n] = true\n\t\t\t}\n\t\t}\n\t\tD.check(t, \"D.Difference(X, Y)\")\n\n\t\t// D.Difference(D, Y)\n\t\tD.bits.Copy(&X.bits)\n\t\tD.bits.Difference(&D.bits, &Y.bits)\n\t\tD.check(t, \"D.Difference(D, Y)\")\n\n\t\t// D.Difference(Y, D)\n\t\tD.bits.Copy(&X.bits)\n\t\tD.bits.Difference(&Y.bits, &D.bits)\n\t\tD.hash = make(map[int]bool)\n\t\tfor n := range Y.hash {\n\t\t\tif !X.hash[n] {\n\t\t\t\tD.hash[n] = true\n\t\t\t}\n\t\t}\n\t\tD.check(t, \"D.Difference(Y, D)\")\n\n\t\t// D.Difference(X, X)\n\t\tD.bits.Difference(&X.bits, &X.bits)\n\t\tD.hash = nil\n\t\tD.check(t, \"D.Difference(X, X)\")\n\n\t\t// D.DifferenceWith(D)\n\t\tD.bits.Copy(&X.bits)\n\t\tD.bits.DifferenceWith(&D.bits)\n\t\tD.check(t, \"D.DifferenceWith(D)\")\n\n\t\t// SD.SymmetricDifference(X, Y)\n\t\tSD := makePset()\n\t\tSD.bits.SymmetricDifference(&X.bits, &Y.bits)\n\t\tfor n := range X.hash {\n\t\t\tif !Y.hash[n] {\n\t\t\t\tSD.hash[n] = true\n\t\t\t}\n\t\t}\n\t\tfor n := range Y.hash {\n\t\t\tif !X.hash[n] {\n\t\t\t\tSD.hash[n] = true\n\t\t\t}\n\t\t}\n\t\tSD.check(t, \"SD.SymmetricDifference(X, Y)\")\n\n\t\t// X.SymmetricDifferenceWith(Y)\n\t\tSD.bits.Copy(&X.bits)\n\t\tSD.bits.SymmetricDifferenceWith(&Y.bits)\n\t\tSD.check(t, \"X.SymmetricDifference(Y)\")\n\n\t\t// Y.SymmetricDifferenceWith(X)\n\t\tSD.bits.Copy(&Y.bits)\n\t\tSD.bits.SymmetricDifferenceWith(&X.bits)\n\t\tSD.check(t, \"Y.SymmetricDifference(X)\")\n\n\t\t// SD.SymmetricDifference(X, X)\n\t\tSD.bits.SymmetricDifference(&X.bits, &X.bits)\n\t\tSD.hash = nil\n\t\tSD.check(t, \"SD.SymmetricDifference(X, X)\")\n\n\t\t// SD.SymmetricDifference(X, Copy(X))\n\t\tX2 := makePset()\n\t\tX2.bits.Copy(&X.bits)\n\t\tSD.bits.SymmetricDifference(&X.bits, &X2.bits)\n\t\tSD.check(t, \"SD.SymmetricDifference(X, Copy(X))\")\n\n\t\t// Copy(X).SymmetricDifferenceWith(X)\n\t\tSD.bits.Copy(&X.bits)\n\t\tSD.bits.SymmetricDifferenceWith(&X.bits)\n\t\tSD.check(t, \"Copy(X).SymmetricDifferenceWith(X)\")\n\t}\n}\n\n// TestUnionWithChanged checks the 'changed' result of UnionWith.\nfunc TestUnionWithChanged(t *testing.T) {\n\tsetOf := func(elems ...int) *intsets.Sparse {\n\t\ts := new(intsets.Sparse)\n\t\tfor _, elem := range elems {\n\t\t\ts.Insert(elem)\n\t\t}\n\t\treturn s\n\t}\n\n\tcheckUnionWith := func(x, y *intsets.Sparse) {\n\t\txstr := x.String()\n\t\tprelen := x.Len()\n\t\tchanged := x.UnionWith(y)\n\t\tif (x.Len() > prelen) != changed {\n\t\t\tt.Errorf(\"%s.UnionWith(%s) => %s, changed=%t\", xstr, y, x, changed)\n\t\t}\n\t}\n\n\t// The case marked \"!\" is a regression test for Issue 50352,\n\t// which spuriously returned true when y ⊂ x.\n\n\t// same block\n\tcheckUnionWith(setOf(1, 2), setOf(1, 2))\n\tcheckUnionWith(setOf(1, 2, 3), setOf(1, 2)) // !\n\tcheckUnionWith(setOf(1, 2), setOf(1, 2, 3))\n\tcheckUnionWith(setOf(1, 2), setOf())\n\n\t// different blocks\n\tcheckUnionWith(setOf(1, 1000000), setOf(1, 1000000))\n\tcheckUnionWith(setOf(1, 2, 1000000), setOf(1, 2))\n\tcheckUnionWith(setOf(1, 2), setOf(1, 2, 1000000))\n\tcheckUnionWith(setOf(1, 1000000), setOf())\n}\n\nfunc TestIntersectionWith(t *testing.T) {\n\t// Edge cases: the pairs (1,1), (1000,2000), (8000,4000)\n\t// exercise the <, >, == cases in IntersectionWith that the\n\t// TestSetOperations data is too dense to cover.\n\tvar X, Y intsets.Sparse\n\tX.Insert(1)\n\tX.Insert(1000)\n\tX.Insert(8000)\n\tY.Insert(1)\n\tY.Insert(2000)\n\tY.Insert(4000)\n\tX.IntersectionWith(&Y)\n\tif got, want := X.String(), \"{1}\"; got != want {\n\t\tt.Errorf(\"IntersectionWith: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestIntersects(t *testing.T) {\n\tprng := rand.New(rand.NewSource(0))\n\n\tfor i := range uint(12) {\n\t\tX, Y := randomPset(prng, 1<<i), randomPset(prng, 1<<i)\n\t\tx, y := &X.bits, &Y.bits\n\n\t\t// test the slow way\n\t\tvar z intsets.Sparse\n\t\tz.Copy(x)\n\t\tz.IntersectionWith(y)\n\n\t\tif got, want := x.Intersects(y), !z.IsEmpty(); got != want {\n\t\t\tt.Errorf(\"Intersects(%s, %s): got %v, want %v (%s)\", x, y, got, want, &z)\n\t\t}\n\n\t\t// make it false\n\t\ta := x.AppendTo(nil)\n\t\tfor _, v := range a {\n\t\t\ty.Remove(v)\n\t\t}\n\n\t\tif got, want := x.Intersects(y), false; got != want {\n\t\t\tt.Errorf(\"Intersects: got %v, want %v\", got, want)\n\t\t}\n\n\t\t// make it true\n\t\tif x.IsEmpty() {\n\t\t\tcontinue\n\t\t}\n\t\ti := prng.Intn(len(a))\n\t\ty.Insert(a[i])\n\n\t\tif got, want := x.Intersects(y), true; got != want {\n\t\t\tt.Errorf(\"Intersects: got %v, want %v\", got, want)\n\t\t}\n\t}\n}\n\nfunc TestSubsetOf(t *testing.T) {\n\tprng := rand.New(rand.NewSource(0))\n\n\tfor i := range uint(12) {\n\t\tX, Y := randomPset(prng, 1<<i), randomPset(prng, 1<<i)\n\t\tx, y := &X.bits, &Y.bits\n\n\t\t// test the slow way\n\t\tvar z intsets.Sparse\n\t\tz.Copy(x)\n\t\tz.DifferenceWith(y)\n\n\t\tif got, want := x.SubsetOf(y), z.IsEmpty(); got != want {\n\t\t\tt.Errorf(\"SubsetOf: got %v, want %v\", got, want)\n\t\t}\n\n\t\t// make it true\n\t\ty.UnionWith(x)\n\n\t\tif got, want := x.SubsetOf(y), true; got != want {\n\t\t\tt.Errorf(\"SubsetOf: got %v, want %v\", got, want)\n\t\t}\n\n\t\t// make it false\n\t\tif x.IsEmpty() {\n\t\t\tcontinue\n\t\t}\n\t\ta := x.AppendTo(nil)\n\t\ti := prng.Intn(len(a))\n\t\ty.Remove(a[i])\n\n\t\tif got, want := x.SubsetOf(y), false; got != want {\n\t\t\tt.Errorf(\"SubsetOf: got %v, want %v\", got, want)\n\t\t}\n\t}\n}\n\nfunc TestBitString(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tinput []int\n\t\twant  string\n\t}{\n\t\t{nil, \"0\"},\n\t\t{[]int{0}, \"1\"},\n\t\t{[]int{0, 4, 5}, \"110001\"},\n\t\t{[]int{0, 7, 177}, \"1\" + strings.Repeat(\"0\", 169) + \"10000001\"},\n\t\t{[]int{-3, 0, 4, 5}, \"110001.001\"},\n\t\t{[]int{-3}, \"0.001\"},\n\t} {\n\t\tvar set intsets.Sparse\n\t\tfor _, x := range test.input {\n\t\t\tset.Insert(x)\n\t\t}\n\t\tif got := set.BitString(); got != test.want {\n\t\t\tt.Errorf(\"BitString(%s) = %s, want %s\", set.String(), got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestFailFastOnShallowCopy(t *testing.T) {\n\tvar x intsets.Sparse\n\tx.Insert(1)\n\n\ty := x // shallow copy (breaks representation invariants)\n\tdefer func() {\n\t\tgot := fmt.Sprint(recover())\n\t\twant := \"interface conversion: interface {} is nil, not intsets.to_copy_a_sparse_you_must_call_its_Copy_method\"\n\t\tif got != want {\n\t\t\tt.Errorf(\"shallow copy: recover() = %q, want %q\", got, want)\n\t\t}\n\t}()\n\t_ = y.String() // panics\n\tt.Error(\"didn't panic as expected\")\n}\n\n// -- Benchmarks -------------------------------------------------------\n\n// TODO(adonovan):\n// - Add benchmarks of each method.\n// - Gather set distributions from pointer analysis.\n// - Measure memory usage.\n\nfunc benchmarkInsertProbeSparse(b *testing.B, size, spread int) {\n\tprng := rand.New(rand.NewSource(0))\n\t// Generate our insertions and probes beforehand (we don't want to benchmark\n\t// the prng).\n\tinsert := make([]int, size)\n\tprobe := make([]int, size*2)\n\tfor i := range insert {\n\t\tinsert[i] = prng.Int() % spread\n\t}\n\tfor i := range probe {\n\t\tprobe[i] = prng.Int() % spread\n\t}\n\n\tvar x intsets.Sparse\n\tfor b.Loop() {\n\t\tx.Clear()\n\t\tfor _, n := range insert {\n\t\t\tx.Insert(n)\n\t\t}\n\t\thits := 0\n\t\tfor _, n := range probe {\n\t\t\tif x.Has(n) {\n\t\t\t\thits++\n\t\t\t}\n\t\t}\n\t\t// Use the variable so it doesn't get optimized away.\n\t\tif hits > len(probe) {\n\t\t\tb.Fatalf(\"%d hits, only %d probes\", hits, len(probe))\n\t\t}\n\t}\n}\n\nfunc BenchmarkInsertProbeSparse_2_10(b *testing.B) {\n\tbenchmarkInsertProbeSparse(b, 2, 10)\n}\n\nfunc BenchmarkInsertProbeSparse_10_10(b *testing.B) {\n\tbenchmarkInsertProbeSparse(b, 10, 10)\n}\n\nfunc BenchmarkInsertProbeSparse_10_1000(b *testing.B) {\n\tbenchmarkInsertProbeSparse(b, 10, 1000)\n}\n\nfunc BenchmarkInsertProbeSparse_100_100(b *testing.B) {\n\tbenchmarkInsertProbeSparse(b, 100, 100)\n}\n\nfunc BenchmarkInsertProbeSparse_100_10000(b *testing.B) {\n\tbenchmarkInsertProbeSparse(b, 100, 1000)\n}\n\nfunc BenchmarkUnionDifferenceSparse(b *testing.B) {\n\tprng := rand.New(rand.NewSource(0))\n\tfor b.Loop() {\n\t\tvar x, y, z intsets.Sparse\n\t\tfor i := range 1000 {\n\t\t\tn := int(prng.Int()) % 100000\n\t\t\tif i%2 == 0 {\n\t\t\t\tx.Insert(n)\n\t\t\t} else {\n\t\t\t\ty.Insert(n)\n\t\t\t}\n\t\t}\n\t\tz.Union(&x, &y)\n\t\tz.Difference(&x, &y)\n\t}\n}\n\nfunc BenchmarkUnionDifferenceHashTable(b *testing.B) {\n\tprng := rand.New(rand.NewSource(0))\n\tfor b.Loop() {\n\t\tx, y, z := make(map[int]bool), make(map[int]bool), make(map[int]bool)\n\t\tfor i := range 1000 {\n\t\t\tn := int(prng.Int()) % 100000\n\t\t\tif i%2 == 0 {\n\t\t\t\tx[n] = true\n\t\t\t} else {\n\t\t\t\ty[n] = true\n\t\t\t}\n\t\t}\n\t\t// union\n\t\tfor n := range x {\n\t\t\tz[n] = true\n\t\t}\n\t\tfor n := range y {\n\t\t\tz[n] = true\n\t\t}\n\t\t// difference\n\t\tz = make(map[int]bool)\n\t\tfor n := range y {\n\t\t\tif !x[n] {\n\t\t\t\tz[n] = true\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc BenchmarkAppendTo(b *testing.B) {\n\tprng := rand.New(rand.NewSource(0))\n\tvar x intsets.Sparse\n\tfor range 1000 {\n\t\tx.Insert(int(prng.Int()) % 10000)\n\t}\n\tvar space [1000]int\n\tfor b.Loop() {\n\t\tx.AppendTo(space[:0])\n\t}\n}\n"
  },
  {
    "path": "copyright/copyright.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package copyright checks that files have the correct copyright notices.\npackage copyright\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// (used only by tests)\nfunc checkCopyright(dir string) ([]string, error) {\n\tvar files []string\n\terr := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif d.IsDir() {\n\t\t\t// Skip directories like \".git\".\n\t\t\tif strings.HasPrefix(d.Name(), \".\") && d.Name() != \".\" && d.Name() != \"..\" {\n\t\t\t\treturn filepath.SkipDir\n\t\t\t}\n\t\t\t// Skip any directory that starts with an underscore, as the go\n\t\t\t// command would.\n\t\t\tif strings.HasPrefix(d.Name(), \"_\") {\n\t\t\t\treturn filepath.SkipDir\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\tneedsCopyright, err := checkFile(dir, path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif needsCopyright {\n\t\t\tfiles = append(files, path)\n\t\t}\n\t\treturn nil\n\t})\n\treturn files, err\n}\n\nvar copyrightRe = regexp.MustCompile(`Copyright \\d{4} The Go Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file.`)\n\nfunc checkFile(toolsDir, filename string) (bool, error) {\n\t// Only check Go files.\n\tif !strings.HasSuffix(filename, \".go\") {\n\t\treturn false, nil\n\t}\n\t// Don't check testdata files.\n\tnormalized := strings.TrimPrefix(filepath.ToSlash(filename), filepath.ToSlash(toolsDir))\n\tif strings.Contains(normalized, \"/testdata/\") {\n\t\treturn false, nil\n\t}\n\t// goyacc is the only file with a different copyright header.\n\tif strings.HasSuffix(normalized, \"cmd/goyacc/yacc.go\") {\n\t\treturn false, nil\n\t}\n\tcontent, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tfset := token.NewFileSet()\n\tparsed, err := parser.ParseFile(fset, filename, content, parser.ParseComments)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\t// Don't require headers on generated files.\n\tif ast.IsGenerated(parsed) {\n\t\treturn false, nil\n\t}\n\tshouldAddCopyright := true\n\tfor _, c := range parsed.Comments {\n\t\t// The copyright should appear before the package declaration.\n\t\tif c.Pos() > parsed.Package {\n\t\t\tbreak\n\t\t}\n\t\tif copyrightRe.MatchString(c.Text()) {\n\t\t\tshouldAddCopyright = false\n\t\t\tbreak\n\t\t}\n\t}\n\treturn shouldAddCopyright, nil\n}\n"
  },
  {
    "path": "copyright/copyright_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage copyright\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestToolsCopyright(t *testing.T) {\n\tfiles, err := checkCopyright(\"..\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(files) > 0 {\n\t\tt.Errorf(\"The following files are missing copyright notices:\\n%s\", strings.Join(files, \"\\n\"))\n\t}\n}\n"
  },
  {
    "path": "cover/profile.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cover provides support for parsing coverage profiles\n// generated by \"go test -coverprofile=cover.out\".\npackage cover // import \"golang.org/x/tools/cover\"\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Profile represents the profiling data for a specific file.\ntype Profile struct {\n\tFileName string\n\tMode     string\n\tBlocks   []ProfileBlock\n}\n\n// ProfileBlock represents a single block of profiling data.\ntype ProfileBlock struct {\n\tStartLine, StartCol int\n\tEndLine, EndCol     int\n\tNumStmt, Count      int\n}\n\ntype byFileName []*Profile\n\nfunc (p byFileName) Len() int           { return len(p) }\nfunc (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }\nfunc (p byFileName) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }\n\n// ParseProfiles parses profile data in the specified file and returns a\n// Profile for each source file described therein.\nfunc ParseProfiles(fileName string) ([]*Profile, error) {\n\tpf, err := os.Open(fileName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer pf.Close()\n\treturn ParseProfilesFromReader(pf)\n}\n\n// ParseProfilesFromReader parses profile data from the Reader and\n// returns a Profile for each source file described therein.\nfunc ParseProfilesFromReader(rd io.Reader) ([]*Profile, error) {\n\t// First line is \"mode: foo\", where foo is \"set\", \"count\", or \"atomic\".\n\t// Rest of file is in the format\n\t//\tencoding/base64/base64.go:34.44,37.40 3 1\n\t// where the fields are: name.go:line.column,line.column numberOfStatements count\n\tfiles := make(map[string]*Profile)\n\ts := bufio.NewScanner(rd)\n\tmode := \"\"\n\tfor s.Scan() {\n\t\tline := s.Text()\n\t\tif mode == \"\" {\n\t\t\tconst p = \"mode: \"\n\t\t\tif !strings.HasPrefix(line, p) || line == p {\n\t\t\t\treturn nil, fmt.Errorf(\"bad mode line: %v\", line)\n\t\t\t}\n\t\t\tmode = line[len(p):]\n\t\t\tcontinue\n\t\t}\n\t\tfn, b, err := parseLine(line)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"line %q doesn't match expected format: %v\", line, err)\n\t\t}\n\t\tp := files[fn]\n\t\tif p == nil {\n\t\t\tp = &Profile{\n\t\t\t\tFileName: fn,\n\t\t\t\tMode:     mode,\n\t\t\t}\n\t\t\tfiles[fn] = p\n\t\t}\n\t\tp.Blocks = append(p.Blocks, b)\n\t}\n\tif err := s.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, p := range files {\n\t\tsort.Sort(blocksByStart(p.Blocks))\n\t\t// Merge samples from the same location.\n\t\tj := 1\n\t\tfor i := 1; i < len(p.Blocks); i++ {\n\t\t\tb := p.Blocks[i]\n\t\t\tlast := p.Blocks[j-1]\n\t\t\tif b.StartLine == last.StartLine &&\n\t\t\t\tb.StartCol == last.StartCol &&\n\t\t\t\tb.EndLine == last.EndLine &&\n\t\t\t\tb.EndCol == last.EndCol {\n\t\t\t\tif b.NumStmt != last.NumStmt {\n\t\t\t\t\treturn nil, fmt.Errorf(\"inconsistent NumStmt: changed from %d to %d\", last.NumStmt, b.NumStmt)\n\t\t\t\t}\n\t\t\t\tif mode == \"set\" {\n\t\t\t\t\tp.Blocks[j-1].Count |= b.Count\n\t\t\t\t} else {\n\t\t\t\t\tp.Blocks[j-1].Count += b.Count\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tp.Blocks[j] = b\n\t\t\tj++\n\t\t}\n\t\tp.Blocks = p.Blocks[:j]\n\t}\n\t// Generate a sorted slice.\n\tprofiles := make([]*Profile, 0, len(files))\n\tfor _, profile := range files {\n\t\tprofiles = append(profiles, profile)\n\t}\n\tsort.Sort(byFileName(profiles))\n\treturn profiles, nil\n}\n\n// parseLine parses a line from a coverage file.\n// It is equivalent to the regex\n// ^(.+):([0-9]+)\\.([0-9]+),([0-9]+)\\.([0-9]+) ([0-9]+) ([0-9]+)$\n//\n// However, it is much faster: https://golang.org/cl/179377\nfunc parseLine(l string) (fileName string, block ProfileBlock, err error) {\n\tend := len(l)\n\n\tb := ProfileBlock{}\n\tb.Count, end, err = seekBack(l, ' ', end, \"Count\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tb.NumStmt, end, err = seekBack(l, ' ', end, \"NumStmt\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tb.EndCol, end, err = seekBack(l, '.', end, \"EndCol\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tb.EndLine, end, err = seekBack(l, ',', end, \"EndLine\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tb.StartCol, end, err = seekBack(l, '.', end, \"StartCol\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tb.StartLine, end, err = seekBack(l, ':', end, \"StartLine\")\n\tif err != nil {\n\t\treturn \"\", b, err\n\t}\n\tfn := l[0:end]\n\tif fn == \"\" {\n\t\treturn \"\", b, errors.New(\"a FileName cannot be blank\")\n\t}\n\treturn fn, b, nil\n}\n\n// seekBack searches backwards from end to find sep in l, then returns the\n// value between sep and end as an integer.\n// If seekBack fails, the returned error will reference what.\nfunc seekBack(l string, sep byte, end int, what string) (value int, nextSep int, err error) {\n\t// Since we're seeking backwards and we know only ASCII is legal for these values,\n\t// we can ignore the possibility of non-ASCII characters.\n\tfor start := end - 1; start >= 0; start-- {\n\t\tif l[start] == sep {\n\t\t\ti, err := strconv.Atoi(l[start+1 : end])\n\t\t\tif err != nil {\n\t\t\t\treturn 0, 0, fmt.Errorf(\"couldn't parse %q: %v\", what, err)\n\t\t\t}\n\t\t\tif i < 0 {\n\t\t\t\treturn 0, 0, fmt.Errorf(\"negative values are not allowed for %s, found %d\", what, i)\n\t\t\t}\n\t\t\treturn i, start, nil\n\t\t}\n\t}\n\treturn 0, 0, fmt.Errorf(\"couldn't find a %s before %s\", string(sep), what)\n}\n\ntype blocksByStart []ProfileBlock\n\nfunc (b blocksByStart) Len() int      { return len(b) }\nfunc (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] }\nfunc (b blocksByStart) Less(i, j int) bool {\n\tbi, bj := b[i], b[j]\n\treturn bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol\n}\n\n// Boundary represents the position in a source file of the beginning or end of a\n// block as reported by the coverage profile. In HTML mode, it will correspond to\n// the opening or closing of a <span> tag and will be used to colorize the source\ntype Boundary struct {\n\tOffset int     // Location as a byte offset in the source file.\n\tStart  bool    // Is this the start of a block?\n\tCount  int     // Event count from the cover profile.\n\tNorm   float64 // Count normalized to [0..1].\n\tIndex  int     // Order in input file.\n}\n\n// Boundaries returns a Profile as a set of Boundary objects within the provided src.\nfunc (p *Profile) Boundaries(src []byte) (boundaries []Boundary) {\n\t// Find maximum count.\n\tmax := 0\n\tfor _, b := range p.Blocks {\n\t\tif b.Count > max {\n\t\t\tmax = b.Count\n\t\t}\n\t}\n\t// Divisor for normalization.\n\tdivisor := math.Log(float64(max))\n\n\t// boundary returns a Boundary, populating the Norm field with a normalized Count.\n\tindex := 0\n\tboundary := func(offset int, start bool, count int) Boundary {\n\t\tb := Boundary{Offset: offset, Start: start, Count: count, Index: index}\n\t\tindex++\n\t\tif !start || count == 0 {\n\t\t\treturn b\n\t\t}\n\t\tif max <= 1 {\n\t\t\tb.Norm = 0.8 // Profile is in\"set\" mode; we want a heat map. Use cov8 in the CSS.\n\t\t} else if count > 0 {\n\t\t\tb.Norm = math.Log(float64(count)) / divisor\n\t\t}\n\t\treturn b\n\t}\n\n\tline, col := 1, 2 // TODO: Why is this 2?\n\tfor si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); {\n\t\tb := p.Blocks[bi]\n\t\tif b.StartLine == line && b.StartCol == col {\n\t\t\tboundaries = append(boundaries, boundary(si, true, b.Count))\n\t\t}\n\t\tif b.EndLine == line && b.EndCol == col || line > b.EndLine {\n\t\t\tboundaries = append(boundaries, boundary(si, false, 0))\n\t\t\tbi++\n\t\t\tcontinue // Don't advance through src; maybe the next block starts here.\n\t\t}\n\t\tif src[si] == '\\n' {\n\t\t\tline++\n\t\t\tcol = 0\n\t\t}\n\t\tcol++\n\t\tsi++\n\t}\n\tsort.Sort(boundariesByPos(boundaries))\n\treturn\n}\n\ntype boundariesByPos []Boundary\n\nfunc (b boundariesByPos) Len() int      { return len(b) }\nfunc (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] }\nfunc (b boundariesByPos) Less(i, j int) bool {\n\tif b[i].Offset == b[j].Offset {\n\t\t// Boundaries at the same offset should be ordered according to\n\t\t// their original position.\n\t\treturn b[i].Index < b[j].Index\n\t}\n\treturn b[i].Offset < b[j].Offset\n}\n"
  },
  {
    "path": "cover/profile_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cover\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestParseProfiles(t *testing.T) {\n\ttests := []struct {\n\t\tname      string\n\t\tinput     string\n\t\toutput    []*Profile\n\t\texpectErr bool\n\t}{\n\t\t{\n\t\t\tname:   \"parsing an empty file produces empty output\",\n\t\t\tinput:  `mode: set`,\n\t\t\toutput: []*Profile{},\n\t\t},\n\t\t{\n\t\t\tname: \"simple valid file produces expected output\",\n\t\t\tinput: `mode: set\nsome/fancy/path:42.69,44.16 2 1`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"file with syntax characters in path produces expected output\",\n\t\t\tinput: `mode: set\nsome fancy:path/some,file.go:42.69,44.16 2 1`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some fancy:path/some,file.go\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"file with multiple blocks in one file produces expected output\",\n\t\t\tinput: `mode: set\nsome/fancy/path:42.69,44.16 2 1\nsome/fancy/path:44.16,46.3 1 0`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 44, StartCol: 16,\n\t\t\t\t\t\t\tEndLine: 46, EndCol: 3,\n\t\t\t\t\t\t\tNumStmt: 1, Count: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"file with multiple files produces expected output\",\n\t\t\tinput: `mode: set\nanother/fancy/path:44.16,46.3 1 0\nsome/fancy/path:42.69,44.16 2 1`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"another/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 44, StartCol: 16,\n\t\t\t\t\t\t\tEndLine: 46, EndCol: 3,\n\t\t\t\t\t\t\tNumStmt: 1, Count: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"intertwined files are merged correctly\",\n\t\t\tinput: `mode: set\nsome/fancy/path:42.69,44.16 2 1\nanother/fancy/path:47.2,47.13 1 1\nsome/fancy/path:44.16,46.3 1 0`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"another/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 47, StartCol: 2,\n\t\t\t\t\t\t\tEndLine: 47, EndCol: 13,\n\t\t\t\t\t\t\tNumStmt: 1, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some/fancy/path\",\n\t\t\t\t\tMode:     \"set\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 44, StartCol: 16,\n\t\t\t\t\t\t\tEndLine: 46, EndCol: 3,\n\t\t\t\t\t\t\tNumStmt: 1, Count: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"duplicate blocks are merged correctly\",\n\t\t\tinput: `mode: count\nsome/fancy/path:42.69,44.16 2 4\nsome/fancy/path:42.69,44.16 2 3`,\n\t\t\toutput: []*Profile{\n\t\t\t\t{\n\t\t\t\t\tFileName: \"some/fancy/path\",\n\t\t\t\t\tMode:     \"count\",\n\t\t\t\t\tBlocks: []ProfileBlock{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStartLine: 42, StartCol: 69,\n\t\t\t\t\t\t\tEndLine: 44, EndCol: 16,\n\t\t\t\t\t\t\tNumStmt: 2, Count: 7,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:      \"an invalid mode line is an error\",\n\t\t\tinput:     `mode:count`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"a missing field is an error\",\n\t\t\tinput: `mode: count\nsome/fancy/path:42.69,44.16 2`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"a missing path field is an error\",\n\t\t\tinput: `mode: count\n42.69,44.16 2 3`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"a non-numeric count is an error\",\n\t\t\tinput: `mode: count\n42.69,44.16 2 nope`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"an empty path is an error\",\n\t\t\tinput: `mode: count\n:42.69,44.16 2 3`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"a negative count is an error\",\n\t\t\tinput: `mode: count\nsome/fancy/path:42.69,44.16 2 -1`,\n\t\t\texpectErr: true,\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tfname := filepath.Join(t.TempDir(), \"test.cov\")\n\t\t\tif err := os.WriteFile(fname, []byte(tc.input), 0644); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tresult, err := ParseProfiles(fname)\n\t\t\tif err != nil {\n\t\t\t\tif !tc.expectErr {\n\t\t\t\t\tt.Errorf(\"Unexpected error: %v\", err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif tc.expectErr {\n\t\t\t\tt.Errorf(\"Expected an error, but got value %q\", stringifyProfileArray(result))\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(result, tc.output) {\n\t\t\t\tt.Errorf(\"Mismatched results.\\nExpected: %s\\nActual:   %s\", stringifyProfileArray(tc.output), stringifyProfileArray(result))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc stringifyProfileArray(profiles []*Profile) string {\n\tderef := make([]Profile, 0, len(profiles))\n\tfor _, p := range profiles {\n\t\tderef = append(deref, *p)\n\t}\n\treturn fmt.Sprintf(\"%#v\", deref)\n}\n\nfunc BenchmarkParseLine(b *testing.B) {\n\tconst line = \"k8s.io/kubernetes/cmd/kube-controller-manager/app/options/ttlafterfinishedcontroller.go:31.73,32.14 1 1\"\n\tb.SetBytes(int64(len(line)))\n\tfor b.Loop() {\n\t\tparseLine(line)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/analysis.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysis\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"time\"\n)\n\n// An Analyzer describes an analysis function and its options.\ntype Analyzer struct {\n\t// The Name of the analyzer must be a valid Go identifier\n\t// as it may appear in command-line flags, URLs, and so on.\n\tName string\n\n\t// Doc is the documentation for the analyzer.\n\t// The part before the first \"\\n\\n\" is the title\n\t// (no capital or period, max ~60 letters).\n\tDoc string\n\n\t// URL holds an optional link to a web page with additional\n\t// documentation for this analyzer.\n\tURL string\n\n\t// Flags defines any flags accepted by the analyzer.\n\t// The manner in which these flags are exposed to the user\n\t// depends on the driver which runs the analyzer.\n\tFlags flag.FlagSet\n\n\t// Run applies the analyzer to a package.\n\t// It returns an error if the analyzer failed.\n\t//\n\t// On success, the Run function may return a result\n\t// computed by the Analyzer; its type must match ResultType.\n\t// The driver makes this result available as an input to\n\t// another Analyzer that depends directly on this one (see\n\t// Requires) when it analyzes the same package.\n\t//\n\t// To pass analysis results between packages (and thus\n\t// potentially between address spaces), use Facts, which are\n\t// serializable.\n\tRun func(*Pass) (any, error)\n\n\t// RunDespiteErrors allows the driver to invoke\n\t// the Run method of this analyzer even on a\n\t// package that contains parse or type errors.\n\t// The [Pass.TypeErrors] field may consequently be non-empty.\n\tRunDespiteErrors bool\n\n\t// Requires is a set of analyzers that must run successfully\n\t// before this one on a given package. This analyzer may inspect\n\t// the outputs produced by each analyzer in Requires.\n\t// The graph over analyzers implied by Requires edges must be acyclic.\n\t//\n\t// Requires establishes a \"horizontal\" dependency between\n\t// analysis passes (different analyzers, same package).\n\tRequires []*Analyzer\n\n\t// ResultType is the type of the optional result of the Run function.\n\tResultType reflect.Type\n\n\t// FactTypes indicates that this analyzer imports and exports\n\t// Facts of the specified concrete types.\n\t// An analyzer that uses facts may assume that its import\n\t// dependencies have been similarly analyzed before it runs.\n\t// Facts must be pointers.\n\t//\n\t// FactTypes establishes a \"vertical\" dependency between\n\t// analysis passes (same analyzer, different packages).\n\tFactTypes []Fact\n}\n\nfunc (a *Analyzer) String() string { return a.Name }\n\n// A Pass provides information to the Run function that\n// applies a specific analyzer to a single Go package.\n//\n// It forms the interface between the analysis logic and the driver\n// program, and has both input and an output components.\n//\n// As in a compiler, one pass may depend on the result computed by another.\n//\n// The Run function should not call any of the Pass functions concurrently.\ntype Pass struct {\n\tAnalyzer *Analyzer // the identity of the current analyzer\n\n\t// syntax and type information\n\tFset         *token.FileSet // file position information; Run may add new files\n\tFiles        []*ast.File    // the abstract syntax tree of each file\n\tOtherFiles   []string       // names of non-Go files of this package\n\tIgnoredFiles []string       // names of ignored source files in this package\n\tPkg          *types.Package // type information about the package\n\tTypesInfo    *types.Info    // type information about the syntax trees\n\tTypesSizes   types.Sizes    // function for computing sizes of types\n\tTypeErrors   []types.Error  // type errors (only if Analyzer.RunDespiteErrors)\n\n\tModule *Module // the package's enclosing module (possibly nil in some drivers)\n\n\t// Report reports a Diagnostic, a finding about a specific location\n\t// in the analyzed source code such as a potential mistake.\n\t// It may be called by the Run function.\n\tReport func(Diagnostic)\n\n\t// ResultOf provides the inputs to this analysis pass, which are\n\t// the corresponding results of its prerequisite analyzers.\n\t// The map keys are the elements of Analysis.Required,\n\t// and the type of each corresponding value is the required\n\t// analysis's ResultType.\n\tResultOf map[*Analyzer]any\n\n\t// ReadFile returns the contents of the named file.\n\t//\n\t// The only valid file names are the elements of OtherFiles\n\t// and IgnoredFiles, and names returned by\n\t// Fset.File(f.FileStart).Name() for each f in Files.\n\t//\n\t// Analyzers must use this function (if provided) instead of\n\t// accessing the file system directly. This allows a driver to\n\t// provide a virtualized file tree (including, for example,\n\t// unsaved editor buffers) and to track dependencies precisely\n\t// to avoid unnecessary recomputation.\n\tReadFile func(filename string) ([]byte, error)\n\n\t// -- facts --\n\n\t// ImportObjectFact retrieves a fact associated with obj.\n\t// Given a value ptr of type *T, where *T satisfies Fact,\n\t// ImportObjectFact copies the value to *ptr.\n\t//\n\t// ImportObjectFact panics if called after the pass is complete.\n\t// ImportObjectFact is not concurrency-safe.\n\tImportObjectFact func(obj types.Object, fact Fact) bool\n\n\t// ImportPackageFact retrieves a fact associated with package pkg,\n\t// which must be this package or one of its dependencies.\n\t// See comments for ImportObjectFact.\n\tImportPackageFact func(pkg *types.Package, fact Fact) bool\n\n\t// ExportObjectFact associates a fact of type *T with the obj,\n\t// replacing any previous fact of that type.\n\t//\n\t// ExportObjectFact panics if it is called after the pass is\n\t// complete, or if obj does not belong to the package being analyzed.\n\t// ExportObjectFact is not concurrency-safe.\n\tExportObjectFact func(obj types.Object, fact Fact)\n\n\t// ExportPackageFact associates a fact with the current package.\n\t// See comments for ExportObjectFact.\n\tExportPackageFact func(fact Fact)\n\n\t// AllPackageFacts returns a new slice containing all package\n\t// facts of the analysis's FactTypes in unspecified order.\n\t// See comments for AllObjectFacts.\n\tAllPackageFacts func() []PackageFact\n\n\t// AllObjectFacts returns a new slice containing all object\n\t// facts of the analysis's FactTypes in unspecified order.\n\t//\n\t// The result includes all facts exported by packages\n\t// whose symbols are referenced by the current package\n\t// (by qualified identifiers or field/method selections).\n\t// And it includes all facts exported from the current\n\t// package by the current analysis pass.\n\tAllObjectFacts func() []ObjectFact\n\n\t/* Further fields may be added in future. */\n}\n\n// PackageFact is a package together with an associated fact.\ntype PackageFact struct {\n\tPackage *types.Package\n\tFact    Fact\n}\n\n// ObjectFact is an object together with an associated fact.\ntype ObjectFact struct {\n\tObject types.Object\n\tFact   Fact\n}\n\n// Reportf is a helper function that reports a Diagnostic using the\n// specified position and formatted error message.\nfunc (pass *Pass) Reportf(pos token.Pos, format string, args ...any) {\n\tmsg := fmt.Sprintf(format, args...)\n\tpass.Report(Diagnostic{Pos: pos, Message: msg})\n}\n\n// The Range interface provides a range. It's equivalent to and satisfied by\n// ast.Node.\ntype Range interface {\n\tPos() token.Pos // position of first character belonging to the node\n\tEnd() token.Pos // position of first character immediately after the node\n}\n\n// ReportRangef is a helper function that reports a Diagnostic using the\n// range provided. ast.Node values can be passed in as the range because\n// they satisfy the Range interface.\nfunc (pass *Pass) ReportRangef(rng Range, format string, args ...any) {\n\tmsg := fmt.Sprintf(format, args...)\n\tpass.Report(Diagnostic{Pos: rng.Pos(), End: rng.End(), Message: msg})\n}\n\nfunc (pass *Pass) String() string {\n\treturn fmt.Sprintf(\"%s@%s\", pass.Analyzer.Name, pass.Pkg.Path())\n}\n\n// A Fact is an intermediate fact produced during analysis.\n//\n// Each fact is associated with a named declaration (a types.Object) or\n// with a package as a whole. A single object or package may have\n// multiple associated facts, but only one of any particular fact type.\n//\n// A Fact represents a predicate such as \"never returns\", but does not\n// represent the subject of the predicate such as \"function F\" or \"package P\".\n//\n// Facts may be produced in one analysis pass and consumed by another\n// analysis pass even if these are in different address spaces.\n// If package P imports Q, all facts about Q produced during\n// analysis of that package will be available during later analysis of P.\n// Facts are analogous to type export data in a build system:\n// just as export data enables separate compilation of several passes,\n// facts enable \"separate analysis\".\n//\n// Each pass (a, p) starts with the set of facts produced by the\n// same analyzer a applied to the packages directly imported by p.\n// The analysis may add facts to the set, and they may be exported in turn.\n// An analysis's Run function may retrieve facts by calling\n// Pass.Import{Object,Package}Fact and update them using\n// Pass.Export{Object,Package}Fact.\n//\n// A fact is logically private to its Analysis. To pass values\n// between different analyzers, use the results mechanism;\n// see Analyzer.Requires, Analyzer.ResultType, and Pass.ResultOf.\n//\n// A Fact type must be a pointer.\n// Facts are encoded and decoded using encoding/gob.\n// A Fact may implement the GobEncoder/GobDecoder interfaces\n// to customize its encoding. Fact encoding should not fail.\n//\n// A Fact should not be modified once exported.\ntype Fact interface {\n\tAFact() // dummy method to avoid type errors\n}\n\n// A Module describes the module to which a package belongs.\ntype Module struct {\n\tPath      string       // module path\n\tVersion   string       // module version (\"\" if unknown, such as for workspace modules)\n\tReplace   *Module      // replaced by this module\n\tTime      *time.Time   // time version was created\n\tMain      bool         // is this the main module?\n\tIndirect  bool         // is this module only an indirect dependency of main module?\n\tDir       string       // directory holding files for this module, if any\n\tGoMod     string       // path to go.mod file used when loading this module, if any\n\tGoVersion string       // go version used in module (e.g. \"go1.22.0\")\n\tError     *ModuleError // error loading module\n}\n\n// ModuleError holds errors loading a module.\ntype ModuleError struct {\n\tErr string // the error itself\n}\n"
  },
  {
    "path": "go/analysis/analysistest/analysistest.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package analysistest provides utilities for testing analyzers.\npackage analysistest\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"text/scanner\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/checker\"\n\t\"golang.org/x/tools/go/analysis/internal\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// WriteFiles is a helper function that creates a temporary directory\n// and populates it with a GOPATH-style project using filemap (which\n// maps file names to contents). On success it returns the name of the\n// directory and a cleanup function to delete it.\n//\n// TODO(adonovan): provide a newer version that accepts a testing.T,\n// calls T.TempDir, and calls T.Fatal on any error, avoiding the need\n// to return cleanup or err:\n//\n//\tfunc WriteFilesToTmp(t *testing.T filemap map[string]string) string\nfunc WriteFiles(filemap map[string]string) (dir string, cleanup func(), err error) {\n\tgopath, err := os.MkdirTemp(\"\", \"analysistest\")\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tcleanup = func() { os.RemoveAll(gopath) }\n\n\tfor name, content := range filemap {\n\t\tfilename := filepath.Join(gopath, \"src\", name)\n\t\tos.MkdirAll(filepath.Dir(filename), 0777) // ignore error\n\t\tif err := os.WriteFile(filename, []byte(content), 0666); err != nil {\n\t\t\tcleanup()\n\t\t\treturn \"\", nil, err\n\t\t}\n\t}\n\treturn gopath, cleanup, nil\n}\n\n// TestData returns the effective filename of\n// the program's \"testdata\" directory.\n// This function may be overridden by projects using\n// an alternative build system (such as Blaze) that\n// does not run a test in its package directory.\nvar TestData = func() string {\n\ttestdata, err := filepath.Abs(\"testdata\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn testdata\n}\n\n// Testing is an abstraction of a *testing.T.\ntype Testing interface {\n\tErrorf(format string, args ...any)\n}\n\n// RunWithSuggestedFixes behaves like Run, but additionally applies\n// suggested fixes and verifies their output.\n//\n// It uses golden files, placed alongside each source file, to express\n// the desired output: the expected transformation of file example.go\n// is specified in file example.go.golden.\n//\n// Golden files may be of two forms: a plain Go source file, or a\n// txtar archive.\n//\n// A plain Go source file indicates the expected result of applying\n// all suggested fixes to the original file.\n//\n// A txtar archive specifies, in each section, the expected result of\n// applying all suggested fixes of a given message to the original\n// file; the name of the archive section is the fix's message. In this\n// way, the various alternative fixes offered by a single diagnostic\n// can be tested independently. Here's an example:\n//\n//\t-- turn into single negation --\n//\tpackage pkg\n//\n//\tfunc fn(b1, b2 bool) {\n//\t\tif !b1 { // want `negating a boolean twice`\n//\t\t\tprintln()\n//\t\t}\n//\t}\n//\n//\t-- remove double negation --\n//\tpackage pkg\n//\n//\tfunc fn(b1, b2 bool) {\n//\t\tif b1 { // want `negating a boolean twice`\n//\t\t\tprintln()\n//\t\t}\n//\t}\n//\n// # Conflicts\n//\n// Regardless of the form of the golden file, it is possible for\n// multiple fixes to conflict, either because they overlap, or are\n// close enough together that the particular diff algorithm cannot\n// separate them.\n//\n// RunWithSuggestedFixes uses a simple three-way merge to accumulate\n// fixes, similar to a git merge. The merge algorithm may be able to\n// coalesce identical edits, for example duplicate imports of the same\n// package. (Bear in mind that this is an editorial decision. In\n// general, coalescing identical edits may not be correct: consider\n// two statements that increment the same counter.)\n//\n// If there are conflicts, the test fails. In any case, the\n// non-conflicting edits will be compared against the expected output.\n// In this situation, we recommend that you increase the textual\n// separation between conflicting parts or, if that fails, split\n// your tests into smaller parts.\n//\n// If a diagnostic offers multiple fixes for the same problem, they\n// are almost certain to conflict, so in this case you should define\n// the expected output using a multi-section txtar file as described\n// above.\nfunc RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {\n\tresults := Run(t, dir, a, patterns...)\n\n\t// If the immediate caller of RunWithSuggestedFixes is in\n\t// x/tools, we apply stricter checks as required by gopls.\n\tinTools := false\n\t{\n\t\tvar pcs [1]uintptr\n\t\tn := runtime.Callers(1, pcs[:])\n\t\tframes := runtime.CallersFrames(pcs[:n])\n\t\tfr, _ := frames.Next()\n\t\tif fr.Func != nil && strings.HasPrefix(fr.Func.Name(), \"golang.org/x/tools/\") {\n\t\t\tinTools = true\n\t\t}\n\t}\n\n\tgenerated := make(map[*token.File]bool)\n\n\t// Process each result (package) separately, matching up the suggested\n\t// fixes into a diff, which we will compare to the .golden file.  We have\n\t// to do this per-result in case a file appears in two packages, such as in\n\t// packages with tests, where mypkg/a.go will appear in both mypkg and\n\t// mypkg.test.  In that case, the analyzer may suggest the same set of\n\t// changes to a.go for each package.  If we merge all the results, those\n\t// changes get doubly applied, which will cause conflicts or mismatches.\n\t// Validating the results separately means as long as the two analyses\n\t// don't produce conflicting suggestions for a single file, everything\n\t// should match up.\n\tfor _, result := range results {\n\t\tact := result.Action\n\n\t\t// Compute set of generated files.\n\t\tfor _, file := range internal.ActionPass(act).Files {\n\t\t\t// Memoize, since there may be many actions\n\t\t\t// for the same package (list of files).\n\t\t\ttokFile := act.Package.Fset.File(file.Pos())\n\t\t\tif _, seen := generated[tokFile]; !seen {\n\t\t\t\tgenerated[tokFile] = ast.IsGenerated(file)\n\t\t\t}\n\t\t}\n\n\t\t// For each fix, split its edits by file and convert to diff form.\n\t\tvar (\n\t\t\t// fixEdits: message -> fixes -> filename -> edits\n\t\t\t//\n\t\t\t// TODO(adonovan): this mapping assumes fix.Messages\n\t\t\t// are unique across analyzers, whereas they are only\n\t\t\t// unique within a given Diagnostic.\n\t\t\tfixEdits     = make(map[string][]map[string][]diff.Edit)\n\t\t\tallFilenames = make(map[string]bool)\n\t\t)\n\t\tfor _, diag := range act.Diagnostics {\n\t\t\t// Fixes are validated upon creation in Pass.Report.\n\t\tfixloop:\n\t\t\tfor _, fix := range diag.SuggestedFixes {\n\t\t\t\t// Assert that lazy fixes have a Category (#65578, #65087).\n\t\t\t\tif inTools && len(fix.TextEdits) == 0 && diag.Category == \"\" {\n\t\t\t\t\tt.Errorf(\"missing Diagnostic.Category for SuggestedFix without TextEdits (gopls requires the category for the name of the fix command\")\n\t\t\t\t}\n\n\t\t\t\t// Skip any fix that edits a generated file.\n\t\t\t\tfor _, edit := range fix.TextEdits {\n\t\t\t\t\tfile := act.Package.Fset.File(edit.Pos)\n\t\t\t\t\tif generated[file] {\n\t\t\t\t\t\tcontinue fixloop\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Convert edits to diff form.\n\t\t\t\t// Group fixes by message and file.\n\t\t\t\tedits := make(map[string][]diff.Edit)\n\t\t\t\tfor _, edit := range fix.TextEdits {\n\t\t\t\t\tfile := act.Package.Fset.File(edit.Pos)\n\t\t\t\t\tallFilenames[file.Name()] = true\n\t\t\t\t\tedits[file.Name()] = append(edits[file.Name()], diff.Edit{\n\t\t\t\t\t\tStart: file.Offset(edit.Pos),\n\t\t\t\t\t\tEnd:   file.Offset(edit.End),\n\t\t\t\t\t\tNew:   string(edit.NewText),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tfixEdits[fix.Message] = append(fixEdits[fix.Message], edits)\n\t\t\t}\n\t\t}\n\n\t\tmerge := func(file, message string, x, y []diff.Edit) []diff.Edit {\n\t\t\tz, ok := diff.Merge(x, y)\n\t\t\tif !ok {\n\t\t\t\tt.Errorf(\"in file %s, conflict applying fix %q\", file, message)\n\t\t\t\treturn x // discard y\n\t\t\t}\n\t\t\treturn z\n\t\t}\n\n\t\t// Because the checking is driven by original\n\t\t// filenames, there is no way to express that a fix\n\t\t// (e.g. extract declaration) creates a new file.\n\t\tfor _, filename := range slices.Sorted(maps.Keys(allFilenames)) {\n\t\t\t// Read the original file.\n\t\t\tcontent, err := os.ReadFile(filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"error reading %s: %v\", filename, err)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check checks that the accumulated edits applied\n\t\t\t// to the original content yield the wanted content.\n\t\t\tcheck := func(prefix string, accumulated []diff.Edit, want []byte) {\n\t\t\t\tif err := applyDiffsAndCompare(result.Pass.Pkg, filename, content, want, accumulated); err != nil {\n\t\t\t\t\tt.Errorf(\"%s: %s\", prefix, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Read the golden file. It may have one of two forms:\n\t\t\t// (1) A txtar archive with one section per fix title,\n\t\t\t//     including all fixes of just that title.\n\t\t\t// (2) The expected output for file.Name after all (?) fixes are applied.\n\t\t\t//     This form requires that no diagnostic has multiple fixes.\n\t\t\tar, err := txtar.ParseFile(filename + \".golden\")\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"error reading %s.golden: %v\", filename, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(ar.Files) > 0 {\n\t\t\t\t// Form #1: one archive section per kind of suggested fix.\n\t\t\t\tif len(ar.Comment) > 0 {\n\t\t\t\t\t// Disallow the combination of comment and archive sections.\n\t\t\t\t\tt.Errorf(\"%s.golden has leading comment; we don't know what to do with it\", filename)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Each archive section is named for a fix.Message.\n\t\t\t\t// Accumulate the parts of the fix that apply to the current file,\n\t\t\t\t// using a simple three-way merge, discarding conflicts,\n\t\t\t\t// then apply the merged edits and compare to the archive section.\n\t\t\t\tfor _, section := range ar.Files {\n\t\t\t\t\tmessage, want := section.Name, section.Data\n\t\t\t\t\tvar accumulated []diff.Edit\n\t\t\t\t\tfor _, fix := range fixEdits[message] {\n\t\t\t\t\t\taccumulated = merge(filename, message, accumulated, fix[filename])\n\t\t\t\t\t}\n\t\t\t\t\tcheck(fmt.Sprintf(\"all fixes of message %q\", message), accumulated, want)\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// Form #2: all suggested fixes are represented by a single file.\n\t\t\t\twant := ar.Comment\n\t\t\t\tvar accumulated []diff.Edit\n\t\t\t\tfor _, message := range slices.Sorted(maps.Keys(fixEdits)) {\n\t\t\t\t\tfor _, fix := range fixEdits[message] {\n\t\t\t\t\t\taccumulated = merge(filename, message, accumulated, fix[filename])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcheck(\"all fixes\", accumulated, want)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results\n}\n\n// applyDiffsAndCompare applies edits to original and compares the results against\n// want after formatting both. fileName is use solely for error reporting.\nfunc applyDiffsAndCompare(pkg *types.Package, filename string, original, want []byte, edits []diff.Edit) error {\n\t// Relativize filename, for tidier errors.\n\tif cwd, err := os.Getwd(); err == nil {\n\t\tif rel, err := filepath.Rel(cwd, filename); err == nil {\n\t\t\tfilename = rel\n\t\t}\n\t}\n\n\tif len(edits) == 0 {\n\t\treturn fmt.Errorf(\"%s: no edits\", filename)\n\t}\n\tfixedBytes, err := diff.ApplyBytes(original, edits)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: error applying fixes: %v (see possible explanations at RunWithSuggestedFixes)\", filename, err)\n\t}\n\tfixed, err := driverutil.FormatSourceRemoveImports(pkg, fixedBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: error formatting resulting source: %v\\n%s\", filename, err, fixedBytes)\n\t}\n\n\twant, err = format.Source(want)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s.golden: error formatting golden file: %v\\n%s\", filename, err, fixed)\n\t}\n\n\t// Keep error reporting logic below consistent with\n\t// TestScript in ../internal/checker/fix_test.go!\n\n\tunified := func(xlabel, ylabel string, x, y []byte) string {\n\t\tx = append(slices.Clip(bytes.TrimSpace(x)), '\\n')\n\t\ty = append(slices.Clip(bytes.TrimSpace(y)), '\\n')\n\t\treturn diff.Unified(xlabel, ylabel, string(x), string(y))\n\t}\n\n\tif diff := unified(filename+\" (fixed)\", filename+\" (want)\", fixed, want); diff != \"\" {\n\t\treturn fmt.Errorf(\"unexpected %s content:\\n\"+\n\t\t\t\"-- original --\\n%s\\n\"+\n\t\t\t\"-- fixed --\\n%s\\n\"+\n\t\t\t\"-- want --\\n%s\\n\"+\n\t\t\t\"-- diff original fixed --\\n%s\\n\"+\n\t\t\t\"-- diff fixed want --\\n%s\",\n\t\t\tfilename,\n\t\t\toriginal,\n\t\t\tfixed,\n\t\t\twant,\n\t\t\tunified(filename+\" (original)\", filename+\" (fixed)\", original, fixed),\n\t\t\tdiff)\n\t}\n\treturn nil\n}\n\n// Run applies an analysis to the packages denoted by the \"go list\" patterns.\n//\n// It loads the packages from the specified\n// directory using golang.org/x/tools/go/packages, runs the analysis on\n// them, and checks that each analysis emits the expected diagnostics\n// and facts specified by the contents of '// want ...' comments in the\n// package's source files. It treats a comment of the form\n// \"//...// want...\" or \"/*...// want... */\" as if it starts at 'want'.\n//\n// If the directory contains a go.mod file, Run treats it as the root of the\n// Go module in which to work. Otherwise, Run treats it as the root of a\n// GOPATH-style tree, with package contained in the src subdirectory.\n//\n// An expectation of a Diagnostic is specified by a string literal\n// containing a regular expression that must match the diagnostic\n// message. For example:\n//\n//\tfmt.Printf(\"%s\", 1) // want `cannot provide int 1 to %s`\n//\n// An expectation of a Fact associated with an object is specified by\n// 'name:\"pattern\"', where name is the name of the object, which must be\n// declared on the same line as the comment, and pattern is a regular\n// expression that must match the string representation of the fact,\n// fmt.Sprint(fact). For example:\n//\n//\tfunc panicf(format string, args interface{}) { // want panicf:\"printfWrapper\"\n//\n// Package facts are specified by the name \"package\" and appear on\n// line 1 of the first source file of the package.\n//\n// A single 'want' comment may contain a mixture of diagnostic and fact\n// expectations, including multiple facts about the same object:\n//\n//\t// want \"diag\" \"diag2\" x:\"fact1\" x:\"fact2\" y:\"fact3\"\n//\n// Unexpected diagnostics and facts, and unmatched expectations, are\n// reported as errors to the Testing.\n//\n// Run reports an error to the Testing if loading or analysis failed.\n// Run also returns a Result for each package for which analysis was\n// attempted, even if unsuccessful. It is safe for a test to ignore all\n// the results, but a test may use it to perform additional checks.\nfunc Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {\n\tif t, ok := t.(testing.TB); ok {\n\t\ttestenv.NeedsGoPackages(t)\n\t}\n\n\tpkgs, err := loadPackages(dir, patterns...)\n\tif err != nil {\n\t\tt.Errorf(\"loading %s: %v\", patterns, err)\n\t\treturn nil\n\t}\n\n\t// Print parse and type errors to the test log.\n\t// (Do not print them to stderr, which would pollute\n\t// the log in cases where the tests pass.)\n\tif t, ok := t.(testing.TB); ok && !a.RunDespiteErrors {\n\t\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\t\tfor _, err := range pkg.Errors {\n\t\t\t\tt.Log(err)\n\t\t\t}\n\t\t})\n\t}\n\n\tres, err := checker.Analyze([]*analysis.Analyzer{a}, pkgs, nil)\n\tif err != nil {\n\t\tt.Errorf(\"Analyze: %v\", err)\n\t\treturn nil\n\t}\n\n\tvar results []*Result\n\tfor _, act := range res.Roots {\n\t\tif act.Err != nil {\n\t\t\tt.Errorf(\"error analyzing %s: %v\", act, act.Err)\n\t\t} else {\n\t\t\tcheck(t, dir, act)\n\t\t}\n\n\t\t// Compute legacy map of facts relating to this package.\n\t\tfacts := make(map[types.Object][]analysis.Fact)\n\t\tfor _, objFact := range act.AllObjectFacts() {\n\t\t\tif obj := objFact.Object; obj.Pkg() == act.Package.Types {\n\t\t\t\tfacts[obj] = append(facts[obj], objFact.Fact)\n\t\t\t}\n\t\t}\n\t\tfor _, pkgFact := range act.AllPackageFacts() {\n\t\t\tif pkgFact.Package == act.Package.Types {\n\t\t\t\tfacts[nil] = append(facts[nil], pkgFact.Fact)\n\t\t\t}\n\t\t}\n\n\t\t// Construct the legacy result.\n\t\tresults = append(results, &Result{\n\t\t\tPass:        internal.ActionPass(act), // may be nil\n\t\t\tDiagnostics: act.Diagnostics,\n\t\t\tFacts:       facts,\n\t\t\tResult:      act.Result,\n\t\t\tErr:         act.Err,\n\t\t\tAction:      act,\n\t\t})\n\t}\n\treturn results\n}\n\n// A Result holds the result of applying an analyzer to a package.\n//\n// Facts contains only facts associated with the package and its objects.\n//\n// This internal type was inadvertently and regrettably exposed\n// through a public type alias. It is essentially redundant with\n// [checker.Action], but must be retained for compatibility. Clients may\n// access the public fields of the Pass but must not invoke any of\n// its \"verbs\", since the pass is already complete.\ntype Result struct {\n\tAction *checker.Action\n\n\t// legacy fields (do not use)\n\tFacts       map[types.Object][]analysis.Fact // nil key => package fact\n\tPass        *analysis.Pass                   // nil => action not executed\n\tDiagnostics []analysis.Diagnostic            // see Action.Diagnostics\n\tResult      any                              // see Action.Result\n\tErr         error                            // see Action.Err\n}\n\n// loadPackages uses go/packages to load a specified packages (from source, with\n// dependencies) from dir, which is the root of a GOPATH-style project tree.\n// loadPackages returns an error if any package had an error, or the pattern\n// matched no packages.\nfunc loadPackages(dir string, patterns ...string) ([]*packages.Package, error) {\n\tenv := []string{\"GOPATH=\" + dir, \"GO111MODULE=off\", \"GOWORK=off\"} // GOPATH mode\n\n\t// Undocumented module mode. Will be replaced by something better.\n\tif _, err := os.Stat(filepath.Join(dir, \"go.mod\")); err == nil {\n\t\tgowork := filepath.Join(dir, \"go.work\")\n\t\tif _, err := os.Stat(gowork); err != nil {\n\t\t\tgowork = \"off\"\n\t\t}\n\n\t\tenv = []string{\"GO111MODULE=on\", \"GOPROXY=off\", \"GOWORK=\" + gowork} // module mode\n\t}\n\n\t// packages.Load loads the real standard library, not a minimal\n\t// fake version, which would be more efficient, especially if we\n\t// have many small tests that import, say, net/http.\n\t// However there is no easy way to make go/packages to consume\n\t// a list of packages we generate and then do the parsing and\n\t// typechecking, though this feature seems to be a recurring need.\n\n\tmode := packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports |\n\t\tpackages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo |\n\t\tpackages.NeedDeps | packages.NeedModule\n\tcfg := &packages.Config{\n\t\tMode:  mode,\n\t\tDir:   dir,\n\t\tTests: true,\n\t\tEnv:   append(os.Environ(), env...),\n\t}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// If any named package couldn't be loaded at all\n\t// (e.g. the Name field is unset), fail fast.\n\tfor _, pkg := range pkgs {\n\t\tif pkg.Name == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"failed to load %q: Errors=%v\",\n\t\t\t\tpkg.PkgPath, pkg.Errors)\n\t\t}\n\t}\n\n\tif len(pkgs) == 0 {\n\t\treturn nil, fmt.Errorf(\"no packages matched %s\", patterns)\n\t}\n\treturn pkgs, nil\n}\n\n// check inspects an analysis pass on which the analysis has already\n// been run, and verifies that all reported diagnostics and facts match\n// specified by the contents of \"// want ...\" comments in the package's\n// source files, which must have been parsed with comments enabled.\nfunc check(t Testing, gopath string, act *checker.Action) {\n\ttype key struct {\n\t\tfile string\n\t\tline int\n\t}\n\n\twant := make(map[key][]expectation)\n\n\t// processComment parses expectations out of comments.\n\tprocessComment := func(filename string, linenum int, text string) {\n\t\ttext = strings.TrimSpace(text)\n\n\t\t// Any comment starting with \"want\" is treated\n\t\t// as an expectation, even without following whitespace.\n\t\tif rest, ok := strings.CutPrefix(text, \"want\"); ok {\n\t\t\tlineDelta, expects, err := parseExpectations(rest)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"%s:%d: in 'want' comment: %s\", filename, linenum, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif expects != nil {\n\t\t\t\twant[key{filename, linenum + lineDelta}] = expects\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract 'want' comments from parsed Go files.\n\tfor _, f := range act.Package.Syntax {\n\t\tfor _, cgroup := range f.Comments {\n\t\t\tfor _, c := range cgroup.List {\n\n\t\t\t\ttext := strings.TrimPrefix(c.Text, \"//\")\n\t\t\t\tif text == c.Text { // not a //-comment.\n\t\t\t\t\ttext = strings.TrimPrefix(text, \"/*\")\n\t\t\t\t\ttext = strings.TrimSuffix(text, \"*/\")\n\t\t\t\t}\n\n\t\t\t\t// Hack: treat a comment of the form \"//...// want...\"\n\t\t\t\t// or \"/*...// want... */\n\t\t\t\t// as if it starts at 'want'.\n\t\t\t\t// This allows us to add comments on comments,\n\t\t\t\t// as required when testing the buildtag analyzer.\n\t\t\t\tif i := strings.Index(text, \"// want\"); i >= 0 {\n\t\t\t\t\ttext = text[i+len(\"// \"):]\n\t\t\t\t}\n\n\t\t\t\t// It's tempting to compute the filename\n\t\t\t\t// once outside the loop, but it's\n\t\t\t\t// incorrect because it can change due\n\t\t\t\t// to //line directives.\n\t\t\t\tposn := act.Package.Fset.Position(c.Pos())\n\t\t\t\tfilename := sanitize(gopath, posn.Filename)\n\t\t\t\tprocessComment(filename, posn.Line, text)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract 'want' comments from non-Go files.\n\t// TODO(adonovan): we may need to handle //line directives.\n\tfiles := act.Package.OtherFiles\n\n\t// Hack: these analyzers need to extract expectations from\n\t// all configurations, so include the files are usually\n\t// ignored. (This was previously a hack in the respective\n\t// analyzers' tests.)\n\tswitch act.Analyzer.Name {\n\tcase \"buildtag\", \"directive\", \"plusbuild\":\n\t\tfiles = slices.Concat(files, act.Package.IgnoredFiles)\n\t}\n\n\tfor _, filename := range files {\n\t\tdata, err := os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"can't read '// want' comments from %s: %v\", filename, err)\n\t\t\tcontinue\n\t\t}\n\t\tfilename := sanitize(gopath, filename)\n\t\tlinenum := 0\n\t\tfor line := range strings.SplitSeq(string(data), \"\\n\") {\n\t\t\tlinenum++\n\n\t\t\t// Hack: treat a comment of the form \"//...// want...\"\n\t\t\t// or \"/*...// want... */\n\t\t\t// as if it starts at 'want'.\n\t\t\t// This allows us to add comments on comments,\n\t\t\t// as required when testing the buildtag analyzer.\n\t\t\tif i := strings.Index(line, \"// want\"); i >= 0 {\n\t\t\t\tline = line[i:]\n\t\t\t}\n\n\t\t\tif i := strings.Index(line, \"//\"); i >= 0 {\n\t\t\t\tline = line[i+len(\"//\"):]\n\t\t\t\tprocessComment(filename, linenum, line)\n\t\t\t}\n\t\t}\n\t}\n\n\tcheckMessage := func(posn token.Position, kind, name, message string) {\n\t\tposn.Filename = sanitize(gopath, posn.Filename)\n\t\tk := key{posn.Filename, posn.Line}\n\t\texpects := want[k]\n\t\tvar unmatched []string\n\t\tfor i, exp := range expects {\n\t\t\tif exp.kind == kind && exp.name == name {\n\t\t\t\tif exp.rx.MatchString(message) {\n\t\t\t\t\t// matched: remove the expectation.\n\t\t\t\t\texpects[i] = expects[len(expects)-1]\n\t\t\t\t\texpects = expects[:len(expects)-1]\n\t\t\t\t\twant[k] = expects\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tunmatched = append(unmatched, fmt.Sprintf(\"%#q\", exp.rx))\n\t\t\t}\n\t\t}\n\t\tif unmatched == nil {\n\t\t\tt.Errorf(\"%v: unexpected %s: %v\", posn, kind, message)\n\t\t} else {\n\t\t\tt.Errorf(\"%v: %s %q does not match pattern %s\",\n\t\t\t\tposn, kind, message, strings.Join(unmatched, \" or \"))\n\t\t}\n\t}\n\n\t// Check the diagnostics match expectations.\n\tfor _, f := range act.Diagnostics {\n\t\t// TODO(matloob): Support ranges in analysistest.\n\t\tposn := act.Package.Fset.Position(f.Pos)\n\t\tcheckMessage(posn, \"diagnostic\", \"\", f.Message)\n\t}\n\n\t// Check the facts match expectations.\n\t// We check only facts relating to the current package.\n\t//\n\t// We report errors in lexical order for determinism.\n\t// (It's only deterministic within each file, not across files,\n\t// because go/packages does not guarantee file.Pos is ascending\n\t// across the files of a single compilation unit.)\n\n\t// package facts: reported at start of first file\n\tfor _, pkgFact := range act.AllPackageFacts() {\n\t\tif pkgFact.Package == act.Package.Types {\n\t\t\tposn := act.Package.Fset.Position(act.Package.Syntax[0].Pos())\n\t\t\tposn.Line, posn.Column = 1, 1\n\t\t\tcheckMessage(posn, \"fact\", \"package\", fmt.Sprint(pkgFact))\n\t\t}\n\t}\n\n\t// object facts: reported at line of object declaration\n\tobjFacts := act.AllObjectFacts()\n\tsort.Slice(objFacts, func(i, j int) bool {\n\t\treturn objFacts[i].Object.Pos() < objFacts[j].Object.Pos()\n\t})\n\tfor _, objFact := range objFacts {\n\t\tif obj := objFact.Object; obj.Pkg() == act.Package.Types {\n\t\t\tposn := act.Package.Fset.Position(obj.Pos())\n\t\t\tcheckMessage(posn, \"fact\", obj.Name(), fmt.Sprint(objFact.Fact))\n\t\t}\n\t}\n\n\t// Reject surplus expectations.\n\t//\n\t// Sometimes an Analyzer reports two similar diagnostics on a\n\t// line with only one expectation. The reader may be confused by\n\t// the error message.\n\t// TODO(adonovan): print a better error:\n\t// \"got 2 diagnostics here; each one needs its own expectation\".\n\tvar surplus []string\n\tfor key, expects := range want {\n\t\tfor _, exp := range expects {\n\t\t\terr := fmt.Sprintf(\"%s:%d: no %s was reported matching %#q\", key.file, key.line, exp.kind, exp.rx)\n\t\t\tsurplus = append(surplus, err)\n\t\t}\n\t}\n\tsort.Strings(surplus)\n\tfor _, err := range surplus {\n\t\tt.Errorf(\"%s\", err)\n\t}\n}\n\ntype expectation struct {\n\tkind string // either \"fact\" or \"diagnostic\"\n\tname string // name of object to which fact belongs, or \"package\" (\"fact\" only)\n\trx   *regexp.Regexp\n}\n\nfunc (ex expectation) String() string {\n\treturn fmt.Sprintf(\"%s %s:%q\", ex.kind, ex.name, ex.rx) // for debugging\n}\n\n// parseExpectations parses the content of a \"// want ...\" comment\n// and returns the expectations, a mixture of diagnostics (\"rx\") and\n// facts (name:\"rx\").\nfunc parseExpectations(text string) (lineDelta int, expects []expectation, err error) {\n\tvar scanErr string\n\tsc := new(scanner.Scanner).Init(strings.NewReader(text))\n\tsc.Error = func(s *scanner.Scanner, msg string) {\n\t\tscanErr = msg // e.g. bad string escape\n\t}\n\tsc.Mode = scanner.ScanIdents | scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanInts\n\n\tscanRegexp := func(tok rune) (*regexp.Regexp, error) {\n\t\tif tok != scanner.String && tok != scanner.RawString {\n\t\t\treturn nil, fmt.Errorf(\"got %s, want regular expression\",\n\t\t\t\tscanner.TokenString(tok))\n\t\t}\n\t\tpattern, _ := strconv.Unquote(sc.TokenText()) // can't fail\n\t\treturn regexp.Compile(pattern)\n\t}\n\n\tfor {\n\t\ttok := sc.Scan()\n\t\tswitch tok {\n\t\tcase '+':\n\t\t\ttok = sc.Scan()\n\t\t\tif tok != scanner.Int {\n\t\t\t\treturn 0, nil, fmt.Errorf(\"got +%s, want +Int\", scanner.TokenString(tok))\n\t\t\t}\n\t\t\tlineDelta, _ = strconv.Atoi(sc.TokenText())\n\t\tcase scanner.String, scanner.RawString:\n\t\t\trx, err := scanRegexp(tok)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, nil, err\n\t\t\t}\n\t\t\texpects = append(expects, expectation{\"diagnostic\", \"\", rx})\n\n\t\tcase scanner.Ident:\n\t\t\tname := sc.TokenText()\n\t\t\ttok = sc.Scan()\n\t\t\tif tok != ':' {\n\t\t\t\treturn 0, nil, fmt.Errorf(\"got %s after %s, want ':'\",\n\t\t\t\t\tscanner.TokenString(tok), name)\n\t\t\t}\n\t\t\ttok = sc.Scan()\n\t\t\trx, err := scanRegexp(tok)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, nil, err\n\t\t\t}\n\t\t\texpects = append(expects, expectation{\"fact\", name, rx})\n\n\t\tcase scanner.EOF:\n\t\t\tif scanErr != \"\" {\n\t\t\t\treturn 0, nil, fmt.Errorf(\"%s\", scanErr)\n\t\t\t}\n\t\t\treturn lineDelta, expects, nil\n\n\t\tdefault:\n\t\t\treturn 0, nil, fmt.Errorf(\"unexpected %s\", scanner.TokenString(tok))\n\t\t}\n\t}\n}\n\n// sanitize removes the GOPATH portion of the filename,\n// typically a gnarly /tmp directory, and returns the rest.\nfunc sanitize(gopath, filename string) string {\n\tprefix := gopath + string(os.PathSeparator) + \"src\" + string(os.PathSeparator)\n\treturn filepath.ToSlash(strings.TrimPrefix(filename, prefix))\n}\n"
  },
  {
    "path": "go/analysis/analysistest/analysistest_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysistest_test\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc init() {\n\t// Run() decides when tests use GOPATH mode or modules.\n\t// We turn off GOPROXY just for good measure.\n\tif err := os.Setenv(\"GOPROXY\", \"off\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\n// TestTheTest tests the analysistest testing infrastructure.\nfunc TestTheTest(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// We'll simulate a partly failing test of the findcall analysis,\n\t// which (by default) reports calls to functions named 'println'.\n\tfindcall.Analyzer.Flags.Set(\"name\", \"println\")\n\n\tfilemap := map[string]string{\n\t\t\"a/b.go\": `package main // want package:\"found\"\n\nfunc main() {\n\t// The expectation is ill-formed:\n\tprint() // want: \"diagnostic\"\n\tprint() // want foo\"fact\"\n\tprint() // want foo:\n\tprint() // want \"\\xZZ scan error\"\n\n\t// A diagnostic is reported at this line, but the expectation doesn't match:\n\tprintln(\"hello, world\") // want \"wrong expectation text\"\n\n\t// An unexpected diagnostic is reported at this line:\n\tprintln() // trigger an unexpected diagnostic\n\n\t// No diagnostic is reported at this line:\n\tprint()\t// want \"unsatisfied expectation\"\n\n\t// OK\n\tprintln(\"hello, world\") // want \"call of println\"\n\n\t// OK /* */-form.\n\tprintln(\"안녕, 세계\") /* want \"call of println\" */\n\n\t// OK  (nested comment)\n\tprintln(\"Γειά σου, Κόσμε\") // some comment // want \"call of println\"\n\n\t// OK (nested comment in /**/)\n\tprintln(\"你好，世界\") /* some comment // want \"call of println\" */\n\n\t// OK (multiple expectations on same line)\n\tprintln(); println() // want \"call of println(...)\" \"call of println(...)\"\n\n\t// A Line that is not formatted correctly in the golden file.\n}\n\n// OK (facts and diagnostics on same line)\nfunc println(...interface{}) { println() } // want println:\"found\" \"call of println(...)\"\n\n`,\n\t\t\"a/b.go.golden\": `package main // want package:\"found\"\n\nfunc main() {\n\t// The expectation is ill-formed:\n\tprint() // want: \"diagnostic\"\n\tprint() // want foo\"fact\"\n\tprint() // want foo:\n\tprint() // want \"\\xZZ scan error\"\n\n\t// A diagnostic is reported at this line, but the expectation doesn't match:\n\tprintln_TEST_(\"hello, world\") // want \"wrong expectation text\"\n\n\t// An unexpected diagnostic is reported at this line:\n\tprintln_TEST_() // trigger an unexpected diagnostic\n\n\t// No diagnostic is reported at this line:\n\tprint() // want \"unsatisfied expectation\"\n\n\t// OK\n\tprintln_TEST_(\"hello, world\") // want \"call of println\"\n\n\t// OK /* */-form.\n\tprintln_TEST_(\"안녕, 세계\") /* want \"call of println\" */\n\n\t// OK  (nested comment)\n\tprintln_TEST_(\"Γειά σου, Κόσμε\") // some comment // want \"call of println\"\n\n\t// OK (nested comment in /**/)\n\tprintln_TEST_(\"你好，世界\") /* some comment // want \"call of println\" */\n\n\t// OK (multiple expectations on same line)\n\tprintln_TEST_()\n\tprintln_TEST_() // want \"call of println(...)\" \"call of println(...)\"\n\t\n\t\t\t// A Line that is not formatted correctly in the golden file.\n}\n\n// OK (facts and diagnostics on same line)\nfunc println(...interface{}) { println_TEST_() } // want println:\"found\" \"call of println(...)\"\n`,\n\t\t\"a/b_test.go\": `package main\n\n// Test file shouldn't mess with things (issue #40574)\n`,\n\t}\n\tdir, cleanup, err := analysistest.WriteFiles(filemap)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\n\tvar got []string\n\tt2 := errorfunc(func(s string) { got = append(got, s) }) // a fake *testing.T\n\tanalysistest.RunWithSuggestedFixes(t2, dir, findcall.Analyzer, \"a\")\n\n\twant := []string{\n\t\t`a/b.go:5: in 'want' comment: unexpected \":\"`,\n\t\t`a/b.go:6: in 'want' comment: got String after foo, want ':'`,\n\t\t`a/b.go:7: in 'want' comment: got EOF, want regular expression`,\n\t\t`a/b.go:8: in 'want' comment: invalid char escape`,\n\t\t\"a/b.go:11:9: diagnostic \\\"call of println(...)\\\" does not match pattern `wrong expectation text`\",\n\t\t`a/b.go:14:9: unexpected diagnostic: call of println(...)`,\n\t\t\"a/b.go:11: no diagnostic was reported matching `wrong expectation text`\",\n\t\t\"a/b.go:17: no diagnostic was reported matching `unsatisfied expectation`\",\n\t\t// duplicate copies of each message from the test package (see issue #40574)\n\t\t`a/b.go:5: in 'want' comment: unexpected \":\"`,\n\t\t`a/b.go:6: in 'want' comment: got String after foo, want ':'`,\n\t\t`a/b.go:7: in 'want' comment: got EOF, want regular expression`,\n\t\t`a/b.go:8: in 'want' comment: invalid char escape`,\n\t\t\"a/b.go:11:9: diagnostic \\\"call of println(...)\\\" does not match pattern `wrong expectation text`\",\n\t\t`a/b.go:14:9: unexpected diagnostic: call of println(...)`,\n\t\t\"a/b.go:11: no diagnostic was reported matching `wrong expectation text`\",\n\t\t\"a/b.go:17: no diagnostic was reported matching `unsatisfied expectation`\",\n\t}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"got:\\n%s\\nwant:\\n%s\",\n\t\t\tstrings.Join(got, \"\\n\"),\n\t\t\tstrings.Join(want, \"\\n\"))\n\t}\n}\n\n// TestNoEnd tests that a missing SuggestedFix.End position is\n// correctly interpreted as if equal to SuggestedFix.Pos (see issue #64199).\nfunc TestNoEnd(t *testing.T) {\n\tnoend := &analysis.Analyzer{\n\t\tName: \"noend\",\n\t\tDoc:  \"inserts /*hello*/ before first decl\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tdecl := pass.Files[0].Decls[0]\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     decl.Pos(),\n\t\t\t\tEnd:     token.NoPos,\n\t\t\t\tMessage: \"say hello\",\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: \"say hello\",\n\t\t\t\t\tTextEdits: []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     decl.Pos(),\n\t\t\t\t\t\t\tEnd:     token.NoPos,\n\t\t\t\t\t\t\tNewText: []byte(\"/*hello*/\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}},\n\t\t\t})\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\n\tfilemap := map[string]string{\n\t\t\"a/a.go\": `package a\n\nfunc F() {} // want \"say hello\"`,\n\t\t\"a/a.go.golden\": `package a\n\n/*hello*/\nfunc F() {} // want \"say hello\"`,\n\t}\n\tdir, cleanup, err := analysistest.WriteFiles(filemap)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\n\tanalysistest.RunWithSuggestedFixes(t, dir, noend, \"a\")\n}\n\nfunc TestModule(t *testing.T) {\n\tconst content = `\nTest that analysis.pass.Module is populated.\n\n-- go.mod --\nmodule golang.org/fake/mod\n\ngo 1.21\n\nrequire golang.org/xyz/fake v0.12.34\n\n-- mod.go --\n// We expect a module.Path and a module.GoVersion, but an empty module.Version.\n\npackage mod // want \"golang.org/fake/mod,,1.21\"\n\nimport \"golang.org/xyz/fake/ver\"\n\nvar _ ver.T\n\n-- vendor/modules.txt --\n# golang.org/xyz/fake v0.12.34\n## explicit; go 1.18\ngolang.org/xyz/fake/ver\n\n-- vendor/golang.org/xyz/fake/ver/ver.go --\n// This package is vendored so that we can populate a non-empty\n// Pass.Module.Version is in a test.\n\npackage ver //want \"golang.org/xyz/fake,v0.12.34,1.18\"\n\ntype T string\n`\n\tfs, err := txtar.FS(txtar.Parse([]byte(content)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdir := testfiles.CopyToTmp(t, fs)\n\n\tfilever := &analysis.Analyzer{\n\t\tName: \"mod\",\n\t\tDoc:  \"reports module information\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tmsg := \"no module info\"\n\t\t\tif m := pass.Module; m != nil {\n\t\t\t\tmsg = fmt.Sprintf(\"%s,%s,%s\", m.Path, m.Version, m.GoVersion)\n\t\t\t}\n\t\t\tfor _, file := range pass.Files {\n\t\t\t\tpass.Reportf(file.Package, \"%s\", msg)\n\t\t\t}\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\tanalysistest.Run(t, dir, filever, \"golang.org/fake/mod\", \"golang.org/xyz/fake/ver\")\n}\n\ntype errorfunc func(string)\n\nfunc (f errorfunc) Errorf(format string, args ...any) {\n\tf(fmt.Sprintf(format, args...))\n}\n"
  },
  {
    "path": "go/analysis/checker/checker.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package checker provides an analysis driver based on the\n// [golang.org/x/tools/go/packages] representation of a set of\n// packages and all their dependencies, as produced by\n// [packages.Load].\n//\n// It is the core of multichecker (the multi-analyzer driver),\n// singlechecker (the single-analyzer driver often used to provide a\n// convenient command alongside each analyzer), and analysistest, the\n// test driver.\n//\n// By contrast, the 'go vet' command is based on unitchecker, an\n// analysis driver that uses separate analysis--analogous to separate\n// compilation--with file-based intermediate results. Like separate\n// compilation, it is more scalable, especially for incremental\n// analysis of large code bases. Commands based on multichecker and\n// singlechecker are capable of detecting when they are being invoked\n// by \"go vet -vettool=exe\" and instead dispatching to unitchecker.\n//\n// Programs built using this package will, in general, not be usable\n// in that way. This package is intended only for use in applications\n// that invoke the analysis driver as a subroutine, and need to insert\n// additional steps before or after the analysis.\n//\n// See the Example of how to build a complete analysis driver program.\npackage checker\n\nimport (\n\t\"bytes\"\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"io\"\n\t\"iter\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/internal\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n)\n\n// Options specifies options that control the analysis driver.\ntype Options struct {\n\t// These options correspond to existing flags exposed by multichecker:\n\tSequential  bool      // disable parallelism\n\tSanityCheck bool      // check fact encoding is ok and deterministic\n\tFactLog     io.Writer // if non-nil, log each exported fact to it\n\n\t// TODO(adonovan): expose ReadFile so that an Overlay specified\n\t// in the [packages.Config] can be communicated via\n\t// Pass.ReadFile to each Analyzer.\n\treadFile driverutil.ReadFileFunc\n}\n\n// Graph holds the results of a round of analysis, including the graph\n// of requested actions (analyzers applied to packages) plus any\n// dependent actions that it was necessary to compute.\ntype Graph struct {\n\t// Roots contains the roots of the action graph.\n\t// Each node (a, p) in the action graph represents the\n\t// application of one analyzer a to one package p.\n\t// (A node thus corresponds to one analysis.Pass instance.)\n\t// Roots holds one action per element of the product\n\t// of the analyzers × packages arguments to Analyze,\n\t// in unspecified order.\n\t//\n\t// Each element of Action.Deps represents an edge in the\n\t// action graph: a dependency from one action to another.\n\t// An edge of the form (a, p) -> (a, p2) indicates that the\n\t// analysis of package p requires information (\"facts\") from\n\t// the same analyzer applied to one of p's dependencies, p2.\n\t// An edge of the form (a, p) -> (a2, p) indicates that the\n\t// analysis of package p requires information (\"results\")\n\t// from a different analyzer a2 applied to the same package.\n\t// These two kind of edges are called \"vertical\" and \"horizontal\",\n\t// respectively.\n\tRoots []*Action\n}\n\n// All returns an iterator over the action graph in depth-first postorder.\n//\n// Example:\n//\n//\tfor act := range graph.All() {\n//\t\t...\n//\t}\nfunc (g *Graph) All() iter.Seq[*Action] {\n\treturn func(yield func(*Action) bool) {\n\t\tforEach(g.Roots, func(act *Action) error {\n\t\t\tif !yield(act) {\n\t\t\t\treturn io.EOF // any error will do\n\t\t\t}\n\t\t\treturn nil\n\t\t}) // ignore error\n\t}\n}\n\n// An Action represents one unit of analysis work by the driver: the\n// application of one analysis to one package. It provides the inputs\n// to and records the outputs of a single analysis.Pass.\n//\n// Actions form a DAG, both within a package (as different analyzers\n// are applied, either in sequence or parallel), and across packages\n// (as dependencies are analyzed).\ntype Action struct {\n\tAnalyzer    *analysis.Analyzer\n\tPackage     *packages.Package\n\tIsRoot      bool // whether this is a root node of the graph\n\tDeps        []*Action\n\tResult      any   // computed result of Analyzer.run, if any (and if IsRoot)\n\tErr         error // error result of Analyzer.run\n\tDiagnostics []analysis.Diagnostic\n\tDuration    time.Duration // execution time of this step\n\n\topts         *Options\n\tonce         sync.Once\n\tpass         *analysis.Pass\n\tobjectFacts  map[objectFactKey]analysis.Fact\n\tpackageFacts map[packageFactKey]analysis.Fact\n}\n\nfunc (act *Action) String() string {\n\treturn fmt.Sprintf(\"%s@%s\", act.Analyzer, act.Package)\n}\n\n// Analyze runs the specified analyzers on the initial packages.\n//\n// The initial packages and all dependencies must have been loaded\n// using the [packages.LoadAllSyntax] flag, Analyze may need to run\n// some analyzer (those that consume and produce facts) on\n// dependencies too.\n//\n// On success, it returns a Graph of actions whose Roots hold one\n// item per (a, p) in the cross-product of analyzers and pkgs.\n//\n// If opts is nil, it is equivalent to new(Options).\nfunc Analyze(analyzers []*analysis.Analyzer, pkgs []*packages.Package, opts *Options) (*Graph, error) {\n\tif opts == nil {\n\t\topts = new(Options)\n\t}\n\n\tif err := analysis.Validate(analyzers); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Construct the action graph.\n\t//\n\t// Each graph node (action) is one unit of analysis.\n\t// Edges express package-to-package (vertical) dependencies,\n\t// and analysis-to-analysis (horizontal) dependencies.\n\ttype key struct {\n\t\ta   *analysis.Analyzer\n\t\tpkg *packages.Package\n\t}\n\tactions := make(map[key]*Action)\n\n\tvar mkAction func(a *analysis.Analyzer, pkg *packages.Package) *Action\n\tmkAction = func(a *analysis.Analyzer, pkg *packages.Package) *Action {\n\t\tk := key{a, pkg}\n\t\tact, ok := actions[k]\n\t\tif !ok {\n\t\t\tact = &Action{Analyzer: a, Package: pkg, opts: opts}\n\n\t\t\t// Add a dependency on each required analyzers.\n\t\t\tfor _, req := range a.Requires {\n\t\t\t\tact.Deps = append(act.Deps, mkAction(req, pkg))\n\t\t\t}\n\n\t\t\t// An analysis that consumes/produces facts\n\t\t\t// must run on the package's dependencies too.\n\t\t\tif len(a.FactTypes) > 0 {\n\t\t\t\tpaths := make([]string, 0, len(pkg.Imports))\n\t\t\t\tfor path := range pkg.Imports {\n\t\t\t\t\tpaths = append(paths, path)\n\t\t\t\t}\n\t\t\t\tsort.Strings(paths) // for determinism\n\t\t\t\tfor _, path := range paths {\n\t\t\t\t\tdep := mkAction(a, pkg.Imports[path])\n\t\t\t\t\tact.Deps = append(act.Deps, dep)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tactions[k] = act\n\t\t}\n\t\treturn act\n\t}\n\n\t// Build nodes for initial packages.\n\tvar roots []*Action\n\tfor _, a := range analyzers {\n\t\tfor _, pkg := range pkgs {\n\t\t\troot := mkAction(a, pkg)\n\t\t\troot.IsRoot = true\n\t\t\troots = append(roots, root)\n\t\t}\n\t}\n\n\t// Execute the graph in parallel.\n\texecAll(roots)\n\n\t// Ensure that only root Results are visible to caller.\n\t// (The others are considered temporary intermediaries.)\n\t// TODO(adonovan): opt: clear them earlier, so we can\n\t// release large data structures like SSA sooner.\n\tfor _, act := range actions {\n\t\tif !act.IsRoot {\n\t\t\tact.Result = nil\n\t\t}\n\t}\n\n\treturn &Graph{Roots: roots}, nil\n}\n\nfunc init() {\n\t// Allow analysistest to access Action.pass,\n\t// for the legacy analysistest.Result data type,\n\t// and for internal/checker.ApplyFixes to access pass.ReadFile.\n\tinternal.ActionPass = func(x any) *analysis.Pass { return x.(*Action).pass }\n}\n\ntype objectFactKey struct {\n\tobj types.Object\n\ttyp reflect.Type\n}\n\ntype packageFactKey struct {\n\tpkg *types.Package\n\ttyp reflect.Type\n}\n\nfunc execAll(actions []*Action) {\n\tvar wg sync.WaitGroup\n\tfor _, act := range actions {\n\t\twg.Add(1)\n\t\twork := func(act *Action) {\n\t\t\tact.exec()\n\t\t\twg.Done()\n\t\t}\n\t\tif act.opts.Sequential {\n\t\t\twork(act)\n\t\t} else {\n\t\t\tgo work(act)\n\t\t}\n\t}\n\twg.Wait()\n}\n\nfunc (act *Action) exec() { act.once.Do(act.execOnce) }\n\nfunc (act *Action) execOnce() {\n\t// Analyze dependencies.\n\texecAll(act.Deps)\n\n\t// Record time spent in this node but not its dependencies.\n\t// In parallel mode, due to GC/scheduler contention, the\n\t// time is 5x higher than in sequential mode, even with a\n\t// semaphore limiting the number of threads here.\n\t// So use -debug=tp.\n\tt0 := time.Now()\n\tdefer func() { act.Duration = time.Since(t0) }()\n\n\t// Report an error if any dependency failed.\n\tvar failed []string\n\tfor _, dep := range act.Deps {\n\t\tif dep.Err != nil {\n\t\t\tfailed = append(failed, dep.String())\n\t\t}\n\t}\n\tif failed != nil {\n\t\tsort.Strings(failed)\n\t\tact.Err = fmt.Errorf(\"failed prerequisites: %s\", strings.Join(failed, \", \"))\n\t\treturn\n\t}\n\n\t// Plumb the output values of the dependencies\n\t// into the inputs of this action.  Also facts.\n\tinputs := make(map[*analysis.Analyzer]any)\n\tact.objectFacts = make(map[objectFactKey]analysis.Fact)\n\tact.packageFacts = make(map[packageFactKey]analysis.Fact)\n\tfor _, dep := range act.Deps {\n\t\tif dep.Package == act.Package {\n\t\t\t// Same package, different analysis (horizontal edge):\n\t\t\t// in-memory outputs of prerequisite analyzers\n\t\t\t// become inputs to this analysis pass.\n\t\t\tinputs[dep.Analyzer] = dep.Result\n\t\t} else if dep.Analyzer == act.Analyzer { // (always true)\n\t\t\t// Same analysis, different package (vertical edge):\n\t\t\t// serialized facts produced by prerequisite analysis\n\t\t\t// become available to this analysis pass.\n\t\t\tinheritFacts(act, dep)\n\t\t}\n\t}\n\n\t// Quick (nonexhaustive) check that the correct go/packages mode bits were used.\n\t// (If there were errors, all bets are off.)\n\tif pkg := act.Package; pkg.Errors == nil {\n\t\tif pkg.Name == \"\" || pkg.PkgPath == \"\" || pkg.Types == nil || pkg.Fset == nil || pkg.TypesSizes == nil {\n\t\t\tpanic(\"packages must be loaded with packages.LoadSyntax mode\")\n\t\t}\n\t}\n\n\tmodule := &analysis.Module{} // possibly empty (non nil) in go/analysis drivers.\n\tif mod := act.Package.Module; mod != nil {\n\t\tmodule = analysisModuleFromPackagesModule(mod)\n\t}\n\n\t// Run the analysis.\n\tpass := &analysis.Pass{\n\t\tAnalyzer:     act.Analyzer,\n\t\tFset:         act.Package.Fset,\n\t\tFiles:        act.Package.Syntax,\n\t\tOtherFiles:   act.Package.OtherFiles,\n\t\tIgnoredFiles: act.Package.IgnoredFiles,\n\t\tPkg:          act.Package.Types,\n\t\tTypesInfo:    act.Package.TypesInfo,\n\t\tTypesSizes:   act.Package.TypesSizes,\n\t\tTypeErrors:   act.Package.TypeErrors,\n\t\tModule:       module,\n\n\t\tResultOf: inputs,\n\t\tReport: func(d analysis.Diagnostic) {\n\t\t\t// Assert that SuggestedFixes are well formed.\n\t\t\tif err := driverutil.ValidateFixes(act.Package.Fset, act.Analyzer, d.SuggestedFixes); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tact.Diagnostics = append(act.Diagnostics, d)\n\t\t},\n\t\tImportObjectFact:  act.ObjectFact,\n\t\tExportObjectFact:  act.exportObjectFact,\n\t\tImportPackageFact: act.PackageFact,\n\t\tExportPackageFact: act.exportPackageFact,\n\t\tAllObjectFacts:    act.AllObjectFacts,\n\t\tAllPackageFacts:   act.AllPackageFacts,\n\t}\n\treadFile := os.ReadFile\n\tif act.opts.readFile != nil {\n\t\treadFile = act.opts.readFile\n\t}\n\tpass.ReadFile = driverutil.CheckedReadFile(pass, readFile)\n\tact.pass = pass\n\n\tact.Result, act.Err = func() (any, error) {\n\t\tif act.Package.IllTyped && !pass.Analyzer.RunDespiteErrors {\n\t\t\treturn nil, fmt.Errorf(\"analysis skipped due to errors in package\")\n\t\t}\n\n\t\tresult, err := pass.Analyzer.Run(pass)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// correct result type?\n\t\tif got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v\",\n\t\t\t\tpass.Pkg.Path(), pass.Analyzer, got, want)\n\t\t}\n\n\t\t// resolve diagnostic URLs\n\t\tfor i := range act.Diagnostics {\n\t\t\turl, err := driverutil.ResolveURL(act.Analyzer, act.Diagnostics[i])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tact.Diagnostics[i].URL = url\n\t\t}\n\t\treturn result, nil\n\t}()\n\n\t// Help detect (disallowed) calls after Run.\n\tpass.ExportObjectFact = nil\n\tpass.ExportPackageFact = nil\n}\n\n// inheritFacts populates act.facts with\n// those it obtains from its dependency, dep.\nfunc inheritFacts(act, dep *Action) {\n\tfor key, fact := range dep.objectFacts {\n\t\t// Filter out facts related to objects\n\t\t// that are irrelevant downstream\n\t\t// (equivalently: not in the compiler export data).\n\t\tif !exportedFrom(key.obj, dep.Package.Types) {\n\t\t\tif false {\n\t\t\t\tlog.Printf(\"%v: discarding %T fact from %s for %s: %s\", act, fact, dep, key.obj, fact)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Optionally serialize/deserialize fact\n\t\t// to verify that it works across address spaces.\n\t\tif act.opts.SanityCheck {\n\t\t\tencodedFact, err := codeFact(fact)\n\t\t\tif err != nil {\n\t\t\t\tlog.Panicf(\"internal error: encoding of %T fact failed in %v\", fact, act)\n\t\t\t}\n\t\t\tfact = encodedFact\n\t\t}\n\n\t\tif false {\n\t\t\tlog.Printf(\"%v: inherited %T fact for %s: %s\", act, fact, key.obj, fact)\n\t\t}\n\t\tact.objectFacts[key] = fact\n\t}\n\n\tfor key, fact := range dep.packageFacts {\n\t\t// TODO: filter out facts that belong to\n\t\t// packages not mentioned in the export data\n\t\t// to prevent side channels.\n\t\t//\n\t\t// The Pass.All{Object,Package}Facts accessors expose too much:\n\t\t// all facts, of all types, for all dependencies in the action\n\t\t// graph. Not only does the representation grow quadratically,\n\t\t// but it violates the separate compilation paradigm, allowing\n\t\t// analysis implementations to communicate with indirect\n\t\t// dependencies that are not mentioned in the export data.\n\t\t//\n\t\t// It's not clear how to fix this short of a rather expensive\n\t\t// filtering step after each action that enumerates all the\n\t\t// objects that would appear in export data, and deletes\n\t\t// facts associated with objects not in this set.\n\n\t\t// Optionally serialize/deserialize fact\n\t\t// to verify that it works across address spaces\n\t\t// and is deterministic.\n\t\tif act.opts.SanityCheck {\n\t\t\tencodedFact, err := codeFact(fact)\n\t\t\tif err != nil {\n\t\t\t\tlog.Panicf(\"internal error: encoding of %T fact failed in %v\", fact, act)\n\t\t\t}\n\t\t\tfact = encodedFact\n\t\t}\n\n\t\tif false {\n\t\t\tlog.Printf(\"%v: inherited %T fact for %s: %s\", act, fact, key.pkg.Path(), fact)\n\t\t}\n\t\tact.packageFacts[key] = fact\n\t}\n}\n\n// codeFact encodes then decodes a fact,\n// just to exercise that logic.\nfunc codeFact(fact analysis.Fact) (analysis.Fact, error) {\n\t// We encode facts one at a time.\n\t// A real modular driver would emit all facts\n\t// into one encoder to improve gob efficiency.\n\tvar buf bytes.Buffer\n\tif err := gob.NewEncoder(&buf).Encode(fact); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Encode it twice and assert that we get the same bits.\n\t// This helps detect nondeterministic Gob encoding (e.g. of maps).\n\tvar buf2 bytes.Buffer\n\tif err := gob.NewEncoder(&buf2).Encode(fact); err != nil {\n\t\treturn nil, err\n\t}\n\tif !bytes.Equal(buf.Bytes(), buf2.Bytes()) {\n\t\treturn nil, fmt.Errorf(\"encoding of %T fact is nondeterministic\", fact)\n\t}\n\n\tnew := reflect.New(reflect.TypeOf(fact).Elem()).Interface().(analysis.Fact)\n\tif err := gob.NewDecoder(&buf).Decode(new); err != nil {\n\t\treturn nil, err\n\t}\n\treturn new, nil\n}\n\n// exportedFrom reports whether obj may be visible to a package that imports pkg.\n// This includes not just the exported members of pkg, but also unexported\n// constants, types, fields, and methods, perhaps belonging to other packages,\n// that find there way into the API.\n// This is an overapproximation of the more accurate approach used by\n// gc export data, which walks the type graph, but it's much simpler.\n//\n// TODO(adonovan): do more accurate filtering by walking the type graph.\nfunc exportedFrom(obj types.Object, pkg *types.Package) bool {\n\tswitch obj := obj.(type) {\n\tcase *types.Func:\n\t\treturn obj.Exported() && obj.Pkg() == pkg ||\n\t\t\tobj.Signature().Recv() != nil\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\treturn true\n\t\t}\n\t\t// we can't filter more aggressively than this because we need\n\t\t// to consider function parameters exported, but have no way\n\t\t// of telling apart function parameters from local variables.\n\t\treturn obj.Pkg() == pkg\n\tcase *types.TypeName, *types.Const:\n\t\treturn true\n\t}\n\treturn false // Nil, Builtin, Label, or PkgName\n}\n\n// ObjectFact retrieves a fact associated with obj,\n// and returns true if one was found.\n// Given a value ptr of type *T, where *T satisfies Fact,\n// ObjectFact copies the value to *ptr.\n//\n// See documentation at ImportObjectFact field of [analysis.Pass].\nfunc (act *Action) ObjectFact(obj types.Object, ptr analysis.Fact) bool {\n\tif obj == nil {\n\t\tpanic(\"nil object\")\n\t}\n\tkey := objectFactKey{obj, factType(ptr)}\n\tif v, ok := act.objectFacts[key]; ok {\n\t\treflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())\n\t\treturn true\n\t}\n\treturn false\n}\n\n// exportObjectFact implements Pass.ExportObjectFact.\nfunc (act *Action) exportObjectFact(obj types.Object, fact analysis.Fact) {\n\tif act.pass.ExportObjectFact == nil {\n\t\tlog.Panicf(\"%s: Pass.ExportObjectFact(%s, %T) called after Run\", act, obj, fact)\n\t}\n\n\tif obj.Pkg() != act.Package.Types {\n\t\tlog.Panicf(\"internal error: in analysis %s of package %s: Fact.Set(%s, %T): can't set facts on objects belonging another package\",\n\t\t\tact.Analyzer, act.Package, obj, fact)\n\t}\n\n\tkey := objectFactKey{obj, factType(fact)}\n\tact.objectFacts[key] = fact // clobber any existing entry\n\tif log := act.opts.FactLog; log != nil {\n\t\tobjstr := types.ObjectString(obj, (*types.Package).Name)\n\t\tfmt.Fprintf(log, \"%s: object %s has fact %s\\n\",\n\t\t\tact.Package.Fset.Position(obj.Pos()), objstr, fact)\n\t}\n}\n\n// AllObjectFacts returns a new slice containing all object facts of\n// the analysis's FactTypes in unspecified order.\n//\n// See documentation at AllObjectFacts field of [analysis.Pass].\nfunc (act *Action) AllObjectFacts() []analysis.ObjectFact {\n\tfacts := make([]analysis.ObjectFact, 0, len(act.objectFacts))\n\tfor k, fact := range act.objectFacts {\n\t\tfacts = append(facts, analysis.ObjectFact{Object: k.obj, Fact: fact})\n\t}\n\treturn facts\n}\n\n// PackageFact retrieves a fact associated with package pkg,\n// which must be this package or one of its dependencies.\n//\n// See documentation at ImportObjectFact field of [analysis.Pass].\nfunc (act *Action) PackageFact(pkg *types.Package, ptr analysis.Fact) bool {\n\tif pkg == nil {\n\t\tpanic(\"nil package\")\n\t}\n\tkey := packageFactKey{pkg, factType(ptr)}\n\tif v, ok := act.packageFacts[key]; ok {\n\t\treflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())\n\t\treturn true\n\t}\n\treturn false\n}\n\n// exportPackageFact implements Pass.ExportPackageFact.\nfunc (act *Action) exportPackageFact(fact analysis.Fact) {\n\tif act.pass.ExportPackageFact == nil {\n\t\tlog.Panicf(\"%s: Pass.ExportPackageFact(%T) called after Run\", act, fact)\n\t}\n\n\tkey := packageFactKey{act.pass.Pkg, factType(fact)}\n\tact.packageFacts[key] = fact // clobber any existing entry\n\tif log := act.opts.FactLog; log != nil {\n\t\tfmt.Fprintf(log, \"%s: package %s has fact %s\\n\",\n\t\t\tact.Package.Fset.Position(act.pass.Files[0].Pos()), act.pass.Pkg.Path(), fact)\n\t}\n}\n\nfunc factType(fact analysis.Fact) reflect.Type {\n\tt := reflect.TypeOf(fact)\n\tif t.Kind() != reflect.Pointer {\n\t\tlog.Fatalf(\"invalid Fact type: got %T, want pointer\", fact)\n\t}\n\treturn t\n}\n\n// AllPackageFacts returns a new slice containing all package\n// facts of the analysis's FactTypes in unspecified order.\n//\n// See documentation at AllPackageFacts field of [analysis.Pass].\nfunc (act *Action) AllPackageFacts() []analysis.PackageFact {\n\tfacts := make([]analysis.PackageFact, 0, len(act.packageFacts))\n\tfor k, fact := range act.packageFacts {\n\t\tfacts = append(facts, analysis.PackageFact{Package: k.pkg, Fact: fact})\n\t}\n\treturn facts\n}\n\n// forEach is a utility function for traversing the action graph. It\n// applies function f to each action in the graph reachable from\n// roots, in depth-first postorder. If any call to f returns an error,\n// the traversal is aborted and ForEach returns the error.\nfunc forEach(roots []*Action, f func(*Action) error) error {\n\tseen := make(map[*Action]bool)\n\tvar visitAll func(actions []*Action) error\n\tvisitAll = func(actions []*Action) error {\n\t\tfor _, act := range actions {\n\t\t\tif !seen[act] {\n\t\t\t\tseen[act] = true\n\t\t\t\tif err := visitAll(act.Deps); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif err := f(act); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn visitAll(roots)\n}\n\nfunc analysisModuleFromPackagesModule(mod *packages.Module) *analysis.Module {\n\tif mod == nil {\n\t\treturn nil\n\t}\n\n\tvar modErr *analysis.ModuleError\n\tif mod.Error != nil {\n\t\tmodErr = &analysis.ModuleError{\n\t\t\tErr: mod.Error.Err,\n\t\t}\n\t}\n\n\treturn &analysis.Module{\n\t\tPath:      mod.Path,\n\t\tVersion:   mod.Version,\n\t\tReplace:   analysisModuleFromPackagesModule(mod.Replace),\n\t\tTime:      mod.Time,\n\t\tMain:      mod.Main,\n\t\tIndirect:  mod.Indirect,\n\t\tDir:       mod.Dir,\n\t\tGoMod:     mod.GoMod,\n\t\tGoVersion: mod.GoVersion,\n\t\tError:     modErr,\n\t}\n}\n"
  },
  {
    "path": "go/analysis/checker/checker_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage checker_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/checker\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TestPassModule checks that an analyzer observes the correct Pass.Module\n// fields (GoMod, Dir, Path, Main, GoVersion) when run on a module.\nfunc TestPassModule(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tconst src = `\n-- go.mod --\nmodule example.com/hello\ngo 1.13\n\n-- hello.go --\npackage hello\n`\n\tdir, err := os.MkdirTemp(\"\", \"\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(dir)\n\n\tfs, err := txtar.FS(txtar.Parse([]byte(src)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.CopyFS(dir, fs); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Capture the Module seen by the analyzer.\n\tvar got *analysis.Module\n\ttestAnalyzer := &analysis.Analyzer{\n\t\tName: \"testmodule\",\n\t\tDoc:  \"Captures Pass.Module for testing.\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tgot = pass.Module\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadAllSyntax | packages.NeedModule,\n\t\tDir:  dir,\n\t}\n\tpkgs, err := packages.Load(cfg, \"example.com/hello\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif _, err := checker.Analyze([]*analysis.Analyzer{testAnalyzer}, pkgs, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif got == nil {\n\t\tt.Fatal(\"Pass.Module is nil\")\n\t}\n\tif got.Path != \"example.com/hello\" {\n\t\tt.Errorf(\"Pass.Module.Path = %q, want %q\", got.Path, \"example.com/hello\")\n\t}\n\tif !got.Main {\n\t\tt.Errorf(\"Pass.Module.Main = false, want true\")\n\t}\n\twantGoMod := filepath.Join(dir, \"go.mod\")\n\tif got.GoMod != wantGoMod {\n\t\tt.Errorf(\"Pass.Module.GoMod = %q, want %q\", got.GoMod, wantGoMod)\n\t}\n\tif got.Dir != dir {\n\t\tt.Errorf(\"Pass.Module.Dir = %q, want %q\", got.Dir, dir)\n\t}\n\tif got.GoVersion != \"1.13\" {\n\t\tt.Errorf(\"Pass.Module.GoVersion = %q, want %q\", got.GoVersion, \"1.13\")\n\t}\n}\n"
  },
  {
    "path": "go/analysis/checker/example_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !wasm\n\n// The example command demonstrates a simple go/packages-based\n// analysis driver program.\npackage checker_test\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/checker\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nconst testdata = `\n-- go.mod --\nmodule example.com\ngo 1.21\n\n-- a/a.go --\npackage a\n\nimport _ \"example.com/b\"\nimport _ \"example.com/c\"\n\nfunc A1()\nfunc A2()\nfunc A3()\n\n-- b/b.go --\npackage b\n\nfunc B1()\nfunc B2()\n\n-- c/c.go --\npackage c\n\nimport _ \"example.com/d\"\n\nfunc C1()\n\n-- d/d.go --\npackage d\n\nfunc D1()\nfunc D2()\nfunc D3()\nfunc D4()\n`\n\nfunc Example() {\n\t// Extract a tree of Go source files.\n\t// (Avoid the standard library as it is always evolving.)\n\tdir, err := os.MkdirTemp(\"\", \"\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfs, err := txtar.FS(txtar.Parse([]byte(testdata)))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.CopyFS(dir, fs); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Load packages: example.com/a + dependencies\n\t//\n\tcfg := &packages.Config{Mode: packages.LoadAllSyntax, Dir: dir}\n\tinitial, err := packages.Load(cfg, \"example.com/a\")\n\tif err != nil {\n\t\tlog.Fatal(err) // failure to enumerate packages\n\t}\n\n\t// There may be parse or type errors among the\n\t// initial packages or their dependencies,\n\t// but the analysis driver can handle faulty inputs,\n\t// as can some analyzers.\n\tpackages.PrintErrors(initial)\n\n\tif len(initial) == 0 {\n\t\tlog.Fatalf(\"no initial packages\")\n\t}\n\n\t// Run analyzers (just one) on example.com packages.\n\tanalyzers := []*analysis.Analyzer{pkgdecls}\n\tgraph, err := checker.Analyze(analyzers, initial, nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Inspect the result of each analysis action,\n\t// including those for all dependencies.\n\t//\n\t// A realistic client would use Result, Err, Diagnostics,\n\t// but for test stability, we just print the action string\n\t// (\"analyzer@package\").\n\tfor act := range graph.All() {\n\t\tfmt.Println(\"printing\", act)\n\t}\n\n\t// Print the package fact for the sole initial package.\n\troot := graph.Roots[0]\n\tfact := new(pkgdeclsFact)\n\tif root.PackageFact(root.Package.Types, fact) {\n\t\tfor k, v := range fact.numdecls {\n\t\t\tfmt.Printf(\"%s:\\t%d decls\\n\", k, v)\n\t\t}\n\t}\n\n\t// Unordered Output:\n\t// printing pkgdecls@example.com/a\n\t// printing pkgdecls@example.com/b\n\t// printing pkgdecls@example.com/c\n\t// printing pkgdecls@example.com/d\n\t// example.com/a:\t3 decls\n\t// example.com/b:\t2 decls\n\t// example.com/c:\t1 decls\n\t// example.com/d:\t4 decls\n}\n\n// pkgdecls is a trivial example analyzer that uses package facts to\n// compute information from the entire dependency graph.\nvar pkgdecls = &analysis.Analyzer{\n\tName:      \"pkgdecls\",\n\tDoc:       \"Computes a package fact mapping each package to its number of declarations.\",\n\tRun:       run,\n\tFactTypes: []analysis.Fact{(*pkgdeclsFact)(nil)},\n}\n\ntype pkgdeclsFact struct{ numdecls map[string]int }\n\nfunc (*pkgdeclsFact) AFact() {}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tnumdecls := map[string]int{\n\t\tpass.Pkg.Path(): pass.Pkg.Scope().Len(),\n\t}\n\n\t// Compute the union across all dependencies.\n\tfor _, imp := range pass.Pkg.Imports() {\n\t\tif depFact := new(pkgdeclsFact); pass.ImportPackageFact(imp, depFact) {\n\t\t\tmaps.Copy(numdecls, depFact.numdecls)\n\t\t}\n\t}\n\n\tpass.ExportPackageFact(&pkgdeclsFact{numdecls})\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/checker/print.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage checker\n\n// This file defines helpers for printing analysis results.\n// They should all be pure functions.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n)\n\n// PrintText emits diagnostics as plain text to w.\n//\n// If contextLines is nonnegative, it also prints the\n// offending line, plus that many lines of context\n// before and after the line.\nfunc (g *Graph) PrintText(w io.Writer, contextLines int) error {\n\treturn writeTextDiagnostics(w, g.Roots, contextLines)\n}\n\nfunc writeTextDiagnostics(w io.Writer, roots []*Action, contextLines int) error {\n\t// De-duplicate diagnostics by position (not token.Pos) to\n\t// avoid double-reporting in source files that belong to\n\t// multiple packages, such as foo and foo.test.\n\t// (We cannot assume that such repeated files were parsed\n\t// only once and use syntax nodes as the key.)\n\ttype key struct {\n\t\tpos token.Position\n\t\tend token.Position\n\t\t*analysis.Analyzer\n\t\tmessage string\n\t}\n\tseen := make(map[key]bool)\n\n\t// TODO(adonovan): opt: plumb errors back from PrintPlain and avoid buffer.\n\tbuf := new(bytes.Buffer)\n\tforEach(roots, func(act *Action) error {\n\t\tif act.Err != nil {\n\t\t\tfmt.Fprintf(w, \"%s: %v\\n\", act.Analyzer.Name, act.Err)\n\t\t} else if act.IsRoot {\n\t\t\tfor _, diag := range act.Diagnostics {\n\t\t\t\t// We don't display Analyzer.Name/diag.Category\n\t\t\t\t// as most users don't care.\n\n\t\t\t\tposn := act.Package.Fset.Position(diag.Pos)\n\t\t\t\tend := act.Package.Fset.Position(diag.End)\n\t\t\t\tk := key{posn, end, act.Analyzer, diag.Message}\n\t\t\t\tif seen[k] {\n\t\t\t\t\tcontinue // duplicate\n\t\t\t\t}\n\t\t\t\tseen[k] = true\n\n\t\t\t\tdriverutil.PrintPlain(buf, act.Package.Fset, contextLines, diag)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\t_, err := w.Write(buf.Bytes())\n\treturn err\n}\n\n// PrintJSON emits diagnostics in JSON form to w.\n// Diagnostics are shown only for the root nodes,\n// but errors (if any) are shown for all dependencies.\nfunc (g *Graph) PrintJSON(w io.Writer) error {\n\treturn writeJSONDiagnostics(w, g.Roots)\n}\n\nfunc writeJSONDiagnostics(w io.Writer, roots []*Action) error {\n\ttree := make(driverutil.JSONTree)\n\tforEach(roots, func(act *Action) error {\n\t\tvar diags []analysis.Diagnostic\n\t\tif act.IsRoot {\n\t\t\tdiags = act.Diagnostics\n\t\t}\n\t\ttree.Add(act.Package.Fset, act.Package.ID, act.Analyzer.Name, diags, act.Err)\n\t\treturn nil\n\t})\n\treturn tree.Print(w)\n}\n"
  },
  {
    "path": "go/analysis/diagnostic.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysis\n\nimport \"go/token\"\n\n// A Diagnostic is a message associated with a source location or range.\n//\n// An Analyzer may return a variety of diagnostics; the optional Category,\n// which should be a constant, may be used to classify them.\n// It is primarily intended to make it easy to look up documentation.\n//\n// All Pos values are interpreted relative to Pass.Fset. If End is\n// provided, the diagnostic is specified to apply to the range between\n// Pos and End.\ntype Diagnostic struct {\n\tPos      token.Pos\n\tEnd      token.Pos // optional\n\tCategory string    // optional\n\tMessage  string\n\n\t// URL is the optional location of a web page that provides\n\t// additional documentation for this diagnostic.\n\t//\n\t// If URL is empty but a Category is specified, then the\n\t// Analysis driver should treat the URL as \"#\"+Category.\n\t//\n\t// The URL may be relative. If so, the base URL is that of the\n\t// Analyzer that produced the diagnostic;\n\t// see https://pkg.go.dev/net/url#URL.ResolveReference.\n\tURL string\n\n\t// SuggestedFixes is an optional list of fixes to address the\n\t// problem described by the diagnostic. Each one represents an\n\t// alternative strategy, and should have a distinct and\n\t// descriptive message; at most one may be applied.\n\t//\n\t// Fixes for different diagnostics should be treated as\n\t// independent changes to the same baseline file state,\n\t// analogous to a set of git commits all with the same parent.\n\t// Combining fixes requires resolving any conflicts that\n\t// arise, analogous to a git merge.\n\t// Any conflicts that remain may be dealt with, depending on\n\t// the tool, by discarding fixes, consulting the user, or\n\t// aborting the operation.\n\tSuggestedFixes []SuggestedFix\n\n\t// Related contains optional secondary positions and messages\n\t// related to the primary diagnostic.\n\tRelated []RelatedInformation\n}\n\n// RelatedInformation contains information related to a diagnostic.\n// For example, a diagnostic that flags duplicated declarations of a\n// variable may include one RelatedInformation per existing\n// declaration.\ntype RelatedInformation struct {\n\tPos     token.Pos\n\tEnd     token.Pos // optional\n\tMessage string\n}\n\n// A SuggestedFix is a code change associated with a Diagnostic that a\n// user can choose to apply to their code. Usually the SuggestedFix is\n// meant to fix the issue flagged by the diagnostic.\n//\n// The TextEdits must not overlap, nor contain edits for other\n// packages. Edits need not be totally ordered, but the order\n// determines how insertions at the same point will be applied.\ntype SuggestedFix struct {\n\t// A verb phrase describing the fix, to be shown to\n\t// a user trying to decide whether to accept it.\n\t//\n\t// Example: \"Remove the surplus argument\"\n\tMessage   string\n\tTextEdits []TextEdit\n}\n\n// A TextEdit represents the replacement of the code between Pos and End with the new text.\n// Each TextEdit should apply to a single file. End should not be earlier in the file than Pos.\ntype TextEdit struct {\n\t// For a pure insertion, End can either be set to Pos or token.NoPos.\n\tPos     token.Pos\n\tEnd     token.Pos\n\tNewText []byte\n}\n"
  },
  {
    "path": "go/analysis/doc/suggested_fixes.md",
    "content": "# Suggested Fixes in the Analysis Framework\n\n## The Purpose of Suggested Fixes\n\nThe analysis framework is planned to add a facility to output\nsuggested fixes. Suggested fixes in the analysis framework\nare meant to address two common use cases. The first is the\nnatural use case of allowing the user to quickly fix errors or issues\npointed out by analyzers through their editor or analysis tool.\nAn editor, when showing a diagnostic for an issue, can propose\ncode to fix that issue. Users can accept the proposal and have\nthe editor apply the fix for them. The second case is to allow\nfor defining refactorings. An analyzer meant to perform a\nrefactoring can produce suggested fixes equivalent to the diff\nof the refactoring. Then, an analysis driver meant to apply\nrefactorings can automatically apply all the diffs that\nare produced by the analysis as suggested fixes.\n\n## Proposed Suggested Fix API\n\nSuggested fixes will be defined using the following structs:\n\n```go\n// A SuggestedFix is a code change associated with a Diagnostic that a user can choose\n// to apply to their code. Usually the SuggestedFix is meant to fix the issue flagged\n// by the diagnostic.\ntype SuggestedFix struct {\n\t// A description for this suggested fix to be shown to a user deciding\n\t// whether to accept it.\n\tMessage   string\n\tTextEdits []TextEdit\n}\n\n// A TextEdit represents the replacement of the code between Pos and End with the new text.\ntype TextEdit struct {\n\t// For a pure insertion, End can either be set to Pos or token.NoPos.\n\tPos     token.Pos\n\tEnd     token.Pos\n\tNewText []byte\n}\n```\n\nA suggested fix needs a message field so it can specify what it will do.\nSome analyses may not have clear cut fixes, and a suggested fix may need\nto provide additional information to help users specify whether they\nshould be added.\n\nSuggested fixes are allowed to make multiple\nedits in a file, because some logical changes may affect otherwise\nunrelated parts of the AST.\n\nA TextEdit specifies a Pos and End: these will usually be the Pos\nand End of an AST node that will be replaced.\n\nFinally, the replacements themselves are represented as []bytes.\n\n\nSuggested fixes themselves will be added as a field in the\nDiagnostic struct:\n\n```go\n\ntype Diagnostic struct {\n\t...\n\tSuggestedFixes []SuggestedFix  // this is an optional field\n}\n\n```\n\n### Requirements for SuggestedFixes\n\nSuggestedFixes will be required to conform to several requirements:\n\n* TextEdits for a SuggestedFix should not overlap.\n* TextEdits for SuggestedFixes should not contain edits for other packages.\n* Each TextEdit should apply to a single file.\n\nThese requirements guarantee that suggested fixes can be cleanly applied.\nBecause a driver may only analyze, or be able to modify, the current package,\nwe restrict edits to the current package. In general this restriction should\nnot be a big problem for users because other packages might not belong to the\nsame module and so will not be safe to modify in a single change.\n\nOn the other hand, analyzers will not be required to produce gofmt-compliant\ncode. Analysis drivers will be expected to apply gofmt to the results of\na SuggestedFix application.\n\n## SuggestedFix integration points\n\n### ```checker -fix```\n\nSinglechecker and multichecker have the ```-fix``` flag, which will automatically\napply all fixes suggested by their analysis or analyses. This is intended to\nbe used primarily by refactoring tools, because in general, like diagnostics,\nsuggested fixes will need to be examined by a human who can decide whether\nthey are relevant.\n\n### gopls\n\nSuggested fixes have been integrated into ```gopls```, and editors can choose\nto display the suggested fixes to the user as they type, so that they can be\naccepted to fix diagnostics immediately.\n\n### Code Review Tools (Future Work)\n\nSuggested fixes can be integrated into programs that are integrated with\ncode review systems to suggest fixes that users can apply from their code review tools.\n\n## Alternatives\n\n### Performing transformations directly on the AST\n\nEven though it may be more convenient\nfor authors of refactorings to perform transformations directly on\nthe AST, allowing mutations on the AST would mean that a copy of the AST\nwould need to be made every time a transformation was produced, to avoid\nhaving transformations interfere with each other.\n\nThis is primarily an issue with the current design of the Go AST and\nit's possible that a new future version of the AST might make this a more\nviable option.\n\n### Supplying AST nodes directly\n\nAnother possibility would be for SuggestedFixes to supply the replacement\nASTs directly. There is one primary limitation to this: that because\ncomments to ASTs specify their location using token.Pos values, it's very\ndifficult to place any comments in the right place.\n\nIn general, it's also more difficult to generate the AST structures for\nsome code than to generate the text for that code. So we prefer to allow\nthe flexibility to do the latter.\n\nBecause users can call ```format.Node``` to produce the text for any\nAST node, users will always be able to produce a SuggestedFix from AST\nnodes. In future, we may choose to add a convenience method that does this for users.\n"
  },
  {
    "path": "go/analysis/doc.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage analysis defines the interface between a modular static\nanalysis and an analysis driver program.\n\n# Background\n\nA static analysis is a function that inspects a package of Go code and\nreports a set of diagnostics (typically mistakes in the code), and\nperhaps produces other results as well, such as suggested refactorings\nor other facts. An analysis that reports mistakes is informally called a\n\"checker\". For example, the printf checker reports mistakes in\nfmt.Printf format strings.\n\nA \"modular\" analysis is one that inspects one package at a time but can\nsave information from a lower-level package and use it when inspecting a\nhigher-level package, analogous to separate compilation in a toolchain.\nThe printf checker is modular: when it discovers that a function such as\nlog.Fatalf delegates to fmt.Printf, it records this fact, and checks\ncalls to that function too, including calls made from another package.\n\nBy implementing a common interface, checkers from a variety of sources\ncan be easily selected, incorporated, and reused in a wide range of\ndriver programs including command-line tools (such as vet), text editors and\nIDEs, build and test systems (such as go build, Bazel, or Buck), test\nframeworks, code review tools, code-base indexers (such as SourceGraph),\ndocumentation viewers (such as godoc), batch pipelines for large code\nbases, and so on.\n\n# Analyzer\n\nThe primary type in the API is [Analyzer]. An Analyzer statically\ndescribes an analysis function: its name, documentation, flags,\nrelationship to other analyzers, and of course, its logic.\n\nTo define an analysis, a user declares a (logically constant) variable\nof type Analyzer. Here is a typical example from one of the analyzers in\nthe go/analysis/passes/ subdirectory:\n\n\tpackage unusedresult\n\n\tvar Analyzer = &analysis.Analyzer{\n\t\tName: \"unusedresult\",\n\t\tDoc:  \"check for unused results of calls to some functions\",\n\t\tRun:  run,\n\t\t...\n\t}\n\n\tfunc run(pass *analysis.Pass) (interface{}, error) {\n\t\t...\n\t}\n\nAn analysis driver is a program such as vet that runs a set of\nanalyses and prints the diagnostics that they report.\nThe driver program must import the list of Analyzers it needs.\nTypically each Analyzer resides in a separate package.\nTo add a new Analyzer to an existing driver, add another item to the list:\n\n\timport ( \"unusedresult\"; \"nilness\"; \"printf\" )\n\n\tvar analyses = []*analysis.Analyzer{\n\t\tunusedresult.Analyzer,\n\t\tnilness.Analyzer,\n\t\tprintf.Analyzer,\n\t}\n\nA driver may use the name, flags, and documentation to provide on-line\nhelp that describes the analyses it performs.\nThe doc comment contains a brief one-line summary,\noptionally followed by paragraphs of explanation.\n\nThe [Analyzer] type has more fields besides those shown above:\n\n\ttype Analyzer struct {\n\t\tName             string\n\t\tDoc              string\n\t\tFlags            flag.FlagSet\n\t\tRun              func(*Pass) (interface{}, error)\n\t\tRunDespiteErrors bool\n\t\tResultType       reflect.Type\n\t\tRequires         []*Analyzer\n\t\tFactTypes        []Fact\n\t}\n\nThe Flags field declares a set of named (global) flag variables that\ncontrol analysis behavior. Unlike vet, analysis flags are not declared\ndirectly in the command line FlagSet; it is up to the driver to set the\nflag variables. A driver for a single analysis, a, might expose its flag\nf directly on the command line as -f, whereas a driver for multiple\nanalyses might prefix the flag name by the analysis name (-a.f) to avoid\nambiguity. An IDE might expose the flags through a graphical interface,\nand a batch pipeline might configure them from a config file.\nSee the \"findcall\" analyzer for an example of flags in action.\n\nThe RunDespiteErrors flag indicates whether the analysis is equipped to\nhandle ill-typed code. If not, the driver will skip the analysis if\nthere were parse or type errors.\nThe optional ResultType field specifies the type of the result value\ncomputed by this analysis and made available to other analyses.\nThe Requires field specifies a list of analyses upon which\nthis one depends and whose results it may access, and it constrains the\norder in which a driver may run analyses.\nThe FactTypes field is discussed in the section on Modularity.\nThe analysis package provides a Validate function to perform basic\nsanity checks on an Analyzer, such as that its Requires graph is\nacyclic, its fact and result types are unique, and so on.\n\nFinally, the Run field contains a function to be called by the driver to\nexecute the analysis on a single package. The driver passes it an\ninstance of the Pass type.\n\n# Pass\n\nA [Pass] describes a single unit of work: the application of a particular\nAnalyzer to a particular package of Go code.\nThe Pass provides information to the Analyzer's Run function about the\npackage being analyzed, and provides operations to the Run function for\nreporting diagnostics and other information back to the driver.\n\n\ttype Pass struct {\n\t\tFset         *token.FileSet\n\t\tFiles        []*ast.File\n\t\tOtherFiles   []string\n\t\tIgnoredFiles []string\n\t\tPkg          *types.Package\n\t\tTypesInfo    *types.Info\n\t\tResultOf     map[*Analyzer]interface{}\n\t\tReport       func(Diagnostic)\n\t\t...\n\t}\n\nThe Fset, Files, Pkg, and TypesInfo fields provide the syntax trees,\ntype information, and source positions for a single package of Go code.\n\nThe OtherFiles field provides the names of non-Go\nfiles such as assembly that are part of this package.\nSimilarly, the IgnoredFiles field provides the names of Go and non-Go\nsource files that are not part of this package with the current build\nconfiguration but may be part of other build configurations.\nThe contents of these files may be read using Pass.ReadFile;\nsee the \"asmdecl\" or \"buildtags\" analyzers for examples of loading\nnon-Go files and reporting diagnostics against them.\n\nThe ResultOf field provides the results computed by the analyzers\nrequired by this one, as expressed in its Analyzer.Requires field. The\ndriver runs the required analyzers first and makes their results\navailable in this map. Each Analyzer must return a value of the type\ndescribed in its Analyzer.ResultType field.\nFor example, the \"ctrlflow\" analyzer returns a *ctrlflow.CFGs, which\nprovides a control-flow graph for each function in the package (see\ngolang.org/x/tools/go/cfg); the \"inspect\" analyzer returns a value that\nenables other Analyzers to traverse the syntax trees of the package more\nefficiently; and the \"buildssa\" analyzer constructs an SSA-form\nintermediate representation.\nEach of these Analyzers extends the capabilities of later Analyzers\nwithout adding a dependency to the core API, so an analysis tool pays\nonly for the extensions it needs.\n\nThe Report function emits a diagnostic, a message associated with a\nsource position. For most analyses, diagnostics are their primary\nresult.\nFor convenience, Pass provides a helper method, Reportf, to report a new\ndiagnostic by formatting a string.\nDiagnostic is defined as:\n\n\ttype Diagnostic struct {\n\t\tPos      token.Pos\n\t\tCategory string // optional\n\t\tMessage  string\n\t}\n\nThe optional Category field is a short identifier that classifies the\nkind of message when an analysis produces several kinds of diagnostic.\n\nThe [Diagnostic] struct does not have a field to indicate its severity\nbecause opinions about the relative importance of Analyzers and their\ndiagnostics vary widely among users. The design of this framework does\nnot hold each Analyzer responsible for identifying the severity of its\ndiagnostics. Instead, we expect that drivers will allow the user to\ncustomize the filtering and prioritization of diagnostics based on the\nproducing Analyzer and optional Category, according to the user's\npreferences.\n\nMost Analyzers inspect typed Go syntax trees, but a few, such as asmdecl\nand buildtag, inspect the raw text of Go source files or even non-Go\nfiles such as assembly. To report a diagnostic against a line of a\nraw text file, use the following sequence:\n\n\tcontent, err := pass.ReadFile(filename)\n\tif err != nil { ... }\n\ttf := fset.AddFile(filename, -1, len(content))\n\ttf.SetLinesForContent(content)\n\t...\n\tpass.Reportf(tf.LineStart(line), \"oops\")\n\n# Modular analysis with Facts\n\nTo improve efficiency and scalability, large programs are routinely\nbuilt using separate compilation: units of the program are compiled\nseparately, and recompiled only when one of their dependencies changes;\nindependent modules may be compiled in parallel. The same technique may\nbe applied to static analyses, for the same benefits. Such analyses are\ndescribed as \"modular\".\n\nA compiler’s type checker is an example of a modular static analysis.\nMany other checkers we would like to apply to Go programs can be\nunderstood as alternative or non-standard type systems. For example,\nvet's printf checker infers whether a function has the \"printf wrapper\"\ntype, and it applies stricter checks to calls of such functions. In\naddition, it records which functions are printf wrappers for use by\nlater analysis passes to identify other printf wrappers by induction.\nA result such as “f is a printf wrapper” that is not interesting by\nitself but serves as a stepping stone to an interesting result (such as\na diagnostic) is called a [Fact].\n\nThe analysis API allows an analysis to define new types of facts, to\nassociate facts of these types with objects (named entities) declared\nwithin the current package, or with the package as a whole, and to query\nfor an existing fact of a given type associated with an object or\npackage.\n\nAn Analyzer that uses facts must declare their types:\n\n\tvar Analyzer = &analysis.Analyzer{\n\t\tName:      \"printf\",\n\t\tFactTypes: []analysis.Fact{new(isWrapper)},\n\t\t...\n\t}\n\n\ttype isWrapper struct{} // => *types.Func f “is a printf wrapper”\n\nThe driver program ensures that facts for a pass’s dependencies are\ngenerated before analyzing the package and is responsible for propagating\nfacts from one package to another, possibly across address spaces.\nConsequently, Facts must be serializable. The API requires that drivers\nuse the gob encoding, an efficient, robust, self-describing binary\nprotocol. A fact type may implement the GobEncoder/GobDecoder interfaces\nif the default encoding is unsuitable. Facts should be stateless.\nBecause serialized facts may appear within build outputs, the gob encoding\nof a fact must be deterministic, to avoid spurious cache misses in\nbuild systems that use content-addressable caches.\nThe driver makes a single call to the gob encoder for all facts\nexported by a given analysis pass, so that the topology of\nshared data structures referenced by multiple facts is preserved.\n\nThe Pass type has functions to import and export facts,\nassociated either with an object or with a package:\n\n\ttype Pass struct {\n\t\t...\n\t\tExportObjectFact func(types.Object, Fact)\n\t\tImportObjectFact func(types.Object, Fact) bool\n\n\t\tExportPackageFact func(fact Fact)\n\t\tImportPackageFact func(*types.Package, Fact) bool\n\t}\n\nAn Analyzer may only export facts associated with the current package or\nits objects, though it may import facts from any package or object that\nis an import dependency of the current package.\n\nConceptually, ExportObjectFact(obj, fact) inserts fact into a hidden map keyed by\nthe pair (obj, TypeOf(fact)), and the ImportObjectFact function\nretrieves the entry from this map and copies its value into the variable\npointed to by fact. This scheme assumes that the concrete type of fact\nis a pointer; this assumption is checked by the Validate function.\nSee the \"printf\" analyzer for an example of object facts in action.\n\nSome driver implementations (such as those based on Bazel and Blaze) do\nnot currently apply analyzers to packages of the standard library.\nTherefore, for best results, analyzer authors should not rely on\nanalysis facts being available for standard packages.\nFor example, although the printf checker is capable of deducing during\nanalysis of the log package that log.Printf is a printf wrapper,\nthis fact is built in to the analyzer so that it correctly checks\ncalls to log.Printf even when run in a driver that does not apply\nit to standard packages. We would like to remove this limitation in future.\n\n# Testing an Analyzer\n\nThe analysistest subpackage provides utilities for testing an Analyzer.\nIn a few lines of code, it is possible to run an analyzer on a package\nof testdata files and check that it reported all the expected\ndiagnostics and facts (and no more). Expectations are expressed using\n\"// want ...\" comments in the input code.\n\n# Standalone commands\n\nAnalyzers are provided in the form of packages that a driver program is\nexpected to import. The vet command imports a set of several analyzers,\nbut users may wish to define their own analysis commands that perform\nadditional checks. To simplify the task of creating an analysis command,\neither for a single analyzer or for a whole suite, we provide the\nsinglechecker and multichecker subpackages.\n\nThe singlechecker package provides the main function for a command that\nruns one analyzer. By convention, each analyzer such as\ngo/analysis/passes/findcall should be accompanied by a singlechecker-based\ncommand such as go/analysis/passes/findcall/cmd/findcall, defined in its\nentirety as:\n\n\tpackage main\n\n\timport (\n\t\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n\t\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t)\n\n\tfunc main() { singlechecker.Main(findcall.Analyzer) }\n\nA tool that provides multiple analyzers can use multichecker in a\nsimilar way, giving it the list of Analyzers.\n*/\npackage analysis\n"
  },
  {
    "path": "go/analysis/internal/analysisflags/flags.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package analysisflags defines helpers for processing flags (-help,\n// -json, -fix, -diff, etc) common to unitchecker and\n// {single,multi}checker. It is not intended for broader use.\npackage analysisflags\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// flags common to all {single,multi,unit}checkers.\nvar (\n\tJSON    = false // -json\n\tContext = -1    // -c=N: if N>0, display offending line plus N lines of context\n\tFix     bool    // -fix\n\tDiff    bool    // -diff\n)\n\n// Parse creates a flag for each of the analyzer's flags,\n// including (in multi mode) a flag named after the analyzer,\n// parses the flags, then filters and returns the list of\n// analyzers enabled by flags.\n//\n// The result is intended to be passed to unitchecker.Run or checker.Run.\n// Use in unitchecker.Run will gob.Register all fact types for the returned\n// graph of analyzers but of course not the ones only reachable from\n// dropped analyzers. To avoid inconsistency about which gob types are\n// registered from run to run, Parse itself gob.Registers all the facts\n// only reachable from dropped analyzers.\n// This is not a particularly elegant API, but this is an internal package.\nfunc Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {\n\t// Connect each analysis flag to the command line as -analysis.flag.\n\tenabled := make(map[*analysis.Analyzer]*triState)\n\tfor _, a := range analyzers {\n\t\tvar prefix string\n\n\t\t// Add -NAME flag to enable it.\n\t\tif multi {\n\t\t\tprefix = a.Name + \".\"\n\n\t\t\tenable := new(triState)\n\t\t\tenableUsage := fmt.Sprintf(\"enable %q analysis\", a.Name)\n\t\t\tflag.Var(enable, a.Name, enableUsage)\n\t\t\tenabled[a] = enable\n\t\t}\n\n\t\ta.Flags.VisitAll(func(f *flag.Flag) {\n\t\t\tif !multi && flag.Lookup(f.Name) != nil {\n\t\t\t\tlog.Printf(\"%s flag -%s would conflict with driver; skipping\", a.Name, f.Name)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tname := prefix + f.Name\n\t\t\tflag.Var(f.Value, name, f.Usage)\n\t\t})\n\t}\n\n\t// standard flags: -flags, -V.\n\tprintflags := flag.Bool(\"flags\", false, \"print analyzer flags in JSON\")\n\taddVersionFlag()\n\n\t// flags common to all checkers\n\tflag.BoolVar(&JSON, \"json\", JSON, \"emit JSON output\")\n\tflag.IntVar(&Context, \"c\", Context, `display offending line with this many lines of context`)\n\tflag.BoolVar(&Fix, \"fix\", false, \"apply all suggested fixes\")\n\tflag.BoolVar(&Diff, \"diff\", false, \"with -fix, don't update the files, but print a unified diff\")\n\n\t// Add shims for legacy vet flags to enable existing\n\t// scripts that run vet to continue to work.\n\t_ = flag.Bool(\"source\", false, \"no effect (deprecated)\")\n\t_ = flag.Bool(\"v\", false, \"no effect (deprecated)\")\n\t_ = flag.Bool(\"all\", false, \"no effect (deprecated)\")\n\t_ = flag.String(\"tags\", \"\", \"no effect (deprecated)\")\n\tfor old, new := range vetLegacyFlags {\n\t\tnewFlag := flag.Lookup(new)\n\t\tif newFlag != nil && flag.Lookup(old) == nil {\n\t\t\tflag.Var(newFlag.Value, old, \"deprecated alias for -\"+new)\n\t\t}\n\t}\n\n\tflag.Parse() // (ExitOnError)\n\n\t// -flags: print flags so that go vet knows which ones are legitimate.\n\tif *printflags {\n\t\tprintFlags()\n\t\tos.Exit(0)\n\t}\n\n\teverything := expand(analyzers)\n\n\t// If any -NAME flag is true,  run only those analyzers. Otherwise,\n\t// if any -NAME flag is false, run all but those analyzers.\n\tif multi {\n\t\tvar hasTrue, hasFalse bool\n\t\tfor _, ts := range enabled {\n\t\t\tswitch *ts {\n\t\t\tcase setTrue:\n\t\t\t\thasTrue = true\n\t\t\tcase setFalse:\n\t\t\t\thasFalse = true\n\t\t\t}\n\t\t}\n\n\t\tvar keep []*analysis.Analyzer\n\t\tif hasTrue {\n\t\t\tfor _, a := range analyzers {\n\t\t\t\tif *enabled[a] == setTrue {\n\t\t\t\t\tkeep = append(keep, a)\n\t\t\t\t}\n\t\t\t}\n\t\t\tanalyzers = keep\n\t\t} else if hasFalse {\n\t\t\tfor _, a := range analyzers {\n\t\t\t\tif *enabled[a] != setFalse {\n\t\t\t\t\tkeep = append(keep, a)\n\t\t\t\t}\n\t\t\t}\n\t\t\tanalyzers = keep\n\t\t}\n\t}\n\n\t// Register fact types of skipped analyzers\n\t// in case we encounter them in imported files.\n\tkept := expand(analyzers)\n\tfor a := range everything {\n\t\tif !kept[a] {\n\t\t\tfor _, f := range a.FactTypes {\n\t\t\t\tgob.Register(f)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn analyzers\n}\n\nfunc expand(analyzers []*analysis.Analyzer) map[*analysis.Analyzer]bool {\n\tseen := make(map[*analysis.Analyzer]bool)\n\tvar visitAll func([]*analysis.Analyzer)\n\tvisitAll = func(analyzers []*analysis.Analyzer) {\n\t\tfor _, a := range analyzers {\n\t\t\tif !seen[a] {\n\t\t\t\tseen[a] = true\n\t\t\t\tvisitAll(a.Requires)\n\t\t\t}\n\t\t}\n\t}\n\tvisitAll(analyzers)\n\treturn seen\n}\n\nfunc printFlags() {\n\ttype jsonFlag struct {\n\t\tName  string\n\t\tBool  bool\n\t\tUsage string\n\t}\n\tvar flags []jsonFlag = nil\n\tflag.VisitAll(func(f *flag.Flag) {\n\t\t// Don't report {single,multi}checker debugging\n\t\t// flags or fix as these have no effect on unitchecker\n\t\t// (as invoked by 'go vet').\n\t\tswitch f.Name {\n\t\tcase \"debug\", \"cpuprofile\", \"memprofile\", \"trace\", \"fix\":\n\t\t\treturn\n\t\t}\n\n\t\tb, ok := f.Value.(interface{ IsBoolFlag() bool })\n\t\tisBool := ok && b.IsBoolFlag()\n\t\tflags = append(flags, jsonFlag{f.Name, isBool, f.Usage})\n\t})\n\tdata, err := json.MarshalIndent(flags, \"\", \"\\t\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tos.Stdout.Write(data)\n}\n\n// addVersionFlag registers a -V flag that, if set,\n// prints the executable version and exits 0.\n//\n// If the -V flag already exists — for example, because it was already\n// registered by a call to cmd/internal/objabi.AddVersionFlag — then\n// addVersionFlag does nothing.\nfunc addVersionFlag() {\n\tif flag.Lookup(\"V\") == nil {\n\t\tflag.Var(versionFlag{}, \"V\", \"print version and exit\")\n\t}\n}\n\n// versionFlag minimally complies with the -V protocol required by \"go vet\".\ntype versionFlag struct{}\n\nfunc (versionFlag) IsBoolFlag() bool { return true }\nfunc (versionFlag) Get() any         { return nil }\nfunc (versionFlag) String() string   { return \"\" }\nfunc (versionFlag) Set(s string) error {\n\tif s != \"full\" {\n\t\tlog.Fatalf(\"unsupported flag value: -V=%s (use -V=full)\", s)\n\t}\n\n\t// This replicates the minimal subset of\n\t// cmd/internal/objabi.AddVersionFlag, which is private to the\n\t// go tool yet forms part of our command-line interface.\n\t// TODO(adonovan): clarify the contract.\n\n\t// Print the tool version so the build system can track changes.\n\t// Formats:\n\t//   $progname version devel ... buildID=...\n\t//   $progname version go1.9.1\n\tprogname, err := os.Executable()\n\tif err != nil {\n\t\treturn err\n\t}\n\tf, err := os.Open(progname)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\th := sha256.New()\n\tif _, err := io.Copy(h, f); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tf.Close()\n\tfmt.Printf(\"%s version devel comments-go-here buildID=%02x\\n\",\n\t\tprogname, string(h.Sum(nil)))\n\tos.Exit(0)\n\treturn nil\n}\n\n// A triState is a boolean that knows whether\n// it has been set to either true or false.\n// It is used to identify whether a flag appears;\n// the standard boolean flag cannot\n// distinguish missing from unset.\n// It also satisfies flag.Value.\ntype triState int\n\nconst (\n\tunset triState = iota\n\tsetTrue\n\tsetFalse\n)\n\n// triState implements flag.Value, flag.Getter, and flag.boolFlag.\n// They work like boolean flags: we can say vet -printf as well as vet -printf=true\nfunc (ts *triState) Get() any {\n\treturn *ts == setTrue\n}\n\nfunc (ts *triState) Set(value string) error {\n\tb, err := strconv.ParseBool(value)\n\tif err != nil {\n\t\t// This error message looks poor but package \"flag\" adds\n\t\t// \"invalid boolean value %q for -NAME: %s\"\n\t\treturn fmt.Errorf(\"want true or false\")\n\t}\n\tif b {\n\t\t*ts = setTrue\n\t} else {\n\t\t*ts = setFalse\n\t}\n\treturn nil\n}\n\nfunc (ts *triState) String() string {\n\tswitch *ts {\n\tcase unset:\n\t\treturn \"true\"\n\tcase setTrue:\n\t\treturn \"true\"\n\tcase setFalse:\n\t\treturn \"false\"\n\t}\n\tpanic(\"not reached\")\n}\n\nfunc (ts triState) IsBoolFlag() bool {\n\treturn true\n}\n\n// Legacy flag support\n\n// vetLegacyFlags maps flags used by legacy vet to their corresponding\n// new names. The old names will continue to work.\nvar vetLegacyFlags = map[string]string{\n\t// Analyzer name changes\n\t\"bool\":       \"bools\",\n\t\"buildtags\":  \"buildtag\",\n\t\"methods\":    \"stdmethods\",\n\t\"rangeloops\": \"loopclosure\",\n\n\t// Analyzer flags\n\t\"compositewhitelist\":  \"composites.whitelist\",\n\t\"printfuncs\":          \"printf.funcs\",\n\t\"shadowstrict\":        \"shadow.strict\",\n\t\"unusedfuncs\":         \"unusedresult.funcs\",\n\t\"unusedstringmethods\": \"unusedresult.stringmethods\",\n}\n"
  },
  {
    "path": "go/analysis/internal/analysisflags/flags_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysisflags_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n)\n\nfunc main() {\n\tfmt.Println(analysisflags.Parse([]*analysis.Analyzer{\n\t\t{Name: \"a1\", Doc: \"a1\"},\n\t\t{Name: \"a2\", Doc: \"a2\"},\n\t\t{Name: \"a3\", Doc: \"a3\"},\n\t}, true))\n\tos.Exit(0)\n}\n\n// This test fork/execs the main function above.\nfunc TestExec(t *testing.T) {\n\tif runtime.GOOS != \"linux\" {\n\t\tt.Skipf(\"skipping fork/exec test on this platform\")\n\t}\n\n\tprogname := os.Args[0]\n\n\tif os.Getenv(\"ANALYSISFLAGS_CHILD\") == \"1\" {\n\t\t// child process\n\t\tos.Args = strings.Fields(progname + \" \" + os.Getenv(\"FLAGS\"))\n\t\tmain()\n\t\tpanic(\"unreachable\")\n\t}\n\n\tfor _, test := range []struct {\n\t\tflags string\n\t\twant  string // output should contain want\n\t}{\n\t\t{\"\", \"[a1 a2 a3]\"},\n\t\t{\"-a1=0\", \"[a2 a3]\"},\n\t\t{\"-a1=1\", \"[a1]\"},\n\t\t{\"-a1\", \"[a1]\"},\n\t\t{\"-a1=1 -a3=1\", \"[a1 a3]\"},\n\t\t{\"-a1=1 -a3=0\", \"[a1]\"},\n\t\t{\"-V=full\", \"analysisflags.test version devel\"},\n\t} {\n\t\tcmd := exec.Command(progname, \"-test.run=TestExec\")\n\t\tcmd.Env = append(os.Environ(), \"ANALYSISFLAGS_CHILD=1\", \"FLAGS=\"+test.flags)\n\n\t\toutput, err := cmd.CombinedOutput()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"exec failed: %v; output=<<%s>>\", err, output)\n\t\t}\n\n\t\tgot := strings.TrimSpace(string(output))\n\t\tif !strings.Contains(got, test.want) {\n\t\t\tt.Errorf(\"got %q, does not contain %q\", got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/internal/analysisflags/help.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysisflags\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\nconst help = `PROGNAME is a tool for static analysis of Go programs.\n\nPROGNAME examines Go source code and reports diagnostics for\nsuspicious constructs or opportunities for improvement.\nDiagnostics may include suggested fixes.\n\nAn example of a suspicious construct is a Printf call whose arguments\ndo not align with the format string. Analyzers may use heuristics that\ndo not guarantee all reports are genuine problems, but can find\nmistakes not caught by the compiler.\n\nAn example of an opportunity for improvement is a loop over\nstrings.Split(doc, \"\\n\"), which may be replaced by a loop over the\nstrings.SplitSeq iterator, avoiding an array allocation.\nDiagnostics in such cases may report non-problems,\nbut should carry fixes that may be safely applied.\n\nFor analyzers of the first kind, use \"go vet -vettool=PROGRAM\"\nto run the tool and report diagnostics.\n\nFor analyzers of the second kind, use \"go fix -fixtool=PROGRAM\"\nto run the tool and apply the fixes it suggests.\n`\n\n// Help implements the help subcommand for a multichecker or unitchecker\n// style command. The optional args specify the analyzers to describe.\n// Help calls log.Fatal if no such analyzer exists.\nfunc Help(progname string, analyzers []*analysis.Analyzer, args []string) {\n\t// No args: show summary of all analyzers.\n\tif len(args) == 0 {\n\t\tfmt.Println(strings.ReplaceAll(help, \"PROGNAME\", progname))\n\t\tfmt.Println(\"Registered analyzers:\")\n\t\tfmt.Println()\n\t\tsort.Slice(analyzers, func(i, j int) bool {\n\t\t\treturn analyzers[i].Name < analyzers[j].Name\n\t\t})\n\t\tfor _, a := range analyzers {\n\t\t\ttitle := strings.Split(a.Doc, \"\\n\\n\")[0]\n\t\t\tfmt.Printf(\"    %-12s %s\\n\", a.Name, title)\n\t\t}\n\t\tfmt.Println(\"\\nBy default all analyzers are run.\")\n\t\tfmt.Println(\"To select specific analyzers, use the -NAME flag for each one,\")\n\t\tfmt.Println(\" or -NAME=false to run all analyzers not explicitly disabled.\")\n\n\t\t// Show only the core command-line flags.\n\t\tfmt.Println(\"\\nCore flags:\")\n\t\tfmt.Println()\n\t\tfs := flag.NewFlagSet(\"\", flag.ExitOnError)\n\t\tflag.VisitAll(func(f *flag.Flag) {\n\t\t\tif !strings.Contains(f.Name, \".\") {\n\t\t\t\tfs.Var(f.Value, f.Name, f.Usage)\n\t\t\t}\n\t\t})\n\t\tfs.SetOutput(os.Stdout)\n\t\tfs.PrintDefaults()\n\n\t\tfmt.Printf(\"\\nTo see details and flags of a specific analyzer, run '%s help name'.\\n\", progname)\n\n\t\treturn\n\t}\n\n\t// Show help on specific analyzer(s).\nouter:\n\tfor _, arg := range args {\n\t\tfor _, a := range analyzers {\n\t\t\tif a.Name == arg {\n\t\t\t\tparas := strings.Split(a.Doc, \"\\n\\n\")\n\t\t\t\ttitle := paras[0]\n\t\t\t\tfmt.Printf(\"%s: %s\\n\", a.Name, title)\n\n\t\t\t\t// Show only the flags relating to this analysis,\n\t\t\t\t// properly prefixed.\n\t\t\t\tfirst := true\n\t\t\t\tfs := flag.NewFlagSet(a.Name, flag.ExitOnError)\n\t\t\t\ta.Flags.VisitAll(func(f *flag.Flag) {\n\t\t\t\t\tif first {\n\t\t\t\t\t\tfirst = false\n\t\t\t\t\t\tfmt.Println(\"\\nAnalyzer flags:\")\n\t\t\t\t\t\tfmt.Println()\n\t\t\t\t\t}\n\t\t\t\t\tfs.Var(f.Value, a.Name+\".\"+f.Name, f.Usage)\n\t\t\t\t})\n\t\t\t\tfs.SetOutput(os.Stdout)\n\t\t\t\tfs.PrintDefaults()\n\n\t\t\t\tif len(paras) > 1 {\n\t\t\t\t\tfmt.Printf(\"\\n%s\\n\", strings.Join(paras[1:], \"\\n\\n\"))\n\t\t\t\t}\n\n\t\t\t\tcontinue outer\n\t\t\t}\n\t\t}\n\t\tlog.Fatalf(\"Analyzer %q not registered\", arg)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/checker.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package internal/checker defines various implementation helpers for\n// the singlechecker and multichecker packages, which provide the\n// complete main function for an analysis driver executable\n// based on go/packages.\n//\n// (Note: it is not used by the public 'checker' package, since the\n// latter provides a set of pure functions for use as building blocks.)\npackage checker\n\n// TODO(adonovan): publish the JSON schema in go/analysis or analysisjson.\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"log\"\n\t\"os\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"runtime/trace\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/checker\"\n\t\"golang.org/x/tools/go/analysis/internal\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n)\n\nvar (\n\t// Debug is a set of single-letter flags:\n\t//\n\t//\tf\tshow [f]acts as they are created\n\t// \tp\tdisable [p]arallel execution of analyzers\n\t//\ts\tdo additional [s]anity checks on fact types and serialization\n\t//\tt\tshow [t]iming info (NB: use 'p' flag to avoid GC/scheduler noise)\n\t//\tv\tshow [v]erbose logging\n\t//\n\tDebug = \"\"\n\n\t// Log files for optional performance tracing.\n\tCPUProfile, MemProfile, Trace string\n\n\t// IncludeTests indicates whether test files should be analyzed too.\n\tIncludeTests = true\n)\n\n// RegisterFlags registers command-line flags used by the analysis driver.\nfunc RegisterFlags() {\n\t// When adding flags here, remember to update\n\t// the list of suppressed flags in analysisflags.\n\n\tflag.StringVar(&Debug, \"debug\", Debug, `debug flags, any subset of \"fpstv\"`)\n\n\tflag.StringVar(&CPUProfile, \"cpuprofile\", \"\", \"write CPU profile to this file\")\n\tflag.StringVar(&MemProfile, \"memprofile\", \"\", \"write memory profile to this file\")\n\tflag.StringVar(&Trace, \"trace\", \"\", \"write trace log to this file\")\n\tflag.BoolVar(&IncludeTests, \"test\", IncludeTests, \"indicates whether test files should be analyzed, too\")\n}\n\n// Run loads the packages specified by args using go/packages,\n// then applies the specified analyzers to them.\n// Analysis flags must already have been set.\n// Analyzers must be valid according to [analysis.Validate].\n// It provides most of the logic for the main functions of both the\n// singlechecker and the multi-analysis commands.\n// It returns the appropriate exit code.\n//\n// TODO(adonovan): tests should not call this function directly.\n// Fiddling with global variables (flags such as [analysisflags.Fix])\n// is error-prone and hostile to parallelism. Instead, use unit tests\n// of the actual units (e.g. checker.Analyze) and integration tests\n// (e.g. TestScript) of whole executables.\nfunc Run(args []string, analyzers []*analysis.Analyzer) (exitcode int) {\n\t// Instead of returning a code directly,\n\t// call this function to monotonically increase the exit code.\n\t// This allows us to keep going in the face of some errors\n\t// without having to remember what code to return.\n\t//\n\t// TODO(adonovan): interpreting exit codes is like reading tea-leaves.\n\t// Instead of wasting effort trying to encode a multidimensional result\n\t// into 7 bits we should just emit structured JSON output, and\n\t// an exit code of 0 or 1 for success or failure.\n\texitAtLeast := func(code int) {\n\t\texitcode = max(code, exitcode)\n\t}\n\n\t// Since analysisflags is linked in (for {single,multi}checker),\n\t// the -v flag is registered for complex legacy reasons\n\t// related to cmd/vet CLI.\n\t// Treat it as an undocumented alias for -debug=v.\n\tif v := flag.CommandLine.Lookup(\"v\"); v != nil &&\n\t\tv.Value.(flag.Getter).Get() == true &&\n\t\t!strings.Contains(Debug, \"v\") {\n\t\tDebug += \"v\"\n\t}\n\n\tif CPUProfile != \"\" {\n\t\tf, err := os.Create(CPUProfile)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif err := pprof.StartCPUProfile(f); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// NB: profile won't be written in case of error.\n\t\tdefer pprof.StopCPUProfile()\n\t}\n\n\tif Trace != \"\" {\n\t\tf, err := os.Create(Trace)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif err := trace.Start(f); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// NB: trace log won't be written in case of error.\n\t\tdefer func() {\n\t\t\ttrace.Stop()\n\t\t\tlog.Printf(\"To view the trace, run:\\n$ go tool trace view %s\", Trace)\n\t\t}()\n\t}\n\n\tif MemProfile != \"\" {\n\t\tf, err := os.Create(MemProfile)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\t// NB: memprofile won't be written in case of error.\n\t\tdefer func() {\n\t\t\truntime.GC() // get up-to-date statistics\n\t\t\tif err := pprof.WriteHeapProfile(f); err != nil {\n\t\t\t\tlog.Fatalf(\"Writing memory profile: %v\", err)\n\t\t\t}\n\t\t\tf.Close()\n\t\t}()\n\t}\n\n\t// Load the packages.\n\tif dbg('v') {\n\t\tlog.SetPrefix(\"\")\n\t\tlog.SetFlags(log.Lmicroseconds) // display timing\n\t\tlog.Printf(\"load %s\", args)\n\t}\n\n\t// Optimization: if the selected analyzers don't produce/consume\n\t// facts, we need source only for the initial packages.\n\tallSyntax := needFacts(analyzers)\n\tinitial, err := load(args, allSyntax)\n\tif err != nil {\n\t\tlog.Print(err)\n\t\texitAtLeast(1)\n\t\treturn\n\t}\n\n\t// Print package and module errors regardless of RunDespiteErrors.\n\t// Do not exit if there are errors, yet.\n\tif n := packages.PrintErrors(initial); n > 0 {\n\t\texitAtLeast(1)\n\t}\n\n\tvar factLog io.Writer\n\tif dbg('f') {\n\t\tfactLog = os.Stderr\n\t}\n\n\t// Run the analysis.\n\topts := &checker.Options{\n\t\tSanityCheck: dbg('s'),\n\t\tSequential:  dbg('p'),\n\t\tFactLog:     factLog,\n\t}\n\tif dbg('v') {\n\t\tlog.Printf(\"building graph of analysis passes\")\n\t}\n\tgraph, err := checker.Analyze(analyzers, initial, opts)\n\tif err != nil {\n\t\tlog.Print(err)\n\t\texitAtLeast(1)\n\t\treturn\n\t}\n\n\t// Don't print the diagnostics,\n\t// but apply all fixes from the root actions.\n\tif analysisflags.Fix {\n\t\tfixActions := make([]driverutil.FixAction, len(graph.Roots))\n\t\tfor i, act := range graph.Roots {\n\t\t\tif pass := internal.ActionPass(act); pass != nil {\n\t\t\t\tfixActions[i] = driverutil.FixAction{\n\t\t\t\t\tName:         act.String(),\n\t\t\t\t\tPkg:          act.Package.Types,\n\t\t\t\t\tFiles:        act.Package.Syntax,\n\t\t\t\t\tFileSet:      act.Package.Fset,\n\t\t\t\t\tReadFileFunc: pass.ReadFile,\n\t\t\t\t\tDiagnostics:  act.Diagnostics,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twrite := func(filename string, content []byte) error {\n\t\t\treturn os.WriteFile(filename, content, 0644)\n\t\t}\n\t\tif err := driverutil.ApplyFixes(fixActions, write, analysisflags.Diff, dbg('v')); err != nil {\n\t\t\t// Fail when applying fixes failed.\n\t\t\tlog.Print(err)\n\t\t\texitAtLeast(1)\n\t\t\treturn\n\t\t}\n\t\t// Don't proceed to print text/JSON,\n\t\t// and don't report an error\n\t\t// just because there were diagnostics.\n\t\treturn\n\t}\n\n\t// Print the results. If !RunDespiteErrors and there\n\t// are errors in the packages, this will have 0 exit\n\t// code. Otherwise, we prefer to return exit code\n\t// indicating diagnostics.\n\texitAtLeast(printDiagnostics(graph))\n\n\treturn\n}\n\n// printDiagnostics prints diagnostics in text or JSON form\n// and returns the appropriate exit code.\nfunc printDiagnostics(graph *checker.Graph) (exitcode int) {\n\t// Keep consistent with analogous logic in\n\t// processResults in ../../unitchecker/unitchecker.go.\n\n\t// Print the results.\n\t// With -json, the exit code is always zero.\n\tif analysisflags.JSON {\n\t\tif err := graph.PrintJSON(os.Stdout); err != nil {\n\t\t\treturn 1\n\t\t}\n\t} else {\n\t\tif err := graph.PrintText(os.Stderr, analysisflags.Context); err != nil {\n\t\t\treturn 1\n\t\t}\n\n\t\t// Compute the exit code.\n\t\tvar numErrors, rootDiags int\n\t\tfor act := range graph.All() {\n\t\t\tif act.Err != nil {\n\t\t\t\tnumErrors++\n\t\t\t} else if act.IsRoot {\n\t\t\t\trootDiags += len(act.Diagnostics)\n\t\t\t}\n\t\t}\n\n\t\tif numErrors > 0 {\n\t\t\texitcode = 1 // analysis failed, at least partially\n\t\t} else if rootDiags > 0 {\n\t\t\texitcode = 3 // successfully produced diagnostics\n\t\t}\n\t}\n\n\t// Print timing info.\n\tif dbg('t') {\n\t\tif !dbg('p') {\n\t\t\tlog.Println(\"Warning: times are mostly GC/scheduler noise; use -debug=tp to disable parallelism\")\n\t\t}\n\n\t\tvar list []*checker.Action\n\t\tvar total time.Duration\n\t\tfor act := range graph.All() {\n\t\t\tlist = append(list, act)\n\t\t\ttotal += act.Duration\n\t\t}\n\n\t\t// Print actions accounting for 90% of the total.\n\t\tsort.Slice(list, func(i, j int) bool {\n\t\t\treturn list[i].Duration > list[j].Duration\n\t\t})\n\t\tvar sum time.Duration\n\t\tfor _, act := range list {\n\t\t\tfmt.Fprintf(os.Stderr, \"%s\\t%s\\n\", act.Duration, act)\n\t\t\tsum += act.Duration\n\t\t\tif sum >= total*9/10 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif total > sum {\n\t\t\tfmt.Fprintf(os.Stderr, \"%s\\tall others\\n\", total-sum)\n\t\t}\n\t}\n\n\treturn exitcode\n}\n\n// load loads the initial packages. Returns only top-level loading\n// errors. Does not consider errors in packages.\nfunc load(patterns []string, allSyntax bool) ([]*packages.Package, error) {\n\tmode := packages.LoadSyntax\n\tif allSyntax {\n\t\tmode = packages.LoadAllSyntax\n\t}\n\tmode |= packages.NeedModule\n\tconf := packages.Config{\n\t\tMode: mode,\n\t\t// Ensure that child process inherits correct alias of PWD.\n\t\t// (See discussion at Dir field of [exec.Command].)\n\t\t// However, this currently breaks some tests.\n\t\t// TODO(adonovan): Investigate.\n\t\t//\n\t\t// Dir:   os.Getenv(\"PWD\"),\n\t\tTests: IncludeTests,\n\t}\n\tinitial, err := packages.Load(&conf, patterns...)\n\tif err == nil && len(initial) == 0 {\n\t\terr = fmt.Errorf(\"%s matched no packages\", strings.Join(patterns, \" \"))\n\t}\n\treturn initial, err\n}\n\n// needFacts reports whether any analysis required by the specified set\n// needs facts.  If so, we must load the entire program from source.\nfunc needFacts(analyzers []*analysis.Analyzer) bool {\n\tseen := make(map[*analysis.Analyzer]bool)\n\tvar q []*analysis.Analyzer // for BFS\n\tq = append(q, analyzers...)\n\tfor len(q) > 0 {\n\t\ta := q[0]\n\t\tq = q[1:]\n\t\tif !seen[a] {\n\t\t\tseen[a] = true\n\t\t\tif len(a.FactTypes) > 0 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tq = append(q, a.Requires...)\n\t\t}\n\t}\n\treturn false\n}\n\nfunc dbg(b byte) bool { return strings.IndexByte(Debug, b) >= 0 }\n"
  },
  {
    "path": "go/analysis/internal/checker/checker_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage checker_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/go/analysis/internal/checker\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestApplyFixes(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.RedirectStderr(t) // associated checker.Run output with this test\n\n\tfiles := map[string]string{\n\t\t\"rename/test.go\": `package rename\n\nfunc Foo() {\n\tbar := 12\n\t_ = bar\n}\n\n// the end\n`}\n\twant := `package rename\n\nfunc Foo() {\n\tbaz := 12\n\t_ = baz\n}\n\n// the end\n`\n\n\ttestdata, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpath := filepath.Join(testdata, \"src/rename/test.go\")\n\n\tanalysisflags.Fix = true\n\tchecker.Run([]string{\"file=\" + path}, []*analysis.Analyzer{renameAnalyzer})\n\tanalysisflags.Fix = false\n\n\tcontents, err := os.ReadFile(path)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgot := string(contents)\n\tif got != want {\n\t\tt.Errorf(\"contents of rewritten file\\ngot: %s\\nwant: %s\", got, want)\n\t}\n\n\tdefer cleanup()\n}\n\nfunc TestRunDespiteErrors(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.RedirectStderr(t) // associate checker.Run output with this test\n\n\tfiles := map[string]string{\n\t\t\"rderr/test.go\": `package rderr\n\n// Foo deliberately has a type error\nfunc Foo(s string) int {\n\treturn s + 1\n}\n`,\n\t\t\"cperr/test.go\": `package copyerr\n\nimport \"sync\"\n\nfunc bar() { } // for renameAnalyzer\n\ntype T struct{ mu sync.Mutex }\ntype T1 struct{ t *T }\n\nfunc NewT1() *T1 { return &T1{T} }\n`,\n\t}\n\n\ttestdata, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\n\trderrFile := \"file=\" + filepath.Join(testdata, \"src/rderr/test.go\")\n\tcperrFile := \"file=\" + filepath.Join(testdata, \"src/cperr/test.go\")\n\n\t// A no-op analyzer that should finish regardless of\n\t// parse or type errors in the code.\n\tnoop := &analysis.Analyzer{\n\t\tName:     \"noop\",\n\t\tDoc:      \"noop\",\n\t\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\treturn nil, nil\n\t\t},\n\t\tRunDespiteErrors: true,\n\t}\n\n\t// A no-op analyzer, with facts, that should finish\n\t// regardless of parse or type errors in the code.\n\tnoopWithFact := &analysis.Analyzer{\n\t\tName:     \"noopfact\",\n\t\tDoc:      \"noopfact\",\n\t\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\treturn nil, nil\n\t\t},\n\t\tRunDespiteErrors: true,\n\t\tFactTypes:        []analysis.Fact{&EmptyFact{}},\n\t}\n\n\tfor _, test := range []struct {\n\t\tname      string\n\t\tpattern   []string\n\t\tanalyzers []*analysis.Analyzer\n\t\tcode      int\n\t}{\n\t\t// parse/type errors\n\t\t{name: \"skip-error\", pattern: []string{rderrFile}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: 1},\n\t\t// RunDespiteErrors allows a driver to run an Analyzer even after parse/type errors.\n\t\t//\n\t\t// The noop analyzer doesn't use facts, so the driver loads only the root\n\t\t// package from source. For the rest, it asks 'go list' for export data,\n\t\t// which fails because the compiler encounters the type error.  Since the\n\t\t// errors come from 'go list', the driver doesn't run the analyzer.\n\t\t{name: \"despite-error\", pattern: []string{rderrFile}, analyzers: []*analysis.Analyzer{noop}, code: exitCodeFailed},\n\t\t// The noopfact analyzer does use facts, so the driver loads source for\n\t\t// all dependencies, does type checking itself, recognizes the error as a\n\t\t// type error, and runs the analyzer.\n\t\t{name: \"despite-error-fact\", pattern: []string{rderrFile}, analyzers: []*analysis.Analyzer{noopWithFact}, code: exitCodeFailed},\n\t\t// combination of parse/type errors and no errors\n\t\t{name: \"despite-error-and-no-error\", pattern: []string{rderrFile, \"sort\"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: exitCodeFailed},\n\t\t// non-existing package error\n\t\t{name: \"no-package\", pattern: []string{\"xyz\"}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: exitCodeFailed},\n\t\t{name: \"no-package-despite-error\", pattern: []string{\"abc\"}, analyzers: []*analysis.Analyzer{noop}, code: exitCodeFailed},\n\t\t{name: \"no-multi-package-despite-error\", pattern: []string{\"xyz\", \"abc\"}, analyzers: []*analysis.Analyzer{noop}, code: exitCodeFailed},\n\t\t// combination of type/parsing and different errors\n\t\t{name: \"different-errors\", pattern: []string{rderrFile, \"xyz\"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: exitCodeFailed},\n\t\t// non existing dir error\n\t\t{name: \"no-match-dir\", pattern: []string{\"file=non/existing/dir\"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: exitCodeFailed},\n\t\t// no errors\n\t\t{name: \"no-errors\", pattern: []string{\"sort\"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: exitCodeSuccess},\n\t\t// duplicate list error with no findings\n\t\t{name: \"list-error\", pattern: []string{cperrFile}, analyzers: []*analysis.Analyzer{noop}, code: exitCodeFailed},\n\t\t// duplicate list errors with findings (issue #67790)\n\t\t{name: \"list-error-findings\", pattern: []string{cperrFile}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: exitCodeDiagnostics},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tif got := checker.Run(test.pattern, test.analyzers); got != test.code {\n\t\t\t\tt.Errorf(\"got incorrect exit code %d for test %s; want %d\", got, test.name, test.code)\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype EmptyFact struct{}\n\nfunc (f *EmptyFact) AFact() {}\n\nfunc TestURL(t *testing.T) {\n\t// TestURL test that URLs get forwarded to diagnostics by internal/checker.\n\ttestenv.NeedsGoPackages(t)\n\n\tfiles := map[string]string{\n\t\t\"p/test.go\": `package p // want \"package name is p\"`,\n\t}\n\tpkgname := &analysis.Analyzer{\n\t\tName: \"pkgname\",\n\t\tDoc:  \"trivial analyzer that reports package names\",\n\t\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/internal/checker\",\n\t\tRun: func(p *analysis.Pass) (any, error) {\n\t\t\tfor _, f := range p.Files {\n\t\t\t\tp.ReportRangef(f.Name, \"package name is %s\", f.Name.Name)\n\t\t\t}\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\n\ttestdata, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\tpath := filepath.Join(testdata, \"src/p/test.go\")\n\tresults := analysistest.Run(t, testdata, pkgname, \"file=\"+path)\n\n\tvar urls []string\n\tfor _, r := range results {\n\t\tfor _, d := range r.Diagnostics {\n\t\t\turls = append(urls, d.URL)\n\t\t}\n\t}\n\twant := []string{\"https://pkg.go.dev/golang.org/x/tools/go/analysis/internal/checker\"}\n\tif !reflect.DeepEqual(urls, want) {\n\t\tt.Errorf(\"Expected Diagnostics.URLs %v. got %v\", want, urls)\n\t}\n}\n\n// TestPassReadFile exercises the Pass.ReadFile function.\nfunc TestPassReadFile(t *testing.T) {\n\tcwd, _ := os.Getwd()\n\n\tconst src = `\n-- go.mod --\nmodule example.com\n\n-- p/file.go --\npackage p\n\n-- p/ignored.go --\n//go:build darwin && mips64\n\npackage p\n\nhello from ignored\n\n-- p/other.s --\nhello from other\n`\n\n\t// Expand archive into tmp tree.\n\tfs, err := txtar.FS(txtar.Parse([]byte(src)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttmpdir := testfiles.CopyToTmp(t, fs)\n\n\tran := false\n\ta := &analysis.Analyzer{\n\t\tName:     \"a\",\n\t\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\t\tDoc:      \"doc\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tif len(pass.OtherFiles)+len(pass.IgnoredFiles) == 0 {\n\t\t\t\tt.Errorf(\"OtherFiles and IgnoredFiles are empty\")\n\t\t\t\treturn nil, nil\n\t\t\t}\n\n\t\t\tfor _, test := range []struct {\n\t\t\t\tfilename string\n\t\t\t\twant     string // substring of file content or error message\n\t\t\t}{\n\t\t\t\t{\n\t\t\t\t\tpass.OtherFiles[0], // [other.s]\n\t\t\t\t\t\"hello from other\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpass.IgnoredFiles[0], // [ignored.go]\n\t\t\t\t\t\"hello from ignored\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"nonesuch\",\n\t\t\t\t\t\"nonesuch is not among OtherFiles, \", // etc\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfilepath.Join(cwd, \"checker_test.go\"),\n\t\t\t\t\t\"checker_test.go is not among OtherFiles, \", // etc\n\t\t\t\t},\n\t\t\t} {\n\t\t\t\tcontent, err := pass.ReadFile(test.filename)\n\t\t\t\tvar got string\n\t\t\t\tif err != nil {\n\t\t\t\t\tgot = err.Error()\n\t\t\t\t} else {\n\t\t\t\t\tgot = string(content)\n\t\t\t\t\tif len(got) > 100 {\n\t\t\t\t\t\tgot = got[:100] + \"...\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(got, test.want) {\n\t\t\t\t\tt.Errorf(\"Pass.ReadFile(%q) did not contain %q; got:\\n%s\",\n\t\t\t\t\t\ttest.filename, test.want, got)\n\t\t\t\t}\n\t\t\t}\n\t\t\tran = true\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\n\tanalysistest.Run(t, tmpdir, a, \"example.com/p\")\n\n\tif !ran {\n\t\tt.Error(\"analyzer did not run\")\n\t}\n\n\t// TODO(adonovan): test that fixes are applied to the\n\t// pass.ReadFile virtual file tree.\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/fix_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage checker_test\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/checker\"\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestMain(m *testing.M) {\n\t// If the CHECKER_TEST_CHILD environment variable is set,\n\t// this process should behave like a multichecker.\n\t// Analyzers are selected by flags.\n\tif _, ok := os.LookupEnv(\"CHECKER_TEST_CHILD\"); ok {\n\t\tmultichecker.Main(\n\t\t\tmarkerAnalyzer,\n\t\t\tnoendAnalyzer,\n\t\t\trenameAnalyzer,\n\t\t\trelatedAnalyzer,\n\t\t)\n\t\tpanic(\"unreachable\")\n\t}\n\n\t// ordinary test\n\tflag.Parse()\n\tos.Exit(m.Run())\n}\n\nconst (\n\texitCodeSuccess     = 0 // success (no diagnostics, or successful -fix)\n\texitCodeFailed      = 1 // analysis failed to run\n\texitCodeDiagnostics = 3 // diagnostics were reported (and no -fix)\n)\n\n// TestReportInvalidDiagnostic tests that a call to pass.Report with\n// certain kind of invalid diagnostic (e.g. conflicting fixes)\n// promptly results in a panic.\nfunc TestReportInvalidDiagnostic(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\t// Load the errors package.\n\tcfg := &packages.Config{Mode: packages.LoadAllSyntax}\n\tinitial, err := packages.Load(cfg, \"errors\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\tname string\n\t\twant string\n\t\tdiag func(pos token.Pos) analysis.Diagnostic\n\t}{\n\t\t// Diagnostic has two alternative fixes with the same Message.\n\t\t{\n\t\t\t\"duplicate message\",\n\t\t\t`analyzer \"a\" suggests two fixes with same Message \\(fix\\)`,\n\t\t\tfunc(pos token.Pos) analysis.Diagnostic {\n\t\t\t\treturn analysis.Diagnostic{\n\t\t\t\t\tPos:     pos,\n\t\t\t\t\tMessage: \"oops\",\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t{Message: \"fix\"},\n\t\t\t\t\t\t{Message: \"fix\"},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t// TextEdit has invalid Pos.\n\t\t{\n\t\t\t\"bad Pos\",\n\t\t\t`analyzer \"a\" suggests invalid fix .*: no token.File for TextEdit.Pos .0.`,\n\t\t\tfunc(pos token.Pos) analysis.Diagnostic {\n\t\t\t\treturn analysis.Diagnostic{\n\t\t\t\t\tPos:     pos,\n\t\t\t\t\tMessage: \"oops\",\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMessage:   \"fix\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{}},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t// TextEdit has invalid End.\n\t\t{\n\t\t\t\"End < Pos\",\n\t\t\t`analyzer \"a\" suggests invalid fix .*: TextEdit.Pos .* > TextEdit.End .*`,\n\t\t\tfunc(pos token.Pos) analysis.Diagnostic {\n\t\t\t\treturn analysis.Diagnostic{\n\t\t\t\t\tPos:     pos,\n\t\t\t\t\tMessage: \"oops\",\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMessage: \"fix\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos: pos + 2,\n\t\t\t\t\t\t\t\tEnd: pos,\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t// Two TextEdits overlap.\n\t\t{\n\t\t\t\"overlapping edits\",\n\t\t\t`analyzer \"a\" suggests invalid fix .*: overlapping edits to .*errors.go \\(1:1-1:3 and 1:2-1:4\\)`,\n\t\t\tfunc(pos token.Pos) analysis.Diagnostic {\n\t\t\t\treturn analysis.Diagnostic{\n\t\t\t\t\tPos:     pos,\n\t\t\t\t\tMessage: \"oops\",\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMessage: \"fix\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{\n\t\t\t\t\t\t\t\t{Pos: pos, End: pos + 2},\n\t\t\t\t\t\t\t\t{Pos: pos + 1, End: pos + 3},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\treached := false\n\t\t\ta := &analysis.Analyzer{Name: \"a\", Doc: \"doc\", Run: func(pass *analysis.Pass) (any, error) {\n\t\t\t\treached = true\n\t\t\t\tpanics(t, test.want, func() {\n\t\t\t\t\tpos := pass.Files[0].FileStart\n\t\t\t\t\tpass.Report(test.diag(pos))\n\t\t\t\t})\n\t\t\t\treturn nil, nil\n\t\t\t}}\n\t\t\tif _, err := checker.Analyze([]*analysis.Analyzer{a}, initial, &checker.Options{}); err != nil {\n\t\t\t\tt.Fatalf(\"Analyze failed: %v\", err)\n\t\t\t}\n\t\t\tif !reached {\n\t\t\t\tt.Error(\"analyzer was never invoked\")\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestScript runs script-driven tests in testdata/*.txt.\n// Each file is a txtar archive, expanded to a temporary directory.\n//\n// The comment section of the archive is a script, with the following\n// commands:\n//\n//\t# comment\n//\t\tignored\n//\tblank line\n//\t\tignored\n//\tskip k=v...\n//\t\tSkip the test if any k=v string is a substring of the string\n//\t\t\"GOOS=darwin GOARCH=arm64\" appropriate to the current build.\n//\tchecker args...\n//\t\tRun the checker command with the specified space-separated\n//\t\targuments; this fork+execs the [TestMain] function above.\n//\t\tIf the archive has a \"stdout\" section, its contents must\n//\t\tmatch the stdout output of the checker command.\n//\t\tDo NOT use this for testing -diff: tests should not\n//\t\trely on the particulars of the diff algorithm.\n//\texit int\n//\t\tAssert that previous checker command had this exit code.\n//\tstderr regexp\n//\t\tAssert that stderr output from previous checker run matches this pattern.\n//\n// The script must include at least one 'checker' command.\nfunc TestScript(t *testing.T) {\n\ttestenv.NeedsExec(t)\n\ttestenv.NeedsGoPackages(t)\n\n\ttxtfiles, err := filepath.Glob(\"testdata/*.txt\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, txtfile := range txtfiles {\n\t\tt.Run(txtfile, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Expand archive into tmp tree.\n\t\t\tar, err := txtar.ParseFile(txtfile)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfs, err := txtar.FS(ar)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdir := testfiles.CopyToTmp(t, fs)\n\n\t\t\t// Parse txtar comment as a script.\n\t\t\tconst noExitCode = -999\n\t\t\tvar (\n\t\t\t\t// state variables operated on by script\n\t\t\t\tlastExitCode = noExitCode\n\t\t\t\tlastStderr   string\n\t\t\t)\n\t\t\tfor i, line := range strings.Split(string(ar.Comment), \"\\n\") {\n\t\t\t\tline = strings.TrimSpace(line)\n\t\t\t\tif line == \"\" || line[0] == '#' {\n\t\t\t\t\tcontinue // skip blanks and comments\n\t\t\t\t}\n\n\t\t\t\tcommand, rest, _ := strings.Cut(line, \" \")\n\t\t\t\tprefix := fmt.Sprintf(\"%s:%d: %s\", txtfile, i+1, command) // for error messages\n\t\t\t\tswitch command {\n\t\t\t\tcase \"checker\":\n\t\t\t\t\tcmd := exec.Command(os.Args[0], strings.Fields(rest)...)\n\t\t\t\t\tcmd.Dir = dir\n\t\t\t\t\tcmd.Stdout = new(strings.Builder)\n\t\t\t\t\tcmd.Stderr = new(strings.Builder)\n\t\t\t\t\tcmd.Env = append(os.Environ(), \"CHECKER_TEST_CHILD=1\", \"GOPROXY=off\")\n\t\t\t\t\tif err := cmd.Run(); err != nil {\n\t\t\t\t\t\tif err, ok := err.(*exec.ExitError); ok {\n\t\t\t\t\t\t\tlastExitCode = err.ExitCode()\n\t\t\t\t\t\t\t// fall through\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Fatalf(\"%s: failed to execute checker: %v (%s)\", prefix, err, cmd)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlastExitCode = 0 // success\n\t\t\t\t\t}\n\n\t\t\t\t\t// Eliminate nondeterministic strings from the output.\n\t\t\t\t\tclean := func(x any) string {\n\t\t\t\t\t\ts := fmt.Sprint(x)\n\t\t\t\t\t\tpwd, _ := os.Getwd()\n\t\t\t\t\t\tif realDir, err := filepath.EvalSymlinks(dir); err == nil {\n\t\t\t\t\t\t\t// Work around checker's packages.Load failing to\n\t\t\t\t\t\t\t// set Config.Dir to dir, causing the filenames\n\t\t\t\t\t\t\t// of loaded packages not to be a subdir of dir.\n\t\t\t\t\t\t\ts = strings.ReplaceAll(s, realDir, dir)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ts = strings.ReplaceAll(s, dir, string(os.PathSeparator)+\"TMP\")\n\t\t\t\t\t\ts = strings.ReplaceAll(s, pwd, string(os.PathSeparator)+\"PWD\")\n\t\t\t\t\t\ts = strings.ReplaceAll(s, cmd.Path, filepath.Base(cmd.Path))\n\t\t\t\t\t\treturn s\n\t\t\t\t\t}\n\n\t\t\t\t\tlastStderr = clean(cmd.Stderr)\n\t\t\t\t\tstdout := clean(cmd.Stdout)\n\n\t\t\t\t\t// Detect bad markers out of band:\n\t\t\t\t\t// though they cause a non-zero exit,\n\t\t\t\t\t// that may be expected.\n\t\t\t\t\tif strings.Contains(lastStderr, badMarker) {\n\t\t\t\t\t\tt.Errorf(\"marker analyzer encountered errors; stderr=%s\", lastStderr)\n\t\t\t\t\t}\n\n\t\t\t\t\t// debugging\n\t\t\t\t\tif false {\n\t\t\t\t\t\tt.Logf(\"%s: $ %s\\nstdout:\\n%s\\nstderr:\\n%s\", prefix, clean(cmd), stdout, lastStderr)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Keep error reporting logic below consistent with\n\t\t\t\t\t// applyDiffsAndCompare in ../../analysistest/analysistest.go!\n\n\t\t\t\t\tunified := func(xlabel, ylabel string, x, y []byte) string {\n\t\t\t\t\t\tx = append(slices.Clip(bytes.TrimSpace(x)), '\\n')\n\t\t\t\t\t\ty = append(slices.Clip(bytes.TrimSpace(y)), '\\n')\n\t\t\t\t\t\treturn diff.Unified(xlabel, ylabel, string(x), string(y))\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check stdout, if there's a section of that name.\n\t\t\t\t\t//\n\t\t\t\t\t// Do not use this for testing -diff! It exposes tests to the\n\t\t\t\t\t// internals of our (often suboptimal) diff algorithm.\n\t\t\t\t\t// Instead, use the want/ mechanism.\n\t\t\t\t\tif f := section(ar, \"stdout\"); f != nil {\n\t\t\t\t\t\tgot, want := []byte(stdout), f.Data\n\t\t\t\t\t\tif diff := unified(\"got\", \"want\", got, want); diff != \"\" {\n\t\t\t\t\t\t\tt.Errorf(\"%s: unexpected stdout: -- got --\\n%s-- want --\\n%s-- diff --\\n%s\",\n\t\t\t\t\t\t\t\tprefix,\n\t\t\t\t\t\t\t\tgot, want, diff)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor _, f := range ar.Files {\n\t\t\t\t\t\t// For each file named want/X, assert that the\n\t\t\t\t\t\t// current content of X now equals want/X.\n\t\t\t\t\t\tif filename, ok := strings.CutPrefix(f.Name, \"want/\"); ok {\n\t\t\t\t\t\t\tfixed, err := os.ReadFile(filepath.Join(dir, filename))\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"reading %s: %v\", filename, err)\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar original []byte\n\t\t\t\t\t\t\tif f := section(ar, filename); f != nil {\n\t\t\t\t\t\t\t\toriginal = f.Data\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\twant := f.Data\n\t\t\t\t\t\t\tif diff := unified(filename+\" (fixed)\", filename+\" (want)\", fixed, want); diff != \"\" {\n\t\t\t\t\t\t\t\tt.Errorf(\"%s: unexpected %s content:\\n\"+\n\t\t\t\t\t\t\t\t\t\"-- original --\\n%s\\n\"+\n\t\t\t\t\t\t\t\t\t\"-- fixed --\\n%s\\n\"+\n\t\t\t\t\t\t\t\t\t\"-- want --\\n%s\\n\"+\n\t\t\t\t\t\t\t\t\t\"-- diff original fixed --\\n%s\\n\"+\n\t\t\t\t\t\t\t\t\t\"-- diff fixed want --\\n%s\",\n\t\t\t\t\t\t\t\t\tprefix, filename,\n\t\t\t\t\t\t\t\t\toriginal,\n\t\t\t\t\t\t\t\t\tfixed,\n\t\t\t\t\t\t\t\t\twant,\n\t\t\t\t\t\t\t\t\tunified(filename+\" (original)\", filename+\" (fixed)\", original, fixed),\n\t\t\t\t\t\t\t\t\tdiff)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\tcase \"skip\":\n\t\t\t\t\tconfig := fmt.Sprintf(\"GOOS=%s GOARCH=%s\", runtime.GOOS, runtime.GOARCH)\n\t\t\t\t\tfor word := range strings.FieldsSeq(rest) {\n\t\t\t\t\t\tif strings.Contains(config, word) {\n\t\t\t\t\t\t\tt.Skip(word)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\tcase \"exit\":\n\t\t\t\t\tif lastExitCode == noExitCode {\n\t\t\t\t\t\tt.Fatalf(\"%s: no prior 'checker' command\", prefix)\n\t\t\t\t\t}\n\t\t\t\t\tvar want int\n\t\t\t\t\tif _, err := fmt.Sscanf(rest, \"%d\", &want); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"%s: requires one numeric operand\", prefix)\n\t\t\t\t\t}\n\t\t\t\t\tif want != lastExitCode {\n\t\t\t\t\t\t// plan9 ExitCode() currently only returns 0 for success or 1 for failure\n\t\t\t\t\t\tif !(runtime.GOOS == \"plan9\" && want != exitCodeSuccess && lastExitCode != exitCodeSuccess) {\n\t\t\t\t\t\t\tt.Errorf(\"%s: exit code was %d, want %d\", prefix, lastExitCode, want)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\tcase \"stderr\":\n\t\t\t\t\tif lastExitCode == noExitCode {\n\t\t\t\t\t\tt.Fatalf(\"%s: no prior 'checker' command\", prefix)\n\t\t\t\t\t}\n\t\t\t\t\tif matched, err := regexp.MatchString(rest, lastStderr); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"%s: invalid regexp: %v\", prefix, err)\n\t\t\t\t\t} else if !matched {\n\t\t\t\t\t\tt.Errorf(\"%s: output didn't match pattern %q:\\n%s\", prefix, rest, lastStderr)\n\t\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tt.Errorf(\"%s: unknown command\", prefix)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif lastExitCode == noExitCode {\n\t\t\t\tt.Errorf(\"test script contains no 'checker' command\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nconst badMarker = \"[bad marker]\"\n\n// The marker analyzer generates fixes from @marker annotations in the\n// source. Each marker is of the form:\n//\n//\t@message(\"pattern\", \"replacement)\n//\n// The \"message\" is used for both the Diagnostic.Message and\n// SuggestedFix.Message field. Multiple markers with the same\n// message form a single diagnostic and fix with a list of textedits.\n//\n// The \"pattern\" is a regular expression that must match on the\n// current line (though it may extend beyond if the pattern starts\n// with \"(?s)\"), and whose extent forms the TextEdit.{Pos,End}\n// deletion. If the pattern contains one subgroup, its range will be\n// used; this allows contextual matching.\n//\n// The \"replacement\" is a literal string that forms the\n// TextEdit.NewText.\n//\n// Fixes are applied in the order they are first mentioned in the\n// source.\nvar markerAnalyzer = &analysis.Analyzer{\n\tName:     \"marker\",\n\tDoc:      \"doc\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun: func(pass *analysis.Pass) (_ any, err error) {\n\t\t// Errors returned by this analyzer cause the\n\t\t// checker command to exit non-zero, but that\n\t\t// may be the expected outcome for other reasons\n\t\t// (e.g. there were diagnostics).\n\t\t//\n\t\t// So, we report these errors out of band by logging\n\t\t// them with a special badMarker string that the\n\t\t// TestScript harness looks for, to ensure that the\n\t\t// test fails in that case.\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"%s: %v\", badMarker, err)\n\t\t\t}\n\t\t}()\n\n\t\t// Parse all notes in the files.\n\t\tvar keys []string\n\t\tedits := make(map[string][]analysis.TextEdit)\n\t\tfor _, file := range pass.Files {\n\t\t\ttokFile := pass.Fset.File(file.FileStart)\n\t\t\tcontent, err := pass.ReadFile(tokFile.Name())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tnotes, err := expect.ExtractGo(tokFile, file)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tfor _, note := range notes {\n\t\t\t\tedit, err := markerEdit(tokFile, content, note)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"%s: %v\", tokFile.Position(note.Pos), err)\n\t\t\t\t}\n\t\t\t\t// Preserve note order as it determines fix order.\n\t\t\t\tif edits[note.Name] == nil {\n\t\t\t\t\tkeys = append(keys, note.Name)\n\t\t\t\t}\n\t\t\t\tedits[note.Name] = append(edits[note.Name], edit)\n\t\t\t}\n\t\t}\n\n\t\t// Report each fix in its own Diagnostic.\n\t\tfor _, key := range keys {\n\t\t\tedits := edits[key]\n\t\t\t// debugging\n\t\t\tif false {\n\t\t\t\tlog.Printf(\"%s: marker: @%s: %+v\", pass.Fset.Position(edits[0].Pos), key, edits)\n\t\t\t}\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     edits[0].Pos,\n\t\t\t\tEnd:     edits[0].Pos,\n\t\t\t\tMessage: key,\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   key,\n\t\t\t\t\tTextEdits: edits,\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t\treturn nil, nil\n\t},\n}\n\n// markerEdit returns the TextEdit denoted by note.\nfunc markerEdit(tokFile *token.File, content []byte, note *expect.Note) (analysis.TextEdit, error) {\n\tif len(note.Args) != 2 {\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"got %d args, want @%s(pattern, replacement)\", len(note.Args), note.Name)\n\t}\n\n\tpattern, ok := note.Args[0].(string)\n\tif !ok {\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"got %T for pattern, want string\", note.Args[0])\n\t}\n\trx, err := regexp.Compile(pattern)\n\tif err != nil {\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"invalid pattern regexp: %v\", err)\n\t}\n\n\t// Match the pattern against the current line.\n\tlineStart := tokFile.LineStart(tokFile.Position(note.Pos).Line)\n\tlineStartOff := tokFile.Offset(lineStart)\n\tlineEndOff := tokFile.Offset(note.Pos)\n\tmatches := rx.FindSubmatchIndex(content[lineStartOff:])\n\tif len(matches) == 0 {\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"no match for regexp %q\", rx)\n\t}\n\tvar start, end int // line-relative offset\n\tswitch len(matches) {\n\tcase 2:\n\t\t// no subgroups: return the range of the regexp expression\n\t\tstart, end = matches[0], matches[1]\n\tcase 4:\n\t\t// one subgroup: return its range\n\t\tstart, end = matches[2], matches[3]\n\tdefault:\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"invalid location regexp %q: expect either 0 or 1 subgroups, got %d\", rx, len(matches)/2-1)\n\t}\n\tif start > lineEndOff-lineStartOff {\n\t\t// The start of the match must be between the start of the line and the\n\t\t// marker position (inclusive).\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"no matching range found starting on the current line\")\n\t}\n\n\treplacement, ok := note.Args[1].(string)\n\tif !ok {\n\t\treturn analysis.TextEdit{}, fmt.Errorf(\"second argument must be pattern, got %T\", note.Args[1])\n\t}\n\n\t// debugging: show matched portion\n\tif false {\n\t\tlog.Printf(\"%s: %s: r%q (%q) -> %q\",\n\t\t\ttokFile.Position(note.Pos),\n\t\t\tnote.Name,\n\t\t\tpattern,\n\t\t\tcontent[lineStartOff+start:lineStartOff+end],\n\t\t\treplacement)\n\t}\n\n\treturn analysis.TextEdit{\n\t\tPos:     lineStart + token.Pos(start),\n\t\tEnd:     lineStart + token.Pos(end),\n\t\tNewText: []byte(replacement),\n\t}, nil\n}\n\nvar renameAnalyzer = &analysis.Analyzer{\n\tName:             \"rename\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tDoc:              \"renames symbols named bar to baz\",\n\tRunDespiteErrors: true,\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tconst (\n\t\t\tfrom = \"bar\"\n\t\t\tto   = \"baz\"\n\t\t)\n\t\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tnodeFilter := []ast.Node{(*ast.Ident)(nil)}\n\t\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\t\tident := n.(*ast.Ident)\n\t\t\tif ident.Name == from {\n\t\t\t\tmsg := fmt.Sprintf(\"renaming %q to %q\", from, to)\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\tPos:     ident.Pos(),\n\t\t\t\t\tEnd:     ident.End(),\n\t\t\t\t\tMessage: msg,\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage: msg,\n\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\tPos:     ident.Pos(),\n\t\t\t\t\t\t\tEnd:     ident.End(),\n\t\t\t\t\t\t\tNewText: []byte(to),\n\t\t\t\t\t\t}},\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t\treturn nil, nil\n\t},\n}\n\nvar noendAnalyzer = &analysis.Analyzer{\n\tName: \"noend\",\n\tDoc:  \"inserts /*hello*/ before first decl\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tdecl := pass.Files[0].Decls[0]\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     decl.Pos(),\n\t\t\tEnd:     token.NoPos,\n\t\t\tMessage: \"say hello\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"say hello\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     decl.Pos(),\n\t\t\t\t\tEnd:     token.NoPos,\n\t\t\t\t\tNewText: []byte(\"/*hello*/\"),\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t\treturn nil, nil\n\t},\n}\n\nvar relatedAnalyzer = &analysis.Analyzer{\n\tName: \"related\",\n\tDoc:  \"reports a Diagnostic with RelatedInformaiton\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tdecl := pass.Files[0].Decls[0]\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     decl.Pos(),\n\t\t\tEnd:     decl.Pos() + 1,\n\t\t\tMessage: \"decl starts here\",\n\t\t\tRelated: []analysis.RelatedInformation{{\n\t\t\t\tMessage: \"decl ends here\",\n\t\t\t\tPos:     decl.End() - 1,\n\t\t\t\tEnd:     decl.End(),\n\t\t\t}},\n\t\t})\n\t\treturn nil, nil\n\t},\n}\n\n// panics asserts that f() panics with with a value whose printed form matches the regexp want.\nfunc panics(t *testing.T, want string, f func()) {\n\tdefer func() {\n\t\tif x := recover(); x == nil {\n\t\t\tt.Errorf(\"function returned normally, wanted panic\")\n\t\t} else if m, err := regexp.MatchString(want, fmt.Sprint(x)); err != nil {\n\t\t\tt.Errorf(\"panics: invalid regexp %q\", want)\n\t\t} else if !m {\n\t\t\tt.Errorf(\"function panicked with value %q, want match for %q\", x, want)\n\t\t}\n\t}()\n\tf()\n}\n\n// section returns the named archive section, or nil.\nfunc section(ar *txtar.Archive, name string) *txtar.File {\n\tfor i, f := range ar.Files {\n\t\tif f.Name == name {\n\t\t\treturn &ar.Files[i]\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/start_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage checker_test\n\nimport (\n\t\"go/ast\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/go/analysis/internal/checker\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestStartFixes make sure modifying the first character\n// of the file takes effect.\nfunc TestStartFixes(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.RedirectStderr(t) // associated checker.Run output with this test\n\n\tfiles := map[string]string{\n\t\t\"comment/doc.go\": `/* Package comment */\npackage comment\n`}\n\n\twant := `// Package comment\npackage comment\n`\n\n\ttestdata, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpath := filepath.Join(testdata, \"src/comment/doc.go\")\n\tanalysisflags.Fix = true\n\tchecker.Run([]string{\"file=\" + path}, []*analysis.Analyzer{commentAnalyzer})\n\tanalysisflags.Fix = false\n\n\tcontents, err := os.ReadFile(path)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgot := string(contents)\n\tif got != want {\n\t\tt.Errorf(\"contents of rewritten file\\ngot: %s\\nwant: %s\", got, want)\n\t}\n\n\tdefer cleanup()\n}\n\nvar commentAnalyzer = &analysis.Analyzer{\n\tName:     \"comment\",\n\tDoc:      \"comment\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      commentRun,\n}\n\nfunc commentRun(pass *analysis.Pass) (any, error) {\n\tconst (\n\t\tfrom = \"/* Package comment */\"\n\t\tto   = \"// Package comment\"\n\t)\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tinspect.Preorder(nil, func(n ast.Node) {\n\t\tif n, ok := n.(*ast.Comment); ok && n.Text == from {\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos: n.Pos(),\n\t\t\t\tEnd: n.End(),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\tPos:     n.Pos(),\n\t\t\t\t\t\tEnd:     n.End(),\n\t\t\t\t\t\tNewText: []byte(to),\n\t\t\t\t\t}},\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t})\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/conflict.txt",
    "content": "# Conflicting edits are legal, so long as they appear in different fixes.\n# The driver will apply them in some order, and discard those that conflict.\n#\n# fix1 appears first, so is applied first; it succeeds.\n# fix2 and fix3 conflict with it and are rejected.\n\nchecker -marker -fix example.com/a\nexit 1\nstderr applied 1 of 3 fixes; 1 file updated...Re-run\n\n-- go.mod --\nmodule example.com\n\ngo 1.22\n\n-- a/a.go --\npackage a\n\nfunc f() {\n\tbar := 12 //@ fix1(\"\\tbar\", \"baz\"), fix2(\"ar \", \"baz\"), fix3(\"bar\", \"lorem ipsum\")\n\t_ = bar   //@ fix1(\" bar\", \"baz\")\n}\n\n-- want/a/a.go --\npackage a\n\nfunc f() {\n\tbaz := 12 //@ fix1(\"\\tbar\", \"baz\"), fix2(\"ar \", \"baz\"), fix3(\"bar\", \"lorem ipsum\")\n\t_ = baz   //@ fix1(\" bar\", \"baz\")\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/diff.txt",
    "content": "# Basic test of -diff: ensure that stdout contains a diff,\n# and the file system is unchanged.\n#\n# (Most tests of fixes should use want/* not -diff + stdout\n# to avoid dependency on the diff algorithm.)\n#\n# File slashes assume non-Windows.\n\nskip GOOS=windows\nchecker -rename -fix -diff example.com/p\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- p/p.go --\npackage p\n\nvar bar int\n\n-- want/p/p.go --\npackage p\n\nvar bar int\n\n-- stdout --\n--- /TMP/p/p.go (old)\n+++ /TMP/p/p.go (new)\n@@ -1,4 +1,3 @@\n package p\n \n-var bar int\n-\n+var baz int\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/fixes.txt",
    "content": "# Ensure that fixes are applied correctly, in\n# particular when processing duplicate fixes for overlapping packages\n# in the same directory (\"p\", \"p [p.test]\", \"p_test [p.test]\").\n\nchecker -rename -fix -v example.com/p\nstderr applied 8 fixes, updated 3 files\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- p/p.go --\npackage p\n\nfunc Foo() {\n\tbar := 12\n\t_ = bar\n}\n\n-- p/p_test.go --\npackage p\n\nfunc InTestFile() {\n\tbar := 13\n\t_ = bar\n}\n\n-- p/p_x_test.go --\npackage p_test\n\nfunc Foo() {\n\tbar := 14\n\t_ = bar\n}\n\n-- want/p/p.go --\npackage p\n\nfunc Foo() {\n\tbaz := 12\n\t_ = baz\n}\n\n-- want/p/p_test.go --\npackage p\n\nfunc InTestFile() {\n\tbaz := 13\n\t_ = baz\n}\n\n-- want/p/p_x_test.go --\npackage p_test\n\nfunc Foo() {\n\tbaz := 14\n\t_ = baz\n}\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/generated.txt",
    "content": "# This test exercises skipping of fixes that edit generated\n# files, and the summary logging thereof.\n\nchecker -rename -marker -fix -v example.com/a\nstderr skipped 1 fix that would edit generated files\nstderr applied 2 fixes, updated 1 file\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/a.go --\npackage a\n\nvar A int //@ fix(\"A\", \"A2\")\n\n-- a/gena.go --\n// Code generated by hand. DO NOT EDIT.\n\npackage a\n\nvar B int //@ fix2(\"B\", \"B2\")\n\n-- want/a/a.go --\npackage a\n\nvar A2 int //@ fix(\"A\", \"A2\")\n\n-- want/a/gena.go --\n// Code generated by hand. DO NOT EDIT.\n\npackage a\n\nvar B int //@ fix2(\"B\", \"B2\")\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/importdup.txt",
    "content": "# Test that duplicate imports--and, more generally, duplicate\n# identical insertions--are coalesced.\n\nchecker -marker -fix -v example.com/a\nstderr applied 2 fixes, updated 1 file\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/a.go --\npackage a\n\nimport (\n\t_ \"errors\"\n\t//@ fix1(\"()//\", `\"foo\"`), fix2(\"()//\", `\"foo\"`)\n)\n\nfunc f() {} //@ fix1(\"()}\", \"n++\"), fix2(\"()}\", \"n++\")\n\n-- want/a/a.go --\npackage a\n\nimport (\n\t_ \"errors\"\n\t\"foo\" //@ fix1(\"()//\", `\"foo\"`), fix2(\"()//\", `\"foo\"`)\n)\n\nfunc f() { n++ } //@ fix1(\"()}\", \"n++\"), fix2(\"()}\", \"n++\")\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/importdup2.txt",
    "content": "# Test of import de-duplication behavior.\n#\n# In packages a and b, there are three fixes,\n# each adding one of two imports, but in different order.\n#\n# In package a, the fixes are [foo, foo, bar],\n# and they are resolved as follows:\n# - foo is applied    -> [foo]\n# - foo is coalesced  -> [foo]\n# - bar is applied    -> [foo bar]\n# The result is then formatted to [bar foo].\n#\n# In package b, the fixes are [foo, bar, foo]:\n# - foo is applied   -> [foo]\n# - bar is applied   -> [foo bar]\n# - foo is coalesced -> [foo bar]\n# The same result is again formatted to [bar foo].\n#\n# In more complex examples, the result\n# may be more subtly order-dependent.\n\nchecker -marker -fix -v example.com/a example.com/b\nstderr applied 6 fixes, updated 2 files\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/a.go --\npackage a\n\nimport (\n\t//@ fix1(\"()//\", \"\\\"foo\\\"\\n\"), fix2(\"()//\", \"\\\"foo\\\"\\n\"), fix3(\"()//\", \"\\\"bar\\\"\\n\")\n)\n\n-- want/a/a.go --\npackage a\n\nimport (\n\t\"bar\"\n\t\"foo\"\n\t// @ fix1(\"()//\", \"\\\"foo\\\"\\n\"), fix2(\"()//\", \"\\\"foo\\\"\\n\"), fix3(\"()//\", \"\\\"bar\\\"\\n\")\n)\n\n-- b/b.go --\npackage b\n\nimport (\n\t//@ fix1(\"()//\", \"\\\"foo\\\"\\n\"), fix2(\"()//\", \"\\\"bar\\\"\\n\"), fix3(\"()//\", \"\\\"foo\\\"\\n\")\n)\n\n-- want/b/b.go --\npackage b\n\nimport (\n\t\"bar\"\n\t\"foo\"\n\t// @ fix1(\"()//\", \"\\\"foo\\\"\\n\"), fix2(\"()//\", \"\\\"bar\\\"\\n\"), fix3(\"()//\", \"\\\"foo\\\"\\n\")\n)\n\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/json.txt",
    "content": "# Test basic JSON output.\n\n# File slashes assume non-Windows.\nskip GOOS=windows\n\nchecker -rename -json example.com/p\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- p/p.go --\npackage p\n\nfunc f(bar int) {}\n\n-- stdout --\n{\n\t\"example.com/p\": {\n\t\t\"rename\": [\n\t\t\t{\n\t\t\t\t\"posn\": \"/TMP/p/p.go:3:8\",\n\t\t\t\t\"end\": \"/TMP/p/p.go:3:11\",\n\t\t\t\t\"message\": \"renaming \\\"bar\\\" to \\\"baz\\\"\",\n\t\t\t\t\"suggested_fixes\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"message\": \"renaming \\\"bar\\\" to \\\"baz\\\"\",\n\t\t\t\t\t\t\"edits\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"filename\": \"/TMP/p/p.go\",\n\t\t\t\t\t\t\t\t\"start\": 18,\n\t\t\t\t\t\t\t\t\"end\": 21,\n\t\t\t\t\t\t\t\t\"new\": \"baz\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t}\n}\n\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/noend.txt",
    "content": "# Test that a missing SuggestedFix.End position is correctly\n# interpreted as if equal to SuggestedFix.Pos (see issue #64199).\n\nchecker -noend -fix example.com/a\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/a.go --\npackage a\n\nfunc f() {}\n\n-- want/a/a.go --\npackage a\n\n/*hello*/\nfunc f() {}\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/overlap.txt",
    "content": "# This test exercises an edge case of merging.\n#\n# Two analyzers generate overlapping fixes for this package:\n# - 'rename' changes \"bar\" to \"baz\"\n# - 'marker' changes  \"ar\" to \"baz\"\n# Historically this used to cause a conflict, but as it happens,\n# the new merge algorithm splits the rename fix, since it overlaps\n# the marker fix, into two subedits:\n# - a deletion of \"b\" and\n# - an edit from \"ar\" to \"baz\".\n# The deletion is of course nonoverlapping, and the edit,\n# by happy chance, is identical to the marker fix, so the two\n# are coalesced.\n#\n# (This is a pretty unlikely situation, but it corresponds\n# to a historical test, TestOther, that used to check for\n# a conflict, and it seemed wrong to delete it without explanation.)\n#\n# The fixes are silently and successfully applied.\n\nchecker -rename -marker -fix -v example.com/a\nstderr applied 2 fixes, updated 1 file\nexit 0\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/a.go --\npackage a\n\nfunc f(bar int) {} //@ fix(\"ar\", \"baz\")\n\n-- want/a/a.go --\npackage a\n\nfunc f(baz int) {} //@ fix(\"ar\", \"baz\")\n"
  },
  {
    "path": "go/analysis/internal/checker/testdata/plain.txt",
    "content": "# Test plain output.\n#\n# File slashes assume non-Windows.\nskip GOOS=windows\n\nchecker -related example.com/p\nstderr p/p.go:3:1: decl starts here\nstderr p/p.go:4:1: \tdecl ends here\n\nchecker -related -c=0 example.com/p\nstderr p/p.go:3:1: decl starts here\nstderr 3\tfunc f\\(bar int\\) {\nstderr p/p.go:4:1: \tdecl ends here\nstderr 4\t}\nexit 3\n\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- p/p.go --\npackage p\n\nfunc f(bar int) {\n}\n"
  },
  {
    "path": "go/analysis/internal/internal.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage internal\n\nimport \"golang.org/x/tools/go/analysis\"\n\n// This function is set by the checker package to provide\n// backdoor access to the private Pass field\n// of the *checker.Action type, for use by analysistest.\n//\n// It may return nil, for example if the action was not\n// executed because of a failed dependent.\nvar ActionPass func(action any) *analysis.Pass\n"
  },
  {
    "path": "go/analysis/internal/versiontest/version_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.21\n\n// Check that GoVersion propagates through to checkers.\n// Depends on Go 1.21 go/types.\n\npackage versiontest\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar analyzer = &analysis.Analyzer{\n\tName: \"versiontest\",\n\tDoc:  \"off\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tpass.Reportf(pass.Files[0].Package, \"goversion=%s\", pass.Pkg.GoVersion())\n\t\treturn nil, nil\n\t},\n}\n\nfunc init() {\n\tif os.Getenv(\"VERSIONTEST_MULTICHECKER\") == \"1\" {\n\t\tmultichecker.Main(analyzer)\n\t\tos.Exit(0)\n\t}\n\tif os.Getenv(\"VERSIONTEST_SINGLECHECKER\") == \"1\" {\n\t\tsinglechecker.Main(analyzer)\n\t\tos.Exit(0)\n\t}\n}\n\nfunc testDir(t *testing.T) (dir string) {\n\tdir = t.TempDir()\n\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), []byte(\"go 1.20\\nmodule m\\n\"), 0666); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(dir, \"x.go\"), []byte(\"package main // want \\\"goversion=go1.20\\\"\\n\"), 0666); err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn dir\n}\n\n// There are many ways to run analyzers. Test all the ones here in x/tools.\n\nfunc TestAnalysistest(t *testing.T) {\n\tanalysistest.Run(t, testDir(t), analyzer)\n}\n\nfunc TestMultichecker(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(exe, \".\")\n\tcmd.Dir = testDir(t)\n\tcmd.Env = append(os.Environ(), \"VERSIONTEST_MULTICHECKER=1\")\n\tout, err := cmd.CombinedOutput()\n\tif err == nil || !strings.Contains(string(out), \"x.go:1:1: goversion=go1.20\") {\n\t\tt.Fatalf(\"multichecker: %v\\n%s\", err, out)\n\t}\n}\n\nfunc TestSinglechecker(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(exe, \".\")\n\tcmd.Dir = testDir(t)\n\tcmd.Env = append(os.Environ(), \"VERSIONTEST_SINGLECHECKER=1\")\n\tout, err := cmd.CombinedOutput()\n\tif err == nil || !strings.Contains(string(out), \"x.go:1:1: goversion=go1.20\") {\n\t\tt.Fatalf(\"multichecker: %v\\n%s\", err, out)\n\t}\n}\n\nfunc TestVettool(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(\"go\", \"vet\", \"-vettool=\"+exe, \".\")\n\tcmd.Dir = testDir(t)\n\tcmd.Env = append(os.Environ(), \"VERSIONTEST_MULTICHECKER=1\")\n\tout, err := cmd.CombinedOutput()\n\tif err == nil || !strings.Contains(string(out), \"x.go:1:1: goversion=go1.20\") {\n\t\tt.Fatalf(\"vettool: %v\\n%s\", err, out)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/multichecker/multichecker.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package multichecker defines the main function for an analysis driver\n// with several analyzers. This package makes it easy for anyone to build\n// an analysis tool containing just the analyzers they need.\npackage multichecker\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/go/analysis/internal/checker\"\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n)\n\nfunc Main(analyzers ...*analysis.Analyzer) {\n\tprogname := filepath.Base(os.Args[0])\n\tlog.SetFlags(0)\n\tlog.SetPrefix(progname + \": \") // e.g. \"vet: \"\n\n\tif err := analysis.Validate(analyzers); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tchecker.RegisterFlags()\n\n\tanalyzers = analysisflags.Parse(analyzers, true)\n\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\tfmt.Fprintf(os.Stderr, `%[1]s is a tool for static analysis of Go programs.\n\nUsage: %[1]s [-flag] [package]\n\nRun '%[1]s help' for more detail,\n or '%[1]s help name' for details and flags of a specific analyzer.\n`, progname)\n\t\tos.Exit(1)\n\t}\n\n\tif args[0] == \"help\" {\n\t\tanalysisflags.Help(progname, analyzers, args[1:])\n\t\tos.Exit(0)\n\t}\n\n\tif len(args) == 1 && strings.HasSuffix(args[0], \".cfg\") {\n\t\tunitchecker.Run(args[0], analyzers)\n\t\tpanic(\"unreachable\")\n\t}\n\n\tos.Exit(checker.Run(args, analyzers))\n}\n"
  },
  {
    "path": "go/analysis/multichecker/multichecker_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.12\n\npackage multichecker_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc main() {\n\tfail := &analysis.Analyzer{\n\t\tName: \"fail\",\n\t\tDoc:  \"always fail on a package 'sort'\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tif pass.Pkg.Path() == \"sort\" {\n\t\t\t\treturn nil, fmt.Errorf(\"failed\")\n\t\t\t}\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\tmultichecker.Main(findcall.Analyzer, fail)\n}\n\n// TestExitCode ensures that analysis failures are reported correctly.\n// This test fork/execs the main function above.\nfunc TestExitCode(t *testing.T) {\n\tif runtime.GOOS != \"linux\" {\n\t\tt.Skipf(\"skipping fork/exec test on this platform\")\n\t}\n\n\tif os.Getenv(\"MULTICHECKER_CHILD\") == \"1\" {\n\t\t// child process\n\n\t\t// replace [progname -test.run=TestExitCode -- ...]\n\t\t//      by [progname ...]\n\t\tos.Args = os.Args[2:]\n\t\tos.Args[0] = \"vet\"\n\t\tmain()\n\t\tpanic(\"unreachable\")\n\t}\n\n\ttestenv.NeedsTool(t, \"go\")\n\n\tfor _, test := range []struct {\n\t\targs []string\n\t\twant int\n\t}{\n\t\t{[]string{\"nosuchdir/...\"}, 1},                      // matched no packages\n\t\t{[]string{\"nosuchpkg\"}, 1},                          // matched no packages\n\t\t{[]string{\"-unknownflag\"}, 2},                       // flag error\n\t\t{[]string{\"-findcall.name=panic\", \"io\"}, 3},         // finds diagnostics\n\t\t{[]string{\"-findcall=0\", \"io\"}, 0},                  // no checkers\n\t\t{[]string{\"-findcall.name=nosuchfunc\", \"io\"}, 0},    // no diagnostics\n\t\t{[]string{\"-findcall.name=panic\", \"sort\", \"io\"}, 1}, // 'fail' failed on 'sort'\n\n\t\t// -json: exits zero even in face of diagnostics or package errors.\n\t\t{[]string{\"-findcall.name=panic\", \"-json\", \"io\"}, 0},\n\t\t{[]string{\"-findcall.name=panic\", \"-json\", \"io\"}, 0},\n\t\t{[]string{\"-findcall.name=panic\", \"-json\", \"sort\", \"io\"}, 0},\n\t} {\n\t\targs := []string{\"-test.run=TestExitCode\", \"--\"}\n\t\targs = append(args, test.args...)\n\t\tcmd := exec.Command(os.Args[0], args...)\n\t\tcmd.Env = append(os.Environ(), \"MULTICHECKER_CHILD=1\")\n\t\tout, err := cmd.CombinedOutput()\n\t\tif len(out) > 0 {\n\t\t\tt.Logf(\"%s: out=<<%s>>\", test.args, out)\n\t\t}\n\t\tvar exitcode int\n\t\tif err, ok := err.(*exec.ExitError); ok {\n\t\t\texitcode = err.ExitCode() // requires go1.12\n\t\t}\n\t\tif exitcode != test.want {\n\t\t\tt.Errorf(\"%s: exited %d, want %d\", test.args, exitcode, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/README",
    "content": "\nThis directory does not contain a Go package,\nbut acts as a container for various analyses\nthat implement the golang.org/x/tools/go/analysis\nAPI and may be imported into an analysis tool.\n\nBy convention, each package foo provides the analysis,\nand each command foo/cmd/foo provides a standalone driver.\n"
  },
  {
    "path": "go/analysis/passes/appends/appends.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package appends defines an Analyzer that detects\n// if there is only one variable in append.\npackage appends\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"appends\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"appends\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tb, ok := typeutil.Callee(pass.TypesInfo, call).(*types.Builtin)\n\t\tif ok && b.Name() == \"append\" && len(call.Args) == 1 {\n\t\t\tpass.ReportRangef(call, \"append with no values\")\n\t\t}\n\t})\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/appends/appends_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage appends_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/appends\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\ttests := []string{\"a\", \"b\"}\n\tanalysistest.Run(t, testdata, appends.Analyzer, tests...)\n}\n"
  },
  {
    "path": "go/analysis/passes/appends/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package appends defines an Analyzer that detects\n// if there is only one variable in append.\n//\n// # Analyzer appends\n//\n// appends: check for missing values after append\n//\n// This checker reports calls to append that pass\n// no values to be appended to the slice.\n//\n//\ts := []string{\"a\", \"b\", \"c\"}\n//\t_ = append(s)\n//\n// Such calls are always no-ops and often indicate an\n// underlying mistake.\npackage appends\n"
  },
  {
    "path": "go/analysis/passes/appends/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the appends checker.\n\npackage a\n\nfunc badAppendSlice1() {\n\tsli := []string{\"a\", \"b\", \"c\"}\n\tsli = append(sli) // want \"append with no values\"\n}\n\nfunc badAppendSlice2() {\n\t_ = append([]string{\"a\"}) // want \"append with no values\"\n}\n\nfunc goodAppendSlice1() {\n\tsli := []string{\"a\", \"b\", \"c\"}\n\tsli = append(sli, \"d\")\n}\n\nfunc goodAppendSlice2() {\n\tsli1 := []string{\"a\", \"b\", \"c\"}\n\tsli2 := []string{\"d\", \"e\", \"f\"}\n\tsli1 = append(sli1, sli2...)\n}\n\nfunc goodAppendSlice3() {\n\tsli := []string{\"a\", \"b\", \"c\"}\n\tsli = append(sli, \"d\", \"e\", \"f\")\n}\n"
  },
  {
    "path": "go/analysis/passes/appends/testdata/src/b/b.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the appends checker.\n\npackage b\n\nfunc append(args ...interface{}) []int {\n\tprintln(args)\n\treturn []int{0}\n}\n\nfunc userdefine() {\n\tsli := []int{1, 2, 3}\n\tsli = append(sli, 4, 5, 6)\n\tsli = append(sli)\n}\n\nfunc localvar() {\n\tappend := func(int) int { return 0 }\n\ta := append(1)\n\t_ = a\n}\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/asmdecl.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package asmdecl defines an Analyzer that reports mismatches between\n// assembly files and Go declarations.\npackage asmdecl\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\nconst Doc = \"report mismatches between assembly files and Go declarations\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"asmdecl\",\n\tDoc:  Doc,\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/asmdecl\",\n\tRun:  run,\n}\n\n// 'kind' is a kind of assembly variable.\n// The kinds 1, 2, 4, 8 stand for values of that size.\ntype asmKind int\n\n// These special kinds are not valid sizes.\nconst (\n\tasmString asmKind = 100 + iota\n\tasmSlice\n\tasmArray\n\tasmInterface\n\tasmEmptyInterface\n\tasmStruct\n\tasmComplex\n)\n\n// An asmArch describes assembly parameters for an architecture\ntype asmArch struct {\n\tname      string\n\tbigEndian bool\n\tstack     string\n\tlr        bool\n\t// retRegs is a list of registers for return value in register ABI (ABIInternal).\n\t// For now, as we only check whether we write to any result, here we only need to\n\t// include the first integer register and first floating-point register. Accessing\n\t// any of them counts as writing to result.\n\tretRegs []string\n\t// writeResult is a list of instructions that will change result register implicitly.\n\twriteResult []string\n\t// calculated during initialization\n\tsizes    types.Sizes\n\tintSize  int\n\tptrSize  int\n\tmaxAlign int\n}\n\n// An asmFunc describes the expected variables for a function on a given architecture.\ntype asmFunc struct {\n\tarch        *asmArch\n\tsize        int // size of all arguments\n\tvars        map[string]*asmVar\n\tvarByOffset map[int]*asmVar\n}\n\n// An asmVar describes a single assembly variable.\ntype asmVar struct {\n\tname  string\n\tkind  asmKind\n\ttyp   string\n\toff   int\n\tsize  int\n\tinner []*asmVar\n}\n\nvar (\n\tasmArch386      = asmArch{name: \"386\", bigEndian: false, stack: \"SP\", lr: false}\n\tasmArchArm      = asmArch{name: \"arm\", bigEndian: false, stack: \"R13\", lr: true}\n\tasmArchArm64    = asmArch{name: \"arm64\", bigEndian: false, stack: \"RSP\", lr: true, retRegs: []string{\"R0\", \"F0\"}, writeResult: []string{\"SVC\"}}\n\tasmArchAmd64    = asmArch{name: \"amd64\", bigEndian: false, stack: \"SP\", lr: false, retRegs: []string{\"AX\", \"X0\"}, writeResult: []string{\"SYSCALL\"}}\n\tasmArchMips     = asmArch{name: \"mips\", bigEndian: true, stack: \"R29\", lr: true}\n\tasmArchMipsLE   = asmArch{name: \"mipsle\", bigEndian: false, stack: \"R29\", lr: true}\n\tasmArchMips64   = asmArch{name: \"mips64\", bigEndian: true, stack: \"R29\", lr: true}\n\tasmArchMips64LE = asmArch{name: \"mips64le\", bigEndian: false, stack: \"R29\", lr: true}\n\tasmArchPpc64    = asmArch{name: \"ppc64\", bigEndian: true, stack: \"R1\", lr: true, retRegs: []string{\"R3\", \"F1\"}, writeResult: []string{\"SYSCALL\"}}\n\tasmArchPpc64LE  = asmArch{name: \"ppc64le\", bigEndian: false, stack: \"R1\", lr: true, retRegs: []string{\"R3\", \"F1\"}, writeResult: []string{\"SYSCALL\"}}\n\tasmArchRISCV64  = asmArch{name: \"riscv64\", bigEndian: false, stack: \"SP\", lr: true, retRegs: []string{\"X10\", \"F10\"}, writeResult: []string{\"ECALL\"}}\n\tasmArchS390X    = asmArch{name: \"s390x\", bigEndian: true, stack: \"R15\", lr: true}\n\tasmArchWasm     = asmArch{name: \"wasm\", bigEndian: false, stack: \"SP\", lr: false}\n\tasmArchLoong64  = asmArch{name: \"loong64\", bigEndian: false, stack: \"R3\", lr: true, retRegs: []string{\"R4\", \"F0\"}, writeResult: []string{\"SYSCALL\"}}\n\n\tarches = []*asmArch{\n\t\t&asmArch386,\n\t\t&asmArchArm,\n\t\t&asmArchArm64,\n\t\t&asmArchAmd64,\n\t\t&asmArchMips,\n\t\t&asmArchMipsLE,\n\t\t&asmArchMips64,\n\t\t&asmArchMips64LE,\n\t\t&asmArchPpc64,\n\t\t&asmArchPpc64LE,\n\t\t&asmArchRISCV64,\n\t\t&asmArchS390X,\n\t\t&asmArchWasm,\n\t\t&asmArchLoong64,\n\t}\n)\n\nfunc init() {\n\tfor _, arch := range arches {\n\t\tarch.sizes = types.SizesFor(\"gc\", arch.name)\n\t\tif arch.sizes == nil {\n\t\t\t// TODO(adonovan): fix: now that asmdecl is not in the standard\n\t\t\t// library we cannot assume types.SizesFor is consistent with arches.\n\t\t\t// For now, assume 64-bit norms and print a warning.\n\t\t\t// But this warning should really be deferred until we attempt to use\n\t\t\t// arch, which is very unlikely. Better would be\n\t\t\t// to defer size computation until we have Pass.TypesSizes.\n\t\t\tarch.sizes = types.SizesFor(\"gc\", \"amd64\")\n\t\t\tlog.Printf(\"unknown architecture %s\", arch.name)\n\t\t}\n\t\tarch.intSize = int(arch.sizes.Sizeof(types.Typ[types.Int]))\n\t\tarch.ptrSize = int(arch.sizes.Sizeof(types.Typ[types.UnsafePointer]))\n\t\tarch.maxAlign = int(arch.sizes.Alignof(types.Typ[types.Int64]))\n\t}\n}\n\nvar (\n\tre           = regexp.MustCompile\n\tasmPlusBuild = re(`//\\s+\\+build\\s+([^\\n]+)`)\n\tasmTEXT      = re(`\\bTEXT\\b(.*)·([^\\(]+)\\(SB\\)(?:\\s*,\\s*([0-9A-Z|+()]+))?(?:\\s*,\\s*\\$(-?[0-9]+)(?:-([0-9]+))?)?`)\n\tasmDATA      = re(`\\b(DATA|GLOBL)\\b`)\n\tasmNamedFP   = re(`\\$?([a-zA-Z0-9_\\xFF-\\x{10FFFF}]+)(?:\\+([0-9]+))\\(FP\\)`)\n\tasmUnnamedFP = re(`[^+\\-0-9](([0-9]+)\\(FP\\))`)\n\tasmSP        = re(`[^+\\-0-9](([0-9]+)\\(([A-Z0-9]+)\\))`)\n\tasmOpcode    = re(`^\\s*(?:[A-Z0-9a-z_]+:)?\\s*([A-Z]+)\\s*([^,]*)(?:,\\s*(.*))?`)\n\tppc64Suff    = re(`([BHWD])(ZU|Z|U|BR)?$`)\n\tabiSuff      = re(`^(.+)<(ABI.+)>$`)\n)\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// No work if no assembly files.\n\tvar sfiles []string\n\tfor _, fname := range pass.OtherFiles {\n\t\tif strings.HasSuffix(fname, \".s\") {\n\t\t\tsfiles = append(sfiles, fname)\n\t\t}\n\t}\n\tif sfiles == nil {\n\t\treturn nil, nil\n\t}\n\n\t// Gather declarations. knownFunc[name][arch] is func description.\n\tknownFunc := make(map[string]map[string]*asmFunc)\n\n\tfor _, f := range pass.Files {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {\n\t\t\t\tknownFunc[decl.Name.Name] = asmParseDecl(pass, decl)\n\t\t\t}\n\t\t}\n\t}\n\nFiles:\n\tfor _, fname := range sfiles {\n\t\tcontent, tf, err := analyzerutil.ReadFile(pass, fname)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Determine architecture from file name if possible.\n\t\tvar arch string\n\t\tvar archDef *asmArch\n\t\tfor _, a := range arches {\n\t\t\tif strings.HasSuffix(fname, \"_\"+a.name+\".s\") {\n\t\t\t\tarch = a.name\n\t\t\t\tarchDef = a\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tlines := strings.SplitAfter(string(content), \"\\n\")\n\t\tvar (\n\t\t\tfn                 *asmFunc\n\t\t\tfnName             string\n\t\t\tabi                string\n\t\t\tlocalSize, argSize int\n\t\t\twroteSP            bool\n\t\t\tnoframe            bool\n\t\t\thaveRetArg         bool\n\t\t\tretLine            []int\n\t\t)\n\n\t\tflushRet := func() {\n\t\t\tif fn != nil && fn.vars[\"ret\"] != nil && !haveRetArg && len(retLine) > 0 {\n\t\t\t\tv := fn.vars[\"ret\"]\n\t\t\t\tresultStr := fmt.Sprintf(\"%d-byte ret+%d(FP)\", v.size, v.off)\n\t\t\t\tif abi == \"ABIInternal\" {\n\t\t\t\t\tresultStr = \"result register\"\n\t\t\t\t}\n\t\t\t\tfor _, line := range retLine {\n\t\t\t\t\tpass.Reportf(tf.LineStart(line), \"[%s] %s: RET without writing to %s\", arch, fnName, resultStr)\n\t\t\t\t}\n\t\t\t}\n\t\t\tretLine = nil\n\t\t}\n\t\ttrimABI := func(fnName string) (string, string) {\n\t\t\tm := abiSuff.FindStringSubmatch(fnName)\n\t\t\tif m != nil {\n\t\t\t\treturn m[1], m[2]\n\t\t\t}\n\t\t\treturn fnName, \"\"\n\t\t}\n\t\tfor lineno, line := range lines {\n\t\t\tlineno++\n\n\t\t\tbadf := func(format string, args ...any) {\n\t\t\t\tpass.Reportf(tf.LineStart(lineno), \"[%s] %s: %s\", arch, fnName, fmt.Sprintf(format, args...))\n\t\t\t}\n\n\t\t\tif arch == \"\" {\n\t\t\t\t// Determine architecture from +build line if possible.\n\t\t\t\tif m := asmPlusBuild.FindStringSubmatch(line); m != nil {\n\t\t\t\t\t// There can be multiple architectures in a single +build line,\n\t\t\t\t\t// so accumulate them all and then prefer the one that\n\t\t\t\t\t// matches build.Default.GOARCH.\n\t\t\t\t\tvar archCandidates []*asmArch\n\t\t\t\t\tfor fld := range strings.FieldsSeq(m[1]) {\n\t\t\t\t\t\tfor _, a := range arches {\n\t\t\t\t\t\t\tif a.name == fld {\n\t\t\t\t\t\t\t\tarchCandidates = append(archCandidates, a)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor _, a := range archCandidates {\n\t\t\t\t\t\tif a.name == build.Default.GOARCH {\n\t\t\t\t\t\t\tarchCandidates = []*asmArch{a}\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif len(archCandidates) > 0 {\n\t\t\t\t\t\tarch = archCandidates[0].name\n\t\t\t\t\t\tarchDef = archCandidates[0]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Ignore comments and commented-out code.\n\t\t\tif i := strings.Index(line, \"//\"); i >= 0 {\n\t\t\t\tline = line[:i]\n\t\t\t}\n\n\t\t\tif m := asmTEXT.FindStringSubmatch(line); m != nil {\n\t\t\t\tflushRet()\n\t\t\t\tif arch == \"\" {\n\t\t\t\t\t// Arch not specified by filename or build tags.\n\t\t\t\t\t// Fall back to build.Default.GOARCH.\n\t\t\t\t\tfor _, a := range arches {\n\t\t\t\t\t\tif a.name == build.Default.GOARCH {\n\t\t\t\t\t\t\tarch = a.name\n\t\t\t\t\t\t\tarchDef = a\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif arch == \"\" {\n\t\t\t\t\t\tlog.Printf(\"%s: cannot determine architecture for assembly file\", fname)\n\t\t\t\t\t\tcontinue Files\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfnName = m[2]\n\t\t\t\tif pkgPath := strings.TrimSpace(m[1]); pkgPath != \"\" {\n\t\t\t\t\t// The assembler uses Unicode division slash within\n\t\t\t\t\t// identifiers to represent the directory separator.\n\t\t\t\t\tpkgPath = strings.Replace(pkgPath, \"∕\", \"/\", -1)\n\t\t\t\t\tif pkgPath != pass.Pkg.Path() {\n\t\t\t\t\t\t// log.Printf(\"%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s\", fname, lineno, arch, fnName, pkgPath)\n\t\t\t\t\t\tfn = nil\n\t\t\t\t\t\tfnName = \"\"\n\t\t\t\t\t\tabi = \"\"\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Trim off optional ABI selector.\n\t\t\t\tfnName, abi = trimABI(fnName)\n\t\t\t\tflag := m[3]\n\t\t\t\tfn = knownFunc[fnName][arch]\n\t\t\t\tif fn != nil {\n\t\t\t\t\tsize, _ := strconv.Atoi(m[5])\n\t\t\t\t\tif size != fn.size && (flag != \"7\" && !strings.Contains(flag, \"NOSPLIT\") || size != 0) {\n\t\t\t\t\t\tbadf(\"wrong argument size %d; expected $...-%d\", size, fn.size)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlocalSize, _ = strconv.Atoi(m[4])\n\t\t\t\tlocalSize += archDef.intSize\n\t\t\t\tif archDef.lr && !strings.Contains(flag, \"NOFRAME\") {\n\t\t\t\t\t// Account for caller's saved LR\n\t\t\t\t\tlocalSize += archDef.intSize\n\t\t\t\t}\n\t\t\t\targSize, _ = strconv.Atoi(m[5])\n\t\t\t\tnoframe = strings.Contains(flag, \"NOFRAME\")\n\t\t\t\tif fn == nil && !strings.Contains(fnName, \"<>\") && !noframe {\n\t\t\t\t\tbadf(\"function %s missing Go declaration\", fnName)\n\t\t\t\t}\n\t\t\t\twroteSP = false\n\t\t\t\thaveRetArg = false\n\t\t\t\tcontinue\n\t\t\t} else if strings.Contains(line, \"TEXT\") && strings.Contains(line, \"SB\") {\n\t\t\t\t// function, but not visible from Go (didn't match asmTEXT), so stop checking\n\t\t\t\tflushRet()\n\t\t\t\tfn = nil\n\t\t\t\tfnName = \"\"\n\t\t\t\tabi = \"\"\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif strings.Contains(line, \"RET\") && !strings.Contains(line, \"(SB)\") {\n\t\t\t\t// RET f(SB) is a tail call. It is okay to not write the results.\n\t\t\t\tretLine = append(retLine, lineno)\n\t\t\t}\n\n\t\t\tif fnName == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif asmDATA.FindStringSubmatch(line) != nil {\n\t\t\t\tfn = nil\n\t\t\t}\n\n\t\t\tif archDef == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif strings.Contains(line, \", \"+archDef.stack) || strings.Contains(line, \",\\t\"+archDef.stack) || strings.Contains(line, \"NOP \"+archDef.stack) || strings.Contains(line, \"NOP\\t\"+archDef.stack) {\n\t\t\t\twroteSP = true\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif arch == \"wasm\" && strings.Contains(line, \"CallImport\") {\n\t\t\t\t// CallImport is a call out to magic that can write the result.\n\t\t\t\thaveRetArg = true\n\t\t\t}\n\n\t\t\tif abi == \"ABIInternal\" && !haveRetArg {\n\t\t\t\tfor _, ins := range archDef.writeResult {\n\t\t\t\t\tif strings.Contains(line, ins) {\n\t\t\t\t\t\thaveRetArg = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor _, reg := range archDef.retRegs {\n\t\t\t\t\tif strings.Contains(line, reg) {\n\t\t\t\t\t\thaveRetArg = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, m := range asmSP.FindAllStringSubmatch(line, -1) {\n\t\t\t\tif m[3] != archDef.stack || wroteSP || noframe {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\toff := 0\n\t\t\t\tif m[1] != \"\" {\n\t\t\t\t\toff, _ = strconv.Atoi(m[2])\n\t\t\t\t}\n\t\t\t\tif off >= localSize {\n\t\t\t\t\tif fn != nil {\n\t\t\t\t\t\tv := fn.varByOffset[off-localSize]\n\t\t\t\t\t\tif v != nil {\n\t\t\t\t\t\t\tbadf(\"%s should be %s+%d(FP)\", m[1], v.name, off-localSize)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif off >= localSize+argSize {\n\t\t\t\t\t\tbadf(\"use of %s points beyond argument frame\", m[1])\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tbadf(\"use of %s to access argument frame\", m[1])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif fn == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {\n\t\t\t\toff, _ := strconv.Atoi(m[2])\n\t\t\t\tv := fn.varByOffset[off]\n\t\t\t\tif v != nil {\n\t\t\t\t\tbadf(\"use of unnamed argument %s; offset %d is %s+%d(FP)\", m[1], off, v.name, v.off)\n\t\t\t\t} else {\n\t\t\t\t\tbadf(\"use of unnamed argument %s\", m[1])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {\n\t\t\t\tname := m[1]\n\t\t\t\toff := 0\n\t\t\t\tif m[2] != \"\" {\n\t\t\t\t\toff, _ = strconv.Atoi(m[2])\n\t\t\t\t}\n\t\t\t\tif name == \"ret\" || strings.HasPrefix(name, \"ret_\") {\n\t\t\t\t\thaveRetArg = true\n\t\t\t\t}\n\t\t\t\tv := fn.vars[name]\n\t\t\t\tif v == nil {\n\t\t\t\t\t// Allow argframe+0(FP).\n\t\t\t\t\tif name == \"argframe\" && off == 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tv = fn.varByOffset[off]\n\t\t\t\t\tif v != nil {\n\t\t\t\t\t\tbadf(\"unknown variable %s; offset %d is %s+%d(FP)\", name, off, v.name, v.off)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbadf(\"unknown variable %s\", name)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tasmCheckVar(badf, fn, line, m[0], off, v, archDef)\n\t\t\t}\n\t\t}\n\t\tflushRet()\n\t}\n\treturn nil, nil\n}\n\nfunc asmKindForType(t types.Type, size int) asmKind {\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Basic:\n\t\tswitch t.Kind() {\n\t\tcase types.String:\n\t\t\treturn asmString\n\t\tcase types.Complex64, types.Complex128:\n\t\t\treturn asmComplex\n\t\t}\n\t\treturn asmKind(size)\n\tcase *types.Pointer, *types.Chan, *types.Map, *types.Signature:\n\t\treturn asmKind(size)\n\tcase *types.Struct:\n\t\treturn asmStruct\n\tcase *types.Interface:\n\t\tif t.Empty() {\n\t\t\treturn asmEmptyInterface\n\t\t}\n\t\treturn asmInterface\n\tcase *types.Array:\n\t\treturn asmArray\n\tcase *types.Slice:\n\t\treturn asmSlice\n\t}\n\tpanic(\"unreachable\")\n}\n\n// A component is an assembly-addressable component of a composite type,\n// or a composite type itself.\ntype component struct {\n\tsize   int\n\toffset int\n\tkind   asmKind\n\ttyp    string\n\tsuffix string // Such as _base for string base, _0_lo for lo half of first element of [1]uint64 on 32 bit machine.\n\touter  string // The suffix for immediately containing composite type.\n}\n\nfunc newComponent(suffix string, kind asmKind, typ string, offset, size int, outer string) component {\n\treturn component{suffix: suffix, kind: kind, typ: typ, offset: offset, size: size, outer: outer}\n}\n\n// componentsOfType generates a list of components of type t.\n// For example, given string, the components are the string itself, the base, and the length.\nfunc componentsOfType(arch *asmArch, t types.Type) []component {\n\treturn appendComponentsRecursive(arch, t, nil, \"\", 0)\n}\n\n// appendComponentsRecursive implements componentsOfType.\n// Recursion is required to correct handle structs and arrays,\n// which can contain arbitrary other types.\nfunc appendComponentsRecursive(arch *asmArch, t types.Type, cc []component, suffix string, off int) []component {\n\ts := t.String()\n\tsize := int(arch.sizes.Sizeof(t))\n\tkind := asmKindForType(t, size)\n\tcc = append(cc, newComponent(suffix, kind, s, off, size, suffix))\n\n\tswitch kind {\n\tcase 8:\n\t\tif arch.ptrSize == 4 {\n\t\t\tw1, w2 := \"lo\", \"hi\"\n\t\t\tif arch.bigEndian {\n\t\t\t\tw1, w2 = w2, w1\n\t\t\t}\n\t\t\tcc = append(cc, newComponent(suffix+\"_\"+w1, 4, \"half \"+s, off, 4, suffix))\n\t\t\tcc = append(cc, newComponent(suffix+\"_\"+w2, 4, \"half \"+s, off+4, 4, suffix))\n\t\t}\n\n\tcase asmEmptyInterface:\n\t\tcc = append(cc, newComponent(suffix+\"_type\", asmKind(arch.ptrSize), \"interface type\", off, arch.ptrSize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_data\", asmKind(arch.ptrSize), \"interface data\", off+arch.ptrSize, arch.ptrSize, suffix))\n\n\tcase asmInterface:\n\t\tcc = append(cc, newComponent(suffix+\"_itable\", asmKind(arch.ptrSize), \"interface itable\", off, arch.ptrSize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_data\", asmKind(arch.ptrSize), \"interface data\", off+arch.ptrSize, arch.ptrSize, suffix))\n\n\tcase asmSlice:\n\t\tcc = append(cc, newComponent(suffix+\"_base\", asmKind(arch.ptrSize), \"slice base\", off, arch.ptrSize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_len\", asmKind(arch.intSize), \"slice len\", off+arch.ptrSize, arch.intSize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_cap\", asmKind(arch.intSize), \"slice cap\", off+arch.ptrSize+arch.intSize, arch.intSize, suffix))\n\n\tcase asmString:\n\t\tcc = append(cc, newComponent(suffix+\"_base\", asmKind(arch.ptrSize), \"string base\", off, arch.ptrSize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_len\", asmKind(arch.intSize), \"string len\", off+arch.ptrSize, arch.intSize, suffix))\n\n\tcase asmComplex:\n\t\tfsize := size / 2\n\t\tcc = append(cc, newComponent(suffix+\"_real\", asmKind(fsize), fmt.Sprintf(\"real(complex%d)\", size*8), off, fsize, suffix))\n\t\tcc = append(cc, newComponent(suffix+\"_imag\", asmKind(fsize), fmt.Sprintf(\"imag(complex%d)\", size*8), off+fsize, fsize, suffix))\n\n\tcase asmStruct:\n\t\ttu := t.Underlying().(*types.Struct)\n\t\tfields := make([]*types.Var, tu.NumFields())\n\t\tfor i := 0; i < tu.NumFields(); i++ {\n\t\t\tfields[i] = tu.Field(i)\n\t\t}\n\t\toffsets := arch.sizes.Offsetsof(fields)\n\t\tfor i, f := range fields {\n\t\t\tcc = appendComponentsRecursive(arch, f.Type(), cc, suffix+\"_\"+f.Name(), off+int(offsets[i]))\n\t\t}\n\n\tcase asmArray:\n\t\ttu := t.Underlying().(*types.Array)\n\t\telem := tu.Elem()\n\t\t// Calculate offset of each element array.\n\t\tfields := []*types.Var{\n\t\t\ttypes.NewField(token.NoPos, nil, \"fake0\", elem, false),\n\t\t\ttypes.NewField(token.NoPos, nil, \"fake1\", elem, false),\n\t\t}\n\t\toffsets := arch.sizes.Offsetsof(fields)\n\t\telemoff := int(offsets[1])\n\t\tfor i := 0; i < int(tu.Len()); i++ {\n\t\t\tcc = appendComponentsRecursive(arch, elem, cc, suffix+\"_\"+strconv.Itoa(i), off+i*elemoff)\n\t\t}\n\t}\n\n\treturn cc\n}\n\n// asmParseDecl parses a function decl for expected assembly variables.\nfunc asmParseDecl(pass *analysis.Pass, decl *ast.FuncDecl) map[string]*asmFunc {\n\tvar (\n\t\tarch   *asmArch\n\t\tfn     *asmFunc\n\t\toffset int\n\t)\n\n\t// addParams adds asmVars for each of the parameters in list.\n\t// isret indicates whether the list are the arguments or the return values.\n\t// TODO(adonovan): simplify by passing (*types.Signature).{Params,Results}\n\t// instead of list.\n\taddParams := func(list []*ast.Field, isret bool) {\n\t\targnum := 0\n\t\tfor _, fld := range list {\n\t\t\tt := pass.TypesInfo.Types[fld.Type].Type\n\n\t\t\t// Work around https://golang.org/issue/28277.\n\t\t\tif t == nil {\n\t\t\t\tif ell, ok := fld.Type.(*ast.Ellipsis); ok {\n\t\t\t\t\tt = types.NewSlice(pass.TypesInfo.Types[ell.Elt].Type)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\talign := int(arch.sizes.Alignof(t))\n\t\t\tsize := int(arch.sizes.Sizeof(t))\n\t\t\toffset += -offset & (align - 1)\n\t\t\tcc := componentsOfType(arch, t)\n\n\t\t\t// names is the list of names with this type.\n\t\t\tnames := fld.Names\n\t\t\tif len(names) == 0 {\n\t\t\t\t// Anonymous args will be called arg, arg1, arg2, ...\n\t\t\t\t// Similarly so for return values: ret, ret1, ret2, ...\n\t\t\t\tname := \"arg\"\n\t\t\t\tif isret {\n\t\t\t\t\tname = \"ret\"\n\t\t\t\t}\n\t\t\t\tif argnum > 0 {\n\t\t\t\t\tname += strconv.Itoa(argnum)\n\t\t\t\t}\n\t\t\t\tnames = []*ast.Ident{ast.NewIdent(name)}\n\t\t\t}\n\t\t\targnum += len(names)\n\n\t\t\t// Create variable for each name.\n\t\t\tfor _, id := range names {\n\t\t\t\tname := id.Name\n\t\t\t\tfor _, c := range cc {\n\t\t\t\t\touter := name + c.outer\n\t\t\t\t\tv := asmVar{\n\t\t\t\t\t\tname: name + c.suffix,\n\t\t\t\t\t\tkind: c.kind,\n\t\t\t\t\t\ttyp:  c.typ,\n\t\t\t\t\t\toff:  offset + c.offset,\n\t\t\t\t\t\tsize: c.size,\n\t\t\t\t\t}\n\t\t\t\t\tif vo := fn.vars[outer]; vo != nil {\n\t\t\t\t\t\tvo.inner = append(vo.inner, &v)\n\t\t\t\t\t}\n\t\t\t\t\tfn.vars[v.name] = &v\n\t\t\t\t\tfor i := 0; i < v.size; i++ {\n\t\t\t\t\t\tfn.varByOffset[v.off+i] = &v\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\toffset += size\n\t\t\t}\n\t\t}\n\t}\n\n\tm := make(map[string]*asmFunc)\n\tfor _, arch = range arches {\n\t\tfn = &asmFunc{\n\t\t\tarch:        arch,\n\t\t\tvars:        make(map[string]*asmVar),\n\t\t\tvarByOffset: make(map[int]*asmVar),\n\t\t}\n\t\toffset = 0\n\t\taddParams(decl.Type.Params.List, false)\n\t\tif decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {\n\t\t\toffset += -offset & (arch.maxAlign - 1)\n\t\t\taddParams(decl.Type.Results.List, true)\n\t\t}\n\t\tfn.size = offset\n\t\tm[arch.name] = fn\n\t}\n\n\treturn m\n}\n\n// asmCheckVar checks a single variable reference.\nfunc asmCheckVar(badf func(string, ...any), fn *asmFunc, line, expr string, off int, v *asmVar, archDef *asmArch) {\n\tm := asmOpcode.FindStringSubmatch(line)\n\tif m == nil {\n\t\tif !strings.HasPrefix(strings.TrimSpace(line), \"//\") {\n\t\t\tbadf(\"cannot find assembly opcode\")\n\t\t}\n\t\treturn\n\t}\n\n\taddr := strings.HasPrefix(expr, \"$\")\n\n\t// Determine operand sizes from instruction.\n\t// Typically the suffix suffices, but there are exceptions.\n\tvar src, dst, kind asmKind\n\top := m[1]\n\tswitch fn.arch.name + \".\" + op {\n\tcase \"386.FMOVLP\":\n\t\tsrc, dst = 8, 4\n\tcase \"arm.MOVD\":\n\t\tsrc = 8\n\tcase \"arm.MOVW\":\n\t\tsrc = 4\n\tcase \"arm.MOVH\", \"arm.MOVHU\":\n\t\tsrc = 2\n\tcase \"arm.MOVB\", \"arm.MOVBU\":\n\t\tsrc = 1\n\t// LEA* opcodes don't really read the second arg.\n\t// They just take the address of it.\n\tcase \"386.LEAL\":\n\t\tdst = 4\n\t\taddr = true\n\tcase \"amd64.LEAQ\":\n\t\tdst = 8\n\t\taddr = true\n\tdefault:\n\t\tswitch fn.arch.name {\n\t\tcase \"386\", \"amd64\":\n\t\t\tif strings.HasPrefix(op, \"F\") && (strings.HasSuffix(op, \"D\") || strings.HasSuffix(op, \"DP\")) {\n\t\t\t\t// FMOVDP, FXCHD, etc\n\t\t\t\tsrc = 8\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif strings.HasPrefix(op, \"P\") && strings.HasSuffix(op, \"RD\") {\n\t\t\t\t// PINSRD, PEXTRD, etc\n\t\t\t\tsrc = 4\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif strings.HasPrefix(op, \"F\") && (strings.HasSuffix(op, \"F\") || strings.HasSuffix(op, \"FP\")) {\n\t\t\t\t// FMOVFP, FXCHF, etc\n\t\t\t\tsrc = 4\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif strings.HasSuffix(op, \"SD\") {\n\t\t\t\t// MOVSD, SQRTSD, etc\n\t\t\t\tsrc = 8\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif strings.HasSuffix(op, \"SS\") {\n\t\t\t\t// MOVSS, SQRTSS, etc\n\t\t\t\tsrc = 4\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif op == \"MOVO\" || op == \"MOVOU\" {\n\t\t\t\tsrc = 16\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif strings.HasPrefix(op, \"SET\") {\n\t\t\t\t// SETEQ, etc\n\t\t\t\tsrc = 1\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tswitch op[len(op)-1] {\n\t\t\tcase 'B':\n\t\t\t\tsrc = 1\n\t\t\tcase 'W':\n\t\t\t\tsrc = 2\n\t\t\tcase 'L':\n\t\t\t\tsrc = 4\n\t\t\tcase 'D', 'Q':\n\t\t\t\tsrc = 8\n\t\t\t}\n\t\tcase \"ppc64\", \"ppc64le\":\n\t\t\t// Strip standard suffixes to reveal size letter.\n\t\t\tm := ppc64Suff.FindStringSubmatch(op)\n\t\t\tif m != nil {\n\t\t\t\tswitch m[1][0] {\n\t\t\t\tcase 'B':\n\t\t\t\t\tsrc = 1\n\t\t\t\tcase 'H':\n\t\t\t\t\tsrc = 2\n\t\t\t\tcase 'W':\n\t\t\t\t\tsrc = 4\n\t\t\t\tcase 'D':\n\t\t\t\t\tsrc = 8\n\t\t\t\t}\n\t\t\t}\n\t\tcase \"loong64\", \"mips\", \"mipsle\", \"mips64\", \"mips64le\":\n\t\t\tswitch op {\n\t\t\tcase \"MOVB\", \"MOVBU\":\n\t\t\t\tsrc = 1\n\t\t\tcase \"MOVH\", \"MOVHU\":\n\t\t\t\tsrc = 2\n\t\t\tcase \"MOVW\", \"MOVWU\", \"MOVF\":\n\t\t\t\tsrc = 4\n\t\t\tcase \"MOVV\", \"MOVD\":\n\t\t\t\tsrc = 8\n\t\t\t}\n\t\tcase \"s390x\":\n\t\t\tswitch op {\n\t\t\tcase \"MOVB\", \"MOVBZ\":\n\t\t\t\tsrc = 1\n\t\t\tcase \"MOVH\", \"MOVHZ\":\n\t\t\t\tsrc = 2\n\t\t\tcase \"MOVW\", \"MOVWZ\", \"FMOVS\":\n\t\t\t\tsrc = 4\n\t\t\tcase \"MOVD\", \"FMOVD\":\n\t\t\t\tsrc = 8\n\t\t\t}\n\t\t}\n\t}\n\tif dst == 0 {\n\t\tdst = src\n\t}\n\n\t// Determine whether the match we're holding\n\t// is the first or second argument.\n\tif strings.Index(line, expr) > strings.Index(line, \",\") {\n\t\tkind = dst\n\t} else {\n\t\tkind = src\n\t}\n\n\tvk := v.kind\n\tvs := v.size\n\tvt := v.typ\n\tswitch vk {\n\tcase asmInterface, asmEmptyInterface, asmString, asmSlice:\n\t\t// allow reference to first word (pointer)\n\t\tvk = v.inner[0].kind\n\t\tvs = v.inner[0].size\n\t\tvt = v.inner[0].typ\n\tcase asmComplex:\n\t\t// Allow a single instruction to load both parts of a complex.\n\t\tif int(kind) == vs {\n\t\t\tkind = asmComplex\n\t\t}\n\t}\n\tif addr {\n\t\tvk = asmKind(archDef.ptrSize)\n\t\tvs = archDef.ptrSize\n\t\tvt = \"address\"\n\t}\n\n\tif off != v.off {\n\t\tvar inner bytes.Buffer\n\t\tfor i, vi := range v.inner {\n\t\t\tif len(v.inner) > 1 {\n\t\t\t\tfmt.Fprintf(&inner, \",\")\n\t\t\t}\n\t\t\tfmt.Fprintf(&inner, \" \")\n\t\t\tif i == len(v.inner)-1 {\n\t\t\t\tfmt.Fprintf(&inner, \"or \")\n\t\t\t}\n\t\t\tfmt.Fprintf(&inner, \"%s+%d(FP)\", vi.name, vi.off)\n\t\t}\n\t\tbadf(\"invalid offset %s; expected %s+%d(FP)%s\", expr, v.name, v.off, inner.String())\n\t\treturn\n\t}\n\tif kind != 0 && kind != vk {\n\t\tvar inner bytes.Buffer\n\t\tif len(v.inner) > 0 {\n\t\t\tfmt.Fprintf(&inner, \" containing\")\n\t\t\tfor i, vi := range v.inner {\n\t\t\t\tif i > 0 && len(v.inner) > 2 {\n\t\t\t\t\tfmt.Fprintf(&inner, \",\")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&inner, \" \")\n\t\t\t\tif i > 0 && i == len(v.inner)-1 {\n\t\t\t\t\tfmt.Fprintf(&inner, \"and \")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&inner, \"%s+%d(FP)\", vi.name, vi.off)\n\t\t\t}\n\t\t}\n\t\tbadf(\"invalid %s of %s; %s is %d-byte value%s\", op, expr, vt, vs, inner.String())\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/asmdecl_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage asmdecl_test\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/asmdecl\"\n)\n\nvar goosarches = []string{\n\t\"linux/amd64\", // asm1.s, asm4.s\n\t\"linux/386\",   // asm2.s\n\t\"linux/arm\",   // asm3.s\n\t// TODO: skip test on loong64 until go toolchain supported loong64.\n\t// \"linux/loong64\", // asm10.s\n\t\"linux/mips64\",  // asm5.s\n\t\"linux/s390x\",   // asm6.s\n\t\"linux/ppc64\",   // asm7.s\n\t\"linux/mips\",    // asm8.s,\n\t\"js/wasm\",       // asm9.s\n\t\"linux/riscv64\", // asm11.s\n}\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tfor _, goosarch := range goosarches {\n\t\tt.Run(goosarch, func(t *testing.T) {\n\t\t\ti := strings.Index(goosarch, \"/\")\n\t\t\tos.Setenv(\"GOOS\", goosarch[:i])\n\t\t\tos.Setenv(\"GOARCH\", goosarch[i+1:])\n\t\t\tanalysistest.Run(t, testdata, asmdecl.Analyzer, \"a\")\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains declarations to test the assembly in test_asm.s.\n\npackage a\n\ntype S struct {\n\ti int32\n\tb bool\n\ts string\n}\n\nfunc arg1(x int8, y uint8)\nfunc arg2(x int16, y uint16)\nfunc arg4(x int32, y uint32)\nfunc arg8(x int64, y uint64)\nfunc argint(x int, y uint)\nfunc argptr(x *byte, y *byte, c chan int, m map[int]int, f func())\nfunc argstring(x, y string)\nfunc argslice(x, y []string)\nfunc argiface(x interface{}, y interface {\n\tm()\n})\nfunc argcomplex(x complex64, y complex128)\nfunc argstruct(x S, y struct{})\nfunc argarray(x [2]S)\nfunc returnint() int\nfunc returnbyte(x int) byte\nfunc returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)\nfunc returnintmissing() int\nfunc leaf(x, y int) int\n\nfunc noprof(x int)\nfunc dupok(x int)\nfunc nosplit(x int)\nfunc rodata(x int)\nfunc noptr(x int)\nfunc wrapper(x int)\n\nfunc f15271() (x uint32)\nfunc f17584(x float32, y complex64)\nfunc f29318(x [2][2]uint64)\n\nfunc noframe1(x int32)\nfunc noframe2(x int32)\n\nfunc fvariadic(int, ...int)\n\nfunc pickStableABI(x int)\nfunc pickInternalABI(x int)\nfunc pickFutureABI(x int)\n\nfunc returnABIInternal() int\nfunc returnmissingABIInternal() int\nfunc returnsyscallABIInternal() int\n\nfunc retjmp() int\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm1.s",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build amd64\n\n// Commented-out code should be ignored.\n//\n//\tTEXT ·unknown(SB),0,$0\n//\t\tRET\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), AX\n\t// MOVB x+0(FP), AX // commented out instructions used to panic\n\tMOVB\ty+1(FP), BX\n\tMOVW\tx+0(FP), AX // want `\\[amd64\\] arg1: invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVW\ty+1(FP), AX // want `invalid MOVW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVL\ty+1(FP), AX // want `invalid MOVL of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVQ\ty+1(FP), AX // want `invalid MOVQ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), AX // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVB\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tTESTB\tx+0(FP), AX\n\tTESTB\ty+1(FP), BX\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTW\ty+1(FP), AX // want `invalid TESTW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTL\ty+1(FP), AX // want `invalid TESTL of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTQ\ty+1(FP), AX // want `invalid TESTQ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTB\tx+1(FP), AX // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTB\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t8(SP), AX // want `8\\(SP\\) should be x\\+0\\(FP\\)`\n\tMOVB\t9(SP), AX // want `9\\(SP\\) should be y\\+1\\(FP\\)`\n\tMOVB\t10(SP), AX // want `use of 10\\(SP\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVB\tx+0(FP), AX // want `arg2: invalid MOVB of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), AX // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+2(FP), BX\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVL\ty+2(FP), AX // want `invalid MOVL of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVQ\ty+2(FP), AX // want `invalid MOVQ of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVW\tx+2(FP), AX // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTB\ty+2(FP), AX // want `invalid TESTB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTW\tx+0(FP), AX\n\tTESTW\ty+2(FP), BX\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTL\ty+2(FP), AX // want `invalid TESTL of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTQ\ty+2(FP), AX // want `invalid TESTQ of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTW\tx+2(FP), AX // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTW\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVW\ty+4(FP), AX // want `invalid MOVW of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVL\ty+4(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVQ\ty+4(FP), AX // want `invalid MOVQ of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVL\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVL\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTB\ty+4(FP), BX // want `invalid TESTB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTW\ty+4(FP), AX // want `invalid TESTW of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTL\tx+0(FP), AX\n\tTESTL\ty+4(FP), AX\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTQ\ty+4(FP), AX // want `invalid TESTQ of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTL\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTL\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), BX // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVL\ty+8(FP), AX // want `invalid MOVL of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVQ\tx+0(FP), AX\n\tMOVQ\ty+8(FP), AX\n\tMOVQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tTESTB\ty+8(FP), BX // want `invalid TESTB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tTESTW\ty+8(FP), AX // want `invalid TESTW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int64 is 8-byte value`\n\tTESTL\ty+8(FP), AX // want `invalid TESTL of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tTESTQ\tx+0(FP), AX\n\tTESTQ\ty+8(FP), AX\n\tTESTQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVB\ty+8(FP), BX // want `invalid MOVB of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVL\ty+8(FP), AX // want `invalid MOVL of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVQ\tx+0(FP), AX\n\tMOVQ\ty+8(FP), AX\n\tMOVQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int is 8-byte value`\n\tTESTB\ty+8(FP), BX // want `invalid TESTB of y\\+8\\(FP\\); uint is 8-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int is 8-byte value`\n\tTESTW\ty+8(FP), AX // want `invalid TESTW of y\\+8\\(FP\\); uint is 8-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int is 8-byte value`\n\tTESTL\ty+8(FP), AX // want `invalid TESTL of y\\+8\\(FP\\); uint is 8-byte value`\n\tTESTQ\tx+0(FP), AX\n\tTESTQ\ty+8(FP), AX\n\tTESTQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-40`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVB\ty+8(FP), BX // want `invalid MOVB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVL\ty+8(FP), AX // want `invalid MOVL of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVQ\tx+0(FP), AX\n\tMOVQ\ty+8(FP), AX\n\tMOVQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tTESTB\ty+8(FP), BX // want `invalid TESTB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tTESTW\ty+8(FP), AX // want `invalid TESTW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tTESTL\ty+8(FP), AX // want `invalid TESTL of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tTESTQ\tx+0(FP), AX\n\tTESTQ\ty+8(FP), AX\n\tTESTQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVL\tc+16(FP), AX // want `invalid MOVL of c\\+16\\(FP\\); chan int is 8-byte value`\n\tMOVL\tm+24(FP), AX // want `invalid MOVL of m\\+24\\(FP\\); map\\[int\\]int is 8-byte value`\n\tMOVL\tf+32(FP), AX // want `invalid MOVL of f\\+32\\(FP\\); func\\(\\) is 8-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \\$\\.\\.\\.-32`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); string base is 8-byte value`\n\tLEAQ\tx+0(FP), AX // ok\n\tMOVQ\tx+0(FP), AX\n\tMOVW\tx_base+0(FP), AX // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVL\tx_base+0(FP), AX // want `invalid MOVL of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVQ\tx_base+0(FP), AX\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVL\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+8(FP), AX // want `invalid MOVW of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVL\tx_len+8(FP), AX // want `invalid MOVL of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVQ\tx_len+8(FP), AX\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+16\\(FP\\)`\n\tMOVQ\ty_len+8(FP), AX // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+24\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVQ\tx+0(FP), AX\n\tMOVW\tx_base+0(FP), AX // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVL\tx_base+0(FP), AX // want `invalid MOVL of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVQ\tx_base+0(FP), AX\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVL\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+8(FP), AX // want `invalid MOVW of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVL\tx_len+8(FP), AX // want `invalid MOVL of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVQ\tx_len+8(FP), AX\n\tMOVW\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVL\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVQ\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVW\tx_cap+16(FP), AX // want `invalid MOVW of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVL\tx_cap+16(FP), AX // want `invalid MOVL of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVQ\tx_cap+16(FP), AX\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+24\\(FP\\)`\n\tMOVQ\ty_len+8(FP), AX // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+32\\(FP\\)`\n\tMOVQ\ty_cap+16(FP), AX // want `invalid offset y_cap\\+16\\(FP\\); expected y_cap\\+40\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-32\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVQ\tx+0(FP), AX\n\tMOVW\tx_type+0(FP), AX // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVL\tx_type+0(FP), AX // want `invalid MOVL of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVQ\tx_type+0(FP), AX\n\tMOVQ\tx_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVQ\tx_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVW\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVL\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVQ\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVW\tx_data+8(FP), AX // want `invalid MOVW of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVL\tx_data+8(FP), AX // want `invalid MOVL of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVQ\tx_data+8(FP), AX\n\tMOVW\ty+16(FP), AX // want `invalid MOVW of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVL\ty+16(FP), AX // want `invalid MOVL of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVQ\ty+16(FP), AX\n\tMOVW\ty_itable+16(FP), AX // want `invalid MOVW of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVL\ty_itable+16(FP), AX // want `invalid MOVL of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVQ\ty_itable+16(FP), AX\n\tMOVQ\ty_type+16(FP), AX // want `unknown variable y_type; offset 16 is y_itable\\+16\\(FP\\)`\n\tMOVW\ty_data+16(FP), AX // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVL\ty_data+16(FP), AX // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVQ\ty_data+16(FP), AX // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVW\ty_data+24(FP), AX // want `invalid MOVW of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVL\ty_data+24(FP), AX // want `invalid MOVL of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVQ\ty_data+24(FP), AX\n\tRET\n\nTEXT ·argcomplex(SB),0,$24 // want `wrong argument size 0; expected \\$\\.\\.\\.-24`\n\tMOVSS\tx+0(FP), X0 // want `invalid MOVSS of x\\+0\\(FP\\); complex64 is 8-byte value containing x_real\\+0\\(FP\\) and x_imag\\+4\\(FP\\)`\n\tMOVSS\tx_real+0(FP), X0\n\tMOVSD\tx_real+0(FP), X0 // want `invalid MOVSD of x_real\\+0\\(FP\\); real\\(complex64\\) is 4-byte value`\n\tMOVSS\tx_real+4(FP), X0 // want `invalid offset x_real\\+4\\(FP\\); expected x_real\\+0\\(FP\\)`\n\tMOVSS\tx_imag+4(FP), X0\n\tMOVSD\tx_imag+4(FP), X0 // want `invalid MOVSD of x_imag\\+4\\(FP\\); imag\\(complex64\\) is 4-byte value`\n\tMOVSS\tx_imag+8(FP), X0 // want `invalid offset x_imag\\+8\\(FP\\); expected x_imag\\+4\\(FP\\)`\n\tMOVSD\ty+8(FP), X0 // want `invalid MOVSD of y\\+8\\(FP\\); complex128 is 16-byte value containing y_real\\+8\\(FP\\) and y_imag\\+16\\(FP\\)`\n\tMOVSS\ty_real+8(FP), X0 // want `invalid MOVSS of y_real\\+8\\(FP\\); real\\(complex128\\) is 8-byte value`\n\tMOVSD\ty_real+8(FP), X0\n\tMOVSS\ty_real+16(FP), X0 // want `invalid offset y_real\\+16\\(FP\\); expected y_real\\+8\\(FP\\)`\n\tMOVSS\ty_imag+16(FP), X0 // want `invalid MOVSS of y_imag\\+16\\(FP\\); imag\\(complex128\\) is 8-byte value`\n\tMOVSD\ty_imag+16(FP), X0\n\tMOVSS\ty_imag+24(FP), X0 // want `invalid offset y_imag\\+24\\(FP\\); expected y_imag\\+16\\(FP\\)`\n\t// Loading both parts of a complex is ok: see issue 35264.\n\tMOVSD\tx+0(FP), X0\n\tMOVO\ty+8(FP), X0\n\tMOVOU\ty+8(FP), X0\n\t// These are not ok.\n\tMOVO\tx+0(FP), X0 // want `invalid MOVO of x\\+0\\(FP\\); complex64 is 8-byte value containing x_real\\+0\\(FP\\) and x_imag\\+4\\(FP\\)`\n\tMOVOU\tx+0(FP), X0 // want `invalid MOVOU of x\\+0\\(FP\\); complex64 is 8-byte value containing x_real\\+0\\(FP\\) and x_imag\\+4\\(FP\\)`\n\tRET\n\nTEXT ·argstruct(SB),0,$64 // want `wrong argument size 0; expected \\$\\.\\.\\.-24`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); a.S is 24-byte value`\n\tMOVQ\tx_i+0(FP), AX // want `invalid MOVQ of x_i\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVQ\tx_b+0(FP), AX // want `invalid offset x_b\\+0\\(FP\\); expected x_b\\+4\\(FP\\)`\n\tMOVQ\tx_s+8(FP), AX\n\tMOVQ\tx_s_base+8(FP), AX\n\tMOVQ\tx_s+16(FP), AX // want `invalid offset x_s\\+16\\(FP\\); expected x_s\\+8\\(FP\\), x_s_base\\+8\\(FP\\), or x_s_len\\+16\\(FP\\)`\n\tMOVQ\tx_s_len+16(FP), AX\n\tRET\n\nTEXT ·argarray(SB),0,$64 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); \\[2\\]a.S is 48-byte value`\n\tMOVQ\tx_0_i+0(FP), AX // want `invalid MOVQ of x_0_i\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVQ\tx_0_b+0(FP), AX // want `invalid offset x_0_b\\+0\\(FP\\); expected x_0_b\\+4\\(FP\\)`\n\tMOVQ\tx_0_s+8(FP), AX\n\tMOVQ\tx_0_s_base+8(FP), AX\n\tMOVQ\tx_0_s+16(FP), AX // want `invalid offset x_0_s\\+16\\(FP\\); expected x_0_s\\+8\\(FP\\), x_0_s_base\\+8\\(FP\\), or x_0_s_len\\+16\\(FP\\)`\n\tMOVQ\tx_0_s_len+16(FP), AX\n\tMOVB\tfoo+25(FP), AX // want `unknown variable foo; offset 25 is x_1_i\\+24\\(FP\\)`\n\tMOVQ\tx_1_s+32(FP), AX\n\tMOVQ\tx_1_s_base+32(FP), AX\n\tMOVQ\tx_1_s+40(FP), AX // want `invalid offset x_1_s\\+40\\(FP\\); expected x_1_s\\+32\\(FP\\), x_1_s_base\\+32\\(FP\\), or x_1_s_len\\+40\\(FP\\)`\n\tMOVQ\tx_1_s_len+40(FP), AX\n\tRET\n\nTEXT ·returnint(SB),0,$0-8\n\tMOVB\tAX, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\tAX, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVL\tAX, ret+0(FP) // want `invalid MOVL of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVQ\tAX, ret+0(FP)\n\tMOVQ\tAX, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVQ\tAX, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-9\n\tMOVQ\tx+0(FP), AX\n\tMOVB\tAX, ret+8(FP)\n\tMOVW\tAX, ret+8(FP) // want `invalid MOVW of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVL\tAX, ret+8(FP) // want `invalid MOVL of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVQ\tAX, ret+8(FP) // want `invalid MOVQ of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVB\tAX, ret+7(FP) // want `invalid offset ret\\+7\\(FP\\); expected ret\\+8\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-41\n\tMOVB\tx+0(FP), AX\n\tMOVQ\tAX, r1+8(FP)\n\tMOVW\tAX, r2+16(FP)\n\tMOVQ\tAX, r3+24(FP)\n\tMOVQ\tAX, r3_base+24(FP)\n\tMOVQ\tAX, r3_len+32(FP)\n\tMOVB\tAX, r4+40(FP)\n\tMOVL\tAX, r1+8(FP) // want `invalid MOVL of r1\\+8\\(FP\\); int is 8-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-8\n\tRET // want `RET without writing to 8-byte ret\\+0\\(FP\\)`\n\n// issue 15271\nTEXT ·f15271(SB), NOSPLIT, $0-4\n    // Stick 123 into the low 32 bits of X0.\n    MOVQ $123, AX\n    PINSRD $0, AX, X0\n\n    // Return them.\n    PEXTRD $0, X0, x+0(FP)\n    RET\n\n// issue 17584\nTEXT ·f17584(SB), NOSPLIT, $12\n\tMOVSS\tx+0(FP), X0\n\tMOVSS\ty_real+4(FP), X0\n\tMOVSS\ty_imag+8(FP), X0\n\tRET\n\n// issue 29318\nTEXT ·f29318(SB), NOSPLIT, $32\n\tMOVQ\tx_0_1+8(FP), AX\n\tMOVQ\tx_1_1+24(FP), CX\n\tRET\n\n// ABI selector\nTEXT ·pickStableABI<ABI0>(SB), NOSPLIT, $32\n\tMOVQ\tx+0(FP), AX\n\tRET\n\n// ABI selector\nTEXT ·pickInternalABI<ABIInternal>(SB), NOSPLIT, $32\n\tMOVQ\tx+0(FP), AX\n\tRET\n\n// ABI selector\nTEXT ·pickFutureABI<ABISomethingNotyetInvented>(SB), NOSPLIT, $32\n\tMOVQ\tx+0(FP), AX\n\tRET\n\n// writing to result in ABIInternal function\nTEXT ·returnABIInternal<ABIInternal>(SB), NOSPLIT, $32\n\tMOVQ\t$123, AX\n\tRET\nTEXT ·returnmissingABIInternal<ABIInternal>(SB), NOSPLIT, $32\n\tMOVQ\t$123, CX\n\tRET // want `RET without writing to result register`\n\n// issue 69352\nTEXT ·returnsyscallABIInternal<ABIInternal>(SB), NOSPLIT, $0\n\tMOVQ\t$123, CX\n\tSYSCALL\n\tRET\n\n// return jump\nTEXT ·retjmp(SB), NOSPLIT, $0-8\n\tRET\tretjmp1(SB) // It's okay to not write results if there's a tail call.\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm10.s",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build loong64\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), R19\n\tMOVBU\ty+1(FP), R18\n\tMOVH\tx+0(FP), R19 // want `\\[loong64\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVHU\ty+1(FP), R19 // want `invalid MOVHU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVWU\ty+1(FP), R19 // want `invalid MOVWU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVV\tx+0(FP), R19 // want `invalid MOVV of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVV\ty+1(FP), R19 // want `invalid MOVV of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), R19 // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVBU\ty+2(FP), R19 // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t16(R3), R19 // want `16\\(R3\\) should be x\\+0\\(FP\\)`\n\tMOVB\t17(R3), R19 // want `17\\(R3\\) should be y\\+1\\(FP\\)`\n\tMOVB\t18(R3), R19 // want `use of 18\\(R3\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVBU\tx+0(FP), R19 // want `arg2: invalid MOVBU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), R19 // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+0(FP), R19\n\tMOVH\ty+2(FP), R18\n\tMOVWU\tx+0(FP), R19 // want `invalid MOVWU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), R19 // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVV\tx+0(FP), R19 // want `invalid MOVV of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVV\ty+2(FP), R19 // want `invalid MOVV of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+2(FP), R19 // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), R19 // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R19 // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), R18 // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), R19 // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), R19\n\tMOVW\ty+4(FP), R19\n\tMOVV\tx+0(FP), R19 // want `invalid MOVV of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVV\ty+4(FP), R19 // want `invalid MOVV of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+4(FP), R19 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R19 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R19 // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), R18 // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), R19 // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), R19 // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVV\ty+8(FP), R19\n\tMOVV\tx+8(FP), R19 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R19 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R19 // want `invalid MOVB of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVB\ty+8(FP), R18 // want `invalid MOVB of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\ty+8(FP), R19 // want `invalid MOVH of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\ty+8(FP), R19 // want `invalid MOVW of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVV\ty+8(FP), R19\n\tMOVV\tx+8(FP), R19 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R19 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-40`\n\tMOVB\tx+0(FP), R19 // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVB\ty+8(FP), R18 // want `invalid MOVB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\ty+8(FP), R19 // want `invalid MOVH of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\ty+8(FP), R19 // want `invalid MOVW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVV\ty+8(FP), R19\n\tMOVV\tx+8(FP), R19 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R19 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVW\tc+16(FP), R19 // want `invalid MOVW of c\\+16\\(FP\\); chan int is 8-byte value`\n\tMOVW\tm+24(FP), R19 // want `invalid MOVW of m\\+24\\(FP\\); map\\[int\\]int is 8-byte value`\n\tMOVW\tf+32(FP), R19 // want `invalid MOVW of f\\+32\\(FP\\); func\\(\\) is 8-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \\$\\.\\.\\.-32`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVH\tx_base+0(FP), R19 // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx_base+0(FP), R19 // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVV\tx_base+0(FP), R19\n\tMOVH\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVV\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R19 // want `invalid MOVH of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVW\tx_len+8(FP), R19 // want `invalid MOVW of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVV\tx_len+8(FP), R19\n\tMOVV\ty+0(FP), R19 // want `invalid offset y\\+0\\(FP\\); expected y\\+16\\(FP\\)`\n\tMOVV\ty_len+8(FP), R19 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+24\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVH\tx_base+0(FP), R19 // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx_base+0(FP), R19 // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVV\tx_base+0(FP), R19\n\tMOVH\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVV\tx_len+0(FP), R19 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R19 // want `invalid MOVH of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVW\tx_len+8(FP), R19 // want `invalid MOVW of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVV\tx_len+8(FP), R19\n\tMOVH\tx_cap+0(FP), R19 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVW\tx_cap+0(FP), R19 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVV\tx_cap+0(FP), R19 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVH\tx_cap+16(FP), R19 // want `invalid MOVH of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVW\tx_cap+16(FP), R19 // want `invalid MOVW of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVV\tx_cap+16(FP), R19\n\tMOVV\ty+0(FP), R19 // want `invalid offset y\\+0\\(FP\\); expected y\\+24\\(FP\\)`\n\tMOVV\ty_len+8(FP), R19 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+32\\(FP\\)`\n\tMOVV\ty_cap+16(FP), R19 // want `invalid offset y_cap\\+16\\(FP\\); expected y_cap\\+40\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-32\n\tMOVH\tx+0(FP), R19 // want `invalid MOVH of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx+0(FP), R19 // want `invalid MOVW of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVV\tx+0(FP), R19\n\tMOVH\tx_type+0(FP), R19 // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx_type+0(FP), R19 // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVV\tx_type+0(FP), R19\n\tMOVV\tx_itable+0(FP), R19 // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVV\tx_itable+1(FP), R19 // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), R19 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVW\tx_data+0(FP), R19 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVV\tx_data+0(FP), R19 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVH\tx_data+8(FP), R19 // want `invalid MOVH of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVW\tx_data+8(FP), R19 // want `invalid MOVW of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVV\tx_data+8(FP), R19\n\tMOVH\ty+16(FP), R19 // want `invalid MOVH of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty+16(FP), R19 // want `invalid MOVW of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVV\ty+16(FP), R19\n\tMOVH\ty_itable+16(FP), R19 // want `invalid MOVH of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty_itable+16(FP), R19 // want `invalid MOVW of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVV\ty_itable+16(FP), R19\n\tMOVV\ty_type+16(FP), R19 // want `unknown variable y_type; offset 16 is y_itable\\+16\\(FP\\)`\n\tMOVH\ty_data+16(FP), R19 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVW\ty_data+16(FP), R19 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVV\ty_data+16(FP), R19 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVH\ty_data+24(FP), R19 // want `invalid MOVH of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVW\ty_data+24(FP), R19 // want `invalid MOVW of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVV\ty_data+24(FP), R19\n\tRET\n\nTEXT ·returnint(SB),0,$0-8\n\tMOVB\tR19, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\tR19, ret+0(FP) // want `invalid MOVH of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\tR19, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVV\tR19, ret+0(FP)\n\tMOVV\tR19, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVV\tR19, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-9\n\tMOVV\tx+0(FP), R19\n\tMOVB\tR19, ret+8(FP)\n\tMOVH\tR19, ret+8(FP) // want `invalid MOVH of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVW\tR19, ret+8(FP) // want `invalid MOVW of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVV\tR19, ret+8(FP) // want `invalid MOVV of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVB\tR19, ret+7(FP) // want `invalid offset ret\\+7\\(FP\\); expected ret\\+8\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-41\n\tMOVB\tx+0(FP), R19\n\tMOVV\tR19, r1+8(FP)\n\tMOVH\tR19, r2+16(FP)\n\tMOVV\tR19, r3+24(FP)\n\tMOVV\tR19, r3_base+24(FP)\n\tMOVV\tR19, r3_len+32(FP)\n\tMOVB\tR19, r4+40(FP)\n\tMOVW\tR19, r1+8(FP) // want `invalid MOVW of r1\\+8\\(FP\\); int is 8-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-8\n\tRET // want `RET without writing to 8-byte ret\\+0\\(FP\\)`\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm11.s",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build riscv64\n\n// writing to result in ABIInternal function\nTEXT ·returnABIInternal<ABIInternal>(SB), NOSPLIT, $8\n\tMOV\t$123, X10\n\tRET\nTEXT ·returnmissingABIInternal<ABIInternal>(SB), NOSPLIT, $8\n\tMOV\t$123, X20\n\tRET // want `RET without writing to result register`\n\n// issue 69352\nTEXT ·returnsyscallABIInternal<ABIInternal>(SB), NOSPLIT, $0\n\tMOV\t$123, X20\n\tECALL\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm2.s",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build 386\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), AX\n\tMOVB\ty+1(FP), BX\n\tMOVW\tx+0(FP), AX // want `\\[386\\] arg1: invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVW\ty+1(FP), AX // want `invalid MOVW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVL\ty+1(FP), AX // want `invalid MOVL of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVQ\ty+1(FP), AX // want `invalid MOVQ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), AX // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVB\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tTESTB\tx+0(FP), AX\n\tTESTB\ty+1(FP), BX\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTW\ty+1(FP), AX // want `invalid TESTW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTL\ty+1(FP), AX // want `invalid TESTL of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int8 is 1-byte value`\n\tTESTQ\ty+1(FP), AX // want `invalid TESTQ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tTESTB\tx+1(FP), AX // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTB\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t4(SP), AX // want `4\\(SP\\) should be x\\+0\\(FP\\)`\n\tMOVB\t5(SP), AX // want `5\\(SP\\) should be y\\+1\\(FP\\)`\n\tMOVB\t6(SP), AX // want `use of 6\\(SP\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVB\tx+0(FP), AX // want `arg2: invalid MOVB of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), AX // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+2(FP), BX\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVL\ty+2(FP), AX // want `invalid MOVL of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVQ\ty+2(FP), AX // want `invalid MOVQ of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVW\tx+2(FP), AX // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTB\ty+2(FP), AX // want `invalid TESTB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTW\tx+0(FP), AX\n\tTESTW\ty+2(FP), BX\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTL\ty+2(FP), AX // want `invalid TESTL of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tTESTQ\ty+2(FP), AX // want `invalid TESTQ of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tTESTW\tx+2(FP), AX // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTW\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVW\ty+4(FP), AX // want `invalid MOVW of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVL\ty+4(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVQ\ty+4(FP), AX // want `invalid MOVQ of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVL\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVL\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTB\ty+4(FP), BX // want `invalid TESTB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTW\ty+4(FP), AX // want `invalid TESTW of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTL\tx+0(FP), AX\n\tTESTL\ty+4(FP), AX\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int32 is 4-byte value`\n\tTESTQ\ty+4(FP), AX // want `invalid TESTQ of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tTESTL\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTL\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), BX // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVL\tx+0(FP), AX // want `invalid MOVL of x\\+0\\(FP\\); int64 is 8-byte value containing x_lo\\+0\\(FP\\) and x_hi\\+4\\(FP\\)`\n\tMOVL\tx_lo+0(FP), AX\n\tMOVL\tx_hi+4(FP), AX\n\tMOVL\ty+8(FP), AX // want `invalid MOVL of y\\+8\\(FP\\); uint64 is 8-byte value containing y_lo\\+8\\(FP\\) and y_hi\\+12\\(FP\\)`\n\tMOVL\ty_lo+8(FP), AX\n\tMOVL\ty_hi+12(FP), AX\n\tMOVQ\tx+0(FP), AX\n\tMOVQ\ty+8(FP), AX\n\tMOVQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tTESTB\ty+8(FP), BX // want `invalid TESTB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tTESTW\ty+8(FP), AX // want `invalid TESTW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tTESTL\tx+0(FP), AX // want `invalid TESTL of x\\+0\\(FP\\); int64 is 8-byte value containing x_lo\\+0\\(FP\\) and x_hi\\+4\\(FP\\)`\n\tTESTL\ty+8(FP), AX // want `invalid TESTL of y\\+8\\(FP\\); uint64 is 8-byte value containing y_lo\\+8\\(FP\\) and y_hi\\+12\\(FP\\)`\n\tTESTQ\tx+0(FP), AX\n\tTESTQ\ty+8(FP), AX\n\tTESTQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVW\ty+4(FP), AX // want `invalid MOVW of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVL\ty+4(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVQ\ty+4(FP), AX // want `invalid MOVQ of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); int is 4-byte value`\n\tTESTB\ty+4(FP), BX // want `invalid TESTB of y\\+4\\(FP\\); uint is 4-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); int is 4-byte value`\n\tTESTW\ty+4(FP), AX // want `invalid TESTW of y\\+4\\(FP\\); uint is 4-byte value`\n\tTESTL\tx+0(FP), AX\n\tTESTL\ty+4(FP), AX\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); int is 4-byte value`\n\tTESTQ\ty+4(FP), AX // want `invalid TESTQ of y\\+4\\(FP\\); uint is 4-byte value`\n\tTESTQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-20`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVW\ty+4(FP), AX // want `invalid MOVW of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVL\ty+4(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVQ\ty+4(FP), AX // want `invalid MOVQ of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tTESTB\tx+0(FP), AX // want `invalid TESTB of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tTESTB\ty+4(FP), BX // want `invalid TESTB of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tTESTW\tx+0(FP), AX // want `invalid TESTW of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tTESTW\ty+4(FP), AX // want `invalid TESTW of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tTESTL\tx+0(FP), AX\n\tTESTL\ty+4(FP), AX\n\tTESTQ\tx+0(FP), AX // want `invalid TESTQ of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tTESTQ\ty+4(FP), AX // want `invalid TESTQ of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tTESTQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tTESTQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tMOVW\tc+8(FP), AX // want `invalid MOVW of c\\+8\\(FP\\); chan int is 4-byte value`\n\tMOVW\tm+12(FP), AX // want `invalid MOVW of m\\+12\\(FP\\); map\\[int\\]int is 4-byte value`\n\tMOVW\tf+16(FP), AX // want `invalid MOVW of f\\+16\\(FP\\); func\\(\\) is 4-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \\$\\.\\.\\.-16`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); string base is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx_base+0(FP), AX // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 4-byte value`\n\tMOVL\tx_base+0(FP), AX\n\tMOVQ\tx_base+0(FP), AX // want `invalid MOVQ of x_base\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVL\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+4(FP), AX // want `invalid MOVW of x_len\\+4\\(FP\\); string len is 4-byte value`\n\tMOVL\tx_len+4(FP), AX\n\tMOVQ\tx_len+4(FP), AX // want `invalid MOVQ of x_len\\+4\\(FP\\); string len is 4-byte value`\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVQ\ty_len+4(FP), AX // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+12\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \\$\\.\\.\\.-24`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx_base+0(FP), AX // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVL\tx_base+0(FP), AX\n\tMOVQ\tx_base+0(FP), AX // want `invalid MOVQ of x_base\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVL\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+4(FP), AX // want `invalid MOVW of x_len\\+4\\(FP\\); slice len is 4-byte value`\n\tMOVL\tx_len+4(FP), AX\n\tMOVQ\tx_len+4(FP), AX // want `invalid MOVQ of x_len\\+4\\(FP\\); slice len is 4-byte value`\n\tMOVW\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVL\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVQ\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVW\tx_cap+8(FP), AX // want `invalid MOVW of x_cap\\+8\\(FP\\); slice cap is 4-byte value`\n\tMOVL\tx_cap+8(FP), AX\n\tMOVQ\tx_cap+8(FP), AX // want `invalid MOVQ of x_cap\\+8\\(FP\\); slice cap is 4-byte value`\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+12\\(FP\\)`\n\tMOVQ\ty_len+4(FP), AX // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+16\\(FP\\)`\n\tMOVQ\ty_cap+8(FP), AX // want `invalid offset y_cap\\+8\\(FP\\); expected y_cap\\+20\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-16\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVL\tx+0(FP), AX\n\tMOVQ\tx+0(FP), AX // want `invalid MOVQ of x\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVW\tx_type+0(FP), AX // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVL\tx_type+0(FP), AX\n\tMOVQ\tx_type+0(FP), AX // want `invalid MOVQ of x_type\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVQ\tx_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVQ\tx_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVW\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVL\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVQ\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVW\tx_data+4(FP), AX // want `invalid MOVW of x_data\\+4\\(FP\\); interface data is 4-byte value`\n\tMOVL\tx_data+4(FP), AX\n\tMOVQ\tx_data+4(FP), AX // want `invalid MOVQ of x_data\\+4\\(FP\\); interface data is 4-byte value`\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVL\ty+8(FP), AX\n\tMOVQ\ty+8(FP), AX // want `invalid MOVQ of y\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVW\ty_itable+8(FP), AX // want `invalid MOVW of y_itable\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVL\ty_itable+8(FP), AX\n\tMOVQ\ty_itable+8(FP), AX // want `invalid MOVQ of y_itable\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVQ\ty_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\\+8\\(FP\\)`\n\tMOVW\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVL\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVQ\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVW\ty_data+12(FP), AX // want `invalid MOVW of y_data\\+12\\(FP\\); interface data is 4-byte value`\n\tMOVL\ty_data+12(FP), AX\n\tMOVQ\ty_data+12(FP), AX // want `invalid MOVQ of y_data\\+12\\(FP\\); interface data is 4-byte value`\n\tRET\n\nTEXT ·returnint(SB),0,$0-4\n\tMOVB\tAX, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 4-byte value`\n\tMOVW\tAX, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 4-byte value`\n\tMOVL\tAX, ret+0(FP)\n\tMOVQ\tAX, ret+0(FP) // want `invalid MOVQ of ret\\+0\\(FP\\); int is 4-byte value`\n\tMOVQ\tAX, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVQ\tAX, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-5\n\tMOVL\tx+0(FP), AX\n\tMOVB\tAX, ret+4(FP)\n\tMOVW\tAX, ret+4(FP) // want `invalid MOVW of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVL\tAX, ret+4(FP) // want `invalid MOVL of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVQ\tAX, ret+4(FP) // want `invalid MOVQ of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVB\tAX, ret+3(FP) // want `invalid offset ret\\+3\\(FP\\); expected ret\\+4\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-21\n\tMOVB\tx+0(FP), AX\n\tMOVL\tAX, r1+4(FP)\n\tMOVW\tAX, r2+8(FP)\n\tMOVL\tAX, r3+12(FP)\n\tMOVL\tAX, r3_base+12(FP)\n\tMOVL\tAX, r3_len+16(FP)\n\tMOVB\tAX, r4+20(FP)\n\tMOVQ\tAX, r1+4(FP) // want `invalid MOVQ of r1\\+4\\(FP\\); int is 4-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-4\n\tRET // want `RET without writing to 4-byte ret\\+0\\(FP\\)`\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm3.s",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build arm\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), AX\n\tMOVB\ty+1(FP), BX\n\tMOVH\tx+0(FP), AX // want `\\[arm\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVH\ty+1(FP), AX // want `invalid MOVH of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVW\ty+1(FP), AX // want `invalid MOVW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), AX // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVB\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t8(R13), AX // want `8\\(R13\\) should be x\\+0\\(FP\\)`\n\tMOVB\t9(R13), AX // want `9\\(R13\\) should be y\\+1\\(FP\\)`\n\tMOVB\t10(R13), AX // want `use of 10\\(R13\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVB\tx+0(FP), AX // want `arg2: invalid MOVB of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), AX // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVH\tx+0(FP), AX\n\tMOVH\ty+2(FP), BX\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), AX // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVH\tx+2(FP), AX // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), AX // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+4(FP), AX\n\tMOVW\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), BX // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), AX // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), AX // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value containing x_lo\\+0\\(FP\\) and x_hi\\+4\\(FP\\)`\n\tMOVW\tx_lo+0(FP), AX\n\tMOVW\tx_hi+4(FP), AX\n\tMOVW\ty+8(FP), AX // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value containing y_lo\\+8\\(FP\\) and y_hi\\+12\\(FP\\)`\n\tMOVW\ty_lo+8(FP), AX\n\tMOVW\ty_hi+12(FP), AX\n\tMOVQ\tx+0(FP), AX\n\tMOVQ\ty+8(FP), AX\n\tMOVQ\tx+8(FP), AX // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVH\ty+4(FP), AX // want `invalid MOVH of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+4(FP), AX\n\tMOVQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-20`\n\tMOVB\tx+0(FP), AX // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVB\ty+4(FP), BX // want `invalid MOVB of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVH\ty+4(FP), AX // want `invalid MOVH of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+4(FP), AX\n\tMOVQ\tx+4(FP), AX // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVQ\ty+2(FP), AX // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tMOVH\tc+8(FP), AX // want `invalid MOVH of c\\+8\\(FP\\); chan int is 4-byte value`\n\tMOVH\tm+12(FP), AX // want `invalid MOVH of m\\+12\\(FP\\); map\\[int\\]int is 4-byte value`\n\tMOVH\tf+16(FP), AX // want `invalid MOVH of f\\+16\\(FP\\); func\\(\\) is 4-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \\$\\.\\.\\.-16`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVH\tx_base+0(FP), AX // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx_base+0(FP), AX\n\tMOVH\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVH\tx_len+4(FP), AX // want `invalid MOVH of x_len\\+4\\(FP\\); string len is 4-byte value`\n\tMOVW\tx_len+4(FP), AX\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVQ\ty_len+4(FP), AX // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+12\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \\$\\.\\.\\.-24`\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVH\tx_base+0(FP), AX // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx_base+0(FP), AX\n\tMOVH\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVQ\tx_len+0(FP), AX // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVH\tx_len+4(FP), AX // want `invalid MOVH of x_len\\+4\\(FP\\); slice len is 4-byte value`\n\tMOVW\tx_len+4(FP), AX\n\tMOVH\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVW\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVQ\tx_cap+0(FP), AX // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVH\tx_cap+8(FP), AX // want `invalid MOVH of x_cap\\+8\\(FP\\); slice cap is 4-byte value`\n\tMOVW\tx_cap+8(FP), AX\n\tMOVQ\ty+0(FP), AX // want `invalid offset y\\+0\\(FP\\); expected y\\+12\\(FP\\)`\n\tMOVQ\ty_len+4(FP), AX // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+16\\(FP\\)`\n\tMOVQ\ty_cap+8(FP), AX // want `invalid offset y_cap\\+8\\(FP\\); expected y_cap\\+20\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-16\n\tMOVH\tx+0(FP), AX // want `invalid MOVH of x\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVW\tx+0(FP), AX\n\tMOVH\tx_type+0(FP), AX // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVW\tx_type+0(FP), AX\n\tMOVQ\tx_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVQ\tx_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVW\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVQ\tx_data+0(FP), AX // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVH\tx_data+4(FP), AX // want `invalid MOVH of x_data\\+4\\(FP\\); interface data is 4-byte value`\n\tMOVW\tx_data+4(FP), AX\n\tMOVH\ty+8(FP), AX // want `invalid MOVH of y\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVW\ty+8(FP), AX\n\tMOVH\ty_itable+8(FP), AX // want `invalid MOVH of y_itable\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVW\ty_itable+8(FP), AX\n\tMOVQ\ty_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\\+8\\(FP\\)`\n\tMOVH\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVW\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVQ\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVH\ty_data+12(FP), AX // want `invalid MOVH of y_data\\+12\\(FP\\); interface data is 4-byte value`\n\tMOVW\ty_data+12(FP), AX\n\tRET\n\nTEXT ·returnint(SB),0,$0-4\n\tMOVB\tAX, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 4-byte value`\n\tMOVH\tAX, ret+0(FP) // want `invalid MOVH of ret\\+0\\(FP\\); int is 4-byte value`\n\tMOVW\tAX, ret+0(FP)\n\tMOVQ\tAX, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVQ\tAX, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-5\n\tMOVW\tx+0(FP), AX\n\tMOVB\tAX, ret+4(FP)\n\tMOVH\tAX, ret+4(FP) // want `invalid MOVH of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVW\tAX, ret+4(FP) // want `invalid MOVW of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVB\tAX, ret+3(FP) // want `invalid offset ret\\+3\\(FP\\); expected ret\\+4\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-21\n\tMOVB\tx+0(FP), AX\n\tMOVW\tAX, r1+4(FP)\n\tMOVH\tAX, r2+8(FP)\n\tMOVW\tAX, r3+12(FP)\n\tMOVW\tAX, r3_base+12(FP)\n\tMOVW\tAX, r3_len+16(FP)\n\tMOVB\tAX, r4+20(FP)\n\tMOVB\tAX, r1+4(FP) // want `invalid MOVB of r1\\+4\\(FP\\); int is 4-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-4\n\tRET // want `RET without writing to 4-byte ret\\+0\\(FP\\)`\n\nTEXT ·leaf(SB),0,$-4-12\n\tMOVW\tx+0(FP), AX\n\tMOVW\ty+4(FP), AX\n\tMOVW\tAX, ret+8(FP)\n\tRET\n\nTEXT ·noframe1(SB),0,$0-4\n\tMOVW\t0(R13), AX // Okay; our saved LR\n\tMOVW\t4(R13), AX // Okay; caller's saved LR\n\tMOVW\tx+8(R13), AX // Okay; x argument\n\tMOVW\t12(R13), AX // want `use of 12\\(R13\\) points beyond argument frame`\n\tRET\n\nTEXT ·noframe2(SB),NOFRAME,$0-4\n\tMOVW\t0(R13), AX // Okay; caller's saved LR\n\tMOVW\tx+4(R13), AX // Okay; x argument\n\tMOVW\t8(R13), AX // Okay - NOFRAME is assumed special\n\tMOVW\t12(R13), AX // Okay - NOFRAME is assumed special\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm4.s",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build amd64\n\n// Test cases for symbolic NOSPLIT etc. on TEXT symbols.\n\nTEXT ·noprof(SB),NOPROF,$0-8\n\tRET\n\nTEXT ·dupok(SB),DUPOK,$0-8\n\tRET\n\nTEXT ·nosplit(SB),NOSPLIT,$0\n\tRET\n\nTEXT ·rodata(SB),RODATA,$0-8\n\tRET\n\nTEXT ·noptr(SB),NOPTR|NOSPLIT,$0\n\tRET\n\nTEXT ·wrapper(SB),WRAPPER,$0-8\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm5.s",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build mips64\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), R1\n\tMOVBU\ty+1(FP), R2\n\tMOVH\tx+0(FP), R1 // want `\\[mips64\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVHU\ty+1(FP), R1 // want `invalid MOVHU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVWU\ty+1(FP), R1 // want `invalid MOVWU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVV\tx+0(FP), R1 // want `invalid MOVV of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVV\ty+1(FP), R1 // want `invalid MOVV of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), R1 // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVBU\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t16(R29), R1 // want `16\\(R29\\) should be x\\+0\\(FP\\)`\n\tMOVB\t17(R29), R1 // want `17\\(R29\\) should be y\\+1\\(FP\\)`\n\tMOVB\t18(R29), R1 // want `use of 18\\(R29\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVBU\tx+0(FP), R1 // want `arg2: invalid MOVBU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), R1 // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+0(FP), R1\n\tMOVH\ty+2(FP), R2\n\tMOVWU\tx+0(FP), R1 // want `invalid MOVWU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), R1 // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVV\tx+0(FP), R1 // want `invalid MOVV of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVV\ty+2(FP), R1 // want `invalid MOVV of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+2(FP), R1 // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), R2 // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), R1 // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVW\ty+4(FP), R1\n\tMOVV\tx+0(FP), R1 // want `invalid MOVV of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVV\ty+4(FP), R1 // want `invalid MOVV of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+4(FP), R1 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVV\ty+8(FP), R1\n\tMOVV\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVV\ty+8(FP), R1\n\tMOVV\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-40`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVV\ty+8(FP), R1\n\tMOVV\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVV\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVW\tc+16(FP), R1 // want `invalid MOVW of c\\+16\\(FP\\); chan int is 8-byte value`\n\tMOVW\tm+24(FP), R1 // want `invalid MOVW of m\\+24\\(FP\\); map\\[int\\]int is 8-byte value`\n\tMOVW\tf+32(FP), R1 // want `invalid MOVW of f\\+32\\(FP\\); func\\(\\) is 8-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \\$\\.\\.\\.-32`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx_base+0(FP), R1 // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVV\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVV\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R1 // want `invalid MOVH of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVW\tx_len+8(FP), R1 // want `invalid MOVW of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVV\tx_len+8(FP), R1\n\tMOVV\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+16\\(FP\\)`\n\tMOVV\ty_len+8(FP), R1 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+24\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx_base+0(FP), R1 // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVV\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVV\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R1 // want `invalid MOVH of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVW\tx_len+8(FP), R1 // want `invalid MOVW of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVV\tx_len+8(FP), R1\n\tMOVH\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVW\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVV\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVH\tx_cap+16(FP), R1 // want `invalid MOVH of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVW\tx_cap+16(FP), R1 // want `invalid MOVW of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVV\tx_cap+16(FP), R1\n\tMOVV\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+24\\(FP\\)`\n\tMOVV\ty_len+8(FP), R1 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+32\\(FP\\)`\n\tMOVV\ty_cap+16(FP), R1 // want `invalid offset y_cap\\+16\\(FP\\); expected y_cap\\+40\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-32\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVV\tx+0(FP), R1\n\tMOVH\tx_type+0(FP), R1 // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx_type+0(FP), R1 // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVV\tx_type+0(FP), R1\n\tMOVV\tx_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVV\tx_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVW\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVV\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVH\tx_data+8(FP), R1 // want `invalid MOVH of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVW\tx_data+8(FP), R1 // want `invalid MOVW of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVV\tx_data+8(FP), R1\n\tMOVH\ty+16(FP), R1 // want `invalid MOVH of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty+16(FP), R1 // want `invalid MOVW of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVV\ty+16(FP), R1\n\tMOVH\ty_itable+16(FP), R1 // want `invalid MOVH of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty_itable+16(FP), R1 // want `invalid MOVW of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVV\ty_itable+16(FP), R1\n\tMOVV\ty_type+16(FP), R1 // want `unknown variable y_type; offset 16 is y_itable\\+16\\(FP\\)`\n\tMOVH\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVW\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVV\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVH\ty_data+24(FP), R1 // want `invalid MOVH of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVW\ty_data+24(FP), R1 // want `invalid MOVW of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVV\ty_data+24(FP), R1\n\tRET\n\nTEXT ·returnint(SB),0,$0-8\n\tMOVB\tR1, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\tR1, ret+0(FP) // want `invalid MOVH of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\tR1, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVV\tR1, ret+0(FP)\n\tMOVV\tR1, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVV\tR1, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-9\n\tMOVV\tx+0(FP), R1\n\tMOVB\tR1, ret+8(FP)\n\tMOVH\tR1, ret+8(FP) // want `invalid MOVH of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVW\tR1, ret+8(FP) // want `invalid MOVW of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVV\tR1, ret+8(FP) // want `invalid MOVV of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVB\tR1, ret+7(FP) // want `invalid offset ret\\+7\\(FP\\); expected ret\\+8\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-41\n\tMOVB\tx+0(FP), R1\n\tMOVV\tR1, r1+8(FP)\n\tMOVH\tR1, r2+16(FP)\n\tMOVV\tR1, r3+24(FP)\n\tMOVV\tR1, r3_base+24(FP)\n\tMOVV\tR1, r3_len+32(FP)\n\tMOVB\tR1, r4+40(FP)\n\tMOVW\tR1, r1+8(FP) // want `invalid MOVW of r1\\+8\\(FP\\); int is 8-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-8\n\tRET // want `RET without writing to 8-byte ret\\+0\\(FP\\)`\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm6.s",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build s390x\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), R1\n\tMOVBZ\ty+1(FP), R2\n\tMOVH\tx+0(FP), R1 // want `\\[s390x\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVHZ\ty+1(FP), R1 // want `invalid MOVHZ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVWZ\ty+1(FP), R1 // want `invalid MOVWZ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVD\tx+0(FP), R1 // want `invalid MOVD of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVD\ty+1(FP), R1 // want `invalid MOVD of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), R1 // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVBZ\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t16(R15), R1 // want `16\\(R15\\) should be x\\+0\\(FP\\)`\n\tMOVB\t17(R15), R1 // want `17\\(R15\\) should be y\\+1\\(FP\\)`\n\tMOVB\t18(R15), R1 // want `use of 18\\(R15\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVBZ\tx+0(FP), R1 // want `arg2: invalid MOVBZ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), R1 // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHZ\tx+0(FP), R1\n\tMOVH\ty+2(FP), R2\n\tMOVWZ\tx+0(FP), R1 // want `invalid MOVWZ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), R1 // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVD\tx+0(FP), R1 // want `invalid MOVD of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVD\ty+2(FP), R1 // want `invalid MOVD of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHZ\tx+2(FP), R1 // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), R2 // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), R1 // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVW\ty+4(FP), R1\n\tMOVD\tx+0(FP), R1 // want `invalid MOVD of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVD\ty+4(FP), R1 // want `invalid MOVD of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+4(FP), R1 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVD\ty+8(FP), R1\n\tMOVD\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVD\ty+8(FP), R1\n\tMOVD\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-40`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVD\ty+8(FP), R1\n\tMOVD\tx+8(FP), R1 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVW\tc+16(FP), R1 // want `invalid MOVW of c\\+16\\(FP\\); chan int is 8-byte value`\n\tMOVW\tm+24(FP), R1 // want `invalid MOVW of m\\+24\\(FP\\); map\\[int\\]int is 8-byte value`\n\tMOVW\tf+32(FP), R1 // want `invalid MOVW of f\\+32\\(FP\\); func\\(\\) is 8-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \\$\\.\\.\\.-32`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx_base+0(FP), R1 // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVD\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVD\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R1 // want `invalid MOVH of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVW\tx_len+8(FP), R1 // want `invalid MOVW of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVD\tx_len+8(FP), R1\n\tMOVD\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+16\\(FP\\)`\n\tMOVD\ty_len+8(FP), R1 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+24\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx_base+0(FP), R1 // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVD\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVD\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R1 // want `invalid MOVH of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVW\tx_len+8(FP), R1 // want `invalid MOVW of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVD\tx_len+8(FP), R1\n\tMOVH\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVW\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVD\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVH\tx_cap+16(FP), R1 // want `invalid MOVH of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVW\tx_cap+16(FP), R1 // want `invalid MOVW of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVD\tx_cap+16(FP), R1\n\tMOVD\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+24\\(FP\\)`\n\tMOVD\ty_len+8(FP), R1 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+32\\(FP\\)`\n\tMOVD\ty_cap+16(FP), R1 // want `invalid offset y_cap\\+16\\(FP\\); expected y_cap\\+40\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-32\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVD\tx+0(FP), R1\n\tMOVH\tx_type+0(FP), R1 // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx_type+0(FP), R1 // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVD\tx_type+0(FP), R1\n\tMOVD\tx_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVD\tx_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVW\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVD\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVH\tx_data+8(FP), R1 // want `invalid MOVH of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVW\tx_data+8(FP), R1 // want `invalid MOVW of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVD\tx_data+8(FP), R1\n\tMOVH\ty+16(FP), R1 // want `invalid MOVH of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty+16(FP), R1 // want `invalid MOVW of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVD\ty+16(FP), R1\n\tMOVH\ty_itable+16(FP), R1 // want `invalid MOVH of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty_itable+16(FP), R1 // want `invalid MOVW of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVD\ty_itable+16(FP), R1\n\tMOVD\ty_type+16(FP), R1 // want `unknown variable y_type; offset 16 is y_itable\\+16\\(FP\\)`\n\tMOVH\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVW\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVD\ty_data+16(FP), R1 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVH\ty_data+24(FP), R1 // want `invalid MOVH of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVW\ty_data+24(FP), R1 // want `invalid MOVW of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVD\ty_data+24(FP), R1\n\tRET\n\nTEXT ·returnint(SB),0,$0-8\n\tMOVB\tR1, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\tR1, ret+0(FP) // want `invalid MOVH of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\tR1, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVD\tR1, ret+0(FP)\n\tMOVD\tR1, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVD\tR1, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-9\n\tMOVD\tx+0(FP), R1\n\tMOVB\tR1, ret+8(FP)\n\tMOVH\tR1, ret+8(FP) // want `invalid MOVH of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVW\tR1, ret+8(FP) // want `invalid MOVW of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVD\tR1, ret+8(FP) // want `invalid MOVD of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVB\tR1, ret+7(FP) // want `invalid offset ret\\+7\\(FP\\); expected ret\\+8\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-41\n\tMOVB\tx+0(FP), R1\n\tMOVD\tR1, r1+8(FP)\n\tMOVH\tR1, r2+16(FP)\n\tMOVD\tR1, r3+24(FP)\n\tMOVD\tR1, r3_base+24(FP)\n\tMOVD\tR1, r3_len+32(FP)\n\tMOVB\tR1, r4+40(FP)\n\tMOVW\tR1, r1+8(FP) // want `invalid MOVW of r1\\+8\\(FP\\); int is 8-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-8\n\tRET // want `RET without writing to 8-byte ret\\+0\\(FP\\)`\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm7.s",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build ppc64 ppc64le\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), R3\n\tMOVBZ\ty+1(FP), R4\n\tMOVH\tx+0(FP), R3 // want `\\[(ppc64|ppc64le)\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVHZ\ty+1(FP), R3 // want `invalid MOVHZ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVWZ\ty+1(FP), R3 // want `invalid MOVWZ of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVD\tx+0(FP), R3 // want `invalid MOVD of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVD\ty+1(FP), R3 // want `invalid MOVD of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), R3 // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVBZ\ty+2(FP), R3 // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t16(R1), R3 // want `16\\(R1\\) should be x\\+0\\(FP\\)`\n\tMOVB\t17(R1), R3 // want `17\\(R1\\) should be y\\+1\\(FP\\)`\n\tMOVB\t18(R1), R3 // want `use of 18\\(R1\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVBZ\tx+0(FP), R3 // want `arg2: invalid MOVBZ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), R3 // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHZ\tx+0(FP), R3\n\tMOVH\ty+2(FP), R4\n\tMOVWZ\tx+0(FP), R3 // want `invalid MOVWZ of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), R3 // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVD\tx+0(FP), R3 // want `invalid MOVD of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVD\ty+2(FP), R3 // want `invalid MOVD of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHZ\tx+2(FP), R3 // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), R3 // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R3 // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), R4 // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), R3 // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), R3\n\tMOVW\ty+4(FP), R3\n\tMOVD\tx+0(FP), R3 // want `invalid MOVD of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVD\ty+4(FP), R3 // want `invalid MOVD of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+4(FP), R3 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R3 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R3 // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), R4 // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), R3 // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVW\ty+8(FP), R3 // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVD\ty+8(FP), R3\n\tMOVD\tx+8(FP), R3 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R3 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R3 // want `invalid MOVB of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVB\ty+8(FP), R4 // want `invalid MOVB of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\ty+8(FP), R3 // want `invalid MOVH of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\ty+8(FP), R3 // want `invalid MOVW of y\\+8\\(FP\\); uint is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVD\ty+8(FP), R3\n\tMOVD\tx+8(FP), R3 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R3 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-40`\n\tMOVB\tx+0(FP), R3 // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVB\ty+8(FP), R4 // want `invalid MOVB of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVH\ty+8(FP), R3 // want `invalid MOVH of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); \\*byte is 8-byte value`\n\tMOVW\ty+8(FP), R3 // want `invalid MOVW of y\\+8\\(FP\\); \\*byte is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVD\ty+8(FP), R3\n\tMOVD\tx+8(FP), R3 // want `invalid offset x\\+8\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVD\ty+2(FP), R3 // want `invalid offset y\\+2\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVW\tc+16(FP), R3 // want `invalid MOVW of c\\+16\\(FP\\); chan int is 8-byte value`\n\tMOVW\tm+24(FP), R3 // want `invalid MOVW of m\\+24\\(FP\\); map\\[int\\]int is 8-byte value`\n\tMOVW\tf+32(FP), R3 // want `invalid MOVW of f\\+32\\(FP\\); func\\(\\) is 8-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \\$\\.\\.\\.-32`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); string base is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVH\tx_base+0(FP), R3 // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVW\tx_base+0(FP), R3 // want `invalid MOVW of x_base\\+0\\(FP\\); string base is 8-byte value`\n\tMOVD\tx_base+0(FP), R3\n\tMOVH\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVD\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R3 // want `invalid MOVH of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVW\tx_len+8(FP), R3 // want `invalid MOVW of x_len\\+8\\(FP\\); string len is 8-byte value`\n\tMOVD\tx_len+8(FP), R3\n\tMOVD\ty+0(FP), R3 // want `invalid offset y\\+0\\(FP\\); expected y\\+16\\(FP\\)`\n\tMOVD\ty_len+8(FP), R3 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+24\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \\$\\.\\.\\.-48`\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVH\tx_base+0(FP), R3 // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVW\tx_base+0(FP), R3 // want `invalid MOVW of x_base\\+0\\(FP\\); slice base is 8-byte value`\n\tMOVD\tx_base+0(FP), R3\n\tMOVH\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVW\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVD\tx_len+0(FP), R3 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+8\\(FP\\)`\n\tMOVH\tx_len+8(FP), R3 // want `invalid MOVH of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVW\tx_len+8(FP), R3 // want `invalid MOVW of x_len\\+8\\(FP\\); slice len is 8-byte value`\n\tMOVD\tx_len+8(FP), R3\n\tMOVH\tx_cap+0(FP), R3 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVW\tx_cap+0(FP), R3 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVD\tx_cap+0(FP), R3 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+16\\(FP\\)`\n\tMOVH\tx_cap+16(FP), R3 // want `invalid MOVH of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVW\tx_cap+16(FP), R3 // want `invalid MOVW of x_cap\\+16\\(FP\\); slice cap is 8-byte value`\n\tMOVD\tx_cap+16(FP), R3\n\tMOVD\ty+0(FP), R3 // want `invalid offset y\\+0\\(FP\\); expected y\\+24\\(FP\\)`\n\tMOVD\ty_len+8(FP), R3 // want `invalid offset y_len\\+8\\(FP\\); expected y_len\\+32\\(FP\\)`\n\tMOVD\ty_cap+16(FP), R3 // want `invalid offset y_cap\\+16\\(FP\\); expected y_cap\\+40\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-32\n\tMOVH\tx+0(FP), R3 // want `invalid MOVH of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx+0(FP), R3 // want `invalid MOVW of x\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVD\tx+0(FP), R3\n\tMOVH\tx_type+0(FP), R3 // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVW\tx_type+0(FP), R3 // want `invalid MOVW of x_type\\+0\\(FP\\); interface type is 8-byte value`\n\tMOVD\tx_type+0(FP), R3\n\tMOVD\tx_itable+0(FP), R3 // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVD\tx_itable+1(FP), R3 // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), R3 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVW\tx_data+0(FP), R3 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVD\tx_data+0(FP), R3 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+8\\(FP\\)`\n\tMOVH\tx_data+8(FP), R3 // want `invalid MOVH of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVW\tx_data+8(FP), R3 // want `invalid MOVW of x_data\\+8\\(FP\\); interface data is 8-byte value`\n\tMOVD\tx_data+8(FP), R3\n\tMOVH\ty+16(FP), R3 // want `invalid MOVH of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty+16(FP), R3 // want `invalid MOVW of y\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVD\ty+16(FP), R3\n\tMOVH\ty_itable+16(FP), R3 // want `invalid MOVH of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVW\ty_itable+16(FP), R3 // want `invalid MOVW of y_itable\\+16\\(FP\\); interface itable is 8-byte value`\n\tMOVD\ty_itable+16(FP), R3\n\tMOVD\ty_type+16(FP), R3 // want `unknown variable y_type; offset 16 is y_itable\\+16\\(FP\\)`\n\tMOVH\ty_data+16(FP), R3 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVW\ty_data+16(FP), R3 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVD\ty_data+16(FP), R3 // want `invalid offset y_data\\+16\\(FP\\); expected y_data\\+24\\(FP\\)`\n\tMOVH\ty_data+24(FP), R3 // want `invalid MOVH of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVW\ty_data+24(FP), R3 // want `invalid MOVW of y_data\\+24\\(FP\\); interface data is 8-byte value`\n\tMOVD\ty_data+24(FP), R3\n\tRET\n\nTEXT ·returnint(SB),0,$0-8\n\tMOVB\tR3, ret+0(FP) // want `invalid MOVB of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVH\tR3, ret+0(FP) // want `invalid MOVH of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVW\tR3, ret+0(FP) // want `invalid MOVW of ret\\+0\\(FP\\); int is 8-byte value`\n\tMOVD\tR3, ret+0(FP)\n\tMOVD\tR3, ret+1(FP) // want `invalid offset ret\\+1\\(FP\\); expected ret\\+0\\(FP\\)`\n\tMOVD\tR3, r+0(FP) // want `unknown variable r; offset 0 is ret\\+0\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-9\n\tMOVD\tx+0(FP), R3\n\tMOVB\tR3, ret+8(FP)\n\tMOVH\tR3, ret+8(FP) // want `invalid MOVH of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVW\tR3, ret+8(FP) // want `invalid MOVW of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVD\tR3, ret+8(FP) // want `invalid MOVD of ret\\+8\\(FP\\); byte is 1-byte value`\n\tMOVB\tR3, ret+7(FP) // want `invalid offset ret\\+7\\(FP\\); expected ret\\+8\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-41\n\tMOVB\tx+0(FP), R3\n\tMOVD\tR3, r1+8(FP)\n\tMOVH\tR3, r2+16(FP)\n\tMOVD\tR3, r3+24(FP)\n\tMOVD\tR3, r3_base+24(FP)\n\tMOVD\tR3, r3_len+32(FP)\n\tMOVB\tR3, r4+40(FP)\n\tMOVW\tR3, r1+8(FP) // want `invalid MOVW of r1\\+8\\(FP\\); int is 8-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-8\n\tRET // want `RET without writing to 8-byte ret\\+0\\(FP\\)`\n\n// writing to result in ABIInternal function\nTEXT ·returnABIInternal<ABIInternal>(SB), NOSPLIT, $8\n\tMOVD\t$123, R3\n\tRET\nTEXT ·returnmissingABIInternal<ABIInternal>(SB), NOSPLIT, $8\n\tMOVD\t$123, R10\n\tRET // want `RET without writing to result register`\n\n// issue 69352\nTEXT ·returnsyscallABIInternal<ABIInternal>(SB), NOSPLIT, $0\n\tMOVD\t$123, R10\n\tSYSCALL\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm8.s",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build mipsle\n\nTEXT ·arg1(SB),0,$0-2\n\tMOVB\tx+0(FP), R1\n\tMOVBU\ty+1(FP), R2\n\tMOVH\tx+0(FP), R1 // want `\\[mipsle\\] arg1: invalid MOVH of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVHU\ty+1(FP), R1 // want `invalid MOVHU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int8 is 1-byte value`\n\tMOVWU\ty+1(FP), R1 // want `invalid MOVWU of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVW\ty+1(FP), R1 // want `invalid MOVW of y\\+1\\(FP\\); uint8 is 1-byte value`\n\tMOVB\tx+1(FP), R1 // want `invalid offset x\\+1\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVBU\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+1\\(FP\\)`\n\tMOVB\t8(R29), R1 // want `8\\(R29\\) should be x\\+0\\(FP\\)`\n\tMOVB\t9(R29), R1 // want `9\\(R29\\) should be y\\+1\\(FP\\)`\n\tMOVB\t10(R29), R1 // want `use of 10\\(R29\\) points beyond argument frame`\n\tRET\n\nTEXT ·arg2(SB),0,$0-4\n\tMOVBU\tx+0(FP), R1 // want `arg2: invalid MOVBU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVB\ty+2(FP), R1 // want `invalid MOVB of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+0(FP), R1\n\tMOVH\ty+2(FP), R2\n\tMOVWU\tx+0(FP), R1 // want `invalid MOVWU of x\\+0\\(FP\\); int16 is 2-byte value`\n\tMOVW\ty+2(FP), R1 // want `invalid MOVW of y\\+2\\(FP\\); uint16 is 2-byte value`\n\tMOVHU\tx+2(FP), R1 // want `invalid offset x\\+2\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVH\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+2\\(FP\\)`\n\tRET\n\nTEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVB\ty+4(FP), R2 // want `invalid MOVB of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int32 is 4-byte value`\n\tMOVH\ty+4(FP), R1 // want `invalid MOVH of y\\+4\\(FP\\); uint32 is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVW\ty+4(FP), R1\n\tMOVW\tx+4(FP), R1 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-16`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVB\ty+8(FP), R2 // want `invalid MOVB of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int64 is 8-byte value`\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); uint64 is 8-byte value`\n\tMOVW\tx+0(FP), R1 // want `invalid MOVW of x\\+0\\(FP\\); int64 is 8-byte value containing x_lo\\+0\\(FP\\) and x_hi\\+4\\(FP\\)`\n\tMOVW\t$x+0(FP), R1 // ok\n\tMOVW\tx_lo+0(FP), R1\n\tMOVW\tx_hi+4(FP), R1\n\tMOVW\ty+8(FP), R1 // want `invalid MOVW of y\\+8\\(FP\\); uint64 is 8-byte value containing y_lo\\+8\\(FP\\) and y_hi\\+12\\(FP\\)`\n\tMOVW\ty_lo+8(FP),  R1\n\tMOVW\ty_hi+12(FP), R1\n\tRET\n\nTEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-8`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVB\ty+4(FP), R2 // want `invalid MOVB of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); int is 4-byte value`\n\tMOVH\ty+4(FP), R1 // want `invalid MOVH of y\\+4\\(FP\\); uint is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVW\ty+4(FP), R1\n\tMOVW\tx+4(FP), R1 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tRET\n\nTEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \\$\\.\\.\\.-20`\n\tMOVB\tx+0(FP), R1 // want `invalid MOVB of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVB\ty+4(FP), R2 // want `invalid MOVB of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); \\*byte is 4-byte value`\n\tMOVH\ty+4(FP), R1 // want `invalid MOVH of y\\+4\\(FP\\); \\*byte is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVW\ty+4(FP), R1\n\tMOVW\tx+4(FP), R1 // want `invalid offset x\\+4\\(FP\\); expected x\\+0\\(FP\\)`\n\tMOVW\ty+2(FP), R1 // want `invalid offset y\\+2\\(FP\\); expected y\\+4\\(FP\\)`\n\tMOVH\tc+8(FP), R1 // want `invalid MOVH of c\\+8\\(FP\\); chan int is 4-byte value`\n\tMOVH\tm+12(FP), R1 // want `invalid MOVH of m\\+12\\(FP\\); map\\[int\\]int is 4-byte value`\n\tMOVH\tf+16(FP), R1 // want `invalid MOVH of f\\+16\\(FP\\); func\\(\\) is 4-byte value`\n\tRET\n\nTEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \\$\\.\\.\\.-16`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); string base is 4-byte value`\n\tMOVW\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVH\tx_len+4(FP), R1 // want `invalid MOVH of x_len\\+4\\(FP\\); string len is 4-byte value`\n\tMOVW\tx_len+4(FP), R1\n\tMOVW\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+8\\(FP\\)`\n\tMOVW\ty_len+4(FP), R1 // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+12\\(FP\\)`\n\tRET\n\nTEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \\$\\.\\.\\.-24`\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVH\tx_base+0(FP), R1 // want `invalid MOVH of x_base\\+0\\(FP\\); slice base is 4-byte value`\n\tMOVW\tx_base+0(FP), R1\n\tMOVH\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVW\tx_len+0(FP), R1 // want `invalid offset x_len\\+0\\(FP\\); expected x_len\\+4\\(FP\\)`\n\tMOVH\tx_len+4(FP), R1 // want `invalid MOVH of x_len\\+4\\(FP\\); slice len is 4-byte value`\n\tMOVW\tx_len+4(FP), R1\n\tMOVH\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVW\tx_cap+0(FP), R1 // want `invalid offset x_cap\\+0\\(FP\\); expected x_cap\\+8\\(FP\\)`\n\tMOVH\tx_cap+8(FP), R1 // want `invalid MOVH of x_cap\\+8\\(FP\\); slice cap is 4-byte value`\n\tMOVW\tx_cap+8(FP), R1\n\tMOVW\ty+0(FP), R1 // want `invalid offset y\\+0\\(FP\\); expected y\\+12\\(FP\\)`\n\tMOVW\ty_len+4(FP), R1 // want `invalid offset y_len\\+4\\(FP\\); expected y_len\\+16\\(FP\\)`\n\tMOVW\ty_cap+8(FP), R1 // want `invalid offset y_cap\\+8\\(FP\\); expected y_cap\\+20\\(FP\\)`\n\tRET\n\nTEXT ·argiface(SB),0,$0-16\n\tMOVH\tx+0(FP), R1 // want `invalid MOVH of x\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVW\tx+0(FP), R1\n\tMOVH\tx_type+0(FP), R1 // want `invalid MOVH of x_type\\+0\\(FP\\); interface type is 4-byte value`\n\tMOVW\tx_type+0(FP), R1\n\tMOVQ\tx_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\\+0\\(FP\\)`\n\tMOVQ\tx_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\\+0\\(FP\\)`\n\tMOVH\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVW\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVQ\tx_data+0(FP), R1 // want `invalid offset x_data\\+0\\(FP\\); expected x_data\\+4\\(FP\\)`\n\tMOVH\tx_data+4(FP), R1 // want `invalid MOVH of x_data\\+4\\(FP\\); interface data is 4-byte value`\n\tMOVW\tx_data+4(FP), R1\n\tMOVH\ty+8(FP), R1 // want `invalid MOVH of y\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVW\ty+8(FP), R1\n\tMOVH\ty_itable+8(FP), R1 // want `invalid MOVH of y_itable\\+8\\(FP\\); interface itable is 4-byte value`\n\tMOVW\ty_itable+8(FP), R1\n\tMOVW\ty_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\\+8\\(FP\\)`\n\tMOVH\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVW\ty_data+8(FP), AX // want `invalid offset y_data\\+8\\(FP\\); expected y_data\\+12\\(FP\\)`\n\tMOVH\ty_data+12(FP), AX // want `invalid MOVH of y_data\\+12\\(FP\\); interface data is 4-byte value`\n\tMOVW\ty_data+12(FP), AX\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-5\n\tMOVW\tx+0(FP), R1\n\tMOVB\tR1, ret+4(FP)\n\tMOVH\tR1, ret+4(FP) // want `invalid MOVH of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVW\tR1, ret+4(FP) // want `invalid MOVW of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVB\tR1, ret+3(FP) // want `invalid offset ret\\+3\\(FP\\); expected ret\\+4\\(FP\\)`\n\tRET\n\nTEXT ·returnbyte(SB),0,$0-5\n\tMOVW\tx+0(FP), R1\n\tMOVB\tR1, ret+4(FP)\n\tMOVH\tR1, ret+4(FP) // want `invalid MOVH of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVW\tR1, ret+4(FP) // want `invalid MOVW of ret\\+4\\(FP\\); byte is 1-byte value`\n\tMOVB\tR1, ret+3(FP) // want `invalid offset ret\\+3\\(FP\\); expected ret\\+4\\(FP\\)`\n\tRET\n\nTEXT ·returnnamed(SB),0,$0-21\n\tMOVB\tx+0(FP), AX\n\tMOVW\tR1, r1+4(FP)\n\tMOVH\tR1, r2+8(FP)\n\tMOVW\tR1, r3+12(FP)\n\tMOVW\tR1, r3_base+12(FP)\n\tMOVW\tR1, r3_len+16(FP)\n\tMOVB\tR1, r4+20(FP)\n\tMOVB\tR1, r1+4(FP) // want `invalid MOVB of r1\\+4\\(FP\\); int is 4-byte value`\n\tRET\n\nTEXT ·returnintmissing(SB),0,$0-4\n\tRET // want `RET without writing to 4-byte ret\\+0\\(FP\\)`\n"
  },
  {
    "path": "go/analysis/passes/asmdecl/testdata/src/a/asm9.s",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build wasm\n\nTEXT ·returnint(SB),NOSPLIT|NOFRAME,$0-8\n\tMOVD\t24(SP), R1 // ok to access beyond stack frame with NOFRAME\n\tCallImport // interpreted as writing result\n\tRET\n\nTEXT ·returnbyte(SB),$0-9\n\tRET // want `RET without writing`\n"
  },
  {
    "path": "go/analysis/passes/assign/assign.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage assign\n\n// TODO(adonovan): check also for assignments to struct fields inside\n// methods that are on T instead of *T.\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"assign\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"assign\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tinfo    = pass.TypesInfo\n\t)\n\n\tfor curAssign := range inspect.Root().Preorder((*ast.AssignStmt)(nil)) {\n\t\tstmt := curAssign.Node().(*ast.AssignStmt)\n\t\tif stmt.Tok != token.ASSIGN {\n\t\t\tcontinue // ignore :=\n\t\t}\n\t\tif len(stmt.Lhs) != len(stmt.Rhs) {\n\t\t\t// If LHS and RHS have different cardinality, they can't be the same.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Delete redundant LHS, RHS pairs, taking care\n\t\t// to include intervening commas.\n\t\tvar (\n\t\t\texprs                    []string // expressions appearing on both sides (x = x)\n\t\t\tedits                    []analysis.TextEdit\n\t\t\trunStartLHS, runStartRHS token.Pos // non-zero => within a run\n\t\t)\n\t\tfor i, lhs := range stmt.Lhs {\n\t\t\trhs := stmt.Rhs[i]\n\t\t\tisSelfAssign := false\n\t\t\tvar le string\n\n\t\t\tif typesinternal.NoEffects(info, lhs) &&\n\t\t\t\ttypesinternal.NoEffects(info, rhs) &&\n\t\t\t\t!isMapIndex(info, lhs) &&\n\t\t\t\treflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check\n\n\t\t\t\tle = astutil.Format(pass.Fset, lhs)\n\t\t\t\tre := astutil.Format(pass.Fset, rhs)\n\t\t\t\tif le == re {\n\t\t\t\t\tisSelfAssign = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif isSelfAssign {\n\t\t\t\texprs = append(exprs, le)\n\t\t\t\tif !runStartLHS.IsValid() {\n\t\t\t\t\t// Start of a new run of self-assignments.\n\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\trunStartLHS = stmt.Lhs[i-1].End()\n\t\t\t\t\t\trunStartRHS = stmt.Rhs[i-1].End()\n\t\t\t\t\t} else {\n\t\t\t\t\t\trunStartLHS = lhs.Pos()\n\t\t\t\t\t\trunStartRHS = rhs.Pos()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if runStartLHS.IsValid() {\n\t\t\t\t// End of a run of self-assignments.\n\t\t\t\tendLHS, endRHS := stmt.Lhs[i-1].End(), stmt.Rhs[i-1].End()\n\t\t\t\tif runStartLHS == stmt.Lhs[0].Pos() {\n\t\t\t\t\tendLHS, endRHS = lhs.Pos(), rhs.Pos()\n\t\t\t\t}\n\t\t\t\tedits = append(edits,\n\t\t\t\t\tanalysis.TextEdit{Pos: runStartLHS, End: endLHS},\n\t\t\t\t\tanalysis.TextEdit{Pos: runStartRHS, End: endRHS},\n\t\t\t\t)\n\t\t\t\trunStartLHS, runStartRHS = 0, 0\n\t\t\t}\n\t\t}\n\n\t\t// If a run of self-assignments continues to the end of the statement, close it.\n\t\tif runStartLHS.IsValid() {\n\t\t\tlast := len(stmt.Lhs) - 1\n\t\t\tedits = append(edits,\n\t\t\t\tanalysis.TextEdit{Pos: runStartLHS, End: stmt.Lhs[last].End()},\n\t\t\t\tanalysis.TextEdit{Pos: runStartRHS, End: stmt.Rhs[last].End()},\n\t\t\t)\n\t\t}\n\n\t\tif len(exprs) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(exprs) == len(stmt.Lhs) {\n\t\t\t// If every part of the statement is a self-assignment,\n\t\t\t// remove the whole statement.\n\t\t\ttokFile := pass.Fset.File(stmt.Pos())\n\t\t\tedits = refactor.DeleteStmt(tokFile, curAssign)\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     stmt.Pos(),\n\t\t\tMessage: \"self-assignment of \" + strings.Join(exprs, \", \"),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   \"Remove self-assignment\",\n\t\t\t\tTextEdits: edits,\n\t\t\t}},\n\t\t})\n\t}\n\n\treturn nil, nil\n}\n\n// isMapIndex returns true if e is a map index expression.\nfunc isMapIndex(info *types.Info, e ast.Expr) bool {\n\tif idx, ok := ast.Unparen(e).(*ast.IndexExpr); ok {\n\t\tif typ := info.Types[idx.X].Type; typ != nil {\n\t\t\t_, ok := typ.Underlying().(*types.Map)\n\t\t\treturn ok\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/assign/assign_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage assign_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/assign\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, assign.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/assign/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package assign defines an Analyzer that detects useless assignments.\n//\n// # Analyzer assign\n//\n// assign: check for useless assignments\n//\n// This checker reports assignments of the form x = x or a[i] = a[i].\n// These are almost always useless, and even when they aren't they are\n// usually a mistake.\npackage assign\n"
  },
  {
    "path": "go/analysis/passes/assign/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the useless-assignment checker.\n\npackage testdata\n\nimport \"math/rand\"\n\ntype ST struct {\n\tx int\n\tl []int\n}\n\nfunc (s *ST) SetX(x int, ch chan int) {\n\t// Accidental self-assignment; it should be \"s.x = x\"\n\tx = x // want \"self-assignment of x\"\n\t// Another mistake\n\ts.x = s.x // want \"self-assignment of s.x\"\n\n\ts.l[0] = s.l[0] // want \"self-assignment of s.l.0.\"\n\n\t// Report self-assignment to x but preserve the actual assignment to s.x\n\tx, s.x = x, 1 // want \"self-assignment of x\"\n\ts.x, x = 1, x // want \"self-assignment of x\"\n\n\t// Delete multiple self-assignment\n\tx, s.x = x, s.x                       // want \"self-assignment of x, s.x\"\n\ts.l[0], x, s.x = 1, x, s.x            // want \"self-assignment of x, s.x\"\n\tx, s.l[0], s.x = x, 1, s.x            // want \"self-assignment of x, s.x\"\n\tx, s.x, s.l[0] = x, s.x, 1            // want \"self-assignment of x, s.x\"\n\ts.l[0], x, s.x, s.l[1] = 1, x, s.x, 1 // want \"self-assignment of x, s.x\"\n\tx, s.l[0], s.l[1], s.x = x, 1, 1, s.x // want \"self-assignment of x, s.x\"\n\n\t// Bail on any potential side effects to avoid false positives\n\ts.l[num()] = s.l[num()]\n\trng := rand.New(rand.NewSource(0))\n\ts.l[rng.Intn(len(s.l))] = s.l[rng.Intn(len(s.l))]\n\ts.l[<-ch] = s.l[<-ch]\n}\n\nfunc num() int { return 2 }\n\nfunc Index() {\n\ts := []int{1}\n\ts[0] = s[0] // want \"self-assignment\"\n\n\tvar a [5]int\n\ta[0] = a[0] // want \"self-assignment\"\n\n\tpa := &[2]int{1, 2}\n\tpa[1] = pa[1] // want \"self-assignment\"\n\n\tvar pss *struct { // report self assignment despite nil dereference\n\t\ts []int\n\t}\n\tpss.s[0] = pss.s[0] // want \"self-assignment\"\n\n\tm := map[int]string{1: \"a\"}\n\tm[0] = m[0]     // bail on map self-assignments due to side effects\n\tm[1] = m[1]     // not modeling what elements must be in the map\n\t(m[2]) = (m[2]) // even with parens\n\ttype Map map[string]bool\n\tnamed := make(Map)\n\tnamed[\"s\"] = named[\"s\"] // even on named maps.\n\tvar psm *struct {\n\t\tm map[string]int\n\t}\n\tpsm.m[\"key\"] = psm.m[\"key\"] // handles dereferences\n}\n"
  },
  {
    "path": "go/analysis/passes/assign/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the useless-assignment checker.\n\npackage testdata\n\nimport \"math/rand\"\n\ntype ST struct {\n\tx int\n\tl []int\n}\n\nfunc (s *ST) SetX(x int, ch chan int) {\n\t// Accidental self-assignment; it should be \"s.x = x\"\n\t// Another mistake\n\n\t// Report self-assignment to x but preserve the actual assignment to s.x\n\ts.x = 1 // want \"self-assignment of x\"\n\ts.x = 1 // want \"self-assignment of x\"\n\n\t// Delete multiple self-assignment\n\ts.l[0] = 1            // want \"self-assignment of x, s.x\"\n\ts.l[0] = 1            // want \"self-assignment of x, s.x\"\n\ts.l[0] = 1            // want \"self-assignment of x, s.x\"\n\ts.l[0], s.l[1] = 1, 1 // want \"self-assignment of x, s.x\"\n\ts.l[0], s.l[1] = 1, 1 // want \"self-assignment of x, s.x\"\n\n\t// Bail on any potential side effects to avoid false positives\n\ts.l[num()] = s.l[num()]\n\trng := rand.New(rand.NewSource(0))\n\ts.l[rng.Intn(len(s.l))] = s.l[rng.Intn(len(s.l))]\n\ts.l[<-ch] = s.l[<-ch]\n}\n\nfunc num() int { return 2 }\n\nfunc Index() {\n\ts := []int{1}\n\n\tvar a [5]int\n\n\tpa := &[2]int{1, 2}\n\n\tvar pss *struct { // report self assignment despite nil dereference\n\t\ts []int\n\t}\n\n\tm := map[int]string{1: \"a\"}\n\tm[0] = m[0]     // bail on map self-assignments due to side effects\n\tm[1] = m[1]     // not modeling what elements must be in the map\n\t(m[2]) = (m[2]) // even with parens\n\ttype Map map[string]bool\n\tnamed := make(Map)\n\tnamed[\"s\"] = named[\"s\"] // even on named maps.\n\tvar psm *struct {\n\t\tm map[string]int\n\t}\n\tpsm.m[\"key\"] = psm.m[\"key\"] // handles dereferences\n}\n"
  },
  {
    "path": "go/analysis/passes/assign/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the useless-assignment checker.\n\npackage testdata\n\nimport \"math/rand\"\n\ntype ST[T interface{ ~int }] struct {\n\tx T\n\tl []T\n}\n\nfunc (s *ST[T]) SetX(x T, ch chan T) {\n\t// Accidental self-assignment; it should be \"s.x = x\"\n\tx = x // want \"self-assignment of x\"\n\t// Another mistake\n\ts.x = s.x // want \"self-assignment of s.x\"\n\n\ts.l[0] = s.l[0] // want \"self-assignment of s.l.0.\"\n\n\t// Bail on any potential side effects to avoid false positives\n\ts.l[num()] = s.l[num()]\n\trng := rand.New(rand.NewSource(0))\n\ts.l[rng.Intn(len(s.l))] = s.l[rng.Intn(len(s.l))]\n\ts.l[<-ch] = s.l[<-ch]\n}\n\nfunc num() int { return 2 }\n"
  },
  {
    "path": "go/analysis/passes/assign/testdata/src/typeparams/typeparams.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the useless-assignment checker.\n\npackage testdata\n\nimport \"math/rand\"\n\ntype ST[T interface{ ~int }] struct {\n\tx T\n\tl []T\n}\n\nfunc (s *ST[T]) SetX(x T, ch chan T) {\n\t// Accidental self-assignment; it should be \"s.x = x\"\n\t// Another mistake\n\n\n\t// Bail on any potential side effects to avoid false positives\n\ts.l[num()] = s.l[num()]\n\trng := rand.New(rand.NewSource(0))\n\ts.l[rng.Intn(len(s.l))] = s.l[rng.Intn(len(s.l))]\n\ts.l[<-ch] = s.l[<-ch]\n}\n\nfunc num() int { return 2 }\n"
  },
  {
    "path": "go/analysis/passes/atomic/atomic.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage atomic\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"atomic\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"atomic\"),\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"sync/atomic\") {\n\t\treturn nil, nil // doesn't directly import sync/atomic\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.AssignStmt)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tn := node.(*ast.AssignStmt)\n\t\tif len(n.Lhs) != len(n.Rhs) {\n\t\t\treturn\n\t\t}\n\t\tif len(n.Lhs) == 1 && n.Tok == token.DEFINE {\n\t\t\treturn\n\t\t}\n\n\t\tfor i, right := range n.Rhs {\n\t\t\tcall, ok := right.(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\t\tif typesinternal.IsFunctionNamed(obj, \"sync/atomic\", \"AddInt32\", \"AddInt64\", \"AddUint32\", \"AddUint64\", \"AddUintptr\") {\n\t\t\t\tcheckAtomicAddAssignment(pass, n.Lhs[i], call)\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// checkAtomicAddAssignment walks the atomic.Add* method calls checking\n// for assigning the return value to the same variable being used in the\n// operation\nfunc checkAtomicAddAssignment(pass *analysis.Pass, left ast.Expr, call *ast.CallExpr) {\n\tif len(call.Args) != 2 {\n\t\treturn\n\t}\n\targ := call.Args[0]\n\tbroken := false\n\n\tgofmt := func(e ast.Expr) string { return astutil.Format(pass.Fset, e) }\n\n\tif uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {\n\t\tbroken = gofmt(left) == gofmt(uarg.X)\n\t} else if star, ok := left.(*ast.StarExpr); ok {\n\t\tbroken = gofmt(star.X) == gofmt(arg)\n\t}\n\n\tif broken {\n\t\tpass.ReportRangef(left, \"direct assignment to atomic value\")\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/atomic/atomic_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage atomic_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/atomic\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, atomic.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/atomic/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package atomic defines an Analyzer that checks for common mistakes\n// using the sync/atomic package.\n//\n// # Analyzer atomic\n//\n// atomic: check for common mistakes using the sync/atomic package\n//\n// The atomic checker looks for assignment statements of the form:\n//\n//\tx = atomic.AddUint64(&x, 1)\n//\n// which are not atomic.\npackage atomic\n"
  },
  {
    "path": "go/analysis/passes/atomic/testdata/src/a/a.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the atomic checker.\n\npackage a\n\nimport (\n\t\"sync/atomic\"\n)\n\ntype Counter uint64\n\nfunc AtomicTests() {\n\tx := uint64(1)\n\tx = atomic.AddUint64(&x, 1)          // want \"direct assignment to atomic value\"\n\t_, x = 10, atomic.AddUint64(&x, 1)   // want \"direct assignment to atomic value\"\n\tx, _ = atomic.AddUint64(&x, 1), 10   // want \"direct assignment to atomic value\"\n\tx, _ = (atomic.AddUint64)(&x, 1), 10 // want \"direct assignment to atomic value\"\n\n\ty := &x\n\t*y = atomic.AddUint64(y, 1) // want \"direct assignment to atomic value\"\n\n\tvar su struct{ Counter uint64 }\n\tsu.Counter = atomic.AddUint64(&su.Counter, 1) // want \"direct assignment to atomic value\"\n\tz1 := atomic.AddUint64(&su.Counter, 1)\n\t_ = z1 // Avoid err \"z declared and not used\"\n\n\tvar sp struct{ Counter *uint64 }\n\t*sp.Counter = atomic.AddUint64(sp.Counter, 1) // want \"direct assignment to atomic value\"\n\tz2 := atomic.AddUint64(sp.Counter, 1)\n\t_ = z2 // Avoid err \"z declared and not used\"\n\n\tau := []uint64{10, 20}\n\tau[0] = atomic.AddUint64(&au[0], 1) // want \"direct assignment to atomic value\"\n\tau[1] = atomic.AddUint64(&au[0], 1)\n\n\tap := []*uint64{&au[0], &au[1]}\n\t*ap[0] = atomic.AddUint64(ap[0], 1) // want \"direct assignment to atomic value\"\n\t*ap[1] = atomic.AddUint64(ap[0], 1)\n\n\tx = atomic.AddUint64() // Used to make vet crash; now silently ignored.\n\n\t{\n\t\t// A variable declaration creates a new variable in the current scope.\n\t\tx := atomic.AddUint64(&x, 1)\n\n\t\t// Re-declaration assigns a new value.\n\t\tx, w := atomic.AddUint64(&x, 1), 10 // want \"direct assignment to atomic value\"\n\t\t_ = w\n\t}\n}\n\ntype T struct{}\n\nfunc (T) AddUint64(addr *uint64, delta uint64) uint64 { return 0 }\n\nfunc NonAtomic() {\n\tx := uint64(1)\n\tvar atomic T\n\tx = atomic.AddUint64(&x, 1) // ok; not the imported pkg\n}\n"
  },
  {
    "path": "go/analysis/passes/atomic/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the atomic checker.\n\npackage a\n\nimport (\n\t\"sync/atomic\"\n)\n\ntype Subtractable interface {\n\t~int64\n}\n\nfunc Sub[T Subtractable](addr *T, delta T) T {\n\t// the followings result in type errors, but doesn't stop this vet check\n\t*addr = atomic.AddInt64(addr, -delta)  // want \"direct assignment to atomic value\"\n\t*addr = atomic.AddUintptr(addr, delta) // want \"direct assignment to atomic value\"\n\tatomic.AddInt64()  // vet ignores it\n\treturn *addr\n}\n\ntype _S[T Subtractable] struct {\n\tx *T\n}\n\nfunc (v _S) AddInt64(_ *int64, delta int64) int64 {\n\t*v.x = atomic.AddInt64(v.x, delta)  // want \"direct assignment to atomic value\"\n\treturn *v.x\n}\n\nfunc NonAtomicInt64() {\n\tvar atomic _S[int64]\n\t*atomic.x = atomic.AddInt64(atomic.x, 123)  // ok; AddInt64 is not sync/atomic.AddInt64.\n}"
  },
  {
    "path": "go/analysis/passes/atomicalign/atomicalign.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package atomicalign defines an Analyzer that checks for non-64-bit-aligned\n// arguments to sync/atomic functions. On non-32-bit platforms, those functions\n// panic if their argument variables are not 64-bit aligned. It is therefore\n// the caller's responsibility to arrange for 64-bit alignment of such variables.\n// See https://golang.org/pkg/sync/atomic/#pkg-note-BUG\npackage atomicalign\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = \"check for non-64-bits-aligned arguments to sync/atomic functions\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"atomicalign\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomicalign\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif 8*pass.TypesSizes.Sizeof(types.Typ[types.Uintptr]) == 64 {\n\t\treturn nil, nil // 64-bit platform\n\t}\n\tif !typesinternal.Imports(pass.Pkg, \"sync/atomic\") {\n\t\treturn nil, nil // doesn't directly import sync/atomic\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tfuncNames := []string{\n\t\t\"AddInt64\", \"AddUint64\",\n\t\t\"LoadInt64\", \"LoadUint64\",\n\t\t\"StoreInt64\", \"StoreUint64\",\n\t\t\"SwapInt64\", \"SwapUint64\",\n\t\t\"CompareAndSwapInt64\", \"CompareAndSwapUint64\",\n\t}\n\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tcall := node.(*ast.CallExpr)\n\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\tif typesinternal.IsFunctionNamed(obj, \"sync/atomic\", funcNames...) {\n\t\t\t// For all the listed functions, the expression to check is always the first function argument.\n\t\t\tcheck64BitAlignment(pass, obj.Name(), call.Args[0])\n\t\t}\n\t})\n\n\treturn nil, nil\n}\n\nfunc check64BitAlignment(pass *analysis.Pass, funcName string, arg ast.Expr) {\n\t// Checks the argument is made of the address operator (&) applied to\n\t// a struct field (as opposed to a variable as the first word of\n\t// uint64 and int64 variables can be relied upon to be 64-bit aligned).\n\tunary, ok := arg.(*ast.UnaryExpr)\n\tif !ok || unary.Op != token.AND {\n\t\treturn\n\t}\n\n\t// Retrieve the types.Struct in order to get the offset of the\n\t// atomically accessed field.\n\tsel, ok := unary.X.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn\n\t}\n\ttvar, ok := pass.TypesInfo.Selections[sel].Obj().(*types.Var)\n\tif !ok || !tvar.IsField() {\n\t\treturn\n\t}\n\n\tstype, ok := pass.TypesInfo.Types[sel.X].Type.Underlying().(*types.Struct)\n\tif !ok {\n\t\treturn\n\t}\n\n\tvar offset int64\n\tvar fields []*types.Var\n\tfor i := 0; i < stype.NumFields(); i++ {\n\t\tf := stype.Field(i)\n\t\tfields = append(fields, f)\n\t\tif f == tvar {\n\t\t\t// We're done, this is the field we were looking for,\n\t\t\t// no need to fill the fields slice further.\n\t\t\toffset = pass.TypesSizes.Offsetsof(fields)[i]\n\t\t\tbreak\n\t\t}\n\t}\n\tif offset&7 == 0 {\n\t\treturn // 64-bit aligned\n\t}\n\n\tpass.ReportRangef(arg, \"address of non 64-bit aligned field .%s passed to atomic.%s\", tvar.Name(), funcName)\n}\n"
  },
  {
    "path": "go/analysis/passes/atomicalign/atomicalign_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage atomicalign_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/atomicalign\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, atomicalign.Analyzer, \"a\", \"b\")\n}\n"
  },
  {
    "path": "go/analysis/passes/atomicalign/testdata/src/a/a.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the atomic alignment checker.\n\n//go:build arm || 386\n// +build arm 386\n\npackage testdata\n\nimport (\n\t\"io\"\n\t\"sync/atomic\"\n)\n\nfunc intsAlignment() {\n\tvar s struct {\n\t\ta bool\n\t\tb uint8\n\t\tc int8\n\t\td byte\n\t\tf int16\n\t\tg int16\n\t\th int64\n\t\ti byte\n\t\tj uint64\n\t}\n\tatomic.AddInt64(&s.h, 9)\n\tatomic.AddUint64(&s.j, 0) // want \"address of non 64-bit aligned field .j passed to atomic.AddUint64\"\n}\n\nfunc floatAlignment() {\n\tvar s struct {\n\t\ta float32\n\t\tb int64\n\t\tc float32\n\t\td float64\n\t\te uint64\n\t}\n\tatomic.LoadInt64(&s.b) // want \"address of non 64-bit aligned field .b passed to atomic.LoadInt64\"\n\tatomic.LoadUint64(&s.e)\n}\n\nfunc uintptrAlignment() {\n\tvar s struct {\n\t\ta uintptr\n\t\tb int64\n\t\tc int\n\t\td uint\n\t\te int32\n\t\tf uint64\n\t}\n\tatomic.StoreInt64(&s.b, 0) // want \"address of non 64-bit aligned field .b passed to atomic.StoreInt64\"\n\tatomic.StoreUint64(&s.f, 0)\n}\n\nfunc runeAlignment() {\n\tvar s struct {\n\t\ta rune\n\t\tb int64\n\t\t_ rune\n\t\tc uint64\n\t}\n\tatomic.SwapInt64(&s.b, 0) // want \"address of non 64-bit aligned field .b passed to atomic.SwapInt64\"\n\tatomic.SwapUint64(&s.c, 0)\n}\n\nfunc complexAlignment() {\n\tvar s struct {\n\t\ta complex64\n\t\tb int64\n\t\tc complex128\n\t\td uint64\n\t}\n\tatomic.CompareAndSwapInt64(&s.b, 0, 1)\n\tatomic.CompareAndSwapUint64(&s.d, 0, 1)\n}\n\n// continuer ici avec les tests\n\nfunc channelAlignment() {\n\tvar a struct {\n\t\ta chan struct{}\n\t\tb int64\n\t\tc <-chan struct{}\n\t\td uint64\n\t}\n\n\tatomic.AddInt64(&a.b, 0) // want \"address of non 64-bit aligned field .b passed to atomic.AddInt64\"\n\tatomic.AddUint64(&a.d, 0)\n}\n\nfunc arrayAlignment() {\n\tvar a struct {\n\t\ta [1]uint16\n\t\tb int64\n\t\t_ [2]uint16\n\t\tc int64\n\t\td [1]uint16\n\t\te uint64\n\t}\n\n\tatomic.LoadInt64(&a.b) // want \"address of non 64-bit aligned field .b passed to atomic.LoadInt64\"\n\tatomic.LoadInt64(&a.c)\n\tatomic.LoadUint64(&a.e)   // want \"address of non 64-bit aligned field .e passed to atomic.LoadUint64\"\n\t(atomic.LoadUint64)(&a.e) // want \"address of non 64-bit aligned field .e passed to atomic.LoadUint64\"\n}\n\nfunc anonymousFieldAlignment() {\n\tvar f struct {\n\t\ta, b int32\n\t\tc, d int64\n\t\t_    bool\n\t\te, f uint64\n\t}\n\n\tatomic.StoreInt64(&f.c, 12)\n\tatomic.StoreInt64(&f.d, 27)\n\tatomic.StoreUint64(&f.e, 6)  // want \"address of non 64-bit aligned field .e passed to atomic.StoreUint64\"\n\tatomic.StoreUint64(&f.f, 79) // want \"address of non 64-bit aligned field .f passed to atomic.StoreUint64\"\n}\n\ntype ts struct {\n\te  int64\n\te2 []int\n\tf  uint64\n}\n\nfunc typedStructAlignment() {\n\tvar b ts\n\tatomic.SwapInt64(&b.e, 9)\n\tatomic.SwapUint64(&b.f, 9) // want \"address of non 64-bit aligned field .f passed to atomic.SwapUint64\"\n}\n\nfunc aliasAlignment() {\n\ttype (\n\t\tmybytea uint8\n\t\tmybyteb byte\n\t\tmybytec = uint8\n\t\tmybyted = byte\n\t)\n\n\tvar e struct {\n\t\ta    byte\n\t\tb    mybytea\n\t\tc    mybyteb\n\t\te    mybytec\n\t\tf    int64\n\t\tg, h uint16\n\t\ti    uint64\n\t}\n\n\tatomic.CompareAndSwapInt64(&e.f, 0, 1) // want \"address of non 64-bit aligned field .f passed to atomic.CompareAndSwapInt64\"\n\tatomic.CompareAndSwapUint64(&e.i, 1, 2)\n}\n\nfunc stringAlignment() {\n\tvar a struct {\n\t\ta uint32\n\t\tb string\n\t\tc int64\n\t}\n\tatomic.AddInt64(&a.c, 10) // want \"address of non 64-bit aligned field .c passed to atomic.AddInt64\"\n}\n\nfunc sliceAlignment() {\n\tvar s struct {\n\t\ta []int32\n\t\tb int64\n\t\tc uint32\n\t\td uint64\n\t}\n\n\tatomic.LoadInt64(&s.b) // want \"address of non 64-bit aligned field .b passed to atomic.LoadInt64\"\n\tatomic.LoadUint64(&s.d)\n}\n\nfunc interfaceAlignment() {\n\tvar s struct {\n\t\ta interface{}\n\t\tb int64\n\t\tc io.Writer\n\t\te int64\n\t\t_ int32\n\t\tf uint64\n\t}\n\n\tatomic.StoreInt64(&s.b, 9)\n\tatomic.StoreInt64(&s.e, 9)\n\tatomic.StoreUint64(&s.f, 9) // want \"address of non 64-bit aligned field .f passed to atomic.StoreUint64\"\n}\n\nfunc pointerAlignment() {\n\tvar s struct {\n\t\ta, b *int\n\t\tc    int64\n\t\td    *interface{}\n\t\te    uint64\n\t}\n\n\tatomic.SwapInt64(&s.c, 9)\n\tatomic.SwapUint64(&s.e, 9) // want \"address of non 64-bit aligned field .e passed to atomic.SwapUint64\"\n}\n\n// non-struct fields are already 64-bits correctly aligned per Go spec\nfunc nonStructFields() {\n\tvar (\n\t\ta *int64\n\t\tb [2]uint64\n\t\tc int64\n\t)\n\n\tatomic.CompareAndSwapInt64(a, 10, 11)\n\tatomic.CompareAndSwapUint64(&b[0], 5, 23)\n\tatomic.CompareAndSwapInt64(&c, -1, -15)\n}\n\nfunc embeddedStructFields() {\n\tvar s1 struct {\n\t\t_ struct{ _ int32 }\n\t\ta int64\n\t\t_ struct{}\n\t\tb uint64\n\t\t_ struct{ _ [2]uint16 }\n\t\tc int64\n\t}\n\n\tatomic.AddInt64(&s1.a, 9)  // want \"address of non 64-bit aligned field .a passed to atomic.AddInt64\"\n\tatomic.AddUint64(&s1.b, 9) // want \"address of non 64-bit aligned field .b passed to atomic.AddUint64\"\n\tatomic.AddInt64(&s1.c, 9)\n}\n"
  },
  {
    "path": "go/analysis/passes/atomicalign/testdata/src/a/stub.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is only here to not trigger \"build constraints exclude all Go files\" during tests\n\npackage testdata\n"
  },
  {
    "path": "go/analysis/passes/atomicalign/testdata/src/b/b.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build !arm,!386\n\npackage testdata\n\nimport (\n\t\"sync/atomic\"\n)\n\nfunc nonAffectedArchs() {\n\tvar s struct {\n\t\t_ bool\n\t\ta uint64\n\t}\n\tatomic.SwapUint64(&s.a, 9) // ok on 64-bit architectures\n}\n"
  },
  {
    "path": "go/analysis/passes/atomicalign/testdata/src/b/stub.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is only here to not trigger \"build constraints exclude all Go files\" during tests\n\npackage testdata\n"
  },
  {
    "path": "go/analysis/passes/bools/bools.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package bools defines an Analyzer that detects common mistakes\n// involving boolean operators.\npackage bools\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = \"check for common mistakes involving boolean operators\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"bools\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/bools\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.BinaryExpr)(nil),\n\t}\n\tseen := make(map[*ast.BinaryExpr]bool)\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\te := n.(*ast.BinaryExpr)\n\t\tif seen[e] {\n\t\t\t// Already processed as a subexpression of an earlier node.\n\t\t\treturn\n\t\t}\n\n\t\tvar op boolOp\n\t\tswitch e.Op {\n\t\tcase token.LOR:\n\t\t\top = or\n\t\tcase token.LAND:\n\t\t\top = and\n\t\tdefault:\n\t\t\treturn\n\t\t}\n\n\t\tcomm := op.commutativeSets(pass.TypesInfo, e, seen)\n\t\tfor _, exprs := range comm {\n\t\t\top.checkRedundant(pass, exprs)\n\t\t\top.checkSuspect(pass, exprs)\n\t\t}\n\t})\n\treturn nil, nil\n}\n\ntype boolOp struct {\n\tname  string\n\ttok   token.Token // token corresponding to this operator\n\tbadEq token.Token // token corresponding to the equality test that should not be used with this operator\n}\n\nvar (\n\tor  = boolOp{\"or\", token.LOR, token.NEQ}\n\tand = boolOp{\"and\", token.LAND, token.EQL}\n)\n\n// commutativeSets returns all side effect free sets of\n// expressions in e that are connected by op.\n// For example, given 'a || b || f() || c || d' with the or op,\n// commutativeSets returns {{b, a}, {d, c}}.\n// commutativeSets adds any expanded BinaryExprs to seen.\nfunc (op boolOp) commutativeSets(info *types.Info, e *ast.BinaryExpr, seen map[*ast.BinaryExpr]bool) [][]ast.Expr {\n\texprs := op.split(e, seen)\n\n\t// Partition the slice of expressions into commutative sets.\n\ti := 0\n\tvar sets [][]ast.Expr\n\tfor j := 0; j <= len(exprs); j++ {\n\t\tif j == len(exprs) || !typesinternal.NoEffects(info, exprs[j]) {\n\t\t\tif i < j {\n\t\t\t\tsets = append(sets, exprs[i:j])\n\t\t\t}\n\t\t\ti = j + 1\n\t\t}\n\t}\n\n\treturn sets\n}\n\n// checkRedundant checks for expressions of the form\n//\n//\te && e\n//\te || e\n//\n// Exprs must contain only side effect free expressions.\nfunc (op boolOp) checkRedundant(pass *analysis.Pass, exprs []ast.Expr) {\n\tseen := make(map[string]bool)\n\tfor _, e := range exprs {\n\t\tefmt := astutil.Format(pass.Fset, e)\n\t\tif seen[efmt] {\n\t\t\tpass.ReportRangef(e, \"redundant %s: %s %s %s\", op.name, efmt, op.tok, efmt)\n\t\t} else {\n\t\t\tseen[efmt] = true\n\t\t}\n\t}\n}\n\n// checkSuspect checks for expressions of the form\n//\n//\tx != c1 || x != c2\n//\tx == c1 && x == c2\n//\n// where c1 and c2 are constant expressions.\n// If c1 and c2 are the same then it's redundant;\n// if c1 and c2 are different then it's always true or always false.\n// Exprs must contain only side effect free expressions.\nfunc (op boolOp) checkSuspect(pass *analysis.Pass, exprs []ast.Expr) {\n\t// seen maps from expressions 'x' to equality expressions 'x != c'.\n\tseen := make(map[string]string)\n\n\tfor _, e := range exprs {\n\t\tbin, ok := e.(*ast.BinaryExpr)\n\t\tif !ok || bin.Op != op.badEq {\n\t\t\tcontinue\n\t\t}\n\n\t\t// In order to avoid false positives, restrict to cases\n\t\t// in which one of the operands is constant. We're then\n\t\t// interested in the other operand.\n\t\t// In the rare case in which both operands are constant\n\t\t// (e.g. runtime.GOOS and \"windows\"), we'll only catch\n\t\t// mistakes if the LHS is repeated, which is how most\n\t\t// code is written.\n\t\tvar x ast.Expr\n\t\tswitch {\n\t\tcase pass.TypesInfo.Types[bin.Y].Value != nil:\n\t\t\tx = bin.X\n\t\tcase pass.TypesInfo.Types[bin.X].Value != nil:\n\t\t\tx = bin.Y\n\t\tdefault:\n\t\t\tcontinue\n\t\t}\n\n\t\t// e is of the form 'x != c' or 'x == c'.\n\t\txfmt := astutil.Format(pass.Fset, x)\n\t\tefmt := astutil.Format(pass.Fset, e)\n\t\tif prev, found := seen[xfmt]; found {\n\t\t\t// checkRedundant handles the case in which efmt == prev.\n\t\t\tif efmt != prev {\n\t\t\t\tpass.ReportRangef(e, \"suspect %s: %s %s %s\", op.name, efmt, op.tok, prev)\n\t\t\t}\n\t\t} else {\n\t\t\tseen[xfmt] = efmt\n\t\t}\n\t}\n}\n\n// split returns a slice of all subexpressions in e that are connected by op.\n// For example, given 'a || (b || c) || d' with the or op,\n// split returns []{d, c, b, a}.\n// seen[e] is already true; any newly processed exprs are added to seen.\nfunc (op boolOp) split(e ast.Expr, seen map[*ast.BinaryExpr]bool) (exprs []ast.Expr) {\n\tfor {\n\t\te = ast.Unparen(e)\n\t\tif b, ok := e.(*ast.BinaryExpr); ok && b.Op == op.tok {\n\t\t\tseen[b] = true\n\t\t\texprs = append(exprs, op.split(b.Y, seen)...)\n\t\t\te = b.X\n\t\t} else {\n\t\t\texprs = append(exprs, e)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "go/analysis/passes/bools/bools_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bools_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/bools\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, bools.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/bools/testdata/src/a/a.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the bool checker.\n\npackage a\n\nimport \"io\"\n\ntype T int\n\nfunc (t T) Foo() int { return int(t) }\n\ntype FT func() int\n\nvar S []int\n\nfunc RatherStupidConditions() {\n\tvar f, g func() int\n\tif f() == 0 || f() == 0 { // OK f might have side effects\n\t}\n\tvar t T\n\t_ = t.Foo() == 2 || t.Foo() == 2        // OK Foo might have side effects\n\tif v, w := f(), g(); v == w || v == w { // want `redundant or: v == w \\|\\| v == w`\n\t}\n\t_ = f == nil || f == nil // want `redundant or: f == nil \\|\\| f == nil`\n\n\tvar B byte\n\t_ = B == byte(1) || B == byte(1) // want `redundant or: B == byte\\(1\\) \\|\\| B == byte\\(1\\)`\n\t_ = t == T(2) || t == T(2)       // want `redundant or: t == T\\(2\\) \\|\\| t == T\\(2\\)`\n\t_ = FT(f) == nil || FT(f) == nil // want `redundant or: FT\\(f\\) == nil \\|\\| FT\\(f\\) == nil`\n\n\t_ = (func() int)(f) == nil || (func() int)(f) == nil // want `redundant or: \\(func\\(\\) int\\)\\(f\\) == nil \\|\\| \\(func\\(\\) int\\)\\(f\\) == nil`\n\t_ = append(S, 3) == nil || append(S, 3) == nil       // OK append has side effects\n\n\tvar namedFuncVar FT\n\t_ = namedFuncVar() == namedFuncVar() // OK still func calls\n\n\tvar c chan int\n\t_ = 0 == <-c || 0 == <-c                                  // OK subsequent receives may yield different values\n\tfor i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // want `redundant or: i == j \\|\\| i == j`\n\t}\n\n\tvar i, j, k int\n\t_ = i+1 == 1 || i+1 == 1         // want `redundant or: i\\+1 == 1 \\|\\| i\\+1 == 1`\n\t_ = i == 1 || j+1 == i || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\n\t_ = i == 1 || i == 1 || f() == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect\n\t_ = f() == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\n\t// Test partition edge cases\n\t_ = f() == 1 || i == 1 || i == 1 || j == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = f() == 1 || j == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || f() == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || i == 1 || f() == 1 || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || i == 1 || j == 1 || f() == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = j == 1 || i == 1 || i == 1 || f() == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || f() == 1 || f() == 1 || i == 1\n\n\t_ = i == 1 || (i == 1 || i == 2)             // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || (f() == 1 || i == 1)           // OK f may alter i as a side effect\n\t_ = i == 1 || (i == 1 || f() == 1)           // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || (i == 2 || (i == 1 || i == 3)) // want `redundant or: i == 1 \\|\\| i == 1`\n\n\tvar a, b bool\n\t_ = i == 1 || (a || (i == 1 || b)) // want `redundant or: i == 1 \\|\\| i == 1`\n\n\t// Check that all redundant ors are flagged\n\t_ = j == 0 ||\n\t\ti == 1 ||\n\t\tf() == 1 ||\n\t\tj == 0 || // want `redundant or: j == 0 \\|\\| j == 0`\n\t\ti == 1 || // want `redundant or: i == 1 \\|\\| i == 1`\n\t\ti == 1 || // want `redundant or: i == 1 \\|\\| i == 1`\n\t\ti == 1 ||\n\t\tj == 0 ||\n\t\tk == 0\n\n\t_ = i == 1*2*3 || i == 1*2*3 // want `redundant or: i == 1\\*2\\*3 \\|\\| i == 1\\*2\\*3`\n\n\t// These test that redundant, suspect expressions do not trigger multiple errors.\n\t_ = i != 0 || i != 0 // want `redundant or: i != 0 \\|\\| i != 0`\n\t_ = i == 0 && i == 0 // want `redundant and: i == 0 && i == 0`\n\n\t// and is dual to or; check the basics and\n\t// let the or tests pull the rest of the weight.\n\t_ = 0 != <-c && 0 != <-c         // OK subsequent receives may yield different values\n\t_ = f() != 0 && f() != 0         // OK f might have side effects\n\t_ = f != nil && f != nil         // want `redundant and: f != nil && f != nil`\n\t_ = i != 1 && i != 1 && f() != 1 // want `redundant and: i != 1 && i != 1`\n\t_ = i != 1 && f() != 1 && i != 1 // OK f may alter i as a side effect\n\t_ = f() != 1 && i != 1 && i != 1 // want `redundant and: i != 1 && i != 1`\n}\n\nfunc RoyallySuspectConditions() {\n\tvar i, j int\n\n\t_ = i == 0 || i == 1 // OK\n\t_ = i != 0 || i != 1 // want `suspect or: i != 0 \\|\\| i != 1`\n\t_ = i != 0 || 1 != i // want `suspect or: i != 0 \\|\\| 1 != i`\n\t_ = 0 != i || 1 != i // want `suspect or: 0 != i \\|\\| 1 != i`\n\t_ = 0 != i || i != 1 // want `suspect or: 0 != i \\|\\| i != 1`\n\n\t_ = (0 != i) || i != 1 // want `suspect or: 0 != i \\|\\| i != 1`\n\n\t_ = i+3 != 7 || j+5 == 0 || i+3 != 9 // want `suspect or: i\\+3 != 7 \\|\\| i\\+3 != 9`\n\n\t_ = i != 0 || j == 0 || i != 1 // want `suspect or: i != 0 \\|\\| i != 1`\n\n\t_ = i != 0 || i != 1<<4 // want `suspect or: i != 0 \\|\\| i != 1<<4`\n\n\t_ = i != 0 || j != 0\n\t_ = 0 != i || 0 != j\n\n\tvar s string\n\t_ = s != \"one\" || s != \"the other\" // want `suspect or: s != .one. \\|\\| s != .the other.`\n\n\t_ = \"et\" != \"alii\" || \"et\" != \"cetera\"         // want `suspect or: .et. != .alii. \\|\\| .et. != .cetera.`\n\t_ = \"me gustas\" != \"tu\" || \"le gustas\" != \"tu\" // OK we could catch this case, but it's not worth the code\n\n\tvar err error\n\t_ = err != nil || err != io.EOF // TODO catch this case?\n\n\t// Sanity check and.\n\t_ = i != 0 && i != 1 // OK\n\t_ = i == 0 && i == 1 // want `suspect and: i == 0 && i == 1`\n\t_ = i == 0 && 1 == i // want `suspect and: i == 0 && 1 == i`\n\t_ = 0 == i && 1 == i // want `suspect and: 0 == i && 1 == i`\n\t_ = 0 == i && i == 1 // want `suspect and: 0 == i && i == 1`\n}\n"
  },
  {
    "path": "go/analysis/passes/bools/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the bool checker.\n\npackage typeparams\n\ntype T[P interface{ ~int }] struct {\n\ta P\n}\n\nfunc (t T[P]) Foo() int { return int(t.a) }\n\ntype FT[P any] func() P\n\nfunc Sink[Elem any]() chan Elem {\n\treturn make(chan Elem)\n}\n\nfunc RedundantConditions[P interface{ int }]() {\n\ttype _f[P1 any] func() P1\n\n\tvar f, g _f[P]\n\tif f() == 0 || f() == 0 { // OK f might have side effects\n\t}\n\tvar t T[P]\n\t_ = t.Foo() == 2 || t.Foo() == 2        // OK Foo might have side effects\n\tif v, w := f(), g(); v == w || v == w { // want `redundant or: v == w \\|\\| v == w`\n\t}\n\n\t// error messages present type params correctly.\n\t_ = t == T[P]{2} || t == T[P]{2}                 // want `redundant or: t == T\\[P\\]\\{2\\} \\|\\| t == T\\[P\\]\\{2\\}`\n\t_ = FT[P](f) == nil || FT[P](f) == nil           // want `redundant or: FT\\[P\\]\\(f\\) == nil \\|\\| FT\\[P\\]\\(f\\) == nil`\n\t_ = (func() P)(f) == nil || (func() P)(f) == nil // want `redundant or: \\(func\\(\\) P\\)\\(f\\) == nil \\|\\| \\(func\\(\\) P\\)\\(f\\) == nil`\n\n\tvar tint T[int]\n\tvar fint _f[int]\n\t_ = tint == T[int]{2} || tint == T[int]{2}                 // want `redundant or: tint == T\\[int\\]\\{2\\} \\|\\| tint\\ == T\\[int\\]\\{2\\}`\n\t_ = FT[int](fint) == nil || FT[int](fint) == nil           // want `redundant or: FT\\[int\\]\\(fint\\) == nil \\|\\| FT\\[int\\]\\(fint\\) == nil`\n\t_ = (func() int)(fint) == nil || (func() int)(fint) == nil // want `redundant or: \\(func\\(\\) int\\)\\(fint\\) == nil \\|\\| \\(func\\(\\) int\\)\\(fint\\) == nil`\n\n\tc := Sink[P]()\n\t_ = 0 == <-c || 0 == <-c                                  // OK subsequent receives may yield different values\n\tfor i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // want `redundant or: i == j \\|\\| i == j`\n\t}\n\n\tvar i, j P\n\t_ = i == 1 || j+1 == i || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n\t_ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect\n\t_ = f() == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \\|\\| i == 1`\n}\n\nfunc SuspectConditions[P interface{ ~int }, S interface{ ~string }]() {\n\tvar i, j P\n\t_ = i == 0 || i == 1                 // OK\n\t_ = i+3 != 7 || j+5 == 0 || i+3 != 9 // want `suspect or: i\\+3 != 7 \\|\\| i\\+3 != 9`\n\n\tvar s S\n\t_ = s != \"one\" || s != \"the other\" // want `suspect or: s != .one. \\|\\| s != .the other.`\n}\n"
  },
  {
    "path": "go/analysis/passes/buildssa/buildssa.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package buildssa defines an Analyzer that constructs the SSA\n// representation of an error-free package and returns the set of all\n// functions within it. It does not report any diagnostics itself but\n// may be used as an input to other analyzers.\npackage buildssa\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"iter\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/ctrlflow\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"buildssa\",\n\tDoc:        \"build SSA-form IR for later passes\",\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildssa\",\n\tRun:        run,\n\tRequires:   []*analysis.Analyzer{ctrlflow.Analyzer},\n\tResultType: reflect.TypeFor[*SSA](),\n\t// Do not add FactTypes here: SSA construction of P must not\n\t// require SSA construction of all of P's dependencies.\n\t// (That's why we enlist the cheaper ctrlflow pass to compute\n\t// noreturn instead of having go/ssa + buildssa do it.)\n\tFactTypes: nil,\n}\n\n// SSA provides SSA-form intermediate representation for all the\n// source functions in the current package.\ntype SSA struct {\n\tPkg      *ssa.Package\n\tSrcFuncs []*ssa.Function\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tcfgs := pass.ResultOf[ctrlflow.Analyzer].(*ctrlflow.CFGs)\n\n\t// We must create a new Program for each Package because the\n\t// analysis API provides no place to hang a Program shared by\n\t// all Packages. Consequently, SSA Packages and Functions do not\n\t// have a canonical representation across an analysis session of\n\t// multiple packages. This is unlikely to be a problem in\n\t// practice because the analysis API essentially forces all\n\t// packages to be analysed independently, so any given call to\n\t// Analysis.Run on a package will see only SSA objects belonging\n\t// to a single Program.\n\n\t// Some Analyzers may need GlobalDebug, in which case we'll have\n\t// to set it globally, but let's wait till we need it.\n\tmode := ssa.BuilderMode(0)\n\n\tprog := ssa.NewProgram(pass.Fset, mode)\n\n\t// Use the result of the ctrlflow analysis to improve the SSA CFG.\n\tprog.SetNoReturn(cfgs.NoReturn)\n\n\t// Create SSA packages for direct imports.\n\tfor _, p := range pass.Pkg.Imports() {\n\t\tprog.CreatePackage(p, nil, nil, true)\n\t}\n\n\t// Create and build the primary package.\n\tssapkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false)\n\tssapkg.Build()\n\n\t// Compute list of source functions, including literals,\n\t// in source order.\n\tvar funcs []*ssa.Function\n\tfor _, fn := range allFunctions(pass) {\n\t\t// (init functions have distinct Func\n\t\t// objects named \"init\" and distinct\n\t\t// ssa.Functions named \"init#1\", ...)\n\n\t\tf := ssapkg.Prog.FuncValue(fn)\n\t\tif f == nil {\n\t\t\tpanic(fn)\n\t\t}\n\n\t\tvar addAnons func(f *ssa.Function)\n\t\taddAnons = func(f *ssa.Function) {\n\t\t\tfuncs = append(funcs, f)\n\t\t\tfor _, anon := range f.AnonFuncs {\n\t\t\t\taddAnons(anon)\n\t\t\t}\n\t\t}\n\t\taddAnons(f)\n\t}\n\n\treturn &SSA{Pkg: ssapkg, SrcFuncs: funcs}, nil\n}\n\n// allFunctions returns an iterator over all named functions.\nfunc allFunctions(pass *analysis.Pass) iter.Seq2[*ast.FuncDecl, *types.Func] {\n\treturn func(yield func(*ast.FuncDecl, *types.Func) bool) {\n\t\tfor _, file := range pass.Files {\n\t\t\tfor _, decl := range file.Decls {\n\t\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\t\tfn := pass.TypesInfo.Defs[decl.Name].(*types.Func)\n\t\t\t\t\tif !yield(decl, fn) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/buildssa/buildssa_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildssa_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/buildssa\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tresult := analysistest.Run(t, testdata, buildssa.Analyzer, \"a\")[0].Result\n\n\tssainfo := result.(*buildssa.SSA)\n\tgot := fmt.Sprint(ssainfo.SrcFuncs)\n\twant := `[a.Fib (a.T).fib a._ a._]`\n\tif got != want {\n\t\tt.Errorf(\"SSA.SrcFuncs = %s, want %s\", got, want)\n\t\tfor _, f := range ssainfo.SrcFuncs {\n\t\t\tf.WriteTo(os.Stderr)\n\t\t}\n\t}\n}\n\nfunc TestGenericDecls(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tresult := analysistest.Run(t, testdata, buildssa.Analyzer, \"b\")[0].Result\n\n\tssainfo := result.(*buildssa.SSA)\n\tgot := fmt.Sprint(ssainfo.SrcFuncs)\n\twant := `[(*b.Pointer[T]).Load b.Load b.LoadPointer]`\n\tif got != want {\n\t\tt.Errorf(\"SSA.SrcFuncs = %s, want %s\", got, want)\n\t\tfor _, f := range ssainfo.SrcFuncs {\n\t\t\tf.WriteTo(os.Stderr)\n\t\t}\n\t}\n}\n\nfunc TestImporting(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tresult := analysistest.Run(t, testdata, buildssa.Analyzer, \"c\")[0].Result\n\n\tssainfo := result.(*buildssa.SSA)\n\tgot := fmt.Sprint(ssainfo.SrcFuncs)\n\twant := `[c.A c.B]`\n\tif got != want {\n\t\tt.Errorf(\"SSA.SrcFuncs = %s, want %s\", got, want)\n\t\tfor _, f := range ssainfo.SrcFuncs {\n\t\t\tf.WriteTo(os.Stderr)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/buildssa/testdata/src/a/a.go",
    "content": "package a\n\nfunc Fib(x int) int {\n\tif x < 2 {\n\t\treturn x\n\t}\n\treturn Fib(x-1) + Fib(x-2)\n}\n\ntype T int\n\nfunc (T) fib(x int) int { return Fib(x) }\n\nfunc _() {\n\tprint(\"hi\")\n}\n\nfunc _() {\n\tprint(\"hello\")\n}\n"
  },
  {
    "path": "go/analysis/passes/buildssa/testdata/src/b/b.go",
    "content": "// Package b contains declarations of generic functions.\npackage b\n\nimport \"unsafe\"\n\ntype Pointer[T any] struct {\n\tv unsafe.Pointer\n}\n\nfunc (x *Pointer[T]) Load() *T {\n\treturn (*T)(LoadPointer(&x.v))\n}\n\nfunc Load[T any](x *Pointer[T]) *T {\n\treturn x.Load()\n}\n\nfunc LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)\n\nvar G Pointer[int]\n"
  },
  {
    "path": "go/analysis/passes/buildssa/testdata/src/c/c.go",
    "content": "// Package c is to test buildssa importing packages.\npackage c\n\nimport (\n\t\"a\"\n\t\"b\"\n\t\"unsafe\"\n)\n\nfunc A() {\n\t_ = a.Fib(10)\n}\n\nfunc B() {\n\tvar x int\n\tptr := unsafe.Pointer(&x)\n\t_ = b.LoadPointer(&ptr)\n\n\tm := b.G.Load()\n\tf := b.Load(&b.G)\n\tif f != m {\n\t\tpanic(\"loads of b.G are expected to be identical\")\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/buildtag/buildtag.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package buildtag defines an Analyzer that checks build tags.\npackage buildtag\n\nimport (\n\t\"go/ast\"\n\t\"go/build/constraint\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\nconst Doc = \"check //go:build and // +build directives\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"buildtag\",\n\tDoc:  Doc,\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildtag\",\n\tRun:  runBuildTag,\n}\n\nfunc runBuildTag(pass *analysis.Pass) (any, error) {\n\tfor _, f := range pass.Files {\n\t\tcheckGoFile(pass, f)\n\t}\n\tfor _, name := range pass.OtherFiles {\n\t\tif err := checkOtherFile(pass, name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tfor _, name := range pass.IgnoredFiles {\n\t\tif strings.HasSuffix(name, \".go\") {\n\t\t\tf, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments|parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\t// Not valid Go source code - not our job to diagnose, so ignore.\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tcheckGoFile(pass, f)\n\t\t} else {\n\t\t\tif err := checkOtherFile(pass, name); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc checkGoFile(pass *analysis.Pass, f *ast.File) {\n\tvar check checker\n\tcheck.init(pass)\n\tdefer check.finish()\n\n\tfor _, group := range f.Comments {\n\t\t// A +build comment is ignored after or adjoining the package declaration.\n\t\tif group.End()+1 >= f.Package {\n\t\t\tcheck.plusBuildOK = false\n\t\t}\n\t\t// A //go:build comment is ignored after the package declaration\n\t\t// (but adjoining it is OK, in contrast to +build comments).\n\t\tif group.Pos() >= f.Package {\n\t\t\tcheck.goBuildOK = false\n\t\t}\n\n\t\t// Check each line of a //-comment.\n\t\tfor _, c := range group.List {\n\t\t\t// \"+build\" is ignored within or after a /*...*/ comment.\n\t\t\tif !strings.HasPrefix(c.Text, \"//\") {\n\t\t\t\tcheck.plusBuildOK = false\n\t\t\t}\n\t\t\tcheck.comment(c.Slash, c.Text)\n\t\t}\n\t}\n}\n\nfunc checkOtherFile(pass *analysis.Pass, filename string) error {\n\tvar check checker\n\tcheck.init(pass)\n\tdefer check.finish()\n\n\t// We cannot use the Go parser, since this may not be a Go source file.\n\t// Read the raw bytes instead.\n\tcontent, tf, err := analyzerutil.ReadFile(pass, filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcheck.file(token.Pos(tf.Base()), string(content))\n\treturn nil\n}\n\ntype checker struct {\n\tpass         *analysis.Pass\n\tplusBuildOK  bool            // \"+build\" lines still OK\n\tgoBuildOK    bool            // \"go:build\" lines still OK\n\tcrossCheck   bool            // cross-check go:build and +build lines when done reading file\n\tinStar       bool            // currently in a /* */ comment\n\tgoBuildPos   token.Pos       // position of first go:build line found\n\tplusBuildPos token.Pos       // position of first \"+build\" line found\n\tgoBuild      constraint.Expr // go:build constraint found\n\tplusBuild    constraint.Expr // AND of +build constraints found\n}\n\nfunc (check *checker) init(pass *analysis.Pass) {\n\tcheck.pass = pass\n\tcheck.goBuildOK = true\n\tcheck.plusBuildOK = true\n\tcheck.crossCheck = true\n}\n\nfunc (check *checker) file(pos token.Pos, text string) {\n\t// Determine cutpoint where +build comments are no longer valid.\n\t// They are valid in leading // comments in the file followed by\n\t// a blank line.\n\t//\n\t// This must be done as a separate pass because of the\n\t// requirement that the comment be followed by a blank line.\n\tvar plusBuildCutoff int\n\tfullText := text\n\tfor text != \"\" {\n\t\ti := strings.Index(text, \"\\n\")\n\t\tif i < 0 {\n\t\t\ti = len(text)\n\t\t} else {\n\t\t\ti++\n\t\t}\n\t\toffset := len(fullText) - len(text)\n\t\tline := text[:i]\n\t\ttext = text[i:]\n\t\tline = strings.TrimSpace(line)\n\t\tif !strings.HasPrefix(line, \"//\") && line != \"\" {\n\t\t\tbreak\n\t\t}\n\t\tif line == \"\" {\n\t\t\tplusBuildCutoff = offset\n\t\t}\n\t}\n\n\t// Process each line.\n\t// Must stop once we hit goBuildOK == false\n\ttext = fullText\n\tcheck.inStar = false\n\tfor text != \"\" {\n\t\ti := strings.Index(text, \"\\n\")\n\t\tif i < 0 {\n\t\t\ti = len(text)\n\t\t} else {\n\t\t\ti++\n\t\t}\n\t\toffset := len(fullText) - len(text)\n\t\tline := text[:i]\n\t\ttext = text[i:]\n\t\tcheck.plusBuildOK = offset < plusBuildCutoff\n\n\t\tif strings.HasPrefix(line, \"//\") {\n\t\t\tcheck.comment(pos+token.Pos(offset), line)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Keep looking for the point at which //go:build comments\n\t\t// stop being allowed. Skip over, cut out any /* */ comments.\n\t\tfor {\n\t\t\tline = strings.TrimSpace(line)\n\t\t\tif check.inStar {\n\t\t\t\ti := strings.Index(line, \"*/\")\n\t\t\t\tif i < 0 {\n\t\t\t\t\tline = \"\"\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tline = line[i+len(\"*/\"):]\n\t\t\t\tcheck.inStar = false\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif strings.HasPrefix(line, \"/*\") {\n\t\t\t\tcheck.inStar = true\n\t\t\t\tline = line[len(\"/*\"):]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tif line != \"\" {\n\t\t\t// Found non-comment non-blank line.\n\t\t\t// Ends space for valid //go:build comments,\n\t\t\t// but also ends the fraction of the file we can\n\t\t\t// reliably parse. From this point on we might\n\t\t\t// incorrectly flag \"comments\" inside multiline\n\t\t\t// string constants or anything else (this might\n\t\t\t// not even be a Go program). So stop.\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (check *checker) comment(pos token.Pos, text string) {\n\tif strings.HasPrefix(text, \"//\") {\n\t\tif strings.Contains(text, \"+build\") {\n\t\t\tcheck.plusBuildLine(pos, text)\n\t\t}\n\t\tif strings.Contains(text, \"//go:build\") {\n\t\t\tcheck.goBuildLine(pos, text)\n\t\t}\n\t}\n\tif strings.HasPrefix(text, \"/*\") {\n\t\tif i := strings.Index(text, \"\\n\"); i >= 0 {\n\t\t\t// multiline /* */ comment - process interior lines\n\t\t\tcheck.inStar = true\n\t\t\ti++\n\t\t\tpos += token.Pos(i)\n\t\t\ttext = text[i:]\n\t\t\tfor text != \"\" {\n\t\t\t\ti := strings.Index(text, \"\\n\")\n\t\t\t\tif i < 0 {\n\t\t\t\t\ti = len(text)\n\t\t\t\t} else {\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\tline := text[:i]\n\t\t\t\tif strings.HasPrefix(line, \"//\") {\n\t\t\t\t\tcheck.comment(pos, line)\n\t\t\t\t}\n\t\t\t\tpos += token.Pos(i)\n\t\t\t\ttext = text[i:]\n\t\t\t}\n\t\t\tcheck.inStar = false\n\t\t}\n\t}\n}\n\nfunc (check *checker) goBuildLine(pos token.Pos, line string) {\n\tif !constraint.IsGoBuild(line) {\n\t\tif !strings.HasPrefix(line, \"//go:build\") && constraint.IsGoBuild(\"//\"+strings.TrimSpace(line[len(\"//\"):])) {\n\t\t\tcheck.pass.Reportf(pos, \"malformed //go:build line (space between // and go:build)\")\n\t\t}\n\t\treturn\n\t}\n\tif !check.goBuildOK || check.inStar {\n\t\tcheck.pass.Reportf(pos, \"misplaced //go:build comment\")\n\t\tcheck.crossCheck = false\n\t\treturn\n\t}\n\n\tif check.goBuildPos == token.NoPos {\n\t\tcheck.goBuildPos = pos\n\t} else {\n\t\tcheck.pass.Reportf(pos, \"unexpected extra //go:build line\")\n\t\tcheck.crossCheck = false\n\t}\n\n\t// testing hack: stop at // ERROR\n\tif i := strings.Index(line, \" // ERROR \"); i >= 0 {\n\t\tline = line[:i]\n\t}\n\n\tx, err := constraint.Parse(line)\n\tif err != nil {\n\t\tcheck.pass.Reportf(pos, \"%v\", err)\n\t\tcheck.crossCheck = false\n\t\treturn\n\t}\n\n\tcheck.tags(pos, x)\n\n\tif check.goBuild == nil {\n\t\tcheck.goBuild = x\n\t}\n}\n\nfunc (check *checker) plusBuildLine(pos token.Pos, line string) {\n\tline = strings.TrimSpace(line)\n\tif !constraint.IsPlusBuild(line) {\n\t\t// Comment with +build but not at beginning.\n\t\t// Only report early in file.\n\t\tif check.plusBuildOK && !strings.HasPrefix(line, \"// want\") {\n\t\t\tcheck.pass.Reportf(pos, \"possible malformed +build comment\")\n\t\t}\n\t\treturn\n\t}\n\tif !check.plusBuildOK { // inStar implies !plusBuildOK\n\t\tcheck.pass.Reportf(pos, \"misplaced +build comment\")\n\t\tcheck.crossCheck = false\n\t}\n\n\tif check.plusBuildPos == token.NoPos {\n\t\tcheck.plusBuildPos = pos\n\t}\n\n\t// testing hack: stop at // ERROR\n\tif i := strings.Index(line, \" // ERROR \"); i >= 0 {\n\t\tline = line[:i]\n\t}\n\n\tfields := strings.Fields(line[len(\"//\"):])\n\t// IsPlusBuildConstraint check above implies fields[0] == \"+build\"\n\tfor _, arg := range fields[1:] {\n\t\tfor elem := range strings.SplitSeq(arg, \",\") {\n\t\t\tif strings.HasPrefix(elem, \"!!\") {\n\t\t\t\tcheck.pass.Reportf(pos, \"invalid double negative in build constraint: %s\", arg)\n\t\t\t\tcheck.crossCheck = false\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\telem = strings.TrimPrefix(elem, \"!\")\n\t\t\tfor _, c := range elem {\n\t\t\t\tif !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {\n\t\t\t\t\tcheck.pass.Reportf(pos, \"invalid non-alphanumeric build constraint: %s\", arg)\n\t\t\t\t\tcheck.crossCheck = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif check.crossCheck {\n\t\ty, err := constraint.Parse(line)\n\t\tif err != nil {\n\t\t\t// Should never happen - constraint.Parse never rejects a // +build line.\n\t\t\t// Also, we just checked the syntax above.\n\t\t\t// Even so, report.\n\t\t\tcheck.pass.Reportf(pos, \"%v\", err)\n\t\t\tcheck.crossCheck = false\n\t\t\treturn\n\t\t}\n\t\tcheck.tags(pos, y)\n\n\t\tif check.plusBuild == nil {\n\t\t\tcheck.plusBuild = y\n\t\t} else {\n\t\t\tcheck.plusBuild = &constraint.AndExpr{X: check.plusBuild, Y: y}\n\t\t}\n\t}\n}\n\nfunc (check *checker) finish() {\n\tif !check.crossCheck || check.plusBuildPos == token.NoPos || check.goBuildPos == token.NoPos {\n\t\treturn\n\t}\n\n\t// Have both //go:build and // +build,\n\t// with no errors found (crossCheck still true).\n\t// Check they match.\n\tvar want constraint.Expr\n\tlines, err := constraint.PlusBuildLines(check.goBuild)\n\tif err != nil {\n\t\tcheck.pass.Reportf(check.goBuildPos, \"%v\", err)\n\t\treturn\n\t}\n\tfor _, line := range lines {\n\t\ty, err := constraint.Parse(line)\n\t\tif err != nil {\n\t\t\t// Definitely should not happen, but not the user's fault.\n\t\t\t// Do not report.\n\t\t\treturn\n\t\t}\n\t\tif want == nil {\n\t\t\twant = y\n\t\t} else {\n\t\t\twant = &constraint.AndExpr{X: want, Y: y}\n\t\t}\n\t}\n\tif want.String() != check.plusBuild.String() {\n\t\tcheck.pass.Reportf(check.plusBuildPos, \"+build lines do not match //go:build condition\")\n\t\treturn\n\t}\n}\n\n// tags reports issues in go versions in tags within the expression e.\nfunc (check *checker) tags(pos token.Pos, e constraint.Expr) {\n\t// Use Eval to visit each tag.\n\t_ = e.Eval(func(tag string) bool {\n\t\tif malformedGoTag(tag) {\n\t\t\tcheck.pass.Reportf(pos, \"invalid go version %q in build constraint\", tag)\n\t\t}\n\t\treturn false // result is immaterial as Eval does not short-circuit\n\t})\n}\n\n// malformedGoTag returns true if a tag is likely to be a malformed\n// go version constraint.\nfunc malformedGoTag(tag string) bool {\n\t// Not a go version?\n\tif !strings.HasPrefix(tag, \"go1\") {\n\t\t// Check for close misspellings of the \"go1.\" prefix.\n\t\tfor _, pre := range []string{\"go.\", \"g1.\", \"go\"} {\n\t\t\tsuffix := strings.TrimPrefix(tag, pre)\n\t\t\tif suffix != tag && validGoVersion(\"go1.\"+suffix) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// The tag starts with \"go1\" so it is almost certainly a GoVersion.\n\t// Report it if it is not a valid build constraint.\n\treturn !validGoVersion(tag)\n}\n\n// validGoVersion reports when a tag is a valid go version.\nfunc validGoVersion(tag string) bool {\n\treturn constraint.GoVersion(&constraint.TagExpr{Tag: tag}) != \"\"\n}\n"
  },
  {
    "path": "go/analysis/passes/buildtag/buildtag_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildtag_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/buildtag\"\n)\n\nfunc Test(t *testing.T) {\n\t// This test has a dedicated hack in the analysistest package:\n\t// Because it cares about IgnoredFiles, which most analyzers\n\t// ignore, the test framework will consider expectations in\n\t// ignore files too, but only for this analyzer.\n\tanalysistest.Run(t, analysistest.TestData(), buildtag.Analyzer, \"a\", \"b\")\n}\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the buildtag checker.\n\n// want +1 `possible malformed \\+build comment`\n// +builder\n// +build ignore\n\n// Mention +build // want `possible malformed \\+build comment`\n\n// want +1 `misplaced \\+build comment`\n// +build nospace\n//go:build ok\npackage a\n\n// want +1 `misplaced \\+build comment`\n// +build toolate\n\nvar _ = 3\n\nvar _ = `\n// +build notacomment\n`\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag2.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build no\n\npackage a\n\n// want +1 `misplaced \\+build comment`\n// +build toolate\n\n// want +1 `misplaced //go:build comment`\n//go:build toolate\n\nvar _ = `\n// +build notacomment\n`\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag3.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +3 `[+]build lines do not match //go:build condition`\n\n//go:build good\n// +build bad\n\npackage a\n\nvar _ = `\n// +build notacomment\n`\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag4.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !(bad || worse)\n// +build !bad\n// +build !worse\n\npackage a\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag5.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !(bad || worse)\n// +build !bad,!worse\n\npackage a\n\n//want +1 `misplaced \\+build comment`\n// +build other\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag6.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n#include \"go_asm.h\"\n\n// ok because we cannot parse assembly files.\n// +build no\n\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag7.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build ignore\n\n#include \"go_asm.h\"\n\n// ok because we cannot parse assembly files\n// the assembler would complain if we did assemble this file.\n//go:build no\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/a/buildtag8.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +3 `\\+build lines do not match //go:build condition`\n\n//go:build something\n// +build ignore\n\n#include \"go_asm.h\"\n\n// ok because we cannot parse assembly files\n// the assembler would complain if we did assemble this file.\n//go:build no\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +3 `invalid go version \\\"go1.20.1\\\" in build constraint`\n// want +1 `invalid go version \\\"go1.20.1\\\" in build constraint`\n//go:build go1.20.1\n// +build go1.20.1\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers1.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is intentionally so its build tags always match.\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers2.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `invalid go version \\\"go120\\\" in build constraint`\n//go:build go120\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers3.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `invalid go version \\\"go1..20\\\" in build constraint`\n//go:build go1..20\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers4.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `invalid go version \\\"go.20\\\" in build constraint`\n//go:build go.20\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers5.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `invalid go version \\\"g1.20\\\" in build constraint`\n//go:build g1.20\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/buildtag/testdata/src/b/vers6.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `invalid go version \\\"go20\\\" in build constraint`\n//go:build go20\n\npackage b\n"
  },
  {
    "path": "go/analysis/passes/cgocall/cgocall.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cgocall defines an Analyzer that detects some violations of\n// the cgo pointer passing rules.\npackage cgocall\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst debug = false\n\nconst Doc = `detect some violations of the cgo pointer passing rules\n\nCheck for invalid cgo pointer passing.\nThis looks for code that uses cgo to call C code passing values\nwhose types are almost always invalid according to the cgo pointer\nsharing rules.\nSpecifically, it warns about attempts to pass a Go chan, map, func,\nor slice to C, either directly, or via a pointer, array, or struct.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"cgocall\",\n\tDoc:              Doc,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/cgocall\",\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"runtime/cgo\") {\n\t\treturn nil, nil // doesn't use cgo\n\t}\n\n\tcgofiles, info, err := typeCheckCgoSourceFiles(pass.Fset, pass.Pkg, pass.Files, pass.TypesInfo, pass.TypesSizes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, f := range cgofiles {\n\t\tcheckCgo(pass.Fset, f, info, pass.Reportf)\n\t}\n\treturn nil, nil\n}\n\nfunc checkCgo(fset *token.FileSet, f *ast.File, info *types.Info, reportf func(token.Pos, string, ...any)) {\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tcall, ok := n.(*ast.CallExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\n\t\t// Is this a C.f() call?\n\t\tvar name string\n\t\tif sel, ok := ast.Unparen(call.Fun).(*ast.SelectorExpr); ok {\n\t\t\tif id, ok := sel.X.(*ast.Ident); ok && id.Name == \"C\" {\n\t\t\t\tname = sel.Sel.Name\n\t\t\t}\n\t\t}\n\t\tif name == \"\" {\n\t\t\treturn true // not a call we need to check\n\t\t}\n\n\t\t// A call to C.CBytes passes a pointer but is always safe.\n\t\tif name == \"CBytes\" {\n\t\t\treturn true\n\t\t}\n\n\t\tif debug {\n\t\t\tlog.Printf(\"%s: call to C.%s\", fset.Position(call.Lparen), name)\n\t\t}\n\n\t\tfor _, arg := range call.Args {\n\t\t\tif !typeOKForCgoCall(cgoBaseType(info, arg), make(map[types.Type]bool)) {\n\t\t\t\treportf(arg.Pos(), \"possibly passing Go type with embedded pointer to C\")\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Check for passing the address of a bad type.\n\t\t\tif conv, ok := arg.(*ast.CallExpr); ok && len(conv.Args) == 1 &&\n\t\t\t\tisUnsafePointer(info, conv.Fun) {\n\t\t\t\targ = conv.Args[0]\n\t\t\t}\n\t\t\tif u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {\n\t\t\t\tif !typeOKForCgoCall(cgoBaseType(info, u.X), make(map[types.Type]bool)) {\n\t\t\t\t\treportf(arg.Pos(), \"possibly passing Go type with embedded pointer to C\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// typeCheckCgoSourceFiles returns type-checked syntax trees for the raw\n// cgo files of a package (those that import \"C\"). Such files are not\n// Go, so there may be gaps in type information around C.f references.\n//\n// This checker was initially written in vet to inspect raw cgo source\n// files using partial type information. However, Analyzers in the new\n// analysis API are presented with the type-checked, \"cooked\" Go ASTs\n// resulting from cgo-processing files, so we must choose between\n// working with the cooked file generated by cgo (which was tried but\n// proved fragile) or locating the raw cgo file (e.g. from //line\n// directives) and working with that, as we now do.\n//\n// Specifically, we must type-check the raw cgo source files (or at\n// least the subtrees needed for this analyzer) in an environment that\n// simulates the rest of the already type-checked package.\n//\n// For example, for each raw cgo source file in the original package,\n// such as this one:\n//\n//\tpackage p\n//\timport \"C\"\n//\timport \"fmt\"\n//\ttype T int\n//\tconst k = 3\n//\tvar x, y = fmt.Println()\n//\tfunc f() { ... }\n//\tfunc g() { ... C.malloc(k) ... }\n//\tfunc (T) f(int) string { ... }\n//\n// we synthesize a new ast.File, shown below, that dot-imports the\n// original \"cooked\" package using a special name (\"·this·\"), so that all\n// references to package members resolve correctly. (References to\n// unexported names cause an \"unexported\" error, which we ignore.)\n//\n// To avoid shadowing names imported from the cooked package,\n// package-level declarations in the new source file are modified so\n// that they do not declare any names.\n// (The cgocall analysis is concerned with uses, not declarations.)\n// Specifically, type declarations are discarded;\n// all names in each var and const declaration are blanked out;\n// each method is turned into a regular function by turning\n// the receiver into the first parameter;\n// and all functions are renamed to \"_\".\n//\n//\tpackage p\n//\timport . \"·this·\" // declares T, k, x, y, f, g, T.f\n//\timport \"C\"\n//\timport \"fmt\"\n//\tconst _ = 3\n//\tvar _, _ = fmt.Println()\n//\tfunc _() { ... }\n//\tfunc _() { ... C.malloc(k) ... }\n//\tfunc _(T, int) string { ... }\n//\n// In this way, the raw function bodies and const/var initializer\n// expressions are preserved but refer to the \"cooked\" objects imported\n// from \"·this·\", and none of the transformed package-level declarations\n// actually declares anything. In the example above, the reference to k\n// in the argument of the call to C.malloc resolves to \"·this·\".k, which\n// has an accurate type.\n//\n// This approach could in principle be generalized to more complex\n// analyses on raw cgo files. One could synthesize a \"C\" package so that\n// C.f would resolve to \"·this·\"._C_func_f, for example. But we have\n// limited ourselves here to preserving function bodies and initializer\n// expressions since that is all that the cgocall analyzer needs.\nfunc typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*ast.File, info *types.Info, sizes types.Sizes) ([]*ast.File, *types.Info, error) {\n\tconst thispkg = \"·this·\"\n\n\t// Which files are cgo files?\n\tvar cgoFiles []*ast.File\n\timportMap := map[string]*types.Package{thispkg: pkg}\n\tfor _, raw := range files {\n\t\t// If f is a cgo-generated file, Position reports\n\t\t// the original file, honoring //line directives.\n\t\tfilename := fset.Position(raw.Pos()).Filename // sic: Pos, not FileStart\n\t\tf, err := parser.ParseFile(fset, filename, nil, parser.SkipObjectResolution)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"can't parse raw cgo file: %v\", err)\n\t\t}\n\t\tfound := false\n\t\tfor _, spec := range f.Imports {\n\t\t\tif spec.Path.Value == `\"C\"` {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tcontinue // not a cgo file\n\t\t}\n\n\t\t// Record the original import map.\n\t\tfor _, spec := range raw.Imports {\n\t\t\tpath, _ := strconv.Unquote(spec.Path.Value)\n\t\t\timportMap[path] = imported(info, spec)\n\t\t}\n\n\t\t// Add special dot-import declaration:\n\t\t//    import . \"·this·\"\n\t\tvar decls []ast.Decl\n\t\tdecls = append(decls, &ast.GenDecl{\n\t\t\tTok: token.IMPORT,\n\t\t\tSpecs: []ast.Spec{\n\t\t\t\t&ast.ImportSpec{\n\t\t\t\t\tName: &ast.Ident{Name: \".\"},\n\t\t\t\t\tPath: &ast.BasicLit{\n\t\t\t\t\t\tKind:  token.STRING,\n\t\t\t\t\t\tValue: strconv.Quote(thispkg),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\n\t\t// Transform declarations from the raw cgo file.\n\t\tfor _, decl := range f.Decls {\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tswitch decl.Tok {\n\t\t\t\tcase token.TYPE:\n\t\t\t\t\t// Discard type declarations.\n\t\t\t\t\tcontinue\n\t\t\t\tcase token.IMPORT:\n\t\t\t\t\t// Keep imports.\n\t\t\t\tcase token.VAR, token.CONST:\n\t\t\t\t\t// Blank the declared var/const names.\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\t\tfor i := range spec.Names {\n\t\t\t\t\t\t\tspec.Names[i].Name = \"_\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\t// Blank the declared func name.\n\t\t\t\tdecl.Name.Name = \"_\"\n\n\t\t\t\t// Turn a method receiver:  func (T) f(P) R {...}\n\t\t\t\t// into regular parameter:  func _(T, P) R {...}\n\t\t\t\tif decl.Recv != nil {\n\t\t\t\t\tvar params []*ast.Field\n\t\t\t\t\tparams = append(params, decl.Recv.List...)\n\t\t\t\t\tparams = append(params, decl.Type.Params.List...)\n\t\t\t\t\tdecl.Type.Params.List = params\n\t\t\t\t\tdecl.Recv = nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tdecls = append(decls, decl)\n\t\t}\n\t\tf.Decls = decls\n\t\tif debug {\n\t\t\tformat.Node(os.Stderr, fset, f) // debugging\n\t\t}\n\t\tcgoFiles = append(cgoFiles, f)\n\t}\n\tif cgoFiles == nil {\n\t\treturn nil, nil, nil // nothing to do (can't happen?)\n\t}\n\n\t// Type-check the synthetic files.\n\ttc := &types.Config{\n\t\tFakeImportC: true,\n\t\tImporter: importerFunc(func(path string) (*types.Package, error) {\n\t\t\treturn importMap[path], nil\n\t\t}),\n\t\tSizes: sizes,\n\t\tError: func(error) {}, // ignore errors (e.g. unused import)\n\t}\n\tsetGoVersion(tc, pkg)\n\n\t// It's tempting to record the new types in the\n\t// existing pass.TypesInfo, but we don't own it.\n\taltInfo := &types.Info{\n\t\tTypes: make(map[ast.Expr]types.TypeAndValue),\n\t}\n\ttc.Check(pkg.Path(), fset, cgoFiles, altInfo)\n\n\treturn cgoFiles, altInfo, nil\n}\n\n// cgoBaseType tries to look through type conversions involving\n// unsafe.Pointer to find the real type. It converts:\n//\n//\tunsafe.Pointer(x) => x\n//\t*(*unsafe.Pointer)(unsafe.Pointer(&x)) => x\nfunc cgoBaseType(info *types.Info, arg ast.Expr) types.Type {\n\tswitch arg := arg.(type) {\n\tcase *ast.CallExpr:\n\t\tif len(arg.Args) == 1 && isUnsafePointer(info, arg.Fun) {\n\t\t\treturn cgoBaseType(info, arg.Args[0])\n\t\t}\n\tcase *ast.StarExpr:\n\t\tcall, ok := arg.X.(*ast.CallExpr)\n\t\tif !ok || len(call.Args) != 1 {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *f(v).\n\t\tt := info.Types[call.Fun].Type\n\t\tif t == nil {\n\t\t\tbreak\n\t\t}\n\t\tptr, ok := t.Underlying().(*types.Pointer)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *(*p)(v)\n\t\telem, ok := ptr.Elem().Underlying().(*types.Basic)\n\t\tif !ok || elem.Kind() != types.UnsafePointer {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *(*unsafe.Pointer)(v)\n\t\tcall, ok = call.Args[0].(*ast.CallExpr)\n\t\tif !ok || len(call.Args) != 1 {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *(*unsafe.Pointer)(f(v))\n\t\tif !isUnsafePointer(info, call.Fun) {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(v))\n\t\tu, ok := call.Args[0].(*ast.UnaryExpr)\n\t\tif !ok || u.Op != token.AND {\n\t\t\tbreak\n\t\t}\n\t\t// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(&v))\n\t\treturn cgoBaseType(info, u.X)\n\t}\n\n\treturn info.Types[arg].Type\n}\n\n// typeOKForCgoCall reports whether the type of arg is OK to pass to a\n// C function using cgo. This is not true for Go types with embedded\n// pointers. m is used to avoid infinite recursion on recursive types.\nfunc typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {\n\tif t == nil || m[t] {\n\t\treturn true\n\t}\n\tm[t] = true\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Chan, *types.Map, *types.Signature, *types.Slice:\n\t\treturn false\n\tcase *types.Pointer:\n\t\treturn typeOKForCgoCall(t.Elem(), m)\n\tcase *types.Array:\n\t\treturn typeOKForCgoCall(t.Elem(), m)\n\tcase *types.Struct:\n\t\tfor field := range t.Fields() {\n\t\t\tif !typeOKForCgoCall(field.Type(), m) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\nfunc isUnsafePointer(info *types.Info, e ast.Expr) bool {\n\tt := info.Types[e].Type\n\treturn t != nil && t.Underlying() == types.Typ[types.UnsafePointer]\n}\n\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n\n// TODO(adonovan): make this a library function or method of Info.\nfunc imported(info *types.Info, spec *ast.ImportSpec) *types.Package {\n\tobj, ok := info.Implicits[spec]\n\tif !ok {\n\t\tobj = info.Defs[spec.Name] // renaming import\n\t}\n\treturn obj.(*types.PkgName).Imported()\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/cgocall_go120.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.21\n\npackage cgocall\n\nimport \"go/types\"\n\nfunc setGoVersion(tc *types.Config, pkg *types.Package) {\n\t// no types.Package.GoVersion until Go 1.21\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/cgocall_go121.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.21\n\npackage cgocall\n\nimport \"go/types\"\n\nfunc setGoVersion(tc *types.Config, pkg *types.Package) {\n\ttc.GoVersion = pkg.GoVersion()\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/cgocall_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cgocall_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/cgocall\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, cgocall.Analyzer, \"a\", \"b\", \"c\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/testdata/src/a/cgo.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the cgo checker.\n\npackage a\n\n// void f(void *ptr) {}\nimport \"C\"\n\nimport \"unsafe\"\n\nfunc CgoTests() {\n\tvar c chan bool\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&c))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&c))                     // want \"embedded pointer\"\n\n\tvar m map[string]string\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&m))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&m))                     // want \"embedded pointer\"\n\n\tvar f func()\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&f))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&f))                     // want \"embedded pointer\"\n\n\tvar s []int\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&s))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&s))                     // want \"embedded pointer\"\n\n\tvar a [1][]int\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&a))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&a))                     // want \"embedded pointer\"\n\n\tvar st struct{ f []int }\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&st))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&st))                     // want \"embedded pointer\"\n\n\tvar st3 S\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&st3))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&st3))                     // want \"embedded pointer\"\n\n\t// The following cases are OK.\n\tvar i int\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&i)))\n\tC.f(unsafe.Pointer(&i))\n\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&s[0])))\n\tC.f(unsafe.Pointer(&s[0]))\n\n\tvar a2 [1]int\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&a2)))\n\tC.f(unsafe.Pointer(&a2))\n\n\tvar st2 struct{ i int }\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&st2)))\n\tC.f(unsafe.Pointer(&st2))\n\n\tvar st4 S2\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&st4)))\n\tC.f(unsafe.Pointer(&st4))\n\n\ttype cgoStruct struct{ p *cgoStruct }\n\tC.f(unsafe.Pointer(&cgoStruct{}))\n\n\tC.CBytes([]byte(\"hello\"))\n}\n\ntype S struct{ slice []int }\n\ntype S2 struct{ int int }\n"
  },
  {
    "path": "go/analysis/passes/cgocall/testdata/src/a/cgo3.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\n// The purpose of this inherited test is unclear.\n\nimport \"C\"\n\nconst x = 1\n\nvar a, b = 1, 2\n\nfunc F() {\n}\n\nfunc FAD(int, string) bool {\n\tC.malloc(3)\n\treturn true\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/testdata/src/b/b.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test the cgo checker on a file that doesn't use cgo, but has an\n// import named \"C\".\n\npackage b\n\nimport C \"fmt\"\n\nimport \"unsafe\"\n\nfunc init() {\n\tvar f func()\n\tC.Println(unsafe.Pointer(&f))\n\n\t// Passing a pointer (via a slice), but C is fmt, not cgo.\n\tC.Println([]int{3})\n}\n"
  },
  {
    "path": "go/analysis/passes/cgocall/testdata/src/c/c.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test the cgo checker on a file that doesn't use cgo.\n\npackage c\n\nimport \"unsafe\"\n\n// Passing a pointer (via the slice), but C isn't cgo.\nvar _ = C.f(unsafe.Pointer(new([]int)))\n\nvar C struct{ f func(interface{}) int }\n"
  },
  {
    "path": "go/analysis/passes/cgocall/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the cgo checker.\n\npackage a\n\n// void f(void *ptr) {}\nimport \"C\"\n\nimport \"unsafe\"\n\nfunc CgoTest[T any]() {\n\tvar c chan bool\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&c))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&c))                     // want \"embedded pointer\"\n\n\tvar schan S[chan bool]\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&schan))) // want \"embedded pointer\"\n\tC.f(unsafe.Pointer(&schan))                     // want \"embedded pointer\"\n\n\tvar x T\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&x))) // no findings as T is not known compile-time\n\tC.f(unsafe.Pointer(&x))\n\n\t// instantiating CgoTest should not yield any warnings\n\tCgoTest[chan bool]()\n\n\tvar sint S[int]\n\tC.f(*(*unsafe.Pointer)(unsafe.Pointer(&sint)))\n\tC.f(unsafe.Pointer(&sint))\n}\n\ntype S[X any] struct {\n\tval X\n}\n"
  },
  {
    "path": "go/analysis/passes/composite/composite.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package composite defines an Analyzer that checks for unkeyed\n// composite literals.\npackage composite\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nconst Doc = `check for unkeyed composite literals\n\nThis analyzer reports a diagnostic for composite literals of struct\ntypes imported from another package that do not use the field-keyed\nsyntax. Such literals are fragile because the addition of a new field\n(even if unexported) to the struct will cause compilation to fail.\n\nAs an example,\n\n\terr = &net.DNSConfigError{err}\n\nshould be replaced by:\n\n\terr = &net.DNSConfigError{Err: err}\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"composites\",\n\tDoc:              Doc,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/composite\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nvar whitelist = true\n\nfunc init() {\n\tAnalyzer.Flags.BoolVar(&whitelist, \"whitelist\", whitelist, \"use composite white list; for testing only\")\n}\n\n// runUnkeyedLiteral checks if a composite literal is a struct literal with\n// unkeyed fields.\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CompositeLit)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcl := n.(*ast.CompositeLit)\n\n\t\ttyp := pass.TypesInfo.Types[cl].Type\n\t\tif typ == nil {\n\t\t\t// cannot determine composite literals' type, skip it\n\t\t\treturn\n\t\t}\n\t\ttypeName := typ.String()\n\t\tif whitelist && unkeyedLiteral[typeName] {\n\t\t\t// skip whitelisted types\n\t\t\treturn\n\t\t}\n\t\tvar structuralTypes []types.Type\n\t\tswitch typ := types.Unalias(typ).(type) {\n\t\tcase *types.TypeParam:\n\t\t\tterms, err := typeparams.StructuralTerms(typ)\n\t\t\tif err != nil {\n\t\t\t\treturn // invalid type\n\t\t\t}\n\t\t\tfor _, term := range terms {\n\t\t\t\tstructuralTypes = append(structuralTypes, term.Type())\n\t\t\t}\n\t\tdefault:\n\t\t\tstructuralTypes = append(structuralTypes, typ)\n\t\t}\n\n\t\tfor _, typ := range structuralTypes {\n\t\t\tstrct, ok := typeparams.Deref(typ).Underlying().(*types.Struct)\n\t\t\tif !ok {\n\t\t\t\t// skip non-struct composite literals\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif isLocalType(pass, typ) {\n\t\t\t\t// allow unkeyed locally defined composite literal\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check if the struct contains an unkeyed field\n\t\t\tallKeyValue := true\n\t\t\tvar suggestedFixAvailable = len(cl.Elts) == strct.NumFields()\n\t\t\tvar missingKeys []analysis.TextEdit\n\t\t\tfor i, e := range cl.Elts {\n\t\t\t\tif _, ok := e.(*ast.KeyValueExpr); !ok {\n\t\t\t\t\tallKeyValue = false\n\t\t\t\t\tif i >= strct.NumFields() {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tfield := strct.Field(i)\n\t\t\t\t\tif !field.Exported() {\n\t\t\t\t\t\t// Adding unexported field names for structs not defined\n\t\t\t\t\t\t// locally will not work.\n\t\t\t\t\t\tsuggestedFixAvailable = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tmissingKeys = append(missingKeys, analysis.TextEdit{\n\t\t\t\t\t\tPos:     e.Pos(),\n\t\t\t\t\t\tEnd:     e.Pos(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s: \", field.Name()),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif allKeyValue {\n\t\t\t\t// all the struct fields are keyed\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tdiag := analysis.Diagnostic{\n\t\t\t\tPos:     cl.Pos(),\n\t\t\t\tEnd:     cl.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"%s struct literal uses unkeyed fields\", typeName),\n\t\t\t}\n\t\t\tif suggestedFixAvailable {\n\t\t\t\tdiag.SuggestedFixes = []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   \"Add field names to struct literal\",\n\t\t\t\t\tTextEdits: missingKeys,\n\t\t\t\t}}\n\t\t\t}\n\t\t\tpass.Report(diag)\n\t\t\treturn\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// isLocalType reports whether typ belongs to the same package as pass.\n// TODO(adonovan): local means \"internal to a function\"; rename to isSamePackageType.\nfunc isLocalType(pass *analysis.Pass, typ types.Type) bool {\n\tswitch x := types.Unalias(typ).(type) {\n\tcase *types.Struct:\n\t\t// struct literals are local types\n\t\treturn true\n\tcase *types.Pointer:\n\t\treturn isLocalType(pass, x.Elem())\n\tcase interface{ Obj() *types.TypeName }: // *Named or *TypeParam (aliases were removed already)\n\t\t// names in package foo are local to foo_test too\n\t\treturn x.Obj().Pkg() != nil &&\n\t\t\tstrings.TrimSuffix(x.Obj().Pkg().Path(), \"_test\") == strings.TrimSuffix(pass.Pkg.Path(), \"_test\")\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/composite/composite_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage composite_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/composite\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, composite.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/a/a.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains the test for untagged struct literals.\n\npackage a\n\nimport (\n\t\"flag\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"image\"\n\t\"sync\"\n\t\"unicode\"\n)\n\nvar Okay1 = []string{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay2 = map[string]bool{\n\t\"Name\":     true,\n\t\"Usage\":    true,\n\t\"DefValue\": true,\n}\n\nvar Okay3 = struct {\n\tX string\n\tY string\n\tZ string\n}{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay4 = []struct {\n\tA int\n\tB int\n}{\n\t{1, 2},\n\t{3, 4},\n}\n\ntype MyStruct struct {\n\tX string\n\tY string\n\tZ string\n}\n\nvar Okay5 = &MyStruct{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay6 = []MyStruct{\n\t{\"foo\", \"bar\", \"baz\"},\n\t{\"aa\", \"bb\", \"cc\"},\n}\n\nvar Okay7 = []*MyStruct{\n\t{\"foo\", \"bar\", \"baz\"},\n\t{\"aa\", \"bb\", \"cc\"},\n}\n\n// Testing is awkward because we need to reference things from a separate package\n// to trigger the warnings.\n\nvar goodStructLiteral = flag.Flag{\n\tName:  \"Name\",\n\tUsage: \"Usage\",\n}\nvar badStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\t\"Name\",\n\t\"Usage\",\n\tnil, // Value\n\t\"DefValue\",\n}\nvar tooManyFieldsStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\t\"Name\",\n\t\"Usage\",\n\tnil, // Value\n\t\"DefValue\",\n\t\"Extra Field\",\n}\nvar tooFewFieldsStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\t\"Name\",\n\t\"Usage\",\n\tnil, // Value\n}\n\nvar delta [3]rune\n\n// SpecialCase is a named slice of CaseRange to test issue 9171.\nvar goodNamedSliceLiteral = unicode.SpecialCase{\n\t{Lo: 1, Hi: 2, Delta: delta},\n\tunicode.CaseRange{Lo: 1, Hi: 2, Delta: delta},\n}\nvar badNamedSliceLiteral = unicode.SpecialCase{\n\t{1, 2, delta},                  // want \"unkeyed fields\"\n\tunicode.CaseRange{1, 2, delta}, // want \"unkeyed fields\"\n}\n\n// ErrorList is a named slice, so no warnings should be emitted.\nvar goodScannerErrorList = scanner.ErrorList{\n\t&scanner.Error{Msg: \"foobar\"},\n}\nvar badScannerErrorList = scanner.ErrorList{\n\t&scanner.Error{token.Position{}, \"foobar\"}, // want \"unkeyed fields\"\n}\n\n// sync.Mutex has unexported fields. We expect a diagnostic but no\n// suggested fix.\nvar mu = sync.Mutex{0, 0} // want \"unkeyed fields\"\n\n// Check whitelisted structs: if vet is run with --compositewhitelist=false,\n// this line triggers an error.\nvar whitelistedPoint = image.Point{1, 2}\n\n// Do not check type from unknown package.\n// See issue 15408.\nvar unknownPkgVar = unicode.NoSuchType{\"foo\", \"bar\"}\n\n// A named pointer slice of CaseRange to test issue 23539. In\n// particular, we're interested in how some slice elements omit their\n// type.\nvar goodNamedPointerSliceLiteral = []*unicode.CaseRange{\n\t{Lo: 1, Hi: 2},\n\t&unicode.CaseRange{Lo: 1, Hi: 2},\n}\nvar badNamedPointerSliceLiteral = []*unicode.CaseRange{\n\t{1, 2, delta},                   // want \"unkeyed fields\"\n\t&unicode.CaseRange{1, 2, delta}, // want \"unkeyed fields\"\n}\n\n// unicode.Range16 is whitelisted, so there'll be no vet error\nvar range16 = unicode.Range16{0xfdd0, 0xfdef, 1}\n\n// unicode.Range32 is whitelisted, so there'll be no vet error\nvar range32 = unicode.Range32{0x1fffe, 0x1ffff, 1}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/a/a.go.golden",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains the test for untagged struct literals.\n\npackage a\n\nimport (\n\t\"flag\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"image\"\n\t\"sync\"\n\t\"unicode\"\n)\n\nvar Okay1 = []string{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay2 = map[string]bool{\n\t\"Name\":     true,\n\t\"Usage\":    true,\n\t\"DefValue\": true,\n}\n\nvar Okay3 = struct {\n\tX string\n\tY string\n\tZ string\n}{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay4 = []struct {\n\tA int\n\tB int\n}{\n\t{1, 2},\n\t{3, 4},\n}\n\ntype MyStruct struct {\n\tX string\n\tY string\n\tZ string\n}\n\nvar Okay5 = &MyStruct{\n\t\"Name\",\n\t\"Usage\",\n\t\"DefValue\",\n}\n\nvar Okay6 = []MyStruct{\n\t{\"foo\", \"bar\", \"baz\"},\n\t{\"aa\", \"bb\", \"cc\"},\n}\n\nvar Okay7 = []*MyStruct{\n\t{\"foo\", \"bar\", \"baz\"},\n\t{\"aa\", \"bb\", \"cc\"},\n}\n\n// Testing is awkward because we need to reference things from a separate package\n// to trigger the warnings.\n\nvar goodStructLiteral = flag.Flag{\n\tName:  \"Name\",\n\tUsage: \"Usage\",\n}\nvar badStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\tName:     \"Name\",\n\tUsage:    \"Usage\",\n\tValue:    nil, // Value\n\tDefValue: \"DefValue\",\n}\nvar tooManyFieldsStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\t\"Name\",\n\t\"Usage\",\n\tnil, // Value\n\t\"DefValue\",\n\t\"Extra Field\",\n}\nvar tooFewFieldsStructLiteral = flag.Flag{ // want \"unkeyed fields\"\n\t\"Name\",\n\t\"Usage\",\n\tnil, // Value\n}\n\nvar delta [3]rune\n\n// SpecialCase is a named slice of CaseRange to test issue 9171.\nvar goodNamedSliceLiteral = unicode.SpecialCase{\n\t{Lo: 1, Hi: 2, Delta: delta},\n\tunicode.CaseRange{Lo: 1, Hi: 2, Delta: delta},\n}\nvar badNamedSliceLiteral = unicode.SpecialCase{\n\t{Lo: 1, Hi: 2, Delta: delta},                  // want \"unkeyed fields\"\n\tunicode.CaseRange{Lo: 1, Hi: 2, Delta: delta}, // want \"unkeyed fields\"\n}\n\n// ErrorList is a named slice, so no warnings should be emitted.\nvar goodScannerErrorList = scanner.ErrorList{\n\t&scanner.Error{Msg: \"foobar\"},\n}\nvar badScannerErrorList = scanner.ErrorList{\n\t&scanner.Error{Pos: token.Position{}, Msg: \"foobar\"}, // want \"unkeyed fields\"\n}\n\n// sync.Mutex has unexported fields. We expect a diagnostic but no\n// suggested fix.\nvar mu = sync.Mutex{0, 0} // want \"unkeyed fields\"\n\n// Check whitelisted structs: if vet is run with --compositewhitelist=false,\n// this line triggers an error.\nvar whitelistedPoint = image.Point{1, 2}\n\n// Do not check type from unknown package.\n// See issue 15408.\nvar unknownPkgVar = unicode.NoSuchType{\"foo\", \"bar\"}\n\n// A named pointer slice of CaseRange to test issue 23539. In\n// particular, we're interested in how some slice elements omit their\n// type.\nvar goodNamedPointerSliceLiteral = []*unicode.CaseRange{\n\t{Lo: 1, Hi: 2},\n\t&unicode.CaseRange{Lo: 1, Hi: 2},\n}\nvar badNamedPointerSliceLiteral = []*unicode.CaseRange{\n\t{Lo: 1, Hi: 2, Delta: delta},                   // want \"unkeyed fields\"\n\t&unicode.CaseRange{Lo: 1, Hi: 2, Delta: delta}, // want \"unkeyed fields\"\n}\n\n// unicode.Range16 is whitelisted, so there'll be no vet error\nvar range16 = unicode.Range16{0xfdd0, 0xfdef, 1}\n\n// unicode.Range32 is whitelisted, so there'll be no vet error\nvar range32 = unicode.Range32{0x1fffe, 0x1ffff, 1}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/a/a_fuzz_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport \"testing\"\n\nvar fuzzTargets = []testing.InternalFuzzTarget{\n\t{\"Fuzz\", Fuzz},\n}\n\nfunc Fuzz(f *testing.F) {}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/a/a_fuzz_test.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport \"testing\"\n\nvar fuzzTargets = []testing.InternalFuzzTarget{\n\t{\"Fuzz\", Fuzz},\n}\n\nfunc Fuzz(f *testing.F) {}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/typeparams/lib/lib.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lib\n\ntype Struct struct{ F int }\ntype Slice []int\ntype Map map[int]int\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"typeparams/lib\"\n\ntype localStruct struct{ F int }\n\nfunc F[\n\tT1 ~struct{ f int },\n\tT2a localStruct,\n\tT2b lib.Struct,\n\tT3 ~[]int,\n\tT4 lib.Slice,\n\tT5 ~map[int]int,\n\tT6 lib.Map,\n]() {\n\t_ = T1{2}\n\t_ = T2a{2}\n\t_ = T2b{2} // want \"unkeyed fields\"\n\t_ = T3{1, 2}\n\t_ = T4{1, 2}\n\t_ = T5{1: 2}\n\t_ = T6{1: 2}\n}\n"
  },
  {
    "path": "go/analysis/passes/composite/testdata/src/typeparams/typeparams.go.golden",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"typeparams/lib\"\n\ntype localStruct struct{ F int }\n\nfunc F[\n\tT1 ~struct{ f int },\n\tT2a localStruct,\n\tT2b lib.Struct,\n\tT3 ~[]int,\n\tT4 lib.Slice,\n\tT5 ~map[int]int,\n\tT6 lib.Map,\n]() {\n\t_ = T1{2}\n\t_ = T2a{2}\n\t_ = T2b{F: 2} // want \"unkeyed fields\"\n\t_ = T3{1, 2}\n\t_ = T4{1, 2}\n\t_ = T5{1: 2}\n\t_ = T6{1: 2}\n}\n"
  },
  {
    "path": "go/analysis/passes/composite/whitelist.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage composite\n\n// unkeyedLiteral is a white list of types in the standard packages\n// that are used with unkeyed literals we deem to be acceptable.\nvar unkeyedLiteral = map[string]bool{\n\t// These image and image/color struct types are frozen. We will never add fields to them.\n\t\"image/color.Alpha16\": true,\n\t\"image/color.Alpha\":   true,\n\t\"image/color.CMYK\":    true,\n\t\"image/color.Gray16\":  true,\n\t\"image/color.Gray\":    true,\n\t\"image/color.NRGBA64\": true,\n\t\"image/color.NRGBA\":   true,\n\t\"image/color.NYCbCrA\": true,\n\t\"image/color.RGBA64\":  true,\n\t\"image/color.RGBA\":    true,\n\t\"image/color.YCbCr\":   true,\n\t\"image.Point\":         true,\n\t\"image.Rectangle\":     true,\n\t\"image.Uniform\":       true,\n\n\t\"unicode.Range16\": true,\n\t\"unicode.Range32\": true,\n\n\t// These four structs are used in generated test main files,\n\t// but the generator can be trusted.\n\t\"testing.InternalBenchmark\":  true,\n\t\"testing.InternalExample\":    true,\n\t\"testing.InternalTest\":       true,\n\t\"testing.InternalFuzzTarget\": true,\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/copylock.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package copylock defines an Analyzer that checks for locks\n// erroneously passed by value.\npackage copylock\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nconst Doc = `check for locks erroneously passed by value\n\nInadvertently copying a value containing a lock, such as sync.Mutex or\nsync.WaitGroup, may cause both copies to malfunction. Generally such\nvalues should be referred to through a pointer.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"copylocks\",\n\tDoc:              Doc,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylock\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tvar goversion string // effective file version (\"\" => unknown)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.AssignStmt)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t\t(*ast.CompositeLit)(nil),\n\t\t(*ast.File)(nil),\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.FuncLit)(nil),\n\t\t(*ast.GenDecl)(nil),\n\t\t(*ast.RangeStmt)(nil),\n\t\t(*ast.ReturnStmt)(nil),\n\t}\n\tinspect.WithStack(nodeFilter, func(node ast.Node, push bool, stack []ast.Node) bool {\n\t\tif !push {\n\t\t\treturn false\n\t\t}\n\t\tswitch node := node.(type) {\n\t\tcase *ast.File:\n\t\t\tgoversion = versions.FileVersion(pass.TypesInfo, node)\n\t\tcase *ast.RangeStmt:\n\t\t\tcheckCopyLocksRange(pass, node)\n\t\tcase *ast.FuncDecl:\n\t\t\tcheckCopyLocksFunc(pass, node.Name.Name, node.Recv, node.Type)\n\t\tcase *ast.FuncLit:\n\t\t\tcheckCopyLocksFunc(pass, \"func\", nil, node.Type)\n\t\tcase *ast.CallExpr:\n\t\t\tcheckCopyLocksCallExpr(pass, node)\n\t\tcase *ast.AssignStmt:\n\t\t\tcheckCopyLocksAssign(pass, node, goversion, parent(stack))\n\t\tcase *ast.GenDecl:\n\t\t\tcheckCopyLocksGenDecl(pass, node)\n\t\tcase *ast.CompositeLit:\n\t\t\tcheckCopyLocksCompositeLit(pass, node)\n\t\tcase *ast.ReturnStmt:\n\t\t\tcheckCopyLocksReturnStmt(pass, node)\n\t\t}\n\t\treturn true\n\t})\n\treturn nil, nil\n}\n\n// checkCopyLocksAssign checks whether an assignment\n// copies a lock.\nfunc checkCopyLocksAssign(pass *analysis.Pass, assign *ast.AssignStmt, goversion string, parent ast.Node) {\n\tlhs := assign.Lhs\n\tfor i, x := range assign.Rhs {\n\t\tif path := lockPathRhs(pass, x); path != nil {\n\t\t\tpass.ReportRangef(x, \"assignment copies lock value to %v: %v\", astutil.Format(pass.Fset, assign.Lhs[i]), path)\n\t\t\tlhs = nil // An lhs has been reported. We prefer the assignment warning and do not report twice.\n\t\t}\n\t}\n\n\t// After GoVersion 1.22, loop variables are implicitly copied on each iteration.\n\t// So a for statement may inadvertently copy a lock when any of the\n\t// iteration variables contain locks.\n\tif assign.Tok == token.DEFINE && versions.AtLeast(goversion, versions.Go1_22) {\n\t\tif parent, _ := parent.(*ast.ForStmt); parent != nil && parent.Init == assign {\n\t\t\tfor _, l := range lhs {\n\t\t\t\tif id, ok := l.(*ast.Ident); ok && id.Name != \"_\" {\n\t\t\t\t\tif obj := pass.TypesInfo.Defs[id]; obj != nil && obj.Type() != nil {\n\t\t\t\t\t\tif path := lockPath(pass.Pkg, obj.Type(), nil); path != nil {\n\t\t\t\t\t\t\tpass.ReportRangef(l, \"for loop iteration copies lock value to %v: %v\", astutil.Format(pass.Fset, l), path)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// checkCopyLocksGenDecl checks whether lock is copied\n// in variable declaration.\nfunc checkCopyLocksGenDecl(pass *analysis.Pass, gd *ast.GenDecl) {\n\tif gd.Tok != token.VAR {\n\t\treturn\n\t}\n\tfor _, spec := range gd.Specs {\n\t\tvalueSpec := spec.(*ast.ValueSpec)\n\t\tfor i, x := range valueSpec.Values {\n\t\t\tif path := lockPathRhs(pass, x); path != nil {\n\t\t\t\tpass.ReportRangef(x, \"variable declaration copies lock value to %v: %v\", valueSpec.Names[i].Name, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// checkCopyLocksCompositeLit detects lock copy inside a composite literal\nfunc checkCopyLocksCompositeLit(pass *analysis.Pass, cl *ast.CompositeLit) {\n\tfor _, x := range cl.Elts {\n\t\tif node, ok := x.(*ast.KeyValueExpr); ok {\n\t\t\tx = node.Value\n\t\t}\n\t\tif path := lockPathRhs(pass, x); path != nil {\n\t\t\tpass.ReportRangef(x, \"literal copies lock value from %v: %v\", astutil.Format(pass.Fset, x), path)\n\t\t}\n\t}\n}\n\n// checkCopyLocksReturnStmt detects lock copy in return statement\nfunc checkCopyLocksReturnStmt(pass *analysis.Pass, rs *ast.ReturnStmt) {\n\tfor _, x := range rs.Results {\n\t\tif path := lockPathRhs(pass, x); path != nil {\n\t\t\tpass.ReportRangef(x, \"return copies lock value: %v\", path)\n\t\t}\n\t}\n}\n\n// checkCopyLocksCallExpr detects lock copy in the arguments to a function call\nfunc checkCopyLocksCallExpr(pass *analysis.Pass, ce *ast.CallExpr) {\n\tvar id *ast.Ident\n\tswitch fun := ce.Fun.(type) {\n\tcase *ast.Ident:\n\t\tid = fun\n\tcase *ast.SelectorExpr:\n\t\tid = fun.Sel\n\t}\n\tif fun, ok := pass.TypesInfo.Uses[id].(*types.Builtin); ok {\n\t\tswitch fun.Name() {\n\t\tcase \"len\", \"cap\", \"Sizeof\", \"Offsetof\", \"Alignof\":\n\t\t\t// The argument of this operation is used only\n\t\t\t// for its type (e.g. len(array)), or the operation\n\t\t\t// does not copy a lock (e.g. len(slice)).\n\t\t\treturn\n\t\t}\n\t}\n\tfor _, x := range ce.Args {\n\t\tif path := lockPathRhs(pass, x); path != nil {\n\t\t\tpass.ReportRangef(x, \"call of %s copies lock value: %v\", astutil.Format(pass.Fset, ce.Fun), path)\n\t\t}\n\t}\n}\n\n// checkCopyLocksFunc checks whether a function might\n// inadvertently copy a lock, by checking whether\n// its receiver, parameters, or return values\n// are locks.\nfunc checkCopyLocksFunc(pass *analysis.Pass, name string, recv *ast.FieldList, typ *ast.FuncType) {\n\tif recv != nil && len(recv.List) > 0 {\n\t\texpr := recv.List[0].Type\n\t\tif path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type, nil); path != nil {\n\t\t\tpass.ReportRangef(expr, \"%s passes lock by value: %v\", name, path)\n\t\t}\n\t}\n\n\tif typ.Params != nil {\n\t\tfor _, field := range typ.Params.List {\n\t\t\texpr := field.Type\n\t\t\tif path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type, nil); path != nil {\n\t\t\t\tpass.ReportRangef(expr, \"%s passes lock by value: %v\", name, path)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Don't check typ.Results. If T has a Lock field it's OK to write\n\t//     return T{}\n\t// because that is returning the zero value. Leave result checking\n\t// to the return statement.\n}\n\n// checkCopyLocksRange checks whether a range statement\n// might inadvertently copy a lock by checking whether\n// any of the range variables are locks.\nfunc checkCopyLocksRange(pass *analysis.Pass, r *ast.RangeStmt) {\n\tcheckCopyLocksRangeVar(pass, r.Tok, r.Key)\n\tcheckCopyLocksRangeVar(pass, r.Tok, r.Value)\n}\n\nfunc checkCopyLocksRangeVar(pass *analysis.Pass, rtok token.Token, e ast.Expr) {\n\tif e == nil {\n\t\treturn\n\t}\n\tid, isId := e.(*ast.Ident)\n\tif isId && id.Name == \"_\" {\n\t\treturn\n\t}\n\n\tvar typ types.Type\n\tif rtok == token.DEFINE {\n\t\tif !isId {\n\t\t\treturn\n\t\t}\n\t\tobj := pass.TypesInfo.Defs[id]\n\t\tif obj == nil {\n\t\t\treturn\n\t\t}\n\t\ttyp = obj.Type()\n\t} else {\n\t\ttyp = pass.TypesInfo.Types[e].Type\n\t}\n\n\tif typ == nil {\n\t\treturn\n\t}\n\tif path := lockPath(pass.Pkg, typ, nil); path != nil {\n\t\tpass.Reportf(e.Pos(), \"range var %s copies lock: %v\", astutil.Format(pass.Fset, e), path)\n\t}\n}\n\ntype typePath []string\n\n// String pretty-prints a typePath.\nfunc (path typePath) String() string {\n\tn := len(path)\n\tvar buf bytes.Buffer\n\tfor i := range path {\n\t\tif i > 0 {\n\t\t\tfmt.Fprint(&buf, \" contains \")\n\t\t}\n\t\t// The human-readable path is in reverse order, outermost to innermost.\n\t\tfmt.Fprint(&buf, path[n-i-1])\n\t}\n\treturn buf.String()\n}\n\nfunc lockPathRhs(pass *analysis.Pass, x ast.Expr) typePath {\n\tx = ast.Unparen(x) // ignore parens on rhs\n\n\tif _, ok := x.(*ast.CompositeLit); ok {\n\t\treturn nil\n\t}\n\tif _, ok := x.(*ast.CallExpr); ok {\n\t\t// A call may return a zero value.\n\t\treturn nil\n\t}\n\tif star, ok := x.(*ast.StarExpr); ok {\n\t\tif _, ok := ast.Unparen(star.X).(*ast.CallExpr); ok {\n\t\t\t// A call may return a pointer to a zero value.\n\t\t\treturn nil\n\t\t}\n\t}\n\tif tv, ok := pass.TypesInfo.Types[x]; ok && tv.IsValue() {\n\t\treturn lockPath(pass.Pkg, tv.Type, nil)\n\t}\n\treturn nil\n}\n\n// lockPath returns a typePath describing the location of a lock value\n// contained in typ. If there is no contained lock, it returns nil.\n//\n// The seen map is used to short-circuit infinite recursion due to type cycles.\nfunc lockPath(tpkg *types.Package, typ types.Type, seen map[types.Type]bool) typePath {\n\tif typ == nil || seen[typ] {\n\t\treturn nil\n\t}\n\tif seen == nil {\n\t\tseen = make(map[types.Type]bool)\n\t}\n\tseen[typ] = true\n\n\tif tpar, ok := types.Unalias(typ).(*types.TypeParam); ok {\n\t\tterms, err := typeparams.StructuralTerms(tpar)\n\t\tif err != nil {\n\t\t\treturn nil // invalid type\n\t\t}\n\t\tfor _, term := range terms {\n\t\t\tsubpath := lockPath(tpkg, term.Type(), seen)\n\t\t\tif len(subpath) > 0 {\n\t\t\t\tif term.Tilde() {\n\t\t\t\t\t// Prepend a tilde to our lock path entry to clarify the resulting\n\t\t\t\t\t// diagnostic message. Consider the following example:\n\t\t\t\t\t//\n\t\t\t\t\t//  func _[Mutex interface{ ~sync.Mutex; M() }](m Mutex) {}\n\t\t\t\t\t//\n\t\t\t\t\t// Here the naive error message will be something like \"passes lock\n\t\t\t\t\t// by value: Mutex contains sync.Mutex\". This is misleading because\n\t\t\t\t\t// the local type parameter doesn't actually contain sync.Mutex,\n\t\t\t\t\t// which lacks the M method.\n\t\t\t\t\t//\n\t\t\t\t\t// With tilde, it is clearer that the containment is via an\n\t\t\t\t\t// approximation element.\n\t\t\t\t\tsubpath[len(subpath)-1] = \"~\" + subpath[len(subpath)-1]\n\t\t\t\t}\n\t\t\t\treturn append(subpath, typ.String())\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\tfor {\n\t\tatyp, ok := typ.Underlying().(*types.Array)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\ttyp = atyp.Elem()\n\t}\n\n\tttyp, ok := typ.Underlying().(*types.Tuple)\n\tif ok {\n\t\tfor v := range ttyp.Variables() {\n\t\t\tsubpath := lockPath(tpkg, v.Type(), seen)\n\t\t\tif subpath != nil {\n\t\t\t\treturn append(subpath, typ.String())\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// We're only interested in the case in which the underlying\n\t// type is a struct. (Interfaces and pointers are safe to copy.)\n\tstyp, ok := typ.Underlying().(*types.Struct)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// We're looking for cases in which a pointer to this type\n\t// is a sync.Locker, but a value is not. This differentiates\n\t// embedded interfaces from embedded values.\n\tif types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) {\n\t\treturn []string{typ.String()}\n\t}\n\n\t// In go1.10, sync.noCopy did not implement Locker.\n\t// (The Unlock method was added only in CL 121876.)\n\t// TODO(adonovan): remove workaround when we drop go1.10.\n\tif typesinternal.IsTypeNamed(typ, \"sync\", \"noCopy\") {\n\t\treturn []string{typ.String()}\n\t}\n\n\tnfields := styp.NumFields()\n\tfor i := range nfields {\n\t\tftyp := styp.Field(i).Type()\n\t\tsubpath := lockPath(tpkg, ftyp, seen)\n\t\tif subpath != nil {\n\t\t\treturn append(subpath, typ.String())\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// parent returns the second from the last node on stack if it exists.\nfunc parent(stack []ast.Node) ast.Node {\n\tif len(stack) >= 2 {\n\t\treturn stack[len(stack)-2]\n\t}\n\treturn nil\n}\n\nvar lockerType *types.Interface\n\n// Construct a sync.Locker interface type.\nfunc init() {\n\tnullary := types.NewSignatureType(nil, nil, nil, nil, nil, false) // func()\n\tmethods := []*types.Func{\n\t\ttypes.NewFunc(token.NoPos, nil, \"Lock\", nullary),\n\t\ttypes.NewFunc(token.NoPos, nil, \"Unlock\", nullary),\n\t}\n\tlockerType = types.NewInterface(methods, nil).Complete()\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/copylock_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage copylock_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/copylock\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, copylock.Analyzer, \"a\", \"typeparams\", \"issue67787\", \"unfortunate\")\n}\n\nfunc TestVersions22(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"src\", \"forstmt\", \"go22.txtar\"))\n\tanalysistest.Run(t, dir, copylock.Analyzer, \"golang.org/fake/forstmt\")\n}\n\nfunc TestVersions21(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"src\", \"forstmt\", \"go21.txtar\"))\n\tanalysistest.Run(t, dir, copylock.Analyzer, \"golang.org/fake/forstmt\")\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The copylock command applies the golang.org/x/tools/go/analysis/passes/copylock\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/copylock\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(copylock.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/a/copylock.go",
    "content": "package a\n\nimport (\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"unsafe\"\n\t. \"unsafe\"\n\tunsafe1 \"unsafe\"\n)\n\nfunc OkFunc() {\n\tvar x *sync.Mutex\n\tp := x\n\tvar y sync.Mutex\n\tp = &y\n\n\tvar z = sync.Mutex{}\n\tw := sync.Mutex{}\n\n\tw = sync.Mutex{}\n\tq := struct{ L sync.Mutex }{\n\t\tL: sync.Mutex{},\n\t}\n\n\tyy := []Tlock{\n\t\tTlock{},\n\t\tTlock{\n\t\t\tonce: sync.Once{},\n\t\t},\n\t}\n\n\tnl := new(sync.Mutex)\n\tmx := make([]sync.Mutex, 10)\n\txx := struct{ L *sync.Mutex }{\n\t\tL: new(sync.Mutex),\n\t}\n\n\tvar pz = (sync.Mutex{})\n\tpw := (sync.Mutex{})\n}\n\ntype Tlock struct {\n\tonce sync.Once\n}\n\nfunc BadFunc() {\n\tvar x *sync.Mutex\n\tp := x\n\tvar y sync.Mutex\n\tp = &y\n\t*p = *x // want `assignment copies lock value to \\*p: sync.Mutex`\n\n\tvar t Tlock\n\tvar tp *Tlock\n\ttp = &t\n\t*tp = t // want `assignment copies lock value to \\*tp: a.Tlock contains sync.Once contains sync\\b.*`\n\tt = *tp // want `assignment copies lock value to t: a.Tlock contains sync.Once contains sync\\b.*`\n\n\ty := *x   // want \"assignment copies lock value to y: sync.Mutex\"\n\tvar z = t // want `variable declaration copies lock value to z: a.Tlock contains sync.Once contains sync\\b.*`\n\n\tw := struct{ L sync.Mutex }{\n\t\tL: *x, // want `literal copies lock value from \\*x: sync.Mutex`\n\t}\n\tvar q = map[int]Tlock{\n\t\t1: t,   // want `literal copies lock value from t: a.Tlock contains sync.Once contains sync\\b.*`\n\t\t2: *tp, // want `literal copies lock value from \\*tp: a.Tlock contains sync.Once contains sync\\b.*`\n\t}\n\tyy := []Tlock{\n\t\tt,   // want `literal copies lock value from t: a.Tlock contains sync.Once contains sync\\b.*`\n\t\t*tp, // want `literal copies lock value from \\*tp: a.Tlock contains sync.Once contains sync\\b.*`\n\t}\n\n\t// override 'new' keyword\n\tnew := func(interface{}) {}\n\tnew(t) // want `call of new copies lock value: a.Tlock contains sync.Once contains sync\\b.*`\n\n\t// copy of array of locks\n\tvar muA [5]sync.Mutex\n\tmuB := muA        // want \"assignment copies lock value to muB: sync.Mutex\"\n\tmuA = muB         // want \"assignment copies lock value to muA: sync.Mutex\"\n\tmuSlice := muA[:] // OK\n\n\t// multidimensional array\n\tvar mmuA [5][5]sync.Mutex\n\tmmuB := mmuA        // want \"assignment copies lock value to mmuB: sync.Mutex\"\n\tmmuA = mmuB         // want \"assignment copies lock value to mmuA: sync.Mutex\"\n\tmmuSlice := mmuA[:] // OK\n\n\t// slice copy is ok\n\tvar fmuA [5][][5]sync.Mutex\n\tfmuB := fmuA        // OK\n\tfmuA = fmuB         // OK\n\tfmuSlice := fmuA[:] // OK\n\n\t// map access by single and tuple copies prohibited\n\ttype mut struct{ mu sync.Mutex }\n\tmuM := map[string]mut{\n\t\t\"a\": mut{},\n\t}\n\tmumA := muM[\"a\"]    // want \"assignment copies lock value to mumA: a.mut contains sync.Mutex\"\n\tmumB, _ := muM[\"a\"] // want \"assignment copies lock value to mumB: \\\\(a.mut, bool\\\\) contains a.mut contains sync.Mutex\"\n}\n\nfunc LenAndCapOnLockArrays() {\n\tvar a [5]sync.Mutex\n\taLen := len(a) // OK\n\taCap := cap(a) // OK\n\n\t// override 'len' and 'cap' keywords\n\n\tlen := func(interface{}) {}\n\tlen(a) // want \"call of len copies lock value: sync.Mutex\"\n\n\tcap := func(interface{}) {}\n\tcap(a) // want \"call of cap copies lock value: sync.Mutex\"\n}\n\nfunc SizeofMutex() {\n\tvar mu sync.Mutex\n\tunsafe.Sizeof(mu)  // OK\n\tunsafe1.Sizeof(mu) // OK\n\tSizeof(mu)         // OK\n\tunsafe := struct{ Sizeof func(interface{}) }{}\n\tunsafe.Sizeof(mu) // want \"call of unsafe.Sizeof copies lock value: sync.Mutex\"\n\tSizeof := func(interface{}) {}\n\tSizeof(mu) // want \"call of Sizeof copies lock value: sync.Mutex\"\n}\n\nfunc OffsetofMutex() {\n\ttype T struct {\n\t\tf  int\n\t\tmu sync.Mutex\n\t}\n\tunsafe.Offsetof(T{}.mu) // OK\n\tunsafe := struct{ Offsetof func(interface{}) }{}\n\tunsafe.Offsetof(T{}.mu) // want \"call of unsafe.Offsetof copies lock value: sync.Mutex\"\n}\n\nfunc AlignofMutex() {\n\ttype T struct {\n\t\tf  int\n\t\tmu sync.Mutex\n\t}\n\tunsafe.Alignof(T{}.mu) // OK\n\tunsafe := struct{ Alignof func(interface{}) }{}\n\tunsafe.Alignof(T{}.mu) // want \"call of unsafe.Alignof copies lock value: sync.Mutex\"\n}\n\n// SyncTypesCheck checks copying of sync.* types except sync.Mutex\nfunc SyncTypesCheck() {\n\t// sync.RWMutex copying\n\tvar rwmuX sync.RWMutex\n\tvar rwmuXX = sync.RWMutex{}\n\trwmuX1 := new(sync.RWMutex)\n\trwmuY := rwmuX     // want \"assignment copies lock value to rwmuY: sync.RWMutex\"\n\trwmuY = rwmuX      // want \"assignment copies lock value to rwmuY: sync.RWMutex\"\n\tvar rwmuYY = rwmuX // want \"variable declaration copies lock value to rwmuYY: sync.RWMutex\"\n\trwmuP := &rwmuX\n\trwmuZ := &sync.RWMutex{}\n\n\t// sync.Cond copying\n\tvar condX sync.Cond\n\tvar condXX = sync.Cond{}\n\tcondX1 := new(sync.Cond)\n\tcondY := condX     // want \"assignment copies lock value to condY: sync.Cond contains sync.noCopy\"\n\tcondY = condX      // want \"assignment copies lock value to condY: sync.Cond contains sync.noCopy\"\n\tvar condYY = condX // want \"variable declaration copies lock value to condYY: sync.Cond contains sync.noCopy\"\n\tcondP := &condX\n\tcondZ := &sync.Cond{\n\t\tL: &sync.Mutex{},\n\t}\n\tcondZ = sync.NewCond(&sync.Mutex{})\n\n\t// sync.WaitGroup copying\n\tvar wgX sync.WaitGroup\n\tvar wgXX = sync.WaitGroup{}\n\twgX1 := new(sync.WaitGroup)\n\twgY := wgX     // want \"assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy\"\n\twgY = wgX      // want \"assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy\"\n\tvar wgYY = wgX // want \"variable declaration copies lock value to wgYY: sync.WaitGroup contains sync.noCopy\"\n\twgP := &wgX\n\twgZ := &sync.WaitGroup{}\n\n\t// sync.Pool copying\n\tvar poolX sync.Pool\n\tvar poolXX = sync.Pool{}\n\tpoolX1 := new(sync.Pool)\n\tpoolY := poolX     // want \"assignment copies lock value to poolY: sync.Pool contains sync.noCopy\"\n\tpoolY = poolX      // want \"assignment copies lock value to poolY: sync.Pool contains sync.noCopy\"\n\tvar poolYY = poolX // want \"variable declaration copies lock value to poolYY: sync.Pool contains sync.noCopy\"\n\tpoolP := &poolX\n\tpoolZ := &sync.Pool{}\n\n\t// sync.Once copying\n\tvar onceX sync.Once\n\tvar onceXX = sync.Once{}\n\tonceX1 := new(sync.Once)\n\tonceY := onceX     // want `assignment copies lock value to onceY: sync.Once contains sync\\b.*`\n\tonceY = onceX      // want `assignment copies lock value to onceY: sync.Once contains sync\\b.*`\n\tvar onceYY = onceX // want `variable declaration copies lock value to onceYY: sync.Once contains sync\\b.*`\n\tonceP := &onceX\n\tonceZ := &sync.Once{}\n}\n\n// AtomicTypesCheck checks copying of sync/atomic types\nfunc AtomicTypesCheck() {\n\t// atomic.Value copying\n\tvar vX atomic.Value\n\tvar vXX = atomic.Value{}\n\tvX1 := new(atomic.Value)\n\t// These are OK because the value has not been used yet.\n\t// (And vet can't tell whether it has been used, so they're always OK.)\n\tvY := vX\n\tvY = vX\n\tvar vYY = vX\n\tvP := &vX\n\tvZ := &atomic.Value{}\n}\n\n// PointerRhsCheck checks that exceptions are made for pointer return values of\n// function calls. These may be zero initialized so they are considered OK.\nfunc PointerRhsCheck() {\n\tnewMutex := func() *sync.Mutex { return new(sync.Mutex) }\n\td := *newMutex()\n\tpd := *(newMutex())\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/a/copylock_func.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the copylock checker's\n// function declaration analysis.\n\n// There are two cases missing from this file which\n// are located in the \"unfortunate\" package in the\n// testdata directory. Once the go.mod >= 1.26 for this\n// repository, merge local_go124.go back into this file.\n\npackage a\n\nimport \"sync\"\n\nfunc OkFunc(*sync.Mutex) {}\nfunc BadFunc(sync.Mutex) {} // want \"BadFunc passes lock by value: sync.Mutex\"\nfunc BadFunc2(sync.Map)  {} // want \"BadFunc2 passes lock by value: sync.Map contains sync.(Mutex|noCopy)\"\nfunc OkRet() *sync.Mutex {}\nfunc BadRet() sync.Mutex {} // Don't warn about results\n\nvar (\n\tOkClosure   = func(*sync.Mutex) {}\n\tBadClosure  = func(sync.Mutex) {} // want \"func passes lock by value: sync.Mutex\"\n\tBadClosure2 = func(sync.Map) {}   // want \"func passes lock by value: sync.Map contains sync.(Mutex|noCopy)\"\n)\n\ntype EmbeddedRWMutex struct {\n\tsync.RWMutex\n}\n\nfunc (*EmbeddedRWMutex) OkMeth() {}\nfunc (EmbeddedRWMutex) BadMeth() {} // want \"BadMeth passes lock by value: a.EmbeddedRWMutex\"\nfunc OkFunc(e *EmbeddedRWMutex)  {}\nfunc BadFunc(EmbeddedRWMutex)    {} // want \"BadFunc passes lock by value: a.EmbeddedRWMutex\"\nfunc OkRet() *EmbeddedRWMutex    {}\nfunc BadRet() EmbeddedRWMutex    {} // Don't warn about results\n\ntype FieldMutex struct {\n\ts sync.Mutex\n}\n\nfunc (*FieldMutex) OkMeth()   {}\nfunc (FieldMutex) BadMeth()   {} // want \"BadMeth passes lock by value: a.FieldMutex contains sync.Mutex\"\nfunc OkFunc(*FieldMutex)      {}\nfunc BadFunc(FieldMutex, int) {} // want \"BadFunc passes lock by value: a.FieldMutex contains sync.Mutex\"\n\ntype L0 struct {\n\tL1\n}\n\ntype L1 struct {\n\tl L2\n}\n\ntype L2 struct {\n\tsync.Mutex\n}\n\nfunc (*L0) Ok() {}\nfunc (L0) Bad() {} // want \"Bad passes lock by value: a.L0 contains a.L1 contains a.L2\"\n\ntype EmbeddedMutexPointer struct {\n\ts *sync.Mutex // safe to copy this pointer\n}\n\nfunc (*EmbeddedMutexPointer) Ok()      {}\nfunc (EmbeddedMutexPointer) AlsoOk()   {}\nfunc StillOk(EmbeddedMutexPointer)     {}\nfunc LookinGood() EmbeddedMutexPointer {}\n\ntype EmbeddedLocker struct {\n\tsync.Locker // safe to copy interface values\n}\n\nfunc (*EmbeddedLocker) Ok()    {}\nfunc (EmbeddedLocker) AlsoOk() {}\n\ntype CustomLock struct{}\n\nfunc (*CustomLock) Lock()   {}\nfunc (*CustomLock) Unlock() {}\n\nfunc Ok(*CustomLock) {}\nfunc Bad(CustomLock) {} // want \"Bad passes lock by value: a.CustomLock\"\n\n// Passing lock values into interface function arguments\nfunc FuncCallInterfaceArg(f func(a int, b interface{})) {\n\tvar m sync.Mutex\n\tvar t struct{ lock sync.Mutex }\n\n\tf(1, \"foo\")\n\tf(2, &t)\n\tf(3, &sync.Mutex{})\n\tf(4, m) // want \"call of f copies lock value: sync.Mutex\"\n\tf(5, t) // want \"call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex\"\n\tvar fntab []func(t)\n\tfntab[0](t) // want \"call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex\"\n}\n\n// Returning lock via interface value\nfunc ReturnViaInterface(x int) (int, interface{}) {\n\tvar m sync.Mutex\n\tvar t struct{ lock sync.Mutex }\n\n\tswitch x % 4 {\n\tcase 0:\n\t\treturn 0, \"qwe\"\n\tcase 1:\n\t\treturn 1, &sync.Mutex{}\n\tcase 2:\n\t\treturn 2, m // want \"return copies lock value: sync.Mutex\"\n\tdefault:\n\t\treturn 3, t // want \"return copies lock value: struct.lock sync.Mutex. contains sync.Mutex\"\n\t}\n}\n\n// Some cases that we don't warn about.\n\nfunc AcceptedCases() {\n\tx := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)\n\tx = BadRet()           // function call on RHS is OK (#16227)\n\tx = *OKRet()           // indirection of function call on RHS is OK (#16227)\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/a/copylock_range.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the copylock checker's\n// range statement analysis.\n\npackage a\n\nimport \"sync\"\n\nfunc rangeMutex() {\n\tvar mu sync.Mutex\n\tvar i int\n\n\tvar s []sync.Mutex\n\tfor range s {\n\t}\n\tfor i = range s {\n\t}\n\tfor i := range s {\n\t}\n\tfor i, _ = range s {\n\t}\n\tfor i, _ := range s {\n\t}\n\tfor _, mu = range s { // want \"range var mu copies lock: sync.Mutex\"\n\t}\n\tfor _, m := range s { // want \"range var m copies lock: sync.Mutex\"\n\t}\n\tfor i, mu = range s { // want \"range var mu copies lock: sync.Mutex\"\n\t}\n\tfor i, m := range s { // want \"range var m copies lock: sync.Mutex\"\n\t}\n\n\tvar a [3]sync.Mutex\n\tfor _, m := range a { // want \"range var m copies lock: sync.Mutex\"\n\t}\n\n\tvar m map[sync.Mutex]sync.Mutex\n\tfor k := range m { // want \"range var k copies lock: sync.Mutex\"\n\t}\n\tfor mu, _ = range m { // want \"range var mu copies lock: sync.Mutex\"\n\t}\n\tfor k, _ := range m { // want \"range var k copies lock: sync.Mutex\"\n\t}\n\tfor _, mu = range m { // want \"range var mu copies lock: sync.Mutex\"\n\t}\n\tfor _, v := range m { // want \"range var v copies lock: sync.Mutex\"\n\t}\n\n\tvar c chan sync.Mutex\n\tfor range c {\n\t}\n\tfor mu = range c { // want \"range var mu copies lock: sync.Mutex\"\n\t}\n\tfor v := range c { // want \"range var v copies lock: sync.Mutex\"\n\t}\n\n\t// Test non-idents in range variables\n\tvar t struct {\n\t\ti  int\n\t\tmu sync.Mutex\n\t}\n\tfor t.i, t.mu = range s { // want \"range var t.mu copies lock: sync.Mutex\"\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/a/issue61678.go",
    "content": "// This test relies on a compiler bug patched in Go 1.26.\n//go:build !go1.26\n\npackage a\n\nimport \"sync\"\n\n// These examples are taken from golang/go#61678, modified so that A and B\n// contain a mutex.\n\ntype A struct {\n\ta  A\n\tmu sync.Mutex\n}\n\ntype B struct {\n\ta  A\n\tb  B\n\tmu sync.Mutex\n}\n\nfunc okay(x A) {}\nfunc sure()    { var x A; nop(x) }\n\nvar fine B\n\nfunc what(x B)   {}                  // want `passes lock by value`\nfunc bad()       { var x B; nop(x) } // want `copies lock value`\nfunc good()      { nop(B{}) }\nfunc stillgood() { nop(B{b: B{b: B{b: B{}}}}) }\nfunc nope()      { nop(B{}.b) } // want `copies lock value`\n\nfunc nop(any) {} // only used to get around unused variable errors\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/a/newexpr_go126.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.26\n\npackage a\n\nimport \"sync\"\n\nfunc _(ptr *sync.Mutex) {\n\t_ = new(sync.Mutex)\n\t_ = new(*ptr) // want `call of new copies lock value: sync.Mutex`\n)\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/forstmt/go21.txtar",
    "content": "Test copylock at go version go1.21.\n\n-- go.mod --\nmodule golang.org/fake/forstmt\n\ngo 1.21\n-- pre.go --\n//go:build go1.21\n\npackage forstmt\n\nimport \"sync\"\n\nfunc InGo21(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {  // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ { // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n}\n-- go22.go --\n//go:build go1.22\n\npackage forstmt\n\nimport \"sync\"\n\nfunc InGo22(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {  // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n}\n-- modver.go --\npackage forstmt\n\nimport \"sync\"\n\nfunc AtGo121ByModuleVersion(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {  // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ { // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/forstmt/go22.txtar",
    "content": "Test copylock at go version go1.22.\n\n-- go.mod --\nmodule golang.org/fake/forstmt\n\ngo 1.22\n-- pre.go --\n//go:build go1.21\n\npackage forstmt\n\nimport \"sync\"\n\nfunc InGo21(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {   // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // Not reported before 1.22.\n\t\t_ = mu.TryLock()\n\t}\n}\n-- go22.go --\n//go:build go1.22\n\npackage forstmt\n\nimport \"sync\"\n\nfunc InGo22(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {  // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n}\n-- modver.go --\npackage forstmt\n\nimport \"sync\"\n\nfunc InGo22ByModuleVersion(l []int) {\n\tvar mu sync.Mutex\n\tvar x int\n\n\tfor x, mu = 0, (sync.Mutex{}); x < 10; x++ {  // Not reported on '='.\n\t}\n\tfor x, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n\tfor x, _ := 0, (sync.Mutex{}); x < 10; x++ {  // Not reported due to '_'.\n\t\t_ = mu.TryLock()\n\t}\n\tfor _, mu := 0, (sync.Mutex{}); x < 10; x++ { // want \"for loop iteration copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n}\n-- assign.go --\n//go:build go1.22\n\npackage forstmt\n\nimport \"sync\"\n\nfunc ReportAssign(l []int) {\n\t// Test we do not report a duplicate if the assignment is reported.\n\tvar mu sync.Mutex\n\tfor x, mu := 0, mu; x < 10; x++ { // want \"assignment copies lock value to mu: sync.Mutex\"\n\t\t_ = mu.TryLock()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/issue67787/issue67787.go",
    "content": "package issue67787\n\nimport \"sync\"\n\ntype T struct{ mu sync.Mutex }\ntype T1 struct{ t *T }\n\nfunc NewT1() *T1 { return &T1{T} } // no analyzer diagnostic about T\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"sync\"\n\n// The copylock analyzer runs despite errors. The following invalid type should\n// not cause an infinite recursion.\ntype R struct{ r R }\n\nfunc TestNoRecursion(r R) {}\n\n// The following recursive type parameter definitions should not cause an\n// infinite recursion.\nfunc TestNoTypeParamRecursion[T1 ~[]T2, T2 ~[]T1 | string, T3 ~struct{ F T3 }](t1 T1, t2 T2, t3 T3) {\n}\n\nfunc OkFunc1[Struct ~*struct{ mu sync.Mutex }](s Struct) {\n}\n\nfunc BadFunc1[Struct ~struct{ mu sync.Mutex }](s Struct) { // want `passes lock by value: .*Struct contains ~struct{mu sync.Mutex}`\n}\n\nfunc OkFunc2[MutexPtr *sync.Mutex](m MutexPtr) {\n\tvar x *MutexPtr\n\tp := x\n\tvar y MutexPtr\n\tp = &y\n\t*p = *x\n\n\tvar mus []MutexPtr\n\n\tfor _, _ = range mus {\n\t}\n}\n\nfunc BadFunc2[Mutex sync.Mutex](m Mutex) { // want `passes lock by value: .*Mutex contains sync.Mutex`\n\tvar x *Mutex\n\tp := x\n\tvar y Mutex\n\tp = &y\n\t*p = *x // want `assignment copies lock value to \\*p: .*Mutex contains sync.Mutex`\n\n\tvar mus []Mutex\n\n\tfor _, _ = range mus {\n\t}\n}\n\nfunc ApproximationError[Mutex interface {\n\t~sync.Mutex\n\tM()\n}](m Mutex) { // want `passes lock by value: .*Mutex contains ~sync.Mutex`\n}\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/unfortunate/local_go123.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.24\n\npackage unfortunate\n\nimport \"sync\"\n\n// TODO: Unfortunate cases\n\n// Non-ideal error message:\n// Since we're looking for Lock methods, sync.Once's underlying\n// sync.Mutex gets called out, but without any reference to the sync.Once.\ntype LocalOnce sync.Once\n\nfunc (LocalOnce) Bad() {} // want `Bad passes lock by value: unfortunate.LocalOnce contains sync.\\b.*`\n\n// False negative:\n// LocalMutex doesn't have a Lock method.\n// Nevertheless, it is probably a bad idea to pass it by value.\ntype LocalMutex sync.Mutex\n\nfunc (LocalMutex) Bad() {} // WANTED: An error here :(\n"
  },
  {
    "path": "go/analysis/passes/copylock/testdata/src/unfortunate/local_go124.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.24\n\npackage unfortunate\n\nimport \"sync\"\n\n// Cases where the interior sync.noCopy shows through.\n\ntype LocalOnce sync.Once\n\nfunc (LocalOnce) Bad() {} // want \"Bad passes lock by value: unfortunate.LocalOnce contains sync.noCopy\"\n\ntype LocalMutex sync.Mutex\n\nfunc (LocalMutex) Bad() {} // want \"Bad passes lock by value: unfortunate.LocalMutex contains sync.noCopy\"\n"
  },
  {
    "path": "go/analysis/passes/ctrlflow/ctrlflow.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package ctrlflow is an analysis that provides a syntactic\n// control-flow graph (CFG) for the body of a function.\n// It records whether a function cannot return.\n// By itself, it does not report any diagnostics.\npackage ctrlflow\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"log\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/cfg\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"ctrlflow\",\n\tDoc:        \"build a control-flow graph\",\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ctrlflow\",\n\tRun:        run,\n\tResultType: reflect.TypeFor[*CFGs](),\n\tFactTypes:  []analysis.Fact{new(noReturn)},\n\tRequires:   []*analysis.Analyzer{inspect.Analyzer},\n}\n\n// noReturn is a fact indicating that a function does not return.\ntype noReturn struct{}\n\nfunc (*noReturn) AFact() {}\n\nfunc (*noReturn) String() string { return \"noReturn\" }\n\n// A CFGs holds the control-flow graphs\n// for all the functions of the current package.\ntype CFGs struct {\n\tdefs      map[*ast.Ident]types.Object // from Pass.TypesInfo.Defs\n\tfuncDecls map[*types.Func]*declInfo\n\tfuncLits  map[*ast.FuncLit]*litInfo\n\tnoReturn  map[*types.Func]bool // functions lacking a reachable return statement\n\tpass      *analysis.Pass       // transient; nil after construction\n}\n\n// NoReturn reports whether the specified control-flow graph cannot return normally.\n//\n// It is defined for at least all function symbols that appear as the static callee of a\n// CallExpr in the current package, even if the callee was imported from a dependency.\n//\n// The result may incorporate interprocedural information based on induction of\n// the \"no return\" property over the static call graph within the package.\n// For example, if f simply calls g and g always calls os.Exit, then both f and g may\n// be deemed never to return.\nfunc (c *CFGs) NoReturn(fn *types.Func) bool {\n\treturn c.noReturn[fn]\n}\n\n// CFGs has two maps: funcDecls for named functions and funcLits for\n// unnamed ones. Unlike funcLits, the funcDecls map is not keyed by its\n// syntax node, *ast.FuncDecl, because callMayReturn needs to do a\n// look-up by *types.Func, and you can get from an *ast.FuncDecl to a\n// *types.Func but not the other way.\n\ntype declInfo struct {\n\tdecl    *ast.FuncDecl\n\tcfg     *cfg.CFG // iff decl.Body != nil\n\tstarted bool     // to break cycles\n}\n\ntype litInfo struct {\n\tcfg      *cfg.CFG\n\tnoReturn bool // (currently unused)\n}\n\n// FuncDecl returns the control-flow graph for a named function.\n// It returns nil if decl.Body==nil.\nfunc (c *CFGs) FuncDecl(decl *ast.FuncDecl) *cfg.CFG {\n\tif decl.Body == nil {\n\t\treturn nil\n\t}\n\tfn := c.defs[decl.Name].(*types.Func)\n\treturn c.funcDecls[fn].cfg\n}\n\n// FuncLit returns the control-flow graph for a literal function.\nfunc (c *CFGs) FuncLit(lit *ast.FuncLit) *cfg.CFG {\n\treturn c.funcLits[lit].cfg\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// Because CFG construction consumes and produces noReturn\n\t// facts, CFGs for exported FuncDecls must be built before 'run'\n\t// returns; we cannot construct them lazily.\n\t// (We could build CFGs for FuncLits lazily,\n\t// but the benefit is marginal.)\n\n\t// Pass 1. Map types.Funcs to ast.FuncDecls in this package.\n\tfuncDecls := make(map[*types.Func]*declInfo) // functions and methods\n\tfuncLits := make(map[*ast.FuncLit]*litInfo)\n\n\tvar decls []*types.Func // keys(funcDecls), in order\n\tvar lits []*ast.FuncLit // keys(funcLits), in order\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.FuncLit)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\t// Type information may be incomplete.\n\t\t\tif fn, ok := pass.TypesInfo.Defs[n.Name].(*types.Func); ok {\n\t\t\t\tfuncDecls[fn] = &declInfo{decl: n}\n\t\t\t\tdecls = append(decls, fn)\n\t\t\t}\n\t\tcase *ast.FuncLit:\n\t\t\tfuncLits[n] = new(litInfo)\n\t\t\tlits = append(lits, n)\n\t\t}\n\t})\n\n\tc := &CFGs{\n\t\tdefs:      pass.TypesInfo.Defs,\n\t\tfuncDecls: funcDecls,\n\t\tfuncLits:  funcLits,\n\t\tnoReturn:  make(map[*types.Func]bool),\n\t\tpass:      pass,\n\t}\n\n\t// Pass 2. Build CFGs.\n\n\t// Build CFGs for named functions.\n\t// Cycles in the static call graph are broken\n\t// arbitrarily but deterministically.\n\t// We create noReturn facts as discovered.\n\tfor _, fn := range decls {\n\t\tc.buildDecl(fn, funcDecls[fn])\n\t}\n\n\t// Build CFGs for literal functions.\n\t// These aren't relevant to facts (since they aren't named)\n\t// but are required for the CFGs.FuncLit API.\n\tfor _, lit := range lits {\n\t\tli := funcLits[lit]\n\t\tif li.cfg == nil {\n\t\t\tli.cfg = cfg.New(lit.Body, c.callMayReturn)\n\t\t\tif li.cfg.NoReturn() {\n\t\t\t\tli.noReturn = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// All CFGs are now built.\n\tc.pass = nil\n\n\treturn c, nil\n}\n\n// di.cfg may be nil on return.\nfunc (c *CFGs) buildDecl(fn *types.Func, di *declInfo) {\n\t// buildDecl may call itself recursively for the same function,\n\t// because cfg.New is passed the callMayReturn method, which\n\t// builds the CFG of the callee, leading to recursion.\n\t// The buildDecl call tree thus resembles the static call graph.\n\t// We mark each node when we start working on it to break cycles.\n\n\tif di.started {\n\t\treturn // break cycle\n\t}\n\tdi.started = true\n\n\tnoreturn, known := knownIntrinsic(fn)\n\tif !known {\n\t\tif di.decl.Body != nil {\n\t\t\tdi.cfg = cfg.New(di.decl.Body, c.callMayReturn)\n\t\t\tif di.cfg.NoReturn() {\n\t\t\t\tnoreturn = true\n\t\t\t}\n\t\t}\n\t}\n\tif noreturn {\n\t\tc.pass.ExportObjectFact(fn, new(noReturn))\n\t\tc.noReturn[fn] = true\n\t}\n\n\t// debugging\n\tif false {\n\t\tlog.Printf(\"CFG for %s:\\n%s (noreturn=%t)\\n\", fn, di.cfg.Format(c.pass.Fset), noreturn)\n\t}\n}\n\n// callMayReturn reports whether the called function may return.\n// It is passed to the CFG builder.\nfunc (c *CFGs) callMayReturn(call *ast.CallExpr) (r bool) {\n\tif id, ok := call.Fun.(*ast.Ident); ok && c.pass.TypesInfo.Uses[id] == panicBuiltin {\n\t\treturn false // panic never returns\n\t}\n\n\t// Is this a static call? Also includes static functions\n\t// parameterized by a type. Such functions may or may not\n\t// return depending on the parameter type, but in some\n\t// cases the answer is definite. We let ctrlflow figure\n\t// that out.\n\tfn := typeutil.StaticCallee(c.pass.TypesInfo, call)\n\tif fn == nil {\n\t\treturn true // callee not statically known; be conservative\n\t}\n\n\t// Function or method declared in this package?\n\tif di, ok := c.funcDecls[fn]; ok {\n\t\tc.buildDecl(fn, di)\n\t\treturn !c.noReturn[fn]\n\t}\n\n\t// Not declared in this package.\n\t// Is there a fact from another package?\n\tif c.pass.ImportObjectFact(fn, new(noReturn)) {\n\t\tc.noReturn[fn] = true\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nvar panicBuiltin = types.Universe.Lookup(\"panic\").(*types.Builtin)\n\n// knownIntrinsic reports whether a function intrinsically never\n// returns because it stops execution of the calling thread, or does\n// in fact return, contrary to its apparent body, because it is\n// handled specially by the compiler.\n//\n// It is the base case in the recursion.\nfunc knownIntrinsic(fn *types.Func) (noreturn, known bool) {\n\t// Add functions here as the need arises, but don't allocate memory.\n\n\t// Functions known intrinsically never to return.\n\tif typesinternal.IsFunctionNamed(fn, \"syscall\", \"Exit\", \"ExitProcess\", \"ExitThread\") ||\n\t\ttypesinternal.IsFunctionNamed(fn, \"runtime\", \"Goexit\", \"fatalthrow\", \"fatalpanic\", \"exit\") ||\n\t\t// Following staticcheck (see go/ir/exits.go) we include functions\n\t\t// in several popular logging packages whose no-return status is\n\t\t// beyond the analysis to infer.\n\t\t// TODO(adonovan): make this list extensible.\n\t\ttypesinternal.IsMethodNamed(fn, \"go.uber.org/zap\", \"Logger\", \"Fatal\", \"Panic\") ||\n\t\ttypesinternal.IsMethodNamed(fn, \"go.uber.org/zap\", \"SugaredLogger\", \"Fatal\", \"Fatalw\", \"Fatalf\", \"Panic\", \"Panicw\", \"Panicf\") ||\n\t\ttypesinternal.IsMethodNamed(fn, \"github.com/sirupsen/logrus\", \"Logger\", \"Exit\", \"Panic\", \"Panicf\", \"Panicln\") ||\n\t\ttypesinternal.IsMethodNamed(fn, \"github.com/sirupsen/logrus\", \"Entry\", \"Panicf\", \"Panicln\") ||\n\t\ttypesinternal.IsFunctionNamed(fn, \"k8s.io/klog\", \"Exit\", \"ExitDepth\", \"Exitf\", \"Exitln\", \"Fatal\", \"FatalDepth\", \"Fatalf\", \"Fatalln\") ||\n\t\ttypesinternal.IsFunctionNamed(fn, \"k8s.io/klog/v2\", \"Exit\", \"ExitDepth\", \"Exitf\", \"Exitln\", \"Fatal\", \"FatalDepth\", \"Fatalf\", \"Fatalln\") {\n\t\treturn true, true\n\t}\n\n\t// Compiler intrinsics known to return, contrary to\n\t// what analysis of the function body would conclude.\n\t//\n\t// Not all such intrinsics must be listed here: ctrlflow\n\t// considers any function called for its value--such as\n\t// crypto/internal/constanttime.bool2Uint8--to potentially\n\t// return; only functions called as a statement, for effects,\n\t// are no-return candidates.\n\t//\n\t// Unfortunately this does sometimes mean peering into internals.\n\t// Where possible, use the nearest enclosing public API function.\n\tif typesinternal.IsFunctionNamed(fn, \"internal/abi\", \"EscapeNonString\") ||\n\t\ttypesinternal.IsFunctionNamed(fn, \"hash/maphash\", \"Comparable\") {\n\t\treturn false, true\n\t}\n\n\treturn // unknown\n}\n"
  },
  {
    "path": "go/analysis/passes/ctrlflow/ctrlflow_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ctrlflow_test\n\nimport (\n\t\"go/ast\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/ctrlflow\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tresults := analysistest.Run(t, testdata, ctrlflow.Analyzer, \"a\", \"typeparams\")\n\n\t// Perform a minimal smoke test on\n\t// the result (CFG) computed by ctrlflow.\n\tfor _, result := range results {\n\t\tcfgs := result.Result.(*ctrlflow.CFGs)\n\n\t\tfor _, decl := range result.Action.Package.Syntax[0].Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && decl.Body != nil {\n\t\t\t\tif cfgs.FuncDecl(decl) == nil {\n\t\t\t\t\tt.Errorf(\"%s: no CFG for func %s\",\n\t\t\t\t\t\tresult.Action.Package.Fset.Position(decl.Pos()), decl.Name.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/ctrlflow/testdata/src/a/a.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\n// This file tests facts produced by ctrlflow.\n\nimport (\n\t\"hash/maphash\"\n\t\"log\"\n\t\"os\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"testing\"\n\n\t\"lib\"\n)\n\nvar cond bool\n\nfunc a() { // want a:\"noReturn\"\n\tif cond {\n\t\tb()\n\t} else {\n\t\tfor {\n\t\t}\n\t}\n}\n\nfunc b() { // want b:\"noReturn\"\n\tselect {}\n}\n\nfunc f(x int) { // no fact here\n\tswitch x {\n\tcase 0:\n\t\tos.Exit(0)\n\tcase 1:\n\t\tpanic(0)\n\t}\n\t// default case returns\n}\n\ntype T int\n\nfunc (T) method1() { // want method1:\"noReturn\"\n\ta()\n}\n\nfunc (T) method2() { // (may return)\n\tif cond {\n\t\ta()\n\t}\n}\n\n// Checking for the noreturn fact associated with F ensures that\n// ctrlflow proved each of the listed functions was \"noReturn\".\nfunc standardFunctions(x int) { // want standardFunctions:\"noReturn\"\n\tt := new(testing.T)\n\tswitch x {\n\tcase 0:\n\t\tt.FailNow()\n\tcase 1:\n\t\tt.Fatal()\n\tcase 2:\n\t\tt.Fatalf(\"\")\n\tcase 3:\n\t\tt.Skip()\n\tcase 4:\n\t\tt.SkipNow()\n\tcase 5:\n\t\tt.Skipf(\"\")\n\tcase 6:\n\t\tlog.Fatal()\n\tcase 7:\n\t\tlog.Fatalf(\"\")\n\tcase 8:\n\t\tlog.Fatalln()\n\tcase 9:\n\t\tos.Exit(0)\n\tcase 10:\n\t\tsyscall.Exit(0)\n\tcase 11:\n\t\truntime.Goexit()\n\tcase 12:\n\t\tlog.Panic()\n\tcase 13:\n\t\tlog.Panicln()\n\tcase 14:\n\t\tlog.Panicf(\"\")\n\tdefault:\n\t\tpanic(0)\n\t}\n}\n\nfunc panicRecover() {\n\tdefer func() { recover() }()\n\tpanic(nil)\n}\n\nfunc noBody()\n\nfunc g() {\n\tlib.CanReturn()\n}\n\nfunc h() { // want h:\"noReturn\"\n\tlib.NoReturn()\n}\n\nfunc returns() {\n\tprint(1)\n\tprint(2)\n\tprint(3)\n}\n\nfunc nobody() // a function with no body is assumed to return\n\nfunc hasPanic() { // want hasPanic:\"noReturn\"\n\tprint(1)\n\tpanic(2)\n\tprint(3)\n}\n\nfunc hasSelect() { // want hasSelect:\"noReturn\"\n\tprint(1)\n\tselect {}\n\tprint(3)\n}\n\nfunc infiniteLoop() { // want infiniteLoop:\"noReturn\"\n\tprint(1)\n\tfor {\n\t}\n\tprint(3)\n}\n\nfunc ifElse(cond bool) { // want ifElse:\"noReturn\"\n\tprint(1)\n\tif cond {\n\t\thasSelect()\n\t} else {\n\t\tinfiniteLoop()\n\t}\n\tprint(3)\n}\n\nfunc swtch(x int) { // want swtch:\"noReturn\"\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\thasSelect()\n\tcase 2:\n\t\tgoexit()\n\tcase 3:\n\t\tlogFatal()\n\tcase 4:\n\t\tosexit()\n\tdefault:\n\t\tpanic(3)\n\t}\n}\n\nfunc _if(cond bool) {\n\tprint(1)\n\tif cond {\n\t\thasSelect()\n\t}\n\tprint(3)\n}\n\nfunc logFatal() { // want logFatal:\"noReturn\"\n\tprint(1)\n\tlog.Fatal(\"oops\")\n\tprint(2)\n}\n\nfunc testFatal(t *testing.T) { // want testFatal:\"noReturn\"\n\tprint(1)\n\tt.Fatal(\"oops\")\n\tprint(2)\n}\n\nfunc goexit() { // want goexit:\"noReturn\"\n\tprint(1)\n\truntime.Goexit()\n\tprint(2)\n}\n\nfunc osexit() { // want osexit:\"noReturn\"\n\tprint(1)\n\tos.Exit(0)\n\tprint(2)\n}\n\nfunc intrinsic() { // (no fact)\n\n\t// Comparable calls abi.EscapeNonString, whose body appears to panic;\n\t// but that's a lie, as EscapeNonString is a compiler intrinsic.\n\t// (go1.24 used a different intrinsic, maphash.escapeForHash.)\n\tmaphash.Comparable[int](maphash.Seed{}, 0)\n}\n"
  },
  {
    "path": "go/analysis/passes/ctrlflow/testdata/src/lib/lib.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lib\n\nfunc CanReturn() {}\n\nfunc NoReturn() {\n\tfor {\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/ctrlflow/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\n// This file tests facts produced by ctrlflow.\n\nvar cond bool\n\nvar funcs = []func(){func() {}}\n\nfunc a[A any]() { // want a:\"noReturn\"\n\tif cond {\n\t\tfuncs[0]()\n\t\tb[A]()\n\t} else {\n\t\tfor {\n\t\t}\n\t}\n}\n\nfunc b[B any]() { // want b:\"noReturn\"\n\tselect {}\n}\n\nfunc c[A, B any]() { // want c:\"noReturn\"\n\tif cond {\n\t\ta[A]()\n\t} else {\n\t\td[A, B]()\n\t}\n}\n\nfunc d[A, B any]() { // want d:\"noReturn\"\n\tb[B]()\n}\n\ntype I[T any] interface {\n\tId(T) T\n}\n\nfunc e[T any](i I[T], t T) T {\n\treturn i.Id(t)\n}\n\nfunc k[T any](i I[T], t T) T { // want k:\"noReturn\"\n\tb[T]()\n\treturn i.Id(t)\n}\n\ntype T[X any] int\n\nfunc (T[X]) method1() { // want method1:\"noReturn\"\n\ta[X]()\n}\n\nfunc (T[X]) method2() { // (may return)\n\tif cond {\n\t\ta[X]()\n\t} else {\n\t\tfuncs[0]()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/deepequalerrors/deepequalerrors.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package deepequalerrors defines an Analyzer that checks for the use\n// of reflect.DeepEqual with error values.\npackage deepequalerrors\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = `check for calls of reflect.DeepEqual on error values\n\nThe deepequalerrors checker looks for calls of the form:\n\n    reflect.DeepEqual(err1, err2)\n\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare\nerrors is discouraged.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"deepequalerrors\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/deepequalerrors\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"reflect\") {\n\t\treturn nil, nil // doesn't directly import reflect\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\tif typesinternal.IsFunctionNamed(obj, \"reflect\", \"DeepEqual\") && hasError(pass, call.Args[0]) && hasError(pass, call.Args[1]) {\n\t\t\tpass.ReportRangef(call, \"avoid using reflect.DeepEqual with errors\")\n\t\t}\n\t})\n\treturn nil, nil\n}\n\nvar errorType = types.Universe.Lookup(\"error\").Type().Underlying().(*types.Interface)\n\n// hasError reports whether the type of e contains the type error.\n// See containsError, below, for the meaning of \"contains\".\nfunc hasError(pass *analysis.Pass, e ast.Expr) bool {\n\ttv, ok := pass.TypesInfo.Types[e]\n\tif !ok { // no type info, assume good\n\t\treturn false\n\t}\n\treturn containsError(tv.Type)\n}\n\n// Report whether any type that typ could store and that could be compared is the\n// error type. This includes typ itself, as well as the types of struct field, slice\n// and array elements, map keys and elements, and pointers. It does not include\n// channel types (incomparable), arg and result types of a Signature (not stored), or\n// methods of a named or interface type (not stored).\nfunc containsError(typ types.Type) bool {\n\t// Track types being processed, to avoid infinite recursion.\n\t// Using types as keys here is OK because we are checking for the identical pointer, not\n\t// type identity. See analysis/passes/printf/types.go.\n\tinProgress := make(map[types.Type]bool)\n\n\tvar check func(t types.Type) bool\n\tcheck = func(t types.Type) bool {\n\t\tif t == errorType {\n\t\t\treturn true\n\t\t}\n\t\tif inProgress[t] {\n\t\t\treturn false\n\t\t}\n\t\tinProgress[t] = true\n\t\tswitch t := t.(type) {\n\t\tcase *types.Pointer:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Slice:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Array:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Map:\n\t\t\treturn check(t.Key()) || check(t.Elem())\n\t\tcase *types.Struct:\n\t\t\tfor field := range t.Fields() {\n\t\t\t\tif check(field.Type()) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\tcase *types.Named, *types.Alias:\n\t\t\treturn check(t.Underlying())\n\n\t\t// We list the remaining valid type kinds for completeness.\n\t\tcase *types.Basic:\n\t\tcase *types.Chan: // channels store values, but they are not comparable\n\t\tcase *types.Signature:\n\t\tcase *types.Tuple: // tuples are only part of signatures\n\t\tcase *types.Interface:\n\t\t}\n\t\treturn false\n\t}\n\n\treturn check(typ)\n}\n"
  },
  {
    "path": "go/analysis/passes/deepequalerrors/deepequalerrors_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage deepequalerrors_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/deepequalerrors\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, deepequalerrors.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/deepequalerrors/testdata/src/a/a.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the deepequalerrors checker.\n\npackage a\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"reflect\"\n)\n\ntype myError int\n\nfunc (myError) Error() string { return \"\" }\n\nfunc bad() error { return nil }\n\ntype s1 struct {\n\ts2 *s2\n\ti  int\n}\n\ntype myError2 error\n\ntype s2 struct {\n\ts1   *s1\n\terrs []*myError2\n}\n\nfunc hasError() {\n\tvar e error\n\tvar m myError2\n\treflect.DeepEqual(bad(), e)           // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(io.EOF, io.EOF)     // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, &e)              // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, m)               // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, s1{})            // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, [1]error{})      // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, map[error]int{}) // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, map[int]error{}) // want `avoid using reflect.DeepEqual with errors`\n\t// We catch the next not because *os.PathError implements error, but because it contains\n\t// a field Err of type error.\n\treflect.DeepEqual(&os.PathError{}, io.EOF) // want `avoid using reflect.DeepEqual with errors`\n\n}\n\nfunc notHasError() {\n\treflect.ValueOf(4)                    // not reflect.DeepEqual\n\treflect.DeepEqual(3, 4)               // not errors\n\treflect.DeepEqual(5, io.EOF)          // only one error\n\treflect.DeepEqual(myError(1), io.EOF) // not types that implement error\n}\n"
  },
  {
    "path": "go/analysis/passes/deepequalerrors/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the deepequalerrors checker.\n\npackage a\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"reflect\"\n)\n\ntype myError int\n\nfunc (myError) Error() string { return \"\" }\n\nfunc bad[T any]() T {\n\tvar t T\n\treturn t\n}\n\ntype s1 struct {\n\ts2 *s2[myError2]\n\ti  int\n}\n\ntype myError2 error\n\ntype s2[T any] struct {\n\ts1   *s1\n\terrs []*T\n}\n\nfunc hasError() {\n\tvar e error\n\tvar m myError2\n\treflect.DeepEqual(bad[error](), e)    // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(io.EOF, io.EOF)     // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, &e)              // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, m)               // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, s1{})            // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, [1]error{})      // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, map[error]int{}) // want `avoid using reflect.DeepEqual with errors`\n\treflect.DeepEqual(e, map[int]error{}) // want `avoid using reflect.DeepEqual with errors`\n\t// We catch the next not because *os.PathError implements error, but because it contains\n\t// a field Err of type error.\n\treflect.DeepEqual(&os.PathError{}, io.EOF) // want `avoid using reflect.DeepEqual with errors`\n\n}\n\nfunc notHasError() {\n\treflect.ValueOf(4)                    // not reflect.DeepEqual\n\treflect.DeepEqual(3, 4)               // not errors\n\treflect.DeepEqual(5, io.EOF)          // only one error\n\treflect.DeepEqual(myError(1), io.EOF) // not types that implement error\n}\n"
  },
  {
    "path": "go/analysis/passes/defers/cmd/defers/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The defers command runs the defers analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/defers\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(defers.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/defers/defers.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage defers\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\n// Analyzer is the defers analyzer.\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"defers\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"defers\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers\",\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"time\") {\n\t\treturn nil, nil\n\t}\n\n\tcheckDeferCall := func(node ast.Node) bool {\n\t\tswitch v := node.(type) {\n\t\tcase *ast.CallExpr:\n\t\t\tif typesinternal.IsFunctionNamed(typeutil.Callee(pass.TypesInfo, v), \"time\", \"Since\") {\n\t\t\t\tpass.Reportf(v.Pos(), \"call to time.Since is not deferred\")\n\t\t\t}\n\t\tcase *ast.FuncLit:\n\t\t\treturn false // prune\n\t\t}\n\t\treturn true\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.DeferStmt)(nil),\n\t}\n\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\td := n.(*ast.DeferStmt)\n\t\tast.Inspect(d.Call, checkDeferCall)\n\t})\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/defers/defers_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage defers_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/defers\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, defers.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/defers/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package defers defines an Analyzer that checks for common mistakes in defer\n// statements.\n//\n// # Analyzer defers\n//\n// defers: report common mistakes in defer statements\n//\n// The defers analyzer reports a diagnostic when a defer statement would\n// result in a non-deferred call to time.Since, as experience has shown\n// that this is nearly always a mistake.\n//\n// For example:\n//\n//\tstart := time.Now()\n//\t...\n//\tdefer recordLatency(time.Since(start)) // error: call to time.Since is not deferred\n//\n// The correct code is:\n//\n//\tdefer func() { recordLatency(time.Since(start)) }()\npackage defers\n"
  },
  {
    "path": "go/analysis/passes/defers/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc Since() (t time.Duration) {\n\treturn\n}\n\nfunc x(time.Duration) {}\nfunc x2(float64)      {}\n\nfunc good() {\n\t// The following are OK because func is not evaluated in defer invocation.\n\tnow := time.Now()\n\tdefer func() {\n\t\tfmt.Println(time.Since(now)) // OK because time.Since is not evaluated in defer\n\t}()\n\tevalBefore := time.Since(now)\n\tdefer fmt.Println(evalBefore)\n\tdo := func(f func()) {}\n\tdefer do(func() { time.Since(now) })\n\tdefer fmt.Println(Since())       // OK because Since function is not in module time\n\tdefer copy([]int(nil), []int{1}) // check that a builtin doesn't cause a panic\n}\n\ntype y struct{}\n\nfunc (y) A(float64)        {}\nfunc (*y) B(float64)       {}\nfunc (y) C(time.Duration)  {}\nfunc (*y) D(time.Duration) {}\n\nfunc bad() {\n\tvar zero time.Time\n\tnow := time.Now()\n\tdefer time.Since(zero)                    // want \"call to time.Since is not deferred\"\n\tdefer time.Since(now)                     // want \"call to time.Since is not deferred\"\n\tdefer fmt.Println(time.Since(now))        // want \"call to time.Since is not deferred\"\n\tdefer fmt.Println(time.Since(time.Now())) // want \"call to time.Since is not deferred\"\n\tdefer x(time.Since(now))                  // want \"call to time.Since is not deferred\"\n\tdefer x2(time.Since(now).Seconds())       // want \"call to time.Since is not deferred\"\n\tdefer y{}.A(time.Since(now).Seconds())    // want \"call to time.Since is not deferred\"\n\tdefer (&y{}).B(time.Since(now).Seconds()) // want \"call to time.Since is not deferred\"\n\tdefer y{}.C(time.Since(now))              // want \"call to time.Since is not deferred\"\n\tdefer (&y{}).D(time.Since(now))           // want \"call to time.Since is not deferred\"\n}\n\nfunc ugly() {\n\t// The following is ok even though time.Since is evaluated. We don't\n\t// walk into function literals or check what function definitions are doing.\n\tdefer x((func() time.Duration { return time.Since(time.Now()) })())\n}\n"
  },
  {
    "path": "go/analysis/passes/directive/directive.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package directive defines an Analyzer that checks known Go toolchain directives.\npackage directive\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\nconst Doc = `check Go toolchain directives such as //go:debug\n\nThis analyzer checks for problems with known Go toolchain directives\nin all Go source files in a package directory, even those excluded by\n//go:build constraints, and all non-Go source files too.\n\nFor //go:debug (see https://go.dev/doc/godebug), the analyzer checks\nthat the directives are placed only in Go source files, only above the\npackage comment, and only in package main or *_test.go files.\n\nSupport for other known directives may be added in the future.\n\nThis analyzer does not check //go:build, which is handled by the\nbuildtag analyzer.\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"directive\",\n\tDoc:  Doc,\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/directive\",\n\tRun:  runDirective,\n}\n\nfunc runDirective(pass *analysis.Pass) (any, error) {\n\tfor _, f := range pass.Files {\n\t\tcheckGoFile(pass, f)\n\t}\n\tfor _, name := range pass.OtherFiles {\n\t\tif err := checkOtherFile(pass, name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tfor _, name := range pass.IgnoredFiles {\n\t\tif strings.HasSuffix(name, \".go\") {\n\t\t\tf, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\t// Not valid Go source code - not our job to diagnose, so ignore.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcheckGoFile(pass, f)\n\t\t} else {\n\t\t\tif err := checkOtherFile(pass, name); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc checkGoFile(pass *analysis.Pass, f *ast.File) {\n\tcheck := newChecker(pass, pass.Fset.File(f.Package).Name(), f)\n\n\tfor _, group := range f.Comments {\n\t\t// A //go:build or a //go:debug comment is ignored after the package declaration\n\t\t// (but adjoining it is OK, in contrast to +build comments).\n\t\tif group.Pos() >= f.Package {\n\t\t\tcheck.inHeader = false\n\t\t}\n\n\t\t// Check each line of a //-comment.\n\t\tfor _, c := range group.List {\n\t\t\tcheck.comment(c.Slash, c.Text)\n\t\t}\n\t}\n}\n\nfunc checkOtherFile(pass *analysis.Pass, filename string) error {\n\t// We cannot use the Go parser, since is not a Go source file.\n\t// Read the raw bytes instead.\n\tcontent, tf, err := analyzerutil.ReadFile(pass, filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcheck := newChecker(pass, filename, nil)\n\tcheck.nonGoFile(token.Pos(tf.Base()), string(content))\n\treturn nil\n}\n\ntype checker struct {\n\tpass     *analysis.Pass\n\tfilename string\n\tfile     *ast.File // nil for non-Go file\n\tinHeader bool      // in file header (before or adjoining package declaration)\n}\n\nfunc newChecker(pass *analysis.Pass, filename string, file *ast.File) *checker {\n\treturn &checker{\n\t\tpass:     pass,\n\t\tfilename: filename,\n\t\tfile:     file,\n\t\tinHeader: true,\n\t}\n}\n\nfunc (check *checker) nonGoFile(pos token.Pos, fullText string) {\n\t// Process each line.\n\ttext := fullText\n\tinStar := false\n\tfor text != \"\" {\n\t\toffset := len(fullText) - len(text)\n\t\tvar line string\n\t\tline, text, _ = strings.Cut(text, \"\\n\")\n\n\t\tif !inStar && strings.HasPrefix(line, \"//\") {\n\t\t\tcheck.comment(pos+token.Pos(offset), line)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Skip over, cut out any /* */ comments,\n\t\t// to avoid being confused by a commented-out // comment.\n\t\tfor {\n\t\t\tline = strings.TrimSpace(line)\n\t\t\tif inStar {\n\t\t\t\tvar ok bool\n\t\t\t\t_, line, ok = strings.Cut(line, \"*/\")\n\t\t\t\tif !ok {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tinStar = false\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tline, inStar = stringsCutPrefix(line, \"/*\")\n\t\t\tif !inStar {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif line != \"\" {\n\t\t\t// Found non-comment non-blank line.\n\t\t\t// Ends space for valid //go:build comments,\n\t\t\t// but also ends the fraction of the file we can\n\t\t\t// reliably parse. From this point on we might\n\t\t\t// incorrectly flag \"comments\" inside multiline\n\t\t\t// string constants or anything else (this might\n\t\t\t// not even be a Go program). So stop.\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (check *checker) comment(pos token.Pos, line string) {\n\tif !strings.HasPrefix(line, \"//go:\") {\n\t\treturn\n\t}\n\t// testing hack: stop at // ERROR\n\tif i := strings.Index(line, \" // ERROR \"); i >= 0 {\n\t\tline = line[:i]\n\t}\n\n\tverb := line\n\tif i := strings.IndexFunc(verb, unicode.IsSpace); i >= 0 {\n\t\tverb = verb[:i]\n\t\tif line[i] != ' ' && line[i] != '\\t' && line[i] != '\\n' {\n\t\t\tr, _ := utf8.DecodeRuneInString(line[i:])\n\t\t\tcheck.pass.Reportf(pos, \"invalid space %#q in %s directive\", r, verb)\n\t\t}\n\t}\n\n\tswitch verb {\n\tdefault:\n\t\t// TODO: Use the go language version for the file.\n\t\t// If that version is not newer than us, then we can\n\t\t// report unknown directives.\n\n\tcase \"//go:build\":\n\t\t// Ignore. The buildtag analyzer reports misplaced comments.\n\n\tcase \"//go:debug\":\n\t\tif check.file == nil {\n\t\t\tcheck.pass.Reportf(pos, \"//go:debug directive only valid in Go source files\")\n\t\t} else if check.file.Name.Name != \"main\" && !strings.HasSuffix(check.filename, \"_test.go\") {\n\t\t\tcheck.pass.Reportf(pos, \"//go:debug directive only valid in package main or test\")\n\t\t} else if !check.inHeader {\n\t\t\tcheck.pass.Reportf(pos, \"//go:debug directive only valid before package declaration\")\n\t\t}\n\t}\n}\n\n// Go 1.20 strings.CutPrefix.\nfunc stringsCutPrefix(s, prefix string) (after string, found bool) {\n\tif !strings.HasPrefix(s, prefix) {\n\t\treturn s, false\n\t}\n\treturn s[len(prefix):], true\n}\n"
  },
  {
    "path": "go/analysis/passes/directive/directive_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage directive_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/directive\"\n)\n\nfunc Test(t *testing.T) {\n\t// This test has a dedicated hack in the analysistest package:\n\t// Because it cares about IgnoredFiles, which most analyzers\n\t// ignore, the test framework will consider expectations in\n\t// ignore files too, but only for this analyzer.\n\tanalysistest.Run(t, analysistest.TestData(), directive.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/badspace.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// want +1 `invalid space '\\\\u00a0' in //go:debug directive`\n//go:debug 00a0\n\npackage main\n\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/issue66046.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n//go:debug panicnil=1\npackage main\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/misplaced.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\npackage main\n\n// want +1 `//go:debug directive only valid before package declaration`\n//go:debug panicnil=1\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/misplaced.s",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `//go:debug directive only valid in Go source files`\n//go:debug panicnil=1\n\n/*\ncan skip over comments\n//go:debug doesn't matter here\n*/\n\n// want +1 `//go:debug directive only valid in Go source files`\n//go:debug panicnil=1\n\npackage a\n\n// no error here because we can't parse this far\n//go:debug panicnil=1\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/misplaced_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:debug panicnil=1\n\npackage p_test\n\n// want +1 `//go:debug directive only valid before package declaration`\n//go:debug panicnil=1\n"
  },
  {
    "path": "go/analysis/passes/directive/testdata/src/a/p.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// want +1 `//go:debug directive only valid in package main or test`\n//go:debug panicnil=1\n\npackage p\n\n// want +1 `//go:debug directive only valid in package main or test`\n//go:debug panicnil=1\n"
  },
  {
    "path": "go/analysis/passes/errorsas/errorsas.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The errorsas package defines an Analyzer that checks that the second argument to\n// errors.As is a pointer to a type implementing error.\npackage errorsas\n\nimport (\n\t\"errors\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nconst Doc = `report passing non-pointer or non-error values to errors.As\n\nThe errorsas analyzer reports calls to errors.As where the type\nof the second argument is not a pointer to a type implementing error.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"errorsas\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas\",\n\tRequires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tswitch pass.Pkg.Path() {\n\tcase \"errors\", \"errors_test\":\n\t\t// These packages know how to use their own APIs.\n\t\t// Sometimes they are testing what happens to incorrect programs.\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\tfor curCall := range index.Calls(index.Object(\"errors\", \"As\")) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tif len(call.Args) < 2 {\n\t\t\tcontinue // spread call: errors.As(pair())\n\t\t}\n\n\t\t// Check for incorrect arguments.\n\t\tif err := checkAsTarget(info, call.Args[1]); err != nil {\n\t\t\tpass.ReportRangef(call, \"%v\", err)\n\t\t\tcontinue\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// checkAsTarget reports an error if the second argument to errors.As is invalid.\nfunc checkAsTarget(info *types.Info, e ast.Expr) error {\n\tt := info.Types[e].Type\n\tif types.Identical(t.Underlying(), anyType) {\n\t\t// A target of any is always allowed, since it often indicates\n\t\t// a value forwarded from another source.\n\t\treturn nil\n\t}\n\tpt, ok := t.Underlying().(*types.Pointer)\n\tif !ok {\n\t\treturn errors.New(\"second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type\")\n\t}\n\tif types.Identical(pt.Elem(), errorType) {\n\t\treturn errors.New(\"second argument to errors.As should not be *error\")\n\t}\n\tif !types.IsInterface(pt.Elem()) && !types.AssignableTo(pt.Elem(), errorType) {\n\t\treturn errors.New(\"second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type\")\n\t}\n\treturn nil\n}\n\nvar (\n\tanyType   = types.Universe.Lookup(\"any\").Type()\n\terrorType = types.Universe.Lookup(\"error\").Type()\n)\n"
  },
  {
    "path": "go/analysis/passes/errorsas/errorsas_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage errorsas_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/errorsas\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, errorsas.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/errorsas/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The errorsas command applies the golang.org/x/tools/go/analysis/passes/errorsas\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/errorsas\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(errorsas.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/errorsas/testdata/src/a/a.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the errorsas checker.\n\npackage a\n\nimport \"errors\"\n\ntype myError int\n\nfunc (myError) Error() string { return \"\" }\n\nfunc perr() *error { return nil }\n\ntype iface interface {\n\tm()\n}\n\nfunc two() (error, interface{}) { return nil, nil }\n\nfunc _() {\n\tvar (\n\t\te  error\n\t\tm  myError\n\t\ti  int\n\t\tf  iface\n\t\tei interface{}\n\t)\n\terrors.As(nil, &e)     // want `second argument to errors.As should not be \\*error`\n\terrors.As(nil, &m)     // *T where T implements error\n\terrors.As(nil, &f)     // *interface\n\terrors.As(nil, perr()) // want `second argument to errors.As should not be \\*error`\n\terrors.As(nil, ei)     //  empty interface\n\n\terrors.As(nil, nil) // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, e)   // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, m)   // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, f)   // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, &i)  // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(two())\n}\n"
  },
  {
    "path": "go/analysis/passes/errorsas/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the errorsas checker.\n\npackage a\n\nimport \"errors\"\n\ntype myError[T any] struct{ t T }\n\nfunc (myError[T]) Error() string { return \"\" }\n\ntype twice[T any] struct {\n\tt T\n}\n\nfunc perr[T any]() *T { return nil }\n\nfunc two[T any]() (error, *T) { return nil, nil }\n\nfunc _[E error](e E) {\n\tvar (\n\t\tm  myError[int]\n\t\ttw twice[myError[int]]\n\t)\n\terrors.As(nil, &e)\n\terrors.As(nil, &m)            // *T where T implements error\n\terrors.As(nil, &tw.t)         // *T where T implements error\n\terrors.As(nil, perr[error]()) // want `second argument to errors.As should not be \\*error`\n\n\terrors.As(nil, e)    // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, m)    // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(nil, tw.t) // want `second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type`\n\terrors.As(two[error]())\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/cmd/fieldalignment/main.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/fieldalignment\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(fieldalignment.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/fieldalignment.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fieldalignment defines an Analyzer that detects structs that would use less\n// memory if their fields were sorted.\npackage fieldalignment\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nconst Doc = `find structs that would use less memory if their fields were sorted\n\nThis analyzer finds structs that can be rearranged to use less memory, and provides\na suggested edit with the most compact order.\n\nNote that there are two different diagnostics reported. One checks struct size,\nand the other reports \"pointer bytes\" used. Pointer bytes is how many bytes of the\nobject that the garbage collector has to potentially scan for pointers, for example:\n\n\tstruct { uint32; string }\n\nhave 16 pointer bytes because the garbage collector has to scan up through the string's\ninner pointer.\n\n\tstruct { string; *uint32 }\n\nhas 24 pointer bytes because it has to scan further through the *uint32.\n\n\tstruct { string; uint32 }\n\nhas 8 because it can stop immediately after the string pointer.\n\nBe aware that the most compact order is not always the most efficient.\nIn rare cases it may cause two variables each updated by its own goroutine\nto occupy the same CPU cache line, inducing a form of memory contention\nknown as \"false sharing\" that slows down both goroutines.\n\nUnlike most analyzers, which report likely mistakes, the diagnostics\nproduced by fieldanalyzer very rarely indicate a significant problem,\nso the analyzer is not included in typical suites such as vet or\ngopls. Use this standalone command to run it on your code:\n\n   $ go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest\n   $ fieldalignment [packages]\n\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"fieldalignment\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/fieldalignment\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.StructType)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tvar s *ast.StructType\n\t\tvar ok bool\n\t\tif s, ok = node.(*ast.StructType); !ok {\n\t\t\treturn\n\t\t}\n\t\tif tv, ok := pass.TypesInfo.Types[s]; ok {\n\t\t\tfieldalignment(pass, s, tv.Type.(*types.Struct))\n\t\t}\n\t})\n\treturn nil, nil\n}\n\nvar unsafePointerTyp = types.Unsafe.Scope().Lookup(\"Pointer\").(*types.TypeName).Type()\n\nfunc fieldalignment(pass *analysis.Pass, node *ast.StructType, typ *types.Struct) {\n\twordSize := pass.TypesSizes.Sizeof(unsafePointerTyp)\n\tmaxAlign := pass.TypesSizes.Alignof(unsafePointerTyp)\n\n\ts := gcSizes{wordSize, maxAlign}\n\toptimal, indexes := optimalOrder(typ, &s)\n\toptsz, optptrs := s.Sizeof(optimal), s.ptrdata(optimal)\n\n\tvar message string\n\tif sz := s.Sizeof(typ); sz != optsz {\n\t\tmessage = fmt.Sprintf(\"struct of size %d could be %d\", sz, optsz)\n\t} else if ptrs := s.ptrdata(typ); ptrs != optptrs {\n\t\tmessage = fmt.Sprintf(\"struct with %d pointer bytes could be %d\", ptrs, optptrs)\n\t} else {\n\t\t// Already optimal order.\n\t\treturn\n\t}\n\n\t// Analyzers borrow syntax tree; they do not own them and must modify them.\n\t// This Clone operation is a quick fix to the data race introduced\n\t// in CL 278872 by the clearing of the Comment and Doc fields below.\n\tnode = astutil.CloneNode(node)\n\n\t// Flatten the ast node since it could have multiple field names per list item while\n\t// *types.Struct only have one item per field.\n\t// TODO: Preserve multi-named fields instead of flattening.\n\tvar flat []*ast.Field\n\tfor _, f := range node.Fields.List {\n\t\t// TODO: Preserve comment, for now get rid of them.\n\t\t//       See https://github.com/golang/go/issues/20744\n\t\tf.Comment = nil\n\t\tf.Doc = nil\n\t\tif len(f.Names) <= 1 {\n\t\t\tflat = append(flat, f)\n\t\t\tcontinue\n\t\t}\n\t\tfor _, name := range f.Names {\n\t\t\tflat = append(flat, &ast.Field{\n\t\t\t\tNames: []*ast.Ident{name},\n\t\t\t\tType:  f.Type,\n\t\t\t})\n\t\t}\n\t}\n\n\t// Sort fields according to the optimal order.\n\tvar reordered []*ast.Field\n\tfor _, index := range indexes {\n\t\treordered = append(reordered, flat[index])\n\t}\n\n\tnewStr := &ast.StructType{\n\t\tFields: &ast.FieldList{\n\t\t\tList: reordered,\n\t\t},\n\t}\n\n\t// Write the newly aligned struct node to get the content for suggested fixes.\n\tvar buf bytes.Buffer\n\tif err := format.Node(&buf, token.NewFileSet(), newStr); err != nil {\n\t\treturn\n\t}\n\n\tpass.Report(analysis.Diagnostic{\n\t\tPos:     node.Pos(),\n\t\tEnd:     node.Pos() + token.Pos(len(\"struct\")),\n\t\tMessage: message,\n\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\tMessage: \"Rearrange fields\",\n\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\tPos:     node.Pos(),\n\t\t\t\tEnd:     node.End(),\n\t\t\t\tNewText: buf.Bytes(),\n\t\t\t}},\n\t\t}},\n\t})\n}\n\nfunc optimalOrder(str *types.Struct, sizes *gcSizes) (*types.Struct, []int) {\n\tnf := str.NumFields()\n\n\ttype elem struct {\n\t\tindex   int\n\t\talignof int64\n\t\tsizeof  int64\n\t\tptrdata int64\n\t}\n\n\telems := make([]elem, nf)\n\tfor i := range nf {\n\t\tfield := str.Field(i)\n\t\tft := field.Type()\n\t\telems[i] = elem{\n\t\t\ti,\n\t\t\tsizes.Alignof(ft),\n\t\t\tsizes.Sizeof(ft),\n\t\t\tsizes.ptrdata(ft),\n\t\t}\n\t}\n\n\tsort.Slice(elems, func(i, j int) bool {\n\t\tei := &elems[i]\n\t\tej := &elems[j]\n\n\t\t// Place zero sized objects before non-zero sized objects.\n\t\tzeroi := ei.sizeof == 0\n\t\tzeroj := ej.sizeof == 0\n\t\tif zeroi != zeroj {\n\t\t\treturn zeroi\n\t\t}\n\n\t\t// Next, place more tightly aligned objects before less tightly aligned objects.\n\t\tif ei.alignof != ej.alignof {\n\t\t\treturn ei.alignof > ej.alignof\n\t\t}\n\n\t\t// Place pointerful objects before pointer-free objects.\n\t\tnoptrsi := ei.ptrdata == 0\n\t\tnoptrsj := ej.ptrdata == 0\n\t\tif noptrsi != noptrsj {\n\t\t\treturn noptrsj\n\t\t}\n\n\t\tif !noptrsi {\n\t\t\t// If both have pointers...\n\n\t\t\t// ... then place objects with less trailing\n\t\t\t// non-pointer bytes earlier. That is, place\n\t\t\t// the field with the most trailing\n\t\t\t// non-pointer bytes at the end of the\n\t\t\t// pointerful section.\n\t\t\ttraili := ei.sizeof - ei.ptrdata\n\t\t\ttrailj := ej.sizeof - ej.ptrdata\n\t\t\tif traili != trailj {\n\t\t\t\treturn traili < trailj\n\t\t\t}\n\t\t}\n\n\t\t// Lastly, order by size.\n\t\tif ei.sizeof != ej.sizeof {\n\t\t\treturn ei.sizeof > ej.sizeof\n\t\t}\n\n\t\treturn false\n\t})\n\n\tfields := make([]*types.Var, nf)\n\tindexes := make([]int, nf)\n\tfor i, e := range elems {\n\t\tfields[i] = str.Field(e.index)\n\t\tindexes[i] = e.index\n\t}\n\treturn types.NewStruct(fields, nil), indexes\n}\n\n// Code below based on go/types.StdSizes.\n\ntype gcSizes struct {\n\tWordSize int64\n\tMaxAlign int64\n}\n\nfunc (s *gcSizes) Alignof(T types.Type) int64 {\n\t// For arrays and structs, alignment is defined in terms\n\t// of alignment of the elements and fields, respectively.\n\tswitch t := T.Underlying().(type) {\n\tcase *types.Array:\n\t\t// spec: \"For a variable x of array type: unsafe.Alignof(x)\n\t\t// is the same as unsafe.Alignof(x[0]), but at least 1.\"\n\t\treturn s.Alignof(t.Elem())\n\tcase *types.Struct:\n\t\t// spec: \"For a variable x of struct type: unsafe.Alignof(x)\n\t\t// is the largest of the values unsafe.Alignof(x.f) for each\n\t\t// field f of x, but at least 1.\"\n\t\tmax := int64(1)\n\t\tfor i, nf := 0, t.NumFields(); i < nf; i++ {\n\t\t\tif a := s.Alignof(t.Field(i).Type()); a > max {\n\t\t\t\tmax = a\n\t\t\t}\n\t\t}\n\t\treturn max\n\t}\n\ta := s.Sizeof(T) // may be 0\n\t// spec: \"For a variable x of any type: unsafe.Alignof(x) is at least 1.\"\n\tif a < 1 {\n\t\treturn 1\n\t}\n\tif a > s.MaxAlign {\n\t\treturn s.MaxAlign\n\t}\n\treturn a\n}\n\nvar basicSizes = [...]byte{\n\ttypes.Bool:       1,\n\ttypes.Int8:       1,\n\ttypes.Int16:      2,\n\ttypes.Int32:      4,\n\ttypes.Int64:      8,\n\ttypes.Uint8:      1,\n\ttypes.Uint16:     2,\n\ttypes.Uint32:     4,\n\ttypes.Uint64:     8,\n\ttypes.Float32:    4,\n\ttypes.Float64:    8,\n\ttypes.Complex64:  8,\n\ttypes.Complex128: 16,\n}\n\nfunc (s *gcSizes) Sizeof(T types.Type) int64 {\n\tswitch t := T.Underlying().(type) {\n\tcase *types.Basic:\n\t\tk := t.Kind()\n\t\tif int(k) < len(basicSizes) {\n\t\t\tif s := basicSizes[k]; s > 0 {\n\t\t\t\treturn int64(s)\n\t\t\t}\n\t\t}\n\t\tif k == types.String {\n\t\t\treturn s.WordSize * 2\n\t\t}\n\tcase *types.Array:\n\t\treturn t.Len() * s.Sizeof(t.Elem())\n\tcase *types.Slice:\n\t\treturn s.WordSize * 3\n\tcase *types.Struct:\n\t\tnf := t.NumFields()\n\t\tif nf == 0 {\n\t\t\treturn 0\n\t\t}\n\n\t\tvar o int64\n\t\tmax := int64(1)\n\t\tfor i := range nf {\n\t\t\tft := t.Field(i).Type()\n\t\t\ta, sz := s.Alignof(ft), s.Sizeof(ft)\n\t\t\tif a > max {\n\t\t\t\tmax = a\n\t\t\t}\n\t\t\tif i == nf-1 && sz == 0 && o != 0 {\n\t\t\t\tsz = 1\n\t\t\t}\n\t\t\to = align(o, a) + sz\n\t\t}\n\t\treturn align(o, max)\n\tcase *types.Interface:\n\t\treturn s.WordSize * 2\n\t}\n\treturn s.WordSize // catch-all\n}\n\n// align returns the smallest y >= x such that y % a == 0.\nfunc align(x, a int64) int64 {\n\ty := x + a - 1\n\treturn y - y%a\n}\n\nfunc (s *gcSizes) ptrdata(T types.Type) int64 {\n\tswitch t := T.Underlying().(type) {\n\tcase *types.Basic:\n\t\tswitch t.Kind() {\n\t\tcase types.String, types.UnsafePointer:\n\t\t\treturn s.WordSize\n\t\t}\n\t\treturn 0\n\tcase *types.Chan, *types.Map, *types.Pointer, *types.Signature, *types.Slice:\n\t\treturn s.WordSize\n\tcase *types.Interface:\n\t\treturn 2 * s.WordSize\n\tcase *types.Array:\n\t\tn := t.Len()\n\t\tif n == 0 {\n\t\t\treturn 0\n\t\t}\n\t\ta := s.ptrdata(t.Elem())\n\t\tif a == 0 {\n\t\t\treturn 0\n\t\t}\n\t\tz := s.Sizeof(t.Elem())\n\t\treturn (n-1)*z + a\n\tcase *types.Struct:\n\t\tnf := t.NumFields()\n\t\tif nf == 0 {\n\t\t\treturn 0\n\t\t}\n\n\t\tvar o, p int64\n\t\tfor i := range nf {\n\t\t\tft := t.Field(i).Type()\n\t\t\ta, sz := s.Alignof(ft), s.Sizeof(ft)\n\t\t\tfp := s.ptrdata(ft)\n\t\t\to = align(o, a)\n\t\t\tif fp != 0 {\n\t\t\t\tp = o + fp\n\t\t\t}\n\t\t\to += sz\n\t\t}\n\t\treturn p\n\t}\n\n\tpanic(\"impossible\")\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/fieldalignment_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fieldalignment_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/fieldalignment\"\n)\n\nfunc TestTest(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, fieldalignment.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a.go",
    "content": "package a\n\ntype Good struct {\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype Bad struct { // want \"struct of size 12 could be 8\"\n\tx byte\n\ty int32\n\tz byte\n}\n\ntype ZeroGood struct {\n\ta [0]byte\n\tb uint32\n}\n\ntype ZeroBad struct { // want \"struct of size 8 could be 4\"\n\ta uint32\n\tb [0]byte\n}\n\ntype NoNameGood struct {\n\tGood\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype NoNameBad struct { // want \"struct of size 20 could be 16\"\n\tGood\n\tx byte\n\ty int32\n\tz byte\n}\n\ntype WithComments struct { // want \"struct of size 8 could be 4\"\n\t// doc style comment\n\ta uint32  // field a comment\n\tb [0]byte // field b comment\n\t// other doc style comment\n\n\t// and a last comment\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a.go.golden",
    "content": "package a\n\ntype Good struct {\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype Bad struct {\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype ZeroGood struct {\n\ta [0]byte\n\tb uint32\n}\n\ntype ZeroBad struct {\n\tb [0]byte\n\ta uint32\n}\n\ntype NoNameGood struct {\n\tGood\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype NoNameBad struct {\n\tGood\n\ty int32\n\tx byte\n\tz byte\n}\n\ntype WithComments struct {\n\tb [0]byte\n\ta uint32\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a_386.go",
    "content": "package a\n\ntype PointerGood struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerBad struct { // want \"struct with 4004 pointer bytes could be 4\"\n\tbuf [1000]uintptr\n\tP   *int\n}\n\ntype PointerSorta struct {\n\ta struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype PointerSortaBad struct { // want \"struct with 16 pointer bytes could be 12\"\n\ta struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n}\n\ntype MultiField struct { // want \"struct of size 20 could be 12\"\n\tb      bool\n\ti1, i2 int\n\ta3     [3]bool\n\t_      [0]func()\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a_386.go.golden",
    "content": "package a\n\ntype PointerGood struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerBad struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerSorta struct {\n\ta struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype PointerSortaBad struct {\n\tb struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\ta struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype MultiField struct {\n\t_  [0]func()\n\ti1 int\n\ti2 int\n\ta3 [3]bool\n\tb  bool\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a_amd64.go",
    "content": "package a\n\ntype PointerGood struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerBad struct { // want \"struct with 8008 pointer bytes could be 8\"\n\tbuf [1000]uintptr\n\tP   *int\n}\n\ntype PointerSorta struct {\n\ta struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype PointerSortaBad struct { // want \"struct with 32 pointer bytes could be 24\"\n\ta struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n}\n\ntype MultiField struct { // want \"struct of size 40 could be 24\"\n\tb      bool\n\ti1, i2 int\n\ta3     [3]bool\n\t_      [0]func()\n}\n\ntype Issue43233 struct { // want \"struct with 88 pointer bytes could be 80\"\n\tAllowedEvents []*string // allowed events\n\tBlockedEvents []*string // blocked events\n\tAPIVersion    string    `mapstructure:\"api_version\"`\n\tBaseURL       string    `mapstructure:\"base_url\"`\n\tAccessToken   string    `mapstructure:\"access_token\"`\n}\n"
  },
  {
    "path": "go/analysis/passes/fieldalignment/testdata/src/a/a_amd64.go.golden",
    "content": "package a\n\ntype PointerGood struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerBad struct {\n\tP   *int\n\tbuf [1000]uintptr\n}\n\ntype PointerSorta struct {\n\ta struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\tb struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype PointerSortaBad struct {\n\tb struct {\n\t\tp *int\n\t\tq uintptr\n\t}\n\ta struct {\n\t\tp *int\n\t\tq [2]uintptr\n\t}\n}\n\ntype MultiField struct {\n\t_  [0]func()\n\ti1 int\n\ti2 int\n\ta3 [3]bool\n\tb  bool\n}\n\ntype Issue43233 struct {\n\tAPIVersion    string `mapstructure:\"api_version\"`\n\tBaseURL       string `mapstructure:\"base_url\"`\n\tAccessToken   string `mapstructure:\"access_token\"`\n\tAllowedEvents []*string\n\tBlockedEvents []*string\n}\n"
  },
  {
    "path": "go/analysis/passes/findcall/cmd/findcall/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The findcall command runs the findcall analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(findcall.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/findcall/findcall.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package findcall defines an Analyzer that serves as a trivial\n// example and test of the Analysis API. It reports a diagnostic for\n// every call to a function or method of the name specified by its\n// -name flag. It also exports a fact for each declaration that\n// matches the name, plus a package-level fact if the package contained\n// one or more such declarations.\npackage findcall\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\nconst Doc = `find calls to a particular function\n\nThe findcall analysis reports calls to functions or methods\nof a particular name.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"findcall\",\n\tDoc:              Doc,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/findcall\",\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tFactTypes:        []analysis.Fact{new(foundFact)},\n}\n\nvar name string // -name flag\n\nfunc init() {\n\tAnalyzer.Flags.StringVar(&name, \"name\", name, \"name of the function to find\")\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tfor _, f := range pass.Files {\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\tvar id *ast.Ident\n\t\t\t\tswitch fun := call.Fun.(type) {\n\t\t\t\tcase *ast.Ident:\n\t\t\t\t\tid = fun\n\t\t\t\tcase *ast.SelectorExpr:\n\t\t\t\t\tid = fun.Sel\n\t\t\t\t}\n\t\t\t\tif id != nil && !pass.TypesInfo.Types[id].IsType() && id.Name == name {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     call.Lparen,\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"call of %s(...)\", id.Name),\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"Add '_TEST_'\"),\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos:     call.Lparen,\n\t\t\t\t\t\t\t\tEnd:     call.Lparen,\n\t\t\t\t\t\t\t\tNewText: []byte(\"_TEST_\"),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\n\t// Export a fact for each matching function.\n\t//\n\t// These facts are produced only to test the testing\n\t// infrastructure in the analysistest package.\n\t// They are not consumed by the findcall Analyzer\n\t// itself, as would happen in a more realistic example.\n\tfor _, f := range pass.Files {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && decl.Name.Name == name {\n\t\t\t\tif obj, ok := pass.TypesInfo.Defs[decl.Name].(*types.Func); ok {\n\t\t\t\t\tpass.ExportObjectFact(obj, new(foundFact))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(pass.AllObjectFacts()) > 0 {\n\t\tpass.ExportPackageFact(new(foundFact))\n\t}\n\n\treturn nil, nil\n}\n\n// foundFact is a fact associated with functions that match -name.\n// We use it to exercise the fact machinery in tests.\ntype foundFact struct{}\n\nfunc (*foundFact) String() string { return \"found\" }\nfunc (*foundFact) AFact()         {}\n"
  },
  {
    "path": "go/analysis/passes/findcall/findcall_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage findcall_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n)\n\nfunc init() {\n\tfindcall.Analyzer.Flags.Set(\"name\", \"println\")\n}\n\n// TestFromStringLiterals demonstrates how to test an analysis using\n// a table of string literals for each test case.\n//\n// Such tests are typically quite compact.\nfunc TestFromStringLiterals(t *testing.T) {\n\n\tfor _, test := range [...]struct {\n\t\tdesc    string\n\t\tpkgpath string\n\t\tfiles   map[string]string\n\t}{\n\t\t{\n\t\t\tdesc:    \"SimpleTest\",\n\t\t\tpkgpath: \"main\",\n\t\t\tfiles: map[string]string{\"main/main.go\": `package main // want package:\"found\"\n\nfunc main() {\n\tprintln(\"hello\") // want \"call of println\"\n\tprint(\"goodbye\") // not a call of println\n}\n\nfunc println(s string) {} // want println:\"found\"`,\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tdir, cleanup, err := analysistest.WriteFiles(test.files)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer cleanup()\n\t\t\tanalysistest.Run(t, dir, findcall.Analyzer, test.pkgpath)\n\t\t})\n\t}\n}\n\n// TestFromFileSystem demonstrates how to test an analysis using input\n// files stored in the file system.\n//\n// These tests have the advantages that test data can be edited\n// directly, and that files named in error messages can be opened.\n// However, they tend to spread a small number of lines of text across a\n// rather deep directory hierarchy, and obscure similarities among\n// related tests, especially when tests involve multiple packages, or\n// multiple variants of a single scenario.\nfunc TestFromFileSystem(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, findcall.Analyzer, \"a\") // loads testdata/src/a/a.go.\n}\n"
  },
  {
    "path": "go/analysis/passes/findcall/testdata/src/a/a.go",
    "content": "package main // want package:\"found\"\n\nfunc main() {\n\tprintln(\"hi\") // want \"call of println\"\n\tprint(\"hi\")   // not a call of println\n}\n\nfunc println(s string) {} // want println:\"found\"\n"
  },
  {
    "path": "go/analysis/passes/findcall/testdata/src/a/a.go.golden",
    "content": "package main // want package:\"found\"\n\nfunc main() {\n\tprintln_TEST_(\"hi\") // want \"call of println\"\n\tprint(\"hi\")         // not a call of println\n}\n\nfunc println(s string) {} // want println:\"found\"\n"
  },
  {
    "path": "go/analysis/passes/framepointer/framepointer.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package framepointer defines an Analyzer that reports assembly code\n// that clobbers the frame pointer before saving it.\npackage framepointer\n\nimport (\n\t\"go/build\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\nconst Doc = \"report assembly that clobbers the frame pointer before saving it\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"framepointer\",\n\tDoc:  Doc,\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer\",\n\tRun:  run,\n}\n\n// Per-architecture checks for instructions.\n// Assume comments, leading and trailing spaces are removed.\ntype arch struct {\n\tisFPWrite             func(string) bool\n\tisFPRead              func(string) bool\n\tisUnconditionalBranch func(string) bool\n}\n\nvar re = regexp.MustCompile\n\nfunc hasAnyPrefix(s string, prefixes ...string) bool {\n\tfor _, p := range prefixes {\n\t\tif strings.HasPrefix(s, p) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nvar arches = map[string]arch{\n\t\"amd64\": {\n\t\tisFPWrite: re(`,\\s*BP$`).MatchString, // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely.\n\t\tisFPRead:  re(`\\bBP\\b`).MatchString,\n\t\tisUnconditionalBranch: func(s string) bool {\n\t\t\treturn hasAnyPrefix(s, \"JMP\", \"RET\")\n\t\t},\n\t},\n\t\"arm64\": {\n\t\tisFPWrite: func(s string) bool {\n\t\t\tif i := strings.LastIndex(s, \",\"); i > 0 && strings.HasSuffix(s[i:], \"R29\") {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif hasAnyPrefix(s, \"LDP\", \"LDAXP\", \"LDXP\", \"CASP\") {\n\t\t\t\t// Instructions which write to a pair of registers, e.g.\n\t\t\t\t//\tLDP 8(R0), (R26, R29)\n\t\t\t\t//\tCASPD (R2, R3), (R2), (R26, R29)\n\t\t\t\tlp := strings.LastIndex(s, \"(\")\n\t\t\t\trp := strings.LastIndex(s, \")\")\n\t\t\t\tif lp > -1 && lp < rp {\n\t\t\t\t\treturn strings.Contains(s[lp:rp], \",\") && strings.Contains(s[lp:rp], \"R29\")\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\t},\n\t\tisFPRead: re(`\\bR29\\b`).MatchString,\n\t\tisUnconditionalBranch: func(s string) bool {\n\t\t\t// Get just the instruction\n\t\t\tif i := strings.IndexFunc(s, unicode.IsSpace); i > 0 {\n\t\t\t\ts = s[:i]\n\t\t\t}\n\t\t\treturn s == \"B\" || s == \"JMP\" || s == \"RET\"\n\t\t},\n\t},\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tarch, ok := arches[build.Default.GOARCH]\n\tif !ok {\n\t\treturn nil, nil\n\t}\n\tif build.Default.GOOS != \"linux\" && build.Default.GOOS != \"darwin\" {\n\t\treturn nil, nil\n\t}\n\n\t// Find assembly files to work on.\n\tvar sfiles []string\n\tfor _, fname := range pass.OtherFiles {\n\t\tif strings.HasSuffix(fname, \".s\") && pass.Pkg.Path() != \"runtime\" {\n\t\t\tsfiles = append(sfiles, fname)\n\t\t}\n\t}\n\n\tfor _, fname := range sfiles {\n\t\tcontent, tf, err := analyzerutil.ReadFile(pass, fname)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tlines := strings.SplitAfter(string(content), \"\\n\")\n\t\tactive := false\n\t\tfor lineno, line := range lines {\n\t\t\tlineno++\n\n\t\t\t// Ignore comments and commented-out code.\n\t\t\tif i := strings.Index(line, \"//\"); i >= 0 {\n\t\t\t\tline = line[:i]\n\t\t\t}\n\t\t\tline = strings.TrimSpace(line)\n\t\t\tif line == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// We start checking code at a TEXT line for a frameless function.\n\t\t\tif strings.HasPrefix(line, \"TEXT\") && strings.Contains(line, \"(SB)\") && strings.Contains(line, \"$0\") {\n\t\t\t\tactive = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !active {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif arch.isFPWrite(line) {\n\t\t\t\tpass.Reportf(tf.LineStart(lineno), \"frame pointer is clobbered before saving\")\n\t\t\t\tactive = false\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif arch.isFPRead(line) || arch.isUnconditionalBranch(line) {\n\t\t\t\tactive = false\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/framepointer/framepointer_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage framepointer_test\n\nimport (\n\t\"go/build\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/framepointer\"\n)\n\nfunc Test(t *testing.T) {\n\tif build.Default.GOOS != \"linux\" && build.Default.GOOS != \"darwin\" {\n\t\t// The test has an os-generic assembly file, testdata/a/asm_amd64.s.\n\t\t// It should produce errors on linux or darwin, but not on other archs.\n\t\t// Unfortunately, there's no way to say that in the \"want\" comments\n\t\t// in that file. So we skip testing on other GOOSes. The framepointer\n\t\t// analyzer should not report any errors on those GOOSes, so it's not\n\t\t// really a hard test on those platforms.\n\t\tt.Skipf(\"test for GOOS=%s is not implemented\", build.Default.GOOS)\n\t}\n\tanalysistest.Run(t, analysistest.TestData(), framepointer.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm_amd64.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nTEXT ·bad1(SB), 0, $0\n\tMOVQ\t$0, BP // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad2(SB), 0, $0\n\tMOVQ\tAX, BP // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad3(SB), 0, $0\n\tMOVQ\t6(AX), BP // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad4(SB), 0, $0\n\tCMPQ\tAX, BX\n\tJEQ\tskip\n\t// Assume the above conditional branch is not taken\n\tMOVQ\t$0, BP // want `frame pointer is clobbered before saving`\nskip:\n\tRET\nTEXT ·good1(SB), 0, $0\n\tPUSHQ\tBP\n\tMOVQ\t$0, BP // this is ok\n\tPOPQ\tBP\n\tRET\nTEXT ·good2(SB), 0, $0\n\tMOVQ\tBP, BX\n\tMOVQ\t$0, BP // this is ok\n\tMOVQ\tBX, BP\n\tRET\nTEXT ·good3(SB), 0, $0\n\tCMPQ\tAX, BX\n\tJMP\tskip\n\tMOVQ\t$0, BP // this is ok\nskip:\n\tRET\nTEXT ·good4(SB), 0, $0\n\tRET\n\tMOVQ\t$0, BP // this is ok\n\tRET\nTEXT ·good5(SB), 0, $8\n\tMOVQ\t$0, BP // this is ok\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm_arm64.s",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nTEXT ·bad1(SB), 0, $0\n\tMOVD\t$0, R29 // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad2(SB), 0, $0\n\tMOVD\tR1, R29 // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad3(SB), 0, $0\n\tMOVD\t6(R2), R29 // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad4(SB), 0, $0\n\tLDP\t0(R1), (R26, R29) // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad5(SB), 0, $0\n\tAND\t$0x1, R3, R29 // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·bad6(SB), 0, $0\n\tCMP\tR1, R2\n\tBEQ\tskip\n\t// Assume that the above conditional branch is not taken\n\tMOVD\t$0, R29 // want `frame pointer is clobbered before saving`\nskip:\n\tRET\nTEXT ·bad7(SB), 0, $0\n\tBL\t·good4(SB)\n\tAND\t$0x1, R3, R29 // want `frame pointer is clobbered before saving`\n\tRET\nTEXT ·good1(SB), 0, $0\n\tSTPW \t(R29, R30), -32(RSP)\n\tMOVD\t$0, R29 // this is ok\n\tLDPW\t32(RSP), (R29, R30)\n\tRET\nTEXT ·good2(SB), 0, $0\n\tMOVD\tR29, R1\n\tMOVD\t$0, R29 // this is ok\n\tMOVD\tR1, R29\n\tRET\nTEXT ·good3(SB), 0, $0\n\tCMP\tR1, R2\n\tB\tskip\n\tMOVD\t$0, R29 // this is ok\nskip:\n\tRET\nTEXT ·good4(SB), 0, $0\n\tRET\n\tMOVD\t$0, R29 // this is ok\n\tRET\nTEXT ·good5(SB), 0, $8\n\tMOVD\t$0, R29 // this is ok\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm_darwin_amd64.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nTEXT ·z1(SB), 0, $0\n\tMOVQ\t$0, BP // want `frame pointer is clobbered before saving`\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm_linux_amd64.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nTEXT ·z1(SB), 0, $0\n\tMOVQ\t$0, BP // want `frame pointer is clobbered before saving`\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/asm_windows_amd64.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\nTEXT ·z1(SB), 0, $0\n\tMOVQ\t$0, BP // not an error on windows\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/framepointer/testdata/src/a/buildtag_amd64.s",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build nope\n\nTEXT ·bt1(SB), 0, $0\n\tMOVQ\t$0, BP // ok because of build tag\n\tRET\n"
  },
  {
    "path": "go/analysis/passes/gofix/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage gofix defines an Analyzer that checks \"//go:fix inline\" directives.\nSee golang.org/x/tools/go/analysis/passes/inline/doc.go for details.\n\n# Analyzer gofixdirective\n\ngofixdirective: validate uses of gofix comment directives\n\nThe gofixdirective analyzer checks \"//go:fix inline\" directives for correctness.\n\nThe proposal https://go.dev/issue/32816 introduces the \"//go:fix\" directives.\n\nThe analyzer checks for the following issues:\n\n- A constant definition can be marked for inlining only if it refers to another\nnamed constant.\n\n\t//go:fix inline\n\tconst (\n\t\ta = 1       // error\n\t\tb = iota    // error\n\t\tc = a       // OK\n\t\td = math.Pi // OK\n\t)\n\n- A type definition can be marked for inlining only if it is an alias.\n\n\t//go:fix inline\n\ttype (\n\t\tT int    // error\n\t\tA = int  // OK\n\t)\n\n- An alias whose right-hand side contains a non-literal array size\ncannot be marked for inlining.\n\n\tconst two = 2\n\n\t//go:fix inline\n\ttype (\n\t\tA = []int     // OK\n\t\tB = [1]int    // OK\n\t\tC = [two]int  // error\n\t)\n*/\npackage gofix\n"
  },
  {
    "path": "go/analysis/passes/gofix/gofix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gofix defines an analyzer that checks go:fix directives.\npackage gofix\n\nimport (\n\t_ \"embed\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/analysis/passes/internal/gofixdirective\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"gofixdirective\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"gofixdirective\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/gofix\",\n\tRun:      run,\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\troot := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root()\n\tgofixdirective.Find(pass, root, nil)\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/gofix/gofix_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gofix_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/gofix\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, gofix.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/gofix/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the gofix checker.\n\npackage a\n\nconst one = 1\n\n//go:fix inline\nconst (\n\tin3  = one\n\tin4  = one\n\tbad1 = 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n)\n\n//go:fix inline\nconst in5,\n\tin6,\n\tbad2 = one, one,\n\tone + 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n//go:fix inline\nconst (\n\ta = iota // want `invalid //go:fix inline directive: const value is iota`\n\tb\n\tin7 = one\n)\n\nfunc shadow() {\n\t//go:fix inline\n\tconst a = iota // want `invalid //go:fix inline directive: const value is iota`\n\n\tconst iota = 2\n\n\t//go:fix inline\n\tconst b = iota // not an error: iota is not the builtin\n}\n\n// Type aliases\n\n//go:fix inline\ntype A int // want `invalid //go:fix inline directive: not a type alias`\n\n//go:fix inline\ntype E = map[[one]string][]int // want `invalid //go:fix inline directive: array types not supported`\n"
  },
  {
    "path": "go/analysis/passes/hostport/hostport.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package hostport defines an analyzer for calls to net.Dial with\n// addresses of the form \"%s:%d\" or \"%s:%s\", which work only with IPv4.\npackage hostport\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nconst Doc = `check format of addresses passed to net.Dial\n\nThis analyzer flags code that produce network address strings using\nfmt.Sprintf, as in this example:\n\n    addr := fmt.Sprintf(\"%s:%d\", host, 12345) // \"will not work with IPv6\"\n    ...\n    conn, err := net.Dial(\"tcp\", addr)       // \"when passed to dial here\"\n\nThe analyzer suggests a fix to use the correct approach, a call to\nnet.JoinHostPort:\n\n    addr := net.JoinHostPort(host, \"12345\")\n    ...\n    conn, err := net.Dial(\"tcp\", addr)\n\nA similar diagnostic and fix are produced for a format string of \"%s:%s\".\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"hostport\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/hostport\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer, typeindexanalyzer.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex      = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo       = pass.TypesInfo\n\t\tfmtSprintf = index.Object(\"fmt\", \"Sprintf\")\n\t)\n\tif !index.Used(fmtSprintf) {\n\t\treturn nil, nil // fast path: package doesn't use fmt.Sprintf\n\t}\n\n\t// checkAddr reports a diagnostic (and returns true) if e\n\t// is a call of the form fmt.Sprintf(\"%s:%d\", ...).\n\t// The diagnostic includes a fix.\n\t//\n\t// dialCall is non-nil if the Dial call is non-local\n\t// but within the same file.\n\tcheckAddr := func(e ast.Expr, dialCall *ast.CallExpr) {\n\t\tif call, ok := e.(*ast.CallExpr); ok &&\n\t\t\tlen(call.Args) == 3 &&\n\t\t\ttypeutil.Callee(info, call) == fmtSprintf {\n\n\t\t\t// Examine format string.\n\t\t\tformatArg := call.Args[0]\n\t\t\tif tv := info.Types[formatArg]; tv.Value != nil {\n\t\t\t\tnumericPort := false\n\t\t\t\tformat := constant.StringVal(tv.Value)\n\t\t\t\tswitch format {\n\t\t\t\tcase \"%s:%d\":\n\t\t\t\t\t// Have: fmt.Sprintf(\"%s:%d\", host, port)\n\t\t\t\t\tnumericPort = true\n\n\t\t\t\tcase \"%s:%s\":\n\t\t\t\t\t// Have: fmt.Sprintf(\"%s:%s\", host, portStr)\n\t\t\t\t\t// Keep port string as is.\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Use granular edits to preserve original formatting.\n\t\t\t\tedits := []analysis.TextEdit{\n\t\t\t\t\t{\n\t\t\t\t\t\t// Replace fmt.Sprintf with net.JoinHostPort.\n\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\tNewText: []byte(\"net.JoinHostPort\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t// Delete format string.\n\t\t\t\t\t\tPos: formatArg.Pos(),\n\t\t\t\t\t\tEnd: call.Args[1].Pos(),\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\t// Turn numeric port into a string.\n\t\t\t\tif numericPort {\n\t\t\t\t\tport := call.Args[2]\n\n\t\t\t\t\t// Is port an integer literal?\n\t\t\t\t\t//\n\t\t\t\t\t// (Don't allow arbitrary constants k otherwise the\n\t\t\t\t\t// transformation k => fmt.Sprintf(\"%d\", \"123\")\n\t\t\t\t\t// loses the symbolic connection to k.)\n\t\t\t\t\tvar kPort int64 = -1\n\t\t\t\t\tif lit, ok := port.(*ast.BasicLit); ok && lit.Kind == token.INT {\n\t\t\t\t\t\tif v, err := strconv.ParseInt(lit.Value, 0, 64); err == nil {\n\t\t\t\t\t\t\tkPort = v\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif kPort >= 0 {\n\t\t\t\t\t\t// literal: 0x7B  => \"123\"\n\t\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\t\tPos:     port.Pos(),\n\t\t\t\t\t\t\tEnd:     port.End(),\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, `\"%d\"`, kPort), // (decimal)\n\t\t\t\t\t\t})\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// non-literal: port => fmt.Sprintf(\"%d\", port)\n\t\t\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos:     port.Pos(),\n\t\t\t\t\t\t\t\tEnd:     port.Pos(),\n\t\t\t\t\t\t\t\tNewText: []byte(`fmt.Sprintf(\"%d\", `),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos:     port.End(),\n\t\t\t\t\t\t\t\tEnd:     port.End(),\n\t\t\t\t\t\t\t\tNewText: []byte(`)`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}...)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Refer to Dial call, if not adjacent.\n\t\t\t\tsuffix := \"\"\n\t\t\t\tif dialCall != nil {\n\t\t\t\t\tsuffix = fmt.Sprintf(\" (passed to net.Dial at L%d)\",\n\t\t\t\t\t\tpass.Fset.Position(dialCall.Pos()).Line)\n\t\t\t\t}\n\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t// Highlight the format string.\n\t\t\t\t\tPos:     formatArg.Pos(),\n\t\t\t\t\tEnd:     formatArg.End(),\n\t\t\t\t\tMessage: fmt.Sprintf(\"address format %q does not work with IPv6%s\", format, suffix),\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage:   \"Replace fmt.Sprintf with net.JoinHostPort\",\n\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check address argument of each call to net.Dial et al.\n\tfor _, callee := range []types.Object{\n\t\tindex.Object(\"net\", \"Dial\"),\n\t\tindex.Object(\"net\", \"DialTimeout\"),\n\t\tindex.Selection(\"net\", \"Dialer\", \"Dial\"),\n\t} {\n\t\tfor curCall := range index.Calls(callee) {\n\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\tswitch address := call.Args[1].(type) {\n\t\t\tcase *ast.CallExpr:\n\t\t\t\tif len(call.Args) == 2 { // avoid spread-call edge case\n\t\t\t\t\t// net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", ...))\n\t\t\t\t\tcheckAddr(address, nil)\n\t\t\t\t}\n\n\t\t\tcase *ast.Ident:\n\t\t\t\t// addr := fmt.Sprintf(\"%s:%d\", ...)\n\t\t\t\t// ...\n\t\t\t\t// net.Dial(\"tcp\", addr)\n\n\t\t\t\t// Search for decl of addrVar within common ancestor of addrVar and Dial call.\n\t\t\t\t// TODO(adonovan): abstract \"find RHS of statement that assigns var v\".\n\t\t\t\t// TODO(adonovan): reject if there are other assignments to var v.\n\t\t\t\tif addrVar, ok := info.Uses[address].(*types.Var); ok {\n\t\t\t\t\tif curId, ok := index.Def(addrVar); ok {\n\t\t\t\t\t\t// curIdent is the declaring ast.Ident of addr.\n\t\t\t\t\t\tswitch parent := curId.Parent().Node().(type) {\n\t\t\t\t\t\tcase *ast.AssignStmt:\n\t\t\t\t\t\t\tif len(parent.Rhs) == 1 {\n\t\t\t\t\t\t\t\t// Have: addr := fmt.Sprintf(\"%s:%d\", ...)\n\t\t\t\t\t\t\t\tcheckAddr(parent.Rhs[0], call)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t\t\tif len(parent.Values) == 1 {\n\t\t\t\t\t\t\t\t// Have: var addr = fmt.Sprintf(\"%s:%d\", ...)\n\t\t\t\t\t\t\t\tcheckAddr(parent.Values[0], call)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/hostport/hostport_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage hostport_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/hostport\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, hostport.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/hostport/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/hostport\"\n)\n\nfunc main() { singlechecker.Main(hostport.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/hostport/testdata/src/a/a.go",
    "content": "package a\n\nimport (\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc direct(host string, port int, portStr string) {\n\t// Dial, directly called with result of Sprintf.\n\tnet.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", host, port)) // want `address format \"%s:%d\" does not work with IPv6`\n\n\tnet.Dial(\"tcp\", fmt.Sprintf(\"%s:%s\", host, portStr)) // want `address format \"%s:%s\" does not work with IPv6`\n}\n\n// port is a literal:\nvar addr4 = fmt.Sprintf(\"%s:%d\", \"localhost\", 123) // want `address format \"%s:%d\" does not work with IPv6 \\(passed to net.Dial at L39\\)`\n\nfunc indirect(host string, port int) {\n\t// Dial, addr is immediately preceding.\n\t{\n\t\taddr1 := fmt.Sprintf(\"%s:%d\", host, port) // want `address format \"%s:%d\" does not work with IPv6.*at L22`\n\t\tnet.Dial(\"tcp\", addr1)\n\t}\n\n\t// DialTimeout, addr is in ancestor block.\n\taddr2 := fmt.Sprintf(\"%s:%d\", host, port) // want `address format \"%s:%d\" does not work with IPv6.*at L28`\n\t{\n\t\tnet.DialTimeout(\"tcp\", addr2, 0)\n\t}\n\n\t// Dialer.Dial, addr is declared with var.\n\tvar dialer net.Dialer\n\t{\n\t\tvar addr3 = fmt.Sprintf(\"%s:%d\", host, port) // want `address format \"%s:%d\" does not work with IPv6.*at L35`\n\t\tdialer.Dial(\"tcp\", addr3)\n\t}\n\n\t// Dialer.Dial again, addr is declared at package level.\n\tdialer.Dial(\"tcp\", addr4)\n}\n\n// Regression tests for crashes in well-typed code that nonetheless mis-uses Sprintf:\n// too few arguments, or port is not an integer.\nvar (\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\"))\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", \"host\"))\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", \"host\", \"port\")) // want `address format \"%s:%d\" does not work with IPv6`\n)\n\nfunc _() {\n\t// port is a non-constant literal\n\tconst port = 0x7B\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", \"localhost\", port)) // want `address format \"%s:%d\" does not work with IPv6`\n}\n"
  },
  {
    "path": "go/analysis/passes/hostport/testdata/src/a/a.go.golden",
    "content": "package a\n\nimport (\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc direct(host string, port int, portStr string) {\n\t// Dial, directly called with result of Sprintf.\n\tnet.Dial(\"tcp\", net.JoinHostPort(host, fmt.Sprintf(\"%d\", port))) // want `address format \"%s:%d\" does not work with IPv6`\n\n\tnet.Dial(\"tcp\", net.JoinHostPort(host, portStr)) // want `address format \"%s:%s\" does not work with IPv6`\n}\n\n// port is a literal:\nvar addr4 = net.JoinHostPort(\"localhost\", \"123\") // want `address format \"%s:%d\" does not work with IPv6 \\(passed to net.Dial at L39\\)`\n\nfunc indirect(host string, port int) {\n\t// Dial, addr is immediately preceding.\n\t{\n\t\taddr1 := net.JoinHostPort(host, fmt.Sprintf(\"%d\", port)) // want `address format \"%s:%d\" does not work with IPv6.*at L22`\n\t\tnet.Dial(\"tcp\", addr1)\n\t}\n\n\t// DialTimeout, addr is in ancestor block.\n\taddr2 := net.JoinHostPort(host, fmt.Sprintf(\"%d\", port)) // want `address format \"%s:%d\" does not work with IPv6.*at L28`\n\t{\n\t\tnet.DialTimeout(\"tcp\", addr2, 0)\n\t}\n\n\t// Dialer.Dial, addr is declared with var.\n\tvar dialer net.Dialer\n\t{\n\t\tvar addr3 = net.JoinHostPort(host, fmt.Sprintf(\"%d\", port)) // want `address format \"%s:%d\" does not work with IPv6.*at L35`\n\t\tdialer.Dial(\"tcp\", addr3)\n\t}\n\n\t// Dialer.Dial again, addr is declared at package level.\n\tdialer.Dial(\"tcp\", addr4)\n}\n\n// Regression tests for crashes in well-typed code that nonetheless mis-uses Sprintf:\n// too few arguments, or port is not an integer.\nvar (\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\"))\n\t_, _ = net.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", \"host\"))\n\t_, _ = net.Dial(\"tcp\", net.JoinHostPort(\"host\", fmt.Sprintf(\"%d\", \"port\"))) // want `address format \"%s:%d\" does not work with IPv6`\n)\n\nfunc _() {\n\t// port is a non-constant literal\n\tconst port = 0x7B\n\t_, _ = net.Dial(\"tcp\", net.JoinHostPort(\"localhost\", fmt.Sprintf(\"%d\", port))) // want `address format \"%s:%d\" does not work with IPv6`\n}\n"
  },
  {
    "path": "go/analysis/passes/httpmux/cmd/httpmux/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The httpmux command runs the httpmux analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/httpmux\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(httpmux.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/httpmux/httpmux.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage httpmux\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = `report using Go 1.22 enhanced ServeMux patterns in older Go versions\n\nThe httpmux analysis is active for Go modules configured to run with Go 1.21 or\nearlier versions. It reports calls to net/http.ServeMux.Handle and HandleFunc\nmethods whose patterns use features added in Go 1.22, like HTTP methods (such as\n\"GET\") and wildcards. (See https://pkg.go.dev/net/http#ServeMux for details.)\nSuch patterns can be registered in older versions of Go, but will not behave as expected.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"httpmux\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpmux\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nvar inTest bool // So Go version checks can be skipped during testing.\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !inTest {\n\t\t// Check that Go version is 1.21 or earlier.\n\t\tif goVersionAfter121(goVersion(pass.Pkg)) {\n\t\t\treturn nil, nil\n\t\t}\n\t}\n\tif !typesinternal.Imports(pass.Pkg, \"net/http\") {\n\t\treturn nil, nil\n\t}\n\t// Look for calls to ServeMux.Handle or ServeMux.HandleFunc.\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tif isServeMuxRegisterCall(pass, call) {\n\t\t\tpat, ok := stringConstantExpr(pass, call.Args[0])\n\t\t\tif ok && likelyEnhancedPattern(pat) {\n\t\t\t\tpass.ReportRangef(call.Args[0], \"possible enhanced ServeMux pattern used with Go version before 1.22 (update go.mod file?)\")\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// isServeMuxRegisterCall reports whether call is a static call to one of:\n// - net/http.Handle\n// - net/http.HandleFunc\n// - net/http.ServeMux.Handle\n// - net/http.ServeMux.HandleFunc\n// TODO(jba): consider expanding this to accommodate wrappers around these functions.\nfunc isServeMuxRegisterCall(pass *analysis.Pass, call *ast.CallExpr) bool {\n\tfn := typeutil.StaticCallee(pass.TypesInfo, call)\n\tif fn == nil {\n\t\treturn false\n\t}\n\tif typesinternal.IsFunctionNamed(fn, \"net/http\", \"Handle\", \"HandleFunc\") {\n\t\treturn true\n\t}\n\tif !isMethodNamed(fn, \"net/http\", \"Handle\", \"HandleFunc\") {\n\t\treturn false\n\t}\n\trecv := fn.Signature().Recv() // isMethodNamed() -> non-nil\n\tisPtr, named := typesinternal.ReceiverNamed(recv)\n\treturn isPtr && typesinternal.IsTypeNamed(named, \"net/http\", \"ServeMux\")\n}\n\n// isMethodNamed reports when a function f is a method,\n// in a package with the path pkgPath and the name of f is in names.\n//\n// (Unlike [analysis.IsMethodNamed], it ignores the receiver type name.)\nfunc isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {\n\tif f == nil {\n\t\treturn false\n\t}\n\tif f.Pkg() == nil || f.Pkg().Path() != pkgPath {\n\t\treturn false // not at pkgPath\n\t}\n\tif f.Signature().Recv() == nil {\n\t\treturn false // not a method\n\t}\n\treturn slices.Contains(names, f.Name())\n}\n\n// stringConstantExpr returns expression's string constant value.\n//\n// (\"\", false) is returned if expression isn't a string\n// constant.\nfunc stringConstantExpr(pass *analysis.Pass, expr ast.Expr) (string, bool) {\n\tlit := pass.TypesInfo.Types[expr].Value\n\tif lit != nil && lit.Kind() == constant.String {\n\t\treturn constant.StringVal(lit), true\n\t}\n\treturn \"\", false\n}\n\n// A valid wildcard must start a segment, and its name must be valid Go\n// identifier.\nvar wildcardRegexp = regexp.MustCompile(`/\\{[_\\pL][_\\pL\\p{Nd}]*(\\.\\.\\.)?\\}`)\n\n// likelyEnhancedPattern reports whether the ServeMux pattern pat probably\n// contains either an HTTP method name or a wildcard, extensions added in Go 1.22.\nfunc likelyEnhancedPattern(pat string) bool {\n\tif strings.Contains(pat, \" \") {\n\t\t// A space in the pattern suggests that it begins with an HTTP method.\n\t\treturn true\n\t}\n\treturn wildcardRegexp.MatchString(pat)\n}\n\nfunc goVersionAfter121(goVersion string) bool {\n\tif goVersion == \"\" { // Maybe the stdlib?\n\t\treturn true\n\t}\n\tversion := versionFromGoVersion(goVersion)\n\treturn semver.Compare(version, \"v1.21\") > 0\n}\n\nfunc goVersion(pkg *types.Package) string {\n\t// types.Package.GoVersion did not exist before Go 1.21.\n\tif p, ok := any(pkg).(interface{ GoVersion() string }); ok {\n\t\treturn p.GoVersion()\n\t}\n\treturn \"\"\n}\n\nvar (\n\t// Regexp for matching go tags. The groups are:\n\t// 1  the major.minor version\n\t// 2  the patch version, or empty if none\n\t// 3  the entire prerelease, if present\n\t// 4  the prerelease type (\"beta\" or \"rc\")\n\t// 5  the prerelease number\n\ttagRegexp = regexp.MustCompile(`^go(\\d+\\.\\d+)(\\.\\d+|)((beta|rc)(\\d+))?$`)\n)\n\n// Copied from pkgsite/internal/stdlib.VersionForTag.\nfunc versionFromGoVersion(goVersion string) string {\n\t// Special cases for go1.\n\tif goVersion == \"go1\" {\n\t\treturn \"v1.0.0\"\n\t}\n\tif goVersion == \"go1.0\" {\n\t\treturn \"\"\n\t}\n\tm := tagRegexp.FindStringSubmatch(goVersion)\n\tif m == nil {\n\t\treturn \"\"\n\t}\n\tversion := \"v\" + m[1]\n\tif m[2] != \"\" {\n\t\tversion += m[2]\n\t} else {\n\t\tversion += \".0\"\n\t}\n\tif m[3] != \"\" {\n\t\tversion += \"-\" + m[4] + \".\" + m[5]\n\t}\n\treturn version\n}\n"
  },
  {
    "path": "go/analysis/passes/httpmux/httpmux_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage httpmux\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\ttests := []string{\"a\"}\n\tinTest = true\n\tanalysistest.Run(t, testdata, Analyzer, tests...)\n}\n\nfunc TestGoVersion(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tin   string\n\t\twant bool\n\t}{\n\t\t{\"\", true},\n\t\t{\"go1\", false},\n\t\t{\"go1.21\", false},\n\t\t{\"go1.21rc3\", false},\n\t\t{\"go1.22\", true},\n\t\t{\"go1.22rc1\", true},\n\t} {\n\t\tgot := goVersionAfter121(test.in)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"%q: got %t, want %t\", test.in, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/httpmux/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the httpmux checker.\n\npackage a\n\nimport \"net/http\"\n\nfunc _() {\n\thttp.HandleFunc(\"GET /x\", nil)  // want \"enhanced ServeMux pattern\"\n\thttp.HandleFunc(\"/{a}/b/\", nil) // want \"enhanced ServeMux pattern\"\n\tmux := http.NewServeMux()\n\tmux.Handle(\"example.com/c/{d}\", nil) // want \"enhanced ServeMux pattern\"\n\tmux.HandleFunc(\"/{x...}\", nil)       // want \"enhanced ServeMux pattern\"\n\n\t// Should not match.\n\n\t// not an enhanced pattern\n\thttp.Handle(\"/\", nil)\n\n\t// invalid wildcard; will panic in 1.22\n\thttp.HandleFunc(\"/{/a/}\", nil)\n\tmux.Handle(\"/{1}\", nil)\n\tmux.Handle(\"/x{a}\", nil)\n\n\t// right package, wrong method\n\thttp.ParseTime(\"GET /\")\n\n\t// right function name, wrong package\n\tHandle(\"GET /\", nil)\n\tHandleFunc(\"GET /\", nil)\n\n\t// right method name, wrong type\n\tvar sm ServeMux\n\tsm.Handle(\"example.com/c/{d}\", nil)\n\tsm.HandleFunc(\"method /{x...}\", nil)\n}\n\nfunc Handle(pat string, x any)     {}\nfunc HandleFunc(pat string, x any) {}\n\ntype ServeMux struct{}\n\nfunc (*ServeMux) Handle(pat string, x any)     {}\nfunc (*ServeMux) HandleFunc(pat string, x any) {}\n"
  },
  {
    "path": "go/analysis/passes/httpresponse/httpresponse.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package httpresponse defines an Analyzer that checks for mistakes\n// using HTTP responses.\npackage httpresponse\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = `check for mistakes using HTTP responses\n\nA common mistake when using the net/http package is to defer a function\ncall to close the http.Response Body before checking the error that\ndetermines whether the response is valid:\n\n\tresp, err := http.Head(url)\n\tdefer resp.Body.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// (defer statement belongs here)\n\nThis checker helps uncover latent nil dereference bugs by reporting a\ndiagnostic for such mistakes.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"httpresponse\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpresponse\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// Fast path: if the package doesn't import net/http,\n\t// skip the traversal.\n\tif !typesinternal.Imports(pass.Pkg, \"net/http\") {\n\t\treturn nil, nil\n\t}\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) bool {\n\t\tif !push {\n\t\t\treturn true\n\t\t}\n\t\tcall := n.(*ast.CallExpr)\n\t\tif !isHTTPFuncOrMethodOnClient(pass.TypesInfo, call) {\n\t\t\treturn true // the function call is not related to this check.\n\t\t}\n\n\t\t// Find the innermost containing block, and get the list\n\t\t// of statements starting with the one containing call.\n\t\tstmts, ncalls := restOfBlock(stack)\n\t\tif len(stmts) < 2 {\n\t\t\t// The call to the http function is the last statement of the block.\n\t\t\treturn true\n\t\t}\n\n\t\t// Skip cases in which the call is wrapped by another (#52661).\n\t\t// Example:  resp, err := checkError(http.Get(url))\n\t\tif ncalls > 1 {\n\t\t\treturn true\n\t\t}\n\n\t\tasg, ok := stmts[0].(*ast.AssignStmt)\n\t\tif !ok {\n\t\t\treturn true // the first statement is not assignment.\n\t\t}\n\n\t\tresp := rootIdent(asg.Lhs[0])\n\t\tif resp == nil {\n\t\t\treturn true // could not find the http.Response in the assignment.\n\t\t}\n\n\t\tdef, ok := stmts[1].(*ast.DeferStmt)\n\t\tif !ok {\n\t\t\treturn true // the following statement is not a defer.\n\t\t}\n\t\troot := rootIdent(def.Call.Fun)\n\t\tif root == nil {\n\t\t\treturn true // could not find the receiver of the defer call.\n\t\t}\n\n\t\tif resp.Obj == root.Obj {\n\t\t\tpass.ReportRangef(root, \"using %s before checking for errors\", resp.Name)\n\t\t}\n\t\treturn true\n\t})\n\treturn nil, nil\n}\n\n// isHTTPFuncOrMethodOnClient checks whether the given call expression is on\n// either a function of the net/http package or a method of http.Client that\n// returns (*http.Response, error).\nfunc isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {\n\tfun, _ := expr.Fun.(*ast.SelectorExpr)\n\tsig, _ := info.Types[fun].Type.(*types.Signature)\n\tif sig == nil {\n\t\treturn false // the call is not of the form x.f()\n\t}\n\n\tres := sig.Results()\n\tif res.Len() != 2 {\n\t\treturn false // the function called does not return two values.\n\t}\n\tisPtr, named := typesinternal.ReceiverNamed(res.At(0))\n\tif !isPtr || named == nil || !typesinternal.IsTypeNamed(named, \"net/http\", \"Response\") {\n\t\treturn false // the first return type is not *http.Response.\n\t}\n\n\terrorType := types.Universe.Lookup(\"error\").Type()\n\tif !types.Identical(res.At(1).Type(), errorType) {\n\t\treturn false // the second return type is not error\n\t}\n\n\ttyp := info.Types[fun.X].Type\n\tif typ == nil {\n\t\tid, ok := fun.X.(*ast.Ident)\n\t\treturn ok && id.Name == \"http\" // function in net/http package.\n\t}\n\n\tif typesinternal.IsTypeNamed(typ, \"net/http\", \"Client\") {\n\t\treturn true // method on http.Client.\n\t}\n\tptr, ok := types.Unalias(typ).(*types.Pointer)\n\treturn ok && typesinternal.IsTypeNamed(ptr.Elem(), \"net/http\", \"Client\") // method on *http.Client.\n}\n\n// restOfBlock, given a traversal stack, finds the innermost containing\n// block and returns the suffix of its statements starting with the current\n// node, along with the number of call expressions encountered.\nfunc restOfBlock(stack []ast.Node) ([]ast.Stmt, int) {\n\tvar ncalls int\n\tfor i := len(stack) - 1; i >= 0; i-- {\n\t\tif b, ok := stack[i].(*ast.BlockStmt); ok {\n\t\t\tfor j, v := range b.List {\n\t\t\t\tif v == stack[i+1] {\n\t\t\t\t\treturn b.List[j:], ncalls\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tif _, ok := stack[i].(*ast.CallExpr); ok {\n\t\t\tncalls++\n\t\t}\n\t}\n\treturn nil, 0\n}\n\n// rootIdent finds the root identifier x in a chain of selections x.y.z, or nil if not found.\nfunc rootIdent(n ast.Node) *ast.Ident {\n\tswitch n := n.(type) {\n\tcase *ast.SelectorExpr:\n\t\treturn rootIdent(n.X)\n\tcase *ast.Ident:\n\t\treturn n\n\tdefault:\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/httpresponse/httpresponse_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage httpresponse_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/httpresponse\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, httpresponse.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/httpresponse/testdata/src/a/a.go",
    "content": "package a\n\nimport (\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc goodHTTPGet() {\n\tres, err := http.Get(\"http://foo.com\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer res.Body.Close()\n}\n\nfunc badHTTPGet() {\n\tres, err := http.Get(\"http://foo.com\")\n\tdefer res.Body.Close() // want \"using res before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc badHTTPHead() {\n\tres, err := http.Head(\"http://foo.com\")\n\tdefer res.Body.Close() // want \"using res before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc goodClientGet() {\n\tclient := http.DefaultClient\n\tres, err := client.Get(\"http://foo.com\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer res.Body.Close()\n}\n\nfunc badClientPtrGet() {\n\tclient := http.DefaultClient\n\tresp, err := client.Get(\"http://foo.com\")\n\tdefer resp.Body.Close() // want \"using resp before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc badClientGet() {\n\tclient := http.Client{}\n\tresp, err := client.Get(\"http://foo.com\")\n\tdefer resp.Body.Close() // want \"using resp before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc badClientPtrDo() {\n\tclient := http.DefaultClient\n\treq, err := http.NewRequest(\"GET\", \"http://foo.com\", nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tresp, err := client.Do(req)\n\tdefer resp.Body.Close() // want \"using resp before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc badClientDo() {\n\tvar client http.Client\n\treq, err := http.NewRequest(\"GET\", \"http://foo.com\", nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tresp, err := client.Do(req)\n\tdefer resp.Body.Close() // want \"using resp before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc goodUnwrapResp() {\n\tunwrapResp := func(resp *http.Response, err error) *http.Response {\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn resp\n\t}\n\tresp := unwrapResp(http.Get(\"https://golang.org\"))\n\t// It is ok to call defer here immediately as err has\n\t// been checked in unwrapResp (see #52661).\n\tdefer resp.Body.Close()\n}\n\nfunc badUnwrapResp() {\n\tunwrapResp := func(resp *http.Response, err error) string {\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn \"https://golang.org/\" + resp.Status\n\t}\n\tresp, err := http.Get(unwrapResp(http.Get(\"https://golang.org\")))\n\tdefer resp.Body.Close() // want \"using resp before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\ntype i66259 struct{}\n\nfunc (_ *i66259) Foo() (*int, int) { return nil, 1 }\n\nfunc issue66259() {\n\tvar f *i66259\n\tf.Foo()\n}\n"
  },
  {
    "path": "go/analysis/passes/httpresponse/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the httpresponse checker.\n\npackage typeparams\n\nimport (\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc badHTTPGet[T any](url string) {\n\tres, err := http.Get(url)\n\tdefer res.Body.Close() // want \"using res before checking for errors\"\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc mkClient[T any]() *T {\n\treturn nil\n}\n\nfunc badClientHTTPGet() {\n\tclient := mkClient[http.Client]()\n\tres, _ := client.Get(\"\")\n\tdefer res.Body.Close() // want \"using res before checking for errors\"\n}\n\n// User-defined type embedded \"http.Client\"\ntype S[P any] struct {\n\thttp.Client\n}\n\nfunc unmatchedClientTypeName(client S[string]) {\n\tres, _ := client.Get(\"\")\n\tdefer res.Body.Close() // the name of client's type doesn't match \"*http.Client\"\n}\n\n// User-defined Client type\ntype C[P any] interface {\n\tGet(url string) (resp *P, err error)\n}\n\nfunc userDefinedClientType(client C[http.Response]) {\n\tresp, _ := client.Get(\"http://foo.com\")\n\tdefer resp.Body.Close() // \"client\" is not of type \"*http.Client\"\n}\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/cmd/ifaceassert/main.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The ifaceassert command runs the ifaceassert analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/ifaceassert\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(ifaceassert.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package ifaceassert defines an Analyzer that flags\n// impossible interface-interface type assertions.\n//\n// # Analyzer ifaceassert\n//\n// ifaceassert: detect impossible interface-to-interface type assertions\n//\n// This checker flags type assertions v.(T) and corresponding type-switch cases\n// in which the static type V of v is an interface that cannot possibly implement\n// the target interface T. This occurs when V and T contain methods with the same\n// name but different signatures. Example:\n//\n//\tvar v interface {\n//\t\tRead()\n//\t}\n//\t_ = v.(io.Reader)\n//\n// The Read method in v has a different signature than the Read method in\n// io.Reader, so this assertion cannot succeed.\npackage ifaceassert\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/ifaceassert.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ifaceassert\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"ifaceassert\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"ifaceassert\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\n// assertableTo checks whether interface v can be asserted into t. It returns\n// nil on success, or the first conflicting method on failure.\nfunc assertableTo(free *typeparams.Free, v, t types.Type) *types.Func {\n\tif t == nil || v == nil {\n\t\t// not assertable to, but there is no missing method\n\t\treturn nil\n\t}\n\t// ensure that v and t are interfaces\n\tV, _ := v.Underlying().(*types.Interface)\n\tT, _ := t.Underlying().(*types.Interface)\n\tif V == nil || T == nil {\n\t\treturn nil\n\t}\n\n\t// Mitigations for interface comparisons and generics.\n\t// TODO(https://github.com/golang/go/issues/50658): Support more precise conclusion.\n\tif free.Has(V) || free.Has(T) {\n\t\treturn nil\n\t}\n\tif f, wrongType := types.MissingMethod(V, T, false); wrongType {\n\t\treturn f\n\t}\n\treturn nil\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.TypeAssertExpr)(nil),\n\t\t(*ast.TypeSwitchStmt)(nil),\n\t}\n\tvar free typeparams.Free\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tvar (\n\t\t\tassert  *ast.TypeAssertExpr // v.(T) expression\n\t\t\ttargets []ast.Expr          // interfaces T in v.(T)\n\t\t)\n\t\tswitch n := n.(type) {\n\t\tcase *ast.TypeAssertExpr:\n\t\t\t// take care of v.(type) in *ast.TypeSwitchStmt\n\t\t\tif n.Type == nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tassert = n\n\t\t\ttargets = append(targets, n.Type)\n\t\tcase *ast.TypeSwitchStmt:\n\t\t\t// retrieve type assertion from type switch's 'assign' field\n\t\t\tswitch t := n.Assign.(type) {\n\t\t\tcase *ast.ExprStmt:\n\t\t\t\tassert = t.X.(*ast.TypeAssertExpr)\n\t\t\tcase *ast.AssignStmt:\n\t\t\t\tassert = t.Rhs[0].(*ast.TypeAssertExpr)\n\t\t\t}\n\t\t\t// gather target types from case clauses\n\t\t\tfor _, c := range n.Body.List {\n\t\t\t\ttargets = append(targets, c.(*ast.CaseClause).List...)\n\t\t\t}\n\t\t}\n\t\tV := pass.TypesInfo.TypeOf(assert.X)\n\t\tfor _, target := range targets {\n\t\t\tT := pass.TypesInfo.TypeOf(target)\n\t\t\tif f := assertableTo(&free, V, T); f != nil {\n\t\t\t\tpass.Reportf(\n\t\t\t\t\ttarget.Pos(),\n\t\t\t\t\t\"impossible type assertion: no type can implement both %v and %v (conflicting types for %v method)\",\n\t\t\t\t\tV, T, f.Name(),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/ifaceassert_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ifaceassert_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/ifaceassert\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, ifaceassert.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the ifaceassert checker.\n\npackage a\n\nimport \"io\"\n\nfunc InterfaceAssertionTest() {\n\tvar (\n\t\ta io.ReadWriteSeeker\n\t\tb interface {\n\t\t\tRead()\n\t\t\tWrite()\n\t\t}\n\t)\n\t_ = a.(io.Reader)\n\t_ = a.(io.ReadWriter)\n\t_ = b.(io.Reader)  // want `^impossible type assertion: no type can implement both interface{Read\\(\\); Write\\(\\)} and io.Reader \\(conflicting types for Read method\\)$`\n\t_ = b.(interface { // want `^impossible type assertion: no type can implement both interface{Read\\(\\); Write\\(\\)} and interface{Read\\(p \\[\\]byte\\) \\(n int, err error\\)} \\(conflicting types for Read method\\)$`\n\t\tRead(p []byte) (n int, err error)\n\t})\n\n\tswitch a.(type) {\n\tcase io.ReadWriter:\n\tcase interface { // want `^impossible type assertion: no type can implement both io.ReadWriteSeeker and interface{Write\\(\\)} \\(conflicting types for Write method\\)$`\n\t\tWrite()\n\t}:\n\tdefault:\n\t}\n\n\tswitch b := b.(type) {\n\tcase io.ReadWriter, interface{ Read() }: // want `^impossible type assertion: no type can implement both interface{Read\\(\\); Write\\(\\)} and io.ReadWriter \\(conflicting types for Read method\\)$`\n\tcase io.Writer: // want `^impossible type assertion: no type can implement both interface{Read\\(\\); Write\\(\\)} and io.Writer \\(conflicting types for Write method\\)$`\n\tdefault:\n\t\t_ = b\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/ifaceassert/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"io\"\n\ntype SourceReader[Source any] interface {\n\tRead(p Source) (n int, err error)\n}\n\nfunc GenericInterfaceAssertionTest[T io.Reader]() {\n\tvar (\n\t\ta SourceReader[[]byte]\n\t\tb SourceReader[[]int]\n\t\tr io.Reader\n\t)\n\t_ = a.(io.Reader)\n\t_ = b.(io.Reader) // want `^impossible type assertion: no type can implement both typeparams.SourceReader\\[\\[\\]int\\] and io.Reader \\(conflicting types for Read method\\)$`\n\n\t_ = r.(SourceReader[[]byte])\n\t_ = r.(SourceReader[[]int]) // want `^impossible type assertion: no type can implement both io.Reader and typeparams.SourceReader\\[\\[\\]int\\] \\(conflicting types for Read method\\)$`\n\t_ = r.(T)                   // not actually an iface assertion, so checked by the type checker.\n\n\tswitch a.(type) {\n\tcase io.Reader:\n\tdefault:\n\t}\n\n\tswitch b.(type) {\n\tcase io.Reader: // want `^impossible type assertion: no type can implement both typeparams.SourceReader\\[\\[\\]int\\] and io.Reader \\(conflicting types for Read method\\)$`\n\n\tdefault:\n\t}\n}\n\n// Issue 50658: Check for type parameters in type switches.\ntype Float interface {\n\tfloat32 | float64\n}\n\ntype Doer[F Float] interface {\n\tDo() F\n}\n\nfunc Underlying[F Float](v Doer[F]) string {\n\tswitch v.(type) {\n\tcase Doer[float32]:\n\t\treturn \"float32!\"\n\tcase Doer[float64]:\n\t\treturn \"float64!\"\n\tdefault:\n\t\treturn \"<unknown>\"\n\t}\n}\n\nfunc DoIf[F Float]() {\n\t// This is a synthetic function to create a non-generic to generic assignment.\n\t// This function does not make much sense.\n\tvar v Doer[float32]\n\tif t, ok := v.(Doer[F]); ok {\n\t\tt.Do()\n\t}\n}\n\nfunc IsASwitch[F Float, U Float](v Doer[F]) bool {\n\tswitch v.(type) {\n\tcase Doer[U]:\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc IsA[F Float, U Float](v Doer[F]) bool {\n\t_, is := v.(Doer[U])\n\treturn is\n}\n\nfunc LayeredTypes[F Float]() {\n\t// This is a synthetic function cover more isParameterized cases.\n\ttype T interface {\n\t\tfoo() struct{ _ map[T][2]chan *F }\n\t}\n\ttype V interface {\n\t\tfoo() struct{ _ map[T][2]chan *float32 }\n\t}\n\tvar t T\n\tvar v V\n\tt, _ = v.(T)\n\t_ = t\n}\n\ntype X[T any] struct{}\n\nfunc (x X[T]) m(T) {}\n\nfunc InstancesOfGenericMethods() {\n\tvar x interface{ m(string) }\n\t// _ = x.(X[int])    // BAD. Not enabled as it does not type check.\n\t_ = x.(X[string]) // OK\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/cmd/inline/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The inline command applies the inliner to the specified packages of\n// Go source code. Run this command to report all fixes:\n//\n//\t$ go run ./go/analysis/passes/inline/cmd/inline packages...\n//\n// Run this command to preview the changes:\n//\n//\t$ go run ./go/analysis/passes/inline/cmd/inline -fix -diff packages...\n//\n// And run this command to apply them:\n//\n//\t$ go run ./go/analysis/passes/inline/cmd/inline -fix packages...\n//\n// This internal command is not officially supported. In the long\n// term, we plan to migrate this functionality into \"go fix\"; see Go\n// issues https//go.dev/issue/32816, 71859, 73605.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/inline\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(inline.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/inline/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage inline defines an analyzer that inlines calls to functions\nand uses of constants marked with a \"//go:fix inline\" directive.\n\n# Analyzer inline\n\ninline: apply fixes based on 'go:fix inline' comment directives\n\nThe inline analyzer inlines functions and constants that are marked for inlining.\n\n## Functions\n\nGiven a function that is marked for inlining, like this one:\n\n\t//go:fix inline\n\tfunc Square(x int) int { return Pow(x, 2) }\n\nthis analyzer will recommend that calls to the function elsewhere, in the same\nor other packages, should be inlined.\n\nInlining can be used to move off of a deprecated function:\n\n\t// Deprecated: prefer Pow(x, 2).\n\t//go:fix inline\n\tfunc Square(x int) int { return Pow(x, 2) }\n\nIt can also be used to move off of an obsolete package,\nas when the import path has changed or a higher major version is available:\n\n\tpackage pkg\n\n\timport pkg2 \"pkg/v2\"\n\n\t//go:fix inline\n\tfunc F() { pkg2.F(nil) }\n\nReplacing a call pkg.F() by pkg2.F(nil) can have no effect on the program,\nso this mechanism provides a low-risk way to update large numbers of calls.\nWe recommend, where possible, expressing the old API in terms of the new one\nto enable automatic migration.\n\nThe inliner takes care to avoid behavior changes, even subtle ones,\nsuch as changes to the order in which argument expressions are\nevaluated. When it cannot safely eliminate all parameter variables,\nit may introduce a \"binding declaration\" of the form\n\n\tvar params = args\n\nto evaluate argument expressions in the correct order and bind them to\nparameter variables. Since the resulting code transformation may be\nstylistically suboptimal, such inlinings may be disabled by specifying\nthe -inline.allow_binding_decl=false flag to the analyzer driver.\n\n(In cases where it is not safe to \"reduce\" a call—that is, to replace\na call f(x) by the body of function f, suitably substituted—the\ninliner machinery is capable of replacing f by a function literal,\nfunc(){...}(). However, the inline analyzer discards all such\n\"literalizations\" unconditionally, again on grounds of style.)\n\n## Constants\n\nGiven a constant that is marked for inlining, like this one:\n\n\t//go:fix inline\n\tconst Ptr = Pointer\n\nthis analyzer will recommend that uses of Ptr should be replaced with Pointer.\n\nAs with functions, inlining can be used to replace deprecated constants and\nconstants in obsolete packages.\n\nA constant definition can be marked for inlining only if it refers to another\nnamed constant.\n\nThe \"//go:fix inline\" comment must appear before a single const declaration on its own,\nas above; before a const declaration that is part of a group, as in this case:\n\n\tconst (\n\t   C = 1\n\t   //go:fix inline\n\t   Ptr = Pointer\n\t)\n\nor before a group, applying to every constant in the group:\n\n\t//go:fix inline\n\tconst (\n\t\tPtr = Pointer\n\t    Val = Value\n\t)\n\nThe proposal https://go.dev/issue/32816 introduces the \"//go:fix inline\" directives.\n\nYou can use this command to apply inline fixes en masse:\n\n\t$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...\n\n# Analyzer gofixdirective\n\ngofixdirective: validate uses of //go:fix comment directives\n\nThe gofixdirective analyzer checks \"//go:fix inline\" directives for correctness.\nSee the documentation for the gofix analyzer for more about \"/go:fix inline\".\n*/\npackage inline\n"
  },
  {
    "path": "go/analysis/passes/inline/inline.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strings\"\n\n\t_ \"embed\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/analysis/passes/internal/gofixdirective\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"inline\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"inline\"),\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline\",\n\tRun:  run,\n\tFactTypes: []analysis.Fact{\n\t\t(*goFixInlineFuncFact)(nil),\n\t\t(*goFixInlineConstFact)(nil),\n\t\t(*goFixInlineAliasFact)(nil),\n\t},\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n}\n\nvar (\n\tallowBindingDecl bool\n\tlazyEdits        bool\n)\n\nfunc init() {\n\tAnalyzer.Flags.BoolVar(&allowBindingDecl, \"allow_binding_decl\", false,\n\t\t\"permit inlinings that require a 'var params = args' declaration\")\n\tAnalyzer.Flags.BoolVar(&lazyEdits, \"lazy_edits\", false,\n\t\t\"compute edits lazily (only meaningful to gopls driver)\")\n}\n\n// analyzer holds the state for this analysis.\ntype analyzer struct {\n\tpass  *analysis.Pass\n\troot  inspector.Cursor\n\tindex *typeindex.Index\n\t// memoization of repeated calls for same file.\n\tfileContent map[string][]byte\n\t// memoization of fact imports (nil => no fact)\n\tinlinableFuncs   map[*types.Func]*inline.Callee\n\tinlinableConsts  map[*types.Const]*goFixInlineConstFact\n\tinlinableAliases map[*types.TypeName]*goFixInlineAliasFact\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\ta := &analyzer{\n\t\tpass:             pass,\n\t\troot:             pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root(),\n\t\tindex:            pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index),\n\t\tfileContent:      make(map[string][]byte),\n\t\tinlinableFuncs:   make(map[*types.Func]*inline.Callee),\n\t\tinlinableConsts:  make(map[*types.Const]*goFixInlineConstFact),\n\t\tinlinableAliases: make(map[*types.TypeName]*goFixInlineAliasFact),\n\t}\n\tgofixdirective.Find(pass, a.root, a)\n\ta.inline()\n\treturn nil, nil\n}\n\n// HandleFunc exports a fact for functions marked with go:fix.\nfunc (a *analyzer) HandleFunc(decl *ast.FuncDecl) {\n\tcontent, err := a.readFile(decl)\n\tif err != nil {\n\t\ta.pass.Reportf(decl.Doc.Pos(), \"invalid inlining candidate: cannot read source file: %v\", err)\n\t\treturn\n\t}\n\tcallee, err := inline.AnalyzeCallee(discard, a.pass.Fset, a.pass.Pkg, a.pass.TypesInfo, decl, content)\n\tif err != nil {\n\t\ta.pass.Reportf(decl.Doc.Pos(), \"invalid inlining candidate: %v\", err)\n\t\treturn\n\t}\n\tfn := a.pass.TypesInfo.Defs[decl.Name].(*types.Func)\n\ta.pass.ExportObjectFact(fn, &goFixInlineFuncFact{callee})\n\ta.inlinableFuncs[fn] = callee\n}\n\n// HandleAlias exports a fact for aliases marked with go:fix.\nfunc (a *analyzer) HandleAlias(spec *ast.TypeSpec) {\n\t// Remember that this is an inlinable alias.\n\ttyp := &goFixInlineAliasFact{}\n\tlhs := a.pass.TypesInfo.Defs[spec.Name].(*types.TypeName)\n\ta.inlinableAliases[lhs] = typ\n\t// Create a fact only if the LHS is exported and defined at top level.\n\t// We create a fact even if the RHS is non-exported,\n\t// so we can warn about uses in other packages.\n\tif lhs.Exported() && typesinternal.IsPackageLevel(lhs) {\n\t\ta.pass.ExportObjectFact(lhs, typ)\n\t}\n}\n\n// HandleConst exports a fact for constants marked with go:fix.\nfunc (a *analyzer) HandleConst(nameIdent, rhsIdent *ast.Ident) {\n\tlhs := a.pass.TypesInfo.Defs[nameIdent].(*types.Const)\n\trhs := a.pass.TypesInfo.Uses[rhsIdent].(*types.Const) // must be so in a well-typed program\n\tcon := &goFixInlineConstFact{\n\t\tRHSName:    rhs.Name(),\n\t\tRHSPkgName: rhs.Pkg().Name(),\n\t\tRHSPkgPath: rhs.Pkg().Path(),\n\t}\n\tif rhs.Pkg() == a.pass.Pkg {\n\t\tcon.rhsObj = rhs\n\t}\n\ta.inlinableConsts[lhs] = con\n\t// Create a fact only if the LHS is exported and defined at top level.\n\t// We create a fact even if the RHS is non-exported,\n\t// so we can warn about uses in other packages.\n\tif lhs.Exported() && typesinternal.IsPackageLevel(lhs) {\n\t\ta.pass.ExportObjectFact(lhs, con)\n\t}\n}\n\n// inline inlines each static call to an inlinable function\n// and each reference to an inlinable constant or type alias.\nfunc (a *analyzer) inline() {\n\tfor cur := range a.root.Preorder((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.CallExpr:\n\t\t\ta.inlineCall(n, cur)\n\n\t\tcase *ast.Ident:\n\t\t\tswitch t := a.pass.TypesInfo.Uses[n].(type) {\n\t\t\tcase *types.TypeName:\n\t\t\t\ta.inlineAlias(t, cur)\n\t\t\tcase *types.Const:\n\t\t\t\ta.inlineConst(t, cur)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// If call is a call to an inlinable func, suggest inlining its use at cur.\nfunc (a *analyzer) inlineCall(call *ast.CallExpr, cur inspector.Cursor) {\n\tif fn := typeutil.StaticCallee(a.pass.TypesInfo, call); fn != nil {\n\t\t// Inlinable?\n\t\tcallee, ok := a.inlinableFuncs[fn]\n\t\tif !ok {\n\t\t\tvar fact goFixInlineFuncFact\n\t\t\tif a.pass.ImportObjectFact(fn, &fact) {\n\t\t\t\tcallee = fact.Callee\n\t\t\t\ta.inlinableFuncs[fn] = callee\n\t\t\t}\n\t\t}\n\t\tif callee == nil {\n\t\t\treturn // nope\n\t\t}\n\n\t\tif a.withinTestOf(cur, fn) {\n\t\t\treturn // don't inline a function from within its own test\n\t\t}\n\n\t\t// Compute the edits.\n\t\t//\n\t\t// Ordinarily the analyzer reports a fix containing\n\t\t// edits. However, the algorithm is somewhat expensive\n\t\t// (unnecessarily so: see go.dev/issue/75773) so\n\t\t// to reduce costs in gopls, we omit the edits,\n\t\t// meaning that gopls must compute them on demand\n\t\t// (based on the Diagnostic.Category) when they are\n\t\t// requested via a code action.\n\t\t//\n\t\t// This does mean that the following categories of\n\t\t// caller-dependent obstacles to inlining will be\n\t\t// reported when the gopls user requests the fix,\n\t\t// rather than by quietly suppressing the diagnostic:\n\t\t// - shadowing problems\n\t\t// - callee imports inaccessible \"internal\" packages\n\t\t// - callee refers to nonexported symbols\n\t\t// - callee uses too-new Go features\n\t\t// - inlining call from a cgo file\n\t\tvar edits []analysis.TextEdit\n\t\tif !lazyEdits {\n\t\t\t// Inline the call.\n\t\t\tcaller := &inline.Caller{\n\t\t\t\tFset:  a.pass.Fset,\n\t\t\t\tTypes: a.pass.Pkg,\n\t\t\t\tInfo:  a.pass.TypesInfo,\n\t\t\t\tFile:  astutil.EnclosingFile(cur),\n\t\t\t\tCall:  call,\n\t\t\t\tCountUses: func(pkgname *types.PkgName) int {\n\t\t\t\t\treturn moreiters.Len(a.index.Uses(pkgname))\n\t\t\t\t},\n\t\t\t}\n\t\t\tres, err := inline.Inline(caller, callee, &inline.Options{Logf: discard})\n\t\t\tif err != nil {\n\t\t\t\ta.pass.Reportf(call.Lparen, \"%v\", err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif res.Literalized {\n\t\t\t\t// Users are not fond of inlinings that literalize\n\t\t\t\t// f(x) to func() { ... }(), so avoid them.\n\t\t\t\t//\n\t\t\t\t// (Unfortunately the inliner is very timid,\n\t\t\t\t// and often literalizes when it cannot prove that\n\t\t\t\t// reducing the call is safe; the user of this tool\n\t\t\t\t// has no indication of what the problem is.)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif res.BindingDecl && !allowBindingDecl {\n\t\t\t\t// When applying fix en masse, users are similarly\n\t\t\t\t// unenthusiastic about inlinings that cannot\n\t\t\t\t// entirely eliminate the parameters and\n\t\t\t\t// insert a 'var params = args' declaration.\n\t\t\t\t// The flag allows them to decline such fixes.\n\t\t\t\treturn\n\t\t\t}\n\t\t\tedits = res.Edits\n\t\t}\n\n\t\ta.pass.Report(analysis.Diagnostic{\n\t\t\tPos:      call.Pos(),\n\t\t\tEnd:      call.End(),\n\t\t\tMessage:  fmt.Sprintf(\"Call of %v should be inlined\", callee),\n\t\t\tCategory: \"inline_call\", // keep consistent with gopls/internal/golang.fixInlineCall\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   fmt.Sprintf(\"Inline call of %v\", callee),\n\t\t\t\tTextEdits: edits, // within gopls, this is nil => compute fix's edits lazily\n\t\t\t}},\n\t\t})\n\t}\n}\n\n// withinTestOf reports whether cur is within a dedicated test\n// function for the inlinable target function.\n// A call within its dedicated test should not be inlined.\nfunc (a *analyzer) withinTestOf(cur inspector.Cursor, target *types.Func) bool {\n\tcurFuncDecl, ok := moreiters.First(cur.Enclosing((*ast.FuncDecl)(nil)))\n\tif !ok {\n\t\treturn false // not in a function\n\t}\n\tfuncDecl := curFuncDecl.Node().(*ast.FuncDecl)\n\tif funcDecl.Recv != nil {\n\t\treturn false // not a test func\n\t}\n\tif strings.TrimSuffix(a.pass.Pkg.Path(), \"_test\") != target.Pkg().Path() {\n\t\treturn false // different package\n\t}\n\tif !strings.HasSuffix(a.pass.Fset.File(funcDecl.Pos()).Name(), \"_test.go\") {\n\t\treturn false // not a test file\n\t}\n\n\t// Computed expected SYMBOL portion of \"TestSYMBOL_comment\"\n\t// for the target symbol.\n\tsymbol := target.Name()\n\tif recv := target.Signature().Recv(); recv != nil {\n\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\tsymbol = named.Obj().Name() + \"_\" + symbol\n\t}\n\n\t// TODO(adonovan): use a proper Test function parser.\n\tfname := funcDecl.Name.Name\n\tfor _, pre := range []string{\"Test\", \"Example\", \"Bench\"} {\n\t\tif fname == pre+symbol || strings.HasPrefix(fname, pre+symbol+\"_\") {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// If tn is the TypeName of an inlinable alias, suggest inlining its use at cur.\nfunc (a *analyzer) inlineAlias(tn *types.TypeName, curId inspector.Cursor) {\n\tinalias, ok := a.inlinableAliases[tn]\n\tif !ok {\n\t\tvar fact goFixInlineAliasFact\n\t\tif a.pass.ImportObjectFact(tn, &fact) {\n\t\t\tinalias = &fact\n\t\t\ta.inlinableAliases[tn] = inalias\n\t\t}\n\t}\n\tif inalias == nil {\n\t\treturn // nope\n\t}\n\n\talias := tn.Type().(*types.Alias)\n\t// Remember the names of the alias's type params. When we check for shadowing\n\t// later, we'll ignore these because they won't appear in the replacement text.\n\ttypeParamNames := map[*types.TypeName]bool{}\n\tfor tp := range alias.TypeParams().TypeParams() {\n\t\ttypeParamNames[tp.Obj()] = true\n\t}\n\trhs := alias.Rhs()\n\tcurPath := a.pass.Pkg.Path()\n\tcurFile := astutil.EnclosingFile(curId)\n\tid := curId.Node().(*ast.Ident)\n\n\t// Find the complete identifier, which may take any of these forms:\n\t//       Id\n\t//       Id[T]\n\t//       Id[K, V]\n\t//   pkg.Id\n\t//   pkg.Id[T]\n\t//   pkg.Id[K, V]\n\tvar expr ast.Expr = id\n\tif curId.ParentEdgeKind() == edge.SelectorExpr_Sel {\n\t\tcurId = curId.Parent()\n\t\texpr = curId.Node().(ast.Expr)\n\t}\n\t// If expr is part of an IndexExpr or IndexListExpr, we'll need that node.\n\t// Given C[int], TypeOf(C) is generic but TypeOf(C[int]) is instantiated.\n\tswitch curId.ParentEdgeKind() {\n\tcase edge.IndexExpr_X:\n\t\texpr = curId.Parent().Node().(*ast.IndexExpr)\n\tcase edge.IndexListExpr_X:\n\t\texpr = curId.Parent().Node().(*ast.IndexListExpr)\n\t}\n\tt := a.pass.TypesInfo.TypeOf(expr).(*types.Alias) // type of entire identifier\n\tif targs := t.TypeArgs(); targs.Len() > 0 {\n\t\t// Instantiate the alias with the type args from this use.\n\t\t// For example, given type A = M[K, V], compute the type of the use\n\t\t// A[int, Foo] as M[int, Foo].\n\t\t// Don't validate instantiation: it can't panic unless we have a bug,\n\t\t// in which case seeing the stack trace via telemetry would be helpful.\n\t\tinstAlias, _ := types.Instantiate(nil, alias, slices.Collect(targs.Types()), false)\n\t\trhs = instAlias.(*types.Alias).Rhs()\n\t}\n\n\t// We have an identifier A here (n), possibly qualified by a package\n\t// identifier (sel.n), and an inlinable \"type A = rhs\" elsewhere.\n\t//\n\t// We can replace A with rhs if no name in rhs is shadowed at n's position,\n\t// and every package in rhs is importable by the current package.\n\tvar (\n\t\timportPrefixes = map[string]string{curPath: \"\"} // from pkg path to prefix\n\t\tedits          []analysis.TextEdit\n\t)\n\tfor _, tn := range typenames(rhs) {\n\t\t// Ignore the type parameters of the alias: they won't appear in the result.\n\t\tif typeParamNames[tn] {\n\t\t\tcontinue\n\t\t}\n\t\tvar pkgPath, pkgName string\n\t\tif pkg := tn.Pkg(); pkg != nil {\n\t\t\tpkgPath = pkg.Path()\n\t\t\tpkgName = pkg.Name()\n\t\t}\n\t\tif pkgPath == \"\" || pkgPath == curPath {\n\t\t\t// The name is in the current package or the universe scope, so no import\n\t\t\t// is required. Check that it is not shadowed (that is, that the type\n\t\t\t// it refers to in rhs is the same one it refers to at n).\n\t\t\tscope := a.pass.TypesInfo.Scopes[curFile].Innermost(id.Pos()) // n's scope\n\t\t\t_, obj := scope.LookupParent(tn.Name(), id.Pos())             // what qn.name means in n's scope\n\t\t\tif obj != tn {\n\t\t\t\treturn\n\t\t\t}\n\t\t} else if !packagepath.CanImport(a.pass.Pkg.Path(), pkgPath) {\n\t\t\t// If this package can't see the package of this part of rhs, we can't inline.\n\t\t\treturn\n\t\t} else if _, ok := importPrefixes[pkgPath]; !ok {\n\t\t\t// Use AddImport to add pkgPath if it's not there already. Associate the prefix it assigns\n\t\t\t// with the prefix it assigns\n\t\t\t// with the package path for use by the TypeString qualifier below.\n\t\t\tprefix, eds := refactor.AddImport(\n\t\t\t\ta.pass.TypesInfo, curFile, pkgName, pkgPath, tn.Name(), id.Pos())\n\t\t\timportPrefixes[pkgPath] = strings.TrimSuffix(prefix, \".\")\n\t\t\tedits = append(edits, eds...)\n\t\t}\n\t}\n\n\t// To get the replacement text, render the alias RHS using the package prefixes\n\t// we assigned above.\n\tnewText := types.TypeString(rhs, func(p *types.Package) string {\n\t\tif p == a.pass.Pkg {\n\t\t\treturn \"\"\n\t\t}\n\t\tif prefix, ok := importPrefixes[p.Path()]; ok {\n\t\t\treturn prefix\n\t\t}\n\t\tpanic(fmt.Sprintf(\"in %q, package path %q has no import prefix\", rhs, p.Path()))\n\t})\n\ta.reportInline(\"type alias\", \"Type alias\", expr, edits, newText)\n}\n\n// typenames returns the TypeNames for types within t (including t itself) that have\n// them: basic types, named types and alias types.\n// The same name may appear more than once.\nfunc typenames(t types.Type) []*types.TypeName {\n\tvar tns []*types.TypeName\n\n\tvar visit func(types.Type)\n\tvisit = func(t types.Type) {\n\t\tif hasName, ok := t.(interface{ Obj() *types.TypeName }); ok {\n\t\t\ttns = append(tns, hasName.Obj())\n\t\t}\n\t\tswitch t := t.(type) {\n\t\tcase *types.Basic:\n\t\t\ttns = append(tns, types.Universe.Lookup(t.Name()).(*types.TypeName))\n\t\tcase *types.Named:\n\t\t\tfor t := range t.TypeArgs().Types() {\n\t\t\t\tvisit(t)\n\t\t\t}\n\t\tcase *types.Alias:\n\t\t\tfor t := range t.TypeArgs().Types() {\n\t\t\t\tvisit(t)\n\t\t\t}\n\t\tcase *types.TypeParam:\n\t\t\ttns = append(tns, t.Obj())\n\t\tcase *types.Pointer:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Slice:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Array:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Chan:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Map:\n\t\t\tvisit(t.Key())\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Struct:\n\t\t\tfor field := range t.Fields() {\n\t\t\t\tvisit(field.Type())\n\t\t\t}\n\t\tcase *types.Signature:\n\t\t\t// Ignore the receiver: although it may be present, it has no meaning\n\t\t\t// in a type expression.\n\t\t\t// Ditto for receiver type params.\n\t\t\t// Also, function type params cannot appear in a type expression.\n\t\t\tif t.TypeParams() != nil {\n\t\t\t\tpanic(\"Signature.TypeParams in type expression\")\n\t\t\t}\n\t\t\tvisit(t.Params())\n\t\t\tvisit(t.Results())\n\t\tcase *types.Interface:\n\t\t\tfor etyp := range t.EmbeddedTypes() {\n\t\t\t\tvisit(etyp)\n\t\t\t}\n\t\t\tfor method := range t.ExplicitMethods() {\n\t\t\t\tvisit(method.Type())\n\t\t\t}\n\t\tcase *types.Tuple:\n\t\t\tfor v := range t.Variables() {\n\t\t\t\tvisit(v.Type())\n\t\t\t}\n\t\tcase *types.Union:\n\t\t\tpanic(\"Union in type expression\")\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unknown type %T\", t))\n\t\t}\n\t}\n\n\tvisit(t)\n\n\treturn tns\n}\n\n// If con is an inlinable constant, suggest inlining its use at cur.\nfunc (a *analyzer) inlineConst(con *types.Const, cur inspector.Cursor) {\n\tincon, ok := a.inlinableConsts[con]\n\tif !ok {\n\t\tvar fact goFixInlineConstFact\n\t\tif a.pass.ImportObjectFact(con, &fact) {\n\t\t\tincon = &fact\n\t\t\ta.inlinableConsts[con] = incon\n\t\t}\n\t}\n\tif incon == nil {\n\t\treturn // nope\n\t}\n\n\t// If n is qualified by a package identifier, we'll need the full selector expression.\n\tcurFile := astutil.EnclosingFile(cur)\n\tn := cur.Node().(*ast.Ident)\n\n\t// We have an identifier A here (n), possibly qualified by a package identifier (sel.X,\n\t// where sel is the parent of n), // and an inlinable \"const A = B\" elsewhere (incon).\n\t// Consider replacing A with B.\n\n\t// Check that the expression we are inlining (B) means the same thing\n\t// (refers to the same object) in n's scope as it does in A's scope.\n\t// If the RHS is not in the current package, AddImport will handle\n\t// shadowing, so we only need to worry about when both expressions\n\t// are in the current package.\n\tif a.pass.Pkg.Path() == incon.RHSPkgPath {\n\t\t// incon.rhsObj is the object referred to by B in the definition of A.\n\t\tscope := a.pass.TypesInfo.Scopes[curFile].Innermost(n.Pos()) // n's scope\n\t\t_, obj := scope.LookupParent(incon.RHSName, n.Pos())         // what \"B\" means in n's scope\n\t\tif obj == nil {\n\t\t\t// Should be impossible: if code at n can refer to the LHS,\n\t\t\t// it can refer to the RHS.\n\t\t\tpanic(fmt.Sprintf(\"no object for inlinable const %s RHS %s\", n.Name, incon.RHSName))\n\t\t}\n\t\tif obj != incon.rhsObj {\n\t\t\t// \"B\" means something different here than at the inlinable const's scope.\n\t\t\treturn\n\t\t}\n\t} else if !packagepath.CanImport(a.pass.Pkg.Path(), incon.RHSPkgPath) {\n\t\t// If this package can't see the RHS's package, we can't inline.\n\t\treturn\n\t}\n\tvar (\n\t\timportPrefix string\n\t\tedits        []analysis.TextEdit\n\t)\n\tif incon.RHSPkgPath != a.pass.Pkg.Path() {\n\t\timportPrefix, edits = refactor.AddImport(\n\t\t\ta.pass.TypesInfo, curFile, incon.RHSPkgName, incon.RHSPkgPath, incon.RHSName, n.Pos())\n\t}\n\t// If n is qualified by a package identifier, we'll need the full selector expression.\n\tvar expr ast.Expr = n\n\tif cur.ParentEdgeKind() == edge.SelectorExpr_Sel {\n\t\texpr = cur.Parent().Node().(ast.Expr)\n\t}\n\ta.reportInline(\"constant\", \"Constant\", expr, edits, importPrefix+incon.RHSName)\n}\n\n// reportInline reports a diagnostic for fixing an inlinable name.\nfunc (a *analyzer) reportInline(kind, capKind string, ident ast.Expr, edits []analysis.TextEdit, newText string) {\n\tedits = append(edits, analysis.TextEdit{\n\t\tPos:     ident.Pos(),\n\t\tEnd:     ident.End(),\n\t\tNewText: []byte(newText),\n\t})\n\tname := astutil.Format(a.pass.Fset, ident)\n\ta.pass.Report(analysis.Diagnostic{\n\t\tPos:     ident.Pos(),\n\t\tEnd:     ident.End(),\n\t\tMessage: fmt.Sprintf(\"%s %s should be inlined\", capKind, name),\n\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\tMessage:   fmt.Sprintf(\"Inline %s %s\", kind, name),\n\t\t\tTextEdits: edits,\n\t\t}},\n\t})\n}\n\nfunc (a *analyzer) readFile(node ast.Node) ([]byte, error) {\n\tfilename := a.pass.Fset.File(node.Pos()).Name()\n\tcontent, ok := a.fileContent[filename]\n\tif !ok {\n\t\tvar err error\n\t\tcontent, err = a.pass.ReadFile(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ta.fileContent[filename] = content\n\t}\n\treturn content, nil\n}\n\n// A goFixInlineFuncFact is exported for each function marked \"//go:fix inline\".\n// It holds information about the callee to support inlining.\ntype goFixInlineFuncFact struct{ Callee *inline.Callee }\n\nfunc (f *goFixInlineFuncFact) String() string { return \"goFixInline \" + f.Callee.String() }\nfunc (*goFixInlineFuncFact) AFact()           {}\n\n// A goFixInlineConstFact is exported for each constant marked \"//go:fix inline\".\n// It holds information about an inlinable constant. Gob-serializable.\ntype goFixInlineConstFact struct {\n\t// Information about \"const LHSName = RHSName\".\n\tRHSName    string\n\tRHSPkgPath string\n\tRHSPkgName string\n\trhsObj     types.Object // for current package\n}\n\nfunc (c *goFixInlineConstFact) String() string {\n\treturn fmt.Sprintf(\"goFixInline const %q.%s\", c.RHSPkgPath, c.RHSName)\n}\n\nfunc (*goFixInlineConstFact) AFact() {}\n\n// A goFixInlineAliasFact is exported for each type alias marked \"//go:fix inline\".\n// It holds no information; its mere existence demonstrates that an alias is inlinable.\ntype goFixInlineAliasFact struct{}\n\nfunc (c *goFixInlineAliasFact) String() string { return \"goFixInline alias\" }\nfunc (*goFixInlineAliasFact) AFact()           {}\n\nfunc discard(string, ...any) {}\n"
  },
  {
    "path": "go/analysis/passes/inline/inline_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"testing\"\n\n\tgocmp \"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc TestAnalyzer(t *testing.T) {\n\tif testenv.Go1Point() < 24 {\n\t\ttestenv.NeedsGoExperiment(t, \"aliastypeparams\")\n\t}\n\tanalysistest.RunWithSuggestedFixes(t, analysistest.TestData(), Analyzer, \"a\", \"b\", \"rmimport\")\n\n\tdir1 := testfiles.ExtractTxtarFileToTmp(t, \"testdata/src/issue76190.txtar\")\n\tanalysistest.RunWithSuggestedFixes(t, dir1, Analyzer, \"example.com/a\", \"example.com/b\")\n\n\tdir2 := testfiles.ExtractTxtarFileToTmp(t, \"testdata/src/issue77610.txtar\")\n\tanalysistest.RunWithSuggestedFixes(t, dir2, Analyzer,\n\t\t\"example.com/a\",\n\t\t\"example.com/b\",\n\t\t\"example.com/c\",\n\t\t\"example.com/d\",\n\t)\n}\n\nfunc TestAllowBindingDeclFlag(t *testing.T) {\n\tsaved := allowBindingDecl\n\tdefer func() { allowBindingDecl = saved }()\n\n\trun := func(allow bool) {\n\t\tname := fmt.Sprintf(\"binding_%v\", allow)\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tallowBindingDecl = allow\n\t\t\tanalysistest.RunWithSuggestedFixes(t, analysistest.TestData(), Analyzer, name)\n\t\t})\n\t}\n\trun(true)  // testdata/src/binding_true\n\trun(false) // testdata/src/binding_false\n}\n\nfunc TestTypesWithNames(t *testing.T) {\n\t// Test setup inspired by internal/analysis/addimport_test.go.\n\ttestenv.NeedsDefaultImporter(t)\n\n\tfor _, test := range []struct {\n\t\ttypeExpr string\n\t\twant     []string\n\t}{\n\t\t{\n\t\t\t\"int\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t\"*int\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t\"[]*int\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t\"[2]int\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t// go/types does not expose the length expression.\n\t\t\t\"[unsafe.Sizeof(uint(1))]int\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t\"map[string]int\",\n\t\t\t[]string{\"int\", \"string\"},\n\t\t},\n\t\t{\n\t\t\t\"map[int]struct{x, y int}\",\n\t\t\t[]string{\"int\"},\n\t\t},\n\t\t{\n\t\t\t\"T\",\n\t\t\t[]string{\"a.T\"},\n\t\t},\n\t\t{\n\t\t\t\"iter.Seq[int]\",\n\t\t\t[]string{\"int\", \"iter.Seq\"},\n\t\t},\n\t\t{\n\t\t\t\"io.Reader\",\n\t\t\t[]string{\"io.Reader\"},\n\t\t},\n\t\t{\n\t\t\t\"map[*io.Writer]map[T]A\",\n\t\t\t[]string{\"a.A\", \"a.T\", \"io.Writer\"},\n\t\t},\n\t\t{\n\t\t\t\"func(int, int) (bool, error)\",\n\t\t\t[]string{\"bool\", \"error\", \"int\"},\n\t\t},\n\t\t{\n\t\t\t\"func(int, ...string) (T, *T, error)\",\n\t\t\t[]string{\"a.T\", \"error\", \"int\", \"string\"},\n\t\t},\n\t\t{\n\t\t\t\"func(iter.Seq[int])\",\n\t\t\t[]string{\"int\", \"iter.Seq\"},\n\t\t},\n\t\t{\n\t\t\t\"struct { a int; b bool}\",\n\t\t\t[]string{\"bool\", \"int\"},\n\t\t},\n\t\t{\n\t\t\t\"struct { io.Reader; a int}\",\n\t\t\t[]string{\"int\", \"io.Reader\"},\n\t\t},\n\t\t{\n\t\t\t\"map[*string]struct{x chan int; y [2]bool}\",\n\t\t\t[]string{\"bool\", \"int\", \"string\"},\n\t\t},\n\t\t{\n\t\t\t\"interface {F(int) bool}\",\n\t\t\t[]string{\"bool\", \"int\"},\n\t\t},\n\t\t{\n\t\t\t\"interface {io.Reader; F(int) bool}\",\n\t\t\t[]string{\"bool\", \"int\", \"io.Reader\"},\n\t\t},\n\t\t{\n\t\t\t\"G\", // a type parameter of the function\n\t\t\t[]string{\"a.G\"},\n\t\t},\n\t} {\n\t\tsrc := `\n\t\t\tpackage a\n\t\t\timport (\"io\"; \"iter\"; \"unsafe\")\n\t\t\tfunc _(io.Reader, iter.Seq[int]) uintptr {return unsafe.Sizeof(1)}\n\t\t\ttype T int\n\t\t\ttype A = T\n\n\t\t\tfunc F[G any]() {\n\t\t\t\tvar V ` + test.typeExpr + `\n\t\t\t\t_ = V\n\t\t\t}`\n\n\t\t// parse\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"a.go\", src, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: %v\", test.typeExpr, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// type-check\n\t\tinfo := &types.Info{\n\t\t\tTypes:     make(map[ast.Expr]types.TypeAndValue),\n\t\t\tScopes:    make(map[ast.Node]*types.Scope),\n\t\t\tDefs:      make(map[*ast.Ident]types.Object),\n\t\t\tImplicits: make(map[ast.Node]types.Object),\n\t\t}\n\t\tconf := &types.Config{\n\t\t\tError:    func(err error) { t.Fatalf(\"%s: %v\", test.typeExpr, err) },\n\t\t\tImporter: importer.Default(),\n\t\t}\n\t\tpkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: %v\", test.typeExpr, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Look at V's type.\n\t\ttyp := pkg.Scope().Lookup(\"F\").(*types.Func).\n\t\t\tScope().Lookup(\"V\").(*types.Var).Type()\n\t\ttns := typenames(typ)\n\t\t// Sort names for comparison.\n\t\tvar got []string\n\t\tfor _, tn := range tns {\n\t\t\tvar prefix string\n\t\t\tif p := tn.Pkg(); p != nil && p.Path() != \"\" {\n\t\t\t\tprefix = p.Path() + \".\"\n\t\t\t}\n\t\t\tgot = append(got, prefix+tn.Name())\n\t\t}\n\t\tslices.Sort(got)\n\t\tgot = slices.Compact(got)\n\n\t\tif diff := gocmp.Diff(test.want, got); diff != \"\" {\n\t\t\tt.Errorf(\"%s: mismatch (-want, +got):\\n%s\", test.typeExpr, diff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/issue77844_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\nimport (\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"testing\"\n)\n\nfunc TestIssue77844(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, \"testdata/src/issue77844.txtar\")\n\tanalysistest.Run(t, dir, Analyzer, \"example.com/main\")\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/a/a.go",
    "content": "package a\n\nimport \"a/internal\"\n\n// Functions.\n\nfunc f() {\n\tOne() // want `Call of a.One should be inlined`\n\n\tnew(T).Two() // want `Call of \\(a.T\\).Two should be inlined`\n}\n\ntype T struct{}\n\n//go:fix inline\nfunc One() int { return one } // want One:`goFixInline a.One`\n\nconst one = 1\n\n//go:fix inline\nfunc (T) Two() int { return 2 } // want Two:`goFixInline \\(a.T\\).Two`\n\n// Constants.\n\nconst Uno = 1\n\n//go:fix inline\nconst In1 = Uno // want In1: `goFixInline const \"a\".Uno`\n\nconst (\n\tno1 = one\n\n\t//go:fix inline\n\tIn2 = one // want In2: `goFixInline const \"a\".one`\n)\n\n//go:fix inline\nconst (\n\tin3  = one\n\tin4  = one\n\tbad1 = 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n)\n\n//go:fix inline\nconst in5,\n\tin6,\n\tbad2 = one, one,\n\tone + 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n// Make sure we don't crash on iota consts, but still process the whole decl.\n//\n//go:fix inline\nconst (\n\ta = iota // want `invalid //go:fix inline directive: const value is iota`\n\tb\n\tin7 = one\n)\n\nfunc _() {\n\tx := In1 // want `Constant In1 should be inlined`\n\tx = In2  // want `Constant In2 should be inlined`\n\tx = in3  // want `Constant in3 should be inlined`\n\tx = in4  // want `Constant in4 should be inlined`\n\tx = in5  // want `Constant in5 should be inlined`\n\tx = in6  // want `Constant in6 should be inlined`\n\tx = in7  // want `Constant in7 should be inlined`\n\tx = no1\n\t_ = x\n\n\tin1 := 1 // don't inline lvalues\n\t_ = in1\n}\n\nconst (\n\tx = 1\n\t//go:fix inline\n\tin8 = x\n)\n\n//go:fix inline\nconst D = internal.D // want D: `goFixInline const \"a/internal\".D`\n\nfunc shadow() {\n\tvar x int // shadows x at package scope\n\n\t//go:fix inline\n\tconst a = iota // want `invalid //go:fix inline directive: const value is iota`\n\n\tconst iota = 2\n\t// Below this point, iota is an ordinary constant.\n\n\t//go:fix inline\n\tconst b = iota\n\n\tx = a // a is defined with the predeclared iota, so it cannot be inlined\n\tx = b // want `Constant b should be inlined`\n\n\t// Don't offer to inline in8, because the result, \"x\", would mean something different\n\t// in this scope than it does in the scope where in8 is defined.\n\tx = in8\n\n\t_ = x\n}\n\n// Type aliases\n\n//go:fix inline\ntype A = T // want A: `goFixInline alias`\n\nvar _ A // want `Type alias A should be inlined`\n\n//go:fix inline\ntype AA = // want AA: `goFixInline alias`\nA         // want `Type alias A should be inlined`\n\nvar _ AA // want `Type alias AA should be inlined`\n\n//go:fix inline\ntype (\n\tB = []T                 // want B: `goFixInline alias`\n\tC = map[*string][]error // want C: `goFixInline alias`\n)\n\nvar _ B // want `Type alias B should be inlined`\nvar _ C // want `Type alias C should be inlined`\n\n//go:fix inline\ntype E = map[[Uno]string][]*T // want `invalid //go:fix inline directive: array types not supported`\n\nvar _ E // nothing should happen here\n\n// literal array lengths are OK\n//\n//go:fix inline\ntype EL = map[[2]string][]*T // want EL: `goFixInline alias`\n\nvar _ EL // want `Type alias EL should be inlined`\n\n//go:fix inline\ntype F = map[internal.T]T // want F: `goFixInline alias`\n\nvar _ F // want `Type alias F should be inlined`\n\n//go:fix inline\ntype G = []chan *internal.T // want G: `goFixInline alias`\n\nvar _ G // want `Type alias G should be inlined`\n\n// local shadowing\nfunc _() {\n\ttype string = int\n\tconst T = 1\n\n\tvar _ B // nope: B's RHS contains T, which is shadowed\n\tvar _ C // nope: C's RHS contains string, which is shadowed\n}\n\n// local inlining\nfunc _[P any]() {\n\tconst a = 1\n\t//go:fix inline\n\tconst b = a\n\n\tx := b // want `Constant b should be inlined`\n\n\t//go:fix inline\n\ttype u = []P\n\n\tvar y u // want `Type alias u should be inlined`\n\n\t_ = x\n\t_ = y\n}\n\n// generic type aliases\n\n//go:fix inline\ntype (\n\tMapset[T comparable] = map[T]bool // want Mapset: `goFixInline alias`\n\tPair[X, Y any]       = struct {   // want Pair: `goFixInline alias`\n\t\tX X\n\t\tY Y\n\t}\n)\n\nvar _ Mapset[int] // want `Type alias Mapset\\[int\\] should be inlined`\n\nvar _ Pair[T, string] // want `Type alias Pair\\[T, string\\] should be inlined`\n\nfunc _[V any]() {\n\t//go:fix inline\n\ttype M[K comparable] = map[K]V\n\n\tvar _ M[int] // want `Type alias M\\[int\\] should be inlined`\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/a/a.go.golden",
    "content": "package a\n\nimport \"a/internal\"\n\n// Functions.\n\nfunc f() {\n\t_ = one // want `Call of a.One should be inlined`\n\n\t_ = 2 // want `Call of \\(a.T\\).Two should be inlined`\n}\n\ntype T struct{}\n\n//go:fix inline\nfunc One() int { return one } // want One:`goFixInline a.One`\n\nconst one = 1\n\n//go:fix inline\nfunc (T) Two() int { return 2 } // want Two:`goFixInline \\(a.T\\).Two`\n\n// Constants.\n\nconst Uno = 1\n\n//go:fix inline\nconst In1 = Uno // want In1: `goFixInline const \"a\".Uno`\n\nconst (\n\tno1 = one\n\n\t//go:fix inline\n\tIn2 = one // want In2: `goFixInline const \"a\".one`\n)\n\n//go:fix inline\nconst (\n\tin3  = one\n\tin4  = one\n\tbad1 = 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n)\n\n//go:fix inline\nconst in5,\n\tin6,\n\tbad2 = one, one,\n\tone + 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n// Make sure we don't crash on iota consts, but still process the whole decl.\n//\n//go:fix inline\nconst (\n\ta = iota // want `invalid //go:fix inline directive: const value is iota`\n\tb\n\tin7 = one\n)\n\nfunc _() {\n\tx := Uno // want `Constant In1 should be inlined`\n\tx = one  // want `Constant In2 should be inlined`\n\tx = one  // want `Constant in3 should be inlined`\n\tx = one  // want `Constant in4 should be inlined`\n\tx = one  // want `Constant in5 should be inlined`\n\tx = one  // want `Constant in6 should be inlined`\n\tx = one  // want `Constant in7 should be inlined`\n\tx = no1\n\t_ = x\n\n\tin1 := 1 // don't inline lvalues\n\t_ = in1\n}\n\nconst (\n\tx = 1\n\t//go:fix inline\n\tin8 = x\n)\n\n//go:fix inline\nconst D = internal.D // want D: `goFixInline const \"a/internal\".D`\n\nfunc shadow() {\n\tvar x int // shadows x at package scope\n\n\t//go:fix inline\n\tconst a = iota // want `invalid //go:fix inline directive: const value is iota`\n\n\tconst iota = 2\n\t// Below this point, iota is an ordinary constant.\n\n\t//go:fix inline\n\tconst b = iota\n\n\tx = a // a is defined with the predeclared iota, so it cannot be inlined\n\tx = iota // want `Constant b should be inlined`\n\n\t// Don't offer to inline in8, because the result, \"x\", would mean something different\n\t// in this scope than it does in the scope where in8 is defined.\n\tx = in8\n\n\t_ = x\n}\n\n// Type aliases\n\n//go:fix inline\ntype A = T // want A: `goFixInline alias`\n\nvar _ T // want `Type alias A should be inlined`\n\n//go:fix inline\ntype AA = // want AA: `goFixInline alias`\nT         // want `Type alias A should be inlined`\n\nvar _ A // want `Type alias AA should be inlined`\n\n//go:fix inline\ntype (\n\tB = []T                 // want B: `goFixInline alias`\n\tC = map[*string][]error // want C: `goFixInline alias`\n)\n\nvar _ []T // want `Type alias B should be inlined`\nvar _ map[*string][]error // want `Type alias C should be inlined`\n\n//go:fix inline\ntype E = map[[Uno]string][]*T // want `invalid //go:fix inline directive: array types not supported`\n\nvar _ E // nothing should happen here\n\n// literal array lengths are OK\n//\n//go:fix inline\ntype EL = map[[2]string][]*T // want EL: `goFixInline alias`\n\nvar _ map[[2]string][]*T // want `Type alias EL should be inlined`\n\n//go:fix inline\ntype F = map[internal.T]T // want F: `goFixInline alias`\n\nvar _ map[internal.T]T // want `Type alias F should be inlined`\n\n//go:fix inline\ntype G = []chan *internal.T // want G: `goFixInline alias`\n\nvar _ []chan *internal.T // want `Type alias G should be inlined`\n\n// local shadowing\nfunc _() {\n\ttype string = int\n\tconst T = 1\n\n\tvar _ B // nope: B's RHS contains T, which is shadowed\n\tvar _ C // nope: C's RHS contains string, which is shadowed\n}\n\n\n// local inlining\nfunc _[P any]() {\n\tconst a = 1\n\t//go:fix inline\n\tconst b = a\n\n\tx := a // want `Constant b should be inlined`\n\n\t//go:fix inline\n\ttype u = []P\n\n\tvar y []P // want `Type alias u should be inlined`\n\n\t_ = x\n\t_ = y\n}\n\n// generic type aliases\n\n//go:fix inline\ntype (\n\tMapset[T comparable] = map[T]bool // want Mapset: `goFixInline alias`\n\tPair[X, Y any]       = struct {   // want Pair: `goFixInline alias`\n\t\tX X\n\t\tY Y\n\t}\n)\n\nvar _ map[int]bool // want `Type alias Mapset\\[int\\] should be inlined`\n\nvar _ struct {\n\tX T\n\tY string\n} // want `Type alias Pair\\[T, string\\] should be inlined`\n\nfunc _[V any]() {\n\t//go:fix inline\n\ttype M[K comparable] = map[K]V\n\n\tvar _ map[int]V // want `Type alias M\\[int\\] should be inlined`\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/a/internal/d.go",
    "content": "// According to the go toolchain's rule about internal packages,\n// this package is visible to package a, but not package b.\npackage internal\n\nconst D = 1\n\ntype T int\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/b/b.go",
    "content": "package b\n\nimport \"a\"\nimport . \"c\"\n\nfunc f() {\n\ta.One() // want `cannot inline call to a.One because body refers to non-exported one`\n\n\tnew(a.T).Two() // want `Call of \\(a.T\\).Two should be inlined`\n}\n\n//go:fix inline\nconst in2 = a.Uno\n\n//go:fix inline\nconst in3 = C // c.C, by dot import\n\nfunc g() {\n\tx := a.In1 // want `Constant a\\.In1 should be inlined`\n\n\ta := 1\n\t// Although the package identifier \"a\" is shadowed here,\n\t// a second import of \"a\" will be added with a new package identifer.\n\tx = in2 // want `Constant in2 should be inlined`\n\n\tx = in3 // want `Constant in3 should be inlined`\n\n\t_ = a\n\t_ = x\n}\n\nconst d = a.D // nope: a.D refers to a constant in a package that is not visible here.\n\nvar _ a.A // want `Type alias a\\.A should be inlined`\nvar _ a.B // want `Type alias a\\.B should be inlined`\nvar _ a.C // want `Type alias a\\.C should be inlined`\nvar _ R   // want `Type alias R should be inlined`\n\nvar _ a.G // nope: a.G refers to a type in a package that is not visible here\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/b/b.go.golden",
    "content": "package b\n\nimport a0 \"a\"\n\nimport \"io\"\n\nimport \"a\"\nimport . \"c\"\n\nfunc f() {\n\ta.One() // want `cannot inline call to a.One because body refers to non-exported one`\n\n\t_ = 2 // want `Call of \\(a.T\\).Two should be inlined`\n}\n\n//go:fix inline\nconst in2 = a.Uno\n\n//go:fix inline\nconst in3 = C // c.C, by dot import\n\nfunc g() {\n\tx := a.Uno // want `Constant a\\.In1 should be inlined`\n\n\ta := 1\n\t// Although the package identifier \"a\" is shadowed here,\n\t// a second import of \"a\" will be added with a new package identifer.\n\tx = a0.Uno // want `Constant in2 should be inlined`\n\n\tx = C // want `Constant in3 should be inlined`\n\n\t_ = a\n\t_ = x\n}\n\nconst d = a.D // nope: a.D refers to a constant in a package that is not visible here.\n\nvar _ a.T                     // want `Type alias a\\.A should be inlined`\nvar _ []a.T                   // want `Type alias a\\.B should be inlined`\nvar _ map[*string][]error     // want `Type alias a\\.C should be inlined`\nvar _ map[io.Reader]io.Reader // want `Type alias R should be inlined`\n\nvar _ a.G  // nope: a.G refers to a type in a package that is not visible here\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/binding_false/a.go",
    "content": "package a\n\n//go:fix inline\nfunc f(x, y int) int { // want f:`goFixInline a.f`\n\treturn y + x\n}\n\nfunc g() {\n\tf(1, 2) // want `Call of a.f should be inlined`\n\n\tf(h(1), h(2))\n}\n\nfunc h(int) int\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/binding_false/a.go.golden",
    "content": "package a\n\n//go:fix inline\nfunc f(x, y int) int { // want f:`goFixInline a.f`\n\treturn y + x\n}\n\nfunc g() {\n\t_ = 2 + 1 // want `Call of a.f should be inlined`\n\n\tf(h(1), h(2))\n}\n\nfunc h(int) int\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/binding_true/a.go",
    "content": "package a\n\n//go:fix inline\nfunc f(x, y int) int { // want f:`goFixInline a.f`\n\treturn y + x\n}\n\nfunc g() {\n\tf(1, 2) // want `Call of a.f should be inlined`\n\n\tf(h(1), h(2)) // want `Call of a.f should be inlined`\n}\n\nfunc h(int) int\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/binding_true/a.go.golden",
    "content": "package a\n\n//go:fix inline\nfunc f(x, y int) int { // want f:`goFixInline a.f`\n\treturn y + x\n}\n\nfunc g() {\n\t_ = 2 + 1 // want `Call of a.f should be inlined`\n\n\tvar x int = h(1)\n\t_ = h(2) + x // want `Call of a.f should be inlined`\n}\n\nfunc h(int) int\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/c/c.go",
    "content": "package c\n\n// This package is dot-imported by package b.\n\nimport \"io\"\n\nconst C = 1\n\n//go:fix inline\ntype R = map[io.Reader]io.Reader\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/directive/directive.go",
    "content": "package directive\n\n// Functions.\n\nfunc f() {\n\tOne()\n\n\tnew(T).Two()\n}\n\ntype T struct{}\n\n//go:fix inline\nfunc One() int { return one } // want One:`goFixInline directive.One`\n\nconst one = 1\n\n//go:fix inline\nfunc (T) Two() int { return 2 } // want Two:`goFixInline \\(directive.T\\).Two`\n\n// Constants.\n\nconst Uno = 1\n\n//go:fix inline\nconst In1 = Uno // want In1: `goFixInline const \"directive\".Uno`\n\nconst (\n\tno1 = one\n\n\t//go:fix inline\n\tIn2 = one // want In2: `goFixInline const \"directive\".one`\n)\n\n//go:fix inline\nconst bad1 = 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n//go:fix inline\nconst in5,\n\tin6,\n\tbad2 = one, one,\n\tone + 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n// Make sure we don't crash on iota consts, but still process the whole decl.\n//\n//go:fix inline\nconst (\n\ta = iota // want `invalid //go:fix inline directive: const value is iota`\n\tb\n\tin7 = one\n)\n\nconst (\n\tx = 1\n\t//go:fix inline\n\tin8 = x\n)\n\n//go:fix inline\nconst in9 = iota // want `invalid //go:fix inline directive: const value is iota`\n\n//go:fix inline\ntype E = map[[Uno]string][]*T // want `invalid //go:fix inline directive: array types not supported`\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/directive/directive.go.golden",
    "content": "package golden\n\nimport \"a/internal\"\n\n// Functions.\n\nfunc f() {\n\tOne()\n\n\tnew(T).Two()\n}\n\ntype T struct{}\n\n//go:fix inline\nfunc One() int { return one }\n\nconst one = 1\n\n//go:fix inline\nfunc (T) Two() int { return 2 }\n\n// Constants.\n\nconst Uno = 1\n\n//go:fix inline\nconst In1 = Uno // want In1: `goFixInline const \"a\".Uno`\n\nconst (\n\tno1 = one\n\n\t//go:fix inline\n\tIn2 = one // want In2: `goFixInline const \"a\".one`\n)\n\n//go:fix inline\nconst bad1 = 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n//go:fix inline\nconst in5,\n\tin6,\n\tbad2 = one, one,\n\tone + 1 // want `invalid //go:fix inline directive: const value is not the name of another constant`\n\n// Make sure we don't crash on iota consts, but still process the whole decl.\n//\n//go:fix inline\nconst (\n\ta = iota // want `invalid //go:fix inline directive: const value is iota`\n\tb\n\tin7 = one\n)\n\nconst (\n\tx = 1\n\t//go:fix inline\n\tin8 = x\n)\n\n//go:fix inline\nconst a = iota // want `invalid //go:fix inline directive: const value is iota`\n\n//go:fix inline\ntype E = map[[Uno]string][]*T // want `invalid //go:fix inline directive: array types not supported`\n\n// literal array lengths are OK\n//\n//go:fix inline\ntype EL = map[[2]string][]*T // want EL: `goFixInline alias`\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/issue76190.txtar",
    "content": "This test checks that calls are not inlined when the call appears in a specific\ntest of the function. (Even deprecated functions deserve tests.)\n\nVariants:\n- functions (TestF) vs methods (TestT_F)\n- optional comment suffixes (TestSYMBOL_comment)\n- in-package test vs external test\n- test of same or different package from symbol\n\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\n//go:fix inline\nfunc F() { print(\"F\") } // want F:\"goFixInline a.F\"\n//go:fix inline\nfunc G() { print(\"G\") } // want G:\"goFixInline a.G\"\n\ntype T int\n//go:fix inline\nfunc (T) F() { print(\"T.F\") } // want F:`goFixInline \\(a.T\\).F`\n//go:fix inline\nfunc (T) G() { print(\"T.G\") } // want G:`goFixInline \\(a.T\\).G`\n\n-- a/a_test.go --\npackage a\n\nimport \"testing\"\n\nfunc TestF(t *testing.T) {\n\tF() // not inlined\n\tG() // want \"Call of a.G should be inlined\"\n}\n\nfunc TestG_comment(t *testing.T) {\n\tF() // want \"Call of a.F should be inlined\"\n\tG() // not inlined\n}\n\nfunc TestT_F(t *testing.T) {\n\tT(0).F() // not inlined\n\tT(0).G() // want `Call of \\(a.T\\).G should be inlined`\n}\n\nfunc TestT_G(t *testing.T) {\n\tT(0).F() // want `Call of \\(a.T\\).F should be inlined`\n\tT(0).G() // not inlined\n}\n\n-- a/a_test.go.golden --\npackage a\n\nimport \"testing\"\n\nfunc TestF(t *testing.T) {\n\tF()        // not inlined\n\tprint(\"G\") // want \"Call of a.G should be inlined\"\n}\n\nfunc TestG_comment(t *testing.T) {\n\tprint(\"F\") // want \"Call of a.F should be inlined\"\n\tG()        // not inlined\n}\n\nfunc TestT_F(t *testing.T) {\n\tT(0).F()     // not inlined\n\tprint(\"T.G\") // want `Call of \\(a.T\\).G should be inlined`\n}\n\nfunc TestT_G(t *testing.T) {\n\tprint(\"T.F\") // want `Call of \\(a.T\\).F should be inlined`\n\tT(0).G()     // not inlined\n}\n\n-- a/a_x_test.go --\npackage a_test\n\nimport (\n\t\"example.com/a\"\n\t\"testing\"\n)\n\nfunc TestF(t *testing.T) {\n\ta.F() // not inlined\n\ta.G() // want \"Call of a.G should be inlined\"\n}\n\nfunc TestG_comment(t *testing.T) {\n\ta.F() // want \"Call of a.F should be inlined\"\n\ta.G() // not inlined\n}\n\nfunc TestT_F(t *testing.T) {\n\ta.T(0).F() // not inlined\n\ta.T(0).G() // want `Call of \\(a.T\\).G should be inlined`\n}\n\nfunc TestT_G(t *testing.T) {\n\ta.T(0).F() // want `Call of \\(a.T\\).F should be inlined`\n\ta.T(0).G() // not inlined\n}\n\n-- a/a_x_test.go.golden --\npackage a_test\n\nimport (\n\t\"example.com/a\"\n\t\"testing\"\n)\n\nfunc TestF(t *testing.T) {\n\ta.F() \t   // not inlined\n\tprint(\"G\") // want \"Call of a.G should be inlined\"\n}\n\nfunc TestG_comment(t *testing.T) {\n\tprint(\"F\") // want \"Call of a.F should be inlined\"\n\ta.G()      // not inlined\n}\n\nfunc TestT_F(t *testing.T) {\n\ta.T(0).F()   // not inlined\n\tprint(\"T.G\") // want `Call of \\(a.T\\).G should be inlined`\n}\n\nfunc TestT_G(t *testing.T) {\n\tprint(\"T.F\") // want `Call of \\(a.T\\).F should be inlined`\n\ta.T(0).G()   // not inlined\n}\n\n-- b/b_test.go --\npackage b_test\n\nimport (\n\t\"example.com/a\"\n\t\"testing\"\n)\n\nfunc TestF(t *testing.T) {\n\ta.F() // want \"Call of a.F should be inlined\"\n}\n\n-- b/b_test.go.golden --\npackage b_test\n\nimport (\n\t\"testing\"\n)\n\nfunc TestF(t *testing.T) {\n\tprint(\"F\") // want \"Call of a.F should be inlined\"\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/issue77610.txtar",
    "content": "This test verifies that unused imports conservatively added by the inliner are\nremoved in FormatSourceRemoveImports.\n\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nimport \"io\"\n\n//go:fix inline\nfunc OldHello(w io.Writer) error { // want OldHello:\"goFixInline a.OldHello\"\n\treturn NewHello(w)\n}\n\nfunc NewHello(w io.Writer) error {\n\t_, err := w.Write([]byte(\"Hello, World!\"))\n\treturn err\n}\n\n-- b/b.go --\npackage b\n\nimport (\n\t\"strings\"\n\t\"example.com/a\"\n)\n\nfunc _() {\n    var buf strings.Builder\n\t// The inliner wants to add an import for \"io\"; make sure post-processing of the fix removes it.\n\ta.OldHello(&buf) // want \"Call of a.OldHello should be inlined\"\n}\n\n-- b/b.go.golden --\npackage b\n\nimport (\n\t\"strings\"\n\t\"example.com/a\"\n)\n\nfunc _() {\n    var buf strings.Builder\n\t// The inliner wants to add an import for \"io\"; make sure post-processing of the fix removes it.\n\ta.NewHello(&buf) // want \"Call of a.OldHello should be inlined\"\n}\n\n-- c/c.go --\npackage c\n\nimport \"encoding/json\"\n\n//go:fix inline\nfunc OldProcess(m json.Marshaler) error { // want OldProcess:\"goFixInline c.OldProcess\"\n\treturn NewProcess(m)\n}\n\nfunc NewProcess(m json.Marshaler) error {\n\t_, err := m.MarshalJSON()\n\treturn err\n}\n\n-- d/d.go --\npackage d\n\nimport (\n\t\"time\"\n\n\t\"example.com/c\"\n)\n\nfunc _() {\n\tt := time.Now()\n\t// The inliner wants to add an import for \"encoding/json\"; make sure post-processing of the fix removes it.\n\tc.OldProcess(t) // want \"Call of c.OldProcess should be inlined\"\n}\n\n-- d/d.go.golden --\npackage d\n\nimport (\n\t\"time\"\n\n\t\"example.com/c\"\n)\n\nfunc _() {\n\tt := time.Now()\n\t// The inliner wants to add an import for \"encoding/json\"; make sure post-processing of the fix removes it.\n\tc.NewProcess(t) // want \"Call of c.OldProcess should be inlined\"\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/issue77844.txtar",
    "content": "-- go.mod --\nmodule example.com\n\ngo 1.24\n\n-- lib/lib.go --\npackage lib\n\n//go:fix inline\ntype Alias[T any] = []T\n\n-- other/other.go --\npackage other\n\ntype Other int\n\n-- main/main.go --\npackage main\n\nimport (\n\t\"example.com/lib\"\n\t\"example.com/other\"\n)\n\nfunc _() {\n\tvar _ lib.Alias[other.Other] // want \"Type alias lib.Alias.other.Other. should be inlined\"\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/rmimport/rmimport.go",
    "content": "package rmimport\n\nimport \"a\"\n\n// Test that application of two fixes that each remove the second-last\n// import of \"a\" results in removal of the import. This is implemented\n// by the general analysis fix logic, not by any one analyzer.\nfunc _() {\n\tprint(a.T{}.Two()) // want `should be inlined`\n\tprint(a.T{}.Two()) // want `should be inlined`\n}\n"
  },
  {
    "path": "go/analysis/passes/inline/testdata/src/rmimport/rmimport.go.golden",
    "content": "package rmimport\n\n// Test that application of two fixes that each remove the second-last\n// import of \"a\" results in removal of the import. This is implemented\n// by the general analysis fix logic, not by any one analyzer.\nfunc _() {\n\tprint(2) // want `should be inlined`\n\tprint(2) // want `should be inlined`\n}\n"
  },
  {
    "path": "go/analysis/passes/inspect/inspect.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package inspect defines an Analyzer that provides an AST inspector\n// (golang.org/x/tools/go/ast/inspector.Inspector) for the syntax trees\n// of a package. It is only a building block for other analyzers.\n//\n// Example of use in another analysis:\n//\n//\timport (\n//\t\t\"golang.org/x/tools/go/analysis\"\n//\t\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n//\t\t\"golang.org/x/tools/go/ast/inspector\"\n//\t)\n//\n//\tvar Analyzer = &analysis.Analyzer{\n//\t\t...\n//\t\tRequires:       []*analysis.Analyzer{inspect.Analyzer},\n//\t}\n//\n//\tfunc run(pass *analysis.Pass) (interface{}, error) {\n//\t\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n//\t\tinspect.Preorder(nil, func(n ast.Node) {\n//\t\t\t...\n//\t\t})\n//\t\treturn nil, nil\n//\t}\npackage inspect\n\nimport (\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"inspect\",\n\tDoc:              \"optimize AST traversal for later passes\",\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inspect\",\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tResultType:       reflect.TypeFor[*inspector.Inspector](),\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\treturn inspector.New(pass.Files), nil\n}\n"
  },
  {
    "path": "go/analysis/passes/internal/gofixdirective/gofixdirective.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gofixdirective searches for and validates go:fix directives. The\n// go/analysis/passes/inline package uses findgofix to perform inlining.\n// The go/analysis/passes/gofix package uses findgofix to check for problems\n// with go:fix directives.\n//\n// gofixdirective is separate from gofix to avoid depending on refactor/inline,\n// which is large.\npackage gofixdirective\n\n// This package is tested by go/analysis/passes/inline.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\tinternalastutil \"golang.org/x/tools/internal/astutil\"\n)\n\n// A Handler handles language entities with go:fix directives.\ntype Handler interface {\n\tHandleFunc(*ast.FuncDecl)\n\tHandleAlias(*ast.TypeSpec)\n\tHandleConst(name, rhs *ast.Ident)\n}\n\n// Find finds functions and constants annotated with an appropriate \"//go:fix\"\n// comment (the syntax proposed by #32816), and calls handler methods for each one.\n// h may be nil.\nfunc Find(pass *analysis.Pass, root inspector.Cursor, h Handler) {\n\tfor cur := range root.Preorder((*ast.FuncDecl)(nil), (*ast.GenDecl)(nil)) {\n\t\tswitch decl := cur.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tfindFunc(decl, h)\n\n\t\tcase *ast.GenDecl:\n\t\t\tif decl.Tok != token.CONST && decl.Tok != token.TYPE {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdeclInline := hasFixInline(decl.Doc)\n\t\t\t// Accept inline directives on the entire decl as well as individual specs.\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.TypeSpec: // Tok == TYPE\n\t\t\t\t\tfindAlias(pass, spec, declInline, h)\n\n\t\t\t\tcase *ast.ValueSpec: // Tok == CONST\n\t\t\t\t\tfindConst(pass, spec, declInline, h)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc findFunc(decl *ast.FuncDecl, h Handler) {\n\tif !hasFixInline(decl.Doc) {\n\t\treturn\n\t}\n\tif h != nil {\n\t\th.HandleFunc(decl)\n\t}\n}\n\nfunc findAlias(pass *analysis.Pass, spec *ast.TypeSpec, declInline bool, h Handler) {\n\tif !declInline && !hasFixInline(spec.Doc) {\n\t\treturn\n\t}\n\tif !spec.Assign.IsValid() {\n\t\tpass.Reportf(spec.Pos(), \"invalid //go:fix inline directive: not a type alias\")\n\t\treturn\n\t}\n\n\t// Disallow inlines of type expressions containing array types.\n\t// Given an array type like [N]int where N is a named constant, go/types provides\n\t// only the value of the constant as an int64. So inlining A in this code:\n\t//\n\t//    const N = 5\n\t//    type A = [N]int\n\t//\n\t// would result in [5]int, breaking the connection with N.\n\tfor n := range ast.Preorder(spec.Type) {\n\t\tif ar, ok := n.(*ast.ArrayType); ok && ar.Len != nil {\n\t\t\t// Make an exception when the array length is a literal int.\n\t\t\tif lit, ok := ast.Unparen(ar.Len).(*ast.BasicLit); ok && lit.Kind == token.INT {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpass.Reportf(spec.Pos(), \"invalid //go:fix inline directive: array types not supported\")\n\t\t\treturn\n\t\t}\n\t}\n\tif h != nil {\n\t\th.HandleAlias(spec)\n\t}\n}\n\nfunc findConst(pass *analysis.Pass, spec *ast.ValueSpec, declInline bool, h Handler) {\n\tspecInline := hasFixInline(spec.Doc)\n\tif declInline || specInline {\n\t\tfor i, nameIdent := range spec.Names {\n\t\t\tif i >= len(spec.Values) {\n\t\t\t\t// Possible following an iota.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvar rhsIdent *ast.Ident\n\t\t\tswitch val := spec.Values[i].(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\t// Constants defined with the predeclared iota cannot be inlined.\n\t\t\t\tif pass.TypesInfo.Uses[val] == builtinIota {\n\t\t\t\t\tpass.Reportf(val.Pos(), \"invalid //go:fix inline directive: const value is iota\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\trhsIdent = val\n\t\t\tcase *ast.SelectorExpr:\n\t\t\t\trhsIdent = val.Sel\n\t\t\tdefault:\n\t\t\t\tpass.Reportf(val.Pos(), \"invalid //go:fix inline directive: const value is not the name of another constant\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif h != nil {\n\t\t\t\th.HandleConst(nameIdent, rhsIdent)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// hasFixInline reports the presence of a \"//go:fix inline\" directive\n// in the comments.\nfunc hasFixInline(cg *ast.CommentGroup) bool {\n\tfor _, d := range internalastutil.Directives(cg) {\n\t\tif d.Tool == \"go\" && d.Name == \"fix\" && d.Args == \"inline\" {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nvar builtinIota = types.Universe.Lookup(\"iota\")\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package loopclosure defines an Analyzer that checks for references to\n// enclosing loop variables from within nested functions.\n//\n// # Analyzer loopclosure\n//\n// loopclosure: check references to loop variables from within nested functions\n//\n// This analyzer reports places where a function literal references the\n// iteration variable of an enclosing loop, and the loop calls the function\n// in such a way (e.g. with go or defer) that it may outlive the loop\n// iteration and possibly observe the wrong value of the variable.\n//\n// Note: An iteration variable can only outlive a loop iteration in Go versions <=1.21.\n// In Go 1.22 and later, the loop variable lifetimes changed to create a new\n// iteration variable per loop iteration. (See go.dev/issue/60078.)\n//\n// In this example, all the deferred functions run after the loop has\n// completed, so all observe the final value of v [<go1.22].\n//\n//\tfor _, v := range list {\n//\t    defer func() {\n//\t        use(v) // incorrect\n//\t    }()\n//\t}\n//\n// One fix is to create a new variable for each iteration of the loop:\n//\n//\tfor _, v := range list {\n//\t    v := v // new var per iteration\n//\t    defer func() {\n//\t        use(v) // ok\n//\t    }()\n//\t}\n//\n// After Go version 1.22, the previous two for loops are equivalent\n// and both are correct.\n//\n// The next example uses a go statement and has a similar problem [<go1.22].\n// In addition, it has a data race because the loop updates v\n// concurrent with the goroutines accessing it.\n//\n//\tfor _, v := range elem {\n//\t    go func() {\n//\t        use(v)  // incorrect, and a data race\n//\t    }()\n//\t}\n//\n// A fix is the same as before. The checker also reports problems\n// in goroutines started by golang.org/x/sync/errgroup.Group.\n// A hard-to-spot variant of this form is common in parallel tests:\n//\n//\tfunc Test(t *testing.T) {\n//\t    for _, test := range tests {\n//\t        t.Run(test.name, func(t *testing.T) {\n//\t            t.Parallel()\n//\t            use(test) // incorrect, and a data race\n//\t        })\n//\t    }\n//\t}\n//\n// The t.Parallel() call causes the rest of the function to execute\n// concurrent with the loop [<go1.22].\n//\n// The analyzer reports references only in the last statement,\n// as it is not deep enough to understand the effects of subsequent\n// statements that might render the reference benign.\n// (\"Last statement\" is defined recursively in compound\n// statements such as if, switch, and select.)\n//\n// See: https://golang.org/doc/go_faq.html#closures_and_goroutines\npackage loopclosure\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/loopclosure.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage loopclosure\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"loopclosure\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"loopclosure\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.File)(nil),\n\t\t(*ast.RangeStmt)(nil),\n\t\t(*ast.ForStmt)(nil),\n\t}\n\tinspect.Nodes(nodeFilter, func(n ast.Node, push bool) bool {\n\t\tif !push {\n\t\t\t// inspect.Nodes is slightly suboptimal as we only use push=true.\n\t\t\treturn true\n\t\t}\n\t\t// Find the variables updated by the loop statement.\n\t\tvar vars []types.Object\n\t\taddVar := func(expr ast.Expr) {\n\t\t\tif id, _ := expr.(*ast.Ident); id != nil {\n\t\t\t\tif obj := pass.TypesInfo.ObjectOf(id); obj != nil {\n\t\t\t\t\tvars = append(vars, obj)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar body *ast.BlockStmt\n\t\tswitch n := n.(type) {\n\t\tcase *ast.File:\n\t\t\t// Only traverse the file if its goversion is strictly before go1.22.\n\t\t\treturn !analyzerutil.FileUsesGoVersion(pass, n, versions.Go1_22)\n\n\t\tcase *ast.RangeStmt:\n\t\t\tbody = n.Body\n\t\t\taddVar(n.Key)\n\t\t\taddVar(n.Value)\n\t\tcase *ast.ForStmt:\n\t\t\tbody = n.Body\n\t\t\tswitch post := n.Post.(type) {\n\t\t\tcase *ast.AssignStmt:\n\t\t\t\t// e.g. for p = head; p != nil; p = p.next\n\t\t\t\tfor _, lhs := range post.Lhs {\n\t\t\t\t\taddVar(lhs)\n\t\t\t\t}\n\t\t\tcase *ast.IncDecStmt:\n\t\t\t\t// e.g. for i := 0; i < n; i++\n\t\t\t\taddVar(post.X)\n\t\t\t}\n\t\t}\n\t\tif vars == nil {\n\t\t\treturn true\n\t\t}\n\n\t\t// Inspect statements to find function literals that may be run outside of\n\t\t// the current loop iteration.\n\t\t//\n\t\t// For go, defer, and errgroup.Group.Go, we ignore all but the last\n\t\t// statement, because it's hard to prove go isn't followed by wait, or\n\t\t// defer by return. \"Last\" is defined recursively.\n\t\t//\n\t\t// TODO: consider allowing the \"last\" go/defer/Go statement to be followed by\n\t\t// N \"trivial\" statements, possibly under a recursive definition of \"trivial\"\n\t\t// so that checker could, for example, conclude that a go statement is\n\t\t// followed by an if statement made of only trivial statements and trivial expressions,\n\t\t// and hence the go statement could still be checked.\n\t\tforEachLastStmt(body.List, func(last ast.Stmt) {\n\t\t\tvar stmts []ast.Stmt\n\t\t\tswitch s := last.(type) {\n\t\t\tcase *ast.GoStmt:\n\t\t\t\tstmts = litStmts(s.Call.Fun)\n\t\t\tcase *ast.DeferStmt:\n\t\t\t\tstmts = litStmts(s.Call.Fun)\n\t\t\tcase *ast.ExprStmt: // check for errgroup.Group.Go\n\t\t\t\tif call, ok := s.X.(*ast.CallExpr); ok {\n\t\t\t\t\tstmts = litStmts(goInvoke(pass.TypesInfo, call))\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor _, stmt := range stmts {\n\t\t\t\treportCaptured(pass, vars, stmt)\n\t\t\t}\n\t\t})\n\n\t\t// Also check for testing.T.Run (with T.Parallel).\n\t\t// We consider every t.Run statement in the loop body, because there is\n\t\t// no commonly used mechanism for synchronizing parallel subtests.\n\t\t// It is of course theoretically possible to synchronize parallel subtests,\n\t\t// though such a pattern is likely to be exceedingly rare as it would be\n\t\t// fighting against the test runner.\n\t\tfor _, s := range body.List {\n\t\t\tswitch s := s.(type) {\n\t\t\tcase *ast.ExprStmt:\n\t\t\t\tif call, ok := s.X.(*ast.CallExpr); ok {\n\t\t\t\t\tfor _, stmt := range parallelSubtest(pass.TypesInfo, call) {\n\t\t\t\t\t\treportCaptured(pass, vars, stmt)\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\treturn nil, nil\n}\n\n// reportCaptured reports a diagnostic stating a loop variable\n// has been captured by a func literal if checkStmt has escaping\n// references to vars. vars is expected to be variables updated by a loop statement,\n// and checkStmt is expected to be a statements from the body of a func literal in the loop.\nfunc reportCaptured(pass *analysis.Pass, vars []types.Object, checkStmt ast.Stmt) {\n\tast.Inspect(checkStmt, func(n ast.Node) bool {\n\t\tid, ok := n.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tobj := pass.TypesInfo.Uses[id]\n\t\tif obj == nil {\n\t\t\treturn true\n\t\t}\n\t\tfor _, v := range vars {\n\t\t\tif v == obj {\n\t\t\t\tpass.ReportRangef(id, \"loop variable %s captured by func literal\", id.Name)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// forEachLastStmt calls onLast on each \"last\" statement in a list of statements.\n// \"Last\" is defined recursively so, for example, if the last statement is\n// a switch statement, then each switch case is also visited to examine\n// its last statements.\nfunc forEachLastStmt(stmts []ast.Stmt, onLast func(last ast.Stmt)) {\n\tif len(stmts) == 0 {\n\t\treturn\n\t}\n\n\ts := stmts[len(stmts)-1]\n\tswitch s := s.(type) {\n\tcase *ast.IfStmt:\n\tloop:\n\t\tfor {\n\t\t\tforEachLastStmt(s.Body.List, onLast)\n\t\t\tswitch e := s.Else.(type) {\n\t\t\tcase *ast.BlockStmt:\n\t\t\t\tforEachLastStmt(e.List, onLast)\n\t\t\t\tbreak loop\n\t\t\tcase *ast.IfStmt:\n\t\t\t\ts = e\n\t\t\tcase nil:\n\t\t\t\tbreak loop\n\t\t\t}\n\t\t}\n\tcase *ast.ForStmt:\n\t\tforEachLastStmt(s.Body.List, onLast)\n\tcase *ast.RangeStmt:\n\t\tforEachLastStmt(s.Body.List, onLast)\n\tcase *ast.SwitchStmt:\n\t\tfor _, c := range s.Body.List {\n\t\t\tcc := c.(*ast.CaseClause)\n\t\t\tforEachLastStmt(cc.Body, onLast)\n\t\t}\n\tcase *ast.TypeSwitchStmt:\n\t\tfor _, c := range s.Body.List {\n\t\t\tcc := c.(*ast.CaseClause)\n\t\t\tforEachLastStmt(cc.Body, onLast)\n\t\t}\n\tcase *ast.SelectStmt:\n\t\tfor _, c := range s.Body.List {\n\t\t\tcc := c.(*ast.CommClause)\n\t\t\tforEachLastStmt(cc.Body, onLast)\n\t\t}\n\tdefault:\n\t\tonLast(s)\n\t}\n}\n\n// litStmts returns all statements from the function body of a function\n// literal.\n//\n// If fun is not a function literal, it returns nil.\nfunc litStmts(fun ast.Expr) []ast.Stmt {\n\tlit, _ := fun.(*ast.FuncLit)\n\tif lit == nil {\n\t\treturn nil\n\t}\n\treturn lit.Body.List\n}\n\n// goInvoke returns a function expression that would be called asynchronously\n// (but not awaited) in another goroutine as a consequence of the call.\n// For example, given the g.Go call below, it returns the function literal expression.\n//\n//\timport \"sync/errgroup\"\n//\tvar g errgroup.Group\n//\tg.Go(func() error { ... })\n//\n// Currently only \"golang.org/x/sync/errgroup.Group()\" is considered.\nfunc goInvoke(info *types.Info, call *ast.CallExpr) ast.Expr {\n\tif !isMethodCall(info, call, \"golang.org/x/sync/errgroup\", \"Group\", \"Go\") {\n\t\treturn nil\n\t}\n\treturn call.Args[0]\n}\n\n// parallelSubtest returns statements that can be easily proven to execute\n// concurrently via the go test runner, as t.Run has been invoked with a\n// function literal that calls t.Parallel.\n//\n// In practice, users rely on the fact that statements before the call to\n// t.Parallel are synchronous. For example by declaring test := test inside the\n// function literal, but before the call to t.Parallel.\n//\n// Therefore, we only flag references in statements that are obviously\n// dominated by a call to t.Parallel. As a simple heuristic, we only consider\n// statements following the final labeled statement in the function body, to\n// avoid scenarios where a jump would cause either the call to t.Parallel or\n// the problematic reference to be skipped.\n//\n//\timport \"testing\"\n//\n//\tfunc TestFoo(t *testing.T) {\n//\t\ttests := []int{0, 1, 2}\n//\t\tfor i, test := range tests {\n//\t\t\tt.Run(\"subtest\", func(t *testing.T) {\n//\t\t\t\tprintln(i, test) // OK\n//\t\t \t\tt.Parallel()\n//\t\t\t\tprintln(i, test) // Not OK\n//\t\t\t})\n//\t\t}\n//\t}\nfunc parallelSubtest(info *types.Info, call *ast.CallExpr) []ast.Stmt {\n\tif !isMethodCall(info, call, \"testing\", \"T\", \"Run\") {\n\t\treturn nil\n\t}\n\n\tif len(call.Args) != 2 {\n\t\t// Ignore calls such as t.Run(fn()).\n\t\treturn nil\n\t}\n\n\tlit, _ := call.Args[1].(*ast.FuncLit)\n\tif lit == nil {\n\t\treturn nil\n\t}\n\n\t// Capture the *testing.T object for the first argument to the function\n\t// literal.\n\tif len(lit.Type.Params.List[0].Names) == 0 {\n\t\treturn nil\n\t}\n\n\ttObj := info.Defs[lit.Type.Params.List[0].Names[0]]\n\tif tObj == nil {\n\t\treturn nil\n\t}\n\n\t// Match statements that occur after a call to t.Parallel following the final\n\t// labeled statement in the function body.\n\t//\n\t// We iterate over lit.Body.List to have a simple, fast and \"frequent enough\"\n\t// dominance relationship for t.Parallel(): lit.Body.List[i] dominates\n\t// lit.Body.List[j] for i < j unless there is a jump.\n\tvar stmts []ast.Stmt\n\tafterParallel := false\n\tfor _, stmt := range lit.Body.List {\n\t\tstmt, labeled := unlabel(stmt)\n\t\tif labeled {\n\t\t\t// Reset: naively we don't know if a jump could have caused the\n\t\t\t// previously considered statements to be skipped.\n\t\t\tstmts = nil\n\t\t\tafterParallel = false\n\t\t}\n\n\t\tif afterParallel {\n\t\t\tstmts = append(stmts, stmt)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check if stmt is a call to t.Parallel(), for the correct t.\n\t\texprStmt, ok := stmt.(*ast.ExprStmt)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tcall, ok := exprStmt.X.(*ast.CallExpr)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif isMethodCall(info, call, \"testing\", \"T\", \"Parallel\") {\n\t\t\tx, _ := call.Fun.(*ast.SelectorExpr)\n\t\t\tif x == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tid, _ := x.X.(*ast.Ident)\n\t\t\tif id == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif info.Uses[id] == tObj {\n\t\t\t\tafterParallel = true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stmts\n}\n\n// unlabel returns the inner statement for the possibly labeled statement stmt,\n// stripping any (possibly nested) *ast.LabeledStmt wrapper.\n//\n// The second result reports whether stmt was an *ast.LabeledStmt.\nfunc unlabel(stmt ast.Stmt) (ast.Stmt, bool) {\n\tlabeled := false\n\tfor {\n\t\tlabelStmt, ok := stmt.(*ast.LabeledStmt)\n\t\tif !ok {\n\t\t\treturn stmt, labeled\n\t\t}\n\t\tlabeled = true\n\t\tstmt = labelStmt.Stmt\n\t}\n}\n\nfunc isMethodCall(info *types.Info, call *ast.CallExpr, pkgPath, typeName, method string) bool {\n\treturn typesinternal.IsMethodNamed(typeutil.Callee(info, call), pkgPath, typeName, method)\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/loopclosure_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage loopclosure_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/loopclosure\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc TestVersions(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"src\", \"versions\", \"go22.txtar\"))\n\tanalysistest.Run(t, dir, loopclosure.Analyzer, \"golang.org/fake/versions\")\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/a/a.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains legacy tests for the loopclosure checker.\n// Legacy expectations are incorrect after go1.22.\n\npackage testdata\n\nimport (\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n)\n\nvar A int\n\nfunc _() {\n\tvar s []int\n\tfor i, v := range s {\n\t\tgo func() {\n\t\t\tprintln(i) // want \"loop variable i captured by func literal\"\n\t\t\tprintln(v) // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n\tfor i, v := range s {\n\t\tdefer func() {\n\t\t\tprintln(i) // want \"loop variable i captured by func literal\"\n\t\t\tprintln(v) // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n\tfor i := range s {\n\t\tgo func() {\n\t\t\tprintln(i) // want \"loop variable i captured by func literal\"\n\t\t}()\n\t}\n\tfor _, v := range s {\n\t\tgo func() {\n\t\t\tprintln(v) // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n\tfor i, v := range s {\n\t\tgo func() {\n\t\t\tprintln(i, v)\n\t\t}()\n\t\tprintln(\"unfortunately, we don't catch the error above because of this statement\")\n\t}\n\tfor i, v := range s {\n\t\tgo func(i, v int) {\n\t\t\tprintln(i, v)\n\t\t}(i, v)\n\t}\n\tfor i, v := range s {\n\t\ti, v := i, v\n\t\tgo func() {\n\t\t\tprintln(i, v)\n\t\t}()\n\t}\n\n\t// iteration variable declared outside the loop\n\tfor A = range s {\n\t\tgo func() {\n\t\t\tprintln(A) // want \"loop variable A captured by func literal\"\n\t\t}()\n\t}\n\t// iteration variable declared in a different file\n\tfor B = range s {\n\t\tgo func() {\n\t\t\tprintln(B) // want \"loop variable B captured by func literal\"\n\t\t}()\n\t}\n\t// If the key of the range statement is not an identifier\n\t// the code should not panic (it used to).\n\tvar x [2]int\n\tvar f int\n\tfor x[0], f = range s {\n\t\tgo func() {\n\t\t\t_ = f // want \"loop variable f captured by func literal\"\n\t\t}()\n\t}\n\ttype T struct {\n\t\tv int\n\t}\n\tfor _, v := range s {\n\t\tgo func() {\n\t\t\t_ = T{v: 1}\n\t\t\t_ = map[int]int{v: 1} // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n\n\t// ordinary for-loops\n\tfor i := 0; i < 10; i++ {\n\t\tgo func() {\n\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t}()\n\t}\n\tfor i, j := 0, 1; i < 100; i, j = j, i+j {\n\t\tgo func() {\n\t\t\tprint(j) // want \"loop variable j captured by func literal\"\n\t\t}()\n\t}\n\ttype cons struct {\n\t\tcar int\n\t\tcdr *cons\n\t}\n\tvar head *cons\n\tfor p := head; p != nil; p = p.cdr {\n\t\tgo func() {\n\t\t\tprint(p.car) // want \"loop variable p captured by func literal\"\n\t\t}()\n\t}\n}\n\n// Cases that rely on recursively checking for last statements.\nfunc _() {\n\n\tfor i := range \"outer\" {\n\t\tfor j := range \"inner\" {\n\t\t\tif j < 1 {\n\t\t\t\tdefer func() {\n\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t}()\n\t\t\t} else if j < 2 {\n\t\t\t\tgo func() {\n\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t}()\n\t\t\t} else {\n\t\t\t\tgo func() {\n\t\t\t\t\tprint(i)\n\t\t\t\t}()\n\t\t\t\tprintln(\"we don't catch the error above because of this statement\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif j < 1 {\n\t\t\t\tswitch j {\n\t\t\t\tcase 0:\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\tdefault:\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\t}\n\t\t\t} else if j < 2 {\n\t\t\t\tvar a interface{} = j\n\t\t\t\tswitch a.(type) {\n\t\t\t\tcase int:\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\tdefault:\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tch := make(chan string)\n\t\t\t\tselect {\n\t\t\t\tcase <-ch:\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\tdefault:\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\t\t}()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Group is used to test that loopclosure only matches Group.Go when Group is\n// from the golang.org/x/sync/errgroup package.\ntype Group struct{}\n\nfunc (g *Group) Go(func() error) {}\n\nfunc _() {\n\tvar s []int\n\t// errgroup.Group.Go() invokes Go routines\n\tg := new(errgroup.Group)\n\tfor i, v := range s {\n\t\tg.Go(func() error {\n\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\tprint(v) // want \"loop variable v captured by func literal\"\n\t\t\treturn nil\n\t\t})\n\t}\n\n\tfor i, v := range s {\n\t\tif i > 0 {\n\t\t\tg.Go(func() error {\n\t\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\t\treturn nil\n\t\t\t})\n\t\t} else {\n\t\t\tg.Go(func() error {\n\t\t\t\tprint(v) // want \"loop variable v captured by func literal\"\n\t\t\t\treturn nil\n\t\t\t})\n\t\t}\n\t}\n\n\t// Do not match other Group.Go cases\n\tg1 := new(Group)\n\tfor i, v := range s {\n\t\tg1.Go(func() error {\n\t\t\tprint(i)\n\t\t\tprint(v)\n\t\t\treturn nil\n\t\t})\n\t}\n}\n\n// Real-world example from #16520, slightly simplified\nfunc _() {\n\tvar nodes []interface{}\n\n\tcritical := new(errgroup.Group)\n\tothers := sync.WaitGroup{}\n\n\tisCritical := func(node interface{}) bool { return false }\n\trun := func(node interface{}) error { return nil }\n\n\tfor _, node := range nodes {\n\t\tif isCritical(node) {\n\t\t\tcritical.Go(func() error {\n\t\t\t\treturn run(node) // want \"loop variable node captured by func literal\"\n\t\t\t})\n\t\t} else {\n\t\t\tothers.Add(1)\n\t\t\tgo func() {\n\t\t\t\t_ = run(node) // want \"loop variable node captured by func literal\"\n\t\t\t\tothers.Done()\n\t\t\t}()\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/a/b.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\n// B is declared in a separate file to test that object resolution spans the\n// entire package.\nvar B int\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/golang.org/x/sync/errgroup/errgroup.go",
    "content": "// Package errgroup synthesizes Go's package \"golang.org/x/sync/errgroup\",\n// which is used in unit-testing.\npackage errgroup\n\ntype Group struct {\n}\n\nfunc (g *Group) Go(f func() error) {\n\tgo func() {\n\t\tf()\n\t}()\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/subtests/subtest.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains legacy tests that the loopclosure analyzer detects leaked\n// references via parallel subtests.\n// Legacy expectations are incorrect after go1.22.\n\npackage subtests\n\nimport (\n\t\"testing\"\n)\n\n// T is used to test that loopclosure only matches T.Run when T is from the\n// testing package.\ntype T struct{}\n\n// Run should not match testing.T.Run. Note that the second argument is\n// intentionally a *testing.T, not a *T, so that we can check both\n// testing.T.Parallel inside a T.Run, and a T.Parallel inside a testing.T.Run.\nfunc (t *T) Run(string, func(*testing.T)) {\n}\n\nfunc (t *T) Parallel() {}\n\nfunc _(t *testing.T) {\n\tfor i, test := range []int{1, 2, 3} {\n\t\t// Check that parallel subtests are identified.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tprintln(i)    // want \"loop variable i captured by func literal\"\n\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t})\n\n\t\t// Check that serial tests are OK.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\n\t\t// Check that the location of t.Parallel matters.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t\tt.Parallel()\n\t\t\tprintln(i)    // want \"loop variable i captured by func literal\"\n\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t})\n\n\t\t// Check that *testing.T value matters.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tvar x testing.T\n\t\t\tx.Parallel()\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\n\t\t// Check that shadowing the loop variables within the test literal is OK if\n\t\t// it occurs before t.Parallel().\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\ti := i\n\t\t\ttest := test\n\t\t\tt.Parallel()\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\n\t\t// Check that shadowing the loop variables within the test literal is Not\n\t\t// OK if it occurs after t.Parallel().\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\ti := i        // want \"loop variable i captured by func literal\"\n\t\t\ttest := test  // want \"loop variable test captured by func literal\"\n\t\t\tprintln(i)    // OK\n\t\t\tprintln(test) // OK\n\t\t})\n\n\t\t// Check uses in nested blocks.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\t{\n\t\t\t\tprintln(i)    // want \"loop variable i captured by func literal\"\n\t\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t\t}\n\t\t})\n\n\t\t// Check that we catch uses in nested subtests.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\t\tprintln(i)    // want \"loop variable i captured by func literal\"\n\t\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t\t})\n\t\t})\n\n\t\t// Check that there is no diagnostic if t is not a *testing.T.\n\t\tt.Run(\"\", func(_ *testing.T) {\n\t\t\tt := &T{}\n\t\t\tt.Parallel()\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\n\t\t// Check that there is no diagnostic when a jump to a label may have caused\n\t\t// the call to t.Parallel to have been skipped.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tif true {\n\t\t\t\tgoto Test\n\t\t\t}\n\t\t\tt.Parallel()\n\t\tTest:\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\n\t\t// Check that there is no diagnostic when a jump to a label may have caused\n\t\t// the loop variable reference to be skipped, but there is a diagnostic\n\t\t// when both the call to t.Parallel and the loop variable reference occur\n\t\t// after the final label in the block.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tif true {\n\t\t\t\tgoto Test\n\t\t\t}\n\t\t\tt.Parallel()\n\t\t\tprintln(i) // maybe OK\n\t\tTest:\n\t\t\tt.Parallel()\n\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t})\n\n\t\t// Check that multiple labels are handled.\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tif true {\n\t\t\t\tgoto Test1\n\t\t\t} else {\n\t\t\t\tgoto Test2\n\t\t\t}\n\t\tTest1:\n\t\tTest2:\n\t\t\tt.Parallel()\n\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t})\n\n\t\t// Check that we do not have problems when t.Run has a single argument.\n\t\tfn := func() (string, func(t *testing.T)) { return \"\", nil }\n\t\tt.Run(fn())\n\t}\n}\n\n// Check that there is no diagnostic when loop variables are shadowed within\n// the loop body.\nfunc _(t *testing.T) {\n\tfor i, test := range []int{1, 2, 3} {\n\t\ti := i\n\t\ttest := test\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\t}\n}\n\n// Check that t.Run must be *testing.T.Run.\nfunc _(t *T) {\n\tfor i, test := range []int{1, 2, 3} {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tprintln(i)\n\t\t\tprintln(test)\n\t\t})\n\t}\n}\n\n// Check that the top-level must be parallel in order to cause a diagnostic.\n//\n// From https://pkg.go.dev/testing:\n//\n//\t\"Run does not return until parallel subtests have completed, providing a\n//\tway to clean up after a group of parallel tests\"\nfunc _(t *testing.T) {\n\tfor _, test := range []int{1, 2, 3} {\n\t\t// In this subtest, a/b must complete before the synchronous subtest \"a\"\n\t\t// completes, so the reference to test does not escape the current loop\n\t\t// iteration.\n\t\tt.Run(\"a\", func(s *testing.T) {\n\t\t\ts.Run(\"b\", func(u *testing.T) {\n\t\t\t\tu.Parallel()\n\t\t\t\tprintln(test)\n\t\t\t})\n\t\t})\n\n\t\t// In this subtest, c executes concurrently, so the reference to test may\n\t\t// escape the current loop iteration.\n\t\tt.Run(\"c\", func(s *testing.T) {\n\t\t\ts.Parallel()\n\t\t\ts.Run(\"d\", func(u *testing.T) {\n\t\t\t\tprintln(test) // want \"loop variable test captured by func literal\"\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains legacy tests for the loopclosure checker for GoVersion <go1.22.\n// Expectations are incorrect after go1.22.\n\n//go:build go1.19\n\npackage typeparams\n\nimport \"golang.org/x/sync/errgroup\"\n\nfunc f[T any](data T) {\n\tprint(data)\n}\n\nfunc _[T any]() {\n\tvar s []T\n\tfor i, v := range s {\n\t\tgo func() {\n\t\t\tf(i) // want \"loop variable i captured by func literal\"\n\t\t\tf(v) // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n}\n\nfunc loop[P interface{ Go(func() error) }](grp P) {\n\tvar s []int\n\tfor i, v := range s {\n\t\t// The checker only matches on methods \"(*...errgroup.Group).Go\".\n\t\tgrp.Go(func() error {\n\t\t\tprint(i)\n\t\t\tprint(v)\n\t\t\treturn nil\n\t\t})\n\t}\n}\n\nfunc _() {\n\tg := new(errgroup.Group)\n\tloop(g) // the analyzer is not \"type inter-procedural\" so no findings are reported\n}\n\ntype T[P any] struct {\n\ta P\n}\n\nfunc (t T[P]) Go(func() error) {}\n\nfunc _(g T[errgroup.Group]) {\n\tvar s []int\n\tfor i, v := range s {\n\t\t// \"T.a\" is method \"(*...errgroup.Group).Go\".\n\t\tg.a.Go(func() error {\n\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\tprint(v) // want \"loop variable v captured by func literal\"\n\t\t\treturn nil\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/versions/go18.txtar",
    "content": "Test loopclosure at go version go1.19.\n\n-- go.mod --\nmodule golang.org/fake/versions\n\ngo 1.19\n-- pre.go --\n//go:build go1.19\n\npackage versions\n\nfunc InGo18(l []int) {\n  for i, v := range l {\n    go func() {\n      print(i) // want \"loop variable i captured by func literal\"\n      print(v) // want \"loop variable v captured by func literal\"\n    }()\n  }\n}\n-- go22.go --\n//go:build go1.22\n\npackage versions\n\nfunc InGo22(l []int) {\n\tfor i, v := range l {\n\t\tgo func() {\n\t\t\tprint(i) // Not reported due to file's GoVersion.\n\t\t\tprint(v) // Not reported due to file's GoVersion.\n\t\t}()\n\t}\n}\n-- modver.go --\npackage versions\n\nfunc At18FromModuleVersion(l []int) {\n\tfor i, v := range l {\n\t\tgo func() {\n\t\t\tprint(i) // want \"loop variable i captured by func literal\"\n\t\t\tprint(v) // want \"loop variable v captured by func literal\"\n\t\t}()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/loopclosure/testdata/src/versions/go22.txtar",
    "content": "Test loopclosure at go version go1.22.\n\nThe go1.21 build tag is necessary to force the file version.\n\n-- go.mod --\nmodule golang.org/fake/versions\n\ngo 1.22\n-- pre.go --\n//go:build go1.21\n\npackage versions\n\nfunc Bad(l []int) {\n  for i, v := range l {\n    go func() {\n      print(i) // want \"loop variable i captured by func literal\"\n      print(v) // want \"loop variable v captured by func literal\"\n    }()\n  }\n}\n-- go22.go --\n//go:build go1.22\n\npackage versions\n\nfunc InGo22(l []int) {\n\tfor i, v := range l {\n\t\tgo func() {\n\t\t\tprint(i) // Not reported due to file's GoVersion.\n\t\t\tprint(v) // Not reported due to file's GoVersion.\n\t\t}()\n\t}\n}\n\n-- modver.go --\npackage versions\n\nfunc At22FromTheModuleVersion(l []int) {\n\tfor i, v := range l {\n\t\tgo func() {\n\t\t\tprint(i) // Not reported due to module's GoVersion.\n\t\t\tprint(v) // Not reported due to module's GoVersion.\n\t\t}()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/cmd/lostcancel/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The lostcancel command applies the golang.org/x/tools/go/analysis/passes/lostcancel\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/lostcancel\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(lostcancel.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package lostcancel defines an Analyzer that checks for failure to\n// call a context cancellation function.\n//\n// # Analyzer lostcancel\n//\n// lostcancel: check cancel func returned by context.WithCancel is called\n//\n// The cancellation function returned by context.WithCancel, WithTimeout,\n// WithDeadline and variants such as WithCancelCause must be called,\n// or the new context will remain live until its parent context is cancelled.\n// (The background context is never cancelled.)\npackage lostcancel\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/lostcancel.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lostcancel\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/ctrlflow\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/cfg\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"lostcancel\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"lostcancel\"),\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel\",\n\tRun:  run,\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\tctrlflow.Analyzer,\n\t},\n}\n\nconst debug = false\n\nvar contextPackage = \"context\"\n\n// checkLostCancel reports a failure to the call the cancel function\n// returned by context.WithCancel, either because the variable was\n// assigned to the blank identifier, or because there exists a\n// control-flow path from the call to a return statement and that path\n// does not \"use\" the cancel function.  Any reference to the variable\n// counts as a use, even within a nested function literal.\n// If the variable's scope is larger than the function\n// containing the assignment, we assume that other uses exist.\n//\n// checkLostCancel analyzes a single named or literal function.\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Fast path: bypass check if file doesn't use context.WithCancel.\n\tif !typesinternal.Imports(pass.Pkg, contextPackage) {\n\t\treturn nil, nil\n\t}\n\n\t// Call runFunc for each Func{Decl,Lit}.\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeTypes := []ast.Node{\n\t\t(*ast.FuncLit)(nil),\n\t\t(*ast.FuncDecl)(nil),\n\t}\n\tinspect.Preorder(nodeTypes, func(n ast.Node) {\n\t\trunFunc(pass, n)\n\t})\n\treturn nil, nil\n}\n\nfunc runFunc(pass *analysis.Pass, node ast.Node) {\n\t// Find scope of function node\n\tvar funcScope *types.Scope\n\tswitch v := node.(type) {\n\tcase *ast.FuncLit:\n\t\tfuncScope = pass.TypesInfo.Scopes[v.Type]\n\tcase *ast.FuncDecl:\n\t\tfuncScope = pass.TypesInfo.Scopes[v.Type]\n\t}\n\n\t// Maps each cancel variable to its defining ValueSpec/AssignStmt.\n\tcancelvars := make(map[*types.Var]ast.Node)\n\n\t// TODO(adonovan): opt: refactor to make a single pass\n\t// over the AST using inspect.WithStack and node types\n\t// {FuncDecl,FuncLit,CallExpr,SelectorExpr}.\n\n\t// Find the set of cancel vars to analyze.\n\tast.PreorderStack(node, nil, func(n ast.Node, stack []ast.Node) bool {\n\t\tif _, ok := n.(*ast.FuncLit); ok && len(stack) > 0 {\n\t\t\treturn false // don't stray into nested functions\n\t\t}\n\n\t\t// Look for n=SelectorExpr beneath stack=[{AssignStmt,ValueSpec} CallExpr]:\n\t\t//\n\t\t//   ctx, cancel    := context.WithCancel(...)\n\t\t//   ctx, cancel     = context.WithCancel(...)\n\t\t//   var ctx, cancel = context.WithCancel(...)\n\t\t//\n\t\tif !isContextWithCancel(pass.TypesInfo, n) || !isCall(stack[len(stack)-1]) {\n\t\t\treturn true\n\t\t}\n\t\tvar id *ast.Ident // id of cancel var\n\t\tstmt := stack[len(stack)-2]\n\t\tswitch stmt := stmt.(type) {\n\t\tcase *ast.ValueSpec:\n\t\t\tif len(stmt.Names) > 1 {\n\t\t\t\tid = stmt.Names[1]\n\t\t\t}\n\t\tcase *ast.AssignStmt:\n\t\t\tif len(stmt.Lhs) > 1 {\n\t\t\t\tid, _ = stmt.Lhs[1].(*ast.Ident)\n\t\t\t}\n\t\t}\n\t\tif id != nil {\n\t\t\tif id.Name == \"_\" {\n\t\t\t\tpass.ReportRangef(id,\n\t\t\t\t\t\"the cancel function returned by context.%s should be called, not discarded, to avoid a context leak\",\n\t\t\t\t\tn.(*ast.SelectorExpr).Sel.Name)\n\t\t\t} else if v, ok := pass.TypesInfo.Uses[id].(*types.Var); ok {\n\t\t\t\t// If the cancel variable is defined outside function scope,\n\t\t\t\t// do not analyze it.\n\t\t\t\tif funcScope.Contains(v.Pos()) {\n\t\t\t\t\tcancelvars[v] = stmt\n\t\t\t\t}\n\t\t\t} else if v, ok := pass.TypesInfo.Defs[id].(*types.Var); ok {\n\t\t\t\tcancelvars[v] = stmt\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\tif len(cancelvars) == 0 {\n\t\treturn // no need to inspect CFG\n\t}\n\n\t// Obtain the CFG.\n\tcfgs := pass.ResultOf[ctrlflow.Analyzer].(*ctrlflow.CFGs)\n\tvar g *cfg.CFG\n\tvar sig *types.Signature\n\tswitch node := node.(type) {\n\tcase *ast.FuncDecl:\n\t\tsig, _ = pass.TypesInfo.Defs[node.Name].Type().(*types.Signature)\n\t\tif node.Name.Name == \"main\" && sig.Recv() == nil && pass.Pkg.Name() == \"main\" {\n\t\t\t// Returning from main.main terminates the process,\n\t\t\t// so there's no need to cancel contexts.\n\t\t\treturn\n\t\t}\n\t\tg = cfgs.FuncDecl(node)\n\n\tcase *ast.FuncLit:\n\t\tsig, _ = pass.TypesInfo.Types[node.Type].Type.(*types.Signature)\n\t\tg = cfgs.FuncLit(node)\n\t}\n\tif sig == nil {\n\t\treturn // missing type information\n\t}\n\n\t// Print CFG.\n\tif debug {\n\t\tfmt.Println(g.Format(pass.Fset))\n\t}\n\n\t// Examine the CFG for each variable in turn.\n\t// (It would be more efficient to analyze all cancelvars in a\n\t// single pass over the AST, but seldom is there more than one.)\n\tfor v, stmt := range cancelvars {\n\t\tif ret := lostCancelPath(pass, g, v, stmt, sig); ret != nil {\n\t\t\tlineno := pass.Fset.Position(stmt.Pos()).Line\n\t\t\tpass.ReportRangef(stmt, \"the %s function is not used on all paths (possible context leak)\", v.Name())\n\n\t\t\tpos, end := ret.Pos(), ret.End()\n\t\t\t// golang/go#64547: cfg.Block.Return may return a synthetic\n\t\t\t// ReturnStmt that overflows the file.\n\t\t\tif pass.Fset.File(pos) != pass.Fset.File(end) {\n\t\t\t\tend = pos\n\t\t\t}\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     pos,\n\t\t\t\tEnd:     end,\n\t\t\t\tMessage: fmt.Sprintf(\"this return statement may be reached without using the %s var defined on line %d\", v.Name(), lineno),\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc isCall(n ast.Node) bool { _, ok := n.(*ast.CallExpr); return ok }\n\n// isContextWithCancel reports whether n is one of the qualified identifiers\n// context.With{Cancel,Timeout,Deadline}.\nfunc isContextWithCancel(info *types.Info, n ast.Node) bool {\n\tsel, ok := n.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn false\n\t}\n\tswitch sel.Sel.Name {\n\tcase \"WithCancel\", \"WithCancelCause\",\n\t\t\"WithTimeout\", \"WithTimeoutCause\",\n\t\t\"WithDeadline\", \"WithDeadlineCause\":\n\tdefault:\n\t\treturn false\n\t}\n\tif x, ok := sel.X.(*ast.Ident); ok {\n\t\tif pkgname, ok := info.Uses[x].(*types.PkgName); ok {\n\t\t\treturn pkgname.Imported().Path() == contextPackage\n\t\t}\n\t\t// Import failed, so we can't check package path.\n\t\t// Just check the local package name (heuristic).\n\t\treturn x.Name == \"context\"\n\t}\n\treturn false\n}\n\n// lostCancelPath finds a path through the CFG, from stmt (which defines\n// the 'cancel' variable v) to a return statement, that doesn't \"use\" v.\n// If it finds one, it returns the return statement (which may be synthetic).\n// sig is the function's type, if known.\nfunc lostCancelPath(pass *analysis.Pass, g *cfg.CFG, v *types.Var, stmt ast.Node, sig *types.Signature) *ast.ReturnStmt {\n\tvIsNamedResult := sig != nil && tupleContains(sig.Results(), v)\n\n\t// uses reports whether stmts contain a \"use\" of variable v.\n\tuses := func(pass *analysis.Pass, v *types.Var, stmts []ast.Node) bool {\n\t\tfound := false\n\t\tfor _, stmt := range stmts {\n\t\t\tast.Inspect(stmt, func(n ast.Node) bool {\n\t\t\t\tswitch n := n.(type) {\n\t\t\t\tcase *ast.Ident:\n\t\t\t\t\tif pass.TypesInfo.Uses[n] == v {\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t}\n\t\t\t\tcase *ast.ReturnStmt:\n\t\t\t\t\t// A naked return statement counts as a use\n\t\t\t\t\t// of the named result variables.\n\t\t\t\t\tif n.Results == nil && vIsNamedResult {\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn !found\n\t\t\t})\n\t\t}\n\t\treturn found\n\t}\n\n\t// blockUses computes \"uses\" for each block, caching the result.\n\tmemo := make(map[*cfg.Block]bool)\n\tblockUses := func(pass *analysis.Pass, v *types.Var, b *cfg.Block) bool {\n\t\tres, ok := memo[b]\n\t\tif !ok {\n\t\t\tres = uses(pass, v, b.Nodes)\n\t\t\tmemo[b] = res\n\t\t}\n\t\treturn res\n\t}\n\n\t// Find the var's defining block in the CFG,\n\t// plus the rest of the statements of that block.\n\tvar defblock *cfg.Block\n\tvar rest []ast.Node\nouter:\n\tfor _, b := range g.Blocks {\n\t\tfor i, n := range b.Nodes {\n\t\t\tif n == stmt {\n\t\t\t\tdefblock = b\n\t\t\t\trest = b.Nodes[i+1:]\n\t\t\t\tbreak outer\n\t\t\t}\n\t\t}\n\t}\n\tif defblock == nil {\n\t\tpanic(\"internal error: can't find defining block for cancel var\")\n\t}\n\n\t// Is v \"used\" in the remainder of its defining block?\n\tif uses(pass, v, rest) {\n\t\treturn nil\n\t}\n\n\t// Does the defining block return without using v?\n\tif ret := defblock.Return(); ret != nil {\n\t\treturn ret\n\t}\n\n\t// Search the CFG depth-first for a path, from defblock to a\n\t// return block, in which v is never \"used\".\n\tseen := make(map[*cfg.Block]bool)\n\tvar search func(blocks []*cfg.Block) *ast.ReturnStmt\n\tsearch = func(blocks []*cfg.Block) *ast.ReturnStmt {\n\t\tfor _, b := range blocks {\n\t\t\tif seen[b] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[b] = true\n\n\t\t\t// Prune the search if the block uses v.\n\t\t\tif blockUses(pass, v, b) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Found path to return statement?\n\t\t\tif ret := b.Return(); ret != nil {\n\t\t\t\tif debug {\n\t\t\t\t\tfmt.Printf(\"found path to return in block %s\\n\", b)\n\t\t\t\t}\n\t\t\t\treturn ret // found\n\t\t\t}\n\n\t\t\t// Recur\n\t\t\tif ret := search(b.Succs); ret != nil {\n\t\t\t\tif debug {\n\t\t\t\t\tfmt.Printf(\" from block %s\\n\", b)\n\t\t\t\t}\n\t\t\t\treturn ret\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn search(defblock.Succs)\n}\n\nfunc tupleContains(tuple *types.Tuple, v *types.Var) bool {\n\tfor v0 := range tuple.Variables() {\n\t\tif v0 == v {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/lostcancel_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lostcancel_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/lostcancel\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, lostcancel.Analyzer, \"a\", \"b\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/testdata/src/a/a.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n)\n\nvar bg = context.Background()\n\n// Check the three functions and assignment forms (var, :=, =) we look for.\n// (Do these early: line numbers are fragile.)\nfunc _() {\n\tvar _, cancel = context.WithCancel(bg) // want `the cancel function is not used on all paths \\(possible context leak\\)`\n\tif false {\n\t\t_ = cancel\n\t}\n} // want \"this return statement may be reached without using the cancel var defined on line 20\"\n\nfunc _() {\n\t_, cancel2 := context.WithDeadline(bg, time.Time{}) // want \"the cancel2 function is not used...\"\n\tif false {\n\t\t_ = cancel2\n\t}\n} // want \"may be reached without using the cancel2 var defined on line 27\"\n\nfunc _() {\n\tvar cancel3 func()\n\t_, cancel3 = context.WithTimeout(bg, 0) // want \"function is not used...\"\n\tif false {\n\t\t_ = cancel3\n\t}\n} // want \"this return statement may be reached without using the cancel3 var defined on line 35\"\n\nfunc _() {\n\tctx, _ := context.WithCancel(bg)               // want \"the cancel function returned by context.WithCancel should be called, not discarded, to avoid a context leak\"\n\tctx, _ = context.WithTimeout(bg, 0)            // want \"the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak\"\n\tctx, _ = context.WithDeadline(bg, time.Time{}) // want \"the cancel function returned by context.WithDeadline should be called, not discarded, to avoid a context leak\"\n\t_ = ctx\n}\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg)\n\tdefer cancel() // ok\n}\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg) // want \"not used on all paths\"\n\tif condition {\n\t\tcancel()\n\t}\n\treturn // want \"this return statement may be reached without using the cancel var\"\n}\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg)\n\tif condition {\n\t\tcancel()\n\t} else {\n\t\t// ok: infinite loop\n\t\tfor {\n\t\t\tprint(0)\n\t\t}\n\t}\n}\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg) // want \"not used on all paths\"\n\tif condition {\n\t\tcancel()\n\t} else {\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tprint(0)\n\t\t}\n\t}\n} // want \"this return statement may be reached without using the cancel var\"\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg)\n\t// ok: used on all paths\n\tswitch someInt {\n\tcase 0:\n\t\tnew(testing.T).FailNow()\n\tcase 1:\n\t\tlog.Fatal()\n\tcase 2:\n\t\tcancel()\n\tcase 3:\n\t\tprint(\"hi\")\n\t\tfallthrough\n\tdefault:\n\t\tos.Exit(1)\n\t}\n}\n\nfunc _() {\n\t_, cancel := context.WithCancel(bg) // want \"not used on all paths\"\n\tswitch someInt {\n\tcase 0:\n\t\tnew(testing.T).FailNow()\n\tcase 1:\n\t\tlog.Fatal()\n\tcase 2:\n\t\tcancel()\n\tcase 3:\n\t\tprint(\"hi\") // falls through to implicit return\n\tdefault:\n\t\tos.Exit(1)\n\t}\n} // want \"this return statement may be reached without using the cancel var\"\n\nfunc _(ch chan int) {\n\t_, cancel := context.WithCancel(bg) // want \"not used on all paths\"\n\tselect {\n\tcase <-ch:\n\t\tnew(testing.T).FailNow()\n\tcase ch <- 2:\n\t\tprint(\"hi\") // falls through to implicit return\n\tcase ch <- 1:\n\t\tcancel()\n\tdefault:\n\t\tos.Exit(1)\n\t}\n} // want \"this return statement may be reached without using the cancel var\"\n\nfunc _(ch chan int) {\n\t_, cancel := context.WithCancel(bg)\n\t// A blocking select must execute one of its cases.\n\tselect {\n\tcase <-ch:\n\t\tpanic(0)\n\t}\n\tif false {\n\t\t_ = cancel\n\t}\n}\n\nfunc _() {\n\tgo func() {\n\t\tctx, cancel := context.WithCancel(bg) // want \"not used on all paths\"\n\t\tif false {\n\t\t\t_ = cancel\n\t\t}\n\t\tprint(ctx)\n\t}() // want \"may be reached without using the cancel var\"\n}\n\nvar condition bool\nvar someInt int\n\n// Regression test for Go issue 16143.\nfunc _() {\n\tvar x struct{ f func() }\n\tx.f()\n}\n\n// Regression test for Go issue 16230.\nfunc _() (ctx context.Context, cancel func()) {\n\tctx, cancel = context.WithCancel(bg)\n\treturn // a naked return counts as a load of the named result values\n}\n\n// Same as above, but for literal function.\nvar _ = func() (ctx context.Context, cancel func()) {\n\tctx, cancel = context.WithCancel(bg)\n\treturn\n}\n\n// Test for Go issue 31856.\nfunc _() {\n\tvar cancel func()\n\n\tfunc() {\n\t\t_, cancel = context.WithCancel(bg)\n\t}()\n\n\tcancel()\n}\n\nvar cancel1 func()\n\n// Same as above, but for package-level cancel variable.\nfunc _() {\n\t// We assume that other uses of cancel1 exist.\n\t_, cancel1 = context.WithCancel(bg)\n}\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/testdata/src/b/b.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport \"context\"\n\n// Return from main is handled specially.\n// Since the program exits, there's no need to call cancel.\nfunc main() {\n\t_, cancel := context.WithCancel(nil)\n\tif maybe {\n\t\tcancel()\n\t}\n}\n\nfunc notMain() {\n\t_, cancel := context.WithCancel(nil) // want \"cancel function.*not used\"\n\n\tif maybe {\n\t\tcancel()\n\t}\n} // want \"return statement.*reached without using the cancel\"\n\nvar maybe bool\n"
  },
  {
    "path": "go/analysis/passes/lostcancel/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the lostcancel checker.\n\npackage typeparams\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"time\"\n)\n\n//\n// These comment lines are ballast to ensure\n// that this is L17. Add/remove as needed.\n\nvar bg = context.Background()\n\nfunc _[T any]() {\n\tvar _, cancel = context.WithCancel(bg) // want `the cancel function is not used on all paths \\(possible context leak\\)`\n\tif false {\n\t\t_ = cancel\n\t}\n} // want \"this return statement may be reached without using the cancel var defined on line 22\"\n\nfunc _[T any]() {\n\t_, cancel := context.WithCancel(bg)\n\tdefer cancel() // ok\n}\n\n// User-defined Context that matches type \"context.Context\"\ntype C1[P1 any, P2 any] interface {\n\tDeadline() (deadline time.Time, ok P1)\n\tDone() <-chan struct{}\n\tErr() error\n\tValue(key P2) P2\n}\n\nfunc _(bg C1[bool, interface{}]) {\n\tctx, _ := context.WithCancel(bg)    // want \"the cancel function returned by context.WithCancel should be called, not discarded, to avoid a context leak\"\n\tctx, _ = context.WithTimeout(bg, 0) // want \"the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak\"\n\t_ = ctx\n}\n\n// User-defined Context that doesn't match type \"context.Context\"\ntype C2[P any] interface {\n\tWithCancel(parent C1[P, bool]) (ctx C1[P, bool], cancel func())\n}\n\nfunc _(c C2[interface{}]) {\n\tctx, _ := c.WithCancel(nil) // not \"context.WithCancel()\"\n\t_ = ctx\n}\n\n// Further regression test for Go issue 16143.\nfunc _() {\n\ttype C[P any] struct{ f func() P }\n\tvar x C[int]\n\tx.f()\n}\n\nfunc withCancelCause(maybe bool) {\n\t{\n\t\t_, cancel := context.WithCancelCause(bg)\n\t\tdefer cancel(io.EOF) // ok\n\t}\n\t{\n\t\t_, cancel := context.WithCancelCause(bg) // want \"the cancel function is not used on all paths \\\\(possible context leak\\\\)\"\n\t\tif maybe {\n\t\t\tcancel(io.EOF)\n\t\t}\n\t}\n} // want \"this return statement may be reached without using the cancel var defined on line 70\"\n"
  },
  {
    "path": "go/analysis/passes/modernize/any.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar AnyAnalyzer = &analysis.Analyzer{\n\tName:     \"any\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"any\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      runAny,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any\",\n}\n\n// The any pass replaces interface{} with go1.18's 'any'.\nfunc runAny(pass *analysis.Pass) (any, error) {\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_18) {\n\t\tfor curIface := range curFile.Preorder((*ast.InterfaceType)(nil)) {\n\t\t\tiface := curIface.Node().(*ast.InterfaceType)\n\n\t\t\tif iface.Methods.NumFields() == 0 {\n\t\t\t\t// Check that 'any' is not shadowed.\n\t\t\t\tif lookup(pass.TypesInfo, curIface, \"any\") == builtinAny {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     iface.Pos(),\n\t\t\t\t\t\tEnd:     iface.End(),\n\t\t\t\t\t\tMessage: \"interface{} can be replaced by any\",\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: \"Replace interface{} by any\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tPos:     iface.Pos(),\n\t\t\t\t\t\t\t\t\tEnd:     iface.End(),\n\t\t\t\t\t\t\t\t\tNewText: []byte(\"any\"),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/atomictypes.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar atomicTypesAnalyzer = &analysis.Analyzer{\n\tName: \"atomictypes\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"atomictypes\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: runAtomic,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#atomictypes\",\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.AtomicTypesModernizer = atomicTypesAnalyzer\n}\n\n// TODO(mkalil): support the Pointer variants.\n// Consider the following function signatures for pointer loading:\n// func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)\n// func (x *Pointer[T]) Load() *T\n// Since the former uses *unsafe.Pointer while the latter uses *Pointer[T],\n// we would need to determine the type T to apply the transformation, and there\n// will be additional edits required to remove any *unsafe.Pointer casts.\n// \t\"LoadPointer\", \"StorePointer\", \"SwapPointer\", \"CompareAndSwapPointer\"\n\n// sync/atomic functions of interest. Some added in go1.19, some added in go1.23.\nvar syncAtomicFuncs = []string{\n\t// Added in go1.19.\n\t\"AddInt32\", \"AddInt64\", \"AddUint32\", \"AddUint64\", \"AddUintptr\",\n\t\"CompareAndSwapInt32\", \"CompareAndSwapInt64\", \"CompareAndSwapUint32\", \"CompareAndSwapUint64\", \"CompareAndSwapUintptr\",\n\t\"LoadInt32\", \"LoadInt64\", \"LoadUint32\", \"LoadUint64\", \"LoadUintptr\",\n\t\"StoreInt32\", \"StoreInt64\", \"StoreUint32\", \"StoreUint64\", \"StoreUintptr\",\n\t\"SwapInt32\", \"SwapInt64\", \"SwapUint32\", \"SwapUint64\", \"SwapUintptr\",\n\t// Added in go1.23.\n\t\"AndInt32\", \"AndInt64\", \"AndUint32\", \"AndUint64\", \"AndUintptr\",\n\t\"OrInt32\", \"OrInt64\", \"OrUint32\", \"OrUint64\", \"OrUintptr\",\n}\n\nfunc runAtomic(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"sync/atomic\") {\n\t\treturn nil, nil // doesn't directly import sync/atomic\n\t}\n\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\t// Gather all candidate variables v appearing\n\t// in calls to atomic.AddInt32(&v, ...) et al.\n\tvar (\n\t\tatomicPkg *types.Package\n\t\tvars      = make(map[*types.Var]string) // maps candidate vars v to the name of the call they appear in\n\t)\n\tfor _, funcName := range syncAtomicFuncs {\n\t\tobj := index.Object(\"sync/atomic\", funcName)\n\t\tif obj == nil {\n\t\t\tcontinue\n\t\t}\n\t\tatomicPkg = obj.Pkg()\n\t\tfor curCall := range index.Calls(obj) {\n\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\tif unary, ok := call.Args[0].(*ast.UnaryExpr); ok && unary.Op == token.AND {\n\t\t\t\tvar v *types.Var\n\t\t\t\tswitch x := unary.X.(type) {\n\t\t\t\tcase *ast.Ident:\n\t\t\t\t\tv, _ = info.Uses[x].(*types.Var)\n\t\t\t\tcase *ast.SelectorExpr:\n\t\t\t\t\tif seln, ok := info.Selections[x]; ok {\n\t\t\t\t\t\tv, _ = seln.Obj().(*types.Var)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif v != nil && !v.Exported() {\n\t\t\t\t\t// v must be a non-exported package or local var, or a struct field.\n\t\t\t\t\tswitch v.Kind() {\n\t\t\t\t\tcase types.RecvVar, types.ParamVar, types.ResultVar:\n\t\t\t\t\t\tcontinue // fix would change func signature\n\t\t\t\t\t}\n\t\t\t\t\tvars[v] = funcName\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check that all uses of each candidate variable\n\t// appear in calls of the form atomic.AddInt32(&v, ...).\nnextvar:\n\tfor v, funcName := range vars {\n\t\tvar edits []analysis.TextEdit\n\t\tfixFiles := make(map[*ast.File]bool) // unique files involved in the current fix\n\n\t\t// Check the form of the declaration: var v int or struct { v int }\n\t\tdef, ok := index.Def(v)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tvar (\n\t\t\ttyp   ast.Expr\n\t\t\tnames []*ast.Ident\n\t\t)\n\t\tswitch parent := def.Parent().Node().(type) {\n\t\tcase *ast.Field: // struct { v int }\n\t\t\tnames = parent.Names\n\t\t\ttyp = parent.Type\n\t\tcase *ast.ValueSpec: // var v int\n\t\t\tif len(parent.Values) > 0 {\n\t\t\t\t// e.g. var v int = 5\n\t\t\t\t// skip because rewriting as `var v atomic.Int32 = 5` is invalid\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnames = parent.Names\n\t\t\ttyp = parent.Type\n\t\t}\n\t\tif len(names) != 1 || typ == nil {\n\t\t\tcontinue // v is not the sole var declared here (e.g. var x, y int32); or no explicit type\n\t\t}\n\t\toldType := info.TypeOf(typ)                             // e.g. \"int32\"\n\t\tnewType := strings.Title(oldType.Underlying().String()) // e.g. \"Int32\"\n\n\t\t// Get package prefix to avoid shadowing.\n\t\tfile := astutil.EnclosingFile(def)\n\t\tpkgPrefix, impEdits := refactor.AddImport(pass.TypesInfo, file, \"atomic\", \"sync/atomic\", \"\", def.Node().Pos())\n\t\tif len(impEdits) > 0 {\n\t\t\tpanic(\"unexpected import edits\") // atomic PkgName should be in scope already\n\t\t}\n\t\t// Edit the type.\n\t\t//\n\t\t// var v int32\n\t\t//       ------------\n\t\t// var v atomic.Int32\n\t\tedits = append(edits, analysis.TextEdit{\n\t\t\tPos:     typ.Pos(),\n\t\t\tEnd:     typ.End(),\n\t\t\tNewText: fmt.Appendf(nil, \"%s%s\", pkgPrefix, newType),\n\t\t})\n\t\tfixFiles[file] = true\n\n\t\t// Each valid use is an Ident v or Selector expr.v within an atomic.F(&...) call.\n\t\tvar validUses []inspector.Cursor\n\t\tfor cur := range index.Uses(v) {\n\t\t\tif v.IsField() && cur.ParentEdgeKind() == edge.KeyValueExpr_Key {\n\t\t\t\tcontinue nextvar // we cannot fix initial an value assignment T{v: 1}\n\t\t\t}\n\t\t\tif cur.ParentEdgeKind() == edge.SelectorExpr_Sel {\n\t\t\t\tcur = cur.Parent() // ascend from v to expr.v\n\t\t\t}\n\t\t\t// Inv: cur is the l-value expression denoting v.\n\t\t\t// v must appear beneath atomic.AddInt32(&v, ...) call.\n\t\t\tvalid := false\n\t\t\tif cur.ParentEdgeKind() == edge.UnaryExpr_X &&\n\t\t\t\tcur.Parent().Node().(*ast.UnaryExpr).Op == token.AND {\n\t\t\t\tif ek, idx := cur.Parent().ParentEdge(); ek == edge.CallExpr_Args && idx == 0 {\n\t\t\t\t\tcurCall := cur.Parent().Parent()\n\t\t\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\t\t\tif fn, ok := typeutil.Callee(info, call).(*types.Func); ok && fn.Pkg() == atomicPkg {\n\t\t\t\t\t\tvalid = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !valid {\n\t\t\t\t// More complex case: reject candidate.\n\t\t\t\t//\n\t\t\t\t// For example, cur may be an unsynchronized load (e.g. v == 0). To\n\t\t\t\t// avoid a type conversion error, we'd have to rewrite this as\n\t\t\t\t// v.Load(). However, this is an invalid rewrite: if the program is\n\t\t\t\t// mixing atomic operations with unsynchronized reads, the author\n\t\t\t\t// might have accidentally introduced a data race and the suggested\n\t\t\t\t// fix could obscure the mistake. Or, if the usage is intentional,\n\t\t\t\t// rewriting may result in a behavior change.\n\t\t\t\tcontinue nextvar\n\t\t\t}\n\t\t\tvalidUses = append(validUses, cur)\n\t\t}\n\n\t\tfor _, cur := range validUses {\n\t\t\tvexpr := cur.Node()\n\t\t\tcall := cur.Parent().Parent().Node().(*ast.CallExpr)\n\t\t\tfn := typeutil.Callee(info, call).(*types.Func)\n\t\t\t// atomic.AddInt32(&v,    ...)\n\t\t\t// ----------------- -----\n\t\t\t//                  v.Add(...)\n\t\t\tafter := vexpr.End() // LoadInt32(&v⁁)\n\t\t\tif len(call.Args) > 1 {\n\t\t\t\tafter = call.Args[1].Pos() // AddInt32(&v, ⁁...)\n\t\t\t}\n\t\t\tverb := strings.TrimSuffix(fn.Name(), newType) // \"AddInt32\" => \"Add\"\n\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t{\n\t\t\t\t\tPos: call.Pos(),\n\t\t\t\t\tEnd: vexpr.Pos(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos:     vexpr.End(),\n\t\t\t\t\tEnd:     after,\n\t\t\t\t\tNewText: fmt.Appendf(nil, \".%s(\", verb),\n\t\t\t\t},\n\t\t\t}...)\n\t\t\tfixFiles[astutil.EnclosingFile(cur)] = true\n\t\t}\n\n\t\t// Check minimum Go version: go1.19, or 1.23 for the And/Or functions.\n\t\tif !(analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_19) ||\n\t\t\tanalyzerutil.FileUsesGoVersion(pass, file, versions.Go1_23) &&\n\t\t\t\t(strings.HasPrefix(funcName, \"And\") || strings.HasPrefix(funcName, \"Or\"))) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Skip if v is not local and the package has ignored files as it may be\n\t\t// an incomplete transformation.\n\t\tif !isLocal(v) && len(pass.IgnoredFiles) > 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     names[0].Pos(),\n\t\t\tEnd:     typ.End(),\n\t\t\tMessage: fmt.Sprintf(\"var %s %s may be simplified using atomic.%s\", v.Name(), oldType, newType),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   fmt.Sprintf(\"Replace %s by atomic.%s\", oldType, newType),\n\t\t\t\tTextEdits: edits,\n\t\t\t}},\n\t\t})\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/bloop.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar BLoopAnalyzer = &analysis.Analyzer{\n\tName: \"bloop\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"bloop\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: bloop,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#bloop\",\n}\n\n// bloop updates benchmarks that use \"for range b.N\", replacing it\n// with go1.24's b.Loop() and eliminating any preceding\n// b.{Start,Stop,Reset}Timer calls.\n//\n// Variants:\n//\n//\tfor i := 0; i < b.N; i++ {}  =>   for b.Loop() {}\n//\tfor range b.N {}\nfunc bloop(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"testing\") {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\t// edits computes the text edits for a matched for/range loop\n\t// at the specified cursor. b is the *testing.B value, and\n\t// (start, end) is the portion using b.N to delete.\n\tedits := func(curLoop inspector.Cursor, b ast.Expr, start, end token.Pos) (edits []analysis.TextEdit) {\n\t\tcurFn, _ := enclosingFunc(curLoop)\n\t\t// Within the same function, delete all calls to\n\t\t// b.{Start,Stop,Timer} that precede the loop.\n\t\tfilter := []ast.Node{(*ast.ExprStmt)(nil), (*ast.FuncLit)(nil)}\n\t\tcurFn.Inspect(filter, func(cur inspector.Cursor) (descend bool) {\n\t\t\tnode := cur.Node()\n\t\t\tif is[*ast.FuncLit](node) {\n\t\t\t\treturn false // don't descend into FuncLits (e.g. sub-benchmarks)\n\t\t\t}\n\t\t\tstmt := node.(*ast.ExprStmt)\n\t\t\tif stmt.Pos() > start {\n\t\t\t\treturn false // not preceding: stop\n\t\t\t}\n\t\t\tif call, ok := stmt.X.(*ast.CallExpr); ok {\n\t\t\t\tobj := typeutil.Callee(info, call)\n\t\t\t\tif typesinternal.IsMethodNamed(obj, \"testing\", \"B\", \"StopTimer\", \"StartTimer\", \"ResetTimer\") {\n\t\t\t\t\t// Delete call statement.\n\t\t\t\t\t// TODO(adonovan): delete following newline, or\n\t\t\t\t\t// up to start of next stmt? (May delete a comment.)\n\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\tPos: stmt.Pos(),\n\t\t\t\t\t\tEnd: stmt.End(),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\n\t\t// Replace ...b.N... with b.Loop().\n\t\treturn append(edits, analysis.TextEdit{\n\t\t\tPos:     start,\n\t\t\tEnd:     end,\n\t\t\tNewText: fmt.Appendf(nil, \"%s.Loop()\", astutil.Format(pass.Fset, b)),\n\t\t})\n\t}\n\n\t// Find all for/range statements.\n\tloops := []ast.Node{\n\t\t(*ast.ForStmt)(nil),\n\t\t(*ast.RangeStmt)(nil),\n\t}\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_24) {\n\t\tfor curLoop := range curFile.Preorder(loops...) {\n\t\t\tswitch n := curLoop.Node().(type) {\n\t\t\tcase *ast.ForStmt:\n\t\t\t\t// for _; i < b.N; _ {}\n\t\t\t\tif cmp, ok := n.Cond.(*ast.BinaryExpr); ok && cmp.Op == token.LSS {\n\t\t\t\t\tif sel, ok := cmp.Y.(*ast.SelectorExpr); ok &&\n\t\t\t\t\t\tsel.Sel.Name == \"N\" &&\n\t\t\t\t\t\ttypesinternal.IsPointerToNamed(info.TypeOf(sel.X), \"testing\", \"B\") && usesBenchmarkNOnce(curLoop, info) {\n\n\t\t\t\t\t\tdelStart, delEnd := n.Cond.Pos(), n.Cond.End()\n\n\t\t\t\t\t\t// Eliminate variable i if no longer needed:\n\t\t\t\t\t\t//  for i := 0; i < b.N; i++ {\n\t\t\t\t\t\t//    ...no references to i...\n\t\t\t\t\t\t//  }\n\t\t\t\t\t\tbody, _ := curLoop.LastChild()\n\t\t\t\t\t\tif v := isIncrementLoop(info, n); v != nil &&\n\t\t\t\t\t\t\t!uses(index, body, v) {\n\t\t\t\t\t\t\tdelStart, delEnd = n.Init.Pos(), n.Post.End()\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t// Highlight \"i < b.N\".\n\t\t\t\t\t\t\tPos:     n.Cond.Pos(),\n\t\t\t\t\t\t\tEnd:     n.Cond.End(),\n\t\t\t\t\t\t\tMessage: \"b.N can be modernized using b.Loop()\",\n\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\tMessage:   \"Replace b.N with b.Loop()\",\n\t\t\t\t\t\t\t\tTextEdits: edits(curLoop, sel.X, delStart, delEnd),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.RangeStmt:\n\t\t\t\t// for range b.N {} -> for b.Loop() {}\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): handle \"for i := range b.N\".\n\t\t\t\tif sel, ok := n.X.(*ast.SelectorExpr); ok &&\n\t\t\t\t\tn.Key == nil &&\n\t\t\t\t\tn.Value == nil &&\n\t\t\t\t\tsel.Sel.Name == \"N\" &&\n\t\t\t\t\ttypesinternal.IsPointerToNamed(info.TypeOf(sel.X), \"testing\", \"B\") && usesBenchmarkNOnce(curLoop, info) {\n\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t// Highlight \"range b.N\".\n\t\t\t\t\t\tPos:     n.Range,\n\t\t\t\t\t\tEnd:     n.X.End(),\n\t\t\t\t\t\tMessage: \"b.N can be modernized using b.Loop()\",\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage:   \"Replace b.N with b.Loop()\",\n\t\t\t\t\t\t\tTextEdits: edits(curLoop, sel.X, n.Range, n.X.End()),\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// uses reports whether the subtree cur contains a use of obj.\nfunc uses(index *typeindex.Index, cur inspector.Cursor, obj types.Object) bool {\n\tfor use := range index.Uses(obj) {\n\t\tif cur.Contains(use) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// enclosingFunc returns the cursor for the innermost Func{Decl,Lit}\n// that encloses c, if any.\nfunc enclosingFunc(c inspector.Cursor) (inspector.Cursor, bool) {\n\treturn moreiters.First(c.Enclosing((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)))\n}\n\n// usesBenchmarkNOnce reports whether a b.N loop should be modernized to b.Loop().\n// Only modernize loops that are:\n// 1. Directly in a benchmark function (not in nested functions)\n//   - b.Loop() must be called in the same goroutine as the benchmark function\n//   - Function literals are often used with goroutines (go func(){...})\n//\n// 2. The only b.N loop in that benchmark function\n//   - b.Loop() can only be called once per benchmark execution\n//   - Multiple calls result in \"B.Loop called with timer stopped\" error\n//   - Multiple loops may have complex interdependencies that are hard to analyze\nfunc usesBenchmarkNOnce(c inspector.Cursor, info *types.Info) bool {\n\t// Find the enclosing benchmark function\n\tcurFunc, ok := enclosingFunc(c)\n\tif !ok {\n\t\treturn false\n\t}\n\n\t// Check if this is actually a benchmark function\n\tfdecl, ok := curFunc.Node().(*ast.FuncDecl)\n\tif !ok {\n\t\treturn false // not in a function; or, inside a FuncLit\n\t}\n\tif !isBenchmarkFunc(fdecl) {\n\t\treturn false\n\t}\n\n\t// Count all b.N references in this benchmark function (including nested functions)\n\tbnRefCount := 0\n\tfilter := []ast.Node{(*ast.SelectorExpr)(nil)}\n\tcurFunc.Inspect(filter, func(cur inspector.Cursor) bool {\n\t\tsel := cur.Node().(*ast.SelectorExpr)\n\t\tif sel.Sel.Name == \"N\" &&\n\t\t\ttypesinternal.IsPointerToNamed(info.TypeOf(sel.X), \"testing\", \"B\") {\n\t\t\tbnRefCount++\n\t\t}\n\t\treturn true\n\t})\n\n\t// Only modernize if there's exactly one b.N reference\n\treturn bnRefCount == 1\n}\n\n// isBenchmarkFunc reports whether f is a benchmark function.\nfunc isBenchmarkFunc(f *ast.FuncDecl) bool {\n\treturn f.Recv == nil &&\n\t\tf.Name != nil &&\n\t\tf.Name.IsExported() &&\n\t\tstrings.HasPrefix(f.Name.Name, \"Benchmark\") &&\n\t\tf.Type.Params != nil &&\n\t\tlen(f.Type.Params.List) == 1\n}\n\n// isIncrementLoop reports whether loop has the form \"for i := 0; ...; i++ { ... }\",\n// and if so, it returns the symbol for the index variable.\nfunc isIncrementLoop(info *types.Info, loop *ast.ForStmt) *types.Var {\n\tif assign, ok := loop.Init.(*ast.AssignStmt); ok &&\n\t\tassign.Tok == token.DEFINE &&\n\t\tlen(assign.Rhs) == 1 &&\n\t\tisZeroIntConst(info, assign.Rhs[0]) &&\n\t\tis[*ast.IncDecStmt](loop.Post) &&\n\t\tloop.Post.(*ast.IncDecStmt).Tok == token.INC &&\n\t\tastutil.EqualSyntax(loop.Post.(*ast.IncDecStmt).X, assign.Lhs[0]) {\n\t\treturn info.Defs[assign.Lhs[0].(*ast.Ident)].(*types.Var)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/cmd/modernize/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The modernize command suggests (or, with -fix, applies) fixes that\n// clarify Go code by using more modern features.\n//\n// See [golang.org/x/tools/go/analysis/passes/modernize] for details.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/passes/modernize\"\n)\n\nfunc main() { multichecker.Main(modernize.Suite...) }\n"
  },
  {
    "path": "go/analysis/passes/modernize/doc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage modernize provides a suite of analyzers that suggest\nsimplifications to Go code, using modern language and library\nfeatures.\n\nEach diagnostic provides a fix. Our intent is that these fixes may\nbe safely applied en masse without changing the behavior of your\nprogram. In some cases the suggested fixes are imperfect and may\nlead to (for example) unused imports or unused local variables,\ncausing build breakage. However, these problems are generally\ntrivial to fix. We regard any modernizer whose fix changes program\nbehavior to have a serious bug and will endeavor to fix it.\n\nTo apply all modernization fixes en masse, you can use the\nfollowing command:\n\n\t$ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...\n\n(Do not use \"go get -tool\" to add gopls as a dependency of your\nmodule; gopls commands must be built from their release branch.)\n\nIf the tool warns of conflicting fixes, you may need to run it more\nthan once until it has applied all fixes cleanly. This command is\nnot an officially supported interface and may change in the future.\n\nChanges produced by this tool should be reviewed as usual before\nbeing merged. In some cases, a loop may be replaced by a simple\nfunction call, causing comments within the loop to be discarded.\nHuman judgment may be required to avoid losing comments of value.\n\nThe modernize suite contains many analyzers. Diagnostics from some,\nsuch as \"any\" (which replaces \"interface{}\" with \"any\" where it\nis safe to do so), are particularly numerous. It may ease the burden of\ncode review to apply fixes in two steps, the first consisting only of\nfixes from the \"any\" analyzer, the second consisting of all\nother analyzers. This can be achieved using flags, as in this example:\n\n\t$ modernize -any=true  -fix ./...\n\t$ modernize -any=false -fix ./...\n\n# Analyzer appendclipped\n\nappendclipped: simplify append chains using slices.Concat\n\nThe appendclipped analyzer suggests replacing chains of append calls with a\nsingle call to slices.Concat, which was added in Go 1.21. For example,\nappend(append(s, s1...), s2...) would be simplified to slices.Concat(s, s1, s2).\n\nIn the simple case of appending to a newly allocated slice, such as\nappend([]T(nil), s...), the analyzer suggests the more concise slices.Clone(s).\nFor byte slices, it will prefer bytes.Clone if the \"bytes\" package is\nalready imported.\n\nThis fix is only applied when the base of the append tower is a\n\"clipped\" slice, meaning its length and capacity are equal (e.g.\nx[:0:0] or []T{}). This is to avoid changing program behavior by\neliminating intended side effects on the base slice's underlying\narray.\n\nThis analyzer is currently disabled by default as the\ntransformation does not preserve the nilness of the base slice in\nall cases; see https://go.dev/issue/73557.\n\n# Analyzer atomictypes\n\natomictypes: replace basic types in sync/atomic calls with atomic types\n\nThe atomictypes analyzer suggests replacing the primitive sync/atomic functions with\nthe strongly typed atomic wrapper types introduced in Go1.19 (e.g.\natomic.Int32). For example,\n\n\tvar x int32\n\tatomic.AddInt32(&x, 1)\n\nwould become\n\n\tvar x atomic.Int32\n\tx.Add(1)\n\nThe atomic types are safer because they don't allow non-atomic access, which is\na common source of bugs. These types also resolve memory alignment issues that\nplagued the old atomic functions on 32-bit architectures.\n\n# Analyzer bloop\n\nbloop: replace for-range over b.N with b.Loop\n\nThe bloop analyzer suggests replacing benchmark loops of the form\n`for i := 0; i < b.N; i++` or `for range b.N` with the more modern\n`for b.Loop()`, which was added in Go 1.24.\n\nThis change makes benchmark code more readable and also removes the need for\nmanual timer control, so any preceding calls to b.StartTimer, b.StopTimer,\nor b.ResetTimer within the same function will also be removed.\n\nCaveats: The b.Loop() method is designed to prevent the compiler from\noptimizing away the benchmark loop, which can occasionally result in\nslower execution due to increased allocations in some specific cases.\nSince its fix may change the performance of nanosecond-scale benchmarks,\nbloop is disabled by default in the `go fix` analyzer suite; see golang/go#74967.\n\n# Analyzer any\n\nany: replace interface{} with any\n\nThe any analyzer suggests replacing uses of the empty interface type,\n`interface{}`, with the `any` alias, which was introduced in Go 1.18.\nThis is a purely stylistic change that makes code more readable.\n\n# Analyzer errorsastype\n\nerrorsastype: replace errors.As with errors.AsType[T]\n\nThis analyzer suggests fixes to simplify uses of [errors.As] of\nthis form:\n\n\tvar myerr *MyErr\n\tif errors.As(err, &myerr) {\n\t\thandle(myerr)\n\t}\n\nby using the less error-prone generic [errors.AsType] function,\nintroduced in Go 1.26:\n\n\tif myerr, ok := errors.AsType[*MyErr](err); ok {\n\t\thandle(myerr)\n\t}\n\nThe fix is only offered if the var declaration has the form shown and\nthere are no uses of myerr outside the if statement.\n\n# Analyzer fmtappendf\n\nfmtappendf: replace []byte(fmt.Sprintf) with fmt.Appendf\n\nThe fmtappendf analyzer suggests replacing `[]byte(fmt.Sprintf(...))` with\n`fmt.Appendf(nil, ...)`. This avoids the intermediate allocation of a string\nby Sprintf, making the code more efficient. The suggestion also applies to\nfmt.Sprint and fmt.Sprintln.\n\n# Analyzer forvar\n\nforvar: remove redundant re-declaration of loop variables\n\nThe forvar analyzer removes unnecessary shadowing of loop variables.\nBefore Go 1.22, it was common to write `for _, x := range s { x := x ... }`\nto create a fresh variable for each iteration. Go 1.22 changed the semantics\nof `for` loops, making this pattern redundant. This analyzer removes the\nunnecessary `x := x` statement.\n\nThis fix only applies to `range` loops.\n\n# Analyzer mapsloop\n\nmapsloop: replace explicit loops over maps with calls to maps package\n\nThe mapsloop analyzer replaces loops of the form\n\n\tfor k, v := range x { m[k] = v }\n\nwith a single call to a function from the `maps` package, added in Go 1.23.\nDepending on the context, this could be `maps.Copy`, `maps.Insert`,\n`maps.Clone`, or `maps.Collect`.\n\nThe transformation to `maps.Clone` is applied conservatively, as it\npreserves the nilness of the source map, which may be a subtle change in\nbehavior if the original code did not handle a nil map in the same way.\n\n# Analyzer minmax\n\nminmax: replace if/else statements with calls to min or max\n\nThe minmax analyzer simplifies conditional assignments by suggesting the use\nof the built-in `min` and `max` functions, introduced in Go 1.21. For example,\n\n\tif a < b { x = a } else { x = b }\n\nis replaced by\n\n\tx = min(a, b).\n\nThis analyzer avoids making suggestions for floating-point types,\nas the behavior of `min` and `max` with NaN values can differ from\nthe original if/else statement.\n\n# Analyzer newexpr\n\nnewexpr: simplify code by using go1.26's new(expr)\n\nThis analyzer finds declarations of functions of this form:\n\n\tfunc varOf(x int) *int { return &x }\n\nand suggests a fix to turn them into inlinable wrappers around\ngo1.26's built-in new(expr) function:\n\n\t//go:fix inline\n\tfunc varOf(x int) *int { return new(x) }\n\n(The directive comment causes the 'inline' analyzer to suggest\nthat calls to such functions are inlined.)\n\nIn addition, this analyzer suggests a fix for each call\nto one of the functions before it is transformed, so that\n\n\tuse(varOf(123))\n\nis replaced by:\n\n\tuse(new(123))\n\nWrapper functions such as varOf are common when working with Go\nserialization packages such as for JSON or protobuf, where pointers\nare often used to express optionality.\n\n# Analyzer omitzero\n\nomitzero: suggest replacing omitempty with omitzero for struct fields\n\nThe omitzero analyzer identifies uses of the `omitempty` JSON struct\ntag on fields that are themselves structs. For struct-typed fields,\nthe `omitempty` tag has no effect on the behavior of json.Marshal and\njson.Unmarshal. The analyzer offers two suggestions: either remove the\ntag, or replace it with `omitzero` (added in Go 1.24), which correctly\nomits the field if the struct value is zero.\n\nHowever, some other serialization packages (notably kubebuilder, see\nhttps://book.kubebuilder.io/reference/markers.html) may have their own\ninterpretation of the `json:\",omitzero\"` tag, so removing it may affect\nprogram behavior. For this reason, the omitzero modernizer will not\nmake changes in any package that contains +kubebuilder annotations.\n\nReplacing `omitempty` with `omitzero` is a change in behavior. The\noriginal code would always encode the struct field, whereas the\nmodified code will omit it if it is a zero-value.\n\n# Analyzer plusbuild\n\nplusbuild: remove obsolete //+build comments\n\nThe plusbuild analyzer suggests a fix to remove obsolete build tags\nof the form:\n\n\t//+build linux,amd64\n\nin files that also contain a Go 1.18-style tag such as:\n\n\t//go:build linux && amd64\n\n(It does not check that the old and new tags are consistent;\nthat is the job of the 'buildtag' analyzer in the vet suite.)\n\n# Analyzer rangeint\n\nrangeint: replace 3-clause for loops with for-range over integers\n\nThe rangeint analyzer suggests replacing traditional for loops such\nas\n\n\tfor i := 0; i < n; i++ { ... }\n\nwith the more idiomatic Go 1.22 style:\n\n\tfor i := range n { ... }\n\nThis transformation is applied only if (a) the loop variable is not\nmodified within the loop body and (b) the loop's limit expression\nis not modified within the loop, as `for range` evaluates its\noperand only once.\n\n# Analyzer reflecttypefor\n\nreflecttypefor: replace reflect.TypeOf(x) with TypeFor[T]()\n\nThis analyzer suggests fixes to replace uses of reflect.TypeOf(x) with\nreflect.TypeFor, introduced in go1.22, when the desired runtime type\nis known at compile time, for example:\n\n\treflect.TypeOf(uint32(0))        -> reflect.TypeFor[uint32]()\n\treflect.TypeOf((*ast.File)(nil)) -> reflect.TypeFor[*ast.File]()\n\nIt also offers a fix to simplify the constructions below, which use\nreflect.TypeOf to return the runtime type for an interface type,\n\n\treflect.TypeOf((*io.Reader)(nil)).Elem()\n\nor:\n\n\treflect.TypeOf([]io.Reader(nil)).Elem()\n\nto:\n\n\treflect.TypeFor[io.Reader]()\n\nNo fix is offered in cases when the runtime type is dynamic, such as:\n\n\tvar r io.Reader = ...\n\treflect.TypeOf(r)\n\nor when the operand has potential side effects.\n\n# Analyzer slicescontains\n\nslicescontains: replace loops with slices.Contains or slices.ContainsFunc\n\nThe slicescontains analyzer simplifies loops that check for the existence of\nan element in a slice. It replaces them with calls to `slices.Contains` or\n`slices.ContainsFunc`, which were added in Go 1.21.\n\nIf the expression for the target element has side effects, this\ntransformation will cause those effects to occur only once, not\nonce per tested slice element.\n\n# Analyzer slicesdelete\n\nslicesdelete: replace append-based slice deletion with slices.Delete\n\nThe slicesdelete analyzer suggests replacing the idiom\n\n\ts = append(s[:i], s[j:]...)\n\nwith the more explicit\n\n\ts = slices.Delete(s, i, j)\n\nintroduced in Go 1.21.\n\nThis analyzer is disabled by default. The `slices.Delete` function\nzeros the elements between the new length and the old length of the\nslice to prevent memory leaks, which is a subtle difference in\nbehavior compared to the append-based idiom; see https://go.dev/issue/73686.\n\n# Analyzer slicessort\n\nslicessort: replace sort.Slice with slices.Sort for basic types\n\nThe slicessort analyzer simplifies sorting slices of basic ordered\ntypes. It replaces\n\n\tsort.Slice(s, func(i, j int) bool { return s[i] < s[j] })\n\nwith the simpler `slices.Sort(s)`, which was added in Go 1.21.\n\n# Analyzer stditerators\n\nstditerators: use iterators instead of Len/At-style APIs\n\nThis analyzer suggests a fix to replace each loop of the form:\n\n\tfor i := 0; i < x.Len(); i++ {\n\t\tuse(x.At(i))\n\t}\n\nor its \"for elem := range x.Len()\" equivalent by a range loop over an\niterator offered by the same data type:\n\n\tfor elem := range x.All() {\n\t\tuse(x.At(i)\n\t}\n\nwhere x is one of various well-known types in the standard library.\n\n# Analyzer stringscut\n\nstringscut: replace strings.Index etc. with strings.Cut\n\nThis analyzer replaces certain patterns of use of [strings.Index] and string slicing by [strings.Cut], added in go1.18.\n\nFor example:\n\n\tidx := strings.Index(s, substr)\n\tif idx >= 0 {\n\t    return s[:idx]\n\t}\n\nis replaced by:\n\n\tbefore, _, ok := strings.Cut(s, substr)\n\tif ok {\n\t    return before\n\t}\n\nAnd:\n\n\tidx := strings.Index(s, substr)\n\tif idx >= 0 {\n\t    return\n\t}\n\nis replaced by:\n\n\tfound := strings.Contains(s, substr)\n\tif found {\n\t    return\n\t}\n\nIt also handles variants using [strings.IndexByte] instead of Index, or the bytes package instead of strings.\n\nFixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.\n\n# Analyzer stringscutprefix\n\nstringscutprefix: replace HasPrefix/TrimPrefix with CutPrefix\n\nThe stringscutprefix analyzer simplifies a common pattern where code first\nchecks for a prefix with `strings.HasPrefix` and then removes it with\n`strings.TrimPrefix`. It replaces this two-step process with a single call\nto `strings.CutPrefix`, introduced in Go 1.20. The analyzer also handles\nthe equivalent functions in the `bytes` package.\n\nFor example, this input:\n\n\tif strings.HasPrefix(s, prefix) {\n\t    use(strings.TrimPrefix(s, prefix))\n\t}\n\nis fixed to:\n\n\tif after, ok := strings.CutPrefix(s, prefix); ok {\n\t    use(after)\n\t}\n\nThe analyzer also offers fixes to use CutSuffix in a similar way.\nThis input:\n\n\tif strings.HasSuffix(s, suffix) {\n\t    use(strings.TrimSuffix(s, suffix))\n\t}\n\nis fixed to:\n\n\tif before, ok := strings.CutSuffix(s, suffix); ok {\n\t    use(before)\n\t}\n\n# Analyzer stringsseq\n\nstringsseq: replace ranging over Split/Fields with SplitSeq/FieldsSeq\n\nThe stringsseq analyzer improves the efficiency of iterating over substrings.\nIt replaces\n\n\tfor range strings.Split(...)\n\nwith the more efficient\n\n\tfor range strings.SplitSeq(...)\n\nwhich was added in Go 1.24 and avoids allocating a slice for the\nsubstrings. The analyzer also handles strings.Fields and the\nequivalent functions in the bytes package.\n\n# Analyzer stringsbuilder\n\nstringsbuilder: replace += with strings.Builder\n\nThis analyzer replaces repeated string += string concatenation\noperations with calls to Go 1.10's strings.Builder.\n\nFor example:\n\n\tvar s = \"[\"\n\tfor x := range seq {\n\t\ts += x\n\t\ts += \".\"\n\t}\n\ts += \"]\"\n\tuse(s)\n\nis replaced by:\n\n\tvar s strings.Builder\n\ts.WriteString(\"[\")\n\tfor x := range seq {\n\t\ts.WriteString(x)\n\t\ts.WriteString(\".\")\n\t}\n\ts.WriteString(\"]\")\n\tuse(s.String())\n\nThis avoids quadratic memory allocation and improves performance.\n\nThe analyzer requires that all references to s before the final uses\nare += operations. To avoid warning about trivial cases, at least one\nmust appear within a loop. The variable s must be a local\nvariable, not a global or parameter.\n\nAll uses of the finished string must come after the last += operation.\nEach such use will be replaced by a call to strings.Builder's String method.\n(These may appear within an intervening loop or function literal, since even\nif s.String() is called repeatedly, it does not allocate memory.)\n\nOften the addend is a call to fmt.Sprintf, as in this example:\n\n\tvar s string\n\tfor x := range seq {\n\t\ts += fmt.Sprintf(\"%v\", x)\n\t}\n\nwhich, once the suggested fix is applied, becomes:\n\n\tvar s strings.Builder\n\tfor x := range seq {\n\t\ts.WriteString(fmt.Sprintf(\"%v\", x))\n\t}\n\nThe WriteString call can be further simplified to the more efficient\nfmt.Fprintf(&s, \"%v\", x), avoiding the allocation of an intermediary.\nHowever, stringsbuilder does not perform this simplification;\nit requires staticcheck analyzer QF1012. (See https://go.dev/issue/76918.)\n\n# Analyzer testingcontext\n\ntestingcontext: replace context.WithCancel with t.Context in tests\n\nThe testingcontext analyzer simplifies context management in tests. It\nreplaces the manual creation of a cancellable context,\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\nwith a single call to t.Context(), which was added in Go 1.24.\n\nThis change is only suggested if the `cancel` function is not used\nfor any other purpose.\n\n# Analyzer unsafefuncs\n\nunsafefuncs: replace unsafe pointer arithmetic with function calls\n\nThe unsafefuncs analyzer simplifies pointer arithmetic expressions by\nreplacing them with calls to helper functions such as unsafe.Add,\nadded in Go 1.17.\n\nExample:\n\n\tunsafe.Pointer(uintptr(ptr) + uintptr(n))\n\nwhere ptr is an unsafe.Pointer, is replaced by:\n\n\tunsafe.Add(ptr, n)\n\n# Analyzer waitgroupgo\n\nwaitgroupgo: replace wg.Add(1)/go/wg.Done() with wg.Go\n\nThe waitgroupgo analyzer simplifies goroutine management with `sync.WaitGroup`.\nIt replaces the common pattern\n\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\t...\n\t}()\n\nwith a single call to\n\n\twg.Go(func(){ ... })\n\nwhich was added in Go 1.25.\n*/\npackage modernize\n"
  },
  {
    "path": "go/analysis/passes/modernize/errorsastype.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"fmt\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar errorsastypeAnalyzer = &analysis.Analyzer{\n\tName:     \"errorsastype\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"errorsastype\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype\",\n\tRequires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},\n\tRun:      errorsastype,\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.ErrorsAsTypeModernizer = errorsastypeAnalyzer\n}\n\n// errorsastype offers a fix to replace error.As with the newer\n// errors.AsType[T] following this pattern:\n//\n//\tvar myerr *MyErr\n//\tif errors.As(err, &myerr) { ... }\n//\n// =>\n//\n//\tif myerr, ok := errors.AsType[*MyErr](err); ok  { ... }\n//\n// (In principle several of these can then be chained using if/else,\n// but we don't attempt that.)\n//\n// We offer the fix only within an if statement, but not within a\n// switch case such as:\n//\n//\tvar myerr *MyErr\n//\tswitch {\n//\tcase errors.As(err, &myerr):\n//\t}\n//\n// because the transformation in that case would be ungainly.\n//\n// Note that the cmd/vet suite includes the \"errorsas\" analyzer, which\n// detects actual mistakes in the use of errors.As. This logic does\n// not belong in errorsas because the problems it fixes are merely\n// stylistic.\n//\n// TODO(adonovan): support more cases:\n//\n//   - Negative cases\n//     var myerr E\n//     if !errors.As(err, &myerr) { ... }\n//     =>\n//     myerr, ok := errors.AsType[E](err)\n//     if !ok { ... }\n//\n// - if myerr := new(E); errors.As(err, myerr); { ... }\n//\n// - if errors.As(err, myerr) && othercond { ... }\nfunc errorsastype(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\tfor curCall := range index.Calls(index.Object(\"errors\", \"As\")) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tif len(call.Args) < 2 {\n\t\t\tcontinue // spread call: errors.As(pair())\n\t\t}\n\n\t\tv, curDeclStmt := canUseErrorsAsType(info, index, curCall)\n\t\tif v == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tfile := astutil.EnclosingFile(curDeclStmt)\n\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {\n\t\t\tcontinue // errors.AsType is too new\n\t\t}\n\n\t\t// Locate identifier \"As\" in errors.As.\n\t\tvar asIdent *ast.Ident\n\t\tswitch n := ast.Unparen(call.Fun).(type) {\n\t\tcase *ast.Ident:\n\t\t\tasIdent = n // \"errors\" was dot-imported\n\t\tcase *ast.SelectorExpr:\n\t\t\tasIdent = n.Sel\n\t\tdefault:\n\t\t\tpanic(\"no Ident for errors.As\")\n\t\t}\n\n\t\t// Format the type as valid Go syntax.\n\t\t// TODO(adonovan): fix: FileQualifier needs to respect\n\t\t// visibility at the current point, and either fail\n\t\t// or edit the imports as needed.\n\t\t// TODO(adonovan): fix: TypeString is not a sound way\n\t\t// to print types as Go syntax as it does not respect\n\t\t// symbol visibility, etc. We need something loosely\n\t\t// integrated with FileQualifier that accumulates\n\t\t// import edits, and may fail (e.g. for unexported\n\t\t// type or field names from other packages).\n\t\t// See https://go.dev/issues/75604.\n\t\tqual := typesinternal.FileQualifier(file, pass.Pkg)\n\t\terrtype := types.TypeString(v.Type(), qual)\n\n\t\t// Choose a name for the \"ok\" variable.\n\t\t// We generate a new name only if 'ok' is already declared at\n\t\t// curCall and it also used within the if-statement.\n\t\tcurIf := curCall.Parent()\n\t\tifScope := info.Scopes[curIf.Node().(*ast.IfStmt)]\n\t\tokName := freshName(info, index, ifScope, v.Pos(), curCall, curIf, token.NoPos, \"ok\")\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Fun.Pos(),\n\t\t\tEnd:     call.Fun.End(),\n\t\t\tMessage: fmt.Sprintf(\"errors.As can be simplified using AsType[%s]\", errtype),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: fmt.Sprintf(\"Replace errors.As with AsType[%s]\", errtype),\n\t\t\t\tTextEdits: append(\n\t\t\t\t\t// delete \"var myerr *MyErr\"\n\t\t\t\t\trefactor.DeleteStmt(pass.Fset.File(call.Fun.Pos()), curDeclStmt),\n\t\t\t\t\t// if              errors.As            (err, &myerr)     { ... }\n\t\t\t\t\t//    -------------       --------------    -------- ----\n\t\t\t\t\t// if myerr, ok := errors.AsType[*MyErr](err        ); ok { ... }\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\t// insert \"myerr, ok := \"\n\t\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\t\tEnd:     call.Pos(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s, %s := \", v.Name(), okName),\n\t\t\t\t\t},\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\t// replace As with AsType[T]\n\t\t\t\t\t\tPos:     asIdent.Pos(),\n\t\t\t\t\t\tEnd:     asIdent.End(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"AsType[%s]\", errtype),\n\t\t\t\t\t},\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\t// delete \", &myerr\"\n\t\t\t\t\t\tPos: call.Args[0].End(),\n\t\t\t\t\t\tEnd: call.Args[1].End(),\n\t\t\t\t\t},\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\t// insert \"; ok\"\n\t\t\t\t\t\tPos:     call.End(),\n\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"; %s\", okName),\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil, nil\n}\n\n// canUseErrorsAsType reports whether curCall is a call to\n// errors.As beneath an if statement, preceded by a\n// declaration of the typed error var. The var must not be\n// used outside the if statement.\nfunc canUseErrorsAsType(info *types.Info, index *typeindex.Index, curCall inspector.Cursor) (_ *types.Var, _ inspector.Cursor) {\n\tif curCall.ParentEdgeKind() != edge.IfStmt_Cond {\n\t\treturn // not beneath if statement\n\t}\n\tvar (\n\t\tcurIfStmt = curCall.Parent()\n\t\tifStmt    = curIfStmt.Node().(*ast.IfStmt)\n\t)\n\tif ifStmt.Init != nil {\n\t\treturn // if statement already has an init part\n\t}\n\tunary, ok := curCall.Node().(*ast.CallExpr).Args[1].(*ast.UnaryExpr)\n\tif !ok || unary.Op != token.AND {\n\t\treturn // 2nd arg is not &var\n\t}\n\tid, ok := unary.X.(*ast.Ident)\n\tif !ok {\n\t\treturn // not a simple ident (local var)\n\t}\n\tv := info.Uses[id].(*types.Var)\n\tcurDef, ok := index.Def(v)\n\tif !ok {\n\t\treturn // var is not local (e.g. dot-imported)\n\t}\n\t// Have: if errors.As(err, &v) { ... }\n\n\t// Reject if v is used outside (before or after) the\n\t// IfStmt, since that will become its new scope.\n\tfor curUse := range index.Uses(v) {\n\t\tif !curIfStmt.Contains(curUse) {\n\t\t\treturn // v used before/after if statement\n\t\t}\n\t}\n\tif curDef.ParentEdgeKind() != edge.ValueSpec_Names {\n\t\treturn // v not declared by \"var v T\"\n\t}\n\tvar (\n\t\tcurSpec = curDef.Parent()  // ValueSpec\n\t\tcurDecl = curSpec.Parent() // GenDecl\n\t\tspec    = curSpec.Node().(*ast.ValueSpec)\n\t)\n\tif len(spec.Names) != 1 || len(spec.Values) != 0 ||\n\t\tlen(curDecl.Node().(*ast.GenDecl).Specs) != 1 {\n\t\treturn // not a simple \"var v T\" decl\n\t}\n\n\t// Have:\n\t//   var v *MyErr\n\t//   ...\n\t//   if errors.As(err, &v) { ... }\n\t// with no uses of v outside the IfStmt.\n\treturn v, curDecl.Parent() // DeclStmt\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/fmtappendf.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/fmtstr\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar FmtAppendfAnalyzer = &analysis.Analyzer{\n\tName: \"fmtappendf\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"fmtappendf\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: fmtappendf,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#fmtappendf\",\n}\n\n// The fmtappend function replaces []byte(fmt.Sprintf(...)) by\n// fmt.Appendf(nil, ...), and similarly for Sprint, Sprintln.\nfunc fmtappendf(pass *analysis.Pass) (any, error) {\n\tindex := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\tfor _, fn := range []types.Object{\n\t\tindex.Object(\"fmt\", \"Sprintf\"),\n\t\tindex.Object(\"fmt\", \"Sprintln\"),\n\t\tindex.Object(\"fmt\", \"Sprint\"),\n\t} {\n\t\tfor curCall := range index.Calls(fn) {\n\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\tif ek, idx := curCall.ParentEdge(); ek == edge.CallExpr_Args && idx == 0 {\n\t\t\t\t// Is parent a T(fmt.SprintX(...)) conversion?\n\t\t\t\tconv := curCall.Parent().Node().(*ast.CallExpr)\n\t\t\t\tinfo := pass.TypesInfo\n\t\t\t\ttv := info.Types[conv.Fun]\n\t\t\t\tif tv.IsType() && types.Identical(tv.Type, byteSliceType) {\n\t\t\t\t\t// Have: []byte(fmt.SprintX(...))\n\t\t\t\t\tif len(call.Args) == 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// fmt.Sprint(f) and fmt.Append(f) have different nil semantics\n\t\t\t\t\t// when the format produces an empty string:\n\t\t\t\t\t// []byte(fmt.Sprintf(\"\")) returns an empty but non-nil\n\t\t\t\t\t// []byte{}, while fmt.Appendf(nil, \"\") returns nil) so we\n\t\t\t\t\t// should skip these cases.\n\t\t\t\t\tif fn.Name() == \"Sprint\" || fn.Name() == \"Sprintf\" {\n\t\t\t\t\t\tformat := info.Types[call.Args[0]].Value\n\t\t\t\t\t\tif format != nil && mayFormatEmpty(constant.StringVal(format)) {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Find \"Sprint\" identifier.\n\t\t\t\t\tvar id *ast.Ident\n\t\t\t\t\tswitch e := ast.Unparen(call.Fun).(type) {\n\t\t\t\t\tcase *ast.SelectorExpr:\n\t\t\t\t\t\tid = e.Sel // \"fmt.Sprint\"\n\t\t\t\t\tcase *ast.Ident:\n\t\t\t\t\t\tid = e // \"Sprint\" after `import . \"fmt\"`\n\t\t\t\t\t}\n\n\t\t\t\t\told, new := fn.Name(), strings.Replace(fn.Name(), \"Sprint\", \"Append\", 1)\n\t\t\t\t\tedits := []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Delete \"[]byte(\", including any spaces before the first argument.\n\t\t\t\t\t\t\tPos: conv.Pos(),\n\t\t\t\t\t\t\tEnd: conv.Args[0].Pos(), // always exactly one argument in a valid byte slice conversion\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Delete \")\", including any non-args (space or\n\t\t\t\t\t\t\t// commas) that come before the right parenthesis.\n\t\t\t\t\t\t\t// Leaving an extra comma here produces invalid\n\t\t\t\t\t\t\t// code. (See golang/go#74709)\n\t\t\t\t\t\t\t// Unfortunately, this and the edit above may result\n\t\t\t\t\t\t\t// in deleting some comments.\n\t\t\t\t\t\t\tPos: conv.Args[0].End(),\n\t\t\t\t\t\t\tEnd: conv.Rparen + 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     id.Pos(),\n\t\t\t\t\t\t\tEnd:     id.End(),\n\t\t\t\t\t\t\tNewText: []byte(new),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     call.Lparen + 1,\n\t\t\t\t\t\t\tNewText: []byte(\"nil, \"),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t\tif !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curCall), versions.Go1_19) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     conv.Pos(),\n\t\t\t\t\t\tEnd:     conv.End(),\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace []byte(fmt.%s...) with fmt.%s\", old, new),\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage:   fmt.Sprintf(\"Replace []byte(fmt.%s...) with fmt.%s\", old, new),\n\t\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// mayFormatEmpty reports whether fmt.Sprintf might produce an empty string.\n// It returns false in the following two cases:\n//  1. formatStr contains non-operation characters.\n//  2. formatStr contains formatting verbs besides s, v, x, X (verbs which may\n//     produce empty results)\n//\n// In all other cases it returns true.\nfunc mayFormatEmpty(formatStr string) bool {\n\tif formatStr == \"\" {\n\t\treturn true\n\t}\n\toperations, err := fmtstr.Parse(formatStr, 0)\n\tif err != nil {\n\t\t// If formatStr is malformed, the printf analyzer will report a\n\t\t// diagnostic, so we can ignore this error.\n\t\t// Calling Parse on a string without % formatters also returns an error,\n\t\t// in which case we can safely return false.\n\t\treturn false\n\t}\n\ttotalOpsLen := 0\n\tfor _, op := range operations {\n\t\ttotalOpsLen += len(op.Text)\n\t\tif !strings.ContainsRune(\"svxX\", rune(op.Verb.Verb)) && op.Prec.Fixed != 0 {\n\t\t\t// A non [s, v, x, X] formatter with non-zero precision cannot\n\t\t\t// produce an empty string.\n\t\t\treturn false\n\t\t}\n\t}\n\t// If the format string contains non-operation characters, it cannot produce\n\t// the empty string.\n\tif totalOpsLen != len(formatStr) {\n\t\treturn false\n\t}\n\t// If we get here, it means that all formatting verbs are %s, %v, %x, %X,\n\t// and there are no additional non-operation characters. We conservatively\n\t// report that this may format as an empty string, ignoring uses of\n\t// precision and the values of the formatter args.\n\treturn true\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/forvar.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar ForVarAnalyzer = &analysis.Analyzer{\n\tName:     \"forvar\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"forvar\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      forvar,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar\",\n}\n\n// forvar offers to fix unnecessary copying of a for variable\n//\n//\tfor _, x := range foo {\n//\t\tx := x // offer to remove this superfluous assignment\n//\t}\n//\n// Prerequisites:\n// First statement in a range loop has to be <ident> := <ident>\n// where the two idents are the same,\n// and the ident is defined (:=) as a variable in the for statement.\n// (Note that this 'fix' does not work for three clause loops\n// because the Go spec says \"The variable used by each subsequent iteration\n// is declared implicitly before executing the post statement and initialized to the\n// value of the previous iteration's variable at that moment.\")\n//\n// Variant: same thing in an IfStmt.Init, when the IfStmt is the sole\n// loop body statement:\n//\n//\tfor _, x := range foo {\n//\t\tif x := x; cond { ... }\n//\t}\n//\n// (The restriction is necessary to avoid potential problems arising\n// from merging two distinct variables.)\n//\n// This analyzer is synergistic with stditerators,\n// which may create redundant \"x := x\" statements.\nfunc forvar(pass *analysis.Pass) (any, error) {\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_22) {\n\t\tfor curLoop := range curFile.Preorder((*ast.RangeStmt)(nil)) {\n\t\t\tloop := curLoop.Node().(*ast.RangeStmt)\n\t\t\tif loop.Tok != token.DEFINE {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tisLoopVarRedecl := func(stmt ast.Stmt) bool {\n\t\t\t\tif assign, ok := stmt.(*ast.AssignStmt); ok &&\n\t\t\t\t\tassign.Tok == token.DEFINE &&\n\t\t\t\t\tlen(assign.Lhs) == len(assign.Rhs) {\n\n\t\t\t\t\tfor i, lhs := range assign.Lhs {\n\t\t\t\t\t\tif !(astutil.EqualSyntax(lhs, assign.Rhs[i]) &&\n\t\t\t\t\t\t\t(astutil.EqualSyntax(lhs, loop.Key) ||\n\t\t\t\t\t\t\t\tastutil.EqualSyntax(lhs, loop.Value))) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Have: for k, v := range x { stmts }\n\t\t\t//\n\t\t\t// Delete the prefix of stmts that are\n\t\t\t// of the form k := k; v := v; k, v := k, v; v, k := v, k.\n\t\t\tfor _, stmt := range loop.Body.List {\n\t\t\t\tif isLoopVarRedecl(stmt) {\n\t\t\t\t\t// { x := x; ... }\n\t\t\t\t\t//   ------\n\t\t\t\t} else if ifstmt, ok := stmt.(*ast.IfStmt); ok &&\n\t\t\t\t\tifstmt.Init != nil &&\n\t\t\t\t\tlen(loop.Body.List) == 1 && // must be sole statement in loop body\n\t\t\t\t\tisLoopVarRedecl(ifstmt.Init) {\n\t\t\t\t\t// if x := x; cond {\n\t\t\t\t\t//    ------\n\t\t\t\t\tstmt = ifstmt.Init\n\t\t\t\t} else {\n\t\t\t\t\tbreak // stop at first other statement\n\t\t\t\t}\n\n\t\t\t\tcurStmt, _ := curLoop.FindNode(stmt)\n\t\t\t\tedits := refactor.DeleteStmt(pass.Fset.File(stmt.Pos()), curStmt)\n\t\t\t\tif len(edits) > 0 {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     stmt.Pos(),\n\t\t\t\t\t\tEnd:     stmt.End(),\n\t\t\t\t\t\tMessage: \"copying variable is unneeded\",\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage:   \"Remove unneeded redeclaration\",\n\t\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/maps.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\n// This file defines modernizers that use the \"maps\" package.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar MapsLoopAnalyzer = &analysis.Analyzer{\n\tName:     \"mapsloop\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"mapsloop\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      mapsloop,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop\",\n}\n\n// The mapsloop pass offers to simplify a loop of map insertions:\n//\n//\tfor k, v := range x {\n//\t\tm[k] = v\n//\t}\n//\n// by a call to go1.23's maps package. There are four variants, the\n// product of two axes: whether the source x is a map or an iter.Seq2,\n// and whether the destination m is a newly created map:\n//\n//\tmaps.Copy(m, x)\t\t(x is map)\n//\tmaps.Insert(m, x)       (x is iter.Seq2)\n//\tm = maps.Clone(x)       (x is a non-nil map, m is a new map)\n//\tm = maps.Collect(x)     (x is iter.Seq2, m is a new map)\n//\n// A map is newly created if the preceding statement has one of these\n// forms, where M is a map type:\n//\n//\tm = make(M)\n//\tm = M{}\nfunc mapsloop(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"maps\", \"bytes\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tinfo := pass.TypesInfo\n\n\t// check is called for each statement of this form:\n\t//   for k, v := range x { m[k] = v }\n\tcheck := func(file *ast.File, curRange inspector.Cursor, assign *ast.AssignStmt, m, x ast.Expr) {\n\n\t\t// Is x a map or iter.Seq2?\n\t\ttx := types.Unalias(info.TypeOf(x))\n\t\tvar xmap bool\n\t\tswitch typeparams.CoreType(tx).(type) {\n\t\tcase *types.Map:\n\t\t\txmap = true\n\n\t\tcase *types.Signature:\n\t\t\tk, v, ok := assignableToIterSeq2(tx)\n\t\t\tif !ok {\n\t\t\t\treturn // a named isomer of Seq2\n\t\t\t}\n\t\t\txmap = false\n\n\t\t\t// Record in tx the unnamed map[K]V type\n\t\t\t// derived from the yield function.\n\t\t\t// This is the type of maps.Collect(x).\n\t\t\ttx = types.NewMap(k, v)\n\n\t\tdefault:\n\t\t\treturn // e.g. slice, channel (or no core type!)\n\t\t}\n\n\t\t// Is the preceding statement of the form\n\t\t//    m = make(M) or M{}\n\t\t// and can we replace its RHS with slices.{Clone,Collect}?\n\t\t//\n\t\t// Beware: if x may be nil, we cannot use Clone as it preserves nilness.\n\t\tvar mrhs ast.Expr // make(M) or M{}, or nil\n\t\tif curPrev, ok := curRange.PrevSibling(); ok {\n\t\t\tif assign, ok := curPrev.Node().(*ast.AssignStmt); ok &&\n\t\t\t\tlen(assign.Lhs) == 1 &&\n\t\t\t\tlen(assign.Rhs) == 1 &&\n\t\t\t\tastutil.EqualSyntax(assign.Lhs[0], m) {\n\n\t\t\t\t// Have: m = rhs; for k, v := range x { m[k] = v }\n\t\t\t\tvar newMap bool\n\t\t\t\trhs := assign.Rhs[0]\n\t\t\t\tswitch rhs := ast.Unparen(rhs).(type) {\n\t\t\t\tcase *ast.CallExpr:\n\t\t\t\t\tif id, ok := ast.Unparen(rhs.Fun).(*ast.Ident); ok &&\n\t\t\t\t\t\tinfo.Uses[id] == builtinMake {\n\t\t\t\t\t\t// Have: m = make(...)\n\t\t\t\t\t\tnewMap = true\n\t\t\t\t\t}\n\t\t\t\tcase *ast.CompositeLit:\n\t\t\t\t\tif len(rhs.Elts) == 0 {\n\t\t\t\t\t\t// Have m = M{}\n\t\t\t\t\t\tnewMap = true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Take care not to change type of m's RHS expression.\n\t\t\t\tif newMap {\n\t\t\t\t\ttrhs := info.TypeOf(rhs)\n\n\t\t\t\t\t// Inv: tx is the type of maps.F(x)\n\t\t\t\t\t// - maps.Clone(x) has the same type as x.\n\t\t\t\t\t// - maps.Collect(x) returns an unnamed map type.\n\n\t\t\t\t\tif assign.Tok == token.DEFINE {\n\t\t\t\t\t\t// DEFINE (:=): we must not\n\t\t\t\t\t\t// change the type of RHS.\n\t\t\t\t\t\tif types.Identical(tx, trhs) {\n\t\t\t\t\t\t\tmrhs = rhs\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// ASSIGN (=): the types of LHS\n\t\t\t\t\t\t// and RHS may differ in namedness.\n\t\t\t\t\t\tif types.AssignableTo(tx, trhs) {\n\t\t\t\t\t\t\tmrhs = rhs\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Temporarily disable the transformation to the\n\t\t\t\t\t// (nil-preserving) maps.Clone until we can prove\n\t\t\t\t\t// that x is non-nil. This is rarely possible,\n\t\t\t\t\t// and may require control flow analysis\n\t\t\t\t\t// (e.g. a dominating \"if len(x)\" check).\n\t\t\t\t\t// See #71844.\n\t\t\t\t\tif xmap {\n\t\t\t\t\t\tmrhs = nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Choose function.\n\t\tvar funcName string\n\t\tif mrhs != nil {\n\t\t\tfuncName = cond(xmap, \"Clone\", \"Collect\")\n\t\t} else {\n\t\t\tfuncName = cond(xmap, \"Copy\", \"Insert\")\n\t\t}\n\n\t\t// Report diagnostic, and suggest fix.\n\t\trng := curRange.Node()\n\t\tprefix, importEdits := refactor.AddImport(info, file, \"maps\", \"maps\", funcName, rng.Pos())\n\t\tvar (\n\t\t\tnewText    []byte\n\t\t\tstart, end token.Pos\n\t\t)\n\t\tif mrhs != nil {\n\t\t\t// Replace assignment and loop with expression.\n\t\t\t//\n\t\t\t//   m = make(...)\n\t\t\t//   for k, v := range x { /* comments */ m[k] = v }\n\t\t\t//\n\t\t\t//   ->\n\t\t\t//\n\t\t\t//   /* comments */\n\t\t\t//   m = maps.Copy(x)\n\t\t\tcurPrev, _ := curRange.PrevSibling()\n\t\t\tstart, end = curPrev.Node().Pos(), rng.End()\n\t\t\tnewText = fmt.Appendf(nil, \"%s%s = %s%s(%s)\",\n\t\t\t\tallComments(file, start, end),\n\t\t\t\tastutil.Format(pass.Fset, m),\n\t\t\t\tprefix,\n\t\t\t\tfuncName,\n\t\t\t\tastutil.Format(pass.Fset, x))\n\t\t} else {\n\t\t\t// Replace loop with call statement.\n\t\t\t//\n\t\t\t//   for k, v := range x { /* comments */ m[k] = v }\n\t\t\t//\n\t\t\t//   ->\n\t\t\t//\n\t\t\t//   /* comments */\n\t\t\t//   maps.Copy(m, x)\n\t\t\tstart, end = rng.Pos(), rng.End()\n\t\t\tnewText = fmt.Appendf(nil, \"%s%s%s(%s, %s)\",\n\t\t\t\tallComments(file, start, end),\n\t\t\t\tprefix,\n\t\t\t\tfuncName,\n\t\t\t\tastutil.Format(pass.Fset, m),\n\t\t\t\tastutil.Format(pass.Fset, x))\n\t\t}\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     assign.Lhs[0].Pos(),\n\t\t\tEnd:     assign.Lhs[0].End(),\n\t\t\tMessage: \"Replace m[k]=v loop with maps.\" + funcName,\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Replace m[k]=v loop with maps.\" + funcName,\n\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{{\n\t\t\t\t\tPos:     start,\n\t\t\t\t\tEnd:     end,\n\t\t\t\t\tNewText: newText,\n\t\t\t\t}}...),\n\t\t\t}},\n\t\t})\n\n\t}\n\n\t// Find all range loops around m[k] = v.\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_23) {\n\t\tfile := curFile.Node().(*ast.File)\n\n\t\tfor curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {\n\t\t\trng := curRange.Node().(*ast.RangeStmt)\n\n\t\t\tif rng.Tok == token.DEFINE &&\n\t\t\t\trng.Key != nil &&\n\t\t\t\trng.Value != nil &&\n\t\t\t\tisAssignBlock(rng.Body) {\n\t\t\t\t// Have: for k, v := range x { lhs = rhs }\n\n\t\t\t\tassign := rng.Body.List[0].(*ast.AssignStmt)\n\n\t\t\t\t// usesKV reports whether e references vars k or v.\n\t\t\t\tusesKV := func(e ast.Expr) bool {\n\t\t\t\t\tk := info.Defs[rng.Key.(*ast.Ident)]\n\t\t\t\t\tv := info.Defs[rng.Value.(*ast.Ident)]\n\t\t\t\t\tfor n := range ast.Preorder(e) {\n\t\t\t\t\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\t\t\t\t\tobj := info.Uses[id]\n\t\t\t\t\t\t\tif obj != nil && // don't rely on k, v being non-nil\n\t\t\t\t\t\t\t\t(obj == k || obj == v) {\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false\n\t\t\t\t}\n\n\t\t\t\tif index, ok := assign.Lhs[0].(*ast.IndexExpr); ok &&\n\t\t\t\t\tlen(assign.Lhs) == 1 &&\n\t\t\t\t\tastutil.EqualSyntax(rng.Key, index.Index) &&\n\t\t\t\t\tastutil.EqualSyntax(rng.Value, assign.Rhs[0]) &&\n\t\t\t\t\t!usesKV(index.X) { // reject (e.g.) f(k, v)[k] = v\n\t\t\t\t\tif tmap, ok := typeparams.CoreType(info.TypeOf(index.X)).(*types.Map); ok &&\n\t\t\t\t\t\ttypes.Identical(info.TypeOf(index), info.TypeOf(rng.Value)) && // m[k], v\n\t\t\t\t\t\ttypes.Identical(tmap.Key(), info.TypeOf(rng.Key)) {\n\n\t\t\t\t\t\t// Have: for k, v := range x { m[k] = v }\n\t\t\t\t\t\t// where there is no implicit conversion\n\t\t\t\t\t\t// of either key or value.\n\t\t\t\t\t\tcheck(file, curRange, assign, index.X, rng.X)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// assignableToIterSeq2 reports whether t is assignable to\n// iter.Seq[K, V] and returns K and V if so.\nfunc assignableToIterSeq2(t types.Type) (k, v types.Type, ok bool) {\n\t// The only named type assignable to iter.Seq2 is iter.Seq2.\n\tif is[*types.Named](t) {\n\t\tif !typesinternal.IsTypeNamed(t, \"iter\", \"Seq2\") {\n\t\t\treturn\n\t\t}\n\t\tt = t.Underlying()\n\t}\n\n\tif t, ok := t.(*types.Signature); ok {\n\t\t// func(yield func(K, V) bool)?\n\t\tif t.Params().Len() == 1 && t.Results().Len() == 0 {\n\t\t\tif yield, ok := t.Params().At(0).Type().(*types.Signature); ok { // sic, no Underlying/CoreType\n\t\t\t\tif yield.Params().Len() == 2 &&\n\t\t\t\t\tyield.Results().Len() == 1 &&\n\t\t\t\t\ttypes.Identical(yield.Results().At(0).Type(), builtinBool.Type()) {\n\t\t\t\t\treturn yield.Params().At(0).Type(), yield.Params().At(1).Type(), true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/minmax.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar MinMaxAnalyzer = &analysis.Analyzer{\n\tName: \"minmax\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"minmax\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: minmax,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#minmax\",\n}\n\n// The minmax pass replaces if/else statements with calls to min or max,\n// and removes user-defined min/max functions that are equivalent to built-ins.\n//\n// If/else replacement patterns:\n//\n//  1. if a < b { x = a } else { x = b }        =>      x = min(a, b)\n//  2. x = a; if a < b { x = b }                =>      x = max(a, b)\n//\n// Pattern 1 requires that a is not NaN, and pattern 2 requires that b\n// is not Nan. Since this is hard to prove, we reject floating-point\n// numbers.\n//\n// Function removal:\n// User-defined min/max functions are suggested for removal if they may\n// be safely replaced by their built-in namesake.\n//\n// Variants:\n// - all four ordered comparisons\n// - \"x := a\" or \"x = a\" or \"var x = a\" in pattern 2\n// - \"x < b\" or \"a < b\" in pattern 2\nfunc minmax(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tinfo    = pass.TypesInfo\n\t)\n\t// Check for user-defined min/max functions that can be removed\n\tcheckUserDefinedMinMax(pass)\n\n\t// check is called for all statements of this form:\n\t//   if a < b { lhs = rhs }\n\tcheck := func(file *ast.File, curIfStmt inspector.Cursor, compare *ast.BinaryExpr) {\n\t\tvar (\n\t\t\tifStmt  = curIfStmt.Node().(*ast.IfStmt)\n\t\t\ttassign = ifStmt.Body.List[0].(*ast.AssignStmt)\n\t\t\ta       = compare.X\n\t\t\tb       = compare.Y\n\t\t\tlhs     = tassign.Lhs[0]\n\t\t\trhs     = tassign.Rhs[0]\n\t\t\tsign    = isInequality(compare.Op)\n\n\t\t\t// callArg formats a call argument, preserving comments from [start-end).\n\t\t\tcallArg = func(arg ast.Expr, start, end token.Pos) string {\n\t\t\t\tcomments := allComments(file, start, end)\n\t\t\t\treturn cond(arg == b, \", \", \"\") + // second argument needs a comma\n\t\t\t\t\tcond(comments != \"\", \"\\n\", \"\") + // comments need their own line\n\t\t\t\t\tcomments +\n\t\t\t\t\tastutil.Format(pass.Fset, arg)\n\t\t\t}\n\t\t)\n\n\t\tif fblock, ok := ifStmt.Else.(*ast.BlockStmt); ok && isAssignBlock(fblock) {\n\t\t\tfassign := fblock.List[0].(*ast.AssignStmt)\n\n\t\t\t// Have: if a < b { lhs = rhs } else { lhs2 = rhs2 }\n\t\t\tlhs2 := fassign.Lhs[0]\n\t\t\trhs2 := fassign.Rhs[0]\n\n\t\t\t// For pattern 1, check that:\n\t\t\t// - lhs = lhs2\n\t\t\t// - {rhs,rhs2} = {a,b}\n\t\t\tif astutil.EqualSyntax(lhs, lhs2) {\n\t\t\t\tif astutil.EqualSyntax(rhs, a) && astutil.EqualSyntax(rhs2, b) {\n\t\t\t\t\tsign = +sign\n\t\t\t\t} else if astutil.EqualSyntax(rhs2, a) && astutil.EqualSyntax(rhs, b) {\n\t\t\t\t\tsign = -sign\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tsym := cond(sign < 0, \"min\", \"max\")\n\n\t\t\t\tif !is[*types.Builtin](lookup(pass.TypesInfo, curIfStmt, sym)) {\n\t\t\t\t\treturn // min/max function is shadowed\n\t\t\t\t}\n\t\t\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_21) {\n\t\t\t\t\treturn // min/max is too new\n\t\t\t\t}\n\n\t\t\t\t// pattern 1\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): if lhs is declared \"var lhs T\" on preceding line,\n\t\t\t\t// simplify the whole thing to \"lhs := min(a, b)\".\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t// Highlight the condition a < b.\n\t\t\t\t\tPos:     compare.Pos(),\n\t\t\t\t\tEnd:     compare.End(),\n\t\t\t\t\tMessage: fmt.Sprintf(\"if/else statement can be modernized using %s\", sym),\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace if statement with %s\", sym),\n\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t// Replace IfStmt with lhs = min(a, b).\n\t\t\t\t\t\t\tPos: ifStmt.Pos(),\n\t\t\t\t\t\t\tEnd: ifStmt.End(),\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s = %s(%s%s)\",\n\t\t\t\t\t\t\t\tastutil.Format(pass.Fset, lhs),\n\t\t\t\t\t\t\t\tsym,\n\t\t\t\t\t\t\t\tcallArg(a, ifStmt.Pos(), ifStmt.Else.Pos()),\n\t\t\t\t\t\t\t\tcallArg(b, ifStmt.Else.Pos(), ifStmt.End()),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}},\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\n\t\t} else if prev, ok := curIfStmt.PrevSibling(); ok && isSimpleAssign(prev.Node()) && ifStmt.Else == nil {\n\t\t\tfassign := prev.Node().(*ast.AssignStmt)\n\n\t\t\t// Have: lhs0 = rhs0; if a < b { lhs = rhs }\n\t\t\t//\n\t\t\t// For pattern 2, check that\n\t\t\t// - lhs = lhs0\n\t\t\t// - {a,b} = {rhs,rhs0} or {rhs,lhs0}\n\t\t\t//   The replacement must use rhs0 not lhs0 though.\n\t\t\t//   For example, we accept this variant:\n\t\t\t//     lhs = x; if lhs < y { lhs = y }   =>   lhs = min(x, y), not min(lhs, y)\n\t\t\t//\n\t\t\t// TODO(adonovan): accept \"var lhs0 = rhs0\" form too.\n\t\t\tlhs0 := fassign.Lhs[0]\n\t\t\trhs0 := fassign.Rhs[0]\n\n\t\t\t// If the assignment occurs within a select\n\t\t\t// comms clause (like \"case lhs0 := <-rhs0:\"),\n\t\t\t// there's no way of rewriting it into a min/max call.\n\t\t\tif prev.ParentEdgeKind() == edge.CommClause_Comm {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif astutil.EqualSyntax(lhs, lhs0) {\n\t\t\t\tif astutil.EqualSyntax(rhs, a) && (astutil.EqualSyntax(rhs0, b) || astutil.EqualSyntax(lhs0, b)) {\n\t\t\t\t\tsign = +sign\n\t\t\t\t} else if (astutil.EqualSyntax(rhs0, a) || astutil.EqualSyntax(lhs0, a)) && astutil.EqualSyntax(rhs, b) {\n\t\t\t\t\tsign = -sign\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsym := cond(sign < 0, \"min\", \"max\")\n\n\t\t\t\tif !is[*types.Builtin](lookup(pass.TypesInfo, curIfStmt, sym)) {\n\t\t\t\t\treturn // min/max function is shadowed\n\t\t\t\t}\n\n\t\t\t\t// Permit lhs0 to stand for rhs0 in the matching,\n\t\t\t\t// but don't actually reduce to lhs0 = min(lhs0, rhs)\n\t\t\t\t// since the \"=\" could be a \":=\". Use min(rhs0, rhs).\n\t\t\t\tif astutil.EqualSyntax(lhs0, a) {\n\t\t\t\t\ta = rhs0\n\t\t\t\t} else if astutil.EqualSyntax(lhs0, b) {\n\t\t\t\t\tb = rhs0\n\t\t\t\t}\n\n\t\t\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_21) {\n\t\t\t\t\treturn // min/max is too new\n\t\t\t\t}\n\n\t\t\t\t// pattern 2\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t// Highlight the condition a < b.\n\t\t\t\t\tPos:     compare.Pos(),\n\t\t\t\t\tEnd:     compare.End(),\n\t\t\t\t\tMessage: fmt.Sprintf(\"if statement can be modernized using %s\", sym),\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace if/else with %s\", sym),\n\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\tPos: fassign.Pos(),\n\t\t\t\t\t\t\tEnd: ifStmt.End(),\n\t\t\t\t\t\t\t// Replace \"x := a; if ... {}\" with \"x = min(...)\", preserving comments.\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s %s %s(%s%s)\",\n\t\t\t\t\t\t\t\tastutil.Format(pass.Fset, lhs),\n\t\t\t\t\t\t\t\tfassign.Tok.String(),\n\t\t\t\t\t\t\t\tsym,\n\t\t\t\t\t\t\t\tcallArg(a, fassign.Pos(), ifStmt.Pos()),\n\t\t\t\t\t\t\t\tcallArg(b, ifStmt.Pos(), ifStmt.End()),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}},\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find all \"if a < b { lhs = rhs }\" statements.\n\tfor curIfStmt := range inspect.Root().Preorder((*ast.IfStmt)(nil)) {\n\t\tifStmt := curIfStmt.Node().(*ast.IfStmt)\n\t\t// Don't bother handling \"if a < b { lhs = rhs }\" when it appears\n\t\t// as the \"else\" branch of another if-statement.\n\t\t//    if cond { ... } else if a < b { lhs = rhs }\n\t\t// (This case would require introducing another block\n\t\t//    if cond { ... } else { if a < b { lhs = rhs } }\n\t\t// and checking that there is no following \"else\".)\n\t\tif curIfStmt.ParentEdgeKind() == edge.IfStmt_Else {\n\t\t\tcontinue\n\t\t}\n\n\t\tif compare, ok := ifStmt.Cond.(*ast.BinaryExpr); ok &&\n\t\t\tifStmt.Init == nil &&\n\t\t\tisInequality(compare.Op) != 0 &&\n\t\t\tisAssignBlock(ifStmt.Body) {\n\t\t\t// a blank var has no type.\n\t\t\tif tLHS := info.TypeOf(ifStmt.Body.List[0].(*ast.AssignStmt).Lhs[0]); tLHS != nil && !maybeNaN(tLHS) {\n\t\t\t\t// Have: if a < b { lhs = rhs }\n\t\t\t\tcheck(astutil.EnclosingFile(curIfStmt), curIfStmt, compare)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// allComments collects all the comments from start to end.\nfunc allComments(file *ast.File, start, end token.Pos) string {\n\tvar buf strings.Builder\n\tfor co := range astutil.Comments(file, start, end) {\n\t\t_, _ = fmt.Fprintf(&buf, \"%s\\n\", co.Text)\n\t}\n\treturn buf.String()\n}\n\n// isInequality reports non-zero if tok is one of < <= => >:\n// +1 for > and -1 for <.\nfunc isInequality(tok token.Token) int {\n\tswitch tok {\n\tcase token.LEQ, token.LSS:\n\t\treturn -1\n\tcase token.GEQ, token.GTR:\n\t\treturn +1\n\t}\n\treturn 0\n}\n\n// isAssignBlock reports whether b is a block of the form { lhs = rhs }.\nfunc isAssignBlock(b *ast.BlockStmt) bool {\n\tif len(b.List) != 1 {\n\t\treturn false\n\t}\n\t// Inv: the sole statement cannot be { lhs := rhs }.\n\treturn isSimpleAssign(b.List[0])\n}\n\n// isSimpleAssign reports whether n has the form \"lhs = rhs\" or \"lhs := rhs\".\nfunc isSimpleAssign(n ast.Node) bool {\n\tassign, ok := n.(*ast.AssignStmt)\n\treturn ok &&\n\t\t(assign.Tok == token.ASSIGN || assign.Tok == token.DEFINE) &&\n\t\tlen(assign.Lhs) == 1 &&\n\t\tlen(assign.Rhs) == 1\n}\n\n// maybeNaN reports whether t is (or may be) a floating-point type.\nfunc maybeNaN(t types.Type) bool {\n\t// For now, we rely on core types.\n\t// TODO(adonovan): In the post-core-types future,\n\t// follow the approach of types.Checker.applyTypeFunc.\n\tt = typeparams.CoreType(t)\n\tif t == nil {\n\t\treturn true // fail safe\n\t}\n\tif basic, ok := t.(*types.Basic); ok && basic.Info()&types.IsFloat != 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// checkUserDefinedMinMax looks for user-defined min/max functions that are\n// equivalent to the built-in functions and suggests removing them.\nfunc checkUserDefinedMinMax(pass *analysis.Pass) {\n\tindex := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\n\t// Look up min and max functions by name in package scope\n\tfor _, funcName := range []string{\"min\", \"max\"} {\n\t\tif fn, ok := pass.Pkg.Scope().Lookup(funcName).(*types.Func); ok {\n\t\t\t// Use typeindex to get the FuncDecl directly\n\t\t\tif def, ok := index.Def(fn); ok {\n\t\t\t\tdecl := def.Parent().Node().(*ast.FuncDecl)\n\t\t\t\t// Check if this function matches the built-in min/max signature\n\t\t\t\t// and behavior, and verify that we have go1.21.\n\t\t\t\tif canUseBuiltinMinMax(fn, decl.Body) &&\n\t\t\t\t\tanalyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(def), versions.Go1_21) {\n\t\t\t\t\t// Expand to include leading doc comment\n\t\t\t\t\tpos := decl.Pos()\n\t\t\t\t\tif docs := astutil.DocComment(decl); docs != nil {\n\t\t\t\t\t\tpos = docs.Pos()\n\t\t\t\t\t}\n\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     decl.Pos(),\n\t\t\t\t\t\tEnd:     decl.End(),\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"user-defined %s function is equivalent to built-in %s and can be removed\", funcName, funcName),\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"Remove user-defined %s function\", funcName),\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos: pos,\n\t\t\t\t\t\t\t\tEnd: decl.End(),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// canUseBuiltinMinMax reports whether it is safe to replace a call\n// to this min or max function by its built-in namesake.\nfunc canUseBuiltinMinMax(fn *types.Func, body *ast.BlockStmt) bool {\n\tsig := fn.Type().(*types.Signature)\n\n\t// Only consider the most common case: exactly 2 parameters\n\tif sig.Params().Len() != 2 {\n\t\treturn false\n\t}\n\n\t// Check if any parameter might be floating-point\n\tfor param := range sig.Params().Variables() {\n\t\tif maybeNaN(param.Type()) {\n\t\t\treturn false // Don't suggest removal for float types due to NaN handling\n\t\t}\n\t}\n\n\t// Must have exactly one return value\n\tif sig.Results().Len() != 1 {\n\t\treturn false\n\t}\n\n\t// Check that the function body implements the expected min/max logic\n\tif body == nil {\n\t\treturn false\n\t}\n\n\treturn hasMinMaxLogic(body, fn.Name())\n}\n\n// hasMinMaxLogic checks if the function body implements simple min/max logic.\nfunc hasMinMaxLogic(body *ast.BlockStmt, funcName string) bool {\n\t// Pattern 1: Single if/else statement\n\tif len(body.List) == 1 {\n\t\tif ifStmt, ok := body.List[0].(*ast.IfStmt); ok {\n\t\t\t// Get the \"false\" result from the else block\n\t\t\tif elseBlock, ok := ifStmt.Else.(*ast.BlockStmt); ok && len(elseBlock.List) == 1 {\n\t\t\t\tif elseRet, ok := elseBlock.List[0].(*ast.ReturnStmt); ok && len(elseRet.Results) == 1 {\n\t\t\t\t\treturn checkMinMaxPattern(ifStmt, elseRet.Results[0], funcName)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Pattern 2: if statement followed by return\n\tif len(body.List) == 2 {\n\t\tif ifStmt, ok := body.List[0].(*ast.IfStmt); ok && ifStmt.Else == nil {\n\t\t\tif retStmt, ok := body.List[1].(*ast.ReturnStmt); ok && len(retStmt.Results) == 1 {\n\t\t\t\treturn checkMinMaxPattern(ifStmt, retStmt.Results[0], funcName)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n\n// checkMinMaxPattern checks if an if statement implements min/max logic.\n// ifStmt: the if statement to check\n// falseResult: the expression returned when the condition is false\n// funcName: \"min\" or \"max\"\nfunc checkMinMaxPattern(ifStmt *ast.IfStmt, falseResult ast.Expr, funcName string) bool {\n\t// Must have condition with comparison\n\tcmp, ok := ifStmt.Cond.(*ast.BinaryExpr)\n\tif !ok {\n\t\treturn false\n\t}\n\n\t// Check if then branch returns one of the compared values\n\tif len(ifStmt.Body.List) != 1 {\n\t\treturn false\n\t}\n\n\tthenRet, ok := ifStmt.Body.List[0].(*ast.ReturnStmt)\n\tif !ok || len(thenRet.Results) != 1 {\n\t\treturn false\n\t}\n\n\t// Use the same logic as the existing minmax analyzer\n\tsign := isInequality(cmp.Op)\n\tif sign == 0 {\n\t\treturn false // Not a comparison operator\n\t}\n\n\tt := thenRet.Results[0] // \"true\" result\n\tf := falseResult        // \"false\" result\n\tx := cmp.X              // left operand\n\ty := cmp.Y              // right operand\n\n\t// Check operand order and adjust sign accordingly\n\tif astutil.EqualSyntax(t, x) && astutil.EqualSyntax(f, y) {\n\t\tsign = +sign\n\t} else if astutil.EqualSyntax(t, y) && astutil.EqualSyntax(f, x) {\n\t\tsign = -sign\n\t} else {\n\t\treturn false\n\t}\n\n\t// Check if the sign matches the function name\n\treturn cond(sign < 0, \"min\", \"max\") == funcName\n}\n\n// -- utils --\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\nfunc cond[T any](cond bool, t, f T) T {\n\tif cond {\n\t\treturn t\n\t} else {\n\t\treturn f\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/modernize.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\n// Suite lists all modernize analyzers.\nvar Suite = []*analysis.Analyzer{\n\tAnyAnalyzer,\n\tatomicTypesAnalyzer,\n\t// AppendClippedAnalyzer, // not nil-preserving!\n\t// BLoopAnalyzer, // may skew benchmark results, see golang/go#74967\n\tFmtAppendfAnalyzer,\n\tForVarAnalyzer,\n\tMapsLoopAnalyzer,\n\tMinMaxAnalyzer,\n\tNewExprAnalyzer,\n\tOmitZeroAnalyzer,\n\tplusBuildAnalyzer,\n\tRangeIntAnalyzer,\n\tReflectTypeForAnalyzer,\n\tSlicesContainsAnalyzer,\n\t// SlicesDeleteAnalyzer, // not nil-preserving!\n\tSlicesSortAnalyzer,\n\tstditeratorsAnalyzer,\n\tstringscutAnalyzer,\n\tStringsCutPrefixAnalyzer,\n\tStringsSeqAnalyzer,\n\tStringsBuilderAnalyzer,\n\tTestingContextAnalyzer,\n\tunsafeFuncsAnalyzer,\n\tWaitGroupGoAnalyzer,\n}\n\n// -- helpers --\n\n// formatExprs formats a comma-separated list of expressions.\nfunc formatExprs(fset *token.FileSet, exprs []ast.Expr) string {\n\tvar buf strings.Builder\n\tfor i, e := range exprs {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(\",  \")\n\t\t}\n\t\tformat.Node(&buf, fset, e) // ignore errors\n\t}\n\treturn buf.String()\n}\n\n// isZeroIntConst reports whether e is an integer whose value is 0.\nfunc isZeroIntConst(info *types.Info, e ast.Expr) bool {\n\treturn isIntLiteral(info, e, 0)\n}\n\n// isIntLiteral reports whether e is an integer with given value.\nfunc isIntLiteral(info *types.Info, e ast.Expr, n int64) bool {\n\treturn info.Types[e].Value == constant.MakeInt64(n)\n}\n\n// filesUsingGoVersion returns a cursor for each *ast.File in the inspector\n// that uses at least the specified version of Go (e.g. \"go1.24\").\n//\n// The pass's analyzer must require [inspect.Analyzer].\n//\n// TODO(adonovan): opt: eliminate this function, instead following the\n// approach of [fmtappendf], which uses typeindex and\n// [analyzerutil.FileUsesGoVersion]; see \"Tip\" documented at the\n// latter function for motivation.\nfunc filesUsingGoVersion(pass *analysis.Pass, version string) iter.Seq[inspector.Cursor] {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\treturn func(yield func(inspector.Cursor) bool) {\n\t\tfor curFile := range inspect.Root().Children() {\n\t\t\tfile := curFile.Node().(*ast.File)\n\t\t\tif analyzerutil.FileUsesGoVersion(pass, file, version) && !yield(curFile) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// within reports whether the current pass is analyzing one of the\n// specified standard packages or their dependencies.\nfunc within(pass *analysis.Pass, pkgs ...string) bool {\n\tpath := pass.Pkg.Path()\n\treturn packagepath.IsStdPackage(path) &&\n\t\tmoreiters.Contains(stdlib.Dependencies(pkgs...), path)\n}\n\n// unparenEnclosing removes enclosing parens from cur in\n// preparation for a call to [Cursor.ParentEdge].\nfunc unparenEnclosing(cur inspector.Cursor) inspector.Cursor {\n\tfor cur.ParentEdgeKind() == edge.ParenExpr_X {\n\t\tcur = cur.Parent()\n\t}\n\treturn cur\n}\n\nvar (\n\tbuiltinAny     = types.Universe.Lookup(\"any\")\n\tbuiltinAppend  = types.Universe.Lookup(\"append\")\n\tbuiltinBool    = types.Universe.Lookup(\"bool\")\n\tbuiltinInt     = types.Universe.Lookup(\"int\")\n\tbuiltinFalse   = types.Universe.Lookup(\"false\")\n\tbuiltinLen     = types.Universe.Lookup(\"len\")\n\tbuiltinMake    = types.Universe.Lookup(\"make\")\n\tbuiltinNew     = types.Universe.Lookup(\"new\")\n\tbuiltinNil     = types.Universe.Lookup(\"nil\")\n\tbuiltinString  = types.Universe.Lookup(\"string\")\n\tbuiltinTrue    = types.Universe.Lookup(\"true\")\n\tbyteSliceType  = types.NewSlice(types.Typ[types.Byte])\n\tomitemptyRegex = regexp.MustCompile(`(?:^json| json):\"[^\"]*(,omitempty)(?:\"|,[^\"]*\")\\s?`)\n)\n\n// lookup returns the symbol denoted by name at the position of the cursor.\nfunc lookup(info *types.Info, cur inspector.Cursor, name string) types.Object {\n\tscope := typesinternal.EnclosingScope(info, cur)\n\t_, obj := scope.LookupParent(name, cur.Node().Pos())\n\treturn obj\n}\n\nfunc first[T any](x T, _ any) T { return x }\n\n// freshName returns a fresh name at the given pos and scope based on preferredName.\n// It generates a new name using refactor.FreshName only if:\n// (a) the preferred name is already defined at definedCur, and\n// (b) there are references to it from within usedCur.\n// If useAfterPos.IsValid(), the references must be after\n// useAfterPos within usedCur in order to warrant a fresh name.\n// Otherwise, it returns preferredName, since shadowing is valid in this case.\n// (declaredCur and usedCur may be identical in some use cases).\nfunc freshName(info *types.Info, index *typeindex.Index, scope *types.Scope, pos token.Pos, defCur inspector.Cursor, useCur inspector.Cursor, useAfterPos token.Pos, preferredName string) string {\n\tobj := lookup(info, defCur, preferredName)\n\tif obj == nil {\n\t\t// preferredName has not been declared here.\n\t\treturn preferredName\n\t}\n\tfor use := range index.Uses(obj) {\n\t\tif useCur.Contains(use) && use.Node().Pos() >= useAfterPos {\n\t\t\treturn refactor.FreshName(scope, pos, preferredName)\n\t\t}\n\t}\n\t// Name is taken but not used in the given block; shadowing is acceptable.\n\treturn preferredName\n}\n\n// isLocal reports whether obj is local to some function.\n// Precondition: not a struct field or interface method.\nfunc isLocal(obj types.Object) bool {\n\t// [... 5=stmt 4=func 3=file 2=pkg 1=universe]\n\tvar depth int\n\tfor scope := obj.Parent(); scope != nil; scope = scope.Parent() {\n\t\tdepth++\n\t}\n\treturn depth >= 4\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/modernize_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize_test\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/modernize\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestAppendClipped(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.AppendClippedAnalyzer, \"appendclipped\")\n}\n\nfunc TestAtomicTypes(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.AtomicTypesModernizer, \"atomictypes/...\")\n}\nfunc TestBloop(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.BLoopAnalyzer, \"bloop\")\n}\n\nfunc TestAny(t *testing.T) {\n\t// The 'any' tests also exercise that fixes are not applied to generated files.\n\tRunWithSuggestedFixes(t, TestData(), modernize.AnyAnalyzer, \"any\")\n}\n\nfunc TestErrorsAsType(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.ErrorsAsTypeModernizer, \"errorsastype/...\")\n}\n\nfunc TestFmtAppendf(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.FmtAppendfAnalyzer, \"fmtappendf\")\n}\n\nfunc TestForVar(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.ForVarAnalyzer, \"forvar\")\n}\n\nfunc TestStdIterators(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.StdIteratorsModernizer, \"stditerators\")\n}\n\nfunc TestMapsLoop(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.MapsLoopAnalyzer, \"mapsloop\")\n}\n\nfunc TestMinMax(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.MinMaxAnalyzer, \"minmax\", \"minmax/userdefined\", \"minmax/wrongoperators\", \"minmax/nonstrict\", \"minmax/wrongreturn\", \"minmax/go120\")\n}\n\nfunc TestNewExpr(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.NewExprAnalyzer, \"newexpr\")\n}\n\nfunc TestOmitZero(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.OmitZeroAnalyzer, \"omitzero/...\")\n}\n\nfunc TestRangeInt(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.RangeIntAnalyzer, \"rangeint\")\n}\n\nfunc TestPlusBuild(t *testing.T) {\n\t// This test assumes a particular OS/ARCH so that the test\n\t// files are selected by the build; otherwise they would\n\t// appear in IgnoredFiles, for which file version information\n\t// is not available. See https://go.dev/issue/77318.\n\tt.Setenv(\"GOOS\", \"linux\")\n\tt.Setenv(\"GOARCH\", \"amd64\")\n\n\t// This test has a dedicated hack in the analysistest package:\n\t// Because it cares about IgnoredFiles, which most analyzers\n\t// ignore, the test framework will consider expectations in\n\t// ignore files too, but only for this analyzer.\n\t// (But see above: IgnoredFiles lack version information\n\t// so we can't safely apply any fixes to them.)\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.PlusBuildModernizer, \"plusbuild\")\n}\n\nfunc TestReflectTypeFor(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 25) // requires go1.25 types.Var.Kind\n\tRunWithSuggestedFixes(t, TestData(), modernize.ReflectTypeForAnalyzer, \"reflecttypefor\")\n}\n\nfunc TestSlicesContains(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.SlicesContainsAnalyzer, \"slicescontains\")\n}\n\nfunc TestSlicesDelete(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.SlicesDeleteAnalyzer, \"slicesdelete\")\n}\n\nfunc TestSlicesSort(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.SlicesSortAnalyzer, \"slicessort\")\n}\n\nfunc TestStringsBuilder(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.StringsBuilderAnalyzer, \"stringsbuilder\")\n}\n\nfunc TestStringsCut(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.StringsCutModernizer, \"stringscut\")\n}\n\nfunc TestStringsCutPrefix(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.StringsCutPrefixAnalyzer,\n\t\t\"stringscutprefix\",\n\t\t\"stringscutprefix/bytescutprefix\")\n}\n\nfunc TestStringsSeq(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.StringsSeqAnalyzer, \"splitseq\", \"fieldsseq\")\n}\n\nfunc TestTestingContext(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.TestingContextAnalyzer, \"testingcontext\")\n}\n\nfunc TestUnsafeFuncs(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), goplsexport.UnsafeFuncsModernizer, \"unsafefuncs\")\n}\n\nfunc TestWaitGroupGo(t *testing.T) {\n\tRunWithSuggestedFixes(t, TestData(), modernize.WaitGroupGoAnalyzer, \"waitgroupgo\")\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/newexpr.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar NewExprAnalyzer = &analysis.Analyzer{\n\tName:      \"newexpr\",\n\tDoc:       analyzerutil.MustExtractDoc(doc, \"newexpr\"),\n\tURL:       \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#newexpr\",\n\tRequires:  []*analysis.Analyzer{inspect.Analyzer},\n\tRun:       run,\n\tFactTypes: []analysis.Fact{&newLike{}},\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tinfo    = pass.TypesInfo\n\t)\n\n\t// Detect functions that are new-like, i.e. have the form:\n\t//\n\t//\tfunc f(x T) *T { return &x }\n\t//\n\t// meaning that it is equivalent to new(x), if x has type T.\n\tfor curFuncDecl := range inspect.Root().Preorder((*ast.FuncDecl)(nil)) {\n\t\tdecl := curFuncDecl.Node().(*ast.FuncDecl)\n\t\tfn := info.Defs[decl.Name].(*types.Func)\n\t\tif decl.Body != nil && len(decl.Body.List) == 1 {\n\t\t\tif ret, ok := decl.Body.List[0].(*ast.ReturnStmt); ok && len(ret.Results) == 1 {\n\t\t\t\tif unary, ok := ret.Results[0].(*ast.UnaryExpr); ok && unary.Op == token.AND {\n\t\t\t\t\tif id, ok := unary.X.(*ast.Ident); ok {\n\t\t\t\t\t\tif v, ok := info.Uses[id].(*types.Var); ok {\n\t\t\t\t\t\t\tsig := fn.Signature()\n\t\t\t\t\t\t\tif sig.Results().Len() == 1 &&\n\t\t\t\t\t\t\t\tis[*types.Pointer](sig.Results().At(0).Type()) && // => no iface conversion\n\t\t\t\t\t\t\t\tsig.Params().Len() == 1 &&\n\t\t\t\t\t\t\t\tsig.Params().At(0) == v {\n\n\t\t\t\t\t\t\t\t// Export a fact for each one.\n\t\t\t\t\t\t\t\tpass.ExportObjectFact(fn, &newLike{})\n\n\t\t\t\t\t\t\t\t// Check file version.\n\t\t\t\t\t\t\t\tfile := astutil.EnclosingFile(curFuncDecl)\n\t\t\t\t\t\t\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {\n\t\t\t\t\t\t\t\t\tcontinue // new(expr) not available in this file\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar edits []analysis.TextEdit\n\n\t\t\t\t\t\t\t\t// If 'new' is not shadowed, replace func body: &x -> new(x).\n\t\t\t\t\t\t\t\t// This makes it safely and cleanly inlinable.\n\t\t\t\t\t\t\t\tcurRet, _ := curFuncDecl.FindNode(ret)\n\t\t\t\t\t\t\t\tif lookup(info, curRet, \"new\") == builtinNew {\n\t\t\t\t\t\t\t\t\tedits = []analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t\t// return    &x\n\t\t\t\t\t\t\t\t\t\t//        ---- -\n\t\t\t\t\t\t\t\t\t\t// return new(x)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tPos:     unary.OpPos,\n\t\t\t\t\t\t\t\t\t\t\tEnd:     unary.OpPos + token.Pos(len(\"&\")),\n\t\t\t\t\t\t\t\t\t\t\tNewText: []byte(\"new(\"),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tPos:     unary.X.End(),\n\t\t\t\t\t\t\t\t\t\t\tEnd:     unary.X.End(),\n\t\t\t\t\t\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Add a //go:fix inline annotation, if not already present.\n\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t// The inliner will not inline a newer callee body into an\n\t\t\t\t\t\t\t\t// older Go file; see https://go.dev/issue/75726.\n\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t// TODO(adonovan): use ast.ParseDirective when go1.26 is assured.\n\t\t\t\t\t\t\t\tif !slices.ContainsFunc(astutil.Directives(decl.Doc), func(d *astutil.Directive) bool {\n\t\t\t\t\t\t\t\t\treturn d.Tool == \"go\" && d.Name == \"fix\" && d.Args == \"inline\"\n\t\t\t\t\t\t\t\t}) {\n\t\t\t\t\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t\tPos:     decl.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     decl.Pos(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(\"//go:fix inline\\n\"),\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif len(edits) > 0 {\n\t\t\t\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t\t\t\tPos:     decl.Name.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     decl.Name.End(),\n\t\t\t\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"%s can be an inlinable wrapper around new(expr)\", decl.Name),\n\t\t\t\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tMessage:   \"Make %s an inlinable wrapper around new(expr)\",\n\t\t\t\t\t\t\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Report and transform calls, when safe.\n\t// In effect, this is inlining the new-like function\n\t// even before we have marked the callee with //go:fix inline.\n\tfor curCall := range inspect.Root().Preorder((*ast.CallExpr)(nil)) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tvar fact newLike\n\t\tif fn, ok := typeutil.Callee(info, call).(*types.Func); ok &&\n\t\t\tpass.ImportObjectFact(fn, &fact) {\n\n\t\t\t// Check file version.\n\t\t\tfile := astutil.EnclosingFile(curCall)\n\t\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {\n\t\t\t\tcontinue // new(expr) not available in this file\n\t\t\t}\n\n\t\t\t// Check new is not shadowed.\n\t\t\tif lookup(info, curCall, \"new\") != builtinNew {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// The return type *T must exactly match the argument type T.\n\t\t\t// (We formulate it this way--not in terms of the parameter\n\t\t\t// type--to support generics.)\n\t\t\tvar targ types.Type\n\t\t\t{\n\t\t\t\targ := call.Args[0]\n\t\t\t\ttvarg := info.Types[arg]\n\n\t\t\t\t// Constants: we must work around the type checker\n\t\t\t\t// bug that causes info.Types to wrongly report the\n\t\t\t\t// \"typed\" type for an untyped constant.\n\t\t\t\t// (See \"historical reasons\" in issue go.dev/issue/70638.)\n\t\t\t\t//\n\t\t\t\t// We don't have a reliable way to do this but we can attempt\n\t\t\t\t// to re-typecheck the constant expression on its own, in\n\t\t\t\t// the original lexical environment but not as a part of some\n\t\t\t\t// larger expression that implies a conversion to some \"typed\" type.\n\t\t\t\t// (For the genesis of this idea see (*state).arguments\n\t\t\t\t// in ../../../../internal/refactor/inline/inline.go.)\n\t\t\t\tif tvarg.Value != nil {\n\t\t\t\t\tinfo2 := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}\n\t\t\t\t\tif err := types.CheckExpr(token.NewFileSet(), pass.Pkg, token.NoPos, arg, info2); err != nil {\n\t\t\t\t\t\tcontinue // unexpected error\n\t\t\t\t\t}\n\t\t\t\t\ttvarg = info2.Types[arg]\n\t\t\t\t}\n\n\t\t\t\ttarg = types.Default(tvarg.Type)\n\t\t\t}\n\t\t\tif !types.Identical(types.NewPointer(targ), info.TypeOf(call)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     call.Pos(),\n\t\t\t\tEnd:     call.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"call of %s(x) can be simplified to new(x)\", fn.Name()),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: fmt.Sprintf(\"Simplify %s(x) to new(x)\", fn.Name()),\n\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\tNewText: []byte(\"new\"),\n\t\t\t\t\t}},\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\n// A newLike fact records that its associated function is \"new-like\".\ntype newLike struct{}\n\nfunc (*newLike) AFact()         {}\nfunc (*newLike) String() string { return \"newlike\" }\n"
  },
  {
    "path": "go/analysis/passes/modernize/omitzero.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar OmitZeroAnalyzer = &analysis.Analyzer{\n\tName:     \"omitzero\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"omitzero\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      omitzero,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero\",\n}\n\n// The omitzero pass searches for instances of \"omitempty\" in a json field tag on a\n// struct. Since \"omitfilesUsingGoVersions not have any effect when applied to a struct field,\n// it suggests either deleting \"omitempty\" or replacing it with \"omitzero\", which\n// correctly excludes structs from a json encoding.\nfunc omitzero(pass *analysis.Pass) (any, error) {\n\t// usesKubebuilder reports whether \"+kubebuilder:\" appears in\n\t// any comment in the package, since it has its own\n\t// interpretation of what omitzero means; see go.dev/issue/76649.\n\t// It is computed once, on demand.\n\tusesKubebuilder := sync.OnceValue[bool](func() bool {\n\t\tfor _, file := range pass.Files {\n\t\t\tfor _, comment := range file.Comments {\n\t\t\t\tif strings.Contains(comment.Text(), \"+kubebuilder:\") {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t})\n\n\tcheckField := func(field *ast.Field) {\n\t\ttyp := pass.TypesInfo.TypeOf(field.Type)\n\t\t_, ok := typ.Underlying().(*types.Struct)\n\t\tif !ok {\n\t\t\t// Not a struct\n\t\t\treturn\n\t\t}\n\t\ttag := field.Tag\n\t\tif tag == nil {\n\t\t\t// No tag to check\n\t\t\treturn\n\t\t}\n\t\t// The omitempty tag may be used by other packages besides json, but we should only modify its use with json\n\t\ttagconv, _ := strconv.Unquote(tag.Value)\n\t\tmatch := omitemptyRegex.FindStringSubmatchIndex(tagconv)\n\t\tif match == nil {\n\t\t\t// No omitempty in json tag\n\t\t\treturn\n\t\t}\n\t\tomitEmpty, err := astutil.RangeInStringLiteral(field.Tag, match[2], match[3])\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tvar remove analysis.Range = omitEmpty\n\n\t\tjsonTag := reflect.StructTag(tagconv).Get(\"json\")\n\t\tif jsonTag == \",omitempty\" {\n\t\t\t// Remove the entire struct tag if json is the only package used\n\t\t\tif match[1]-match[0] == len(tagconv) {\n\t\t\t\tremove = field.Tag\n\t\t\t} else {\n\t\t\t\t// Remove the json tag if omitempty is the only field\n\t\t\t\tremove, err = astutil.RangeInStringLiteral(field.Tag, match[0], match[1])\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Don't offer a fix if the package seems to use kubebuilder,\n\t\t// as it has its own intepretation of \"omitzero\" tags.\n\t\t// https://book.kubebuilder.io/reference/markers.html\n\t\tif usesKubebuilder() {\n\t\t\treturn\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     field.Tag.Pos(),\n\t\t\tEnd:     field.Tag.End(),\n\t\t\tMessage: \"Omitempty has no effect on nested struct fields\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t{\n\t\t\t\t\tMessage: \"Remove redundant omitempty tag\",\n\t\t\t\t\tTextEdits: []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: remove.Pos(),\n\t\t\t\t\t\t\tEnd: remove.End(),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMessage: \"Replace omitempty with omitzero (behavior change)\",\n\t\t\t\t\tTextEdits: []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     omitEmpty.Pos(),\n\t\t\t\t\t\t\tEnd:     omitEmpty.End(),\n\t\t\t\t\t\t\tNewText: []byte(\",omitzero\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}})\n\t}\n\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_24) {\n\t\tfor curStruct := range curFile.Preorder((*ast.StructType)(nil)) {\n\t\t\tfor _, curField := range curStruct.Node().(*ast.StructType).Fields.List {\n\t\t\t\tcheckField(curField)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/plusbuild.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar plusBuildAnalyzer = &analysis.Analyzer{\n\tName: \"plusbuild\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"plusbuild\"),\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild\",\n\tRun:  plusbuild,\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.PlusBuildModernizer = plusBuildAnalyzer\n}\n\nfunc plusbuild(pass *analysis.Pass) (any, error) {\n\tcheck := func(f *ast.File) {\n\t\t// \"//go:build\" directives were added in go1.17, but\n\t\t// we didn't start eliminating +build directives till go1.18.\n\t\tif !analyzerutil.FileUsesGoVersion(pass, f, versions.Go1_18) {\n\t\t\treturn\n\t\t}\n\n\t\t// When gofmt sees a +build comment, it adds a\n\t\t// preceding equivalent //go:build directive, so in\n\t\t// formatted files we can assume that a +build line is\n\t\t// part of a comment group that starts with a\n\t\t// //go:build line and is followed by a blank line.\n\t\t//\n\t\t// While we cannot delete comments from an AST and\n\t\t// expect consistent output in general, this specific\n\t\t// case--deleting only some lines from a comment\n\t\t// block--does format correctly.\n\t\tfor _, g := range f.Comments {\n\t\t\tsawGoBuild := false\n\t\t\tfor _, c := range g.List {\n\t\t\t\tif sawGoBuild && strings.HasPrefix(c.Text, \"// +build \") {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     c.Pos(),\n\t\t\t\t\t\tEnd:     c.End(),\n\t\t\t\t\t\tMessage: \"+build line is no longer needed\",\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: \"Remove obsolete +build line\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos: c.Pos(),\n\t\t\t\t\t\t\t\tEnd: c.End(),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif strings.HasPrefix(c.Text, \"//go:build \") {\n\t\t\t\t\tsawGoBuild = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, f := range pass.Files {\n\t\tcheck(f)\n\t}\n\tfor _, name := range pass.IgnoredFiles {\n\t\tif strings.HasSuffix(name, \".go\") {\n\t\t\tf, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments|parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\tcontinue // parse error: ignore\n\t\t\t}\n\t\t\tcheck(f)\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/rangeint.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar RangeIntAnalyzer = &analysis.Analyzer{\n\tName: \"rangeint\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"rangeint\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: rangeint,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#rangeint\",\n}\n\n// rangeint offers a fix to replace a 3-clause 'for' loop:\n//\n//\tfor i := 0; i < limit; i++ {}\n//\n// by a range loop with an integer operand:\n//\n//\tfor i := range limit {}\n//\n// Variants:\n//   - The ':=' may be replaced by '='.\n//   - The fix may remove \"i :=\" if it would become unused.\n//\n// Restrictions:\n//   - The variable i must not be assigned or address-taken within the\n//     loop, because a \"for range int\" loop does not respect assignments\n//     to the loop index.\n//   - The limit must not be b.N, to avoid redundancy with bloop's fixes.\n//\n// Caveats:\n//\n// The fix causes the limit expression to be evaluated exactly once,\n// instead of once per iteration. So, to avoid changing the\n// cardinality of side effects, the limit expression must not involve\n// function calls (e.g. seq.Len()) or channel receives. Moreover, the\n// value of the limit expression must be loop invariant, which in\n// practice means it must take one of the following forms:\n//\n//   - a local variable that is assigned only once and not address-taken;\n//   - a constant; or\n//   - len(s), where s has the above properties.\nfunc rangeint(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tinfo      = pass.TypesInfo\n\t\ttypeindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t)\n\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_22) {\n\tnextLoop:\n\t\tfor curLoop := range curFile.Preorder((*ast.ForStmt)(nil)) {\n\t\t\tloop := curLoop.Node().(*ast.ForStmt)\n\t\t\tif init, ok := loop.Init.(*ast.AssignStmt); ok &&\n\t\t\t\tisSimpleAssign(init) &&\n\t\t\t\tis[*ast.Ident](init.Lhs[0]) &&\n\t\t\t\tisZeroIntConst(info, init.Rhs[0]) {\n\t\t\t\t// Have: for i = 0; ... (or i := 0)\n\t\t\t\tindex := init.Lhs[0].(*ast.Ident)\n\n\t\t\t\tif compare, ok := loop.Cond.(*ast.BinaryExpr); ok &&\n\t\t\t\t\tcompare.Op == token.LSS &&\n\t\t\t\t\tastutil.EqualSyntax(compare.X, init.Lhs[0]) {\n\t\t\t\t\t// Have: for i = 0; i < limit; ... {}\n\n\t\t\t\t\tlimit := compare.Y\n\n\t\t\t\t\t// If limit is \"len(slice)\", simplify it to \"slice\".\n\t\t\t\t\t//\n\t\t\t\t\t// (Don't replace \"for i := 0; i < len(map); i++\"\n\t\t\t\t\t// with \"for range m\" because it's too hard to prove\n\t\t\t\t\t// that len(m) is loop-invariant).\n\t\t\t\t\tif call, ok := limit.(*ast.CallExpr); ok &&\n\t\t\t\t\t\ttypeutil.Callee(info, call) == builtinLen &&\n\t\t\t\t\t\tis[*types.Slice](info.TypeOf(call.Args[0]).Underlying()) {\n\t\t\t\t\t\tlimit = call.Args[0]\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check the form of limit: must be a constant,\n\t\t\t\t\t// or a local var that is not assigned or address-taken.\n\t\t\t\t\tlimitOK := false\n\t\t\t\t\tif info.Types[limit].Value != nil {\n\t\t\t\t\t\tlimitOK = true // constant\n\t\t\t\t\t} else if id, ok := limit.(*ast.Ident); ok {\n\t\t\t\t\t\tif v, ok := info.Uses[id].(*types.Var); ok &&\n\t\t\t\t\t\t\t!(v.Exported() && typesinternal.IsPackageLevel(v)) {\n\t\t\t\t\t\t\t// limit is a local or unexported global var.\n\t\t\t\t\t\t\t// (An exported global may have uses we can't see.)\n\t\t\t\t\t\t\tfor cur := range typeindex.Uses(v) {\n\t\t\t\t\t\t\t\tif isScalarLvalue(info, cur) {\n\t\t\t\t\t\t\t\t\t// Limit var is assigned or address-taken.\n\t\t\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlimitOK = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif !limitOK {\n\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t}\n\n\t\t\t\t\tvalidIncrement := false\n\t\t\t\t\tif inc, ok := loop.Post.(*ast.IncDecStmt); ok &&\n\t\t\t\t\t\tinc.Tok == token.INC &&\n\t\t\t\t\t\tastutil.EqualSyntax(compare.X, inc.X) {\n\t\t\t\t\t\t// Have: i++\n\t\t\t\t\t\tvalidIncrement = true\n\t\t\t\t\t} else if assign, ok := loop.Post.(*ast.AssignStmt); ok &&\n\t\t\t\t\t\tassign.Tok == token.ADD_ASSIGN &&\n\t\t\t\t\t\tlen(assign.Rhs) == 1 && isIntLiteral(info, assign.Rhs[0], 1) &&\n\t\t\t\t\t\tlen(assign.Lhs) == 1 && astutil.EqualSyntax(compare.X, assign.Lhs[0]) {\n\t\t\t\t\t\t// Have: i += 1\n\t\t\t\t\t\tvalidIncrement = true\n\t\t\t\t\t}\n\n\t\t\t\t\tif validIncrement {\n\t\t\t\t\t\t// Have: for i = 0; i < limit; i++ {}\n\n\t\t\t\t\t\t// Find references to i within the loop body.\n\t\t\t\t\t\tv := info.ObjectOf(index).(*types.Var)\n\t\t\t\t\t\tswitch v.Kind() {\n\t\t\t\t\t\tcase types.PackageVar:\n\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\tcase types.ResultVar:\n\t\t\t\t\t\t\t// If v is a named result, it is implicitly\n\t\t\t\t\t\t\t// used after the loop (go.dev/issue/76880).\n\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tused := false\n\t\t\t\t\t\tfor curId := range curLoop.Child(loop.Body).Preorder((*ast.Ident)(nil)) {\n\t\t\t\t\t\t\tid := curId.Node().(*ast.Ident)\n\t\t\t\t\t\t\tif info.Uses[id] == v {\n\t\t\t\t\t\t\t\tused = true\n\n\t\t\t\t\t\t\t\t// Reject if any is an l-value (assigned or address-taken):\n\t\t\t\t\t\t\t\t// a \"for range int\" loop does not respect assignments to\n\t\t\t\t\t\t\t\t// the loop variable.\n\t\t\t\t\t\t\t\tif isScalarLvalue(info, curId) {\n\t\t\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If i is no longer used, delete \"i := \".\n\t\t\t\t\t\tvar edits []analysis.TextEdit\n\t\t\t\t\t\tif !used && init.Tok == token.DEFINE {\n\t\t\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\t\t\tPos: index.Pos(),\n\t\t\t\t\t\t\t\tEnd: init.Rhs[0].Pos(),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If i is used after the loop,\n\t\t\t\t\t\t// don't offer a fix, as a range loop\n\t\t\t\t\t\t// leaves i with a different final value (limit-1).\n\t\t\t\t\t\tif init.Tok == token.ASSIGN {\n\t\t\t\t\t\t\t// Find the nearest ancestor that is not a label.\n\t\t\t\t\t\t\t// Otherwise, checking for i usage outside of a for\n\t\t\t\t\t\t\t// loop might not function properly further below.\n\t\t\t\t\t\t\t// This is because the i usage might be a child of\n\t\t\t\t\t\t\t// the loop's parent's parent, for example:\n\t\t\t\t\t\t\t//     var i int\n\t\t\t\t\t\t\t// Loop:\n\t\t\t\t\t\t\t//     for i = 0; i < 10; i++ { break loop }\n\t\t\t\t\t\t\t//     // i is in the sibling of the label, not the loop\n\t\t\t\t\t\t\t//     fmt.Println(i)\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\tancestor := curLoop.Parent()\n\t\t\t\t\t\t\tfor is[*ast.LabeledStmt](ancestor.Node()) {\n\t\t\t\t\t\t\t\tancestor = ancestor.Parent()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor curId := range ancestor.Preorder((*ast.Ident)(nil)) {\n\t\t\t\t\t\t\t\tid := curId.Node().(*ast.Ident)\n\t\t\t\t\t\t\t\tif info.Uses[id] == v {\n\t\t\t\t\t\t\t\t\t// Is i used after loop?\n\t\t\t\t\t\t\t\t\tif id.Pos() > loop.End() {\n\t\t\t\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// Is i used within a defer statement\n\t\t\t\t\t\t\t\t\t// that is within the scope of i?\n\t\t\t\t\t\t\t\t\t//     var i int\n\t\t\t\t\t\t\t\t\t//     defer func() { print(i)}\n\t\t\t\t\t\t\t\t\t//     for i = ... { ... }\n\t\t\t\t\t\t\t\t\tfor curDefer := range curId.Enclosing((*ast.DeferStmt)(nil)) {\n\t\t\t\t\t\t\t\t\t\tif curDefer.Node().Pos() > v.Pos() {\n\t\t\t\t\t\t\t\t\t\t\tcontinue nextLoop\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If limit is len(slice),\n\t\t\t\t\t\t// simplify \"range len(slice)\" to \"range slice\".\n\t\t\t\t\t\tif call, ok := limit.(*ast.CallExpr); ok &&\n\t\t\t\t\t\t\ttypeutil.Callee(info, call) == builtinLen &&\n\t\t\t\t\t\t\tis[*types.Slice](info.TypeOf(call.Args[0]).Underlying()) {\n\t\t\t\t\t\t\tlimit = call.Args[0]\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If the limit is a untyped constant of non-integer type,\n\t\t\t\t\t\t// such as \"const limit = 1e3\", its effective type may\n\t\t\t\t\t\t// differ between the two forms.\n\t\t\t\t\t\t// In a for loop, it must be comparable with int i,\n\t\t\t\t\t\t//    for i := 0; i < limit; i++ {}\n\t\t\t\t\t\t// but in a range loop it would become a float,\n\t\t\t\t\t\t//    for i := range limit {}\n\t\t\t\t\t\t// which is a type error. We need to convert it to int\n\t\t\t\t\t\t// in this case.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Unfortunately go/types discards the untyped type\n\t\t\t\t\t\t// (but see Untyped in golang/go#70638) so we must\n\t\t\t\t\t\t// re-type check the expression to detect this case.\n\t\t\t\t\t\tvar beforeLimit, afterLimit string\n\t\t\t\t\t\tif v := info.Types[limit].Value; v != nil {\n\t\t\t\t\t\t\ttVar := info.TypeOf(init.Rhs[0])\n\t\t\t\t\t\t\tfile := curFile.Node().(*ast.File)\n\t\t\t\t\t\t\t// TODO(mkalil): use a types.Qualifier that respects the existing\n\t\t\t\t\t\t\t// imports of this file that are visible (not shadowed) at the current position.\n\t\t\t\t\t\t\tqual := typesinternal.FileQualifier(file, pass.Pkg)\n\t\t\t\t\t\t\tbeforeLimit, afterLimit = fmt.Sprintf(\"%s(\", types.TypeString(tVar, qual)), \")\"\n\t\t\t\t\t\t\tinfo2 := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}\n\t\t\t\t\t\t\tif types.CheckExpr(pass.Fset, pass.Pkg, limit.Pos(), limit, info2) == nil {\n\t\t\t\t\t\t\t\ttLimit := info2.TypeOf(limit)\n\t\t\t\t\t\t\t\t// Eliminate conversion when safe.\n\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t// Redundant conversions are not only unsightly but may in some cases cause\n\t\t\t\t\t\t\t\t// architecture-specific types (e.g. syscall.Timespec.Nsec) to be inserted\n\t\t\t\t\t\t\t\t// into otherwise portable files.\n\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t// The operand must have an integer type (not, say, '1e6')\n\t\t\t\t\t\t\t\t// even when assigning to an existing integer variable.\n\t\t\t\t\t\t\t\tif isInteger(tLimit) {\n\t\t\t\t\t\t\t\t\t// When declaring a new var from an untyped limit,\n\t\t\t\t\t\t\t\t\t// the limit's default type is what matters.\n\t\t\t\t\t\t\t\t\tif init.Tok != token.ASSIGN {\n\t\t\t\t\t\t\t\t\t\ttLimit = types.Default(tLimit)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif types.AssignableTo(tLimit, tVar) {\n\t\t\t\t\t\t\t\t\t\tbeforeLimit, afterLimit = \"\", \"\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\tPos:     init.Pos(),\n\t\t\t\t\t\t\tEnd:     loop.Post.End(),\n\t\t\t\t\t\t\tMessage: \"for loop can be modernized using range over int\",\n\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace for loop with range %s\",\n\t\t\t\t\t\t\t\t\tastutil.Format(pass.Fset, limit)),\n\t\t\t\t\t\t\t\tTextEdits: append(edits, []analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t// for i := 0; i < limit; i++ {}\n\t\t\t\t\t\t\t\t\t//     -----              ---\n\t\t\t\t\t\t\t\t\t//          -------\n\t\t\t\t\t\t\t\t\t// for i := range  limit      {}\n\n\t\t\t\t\t\t\t\t\t// Delete init.\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     init.Rhs[0].Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     limit.Pos(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(\"range \"),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t// Add \"int(\" before limit, if needed.\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     limit.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     limit.Pos(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(beforeLimit),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t// Delete inc.\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos: limit.End(),\n\t\t\t\t\t\t\t\t\t\tEnd: loop.Post.End(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t// Add \")\" after limit, if needed.\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     limit.End(),\n\t\t\t\t\t\t\t\t\t\tEnd:     limit.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(afterLimit),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}...),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// isScalarLvalue reports whether the specified identifier is\n// address-taken or appears on the left side of an assignment.\n//\n// This function is valid only for scalars (x = ...),\n// not for aggregates (x.a[i] = ...)\nfunc isScalarLvalue(info *types.Info, curId inspector.Cursor) bool {\n\t// Unfortunately we can't simply use info.Types[e].Assignable()\n\t// as it is always true for a variable even when that variable is\n\t// used only as an r-value. So we must inspect enclosing syntax.\n\n\tcur := curId\n\n\t// Strip enclosing parens.\n\tek := cur.ParentEdgeKind()\n\tfor ek == edge.ParenExpr_X {\n\t\tcur = cur.Parent()\n\t\tek = cur.ParentEdgeKind()\n\t}\n\n\tswitch ek {\n\tcase edge.AssignStmt_Lhs:\n\t\tassign := cur.Parent().Node().(*ast.AssignStmt)\n\t\tif assign.Tok != token.DEFINE {\n\t\t\treturn true // i = j or i += j\n\t\t}\n\t\tid := curId.Node().(*ast.Ident)\n\t\tif v, ok := info.Defs[id]; ok && v.Pos() != id.Pos() {\n\t\t\treturn true // reassignment of i (i, j := 1, 2)\n\t\t}\n\tcase edge.RangeStmt_Key:\n\t\trng := cur.Parent().Node().(*ast.RangeStmt)\n\t\tif rng.Tok == token.ASSIGN {\n\t\t\treturn true // \"for k, v = range x\" is like an AssignStmt to k, v\n\t\t}\n\tcase edge.IncDecStmt_X:\n\t\treturn true // i++, i--\n\tcase edge.UnaryExpr_X:\n\t\tif cur.Parent().Node().(*ast.UnaryExpr).Op == token.AND {\n\t\t\treturn true // &i\n\t\t}\n\t}\n\treturn false\n}\n\n// enclosingSignature returns the signature of the innermost\n// function enclosing the syntax node denoted by cur\n// or nil if the node is not within a function.\n//\n// TODO(adonovan): factor with gopls/internal/util/typesutil.EnclosingSignature.\nfunc enclosingSignature(cur inspector.Cursor, info *types.Info) *types.Signature {\n\tif c, ok := enclosingFunc(cur); ok {\n\t\tswitch n := c.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif f, ok := info.Defs[n.Name]; ok {\n\t\t\t\treturn f.Type().(*types.Signature)\n\t\t\t}\n\t\tcase *ast.FuncLit:\n\t\t\tif f, ok := info.Types[n]; ok {\n\t\t\t\treturn f.Type.(*types.Signature)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/reflect.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\n// This file defines modernizers that use the \"reflect\" package.\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar ReflectTypeForAnalyzer = &analysis.Analyzer{\n\tName: \"reflecttypefor\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"reflecttypefor\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: reflecttypefor,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#reflecttypefor\",\n}\n\nfunc reflecttypefor(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\n\t\treflectTypeOf = index.Object(\"reflect\", \"TypeOf\")\n\t)\n\n\tfor curCall := range index.Calls(reflectTypeOf) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t// Have: reflect.TypeOf(expr)\n\n\t\texpr := call.Args[0]\n\n\t\t// reflect.TypeFor cannot be instantiated with an untyped nil.\n\t\t// We use type information rather than checking the identifier name\n\t\t// to correctly handle edge cases where \"nil\" is shadowed (e.g. nil := \"nil\").\n\t\tif info.Types[expr].IsNil() {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !typesinternal.NoEffects(info, expr) {\n\t\t\tcontinue // don't eliminate operand: may have effects\n\t\t}\n\n\t\tt := info.TypeOf(expr)\n\t\tvar edits []analysis.TextEdit\n\n\t\t// Special cases for TypeOf((*T)(nil)).Elem(), and\n\t\t// TypeOf([]T(nil)).Elem(), needed when T is an interface type.\n\t\tif curCall.ParentEdgeKind() == edge.SelectorExpr_X {\n\t\t\tcurSel := unparenEnclosing(curCall).Parent()\n\t\t\tif curSel.ParentEdgeKind() == edge.CallExpr_Fun {\n\t\t\t\tcall2 := unparenEnclosing(curSel).Parent().Node().(*ast.CallExpr) // potentially .Elem()\n\t\t\t\tobj := typeutil.Callee(info, call2)\n\t\t\t\tif typesinternal.IsMethodNamed(obj, \"reflect\", \"Type\", \"Elem\") {\n\t\t\t\t\t// reflect.TypeOf(expr).Elem()\n\t\t\t\t\t//                     -------\n\t\t\t\t\t// reflect.TypeOf(expr)\n\t\t\t\t\tif typ, hasElem := t.(interface{ Elem() types.Type }); hasElem {\n\t\t\t\t\t\t// Have: TypeOf(expr).Elem() where expr is *T, []T, [k]T, chan T, map[K]T, etc.\n\t\t\t\t\t\tt = typ.Elem()\n\t\t\t\t\t\tedits = []analysis.TextEdit{{\n\t\t\t\t\t\t\tPos: call.End(),\n\t\t\t\t\t\t\tEnd: call2.End(),\n\t\t\t\t\t\t}}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// TypeOf(x) where x has an interface type is a\n\t\t// dynamic operation; don't transform it to TypeFor.\n\t\t// (edits == nil means \"not the Elem() special case\".)\n\t\tif types.IsInterface(t) && edits == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tfile := astutil.EnclosingFile(curCall)\n\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_22) {\n\t\t\tcontinue // TypeFor requires go1.22\n\t\t}\n\t\ttokFile := pass.Fset.File(file.Pos())\n\n\t\t// Format the type as valid Go syntax.\n\t\t// TODO(adonovan): FileQualifier needs to respect\n\t\t// visibility at the current point, and either fail\n\t\t// or edit the imports as needed.\n\t\tqual := typesinternal.FileQualifier(file, pass.Pkg)\n\t\ttstr := types.TypeString(t, qual)\n\n\t\tsel, ok := call.Fun.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\tcontinue // e.g. reflect was dot-imported\n\t\t}\n\n\t\t// Don't offer a fix if the type contains an unnamed struct or unnamed\n\t\t// interface because the replacement would be significantly more verbose.\n\t\t// (See golang/go#76698)\n\t\tif isComplicatedType(t) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Don't offer the fix if the type string is too long. We define \"too\n\t\t// long\" as more than three times the length of the original expression\n\t\t// and at least 16 characters (a 3x length increase of a very\n\t\t// short expression should not be cause for skipping the fix).\n\t\toldLen := int(expr.End() - expr.Pos())\n\t\tnewLen := len(tstr)\n\t\tif newLen >= 16 && newLen > 3*oldLen {\n\t\t\tcontinue\n\t\t}\n\n\t\t// If the call argument contains the last use\n\t\t// of a variable, as in:\n\t\t//\tvar zero T\n\t\t//\treflect.TypeOf(zero)\n\t\t// remove the declaration of that variable.\n\t\tcurArg0 := curCall.ChildAt(edge.CallExpr_Args, 0)\n\t\tedits = append(edits, refactor.DeleteUnusedVars(index, info, tokFile, curArg0)...)\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Fun.Pos(),\n\t\t\tEnd:     call.Fun.End(),\n\t\t\tMessage: \"reflect.TypeOf call can be simplified using TypeFor\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t// reflect.TypeOf    (...T value...)\n\t\t\t\t//         ------     -------------\n\t\t\t\t// reflect.TypeFor[T](             )\n\t\t\t\tMessage: \"Replace TypeOf by TypeFor\",\n\t\t\t\tTextEdits: append([]analysis.TextEdit{\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     sel.Sel.Pos(),\n\t\t\t\t\t\tEnd:     sel.Sel.End(),\n\t\t\t\t\t\tNewText: []byte(\"TypeFor[\" + tstr + \"]\"),\n\t\t\t\t\t},\n\t\t\t\t\t// delete (pure) argument\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: call.Lparen + 1,\n\t\t\t\t\t\tEnd: call.Rparen,\n\t\t\t\t\t},\n\t\t\t\t}, edits...),\n\t\t\t}},\n\t\t})\n\t}\n\n\treturn nil, nil\n}\n\n// isComplicatedType reports whether type t is complicated, e.g. it is or contains an\n// unnamed struct, interface, or function signature.\nfunc isComplicatedType(t types.Type) bool {\n\tvar check func(typ types.Type) bool\n\tcheck = func(typ types.Type) bool {\n\t\tswitch t := typ.(type) {\n\t\tcase typesinternal.NamedOrAlias:\n\t\t\tfor ta := range t.TypeArgs().Types() {\n\t\t\t\tif check(ta) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\tcase *types.Struct, *types.Interface, *types.Signature:\n\t\t\t// These are complex types with potentially many elements\n\t\t\t// so we should avoid duplicating their definition.\n\t\t\treturn true\n\t\tcase *types.Pointer:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Slice:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Array:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Chan:\n\t\t\treturn check(t.Elem())\n\t\tcase *types.Map:\n\t\t\treturn check(t.Key()) || check(t.Elem())\n\t\tcase *types.Basic:\n\t\t\treturn false\n\t\tcase *types.TypeParam:\n\t\t\treturn false\n\t\tdefault:\n\t\t\t// Includes types.Union\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn check(t)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/slices.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// Warning: this analyzer is not safe to enable by default.\nvar AppendClippedAnalyzer = &analysis.Analyzer{\n\tName:     \"appendclipped\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"appendclipped\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      appendclipped,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped\",\n}\n\n// The appendclipped pass offers to simplify a tower of append calls:\n//\n//\tappend(append(append(base, a...), b..., c...)\n//\n// with a call to go1.21's slices.Concat(base, a, b, c), or simpler\n// replacements such as slices.Clone(a) in degenerate cases.\n//\n// We offer bytes.Clone in preference to slices.Clone where\n// appropriate, if the package already imports \"bytes\";\n// their behaviors are identical.\n//\n// The base expression must denote a clipped slice (see [isClipped]\n// for definition), otherwise the replacement might eliminate intended\n// side effects to the base slice's array.\n//\n// Examples:\n//\n//\tappend(append(append(x[:0:0], a...), b...), c...) -> slices.Concat(a, b, c)\n//\tappend(append(slices.Clip(a), b...)               -> slices.Concat(a, b)\n//\tappend([]T{}, a...)                               -> slices.Clone(a)\n//\tappend([]string(nil), os.Environ()...)            -> os.Environ()\n//\n// The fix does not always preserve nilness the of base slice when the\n// addends (a, b, c) are all empty (see #73557).\nfunc appendclipped(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"slices\", \"bytes\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tinfo := pass.TypesInfo\n\n\t// sliceArgs is a non-empty (reversed) list of slices to be concatenated.\n\tsimplifyAppendEllipsis := func(file *ast.File, call *ast.CallExpr, base ast.Expr, sliceArgs []ast.Expr) {\n\t\t// Only appends whose base is a clipped slice can be simplified:\n\t\t// We must conservatively assume an append to an unclipped slice\n\t\t// such as append(y[:0], x...) is intended to have effects on y.\n\t\tclipped, empty := clippedSlice(info, base)\n\t\tif clipped == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// If any slice arg has a different type from the base\n\t\t// (and thus the result) don't offer a fix, to avoid\n\t\t// changing the return type, e.g:\n\t\t//\n\t\t//     type S []int\n\t\t//   - x := append([]int(nil), S{}...) // x : []int\n\t\t//   + x := slices.Clone(S{})          // x : S\n\t\t//\n\t\t// We could do better by inserting an explicit generic\n\t\t// instantiation:\n\t\t//\n\t\t//   x := slices.Clone[[]int](S{})\n\t\t//\n\t\t// but this is often unnecessary and unwanted, such as\n\t\t// when the value is used an in assignment context that\n\t\t// provides an explicit type:\n\t\t//\n\t\t//   var x []int = slices.Clone(S{})\n\t\tbaseType := info.TypeOf(base)\n\t\tfor _, arg := range sliceArgs {\n\t\t\tif !types.Identical(info.TypeOf(arg), baseType) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// If the (clipped) base is empty, it may be safely ignored.\n\t\t// Otherwise treat it (or its unclipped subexpression, if possible)\n\t\t// as just another arg (the first) to Concat.\n\t\t//\n\t\t// TODO(adonovan): not so fast! If all the operands\n\t\t// are empty, then the nilness of base matters, because\n\t\t// append preserves nilness whereas Concat does not (#73557).\n\t\tif !empty {\n\t\t\tsliceArgs = append(sliceArgs, clipped)\n\t\t}\n\t\tslices.Reverse(sliceArgs)\n\n\t\t// TODO(adonovan): simplify sliceArgs[0] further: slices.Clone(s) -> s\n\n\t\t// Concat of a single (non-trivial) slice degenerates to Clone.\n\t\tif len(sliceArgs) == 1 {\n\t\t\ts := sliceArgs[0]\n\n\t\t\t// Special case for common but redundant clone of os.Environ().\n\t\t\t// append(zerocap, os.Environ()...) -> os.Environ()\n\t\t\tif scall, ok := s.(*ast.CallExpr); ok {\n\t\t\t\tobj := typeutil.Callee(info, scall)\n\t\t\t\tif typesinternal.IsFunctionNamed(obj, \"os\", \"Environ\") {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\tMessage: \"Redundant clone of os.Environ()\",\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: \"Eliminate redundant clone\",\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\t\t\tNewText: []byte(astutil.Format(pass.Fset, s)),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the slice type is []byte, and the file imports\n\t\t\t// \"bytes\" but not \"slices\", prefer the (behaviorally\n\t\t\t// identical) bytes.Clone for local consistency.\n\t\t\t// https://go.dev/issue/70815#issuecomment-2671572984\n\t\t\tfileImports := func(path string) bool {\n\t\t\t\treturn slices.ContainsFunc(file.Imports, func(spec *ast.ImportSpec) bool {\n\t\t\t\t\treturn first(strconv.Unquote(spec.Path.Value)) == path\n\t\t\t\t})\n\t\t\t}\n\t\t\tclonepkg := cond(\n\t\t\t\ttypes.Identical(info.TypeOf(call), byteSliceType) &&\n\t\t\t\t\t!fileImports(\"slices\") && fileImports(\"bytes\"),\n\t\t\t\t\"bytes\",\n\t\t\t\t\"slices\")\n\n\t\t\t// append(zerocap, s...) -> slices.Clone(s) or bytes.Clone(s)\n\t\t\t//\n\t\t\t// This is unsound if s is empty and its nilness\n\t\t\t// differs from zerocap (#73557).\n\t\t\tprefix, importEdits := refactor.AddImport(info, file, clonepkg, clonepkg, \"Clone\", call.Pos())\n\t\t\tmessage := fmt.Sprintf(\"Replace append with %s.Clone\", clonepkg)\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     call.Pos(),\n\t\t\t\tEnd:     call.End(),\n\t\t\t\tMessage: message,\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: message,\n\t\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{{\n\t\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%sClone(%s)\", prefix, astutil.Format(pass.Fset, s)),\n\t\t\t\t\t}}...),\n\t\t\t\t}},\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// append(append(append(base, a...), b..., c...) -> slices.Concat(base, a, b, c)\n\t\t//\n\t\t// This is unsound if all slices are empty and base is non-nil (#73557).\n\t\tprefix, importEdits := refactor.AddImport(info, file, \"slices\", \"slices\", \"Concat\", call.Pos())\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Pos(),\n\t\t\tEnd:     call.End(),\n\t\t\tMessage: \"Replace append with slices.Concat\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Replace append with slices.Concat\",\n\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{{\n\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\tNewText: fmt.Appendf(nil, \"%sConcat(%s)\", prefix, formatExprs(pass.Fset, sliceArgs)),\n\t\t\t\t}}...),\n\t\t\t}},\n\t\t})\n\t}\n\n\t// Mark nested calls to append so that we don't emit diagnostics for them.\n\tskip := make(map[*ast.CallExpr]bool)\n\n\t// Visit calls of form append(x, y...).\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_21) {\n\t\tfile := curFile.Node().(*ast.File)\n\n\t\tfor curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {\n\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\tif skip[call] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Recursively unwrap ellipsis calls to append, so\n\t\t\t//   append(append(append(base, a...), b..., c...)\n\t\t\t// yields (base, [c b a]).\n\t\t\tbase, slices := ast.Expr(call), []ast.Expr(nil) // base case: (call, nil)\n\t\tagain:\n\t\t\tif call, ok := base.(*ast.CallExpr); ok {\n\t\t\t\tif id, ok := call.Fun.(*ast.Ident); ok &&\n\t\t\t\t\tcall.Ellipsis.IsValid() &&\n\t\t\t\t\tlen(call.Args) == 2 &&\n\t\t\t\t\tinfo.Uses[id] == builtinAppend {\n\n\t\t\t\t\t// Have: append(base, s...)\n\t\t\t\t\tbase, slices = call.Args[0], append(slices, call.Args[1])\n\t\t\t\t\tskip[call] = true\n\t\t\t\t\tgoto again\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif len(slices) > 0 {\n\t\t\t\tsimplifyAppendEllipsis(file, call, base, slices)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// clippedSlice returns res != nil if e denotes a slice that is\n// definitely clipped, that is, its len(s)==cap(s).\n//\n// The value of res is either the same as e or is a subexpression of e\n// that denotes the same slice but without the clipping operation.\n//\n// In addition, it reports whether the slice is definitely empty.\n//\n// Examples of clipped slices:\n//\n//\tx[:0:0]\t\t\t\t(empty)\n//\t[]T(nil)\t\t\t(empty)\n//\tSlice{}\t\t\t\t(empty)\n//\tx[:len(x):len(x)]\t\t(nonempty)  res=x\n//\tx[:k:k]\t \t         \t(nonempty)\n//\tslices.Clip(x)\t\t\t(nonempty)  res=x\n//\n// TODO(adonovan): Add a check that the expression x has no side effects in\n// case x[:len(x):len(x)] -> x. Now the program behavior may change.\nfunc clippedSlice(info *types.Info, e ast.Expr) (res ast.Expr, empty bool) {\n\tswitch e := e.(type) {\n\tcase *ast.SliceExpr:\n\t\t// x[:0:0], x[:len(x):len(x)], x[:k:k]\n\t\tif e.Slice3 && e.High != nil && e.Max != nil && astutil.EqualSyntax(e.High, e.Max) { // x[:k:k]\n\t\t\tres = e\n\t\t\tempty = isZeroIntConst(info, e.High) // x[:0:0]\n\t\t\tif call, ok := e.High.(*ast.CallExpr); ok &&\n\t\t\t\ttypeutil.Callee(info, call) == builtinLen &&\n\t\t\t\tastutil.EqualSyntax(call.Args[0], e.X) {\n\t\t\t\tres = e.X // x[:len(x):len(x)] -> x\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\treturn\n\n\tcase *ast.CallExpr:\n\t\t// []T(nil)?\n\t\tif info.Types[e.Fun].IsType() &&\n\t\t\tis[*ast.Ident](e.Args[0]) &&\n\t\t\tinfo.Uses[e.Args[0].(*ast.Ident)] == builtinNil {\n\t\t\treturn e, true\n\t\t}\n\n\t\t// slices.Clip(x)?\n\t\tobj := typeutil.Callee(info, e)\n\t\tif typesinternal.IsFunctionNamed(obj, \"slices\", \"Clip\") {\n\t\t\treturn e.Args[0], false // slices.Clip(x) -> x\n\t\t}\n\n\tcase *ast.CompositeLit:\n\t\t// Slice{}?\n\t\tif len(e.Elts) == 0 {\n\t\t\treturn e, true\n\t\t}\n\t}\n\treturn nil, false\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/slicescontains.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar SlicesContainsAnalyzer = &analysis.Analyzer{\n\tName: \"slicescontains\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"slicescontains\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: slicescontains,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains\",\n}\n\n// The slicescontains pass identifies loops that can be replaced by a\n// call to slices.Contains{,Func}. For example:\n//\n//\tfor i, elem := range s {\n//\t\tif elem == needle {\n//\t\t\t...\n//\t\t\tbreak\n//\t\t}\n//\t}\n//\n// =>\n//\n//\tif slices.Contains(s, needle) { ... }\n//\n// Variants:\n//   - if the if-condition is f(elem), the replacement\n//     uses slices.ContainsFunc(s, f).\n//   - if the if-body is \"return true\" and the fallthrough\n//     statement is \"return false\" (or vice versa), the\n//     loop becomes \"return [!]slices.Contains(...)\".\n//   - if the if-body is \"found = true\" and the previous\n//     statement is \"found = false\" (or vice versa), the\n//     loop becomes \"found = [!]slices.Contains(...)\".\n//\n// It may change cardinality of effects of the \"needle\" expression.\n// (Mostly this appears to be a desirable optimization, avoiding\n// redundantly repeated evaluation.)\n//\n// TODO(adonovan): Add a check that needle/predicate expression from\n// if-statement has no effects. Now the program behavior may change.\nfunc slicescontains(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"slices\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\t// check is called for each RangeStmt of this form:\n\t//   for i, elem := range s { if cond { ... } }\n\tcheck := func(file *ast.File, curRange inspector.Cursor) {\n\t\trng := curRange.Node().(*ast.RangeStmt)\n\t\tifStmt := rng.Body.List[0].(*ast.IfStmt)\n\n\t\t// isSliceElem reports whether e denotes the\n\t\t// current slice element (elem or s[i]).\n\t\tisSliceElem := func(e ast.Expr) bool {\n\t\t\tif rng.Value != nil && astutil.EqualSyntax(e, rng.Value) {\n\t\t\t\treturn true // \"elem\"\n\t\t\t}\n\t\t\tif x, ok := e.(*ast.IndexExpr); ok &&\n\t\t\t\tastutil.EqualSyntax(x.X, rng.X) &&\n\t\t\t\tastutil.EqualSyntax(x.Index, rng.Key) {\n\t\t\t\treturn true // \"s[i]\"\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\n\t\t// Examine the condition for one of these forms:\n\t\t//\n\t\t// - if elem or s[i] == needle  { ... } => Contains\n\t\t// - if predicate(s[i] or elem) { ... } => ContainsFunc\n\t\tvar (\n\t\t\tfuncName string   // \"Contains\" or \"ContainsFunc\"\n\t\t\targ2     ast.Expr // second argument to func (needle or predicate)\n\t\t)\n\t\tswitch cond := ifStmt.Cond.(type) {\n\t\tcase *ast.BinaryExpr:\n\t\t\tif cond.Op == token.EQL {\n\t\t\t\tvar elem ast.Expr\n\t\t\t\tif isSliceElem(cond.X) {\n\t\t\t\t\tfuncName = \"Contains\"\n\t\t\t\t\telem = cond.X\n\t\t\t\t\targ2 = cond.Y // \"if elem == needle\"\n\t\t\t\t} else if isSliceElem(cond.Y) {\n\t\t\t\t\tfuncName = \"Contains\"\n\t\t\t\t\telem = cond.Y\n\t\t\t\t\targ2 = cond.X // \"if needle == elem\"\n\t\t\t\t}\n\n\t\t\t\t// Reject if elem and needle have different types.\n\t\t\t\tif elem != nil {\n\t\t\t\t\ttElem := info.TypeOf(elem)\n\t\t\t\t\ttNeedle := info.TypeOf(arg2)\n\t\t\t\t\tif !types.Identical(tElem, tNeedle) {\n\t\t\t\t\t\t// Avoid ill-typed slices.Contains([]error, any).\n\t\t\t\t\t\tif !types.AssignableTo(tNeedle, tElem) {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// TODO(adonovan): relax this check to allow\n\t\t\t\t\t\t//   slices.Contains([]error, error(any)),\n\t\t\t\t\t\t// inserting an explicit widening conversion\n\t\t\t\t\t\t// around the needle.\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.CallExpr:\n\t\t\tif len(cond.Args) == 1 &&\n\t\t\t\tisSliceElem(cond.Args[0]) &&\n\t\t\t\ttypeutil.Callee(info, cond) != nil { // not a conversion\n\n\t\t\t\t// Attempt to get signature\n\t\t\t\tsig, isSignature := info.TypeOf(cond.Fun).(*types.Signature)\n\t\t\t\tif isSignature {\n\t\t\t\t\t// skip variadic functions\n\t\t\t\t\tif sig.Variadic() {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Slice element type must match function parameter type.\n\t\t\t\t\tvar (\n\t\t\t\t\t\ttElem  = typeparams.CoreType(info.TypeOf(rng.X)).(*types.Slice).Elem()\n\t\t\t\t\t\ttParam = sig.Params().At(0).Type()\n\t\t\t\t\t)\n\t\t\t\t\tif !types.Identical(tElem, tParam) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfuncName = \"ContainsFunc\"\n\t\t\t\targ2 = cond.Fun // \"if predicate(elem)\"\n\t\t\t}\n\t\t}\n\t\tif funcName == \"\" {\n\t\t\treturn // not a candidate for Contains{,Func}\n\t\t}\n\n\t\t// body is the \"true\" body.\n\t\tbody := ifStmt.Body\n\t\tif len(body.List) == 0 {\n\t\t\t// (We could perhaps delete the loop entirely.)\n\t\t\treturn\n\t\t}\n\n\t\t// Reject if the body, needle or predicate references either range variable.\n\t\tusesRangeVar := func(n ast.Node) bool {\n\t\t\tcur, ok := curRange.FindNode(n)\n\t\t\tif !ok {\n\t\t\t\tpanic(fmt.Sprintf(\"FindNode(%T) failed\", n))\n\t\t\t}\n\t\t\treturn uses(index, cur, info.Defs[rng.Key.(*ast.Ident)]) ||\n\t\t\t\trng.Value != nil && uses(index, cur, info.Defs[rng.Value.(*ast.Ident)])\n\t\t}\n\t\tif usesRangeVar(body) {\n\t\t\t// Body uses range var \"i\" or \"elem\".\n\t\t\t//\n\t\t\t// (The check for \"i\" could be relaxed when we\n\t\t\t// generalize this to support slices.Index;\n\t\t\t// and the check for \"elem\" could be relaxed\n\t\t\t// if \"elem\" can safely be replaced in the\n\t\t\t// body by \"needle\".)\n\t\t\treturn\n\t\t}\n\t\tif usesRangeVar(arg2) {\n\t\t\treturn\n\t\t}\n\n\t\t// Prepare slices.Contains{,Func} call.\n\t\tprefix, importEdits := refactor.AddImport(info, file, \"slices\", \"slices\", funcName, rng.Pos())\n\t\tcontains := fmt.Sprintf(\"%s%s(%s, %s)\",\n\t\t\tprefix,\n\t\t\tfuncName,\n\t\t\tastutil.Format(pass.Fset, rng.X),\n\t\t\tastutil.Format(pass.Fset, arg2))\n\n\t\treport := func(edits []analysis.TextEdit) {\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     rng.Pos(),\n\t\t\t\tEnd:     rng.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"Loop can be simplified using slices.%s\", funcName),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   \"Replace loop by call to slices.\" + funcName,\n\t\t\t\t\tTextEdits: append(edits, importEdits...),\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\n\t\t// Last statement of body must return/break out of the loop.\n\t\t//\n\t\t// TODO(adonovan): opt:consider avoiding FindNode with new API of form:\n\t\t//    curRange.Get(edge.RangeStmt_Body, -1).\n\t\t//             Get(edge.BodyStmt_List, 0).\n\t\t//             Get(edge.IfStmt_Body)\n\t\tcurBody, _ := curRange.FindNode(body)\n\t\tcurLastStmt, _ := curBody.LastChild()\n\n\t\t// Reject if any statement in the body except the\n\t\t// last has a free continuation (continue or break)\n\t\t// that might affected by melting down the loop.\n\t\t//\n\t\t// TODO(adonovan): relax check by analyzing branch target.\n\t\tnumBodyStmts := 0\n\t\tfor curBodyStmt := range curBody.Children() {\n\t\t\tnumBodyStmts += 1\n\t\t\tif curBodyStmt != curLastStmt {\n\t\t\t\tfor range curBodyStmt.Preorder((*ast.BranchStmt)(nil), (*ast.ReturnStmt)(nil)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tswitch lastStmt := curLastStmt.Node().(type) {\n\t\tcase *ast.ReturnStmt:\n\t\t\t// Have: for ... range seq { if ... { stmts; return x } }\n\n\t\t\t// Special case:\n\t\t\t// body={ return true } next=\"return false\"   (or negation)\n\t\t\t// => return [!]slices.Contains(...)\n\t\t\tif curNext, ok := curRange.NextSibling(); ok {\n\t\t\t\tnextStmt := curNext.Node().(ast.Stmt)\n\t\t\t\ttval := isReturnTrueOrFalse(info, lastStmt)\n\t\t\t\tfval := isReturnTrueOrFalse(info, nextStmt)\n\t\t\t\tif len(body.List) == 1 && tval*fval < 0 {\n\t\t\t\t\t//    for ... { if ... { return true/false } }\n\t\t\t\t\t// => return [!]slices.Contains(...)\n\t\t\t\t\treport([]analysis.TextEdit{\n\t\t\t\t\t\t// Delete the range statement and following space.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: rng.Pos(),\n\t\t\t\t\t\t\tEnd: nextStmt.Pos(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// Change return to [!]slices.Contains(...).\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: nextStmt.Pos(),\n\t\t\t\t\t\t\tEnd: nextStmt.End(),\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"return %s%s\",\n\t\t\t\t\t\t\t\tcond(tval > 0, \"\", \"!\"),\n\t\t\t\t\t\t\t\tcontains),\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// General case:\n\t\t\t// => if slices.Contains(...) { stmts; return x }\n\t\t\treport([]analysis.TextEdit{\n\t\t\t\t// Replace \"for ... { if ... \" with \"if slices.Contains(...)\".\n\t\t\t\t{\n\t\t\t\t\tPos:     rng.Pos(),\n\t\t\t\t\tEnd:     ifStmt.Body.Pos(),\n\t\t\t\t\tNewText: fmt.Appendf(nil, \"if %s \", contains),\n\t\t\t\t},\n\t\t\t\t// Delete '}' of range statement and preceding space.\n\t\t\t\t{\n\t\t\t\t\tPos: ifStmt.Body.End(),\n\t\t\t\t\tEnd: rng.End(),\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn\n\n\t\tcase *ast.BranchStmt:\n\t\t\tif lastStmt.Tok == token.BREAK && lastStmt.Label == nil { // unlabeled break\n\t\t\t\t// Have: for ... { if ... { stmts; break } }\n\t\t\t\tif numBodyStmts == 1 {\n\t\t\t\t\t// If the only stmt in the body is an unlabeled \"break\" that\n\t\t\t\t\t// will get deleted in the fix, don't suggest a fix, as it\n\t\t\t\t\t// produces confusing code:\n\t\t\t\t\t//    if slices.Contains(slice, f) {}\n\t\t\t\t\t// Explicitly discarding the result isn't much better:\n\t\t\t\t\t//    _ = slices.Contains(slice, f) // just for effects\n\t\t\t\t\t// See https://go.dev/issue/77677.\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvar prevStmt ast.Stmt // previous statement to range (if any)\n\t\t\t\tif curPrev, ok := curRange.PrevSibling(); ok {\n\t\t\t\t\t// If the RangeStmt's previous sibling is a Stmt,\n\t\t\t\t\t// the RangeStmt must be among the Body list of\n\t\t\t\t\t// a BlockStmt, CauseClause, or CommClause.\n\t\t\t\t\t// In all cases, the prevStmt is the immediate\n\t\t\t\t\t// predecessor of the RangeStmt during execution.\n\t\t\t\t\t//\n\t\t\t\t\t// (This is not true for Stmts in general;\n\t\t\t\t\t// see [Cursor.Children] and #71074.)\n\t\t\t\t\tprevStmt, _ = curPrev.Node().(ast.Stmt)\n\t\t\t\t}\n\n\t\t\t\t// Special case:\n\t\t\t\t// prev=\"lhs = false\" body={ lhs = true; break }\n\t\t\t\t// => lhs = slices.Contains(...) (or its negation)\n\t\t\t\tif assign, ok := body.List[0].(*ast.AssignStmt); ok &&\n\t\t\t\t\tlen(body.List) == 2 &&\n\t\t\t\t\tassign.Tok == token.ASSIGN &&\n\t\t\t\t\tlen(assign.Lhs) == 1 &&\n\t\t\t\t\tlen(assign.Rhs) == 1 {\n\n\t\t\t\t\t// Have: body={ lhs = rhs; break }\n\t\t\t\t\tassignBool := isTrueOrFalse(info, assign.Rhs[0])\n\t\t\t\t\tif prevAssign, ok := prevStmt.(*ast.AssignStmt); ok &&\n\t\t\t\t\t\tlen(prevAssign.Lhs) == 1 &&\n\t\t\t\t\t\tlen(prevAssign.Rhs) == 1 &&\n\t\t\t\t\t\tassignBool != 0 && // non-bool assignments don't apply in this case\n\t\t\t\t\t\tastutil.EqualSyntax(prevAssign.Lhs[0], assign.Lhs[0]) &&\n\t\t\t\t\t\tassignBool == -isTrueOrFalse(info, prevAssign.Rhs[0]) {\n\n\t\t\t\t\t\t// Have:\n\t\t\t\t\t\t//    lhs = false\n\t\t\t\t\t\t//    for ... { if ... { lhs = true; break } }\n\t\t\t\t\t\t//  =>\n\t\t\t\t\t\t//    lhs = slices.Contains(...)\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// TODO(adonovan):\n\t\t\t\t\t\t// - support \"var lhs bool = false\" and variants.\n\t\t\t\t\t\t// - allow the break to be omitted.\n\t\t\t\t\t\tneg := cond(assignBool < 0, \"!\", \"\")\n\t\t\t\t\t\treport([]analysis.TextEdit{\n\t\t\t\t\t\t\t// Replace \"rhs\" of previous assignment by [!]slices.Contains(...)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos:     prevAssign.Rhs[0].Pos(),\n\t\t\t\t\t\t\t\tEnd:     prevAssign.Rhs[0].End(),\n\t\t\t\t\t\t\t\tNewText: []byte(neg + contains),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// Delete the loop and preceding space.\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos: prevAssign.Rhs[0].End(),\n\t\t\t\t\t\t\t\tEnd: rng.End(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// General case:\n\t\t\t\t//    for ... { if ...        { stmts; break } }\n\t\t\t\t// => if slices.Contains(...) { stmts        }\n\t\t\t\treport([]analysis.TextEdit{\n\t\t\t\t\t// Replace \"for ... { if ... \" with \"if slices.Contains(...)\".\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     rng.Pos(),\n\t\t\t\t\t\tEnd:     ifStmt.Body.Pos(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"if %s \", contains),\n\t\t\t\t\t},\n\t\t\t\t\t// Delete break statement and preceding space.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: func() token.Pos {\n\t\t\t\t\t\t\tif len(body.List) > 1 {\n\t\t\t\t\t\t\t\tbeforeBreak, _ := curLastStmt.PrevSibling()\n\t\t\t\t\t\t\t\treturn beforeBreak.Node().End()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn lastStmt.Pos()\n\t\t\t\t\t\t}(),\n\t\t\t\t\t\tEnd: lastStmt.End(),\n\t\t\t\t\t},\n\t\t\t\t\t// Delete '}' of range statement and preceding space.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: ifStmt.Body.End(),\n\t\t\t\t\t\tEnd: rng.End(),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_21) {\n\t\tfile := curFile.Node().(*ast.File)\n\n\t\tfor curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {\n\t\t\trng := curRange.Node().(*ast.RangeStmt)\n\n\t\t\tif is[*ast.Ident](rng.Key) &&\n\t\t\t\trng.Tok == token.DEFINE &&\n\t\t\t\tlen(rng.Body.List) == 1 &&\n\t\t\t\tis[*types.Slice](typeparams.CoreType(info.TypeOf(rng.X))) {\n\n\t\t\t\t// Have:\n\t\t\t\t// - for _, elem := range s { S }\n\t\t\t\t// - for i       := range s { S }\n\n\t\t\t\tif ifStmt, ok := rng.Body.List[0].(*ast.IfStmt); ok &&\n\t\t\t\t\tifStmt.Init == nil && ifStmt.Else == nil {\n\n\t\t\t\t\t// Have: for i, elem := range s { if cond { ... } }\n\t\t\t\t\tcheck(file, curRange)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// -- helpers --\n\n// isReturnTrueOrFalse returns nonzero if stmt returns true (+1) or false (-1).\nfunc isReturnTrueOrFalse(info *types.Info, stmt ast.Stmt) int {\n\tif ret, ok := stmt.(*ast.ReturnStmt); ok && len(ret.Results) == 1 {\n\t\treturn isTrueOrFalse(info, ret.Results[0])\n\t}\n\treturn 0\n}\n\n// isTrueOrFalse returns nonzero if expr is literally true (+1) or false (-1).\nfunc isTrueOrFalse(info *types.Info, expr ast.Expr) int {\n\tif id, ok := expr.(*ast.Ident); ok {\n\t\tswitch info.Uses[id] {\n\t\tcase builtinTrue:\n\t\t\treturn +1\n\t\tcase builtinFalse:\n\t\t\treturn -1\n\t\t}\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/slicesdelete.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// Warning: this analyzer is not safe to enable by default (not nil-preserving).\nvar SlicesDeleteAnalyzer = &analysis.Analyzer{\n\tName:     \"slicesdelete\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"slicesdelete\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      slicesdelete,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete\",\n}\n\n// The slicesdelete pass attempts to replace instances of append(s[:i], s[i+k:]...)\n// with slices.Delete(s, i, i+k) where k is some positive constant.\n// Other variations that will also have suggested replacements include:\n// append(s[:i-1], s[i:]...) and append(s[:i+k1], s[i+k2:]) where k2 > k1.\nfunc slicesdelete(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"slices\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tinfo := pass.TypesInfo\n\treport := func(file *ast.File, call *ast.CallExpr, slice1, slice2 *ast.SliceExpr) {\n\t\tinsert := func(pos token.Pos, text string) analysis.TextEdit {\n\t\t\treturn analysis.TextEdit{Pos: pos, End: pos, NewText: []byte(text)}\n\t\t}\n\t\tisIntExpr := func(e ast.Expr) bool {\n\t\t\treturn types.Identical(types.Default(info.TypeOf(e)), builtinInt.Type())\n\t\t}\n\t\tisIntShadowed := func() bool {\n\t\t\tscope := info.Scopes[file].Innermost(call.Lparen)\n\t\t\tif _, obj := scope.LookupParent(\"int\", call.Lparen); obj != builtinInt {\n\t\t\t\treturn true // int type is shadowed\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\n\t\tprefix, edits := refactor.AddImport(info, file, \"slices\", \"slices\", \"Delete\", call.Pos())\n\t\t// append's indices may be any integer type; slices.Delete requires int.\n\t\t// Insert int conversions as needed (and if possible).\n\t\tif isIntShadowed() && (!isIntExpr(slice1.High) || !isIntExpr(slice2.Low)) {\n\t\t\treturn\n\t\t}\n\t\tif !isIntExpr(slice1.High) {\n\t\t\tedits = append(edits,\n\t\t\t\tinsert(slice1.High.Pos(), \"int(\"),\n\t\t\t\tinsert(slice1.High.End(), \")\"),\n\t\t\t)\n\t\t}\n\t\tif !isIntExpr(slice2.Low) {\n\t\t\tedits = append(edits,\n\t\t\t\tinsert(slice2.Low.Pos(), \"int(\"),\n\t\t\t\tinsert(slice2.Low.End(), \")\"),\n\t\t\t)\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Pos(),\n\t\t\tEnd:     call.End(),\n\t\t\tMessage: \"Replace append with slices.Delete\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Replace append with slices.Delete\",\n\t\t\t\tTextEdits: append(edits, []analysis.TextEdit{\n\t\t\t\t\t// Change name of called function.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\tNewText: []byte(prefix + \"Delete\"),\n\t\t\t\t\t},\n\t\t\t\t\t// Delete ellipsis.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: call.Ellipsis,\n\t\t\t\t\t\tEnd: call.Ellipsis + token.Pos(len(\"...\")), // delete ellipsis\n\t\t\t\t\t},\n\t\t\t\t\t// Remove second slice variable name.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: slice2.X.Pos(),\n\t\t\t\t\t\tEnd: slice2.X.End(),\n\t\t\t\t\t},\n\t\t\t\t\t// Insert after first slice variable name.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     slice1.X.End(),\n\t\t\t\t\t\tNewText: []byte(\", \"),\n\t\t\t\t\t},\n\t\t\t\t\t// Remove brackets and colons.\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: slice1.Lbrack,\n\t\t\t\t\t\tEnd: slice1.High.Pos(),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: slice1.Rbrack,\n\t\t\t\t\t\tEnd: slice1.Rbrack + 1,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: slice2.Lbrack,\n\t\t\t\t\t\tEnd: slice2.Lbrack + 1,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPos: slice2.Low.End(),\n\t\t\t\t\t\tEnd: slice2.Rbrack + 1,\n\t\t\t\t\t},\n\t\t\t\t}...),\n\t\t\t}},\n\t\t})\n\t}\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_21) {\n\t\tfile := curFile.Node().(*ast.File)\n\t\tfor curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {\n\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\tif id, ok := call.Fun.(*ast.Ident); ok && len(call.Args) == 2 {\n\t\t\t\t// Verify we have append with two slices and ... operator,\n\t\t\t\t// the first slice has no low index and second slice has no\n\t\t\t\t// high index, and not a three-index slice.\n\t\t\t\tif call.Ellipsis.IsValid() && info.Uses[id] == builtinAppend {\n\t\t\t\t\tslice1, ok1 := call.Args[0].(*ast.SliceExpr)\n\t\t\t\t\tslice2, ok2 := call.Args[1].(*ast.SliceExpr)\n\t\t\t\t\tif ok1 && slice1.Low == nil && !slice1.Slice3 &&\n\t\t\t\t\t\tok2 && slice2.High == nil && !slice2.Slice3 &&\n\t\t\t\t\t\tastutil.EqualSyntax(slice1.X, slice2.X) &&\n\t\t\t\t\t\ttypesinternal.NoEffects(info, slice1.X) &&\n\t\t\t\t\t\tincreasingSliceIndices(info, slice1.High, slice2.Low) {\n\t\t\t\t\t\t// Have append(s[:a], s[b:]...) where we can verify a < b.\n\t\t\t\t\t\treport(file, call, slice1, slice2)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// Given two slice indices a and b, returns true if we can verify that a < b.\n// It recognizes certain forms such as i+k1 < i+k2 where k1 < k2.\nfunc increasingSliceIndices(info *types.Info, a, b ast.Expr) bool {\n\t// Given an expression of the form i±k, returns (i, k)\n\t// where k is a signed constant. Otherwise it returns (e, 0).\n\tsplit := func(e ast.Expr) (ast.Expr, constant.Value) {\n\t\tif binary, ok := e.(*ast.BinaryExpr); ok && (binary.Op == token.SUB || binary.Op == token.ADD) {\n\t\t\t// Negate constants if operation is subtract instead of add\n\t\t\tif k := info.Types[binary.Y].Value; k != nil {\n\t\t\t\treturn binary.X, constant.UnaryOp(binary.Op, k, 0) // i ± k\n\t\t\t}\n\t\t}\n\t\treturn e, constant.MakeInt64(0)\n\t}\n\n\t// Handle case where either a or b is a constant\n\tak := info.Types[a].Value\n\tbk := info.Types[b].Value\n\tif ak != nil || bk != nil {\n\t\treturn ak != nil && bk != nil && constant.Compare(ak, token.LSS, bk)\n\t}\n\n\tai, ak := split(a)\n\tbi, bk := split(b)\n\treturn astutil.EqualSyntax(ai, bi) && constant.Compare(ak, token.LSS, bk)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/sortslice.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// (Not to be confused with go/analysis/passes/sortslice.)\nvar SlicesSortAnalyzer = &analysis.Analyzer{\n\tName: \"slicessort\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"slicessort\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: slicessort,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicessort\",\n}\n\n// The slicessort pass replaces sort.Slice(slice, less) with\n// slices.Sort(slice) when slice is a []T and less is a FuncLit\n// equivalent to cmp.Ordered[T].\n//\n//\t\tsort.Slice(s, func(i, j int) bool { return s[i] < s[j] })\n//\t  =>\tslices.Sort(s)\n//\n// There is no slices.SortStable.\n//\n// TODO(adonovan): support\n//\n//   - sort.Slice(s, func(i, j int) bool { return s[i] ... s[j] })\n//     -> slices.SortFunc(s, func(x, y T) int { return x ... y })\n//     iff all uses of i, j can be replaced by s[i], s[j] and \"<\" can be replaced with cmp.Compare.\n//\n//   - As above for sort.SliceStable -> slices.SortStableFunc.\n//\n//   - sort.Sort(x) where x has a named slice type whose Less method is the natural order.\n//     -> sort.Slice(x)\nfunc slicessort(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"slices\", \"sort\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tinfo      = pass.TypesInfo\n\t\tindex     = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tsortSlice = index.Object(\"sort\", \"Slice\")\n\t)\n\tfor curCall := range index.Calls(sortSlice) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tif lit, ok := call.Args[1].(*ast.FuncLit); ok && len(lit.Body.List) == 1 {\n\t\t\tsig := info.Types[lit.Type].Type.(*types.Signature)\n\n\t\t\t// Have: sort.Slice(s, func(i, j int) bool { return ... })\n\t\t\ts := call.Args[0]\n\t\t\ti := sig.Params().At(0)\n\t\t\tj := sig.Params().At(1)\n\n\t\t\tif ret, ok := lit.Body.List[0].(*ast.ReturnStmt); ok {\n\t\t\t\tif compare, ok := ret.Results[0].(*ast.BinaryExpr); ok && compare.Op == token.LSS {\n\t\t\t\t\t// isIndex reports whether e is s[v].\n\t\t\t\t\tisIndex := func(e ast.Expr, v *types.Var) bool {\n\t\t\t\t\t\tindex, ok := e.(*ast.IndexExpr)\n\t\t\t\t\t\treturn ok &&\n\t\t\t\t\t\t\tastutil.EqualSyntax(index.X, s) &&\n\t\t\t\t\t\t\tis[*ast.Ident](index.Index) &&\n\t\t\t\t\t\t\tinfo.Uses[index.Index.(*ast.Ident)] == v\n\t\t\t\t\t}\n\t\t\t\t\tfile := astutil.EnclosingFile(curCall)\n\t\t\t\t\tif isIndex(compare.X, i) && isIndex(compare.Y, j) &&\n\t\t\t\t\t\tanalyzerutil.FileUsesGoVersion(pass, file, versions.Go1_21) {\n\t\t\t\t\t\t// Have: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })\n\n\t\t\t\t\t\tprefix, importEdits := refactor.AddImport(\n\t\t\t\t\t\t\tinfo, file, \"slices\", \"slices\", \"Sort\", call.Pos())\n\n\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t// Highlight \"sort.Slice\".\n\t\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\t\tMessage: \"sort.Slice can be modernized using slices.Sort\",\n\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\tMessage: \"Replace sort.Slice call by slices.Sort\",\n\t\t\t\t\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// Replace sort.Slice with slices.Sort.\n\t\t\t\t\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(prefix + \"Sort\"),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// Eliminate FuncLit.\n\t\t\t\t\t\t\t\t\t\tPos: call.Args[0].End(),\n\t\t\t\t\t\t\t\t\t\tEnd: call.Rparen,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}...),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/stditerators.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nvar stditeratorsAnalyzer = &analysis.Analyzer{\n\tName: \"stditerators\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"stditerators\"),\n\tRequires: []*analysis.Analyzer{\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: stditerators,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stditerators\",\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.StdIteratorsModernizer = stditeratorsAnalyzer\n}\n\n// stditeratorsTable records std types that have legacy T.{Len,At}\n// iteration methods as well as a newer T.All method that returns an\n// iter.Seq.\nvar stditeratorsTable = [...]struct {\n\tpkgpath, typename, lenmethod, atmethod, itermethod, elemname string\n\n\tseqn int // 1 or 2 => \"for x\" or \"for _, x\"\n}{\n\t// Example: in go/types, (*Tuple).Variables returns an\n\t// iterator that replaces a loop over (*Tuple).{Len,At}.\n\t// The loop variable is named \"v\".\n\t{\"go/types\", \"Interface\", \"NumEmbeddeds\", \"EmbeddedType\", \"EmbeddedTypes\", \"etyp\", 1},\n\t{\"go/types\", \"Interface\", \"NumExplicitMethods\", \"ExplicitMethod\", \"ExplicitMethods\", \"method\", 1},\n\t{\"go/types\", \"Interface\", \"NumMethods\", \"Method\", \"Methods\", \"method\", 1},\n\t{\"go/types\", \"MethodSet\", \"Len\", \"At\", \"Methods\", \"method\", 1},\n\t{\"go/types\", \"Named\", \"NumMethods\", \"Method\", \"Methods\", \"method\", 1},\n\t{\"go/types\", \"Scope\", \"NumChildren\", \"Child\", \"Children\", \"child\", 1},\n\t{\"go/types\", \"Struct\", \"NumFields\", \"Field\", \"Fields\", \"field\", 1},\n\t{\"go/types\", \"Tuple\", \"Len\", \"At\", \"Variables\", \"v\", 1},\n\t{\"go/types\", \"TypeList\", \"Len\", \"At\", \"Types\", \"t\", 1},\n\t{\"go/types\", \"TypeParamList\", \"Len\", \"At\", \"TypeParams\", \"tparam\", 1},\n\t{\"go/types\", \"Union\", \"Len\", \"Term\", \"Terms\", \"term\", 1},\n\t{\"reflect\", \"Type\", \"NumField\", \"Field\", \"Fields\", \"field\", 1},\n\t{\"reflect\", \"Type\", \"NumMethod\", \"Method\", \"Methods\", \"method\", 1},\n\t{\"reflect\", \"Type\", \"NumIn\", \"In\", \"Ins\", \"in\", 1},\n\t{\"reflect\", \"Type\", \"NumOut\", \"Out\", \"Outs\", \"out\", 1},\n\t{\"reflect\", \"Value\", \"NumField\", \"Field\", \"Fields\", \"field\", 2},\n\t{\"reflect\", \"Value\", \"NumMethod\", \"Method\", \"Methods\", \"method\", 2},\n}\n\n// stditerators suggests fixes to replace loops using Len/At-style\n// iterator APIs by a range loop over an iterator. The set of\n// participating types and methods is defined by [iteratorsTable].\n//\n// Pattern:\n//\n//\tfor i := 0; i < x.Len(); i++ {\n//\t\tuse(x.At(i))\n//\t}\n//\n// =>\n//\n//\tfor elem := range x.All() {\n//\t\tuse(elem)\n//\t}\n//\n// Variant:\n//\n//\tfor i := range x.Len() { ... }\n//\n// Note: Iterators have a dynamic cost. How do we know that\n// the user hasn't intentionally chosen not to use an\n// iterator for that reason? We don't want to go fix to\n// undo optimizations. Do we need a suppression mechanism?\n//\n// TODO(adonovan): recognize the more complex patterns that\n// could make full use of both components of an iter.Seq2, e.g.\n//\n//\tfor i := 0; i < v.NumField(); i++ {\n//\t\tuse(v.Field(i), v.Type().Field(i))\n//\t}\n//\n// =>\n//\n//\tfor structField, field := range v.Fields() {\n//\t\tuse(structField, field)\n//\t}\nfunc stditerators(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\t)\n\n\tfor _, row := range stditeratorsTable {\n\t\t// Don't offer fixes within the package\n\t\t// that defines the iterator in question.\n\t\tif within(pass, row.pkgpath) {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar (\n\t\t\tlenMethod = index.Selection(row.pkgpath, row.typename, row.lenmethod)\n\t\t\tatMethod  = index.Selection(row.pkgpath, row.typename, row.atmethod)\n\t\t)\n\n\t\t// chooseName returns an appropriate fresh name\n\t\t// for the index variable of the iterator loop\n\t\t// whose body is specified.\n\t\t//\n\t\t// If the loop body starts with\n\t\t//\n\t\t//     for ... { e := x.At(i); use(e) }\n\t\t//\n\t\t// or\n\t\t//\n\t\t//     for ... { if e := x.At(i); cond { use(e) } }\n\t\t//\n\t\t// then chooseName prefers the name e and additionally\n\t\t// returns the var's symbol. We'll transform this to:\n\t\t//\n\t\t//     for e := range x.Len() { e := e; use(e) }\n\t\t//\n\t\t// which leaves a redundant assignment that a\n\t\t// subsequent 'forvar' pass will eliminate.\n\t\tchooseName := func(curBody inspector.Cursor, x ast.Expr, i *types.Var) (string, *types.Var) {\n\n\t\t\t// isVarAssign reports whether stmt has the form v := x.At(i)\n\t\t\t// and returns the variable if so.\n\t\t\tisVarAssign := func(stmt ast.Stmt) *types.Var {\n\t\t\t\tif assign, ok := stmt.(*ast.AssignStmt); ok &&\n\t\t\t\t\tassign.Tok == token.DEFINE &&\n\t\t\t\t\tlen(assign.Lhs) == 1 &&\n\t\t\t\t\tlen(assign.Rhs) == 1 &&\n\t\t\t\t\tis[*ast.Ident](assign.Lhs[0]) {\n\t\t\t\t\t// call to x.At(i)?\n\t\t\t\t\tif call, ok := assign.Rhs[0].(*ast.CallExpr); ok &&\n\t\t\t\t\t\ttypeutil.Callee(info, call) == atMethod &&\n\t\t\t\t\t\tastutil.EqualSyntax(ast.Unparen(call.Fun).(*ast.SelectorExpr).X, x) &&\n\t\t\t\t\t\tis[*ast.Ident](call.Args[0]) &&\n\t\t\t\t\t\tinfo.Uses[call.Args[0].(*ast.Ident)] == i {\n\t\t\t\t\t\t// Have: elem := x.At(i)\n\t\t\t\t\t\tid := assign.Lhs[0].(*ast.Ident)\n\t\t\t\t\t\treturn info.Defs[id].(*types.Var)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tbody := curBody.Node().(*ast.BlockStmt)\n\t\t\tif len(body.List) > 0 {\n\t\t\t\t// Is body { elem := x.At(i); ... } ?\n\t\t\t\tif v := isVarAssign(body.List[0]); v != nil {\n\t\t\t\t\treturn v.Name(), v\n\t\t\t\t}\n\n\t\t\t\t// Or { if elem := x.At(i); cond { ... } } ?\n\t\t\t\tif ifstmt, ok := body.List[0].(*ast.IfStmt); ok && ifstmt.Init != nil {\n\t\t\t\t\tif v := isVarAssign(ifstmt.Init); v != nil {\n\t\t\t\t\t\treturn v.Name(), v\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tloop := curBody.Parent().Node()\n\t\t\t// We generate a new name only if the preferred name is already declared here\n\t\t\t// and is used within the loop body.\n\t\t\tname := freshName(info, index, info.Scopes[loop], loop.Pos(), curBody, curBody, token.NoPos, row.elemname)\n\t\t\treturn name, nil\n\t\t}\n\n\t\t// Process each call of x.Len().\n\tnextCall:\n\t\tfor curLenCall := range index.Calls(lenMethod) {\n\t\t\tlenSel, ok := ast.Unparen(curLenCall.Node().(*ast.CallExpr).Fun).(*ast.SelectorExpr)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// lenSel is \"x.Len\"\n\n\t\t\tvar (\n\t\t\t\trng      analysis.Range   // where to report diagnostic\n\t\t\t\tcurBody  inspector.Cursor // loop body\n\t\t\t\tindexVar *types.Var       // old loop index var\n\t\t\t\telemVar  *types.Var       // existing \"elem := x.At(i)\" var, if present\n\t\t\t\telem     string           // name for new loop var\n\t\t\t\tedits    []analysis.TextEdit\n\t\t\t)\n\n\t\t\t// Analyze enclosing loop.\n\t\t\tswitch curLenCall.ParentEdgeKind() {\n\t\t\tcase edge.BinaryExpr_Y:\n\t\t\t\t// pattern 1: for i := 0; i < x.Len(); i++ { ... }\n\t\t\t\tvar (\n\t\t\t\t\tcurCmp = curLenCall.Parent()\n\t\t\t\t\tcmp    = curCmp.Node().(*ast.BinaryExpr)\n\t\t\t\t)\n\t\t\t\tif cmp.Op != token.LSS ||\n\t\t\t\t\tcurCmp.ParentEdgeKind() != edge.ForStmt_Cond {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif id, ok := cmp.X.(*ast.Ident); ok {\n\t\t\t\t\t// Have: for _; i < x.Len(); _ { ... }\n\t\t\t\t\tvar (\n\t\t\t\t\t\tv      = info.Uses[id].(*types.Var)\n\t\t\t\t\t\tcurFor = curCmp.Parent()\n\t\t\t\t\t\tloop   = curFor.Node().(*ast.ForStmt)\n\t\t\t\t\t)\n\t\t\t\t\tif v != isIncrementLoop(info, loop) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// Have: for i := 0; i < x.Len(); i++ { ... }.\n\t\t\t\t\t//       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\t\t\t\t\trng = astutil.RangeOf(loop.For, loop.Post.End())\n\t\t\t\t\tindexVar = v\n\t\t\t\t\tcurBody = curFor.ChildAt(edge.ForStmt_Body, -1)\n\t\t\t\t\telem, elemVar = chooseName(curBody, lenSel.X, indexVar)\n\t\t\t\t\telemPrefix := cond(row.seqn == 2, \"_, \", \"\")\n\n\t\t\t\t\t//\tfor i       := 0; i < x.Len(); i++ {\n\t\t\t\t\t//          ----       -------  ---  -----\n\t\t\t\t\t//\tfor elem    := range  x.All()      {\n\t\t\t\t\t// or   for _, elem := ...\n\t\t\t\t\tedits = []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     v.Pos(),\n\t\t\t\t\t\t\tEnd:     v.Pos() + token.Pos(len(v.Name())),\n\t\t\t\t\t\t\tNewText: []byte(elemPrefix + elem),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     loop.Init.(*ast.AssignStmt).Rhs[0].Pos(),\n\t\t\t\t\t\t\tEnd:     cmp.Y.Pos(),\n\t\t\t\t\t\t\tNewText: []byte(\"range \"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     lenSel.Sel.Pos(),\n\t\t\t\t\t\t\tEnd:     lenSel.Sel.End(),\n\t\t\t\t\t\t\tNewText: []byte(row.itermethod),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: curLenCall.Node().End(),\n\t\t\t\t\t\t\tEnd: loop.Post.End(),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase edge.RangeStmt_X:\n\t\t\t\t// pattern 2: for i := range x.Len() { ... }\n\t\t\t\tvar (\n\t\t\t\t\tcurRange = curLenCall.Parent()\n\t\t\t\t\tloop     = curRange.Node().(*ast.RangeStmt)\n\t\t\t\t)\n\t\t\t\tif id, ok := loop.Key.(*ast.Ident); ok &&\n\t\t\t\t\tloop.Value == nil &&\n\t\t\t\t\tloop.Tok == token.DEFINE {\n\t\t\t\t\t// Have: for i := range x.Len() { ... }\n\t\t\t\t\t//                ~~~~~~~~~~~~~\n\n\t\t\t\t\trng = astutil.RangeOf(loop.Range, loop.X.End())\n\t\t\t\t\tindexVar = info.Defs[id].(*types.Var)\n\t\t\t\t\tcurBody = curRange.ChildAt(edge.RangeStmt_Body, -1)\n\t\t\t\t\telem, elemVar = chooseName(curBody, lenSel.X, indexVar)\n\t\t\t\t\telemPrefix := cond(row.seqn == 2, \"_, \", \"\")\n\n\t\t\t\t\t//\tfor i    := range x.Len() {\n\t\t\t\t\t//          ----            ---\n\t\t\t\t\t//\tfor elem := range x.All() {\n\t\t\t\t\tedits = []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     loop.Key.Pos(),\n\t\t\t\t\t\t\tEnd:     loop.Key.End(),\n\t\t\t\t\t\t\tNewText: []byte(elemPrefix + elem),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     lenSel.Sel.Pos(),\n\t\t\t\t\t\t\tEnd:     lenSel.Sel.End(),\n\t\t\t\t\t\t\tNewText: []byte(row.itermethod),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif indexVar == nil {\n\t\t\t\tcontinue // no loop of the required form\n\t\t\t}\n\n\t\t\t// TODO(adonovan): what about possible\n\t\t\t// modifications of x within the loop?\n\t\t\t// Aliasing seems to make a conservative\n\t\t\t// treatment impossible.\n\n\t\t\t// Check that all uses of var i within loop body are x.At(i).\n\t\t\tfor curUse := range index.Uses(indexVar) {\n\t\t\t\tif !curBody.Contains(curUse) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif ek, argidx := curUse.ParentEdge(); ek != edge.CallExpr_Args || argidx != 0 {\n\t\t\t\t\tcontinue nextCall // use is not arg of call\n\t\t\t\t}\n\t\t\t\tcurAtCall := curUse.Parent()\n\t\t\t\tatCall := curAtCall.Node().(*ast.CallExpr)\n\t\t\t\tif typeutil.Callee(info, atCall) != atMethod {\n\t\t\t\t\tcontinue nextCall // use is not arg of call to T.At\n\t\t\t\t}\n\t\t\t\tatSel := ast.Unparen(atCall.Fun).(*ast.SelectorExpr)\n\n\t\t\t\t// Check receivers of Len, At calls match (syntactically).\n\t\t\t\tif !astutil.EqualSyntax(lenSel.X, atSel.X) {\n\t\t\t\t\tcontinue nextCall\n\t\t\t\t}\n\n\t\t\t\t// At each point of use, check that\n\t\t\t\t// the fresh variable is not shadowed\n\t\t\t\t// by an intervening local declaration\n\t\t\t\t// (or by the idiomatic elemVar optionally\n\t\t\t\t// found by chooseName).\n\t\t\t\tif obj := lookup(info, curAtCall, elem); obj != nil && obj != elemVar && obj.Pos() > indexVar.Pos() {\n\t\t\t\t\t// (Ideally, instead of giving up, we would\n\t\t\t\t\t// embellish the name and try again.)\n\t\t\t\t\tcontinue nextCall\n\t\t\t\t}\n\n\t\t\t\t// use(x.At(i))\n\t\t\t\t//     -------\n\t\t\t\t// use(elem   )\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\tPos:     atCall.Pos(),\n\t\t\t\t\tEnd:     atCall.End(),\n\t\t\t\t\tNewText: []byte(elem),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Check file Go version is new enough for the iterator method.\n\t\t\t// (In the long run, version filters are not highly selective,\n\t\t\t// so there's no need to do them first, especially as this check\n\t\t\t// may be somewhat expensive.)\n\t\t\tif v, err := methodGoVersion(row.pkgpath, row.typename, row.itermethod); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t} else if !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curLenCall), v.String()) {\n\t\t\t\tcontinue nextCall\n\t\t\t}\n\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos: rng.Pos(),\n\t\t\t\tEnd: rng.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"%s/%s loop can simplified using %s.%s iteration\",\n\t\t\t\t\trow.lenmethod, row.atmethod, row.typename, row.itermethod),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: fmt.Sprintf(\n\t\t\t\t\t\t\"Replace %s/%s loop with %s.%s iteration\",\n\t\t\t\t\t\trow.lenmethod, row.atmethod, row.typename, row.itermethod),\n\t\t\t\t\tTextEdits: edits,\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// -- helpers --\n\n// methodGoVersion reports the version at which the method\n// (pkgpath.recvtype).method appeared in the standard library.\nfunc methodGoVersion(pkgpath, recvtype, method string) (stdlib.Version, error) {\n\t// TODO(adonovan): opt: this might be inefficient for large packages\n\t// like go/types. If so, memoize using a map (and kill two birds with\n\t// one stone by also memoizing the 'within' check above).\n\tfor _, sym := range stdlib.PackageSymbols[pkgpath] {\n\t\tif sym.Kind == stdlib.Method {\n\t\t\t_, recv, name := sym.SplitMethod()\n\t\t\tif recv == recvtype && name == method {\n\t\t\t\treturn sym.Version, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn 0, fmt.Errorf(\"methodGoVersion: %s.%s.%s missing from stdlib manifest\", pkgpath, recvtype, method)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/stringsbuilder.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"cmp\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nvar StringsBuilderAnalyzer = &analysis.Analyzer{\n\tName: \"stringsbuilder\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"stringsbuilder\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: stringsbuilder,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringbuilder\",\n}\n\n// stringsbuilder replaces string += string in a loop by strings.Builder.\nfunc stringsbuilder(pass *analysis.Pass) (any, error) {\n\t// Skip the analyzer in packages where its\n\t// fixes would create an import cycle.\n\tif within(pass, \"strings\", \"runtime\") {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tindex   = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t)\n\n\t// Gather all local string variables that appear on the\n\t// LHS of some string += string assignment.\n\tcandidates := make(map[*types.Var]bool)\n\tfor curAssign := range inspect.Root().Preorder((*ast.AssignStmt)(nil)) {\n\t\tassign := curAssign.Node().(*ast.AssignStmt)\n\t\tif assign.Tok == token.ADD_ASSIGN && is[*ast.Ident](assign.Lhs[0]) {\n\t\t\tif v, ok := pass.TypesInfo.Uses[assign.Lhs[0].(*ast.Ident)].(*types.Var); ok &&\n\t\t\t\tv.Kind() == types.LocalVar &&\n\t\t\t\ttypes.Identical(v.Type(), builtinString.Type()) {\n\t\t\t\tcandidates[v] = true\n\t\t\t}\n\t\t}\n\t}\n\n\tlexicalOrder := func(x, y *types.Var) int { return cmp.Compare(x.Pos(), y.Pos()) }\n\n\t// File and Pos of last fix edit,\n\t// for overlapping fix span detection.\n\tvar (\n\t\tlastEditFile *ast.File\n\t\tlastEditEnd  token.Pos\n\t)\n\n\t// Now check each candidate variable's decl and uses.\nnextcand:\n\tfor _, v := range slices.SortedFunc(maps.Keys(candidates), lexicalOrder) {\n\t\tvar edits []analysis.TextEdit\n\n\t\t// Check declaration of s has one of these forms:\n\t\t//\n\t\t//    s := expr\n\t\t//    var s [string] [= expr]\n\t\t//    var ( ...; s [string] [= expr] )\t\t\t(s is last)\n\t\t//\n\t\t// and transform to one of:\n\t\t//\n\t\t//    var   s strings.Builder ; s.WriteString(expr)\n\t\t//    var ( s strings.Builder); s.WriteString(expr)\n\t\t//\n\t\tdef, ok := index.Def(v)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\t// To avoid semantic conflicts, do not offer a fix if its edit\n\t\t// range (ignoring import edits) overlaps a previous fix.\n\t\t// This fixes #76983 and is an ad-hoc mitigation of #76476.\n\t\tfile := astutil.EnclosingFile(def)\n\t\tif file == lastEditFile && v.Pos() < lastEditEnd {\n\t\t\tcontinue\n\t\t}\n\n\t\tek := def.ParentEdgeKind()\n\t\tif ek == edge.AssignStmt_Lhs &&\n\t\t\tlen(def.Parent().Node().(*ast.AssignStmt).Lhs) == 1 {\n\t\t\t// Have: s := expr\n\t\t\t// => var s strings.Builder; s.WriteString(expr)\n\n\t\t\tassign := def.Parent().Node().(*ast.AssignStmt)\n\n\t\t\t// Reject \"if s := f(); ...\" since in that context\n\t\t\t// we can't replace the assign with two statements.\n\t\t\tswitch def.Parent().Parent().Node().(type) {\n\t\t\tcase *ast.BlockStmt, *ast.CaseClause, *ast.CommClause:\n\t\t\t\t// OK: these are the parts of syntax that\n\t\t\t\t// allow unrestricted statement lists.\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Add strings import.\n\t\t\tprefix, importEdits := refactor.AddImport(\n\t\t\t\tpass.TypesInfo, astutil.EnclosingFile(def), \"strings\", \"strings\", \"Builder\", v.Pos())\n\t\t\tedits = append(edits, importEdits...)\n\n\t\t\tif isEmptyString(pass.TypesInfo, assign.Rhs[0]) {\n\t\t\t\t// s := \"\"\n\t\t\t\t// ---------------------\n\t\t\t\t// var s strings.Builder\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\tPos:     assign.Pos(),\n\t\t\t\t\tEnd:     assign.End(),\n\t\t\t\t\tNewText: fmt.Appendf(nil, \"var %[1]s %[2]sBuilder\", v.Name(), prefix),\n\t\t\t\t})\n\n\t\t\t} else {\n\t\t\t\t// s :=                                 expr\n\t\t\t\t// -------------------------------------    -\n\t\t\t\t// var s strings.Builder; s.WriteString(expr)\n\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     assign.Pos(),\n\t\t\t\t\t\tEnd:     assign.Rhs[0].Pos(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"var %[1]s %[2]sBuilder; %[1]s.WriteString(\", v.Name(), prefix),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     assign.End(),\n\t\t\t\t\t\tEnd:     assign.End(),\n\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t},\n\t\t\t\t}...)\n\n\t\t\t}\n\n\t\t} else if ek == edge.ValueSpec_Names &&\n\t\t\tlen(def.Parent().Node().(*ast.ValueSpec).Names) == 1 &&\n\t\t\tfirst(def.Parent().Parent().LastChild()) == def.Parent() {\n\t\t\t// Have: var   s [string] [= expr]\n\t\t\t//   or: var ( s [string] [= expr] )\n\t\t\t// => var s strings.Builder; s.WriteString(expr)\n\t\t\t//\n\t\t\t// The LastChild check rejects this case:\n\t\t\t//   var ( s [string] [= expr]; others... )\n\t\t\t// =>\n\t\t\t//   var ( s strings.Builder; others... ); s.WriteString(expr)\n\t\t\t// since it moves 'expr' across 'others', requiring\n\t\t\t// reformatting of syntax, which in general is lossy\n\t\t\t// of comments and vertical space.\n\t\t\t// We expect this to be rare.\n\n\t\t\t// Add strings import.\n\t\t\tprefix, importEdits := refactor.AddImport(\n\t\t\t\tpass.TypesInfo, astutil.EnclosingFile(def), \"strings\", \"strings\", \"Builder\", v.Pos())\n\t\t\tedits = append(edits, importEdits...)\n\n\t\t\tspec := def.Parent().Node().(*ast.ValueSpec)\n\t\t\tdecl := def.Parent().Parent().Node().(*ast.GenDecl)\n\n\t\t\tinit := spec.Names[0].End() // start of \" = expr\"\n\t\t\tif spec.Type != nil {\n\t\t\t\tinit = spec.Type.End()\n\t\t\t}\n\n\t\t\t// Replace (possibly absent) type:\n\t\t\t//\n\t\t\t// var s [string]\n\t\t\t//      ----------------\n\t\t\t// var s strings.Builder\n\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\tPos:     spec.Names[0].End(),\n\t\t\t\tEnd:     init,\n\t\t\t\tNewText: fmt.Appendf(nil, \" %sBuilder\", prefix),\n\t\t\t})\n\n\t\t\tif len(spec.Values) > 0 && !isEmptyString(pass.TypesInfo, spec.Values[0]) {\n\t\t\t\tif decl.Rparen.IsValid() {\n\t\t\t\t\t// var decl with explicit parens:\n\t\t\t\t\t//\n\t\t\t\t\t// var ( ...  =               expr )\n\t\t\t\t\t//           -                     -\n\t\t\t\t\t// var ( ... ); s.WriteString(expr)\n\t\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     init,\n\t\t\t\t\t\t\tEnd:     init,\n\t\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: spec.Values[0].End(),\n\t\t\t\t\t\t\tEnd: decl.End(),\n\t\t\t\t\t\t},\n\t\t\t\t\t}...)\n\t\t\t\t}\n\n\t\t\t\t// =               expr\n\t\t\t\t// ----------------    -\n\t\t\t\t// ; s.WriteString(expr)\n\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     init,\n\t\t\t\t\t\tEnd:     spec.Values[0].Pos(),\n\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"; %s.WriteString(\", v.Name()),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     spec.Values[0].End(),\n\t\t\t\t\t\tEnd:     spec.Values[0].End(),\n\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t},\n\t\t\t\t}...)\n\t\t\t} else {\n\t\t\t\t// delete \"= expr\"\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\tPos: init,\n\t\t\t\t\tEnd: spec.End(),\n\t\t\t\t})\n\t\t\t}\n\n\t\t} else {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check uses of s.\n\t\t//\n\t\t// - All uses of s except the final one must be of the form\n\t\t//\n\t\t//    s += expr\n\t\t//\n\t\t//   Each of these will become s.WriteString(expr).\n\t\t//   At least one of them must be in an intervening loop\n\t\t//   w.r.t. the declaration of s:\n\t\t//\n\t\t//    var s string\n\t\t//    for ... { s += expr }\n\t\t//\n\t\t// - All uses of s after the last += must be rvalue uses (e.g. use(s), not &s).\n\t\t//   Each of these will become s.String().\n\t\t//\n\t\t//   Perhaps surprisingly, it is fine for there to be an\n\t\t//   intervening loop or lambda w.r.t. the declaration of s:\n\t\t//\n\t\t//    var s strings.Builder\n\t\t//    for range kSmall { s.WriteString(expr) }\n\t\t//    for range kLarge { use(s.String()) } // called repeatedly\n\t\t//\n\t\t//   Even though that might cause the s.String() operation to be\n\t\t//   executed repeatedly, this is not a deoptimization because,\n\t\t//   by design, (*strings.Builder).String does not allocate.\n\t\tvar (\n\t\t\tnumLoopAssigns int             // number of += assignments within a loop\n\t\t\tloopAssign     *ast.AssignStmt // first += assignment within a loop\n\t\t\tseenRvalueUse  bool            // => we've seen at least one rvalue use of s\n\t\t)\n\t\tfor curUse := range index.Uses(v) {\n\t\t\t// Strip enclosing parens around Ident.\n\t\t\tek := curUse.ParentEdgeKind()\n\t\t\tfor ek == edge.ParenExpr_X {\n\t\t\t\tcurUse = curUse.Parent()\n\t\t\t\tek = curUse.ParentEdgeKind()\n\t\t\t}\n\n\t\t\t// intervening reports whether cur has an ancestor of\n\t\t\t// one of the given types that is within the scope of v.\n\t\t\tintervening := func(types ...ast.Node) bool {\n\t\t\t\tfor cur := range curUse.Enclosing(types...) {\n\t\t\t\t\tif v.Pos() <= cur.Node().Pos() { // in scope of v\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif ek == edge.AssignStmt_Lhs {\n\t\t\t\t// After an rvalue use, no more assignments are allowed.\n\t\t\t\tif seenRvalueUse {\n\t\t\t\t\tcontinue nextcand\n\t\t\t\t}\n\n\t\t\t\tassign := curUse.Parent().Node().(*ast.AssignStmt)\n\t\t\t\tif assign.Tok != token.ADD_ASSIGN {\n\t\t\t\t\tcontinue nextcand\n\t\t\t\t}\n\t\t\t\t// Have: s += expr\n\n\t\t\t\t// At least one of the += operations\n\t\t\t\t// must appear within a loop.\n\t\t\t\t// relative to the declaration of s.\n\t\t\t\tif intervening((*ast.ForStmt)(nil), (*ast.RangeStmt)(nil)) {\n\t\t\t\t\tnumLoopAssigns++\n\t\t\t\t\tif loopAssign == nil {\n\t\t\t\t\t\tloopAssign = assign\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// s +=          expr\n\t\t\t\t//  -------------    -\n\t\t\t\t// s.WriteString(expr)\n\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t// replace \" += \" with \".WriteString(\"\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     assign.Lhs[0].End(),\n\t\t\t\t\t\tEnd:     assign.Rhs[0].Pos(),\n\t\t\t\t\t\tNewText: []byte(\".WriteString(\"),\n\t\t\t\t\t},\n\t\t\t\t\t// insert \")\"\n\t\t\t\t\t{\n\t\t\t\t\t\tPos:     assign.End(),\n\t\t\t\t\t\tEnd:     assign.End(),\n\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t},\n\t\t\t\t}...)\n\n\t\t\t} else if ek == edge.UnaryExpr_X &&\n\t\t\t\tcurUse.Parent().Node().(*ast.UnaryExpr).Op == token.AND {\n\t\t\t\t// Have: use(&s)\n\t\t\t\tcontinue nextcand // s is used as an lvalue; reject\n\n\t\t\t} else {\n\t\t\t\t// The only possible l-value uses of a string variable\n\t\t\t\t// are assignments (s=expr, s+=expr, etc) and &s.\n\t\t\t\t// (For strings, we can ignore method calls s.m().)\n\t\t\t\t// All other uses are r-values.\n\t\t\t\tseenRvalueUse = true\n\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t// insert \".String()\"\n\t\t\t\t\tPos:     curUse.Node().End(),\n\t\t\t\t\tEnd:     curUse.Node().End(),\n\t\t\t\t\tNewText: []byte(\".String()\"),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tif !seenRvalueUse {\n\t\t\tcontinue nextcand // no rvalue use; reject\n\t\t}\n\t\tif numLoopAssigns == 0 {\n\t\t\tcontinue nextcand // no += in a loop; reject\n\t\t}\n\n\t\tlastEditFile = file\n\t\tlastEditEnd = edits[len(edits)-1].End\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     loopAssign.Pos(),\n\t\t\tEnd:     loopAssign.End(),\n\t\t\tMessage: \"using string += string in a loop is inefficient\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   \"Replace string += string with strings.Builder\",\n\t\t\t\tTextEdits: edits,\n\t\t\t}},\n\t\t})\n\t}\n\n\treturn nil, nil\n}\n\n// isEmptyString reports whether e (a string-typed expression) has constant value \"\".\nfunc isEmptyString(info *types.Info, e ast.Expr) bool {\n\ttv, ok := info.Types[e]\n\treturn ok && tv.Value != nil && constant.StringVal(tv.Value) == \"\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/stringscut.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar stringscutAnalyzer = &analysis.Analyzer{\n\tName: \"stringscut\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"stringscut\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: stringscut,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscut\",\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.StringsCutModernizer = stringscutAnalyzer\n}\n\n// stringscut offers a fix to replace an occurrence of strings.Index{,Byte} with\n// strings.{Cut,Contains}, and similar fixes for functions in the bytes package.\n// Consider some candidate for replacement i := strings.Index(s, substr).\n// The following must hold for a replacement to occur:\n//\n//  1. All instances of i and s must be in one of these forms.\n//\n//     Binary expressions must be inequalities equivalent to\n//     \"Index failed\" (e.g. i < 0) or \"Index succeeded\" (i >= 0),\n//     or identities such as these (and their negations):\n//\n//     0 > i                 (flips left and right)\n//     i <= -1, -1 >= i      (replace strict inequality by non-strict)\n//     i == -1, -1 == i      (Index() guarantees i < 0 => i == -1)\n//\n//     Slice expressions:\n//     a: s[:i], s[0:i]\n//     b: s[i+len(substr):], s[len(substr) + i:], s[i + const], s[k + i] (where k = len(substr))\n//\n//  2. There can be no uses of s, substr, or i where they are\n//     potentially modified (i.e. in assignments, or function calls with unknown side\n//     effects).\n//\n// Then, the replacement involves the following substitutions:\n//\n//  1. Replace \"i := strings.Index(s, substr)\" with \"before, after, ok := strings.Cut(s, substr)\"\n//\n//  2. Replace instances of binary expressions (a) with !ok and binary expressions (b) with ok.\n//\n//  3. Replace slice expressions (a) with \"before\" and slice expressions (b) with after.\n//\n//  4. The assignments to before, after, and ok may use the blank identifier \"_\" if they are unused.\n//\n//     For example:\n//\n//     i := strings.Index(s, substr)\n//     if i >= 0 {\n//     use(s[:i], s[i+len(substr):])\n//     }\n//\n//     Would become:\n//\n//     before, after, ok := strings.Cut(s, substr)\n//     if ok {\n//     use(before, after)\n//     }\n//\n// If the condition involving `i` is equivalent to i >= 0, then we replace it with\n// `if ok“.\n// If the condition is negated (e.g. equivalent to `i < 0`), we use `if !ok` instead.\n// If the slices of `s` match `s[:i]` or `s[i+len(substr):]` or their variants listed above,\n// then we replace them with before and after.\n//\n// When the index `i` is used only to check for the presence of the substring or byte slice,\n// the suggested fix uses Contains() instead of Cut.\n//\n// For example:\n//\n//\ti := strings.Index(s, substr)\n//\tif i >= 0 {\n//\t\treturn\n//\t}\n//\n// Would become:\n//\n//\tfound := strings.Contains(s, substr)\n//\tif found {\n//\t\treturn\n//\t}\nfunc stringscut(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\n\t\tstringsIndex     = index.Object(\"strings\", \"Index\")\n\t\tstringsIndexByte = index.Object(\"strings\", \"IndexByte\")\n\t\tbytesIndex       = index.Object(\"bytes\", \"Index\")\n\t\tbytesIndexByte   = index.Object(\"bytes\", \"IndexByte\")\n\t)\n\n\tscopeFixCount := make(map[*types.Scope]int) // the number of times we have offered a fix within a given scope in the current pass\n\n\tfor _, obj := range []types.Object{\n\t\tstringsIndex,\n\t\tstringsIndexByte,\n\t\tbytesIndex,\n\t\tbytesIndexByte,\n\t} {\n\t\t// (obj may be nil)\n\tnextcall:\n\t\tfor curCall := range index.Calls(obj) {\n\t\t\t// Check file version.\n\t\t\tif !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curCall), versions.Go1_18) {\n\t\t\t\tcontinue // strings.Index not available in this file\n\t\t\t}\n\t\t\tindexCall := curCall.Node().(*ast.CallExpr) // the call to strings.Index, etc.\n\t\t\tobj := typeutil.Callee(info, indexCall)\n\t\t\tif obj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar iIdent *ast.Ident // defining identifier of i var\n\t\t\tswitch ek, idx := curCall.ParentEdge(); ek {\n\t\t\tcase edge.ValueSpec_Values:\n\t\t\t\t// Have: var i = strings.Index(...)\n\t\t\t\tcurName := curCall.Parent().ChildAt(edge.ValueSpec_Names, idx)\n\t\t\t\tiIdent = curName.Node().(*ast.Ident)\n\t\t\tcase edge.AssignStmt_Rhs:\n\t\t\t\t// Have: i := strings.Index(...)\n\t\t\t\t// (Must be i's definition.)\n\t\t\t\tcurLhs := curCall.Parent().ChildAt(edge.AssignStmt_Lhs, idx)\n\t\t\t\tiIdent, _ = curLhs.Node().(*ast.Ident) // may be nil\n\t\t\t}\n\n\t\t\tif iIdent == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Inv: iIdent is i's definition. The following would be skipped: 'var i int; i = strings.Index(...)'\n\t\t\t// Get uses of i.\n\t\t\tiObj := info.ObjectOf(iIdent)\n\t\t\tif iObj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar (\n\t\t\t\ts      = indexCall.Args[0]\n\t\t\t\tsubstr = indexCall.Args[1]\n\t\t\t)\n\n\t\t\t// Check that there are no statements that alter the value of s\n\t\t\t// or substr after the call to Index().\n\t\t\tif !indexArgValid(info, index, s, indexCall.Pos()) ||\n\t\t\t\t!indexArgValid(info, index, substr, indexCall.Pos()) {\n\t\t\t\tcontinue nextcall\n\t\t\t}\n\n\t\t\t// Next, examine all uses of i. If the only uses are of the\n\t\t\t// forms mentioned above (e.g. i < 0, i >= 0, s[:i] and s[i +\n\t\t\t// len(substr)]), then we can replace the call to Index()\n\t\t\t// with a call to Cut() and use the returned ok, before,\n\t\t\t// and after variables accordingly.\n\t\t\tnegative, nonnegative, beforeSlice, afterSlice := checkIdxUses(pass.TypesInfo, index.Uses(iObj), s, substr, iObj)\n\n\t\t\t// Either there are no uses of before, after, or ok, or some use\n\t\t\t// of i does not match our criteria - don't suggest a fix.\n\t\t\tif negative == nil && nonnegative == nil && beforeSlice == nil && afterSlice == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If the only uses are ok and !ok, don't suggest a Cut() fix - these should be using Contains()\n\t\t\tisContains := (len(negative) > 0 || len(nonnegative) > 0) && len(beforeSlice) == 0 && len(afterSlice) == 0\n\n\t\t\tenclosingBlock, ok := moreiters.First(curCall.Enclosing((*ast.BlockStmt)(nil)))\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tscope := iObj.Parent()\n\t\t\t// Generate fresh names for ok, before, after, found, but only if\n\t\t\t// they are defined by the end of the enclosing block and used\n\t\t\t// within the enclosing block after the Index call. We need a Cursor\n\t\t\t// for the end of the enclosing block, but we can't just find the\n\t\t\t// Cursor at scope.End() because it corresponds to the entire\n\t\t\t// enclosingBlock. Instead, get the last child of the enclosing\n\t\t\t// block.\n\t\t\tlastStmtCur, _ := enclosingBlock.LastChild()\n\t\t\tlastStmt := lastStmtCur.Node()\n\n\t\t\tfresh := func(preferred string) string {\n\t\t\t\treturn freshName(info, index, scope, lastStmt.End(), lastStmtCur, enclosingBlock, iIdent.Pos(), preferred)\n\t\t\t}\n\n\t\t\tvar okVarName, beforeVarName, afterVarName, foundVarName string\n\t\t\tif isContains {\n\t\t\t\tfoundVarName = fresh(\"found\")\n\t\t\t} else {\n\t\t\t\tokVarName = fresh(\"ok\")\n\t\t\t\tbeforeVarName = fresh(\"before\")\n\t\t\t\tafterVarName = fresh(\"after\")\n\t\t\t}\n\n\t\t\t// If we are already suggesting a fix within the index's scope, we\n\t\t\t// must get fresh names for before, after and ok.\n\t\t\t// This is a specific symptom of the general problem that analyzers\n\t\t\t// can generate conflicting fixes.\n\t\t\tif scopeFixCount[scope] > 0 {\n\t\t\t\tsuffix := scopeFixCount[scope] - 1 // start at 0\n\t\t\t\tif isContains {\n\t\t\t\t\tfoundVarName = fresh(fmt.Sprintf(\"%s%d\", foundVarName, suffix))\n\t\t\t\t} else {\n\t\t\t\t\tokVarName = fresh(fmt.Sprintf(\"%s%d\", okVarName, suffix))\n\t\t\t\t\tbeforeVarName = fresh(fmt.Sprintf(\"%s%d\", beforeVarName, suffix))\n\t\t\t\t\tafterVarName = fresh(fmt.Sprintf(\"%s%d\", afterVarName, suffix))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If there will be no uses of ok, before, or after, use the\n\t\t\t// blank identifier instead.\n\t\t\tif len(negative) == 0 && len(nonnegative) == 0 {\n\t\t\t\tokVarName = \"_\"\n\t\t\t}\n\t\t\tif len(beforeSlice) == 0 {\n\t\t\t\tbeforeVarName = \"_\"\n\t\t\t}\n\t\t\tif len(afterSlice) == 0 {\n\t\t\t\tafterVarName = \"_\"\n\t\t\t}\n\n\t\t\tvar edits []analysis.TextEdit\n\t\t\treplace := func(exprs []ast.Expr, new string) {\n\t\t\t\tfor _, expr := range exprs {\n\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\tPos:     expr.Pos(),\n\t\t\t\t\t\tEnd:     expr.End(),\n\t\t\t\t\t\tNewText: []byte(new),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Get the ident for the call to strings.Index, which could just be\n\t\t\t// \"Index\" if the strings package is dot imported.\n\t\t\tindexCallId := typesinternal.UsedIdent(info, indexCall.Fun)\n\t\t\treplacedFunc := \"Cut\"\n\t\t\tif isContains {\n\t\t\t\treplacedFunc = \"Contains\"\n\t\t\t\treplace(negative, \"!\"+foundVarName) // idx < 0   ->  !found\n\t\t\t\treplace(nonnegative, foundVarName)  // idx > -1  ->   found\n\n\t\t\t\t// Replace the assignment with found, and replace the call to\n\t\t\t\t// Index or IndexByte with a call to Contains.\n\t\t\t\t// i     := strings.Index   (...)\n\t\t\t\t// -----            --------\n\t\t\t\t// found := strings.Contains(...)\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\tPos:     iIdent.Pos(),\n\t\t\t\t\tEnd:     iIdent.End(),\n\t\t\t\t\tNewText: []byte(foundVarName),\n\t\t\t\t}, analysis.TextEdit{\n\t\t\t\t\tPos:     indexCallId.Pos(),\n\t\t\t\t\tEnd:     indexCallId.End(),\n\t\t\t\t\tNewText: []byte(\"Contains\"),\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\treplace(negative, \"!\"+okVarName)    // idx < 0   ->  !ok\n\t\t\t\treplace(nonnegative, okVarName)     // idx > -1  ->   ok\n\t\t\t\treplace(beforeSlice, beforeVarName) // s[:idx]   ->   before\n\t\t\t\treplace(afterSlice, afterVarName)   // s[idx+k:] ->   after\n\n\t\t\t\t// Replace the assignment with before, after, ok, and replace\n\t\t\t\t// the call to Index or IndexByte with a call to Cut.\n\t\t\t\t// i     \t\t\t := strings.Index(...)\n\t\t\t\t// -----------------            -----\n\t\t\t\t// before, after, ok := strings.Cut  (...)\n\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\tPos:     iIdent.Pos(),\n\t\t\t\t\tEnd:     iIdent.End(),\n\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s, %s, %s\", beforeVarName, afterVarName, okVarName),\n\t\t\t\t}, analysis.TextEdit{\n\t\t\t\t\tPos:     indexCallId.Pos(),\n\t\t\t\t\tEnd:     indexCallId.End(),\n\t\t\t\t\tNewText: []byte(\"Cut\"),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Calls to IndexByte have a byte as their second arg, which\n\t\t\t// must be converted to a string or []byte to be a valid arg for Cut/Contains.\n\t\t\tif obj.Name() == \"IndexByte\" {\n\t\t\t\tswitch obj.Pkg().Name() {\n\t\t\t\tcase \"strings\":\n\t\t\t\t\tsearchByteVal := info.Types[substr].Value\n\t\t\t\t\tif searchByteVal == nil {\n\t\t\t\t\t\t// substr is a variable, e.g. substr := byte('b')\n\t\t\t\t\t\t// use string(substr)\n\t\t\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos:     substr.Pos(),\n\t\t\t\t\t\t\t\tNewText: []byte(\"string(\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPos:     substr.End(),\n\t\t\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}...)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// substr is a byte constant\n\t\t\t\t\t\tval, _ := constant.Int64Val(searchByteVal) // inv: must be a valid byte\n\t\t\t\t\t\t// strings.Cut/Contains requires a string, so convert byte literal to string literal; e.g. 'a' -> \"a\", 55 -> \"7\"\n\t\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\t\tPos:     substr.Pos(),\n\t\t\t\t\t\t\tEnd:     substr.End(),\n\t\t\t\t\t\t\tNewText: strconv.AppendQuote(nil, string(byte(val))),\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\tcase \"bytes\":\n\t\t\t\t\t// bytes.Cut/Contains requires a []byte, so wrap substr in a []byte{}\n\t\t\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     substr.Pos(),\n\t\t\t\t\t\t\tNewText: []byte(\"[]byte{\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     substr.End(),\n\t\t\t\t\t\t\tNewText: []byte(\"}\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t}...)\n\t\t\t\t}\n\t\t\t}\n\t\t\tscopeFixCount[scope]++\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos: indexCall.Fun.Pos(),\n\t\t\t\tEnd: indexCall.Fun.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"%s.%s can be simplified using %s.%s\",\n\t\t\t\t\tobj.Pkg().Name(), obj.Name(), obj.Pkg().Name(), replacedFunc),\n\t\t\t\tCategory: \"stringscut\",\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   fmt.Sprintf(\"Simplify %s.%s call using %s.%s\", obj.Pkg().Name(), obj.Name(), obj.Pkg().Name(), replacedFunc),\n\t\t\t\t\tTextEdits: edits,\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\n// indexArgValid reports whether expr is a valid strings.Index(_, _) arg\n// for the transformation. An arg is valid iff it is:\n// - constant;\n// - a local variable with no modifying uses after the Index() call; or\n// - []byte(x) where x is also valid by this definition.\n// All other expressions are assumed not referentially transparent,\n// so we cannot be sure that all uses are safe to replace.\nfunc indexArgValid(info *types.Info, index *typeindex.Index, expr ast.Expr, afterPos token.Pos) bool {\n\ttv := info.Types[expr]\n\tif tv.Value != nil {\n\t\treturn true // constant\n\t}\n\tswitch expr := expr.(type) {\n\tcase *ast.CallExpr:\n\t\treturn types.Identical(tv.Type, byteSliceType) &&\n\t\t\tinfo.Types[expr.Fun].IsType() && // make sure this isn't a function that returns a byte slice\n\t\t\tindexArgValid(info, index, expr.Args[0], afterPos) // check s in []byte(s)\n\tcase *ast.Ident:\n\t\tsObj := info.Uses[expr]\n\t\tsUses := index.Uses(sObj)\n\t\treturn !hasModifyingUses(info, sUses, afterPos)\n\tdefault:\n\t\t// For now, skip instances where s or substr are not\n\t\t// identifers, basic lits, or call expressions of the form\n\t\t// []byte(s).\n\t\t// TODO(mkalil): Handle s and substr being expressions like ptr.field[i].\n\t\t// From adonovan: We'd need to analyze s and substr to see\n\t\t// whether they are referentially transparent, and if not,\n\t\t// analyze all code between declaration and use and see if\n\t\t// there are statements or expressions with potential side\n\t\t// effects.\n\t\treturn false\n\t}\n}\n\n// checkIdxUses inspects the uses of i to make sure they match certain criteria that\n// allows us to suggest a modernization. If all uses of i, s and substr match\n// one of the following four valid formats, it returns a list of occurrences for\n// each format. If any of the uses do not match one of the formats, return nil\n// for all values, since we should not offer a replacement.\n// 1. negative - a condition equivalent to i < 0\n// 2. nonnegative - a condition equivalent to i >= 0\n// 3. beforeSlice - a slice of `s` that matches either s[:i], s[0:i]\n// 4. afterSlice - a slice of `s` that matches one of: s[i+len(substr):], s[len(substr) + i:], s[i + const], s[k + i] (where k = len(substr))\n//\n// Additionally, all beforeSlice and afterSlice uses must be dominated by a\n// nonnegative guard on i (i.e., inside the body of an if whose condition\n// checks i >= 0, or in the else of a negative check, or after an\n// early-return negative check). This ensures that the rewrite from\n// s[i+len(sep):] to \"after\" preserves semantics, since when i == -1,\n// s[i+len(sep):] may yield a valid substring (e.g. s[0:] for single-byte\n// separators), but \"after\" would be \"\".\n//\n// When len(substr)==1, it's safe to use s[i+1:] even when i < 0.\n// Otherwise, each replacement of s[i+1:] must be guarded by a check\n// that i is nonnegative.\nfunc checkIdxUses(info *types.Info, uses iter.Seq[inspector.Cursor], s, substr ast.Expr, iObj types.Object) (negative, nonnegative, beforeSlice, afterSlice []ast.Expr) {\n\trequireGuard := true\n\tif l := constSubstrLen(info, substr); l != -1 && l != 1 {\n\t\trequireGuard = false\n\t}\n\n\tuse := func(cur inspector.Cursor) bool {\n\t\tek := cur.ParentEdgeKind()\n\t\tn := cur.Parent().Node()\n\t\tswitch ek {\n\t\tcase edge.BinaryExpr_X, edge.BinaryExpr_Y:\n\t\t\tcheck := n.(*ast.BinaryExpr)\n\t\t\tswitch checkIdxComparison(info, check, iObj) {\n\t\t\tcase -1:\n\t\t\t\tnegative = append(negative, check)\n\t\t\t\treturn true\n\t\t\tcase 1:\n\t\t\t\tnonnegative = append(nonnegative, check)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Check is not equivalent to that i < 0 or i >= 0.\n\t\t\t// Might be part of an outer slice expression like s[i + k]\n\t\t\t// which requires a different check.\n\t\t\t// Check that the thing being sliced is s and that the slice\n\t\t\t// doesn't have a max index.\n\t\t\tif slice, ok := cur.Parent().Parent().Node().(*ast.SliceExpr); ok &&\n\t\t\t\tsameObject(info, s, slice.X) &&\n\t\t\t\tslice.Max == nil {\n\t\t\t\tif isBeforeSlice(info, ek, slice) && (!requireGuard || isSliceIndexGuarded(info, cur, iObj)) {\n\t\t\t\t\tbeforeSlice = append(beforeSlice, slice)\n\t\t\t\t\treturn true\n\t\t\t\t} else if isAfterSlice(info, ek, slice, substr) && (!requireGuard || isSliceIndexGuarded(info, cur, iObj)) {\n\t\t\t\t\tafterSlice = append(afterSlice, slice)\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\tcase edge.SliceExpr_Low, edge.SliceExpr_High:\n\t\t\tslice := n.(*ast.SliceExpr)\n\t\t\t// Check that the thing being sliced is s and that the slice doesn't\n\t\t\t// have a max index.\n\t\t\tif sameObject(info, s, slice.X) && slice.Max == nil {\n\t\t\t\tif isBeforeSlice(info, ek, slice) && (!requireGuard || isSliceIndexGuarded(info, cur, iObj)) {\n\t\t\t\t\tbeforeSlice = append(beforeSlice, slice)\n\t\t\t\t\treturn true\n\t\t\t\t} else if isAfterSlice(info, ek, slice, substr) && (!requireGuard || isSliceIndexGuarded(info, cur, iObj)) {\n\t\t\t\t\tafterSlice = append(afterSlice, slice)\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfor curIdent := range uses {\n\t\tif !use(curIdent) {\n\t\t\treturn nil, nil, nil, nil\n\t\t}\n\t}\n\treturn negative, nonnegative, beforeSlice, afterSlice\n}\n\n// hasModifyingUses reports whether any of the uses involve potential\n// modifications. Uses involving assignments before the \"afterPos\" won't be\n// considered.\nfunc hasModifyingUses(info *types.Info, uses iter.Seq[inspector.Cursor], afterPos token.Pos) bool {\n\tfor curUse := range uses {\n\t\tek := curUse.ParentEdgeKind()\n\t\tif ek == edge.AssignStmt_Lhs {\n\t\t\tif curUse.Node().Pos() <= afterPos {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tassign := curUse.Parent().Node().(*ast.AssignStmt)\n\t\t\tif sameObject(info, assign.Lhs[0], curUse.Node().(*ast.Ident)) {\n\t\t\t\t// Modifying use because we are reassigning the value of the object.\n\t\t\t\treturn true\n\t\t\t}\n\t\t} else if ek == edge.UnaryExpr_X &&\n\t\t\tcurUse.Parent().Node().(*ast.UnaryExpr).Op == token.AND {\n\t\t\t// Modifying use because we might be passing the object by reference (an explicit &).\n\t\t\t// We can ignore the case where we have a method call on the expression (which\n\t\t\t// has an implicit &) because we know the type of s and substr are strings\n\t\t\t// which cannot have methods on them.\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// checkIdxComparison reports whether the check is equivalent to i < 0 or its negation, or neither.\n// For equivalent to i >= 0, we only accept this exact BinaryExpr since\n// expressions like i > 0 or i >= 1 make a stronger statement about the value of i.\n// We avoid suggesting a fix in this case since it may result in an invalid\n// transformation (See golang/go#76687).\n// Since strings.Index returns exactly -1 if the substring is not found, we\n// don't need to handle expressions like i <= -3.\n// We return 0 if the expression does not match any of these options.\nfunc checkIdxComparison(info *types.Info, check *ast.BinaryExpr, iObj types.Object) int {\n\tisI := func(e ast.Expr) bool {\n\t\tid, ok := e.(*ast.Ident)\n\t\treturn ok && info.Uses[id] == iObj\n\t}\n\tif !isI(check.X) && !isI(check.Y) {\n\t\treturn 0\n\t}\n\n\t// Ensure that the constant (if any) is on the right.\n\tx, op, y := check.X, check.Op, check.Y\n\tif info.Types[x].Value != nil {\n\t\tx, op, y = y, flip(op), x\n\t}\n\n\tyIsInt := func(k int64) bool {\n\t\treturn isIntLiteral(info, y, k)\n\t}\n\n\tif op == token.LSS && yIsInt(0) || // i < 0\n\t\top == token.EQL && yIsInt(-1) || // i == -1\n\t\top == token.LEQ && yIsInt(-1) { // i <= -1\n\t\treturn -1 // check <=> i is negative\n\t}\n\n\tif op == token.GEQ && yIsInt(0) || // i >= 0\n\t\top == token.NEQ && yIsInt(-1) || // i != -1\n\t\top == token.GTR && yIsInt(-1) { // i > -1\n\t\treturn +1 // check <=> i is non-negative\n\t}\n\n\treturn 0 // unknown\n}\n\n// flip changes the comparison token as if the operands were flipped.\n// It is defined only for == and the four inequalities.\nfunc flip(op token.Token) token.Token {\n\tswitch op {\n\tcase token.EQL:\n\t\treturn token.EQL // (same)\n\tcase token.GEQ:\n\t\treturn token.LEQ\n\tcase token.GTR:\n\t\treturn token.LSS\n\tcase token.LEQ:\n\t\treturn token.GEQ\n\tcase token.LSS:\n\t\treturn token.GTR\n\t}\n\treturn op\n}\n\n// isBeforeSlice reports whether the SliceExpr is of the form s[:i] or s[0:i].\nfunc isBeforeSlice(info *types.Info, ek edge.Kind, slice *ast.SliceExpr) bool {\n\treturn ek == edge.SliceExpr_High && (slice.Low == nil || isZeroIntConst(info, slice.Low))\n}\n\n// constSubstrLen returns the constant length of substr, or -1 if unknown.\nfunc constSubstrLen(info *types.Info, substr ast.Expr) int {\n\t// Handle len([]byte(substr))\n\tif call, ok := substr.(*ast.CallExpr); ok {\n\t\ttv := info.Types[call.Fun]\n\t\tif tv.IsType() && types.Identical(tv.Type, byteSliceType) {\n\t\t\t// Only one arg in []byte conversion.\n\t\t\tsubstr = call.Args[0]\n\t\t}\n\t}\n\tsubstrVal := info.Types[substr].Value\n\tif substrVal != nil {\n\t\tswitch substrVal.Kind() {\n\t\tcase constant.String:\n\t\t\treturn len(constant.StringVal(substrVal))\n\t\tcase constant.Int:\n\t\t\t// constant.Value is a byte literal, e.g. bytes.IndexByte(_, 'a')\n\t\t\t// or a numeric byte literal, e.g. bytes.IndexByte(_, 65)\n\t\t\t// ([]byte(rune) is not legal.)\n\t\t\treturn 1\n\t\t}\n\t}\n\treturn -1\n}\n\n// isAfterSlice reports whether the SliceExpr is of the form s[i+len(substr):],\n// or s[i + k:] where k is a const is equal to len(substr).\nfunc isAfterSlice(info *types.Info, ek edge.Kind, slice *ast.SliceExpr, substr ast.Expr) bool {\n\tlowExpr, ok := slice.Low.(*ast.BinaryExpr)\n\tif !ok || slice.High != nil {\n\t\treturn false\n\t}\n\t// Returns true if the expression is a call to len(substr).\n\tisLenCall := func(expr ast.Expr) bool {\n\t\tcall, ok := expr.(*ast.CallExpr)\n\t\tif !ok || len(call.Args) != 1 {\n\t\t\treturn false\n\t\t}\n\t\treturn sameObject(info, substr, call.Args[0]) && typeutil.Callee(info, call) == builtinLen\n\t}\n\n\tsubstrLen := constSubstrLen(info, substr)\n\n\tswitch ek {\n\tcase edge.BinaryExpr_X:\n\t\tkVal := info.Types[lowExpr.Y].Value\n\t\tif kVal == nil {\n\t\t\t// i + len(substr)\n\t\t\treturn lowExpr.Op == token.ADD && isLenCall(lowExpr.Y)\n\t\t} else {\n\t\t\t// i + k\n\t\t\tkInt, ok := constant.Int64Val(kVal)\n\t\t\treturn ok && substrLen == int(kInt)\n\t\t}\n\tcase edge.BinaryExpr_Y:\n\t\tkVal := info.Types[lowExpr.X].Value\n\t\tif kVal == nil {\n\t\t\t// len(substr) + i\n\t\t\treturn lowExpr.Op == token.ADD && isLenCall(lowExpr.X)\n\t\t} else {\n\t\t\t// k + i\n\t\t\tkInt, ok := constant.Int64Val(kVal)\n\t\t\treturn ok && substrLen == int(kInt)\n\t\t}\n\t}\n\treturn false\n}\n\n// isSliceIndexGuarded reports whether a use of the index variable i (at the given cursor)\n// inside a slice expression is dominated by a nonnegative guard.\n// A use is considered guarded if any of the following are true:\n//   - It is inside the Body of an IfStmt whose condition is a nonnegative check on i.\n//   - It is inside the Else of an IfStmt whose condition is a negative check on i.\n//   - It is preceded (in the same block) by an IfStmt whose condition is a\n//     negative check on i with a terminating body (e.g., early return).\n//\n// Conversely, a use is immediately rejected if:\n//   - It is inside the Body of an IfStmt whose condition is a negative check on i.\n//   - It is inside the Else of an IfStmt whose condition is a nonnegative check on i.\n//\n// We have already checked (see [hasModifyingUses]) that there are no\n// intervening uses (incl. via aliases) of i that might alter its value.\nfunc isSliceIndexGuarded(info *types.Info, cur inspector.Cursor, iObj types.Object) bool {\n\tfor anc := range cur.Enclosing() {\n\t\tswitch anc.ParentEdgeKind() {\n\t\tcase edge.IfStmt_Body, edge.IfStmt_Else:\n\t\t\tifStmt := anc.Parent().Node().(*ast.IfStmt)\n\t\t\tcheck := condChecksIdx(info, ifStmt.Cond, iObj)\n\t\t\tif anc.ParentEdgeKind() == edge.IfStmt_Else {\n\t\t\t\tcheck = -check\n\t\t\t}\n\t\t\tif check > 0 {\n\t\t\t\treturn true // inside nonnegative-guarded block (i >= 0 here)\n\t\t\t}\n\t\t\tif check < 0 {\n\t\t\t\treturn false // inside negative-guarded block (i < 0 here)\n\t\t\t}\n\t\tcase edge.BlockStmt_List:\n\t\t\t// Check preceding siblings for early-return negative checks.\n\t\t\tfor sib, ok := anc.PrevSibling(); ok; sib, ok = sib.PrevSibling() {\n\t\t\t\tifStmt, ok := sib.Node().(*ast.IfStmt)\n\t\t\t\tif ok && condChecksIdx(info, ifStmt.Cond, iObj) < 0 && bodyTerminates(ifStmt.Body) {\n\t\t\t\t\treturn true // preceded by early-return negative check\n\t\t\t\t}\n\t\t\t}\n\t\tcase edge.FuncDecl_Body, edge.FuncLit_Body:\n\t\t\treturn false // stop at function boundary\n\t\t}\n\t}\n\treturn false\n}\n\n// condChecksIdx reports whether cond is a BinaryExpr that checks\n// the index variable iObj for negativity or non-negativity.\n// Returns -1 for negative (e.g. i < 0), +1 for nonnegative (e.g. i >= 0), 0 otherwise.\nfunc condChecksIdx(info *types.Info, cond ast.Expr, iObj types.Object) int {\n\tbinExpr, ok := cond.(*ast.BinaryExpr)\n\tif !ok {\n\t\treturn 0\n\t}\n\treturn checkIdxComparison(info, binExpr, iObj)\n}\n\n// bodyTerminates reports whether the given block statement unconditionally\n// terminates execution (via return, break, continue, or goto).\nfunc bodyTerminates(block *ast.BlockStmt) bool {\n\tif len(block.List) == 0 {\n\t\treturn false\n\t}\n\tlast := block.List[len(block.List)-1]\n\tswitch last.(type) {\n\tcase *ast.ReturnStmt, *ast.BranchStmt:\n\t\treturn true // return, break, continue, goto\n\t}\n\treturn false\n}\n\n// sameObject reports whether we know that the expressions resolve to the same object.\nfunc sameObject(info *types.Info, expr1, expr2 ast.Expr) bool {\n\tif ident1, ok := expr1.(*ast.Ident); ok {\n\t\tif ident2, ok := expr2.(*ast.Ident); ok {\n\t\t\tuses1, ok1 := info.Uses[ident1]\n\t\t\tuses2, ok2 := info.Uses[ident2]\n\t\t\treturn ok1 && ok2 && uses1 == uses2\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/stringscutprefix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar StringsCutPrefixAnalyzer = &analysis.Analyzer{\n\tName: \"stringscutprefix\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"stringscutprefix\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: stringscutprefix,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscutprefix\",\n}\n\n// stringscutprefix offers a fix to replace an if statement which\n// calls to the 2 patterns below with strings.CutPrefix or strings.CutSuffix.\n//\n// Patterns:\n//\n//  1. if strings.HasPrefix(s, pre) { use(strings.TrimPrefix(s, pre) }\n//     =>\n//     if after, ok := strings.CutPrefix(s, pre); ok { use(after) }\n//\n//  2. if after := strings.TrimPrefix(s, pre); after != s { use(after) }\n//     =>\n//     if after, ok := strings.CutPrefix(s, pre); ok { use(after) }\n//\n// Similar patterns apply for CutSuffix.\n//\n// The use must occur within the first statement of the block, and the offered fix\n// only replaces the first occurrence of strings.TrimPrefix/TrimSuffix.\n//\n// Variants:\n// - bytes.HasPrefix/HasSuffix usage as pattern 1.\nfunc stringscutprefix(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\n\t\tstringsTrimPrefix = index.Object(\"strings\", \"TrimPrefix\")\n\t\tbytesTrimPrefix   = index.Object(\"bytes\", \"TrimPrefix\")\n\t\tstringsTrimSuffix = index.Object(\"strings\", \"TrimSuffix\")\n\t\tbytesTrimSuffix   = index.Object(\"bytes\", \"TrimSuffix\")\n\t)\n\tif !index.Used(stringsTrimPrefix, bytesTrimPrefix, stringsTrimSuffix, bytesTrimSuffix) {\n\t\treturn nil, nil\n\t}\n\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_20) {\n\t\tfor curIfStmt := range curFile.Preorder((*ast.IfStmt)(nil)) {\n\t\t\tifStmt := curIfStmt.Node().(*ast.IfStmt)\n\n\t\t\t// pattern1\n\t\t\tif call, ok := ifStmt.Cond.(*ast.CallExpr); ok && ifStmt.Init == nil && len(ifStmt.Body.List) > 0 {\n\n\t\t\t\tobj := typeutil.Callee(info, call)\n\t\t\t\tif !typesinternal.IsFunctionNamed(obj, \"strings\", \"HasPrefix\", \"HasSuffix\") &&\n\t\t\t\t\t!typesinternal.IsFunctionNamed(obj, \"bytes\", \"HasPrefix\", \"HasSuffix\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tisPrefix := strings.HasSuffix(obj.Name(), \"Prefix\")\n\n\t\t\t\t// Replace the first occurrence of strings.TrimPrefix(s, pre) in the first statement only,\n\t\t\t\t// but not later statements in case s or pre are modified by intervening logic (ditto Suffix).\n\t\t\t\tfirstStmt := curIfStmt.Child(ifStmt.Body).Child(ifStmt.Body.List[0])\n\t\t\t\tfor curCall := range firstStmt.Preorder((*ast.CallExpr)(nil)) {\n\t\t\t\t\tcall1 := curCall.Node().(*ast.CallExpr)\n\t\t\t\t\tobj1 := typeutil.Callee(info, call1)\n\t\t\t\t\t// bytesTrimPrefix or stringsTrimPrefix might be nil if the file doesn't import it,\n\t\t\t\t\t// so we need to ensure the obj1 is not nil otherwise the call1 is not TrimPrefix and cause a panic (ditto Suffix).\n\t\t\t\t\tif obj1 == nil ||\n\t\t\t\t\t\tobj1 != stringsTrimPrefix && obj1 != bytesTrimPrefix &&\n\t\t\t\t\t\t\tobj1 != stringsTrimSuffix && obj1 != bytesTrimSuffix {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tisPrefix1 := strings.HasSuffix(obj1.Name(), \"Prefix\")\n\t\t\t\t\tvar cutFuncName, varName, message, fixMessage string\n\t\t\t\t\tif isPrefix && isPrefix1 {\n\t\t\t\t\t\tcutFuncName = \"CutPrefix\"\n\t\t\t\t\t\tvarName = \"after\"\n\t\t\t\t\t\tmessage = \"HasPrefix + TrimPrefix can be simplified to CutPrefix\"\n\t\t\t\t\t\tfixMessage = \"Replace HasPrefix/TrimPrefix with CutPrefix\"\n\t\t\t\t\t} else if !isPrefix && !isPrefix1 {\n\t\t\t\t\t\tcutFuncName = \"CutSuffix\"\n\t\t\t\t\t\tvarName = \"before\"\n\t\t\t\t\t\tmessage = \"HasSuffix + TrimSuffix can be simplified to CutSuffix\"\n\t\t\t\t\t\tfixMessage = \"Replace HasSuffix/TrimSuffix with CutSuffix\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\t// Have: if strings.HasPrefix(s0, pre0) { ...strings.TrimPrefix(s, pre)... } (ditto Suffix)\n\t\t\t\t\tvar (\n\t\t\t\t\t\ts0   = call.Args[0]\n\t\t\t\t\t\tpre0 = call.Args[1]\n\t\t\t\t\t\ts    = call1.Args[0]\n\t\t\t\t\t\tpre  = call1.Args[1]\n\t\t\t\t\t)\n\n\t\t\t\t\t// check whether the obj1 uses the exact the same argument with strings.HasPrefix\n\t\t\t\t\t// shadow variables won't be valid because we only access the first statement (ditto Suffix).\n\t\t\t\t\tif astutil.EqualSyntax(s0, s) && astutil.EqualSyntax(pre0, pre) {\n\t\t\t\t\t\tafter := refactor.FreshName(info.Scopes[ifStmt], ifStmt.Pos(), varName)\n\t\t\t\t\t\tprefix, importEdits := refactor.AddImport(\n\t\t\t\t\t\t\tinfo,\n\t\t\t\t\t\t\tcurFile.Node().(*ast.File),\n\t\t\t\t\t\t\tobj1.Pkg().Name(),\n\t\t\t\t\t\t\tobj1.Pkg().Path(),\n\t\t\t\t\t\t\tcutFuncName,\n\t\t\t\t\t\t\tcall.Pos(),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tokVarName := refactor.FreshName(info.Scopes[ifStmt], ifStmt.Pos(), \"ok\")\n\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t// highlight at HasPrefix call (ditto Suffix).\n\t\t\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\t\tMessage: message,\n\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\tMessage: fixMessage,\n\t\t\t\t\t\t\t\t// if              strings.HasPrefix(s, pre)     { use(strings.TrimPrefix(s, pre)) }\n\t\t\t\t\t\t\t\t//    ------------ -----------------        -----      --------------------------\n\t\t\t\t\t\t\t\t// if after, ok := strings.CutPrefix(s, pre); ok { use(after)                      }\n\t\t\t\t\t\t\t\t// (ditto Suffix)\n\t\t\t\t\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call.Fun.Pos(),\n\t\t\t\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s, %s :=\", after, okVarName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s%s\", prefix, cutFuncName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     call.End(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"; %s \", okVarName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     call1.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call1.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(after),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}...),\n\t\t\t\t\t\t\t}}},\n\t\t\t\t\t\t)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// pattern2\n\t\t\tif bin, ok := ifStmt.Cond.(*ast.BinaryExpr); ok &&\n\t\t\t\tbin.Op == token.NEQ &&\n\t\t\t\tifStmt.Init != nil &&\n\t\t\t\tisSimpleAssign(ifStmt.Init) {\n\t\t\t\tassign := ifStmt.Init.(*ast.AssignStmt)\n\t\t\t\tif call, ok := assign.Rhs[0].(*ast.CallExpr); ok && assign.Tok == token.DEFINE {\n\t\t\t\t\tlhs := assign.Lhs[0]\n\t\t\t\t\tobj := typeutil.Callee(info, call)\n\n\t\t\t\t\tif obj == nil ||\n\t\t\t\t\t\tobj != stringsTrimPrefix && obj != bytesTrimPrefix && obj != stringsTrimSuffix && obj != bytesTrimSuffix {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tisPrefix1 := strings.HasSuffix(obj.Name(), \"Prefix\")\n\t\t\t\t\tvar cutFuncName, message, fixMessage string\n\t\t\t\t\tif isPrefix1 {\n\t\t\t\t\t\tcutFuncName = \"CutPrefix\"\n\t\t\t\t\t\tmessage = \"TrimPrefix can be simplified to CutPrefix\"\n\t\t\t\t\t\tfixMessage = \"Replace TrimPrefix with CutPrefix\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcutFuncName = \"CutSuffix\"\n\t\t\t\t\t\tmessage = \"TrimSuffix can be simplified to CutSuffix\"\n\t\t\t\t\t\tfixMessage = \"Replace TrimSuffix with CutSuffix\"\n\t\t\t\t\t}\n\n\t\t\t\t\tif astutil.EqualSyntax(lhs, bin.X) && astutil.EqualSyntax(call.Args[0], bin.Y) ||\n\t\t\t\t\t\t(astutil.EqualSyntax(lhs, bin.Y) && astutil.EqualSyntax(call.Args[0], bin.X)) {\n\t\t\t\t\t\tokVarName := freshName(info, index, info.Scopes[ifStmt], ifStmt.Pos(), curIfStmt, curIfStmt, token.NoPos, \"ok\")\n\t\t\t\t\t\t// Have one of:\n\t\t\t\t\t\t//   if rest := TrimPrefix(s, prefix); rest != s { (ditto Suffix)\n\t\t\t\t\t\t//   if rest := TrimPrefix(s, prefix); s != rest { (ditto Suffix)\n\n\t\t\t\t\t\t// We use AddImport not to add an import (since it exists already)\n\t\t\t\t\t\t// but to compute the correct prefix in the dot-import case.\n\t\t\t\t\t\tprefix, importEdits := refactor.AddImport(\n\t\t\t\t\t\t\tinfo,\n\t\t\t\t\t\t\tcurFile.Node().(*ast.File),\n\t\t\t\t\t\t\tobj.Pkg().Name(),\n\t\t\t\t\t\t\tobj.Pkg().Path(),\n\t\t\t\t\t\t\tcutFuncName,\n\t\t\t\t\t\t\tcall.Pos(),\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t// highlight from the init and the condition end.\n\t\t\t\t\t\t\tPos:     ifStmt.Init.Pos(),\n\t\t\t\t\t\t\tEnd:     ifStmt.Cond.End(),\n\t\t\t\t\t\t\tMessage: message,\n\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\tMessage: fixMessage,\n\t\t\t\t\t\t\t\t// if x     := strings.TrimPrefix(s, pre); x != s ...\n\t\t\t\t\t\t\t\t//     ----            ----------          ------\n\t\t\t\t\t\t\t\t// if x, ok := strings.CutPrefix (s, pre); ok     ...\n\t\t\t\t\t\t\t\t// (ditto Suffix)\n\t\t\t\t\t\t\t\tTextEdits: append(importEdits, []analysis.TextEdit{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     assign.Lhs[0].End(),\n\t\t\t\t\t\t\t\t\t\tEnd:     assign.Lhs[0].End(),\n\t\t\t\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \", %s\", okVarName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s%s\", prefix, cutFuncName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPos:     ifStmt.Cond.Pos(),\n\t\t\t\t\t\t\t\t\t\tEnd:     ifStmt.Cond.End(),\n\t\t\t\t\t\t\t\t\t\tNewText: []byte(okVarName),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}...),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/stringsseq.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar StringsSeqAnalyzer = &analysis.Analyzer{\n\tName: \"stringsseq\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"stringsseq\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: stringsseq,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringsseq\",\n}\n\n// stringsseq offers a fix to replace a call to strings.Split with\n// SplitSeq or strings.Fields with FieldsSeq\n// when it is the operand of a range loop, either directly:\n//\n//\tfor _, line := range strings.Split() {...}\n//\n// or indirectly, if the variable's sole use is the range statement:\n//\n//\tlines := strings.Split()\n//\tfor _, line := range lines {...}\n//\n// Variants:\n// - bytes.SplitSeq\n// - bytes.FieldsSeq\nfunc stringsseq(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\n\t\tstringsSplit  = index.Object(\"strings\", \"Split\")\n\t\tstringsFields = index.Object(\"strings\", \"Fields\")\n\t\tbytesSplit    = index.Object(\"bytes\", \"Split\")\n\t\tbytesFields   = index.Object(\"bytes\", \"Fields\")\n\t)\n\tif !index.Used(stringsSplit, stringsFields, bytesSplit, bytesFields) {\n\t\treturn nil, nil\n\t}\n\n\tfor curFile := range filesUsingGoVersion(pass, versions.Go1_24) {\n\t\tfor curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {\n\t\t\trng := curRange.Node().(*ast.RangeStmt)\n\n\t\t\t// Reject \"for i, line := ...\" since SplitSeq is not an iter.Seq2.\n\t\t\t// (We require that i is blank.)\n\t\t\tif id, ok := rng.Key.(*ast.Ident); ok && id.Name != \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Find the call operand of the range statement,\n\t\t\t// whether direct or indirect.\n\t\t\tcall, ok := rng.X.(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\tif id, ok := rng.X.(*ast.Ident); ok {\n\t\t\t\t\tif v, ok := info.Uses[id].(*types.Var); ok {\n\t\t\t\t\t\tif ek, idx := curRange.ParentEdge(); ek == edge.BlockStmt_List && idx > 0 {\n\t\t\t\t\t\t\tcurPrev, _ := curRange.PrevSibling()\n\t\t\t\t\t\t\tif assign, ok := curPrev.Node().(*ast.AssignStmt); ok &&\n\t\t\t\t\t\t\t\tassign.Tok == token.DEFINE &&\n\t\t\t\t\t\t\t\tlen(assign.Lhs) == 1 &&\n\t\t\t\t\t\t\t\tlen(assign.Rhs) == 1 &&\n\t\t\t\t\t\t\t\tinfo.Defs[assign.Lhs[0].(*ast.Ident)] == v &&\n\t\t\t\t\t\t\t\tsoleUseIs(index, v, id) {\n\t\t\t\t\t\t\t\t// Have:\n\t\t\t\t\t\t\t\t//    lines := ...\n\t\t\t\t\t\t\t\t//    for _, line := range lines {...}\n\t\t\t\t\t\t\t\t// and no other uses of lines.\n\t\t\t\t\t\t\t\tcall, _ = assign.Rhs[0].(*ast.CallExpr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif call != nil {\n\t\t\t\tvar edits []analysis.TextEdit\n\t\t\t\tif rng.Key != nil {\n\t\t\t\t\t// Delete (blank) RangeStmt.Key:\n\t\t\t\t\t//  for _, line := -> for line :=\n\t\t\t\t\t//  for _, _    := -> for\n\t\t\t\t\t//  for _       := -> for\n\t\t\t\t\tend := rng.Range\n\t\t\t\t\tif rng.Value != nil {\n\t\t\t\t\t\tend = rng.Value.Pos()\n\t\t\t\t\t}\n\t\t\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\t\t\tPos: rng.Key.Pos(),\n\t\t\t\t\t\tEnd: end,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tsel, ok := call.Fun.(*ast.SelectorExpr)\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tswitch obj := typeutil.Callee(info, call); obj {\n\t\t\t\tcase stringsSplit, stringsFields, bytesSplit, bytesFields:\n\t\t\t\t\toldFnName := obj.Name()\n\t\t\t\t\tseqFnName := fmt.Sprintf(\"%sSeq\", oldFnName)\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     sel.Pos(),\n\t\t\t\t\t\tEnd:     sel.End(),\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"Ranging over %s is more efficient\", seqFnName),\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace %s with %s\", oldFnName, seqFnName),\n\t\t\t\t\t\t\tTextEdits: append(edits, analysis.TextEdit{\n\t\t\t\t\t\t\t\tPos:     sel.Sel.Pos(),\n\t\t\t\t\t\t\t\tEnd:     sel.Sel.End(),\n\t\t\t\t\t\t\t\tNewText: []byte(seqFnName)}),\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/any/any.go",
    "content": "package any\n\nfunc _(x interface{}) {} // want \"interface{} can be replaced by any\"\n\nfunc _() {\n\tvar x interface{} // want \"interface{} can be replaced by any\"\n\tconst any = 1\n\tvar y interface{} // nope: any is shadowed here\n\t_, _ = x, y\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/any/any.go.golden",
    "content": "package any\n\nfunc _(x any) {} // want \"interface{} can be replaced by any\"\n\nfunc _() {\n\tvar x any // want \"interface{} can be replaced by any\"\n\tconst any = 1\n\tvar y interface{} // nope: any is shadowed here\n\t_, _ = x, y\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/any/generated.go",
    "content": "// Code generated by hand. DO NOT EDIT.\n\npackage any\n\nfunc _(x interface{}) {} // want \"interface{} can be replaced by any\"\n\nfunc _() {\n\tvar x interface{} // want \"interface{} can be replaced by any\"\n\tconst any = 1\n\tvar y interface{} // nope: any is shadowed here\n\t_, _ = x, y\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/any/generated.go.golden",
    "content": "// Code generated by hand. DO NOT EDIT.\n\npackage any\n\nfunc _(x interface{}) {} // want \"interface{} can be replaced by any\"\n\nfunc _() {\n\tvar x interface{} // want \"interface{} can be replaced by any\"\n\tconst any = 1\n\tvar y interface{} // nope: any is shadowed here\n\t_, _ = x, y\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/appendclipped/appendclipped.go",
    "content": "package appendclipped\n\nimport (\n\t\"os\"\n\t\"slices\"\n)\n\ntype (\n\tBytes  []byte\n\tBytes2 []byte\n)\n\nfunc _(s, other []string) {\n\tprint(append([]string{}, s...))              // want \"Replace append with slices.Clone\"\n\tprint(append([]string(nil), s...))           // want \"Replace append with slices.Clone\"\n\tprint(append(Bytes(nil), Bytes{1, 2, 3}...)) // want \"Replace append with slices.Clone\"\n\tprint(append(other[:0:0], s...))             // want \"Replace append with slices.Clone\"\n\tprint(append(other[:0:0], os.Environ()...))  // want \"Redundant clone of os.Environ()\"\n\tprint(append(other[:0], s...))               // nope: intent may be to mutate other\n\n\tprint(append(append(append([]string{}, s...), other...), other...))             // want \"Replace append with slices.Concat\"\n\tprint(append(append(append([]string(nil), s...), other...), other...))          // want \"Replace append with slices.Concat\"\n\tprint(append(append(Bytes(nil), Bytes{1, 2, 3}...), Bytes{4, 5, 6}...))         // want \"Replace append with slices.Concat\"\n\tprint(append(append(append(other[:0:0], s...), other...), other...))            // want \"Replace append with slices.Concat\"\n\tprint(append(append(append(other[:0:0], os.Environ()...), other...), other...)) // want \"Replace append with slices.Concat\"\n\tprint(append(append(other[:len(other):len(other)], s...), other...))            // want \"Replace append with slices.Concat\"\n\tprint(append(append(slices.Clip(other), s...), other...))                       // want \"Replace append with slices.Concat\"\n\tprint(append(append(append(other[:0], s...), other...), other...))              // nope: intent may be to mutate other\n}\n\nvar (\n\t_ Bytes  = append(Bytes(nil), []byte(nil)...) // nope: correct fix requires Clone[Bytes] (#73661)\n\t_ Bytes  = append([]byte(nil), Bytes(nil)...) // nope: correct fix requires Clone[Bytes] (#73661)\n\t_ Bytes2 = append([]byte(nil), Bytes(nil)...) // nope: correct fix requires Clone[Bytes2] (#73661)\n)\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/appendclipped/appendclipped.go.golden",
    "content": "package appendclipped\n\nimport (\n\t\"os\"\n\t\"slices\"\n)\n\ntype (\n\tBytes\t[]byte\n\tBytes2  []byte\n)\n\nfunc _(s, other []string) {\n\tprint(slices.Clone(s))              // want \"Replace append with slices.Clone\"\n\tprint(slices.Clone(s))              // want \"Replace append with slices.Clone\"\n\tprint(slices.Clone(Bytes{1, 2, 3})) // want \"Replace append with slices.Clone\"\n\tprint(slices.Clone(s))              // want \"Replace append with slices.Clone\"\n\tprint(os.Environ())                 // want \"Redundant clone of os.Environ()\"\n\tprint(append(other[:0], s...))      // nope: intent may be to mutate other\n\n\tprint(slices.Concat(s, other, other))                              // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(s, other, other))                              // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(Bytes{1, 2, 3}, Bytes{4, 5, 6}))               // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(s, other, other))                              // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(os.Environ(), other, other))                   // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(other, s, other))                              // want \"Replace append with slices.Concat\"\n\tprint(slices.Concat(other, s, other))                              // want \"Replace append with slices.Concat\"\n\tprint(append(append(append(other[:0], s...), other...), other...)) // nope: intent may be to mutate other\n}\n\nvar (\n\t_ Bytes  = append(Bytes(nil), []byte(nil)...) // nope: correct fix requires Clone[Bytes] (#73661)\n\t_ Bytes  = append([]byte(nil), Bytes(nil)...) // nope: correct fix requires Clone[Bytes] (#73661)\n\t_ Bytes2 = append([]byte(nil), Bytes(nil)...) // nope: correct fix requires Clone[Bytes2] (#73661)\n)\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/appendclipped/bytesclone.go",
    "content": "package appendclipped\n\nimport (\n\t\"bytes\"\n)\n\nvar _ bytes.Buffer\n\nfunc _(b []byte) {\n\tprint(append([]byte{}, b...)) // want \"Replace append with bytes.Clone\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/appendclipped/bytesclone.go.golden",
    "content": "package appendclipped\n\nimport (\n\t\"bytes\"\n)\n\nvar _ bytes.Buffer\n\nfunc _(b []byte) {\n\tprint(bytes.Clone(b)) // want \"Replace append with bytes.Clone\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/atomic.go",
    "content": "package atomic\n\nimport (\n\t\"log\"\n\t\"sync/atomic\"\n)\n\ntype X struct {\n\tx int32 // want \"var x int32 may be simplified using atomic.Int32\"\n}\n\ntype Z struct {\n\ty int64 // want \"var y int64 may be simplified using atomic.Int64\"\n\tz int64\n}\n\nfunc (wrapper *Z) fix() {\n\tvar x int32 // want \"var x int32 may be simplified using atomic.Int32\"\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 1)\n\t}\n\n\tvar x2 int32 = 5 // nope: can't assign an int to an atomic.Int32\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x2, 1)\n\t}\n\n\tvar y X\n\tfor range 100 {\n\t\tgo atomic.CompareAndSwapInt32(&y.x, 2, 3)\n\t}\n\n\tatomic.CompareAndSwapInt64(&wrapper.y, 2, 3)\n\n\tvar z int32\n\t_ = z\n\tif z == 0 { // nope: cannot rewrite rvalue use (unsynchronized load)\n\t\tgo atomic.LoadInt32(&z)\n\t\tlog.Print(z)\n\t}\n}\n\ntype Y int32\n\nfunc (y Y) dontfix(x int32) (result int32) {\n\tatomic.AddInt32(&x, 1)           // nope - v is a type param\n\tatomic.StoreInt32(&result, 100)  // nope - v is a return value\n\tatomic.AddInt32((*int32)(&y), 1) // nope - v is a receiver var\n\tw := Z{\n\t\tz: 1,\n\t}\n\tatomic.AddInt64(&w.z, 1) // nope - cannot fix initial value assignment\n\treturn\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/atomic.go.golden",
    "content": "package atomic\n\nimport (\n\t\"log\"\n\t\"sync/atomic\"\n)\n\ntype X struct {\n\tx atomic.Int32 // want \"var x int32 may be simplified using atomic.Int32\"\n}\n\ntype Z struct {\n\ty atomic.Int64 // want \"var y int64 may be simplified using atomic.Int64\"\n\tz int64\n}\n\nfunc (wrapper *Z) fix() {\n\tvar x atomic.Int32 // want \"var x int32 may be simplified using atomic.Int32\"\n\tfor range 100 {\n\t\tgo x.Add(1)\n\t}\n\n\tvar x2 int32 = 5 // nope: can't assign an int to an atomic.Int32\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x2, 1)\n\t}\n\n\tvar y X\n\tfor range 100 {\n\t\tgo y.x.CompareAndSwap(2, 3)\n\t}\n\n\twrapper.y.CompareAndSwap(2, 3)\n\n\tvar z int32\n\t_ = z\n\tif z == 0 { // nope: cannot rewrite rvalue use (unsynchronized load)\n\t\tgo atomic.LoadInt32(&z)\n\t\tlog.Print(z)\n\t}\n}\n\ntype Y int32\n\nfunc (y Y) dontfix(x int32) (result int32) {\n\tatomic.AddInt32(&x, 1)           // nope - v is a type param\n\tatomic.StoreInt32(&result, 100)  // nope - v is a return value\n\tatomic.AddInt32((*int32)(&y), 1) // nope - v is a receiver var\n\tw := Z{\n\t\tz: 1,\n\t}\n\tatomic.AddInt64(&w.z, 1) // nope - cannot fix initial value assignment\n\treturn\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/atomic_shadow.go",
    "content": "package atomic\n\nimport myatomic \"sync/atomic\"\n\nfunc _() {\n\tvar x int32 // want \"var x int32 may be simplified using atomic.Int32\"\n\tfor range 100 {\n\t\tgo myatomic.AddInt32(&x, 1)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/atomic_shadow.go.golden",
    "content": "package atomic\n\nimport myatomic \"sync/atomic\"\n\nfunc _() {\n\tvar x myatomic.Int32 // want \"var x int32 may be simplified using atomic.Int32\"\n\tfor range 100 {\n\t\tgo x.Add(1)\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/go118/atomic_go118.go",
    "content": "//go:build !go1.19\n\npackage go118\n\nimport \"sync/atomic\"\n\nfunc _() {\n\tvar x int32 // AddInt32 not available until go1.19\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 1)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/go118/atomic_go118.go.golden",
    "content": "//go:build !go1.19\n\npackage go118\n\nimport \"sync/atomic\"\n\nfunc _() {\n\tvar x int32 // AddInt32 not available until go1.19\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 2)\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/go120/atomic_go120.go",
    "content": "//go:build !go1.21\n\npackage go120\n\nimport \"sync/atomic\"\n\nfunc _() {\n\tvar x int32 // AndInt32 not available until go1.23\n\tfor range 100 {\n\t\tgo atomic.AndInt32(&x, 1)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/go120/atomic_go120.go.golden",
    "content": "//go:build !go1.21\n\npackage go120\n\nimport \"sync/atomic\"\n\nfunc _() {\n\tvar x int32 // AndInt32 not available until go1.23\n\tfor range 100 {\n\t\tgo atomic.AndInt32(&x, 1)\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/ignored/atomic.go",
    "content": "package ignored\n\nimport (\n\t\"sync/atomic\"\n)\n\nvar x int32 // don't fix - package has ignored files\n\nfunc _() {\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 1)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/ignored/atomic.go.golden",
    "content": "package ignored\n\nimport (\n\t\"sync/atomic\"\n)\n\nvar x int32 // don't fix - package has ignored files\n\nfunc _() {\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 1)\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/atomictypes/ignored/atomic_ignored.go",
    "content": "//go:build !go1.19\n\npackage ignored\n\nimport \"sync/atomic\"\n\nfunc _() {\n\tfor range 100 {\n\t\tgo atomic.AddInt32(&x, 1)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/bloop/bloop.go",
    "content": "package bloop\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/bloop/bloop_test.go",
    "content": "//go:build go1.24\n\npackage bloop\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc BenchmarkA(b *testing.B) {\n\tprintln(\"slow\")\n\tb.ResetTimer()\n\n\tfor range b.N { // want \"b.N can be modernized using b.Loop..\"\n\t}\n}\n\nfunc BenchmarkB(b *testing.B) {\n\t// setup\n\t{\n\t\tb.StopTimer()\n\t\tprintln(\"slow\")\n\t\tb.StartTimer()\n\t}\n\n\tfor i := range b.N { // Nope. Should we change this to \"for i := 0; b.Loop(); i++\"?\n\t\tprint(i)\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkC(b *testing.B) {\n\t// setup\n\t{\n\t\tb.StopTimer()\n\t\tprintln(\"slow\")\n\t\tb.StartTimer()\n\t}\n\n\tfor i := 0; i < b.N; i++ { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(\"no uses of i\")\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkD(b *testing.B) {\n\tfor i := 0; i < b.N; i++ { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(i)\n\t}\n}\n\nfunc BenchmarkE(b *testing.B) {\n\tb.Run(\"sub\", func(b *testing.B) {\n\t\tb.StopTimer() // not deleted\n\t\tprintln(\"slow\")\n\t\tb.StartTimer() // not deleted\n\n\t\t// ...\n\t})\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(\"no uses of i\")\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkF(b *testing.B) {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor i := 0; i < b.N; i++ { // nope: b.N accessed from a FuncLit\n\t\t}\n\t}()\n\twg.Wait()\n}\n\nfunc BenchmarkG(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tposter := func() {\n\t\tfor i := 0; i < b.N; i++ { // nope: b.N accessed from a FuncLit\n\t\t}\n\t\twg.Done()\n\t}\n\twg.Add(2)\n\tfor i := 0; i < 2; i++ {\n\t\tgo poster()\n\t}\n\twg.Wait()\n}\n\nfunc BenchmarkH(b *testing.B) {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor range b.N { // nope: b.N accessed from a FuncLit\n\t\t}\n\t}()\n\twg.Wait()\n}\n\nfunc BenchmarkI(b *testing.B) {\n\tfor i := 0; i < b.N; i++ { // nope: b.N accessed more than once in benchmark\n\t}\n\tfor i := 0; i < b.N; i++ { // nope: b.N accessed more than once in benchmark\n\t}\n}\n\nfunc BenchmarkJ(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tch := make(chan int, 10)\n\twg.Add(1)\n\tgo func() {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t<-ch\n\t\t}\n\t\twg.Done()\n\t}()\n\tb.ResetTimer()\n\tfor i := 0; i < b.N; i++ { // nope: multiple b.N loops in same function\n\t\tch <- i\n\t}\n\tb.StopTimer()\n\twg.Wait()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/bloop/bloop_test.go.golden",
    "content": "//go:build go1.24\n\npackage bloop\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc BenchmarkA(b *testing.B) {\n\tprintln(\"slow\")\n\n\tfor b.Loop() { // want \"b.N can be modernized using b.Loop..\"\n\t}\n}\n\nfunc BenchmarkB(b *testing.B) {\n\t// setup\n\t{\n\t\tb.StopTimer()\n\t\tprintln(\"slow\")\n\t\tb.StartTimer()\n\t}\n\n\tfor i := range b.N { // Nope. Should we change this to \"for i := 0; b.Loop(); i++\"?\n\t\tprint(i)\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkC(b *testing.B) {\n\t// setup\n\t{\n\n\t\tprintln(\"slow\")\n\n\t}\n\n\tfor b.Loop() { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(\"no uses of i\")\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkD(b *testing.B) {\n\tfor i := 0; b.Loop(); i++ { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(i)\n\t}\n}\n\nfunc BenchmarkE(b *testing.B) {\n\tb.Run(\"sub\", func(b *testing.B) {\n\t\tb.StopTimer() // not deleted\n\t\tprintln(\"slow\")\n\t\tb.StartTimer() // not deleted\n\n\t\t// ...\n\t})\n\n\tfor b.Loop() { // want \"b.N can be modernized using b.Loop..\"\n\t\tprintln(\"no uses of i\")\n\t}\n\n\tb.StopTimer()\n\tprintln(\"slow\")\n}\n\nfunc BenchmarkF(b *testing.B) {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor i := 0; i < b.N; i++ { // nope: b.N accessed from a FuncLit\n\t\t}\n\t}()\n\twg.Wait()\n}\n\nfunc BenchmarkG(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tposter := func() {\n\t\tfor i := 0; i < b.N; i++ { // nope: b.N accessed from a FuncLit\n\t\t}\n\t\twg.Done()\n\t}\n\twg.Add(2)\n\tfor i := 0; i < 2; i++ {\n\t\tgo poster()\n\t}\n\twg.Wait()\n}\n\nfunc BenchmarkH(b *testing.B) {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor range b.N { // nope: b.N accessed from a FuncLit\n\t\t}\n\t}()\n\twg.Wait()\n}\n\nfunc BenchmarkI(b *testing.B) {\n\tfor i := 0; i < b.N; i++ { // nope: b.N accessed more than once in benchmark\n\t}\n\tfor i := 0; i < b.N; i++ { // nope: b.N accessed more than once in benchmark\n\t}\n}\n\nfunc BenchmarkJ(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tch := make(chan int, 10)\n\twg.Add(1)\n\tgo func() {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t<-ch\n\t\t}\n\t\twg.Done()\n\t}()\n\tb.ResetTimer()\n\tfor i := 0; i < b.N; i++ { // nope: multiple b.N loops in same function\n\t\tch <- i\n\t}\n\tb.StopTimer()\n\twg.Wait()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/errorsastype/dotimport/a.go",
    "content": "package errorsastype\n\nimport (\n\t. \"errors\"\n\t\"os\"\n)\n\nfunc _(err error) {\n\tvar patherr *os.PathError\n\tif As(err, &patherr) { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\tprint(patherr)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/errorsastype/dotimport/a.go.golden",
    "content": "package errorsastype\n\nimport (\n\t. \"errors\"\n\t\"os\"\n)\n\nfunc _(err error) {\n\tif patherr, ok := AsType[*os.PathError](err); ok { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\tprint(patherr)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/errorsastype/errorsastype.go",
    "content": "package errorsastype\n\nimport (\n\t\"errors\"\n\t\"os\"\n)\n\nfunc _(err error) {\n\t{\n\t\tvar patherr *os.PathError\n\t\tif errors.As(err, &patherr) { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tprint(\"not a use of patherr\")\n\t\tif errors.As(err, &patherr) { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t\tprint(\"also not a use of patherr\")\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tprint(patherr)\n\t\tif errors.As(err, &patherr) { // nope: patherr is used outside scope of if\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tif errors.As(err, &patherr) { // nope: patherr is used outside scope of if\n\t\t\tprint(patherr)\n\t\t}\n\t\tprint(patherr)\n\t}\n\n\t// Test of 'ok' var shadowing/freshness.\n\tconst ok = 1\n\t{\n\t\tvar patherr *os.PathError\n\t\tif errors.As(err, &patherr) { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tif errors.As(err, &patherr) { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr, ok)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/errorsastype/errorsastype.go.golden",
    "content": "package errorsastype\n\nimport (\n\t\"errors\"\n\t\"os\"\n)\n\nfunc _(err error) {\n\t{\n\t\tif patherr, ok := errors.AsType[*os.PathError](err); ok { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tprint(\"not a use of patherr\")\n\t\tif patherr, ok := errors.AsType[*os.PathError](err); ok { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t\tprint(\"also not a use of patherr\")\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tprint(patherr)\n\t\tif errors.As(err, &patherr) { // nope: patherr is used outside scope of if\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tvar patherr *os.PathError\n\t\tif errors.As(err, &patherr) { // nope: patherr is used outside scope of if\n\t\t\tprint(patherr)\n\t\t}\n\t\tprint(patherr)\n\t}\n\n\t// Test of 'ok' var shadowing/freshness.\n\tconst ok = 1\n\t{\n\t\tif patherr, ok := errors.AsType[*os.PathError](err); ok { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr)\n\t\t}\n\t}\n\t{\n\t\tif patherr, ok0 := errors.AsType[*os.PathError](err); ok0 { // want `errors.As can be simplified using AsType\\[\\*os.PathError\\]`\n\t\t\tprint(patherr, ok)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/fieldsseq/fieldsseq.go",
    "content": "//go:build go1.24\n\npackage fieldsseq\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc _() {\n\tfor _, line := range strings.Fields(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t\tprintln(line)\n\t}\n\tfor i, line := range strings.Fields(\"\") { // nope: uses index var\n\t\tprintln(i, line)\n\t}\n\tfor i, _ := range strings.Fields(\"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor i := range strings.Fields(\"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor _ = range strings.Fields(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\tfor range strings.Fields(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\tfor range bytes.Fields(nil) { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\t{\n\t\tlines := strings.Fields(\"\") // want \"Ranging over FieldsSeq is more efficient\"\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t}\n\t{\n\t\tlines := strings.Fields(\"\") // nope: lines is used not just by range\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t\tprintln(lines)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/fieldsseq/fieldsseq.go.golden",
    "content": "//go:build go1.24\n\npackage fieldsseq\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc _() {\n\tfor line := range strings.FieldsSeq(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t\tprintln(line)\n\t}\n\tfor i, line := range strings.Fields( \"\") { // nope: uses index var\n\t\tprintln(i, line)\n\t}\n\tfor i, _ := range strings.Fields( \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor i := range strings.Fields( \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor range strings.FieldsSeq(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\tfor range strings.FieldsSeq(\"\") { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\tfor range bytes.FieldsSeq(nil) { // want \"Ranging over FieldsSeq is more efficient\"\n\t}\n\t{\n\t\tlines := strings.FieldsSeq(\"\") // want \"Ranging over FieldsSeq is more efficient\"\n\t\tfor line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t}\n\t{\n\t\tlines := strings.Fields( \"\") // nope: lines is used not just by range\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t\tprintln(lines)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/fieldsseq/fieldsseq_go123.go",
    "content": "package fieldsseq\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/fmtappendf/fmtappendf.go",
    "content": "package fmtappendf\n\nimport (\n\t\"fmt\"\n)\n\nfunc two() string {\n\treturn \"two\"\n}\n\nfunc bye() {\n\t_ = []byte(fmt.Sprintf(\"bye %d\", 1)) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc funcsandvars() {\n\tone := \"one\"\n\t_ = []byte(fmt.Sprintf(\"bye %d %s %s\", 1, two(), one)) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc typealias() {\n\ttype b = byte\n\ttype bt = []byte\n\t_ = []b(fmt.Sprintf(\"bye %d\", 1)) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n\t_ = bt(fmt.Sprintf(\"bye %d\", 1))  // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc otherprints() {\n\t_ = []byte(fmt.Sprint(\"bye %d\", 1))   // want \"Replace .*Sprint.* with fmt.Append\"\n\t_ = []byte(fmt.Sprintln(\"bye %d\", 1)) // want \"Replace .*Sprintln.* with fmt.Appendln\"\n}\n\nfunc comma() {\n\ttype S struct{ Bytes []byte }\n\tvar _ = struct{ A S }{\n\t\tA: S{\n\t\t\tBytes: []byte( // want \"Replace .*Sprint.* with fmt.Appendf\"\n\t\t\t\tfmt.Sprintf(\"%d\", 0),\n\t\t\t),\n\t\t},\n\t}\n\t_ = []byte( // want \"Replace .*Sprint.* with fmt.Appendf\"\n\t\tfmt.Sprintf(\"%d\", 0),\n\t)\n}\n\nfunc emptystring() {\n\t// empty string edge case only applies to Sprintf\n\t_ = []byte(fmt.Sprintln(\"\")) // want \"Replace .*Sprintln.* with fmt.Appendln\"\n\t// nope - these return []byte{}, while the fmt.Append version returns nil\n\t_ = []byte(fmt.Sprint(\"\"))\n\t_ = []byte(fmt.Sprintf(\"%s\", \"\"))\n\t_ = []byte(fmt.Sprintf(\"%#s\", \"\"))\n\t_ = []byte(fmt.Sprintf(\"%s%v\", \"\", getString()))\n\t// conservatively omitting a suggested fix (ignoring precision and args)\n\t_ = []byte(fmt.Sprintf(\"%.0q\", \"notprinted\"))\n\t_ = []byte(fmt.Sprintf(\"%v\", \"nonempty\"))\n\t// has non-operation characters\n\t_ = []byte(fmt.Sprintf(\"%vother\", \"\")) // want \"Replace .*Sprint.* with fmt.Appendf\"\n}\n\nfunc multiline() []byte {\n\t_ = []byte( // want \"Replace .*Sprintf.* with fmt.Appendf\"\n\t\tfmt.Sprintf(\"str %d\", 1))\n\n\treturn []byte( // want \"Replace .*Sprintf.* with fmt.Appendf\"\n\t\tfmt.Sprintf(\"str %d\", 1),\n\t)\n}\n\nfunc getString() string {\n\treturn \"\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/fmtappendf/fmtappendf.go.golden",
    "content": "package fmtappendf\n\nimport (\n\t\"fmt\"\n)\n\nfunc two() string {\n\treturn \"two\"\n}\n\nfunc bye() {\n\t_ = fmt.Appendf(nil, \"bye %d\", 1) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc funcsandvars() {\n\tone := \"one\"\n\t_ = fmt.Appendf(nil, \"bye %d %s %s\", 1, two(), one) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc typealias() {\n\ttype b = byte\n\ttype bt = []byte\n\t_ = fmt.Appendf(nil, \"bye %d\", 1) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n\t_ = fmt.Appendf(nil, \"bye %d\", 1) // want \"Replace .*Sprintf.* with fmt.Appendf\"\n}\n\nfunc otherprints() {\n\t_ = fmt.Append(nil, \"bye %d\", 1) // want \"Replace .*Sprint.* with fmt.Append\"\n\t_ = fmt.Appendln(nil, \"bye %d\", 1) // want \"Replace .*Sprintln.* with fmt.Appendln\"\n}\n\nfunc comma() {\n\ttype S struct{ Bytes []byte }\n\tvar _ = struct{ A S }{\n\t\tA: S{\n\t\t\tBytes: fmt.Appendf(nil, \"%d\", 0),\n\t\t},\n\t}\n\t_ = fmt.Appendf(nil, \"%d\", 0)          \n}\n\nfunc emptystring() {\n\t// empty string edge case only applies to Sprintf\n\t_ = fmt.Appendln(nil, \"\")  // want \"Replace .*Sprintln.* with fmt.Appendln\"\n\t// nope - these return []byte{}, while the fmt.Append version returns nil\n\t_ = []byte(fmt.Sprint(\"\"))\n\t_ = []byte(fmt.Sprintf(\"%s\", \"\"))\n\t_ = []byte(fmt.Sprintf(\"%#s\", \"\"))\n\t_ = []byte(fmt.Sprintf(\"%s%v\", \"\", getString()))\n\t// conservatively omitting a suggested fix (ignoring precision and args)\n\t_ = []byte(fmt.Sprintf(\"%.0q\", \"notprinted\"))\n\t_ = []byte(fmt.Sprintf(\"%v\", \"nonempty\"))\n\t// has non-operation characters\n\t_ = fmt.Appendf(nil, \"%vother\", \"\") // want \"Replace .*Sprint.* with fmt.Appendf\"\n}\n\nfunc multiline() []byte {\n\t_ = fmt.Appendf(nil, \"str %d\", 1)\n\n\treturn fmt.Appendf(nil, \"str %d\", 1)\n}\n\nfunc getString() string {\n\treturn \"\"\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/forvar/forvar.go",
    "content": "package forvar\n\nfunc _(m map[int]int, s []int) {\n\t// changed\n\tfor i := range s {\n\t\ti := i // want \"copying variable is unneeded\"\n\t\tgo f(i)\n\t}\n\tfor _, v := range s {\n\t\tv := v // want \"copying variable is unneeded\"\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tk := k // want \"copying variable is unneeded\"\n\t\tv := v // want \"copying variable is unneeded\"\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tv := v // want \"copying variable is unneeded\"\n\t\tk := k // want \"copying variable is unneeded\"\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tk, v := k, v // want \"copying variable is unneeded\"\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tv, k := v, k // want \"copying variable is unneeded\"\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor i := range s {\n\t\t/* hi */ i := i // want \"copying variable is unneeded\"\n\t\tgo f(i)\n\t}\n\tfor v := range m {\n\t\tif v := v; true { // want \"copying variable is unneeded\"\n\t\t\tprint(v)\n\t\t}\n\t}\n\n\t// nope\n\tvar i, k, v int\n\n\tfor i = range s { // nope, scope change\n\t\ti := i\n\t\tgo f(i)\n\t}\n\tfor _, v = range s { // nope, scope change\n\t\tv := v\n\t\tgo f(v)\n\t}\n\tfor k = range m { // nope, scope change\n\t\tk := k\n\t\tgo f(k)\n\t}\n\tfor k, v = range m { // nope, scope change\n\t\tk := k\n\t\tv := v\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor _, v = range m { // nope, scope change\n\t\tv := v\n\t\tgo f(v)\n\t}\n\tfor _, v = range m { // nope, not x := x\n\t\tv := i\n\t\tgo f(v)\n\t}\n\tfor k, v := range m { // nope, LHS and RHS differ\n\t\tv, k := k, v\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m { // nope, not a simple redecl\n\t\tk, v, x := k, v, 1\n\t\tgo f(k)\n\t\tgo f(v)\n\t\tgo f(x)\n\t}\n\tfor i := range s { // nope, not a simple redecl\n\t\ti := (i)\n\t\tgo f(i)\n\t}\n\tfor i := range s { // nope, not a simple redecl\n\t\ti := i + 1\n\t\tgo f(i)\n\t}\n\tfor v := range m {\n\t\tif v := v; true { // nope, would merge distinct outer and inner variables v\n\t\t\tprint(v)\n\t\t}\n\t\tprint(v)\n\t}\n}\n\nfunc f(n int) {}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/forvar/forvar.go.golden",
    "content": "package forvar\n\nfunc _(m map[int]int, s []int) {\n\t// changed\n\tfor i := range s {\n\t\tgo f(i)\n\t}\n\tfor _, v := range s {\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m {\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor i := range s {\n\t\tgo f(i)\n\t}\n\tfor v := range m {\n\t\tif true { // want \"copying variable is unneeded\"\n\t\t\tprint(v)\n\t\t}\n\t}\n\n\t// nope\n\tvar i, k, v int\n\n\tfor i = range s { // nope, scope change\n\t\ti := i\n\t\tgo f(i)\n\t}\n\tfor _, v = range s { // nope, scope change\n\t\tv := v\n\t\tgo f(v)\n\t}\n\tfor k = range m { // nope, scope change\n\t\tk := k\n\t\tgo f(k)\n\t}\n\tfor k, v = range m { // nope, scope change\n\t\tk := k\n\t\tv := v\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor _, v = range m { // nope, scope change\n\t\tv := v\n\t\tgo f(v)\n\t}\n\tfor _, v = range m { // nope, not x := x\n\t\tv := i\n\t\tgo f(v)\n\t}\n\tfor k, v := range m { // nope, LHS and RHS differ\n\t\tv, k := k, v\n\t\tgo f(k)\n\t\tgo f(v)\n\t}\n\tfor k, v := range m { // nope, not a simple redecl\n\t\tk, v, x := k, v, 1\n\t\tgo f(k)\n\t\tgo f(v)\n\t\tgo f(x)\n\t}\n\tfor i := range s { // nope, not a simple redecl\n\t\ti := (i)\n\t\tgo f(i)\n\t}\n\tfor i := range s { // nope, not a simple redecl\n\t\ti := i + 1\n\t\tgo f(i)\n\t}\n\tfor v := range m {\n\t\tif v := v; true { // nope, would merge distinct outer and inner variables v\n\t\t\tprint(v)\n\t\t}\n\t\tprint(v)\n\t}\n}\n\nfunc f(n int) {}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/mapsloop/mapsloop.go",
    "content": "//go:build go1.23\n\npackage mapsloop\n\nimport (\n\t\"iter\"\n\t\"maps\"\n)\n\nvar _ = maps.Clone[M] // force \"maps\" import so that each diagnostic doesn't add one\n\ntype M map[int]string\n\n// -- src is map --\n\nfunc useCopy(dst, src map[int]string) {\n\t// Replace loop by maps.Copy.\n\tfor key, value := range src {\n\t\t// A\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n}\n\nfunc useCopyRetrieveMap(x map[int]int) {\n\tgetMap := func(int) map[int]int { return nil }\n\tfor i, v := range x {\n\t\t// TODO(yuchen): don't assume that getMap returns the same map each time and has no effects.\n\t\t//\n\t\t// So, to avoid changing the cardinality of side effects,\n\t\t// the limit expression must not involve function calls (e.g. seq.Len()) or channel receives.\n\t\tgetMap(0)[i] = v // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n}\n\nfunc useCopyGeneric[K comparable, V any, M ~map[K]V](dst, src M) {\n\t// Replace loop by maps.Copy.\n\tfor key, value := range src {\n\t\t// A\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n}\n\nfunc useCopyNotClone(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace make(...) by maps.Copy.\n\tdst := make(map[int]string, len(src))\n\t// A\n\tfor key, value := range src {\n\t\t// B\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t\t// C\n\t}\n\n\t// A\n\tdst = map[int]string{}\n\t// B\n\tfor key, value := range src {\n\t\t// C\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useCopyParen(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace (make)(...) by maps.Clone.\n\tdst := (make)(map[int]string, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\n\tdst = (map[int]string{})\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useCopy_typesDiffer(src M) {\n\t// Replace loop but not make(...) as maps.Copy(src) would return wrong type M.\n\tdst := make(map[int]string, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useCopy_typesDiffer2(src map[int]string) {\n\t// Replace loop but not make(...) as maps.Copy(src) would return wrong type map[int]string.\n\tdst := make(M, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useClone_typesDiffer3(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) as maps.Clone(src) returns map[int]string\n\t// which is assignable to M.\n\tvar dst M\n\tdst = make(M, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useClone_typesDiffer4(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) as maps.Clone(src) returns map[int]string\n\t// which is assignable to M.\n\tvar dst M\n\tdst = make(M, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\nfunc useClone_generic[Map ~map[K]V, K comparable, V any](src Map) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) by maps.Clone\n\tdst := make(Map, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n\n// -- src is iter.Seq2 --\n\nfunc useInsert_assignableToSeq2(dst map[int]string, src func(yield func(int, string) bool)) {\n\t// Replace loop by maps.Insert because src is assignable to iter.Seq2.\n\tfor k, v := range src {\n\t\tdst[k] = v // want \"Replace m\\\\[k\\\\]=v loop with maps.Insert\"\n\t}\n}\n\nfunc useCollect(src iter.Seq2[int, string]) {\n\t// Replace loop and make(...) by maps.Collect.\n\tvar dst map[int]string\n\tdst = make(map[int]string) // A\n\t// B\n\tfor key, value := range src {\n\t\t// C\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Collect\"\n\t}\n}\n\nfunc useInsert_typesDifferAssign(src iter.Seq2[int, string]) {\n\t// Replace loop and make(...): maps.Collect returns an unnamed map type\n\t// that is assignable to M.\n\tvar dst M\n\tdst = make(M)\n\t// A\n\tfor key, value := range src {\n\t\t// B\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Collect\"\n\t}\n}\n\nfunc useInsert_typesDifferDeclare(src iter.Seq2[int, string]) {\n\t// Replace loop but not make(...) as maps.Collect would return an\n\t// unnamed map type that would change the type of dst.\n\tdst := make(M)\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Insert\"\n\t}\n}\n\n// -- non-matches --\n\ntype isomerOfSeq2 func(yield func(int, string) bool)\n\nfunc nopeInsertRequiresAssignableToSeq2(dst map[int]string, src isomerOfSeq2) {\n\tfor k, v := range src { // nope: src is not assignable to maps.Insert's iter.Seq2 parameter\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeSingleVarRange(dst map[int]bool, src map[int]string) {\n\tfor key := range src { // nope: must be \"for k, v\"\n\t\tdst[key] = true\n\t}\n}\n\nfunc nopeBodyNotASingleton(src map[int]string) {\n\tvar dst map[int]string\n\tfor key, value := range src {\n\t\tdst[key] = value\n\t\tprintln() // nope: other things in the loop body\n\t}\n}\n\n// Regression test for https://github.com/golang/go/issues/70815#issuecomment-2581999787.\nfunc nopeAssignmentHasIncrementOperator(src map[int]int) {\n\tdst := make(map[int]int)\n\tfor k, v := range src {\n\t\tdst[k] += v\n\t}\n}\n\nfunc nopeNotAMap(src map[int]string) {\n\tvar dst []string\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeNotAMapGeneric[E any, M ~map[int]E, S ~[]E](src M) {\n\tvar dst S\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeHasImplicitValueWidening(src map[string]int) {\n\tdst := make(map[string]any)\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeHasImplicitKeyWidening(src map[string]string) {\n\tdst := make(map[any]string)\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\n// The expression for the map (y[v]) must not itself refer to loop variables.\n// See https://go.dev/issue/77008.\nfunc nopeMapExprUsesLoopVars(x map[int]int, y []map[int]int) {\n\tfor i, v := range x {\n\t\ty[v][i] = v\n\t}\n}\n\nfunc nopeExtraKeyValueUsage(x map[int]int, y []map[int]int) {\n\tfor i, v := range x {\n\t\ty[i][i] = v\n\t}\n\n\tgetMap := func(int) map[int]int { return nil }\n\tfor i, v := range x {\n\t\tgetMap(i)[i] = v\n\t}\n\n\tfor i, v := range x {\n\t\tgetMap(v)[i] = v\n\t}\n}\n\nfunc nope2LhsAssigment(x map[int]int, y map[int]int) {\n\tfor i, v := range x {\n\t\ty[i], _ = v, 0\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/mapsloop/mapsloop.go.golden",
    "content": "//go:build go1.23\n\npackage mapsloop\n\nimport (\n\t\"iter\"\n\t\"maps\"\n)\n\nvar _ = maps.Clone[M] // force \"maps\" import so that each diagnostic doesn't add one\n\ntype M map[int]string\n\n// -- src is map --\n\nfunc useCopy(dst, src map[int]string) {\n\t// Replace loop by maps.Copy.\n\t// A\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n}\n\nfunc useCopyRetrieveMap(x map[int]int) {\n\tgetMap := func(int) map[int]int { return nil }\n\t// TODO(yuchen): don't assume that getMap returns the same map each time and has no effects.\n\t//\n\t// So, to avoid changing the cardinality of side effects,\n\t// the limit expression must not involve function calls (e.g. seq.Len()) or channel receives.\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(getMap(0), x)\n}\n\nfunc useCopyGeneric[K comparable, V any, M ~map[K]V](dst, src M) {\n\t// Replace loop by maps.Copy.\n\t// A\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n}\n\nfunc useCopyNotClone(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace make(...) by maps.Copy.\n\tdst := make(map[int]string, len(src))\n\t// A\n\t// B\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t// C\n\tmaps.Copy(dst, src)\n\n\t// A\n\tdst = map[int]string{}\n\t// B\n\t// C\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useCopyParen(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace (make)(...) by maps.Clone.\n\tdst := (make)(map[int]string, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\n\tdst = (map[int]string{})\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useCopy_typesDiffer(src M) {\n\t// Replace loop but not make(...) as maps.Copy(src) would return wrong type M.\n\tdst := make(map[int]string, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useCopy_typesDiffer2(src map[int]string) {\n\t// Replace loop but not make(...) as maps.Copy(src) would return wrong type map[int]string.\n\tdst := make(M, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useClone_typesDiffer3(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) as maps.Clone(src) returns map[int]string\n\t// which is assignable to M.\n\tvar dst M\n\tdst = make(M, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useClone_typesDiffer4(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) as maps.Clone(src) returns map[int]string\n\t// which is assignable to M.\n\tvar dst M\n\tdst = make(M, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\nfunc useClone_generic[Map ~map[K]V, K comparable, V any](src Map) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace loop and make(...) by maps.Clone\n\tdst := make(Map, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tmaps.Copy(dst, src)\n\tprintln(dst)\n}\n\n// -- src is iter.Seq2 --\n\nfunc useInsert_assignableToSeq2(dst map[int]string, src func(yield func(int, string) bool)) {\n\t// Replace loop by maps.Insert because src is assignable to iter.Seq2.\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Insert\"\n\tmaps.Insert(dst, src)\n}\n\nfunc useCollect(src iter.Seq2[int, string]) {\n\t// Replace loop and make(...) by maps.Collect.\n\tvar dst map[int]string\n\t// A\n\t// B\n\t// C\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Collect\"\n\tdst = maps.Collect(src)\n}\n\nfunc useInsert_typesDifferAssign(src iter.Seq2[int, string]) {\n\t// Replace loop and make(...): maps.Collect returns an unnamed map type\n\t// that is assignable to M.\n\tvar dst M\n\t// A\n\t// B\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Collect\"\n\tdst = maps.Collect(src)\n}\n\nfunc useInsert_typesDifferDeclare(src iter.Seq2[int, string]) {\n\t// Replace loop but not make(...) as maps.Collect would return an\n\t// unnamed map type that would change the type of dst.\n\tdst := make(M)\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Insert\"\n\tmaps.Insert(dst, src)\n}\n\n// -- non-matches --\n\ntype isomerOfSeq2 func(yield func(int, string) bool)\n\nfunc nopeInsertRequiresAssignableToSeq2(dst map[int]string, src isomerOfSeq2) {\n\tfor k, v := range src { // nope: src is not assignable to maps.Insert's iter.Seq2 parameter\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeSingleVarRange(dst map[int]bool, src map[int]string) {\n\tfor key := range src { // nope: must be \"for k, v\"\n\t\tdst[key] = true\n\t}\n}\n\nfunc nopeBodyNotASingleton(src map[int]string) {\n\tvar dst map[int]string\n\tfor key, value := range src {\n\t\tdst[key] = value\n\t\tprintln() // nope: other things in the loop body\n\t}\n}\n\n// Regression test for https://github.com/golang/go/issues/70815#issuecomment-2581999787.\nfunc nopeAssignmentHasIncrementOperator(src map[int]int) {\n\tdst := make(map[int]int)\n\tfor k, v := range src {\n\t\tdst[k] += v\n\t}\n}\n\nfunc nopeNotAMap(src map[int]string) {\n\tvar dst []string\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeNotAMapGeneric[E any, M ~map[int]E, S ~[]E](src M) {\n\tvar dst S\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeHasImplicitValueWidening(src map[string]int) {\n\tdst := make(map[string]any)\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\nfunc nopeHasImplicitKeyWidening(src map[string]string) {\n\tdst := make(map[any]string)\n\tfor k, v := range src {\n\t\tdst[k] = v\n\t}\n}\n\n// The expression for the map (y[v]) must not itself refer to loop variables.\n// See https://go.dev/issue/77008.\nfunc nopeMapExprUsesLoopVars(x map[int]int, y []map[int]int) {\n\tfor i, v := range x {\n\t\ty[v][i] = v\n\t}\n}\n\nfunc nopeExtraKeyValueUsage(x map[int]int, y []map[int]int) {\n\tfor i, v := range x {\n\t\ty[i][i] = v\n\t}\n\n\tgetMap := func(int) map[int]int { return nil }\n\tfor i, v := range x {\n\t\tgetMap(i)[i] = v\n\t}\n\n\tfor i, v := range x {\n\t\tgetMap(v)[i] = v\n\t}\n}\n\nfunc nope2LhsAssigment(x map[int]int, y map[int]int) {\n\tfor i, v := range x {\n\t\ty[i], _ = v, 0\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/mapsloop/mapsloop_dot.go",
    "content": "//go:build go1.23\n\npackage mapsloop\n\nimport . \"maps\"\n\nvar _ = Clone[M] // force \"maps\" import so that each diagnostic doesn't add one\n\nfunc useCopyDot(dst, src map[int]string) {\n\t// Replace loop by maps.Copy.\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n}\n\nfunc useCloneDot(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace make(...) by maps.Copy.\n\tdst := make(map[int]string, len(src))\n\tfor key, value := range src {\n\t\tdst[key] = value // want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\t}\n\tprintln(dst)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/mapsloop/mapsloop_dot.go.golden",
    "content": "//go:build go1.23\n\npackage mapsloop\n\nimport . \"maps\"\n\nvar _ = Clone[M] // force \"maps\" import so that each diagnostic doesn't add one\n\nfunc useCopyDot(dst, src map[int]string) {\n\t// Replace loop by maps.Copy.\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tCopy(dst, src)\n}\n\nfunc useCloneDot(src map[int]string) {\n\t// Clone is tempting but wrong when src may be nil; see #71844.\n\n\t// Replace make(...) by maps.Copy.\n\tdst := make(map[int]string, len(src))\n\t// want \"Replace m\\\\[k\\\\]=v loop with maps.Copy\"\n\tCopy(dst, src)\n\tprintln(dst)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/go120/minmax.go",
    "content": "package go120\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/go120/minmax_go120.go",
    "content": "//go:build !go1.21\n\npackage go120\n\nfunc min(a, b int) int { // can't be removed because we don't have at least go1.21\n\tif a <= b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/go120/minmax_go120.go.golden",
    "content": "//go:build !go1.21\n\npackage go120\n\nfunc min(a, b int) int { // can't be removed because we don't have at least go1.21\n\tif a <= b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/minmax.go",
    "content": "package minmax\n\nfunc ifmin(a, b int) {\n\tx := a // A\n\t// B\n\tif a < b { // want \"if statement can be modernized using max\"\n\t\t// C\n\t\tx = b // D\n\t\t// E\n\t}\n\tprint(x)\n}\n\nfunc ifmax(a, b int) {\n\tx := a\n\tif a > b { // want \"if statement can be modernized using min\"\n\t\tx = b\n\t}\n\tprint(x)\n}\n\nfunc ifminvariant(a, b int) {\n\tx := a\n\tif x > b { // want \"if statement can be modernized using min\"\n\t\tx = b\n\t}\n\tprint(x)\n}\n\nfunc ifmaxvariant(a, b int) {\n\tx := b\n\tif a < x { // want \"if statement can be modernized using min\"\n\t\tx = a\n\t}\n\tprint(x)\n}\n\nfunc ifelsemin(a, b int) {\n\tvar x int // A\n\t// B\n\tif a <= b { // want \"if/else statement can be modernized using min\"\n\t\t// C\n\t\tx = a // D\n\t\t// E\n\t} else {\n\t\t// F\n\t\tx = b // G\n\t\t// H\n\t}\n\tprint(x)\n}\n\nfunc ifelsemax(a, b int) {\n\t// A\n\tvar x int // B\n\t// C\n\tif a >= b { // want \"if/else statement can be modernized using max\"\n\t\t// D\n\t\tx = a // E\n\t\t// F\n\t} else {\n\t\t// G\n\t\tx = b\n\t}\n\tprint(x)\n}\n\nfunc shadowed() int {\n\thour, min := 3600, 60\n\n\tvar time int\n\tif hour < min { // silent: the built-in min function is shadowed here\n\t\ttime = hour\n\t} else {\n\t\ttime = min\n\t}\n\treturn time\n}\n\nfunc nopeIfStmtHasInitStmt() {\n\tx := 1\n\tif y := 2; y < x { // silent: IfStmt has an Init stmt\n\t\tx = y\n\t}\n\tprint(x)\n}\n\n// Regression test for a bug: fix was \"y := max(x, y)\".\nfunc oops() {\n\tx := 1\n\ty := 2\n\tif x > y { // want \"if statement can be modernized using max\"\n\t\ty = x\n\t}\n\tprint(y)\n}\n\n// Regression test for a bug: += is not a simple assignment.\nfunc nopeAssignHasIncrementOperator() {\n\tx := 1\n\ty := 0\n\ty += 2\n\tif x > y {\n\t\ty = x\n\t}\n\tprint(y)\n}\n\n// Regression test for https://github.com/golang/go/issues/71721.\nfunc nopeNotAMinimum(x, y int) int {\n\t// A value of -1 or 0 will use a default value (30).\n\tif x <= 0 {\n\t\ty = 30\n\t} else {\n\t\ty = x\n\t}\n\treturn y\n}\n\n// Regression test for https://github.com/golang/go/issues/71847#issuecomment-2673491596\nfunc nopeHasElseBlock(x int) int {\n\ty := x\n\t// Before, this was erroneously reduced to y = max(x, 0)\n\tif y < 0 {\n\t\ty = 0\n\t} else {\n\t\ty += 2\n\t}\n\treturn y\n}\n\nfunc fix72727(a, b int) {\n\to := a - 42\n\t// some important comment. DO NOT REMOVE.\n\tif o < b { // want \"if statement can be modernized using max\"\n\t\to = b\n\t}\n}\n\ntype myfloat float64\n\n// The built-in min/max differ in their treatment of NaN,\n// so reject floating-point numbers (#72829).\nfunc nopeFloat(a, b myfloat) (res myfloat) {\n\tif a < b {\n\t\tres = a\n\t} else {\n\t\tres = b\n\t}\n\treturn\n}\n\n// Regression test for golang/go#72928.\nfunc underscoreAssign(a, b int) {\n\tif a > b {\n\t\t_ = a\n\t}\n}\n\n// Regression test for https://github.com/golang/go/issues/73576.\nfunc nopeIfElseIf(a int) int {\n\tx := 0\n\tif a < 0 {\n\t\tx = 0\n\t} else if a > 100 {\n\t\tx = 100\n\t} else {\n\t\tx = a\n\t}\n\treturn x\n}\n\n// Regression test for https://go.dev/issue/77671\nfunc selectComm(ch chan int) int {\n\tselect {\n\tcase n := <-ch:\n\t\tif n > 100 {\n\t\t\tn = 100\n\t\t}\n\t\treturn n\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/minmax.go.golden",
    "content": "package minmax\n\nfunc ifmin(a, b int) {\n\tx := max(\n\t\t// A\n\t\t// B\n\t\ta,\n\t\t// want \"if statement can be modernized using max\"\n\t\t// C\n\t\t// D\n\t\t// E\n\t\tb)\n\tprint(x)\n}\n\nfunc ifmax(a, b int) {\n\tx := min(a,\n\t\t// want \"if statement can be modernized using min\"\n\t\tb)\n\tprint(x)\n}\n\nfunc ifminvariant(a, b int) {\n\tx := min(a,\n\t\t// want \"if statement can be modernized using min\"\n\t\tb)\n\tprint(x)\n}\n\nfunc ifmaxvariant(a, b int) {\n\tx := min(a,\n\t\t// want \"if statement can be modernized using min\"\n\t\tb)\n\tprint(x)\n}\n\nfunc ifelsemin(a, b int) {\n\tvar x int // A\n\t// B\n\tx = min(\n\t\t// want \"if/else statement can be modernized using min\"\n\t\t// C\n\t\t// D\n\t\t// E\n\t\ta,\n\t\t// F\n\t\t// G\n\t\t// H\n\t\tb)\n\tprint(x)\n}\n\nfunc ifelsemax(a, b int) {\n\t// A\n\tvar x int // B\n\t// C\n\tx = max(\n\t\t// want \"if/else statement can be modernized using max\"\n\t\t// D\n\t\t// E\n\t\t// F\n\t\ta,\n\t\t// G\n\t\tb)\n\tprint(x)\n}\n\nfunc shadowed() int {\n\thour, min := 3600, 60\n\n\tvar time int\n\tif hour < min { // silent: the built-in min function is shadowed here\n\t\ttime = hour\n\t} else {\n\t\ttime = min\n\t}\n\treturn time\n}\n\nfunc nopeIfStmtHasInitStmt() {\n\tx := 1\n\tif y := 2; y < x { // silent: IfStmt has an Init stmt\n\t\tx = y\n\t}\n\tprint(x)\n}\n\n// Regression test for a bug: fix was \"y := max(x, y)\".\nfunc oops() {\n\tx := 1\n\ty := max(x,\n\t\t// want \"if statement can be modernized using max\"\n\t\t2)\n\tprint(y)\n}\n\n// Regression test for a bug: += is not a simple assignment.\nfunc nopeAssignHasIncrementOperator() {\n\tx := 1\n\ty := 0\n\ty += 2\n\tif x > y {\n\t\ty = x\n\t}\n\tprint(y)\n}\n\n// Regression test for https://github.com/golang/go/issues/71721.\nfunc nopeNotAMinimum(x, y int) int {\n\t// A value of -1 or 0 will use a default value (30).\n\tif x <= 0 {\n\t\ty = 30\n\t} else {\n\t\ty = x\n\t}\n\treturn y\n}\n\n// Regression test for https://github.com/golang/go/issues/71847#issuecomment-2673491596\nfunc nopeHasElseBlock(x int) int {\n\ty := x\n\t// Before, this was erroneously reduced to y = max(x, 0)\n\tif y < 0 {\n\t\ty = 0\n\t} else {\n\t\ty += 2\n\t}\n\treturn y\n}\n\nfunc fix72727(a, b int) {\n\to := max(\n\t\t// some important comment. DO NOT REMOVE.\n\t\ta-42,\n\t\t// want \"if statement can be modernized using max\"\n\t\tb)\n}\n\ntype myfloat float64\n\n// The built-in min/max differ in their treatment of NaN,\n// so reject floating-point numbers (#72829).\nfunc nopeFloat(a, b myfloat) (res myfloat) {\n\tif a < b {\n\t\tres = a\n\t} else {\n\t\tres = b\n\t}\n\treturn\n}\n\n// Regression test for golang/go#72928.\nfunc underscoreAssign(a, b int) {\n\tif a > b {\n\t\t_ = a\n\t}\n}\n\n// Regression test for https://github.com/golang/go/issues/73576.\nfunc nopeIfElseIf(a int) int {\n\tx := 0\n\tif a < 0 {\n\t\tx = 0\n\t} else if a > 100 {\n\t\tx = 100\n\t} else {\n\t\tx = a\n\t}\n\treturn x\n}\n\n// Regression test for https://go.dev/issue/77671\nfunc selectComm(ch chan int) int {\n\tselect {\n\tcase n := <-ch:\n\t\tif n > 100 {\n\t\t\tn = 100\n\t\t}\n\t\treturn n\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/nonstrict/nonstrict.go",
    "content": "package nonstrict\n\n// min with <= operator - should be detected and removed\nfunc min(a, b int) int { // want \"user-defined min function is equivalent to built-in min and can be removed\"\n\tif a <= b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// max with >= operator - should be detected and removed\nfunc max(a, b int) int { // want \"user-defined max function is equivalent to built-in max and can be removed\"\n\tif a >= b {\n\t\treturn a\n\t}\n\treturn b\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/nonstrict/nonstrict.go.golden",
    "content": "package nonstrict"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/userdefined/userdefined.go",
    "content": "package userdefined\n\n// User-defined min with float parameters - should NOT be removed due to NaN handling\nfunc minFloat(a, b float64) float64 {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined max with float parameters - should NOT be removed due to NaN handling\nfunc maxFloat(a, b float64) float64 {\n\tif a > b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined function with different name - should NOT be removed\nfunc minimum(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined min with different logic - should NOT be removed\nfunc minDifferent(a, b int) int {\n\treturn a + b // Completely different logic\n}\n\n// Method on a type - should NOT be removed\ntype MyType struct{}\n\nfunc (m MyType) min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// Function with wrong signature - should NOT be removed\nfunc minWrongSig(a int) int {\n\treturn a\n}\n\n// Function with complex body that doesn't match pattern - should NOT be removed\nfunc minComplex(a, b int) int {\n\tprintln(\"choosing min\")\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// min returns the smaller of two values.\nfunc min(a, b int) int { // want \"user-defined min function is equivalent to built-in min and can be removed\"\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// max returns the larger of two values.\nfunc max(a, b int) int { // want \"user-defined max function is equivalent to built-in max and can be removed\"\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/userdefined/userdefined.go.golden",
    "content": "package userdefined\n\n// User-defined min with float parameters - should NOT be removed due to NaN handling\nfunc minFloat(a, b float64) float64 {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined max with float parameters - should NOT be removed due to NaN handling\nfunc maxFloat(a, b float64) float64 {\n\tif a > b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined function with different name - should NOT be removed\nfunc minimum(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// User-defined min with different logic - should NOT be removed\nfunc minDifferent(a, b int) int {\n\treturn a + b // Completely different logic\n}\n\n// Method on a type - should NOT be removed\ntype MyType struct{}\n\nfunc (m MyType) min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// Function with wrong signature - should NOT be removed\nfunc minWrongSig(a int) int {\n\treturn a\n}\n\n// Function with complex body that doesn't match pattern - should NOT be removed\nfunc minComplex(a, b int) int {\n\tprintln(\"choosing min\")\n\tif a < b {\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/wrongoperators/wrongoperators.go",
    "content": "package wrongoperators\n\n// min function with max logic - should NOT be detected (wrong logic)\nfunc min(a, b int) int {\n\tif a >= b { // This is max logic, not min logic\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// max function with min logic - should NOT be detected (wrong logic)\nfunc max(a, b int) int {\n\tif a <= b { // This is min logic, not max logic\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/wrongoperators/wrongoperators.go.golden",
    "content": "package operators\n\n// min function with max logic - should NOT be detected (wrong logic)\nfunc min(a, b int) int {\n\tif a >= b {  // This is max logic, not min logic\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}\n\n// max function with min logic - should NOT be detected (wrong logic)\nfunc max(a, b int) int {\n\tif a <= b {  // This is min logic, not max logic\n\t\treturn a\n\t} else {\n\t\treturn b\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/wrongreturn/wrongreturn.go",
    "content": "package wrongreturn\n\n// This should NOT be detected as min - it returns the wrong values\nfunc min(x, y int) int {\n\tif x <= y {\n\t\treturn y\n\t} else {\n\t\treturn x\n\t}\n}\n\n// This should NOT be detected as max - it returns the wrong values\nfunc max(x, y int) int {\n\tif x > y {\n\t\treturn y\n\t} else {\n\t\treturn x\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/minmax/wrongreturn/wrongreturn.go.golden",
    "content": "package wrongreturn\n\n// This should NOT be detected as min - it returns the wrong values\nfunc min(x, y int) int {\n\tif x <= y {\n\t\treturn y\n\t} else {\n\t\treturn x\n\t}\n}\n\n// This should NOT be detected as max - it returns the wrong values  \nfunc max(x, y int) int {\n\tif x > y {\n\t\treturn y\n\t} else {\n\t\treturn x\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/newexpr/newexpr.go",
    "content": "//go:build go1.26\n\npackage newexpr\n\n// intVar returns a new var whose value is i.\nfunc intVar(i int) *int { return &i } // want `intVar can be an inlinable wrapper around new\\(expr\\)` intVar:\"newlike\"\n\nfunc int64Var(i int64) *int64 { return &i } // want `int64Var can be an inlinable wrapper around new\\(expr\\)` int64Var:\"newlike\"\n\nfunc stringVar(s string) *string { return &s } // want `stringVar can be an inlinable wrapper around new\\(expr\\)` stringVar:\"newlike\"\n\nfunc varOf[T any](x T) *T { return &x } // want `varOf can be an inlinable wrapper around new\\(expr\\)` varOf:\"newlike\"\n\n//go:fix inline\nfunc alreadyAnnotated[T any](x T) *T { return &x } // want `alreadyAnnotated can be an inlinable wrapper around new\\(expr\\)` alreadyAnnotated:\"newlike\"\n\nvar (\n\ts struct {\n\t\tint\n\t\tstring\n\t}\n\t_ = intVar(123)       // want `call of intVar\\(x\\) can be simplified to new\\(x\\)`\n\t_ = int64Var(123)     // nope: implicit conversion from untyped int to int64\n\t_ = stringVar(\"abc\")  // want `call of stringVar\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf(s)          // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf(123)        // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf(int64(123)) // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf[int](123)   // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf[int64](123) // nope: implicit conversion from untyped int to int64\n\t_ = varOf( // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t\tvarOf(123)) // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = alreadyAnnotated[int](123) // want `call of alreadyAnnotated\\(x\\) can be simplified to new\\(x\\)`\n)\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/newexpr/newexpr.go.golden",
    "content": "//go:build go1.26\n\npackage newexpr\n\n// intVar returns a new var whose value is i.\n//\n//go:fix inline\nfunc intVar(i int) *int { return new(i) } // want `intVar can be an inlinable wrapper around new\\(expr\\)` intVar:\"newlike\"\n\n//go:fix inline\nfunc int64Var(i int64) *int64 { return new(i) } // want `int64Var can be an inlinable wrapper around new\\(expr\\)` int64Var:\"newlike\"\n\n//go:fix inline\nfunc stringVar(s string) *string { return new(s) } // want `stringVar can be an inlinable wrapper around new\\(expr\\)` stringVar:\"newlike\"\n\n//go:fix inline\nfunc varOf[T any](x T) *T { return new(x) } // want `varOf can be an inlinable wrapper around new\\(expr\\)` varOf:\"newlike\"\n\n//go:fix inline\nfunc alreadyAnnotated[T any](x T) *T { return new(x) } // want `alreadyAnnotated can be an inlinable wrapper around new\\(expr\\)` alreadyAnnotated:\"newlike\"\n\nvar (\n\ts struct {\n\t\tint\n\t\tstring\n\t}\n\t_ = new(123)          // want `call of intVar\\(x\\) can be simplified to new\\(x\\)`\n\t_ = int64Var(123)     // nope: implicit conversion from untyped int to int64\n\t_ = new(\"abc\")        // want `call of stringVar\\(x\\) can be simplified to new\\(x\\)`\n\t_ = new(s)            // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = new(123)          // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = new(int64(123))   // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = new(123)          // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = varOf[int64](123) // nope: implicit conversion from untyped int to int64\n\t_ = new(              // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t\tnew(123)) // want `call of varOf\\(x\\) can be simplified to new\\(x\\)`\n\t_ = new(123) // want `call of alreadyAnnotated\\(x\\) can be simplified to new\\(x\\)`\n)"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/newexpr/newexpr_go125.go",
    "content": "package newexpr\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/omitzero/kube/kube.go",
    "content": "package kube\n\ntype Foo struct {\n\tEmptyStruct struct{} `json:\",omitempty\"` // nope: the comment below mentions the k-word\n}\n\n// +kubebuilder:validation:Optional\ntype Other struct {\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/omitzero/omitzero.go",
    "content": "package omitzero\n\ntype Foo struct {\n\tEmptyStruct struct{} `json:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Bar struct {\n\tNonEmptyStruct struct{ a int } `json:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype C struct {\n\tD string `json:\",omitempty\"`\n}\n\ntype R struct {\n\tM string `json:\",omitempty\"`\n}\n\ntype A struct {\n\tC C `json:\"test,omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n\tR R `json:\"test\"`\n}\n\ntype X struct {\n\tNonEmptyStruct struct{ a int } `json:\",omitempty\" yaml:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Y struct {\n\tNonEmptyStruct struct{ a int } `yaml:\",omitempty\" json:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/omitzero/omitzero.go.golden",
    "content": "-- Replace omitempty with omitzero (behavior change) --\npackage omitzero\n\ntype Foo struct {\n\tEmptyStruct struct{} `json:\",omitzero\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Bar struct {\n\tNonEmptyStruct struct{ a int } `json:\",omitzero\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype C struct {\n\tD string `json:\",omitempty\"`\n}\n\ntype R struct {\n\tM string `json:\",omitempty\"`\n}\n\ntype A struct {\n\tC C `json:\"test,omitzero\"` // want \"Omitempty has no effect on nested struct fields\"\n\tR R `json:\"test\"`\n}\n\ntype X struct {\n\tNonEmptyStruct struct{ a int } `json:\",omitzero\" yaml:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Y struct {\n\tNonEmptyStruct struct{ a int } `yaml:\",omitempty\" json:\",omitzero\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\n-- Remove redundant omitempty tag --\npackage omitzero\n\ntype Foo struct {\n\tEmptyStruct struct{} // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Bar struct {\n\tNonEmptyStruct struct{ a int } // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype C struct {\n\tD string `json:\",omitempty\"`\n}\n\ntype R struct {\n\tM string `json:\",omitempty\"`\n}\n\ntype A struct {\n\tC C `json:\"test\"` // want \"Omitempty has no effect on nested struct fields\"\n\tR R `json:\"test\"`\n}\n\ntype X struct {\n\tNonEmptyStruct struct{ a int } `yaml:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n\ntype Y struct {\n\tNonEmptyStruct struct{ a int } `yaml:\",omitempty\"` // want \"Omitempty has no effect on nested struct fields\"\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/plusbuild/plusbuild.go",
    "content": "// want +3 `.build line is no longer needed`\n\n//go:build linux && amd64\n// +build linux,amd64\n\npackage plusbuild\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/plusbuild/plusbuild.go.golden",
    "content": "// want +3 `.build line is no longer needed`\n\n//go:build linux && amd64\n\npackage plusbuild\n\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/plusbuild/plusbuild2.go",
    "content": "// This file ensures that the package is non-empty\n// in every build configuration.\n\npackage plusbuild\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/rangeint/a/a.go",
    "content": "package a\n\ntype ID int\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/rangeint/rangeint.go",
    "content": "package rangeint\n\nimport (\n\t\"os\"\n\tos1 \"os\"\n\t\"rangeint/a\"\n)\n\nfunc _(i int, s struct{ i int }, slice []int) {\n\tfor i := 0; i < 10; i++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\tfor j := int(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int8(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int16(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int32(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int64(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := uint8(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := uint16(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := uint32(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := uint64(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int8(0.); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := int8(.0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := os.FileMode(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\n\t{\n\t\tvar i int\n\t\tfor i = 0; i < 10; i++ { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t\t// NB: no uses of i after loop.\n\t}\n\tfor i := 0; i < 10; i++ { // want \"for loop can be modernized using range over int\"\n\t\t// i unused within loop\n\t}\n\tfor i := 0; i < len(slice); i++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(slice[i])\n\t}\n\tfor i := 0; i < len(\"\"); i++ { // want \"for loop can be modernized using range over int\"\n\t\t// NB: not simplified to range \"\"\n\t}\n\n\t// nope\n\tfor j := .0; j < 10; j++ { // nope: j is a float type\n\t\tprintln(j)\n\t}\n\tfor j := float64(0); j < 10; j++ { // nope: j is a float type\n\t\tprintln(j)\n\t}\n\tfor i := 0; i < 10; { // nope: missing increment\n\t}\n\tfor i := 0; i < 10; i-- { // nope: negative increment\n\t}\n\tfor i := 0; ; i++ { // nope: missing comparison\n\t}\n\tfor i := 0; i <= 10; i++ { // nope: wrong comparison\n\t}\n\tfor ; i < 10; i++ { // nope: missing init\n\t}\n\tfor s.i = 0; s.i < 10; s.i++ { // nope: not an ident\n\t}\n\tfor i := 0; i < 10; i++ { // nope: takes address of i\n\t\tprintln(&i)\n\t}\n\tfor i := 0; i < 10; i++ { // nope: increments i\n\t\ti++\n\t}\n\tfor i := 0; i < 10; i++ { // nope: assigns i\n\t\ti = 8\n\t}\n\n\tfor i := 0; i < 10; i += 1 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; s.i += 1 { // nope: modifies another variable\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; i -= 1 { // nope: decrements i\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; i += 2 { // nope: range only increments by 1\n\t\tprintln(i)\n\t}\n\n\t// The limit expression must be loop invariant;\n\t// see https://github.com/golang/go/issues/72917\n\tfor i := 0; i < f(); i++ { // nope\n\t}\n\t{\n\t\tvar s struct{ limit int }\n\t\tfor i := 0; i < s.limit; i++ { // nope: limit is not a const or local var\n\t\t}\n\t}\n\t{\n\t\tconst k = 10\n\t\tfor i := 0; i < k; i++ { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}\n\t{\n\t\tvar limit = 10\n\t\tfor i := 0; i < limit; i++ { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}\n\t{\n\t\tvar limit = 10\n\t\tfor i := 0; i < limit; i++ { // nope: limit is address-taken\n\t\t}\n\t\tprint(&limit)\n\t}\n\t{\n\t\tlimit := 10\n\t\tlimit++\n\t\tfor i := 0; i < limit; i++ { // nope: limit is assigned other than by its declaration\n\t\t}\n\t}\n\tfor i := 0; i < Global; i++ { // nope: limit is an exported global var; may be updated elsewhere\n\t}\n\tfor i := 0; i < len(table); i++ { // want \"for loop can be modernized using range over int\"\n\t}\n\t{\n\t\ts := []string{}\n\t\tfor i := 0; i < len(s); i++ { // nope: limit is not loop-invariant\n\t\t\ts = s[1:]\n\t\t}\n\t}\n\tfor i := 0; i < len(slice); i++ { // nope: i is incremented within loop\n\t\ti += 1\n\t}\n\tfor Global = 0; Global < 10; Global++ { // nope: loop index is a global variable.\n\t}\n}\n\nvar Global int\n\nvar table = []string{\"hello\", \"world\"}\n\nfunc f() int { return 0 }\n\n// Repro for part of #71847: (\"for range n is invalid if the loop body contains i++\"):\nfunc _(s string) {\n\tvar i int                    // (this is necessary)\n\tfor i = 0; i < len(s); i++ { // nope: loop body increments i\n\t\tif true {\n\t\t\ti++ // nope\n\t\t}\n\t}\n}\n\n// Repro for #71952: for and range loops have different final values\n// on i (n and n-1, respectively) so we can't offer the fix if i is\n// used after the loop.\nfunc nopePostconditionDiffers() {\n\ti := 0\n\tfor i = 0; i < 5; i++ {\n\t\tprintln(i)\n\t}\n\tprintln(i) // must print 5, not 4\n}\n\n// Non-integer untyped constants need to be explicitly converted to int.\nfunc issue71847d() {\n\tconst limit = 1e3            // float\n\tfor i := 0; i < limit; i++ { // want \"for loop can be modernized using range over int\"\n\t}\n\tfor i := int(0); i < limit; i++ { // want \"for loop can be modernized using range over int\"\n\t}\n\tfor i := uint(0); i < limit; i++ { // want \"for loop can be modernized using range over int\"\n\t}\n\n\tconst limit2 = 1 + 0i         // complex\n\tfor i := 0; i < limit2; i++ { // want \"for loop can be modernized using range over int\"\n\t}\n}\n\nfunc issue72726() {\n\tvar n, kd int\n\tfor i := 0; i < n; i++ { // want \"for loop can be modernized using range over int\"\n\t\t// nope: j will be invisible once it's refactored to 'for j := range min(n-j, kd+1)'\n\t\tfor j := 0; j < min(n-j, kd+1); j++ { // nope\n\t\t\t_, _ = i, j\n\t\t}\n\t}\n\n\tfor i := 0; i < i; i++ { // nope\n\t}\n\n\tvar i int\n\tfor i = 0; i < i/2; i++ { // nope\n\t}\n\n\tvar arr []int\n\tfor i = 0; i < arr[i]; i++ { // nope\n\t}\n}\n\nfunc todo() {\n\tfor j := os1.FileMode(0); j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n}\n\ntype T uint\ntype TAlias = uint\n\nfunc Fn(a int) T {\n\treturn T(a)\n}\n\nfunc issue73037() {\n\tvar q T\n\tfor a := T(0); a < q; a++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(a)\n\t}\n\tfor a := Fn(0); a < q; a++ {\n\t\tprintln(a)\n\t}\n\tvar qa TAlias\n\tfor a := TAlias(0); a < qa; a++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(a)\n\t}\n\tfor a := T(0); a < 10; a++ { // want \"for loop can be modernized using range over int\"\n\t\tfor b := T(0); b < 10; b++ { // want \"for loop can be modernized using range over int\"\n\t\t\tprintln(a, b)\n\t\t}\n\t}\n}\n\nfunc issue75289() {\n\t// A use of i within a defer may be textually before the loop but runs\n\t// after, so it should cause the loop to be rejected as a candidate\n\t// to avoid it observing a different final value of i.\n\t{\n\t\tvar i int\n\t\tdefer func() { println(i) }()\n\t\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop (via defer)\n\t\t}\n\t}\n\n\t// A use of i within a defer within the loop is also a dealbreaker.\n\t{\n\t\tvar i int\n\t\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop (via defer)\n\t\t\tdefer func() { println(i) }()\n\t\t}\n\t}\n\n\t// This (outer) defer is irrelevant.\n\tdefer func() {\n\t\tvar i int\n\t\tfor i = 0; i < 10; i++ { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}()\n}\n\n// See go.dev/issue/76880.\nfunc _() (i int) {\n\tfor i = 0; i < 3; i++ { // nope: i is implicitly accessed after the loop\n\t}\n\treturn\n}\n\nfunc issue74687() {\n\tfor i := a.ID(0); i < 10; i++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\n\tfor i := a.ID(0); i < a.ID(13); i++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n}\n\nfunc issue76470() {\n\tvar i, j int\nUsedAfter:\n\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop\n\t\tbreak UsedAfter\n\t}\n\tif i == 9 {\n\t\tpanic(\"Modernizer changes behavior\")\n\t}\n\nNotUsedAfter:\n\tfor j = 0; j < 10; j++ { // want \"for loop can be modernized using range over int\"\n\t\tbreak NotUsedAfter\n\t}\n}\n\n// Don't allow rewriting of an outer loop when its inner loop modifies the outer\n// loop variable.\nfunc issue77034() {\n\tfor i := 0; i < 5; i++ {\n\t\tfor i = range 10 {\n\t\t}\n\t}\n}\n\nfunc issue77034_define_inner() {\n\tfor i := 0; i < 5; i++ { // want \"for loop can be modernized using range over int\"\n\t\tfor i := range 10 { // inner \"i\" doesn't modify outer \"i\"\n\t\t\tprintln(i)\n\t\t}\n\t}\n}\n\ntype C int32\n\n// Don't add an unneeded type cast if the limit's default type is an integer, and\n// the init value is assigned outside the loop, because the compiler can infer the type.\nfunc issue77891() {\n\tconst limit_float = 1e6\n\tvar i int\n\tfor i = 0; i < limit_float; i++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\n\tvar j int64\n\tfor j = 0; j < 20; j++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\n\tvar c C\n\tfor c = 0; c < 10; c++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(c)\n\t}\n\n\tvar ptr uintptr\n\tfor ptr = 0; ptr < 100; ptr++ { // want \"for loop can be modernized using range over int\"\n\t\tprintln(ptr)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/rangeint/rangeint.go.golden",
    "content": "package rangeint\n\nimport (\n\tos1 \"os\"\n\t\"rangeint/a\"\n)\n\nfunc _(i int, s struct{ i int }, slice []int) {\n\tfor i := range 10 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\tfor j := range 10 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int8(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int16(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int32(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int64(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range uint8(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range uint16(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range uint32(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range uint64(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int8(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range int8(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\tfor j := range os1.FileMode(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\n\t{\n\t\tvar i int\n\t\tfor i = range 10 { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t\t// NB: no uses of i after loop.\n\t}\n\tfor range 10 { // want \"for loop can be modernized using range over int\"\n\t\t// i unused within loop\n\t}\n\tfor i := range slice { // want \"for loop can be modernized using range over int\"\n\t\tprintln(slice[i])\n\t}\n\tfor range len(\"\") { // want \"for loop can be modernized using range over int\"\n\t\t// NB: not simplified to range \"\"\n\t}\n\n\t// nope\n\tfor j := .0; j < 10; j++ { // nope: j is a float type\n\t\tprintln(j)\n\t}\n\tfor j := float64(0); j < 10; j++ { // nope: j is a float type\n\t\tprintln(j)\n\t}\n\tfor i := 0; i < 10; { // nope: missing increment\n\t}\n\tfor i := 0; i < 10; i-- { // nope: negative increment\n\t}\n\tfor i := 0; ; i++ { // nope: missing comparison\n\t}\n\tfor i := 0; i <= 10; i++ { // nope: wrong comparison\n\t}\n\tfor ; i < 10; i++ { // nope: missing init\n\t}\n\tfor s.i = 0; s.i < 10; s.i++ { // nope: not an ident\n\t}\n\tfor i := 0; i < 10; i++  { // nope: takes address of i\n\t\tprintln(&i)\n\t}\n\tfor i := 0; i < 10; i++  { // nope: increments i\n\t\ti++\n\t}\n\tfor i := 0; i < 10; i++  { // nope: assigns i\n\t\ti = 8\n\t}\n\n\tfor i := range 10 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; s.i += 1 { // nope: modifies another variable\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; i -= 1 { // nope: decrements i\n\t\tprintln(i)\n\t}\n\tfor i := 0; i < 10; i += 2 { // nope: range only increments by 1\n\t\tprintln(i)\n\t}\n\n\t// The limit expression must be loop invariant;\n\t// see https://github.com/golang/go/issues/72917\n\tfor i := 0; i < f(); i++ { // nope\n\t}\n\t{\n\t\tvar s struct{ limit int }\n\t\tfor i := 0; i < s.limit; i++ { // nope: limit is not a const or local var\n\t\t}\n\t}\n\t{\n\t\tconst k = 10\n\t\tfor range k { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}\n\t{\n\t\tvar limit = 10\n\t\tfor range limit { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}\n\t{\n\t\tvar limit = 10\n\t\tfor i := 0; i < limit; i++ { // nope: limit is address-taken\n\t\t}\n\t\tprint(&limit)\n\t}\n\t{\n\t\tlimit := 10\n\t\tlimit++\n\t\tfor i := 0; i < limit; i++ { // nope: limit is assigned other than by its declaration\n\t\t}\n\t}\n\tfor i := 0; i < Global; i++ { // nope: limit is an exported global var; may be updated elsewhere\n\t}\n\tfor range table { // want \"for loop can be modernized using range over int\"\n\t}\n\t{\n\t\ts := []string{}\n\t\tfor i := 0; i < len(s); i++ { // nope: limit is not loop-invariant\n\t\t\ts = s[1:]\n\t\t}\n\t}\n\tfor i := 0; i < len(slice); i++ { // nope: i is incremented within loop\n\t\ti += 1\n\t}\n\tfor Global = 0; Global < 10; Global++ { // nope: loop index is a global variable.\n\t}\n}\n\nvar Global int\n\nvar table = []string{\"hello\", \"world\"}\n\nfunc f() int { return 0 }\n\n// Repro for part of #71847: (\"for range n is invalid if the loop body contains i++\"):\nfunc _(s string) {\n\tvar i int                    // (this is necessary)\n\tfor i = 0; i < len(s); i++ { // nope: loop body increments i\n\t\tif true {\n\t\t\ti++ // nope\n\t\t}\n\t}\n}\n\n// Repro for #71952: for and range loops have different final values\n// on i (n and n-1, respectively) so we can't offer the fix if i is\n// used after the loop.\nfunc nopePostconditionDiffers() {\n\ti := 0\n\tfor i = 0; i < 5; i++ {\n\t\tprintln(i)\n\t}\n\tprintln(i) // must print 5, not 4\n}\n\n// Non-integer untyped constants need to be explicitly converted to int.\nfunc issue71847d() {\n\tconst limit = 1e3            // float\n\tfor range int(limit) { // want \"for loop can be modernized using range over int\"\n\t}\n\tfor range int(limit) { // want \"for loop can be modernized using range over int\"\n\t}\n\tfor range uint(limit) { // want \"for loop can be modernized using range over int\"\n\t}\n\n\tconst limit2 = 1 + 0i         // complex\n\tfor range int(limit2) { // want \"for loop can be modernized using range over int\"\n\t}\n}\n\nfunc issue72726() {\n\tvar n, kd int\n\tfor i := range n { // want \"for loop can be modernized using range over int\"\n\t\t// nope: j will be invisible once it's refactored to 'for j := range min(n-j, kd+1)'\n\t\tfor j := 0; j < min(n-j, kd+1); j++ { // nope\n\t\t\t_, _ = i, j\n\t\t}\n\t}\n\n\tfor i := 0; i < i; i++ { // nope\n\t}\n\n\tvar i int\n\tfor i = 0; i < i/2; i++ { // nope\n\t}\n\n\tvar arr []int\n\tfor i = 0; i < arr[i]; i++ { // nope\n\t}\n}\n\nfunc todo() {\n\tfor j := range os1.FileMode(10)  { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n}\n\ntype T uint\ntype TAlias = uint\n\nfunc Fn(a int) T {\n\treturn T(a)\n}\n\nfunc issue73037() {\n\tvar q T\n\tfor a := range q { // want \"for loop can be modernized using range over int\"\n\t\tprintln(a)\n\t}\n\tfor a := Fn(0); a < q; a++ {\n\t\tprintln(a)\n\t}\n\tvar qa TAlias\n\tfor a := range qa { // want \"for loop can be modernized using range over int\"\n\t\tprintln(a)\n\t}\n\tfor a := range T(10) { // want \"for loop can be modernized using range over int\"\n\t\tfor b := range T(10) { // want \"for loop can be modernized using range over int\"\n\t\t\tprintln(a, b)\n\t\t}\n\t}\n}\n\nfunc issue75289() {\n\t// A use of i within a defer may be textually before the loop but runs\n\t// after, so it should cause the loop to be rejected as a candidate\n\t// to avoid it observing a different final value of i.\n\t{\n\t\tvar i int\n\t\tdefer func() { println(i) }()\n\t\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop (via defer)\n\t\t}\n\t}\n\n\t// A use of i within a defer within the loop is also a dealbreaker.\n\t{\n\t\tvar i int\n\t\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop (via defer)\n\t\t\tdefer func() { println(i) }()\n\t\t}\n\t}\n\n\t// This (outer) defer is irrelevant.\n\tdefer func() {\n\t\tvar i int\n\t\tfor i = range 10 { // want \"for loop can be modernized using range over int\"\n\t\t}\n\t}()\n}\n\n// See go.dev/issue/76880.\nfunc _() (i int) {\n\tfor i = 0; i < 3; i++ { // nope: i is implicitly accessed after the loop\n\t}\n\treturn\n}\n\nfunc issue74687() {\n\tfor i := range a.ID(10) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\n\tfor i := range a.ID(13) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n}\n\nfunc issue76470() {\n\tvar i, j int\nUsedAfter:\n\tfor i = 0; i < 10; i++ { // nope: i is accessed after the loop\n\t\tbreak UsedAfter\n\t}\n\tif i == 9 {\n\t\tpanic(\"Modernizer changes behavior\")\n\t}\n\nNotUsedAfter:\n\tfor j = range(10) { // want \"for loop can be modernized using range over int\"\n\t\tbreak NotUsedAfter\n\t}\n}\n\n// Don't allow rewriting of an outer loop when its inner loop modifies the outer\n// loop variable.\nfunc issue77034() {\n\tfor i := 0; i < 5; i++ {\n\t\tfor i = range 10 {\n\t\t}\n\t}\n}\n\nfunc issue77034_define_inner() {\n\tfor range 5 { // want \"for loop can be modernized using range over int\"\n\t\tfor i := range 10 { // inner \"i\" doesn't modify outer \"i\"\n\t\t\tprintln(i)\n\t\t}\n\t}\n}\n\ntype C int32\n\n// Don't add an unneeded type cast if the limit's default type is an integer, and\n// the init value is assigned outside the loop, because the compiler can infer the type.\nfunc issue77891() {\n\tconst limit_float = 1e6\n\tvar i int\n\tfor i = range int(limit_float) { // want \"for loop can be modernized using range over int\"\n\t\tprintln(i)\n\t}\n\n\tvar j int64\n\tfor j = range 20 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(j)\n\t}\n\n\tvar c C\n\tfor c = range 10 { \t\t// want \"for loop can be modernized using range over int\"\n\t\tprintln(c)\n\t}\n\n\tvar ptr uintptr\n\tfor ptr = range 100 { // want \"for loop can be modernized using range over int\"\n\t\tprintln(ptr)\n\t}\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/reflecttypefor/reflecttypefor.go",
    "content": "package reflecttypefor\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"time\"\n)\n\ntype A string\n\ntype B[T any] int\n\nvar (\n\tx any\n\ta A\n\tb B[int]\n\t_ = reflect.TypeOf(x)                          // nope (dynamic)\n\t_ = reflect.TypeOf(0)                          // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(nil)                        // nope (likely a mistake)\n\t_ = reflect.TypeOf(uint(0))                    // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(error(nil))                 // nope (likely a mistake)\n\t_ = reflect.TypeOf((*error)(nil))              // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(io.Reader(nil))             // nope (likely a mistake)\n\t_ = reflect.TypeOf((io.Reader)(nil))           // nope (likely a mistake)\n\t_ = reflect.TypeOf((*io.Reader)(nil))          // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(*new(time.Time))            // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(time.Time{})                // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(time.Duration(0))           // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(&a)                         // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(&b)                         // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([]io.Reader(nil)).Elem()    // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([]*io.Reader(nil)).Elem()   // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf((*io.Reader)(nil)).Elem()   // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([0]io.Reader{}).Elem()      // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([1]io.Reader{nil}).Elem()   // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([...]io.Reader{}).Elem()    // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf([...]io.Reader{nil}).Elem() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(chan int(nil)).Elem()       // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(map[string]int(nil)).Elem() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n)\n\n// Eliminate local var if we deleted its last use.\nfunc _() {\n\t// Test for shadowed nil\n\tnil := \"nil\"\n\t_ = reflect.TypeOf(nil) // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = nil                 // shadowed nil has multiple uses\n\n\tvar zero string\n\t_ = reflect.TypeOf(zero) // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\n\tvar z2 string\n\t_ = reflect.TypeOf(z2) // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = z2                 // z2 has multiple uses\n}\n\ntype T struct {\n\tf struct {\n\t\tA bool\n\t\tB int\n\t\tC string\n\t}\n}\n\ntype S struct {\n\tf [2]struct {\n\t\tA bool\n\t\tB int\n\t\tC string\n\t}\n}\n\ntype R []struct {\n\tA int\n}\n\ntype M[T struct{ F int }] int\n\ntype P struct {\n\tf interface {\n\t}\n\tg func() // fine length\n\n\tlong func(a int, b int, c int) (bool, string, int) // too long\n\n\ts func(a struct{})\n\n\tq func() struct{}\n}\n\nfunc f(t *T, r R, m *M[struct{ F int }], s *S, p *P) {\n\t// No suggested fix for all of the following because the type is complicated -- e.g. has an unnamed struct,\n\t// interface, or signature -- so the fix would be more verbose than the original expression.\n\t// Also because structs and interfaces often acquire new fields and methods, and the type string\n\t// produced by this modernizer won't get updated automatically, potentially causing a bug.\n\t_ = reflect.TypeOf(&t.f)\n\t_ = reflect.TypeOf(r[0])\n\t_ = reflect.TypeOf(m)\n\t_ = reflect.TypeOf(&s.f)\n\t_ = reflect.TypeOf(&p.f)\n\t_ = reflect.TypeOf(&p.g)\n\t_ = reflect.TypeOf(&p.long)\n\t_ = reflect.TypeOf(&p.q)\n\t_ = reflect.TypeOf(&p.s)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/reflecttypefor/reflecttypefor.go.golden",
    "content": "package reflecttypefor\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"time\"\n)\n\ntype A string\n\ntype B[T any] int\n\nvar (\n\tx any\n\ta A\n\tb B[int]\n\t_ = reflect.TypeOf(x)                // nope (dynamic)\n\t_ = reflect.TypeFor[int]()           // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(nil)              // nope (likely a mistake)\n\t_ = reflect.TypeFor[uint]()          // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(error(nil))       // nope (likely a mistake)\n\t_ = reflect.TypeFor[*error]()        // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeOf(io.Reader(nil))   // nope (likely a mistake)\n\t_ = reflect.TypeOf((io.Reader)(nil)) // nope (likely a mistake)\n\t_ = reflect.TypeFor[*io.Reader]()    // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[time.Time]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[time.Time]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[time.Duration]() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[*A]()            // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[*B[int]]()       // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[*io.Reader]()    // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[io.Reader]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[int]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = reflect.TypeFor[int]()     // want \"reflect.TypeOf call can be simplified using TypeFor\"\n)\n\n// Eliminate local var if we deleted its last use.\nfunc _() {\n\t// Test for shadowed nil\n\tnil := \"nil\"\n\t_ = reflect.TypeFor[string]() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = nil                 // shadowed nil has multiple uses\n \t\n\t_ = reflect.TypeFor[string]() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\n\tvar z2 string\n\t_ = reflect.TypeFor[string]() // want \"reflect.TypeOf call can be simplified using TypeFor\"\n\t_ = z2                 // z2 has multiple uses\n}\n\ntype T struct {\n\tf struct {\n\t\tA bool\n\t\tB int\n\t\tC string\n\t}\n}\n\ntype S struct {\n\tf [2]struct {\n\t\tA bool\n\t\tB int\n\t\tC string\n\t}\n}\n\ntype R []struct {\n\tA int\n}\n\ntype M[T struct{ F int }] int\n\ntype P struct {\n\tf interface {\n\t}\n\tg func() // fine length\n\n\tlong func(a int, b int, c int) (bool, string, int) // too long\n\n\ts func(a struct{})\n\n\tq func() struct{}\n}\n\nfunc f(t *T, r R, m *M[struct{ F int }], s *S, p *P) {\n\t// No suggested fix for all of the following because the type is complicated -- e.g. has an unnamed struct,\n\t// interface, or signature -- so the fix would be more verbose than the original expression.\n\t// Also because structs and interfaces often acquire new fields and methods, and the type string\n\t// produced by this modernizer won't get updated automatically, potentially causing a bug.\n\t_ = reflect.TypeOf(&t.f)\n\t_ = reflect.TypeOf(r[0])\n\t_ = reflect.TypeOf(m)\n\t_ = reflect.TypeOf(&s.f)\n\t_ = reflect.TypeOf(&p.f)\n\t_ = reflect.TypeOf(&p.g)\n\t_ = reflect.TypeOf(&p.long)\n\t_ = reflect.TypeOf(&p.q)\n\t_ = reflect.TypeOf(&p.s)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicescontains/slicescontains.go",
    "content": "package slicescontains\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nvar _ = slices.Contains[[]int] // force import of \"slices\" to avoid duplicate import edits\n\nfunc nopeNoBreak(slice []int, needle int) {\n\tfor i := range slice {\n\t\tif slice[i] == needle {\n\t\t\tprintln(\"found\")\n\t\t}\n\t}\n}\n\nfunc rangeIndex(slice []int, needle int) {\n\tfor i := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif slice[i] == needle {\n\t\t\tprintln(\"found\")\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc rangeValue(slice []int, needle int) {\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif elem == needle {\n\t\t\tprintln(\"found\")\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc returns(slice []int, needle int) {\n\tfor i := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif slice[i] == needle {\n\t\t\tprintln(\"found\")\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc assignTrueBreak(slice []int, needle int) {\n\tfound := false\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif elem == needle {\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\tprint(found)\n}\n\nfunc assignFalseBreak(slice []int, needle int) {\n\tfound := true\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif elem == needle {\n\t\t\tfound = false\n\t\t\tbreak\n\t\t}\n\t}\n\tprint(found)\n}\n\nfunc assignFalseBreakInSelectSwitch(slice []int, needle int) {\n\t// Exercise RangeStmt in CommClause, CaseClause.\n\tselect {\n\tdefault:\n\t\tfound := false\n\t\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\t\tif elem == needle {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tprint(found)\n\t}\n\tswitch {\n\tdefault:\n\t\tfound := false\n\t\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\t\tif elem == needle {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tprint(found)\n\t}\n}\n\nfunc returnTrue(slice []int, needle int) bool {\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif elem == needle {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc returnFalse(slice []int, needle int) bool {\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.Contains\"\n\t\tif elem == needle {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc containsFunc(slice []int, needle int) bool {\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.ContainsFunc\"\n\t\tif predicate(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc nopeLoopBodyHasFreeContinuation(slice []int, needle int) bool {\n\tfor _, elem := range slice {\n\t\tif predicate(elem) {\n\t\t\tif needle == 7 {\n\t\t\t\tcontinue // this statement defeats loop elimination\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc generic[T any](slice []T, f func(T) bool) bool {\n\tfor _, elem := range slice { // want \"Loop can be simplified using slices.ContainsFunc\"\n\t\tif f(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc predicate(int) bool\n\n// Regression tests for bad fixes when needle\n// and haystack have different types (#71313):\n\nfunc nopeNeedleHaystackDifferentTypes(x any, args []error) {\n\tfor _, arg := range args {\n\t\tif arg == x {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc nopeNeedleHaystackDifferentTypes2(x error, args []any) {\n\tfor _, arg := range args {\n\t\tif arg == x {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc nopeVariadicNamedContainsFunc(slice []int) bool {\n\tfor _, elem := range slice {\n\t\tif variadicPredicate(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc variadicPredicate(int, ...any) bool\n\nfunc nopeVariadicContainsFunc(slice []int) bool {\n\tf := func(int, ...any) bool {\n\t\treturn true\n\t}\n\tfor _, elem := range slice {\n\t\tif f(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Negative test case for implicit C->I conversion\ntype I interface{ F() }\ntype C int\n\nfunc (C) F() {}\n\nfunc nopeImplicitConversionContainsFunc(slice []C, f func(I) bool) bool {\n\tfor _, elem := range slice {\n\t\tif f(elem) { // implicit conversion from C to I\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc nopeTypeParamWidening[T any](slice []T, f func(any) bool) bool {\n\tfor _, elem := range slice {\n\t\tif f(elem) { // implicit conversion from T to any\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc issue76210(haystack []string, needle string) bool {\n\tres := len(haystack) == 0\n\tfor _, elem := range haystack { // want \"Loop can be simplified using slices.Contains\"\n\t\tif needle == elem {\n\t\t\tres = true\n\t\t\tbreak\n\t\t}\n\t}\n\treturn res\n}\n\nfunc issue76210negation(haystack []string, needle string) bool {\n\tres := len(haystack) != 0\n\tfor _, elem := range haystack { // want \"Loop can be simplified using slices.Contains\"\n\t\tif needle == elem {\n\t\t\tres = false\n\t\t\tbreak\n\t\t}\n\t}\n\treturn res\n}\n\nfunc issue77677emptybody(slice []int, needle int) {\n\tfor _, elem := range slice { // nope: would produce \"if slices.Contains\" with an empty body\n\t\tif elem == needle {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype Object struct{}\n\nfunc (o Object) Do() Object { return Object{} }\nfunc (o Object) Print()     { fmt.Println(\"Hello, World!\") }\n\nfunc issue78149nonboolassign(obj Object, opts ...string) {\n\to := obj\n\tfor _, opt := range opts { // want \"Loop can be simplified using slices.Contains\"\n\t\tif opt == \"something\" {\n\t\t\to = o.Do()\n\t\t\tbreak\n\t\t}\n\t}\n\to.Print()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicescontains/slicescontains.go.golden",
    "content": "package slicescontains\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nvar _ = slices.Contains[[]int] // force import of \"slices\" to avoid duplicate import edits\n\nfunc nopeNoBreak(slice []int, needle int) {\n\tfor i := range slice {\n\t\tif slice[i] == needle {\n\t\t\tprintln(\"found\")\n\t\t}\n\t}\n}\n\nfunc rangeIndex(slice []int, needle int) {\n\tif slices.Contains(slice, needle) {\n\t\tprintln(\"found\")\n\t}\n}\n\nfunc rangeValue(slice []int, needle int) {\n\tif slices.Contains(slice, needle) {\n\t\tprintln(\"found\")\n\t}\n}\n\nfunc returns(slice []int, needle int) {\n\tif slices.Contains(slice, needle) {\n\t\tprintln(\"found\")\n\t\treturn\n\t}\n}\n\nfunc assignTrueBreak(slice []int, needle int) {\n\tfound := slices.Contains(slice, needle)\n\tprint(found)\n}\n\nfunc assignFalseBreak(slice []int, needle int) {\n\tfound := !slices.Contains(slice, needle)\n\tprint(found)\n}\n\nfunc assignFalseBreakInSelectSwitch(slice []int, needle int) {\n\t// Exercise RangeStmt in CommClause, CaseClause.\n\tselect {\n\tdefault:\n\t\tfound := slices.Contains(slice, needle)\n\t\tprint(found)\n\t}\n\tswitch {\n\tdefault:\n\t\tfound := slices.Contains(slice, needle)\n\t\tprint(found)\n\t}\n}\n\nfunc returnTrue(slice []int, needle int) bool {\n\treturn slices.Contains(slice, needle)\n}\n\nfunc returnFalse(slice []int, needle int) bool {\n\treturn !slices.Contains(slice, needle)\n}\n\nfunc containsFunc(slice []int, needle int) bool {\n\treturn slices.ContainsFunc(slice, predicate)\n}\n\nfunc nopeLoopBodyHasFreeContinuation(slice []int, needle int) bool {\n\tfor _, elem := range slice {\n\t\tif predicate(elem) {\n\t\t\tif needle == 7 {\n\t\t\t\tcontinue // this statement defeats loop elimination\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc generic[T any](slice []T, f func(T) bool) bool {\n\treturn slices.ContainsFunc(slice, f)\n}\n\nfunc predicate(int) bool\n\n// Regression tests for bad fixes when needle\n// and haystack have different types (#71313):\n\nfunc nopeNeedleHaystackDifferentTypes(x any, args []error) {\n\tfor _, arg := range args {\n\t\tif arg == x {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc nopeNeedleHaystackDifferentTypes2(x error, args []any) {\n\tfor _, arg := range args {\n\t\tif arg == x {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc nopeVariadicNamedContainsFunc(slice []int) bool {\n\tfor _, elem := range slice {\n\t\tif variadicPredicate(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc variadicPredicate(int, ...any) bool\n\nfunc nopeVariadicContainsFunc(slice []int) bool {\n\tf := func(int, ...any) bool {\n\t\treturn true\n\t}\n\tfor _, elem := range slice {\n\t\tif f(elem) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Negative test case for implicit C->I conversion\ntype I interface{ F() }\ntype C int\n\nfunc (C) F() {}\n\nfunc nopeImplicitConversionContainsFunc(slice []C, f func(I) bool) bool {\n\tfor _, elem := range slice {\n\t\tif f(elem) { // implicit conversion from C to I\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc nopeTypeParamWidening[T any](slice []T, f func(any) bool) bool {\n\tfor _, elem := range slice {\n\t\tif f(elem) { // implicit conversion from T to any\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc issue76210(haystack []string, needle string) bool {\n\tres := len(haystack) == 0\n\tif slices.Contains(haystack, needle) {\n\t\tres = true\n\t}\n\treturn res\n}\n\nfunc issue76210negation(haystack []string, needle string) bool {\n\tres := len(haystack) != 0\n\tif slices.Contains(haystack, needle) {\n\t\tres = false\n\t}\n\treturn res\n}\n\nfunc issue77677emptybody(slice []int, needle int) {\n\tfor _, elem := range slice { // nope: would produce \"if slices.Contains\" with an empty body\n\t\tif elem == needle {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype Object struct{}\n\nfunc (o Object) Do() Object { return Object{} }\nfunc (o Object) Print()     { fmt.Println(\"Hello, World!\") }\n\nfunc issue78149nonboolassign(obj Object, opts ...string) {\n\to := obj\n\tif slices.Contains(opts, \"something\") {\n\t\to = o.Do()\n\t}\n\to.Print()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicesdelete/slicesdelete.go",
    "content": "package slicesdelete\n\nvar g struct{ f []int }\n\nfunc h() []int { return []int{} }\n\nvar ch chan []int\n\nfunc slicesdelete(test, other []byte, i int) {\n\tconst k = 1\n\t_ = append(test[:i], test[i+1:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i+1], test[i+2:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i+1], test[i+1:]...) // not deleting any slice elements\n\n\t_ = append(test[:i], test[i-1:]...) // not deleting any slice elements\n\n\t_ = append(test[:i-1], test[i:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i-2], test[i+1:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i-2], other[i+1:]...) // different slices \"test\" and \"other\"\n\n\t_ = append(test[:i-2], other[i+1+k:]...) // cannot verify a < b\n\n\t_ = append(test[:i-2], test[11:]...) // cannot verify a < b\n\n\t_ = append(test[:1], test[3:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(g.f[:i], g.f[i+k:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(h()[:i], h()[i+1:]...) // potentially has side effects\n\n\t_ = append((<-ch)[:i], (<-ch)[i+1:]...) // has side effects\n\n\t_ = append(test[:3], test[i+1:]...) // cannot verify a < b\n\n\t_ = append(test[:i-4], test[i-1:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:1+2], test[3+4:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:1+2], test[i-1:]...) // cannot verify a < b\n}\n\nfunc issue73663(test, other []byte, i int32) {\n\tconst k = 1\n\t_ = append(test[:i], test[i+1:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i-1], test[i:]...) // want \"Replace append with slices.Delete\"\n\n\t_ = append(g.f[:i], g.f[i+k:]...) // want \"Replace append with slices.Delete\"\n\n\ttype int string // int is shadowed, so no offered fix.\n\t_ = append(test[:i], test[i+1:]...)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicesdelete/slicesdelete.go.golden",
    "content": "package slicesdelete\n\nimport \"slices\"\n\nvar g struct{ f []int }\n\nfunc h() []int { return []int{} }\n\nvar ch chan []int\n\nfunc slicesdelete(test, other []byte, i int) {\n\tconst k = 1\n\t_ = slices.Delete(test, i, i+1) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(test, i+1, i+2) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i+1], test[i+1:]...) // not deleting any slice elements\n\n\t_ = append(test[:i], test[i-1:]...) // not deleting any slice elements\n\n\t_ = slices.Delete(test, i-1, i) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(test, i-2, i+1) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:i-2], other[i+1:]...) // different slices \"test\" and \"other\"\n\n\t_ = append(test[:i-2], other[i+1+k:]...) // cannot verify a < b\n\n\t_ = append(test[:i-2], test[11:]...) // cannot verify a < b\n\n\t_ = slices.Delete(test, 1, 3) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(g.f, i, i+k) // want \"Replace append with slices.Delete\"\n\n\t_ = append(h()[:i], h()[i+1:]...) // potentially has side effects\n\n\t_ = append((<-ch)[:i], (<-ch)[i+1:]...) // has side effects\n\n\t_ = append(test[:3], test[i+1:]...) // cannot verify a < b\n\n\t_ = slices.Delete(test, i-4, i-1) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(test, 1+2, 3+4) // want \"Replace append with slices.Delete\"\n\n\t_ = append(test[:1+2], test[i-1:]...) // cannot verify a < b\n}\n\nfunc issue73663(test, other []byte, i int32) {\n\tconst k = 1\n\t_ = slices.Delete(test, int(i), int(i+1)) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(test, int(i-1), int(i)) // want \"Replace append with slices.Delete\"\n\n\t_ = slices.Delete(g.f, int(i), int(i+k)) // want \"Replace append with slices.Delete\"\n\n\ttype int string // int is shadowed, so no offered fix.\n\t_ = append(test[:i], test[i+1:]...)\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go",
    "content": "package slicessort\n\nimport \"sort\"\n\ntype myint int\n\nfunc _(s []myint) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] < s[j] }) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(x *struct{ s []int }) {\n\tsort.Slice(x.s, func(first, second int) bool { return x.s[first] < x.s[second] }) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] > s[j] }) // nope: wrong comparison operator\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var\n}\n\nfunc _(sense bool, s2 []struct{ x int }) {\n\tsort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation\n\n\t// Regression test for a crash: the sole statement of a\n\t// comparison func body is not necessarily a return!\n\tsort.Slice(s2, func(i, j int) bool {\n\t\tif sense {\n\t\t\treturn s2[i].x < s2[j].x\n\t\t} else {\n\t\t\treturn s2[i].x > s2[j].x\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go.golden",
    "content": "package slicessort\n\nimport \"slices\"\n\nimport \"sort\"\n\ntype myint int\n\nfunc _(s []myint) {\n\tslices.Sort(s) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(x *struct{ s []int }) {\n\tslices.Sort(x.s) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] > s[j] }) // nope: wrong comparison operator\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var\n}\n\nfunc _(sense bool, s2 []struct{ x int }) {\n\tsort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation\n\n\t// Regression test for a crash: the sole statement of a\n\t// comparison func body is not necessarily a return!\n\tsort.Slice(s2, func(i, j int) bool {\n\t\tif sense {\n\t\t\treturn s2[i].x < s2[j].x\n\t\t} else {\n\t\t\treturn s2[i].x > s2[j].x\t\t\t\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicessort/slicessort_dot.go",
    "content": "package slicessort\n\nimport (\n\t. \"slices\"\n\t\"sort\"\n)\n\nfunc _(s []myint) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] < s[j] }) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(x *struct{ s []int }) {\n\tsort.Slice(x.s, func(first, second int) bool { return x.s[first] < x.s[second] }) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] > s[j] }) // nope: wrong comparison operator\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var\n}\n\nfunc _(s2 []struct{ x int }) {\n\tsort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation\n}\n\nfunc _() { Clip([]int{}) }\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/slicessort/slicessort_dot.go.golden",
    "content": "package slicessort\n\nimport (\n\t. \"slices\"\n\t\"sort\"\n)\n\nfunc _(s []myint) {\n\tSort(s) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(x *struct{ s []int }) {\n\tSort(x.s) // want \"sort.Slice can be modernized using slices.Sort\"\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[i] > s[j] }) // nope: wrong comparison operator\n}\n\nfunc _(s []int) {\n\tsort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var\n}\n\nfunc _(s2 []struct{ x int }) {\n\tsort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation\n}\n\nfunc _() { Clip([]int{}) }\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/splitseq/splitseq.go",
    "content": "//go:build go1.24\n\npackage splitseq\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc _() {\n\tfor _, line := range strings.Split(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t\tprintln(line)\n\t}\n\tfor i, line := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i, line)\n\t}\n\tfor i, _ := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor i := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor _ = range strings.Split(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\tfor range strings.Split(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\tfor range bytes.Split(nil, nil) { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\t{\n\t\tlines := strings.Split(\"\", \"\") // want \"Ranging over SplitSeq is more efficient\"\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t}\n\t{\n\t\tlines := strings.Split(\"\", \"\") // nope: lines is used not just by range\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t\tprintln(lines)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/splitseq/splitseq.go.golden",
    "content": "//go:build go1.24\n\npackage splitseq\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc _() {\n\tfor line := range strings.SplitSeq(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t\tprintln(line)\n\t}\n\tfor i, line := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i, line)\n\t}\n\tfor i, _ := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor i := range strings.Split(\"\", \"\") { // nope: uses index var\n\t\tprintln(i)\n\t}\n\tfor range strings.SplitSeq(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\tfor range strings.SplitSeq(\"\", \"\") { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\tfor range bytes.SplitSeq(nil, nil) { // want \"Ranging over SplitSeq is more efficient\"\n\t}\n\t{\n\t\tlines := strings.SplitSeq(\"\", \"\") // want \"Ranging over SplitSeq is more efficient\"\n\t\tfor line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t}\n\t{\n\t\tlines := strings.Split(\"\", \"\") // nope: lines is used not just by range\n\t\tfor _, line := range lines {\n\t\t\tprintln(line)\n\t\t}\n\t\tprintln(lines)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/splitseq/splitseq_go123.go",
    "content": "package splitseq\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stditerators/stditerators.go",
    "content": "package stditerators\n\nimport (\n\t\"go/types\"\n\t\"reflect\"\n)\n\nfunc _(tuple *types.Tuple) {\n\tfor i := 0; i < tuple.Len(); i++ { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\tprint(tuple.At(i))\n\t}\n}\n\nfunc _(scope *types.Scope) {\n\tfor i := 0; i < scope.NumChildren(); i++ { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\tprint(scope.Child(i))\n\t}\n\t{\n\t\t// tests of shadowing of preferred name at def\n\t\tconst child = 0\n\t\tfor i := 0; i < scope.NumChildren(); i++ { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tprint(scope.Child(i))\n\t\t}\n\t\tfor i := 0; i < scope.NumChildren(); i++ { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tprint(scope.Child(i), child)\n\t\t}\n\t}\n\t{\n\t\tfor i := 0; i < scope.NumChildren(); i++ {\n\t\t\tconst child = 0 // nope: shadowing of fresh name at use\n\t\t\tprint(scope.Child(i))\n\t\t}\n\t}\n\t{\n\t\tfor i := 0; i < scope.NumChildren(); i++ { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\telem := scope.Child(i) // => preferred name = \"elem\"\n\t\t\tprint(elem)\n\t\t}\n\t}\n\t{\n\t\tfor i := 0; i < scope.NumChildren(); i++ { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tfirst := scope.Child(0) // the name heuristic should not be fooled by this\n\t\t\tprint(first, scope.Child(i))\n\t\t}\n\t}\n}\n\nfunc _(union, union2 *types.Union) {\n\tfor i := 0; i < union.Len(); i++ { // want \"Len/Term loop can simplified using Union.Terms iteration\"\n\t\tprint(union.Term(i))\n\t\tprint(union.Term(i))\n\t}\n\tfor i := union.Len() - 1; i >= 0; i-- { // nope: wrong loop form\n\t\tprint(union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: wrong loop form\n\t\tprint(union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: use of i not in x.At(i)\n\t\tprint(i, union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: x.At and x.Len have different receivers\n\t\tprint(i, union2.Term(i))\n\t}\n}\n\nfunc _(tuple *types.Tuple) {\n\tfor i := 0; i < tuple.Len(); i++ { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\tif foo := tuple.At(i); true { // => preferred name = \"foo\"\n\t\t\tprint(foo)\n\t\t}\n\t\tbar := tuple.At(i)\n\t\tprint(bar)\n\t}\n\t{\n\t\t// The name v is already declared, but not\n\t\t// used in the loop, so we can use it again.\n\t\tv := 1\n\t\tprint(v)\n\n\t\tfor i := 0; i < tuple.Len(); i++ { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\t\tprint(tuple.At(i))\n\t\t}\n\t}\n\t{\n\t\t// The name v is used from the loop, so\n\t\t// we must choose a fresh name.\n\t\tv := 1\n\t\tfor i := 0; i < tuple.Len(); i++ { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\t\tprint(tuple.At(i), v)\n\t\t}\n\t}\n}\n\nfunc _(t reflect.Type) {\n\tfor i := 0; i < t.NumField(); i++ { // want \"NumField/Field loop can simplified using Type.Fields iteration\"\n\t\tprint(t.Field(i))\n\t}\n\tfor i := 0; i < t.NumMethod(); i++ { // want \"NumMethod/Method loop can simplified using Type.Methods iteration\"\n\t\tprint(t.Method(i))\n\t}\n\tfor i := 0; i < t.NumIn(); i++ { // want \"NumIn/In loop can simplified using Type.Ins iteration\"\n\t\tprint(t.In(i))\n\t}\n\tfor i := 0; i < t.NumOut(); i++ { // want \"NumOut/Out loop can simplified using Type.Outs iteration\"\n\t\tprint(t.Out(i))\n\t}\n}\n\nfunc _(v reflect.Value) {\n\tfor i := 0; i < v.NumField(); i++ { // want \"NumField/Field loop can simplified using Value.Fields iteration\"\n\t\tprint(v.Field(i))\n\t}\n\t// Ideally we would use both parts of Value.Field's iter.Seq2 here.\n\tfor i := 0; i < v.NumField(); i++ {\n\t\tprint(v.Field(i), v.Type().Field(i)) // nope\n\t}\n\tfor i := 0; i < v.NumMethod(); i++ { // want \"NumMethod/Method loop can simplified using Value.Methods iteration\"\n\t\tprint(v.Method(i))\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stditerators/stditerators.go.golden",
    "content": "package stditerators\n\nimport (\n\t\"go/types\"\n\t\"reflect\"\n)\n\nfunc _(tuple *types.Tuple) {\n\tfor v := range tuple.Variables() { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\tprint(v)\n\t}\n}\n\nfunc _(scope *types.Scope) {\n\tfor child := range scope.Children() { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\tprint(child)\n\t}\n\t{\n\t\t// tests of shadowing of preferred name at def\n\t\tconst child = 0\n\t\tfor child := range scope.Children() { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tprint(child)\n\t\t}\n\t\tfor child0 := range scope.Children() { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tprint(child0, child)\n\t\t}\n\t}\n\t{\n       \t\tfor i := 0; i < scope.NumChildren(); i++ {\n       \t\t\tconst child = 0 // nope: shadowing of fresh name at use\n       \t\t\tprint(scope.Child(i))\n       \t\t}\n       \t}\n\t{\n\t\tfor elem := range scope.Children() { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\telem := elem // => preferred name = \"elem\"\n\t\t\tprint(elem)\n\t\t}\n\t}\n\t{\n\t\tfor child := range scope.Children() { // want \"NumChildren/Child loop can simplified using Scope.Children iteration\"\n\t\t\tfirst := scope.Child(0) // the name heuristic should not be fooled by this\n\t\t\tprint(first, child)\n\t\t}\n\t}\n}\n\nfunc _(union, union2 *types.Union) {\n\tfor term := range union.Terms() { // want \"Len/Term loop can simplified using Union.Terms iteration\"\n\t\tprint(term)\n\t\tprint(term)\n\t}\n\tfor i := union.Len() - 1; i >= 0; i-- { // nope: wrong loop form\n\t\tprint(union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: wrong loop form\n\t\tprint(union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: use of i not in x.At(i)\n\t\tprint(i, union.Term(i))\n\t}\n\tfor i := 0; i <= union.Len(); i++ { // nope: x.At and x.Len have different receivers\n\t\tprint(i, union2.Term(i))\n\t}\n}\n\nfunc _(tuple *types.Tuple) {\n\tfor foo := range tuple.Variables() { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\tif foo := foo; true { // => preferred name = \"foo\"\n\t\t\tprint(foo)\n\t\t}\n\t\tbar := foo\n\t\tprint(bar)\n\t}\n\t{\n\t\t// The name v is already declared, but not\n\t\t// used in the loop, so we can use it again.\n\t\tv := 1\n\t\tprint(v)\n\n\t\tfor v := range tuple.Variables() { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\t\tprint(v)\n\t\t}\n\t}\n\t{\n\t\t// The name v is used from the loop, so\n\t\t// we must choose a fresh name.\n\t\tv := 1\n\t\tfor v0 := range tuple.Variables() { // want \"Len/At loop can simplified using Tuple.Variables iteration\"\n\t\t\tprint(v0, v)\n\t\t}\n\t}\n}\n\nfunc _(t reflect.Type) {\n\tfor field := range t.Fields() { // want \"NumField/Field loop can simplified using Type.Fields iteration\"\n\t\tprint(field)\n\t}\n\tfor method := range t.Methods() { // want \"NumMethod/Method loop can simplified using Type.Methods iteration\"\n\t\tprint(method)\n\t}\n\tfor in := range t.Ins() { // want \"NumIn/In loop can simplified using Type.Ins iteration\"\n\t\tprint(in)\n\t}\n\tfor out := range t.Outs() { // want \"NumOut/Out loop can simplified using Type.Outs iteration\"\n\t\tprint(out)\n\t}\n}\n\nfunc _(v reflect.Value) {\n\tfor _, field := range v.Fields() { // want \"NumField/Field loop can simplified using Value.Fields iteration\"\n\t\tprint(field)\n\t}\n\t// Ideally we would use both parts of Value.Field's iter.Seq2 here.\n\tfor i := 0; i < v.NumField(); i++ {\n\t\tprint(v.Field(i), v.Type().Field(i)) // nope\n\t}\n\tfor _, method := range v.Methods() { // want \"NumMethod/Method loop can simplified using Value.Methods iteration\"\n\t\tprint(method)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringsbuilder/stringsbuilder.go",
    "content": "package stringsbuilder\n\nimport \"strings\"\n\n// basic test\nfunc _() {\n\tvar s string\n\ts += \"before\"\n\tfor range 10 {\n\t\ts += \"in\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t\ts += \"in2\"\n\t}\n\ts += \"after\"\n\tprint(s)\n}\n\n// with initializer\nfunc _() {\n\tvar s = \"a\"\n\tfor range 10 {\n\t\ts += \"b\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s)\n}\n\n// with empty initializer\nfunc _() {\n\tvar s = \"\"\n\tfor range 10 {\n\t\ts += \"b\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s)\n}\n\n// with short decl\nfunc _() {\n\ts := \"a\"\n\tfor range 10 {\n\t\ts += \"b\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s)\n}\n\n// with short decl and empty initializer\nfunc _() {\n\ts := \"\"\n\tfor range 10 {\n\t\ts += \"b\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s)\n}\n\n// nope: += must appear at least once within a loop.\nfunc _() {\n\tvar s string\n\ts += \"a\"\n\ts += \"b\"\n\ts += \"c\"\n\tprint(s)\n}\n\n// nope: the declaration of s is not in a block.\nfunc _() {\n\tif s := \"a\"; true {\n\t\tfor range 10 {\n\t\t\ts += \"x\"\n\t\t}\n\t\tprint(s)\n\t}\n}\n\n// in a switch (special case of \"in a block\" logic)\nfunc _() {\n\tswitch {\n\tdefault:\n\t\ts := \"a\"\n\t\tfor range 10 {\n\t\t\ts += \"b\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t\t}\n\t\tprint(s)\n\t}\n}\n\n// nope: don't handle direct assignments to the string  (only +=).\nfunc _(x string) string {\n\tvar s string\n\ts = x\n\tfor range 3 {\n\t\ts += \"\" + x\n\t}\n\treturn s\n}\n\n// Regression test for bug in a GenDecl with parens.\nfunc issue75318(slice []string) string {\n\tvar (\n\t\tmsg string\n\t)\n\tfor _, s := range slice {\n\t\tmsg += s // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\treturn msg\n}\n\n// Regression test for https://go.dev/issue/76983.\n// We offer only the first fix if the second would overlap.\n// This is an ad-hoc mitigation of the more general issue #76476.\nfunc _(slice []string) string {\n\ta := \"12\"\n\tfor range 2 {\n\t\ta += \"34\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tb := \"56\"\n\tfor range 2 {\n\t\tb += \"78\"\n\t}\n\ta += b\n\treturn a\n}\nfunc _(slice []string) string {\n\tvar a strings.Builder\n\ta.WriteString(\"12\")\n\tfor range 2 {\n\t\ta.WriteString(\"34\")\n\t}\n\tb := \"56\"\n\tfor range 2 {\n\t\tb += \"78\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\ta.WriteString(b)\n\treturn a.String()\n}\n\n// Regression test for go.dev/issue/76934, which mutilated the var decl.\nfunc stringDeclaredWithVarDecl() {\n\tvar (\n\t\tbefore int // this is ok\n\t\tstr    = \"hello world\"\n\t)\n\tfor range 100 {\n\t\tstr += \"!\" // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprintln(before, str)\n}\n\nfunc nopeStringIsNotLastValueSpecInVarDecl() {\n\tvar (\n\t\tstr   = \"hello world\"\n\t\tafter int // this defeats the transformation\n\t)\n\tfor range 100 {\n\t\tstr += \"!\" // nope\n\t}\n\tprintln(str, after)\n}\n\n// Regression test for go.dev/issue/77659.\n// Multiple rvalue uses of the accumulated string should all be converted.\nfunc _() {\n\tacc := \"s1\"\n\tfor _, s := range []string{\"foo\", \"bar\"} {\n\t\tacc += s // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\t_ = acc\n\t_ = acc + \"footer2\"\n}\n\n// Regression test for go.dev/issue/77659 (negative case).\n// += after an rvalue use should still be rejected.\nfunc _() {\n\tvar s string\n\tfor _, x := range []string{\"a\", \"b\"} {\n\t\ts += x\n\t}\n\tprint(s)\n\ts += \"extra\" // nope: += after rvalue use\n\tprint(s)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringsbuilder/stringsbuilder.go.golden",
    "content": "package stringsbuilder\n\nimport \"strings\"\n\n// basic test\nfunc _() {\n\tvar s strings.Builder\n\ts.WriteString(\"before\")\n\tfor range 10 {\n\t\ts.WriteString(\"in\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t\ts.WriteString(\"in2\")\n\t}\n\ts.WriteString(\"after\")\n\tprint(s.String())\n}\n\n// with initializer\nfunc _() {\n\tvar s strings.Builder\n\ts.WriteString(\"a\")\n\tfor range 10 {\n\t\ts.WriteString(\"b\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s.String())\n}\n\n// with empty initializer\nfunc _() {\n\tvar s strings.Builder\n\tfor range 10 {\n\t\ts.WriteString(\"b\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s.String())\n}\n\n// with short decl\nfunc _() {\n\tvar s strings.Builder\n\ts.WriteString(\"a\")\n\tfor range 10 {\n\t\ts.WriteString(\"b\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s.String())\n}\n\n// with short decl and empty initializer\nfunc _() {\n\tvar s strings.Builder\n\tfor range 10 {\n\t\ts.WriteString(\"b\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprint(s.String())\n}\n\n// nope: += must appear at least once within a loop.\nfunc _() {\n\tvar s string\n\ts += \"a\"\n\ts += \"b\"\n\ts += \"c\"\n\tprint(s)\n}\n\n// nope: the declaration of s is not in a block.\nfunc _() {\n\tif s := \"a\"; true {\n\t\tfor range 10 {\n\t\t\ts += \"x\"\n\t\t}\n\t\tprint(s)\n\t}\n}\n\n// in a switch (special case of \"in a block\" logic)\nfunc _() {\n\tswitch {\n\tdefault:\n\t\tvar s strings.Builder\n\t\ts.WriteString(\"a\")\n\t\tfor range 10 {\n\t\t\ts.WriteString(\"b\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t\t}\n\t\tprint(s.String())\n\t}\n}\n\n// nope: don't handle direct assignments to the string  (only +=).\nfunc _(x string) string {\n\tvar s string\n\ts = x\n\tfor range 3 {\n\t\ts += \"\" + x\n\t}\n\treturn s\n}\n\n// Regression test for bug in a GenDecl with parens.\nfunc issue75318(slice []string) string {\n\tvar (\n\t\tmsg strings.Builder\n\t)\n\tfor _, s := range slice {\n\t\tmsg.WriteString(s) // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\treturn msg.String()\n}\n\n// Regression test for https://go.dev/issue/76983.\n// We offer only the first fix if the second would overlap.\n// This is an ad-hoc mitigation of the more general issue #76476.\nfunc _(slice []string) string {\n\tvar a strings.Builder; a.WriteString(\"12\")\n\tfor range 2 {\n\t\ta.WriteString(\"34\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tb := \"56\"\n\tfor range 2 {\n\t\tb += \"78\"\n\t}\n\ta.WriteString(b)\n\treturn a.String()\n}\nfunc _(slice []string) string {\n\tvar a strings.Builder\n\ta.WriteString(\"12\")\n\tfor range 2 {\n\t\ta.WriteString(\"34\")\n\t}\n\tvar b strings.Builder\n\tb.WriteString(\"56\")\n\tfor range 2 {\n\t\tb.WriteString(\"78\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\ta.WriteString(b.String())\n\treturn a.String()\n}\n\n// Regression test for go.dev/issue/76934, which mutilated the var decl.\nfunc stringDeclaredWithVarDecl() {\n\tvar (\n\t\tbefore int // this is ok\n\t\tstr strings.Builder\n\t)\n\tstr.WriteString(\"hello world\")\n\tfor range 100 {\n\t\tstr.WriteString(\"!\") // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\tprintln(before, str.String())\n}\n\nfunc nopeStringIsNotLastValueSpecInVarDecl() {\n\tvar (\n\t\tstr   = \"hello world\"\n\t\tafter int // this defeats the transformation\n\t)\n\tfor range 100 {\n\t\tstr += \"!\" // nope\n\t}\n\tprintln(str, after)\n}\n\n// Regression test for go.dev/issue/77659.\n// Multiple rvalue uses of the accumulated string should all be converted.\nfunc _() {\n\tvar acc strings.Builder\n\tacc.WriteString(\"s1\")\n\tfor _, s := range []string{\"foo\", \"bar\"} {\n\t\tacc.WriteString(s) // want \"using string \\\\+= string in a loop is inefficient\"\n\t}\n\t_ = acc.String()\n\t_ = acc.String() + \"footer2\"\n}\n\n// Regression test for go.dev/issue/77659 (negative case).\n// += after an rvalue use should still be rejected.\nfunc _() {\n\tvar s string\n\tfor _, x := range []string{\"a\", \"b\"} {\n\t\ts += x\n\t}\n\tprint(s)\n\ts += \"extra\" // nope: += after rvalue use\n\tprint(s)\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go",
    "content": "package stringscut\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc basic(s string) bool {\n\ts = \"reassigned\"\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tprint(s[:i])\n\t}\n\treturn i >= 0\n}\n\nfunc basic_contains(s string) bool {\n\ts = \"reassigned\"\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Contains\"\n\treturn i >= 0\n}\n\nfunc contains_variety(s, sub string) {\n\ti := strings.Index(s, sub) // want \"strings.Index can be simplified using strings.Contains\"\n\tif i >= 0 {\n\t\tprint(\"found\")\n\t}\n\tif i < 0 {\n\t\tprint(\"not found\")\n\t}\n\tif i <= -1 {\n\t\tprint(\"not found\")\n\t}\n}\n\nfunc basic_contains_bytes(s string) bool {\n\ti := strings.IndexByte(s, '=') // want \"strings.IndexByte can be simplified using strings.Contains\"\n\treturn i < 0\n}\n\nfunc basic_contains_bytes_byte(s []byte) bool {\n\ti := bytes.IndexByte(s, 22) // want \"bytes.IndexByte can be simplified using bytes.Contains\"\n\treturn i < 0\n}\n\nfunc skip_var_decl(s string) bool {\n\tvar i int\n\ti = strings.Index(s, \"=\") // don't modernize - i might be reassigned\n\tprint(s[:i])\n\treturn i >= 0\n}\n\nfunc basic_substr_arg(s string, substr string) bool {\n\ti := strings.Index(s, substr) // want \"strings.Index can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tprint(s[i+len(substr):])\n\t}\n\treturn i >= 0\n}\n\nfunc wrong_len_arg(s string, substr string) bool {\n\ti := strings.Index(s, substr) // don't modernize since i+len(s) is not valid\n\tprint(s[i+len(s):])\n\treturn i >= 0\n}\n\nfunc basic_strings_byte(s string) bool {\n\ti := strings.IndexByte(s, '+') // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tprint(s[:i])\n\t}\n\treturn i >= 0\n}\n\nfunc basic_strings_byte_int(s string) bool {\n\ti := strings.IndexByte(s, 55) // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tprint(s[:i])\n\t}\n\treturn i >= 0\n}\n\nfunc basic_strings_byte_var(s string) bool {\n\tb := byte('b')\n\ti := strings.IndexByte(s, b) // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tprint(s[:i])\n\t}\n\treturn i >= 0\n}\n\nfunc basic_bytes(b []byte) []byte {\n\ti := bytes.Index(b, []byte(\"str\")) // want \"bytes.Index can be simplified using bytes.Cut\"\n\tif i >= 0 {\n\t\treturn b[:i]\n\t} else {\n\t\treturn b[i+3:]\n\t}\n}\n\nfunc basic_index_bytes(b []byte) string {\n\ti := bytes.IndexByte(b, 's') // don't modernize: b[i+1:] in else is not guarded\n\tif i >= 0 {\n\t\treturn string(b[:i])\n\t} else {\n\t\treturn string(b[i+1:])\n\t}\n}\n\nfunc const_substr_len(s string) bool {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tr := s[i+len(\"=\"):]\n\t\treturn len(r) > 0\n\t}\n\treturn false\n}\n\nfunc const_for_len(s string) bool {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\tr := s[i+1:]\n\t\treturn len(r) > 0\n\t}\n\treturn false\n}\n\nfunc index(s string) bool {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i < 0 {\n\t\treturn false\n\t}\n\tif i >= 0 {\n\t\treturn true\n\t}\n\tprint(s[:i])\n\treturn true\n}\n\nfunc index_flipped(s string) bool {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif 0 > i {\n\t\treturn false\n\t}\n\tif 0 <= i {\n\t\treturn true\n\t}\n\tprint(s[:i])\n\treturn true\n}\n\nfunc invalid_index(s string) bool {\n\ti := strings.Index(s, \"=\") // don't modernize since i is used in an \"invalid\" binaryexpr\n\tif 0 > i {\n\t\treturn false\n\t}\n\tif i < 10 {\n\t\treturn true\n\t}\n\treturn true\n}\n\nfunc invalid_slice(s string) string {\n\ti := strings.Index(s, \"=\") // don't modernize since i is used in an \"invalid\" slice index\n\tif i >= 0 {\n\t\treturn s[i+4:]\n\t}\n\treturn \"\"\n}\n\nfunc index_and_before_after(s string) string {\n\tsubstr := \"=\"\n\ti := strings.Index(s, substr) // don't modernize: s[i+len(substr):] and s[len(substr)+i:] not nonneg-guarded\n\tif i == -1 {\n\t\tprint(\"test\")\n\t}\n\tif i < 0 {\n\t\treturn \"\"\n\t} else {\n\t\tif i >= 0 {\n\t\t\treturn s[:i]\n\t\t} else {\n\t\t\treturn s[i+len(substr):]\n\t\t}\n\t}\n\tif -1 == i {\n\t\treturn s[len(substr)+i:]\n\t}\n\treturn \"final\"\n}\n\nfunc idx_var_init(s string) (string, string) {\n\tvar idx = strings.Index(s, \"=\") // don't modernize: s[0:idx] is not guarded\n\treturn s[0:idx], s\n}\n\nfunc idx_reassigned(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets reassigned\n\tidx = 10\n\treturn s[:idx]\n}\n\nfunc idx_printed(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx is used\n\tprint(idx)\n\treturn s[:idx]\n}\n\nfunc idx_aliased(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets aliased\n\ti := idx\n\treturn s[:i]\n}\n\nfunc idx_aliased_var(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets aliased\n\tvar i = idx\n\tprint(i)\n\treturn s[:idx]\n}\n\nfunc s_modified(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since s gets modified\n\ts = \"newstring\"\n\treturn s[:idx]\n}\n\nfunc s_modified_no_params() string {\n\ts := \"string\"\n\tidx := strings.Index(s, \"=\") // don't modernize since s gets modified\n\ts = \"newstring\"\n\treturn s[:idx]\n}\n\nfunc s_in_func_call() string {\n\ts := \"string\"\n\tsubstr := \"substr\"\n\tidx := strings.Index(s, substr) // don't modernize: s[:idx] is not guarded\n\tfunction(s)\n\treturn s[:idx]\n}\n\nfunc s_pointer() string {\n\ts := \"string\"\n\tidx := strings.Index(s, \"s\")\n\tptr := &s // don't modernize since s may get modified\n\treference_str(ptr)\n\treturn s[:idx]\n}\n\nfunc s_pointer_before_call() string {\n\ts := \"string\"\n\tptr := &s // don't modernize since s may get modified\n\treference_str(ptr)\n\tidx := strings.Index(s, \"s\")\n\treturn s[:idx]\n}\n\nfunc idx_used_before(s string, sub string) string {\n\tvar index int\n\treference_int(&index)\n\tindex = strings.Index(s, sub) // don't modernize since index may get modified\n\tblank()\n\tif index >= 0 {\n\t\treturn s[:index]\n\t}\n\treturn \"\"\n}\n\nfunc idx_used_other_substr(s string, sub string) string {\n\totherstr := \"other\"\n\ti := strings.Index(s, sub)\n\tprint(otherstr[:i]) // don't modernize since i used in another slice expr\n\tif i >= 0 {\n\t\treturn s[:i]\n\t} else {\n\t\treturn \"\"\n\t}\n}\n\nfunc idx_gtr_zero_invalid(s string, sub string) string {\n\ti := strings.Index(s, sub)\n\tif i > 0 { // don't modernize since this is a stronger claim than i >= 0\n\t\treturn s[:i]\n\t}\n\treturn \"\"\n}\n\nfunc idx_gtreq_one_invalid(s string, sub string) string {\n\ti := strings.Index(s, sub)\n\tif i >= 1 { // don't modernize since this is a stronger claim than i >= 0\n\t\treturn s[:i]\n\t}\n\treturn \"\"\n}\n\nfunc idx_gtr_negone(s string, sub string) string {\n\ti := strings.Index(s, sub) // want \"strings.Index can be simplified using strings.Cut\"\n\tif i > -1 {\n\t\treturn s[:i]\n\t}\n\tif i != -1 {\n\t\treturn s\n\t}\n\treturn \"\"\n}\n\n// Regression test for a crash (https://go.dev/issue/77208)\nfunc idx_call() {\n\ti := bytes.Index(b(), []byte(\"\"))\n\t_ = i\n}\n\n// Fix for golang/go#77566\nfunc multipleCallsSameScope(s string) (bool, bool) {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i != -1 {\n\t\tprint(s[:i])\n\t}\n\tj := strings.Index(s, \"-\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif j != -1 {\n\t\tprint(s[:j])\n\t}\n\treturn i >= 0, j >= 0\n}\n\nfunc shadowing(s string) string {\n\tok := \"true\"\n\tbefore := \"before\"\n\tprint(before)              // declared within scope but not used after the index call, so no fresh name\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tprint(ok)\n\tif i >= 0 {\n\t\tprint(s[:i])\n\t\tprint(i >= 0)\n\t\treturn s[i+1:]\n\t}\n\treturn \"\"\n}\n\nfunc foreshadowing(s string) string {\n\ti := strings.Index(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i != -1 {\n\t\treturn s[i+1:]\n\t}\n\t// Generate a fresh name for ok because it is used within the scope after the Index call.\n\tok, m := true, \"m\"\n\tif ok {\n\t\treturn m\n\t}\n\tif i != -1 {\n\t\treturn s\n\t}\n\treturn \"\"\n}\n\nfunc b() []byte {\n\treturn nil\n}\n\nfunc function(s string) {}\n\nfunc reference_str(s *string) {}\n\nfunc reference_int(i *int) {}\n\nfunc blank() {}\n\n// Regression test for unguarded slice uses (https://go.dev/issue/77737).\n// The s[colon+1:] usage outside the \"if\" relies on -1+1=0 to return the full\n// string when the separator is absent. Rewriting to \"after\" would return \"\".\nfunc unguarded_after_slice(s string) (int, string) {\n\tcolon := strings.Index(s, \":\")\n\tif colon != -1 {\n\t\tprint(s[:colon])\n\t}\n\treturn colon, s[colon+1:] // don't modernize: s[colon+1:] not guarded\n}\n\n// Same as above but with the guard using i < 0.\nfunc unguarded_after_slice_negcheck(s string) string {\n\ti := strings.Index(s, \":\")\n\tif i < 0 {\n\t\tprint(\"not found\")\n\t}\n\treturn s[i+1:] // don't modernize: s[i+1:] not guarded\n}\n\n// Safe: both slice uses are inside the nonneg guard.\nfunc guarded_both_slices(s string) (string, string) {\n\ti := strings.Index(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i >= 0 {\n\t\treturn s[:i], s[i+1:]\n\t}\n\treturn \"\", s\n}\n\n// Safe: slice uses after early-return negative check.\nfunc guarded_early_return(s string) (string, string) {\n\ti := strings.Index(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i < 0 {\n\t\treturn \"\", s\n\t}\n\treturn s[:i], s[i+1:]\n}\n\n// Safe: slice uses in else of negative check.\nfunc guarded_neg_else(s string) (string, string) {\n\ti := strings.Index(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif i == -1 {\n\t\treturn \"\", s\n\t} else {\n\t\treturn s[:i], s[i+1:]\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go.golden",
    "content": "package stringscut\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\nfunc basic(s string) bool {\n\ts = \"reassigned\"\n\tbefore, _, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(before)\n\t}\n\treturn ok\n}\n\nfunc basic_contains(s string) bool {\n\ts = \"reassigned\"\n\tfound := strings.Contains(s, \"=\") // want \"strings.Index can be simplified using strings.Contains\"\n\treturn found\n}\n\nfunc contains_variety(s, sub string) {\n\tfound := strings.Contains(s, sub) // want \"strings.Index can be simplified using strings.Contains\"\n\tif found {\n\t\tprint(\"found\")\n\t}\n\tif !found {\n\t\tprint(\"not found\")\n\t}\n\tif !found {\n\t\tprint(\"not found\")\n\t}\n}\n\nfunc basic_contains_bytes(s string) bool {\n\tfound := strings.Contains(s, \"=\") // want \"strings.IndexByte can be simplified using strings.Contains\"\n\treturn !found\n}\n\nfunc basic_contains_bytes_byte(s []byte) bool {\n\tfound := bytes.Contains(s, []byte{22}) // want \"bytes.IndexByte can be simplified using bytes.Contains\"\n\treturn !found\n}\n\nfunc skip_var_decl(s string) bool {\n\tvar i int\n\ti = strings.Index(s, \"=\") // don't modernize - i might be reassigned\n\tprint(s[:i])\n\treturn i >= 0\n}\n\nfunc basic_substr_arg(s string, substr string) bool {\n\t_, after, ok := strings.Cut(s, substr) // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(after)\n\t}\n\treturn ok\n}\n\nfunc wrong_len_arg(s string, substr string) bool {\n\ti := strings.Index(s, substr) // don't modernize since i+len(s) is not valid\n\tprint(s[i+len(s):])\n\treturn i >= 0\n}\n\nfunc basic_strings_byte(s string) bool {\n\tbefore, _, ok := strings.Cut(s, \"+\") // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(before)\n\t}\n\treturn ok\n}\n\nfunc basic_strings_byte_int(s string) bool {\n\tbefore, _, ok := strings.Cut(s, \"7\") // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(before)\n\t}\n\treturn ok\n}\n\nfunc basic_strings_byte_var(s string) bool {\n\tb := byte('b')\n\tbefore, _, ok := strings.Cut(s, string(b)) // want \"strings.IndexByte can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(before)\n\t}\n\treturn ok\n}\n\nfunc basic_bytes(b []byte) []byte {\n\tbefore, after, ok := bytes.Cut(b, []byte(\"str\")) // want \"bytes.Index can be simplified using bytes.Cut\"\n\tif ok {\n\t\treturn before\n\t} else {\n\t\treturn after\n\t}\n}\n\nfunc basic_index_bytes(b []byte) string {\n\ti := bytes.IndexByte(b, 's') // don't modernize: b[i+1:] in else is not guarded\n\tif i >= 0 {\n\t\treturn string(b[:i])\n\t} else {\n\t\treturn string(b[i+1:])\n\t}\n}\n\nfunc const_substr_len(s string) bool {\n\t_, after, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\tr := after\n\t\treturn len(r) > 0\n\t}\n\treturn false\n}\n\nfunc const_for_len(s string) bool {\n\t_, after, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\tr := after\n\t\treturn len(r) > 0\n\t}\n\treturn false\n}\n\nfunc index(s string) bool {\n\tbefore, _, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif !ok {\n\t\treturn false\n\t}\n\tif ok {\n\t\treturn true\n\t}\n\tprint(before)\n\treturn true\n}\n\nfunc index_flipped(s string) bool {\n\tbefore, _, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif !ok {\n\t\treturn false\n\t}\n\tif ok {\n\t\treturn true\n\t}\n\tprint(before)\n\treturn true\n}\n\nfunc invalid_index(s string) bool {\n\ti := strings.Index(s, \"=\") // don't modernize since i is used in an \"invalid\" binaryexpr\n\tif 0 > i {\n\t\treturn false\n\t}\n\tif i < 10 {\n\t\treturn true\n\t}\n\treturn true\n}\n\nfunc invalid_slice(s string) string {\n\ti := strings.Index(s, \"=\") // don't modernize since i is used in an \"invalid\" slice index\n\tif i >= 0 {\n\t\treturn s[i+4:]\n\t}\n\treturn \"\"\n}\n\nfunc index_and_before_after(s string) string {\n\tsubstr := \"=\"\n\ti := strings.Index(s, substr) // don't modernize: s[i+len(substr):] and s[len(substr)+i:] not nonneg-guarded\n\tif i == -1 {\n\t\tprint(\"test\")\n\t}\n\tif i < 0 {\n\t\treturn \"\"\n\t} else {\n\t\tif i >= 0 {\n\t\t\treturn s[:i]\n\t\t} else {\n\t\t\treturn s[i+len(substr):]\n\t\t}\n\t}\n\tif -1 == i {\n\t\treturn s[len(substr)+i:]\n\t}\n\treturn \"final\"\n}\n\nfunc idx_var_init(s string) (string, string) {\n\tvar idx = strings.Index(s, \"=\") // don't modernize: s[0:idx] is not guarded\n\treturn s[0:idx], s\n}\n\nfunc idx_reassigned(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets reassigned\n\tidx = 10\n\treturn s[:idx]\n}\n\nfunc idx_printed(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx is used\n\tprint(idx)\n\treturn s[:idx]\n}\n\nfunc idx_aliased(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets aliased\n\ti := idx\n\treturn s[:i]\n}\n\nfunc idx_aliased_var(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since idx gets aliased\n\tvar i = idx\n\tprint(i)\n\treturn s[:idx]\n}\n\nfunc s_modified(s string) string {\n\tidx := strings.Index(s, \"=\") // don't modernize since s gets modified\n\ts = \"newstring\"\n\treturn s[:idx]\n}\n\nfunc s_modified_no_params() string {\n\ts := \"string\"\n\tidx := strings.Index(s, \"=\") // don't modernize since s gets modified\n\ts = \"newstring\"\n\treturn s[:idx]\n}\n\nfunc s_in_func_call() string {\n\ts := \"string\"\n\tsubstr := \"substr\"\n\tidx := strings.Index(s, substr) // don't modernize: s[:idx] is not guarded\n\tfunction(s)\n\treturn s[:idx]\n}\n\nfunc s_pointer() string {\n\ts := \"string\"\n\tidx := strings.Index(s, \"s\")\n\tptr := &s // don't modernize since s may get modified\n\treference_str(ptr)\n\treturn s[:idx]\n}\n\nfunc s_pointer_before_call() string {\n\ts := \"string\"\n\tptr := &s // don't modernize since s may get modified\n\treference_str(ptr)\n\tidx := strings.Index(s, \"s\")\n\treturn s[:idx]\n}\n\nfunc idx_used_before(s string, sub string) string {\n\tvar index int\n\treference_int(&index)\n\tindex = strings.Index(s, sub) // don't modernize since index may get modified\n\tblank()\n\tif index >= 0 {\n\t\treturn s[:index]\n\t}\n\treturn \"\"\n}\n\nfunc idx_used_other_substr(s string, sub string) string {\n\totherstr := \"other\"\n\ti := strings.Index(s, sub)\n\tprint(otherstr[:i]) // don't modernize since i used in another slice expr\n\tif i >= 0 {\n\t\treturn s[:i]\n\t} else {\n\t\treturn \"\"\n\t}\n}\n\nfunc idx_gtr_zero_invalid(s string, sub string) string {\n\ti := strings.Index(s, sub)\n\tif i > 0 { // don't modernize since this is a stronger claim than i >= 0\n\t\treturn s[:i]\n\t}\n\treturn \"\"\n}\n\nfunc idx_gtreq_one_invalid(s string, sub string) string {\n\ti := strings.Index(s, sub)\n\tif i >= 1 { // don't modernize since this is a stronger claim than i >= 0\n\t\treturn s[:i]\n\t}\n\treturn \"\"\n}\n\nfunc idx_gtr_negone(s string, sub string) string {\n\tbefore, _, ok := strings.Cut(s, sub) // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\treturn before\n\t}\n\tif ok {\n\t\treturn s\n\t}\n\treturn \"\"\n}\n\n// Regression test for a crash (https://go.dev/issue/77208)\nfunc idx_call() {\n\ti := bytes.Index(b(), []byte(\"\"))\n\t_ = i\n}\n\n// Fix for golang/go#77566\nfunc multipleCallsSameScope(s string) (bool, bool) {\n\tbefore, _, ok := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\tprint(before)\n\t}\n\tbefore0, _, ok0 := strings.Cut(s, \"-\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok0 {\n\t\tprint(before0)\n\t}\n\treturn ok, ok0\n}\n\nfunc shadowing(s string) string {\n\tok := \"true\"\n\tbefore := \"before\"\n\tprint(before)              // declared within scope but not used after the index call, so no fresh name\n\tbefore, after, ok0 := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tprint(ok)\n\tif ok0 {\n\t\tprint(before)\n\t\tprint(ok0)\n\t\treturn after\n\t}\n\treturn \"\"\n}\n\nfunc foreshadowing(s string) string {\n\t_, after, ok0 := strings.Cut(s, \"=\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok0 {\n\t\treturn after\n\t}\n\t// Generate a fresh name for ok because it is used within the scope after the Index call.\n\tok, m := true, \"m\"\n\tif ok {\n\t\treturn m\n\t}\n\tif ok0 {\n\t\treturn s\n\t}\n\treturn \"\"\n}\n\nfunc b() []byte {\n\treturn nil\n}\n\nfunc function(s string) {}\n\nfunc reference_str(s *string) {}\n\nfunc reference_int(i *int) {}\n\nfunc blank() {}\n\n// Regression test for unguarded slice uses (https://go.dev/issue/77737).\n// The s[colon+1:] usage outside the \"if\" relies on -1+1=0 to return the full\n// string when the separator is absent. Rewriting to \"after\" would return \"\".\nfunc unguarded_after_slice(s string) (int, string) {\n\tcolon := strings.Index(s, \":\")\n\tif colon != -1 {\n\t\tprint(s[:colon])\n\t}\n\treturn colon, s[colon+1:] // don't modernize: s[colon+1:] not guarded\n}\n\n// Same as above but with the guard using i < 0.\nfunc unguarded_after_slice_negcheck(s string) string {\n\ti := strings.Index(s, \":\")\n\tif i < 0 {\n\t\tprint(\"not found\")\n\t}\n\treturn s[i+1:] // don't modernize: s[i+1:] not guarded\n}\n\n// Safe: both slice uses are inside the nonneg guard.\nfunc guarded_both_slices(s string) (string, string) {\n\tbefore, after, ok := strings.Cut(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif ok {\n\t\treturn before, after\n\t}\n\treturn \"\", s\n}\n\n// Safe: slice uses after early-return negative check.\nfunc guarded_early_return(s string) (string, string) {\n\tbefore, after, ok := strings.Cut(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif !ok {\n\t\treturn \"\", s\n\t}\n\treturn before, after\n}\n\n// Safe: slice uses in else of negative check.\nfunc guarded_neg_else(s string) (string, string) {\n\tbefore, after, ok := strings.Cut(s, \":\") // want \"strings.Index can be simplified using strings.Cut\"\n\tif !ok {\n\t\treturn \"\", s\n\t} else {\n\t\treturn before, after\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/bytescutprefix/bytescutprefix.go",
    "content": "package bytescutprefix\n\nimport (\n\t\"bytes\"\n)\n\nfunc _() {\n\tif bytes.HasPrefix(bss, bspre) { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := bytes.TrimPrefix(bss, bspre)\n\t\t_ = a\n\t}\n\tif bytes.HasPrefix([]byte(\"\"), []byte(\"\")) { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := bytes.TrimPrefix([]byte(\"\"), []byte(\"\"))\n\t\t_ = a\n\t}\n\n\tif bytes.HasSuffix(bss, bssuf) { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := bytes.TrimSuffix(bss, bssuf)\n\t\t_ = a\n\t}\n\tif bytes.HasSuffix([]byte(\"\"), []byte(\"\")) { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := bytes.TrimSuffix([]byte(\"\"), []byte(\"\"))\n\t\t_ = a\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/bytescutprefix/bytescutprefix.go.golden",
    "content": "package bytescutprefix\n\nimport (\n\t\"bytes\"\n)\n\nfunc _() {\n\tif after, ok := bytes.CutPrefix(bss, bspre); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n\tif after, ok := bytes.CutPrefix([]byte(\"\"), []byte(\"\")); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n\n\tif before, ok := bytes.CutSuffix(bss, bssuf); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := before\n\t\t_ = a\n\t}\n\tif before, ok := bytes.CutSuffix([]byte(\"\"), []byte(\"\")); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := before\n\t\t_ = a\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/bytescutprefix/bytescutprefix_dot.go",
    "content": "package bytescutprefix\n\nimport (\n\t. \"bytes\"\n)\n\nvar bss, bspre, bssuf []byte\n\n// test supported cases of pattern 1\nfunc _() {\n\tif HasPrefix(bss, bspre) { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := TrimPrefix(bss, bspre)\n\t\t_ = a\n\t}\n\n\tif HasSuffix(bss, bssuf) { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\tb := TrimSuffix(bss, bssuf)\n\t\t_ = b\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/bytescutprefix/bytescutprefix_dot.go.golden",
    "content": "package bytescutprefix\n\nimport (\n\t. \"bytes\"\n)\n\nvar bss, bspre, bssuf []byte\n\n// test supported cases of pattern 1\nfunc _() {\n\tif after, ok := CutPrefix(bss, bspre); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n\n\tif before, ok := CutSuffix(bss, bssuf); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\tb := before\n\t\t_ = b\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go",
    "content": "package stringscutprefix\n\nimport (\n\t\"strings\"\n)\n\nvar (\n\ts, pre, suf string\n)\n\n// test supported cases of pattern 1 - CutPrefix\nfunc _() {\n\tif strings.HasPrefix(s, pre) { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := strings.TrimPrefix(s, pre)\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(\"\", \"\") { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := strings.TrimPrefix(\"\", \"\")\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(s, \"\") { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln([]byte(strings.TrimPrefix(s, \"\")))\n\t}\n\tif strings.HasPrefix(s, \"\") { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b := \"\", strings.TrimPrefix(s, \"\")\n\t\t_, _ = a, b\n\t}\n\tif strings.HasPrefix(s, \"\") { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b := strings.TrimPrefix(s, \"\"), strings.TrimPrefix(s, \"\") // only replace the first occurrence\n\t\ts = \"123\"\n\t\tb = strings.TrimPrefix(s, \"\") // only replace the first occurrence\n\t\t_, _ = a, b\n\t}\n\n\tvar a, b string\n\tif strings.HasPrefix(s, \"\") { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b = \"\", strings.TrimPrefix(s, \"\")\n\t\t_, _ = a, b\n\t}\n}\n\n// test basic cases for CutSuffix - only covering the key differences\nfunc _() {\n\tif strings.HasSuffix(s, suf) { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := strings.TrimSuffix(s, suf)\n\t\t_ = a\n\t}\n\tif strings.HasSuffix(s, \"\") { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln([]byte(strings.TrimSuffix(s, \"\")))\n\t}\n}\n\n// test cases that are not supported by pattern1 - CutPrefix\nfunc _() {\n\tok := strings.HasPrefix(\"\", \"\")\n\tif ok { // noop, currently it doesn't track the result usage of HasPrefix\n\t\ta := strings.TrimPrefix(\"\", \"\")\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(s, pre) {\n\t\ta := strings.TrimPrefix(\"\", \"\") // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(s, pre) {\n\t\tvar result string\n\t\tresult = strings.TrimPrefix(\"\", \"\") // noop, as we believe define is more popular.\n\t\t_ = result\n\t}\n\tif strings.HasPrefix(\"\", \"\") {\n\t\ta := strings.TrimPrefix(s, pre) // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n\tif s1 := s; strings.HasPrefix(s1, pre) {\n\t\ta := strings.TrimPrefix(s1, pre) // noop, as IfStmt.Init is present\n\t\t_ = a\n\t}\n}\n\n// test basic unsupported case for CutSuffix\nfunc _() {\n\tif strings.HasSuffix(s, suf) {\n\t\ta := strings.TrimSuffix(\"\", \"\") // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n}\n\nvar value0 string\n\n// test supported cases of pattern2 - CutPrefix\nfunc _() {\n\tif after := strings.TrimPrefix(s, pre); after != s { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after := strings.TrimPrefix(s, pre); s != after { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after := strings.TrimPrefix(s, pre); s != after { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(strings.TrimPrefix(s, pre)) // noop here\n\t}\n\tif after := strings.TrimPrefix(s, \"\"); s != after { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tvar ok bool                                          // define an ok variable to test the fix won't shadow it for its if stmt body\n\tif after := strings.TrimPrefix(s, pre); after != s { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\t_ = ok\n\t\tprintln(after)\n\t}\n\t_ = ok                                               // fine to shadow, since ok is not used within the ifstmt block\n\tif after := strings.TrimPrefix(s, pre); after != s { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tvar predefined string\n\tif predefined = strings.TrimPrefix(s, pre); s != predefined { // noop\n\t\tprintln(predefined)\n\t}\n\tif predefined = strings.TrimPrefix(s, pre); s != predefined { // noop\n\t\tprintln(&predefined)\n\t}\n\tvar value string\n\tif value = strings.TrimPrefix(s, pre); s != value { // noop\n\t\tprintln(value)\n\t}\n\tlhsMap := make(map[string]string)\n\tif lhsMap[\"\"] = strings.TrimPrefix(s, pre); s != lhsMap[\"\"] { // noop\n\t\tprintln(lhsMap[\"\"])\n\t}\n\tarr := make([]string, 0)\n\tif arr[0] = strings.TrimPrefix(s, pre); s != arr[0] { // noop\n\t\tprintln(arr[0])\n\t}\n\ttype example struct {\n\t\tfield string\n\t}\n\tvar e example\n\tif e.field = strings.TrimPrefix(s, pre); s != e.field { // noop\n\t\tprintln(e.field)\n\t}\n}\n\n// test basic cases for pattern2 - CutSuffix\nfunc _() {\n\tif before := strings.TrimSuffix(s, suf); before != s { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n\tif before := strings.TrimSuffix(s, suf); s != before { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n}\n\n// test cases that not supported by pattern2 - CutPrefix\nfunc _() {\n\tif after := strings.TrimPrefix(s, pre); s != pre { // noop\n\t\tprintln(after)\n\t}\n\tif after := strings.TrimPrefix(s, pre); after != pre { // noop\n\t\tprintln(after)\n\t}\n\tif strings.TrimPrefix(s, pre) != s {\n\t\tprintln(strings.TrimPrefix(s, pre))\n\t}\n}\n\n// test basic unsupported case for pattern2 - CutSuffix\nfunc _() {\n\tif before := strings.TrimSuffix(s, suf); s != suf { // noop\n\t\tprintln(before)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go.golden",
    "content": "package stringscutprefix\n\nimport (\n\t\"strings\"\n)\n\nvar (\n\ts, pre, suf string\n)\n\n// test supported cases of pattern 1 - CutPrefix\nfunc _() {\n\tif after, ok := strings.CutPrefix(s, pre); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n\tif after, ok := strings.CutPrefix(\"\", \"\"); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n\tif after, ok := strings.CutPrefix(s, \"\"); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln([]byte(after))\n\t}\n\tif after, ok := strings.CutPrefix(s, \"\"); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b := \"\", after\n\t\t_, _ = a, b\n\t}\n\tif after, ok := strings.CutPrefix(s, \"\"); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b := after, strings.TrimPrefix(s, \"\") // only replace the first occurrence\n\t\ts = \"123\"\n\t\tb = strings.TrimPrefix(s, \"\") // only replace the first occurrence\n\t\t_, _ = a, b\n\t}\n\n\tvar a, b string\n\tif after, ok := strings.CutPrefix(s, \"\"); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta, b = \"\", after\n\t\t_, _ = a, b\n\t}\n}\n\n// test basic cases for CutSuffix - only covering the key differences\nfunc _() {\n\tif before, ok := strings.CutSuffix(s, suf); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := before\n\t\t_ = a\n\t}\n\tif before, ok := strings.CutSuffix(s, \"\"); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln([]byte(before))\n\t}\n}\n\n// test cases that are not supported by pattern1 - CutPrefix\nfunc _() {\n\tok := strings.HasPrefix(\"\", \"\")\n\tif ok { // noop, currently it doesn't track the result usage of HasPrefix\n\t\ta := strings.TrimPrefix(\"\", \"\")\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(s, pre) {\n\t\ta := strings.TrimPrefix(\"\", \"\") // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n\tif strings.HasPrefix(s, pre) {\n\t\tvar result string\n\t\tresult = strings.TrimPrefix(\"\", \"\") // noop, as we believe define is more popular.\n\t\t_ = result\n\t}\n\tif strings.HasPrefix(\"\", \"\") {\n\t\ta := strings.TrimPrefix(s, pre) // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n\tif s1 := s; strings.HasPrefix(s1, pre) {\n\t\ta := strings.TrimPrefix(s1, pre) // noop, as IfStmt.Init is present\n\t\t_ = a\n\t}\n}\n\n// test basic unsupported case for CutSuffix\nfunc _() {\n\tif strings.HasSuffix(s, suf) {\n\t\ta := strings.TrimSuffix(\"\", \"\") // noop, as the argument isn't the same\n\t\t_ = a\n\t}\n}\n\nvar value0 string\n\n// test supported cases of pattern2 - CutPrefix\nfunc _() {\n\tif after, ok := strings.CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after, ok := strings.CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after, ok := strings.CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(strings.TrimPrefix(s, pre)) // noop here\n\t}\n\tif after, ok := strings.CutPrefix(s, \"\"); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tvar ok bool // define an ok variable to test the fix won't shadow it for its if stmt body\n\tif after, ok0 := strings.CutPrefix(s, pre); ok0 { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\t_ = ok\n\t\tprintln(after)\n\t}\n\t_ = ok                                               // fine to shadow, since ok is not used within the ifstmt block\n\tif after, ok := strings.CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tvar predefined string\n\tif predefined = strings.TrimPrefix(s, pre); s != predefined { // noop\n\t\tprintln(predefined)\n\t}\n\tif predefined = strings.TrimPrefix(s, pre); s != predefined { // noop\n\t\tprintln(&predefined)\n\t}\n\tvar value string\n\tif value = strings.TrimPrefix(s, pre); s != value { // noop\n\t\tprintln(value)\n\t}\n\tlhsMap := make(map[string]string)\n\tif lhsMap[\"\"] = strings.TrimPrefix(s, pre); s != lhsMap[\"\"] { // noop\n\t\tprintln(lhsMap[\"\"])\n\t}\n\tarr := make([]string, 0)\n\tif arr[0] = strings.TrimPrefix(s, pre); s != arr[0] { // noop\n\t\tprintln(arr[0])\n\t}\n\ttype example struct {\n\t\tfield string\n\t}\n\tvar e example\n\tif e.field = strings.TrimPrefix(s, pre); s != e.field { // noop\n\t\tprintln(e.field)\n\t}\n}\n\n// test basic cases for pattern2 - CutSuffix\nfunc _() {\n\tif before, ok := strings.CutSuffix(s, suf); ok { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n\tif before, ok := strings.CutSuffix(s, suf); ok { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n}\n\n// test cases that not supported by pattern2 - CutPrefix\nfunc _() {\n\tif after := strings.TrimPrefix(s, pre); s != pre { // noop\n\t\tprintln(after)\n\t}\n\tif after := strings.TrimPrefix(s, pre); after != pre { // noop\n\t\tprintln(after)\n\t}\n\tif strings.TrimPrefix(s, pre) != s {\n\t\tprintln(strings.TrimPrefix(s, pre))\n\t}\n}\n\n// test basic unsupported case for pattern2 - CutSuffix\nfunc _() {\n\tif before := strings.TrimSuffix(s, suf); s != suf { // noop\n\t\tprintln(before)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix_dot.go",
    "content": "package stringscutprefix\n\nimport (\n\t. \"strings\"\n)\n\n// test supported cases of pattern 1 - CutPrefix\nfunc _() {\n\tif HasPrefix(s, pre) { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := TrimPrefix(s, pre)\n\t\t_ = a\n\t}\n}\n\n// test supported cases of pattern 1 - CutSuffix\nfunc _() {\n\tif HasSuffix(s, suf) { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := TrimSuffix(s, suf)\n\t\t_ = a\n\t}\n}\n\n// test supported cases of pattern2 - CutPrefix\nfunc _() {\n\tif after := TrimPrefix(s, pre); after != s { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after := TrimPrefix(s, pre); s != after { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n}\n\n// test supported cases of pattern2 - CutSuffix\nfunc _() {\n\tif before := TrimSuffix(s, suf); before != s { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n\tif before := TrimSuffix(s, suf); s != before { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix_dot.go.golden",
    "content": "package stringscutprefix\n\nimport (\n\t. \"strings\"\n)\n\n// test supported cases of pattern 1 - CutPrefix\nfunc _() {\n\tif after, ok := CutPrefix(s, pre); ok { // want \"HasPrefix \\\\+ TrimPrefix can be simplified to CutPrefix\"\n\t\ta := after\n\t\t_ = a\n\t}\n}\n\n// test supported cases of pattern 1 - CutSuffix\nfunc _() {\n\tif before, ok := CutSuffix(s, suf); ok { // want \"HasSuffix \\\\+ TrimSuffix can be simplified to CutSuffix\"\n\t\ta := before\n\t\t_ = a\n\t}\n}\n\n// test supported cases of pattern2 - CutPrefix\nfunc _() {\n\tif after, ok := CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n\tif after, ok := CutPrefix(s, pre); ok { // want \"TrimPrefix can be simplified to CutPrefix\"\n\t\tprintln(after)\n\t}\n}\n\n// test supported cases of pattern2 - CutSuffix\nfunc _() {\n\tif before, ok := CutSuffix(s, suf); ok { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n\tif before, ok := CutSuffix(s, suf); ok { // want \"TrimSuffix can be simplified to CutSuffix\"\n\t\tprintln(before)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/testingcontext/testingcontext.go",
    "content": "package testingcontext\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/testingcontext/testingcontext_test.go",
    "content": "package testingcontext\n\nimport (\n\t\"context\"\n\n\t\"testing\"\n)\n\nfunc Test(t *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using t.Context\"\n\tdefer cancel()\n\t_ = ctx\n\n\tfunc() {\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. scope of defer is not the testing func.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t}()\n\n\t{\n\t\tctx, cancel := context.WithCancel(context.TODO()) // want \"context.WithCancel can be modernized using t.Context\"\n\t\tdefer cancel()\n\t\t_ = ctx\n\t\tvar t int // not in scope of the call to WithCancel\n\t\t_ = t\n\t}\n\n\t{\n\t\tctx := context.Background()\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. ctx is redeclared.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t}\n\n\t{\n\t\tvar t int\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. t is shadowed.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t\t_ = t\n\t}\n\n\tt.Run(\"subtest\", func(t2 *testing.T) {\n\t\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using t2.Context\"\n\t\tdefer cancel()\n\t\t_ = ctx\n\t})\n}\n\nfunc TestAlt(t2 *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using t2.Context\"\n\tdefer cancel()\n\t_ = ctx\n}\n\nfunc Testnot(t *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background()) // Nope. Not a test func.\n\tdefer cancel()\n\t_ = ctx\n}\n\nfunc Benchmark(b *testing.B) {\n\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using b.Context\"\n\tdefer cancel()\n\t_ = ctx\n\n\tb.Run(\"subtest\", func(b2 *testing.B) {\n\t\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using b2.Context\"\n\t\tdefer cancel()\n\t\t_ = ctx\n\t})\n}\n\nfunc Fuzz(f *testing.F) {\n\tctx, cancel := context.WithCancel(context.Background()) // want \"context.WithCancel can be modernized using f.Context\"\n\tdefer cancel()\n\t_ = ctx\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/testingcontext/testingcontext_test.go.golden",
    "content": "package testingcontext\n\nimport (\n\t\"context\"\n\n\t\"testing\"\n)\n\nfunc Test(t *testing.T) {\n\tctx := t.Context()\n\t_ = ctx\n\n\tfunc() {\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. scope of defer is not the testing func.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t}()\n\n\t{\n\t\tctx := t.Context()\n\t\t_ = ctx\n\t\tvar t int // not in scope of the call to WithCancel\n\t\t_ = t\n\t}\n\n\t{\n\t\tctx := context.Background()\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. ctx is redeclared.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t}\n\n\t{\n\t\tvar t int\n\t\tctx, cancel := context.WithCancel(context.Background()) // Nope. t is shadowed.\n\t\tdefer cancel()\n\t\t_ = ctx\n\t\t_ = t\n\t}\n\n\tt.Run(\"subtest\", func(t2 *testing.T) {\n\t\tctx := t2.Context()\n\t\t_ = ctx\n\t})\n}\n\nfunc TestAlt(t2 *testing.T) {\n\tctx := t2.Context()\n\t_ = ctx\n}\n\nfunc Testnot(t *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background()) // Nope. Not a test func.\n\tdefer cancel()\n\t_ = ctx\n}\n\nfunc Benchmark(b *testing.B) {\n\tctx := b.Context()\n\t_ = ctx\n\n\tb.Run(\"subtest\", func(b2 *testing.B) {\n\t\tctx := b2.Context()\n\t\t_ = ctx\n\t})\n}\n\nfunc Fuzz(f *testing.F) {\n\tctx := f.Context()\n\t_ = ctx\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/unsafefuncs/unsafefuncs.go",
    "content": "package unsafefuncs\n\nimport \"unsafe\"\n\nfunc _(ptr unsafe.Pointer) unsafe.Pointer {\n\treturn unsafe.Pointer(uintptr(ptr) + 1) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\ntype uP = unsafe.Pointer\n\nfunc _(ptr uP) uP {\n\treturn uP(uintptr(ptr) + 1) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\nfunc _(ptr unsafe.Pointer, n int) unsafe.Pointer {\n\treturn unsafe.Pointer(uintptr(ptr) + uintptr(n)) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\nfunc _(ptr *byte, len int) *byte {\n\treturn (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + uintptr(len))) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\ntype namedUP unsafe.Pointer\n\nfunc _(ptr namedUP) namedUP {\n\treturn namedUP(uintptr(ptr) + 1) // nope: Add does not accept named unsafe.Pointer types\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/unsafefuncs/unsafefuncs.go.golden",
    "content": "package unsafefuncs\n\nimport \"unsafe\"\n\nfunc _(ptr unsafe.Pointer) unsafe.Pointer {\n\treturn unsafe.Add(ptr, 1) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\ntype uP = unsafe.Pointer\n\nfunc _(ptr uP) uP {\n\treturn unsafe.Add(ptr, 1) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\nfunc _(ptr unsafe.Pointer, n int) unsafe.Pointer {\n\treturn unsafe.Add(ptr, n) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\nfunc _(ptr *byte, len int) *byte {\n\treturn (*byte)(unsafe.Add(unsafe.Pointer(ptr), len)) // want `pointer \\+ integer can be simplified using unsafe.Add`\n}\n\ntype namedUP unsafe.Pointer\n\nfunc _(ptr namedUP) namedUP {\n\treturn namedUP(uintptr(ptr) + 1) // nope: Add does not accept named unsafe.Pointer types\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup.go",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\n// supported case for pattern 1.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t}()\n\n\tfor range 10 {\n\t\twg.Add(1)\n\t\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\t\tdefer wg.Done()\n\t\t\tfmt.Println()\n\t\t}()\n\t}\n}\n\n// supported case for pattern 2.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\twg.Done()\n\t}()\n\n\tfor range 10 {\n\t\twg.Add(1)\n\t\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\t\tfmt.Println()\n\t\t\twg.Done()\n\t\t}()\n\t}\n}\n\n// this function puts some wrong usages but waitgroupgo modernizer will still offer fixes.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t\twg.Done()\n\t}()\n}\n\n// this function puts the unsupported cases of pattern 1.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {}()\n\n\twg.Add(1)\n\tgo func(i int) {\n\t\tdefer wg.Done()\n\t\tfmt.Println(i)\n\t}(1)\n\n\twg.Add(1)\n\tgo func() {\n\t\tfmt.Println()\n\t\tdefer wg.Done()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // noop: no wg.Done call inside function body.\n\t\tfmt.Println()\n\t}()\n\n\tgo func() { // noop: no Add call before this go stmt.\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(2) // noop: only support Add(1).\n\tgo func() {\n\t\tdefer wg.Done()\n\t}()\n\n\tvar wg1 sync.WaitGroup\n\twg1.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tdefer wg1.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1) // noop: function literal has return values, wg.Go requires func().\n\tgo func() int {\n\t\tdefer wg.Done()\n\t\treturn 0\n\t}()\n}\n\n// this function puts the unsupported cases of pattern 2.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\twg.Done()\n\t\tfmt.Println()\n\t}()\n\n\tgo func() { // noop: no Add call before this go stmt.\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\tvar wg1 sync.WaitGroup\n\twg1.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\twg.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tfmt.Println()\n\t\twg1.Done()\n\t}()\n\n\twg.Add(1) // noop: function literal has return values, wg.Go requires func().\n\tgo func() int {\n\t\tfmt.Println()\n\t\twg.Done()\n\t\treturn 0\n\t}()\n}\n\ntype Server struct {\n\twg sync.WaitGroup\n}\n\ntype ServerContainer struct {\n\tserv Server\n}\n\nfunc _() {\n\tvar s Server\n\ts.wg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t\ts.wg.Done()\n\t}()\n\n\tvar sc ServerContainer\n\tsc.serv.wg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t\tsc.serv.wg.Done()\n\t}()\n\n\tvar wg sync.WaitGroup\n\tarr := [1]*sync.WaitGroup{&wg}\n\tarr[0].Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t\tarr[0].Done()\n\t}()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup.go.golden",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\n// supported case for pattern 1.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t})\n\n\tfor range 10 {\n\t\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\t\tfmt.Println()\n\t\t})\n\t}\n}\n\n// supported case for pattern 2.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t})\n\n\tfor range 10 {\n\t\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\t\tfmt.Println()\n\t\t})\n\t}\n}\n\n// this function puts some wrong usages but waitgroupgo modernizer will still offer fixes.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t})\n}\n\n// this function puts the unsupported cases of pattern 1.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {}()\n\n\twg.Add(1)\n\tgo func(i int) {\n\t\tdefer wg.Done()\n\t\tfmt.Println(i)\n\t}(1)\n\n\twg.Add(1)\n\tgo func() {\n\t\tfmt.Println()\n\t\tdefer wg.Done()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // noop: no wg.Done call inside function body.\n\t\tfmt.Println()\n\t}()\n\n\tgo func() { // noop: no Add call before this go stmt.\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(2) // noop: only support Add(1).\n\tgo func() {\n\t\tdefer wg.Done()\n\t}()\n\n\tvar wg1 sync.WaitGroup\n\twg1.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tdefer wg1.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1) // noop: function literal has return values, wg.Go requires func().\n\tgo func() int {\n\t\tdefer wg.Done()\n\t\treturn 0\n\t}()\n}\n\n// this function puts the unsupported cases of pattern 2.\nfunc _() {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\twg.Done()\n\t\tfmt.Println()\n\t}()\n\n\tgo func() { // noop: no Add call before this go stmt.\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\tvar wg1 sync.WaitGroup\n\twg1.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n\n\twg.Add(1) // noop: Add and Done should be the same object.\n\tgo func() {\n\t\tfmt.Println()\n\t\twg1.Done()\n\t}()\n\n\twg.Add(1) // noop: function literal has return values, wg.Go requires func().\n\tgo func() int {\n\t\tfmt.Println()\n\t\twg.Done()\n\t\treturn 0\n\t}()\n}\n\ntype Server struct {\n\twg sync.WaitGroup\n}\n\ntype ServerContainer struct {\n\tserv Server\n}\n\nfunc _() {\n\tvar s Server\n\ts.wg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t})\n\n\tvar sc ServerContainer\n\tsc.serv.wg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t})\n\n\tvar wg sync.WaitGroup\n\tarr := [1]*sync.WaitGroup{&wg}\n\tarr[0].Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tprint()\n\t})\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup_alias.go",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\tsync1 \"sync\"\n)\n\nfunc _() {\n\tvar wg sync1.WaitGroup\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup_alias.go.golden",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\tsync1 \"sync\"\n)\n\nfunc _() {\n\tvar wg sync1.WaitGroup\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup_dot.go",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\t. \"sync\"\n)\n\n// supported case for pattern 1.\nfunc _() {\n\tvar wg WaitGroup\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tdefer wg.Done()\n\t\tfmt.Println()\n\t}()\n\n\twg.Add(1)\n\tgo func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t\twg.Done()\n\t}()\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/testdata/src/waitgroupgo/waitgroup_dot.go.golden",
    "content": "package waitgroup\n\nimport (\n\t\"fmt\"\n\t. \"sync\"\n)\n\n// supported case for pattern 1.\nfunc _() {\n\tvar wg WaitGroup\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n\n\twg.Go(func() { // want \"Goroutine creation can be simplified using WaitGroup.Go\"\n\t\tfmt.Println()\n\t})\n}"
  },
  {
    "path": "go/analysis/passes/modernize/testingcontext.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar TestingContextAnalyzer = &analysis.Analyzer{\n\tName: \"testingcontext\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"testingcontext\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: testingContext,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#testingcontext\",\n}\n\n// The testingContext pass replaces calls to context.WithCancel from within\n// tests to a use of testing.{T,B,F}.Context(), added in Go 1.24.\n//\n// Specifically, the testingContext pass suggests to replace:\n//\n//\tctx, cancel := context.WithCancel(context.Background()) // or context.TODO\n//\tdefer cancel()\n//\n// with:\n//\n//\tctx := t.Context()\n//\n// provided:\n//\n//   - ctx and cancel are declared by the assignment\n//   - the deferred call is the only use of cancel\n//   - the call is within a test or subtest function\n//   - the relevant testing.{T,B,F} is named and not shadowed at the call\nfunc testingContext(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo  = pass.TypesInfo\n\n\t\tcontextWithCancel = index.Object(\"context\", \"WithCancel\")\n\t)\n\ncalls:\n\tfor cur := range index.Calls(contextWithCancel) {\n\t\tcall := cur.Node().(*ast.CallExpr)\n\t\t// Have: context.WithCancel(...)\n\n\t\targ, ok := call.Args[0].(*ast.CallExpr)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif !typesinternal.IsFunctionNamed(typeutil.Callee(info, arg), \"context\", \"Background\", \"TODO\") {\n\t\t\tcontinue\n\t\t}\n\t\t// Have: context.WithCancel(context.{Background,TODO}())\n\n\t\tparent := cur.Parent()\n\t\tassign, ok := parent.Node().(*ast.AssignStmt)\n\t\tif !ok || assign.Tok != token.DEFINE {\n\t\t\tcontinue\n\t\t}\n\t\t// Have: a, b := context.WithCancel(context.{Background,TODO}())\n\n\t\t// Check that both a and b are declared, not redeclarations.\n\t\tvar lhs []types.Object\n\t\tfor _, expr := range assign.Lhs {\n\t\t\tid, ok := expr.(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\tcontinue calls\n\t\t\t}\n\t\t\tobj, ok := info.Defs[id]\n\t\t\tif !ok {\n\t\t\t\tcontinue calls\n\t\t\t}\n\t\t\tlhs = append(lhs, obj)\n\t\t}\n\n\t\tnext, ok := parent.NextSibling()\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tdefr, ok := next.Node().(*ast.DeferStmt)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tdeferId, ok := defr.Call.Fun.(*ast.Ident)\n\t\tif !ok || !soleUseIs(index, lhs[1], deferId) {\n\t\t\tcontinue // b is used elsewhere\n\t\t}\n\t\t// Have:\n\t\t// a, b := context.WithCancel(context.{Background,TODO}())\n\t\t// defer b()\n\n\t\t// Check that we are in a test func.\n\t\tvar testObj types.Object // relevant testing.{T,B,F}, or nil\n\t\tif curFunc, ok := enclosingFunc(cur); ok {\n\t\t\tswitch n := curFunc.Node().(type) {\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tif ek, idx := curFunc.ParentEdge(); ek == edge.CallExpr_Args && idx == 1 {\n\t\t\t\t\t// Have: call(..., func(...) { ...context.WithCancel(...)... })\n\t\t\t\t\tobj := typeutil.Callee(info, curFunc.Parent().Node().(*ast.CallExpr))\n\t\t\t\t\tif (typesinternal.IsMethodNamed(obj, \"testing\", \"T\", \"Run\") ||\n\t\t\t\t\t\ttypesinternal.IsMethodNamed(obj, \"testing\", \"B\", \"Run\")) &&\n\t\t\t\t\t\tlen(n.Type.Params.List[0].Names) == 1 {\n\n\t\t\t\t\t\t// Have tb.Run(..., func(..., tb *testing.[TB]) { ...context.WithCancel(...)... }\n\t\t\t\t\t\ttestObj = info.Defs[n.Type.Params.List[0].Names[0]]\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\ttestObj = isTestFn(info, n)\n\t\t\t}\n\t\t}\n\t\tif testObj != nil && analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(cur), versions.Go1_24) {\n\t\t\t// Have a test function. Check that we can resolve the relevant\n\t\t\t// testing.{T,B,F} at the current position.\n\t\t\tif _, obj := lhs[0].Parent().LookupParent(testObj.Name(), lhs[0].Pos()); obj == testObj {\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\tMessage: fmt.Sprintf(\"context.WithCancel can be modernized using %s.Context\", testObj.Name()),\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"Replace context.WithCancel with %s.Context\", testObj.Name()),\n\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\tPos:     assign.Pos(),\n\t\t\t\t\t\t\tEnd:     defr.End(),\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s := %s.Context()\", lhs[0].Name(), testObj.Name()),\n\t\t\t\t\t\t}},\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// soleUseIs reports whether id is the sole Ident that uses obj.\n// (It returns false if there were no uses of obj.)\nfunc soleUseIs(index *typeindex.Index, obj types.Object, id *ast.Ident) bool {\n\tempty := true\n\tfor use := range index.Uses(obj) {\n\t\tempty = false\n\t\tif use.Node() != id {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn !empty\n}\n\n// isTestFn checks whether fn is a test function (TestX, BenchmarkX, FuzzX),\n// returning the corresponding types.Object of the *testing.{T,B,F} argument.\n// Returns nil if fn is a test function, but the testing.{T,B,F} argument is\n// unnamed (or _).\n//\n// TODO(rfindley): consider handling the case of an unnamed argument, by adding\n// an edit to give the argument a name.\n//\n// Adapted from go/analysis/passes/tests.\n// TODO(rfindley): consider refactoring to share logic.\nfunc isTestFn(info *types.Info, fn *ast.FuncDecl) types.Object {\n\t// Want functions with 0 results and 1 parameter.\n\tif fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||\n\t\tfn.Type.Params == nil ||\n\t\tlen(fn.Type.Params.List) != 1 ||\n\t\tlen(fn.Type.Params.List[0].Names) != 1 {\n\n\t\treturn nil\n\t}\n\n\tprefix := testKind(fn.Name.Name)\n\tif prefix == \"\" {\n\t\treturn nil\n\t}\n\n\tif tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 {\n\t\treturn nil // test functions must not be generic\n\t}\n\n\tobj := info.Defs[fn.Type.Params.List[0].Names[0]]\n\tif obj == nil {\n\t\treturn nil // e.g. _ *testing.T\n\t}\n\n\tvar name string\n\tswitch prefix {\n\tcase \"Test\":\n\t\tname = \"T\"\n\tcase \"Benchmark\":\n\t\tname = \"B\"\n\tcase \"Fuzz\":\n\t\tname = \"F\"\n\t}\n\n\tif !typesinternal.IsPointerToNamed(obj.Type(), \"testing\", name) {\n\t\treturn nil\n\t}\n\treturn obj\n}\n\n// testKind returns \"Test\", \"Benchmark\", or \"Fuzz\" if name is a valid resp.\n// test, benchmark, or fuzz function name. Otherwise, isTestName returns \"\".\n//\n// Adapted from go/analysis/passes/tests.isTestName.\nfunc testKind(name string) string {\n\tvar prefix string\n\tswitch {\n\tcase strings.HasPrefix(name, \"Test\"):\n\t\tprefix = \"Test\"\n\tcase strings.HasPrefix(name, \"Benchmark\"):\n\t\tprefix = \"Benchmark\"\n\tcase strings.HasPrefix(name, \"Fuzz\"):\n\t\tprefix = \"Fuzz\"\n\t}\n\tif prefix == \"\" {\n\t\treturn \"\"\n\t}\n\tsuffix := name[len(prefix):]\n\tif len(suffix) == 0 {\n\t\t// \"Test\" is ok.\n\t\treturn prefix\n\t}\n\tr, _ := utf8.DecodeRuneInString(suffix)\n\tif unicode.IsLower(r) {\n\t\treturn \"\"\n\t}\n\treturn prefix\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/unsafefuncs.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// TODO(adonovan): also support:\n//\n// func String(ptr *byte, len IntegerType) string\n// func StringData(str string) *byte\n// func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType\n// func SliceData(slice []ArbitraryType) *ArbitraryType\n\nvar unsafeFuncsAnalyzer = &analysis.Analyzer{\n\tName:     \"unsafefuncs\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unsafefuncs\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      unsafefuncs,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs\",\n}\n\nfunc init() {\n\t// Export to gopls until this is a published modernizer.\n\tgoplsexport.UnsafeFuncsModernizer = unsafeFuncsAnalyzer\n}\n\nfunc unsafefuncs(pass *analysis.Pass) (any, error) {\n\t// Short circuit if the package doesn't use unsafe.\n\t// (In theory one could use some imported alias of unsafe.Pointer,\n\t// but let's ignore that.)\n\tif !typesinternal.Imports(pass.Pkg, \"unsafe\") {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tinspect        = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tinfo           = pass.TypesInfo\n\t\ttUnsafePointer = types.Typ[types.UnsafePointer]\n\t)\n\n\t// isConversion reports whether e is a conversion T(x).\n\t// If so, it returns T and x.\n\tisConversion := func(curExpr inspector.Cursor) (t types.Type, x inspector.Cursor) {\n\t\te := curExpr.Node().(ast.Expr)\n\t\tif conv, ok := ast.Unparen(e).(*ast.CallExpr); ok && len(conv.Args) == 1 {\n\t\t\tif tv := pass.TypesInfo.Types[conv.Fun]; tv.IsType() {\n\t\t\t\treturn tv.Type, curExpr.ChildAt(edge.CallExpr_Args, 0)\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\t// The general form is where ptr and the result are of type unsafe.Pointer:\n\t//\n\t// \tunsafe.Pointer(uintptr(ptr) + uintptr(n))\n\t// =>\n\t// \tunsafe.Add(ptr, n)\n\n\t// Search for 'unsafe.Pointer(uintptr + uintptr)'\n\t// where the left operand was converted from a pointer.\n\t//\n\t// (Start from sum, not conversion, as it is not\n\t// uncommon to use a local type alias for unsafe.Pointer.)\n\tfor curSum := range inspect.Root().Preorder((*ast.BinaryExpr)(nil)) {\n\t\tif sum, ok := curSum.Node().(*ast.BinaryExpr); ok &&\n\t\t\tsum.Op == token.ADD &&\n\t\t\ttypes.Identical(info.TypeOf(sum.X), types.Typ[types.Uintptr]) &&\n\t\t\tcurSum.ParentEdgeKind() == edge.CallExpr_Args {\n\t\t\t// Have: sum ≡ T(x:...uintptr... + y:...uintptr...)\n\t\t\tcurX := curSum.ChildAt(edge.BinaryExpr_X, -1)\n\t\t\tcurY := curSum.ChildAt(edge.BinaryExpr_Y, -1)\n\n\t\t\t// Is sum converted to unsafe.Pointer?\n\t\t\tcurResult := curSum.Parent()\n\t\t\tif t, _ := isConversion(curResult); !(t != nil && types.Identical(t, tUnsafePointer)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Have: result ≡ unsafe.Pointer(x:...uintptr... + y:...uintptr...)\n\n\t\t\t// Is sum.x converted from unsafe.Pointer?\n\t\t\t_, curPtr := isConversion(curX)\n\t\t\tif !curPtr.Valid() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tptr := curPtr.Node().(ast.Expr)\n\t\t\tif !types.Identical(info.TypeOf(ptr), tUnsafePointer) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Have: result ≡ unsafe.Pointer(x:uintptr(...unsafe.Pointer...) + y:...uintptr...)\n\n\t\t\tfile := astutil.EnclosingFile(curSum)\n\t\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_17) {\n\t\t\t\tcontinue // unsafe.Add not available in this file\n\t\t\t}\n\n\t\t\t// import \"unsafe\"\n\t\t\tunsafedot, edits := refactor.AddImport(info, file, \"unsafe\", \"unsafe\", \"Add\", sum.Pos())\n\n\t\t\t// unsafe.Pointer(x + y)\n\t\t\t// ---------------     -\n\t\t\t//                x + y\n\t\t\tedits = append(edits, deleteConv(curResult)...)\n\n\t\t\t// uintptr   (ptr) + offset\n\t\t\t// -----------   ----      -\n\t\t\t// unsafe.Add(ptr,   offset)\n\t\t\tedits = append(edits, []analysis.TextEdit{\n\t\t\t\t{\n\t\t\t\t\tPos:     sum.Pos(),\n\t\t\t\t\tEnd:     ptr.Pos(),\n\t\t\t\t\tNewText: fmt.Appendf(nil, \"%sAdd(\", unsafedot),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos:     ptr.End(),\n\t\t\t\t\tEnd:     sum.Y.Pos(),\n\t\t\t\t\tNewText: []byte(\", \"),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos:     sum.Y.End(),\n\t\t\t\t\tEnd:     sum.Y.End(),\n\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t},\n\t\t\t}...)\n\n\t\t\t// Variant: sum.y operand was converted from another integer type.\n\t\t\t// Discard the conversion, as Add is generic over integers.\n\t\t\t//\n\t\t\t// e.g. unsafe.Pointer(uintptr(ptr) + uintptr(len(s)))\n\t\t\t//                                    --------      -\n\t\t\t//      unsafe.Add    (        ptr,           len(s))\n\t\t\tif t, _ := isConversion(curY); t != nil && isInteger(t) {\n\t\t\t\tedits = append(edits, deleteConv(curY)...)\n\t\t\t}\n\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     sum.Pos(),\n\t\t\t\tEnd:     sum.End(),\n\t\t\t\tMessage: \"pointer + integer can be simplified using unsafe.Add\",\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   \"Simplify pointer addition using unsafe.Add\",\n\t\t\t\t\tTextEdits: edits,\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\n// deleteConv returns edits for changing T(x) to x, respecting precedence.\nfunc deleteConv(cur inspector.Cursor) []analysis.TextEdit {\n\tconv := cur.Node().(*ast.CallExpr)\n\n\tusesPrec := func(n ast.Node) bool {\n\t\tswitch n.(type) {\n\t\tcase *ast.BinaryExpr, *ast.UnaryExpr:\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\t// Be careful not to change precedence of e.g. T(1+2) * 3.\n\t// TODO(adonovan): refine this.\n\tif usesPrec(cur.Parent().Node()) && usesPrec(conv.Args[0]) {\n\t\t// T(x+y) * z\n\t\t// -\n\t\t//  (x+y) * z\n\t\treturn []analysis.TextEdit{{\n\t\t\tPos: conv.Fun.Pos(),\n\t\t\tEnd: conv.Fun.End(),\n\t\t}}\n\t}\n\n\t// T(x)\n\t// -- -\n\t//   x\n\treturn []analysis.TextEdit{\n\t\t{\n\t\t\tPos: conv.Pos(),\n\t\t\tEnd: conv.Args[0].Pos(),\n\t\t},\n\t\t{\n\t\t\tPos: conv.Args[0].End(),\n\t\t\tEnd: conv.End(),\n\t\t},\n\t}\n}\n\nfunc isInteger(t types.Type) bool {\n\tbasic, ok := t.Underlying().(*types.Basic)\n\treturn ok && basic.Info()&types.IsInteger != 0\n}\n"
  },
  {
    "path": "go/analysis/passes/modernize/waitgroupgo.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modernize\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar WaitGroupGoAnalyzer = &analysis.Analyzer{\n\tName: \"waitgroupgo\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"waitgroupgo\"),\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t\ttypeindexanalyzer.Analyzer,\n\t},\n\tRun: waitgroup,\n\tURL: \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#waitgroupgo\",\n}\n\n// The waitgroupgo pass replaces old more complex code with\n// go1.25 added API WaitGroup.Go.\n//\n// Patterns:\n//\n//  1. wg.Add(1); go func() { defer wg.Done(); ... }()\n//     =>\n//     wg.Go(go func() { ... })\n//\n//  2. wg.Add(1); go func() { ...; wg.Done() }()\n//     =>\n//     wg.Go(go func() { ... })\n//\n// The wg.Done must occur within the first statement of the block in a\n// defer format or last statement of the block, and the offered fix\n// only removes the first/last wg.Done call. It doesn't fix existing\n// wrong usage of sync.WaitGroup.\n//\n// The use of WaitGroup.Go in pattern 1 implicitly introduces a\n// 'defer', which may change the behavior in the case of panic from\n// the \"...\" logic. In this instance, the change is safe: before and\n// after the transformation, an unhandled panic inevitably results in\n// a fatal crash. The fact that the transformed code calls wg.Done()\n// before the crash doesn't materially change anything. (If Done had\n// other effects, or blocked, or if WaitGroup.Go propagated panics\n// from child to parent goroutine, the argument would be different.)\nfunc waitgroup(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tindex             = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo              = pass.TypesInfo\n\t\tsyncWaitGroupAdd  = index.Selection(\"sync\", \"WaitGroup\", \"Add\")\n\t\tsyncWaitGroupDone = index.Selection(\"sync\", \"WaitGroup\", \"Done\")\n\t)\n\tif !index.Used(syncWaitGroupDone) {\n\t\treturn nil, nil\n\t}\n\n\tfor curAddCall := range index.Calls(syncWaitGroupAdd) {\n\t\t// Extract receiver from wg.Add call.\n\t\taddCall := curAddCall.Node().(*ast.CallExpr)\n\t\tif !isIntLiteral(info, addCall.Args[0], 1) {\n\t\t\tcontinue // not a call to wg.Add(1)\n\t\t}\n\t\t// Inv: the Args[0] check ensures addCall is not of\n\t\t// the form sync.WaitGroup.Add(&wg, 1).\n\t\taddCallRecv := ast.Unparen(addCall.Fun).(*ast.SelectorExpr).X\n\n\t\t// Following statement must be go func() { ... } ().\n\t\tcurAddStmt := curAddCall.Parent()\n\t\tif !is[*ast.ExprStmt](curAddStmt.Node()) {\n\t\t\tcontinue // unnecessary parens?\n\t\t}\n\t\tcurNext, ok := curAddCall.Parent().NextSibling()\n\t\tif !ok {\n\t\t\tcontinue // no successor\n\t\t}\n\t\tgoStmt, ok := curNext.Node().(*ast.GoStmt)\n\t\tif !ok {\n\t\t\tcontinue // not a go stmt\n\t\t}\n\t\tlit, ok := goStmt.Call.Fun.(*ast.FuncLit)\n\t\tif !ok || len(goStmt.Call.Args) != 0 {\n\t\t\tcontinue // go argument is not func(){...}()\n\t\t}\n\t\tif lit.Type.Results != nil && len(lit.Type.Results.List) > 0 {\n\t\t\tcontinue // function literal has return values; wg.Go requires func()\n\t\t}\n\t\tlist := lit.Body.List\n\t\tif len(list) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Body must start with \"defer wg.Done()\" or end with \"wg.Done()\".\n\t\tvar doneStmt ast.Stmt\n\t\tif deferStmt, ok := list[0].(*ast.DeferStmt); ok &&\n\t\t\ttypeutil.Callee(info, deferStmt.Call) == syncWaitGroupDone &&\n\t\t\tastutil.EqualSyntax(ast.Unparen(deferStmt.Call.Fun).(*ast.SelectorExpr).X, addCallRecv) {\n\t\t\tdoneStmt = deferStmt // \"defer wg.Done()\"\n\n\t\t} else if lastStmt, ok := list[len(list)-1].(*ast.ExprStmt); ok {\n\t\t\tif doneCall, ok := lastStmt.X.(*ast.CallExpr); ok &&\n\t\t\t\ttypeutil.Callee(info, doneCall) == syncWaitGroupDone &&\n\t\t\t\tastutil.EqualSyntax(ast.Unparen(doneCall.Fun).(*ast.SelectorExpr).X, addCallRecv) {\n\t\t\t\tdoneStmt = lastStmt // \"wg.Done()\"\n\t\t\t}\n\t\t}\n\t\tif doneStmt == nil {\n\t\t\tcontinue\n\t\t}\n\t\tcurDoneStmt, ok := curNext.FindNode(doneStmt)\n\t\tif !ok {\n\t\t\tpanic(\"can't find Cursor for 'done' statement\")\n\t\t}\n\n\t\tfile := astutil.EnclosingFile(curAddCall)\n\t\tif !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_25) {\n\t\t\tcontinue\n\t\t}\n\t\ttokFile := pass.Fset.File(file.Pos())\n\n\t\tvar addCallRecvText bytes.Buffer\n\t\terr := printer.Fprint(&addCallRecvText, pass.Fset, addCallRecv)\n\t\tif err != nil {\n\t\t\tcontinue // error getting text for the edit\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\t// go func() {\n\t\t\t// ~~~~~~~~~\n\t\t\tPos:     goStmt.Pos(),\n\t\t\tEnd:     lit.Type.End(),\n\t\t\tMessage: \"Goroutine creation can be simplified using WaitGroup.Go\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Simplify by using WaitGroup.Go\",\n\t\t\t\tTextEdits: slices.Concat(\n\t\t\t\t\t// delete \"wg.Add(1)\"\n\t\t\t\t\trefactor.DeleteStmt(tokFile, curAddStmt),\n\t\t\t\t\t// delete \"wg.Done()\" or \"defer wg.Done()\"\n\t\t\t\t\trefactor.DeleteStmt(tokFile, curDoneStmt),\n\t\t\t\t\t[]analysis.TextEdit{\n\t\t\t\t\t\t// go    func()\n\t\t\t\t\t\t// ------\n\t\t\t\t\t\t// wg.Go(func()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos:     goStmt.Pos(),\n\t\t\t\t\t\t\tEnd:     goStmt.Call.Pos(),\n\t\t\t\t\t\t\tNewText: fmt.Appendf(nil, \"%s.Go(\", addCallRecvText.String()),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// ... }()\n\t\t\t\t\t\t//      -\n\t\t\t\t\t\t// ... } )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPos: goStmt.Call.Lparen,\n\t\t\t\t\t\t\tEnd: goStmt.Call.Rparen,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/nilfunc/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package nilfunc defines an Analyzer that checks for useless\n// comparisons against nil.\n//\n// # Analyzer nilfunc\n//\n// nilfunc: check for useless comparisons between functions and nil\n//\n// A useless comparison is one like f == nil as opposed to f() == nil.\npackage nilfunc\n"
  },
  {
    "path": "go/analysis/passes/nilfunc/nilfunc.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package nilfunc defines an Analyzer that checks for useless\n// comparisons against nil.\npackage nilfunc\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"nilfunc\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"nilfunc\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.BinaryExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\te := n.(*ast.BinaryExpr)\n\n\t\t// Only want == or != comparisons.\n\t\tif e.Op != token.EQL && e.Op != token.NEQ {\n\t\t\treturn\n\t\t}\n\n\t\t// Only want comparisons with a nil identifier on one side.\n\t\tvar e2 ast.Expr\n\t\tswitch {\n\t\tcase pass.TypesInfo.Types[e.X].IsNil():\n\t\t\te2 = e.Y\n\t\tcase pass.TypesInfo.Types[e.Y].IsNil():\n\t\t\te2 = e.X\n\t\tdefault:\n\t\t\treturn\n\t\t}\n\n\t\t// Only want functions.\n\t\tobj := pass.TypesInfo.Uses[typesinternal.UsedIdent(pass.TypesInfo, e2)]\n\t\tif _, ok := obj.(*types.Func); !ok {\n\t\t\treturn\n\t\t}\n\n\t\tpass.ReportRangef(e, \"comparison of function %v %v nil is always %v\", obj.Name(), e.Op, e.Op == token.NEQ)\n\t})\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/nilfunc/nilfunc_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nilfunc_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/nilfunc\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, nilfunc.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/nilfunc/testdata/src/a/a.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nfunc F() {}\n\ntype T struct {\n\tF func()\n}\n\nfunc (T) M() {}\n\nvar Fv = F\n\nfunc Comparison() {\n\tvar t T\n\tvar fn func()\n\tif fn == nil || Fv == nil || t.F == nil {\n\t\t// no error; these func vars or fields may be nil\n\t}\n\tif F == nil { // want \"comparison of function F == nil is always false\"\n\t\tpanic(\"can't happen\")\n\t}\n\tif t.M == nil { // want \"comparison of function M == nil is always false\"\n\t\tpanic(\"can't happen\")\n\t}\n\tif F != nil { // want \"comparison of function F != nil is always true\"\n\t\tif t.M != nil { // want \"comparison of function M != nil is always true\"\n\t\t\treturn\n\t\t}\n\t}\n\tpanic(\"can't happen\")\n}\n"
  },
  {
    "path": "go/analysis/passes/nilfunc/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the lostcancel checker.\n\npackage typeparams\n\nfunc f[P any]() {}\n\nfunc g[P1 any, P2 any](x P1) {}\n\nvar f1 = f[int]\n\ntype T1[P any] struct {\n\tf func() P\n}\n\ntype T2[P1 any, P2 any] struct {\n\tg func(P1) P2\n}\n\nfunc Comparison[P any](f2 func() T1[P]) {\n\tvar t1 T1[P]\n\tvar t2 T2[P, int]\n\tvar fn func()\n\tif fn == nil || f1 == nil || f2 == nil || t1.f == nil || t2.g == nil {\n\t\t// no error; these func vars or fields may be nil\n\t}\n\tif f[P] == nil { // want \"comparison of function f == nil is always false\"\n\t\tpanic(\"can't happen\")\n\t}\n\tif f[int] == nil { // want \"comparison of function f == nil is always false\"\n\t\tpanic(\"can't happen\")\n\t}\n\tif g[P, int] == nil { // want \"comparison of function g == nil is always false\"\n\t\tpanic(\"can't happen\")\n\t}\n}\n\nfunc Index[P any](a [](func() P)) {\n\tif a[1] == nil {\n\t\t// no error\n\t}\n\tvar t1 []T1[P]\n\tvar t2 [][]T2[P, P]\n\tif t1[1].f == nil || t2[0][1].g == nil {\n\t\t// no error\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/cmd/nilness/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The nilness command applies the golang.org/x/tools/go/analysis/passes/nilness\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/nilness\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(nilness.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/nilness/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package nilness inspects the control-flow graph of an SSA function\n// and reports errors such as nil pointer dereferences and degenerate\n// nil pointer comparisons.\n//\n// # Analyzer nilness\n//\n// nilness: check for redundant or impossible nil comparisons\n//\n// The nilness checker inspects the control-flow graph of each function in\n// a package and reports nil pointer dereferences, degenerate nil\n// pointers, and panics with nil values. A degenerate comparison is of the form\n// x==nil or x!=nil where x is statically known to be nil or non-nil. These are\n// often a mistake, especially in control flow related to errors. Panics with nil\n// values are checked because they are not detectable by\n//\n//\tif r := recover(); r != nil {\n//\n// This check reports conditions such as:\n//\n//\tif f == nil { // impossible condition (f is a function)\n//\t}\n//\n// and:\n//\n//\tp := &v\n//\t...\n//\tif p != nil { // tautological condition\n//\t}\n//\n// and:\n//\n//\tif p == nil {\n//\t\tprint(*p) // nil dereference\n//\t}\n//\n// and:\n//\n//\tif p == nil {\n//\t\tpanic(p)\n//\t}\n//\n// Sometimes the control flow may be quite complex, making bugs hard\n// to spot. In the example below, the err.Error expression is\n// guaranteed to panic because, after the first return, err must be\n// nil. The intervening loop is just a distraction.\n//\n//\t...\n//\terr := g.Wait()\n//\tif err != nil {\n//\t\treturn err\n//\t}\n//\tpartialSuccess := false\n//\tfor _, err := range errs {\n//\t\tif err == nil {\n//\t\t\tpartialSuccess = true\n//\t\t\tbreak\n//\t\t}\n//\t}\n//\tif partialSuccess {\n//\t\treportStatus(StatusMessage{\n//\t\t\tCode:   code.ERROR,\n//\t\t\tDetail: err.Error(), // \"nil dereference in dynamic method call\"\n//\t\t})\n//\t\treturn nil\n//\t}\n//\n// ...\npackage nilness\n"
  },
  {
    "path": "go/analysis/passes/nilness/nilness.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nilness\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/buildssa\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"nilness\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"nilness\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilness\",\n\tRun:      run,\n\tRequires: []*analysis.Analyzer{buildssa.Analyzer},\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tssainput := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)\n\tfor _, fn := range ssainput.SrcFuncs {\n\t\trunFunc(pass, fn)\n\t}\n\treturn nil, nil\n}\n\nfunc runFunc(pass *analysis.Pass, fn *ssa.Function) {\n\treportf := func(category string, pos token.Pos, format string, args ...any) {\n\t\t// We ignore nil-checking ssa.Instructions\n\t\t// that don't correspond to syntax.\n\t\tif pos.IsValid() {\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:      pos,\n\t\t\t\tCategory: category,\n\t\t\t\tMessage:  fmt.Sprintf(format, args...),\n\t\t\t})\n\t\t}\n\t}\n\n\t// notNil reports an error if v is provably nil.\n\tnotNil := func(stack []fact, instr ssa.Instruction, v ssa.Value, descr string) {\n\t\tif nilnessOf(stack, v) == isnil {\n\t\t\treportf(\"nilderef\", instr.Pos(), \"%s\", descr)\n\t\t}\n\t}\n\n\t// visit visits reachable blocks of the CFG in dominance order,\n\t// maintaining a stack of dominating nilness facts.\n\t//\n\t// By traversing the dom tree, we can pop facts off the stack as\n\t// soon as we've visited a subtree.  Had we traversed the CFG,\n\t// we would need to retain the set of facts for each block.\n\tseen := make([]bool, len(fn.Blocks)) // seen[i] means visit should ignore block i\n\tvar visit func(b *ssa.BasicBlock, stack []fact)\n\tvisit = func(b *ssa.BasicBlock, stack []fact) {\n\t\tif seen[b.Index] {\n\t\t\treturn\n\t\t}\n\t\tseen[b.Index] = true\n\n\t\t// Report nil dereferences.\n\t\tfor _, instr := range b.Instrs {\n\t\t\tswitch instr := instr.(type) {\n\t\t\tcase ssa.CallInstruction:\n\t\t\t\t// A nil receiver may be okay for type params.\n\t\t\t\tcc := instr.Common()\n\t\t\t\tif !(cc.IsInvoke() && typeparams.IsTypeParam(cc.Value.Type())) {\n\t\t\t\t\tnotNil(stack, instr, cc.Value, \"nil dereference in \"+cc.Description())\n\t\t\t\t}\n\t\t\tcase *ssa.FieldAddr:\n\t\t\t\tnotNil(stack, instr, instr.X, \"nil dereference in field selection\")\n\t\t\tcase *ssa.IndexAddr:\n\t\t\t\tswitch typeparams.CoreType(instr.X.Type()).(type) {\n\t\t\t\tcase *types.Pointer: // *array\n\t\t\t\t\tnotNil(stack, instr, instr.X, \"nil dereference in array index operation\")\n\t\t\t\tcase *types.Slice:\n\t\t\t\t\t// This is not necessarily a runtime error, because\n\t\t\t\t\t// it is usually dominated by a bounds check.\n\t\t\t\t\tif isRangeIndex(instr) {\n\t\t\t\t\t\tnotNil(stack, instr, instr.X, \"range of nil slice\")\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnotNil(stack, instr, instr.X, \"index of nil slice\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *ssa.MapUpdate:\n\t\t\t\tnotNil(stack, instr, instr.Map, \"nil dereference in map update\")\n\t\t\tcase *ssa.Range:\n\t\t\t\t// (Not a runtime error, but a likely mistake.)\n\t\t\t\tnotNil(stack, instr, instr.X, \"range over nil map\")\n\t\t\tcase *ssa.Slice:\n\t\t\t\t// A nilcheck occurs in ptr[:] iff ptr is a pointer to an array.\n\t\t\t\tif is[*types.Pointer](instr.X.Type().Underlying()) {\n\t\t\t\t\tnotNil(stack, instr, instr.X, \"nil dereference in slice operation\")\n\t\t\t\t}\n\t\t\tcase *ssa.Store:\n\t\t\t\tnotNil(stack, instr, instr.Addr, \"nil dereference in store\")\n\t\t\tcase *ssa.TypeAssert:\n\t\t\t\tif !instr.CommaOk {\n\t\t\t\t\tnotNil(stack, instr, instr.X, \"nil dereference in type assertion\")\n\t\t\t\t}\n\t\t\tcase *ssa.UnOp:\n\t\t\t\tswitch instr.Op {\n\t\t\t\tcase token.MUL: // *X\n\t\t\t\t\tnotNil(stack, instr, instr.X, \"nil dereference in load\")\n\t\t\t\tcase token.ARROW: // <-ch\n\t\t\t\t\t// (Not a runtime error, but a likely mistake.)\n\t\t\t\t\tnotNil(stack, instr, instr.X, \"receive from nil channel\")\n\t\t\t\t}\n\t\t\tcase *ssa.Send:\n\t\t\t\t// (Not a runtime error, but a likely mistake.)\n\t\t\t\tnotNil(stack, instr, instr.Chan, \"send to nil channel\")\n\t\t\t}\n\t\t}\n\n\t\t// Look for panics with nil value\n\t\tfor _, instr := range b.Instrs {\n\t\t\tswitch instr := instr.(type) {\n\t\t\tcase *ssa.Panic:\n\t\t\t\tif nilnessOf(stack, instr.X) == isnil {\n\t\t\t\t\treportf(\"nilpanic\", instr.Pos(), \"panic with nil value\")\n\t\t\t\t}\n\t\t\tcase *ssa.SliceToArrayPointer:\n\t\t\t\tnn := nilnessOf(stack, instr.X)\n\t\t\t\tif nn == isnil && slice2ArrayPtrLen(instr) > 0 {\n\t\t\t\t\treportf(\"conversionpanic\", instr.Pos(), \"nil slice being cast to an array of len > 0 will always panic\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// For nil comparison blocks, report an error if the condition\n\t\t// is degenerate, and push a nilness fact on the stack when\n\t\t// visiting its true and false successor blocks.\n\t\tif binop, tsucc, fsucc := eq(b); binop != nil {\n\t\t\txnil := nilnessOf(stack, binop.X)\n\t\t\tynil := nilnessOf(stack, binop.Y)\n\n\t\t\tif ynil != unknown && xnil != unknown && (xnil == isnil || ynil == isnil) {\n\t\t\t\t// Degenerate condition:\n\t\t\t\t// the nilness of both operands is known,\n\t\t\t\t// and at least one of them is nil.\n\t\t\t\tvar adj string\n\t\t\t\tif (xnil == ynil) == (binop.Op == token.EQL) {\n\t\t\t\t\tadj = \"tautological\"\n\t\t\t\t} else {\n\t\t\t\t\tadj = \"impossible\"\n\t\t\t\t}\n\t\t\t\treportf(\"cond\", binop.Pos(), \"%s condition: %s %s %s\", adj, xnil, binop.Op, ynil)\n\n\t\t\t\t// If tsucc's or fsucc's sole incoming edge is impossible,\n\t\t\t\t// it is unreachable.  Prune traversal of it and\n\t\t\t\t// all the blocks it dominates.\n\t\t\t\t// (We could be more precise with full dataflow\n\t\t\t\t// analysis of control-flow joins.)\n\t\t\t\tvar skip *ssa.BasicBlock\n\t\t\t\tif xnil == ynil {\n\t\t\t\t\tskip = fsucc\n\t\t\t\t} else {\n\t\t\t\t\tskip = tsucc\n\t\t\t\t}\n\t\t\t\tfor _, d := range b.Dominees() {\n\t\t\t\t\tif d == skip && len(d.Preds) == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tvisit(d, stack)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// \"if x == nil\" or \"if nil == y\" condition; x, y are unknown.\n\t\t\tif xnil == isnil || ynil == isnil {\n\t\t\t\tvar newFacts facts\n\t\t\t\tif xnil == isnil {\n\t\t\t\t\t// x is nil, y is unknown:\n\t\t\t\t\t// t successor learns y is nil.\n\t\t\t\t\tnewFacts = expandFacts(fact{binop.Y, isnil})\n\t\t\t\t} else {\n\t\t\t\t\t// y is nil, x is unknown:\n\t\t\t\t\t// t successor learns x is nil.\n\t\t\t\t\tnewFacts = expandFacts(fact{binop.X, isnil})\n\t\t\t\t}\n\n\t\t\t\tfor _, d := range b.Dominees() {\n\t\t\t\t\t// Successor blocks learn a fact\n\t\t\t\t\t// only at non-critical edges.\n\t\t\t\t\t// (We could do be more precise with full dataflow\n\t\t\t\t\t// analysis of control-flow joins.)\n\t\t\t\t\ts := stack\n\t\t\t\t\tif len(d.Preds) == 1 {\n\t\t\t\t\t\tif d == tsucc {\n\t\t\t\t\t\t\ts = append(s, newFacts...)\n\t\t\t\t\t\t} else if d == fsucc {\n\t\t\t\t\t\t\ts = append(s, newFacts.negate()...)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvisit(d, s)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// In code of the form:\n\t\t//\n\t\t// \tif ptr, ok := x.(*T); ok { ... } else { fsucc }\n\t\t//\n\t\t// the fsucc block learns that ptr == nil,\n\t\t// since that's its zero value.\n\t\tif If, ok := b.Instrs[len(b.Instrs)-1].(*ssa.If); ok {\n\t\t\t// Handle \"if ok\" and \"if !ok\" variants.\n\t\t\tcond, fsucc := If.Cond, b.Succs[1]\n\t\t\tif unop, ok := cond.(*ssa.UnOp); ok && unop.Op == token.NOT {\n\t\t\t\tcond, fsucc = unop.X, b.Succs[0]\n\t\t\t}\n\n\t\t\t// Match pattern:\n\t\t\t//   t0 = typeassert (pointerlike)\n\t\t\t//   t1 = extract t0 #0  // ptr\n\t\t\t//   t2 = extract t0 #1  // ok\n\t\t\t//   if t2 goto tsucc, fsucc\n\t\t\tif extract1, ok := cond.(*ssa.Extract); ok && extract1.Index == 1 {\n\t\t\t\tif assert, ok := extract1.Tuple.(*ssa.TypeAssert); ok &&\n\t\t\t\t\tisNillable(assert.AssertedType) {\n\t\t\t\t\tfor _, pinstr := range *assert.Referrers() {\n\t\t\t\t\t\tif extract0, ok := pinstr.(*ssa.Extract); ok &&\n\t\t\t\t\t\t\textract0.Index == 0 &&\n\t\t\t\t\t\t\textract0.Tuple == extract1.Tuple {\n\t\t\t\t\t\t\tfor _, d := range b.Dominees() {\n\t\t\t\t\t\t\t\tif len(d.Preds) == 1 && d == fsucc {\n\t\t\t\t\t\t\t\t\tvisit(d, append(stack, fact{extract0, isnil}))\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor _, d := range b.Dominees() {\n\t\t\tvisit(d, stack)\n\t\t}\n\t}\n\n\t// Visit the entry block.  No need to visit fn.Recover.\n\tif fn.Blocks != nil {\n\t\tvisit(fn.Blocks[0], make([]fact, 0, 20)) // 20 is plenty\n\t}\n}\n\n// A fact records that a block is dominated\n// by the condition v == nil or v != nil.\ntype fact struct {\n\tvalue   ssa.Value\n\tnilness nilness\n}\n\nfunc (f fact) negate() fact { return fact{f.value, -f.nilness} }\n\ntype nilness int\n\nconst (\n\tisnonnil         = -1\n\tunknown  nilness = 0\n\tisnil            = 1\n)\n\nvar nilnessStrings = []string{\"non-nil\", \"unknown\", \"nil\"}\n\nfunc (n nilness) String() string { return nilnessStrings[n+1] }\n\n// nilnessOf reports whether v is definitely nil, definitely not nil,\n// or unknown given the dominating stack of facts.\nfunc nilnessOf(stack []fact, v ssa.Value) nilness {\n\n\tswitch v := v.(type) {\n\t// unwrap ChangeInterface and Slice values recursively, to detect if underlying\n\t// values have any facts recorded or are otherwise known with regard to nilness.\n\t//\n\t// This work must be in addition to expanding facts about\n\t// ChangeInterfaces during inference/fact gathering because this covers\n\t// cases where the nilness of a value is intrinsic, rather than based\n\t// on inferred facts, such as a zero value interface variable. That\n\t// said, this work alone would only inform us when facts are about\n\t// underlying values, rather than outer values, when the analysis is\n\t// transitive in both directions.\n\tcase *ssa.ChangeInterface:\n\t\tif underlying := nilnessOf(stack, v.X); underlying != unknown {\n\t\t\treturn underlying\n\t\t}\n\tcase *ssa.MakeInterface:\n\t\t// A MakeInterface is non-nil unless its operand is a type parameter.\n\t\ttparam, ok := types.Unalias(v.X.Type()).(*types.TypeParam)\n\t\tif !ok {\n\t\t\treturn isnonnil\n\t\t}\n\n\t\t// A MakeInterface of a type parameter is non-nil if\n\t\t// the type parameter cannot be instantiated as an\n\t\t// interface type (#66835).\n\t\tif terms, err := typeparams.NormalTerms(tparam.Constraint()); err == nil && len(terms) > 0 {\n\t\t\treturn isnonnil\n\t\t}\n\n\t\t// If the type parameter can be instantiated as an\n\t\t// interface (and thus also as a concrete type),\n\t\t// we can't determine the nilness.\n\n\tcase *ssa.Slice:\n\t\tif underlying := nilnessOf(stack, v.X); underlying != unknown {\n\t\t\treturn underlying\n\t\t}\n\tcase *ssa.SliceToArrayPointer:\n\t\tnn := nilnessOf(stack, v.X)\n\t\tif slice2ArrayPtrLen(v) > 0 {\n\t\t\tif nn == isnil {\n\t\t\t\t// We know that *(*[1]byte)(nil) is going to panic because of the\n\t\t\t\t// conversion. So return unknown to the caller, prevent useless\n\t\t\t\t// nil deference reporting due to * operator.\n\t\t\t\treturn unknown\n\t\t\t}\n\t\t\t// Otherwise, the conversion will yield a non-nil pointer to array.\n\t\t\t// Note that the instruction can still panic if array length greater\n\t\t\t// than slice length. If the value is used by another instruction,\n\t\t\t// that instruction can assume the panic did not happen when that\n\t\t\t// instruction is reached.\n\t\t\treturn isnonnil\n\t\t}\n\t\t// In case array length is zero, the conversion result depends on nilness of the slice.\n\t\tif nn != unknown {\n\t\t\treturn nn\n\t\t}\n\t}\n\n\t// Is value intrinsically nil or non-nil?\n\tswitch v := v.(type) {\n\tcase *ssa.Alloc,\n\t\t*ssa.FieldAddr,\n\t\t*ssa.FreeVar,\n\t\t*ssa.Function,\n\t\t*ssa.Global,\n\t\t*ssa.IndexAddr,\n\t\t*ssa.MakeChan,\n\t\t*ssa.MakeClosure,\n\t\t*ssa.MakeMap,\n\t\t*ssa.MakeSlice:\n\t\treturn isnonnil\n\n\tcase *ssa.Const:\n\t\tif v.IsNil() {\n\t\t\treturn isnil // nil or zero value of a pointer-like type\n\t\t} else {\n\t\t\treturn unknown // non-pointer\n\t\t}\n\t}\n\n\t// Search dominating control-flow facts.\n\tfor _, f := range stack {\n\t\tif f.value == v {\n\t\t\treturn f.nilness\n\t\t}\n\t}\n\treturn unknown\n}\n\nfunc slice2ArrayPtrLen(v *ssa.SliceToArrayPointer) int64 {\n\treturn v.Type().(*types.Pointer).Elem().Underlying().(*types.Array).Len()\n}\n\n// If b ends with an equality comparison, eq returns the operation and\n// its true (equal) and false (not equal) successors.\nfunc eq(b *ssa.BasicBlock) (op *ssa.BinOp, tsucc, fsucc *ssa.BasicBlock) {\n\tif If, ok := b.Instrs[len(b.Instrs)-1].(*ssa.If); ok {\n\t\tif binop, ok := If.Cond.(*ssa.BinOp); ok {\n\t\t\tswitch binop.Op {\n\t\t\tcase token.EQL:\n\t\t\t\treturn binop, b.Succs[0], b.Succs[1]\n\t\t\tcase token.NEQ:\n\t\t\t\treturn binop, b.Succs[1], b.Succs[0]\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil, nil\n}\n\n// expandFacts takes a single fact and returns the set of facts that can be\n// known about it or any of its related values. Some operations, like\n// ChangeInterface, have transitive nilness, such that if you know the\n// underlying value is nil, you also know the value itself is nil, and vice\n// versa. This operation allows callers to match on any of the related values\n// in analyses, rather than just the one form of the value that happened to\n// appear in a comparison.\n//\n// This work must be in addition to unwrapping values within nilnessOf because\n// while this work helps give facts about transitively known values based on\n// inferred facts, the recursive check within nilnessOf covers cases where\n// nilness facts are intrinsic to the underlying value, such as a zero value\n// interface variables.\n//\n// ChangeInterface is the only expansion currently supported, but others, like\n// Slice, could be added. At this time, this tool does not check slice\n// operations in a way this expansion could help. See\n// https://play.golang.org/p/mGqXEp7w4fR for an example.\nfunc expandFacts(f fact) []fact {\n\tff := []fact{f}\n\nLoop:\n\tfor {\n\t\tswitch v := f.value.(type) {\n\t\tcase *ssa.ChangeInterface:\n\t\t\tf = fact{v.X, f.nilness}\n\t\t\tff = append(ff, f)\n\t\tdefault:\n\t\t\tbreak Loop\n\t\t}\n\t}\n\n\treturn ff\n}\n\ntype facts []fact\n\nfunc (ff facts) negate() facts {\n\tnn := make([]fact, len(ff))\n\tfor i, f := range ff {\n\t\tnn[i] = f.negate()\n\t}\n\treturn nn\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\nfunc isNillable(t types.Type) bool {\n\t// TODO(adonovan): CoreType (+ case *Interface) looks wrong.\n\t// This should probably use Underlying, and handle TypeParam\n\t// by computing the union across its normal terms.\n\tswitch t := typeparams.CoreType(t).(type) {\n\tcase *types.Pointer,\n\t\t*types.Map,\n\t\t*types.Signature,\n\t\t*types.Chan,\n\t\t*types.Interface,\n\t\t*types.Slice:\n\t\treturn true\n\tcase *types.Basic:\n\t\treturn t == types.Typ[types.UnsafePointer]\n\t}\n\treturn false\n}\n\n// isRangeIndex reports whether the instruction is a slice indexing\n// operation slice[i] within a \"for range slice\" loop. The operation\n// could be explicit, such as slice[i] within (or even after) the\n// loop, or it could be implicit, such as \"for i, v := range slice {}\".\n// (These cannot be reliably distinguished.)\nfunc isRangeIndex(instr *ssa.IndexAddr) bool {\n\t// Here we reverse-engineer the go/ssa lowering of range-over-slice:\n\t//\n\t//      n = len(x)\n\t//      jump loop\n\t// loop:                                                \"rangeindex.loop\"\n\t//      phi = φ(-1, incr) #rangeindex\n\t//      incr = phi + 1\n\t//      cond = incr < n\n\t//      if cond goto body else done\n\t// body:                                                \"rangeindex.body\"\n\t//      instr = &x[incr]\n\t//      ...\n\t// done:\n\tif incr, ok := instr.Index.(*ssa.BinOp); ok && incr.Op == token.ADD {\n\t\tif b := incr.Block(); b.Comment == \"rangeindex.loop\" {\n\t\t\tif If, ok := b.Instrs[len(b.Instrs)-1].(*ssa.If); ok {\n\t\t\t\tif cond := If.Cond.(*ssa.BinOp); cond.X == incr && cond.Op == token.LSS {\n\t\t\t\t\tif call, ok := cond.Y.(*ssa.Call); ok {\n\t\t\t\t\t\tcommon := call.Common()\n\t\t\t\t\t\tif blt, ok := common.Value.(*ssa.Builtin); ok && blt.Name() == \"len\" {\n\t\t\t\t\t\t\treturn common.Args[0] == instr.X\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/nilness_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nilness_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/nilness\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, nilness.Analyzer, \"a\")\n}\n\nfunc TestNilness(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, nilness.Analyzer, \"b\")\n}\n\nfunc TestInstantiated(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, nilness.Analyzer, \"c\")\n}\n\nfunc TestTypeSet(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, nilness.Analyzer, \"d\")\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/testdata/src/a/a.go",
    "content": "package a\n\nimport (\n\t\"log\"\n\t\"os\"\n)\n\ntype X struct{ f, g int }\n\nfunc f(x, y *X) {\n\tif x == nil {\n\t\tprint(x.f) // want \"nil dereference in field selection\"\n\t} else {\n\t\tprint(x.f)\n\t}\n\n\tif x == nil {\n\t\tif nil != y {\n\t\t\tprint(1)\n\t\t\tpanic(0)\n\t\t}\n\t\tx.f = 1 // want \"nil dereference in field selection\"\n\t\ty.f = 1 // want \"nil dereference in field selection\"\n\t}\n\n\tvar f func()\n\tif f == nil { // want \"tautological condition: nil == nil\"\n\t\tgo f() // want \"nil dereference in dynamic function call\"\n\t} else {\n\t\t// This block is unreachable,\n\t\t// so we don't report an error for the\n\t\t// nil dereference in the call.\n\t\tdefer f()\n\t}\n}\n\nfunc f2(ptr *[3]int, i interface{}) {\n\tif ptr != nil {\n\t\tprint(ptr[:])\n\t\t*ptr = [3]int{}\n\t\tprint(*ptr)\n\t} else {\n\t\tprint(ptr[:])   // want \"nil dereference in slice operation\"\n\t\t*ptr = [3]int{} // want \"nil dereference in store\"\n\t\tprint(*ptr)     // want \"nil dereference in load\"\n\n\t\tif ptr != nil { // want \"impossible condition: nil != nil\"\n\t\t\t// Dominated by ptr==nil and ptr!=nil,\n\t\t\t// this block is unreachable.\n\t\t\t// We do not report errors within it.\n\t\t\tprint(*ptr)\n\t\t}\n\t}\n\n\tif i != nil {\n\t\tprint(i.(interface{ f() }))\n\t} else {\n\t\tprint(i.(interface{ f() })) // want \"nil dereference in type assertion\"\n\t}\n}\n\nfunc g() error { return nil }\n\nfunc f3() error {\n\terr := g()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err != nil && err.Error() == \"foo\" { // want \"impossible condition: nil != nil\"\n\t\tprint(0)\n\t}\n\tch := make(chan int)\n\tif ch == nil { // want \"impossible condition: non-nil == nil\"\n\t\tprint(0)\n\t}\n\tif ch != nil { // want \"tautological condition: non-nil != nil\"\n\t\tprint(0)\n\t}\n\treturn nil\n}\n\nfunc h(err error, b bool) {\n\tif err != nil && b {\n\t\treturn\n\t} else if err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc i(*int) error {\n\tfor {\n\t\tif err := g(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\nfunc f4(x *X) {\n\tif x == nil {\n\t\tpanic(x)\n\t}\n}\n\nfunc f5(x *X) {\n\tpanic(nil) // want \"panic with nil value\"\n}\n\nfunc f6(x *X) {\n\tvar err error\n\tpanic(err) // want \"panic with nil value\"\n}\n\nfunc f7() {\n\tx, err := bad()\n\tif err != nil {\n\t\tpanic(0)\n\t}\n\tif x == nil {\n\t\tpanic(err) // want \"panic with nil value\"\n\t}\n}\n\nfunc bad() (*X, error) {\n\treturn nil, nil\n}\n\nfunc f8() {\n\tvar e error\n\tv, _ := e.(interface{})\n\tprint(v)\n}\n\nfunc f9(x interface {\n\ta()\n\tb()\n\tc()\n}) {\n\tx.b() // we don't catch this panic because we don't have any facts yet\n\txx := interface {\n\t\ta()\n\t\tb()\n\t}(x)\n\tif xx != nil {\n\t\treturn\n\t}\n\tx.c()  // want \"nil dereference in dynamic method call\"\n\txx.b() // want \"nil dereference in dynamic method call\"\n\txxx := interface{ a() }(xx)\n\txxx.a() // want \"nil dereference in dynamic method call\"\n\n\tif unknown() {\n\t\tpanic(x) // want \"panic with nil value\"\n\t}\n\tif unknown() {\n\t\tpanic(xx) // want \"panic with nil value\"\n\t}\n\tif unknown() {\n\t\tpanic(xxx) // want \"panic with nil value\"\n\t}\n}\n\nfunc f10() {\n\ts0 := make([]string, 0)\n\tif s0 == nil { // want \"impossible condition: non-nil == nil\"\n\t\tprint(0)\n\t}\n\n\tvar s1 []string\n\tif s1 == nil { // want \"tautological condition: nil == nil\"\n\t\tprint(0)\n\t}\n\ts2 := s1[:][:]\n\tif s2 == nil { // want \"tautological condition: nil == nil\"\n\t\tprint(0)\n\t}\n}\n\nfunc unknown() bool {\n\treturn false\n}\n\nfunc f11(a interface{}) {\n\tswitch a.(type) {\n\tcase nil:\n\t\treturn\n\t}\n\tswitch a.(type) {\n\tcase nil: // want \"impossible condition: non-nil == nil\"\n\t\treturn\n\t}\n}\n\nfunc f12(a interface{}) {\n\tswitch a {\n\tcase nil:\n\t\treturn\n\t}\n\tswitch a {\n\tcase 5,\n\t\tnil: // want \"impossible condition: non-nil == nil\"\n\t\treturn\n\t}\n}\n\ntype Y struct {\n\tinnerY\n}\n\ntype innerY struct {\n\tvalue int\n}\n\nfunc f13() {\n\tvar d *Y\n\tprint(d.value) // want \"nil dereference in field selection\"\n}\n\nfunc f14() {\n\tvar x struct{ f string }\n\tif x == struct{ f string }{} { // we don't catch this tautology as we restrict to reference types\n\t\tprint(x)\n\t}\n}\n\nfunc f15(x any) {\n\tptr, ok := x.(*int)\n\tif ok {\n\t\treturn\n\t}\n\tprintln(*ptr) // want \"nil dereference in load\"\n}\n\nfunc f16(x any) {\n\tptr, ok := x.(*int)\n\tif !ok {\n\t\tprintln(*ptr) // want \"nil dereference in load\"\n\t\treturn\n\t}\n\tprintln(*ptr)\n}\n\nfunc f18(x any) {\n\tptr, ok := x.(*int)\n\tif ok {\n\t\tprintln(ptr)\n\t\t// falls through\n\t}\n\tprintln(*ptr)\n}\n\n// Regression test for https://github.com/golang/go/issues/65674:\n// spurious \"nil deference in slice index operation\" when the\n// index was subject to a range loop.\nfunc f19(slice []int, array *[2]int, m map[string]int, ch chan int) {\n\tif slice == nil {\n\t\t// A range over a nil slice is dynamically benign,\n\t\t// but still signifies a programmer mistake.\n\t\t//\n\t\t// Since SSA has melted down the control structure,\n\t\t// so we can only report a diagnostic about the\n\t\t// index operation, with heuristics for \"range\".\n\n\t\tfor range slice { // nothing to report here\n\t\t}\n\t\tfor _, v := range slice { // want \"range of nil slice\"\n\t\t\t_ = v\n\t\t}\n\t\tfor i := range slice {\n\t\t\t_ = slice[i] // want \"range of nil slice\"\n\t\t}\n\t\t{\n\t\t\tvar i int\n\t\t\tfor i = range slice {\n\t\t\t}\n\t\t\t_ = slice[i] // want \"index of nil slice\"\n\t\t}\n\t\tfor i := range slice {\n\t\t\tif i < len(slice) {\n\t\t\t\t_ = slice[i] // want \"range of nil slice\"\n\t\t\t}\n\t\t}\n\t\tif len(slice) > 3 {\n\t\t\t_ = slice[2] // want \"index of nil slice\"\n\t\t}\n\t\tfor i := 0; i < len(slice); i++ {\n\t\t\t_ = slice[i] // want \"index of nil slice\"\n\t\t}\n\t}\n\n\tif array == nil {\n\t\t// (The v var is necessary, otherwise the SSA\n\t\t// code doesn't dereference the pointer.)\n\t\tfor _, v := range array { // want \"nil dereference in array index operation\"\n\t\t\t_ = v\n\t\t}\n\t}\n\n\tif m == nil {\n\t\tfor range m { // want \"range over nil map\"\n\t\t}\n\t\tm[\"one\"] = 1 // want \"nil dereference in map update\"\n\t}\n\n\tif ch == nil {\n\t\tfor range ch { // want \"receive from nil channel\"\n\t\t}\n\t\t<-ch    // want \"receive from nil channel\"\n\t\tch <- 0 // want \"send to nil channel\"\n\t}\n}\n\nfunc f20() {\n\tf, err := os.Open(\"\")\n\tif err != nil {\n\t\tlog.Fatal(err) // noreturn analysis proves this call doesn't return\n\t}\n\tif err != nil { // want \"impossible condition\"\n\t\tlog.Fatal(err)\n\t}\n\tf.Close()\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/testdata/src/b/b.go",
    "content": "package b\n\nfunc f() {\n\tvar s []int\n\tt := (*[0]int)(s)\n\t_ = *t // want \"nil dereference in load\"\n\t_ = (*[0]int)(s)\n\t_ = *(*[0]int)(s) // want \"nil dereference in load\"\n\n\t// these operation is panic\n\t_ = (*[1]int)(s)  // want \"nil slice being cast to an array of len > 0 will always panic\"\n\t_ = *(*[1]int)(s) // want \"nil slice being cast to an array of len > 0 will always panic\"\n}\n\nfunc g() {\n\tvar s = make([]int, 0)\n\tt := (*[0]int)(s)\n\tprintln(*t)\n}\n\nfunc h() {\n\tvar s = make([]int, 1)\n\tt := (*[1]int)(s)\n\tprintln(*t)\n}\n\nfunc i(x []int) {\n\ta := (*[1]int)(x)\n\tif a != nil { // want \"tautological condition: non-nil != nil\"\n\t\t_ = *a\n\t}\n}\n\nfunc _(err error) {\n\tif err == nil {\n\t\terr.Error() // want \"nil dereference in dynamic method call\"\n\n\t\t// SSA uses TypeAssert for the nil check in a method value:\n\t\t_ = err.Error // want \"nil dereference in type assertion\"\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/testdata/src/c/c.go",
    "content": "package c\n\nfunc instantiated[X any](x *X) int {\n\tif x == nil {\n\t\tprint(*x) // want \"nil dereference in load\"\n\t}\n\treturn 1\n}\n\nvar g int\n\nfunc init() {\n\tg = instantiated[int](&g)\n}\n\n// -- issue 66835 --\n\ntype Empty1 any\ntype Empty2 any\n\n// T may be instantiated with an interface type, so any(x) may be nil.\nfunc TypeParamInterface[T error](x T) {\n\tif any(x) == nil {\n\t\tprint()\n\t}\n}\n\n// T may not be instantiated with an interface type, so any(x) is non-nil\nfunc TypeParamTypeSetWithInt[T interface {\n\terror\n\tint\n}](x T) {\n\tif any(x) == nil { // want \"impossible condition: non-nil == nil\"\n\t\tprint()\n\t}\n}\n\nfunc TypeParamUnionEmptyEmpty[T Empty1 | Empty2](x T) {\n\tif any(x) == nil {\n\t\tprint()\n\t}\n}\n\nfunc TypeParamUnionEmptyInt[T Empty1 | int](x T) {\n\tif any(x) == nil {\n\t\tprint()\n\t}\n}\n\nfunc TypeParamUnionStringInt[T string | int](x T) {\n\tif any(x) == nil { // want \"impossible condition: non-nil == nil\"\n\t\tprint()\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/nilness/testdata/src/d/d.go",
    "content": "package d\n\ntype message interface{ PR() }\n\nfunc noparam() {\n\tvar messageT message\n\tmessageT.PR() // want \"nil dereference in dynamic method call\"\n}\n\nfunc paramNonnil[T message]() {\n\tvar messageT T\n\tmessageT.PR() // cannot conclude messageT is nil.\n}\n\nfunc instance() {\n\t// buildssa.BuilderMode does not include InstantiateGenerics.\n\tparamNonnil[message]() // no warning is expected as param[message] id not built.\n}\n\nfunc param[T interface {\n\tmessage\n\t~*int | ~chan int\n}]() {\n\tvar messageT T // messageT is nil.\n\tmessageT.PR()  // nil receiver may be okay. See param[nilMsg].\n}\n\ntype nilMsg chan int\n\nfunc (m nilMsg) PR() {\n\tif m == nil {\n\t\tprint(\"not an error\")\n\t}\n}\n\nvar G func() = param[nilMsg] // no warning\n\nfunc allNillable[T ~*int | ~chan int]() {\n\tvar x, y T  // both are nillable and are nil.\n\tif x != y { // want \"impossible condition: nil != nil\"\n\t\tprint(\"unreachable\")\n\t}\n}\n\nfunc notAll[T ~*int | ~chan int | ~int]() {\n\tvar x, y T  // neither are nillable due to ~int\n\tif x != y { // no warning\n\t\tprint(\"unreachable\")\n\t}\n}\n\nfunc noninvoke[T ~func()]() {\n\tvar x T\n\tx() // want \"nil dereference in dynamic function call\"\n}\n"
  },
  {
    "path": "go/analysis/passes/pkgfact/pkgfact.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The pkgfact package is a demonstration and test of the package fact\n// mechanism.\n//\n// The output of the pkgfact analysis is a set of key/values pairs\n// gathered from the analyzed package and its imported dependencies.\n// Each key/value pair comes from a top-level constant declaration\n// whose name starts and ends with \"_\".  For example:\n//\n//\tpackage p\n//\n//\tconst _greeting_  = \"hello\"\n//\tconst _audience_  = \"world\"\n//\n// the pkgfact analysis output for package p would be:\n//\n//\t{\"greeting\": \"hello\", \"audience\": \"world\"}.\n//\n// In addition, the analysis reports a diagnostic at each import\n// showing which key/value pairs it contributes.\npackage pkgfact\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"pkgfact\",\n\tDoc:        \"gather name/value pairs from constant declarations\",\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/pkgfact\",\n\tRun:        run,\n\tFactTypes:  []analysis.Fact{new(pairsFact)},\n\tResultType: reflect.TypeFor[map[string]string](),\n}\n\n// A pairsFact is a package-level fact that records\n// a set of key=value strings accumulated from constant\n// declarations in this package and its dependencies.\n// Elements are ordered by keys, which are unique.\ntype pairsFact []string\n\nfunc (f *pairsFact) AFact()         {}\nfunc (f *pairsFact) String() string { return \"pairs(\" + strings.Join(*f, \", \") + \")\" }\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tresult := make(map[string]string)\n\n\t// At each import, print the fact from the imported\n\t// package and accumulate its information into the result.\n\t// (Warning: accumulation leads to quadratic growth of work.)\n\tdoImport := func(spec *ast.ImportSpec) {\n\t\tpkg := imported(pass.TypesInfo, spec)\n\t\tvar fact pairsFact\n\t\tif pass.ImportPackageFact(pkg, &fact) {\n\t\t\tfor _, pair := range fact {\n\t\t\t\teq := strings.IndexByte(pair, '=')\n\t\t\t\tresult[pair[:eq]] = pair[1+eq:]\n\t\t\t}\n\t\t\tpass.ReportRangef(spec, \"%s\", strings.Join(fact, \" \"))\n\t\t}\n\t}\n\n\t// At each \"const _name_ = value\", add a fact into env.\n\tdoConst := func(spec *ast.ValueSpec) {\n\t\tif len(spec.Names) == len(spec.Values) {\n\t\t\tfor i := range spec.Names {\n\t\t\t\tname := spec.Names[i].Name\n\t\t\t\tif strings.HasPrefix(name, \"_\") && strings.HasSuffix(name, \"_\") {\n\n\t\t\t\t\tif key := strings.Trim(name, \"_\"); key != \"\" {\n\t\t\t\t\t\tvalue := pass.TypesInfo.Types[spec.Values[i]].Value.String()\n\t\t\t\t\t\tresult[key] = value\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, f := range pass.Files {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.GenDecl); ok {\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tswitch decl.Tok {\n\t\t\t\t\tcase token.IMPORT:\n\t\t\t\t\t\tdoImport(spec.(*ast.ImportSpec))\n\t\t\t\t\tcase token.CONST:\n\t\t\t\t\t\tdoConst(spec.(*ast.ValueSpec))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Sort/deduplicate the result and save it as a package fact.\n\tkeys := make([]string, 0, len(result))\n\tfor key := range result {\n\t\tkeys = append(keys, key)\n\t}\n\tsort.Strings(keys)\n\tvar fact pairsFact\n\tfor _, key := range keys {\n\t\tfact = append(fact, fmt.Sprintf(\"%s=%s\", key, result[key]))\n\t}\n\tif len(fact) > 0 {\n\t\tpass.ExportPackageFact(&fact)\n\t}\n\n\treturn result, nil\n}\n\nfunc imported(info *types.Info, spec *ast.ImportSpec) *types.Package {\n\tobj, ok := info.Implicits[spec]\n\tif !ok {\n\t\tobj = info.Defs[spec.Name] // renaming import\n\t}\n\treturn obj.(*types.PkgName).Imported()\n}\n"
  },
  {
    "path": "go/analysis/passes/pkgfact/pkgfact_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgfact_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/pkgfact\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, pkgfact.Analyzer, \"c\")\n}\n"
  },
  {
    "path": "go/analysis/passes/pkgfact/testdata/src/a/a.go",
    "content": "package a\n\nconst _greeting_ = \"hello\"\nconst _audience_ = \"world\"\n"
  },
  {
    "path": "go/analysis/passes/pkgfact/testdata/src/b/b.go",
    "content": "package b\n\nimport _ \"a\"\n\nconst _pi_ = 3.14159\n"
  },
  {
    "path": "go/analysis/passes/pkgfact/testdata/src/c/c.go",
    "content": "// want package:`pairs\\(audience=\"world\", greeting=\"hello\", pi=3.14159\\)`\n\npackage c\n\nimport _ \"b\" // want `audience=\"world\" greeting=\"hello\" pi=3.14159`\n"
  },
  {
    "path": "go/analysis/passes/printf/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package printf defines an Analyzer that checks consistency\n// of Printf format strings and arguments.\n//\n// # Analyzer printf\n//\n// printf: check consistency of Printf format strings and arguments\n//\n// The check applies to calls of the formatting functions such as\n// [fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of\n// those functions such as [log.Printf]. It reports a variety of\n// mistakes such as syntax errors in the format string and mismatches\n// (of number and type) between the verbs and their arguments.\n//\n// See the documentation of the fmt package for the complete set of\n// format operators and their operand types.\n//\n// # Examples\n//\n// The %d format operator requires an integer operand.\n// Here it is incorrectly applied to a string:\n//\n//\tfmt.Printf(\"%d\", \"hello\") // fmt.Printf format %d has arg \"hello\" of wrong type string\n//\n// A call to Printf must have as many operands as there are \"verbs\" in\n// the format string, not too few:\n//\n//\tfmt.Printf(\"%d\") // fmt.Printf format reads arg 1, but call has 0 args\n//\n// nor too many:\n//\n//\tfmt.Printf(\"%d\", 1, 2) // fmt.Printf call needs 1 arg, but has 2 args\n//\n// Explicit argument indexes must be no greater than the number of\n// arguments:\n//\n//\tfmt.Printf(\"%[3]d\", 1, 2) // fmt.Printf call has invalid argument index 3\n//\n// The checker also uses a heuristic to report calls to Print-like\n// functions that appear to have been intended for their Printf-like\n// counterpart:\n//\n//\tlog.Print(\"%d\", 123) // log.Print call has possible formatting directive %d\n//\n// Conversely, it also reports calls to Printf-like functions with a\n// non-constant format string and no other arguments:\n//\n//\tfmt.Printf(message) // non-constant format string in call to fmt.Printf\n//\n// Such calls may have been intended for the function's Print-like\n// counterpart: if the value of message happens to contain \"%\",\n// misformatting will occur. In this case, the checker additionally\n// suggests a fix to turn the call into:\n//\n//\tfmt.Printf(\"%s\", message)\n//\n// # Inferred printf wrappers\n//\n// Functions that delegate their arguments to fmt.Printf are\n// considered \"printf wrappers\"; calls to them are subject to the same\n// checking. In this example, logf is a printf wrapper:\n//\n//\tfunc logf(level int, format string, args ...any) {\n//\t\tif enabled(level) {\n//\t\t\tlog.Printf(format, args...)\n//\t\t}\n//\t}\n//\n//\tlogf(3, \"invalid request: %v\") // logf format reads arg 1, but call has 0 args\n//\n// To enable printf checking on a function that is not found by this\n// analyzer's heuristics (for example, because control is obscured by\n// dynamic method calls), insert a bogus call:\n//\n//\tfunc MyPrintf(format string, args ...any) {\n//\t\tif false {\n//\t\t\t_ = fmt.Sprintf(format, args...) // enable printf checking\n//\t\t}\n//\t\t...\n//\t}\n//\n// A local function may also be inferred as a printf wrapper. If it\n// is assigned to a variable, each call made through that variable will\n// be checked just like a call to a function:\n//\n//\tlogf := func(format string, args ...any) {\n//\t\tmessage := fmt.Sprintf(format, args...)\n//\t\tlog.Printf(\"%s: %s\", prefix, message)\n//\t}\n//\tlogf(\"%s\", 123) // logf format %s has arg 123 of wrong type int\n//\n// Interface methods may also be analyzed as printf wrappers, if\n// within the interface's package there is an assignment from a\n// implementation type whose corresponding method is a printf wrapper.\n//\n// For example, the var declaration below causes a *myLoggerImpl value\n// to be assigned to a Logger variable:\n//\n//\ttype Logger interface {\n//\t\tLogf(format string, args ...any)\n//\t}\n//\n//\ttype myLoggerImpl struct{ ... }\n//\n//\tvar _ Logger = (*myLoggerImpl)(nil)\n//\n//\tfunc  (*myLoggerImpl) Logf(format string, args ...any) {\n//\t\tprintln(fmt.Sprintf(format, args...))\n//\t}\n//\n// Since myLoggerImpl's Logf method is a printf wrapper, this\n// establishes that Logger.Logf is a printf wrapper too, causing\n// dynamic calls through the interface to be checked:\n//\n//\tfunc f(log Logger) {\n//\t\tlog.Logf(\"%s\", 123) // Logger.Logf format %s has arg 123 of wrong type int\n//\t}\n//\n// This feature applies only to interface methods declared in files\n// using at least Go 1.26.\n//\n// # Specifying printf wrappers by flag\n//\n// The -funcs flag specifies a comma-separated list of names of\n// additional known formatting functions or methods. (This legacy flag\n// is rarely used due to the automatic inference described above.)\n//\n// If the name contains a period, it must denote a specific function\n// using one of the following forms:\n//\n//\tdir/pkg.Function\n//\tdir/pkg.Type.Method\n//\t(*dir/pkg.Type).Method\n//\n// Otherwise the name is interpreted as a case-insensitive unqualified\n// identifier such as \"errorf\". Either way, if a listed name ends in f, the\n// function is assumed to be Printf-like, taking a format string before the\n// argument list. Otherwise it is assumed to be Print-like, taking a list\n// of arguments with no format string.\npackage printf\n"
  },
  {
    "path": "go/analysis/passes/printf/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The printf command applies the printf checker to the specified\n// packages of Go source code.\n//\n// Run with:\n//\n//\t$ go run ./go/analysis/passes/printf/main.go -- packages...\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(printf.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/printf/printf.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage printf\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/fmtstr\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\nfunc init() {\n\tAnalyzer.Flags.Var(isPrint, \"funcs\", \"comma-separated list of print function names to check\")\n}\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"printf\",\n\tDoc:        analyzerutil.MustExtractDoc(doc, \"printf\"),\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf\",\n\tRequires:   []*analysis.Analyzer{inspect.Analyzer},\n\tRun:        run,\n\tResultType: reflect.TypeFor[*Result](),\n\tFactTypes:  []analysis.Fact{new(isWrapper)},\n}\n\n// Kind is a kind of fmt function behavior.\ntype Kind int\n\nconst (\n\tKindNone   Kind = iota // not a fmt wrapper function\n\tKindPrint              // function behaves like fmt.Print\n\tKindPrintf             // function behaves like fmt.Printf\n\tKindErrorf             // function behaves like fmt.Errorf\n)\n\nfunc (kind Kind) String() string {\n\tswitch kind {\n\tcase KindPrint:\n\t\treturn \"print\"\n\tcase KindPrintf:\n\t\treturn \"printf\"\n\tcase KindErrorf:\n\t\treturn \"errorf\"\n\t}\n\treturn \"(none)\"\n}\n\n// Result is the printf analyzer's result type. Clients may query the result\n// to learn whether a function behaves like fmt.Print or fmt.Printf.\ntype Result struct {\n\tfuncs map[types.Object]Kind\n}\n\n// Kind reports whether fn behaves like fmt.Print or fmt.Printf.\nfunc (r *Result) Kind(fn *types.Func) Kind {\n\t_, ok := isPrint[fn.FullName()]\n\tif !ok {\n\t\t// Next look up just \"printf\", for use with -printf.funcs.\n\t\t_, ok = isPrint[strings.ToLower(fn.Name())]\n\t}\n\tif ok {\n\t\tif strings.HasSuffix(fn.Name(), \"f\") {\n\t\t\treturn KindPrintf\n\t\t} else {\n\t\t\treturn KindPrint\n\t\t}\n\t}\n\n\treturn r.funcs[fn]\n}\n\n// isWrapper is a fact indicating that a function is a print or printf wrapper.\ntype isWrapper struct{ Kind Kind }\n\nfunc (f *isWrapper) AFact() {}\n\nfunc (f *isWrapper) String() string {\n\tswitch f.Kind {\n\tcase KindPrintf:\n\t\treturn \"printfWrapper\"\n\tcase KindPrint:\n\t\treturn \"printWrapper\"\n\tcase KindErrorf:\n\t\treturn \"errorfWrapper\"\n\tdefault:\n\t\treturn \"unknownWrapper\"\n\t}\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tres := &Result{\n\t\tfuncs: make(map[types.Object]Kind),\n\t}\n\tfindPrintLike(pass, res)\n\tcheckCalls(pass, res)\n\treturn res, nil\n}\n\n// A wrapper is a candidate print/printf wrapper function.\n//\n// We represent functions generally as types.Object, not *Func, so\n// that we can analyze anonymous functions such as\n//\n//\tprintf := func(format string, args ...any) {...},\n//\n// representing them by the *types.Var symbol for the local variable\n// 'printf'.\ntype wrapper struct {\n\tobj     types.Object     // *Func or *Var\n\tcurBody inspector.Cursor // for *ast.BlockStmt\n\tformat  *types.Var       // optional \"format string\" parameter in the Func{Decl,Lit}\n\targs    *types.Var       // \"args ...any\" parameter in the Func{Decl,Lit}\n\tcallers []printfCaller\n}\n\n// printfCaller is a candidate print{,f} forwarding call from candidate wrapper w.\ntype printfCaller struct {\n\tw    *wrapper\n\tcall *ast.CallExpr // forwarding call (nil for implicit interface method -> impl calls)\n}\n\n// formatArgsParams returns the \"format string\" and \"args ...any\"\n// parameters of a potential print or printf wrapper function.\n// (The format is nil in the print-like case.)\nfunc formatArgsParams(sig *types.Signature) (format, args *types.Var) {\n\tif !sig.Variadic() {\n\t\treturn nil, nil // not variadic\n\t}\n\n\tparams := sig.Params()\n\tnparams := params.Len() // variadic => nonzero\n\n\t// Is second last param 'format string'?\n\tif nparams >= 2 {\n\t\tif p := params.At(nparams - 2); p.Type() == types.Typ[types.String] {\n\t\t\tformat = p\n\t\t}\n\t}\n\n\t// Check final parameter is \"args ...any\".\n\t// (variadic => slice)\n\targs = params.At(nparams - 1)\n\tiface, ok := types.Unalias(args.Type().(*types.Slice).Elem()).(*types.Interface)\n\tif !ok || !iface.Empty() {\n\t\treturn nil, nil\n\t}\n\n\treturn format, args\n}\n\n// findPrintLike scans the entire package to find print or printf-like functions.\n// When it returns, all such functions have been identified.\nfunc findPrintLike(pass *analysis.Pass, res *Result) {\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tinfo    = pass.TypesInfo\n\t)\n\n\t// Pass 1: gather candidate wrapper functions (and populate wrappers).\n\tvar (\n\t\twrappers []*wrapper\n\t\tbyObj    = make(map[types.Object]*wrapper)\n\t)\n\tfor cur := range inspect.Root().Preorder((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil), (*ast.InterfaceType)(nil)) {\n\n\t\t// addWrapper records that a func (or var representing\n\t\t// a FuncLit) is a potential print{,f} wrapper.\n\t\t// curBody is its *ast.BlockStmt, if any.\n\t\taddWrapper := func(obj types.Object, sig *types.Signature, curBody inspector.Cursor) *wrapper {\n\t\t\tformat, args := formatArgsParams(sig)\n\t\t\tif args != nil {\n\t\t\t\t// obj (the symbol for a function/method, or variable\n\t\t\t\t// assigned to an anonymous function) is a potential\n\t\t\t\t// print or printf wrapper.\n\t\t\t\t//\n\t\t\t\t// Later processing will analyze the graph of potential\n\t\t\t\t// wrappers and their function bodies to pick out the\n\t\t\t\t// ones that are true wrappers.\n\t\t\t\tw := &wrapper{\n\t\t\t\t\tobj:     obj,\n\t\t\t\t\tcurBody: curBody,\n\t\t\t\t\tformat:  format, // non-nil => printf\n\t\t\t\t\targs:    args,\n\t\t\t\t}\n\t\t\t\tbyObj[w.obj] = w\n\t\t\t\twrappers = append(wrappers, w)\n\t\t\t\treturn w\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\tswitch f := cur.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\t// named function or method:\n\t\t\t//\n\t\t\t//    func wrapf(format string, args ...any) {...}\n\t\t\tif f.Body != nil {\n\t\t\t\tfn := info.Defs[f.Name].(*types.Func)\n\t\t\t\taddWrapper(fn, fn.Signature(), cur.ChildAt(edge.FuncDecl_Body, -1))\n\t\t\t}\n\n\t\tcase *ast.FuncLit:\n\t\t\t// anonymous function directly assigned to a variable:\n\t\t\t//\n\t\t\t//    var wrapf = func(format string, args ...any) {...}\n\t\t\t//    wrapf    := func(format string, args ...any) {...}\n\t\t\t//    wrapf     = func(format string, args ...any) {...}\n\t\t\t//\n\t\t\t// The LHS may also be a struct field x.wrapf or\n\t\t\t// an imported var pkg.Wrapf.\n\t\t\t//\n\t\t\tvar lhs ast.Expr\n\t\t\tswitch ek, idx := cur.ParentEdge(); ek {\n\t\t\tcase edge.ValueSpec_Values:\n\t\t\t\tcurName := cur.Parent().ChildAt(edge.ValueSpec_Names, idx)\n\t\t\t\tlhs = curName.Node().(*ast.Ident)\n\t\t\tcase edge.AssignStmt_Rhs:\n\t\t\t\tcurLhs := cur.Parent().ChildAt(edge.AssignStmt_Lhs, idx)\n\t\t\t\tlhs = curLhs.Node().(ast.Expr)\n\t\t\t}\n\n\t\t\tvar v *types.Var\n\t\t\tswitch lhs := lhs.(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\t// variable: wrapf = func(...)\n\t\t\t\tv, _ = info.ObjectOf(lhs).(*types.Var)\n\t\t\tcase *ast.SelectorExpr:\n\t\t\t\tif sel, ok := info.Selections[lhs]; ok {\n\t\t\t\t\t// struct field: x.wrapf = func(...)\n\t\t\t\t\tv = sel.Obj().(*types.Var)\n\t\t\t\t} else {\n\t\t\t\t\t// imported var: pkg.Wrapf = func(...)\n\t\t\t\t\tv = info.Uses[lhs.Sel].(*types.Var)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif v != nil {\n\t\t\t\tsig := info.TypeOf(f).(*types.Signature)\n\t\t\t\tcurBody := cur.ChildAt(edge.FuncLit_Body, -1)\n\t\t\t\taddWrapper(v, sig, curBody)\n\t\t\t}\n\n\t\tcase *ast.InterfaceType:\n\t\t\t// Induction through interface methods is gated as\n\t\t\t// if it were a go1.26 language feature, to avoid\n\t\t\t// surprises when go test's vet suite gets stricter.\n\t\t\tif analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(cur), versions.Go1_26) {\n\t\t\t\tfor imeth := range info.TypeOf(f).(*types.Interface).Methods() {\n\t\t\t\t\taddWrapper(imeth, imeth.Signature(), inspector.Cursor{})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// impls maps abstract methods to implementations.\n\t//\n\t// Interface methods are modelled as if they have a body\n\t// that calls each implementing method.\n\t//\n\t// In the code below, impls maps Logger.Logf to\n\t// [myLogger.Logf], and if myLogger.Logf is discovered to be\n\t// printf-like, then so will be Logger.Logf.\n\t//\n\t//   type Logger interface {\n\t// \tLogf(format string, args ...any)\n\t//   }\n\t//   type myLogger struct{ ... }\n\t//   func (myLogger) Logf(format string, args ...any) {...}\n\t//   var _ Logger = myLogger{}\n\timpls := methodImplementations(pass)\n\n\t// doCall records a call from one wrapper to another.\n\tdoCall := func(w *wrapper, callee types.Object, call *ast.CallExpr) {\n\t\t// Call from one wrapper candidate to another?\n\t\t// Record the edge so that if callee is found to be\n\t\t// a true wrapper, w will be too.\n\t\tif w2, ok := byObj[callee]; ok {\n\t\t\tw2.callers = append(w2.callers, printfCaller{w, call})\n\t\t}\n\n\t\t// Is the candidate a true wrapper, because it calls\n\t\t// a known print{,f}-like function from the allowlist\n\t\t// or an imported fact, or another wrapper found\n\t\t// to be a true wrapper?\n\t\t// If so, convert all w's callers to kind.\n\t\tkind := callKind(pass, callee, res)\n\t\tif kind != KindNone {\n\t\t\tpropagate(pass, w, call, kind, res)\n\t\t}\n\t}\n\n\t// Pass 2: scan the body of each wrapper function\n\t// for calls to other printf-like functions.\n\tfor _, w := range wrappers {\n\n\t\t// An interface method has no body, but acts\n\t\t// like an implicit call to each implementing method.\n\t\tif !w.curBody.Valid() {\n\t\t\tfor impl := range impls[w.obj.(*types.Func)] {\n\t\t\t\tdoCall(w, impl, nil)\n\t\t\t}\n\t\t\tcontinue // (no body)\n\t\t}\n\n\t\t// Process all calls in the wrapper function's body.\n\tscan:\n\t\tfor cur := range w.curBody.Preorder(\n\t\t\t(*ast.AssignStmt)(nil),\n\t\t\t(*ast.UnaryExpr)(nil),\n\t\t\t(*ast.CallExpr)(nil),\n\t\t) {\n\t\t\tswitch n := cur.Node().(type) {\n\n\t\t\t// Reject tricky cases where the parameters\n\t\t\t// are potentially mutated by AssignStmt or UnaryExpr.\n\t\t\t// (This logic checks for mutation only before the call.)\n\t\t\t// TODO: Relax these checks; issue 26555.\n\n\t\t\tcase *ast.AssignStmt:\n\t\t\t\t// If the wrapper updates format or args\n\t\t\t\t// it is not a simple wrapper.\n\t\t\t\tfor _, lhs := range n.Lhs {\n\t\t\t\t\tif w.format != nil && match(info, lhs, w.format) ||\n\t\t\t\t\t\tmatch(info, lhs, w.args) {\n\t\t\t\t\t\tbreak scan\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.UnaryExpr:\n\t\t\t\t// If the wrapper computes &format or &args,\n\t\t\t\t// it is not a simple wrapper.\n\t\t\t\tif n.Op == token.AND &&\n\t\t\t\t\t(w.format != nil && match(info, n.X, w.format) ||\n\t\t\t\t\t\tmatch(info, n.X, w.args)) {\n\t\t\t\t\tbreak scan\n\t\t\t\t}\n\n\t\t\tcase *ast.CallExpr:\n\t\t\t\tif len(n.Args) > 0 && match(info, n.Args[len(n.Args)-1], w.args) {\n\t\t\t\t\tif callee := typeutil.Callee(pass.TypesInfo, n); callee != nil {\n\t\t\t\t\t\tdoCall(w, callee, n)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// methodImplementations returns the mapping from interface methods\n// declared in this package to their corresponding implementing\n// methods (which may also be interface methods), according to the set\n// of assignments to interface types that appear within this package.\nfunc methodImplementations(pass *analysis.Pass) map[*types.Func]map[*types.Func]bool {\n\timpls := make(map[*types.Func]map[*types.Func]bool)\n\n\t// To find interface/implementation relations,\n\t// we use the 'satisfy' pass, but proposal #70638\n\t// provides a better way.\n\t//\n\t// This pass over the syntax could be factored out as\n\t// a separate analysis pass if it is needed by other\n\t// analyzers.\n\tvar f satisfy.Finder\n\tf.Find(pass.TypesInfo, pass.Files)\n\tfor assign := range f.Result {\n\t\t// Have: LHS = RHS, where LHS is an interface type.\n\t\tfor imeth := range assign.LHS.Underlying().(*types.Interface).Methods() {\n\t\t\t// Limit to interface methods of current package.\n\t\t\tif imeth.Pkg() != pass.Pkg {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif _, args := formatArgsParams(imeth.Signature()); args == nil {\n\t\t\t\tcontinue // not print{,f}-like\n\t\t\t}\n\n\t\t\t// Add implementing method to the set.\n\t\t\timpl, _, _ := types.LookupFieldOrMethod(assign.RHS, false, pass.Pkg, imeth.Name()) // can't fail\n\t\t\tset, ok := impls[imeth]\n\t\t\tif !ok {\n\t\t\t\tset = make(map[*types.Func]bool)\n\t\t\t\timpls[imeth] = set\n\t\t\t}\n\t\t\tset[impl.(*types.Func)] = true\n\t\t}\n\t}\n\treturn impls\n}\n\nfunc match(info *types.Info, arg ast.Expr, param *types.Var) bool {\n\tid, ok := arg.(*ast.Ident)\n\treturn ok && info.ObjectOf(id) == param\n}\n\n// propagate propagates changes in wrapper (non-None) kind information backwards\n// through through the wrapper.callers graph of well-formed forwarding calls.\nfunc propagate(pass *analysis.Pass, w *wrapper, call *ast.CallExpr, kind Kind, res *Result) {\n\t// Check correct call forwarding.\n\t//\n\t// Interface methods (call==nil) forward\n\t// correctly by construction.\n\tif call != nil && !checkForward(pass, w, call, kind) {\n\t\treturn\n\t}\n\n\t// If the candidate's print{,f} status becomes known,\n\t// propagate it back to all its so-far known callers.\n\tif res.funcs[w.obj] != kind {\n\t\tres.funcs[w.obj] = kind\n\n\t\t// Export a fact.\n\t\t// (This is a no-op for local symbols.)\n\t\t// We can't export facts on a symbol of another package,\n\t\t// but we can treat the symbol as a wrapper within\n\t\t// the current analysis unit.\n\t\tif w.obj.Pkg() == pass.Pkg {\n\t\t\t// Facts are associated with origins.\n\t\t\tpass.ExportObjectFact(origin(w.obj), &isWrapper{Kind: kind})\n\t\t}\n\n\t\t// Propagate kind back to known callers.\n\t\tfor _, caller := range w.callers {\n\t\t\tpropagate(pass, caller.w, caller.call, kind, res)\n\t\t}\n\t}\n}\n\n// checkForward checks whether a call from wrapper w is a well-formed\n// forwarding call of the specified (non-None) kind.\n//\n// If not, it reports a diagnostic that the user wrote\n// fmt.Printf(format, args) instead of fmt.Printf(format, args...).\nfunc checkForward(pass *analysis.Pass, w *wrapper, call *ast.CallExpr, kind Kind) bool {\n\t// Printf/Errorf calls must delegate the format string.\n\tswitch kind {\n\tcase KindPrintf, KindErrorf:\n\t\tif len(call.Args) < 2 || !match(pass.TypesInfo, call.Args[len(call.Args)-2], w.format) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// The args... delegation must be variadic.\n\t// (That args is actually delegated was\n\t// established before the root call to doCall.)\n\tif !call.Ellipsis.IsValid() {\n\t\ttyp, ok := pass.TypesInfo.Types[call.Fun].Type.(*types.Signature)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif len(call.Args) > typ.Params().Len() {\n\t\t\t// If we're passing more arguments than what the\n\t\t\t// print/printf function can take, adding an ellipsis\n\t\t\t// would break the program. For example:\n\t\t\t//\n\t\t\t//   func foo(arg1 string, arg2 ...interface{}) {\n\t\t\t//       fmt.Printf(\"%s %v\", arg1, arg2)\n\t\t\t//   }\n\t\t\treturn false\n\t\t}\n\t\tpass.ReportRangef(call, \"missing ... in args forwarded to %s-like function\", kind)\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc origin(obj types.Object) types.Object {\n\tswitch obj := obj.(type) {\n\tcase *types.Func:\n\t\treturn obj.Origin()\n\tcase *types.Var:\n\t\treturn obj.Origin()\n\t}\n\treturn obj\n}\n\n// isPrint records the print functions.\n// If a key ends in 'f' then it is assumed to be a formatted print.\n//\n// Keys are either values returned by (*types.Func).FullName,\n// or case-insensitive identifiers such as \"errorf\".\n//\n// The -funcs flag adds to this set.\n//\n// The set below includes facts for many important standard library\n// functions, even though the analysis is capable of deducing that, for\n// example, fmt.Printf forwards to fmt.Fprintf. We avoid relying on the\n// driver applying analyzers to standard packages because \"go vet\" does\n// not do so with gccgo, and nor do some other build systems.\nvar isPrint = stringSet{\n\t\"fmt.Appendf\":  true,\n\t\"fmt.Append\":   true,\n\t\"fmt.Appendln\": true,\n\t\"fmt.Errorf\":   true,\n\t\"fmt.Fprint\":   true,\n\t\"fmt.Fprintf\":  true,\n\t\"fmt.Fprintln\": true,\n\t\"fmt.Print\":    true,\n\t\"fmt.Printf\":   true,\n\t\"fmt.Println\":  true,\n\t\"fmt.Sprint\":   true,\n\t\"fmt.Sprintf\":  true,\n\t\"fmt.Sprintln\": true,\n\n\t\"runtime/trace.Logf\": true,\n\n\t\"log.Print\":             true,\n\t\"log.Printf\":            true,\n\t\"log.Println\":           true,\n\t\"log.Fatal\":             true,\n\t\"log.Fatalf\":            true,\n\t\"log.Fatalln\":           true,\n\t\"log.Panic\":             true,\n\t\"log.Panicf\":            true,\n\t\"log.Panicln\":           true,\n\t\"(*log.Logger).Fatal\":   true,\n\t\"(*log.Logger).Fatalf\":  true,\n\t\"(*log.Logger).Fatalln\": true,\n\t\"(*log.Logger).Panic\":   true,\n\t\"(*log.Logger).Panicf\":  true,\n\t\"(*log.Logger).Panicln\": true,\n\t\"(*log.Logger).Print\":   true,\n\t\"(*log.Logger).Printf\":  true,\n\t\"(*log.Logger).Println\": true,\n\n\t\"(*testing.common).Error\":  true,\n\t\"(*testing.common).Errorf\": true,\n\t\"(*testing.common).Fatal\":  true,\n\t\"(*testing.common).Fatalf\": true,\n\t\"(*testing.common).Log\":    true,\n\t\"(*testing.common).Logf\":   true,\n\t\"(*testing.common).Skip\":   true,\n\t\"(*testing.common).Skipf\":  true,\n\t\"(testing.TB).Error\":       true,\n\t\"(testing.TB).Errorf\":      true,\n\t\"(testing.TB).Fatal\":       true,\n\t\"(testing.TB).Fatalf\":      true,\n\t\"(testing.TB).Log\":         true,\n\t\"(testing.TB).Logf\":        true,\n\t\"(testing.TB).Skip\":        true,\n\t\"(testing.TB).Skipf\":       true,\n}\n\n// formatStringIndex returns the index of the format string (the last\n// non-variadic parameter) within the given printf-like call\n// expression, or -1 if unknown.\nfunc formatStringIndex(pass *analysis.Pass, call *ast.CallExpr) int {\n\ttyp := pass.TypesInfo.Types[call.Fun].Type\n\tif typ == nil {\n\t\treturn -1 // missing type\n\t}\n\tsig, ok := typ.(*types.Signature)\n\tif !ok {\n\t\treturn -1 // ill-typed\n\t}\n\tif !sig.Variadic() {\n\t\t// Skip checking non-variadic functions.\n\t\treturn -1\n\t}\n\tidx := sig.Params().Len() - 2\n\tif idx < 0 {\n\t\t// Skip checking variadic functions without\n\t\t// fixed arguments.\n\t\treturn -1\n\t}\n\treturn idx\n}\n\n// stringConstantExpr returns expression's string constant value.\n//\n// (\"\", false) is returned if expression isn't a string\n// constant.\nfunc stringConstantExpr(pass *analysis.Pass, expr ast.Expr) (string, bool) {\n\tlit := pass.TypesInfo.Types[expr].Value\n\tif lit != nil && lit.Kind() == constant.String {\n\t\treturn constant.StringVal(lit), true\n\t}\n\treturn \"\", false\n}\n\n// checkCalls triggers the print-specific checks for calls that invoke a print\n// function.\nfunc checkCalls(pass *analysis.Pass, res *Result) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.File)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t}\n\n\tvar fileVersion string // for selectively suppressing checks; \"\" if unknown.\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.File:\n\t\t\tfileVersion = versions.Lang(versions.FileVersion(pass.TypesInfo, n))\n\n\t\tcase *ast.CallExpr:\n\t\t\tif callee := typeutil.Callee(pass.TypesInfo, n); callee != nil {\n\t\t\t\tkind := callKind(pass, callee, res)\n\t\t\t\tswitch kind {\n\t\t\t\tcase KindPrintf, KindErrorf:\n\t\t\t\t\tcheckPrintf(pass, fileVersion, kind, n, fullname(callee))\n\t\t\t\tcase KindPrint:\n\t\t\t\t\tcheckPrint(pass, n, fullname(callee))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc fullname(obj types.Object) string {\n\tif fn, ok := obj.(*types.Func); ok {\n\t\treturn fn.FullName()\n\t}\n\treturn obj.Name()\n}\n\n// callKind returns the symbol of the called function\n// and its print/printf kind, if any.\n// (The symbol may be a var for an anonymous function.)\n// The result is memoized in res.funcs.\nfunc callKind(pass *analysis.Pass, obj types.Object, res *Result) Kind {\n\tkind, ok := res.funcs[obj]\n\tif !ok {\n\t\t// cache miss\n\t\t_, ok := isPrint[fullname(obj)]\n\t\tif !ok {\n\t\t\t// Next look up just \"printf\", for use with -printf.funcs.\n\t\t\t_, ok = isPrint[strings.ToLower(obj.Name())]\n\t\t}\n\t\tif ok {\n\t\t\t// well-known printf functions\n\t\t\tif fullname(obj) == \"fmt.Errorf\" {\n\t\t\t\tkind = KindErrorf\n\t\t\t} else if strings.HasSuffix(obj.Name(), \"f\") {\n\t\t\t\tkind = KindPrintf\n\t\t\t} else {\n\t\t\t\tkind = KindPrint\n\t\t\t}\n\t\t} else {\n\t\t\t// imported wrappers\n\t\t\t// Facts are associated with generic declarations, not instantiations.\n\t\t\tobj = origin(obj)\n\t\t\tvar fact isWrapper\n\t\t\tif pass.ImportObjectFact(obj, &fact) {\n\t\t\t\tkind = fact.Kind\n\t\t\t}\n\t\t}\n\t\tres.funcs[obj] = kind // cache\n\t}\n\treturn kind\n}\n\n// isFormatter reports whether t could satisfy fmt.Formatter.\n// The only interface method to look for is \"Format(State, rune)\".\nfunc isFormatter(typ types.Type) bool {\n\t// If the type is an interface, the value it holds might satisfy fmt.Formatter.\n\tif _, ok := typ.Underlying().(*types.Interface); ok {\n\t\t// Don't assume type parameters could be formatters. With the greater\n\t\t// expressiveness of constraint interface syntax we expect more type safety\n\t\t// when using type parameters.\n\t\tif !typeparams.IsTypeParam(typ) {\n\t\t\treturn true\n\t\t}\n\t}\n\tobj, _, _ := types.LookupFieldOrMethod(typ, false, nil, \"Format\")\n\tfn, ok := obj.(*types.Func)\n\tif !ok {\n\t\treturn false\n\t}\n\tsig := fn.Type().(*types.Signature)\n\treturn sig.Params().Len() == 2 &&\n\t\tsig.Results().Len() == 0 &&\n\t\ttypesinternal.IsTypeNamed(sig.Params().At(0).Type(), \"fmt\", \"State\") &&\n\t\ttypes.Identical(sig.Params().At(1).Type(), types.Typ[types.Rune])\n}\n\n// checkPrintf checks a call to a formatted print routine such as Printf.\nfunc checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.CallExpr, name string) {\n\tidx := formatStringIndex(pass, call)\n\tif idx < 0 || idx >= len(call.Args) {\n\t\treturn\n\t}\n\tformatArg := call.Args[idx]\n\tformat, ok := stringConstantExpr(pass, formatArg)\n\tif !ok {\n\t\t// Format string argument is non-constant.\n\n\t\t// It is a common mistake to call fmt.Printf(msg) with a\n\t\t// non-constant format string and no arguments:\n\t\t// if msg contains \"%\", misformatting occurs.\n\t\t// Report the problem and suggest a fix: fmt.Printf(\"%s\", msg).\n\t\t//\n\t\t// However, as described in golang/go#71485, this analysis can produce a\n\t\t// significant number of diagnostics in existing code, and the bugs it\n\t\t// finds are sometimes unlikely or inconsequential, and may not be worth\n\t\t// fixing for some users. Gating on language version allows us to avoid\n\t\t// breaking existing tests and CI scripts.\n\t\tif idx == len(call.Args)-1 &&\n\t\t\tfileVersion != \"\" && // fail open\n\t\t\tversions.AtLeast(fileVersion, versions.Go1_24) {\n\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos: formatArg.Pos(),\n\t\t\t\tEnd: formatArg.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"non-constant format string in call to %s\",\n\t\t\t\t\tname),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: `Insert \"%s\" format string`,\n\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\tPos:     formatArg.Pos(),\n\t\t\t\t\t\tEnd:     formatArg.Pos(),\n\t\t\t\t\t\tNewText: []byte(`\"%s\", `),\n\t\t\t\t\t}},\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t\treturn\n\t}\n\n\tfirstArg := idx + 1 // Arguments are immediately after format string.\n\tif !strings.Contains(format, \"%\") {\n\t\tif len(call.Args) > firstArg {\n\t\t\tpass.ReportRangef(call.Args[firstArg], \"%s call has arguments but no formatting directives\", name)\n\t\t}\n\t\treturn\n\t}\n\n\t// Pass the string constant value so\n\t// fmt.Sprintf(\"%\"+(\"s\"), \"hi\", 3) can be reported as\n\t// \"fmt.Sprintf call needs 1 arg but has 2 args\".\n\toperations, err := fmtstr.Parse(format, idx)\n\tif err != nil {\n\t\t// All error messages are in predicate form (\"call has a problem\")\n\t\t// so that they may be affixed into a subject (\"log.Printf \").\n\t\tpass.ReportRangef(formatArg, \"%s %s\", name, err)\n\t\treturn\n\t}\n\n\t// index of the highest used index.\n\tmaxArgIndex := firstArg - 1\n\tanyIndex := false\n\t// Check formats against args.\n\tfor _, op := range operations {\n\t\tif op.Prec.Index != -1 ||\n\t\t\top.Width.Index != -1 ||\n\t\t\top.Verb.Index != -1 {\n\t\t\tanyIndex = true\n\t\t}\n\t\trng := opRange(formatArg, op)\n\t\tif !okPrintfArg(pass, fileVersion, call, rng, &maxArgIndex, firstArg, name, op) {\n\t\t\t// One error per format is enough.\n\t\t\treturn\n\t\t}\n\t\tif op.Verb.Verb == 'w' {\n\t\t\tswitch kind {\n\t\t\tcase KindNone, KindPrint, KindPrintf:\n\t\t\t\tpass.ReportRangef(rng, \"%s does not support error-wrapping directive %%w\", name)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\t// Dotdotdot is hard.\n\tif call.Ellipsis.IsValid() && maxArgIndex >= len(call.Args)-2 {\n\t\treturn\n\t}\n\t// If any formats are indexed, extra arguments are ignored.\n\tif anyIndex {\n\t\treturn\n\t}\n\t// There should be no leftover arguments.\n\tif maxArgIndex+1 < len(call.Args) {\n\t\texpect := maxArgIndex + 1 - firstArg\n\t\tnumArgs := len(call.Args) - firstArg\n\t\tpass.ReportRangef(call, \"%s call needs %v but has %v\", name, count(expect, \"arg\"), count(numArgs, \"arg\"))\n\t}\n}\n\n// opRange returns the source range for the specified printf operation,\n// such as the position of the %v substring of \"...%v...\".\nfunc opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range {\n\tif lit, ok := formatArg.(*ast.BasicLit); ok {\n\t\trng, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End)\n\t\tif err == nil {\n\t\t\treturn rng // position of \"%v\"\n\t\t}\n\t}\n\treturn formatArg // entire format string\n}\n\n// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.\ntype printfArgType int\n\nconst (\n\targBool printfArgType = 1 << iota\n\targByte\n\targInt\n\targRune\n\targString\n\targFloat\n\targComplex\n\targPointer\n\targError\n\tanyType printfArgType = ^0\n)\n\ntype printVerb struct {\n\tverb  rune   // User may provide verb through Formatter; could be a rune.\n\tflags string // known flags are all ASCII\n\ttyp   printfArgType\n}\n\n// Common flag sets for printf verbs.\nconst (\n\tnoFlag       = \"\"\n\tnumFlag      = \" -+.0\"\n\tsharpNumFlag = \" -+.0#\"\n\tallFlags     = \" -+.0#\"\n)\n\n// printVerbs identifies which flags are known to printf for each verb.\nvar printVerbs = []printVerb{\n\t// '-' is a width modifier, always valid.\n\t// '.' is a precision for float, max width for strings.\n\t// '+' is required sign for numbers, Go format for %v.\n\t// '#' is alternate format for several verbs.\n\t// ' ' is spacer for numbers\n\t{'%', noFlag, 0},\n\t{'b', sharpNumFlag, argInt | argFloat | argComplex | argPointer},\n\t{'c', \"-\", argRune | argInt},\n\t{'d', numFlag, argInt | argPointer},\n\t{'e', sharpNumFlag, argFloat | argComplex},\n\t{'E', sharpNumFlag, argFloat | argComplex},\n\t{'f', sharpNumFlag, argFloat | argComplex},\n\t{'F', sharpNumFlag, argFloat | argComplex},\n\t{'g', sharpNumFlag, argFloat | argComplex},\n\t{'G', sharpNumFlag, argFloat | argComplex},\n\t{'o', sharpNumFlag, argInt | argPointer},\n\t{'O', sharpNumFlag, argInt | argPointer},\n\t{'p', \"-#\", argPointer},\n\t{'q', \" -+.0#\", argRune | argInt | argString}, // note: when analyzing go1.26 code, argInt => argByte\n\t{'s', \" -+.0\", argString},\n\t{'t', \"-\", argBool},\n\t{'T', \"-\", anyType},\n\t{'U', \"-#\", argRune | argInt},\n\t{'v', allFlags, anyType},\n\t{'w', allFlags, argError},\n\t{'x', sharpNumFlag, argRune | argInt | argString | argPointer | argFloat | argComplex},\n\t{'X', sharpNumFlag, argRune | argInt | argString | argPointer | argFloat | argComplex},\n}\n\n// okPrintfArg compares the operation to the arguments actually present,\n// reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index.\n// If the final argument is ellipsissed, there's little it can do for that.\nfunc okPrintfArg(pass *analysis.Pass, fileVersion string, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) {\n\tverb := operation.Verb.Verb\n\tvar v printVerb\n\tfound := false\n\t// Linear scan is fast enough for a small list.\n\tfor _, v = range printVerbs {\n\t\tif v.verb == verb {\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// When analyzing go1.26 code, rune and byte are the only %q integers (#72850).\n\tif verb == 'q' &&\n\t\tfileVersion != \"\" && // fail open\n\t\tversions.AtLeast(fileVersion, versions.Go1_26) {\n\t\tv.typ = argRune | argByte | argString\n\t}\n\n\t// Could verb's arg implement fmt.Formatter?\n\t// Skip check for the %w verb, which requires an error.\n\tformatter := false\n\tif v.typ != argError && operation.Verb.ArgIndex < len(call.Args) {\n\t\tif tv, ok := pass.TypesInfo.Types[call.Args[operation.Verb.ArgIndex]]; ok {\n\t\t\tformatter = isFormatter(tv.Type)\n\t\t}\n\t}\n\n\tif !formatter {\n\t\tif !found {\n\t\t\tpass.ReportRangef(rng, \"%s format %s has unknown verb %c\", name, operation.Text, verb)\n\t\t\treturn false\n\t\t}\n\t\tfor _, flag := range operation.Flags {\n\t\t\t// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.\n\t\t\t// See issues 23598 and 23605.\n\t\t\tif flag == '0' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !strings.ContainsRune(v.flags, rune(flag)) {\n\t\t\t\tpass.ReportRangef(rng, \"%s format %s has unrecognized flag %c\", name, operation.Text, flag)\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\n\tvar argIndexes []int\n\t// First check for *.\n\tif operation.Width.Dynamic != -1 {\n\t\targIndexes = append(argIndexes, operation.Width.Dynamic)\n\t}\n\tif operation.Prec.Dynamic != -1 {\n\t\targIndexes = append(argIndexes, operation.Prec.Dynamic)\n\t}\n\t// If len(argIndexes)>0, we have something like %.*s and all\n\t// indexes in argIndexes must be an integer.\n\tfor _, argIndex := range argIndexes {\n\t\tif !argCanBeChecked(pass, call, rng, argIndex, firstArg, operation, name) {\n\t\t\treturn\n\t\t}\n\t\targ := call.Args[argIndex]\n\t\tif reason, ok := matchArgType(pass, argInt, arg); !ok {\n\t\t\tdetails := \"\"\n\t\t\tif reason != \"\" {\n\t\t\t\tdetails = \" (\" + reason + \")\"\n\t\t\t}\n\t\t\tpass.ReportRangef(rng, \"%s format %s uses non-int %s%s as argument of *\", name, operation.Text, astutil.Format(pass.Fset, arg), details)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Collect to update maxArgNum in one loop.\n\tif operation.Verb.ArgIndex != -1 && verb != '%' {\n\t\targIndexes = append(argIndexes, operation.Verb.ArgIndex)\n\t}\n\tfor _, index := range argIndexes {\n\t\t*maxArgIndex = max(*maxArgIndex, index)\n\t}\n\n\t// Special case for '%', go will print \"fmt.Printf(\"%10.2%%dhello\", 4)\"\n\t// as \"%4hello\", discard any runes between the two '%'s, and treat the verb '%'\n\t// as an ordinary rune, so early return to skip the type check.\n\tif verb == '%' || formatter {\n\t\treturn true\n\t}\n\n\t// Now check verb's type.\n\tverbArgIndex := operation.Verb.ArgIndex\n\tif !argCanBeChecked(pass, call, rng, verbArgIndex, firstArg, operation, name) {\n\t\treturn false\n\t}\n\targ := call.Args[verbArgIndex]\n\tif isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' {\n\t\tpass.ReportRangef(rng, \"%s format %s arg %s is a func value, not called\", name, operation.Text, astutil.Format(pass.Fset, arg))\n\t\treturn false\n\t}\n\tif reason, ok := matchArgType(pass, v.typ, arg); !ok {\n\t\ttypeString := \"\"\n\t\tif typ := pass.TypesInfo.Types[arg].Type; typ != nil {\n\t\t\ttypeString = typ.String()\n\t\t}\n\t\tdetails := \"\"\n\t\tif reason != \"\" {\n\t\t\tdetails = \" (\" + reason + \")\"\n\t\t}\n\t\tpass.ReportRangef(rng, \"%s format %s has arg %s of wrong type %s%s\", name, operation.Text, astutil.Format(pass.Fset, arg), typeString, details)\n\t\treturn false\n\t}\n\t// Detect recursive formatting via value's String/Error methods.\n\t// The '#' flag suppresses the methods, except with %x, %X, and %q.\n\tif v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, \"#\") || strings.ContainsRune(\"qxX\", v.verb)) {\n\t\tif methodName, ok := recursiveStringer(pass, arg); ok {\n\t\t\tpass.ReportRangef(rng, \"%s format %s with arg %s causes recursive %s method call\", name, operation.Text, astutil.Format(pass.Fset, arg), methodName)\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// recursiveStringer reports whether the argument e is a potential\n// recursive call to stringer or is an error, such as t and &t in these examples:\n//\n//\tfunc (t *T) String() string { printf(\"%s\",  t) }\n//\tfunc (t  T) Error() string { printf(\"%s\",  t) }\n//\tfunc (t  T) String() string { printf(\"%s\", &t) }\nfunc recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) {\n\ttyp := pass.TypesInfo.Types[e].Type\n\n\t// It's unlikely to be a recursive stringer if it has a Format method.\n\tif isFormatter(typ) {\n\t\treturn \"\", false\n\t}\n\n\t// Does e allow e.String() or e.Error()?\n\tstrObj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, \"String\")\n\tstrMethod, strOk := strObj.(*types.Func)\n\terrObj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, \"Error\")\n\terrMethod, errOk := errObj.(*types.Func)\n\tif !strOk && !errOk {\n\t\treturn \"\", false\n\t}\n\n\t// inScope returns true if e is in the scope of f.\n\tinScope := func(e ast.Expr, f *types.Func) bool {\n\t\treturn f.Scope() != nil && f.Scope().Contains(e.Pos())\n\t}\n\n\t// Is the expression e within the body of that String or Error method?\n\tvar method *types.Func\n\tif strOk && strMethod.Pkg() == pass.Pkg && inScope(e, strMethod) {\n\t\tmethod = strMethod\n\t} else if errOk && errMethod.Pkg() == pass.Pkg && inScope(e, errMethod) {\n\t\tmethod = errMethod\n\t} else {\n\t\treturn \"\", false\n\t}\n\n\tsig := method.Type().(*types.Signature)\n\tif !isStringer(sig) {\n\t\treturn \"\", false\n\t}\n\n\t// Is it the receiver r, or &r?\n\tif u, ok := e.(*ast.UnaryExpr); ok && u.Op == token.AND {\n\t\te = u.X // strip off & from &r\n\t}\n\tif id, ok := e.(*ast.Ident); ok {\n\t\tif pass.TypesInfo.Uses[id] == sig.Recv() {\n\t\t\treturn method.FullName(), true\n\t\t}\n\t}\n\treturn \"\", false\n}\n\n// isStringer reports whether the method signature matches the String() definition in fmt.Stringer.\nfunc isStringer(sig *types.Signature) bool {\n\treturn sig.Params().Len() == 0 &&\n\t\tsig.Results().Len() == 1 &&\n\t\tsig.Results().At(0).Type() == types.Typ[types.String]\n}\n\n// isFunctionValue reports whether the expression is a function as opposed to a function call.\n// It is almost always a mistake to print a function value.\nfunc isFunctionValue(pass *analysis.Pass, e ast.Expr) bool {\n\tif typ := pass.TypesInfo.Types[e].Type; typ != nil {\n\t\t// Don't call Underlying: a named func type with a String method is ok.\n\t\t// TODO(adonovan): it would be more precise to check isStringer.\n\t\t_, ok := typ.(*types.Signature)\n\t\treturn ok\n\t}\n\treturn false\n}\n\n// argCanBeChecked reports whether the specified argument is statically present;\n// it may be beyond the list of arguments or in a terminal slice... argument, which\n// means we can't see it.\nfunc argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool {\n\tif argIndex <= 0 {\n\t\t// Shouldn't happen, so catch it with prejudice.\n\t\tpanic(\"negative argIndex\")\n\t}\n\tif argIndex < len(call.Args)-1 {\n\t\treturn true // Always OK.\n\t}\n\tif call.Ellipsis.IsValid() {\n\t\treturn false // We just can't tell; there could be many more arguments.\n\t}\n\tif argIndex < len(call.Args) {\n\t\treturn true\n\t}\n\t// There are bad indexes in the format or there are fewer arguments than the format needs.\n\t// This is the argument number relative to the format: Printf(\"%s\", \"hi\") will give 1 for the \"hi\".\n\targ := argIndex - firstArg + 1 // People think of arguments as 1-indexed.\n\tpass.ReportRangef(rng, \"%s format %s reads arg #%d, but call has %v\", name, operation.Text, arg, count(len(call.Args)-firstArg, \"arg\"))\n\treturn false\n}\n\n// printFormatRE is the regexp we match and report as a possible format string\n// in the first argument to unformatted prints like fmt.Print.\n// We exclude the space flag, so that printing a string like \"x % y\" is not reported as a format.\nvar printFormatRE = regexp.MustCompile(`%` + flagsRE + numOptRE + `\\.?` + numOptRE + indexOptRE + verbRE)\n\nconst (\n\tflagsRE    = `[+\\-#]*`\n\tindexOptRE = `(\\[[0-9]+\\])?`\n\tnumOptRE   = `([0-9]+|` + indexOptRE + `\\*)?`\n\tverbRE     = `[bcdefgopqstvxEFGTUX]`\n)\n\n// checkPrint checks a call to an unformatted print routine such as Println.\nfunc checkPrint(pass *analysis.Pass, call *ast.CallExpr, name string) {\n\tfirstArg := 0\n\ttyp := pass.TypesInfo.Types[call.Fun].Type\n\tif typ == nil {\n\t\t// Skip checking functions with unknown type.\n\t\treturn\n\t}\n\tif sig, ok := typ.Underlying().(*types.Signature); ok {\n\t\tif !sig.Variadic() {\n\t\t\t// Skip checking non-variadic functions.\n\t\t\treturn\n\t\t}\n\t\tparams := sig.Params()\n\t\tfirstArg = params.Len() - 1\n\n\t\ttyp := params.At(firstArg).Type()\n\t\ttyp = typ.(*types.Slice).Elem()\n\t\tit, ok := types.Unalias(typ).(*types.Interface)\n\t\tif !ok || !it.Empty() {\n\t\t\t// Skip variadic functions accepting non-interface{} args.\n\t\t\treturn\n\t\t}\n\t}\n\targs := call.Args\n\tif len(args) <= firstArg {\n\t\t// Skip calls without variadic args.\n\t\treturn\n\t}\n\targs = args[firstArg:]\n\n\tif firstArg == 0 {\n\t\tif sel, ok := call.Args[0].(*ast.SelectorExpr); ok {\n\t\t\tif x, ok := sel.X.(*ast.Ident); ok {\n\t\t\t\tif x.Name == \"os\" && strings.HasPrefix(sel.Sel.Name, \"Std\") {\n\t\t\t\t\tpass.ReportRangef(call, \"%s does not take io.Writer but has first arg %s\", name, astutil.Format(pass.Fset, call.Args[0]))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\targ := args[0]\n\tif s, ok := stringConstantExpr(pass, arg); ok {\n\t\t// Ignore trailing % character\n\t\t// The % in \"abc 0.0%\" couldn't be a formatting directive.\n\t\ts = strings.TrimSuffix(s, \"%\")\n\t\tif strings.Contains(s, \"%\") {\n\t\t\tfor _, m := range printFormatRE.FindAllString(s, -1) {\n\t\t\t\t// Allow %XX where XX are hex digits,\n\t\t\t\t// as this is common in URLs.\n\t\t\t\tif len(m) >= 3 && isHex(m[1]) && isHex(m[2]) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tpass.ReportRangef(call, \"%s call has possible Printf formatting directive %s\", name, m)\n\t\t\t\tbreak // report only the first one\n\t\t\t}\n\t\t}\n\t}\n\tif strings.HasSuffix(name, \"ln\") {\n\t\t// The last item, if a string, should not have a newline.\n\t\targ = args[len(args)-1]\n\t\tif s, ok := stringConstantExpr(pass, arg); ok {\n\t\t\tif strings.HasSuffix(s, \"\\n\") {\n\t\t\t\tpass.ReportRangef(call, \"%s arg list ends with redundant newline\", name)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, arg := range args {\n\t\tif isFunctionValue(pass, arg) {\n\t\t\tpass.ReportRangef(call, \"%s arg %s is a func value, not called\", name, astutil.Format(pass.Fset, arg))\n\t\t}\n\t\tif methodName, ok := recursiveStringer(pass, arg); ok {\n\t\t\tpass.ReportRangef(call, \"%s arg %s causes recursive call to %s method\", name, astutil.Format(pass.Fset, arg), methodName)\n\t\t}\n\t}\n}\n\n// count(n, what) returns \"1 what\" or \"N whats\"\n// (assuming the plural of what is whats).\nfunc count(n int, what string) string {\n\tif n == 1 {\n\t\treturn \"1 \" + what\n\t}\n\treturn fmt.Sprintf(\"%d %ss\", n, what)\n}\n\n// stringSet is a set-of-nonempty-strings-valued flag.\n// Note: elements without a '.' get lower-cased.\ntype stringSet map[string]bool\n\nfunc (ss stringSet) String() string {\n\tvar list []string\n\tfor name := range ss {\n\t\tlist = append(list, name)\n\t}\n\tsort.Strings(list)\n\treturn strings.Join(list, \",\")\n}\n\nfunc (ss stringSet) Set(flag string) error {\n\tfor name := range strings.SplitSeq(flag, \",\") {\n\t\tif len(name) == 0 {\n\t\t\treturn fmt.Errorf(\"empty string\")\n\t\t}\n\t\tif !strings.Contains(name, \".\") {\n\t\t\tname = strings.ToLower(name)\n\t\t}\n\t\tss[name] = true\n\t}\n\treturn nil\n}\n\n// isHex reports whether b is a hex digit.\nfunc isHex(b byte) bool {\n\treturn '0' <= b && b <= '9' ||\n\t\t'A' <= b && b <= 'F' ||\n\t\t'a' <= b && b <= 'f'\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/printf_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage printf_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tprintf.Analyzer.Flags.Set(\"funcs\", \"Warn,Warnf\")\n\n\tanalysistest.Run(t, testdata, printf.Analyzer,\n\t\t\"a\", \"b\", \"nofmt\", \"nonconst\", \"typeparams\", \"issue68744\", \"issue70572\", \"issue72850\", \"issue76616\")\n}\n\nfunc TestNonConstantFmtString_Go123(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"nonconst_go123.txtar\"))\n\tanalysistest.RunWithSuggestedFixes(t, dir, printf.Analyzer, \"example.com/nonconst\")\n}\n\nfunc TestNonConstantFmtString_Go124(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 24)\n\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"nonconst_go124.txtar\"))\n\tanalysistest.RunWithSuggestedFixes(t, dir, printf.Analyzer, \"example.com/nonconst\")\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/nonconst_go123.txtar",
    "content": "This test checks for the correct suppression (or activation) of the\nnon-constant format string check (golang/go#60529), in a go1.23 module.\n\nSee golang/go#71485 for details.\n\n-- go.mod --\nmodule example.com/nonconst\n\ngo 1.23\n\n-- nonconst.go --\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc _(s string) {\n\tfmt.Printf(s)\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, s)\n\tlog.Printf(s)\n}\n\n-- nonconst_go124.go --\n//go:build go1.24\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// With Go 1.24, the analyzer should be activated, as this is a go1.24 file.\nfunc _(s string) {\n\tfmt.Printf(s) // want `non-constant format string in call to fmt.Printf`\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, s) // want `non-constant format string in call to fmt.Fprintf`\n\tlog.Printf(s)             // want `non-constant format string in call to log.Printf`\n}\n\n-- nonconst_go124.go.golden --\n//go:build go1.24\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// With Go 1.24, the analyzer should be activated, as this is a go1.24 file.\nfunc _(s string) {\n\tfmt.Printf(\"%s\", s) // want `non-constant format string in call to fmt.Printf`\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, \"%s\", s) // want `non-constant format string in call to fmt.Fprintf`\n\tlog.Printf(\"%s\", s)             // want `non-constant format string in call to log.Printf`\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/nonconst_go124.txtar",
    "content": "This test checks for the correct suppression (or activation) of the\nnon-constant format string check (golang/go#60529), in a go1.24 module.\n\nSee golang/go#71485 for details.\n\n-- go.mod --\nmodule example.com/nonconst\n\ngo 1.24\n\n-- nonconst.go --\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc _(s string) {\n\tfmt.Printf(s) // want `non-constant format string in call to fmt.Printf`\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, s) // want `non-constant format string in call to fmt.Fprintf`\n\tlog.Printf(s)             // want `non-constant format string in call to log.Printf`\n}\n\n-- nonconst.go.golden --\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc _(s string) {\n\tfmt.Printf(\"%s\", s) // want `non-constant format string in call to fmt.Printf`\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, \"%s\", s) // want `non-constant format string in call to fmt.Fprintf`\n\tlog.Printf(\"%s\", s)             // want `non-constant format string in call to log.Printf`\n}\n\n-- nonconst_go123.go --\n//go:build go1.23\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// The analyzer should be silent, as this is a go1.23 file.\nfunc _(s string) {\n\tfmt.Printf(s)\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, s)\n\tlog.Printf(s)\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/a/a.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the printf checker.\n\npackage a\n\nimport (\n\t\"fmt\"\n\tlogpkg \"log\" // renamed to make it harder to see\n\t\"math\"\n\t\"os\"\n\t\"testing\"\n\t\"unsafe\" // just for test case printing unsafe.Pointer\n\n\t// For testing printf-like functions from external package.\n\t// \"github.com/foobar/externalprintf\"\n\t\"b\"\n)\n\nfunc UnsafePointerPrintfTest() {\n\tvar up unsafe.Pointer\n\tfmt.Printf(\"%p, %x %X\", up, up, up)\n}\n\n// Error methods that do not satisfy the Error interface and should be checked.\ntype errorTest1 int\n\nfunc (errorTest1) Error(...interface{}) string {\n\treturn \"hi\"\n}\n\ntype errorTest2 int // Analogous to testing's *T type.\nfunc (errorTest2) Error(...interface{}) {\n}\n\ntype errorTest3 int\n\nfunc (errorTest3) Error() { // No return value.\n}\n\ntype errorTest4 int\n\nfunc (errorTest4) Error() int { // Different return type.\n\treturn 3\n}\n\ntype errorTest5 int\n\nfunc (errorTest5) error() { // niladic; don't complain if no args (was bug)\n}\n\ntype errorTestOK int\n\nfunc (errorTestOK) Error() string { return \"\" }\n\n// This function never executes, but it serves as a simple test for the program.\n// Test with make test.\nfunc PrintfTests() {\n\tvar b bool\n\tvar i int\n\tvar r rune\n\tvar s string\n\tvar x float64\n\tvar p *int\n\tvar imap map[int]int\n\tvar fslice []float64\n\tvar c complex64\n\tvar err error\n\t// Some good format/argtypes\n\tfmt.Printf(\"\")\n\tfmt.Printf(\"%b %b %b\", 3, i, x)\n\tfmt.Printf(\"%c %c %c %c\", 3, i, 'x', r)\n\tfmt.Printf(\"%d %d %d\", 3, i, imap)\n\tfmt.Printf(\"%e %e %e %e\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%E %E %E %E\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%f %f %f %f\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%F %F %F %F\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%g %g %g %g\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%G %G %G %G\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%b %b %b %b\", 3e9, x, fslice, c)\n\tfmt.Printf(\"%o %o\", 3, i)\n\tfmt.Printf(\"%O %O\", 3, i)\n\tfmt.Printf(\"%p\", p)\n\tfmt.Printf(\"%q %q %q\", byte(i), 'x', r)\n\tfmt.Printf(\"%s %s %s\", \"hi\", s, []byte{65})\n\tfmt.Printf(\"%t %t\", true, b)\n\tfmt.Printf(\"%T %T\", 3, i)\n\tfmt.Printf(\"%U %U\", 3, i)\n\tfmt.Printf(\"%v %v\", 3, i)\n\tfmt.Printf(\"%x %x %x %x %x %x %x\", 3, i, \"hi\", s, x, c, fslice)\n\tfmt.Printf(\"%X %X %X %X %X %X %X\", 3, i, \"hi\", s, x, c, fslice)\n\tfmt.Printf(\"%.*s %d %g\", 3, \"hi\", 23, 2.3)\n\tfmt.Printf(\"%s\", &stringerv)\n\tfmt.Printf(\"%v\", &stringerv)\n\tfmt.Printf(\"%T\", &stringerv)\n\tfmt.Printf(\"%s\", &embeddedStringerv)\n\tfmt.Printf(\"%v\", &embeddedStringerv)\n\tfmt.Printf(\"%T\", &embeddedStringerv)\n\tfmt.Printf(\"%v\", notstringerv)\n\tfmt.Printf(\"%T\", notstringerv)\n\tfmt.Printf(\"%q\", stringerarrayv)\n\tfmt.Printf(\"%v\", stringerarrayv)\n\tfmt.Printf(\"%s\", stringerarrayv)\n\tfmt.Printf(\"%v\", notstringerarrayv)\n\tfmt.Printf(\"%T\", notstringerarrayv)\n\tfmt.Printf(\"%d\", new(fmt.Formatter))\n\tfmt.Printf(\"%*%\", 2)                              // Ridiculous but allowed.\n\tfmt.Printf(\"%s\", interface{}(nil))                // Nothing useful we can say.\n\tfmt.Printf(\"%a\", interface{}(new(BoolFormatter))) // Could be a fmt.Formatter.\n\n\tfmt.Printf(\"%g\", 1+2i)\n\tfmt.Printf(\"%#e %#E %#f %#F %#g %#G\", 1.2, 1.2, 1.2, 1.2, 1.2, 1.2) // OK since Go 1.9\n\t// Some bad format/argTypes\n\tfmt.Printf(\"%b\", \"hi\")                      // want \"fmt.Printf format %b has arg \\x22hi\\x22 of wrong type string\"\n\tfmt.Printf(\"%t\", c)                         // want \"fmt.Printf format %t has arg c of wrong type complex64\"\n\tfmt.Printf(\"%t\", 1+2i)                      // want `fmt.Printf format %t has arg 1 \\+ 2i of wrong type complex128`\n\tfmt.Printf(\"%c\", 2.3)                       // want \"fmt.Printf format %c has arg 2.3 of wrong type float64\"\n\tfmt.Printf(\"%d\", 2.3)                       // want \"fmt.Printf format %d has arg 2.3 of wrong type float64\"\n\tfmt.Printf(\"%e\", \"hi\")                      // want `fmt.Printf format %e has arg \"hi\" of wrong type string`\n\tfmt.Printf(\"%E\", true)                      // want \"fmt.Printf format %E has arg true of wrong type bool\"\n\tfmt.Printf(\"%f\", \"hi\")                      // want \"fmt.Printf format %f has arg \\x22hi\\x22 of wrong type string\"\n\tfmt.Printf(\"%F\", 'x')                       // want \"fmt.Printf format %F has arg 'x' of wrong type rune\"\n\tfmt.Printf(\"%g\", \"hi\")                      // want `fmt.Printf format %g has arg \"hi\" of wrong type string`\n\tfmt.Printf(\"%g\", imap)                      // want `fmt.Printf format %g has arg imap of wrong type map\\[int\\]int`\n\tfmt.Printf(\"%G\", i)                         // want \"fmt.Printf format %G has arg i of wrong type int\"\n\tfmt.Printf(\"%o\", x)                         // want \"fmt.Printf format %o has arg x of wrong type float64\"\n\tfmt.Printf(\"%O\", x)                         // want \"fmt.Printf format %O has arg x of wrong type float64\"\n\tfmt.Printf(\"%p\", nil)                       // want \"fmt.Printf format %p has arg nil of wrong type untyped nil\"\n\tfmt.Printf(\"%p\", 23)                        // want \"fmt.Printf format %p has arg 23 of wrong type int\"\n\tfmt.Printf(\"%q\", x)                         // want \"fmt.Printf format %q has arg x of wrong type float64\"\n\tfmt.Printf(\"%s\", b)                         // want \"fmt.Printf format %s has arg b of wrong type bool\"\n\tfmt.Printf(\"%s\", byte(65))                  // want `fmt.Printf format %s has arg byte\\(65\\) of wrong type byte`\n\tfmt.Printf(\"%t\", 23)                        // want \"fmt.Printf format %t has arg 23 of wrong type int\"\n\tfmt.Printf(\"%U\", x)                         // want \"fmt.Printf format %U has arg x of wrong type float64\"\n\tfmt.Printf(\"%x\", nil)                       // want \"fmt.Printf format %x has arg nil of wrong type untyped nil\"\n\tfmt.Printf(\"%s\", stringerv)                 // want \"fmt.Printf format %s has arg stringerv of wrong type a.ptrStringer\"\n\tfmt.Printf(\"%t\", stringerv)                 // want \"fmt.Printf format %t has arg stringerv of wrong type a.ptrStringer\"\n\tfmt.Printf(\"%s\", embeddedStringerv)         // want \"fmt.Printf format %s has arg embeddedStringerv of wrong type a.embeddedStringer\"\n\tfmt.Printf(\"%t\", embeddedStringerv)         // want \"fmt.Printf format %t has arg embeddedStringerv of wrong type a.embeddedStringer\"\n\tfmt.Printf(\"%q\", notstringerv)              // want \"fmt.Printf format %q has arg notstringerv of wrong type a.notstringer\"\n\tfmt.Printf(\"%t\", notstringerv)              // want \"fmt.Printf format %t has arg notstringerv of wrong type a.notstringer\"\n\tfmt.Printf(\"%t\", stringerarrayv)            // want \"fmt.Printf format %t has arg stringerarrayv of wrong type a.stringerarray\"\n\tfmt.Printf(\"%t\", notstringerarrayv)         // want \"fmt.Printf format %t has arg notstringerarrayv of wrong type a.notstringerarray\"\n\tfmt.Printf(\"%q\", notstringerarrayv)         // want \"fmt.Printf format %q has arg notstringerarrayv of wrong type a.notstringerarray\"\n\tfmt.Printf(\"%d\", BoolFormatter(true))       // want `fmt.Printf format %d has arg BoolFormatter\\(true\\) of wrong type a.BoolFormatter`\n\tfmt.Printf(\"%z\", FormatterVal(true))        // correct (the type is responsible for formatting)\n\tfmt.Printf(\"%d\", FormatterVal(true))        // correct (the type is responsible for formatting)\n\tfmt.Printf(\"%s\", nonemptyinterface)         // correct (the type is responsible for formatting)\n\tfmt.Printf(\"%.*s %d %6g\", 3, \"hi\", 23, 'x') // want \"fmt.Printf format %6g has arg 'x' of wrong type rune\"\n\tfmt.Println()                               // not an error\n\tfmt.Println(\"%s\", \"hi\")                     // want \"fmt.Println call has possible Printf formatting directive %s\"\n\tfmt.Println(\"%v\", \"hi\")                     // want \"fmt.Println call has possible Printf formatting directive %v\"\n\tfmt.Println(\"%T\", \"hi\")                     // want \"fmt.Println call has possible Printf formatting directive %T\"\n\tfmt.Println(\"%s\"+\" there\", \"hi\")            // want \"fmt.Println call has possible Printf formatting directive %s\"\n\tfmt.Println(\"http://foo.com?q%2Fabc\")       // no diagnostic: %XX is excepted\n\tfmt.Println(\"http://foo.com?q%2Fabc-%s\")    // want\"fmt.Println call has possible Printf formatting directive %s\"\n\tfmt.Println(\"0.0%\")                         // correct (trailing % couldn't be a formatting directive)\n\tfmt.Printf(\"%s\", \"hi\", 3)                   // want \"fmt.Printf call needs 1 arg but has 2 args\"\n\t_ = fmt.Sprintf(\"%\"+(\"s\"), \"hi\", 3)         // want \"fmt.Sprintf call needs 1 arg but has 2 args\"\n\tfmt.Printf(\"%s%%%d\", \"hi\", 3)               // correct\n\tfmt.Printf(\"%08s\", \"woo\")                   // correct\n\tfmt.Printf(\"% 8s\", \"woo\")                   // correct\n\tfmt.Printf(\"%.*d\", 3, 3)                    // correct\n\tfmt.Printf(\"%.*d x\", 3, 3, 3, 3)            // want \"fmt.Printf call needs 2 args but has 4 args\"\n\tfmt.Printf(\"%.*d x\", \"hi\", 3)               // want `fmt.Printf format %.*d uses non-int \"hi\" as argument of \\*`\n\tfmt.Printf(\"%.*d x\", i, 3)                  // correct\n\tfmt.Printf(\"%.*d x\", s, 3)                  // want `fmt.Printf format %.\\*d uses non-int s as argument of \\*`\n\tfmt.Printf(\"%*% x\", 0.22)                   // want `fmt.Printf format %\\*% uses non-int 0.22 as argument of \\*`\n\tfmt.Printf(\"%q %q\", multi()...)             // ok\n\tfmt.Printf(\"%#q\", `blah`)                   // ok\n\tfmt.Printf(\"%#b\", 3)                        // ok\n\tfmt.Printf(\"%q\", 3)                         // ok before go1.26 (#72850)\n\n\t// printf(\"now is the time\", \"buddy\")          // no error \"a.printf call has arguments but no formatting directives\"\n\tPrintf(\"now is the time\", \"buddy\") // want \"a.Printf call has arguments but no formatting directives\"\n\tPrintf(\"hi\")                       // ok\n\tconst format = \"%s %s\\n\"\n\tPrintf(format, \"hi\", \"there\")\n\tPrintf(format, \"hi\")              // want \"a.Printf format %s reads arg #2, but call has 1 arg$\"\n\tPrintf(\"%s %d %.3v %q\", \"str\", 4) // want \"a.Printf format %.3v reads arg #3, but call has 2 args\"\n\tf := new(ptrStringer)\n\tf.Warn(0, \"%s\", \"hello\", 3)           // want `\\(\\*a.ptrStringer\\).Warn call has possible Printf formatting directive %s`\n\tf.Warnf(0, \"%s\", \"hello\", 3)          // want `\\(\\*a.ptrStringer\\).Warnf call needs 1 arg but has 2 args`\n\tf.Warnf(0, \"%r\", \"hello\")             // want `\\(\\*a.ptrStringer\\).Warnf format %r has unknown verb r`\n\tf.Warnf(0, \"%#s\", \"hello\")            // want `\\(\\*a.ptrStringer\\).Warnf format %#s has unrecognized flag #`\n\tf.Warn2(0, \"%s\", \"hello\", 3)          // want `\\(\\*a.ptrStringer\\).Warn2 call has possible Printf formatting directive %s`\n\tf.Warnf2(0, \"%s\", \"hello\", 3)         // want `\\(\\*a.ptrStringer\\).Warnf2 call needs 1 arg but has 2 args`\n\tf.Warnf2(0, \"%r\", \"hello\")            // want `\\(\\*a.ptrStringer\\).Warnf2 format %r has unknown verb r`\n\tf.Warnf2(0, \"%#s\", \"hello\")           // want `\\(\\*a.ptrStringer\\).Warnf2 format %#s has unrecognized flag #`\n\tf.Wrap(0, \"%s\", \"hello\", 3)           // want `\\(\\*a.ptrStringer\\).Wrap call has possible Printf formatting directive %s`\n\tf.Wrapf(0, \"%s\", \"hello\", 3)          // want `\\(\\*a.ptrStringer\\).Wrapf call needs 1 arg but has 2 args`\n\tf.Wrapf(0, \"%r\", \"hello\")             // want `\\(\\*a.ptrStringer\\).Wrapf format %r has unknown verb r`\n\tf.Wrapf(0, \"%#s\", \"hello\")            // want `\\(\\*a.ptrStringer\\).Wrapf format %#s has unrecognized flag #`\n\tf.Wrap2(0, \"%s\", \"hello\", 3)          // want `\\(\\*a.ptrStringer\\).Wrap2 call has possible Printf formatting directive %s`\n\tf.Wrapf2(0, \"%s\", \"hello\", 3)         // want `\\(\\*a.ptrStringer\\).Wrapf2 call needs 1 arg but has 2 args`\n\tf.Wrapf2(0, \"%r\", \"hello\")            // want `\\(\\*a.ptrStringer\\).Wrapf2 format %r has unknown verb r`\n\tf.Wrapf2(0, \"%#s\", \"hello\")           // want `\\(\\*a.ptrStringer\\).Wrapf2 format %#s has unrecognized flag #`\n\tfmt.Printf(\"%#s\", FormatterVal(true)) // correct (the type is responsible for formatting)\n\tPrintf(\"d%\", 2)                       // want \"a.Printf format % is missing verb at end of string\"\n\tPrintf(\"%d\", percentDV)\n\tPrintf(\"%d\", &percentDV)\n\tPrintf(\"%d\", notPercentDV)  // want \"a.Printf format %d has arg notPercentDV of wrong type a.notPercentDStruct\"\n\tPrintf(\"%d\", &notPercentDV) // want `a.Printf format %d has arg &notPercentDV of wrong type \\*a.notPercentDStruct`\n\tPrintf(\"%p\", &notPercentDV) // Works regardless: we print it as a pointer.\n\tPrintf(\"%q\", &percentDV)    // want `a.Printf format %q has arg &percentDV of wrong type \\*a.percentDStruct`\n\tPrintf(\"%s\", percentSV)\n\tPrintf(\"%s\", &percentSV)\n\t// Good argument reorderings.\n\tPrintf(\"%[1]d\", 3)\n\tPrintf(\"%[1]*d\", 3, 1)\n\tPrintf(\"%[2]*[1]d\", 1, 3)\n\tPrintf(\"%[2]*.[1]*[3]d\", 2, 3, 4)\n\tfmt.Fprintf(os.Stderr, \"%[2]*.[1]*[3]d\", 2, 3, 4) // Use Fprintf to make sure we count arguments correctly.\n\t// Bad argument reorderings.\n\tPrintf(\"%[xd\", 3)                      // want `a.Printf format %\\[xd is missing closing \\]`\n\tPrintf(\"%[x]d x\", 3)                   // want `a.Printf format has invalid argument index \\[x\\]`\n\tPrintf(\"%[3]*s x\", \"hi\", 2)            // want `a.Printf format %\\[3]\\*s reads arg #3, but call has 2 args`\n\t_ = fmt.Sprintf(\"%[3]d x\", 2)          // want `fmt.Sprintf format %\\[3]d reads arg #3, but call has 1 arg`\n\tPrintf(\"%[2]*.[1]*[3]d x\", 2, \"hi\", 4) // want `a.Printf format %\\[2]\\*\\.\\[1\\]\\*\\[3\\]d uses non-int \\x22hi\\x22 as argument of \\*`\n\tPrintf(\"%[0]s x\", \"arg1\")              // want `a.Printf format has invalid argument index \\[0\\]`\n\tPrintf(\"%[0]d x\", 1)                   // want `a.Printf format has invalid argument index \\[0\\]`\n\tPrintf(\"%[3]*.[2*[1]f\", 1, 2, 3)       // want `a.Printf format has invalid argument index \\[2\\*\\[1\\]`\n\t// Something that satisfies the error interface.\n\tvar e error\n\tfmt.Println(e.Error()) // ok\n\t// Something that looks like an error interface but isn't, such as the (*T).Error method\n\t// in the testing package.\n\tvar et1 *testing.T\n\tet1.Error()         // ok\n\tet1.Error(\"hi\")     // ok\n\tet1.Error(\"%d\", 3)  // want `\\(\\*testing.common\\).Error call has possible Printf formatting directive %d`\n\tet1.Errorf(\"%s\", 1) // want `\\(\\*testing.common\\).Errorf format %s has arg 1 of wrong type int`\n\tvar et3 errorTest3\n\tet3.Error() // ok, not an error method.\n\tvar et4 errorTest4\n\tet4.Error() // ok, not an error method.\n\tvar et5 errorTest5\n\tet5.error() // ok, not an error method.\n\t// Interfaces can be used with any verb.\n\tvar iface interface {\n\t\tToTheMadness() bool // Method ToTheMadness usually returns false\n\t}\n\tfmt.Printf(\"%f\", iface) // ok: fmt treats interfaces as transparent and iface may well have a float concrete type\n\t// Can't print a function.\n\tPrintf(\"%d\", someFunction) // want \"a.Printf format %d arg someFunction is a func value, not called\"\n\tPrintf(\"%v\", someFunction) // want \"a.Printf format %v arg someFunction is a func value, not called\"\n\tPrintln(someFunction)      // want \"a.Println arg someFunction is a func value, not called\"\n\tPrintf(\"%p\", someFunction) // ok: maybe someone wants to see the pointer\n\tPrintf(\"%T\", someFunction) // ok: maybe someone wants to see the type\n\t// Bug: used to recur forever.\n\tPrintf(\"%p %x\", recursiveStructV, recursiveStructV.next)\n\tPrintf(\"%p %x\", recursiveStruct1V, recursiveStruct1V.next) // want `a.Printf format %x has arg recursiveStruct1V\\.next of wrong type \\*a\\.RecursiveStruct2`\n\tPrintf(\"%p %x\", recursiveSliceV, recursiveSliceV)\n\tPrintf(\"%p %x\", recursiveMapV, recursiveMapV)\n\t// Special handling for Log.\n\tmath.Log(3) // OK\n\tvar t *testing.T\n\tt.Log(\"%d\", 3) // want `\\(\\*testing.common\\).Log call has possible Printf formatting directive %d`\n\tt.Logf(\"%d\", 3)\n\tt.Logf(\"%d\", \"hi\") // want `\\(\\*testing.common\\).Logf format %d has arg \"hi\" of wrong type string`\n\n\tErrorf(1, \"%d\", 3)    // OK\n\tErrorf(1, \"%d\", \"hi\") // want `a.Errorf format %d has arg \"hi\" of wrong type string`\n\n\t// Multiple string arguments before variadic args\n\terrorf(\"WARNING\", \"foobar\")            // OK\n\terrorf(\"INFO\", \"s=%s, n=%d\", \"foo\", 1) // OK\n\terrorf(\"ERROR\", \"%d\")                  // want \"a.errorf format %d reads arg #1, but call has 0 args\"\n\n\tvar tb testing.TB\n\ttb.Errorf(\"%s\", 1) // want `\\(testing.TB\\).Errorf format %s has arg 1 of wrong type int`\n\n\t// Printf from external package\n\t// externalprintf.Printf(\"%d\", 42) // OK\n\t// externalprintf.Printf(\"foobar\") // OK\n\t// level := 123\n\t// externalprintf.Logf(level, \"%d\", 42)                        // OK\n\t// externalprintf.Errorf(level, level, \"foo %q bar\", \"foobar\") // OK\n\t// externalprintf.Logf(level, \"%d\")                            // no error \"Logf format %d reads arg #1, but call has 0 args\"\n\t// var formatStr = \"%s %s\"\n\t// externalprintf.Sprintf(formatStr, \"a\", \"b\")     // OK\n\t// externalprintf.Logf(level, formatStr, \"a\", \"b\") // OK\n\n\t// user-defined Println-like functions\n\tss := &someStruct{}\n\tss.Log(someFunction, \"foo\")          // OK\n\tss.Error(someFunction, someFunction) // OK\n\tss.Println()                         // OK\n\tss.Println(1.234, \"foo\")             // OK\n\tss.Println(1, someFunction)          // no error \"Println arg someFunction is a func value, not called\"\n\tss.log(someFunction)                 // OK\n\tss.log(someFunction, \"bar\", 1.33)    // OK\n\tss.log(someFunction, someFunction)   // no error \"log arg someFunction is a func value, not called\"\n\n\t// indexed arguments\n\tPrintf(\"%d %[3]d %d %[2]d x\", 1, 2, 3, 4)             // OK\n\tPrintf(\"%d %[0]d %d %[2]d x\", 1, 2, 3, 4)             // want `a.Printf format has invalid argument index \\[0\\]`\n\tPrintf(\"%d %[3]d %d %[-2]d x\", 1, 2, 3, 4)            // want `a.Printf format has invalid argument index \\[-2\\]`\n\tPrintf(\"%d %[3]d %d %[2234234234234]d x\", 1, 2, 3, 4) // want `a.Printf format has invalid argument index \\[2234234234234\\]`\n\tPrintf(\"%d %[3]d %-10d %[2]d x\", 1, 2, 3)             // want \"a.Printf format %-10d reads arg #4, but call has 3 args\"\n\tPrintf(\"%[1][3]d x\", 1, 2)                            // want `a.Printf format %\\[1\\]\\[ has unknown verb \\[`\n\tPrintf(\"%[1]d x\", 1, 2)                               // OK\n\tPrintf(\"%d %[3]d %d %[2]d x\", 1, 2, 3, 4, 5)          // OK\n\n\t// wrote Println but meant Fprintln\n\tPrintf(\"%p\\n\", os.Stdout)   // OK\n\tPrintln(os.Stdout, \"hello\") // want \"a.Println does not take io.Writer but has first arg os.Stdout\"\n\n\tPrintf(someString(), \"hello\") // OK\n\n\t// Printf wrappers in package log should be detected automatically\n\tlogpkg.Fatal(\"%d\", 1)    // want \"log.Fatal call has possible Printf formatting directive %d\"\n\tlogpkg.Fatalf(\"%d\", \"x\") // want `log.Fatalf format %d has arg \"x\" of wrong type string`\n\tlogpkg.Fatalln(\"%d\", 1)  // want \"log.Fatalln call has possible Printf formatting directive %d\"\n\tlogpkg.Panic(\"%d\", 1)    // want \"log.Panic call has possible Printf formatting directive %d\"\n\tlogpkg.Panicf(\"%d\", \"x\") // want `log.Panicf format %d has arg \"x\" of wrong type string`\n\tlogpkg.Panicln(\"%d\", 1)  // want \"log.Panicln call has possible Printf formatting directive %d\"\n\tlogpkg.Print(\"%d\", 1)    // want \"log.Print call has possible Printf formatting directive %d\"\n\tlogpkg.Printf(\"%d\", \"x\") // want `log.Printf format %d has arg \"x\" of wrong type string`\n\tlogpkg.Println(\"%d\", 1)  // want \"log.Println call has possible Printf formatting directive %d\"\n\n\t// Methods too.\n\tvar l *logpkg.Logger\n\tl.Fatal(\"%d\", 1)    // want `\\(\\*log.Logger\\).Fatal call has possible Printf formatting directive %d`\n\tl.Fatalf(\"%d\", \"x\") // want `\\(\\*log.Logger\\).Fatalf format %d has arg \"x\" of wrong type string`\n\tl.Fatalln(\"%d\", 1)  // want `\\(\\*log.Logger\\).Fatalln call has possible Printf formatting directive %d`\n\tl.Panic(\"%d\", 1)    // want `\\(\\*log.Logger\\).Panic call has possible Printf formatting directive %d`\n\tl.Panicf(\"%d\", \"x\") // want `\\(\\*log.Logger\\).Panicf format %d has arg \"x\" of wrong type string`\n\tl.Panicln(\"%d\", 1)  // want `\\(\\*log.Logger\\).Panicln call has possible Printf formatting directive %d`\n\tl.Print(\"%d\", 1)    // want `\\(\\*log.Logger\\).Print call has possible Printf formatting directive %d`\n\tl.Printf(\"%d\", \"x\") // want `\\(\\*log.Logger\\).Printf format %d has arg \"x\" of wrong type string`\n\tl.Println(\"%d\", 1)  // want `\\(\\*log.Logger\\).Println call has possible Printf formatting directive %d`\n\n\t// Issue 26486\n\tdbg(\"\", 1) // no error \"call has arguments but no formatting directive\"\n\n\t// %w\n\tvar errSubset interface {\n\t\tError() string\n\t\tA()\n\t}\n\t_ = fmt.Errorf(\"%w\", err)               // OK\n\t_ = fmt.Errorf(\"%#w\", err)              // OK\n\t_ = fmt.Errorf(\"%[2]w %[1]s\", \"x\", err) // OK\n\t_ = fmt.Errorf(\"%[2]w %[1]s\", e, \"x\")   // want `fmt.Errorf format %\\[2\\]w has arg \"x\" of wrong type string`\n\t_ = fmt.Errorf(\"%w\", \"x\")               // want `fmt.Errorf format %w has arg \"x\" of wrong type string`\n\t_ = fmt.Errorf(\"%w %w\", err, err)       // OK\n\t_ = fmt.Errorf(\"%w\", interface{}(nil))  // want `fmt.Errorf format %w has arg interface{}\\(nil\\) of wrong type interface{}`\n\t_ = fmt.Errorf(\"%w\", errorTestOK(0))    // concrete value implements error\n\t_ = fmt.Errorf(\"%w\", errSubset)         // interface value implements error\n\tfmt.Printf(\"%w\", err)                   // want `fmt.Printf does not support error-wrapping directive %w`\n\tvar wt *testing.T\n\twt.Errorf(\"%w\", err)          // want `\\(\\*testing.common\\).Errorf does not support error-wrapping directive %w`\n\twt.Errorf(\"%[1][3]d x\", 1, 2) // want `\\(\\*testing.common\\).Errorf format %\\[1\\]\\[ has unknown verb \\[`\n\twt.Errorf(\"%[1]d x\", 1, 2)    // OK\n\t// Errorf is a printfWrapper, not an errorfWrapper.\n\tErrorf(0, \"%w\", err) // want `a.Errorf does not support error-wrapping directive %w`\n\t// %w should work on fmt.Errorf-based wrappers.\n\tvar es errorfStruct\n\tvar eis errorfIntStruct\n\tvar ess errorfStringStruct\n\tes.Errorf(\"%w\", err)           // OK\n\teis.Errorf(0, \"%w\", err)       // OK\n\tess.Errorf(\"ERROR\", \"%w\", err) // OK\n\tfmt.Appendf(nil, \"%d\", \"123\")  // want `wrong type`\n\tfmt.Append(nil, \"%d\", 123)     // want `fmt.Append call has possible Printf formatting directive %d`\n\n}\n\nfunc someString() string { return \"X\" }\n\ntype someStruct struct{}\n\n// Log is non-variadic user-define Println-like function.\n// Calls to this func must be skipped when checking\n// for Println-like arguments.\nfunc (ss *someStruct) Log(f func(), s string) {}\n\n// Error is variadic user-define Println-like function.\n// Calls to this func mustn't be checked for Println-like arguments,\n// since variadic arguments type isn't interface{}.\nfunc (ss *someStruct) Error(args ...func()) {}\n\n// Println is variadic user-defined Println-like function.\n// Calls to this func must be checked for Println-like arguments.\nfunc (ss *someStruct) Println(args ...interface{}) {}\n\n// log is variadic user-defined Println-like function.\n// Calls to this func must be checked for Println-like arguments.\nfunc (ss *someStruct) log(f func(), args ...interface{}) {}\n\n// A function we use as a function value; it has no other purpose.\nfunc someFunction() {}\n\n// Printf is used by the test so we must declare it.\nfunc Printf(format string, args ...interface{}) { // want Printf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n\n// Println is used by the test so we must declare it.\nfunc Println(args ...interface{}) { // want Println:\"printWrapper\"\n\tfmt.Println(args...)\n}\n\n// printf is used by the test so we must declare it.\nfunc printf(format string, args ...interface{}) { // want printf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n\n// Errorf is used by the test for a case in which the first parameter\n// is not a format string.\nfunc Errorf(i int, format string, args ...interface{}) { // want Errorf:\"printfWrapper\"\n\tfmt.Sprintf(format, args...)\n}\n\n// errorf is used by the test for a case in which the function accepts multiple\n// string parameters before variadic arguments\nfunc errorf(level, format string, args ...interface{}) { // want errorf:\"printfWrapper\"\n\tfmt.Sprintf(format, args...)\n}\n\ntype errorfStruct struct{}\n\n// Errorf is used to test %w works on errorf wrappers.\nfunc (errorfStruct) Errorf(format string, args ...interface{}) { // want Errorf:\"errorfWrapper\"\n\t_ = fmt.Errorf(format, args...)\n}\n\ntype errorfStringStruct struct{}\n\n// Errorf is used by the test for a case in which the function accepts multiple\n// string parameters before variadic arguments\nfunc (errorfStringStruct) Errorf(level, format string, args ...interface{}) { // want Errorf:\"errorfWrapper\"\n\t_ = fmt.Errorf(format, args...)\n}\n\ntype errorfIntStruct struct{}\n\n// Errorf is used by the test for a case in which the first parameter\n// is not a format string.\nfunc (errorfIntStruct) Errorf(i int, format string, args ...interface{}) { // want Errorf:\"errorfWrapper\"\n\t_ = fmt.Errorf(format, args...)\n}\n\n// multi is used by the test.\nfunc multi() []interface{} {\n\tpanic(\"don't call - testing only\")\n}\n\ntype stringer int\n\nfunc (stringer) String() string { return \"string\" }\n\ntype ptrStringer float64\n\nvar stringerv ptrStringer\n\nfunc (*ptrStringer) String() string {\n\treturn \"string\"\n}\n\nfunc (p *ptrStringer) Warn2(x int, args ...interface{}) string { // want Warn2:\"printWrapper\"\n\treturn p.Warn(x, args...)\n}\n\nfunc (p *ptrStringer) Warnf2(x int, format string, args ...interface{}) string { // want Warnf2:\"printfWrapper\"\n\treturn p.Warnf(x, format, args...)\n}\n\n// During testing -printf.funcs flag matches Warn.\nfunc (*ptrStringer) Warn(x int, args ...interface{}) string {\n\treturn \"warn\"\n}\n\n// During testing -printf.funcs flag matches Warnf.\nfunc (*ptrStringer) Warnf(x int, format string, args ...interface{}) string {\n\treturn \"warnf\"\n}\n\nfunc (p *ptrStringer) Wrap2(x int, args ...interface{}) string { // want Wrap2:\"printWrapper\"\n\treturn p.Wrap(x, args...)\n}\n\nfunc (p *ptrStringer) Wrapf2(x int, format string, args ...interface{}) string { // want Wrapf2:\"printfWrapper\"\n\treturn p.Wrapf(x, format, args...)\n}\n\nfunc (*ptrStringer) Wrap(x int, args ...interface{}) string { // want Wrap:\"printWrapper\"\n\treturn fmt.Sprint(args...)\n}\n\nfunc (*ptrStringer) Wrapf(x int, format string, args ...interface{}) string { // want Wrapf:\"printfWrapper\"\n\treturn fmt.Sprintf(format, args...)\n}\n\nfunc (*ptrStringer) BadWrap(x int, args ...interface{}) string {\n\treturn fmt.Sprint(args) // want \"missing ... in args forwarded to print-like function\"\n}\n\nfunc (*ptrStringer) BadWrapf(x int, format string, args ...interface{}) string {\n\treturn fmt.Sprintf(format, args) // want \"missing ... in args forwarded to printf-like function\"\n}\n\nfunc (*ptrStringer) WrapfFalsePositive(x int, arg1 string, arg2 ...interface{}) string {\n\treturn fmt.Sprintf(\"%s %v\", arg1, arg2)\n}\n\ntype embeddedStringer struct {\n\tfoo string\n\tptrStringer\n\tbar int\n}\n\nvar embeddedStringerv embeddedStringer\n\ntype notstringer struct {\n\tf float64\n}\n\nvar notstringerv notstringer\n\ntype stringerarray [4]float64\n\nfunc (stringerarray) String() string {\n\treturn \"string\"\n}\n\nvar stringerarrayv stringerarray\n\ntype notstringerarray [4]float64\n\nvar notstringerarrayv notstringerarray\n\nvar nonemptyinterface = interface {\n\tf()\n}(nil)\n\n// A data type we can print with \"%d\".\ntype percentDStruct struct {\n\ta int\n\tb []byte\n\tc *float64\n}\n\nvar percentDV percentDStruct\n\n// A data type we cannot print correctly with \"%d\".\ntype notPercentDStruct struct {\n\ta int\n\tb []byte\n\tc bool\n}\n\nvar notPercentDV notPercentDStruct\n\n// A data type we can print with \"%s\".\ntype percentSStruct struct {\n\ta string\n\tb []byte\n\tC stringerarray\n}\n\nvar percentSV percentSStruct\n\ntype recursiveStringer int\n\nfunc (s recursiveStringer) String() string {\n\t_ = fmt.Sprintf(\"%d\", s)\n\t_ = fmt.Sprintf(\"%#v\", s)\n\t_ = fmt.Sprintf(\"%v\", s)   // want `fmt.Sprintf format %v with arg s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%v\", &s)  // want `fmt.Sprintf format %v with arg &s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#x\", s)  // want `fmt.Sprintf format %#x with arg s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#x\", &s) // want `fmt.Sprintf format %#x with arg &s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#X\", s)  // want `fmt.Sprintf format %#X with arg s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#X\", &s) // want `fmt.Sprintf format %#X with arg &s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#q\", s)  // want `fmt.Sprintf format %#q with arg s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%#q\", &s) // want `fmt.Sprintf format %#q with arg &s causes recursive \\(a.recursiveStringer\\).String method call`\n\t_ = fmt.Sprintf(\"%T\", s)   // ok; does not recursively call String\n\treturn fmt.Sprintln(s)     // want `fmt.Sprintln arg s causes recursive call to \\(a.recursiveStringer\\).String method`\n}\n\ntype recursivePtrStringer int\n\nfunc (p *recursivePtrStringer) String() string {\n\t_ = fmt.Sprintf(\"%v\", *p)\n\t_ = fmt.Sprint(&p)     // ok; prints address\n\treturn fmt.Sprintln(p) // want `fmt.Sprintln arg p causes recursive call to \\(\\*a.recursivePtrStringer\\).String method`\n}\n\ntype recursiveError int\n\nfunc (s recursiveError) Error() string {\n\t_ = fmt.Sprintf(\"%d\", s)\n\t_ = fmt.Sprintf(\"%#v\", s)\n\t_ = fmt.Sprintf(\"%v\", s)   // want `fmt.Sprintf format %v with arg s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%v\", &s)  // want `fmt.Sprintf format %v with arg &s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#x\", s)  // want `fmt.Sprintf format %#x with arg s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#x\", &s) // want `fmt.Sprintf format %#x with arg &s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#X\", s)  // want `fmt.Sprintf format %#X with arg s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#X\", &s) // want `fmt.Sprintf format %#X with arg &s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#q\", s)  // want `fmt.Sprintf format %#q with arg s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#q\", &s) // want `fmt.Sprintf format %#q with arg &s causes recursive \\(a.recursiveError\\).Error method call`\n\t_ = fmt.Sprintf(\"%T\", s)   // ok; does not recursively call Error\n\treturn fmt.Sprintln(s)     // want `fmt.Sprintln arg s causes recursive call to \\(a.recursiveError\\).Error method`\n}\n\ntype recursivePtrError int\n\nfunc (p *recursivePtrError) Error() string {\n\t_ = fmt.Sprintf(\"%v\", *p)\n\t_ = fmt.Sprint(&p)     // ok; prints address\n\treturn fmt.Sprintln(p) // want `fmt.Sprintln arg p causes recursive call to \\(\\*a.recursivePtrError\\).Error method`\n}\n\ntype recursiveStringerAndError int\n\nfunc (s recursiveStringerAndError) String() string {\n\t_ = fmt.Sprintf(\"%d\", s)\n\t_ = fmt.Sprintf(\"%#v\", s)\n\t_ = fmt.Sprintf(\"%v\", s)   // want `fmt.Sprintf format %v with arg s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%v\", &s)  // want `fmt.Sprintf format %v with arg &s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#x\", s)  // want `fmt.Sprintf format %#x with arg s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#x\", &s) // want `fmt.Sprintf format %#x with arg &s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#X\", s)  // want `fmt.Sprintf format %#X with arg s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#X\", &s) // want `fmt.Sprintf format %#X with arg &s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#q\", s)  // want `fmt.Sprintf format %#q with arg s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%#q\", &s) // want `fmt.Sprintf format %#q with arg &s causes recursive \\(a.recursiveStringerAndError\\).String method call`\n\t_ = fmt.Sprintf(\"%T\", s)   // ok; does not recursively call String\n\treturn fmt.Sprintln(s)     // want `fmt.Sprintln arg s causes recursive call to \\(a.recursiveStringerAndError\\).String method`\n}\n\nfunc (s recursiveStringerAndError) Error() string {\n\t_ = fmt.Sprintf(\"%d\", s)\n\t_ = fmt.Sprintf(\"%#v\", s)\n\t_ = fmt.Sprintf(\"%v\", s)   // want `fmt.Sprintf format %v with arg s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%v\", &s)  // want `fmt.Sprintf format %v with arg &s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#x\", s)  // want `fmt.Sprintf format %#x with arg s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#x\", &s) // want `fmt.Sprintf format %#x with arg &s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#X\", s)  // want `fmt.Sprintf format %#X with arg s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#X\", &s) // want `fmt.Sprintf format %#X with arg &s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#q\", s)  // want `fmt.Sprintf format %#q with arg s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%#q\", &s) // want `fmt.Sprintf format %#q with arg &s causes recursive \\(a.recursiveStringerAndError\\).Error method call`\n\t_ = fmt.Sprintf(\"%T\", s)   // ok; does not recursively call Error\n\treturn fmt.Sprintln(s)     // want `fmt.Sprintln arg s causes recursive call to \\(a.recursiveStringerAndError\\).Error method`\n}\n\ntype recursivePtrStringerAndError int\n\nfunc (p *recursivePtrStringerAndError) String() string {\n\t_ = fmt.Sprintf(\"%v\", *p)\n\t_ = fmt.Sprint(&p)     // ok; prints address\n\treturn fmt.Sprintln(p) // want `fmt.Sprintln arg p causes recursive call to \\(\\*a.recursivePtrStringerAndError\\).String method`\n}\n\nfunc (p *recursivePtrStringerAndError) Error() string {\n\t_ = fmt.Sprintf(\"%v\", *p)\n\t_ = fmt.Sprint(&p)     // ok; prints address\n\treturn fmt.Sprintln(p) // want `fmt.Sprintln arg p causes recursive call to \\(\\*a.recursivePtrStringerAndError\\).Error method`\n}\n\n// implements a String() method but with non-matching return types\ntype nonStringerWrongReturn int\n\nfunc (s nonStringerWrongReturn) String() (string, error) {\n\treturn \"\", fmt.Errorf(\"%v\", s)\n}\n\n// implements a String() method but with non-matching arguments\ntype nonStringerWrongArgs int\n\nfunc (s nonStringerWrongArgs) String(i int) string {\n\treturn fmt.Sprintf(\"%d%v\", i, s)\n}\n\ntype cons struct {\n\tcar int\n\tcdr *cons\n}\n\nfunc (cons *cons) String() string {\n\tif cons == nil {\n\t\treturn \"nil\"\n\t}\n\t_ = fmt.Sprint(cons.cdr)                            // don't want \"recursive call\" diagnostic\n\treturn fmt.Sprintf(\"(%d . %v)\", cons.car, cons.cdr) // don't want \"recursive call\" diagnostic\n}\n\ntype BoolFormatter bool\n\nfunc (*BoolFormatter) Format(fmt.State, rune) {\n}\n\n// Formatter with value receiver\ntype FormatterVal bool\n\nfunc (FormatterVal) Format(fmt.State, rune) {\n}\n\ntype RecursiveSlice []RecursiveSlice\n\nvar recursiveSliceV = &RecursiveSlice{}\n\ntype RecursiveMap map[int]RecursiveMap\n\nvar recursiveMapV = make(RecursiveMap)\n\ntype RecursiveStruct struct {\n\tnext *RecursiveStruct\n}\n\nvar recursiveStructV = &RecursiveStruct{}\n\ntype RecursiveStruct1 struct {\n\tnext *RecursiveStruct2\n}\n\ntype RecursiveStruct2 struct {\n\tnext *RecursiveStruct1\n}\n\nvar recursiveStruct1V = &RecursiveStruct1{}\n\ntype unexportedInterface struct {\n\tf interface{}\n}\n\n// Issue 17798: unexported ptrStringer cannot be formatted.\ntype unexportedStringer struct {\n\tt ptrStringer\n}\n\ntype unexportedStringerOtherFields struct {\n\ts string\n\tt ptrStringer\n\tS string\n}\n\n// Issue 17798: unexported error cannot be formatted.\ntype unexportedError struct {\n\te error\n}\n\ntype unexportedErrorOtherFields struct {\n\ts string\n\te error\n\tS string\n}\n\ntype errorer struct{}\n\nfunc (e errorer) Error() string { return \"errorer\" }\n\ntype unexportedCustomError struct {\n\te errorer\n}\n\ntype errorInterface interface {\n\terror\n\tExtraMethod()\n}\n\ntype unexportedErrorInterface struct {\n\te errorInterface\n}\n\nfunc UnexportedStringerOrError() {\n\tfmt.Printf(\"%s\", unexportedInterface{\"foo\"}) // ok; prints {foo}\n\tfmt.Printf(\"%s\", unexportedInterface{3})     // ok; we can't see the problem\n\n\tus := unexportedStringer{}\n\tfmt.Printf(\"%s\", us)  // want \"Printf format %s has arg us of wrong type a.unexportedStringer\"\n\tfmt.Printf(\"%s\", &us) // want \"Printf format %s has arg &us of wrong type [*]a.unexportedStringer\"\n\n\tusf := unexportedStringerOtherFields{\n\t\ts: \"foo\",\n\t\tS: \"bar\",\n\t}\n\tfmt.Printf(\"%s\", usf)  // want \"Printf format %s has arg usf of wrong type a.unexportedStringerOtherFields\"\n\tfmt.Printf(\"%s\", &usf) // want \"Printf format %s has arg &usf of wrong type [*]a.unexportedStringerOtherFields\"\n\n\tue := unexportedError{\n\t\te: &errorer{},\n\t}\n\tfmt.Printf(\"%s\", ue)  // want \"Printf format %s has arg ue of wrong type a.unexportedError\"\n\tfmt.Printf(\"%s\", &ue) // want \"Printf format %s has arg &ue of wrong type [*]a.unexportedError\"\n\n\tuef := unexportedErrorOtherFields{\n\t\ts: \"foo\",\n\t\te: &errorer{},\n\t\tS: \"bar\",\n\t}\n\tfmt.Printf(\"%s\", uef)  // want \"Printf format %s has arg uef of wrong type a.unexportedErrorOtherFields\"\n\tfmt.Printf(\"%s\", &uef) // want \"Printf format %s has arg &uef of wrong type [*]a.unexportedErrorOtherFields\"\n\n\tuce := unexportedCustomError{\n\t\te: errorer{},\n\t}\n\tfmt.Printf(\"%s\", uce) // want \"Printf format %s has arg uce of wrong type a.unexportedCustomError\"\n\n\tuei := unexportedErrorInterface{}\n\tfmt.Printf(\"%s\", uei)       // want \"Printf format %s has arg uei of wrong type a.unexportedErrorInterface\"\n\tfmt.Println(\"foo\\n\", \"bar\") // not an error\n\n\tfmt.Println(\"foo\\n\")      // want \"Println arg list ends with redundant newline\"\n\tfmt.Println(\"foo\" + \"\\n\") // want \"Println arg list ends with redundant newline\"\n\tfmt.Println(\"foo\\\\n\")     // not an error\n\tfmt.Println(`foo\\n`)      // not an error\n\n\tintSlice := []int{3, 4}\n\tfmt.Printf(\"%s\", intSlice) // want `fmt.Printf format %s has arg intSlice of wrong type \\[\\]int`\n\tnonStringerArray := [1]unexportedStringer{{}}\n\tfmt.Printf(\"%s\", nonStringerArray)  // want `fmt.Printf format %s has arg nonStringerArray of wrong type \\[1\\]a.unexportedStringer`\n\tfmt.Printf(\"%s\", []stringer{3, 4})  // not an error\n\tfmt.Printf(\"%s\", [2]stringer{3, 4}) // not an error\n}\n\n// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.\n// See issues 23598 and 23605.\nfunc DisableErrorForFlag0() {\n\tfmt.Printf(\"%0t\", true)\n}\n\n// Issue 26486.\nfunc dbg(format string, args ...interface{}) {\n\tif format == \"\" {\n\t\tformat = \"%v\"\n\t}\n\tfmt.Printf(format, args...)\n}\n\nfunc PointersToCompoundTypes() {\n\tstringSlice := []string{\"a\", \"b\"}\n\tfmt.Printf(\"%s\", &stringSlice) // not an error\n\n\tintSlice := []int{3, 4}\n\tfmt.Printf(\"%s\", &intSlice) // want `fmt.Printf format %s has arg &intSlice of wrong type \\*\\[\\]int`\n\n\tstringArray := [2]string{\"a\", \"b\"}\n\tfmt.Printf(\"%s\", &stringArray) // not an error\n\n\tintArray := [2]int{3, 4}\n\tfmt.Printf(\"%s\", &intArray) // want `fmt.Printf format %s has arg &intArray of wrong type \\*\\[2\\]int`\n\n\tstringStruct := struct{ F string }{\"foo\"}\n\tfmt.Printf(\"%s\", &stringStruct) // not an error\n\n\tintStruct := struct{ F int }{3}\n\tfmt.Printf(\"%s\", &intStruct) // want `fmt.Printf format %s has arg &intStruct of wrong type \\*struct{F int}`\n\n\tstringMap := map[string]string{\"foo\": \"bar\"}\n\tfmt.Printf(\"%s\", &stringMap) // not an error\n\n\tintMap := map[int]int{3: 4}\n\tfmt.Printf(\"%s\", &intMap) // want `fmt.Printf format %s has arg &intMap of wrong type \\*map\\[int\\]int`\n\n\ttype T2 struct {\n\t\tX string\n\t}\n\ttype T1 struct {\n\t\tX *T2\n\t}\n\tfmt.Printf(\"%s\\n\", T1{&T2{\"x\"}}) // want `fmt.Printf format %s has arg T1{&T2{.x.}} of wrong type a\\.T1`\n}\n\n// Printf wrappers from external package\nfunc externalPackage() {\n\tb.Wrapf(\"%s\", 1) // want \"Wrapf format %s has arg 1 of wrong type int\"\n\tb.Wrap(\"%s\", 1)  // want \"Wrap call has possible Printf formatting directive %s\"\n\tb.NoWrap(\"%s\", 1)\n\tb.Wrapf2(\"%s\", 1) // want \"Wrapf2 format %s has arg 1 of wrong type int\"\n}\n\nfunc PointerVerbs() {\n\t// Use booleans, so that we don't just format the elements like in\n\t// PointersToCompoundTypes. Bools can only be formatted with verbs like\n\t// %t and %v, and none of the ones below.\n\tptr := new(bool)\n\tslice := []bool{}\n\tarray := [3]bool{}\n\tmap_ := map[bool]bool{}\n\tchan_ := make(chan bool)\n\tfunc_ := func(bool) {}\n\n\t// %p, %b, %d, %o, %O, %x, and %X all support pointers.\n\tfmt.Printf(\"%p\", ptr)\n\tfmt.Printf(\"%b\", ptr)\n\tfmt.Printf(\"%d\", ptr)\n\tfmt.Printf(\"%o\", ptr)\n\tfmt.Printf(\"%O\", ptr)\n\tfmt.Printf(\"%x\", ptr)\n\tfmt.Printf(\"%X\", ptr)\n\n\t// %p, %b, %d, %o, %O, %x, and %X all support channels.\n\tfmt.Printf(\"%p\", chan_)\n\tfmt.Printf(\"%b\", chan_)\n\tfmt.Printf(\"%d\", chan_)\n\tfmt.Printf(\"%o\", chan_)\n\tfmt.Printf(\"%O\", chan_)\n\tfmt.Printf(\"%x\", chan_)\n\tfmt.Printf(\"%X\", chan_)\n\n\t// %p is the only one that supports funcs.\n\tfmt.Printf(\"%p\", func_)\n\tfmt.Printf(\"%b\", func_) // want `fmt.Printf format %b arg func_ is a func value, not called`\n\tfmt.Printf(\"%d\", func_) // want `fmt.Printf format %d arg func_ is a func value, not called`\n\tfmt.Printf(\"%o\", func_) // want `fmt.Printf format %o arg func_ is a func value, not called`\n\tfmt.Printf(\"%O\", func_) // want `fmt.Printf format %O arg func_ is a func value, not called`\n\tfmt.Printf(\"%x\", func_) // want `fmt.Printf format %x arg func_ is a func value, not called`\n\tfmt.Printf(\"%X\", func_) // want `fmt.Printf format %X arg func_ is a func value, not called`\n\n\t// %p is the only one that supports all slices, by printing the address\n\t// of the 0th element.\n\tfmt.Printf(\"%p\", slice) // supported; address of 0th element\n\tfmt.Printf(\"%b\", slice) // want `fmt.Printf format %b has arg slice of wrong type \\[\\]bool`\n\n\tfmt.Printf(\"%d\", slice) // want `fmt.Printf format %d has arg slice of wrong type \\[\\]bool`\n\n\tfmt.Printf(\"%o\", slice) // want `fmt.Printf format %o has arg slice of wrong type \\[\\]bool`\n\tfmt.Printf(\"%O\", slice) // want `fmt.Printf format %O has arg slice of wrong type \\[\\]bool`\n\n\tfmt.Printf(\"%x\", slice) // want `fmt.Printf format %x has arg slice of wrong type \\[\\]bool`\n\tfmt.Printf(\"%X\", slice) // want `fmt.Printf format %X has arg slice of wrong type \\[\\]bool`\n\n\t// None support arrays.\n\tfmt.Printf(\"%p\", array) // want `fmt.Printf format %p has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%b\", array) // want `fmt.Printf format %b has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%d\", array) // want `fmt.Printf format %d has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%o\", array) // want `fmt.Printf format %o has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%O\", array) // want `fmt.Printf format %O has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%x\", array) // want `fmt.Printf format %x has arg array of wrong type \\[3\\]bool`\n\tfmt.Printf(\"%X\", array) // want `fmt.Printf format %X has arg array of wrong type \\[3\\]bool`\n\n\t// %p is the only one that supports all maps.\n\tfmt.Printf(\"%p\", map_) // supported; address of 0th element\n\tfmt.Printf(\"%b\", map_) // want `fmt.Printf format %b has arg map_ of wrong type map\\[bool\\]bool`\n\n\tfmt.Printf(\"%d\", map_) // want `fmt.Printf format %d has arg map_ of wrong type map\\[bool\\]bool`\n\n\tfmt.Printf(\"%o\", map_) // want `fmt.Printf format %o has arg map_ of wrong type map\\[bool\\]bool`\n\tfmt.Printf(\"%O\", map_) // want `fmt.Printf format %O has arg map_ of wrong type map\\[bool\\]bool`\n\n\tfmt.Printf(\"%x\", map_) // want `fmt.Printf format %x has arg map_ of wrong type map\\[bool\\]bool`\n\tfmt.Printf(\"%X\", map_) // want `fmt.Printf format %X has arg map_ of wrong type map\\[bool\\]bool`\n}\n\n// Tests of calls to anonymous print{,f}-wrapper\n// functions assigned to variables (local/package/field).\n\n// Test a local assigned an anonymous function using :=.\nfunc _() {\n\tprintf := func(format string, args ...any) { // want printf:\"printfWrapper\"\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tprintf(\"%s\", 123)                            // want `printf format %s has arg 123 of wrong type int`\n\tprintf = nil                                 // this doesn't undo the variable's printf-wrapper status\n\tprintf = func(format string, args ...any) {} // nor does this\n\tprintf(\"%s\", 123)                            // want `printf format %s has arg 123 of wrong type int`\n}\n\n// Test a global variable.\nfunc _() {\n\tglobalPrintf(\"%s\", 123) // want `globalPrintf format %s has arg 123 of wrong type int`\n\n\t// This assignment causes calls to GlobalWrapf2 to\n\t// be checked as a wrapper in this package only.\n\tb.GlobalWrapf2 = func(format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tb.GlobalWrapf(\"%s\", 123)    // want `GlobalWrapf format %s has arg 123 of wrong type int`\n\tb.GlobalWrapf2(\"%s\", 123)   // want `GlobalWrapf2 format %s has arg 123 of wrong type int`\n\tb.GlobalNonWrapf(\"%s\", 123) // nope\n}\n\nvar globalPrintf = func(format string, args ...any) { // want globalPrintf:\"printfWrapper\"\n\tprintln(fmt.Sprintf(format, args...))\n}\n\n// Test a non-wrapper anonymous function with a plausible signature.\nfunc _() {\n\tnotprintf := func(format string, args ...any) {}\n\tnotprintf(\"%s\", 123)\n}\n\n// Test '=' assignment.\n// Even calls through the var before it is\n// assigned a printf-like value are checked.\nfunc _() {\n\tvar printf func(bogus int, format string, args ...any) // want printf:\"printfWrapper\"\n\tprintf(0, \"%s\", 123)                                   // want `printf format %s has arg 123 of wrong type int`\n\tprintf = func(bogus int, format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tprintf(0, \"%s\", 123) // want `printf format %s has arg 123 of wrong type int`\n}\n\n// Test of literal wrapper function assigned to local variable.\nfunc _() {\n\tvar printf = func(format string, args ...any) { // want printf:\"printfWrapper\"\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tprintf(\"%s\", 123) // want `printf format %s has arg 123 of wrong type int`\n}\n\n// Test of literal wrapper function assigned to struct field.\nfunc _() {\n\tvar local struct {\n\t\tprintf func(format string, args ...any) // want printf:\"printfWrapper\"\n\t}\n\tlocal.printf = func(format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tlocal.printf(\"%s\", 123) // want `printf format %s has arg 123 of wrong type int`\n\n\t// This assignment causes calls to Struct.Wrapf to\n\t// be checked as a wrapper in this package only.\n\tb.Struct.Wrapf2 = func(format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tb.Struct.Wrapf(\"%s\", 123)    // want `Wrapf format %s has arg 123 of wrong type int`\n\tb.Struct.Wrapf2(\"%s\", 123)   // want `Wrapf2 format %s has arg 123 of wrong type int`\n\tb.Struct.NonWrapf(\"%s\", 123) // nope\n\n\t// variant using generic struct type.\n\t{\n\t\ttype S[T any] struct {\n\t\t\tprintf func(x T, format string, args ...any) // want printf:\"printfWrapper\"\n\t\t}\n\t\tnew(S[bool]).printf = func(_ bool, format string, args ...any) {\n\t\t\tprintln(fmt.Sprintf(format, args...))\n\t\t}\n\t\tnew(S[int]).printf(0, \"%s\", 123) // want `printf format %s has arg 123 of wrong type int`\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/a/a2.go",
    "content": "//go:build go1.26\n\npackage a\n\n// Test of induction through interface assignments. (Applies only to\n// interface methods declared in files that use at least Go 1.26.)\n\nimport \"fmt\"\n\ntype myLogger int\n\nfunc (myLogger) Logf(format string, args ...any) { // want Logf:\"printfWrapper\"\n\tprint(fmt.Sprintf(format, args...))\n}\n\n// Logger is assigned from myLogger.\n\ntype Logger interface {\n\tLogf(format string, args ...any) // want Logf:\"printfWrapper\"\n}\n\nvar _ Logger = myLogger(0) // establishes that Logger wraps myLogger\n\nfunc _(log Logger) {\n\tlog.Logf(\"%s\", 123) // want `\\(a.Logger\\).Logf format %s has arg 123 of wrong type int`\n}\n\n// Logger2 is not assigned from myLogger.\n\ntype Logger2 interface {\n\tLogf(format string, args ...any)\n}\n\nfunc _(log Logger2) {\n\tlog.Logf(\"%s\", 123) // nope\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/b/b.go",
    "content": "package b\n\nimport \"fmt\"\n\n// Wrapf is a printf wrapper.\nfunc Wrapf(format string, args ...interface{}) { // want Wrapf:\"printfWrapper\"\n\tfmt.Sprintf(format, args...)\n}\n\n// Wrap is a print wrapper.\nfunc Wrap(args ...interface{}) { // want Wrap:\"printWrapper\"\n\tfmt.Sprint(args...)\n}\n\n// NoWrap is not a wrapper.\nfunc NoWrap(format string, args ...interface{}) {\n}\n\n// Wrapf2 is another printf wrapper.\nfunc Wrapf2(format string, args ...interface{}) string { // want Wrapf2:\"printfWrapper\"\n\n\t// This statement serves as an assertion that this function is a\n\t// printf wrapper and that calls to it should be checked\n\t// accordingly, even though the delegation below is obscured by\n\t// the \"(\"+format+\")\" operations.\n\tif false {\n\t\tfmt.Sprintf(format, args...)\n\t}\n\n\t// Effectively a printf delegation,\n\t// but the printf checker can't see it.\n\treturn fmt.Sprintf(\"(\"+format+\")\", args...)\n}\n\nvar (\n\t// GlobalWrapf is assigned a literal printf wrapper\n\t// in this package, and thus has a fact.\n\tGlobalWrapf func(format string, args ...interface{}) // want GlobalWrapf:\"printfWrapper\"\n\n\t// GlobalWrapf2 is also assigned, but in another package (a),\n\t// and thus has no fact. Nonetheless it is checked as a\n\t// wrapper in that package.\n\tGlobalWrapf2 func(format string, args ...interface{})\n\n\t// GlobalNonWrapf is never assigned a wrapper.\n\tGlobalNonWrapf func(format string, args ...interface{})\n)\n\nvar Struct struct {\n\t// These fields follow the same pattern as the Global* vars.\n\tWrapf    func(format string, args ...interface{}) // want Wrapf:\"printfWrapper\"\n\tWrapf2   func(format string, args ...interface{})\n\tNonWrapf func(format string, args ...interface{})\n}\n\nfunc init() {\n\tGlobalWrapf = func(format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tGlobalWrapf(\"%s\", 123)    // want \"GlobalWrapf format %s has arg 123 of wrong type int\"\n\tGlobalWrapf2(\"%s\", 123)   // nope\n\tGlobalNonWrapf(\"%s\", 123) // nope\n\n\tStruct.Wrapf = func(format string, args ...any) {\n\t\tprintln(fmt.Sprintf(format, args...))\n\t}\n\tStruct.Wrapf(\"%s\", 123)    // want \"Wrapf format %s has arg 123 of wrong type int\"\n\tStruct.Wrapf2(\"%s\", 123)   // nope\n\tStruct.NonWrapf(\"%s\", 123) // nope\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/issue68744/issue68744.go",
    "content": "package issue68744\n\nimport \"fmt\"\n\n// The use of \"any\" here is crucial to exercise the bug.\n// (None of our earlier tests covered this vital detail!)\nfunc wrapf(format string, args ...any) { // want wrapf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n\nfunc _() {\n\twrapf(\"%s\", 123) // want `issue68744.wrapf format %s has arg 123 of wrong type int`\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/issue70572/issue70572.go",
    "content": "package issue70572\n\n// Regression test for failure to detect that a call to B[bool].Printf\n// was printf-like, because of a missing call to types.Func.Origin.\n\nimport \"fmt\"\n\ntype A struct{}\n\nfunc (v A) Printf(format string, values ...any) { // want Printf:\"printfWrapper\"\n\tfmt.Printf(format, values...)\n}\n\ntype B[T any] struct{}\n\nfunc (v B[T]) Printf(format string, values ...any) { // want Printf:\"printfWrapper\"\n\tfmt.Printf(format, values...)\n}\n\nfunc main() {\n\tvar a A\n\tvar b B[bool]\n\ta.Printf(\"x\", 1) // want \"arguments but no formatting directives\"\n\tb.Printf(\"x\", 1) // want \"arguments but no formatting directives\"\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/issue72850/a_go125.go",
    "content": "//go:build !go1.26\n\npackage a\n\nimport \"fmt\"\n\nvar (\n\t_ = fmt.Sprintf(\"%q\", byte(65)) // ok\n\t_ = fmt.Sprintf(\"%q\", rune(65)) // ok\n\t_ = fmt.Sprintf(\"%q\", 123)      // ok: pre-1.26 code allows %q on any integer\n)\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/issue72850/a_go126.go",
    "content": "//go:build go1.26\n\npackage a\n\nimport \"fmt\"\n\nvar (\n\t_ = fmt.Sprintf(\"%q\", byte(65)) // ok\n\t_ = fmt.Sprintf(\"%q\", rune(65)) // ok\n\t_ = fmt.Sprintf(\"%q\", 123)      // want `fmt.Sprintf format %q has arg 123 of wrong type int`\n)\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/issue76616/issue76616.go",
    "content": "package issue76616\n\nfunc _() {\n\t_ = func() {}\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/nofmt/nofmt.go",
    "content": "package b\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n)\n\nfunc formatBigInt(t *testing.T) {\n\tt.Logf(\"%d\\n\", big.NewInt(4))\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/nonconst/nonconst.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests of the printf checker's handling of non-constant\n// format strings (golang/go#60529).\n\npackage nonconst\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// As the language version is empty here, and the new check is gated on go1.24,\n// diagnostics are suppressed here.\nfunc nonConstantFormat(s string) {\n\tfmt.Printf(s)\n\tfmt.Printf(s, \"arg\")\n\tfmt.Fprintf(os.Stderr, s)\n\tlog.Printf(s)\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/typeparams/diagnostics.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"fmt\"\n\nfunc TestBasicTypeParams[T interface{ ~int }, E error, F fmt.Formatter, S fmt.Stringer, A any](t T, e E, f F, s S, a A) {\n\tfmt.Printf(\"%d\", t)\n\tfmt.Printf(\"%s\", t) // want \"wrong type.*contains ~int\"\n\tfmt.Printf(\"%v\", t)\n\tfmt.Printf(\"%d\", e) // want \"wrong type\"\n\tfmt.Printf(\"%s\", e)\n\tfmt.Errorf(\"%w\", e)\n\tfmt.Printf(\"%a\", f)\n\tfmt.Printf(\"%d\", f)\n\tfmt.Printf(\"%T\", f.Format)\n\tfmt.Printf(\"%p\", f.Format)\n\tfmt.Printf(\"%s\", s)\n\tfmt.Errorf(\"%w\", s) // want \"wrong type\"\n\tfmt.Printf(\"%d\", a) // want \"wrong type\"\n\tfmt.Printf(\"%s\", a) // want \"wrong type\"\n\tfmt.Printf(\"%v\", a)\n\tfmt.Printf(\"%T\", a)\n}\n\ntype Constraint interface {\n\t~int\n}\n\nfunc TestNamedConstraints_Issue49597[T Constraint](t T) {\n\tfmt.Printf(\"%d\", t)\n\tfmt.Printf(\"%s\", t) // want \"wrong type.*contains ~int\"\n}\n\nfunc TestNestedTypeParams[T interface{ ~int }, S interface{ ~string }]() {\n\tvar x struct {\n\t\tf int\n\t\tt T\n\t}\n\tfmt.Printf(\"%d\", x)\n\tfmt.Printf(\"%s\", x) // want \"wrong type\"\n\tvar y struct {\n\t\tf string\n\t\tt S\n\t}\n\tfmt.Printf(\"%d\", y) // want \"wrong type\"\n\tfmt.Printf(\"%s\", y)\n\tvar m1 map[T]T\n\tfmt.Printf(\"%d\", m1)\n\tfmt.Printf(\"%s\", m1) // want \"wrong type\"\n\tvar m2 map[S]S\n\tfmt.Printf(\"%d\", m2) // want \"wrong type\"\n\tfmt.Printf(\"%s\", m2)\n}\n\ntype R struct {\n\tF []R\n}\n\nfunc TestRecursiveTypeDefinition() {\n\tvar r []R\n\tfmt.Printf(\"%d\", r) // No error: avoids infinite recursion.\n}\n\nfunc TestRecursiveTypeParams[T1 ~[]T2, T2 ~[]T1 | string, T3 ~struct{ F T3 }](t1 T1, t2 T2, t3 T3) {\n\t// No error is reported on the following lines to avoid infinite recursion.\n\tfmt.Printf(\"%s\", t1)\n\tfmt.Printf(\"%s\", t2)\n\tfmt.Printf(\"%s\", t3)\n}\n\nfunc TestRecusivePointers[T1 ~*T2, T2 ~*T1](t1 T1, t2 T2) {\n\t// No error: we can't determine if pointer rules apply.\n\tfmt.Printf(\"%s\", t1)\n\tfmt.Printf(\"%s\", t2)\n}\n\nfunc TestEmptyTypeSet[T interface {\n\tint | string\n\tfloat64\n}](t T) {\n\tfmt.Printf(\"%s\", t) // No error: empty type set.\n}\n\nfunc TestPointerRules[T ~*[]int | *[2]int](t T) {\n\tvar slicePtr *[]int\n\tvar arrayPtr *[2]int\n\tfmt.Printf(\"%d\", slicePtr)\n\tfmt.Printf(\"%d\", arrayPtr)\n\tfmt.Printf(\"%d\", t)\n}\n\nfunc TestInterfacePromotion[E interface {\n\t~int\n\tError() string\n}, S interface {\n\tfloat64\n\tString() string\n}](e E, s S) {\n\tfmt.Printf(\"%d\", e)\n\tfmt.Printf(\"%s\", e)\n\tfmt.Errorf(\"%w\", e)\n\tfmt.Printf(\"%d\", s) // want \"wrong type.*contains float64\"\n\tfmt.Printf(\"%s\", s)\n\tfmt.Errorf(\"%w\", s) // want \"wrong type\"\n}\n\ntype myInt int\n\nfunc TestTermReduction[T1 interface{ ~int | string }, T2 interface {\n\t~int | string\n\tmyInt\n}](t1 T1, t2 T2) {\n\tfmt.Printf(\"%d\", t1) // want \"wrong type.*contains string\"\n\tfmt.Printf(\"%s\", t1) // want \"wrong type.*contains ~int\"\n\tfmt.Printf(\"%d\", t2)\n\tfmt.Printf(\"%s\", t2) // want \"wrong type.*contains typeparams.myInt\"\n}\n\ntype U[T any] struct{}\n\nfunc (u U[T]) String() string {\n\tfmt.Println(u) // want `fmt.Println arg u causes recursive call to \\(typeparams.U\\[T\\]\\).String method`\n\treturn \"\"\n}\n\ntype S[T comparable] struct {\n\tt T\n}\n\nfunc (s S[T]) String() T {\n\tfmt.Println(s) // Not flagged. We currently do not consider String() T to implement fmt.Stringer (see #55928).\n\treturn s.t\n}\n\nfunc TestInstanceStringer() {\n\t// Tests String method with nil Scope (#55350)\n\tfmt.Println(&S[string]{})\n\tfmt.Println(&U[string]{})\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/testdata/src/typeparams/wrappers.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"fmt\"\n\ntype N[T any] int\n\nfunc (N[P]) Wrapf(p P, format string, args ...interface{}) { // want Wrapf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n\nfunc (*N[P]) PtrWrapf(p P, format string, args ...interface{}) { // want PtrWrapf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n\nfunc Printf[P any](p P, format string, args ...interface{}) { // want Printf:\"printfWrapper\"\n\tfmt.Printf(format, args...)\n}\n"
  },
  {
    "path": "go/analysis/passes/printf/types.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage printf\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nvar errorType = types.Universe.Lookup(\"error\").Type().Underlying().(*types.Interface)\n\n// matchArgType reports an error if printf verb t is not appropriate for\n// operand arg.\n//\n// If arg is a type parameter, the verb t must be appropriate for every type in\n// the type parameter type set.\nfunc matchArgType(pass *analysis.Pass, t printfArgType, arg ast.Expr) (reason string, ok bool) {\n\t// %v, %T accept any argument type.\n\tif t == anyType {\n\t\treturn \"\", true\n\t}\n\n\ttyp := pass.TypesInfo.Types[arg].Type\n\tif typ == nil {\n\t\treturn \"\", true // probably a type check problem\n\t}\n\n\tm := &argMatcher{t: t, seen: make(map[types.Type]bool)}\n\tok = m.match(typ, true)\n\treturn m.reason, ok\n}\n\n// argMatcher recursively matches types against the printfArgType t.\n//\n// To short-circuit recursion, it keeps track of types that have already been\n// matched (or are in the process of being matched) via the seen map. Recursion\n// arises from the compound types {map,chan,slice} which may be printed with %d\n// etc. if that is appropriate for their element types, as well as from type\n// parameters, which are expanded to the constituents of their type set.\n//\n// The reason field may be set to report the cause of the mismatch.\ntype argMatcher struct {\n\tt      printfArgType\n\tseen   map[types.Type]bool\n\treason string\n}\n\n// match checks if typ matches m's printf arg type. If topLevel is true, typ is\n// the actual type of the printf arg, for which special rules apply. As a\n// special case, top level type parameters pass topLevel=true when checking for\n// matches among the constituents of their type set, as type arguments will\n// replace the type parameter at compile time.\nfunc (m *argMatcher) match(typ types.Type, topLevel bool) bool {\n\t// %w accepts only errors.\n\tif m.t == argError {\n\t\treturn types.ConvertibleTo(typ, errorType)\n\t}\n\n\t// If the type implements fmt.Formatter, we have nothing to check.\n\tif isFormatter(typ) {\n\t\treturn true\n\t}\n\n\t// If we can use a string, might arg (dynamically) implement the Stringer or Error interface?\n\tif m.t&argString != 0 && isConvertibleToString(typ) {\n\t\treturn true\n\t}\n\n\tif typ, _ := types.Unalias(typ).(*types.TypeParam); typ != nil {\n\t\t// Avoid infinite recursion through type parameters.\n\t\tif m.seen[typ] {\n\t\t\treturn true\n\t\t}\n\t\tm.seen[typ] = true\n\t\tterms, err := typeparams.StructuralTerms(typ)\n\t\tif err != nil {\n\t\t\treturn true // invalid type (possibly an empty type set)\n\t\t}\n\n\t\tif len(terms) == 0 {\n\t\t\t// No restrictions on the underlying of typ. Type parameters implementing\n\t\t\t// error, fmt.Formatter, or fmt.Stringer were handled above, and %v and\n\t\t\t// %T was handled in matchType. We're about to check restrictions the\n\t\t\t// underlying; if the underlying type is unrestricted there must be an\n\t\t\t// element of the type set that violates one of the arg type checks\n\t\t\t// below, so we can safely return false here.\n\n\t\t\tif m.t == anyType { // anyType must have already been handled.\n\t\t\t\tpanic(\"unexpected printfArgType\")\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\n\t\t// Only report a reason if typ is the argument type, otherwise it won't\n\t\t// make sense. Note that it is not sufficient to check if topLevel == here,\n\t\t// as type parameters can have a type set consisting of other type\n\t\t// parameters.\n\t\treportReason := len(m.seen) == 1\n\n\t\tfor _, term := range terms {\n\t\t\tif !m.match(term.Type(), topLevel) {\n\t\t\t\tif reportReason {\n\t\t\t\t\tif term.Tilde() {\n\t\t\t\t\t\tm.reason = fmt.Sprintf(\"contains ~%s\", term.Type())\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm.reason = fmt.Sprintf(\"contains %s\", term.Type())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\ttyp = typ.Underlying()\n\tif m.seen[typ] {\n\t\t// We've already considered typ, or are in the process of considering it.\n\t\t// In case we've already considered typ, it must have been valid (else we\n\t\t// would have stopped matching). In case we're in the process of\n\t\t// considering it, we must avoid infinite recursion.\n\t\t//\n\t\t// There are some pathological cases where returning true here is\n\t\t// incorrect, for example `type R struct { F []R }`, but these are\n\t\t// acceptable false negatives.\n\t\treturn true\n\t}\n\tm.seen[typ] = true\n\n\tswitch typ := typ.(type) {\n\tcase *types.Signature:\n\t\treturn m.t == argPointer\n\n\tcase *types.Map:\n\t\tif m.t == argPointer {\n\t\t\treturn true\n\t\t}\n\t\t// Recur: map[int]int matches %d.\n\t\treturn m.match(typ.Key(), false) && m.match(typ.Elem(), false)\n\n\tcase *types.Chan:\n\t\treturn m.t&argPointer != 0\n\n\tcase *types.Array:\n\t\t// Same as slice.\n\t\tif types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && m.t&argString != 0 {\n\t\t\treturn true // %s matches []byte\n\t\t}\n\t\t// Recur: []int matches %d.\n\t\treturn m.match(typ.Elem(), false)\n\n\tcase *types.Slice:\n\t\t// Same as array.\n\t\tif types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && m.t&argString != 0 {\n\t\t\treturn true // %s matches []byte\n\t\t}\n\t\tif m.t == argPointer {\n\t\t\treturn true // %p prints a slice's 0th element\n\t\t}\n\t\t// Recur: []int matches %d. But watch out for\n\t\t//\ttype T []T\n\t\t// If the element is a pointer type (type T[]*T), it's handled fine by the Pointer case below.\n\t\treturn m.match(typ.Elem(), false)\n\n\tcase *types.Pointer:\n\t\t// Ugly, but dealing with an edge case: a known pointer to an invalid type,\n\t\t// probably something from a failed import.\n\t\tif typ.Elem() == types.Typ[types.Invalid] {\n\t\t\treturn true // special case\n\t\t}\n\t\t// If it's actually a pointer with %p, it prints as one.\n\t\tif m.t == argPointer {\n\t\t\treturn true\n\t\t}\n\n\t\tif typeparams.IsTypeParam(typ.Elem()) {\n\t\t\treturn true // We don't know whether the logic below applies. Give up.\n\t\t}\n\n\t\tunder := typ.Elem().Underlying()\n\t\tswitch under.(type) {\n\t\tcase *types.Struct: // see below\n\t\tcase *types.Array: // see below\n\t\tcase *types.Slice: // see below\n\t\tcase *types.Map: // see below\n\t\tdefault:\n\t\t\t// Check whether the rest can print pointers.\n\t\t\treturn m.t&argPointer != 0\n\t\t}\n\t\t// If it's a top-level pointer to a struct, array, slice, type param, or\n\t\t// map, that's equivalent in our analysis to whether we can\n\t\t// print the type being pointed to. Pointers in nested levels\n\t\t// are not supported to minimize fmt running into loops.\n\t\tif !topLevel {\n\t\t\treturn false\n\t\t}\n\t\treturn m.match(under, false)\n\n\tcase *types.Struct:\n\t\t// report whether all the elements of the struct match the expected type. For\n\t\t// instance, with \"%d\" all the elements must be printable with the \"%d\" format.\n\t\tfor typf := range typ.Fields() {\n\t\t\tif !m.match(typf.Type(), false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif m.t&argString != 0 && !typf.Exported() && isConvertibleToString(typf.Type()) {\n\t\t\t\t// Issue #17798: unexported Stringer or error cannot be properly formatted.\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase *types.Interface:\n\t\t// There's little we can do.\n\t\t// Whether any particular verb is valid depends on the argument.\n\t\t// The user may have reasonable prior knowledge of the contents of the interface.\n\t\treturn true\n\n\tcase *types.Basic:\n\t\tswitch typ.Kind() {\n\t\tcase types.UntypedBool,\n\t\t\ttypes.Bool:\n\t\t\treturn m.t&argBool != 0\n\n\t\tcase types.Byte:\n\t\t\treturn m.t&(argInt|argByte) != 0\n\n\t\tcase types.Rune, types.UntypedRune:\n\t\t\treturn m.t&(argInt|argRune) != 0\n\n\t\tcase types.UntypedInt,\n\t\t\ttypes.Int,\n\t\t\ttypes.Int8,\n\t\t\ttypes.Int16,\n\t\t\t// see case Rune for int32\n\t\t\ttypes.Int64,\n\t\t\ttypes.Uint,\n\t\t\t// see case Byte for uint8\n\t\t\ttypes.Uint16,\n\t\t\ttypes.Uint32,\n\t\t\ttypes.Uint64,\n\t\t\ttypes.Uintptr:\n\t\t\treturn m.t&argInt != 0\n\n\t\tcase types.UntypedFloat,\n\t\t\ttypes.Float32,\n\t\t\ttypes.Float64:\n\t\t\treturn m.t&argFloat != 0\n\n\t\tcase types.UntypedComplex,\n\t\t\ttypes.Complex64,\n\t\t\ttypes.Complex128:\n\t\t\treturn m.t&argComplex != 0\n\n\t\tcase types.UntypedString,\n\t\t\ttypes.String:\n\t\t\treturn m.t&argString != 0\n\n\t\tcase types.UnsafePointer:\n\t\t\treturn m.t&(argPointer|argInt) != 0\n\n\t\tcase types.UntypedNil:\n\t\t\treturn false\n\n\t\tcase types.Invalid:\n\t\t\treturn true // Probably a type check problem.\n\t\t}\n\t\tpanic(\"unreachable\")\n\t}\n\n\treturn false\n}\n\nfunc isConvertibleToString(typ types.Type) bool {\n\tif bt, ok := types.Unalias(typ).(*types.Basic); ok && bt.Kind() == types.UntypedNil {\n\t\t// We explicitly don't want untyped nil, which is\n\t\t// convertible to both of the interfaces below, as it\n\t\t// would just panic anyway.\n\t\treturn false\n\t}\n\tif types.ConvertibleTo(typ, errorType) {\n\t\treturn true // via .Error()\n\t}\n\n\t// Does it implement fmt.Stringer?\n\tif obj, _, _ := types.LookupFieldOrMethod(typ, false, nil, \"String\"); obj != nil {\n\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\tsig := fn.Type().(*types.Signature)\n\t\t\tif sig.Params().Len() == 0 &&\n\t\t\t\tsig.Results().Len() == 1 &&\n\t\t\t\tsig.Results().At(0).Type() == types.Typ[types.String] {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "go/analysis/passes/reflectvaluecompare/cmd/reflectvaluecompare/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The reflectvaluecompare command applies the reflectvaluecompare\n// checker to the specified packages of Go source code.\n//\n// Run with:\n//\n//\t$ go run ./go/analysis/passes/reflectvaluecompare/cmd/reflectvaluecompare -- packages...\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/reflectvaluecompare\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(reflectvaluecompare.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/reflectvaluecompare/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package reflectvaluecompare defines an Analyzer that checks for accidentally\n// using == or reflect.DeepEqual to compare reflect.Value values.\n// See issues 43993 and 18871.\n//\n// # Analyzer reflectvaluecompare\n//\n// reflectvaluecompare: check for comparing reflect.Value values with == or reflect.DeepEqual\n//\n// The reflectvaluecompare checker looks for expressions of the form:\n//\n//\tv1 == v2\n//\tv1 != v2\n//\treflect.DeepEqual(v1, v2)\n//\n// where v1 or v2 are reflect.Values. Comparing reflect.Values directly\n// is almost certainly not correct, as it compares the reflect package's\n// internal representation, not the underlying value.\n// Likely what is intended is:\n//\n//\tv1.Interface() == v2.Interface()\n//\tv1.Interface() != v2.Interface()\n//\treflect.DeepEqual(v1.Interface(), v2.Interface())\npackage reflectvaluecompare\n"
  },
  {
    "path": "go/analysis/passes/reflectvaluecompare/reflectvaluecompare.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflectvaluecompare\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"reflectvaluecompare\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"reflectvaluecompare\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/reflectvaluecompare\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.BinaryExpr)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.BinaryExpr:\n\t\t\tif n.Op != token.EQL && n.Op != token.NEQ {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif isReflectValue(pass, n.X) || isReflectValue(pass, n.Y) {\n\t\t\t\tif n.Op == token.EQL {\n\t\t\t\t\tpass.ReportRangef(n, \"avoid using == with reflect.Value\")\n\t\t\t\t} else {\n\t\t\t\t\tpass.ReportRangef(n, \"avoid using != with reflect.Value\")\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.CallExpr:\n\t\t\tobj := typeutil.Callee(pass.TypesInfo, n)\n\t\t\tif typesinternal.IsFunctionNamed(obj, \"reflect\", \"DeepEqual\") && (isReflectValue(pass, n.Args[0]) || isReflectValue(pass, n.Args[1])) {\n\t\t\t\tpass.ReportRangef(n, \"avoid using reflect.DeepEqual with reflect.Value\")\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// isReflectValue reports whether the type of e is reflect.Value.\nfunc isReflectValue(pass *analysis.Pass, e ast.Expr) bool {\n\ttv, ok := pass.TypesInfo.Types[e]\n\tif !ok { // no type info, something else is wrong\n\t\treturn false\n\t}\n\t// See if the type is reflect.Value\n\tif !typesinternal.IsTypeNamed(tv.Type, \"reflect\", \"Value\") {\n\t\treturn false\n\t}\n\tif _, ok := e.(*ast.CompositeLit); ok {\n\t\t// This is reflect.Value{}. Don't treat that as an error.\n\t\t// Users should probably use x.IsValid() rather than x == reflect.Value{}, but the latter isn't wrong.\n\t\treturn false\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "go/analysis/passes/reflectvaluecompare/reflectvaluecompare_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflectvaluecompare_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/reflectvaluecompare\"\n)\n\nfunc TestReflectValueCompare(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, reflectvaluecompare.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/reflectvaluecompare/testdata/src/a/a.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the reflectvaluecompare checker.\n\npackage a\n\nimport (\n\t\"reflect\"\n)\n\nfunc f() {\n\tvar x, y reflect.Value\n\tvar a, b interface{}\n\t_ = x == y // want `avoid using == with reflect.Value`\n\t_ = x == a // want `avoid using == with reflect.Value`\n\t_ = a == x // want `avoid using == with reflect.Value`\n\t_ = a == b\n\n\t// Comparing to reflect.Value{} is ok.\n\t_ = a == reflect.Value{}\n\t_ = reflect.Value{} == a\n\t_ = reflect.Value{} == reflect.Value{}\n}\nfunc g() {\n\tvar x, y reflect.Value\n\tvar a, b interface{}\n\t_ = x != y // want `avoid using != with reflect.Value`\n\t_ = x != a // want `avoid using != with reflect.Value`\n\t_ = a != x // want `avoid using != with reflect.Value`\n\t_ = a != b\n\n\t// Comparing to reflect.Value{} is ok.\n\t_ = a != reflect.Value{}\n\t_ = reflect.Value{} != a\n\t_ = reflect.Value{} != reflect.Value{}\n}\nfunc h() {\n\tvar x, y reflect.Value\n\tvar a, b interface{}\n\treflect.DeepEqual(x, y) // want `avoid using reflect.DeepEqual with reflect.Value`\n\treflect.DeepEqual(x, a) // want `avoid using reflect.DeepEqual with reflect.Value`\n\treflect.DeepEqual(a, x) // want `avoid using reflect.DeepEqual with reflect.Value`\n\treflect.DeepEqual(a, b)\n\n\t// Comparing to reflect.Value{} is ok.\n\treflect.DeepEqual(reflect.Value{}, a)\n\treflect.DeepEqual(a, reflect.Value{})\n\treflect.DeepEqual(reflect.Value{}, reflect.Value{})\n}\n"
  },
  {
    "path": "go/analysis/passes/shadow/cmd/shadow/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The shadow command runs the shadow analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/shadow\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(shadow.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/shadow/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package shadow defines an Analyzer that checks for shadowed variables.\n//\n// # Analyzer shadow\n//\n// shadow: check for possible unintended shadowing of variables\n//\n// This analyzer check for shadowed variables.\n// A shadowed variable is a variable declared in an inner scope\n// with the same name and type as a variable in an outer scope,\n// and where the outer variable is mentioned after the inner one\n// is declared.\n//\n// (This definition can be refined; the module generates too many\n// false positives and is not yet enabled by default.)\n//\n// For example:\n//\n//\tfunc BadRead(f *os.File, buf []byte) error {\n//\t\tvar err error\n//\t\tfor {\n//\t\t\tn, err := f.Read(buf) // shadows the function variable 'err'\n//\t\t\tif err != nil {\n//\t\t\t\tbreak // causes return of wrong value\n//\t\t\t}\n//\t\t\tfoo(buf)\n//\t\t}\n//\t\treturn err\n//\t}\npackage shadow\n"
  },
  {
    "path": "go/analysis/passes/shadow/shadow.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage shadow\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n// NOTE: Experimental. Not part of the vet suite.\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"shadow\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"shadow\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shadow\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\n// flags\nvar strict = false\n\nfunc init() {\n\tAnalyzer.Flags.BoolVar(&strict, \"strict\", strict, \"whether to be strict about shadowing; can be noisy\")\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tspans := make(map[types.Object]span)\n\tfor id, obj := range pass.TypesInfo.Defs {\n\t\t// Ignore identifiers that don't denote objects\n\t\t// (package names, symbolic variables such as t\n\t\t// in t := x.(type) of type switch headers).\n\t\tif obj != nil {\n\t\t\tgrowSpan(spans, obj, id.Pos(), id.End())\n\t\t}\n\t}\n\tfor id, obj := range pass.TypesInfo.Uses {\n\t\tgrowSpan(spans, obj, id.Pos(), id.End())\n\t}\n\tfor node, obj := range pass.TypesInfo.Implicits {\n\t\t// A type switch with a short variable declaration\n\t\t// such as t := x.(type) doesn't declare the symbolic\n\t\t// variable (t in the example) at the switch header;\n\t\t// instead a new variable t (with specific type) is\n\t\t// declared implicitly for each case. Such variables\n\t\t// are found in the types.Info.Implicits (not Defs)\n\t\t// map. Add them here, assuming they are declared at\n\t\t// the type cases' colon \":\".\n\t\tif cc, ok := node.(*ast.CaseClause); ok {\n\t\t\tgrowSpan(spans, obj, cc.Colon, cc.Colon)\n\t\t}\n\t}\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.AssignStmt)(nil),\n\t\t(*ast.GenDecl)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.AssignStmt:\n\t\t\tcheckShadowAssignment(pass, spans, n)\n\t\tcase *ast.GenDecl:\n\t\t\tcheckShadowDecl(pass, spans, n)\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// A span stores the minimum range of byte positions in the file in which a\n// given variable (types.Object) is mentioned. It is lexically defined: it spans\n// from the beginning of its first mention to the end of its last mention.\n// A variable is considered shadowed (if strict is off) only if the\n// shadowing variable is declared within the span of the shadowed variable.\n// In other words, if a variable is shadowed but not used after the shadowed\n// variable is declared, it is inconsequential and not worth complaining about.\n// This simple check dramatically reduces the nuisance rate for the shadowing\n// check, at least until something cleverer comes along.\n//\n// One wrinkle: A \"naked return\" is a silent use of a variable that the Span\n// will not capture, but the compilers catch naked returns of shadowed\n// variables so we don't need to.\n//\n// Cases this gets wrong (TODO):\n// - If a for loop's continuation statement mentions a variable redeclared in\n// the block, we should complain about it but don't.\n// - A variable declared inside a function literal can falsely be identified\n// as shadowing a variable in the outer function.\ntype span struct {\n\tmin token.Pos\n\tmax token.Pos\n}\n\n// contains reports whether the position is inside the span.\nfunc (s span) contains(pos token.Pos) bool {\n\treturn s.min <= pos && pos < s.max\n}\n\n// growSpan expands the span for the object to contain the source range [pos, end).\nfunc growSpan(spans map[types.Object]span, obj types.Object, pos, end token.Pos) {\n\tif strict {\n\t\treturn // No need\n\t}\n\ts, ok := spans[obj]\n\tif ok {\n\t\tif s.min > pos {\n\t\t\ts.min = pos\n\t\t}\n\t\tif s.max < end {\n\t\t\ts.max = end\n\t\t}\n\t} else {\n\t\ts = span{pos, end}\n\t}\n\tspans[obj] = s\n}\n\n// checkShadowAssignment checks for shadowing in a short variable declaration.\nfunc checkShadowAssignment(pass *analysis.Pass, spans map[types.Object]span, a *ast.AssignStmt) {\n\tif a.Tok != token.DEFINE {\n\t\treturn\n\t}\n\tif idiomaticShortRedecl(pass, a) {\n\t\treturn\n\t}\n\tfor _, expr := range a.Lhs {\n\t\tident, ok := expr.(*ast.Ident)\n\t\tif !ok {\n\t\t\tpass.ReportRangef(expr, \"invalid AST: short variable declaration of non-identifier\")\n\t\t\treturn\n\t\t}\n\t\tcheckShadowing(pass, spans, ident)\n\t}\n}\n\n// idiomaticShortRedecl reports whether this short declaration can be ignored for\n// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.\nfunc idiomaticShortRedecl(pass *analysis.Pass, a *ast.AssignStmt) bool {\n\t// Don't complain about deliberate redeclarations of the form\n\t//\ti := i\n\t// Such constructs are idiomatic in range loops to create a new variable\n\t// for each iteration. Another example is\n\t//\tswitch n := n.(type)\n\tif len(a.Rhs) != len(a.Lhs) {\n\t\treturn false\n\t}\n\t// We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)\n\tfor i, expr := range a.Lhs {\n\t\tlhs, ok := expr.(*ast.Ident)\n\t\tif !ok {\n\t\t\tpass.ReportRangef(expr, \"invalid AST: short variable declaration of non-identifier\")\n\t\t\treturn true // Don't do any more processing.\n\t\t}\n\t\tswitch rhs := a.Rhs[i].(type) {\n\t\tcase *ast.Ident:\n\t\t\tif lhs.Name != rhs.Name {\n\t\t\t\treturn false\n\t\t\t}\n\t\tcase *ast.TypeAssertExpr:\n\t\t\tif id, ok := rhs.X.(*ast.Ident); ok {\n\t\t\t\tif lhs.Name != id.Name {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// idiomaticRedecl reports whether this declaration spec can be ignored for\n// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.\nfunc idiomaticRedecl(d *ast.ValueSpec) bool {\n\t// Don't complain about deliberate redeclarations of the form\n\t//\tvar i, j = i, j\n\t// Don't ignore redeclarations of the form\n\t//\tvar i = 3\n\tif len(d.Names) != len(d.Values) {\n\t\treturn false\n\t}\n\tfor i, lhs := range d.Names {\n\t\trhs, ok := d.Values[i].(*ast.Ident)\n\t\tif !ok || lhs.Name != rhs.Name {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// checkShadowDecl checks for shadowing in a general variable declaration.\nfunc checkShadowDecl(pass *analysis.Pass, spans map[types.Object]span, d *ast.GenDecl) {\n\tif d.Tok != token.VAR {\n\t\treturn\n\t}\n\tfor _, spec := range d.Specs {\n\t\tvalueSpec, ok := spec.(*ast.ValueSpec)\n\t\tif !ok {\n\t\t\tpass.ReportRangef(spec, \"invalid AST: var GenDecl not ValueSpec\")\n\t\t\treturn\n\t\t}\n\t\t// Don't complain about deliberate redeclarations of the form\n\t\t//\tvar i = i\n\t\tif idiomaticRedecl(valueSpec) {\n\t\t\treturn\n\t\t}\n\t\tfor _, ident := range valueSpec.Names {\n\t\t\tcheckShadowing(pass, spans, ident)\n\t\t}\n\t}\n}\n\n// checkShadowing checks whether the identifier shadows an identifier in an outer scope.\nfunc checkShadowing(pass *analysis.Pass, spans map[types.Object]span, ident *ast.Ident) {\n\tif ident.Name == \"_\" {\n\t\t// Can't shadow the blank identifier.\n\t\treturn\n\t}\n\tobj := pass.TypesInfo.Defs[ident]\n\tif obj == nil {\n\t\treturn\n\t}\n\t// obj.Parent.Parent is the surrounding scope. If we can find another declaration\n\t// starting from there, we have a shadowed identifier.\n\t_, shadowed := obj.Parent().Parent().LookupParent(obj.Name(), obj.Pos())\n\tif shadowed == nil {\n\t\treturn\n\t}\n\t// Don't complain if it's shadowing a universe-declared identifier; that's fine.\n\tif shadowed.Parent() == types.Universe {\n\t\treturn\n\t}\n\tif strict {\n\t\t// The shadowed identifier must appear before this one to be an instance of shadowing.\n\t\tif shadowed.Pos() > ident.Pos() {\n\t\t\treturn\n\t\t}\n\t} else {\n\t\t// Don't complain if the span of validity of the shadowed identifier doesn't include\n\t\t// the shadowing identifier.\n\t\tspan, ok := spans[shadowed]\n\t\tif !ok {\n\t\t\tpass.ReportRangef(ident, \"internal error: no range for %q\", ident.Name)\n\t\t\treturn\n\t\t}\n\t\tif !span.contains(ident.Pos()) {\n\t\t\treturn\n\t\t}\n\t}\n\t// Don't complain if the types differ: that implies the programmer really wants two different things.\n\tif types.Identical(obj.Type(), shadowed.Type()) {\n\t\tline := pass.Fset.Position(shadowed.Pos()).Line\n\t\tpass.ReportRangef(ident, \"declaration of %q shadows declaration at line %d\", obj.Name(), line)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/shadow/shadow_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage shadow_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/shadow\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, shadow.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/shadow/testdata/src/a/a.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the shadowed variable checker.\n// Some of these errors are caught by the compiler (shadowed return parameters for example)\n// but are nonetheless useful tests.\n\npackage a\n\nimport \"os\"\n\nfunc ShadowRead(f *os.File, buf []byte) (err error) {\n\tvar x int\n\tif f != nil {\n\t\terr := 3 // OK - different type.\n\t\t_ = err\n\t}\n\tif f != nil {\n\t\t_, err := f.Read(buf) // want \"declaration of .err. shadows declaration at line 13\"\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ti := 3 // OK\n\t\t_ = i\n\t}\n\tif f != nil {\n\t\tx := one()               // want \"declaration of .x. shadows declaration at line 14\"\n\t\tvar _, err = f.Read(buf) // want \"declaration of .err. shadows declaration at line 13\"\n\t\tif x == 1 && err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor i := 0; i < 10; i++ {\n\t\ti := i // OK: obviously intentional idiomatic redeclaration\n\t\tgo func() {\n\t\t\tprintln(i)\n\t\t}()\n\t}\n\tvar shadowTemp interface{}\n\tswitch shadowTemp := shadowTemp.(type) { // OK: obviously intentional idiomatic redeclaration\n\tcase int:\n\t\tprintln(\"OK\")\n\t\t_ = shadowTemp\n\t}\n\tif shadowTemp := shadowTemp; true { // OK: obviously intentional idiomatic redeclaration\n\t\tvar f *os.File // OK because f is not mentioned later in the function.\n\t\t// The declaration of x is a shadow because x is mentioned below.\n\t\tvar x int // want \"declaration of .x. shadows declaration at line 14\"\n\t\t_, _, _ = x, f, shadowTemp\n\t}\n\t// Use a couple of variables to trigger shadowing errors.\n\t_, _ = err, x\n\treturn\n}\n\nfunc one() int {\n\treturn 1\n}\n\n// Must not complain with an internal error for the\n// implicitly declared type switch variable v.\nfunc issue26725(x interface{}) int {\n\tswitch v := x.(type) {\n\tcase int, int32:\n\t\tif v, ok := x.(int); ok {\n\t\t\treturn v\n\t\t}\n\tcase int64:\n\t\treturn int(v)\n\t}\n\treturn 0\n}\n\n// Verify that implicitly declared variables from\n// type switches are considered in shadowing analysis.\nfunc shadowTypeSwitch(a interface{}) {\n\tswitch t := a.(type) {\n\tcase int:\n\t\t{\n\t\t\tt := 0 // want \"declaration of .t. shadows declaration at line 78\"\n\t\t\t_ = t\n\t\t}\n\t\t_ = t\n\tcase uint:\n\t\t{\n\t\t\tt := uint(0) // OK because t is not mentioned later in this function\n\t\t\t_ = t\n\t\t}\n\t}\n}\n\nfunc shadowBlock() {\n\tvar a int\n\t{\n\t\tvar a = 3 // want \"declaration of .a. shadows declaration at line 94\"\n\t\t_ = a\n\t}\n\t_ = a\n}\n"
  },
  {
    "path": "go/analysis/passes/shift/dead.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage shift\n\n// Simplified dead code detector.\n// Used for skipping shift checks on unreachable arch-specific code.\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/types\"\n)\n\n// updateDead puts unreachable \"if\" and \"case\" nodes into dead.\nfunc updateDead(info *types.Info, dead map[ast.Node]bool, node ast.Node) {\n\tif dead[node] {\n\t\t// The node is already marked as dead.\n\t\treturn\n\t}\n\n\t// setDead marks the node and all the children as dead.\n\tsetDead := func(n ast.Node) {\n\t\tast.Inspect(n, func(node ast.Node) bool {\n\t\t\tif node != nil {\n\t\t\t\tdead[node] = true\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\n\tswitch stmt := node.(type) {\n\tcase *ast.IfStmt:\n\t\t// \"if\" branch is dead if its condition evaluates\n\t\t// to constant false.\n\t\tv := info.Types[stmt.Cond].Value\n\t\tif v == nil {\n\t\t\treturn\n\t\t}\n\t\tif !constant.BoolVal(v) {\n\t\t\tsetDead(stmt.Body)\n\t\t\treturn\n\t\t}\n\t\tif stmt.Else != nil {\n\t\t\tsetDead(stmt.Else)\n\t\t}\n\tcase *ast.SwitchStmt:\n\t\t// Case clause with empty switch tag is dead if it evaluates\n\t\t// to constant false.\n\t\tif stmt.Tag == nil {\n\t\tBodyLoopBool:\n\t\t\tfor _, stmt := range stmt.Body.List {\n\t\t\t\tcc := stmt.(*ast.CaseClause)\n\t\t\t\tif cc.List == nil {\n\t\t\t\t\t// Skip default case.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor _, expr := range cc.List {\n\t\t\t\t\tv := info.Types[expr].Value\n\t\t\t\t\tif v == nil || v.Kind() != constant.Bool || constant.BoolVal(v) {\n\t\t\t\t\t\tcontinue BodyLoopBool\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetDead(cc)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Case clause is dead if its constant value doesn't match\n\t\t// the constant value from the switch tag.\n\t\t// TODO: This handles integer comparisons only.\n\t\tv := info.Types[stmt.Tag].Value\n\t\tif v == nil || v.Kind() != constant.Int {\n\t\t\treturn\n\t\t}\n\t\ttagN, ok := constant.Uint64Val(v)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\tBodyLoopInt:\n\t\tfor _, x := range stmt.Body.List {\n\t\t\tcc := x.(*ast.CaseClause)\n\t\t\tif cc.List == nil {\n\t\t\t\t// Skip default case.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, expr := range cc.List {\n\t\t\t\tv := info.Types[expr].Value\n\t\t\t\tif v == nil {\n\t\t\t\t\tcontinue BodyLoopInt\n\t\t\t\t}\n\t\t\t\tn, ok := constant.Uint64Val(v)\n\t\t\t\tif !ok || tagN == n {\n\t\t\t\t\tcontinue BodyLoopInt\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetDead(cc)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/shift/shift.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package shift defines an Analyzer that checks for shifts that exceed\n// the width of an integer.\npackage shift\n\n// TODO(adonovan): integrate with ctrflow (CFG-based) dead code analysis. May\n// have impedance mismatch due to its (non-)treatment of constant\n// expressions (such as runtime.GOARCH==\"386\").\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nconst Doc = \"check for shifts that equal or exceed the width of the integer\"\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"shift\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shift\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// Do a complete pass to compute dead nodes.\n\tdead := make(map[ast.Node]bool)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.IfStmt)(nil),\n\t\t(*ast.SwitchStmt)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\t// TODO(adonovan): move updateDead into this file.\n\t\tupdateDead(pass.TypesInfo, dead, n)\n\t})\n\n\tnodeFilter = []ast.Node{\n\t\t(*ast.AssignStmt)(nil),\n\t\t(*ast.BinaryExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tif dead[node] {\n\t\t\t// Skip shift checks on unreachable nodes.\n\t\t\treturn\n\t\t}\n\n\t\tswitch node := node.(type) {\n\t\tcase *ast.BinaryExpr:\n\t\t\tif node.Op == token.SHL || node.Op == token.SHR {\n\t\t\t\tcheckLongShift(pass, node, node.X, node.Y)\n\t\t\t}\n\t\tcase *ast.AssignStmt:\n\t\t\tif len(node.Lhs) != 1 || len(node.Rhs) != 1 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif node.Tok == token.SHL_ASSIGN || node.Tok == token.SHR_ASSIGN {\n\t\t\t\tcheckLongShift(pass, node, node.Lhs[0], node.Rhs[0])\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// checkLongShift checks if shift or shift-assign operations shift by more than\n// the length of the underlying variable.\nfunc checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) {\n\tif pass.TypesInfo.Types[x].Value != nil {\n\t\t// Ignore shifts of constants.\n\t\t// These are frequently used for bit-twiddling tricks\n\t\t// like ^uint(0) >> 63 for 32/64 bit detection and compatibility.\n\t\treturn\n\t}\n\n\tv := pass.TypesInfo.Types[y].Value\n\tif v == nil {\n\t\treturn\n\t}\n\tu := constant.ToInt(v) // either an Int or Unknown\n\tamt, ok := constant.Int64Val(u)\n\tif !ok {\n\t\treturn\n\t}\n\tt := pass.TypesInfo.Types[x].Type\n\tif t == nil {\n\t\treturn\n\t}\n\tvar structuralTypes []types.Type\n\tswitch t := types.Unalias(t).(type) {\n\tcase *types.TypeParam:\n\t\tterms, err := typeparams.StructuralTerms(t)\n\t\tif err != nil {\n\t\t\treturn // invalid type\n\t\t}\n\t\tfor _, term := range terms {\n\t\t\tstructuralTypes = append(structuralTypes, term.Type())\n\t\t}\n\tdefault:\n\t\tstructuralTypes = append(structuralTypes, t)\n\t}\n\tsizes := make(map[int64]struct{})\n\tfor _, t := range structuralTypes {\n\t\tsize := 8 * pass.TypesSizes.Sizeof(t)\n\t\tsizes[size] = struct{}{}\n\t}\n\tminSize := int64(math.MaxInt64)\n\tfor size := range sizes {\n\t\tif size < minSize {\n\t\t\tminSize = size\n\t\t}\n\t}\n\tif amt >= minSize {\n\t\tident := astutil.Format(pass.Fset, x)\n\t\tqualifier := \"\"\n\t\tif len(sizes) > 1 {\n\t\t\tqualifier = \"may be \"\n\t\t}\n\t\tpass.ReportRangef(node, \"%s (%s%d bits) too small for shift of %d\", ident, qualifier, minSize, amt)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/shift/shift_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage shift_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/shift\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, shift.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/shift/testdata/src/a/a.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the suspicious shift checker.\n\npackage shift\n\nimport (\n\t\"unsafe\"\n)\n\nfunc ShiftTest() {\n\tvar i8 int8\n\t_ = i8 << 7\n\t_ = (i8 + 1) << 8 // want \".i8 . 1. .8 bits. too small for shift of 8\"\n\t_ = i8 << (7 + 1) // want \"i8 .8 bits. too small for shift of 8\"\n\t_ = i8 >> 8       // want \"i8 .8 bits. too small for shift of 8\"\n\ti8 <<= 8          // want \"i8 .8 bits. too small for shift of 8\"\n\ti8 >>= 8          // want \"i8 .8 bits. too small for shift of 8\"\n\tvar i16 int16\n\t_ = i16 << 15\n\t_ = i16 << 16 // want \"i16 .16 bits. too small for shift of 16\"\n\t_ = i16 >> 16 // want \"i16 .16 bits. too small for shift of 16\"\n\ti16 <<= 16    // want \"i16 .16 bits. too small for shift of 16\"\n\ti16 >>= 16    // want \"i16 .16 bits. too small for shift of 16\"\n\tvar i32 int32\n\t_ = i32 << 31\n\t_ = i32 << 32 // want \"i32 .32 bits. too small for shift of 32\"\n\t_ = i32 >> 32 // want \"i32 .32 bits. too small for shift of 32\"\n\ti32 <<= 32    // want \"i32 .32 bits. too small for shift of 32\"\n\ti32 >>= 32    // want \"i32 .32 bits. too small for shift of 32\"\n\tvar i64 int64\n\t_ = i64 << 63\n\t_ = i64 << 64 // want \"i64 .64 bits. too small for shift of 64\"\n\t_ = i64 >> 64 // want \"i64 .64 bits. too small for shift of 64\"\n\ti64 <<= 64    // want \"i64 .64 bits. too small for shift of 64\"\n\ti64 >>= 64    // want \"i64 .64 bits. too small for shift of 64\"\n\tvar u8 uint8\n\t_ = u8 << 7\n\t_ = u8 << 8 // want \"u8 .8 bits. too small for shift of 8\"\n\t_ = u8 >> 8 // want \"u8 .8 bits. too small for shift of 8\"\n\tu8 <<= 8    // want \"u8 .8 bits. too small for shift of 8\"\n\tu8 >>= 8    // want \"u8 .8 bits. too small for shift of 8\"\n\tvar u16 uint16\n\t_ = u16 << 15\n\t_ = u16 << 16 // want \"u16 .16 bits. too small for shift of 16\"\n\t_ = u16 >> 16 // want \"u16 .16 bits. too small for shift of 16\"\n\tu16 <<= 16    // want \"u16 .16 bits. too small for shift of 16\"\n\tu16 >>= 16    // want \"u16 .16 bits. too small for shift of 16\"\n\tvar u32 uint32\n\t_ = u32 << 31\n\t_ = u32 << 32 // want \"u32 .32 bits. too small for shift of 32\"\n\t_ = u32 >> 32 // want \"u32 .32 bits. too small for shift of 32\"\n\tu32 <<= 32    // want \"u32 .32 bits. too small for shift of 32\"\n\tu32 >>= 32    // want \"u32 .32 bits. too small for shift of 32\"\n\tvar u64 uint64\n\t_ = u64 << 63\n\t_ = u64 << 64  // want \"u64 .64 bits. too small for shift of 64\"\n\t_ = u64 >> 64  // want \"u64 .64 bits. too small for shift of 64\"\n\tu64 <<= 64     // want \"u64 .64 bits. too small for shift of 64\"\n\tu64 >>= 64     // want \"u64 .64 bits. too small for shift of 64\"\n\t_ = u64 << u64 // Non-constant shifts should succeed.\n\n\tvar i int\n\t_ = i << 31\n\tconst in = 8 * unsafe.Sizeof(i)\n\t_ = i << in // want \"too small for shift\"\n\t_ = i >> in // want \"too small for shift\"\n\ti <<= in    // want \"too small for shift\"\n\ti >>= in    // want \"too small for shift\"\n\tconst ix = 8*unsafe.Sizeof(i) - 1\n\t_ = i << ix\n\t_ = i >> ix\n\ti <<= ix\n\ti >>= ix\n\n\tvar u uint\n\t_ = u << 31\n\tconst un = 8 * unsafe.Sizeof(u)\n\t_ = u << un // want \"too small for shift\"\n\t_ = u >> un // want \"too small for shift\"\n\tu <<= un    // want \"too small for shift\"\n\tu >>= un    // want \"too small for shift\"\n\tconst ux = 8*unsafe.Sizeof(u) - 1\n\t_ = u << ux\n\t_ = u >> ux\n\tu <<= ux\n\tu >>= ux\n\n\tvar p uintptr\n\t_ = p << 31\n\tconst pn = 8 * unsafe.Sizeof(p)\n\t_ = p << pn // want \"too small for shift\"\n\t_ = p >> pn // want \"too small for shift\"\n\tp <<= pn    // want \"too small for shift\"\n\tp >>= pn    // want \"too small for shift\"\n\tconst px = 8*unsafe.Sizeof(p) - 1\n\t_ = p << px\n\t_ = p >> px\n\tp <<= px\n\tp >>= px\n\n\tconst oneIf64Bit = ^uint(0) >> 63 // allow large shifts of constants; they are used for 32/64 bit compatibility tricks\n\n\tvar h uintptr\n\th = h<<8 | (h >> (8 * (unsafe.Sizeof(h) - 1)))\n\th <<= 8 * unsafe.Sizeof(h) // want \"too small for shift\"\n\th >>= 7 * unsafe.Alignof(h)\n\th >>= 8 * unsafe.Alignof(h) // want \"too small for shift\"\n}\n\nfunc ShiftDeadCode() {\n\tvar i int\n\tconst iBits = 8 * unsafe.Sizeof(i)\n\n\tif iBits <= 32 {\n\t\tif iBits == 16 {\n\t\t\t_ = i >> 8\n\t\t} else {\n\t\t\t_ = i >> 16\n\t\t}\n\t} else {\n\t\t_ = i >> 32\n\t}\n\n\tif iBits >= 64 {\n\t\t_ = i << 32\n\t\tif iBits == 128 {\n\t\t\t_ = i << 64\n\t\t}\n\t} else {\n\t\t_ = i << 16\n\t}\n\n\tif iBits == 64 {\n\t\t_ = i << 32\n\t}\n\n\tswitch iBits {\n\tcase 128, 64:\n\t\t_ = i << 32\n\tdefault:\n\t\t_ = i << 16\n\t}\n\n\tswitch {\n\tcase iBits < 32:\n\t\t_ = i << 16\n\tcase iBits > 64:\n\t\t_ = i << 64\n\tdefault:\n\t\t_ = i << 64 // want \"too small for shift\"\n\t}\n}\n\nfunc issue65939() {\n\ta := 1\n\tprintln(a << 2.0)\n}\n"
  },
  {
    "path": "go/analysis/passes/shift/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"unsafe\"\n\nfunc GenericShiftTest[DifferentSize ~int8|int16|int64, SameSize int8|byte]() {\n\tvar d DifferentSize\n\t_ = d << 7\n\t_ = d << 8        // want \"d .may be 8 bits. too small for shift of 8\"\n\t_ = d << 15       // want \"d .may be 8 bits. too small for shift of 15\"\n\t_ = (d + 1) << 8  // want \".d . 1. .may be 8 bits. too small for shift of 8\"\n\t_ = (d + 1) << 16 // want \".d . 1. .may be 8 bits. too small for shift of 16\"\n\t_ = d << (7 + 1)  // want \"d .may be 8 bits. too small for shift of 8\"\n\t_ = d >> 8        // want \"d .may be 8 bits. too small for shift of 8\"\n\td <<= 8           // want \"d .may be 8 bits. too small for shift of 8\"\n\td >>= 8           // want \"d .may be 8 bits. too small for shift of 8\"\n\n\t// go/types does not compute constant sizes for type parameters, so we do not\n\t// report a diagnostic here.\n\t_ = d << (8 * DifferentSize(unsafe.Sizeof(d)))\n\n\tvar s SameSize\n\t_ = s << 7\n\t_ = s << 8        // want \"s .8 bits. too small for shift of 8\"\n\t_ = s << (7 + 1)  // want \"s .8 bits. too small for shift of 8\"\n\t_ = s >> 8        // want \"s .8 bits. too small for shift of 8\"\n\ts <<= 8           // want \"s .8 bits. too small for shift of 8\"\n\ts >>= 8           // want \"s .8 bits. too small for shift of 8\"\n}\n"
  },
  {
    "path": "go/analysis/passes/sigchanyzer/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sigchanyzer defines an Analyzer that detects\n// misuse of unbuffered signal as argument to signal.Notify.\n//\n// # Analyzer sigchanyzer\n//\n// sigchanyzer: check for unbuffered channel of os.Signal\n//\n// This checker reports call expression of the form\n//\n//\tsignal.Notify(c <-chan os.Signal, sig ...os.Signal),\n//\n// where c is an unbuffered channel, which can be at risk of missing the signal.\npackage sigchanyzer\n"
  },
  {
    "path": "go/analysis/passes/sigchanyzer/sigchanyzer.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sigchanyzer defines an Analyzer that detects\n// misuse of unbuffered signal as argument to signal.Notify.\npackage sigchanyzer\n\nimport (\n\t\"bytes\"\n\t\"slices\"\n\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\n// Analyzer describes sigchanyzer analysis function detector.\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"sigchanyzer\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"sigchanyzer\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"os/signal\") {\n\t\treturn nil, nil // doesn't directly import signal\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tif !isSignalNotify(pass.TypesInfo, call) {\n\t\t\treturn\n\t\t}\n\t\tvar chanDecl *ast.CallExpr\n\t\tswitch arg := call.Args[0].(type) {\n\t\tcase *ast.Ident:\n\t\t\tif decl, ok := findDecl(arg).(*ast.CallExpr); ok {\n\t\t\t\tchanDecl = decl\n\t\t\t}\n\t\tcase *ast.CallExpr:\n\t\t\t// Only signal.Notify(make(chan os.Signal), os.Interrupt) is safe,\n\t\t\t// conservatively treat others as not safe, see golang/go#45043\n\t\t\tif isBuiltinMake(pass.TypesInfo, arg) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tchanDecl = arg\n\t\t}\n\t\tif chanDecl == nil || len(chanDecl.Args) != 1 {\n\t\t\treturn\n\t\t}\n\n\t\t// Make a copy of the channel's declaration to avoid\n\t\t// mutating the AST. See https://golang.org/issue/46129.\n\t\tchanDeclCopy := &ast.CallExpr{}\n\t\t*chanDeclCopy = *chanDecl\n\t\tchanDeclCopy.Args = slices.Clone(chanDecl.Args)\n\t\tchanDeclCopy.Args = append(chanDeclCopy.Args, &ast.BasicLit{\n\t\t\tKind:  token.INT,\n\t\t\tValue: \"1\",\n\t\t})\n\n\t\tvar buf bytes.Buffer\n\t\tif err := format.Node(&buf, token.NewFileSet(), chanDeclCopy); err != nil {\n\t\t\treturn\n\t\t}\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Pos(),\n\t\t\tEnd:     call.End(),\n\t\t\tMessage: \"misuse of unbuffered os.Signal channel as argument to signal.Notify\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Change to buffer channel\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     chanDecl.Pos(),\n\t\t\t\t\tEnd:     chanDecl.End(),\n\t\t\t\t\tNewText: buf.Bytes(),\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t})\n\treturn nil, nil\n}\n\nfunc isSignalNotify(info *types.Info, call *ast.CallExpr) bool {\n\tcheck := func(id *ast.Ident) bool {\n\t\tobj := info.ObjectOf(id)\n\t\treturn obj.Name() == \"Notify\" && obj.Pkg().Path() == \"os/signal\"\n\t}\n\tswitch fun := call.Fun.(type) {\n\tcase *ast.SelectorExpr:\n\t\treturn check(fun.Sel)\n\tcase *ast.Ident:\n\t\tif fun, ok := findDecl(fun).(*ast.SelectorExpr); ok {\n\t\t\treturn check(fun.Sel)\n\t\t}\n\t\treturn false\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc findDecl(arg *ast.Ident) ast.Node {\n\tif arg.Obj == nil {\n\t\treturn nil\n\t}\n\tswitch as := arg.Obj.Decl.(type) {\n\tcase *ast.AssignStmt:\n\t\tif len(as.Lhs) != len(as.Rhs) {\n\t\t\treturn nil\n\t\t}\n\t\tfor i, lhs := range as.Lhs {\n\t\t\tlid, ok := lhs.(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif lid.Obj == arg.Obj {\n\t\t\t\treturn as.Rhs[i]\n\t\t\t}\n\t\t}\n\tcase *ast.ValueSpec:\n\t\tif len(as.Names) != len(as.Values) {\n\t\t\treturn nil\n\t\t}\n\t\tfor i, name := range as.Names {\n\t\t\tif name.Obj == arg.Obj {\n\t\t\t\treturn as.Values[i]\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc isBuiltinMake(info *types.Info, call *ast.CallExpr) bool {\n\ttypVal := info.Types[call.Fun]\n\tif !typVal.IsBuiltin() {\n\t\treturn false\n\t}\n\tswitch fun := call.Fun.(type) {\n\tcase *ast.Ident:\n\t\treturn info.ObjectOf(fun).Name() == \"make\"\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/sigchanyzer/sigchanyzer_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sigchanyzer_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/sigchanyzer\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, sigchanyzer.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/sigchanyzer/testdata/src/a/a.go",
    "content": "package p\n\nimport (\n\t\"os\"\n\tao \"os\"\n\t\"os/signal\"\n)\n\nvar c = make(chan os.Signal)\nvar d = make(chan os.Signal)\n\nfunc f() {\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, os.Interrupt) // ok\n\t_ = <-c\n}\n\nfunc g() {\n\tc := make(chan os.Signal)\n\tsignal.Notify(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n\t_ = <-c\n}\n\nfunc h() {\n\tc := make(chan ao.Signal)\n\tsignal.Notify(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n\t_ = <-c\n}\n\nfunc i() {\n\tsignal.Notify(d, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n}\n\nfunc j() {\n\tc := make(chan os.Signal)\n\tf := signal.Notify\n\tf(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n}\n\nfunc k() {\n\tsignal.Notify(make(chan os.Signal), os.Interrupt) // ok\n}\n\nfunc l() {\n\tsignal.Notify(make(chan os.Signal, 1), os.Interrupt) // ok\n}\n\nfunc m() {\n\tsignal.Notify(make(chan ao.Signal, 1), os.Interrupt) // ok\n}\n\nfunc n() {\n\tsignal.Notify(make(chan ao.Signal), os.Interrupt) // ok\n}\n"
  },
  {
    "path": "go/analysis/passes/sigchanyzer/testdata/src/a/a.go.golden",
    "content": "package p\n\nimport (\n\t\"os\"\n\tao \"os\"\n\t\"os/signal\"\n)\n\nvar c = make(chan os.Signal)\nvar d = make(chan os.Signal, 1)\n\nfunc f() {\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, os.Interrupt) // ok\n\t_ = <-c\n}\n\nfunc g() {\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n\t_ = <-c\n}\n\nfunc h() {\n\tc := make(chan ao.Signal, 1)\n\tsignal.Notify(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n\t_ = <-c\n}\n\nfunc i() {\n\tsignal.Notify(d, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n}\n\nfunc j() {\n\tc := make(chan os.Signal, 1)\n\tf := signal.Notify\n\tf(c, os.Interrupt) // want \"misuse of unbuffered os.Signal channel as argument to signal.Notify\"\n}\n\nfunc k() {\n\tsignal.Notify(make(chan os.Signal), os.Interrupt) // ok\n}\n\nfunc l() {\n\tsignal.Notify(make(chan os.Signal, 1), os.Interrupt) // ok\n}\n\nfunc m() {\n\tsignal.Notify(make(chan ao.Signal, 1), os.Interrupt) // ok\n}\n\nfunc n() {\n\tsignal.Notify(make(chan ao.Signal), os.Interrupt) // ok\n}\n"
  },
  {
    "path": "go/analysis/passes/slog/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package slog defines an Analyzer that checks for\n// mismatched key-value pairs in log/slog calls.\n//\n// # Analyzer slog\n//\n// slog: check for invalid structured logging calls\n//\n// The slog checker looks for calls to functions from the log/slog\n// package that take alternating key-value pairs. It reports calls\n// where an argument in a key position is neither a string nor a\n// slog.Attr, and where a final key is missing its value.\n// For example,it would report\n//\n//\tslog.Warn(\"message\", 11, \"k\") // slog.Warn arg \"11\" should be a string or a slog.Attr\n//\n// and\n//\n//\tslog.Info(\"message\", \"k1\", v1, \"k2\") // call to slog.Info missing a final value\npackage slog\n"
  },
  {
    "path": "go/analysis/passes/slog/slog.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// TODO(jba) deduce which functions wrap the log/slog functions, and use the\n// fact mechanism to propagate this information, so we can provide diagnostics\n// for user-supplied wrappers.\n\npackage slog\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"slog\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"slog\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nvar stringType = types.Universe.Lookup(\"string\").Type()\n\n// A position describes what is expected to appear in an argument position.\ntype position int\n\nconst (\n\t// key is an argument position that should hold a string key or an Attr.\n\tkey position = iota\n\t// value is an argument position that should hold a value.\n\tvalue\n\t// unknown represents that we do not know if position should hold a key or a value.\n\tunknown\n)\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tvar attrType types.Type // The type of slog.Attr\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tcall := node.(*ast.CallExpr)\n\t\tfn := typeutil.StaticCallee(pass.TypesInfo, call)\n\t\tif fn == nil {\n\t\t\treturn // not a static call\n\t\t}\n\t\tif call.Ellipsis != token.NoPos {\n\t\t\treturn // skip calls with \"...\" args\n\t\t}\n\t\tskipArgs, ok := kvFuncSkipArgs(fn)\n\t\tif !ok {\n\t\t\t// Not a slog function that takes key-value pairs.\n\t\t\treturn\n\t\t}\n\t\t// Here we know that fn.Pkg() is \"log/slog\".\n\t\tif attrType == nil {\n\t\t\tattrType = fn.Pkg().Scope().Lookup(\"Attr\").Type()\n\t\t}\n\n\t\tif isMethodExpr(pass.TypesInfo, call) {\n\t\t\t// Call is to a method value. Skip the first argument.\n\t\t\tskipArgs++\n\t\t}\n\t\tif len(call.Args) <= skipArgs {\n\t\t\t// Too few args; perhaps there are no k-v pairs.\n\t\t\treturn\n\t\t}\n\n\t\t// Check this call.\n\t\t// The first position should hold a key or Attr.\n\t\tpos := key\n\t\tvar unknownArg ast.Expr // nil or the last unknown argument\n\t\tfor _, arg := range call.Args[skipArgs:] {\n\t\t\tt := pass.TypesInfo.Types[arg].Type\n\t\t\tswitch pos {\n\t\t\tcase key:\n\t\t\t\t// Expect a string or Attr.\n\t\t\t\tswitch {\n\t\t\t\tcase t == stringType:\n\t\t\t\t\tpos = value\n\t\t\t\tcase isAttr(t):\n\t\t\t\t\tpos = key\n\t\t\t\tcase types.IsInterface(t):\n\t\t\t\t\t// As we do not do dataflow, we do not know what the dynamic type is.\n\t\t\t\t\t// But we might be able to learn enough to make a decision.\n\t\t\t\t\tif types.AssignableTo(stringType, t) {\n\t\t\t\t\t\t// t must be an empty interface. So it can also be an Attr.\n\t\t\t\t\t\t// We don't know enough to make an assumption.\n\t\t\t\t\t\tpos = unknown\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t} else if attrType != nil && types.AssignableTo(attrType, t) {\n\t\t\t\t\t\t// Assume it is an Attr.\n\t\t\t\t\t\tpos = key\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// Can't be either a string or Attr. Definitely an error.\n\t\t\t\t\tfallthrough\n\t\t\t\tdefault:\n\t\t\t\t\tif unknownArg == nil {\n\t\t\t\t\t\tpass.ReportRangef(arg, \"%s arg %q should be a string or a slog.Attr (possible missing key or value)\",\n\t\t\t\t\t\t\tshortName(fn), astutil.Format(pass.Fset, arg))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpass.ReportRangef(arg, \"%s arg %q should probably be a string or a slog.Attr (previous arg %q cannot be a key)\",\n\t\t\t\t\t\t\tshortName(fn), astutil.Format(pass.Fset, arg), astutil.Format(pass.Fset, unknownArg))\n\t\t\t\t\t}\n\t\t\t\t\t// Stop here so we report at most one missing key per call.\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\tcase value:\n\t\t\t\t// Anything can appear in this position.\n\t\t\t\t// The next position should be a key.\n\t\t\t\tpos = key\n\n\t\t\tcase unknown:\n\t\t\t\t// Once we encounter an unknown position, we can never be\n\t\t\t\t// sure if a problem later or at the end of the call is due to a\n\t\t\t\t// missing final value, or a non-key in key position.\n\t\t\t\t// In both cases, unknownArg != nil.\n\t\t\t\tunknownArg = arg\n\n\t\t\t\t// We don't know what is expected about this position, but all hope is not lost.\n\t\t\t\tif t != stringType && !isAttr(t) && !types.IsInterface(t) {\n\t\t\t\t\t// This argument is definitely not a key.\n\t\t\t\t\t//\n\t\t\t\t\t// unknownArg cannot have been a key, in which case this is the\n\t\t\t\t\t// corresponding value, and the next position should hold another key.\n\t\t\t\t\tpos = key\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif pos == value {\n\t\t\tif unknownArg == nil {\n\t\t\t\tpass.ReportRangef(call, \"call to %s missing a final value\", shortName(fn))\n\t\t\t} else {\n\t\t\t\tpass.ReportRangef(call, \"call to %s has a missing or misplaced value\", shortName(fn))\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\nfunc isAttr(t types.Type) bool {\n\treturn typesinternal.IsTypeNamed(t, \"log/slog\", \"Attr\")\n}\n\n// shortName returns a name for the function that is shorter than FullName.\n// Examples:\n//\n//\t\"slog.Info\" (instead of \"log/slog.Info\")\n//\t\"slog.Logger.With\" (instead of \"(*log/slog.Logger).With\")\nfunc shortName(fn *types.Func) string {\n\tvar r string\n\tif recv := fn.Signature().Recv(); recv != nil {\n\t\tif _, named := typesinternal.ReceiverNamed(recv); named != nil {\n\t\t\tr = named.Obj().Name()\n\t\t} else {\n\t\t\tr = recv.Type().String() // anon struct/interface\n\t\t}\n\t\tr += \".\"\n\t}\n\treturn fmt.Sprintf(\"%s.%s%s\", fn.Pkg().Name(), r, fn.Name())\n}\n\n// If fn is a slog function that has a ...any parameter for key-value pairs,\n// kvFuncSkipArgs returns the number of arguments to skip over to reach the\n// corresponding arguments, and true.\n// Otherwise it returns (0, false).\nfunc kvFuncSkipArgs(fn *types.Func) (int, bool) {\n\tif pkg := fn.Pkg(); pkg == nil || pkg.Path() != \"log/slog\" {\n\t\treturn 0, false\n\t}\n\tvar recvName string // by default a slog package function\n\tif recv := fn.Signature().Recv(); recv != nil {\n\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\tif named == nil {\n\t\t\treturn 0, false // anon struct/interface\n\t\t}\n\t\trecvName = named.Obj().Name()\n\t}\n\tskip, ok := kvFuncs[recvName][fn.Name()]\n\treturn skip, ok\n}\n\n// The names of functions and methods in log/slog that take\n// ...any for key-value pairs, mapped to the number of initial args to skip in\n// order to get to the ones that match the ...any parameter.\n// The first key is the dereferenced receiver type name, or \"\" for a function.\nvar kvFuncs = map[string]map[string]int{\n\t\"\": {\n\t\t\"Debug\":        1,\n\t\t\"Info\":         1,\n\t\t\"Warn\":         1,\n\t\t\"Error\":        1,\n\t\t\"DebugContext\": 2,\n\t\t\"InfoContext\":  2,\n\t\t\"WarnContext\":  2,\n\t\t\"ErrorContext\": 2,\n\t\t\"Log\":          3,\n\t\t\"Group\":        1,\n\t},\n\t\"Logger\": {\n\t\t\"Debug\":        1,\n\t\t\"Info\":         1,\n\t\t\"Warn\":         1,\n\t\t\"Error\":        1,\n\t\t\"DebugContext\": 2,\n\t\t\"InfoContext\":  2,\n\t\t\"WarnContext\":  2,\n\t\t\"ErrorContext\": 2,\n\t\t\"Log\":          3,\n\t\t\"With\":         0,\n\t},\n\t\"Record\": {\n\t\t\"Add\": 0,\n\t},\n}\n\n// isMethodExpr reports whether a call is to a MethodExpr.\nfunc isMethodExpr(info *types.Info, c *ast.CallExpr) bool {\n\ts, ok := c.Fun.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn false\n\t}\n\tsel := info.Selections[s]\n\treturn sel != nil && sel.Kind() == types.MethodExpr\n}\n"
  },
  {
    "path": "go/analysis/passes/slog/slog_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage slog\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, Analyzer, \"a\", \"b\")\n}\n"
  },
  {
    "path": "go/analysis/passes/slog/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the slog checker.\n\n//go:build go1.21\n\npackage a\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n)\n\nfunc F() {\n\tvar (\n\t\tl *slog.Logger\n\t\tr slog.Record\n\t)\n\n\t// Unrelated call.\n\tfmt.Println(\"ok\")\n\n\t// Valid calls.\n\tslog.Info(\"msg\")\n\tslog.Info(\"msg\", \"a\", 1)\n\tslog.Info(\"\", \"a\", 1, \"b\", \"two\")\n\tl.Debug(\"msg\", \"a\", 1)\n\tl.With(\"a\", 1)\n\tslog.Warn(\"msg\", slog.Int(\"a\", 1))\n\tslog.Warn(\"msg\", slog.Int(\"a\", 1), \"k\", 2)\n\tl.WarnContext(nil, \"msg\", \"a\", 1, slog.Int(\"b\", 2), slog.Int(\"c\", 3), \"d\", 4)\n\tl.DebugContext(nil, \"msg\", \"a\", 1, slog.Int(\"b\", 2), slog.Int(\"c\", 3), \"d\", 4, slog.Int(\"e\", 5))\n\tr.Add(\"a\", 1, \"b\", 2)\n\t(*slog.Logger).Debug(l, \"msg\", \"a\", 1, \"b\", 2)\n\n\tvar key string\n\tr.Add(key, 1)\n\n\t// bad\n\tslog.Info(\"msg\", 1)                        // want `slog.Info arg \"1\" should be a string or a slog.Attr`\n\tl.Info(\"msg\", 2)                           // want `slog.Logger.Info arg \"2\" should be a string or a slog.Attr`\n\tslog.Debug(\"msg\", \"a\")                     // want `call to slog.Debug missing a final value`\n\tslog.Warn(\"msg\", slog.Int(\"a\", 1), \"k\")    // want `call to slog.Warn missing a final value`\n\tslog.ErrorContext(nil, \"msg\", \"a\", 1, \"b\") // want `call to slog.ErrorContext missing a final value`\n\tr.Add(\"K\", \"v\", \"k\")                       // want `call to slog.Record.Add missing a final value`\n\tl.With(\"a\", \"b\", 2)                        // want `slog.Logger.With arg \"2\" should be a string or a slog.Attr`\n\n\t// Report the first problem if there are multiple bad keys.\n\tslog.Debug(\"msg\", \"a\", 1, 2, 3, 4) // want `slog.Debug arg \"2\" should be a string or a slog.Attr`\n\tslog.Debug(\"msg\", \"a\", 1, 2, 3, 4) // want `slog.Debug arg \"2\" should be a string or a slog.Attr`\n\n\tslog.Log(nil, slog.LevelWarn, \"msg\", \"a\", \"b\", 2) // want `slog.Log arg \"2\" should be a string or a slog.Attr`\n\n\t// Test method expression call.\n\t(*slog.Logger).Debug(l, \"msg\", \"a\", 1, 2, 3) // want `slog.Logger.Debug arg \"2\" should be a string or a slog.Attr`\n\n\t// Skip calls with spread args.\n\tvar args []any\n\tslog.Info(\"msg\", args...)\n\n\t// Report keys that are statically not exactly \"string\".\n\ttype MyString string\n\tmyKey := MyString(\"a\")  // any(x) looks like <MyString, \"a\">.\n\tslog.Info(\"\", myKey, 1) // want `slog.Info arg \"myKey\" should be a string or a slog.Attr`\n\n\t// The variadic part of all the calls below begins with an argument of\n\t// static type any, followed by an integer.\n\t// Even though the we don't know the dynamic type of the first arg, and thus\n\t// whether it is a key, an Attr, or something else, the fact that the\n\t// following integer arg cannot be a key allows us to assume that we should\n\t// expect a key to follow.\n\tvar a any = \"key\"\n\n\t// This is a valid call for which  we correctly produce no diagnostic.\n\tslog.Info(\"msg\", a, 7, \"key2\", 5)\n\n\t// This is an invalid call because the final value is missing, but we can't\n\t// be sure that's the reason.\n\tslog.Info(\"msg\", a, 7, \"key2\") // want `call to slog.Info has a missing or misplaced value`\n\n\t// Here our guess about the unknown arg (a) is wrong: we assume it's a string, but it's an Attr.\n\t// Therefore the second argument should be a key, but it is a number.\n\t// Ideally our diagnostic would pinpoint the problem, but we don't have enough information.\n\ta = slog.Int(\"a\", 1)\n\tslog.Info(\"msg\", a, 7, \"key2\") // want `call to slog.Info has a missing or misplaced value`\n\n\t// This call is invalid for the same reason as the one above, but we can't\n\t// detect that.\n\tslog.Info(\"msg\", a, 7, \"key2\", 5)\n\n\t// Another invalid call we can't detect. Here the first argument is wrong.\n\ta = 1\n\tslog.Info(\"msg\", a, 7, \"b\", 5)\n\n\t// We can detect the first case as the type of key is UntypedNil,\n\t// e.g. not yet assigned to any and not yet an interface.\n\t// We cannot detect the second.\n\tslog.Debug(\"msg\", nil, 2) // want `slog.Debug arg \"nil\" should be a string or a slog.Attr`\n\tslog.Debug(\"msg\", any(nil), 2)\n\n\t// Recovery from unknown value.\n\tslog.Debug(\"msg\", any(nil), \"a\")\n\tslog.Debug(\"msg\", any(nil), \"a\", 2)\n\tslog.Debug(\"msg\", any(nil), \"a\", 2, \"b\") // want `call to slog.Debug has a missing or misplaced value`\n\tslog.Debug(\"msg\", any(nil), 2, 3, 4)     // want \"slog.Debug arg \\\\\\\"3\\\\\\\" should probably be a string or a slog.Attr \\\\(previous arg \\\\\\\"2\\\\\\\" cannot be a key\\\\)\"\n\n\t// In these cases, an argument in key position is an interface, but we can glean useful information about it.\n\n\t// An error interface in key position is definitely invalid: it can't be a string\n\t// or slog.Attr.\n\tvar err error\n\tslog.Error(\"msg\", err) // want `slog.Error arg \"err\" should be a string or a slog.Attr`\n\n\t// slog.Attr implements fmt.Stringer, but string does not, so assume the arg is an Attr.\n\tvar stringer fmt.Stringer\n\tslog.Info(\"msg\", stringer, \"a\", 1)\n\tslog.Info(\"msg\", stringer, 1) // want `slog.Info arg \"1\" should be a string or a slog.Attr`\n}\n\nfunc All() {\n\t// Test all functions and methods at least once.\n\tvar (\n\t\tl   *slog.Logger\n\t\tr   slog.Record\n\t\tctx context.Context\n\t)\n\tslog.Debug(\"msg\", 1, 2) // want `slog.Debug arg \"1\" should be a string or a slog.Attr`\n\tslog.Error(\"msg\", 1, 2) // want `slog.Error arg \"1\" should be a string or a slog.Attr`\n\tslog.Info(\"msg\", 1, 2)  // want `slog.Info arg \"1\" should be a string or a slog.Attr`\n\tslog.Warn(\"msg\", 1, 2)  // want `slog.Warn arg \"1\" should be a string or a slog.Attr`\n\n\tslog.DebugContext(ctx, \"msg\", 1, 2) // want `slog.DebugContext arg \"1\" should be a string or a slog.Attr`\n\tslog.ErrorContext(ctx, \"msg\", 1, 2) // want `slog.ErrorContext arg \"1\" should be a string or a slog.Attr`\n\tslog.InfoContext(ctx, \"msg\", 1, 2)  // want `slog.InfoContext arg \"1\" should be a string or a slog.Attr`\n\tslog.WarnContext(ctx, \"msg\", 1, 2)  // want `slog.WarnContext arg \"1\" should be a string or a slog.Attr`\n\n\tslog.Log(ctx, slog.LevelDebug, \"msg\", 1, 2) // want `slog.Log arg \"1\" should be a string or a slog.Attr`\n\n\tl.Debug(\"msg\", 1, 2) // want `slog.Logger.Debug arg \"1\" should be a string or a slog.Attr`\n\tl.Error(\"msg\", 1, 2) // want `slog.Logger.Error arg \"1\" should be a string or a slog.Attr`\n\tl.Info(\"msg\", 1, 2)  // want `slog.Logger.Info arg \"1\" should be a string or a slog.Attr`\n\tl.Warn(\"msg\", 1, 2)  // want `slog.Logger.Warn arg \"1\" should be a string or a slog.Attr`\n\n\tl.DebugContext(ctx, \"msg\", 1, 2) // want `slog.Logger.DebugContext arg \"1\" should be a string or a slog.Attr`\n\tl.ErrorContext(ctx, \"msg\", 1, 2) // want `slog.Logger.ErrorContext arg \"1\" should be a string or a slog.Attr`\n\tl.InfoContext(ctx, \"msg\", 1, 2)  // want `slog.Logger.InfoContext arg \"1\" should be a string or a slog.Attr`\n\tl.WarnContext(ctx, \"msg\", 1, 2)  // want `slog.Logger.WarnContext arg \"1\" should be a string or a slog.Attr`\n\n\tl.Log(ctx, slog.LevelDebug, \"msg\", 1, 2) // want `slog.Logger.Log arg \"1\" should be a string or a slog.Attr`\n\n\t_ = l.With(1, 2) // want `slog.Logger.With arg \"1\" should be a string or a slog.Attr`\n\n\tr.Add(1, 2) // want `slog.Record.Add arg \"1\" should be a string or a slog.Attr`\n\n\t_ = slog.Group(\"key\", \"a\", 1, \"b\", 2)\n\t_ = slog.Group(\"key\", \"a\", 1, 2, 3) // want `slog.Group arg \"2\" should be a string or a slog.Attr`\n\n\tslog.Error(\"foo\", \"err\", errors.New(\"oops\")) // regression test for #61228.\n}\n\n// Used in tests by package b.\nvar MyLogger = slog.Default()\n"
  },
  {
    "path": "go/analysis/passes/slog/testdata/src/b/b.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the slog checker.\n\n//go:build go1.21\n\npackage b\n\nimport \"a\"\n\nfunc Imported() {\n\t_ = a.MyLogger.With(\"a\", 1, 2, 3) // want `slog.Logger.With arg \"2\" should be a string or a slog.Attr`\n}\n"
  },
  {
    "path": "go/analysis/passes/sortslice/analyzer.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sortslice defines an Analyzer that checks for calls\n// to sort.Slice that do not use a slice type as first argument.\npackage sortslice\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst Doc = `check the argument type of sort.Slice\n\nsort.Slice requires an argument of a slice type. Check that\nthe interface{} value passed to sort.Slice is actually a slice.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"sortslice\",\n\tDoc:      Doc,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sortslice\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"sort\") {\n\t\treturn nil, nil // doesn't directly import sort\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\tif !typesinternal.IsFunctionNamed(obj, \"sort\", \"Slice\", \"SliceStable\", \"SliceIsSorted\") {\n\t\t\treturn\n\t\t}\n\t\tcallee := obj.(*types.Func)\n\n\t\targ := call.Args[0]\n\t\ttyp := pass.TypesInfo.Types[arg].Type\n\n\t\tif tuple, ok := typ.(*types.Tuple); ok {\n\t\t\ttyp = tuple.At(0).Type() // special case for Slice(f(...))\n\t\t}\n\n\t\tswitch typ.Underlying().(type) {\n\t\tcase *types.Slice, *types.Interface:\n\t\t\treturn\n\t\t}\n\n\t\t// Restore typ to the original type, we may unwrap the tuple above,\n\t\t// typ might not be the type of arg.\n\t\ttyp = pass.TypesInfo.Types[arg].Type\n\n\t\tvar fixes []analysis.SuggestedFix\n\t\tswitch v := typ.Underlying().(type) {\n\t\tcase *types.Array:\n\t\t\tvar buf bytes.Buffer\n\t\t\tformat.Node(&buf, pass.Fset, &ast.SliceExpr{\n\t\t\t\tX:      arg,\n\t\t\t\tSlice3: false,\n\t\t\t\tLbrack: arg.End() + 1,\n\t\t\t\tRbrack: arg.End() + 3,\n\t\t\t})\n\t\t\tfixes = append(fixes, analysis.SuggestedFix{\n\t\t\t\tMessage: \"Get a slice of the full array\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     arg.Pos(),\n\t\t\t\t\tEnd:     arg.End(),\n\t\t\t\t\tNewText: buf.Bytes(),\n\t\t\t\t}},\n\t\t\t})\n\t\tcase *types.Pointer:\n\t\t\t_, ok := v.Elem().Underlying().(*types.Slice)\n\t\t\tif !ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvar buf bytes.Buffer\n\t\t\tformat.Node(&buf, pass.Fset, &ast.StarExpr{\n\t\t\t\tX: arg,\n\t\t\t})\n\t\t\tfixes = append(fixes, analysis.SuggestedFix{\n\t\t\t\tMessage: \"Dereference the pointer to the slice\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     arg.Pos(),\n\t\t\t\t\tEnd:     arg.End(),\n\t\t\t\t\tNewText: buf.Bytes(),\n\t\t\t\t}},\n\t\t\t})\n\t\tcase *types.Signature:\n\t\t\tif v.Params().Len() != 0 || v.Results().Len() != 1 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif _, ok := v.Results().At(0).Type().Underlying().(*types.Slice); !ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvar buf bytes.Buffer\n\t\t\tformat.Node(&buf, pass.Fset, &ast.CallExpr{\n\t\t\t\tFun: arg,\n\t\t\t})\n\t\t\tfixes = append(fixes, analysis.SuggestedFix{\n\t\t\t\tMessage: \"Call the function\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     arg.Pos(),\n\t\t\t\t\tEnd:     arg.End(),\n\t\t\t\t\tNewText: buf.Bytes(),\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:            call.Pos(),\n\t\t\tEnd:            call.End(),\n\t\t\tMessage:        fmt.Sprintf(\"%s's argument must be a slice; is called with %s\", callee.FullName(), typ.String()),\n\t\t\tSuggestedFixes: fixes,\n\t\t})\n\t})\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/sortslice/analyzer_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sortslice_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/sortslice\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, sortslice.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/sortslice/testdata/src/a/a.go",
    "content": "package a\n\nimport \"sort\"\n\n// IncorrectSort tries to sort an integer.\nfunc IncorrectSort() {\n\ti := 5\n\tsortFn := func(i, j int) bool { return false }\n\tsort.Slice(i, sortFn)         // want \"sort.Slice's argument must be a slice; is called with int\"\n\tsort.SliceStable(i, sortFn)   // want \"sort.SliceStable's argument must be a slice; is called with int\"\n\tsort.SliceIsSorted(i, sortFn) // want \"sort.SliceIsSorted's argument must be a slice; is called with int\"\n}\n\n// CorrectSort sorts integers. It should not produce a diagnostic.\nfunc CorrectSort() {\n\ts := []int{2, 3, 5, 6}\n\tsortFn := func(i, j int) bool { return s[i] < s[j] }\n\tsort.Slice(s, sortFn)\n\tsort.SliceStable(s, sortFn)\n\tsort.SliceIsSorted(s, sortFn)\n}\n\n// CorrectInterface sorts an interface with a slice\n// as the concrete type. It should not produce a diagnostic.\nfunc CorrectInterface() {\n\tvar s interface{}\n\ts = interface{}([]int{2, 1, 0})\n\tsortFn := func(i, j int) bool { return s.([]int)[i] < s.([]int)[j] }\n\tsort.Slice(s, sortFn)\n\tsort.SliceStable(s, sortFn)\n\tsort.SliceIsSorted(s, sortFn)\n}\n\ntype slicecompare interface {\n\tcompare(i, j int) bool\n}\n\ntype intslice []int\n\nfunc (s intslice) compare(i, j int) bool {\n\treturn s[i] < s[j]\n}\n\n// UnderlyingInterface sorts an interface with a slice\n// as the concrete type. It should not produce a diagnostic.\nfunc UnderlyingInterface() {\n\tvar s slicecompare\n\ts = intslice([]int{2, 1, 0})\n\tsort.Slice(s, s.compare)\n\tsort.SliceStable(s, s.compare)\n\tsort.SliceIsSorted(s, s.compare)\n}\n\ntype mySlice []int\n\n// UnderlyingSlice sorts a type with an underlying type of\n// slice of ints. It should not produce a diagnostic.\nfunc UnderlyingSlice() {\n\ts := mySlice{2, 3, 5, 6}\n\tsortFn := func(i, j int) bool { return s[i] < s[j] }\n\tsort.Slice(s, sortFn)\n\tsort.SliceStable(s, sortFn)\n\tsort.SliceIsSorted(s, sortFn)\n}\n\n// FunctionResultsAsArguments passes a function which returns two values\n// that satisfy sort.Slice signature. It should not produce a diagnostic.\nfunc FunctionResultsAsArguments() {\n\ts := []string{\"a\", \"z\", \"ooo\"}\n\tsort.Slice(less(s))\n\tsort.Slice(lessPtr(s)) // want `sort.Slice's argument must be a slice; is called with \\(\\*\\[\\]string,.*`\n}\n\nfunc less(s []string) ([]string, func(i, j int) bool) {\n\treturn s, func(i, j int) bool {\n\t\treturn s[i] < s[j]\n\t}\n}\n\nfunc lessPtr(s []string) (*[]string, func(i, j int) bool) {\n\treturn &s, func(i, j int) bool {\n\t\treturn s[i] < s[j]\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package stdmethods defines an Analyzer that checks for misspellings\n// in the signatures of methods similar to well-known interfaces.\n//\n// # Analyzer stdmethods\n//\n// stdmethods: check signature of methods of well-known interfaces\n//\n// Sometimes a type may be intended to satisfy an interface but may fail to\n// do so because of a mistake in its method signature.\n// For example, the result of this WriteTo method should be (int64, error),\n// not error, to satisfy io.WriterTo:\n//\n//\ttype myWriterTo struct{...}\n//\tfunc (myWriterTo) WriteTo(w io.Writer) error { ... }\n//\n// This check ensures that each method whose name matches one of several\n// well-known interface methods from the standard library has the correct\n// signature for that interface.\n//\n// Checked method names include:\n//\n//\tFormat GobEncode GobDecode MarshalJSON MarshalXML\n//\tPeek ReadByte ReadFrom ReadRune Scan Seek\n//\tUnmarshalJSON UnreadByte UnreadRune WriteByte\n//\tWriteTo\npackage stdmethods\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/stdmethods.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stdmethods\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"stdmethods\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"stdmethods\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\n// canonicalMethods lists the input and output types for Go methods\n// that are checked using dynamic interface checks. Because the\n// checks are dynamic, such methods would not cause a compile error\n// if they have the wrong signature: instead the dynamic check would\n// fail, sometimes mysteriously. If a method is found with a name listed\n// here but not the input/output types listed here, vet complains.\n//\n// A few of the canonical methods have very common names.\n// For example, a type might implement a Scan method that\n// has nothing to do with fmt.Scanner, but we still want to check\n// the methods that are intended to implement fmt.Scanner.\n// To do that, the arguments that have a = prefix are treated as\n// signals that the canonical meaning is intended: if a Scan\n// method doesn't have a fmt.ScanState as its first argument,\n// we let it go. But if it does have a fmt.ScanState, then the\n// rest has to match.\nvar canonicalMethods = map[string]struct{ args, results []string }{\n\t\"As\": {[]string{\"any\"}, []string{\"bool\"}}, // errors.As\n\t// \"Flush\": {{}, {\"error\"}}, // http.Flusher and jpeg.writer conflict\n\t\"Format\":        {[]string{\"=fmt.State\", \"rune\"}, []string{}},                      // fmt.Formatter\n\t\"GobDecode\":     {[]string{\"[]byte\"}, []string{\"error\"}},                           // gob.GobDecoder\n\t\"GobEncode\":     {[]string{}, []string{\"[]byte\", \"error\"}},                         // gob.GobEncoder\n\t\"Is\":            {[]string{\"error\"}, []string{\"bool\"}},                             // errors.Is\n\t\"MarshalJSON\":   {[]string{}, []string{\"[]byte\", \"error\"}},                         // json.Marshaler\n\t\"MarshalXML\":    {[]string{\"*xml.Encoder\", \"xml.StartElement\"}, []string{\"error\"}}, // xml.Marshaler\n\t\"ReadByte\":      {[]string{}, []string{\"byte\", \"error\"}},                           // io.ByteReader\n\t\"ReadFrom\":      {[]string{\"=io.Reader\"}, []string{\"int64\", \"error\"}},              // io.ReaderFrom\n\t\"ReadRune\":      {[]string{}, []string{\"rune\", \"int\", \"error\"}},                    // io.RuneReader\n\t\"Scan\":          {[]string{\"=fmt.ScanState\", \"rune\"}, []string{\"error\"}},           // fmt.Scanner\n\t\"Seek\":          {[]string{\"=int64\", \"int\"}, []string{\"int64\", \"error\"}},           // io.Seeker\n\t\"UnmarshalJSON\": {[]string{\"[]byte\"}, []string{\"error\"}},                           // json.Unmarshaler\n\t\"UnmarshalXML\":  {[]string{\"*xml.Decoder\", \"xml.StartElement\"}, []string{\"error\"}}, // xml.Unmarshaler\n\t\"UnreadByte\":    {[]string{}, []string{\"error\"}},\n\t\"UnreadRune\":    {[]string{}, []string{\"error\"}},\n\t\"Unwrap\":        {[]string{}, []string{\"error\"}},                      // errors.Unwrap\n\t\"WriteByte\":     {[]string{\"byte\"}, []string{\"error\"}},                // jpeg.writer (matching bufio.Writer)\n\t\"WriteTo\":       {[]string{\"=io.Writer\"}, []string{\"int64\", \"error\"}}, // io.WriterTo\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.InterfaceType)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif n.Recv != nil {\n\t\t\t\tcanonicalMethod(pass, n.Name)\n\t\t\t}\n\t\tcase *ast.InterfaceType:\n\t\t\tfor _, field := range n.Methods.List {\n\t\t\t\tfor _, id := range field.Names {\n\t\t\t\t\tcanonicalMethod(pass, id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\nfunc canonicalMethod(pass *analysis.Pass, id *ast.Ident) {\n\t// Expected input/output.\n\texpect, ok := canonicalMethods[id.Name]\n\tif !ok {\n\t\treturn\n\t}\n\n\t// Actual input/output\n\tsign := pass.TypesInfo.Defs[id].Type().(*types.Signature)\n\targs := sign.Params()\n\tresults := sign.Results()\n\n\t// Special case: WriteTo with more than one argument,\n\t// not trying at all to implement io.WriterTo,\n\t// comes up often enough to skip.\n\tif id.Name == \"WriteTo\" && args.Len() > 1 {\n\t\treturn\n\t}\n\n\t// Special case: Is, As and Unwrap only apply when type\n\t// implements error.\n\tif id.Name == \"Is\" || id.Name == \"As\" || id.Name == \"Unwrap\" {\n\t\tif recv := sign.Recv(); recv == nil || !implementsError(recv.Type()) {\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Special case: Unwrap has two possible signatures.\n\t// Check for Unwrap() []error here.\n\tif id.Name == \"Unwrap\" {\n\t\tif args.Len() == 0 && results.Len() == 1 {\n\t\t\tt := typeString(results.At(0).Type())\n\t\t\tif t == \"error\" || t == \"[]error\" {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tpass.ReportRangef(id, \"method Unwrap() should have signature Unwrap() error or Unwrap() []error\")\n\t\treturn\n\t}\n\n\t// Do the =s (if any) all match?\n\tif !matchParams(expect.args, args, \"=\") || !matchParams(expect.results, results, \"=\") {\n\t\treturn\n\t}\n\n\t// Everything must match.\n\tif !matchParams(expect.args, args, \"\") || !matchParams(expect.results, results, \"\") {\n\t\texpectFmt := id.Name + \"(\" + argjoin(expect.args) + \")\"\n\t\tif len(expect.results) == 1 {\n\t\t\texpectFmt += \" \" + argjoin(expect.results)\n\t\t} else if len(expect.results) > 1 {\n\t\t\texpectFmt += \" (\" + argjoin(expect.results) + \")\"\n\t\t}\n\n\t\tactual := typeString(sign)\n\t\tactual = strings.TrimPrefix(actual, \"func\")\n\t\tactual = id.Name + actual\n\n\t\tpass.ReportRangef(id, \"method %s should have signature %s\", actual, expectFmt)\n\t}\n}\n\nfunc typeString(typ types.Type) string {\n\treturn types.TypeString(typ, (*types.Package).Name)\n}\n\nfunc argjoin(x []string) string {\n\ty := make([]string, len(x))\n\tfor i, s := range x {\n\t\tif s[0] == '=' {\n\t\t\ts = s[1:]\n\t\t}\n\t\ty[i] = s\n\t}\n\treturn strings.Join(y, \", \")\n}\n\n// Does each type in expect with the given prefix match the corresponding type in actual?\nfunc matchParams(expect []string, actual *types.Tuple, prefix string) bool {\n\tfor i, x := range expect {\n\t\tif !strings.HasPrefix(x, prefix) {\n\t\t\tcontinue\n\t\t}\n\t\tif i >= actual.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif !matchParamType(x, actual.At(i).Type()) {\n\t\t\treturn false\n\t\t}\n\t}\n\tif prefix == \"\" && actual.Len() > len(expect) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// Does this one type match?\nfunc matchParamType(expect string, actual types.Type) bool {\n\texpect = strings.TrimPrefix(expect, \"=\")\n\t// Overkill but easy.\n\tt := typeString(actual)\n\treturn t == expect ||\n\t\t(t == \"any\" || t == \"interface{}\") && (expect == \"any\" || expect == \"interface{}\")\n}\n\nvar errorType = types.Universe.Lookup(\"error\").Type().Underlying().(*types.Interface)\n\nfunc implementsError(actual types.Type) bool {\n\treturn types.Implements(actual, errorType)\n}\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/stdmethods_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stdmethods_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/stdmethods\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, stdmethods.Analyzer, \"a\", \"typeparams\")\n}\n\nfunc TestAnalyzeEncodingXML(t *testing.T) {\n\tanalysistest.Run(t, \"\", stdmethods.Analyzer, \"encoding/xml\")\n}\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/testdata/src/a/a.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n)\n\ntype T int\n\nfunc (T) Scan(x fmt.ScanState, c byte) {} // want `should have signature Scan\\(fmt\\.ScanState, rune\\) error`\n\nfunc (T) Format(fmt.State, byte) {} // want `should have signature Format\\(fmt.State, rune\\)`\n\ntype U int\n\nfunc (U) Format(byte) {} // no error: first parameter must be fmt.State to trigger check\n\nfunc (U) GobDecode() {} // want `should have signature GobDecode\\(\\[\\]byte\\) error`\n\n// Test rendering of type names such as xml.Encoder in diagnostic.\nfunc (U) MarshalXML(*xml.Encoder) {} // want `method MarshalXML\\(\\*xml.Encoder\\) should...`\n\nfunc (U) UnmarshalXML(*xml.Decoder, xml.StartElement) error { // no error: signature matches xml.Unmarshaler\n\treturn nil\n}\n\nfunc (U) WriteTo(w io.Writer) {} // want `method WriteTo\\(w io.Writer\\) should have signature WriteTo\\(io.Writer\\) \\(int64, error\\)`\n\nfunc (T) WriteTo(w io.Writer, more, args int) {} // ok - clearly not io.WriterTo\n\ntype I interface {\n\tReadByte() byte // want `should have signature ReadByte\\(\\) \\(byte, error\\)`\n}\n\ntype V int // V does not implement error.\n\nfunc (V) As() T       { return 0 }     // ok - V is not an error\nfunc (V) Is() bool    { return false } // ok - V is not an error\nfunc (V) Unwrap() int { return 0 }     // ok - V is not an error\n\ntype E int\n\nfunc (E) Error() string { return \"\" } // E implements error.\n\nfunc (E) As()     {} // want `method As\\(\\) should have signature As\\((any|interface\\{\\})\\) bool`\nfunc (E) Is()     {} // want `method Is\\(\\) should have signature Is\\(error\\) bool`\nfunc (E) Unwrap() {} // want `method Unwrap\\(\\) should have signature Unwrap\\(\\) error or Unwrap\\(\\) \\[\\]error`\n\ntype F int\n\nfunc (F) Error() string { return \"\" } // Both F and *F implement error.\n\nfunc (*F) As()     {} // want `method As\\(\\) should have signature As\\((any|interface\\{\\})\\) bool`\nfunc (*F) Is()     {} // want `method Is\\(\\) should have signature Is\\(error\\) bool`\nfunc (*F) Unwrap() {} // want `method Unwrap\\(\\) should have signature Unwrap\\(\\) error or Unwrap\\(\\) \\[\\]error`\n\ntype G int\n\nfunc (G) As(interface{}) bool // ok\n\ntype W int\n\nfunc (W) Error() string { return \"\" }\nfunc (W) Unwrap() error { return nil } // ok\n\ntype M int\n\nfunc (M) Error() string   { return \"\" }\nfunc (M) Unwrap() []error { return nil } // ok\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/testdata/src/a/b.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\ntype H int\n\nfunc (H) As(any) bool // ok\n"
  },
  {
    "path": "go/analysis/passes/stdmethods/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"fmt\"\n\ntype T[P any] int\n\nfunc (T[_]) Scan(x fmt.ScanState, c byte) {} // want `should have signature Scan\\(fmt\\.ScanState, rune\\) error`\n\nfunc (T[_]) Format(fmt.State, byte) {} // want `should have signature Format\\(fmt.State, rune\\)`\n\ntype U[P any] int\n\nfunc (U[_]) Format(byte) {} // no error: first parameter must be fmt.State to trigger check\n\nfunc (U[P]) GobDecode(P) {} // want `should have signature GobDecode\\(\\[\\]byte\\) error`\n\ntype V[P any] int // V does not implement error.\n\nfunc (V[_]) As() T[int]  { return 0 }     // ok - V is not an error\nfunc (V[_]) Is() bool    { return false } // ok - V is not an error\nfunc (V[_]) Unwrap() int { return 0 }     // ok - V is not an error\n\ntype E[P any] int\n\nfunc (E[_]) Error() string { return \"\" } // E implements error.\n\nfunc (E[P]) As()     {} // want `method As\\(\\) should have signature As\\((any|interface\\{\\})\\) bool`\nfunc (E[_]) Is()     {} // want `method Is\\(\\) should have signature Is\\(error\\) bool`\nfunc (E[_]) Unwrap() {} // want `method Unwrap\\(\\) should have signature Unwrap\\(\\) error or Unwrap\\(\\) \\[\\]error`\n\ntype F[P any] int\n\nfunc (F[_]) Error() string { return \"\" } // Both F and *F implement error.\n\nfunc (*F[_]) As()     {} // want `method As\\(\\) should have signature As\\((any|interface\\{\\})\\) bool`\nfunc (*F[_]) Is()     {} // want `method Is\\(\\) should have signature Is\\(error\\) bool`\nfunc (*F[_]) Unwrap() {} // want `method Unwrap\\(\\) should have signature Unwrap\\(\\) error or Unwrap\\(\\) \\[\\]error`\n"
  },
  {
    "path": "go/analysis/passes/stdversion/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/stdversion\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(stdversion.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/stdversion/stdversion.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package stdversion reports uses of standard library symbols that are\n// \"too new\" for the Go version in force in the referring file.\npackage stdversion\n\nimport (\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/types\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nconst Doc = `report uses of too-new standard library symbols\n\nThe stdversion analyzer reports references to symbols in the standard\nlibrary that were introduced by a Go release higher than the one in\nforce in the referring file. (Recall that the file's Go version is\ndefined by the 'go' directive its module's go.mod file, or by a\n\"//go:build go1.X\" build tag at the top of the file.)\n\nThe analyzer does not report a diagnostic for a reference to a \"too\nnew\" field or method of a type that is itself \"too new\", as this may\nhave false positives, for example if fields or methods are accessed\nthrough a type alias that is guarded by a Go version constraint.\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"stdversion\",\n\tDoc:              Doc,\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion\",\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Prior to go1.22, versions.FileVersion returns only the\n\t// toolchain version, which is of no use to us, so\n\t// disable this analyzer on earlier versions.\n\tif !slices.Contains(build.Default.ReleaseTags, \"go1.22\") {\n\t\treturn nil, nil\n\t}\n\n\t// Don't report diagnostics for modules marked before go1.21,\n\t// since at that time the go directive wasn't clearly\n\t// specified as a toolchain requirement.\n\tpkgVersion := pass.Pkg.GoVersion()\n\tif !versions.AtLeast(pkgVersion, \"go1.21\") {\n\t\treturn nil, nil\n\t}\n\n\t// disallowedSymbols returns the set of standard library symbols\n\t// in a given package that are disallowed at the specified Go version.\n\ttype key struct {\n\t\tpkg     *types.Package\n\t\tversion string\n\t}\n\tmemo := make(map[key]map[types.Object]string) // records symbol's minimum Go version\n\tdisallowedSymbols := func(pkg *types.Package, version string) map[types.Object]string {\n\t\tk := key{pkg, version}\n\t\tdisallowed, ok := memo[k]\n\t\tif !ok {\n\t\t\tdisallowed = typesinternal.TooNewStdSymbols(pkg, version)\n\t\t\tmemo[k] = disallowed\n\t\t}\n\t\treturn disallowed\n\t}\n\n\t// Scan the syntax looking for references to symbols\n\t// that are disallowed by the version of the file.\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.File)(nil),\n\t\t(*ast.Ident)(nil),\n\t}\n\tvar fileVersion string // \"\" => no check\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.File:\n\t\t\tif ast.IsGenerated(n) {\n\t\t\t\t// Suppress diagnostics in generated files (such as cgo).\n\t\t\t\tfileVersion = \"\"\n\t\t\t} else {\n\t\t\t\tfileVersion = versions.Lang(versions.FileVersion(pass.TypesInfo, n))\n\t\t\t\t// (may be \"\" if unknown)\n\t\t\t}\n\n\t\tcase *ast.Ident:\n\t\t\tif fileVersion != \"\" {\n\t\t\t\tif obj, ok := pass.TypesInfo.Uses[n]; ok && obj.Pkg() != nil {\n\t\t\t\t\tdisallowed := disallowedSymbols(obj.Pkg(), fileVersion)\n\t\t\t\t\tif minVersion, ok := disallowed[origin(obj)]; ok {\n\t\t\t\t\t\t// Some symbols are accessible before their release but\n\t\t\t\t\t\t// only with specific build tags unknown to us here.\n\t\t\t\t\t\t// Avoid false positives in such cases.\n\t\t\t\t\t\t// TODO(mkalil): move this check into typesinternal.TooNewStdSymbols.\n\t\t\t\t\t\tif obj.Pkg().Path() == \"testing/synctest\" && versions.AtLeast(fileVersion, \"go1.24\") {\n\t\t\t\t\t\t\tbreak // requires go1.24 && goexperiment.synctest || go1.25\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnoun := \"module\"\n\t\t\t\t\t\tif fileVersion != pkgVersion {\n\t\t\t\t\t\t\tnoun = \"file\"\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpass.ReportRangef(n, \"%s.%s requires %v or later (%s is %s)\",\n\t\t\t\t\t\t\tobj.Pkg().Name(), obj.Name(), minVersion, noun, fileVersion)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// origin returns the original uninstantiated symbol for obj.\nfunc origin(obj types.Object) types.Object {\n\tswitch obj := obj.(type) {\n\tcase *types.Var:\n\t\treturn obj.Origin()\n\tcase *types.Func:\n\t\treturn obj.Origin()\n\tcase *types.TypeName:\n\t\tif named, ok := obj.Type().(*types.Named); ok { // (don't unalias)\n\t\t\treturn named.Origin().Obj()\n\t\t}\n\t}\n\treturn obj\n}\n"
  },
  {
    "path": "go/analysis/passes/stdversion/stdversion_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stdversion_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/stdversion\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc Test(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23) // TODO(#68658): Waiting on 1.22 backport.\n\n\t// The test relies on go1.21 std symbols, but the analyzer\n\t// itself requires the go1.22 implementation of versions.FileVersions.\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"test.txtar\"))\n\tanalysistest.Run(t, dir, stdversion.Analyzer,\n\t\t\"example.com/basic\",\n\t\t\"example.com/despite\",\n\t\t\"example.com/mod20\",\n\t\t\"example.com/mod21\",\n\t\t\"example.com/mod22\",\n\t\t\"example.com/old\",\n\t)\n}\n"
  },
  {
    "path": "go/analysis/passes/stdversion/testdata/test.txtar",
    "content": "Test of \"too new\" diagnostics from the stdversion analyzer.\n\nThis test references go1.21 and go1.22 symbols from std.\n\nSee also gopls/internal/test/marker/testdata/diagnostics/stdversion.txt\nwhich runs the same test within the gopls analysis driver, to ensure\ncoverage of per-file Go version support.\n\n-- go.work --\ngo 1.22\n\nuse .\nuse mod20\nuse mod21\nuse mod22\nuse old\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- basic/basic.go --\n// File version is 1.21.\npackage basic\n\nimport \"go/types\"\n\nfunc _() {\n\t// old package-level type\n\tvar _ types.Info // ok: defined by go1.0\n\n\t// new field of older type\n\t_ = new(types.Info).FileVersions // want `types.FileVersions requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new method of older type\n\tnew(types.Info).PkgNameOf // want `types.PkgNameOf requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new package-level type\n\tvar a types.Alias // want `types.Alias requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new method of new type\n\ta.Underlying() // no diagnostic\n}\n\n-- despite/errors.go --\n// File version is 1.21.\n\n// Check that RunDespiteErrors is enabled.\npackage ignore\n\nimport \"go/types\"\n\nfunc _() {\n\t// report something before the syntax error.\n\t_ = new(types.Info).FileVersions // want `types.FileVersions requires go1.22 or later \\(module is go1.21\\)`\n}\n\ninvalid syntax // exercise RunDespiteErrors\n\n-- mod20/go.mod --\nmodule example.com/mod20\n\ngo 1.20\n\n-- mod20/notag.go --\n// The 1.20 module is before the forward compatibility regime:\n// The file's build tag effects selection, but\n// not language semantics, so stdversion is silent.\n\npackage mod20\n\nimport \"go/types\"\n\nfunc _() {\n\tvar _ types.Alias\n}\n\n-- mod20/tag16.go --\n// The 1.20 module is before the forward compatibility regime:\n// The file's build tag effects selection, but\n// not language semantics, so stdversion is silent.\n\n//go:build go1.16\n\npackage mod20\n\nimport \"bytes\"\nimport \"go/types\"\n\nvar _ = bytes.Clone\nvar _ = types.Alias\n\n-- mod20/tag22.go --\n// The 1.20 module is before the forward compatibility regime:\n// The file's build tag effects selection, but\n// not language semantics, so stdversion is silent.\n\n//go:build go1.22\n\npackage mod20\n\nimport \"bytes\"\nimport \"go/types\"\n\nvar _ = bytes.Clone\nvar _ = types.Alias\n\n-- mod21/go.mod --\nmodule example.com/mod21\n\ngo 1.21\n\n-- mod21/notag.go --\n// File version is 1.21.\npackage mod21\n\nimport \"go/types\"\n\nfunc _() {\n\t// old package-level type\n\tvar _ types.Info // ok: defined by go1.0\n\n\t// new field of older type\n\t_ = new(types.Info).FileVersions // want `types.FileVersions requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new method of older type\n\tnew(types.Info).PkgNameOf // want `types.PkgNameOf requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new package-level type\n\tvar a types.Alias // want `types.Alias requires go1.22 or later \\(module is go1.21\\)`\n\n\t// new method of new type\n\ta.Underlying() // no diagnostic\n}\n\n-- mod21/tag16.go --\n// File version is 1.21.\n//\n// The module is within the forward compatibility regime so\n// the build tag (1.16) can modify the file version, but it cannot\n// go below the 1.21 \"event horizon\" (#68658).\n\n//go:build go1.16\n\npackage mod21\n\nimport \"bytes\"\nimport \"go/types\"\n\nvar _ = bytes.Clone\nvar _ = types.Alias // want `types.Alias requires go1.22 or later \\(module is go1.21\\)`\n\n-- mod21/tag22.go --\n// File version is 1.22.\n//\n// The module is within the forward compatibility regime so\n// the build tag (1.22) updates the file version to 1.22.\n\n//go:build go1.22\n\npackage mod21\n\nimport \"bytes\"\nimport \"go/types\"\n\nvar _ = bytes.Clone\nvar _ = types.Alias \n\n-- mod22/go.mod --\nmodule example.com/mod22\n\ngo 1.22\n\n-- mod22/notag.go --\n// File version is 1.22.\npackage mod22\n\nimport \"go/types\"\n\nfunc _() {\n\tvar _ = bytes.Clone\n\tvar _ = types.Alias\n}\n\n-- mod22/tag16.go --\n// File version is 1.21.\n//\n// The module is within the forward compatibility regime so\n// the build tag (1.16) can modify the file version, but it cannot\n// go below the 1.21 \"event horizon\" (#68658).\n\n//go:build go1.16\n\npackage mod22\n\nimport \"bytes\"\nimport \"go/types\"\n\nvar _ = bytes.Clone\nvar _ = types.Alias // want `types.Alias requires go1.22 or later \\(file is go1.21\\)`\n\n-- old/go.mod --\nmodule example.com/old\n\ngo 1.5\n\n-- old/notag.go --\npackage old\n\nimport \"go/types\"\n\nvar _ types.Alias // no diagnostic: go.mod is too old for us to care\n\n-- old/tag21.go --\n// The build tag is ignored due to the module version.\n\n//go:build go1.21\n\npackage old\n\nimport \"go/types\"\n\nvar _ = types.Alias // no diagnostic: go.mod is too old for us to care\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/cmd/stringintconv/main.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The stringintconv command runs the stringintconv analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/stringintconv\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(stringintconv.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package stringintconv defines an Analyzer that flags type conversions\n// from integers to strings.\n//\n// # Analyzer stringintconv\n//\n// stringintconv: check for string(int) conversions\n//\n// This checker flags conversions of the form string(x) where x is an integer\n// (but not byte or rune) type. Such conversions are discouraged because they\n// return the UTF-8 representation of the Unicode code point x, and not a decimal\n// string representation of x as one might expect. Furthermore, if x denotes an\n// invalid code point, the conversion cannot be statically rejected.\n//\n// For conversions that intend on using the code point, consider replacing them\n// with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the\n// string representation of the value in the desired base.\npackage stringintconv\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/string.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stringintconv\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"stringintconv\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"stringintconv\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\n// describe returns a string describing the type typ contained within the type\n// set of inType. If non-empty, inName is used as the name of inType (this is\n// necessary so that we can use alias type names that may not be reachable from\n// inType itself).\nfunc describe(typ, inType types.Type, inName string) string {\n\tname := inName\n\tif typ != inType {\n\t\tname = typeName(typ)\n\t}\n\tif name == \"\" {\n\t\treturn \"\"\n\t}\n\n\tvar parentheticals []string\n\tif underName := typeName(typ.Underlying()); underName != \"\" && underName != name {\n\t\tparentheticals = append(parentheticals, underName)\n\t}\n\n\tif typ != inType && inName != \"\" && inName != name {\n\t\tparentheticals = append(parentheticals, \"in \"+inName)\n\t}\n\n\tif len(parentheticals) > 0 {\n\t\tname += \" (\" + strings.Join(parentheticals, \", \") + \")\"\n\t}\n\n\treturn name\n}\n\nfunc typeName(t types.Type) string {\n\tif basic, ok := t.(*types.Basic); ok {\n\t\treturn basic.Name() // may be (e.g.) \"untyped int\", which has no TypeName\n\t}\n\tif tname := typesinternal.TypeNameFor(t); tname != nil {\n\t\treturn tname.Name()\n\t}\n\treturn \"\"\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.File)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tvar file *ast.File\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tif n, ok := n.(*ast.File); ok {\n\t\t\tfile = n\n\t\t\treturn\n\t\t}\n\t\tcall := n.(*ast.CallExpr)\n\n\t\tif len(call.Args) != 1 {\n\t\t\treturn\n\t\t}\n\t\targ := call.Args[0]\n\n\t\t// Retrieve target type name.\n\t\tvar tname *types.TypeName\n\t\tswitch fun := call.Fun.(type) {\n\t\tcase *ast.Ident:\n\t\t\ttname, _ = pass.TypesInfo.Uses[fun].(*types.TypeName)\n\t\tcase *ast.SelectorExpr:\n\t\t\ttname, _ = pass.TypesInfo.Uses[fun.Sel].(*types.TypeName)\n\t\t}\n\t\tif tname == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// In the conversion T(v) of a value v of type V to a target type T, we\n\t\t// look for types T0 in the type set of T and V0 in the type set of V, such\n\t\t// that V0->T0 is a problematic conversion. If T and V are not type\n\t\t// parameters, this amounts to just checking if V->T is a problematic\n\t\t// conversion.\n\n\t\t// First, find a type T0 in T that has an underlying type of string.\n\t\tT := tname.Type()\n\t\tttypes, err := structuralTypes(T)\n\t\tif err != nil {\n\t\t\treturn // invalid type\n\t\t}\n\n\t\tvar T0 types.Type // string type in the type set of T\n\n\t\tfor _, tt := range ttypes {\n\t\t\tu, _ := tt.Underlying().(*types.Basic)\n\t\t\tif u != nil && u.Kind() == types.String {\n\t\t\t\tT0 = tt\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif T0 == nil {\n\t\t\t// No target types have an underlying type of string.\n\t\t\treturn\n\t\t}\n\n\t\t// Next, find a type V0 in V that has an underlying integral type that is\n\t\t// not byte or rune.\n\t\tV := pass.TypesInfo.TypeOf(arg)\n\t\tvtypes, err := structuralTypes(V)\n\t\tif err != nil {\n\t\t\treturn // invalid type\n\t\t}\n\n\t\tvar V0 types.Type // integral type in the type set of V\n\n\t\tfor _, vt := range vtypes {\n\t\t\tu, _ := vt.Underlying().(*types.Basic)\n\t\t\tif u != nil && u.Info()&types.IsInteger != 0 {\n\t\t\t\tswitch u.Kind() {\n\t\t\t\tcase types.Byte, types.Rune, types.UntypedRune:\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tV0 = vt\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif V0 == nil {\n\t\t\t// No source types are non-byte or rune integer types.\n\t\t\treturn\n\t\t}\n\n\t\tconvertibleToRune := true // if true, we can suggest a fix\n\t\tfor _, t := range vtypes {\n\t\t\tif !types.ConvertibleTo(t, types.Typ[types.Rune]) {\n\t\t\t\tconvertibleToRune = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\ttarget := describe(T0, T, tname.Name())\n\t\tsource := describe(V0, V, typeName(V))\n\n\t\tif target == \"\" || source == \"\" {\n\t\t\treturn // something went wrong\n\t\t}\n\n\t\tdiag := analysis.Diagnostic{\n\t\t\tPos:     n.Pos(),\n\t\t\tMessage: fmt.Sprintf(\"conversion from %s to %s yields a string of one rune, not a string of digits\", source, target),\n\t\t}\n\t\taddFix := func(message string, edits []analysis.TextEdit) {\n\t\t\tdiag.SuggestedFixes = append(diag.SuggestedFixes, analysis.SuggestedFix{\n\t\t\t\tMessage:   message,\n\t\t\t\tTextEdits: edits,\n\t\t\t})\n\t\t}\n\n\t\t// Fix 1: use fmt.Sprint(x)\n\t\t//\n\t\t// Prefer fmt.Sprint over strconv.Itoa, FormatInt,\n\t\t// or FormatUint, as it works for any type.\n\t\t// Add an import of \"fmt\" as needed.\n\t\t//\n\t\t// Unless the type is exactly string, we must retain the conversion.\n\t\t//\n\t\t// Do not offer this fix if type parameters are involved,\n\t\t// as there are too many combinations and subtleties.\n\t\t// Consider x = rune | int16 | []byte: in all cases,\n\t\t// string(x) is legal, but the appropriate diagnostic\n\t\t// and fix differs. Similarly, don't offer the fix if\n\t\t// the type has methods, as some {String,GoString,Format}\n\t\t// may change the behavior of fmt.Sprint.\n\t\tif len(ttypes) == 1 && len(vtypes) == 1 && types.NewMethodSet(V0).Len() == 0 {\n\t\t\tprefix, importEdits := refactor.AddImport(pass.TypesInfo, file, \"fmt\", \"fmt\", \"Sprint\", arg.Pos())\n\t\t\tif types.Identical(T0, types.Typ[types.String]) {\n\t\t\t\t// string(x) -> fmt.Sprint(x)\n\t\t\t\taddFix(\"Format the number as a decimal\", append(importEdits,\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\tPos:     call.Fun.Pos(),\n\t\t\t\t\t\tEnd:     call.Fun.End(),\n\t\t\t\t\t\tNewText: []byte(prefix + \"Sprint\"),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\t// mystring(x) -> mystring(fmt.Sprint(x))\n\t\t\t\taddFix(\"Format the number as a decimal\", append(importEdits,\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\tPos:     call.Lparen + 1,\n\t\t\t\t\t\tEnd:     call.Lparen + 1,\n\t\t\t\t\t\tNewText: []byte(prefix + \"Sprint(\"),\n\t\t\t\t\t},\n\t\t\t\t\tanalysis.TextEdit{\n\t\t\t\t\t\tPos:     call.Rparen,\n\t\t\t\t\t\tEnd:     call.Rparen,\n\t\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Fix 2: use string(rune(x))\n\t\tif convertibleToRune {\n\t\t\taddFix(\"Convert a single rune to a string\", []analysis.TextEdit{\n\t\t\t\t{\n\t\t\t\t\tPos:     arg.Pos(),\n\t\t\t\t\tEnd:     arg.Pos(),\n\t\t\t\t\tNewText: []byte(\"rune(\"),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos:     arg.End(),\n\t\t\t\t\tEnd:     arg.End(),\n\t\t\t\t\tNewText: []byte(\")\"),\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\tpass.Report(diag)\n\t})\n\treturn nil, nil\n}\n\nfunc structuralTypes(t types.Type) ([]types.Type, error) {\n\tvar structuralTypes []types.Type\n\tif tp, ok := types.Unalias(t).(*types.TypeParam); ok {\n\t\tterms, err := typeparams.StructuralTerms(tp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, term := range terms {\n\t\t\tstructuralTypes = append(structuralTypes, term.Type())\n\t\t}\n\t} else {\n\t\tstructuralTypes = append(structuralTypes, t)\n\t}\n\treturn structuralTypes, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/string_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stringintconv_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/stringintconv\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, stringintconv.Analyzer, \"a\", \"typeparams\")\n\tanalysistest.RunWithSuggestedFixes(t, testdata, stringintconv.Analyzer, \"fix\")\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the stringintconv checker.\n\npackage a\n\ntype A string\n\ntype B = string\n\ntype C int\n\ntype D = uintptr\n\nfunc StringTest() {\n\tvar (\n\t\ti int\n\t\tj rune\n\t\tk byte\n\t\tl C\n\t\tm D\n\t\tn = []int{0, 1, 2}\n\t\to struct{ x int }\n\t)\n\tconst p = 0\n\t// First time only, assert the complete message:\n\t_ = string(i) // want `^conversion from int to string yields a string of one rune, not a string of digits$`\n\t_ = string(j)\n\t_ = string(k)\n\t_ = string(p)    // want `...from untyped int to string...`\n\t_ = A(l)         // want `...from C \\(int\\) to A \\(string\\)...`\n\t_ = B(m)         // want `...from (uintptr|D \\(uintptr\\)) to B \\(string\\)...`\n\t_ = string(n[1]) // want `...from int to string...`\n\t_ = string(o.x)  // want `...from int to string...`\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fix.go",
    "content": "package fix\n\nfunc _(x uint64) {\n\tprintln(string(x)) // want `conversion from uint64 to string yields...`\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fix.go.golden",
    "content": "-- Format the number as a decimal --\npackage fix\n\nimport \"fmt\"\n\nfunc _(x uint64) {\n     println(fmt.Sprint(x)) // want `conversion from uint64 to string yields...`\n}\n\n-- Convert a single rune to a string --\npackage fix\n\nfunc _(x uint64) {\n     println(string(rune(x))) // want `conversion from uint64 to string yields...`\n}\n\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fixdot.go",
    "content": "package fix\n\nimport . \"fmt\"\n\nfunc _(x uint64) {\n\tPrintln(string(x)) // want `conversion from uint64 to string yields...`\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fixdot.go.golden",
    "content": "-- Format the number as a decimal --\npackage fix\n\nimport . \"fmt\"\n\nfunc _(x uint64) {\n     Println(Sprint(x)) // want `conversion from uint64 to string yields...`\n}\n\n-- Convert a single rune to a string --\npackage fix\n\nimport . \"fmt\"\n\nfunc _(x uint64) {\n     Println(string(rune(x))) // want `conversion from uint64 to string yields...`\n}\n\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fixnamed.go",
    "content": "package fix\n\ntype mystring string\n\nfunc _(x int16) mystring {\n\treturn mystring(x) // want `conversion from int16 to mystring \\(string\\)...`\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/fix/fixnamed.go.golden",
    "content": "-- Format the number as a decimal --\npackage fix\n\nimport \"fmt\"\n\ntype mystring string\n\nfunc _(x int16) mystring {\n\treturn mystring(fmt.Sprint(x)) // want `conversion from int16 to mystring \\(string\\)...`\n}\n\n-- Convert a single rune to a string --\npackage fix\n\ntype mystring string\n\nfunc _(x int16) mystring {\n\treturn mystring(rune(x)) // want `conversion from int16 to mystring \\(string\\)...`\n}\n"
  },
  {
    "path": "go/analysis/passes/stringintconv/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\ntype (\n\tInt     int\n\tUintptr = uintptr\n\tString  string\n)\n\nfunc _[AllString ~string, MaybeString ~string | ~int, NotString ~int | byte, NamedString String | Int]() {\n\tvar (\n\t\ti int\n\t\tr rune\n\t\tb byte\n\t\tI Int\n\t\tU uintptr\n\t\tM MaybeString\n\t\tN NotString\n\t)\n\tconst p = 0\n\n\t_ = MaybeString(i) // want `conversion from int to string .in MaybeString. yields a string of one rune, not a string of digits`\n\t_ = MaybeString(r)\n\t_ = MaybeString(b)\n\t_ = MaybeString(I) // want `conversion from Int .int. to string .in MaybeString. yields a string of one rune, not a string of digits`\n\t_ = MaybeString(U) // want `conversion from uintptr to string .in MaybeString. yields a string of one rune, not a string of digits`\n\t// Type parameters are never constant types, so arguments are always\n\t// converted to their default type (int versus untyped int, in this case)\n\t_ = MaybeString(p) // want `conversion from int to string .in MaybeString. yields a string of one rune, not a string of digits`\n\t// ...even if the type parameter is only strings.\n\t_ = AllString(p) // want `conversion from int to string .in AllString. yields a string of one rune, not a string of digits`\n\n\t_ = NotString(i)\n\t_ = NotString(r)\n\t_ = NotString(b)\n\t_ = NotString(I)\n\t_ = NotString(U)\n\t_ = NotString(p)\n\n\t_ = NamedString(i) // want `conversion from int to String .string, in NamedString. yields a string of one rune, not a string of digits`\n\t_ = string(M)      // want `conversion from int .in MaybeString. to string yields a string of one rune, not a string of digits`\n\n\t// Note that M is not convertible to rune.\n\t_ = MaybeString(M) // want `conversion from int .in MaybeString. to string .in MaybeString. yields a string of one rune, not a string of digits`\n\t_ = NotString(N)   // ok\n}\n"
  },
  {
    "path": "go/analysis/passes/structtag/structtag.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package structtag defines an Analyzer that checks struct field tags\n// are well formed.\npackage structtag\n\nimport (\n\t\"errors\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"fmt\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\nconst Doc = `check that struct field tags conform to reflect.StructTag.Get\n\nAlso report certain struct tags (json, xml) used with unexported fields.`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"structtag\",\n\tDoc:              Doc,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/structtag\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.StructType)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tstyp, ok := pass.TypesInfo.Types[n.(*ast.StructType)].Type.(*types.Struct)\n\t\t// Type information may be incomplete.\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tvar seen namesSeen\n\t\tfor i := 0; i < styp.NumFields(); i++ {\n\t\t\tfield := styp.Field(i)\n\t\t\ttag := styp.Tag(i)\n\t\t\tcheckCanonicalFieldTag(pass, field, tag, &seen)\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// namesSeen keeps track of encoding tags by their key, name, and nested level\n// from the initial struct. The level is taken into account because equal\n// encoding key names only conflict when at the same level; otherwise, the lower\n// level shadows the higher level.\ntype namesSeen map[uniqueName]token.Pos\n\ntype uniqueName struct {\n\tkey   string // \"xml\" or \"json\"\n\tname  string // the encoding name\n\tlevel int    // anonymous struct nesting level\n}\n\nfunc (s *namesSeen) Get(key, name string, level int) (token.Pos, bool) {\n\tif *s == nil {\n\t\t*s = make(map[uniqueName]token.Pos)\n\t}\n\tpos, ok := (*s)[uniqueName{key, name, level}]\n\treturn pos, ok\n}\n\nfunc (s *namesSeen) Set(key, name string, level int, pos token.Pos) {\n\tif *s == nil {\n\t\t*s = make(map[uniqueName]token.Pos)\n\t}\n\t(*s)[uniqueName{key, name, level}] = pos\n}\n\nvar checkTagDups = []string{\"json\", \"xml\"}\nvar checkTagSpaces = map[string]bool{\"json\": true, \"xml\": true, \"asn1\": true}\n\n// checkCanonicalFieldTag checks a single struct field tag.\nfunc checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, seen *namesSeen) {\n\tif strings.HasPrefix(pass.Pkg.Path(), \"encoding/\") {\n\t\t// These packages know how to use their own APIs.\n\t\t// Sometimes they are testing what happens to incorrect programs.\n\t\treturn\n\t}\n\n\tfor _, key := range checkTagDups {\n\t\tcheckTagDuplicates(pass, tag, key, field, field, seen, 1)\n\t}\n\n\tif err := validateStructTag(tag); err != nil {\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     field.Pos(),\n\t\t\tEnd:     field.Pos() + token.Pos(len(field.Name())),\n\t\t\tMessage: fmt.Sprintf(\"struct field tag %#q not compatible with reflect.StructTag.Get: %s\", tag, err),\n\t\t})\n\t}\n\n\t// Check for use of json or xml tags with unexported fields.\n\n\t// Embedded struct. Nothing to do for now, but that\n\t// may change, depending on what happens with issue 7363.\n\t// TODO(adonovan): investigate, now that issue is fixed.\n\tif field.Anonymous() {\n\t\treturn\n\t}\n\n\tif field.Exported() {\n\t\treturn\n\t}\n\n\tfor _, enc := range [...]string{\"json\", \"xml\"} {\n\t\tswitch reflect.StructTag(tag).Get(enc) {\n\t\t// Ignore warning if the field not exported and the tag is marked as\n\t\t// ignored.\n\t\tcase \"\", \"-\":\n\t\tdefault:\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     field.Pos(),\n\t\t\t\tEnd:     field.Pos() + token.Pos(len(field.Name())),\n\t\t\t\tMessage: fmt.Sprintf(\"struct field %s has %s tag but is not exported\", field.Name(), enc),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// checkTagDuplicates checks a single struct field tag to see if any tags are\n// duplicated. nearest is the field that's closest to the field being checked,\n// while still being part of the top-level struct type.\nfunc checkTagDuplicates(pass *analysis.Pass, tag, key string, nearest, field *types.Var, seen *namesSeen, level int) {\n\tval := reflect.StructTag(tag).Get(key)\n\tif val == \"-\" {\n\t\t// Ignored, even if the field is anonymous.\n\t\treturn\n\t}\n\tif val == \"\" || val[0] == ',' {\n\t\tif !field.Anonymous() {\n\t\t\t// Ignored if the field isn't anonymous.\n\t\t\treturn\n\t\t}\n\t\ttyp, ok := field.Type().Underlying().(*types.Struct)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tfor i := 0; i < typ.NumFields(); i++ {\n\t\t\tfield := typ.Field(i)\n\t\t\tif !field.Exported() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttag := typ.Tag(i)\n\t\t\tcheckTagDuplicates(pass, tag, key, nearest, field, seen, level+1)\n\t\t}\n\t\treturn\n\t}\n\tif key == \"xml\" && field.Name() == \"XMLName\" {\n\t\t// XMLName defines the XML element name of the struct being\n\t\t// checked. That name cannot collide with element or attribute\n\t\t// names defined on other fields of the struct. Vet does not have a\n\t\t// check for untagged fields of type struct defining their own name\n\t\t// by containing a field named XMLName; see issue 18256.\n\t\treturn\n\t}\n\tif i := strings.Index(val, \",\"); i >= 0 {\n\t\tif key == \"xml\" {\n\t\t\t// Use a separate namespace for XML attributes.\n\t\t\tif slices.Contains(strings.Split(val[i:], \",\"), \"attr\") {\n\t\t\t\tkey += \" attribute\" // Key is part of the error message.\n\t\t\t}\n\t\t}\n\t\tval = val[:i]\n\t}\n\tif pos, ok := seen.Get(key, val, level); ok {\n\t\talsoPos := pass.Fset.Position(pos)\n\t\talsoPos.Column = 0\n\n\t\t// Make the \"also at\" position relative to the current position,\n\t\t// to ensure that all warnings are unambiguous and correct. For\n\t\t// example, via anonymous struct fields, it's possible for the\n\t\t// two fields to be in different packages and directories.\n\t\tthisPos := pass.Fset.Position(field.Pos())\n\t\trel, err := filepath.Rel(filepath.Dir(thisPos.Filename), alsoPos.Filename)\n\t\tif err != nil {\n\t\t\t// Possibly because the paths are relative; leave the\n\t\t\t// filename alone.\n\t\t} else {\n\t\t\talsoPos.Filename = rel\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     nearest.Pos(),\n\t\t\tEnd:     nearest.Pos() + token.Pos(len(nearest.Name())),\n\t\t\tMessage: fmt.Sprintf(\"struct field %s repeats %s tag %q also at %s\", field.Name(), key, val, alsoPos),\n\t\t})\n\t} else {\n\t\tseen.Set(key, val, level, field.Pos())\n\t}\n}\n\nvar (\n\terrTagSyntax      = errors.New(\"bad syntax for struct tag pair\")\n\terrTagKeySyntax   = errors.New(\"bad syntax for struct tag key\")\n\terrTagValueSyntax = errors.New(\"bad syntax for struct tag value\")\n\terrTagValueSpace  = errors.New(\"suspicious space in struct tag value\")\n\terrTagSpace       = errors.New(\"key:\\\"value\\\" pairs not separated by spaces\")\n)\n\n// validateStructTag parses the struct tag and returns an error if it is not\n// in the canonical format, which is a space-separated list of key:\"value\"\n// settings. The value may contain spaces.\nfunc validateStructTag(tag string) error {\n\t// This code is based on the StructTag.Get code in package reflect.\n\n\tn := 0\n\tfor ; tag != \"\"; n++ {\n\t\tif n > 0 && tag != \"\" && tag[0] != ' ' {\n\t\t\t// More restrictive than reflect, but catches likely mistakes\n\t\t\t// like `x:\"foo\",y:\"bar\"`, which parses as `x:\"foo\" ,y:\"bar\"` with second key \",y\".\n\t\t\treturn errTagSpace\n\t\t}\n\t\t// Skip leading space.\n\t\ti := 0\n\t\tfor i < len(tag) && tag[i] == ' ' {\n\t\t\ti++\n\t\t}\n\t\ttag = tag[i:]\n\t\tif tag == \"\" {\n\t\t\tbreak\n\t\t}\n\n\t\t// Scan to colon. A space, a quote or a control character is a syntax error.\n\t\t// Strictly speaking, control chars include the range [0x7f, 0x9f], not just\n\t\t// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters\n\t\t// as it is simpler to inspect the tag's bytes than the tag's runes.\n\t\ti = 0\n\t\tfor i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '\"' && tag[i] != 0x7f {\n\t\t\ti++\n\t\t}\n\t\tif i == 0 {\n\t\t\treturn errTagKeySyntax\n\t\t}\n\t\tif i+1 >= len(tag) || tag[i] != ':' {\n\t\t\treturn errTagSyntax\n\t\t}\n\t\tif tag[i+1] != '\"' {\n\t\t\treturn errTagValueSyntax\n\t\t}\n\t\tkey := tag[:i]\n\t\ttag = tag[i+1:]\n\n\t\t// Scan quoted string to find value.\n\t\ti = 1\n\t\tfor i < len(tag) && tag[i] != '\"' {\n\t\t\tif tag[i] == '\\\\' {\n\t\t\t\ti++\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tif i >= len(tag) {\n\t\t\treturn errTagValueSyntax\n\t\t}\n\t\tqvalue := tag[:i+1]\n\t\ttag = tag[i+1:]\n\n\t\tvalue, err := strconv.Unquote(qvalue)\n\t\tif err != nil {\n\t\t\treturn errTagValueSyntax\n\t\t}\n\n\t\tif !checkTagSpaces[key] {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch key {\n\t\tcase \"xml\":\n\t\t\t// If the first or last character in the XML tag is a space, it is\n\t\t\t// suspicious.\n\t\t\tif strings.Trim(value, \" \") != value {\n\t\t\t\treturn errTagValueSpace\n\t\t\t}\n\n\t\t\t// If there are multiple spaces, they are suspicious.\n\t\t\tif strings.Count(value, \" \") > 1 {\n\t\t\t\treturn errTagValueSpace\n\t\t\t}\n\n\t\t\t// If there is no comma, skip the rest of the checks.\n\t\t\tcomma := strings.IndexRune(value, ',')\n\t\t\tif comma < 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If the character before a comma is a space, this is suspicious.\n\t\t\tif comma > 0 && value[comma-1] == ' ' {\n\t\t\t\treturn errTagValueSpace\n\t\t\t}\n\t\t\tvalue = value[comma+1:]\n\t\tcase \"json\":\n\t\t\t// JSON allows using spaces in the name, so skip it.\n\t\t\tcomma := strings.IndexRune(value, ',')\n\t\t\tif comma < 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue = value[comma+1:]\n\t\t}\n\n\t\tif strings.IndexByte(value, ' ') >= 0 {\n\t\t\treturn errTagValueSpace\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "go/analysis/passes/structtag/structtag_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage structtag_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/structtag\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, structtag.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/structtag/testdata/src/a/a.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains the test for canonical struct tags.\n\npackage a\n\nimport (\n\t\"a/b\"\n\t\"encoding/xml\"\n)\n\ntype StructTagTest struct {\n\tA   int \"hello\"            // want \"`hello` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair\"\n\tB   int \"\\tx:\\\"y\\\"\"        // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag key\"\n\tC   int \"x:\\\"y\\\"\\tx:\\\"y\\\"\" // want \"not compatible with reflect.StructTag.Get\"\n\tD   int \"x:`y`\"            // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag value\"\n\tE   int \"ct\\brl:\\\"char\\\"\"  // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag pair\"\n\tF   int `:\"emptykey\"`      // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag key\"\n\tG   int `x:\"noEndQuote`    // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag value\"\n\tH   int `x:\"trunc\\x0\"`     // want \"not compatible with reflect.StructTag.Get: bad syntax for struct tag value\"\n\tI   int `x:\"foo\",y:\"bar\"`  // want \"not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces\"\n\tJ   int `x:\"foo\"y:\"bar\"`   // want \"not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces\"\n\tOK0 int `x:\"y\" u:\"v\" w:\"\"`\n\tOK1 int `x:\"y:z\" u:\"v\" w:\"\"` // note multiple colons.\n\tOK2 int \"k0:\\\"values contain spaces\\\" k1:\\\"literal\\ttabs\\\" k2:\\\"and\\\\tescaped\\\\tabs\\\"\"\n\tOK3 int `under_scores:\"and\" CAPS:\"ARE_OK\"`\n}\n\ntype UnexportedEncodingTagTest struct {\n\tx int `json:\"xx\"` // want \"struct field x has json tag but is not exported\"\n\ty int `xml:\"yy\"`  // want \"struct field y has xml tag but is not exported\"\n\tz int\n\tA int `json:\"aa\" xml:\"bb\"`\n\tb int `json:\"-\"`\n\tC int `json:\"-\"`\n}\n\ntype unexp struct{}\n\ntype JSONEmbeddedField struct {\n\tUnexportedEncodingTagTest `is:\"embedded\"`\n\tunexp                     `is:\"embedded,notexported\" json:\"unexp\"` // OK for now, see issue 7363\n}\n\ntype AnonymousJSON struct{}\ntype AnonymousXML struct{}\n\ntype AnonymousJSONField struct {\n\tDuplicateAnonJSON int `json:\"a\"`\n\n\tA int \"hello\" // want \"`hello` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair\"\n}\n\n// With different names to allow using as anonymous fields multiple times.\n\ntype AnonymousJSONField2 struct {\n\tDuplicateAnonJSON int `json:\"a\"`\n}\ntype AnonymousJSONField3 struct {\n\tDuplicateAnonJSON int `json:\"a\"`\n}\n\ntype DuplicateJSONFields struct {\n\tJSON              int `json:\"a\"`\n\tDuplicateJSON     int `json:\"a\"` // want \"struct field DuplicateJSON repeats json tag .a. also at a.go:66\"\n\tIgnoredJSON       int `json:\"-\"`\n\tOtherIgnoredJSON  int `json:\"-\"`\n\tOmitJSON          int `json:\",omitempty\"`\n\tOtherOmitJSON     int `json:\",omitempty\"`\n\tDuplicateOmitJSON int `json:\"a,omitempty\"` // want \"struct field DuplicateOmitJSON repeats json tag .a. also at a.go:66\"\n\tNonJSON           int `foo:\"a\"`\n\tDuplicateNonJSON  int `foo:\"a\"`\n\tEmbedded          struct {\n\t\tDuplicateJSON int `json:\"a\"` // OK because it's not in the same struct type\n\t}\n\tAnonymousJSON `json:\"a\"` // want \"struct field AnonymousJSON repeats json tag .a. also at a.go:66\"\n\n\tXML              int `xml:\"a\"`\n\tDuplicateXML     int `xml:\"a\"` // want \"struct field DuplicateXML repeats xml tag .a. also at a.go:80\"\n\tIgnoredXML       int `xml:\"-\"`\n\tOtherIgnoredXML  int `xml:\"-\"`\n\tOmitXML          int `xml:\",omitempty\"`\n\tOtherOmitXML     int `xml:\",omitempty\"`\n\tDuplicateOmitXML int `xml:\"a,omitempty\"` // want \"struct field DuplicateOmitXML repeats xml tag .a. also at a.go:80\"\n\tNonXML           int `foo:\"a\"`\n\tDuplicateNonXML  int `foo:\"a\"`\n\tEmbedded2        struct {\n\t\tDuplicateXML int `xml:\"a\"` // OK because it's not in the same struct type\n\t}\n\tAnonymousXML `xml:\"a\"` // want \"struct field AnonymousXML repeats xml tag .a. also at a.go:80\"\n\tAttribute    struct {\n\t\tXMLName     xml.Name `xml:\"b\"`\n\t\tNoDup       int      `xml:\"b\"`                // OK because XMLName above affects enclosing struct.\n\t\tAttr        int      `xml:\"b,attr\"`           // OK because <b b=\"0\"><b>0</b></b> is valid.\n\t\tDupAttr     int      `xml:\"b,attr\"`           // want \"struct field DupAttr repeats xml attribute tag .b. also at a.go:96\"\n\t\tDupOmitAttr int      `xml:\"b,omitempty,attr\"` // want \"struct field DupOmitAttr repeats xml attribute tag .b. also at a.go:96\"\n\n\t\tAnonymousXML `xml:\"b,attr\"` // want \"struct field AnonymousXML repeats xml attribute tag .b. also at a.go:96\"\n\t}\n\n\tAnonymousJSONField2 `json:\"not_anon\"` // ok; fields aren't embedded in JSON\n\tAnonymousJSONField3 `json:\"-\"`        // ok; entire field is ignored in JSON\n}\n\ntype UnexpectedSpacetest struct {\n\tA int `json:\"a,omitempty\"`\n\tB int `json:\"b, omitempty\"` // want \"suspicious space in struct tag value\"\n\tC int `json:\"c ,omitempty\"`\n\tD int `json:\"d,omitempty, string\"` // want \"suspicious space in struct tag value\"\n\tE int `xml:\"e local\"`\n\tF int `xml:\"f \"`                 // want \"suspicious space in struct tag value\"\n\tG int `xml:\" g\"`                 // want \"suspicious space in struct tag value\"\n\tH int `xml:\"h ,omitempty\"`       // want \"suspicious space in struct tag value\"\n\tI int `xml:\"i, omitempty\"`       // want \"suspicious space in struct tag value\"\n\tJ int `xml:\"j local ,omitempty\"` // want \"suspicious space in struct tag value\"\n\tK int `xml:\"k local, omitempty\"` // want \"suspicious space in struct tag value\"\n\tL int `xml:\" l local,omitempty\"` // want \"suspicious space in struct tag value\"\n\tM int `xml:\"m  local,omitempty\"` // want \"suspicious space in struct tag value\"\n\tN int `xml:\" \"`                  // want \"suspicious space in struct tag value\"\n\tO int `xml:\"\"`\n\tP int `xml:\",\"`\n\tQ int `foo:\" doesn't care \"`\n}\n\n// Nested fields can be shadowed by fields further up. For example,\n// ShadowingAnonJSON replaces the json:\"a\" field in AnonymousJSONField.\n// However, if the two conflicting fields appear at the same level like in\n// DuplicateWithAnotherPackage, we should error.\n\ntype ShadowingJsonFieldName struct {\n\tAnonymousJSONField\n\tShadowingAnonJSON int `json:\"a\"`\n}\n\ntype DuplicateWithAnotherPackage struct {\n\tb.AnonymousJSONField\n\tAnonymousJSONField2 // want \"struct field DuplicateAnonJSON repeats json tag .a. also at b.b.go:8\"\n}\n"
  },
  {
    "path": "go/analysis/passes/structtag/testdata/src/a/b/b.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage b\n\ntype AnonymousJSONField struct {\n\tDuplicateAnonJSON int `json:\"a\"`\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package testinggoroutine defines an Analyzerfor detecting calls to\n// Fatal from a test goroutine.\n//\n// # Analyzer testinggoroutine\n//\n// testinggoroutine: report calls to (*testing.T).Fatal from goroutines started by a test\n//\n// Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and\n// Skip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.\n// This checker detects calls to these functions that occur within a goroutine\n// started by the test. For example:\n//\n//\tfunc TestFoo(t *testing.T) {\n//\t    go func() {\n//\t        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n//\t    }()\n//\t}\npackage testinggoroutine\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"log\"\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc TestBadFatalf(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < 2; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tt.Fatalf(\"TestFailed: id = %v\\n\", id) // want \"call to .+T.+Fatalf from a non-test goroutine\"\n\t\t}(i)\n\t}\n}\n\nfunc TestOKErrorf(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < 2; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tt.Errorf(\"TestFailed: id = %v\\n\", id)\n\t\t}(i)\n\t}\n}\n\nfunc TestBadFatal(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < 2; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tt.Fatal(\"TestFailed\") // want \"call to .+T.+Fatal from a non-test goroutine\"\n\t\t}(i)\n\t}\n}\n\nfunc f(t *testing.T, _ string) {\n\tt.Fatal(\"TestFailed\")\n}\n\nfunc g() {}\n\nfunc TestBadFatalIssue47470(t *testing.T) {\n\tgo f(t, \"failed test 1\") // want \"call to .+T.+Fatal from a non-test goroutine\"\n\n\tg := func(t *testing.T, _ string) {\n\t\tt.Fatal(\"TestFailed\")\n\t}\n\tgo g(t, \"failed test 2\") // want \"call to .+T.+Fatal from a non-test goroutine\"\n}\n\nfunc BenchmarkBadFatalf(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < b.N; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tb.Fatalf(\"TestFailed: id = %v\\n\", id) // want \"call to .+B.+Fatalf from a non-test goroutine\"\n\t\t}(i)\n\t}\n}\n\nfunc BenchmarkBadFatal(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < b.N; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tb.Fatal(\"TestFailed\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t\t}(i)\n\t}\n}\n\nfunc BenchmarkOKErrorf(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < b.N; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer wg.Done()\n\t\t\tb.Errorf(\"TestFailed: %d\", i)\n\t\t}(i)\n\t}\n}\n\nfunc BenchmarkBadFatalGoGo(b *testing.B) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < b.N; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tgo func() {\n\t\t\t\tdefer wg.Done()\n\t\t\t\tb.Fatal(\"TestFailed\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t\t\t}()\n\t\t}(i)\n\t}\n\n\tif false {\n\t\tdefer b.Fatal(\"here\")\n\t}\n\n\tif true {\n\t\tgo func() {\n\t\t\tb.Fatal(\"in here\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t\t}()\n\t}\n\n\tfunc() {\n\t\tfunc() {\n\t\t\tfunc() {\n\t\t\t\tfunc() {\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tb.Fatal(\"Here\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t\t\t\t\t}()\n\t\t\t\t}()\n\t\t\t}()\n\t\t}()\n\t}()\n\n\t_ = 10 * 10\n\t_ = func() bool {\n\t\tgo b.Fatal(\"Failed\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t\treturn true\n\t}\n\n\tdefer func() {\n\t\tgo b.Fatal(\"Here\") // want \"call to .+B.+Fatal from a non-test goroutine\"\n\t}()\n}\n\nfunc BenchmarkBadSkip(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tif i == 100 {\n\t\t\tgo b.Skip(\"Skipping\") // want \"call to .+B.+Skip from a non-test goroutine\"\n\t\t}\n\t\tif i == 22 {\n\t\t\tgo func() {\n\t\t\t\tgo func() {\n\t\t\t\t\tb.Skip(\"Skipping now\") // want \"call to .+B.+Skip from a non-test goroutine\"\n\t\t\t\t}()\n\t\t\t}()\n\t\t}\n\t}\n}\n\nfunc TestBadSkip(t *testing.T) {\n\tfor i := 0; i < 1000; i++ {\n\t\tif i == 100 {\n\t\t\tgo t.Skip(\"Skipping\") // want \"call to .+T.+Skip from a non-test goroutine\"\n\t\t}\n\t\tif i == 22 {\n\t\t\tgo func() {\n\t\t\t\tgo func() {\n\t\t\t\t\tt.Skip(\"Skipping now\") // want \"call to .+T.+Skip from a non-test goroutine\"\n\t\t\t\t}()\n\t\t\t}()\n\t\t}\n\t}\n}\n\nfunc BenchmarkBadFailNow(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tif i == 100 {\n\t\t\tgo b.FailNow() // want \"call to .+B.+FailNow from a non-test goroutine\"\n\t\t}\n\t\tif i == 22 {\n\t\t\tgo func() {\n\t\t\t\tgo func() {\n\t\t\t\t\tb.FailNow() // want \"call to .+B.+FailNow from a non-test goroutine\"\n\t\t\t\t}()\n\t\t\t}()\n\t\t}\n\t}\n}\n\nfunc TestBadFailNow(t *testing.T) {\n\tfor i := 0; i < 1000; i++ {\n\t\tif i == 100 {\n\t\t\tgo t.FailNow() // want \"call to .+T.+FailNow from a non-test goroutine\"\n\t\t}\n\t\tif i == 22 {\n\t\t\tgo func() {\n\t\t\t\tgo func() {\n\t\t\t\t\tt.FailNow() // want \"call to .+T.+FailNow from a non-test goroutine\"\n\t\t\t\t}()\n\t\t\t}()\n\t\t}\n\t}\n}\n\nfunc TestBadWithLoopCond(ty *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < 10; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tdefer ty.Fatalf(\"Why\") // want \"call to .+T.+Fatalf from a non-test goroutine\"\n\t\t\tgo func() {\n\t\t\t\tfor j := 0; j < 2; ty.FailNow() { // want \"call to .+T.+FailNow from\"\n\t\t\t\t\tj++\n\t\t\t\t\tty.Errorf(\"Done here\")\n\t\t\t\t}\n\t\t\t}()\n\t\t}(i)\n\t}\n}\n\ntype customType int\n\nfunc (ct *customType) Fatalf(fmtSpec string, args ...interface{}) {\n\tif fmtSpec == \"\" {\n\t\tpanic(\"empty format specifier\")\n\t}\n}\n\nfunc (ct *customType) FailNow() {}\nfunc (ct *customType) Skip()    {}\n\nfunc TestWithLogFatalf(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tfor i := 0; i < 10; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tgo func() {\n\t\t\t\tfor j := 0; j < 2; j++ {\n\t\t\t\t\tlog.Fatal(\"Done here\")\n\t\t\t\t}\n\t\t\t}()\n\t\t}(i)\n\t}\n}\n\nfunc TestWithCustomType(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tdefer wg.Wait()\n\n\tct := new(customType)\n\tdefer ct.FailNow()\n\tdefer ct.Skip()\n\n\tfor i := 0; i < 10; i++ {\n\t\twg.Add(1)\n\t\tgo func(id int) {\n\t\t\tgo func() {\n\t\t\t\tfor j := 0; j < 2; j++ {\n\t\t\t\t\tct.Fatalf(\"Done here: %d\", i)\n\t\t\t\t}\n\t\t\t}()\n\t\t}(i)\n\t}\n}\n\nfunc helpTB(tb testing.TB) {\n\ttb.FailNow()\n}\n\nfunc TestTB(t *testing.T) {\n\tgo helpTB(t) // want \"call to .+TB.+FailNow from a non-test goroutine\"\n}\n\nfunc TestIssue48124(t *testing.T) {\n\tgo helper(t) // want \"call to .+T.+Skip from a non-test goroutine\"\n}\n\nfunc TestEachCall(t *testing.T) {\n\tgo helper(t) // want \"call to .+T.+Skip from a non-test goroutine\"\n\tgo helper(t) // want \"call to .+T.+Skip from a non-test goroutine\"\n}\n\nfunc TestWithSubtest(t *testing.T) {\n\tt.Run(\"name\", func(t2 *testing.T) {\n\t\tt.FailNow() // want \"call to .+T.+FailNow on t defined outside of the subtest\"\n\t\tt2.Fatal()\n\t})\n\n\tf := func(t3 *testing.T) {\n\t\tt.FailNow()\n\t\tt3.Fatal()\n\t}\n\tt.Run(\"name\", f) // want \"call to .+T.+FailNow on t defined outside of the subtest\"\n\n\tg := func(t4 *testing.T) {\n\t\tt.FailNow()\n\t\tt4.Fatal()\n\t}\n\tg(t)\n\n\tt.Run(\"name\", helper)\n\n\tgo t.Run(\"name\", func(t2 *testing.T) {\n\t\tt.FailNow() // want \"call to .+T.+FailNow on t defined outside of the subtest\"\n\t\tt2.Fatal()\n\t})\n}\n\nfunc TestMultipleVariables(t *testing.T) {\n\t{ // short decl\n\t\tf, g := func(t1 *testing.T) {\n\t\t\tt1.Fatal()\n\t\t}, func(t2 *testing.T) {\n\t\t\tt2.Error()\n\t\t}\n\n\t\tgo f(t) // want \"call to .+T.+Fatal from a non-test goroutine\"\n\t\tgo g(t)\n\n\t\tt.Run(\"name\", f)\n\t\tt.Run(\"name\", g)\n\t}\n\n\t{ // var decl\n\t\tvar f, g = func(t1 *testing.T) {\n\t\t\tt1.Fatal()\n\t\t}, func(t2 *testing.T) {\n\t\t\tt2.Error()\n\t\t}\n\n\t\tgo f(t) // want \"call to .+T.+Fatal from a non-test goroutine\"\n\t\tgo g(t)\n\n\t\tt.Run(\"name\", f)\n\t\tt.Run(\"name\", g)\n\t}\n}\n\nfunc BadIgnoresMultipleAssignments(t *testing.T) {\n\t{\n\t\tf := func(t1 *testing.T) {\n\t\t\tt1.Fatal()\n\t\t}\n\t\tgo f(t) // want \"call to .+T.+Fatal from a non-test goroutine\"\n\n\t\tf = func(t2 *testing.T) {\n\t\t\tt2.Error()\n\t\t}\n\t\tgo f(t) // want \"call to .+T.+Fatal from a non-test goroutine\"\n\t}\n\t{\n\t\tf := func(t1 *testing.T) {\n\t\t\tt1.Error()\n\t\t}\n\t\tgo f(t)\n\n\t\tf = func(t2 *testing.T) {\n\t\t\tt2.FailNow()\n\t\t}\n\t\tgo f(t) // false negative\n\t}\n}\n\nfunc TestGoDoesNotDescendIntoSubtest(t *testing.T) {\n\tf := func(t2 *testing.T) {\n\t\tg := func(t3 *testing.T) {\n\t\t\tt3.Fatal() // fine\n\t\t}\n\t\tt2.Run(\"name\", g)\n\t\tt2.FailNow() // bad\n\t}\n\tgo f(t) // want \"call to .+T.+FailNow from a non-test goroutine\"\n}\n\nfunc TestFreeVariableAssignedWithinEnclosing(t *testing.T) {\n\tf := func(t2 *testing.T) {\n\t\tinner := t\n\t\tinner.FailNow()\n\t}\n\n\tgo f(nil) // want \"call to .+T.+FailNow from a non-test goroutine\"\n\n\tt.Run(\"name\", func(t3 *testing.T) {\n\t\tgo f(nil) // want \"call to .+T.+FailNow from a non-test goroutine\"\n\t})\n\n\t// Without pointer analysis we cannot tell if inner is t or t2.\n\t// So we accept a false negatives on the following examples.\n\tt.Run(\"name\", f)\n\n\tgo func(_ *testing.T) {\n\t\tt.Run(\"name\", f)\n\t}(nil)\n\n\tgo t.Run(\"name\", f)\n}\n\nfunc TestWithUnusedSelection(t *testing.T) {\n\tgo func() {\n\t\t_ = t.FailNow\n\t}()\n\tt.Run(\"name\", func(t2 *testing.T) {\n\t\t_ = t.FailNow\n\t})\n}\n\nfunc TestMethodExprsAreIgnored(t *testing.T) {\n\tgo func() {\n\t\t(*testing.T).FailNow(t)\n\t}()\n}\n\nfunc TestRecursive(t *testing.T) {\n\tt.SkipNow()\n\n\tgo TestRecursive(t) // want \"call to .+T.+SkipNow from a non-test goroutine\"\n\n\tt.Run(\"name\", TestRecursive)\n}\n\nfunc TestMethodSelection(t *testing.T) {\n\tvar h helperType\n\n\tgo h.help(t) // want \"call to .+T.+SkipNow from a non-test goroutine\"\n\tt.Run(\"name\", h.help)\n}\n\ntype helperType struct{}\n\nfunc (h *helperType) help(t *testing.T) { t.SkipNow() }\n\nfunc TestIssue63799a(t *testing.T) {\n\tdone := make(chan struct{})\n\tgo func() {\n\t\tdefer close(done)\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Fatal() // No warning. This is in a subtest.\n\t\t})\n\t}()\n\t<-done\n}\n\nfunc TestIssue63799b(t *testing.T) {\n\t// Simplified from go.dev/cl/538698\n\n\t// nondet is some unspecified boolean placeholder.\n\tvar nondet func() bool\n\n\tt.Run(\"nohup\", func(t *testing.T) {\n\t\tif nondet() {\n\t\t\tt.Skip(\"ignored\")\n\t\t}\n\n\t\tgo t.Run(\"nohup-i\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tif nondet() {\n\t\t\t\tif nondet() {\n\t\t\t\t\tt.Skip(\"go.dev/cl/538698 wanted to have skip here\")\n\t\t\t\t}\n\n\t\t\t\tt.Error(\"ignored\")\n\t\t\t} else {\n\t\t\t\tt.Log(\"ignored\")\n\t\t\t}\n\t\t})\n\t})\n}\n\nfunc TestIssue63849(t *testing.T) {\n\tgo func() {\n\t\thelper(t) // False negative. We do not do an actual interprodecural reachability analysis.\n\t}()\n\tgo helper(t) // want \"call to .+T.+Skip from a non-test goroutine\"\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/testdata/src/a/b.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport \"testing\"\n\nfunc helper(t *testing.T) {\n\tt.Skip()\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"testing\"\n)\n\nfunc f[P any](t *testing.T) {\n\tt.Fatal(\"failed\")\n}\n\nfunc TestBadFatalf[P any](t *testing.T) {\n\tgo f[int](t) // want \"call to .+T.+Fatal from a non-test goroutine\"\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/testinggoroutine.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testinggoroutine\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar reportSubtest bool\n\nfunc init() {\n\tAnalyzer.Flags.BoolVar(&reportSubtest, \"subtest\", false, \"whether to check if t.Run subtest is terminated correctly; experimental\")\n}\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"testinggoroutine\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"testinggoroutine\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tif !typesinternal.Imports(pass.Pkg, \"testing\") {\n\t\treturn nil, nil\n\t}\n\n\ttoDecl := localFunctionDecls(pass.TypesInfo, pass.Files)\n\n\t// asyncs maps nodes whose statements will be executed concurrently\n\t// with respect to some test function, to the call sites where they\n\t// are invoked asynchronously. There may be multiple such call sites\n\t// for e.g. test helpers.\n\tasyncs := make(map[ast.Node][]*asyncCall)\n\tvar regions []ast.Node\n\taddCall := func(c *asyncCall) {\n\t\tif c != nil {\n\t\t\tr := c.region\n\t\t\tif asyncs[r] == nil {\n\t\t\t\tregions = append(regions, r)\n\t\t\t}\n\t\t\tasyncs[r] = append(asyncs[r], c)\n\t\t}\n\t}\n\n\t// Collect all of the go callee() and t.Run(name, callee) extents.\n\tinspect.Nodes([]ast.Node{\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.GoStmt)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t}, func(node ast.Node, push bool) bool {\n\t\tif !push {\n\t\t\treturn false\n\t\t}\n\t\tswitch node := node.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\treturn hasBenchmarkOrTestParams(node)\n\n\t\tcase *ast.GoStmt:\n\t\t\tc := goAsyncCall(pass.TypesInfo, node, toDecl)\n\t\t\taddCall(c)\n\n\t\tcase *ast.CallExpr:\n\t\t\tc := tRunAsyncCall(pass.TypesInfo, node)\n\t\t\taddCall(c)\n\t\t}\n\t\treturn true\n\t})\n\n\t// Check for t.Forbidden() calls within each region r that is a\n\t// callee in some go r() or a t.Run(\"name\", r).\n\t//\n\t// Also considers a special case when r is a go t.Forbidden() call.\n\tfor _, region := range regions {\n\t\tast.Inspect(region, func(n ast.Node) bool {\n\t\t\tif n == region {\n\t\t\t\treturn true // always descend into the region itself.\n\t\t\t} else if asyncs[n] != nil {\n\t\t\t\treturn false // will be visited by another region.\n\t\t\t}\n\n\t\t\tcall, ok := n.(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tx, sel, fn := forbiddenMethod(pass.TypesInfo, call)\n\t\t\tif x == nil {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tfor _, e := range asyncs[region] {\n\t\t\t\tif !withinScope(e.scope, x) {\n\t\t\t\t\tforbidden := formatMethod(sel, fn) // e.g. \"(*testing.T).Forbidden\n\n\t\t\t\t\tvar context string\n\t\t\t\t\tvar where analysis.Range = e.async // Put the report at the go fun() or t.Run(name, fun).\n\t\t\t\t\tif _, local := e.fun.(*ast.FuncLit); local {\n\t\t\t\t\t\twhere = call // Put the report at the t.Forbidden() call.\n\t\t\t\t\t} else if id, ok := e.fun.(*ast.Ident); ok {\n\t\t\t\t\t\tcontext = fmt.Sprintf(\" (%s calls %s)\", id.Name, forbidden)\n\t\t\t\t\t}\n\t\t\t\t\tif _, ok := e.async.(*ast.GoStmt); ok {\n\t\t\t\t\t\tpass.ReportRangef(where, \"call to %s from a non-test goroutine%s\", forbidden, context)\n\t\t\t\t\t} else if reportSubtest {\n\t\t\t\t\t\tpass.ReportRangef(where, \"call to %s on %s defined outside of the subtest%s\", forbidden, x.Name(), context)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\n\treturn nil, nil\n}\n\nfunc hasBenchmarkOrTestParams(fnDecl *ast.FuncDecl) bool {\n\t// Check that the function's arguments include \"*testing.T\" or \"*testing.B\".\n\tparams := fnDecl.Type.Params.List\n\n\tfor _, param := range params {\n\t\tif _, ok := typeIsTestingDotTOrB(param.Type); ok {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc typeIsTestingDotTOrB(expr ast.Expr) (string, bool) {\n\tstarExpr, ok := expr.(*ast.StarExpr)\n\tif !ok {\n\t\treturn \"\", false\n\t}\n\tselExpr, ok := starExpr.X.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn \"\", false\n\t}\n\tvarPkg := selExpr.X.(*ast.Ident)\n\tif varPkg.Name != \"testing\" {\n\t\treturn \"\", false\n\t}\n\n\tvarTypeName := selExpr.Sel.Name\n\tok = varTypeName == \"B\" || varTypeName == \"T\"\n\treturn varTypeName, ok\n}\n\n// asyncCall describes a region of code that needs to be checked for\n// t.Forbidden() calls as it is started asynchronously from an async\n// node go fun() or t.Run(name, fun).\ntype asyncCall struct {\n\tregion ast.Node // region of code to check for t.Forbidden() calls.\n\tasync  ast.Node // *ast.GoStmt or *ast.CallExpr (for t.Run)\n\tscope  ast.Node // Report t.Forbidden() if t is not declared within scope.\n\tfun    ast.Expr // fun in go fun() or t.Run(name, fun)\n}\n\n// withinScope returns true if x.Pos() is in [scope.Pos(), scope.End()].\nfunc withinScope(scope ast.Node, x *types.Var) bool {\n\tif scope != nil {\n\t\treturn x.Pos() != token.NoPos && scope.Pos() <= x.Pos() && x.Pos() <= scope.End()\n\t}\n\treturn false\n}\n\n// goAsyncCall returns the extent of a call from a go fun() statement.\nfunc goAsyncCall(info *types.Info, goStmt *ast.GoStmt, toDecl func(*types.Func) *ast.FuncDecl) *asyncCall {\n\tcall := goStmt.Call\n\n\tfun := ast.Unparen(call.Fun)\n\tif id := typesinternal.UsedIdent(info, fun); id != nil {\n\t\tif lit := funcLitInScope(id); lit != nil {\n\t\t\treturn &asyncCall{region: lit, async: goStmt, scope: nil, fun: fun}\n\t\t}\n\t}\n\n\tif fn := typeutil.StaticCallee(info, call); fn != nil { // static call or method in the package?\n\t\tif decl := toDecl(fn); decl != nil {\n\t\t\treturn &asyncCall{region: decl, async: goStmt, scope: nil, fun: fun}\n\t\t}\n\t}\n\n\t// Check go statement for go t.Forbidden() or go func(){t.Forbidden()}().\n\treturn &asyncCall{region: goStmt, async: goStmt, scope: nil, fun: fun}\n}\n\n// tRunAsyncCall returns the extent of a call from a t.Run(\"name\", fun) expression.\nfunc tRunAsyncCall(info *types.Info, call *ast.CallExpr) *asyncCall {\n\tif len(call.Args) != 2 {\n\t\treturn nil\n\t}\n\trun := typeutil.Callee(info, call)\n\tif run, ok := run.(*types.Func); !ok || !isMethodNamed(run, \"testing\", \"Run\") {\n\t\treturn nil\n\t}\n\n\tfun := ast.Unparen(call.Args[1])\n\tif lit, ok := fun.(*ast.FuncLit); ok { // function lit?\n\t\treturn &asyncCall{region: lit, async: call, scope: lit, fun: fun}\n\t}\n\n\tif id := typesinternal.UsedIdent(info, fun); id != nil {\n\t\tif lit := funcLitInScope(id); lit != nil { // function lit in variable?\n\t\t\treturn &asyncCall{region: lit, async: call, scope: lit, fun: fun}\n\t\t}\n\t}\n\n\t// Check within t.Run(name, fun) for calls to t.Forbidden,\n\t// e.g. t.Run(name, func(t *testing.T){ t.Forbidden() })\n\treturn &asyncCall{region: call, async: call, scope: fun, fun: fun}\n}\n\nvar forbidden = []string{\n\t\"FailNow\",\n\t\"Fatal\",\n\t\"Fatalf\",\n\t\"Skip\",\n\t\"Skipf\",\n\t\"SkipNow\",\n}\n\n// forbiddenMethod decomposes a call x.m() into (x, x.m, m) where\n// x is a variable, x.m is a selection, and m is the static callee m.\n// Returns (nil, nil, nil) if call is not of this form.\nfunc forbiddenMethod(info *types.Info, call *ast.CallExpr) (*types.Var, *types.Selection, *types.Func) {\n\t// Compare to typeutil.StaticCallee.\n\tfun := ast.Unparen(call.Fun)\n\tselExpr, ok := fun.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn nil, nil, nil\n\t}\n\tsel := info.Selections[selExpr]\n\tif sel == nil {\n\t\treturn nil, nil, nil\n\t}\n\n\tvar x *types.Var\n\tif id, ok := ast.Unparen(selExpr.X).(*ast.Ident); ok {\n\t\tx, _ = info.Uses[id].(*types.Var)\n\t}\n\tif x == nil {\n\t\treturn nil, nil, nil\n\t}\n\n\tfn, _ := sel.Obj().(*types.Func)\n\tif fn == nil || !isMethodNamed(fn, \"testing\", forbidden...) {\n\t\treturn nil, nil, nil\n\t}\n\treturn x, sel, fn\n}\n\nfunc formatMethod(sel *types.Selection, fn *types.Func) string {\n\tvar ptr string\n\trtype := sel.Recv()\n\tif p, ok := types.Unalias(rtype).(*types.Pointer); ok {\n\t\tptr = \"*\"\n\t\trtype = p.Elem()\n\t}\n\treturn fmt.Sprintf(\"(%s%s).%s\", ptr, rtype.String(), fn.Name())\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/testinggoroutine_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testinggoroutine_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/testinggoroutine\"\n)\n\nfunc init() {\n\ttestinggoroutine.Analyzer.Flags.Set(\"subtest\", \"true\")\n}\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tpkgs := []string{\"a\", \"typeparams\"}\n\tanalysistest.Run(t, testdata, testinggoroutine.Analyzer, pkgs...)\n}\n"
  },
  {
    "path": "go/analysis/passes/testinggoroutine/util.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testinggoroutine\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"slices\"\n)\n\n// AST and types utilities that not specific to testinggoroutines.\n\n// localFunctionDecls returns a mapping from *types.Func to *ast.FuncDecl in files.\nfunc localFunctionDecls(info *types.Info, files []*ast.File) func(*types.Func) *ast.FuncDecl {\n\tvar fnDecls map[*types.Func]*ast.FuncDecl // computed lazily\n\treturn func(f *types.Func) *ast.FuncDecl {\n\t\tif f != nil && fnDecls == nil {\n\t\t\tfnDecls = make(map[*types.Func]*ast.FuncDecl)\n\t\t\tfor _, file := range files {\n\t\t\t\tfor _, decl := range file.Decls {\n\t\t\t\t\tif fnDecl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\t\t\tif fn, ok := info.Defs[fnDecl.Name].(*types.Func); ok {\n\t\t\t\t\t\t\tfnDecls[fn] = fnDecl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// TODO: set f = f.Origin() here.\n\t\treturn fnDecls[f]\n\t}\n}\n\n// isMethodNamed returns true if f is a method defined\n// in package with the path pkgPath with a name in names.\n//\n// (Unlike [analysis.IsMethodNamed], it ignores the receiver type name.)\nfunc isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {\n\tif f == nil {\n\t\treturn false\n\t}\n\tif f.Pkg() == nil || f.Pkg().Path() != pkgPath {\n\t\treturn false\n\t}\n\tif f.Signature().Recv() == nil {\n\t\treturn false\n\t}\n\treturn slices.Contains(names, f.Name())\n}\n\n// funcLitInScope returns a FuncLit that id is at least initially assigned to.\n//\n// TODO: This is closely tied to id.Obj which is deprecated.\nfunc funcLitInScope(id *ast.Ident) *ast.FuncLit {\n\t// Compare to (*ast.Object).Pos().\n\tif id.Obj == nil {\n\t\treturn nil\n\t}\n\tvar rhs ast.Expr\n\tswitch d := id.Obj.Decl.(type) {\n\tcase *ast.AssignStmt:\n\t\tfor i, x := range d.Lhs {\n\t\t\tif ident, isIdent := x.(*ast.Ident); isIdent && ident.Name == id.Name && i < len(d.Rhs) {\n\t\t\t\trhs = d.Rhs[i]\n\t\t\t}\n\t\t}\n\tcase *ast.ValueSpec:\n\t\tfor i, n := range d.Names {\n\t\t\tif n.Name == id.Name && i < len(d.Values) {\n\t\t\t\trhs = d.Values[i]\n\t\t\t}\n\t\t}\n\t}\n\tlit, _ := rhs.(*ast.FuncLit)\n\treturn lit\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package tests defines an Analyzer that checks for common mistaken\n// usages of tests and examples.\n//\n// # Analyzer tests\n//\n// tests: check for common mistaken usages of tests and examples\n//\n// The tests checker walks Test, Benchmark, Fuzzing and Example functions checking\n// malformed names, wrong signatures and examples documenting non-existent\n// identifiers.\n//\n// Please see the documentation for package testing in golang.org/pkg/testing\n// for the conventions that are enforced for Tests, Benchmarks, and Examples.\npackage tests\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/a/a.go",
    "content": "package a\n\nfunc Foo() {}\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/a/a_test.go",
    "content": "package a\n\nimport (\n\t\"testing\"\n)\n\n// Buf is a ...\ntype Buf []byte\n\n// Append ...\nfunc (*Buf) Append([]byte) {}\n\nfunc (Buf) Reset() {}\n\nfunc (Buf) Len() int { return 0 }\n\n// DefaultBuf is a ...\nvar DefaultBuf Buf\n\nfunc Example() {} // OK because is package-level.\n\nfunc Example_goodSuffix() {} // OK because refers to suffix annotation.\n\nfunc Example_BadSuffix() {} // want \"Example_BadSuffix has malformed example suffix: BadSuffix\"\n\nfunc ExampleBuf() {} // OK because refers to known top-level type.\n\nfunc ExampleBuf_Append() {} // OK because refers to known method.\n\nfunc ExampleBuf_Clear() {} // want \"ExampleBuf_Clear refers to unknown field or method: Buf.Clear\"\n\nfunc ExampleBuf_suffix() {} // OK because refers to suffix annotation.\n\nfunc ExampleBuf_Append_Bad() {} // want \"ExampleBuf_Append_Bad has malformed example suffix: Bad\"\n\nfunc ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.\n\nfunc ExampleDefaultBuf() {} // OK because refers to top-level identifier.\n\nfunc ExampleBuf_Reset() bool { return true } // want \"ExampleBuf_Reset should return nothing\"\n\nfunc ExampleBuf_Len(i int) {} // want \"ExampleBuf_Len should be niladic\"\n\n// \"Puffer\" is German for \"Buffer\".\n\nfunc ExamplePuffer() {} // want \"ExamplePuffer refers to unknown identifier: Puffer\"\n\nfunc ExamplePuffer_Append() {} // want \"ExamplePuffer_Append refers to unknown identifier: Puffer\"\n\nfunc ExamplePuffer_suffix() {} // want \"ExamplePuffer_suffix refers to unknown identifier: Puffer\"\n\nfunc ExampleFoo() {} // OK because a.Foo exists\n\nfunc ExampleBar() {} // want \"ExampleBar refers to unknown identifier: Bar\"\n\nfunc Example_withOutput() {\n\t// Output:\n\t// meow\n} // OK because output is the last comment block\n\nfunc Example_withBadOutput() {\n\t// Output: // want \"output comment block must be the last comment block\"\n\t// meow\n\n\t// todo: change to bark\n}\n\nfunc Example_withBadUnorderedOutput() {\n\t// Unordered Output: // want \"output comment block must be the last comment block\"\n\t// meow\n\n\t// todo: change to bark\n}\n\nfunc Example_withCommentAfterFunc() {\n\t// Output: // OK because it is the last comment block\n\t// meow\n} // todo: change to bark\n\nfunc Example_withOutputCommentAfterFunc() {\n\t// Output:\n\t// meow\n} // Output: bark // OK because output is not inside of an example\n\nfunc Example_withMultipleOutputs() {\n\t// Output: // want \"there can only be one output comment block per example\"\n\t// meow\n\n\t// Output: // want \"there can only be one output comment block per example\"\n\t// bark\n\n\t// Output: // OK because it is the last output comment block\n\t// ribbit\n}\n\nfunc nonTest() {} // OK because it doesn't start with \"Test\".\n\nfunc (Buf) TesthasReceiver() {} // OK because it has a receiver.\n\nfunc TestOKSuffix(*testing.T) {} // OK because first char after \"Test\" is Uppercase.\n\nfunc TestÜnicodeWorks(*testing.T) {} // OK because the first char after \"Test\" is Uppercase.\n\nfunc TestbadSuffix(*testing.T) {} // want \"first letter after 'Test' must not be lowercase\"\n\nfunc TestemptyImportBadSuffix(*testing.T) {} // want \"first letter after 'Test' must not be lowercase\"\n\nfunc Test(*testing.T) {} // OK \"Test\" on its own is considered a test.\n\nfunc Testify() {} // OK because it takes no parameters.\n\nfunc TesttooManyParams(*testing.T, string) {} // OK because it takes too many parameters.\n\nfunc TesttooManyNames(a, b *testing.T) {} // OK because it takes too many names.\n\nfunc TestnoTParam(string) {} // OK because it doesn't take a *testing.T\n\nfunc BenchmarkbadSuffix(*testing.B) {} // want \"first letter after 'Benchmark' must not be lowercase\"\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/a/ax_test.go",
    "content": "package a_test\n\nimport _ \"a\"\n\nfunc ExampleFoo() {} // OK because a.Foo exists\n\nfunc ExampleBar() {} // want \"ExampleBar refers to unknown identifier: Bar\"\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/a/go118_test.go",
    "content": "package a\n\nimport (\n\t\"testing\"\n)\n\nfunc Fuzzfoo(*testing.F) {} // want \"first letter after 'Fuzz' must not be lowercase\"\n\nfunc FuzzBoo(*testing.F) {} // OK because first letter after 'Fuzz' is Uppercase.\n\nfunc FuzzCallDifferentFunc(f *testing.F) {\n\tf.Name() //OK\n}\n\nfunc FuzzFunc(f *testing.F) {\n\tf.Fuzz(func(t *testing.T) {}) // OK \"first argument is of type *testing.T\"\n}\n\nfunc FuzzFuncWithArgs(f *testing.F) {\n\tf.Add()                                      // want `wrong number of values in call to \\(\\*testing.F\\)\\.Add: 0, fuzz target expects 2`\n\tf.Add(1, 2, 3, 4)                            // want `wrong number of values in call to \\(\\*testing.F\\)\\.Add: 4, fuzz target expects 2`\n\tf.Add(5, 5)                                  // want `mismatched type in call to \\(\\*testing.F\\)\\.Add: int, fuzz target expects \\[\\]byte`\n\tf.Add([]byte(\"hello\"), 5)                    // want `mismatched types in call to \\(\\*testing.F\\)\\.Add: \\[\\[\\]byte int\\], fuzz target expects \\[int \\[\\]byte\\]`\n\tf.Add(5, []byte(\"hello\"))                    // OK\n\tf.Fuzz(func(t *testing.T, i int, b []byte) { // OK \"arguments in func are allowed\"\n\t\tf.Add(5, []byte(\"hello\"))     // want `fuzz target must not call any \\*F methods`\n\t\tf.Name()                      // OK \"calls to (*F).Failed and (*F).Name are allowed\"\n\t\tf.Failed()                    // OK \"calls to (*F).Failed and (*F).Name are allowed\"\n\t\tf.Fuzz(func(t *testing.T) {}) // want `fuzz target must not call any \\*F methods`\n\t})\n}\n\nfunc FuzzArgFunc(f *testing.F) {\n\tf.Fuzz(0) // want \"argument to Fuzz must be a function\"\n}\n\nfunc FuzzFuncWithReturn(f *testing.F) {\n\tf.Fuzz(func(t *testing.T) bool { return true }) // want \"fuzz target must not return any value\"\n}\n\nfunc FuzzFuncNoArg(f *testing.F) {\n\tf.Fuzz(func() {}) // want \"fuzz target must have 1 or more argument\"\n}\n\nfunc FuzzFuncFirstArgNotTesting(f *testing.F) {\n\tf.Fuzz(func(i int64) {}) // want \"the first parameter of a fuzz target must be \\\\*testing.T\"\n}\n\nfunc FuzzFuncFirstArgTestingNotT(f *testing.F) {\n\tf.Fuzz(func(t *testing.F) {}) // want \"the first parameter of a fuzz target must be \\\\*testing.T\"\n}\n\nfunc FuzzFuncSecondArgNotAllowed(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, i complex64) {}) // want \"fuzzing arguments can only have the following types: string, bool, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, \\\\[\\\\]byte\"\n}\n\nfunc FuzzFuncSecondArgArrNotAllowed(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, i []int) {}) // want \"fuzzing arguments can only have the following types: string, bool, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, \\\\[\\\\]byte\"\n}\n\nfunc FuzzFuncConsecutiveArgNotAllowed(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, i, j string, k complex64) {}) // want \"fuzzing arguments can only have the following types: string, bool, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, \\\\[\\\\]byte\"\n}\n\nfunc FuzzFuncInner(f *testing.F) {\n\tinnerFunc := func(t *testing.T, i float32) {}\n\tf.Fuzz(innerFunc) // ok\n}\n\nfunc FuzzArrayOfFunc(f *testing.F) {\n\tvar funcs = []func(t *testing.T, i int){func(t *testing.T, i int) {}}\n\tf.Fuzz(funcs[0]) // ok\n}\n\ntype GenericSlice[T any] []T\n\nfunc FuzzGenericFunc(f *testing.F) {\n\tg := GenericSlice[func(t *testing.T, i int)]{func(t *testing.T, i int) {}}\n\tf.Fuzz(g[0]) // ok\n}\n\ntype F func(t *testing.T, i int32)\n\ntype myType struct {\n\tmyVar F\n}\n\nfunc FuzzObjectMethod(f *testing.F) {\n\tobj := myType{\n\t\tmyVar: func(t *testing.T, i int32) {},\n\t}\n\tf.Fuzz(obj.myVar) // ok\n}\n\n// Test for golang/go#56505: checking fuzz arguments should not panic on *error.\nfunc FuzzIssue56505(f *testing.F) {\n\tf.Fuzz(func(e *error) {}) // want \"the first parameter of a fuzz target must be \\\\*testing.T\"\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/b/b.go",
    "content": "package b\n\ntype Foo struct {\n}\n\nfunc (f *Foo) F() {\n\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/b_x_test/b_test.go",
    "content": "package b_x_test\n\nimport (\n\t\"a\"\n\t\"b\"\n)\n\nfunc ExampleFoo_F() {\n\tvar x b.Foo\n\tx.F()\n\ta.Foo()\n}\n\nfunc ExampleFoo_G() { // want \"ExampleFoo_G refers to unknown field or method: Foo.G\"\n\n}\n\nfunc ExampleBar_F() { // want \"ExampleBar_F refers to unknown identifier: Bar\"\n\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/divergent/buf.go",
    "content": "// Test of examples with divergent packages.\n\n// Package buf ...\npackage buf\n\n// Buf is a ...\ntype Buf []byte\n\n// Append ...\nfunc (*Buf) Append([]byte) {}\n\nfunc (Buf) Reset() {}\n\nfunc (Buf) Len() int { return 0 }\n\n// DefaultBuf is a ...\nvar DefaultBuf Buf\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/divergent/buf_test.go",
    "content": "// Test of examples with divergent packages.\n\npackage buf\n\nfunc Example() {} // OK because is package-level.\n\nfunc Example_suffix() {} // OK because refers to suffix annotation.\n\nfunc Example_BadSuffix() {} // want \"Example_BadSuffix has malformed example suffix: BadSuffix\"\n\nfunc ExampleBuf() {} // OK because refers to known top-level type.\n\nfunc ExampleBuf_Append() {} // OK because refers to known method.\n\nfunc ExampleBuf_Clear() {} // want \"ExampleBuf_Clear refers to unknown field or method: Buf.Clear\"\n\nfunc ExampleBuf_suffix() {} // OK because refers to suffix annotation.\n\nfunc ExampleBuf_Append_Bad() {} // want \"ExampleBuf_Append_Bad has malformed example suffix: Bad\"\n\nfunc ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.\n\nfunc ExampleDefaultBuf() {} // OK because refers to top-level identifier.\n\nfunc ExampleBuf_Reset() bool { return true } // want \"ExampleBuf_Reset should return nothing\"\n\nfunc ExampleBuf_Len(i int) {} // want \"ExampleBuf_Len should be niladic\"\n\n// \"Puffer\" is German for \"Buffer\".\n\nfunc ExamplePuffer() {} // want \"ExamplePuffer refers to unknown identifier: Puffer\"\n\nfunc ExamplePuffer_Append() {} // want \"ExamplePuffer_Append refers to unknown identifier: Puffer\"\n\nfunc ExamplePuffer_suffix() {} // want \"ExamplePuffer_suffix refers to unknown identifier: Puffer\"\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nfunc Zero[T any]() T {\n\tvar zero T\n\treturn zero\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/testdata/src/typeparams/typeparams_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"testing\"\n\nfunc Test(*testing.T) {\n\t_ = Zero[int]() // It is fine to use generics within tests.\n}\n\n// Note: We format {Test,Benchmark}typeParam with a 't' in \"type\" to avoid an error from\n// cmd/go/internal/load. That package can also give an error about Test and Benchmark\n// functions with TypeParameters. These tests may need to be updated if that logic changes.\nfunc TesttypeParam[T any](*testing.T)      {} // want \"TesttypeParam has type parameters: it will not be run by go test as a TestXXX function\" \"TesttypeParam has malformed name\"\nfunc BenchmarktypeParam[T any](*testing.B) {} // want \"BenchmarktypeParam has type parameters: it will not be run by go test as a BenchmarkXXX function\" \"BenchmarktypeParam has malformed name\"\n\nfunc ExampleZero[T any]() { // want \"ExampleZero should not have type params\"\n\tprint(Zero[T]())\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/tests.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage tests\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"tests\",\n\tDoc:  analyzerutil.MustExtractDoc(doc, \"tests\"),\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests\",\n\tRun:  run,\n}\n\nvar acceptedFuzzTypes = []types.Type{\n\ttypes.Typ[types.String],\n\ttypes.Typ[types.Bool],\n\ttypes.Typ[types.Float32],\n\ttypes.Typ[types.Float64],\n\ttypes.Typ[types.Int],\n\ttypes.Typ[types.Int8],\n\ttypes.Typ[types.Int16],\n\ttypes.Typ[types.Int32],\n\ttypes.Typ[types.Int64],\n\ttypes.Typ[types.Uint],\n\ttypes.Typ[types.Uint8],\n\ttypes.Typ[types.Uint16],\n\ttypes.Typ[types.Uint32],\n\ttypes.Typ[types.Uint64],\n\ttypes.NewSlice(types.Universe.Lookup(\"byte\").Type()),\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tfor _, f := range pass.Files {\n\t\tif !strings.HasSuffix(pass.Fset.File(f.FileStart).Name(), \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, decl := range f.Decls {\n\t\t\tfn, ok := decl.(*ast.FuncDecl)\n\t\t\tif !ok || fn.Recv != nil {\n\t\t\t\t// Ignore non-functions or functions with receivers.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch {\n\t\t\tcase strings.HasPrefix(fn.Name.Name, \"Example\"):\n\t\t\t\tcheckExampleName(pass, fn)\n\t\t\t\tcheckExampleOutput(pass, fn, f.Comments)\n\t\t\tcase strings.HasPrefix(fn.Name.Name, \"Test\"):\n\t\t\t\tcheckTest(pass, fn, \"Test\")\n\t\t\tcase strings.HasPrefix(fn.Name.Name, \"Benchmark\"):\n\t\t\t\tcheckTest(pass, fn, \"Benchmark\")\n\t\t\tcase strings.HasPrefix(fn.Name.Name, \"Fuzz\"):\n\t\t\t\tcheckTest(pass, fn, \"Fuzz\")\n\t\t\t\tcheckFuzz(pass, fn)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// checkFuzz checks the contents of a fuzz function.\nfunc checkFuzz(pass *analysis.Pass, fn *ast.FuncDecl) {\n\tparams := checkFuzzCall(pass, fn)\n\tif params != nil {\n\t\tcheckAddCalls(pass, fn, params)\n\t}\n}\n\n// checkFuzzCall checks the arguments of f.Fuzz() calls:\n//\n//  1. f.Fuzz() should call a function and it should be of type (*testing.F).Fuzz().\n//  2. The called function in f.Fuzz(func(){}) should not return result.\n//  3. First argument of func() should be of type *testing.T\n//  4. Second argument onwards should be of type []byte, string, bool, byte,\n//     rune, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16,\n//     uint32, uint64\n//  5. func() must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip\n//     The only *F methods that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.\n//\n// Returns the list of parameters to the fuzz function, if they are valid fuzz parameters.\nfunc checkFuzzCall(pass *analysis.Pass, fn *ast.FuncDecl) (params *types.Tuple) {\n\tast.Inspect(fn, func(n ast.Node) bool {\n\t\tcall, ok := n.(*ast.CallExpr)\n\t\tif ok {\n\t\t\tif !isFuzzTargetDotFuzz(pass, call) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Only one argument (func) must be passed to (*testing.F).Fuzz.\n\t\t\tif len(call.Args) != 1 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\texpr := call.Args[0]\n\t\t\tif pass.TypesInfo.Types[expr].Type == nil {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tt := pass.TypesInfo.Types[expr].Type.Underlying()\n\t\t\ttSign, argOk := t.(*types.Signature)\n\t\t\t// Argument should be a function\n\t\t\tif !argOk {\n\t\t\t\tpass.ReportRangef(expr, \"argument to Fuzz must be a function\")\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// ff Argument function should not return\n\t\t\tif tSign.Results().Len() != 0 {\n\t\t\t\tpass.ReportRangef(expr, \"fuzz target must not return any value\")\n\t\t\t}\n\t\t\t// ff Argument function should have 1 or more argument\n\t\t\tif tSign.Params().Len() == 0 {\n\t\t\t\tpass.ReportRangef(expr, \"fuzz target must have 1 or more argument\")\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tok := validateFuzzArgs(pass, tSign.Params(), expr)\n\t\t\tif ok && params == nil {\n\t\t\t\tparams = tSign.Params()\n\t\t\t}\n\t\t\t// Inspect the function that was passed as an argument to make sure that\n\t\t\t// there are no calls to *F methods, except for Name and Failed.\n\t\t\tast.Inspect(expr, func(n ast.Node) bool {\n\t\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\tif !isFuzzTargetDot(pass, call, \"\") {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t\tif !isFuzzTargetDot(pass, call, \"Name\") && !isFuzzTargetDot(pass, call, \"Failed\") {\n\t\t\t\t\t\tpass.ReportRangef(call, \"fuzz target must not call any *F methods\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t\t// We do not need to look at any calls to f.Fuzz inside of a Fuzz call,\n\t\t\t// since they are not allowed.\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\treturn params\n}\n\n// checkAddCalls checks that the arguments of f.Add calls have the same number and type of arguments as\n// the signature of the function passed to (*testing.F).Fuzz\nfunc checkAddCalls(pass *analysis.Pass, fn *ast.FuncDecl, params *types.Tuple) {\n\tast.Inspect(fn, func(n ast.Node) bool {\n\t\tcall, ok := n.(*ast.CallExpr)\n\t\tif ok {\n\t\t\tif !isFuzzTargetDotAdd(pass, call) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// The first argument to function passed to (*testing.F).Fuzz is (*testing.T).\n\t\t\tif len(call.Args) != params.Len()-1 {\n\t\t\t\tpass.ReportRangef(call, \"wrong number of values in call to (*testing.F).Add: %d, fuzz target expects %d\", len(call.Args), params.Len()-1)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tvar mismatched []int\n\t\t\tfor i, expr := range call.Args {\n\t\t\t\tif pass.TypesInfo.Types[expr].Type == nil {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tt := pass.TypesInfo.Types[expr].Type\n\t\t\t\tif !types.Identical(t, params.At(i+1).Type()) {\n\t\t\t\t\tmismatched = append(mismatched, i)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If just one of the types is mismatched report for that\n\t\t\t// type only. Otherwise report for the whole call to (*testing.F).Add\n\t\t\tif len(mismatched) == 1 {\n\t\t\t\ti := mismatched[0]\n\t\t\t\texpr := call.Args[i]\n\t\t\t\tt := pass.TypesInfo.Types[expr].Type\n\t\t\t\tpass.ReportRangef(expr, \"mismatched type in call to (*testing.F).Add: %v, fuzz target expects %v\", t, params.At(i+1).Type())\n\t\t\t} else if len(mismatched) > 1 {\n\t\t\t\tvar gotArgs, wantArgs []types.Type\n\t\t\t\tfor i := 0; i < len(call.Args); i++ {\n\t\t\t\t\tgotArgs, wantArgs = append(gotArgs, pass.TypesInfo.Types[call.Args[i]].Type), append(wantArgs, params.At(i+1).Type())\n\t\t\t\t}\n\t\t\t\tpass.ReportRangef(call, \"mismatched types in call to (*testing.F).Add: %v, fuzz target expects %v\", gotArgs, wantArgs)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// isFuzzTargetDotFuzz reports whether call is (*testing.F).Fuzz().\nfunc isFuzzTargetDotFuzz(pass *analysis.Pass, call *ast.CallExpr) bool {\n\treturn isFuzzTargetDot(pass, call, \"Fuzz\")\n}\n\n// isFuzzTargetDotAdd reports whether call is (*testing.F).Add().\nfunc isFuzzTargetDotAdd(pass *analysis.Pass, call *ast.CallExpr) bool {\n\treturn isFuzzTargetDot(pass, call, \"Add\")\n}\n\n// isFuzzTargetDot reports whether call is (*testing.F).<name>().\nfunc isFuzzTargetDot(pass *analysis.Pass, call *ast.CallExpr, name string) bool {\n\tif selExpr, ok := call.Fun.(*ast.SelectorExpr); ok {\n\t\tif !isTestingType(pass.TypesInfo.Types[selExpr.X].Type, \"F\") {\n\t\t\treturn false\n\t\t}\n\t\tif name == \"\" || selExpr.Sel.Name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Validate the arguments of fuzz target.\nfunc validateFuzzArgs(pass *analysis.Pass, params *types.Tuple, expr ast.Expr) bool {\n\tfLit, isFuncLit := expr.(*ast.FuncLit)\n\texprRange := expr\n\tok := true\n\tif !isTestingType(params.At(0).Type(), \"T\") {\n\t\tif isFuncLit {\n\t\t\texprRange = fLit.Type.Params.List[0].Type\n\t\t}\n\t\tpass.ReportRangef(exprRange, \"the first parameter of a fuzz target must be *testing.T\")\n\t\tok = false\n\t}\n\tfor i := 1; i < params.Len(); i++ {\n\t\tif !isAcceptedFuzzType(params.At(i).Type()) {\n\t\t\tif isFuncLit {\n\t\t\t\tcurr := 0\n\t\t\t\tfor _, field := range fLit.Type.Params.List {\n\t\t\t\t\tcurr += len(field.Names)\n\t\t\t\t\tif i < curr {\n\t\t\t\t\t\texprRange = field.Type\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tpass.ReportRangef(exprRange, \"fuzzing arguments can only have the following types: %s\", formatAcceptedFuzzType())\n\t\t\tok = false\n\t\t}\n\t}\n\treturn ok\n}\n\nfunc isTestingType(typ types.Type, testingType string) bool {\n\t// No Unalias here: I doubt \"go test\" recognizes\n\t// \"type A = *testing.T; func Test(A) {}\" as a test.\n\tptr, ok := typ.(*types.Pointer)\n\tif !ok {\n\t\treturn false\n\t}\n\treturn typesinternal.IsTypeNamed(ptr.Elem(), \"testing\", testingType)\n}\n\n// Validate that fuzz target function's arguments are of accepted types.\nfunc isAcceptedFuzzType(paramType types.Type) bool {\n\tfor _, typ := range acceptedFuzzTypes {\n\t\tif types.Identical(typ, paramType) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc formatAcceptedFuzzType() string {\n\tvar acceptedFuzzTypesStrings []string\n\tfor _, typ := range acceptedFuzzTypes {\n\t\tacceptedFuzzTypesStrings = append(acceptedFuzzTypesStrings, typ.String())\n\t}\n\tacceptedFuzzTypesMsg := strings.Join(acceptedFuzzTypesStrings, \", \")\n\treturn acceptedFuzzTypesMsg\n}\n\nfunc isExampleSuffix(s string) bool {\n\tr, size := utf8.DecodeRuneInString(s)\n\treturn size > 0 && unicode.IsLower(r)\n}\n\nfunc isTestSuffix(name string) bool {\n\tif len(name) == 0 {\n\t\t// \"Test\" is ok.\n\t\treturn true\n\t}\n\tr, _ := utf8.DecodeRuneInString(name)\n\treturn !unicode.IsLower(r)\n}\n\nfunc isTestParam(typ ast.Expr, wantType string) bool {\n\tptr, ok := typ.(*ast.StarExpr)\n\tif !ok {\n\t\t// Not a pointer.\n\t\treturn false\n\t}\n\t// No easy way of making sure it's a *testing.T or *testing.B:\n\t// ensure the name of the type matches.\n\tif name, ok := ptr.X.(*ast.Ident); ok {\n\t\treturn name.Name == wantType\n\t}\n\tif sel, ok := ptr.X.(*ast.SelectorExpr); ok {\n\t\treturn sel.Sel.Name == wantType\n\t}\n\treturn false\n}\n\nfunc lookup(pkg *types.Package, name string) []types.Object {\n\tif o := pkg.Scope().Lookup(name); o != nil {\n\t\treturn []types.Object{o}\n\t}\n\n\tvar ret []types.Object\n\t// Search through the imports to see if any of them define name.\n\t// It's hard to tell in general which package is being tested, so\n\t// for the purposes of the analysis, allow the object to appear\n\t// in any of the imports. This guarantees there are no false positives\n\t// because the example needs to use the object so it must be defined\n\t// in the package or one if its imports. On the other hand, false\n\t// negatives are possible, but should be rare.\n\tfor _, imp := range pkg.Imports() {\n\t\tif obj := imp.Scope().Lookup(name); obj != nil {\n\t\t\tret = append(ret, obj)\n\t\t}\n\t}\n\treturn ret\n}\n\n// This pattern is taken from /go/src/go/doc/example.go\nvar outputRe = regexp.MustCompile(`(?i)^[[:space:]]*(unordered )?output:`)\n\ntype commentMetadata struct {\n\tisOutput bool\n\tpos      token.Pos\n}\n\nfunc checkExampleOutput(pass *analysis.Pass, fn *ast.FuncDecl, fileComments []*ast.CommentGroup) {\n\tcommentsInExample := []commentMetadata{}\n\tnumOutputs := 0\n\n\t// Find the comment blocks that are in the example. These comments are\n\t// guaranteed to be in order of appearance.\n\tfor _, cg := range fileComments {\n\t\tif cg.Pos() < fn.Pos() {\n\t\t\tcontinue\n\t\t} else if cg.End() > fn.End() {\n\t\t\tbreak\n\t\t}\n\n\t\tisOutput := outputRe.MatchString(cg.Text())\n\t\tif isOutput {\n\t\t\tnumOutputs++\n\t\t}\n\n\t\tcommentsInExample = append(commentsInExample, commentMetadata{\n\t\t\tisOutput: isOutput,\n\t\t\tpos:      cg.Pos(),\n\t\t})\n\t}\n\n\t// Change message based on whether there are multiple output comment blocks.\n\tmsg := \"output comment block must be the last comment block\"\n\tif numOutputs > 1 {\n\t\tmsg = \"there can only be one output comment block per example\"\n\t}\n\n\tfor i, cg := range commentsInExample {\n\t\t// Check for output comments that are not the last comment in the example.\n\t\tisLast := (i == len(commentsInExample)-1)\n\t\tif cg.isOutput && !isLast {\n\t\t\tpass.Report(\n\t\t\t\tanalysis.Diagnostic{\n\t\t\t\t\tPos:     cg.pos,\n\t\t\t\t\tMessage: msg,\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t}\n}\n\nfunc checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) {\n\tfnName := fn.Name.Name\n\tif params := fn.Type.Params; len(params.List) != 0 {\n\t\tpass.Reportf(fn.Pos(), \"%s should be niladic\", fnName)\n\t}\n\tif results := fn.Type.Results; results != nil && len(results.List) != 0 {\n\t\tpass.Reportf(fn.Pos(), \"%s should return nothing\", fnName)\n\t}\n\tif tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 {\n\t\tpass.Reportf(fn.Pos(), \"%s should not have type params\", fnName)\n\t}\n\n\tif fnName == \"Example\" {\n\t\t// Nothing more to do.\n\t\treturn\n\t}\n\n\tvar (\n\t\texName = strings.TrimPrefix(fnName, \"Example\")\n\t\telems  = strings.SplitN(exName, \"_\", 3)\n\t\tident  = elems[0]\n\t\tobjs   = lookup(pass.Pkg, ident)\n\t)\n\tif ident != \"\" && len(objs) == 0 {\n\t\t// Check ExampleFoo and ExampleBadFoo.\n\t\tpass.Reportf(fn.Pos(), \"%s refers to unknown identifier: %s\", fnName, ident)\n\t\t// Abort since obj is absent and no subsequent checks can be performed.\n\t\treturn\n\t}\n\tif len(elems) < 2 {\n\t\t// Nothing more to do.\n\t\treturn\n\t}\n\n\tif ident == \"\" {\n\t\t// Check Example_suffix and Example_BadSuffix.\n\t\tif residual := strings.TrimPrefix(exName, \"_\"); !isExampleSuffix(residual) {\n\t\t\tpass.Reportf(fn.Pos(), \"%s has malformed example suffix: %s\", fnName, residual)\n\t\t}\n\t\treturn\n\t}\n\n\tmmbr := elems[1]\n\tif !isExampleSuffix(mmbr) {\n\t\t// Check ExampleFoo_Method and ExampleFoo_BadMethod.\n\t\tfound := false\n\t\t// Check if Foo.Method exists in this package or its imports.\n\t\tfor _, obj := range objs {\n\t\t\tif obj, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), mmbr); obj != nil {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tpass.Reportf(fn.Pos(), \"%s refers to unknown field or method: %s.%s\", fnName, ident, mmbr)\n\t\t}\n\t}\n\tif len(elems) == 3 && !isExampleSuffix(elems[2]) {\n\t\t// Check ExampleFoo_Method_suffix and ExampleFoo_Method_Badsuffix.\n\t\tpass.Reportf(fn.Pos(), \"%s has malformed example suffix: %s\", fnName, elems[2])\n\t}\n}\n\nfunc checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) {\n\t// Want functions with 0 results and 1 parameter.\n\tif fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||\n\t\tfn.Type.Params == nil ||\n\t\tlen(fn.Type.Params.List) != 1 ||\n\t\tlen(fn.Type.Params.List[0].Names) > 1 {\n\t\treturn\n\t}\n\n\t// The param must look like a *testing.T or *testing.B.\n\tif !isTestParam(fn.Type.Params.List[0].Type, prefix[:1]) {\n\t\treturn\n\t}\n\n\tif tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 {\n\t\t// Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters.\n\t\t// We have currently decided to also warn before compilation/package loading. This can help users in IDEs.\n\t\tpass.ReportRangef(astutil.RangeOf(tparams.Opening, tparams.Closing),\n\t\t\t\"%s has type parameters: it will not be run by go test as a %sXXX function\",\n\t\t\tfn.Name.Name, prefix)\n\t}\n\n\tif !isTestSuffix(fn.Name.Name[len(prefix):]) {\n\t\tpass.ReportRangef(fn.Name, \"%s has malformed name: first letter after '%s' must not be lowercase\", fn.Name.Name, prefix)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/tests/tests_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage tests_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/tests\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, tests.Analyzer,\n\t\t\"a\",        // loads \"a\", \"a [a.test]\", and \"a.test\"\n\t\t\"b_x_test\", // loads \"b\" and \"b_x_test\"\n\t\t\"divergent\",\n\t\t\"typeparams\",\n\t)\n}\n"
  },
  {
    "path": "go/analysis/passes/timeformat/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package timeformat defines an Analyzer that checks for the use\n// of time.Format or time.Parse calls with a bad format.\n//\n// # Analyzer timeformat\n//\n// timeformat: check for calls of (time.Time).Format or time.Parse with 2006-02-01\n//\n// The timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\n// format. Internationally, \"yyyy-dd-mm\" does not occur in common calendar date\n// standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\npackage timeformat\n"
  },
  {
    "path": "go/analysis/passes/timeformat/testdata/src/a/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the timeformat checker.\n\npackage a\n\nimport (\n\t\"time\"\n\n\t\"b\"\n)\n\nfunc hasError() {\n\ta, _ := time.Parse(\"2006-02-01 15:04:05\", \"2021-01-01 00:00:00\") // want `2006-02-01 should be 2006-01-02`\n\ta.Format(`2006-02-01`)                                           // want `2006-02-01 should be 2006-01-02`\n\ta.Format(\"2006-02-01 15:04:05\")                                  // want `2006-02-01 should be 2006-01-02`\n\n\tconst c = \"2006-02-01\"\n\ta.Format(c) // want `2006-02-01 should be 2006-01-02`\n}\n\nfunc notHasError() {\n\ta, _ := time.Parse(\"2006-01-02 15:04:05\", \"2021-01-01 00:00:00\")\n\ta.Format(\"2006-01-02\")\n\n\tconst c = \"2006-01-02\"\n\ta.Format(c)\n\n\tv := \"2006-02-01\"\n\ta.Format(v) // Allowed though variables.\n\n\tm := map[string]string{\n\t\t\"y\": \"2006-02-01\",\n\t}\n\ta.Format(m[\"y\"])\n\n\ts := []string{\"2006-02-01\"}\n\ta.Format(s[0])\n\n\ta.Format(badFormat())\n\n\to := b.Parse(\"2006-02-01 15:04:05\", \"2021-01-01 00:00:00\")\n\to.Format(\"2006-02-01\")\n}\n\nfunc badFormat() string {\n\treturn \"2006-02-01\"\n}\n"
  },
  {
    "path": "go/analysis/passes/timeformat/testdata/src/a/a.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the timeformat checker.\n\npackage a\n\nimport (\n\t\"time\"\n\n\t\"b\"\n)\n\nfunc hasError() {\n\ta, _ := time.Parse(\"2006-01-02 15:04:05\", \"2021-01-01 00:00:00\") // want `2006-02-01 should be 2006-01-02`\n\ta.Format(`2006-01-02`)                                           // want `2006-02-01 should be 2006-01-02`\n\ta.Format(\"2006-01-02 15:04:05\")                                  // want `2006-02-01 should be 2006-01-02`\n\n\tconst c = \"2006-02-01\"\n\ta.Format(c) // want `2006-02-01 should be 2006-01-02`\n}\n\nfunc notHasError() {\n\ta, _ := time.Parse(\"2006-01-02 15:04:05\", \"2021-01-01 00:00:00\")\n\ta.Format(\"2006-01-02\")\n\n\tconst c = \"2006-01-02\"\n\ta.Format(c)\n\n\tv := \"2006-02-01\"\n\ta.Format(v) // Allowed though variables.\n\n\tm := map[string]string{\n\t\t\"y\": \"2006-02-01\",\n\t}\n\ta.Format(m[\"y\"])\n\n\ts := []string{\"2006-02-01\"}\n\ta.Format(s[0])\n\n\ta.Format(badFormat())\n\n\to := b.Parse(\"2006-02-01 15:04:05\", \"2021-01-01 00:00:00\")\n\to.Format(\"2006-02-01\")\n}\n\nfunc badFormat() string {\n\treturn \"2006-02-01\"\n}\n"
  },
  {
    "path": "go/analysis/passes/timeformat/testdata/src/b/b.go",
    "content": "package b\n\ntype B struct {\n}\n\nfunc Parse(string, string) B {\n\treturn B{}\n}\n\nfunc (b B) Format(string) {\n}\n"
  },
  {
    "path": "go/analysis/passes/timeformat/timeformat.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package timeformat defines an Analyzer that checks for the use\n// of time.Format or time.Parse calls with a bad format.\npackage timeformat\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst badFormat = \"2006-02-01\"\nconst goodFormat = \"2006-01-02\"\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"timeformat\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"timeformat\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Note: (time.Time).Format is a method and can be a typeutil.Callee\n\t// without directly importing \"time\". So we cannot just skip this package\n\t// when !analysis.Imports(pass.Pkg, \"time\").\n\t// TODO(taking): Consider using a prepass to collect typeutil.Callees.\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\tif !typesinternal.IsMethodNamed(obj, \"time\", \"Time\", \"Format\") &&\n\t\t\t!typesinternal.IsFunctionNamed(obj, \"time\", \"Parse\") {\n\t\t\treturn\n\t\t}\n\t\tif len(call.Args) > 0 {\n\t\t\targ := call.Args[0]\n\t\t\tbadAt := badFormatAt(pass.TypesInfo, arg)\n\n\t\t\tif badAt > -1 {\n\t\t\t\t// Check if it's a literal string, otherwise we can't suggest a fix.\n\t\t\t\tif _, ok := arg.(*ast.BasicLit); ok {\n\t\t\t\t\tpos := int(arg.Pos()) + badAt + 1 // +1 to skip the \" or `\n\t\t\t\t\tend := pos + len(badFormat)\n\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     token.Pos(pos),\n\t\t\t\t\t\tEnd:     token.Pos(end),\n\t\t\t\t\t\tMessage: badFormat + \" should be \" + goodFormat,\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage: \"Replace \" + badFormat + \" with \" + goodFormat,\n\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\tPos:     token.Pos(pos),\n\t\t\t\t\t\t\t\tEnd:     token.Pos(end),\n\t\t\t\t\t\t\t\tNewText: []byte(goodFormat),\n\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tpass.Reportf(arg.Pos(), badFormat+\" should be \"+goodFormat)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// badFormatAt return the start of a bad format in e or -1 if no bad format is found.\nfunc badFormatAt(info *types.Info, e ast.Expr) int {\n\ttv, ok := info.Types[e]\n\tif !ok { // no type info, assume good\n\t\treturn -1\n\t}\n\n\tt, ok := tv.Type.(*types.Basic) // sic, no unalias\n\tif !ok || t.Info()&types.IsString == 0 {\n\t\treturn -1\n\t}\n\n\tif tv.Value == nil {\n\t\treturn -1\n\t}\n\n\treturn strings.Index(constant.StringVal(tv.Value), badFormat)\n}\n"
  },
  {
    "path": "go/analysis/passes/timeformat/timeformat_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage timeformat_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/timeformat\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, timeformat.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unmarshal/cmd/unmarshal/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The unmarshal command runs the unmarshal analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/unmarshal\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(unmarshal.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/unmarshal/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The unmarshal package defines an Analyzer that checks for passing\n// non-pointer or non-interface types to unmarshal and decode functions.\n//\n// # Analyzer unmarshal\n//\n// unmarshal: report passing non-pointer or non-interface values to unmarshal\n//\n// The unmarshal analysis reports calls to functions such as json.Unmarshal\n// in which the argument type is not a pointer or an interface.\npackage unmarshal\n"
  },
  {
    "path": "go/analysis/passes/unmarshal/testdata/src/a/a.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the unmarshal checker.\n\npackage testdata\n\nimport (\n\t\"encoding/asn1\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"io\"\n)\n\nfunc _() {\n\ttype t struct {\n\t\ta int\n\t}\n\tvar v t\n\tvar r io.Reader\n\n\tjson.Unmarshal([]byte{}, v) // want \"call of Unmarshal passes non-pointer as second argument\"\n\tjson.Unmarshal([]byte{}, &v)\n\tjson.NewDecoder(r).Decode(v) // want \"call of Decode passes non-pointer\"\n\tjson.NewDecoder(r).Decode(&v)\n\tgob.NewDecoder(r).Decode(v) // want \"call of Decode passes non-pointer\"\n\tgob.NewDecoder(r).Decode(&v)\n\txml.Unmarshal([]byte{}, v) // want \"call of Unmarshal passes non-pointer as second argument\"\n\txml.Unmarshal([]byte{}, &v)\n\txml.NewDecoder(r).Decode(v) // want \"call of Decode passes non-pointer\"\n\txml.NewDecoder(r).Decode(&v)\n\tasn1.Unmarshal([]byte{}, v) // want \"call of Unmarshal passes non-pointer as second argument\"\n\tasn1.Unmarshal([]byte{}, &v)\n\n\tvar p *t\n\tjson.Unmarshal([]byte{}, p)\n\tjson.Unmarshal([]byte{}, *p) // want \"call of Unmarshal passes non-pointer as second argument\"\n\tjson.NewDecoder(r).Decode(p)\n\tjson.NewDecoder(r).Decode(*p) // want \"call of Decode passes non-pointer\"\n\tgob.NewDecoder(r).Decode(p)\n\tgob.NewDecoder(r).Decode(*p) // want \"call of Decode passes non-pointer\"\n\txml.Unmarshal([]byte{}, p)\n\txml.Unmarshal([]byte{}, *p) // want \"call of Unmarshal passes non-pointer as second argument\"\n\txml.NewDecoder(r).Decode(p)\n\txml.NewDecoder(r).Decode(*p) // want \"call of Decode passes non-pointer\"\n\tasn1.Unmarshal([]byte{}, p)\n\tasn1.Unmarshal([]byte{}, *p) // want \"call of Unmarshal passes non-pointer as second argument\"\n\n\tvar i interface{}\n\tjson.Unmarshal([]byte{}, i)\n\tjson.NewDecoder(r).Decode(i)\n\n\tjson.Unmarshal([]byte{}, nil)               // want \"call of Unmarshal passes non-pointer as second argument\"\n\tjson.Unmarshal([]byte{}, []t{})             // want \"call of Unmarshal passes non-pointer as second argument\"\n\tjson.Unmarshal([]byte{}, map[string]int{})  // want \"call of Unmarshal passes non-pointer as second argument\"\n\tjson.NewDecoder(r).Decode(nil)              // want \"call of Decode passes non-pointer\"\n\tjson.NewDecoder(r).Decode([]t{})            // want \"call of Decode passes non-pointer\"\n\tjson.NewDecoder(r).Decode(map[string]int{}) // want \"call of Decode passes non-pointer\"\n\n\tjson.Unmarshal(func() ([]byte, interface{}) { return []byte{}, v }())\n}\n"
  },
  {
    "path": "go/analysis/passes/unmarshal/testdata/src/typeparams/typeparams.go",
    "content": "package typeparams\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\nfunc unmarshalT[T any](data []byte) T {\n\tvar x T\n\tjson.Unmarshal(data, x)\n\treturn x\n}\n\nfunc unmarshalT2[T any](data []byte, t T) {\n    json.Unmarshal(data, t)\n}\n\nfunc main() {\n\tx := make(map[string]interface{})\n\tunmarshalT2([]byte(`{\"a\":1}`), &x)\n\tfmt.Println(x)\n}"
  },
  {
    "path": "go/analysis/passes/unmarshal/unmarshal.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unmarshal\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unmarshal\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unmarshal\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tswitch pass.Pkg.Path() {\n\tcase \"encoding/gob\", \"encoding/json\", \"encoding/xml\", \"encoding/asn1\":\n\t\t// These packages know how to use their own APIs.\n\t\t// Sometimes they are testing what happens to incorrect programs.\n\t\treturn nil, nil\n\t}\n\n\t// Note: (*\"encoding/json\".Decoder).Decode, (* \"encoding/gob\".Decoder).Decode\n\t// and (* \"encoding/xml\".Decoder).Decode are methods and can be a typeutil.Callee\n\t// without directly importing their packages. So we cannot just skip this package\n\t// when !analysis.Imports(pass.Pkg, \"encoding/...\").\n\t// TODO(taking): Consider using a prepass to collect typeutil.Callees.\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tfn := typeutil.StaticCallee(pass.TypesInfo, call)\n\t\tif fn == nil {\n\t\t\treturn // not a static call\n\t\t}\n\n\t\t// Classify the callee (without allocating memory).\n\t\targidx := -1\n\n\t\trecv := fn.Signature().Recv()\n\t\tif fn.Name() == \"Unmarshal\" && recv == nil {\n\t\t\t// \"encoding/json\".Unmarshal\n\t\t\t// \"encoding/xml\".Unmarshal\n\t\t\t// \"encoding/asn1\".Unmarshal\n\t\t\tswitch fn.Pkg().Path() {\n\t\t\tcase \"encoding/json\", \"encoding/xml\", \"encoding/asn1\":\n\t\t\t\targidx = 1 // func([]byte, interface{})\n\t\t\t}\n\t\t} else if fn.Name() == \"Decode\" && recv != nil {\n\t\t\t// (*\"encoding/json\".Decoder).Decode\n\t\t\t// (* \"encoding/gob\".Decoder).Decode\n\t\t\t// (* \"encoding/xml\".Decoder).Decode\n\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\tif tname := named.Obj(); tname.Name() == \"Decoder\" {\n\t\t\t\tswitch tname.Pkg().Path() {\n\t\t\t\tcase \"encoding/json\", \"encoding/xml\", \"encoding/gob\":\n\t\t\t\t\targidx = 0 // func(interface{})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif argidx < 0 {\n\t\t\treturn // not a function we are interested in\n\t\t}\n\n\t\tif len(call.Args) < argidx+1 {\n\t\t\treturn // not enough arguments, e.g. called with return values of another function\n\t\t}\n\n\t\tt := pass.TypesInfo.Types[call.Args[argidx]].Type\n\t\tswitch t.Underlying().(type) {\n\t\tcase *types.Pointer, *types.Interface, *types.TypeParam:\n\t\t\treturn\n\t\t}\n\n\t\tswitch argidx {\n\t\tcase 0:\n\t\t\tpass.Reportf(call.Lparen, \"call of %s passes non-pointer\", fn.Name())\n\t\tcase 1:\n\t\t\tpass.Reportf(call.Lparen, \"call of %s passes non-pointer as second argument\", fn.Name())\n\t\t}\n\t})\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/analysis/passes/unmarshal/unmarshal_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unmarshal_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/unmarshal\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, unmarshal.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unreachable/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unreachable defines an Analyzer that checks for unreachable code.\n//\n// # Analyzer unreachable\n//\n// unreachable: check for unreachable code\n//\n// The unreachable analyzer finds statements that execution can never reach\n// because they are preceded by a return statement, a call to panic, an\n// infinite loop, or similar constructs.\npackage unreachable\n"
  },
  {
    "path": "go/analysis/passes/unreachable/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unreachable\n\n// This file produces masses of errors from the type checker due to\n// missing returns statements and other things.\n\ntype T int\n\nvar x interface{}\nvar c chan int\n\nfunc external() int // ok\n\nfunc _() int {\n}\n\nfunc _() int {\n\tprint(1)\n}\n\nfunc _() int {\n\tprint(1)\n\treturn 2\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tgoto L\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tpanic(2)\n\tprintln() // want \"unreachable code\"\n}\n\n// but only builtin panic\nfunc _() int {\n\tvar panic = func(int) {}\n\tprint(1)\n\tpanic(2)\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t\tprintln() // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\treturn 2\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tgoto L\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tpanic(2)\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 2 {\n\t\tpanic(3)\n\t} else {\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\n// if-else chain missing final else is not okay, even if the\n// conditions cover every possible case.\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x != nil {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 1 {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor {\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t\tprintln() // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tcontinue\n\t\t\tprintln() // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tfor {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tfor {\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t}\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tfor {\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor x == nil {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor x == nil {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor x == nil {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor true {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor true {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor true {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\tselect {}\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tgoto L // want \"unreachable code\"\n\tcase c <- 1:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tdefault:\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tbreak L\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(1)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 2:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tbreak L // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\t\tbreak // want \"unreachable code\"\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase float64:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tbreak L // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\t\tbreak // want \"unreachable code\"\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\n// again, but without the leading print(1).\n// testing that everything works when the terminating statement is first.\n\nfunc _() int {\n\tprintln() // ok\n}\n\nfunc _() int {\n\treturn 2\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\tgoto L\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\tpanic(2)\n\tprintln() // want \"unreachable code\"\n}\n\n// but only builtin panic\nfunc _() int {\n\tvar panic = func(int) {}\n\tpanic(2)\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nfunc _() int {\n\treturn 2\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tgoto L\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tpanic(2)\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\n// again, with func literals\n\nvar _ = func() int {\n}\n\nvar _ = func() int {\n\tprint(1)\n}\n\nvar _ = func() int {\n\tprint(1)\n\treturn 2\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tgoto L\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tpanic(2)\n\tprintln() // want \"unreachable code\"\n}\n\n// but only builtin panic\nvar _ = func() int {\n\tvar panic = func(int) {}\n\tprint(1)\n\tpanic(2)\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t\tprintln() // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\treturn 2\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tgoto L\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tpanic(2)\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n\t{ // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 2 {\n\t\tpanic(3)\n\t} else {\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\n// if-else chain missing final else is not okay, even if the\n// conditions cover every possible case.\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x != nil {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 1 {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor {\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t\tprintln() // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tcontinue\n\t\t\tprintln() // want \"unreachable code\"\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor {\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t}\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tfor {\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor x == nil {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor x == nil {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor x == nil {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor true {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor true {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor true {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\tselect {}\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tgoto L // want \"unreachable code\"\n\tcase c <- 1:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tdefault:\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tbreak L\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(1)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t\tbreak // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 2:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tbreak L // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\t\tbreak // want \"unreachable code\"\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase float64:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t\tbreak L // want \"unreachable code\"\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\t\tbreak // want \"unreachable code\"\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\n// again, but without the leading print(1).\n// testing that everything works when the terminating statement is first.\n\nvar _ = func() int {\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\treturn 2\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\tgoto L\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\tpanic(2)\n\tprintln() // want \"unreachable code\"\n}\n\n// but only builtin panic\nvar _ = func() int {\n\tvar panic = func(int) {}\n\tpanic(2)\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t\tprintln() // want \"unreachable code\"\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // want \"unreachable code\"\n}\n\nvar _ = func() int {\n\treturn 2\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tgoto L\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tpanic(2)\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t\t{ // want \"unreachable code\"\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n\t{ // want \"unreachable code\"\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t// Empty switch tag with non-bool case value used to panic.\n\tswitch {\n\tcase 1:\n\t\tprintln()\n\t}\n\tprintln()\n}\n"
  },
  {
    "path": "go/analysis/passes/unreachable/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unreachable\n\n// This file produces masses of errors from the type checker due to\n// missing returns statements and other things.\n\ntype T int\n\nvar x interface{}\nvar c chan int\n\nfunc external() int // ok\n\nfunc _() int {\n}\n\nfunc _() int {\n\tprint(1)\n}\n\nfunc _() int {\n\tprint(1)\n\treturn 2\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tgoto L\n}\n\nfunc _() int {\n\tprint(1)\n\tpanic(2)\n}\n\n// but only builtin panic\nfunc _() int {\n\tvar panic = func(int) {}\n\tprint(1)\n\tpanic(2)\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\treturn 2\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tgoto L\n}\n\nfunc _() int {\n\tprint(1)\n\tpanic(2)\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tpanic(3)\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 2 {\n\t\tpanic(3)\n\t} else {\n\t\tgoto L\n\t}\n}\n\n// if-else chain missing final else is not okay, even if the\n// conditions cover every possible case.\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x != nil {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 1 {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor {\n\t}\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tfor {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tfor {\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor {\n\t\tfor {\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tfor {\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor x == nil {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor x == nil {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor x == nil {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tfor true {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor true {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tfor true {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tdefault:\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tbreak L\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(1)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 2:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase float64:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\n// again, but without the leading print(1).\n// testing that everything works when the terminating statement is first.\n\nfunc _() int {\n\tprintln() // ok\n}\n\nfunc _() int {\n\treturn 2\n}\n\nfunc _() int {\nL:\n\tgoto L\n}\n\nfunc _() int {\n\tpanic(2)\n}\n\n// but only builtin panic\nfunc _() int {\n\tvar panic = func(int) {}\n\tpanic(2)\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n}\n\nfunc _() int {\n\treturn 2\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\tgoto L\n\tprintln() // ok\n}\n\nfunc _() int {\n\tpanic(2)\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\n// again, with func literals\n\nvar _ = func() int {\n}\n\nvar _ = func() int {\n\tprint(1)\n}\n\nvar _ = func() int {\n\tprint(1)\n\treturn 2\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tgoto L\n}\n\nvar _ = func() int {\n\tprint(1)\n\tpanic(2)\n}\n\n// but only builtin panic\nvar _ = func() int {\n\tvar panic = func(int) {}\n\tprint(1)\n\tpanic(2)\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\treturn 2\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tgoto L\n}\n\nvar _ = func() int {\n\tprint(1)\n\tpanic(2)\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tprint(1)\n\t\treturn 2\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tprint(1)\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tpanic(3)\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else {\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 2 {\n\t\tpanic(3)\n\t} else {\n\t\tgoto L\n\t}\n}\n\n// if-else chain missing final else is not okay, even if the\n// conditions cover every possible case.\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x != nil {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tif x == nil {\n\t\tpanic(2)\n\t} else if x == 1 {\n\t\treturn 0\n\t} else if x != 1 {\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor {\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tfor {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor {\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor {\n\t\tfor {\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tfor {\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor x == nil {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor x == nil {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor x == nil {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tfor true {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor true {\n\t\tfor {\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tfor true {\n\tL:\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t}\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tprint(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tdefault:\n\t\tbreak\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tselect {\n\tcase <-c:\n\t\tprint(2)\n\t\tpanic(\"abc\")\n\tcase c <- 1:\n\t\tprint(2)\n\t\tbreak L\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tselect {\n\tcase <-c:\n\t\tprint(1)\n\t\tpanic(\"abc\")\n\tdefault:\n\t\tselect {}\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 2:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfallthrough\n\tcase 2:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x {\n\tdefault:\n\t\treturn 4\n\tcase 1:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x {\n\tcase 1:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tdefault:\n\t\treturn 4\n\t}\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch {\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase float64:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfallthrough\n\tcase float64:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\n\tswitch x.(type) {\n\tdefault:\n\t\treturn 4\n\tcase int:\n\t\tprint(2)\n\t\tpanic(3)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tprint(1)\nL:\n\tswitch x.(type) {\n\tcase int:\n\t\tprint(2)\n\t\tfor {\n\t\t\tbreak L\n\t\t}\n\tdefault:\n\t\treturn 4\n\t}\n\tprintln() // ok\n}\n\n// again, but without the leading print(1).\n// testing that everything works when the terminating statement is first.\n\nvar _ = func() int {\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\treturn 2\n}\n\nvar _ = func() int {\nL:\n\tgoto L\n}\n\nvar _ = func() int {\n\tpanic(2)\n}\n\n// but only builtin panic\nvar _ = func() int {\n\tvar panic = func(int) {}\n\tpanic(2)\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n}\n\nvar _ = func() int {\n\treturn 2\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\tgoto L\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\tpanic(2)\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\treturn 2\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\nL:\n\t{\n\t\tgoto L\n\t}\n\tprintln() // ok\n}\n\nvar _ = func() int {\n\t{\n\t\tpanic(2)\n\t}\n\tprintln() // ok\n}\n\nfunc _() int {\n\t// Empty switch tag with non-bool case value used to panic.\n\tswitch {\n\tcase 1:\n\t\tprintln()\n\t}\n\tprintln()\n}\n"
  },
  {
    "path": "go/analysis/passes/unreachable/unreachable.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unreachable\n\n// TODO(adonovan): use the new cfg package, which is more precise.\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"log\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"unreachable\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"unreachable\"),\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable\",\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRunDespiteErrors: true,\n\tRun:              run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.FuncLit)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tvar body *ast.BlockStmt\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tbody = n.Body\n\t\tcase *ast.FuncLit:\n\t\t\tbody = n.Body\n\t\t}\n\t\tif body == nil {\n\t\t\treturn\n\t\t}\n\t\td := &deadState{\n\t\t\tpass:     pass,\n\t\t\thasBreak: make(map[ast.Stmt]bool),\n\t\t\thasGoto:  make(map[string]bool),\n\t\t\tlabels:   make(map[string]ast.Stmt),\n\t\t}\n\t\td.findLabels(body)\n\t\td.reachable = true\n\t\td.findDead(body)\n\t})\n\treturn nil, nil\n}\n\ntype deadState struct {\n\tpass        *analysis.Pass\n\thasBreak    map[ast.Stmt]bool\n\thasGoto     map[string]bool\n\tlabels      map[string]ast.Stmt\n\tbreakTarget ast.Stmt\n\n\treachable bool\n}\n\n// findLabels gathers information about the labels defined and used by stmt\n// and about which statements break, whether a label is involved or not.\nfunc (d *deadState) findLabels(stmt ast.Stmt) {\n\tswitch x := stmt.(type) {\n\tdefault:\n\t\tlog.Fatalf(\"%s: internal error in findLabels: unexpected statement %T\", d.pass.Fset.Position(x.Pos()), x)\n\n\tcase *ast.AssignStmt,\n\t\t*ast.BadStmt,\n\t\t*ast.DeclStmt,\n\t\t*ast.DeferStmt,\n\t\t*ast.EmptyStmt,\n\t\t*ast.ExprStmt,\n\t\t*ast.GoStmt,\n\t\t*ast.IncDecStmt,\n\t\t*ast.ReturnStmt,\n\t\t*ast.SendStmt:\n\t\t// no statements inside\n\n\tcase *ast.BlockStmt:\n\t\tfor _, stmt := range x.List {\n\t\t\td.findLabels(stmt)\n\t\t}\n\n\tcase *ast.BranchStmt:\n\t\tswitch x.Tok {\n\t\tcase token.GOTO:\n\t\t\tif x.Label != nil {\n\t\t\t\td.hasGoto[x.Label.Name] = true\n\t\t\t}\n\n\t\tcase token.BREAK:\n\t\t\tstmt := d.breakTarget\n\t\t\tif x.Label != nil {\n\t\t\t\tstmt = d.labels[x.Label.Name]\n\t\t\t}\n\t\t\tif stmt != nil {\n\t\t\t\td.hasBreak[stmt] = true\n\t\t\t}\n\t\t}\n\n\tcase *ast.IfStmt:\n\t\td.findLabels(x.Body)\n\t\tif x.Else != nil {\n\t\t\td.findLabels(x.Else)\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\td.labels[x.Label.Name] = x.Stmt\n\t\td.findLabels(x.Stmt)\n\n\t// These cases are all the same, but the x.Body only works\n\t// when the specific type of x is known, so the cases cannot\n\t// be merged.\n\tcase *ast.ForStmt:\n\t\touter := d.breakTarget\n\t\td.breakTarget = x\n\t\td.findLabels(x.Body)\n\t\td.breakTarget = outer\n\n\tcase *ast.RangeStmt:\n\t\touter := d.breakTarget\n\t\td.breakTarget = x\n\t\td.findLabels(x.Body)\n\t\td.breakTarget = outer\n\n\tcase *ast.SelectStmt:\n\t\touter := d.breakTarget\n\t\td.breakTarget = x\n\t\td.findLabels(x.Body)\n\t\td.breakTarget = outer\n\n\tcase *ast.SwitchStmt:\n\t\touter := d.breakTarget\n\t\td.breakTarget = x\n\t\td.findLabels(x.Body)\n\t\td.breakTarget = outer\n\n\tcase *ast.TypeSwitchStmt:\n\t\touter := d.breakTarget\n\t\td.breakTarget = x\n\t\td.findLabels(x.Body)\n\t\td.breakTarget = outer\n\n\tcase *ast.CommClause:\n\t\tfor _, stmt := range x.Body {\n\t\t\td.findLabels(stmt)\n\t\t}\n\n\tcase *ast.CaseClause:\n\t\tfor _, stmt := range x.Body {\n\t\t\td.findLabels(stmt)\n\t\t}\n\t}\n}\n\n// findDead walks the statement looking for dead code.\n// If d.reachable is false on entry, stmt itself is dead.\n// When findDead returns, d.reachable tells whether the\n// statement following stmt is reachable.\nfunc (d *deadState) findDead(stmt ast.Stmt) {\n\t// Is this a labeled goto target?\n\t// If so, assume it is reachable due to the goto.\n\t// This is slightly conservative, in that we don't\n\t// check that the goto is reachable, so\n\t//\tL: goto L\n\t// will not provoke a warning.\n\t// But it's good enough.\n\tif x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {\n\t\td.reachable = true\n\t}\n\n\tif !d.reachable {\n\t\tswitch stmt.(type) {\n\t\tcase *ast.EmptyStmt:\n\t\t\t// do not warn about unreachable empty statements\n\t\tdefault:\n\t\t\tvar (\n\t\t\t\tinspect    = d.pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\t\t\tcurStmt, _ = inspect.Root().FindNode(stmt)\n\t\t\t\ttokFile    = d.pass.Fset.File(stmt.Pos())\n\t\t\t)\n\t\t\t// (This call to pass.Report is a frequent source\n\t\t\t// of diagnostics beyond EOF in a truncated file;\n\t\t\t// see #71659.)\n\t\t\td.pass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     stmt.Pos(),\n\t\t\t\tEnd:     stmt.End(),\n\t\t\t\tMessage: \"unreachable code\",\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   \"Remove\",\n\t\t\t\t\tTextEdits: refactor.DeleteStmt(tokFile, curStmt),\n\t\t\t\t}},\n\t\t\t})\n\t\t\td.reachable = true // silence error about next statement\n\t\t}\n\t}\n\n\tswitch x := stmt.(type) {\n\tdefault:\n\t\tlog.Fatalf(\"%s: internal error in findDead: unexpected statement %T\", d.pass.Fset.Position(x.Pos()), x)\n\n\tcase *ast.AssignStmt,\n\t\t*ast.BadStmt,\n\t\t*ast.DeclStmt,\n\t\t*ast.DeferStmt,\n\t\t*ast.EmptyStmt,\n\t\t*ast.GoStmt,\n\t\t*ast.IncDecStmt,\n\t\t*ast.SendStmt:\n\t\t// no control flow\n\n\tcase *ast.BlockStmt:\n\t\tfor _, stmt := range x.List {\n\t\t\td.findDead(stmt)\n\t\t}\n\n\tcase *ast.BranchStmt:\n\t\tswitch x.Tok {\n\t\tcase token.BREAK, token.GOTO, token.FALLTHROUGH:\n\t\t\td.reachable = false\n\t\tcase token.CONTINUE:\n\t\t\t// NOTE: We accept \"continue\" statements as terminating.\n\t\t\t// They are not necessary in the spec definition of terminating,\n\t\t\t// because a continue statement cannot be the final statement\n\t\t\t// before a return. But for the more general problem of syntactically\n\t\t\t// identifying dead code, continue redirects control flow just\n\t\t\t// like the other terminating statements.\n\t\t\td.reachable = false\n\t\t}\n\n\tcase *ast.ExprStmt:\n\t\t// Call to panic?\n\t\tcall, ok := x.X.(*ast.CallExpr)\n\t\tif ok {\n\t\t\tname, ok := call.Fun.(*ast.Ident)\n\t\t\tif ok && name.Name == \"panic\" && name.Obj == nil {\n\t\t\t\td.reachable = false\n\t\t\t}\n\t\t}\n\n\tcase *ast.ForStmt:\n\t\td.findDead(x.Body)\n\t\td.reachable = x.Cond != nil || d.hasBreak[x]\n\n\tcase *ast.IfStmt:\n\t\td.findDead(x.Body)\n\t\tif x.Else != nil {\n\t\t\tr := d.reachable\n\t\t\td.reachable = true\n\t\t\td.findDead(x.Else)\n\t\t\td.reachable = d.reachable || r\n\t\t} else {\n\t\t\t// might not have executed if statement\n\t\t\td.reachable = true\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\td.findDead(x.Stmt)\n\n\tcase *ast.RangeStmt:\n\t\td.findDead(x.Body)\n\t\td.reachable = true\n\n\tcase *ast.ReturnStmt:\n\t\td.reachable = false\n\n\tcase *ast.SelectStmt:\n\t\t// NOTE: Unlike switch and type switch below, we don't care\n\t\t// whether a select has a default, because a select without a\n\t\t// default blocks until one of the cases can run. That's different\n\t\t// from a switch without a default, which behaves like it has\n\t\t// a default with an empty body.\n\t\tanyReachable := false\n\t\tfor _, comm := range x.Body.List {\n\t\t\td.reachable = true\n\t\t\tfor _, stmt := range comm.(*ast.CommClause).Body {\n\t\t\t\td.findDead(stmt)\n\t\t\t}\n\t\t\tanyReachable = anyReachable || d.reachable\n\t\t}\n\t\td.reachable = anyReachable || d.hasBreak[x]\n\n\tcase *ast.SwitchStmt:\n\t\tanyReachable := false\n\t\thasDefault := false\n\t\tfor _, cas := range x.Body.List {\n\t\t\tcc := cas.(*ast.CaseClause)\n\t\t\tif cc.List == nil {\n\t\t\t\thasDefault = true\n\t\t\t}\n\t\t\td.reachable = true\n\t\t\tfor _, stmt := range cc.Body {\n\t\t\t\td.findDead(stmt)\n\t\t\t}\n\t\t\tanyReachable = anyReachable || d.reachable\n\t\t}\n\t\td.reachable = anyReachable || d.hasBreak[x] || !hasDefault\n\n\tcase *ast.TypeSwitchStmt:\n\t\tanyReachable := false\n\t\thasDefault := false\n\t\tfor _, cas := range x.Body.List {\n\t\t\tcc := cas.(*ast.CaseClause)\n\t\t\tif cc.List == nil {\n\t\t\t\thasDefault = true\n\t\t\t}\n\t\t\td.reachable = true\n\t\t\tfor _, stmt := range cc.Body {\n\t\t\t\td.findDead(stmt)\n\t\t\t}\n\t\t\tanyReachable = anyReachable || d.reachable\n\t\t}\n\t\td.reachable = anyReachable || d.hasBreak[x] || !hasDefault\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/unreachable/unreachable_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unreachable_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/unreachable\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, unreachable.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unsafeptr defines an Analyzer that checks for invalid\n// conversions of uintptr to unsafe.Pointer.\n//\n// # Analyzer unsafeptr\n//\n// unsafeptr: check for invalid conversions of uintptr to unsafe.Pointer\n//\n// The unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer\n// to convert integers to pointers. A conversion from uintptr to\n// unsafe.Pointer is invalid if it implies that there is a uintptr-typed\n// word in memory that holds a pointer value, because that word will be\n// invisible to stack copying and to the garbage collector.\npackage unsafeptr\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/testdata/src/a/a.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"reflect\"\n\t\"unsafe\"\n)\n\nfunc f() {\n\tvar x unsafe.Pointer\n\tvar y uintptr\n\tx = unsafe.Pointer(y) // want \"possible misuse of unsafe.Pointer\"\n\ty = uintptr(x)\n\n\t// only allowed pointer arithmetic is ptr +/-/&^ num.\n\t// num+ptr is technically okay but still flagged: write ptr+num instead.\n\tx = unsafe.Pointer(uintptr(x) + 1)\n\tx = unsafe.Pointer(((uintptr((x))) + 1))\n\tx = unsafe.Pointer(1 + uintptr(x))          // want \"possible misuse of unsafe.Pointer\"\n\tx = unsafe.Pointer(uintptr(x) + uintptr(x)) // want \"possible misuse of unsafe.Pointer\"\n\tx = unsafe.Pointer(uintptr(x) - 1)\n\tx = unsafe.Pointer(1 - uintptr(x)) // want \"possible misuse of unsafe.Pointer\"\n\tx = unsafe.Pointer(uintptr(x) &^ 3)\n\tx = unsafe.Pointer(1 &^ uintptr(x)) // want \"possible misuse of unsafe.Pointer\"\n\n\t// certain uses of reflect are okay\n\tvar v reflect.Value\n\tx = unsafe.Pointer(v.Pointer())\n\tx = unsafe.Pointer(v.Pointer() + 1) // want \"possible misuse of unsafe.Pointer\"\n\tx = unsafe.Pointer(v.UnsafeAddr())\n\tx = unsafe.Pointer((v.UnsafeAddr()))\n\tvar s1 *reflect.StringHeader\n\tx = unsafe.Pointer(s1.Data)\n\tx = unsafe.Pointer(s1.Data + 1) // want \"possible misuse of unsafe.Pointer\"\n\tvar s2 *reflect.SliceHeader\n\tx = unsafe.Pointer(s2.Data)\n\tvar s3 reflect.StringHeader\n\tx = unsafe.Pointer(s3.Data) // want \"possible misuse of unsafe.Pointer\"\n\tvar s4 reflect.SliceHeader\n\tx = unsafe.Pointer(s4.Data) // want \"possible misuse of unsafe.Pointer\"\n\n\t// but only in reflect\n\tvar vv V\n\tx = unsafe.Pointer(vv.Pointer())    // want \"possible misuse of unsafe.Pointer\"\n\tx = unsafe.Pointer(vv.UnsafeAddr()) // want \"possible misuse of unsafe.Pointer\"\n\tvar ss1 *StringHeader\n\tx = unsafe.Pointer(ss1.Data) // want \"possible misuse of unsafe.Pointer\"\n\tvar ss2 *SliceHeader\n\tx = unsafe.Pointer(ss2.Data) // want \"possible misuse of unsafe.Pointer\"\n\n}\n\ntype V interface {\n\tPointer() uintptr\n\tUnsafeAddr() uintptr\n}\n\ntype StringHeader struct {\n\tData uintptr\n}\n\ntype SliceHeader struct {\n\tData uintptr\n}\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/testdata/src/a/issue40701.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"reflect\"\n\t\"unsafe\"\n)\n\n// Explicitly allocating a variable of type reflect.SliceHeader.\nfunc _(p *byte, n int) []byte {\n\tvar sh reflect.SliceHeader\n\tsh.Data = uintptr(unsafe.Pointer(p))\n\tsh.Len = n\n\tsh.Cap = n\n\treturn *(*[]byte)(unsafe.Pointer(&sh)) // want \"possible misuse of reflect.SliceHeader\"\n}\n\n// Implicitly allocating a variable of type reflect.SliceHeader.\nfunc _(p *byte, n int) []byte {\n\treturn *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ // want \"possible misuse of reflect.SliceHeader\"\n\t\tData: uintptr(unsafe.Pointer(p)),\n\t\tLen:  n,\n\t\tCap:  n,\n\t}))\n}\n\n// Use reflect.StringHeader as a composite literal value.\nfunc _(p *byte, n int) []byte {\n\tvar res []byte\n\t*(*reflect.StringHeader)(unsafe.Pointer(&res)) = reflect.StringHeader{ // want \"possible misuse of reflect.StringHeader\"\n\t\tData: uintptr(unsafe.Pointer(p)),\n\t\tLen:  n,\n\t}\n\treturn res\n}\n\nfunc _() {\n\t// don't crash when obj.Pkg() == nil\n\tvar err error\n\t_ = &err\n}\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport \"unsafe\"\n\nfunc _[IntPtr ~uintptr, RealPtr *T, AnyPtr uintptr | *T, T any]() {\n\tvar (\n\t\ti IntPtr\n\t\tr RealPtr\n\t\ta AnyPtr\n\t)\n\t_ = unsafe.Pointer(i)          // incorrect, but not detected\n\t_ = unsafe.Pointer(i + i)      // incorrect, but not detected\n\t_ = unsafe.Pointer(1 + i)      // incorrect, but not detected\n\t_ = unsafe.Pointer(uintptr(i)) // want \"possible misuse of unsafe.Pointer\"\n\t_ = unsafe.Pointer(r)\n\t_ = unsafe.Pointer(a) // possibly incorrect, but not detected\n}\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/unsafeptr.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unsafeptr defines an Analyzer that checks for invalid\n// conversions of uintptr to unsafe.Pointer.\npackage unsafeptr\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unsafeptr\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unsafeptr\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t\t(*ast.StarExpr)(nil),\n\t\t(*ast.UnaryExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tswitch x := n.(type) {\n\t\tcase *ast.CallExpr:\n\t\t\tif len(x.Args) == 1 &&\n\t\t\t\thasBasicType(pass.TypesInfo, x.Fun, types.UnsafePointer) &&\n\t\t\t\thasBasicType(pass.TypesInfo, x.Args[0], types.Uintptr) &&\n\t\t\t\t!isSafeUintptr(pass.TypesInfo, x.Args[0]) {\n\t\t\t\tpass.ReportRangef(x, \"possible misuse of unsafe.Pointer\")\n\t\t\t}\n\t\tcase *ast.StarExpr:\n\t\t\tif t := pass.TypesInfo.Types[x].Type; isReflectHeader(t) {\n\t\t\t\tpass.ReportRangef(x, \"possible misuse of %s\", t)\n\t\t\t}\n\t\tcase *ast.UnaryExpr:\n\t\t\tif x.Op != token.AND {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif t := pass.TypesInfo.Types[x.X].Type; isReflectHeader(t) {\n\t\t\t\tpass.ReportRangef(x, \"possible misuse of %s\", t)\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// isSafeUintptr reports whether x - already known to be a uintptr -\n// is safe to convert to unsafe.Pointer.\nfunc isSafeUintptr(info *types.Info, x ast.Expr) bool {\n\t// Check unsafe.Pointer safety rules according to\n\t// https://golang.org/pkg/unsafe/#Pointer.\n\n\tswitch x := ast.Unparen(x).(type) {\n\tcase *ast.SelectorExpr:\n\t\t// \"(6) Conversion of a reflect.SliceHeader or\n\t\t// reflect.StringHeader Data field to or from Pointer.\"\n\t\tif x.Sel.Name != \"Data\" {\n\t\t\tbreak\n\t\t}\n\t\t// reflect.SliceHeader and reflect.StringHeader are okay,\n\t\t// but only if they are pointing at a real slice or string.\n\t\t// It's not okay to do:\n\t\t//\tvar x SliceHeader\n\t\t//\tx.Data = uintptr(unsafe.Pointer(...))\n\t\t//\t... use x ...\n\t\t//\tp := unsafe.Pointer(x.Data)\n\t\t// because in the middle the garbage collector doesn't\n\t\t// see x.Data as a pointer and so x.Data may be dangling\n\t\t// by the time we get to the conversion at the end.\n\t\t// For now approximate by saying that *Header is okay\n\t\t// but Header is not.\n\t\tpt, ok := types.Unalias(info.Types[x.X].Type).(*types.Pointer)\n\t\tif ok && isReflectHeader(pt.Elem()) {\n\t\t\treturn true\n\t\t}\n\n\tcase *ast.CallExpr:\n\t\t// \"(5) Conversion of the result of reflect.Value.Pointer or\n\t\t// reflect.Value.UnsafeAddr from uintptr to Pointer.\"\n\t\tif len(x.Args) != 0 {\n\t\t\tbreak\n\t\t}\n\t\tsel, ok := x.Fun.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tswitch sel.Sel.Name {\n\t\tcase \"Pointer\", \"UnsafeAddr\":\n\t\t\tif typesinternal.IsTypeNamed(info.Types[sel.X].Type, \"reflect\", \"Value\") {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\t// \"(3) Conversion of a Pointer to a uintptr and back, with arithmetic.\"\n\treturn isSafeArith(info, x)\n}\n\n// isSafeArith reports whether x is a pointer arithmetic expression that is safe\n// to convert to unsafe.Pointer.\nfunc isSafeArith(info *types.Info, x ast.Expr) bool {\n\tswitch x := ast.Unparen(x).(type) {\n\tcase *ast.CallExpr:\n\t\t// Base case: initial conversion from unsafe.Pointer to uintptr.\n\t\treturn len(x.Args) == 1 &&\n\t\t\thasBasicType(info, x.Fun, types.Uintptr) &&\n\t\t\thasBasicType(info, x.Args[0], types.UnsafePointer)\n\n\tcase *ast.BinaryExpr:\n\t\t// \"It is valid both to add and to subtract offsets from a\n\t\t// pointer in this way. It is also valid to use &^ to round\n\t\t// pointers, usually for alignment.\"\n\t\tswitch x.Op {\n\t\tcase token.ADD, token.SUB, token.AND_NOT:\n\t\t\t// TODO(mdempsky): Match compiler\n\t\t\t// semantics. ADD allows a pointer on either\n\t\t\t// side; SUB and AND_NOT don't care about RHS.\n\t\t\treturn isSafeArith(info, x.X) && !isSafeArith(info, x.Y)\n\t\t}\n\t}\n\n\treturn false\n}\n\n// hasBasicType reports whether x's type is a types.Basic with the given kind.\nfunc hasBasicType(info *types.Info, x ast.Expr, kind types.BasicKind) bool {\n\tt := info.Types[x].Type\n\tif t != nil {\n\t\tt = t.Underlying()\n\t}\n\tb, ok := t.(*types.Basic)\n\treturn ok && b.Kind() == kind\n}\n\n// isReflectHeader reports whether t is reflect.SliceHeader or reflect.StringHeader.\nfunc isReflectHeader(t types.Type) bool {\n\treturn typesinternal.IsTypeNamed(t, \"reflect\", \"SliceHeader\", \"StringHeader\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unsafeptr/unsafeptr_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unsafeptr_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/unsafeptr\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, unsafeptr.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/cmd/unusedresult/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The unusedresult command applies the golang.org/x/tools/go/analysis/passes/unusedresult\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/unusedresult\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(unusedresult.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedresult defines an analyzer that checks for unused\n// results of calls to certain pure functions.\n//\n// # Analyzer unusedresult\n//\n// unusedresult: check for unused results of calls to some functions\n//\n// Some functions like fmt.Errorf return a result and have no side\n// effects, so it is always a mistake to discard the result. Other\n// functions may return an error that must not be ignored, or a cleanup\n// operation that must be called. This analyzer reports calls to\n// functions like these when the result of the call is ignored.\n//\n// The set of functions may be controlled using flags.\npackage unusedresult\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/testdata/src/a/a.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t. \"fmt\"\n)\n\nfunc _() {\n\tfmt.Errorf(\"\") // want \"result of fmt.Errorf call not used\"\n\t_ = fmt.Errorf(\"\")\n\n\terrors.New(\"\") // want \"result of errors.New call not used\"\n\n\terr := errors.New(\"\")\n\terr.Error() // want `result of \\(error\\).Error call not used`\n\n\tvar buf bytes.Buffer\n\tbuf.String() // want `result of \\(\\*bytes.Buffer\\).String call not used`\n\n\tfmt.Sprint(\"\")  // want \"result of fmt.Sprint call not used\"\n\tfmt.Sprintf(\"\") // want \"result of fmt.Sprintf call not used\"\n\n\tSprint(\"\")  // want \"result of fmt.Sprint call not used\"\n\tSprintf(\"\") // want \"result of fmt.Sprintf call not used\"\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"typeparams/userdefs\"\n)\n\nfunc _[T any]() {\n\tfmt.Errorf(\"\") // want \"result of fmt.Errorf call not used\"\n\t_ = fmt.Errorf(\"\")\n\n\terrors.New(\"\") // want \"result of errors.New call not used\"\n\n\terr := errors.New(\"\")\n\terr.Error() // want `result of \\(error\\).Error call not used`\n\n\tvar buf bytes.Buffer\n\tbuf.String() // want `result of \\(\\*bytes.Buffer\\).String call not used`\n\n\tfmt.Sprint(\"\")  // want \"result of fmt.Sprint call not used\"\n\tfmt.Sprintf(\"\") // want \"result of fmt.Sprintf call not used\"\n\n\tuserdefs.MustUse[int](1) // want \"result of typeparams/userdefs.MustUse call not used\"\n\t_ = userdefs.MustUse[int](2)\n\n\ts := userdefs.SingleTypeParam[int]{X: 1}\n\ts.String() // want `result of \\(\\*typeparams/userdefs.SingleTypeParam\\[int\\]\\).String call not used`\n\t_ = s.String()\n\n\tm := userdefs.MultiTypeParam[int, string]{X: 1, Y: \"one\"}\n\tm.String() // want `result of \\(\\*typeparams/userdefs.MultiTypeParam\\[int, string\\]\\).String call not used`\n\t_ = m.String()\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/testdata/src/typeparams/userdefs/userdefs.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage userdefs\n\nfunc MustUse[T interface{ ~int }](v T) T {\n\treturn v + 1\n}\n\ntype SingleTypeParam[T any] struct {\n\tX T\n}\n\nfunc (_ *SingleTypeParam[T]) String() string {\n\treturn \"SingleTypeParam\"\n}\n\ntype MultiTypeParam[T any, U any] struct {\n\tX T\n\tY U\n}\n\nfunc (_ *MultiTypeParam[T, U]) String() string {\n\treturn \"MultiTypeParam\"\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/unusedresult.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedresult defines an analyzer that checks for unused\n// results of calls to certain functions.\npackage unusedresult\n\n// It is tempting to make this analysis inductive: for each function\n// that tail-calls one of the functions that we check, check those\n// functions too. However, just because you must use the result of\n// fmt.Sprintf doesn't mean you need to use the result of every\n// function that returns a formatted string: it may have other results\n// and effects.\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unusedresult\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unusedresult\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\n// flags\nvar funcs, stringMethods stringSetFlag\n\nfunc init() {\n\t// TODO(adonovan): provide a comment or declaration syntax to\n\t// allow users to add their functions to this set using facts.\n\t// For example:\n\t//\n\t//    func ignoringTheErrorWouldBeVeryBad() error {\n\t//      type mustUseResult struct{} // enables vet unusedresult check\n\t//      ...\n\t//    }\n\t//\n\t//    ignoringTheErrorWouldBeVeryBad() // oops\n\t//\n\n\t// List standard library functions here.\n\t// The context.With{Cancel,Deadline,Timeout} entries are\n\t// effectively redundant wrt the lostcancel analyzer.\n\tfuncs = stringSetFlag{\n\t\t\"context.WithCancel\":      true,\n\t\t\"context.WithDeadline\":    true,\n\t\t\"context.WithTimeout\":     true,\n\t\t\"context.WithValue\":       true,\n\t\t\"errors.New\":              true,\n\t\t\"fmt.Append\":              true,\n\t\t\"fmt.Appendf\":             true,\n\t\t\"fmt.Appendln\":            true,\n\t\t\"fmt.Errorf\":              true,\n\t\t\"fmt.Sprint\":              true,\n\t\t\"fmt.Sprintf\":             true,\n\t\t\"fmt.Sprintln\":            true,\n\t\t\"maps.All\":                true,\n\t\t\"maps.Clone\":              true,\n\t\t\"maps.Collect\":            true,\n\t\t\"maps.Equal\":              true,\n\t\t\"maps.EqualFunc\":          true,\n\t\t\"maps.Keys\":               true,\n\t\t\"maps.Values\":             true,\n\t\t\"slices.All\":              true,\n\t\t\"slices.AppendSeq\":        true,\n\t\t\"slices.Backward\":         true,\n\t\t\"slices.BinarySearch\":     true,\n\t\t\"slices.BinarySearchFunc\": true,\n\t\t\"slices.Chunk\":            true,\n\t\t\"slices.Clip\":             true,\n\t\t\"slices.Clone\":            true,\n\t\t\"slices.Collect\":          true,\n\t\t\"slices.Compact\":          true,\n\t\t\"slices.CompactFunc\":      true,\n\t\t\"slices.Compare\":          true,\n\t\t\"slices.CompareFunc\":      true,\n\t\t\"slices.Concat\":           true,\n\t\t\"slices.Contains\":         true,\n\t\t\"slices.ContainsFunc\":     true,\n\t\t\"slices.Delete\":           true,\n\t\t\"slices.DeleteFunc\":       true,\n\t\t\"slices.Equal\":            true,\n\t\t\"slices.EqualFunc\":        true,\n\t\t\"slices.Grow\":             true,\n\t\t\"slices.Index\":            true,\n\t\t\"slices.IndexFunc\":        true,\n\t\t\"slices.Insert\":           true,\n\t\t\"slices.IsSorted\":         true,\n\t\t\"slices.IsSortedFunc\":     true,\n\t\t\"slices.Max\":              true,\n\t\t\"slices.MaxFunc\":          true,\n\t\t\"slices.Min\":              true,\n\t\t\"slices.MinFunc\":          true,\n\t\t\"slices.Repeat\":           true,\n\t\t\"slices.Replace\":          true,\n\t\t\"slices.Sorted\":           true,\n\t\t\"slices.SortedFunc\":       true,\n\t\t\"slices.SortedStableFunc\": true,\n\t\t\"slices.Values\":           true,\n\t\t\"sort.Reverse\":            true,\n\t}\n\tAnalyzer.Flags.Var(&funcs, \"funcs\",\n\t\t\"comma-separated list of functions whose results must be used\")\n\n\tstringMethods.Set(\"Error,String\")\n\tAnalyzer.Flags.Var(&stringMethods, \"stringmethods\",\n\t\t\"comma-separated list of names of methods of type func() string whose results must be used\")\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// Split functions into (pkg, name) pairs to save allocation later.\n\tpkgFuncs := make(map[[2]string]bool, len(funcs))\n\tfor s := range funcs {\n\t\tif i := strings.LastIndexByte(s, '.'); i > 0 {\n\t\t\tpkgFuncs[[2]string{s[:i], s[i+1:]}] = true\n\t\t}\n\t}\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.ExprStmt)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall, ok := ast.Unparen(n.(*ast.ExprStmt).X).(*ast.CallExpr)\n\t\tif !ok {\n\t\t\treturn // not a call statement\n\t\t}\n\n\t\t// Call to function or method?\n\t\tfn, ok := typeutil.Callee(pass.TypesInfo, call).(*types.Func)\n\t\tif !ok {\n\t\t\treturn // e.g. var or builtin\n\t\t}\n\t\tif sig := fn.Signature(); sig.Recv() != nil {\n\t\t\t// method (e.g. foo.String())\n\t\t\tif types.Identical(sig, sigNoArgsStringResult) {\n\t\t\t\tif stringMethods[fn.Name()] {\n\t\t\t\t\tpass.ReportRangef(astutil.RangeOf(call.Pos(), call.Lparen),\n\t\t\t\t\t\t\"result of (%s).%s call not used\",\n\t\t\t\t\t\tsig.Recv().Type(), fn.Name())\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// package-level function (e.g. fmt.Errorf)\n\t\t\tif pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] {\n\t\t\t\tpass.ReportRangef(astutil.RangeOf(call.Pos(), call.Lparen),\n\t\t\t\t\t\"result of %s.%s call not used\",\n\t\t\t\t\tfn.Pkg().Path(), fn.Name())\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n\n// func() string\nvar sigNoArgsStringResult = types.NewSignatureType(nil, nil, nil, nil, types.NewTuple(types.NewParam(token.NoPos, nil, \"\", types.Typ[types.String])), false)\n\ntype stringSetFlag map[string]bool\n\nfunc (ss *stringSetFlag) String() string {\n\tvar items []string\n\tfor item := range *ss {\n\t\titems = append(items, item)\n\t}\n\tsort.Strings(items)\n\treturn strings.Join(items, \",\")\n}\n\nfunc (ss *stringSetFlag) Set(s string) error {\n\tm := make(map[string]bool) // clobber previous value\n\tif s != \"\" {\n\t\tfor name := range strings.SplitSeq(s, \",\") {\n\t\t\tif name == \"\" {\n\t\t\t\tcontinue // TODO: report error? proceed?\n\t\t\t}\n\t\t\tm[name] = true\n\t\t}\n\t}\n\t*ss = m\n\treturn nil\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedresult/unusedresult_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedresult_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedresult\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tfuncs := \"typeparams/userdefs.MustUse,errors.New,fmt.Errorf,fmt.Sprintf,fmt.Sprint\"\n\tunusedresult.Analyzer.Flags.Set(\"funcs\", funcs)\n\tanalysistest.Run(t, testdata, unusedresult.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedwrite checks for unused writes to the elements of a struct or array object.\n//\n// # Analyzer unusedwrite\n//\n// unusedwrite: checks for unused writes\n//\n// The analyzer reports instances of writes to struct fields and\n// arrays that are never read. Specifically, when a struct object\n// or an array is copied, its elements are copied implicitly by\n// the compiler, and any element write to this copy does nothing\n// with the original object.\n//\n// For example:\n//\n//\ttype T struct { x int }\n//\n//\tfunc f(input []T) {\n//\t\tfor i, v := range input {  // v is a copy\n//\t\t\tv.x = i  // unused write to field x\n//\t\t}\n//\t}\n//\n// Another example is about non-pointer receiver:\n//\n//\ttype T struct { x int }\n//\n//\tfunc (t T) f() {  // t is a copy\n//\t\tt.x = i  // unused write to field x\n//\t}\npackage unusedwrite\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The unusedwrite command runs the unusedwrite analyzer\n// on the specified packages.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/unusedwrite\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(unusedwrite.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/testdata/src/a/unusedwrite.go",
    "content": "package a\n\ntype T1 struct{ x int }\n\ntype T2 struct {\n\tx int\n\ty int\n}\n\ntype T3 struct{ y *T1 }\n\nfunc BadWrites() {\n\t// Test struct field writes.\n\tvar s1 T1\n\ts1.x = 10 // want \"unused write to field x\"\n\n\t// Test array writes.\n\tvar s2 [10]int\n\ts2[1] = 10 // want \"unused write to array index 1:int\"\n\n\t// Test range variables of struct type.\n\ts3 := []T1{T1{x: 100}}\n\tfor i, v := range s3 {\n\t\tv.x = i // want \"unused write to field x\"\n\t}\n\n\t// Test the case where a different field is read after the write.\n\ts4 := []T2{T2{x: 1, y: 2}}\n\tfor i, v := range s4 {\n\t\tv.x = i // want \"unused write to field x\"\n\t\t_ = v.y\n\t}\n\n\t// The analyzer can handle only simple control flow.\n\ttype T struct{ x, y int }\n\tt := new(T)\n\tif true {\n\t\tt = new(T)\n\t} // causes t below to become phi(alloc, alloc), not a simple alloc\n\tt.x = 1 // false negative\n\tprint(t.y)\n}\n\nfunc (t T1) BadValueReceiverWrite(v T2) {\n\tt.x = 10 // want \"unused write to field x\"\n\tv.y = 20 // want \"unused write to field y\"\n}\n\nfunc GoodWrites(m map[int]int) {\n\t// A map is copied by reference such that a write will affect the original map.\n\tm[1] = 10\n\n\t// Test struct field writes.\n\tvar s1 T1\n\ts1.x = 10\n\tprint(s1.x)\n\n\t// Test array writes.\n\tvar s2 [10]int\n\ts2[1] = 10\n\t// Current the checker doesn't distinguish index 1 and index 2.\n\t_ = s2[2]\n\n\t// Test range variables of struct type.\n\ts3 := []T1{T1{x: 100}}\n\tfor i, v := range s3 { // v is a copy\n\t\tv.x = i\n\t\t_ = v.x // still a usage\n\t}\n\n\t// Test an object with multiple fields.\n\to := &T2{x: 10, y: 20}\n\tprint(o)\n\n\t// Test an object of embedded struct/pointer type.\n\tt1 := &T1{x: 10}\n\tt2 := &T3{y: t1}\n\tprint(t2)\n}\n\nfunc (t *T1) GoodPointerReceiverWrite(v *T2) {\n\tt.x = 10\n\tv.y = 20\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/testdata/src/importsunsafe/i.go",
    "content": "package importsunsafe\n\nimport \"unsafe\"\n\ntype S struct {\n\tF, G int\n}\n\nfunc _() {\n\tvar s S\n\ts.F = 1\n\t// This write to G is used below, because &s.F allows access to all of s, but\n\t// the analyzer would naively report it as unused. For this reason, we\n\t// silence the analysis if unsafe is imported.\n\ts.G = 2\n\n\tptr := unsafe.Pointer(&s.F)\n\tt := (*S)(ptr)\n\tprintln(t.G)\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/unusedwrite.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedwrite\n\nimport (\n\t_ \"embed\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/buildssa\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n//go:embed doc.go\nvar doc string\n\n// Analyzer reports instances of writes to struct fields and arrays\n// that are never read.\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unusedwrite\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unusedwrite\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite\",\n\tRequires: []*analysis.Analyzer{buildssa.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tfor _, pkg := range pass.Pkg.Imports() {\n\t\tif pkg.Path() == \"unsafe\" {\n\t\t\t// See golang/go#67684, or testdata/src/importsunsafe: the unusedwrite\n\t\t\t// analyzer may have false positives when used with unsafe.\n\t\t\treturn nil, nil\n\t\t}\n\t}\n\n\tssainput := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)\n\tfor _, fn := range ssainput.SrcFuncs {\n\t\treports := checkStores(fn)\n\t\tfor _, store := range reports {\n\t\t\tswitch addr := store.Addr.(type) {\n\t\t\tcase *ssa.FieldAddr:\n\t\t\t\tfield := typeparams.CoreType(typeparams.MustDeref(addr.X.Type())).(*types.Struct).Field(addr.Field)\n\t\t\t\tpass.Reportf(store.Pos(),\n\t\t\t\t\t\"unused write to field %s\", field.Name())\n\t\t\tcase *ssa.IndexAddr:\n\t\t\t\tpass.Reportf(store.Pos(),\n\t\t\t\t\t\"unused write to array index %s\", addr.Index)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// checkStores returns *Stores in fn whose address is written to but never used.\nfunc checkStores(fn *ssa.Function) []*ssa.Store {\n\tvar reports []*ssa.Store\n\t// Visit each block. No need to visit fn.Recover.\n\tfor _, blk := range fn.Blocks {\n\t\tfor _, instr := range blk.Instrs {\n\t\t\t// Identify writes.\n\t\t\tif store, ok := instr.(*ssa.Store); ok {\n\t\t\t\t// Consider field/index writes to an object whose elements are copied and not shared.\n\t\t\t\t// MapUpdate is excluded since only the reference of the map is copied.\n\t\t\t\tswitch addr := store.Addr.(type) {\n\t\t\t\tcase *ssa.FieldAddr:\n\t\t\t\t\tif isDeadStore(store, addr.X, addr) {\n\t\t\t\t\t\treports = append(reports, store)\n\t\t\t\t\t}\n\t\t\t\tcase *ssa.IndexAddr:\n\t\t\t\t\tif isDeadStore(store, addr.X, addr) {\n\t\t\t\t\t\treports = append(reports, store)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn reports\n}\n\n// isDeadStore determines whether a field/index write to an object is dead.\n// Argument \"obj\" is the object, and \"addr\" is the instruction fetching the field/index.\nfunc isDeadStore(store *ssa.Store, obj ssa.Value, addr ssa.Instruction) bool {\n\t// Consider only struct or array objects.\n\tif !hasStructOrArrayType(obj) {\n\t\treturn false\n\t}\n\t// Check liveness: if the value is used later, then don't report the write.\n\tfor _, ref := range *obj.Referrers() {\n\t\tif ref == store || ref == addr {\n\t\t\tcontinue\n\t\t}\n\t\tswitch ins := ref.(type) {\n\t\tcase ssa.CallInstruction:\n\t\t\treturn false\n\t\tcase *ssa.FieldAddr:\n\t\t\t// Check whether the same field is used.\n\t\t\tif ins.X == obj {\n\t\t\t\tif faddr, ok := addr.(*ssa.FieldAddr); ok {\n\t\t\t\t\tif faddr.Field == ins.Field {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Otherwise another field is used, and this usage doesn't count.\n\t\t\tcontinue\n\t\tcase *ssa.IndexAddr:\n\t\t\tif ins.X == obj {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tcontinue // Otherwise another object is used\n\t\tcase *ssa.Lookup:\n\t\t\tif ins.X == obj {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tcontinue // Otherwise another object is used\n\t\tcase *ssa.Store:\n\t\t\tif ins.Val == obj {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tcontinue // Otherwise other object is stored\n\t\tdefault: // consider live if the object is used in any other instruction\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// isStructOrArray returns whether the underlying type is struct or array.\nfunc isStructOrArray(tp types.Type) bool {\n\tswitch tp.Underlying().(type) {\n\tcase *types.Array:\n\t\treturn true\n\tcase *types.Struct:\n\t\treturn true\n\t}\n\treturn false\n}\n\n// hasStructOrArrayType returns whether a value is of struct or array type.\nfunc hasStructOrArrayType(v ssa.Value) bool {\n\tif instr, ok := v.(ssa.Instruction); ok {\n\t\tif alloc, ok := instr.(*ssa.Alloc); ok {\n\t\t\t// Check the element type of an allocated register (which always has pointer type)\n\t\t\t// e.g., for\n\t\t\t//   func (t T) f() { ...}\n\t\t\t// the receiver object is of type *T:\n\t\t\t//   t0 = local T (t)   *T\n\t\t\tif tp, ok := types.Unalias(alloc.Type()).(*types.Pointer); ok {\n\t\t\t\treturn isStructOrArray(tp.Elem())\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\treturn isStructOrArray(v.Type())\n}\n"
  },
  {
    "path": "go/analysis/passes/unusedwrite/unusedwrite_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedwrite_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedwrite\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, unusedwrite.Analyzer, \"a\", \"importsunsafe\")\n}\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package usesgenerics defines an Analyzer that checks for usage of generic\n// features added in Go 1.18.\n//\n// # Analyzer usesgenerics\n//\n// usesgenerics: detect whether a package uses generics features\n//\n// The usesgenerics analysis reports whether a package directly or transitively\n// uses certain features associated with generic programming in Go.\npackage usesgenerics\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/testdata/src/a/a.go",
    "content": "// want package:`features{typeDecl,funcDecl,funcInstance}`\n\npackage a\n\ntype T[P any] int\n\nfunc F[P any]() {}\n\nvar _ = F[int]\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/testdata/src/b/b.go",
    "content": "// want package:`features{typeSet}`\n\npackage b\n\ntype Constraint interface {\n\t~int | string\n}\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/testdata/src/c/c.go",
    "content": "// want package:`features{typeDecl,funcDecl,typeSet,typeInstance,funcInstance}`\n\n// Features funcDecl, typeSet, and funcInstance come from imported packages \"a\"\n// and \"b\". These features are not directly present in \"c\".\n\npackage c\n\nimport (\n\t\"a\"\n\t\"b\"\n)\n\ntype T[P b.Constraint] a.T[P]\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/testdata/src/d/d.go",
    "content": "// want package:`features{typeSet}`\n\npackage d\n\ntype myInt int\n\nfunc _() {\n\t// Sanity check that we can both detect local types and interfaces with\n\t// embedded defined types.\n\ttype constraint interface {\n\t\tmyInt\n\t}\n}\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/usesgenerics.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage usesgenerics\n\nimport (\n\t_ \"embed\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typeparams/genericfeatures\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"usesgenerics\",\n\tDoc:        analyzerutil.MustExtractDoc(doc, \"usesgenerics\"),\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/usesgenerics\",\n\tRequires:   []*analysis.Analyzer{inspect.Analyzer},\n\tRun:        run,\n\tResultType: reflect.TypeFor[*Result](),\n\tFactTypes:  []analysis.Fact{new(featuresFact)},\n}\n\ntype Features = genericfeatures.Features\n\nconst (\n\tGenericTypeDecls  = genericfeatures.GenericTypeDecls\n\tGenericFuncDecls  = genericfeatures.GenericFuncDecls\n\tEmbeddedTypeSets  = genericfeatures.EmbeddedTypeSets\n\tTypeInstantiation = genericfeatures.TypeInstantiation\n\tFuncInstantiation = genericfeatures.FuncInstantiation\n)\n\n// Result is the usesgenerics analyzer result type. The Direct field records\n// features used directly by the package being analyzed (i.e. contained in the\n// package source code). The Transitive field records any features used by the\n// package or any of its transitive imports.\ntype Result struct {\n\tDirect, Transitive Features\n}\n\ntype featuresFact struct {\n\tFeatures Features\n}\n\nfunc (f *featuresFact) AFact()         {}\nfunc (f *featuresFact) String() string { return f.Features.String() }\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tdirect := genericfeatures.ForPackage(inspect, pass.TypesInfo)\n\n\ttransitive := direct | importedTransitiveFeatures(pass)\n\tif transitive != 0 {\n\t\tpass.ExportPackageFact(&featuresFact{transitive})\n\t}\n\n\treturn &Result{\n\t\tDirect:     direct,\n\t\tTransitive: transitive,\n\t}, nil\n}\n\n// importedTransitiveFeatures computes features that are used transitively via\n// imports.\nfunc importedTransitiveFeatures(pass *analysis.Pass) Features {\n\tvar feats Features\n\tfor _, imp := range pass.Pkg.Imports() {\n\t\tvar importedFact featuresFact\n\t\tif pass.ImportPackageFact(imp, &importedFact) {\n\t\t\tfeats |= importedFact.Features\n\t\t}\n\t}\n\treturn feats\n}\n"
  },
  {
    "path": "go/analysis/passes/usesgenerics/usesgenerics_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage usesgenerics_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/usesgenerics\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, usesgenerics.Analyzer, \"a\", \"b\", \"c\", \"d\")\n}\n"
  },
  {
    "path": "go/analysis/passes/waitgroup/doc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package waitgroup defines an Analyzer that detects simple misuses\n// of sync.WaitGroup.\n//\n// # Analyzer waitgroup\n//\n// waitgroup: check for misuses of sync.WaitGroup\n//\n// This analyzer detects mistaken calls to the (*sync.WaitGroup).Add\n// method from inside a new goroutine, causing Add to race with Wait:\n//\n//\t// WRONG\n//\tvar wg sync.WaitGroup\n//\tgo func() {\n//\t        wg.Add(1) // \"WaitGroup.Add called from inside new goroutine\"\n//\t        defer wg.Done()\n//\t        ...\n//\t}()\n//\twg.Wait() // (may return prematurely before new goroutine starts)\n//\n// The correct code calls Add before starting the goroutine:\n//\n//\t// RIGHT\n//\tvar wg sync.WaitGroup\n//\twg.Add(1)\n//\tgo func() {\n//\t\tdefer wg.Done()\n//\t\t...\n//\t}()\n//\twg.Wait()\npackage waitgroup\n"
  },
  {
    "path": "go/analysis/passes/waitgroup/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The waitgroup command applies the golang.org/x/tools/go/analysis/passes/waitgroup\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/waitgroup\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(waitgroup.Analyzer) }\n"
  },
  {
    "path": "go/analysis/passes/waitgroup/testdata/src/a/a.go",
    "content": "package a\n\nimport \"sync\"\n\nfunc f() {\n\tvar wg sync.WaitGroup\n\twg.Add(1) // ok\n\tgo func() {\n\t\twg.Add(1) // want \"WaitGroup.Add called from inside new goroutine\"\n\t\t// ...\n\t\twg.Add(1) // ok\n\t}()\n\twg.Add(1) // ok\n}\n"
  },
  {
    "path": "go/analysis/passes/waitgroup/waitgroup.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package waitgroup defines an Analyzer that detects simple misuses\n// of sync.WaitGroup.\npackage waitgroup\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"waitgroup\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"waitgroup\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tif !typesinternal.Imports(pass.Pkg, \"sync\") {\n\t\treturn nil, nil // doesn't directly import sync\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.CallExpr)(nil),\n\t}\n\n\tinspect.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) (proceed bool) {\n\t\tif push {\n\t\t\tcall := n.(*ast.CallExpr)\n\t\t\tobj := typeutil.Callee(pass.TypesInfo, call)\n\t\t\tif typesinternal.IsMethodNamed(obj, \"sync\", \"WaitGroup\", \"Add\") &&\n\t\t\t\thasSuffix(stack, wantSuffix) &&\n\t\t\t\tbackindex(stack, 1) == backindex(stack, 2).(*ast.BlockStmt).List[0] { // ExprStmt must be Block's first stmt\n\n\t\t\t\tpass.Reportf(call.Lparen, \"WaitGroup.Add called from inside new goroutine\")\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\treturn nil, nil\n}\n\n//\tgo func() {\n//\t   wg.Add(1)\n//\t   ...\n//\t}()\nvar wantSuffix = []ast.Node{\n\t(*ast.GoStmt)(nil),\n\t(*ast.CallExpr)(nil),\n\t(*ast.FuncLit)(nil),\n\t(*ast.BlockStmt)(nil),\n\t(*ast.ExprStmt)(nil),\n\t(*ast.CallExpr)(nil),\n}\n\n// hasSuffix reports whether stack has the matching suffix,\n// considering only node types.\nfunc hasSuffix(stack, suffix []ast.Node) bool {\n\t// TODO(adonovan): the inspector could implement this for us.\n\tif len(stack) < len(suffix) {\n\t\treturn false\n\t}\n\tfor i := range len(suffix) {\n\t\tif reflect.TypeOf(backindex(stack, i)) != reflect.TypeOf(backindex(suffix, i)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// backindex is like [slices.Index] but from the back of the slice.\nfunc backindex[T any](slice []T, i int) T {\n\treturn slice[len(slice)-1-i]\n}\n"
  },
  {
    "path": "go/analysis/passes/waitgroup/waitgroup_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage waitgroup_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/waitgroup\"\n)\n\nfunc Test(t *testing.T) {\n\tanalysistest.Run(t, analysistest.TestData(), waitgroup.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "go/analysis/singlechecker/singlechecker.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package singlechecker defines the main function for an analysis\n// driver with only a single analysis.\n// This package makes it easy for a provider of an analysis package to\n// also provide a standalone tool that runs just that analysis.\n//\n// For example, if example.org/findbadness is an analysis package,\n// all that is needed to define a standalone tool is a file,\n// example.org/findbadness/cmd/findbadness/main.go, containing:\n//\n//\t// The findbadness command runs an analysis.\n//\tpackage main\n//\n//\timport (\n//\t\t\"example.org/findbadness\"\n//\t\t\"golang.org/x/tools/go/analysis/singlechecker\"\n//\t)\n//\n//\tfunc main() { singlechecker.Main(findbadness.Analyzer) }\npackage singlechecker\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/go/analysis/internal/checker\"\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n)\n\n// Main is the main function for a checker command for a single analysis.\nfunc Main(a *analysis.Analyzer) {\n\tlog.SetFlags(0)\n\tlog.SetPrefix(a.Name + \": \")\n\n\tanalyzers := []*analysis.Analyzer{a}\n\n\tif err := analysis.Validate(analyzers); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tchecker.RegisterFlags()\n\n\tflag.Usage = func() {\n\t\tparas := strings.Split(a.Doc, \"\\n\\n\")\n\t\tfmt.Fprintf(os.Stderr, \"%s: %s\\n\\n\", a.Name, paras[0])\n\t\tfmt.Fprintf(os.Stderr, \"Usage: %s [-flag] [package]\\n\\n\", a.Name)\n\t\tif len(paras) > 1 {\n\t\t\tfmt.Fprintln(os.Stderr, strings.Join(paras[1:], \"\\n\\n\"))\n\t\t}\n\t\tfmt.Fprintln(os.Stderr, \"\\nFlags:\")\n\t\tflag.PrintDefaults()\n\t}\n\n\tanalyzers = analysisflags.Parse(analyzers, false)\n\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\tflag.Usage()\n\t\tos.Exit(1)\n\t}\n\n\tif len(args) == 1 && strings.HasSuffix(args[0], \".cfg\") {\n\t\tunitchecker.Run(args[0], analyzers)\n\t\tpanic(\"unreachable\")\n\t}\n\n\tos.Exit(checker.Run(args, analyzers))\n}\n"
  },
  {
    "path": "go/analysis/unitchecker/export_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unitchecker\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// This file exposes various internal hooks to the separate_test.\n//\n// TODO(adonovan): expose a public API to unitchecker that doesn't\n// rely on details of JSON .cfg files or enshrine I/O decisions or\n// assumptions about how \"go vet\" locates things. Ideally the new Run\n// function would accept an interface, and a Config file would be just\n// one way--the go vet way--to implement it.\n\nfunc SetTypeImportExport(\n\tMakeTypesImporter func(*Config, *token.FileSet) types.Importer,\n\tExportTypes func(*Config, *token.FileSet, *types.Package) error,\n) {\n\tmakeTypesImporter = MakeTypesImporter\n\texportTypes = ExportTypes\n}\n"
  },
  {
    "path": "go/analysis/unitchecker/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// This file provides an example command for static checkers\n// conforming to the golang.org/x/tools/go/analysis API.\n// It serves as a model for the behavior of the cmd/vet tool in $GOROOT.\n// Being based on the unitchecker driver, it must be run by go vet:\n//\n//\t$ go build -o unitchecker main.go\n//\t$ go vet -vettool=unitchecker my/project/...\n//\n// For a checker also capable of running standalone, use multichecker.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n\n\t\"golang.org/x/tools/go/analysis/passes/appends\"\n\t\"golang.org/x/tools/go/analysis/passes/asmdecl\"\n\t\"golang.org/x/tools/go/analysis/passes/assign\"\n\t\"golang.org/x/tools/go/analysis/passes/atomic\"\n\t\"golang.org/x/tools/go/analysis/passes/bools\"\n\t\"golang.org/x/tools/go/analysis/passes/buildtag\"\n\t\"golang.org/x/tools/go/analysis/passes/cgocall\"\n\t\"golang.org/x/tools/go/analysis/passes/composite\"\n\t\"golang.org/x/tools/go/analysis/passes/copylock\"\n\t\"golang.org/x/tools/go/analysis/passes/directive\"\n\t\"golang.org/x/tools/go/analysis/passes/errorsas\"\n\t\"golang.org/x/tools/go/analysis/passes/framepointer\"\n\t\"golang.org/x/tools/go/analysis/passes/httpresponse\"\n\t\"golang.org/x/tools/go/analysis/passes/ifaceassert\"\n\t\"golang.org/x/tools/go/analysis/passes/loopclosure\"\n\t\"golang.org/x/tools/go/analysis/passes/lostcancel\"\n\t\"golang.org/x/tools/go/analysis/passes/nilfunc\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/passes/shift\"\n\t\"golang.org/x/tools/go/analysis/passes/sigchanyzer\"\n\t\"golang.org/x/tools/go/analysis/passes/stdmethods\"\n\t\"golang.org/x/tools/go/analysis/passes/stringintconv\"\n\t\"golang.org/x/tools/go/analysis/passes/structtag\"\n\t\"golang.org/x/tools/go/analysis/passes/testinggoroutine\"\n\t\"golang.org/x/tools/go/analysis/passes/tests\"\n\t\"golang.org/x/tools/go/analysis/passes/timeformat\"\n\t\"golang.org/x/tools/go/analysis/passes/unmarshal\"\n\t\"golang.org/x/tools/go/analysis/passes/unreachable\"\n\t\"golang.org/x/tools/go/analysis/passes/unsafeptr\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedresult\"\n)\n\nfunc main() {\n\tunitchecker.Main(\n\t\tappends.Analyzer,\n\t\tasmdecl.Analyzer,\n\t\tassign.Analyzer,\n\t\tatomic.Analyzer,\n\t\tbools.Analyzer,\n\t\tbuildtag.Analyzer,\n\t\tcgocall.Analyzer,\n\t\tcomposite.Analyzer,\n\t\tcopylock.Analyzer,\n\t\tdirective.Analyzer,\n\t\terrorsas.Analyzer,\n\t\tframepointer.Analyzer,\n\t\thttpresponse.Analyzer,\n\t\tifaceassert.Analyzer,\n\t\tloopclosure.Analyzer,\n\t\tlostcancel.Analyzer,\n\t\tnilfunc.Analyzer,\n\t\tprintf.Analyzer,\n\t\tshift.Analyzer,\n\t\tsigchanyzer.Analyzer,\n\t\tstdmethods.Analyzer,\n\t\tstringintconv.Analyzer,\n\t\tstructtag.Analyzer,\n\t\ttests.Analyzer,\n\t\ttestinggoroutine.Analyzer,\n\t\ttimeformat.Analyzer,\n\t\tunmarshal.Analyzer,\n\t\tunreachable.Analyzer,\n\t\tunsafeptr.Analyzer,\n\t\tunusedresult.Analyzer,\n\t)\n}\n"
  },
  {
    "path": "go/analysis/unitchecker/separate_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unitchecker_test\n\n// This file illustrates separate analysis with an example.\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TestExampleSeparateAnalysis demonstrates the principle of separate\n// analysis, the distribution of units of type-checking and analysis\n// work across several processes, using serialized summaries to\n// communicate between them.\n//\n// It uses two different kinds of task, \"manager\" and \"worker\":\n//\n//   - The manager computes the graph of package dependencies, and makes\n//     a request to the worker for each package. It does not parse,\n//     type-check, or analyze Go code. It is analogous \"go vet\".\n//\n//   - The worker, which contains the Analyzers, reads each request,\n//     loads, parses, and type-checks the files of one package,\n//     applies all necessary analyzers to the package, then writes\n//     its results to a file. It is a unitchecker-based driver,\n//     analogous to the program specified by go vet -vettool= flag.\n//\n// In practice these would be separate executables, but for simplicity\n// of this example they are provided by one executable in two\n// different modes: the Example function is the manager, and the same\n// executable invoked with ENTRYPOINT=worker is the worker.\n// (See TestIntegration for how this happens.)\n//\n// Unfortunately this can't be a true Example because of the skip,\n// which requires a testing.T.\nfunc TestExampleSeparateAnalysis(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\t// src is an archive containing a module with a printf mistake.\n\tconst src = `\n-- go.mod --\nmodule separate\ngo 1.18\n\n-- main/main.go --\npackage main\n\nimport \"separate/lib\"\n\nfunc main() {\n\tlib.MyPrintf(\"%s\", 123)\n}\n\n-- lib/lib.go --\npackage lib\n\nimport \"fmt\"\n\nfunc MyPrintf(format string, args ...any) {\n\tfmt.Printf(format, args...)\n}\n`\n\n\t// Expand archive into tmp tree.\n\tfs, err := txtar.FS(txtar.Parse([]byte(src)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttmpdir := testfiles.CopyToTmp(t, fs)\n\n\t// Load metadata for the main package and all its dependencies.\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedModule,\n\t\tDir:  tmpdir,\n\t\tEnv: append(os.Environ(),\n\t\t\t\"GOPROXY=off\", // disable network\n\t\t\t\"GOWORK=off\",  // an ambient GOWORK value would break package loading\n\t\t),\n\t\tLogf: t.Logf,\n\t}\n\tpkgs, err := packages.Load(cfg, \"separate/main\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Stop if any package had a metadata error.\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tt.Fatal(\"there were errors among loaded packages\")\n\t}\n\n\t// Now we have loaded the import graph,\n\t// let's begin the proper work of the manager.\n\n\t// Gather root packages. They will get all analyzers,\n\t// whereas dependencies get only the subset that\n\t// produce facts or are required by them.\n\troots := make(map[*packages.Package]bool)\n\tfor _, pkg := range pkgs {\n\t\troots[pkg] = true\n\t}\n\n\t// nextID generates sequence numbers for each unit of work.\n\t// We use it to create names of temporary files.\n\tvar nextID atomic.Int32\n\n\tvar allDiagnostics []string\n\n\t// Visit all packages in postorder: dependencies first.\n\t// TODO(adonovan): opt: use parallel postorder.\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tif pkg.PkgPath == \"unsafe\" {\n\t\t\treturn\n\t\t}\n\n\t\t// Choose a unique prefix for temporary files\n\t\t// (.cfg .types .facts) produced by this package.\n\t\t// We stow it in an otherwise unused field of\n\t\t// Package so it can be accessed by our importers.\n\t\tprefix := fmt.Sprintf(\"%s/%d\", tmpdir, nextID.Add(1))\n\t\tpkg.ExportFile = prefix\n\n\t\t// Construct the request to the worker.\n\t\tvar (\n\t\t\timportMap   = make(map[string]string)\n\t\t\tpackageFile = make(map[string]string)\n\t\t\tpackageVetx = make(map[string]string)\n\t\t)\n\t\tfor importPath, dep := range pkg.Imports {\n\t\t\timportMap[importPath] = dep.PkgPath\n\t\t\tif depPrefix := dep.ExportFile; depPrefix != \"\" { // skip \"unsafe\"\n\t\t\t\tpackageFile[dep.PkgPath] = depPrefix + \".types\"\n\t\t\t\tpackageVetx[dep.PkgPath] = depPrefix + \".facts\"\n\t\t\t}\n\t\t}\n\t\tcfg := unitchecker.Config{\n\t\t\tID:           pkg.ID,\n\t\t\tImportPath:   pkg.PkgPath,\n\t\t\tGoFiles:      pkg.CompiledGoFiles,\n\t\t\tNonGoFiles:   pkg.OtherFiles,\n\t\t\tIgnoredFiles: pkg.IgnoredFiles,\n\t\t\tImportMap:    importMap,\n\t\t\tPackageFile:  packageFile,\n\t\t\tPackageVetx:  packageVetx,\n\t\t\tVetxOnly:     !roots[pkg],\n\t\t\tVetxOutput:   prefix + \".facts\",\n\t\t}\n\t\tif pkg.Module != nil {\n\t\t\tif v := pkg.Module.GoVersion; v != \"\" {\n\t\t\t\tcfg.GoVersion = \"go\" + v\n\t\t\t}\n\t\t\tcfg.ModulePath = pkg.Module.Path\n\t\t\tcfg.ModuleVersion = pkg.Module.Version\n\t\t}\n\n\t\t// Write the JSON configuration message to a file.\n\t\tcfgData, err := json.Marshal(cfg)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"internal error in json.Marshal: %v\", err)\n\t\t}\n\t\tcfgFile := prefix + \".cfg\"\n\t\tif err := os.WriteFile(cfgFile, cfgData, 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Send the request to the worker.\n\t\tcmd := testenv.Command(t, os.Args[0], \"-json\", cfgFile)\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Stdout = new(bytes.Buffer)\n\t\tcmd.Env = append(os.Environ(), \"ENTRYPOINT=worker\")\n\t\tif err := cmd.Run(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Parse JSON output and gather in allDiagnostics.\n\t\tdec := json.NewDecoder(cmd.Stdout.(io.Reader))\n\t\tfor {\n\t\t\ttype jsonDiagnostic struct {\n\t\t\t\tPosn    string `json:\"posn\"`\n\t\t\t\tMessage string `json:\"message\"`\n\t\t\t}\n\t\t\t// 'results' maps Package.Path -> Analyzer.Name -> diagnostics\n\t\t\tvar results map[string]map[string][]jsonDiagnostic\n\t\t\tif err := dec.Decode(&results); err != nil {\n\t\t\t\tif err == io.EOF {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tt.Fatalf(\"internal error decoding JSON: %v\", err)\n\t\t\t}\n\t\t\tfor _, result := range results {\n\t\t\t\tfor analyzer, diags := range result {\n\t\t\t\t\tfor _, diag := range diags {\n\t\t\t\t\t\trel := strings.ReplaceAll(diag.Posn, tmpdir, \"\")\n\t\t\t\t\t\trel = filepath.ToSlash(rel)\n\t\t\t\t\t\tmsg := fmt.Sprintf(\"%s: [%s] %s\", rel, analyzer, diag.Message)\n\t\t\t\t\t\tallDiagnostics = append(allDiagnostics, msg)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\t// Observe that the example produces a fact-based diagnostic\n\t// from separate analysis of \"main\", \"lib\", and \"fmt\":\n\n\tconst want = `/main/main.go:6:16: [printf] separate/lib.MyPrintf format %s has arg 123 of wrong type int`\n\tsort.Strings(allDiagnostics)\n\tif got := strings.Join(allDiagnostics, \"\\n\"); got != want {\n\t\tt.Errorf(\"Got: %s\\nWant: %s\", got, want)\n\t}\n}\n\n// -- worker process --\n\n// worker is the main entry point for a unitchecker-based driver\n// with only a single analyzer, for illustration.\nfunc worker() {\n\t// Currently the unitchecker API doesn't allow clients to\n\t// control exactly how and where fact and type information\n\t// is produced and consumed.\n\t//\n\t// So, for example, it assumes that type information has\n\t// already been produced by the compiler, which is true when\n\t// running under \"go vet\", but isn't necessary. It may be more\n\t// convenient and efficient for a distributed analysis system\n\t// if the worker generates both of them, which is the approach\n\t// taken in this example; they could even be saved as two\n\t// sections of a single file.\n\t//\n\t// Consequently, this test currently needs special access to\n\t// private hooks in unitchecker to control how and where facts\n\t// and types are produced and consumed. In due course this\n\t// will become a respectable public API. In the meantime, it\n\t// should at least serve as a demonstration of how one could\n\t// fork unitchecker to achieve separate analysis without go vet.\n\tunitchecker.SetTypeImportExport(makeTypesImporter, exportTypes)\n\n\tunitchecker.Main(printf.Analyzer)\n}\n\nfunc makeTypesImporter(cfg *unitchecker.Config, fset *token.FileSet) types.Importer {\n\timports := make(map[string]*types.Package)\n\treturn importerFunc(func(importPath string) (*types.Package, error) {\n\t\t// Resolve import path to package path (vendoring, etc)\n\t\tpath, ok := cfg.ImportMap[importPath]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"can't resolve import %q\", path)\n\t\t}\n\t\tif path == \"unsafe\" {\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\n\t\t// Find, read, and decode file containing type information.\n\t\tfile, ok := cfg.PackageFile[path]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"no package file for %q\", path)\n\t\t}\n\t\tf, err := os.Open(file)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer f.Close() // ignore error\n\t\treturn gcexportdata.Read(f, fset, imports, path)\n\t})\n}\n\nfunc exportTypes(cfg *unitchecker.Config, fset *token.FileSet, pkg *types.Package) error {\n\tvar out bytes.Buffer\n\tif err := gcexportdata.Write(&out, fset, pkg); err != nil {\n\t\treturn err\n\t}\n\ttypesFile := strings.TrimSuffix(cfg.VetxOutput, \".facts\") + \".types\"\n\treturn os.WriteFile(typesFile, out.Bytes(), 0666)\n}\n\n// -- helpers --\n\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n"
  },
  {
    "path": "go/analysis/unitchecker/unitchecker.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The unitchecker package defines the main function for an analysis\n// driver that analyzes a single compilation unit during a build.\n// It is invoked by a build system such as \"go vet\":\n//\n//\t$ go vet -vettool=$(which vet)\n//\n// It supports the following command-line protocol:\n//\n//\t-V=full         describe executable               (to the build tool)\n//\t-flags          describe flags                    (to the build tool)\n//\tfoo.cfg         description of compilation unit (from the build tool)\n//\n// This package does not depend on go/packages.\n// If you need a standalone tool, use multichecker,\n// which supports this mode but can also load packages\n// from source using go/packages.\npackage unitchecker\n\n// TODO(adonovan):\n// - with gccgo, go build does not build standard library,\n//   so we will not get to analyze it. Yet we must in order\n//   to create base facts for, say, the fmt package for the\n//   printf checker.\n\nimport (\n\t\"archive/zip\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/internal/analysisflags\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n\t\"golang.org/x/tools/internal/facts\"\n)\n\n// A Config describes a compilation unit to be analyzed.\n// It is provided to the tool in a JSON-encoded file\n// whose name ends with \".cfg\".\ntype Config struct {\n\tID                        string // e.g. \"fmt [fmt.test]\"\n\tCompiler                  string // gc or gccgo, provided to MakeImporter\n\tDir                       string // (unused)\n\tImportPath                string // package path\n\tGoVersion                 string // minimum required Go version, such as \"go1.21.0\"\n\tGoFiles                   []string\n\tNonGoFiles                []string\n\tIgnoredFiles              []string\n\tModulePath                string            // module path\n\tModuleVersion             string            // module version\n\tImportMap                 map[string]string // maps import path to package path\n\tPackageFile               map[string]string // maps package path to file of type information\n\tStandard                  map[string]bool   // package belongs to standard library\n\tPackageVetx               map[string]string // maps package path to file of fact information\n\tVetxOnly                  bool              // run analysis only for facts, not diagnostics\n\tVetxOutput                string            // where to write file of fact information\n\tStdout                    string            // write stdout (e.g. JSON, unified diff) to this file\n\tFixArchive                string            // write fixed files to this zip archive, if non-empty\n\tSucceedOnTypecheckFailure bool              // obsolete awful hack; see #18395 and below\n}\n\n// Main is the main function of a vet-like analysis tool that must be\n// invoked by a build system to analyze a single package.\n//\n// The protocol required by 'go vet -vettool=...' is that the tool must support:\n//\n//\t-flags          describe flags in JSON\n//\t-V=full         describe executable for build caching\n//\tfoo.cfg         perform separate modular analyze on the single\n//\t                unit described by a JSON config file foo.cfg.\n//\t-fix\t\tdon't print each diagnostic, apply its first fix\n//\t-diff\t\tdon't apply a fix, print the diff (requires -fix)\n//\t-json\t\tprint diagnostics and fixes in JSON form\nfunc Main(analyzers ...*analysis.Analyzer) {\n\tprogname := filepath.Base(os.Args[0])\n\tlog.SetFlags(0)\n\tlog.SetPrefix(progname + \": \")\n\n\tif err := analysis.Validate(analyzers); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tflag.Usage = func() {\n\t\tfmt.Fprintf(os.Stderr, `%[1]s is a tool for static analysis of Go programs.\n\nUsage of %[1]s:\n\t%.16[1]s unit.cfg\t# execute analysis specified by config file\n\t%.16[1]s help    \t# general help, including listing analyzers and flags\n\t%.16[1]s help name\t# help on specific analyzer and its flags\n`, progname)\n\t\tos.Exit(1)\n\t}\n\n\tanalyzers = analysisflags.Parse(analyzers, true)\n\n\targs := flag.Args()\n\tif len(args) == 0 {\n\t\tflag.Usage()\n\t}\n\tif args[0] == \"help\" {\n\t\tanalysisflags.Help(progname, analyzers, args[1:])\n\t\tos.Exit(0)\n\t}\n\tif len(args) != 1 || !strings.HasSuffix(args[0], \".cfg\") {\n\t\tlog.Fatalf(`invoking \"go tool %[1]s\" directly is unsupported; use \"go %[1]s\"`, progname)\n\t}\n\tRun(args[0], analyzers)\n}\n\n// Run reads the *.cfg file, runs the analysis,\n// and calls os.Exit with an appropriate error code.\n// It assumes flags have already been set.\nfunc Run(configFile string, analyzers []*analysis.Analyzer) {\n\tcfg, err := readConfig(configFile)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Redirect stdout to a file as requested.\n\tif cfg.Stdout != \"\" {\n\t\tf, err := os.Create(cfg.Stdout)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tos.Stdout = f\n\t}\n\n\tfset := token.NewFileSet()\n\tresults, err := run(fset, cfg, analyzers)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tcode := 0\n\n\t// In VetxOnly mode, the analysis is run only for facts.\n\tif !cfg.VetxOnly {\n\t\tcode = processResults(fset, cfg.ID, cfg.FixArchive, results)\n\t}\n\n\tos.Exit(code)\n}\n\nfunc readConfig(filename string) (*Config, error) {\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcfg := new(Config)\n\tif err := json.Unmarshal(data, cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot decode JSON config file %s: %v\", filename, err)\n\t}\n\tif len(cfg.GoFiles) == 0 {\n\t\t// The go command disallows packages with no files.\n\t\t// The only exception is unsafe, but the go command\n\t\t// doesn't call vet on it.\n\t\treturn nil, fmt.Errorf(\"package has no files: %s\", cfg.ImportPath)\n\t}\n\treturn cfg, nil\n}\n\nfunc processResults(fset *token.FileSet, id, fixArchive string, results []result) (exit int) {\n\tif analysisflags.Fix {\n\t\t// Don't print the diagnostics,\n\t\t// but apply all fixes from the root actions.\n\n\t\t// Convert results to form needed by ApplyFixes.\n\t\tfixActions := make([]driverutil.FixAction, len(results))\n\t\tfor i, res := range results {\n\t\t\tfixActions[i] = driverutil.FixAction{\n\t\t\t\tName:         res.a.Name,\n\t\t\t\tPkg:          res.pkg,\n\t\t\t\tFiles:        res.files,\n\t\t\t\tFileSet:      fset,\n\t\t\t\tReadFileFunc: os.ReadFile, // TODO(adonovan): respect overlays\n\t\t\t\tDiagnostics:  res.diagnostics,\n\t\t\t}\n\t\t}\n\n\t\t// By default, fixes overwrite the original file.\n\t\t// With the -diff flag, print the diffs to stdout.\n\t\t// If \"go fix\" provides a fix archive, we write files\n\t\t// into it so that mutations happen after the build.\n\t\twrite := func(filename string, content []byte) error {\n\t\t\treturn os.WriteFile(filename, content, 0644)\n\t\t}\n\t\tif fixArchive != \"\" {\n\t\t\tf, err := os.Create(fixArchive)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"can't create -fix archive: %v\", err)\n\t\t\t}\n\t\t\tzw := zip.NewWriter(f)\n\t\t\tzw.SetComment(id) // ignore error\n\t\t\tdefer func() {\n\t\t\t\tif err := zw.Close(); err != nil {\n\t\t\t\t\tlog.Fatalf(\"closing -fix archive zip writer: %v\", err)\n\t\t\t\t}\n\t\t\t\tif err := f.Close(); err != nil {\n\t\t\t\t\tlog.Fatalf(\"closing -fix archive file: %v\", err)\n\t\t\t\t}\n\t\t\t}()\n\t\t\twrite = func(filename string, content []byte) error {\n\t\t\t\tf, err := zw.Create(filename)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\t_, err = f.Write(content)\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif err := driverutil.ApplyFixes(fixActions, write, analysisflags.Diff, false); err != nil {\n\t\t\t// Fail when applying fixes failed.\n\t\t\tlog.Print(err)\n\t\t\texit = 1\n\t\t}\n\n\t\t// Don't proceed to print text/JSON,\n\t\t// and don't report an error\n\t\t// just because there were diagnostics.\n\t\treturn\n\t}\n\n\t// Keep consistent with analogous logic in\n\t// printDiagnostics in ../internal/checker/checker.go.\n\n\tif analysisflags.JSON {\n\t\t// JSON output\n\t\ttree := make(driverutil.JSONTree)\n\t\tfor _, res := range results {\n\t\t\ttree.Add(fset, id, res.a.Name, res.diagnostics, res.err)\n\t\t}\n\t\ttree.Print(os.Stdout) // ignore error\n\n\t} else {\n\t\t// plain text\n\t\tfor _, res := range results {\n\t\t\tif res.err != nil {\n\t\t\t\tlog.Println(res.err)\n\t\t\t\texit = 1\n\t\t\t}\n\t\t}\n\t\tfor _, res := range results {\n\t\t\tfor _, diag := range res.diagnostics {\n\t\t\t\tdriverutil.PrintPlain(os.Stderr, fset, analysisflags.Context, diag)\n\t\t\t\texit = 1\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n\ntype factImporter = func(pkgPath string) ([]byte, error)\n\n// These four hook variables are a proof of concept of a future\n// parameterization of a unitchecker API that allows the client to\n// determine how and where facts and types are produced and consumed.\n// (Note that the eventual API will likely be quite different.)\n//\n// The defaults honor a Config in a manner compatible with 'go vet'.\nvar (\n\tmakeTypesImporter = func(cfg *Config, fset *token.FileSet) types.Importer {\n\t\tcompilerImporter := importer.ForCompiler(fset, cfg.Compiler, func(path string) (io.ReadCloser, error) {\n\t\t\t// path is a resolved package path, not an import path.\n\t\t\tfile, ok := cfg.PackageFile[path]\n\t\t\tif !ok {\n\t\t\t\tif cfg.Compiler == \"gccgo\" && cfg.Standard[path] {\n\t\t\t\t\treturn nil, nil // fall back to default gccgo lookup\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"no package file for %q\", path)\n\t\t\t}\n\t\t\treturn os.Open(file)\n\t\t})\n\t\treturn importerFunc(func(importPath string) (*types.Package, error) {\n\t\t\tpath, ok := cfg.ImportMap[importPath] // resolve vendoring, etc\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"can't resolve import %q\", path)\n\t\t\t}\n\t\t\treturn compilerImporter.Import(path)\n\t\t})\n\t}\n\n\texportTypes = func(*Config, *token.FileSet, *types.Package) error {\n\t\t// By default this is a no-op, because \"go vet\"\n\t\t// makes the compiler produce type information.\n\t\treturn nil\n\t}\n\n\tmakeFactImporter = func(cfg *Config) factImporter {\n\t\treturn func(pkgPath string) ([]byte, error) {\n\t\t\tif vetx, ok := cfg.PackageVetx[pkgPath]; ok {\n\t\t\t\treturn os.ReadFile(vetx)\n\t\t\t}\n\t\t\treturn nil, nil // no .vetx file, no facts\n\t\t}\n\t}\n\n\texportFacts = func(cfg *Config, data []byte) error {\n\t\treturn os.WriteFile(cfg.VetxOutput, data, 0666)\n\t}\n)\n\nfunc run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]result, error) {\n\t// Load, parse, typecheck.\n\tvar files []*ast.File\n\tfor _, name := range cfg.GoFiles {\n\t\tf, err := parser.ParseFile(fset, name, nil, parser.ParseComments)\n\t\tif err != nil {\n\t\t\tif cfg.SucceedOnTypecheckFailure {\n\t\t\t\t// Silently succeed; let the compiler\n\t\t\t\t// report parse errors.\n\t\t\t\terr = nil\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfiles = append(files, f)\n\t}\n\ttc := &types.Config{\n\t\tImporter:  makeTypesImporter(cfg, fset),\n\t\tSizes:     types.SizesFor(\"gc\", build.Default.GOARCH), // TODO(adonovan): use cfg.Compiler\n\t\tGoVersion: cfg.GoVersion,\n\t}\n\tinfo := &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\n\tpkg, err := tc.Check(cfg.ImportPath, fset, files, info)\n\tif err != nil {\n\t\tif cfg.SucceedOnTypecheckFailure {\n\t\t\t// Silently succeed; let the compiler\n\t\t\t// report type errors.\n\t\t\terr = nil\n\t\t}\n\t\treturn nil, err\n\t}\n\n\t// Register fact types with gob.\n\t// In VetxOnly mode, analyzers are only for their facts,\n\t// so we can skip any analysis that neither produces facts\n\t// nor depends on any analysis that produces facts.\n\t//\n\t// TODO(adonovan): fix: the command (and logic!) here are backwards.\n\t// It should say \"...nor is required by any...\". (Issue 443099)\n\t//\n\t// Also build a map to hold working state and result.\n\ttype action struct {\n\t\tonce        sync.Once\n\t\tresult      any\n\t\terr         error\n\t\tusesFacts   bool // (transitively uses)\n\t\tdiagnostics []analysis.Diagnostic\n\t}\n\tactions := make(map[*analysis.Analyzer]*action)\n\tvar registerFacts func(a *analysis.Analyzer) bool\n\tregisterFacts = func(a *analysis.Analyzer) bool {\n\t\tact, ok := actions[a]\n\t\tif !ok {\n\t\t\tact = new(action)\n\t\t\tvar usesFacts bool\n\t\t\tfor _, f := range a.FactTypes {\n\t\t\t\tusesFacts = true\n\t\t\t\tgob.Register(f)\n\t\t\t}\n\t\t\tfor _, req := range a.Requires {\n\t\t\t\tif registerFacts(req) {\n\t\t\t\t\tusesFacts = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tact.usesFacts = usesFacts\n\t\t\tactions[a] = act\n\t\t}\n\t\treturn act.usesFacts\n\t}\n\tvar filtered []*analysis.Analyzer\n\tfor _, a := range analyzers {\n\t\tif registerFacts(a) || !cfg.VetxOnly {\n\t\t\tfiltered = append(filtered, a)\n\t\t}\n\t}\n\tanalyzers = filtered\n\n\t// Read facts from imported packages.\n\tfacts, err := facts.NewDecoder(pkg).Decode(makeFactImporter(cfg))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// In parallel, execute the DAG of analyzers.\n\tvar exec func(a *analysis.Analyzer) *action\n\tvar execAll func(analyzers []*analysis.Analyzer)\n\texec = func(a *analysis.Analyzer) *action {\n\t\tact := actions[a]\n\t\tact.once.Do(func() {\n\t\t\texecAll(a.Requires) // prefetch dependencies in parallel\n\n\t\t\t// The inputs to this analysis are the\n\t\t\t// results of its prerequisites.\n\t\t\tinputs := make(map[*analysis.Analyzer]any)\n\t\t\tvar failed []string\n\t\t\tfor _, req := range a.Requires {\n\t\t\t\treqact := exec(req)\n\t\t\t\tif reqact.err != nil {\n\t\t\t\t\tfailed = append(failed, req.String())\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tinputs[req] = reqact.result\n\t\t\t}\n\n\t\t\t// Report an error if any dependency failed.\n\t\t\tif failed != nil {\n\t\t\t\tsort.Strings(failed)\n\t\t\t\tact.err = fmt.Errorf(\"failed prerequisites: %s\", strings.Join(failed, \", \"))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfactFilter := make(map[reflect.Type]bool)\n\t\t\tfor _, f := range a.FactTypes {\n\t\t\t\tfactFilter[reflect.TypeOf(f)] = true\n\t\t\t}\n\n\t\t\tmodule := &analysis.Module{\n\t\t\t\tPath:      cfg.ModulePath,\n\t\t\t\tVersion:   cfg.ModuleVersion,\n\t\t\t\tGoVersion: cfg.GoVersion,\n\t\t\t}\n\n\t\t\tpass := &analysis.Pass{\n\t\t\t\tAnalyzer:     a,\n\t\t\t\tFset:         fset,\n\t\t\t\tFiles:        files,\n\t\t\t\tOtherFiles:   cfg.NonGoFiles,\n\t\t\t\tIgnoredFiles: cfg.IgnoredFiles,\n\t\t\t\tPkg:          pkg,\n\t\t\t\tTypesInfo:    info,\n\t\t\t\tTypesSizes:   tc.Sizes,\n\t\t\t\tTypeErrors:   nil, // unitchecker doesn't RunDespiteErrors\n\t\t\t\tResultOf:     inputs,\n\t\t\t\tReport: func(d analysis.Diagnostic) {\n\t\t\t\t\t// Unitchecker doesn't apply fixes, but it does report them in the JSON output.\n\t\t\t\t\tif err := driverutil.ValidateFixes(fset, a, d.SuggestedFixes); err != nil {\n\t\t\t\t\t\t// Since we have diagnostics, the exit code will be nonzero,\n\t\t\t\t\t\t// so logging these errors is sufficient.\n\t\t\t\t\t\tlog.Println(err)\n\t\t\t\t\t\td.SuggestedFixes = nil\n\t\t\t\t\t}\n\t\t\t\t\tact.diagnostics = append(act.diagnostics, d)\n\t\t\t\t},\n\t\t\t\tImportObjectFact:  facts.ImportObjectFact,\n\t\t\t\tExportObjectFact:  facts.ExportObjectFact,\n\t\t\t\tAllObjectFacts:    func() []analysis.ObjectFact { return facts.AllObjectFacts(factFilter) },\n\t\t\t\tImportPackageFact: facts.ImportPackageFact,\n\t\t\t\tExportPackageFact: facts.ExportPackageFact,\n\t\t\t\tAllPackageFacts:   func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },\n\t\t\t\tModule:            module,\n\t\t\t}\n\t\t\tpass.ReadFile = driverutil.CheckedReadFile(pass, os.ReadFile)\n\n\t\t\tt0 := time.Now()\n\t\t\tact.result, act.err = a.Run(pass)\n\n\t\t\tif act.err == nil { // resolve URLs on diagnostics.\n\t\t\t\tfor i := range act.diagnostics {\n\t\t\t\t\tif url, uerr := driverutil.ResolveURL(a, act.diagnostics[i]); uerr == nil {\n\t\t\t\t\t\tact.diagnostics[i].URL = url\n\t\t\t\t\t} else {\n\t\t\t\t\t\tact.err = uerr // keep the last error\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif false {\n\t\t\t\tlog.Printf(\"analysis %s = %s\", pass, time.Since(t0))\n\t\t\t}\n\t\t})\n\t\treturn act\n\t}\n\texecAll = func(analyzers []*analysis.Analyzer) {\n\t\tvar wg sync.WaitGroup\n\t\tfor _, a := range analyzers {\n\t\t\twg.Add(1)\n\t\t\tgo func(a *analysis.Analyzer) {\n\t\t\t\t_ = exec(a)\n\t\t\t\twg.Done()\n\t\t\t}(a)\n\t\t}\n\t\twg.Wait()\n\t}\n\n\texecAll(analyzers)\n\n\t// Return diagnostics and errors from root analyzers.\n\tresults := make([]result, len(analyzers))\n\tfor i, a := range analyzers {\n\t\tact := actions[a]\n\t\tresults[i] = result{pkg, files, a, act.diagnostics, act.err}\n\t}\n\n\tdata := facts.Encode()\n\tif err := exportFacts(cfg, data); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to export analysis facts: %v\", err)\n\t}\n\tif err := exportTypes(cfg, fset, pkg); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to export type information: %v\", err)\n\t}\n\n\treturn results, nil\n}\n\ntype result struct {\n\tpkg         *types.Package\n\tfiles       []*ast.File\n\ta           *analysis.Analyzer\n\tdiagnostics []analysis.Diagnostic\n\terr         error\n}\n\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n"
  },
  {
    "path": "go/analysis/unitchecker/unitchecker_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unitchecker_test\n\nimport (\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/passes/assign\"\n\t\"golang.org/x/tools/go/analysis/passes/findcall\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestMain(m *testing.M) {\n\t// child process?\n\tswitch os.Getenv(\"ENTRYPOINT\") {\n\tcase \"vet\":\n\t\tvet()\n\t\tpanic(\"unreachable\")\n\tcase \"minivet\":\n\t\tminivet()\n\t\tpanic(\"unreachable\")\n\tcase \"worker\":\n\t\tworker() // see ExampleSeparateAnalysis\n\t\tpanic(\"unreachable\")\n\t}\n\n\t// test process\n\tflag.Parse()\n\tos.Exit(m.Run())\n}\n\n// minivet is a vet-like tool with a few analyzers, for testing.\nfunc minivet() {\n\tunitchecker.Main(\n\t\tfindcall.Analyzer,\n\t\tprintf.Analyzer,\n\t\tassign.Analyzer,\n\t)\n}\n\n// This is a very basic integration test of modular\n// analysis with facts using unitchecker under \"go vet\".\n// It fork/execs the main function above.\nfunc TestIntegration(t *testing.T) {\n\tif runtime.GOOS != \"linux\" && runtime.GOOS != \"darwin\" {\n\t\tt.Skipf(\"skipping fork/exec test on this platform\")\n\t}\n\n\tconst src = `\n-- go.mod --\nmodule golang.org/fake\ngo 1.24\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tMyFunc123()\n}\n\nfunc MyFunc123() {}\n\n-- b/b.go --\npackage b\n\nimport \"golang.org/fake/a\"\n\nfunc _() {\n\ta.MyFunc123()\n\tMyFunc123()\n}\n\nfunc MyFunc123() {}\n\n-- c/c.go --\npackage c\n\nfunc _() {\n    i := 5\n    i = i\n}\n\n-- d/d.go --\npackage d\n\nimport \"fmt\"\n\nvar (\n\tmsg string\n\t_ = fmt.Sprintf(msg)\n)\n\n-- d/dgen.go --\n// Code generated by hand. DO NOT EDIT.\n\npackage d\n\nimport \"fmt\"\n\nvar _ = fmt.Sprintf(msg)\n`\n\t// Expand archive into tmp tree.\n\tfs, err := txtar.FS(txtar.Parse([]byte(src)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttmpdir := testfiles.CopyToTmp(t, fs)\n\n\t// -- operators --\n\n\t// vet runs \"go vet\" with the specified arguments (plus -findcall.name=MyFunc123).\n\tvet := func(t *testing.T, args ...string) (exitcode int, stdout, stderr string) {\n\t\tcmd := exec.Command(\"go\", \"vet\", \"-vettool=\"+os.Args[0], \"-findcall.name=MyFunc123\")\n\t\tcmd.Stdout = new(strings.Builder)\n\t\tcmd.Stderr = new(strings.Builder)\n\t\tcmd.Args = append(cmd.Args, args...)\n\t\tcmd.Env = append(os.Environ(), \"ENTRYPOINT=minivet\")\n\t\tcmd.Dir = tmpdir\n\t\tif err := cmd.Run(); err != nil {\n\t\t\texitErr, ok := err.(*exec.ExitError)\n\t\t\tif !ok {\n\t\t\t\tt.Fatalf(\"couldn't exec %v: %v\", cmd, err)\n\t\t\t}\n\t\t\texitcode = exitErr.ExitCode()\n\t\t}\n\n\t\t// Sanitize filenames; this is imperfect due to\n\t\t// (e.g.) /private/tmp -> /tmp symlink on macOS.\n\t\tstdout = strings.ReplaceAll(fmt.Sprint(cmd.Stdout), tmpdir, \"TMPDIR\")\n\t\tstderr = strings.ReplaceAll(fmt.Sprint(cmd.Stderr), tmpdir, \"TMPDIR\")\n\n\t\t// Show vet information on failure.\n\t\tt.Cleanup(func() {\n\t\t\tif t.Failed() {\n\t\t\t\tt.Logf(\"command: %v\", cmd)\n\t\t\t\tt.Logf(\"exit code: %d\", exitcode)\n\t\t\t\tt.Logf(\"stdout: %s\", stdout)\n\t\t\t\tt.Logf(\"stderr: %s\", stderr)\n\t\t\t}\n\t\t})\n\t\treturn\n\t}\n\n\t// exitcode asserts that the exit code was \"want\".\n\texitcode := func(t *testing.T, got, want int) {\n\t\tif got != want {\n\t\t\tt.Fatalf(\"vet tool exit code was %d\", got)\n\t\t}\n\t}\n\n\t// parseJSON parses the JSON diagnostics into a simple line-oriented form.\n\tparseJSON := func(t *testing.T, stdout string) string {\n\t\tvar v map[string]map[string][]map[string]any\n\t\tif err := json.Unmarshal([]byte(stdout), &v); err != nil {\n\t\t\tt.Fatalf(\"invalid JSON: %v\", err)\n\t\t}\n\t\tvar res strings.Builder\n\t\tfor pkgpath, v := range v {\n\t\t\tfor analyzer, v := range v {\n\t\t\t\tfor _, v := range v {\n\t\t\t\t\tfmt.Fprintf(&res, \"%s: [%s@%s] %v\\n\",\n\t\t\t\t\t\tv[\"posn\"],\n\t\t\t\t\t\tanalyzer, pkgpath,\n\t\t\t\t\t\tv[\"message\"])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Show parsed JSON information on failure.\n\t\tt.Cleanup(func() {\n\t\t\tif t.Failed() {\n\t\t\t\tt.Logf(\"json: %s\", &res)\n\t\t\t}\n\t\t})\n\t\treturn res.String()\n\t}\n\n\t// substring asserts that the labeled output contained the substring.\n\tsubstring := func(t *testing.T, label, output, substr string) {\n\t\tif !strings.Contains(output, substr) {\n\t\t\tt.Fatalf(\"%s: expected substring %q\", label, substr)\n\t\t}\n\t}\n\n\t// contains asserts that the specified file contains the substring.\n\tcontains := func(t *testing.T, filename, substr string) {\n\t\tcontent, err := os.ReadFile(filepath.Join(tmpdir, filename))\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"can't read %s: %v\", filename, err)\n\t\t}\n\t\tt.Cleanup(func() {\n\t\t\tif t.Failed() {\n\t\t\t\tt.Logf(\"content of %s: <<%s>>\", filename, content)\n\t\t\t}\n\t\t})\n\t\tsubstring(t, filename, string(content), substr)\n\t}\n\n\t// -- scenarios --\n\n\tt.Run(\"a\", func(t *testing.T) {\n\t\tcode, _, stderr := vet(t, \"golang.org/fake/a\")\n\t\texitcode(t, code, 1)\n\t\tsubstring(t, \"stderr\", stderr, \"a/a.go:4:11: call of MyFunc123\")\n\t})\n\tt.Run(\"b\", func(t *testing.T) {\n\t\tcode, _, stderr := vet(t, \"golang.org/fake/b\")\n\t\texitcode(t, code, 1)\n\t\tsubstring(t, \"stderr\", stderr, \"b/b.go:6:13: call of MyFunc123\")\n\t\tsubstring(t, \"stderr\", stderr, \"b/b.go:7:11: call of MyFunc123\")\n\t})\n\tt.Run(\"c\", func(t *testing.T) {\n\t\tcode, _, stderr := vet(t, \"golang.org/fake/c\")\n\t\texitcode(t, code, 1)\n\t\tsubstring(t, \"stderr\", stderr, \"c/c.go:5:5: self-assignment of i\")\n\t})\n\tt.Run(\"ab\", func(t *testing.T) {\n\t\tcode, _, stderr := vet(t, \"golang.org/fake/a\", \"golang.org/fake/b\")\n\t\texitcode(t, code, 1)\n\t\tsubstring(t, \"stderr\", stderr, \"a/a.go:4:11: call of MyFunc123\")\n\t\tsubstring(t, \"stderr\", stderr, \"b/b.go:6:13: call of MyFunc123\")\n\t\tsubstring(t, \"stderr\", stderr, \"b/b.go:7:11: call of MyFunc123\")\n\t})\n\tt.Run(\"a-json\", func(t *testing.T) {\n\t\tcode, stdout, _ := vet(t, \"-json\", \"golang.org/fake/a\")\n\t\texitcode(t, code, 0)\n\t\ttestenv.NeedsGo1Point(t, 26) // depends on CL 702815 (go vet -json => stdout)\n\t\tjson := parseJSON(t, stdout)\n\t\tsubstring(t, \"json\", json, \"a/a.go:4:11: [findcall@golang.org/fake/a] call of MyFunc123\")\n\t})\n\tt.Run(\"c-json\", func(t *testing.T) {\n\t\tcode, stdout, _ := vet(t, \"-json\", \"golang.org/fake/c\")\n\t\texitcode(t, code, 0)\n\t\ttestenv.NeedsGo1Point(t, 26) // depends on CL 702815 (go vet -json => stdout)\n\t\tjson := parseJSON(t, stdout)\n\t\tsubstring(t, \"json\", json, \"c/c.go:5:5: [assign@golang.org/fake/c] self-assignment of i\")\n\t})\n\tt.Run(\"a-context\", func(t *testing.T) {\n\t\tcode, _, stderr := vet(t, \"-c=0\", \"golang.org/fake/a\")\n\t\texitcode(t, code, 1)\n\t\tsubstring(t, \"stderr\", stderr, \"a/a.go:4:11: call of MyFunc123\")\n\t\tsubstring(t, \"stderr\", stderr, \"4\t\tMyFunc123\")\n\t})\n\tt.Run(\"d-fix\", func(t *testing.T) {\n\t\ttestenv.NeedsGo1Point(t, 26)\n\t\tcode, _, stderr := vet(t, \"-fix\", \"-v\", \"golang.org/fake/d\")\n\t\texitcode(t, code, 0)\n\t\tcontains(t, \"d/d.go\", `fmt.Sprintf(\"%s\", msg)`) // fixed\n\t\tcontains(t, \"d/dgen.go\", `fmt.Sprintf(msg)`)    // fix not applied to generated file\n\t\t// TODO(adonovan): plumb -v from go vet/fix down to unitchecker.\n\t\tif false {\n\t\t\tsubstring(t, \"stderr\", stderr, \"skipped 1 fix that would edit generated files\")\n\t\t\tsubstring(t, \"stderr\", stderr, \"applied 1 of 2 fixes; 1 files updated\")\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "go/analysis/unitchecker/vet_std_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unitchecker_test\n\nimport (\n\t\"go/version\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/passes/appends\"\n\t\"golang.org/x/tools/go/analysis/passes/asmdecl\"\n\t\"golang.org/x/tools/go/analysis/passes/assign\"\n\t\"golang.org/x/tools/go/analysis/passes/atomic\"\n\t\"golang.org/x/tools/go/analysis/passes/bools\"\n\t\"golang.org/x/tools/go/analysis/passes/buildtag\"\n\t\"golang.org/x/tools/go/analysis/passes/cgocall\"\n\t\"golang.org/x/tools/go/analysis/passes/composite\"\n\t\"golang.org/x/tools/go/analysis/passes/copylock\"\n\t\"golang.org/x/tools/go/analysis/passes/defers\"\n\t\"golang.org/x/tools/go/analysis/passes/directive\"\n\t\"golang.org/x/tools/go/analysis/passes/errorsas\"\n\t\"golang.org/x/tools/go/analysis/passes/framepointer\"\n\t\"golang.org/x/tools/go/analysis/passes/gofix\"\n\t\"golang.org/x/tools/go/analysis/passes/hostport\"\n\t\"golang.org/x/tools/go/analysis/passes/httpresponse\"\n\t\"golang.org/x/tools/go/analysis/passes/ifaceassert\"\n\t\"golang.org/x/tools/go/analysis/passes/loopclosure\"\n\t\"golang.org/x/tools/go/analysis/passes/lostcancel\"\n\t\"golang.org/x/tools/go/analysis/passes/nilfunc\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/passes/shift\"\n\t\"golang.org/x/tools/go/analysis/passes/sigchanyzer\"\n\t\"golang.org/x/tools/go/analysis/passes/stdmethods\"\n\t\"golang.org/x/tools/go/analysis/passes/stdversion\"\n\t\"golang.org/x/tools/go/analysis/passes/stringintconv\"\n\t\"golang.org/x/tools/go/analysis/passes/structtag\"\n\t\"golang.org/x/tools/go/analysis/passes/testinggoroutine\"\n\t\"golang.org/x/tools/go/analysis/passes/tests\"\n\t\"golang.org/x/tools/go/analysis/passes/timeformat\"\n\t\"golang.org/x/tools/go/analysis/passes/unmarshal\"\n\t\"golang.org/x/tools/go/analysis/passes/unreachable\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedresult\"\n\t\"golang.org/x/tools/go/analysis/unitchecker\"\n)\n\n// vet is the entrypoint of this executable when ENTRYPOINT=vet.\n// Keep consistent with the actual vet in GOROOT/src/cmd/vet/main.go.\nfunc vet() {\n\tunitchecker.Main(\n\t\tappends.Analyzer,\n\t\tasmdecl.Analyzer,\n\t\tassign.Analyzer,\n\t\tatomic.Analyzer,\n\t\tbools.Analyzer,\n\t\tbuildtag.Analyzer,\n\t\tcgocall.Analyzer,\n\t\tcomposite.Analyzer,\n\t\tcopylock.Analyzer,\n\t\tdefers.Analyzer,\n\t\tdirective.Analyzer,\n\t\terrorsas.Analyzer,\n\t\tframepointer.Analyzer,\n\t\tgofix.Analyzer,\n\t\thttpresponse.Analyzer,\n\t\thostport.Analyzer,\n\t\tifaceassert.Analyzer,\n\t\tloopclosure.Analyzer,\n\t\tlostcancel.Analyzer,\n\t\tnilfunc.Analyzer,\n\t\tprintf.Analyzer,\n\t\tshift.Analyzer,\n\t\tsigchanyzer.Analyzer,\n\t\tstdmethods.Analyzer,\n\t\tstdversion.Analyzer,\n\t\tstringintconv.Analyzer,\n\t\tstructtag.Analyzer,\n\t\ttestinggoroutine.Analyzer,\n\t\ttests.Analyzer,\n\t\ttimeformat.Analyzer,\n\t\tunmarshal.Analyzer,\n\t\tunreachable.Analyzer,\n\t\t// unsafeptr.Analyzer, // currently reports findings in runtime\n\t\tunusedresult.Analyzer,\n\t)\n}\n\n// TestVetStdlib runs the same analyzers as the actual vet over the\n// standard library, using go vet and unitchecker, to ensure that\n// there are no findings.\nfunc TestVetStdlib(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in -short mode\")\n\t}\n\tif builder := os.Getenv(\"GO_BUILDER_NAME\"); builder != \"\" && !strings.HasPrefix(builder, \"x_tools-gotip-\") {\n\t\t// Run on builders like x_tools-gotip-linux-amd64-longtest,\n\t\t// skip on others like x_tools-go1.24-linux-amd64-longtest.\n\t\tt.Skipf(\"This test is only wanted on development branches where code can be easily fixed. Skipping on non-gotip builder %q.\", builder)\n\t} else if v := runtime.Version(); !strings.Contains(v, \"devel\") || version.Compare(v, version.Lang(v)) != 0 {\n\t\t// Run on versions like \"go1.25-devel_9ce47e66e8 Wed Mar 26 03:48:50 2025 -0700\",\n\t\t// skip on others like \"go1.24.2\" or \"go1.24.2-devel_[…]\".\n\t\tt.Skipf(\"This test is only wanted on development versions where code can be easily fixed. Skipping on non-gotip version %q.\", v)\n\t}\n\n\tcmd := exec.Command(\"go\", \"vet\", \"-vettool=\"+os.Args[0], \"std\")\n\tcmd.Env = append(os.Environ(), \"ENTRYPOINT=vet\")\n\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Errorf(\"go vet std failed (%v):\\n%s\", err, out)\n\t}\n}\n"
  },
  {
    "path": "go/analysis/validate.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysis\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"unicode\"\n)\n\n// Validate reports an error if any of the analyzers are misconfigured.\n// Checks include:\n// that the name is a valid identifier;\n// that the Doc is not empty;\n// that the Run is non-nil;\n// that the Requires graph is acyclic;\n// that analyzer fact types are unique;\n// that each fact type is a pointer.\n//\n// Analyzer names need not be unique, though this may be confusing.\nfunc Validate(analyzers []*Analyzer) error {\n\t// Map each fact type to its sole generating analyzer.\n\tfactTypes := make(map[reflect.Type]*Analyzer)\n\n\t// Traverse the Requires graph, depth first.\n\tconst (\n\t\twhite = iota\n\t\tgrey\n\t\tblack\n\t\tfinished\n\t)\n\tcolor := make(map[*Analyzer]uint8)\n\tvar visit func(a *Analyzer) error\n\tvisit = func(a *Analyzer) error {\n\t\tif a == nil {\n\t\t\treturn fmt.Errorf(\"nil *Analyzer\")\n\t\t}\n\t\tif color[a] == white {\n\t\t\tcolor[a] = grey\n\n\t\t\t// names\n\t\t\tif !validIdent(a.Name) {\n\t\t\t\treturn fmt.Errorf(\"invalid analyzer name %q\", a)\n\t\t\t}\n\n\t\t\tif a.Doc == \"\" {\n\t\t\t\treturn fmt.Errorf(\"analyzer %q is undocumented\", a)\n\t\t\t}\n\n\t\t\tif a.Run == nil {\n\t\t\t\treturn fmt.Errorf(\"analyzer %q has nil Run\", a)\n\t\t\t}\n\t\t\t// fact types\n\t\t\tfor _, f := range a.FactTypes {\n\t\t\t\tif f == nil {\n\t\t\t\t\treturn fmt.Errorf(\"analyzer %s has nil FactType\", a)\n\t\t\t\t}\n\t\t\t\tt := reflect.TypeOf(f)\n\t\t\t\tif prev := factTypes[t]; prev != nil {\n\t\t\t\t\treturn fmt.Errorf(\"fact type %s registered by two analyzers: %v, %v\",\n\t\t\t\t\t\tt, a, prev)\n\t\t\t\t}\n\t\t\t\tif t.Kind() != reflect.Pointer {\n\t\t\t\t\treturn fmt.Errorf(\"%s: fact type %s is not a pointer\", a, t)\n\t\t\t\t}\n\t\t\t\tfactTypes[t] = a\n\t\t\t}\n\n\t\t\t// recursion\n\t\t\tfor _, req := range a.Requires {\n\t\t\t\tif err := visit(req); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\tcolor[a] = black\n\t\t}\n\n\t\tif color[a] == grey {\n\t\t\tstack := []*Analyzer{a}\n\t\t\tinCycle := map[string]bool{}\n\t\t\tfor len(stack) > 0 {\n\t\t\t\tcurrent := stack[len(stack)-1]\n\t\t\t\tstack = stack[:len(stack)-1]\n\t\t\t\tif color[current] == grey && !inCycle[current.Name] {\n\t\t\t\t\tinCycle[current.Name] = true\n\t\t\t\t\tstack = append(stack, current.Requires...)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn &CycleInRequiresGraphError{AnalyzerNames: inCycle}\n\t\t}\n\n\t\treturn nil\n\t}\n\tfor _, a := range analyzers {\n\t\tif err := visit(a); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Reject duplicates among analyzers.\n\t// Precondition:  color[a] == black.\n\t// Postcondition: color[a] == finished.\n\tfor _, a := range analyzers {\n\t\tif color[a] == finished {\n\t\t\treturn fmt.Errorf(\"duplicate analyzer: %s\", a.Name)\n\t\t}\n\t\tcolor[a] = finished\n\t}\n\n\treturn nil\n}\n\nfunc validIdent(name string) bool {\n\tfor i, r := range name {\n\t\tif !(r == '_' || unicode.IsLetter(r) || i > 0 && unicode.IsDigit(r)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn name != \"\"\n}\n\ntype CycleInRequiresGraphError struct {\n\tAnalyzerNames map[string]bool\n}\n\nfunc (e *CycleInRequiresGraphError) Error() string {\n\tvar b strings.Builder\n\tb.WriteString(\"cycle detected involving the following analyzers:\")\n\tfor n := range e.AnalyzerNames {\n\t\tb.WriteByte(' ')\n\t\tb.WriteString(n)\n\t}\n\treturn b.String()\n}\n"
  },
  {
    "path": "go/analysis/validate_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analysis\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestValidate(t *testing.T) {\n\tvar (\n\t\trun = func(p *Pass) (any, error) {\n\t\t\treturn nil, nil\n\t\t}\n\t\tdependsOnSelf = &Analyzer{\n\t\t\tName: \"dependsOnSelf\",\n\t\t\tDoc:  \"this analyzer depends on itself\",\n\t\t\tRun:  run,\n\t\t}\n\t\tinCycleA = &Analyzer{\n\t\t\tName: \"inCycleA\",\n\t\t\tDoc:  \"this analyzer depends on inCycleB\",\n\t\t\tRun:  run,\n\t\t}\n\t\tinCycleB = &Analyzer{\n\t\t\tName: \"inCycleB\",\n\t\t\tDoc:  \"this analyzer depends on inCycleA and notInCycleA\",\n\t\t\tRun:  run,\n\t\t}\n\t\tpointsToCycle = &Analyzer{\n\t\t\tName: \"pointsToCycle\",\n\t\t\tDoc:  \"this analyzer depends on inCycleA\",\n\t\t\tRun:  run,\n\t\t}\n\t\tnotInCycleA = &Analyzer{\n\t\t\tName: \"notInCycleA\",\n\t\t\tDoc:  \"this analyzer depends on notInCycleB and notInCycleC\",\n\t\t\tRun:  run,\n\t\t}\n\t\tnotInCycleB = &Analyzer{\n\t\t\tName: \"notInCycleB\",\n\t\t\tDoc:  \"this analyzer depends on notInCycleC\",\n\t\t\tRun:  run,\n\t\t}\n\t\tnotInCycleC = &Analyzer{\n\t\t\tName: \"notInCycleC\",\n\t\t\tDoc:  \"this analyzer has no dependencies\",\n\t\t\tRun:  run,\n\t\t}\n\t)\n\n\tdependsOnSelf.Requires = append(dependsOnSelf.Requires, dependsOnSelf)\n\tinCycleA.Requires = append(inCycleA.Requires, inCycleB)\n\tinCycleB.Requires = append(inCycleB.Requires, inCycleA, notInCycleA)\n\tpointsToCycle.Requires = append(pointsToCycle.Requires, inCycleA)\n\tnotInCycleA.Requires = append(notInCycleA.Requires, notInCycleB, notInCycleC)\n\tnotInCycleB.Requires = append(notInCycleB.Requires, notInCycleC)\n\tnotInCycleC.Requires = []*Analyzer{}\n\n\tcases := []struct {\n\t\tanalyzers        []*Analyzer\n\t\twantErr          bool\n\t\tanalyzersInCycle map[string]bool\n\t}{\n\t\t{\n\t\t\t[]*Analyzer{dependsOnSelf},\n\t\t\ttrue,\n\t\t\tmap[string]bool{\"dependsOnSelf\": true},\n\t\t},\n\t\t{\n\t\t\t[]*Analyzer{inCycleA, inCycleB},\n\t\t\ttrue,\n\t\t\tmap[string]bool{\"inCycleA\": true, \"inCycleB\": true},\n\t\t},\n\t\t{\n\t\t\t[]*Analyzer{pointsToCycle},\n\t\t\ttrue,\n\t\t\tmap[string]bool{\"inCycleA\": true, \"inCycleB\": true},\n\t\t},\n\t\t{\n\t\t\t[]*Analyzer{notInCycleA},\n\t\t\tfalse,\n\t\t\tmap[string]bool{},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tgot := Validate(c.analyzers)\n\n\t\tif !c.wantErr {\n\t\t\tif got == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tt.Errorf(\"got unexpected error while validating analyzers %v: %v\", c.analyzers, got)\n\t\t}\n\n\t\tif got == nil {\n\t\t\tt.Errorf(\"expected error while validating analyzers %v, but got nil\", c.analyzers)\n\t\t}\n\n\t\terr, ok := got.(*CycleInRequiresGraphError)\n\t\tif !ok {\n\t\t\tt.Errorf(\"want CycleInRequiresGraphError, got %T\", err)\n\t\t}\n\n\t\tfor a := range c.analyzersInCycle {\n\t\t\tif !err.AnalyzerNames[a] {\n\t\t\t\tt.Errorf(\"analyzer %s should be in cycle\", a)\n\t\t\t}\n\t\t}\n\t\tfor a := range err.AnalyzerNames {\n\t\t\tif !c.analyzersInCycle[a] {\n\t\t\t\tt.Errorf(\"analyzer %s should not be in cycle\", a)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCycleInRequiresGraphErrorMessage(t *testing.T) {\n\terr := CycleInRequiresGraphError{}\n\terrMsg := err.Error()\n\twantSubstring := \"cycle detected\"\n\tif !strings.Contains(errMsg, wantSubstring) {\n\t\tt.Errorf(\"error string %s does not contain expected substring %q\", errMsg, wantSubstring)\n\t}\n}\n\nfunc TestValidateEmptyDoc(t *testing.T) {\n\twithoutDoc := &Analyzer{\n\t\tName: \"withoutDoc\",\n\t\tRun: func(p *Pass) (any, error) {\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\terr := Validate([]*Analyzer{withoutDoc})\n\tif err == nil || !strings.Contains(err.Error(), \"is undocumented\") {\n\t\tt.Errorf(\"got unexpected error while validating analyzers withoutDoc: %v\", err)\n\t}\n}\n\nfunc TestValidateNoRun(t *testing.T) {\n\twithoutRun := &Analyzer{\n\t\tName: \"withoutRun\",\n\t\tDoc:  \"this analyzer has no Run\",\n\t}\n\terr := Validate([]*Analyzer{withoutRun})\n\tif err == nil || !strings.Contains(err.Error(), \"has nil Run\") {\n\t\tt.Errorf(\"got unexpected error while validating analyzers withoutRun: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "go/ast/astutil/enclosing.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\n// This file defines utilities for working with source positions.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"sort\"\n)\n\n// PathEnclosingInterval returns the node that encloses the source\n// interval [start, end), and all its ancestors up to the AST root.\n//\n// The definition of \"enclosing\" used by this function considers\n// additional whitespace abutting a node to be enclosed by it.\n// In this example:\n//\n//\tz := x + y // add them\n//\t     <-A->\n//\t    <----B----->\n//\n// the ast.BinaryExpr(+) node is considered to enclose interval B\n// even though its [Pos()..End()) is actually only interval A.\n// This behaviour makes user interfaces more tolerant of imperfect\n// input.\n//\n// This function treats tokens as nodes, though they are not included\n// in the result. e.g. PathEnclosingInterval(\"+\") returns the\n// enclosing ast.BinaryExpr(\"x + y\").\n//\n// If start==end, the 1-char interval following start is used instead.\n//\n// The 'exact' result is true if the interval contains only path[0]\n// and perhaps some adjacent whitespace.  It is false if the interval\n// overlaps multiple children of path[0], or if it contains only\n// interior whitespace of path[0].\n// In this example:\n//\n//\tz := x + y // add them\n//\t  <--C-->     <---E-->\n//\t    ^\n//\t    D\n//\n// intervals C, D and E are inexact.  C is contained by the\n// z-assignment statement, because it spans three of its children (:=,\n// x, +).  So too is the 1-char interval D, because it contains only\n// interior whitespace of the assignment.  E is considered interior\n// whitespace of the BlockStmt containing the assignment.\n//\n// The resulting path is never empty; it always contains at least the\n// 'root' *ast.File.  Ideally PathEnclosingInterval would reject\n// intervals that lie wholly or partially outside the range of the\n// file, but unfortunately ast.File records only the token.Pos of\n// the 'package' keyword, but not of the start of the file itself.\nfunc PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) {\n\t// fmt.Printf(\"EnclosingInterval %d %d\\n\", start, end) // debugging\n\n\t// Precondition: node.[Pos..End) and adjoining whitespace contain [start, end).\n\tvar visit func(node ast.Node) bool\n\tvisit = func(node ast.Node) bool {\n\t\tpath = append(path, node)\n\n\t\tnodePos := node.Pos()\n\t\tnodeEnd := node.End()\n\n\t\t// fmt.Printf(\"visit(%T, %d, %d)\\n\", node, nodePos, nodeEnd) // debugging\n\n\t\t// Intersect [start, end) with interval of node.\n\t\tif start < nodePos {\n\t\t\tstart = nodePos\n\t\t}\n\t\tif end > nodeEnd {\n\t\t\tend = nodeEnd\n\t\t}\n\n\t\t// Find sole child that contains [start, end).\n\t\tchildren := childrenOf(node)\n\t\tl := len(children)\n\t\tfor i, child := range children {\n\t\t\t// [childPos, childEnd) is unaugmented interval of child.\n\t\t\tchildPos := child.Pos()\n\t\t\tchildEnd := child.End()\n\n\t\t\t// [augPos, augEnd) is whitespace-augmented interval of child.\n\t\t\taugPos := childPos\n\t\t\taugEnd := childEnd\n\t\t\tif i > 0 {\n\t\t\t\taugPos = children[i-1].End() // start of preceding whitespace\n\t\t\t}\n\t\t\tif i < l-1 {\n\t\t\t\tnextChildPos := children[i+1].Pos()\n\t\t\t\t// Does [start, end) lie between child and next child?\n\t\t\t\tif start >= augEnd && end <= nextChildPos {\n\t\t\t\t\treturn false // inexact match\n\t\t\t\t}\n\t\t\t\taugEnd = nextChildPos // end of following whitespace\n\t\t\t}\n\n\t\t\t// fmt.Printf(\"\\tchild %d: [%d..%d)\\tcontains interval [%d..%d)?\\n\",\n\t\t\t// \ti, augPos, augEnd, start, end) // debugging\n\n\t\t\t// Does augmented child strictly contain [start, end)?\n\t\t\tif augPos <= start && end <= augEnd {\n\t\t\t\tif is[tokenNode](child) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\t// childrenOf elides the FuncType node beneath FuncDecl.\n\t\t\t\t// Add it back here for TypeParams, Params, Results,\n\t\t\t\t// all FieldLists). But we don't add it back for the \"func\" token\n\t\t\t\t// even though it is the tree at FuncDecl.Type.Func.\n\t\t\t\tif decl, ok := node.(*ast.FuncDecl); ok {\n\t\t\t\t\tif fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv {\n\t\t\t\t\t\tpath = append(path, decl.Type)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn visit(child)\n\t\t\t}\n\n\t\t\t// Does [start, end) overlap multiple children?\n\t\t\t// i.e. left-augmented child contains start\n\t\t\t// but LR-augmented child does not contain end.\n\t\t\tif start < childEnd && end > augEnd {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// No single child contained [start, end),\n\t\t// so node is the result.  Is it exact?\n\n\t\t// (It's tempting to put this condition before the\n\t\t// child loop, but it gives the wrong result in the\n\t\t// case where a node (e.g. ExprStmt) and its sole\n\t\t// child have equal intervals.)\n\t\tif start == nodePos && end == nodeEnd {\n\t\t\treturn true // exact match\n\t\t}\n\n\t\treturn false // inexact: overlaps multiple children\n\t}\n\n\t// Ensure [start,end) is nondecreasing.\n\tif start > end {\n\t\tstart, end = end, start\n\t}\n\n\tif start < root.End() && end > root.Pos() {\n\t\tif start == end {\n\t\t\tend = start + 1 // empty interval => interval of size 1\n\t\t}\n\t\texact = visit(root)\n\n\t\t// Reverse the path:\n\t\tfor i, l := 0, len(path); i < l/2; i++ {\n\t\t\tpath[i], path[l-1-i] = path[l-1-i], path[i]\n\t\t}\n\t} else {\n\t\t// Selection lies within whitespace preceding the\n\t\t// first (or following the last) declaration in the file.\n\t\t// The result nonetheless always includes the ast.File.\n\t\tpath = append(path, root)\n\t}\n\n\treturn\n}\n\n// tokenNode is a dummy implementation of ast.Node for a single token.\n// They are used transiently by PathEnclosingInterval but never escape\n// this package.\ntype tokenNode struct {\n\tpos token.Pos\n\tend token.Pos\n}\n\nfunc (n tokenNode) Pos() token.Pos {\n\treturn n.pos\n}\n\nfunc (n tokenNode) End() token.Pos {\n\treturn n.end\n}\n\nfunc tok(pos token.Pos, len int) ast.Node {\n\treturn tokenNode{pos, pos + token.Pos(len)}\n}\n\n// childrenOf returns the direct non-nil children of ast.Node n.\n// It may include fake ast.Node implementations for bare tokens.\n// it is not safe to call (e.g.) ast.Walk on such nodes.\nfunc childrenOf(n ast.Node) []ast.Node {\n\tvar children []ast.Node\n\n\t// First add nodes for all true subtrees.\n\tast.Inspect(n, func(node ast.Node) bool {\n\t\tif node == n { // push n\n\t\t\treturn true // recur\n\t\t}\n\t\tif node != nil { // push child\n\t\t\tchildren = append(children, node)\n\t\t}\n\t\treturn false // no recursion\n\t})\n\n\t// TODO(adonovan): be more careful about missing (!Pos.Valid)\n\t// tokens in trees produced from invalid input.\n\n\t// Then add fake Nodes for bare tokens.\n\tswitch n := n.(type) {\n\tcase *ast.ArrayType:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lbrack, len(\"[\")),\n\t\t\ttok(n.Elt.End(), len(\"]\")))\n\n\tcase *ast.AssignStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.TokPos, len(n.Tok.String())))\n\n\tcase *ast.BasicLit:\n\t\tchildren = append(children,\n\t\t\ttok(n.ValuePos, len(n.Value)))\n\n\tcase *ast.BinaryExpr:\n\t\tchildren = append(children, tok(n.OpPos, len(n.Op.String())))\n\n\tcase *ast.BlockStmt:\n\t\tif n.Lbrace.IsValid() {\n\t\t\tchildren = append(children, tok(n.Lbrace, len(\"{\")))\n\t\t}\n\t\tif n.Rbrace.IsValid() {\n\t\t\tchildren = append(children, tok(n.Rbrace, len(\"}\")))\n\t\t}\n\n\tcase *ast.BranchStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.TokPos, len(n.Tok.String())))\n\n\tcase *ast.CallExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lparen, len(\"(\")),\n\t\t\ttok(n.Rparen, len(\")\")))\n\t\tif n.Ellipsis != 0 {\n\t\t\tchildren = append(children, tok(n.Ellipsis, len(\"...\")))\n\t\t}\n\n\tcase *ast.CaseClause:\n\t\tif n.List == nil {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Case, len(\"default\")))\n\t\t} else {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Case, len(\"case\")))\n\t\t}\n\t\tchildren = append(children, tok(n.Colon, len(\":\")))\n\n\tcase *ast.ChanType:\n\t\tswitch n.Dir {\n\t\tcase ast.RECV:\n\t\t\tchildren = append(children, tok(n.Begin, len(\"<-chan\")))\n\t\tcase ast.SEND:\n\t\t\tchildren = append(children, tok(n.Begin, len(\"chan<-\")))\n\t\tcase ast.RECV | ast.SEND:\n\t\t\tchildren = append(children, tok(n.Begin, len(\"chan\")))\n\t\t}\n\n\tcase *ast.CommClause:\n\t\tif n.Comm == nil {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Case, len(\"default\")))\n\t\t} else {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Case, len(\"case\")))\n\t\t}\n\t\tchildren = append(children, tok(n.Colon, len(\":\")))\n\n\tcase *ast.Comment:\n\t\t// nop\n\n\tcase *ast.CommentGroup:\n\t\t// nop\n\n\tcase *ast.CompositeLit:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lbrace, len(\"{\")),\n\t\t\ttok(n.Rbrace, len(\"{\")))\n\n\tcase *ast.DeclStmt:\n\t\t// nop\n\n\tcase *ast.DeferStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Defer, len(\"defer\")))\n\n\tcase *ast.Ellipsis:\n\t\tchildren = append(children,\n\t\t\ttok(n.Ellipsis, len(\"...\")))\n\n\tcase *ast.EmptyStmt:\n\t\t// nop\n\n\tcase *ast.ExprStmt:\n\t\t// nop\n\n\tcase *ast.Field:\n\t\t// TODO(adonovan): Field.{Doc,Comment,Tag}?\n\n\tcase *ast.FieldList:\n\t\tif n.Opening.IsValid() {\n\t\t\tchildren = append(children, tok(n.Opening, len(\"(\")))\n\t\t}\n\t\tif n.Closing.IsValid() {\n\t\t\tchildren = append(children, tok(n.Closing, len(\")\")))\n\t\t}\n\n\tcase *ast.File:\n\t\t// TODO test: Doc\n\t\tchildren = append(children,\n\t\t\ttok(n.Package, len(\"package\")))\n\n\tcase *ast.ForStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.For, len(\"for\")))\n\n\tcase *ast.FuncDecl:\n\t\t// TODO(adonovan): FuncDecl.Comment?\n\n\t\t// Uniquely, FuncDecl breaks the invariant that\n\t\t// preorder traversal yields tokens in lexical order:\n\t\t// in fact, FuncDecl.Recv precedes FuncDecl.Type.Func.\n\t\t//\n\t\t// As a workaround, we inline the case for FuncType\n\t\t// here and order things correctly.\n\t\t// We also need to insert the elided FuncType just\n\t\t// before the 'visit' recursion.\n\t\t//\n\t\tchildren = nil // discard ast.Walk(FuncDecl) info subtrees\n\t\tchildren = append(children, tok(n.Type.Func, len(\"func\")))\n\t\tif n.Recv != nil {\n\t\t\tchildren = append(children, n.Recv)\n\t\t}\n\t\tchildren = append(children, n.Name)\n\t\tif tparams := n.Type.TypeParams; tparams != nil {\n\t\t\tchildren = append(children, tparams)\n\t\t}\n\t\tif n.Type.Params != nil {\n\t\t\tchildren = append(children, n.Type.Params)\n\t\t}\n\t\tif n.Type.Results != nil {\n\t\t\tchildren = append(children, n.Type.Results)\n\t\t}\n\t\tif n.Body != nil {\n\t\t\tchildren = append(children, n.Body)\n\t\t}\n\n\tcase *ast.FuncLit:\n\t\t// nop\n\n\tcase *ast.FuncType:\n\t\tif n.Func != 0 {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Func, len(\"func\")))\n\t\t}\n\n\tcase *ast.GenDecl:\n\t\tchildren = append(children,\n\t\t\ttok(n.TokPos, len(n.Tok.String())))\n\t\tif n.Lparen != 0 {\n\t\t\tchildren = append(children,\n\t\t\t\ttok(n.Lparen, len(\"(\")),\n\t\t\t\ttok(n.Rparen, len(\")\")))\n\t\t}\n\n\tcase *ast.GoStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Go, len(\"go\")))\n\n\tcase *ast.Ident:\n\t\tchildren = append(children,\n\t\t\ttok(n.NamePos, len(n.Name)))\n\n\tcase *ast.IfStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.If, len(\"if\")))\n\n\tcase *ast.ImportSpec:\n\t\t// TODO(adonovan): ImportSpec.{Doc,EndPos}?\n\n\tcase *ast.IncDecStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.TokPos, len(n.Tok.String())))\n\n\tcase *ast.IndexExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lbrack, len(\"[\")),\n\t\t\ttok(n.Rbrack, len(\"]\")))\n\n\tcase *ast.IndexListExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lbrack, len(\"[\")),\n\t\t\ttok(n.Rbrack, len(\"]\")))\n\n\tcase *ast.InterfaceType:\n\t\tchildren = append(children,\n\t\t\ttok(n.Interface, len(\"interface\")))\n\n\tcase *ast.KeyValueExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Colon, len(\":\")))\n\n\tcase *ast.LabeledStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Colon, len(\":\")))\n\n\tcase *ast.MapType:\n\t\tchildren = append(children,\n\t\t\ttok(n.Map, len(\"map\")))\n\n\tcase *ast.ParenExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lparen, len(\"(\")),\n\t\t\ttok(n.Rparen, len(\")\")))\n\n\tcase *ast.RangeStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.For, len(\"for\")),\n\t\t\ttok(n.TokPos, len(n.Tok.String())))\n\n\tcase *ast.ReturnStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Return, len(\"return\")))\n\n\tcase *ast.SelectStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Select, len(\"select\")))\n\n\tcase *ast.SelectorExpr:\n\t\t// nop\n\n\tcase *ast.SendStmt:\n\t\tchildren = append(children,\n\t\t\ttok(n.Arrow, len(\"<-\")))\n\n\tcase *ast.SliceExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lbrack, len(\"[\")),\n\t\t\ttok(n.Rbrack, len(\"]\")))\n\n\tcase *ast.StarExpr:\n\t\tchildren = append(children, tok(n.Star, len(\"*\")))\n\n\tcase *ast.StructType:\n\t\tchildren = append(children, tok(n.Struct, len(\"struct\")))\n\n\tcase *ast.SwitchStmt:\n\t\tchildren = append(children, tok(n.Switch, len(\"switch\")))\n\n\tcase *ast.TypeAssertExpr:\n\t\tchildren = append(children,\n\t\t\ttok(n.Lparen-1, len(\".\")),\n\t\t\ttok(n.Lparen, len(\"(\")),\n\t\t\ttok(n.Rparen, len(\")\")))\n\n\tcase *ast.TypeSpec:\n\t\t// TODO(adonovan): TypeSpec.{Doc,Comment}?\n\n\tcase *ast.TypeSwitchStmt:\n\t\tchildren = append(children, tok(n.Switch, len(\"switch\")))\n\n\tcase *ast.UnaryExpr:\n\t\tchildren = append(children, tok(n.OpPos, len(n.Op.String())))\n\n\tcase *ast.ValueSpec:\n\t\t// TODO(adonovan): ValueSpec.{Doc,Comment}?\n\n\tcase *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:\n\t\t// nop\n\t}\n\n\t// TODO(adonovan): opt: merge the logic of ast.Inspect() into\n\t// the switch above so we can make interleaved callbacks for\n\t// both Nodes and Tokens in the right order and avoid the need\n\t// to sort.\n\tsort.Sort(byPos(children))\n\n\treturn children\n}\n\ntype byPos []ast.Node\n\nfunc (sl byPos) Len() int {\n\treturn len(sl)\n}\nfunc (sl byPos) Less(i, j int) bool {\n\treturn sl[i].Pos() < sl[j].Pos()\n}\nfunc (sl byPos) Swap(i, j int) {\n\tsl[i], sl[j] = sl[j], sl[i]\n}\n\n// NodeDescription returns a description of the concrete type of n suitable\n// for a user interface.\n//\n// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident,\n// StarExpr) we could be much more specific given the path to the AST\n// root.  Perhaps we should do that.\nfunc NodeDescription(n ast.Node) string {\n\tswitch n := n.(type) {\n\tcase *ast.ArrayType:\n\t\treturn \"array type\"\n\tcase *ast.AssignStmt:\n\t\treturn \"assignment\"\n\tcase *ast.BadDecl:\n\t\treturn \"bad declaration\"\n\tcase *ast.BadExpr:\n\t\treturn \"bad expression\"\n\tcase *ast.BadStmt:\n\t\treturn \"bad statement\"\n\tcase *ast.BasicLit:\n\t\treturn \"basic literal\"\n\tcase *ast.BinaryExpr:\n\t\treturn fmt.Sprintf(\"binary %s operation\", n.Op)\n\tcase *ast.BlockStmt:\n\t\treturn \"block\"\n\tcase *ast.BranchStmt:\n\t\tswitch n.Tok {\n\t\tcase token.BREAK:\n\t\t\treturn \"break statement\"\n\t\tcase token.CONTINUE:\n\t\t\treturn \"continue statement\"\n\t\tcase token.GOTO:\n\t\t\treturn \"goto statement\"\n\t\tcase token.FALLTHROUGH:\n\t\t\treturn \"fall-through statement\"\n\t\t}\n\tcase *ast.CallExpr:\n\t\tif len(n.Args) == 1 && !n.Ellipsis.IsValid() {\n\t\t\treturn \"function call (or conversion)\"\n\t\t}\n\t\treturn \"function call\"\n\tcase *ast.CaseClause:\n\t\treturn \"case clause\"\n\tcase *ast.ChanType:\n\t\treturn \"channel type\"\n\tcase *ast.CommClause:\n\t\treturn \"communication clause\"\n\tcase *ast.Comment:\n\t\treturn \"comment\"\n\tcase *ast.CommentGroup:\n\t\treturn \"comment group\"\n\tcase *ast.CompositeLit:\n\t\treturn \"composite literal\"\n\tcase *ast.DeclStmt:\n\t\treturn NodeDescription(n.Decl) + \" statement\"\n\tcase *ast.DeferStmt:\n\t\treturn \"defer statement\"\n\tcase *ast.Ellipsis:\n\t\treturn \"ellipsis\"\n\tcase *ast.EmptyStmt:\n\t\treturn \"empty statement\"\n\tcase *ast.ExprStmt:\n\t\treturn \"expression statement\"\n\tcase *ast.Field:\n\t\t// Can be any of these:\n\t\t// struct {x, y int}  -- struct field(s)\n\t\t// struct {T}         -- anon struct field\n\t\t// interface {I}      -- interface embedding\n\t\t// interface {f()}    -- interface method\n\t\t// func (A) func(B) C -- receiver, param(s), result(s)\n\t\treturn \"field/method/parameter\"\n\tcase *ast.FieldList:\n\t\treturn \"field/method/parameter list\"\n\tcase *ast.File:\n\t\treturn \"source file\"\n\tcase *ast.ForStmt:\n\t\treturn \"for loop\"\n\tcase *ast.FuncDecl:\n\t\treturn \"function declaration\"\n\tcase *ast.FuncLit:\n\t\treturn \"function literal\"\n\tcase *ast.FuncType:\n\t\treturn \"function type\"\n\tcase *ast.GenDecl:\n\t\tswitch n.Tok {\n\t\tcase token.IMPORT:\n\t\t\treturn \"import declaration\"\n\t\tcase token.CONST:\n\t\t\treturn \"constant declaration\"\n\t\tcase token.TYPE:\n\t\t\treturn \"type declaration\"\n\t\tcase token.VAR:\n\t\t\treturn \"variable declaration\"\n\t\t}\n\tcase *ast.GoStmt:\n\t\treturn \"go statement\"\n\tcase *ast.Ident:\n\t\treturn \"identifier\"\n\tcase *ast.IfStmt:\n\t\treturn \"if statement\"\n\tcase *ast.ImportSpec:\n\t\treturn \"import specification\"\n\tcase *ast.IncDecStmt:\n\t\tif n.Tok == token.INC {\n\t\t\treturn \"increment statement\"\n\t\t}\n\t\treturn \"decrement statement\"\n\tcase *ast.IndexExpr:\n\t\treturn \"index expression\"\n\tcase *ast.IndexListExpr:\n\t\treturn \"index list expression\"\n\tcase *ast.InterfaceType:\n\t\treturn \"interface type\"\n\tcase *ast.KeyValueExpr:\n\t\treturn \"key/value association\"\n\tcase *ast.LabeledStmt:\n\t\treturn \"statement label\"\n\tcase *ast.MapType:\n\t\treturn \"map type\"\n\tcase *ast.Package:\n\t\treturn \"package\"\n\tcase *ast.ParenExpr:\n\t\treturn \"parenthesized \" + NodeDescription(n.X)\n\tcase *ast.RangeStmt:\n\t\treturn \"range loop\"\n\tcase *ast.ReturnStmt:\n\t\treturn \"return statement\"\n\tcase *ast.SelectStmt:\n\t\treturn \"select statement\"\n\tcase *ast.SelectorExpr:\n\t\treturn \"selector\"\n\tcase *ast.SendStmt:\n\t\treturn \"channel send\"\n\tcase *ast.SliceExpr:\n\t\treturn \"slice expression\"\n\tcase *ast.StarExpr:\n\t\treturn \"*-operation\" // load/store expr or pointer type\n\tcase *ast.StructType:\n\t\treturn \"struct type\"\n\tcase *ast.SwitchStmt:\n\t\treturn \"switch statement\"\n\tcase *ast.TypeAssertExpr:\n\t\treturn \"type assertion\"\n\tcase *ast.TypeSpec:\n\t\treturn \"type specification\"\n\tcase *ast.TypeSwitchStmt:\n\t\treturn \"type switch\"\n\tcase *ast.UnaryExpr:\n\t\treturn fmt.Sprintf(\"unary %s operation\", n.Op)\n\tcase *ast.ValueSpec:\n\t\treturn \"value specification\"\n\n\t}\n\tpanic(fmt.Sprintf(\"unexpected node type: %T\", n))\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n"
  },
  {
    "path": "go/ast/astutil/enclosing_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil_test\n\n// This file defines tests of PathEnclosingInterval.\n\n// TODO(adonovan): exhaustive tests that run over the whole input\n// tree, not just handcrafted examples.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n)\n\n// pathToString returns a string containing the concrete types of the\n// nodes in path.\nfunc pathToString(path []ast.Node) string {\n\tvar buf bytes.Buffer\n\tfmt.Fprint(&buf, \"[\")\n\tfor i, n := range path {\n\t\tif i > 0 {\n\t\t\tfmt.Fprint(&buf, \" \")\n\t\t}\n\t\tfmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf(\"%T\", n), \"*ast.\"))\n\t}\n\tfmt.Fprint(&buf, \"]\")\n\treturn buf.String()\n}\n\n// findInterval parses input and returns the [start, end) positions of\n// the first occurrence of substr in input.  f==nil indicates failure;\n// an error has already been reported in that case.\nfunc findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {\n\tf, err := parser.ParseFile(fset, \"<input>\", input, 0)\n\tif err != nil {\n\t\tt.Errorf(\"parse error: %s\", err)\n\t\treturn\n\t}\n\n\ti := strings.Index(input, substr)\n\tif i < 0 {\n\t\tt.Errorf(\"%q is not a substring of input\", substr)\n\t\tf = nil\n\t\treturn\n\t}\n\n\tfilePos := fset.File(f.Package)\n\treturn f, filePos.Pos(i), filePos.Pos(i + len(substr))\n}\n\n// Common input for following tests.\nconst input = `\n// Hello.\npackage main\nimport \"fmt\"\nfunc f() {}\nfunc main() {\n\tz := (x + y) // add them\n        f() // NB: ExprStmt and its CallExpr have same Pos/End\n}\n\nfunc g[A any, P interface{ctype1| ~ctype2}](a1 A, p1 P) {}\n\ntype PT[T constraint] struct{ t T }\n\nfunc (r recv) method(p param) {}\n\nvar v GT[targ1]\n\nvar h = g[ targ2, targ3]\n`\n\nfunc TestPathEnclosingInterval_Exact(t *testing.T) {\n\ttype testCase struct {\n\t\tsubstr string // first occurrence of this string indicates interval\n\t\tnode   string // complete text of expected containing node\n\t}\n\n\tdup := func(s string) testCase { return testCase{s, s} }\n\t// For the exact tests, we check that a substring is mapped to\n\t// the canonical string for the node it denotes.\n\ttests := []testCase{\n\t\t{\"package\",\n\t\t\tinput[11 : len(input)-1]},\n\t\t{\"\\npack\",\n\t\t\tinput[11 : len(input)-1]},\n\t\tdup(\"main\"),\n\t\t{\"import\",\n\t\t\t\"import \\\"fmt\\\"\"},\n\t\tdup(\"\\\"fmt\\\"\"),\n\t\t{\"\\nfunc f() {}\\n\",\n\t\t\t\"func f() {}\"},\n\t\t{\"x \",\n\t\t\t\"x\"},\n\t\t{\" y\",\n\t\t\t\"y\"},\n\t\tdup(\"z\"),\n\t\t{\" + \",\n\t\t\t\"x + y\"},\n\t\t{\" :=\",\n\t\t\t\"z := (x + y)\"},\n\t\tdup(\"x + y\"),\n\t\tdup(\"(x + y)\"),\n\t\t{\" (x + y) \",\n\t\t\t\"(x + y)\"},\n\t\t{\" (x + y) // add\",\n\t\t\t\"(x + y)\"},\n\t\t{\"func\",\n\t\t\t\"func f() {}\"},\n\t\tdup(\"func f() {}\"),\n\t\t{\"\\nfun\",\n\t\t\t\"func f() {}\"},\n\t\t{\" f\",\n\t\t\t\"f\"},\n\t\tdup(\"[A any, P interface{ctype1| ~ctype2}]\"),\n\t\t{\"[\", \"[A any, P interface{ctype1| ~ctype2}]\"},\n\t\tdup(\"A\"),\n\t\t{\" any\", \"any\"},\n\t\tdup(\"ctype1\"),\n\t\t{\"|\", \"ctype1| ~ctype2\"},\n\t\tdup(\"ctype2\"),\n\t\t{\"~\", \"~ctype2\"},\n\t\tdup(\"~ctype2\"),\n\t\t{\" ~ctype2\", \"~ctype2\"},\n\t\t{\"]\", \"[A any, P interface{ctype1| ~ctype2}]\"},\n\t\tdup(\"a1\"),\n\t\tdup(\"a1 A\"),\n\t\tdup(\"(a1 A, p1 P)\"),\n\t\tdup(\"type PT[T constraint] struct{ t T }\"),\n\t\tdup(\"PT\"),\n\t\tdup(\"[T constraint]\"),\n\t\tdup(\"constraint\"),\n\t\tdup(\"targ1\"),\n\t\t{\" targ2\", \"targ2\"},\n\t\tdup(\"g[ targ2, targ3]\"),\n\t}\n\tfor _, test := range tests {\n\t\tf, start, end := findInterval(t, new(token.FileSet), input, test.substr)\n\t\tif f == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tpath, exact := astutil.PathEnclosingInterval(f, start, end)\n\t\tif !exact {\n\t\t\tt.Errorf(\"PathEnclosingInterval(%q) not exact\", test.substr)\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(path) == 0 {\n\t\t\tif test.node != \"\" {\n\t\t\t\tt.Errorf(\"PathEnclosingInterval(%q).path: got [], want %q\",\n\t\t\t\t\ttest.substr, test.node)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif got := input[path[0].Pos():path[0].End()]; got != test.node {\n\t\t\tt.Errorf(\"PathEnclosingInterval(%q): got %q, want %q (path was %s)\",\n\t\t\t\ttest.substr, got, test.node, pathToString(path))\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc TestPathEnclosingInterval_Paths(t *testing.T) {\n\ttype testCase struct {\n\t\tsubstr string // first occurrence of this string indicates interval\n\t\tpath   string // the pathToString(),exact of the expected path\n\t}\n\t// For these tests, we check only the path of the enclosing\n\t// node, but not its complete text because it's often quite\n\t// large when !exact.\n\ttests := []testCase{\n\t\t{\"// add\",\n\t\t\t\"[BlockStmt FuncDecl File],false\"},\n\t\t{\"(x + y\",\n\t\t\t\"[ParenExpr AssignStmt BlockStmt FuncDecl File],false\"},\n\t\t{\"x +\",\n\t\t\t\"[BinaryExpr ParenExpr AssignStmt BlockStmt FuncDecl File],false\"},\n\t\t{\"z := (x\",\n\t\t\t\"[AssignStmt BlockStmt FuncDecl File],false\"},\n\t\t{\"func f\",\n\t\t\t\"[FuncDecl File],false\"},\n\t\t{\"func f()\",\n\t\t\t\"[FuncDecl File],false\"},\n\t\t{\" f()\",\n\t\t\t\"[FuncDecl File],false\"},\n\t\t{\"() {}\",\n\t\t\t\"[FuncDecl File],false\"},\n\t\t{\"// Hello\",\n\t\t\t\"[File],false\"},\n\t\t{\" f\",\n\t\t\t\"[Ident FuncDecl File],true\"},\n\t\t{\"func \",\n\t\t\t\"[FuncDecl File],true\"},\n\t\t{\"mai\",\n\t\t\t\"[Ident File],true\"},\n\t\t{\"f() // NB\",\n\t\t\t\"[CallExpr ExprStmt BlockStmt FuncDecl File],true\"},\n\t\t{\" any\", \"[Ident Field FieldList FuncType FuncDecl File],true\"},\n\t\t{\"|\", \"[BinaryExpr Field FieldList InterfaceType Field FieldList FuncType FuncDecl File],true\"},\n\t\t{\"ctype2\",\n\t\t\t\"[Ident UnaryExpr BinaryExpr Field FieldList InterfaceType Field FieldList FuncType FuncDecl File],true\"},\n\t\t{\"a1\", \"[Ident Field FieldList FuncType FuncDecl File],true\"},\n\t\t{\"PT[T constraint]\", \"[TypeSpec GenDecl File],false\"},\n\t\t{\"[T constraint]\", \"[FieldList TypeSpec GenDecl File],true\"},\n\t\t{\"targ2\", \"[Ident IndexListExpr ValueSpec GenDecl File],true\"},\n\t\t{\"p param\", \"[Field FieldList FuncType FuncDecl File],true\"}, // FuncType is present for FuncDecl.Params (etc)\n\t\t{\"r recv\", \"[Field FieldList FuncDecl File],true\"},           // no FuncType for FuncDecl.Recv\n\t}\n\tfor _, test := range tests {\n\t\tf, start, end := findInterval(t, new(token.FileSet), input, test.substr)\n\t\tif f == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tpath, exact := astutil.PathEnclosingInterval(f, start, end)\n\t\tif got := fmt.Sprintf(\"%s,%v\", pathToString(path), exact); got != test.path {\n\t\t\tt.Errorf(\"PathEnclosingInterval(%q): got %q, want %q\",\n\t\t\t\ttest.substr, got, test.path)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ast/astutil/imports.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package astutil contains common utilities for working with the Go AST.\npackage astutil // import \"golang.org/x/tools/go/ast/astutil\"\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// AddImport adds the import path to the file f, if absent.\nfunc AddImport(fset *token.FileSet, f *ast.File, path string) (added bool) {\n\treturn AddNamedImport(fset, f, \"\", path)\n}\n\n// AddNamedImport adds the import with the given name and path to the file f, if absent.\n// If name is not empty, it is used to rename the import.\n//\n// For example, calling\n//\n//\tAddNamedImport(fset, f, \"pathpkg\", \"path\")\n//\n// adds\n//\n//\timport pathpkg \"path\"\nfunc AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added bool) {\n\tif imports(f, name, path) {\n\t\treturn false\n\t}\n\n\tnewImport := &ast.ImportSpec{\n\t\tPath: &ast.BasicLit{\n\t\t\tKind:  token.STRING,\n\t\t\tValue: strconv.Quote(path),\n\t\t},\n\t}\n\tif name != \"\" {\n\t\tnewImport.Name = &ast.Ident{Name: name}\n\t}\n\n\t// Find an import decl to add to.\n\t// The goal is to find an existing import\n\t// whose import path has the longest shared\n\t// prefix with path.\n\tvar (\n\t\tbestMatch  = -1         // length of longest shared prefix\n\t\tlastImport = -1         // index in f.Decls of the file's final import decl\n\t\timpDecl    *ast.GenDecl // import decl containing the best match\n\t\timpIndex   = -1         // spec index in impDecl containing the best match\n\n\t\tisThirdPartyPath = isThirdParty(path)\n\t)\n\tfor i, decl := range f.Decls {\n\t\tgen, ok := decl.(*ast.GenDecl)\n\t\tif ok && gen.Tok == token.IMPORT {\n\t\t\tlastImport = i\n\t\t\t// Do not add to import \"C\", to avoid disrupting the\n\t\t\t// association with its doc comment, breaking cgo.\n\t\t\tif declImports(gen, \"C\") {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Match an empty import decl if that's all that is available.\n\t\t\tif len(gen.Specs) == 0 && bestMatch == -1 {\n\t\t\t\timpDecl = gen\n\t\t\t}\n\n\t\t\t// Compute longest shared prefix with imports in this group and find best\n\t\t\t// matched import spec.\n\t\t\t// 1. Always prefer import spec with longest shared prefix.\n\t\t\t// 2. While match length is 0,\n\t\t\t// - for stdlib package: prefer first import spec.\n\t\t\t// - for third party package: prefer first third party import spec.\n\t\t\t// We cannot use last import spec as best match for third party package\n\t\t\t// because grouped imports are usually placed last by goimports -local\n\t\t\t// flag.\n\t\t\t// See issue #19190.\n\t\t\tseenAnyThirdParty := false\n\t\t\tfor j, spec := range gen.Specs {\n\t\t\t\timpspec := spec.(*ast.ImportSpec)\n\t\t\t\tp := importPath(impspec)\n\t\t\t\tn := matchLen(p, path)\n\t\t\t\tif n > bestMatch || (bestMatch == 0 && !seenAnyThirdParty && isThirdPartyPath) {\n\t\t\t\t\tbestMatch = n\n\t\t\t\t\timpDecl = gen\n\t\t\t\t\timpIndex = j\n\t\t\t\t}\n\t\t\t\tseenAnyThirdParty = seenAnyThirdParty || isThirdParty(p)\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no import decl found, add one after the last import.\n\tif impDecl == nil {\n\t\timpDecl = &ast.GenDecl{\n\t\t\tTok: token.IMPORT,\n\t\t}\n\t\tif lastImport >= 0 {\n\t\t\timpDecl.TokPos = f.Decls[lastImport].End()\n\t\t} else {\n\t\t\t// There are no existing imports.\n\t\t\t// Our new import, preceded by a blank line,  goes after the package declaration\n\t\t\t// and after the comment, if any, that starts on the same line as the\n\t\t\t// package declaration.\n\t\t\timpDecl.TokPos = f.Package\n\n\t\t\tfile := fset.File(f.Package)\n\t\t\tpkgLine := file.Line(f.Package)\n\t\t\tfor _, c := range f.Comments {\n\t\t\t\tif file.Line(c.Pos()) > pkgLine {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// +2 for a blank line\n\t\t\t\timpDecl.TokPos = c.End() + 2\n\t\t\t}\n\t\t}\n\t\tf.Decls = append(f.Decls, nil)\n\t\tcopy(f.Decls[lastImport+2:], f.Decls[lastImport+1:])\n\t\tf.Decls[lastImport+1] = impDecl\n\t}\n\n\t// Insert new import at insertAt.\n\tinsertAt := 0\n\tif impIndex >= 0 {\n\t\t// insert after the found import\n\t\tinsertAt = impIndex + 1\n\t}\n\timpDecl.Specs = append(impDecl.Specs, nil)\n\tcopy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:])\n\timpDecl.Specs[insertAt] = newImport\n\tpos := impDecl.Pos()\n\tif insertAt > 0 {\n\t\t// If there is a comment after an existing import, preserve the comment\n\t\t// position by adding the new import after the comment.\n\t\tif spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil {\n\t\t\tpos = spec.Comment.End()\n\t\t} else {\n\t\t\t// Assign same position as the previous import,\n\t\t\t// so that the sorter sees it as being in the same block.\n\t\t\tpos = impDecl.Specs[insertAt-1].Pos()\n\t\t}\n\t}\n\tif newImport.Name != nil {\n\t\tnewImport.Name.NamePos = pos\n\t}\n\tupdateBasicLitPos(newImport.Path, pos)\n\tnewImport.EndPos = pos\n\n\t// Clean up parens. impDecl contains at least one spec.\n\tif len(impDecl.Specs) == 1 {\n\t\t// Remove unneeded parens.\n\t\timpDecl.Lparen = token.NoPos\n\t} else if !impDecl.Lparen.IsValid() {\n\t\t// impDecl needs parens added.\n\t\timpDecl.Lparen = impDecl.Specs[0].Pos()\n\t}\n\n\tf.Imports = append(f.Imports, newImport)\n\n\tif len(f.Decls) <= 1 {\n\t\treturn true\n\t}\n\n\t// Merge all the import declarations into the first one.\n\tvar first *ast.GenDecl\n\tfor i := 0; i < len(f.Decls); i++ {\n\t\tdecl := f.Decls[i]\n\t\tgen, ok := decl.(*ast.GenDecl)\n\t\tif !ok || gen.Tok != token.IMPORT || declImports(gen, \"C\") {\n\t\t\tcontinue\n\t\t}\n\t\tif first == nil {\n\t\t\tfirst = gen\n\t\t\tcontinue // Don't touch the first one.\n\t\t}\n\t\t// We now know there is more than one package in this import\n\t\t// declaration. Ensure that it ends up parenthesized.\n\t\tfirst.Lparen = first.Pos()\n\t\t// Move the imports of the other import declaration to the first one.\n\t\tfor _, spec := range gen.Specs {\n\t\t\tupdateBasicLitPos(spec.(*ast.ImportSpec).Path, first.Pos())\n\t\t\tfirst.Specs = append(first.Specs, spec)\n\t\t}\n\t\tf.Decls = slices.Delete(f.Decls, i, i+1)\n\t\ti--\n\t}\n\n\treturn true\n}\n\nfunc isThirdParty(importPath string) bool {\n\t// Third party package import path usually contains \".\" (\".com\", \".org\", ...)\n\t// This logic is taken from golang.org/x/tools/imports package.\n\treturn strings.Contains(importPath, \".\")\n}\n\n// DeleteImport deletes the import path from the file f, if present.\n// If there are duplicate import declarations, all matching ones are deleted.\nfunc DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) {\n\treturn DeleteNamedImport(fset, f, \"\", path)\n}\n\n// DeleteNamedImport deletes the import with the given name and path from the file f, if present.\n// If there are duplicate import declarations, all matching ones are deleted.\nfunc DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) {\n\tvar (\n\t\tdelspecs    = make(map[*ast.ImportSpec]bool)\n\t\tdelcomments = make(map[*ast.CommentGroup]bool)\n\t)\n\n\t// Find the import nodes that import path, if any.\n\tfor i := 0; i < len(f.Decls); i++ {\n\t\tgen, ok := f.Decls[i].(*ast.GenDecl)\n\t\tif !ok || gen.Tok != token.IMPORT {\n\t\t\tcontinue\n\t\t}\n\t\tfor j := 0; j < len(gen.Specs); j++ {\n\t\t\timpspec := gen.Specs[j].(*ast.ImportSpec)\n\t\t\tif importName(impspec) != name || importPath(impspec) != path {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// We found an import spec that imports path.\n\t\t\t// Delete it.\n\t\t\tdelspecs[impspec] = true\n\t\t\tdeleted = true\n\t\t\tgen.Specs = slices.Delete(gen.Specs, j, j+1)\n\n\t\t\t// If this was the last import spec in this decl,\n\t\t\t// delete the decl, too.\n\t\t\tif len(gen.Specs) == 0 {\n\t\t\t\tf.Decls = slices.Delete(f.Decls, i, i+1)\n\t\t\t\ti--\n\t\t\t\tbreak\n\t\t\t} else if len(gen.Specs) == 1 {\n\t\t\t\tif impspec.Doc != nil {\n\t\t\t\t\tdelcomments[impspec.Doc] = true\n\t\t\t\t}\n\t\t\t\tif impspec.Comment != nil {\n\t\t\t\t\tdelcomments[impspec.Comment] = true\n\t\t\t\t}\n\t\t\t\tfor _, cg := range f.Comments {\n\t\t\t\t\t// Found comment on the same line as the import spec.\n\t\t\t\t\tif cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line {\n\t\t\t\t\t\tdelcomments[cg] = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tspec := gen.Specs[0].(*ast.ImportSpec)\n\n\t\t\t\t// Move the documentation right after the import decl.\n\t\t\t\tif spec.Doc != nil {\n\t\t\t\t\tfor fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Doc.Pos()).Line {\n\t\t\t\t\t\tfset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor _, cg := range f.Comments {\n\t\t\t\t\tif cg.End() < spec.Pos() && fset.Position(cg.End()).Line == fset.Position(spec.Pos()).Line {\n\t\t\t\t\t\tfor fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Pos()).Line {\n\t\t\t\t\t\t\tfset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif j > 0 {\n\t\t\t\tlastImpspec := gen.Specs[j-1].(*ast.ImportSpec)\n\t\t\t\tlastLine := fset.PositionFor(lastImpspec.Path.ValuePos, false).Line\n\t\t\t\tline := fset.PositionFor(impspec.Path.ValuePos, false).Line\n\n\t\t\t\t// We deleted an entry but now there may be\n\t\t\t\t// a blank line-sized hole where the import was.\n\t\t\t\tif line-lastLine > 1 || !gen.Rparen.IsValid() {\n\t\t\t\t\t// There was a blank line immediately preceding the deleted import,\n\t\t\t\t\t// so there's no need to close the hole. The right parenthesis is\n\t\t\t\t\t// invalid after AddImport to an import statement without parenthesis.\n\t\t\t\t\t// Do nothing.\n\t\t\t\t} else if line != fset.File(gen.Rparen).LineCount() {\n\t\t\t\t\t// There was no blank line. Close the hole.\n\t\t\t\t\tfset.File(gen.Rparen).MergeLine(line)\n\t\t\t\t}\n\t\t\t}\n\t\t\tj--\n\t\t}\n\t}\n\n\t// Delete imports from f.Imports.\n\tbefore := len(f.Imports)\n\tf.Imports = slices.DeleteFunc(f.Imports, func(imp *ast.ImportSpec) bool {\n\t\t_, ok := delspecs[imp]\n\t\treturn ok\n\t})\n\tif len(f.Imports)+len(delspecs) != before {\n\t\t// This can happen when the AST is invalid (i.e. imports differ between f.Decls and f.Imports).\n\t\tpanic(fmt.Sprintf(\"deleted specs from Decls but not Imports: %v\", delspecs))\n\t}\n\n\t// Delete comments from f.Comments.\n\tf.Comments = slices.DeleteFunc(f.Comments, func(cg *ast.CommentGroup) bool {\n\t\t_, ok := delcomments[cg]\n\t\treturn ok\n\t})\n\n\treturn\n}\n\n// RewriteImport rewrites any import of path oldPath to path newPath.\nfunc RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) {\n\tfor _, imp := range f.Imports {\n\t\tif importPath(imp) == oldPath {\n\t\t\trewrote = true\n\t\t\t// record old End, because the default is to compute\n\t\t\t// it using the length of imp.Path.Value.\n\t\t\timp.EndPos = imp.End()\n\t\t\timp.Path.Value = strconv.Quote(newPath)\n\t\t}\n\t}\n\treturn\n}\n\n// UsesImport reports whether a given import is used.\n// The provided File must have been parsed with syntactic object resolution\n// (not using go/parser.SkipObjectResolution).\nfunc UsesImport(f *ast.File, path string) (used bool) {\n\tif f.Scope == nil {\n\t\tpanic(\"file f was not parsed with syntactic object resolution\")\n\t}\n\tspec := importSpec(f, path)\n\tif spec == nil {\n\t\treturn\n\t}\n\n\tname := spec.Name.String()\n\tswitch name {\n\tcase \"<nil>\":\n\t\t// If the package name is not explicitly specified,\n\t\t// make an educated guess. This is not guaranteed to be correct.\n\t\tlastSlash := strings.LastIndex(path, \"/\")\n\t\tif lastSlash == -1 {\n\t\t\tname = path\n\t\t} else {\n\t\t\tname = path[lastSlash+1:]\n\t\t}\n\tcase \"_\", \".\":\n\t\t// Not sure if this import is used - err on the side of caution.\n\t\treturn true\n\t}\n\n\tast.Walk(visitFn(func(n ast.Node) {\n\t\tsel, ok := n.(*ast.SelectorExpr)\n\t\tif ok && isTopName(sel.X, name) {\n\t\t\tused = true\n\t\t}\n\t}), f)\n\n\treturn\n}\n\ntype visitFn func(node ast.Node)\n\nfunc (fn visitFn) Visit(node ast.Node) ast.Visitor {\n\tfn(node)\n\treturn fn\n}\n\n// imports reports whether f has an import with the specified name and path.\nfunc imports(f *ast.File, name, path string) bool {\n\tfor _, s := range f.Imports {\n\t\tif importName(s) == name && importPath(s) == path {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// importSpec returns the import spec if f imports path,\n// or nil otherwise.\nfunc importSpec(f *ast.File, path string) *ast.ImportSpec {\n\tfor _, s := range f.Imports {\n\t\tif importPath(s) == path {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\n// importName returns the name of s,\n// or \"\" if the import is not named.\nfunc importName(s *ast.ImportSpec) string {\n\tif s.Name == nil {\n\t\treturn \"\"\n\t}\n\treturn s.Name.Name\n}\n\n// importPath returns the unquoted import path of s,\n// or \"\" if the path is not properly quoted.\nfunc importPath(s *ast.ImportSpec) string {\n\tt, err := strconv.Unquote(s.Path.Value)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn t\n}\n\n// declImports reports whether gen contains an import of path.\nfunc declImports(gen *ast.GenDecl, path string) bool {\n\tif gen.Tok != token.IMPORT {\n\t\treturn false\n\t}\n\tfor _, spec := range gen.Specs {\n\t\timpspec := spec.(*ast.ImportSpec)\n\t\tif importPath(impspec) == path {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// matchLen returns the length of the longest path segment prefix shared by x and y.\nfunc matchLen(x, y string) int {\n\tn := 0\n\tfor i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ {\n\t\tif x[i] == '/' {\n\t\t\tn++\n\t\t}\n\t}\n\treturn n\n}\n\n// isTopName returns true if n is a top-level unresolved identifier with the given name.\nfunc isTopName(n ast.Expr, name string) bool {\n\tid, ok := n.(*ast.Ident)\n\treturn ok && id.Name == name && id.Obj == nil\n}\n\n// Imports returns the file imports grouped by paragraph.\nfunc Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec {\n\tvar groups [][]*ast.ImportSpec\n\n\tfor _, decl := range f.Decls {\n\t\tgenDecl, ok := decl.(*ast.GenDecl)\n\t\tif !ok || genDecl.Tok != token.IMPORT {\n\t\t\tbreak\n\t\t}\n\n\t\tgroup := []*ast.ImportSpec{}\n\n\t\tvar lastLine int\n\t\tfor _, spec := range genDecl.Specs {\n\t\t\timportSpec := spec.(*ast.ImportSpec)\n\t\t\tpos := importSpec.Path.ValuePos\n\t\t\tline := fset.Position(pos).Line\n\t\t\tif lastLine > 0 && pos > 0 && line-lastLine > 1 {\n\t\t\t\tgroups = append(groups, group)\n\t\t\t\tgroup = []*ast.ImportSpec{}\n\t\t\t}\n\t\t\tgroup = append(group, importSpec)\n\t\t\tlastLine = line\n\t\t}\n\t\tgroups = append(groups, group)\n\t}\n\n\treturn groups\n}\n\n// updateBasicLitPos updates lit.Pos,\n// ensuring that lit.End (if set) is displaced by the same amount.\n// (See https://go.dev/issue/76395.)\nfunc updateBasicLitPos(lit *ast.BasicLit, pos token.Pos) {\n\tlen := lit.End() - lit.Pos()\n\tlit.ValuePos = pos\n\t// TODO(adonovan): after go1.26, simplify to:\n\t//   lit.ValueEnd = pos + len\n\tv := reflect.ValueOf(lit).Elem().FieldByName(\"ValueEnd\")\n\tif v.IsValid() && v.Int() != 0 {\n\t\tv.SetInt(int64(pos + len))\n\t}\n}\n"
  },
  {
    "path": "go/ast/astutil/imports_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n)\n\nvar fset = token.NewFileSet()\n\nfunc parse(t *testing.T, name, in string) *ast.File {\n\tfile, err := parser.ParseFile(fset, name, in, parser.ParseComments)\n\tif err != nil {\n\t\tt.Fatalf(\"%s parse: %v\", name, err)\n\t}\n\treturn file\n}\n\nfunc print(t *testing.T, name string, f *ast.File) string {\n\tvar buf bytes.Buffer\n\tif err := format.Node(&buf, fset, f); err != nil {\n\t\tt.Fatalf(\"%s gofmt: %v\", name, err)\n\t}\n\treturn buf.String()\n}\n\ntype test struct {\n\tname       string\n\trenamedPkg string\n\tpkg        string\n\tin         string\n\tout        string\n\tunchanged  bool // Expect added/deleted return value to be false.\n}\n\nvar addTests = []test{\n\t{\n\t\tname: \"leave os alone\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\nimport (\n\t\"os\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"os\"\n)\n`,\n\t\tunchanged: true,\n\t},\n\t{\n\t\tname: \"import.1\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n`,\n\t\tout: `package main\n\nimport \"os\"\n`,\n\t},\n\t{\n\t\tname: \"import.2\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\nimport \"os\"\n`,\n\t},\n\t{\n\t\tname: \"import.3\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"io\"\n\t\"utf8\"\n)\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.17\",\n\t\tpkg:  \"x/y/z\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"a\"\n\t\"b\"\n\n\t\"x/w\"\n\n\t\"d/f\"\n)\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"a\"\n\t\"b\"\n\n\t\"x/w\"\n\t\"x/y/z\"\n\n\t\"d/f\"\n)\n`,\n\t},\n\t{\n\t\tname: \"issue #19190\",\n\t\tpkg:  \"x.org/y/z\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\n\t\"d.com/f\"\n)\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\n\t\"d.com/f\"\n\t\"x.org/y/z\"\n)\n`,\n\t},\n\t{\n\t\tname: \"issue #19190 with existing grouped import packages\",\n\t\tpkg:  \"x.org/y/z\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\n\t\"c.com/f\"\n\t\"d.com/f\"\n\n\t\"y.com/a\"\n\t\"y.com/b\"\n\t\"y.com/c\"\n)\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\n\t\"c.com/f\"\n\t\"d.com/f\"\n\t\"x.org/y/z\"\n\n\t\"y.com/a\"\n\t\"y.com/b\"\n\t\"y.com/c\"\n)\n`,\n\t},\n\t{\n\t\tname: \"issue #19190 - match score is still respected\",\n\t\tpkg:  \"y.org/c\",\n\t\tin: `package main\n\nimport (\n\t\"x.org/a\"\n\n\t\"y.org/b\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"x.org/a\"\n\n\t\"y.org/b\"\n\t\"y.org/c\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import into singular group\",\n\t\tpkg:  \"bytes\",\n\t\tin: `package main\n\nimport \"os\"\n\n`,\n\t\tout: `package main\n\nimport (\n\t\"bytes\"\n\t\"os\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import into singular group with comment\",\n\t\tpkg:  \"bytes\",\n\t\tin: `package main\n\nimport /* why */ /* comment here? */ \"os\"\n\n`,\n\t\tout: `package main\n\nimport /* why */ /* comment here? */ (\n\t\"bytes\"\n\t\"os\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import into group with leading comment\",\n\t\tpkg:  \"strings\",\n\t\tin: `package main\n\nimport (\n\t// comment before bytes\n\t\"bytes\"\n\t\"os\"\n)\n\n`,\n\t\tout: `package main\n\nimport (\n\t// comment before bytes\n\t\"bytes\"\n\t\"os\"\n\t\"strings\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"\",\n\t\trenamedPkg: \"fmtpkg\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport \"os\"\n\n`,\n\t\tout: `package main\n\nimport (\n\tfmtpkg \"fmt\"\n\t\"os\"\n)\n`,\n\t},\n\t{\n\t\tname: \"struct comment\",\n\t\tpkg:  \"time\",\n\t\tin: `package main\n\n// This is a comment before a struct.\ntype T struct {\n\tt  time.Time\n}\n`,\n\t\tout: `package main\n\nimport \"time\"\n\n// This is a comment before a struct.\ntype T struct {\n\tt time.Time\n}\n`,\n\t},\n\t{\n\t\tname: \"issue 8729 import C\",\n\t\tpkg:  \"time\",\n\t\tin: `package main\n\nimport \"C\"\n\n// comment\ntype T time.Time\n`,\n\t\tout: `package main\n\nimport \"C\"\nimport \"time\"\n\n// comment\ntype T time.Time\n`,\n\t},\n\t{\n\t\tname: \"issue 8729 empty import\",\n\t\tpkg:  \"time\",\n\t\tin: `package main\n\nimport ()\n\n// comment\ntype T time.Time\n`,\n\t\tout: `package main\n\nimport \"time\"\n\n// comment\ntype T time.Time\n`,\n\t},\n\t{\n\t\tname: \"issue 8729 comment on package line\",\n\t\tpkg:  \"time\",\n\t\tin: `package main // comment\n\ntype T time.Time\n`,\n\t\tout: `package main // comment\n\nimport \"time\"\n\ntype T time.Time\n`,\n\t},\n\t{\n\t\tname: \"issue 8729 comment after package\",\n\t\tpkg:  \"time\",\n\t\tin: `package main\n// comment\n\ntype T time.Time\n`,\n\t\tout: `package main\n\nimport \"time\"\n\n// comment\n\ntype T time.Time\n`,\n\t},\n\t{\n\t\tname: \"issue 8729 comment before and on package line\",\n\t\tpkg:  \"time\",\n\t\tin: `// comment before\npackage main // comment on\n\ntype T time.Time\n`,\n\t\tout: `// comment before\npackage main // comment on\n\nimport \"time\"\n\ntype T time.Time\n`,\n\t},\n\n\t// Issue 9961: Match prefixes using path segments rather than bytes\n\t{\n\t\tname: \"issue 9961\",\n\t\tpkg:  \"regexp\",\n\t\tin: `package main\n\nimport (\n\t\"flag\"\n\t\"testing\"\n\n\t\"rsc.io/p\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"flag\"\n\t\"regexp\"\n\t\"testing\"\n\n\t\"rsc.io/p\"\n)\n`,\n\t},\n\t// Issue 10337: Preserve comment position\n\t{\n\t\tname: \"issue 10337\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"bytes\" // a\n\t\"log\" // c\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"bytes\" // a\n\t\"fmt\"\n\t\"log\" // c\n)\n`,\n\t},\n\t{\n\t\tname: \"issue 10337 new import at the start\",\n\t\tpkg:  \"bytes\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\" // b\n\t\"log\" // c\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\" // b\n\t\"log\" // c\n)\n`,\n\t},\n\t{\n\t\tname: \"issue 10337 new import at the end\",\n\t\tpkg:  \"log\",\n\t\tin: `package main\n\nimport (\n\t\"bytes\" // a\n\t\"fmt\" // b\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"bytes\" // a\n\t\"fmt\"   // b\n\t\"log\"\n)\n`,\n\t},\n\t// Issue 14075: Merge import declarations\n\t{\n\t\tname: \"issue 14075\",\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\nimport \"bytes\"\nimport \"fmt\"\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname: \"issue 14075 update position\",\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\nimport \"bytes\"\nimport (\n\t\"fmt\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 14075 ignore import \"C\"`,\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport \"bytes\"\nimport \"fmt\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 14075 ignore adjacent import \"C\"`,\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\nimport \"fmt\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\nimport (\n\t\"bufio\"\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 14075 ignore adjacent import \"C\" (without factored import)`,\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\nimport \"fmt\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\nimport (\n\t\"bufio\"\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 14075 ignore single import \"C\"`,\n\t\tpkg:  \"bufio\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\nimport \"bufio\"\n`,\n\t},\n\t{\n\t\tname: `issue 17212 several single-import lines with shared prefix ending in a slash`,\n\t\tpkg:  \"net/http\",\n\t\tin: `package main\n\nimport \"bufio\"\nimport \"net/url\"\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"net/http\"\n\t\"net/url\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 17212 block imports lines with shared prefix ending in a slash`,\n\t\tpkg:  \"net/http\",\n\t\tin: `package main\n\nimport (\n\t\"bufio\"\n\t\"net/url\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"net/http\"\n\t\"net/url\"\n)\n`,\n\t},\n\t{\n\t\tname: `issue 17213 many single-import lines`,\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport \"bufio\"\nimport \"bytes\"\nimport \"errors\"\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n)\n`,\n\t},\n\n\t// Issue 28605: Add specified import, even if that import path is imported under another name\n\t{\n\t\tname:       \"issue 28605 add unnamed path\",\n\t\trenamedPkg: \"\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"issue 28605 add pathpkg-renamed path\",\n\t\trenamedPkg: \"pathpkg\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"issue 28605 add blank identifier path\",\n\t\trenamedPkg: \"_\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"issue 28605 add dot import path\",\n\t\trenamedPkg: \".\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\n\t{\n\t\tname:       \"duplicate import declarations, add existing one\",\n\t\trenamedPkg: \"f\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport \"fmt\"\nimport \"fmt\"\nimport f \"fmt\"\nimport f \"fmt\"\n`,\n\t\tout: `package main\n\nimport \"fmt\"\nimport \"fmt\"\nimport f \"fmt\"\nimport f \"fmt\"\n`,\n\t\tunchanged: true,\n\t},\n}\n\nfunc TestAddImport(t *testing.T) {\n\tfor _, test := range addTests {\n\t\tfile := parse(t, test.name, test.in)\n\t\tvar before bytes.Buffer\n\t\tast.Fprint(&before, fset, file, nil)\n\t\tadded := AddNamedImport(fset, file, test.renamedPkg, test.pkg)\n\t\tif got := print(t, test.name, file); got != test.out {\n\t\t\tt.Errorf(\"first run: %s:\\ngot: %s\\nwant: %s\", test.name, got, test.out)\n\t\t\tvar after bytes.Buffer\n\t\t\tast.Fprint(&after, fset, file, nil)\n\t\t\tt.Logf(\"AST before:\\n%s\\nAST after:\\n%s\\n\", before.String(), after.String())\n\t\t}\n\t\tif got, want := added, !test.unchanged; got != want {\n\t\t\tt.Errorf(\"first run: %s: added = %v, want %v\", test.name, got, want)\n\t\t}\n\n\t\t// AddNamedImport should be idempotent. Verify that by calling it again,\n\t\t// expecting no change to the AST, and the returned added value to always be false.\n\t\tadded = AddNamedImport(fset, file, test.renamedPkg, test.pkg)\n\t\tif got := print(t, test.name, file); got != test.out {\n\t\t\tt.Errorf(\"second run: %s:\\ngot: %s\\nwant: %s\", test.name, got, test.out)\n\t\t}\n\t\tif got, want := added, false; got != want {\n\t\t\tt.Errorf(\"second run: %s: added = %v, want %v\", test.name, got, want)\n\t\t}\n\t}\n}\n\nfunc TestDoubleAddImport(t *testing.T) {\n\tfile := parse(t, \"doubleimport\", \"package main\\n\")\n\tAddImport(fset, file, \"os\")\n\tAddImport(fset, file, \"bytes\")\n\twant := `package main\n\nimport (\n\t\"bytes\"\n\t\"os\"\n)\n`\n\tif got := print(t, \"doubleimport\", file); got != want {\n\t\tt.Errorf(\"got: %s\\nwant: %s\", got, want)\n\t}\n}\n\nfunc TestDoubleAddNamedImport(t *testing.T) {\n\tfile := parse(t, \"doublenamedimport\", \"package main\\n\")\n\tAddNamedImport(fset, file, \"o\", \"os\")\n\tAddNamedImport(fset, file, \"i\", \"io\")\n\twant := `package main\n\nimport (\n\ti \"io\"\n\to \"os\"\n)\n`\n\tif got := print(t, \"doublenamedimport\", file); got != want {\n\t\tt.Errorf(\"got: %s\\nwant: %s\", got, want)\n\t}\n}\n\n// Part of issue 8729.\nfunc TestDoubleAddImportWithDeclComment(t *testing.T) {\n\tfile := parse(t, \"doubleimport\", `package main\n\nimport (\n)\n\n// comment\ntype I int\n`)\n\t// The AddImport order here matters.\n\tAddImport(fset, file, \"golang.org/x/tools/go/ast/astutil\")\n\tAddImport(fset, file, \"os\")\n\twant := `package main\n\nimport (\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"os\"\n)\n\n// comment\ntype I int\n`\n\tif got := print(t, \"doubleimport_with_decl_comment\", file); got != want {\n\t\tt.Errorf(\"got: %s\\nwant: %s\", got, want)\n\t}\n}\n\nvar deleteTests = []test{\n\t{\n\t\tname: \"import.4\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\nimport (\n\t\"os\"\n)\n`,\n\t\tout: `package main\n`,\n\t},\n\t{\n\t\tname: \"import.5\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\nimport \"os\"\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n`,\n\t},\n\t{\n\t\tname: \"import.6\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t\tout: `package main\n\n// Comment\nimport \"C\"\n\nimport (\n\t\"io\"\n\t\"utf8\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.7\",\n\t\tpkg:  \"io\",\n\t\tin: `package main\n\nimport (\n\t\"io\"   // a\n\t\"os\"   // b\n\t\"utf8\" // c\n)\n`,\n\t\tout: `package main\n\nimport (\n\t// a\n\t\"os\"   // b\n\t\"utf8\" // c\n)\n`,\n\t},\n\t{\n\t\tname: \"import.8\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\nimport (\n\t\"io\"   // a\n\t\"os\"   // b\n\t\"utf8\" // c\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"io\" // a\n\t// b\n\t\"utf8\" // c\n)\n`,\n\t},\n\t{\n\t\tname: \"import.9\",\n\t\tpkg:  \"utf8\",\n\t\tin: `package main\n\nimport (\n\t\"io\"   // a\n\t\"os\"   // b\n\t\"utf8\" // c\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"io\" // a\n\t\"os\" // b\n\t// c\n)\n`,\n\t},\n\t{\n\t\tname: \"import.10\",\n\t\tpkg:  \"io\",\n\t\tin: `package main\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.11\",\n\t\tpkg:  \"os\",\n\t\tin: `package main\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"io\"\n\t\"utf8\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.12\",\n\t\tpkg:  \"utf8\",\n\t\tin: `package main\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n`,\n\t},\n\t{\n\t\tname: \"handle.raw.quote.imports\",\n\t\tpkg:  \"os\",\n\t\tin:   \"package main\\n\\nimport `os`\",\n\t\tout: `package main\n`,\n\t},\n\t{\n\t\tname: \"import.13\",\n\t\tpkg:  \"io\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"io\"\n\t\"os\"\n\t\"utf8\"\n\n\t\"go/format\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"os\"\n\t\"utf8\"\n\n\t\"go/format\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.14\",\n\t\tpkg:  \"io\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\" // a\n\n\t\"io\"   // b\n\t\"os\"   // c\n\t\"utf8\" // d\n\n\t\"go/format\" // e\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\" // a\n\n\t// b\n\t\"os\"   // c\n\t\"utf8\" // d\n\n\t\"go/format\" // e\n)\n`,\n\t},\n\t{\n\t\tname: \"import.15\",\n\t\tpkg:  \"double\",\n\t\tin: `package main\n\nimport (\n\t\"double\"\n\t\"double\"\n)\n`,\n\t\tout: `package main\n`,\n\t},\n\t{\n\t\tname: \"import.16\",\n\t\tpkg:  \"bubble\",\n\t\tin: `package main\n\nimport (\n\t\"toil\"\n\t\"bubble\"\n\t\"bubble\"\n\t\"trouble\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"toil\"\n\t\"trouble\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.17\",\n\t\tpkg:  \"quad\",\n\t\tin: `package main\n\nimport (\n\t\"quad\"\n\t\"quad\"\n)\n\nimport (\n\t\"quad\"\n\t\"quad\"\n)\n`,\n\t\tout: `package main\n`,\n\t},\n\t{\n\t\tname:       \"import.18\",\n\t\trenamedPkg: \"x\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\tx \"fmt\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.18\",\n\t\trenamedPkg: \"x\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport x \"fmt\"\nimport y \"fmt\"\n`,\n\t\tout: `package main\n\nimport y \"fmt\"\n`,\n\t},\n\t// Issue #15432, #18051\n\t{\n\t\tname: \"import.19\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\n\t// Some comment.\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t// Some comment.\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.20\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\n\t// Some\n\t// comment.\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t// Some\n\t// comment.\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.21\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\n\t/*\n\t\tSome\n\t\tcomment.\n\t*/\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t/*\n\t\tSome\n\t\tcomment.\n\t*/\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.22\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t/* Some */\n\t// comment.\n\t\"io\"\n\t\"fmt\"\n)`,\n\t\tout: `package main\n\nimport (\n\t/* Some */\n\t// comment.\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.23\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t// comment 1\n\t\"fmt\"\n\t// comment 2\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t// comment 2\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.24\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\" // comment 1\n\t\"io\" // comment 2\n)`,\n\t\tout: `package main\n\nimport (\n\t\"io\" // comment 2\n)\n`,\n\t},\n\t{\n\t\tname: \"import.25\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\t/* comment */ \"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t/* comment */ \"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.26\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\t\"io\" /* comment */\n)`,\n\t\tout: `package main\n\nimport (\n\t\"io\" /* comment */\n)\n`,\n\t},\n\t{\n\t\tname: \"import.27\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\" /* comment */\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.28\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\nimport (\n\t/* comment */  \"fmt\"\n\t\"io\"\n)`,\n\t\tout: `package main\n\nimport (\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.29\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\t\"fmt\"\n\t\"io\" // comment 2\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\t\"io\" // comment 2\n)\n`,\n\t},\n\t{\n\t\tname: \"import.30\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\t\"fmt\" // comment 2\n\t\"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.31\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\t\"fmt\"\n\t/* comment 2 */ \"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\t/* comment 2 */ \"io\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.32\",\n\t\tpkg:        \"fmt\",\n\t\trenamedPkg: \"f\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\tf \"fmt\"\n\t/* comment 2 */ i \"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\t/* comment 2 */ i \"io\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.33\",\n\t\tpkg:        \"fmt\",\n\t\trenamedPkg: \"f\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\t/* comment 2 */ f \"fmt\"\n\ti \"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\ti \"io\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.34\",\n\t\tpkg:        \"fmt\",\n\t\trenamedPkg: \"f\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\tf \"fmt\" /* comment 2 */\n\ti \"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\ti \"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.35\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\n// comment 1\nimport (\n\t\"fmt\"\n\t// comment 2\n\t\"io\"\n)`,\n\t\tout: `package main\n\n// comment 1\nimport (\n\t// comment 2\n\t\"io\"\n)\n`,\n\t},\n\t{\n\t\tname: \"import.36\",\n\t\tpkg:  \"fmt\",\n\t\tin: `package main\n\n/* comment 1 */\nimport (\n\t\"fmt\"\n\t/* comment 2 */\n\t\"io\"\n)`,\n\t\tout: `package main\n\n/* comment 1 */\nimport (\n\t/* comment 2 */\n\t\"io\"\n)\n`,\n\t},\n\n\t// Issue 20229: MergeLine panic on weird input\n\t{\n\t\tname: \"import.37\",\n\t\tpkg:  \"io\",\n\t\tin: `package main\nimport(\"_\"\n\"io\")`,\n\t\tout: `package main\n\nimport (\n\t\"_\"\n)\n`,\n\t},\n\n\t// Issue 28605: Delete specified import, even if that import path is imported under another name\n\t{\n\t\tname:       \"import.38\",\n\t\trenamedPkg: \"\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.39\",\n\t\trenamedPkg: \"pathpkg\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.40\",\n\t\trenamedPkg: \"_\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\t{\n\t\tname:       \"import.41\",\n\t\trenamedPkg: \".\",\n\t\tpkg:        \"path\",\n\t\tin: `package main\n\nimport (\n\t\"path\"\n\t. \"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"path\"\n\t_ \"path\"\n\tpathpkg \"path\"\n)\n`,\n\t},\n\n\t// Duplicate import declarations, all matching ones are deleted.\n\t{\n\t\tname:       \"import.42\",\n\t\trenamedPkg: \"f\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport \"fmt\"\nimport \"fmt\"\nimport f \"fmt\"\nimport f \"fmt\"\n`,\n\t\tout: `package main\n\nimport \"fmt\"\nimport \"fmt\"\n`,\n\t},\n\t{\n\t\tname:       \"import.43\",\n\t\trenamedPkg: \"x\",\n\t\tpkg:        \"fmt\",\n\t\tin: `package main\n\nimport \"fmt\"\nimport \"fmt\"\nimport f \"fmt\"\nimport f \"fmt\"\n`,\n\t\tout: `package main\n\nimport \"fmt\"\nimport \"fmt\"\nimport f \"fmt\"\nimport f \"fmt\"\n`,\n\t\tunchanged: true,\n\t},\n\t// this test panics without PositionFor in DeleteNamedImport\n\t{\n\t\tname:       \"import.44\",\n\t\tpkg:        \"foo.com/other/v3\",\n\t\trenamedPkg: \"\",\n\t\tin: `package main\n//line mah.go:600\n\nimport (\n\"foo.com/a.thing\"\n\"foo.com/surprise\"\n\"foo.com/v1\"\n\"foo.com/other/v2\"\n\"foo.com/other/v3\"\n)\n`,\n\t\tout: `package main\n\n//line mah.go:600\n\nimport (\n\t\"foo.com/a.thing\"\n\t\"foo.com/other/v2\"\n\t\"foo.com/surprise\"\n\t\"foo.com/v1\"\n)\n`,\n\t},\n}\n\nfunc TestDeleteImport(t *testing.T) {\n\tfor _, test := range deleteTests {\n\t\tfile := parse(t, test.name, test.in)\n\t\tvar before bytes.Buffer\n\t\tast.Fprint(&before, fset, file, nil)\n\t\tdeleted := DeleteNamedImport(fset, file, test.renamedPkg, test.pkg)\n\t\tif got := print(t, test.name, file); got != test.out {\n\t\t\tt.Errorf(\"first run: %s:\\ngot: %s\\nwant: %s\", test.name, got, test.out)\n\t\t\tvar after bytes.Buffer\n\t\t\tast.Fprint(&after, fset, file, nil)\n\t\t\tt.Logf(\"AST before:\\n%s\\nAST after:\\n%s\\n\", before.String(), after.String())\n\t\t}\n\t\tif got, want := deleted, !test.unchanged; got != want {\n\t\t\tt.Errorf(\"first run: %s: deleted = %v, want %v\", test.name, got, want)\n\t\t}\n\n\t\t// DeleteNamedImport should be idempotent. Verify that by calling it again,\n\t\t// expecting no change to the AST, and the returned deleted value to always be false.\n\t\tdeleted = DeleteNamedImport(fset, file, test.renamedPkg, test.pkg)\n\t\tif got := print(t, test.name, file); got != test.out {\n\t\t\tt.Errorf(\"second run: %s:\\ngot: %s\\nwant: %s\", test.name, got, test.out)\n\t\t}\n\t\tif got, want := deleted, false; got != want {\n\t\t\tt.Errorf(\"second run: %s: deleted = %v, want %v\", test.name, got, want)\n\t\t}\n\t}\n}\n\nfunc TestDeleteImportAfterAddImport(t *testing.T) {\n\tfile := parse(t, \"test\", `package main\n\nimport \"os\"\n`)\n\tif got, want := AddImport(fset, file, \"fmt\"), true; got != want {\n\t\tt.Errorf(\"AddImport: got: %v, want: %v\", got, want)\n\t}\n\tif got, want := DeleteImport(fset, file, \"fmt\"), true; got != want {\n\t\tt.Errorf(\"DeleteImport: got: %v, want: %v\", got, want)\n\t}\n}\n\ntype rewriteTest struct {\n\tname   string\n\tsrcPkg string\n\tdstPkg string\n\tin     string\n\tout    string\n}\n\nvar rewriteTests = []rewriteTest{\n\t{\n\t\tname:   \"import.13\",\n\t\tsrcPkg: \"utf8\",\n\t\tdstPkg: \"encoding/utf8\",\n\t\tin: `package main\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"utf8\" // thanks ken\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"encoding/utf8\" // thanks ken\n\t\"io\"\n\t\"os\"\n)\n`,\n\t},\n\t{\n\t\tname:   \"import.14\",\n\t\tsrcPkg: \"asn1\",\n\t\tdstPkg: \"encoding/asn1\",\n\t\tin: `package main\n\nimport (\n\t\"asn1\"\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t_ \"crypto/sha1\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"time\"\n)\n\nvar x = 1\n`,\n\t\tout: `package main\n\nimport (\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t_ \"crypto/sha1\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/asn1\"\n\t\"time\"\n)\n\nvar x = 1\n`,\n\t},\n\t{\n\t\tname:   \"import.15\",\n\t\tsrcPkg: \"url\",\n\t\tdstPkg: \"net/url\",\n\t\tin: `package main\n\nimport (\n\t\"bufio\"\n\t\"net\"\n\t\"path\"\n\t\"url\"\n)\n\nvar x = 1 // comment on x, not on url\n`,\n\t\tout: `package main\n\nimport (\n\t\"bufio\"\n\t\"net\"\n\t\"net/url\"\n\t\"path\"\n)\n\nvar x = 1 // comment on x, not on url\n`,\n\t},\n\t{\n\t\tname:   \"import.16\",\n\t\tsrcPkg: \"http\",\n\t\tdstPkg: \"net/http\",\n\t\tin: `package main\n\nimport (\n\t\"flag\"\n\t\"http\"\n\t\"log\"\n\t\"text/template\"\n)\n\nvar addr = flag.String(\"addr\", \":1718\", \"http service address\") // Q=17, R=18\n`,\n\t\tout: `package main\n\nimport (\n\t\"flag\"\n\t\"log\"\n\t\"net/http\"\n\t\"text/template\"\n)\n\nvar addr = flag.String(\"addr\", \":1718\", \"http service address\") // Q=17, R=18\n`,\n\t},\n}\n\nfunc TestRewriteImport(t *testing.T) {\n\tfor _, test := range rewriteTests {\n\t\tfile := parse(t, test.name, test.in)\n\t\tRewriteImport(fset, file, test.srcPkg, test.dstPkg)\n\t\tif got := print(t, test.name, file); got != test.out {\n\t\t\tt.Errorf(\"%s:\\ngot: %s\\nwant: %s\", test.name, got, test.out)\n\t\t}\n\t}\n}\n\nvar importsTests = []struct {\n\tname string\n\tin   string\n\twant [][]string\n}{\n\t{\n\t\tname: \"no packages\",\n\t\tin: `package foo\n`,\n\t\twant: nil,\n\t},\n\t{\n\t\tname: \"one group\",\n\t\tin: `package foo\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n`,\n\t\twant: [][]string{{\"fmt\", \"testing\"}},\n\t},\n\t{\n\t\tname: \"four groups\",\n\t\tin: `package foo\n\nimport \"C\"\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"appengine\"\n\n\t\"myproject/mylib1\"\n\t\"myproject/mylib2\"\n)\n`,\n\t\twant: [][]string{\n\t\t\t{\"C\"},\n\t\t\t{\"fmt\", \"testing\"},\n\t\t\t{\"appengine\"},\n\t\t\t{\"myproject/mylib1\", \"myproject/mylib2\"},\n\t\t},\n\t},\n\t{\n\t\tname: \"multiple factored groups\",\n\t\tin: `package foo\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"appengine\"\n)\nimport (\n\t\"reflect\"\n\n\t\"bytes\"\n)\n`,\n\t\twant: [][]string{\n\t\t\t{\"fmt\", \"testing\"},\n\t\t\t{\"appengine\"},\n\t\t\t{\"reflect\"},\n\t\t\t{\"bytes\"},\n\t\t},\n\t},\n}\n\nfunc unquote(s string) string {\n\tres, err := strconv.Unquote(s)\n\tif err != nil {\n\t\treturn \"could_not_unquote\"\n\t}\n\treturn res\n}\n\nfunc TestImports(t *testing.T) {\n\tfset := token.NewFileSet()\n\tfor _, test := range importsTests {\n\t\tf, err := parser.ParseFile(fset, \"test.go\", test.in, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: %v\", test.name, err)\n\t\t\tcontinue\n\t\t}\n\t\tvar got [][]string\n\t\tfor _, group := range Imports(fset, f) {\n\t\t\tvar b []string\n\t\t\tfor _, spec := range group {\n\t\t\t\tb = append(b, unquote(spec.Path.Value))\n\t\t\t}\n\t\t\tgot = append(got, b)\n\t\t}\n\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\tt.Errorf(\"Imports(%s)=%v, want %v\", test.name, got, test.want)\n\t\t}\n\t}\n}\n\nvar usesImportTests = []struct {\n\tname string\n\tpath string\n\tin   string\n\twant bool\n}{\n\t{\n\t\tname: \"no packages\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.1\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport \"io\"\n\nvar _ io.Writer\n`,\n\t\twant: true,\n\t},\n\t{\n\t\tname: \"import.2\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport \"io\"\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.3\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport \"io\"\n\nvar io = 42\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.4\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport i \"io\"\n\nvar _ i.Writer\n`,\n\t\twant: true,\n\t},\n\t{\n\t\tname: \"import.5\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport i \"io\"\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.6\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport i \"io\"\n\nvar i = 42\nvar io = 42\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.7\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport \"encoding/json\"\n\nvar _ json.Encoder\n`,\n\t\twant: true,\n\t},\n\t{\n\t\tname: \"import.8\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport \"encoding/json\"\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.9\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport \"encoding/json\"\n\nvar json = 42\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.10\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport j \"encoding/json\"\n\nvar _ j.Encoder\n`,\n\t\twant: true,\n\t},\n\t{\n\t\tname: \"import.11\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport j \"encoding/json\"\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.12\",\n\t\tpath: \"encoding/json\",\n\t\tin: `package foo\n\nimport j \"encoding/json\"\n\nvar j = 42\nvar json = 42\n`,\n\t\twant: false,\n\t},\n\t{\n\t\tname: \"import.13\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport _ \"io\"\n`,\n\t\twant: true,\n\t},\n\t{\n\t\tname: \"import.14\",\n\t\tpath: \"io\",\n\t\tin: `package foo\n\nimport . \"io\"\n`,\n\t\twant: true,\n\t},\n}\n\nfunc TestUsesImport(t *testing.T) {\n\tfset := token.NewFileSet()\n\tfor _, test := range usesImportTests {\n\t\tf, err := parser.ParseFile(fset, \"test.go\", test.in, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: %v\", test.name, err)\n\t\t\tcontinue\n\t\t}\n\t\tgot := UsesImport(f, test.path)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"UsesImport(%s)=%v, want %v\", test.name, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ast/astutil/rewrite.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"reflect\"\n\t\"sort\"\n)\n\n// An ApplyFunc is invoked by Apply for each node n, even if n is nil,\n// before and/or after the node's children, using a Cursor describing\n// the current node and providing operations on it.\n//\n// The return value of ApplyFunc controls the syntax tree traversal.\n// See Apply for details.\ntype ApplyFunc func(*Cursor) bool\n\n// Apply traverses a syntax tree recursively, starting with root,\n// and calling pre and post for each node as described below.\n// Apply returns the syntax tree, possibly modified.\n//\n// If pre is not nil, it is called for each node before the node's\n// children are traversed (pre-order). If pre returns false, no\n// children are traversed, and post is not called for that node.\n//\n// If post is not nil, and a prior call of pre didn't return false,\n// post is called for each node after its children are traversed\n// (post-order). If post returns false, traversal is terminated and\n// Apply returns immediately.\n//\n// Only fields that refer to AST nodes are considered children;\n// i.e., token.Pos, Scopes, Objects, and fields of basic types\n// (strings, etc.) are ignored.\n//\n// Children are traversed in the order in which they appear in the\n// respective node's struct definition. A package's files are\n// traversed in the filenames' alphabetical order.\nfunc Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) {\n\tparent := &struct{ ast.Node }{root}\n\tdefer func() {\n\t\tif r := recover(); r != nil && r != abort {\n\t\t\tpanic(r)\n\t\t}\n\t\tresult = parent.Node\n\t}()\n\ta := &application{pre: pre, post: post}\n\ta.apply(parent, \"Node\", nil, root)\n\treturn\n}\n\nvar abort = new(int) // singleton, to signal termination of Apply\n\n// A Cursor describes a node encountered during Apply.\n// Information about the node and its parent is available\n// from the Node, Parent, Name, and Index methods.\n//\n// If p is a variable of type and value of the current parent node\n// c.Parent(), and f is the field identifier with name c.Name(),\n// the following invariants hold:\n//\n//\tp.f            == c.Node()  if c.Index() <  0\n//\tp.f[c.Index()] == c.Node()  if c.Index() >= 0\n//\n// The methods Replace, Delete, InsertBefore, and InsertAfter\n// can be used to change the AST without disrupting Apply.\n//\n// This type is not to be confused with [inspector.Cursor] from\n// package [golang.org/x/tools/go/ast/inspector], which provides\n// stateless navigation of immutable syntax trees.\ntype Cursor struct {\n\tparent ast.Node\n\tname   string\n\titer   *iterator // valid if non-nil\n\tnode   ast.Node\n}\n\n// Node returns the current Node.\nfunc (c *Cursor) Node() ast.Node { return c.node }\n\n// Parent returns the parent of the current Node.\nfunc (c *Cursor) Parent() ast.Node { return c.parent }\n\n// Name returns the name of the parent Node field that contains the current Node.\n// If the parent is a *ast.Package and the current Node is a *ast.File, Name returns\n// the filename for the current Node.\nfunc (c *Cursor) Name() string { return c.name }\n\n// Index reports the index >= 0 of the current Node in the slice of Nodes that\n// contains it, or a value < 0 if the current Node is not part of a slice.\n// The index of the current node changes if InsertBefore is called while\n// processing the current node.\nfunc (c *Cursor) Index() int {\n\tif c.iter != nil {\n\t\treturn c.iter.index\n\t}\n\treturn -1\n}\n\n// field returns the current node's parent field value.\nfunc (c *Cursor) field() reflect.Value {\n\treturn reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name)\n}\n\n// Replace replaces the current Node with n.\n// The replacement node is not walked by Apply.\nfunc (c *Cursor) Replace(n ast.Node) {\n\tif _, ok := c.node.(*ast.File); ok {\n\t\tfile, ok := n.(*ast.File)\n\t\tif !ok {\n\t\t\tpanic(\"attempt to replace *ast.File with non-*ast.File\")\n\t\t}\n\t\tc.parent.(*ast.Package).Files[c.name] = file\n\t\treturn\n\t}\n\n\tv := c.field()\n\tif i := c.Index(); i >= 0 {\n\t\tv = v.Index(i)\n\t}\n\tv.Set(reflect.ValueOf(n))\n}\n\n// Delete deletes the current Node from its containing slice.\n// If the current Node is not part of a slice, Delete panics.\n// As a special case, if the current node is a package file,\n// Delete removes it from the package's Files map.\nfunc (c *Cursor) Delete() {\n\tif _, ok := c.node.(*ast.File); ok {\n\t\tdelete(c.parent.(*ast.Package).Files, c.name)\n\t\treturn\n\t}\n\n\ti := c.Index()\n\tif i < 0 {\n\t\tpanic(\"Delete node not contained in slice\")\n\t}\n\tv := c.field()\n\tl := v.Len()\n\treflect.Copy(v.Slice(i, l), v.Slice(i+1, l))\n\tv.Index(l - 1).Set(reflect.Zero(v.Type().Elem()))\n\tv.SetLen(l - 1)\n\tc.iter.step--\n}\n\n// InsertAfter inserts n after the current Node in its containing slice.\n// If the current Node is not part of a slice, InsertAfter panics.\n// Apply does not walk n.\nfunc (c *Cursor) InsertAfter(n ast.Node) {\n\ti := c.Index()\n\tif i < 0 {\n\t\tpanic(\"InsertAfter node not contained in slice\")\n\t}\n\tv := c.field()\n\tv.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))\n\tl := v.Len()\n\treflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l))\n\tv.Index(i + 1).Set(reflect.ValueOf(n))\n\tc.iter.step++\n}\n\n// InsertBefore inserts n before the current Node in its containing slice.\n// If the current Node is not part of a slice, InsertBefore panics.\n// Apply will not walk n.\nfunc (c *Cursor) InsertBefore(n ast.Node) {\n\ti := c.Index()\n\tif i < 0 {\n\t\tpanic(\"InsertBefore node not contained in slice\")\n\t}\n\tv := c.field()\n\tv.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))\n\tl := v.Len()\n\treflect.Copy(v.Slice(i+1, l), v.Slice(i, l))\n\tv.Index(i).Set(reflect.ValueOf(n))\n\tc.iter.index++\n}\n\n// application carries all the shared data so we can pass it around cheaply.\ntype application struct {\n\tpre, post ApplyFunc\n\tcursor    Cursor\n\titer      iterator\n}\n\nfunc (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) {\n\t// convert typed nil into untyped nil\n\tif v := reflect.ValueOf(n); v.Kind() == reflect.Pointer && v.IsNil() {\n\t\tn = nil\n\t}\n\n\t// avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead\n\tsaved := a.cursor\n\ta.cursor.parent = parent\n\ta.cursor.name = name\n\ta.cursor.iter = iter\n\ta.cursor.node = n\n\n\tif a.pre != nil && !a.pre(&a.cursor) {\n\t\ta.cursor = saved\n\t\treturn\n\t}\n\n\t// walk children\n\t// (the order of the cases matches the order of the corresponding node types in go/ast)\n\tswitch n := n.(type) {\n\tcase nil:\n\t\t// nothing to do\n\n\t// Comments and fields\n\tcase *ast.Comment:\n\t\t// nothing to do\n\n\tcase *ast.CommentGroup:\n\t\tif n != nil {\n\t\t\ta.applyList(n, \"List\")\n\t\t}\n\n\tcase *ast.Field:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.applyList(n, \"Names\")\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.apply(n, \"Tag\", nil, n.Tag)\n\t\ta.apply(n, \"Comment\", nil, n.Comment)\n\n\tcase *ast.FieldList:\n\t\ta.applyList(n, \"List\")\n\n\t// Expressions\n\tcase *ast.BadExpr, *ast.Ident, *ast.BasicLit:\n\t\t// nothing to do\n\n\tcase *ast.Ellipsis:\n\t\ta.apply(n, \"Elt\", nil, n.Elt)\n\n\tcase *ast.FuncLit:\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\tcase *ast.CompositeLit:\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.applyList(n, \"Elts\")\n\n\tcase *ast.ParenExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\n\tcase *ast.SelectorExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Sel\", nil, n.Sel)\n\n\tcase *ast.IndexExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Index\", nil, n.Index)\n\n\tcase *ast.IndexListExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.applyList(n, \"Indices\")\n\n\tcase *ast.SliceExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Low\", nil, n.Low)\n\t\ta.apply(n, \"High\", nil, n.High)\n\t\ta.apply(n, \"Max\", nil, n.Max)\n\n\tcase *ast.TypeAssertExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\n\tcase *ast.CallExpr:\n\t\ta.apply(n, \"Fun\", nil, n.Fun)\n\t\ta.applyList(n, \"Args\")\n\n\tcase *ast.StarExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\n\tcase *ast.UnaryExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\n\tcase *ast.BinaryExpr:\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Y\", nil, n.Y)\n\n\tcase *ast.KeyValueExpr:\n\t\ta.apply(n, \"Key\", nil, n.Key)\n\t\ta.apply(n, \"Value\", nil, n.Value)\n\n\t// Types\n\tcase *ast.ArrayType:\n\t\ta.apply(n, \"Len\", nil, n.Len)\n\t\ta.apply(n, \"Elt\", nil, n.Elt)\n\n\tcase *ast.StructType:\n\t\ta.apply(n, \"Fields\", nil, n.Fields)\n\n\tcase *ast.FuncType:\n\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\ta.apply(n, \"TypeParams\", nil, tparams)\n\t\t}\n\t\ta.apply(n, \"Params\", nil, n.Params)\n\t\ta.apply(n, \"Results\", nil, n.Results)\n\n\tcase *ast.InterfaceType:\n\t\ta.apply(n, \"Methods\", nil, n.Methods)\n\n\tcase *ast.MapType:\n\t\ta.apply(n, \"Key\", nil, n.Key)\n\t\ta.apply(n, \"Value\", nil, n.Value)\n\n\tcase *ast.ChanType:\n\t\ta.apply(n, \"Value\", nil, n.Value)\n\n\t// Statements\n\tcase *ast.BadStmt:\n\t\t// nothing to do\n\n\tcase *ast.DeclStmt:\n\t\ta.apply(n, \"Decl\", nil, n.Decl)\n\n\tcase *ast.EmptyStmt:\n\t\t// nothing to do\n\n\tcase *ast.LabeledStmt:\n\t\ta.apply(n, \"Label\", nil, n.Label)\n\t\ta.apply(n, \"Stmt\", nil, n.Stmt)\n\n\tcase *ast.ExprStmt:\n\t\ta.apply(n, \"X\", nil, n.X)\n\n\tcase *ast.SendStmt:\n\t\ta.apply(n, \"Chan\", nil, n.Chan)\n\t\ta.apply(n, \"Value\", nil, n.Value)\n\n\tcase *ast.IncDecStmt:\n\t\ta.apply(n, \"X\", nil, n.X)\n\n\tcase *ast.AssignStmt:\n\t\ta.applyList(n, \"Lhs\")\n\t\ta.applyList(n, \"Rhs\")\n\n\tcase *ast.GoStmt:\n\t\ta.apply(n, \"Call\", nil, n.Call)\n\n\tcase *ast.DeferStmt:\n\t\ta.apply(n, \"Call\", nil, n.Call)\n\n\tcase *ast.ReturnStmt:\n\t\ta.applyList(n, \"Results\")\n\n\tcase *ast.BranchStmt:\n\t\ta.apply(n, \"Label\", nil, n.Label)\n\n\tcase *ast.BlockStmt:\n\t\ta.applyList(n, \"List\")\n\n\tcase *ast.IfStmt:\n\t\ta.apply(n, \"Init\", nil, n.Init)\n\t\ta.apply(n, \"Cond\", nil, n.Cond)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\t\ta.apply(n, \"Else\", nil, n.Else)\n\n\tcase *ast.CaseClause:\n\t\ta.applyList(n, \"List\")\n\t\ta.applyList(n, \"Body\")\n\n\tcase *ast.SwitchStmt:\n\t\ta.apply(n, \"Init\", nil, n.Init)\n\t\ta.apply(n, \"Tag\", nil, n.Tag)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\tcase *ast.TypeSwitchStmt:\n\t\ta.apply(n, \"Init\", nil, n.Init)\n\t\ta.apply(n, \"Assign\", nil, n.Assign)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\tcase *ast.CommClause:\n\t\ta.apply(n, \"Comm\", nil, n.Comm)\n\t\ta.applyList(n, \"Body\")\n\n\tcase *ast.SelectStmt:\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\tcase *ast.ForStmt:\n\t\ta.apply(n, \"Init\", nil, n.Init)\n\t\ta.apply(n, \"Cond\", nil, n.Cond)\n\t\ta.apply(n, \"Post\", nil, n.Post)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\tcase *ast.RangeStmt:\n\t\ta.apply(n, \"Key\", nil, n.Key)\n\t\ta.apply(n, \"Value\", nil, n.Value)\n\t\ta.apply(n, \"X\", nil, n.X)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\t// Declarations\n\tcase *ast.ImportSpec:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.apply(n, \"Name\", nil, n.Name)\n\t\ta.apply(n, \"Path\", nil, n.Path)\n\t\ta.apply(n, \"Comment\", nil, n.Comment)\n\n\tcase *ast.ValueSpec:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.applyList(n, \"Names\")\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.applyList(n, \"Values\")\n\t\ta.apply(n, \"Comment\", nil, n.Comment)\n\n\tcase *ast.TypeSpec:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.apply(n, \"Name\", nil, n.Name)\n\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\ta.apply(n, \"TypeParams\", nil, tparams)\n\t\t}\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.apply(n, \"Comment\", nil, n.Comment)\n\n\tcase *ast.BadDecl:\n\t\t// nothing to do\n\n\tcase *ast.GenDecl:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.applyList(n, \"Specs\")\n\n\tcase *ast.FuncDecl:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.apply(n, \"Recv\", nil, n.Recv)\n\t\ta.apply(n, \"Name\", nil, n.Name)\n\t\ta.apply(n, \"Type\", nil, n.Type)\n\t\ta.apply(n, \"Body\", nil, n.Body)\n\n\t// Files and packages\n\tcase *ast.File:\n\t\ta.apply(n, \"Doc\", nil, n.Doc)\n\t\ta.apply(n, \"Name\", nil, n.Name)\n\t\ta.applyList(n, \"Decls\")\n\t\t// Don't walk n.Comments; they have either been walked already if\n\t\t// they are Doc comments, or they can be easily walked explicitly.\n\n\tcase *ast.Package:\n\t\t// collect and sort names for reproducible behavior\n\t\tvar names []string\n\t\tfor name := range n.Files {\n\t\t\tnames = append(names, name)\n\t\t}\n\t\tsort.Strings(names)\n\t\tfor _, name := range names {\n\t\t\ta.apply(n, name, nil, n.Files[name])\n\t\t}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"Apply: unexpected node type %T\", n))\n\t}\n\n\tif a.post != nil && !a.post(&a.cursor) {\n\t\tpanic(abort)\n\t}\n\n\ta.cursor = saved\n}\n\n// An iterator controls iteration over a slice of nodes.\ntype iterator struct {\n\tindex, step int\n}\n\nfunc (a *application) applyList(parent ast.Node, name string) {\n\t// avoid heap-allocating a new iterator for each applyList call; reuse a.iter instead\n\tsaved := a.iter\n\ta.iter.index = 0\n\tfor {\n\t\t// must reload parent.name each time, since cursor modifications might change it\n\t\tv := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name)\n\t\tif a.iter.index >= v.Len() {\n\t\t\tbreak\n\t\t}\n\n\t\t// element x may be nil in a bad AST - be cautious\n\t\tvar x ast.Node\n\t\tif e := v.Index(a.iter.index); e.IsValid() {\n\t\t\tx = e.Interface().(ast.Node)\n\t\t}\n\n\t\ta.iter.step = 1\n\t\ta.apply(parent, name, &a.iter, x)\n\t\ta.iter.index += a.iter.step\n\t}\n\ta.iter = saved\n}\n"
  },
  {
    "path": "go/ast/astutil/rewrite_test.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil_test\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n)\n\ntype rewriteTest struct {\n\tname       string\n\torig, want string\n\tpre, post  astutil.ApplyFunc\n}\n\nvar rewriteTests = []rewriteTest{\n\t{name: \"nop\", orig: \"package p\\n\", want: \"package p\\n\"},\n\n\t{name: \"replace\",\n\t\torig: `package p\n\nvar x int\n`,\n\t\twant: `package p\n\nvar t T\n`,\n\t\tpost: func(c *astutil.Cursor) bool {\n\t\t\tif _, ok := c.Node().(*ast.ValueSpec); ok {\n\t\t\t\tc.Replace(valspec(\"t\", \"T\"))\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"set doc strings\",\n\t\torig: `package p\n\nconst z = 0\n\ntype T struct{}\n\nvar x int\n`,\n\t\twant: `package p\n// a foo is a foo\nconst z = 0\n// a foo is a foo\ntype T struct{}\n// a foo is a foo\nvar x int\n`,\n\t\tpost: func(c *astutil.Cursor) bool {\n\t\t\tif _, ok := c.Parent().(*ast.GenDecl); ok && c.Name() == \"Doc\" && c.Node() == nil {\n\t\t\t\tc.Replace(&ast.CommentGroup{List: []*ast.Comment{{Text: \"// a foo is a foo\"}}})\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"insert names\",\n\t\torig: `package p\n\nconst a = 1\n`,\n\t\twant: `package p\n\nconst a, b, c = 1, 2, 3\n`,\n\t\tpre: func(c *astutil.Cursor) bool {\n\t\t\tif _, ok := c.Parent().(*ast.ValueSpec); ok {\n\t\t\t\tswitch c.Name() {\n\t\t\t\tcase \"Names\":\n\t\t\t\t\tc.InsertAfter(ast.NewIdent(\"c\"))\n\t\t\t\t\tc.InsertAfter(ast.NewIdent(\"b\"))\n\t\t\t\tcase \"Values\":\n\t\t\t\t\tc.InsertAfter(&ast.BasicLit{Kind: token.INT, Value: \"3\"})\n\t\t\t\t\tc.InsertAfter(&ast.BasicLit{Kind: token.INT, Value: \"2\"})\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"insert\",\n\t\torig: `package p\n\nvar (\n\tx int\n\ty int\n)\n`,\n\t\twant: `package p\n\nvar before1 int\nvar before2 int\n\nvar (\n\tx int\n\ty int\n)\nvar after2 int\nvar after1 int\n`,\n\t\tpre: func(c *astutil.Cursor) bool {\n\t\t\tif _, ok := c.Node().(*ast.GenDecl); ok {\n\t\t\t\tc.InsertBefore(vardecl(\"before1\", \"int\"))\n\t\t\t\tc.InsertAfter(vardecl(\"after1\", \"int\"))\n\t\t\t\tc.InsertAfter(vardecl(\"after2\", \"int\"))\n\t\t\t\tc.InsertBefore(vardecl(\"before2\", \"int\"))\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"delete\",\n\t\torig: `package p\n\nvar x int\nvar y int\nvar z int\n`,\n\t\twant: `package p\n\nvar y int\nvar z int\n`,\n\t\tpre: func(c *astutil.Cursor) bool {\n\t\t\tn := c.Node()\n\t\t\tif d, ok := n.(*ast.GenDecl); ok && d.Specs[0].(*ast.ValueSpec).Names[0].Name == \"x\" {\n\t\t\t\tc.Delete()\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"insertafter-delete\",\n\t\torig: `package p\n\nvar x int\nvar y int\nvar z int\n`,\n\t\twant: `package p\n\nvar x1 int\n\nvar y int\nvar z int\n`,\n\t\tpre: func(c *astutil.Cursor) bool {\n\t\t\tn := c.Node()\n\t\t\tif d, ok := n.(*ast.GenDecl); ok && d.Specs[0].(*ast.ValueSpec).Names[0].Name == \"x\" {\n\t\t\t\tc.InsertAfter(vardecl(\"x1\", \"int\"))\n\t\t\t\tc.Delete()\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\n\t{name: \"delete-insertafter\",\n\t\torig: `package p\n\nvar x int\nvar y int\nvar z int\n`,\n\t\twant: `package p\n\nvar y int\nvar x1 int\nvar z int\n`,\n\t\tpre: func(c *astutil.Cursor) bool {\n\t\t\tn := c.Node()\n\t\t\tif d, ok := n.(*ast.GenDecl); ok && d.Specs[0].(*ast.ValueSpec).Names[0].Name == \"x\" {\n\t\t\t\tc.Delete()\n\t\t\t\t// The cursor is now effectively atop the 'var y int' node.\n\t\t\t\tc.InsertAfter(vardecl(\"x1\", \"int\"))\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n\t{\n\t\tname: \"replace\",\n\t\torig: `package p\n\ntype T[P1, P2 any] int\n\ntype R T[int, string]\n\nfunc F[Q1 any](q Q1) {}\n`,\n\t\t// TODO: note how the rewrite adds a trailing comma in \"func F\".\n\t\t// Is that a bug in the test, or in astutil.Apply?\n\t\twant: `package p\n\ntype S[R1, P2 any] int32\n\ntype R S[int32, string]\n\nfunc F[X1 any](q X1,) {}\n`,\n\t\tpost: func(c *astutil.Cursor) bool {\n\t\t\tif ident, ok := c.Node().(*ast.Ident); ok {\n\t\t\t\tswitch ident.Name {\n\t\t\t\tcase \"int\":\n\t\t\t\t\tc.Replace(ast.NewIdent(\"int32\"))\n\t\t\t\tcase \"T\":\n\t\t\t\t\tc.Replace(ast.NewIdent(\"S\"))\n\t\t\t\tcase \"P1\":\n\t\t\t\t\tc.Replace(ast.NewIdent(\"R1\"))\n\t\t\t\tcase \"Q1\":\n\t\t\t\t\tc.Replace(ast.NewIdent(\"X1\"))\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t},\n}\n\nfunc valspec(name, typ string) *ast.ValueSpec {\n\treturn &ast.ValueSpec{Names: []*ast.Ident{ast.NewIdent(name)},\n\t\tType: ast.NewIdent(typ),\n\t}\n}\n\nfunc vardecl(name, typ string) *ast.GenDecl {\n\treturn &ast.GenDecl{\n\t\tTok:   token.VAR,\n\t\tSpecs: []ast.Spec{valspec(name, typ)},\n\t}\n}\n\nfunc TestRewrite(t *testing.T) {\n\tt.Run(\"*\", func(t *testing.T) {\n\t\tfor _, test := range rewriteTests {\n\t\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\tfset := token.NewFileSet()\n\t\t\t\tf, err := parser.ParseFile(fset, test.name, test.orig, parser.ParseComments)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tn := astutil.Apply(f, test.pre, test.post)\n\t\t\t\tvar buf bytes.Buffer\n\t\t\t\tif err := format.Node(&buf, fset, n); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tgot := buf.String()\n\t\t\t\tif got != test.want {\n\t\t\t\t\tt.Errorf(\"got:\\n\\n%s\\nwant:\\n\\n%s\\n\", got, test.want)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}\n\nvar sink ast.Node\n\nfunc BenchmarkRewrite(b *testing.B) {\n\tfor _, test := range rewriteTests {\n\t\tb.Run(test.name, func(b *testing.B) {\n\t\t\tfor b.Loop() {\n\t\t\t\tb.StopTimer()\n\t\t\t\tfset := token.NewFileSet()\n\t\t\t\tf, err := parser.ParseFile(fset, test.name, test.orig, parser.ParseComments)\n\t\t\t\tif err != nil {\n\t\t\t\t\tb.Fatal(err)\n\t\t\t\t}\n\t\t\t\tb.StartTimer()\n\t\t\t\tsink = astutil.Apply(f, test.pre, test.post)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/ast/astutil/util.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport \"go/ast\"\n\n// Unparen returns e with any enclosing parentheses stripped.\n// Deprecated: use [ast.Unparen].\n//\n//go:fix inline\nfunc Unparen(e ast.Expr) ast.Expr { return ast.Unparen(e) }\n"
  },
  {
    "path": "go/ast/edge/edge.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package edge defines identifiers for each field of an ast.Node\n// struct type that refers to another Node.\npackage edge\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"reflect\"\n)\n\n// A Kind describes a field of an ast.Node struct.\ntype Kind uint8\n\n// String returns a description of the edge kind.\nfunc (k Kind) String() string {\n\tif k == Invalid {\n\t\treturn \"<invalid>\"\n\t}\n\tinfo := fieldInfos[k]\n\treturn fmt.Sprintf(\"%v.%s\", info.nodeType.Elem().Name(), info.name)\n}\n\n// NodeType returns the pointer-to-struct type of the ast.Node implementation.\nfunc (k Kind) NodeType() reflect.Type { return fieldInfos[k].nodeType }\n\n// FieldName returns the name of the field.\nfunc (k Kind) FieldName() string { return fieldInfos[k].name }\n\n// FieldType returns the declared type of the field.\nfunc (k Kind) FieldType() reflect.Type { return fieldInfos[k].fieldType }\n\n// Get returns the direct child of n identified by (k, idx).\n// n's type must match k.NodeType().\n// idx must be a valid slice index, or -1 for a non-slice.\nfunc (k Kind) Get(n ast.Node, idx int) ast.Node {\n\tif k.NodeType() != reflect.TypeOf(n) {\n\t\tpanic(fmt.Sprintf(\"%v.Get(%T): invalid node type\", k, n))\n\t}\n\tv := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)\n\tif idx != -1 {\n\t\tv = v.Index(idx) // asserts valid index\n\t} else {\n\t\t// (The type assertion below asserts that v is not a slice.)\n\t}\n\treturn v.Interface().(ast.Node) // may be nil\n}\n\nconst (\n\tInvalid Kind = iota // for nodes at the root of the traversal\n\n\t// Kinds are sorted alphabetically.\n\t// Numbering is not stable.\n\t// Each is named Type_Field, where Type is the\n\t// ast.Node struct type and Field is the name of the field\n\n\tArrayType_Elt\n\tArrayType_Len\n\tAssignStmt_Lhs\n\tAssignStmt_Rhs\n\tBinaryExpr_X\n\tBinaryExpr_Y\n\tBlockStmt_List\n\tBranchStmt_Label\n\tCallExpr_Args\n\tCallExpr_Fun\n\tCaseClause_Body\n\tCaseClause_List\n\tChanType_Value\n\tCommClause_Body\n\tCommClause_Comm\n\tCommentGroup_List\n\tCompositeLit_Elts\n\tCompositeLit_Type\n\tDeclStmt_Decl\n\tDeferStmt_Call\n\tEllipsis_Elt\n\tExprStmt_X\n\tFieldList_List\n\tField_Comment\n\tField_Doc\n\tField_Names\n\tField_Tag\n\tField_Type\n\tFile_Decls\n\tFile_Doc\n\tFile_Name\n\tForStmt_Body\n\tForStmt_Cond\n\tForStmt_Init\n\tForStmt_Post\n\tFuncDecl_Body\n\tFuncDecl_Doc\n\tFuncDecl_Name\n\tFuncDecl_Recv\n\tFuncDecl_Type\n\tFuncLit_Body\n\tFuncLit_Type\n\tFuncType_Params\n\tFuncType_Results\n\tFuncType_TypeParams\n\tGenDecl_Doc\n\tGenDecl_Specs\n\tGoStmt_Call\n\tIfStmt_Body\n\tIfStmt_Cond\n\tIfStmt_Else\n\tIfStmt_Init\n\tImportSpec_Comment\n\tImportSpec_Doc\n\tImportSpec_Name\n\tImportSpec_Path\n\tIncDecStmt_X\n\tIndexExpr_Index\n\tIndexExpr_X\n\tIndexListExpr_Indices\n\tIndexListExpr_X\n\tInterfaceType_Methods\n\tKeyValueExpr_Key\n\tKeyValueExpr_Value\n\tLabeledStmt_Label\n\tLabeledStmt_Stmt\n\tMapType_Key\n\tMapType_Value\n\tParenExpr_X\n\tRangeStmt_Body\n\tRangeStmt_Key\n\tRangeStmt_Value\n\tRangeStmt_X\n\tReturnStmt_Results\n\tSelectStmt_Body\n\tSelectorExpr_Sel\n\tSelectorExpr_X\n\tSendStmt_Chan\n\tSendStmt_Value\n\tSliceExpr_High\n\tSliceExpr_Low\n\tSliceExpr_Max\n\tSliceExpr_X\n\tStarExpr_X\n\tStructType_Fields\n\tSwitchStmt_Body\n\tSwitchStmt_Init\n\tSwitchStmt_Tag\n\tTypeAssertExpr_Type\n\tTypeAssertExpr_X\n\tTypeSpec_Comment\n\tTypeSpec_Doc\n\tTypeSpec_Name\n\tTypeSpec_Type\n\tTypeSpec_TypeParams\n\tTypeSwitchStmt_Assign\n\tTypeSwitchStmt_Body\n\tTypeSwitchStmt_Init\n\tUnaryExpr_X\n\tValueSpec_Comment\n\tValueSpec_Doc\n\tValueSpec_Names\n\tValueSpec_Type\n\tValueSpec_Values\n\n\tmaxKind\n)\n\n// Assert that the encoding fits in 7 bits,\n// as the inspector relies on this.\n// (We are currently at 104.)\nvar _ = [1 << 7]struct{}{}[maxKind]\n\ntype fieldInfo struct {\n\tnodeType  reflect.Type // pointer-to-struct type of ast.Node implementation\n\tname      string\n\tindex     int\n\tfieldType reflect.Type\n}\n\nfunc info[N ast.Node](fieldName string) fieldInfo {\n\tnodePtrType := reflect.TypeFor[N]()\n\tf, ok := nodePtrType.Elem().FieldByName(fieldName)\n\tif !ok {\n\t\tpanic(fieldName)\n\t}\n\treturn fieldInfo{nodePtrType, fieldName, f.Index[0], f.Type}\n}\n\nvar fieldInfos = [...]fieldInfo{\n\tInvalid:               {},\n\tArrayType_Elt:         info[*ast.ArrayType](\"Elt\"),\n\tArrayType_Len:         info[*ast.ArrayType](\"Len\"),\n\tAssignStmt_Lhs:        info[*ast.AssignStmt](\"Lhs\"),\n\tAssignStmt_Rhs:        info[*ast.AssignStmt](\"Rhs\"),\n\tBinaryExpr_X:          info[*ast.BinaryExpr](\"X\"),\n\tBinaryExpr_Y:          info[*ast.BinaryExpr](\"Y\"),\n\tBlockStmt_List:        info[*ast.BlockStmt](\"List\"),\n\tBranchStmt_Label:      info[*ast.BranchStmt](\"Label\"),\n\tCallExpr_Args:         info[*ast.CallExpr](\"Args\"),\n\tCallExpr_Fun:          info[*ast.CallExpr](\"Fun\"),\n\tCaseClause_Body:       info[*ast.CaseClause](\"Body\"),\n\tCaseClause_List:       info[*ast.CaseClause](\"List\"),\n\tChanType_Value:        info[*ast.ChanType](\"Value\"),\n\tCommClause_Body:       info[*ast.CommClause](\"Body\"),\n\tCommClause_Comm:       info[*ast.CommClause](\"Comm\"),\n\tCommentGroup_List:     info[*ast.CommentGroup](\"List\"),\n\tCompositeLit_Elts:     info[*ast.CompositeLit](\"Elts\"),\n\tCompositeLit_Type:     info[*ast.CompositeLit](\"Type\"),\n\tDeclStmt_Decl:         info[*ast.DeclStmt](\"Decl\"),\n\tDeferStmt_Call:        info[*ast.DeferStmt](\"Call\"),\n\tEllipsis_Elt:          info[*ast.Ellipsis](\"Elt\"),\n\tExprStmt_X:            info[*ast.ExprStmt](\"X\"),\n\tFieldList_List:        info[*ast.FieldList](\"List\"),\n\tField_Comment:         info[*ast.Field](\"Comment\"),\n\tField_Doc:             info[*ast.Field](\"Doc\"),\n\tField_Names:           info[*ast.Field](\"Names\"),\n\tField_Tag:             info[*ast.Field](\"Tag\"),\n\tField_Type:            info[*ast.Field](\"Type\"),\n\tFile_Decls:            info[*ast.File](\"Decls\"),\n\tFile_Doc:              info[*ast.File](\"Doc\"),\n\tFile_Name:             info[*ast.File](\"Name\"),\n\tForStmt_Body:          info[*ast.ForStmt](\"Body\"),\n\tForStmt_Cond:          info[*ast.ForStmt](\"Cond\"),\n\tForStmt_Init:          info[*ast.ForStmt](\"Init\"),\n\tForStmt_Post:          info[*ast.ForStmt](\"Post\"),\n\tFuncDecl_Body:         info[*ast.FuncDecl](\"Body\"),\n\tFuncDecl_Doc:          info[*ast.FuncDecl](\"Doc\"),\n\tFuncDecl_Name:         info[*ast.FuncDecl](\"Name\"),\n\tFuncDecl_Recv:         info[*ast.FuncDecl](\"Recv\"),\n\tFuncDecl_Type:         info[*ast.FuncDecl](\"Type\"),\n\tFuncLit_Body:          info[*ast.FuncLit](\"Body\"),\n\tFuncLit_Type:          info[*ast.FuncLit](\"Type\"),\n\tFuncType_Params:       info[*ast.FuncType](\"Params\"),\n\tFuncType_Results:      info[*ast.FuncType](\"Results\"),\n\tFuncType_TypeParams:   info[*ast.FuncType](\"TypeParams\"),\n\tGenDecl_Doc:           info[*ast.GenDecl](\"Doc\"),\n\tGenDecl_Specs:         info[*ast.GenDecl](\"Specs\"),\n\tGoStmt_Call:           info[*ast.GoStmt](\"Call\"),\n\tIfStmt_Body:           info[*ast.IfStmt](\"Body\"),\n\tIfStmt_Cond:           info[*ast.IfStmt](\"Cond\"),\n\tIfStmt_Else:           info[*ast.IfStmt](\"Else\"),\n\tIfStmt_Init:           info[*ast.IfStmt](\"Init\"),\n\tImportSpec_Comment:    info[*ast.ImportSpec](\"Comment\"),\n\tImportSpec_Doc:        info[*ast.ImportSpec](\"Doc\"),\n\tImportSpec_Name:       info[*ast.ImportSpec](\"Name\"),\n\tImportSpec_Path:       info[*ast.ImportSpec](\"Path\"),\n\tIncDecStmt_X:          info[*ast.IncDecStmt](\"X\"),\n\tIndexExpr_Index:       info[*ast.IndexExpr](\"Index\"),\n\tIndexExpr_X:           info[*ast.IndexExpr](\"X\"),\n\tIndexListExpr_Indices: info[*ast.IndexListExpr](\"Indices\"),\n\tIndexListExpr_X:       info[*ast.IndexListExpr](\"X\"),\n\tInterfaceType_Methods: info[*ast.InterfaceType](\"Methods\"),\n\tKeyValueExpr_Key:      info[*ast.KeyValueExpr](\"Key\"),\n\tKeyValueExpr_Value:    info[*ast.KeyValueExpr](\"Value\"),\n\tLabeledStmt_Label:     info[*ast.LabeledStmt](\"Label\"),\n\tLabeledStmt_Stmt:      info[*ast.LabeledStmt](\"Stmt\"),\n\tMapType_Key:           info[*ast.MapType](\"Key\"),\n\tMapType_Value:         info[*ast.MapType](\"Value\"),\n\tParenExpr_X:           info[*ast.ParenExpr](\"X\"),\n\tRangeStmt_Body:        info[*ast.RangeStmt](\"Body\"),\n\tRangeStmt_Key:         info[*ast.RangeStmt](\"Key\"),\n\tRangeStmt_Value:       info[*ast.RangeStmt](\"Value\"),\n\tRangeStmt_X:           info[*ast.RangeStmt](\"X\"),\n\tReturnStmt_Results:    info[*ast.ReturnStmt](\"Results\"),\n\tSelectStmt_Body:       info[*ast.SelectStmt](\"Body\"),\n\tSelectorExpr_Sel:      info[*ast.SelectorExpr](\"Sel\"),\n\tSelectorExpr_X:        info[*ast.SelectorExpr](\"X\"),\n\tSendStmt_Chan:         info[*ast.SendStmt](\"Chan\"),\n\tSendStmt_Value:        info[*ast.SendStmt](\"Value\"),\n\tSliceExpr_High:        info[*ast.SliceExpr](\"High\"),\n\tSliceExpr_Low:         info[*ast.SliceExpr](\"Low\"),\n\tSliceExpr_Max:         info[*ast.SliceExpr](\"Max\"),\n\tSliceExpr_X:           info[*ast.SliceExpr](\"X\"),\n\tStarExpr_X:            info[*ast.StarExpr](\"X\"),\n\tStructType_Fields:     info[*ast.StructType](\"Fields\"),\n\tSwitchStmt_Body:       info[*ast.SwitchStmt](\"Body\"),\n\tSwitchStmt_Init:       info[*ast.SwitchStmt](\"Init\"),\n\tSwitchStmt_Tag:        info[*ast.SwitchStmt](\"Tag\"),\n\tTypeAssertExpr_Type:   info[*ast.TypeAssertExpr](\"Type\"),\n\tTypeAssertExpr_X:      info[*ast.TypeAssertExpr](\"X\"),\n\tTypeSpec_Comment:      info[*ast.TypeSpec](\"Comment\"),\n\tTypeSpec_Doc:          info[*ast.TypeSpec](\"Doc\"),\n\tTypeSpec_Name:         info[*ast.TypeSpec](\"Name\"),\n\tTypeSpec_Type:         info[*ast.TypeSpec](\"Type\"),\n\tTypeSpec_TypeParams:   info[*ast.TypeSpec](\"TypeParams\"),\n\tTypeSwitchStmt_Assign: info[*ast.TypeSwitchStmt](\"Assign\"),\n\tTypeSwitchStmt_Body:   info[*ast.TypeSwitchStmt](\"Body\"),\n\tTypeSwitchStmt_Init:   info[*ast.TypeSwitchStmt](\"Init\"),\n\tUnaryExpr_X:           info[*ast.UnaryExpr](\"X\"),\n\tValueSpec_Comment:     info[*ast.ValueSpec](\"Comment\"),\n\tValueSpec_Doc:         info[*ast.ValueSpec](\"Doc\"),\n\tValueSpec_Names:       info[*ast.ValueSpec](\"Names\"),\n\tValueSpec_Type:        info[*ast.ValueSpec](\"Type\"),\n\tValueSpec_Values:      info[*ast.ValueSpec](\"Values\"),\n}\n"
  },
  {
    "path": "go/ast/inspector/cursor.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"iter\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n)\n\n// A Cursor represents an [ast.Node]. It is immutable.\n//\n// Two Cursors compare equal if they represent the same node.\n//\n// The zero value of Cursor is not valid.\n//\n// Call [Inspector.Root] to obtain a cursor for the virtual root node\n// of the traversal. This is the sole valid cursor for which [Cursor.Node]\n// returns nil.\n//\n// Use the following methods to navigate efficiently around the tree:\n//   - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing];\n//   - for children, use [Cursor.Child], [Cursor.Children],\n//     [Cursor.FirstChild], and [Cursor.LastChild];\n//   - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling];\n//   - for descendants, use [Cursor.FindByPos], [Cursor.FindNode],\n//     [Cursor.Inspect], and [Cursor.Preorder].\n//\n// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for\n// information about the edges in a tree: which field (and slice\n// element) of the parent node holds the child.\ntype Cursor struct {\n\tin    *Inspector\n\tindex int32 // index of push node; -1 for virtual root node\n}\n\n// Root returns a valid cursor for the virtual root node,\n// whose children are the files provided to [New].\n//\n// Its [Cursor.Node] method return nil.\nfunc (in *Inspector) Root() Cursor {\n\treturn Cursor{in, -1}\n}\n\n// At returns the cursor at the specified index in the traversal,\n// which must have been obtained from [Cursor.Index] on a Cursor\n// belonging to the same Inspector (see [Cursor.Inspector]).\nfunc (in *Inspector) At(index int32) Cursor {\n\tif index < 0 {\n\t\tpanic(\"negative index\")\n\t}\n\tif int(index) >= len(in.events) {\n\t\tpanic(\"index out of range for this inspector\")\n\t}\n\tif in.events[index].index < index {\n\t\tpanic(\"invalid index\") // (a push, not a pop)\n\t}\n\treturn Cursor{in, index}\n}\n\n// Valid reports whether the cursor is valid.\n// The zero value of cursor is invalid.\n// Unless otherwise documented, it is not safe to call\n// any other method on an invalid cursor.\nfunc (c Cursor) Valid() bool {\n\treturn c.in != nil\n}\n\n// Inspector returns the cursor's Inspector.\n// It returns nil if the Cursor is not valid.\nfunc (c Cursor) Inspector() *Inspector { return c.in }\n\n// Index returns the index of this cursor position within the package.\n//\n// Clients should not assume anything about the numeric Index value\n// except that it increases monotonically throughout the traversal.\n// It is provided for use with [Inspector.At].\n//\n// Index must not be called on the Root node.\nfunc (c Cursor) Index() int32 {\n\tif c.index < 0 {\n\t\tpanic(\"Index called on Root node\")\n\t}\n\treturn c.index\n}\n\n// Node returns the node at the current cursor position,\n// or nil for the cursor returned by [Inspector.Root].\nfunc (c Cursor) Node() ast.Node {\n\tif c.index < 0 {\n\t\treturn nil\n\t}\n\treturn c.in.events[c.index].node\n}\n\n// String returns information about the cursor's node, if any.\nfunc (c Cursor) String() string {\n\tif !c.Valid() {\n\t\treturn \"(invalid)\"\n\t}\n\tif c.index < 0 {\n\t\treturn \"(root)\"\n\t}\n\treturn reflect.TypeOf(c.Node()).String()\n}\n\n// indices return the [start, end) half-open interval of event indices.\nfunc (c Cursor) indices() (int32, int32) {\n\tif c.index < 0 {\n\t\treturn 0, int32(len(c.in.events)) // root: all events\n\t} else {\n\t\treturn c.index, c.in.events[c.index].index + 1 // just one subtree\n\t}\n}\n\n// Preorder returns an iterator over the nodes of the subtree\n// represented by c in depth-first order. Each node in the sequence is\n// represented by a Cursor that allows access to the Node, but may\n// also be used to start a new traversal, or to obtain the stack of\n// nodes enclosing the cursor.\n//\n// The traversal sequence is determined by [ast.Inspect]. The types\n// argument, if non-empty, enables type-based filtering of events. The\n// function f if is called only for nodes whose type matches an\n// element of the types slice.\n//\n// If you need control over descent into subtrees,\n// or need both pre- and post-order notifications, use [Cursor.Inspect]\nfunc (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] {\n\tmask := maskOf(types)\n\n\treturn func(yield func(Cursor) bool) {\n\t\tevents := c.in.events\n\n\t\tfor i, limit := c.indices(); i < limit; {\n\t\t\tev := events[i]\n\t\t\tif ev.index > i { // push?\n\t\t\t\tif ev.typ&mask != 0 && !yield(Cursor{c.in, i}) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tpop := ev.index\n\t\t\t\tif events[pop].typ&mask == 0 {\n\t\t\t\t\t// Subtree does not contain types: skip.\n\t\t\t\t\ti = pop + 1\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Inspect visits the nodes of the subtree represented by c in\n// depth-first order. It calls f(n) for each node n before it\n// visits n's children. If f returns true, Inspect invokes f\n// recursively for each of the non-nil children of the node.\n//\n// Each node is represented by a Cursor that allows access to the\n// Node, but may also be used to start a new traversal, or to obtain\n// the stack of nodes enclosing the cursor.\n//\n// The complete traversal sequence is determined by [ast.Inspect].\n// The types argument, if non-empty, enables type-based filtering of\n// events. The function f if is called only for nodes whose type\n// matches an element of the types slice.\nfunc (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) {\n\tmask := maskOf(types)\n\tevents := c.in.events\n\tfor i, limit := c.indices(); i < limit; {\n\t\tev := events[i]\n\t\tif ev.index > i {\n\t\t\t// push\n\t\t\tpop := ev.index\n\t\t\tif ev.typ&mask != 0 && !f(Cursor{c.in, i}) ||\n\t\t\t\tevents[pop].typ&mask == 0 {\n\t\t\t\t// The user opted not to descend, or the\n\t\t\t\t// subtree does not contain types:\n\t\t\t\t// skip past the pop.\n\t\t\t\ti = pop + 1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n}\n\n// Enclosing returns an iterator over the nodes enclosing the current\n// current node, starting with the Cursor itself.\n//\n// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil).\n//\n// The types argument, if non-empty, enables type-based filtering of\n// events: the sequence includes only enclosing nodes whose type\n// matches an element of the types slice.\nfunc (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.Enclosing called on Root node\")\n\t}\n\n\tmask := maskOf(types)\n\n\treturn func(yield func(Cursor) bool) {\n\t\tevents := c.in.events\n\t\tfor i := c.index; i >= 0; i = events[i].parent {\n\t\t\tif events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Parent returns the parent of the current node.\n//\n// Parent must not be called on the Root node (whose [Cursor.Node] returns nil).\nfunc (c Cursor) Parent() Cursor {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.Parent called on Root node\")\n\t}\n\n\treturn Cursor{c.in, c.in.events[c.index].parent}\n}\n\n// ParentEdge returns the identity of the field in the parent node\n// that holds this cursor's node, and if it is a list, the index within it.\n//\n// For example, f(x, y) is a CallExpr whose three children are Idents.\n// f has edge kind [edge.CallExpr_Fun] and index -1.\n// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively.\n//\n// If called on a child of the Root node, it returns ([edge.Invalid], -1).\n//\n// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil).\nfunc (c Cursor) ParentEdge() (edge.Kind, int) {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.ParentEdge called on Root node\")\n\t}\n\tevents := c.in.events\n\tpop := events[c.index].index\n\treturn unpackEdgeKindAndIndex(events[pop].parent)\n}\n\n// ParentEdgeKind returns the kind component of the result of [Cursor.ParentEdge].\nfunc (c Cursor) ParentEdgeKind() edge.Kind {\n\tek, _ := c.ParentEdge()\n\treturn ek\n}\n\n// ParentEdgeIndex returns the index component of the result of [Cursor.ParentEdge].\nfunc (c Cursor) ParentEdgeIndex() int {\n\t_, index := c.ParentEdge()\n\treturn index\n}\n\n// ChildAt returns the cursor for the child of the\n// current node identified by its edge and index.\n// The index must be -1 if the edge.Kind is not a slice.\n// The indicated child node must exist.\n//\n// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil).\n//\n// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c.\nfunc (c Cursor) ChildAt(k edge.Kind, idx int) Cursor {\n\ttarget := packEdgeKindAndIndex(k, idx)\n\n\t// Unfortunately there's no shortcut to looping.\n\tevents := c.in.events\n\ti := c.index + 1\n\tfor {\n\t\tpop := events[i].index\n\t\tif pop < i {\n\t\t\tbreak\n\t\t}\n\t\tif events[pop].parent == target {\n\t\t\treturn Cursor{c.in, i}\n\t\t}\n\t\ti = pop + 1\n\t}\n\tpanic(fmt.Sprintf(\"ChildAt(%v, %d): no such child of %v\", k, idx, c))\n}\n\n// Child returns the cursor for n, which must be a direct child of c's Node.\n//\n// Child must not be called on the Root node (whose [Cursor.Node] returns nil).\nfunc (c Cursor) Child(n ast.Node) Cursor {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.Child called on Root node\")\n\t}\n\n\tif false {\n\t\t// reference implementation\n\t\tfor child := range c.Children() {\n\t\t\tif child.Node() == n {\n\t\t\t\treturn child\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// optimized implementation\n\t\tevents := c.in.events\n\t\tfor i := c.index + 1; events[i].index > i; i = events[i].index + 1 {\n\t\t\tif events[i].node == n {\n\t\t\t\treturn Cursor{c.in, i}\n\t\t\t}\n\t\t}\n\t}\n\tpanic(fmt.Sprintf(\"Child(%T): not a child of %v\", n, c))\n}\n\n// NextSibling returns the cursor for the next sibling node in the same list\n// (for example, of files, decls, specs, statements, fields, or expressions) as\n// the current node. It returns (zero, false) if the node is the last node in\n// the list, or is not part of a list.\n//\n// NextSibling must not be called on the Root node.\n//\n// See note at [Cursor.Children].\nfunc (c Cursor) NextSibling() (Cursor, bool) {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.NextSibling called on Root node\")\n\t}\n\n\tevents := c.in.events\n\ti := events[c.index].index + 1 // after corresponding pop\n\tif i < int32(len(events)) {\n\t\tif events[i].index > i { // push?\n\t\t\treturn Cursor{c.in, i}, true\n\t\t}\n\t}\n\treturn Cursor{}, false\n}\n\n// PrevSibling returns the cursor for the previous sibling node in the\n// same list (for example, of files, decls, specs, statements, fields,\n// or expressions) as the current node. It returns zero if the node is\n// the first node in the list, or is not part of a list.\n//\n// It must not be called on the Root node.\n//\n// See note at [Cursor.Children].\nfunc (c Cursor) PrevSibling() (Cursor, bool) {\n\tif c.index < 0 {\n\t\tpanic(\"Cursor.PrevSibling called on Root node\")\n\t}\n\n\tevents := c.in.events\n\ti := c.index - 1\n\tif i >= 0 {\n\t\tif j := events[i].index; j < i { // pop?\n\t\t\treturn Cursor{c.in, j}, true\n\t\t}\n\t}\n\treturn Cursor{}, false\n}\n\n// FirstChild returns the first direct child of the current node,\n// or zero if it has no children.\nfunc (c Cursor) FirstChild() (Cursor, bool) {\n\tevents := c.in.events\n\ti := c.index + 1                                   // i=0 if c is root\n\tif i < int32(len(events)) && events[i].index > i { // push?\n\t\treturn Cursor{c.in, i}, true\n\t}\n\treturn Cursor{}, false\n}\n\n// LastChild returns the last direct child of the current node,\n// or zero if it has no children.\nfunc (c Cursor) LastChild() (Cursor, bool) {\n\tevents := c.in.events\n\tif c.index < 0 { // root?\n\t\tif len(events) > 0 {\n\t\t\t// return push of final event (a pop)\n\t\t\treturn Cursor{c.in, events[len(events)-1].index}, true\n\t\t}\n\t} else {\n\t\tj := events[c.index].index - 1 // before corresponding pop\n\t\t// Inv: j == c.index if c has no children\n\t\t//  or  j is last child's pop.\n\t\tif j > c.index { // c has children\n\t\t\treturn Cursor{c.in, events[j].index}, true\n\t\t}\n\t}\n\treturn Cursor{}, false\n}\n\n// Children returns an iterator over the direct children of the\n// current node, if any.\n//\n// When using Children, NextChild, and PrevChild, bear in mind that a\n// Node's children may come from different fields, some of which may\n// be lists of nodes without a distinguished intervening container\n// such as [ast.BlockStmt].\n//\n// For example, [ast.CaseClause] has a field List of expressions and a\n// field Body of statements, so the children of a CaseClause are a mix\n// of expressions and statements. Other nodes that have \"uncontained\"\n// list fields include:\n//\n//   - [ast.ValueSpec] (Names, Values)\n//   - [ast.CompositeLit] (Type, Elts)\n//   - [ast.IndexListExpr] (X, Indices)\n//   - [ast.CallExpr] (Fun, Args)\n//   - [ast.AssignStmt] (Lhs, Rhs)\n//\n// So, do not assume that the previous sibling of an ast.Stmt is also\n// an ast.Stmt, or if it is, that they are executed sequentially,\n// unless you have established that, say, its parent is a BlockStmt\n// or its [Cursor.ParentEdge] is [edge.BlockStmt_List].\n// For example, given \"for S1; ; S2 {}\", the predecessor of S2 is S1,\n// even though they are not executed in sequence.\nfunc (c Cursor) Children() iter.Seq[Cursor] {\n\treturn func(yield func(Cursor) bool) {\n\t\tc, ok := c.FirstChild()\n\t\tfor ok && yield(c) {\n\t\t\tc, ok = c.NextSibling()\n\t\t}\n\t}\n}\n\n// Contains reports whether c contains or is equal to c2.\n//\n// Both Cursors must belong to the same [Inspector];\n// neither may be its Root node.\nfunc (c Cursor) Contains(c2 Cursor) bool {\n\tif c.in != c2.in {\n\t\tpanic(\"different inspectors\")\n\t}\n\tevents := c.in.events\n\treturn c.index <= c2.index && events[c2.index].index <= events[c.index].index\n}\n\n// FindNode returns the cursor for node n if it belongs to the subtree\n// rooted at c. It returns zero if n is not found.\nfunc (c Cursor) FindNode(n ast.Node) (Cursor, bool) {\n\n\t// FindNode is equivalent to this code,\n\t// but more convenient and 15-20% faster:\n\tif false {\n\t\tfor candidate := range c.Preorder(n) {\n\t\t\tif candidate.Node() == n {\n\t\t\t\treturn candidate, true\n\t\t\t}\n\t\t}\n\t\treturn Cursor{}, false\n\t}\n\n\t// TODO(adonovan): opt: should we assume Node.Pos is accurate\n\t// and combine type-based filtering with position filtering\n\t// like FindByPos?\n\n\tmask := maskOf([]ast.Node{n})\n\tevents := c.in.events\n\n\tfor i, limit := c.indices(); i < limit; i++ {\n\t\tev := events[i]\n\t\tif ev.index > i { // push?\n\t\t\tif ev.typ&mask != 0 && ev.node == n {\n\t\t\t\treturn Cursor{c.in, i}, true\n\t\t\t}\n\t\t\tpop := ev.index\n\t\t\tif events[pop].typ&mask == 0 {\n\t\t\t\t// Subtree does not contain type of n: skip.\n\t\t\t\ti = pop\n\t\t\t}\n\t\t}\n\t}\n\treturn Cursor{}, false\n}\n\n// FindByPos returns the cursor for the innermost node n in the tree\n// rooted at c such that n.Pos() <= start && end <= n.End().\n// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.)\n//\n// An empty range (start == end) between two adjacent nodes is\n// considered to belong to the first node.\n//\n// It returns zero if none is found.\n// Precondition: start <= end.\n//\n// See also [astutil.PathEnclosingInterval], which\n// tolerates adjoining whitespace.\nfunc (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {\n\tif end < start {\n\t\tpanic(\"end < start\")\n\t}\n\tevents := c.in.events\n\n\t// This algorithm could be implemented using c.Inspect,\n\t// but it is about 2.5x slower.\n\n\t// best is the push-index of the latest (=innermost) node containing range.\n\t// (Beware: latest is not always innermost because FuncDecl.{Name,Type} overlap.)\n\tbest := int32(-1)\n\tfor i, limit := c.indices(); i < limit; i++ {\n\t\tev := events[i]\n\t\tif ev.index > i { // push?\n\t\t\tn := ev.node\n\t\t\tvar nodeEnd token.Pos\n\t\t\tif file, ok := n.(*ast.File); ok {\n\t\t\t\tnodeEnd = file.FileEnd\n\t\t\t\t// Note: files may be out of Pos order.\n\t\t\t\tif file.FileStart > start {\n\t\t\t\t\ti = ev.index // disjoint, after; skip to next file\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Edge case: FuncDecl.Name and .Type overlap:\n\t\t\t\t// Don't update best from Name to FuncDecl.Type.\n\t\t\t\t//\n\t\t\t\t// The condition can be read as:\n\t\t\t\t// - n is FuncType\n\t\t\t\t// - n.parent is FuncDecl\n\t\t\t\t// - best is strictly beneath the FuncDecl\n\t\t\t\tif ev.typ == 1<<nFuncType &&\n\t\t\t\t\tevents[ev.parent].typ == 1<<nFuncDecl &&\n\t\t\t\t\tbest > ev.parent {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tnodeEnd = n.End()\n\t\t\t\tif n.Pos() > start {\n\t\t\t\t\tbreak // disjoint, after; stop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Inv: node.{Pos,FileStart} <= start\n\t\t\tif end <= nodeEnd {\n\t\t\t\t// node fully contains target range\n\t\t\t\tbest = i\n\n\t\t\t\t// Don't search beyond end of the first match.\n\t\t\t\t// This is important only for an empty range (start=end)\n\t\t\t\t// between two adjoining nodes, which would otherwise\n\t\t\t\t// match both nodes; we want to match only the first.\n\t\t\t\tlimit = ev.index\n\t\t\t} else if nodeEnd < start {\n\t\t\t\ti = ev.index // disjoint, before; skip forward\n\t\t\t}\n\t\t}\n\t}\n\tif best >= 0 {\n\t\treturn Cursor{c.in, best}, true\n\t}\n\treturn Cursor{}, false\n}\n"
  },
  {
    "path": "go/ast/inspector/cursor_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"iter\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\nfunc TestCursor_Preorder(t *testing.T) {\n\tinspect := netInspect\n\n\tnodeFilter := []ast.Node{(*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)}\n\n\t// reference implementation\n\tvar want []ast.Node\n\tfor cur := range inspect.Root().Preorder(nodeFilter...) {\n\t\twant = append(want, cur.Node())\n\t}\n\n\t// Check entire sequence.\n\tgot := slices.Collect(inspect.PreorderSeq(nodeFilter...))\n\tcompare(t, got, want)\n\n\t// Check that break works.\n\tgot = got[:0]\n\tfor _, c := range firstN(10, inspect.Root().Preorder(nodeFilter...)) {\n\t\tgot = append(got, c.Node())\n\t}\n\tcompare(t, got, want[:10])\n}\n\nfunc TestCursor_nestedTraversal(t *testing.T) {\n\tconst src = `package a\nfunc f() {\n\tprint(\"hello\")\n}\nfunc g() {\n\tprint(\"goodbye\")\n\tpanic(\"oops\")\n}\n`\n\tfset := token.NewFileSet()\n\tf, _ := parser.ParseFile(fset, \"a.go\", src, 0)\n\tinspect := inspector.New([]*ast.File{f})\n\n\tvar (\n\t\tfuncDecls = []ast.Node{(*ast.FuncDecl)(nil)}\n\t\tcallExprs = []ast.Node{(*ast.CallExpr)(nil)}\n\t\tnfuncs    = 0\n\t\tncalls    = 0\n\t)\n\n\tfor curFunc := range inspect.Root().Preorder(funcDecls...) {\n\t\t_ = curFunc.Node().(*ast.FuncDecl)\n\n\t\t// Check edge and index.\n\t\tif k, idx := curFunc.ParentEdge(); k != edge.File_Decls || idx != nfuncs {\n\t\t\tt.Errorf(\"%v.ParentEdge() = (%v, %d),  want edge.File_Decls, %d\", curFunc, k, idx, nfuncs)\n\t\t}\n\n\t\tnfuncs++\n\t\tstack := slices.Collect(curFunc.Enclosing())\n\n\t\t// Stacks are convenient to print!\n\t\tif got, want := fmt.Sprint(stack), \"[*ast.FuncDecl *ast.File]\"; got != want {\n\t\t\tt.Errorf(\"curFunc.Enclosing() = %q, want %q\", got, want)\n\t\t}\n\n\t\t// Parent, iterated, is Enclosing stack.\n\t\ti := 0\n\t\tfor c := curFunc; c.Node() != nil; c = c.Parent() {\n\t\t\tif got, want := stack[i], c; got != want {\n\t\t\t\tt.Errorf(\"Enclosing[%d] = %v; Parent()^%d = %v\", i, got, i, want)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\n\t\twantStack := \"[*ast.CallExpr *ast.ExprStmt *ast.BlockStmt *ast.FuncDecl *ast.File]\"\n\n\t\t// nested Preorder traversal\n\t\tpreorderCount := 0\n\t\tfor curCall := range curFunc.Preorder(callExprs...) {\n\t\t\t_ = curCall.Node().(*ast.CallExpr)\n\t\t\tpreorderCount++\n\t\t\tstack := slices.Collect(curCall.Enclosing())\n\t\t\tif got := fmt.Sprint(stack); got != wantStack {\n\t\t\t\tt.Errorf(\"curCall.Enclosing() = %q, want %q\", got, wantStack)\n\t\t\t}\n\t\t}\n\n\t\t// nested Inspect traversal\n\t\tinspectCount := 0\n\t\tcurFunc.Inspect(callExprs, func(curCall inspector.Cursor) (proceed bool) {\n\t\t\t_ = curCall.Node().(*ast.CallExpr)\n\t\t\tinspectCount++\n\t\t\tstack := slices.Collect(curCall.Enclosing())\n\t\t\tif got := fmt.Sprint(stack); got != wantStack {\n\t\t\t\tt.Errorf(\"curCall.Enclosing() = %q, want %q\", got, wantStack)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\n\t\tif inspectCount != preorderCount {\n\t\t\tt.Errorf(\"Inspect (%d) and Preorder (%d) events are not consistent\", inspectCount, preorderCount)\n\t\t}\n\n\t\tncalls += preorderCount\n\t}\n\n\tif nfuncs != 2 {\n\t\tt.Errorf(\"Found %d FuncDecls, want 2\", nfuncs)\n\t}\n\tif ncalls != 3 {\n\t\tt.Errorf(\"Found %d CallExprs, want 3\", ncalls)\n\t}\n}\n\nfunc TestCursor_Children(t *testing.T) {\n\tinspect := netInspect\n\n\t// Assert that Cursor.Children agrees with\n\t// reference implementation for every node.\n\tvar want, got []ast.Node\n\tfor c := range inspect.Root().Preorder() {\n\n\t\t// reference implementation\n\t\twant = want[:0]\n\t\t{\n\t\t\tparent := c.Node()\n\t\t\tast.Inspect(parent, func(n ast.Node) bool {\n\t\t\t\tif n != nil && n != parent {\n\t\t\t\t\twant = append(want, n)\n\t\t\t\t}\n\t\t\t\treturn n == parent // descend only into parent\n\t\t\t})\n\t\t}\n\n\t\t// Check cursor-based implementation\n\t\t// (uses FirstChild+NextSibling).\n\t\tgot = got[:0]\n\t\tfor child := range c.Children() {\n\t\t\tgot = append(got, child.Node())\n\t\t}\n\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"For %v\\n\"+\n\t\t\t\t\"Using FirstChild+NextSibling: %v\\n\"+\n\t\t\t\t\"Using ast.Inspect:            %v\",\n\t\t\t\tc, sliceTypes(got), sliceTypes(want))\n\t\t}\n\n\t\t// Second cursor-based implementation\n\t\t// using LastChild+PrevSibling+reverse.\n\t\tgot = got[:0]\n\t\tfor c, ok := c.LastChild(); ok; c, ok = c.PrevSibling() {\n\t\t\tgot = append(got, c.Node())\n\t\t}\n\t\tslices.Reverse(got)\n\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"For %v\\n\"+\n\t\t\t\t\"Using LastChild+PrevSibling: %v\\n\"+\n\t\t\t\t\"Using ast.Inspect:           %v\",\n\t\t\t\tc, sliceTypes(got), sliceTypes(want))\n\t\t}\n\t}\n}\n\nfunc TestCursor_Inspect(t *testing.T) {\n\tinspect := netInspect\n\n\t// In all three loops, we'll gather both kinds of type switches,\n\t// but we'll prune the traversal from descending into (value) switches.\n\tswitches := []ast.Node{(*ast.SwitchStmt)(nil), (*ast.TypeSwitchStmt)(nil)}\n\n\t// reference implementation (ast.Inspect)\n\tvar nodesA []ast.Node\n\tfor _, f := range netFiles {\n\t\tast.Inspect(f, func(n ast.Node) (proceed bool) {\n\t\t\tswitch n.(type) {\n\t\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt:\n\t\t\t\tnodesA = append(nodesA, n)\n\t\t\t\treturn !is[*ast.SwitchStmt](n) // descend only into TypeSwitchStmt\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\n\t// Test Cursor.Inspect implementation.\n\tvar nodesB []ast.Node\n\tinspect.Root().Inspect(switches, func(c inspector.Cursor) (proceed bool) {\n\t\tn := c.Node()\n\t\tnodesB = append(nodesB, n)\n\t\treturn !is[*ast.SwitchStmt](n) // descend only into TypeSwitchStmt\n\t})\n\tcompare(t, nodesA, nodesB)\n\n\t// Test WithStack implementation.\n\tvar nodesC []ast.Node\n\tinspect.WithStack(switches, func(n ast.Node, push bool, stack []ast.Node) (proceed bool) {\n\t\tif push {\n\t\t\tnodesC = append(nodesC, n)\n\t\t\treturn !is[*ast.SwitchStmt](n) // descend only into TypeSwitchStmt\n\t\t}\n\t\treturn false\n\t})\n\tcompare(t, nodesA, nodesC)\n}\n\nfunc TestCursor_FindNode(t *testing.T) {\n\tinspect := netInspect\n\n\t// Enumerate all nodes of a particular type,\n\t// then check that FindByPos can find them,\n\t// starting at the root.\n\t//\n\t// (We use BasicLit because they are numerous.)\n\troot := inspect.Root()\n\tfor c := range root.Preorder((*ast.BasicLit)(nil)) {\n\t\tnode := c.Node()\n\t\tgot, ok := root.FindNode(node)\n\t\tif !ok {\n\t\t\tt.Errorf(\"root.FindNode failed\")\n\t\t} else if got != c {\n\t\t\tt.Errorf(\"root.FindNode returned %v, want %v\", got, c)\n\t\t}\n\t}\n\n\t// Same thing, but searching only within subtrees (each FuncDecl).\n\tfor funcDecl := range root.Preorder((*ast.FuncDecl)(nil)) {\n\t\tfor c := range funcDecl.Preorder((*ast.BasicLit)(nil)) {\n\t\t\tnode := c.Node()\n\t\t\tgot, ok := funcDecl.FindNode(node)\n\t\t\tif !ok {\n\t\t\t\tt.Errorf(\"funcDecl.FindNode failed\")\n\t\t\t} else if got != c {\n\t\t\t\tt.Errorf(\"funcDecl.FindNode returned %v, want %v\", got, c)\n\t\t\t}\n\n\t\t\t// Also, check that we cannot find the BasicLit\n\t\t\t// beneath a different FuncDecl.\n\t\t\tif prevFunc, ok := funcDecl.PrevSibling(); ok {\n\t\t\t\tgot, ok := prevFunc.FindNode(node)\n\t\t\t\tif ok {\n\t\t\t\t\tt.Errorf(\"prevFunc.FindNode succeeded unexpectedly: %v\", got)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestCursor_FindByPos_order ensures that FindByPos does not assume files are in Pos order.\nfunc TestCursor_FindByPos_order(t *testing.T) {\n\t// Pick an arbitrary decl.\n\ttarget := netFiles[7].Decls[0]\n\n\t// Find the target decl by its position.\n\tcur, ok := netInspect.Root().FindByPos(target.Pos(), target.End())\n\tif !ok || cur.Node() != target {\n\t\tt.Fatalf(\"unshuffled: FindByPos(%T) = (%v, %t)\", target, cur, ok)\n\t}\n\n\t// Shuffle the files out of Pos order.\n\tfiles := slices.Clone(netFiles)\n\trand.Shuffle(len(files), func(i, j int) {\n\t\tfiles[i], files[j] = files[j], files[i]\n\t})\n\n\t// Find it again.\n\tinspect := inspector.New(files)\n\tcur, ok = inspect.Root().FindByPos(target.Pos(), target.End())\n\tif !ok || cur.Node() != target {\n\t\tt.Fatalf(\"shuffled: FindByPos(%T) = (%v, %t)\", target, cur, ok)\n\t}\n}\n\nfunc TestCursor_Edge(t *testing.T) {\n\troot := netInspect.Root()\n\tfor cur := range root.Preorder() {\n\t\tif cur == root {\n\t\t\tcontinue // root node\n\t\t}\n\n\t\tvar (\n\t\t\tparent = cur.Parent()\n\t\t\te, idx = cur.ParentEdge()\n\t\t)\n\n\t\t// ast.File, child of root?\n\t\tif parent.Node() == nil {\n\t\t\tif e != edge.Invalid || idx != -1 {\n\t\t\t\tt.Errorf(\"%v.Edge = (%v, %d), want (Invalid, -1)\", cur, e, idx)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check Edge.NodeType matches type of Parent.Node.\n\t\tif e.NodeType() != reflect.TypeOf(parent.Node()) {\n\t\t\tt.Errorf(\"Edge.NodeType = %v, Parent.Node has type %T\",\n\t\t\t\te.NodeType(), parent.Node())\n\t\t}\n\n\t\t// Check c.Edge.Get(c.Parent.Node) == c.Node.\n\t\tif got := e.Get(parent.Node(), idx); got != cur.Node() {\n\t\t\tt.Errorf(\"cur=%v@%s: %s.Get(cur.Parent().Node(), %d) = %T@%s, want cur.Node()\",\n\t\t\t\tcur, netFset.Position(cur.Node().Pos()), e, idx, got, netFset.Position(got.Pos()))\n\t\t}\n\n\t\t// Check c.Parent.ChildAt(c.ParentEdge()) == c.\n\t\tif got := parent.ChildAt(e, idx); got != cur {\n\t\t\tt.Errorf(\"cur=%v@%s: cur.Parent().ChildAt(%v, %d) = %T@%s, want cur\",\n\t\t\t\tcur, netFset.Position(cur.Node().Pos()), e, idx, got.Node(), netFset.Position(got.Node().Pos()))\n\t\t}\n\n\t\t// Check that reflection on the parent finds the current node.\n\t\tfv := reflect.ValueOf(parent.Node()).Elem().FieldByName(e.FieldName())\n\t\tif idx >= 0 {\n\t\t\tfv = fv.Index(idx) // element of []ast.Node\n\t\t}\n\t\tif fv.Kind() == reflect.Interface {\n\t\t\tfv = fv.Elem() // e.g. ast.Expr -> *ast.Ident\n\t\t}\n\t\tgot := fv.Interface().(ast.Node)\n\t\tif got != cur.Node() {\n\t\t\tt.Errorf(\"%v.Edge = (%v, %d); FieldName/Index reflection gave %T@%s, not original node\",\n\t\t\t\tcur, e, idx, got, netFset.Position(got.Pos()))\n\t\t}\n\n\t\t// Check that Cursor.Child is the reverse of Parent.\n\t\tif cur.Parent().Child(cur.Node()) != cur {\n\t\t\tt.Errorf(\"Cursor.Parent.Child = %v, want %v\", cur.Parent().Child(cur.Node()), cur)\n\t\t}\n\n\t\t// Check invariants of Contains:\n\n\t\t// A cursor contains itself.\n\t\tif !cur.Contains(cur) {\n\t\t\tt.Errorf(\"!cur.Contains(cur): %v\", cur)\n\t\t}\n\t\t// A parent contains its child, but not the inverse.\n\t\tif !parent.Contains(cur) {\n\t\t\tt.Errorf(\"!cur.Parent().Contains(cur): %v\", cur)\n\t\t}\n\t\tif cur.Contains(parent) {\n\t\t\tt.Errorf(\"cur.Contains(cur.Parent()): %v\", cur)\n\t\t}\n\t\t// A grandparent contains its grandchild, but not the inverse.\n\t\tif grandparent := cur.Parent(); grandparent.Node() != nil {\n\t\t\tif !grandparent.Contains(cur) {\n\t\t\t\tt.Errorf(\"!cur.Parent().Parent().Contains(cur): %v\", cur)\n\t\t\t}\n\t\t\tif cur.Contains(grandparent) {\n\t\t\t\tt.Errorf(\"cur.Contains(cur.Parent().Parent()): %v\", cur)\n\t\t\t}\n\t\t}\n\t\t// A cursor and its uncle/aunt do not contain each other.\n\t\tif uncle, ok := parent.NextSibling(); ok {\n\t\t\tif uncle.Contains(cur) {\n\t\t\t\tt.Errorf(\"cur.Parent().NextSibling().Contains(cur): %v\", cur)\n\t\t\t}\n\t\t\tif cur.Contains(uncle) {\n\t\t\t\tt.Errorf(\"cur.Contains(cur.Parent().NextSibling()): %v\", cur)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Regression test for mutilple matching nodes in FindByPos (#76872).\nfunc TestCursor_FindByPos_Boundary(t *testing.T) {\n\t// This test verifies that when a cursor position is on the boundary of two\n\t// adjacent nodes (e.g. \"foo|(\"), FindByPos returns the first node\n\t// encountered in traversal order (which is usually the node \"to the left\").\n\t//\n\t// Note: The source is intentionally unformatted (no space between ')' and\n\t// '{') to ensure the nodes are strictly adjacent at the boundary.\n\tconst src = `package p; func foo(a int){}`\n\tvar (\n\t\tfset    = token.NewFileSet()\n\t\tf, _    = parser.ParseFile(fset, \"p.go\", src, 0)\n\t\ttokFile = fset.File(f.FileStart)\n\t\tinspect = inspector.New([]*ast.File{f})\n\t)\n\n\td := f.Decls[0].(*ast.FuncDecl)\n\n\tformat := func(pos token.Pos) string {\n\t\toff := tokFile.Offset(pos)\n\t\treturn fmt.Sprintf(\"...%s<<>>%s...\", src[off-1:off], src[off:off+1])\n\t}\n\n\tfor _, test := range []struct {\n\t\tname string\n\t\tpos  token.Pos\n\t\twant ast.Node\n\t}{\n\t\t{\n\t\t\t// \"foo|(\" Ident\n\t\t\tpos:  d.Type.Params.Opening,\n\t\t\twant: d.Name,\n\t\t},\n\t\t{\n\t\t\t// \")|{\" FieldList\n\t\t\tpos:  d.Body.Pos(),\n\t\t\twant: d.Type.Params,\n\t\t},\n\t} {\n\t\tcur, ok := inspect.Root().FindByPos(test.pos, test.pos)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"FindByPos(%d) %s found nothing\", test.pos, format(test.pos))\n\t\t}\n\n\t\tif cur.Node() != test.want {\n\t\t\tt.Errorf(\"FindByPos(%d) %s:\\ngot  %T (%v)\\nwant %T (%v)\",\n\t\t\t\ttest.pos, format(test.pos),\n\t\t\t\tcur.Node(), cur.Node(),\n\t\t\t\ttest.want, test.want)\n\t\t}\n\t}\n}\n\n// Regression test for FuncDecl.Type irregularity in FindByPos (#75997).\nfunc TestCursor_FindByPos(t *testing.T) {\n\t// Observe that the range of FuncType has a hole between\n\t// the \"func\" token and the start of Type.Params.\n\t// The hole contains FuncDecl.{Recv,Name}.\n\t//\n\t//                      ~~~~~~~~~~~~FuncDecl~~~~~~~~~~~~~~~~~~~~~~~~~\n\t//                           ~Recv~ ~Name~\n\t//                      ~~~~--------------~~~~FuncType~~~~~~\n\t//                                        ~Params~ ~Results~\n\tconst src = `package a; func (recv) method(params) (results) { body }`\n\tvar (\n\t\tfset    = token.NewFileSet()\n\t\tf, _    = parser.ParseFile(fset, \"a.go\", src, 0) // ignore parse errors\n\t\ttokFile = fset.File(f.FileStart)\n\t\tinspect = inspector.New([]*ast.File{f})\n\t)\n\tformat := func(start, end token.Pos) string {\n\t\tvar (\n\t\t\tstartOffset = tokFile.Offset(start)\n\t\t\tendOffset   = tokFile.Offset(end)\n\t\t)\n\t\treturn fmt.Sprintf(\"%s<<%s>>%s\", src[:startOffset], src[startOffset:endOffset], src[endOffset:])\n\t}\n\n\td := f.Decls[0].(*ast.FuncDecl)\n\n\t// Each test case specifies a [pos-end) range for\n\t// FindByPos and the syntax node it should find.\n\tfor _, test := range []struct {\n\t\tstart, end token.Pos\n\t\twant       ast.Node\n\t}{\n\t\t// pure subtrees\n\t\t{d.Pos(), d.End(), d},                // decl\n\t\t{d.Recv.Pos(), d.Recv.End(), d.Recv}, // recv\n\t\t{d.Name.Pos(), d.Name.End(), d.Name}, // name\n\t\t// (A FuncDecl can't have both Recv and TypeParams, so skip this one.)\n\t\t// {d.Type.TypeParams.Pos(), d.Type.TypeParams.End(), d.Type.TypeParams},\n\t\t{d.Type.Params.Pos(), d.Type.Params.End(), d.Type.Params},    // params\n\t\t{d.Type.Results.Pos(), d.Type.Results.End(), d.Type.Results}, // results\n\t\t{d.Body.Pos(), d.Body.End(), d.Body},                         // body\n\n\t\t// single tokens\n\t\t{\n\t\t\t// \"func\"\n\t\t\td.Type.Func, d.Type.Func + 4,\n\t\t\td, // arguably this should be d.Type\n\t\t},\n\t\t{\n\t\t\t// \"(\" FieldList\n\t\t\td.Recv.Pos(), d.Recv.Pos() + 1,\n\t\t\td.Recv,\n\t\t},\n\t\t{\n\t\t\t// \"recv\" Ident\n\t\t\td.Recv.List[0].Pos(), d.Recv.List[0].Pos() + 1,\n\t\t\td.Recv.List[0].Type,\n\t\t},\n\t\t{\n\t\t\t// \"name\" Ident\n\t\t\td.Name.Pos(), d.Name.Pos() + 1,\n\t\t\td.Name,\n\t\t},\n\t\t{\n\t\t\t// \"(\" FieldList\n\t\t\td.Type.Params.Pos(), d.Type.Params.Pos() + 1,\n\t\t\td.Type.Params,\n\t\t},\n\t\t{\n\t\t\t// \"params\" Ident\n\t\t\td.Type.Params.List[0].Pos(), d.Type.Params.List[0].Pos() + 1,\n\t\t\td.Type.Params.List[0].Type,\n\t\t},\n\t\t{\n\t\t\t// \"(\" FieldList\n\t\t\td.Type.Results.Pos(), d.Type.Results.Pos() + 1,\n\t\t\td.Type.Results,\n\t\t},\n\t\t{\n\t\t\t// \"results\" Ident\n\t\t\td.Type.Results.List[0].Pos(), d.Type.Results.List[0].Pos() + 1,\n\t\t\td.Type.Results.List[0].Type,\n\t\t},\n\t\t{\n\t\t\t// \"{\" BlockStmt\n\t\t\td.Body.Pos(), d.Body.Pos() + 1,\n\t\t\td.Body,\n\t\t},\n\t\t{\n\t\t\t// \"body\" Ident\n\t\t\td.Body.List[0].Pos(), d.Body.List[0].Pos() + 1,\n\t\t\td.Body.List[0].(*ast.ExprStmt).X,\n\t\t},\n\t} {\n\t\tcur, ok := inspect.Root().FindByPos(test.start, test.end)\n\t\tif !ok || cur.Node() == nil {\n\t\t\tt.Errorf(\"%s: FindByPos failed\", format(test.start, test.end))\n\t\t\tcontinue\n\t\t}\n\t\tgot := cur.Node()\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"FindByPos:\\ninput:\\t%s\\ngot:\\t%s (%T)\\nwant:\\t%s (%T)\",\n\t\t\t\tformat(test.start, test.end),\n\t\t\t\tformat(got.Pos(), got.End()), got,\n\t\t\t\tformat(test.want.Pos(), test.want.End()), test.want)\n\t\t}\n\t}\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\n// sliceTypes is a debugging helper that formats each slice element with %T.\nfunc sliceTypes[T any](slice []T) string {\n\tvar buf strings.Builder\n\tbuf.WriteByte('[')\n\tfor i, elem := range slice {\n\t\tif i > 0 {\n\t\t\tbuf.WriteByte(' ')\n\t\t}\n\t\tfmt.Fprintf(&buf, \"%T\", elem)\n\t}\n\tbuf.WriteByte(']')\n\treturn buf.String()\n}\n\nfunc BenchmarkInspectCalls(b *testing.B) {\n\tinspect := netInspect\n\n\t// Measure marginal cost of traversal.\n\n\tcallExprs := []ast.Node{(*ast.CallExpr)(nil)}\n\n\tb.Run(\"Preorder\", func(b *testing.B) {\n\t\tvar ncalls int\n\t\tfor b.Loop() {\n\t\t\tinspect.Preorder(callExprs, func(n ast.Node) {\n\t\t\t\t_ = n.(*ast.CallExpr)\n\t\t\t\tncalls++\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"WithStack\", func(b *testing.B) {\n\t\tvar ncalls int\n\t\tfor b.Loop() {\n\t\t\tinspect.WithStack(callExprs, func(n ast.Node, push bool, stack []ast.Node) (proceed bool) {\n\t\t\t\t_ = n.(*ast.CallExpr)\n\t\t\t\tif push {\n\t\t\t\t\tncalls++\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"Cursor\", func(b *testing.B) {\n\t\tvar ncalls int\n\t\tfor b.Loop() {\n\t\t\tfor cur := range inspect.Root().Preorder(callExprs...) {\n\t\t\t\t_ = cur.Node().(*ast.CallExpr)\n\t\t\t\tncalls++\n\t\t\t}\n\t\t}\n\t})\n\n\tb.Run(\"CursorEnclosing\", func(b *testing.B) {\n\t\tvar ncalls int\n\t\tfor b.Loop() {\n\t\t\tfor cur := range inspect.Root().Preorder(callExprs...) {\n\t\t\t\t_ = cur.Node().(*ast.CallExpr)\n\t\t\t\tfor range cur.Enclosing() {\n\t\t\t\t}\n\t\t\t\tncalls++\n\t\t\t}\n\t\t}\n\t})\n}\n\n// This benchmark compares methods for finding a known node in a tree.\nfunc BenchmarkCursor_FindNode(b *testing.B) {\n\troot := netInspect.Root()\n\n\tcallExprs := []ast.Node{(*ast.CallExpr)(nil)}\n\n\t// Choose a needle in the haystack to use as the search target:\n\t// a CallExpr not too near the start nor at too shallow a depth.\n\tvar needle inspector.Cursor\n\t{\n\t\tcount := 0\n\t\tfound := false\n\t\tfor c := range root.Preorder(callExprs...) {\n\t\t\tcount++\n\t\t\tif count >= 1000 && iterlen(c.Enclosing()) >= 6 {\n\t\t\t\tneedle = c\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tb.Fatal(\"can't choose needle\")\n\t\t}\n\t}\n\n\tb.ResetTimer()\n\n\tb.Run(\"Cursor.Preorder\", func(b *testing.B) {\n\t\tneedleNode := needle.Node()\n\t\tfor b.Loop() {\n\t\t\tvar found inspector.Cursor\n\t\t\tfor c := range root.Preorder(callExprs...) {\n\t\t\t\tif c.Node() == needleNode {\n\t\t\t\t\tfound = c\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif found != needle {\n\t\t\t\tb.Errorf(\"Preorder search failed: got %v, want %v\", found, needle)\n\t\t\t}\n\t\t}\n\t})\n\n\t// This method is about 10-15% faster than Cursor.Preorder.\n\tb.Run(\"Cursor.FindNode\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tfound, ok := root.FindNode(needle.Node())\n\t\t\tif !ok || found != needle {\n\t\t\t\tb.Errorf(\"FindNode search failed: got %v, want %v\", found, needle)\n\t\t\t}\n\t\t}\n\t})\n\n\t// This method is about 100x (!) faster than Cursor.Preorder.\n\tb.Run(\"Cursor.FindByPos\", func(b *testing.B) {\n\t\tneedleNode := needle.Node()\n\t\tfor b.Loop() {\n\t\t\tfound, ok := root.FindByPos(needleNode.Pos(), needleNode.End())\n\t\t\tif !ok || found != needle {\n\t\t\t\tb.Errorf(\"FindByPos search failed: got %v, want %v\", found, needle)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc iterlen[T any](seq iter.Seq[T]) (len int) {\n\tfor range seq {\n\t\tlen++\n\t}\n\treturn\n}\n"
  },
  {
    "path": "go/ast/inspector/inspector.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package inspector provides helper functions for traversal over the\n// syntax trees of a package, including node filtering by type, and\n// materialization of the traversal stack.\n//\n// During construction, the inspector does a complete traversal and\n// builds a list of push/pop events and their node type. Subsequent\n// method calls that request a traversal scan this list, rather than walk\n// the AST, and perform type filtering using efficient bit sets.\n// This representation is sometimes called a \"balanced parenthesis tree.\"\n//\n// Experiments suggest the inspector's traversals are about 2.5x faster\n// than [ast.Inspect], but it may take around 5 traversals for this\n// benefit to amortize the inspector's construction cost.\n// If efficiency is the primary concern, do not use Inspector for\n// one-off traversals.\n//\n// The [Cursor] type provides a more flexible API for efficient\n// navigation of syntax trees in all four \"cardinal directions\". For\n// example, traversals may be nested, so you can find each node of\n// type A and then search within it for nodes of type B. Or you can\n// traverse from a node to its immediate neighbors: its parent, its\n// previous and next sibling, or its first and last child. We\n// recommend using methods of Cursor in preference to Inspector where\n// possible.\npackage inspector\n\n// There are four orthogonal features in a traversal:\n//  1 type filtering\n//  2 pruning\n//  3 postorder calls to f\n//  4 stack\n// Rather than offer all of them in the API,\n// only a few combinations are exposed:\n// - Preorder is the fastest and has fewest features,\n//   but is the most commonly needed traversal.\n// - Nodes and WithStack both provide pruning and postorder calls,\n//   even though few clients need it, because supporting two versions\n//   is not justified.\n// More combinations could be supported by expressing them as\n// wrappers around a more generic traversal, but this was measured\n// and found to degrade performance significantly (30%).\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n)\n\n// An Inspector provides methods for inspecting\n// (traversing) the syntax trees of a package.\ntype Inspector struct {\n\tevents []event\n}\n\nfunc packEdgeKindAndIndex(ek edge.Kind, index int) int32 {\n\treturn int32(uint32(index+1)<<7 | uint32(ek))\n}\n\n// unpackEdgeKindAndIndex unpacks the edge kind and edge index (within\n// an []ast.Node slice) from the parent field of a pop event.\nfunc unpackEdgeKindAndIndex(x int32) (edge.Kind, int) {\n\t// The \"parent\" field of a pop node holds the\n\t// edge Kind in the lower 7 bits and the index+1\n\t// in the upper 25.\n\treturn edge.Kind(x & 0x7f), int(x>>7) - 1\n}\n\n// New returns an Inspector for the specified syntax trees.\nfunc New(files []*ast.File) *Inspector {\n\treturn &Inspector{traverse(files)}\n}\n\n// An event represents a push or a pop\n// of an ast.Node during a traversal.\ntype event struct {\n\tnode   ast.Node\n\ttyp    uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events\n\tindex  int32  // index of corresponding push or pop event\n\tparent int32  // index of parent's push node (push nodes only), or packed edge kind/index (pop nodes only)\n}\n\n// TODO: Experiment with storing only the second word of event.node (unsafe.Pointer).\n// Type can be recovered from the sole bit in typ.\n// [Tried this, wasn't faster. --adonovan]\n\n// Preorder visits all the nodes of the files supplied to [New] in\n// depth-first order. It calls f(n) for each node n before it visits\n// n's children.\n//\n// The complete traversal sequence is determined by [ast.Inspect].\n// The types argument, if non-empty, enables type-based filtering of\n// events. The function f is called only for nodes whose type\n// matches an element of the types slice.\n//\n// The [Cursor.Preorder] method provides a richer alternative interface.\n// Example:\n//\n//\tfor c := range in.Root().Preorder(types) { ... }\nfunc (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {\n\t// Because it avoids postorder calls to f, and the pruning\n\t// check, Preorder is almost twice as fast as Nodes. The two\n\t// features seem to contribute similar slowdowns (~1.4x each).\n\n\t// This function is equivalent to the PreorderSeq call below,\n\t// but to avoid the additional dynamic call (which adds 13-35%\n\t// to the benchmarks), we expand it out.\n\t//\n\t// in.PreorderSeq(types...)(func(n ast.Node) bool {\n\t// \tf(n)\n\t// \treturn true\n\t// })\n\n\tmask := maskOf(types)\n\tfor i := int32(0); i < int32(len(in.events)); {\n\t\tev := in.events[i]\n\t\tif ev.index > i {\n\t\t\t// push\n\t\t\tif ev.typ&mask != 0 {\n\t\t\t\tf(ev.node)\n\t\t\t}\n\t\t\tpop := ev.index\n\t\t\tif in.events[pop].typ&mask == 0 {\n\t\t\t\t// Subtrees do not contain types: skip them and pop.\n\t\t\t\ti = pop + 1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n}\n\n// Nodes visits the nodes of the files supplied to [New] in depth-first\n// order. It calls f(n, true) for each node n before it visits n's\n// children. If f returns true, Nodes invokes f recursively for each\n// of the non-nil children of the node, followed by a call of\n// f(n, false).\n//\n// The complete traversal sequence is determined by [ast.Inspect].\n// The types argument, if non-empty, enables type-based filtering of\n// events. The function f if is called only for nodes whose type\n// matches an element of the types slice.\n//\n// The [Cursor.Inspect] method provides a richer alternative interface.\n// Example:\n//\n//\tin.Root().Inspect(types, func(c Cursor) bool {\n//\t\t...\n//\t\treturn true\n//\t}\nfunc (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) {\n\tmask := maskOf(types)\n\tfor i := int32(0); i < int32(len(in.events)); {\n\t\tev := in.events[i]\n\t\tif ev.index > i {\n\t\t\t// push\n\t\t\tpop := ev.index\n\t\t\tif ev.typ&mask != 0 {\n\t\t\t\tif !f(ev.node, true) {\n\t\t\t\t\ti = pop + 1 // jump to corresponding pop + 1\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif in.events[pop].typ&mask == 0 {\n\t\t\t\t// Subtrees do not contain types: skip them.\n\t\t\t\ti = pop\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// pop\n\t\t\tpush := ev.index\n\t\t\tif in.events[push].typ&mask != 0 {\n\t\t\t\tf(ev.node, false)\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n}\n\n// WithStack visits nodes in a similar manner to Nodes, but it\n// supplies each call to f an additional argument, the current\n// traversal stack. The stack's first element is the outermost node,\n// an *ast.File; its last is the innermost, n.\n//\n// The [Cursor.Inspect] method provides a richer alternative interface.\n// Example:\n//\n//\tin.Root().Inspect(types, func(c Cursor) bool {\n//\t\tstack := slices.Collect(c.Enclosing())\n//\t\t...\n//\t\treturn true\n//\t})\nfunc (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) {\n\tmask := maskOf(types)\n\tvar stack []ast.Node\n\tfor i := int32(0); i < int32(len(in.events)); {\n\t\tev := in.events[i]\n\t\tif ev.index > i {\n\t\t\t// push\n\t\t\tpop := ev.index\n\t\t\tstack = append(stack, ev.node)\n\t\t\tif ev.typ&mask != 0 {\n\t\t\t\tif !f(ev.node, true, stack) {\n\t\t\t\t\ti = pop + 1\n\t\t\t\t\tstack = stack[:len(stack)-1]\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif in.events[pop].typ&mask == 0 {\n\t\t\t\t// Subtrees does not contain types: skip them.\n\t\t\t\ti = pop\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// pop\n\t\t\tpush := ev.index\n\t\t\tif in.events[push].typ&mask != 0 {\n\t\t\t\tf(ev.node, false, stack)\n\t\t\t}\n\t\t\tstack = stack[:len(stack)-1]\n\t\t}\n\t\ti++\n\t}\n}\n\n// traverse builds the table of events representing a traversal.\nfunc traverse(files []*ast.File) []event {\n\t// Preallocate approximate number of events\n\t// based on source file extent of the declarations.\n\t// (We use End-Pos not FileStart-FileEnd to neglect\n\t// the effect of long doc comments.)\n\t// This makes traverse faster by 4x (!).\n\tvar extent int\n\tfor _, f := range files {\n\t\textent += int(f.End() - f.Pos())\n\t}\n\t// This estimate is based on the net/http package.\n\tcapacity := min(extent*33/100, 1e6) // impose some reasonable maximum (1M)\n\n\tv := &visitor{\n\t\tevents: make([]event, 0, capacity),\n\t\tstack:  []item{{index: -1}}, // include an extra event so file nodes have a parent\n\t}\n\tfor _, file := range files {\n\t\twalk(v, edge.Invalid, -1, file)\n\t}\n\treturn v.events\n}\n\ntype visitor struct {\n\tevents []event\n\tstack  []item\n}\n\ntype item struct {\n\tindex            int32  // index of current node's push event\n\tparentIndex      int32  // index of parent node's push event\n\ttypAccum         uint64 // accumulated type bits of current node's descendants\n\tedgeKindAndIndex int32  // edge.Kind and index, bit packed\n}\n\nfunc (v *visitor) push(ek edge.Kind, eindex int, node ast.Node) {\n\tvar (\n\t\tindex       = int32(len(v.events))\n\t\tparentIndex = v.stack[len(v.stack)-1].index\n\t)\n\tv.events = append(v.events, event{\n\t\tnode:   node,\n\t\tparent: parentIndex,\n\t\ttyp:    typeOf(node),\n\t\tindex:  0, // (pop index is set later by visitor.pop)\n\t})\n\tv.stack = append(v.stack, item{\n\t\tindex:            index,\n\t\tparentIndex:      parentIndex,\n\t\tedgeKindAndIndex: packEdgeKindAndIndex(ek, eindex),\n\t})\n\n\t// 2B nodes ought to be enough for anyone!\n\tif int32(len(v.events)) < 0 {\n\t\tpanic(\"event index exceeded int32\")\n\t}\n\n\t// 32M elements in an []ast.Node ought to be enough for anyone!\n\tif ek2, eindex2 := unpackEdgeKindAndIndex(packEdgeKindAndIndex(ek, eindex)); ek2 != ek || eindex2 != eindex {\n\t\tpanic(\"Node slice index exceeded uint25\")\n\t}\n}\n\nfunc (v *visitor) pop(node ast.Node) {\n\ttop := len(v.stack) - 1\n\tcurrent := v.stack[top]\n\n\tpush := &v.events[current.index]\n\tparent := &v.stack[top-1]\n\n\tpush.index = int32(len(v.events))              // make push event refer to pop\n\tparent.typAccum |= current.typAccum | push.typ // accumulate type bits into parent\n\n\tv.stack = v.stack[:top]\n\n\tv.events = append(v.events, event{\n\t\tnode:   node,\n\t\ttyp:    current.typAccum,\n\t\tindex:  current.index,\n\t\tparent: current.edgeKindAndIndex, // see [unpackEdgeKindAndIndex]\n\t})\n}\n"
  },
  {
    "path": "go/ast/inspector/inspector_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector_test\n\nimport (\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"log\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\n// net/http package\nvar (\n\tnetFset    = token.NewFileSet()\n\tnetFiles   []*ast.File\n\tnetInspect *inspector.Inspector\n)\n\nfunc init() {\n\tfiles, err := parseNetFiles()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tnetFiles = files\n\tnetInspect = inspector.New(netFiles)\n}\n\nfunc parseNetFiles() ([]*ast.File, error) {\n\tpkg, err := build.Default.Import(\"net\", \"\", 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar files []*ast.File\n\tfor _, filename := range pkg.GoFiles {\n\t\tfilename = filepath.Join(pkg.Dir, filename)\n\t\tf, err := parser.ParseFile(netFset, filename, nil, 0)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfiles = append(files, f)\n\t}\n\treturn files, nil\n}\n\n// TestInspectAllNodes compares Inspector against ast.Inspect.\nfunc TestInspectAllNodes(t *testing.T) {\n\tinspect := inspector.New(netFiles)\n\n\tvar nodesA []ast.Node\n\tinspect.Nodes(nil, func(n ast.Node, push bool) bool {\n\t\tif push {\n\t\t\tnodesA = append(nodesA, n)\n\t\t}\n\t\treturn true\n\t})\n\tvar nodesB []ast.Node\n\tfor _, f := range netFiles {\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif n != nil {\n\t\t\t\tnodesB = append(nodesB, n)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\tcompare(t, nodesA, nodesB)\n}\n\nfunc TestInspectGenericNodes(t *testing.T) {\n\t// src is using the 16 identifiers i0, i1, ... i15 so\n\t// we can easily verify that we've found all of them.\n\tconst src = `package a\n\ntype I interface { ~i0|i1 }\n\ntype T[i2, i3 interface{ ~i4 }] struct {}\n\nfunc f[i5, i6 any]() {\n\t_ = f[i7, i8]\n\tvar x T[i9, i10]\n}\n\nfunc (*T[i11, i12]) m()\n\nvar _ i13[i14, i15]\n`\n\tfset := token.NewFileSet()\n\tf, _ := parser.ParseFile(fset, \"a.go\", src, 0)\n\tinspect := inspector.New([]*ast.File{f})\n\tfound := make([]bool, 16)\n\n\tindexListExprs := make(map[*ast.IndexListExpr]bool)\n\n\t// Verify that we reach all i* identifiers, and collect IndexListExpr nodes.\n\tinspect.Preorder(nil, func(n ast.Node) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Ident:\n\t\t\tif n.Name[0] == 'i' {\n\t\t\t\tindex, err := strconv.Atoi(n.Name[1:])\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tfound[index] = true\n\t\t\t}\n\t\tcase *ast.IndexListExpr:\n\t\t\tindexListExprs[n] = false\n\t\t}\n\t})\n\tfor i, v := range found {\n\t\tif !v {\n\t\t\tt.Errorf(\"missed identifier i%d\", i)\n\t\t}\n\t}\n\n\t// Verify that we can filter to IndexListExprs that we found in the first\n\t// step.\n\tif len(indexListExprs) == 0 {\n\t\tt.Fatal(\"no index list exprs found\")\n\t}\n\tinspect.Preorder([]ast.Node{&ast.IndexListExpr{}}, func(n ast.Node) {\n\t\tix := n.(*ast.IndexListExpr)\n\t\tindexListExprs[ix] = true\n\t})\n\tfor ix, v := range indexListExprs {\n\t\tif !v {\n\t\t\tt.Errorf(\"inspected node %v not filtered\", ix)\n\t\t}\n\t}\n}\n\n// TestInspectPruning compares Inspector against ast.Inspect,\n// pruning descent within ast.CallExpr nodes.\nfunc TestInspectPruning(t *testing.T) {\n\tinspect := inspector.New(netFiles)\n\n\tvar nodesA []ast.Node\n\tinspect.Nodes(nil, func(n ast.Node, push bool) bool {\n\t\tif push {\n\t\t\tnodesA = append(nodesA, n)\n\t\t\t_, isCall := n.(*ast.CallExpr)\n\t\t\treturn !isCall // don't descend into function calls\n\t\t}\n\t\treturn false\n\t})\n\tvar nodesB []ast.Node\n\tfor _, f := range netFiles {\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif n != nil {\n\t\t\t\tnodesB = append(nodesB, n)\n\t\t\t\t_, isCall := n.(*ast.CallExpr)\n\t\t\t\treturn !isCall // don't descend into function calls\n\t\t\t}\n\t\t\treturn false\n\t\t})\n\t}\n\tcompare(t, nodesA, nodesB)\n}\n\n// compare calls t.Error if !slices.Equal(nodesA, nodesB).\nfunc compare[N comparable](t *testing.T, nodesA, nodesB []N) {\n\tif len(nodesA) != len(nodesB) {\n\t\tt.Errorf(\"inconsistent node lists: %d vs %d\", len(nodesA), len(nodesB))\n\t} else {\n\t\tfor i := range nodesA {\n\t\t\tif a, b := nodesA[i], nodesB[i]; a != b {\n\t\t\t\tt.Errorf(\"node %d is inconsistent: %T, %T\", i, a, b)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestTypeFiltering(t *testing.T) {\n\tconst src = `package a\nfunc f() {\n\tprint(\"hi\")\n\tpanic(\"oops\")\n}\n`\n\tfset := token.NewFileSet()\n\tf, _ := parser.ParseFile(fset, \"a.go\", src, 0)\n\tinspect := inspector.New([]*ast.File{f})\n\n\tvar got []string\n\tfn := func(n ast.Node, push bool) bool {\n\t\tif push {\n\t\t\tgot = append(got, typeOf(n))\n\t\t}\n\t\treturn true\n\t}\n\n\t// no type filtering\n\tinspect.Nodes(nil, fn)\n\tif want := strings.Fields(\"File Ident FuncDecl Ident FuncType FieldList BlockStmt ExprStmt CallExpr Ident BasicLit ExprStmt CallExpr Ident BasicLit\"); !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"inspect: got %s, want %s\", got, want)\n\t}\n\n\t// type filtering\n\tnodeTypes := []ast.Node{\n\t\t(*ast.BasicLit)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t}\n\tgot = nil\n\tinspect.Nodes(nodeTypes, fn)\n\tif want := strings.Fields(\"CallExpr BasicLit CallExpr BasicLit\"); !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"inspect: got %s, want %s\", got, want)\n\t}\n\n\t// inspect with stack\n\tgot = nil\n\tinspect.WithStack(nodeTypes, func(n ast.Node, push bool, stack []ast.Node) bool {\n\t\tif push {\n\t\t\tvar line []string\n\t\t\tfor _, n := range stack {\n\t\t\t\tline = append(line, typeOf(n))\n\t\t\t}\n\t\t\tgot = append(got, strings.Join(line, \" \"))\n\t\t}\n\t\treturn true\n\t})\n\twant := []string{\n\t\t\"File FuncDecl BlockStmt ExprStmt CallExpr\",\n\t\t\"File FuncDecl BlockStmt ExprStmt CallExpr BasicLit\",\n\t\t\"File FuncDecl BlockStmt ExprStmt CallExpr\",\n\t\t\"File FuncDecl BlockStmt ExprStmt CallExpr BasicLit\",\n\t}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"inspect: got %s, want %s\", got, want)\n\t}\n}\n\nfunc typeOf(n ast.Node) string {\n\treturn strings.TrimPrefix(reflect.TypeOf(n).String(), \"*ast.\")\n}\n\n// The numbers show a marginal improvement (ASTInspect/Inspect) of 3.5x,\n// but a break-even point (NewInspector/(ASTInspect-Inspect)) of about 5\n// traversals.\n//\n// BenchmarkASTInspect     1.0 ms\n// BenchmarkNewInspector   2.2 ms\n// BenchmarkInspect        0.39ms\n// BenchmarkInspectFilter  0.01ms\n// BenchmarkInspectCalls   0.14ms\n\nfunc BenchmarkNewInspector(b *testing.B) {\n\t// Measure one-time construction overhead.\n\tfor b.Loop() {\n\t\tinspector.New(netFiles)\n\t}\n}\n\nfunc BenchmarkInspect(b *testing.B) {\n\n\tinspect := inspector.New(netFiles)\n\n\t// Measure marginal cost of traversal.\n\tvar ndecls, nlits int\n\tfor b.Loop() {\n\t\tinspect.Preorder(nil, func(n ast.Node) {\n\t\t\tswitch n.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tndecls++\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tnlits++\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkInspectFilter(b *testing.B) {\n\n\tinspect := inspector.New(netFiles)\n\n\t// Measure marginal cost of traversal.\n\tnodeFilter := []ast.Node{(*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)}\n\tvar ndecls, nlits int\n\tfor b.Loop() {\n\t\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\t\tswitch n.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tndecls++\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tnlits++\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkASTInspect(b *testing.B) {\n\tvar ndecls, nlits int\n\tfor b.Loop() {\n\t\tfor _, f := range netFiles {\n\t\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\t\tswitch n.(type) {\n\t\t\t\tcase *ast.FuncDecl:\n\t\t\t\t\tndecls++\n\t\t\t\tcase *ast.FuncLit:\n\t\t\t\t\tnlits++\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ast/inspector/iter.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.23\n\npackage inspector\n\nimport (\n\t\"go/ast\"\n\t\"iter\"\n)\n\n// PreorderSeq returns an iterator that visits all the\n// nodes of the files supplied to [New] in depth-first order.\n// It visits each node n before n's children.\n// The complete traversal sequence is determined by ast.Inspect.\n//\n// The types argument, if non-empty, enables type-based filtering:\n// only nodes whose type matches an element of the types slice are\n// included in the sequence.\n//\n// Example:\n//\n//\tfor call := range in.PreorderSeq((*ast.CallExpr)(nil)) { ... }\n//\n// The [All] function is more convenient if there is exactly one node type:\n//\n//\tfor call := range All[*ast.CallExpr](in) { ... }\n//\n// See also the newer and more flexible [Cursor] API, which lets you\n// start the traversal at an arbitrary node, and reports each matching\n// node by its Cursor, enabling easier navigation.\n// The above example would be written thus:\n//\n//\tfor curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {\n//\t\tcall := curCall.Node().(*ast.CallExpr)\n//\t\t...\n//\t}\nfunc (in *Inspector) PreorderSeq(types ...ast.Node) iter.Seq[ast.Node] {\n\n\t// This implementation is identical to Preorder,\n\t// except that it supports breaking out of the loop.\n\n\treturn func(yield func(ast.Node) bool) {\n\t\tmask := maskOf(types)\n\t\tfor i := int32(0); i < int32(len(in.events)); {\n\t\t\tev := in.events[i]\n\t\t\tif ev.index > i {\n\t\t\t\t// push\n\t\t\t\tif ev.typ&mask != 0 {\n\t\t\t\t\tif !yield(ev.node) {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpop := ev.index\n\t\t\t\tif in.events[pop].typ&mask == 0 {\n\t\t\t\t\t// Subtrees do not contain types: skip them and pop.\n\t\t\t\t\ti = pop + 1\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// All[N] returns an iterator over all the nodes of type N.\n// N must be a pointer-to-struct type that implements ast.Node.\n//\n// Example:\n//\n//\tfor call := range All[*ast.CallExpr](in) { ... }\n//\n// See also the newer and more flexible [Cursor] API, which lets you\n// start the traversal at an arbitrary node, and reports each matching\n// node by its Cursor, enabling easier navigation.\n// The above example would be written thus:\n//\n//\tfor curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {\n//\t\tcall := curCall.Node().(*ast.CallExpr)\n//\t\t...\n//\t}\nfunc All[N interface {\n\t*S\n\tast.Node\n}, S any](in *Inspector) iter.Seq[N] {\n\n\t// To avoid additional dynamic call overheads,\n\t// we duplicate rather than call the logic of PreorderSeq.\n\n\tmask := typeOf((N)(nil))\n\treturn func(yield func(N) bool) {\n\t\tfor i := int32(0); i < int32(len(in.events)); {\n\t\t\tev := in.events[i]\n\t\t\tif ev.index > i {\n\t\t\t\t// push\n\t\t\t\tif ev.typ&mask != 0 {\n\t\t\t\t\tif !yield(ev.node.(N)) {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpop := ev.index\n\t\t\t\tif in.events[pop].typ&mask == 0 {\n\t\t\t\t\t// Subtrees do not contain types: skip them and pop.\n\t\t\t\t\ti = pop + 1\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ast/inspector/iter_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector_test\n\nimport (\n\t\"go/ast\"\n\t\"iter\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\n// TestPreorderSeq checks PreorderSeq against Preorder.\nfunc TestPreorderSeq(t *testing.T) {\n\tinspect := inspector.New(netFiles)\n\n\tnodeFilter := []ast.Node{(*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)}\n\n\t// reference implementation\n\tvar want []ast.Node\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\twant = append(want, n)\n\t})\n\n\t// Check entire sequence.\n\tgot := slices.Collect(inspect.PreorderSeq(nodeFilter...))\n\tcompare(t, got, want)\n\n\t// Check that break works.\n\tgot = firstN(10, inspect.PreorderSeq(nodeFilter...))\n\tcompare(t, got, want[:10])\n}\n\n// TestAll checks All against Preorder.\nfunc TestAll(t *testing.T) {\n\tinspect := inspector.New(netFiles)\n\n\t// reference implementation\n\tvar want []*ast.CallExpr\n\tinspect.Preorder([]ast.Node{(*ast.CallExpr)(nil)}, func(n ast.Node) {\n\t\twant = append(want, n.(*ast.CallExpr))\n\t})\n\n\t// Check entire sequence.\n\tgot := slices.Collect(inspector.All[*ast.CallExpr](inspect))\n\tcompare(t, got, want)\n\n\t// Check that break works.\n\tgot = firstN(10, inspector.All[*ast.CallExpr](inspect))\n\tcompare(t, got, want[:10])\n}\n\n// firstN(n, seq), returns a slice of up to n elements of seq.\nfunc firstN[T any](n int, seq iter.Seq[T]) (res []T) {\n\tfor x := range seq {\n\t\tres = append(res, x)\n\t\tif len(res) == n {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn res\n}\n\n// BenchmarkAllCalls is like BenchmarkInspectCalls,\n// but using the single-type filtering iterator, All.\n// (The iterator adds about 5-15%.)\nfunc BenchmarkAllCalls(b *testing.B) {\n\tinspect := inspector.New(netFiles)\n\n\t// Measure marginal cost of traversal.\n\tvar ncalls int\n\tfor b.Loop() {\n\t\tfor range inspector.All[*ast.CallExpr](inspect) {\n\t\t\tncalls++\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ast/inspector/typeof.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector\n\n// This file defines func typeOf(ast.Node) uint64.\n//\n// The initial map-based implementation was too slow;\n// see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196\n\nimport (\n\t\"go/ast\"\n\t\"math\"\n)\n\nconst (\n\tnArrayType = iota\n\tnAssignStmt\n\tnBadDecl\n\tnBadExpr\n\tnBadStmt\n\tnBasicLit\n\tnBinaryExpr\n\tnBlockStmt\n\tnBranchStmt\n\tnCallExpr\n\tnCaseClause\n\tnChanType\n\tnCommClause\n\tnComment\n\tnCommentGroup\n\tnCompositeLit\n\tnDeclStmt\n\tnDeferStmt\n\tnEllipsis\n\tnEmptyStmt\n\tnExprStmt\n\tnField\n\tnFieldList\n\tnFile\n\tnForStmt\n\tnFuncDecl\n\tnFuncLit\n\tnFuncType\n\tnGenDecl\n\tnGoStmt\n\tnIdent\n\tnIfStmt\n\tnImportSpec\n\tnIncDecStmt\n\tnIndexExpr\n\tnIndexListExpr\n\tnInterfaceType\n\tnKeyValueExpr\n\tnLabeledStmt\n\tnMapType\n\tnPackage\n\tnParenExpr\n\tnRangeStmt\n\tnReturnStmt\n\tnSelectStmt\n\tnSelectorExpr\n\tnSendStmt\n\tnSliceExpr\n\tnStarExpr\n\tnStructType\n\tnSwitchStmt\n\tnTypeAssertExpr\n\tnTypeSpec\n\tnTypeSwitchStmt\n\tnUnaryExpr\n\tnValueSpec\n)\n\n// typeOf returns a distinct single-bit value that represents the type of n.\n//\n// Various implementations were benchmarked with BenchmarkNewInspector:\n//\n//\t                                                                GOGC=off\n//\t- type switch\t\t\t\t\t4.9-5.5ms\t2.1ms\n//\t- binary search over a sorted list of types\t5.5-5.9ms\t2.5ms\n//\t- linear scan, frequency-ordered list\t\t5.9-6.1ms\t2.7ms\n//\t- linear scan, unordered list\t\t\t6.4ms\t\t2.7ms\n//\t- hash table\t\t\t\t\t6.5ms\t\t3.1ms\n//\n// A perfect hash seemed like overkill.\n//\n// The compiler's switch statement is the clear winner\n// as it produces a binary tree in code,\n// with constant conditions and good branch prediction.\n// (Sadly it is the most verbose in source code.)\n// Binary search suffered from poor branch prediction.\nfunc typeOf(n ast.Node) uint64 {\n\t// Fast path: nearly half of all nodes are identifiers.\n\tif _, ok := n.(*ast.Ident); ok {\n\t\treturn 1 << nIdent\n\t}\n\n\t// These cases include all nodes encountered by ast.Inspect.\n\tswitch n.(type) {\n\tcase *ast.ArrayType:\n\t\treturn 1 << nArrayType\n\tcase *ast.AssignStmt:\n\t\treturn 1 << nAssignStmt\n\tcase *ast.BadDecl:\n\t\treturn 1 << nBadDecl\n\tcase *ast.BadExpr:\n\t\treturn 1 << nBadExpr\n\tcase *ast.BadStmt:\n\t\treturn 1 << nBadStmt\n\tcase *ast.BasicLit:\n\t\treturn 1 << nBasicLit\n\tcase *ast.BinaryExpr:\n\t\treturn 1 << nBinaryExpr\n\tcase *ast.BlockStmt:\n\t\treturn 1 << nBlockStmt\n\tcase *ast.BranchStmt:\n\t\treturn 1 << nBranchStmt\n\tcase *ast.CallExpr:\n\t\treturn 1 << nCallExpr\n\tcase *ast.CaseClause:\n\t\treturn 1 << nCaseClause\n\tcase *ast.ChanType:\n\t\treturn 1 << nChanType\n\tcase *ast.CommClause:\n\t\treturn 1 << nCommClause\n\tcase *ast.Comment:\n\t\treturn 1 << nComment\n\tcase *ast.CommentGroup:\n\t\treturn 1 << nCommentGroup\n\tcase *ast.CompositeLit:\n\t\treturn 1 << nCompositeLit\n\tcase *ast.DeclStmt:\n\t\treturn 1 << nDeclStmt\n\tcase *ast.DeferStmt:\n\t\treturn 1 << nDeferStmt\n\tcase *ast.Ellipsis:\n\t\treturn 1 << nEllipsis\n\tcase *ast.EmptyStmt:\n\t\treturn 1 << nEmptyStmt\n\tcase *ast.ExprStmt:\n\t\treturn 1 << nExprStmt\n\tcase *ast.Field:\n\t\treturn 1 << nField\n\tcase *ast.FieldList:\n\t\treturn 1 << nFieldList\n\tcase *ast.File:\n\t\treturn 1 << nFile\n\tcase *ast.ForStmt:\n\t\treturn 1 << nForStmt\n\tcase *ast.FuncDecl:\n\t\treturn 1 << nFuncDecl\n\tcase *ast.FuncLit:\n\t\treturn 1 << nFuncLit\n\tcase *ast.FuncType:\n\t\treturn 1 << nFuncType\n\tcase *ast.GenDecl:\n\t\treturn 1 << nGenDecl\n\tcase *ast.GoStmt:\n\t\treturn 1 << nGoStmt\n\tcase *ast.Ident:\n\t\treturn 1 << nIdent\n\tcase *ast.IfStmt:\n\t\treturn 1 << nIfStmt\n\tcase *ast.ImportSpec:\n\t\treturn 1 << nImportSpec\n\tcase *ast.IncDecStmt:\n\t\treturn 1 << nIncDecStmt\n\tcase *ast.IndexExpr:\n\t\treturn 1 << nIndexExpr\n\tcase *ast.IndexListExpr:\n\t\treturn 1 << nIndexListExpr\n\tcase *ast.InterfaceType:\n\t\treturn 1 << nInterfaceType\n\tcase *ast.KeyValueExpr:\n\t\treturn 1 << nKeyValueExpr\n\tcase *ast.LabeledStmt:\n\t\treturn 1 << nLabeledStmt\n\tcase *ast.MapType:\n\t\treturn 1 << nMapType\n\tcase *ast.Package:\n\t\treturn 1 << nPackage\n\tcase *ast.ParenExpr:\n\t\treturn 1 << nParenExpr\n\tcase *ast.RangeStmt:\n\t\treturn 1 << nRangeStmt\n\tcase *ast.ReturnStmt:\n\t\treturn 1 << nReturnStmt\n\tcase *ast.SelectStmt:\n\t\treturn 1 << nSelectStmt\n\tcase *ast.SelectorExpr:\n\t\treturn 1 << nSelectorExpr\n\tcase *ast.SendStmt:\n\t\treturn 1 << nSendStmt\n\tcase *ast.SliceExpr:\n\t\treturn 1 << nSliceExpr\n\tcase *ast.StarExpr:\n\t\treturn 1 << nStarExpr\n\tcase *ast.StructType:\n\t\treturn 1 << nStructType\n\tcase *ast.SwitchStmt:\n\t\treturn 1 << nSwitchStmt\n\tcase *ast.TypeAssertExpr:\n\t\treturn 1 << nTypeAssertExpr\n\tcase *ast.TypeSpec:\n\t\treturn 1 << nTypeSpec\n\tcase *ast.TypeSwitchStmt:\n\t\treturn 1 << nTypeSwitchStmt\n\tcase *ast.UnaryExpr:\n\t\treturn 1 << nUnaryExpr\n\tcase *ast.ValueSpec:\n\t\treturn 1 << nValueSpec\n\t}\n\treturn 0\n}\n\nfunc maskOf(nodes []ast.Node) uint64 {\n\tif len(nodes) == 0 {\n\t\treturn math.MaxUint64 // match all node types\n\t}\n\tvar mask uint64\n\tfor _, n := range nodes {\n\t\tmask |= typeOf(n)\n\t}\n\treturn mask\n}\n"
  },
  {
    "path": "go/ast/inspector/walk.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inspector\n\n// This file is a fork of ast.Inspect to reduce unnecessary dynamic\n// calls and to gather edge information.\n//\n// Consistency with the original is ensured by TestInspectAllNodes.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n)\n\nfunc walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) {\n\tfor i, node := range list {\n\t\twalk(v, ek, i, node)\n\t}\n}\n\nfunc walk(v *visitor, ek edge.Kind, index int, node ast.Node) {\n\tv.push(ek, index, node)\n\n\t// walk children\n\t// (the order of the cases matches the order\n\t// of the corresponding node types in ast.go)\n\tswitch n := node.(type) {\n\t// Comments and fields\n\tcase *ast.Comment:\n\t\t// nothing to do\n\n\tcase *ast.CommentGroup:\n\t\twalkList(v, edge.CommentGroup_List, n.List)\n\n\tcase *ast.Field:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.Field_Doc, -1, n.Doc)\n\t\t}\n\t\twalkList(v, edge.Field_Names, n.Names)\n\t\tif n.Type != nil {\n\t\t\twalk(v, edge.Field_Type, -1, n.Type)\n\t\t}\n\t\tif n.Tag != nil {\n\t\t\twalk(v, edge.Field_Tag, -1, n.Tag)\n\t\t}\n\t\tif n.Comment != nil {\n\t\t\twalk(v, edge.Field_Comment, -1, n.Comment)\n\t\t}\n\n\tcase *ast.FieldList:\n\t\twalkList(v, edge.FieldList_List, n.List)\n\n\t// Expressions\n\tcase *ast.BadExpr, *ast.Ident, *ast.BasicLit:\n\t\t// nothing to do\n\n\tcase *ast.Ellipsis:\n\t\tif n.Elt != nil {\n\t\t\twalk(v, edge.Ellipsis_Elt, -1, n.Elt)\n\t\t}\n\n\tcase *ast.FuncLit:\n\t\twalk(v, edge.FuncLit_Type, -1, n.Type)\n\t\twalk(v, edge.FuncLit_Body, -1, n.Body)\n\n\tcase *ast.CompositeLit:\n\t\tif n.Type != nil {\n\t\t\twalk(v, edge.CompositeLit_Type, -1, n.Type)\n\t\t}\n\t\twalkList(v, edge.CompositeLit_Elts, n.Elts)\n\n\tcase *ast.ParenExpr:\n\t\twalk(v, edge.ParenExpr_X, -1, n.X)\n\n\tcase *ast.SelectorExpr:\n\t\twalk(v, edge.SelectorExpr_X, -1, n.X)\n\t\twalk(v, edge.SelectorExpr_Sel, -1, n.Sel)\n\n\tcase *ast.IndexExpr:\n\t\twalk(v, edge.IndexExpr_X, -1, n.X)\n\t\twalk(v, edge.IndexExpr_Index, -1, n.Index)\n\n\tcase *ast.IndexListExpr:\n\t\twalk(v, edge.IndexListExpr_X, -1, n.X)\n\t\twalkList(v, edge.IndexListExpr_Indices, n.Indices)\n\n\tcase *ast.SliceExpr:\n\t\twalk(v, edge.SliceExpr_X, -1, n.X)\n\t\tif n.Low != nil {\n\t\t\twalk(v, edge.SliceExpr_Low, -1, n.Low)\n\t\t}\n\t\tif n.High != nil {\n\t\t\twalk(v, edge.SliceExpr_High, -1, n.High)\n\t\t}\n\t\tif n.Max != nil {\n\t\t\twalk(v, edge.SliceExpr_Max, -1, n.Max)\n\t\t}\n\n\tcase *ast.TypeAssertExpr:\n\t\twalk(v, edge.TypeAssertExpr_X, -1, n.X)\n\t\tif n.Type != nil {\n\t\t\twalk(v, edge.TypeAssertExpr_Type, -1, n.Type)\n\t\t}\n\n\tcase *ast.CallExpr:\n\t\twalk(v, edge.CallExpr_Fun, -1, n.Fun)\n\t\twalkList(v, edge.CallExpr_Args, n.Args)\n\n\tcase *ast.StarExpr:\n\t\twalk(v, edge.StarExpr_X, -1, n.X)\n\n\tcase *ast.UnaryExpr:\n\t\twalk(v, edge.UnaryExpr_X, -1, n.X)\n\n\tcase *ast.BinaryExpr:\n\t\twalk(v, edge.BinaryExpr_X, -1, n.X)\n\t\twalk(v, edge.BinaryExpr_Y, -1, n.Y)\n\n\tcase *ast.KeyValueExpr:\n\t\twalk(v, edge.KeyValueExpr_Key, -1, n.Key)\n\t\twalk(v, edge.KeyValueExpr_Value, -1, n.Value)\n\n\t// Types\n\tcase *ast.ArrayType:\n\t\tif n.Len != nil {\n\t\t\twalk(v, edge.ArrayType_Len, -1, n.Len)\n\t\t}\n\t\twalk(v, edge.ArrayType_Elt, -1, n.Elt)\n\n\tcase *ast.StructType:\n\t\twalk(v, edge.StructType_Fields, -1, n.Fields)\n\n\tcase *ast.FuncType:\n\t\tif n.TypeParams != nil {\n\t\t\twalk(v, edge.FuncType_TypeParams, -1, n.TypeParams)\n\t\t}\n\t\tif n.Params != nil {\n\t\t\twalk(v, edge.FuncType_Params, -1, n.Params)\n\t\t}\n\t\tif n.Results != nil {\n\t\t\twalk(v, edge.FuncType_Results, -1, n.Results)\n\t\t}\n\n\tcase *ast.InterfaceType:\n\t\twalk(v, edge.InterfaceType_Methods, -1, n.Methods)\n\n\tcase *ast.MapType:\n\t\twalk(v, edge.MapType_Key, -1, n.Key)\n\t\twalk(v, edge.MapType_Value, -1, n.Value)\n\n\tcase *ast.ChanType:\n\t\twalk(v, edge.ChanType_Value, -1, n.Value)\n\n\t// Statements\n\tcase *ast.BadStmt:\n\t\t// nothing to do\n\n\tcase *ast.DeclStmt:\n\t\twalk(v, edge.DeclStmt_Decl, -1, n.Decl)\n\n\tcase *ast.EmptyStmt:\n\t\t// nothing to do\n\n\tcase *ast.LabeledStmt:\n\t\twalk(v, edge.LabeledStmt_Label, -1, n.Label)\n\t\twalk(v, edge.LabeledStmt_Stmt, -1, n.Stmt)\n\n\tcase *ast.ExprStmt:\n\t\twalk(v, edge.ExprStmt_X, -1, n.X)\n\n\tcase *ast.SendStmt:\n\t\twalk(v, edge.SendStmt_Chan, -1, n.Chan)\n\t\twalk(v, edge.SendStmt_Value, -1, n.Value)\n\n\tcase *ast.IncDecStmt:\n\t\twalk(v, edge.IncDecStmt_X, -1, n.X)\n\n\tcase *ast.AssignStmt:\n\t\twalkList(v, edge.AssignStmt_Lhs, n.Lhs)\n\t\twalkList(v, edge.AssignStmt_Rhs, n.Rhs)\n\n\tcase *ast.GoStmt:\n\t\twalk(v, edge.GoStmt_Call, -1, n.Call)\n\n\tcase *ast.DeferStmt:\n\t\twalk(v, edge.DeferStmt_Call, -1, n.Call)\n\n\tcase *ast.ReturnStmt:\n\t\twalkList(v, edge.ReturnStmt_Results, n.Results)\n\n\tcase *ast.BranchStmt:\n\t\tif n.Label != nil {\n\t\t\twalk(v, edge.BranchStmt_Label, -1, n.Label)\n\t\t}\n\n\tcase *ast.BlockStmt:\n\t\twalkList(v, edge.BlockStmt_List, n.List)\n\n\tcase *ast.IfStmt:\n\t\tif n.Init != nil {\n\t\t\twalk(v, edge.IfStmt_Init, -1, n.Init)\n\t\t}\n\t\twalk(v, edge.IfStmt_Cond, -1, n.Cond)\n\t\twalk(v, edge.IfStmt_Body, -1, n.Body)\n\t\tif n.Else != nil {\n\t\t\twalk(v, edge.IfStmt_Else, -1, n.Else)\n\t\t}\n\n\tcase *ast.CaseClause:\n\t\twalkList(v, edge.CaseClause_List, n.List)\n\t\twalkList(v, edge.CaseClause_Body, n.Body)\n\n\tcase *ast.SwitchStmt:\n\t\tif n.Init != nil {\n\t\t\twalk(v, edge.SwitchStmt_Init, -1, n.Init)\n\t\t}\n\t\tif n.Tag != nil {\n\t\t\twalk(v, edge.SwitchStmt_Tag, -1, n.Tag)\n\t\t}\n\t\twalk(v, edge.SwitchStmt_Body, -1, n.Body)\n\n\tcase *ast.TypeSwitchStmt:\n\t\tif n.Init != nil {\n\t\t\twalk(v, edge.TypeSwitchStmt_Init, -1, n.Init)\n\t\t}\n\t\twalk(v, edge.TypeSwitchStmt_Assign, -1, n.Assign)\n\t\twalk(v, edge.TypeSwitchStmt_Body, -1, n.Body)\n\n\tcase *ast.CommClause:\n\t\tif n.Comm != nil {\n\t\t\twalk(v, edge.CommClause_Comm, -1, n.Comm)\n\t\t}\n\t\twalkList(v, edge.CommClause_Body, n.Body)\n\n\tcase *ast.SelectStmt:\n\t\twalk(v, edge.SelectStmt_Body, -1, n.Body)\n\n\tcase *ast.ForStmt:\n\t\tif n.Init != nil {\n\t\t\twalk(v, edge.ForStmt_Init, -1, n.Init)\n\t\t}\n\t\tif n.Cond != nil {\n\t\t\twalk(v, edge.ForStmt_Cond, -1, n.Cond)\n\t\t}\n\t\tif n.Post != nil {\n\t\t\twalk(v, edge.ForStmt_Post, -1, n.Post)\n\t\t}\n\t\twalk(v, edge.ForStmt_Body, -1, n.Body)\n\n\tcase *ast.RangeStmt:\n\t\tif n.Key != nil {\n\t\t\twalk(v, edge.RangeStmt_Key, -1, n.Key)\n\t\t}\n\t\tif n.Value != nil {\n\t\t\twalk(v, edge.RangeStmt_Value, -1, n.Value)\n\t\t}\n\t\twalk(v, edge.RangeStmt_X, -1, n.X)\n\t\twalk(v, edge.RangeStmt_Body, -1, n.Body)\n\n\t// Declarations\n\tcase *ast.ImportSpec:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.ImportSpec_Doc, -1, n.Doc)\n\t\t}\n\t\tif n.Name != nil {\n\t\t\twalk(v, edge.ImportSpec_Name, -1, n.Name)\n\t\t}\n\t\twalk(v, edge.ImportSpec_Path, -1, n.Path)\n\t\tif n.Comment != nil {\n\t\t\twalk(v, edge.ImportSpec_Comment, -1, n.Comment)\n\t\t}\n\n\tcase *ast.ValueSpec:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.ValueSpec_Doc, -1, n.Doc)\n\t\t}\n\t\twalkList(v, edge.ValueSpec_Names, n.Names)\n\t\tif n.Type != nil {\n\t\t\twalk(v, edge.ValueSpec_Type, -1, n.Type)\n\t\t}\n\t\twalkList(v, edge.ValueSpec_Values, n.Values)\n\t\tif n.Comment != nil {\n\t\t\twalk(v, edge.ValueSpec_Comment, -1, n.Comment)\n\t\t}\n\n\tcase *ast.TypeSpec:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.TypeSpec_Doc, -1, n.Doc)\n\t\t}\n\t\twalk(v, edge.TypeSpec_Name, -1, n.Name)\n\t\tif n.TypeParams != nil {\n\t\t\twalk(v, edge.TypeSpec_TypeParams, -1, n.TypeParams)\n\t\t}\n\t\twalk(v, edge.TypeSpec_Type, -1, n.Type)\n\t\tif n.Comment != nil {\n\t\t\twalk(v, edge.TypeSpec_Comment, -1, n.Comment)\n\t\t}\n\n\tcase *ast.BadDecl:\n\t\t// nothing to do\n\n\tcase *ast.GenDecl:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.GenDecl_Doc, -1, n.Doc)\n\t\t}\n\t\twalkList(v, edge.GenDecl_Specs, n.Specs)\n\n\tcase *ast.FuncDecl:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.FuncDecl_Doc, -1, n.Doc)\n\t\t}\n\t\tif n.Recv != nil {\n\t\t\twalk(v, edge.FuncDecl_Recv, -1, n.Recv)\n\t\t}\n\t\twalk(v, edge.FuncDecl_Name, -1, n.Name)\n\t\twalk(v, edge.FuncDecl_Type, -1, n.Type)\n\t\tif n.Body != nil {\n\t\t\twalk(v, edge.FuncDecl_Body, -1, n.Body)\n\t\t}\n\n\tcase *ast.File:\n\t\tif n.Doc != nil {\n\t\t\twalk(v, edge.File_Doc, -1, n.Doc)\n\t\t}\n\t\twalk(v, edge.File_Name, -1, n.Name)\n\t\twalkList(v, edge.File_Decls, n.Decls)\n\t\t// don't walk n.Comments - they have been\n\t\t// visited already through the individual\n\t\t// nodes\n\n\tdefault:\n\t\t// (includes *ast.Package)\n\t\tpanic(fmt.Sprintf(\"Walk: unexpected node type %T\", n))\n\t}\n\n\tv.pop(node)\n}\n"
  },
  {
    "path": "go/buildutil/allpackages.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package buildutil provides utilities related to the go/build\n// package in the standard library.\n//\n// All I/O is done via the build.Context file system interface, which must\n// be concurrency-safe.\npackage buildutil // import \"golang.org/x/tools/go/buildutil\"\n\nimport (\n\t\"go/build\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// AllPackages returns the package path of each Go package in any source\n// directory of the specified build context (e.g. $GOROOT or an element\n// of $GOPATH).  Errors are ignored.  The results are sorted.\n// All package paths are canonical, and thus may contain \"/vendor/\".\n//\n// The result may include import paths for directories that contain no\n// *.go files, such as \"archive\" (in $GOROOT/src).\n//\n// All I/O is done via the build.Context file system interface,\n// which must be concurrency-safe.\nfunc AllPackages(ctxt *build.Context) []string {\n\tvar list []string\n\tForEachPackage(ctxt, func(pkg string, _ error) {\n\t\tlist = append(list, pkg)\n\t})\n\tsort.Strings(list)\n\treturn list\n}\n\n// ForEachPackage calls the found function with the package path of\n// each Go package it finds in any source directory of the specified\n// build context (e.g. $GOROOT or an element of $GOPATH).\n// All package paths are canonical, and thus may contain \"/vendor/\".\n//\n// If the package directory exists but could not be read, the second\n// argument to the found function provides the error.\n//\n// All I/O is done via the build.Context file system interface,\n// which must be concurrency-safe.\nfunc ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {\n\tch := make(chan item)\n\n\tvar wg sync.WaitGroup\n\tfor _, root := range ctxt.SrcDirs() {\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\tallPackages(ctxt, root, ch)\n\t\t\twg.Done()\n\t\t}()\n\t}\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(ch)\n\t}()\n\n\t// All calls to found occur in the caller's goroutine.\n\tfor i := range ch {\n\t\tfound(i.importPath, i.err)\n\t}\n}\n\ntype item struct {\n\timportPath string\n\terr        error // (optional)\n}\n\n// We use a process-wide counting semaphore to limit\n// the number of parallel calls to ReadDir.\nvar ioLimit = make(chan bool, 20)\n\nfunc allPackages(ctxt *build.Context, root string, ch chan<- item) {\n\troot = filepath.Clean(root) + string(os.PathSeparator)\n\n\tvar wg sync.WaitGroup\n\n\tvar walkDir func(dir string)\n\twalkDir = func(dir string) {\n\t\t// Avoid .foo, _foo, and testdata directory trees.\n\t\tbase := filepath.Base(dir)\n\t\tif base == \"\" || base[0] == '.' || base[0] == '_' || base == \"testdata\" {\n\t\t\treturn\n\t\t}\n\n\t\tpkg := filepath.ToSlash(strings.TrimPrefix(dir, root))\n\n\t\t// Prune search if we encounter any of these import paths.\n\t\tswitch pkg {\n\t\tcase \"builtin\":\n\t\t\treturn\n\t\t}\n\n\t\tioLimit <- true\n\t\tfiles, err := ReadDir(ctxt, dir)\n\t\t<-ioLimit\n\t\tif pkg != \"\" || err != nil {\n\t\t\tch <- item{pkg, err}\n\t\t}\n\t\tfor _, fi := range files {\n\t\t\tif fi.IsDir() {\n\t\t\t\twg.Add(1)\n\t\t\t\tgo func() {\n\t\t\t\t\twalkDir(filepath.Join(dir, fi.Name()))\n\t\t\t\t\twg.Done()\n\t\t\t\t}()\n\t\t\t}\n\t\t}\n\t}\n\n\twalkDir(root)\n\twg.Wait()\n}\n\n// ExpandPatterns returns the set of packages matched by patterns,\n// which may have the following forms:\n//\n//\tgolang.org/x/tools/cmd/guru     # a single package\n//\tgolang.org/x/tools/...          # all packages beneath dir\n//\t...                             # the entire workspace.\n//\n// Order is significant: a pattern preceded by '-' removes matching\n// packages from the set.  For example, these patterns match all encoding\n// packages except encoding/xml:\n//\n//\tencoding/... -encoding/xml\n//\n// A trailing slash in a pattern is ignored.  (Path components of Go\n// package names are separated by slash, not the platform's path separator.)\nfunc ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool {\n\t// TODO(adonovan): support other features of 'go list':\n\t// - \"std\"/\"cmd\"/\"all\" meta-packages\n\t// - \"...\" not at the end of a pattern\n\t// - relative patterns using \"./\" or \"../\" prefix\n\n\tpkgs := make(map[string]bool)\n\tdoPkg := func(pkg string, neg bool) {\n\t\tif neg {\n\t\t\tdelete(pkgs, pkg)\n\t\t} else {\n\t\t\tpkgs[pkg] = true\n\t\t}\n\t}\n\n\t// Scan entire workspace if wildcards are present.\n\t// TODO(adonovan): opt: scan only the necessary subtrees of the workspace.\n\tvar all []string\n\tfor _, arg := range patterns {\n\t\tif strings.HasSuffix(arg, \"...\") {\n\t\t\tall = AllPackages(ctxt)\n\t\t\tbreak\n\t\t}\n\t}\n\n\tfor _, arg := range patterns {\n\t\tif arg == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tneg := arg[0] == '-'\n\t\tif neg {\n\t\t\targ = arg[1:]\n\t\t}\n\n\t\tif arg == \"...\" {\n\t\t\t// ... matches all packages\n\t\t\tfor _, pkg := range all {\n\t\t\t\tdoPkg(pkg, neg)\n\t\t\t}\n\t\t} else if dir, ok := strings.CutSuffix(arg, \"/...\"); ok {\n\t\t\t// dir/... matches all packages beneath dir\n\t\t\tfor _, pkg := range all {\n\t\t\t\tif strings.HasPrefix(pkg, dir) &&\n\t\t\t\t\t(len(pkg) == len(dir) || pkg[len(dir)] == '/') {\n\t\t\t\t\tdoPkg(pkg, neg)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// single package\n\t\t\tdoPkg(strings.TrimSuffix(arg, \"/\"), neg)\n\t\t}\n\t}\n\n\treturn pkgs\n}\n"
  },
  {
    "path": "go/buildutil/allpackages_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Incomplete source tree on Android.\n\n//go:build !android\n\npackage buildutil_test\n\nimport (\n\t\"go/build\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestAllPackages(t *testing.T) {\n\tif runtime.Compiler == \"gccgo\" {\n\t\tt.Skip(\"gccgo has no standard packages\")\n\t}\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{\n\t\t{Name: \"golang.org/x/tools/go/buildutil\", Files: packagestest.MustCopyFileTree(\".\")}})\n\tdefer exported.Cleanup()\n\n\tvar gopath string\n\tfor _, env := range exported.Config.Env {\n\t\tif !strings.HasPrefix(env, \"GOPATH=\") {\n\t\t\tcontinue\n\t\t}\n\t\tgopath = strings.TrimPrefix(env, \"GOPATH=\")\n\t}\n\tif gopath == \"\" {\n\t\tt.Fatal(\"Failed to fish GOPATH out of env: \", exported.Config.Env)\n\t}\n\n\tvar buildContext = build.Default\n\tbuildContext.GOPATH = gopath\n\tall := buildutil.AllPackages(&buildContext)\n\n\tset := make(map[string]bool)\n\tfor _, pkg := range all {\n\t\tset[pkg] = true\n\t}\n\n\tconst wantAtLeast = 250\n\tif len(all) < wantAtLeast {\n\t\tt.Errorf(\"Found only %d packages, want at least %d\", len(all), wantAtLeast)\n\t}\n\n\tfor _, want := range []string{\"fmt\", \"crypto/sha256\", \"golang.org/x/tools/go/buildutil\"} {\n\t\tif !set[want] {\n\t\t\tt.Errorf(\"Package %q not found; got %s\", want, all)\n\t\t}\n\t}\n}\n\nfunc TestExpandPatterns(t *testing.T) {\n\ttree := make(map[string]map[string]string)\n\tfor _, pkg := range []string{\n\t\t\"encoding\",\n\t\t\"encoding/xml\",\n\t\t\"encoding/hex\",\n\t\t\"encoding/json\",\n\t\t\"fmt\",\n\t} {\n\t\ttree[pkg] = make(map[string]string)\n\t}\n\tctxt := buildutil.FakeContext(tree)\n\n\tfor _, test := range []struct {\n\t\tpatterns string\n\t\twant     string\n\t}{\n\t\t{\"\", \"\"},\n\t\t{\"fmt\", \"fmt\"},\n\t\t{\"nosuchpkg\", \"nosuchpkg\"},\n\t\t{\"nosuchdir/...\", \"\"},\n\t\t{\"...\", \"encoding encoding/hex encoding/json encoding/xml fmt\"},\n\t\t{\"encoding/... -encoding/xml\", \"encoding encoding/hex encoding/json\"},\n\t\t{\"... -encoding/...\", \"fmt\"},\n\t\t{\"encoding\", \"encoding\"},\n\t\t{\"encoding/\", \"encoding\"},\n\t} {\n\t\tvar pkgs []string\n\t\tfor pkg := range buildutil.ExpandPatterns(ctxt, strings.Fields(test.patterns)) {\n\t\t\tpkgs = append(pkgs, pkg)\n\t\t}\n\t\tsort.Strings(pkgs)\n\t\tgot := strings.Join(pkgs, \" \")\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"ExpandPatterns(%s) = %s, want %s\",\n\t\t\t\ttest.patterns, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/buildutil/fakecontext.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil\n\nimport (\n\t\"fmt\"\n\t\"go/build\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n)\n\n// FakeContext returns a build.Context for the fake file tree specified\n// by pkgs, which maps package import paths to a mapping from file base\n// names to contents.\n//\n// The fake Context has a GOROOT of \"/go\" and no GOPATH, and overrides\n// the necessary file access methods to read from memory instead of the\n// real file system.\n//\n// Unlike a real file tree, the fake one has only two levels---packages\n// and files---so ReadDir(\"/go/src/\") returns all packages under\n// /go/src/ including, for instance, \"math\" and \"math/big\".\n// ReadDir(\"/go/src/math/big\") would return all the files in the\n// \"math/big\" package.\nfunc FakeContext(pkgs map[string]map[string]string) *build.Context {\n\tclean := func(filename string) string {\n\t\tf := path.Clean(filepath.ToSlash(filename))\n\t\t// Removing \"/go/src\" while respecting segment\n\t\t// boundaries has this unfortunate corner case:\n\t\tif f == \"/go/src\" {\n\t\t\treturn \"\"\n\t\t}\n\t\treturn strings.TrimPrefix(f, \"/go/src/\")\n\t}\n\n\tctxt := build.Default // copy\n\tctxt.GOROOT = \"/go\"\n\tctxt.GOPATH = \"\"\n\tctxt.Compiler = \"gc\"\n\tctxt.IsDir = func(dir string) bool {\n\t\tdir = clean(dir)\n\t\tif dir == \"\" {\n\t\t\treturn true // needed by (*build.Context).SrcDirs\n\t\t}\n\t\treturn pkgs[dir] != nil\n\t}\n\tctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {\n\t\tdir = clean(dir)\n\t\tvar fis []os.FileInfo\n\t\tif dir == \"\" {\n\t\t\t// enumerate packages\n\t\t\tfor importPath := range pkgs {\n\t\t\t\tfis = append(fis, fakeDirInfo(importPath))\n\t\t\t}\n\t\t} else {\n\t\t\t// enumerate files of package\n\t\t\tfor basename := range pkgs[dir] {\n\t\t\t\tfis = append(fis, fakeFileInfo(basename))\n\t\t\t}\n\t\t}\n\t\tsort.Sort(byName(fis))\n\t\treturn fis, nil\n\t}\n\tctxt.OpenFile = func(filename string) (io.ReadCloser, error) {\n\t\tfilename = clean(filename)\n\t\tdir, base := path.Split(filename)\n\t\tcontent, ok := pkgs[path.Clean(dir)][base]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"file not found: %s\", filename)\n\t\t}\n\t\treturn io.NopCloser(strings.NewReader(content)), nil\n\t}\n\tctxt.IsAbsPath = func(path string) bool {\n\t\tpath = filepath.ToSlash(path)\n\t\t// Don't rely on the default (filepath.Path) since on\n\t\t// Windows, it reports virtual paths as non-absolute.\n\t\treturn strings.HasPrefix(path, \"/\")\n\t}\n\treturn &ctxt\n}\n\ntype byName []os.FileInfo\n\nfunc (s byName) Len() int           { return len(s) }\nfunc (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }\nfunc (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }\n\ntype fakeFileInfo string\n\nfunc (fi fakeFileInfo) Name() string    { return string(fi) }\nfunc (fakeFileInfo) Sys() any           { return nil }\nfunc (fakeFileInfo) ModTime() time.Time { return time.Time{} }\nfunc (fakeFileInfo) IsDir() bool        { return false }\nfunc (fakeFileInfo) Size() int64        { return 0 }\nfunc (fakeFileInfo) Mode() os.FileMode  { return 0644 }\n\ntype fakeDirInfo string\n\nfunc (fd fakeDirInfo) Name() string    { return string(fd) }\nfunc (fakeDirInfo) Sys() any           { return nil }\nfunc (fakeDirInfo) ModTime() time.Time { return time.Time{} }\nfunc (fakeDirInfo) IsDir() bool        { return true }\nfunc (fakeDirInfo) Size() int64        { return 0 }\nfunc (fakeDirInfo) Mode() os.FileMode  { return 0755 }\n"
  },
  {
    "path": "go/buildutil/overlay.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// OverlayContext overlays a build.Context with additional files from\n// a map. Files in the map take precedence over other files.\n//\n// In addition to plain string comparison, two file names are\n// considered equal if their base names match and their directory\n// components point at the same directory on the file system. That is,\n// symbolic links are followed for directories, but not files.\n//\n// A common use case for OverlayContext is to allow editors to pass in\n// a set of unsaved, modified files.\n//\n// Currently, only the Context.OpenFile function will respect the\n// overlay. This may change in the future.\nfunc OverlayContext(orig *build.Context, overlay map[string][]byte) *build.Context {\n\t// TODO(dominikh): Implement IsDir, HasSubdir and ReadDir\n\n\trc := func(data []byte) (io.ReadCloser, error) {\n\t\treturn io.NopCloser(bytes.NewBuffer(data)), nil\n\t}\n\n\tcopy := *orig // make a copy\n\tctxt := &copy\n\tctxt.OpenFile = func(path string) (io.ReadCloser, error) {\n\t\t// Fast path: names match exactly.\n\t\tif content, ok := overlay[path]; ok {\n\t\t\treturn rc(content)\n\t\t}\n\n\t\t// Slow path: check for same file under a different\n\t\t// alias, perhaps due to a symbolic link.\n\t\tfor filename, content := range overlay {\n\t\t\tif sameFile(path, filename) {\n\t\t\t\treturn rc(content)\n\t\t\t}\n\t\t}\n\n\t\treturn OpenFile(orig, path)\n\t}\n\treturn ctxt\n}\n\n// ParseOverlayArchive parses an archive containing Go files and their\n// contents. The result is intended to be used with OverlayContext.\n//\n// # Archive format\n//\n// The archive consists of a series of files. Each file consists of a\n// name, a decimal file size and the file contents, separated by\n// newlines. No newline follows after the file contents.\nfunc ParseOverlayArchive(archive io.Reader) (map[string][]byte, error) {\n\toverlay := make(map[string][]byte)\n\tr := bufio.NewReader(archive)\n\tfor {\n\t\t// Read file name.\n\t\tfilename, err := r.ReadString('\\n')\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak // OK\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"reading archive file name: %v\", err)\n\t\t}\n\t\tfilename = filepath.Clean(strings.TrimSpace(filename))\n\n\t\t// Read file size.\n\t\tsz, err := r.ReadString('\\n')\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading size of archive file %s: %v\", filename, err)\n\t\t}\n\t\tsz = strings.TrimSpace(sz)\n\t\tsize, err := strconv.ParseUint(sz, 10, 32)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parsing size of archive file %s: %v\", filename, err)\n\t\t}\n\n\t\t// Read file content.\n\t\tcontent := make([]byte, size)\n\t\tif _, err := io.ReadFull(r, content); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading archive file %s: %v\", filename, err)\n\t\t}\n\t\toverlay[filename] = content\n\t}\n\n\treturn overlay, nil\n}\n"
  },
  {
    "path": "go/buildutil/overlay_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil_test\n\nimport (\n\t\"go/build\"\n\t\"io\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n)\n\nfunc TestParseOverlayArchive(t *testing.T) {\n\tvar tt = []struct {\n\t\tin     string\n\t\tout    map[string][]byte\n\t\thasErr bool\n\t}{\n\t\t{\n\t\t\t\"a.go\\n5\\n12345\",\n\t\t\tmap[string][]byte{\"a.go\": []byte(\"12345\")},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"a.go\\n5\\n1234\",\n\t\t\tnil,\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"a.go\\n5\\n12345b.go\\n4\\n1234\",\n\t\t\tmap[string][]byte{\"a.go\": []byte(\"12345\"), \"b.go\": []byte(\"1234\")},\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor _, test := range tt {\n\t\tgot, err := buildutil.ParseOverlayArchive(strings.NewReader(test.in))\n\t\tif err == nil && test.hasErr {\n\t\t\tt.Errorf(\"expected error for %q\", test.in)\n\t\t}\n\t\tif err != nil && !test.hasErr {\n\t\t\tt.Errorf(\"unexpected error %v for %q\", err, test.in)\n\t\t}\n\t\tif !reflect.DeepEqual(got, test.out) {\n\t\t\tt.Errorf(\"got %#v, want %#v\", got, test.out)\n\t\t}\n\t}\n}\n\nfunc TestOverlay(t *testing.T) {\n\tctx := &build.Default\n\tov := map[string][]byte{\n\t\t\"/somewhere/a.go\": []byte(\"file contents\"),\n\t}\n\tnames := []string{\"/somewhere/a.go\", \"/somewhere//a.go\"}\n\tctx = buildutil.OverlayContext(ctx, ov)\n\tfor _, name := range names {\n\t\tf, err := buildutil.OpenFile(ctx, name)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"unexpected error %v\", err)\n\t\t}\n\t\tb, err := io.ReadAll(f)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"unexpected error %v\", err)\n\t\t}\n\t\tif got, expected := string(b), string(ov[\"/somewhere/a.go\"]); got != expected {\n\t\t\tt.Errorf(\"read %q, expected %q\", got, expected)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/buildutil/tags.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil\n\n// This duplicated logic must be kept in sync with that from go build:\n//   $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)\n//   $GOROOT/src/cmd/go/internal/base/flag.go (StringsFlag.Set)\n//   $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nconst TagsFlagDoc = \"a list of `build tags` to consider satisfied during the build. \" +\n\t\"For more information about build tags, see the description of \" +\n\t\"build constraints in the documentation for the go/build package\"\n\n// TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses\n// a flag value the same as go build's -tags flag and populates a []string slice.\n//\n// See $GOROOT/src/go/build/doc.go for description of build tags.\n// See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.\n//\n// Example:\n//\n//\tflag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), \"tags\", buildutil.TagsFlagDoc)\ntype TagsFlag []string\n\nfunc (v *TagsFlag) Set(s string) error {\n\t// See $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)\n\t// For compatibility with Go 1.12 and earlier, allow \"-tags='a b c'\" or even just \"-tags='a'\".\n\tif strings.Contains(s, \" \") || strings.Contains(s, \"'\") {\n\t\tvar err error\n\t\t*v, err = splitQuotedFields(s)\n\t\tif *v == nil {\n\t\t\t*v = []string{}\n\t\t}\n\t\treturn err\n\t}\n\n\t// Starting in Go 1.13, the -tags flag is a comma-separated list of build tags.\n\t*v = []string{}\n\tfor s := range strings.SplitSeq(s, \",\") {\n\t\tif s != \"\" {\n\t\t\t*v = append(*v, s)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (v *TagsFlag) Get() any { return *v }\n\nfunc splitQuotedFields(s string) ([]string, error) {\n\t// See $GOROOT/src/cmd/internal/quoted/quoted.go (Split)\n\t// This must remain in sync with that logic.\n\tvar f []string\n\tfor len(s) > 0 {\n\t\tfor len(s) > 0 && isSpaceByte(s[0]) {\n\t\t\ts = s[1:]\n\t\t}\n\t\tif len(s) == 0 {\n\t\t\tbreak\n\t\t}\n\t\t// Accepted quoted string. No unescaping inside.\n\t\tif s[0] == '\"' || s[0] == '\\'' {\n\t\t\tquote := s[0]\n\t\t\ts = s[1:]\n\t\t\ti := 0\n\t\t\tfor i < len(s) && s[i] != quote {\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i >= len(s) {\n\t\t\t\treturn nil, fmt.Errorf(\"unterminated %c string\", quote)\n\t\t\t}\n\t\t\tf = append(f, s[:i])\n\t\t\ts = s[i+1:]\n\t\t\tcontinue\n\t\t}\n\t\ti := 0\n\t\tfor i < len(s) && !isSpaceByte(s[i]) {\n\t\t\ti++\n\t\t}\n\t\tf = append(f, s[:i])\n\t\ts = s[i:]\n\t}\n\treturn f, nil\n}\n\nfunc (v *TagsFlag) String() string {\n\treturn \"<tagsFlag>\"\n}\n\nfunc isSpaceByte(c byte) bool {\n\t// See $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)\n\t// This list must remain in sync with that.\n\treturn c == ' ' || c == '\\t' || c == '\\n' || c == '\\r'\n}\n"
  },
  {
    "path": "go/buildutil/tags_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil_test\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"go/build\"\n\t\"os/exec\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestTags(t *testing.T) {\n\n\ttype tagTestCase struct {\n\t\ttags    string\n\t\twant    []string\n\t\twantErr bool\n\t}\n\n\tfor name, tc := range map[string]tagTestCase{\n\t\t// Normal valid cases\n\t\t\"empty\": {\n\t\t\ttags: \"\",\n\t\t\twant: []string{},\n\t\t},\n\t\t\"commas\": {\n\t\t\ttags: \"tag1,tag_2,🐹,tag/3,tag-4\",\n\t\t\twant: []string{\"tag1\", \"tag_2\", \"🐹\", \"tag/3\", \"tag-4\"},\n\t\t},\n\t\t\"delimiters are spaces\": {\n\t\t\ttags: \"a b\\tc\\rd\\ne\",\n\t\t\twant: []string{\"a\", \"b\", \"c\", \"d\", \"e\"},\n\t\t},\n\t\t\"old quote and space form\": {\n\t\t\ttags: \"'a' 'b' 'c'\",\n\t\t\twant: []string{\"a\", \"b\", \"c\"},\n\t\t},\n\n\t\t// Normal error cases\n\t\t\"unterminated\": {\n\t\t\ttags:    `\"missing closing quote`,\n\t\t\twant:    []string{},\n\t\t\twantErr: true,\n\t\t},\n\t\t\"unterminated single\": {\n\t\t\ttags:    `'missing closing quote`,\n\t\t\twant:    []string{},\n\t\t\twantErr: true,\n\t\t},\n\n\t\t// Maybe surprising difference for unterminated quotes, no spaces\n\t\t\"unterminated no spaces\": {\n\t\t\ttags: `\"missing_closing_quote`,\n\t\t\twant: []string{\"\\\"missing_closing_quote\"},\n\t\t},\n\t\t\"unterminated no spaces single\": {\n\t\t\ttags:    `'missing_closing_quote`,\n\t\t\twant:    []string{},\n\t\t\twantErr: true,\n\t\t},\n\n\t\t// Permitted but not recommended\n\t\t\"delimiters contiguous spaces\": {\n\t\t\ttags: \"a \\t\\r\\n, b \\t\\r\\nc,d\\te\\tf\",\n\t\t\twant: []string{\"a\", \",\", \"b\", \"c,d\", \"e\", \"f\"},\n\t\t},\n\t\t\"quotes and spaces\": {\n\t\t\ttags: ` 'one'\"two\"\t'three \"four\"'`,\n\t\t\twant: []string{\"one\", \"two\", \"three \\\"four\\\"\"},\n\t\t},\n\t\t\"quotes single no spaces\": {\n\t\t\ttags: `'t1','t2',\"t3\"`,\n\t\t\twant: []string{\"t1\", \",'t2',\\\"t3\\\"\"},\n\t\t},\n\t\t\"quotes double no spaces\": {\n\t\t\ttags: `\"t1\",\"t2\",\"t3\"`,\n\t\t\twant: []string{`\"t1\"`, `\"t2\"`, `\"t3\"`},\n\t\t},\n\t} {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tf := flag.NewFlagSet(\"TestTags\", flag.ContinueOnError)\n\t\t\tvar ctxt build.Context\n\t\t\tf.Var((*buildutil.TagsFlag)(&ctxt.BuildTags), \"tags\", buildutil.TagsFlagDoc)\n\n\t\t\t// Normal case valid parsed tags\n\t\t\tf.Parse([]string{\"-tags\", tc.tags, \"rest\"})\n\n\t\t\t// BuildTags\n\t\t\tif !reflect.DeepEqual(ctxt.BuildTags, tc.want) {\n\t\t\t\tt.Errorf(\"Case = %s, BuildTags = %q, want %q\", name, ctxt.BuildTags, tc.want)\n\t\t\t}\n\n\t\t\t// Args()\n\t\t\tif want := []string{\"rest\"}; !reflect.DeepEqual(f.Args(), want) {\n\t\t\t\tt.Errorf(\"Case = %s, f.Args() = %q, want %q\", name, f.Args(), want)\n\t\t\t}\n\n\t\t\t// Regression check against base go tooling\n\t\t\tcmd := testenv.Command(t, \"go\", \"list\", \"-f\", \"{{context.BuildTags}}\", \"-tags\", tc.tags, \".\")\n\t\t\tvar out bytes.Buffer\n\t\t\tcmd.Stdout = &out\n\t\t\tif err := cmd.Run(); err != nil {\n\t\t\t\tif ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {\n\t\t\t\t\tt.Logf(\"stderr:\\n%s\", ee.Stderr)\n\t\t\t\t}\n\t\t\t\tif !tc.wantErr {\n\t\t\t\t\tt.Errorf(\"%v: %v\", cmd, err)\n\t\t\t\t}\n\t\t\t} else if tc.wantErr {\n\t\t\t\tt.Errorf(\"Expected failure for %v\", cmd)\n\t\t\t} else {\n\t\t\t\twantDescription := strings.Join(tc.want, \" \")\n\t\t\t\toutput := strings.Trim(strings.TrimSuffix(out.String(), \"\\n\"), \"[]\")\n\t\t\t\tif output != wantDescription {\n\t\t\t\t\tt.Errorf(\"Output = %s, want %s\", output, wantDescription)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/buildutil/util.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// ParseFile behaves like parser.ParseFile,\n// but uses the build context's file system interface, if any.\n//\n// If file is not absolute (as defined by IsAbsPath), the (dir, file)\n// components are joined using JoinPath; dir must be absolute.\n//\n// The displayPath function, if provided, is used to transform the\n// filename that will be attached to the ASTs.\n//\n// TODO(adonovan): call this from go/loader.parseFiles when the tree thaws.\nfunc ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) {\n\tif !IsAbsPath(ctxt, file) {\n\t\tfile = JoinPath(ctxt, dir, file)\n\t}\n\trd, err := OpenFile(ctxt, file)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer rd.Close() // ignore error\n\tif displayPath != nil {\n\t\tfile = displayPath(file)\n\t}\n\treturn parser.ParseFile(fset, file, rd, mode)\n}\n\n// ContainingPackage returns the package containing filename.\n//\n// If filename is not absolute, it is interpreted relative to working directory dir.\n// All I/O is via the build context's file system interface, if any.\n//\n// The '...Files []string' fields of the resulting build.Package are not\n// populated (build.FindOnly mode).\nfunc ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) {\n\tif !IsAbsPath(ctxt, filename) {\n\t\tfilename = JoinPath(ctxt, dir, filename)\n\t}\n\n\t// We must not assume the file tree uses\n\t// \"/\" always,\n\t// `\\` always,\n\t// or os.PathSeparator (which varies by platform),\n\t// but to make any progress, we are forced to assume that\n\t// paths will not use `\\` unless the PathSeparator\n\t// is also `\\`, thus we can rely on filepath.ToSlash for some sanity.\n\n\tdirSlash := path.Dir(filepath.ToSlash(filename)) + \"/\"\n\n\t// We assume that no source root (GOPATH[i] or GOROOT) contains any other.\n\tfor _, srcdir := range ctxt.SrcDirs() {\n\t\tsrcdirSlash := filepath.ToSlash(srcdir) + \"/\"\n\t\tif importPath, ok := HasSubdir(ctxt, srcdirSlash, dirSlash); ok {\n\t\t\treturn ctxt.Import(importPath, dir, build.FindOnly)\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"can't find package containing %s\", filename)\n}\n\n// -- Effective methods of file system interface -------------------------\n\n// (go/build.Context defines these as methods, but does not export them.)\n\n// HasSubdir calls ctxt.HasSubdir (if not nil) or else uses\n// the local file system to answer the question.\nfunc HasSubdir(ctxt *build.Context, root, dir string) (rel string, ok bool) {\n\tif f := ctxt.HasSubdir; f != nil {\n\t\treturn f(root, dir)\n\t}\n\n\t// Try using paths we received.\n\tif rel, ok = hasSubdir(root, dir); ok {\n\t\treturn\n\t}\n\n\t// Try expanding symlinks and comparing\n\t// expanded against unexpanded and\n\t// expanded against expanded.\n\trootSym, _ := filepath.EvalSymlinks(root)\n\tdirSym, _ := filepath.EvalSymlinks(dir)\n\n\tif rel, ok = hasSubdir(rootSym, dir); ok {\n\t\treturn\n\t}\n\tif rel, ok = hasSubdir(root, dirSym); ok {\n\t\treturn\n\t}\n\treturn hasSubdir(rootSym, dirSym)\n}\n\nfunc hasSubdir(root, dir string) (rel string, ok bool) {\n\tconst sep = string(filepath.Separator)\n\troot = filepath.Clean(root)\n\tif !strings.HasSuffix(root, sep) {\n\t\troot += sep\n\t}\n\n\tdir = filepath.Clean(dir)\n\tif !strings.HasPrefix(dir, root) {\n\t\treturn \"\", false\n\t}\n\n\treturn filepath.ToSlash(dir[len(root):]), true\n}\n\n// FileExists returns true if the specified file exists,\n// using the build context's file system interface.\nfunc FileExists(ctxt *build.Context, path string) bool {\n\tif ctxt.OpenFile != nil {\n\t\tr, err := ctxt.OpenFile(path)\n\t\tif err != nil {\n\t\t\treturn false\n\t\t}\n\t\tr.Close() // ignore error\n\t\treturn true\n\t}\n\t_, err := os.Stat(path)\n\treturn err == nil\n}\n\n// OpenFile behaves like os.Open,\n// but uses the build context's file system interface, if any.\nfunc OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {\n\tif ctxt.OpenFile != nil {\n\t\treturn ctxt.OpenFile(path)\n\t}\n\treturn os.Open(path)\n}\n\n// IsAbsPath behaves like filepath.IsAbs,\n// but uses the build context's file system interface, if any.\nfunc IsAbsPath(ctxt *build.Context, path string) bool {\n\tif ctxt.IsAbsPath != nil {\n\t\treturn ctxt.IsAbsPath(path)\n\t}\n\treturn filepath.IsAbs(path)\n}\n\n// JoinPath behaves like filepath.Join,\n// but uses the build context's file system interface, if any.\nfunc JoinPath(ctxt *build.Context, path ...string) string {\n\tif ctxt.JoinPath != nil {\n\t\treturn ctxt.JoinPath(path...)\n\t}\n\treturn filepath.Join(path...)\n}\n\n// IsDir behaves like os.Stat plus IsDir,\n// but uses the build context's file system interface, if any.\nfunc IsDir(ctxt *build.Context, path string) bool {\n\tif ctxt.IsDir != nil {\n\t\treturn ctxt.IsDir(path)\n\t}\n\tfi, err := os.Stat(path)\n\treturn err == nil && fi.IsDir()\n}\n\n// ReadDir behaves like ioutil.ReadDir,\n// but uses the build context's file system interface, if any.\nfunc ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) {\n\tif ctxt.ReadDir != nil {\n\t\treturn ctxt.ReadDir(path)\n\t}\n\treturn ioutil.ReadDir(path)\n}\n\n// SplitPathList behaves like filepath.SplitList,\n// but uses the build context's file system interface, if any.\nfunc SplitPathList(ctxt *build.Context, s string) []string {\n\tif ctxt.SplitPathList != nil {\n\t\treturn ctxt.SplitPathList(s)\n\t}\n\treturn filepath.SplitList(s)\n}\n\n// sameFile returns true if x and y have the same basename and denote\n// the same file.\nfunc sameFile(x, y string) bool {\n\tif path.Clean(x) == path.Clean(y) {\n\t\treturn true\n\t}\n\tif filepath.Base(x) == filepath.Base(y) { // (optimisation)\n\t\tif xi, err := os.Stat(x); err == nil {\n\t\t\tif yi, err := os.Stat(y); err == nil {\n\t\t\t\treturn os.SameFile(xi, yi)\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "go/buildutil/util_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil_test\n\nimport (\n\t\"go/build\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestContainingPackage(t *testing.T) {\n\tif runtime.Compiler == \"gccgo\" {\n\t\tt.Skip(\"gccgo has no GOROOT\")\n\t}\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{\n\t\t{Name: \"golang.org/x/tools/go/buildutil\", Files: packagestest.MustCopyFileTree(\".\")}})\n\tdefer exported.Cleanup()\n\n\tgoroot := runtime.GOROOT()\n\tvar gopath string\n\tfor _, env := range exported.Config.Env {\n\t\tif !strings.HasPrefix(env, \"GOPATH=\") {\n\t\t\tcontinue\n\t\t}\n\t\tgopath = strings.TrimPrefix(env, \"GOPATH=\")\n\t}\n\tif gopath == \"\" {\n\t\tt.Fatal(\"Failed to fish GOPATH out of env: \", exported.Config.Env)\n\t}\n\tbuildutildir := filepath.Join(gopath, \"golang.org\", \"x\", \"tools\", \"go\", \"buildutil\")\n\n\ttype Test struct {\n\t\tgopath, filename, wantPkg string\n\t}\n\n\ttests := []Test{\n\t\t{gopath, goroot + \"/src/fmt/print.go\", \"fmt\"},\n\t\t{gopath, goroot + \"/src/encoding/json/foo.go\", \"encoding/json\"},\n\t\t{gopath, goroot + \"/src/encoding/missing/foo.go\", \"(not found)\"},\n\t\t{gopath, gopath + \"/src/golang.org/x/tools/go/buildutil/util_test.go\",\n\t\t\t\"golang.org/x/tools/go/buildutil\"},\n\t}\n\n\tif runtime.GOOS != \"windows\" && runtime.GOOS != \"plan9\" {\n\t\t// Make a symlink to gopath for test\n\t\ttmp, err := os.MkdirTemp(os.TempDir(), \"go\")\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unable to create a temporary directory in %s\", os.TempDir())\n\t\t}\n\n\t\tdefer os.RemoveAll(tmp)\n\n\t\t// symlink between $GOPATH/src and /tmp/go/src\n\t\t// in order to test all possible symlink cases\n\t\tif err := os.Symlink(gopath+\"/src\", tmp+\"/src\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\ttests = append(tests, []Test{\n\t\t\t{gopath, tmp + \"/src/golang.org/x/tools/go/buildutil/util_test.go\", \"golang.org/x/tools/go/buildutil\"},\n\t\t\t{tmp, gopath + \"/src/golang.org/x/tools/go/buildutil/util_test.go\", \"golang.org/x/tools/go/buildutil\"},\n\t\t\t{tmp, tmp + \"/src/golang.org/x/tools/go/buildutil/util_test.go\", \"golang.org/x/tools/go/buildutil\"},\n\t\t}...)\n\t}\n\n\tfor _, test := range tests {\n\t\tvar got string\n\t\tvar buildContext = build.Default\n\t\tbuildContext.GOPATH = test.gopath\n\t\tbp, err := buildutil.ContainingPackage(&buildContext, buildutildir, test.filename)\n\t\tif err != nil {\n\t\t\tgot = \"(not found)\"\n\t\t} else {\n\t\t\tgot = bp.ImportPath\n\t\t}\n\t\tif got != test.wantPkg {\n\t\t\tt.Errorf(\"ContainingPackage(%q) = %s, want %s\", test.filename, got, test.wantPkg)\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "go/buildutil/util_windows_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buildutil_test\n\nimport (\n\t\"fmt\"\n\t\"go/build\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n)\n\nfunc testContainingPackageCaseFold(file, want string) error {\n\tbp, err := buildutil.ContainingPackage(&build.Default, \".\", file)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif got := bp.ImportPath; got != want {\n\t\treturn fmt.Errorf(\"ContainingPackage(%q) = %s, want %s\", file, got, want)\n\t}\n\treturn nil\n}\n\nfunc TestContainingPackageCaseFold(t *testing.T) {\n\tpath := filepath.Join(runtime.GOROOT(), `src\\fmt\\print.go`)\n\terr := testContainingPackageCaseFold(path, \"fmt\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\tvol := filepath.VolumeName(path)\n\tif len(vol) != 2 || vol[1] != ':' {\n\t\tt.Fatalf(\"GOROOT path has unexpected volume name: %v\", vol)\n\t}\n\trest := path[len(vol):]\n\terr = testContainingPackageCaseFold(strings.ToUpper(vol)+rest, \"fmt\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\terr = testContainingPackageCaseFold(strings.ToLower(vol)+rest, \"fmt\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/callgraph.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage callgraph defines the call graph and various algorithms\nand utilities to operate on it.\n\nA call graph is a labelled directed graph whose nodes represent\nfunctions and whose edge labels represent syntactic function call\nsites.  The presence of a labelled edge (caller, site, callee)\nindicates that caller may call callee at the specified call site.\n\nA call graph is a multigraph: it may contain multiple edges (caller,\n*, callee) connecting the same pair of nodes, so long as the edges\ndiffer by label; this occurs when one function calls another function\nfrom multiple call sites.  Also, it may contain multiple edges\n(caller, site, *) that differ only by callee; this indicates a\npolymorphic call.\n\nA SOUND call graph is one that overapproximates the dynamic calling\nbehaviors of the program in all possible executions.  One call graph\nis more PRECISE than another if it is a smaller overapproximation of\nthe dynamic behavior.\n\nAll call graphs have a synthetic root node which is responsible for\ncalling main() and init().\n\nCalls to built-in functions (e.g. panic, println) are not represented\nin the call graph; they are treated like built-in operators of the\nlanguage.\n*/\npackage callgraph // import \"golang.org/x/tools/go/callgraph\"\n\n// TODO(zpavlinovic): decide how callgraphs handle calls to and from generic function bodies.\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// A Graph represents a call graph.\n//\n// A graph may contain nodes that are not reachable from the root.\n// If the call graph is sound, such nodes indicate unreachable\n// functions.\ntype Graph struct {\n\tRoot  *Node                   // the distinguished root node (Root.Func may be nil)\n\tNodes map[*ssa.Function]*Node // all nodes by function\n}\n\n// New returns a new Graph with the specified (optional) root node.\nfunc New(root *ssa.Function) *Graph {\n\tg := &Graph{Nodes: make(map[*ssa.Function]*Node)}\n\tg.Root = g.CreateNode(root)\n\treturn g\n}\n\n// CreateNode returns the Node for fn, creating it if not present.\n// The root node may have fn=nil.\nfunc (g *Graph) CreateNode(fn *ssa.Function) *Node {\n\tn, ok := g.Nodes[fn]\n\tif !ok {\n\t\tn = &Node{Func: fn, ID: len(g.Nodes)}\n\t\tg.Nodes[fn] = n\n\t}\n\treturn n\n}\n\n// A Node represents a node in a call graph.\ntype Node struct {\n\tFunc *ssa.Function // the function this node represents\n\tID   int           // 0-based sequence number\n\tIn   []*Edge       // unordered set of incoming call edges (n.In[*].Callee == n)\n\tOut  []*Edge       // unordered set of outgoing call edges (n.Out[*].Caller == n)\n}\n\nfunc (n *Node) String() string {\n\treturn fmt.Sprintf(\"n%d:%s\", n.ID, n.Func)\n}\n\n// A Edge represents an edge in the call graph.\n//\n// Site is nil for edges originating in synthetic or intrinsic\n// functions, e.g. reflect.Value.Call or the root of the call graph.\ntype Edge struct {\n\tCaller *Node\n\tSite   ssa.CallInstruction\n\tCallee *Node\n}\n\nfunc (e Edge) String() string {\n\treturn fmt.Sprintf(\"%s --> %s\", e.Caller, e.Callee)\n}\n\nfunc (e Edge) Description() string {\n\tvar prefix string\n\tswitch e.Site.(type) {\n\tcase nil:\n\t\treturn \"synthetic call\"\n\tcase *ssa.Go:\n\t\tprefix = \"concurrent \"\n\tcase *ssa.Defer:\n\t\tprefix = \"deferred \"\n\t}\n\treturn prefix + e.Site.Common().Description()\n}\n\nfunc (e Edge) Pos() token.Pos {\n\tif e.Site == nil {\n\t\treturn token.NoPos\n\t}\n\treturn e.Site.Pos()\n}\n\n// AddEdge adds the edge (caller, site, callee) to the call graph.\n// Elimination of duplicate edges is the caller's responsibility.\nfunc AddEdge(caller *Node, site ssa.CallInstruction, callee *Node) {\n\te := &Edge{caller, site, callee}\n\tcallee.In = append(callee.In, e)\n\tcaller.Out = append(caller.Out, e)\n}\n"
  },
  {
    "path": "go/callgraph/callgraph_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage callgraph_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/cha\"\n\t\"golang.org/x/tools/go/callgraph/rta\"\n\t\"golang.org/x/tools/go/callgraph/static\"\n\t\"golang.org/x/tools/go/callgraph/vta\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// Benchmarks comparing different callgraph algorithms implemented in\n// x/tools/go/callgraph. Comparison is on both speed, memory and precision.\n// Fewer edges and fewer reachable nodes implies a more precise result.\n// Comparison is done on a hello world http server using net/http.\n//\n// Current results were on an i7 macbook on go version devel go1.20-2730.\n// Number of nodes, edges, and reachable function are expected to vary between\n// go versions. Timing results are expected to vary between machines.\n// BenchmarkStatic-12\t 53 ms/op     6 MB/op\t12113 nodes\t 37355 edges\t1522 reachable\n// BenchmarkCHA-12    \t 86 ms/op\t 16 MB/op\t12113 nodes\t131717 edges\t7640 reachable\n// BenchmarkRTA-12\t\t110 ms/op\t 12 MB/op\t 6566 nodes\t 42291 edges\t5099 reachable\n// BenchmarkPTA-12\t   1427 ms/op\t600 MB/op\t 8714 nodes\t 28244 edges\t4184 reachable\n// BenchmarkVTA-12\t\t600 ms/op\t 78 MB/op\t12114 nodes\t 44861 edges\t4919 reachable\n// BenchmarkVTA2-12\t\t793 ms/op\t104 MB/op\t 5450 nodes\t 22208 edges\t4042 reachable\n// BenchmarkVTA3-12\t\t977 ms/op\t124 MB/op\t 4621 nodes\t 19331 edges\t3700 reachable\n// BenchmarkVTAAlt-12\t372 ms/op\t 57 MB/op\t 7763 nodes\t 29912 edges\t4258 reachable\n// BenchmarkVTAAlt2-12\t570 ms/op\t 78 MB/op\t 4838 nodes\t 20169 edges\t3737 reachable\n//\n// Note:\n// * Static is unsound and may miss real edges.\n// * RTA starts from a main function and only includes reachable functions.\n// * CHA starts from all functions.\n// * VTA, VTA2, and VTA3 are starting from all functions and the CHA callgraph.\n//   VTA2 and VTA3 are the result of re-applying VTA to the functions reachable\n//   from main() via the callgraph of the previous stage.\n// * VTAAlt, and VTAAlt2 start from the functions reachable from main via the\n//   CHA callgraph.\n// * All algorithms are unsound w.r.t. reflection.\n\nconst httpEx = `\n-- go.mod --\nmodule x.io\n\n-- main.go --\npackage main\n\nimport (\n    \"fmt\"\n    \"net/http\"\n)\n\nfunc hello(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"hello world\\n\")\n}\n\nfunc main() {\n    http.HandleFunc(\"/hello\", hello)\n    http.ListenAndServe(\":8090\", nil)\n}\n`\n\nvar (\n\tonce sync.Once\n\tmain *ssa.Function\n)\n\nfunc example(t testing.TB) (*ssa.Program, *ssa.Function) {\n\tonce.Do(func() {\n\t\tpkgs := testfiles.LoadPackages(t, txtar.Parse([]byte(httpEx)), \".\")\n\t\tprog, ssapkgs := ssautil.Packages(pkgs, ssa.InstantiateGenerics)\n\t\tprog.Build()\n\t\tmain = ssapkgs[0].Members[\"main\"].(*ssa.Function)\n\t})\n\treturn main.Prog, main\n}\n\nvar stats bool = false // print stats?\n\nfunc logStats(b *testing.B, cnd bool, name string, cg *callgraph.Graph, main *ssa.Function) {\n\tif cnd && stats {\n\t\te := 0\n\t\tfor _, n := range cg.Nodes {\n\t\t\te += len(n.Out)\n\t\t}\n\t\tr := len(reaches(main, cg, false))\n\t\tb.Logf(\"%s:\\t%d nodes\\t%d edges\\t%d reachable\", name, len(cg.Nodes), e, r)\n\t}\n}\n\nfunc BenchmarkStatic(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tcg := static.CallGraph(prog)\n\t\tlogStats(b, i == 0, \"static\", cg, main)\n\t}\n}\n\nfunc BenchmarkCHA(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tcg := cha.CallGraph(prog)\n\t\tlogStats(b, i == 0, \"cha\", cg, main)\n\t}\n}\n\nfunc BenchmarkRTA(b *testing.B) {\n\n\t_, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tres := rta.Analyze([]*ssa.Function{main}, true)\n\t\tcg := res.CallGraph\n\t\tlogStats(b, i == 0, \"rta\", cg, main)\n\t}\n}\n\nfunc BenchmarkVTA(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tcg := vta.CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))\n\t\tlogStats(b, i == 0, \"vta\", cg, main)\n\t}\n}\n\nfunc BenchmarkVTA2(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tvta1 := vta.CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))\n\t\tcg := vta.CallGraph(reaches(main, vta1, true), vta1)\n\t\tlogStats(b, i == 0, \"vta2\", cg, main)\n\t}\n}\n\nfunc BenchmarkVTA3(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tvta1 := vta.CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))\n\t\tvta2 := vta.CallGraph(reaches(main, vta1, true), vta1)\n\t\tcg := vta.CallGraph(reaches(main, vta2, true), vta2)\n\t\tlogStats(b, i == 0, \"vta3\", cg, main)\n\t}\n}\n\nfunc BenchmarkVTAAlt(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tcha := cha.CallGraph(prog)\n\t\tcg := vta.CallGraph(reaches(main, cha, true), cha) // start from only functions reachable by CHA.\n\t\tlogStats(b, i == 0, \"vta-alt\", cg, main)\n\t}\n}\n\nfunc BenchmarkVTAAlt2(b *testing.B) {\n\n\tprog, main := example(b)\n\n\tfor i := 0; b.Loop(); i++ {\n\t\tcha := cha.CallGraph(prog)\n\t\tvta1 := vta.CallGraph(reaches(main, cha, true), cha)\n\t\tcg := vta.CallGraph(reaches(main, vta1, true), vta1)\n\t\tlogStats(b, i == 0, \"vta-alt2\", cg, main)\n\t}\n}\n\n// reaches computes the transitive closure of functions forward reachable\n// via calls in cg starting from `sources`. If refs is true, include\n// functions referred to in an instruction.\nfunc reaches(source *ssa.Function, cg *callgraph.Graph, refs bool) map[*ssa.Function]bool {\n\tseen := make(map[*ssa.Function]bool)\n\tvar visit func(f *ssa.Function)\n\tvisit = func(f *ssa.Function) {\n\t\tif seen[f] {\n\t\t\treturn\n\t\t}\n\t\tseen[f] = true\n\n\t\tif n := cg.Nodes[f]; n != nil {\n\t\t\tfor _, e := range n.Out {\n\t\t\t\tif e.Site != nil {\n\t\t\t\t\tvisit(e.Callee.Func)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif refs {\n\t\t\tvar buf [10]*ssa.Value // avoid alloc in common case\n\t\t\tfor _, b := range f.Blocks {\n\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\tfor _, op := range instr.Operands(buf[:0]) {\n\t\t\t\t\t\tif fn, ok := (*op).(*ssa.Function); ok {\n\t\t\t\t\t\t\tvisit(fn)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvisit(source)\n\treturn seen\n}\n"
  },
  {
    "path": "go/callgraph/cha/cha.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cha computes the call graph of a Go program using the Class\n// Hierarchy Analysis (CHA) algorithm.\n//\n// CHA was first described in \"Optimization of Object-Oriented Programs\n// Using Static Class Hierarchy Analysis\", Jeffrey Dean, David Grove,\n// and Craig Chambers, ECOOP'95.\n//\n// CHA is related to RTA (see go/callgraph/rta); the difference is that\n// CHA conservatively computes the entire \"implements\" relation between\n// interfaces and concrete types ahead of time, whereas RTA uses dynamic\n// programming to construct it on the fly as it encounters new functions\n// reachable from main.  CHA may thus include spurious call edges for\n// types that haven't been instantiated yet, or types that are never\n// instantiated.\n//\n// Since CHA conservatively assumes that all functions are address-taken\n// and all concrete types are put into interfaces, it is sound to run on\n// partial programs, such as libraries without a main or test function.\npackage cha // import \"golang.org/x/tools/go/callgraph/cha\"\n\n// TODO(zpavlinovic): update CHA for how it handles generic function bodies.\n\nimport (\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/internal/chautil\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\n// CallGraph computes the call graph of the specified program using the\n// Class Hierarchy Analysis algorithm.\nfunc CallGraph(prog *ssa.Program) *callgraph.Graph {\n\tcg := callgraph.New(nil) // TODO(adonovan) eliminate concept of rooted callgraph\n\n\tallFuncs := ssautil.AllFunctions(prog)\n\n\tcalleesOf := lazyCallees(allFuncs)\n\n\taddEdge := func(fnode *callgraph.Node, site ssa.CallInstruction, g *ssa.Function) {\n\t\tgnode := cg.CreateNode(g)\n\t\tcallgraph.AddEdge(fnode, site, gnode)\n\t}\n\n\taddEdges := func(fnode *callgraph.Node, site ssa.CallInstruction, callees []*ssa.Function) {\n\t\t// Because every call to a highly polymorphic and\n\t\t// frequently used abstract method such as\n\t\t// (io.Writer).Write is assumed to call every concrete\n\t\t// Write method in the program, the call graph can\n\t\t// contain a lot of duplication.\n\t\tfor _, g := range callees {\n\t\t\taddEdge(fnode, site, g)\n\t\t}\n\t}\n\n\tfor f := range allFuncs {\n\t\tfnode := cg.CreateNode(f)\n\t\tfor _, b := range f.Blocks {\n\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\tif site, ok := instr.(ssa.CallInstruction); ok {\n\t\t\t\t\tif g := site.Common().StaticCallee(); g != nil {\n\t\t\t\t\t\taddEdge(fnode, site, g)\n\t\t\t\t\t} else {\n\t\t\t\t\t\taddEdges(fnode, site, calleesOf(site))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cg\n}\n\nvar lazyCallees = chautil.LazyCallees\n"
  },
  {
    "path": "go/callgraph/cha/cha_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage cha_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/cha\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nvar inputs = []string{\n\t\"testdata/func.go\",\n\t\"testdata/iface.go\",\n\t\"testdata/recv.go\",\n\t\"testdata/issue23925.go\",\n}\n\nfunc expectation(f *ast.File) (string, token.Pos) {\n\tfor _, c := range f.Comments {\n\t\ttext := strings.TrimSpace(c.Text())\n\t\tif t, ok := strings.CutPrefix(text, \"WANT:\\n\"); ok {\n\t\t\treturn t, c.Pos()\n\t\t}\n\t}\n\treturn \"\", token.NoPos\n}\n\n// TestCHA runs CHA on each file in inputs, prints the dynamic edges of\n// the call graph, and compares it with the golden results embedded in\n// the WANT comment at the end of the file.\nfunc TestCHA(t *testing.T) {\n\tfor _, filename := range inputs {\n\t\tpkg, ssapkg := loadFile(t, filename, ssa.InstantiateGenerics)\n\n\t\twant, pos := expectation(pkg.Syntax[0])\n\t\tif pos == token.NoPos {\n\t\t\tt.Error(fmt.Errorf(\"No WANT: comment in %s\", filename))\n\t\t\tcontinue\n\t\t}\n\n\t\tcg := cha.CallGraph(ssapkg.Prog)\n\n\t\tif got := printGraph(cg, pkg.Types, \"dynamic\", \"Dynamic calls\"); got != want {\n\t\t\tt.Errorf(\"%s: got:\\n%s\\nwant:\\n%s\",\n\t\t\t\tssapkg.Prog.Fset.Position(pos), got, want)\n\t\t}\n\t}\n}\n\n// TestCHAGenerics is TestCHA tailored for testing generics,\nfunc TestCHAGenerics(t *testing.T) {\n\tfilename := \"testdata/generics.go\"\n\tpkg, ssapkg := loadFile(t, filename, ssa.InstantiateGenerics)\n\n\twant, pos := expectation(pkg.Syntax[0])\n\tif pos == token.NoPos {\n\t\tt.Fatal(fmt.Errorf(\"No WANT: comment in %s\", filename))\n\t}\n\n\tcg := cha.CallGraph(ssapkg.Prog)\n\n\tif got := printGraph(cg, pkg.Types, \"\", \"All calls\"); got != want {\n\t\tt.Errorf(\"%s: got:\\n%s\\nwant:\\n%s\",\n\t\t\tssapkg.Prog.Fset.Position(pos), got, want)\n\t}\n}\n\n// TestCHAUnexported tests call resolution for unexported methods.\nfunc TestCHAUnexported(t *testing.T) {\n\t// The two packages below each have types with methods called \"m\".\n\t// Each of these methods should only be callable by functions in their\n\t// own package, because they are unexported.\n\t//\n\t// In particular:\n\t// - main.main can call    (main.S1).m\n\t// - p2.Foo    can call    (p2.S2).m\n\t// - main.main cannot call (p2.S2).m\n\t// - p2.Foo    cannot call (main.S1).m\n\t//\n\t// We use CHA to build a callgraph, then check that it has the\n\t// appropriate set of edges.\n\n\tconst src = `\n-- go.mod --\nmodule x.io\ngo 1.18\n\n-- main/main.go --\npackage main\n\nimport \"x.io/p2\"\n\ntype I1 interface { m() }\ntype S1 struct { p2.I2 }\nfunc (s S1) m() { }\nfunc main() {\n\tvar s S1\n\tvar o I1 = s\n\to.m()\n\tp2.Foo(s)\n}\n\n-- p2/p2.go --\npackage p2\n\ntype I2 interface { m() }\ntype S2 struct { }\nfunc (s S2) m() { }\nfunc Foo(i I2) { i.m() }\n`\n\n\twant := `All calls\n  x.io/main.init --> x.io/p2.init\n  x.io/main.main --> (x.io/main.S1).m\n  x.io/main.main --> x.io/p2.Foo\n  x.io/p2.Foo --> (x.io/p2.S2).m`\n\n\tpkgs := testfiles.LoadPackages(t, txtar.Parse([]byte(src)), \"./...\")\n\tprog, _ := ssautil.Packages(pkgs, ssa.InstantiateGenerics)\n\tprog.Build()\n\n\tcg := cha.CallGraph(prog)\n\n\t// The graph is easier to read without synthetic nodes.\n\tcg.DeleteSyntheticNodes()\n\n\tif got := printGraph(cg, nil, \"\", \"All calls\"); got != want {\n\t\tt.Errorf(\"cha.CallGraph: got:\\n%s\\nwant:\\n%s\", got, want)\n\t}\n}\n\n// loadFile loads a built SSA package for a single-file \"x.io/main\" package.\n// (Ideally all uses would be converted over to txtar files with explicit go.mod files.)\nfunc loadFile(t testing.TB, filename string, mode ssa.BuilderMode) (*packages.Package, *ssa.Package) {\n\ttestenv.NeedsGoPackages(t)\n\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdir := t.TempDir()\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadAllSyntax,\n\t\tDir:  dir,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(dir, \"go.mod\"):       []byte(\"module x.io\\ngo 1.22\"),\n\t\t\tfilepath.Join(dir, \"main/main.go\"): data,\n\t\t},\n\t\tEnv: append(os.Environ(), \"GO111MODULES=on\", \"GOPATH=\", \"GOWORK=off\", \"GOPROXY=off\"),\n\t}\n\tpkgs, err := packages.Load(cfg, \"./main\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif num := packages.PrintErrors(pkgs); num > 0 {\n\t\tt.Fatalf(\"packages contained %d errors\", num)\n\t}\n\tprog, ssapkgs := ssautil.Packages(pkgs, mode)\n\tprog.Build()\n\treturn pkgs[0], ssapkgs[0]\n}\n\n// printGraph returns a string representation of cg involving only edges\n// whose description contains edgeMatch. The string representation is\n// prefixed with a desc line.\nfunc printGraph(cg *callgraph.Graph, from *types.Package, edgeMatch string, desc string) string {\n\tvar edges []string\n\tcallgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {\n\t\tif strings.Contains(e.Description(), edgeMatch) {\n\t\t\tedges = append(edges, fmt.Sprintf(\"%s --> %s\",\n\t\t\t\te.Caller.Func.RelString(from),\n\t\t\t\te.Callee.Func.RelString(from)))\n\t\t}\n\t\treturn nil\n\t})\n\tsort.Strings(edges)\n\n\tvar buf bytes.Buffer\n\tbuf.WriteString(desc + \"\\n\")\n\tfor _, edge := range edges {\n\t\tfmt.Fprintf(&buf, \"  %s\\n\", edge)\n\t}\n\treturn strings.TrimSpace(buf.String())\n}\n"
  },
  {
    "path": "go/callgraph/cha/testdata/func.go",
    "content": "package main\n\n// Test of dynamic function calls; no interfaces.\n\nfunc A(int) {}\n\nvar (\n\tB = func(int) {}\n\tC = func(int) {}\n)\n\nfunc f() {\n\tpfn := B\n\tpfn(0) // calls A, B, C, even though A is not even address-taken\n}\n\n// WANT:\n// Dynamic calls\n//   f --> A\n//   f --> init$1\n//   f --> init$2\n"
  },
  {
    "path": "go/callgraph/cha/testdata/generics.go",
    "content": "package main\n\n// Test of generic function calls.\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc instantiated[X I](x X) {\n\tx.Foo()\n}\n\nfunc Bar() {}\n\nfunc f(h func(), g func(I), k func(A), a A, b B) {\n\th()\n\n\tk(a)\n\tg(b) // g:func(I) is not matched by instantiated[B]:func(B)\n\n\tinstantiated[A](a) // static call\n\tinstantiated[B](b) // static call\n}\n\n// WANT:\n// All calls\n//   (*A).Foo --> (A).Foo\n//   (*B).Foo --> (B).Foo\n//   f --> Bar\n//   f --> instantiated[x.io/main.A]\n//   f --> instantiated[x.io/main.A]\n//   f --> instantiated[x.io/main.B]\n//   instantiated --> (*A).Foo\n//   instantiated --> (*B).Foo\n//   instantiated --> (A).Foo\n//   instantiated --> (B).Foo\n//   instantiated[x.io/main.A] --> (A).Foo\n//   instantiated[x.io/main.B] --> (B).Foo\n"
  },
  {
    "path": "go/callgraph/cha/testdata/iface.go",
    "content": "package main\n\n// Test of interface calls.  None of the concrete types are ever\n// instantiated or converted to interfaces.\n\ntype I interface {\n\tf()\n}\n\ntype J interface {\n\tf()\n\tg()\n}\n\ntype C int // implements I\n\nfunc (*C) f()\n\ntype D int // implements I and J\n\nfunc (*D) f()\nfunc (*D) g()\n\nfunc one(i I, j J) {\n\ti.f() // calls *C and *D\n}\n\nfunc two(i I, j J) {\n\tj.f() // calls *D (but not *C, even though it defines method f)\n}\n\nfunc three(i I, j J) {\n\tj.g() // calls *D\n}\n\nfunc four(i I, j J) {\n\tJf := J.f\n\tif unknown {\n\t\tJf = nil // suppress SSA constant propagation\n\t}\n\tJf(nil) // calls *D\n}\n\nfunc five(i I, j J) {\n\tjf := j.f\n\tif unknown {\n\t\tjf = nil // suppress SSA constant propagation\n\t}\n\tjf() // calls *D\n}\n\nvar unknown bool\n\n// WANT:\n// Dynamic calls\n//   (J).f$bound --> (*D).f\n//   (J).f$thunk --> (*D).f\n//   five --> (J).f$bound\n//   four --> (J).f$thunk\n//   one --> (*C).f\n//   one --> (*D).f\n//   three --> (*D).g\n//   two --> (*D).f\n"
  },
  {
    "path": "go/callgraph/cha/testdata/issue23925.go",
    "content": "package main\n\n// Regression test for https://golang.org/issue/23925\n\ntype stringFlagImpl string\n\nfunc (*stringFlagImpl) Set(s string) error { return nil }\n\ntype boolFlagImpl bool\n\nfunc (*boolFlagImpl) Set(s string) error { return nil }\nfunc (*boolFlagImpl) extra()             {}\n\n// A copy of flag.boolFlag interface, without a dependency.\n// Must appear first, so that it becomes the owner of the Set methods.\ntype boolFlag interface {\n\tflagValue\n\textra()\n}\n\n// A copy of flag.Value, without adding a dependency.\ntype flagValue interface {\n\tSet(string) error\n}\n\nfunc main() {\n\tvar x flagValue = new(stringFlagImpl)\n\tx.Set(\"\")\n\n\tvar y boolFlag = new(boolFlagImpl)\n\ty.Set(\"\")\n}\n\n// WANT:\n// Dynamic calls\n//   main --> (*boolFlagImpl).Set\n//   main --> (*boolFlagImpl).Set\n//   main --> (*stringFlagImpl).Set\n"
  },
  {
    "path": "go/callgraph/cha/testdata/recv.go",
    "content": "package main\n\ntype I interface {\n\tf()\n}\n\ntype J interface {\n\tg()\n}\n\ntype C int // C and *C implement I; *C implements J\n\nfunc (C) f()\nfunc (*C) g()\n\ntype D int // *D implements I and J\n\nfunc (*D) f()\nfunc (*D) g()\n\nfunc f(i I) {\n\ti.f() // calls C, *C, *D\n}\n\nfunc g(j J) {\n\tj.g() // calls *C, *D\n}\n\n// WANT:\n// Dynamic calls\n//   f --> (*C).f\n//   f --> (*D).f\n//   f --> (C).f\n//   g --> (*C).g\n//   g --> (*D).g\n"
  },
  {
    "path": "go/callgraph/internal/chautil/lazy.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package chautil provides helper functions related to\n// class hierarchy analysis (CHA) for use in x/tools.\npackage chautil\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\n// LazyCallees returns a function that maps a call site (in a function in fns)\n// to its callees within fns. The set of callees is computed using the CHA algorithm,\n// i.e., on the entire implements relation between interfaces and concrete types\n// in fns. Please see golang.org/x/tools/go/callgraph/cha for more information.\n//\n// The resulting function is not concurrency safe.\nfunc LazyCallees(fns map[*ssa.Function]bool) func(site ssa.CallInstruction) []*ssa.Function {\n\t// funcsBySig contains all functions, keyed by signature.  It is\n\t// the effective set of address-taken functions used to resolve\n\t// a dynamic call of a particular signature.\n\tvar funcsBySig typeutil.Map // value is []*ssa.Function\n\n\t// methodsByID contains all methods, grouped by ID for efficient\n\t// lookup.\n\t//\n\t// We must key by ID, not name, for correct resolution of interface\n\t// calls to a type with two (unexported) methods spelled the same but\n\t// from different packages. The fact that the concrete type implements\n\t// the interface does not mean the call dispatches to both methods.\n\tmethodsByID := make(map[string][]*ssa.Function)\n\n\t// An imethod represents an interface method I.m.\n\t// (There's no go/types object for it;\n\t// a *types.Func may be shared by many interfaces due to interface embedding.)\n\ttype imethod struct {\n\t\tI  *types.Interface\n\t\tid string\n\t}\n\t// methodsMemo records, for every abstract method call I.m on\n\t// interface type I, the set of concrete methods C.m of all\n\t// types C that satisfy interface I.\n\t//\n\t// Abstract methods may be shared by several interfaces,\n\t// hence we must pass I explicitly, not guess from m.\n\t//\n\t// methodsMemo is just a cache, so it needn't be a typeutil.Map.\n\tmethodsMemo := make(map[imethod][]*ssa.Function)\n\tlookupMethods := func(I *types.Interface, m *types.Func) []*ssa.Function {\n\t\tid := m.Id()\n\t\tmethods, ok := methodsMemo[imethod{I, id}]\n\t\tif !ok {\n\t\t\tfor _, f := range methodsByID[id] {\n\t\t\t\tC := f.Signature.Recv().Type() // named or *named\n\t\t\t\tif types.Implements(C, I) {\n\t\t\t\t\tmethods = append(methods, f)\n\t\t\t\t}\n\t\t\t}\n\t\t\tmethodsMemo[imethod{I, id}] = methods\n\t\t}\n\t\treturn methods\n\t}\n\n\tfor f := range fns {\n\t\tif f.Signature.Recv() == nil {\n\t\t\t// Package initializers can never be address-taken.\n\t\t\tif f.Name() == \"init\" && f.Synthetic == \"package initializer\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfuncs, _ := funcsBySig.At(f.Signature).([]*ssa.Function)\n\t\t\tfuncs = append(funcs, f)\n\t\t\tfuncsBySig.Set(f.Signature, funcs)\n\t\t} else if obj := f.Object(); obj != nil {\n\t\t\tid := obj.(*types.Func).Id()\n\t\t\tmethodsByID[id] = append(methodsByID[id], f)\n\t\t}\n\t}\n\n\treturn func(site ssa.CallInstruction) []*ssa.Function {\n\t\tcall := site.Common()\n\t\tif call.IsInvoke() {\n\t\t\ttiface := call.Value.Type().Underlying().(*types.Interface)\n\t\t\treturn lookupMethods(tiface, call.Method)\n\t\t} else if g := call.StaticCallee(); g != nil {\n\t\t\treturn []*ssa.Function{g}\n\t\t} else if _, ok := call.Value.(*ssa.Builtin); !ok {\n\t\t\tfns, _ := funcsBySig.At(call.Signature()).([]*ssa.Function)\n\t\t\treturn fns\n\t\t}\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/rta/rta.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This package provides Rapid Type Analysis (RTA) for Go, a fast\n// algorithm for call graph construction and discovery of reachable code\n// (and hence dead code) and runtime types.  The algorithm was first\n// described in:\n//\n// David F. Bacon and Peter F. Sweeney. 1996.\n// Fast static analysis of C++ virtual function calls. (OOPSLA '96)\n// http://doi.acm.org/10.1145/236337.236371\n//\n// The algorithm uses dynamic programming to tabulate the cross-product\n// of the set of known \"address-taken\" functions with the set of known\n// dynamic calls of the same type.  As each new address-taken function\n// is discovered, call graph edges are added from each known callsite,\n// and as each new call site is discovered, call graph edges are added\n// from it to each known address-taken function.\n//\n// A similar approach is used for dynamic calls via interfaces: it\n// tabulates the cross-product of the set of known \"runtime types\",\n// i.e. types that may appear in an interface value, or may be derived from\n// one via reflection, with the set of known \"invoke\"-mode dynamic\n// calls.  As each new runtime type is discovered, call edges are\n// added from the known call sites, and as each new call site is\n// discovered, call graph edges are added to each compatible\n// method.\n//\n// In addition, we must consider as reachable all address-taken\n// functions and all exported methods of any runtime type, since they\n// may be called via reflection.\n//\n// Each time a newly added call edge causes a new function to become\n// reachable, the code of that function is analyzed for more call sites,\n// address-taken functions, and runtime types.  The process continues\n// until a fixed point is reached.\npackage rta // import \"golang.org/x/tools/go/callgraph/rta\"\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"hash/crc32\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\n// A Result holds the results of Rapid Type Analysis, which includes the\n// set of reachable functions/methods, runtime types, and the call graph.\ntype Result struct {\n\t// CallGraph is the discovered callgraph.\n\t// It does not include edges for calls made via reflection.\n\tCallGraph *callgraph.Graph\n\n\t// Reachable contains the set of reachable functions and methods.\n\t// This includes exported methods of runtime types, since\n\t// they may be accessed via reflection.\n\t// The value indicates whether the function is address-taken.\n\t//\n\t// (We wrap the bool in a struct to avoid inadvertent use of\n\t// \"if Reachable[f] {\" to test for set membership.)\n\tReachable map[*ssa.Function]struct{ AddrTaken bool }\n\n\t// RuntimeTypes contains the set of types that are needed at\n\t// runtime, for interfaces or reflection.\n\t//\n\t// The value indicates whether the type is inaccessible to reflection.\n\t// Consider:\n\t// \ttype A struct{B}\n\t// \tfmt.Println(new(A))\n\t// Types *A, A and B are accessible to reflection, but the unnamed\n\t// type struct{B} is not.\n\tRuntimeTypes typeutil.Map\n}\n\n// Working state of the RTA algorithm.\ntype rta struct {\n\tresult *Result\n\n\tprog *ssa.Program\n\n\treflectValueCall *ssa.Function // (*reflect.Value).Call, iff part of prog\n\n\tworklist []*ssa.Function // list of functions to visit\n\n\t// addrTakenFuncsBySig contains all address-taken *Functions, grouped by signature.\n\t// Keys are *types.Signature, values are map[*ssa.Function]bool sets.\n\taddrTakenFuncsBySig typeutil.Map\n\n\t// dynCallSites contains all dynamic \"call\"-mode call sites, grouped by signature.\n\t// Keys are *types.Signature, values are unordered []ssa.CallInstruction.\n\tdynCallSites typeutil.Map\n\n\t// invokeSites contains all \"invoke\"-mode call sites, grouped by interface.\n\t// Keys are *types.Interface (never *types.Named),\n\t// Values are unordered []ssa.CallInstruction sets.\n\tinvokeSites typeutil.Map\n\n\t// The following two maps together define the subset of the\n\t// m:n \"implements\" relation needed by the algorithm.\n\n\t// concreteTypes maps each concrete type to information about it.\n\t// Keys are types.Type, values are *concreteTypeInfo.\n\t// Only concrete types used as MakeInterface operands are included.\n\tconcreteTypes typeutil.Map\n\n\t// interfaceTypes maps each interface type to information about it.\n\t// Keys are *types.Interface, values are *interfaceTypeInfo.\n\t// Only interfaces used in \"invoke\"-mode CallInstructions are included.\n\tinterfaceTypes typeutil.Map\n}\n\ntype concreteTypeInfo struct {\n\tC          types.Type\n\tmset       *types.MethodSet\n\tfprint     uint64             // fingerprint of method set\n\timplements []*types.Interface // unordered set of implemented interfaces\n}\n\ntype interfaceTypeInfo struct {\n\tI               *types.Interface\n\tmset            *types.MethodSet\n\tfprint          uint64\n\timplementations []types.Type // unordered set of concrete implementations\n}\n\n// addReachable marks a function as potentially callable at run-time,\n// and ensures that it gets processed.\nfunc (r *rta) addReachable(f *ssa.Function, addrTaken bool) {\n\treachable := r.result.Reachable\n\tn := len(reachable)\n\tv := reachable[f]\n\tif addrTaken {\n\t\tv.AddrTaken = true\n\t}\n\treachable[f] = v\n\tif len(reachable) > n {\n\t\t// First time seeing f.  Add it to the worklist.\n\t\tr.worklist = append(r.worklist, f)\n\t}\n}\n\n// addEdge adds the specified call graph edge, and marks it reachable.\n// addrTaken indicates whether to mark the callee as \"address-taken\".\n// site is nil for calls made via reflection.\nfunc (r *rta) addEdge(caller *ssa.Function, site ssa.CallInstruction, callee *ssa.Function, addrTaken bool) {\n\tr.addReachable(callee, addrTaken)\n\n\tif g := r.result.CallGraph; g != nil {\n\t\tif caller == nil {\n\t\t\tpanic(site)\n\t\t}\n\t\tfrom := g.CreateNode(caller)\n\t\tto := g.CreateNode(callee)\n\t\tcallgraph.AddEdge(from, site, to)\n\t}\n}\n\n// ---------- addrTakenFuncs × dynCallSites ----------\n\n// visitAddrTakenFunc is called each time we encounter an address-taken function f.\nfunc (r *rta) visitAddrTakenFunc(f *ssa.Function) {\n\t// Create two-level map (Signature -> Function -> bool).\n\tS := f.Signature\n\tfuncs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)\n\tif funcs == nil {\n\t\tfuncs = make(map[*ssa.Function]bool)\n\t\tr.addrTakenFuncsBySig.Set(S, funcs)\n\t}\n\tif !funcs[f] {\n\t\t// First time seeing f.\n\t\tfuncs[f] = true\n\n\t\t// If we've seen any dyncalls of this type, mark it reachable,\n\t\t// and add call graph edges.\n\t\tsites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)\n\t\tfor _, site := range sites {\n\t\t\tr.addEdge(site.Parent(), site, f, true)\n\t\t}\n\n\t\t// If the program includes (*reflect.Value).Call,\n\t\t// add a dynamic call edge from it to any address-taken\n\t\t// function, regardless of signature.\n\t\t//\n\t\t// This isn't perfect.\n\t\t// - The actual call comes from an internal function\n\t\t//   called reflect.call, but we can't rely on that here.\n\t\t// - reflect.Value.CallSlice behaves similarly,\n\t\t//   but we don't bother to create callgraph edges from\n\t\t//   it as well as it wouldn't fundamentally change the\n\t\t//   reachability but it would add a bunch more edges.\n\t\t// - We assume that if reflect.Value.Call is among\n\t\t//   the dependencies of the application, it is itself\n\t\t//   reachable. (It would be more accurate to defer\n\t\t//   all the addEdges below until r.V.Call itself\n\t\t//   becomes reachable.)\n\t\t// - Fake call graph edges are added from r.V.Call to\n\t\t//   each address-taken function, but not to every\n\t\t//   method reachable through a materialized rtype,\n\t\t//   which is a little inconsistent. Still, the\n\t\t//   reachable set includes both kinds, which is what\n\t\t//   matters for e.g. deadcode detection.)\n\t\tif r.reflectValueCall != nil {\n\t\t\tvar site ssa.CallInstruction = nil // can't find actual call site\n\t\t\tr.addEdge(r.reflectValueCall, site, f, true)\n\t\t}\n\t}\n}\n\n// visitDynCall is called each time we encounter a dynamic \"call\"-mode call.\nfunc (r *rta) visitDynCall(site ssa.CallInstruction) {\n\tS := site.Common().Signature()\n\n\t// Record the call site.\n\tsites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)\n\tr.dynCallSites.Set(S, append(sites, site))\n\n\t// For each function of signature S that we know is address-taken,\n\t// add an edge and mark it reachable.\n\tfuncs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)\n\tfor g := range funcs {\n\t\tr.addEdge(site.Parent(), site, g, true)\n\t}\n}\n\n// ---------- concrete types × invoke sites ----------\n\n// addInvokeEdge is called for each new pair (site, C) in the matrix.\nfunc (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {\n\t// Ascertain the concrete method of C to be called.\n\timethod := site.Common().Method\n\tcmethod := r.prog.LookupMethod(C, imethod.Pkg(), imethod.Name())\n\tr.addEdge(site.Parent(), site, cmethod, true)\n}\n\n// visitInvoke is called each time the algorithm encounters an \"invoke\"-mode call.\nfunc (r *rta) visitInvoke(site ssa.CallInstruction) {\n\tI := site.Common().Value.Type().Underlying().(*types.Interface)\n\n\t// Record the invoke site.\n\tsites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)\n\tr.invokeSites.Set(I, append(sites, site))\n\n\t// Add callgraph edge for each existing\n\t// address-taken concrete type implementing I.\n\tfor _, C := range r.implementations(I) {\n\t\tr.addInvokeEdge(site, C)\n\t}\n}\n\n// ---------- main algorithm ----------\n\n// visitFunc processes function f.\nfunc (r *rta) visitFunc(f *ssa.Function) {\n\tvar space [32]*ssa.Value // preallocate space for common case\n\n\tfor _, b := range f.Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\trands := instr.Operands(space[:0])\n\n\t\t\tswitch instr := instr.(type) {\n\t\t\tcase ssa.CallInstruction:\n\t\t\t\tcall := instr.Common()\n\t\t\t\tif call.IsInvoke() {\n\t\t\t\t\tr.visitInvoke(instr)\n\t\t\t\t} else if g := call.StaticCallee(); g != nil {\n\t\t\t\t\tr.addEdge(f, instr, g, false)\n\t\t\t\t} else if _, ok := call.Value.(*ssa.Builtin); !ok {\n\t\t\t\t\tr.visitDynCall(instr)\n\t\t\t\t}\n\n\t\t\t\t// Ignore the call-position operand when\n\t\t\t\t// looking for address-taken Functions.\n\t\t\t\t// Hack: assume this is rands[0].\n\t\t\t\trands = rands[1:]\n\n\t\t\tcase *ssa.MakeInterface:\n\t\t\t\t// Converting a value of type T to an\n\t\t\t\t// interface materializes its runtime\n\t\t\t\t// type, allowing any of its exported\n\t\t\t\t// methods to be called though reflection.\n\t\t\t\tr.addRuntimeType(instr.X.Type(), false)\n\t\t\t}\n\n\t\t\t// Process all address-taken functions.\n\t\t\tfor _, op := range rands {\n\t\t\t\tif g, ok := (*op).(*ssa.Function); ok {\n\t\t\t\t\tr.visitAddrTakenFunc(g)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Analyze performs Rapid Type Analysis, starting at the specified root\n// functions.  It returns nil if no roots were specified.\n//\n// The root functions must be one or more entrypoints (main and init\n// functions) of a complete SSA program, with function bodies for all\n// dependencies, constructed with the [ssa.InstantiateGenerics] mode\n// flag.\n//\n// If buildCallGraph is true, Result.CallGraph will contain a call\n// graph; otherwise, only the other fields (reachable functions) are\n// populated.\nfunc Analyze(roots []*ssa.Function, buildCallGraph bool) *Result {\n\tif len(roots) == 0 {\n\t\treturn nil\n\t}\n\n\tr := &rta{\n\t\tresult: &Result{Reachable: make(map[*ssa.Function]struct{ AddrTaken bool })},\n\t\tprog:   roots[0].Prog,\n\t}\n\n\tif buildCallGraph {\n\t\t// TODO(adonovan): change callgraph API to eliminate the\n\t\t// notion of a distinguished root node.  Some callgraphs\n\t\t// have many roots, or none.\n\t\tr.result.CallGraph = callgraph.New(roots[0])\n\t}\n\n\t// Grab ssa.Function for (*reflect.Value).Call,\n\t// if \"reflect\" is among the dependencies.\n\tif reflectPkg := r.prog.ImportedPackage(\"reflect\"); reflectPkg != nil {\n\t\treflectValue := reflectPkg.Members[\"Value\"].(*ssa.Type)\n\t\tr.reflectValueCall = r.prog.LookupMethod(reflectValue.Object().Type(), reflectPkg.Pkg, \"Call\")\n\t}\n\n\thasher := typeutil.MakeHasher()\n\tr.result.RuntimeTypes.SetHasher(hasher)\n\tr.addrTakenFuncsBySig.SetHasher(hasher)\n\tr.dynCallSites.SetHasher(hasher)\n\tr.invokeSites.SetHasher(hasher)\n\tr.concreteTypes.SetHasher(hasher)\n\tr.interfaceTypes.SetHasher(hasher)\n\n\tfor _, root := range roots {\n\t\tr.addReachable(root, false)\n\t}\n\n\t// Visit functions, processing their instructions, and adding\n\t// new functions to the worklist, until a fixed point is\n\t// reached.\n\tvar shadow []*ssa.Function // for efficiency, we double-buffer the worklist\n\tfor len(r.worklist) > 0 {\n\t\tshadow, r.worklist = r.worklist, shadow[:0]\n\t\tfor _, f := range shadow {\n\t\t\tr.visitFunc(f)\n\t\t}\n\t}\n\treturn r.result\n}\n\n// interfaces(C) returns all currently known interfaces implemented by C.\nfunc (r *rta) interfaces(C types.Type) []*types.Interface {\n\t// Create an info for C the first time we see it.\n\tvar cinfo *concreteTypeInfo\n\tif v := r.concreteTypes.At(C); v != nil {\n\t\tcinfo = v.(*concreteTypeInfo)\n\t} else {\n\t\tmset := r.prog.MethodSets.MethodSet(C)\n\t\tcinfo = &concreteTypeInfo{\n\t\t\tC:      C,\n\t\t\tmset:   mset,\n\t\t\tfprint: fingerprint(mset),\n\t\t}\n\t\tr.concreteTypes.Set(C, cinfo)\n\n\t\t// Ascertain set of interfaces C implements\n\t\t// and update the 'implements' relation.\n\t\tr.interfaceTypes.Iterate(func(I types.Type, v any) {\n\t\t\tiinfo := v.(*interfaceTypeInfo)\n\t\t\tif I := types.Unalias(I).(*types.Interface); implements(cinfo, iinfo) {\n\t\t\t\tiinfo.implementations = append(iinfo.implementations, C)\n\t\t\t\tcinfo.implements = append(cinfo.implements, I)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn cinfo.implements\n}\n\n// implementations(I) returns all currently known concrete types that implement I.\nfunc (r *rta) implementations(I *types.Interface) []types.Type {\n\t// Create an info for I the first time we see it.\n\tvar iinfo *interfaceTypeInfo\n\tif v := r.interfaceTypes.At(I); v != nil {\n\t\tiinfo = v.(*interfaceTypeInfo)\n\t} else {\n\t\tmset := r.prog.MethodSets.MethodSet(I)\n\t\tiinfo = &interfaceTypeInfo{\n\t\t\tI:      I,\n\t\t\tmset:   mset,\n\t\t\tfprint: fingerprint(mset),\n\t\t}\n\t\tr.interfaceTypes.Set(I, iinfo)\n\n\t\t// Ascertain set of concrete types that implement I\n\t\t// and update the 'implements' relation.\n\t\tr.concreteTypes.Iterate(func(C types.Type, v any) {\n\t\t\tcinfo := v.(*concreteTypeInfo)\n\t\t\tif implements(cinfo, iinfo) {\n\t\t\t\tcinfo.implements = append(cinfo.implements, I)\n\t\t\t\tiinfo.implementations = append(iinfo.implementations, C)\n\t\t\t}\n\t\t})\n\t}\n\treturn iinfo.implementations\n}\n\n// addRuntimeType is called for each concrete type that can be the\n// dynamic type of some interface or reflect.Value.\n// Adapted from needMethods in go/ssa/builder.go\nfunc (r *rta) addRuntimeType(T types.Type, skip bool) {\n\t// Never record aliases.\n\tT = types.Unalias(T)\n\n\tif prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {\n\t\tif skip && !prev {\n\t\t\tr.result.RuntimeTypes.Set(T, skip)\n\t\t}\n\t\treturn\n\t}\n\tr.result.RuntimeTypes.Set(T, skip)\n\n\tmset := r.prog.MethodSets.MethodSet(T)\n\n\tif _, ok := T.Underlying().(*types.Interface); !ok {\n\t\t// T is a new concrete type.\n\t\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\t\tsel := mset.At(i)\n\t\t\tm := sel.Obj()\n\n\t\t\tif m.Exported() {\n\t\t\t\t// Exported methods are always potentially callable via reflection.\n\t\t\t\tr.addReachable(r.prog.MethodValue(sel), true)\n\t\t\t}\n\t\t}\n\n\t\t// Add callgraph edge for each existing dynamic\n\t\t// \"invoke\"-mode call via that interface.\n\t\tfor _, I := range r.interfaces(T) {\n\t\t\tsites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)\n\t\t\tfor _, site := range sites {\n\t\t\t\tr.addInvokeEdge(site, T)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Precondition: T is not a method signature (*Signature with Recv()!=nil).\n\t// Recursive case: skip => don't call makeMethods(T).\n\t// Each package maintains its own set of types it has visited.\n\n\tvar n *types.Named\n\tswitch T := types.Unalias(T).(type) {\n\tcase *types.Named:\n\t\tn = T\n\tcase *types.Pointer:\n\t\tn, _ = types.Unalias(T.Elem()).(*types.Named)\n\t}\n\tif n != nil {\n\t\towner := n.Obj().Pkg()\n\t\tif owner == nil {\n\t\t\treturn // built-in error type\n\t\t}\n\t}\n\n\t// Recursion over signatures of each exported method.\n\tfor method := range mset.Methods() {\n\t\tif method.Obj().Exported() {\n\t\t\tsig := method.Type().(*types.Signature)\n\t\t\tr.addRuntimeType(sig.Params(), true)  // skip the Tuple itself\n\t\t\tr.addRuntimeType(sig.Results(), true) // skip the Tuple itself\n\t\t}\n\t}\n\n\tswitch t := T.(type) {\n\tcase *types.Alias:\n\t\tpanic(\"unreachable\")\n\n\tcase *types.Basic:\n\t\t// nop\n\n\tcase *types.Interface:\n\t\t// nop---handled by recursion over method set.\n\n\tcase *types.Pointer:\n\t\tr.addRuntimeType(t.Elem(), false)\n\n\tcase *types.Slice:\n\t\tr.addRuntimeType(t.Elem(), false)\n\n\tcase *types.Chan:\n\t\tr.addRuntimeType(t.Elem(), false)\n\n\tcase *types.Map:\n\t\tr.addRuntimeType(t.Key(), false)\n\t\tr.addRuntimeType(t.Elem(), false)\n\n\tcase *types.Signature:\n\t\tif t.Recv() != nil {\n\t\t\tpanic(fmt.Sprintf(\"Signature %s has Recv %s\", t, t.Recv()))\n\t\t}\n\t\tr.addRuntimeType(t.Params(), true)  // skip the Tuple itself\n\t\tr.addRuntimeType(t.Results(), true) // skip the Tuple itself\n\n\tcase *types.Named:\n\t\t// A pointer-to-named type can be derived from a named\n\t\t// type via reflection.  It may have methods too.\n\t\tr.addRuntimeType(types.NewPointer(T), false)\n\n\t\t// Consider 'type T struct{S}' where S has methods.\n\t\t// Reflection provides no way to get from T to struct{S},\n\t\t// only to S, so the method set of struct{S} is unwanted,\n\t\t// so set 'skip' flag during recursion.\n\t\tr.addRuntimeType(t.Underlying(), true)\n\n\tcase *types.Array:\n\t\tr.addRuntimeType(t.Elem(), false)\n\n\tcase *types.Struct:\n\t\tfor i, n := 0, t.NumFields(); i < n; i++ {\n\t\t\tr.addRuntimeType(t.Field(i).Type(), false)\n\t\t}\n\n\tcase *types.Tuple:\n\t\tfor i, n := 0, t.Len(); i < n; i++ {\n\t\t\tr.addRuntimeType(t.At(i).Type(), false)\n\t\t}\n\n\tdefault:\n\t\tpanic(T)\n\t}\n}\n\n// fingerprint returns a bitmask with one bit set per method id,\n// enabling 'implements' to quickly reject most candidates.\nfunc fingerprint(mset *types.MethodSet) uint64 {\n\tvar space [64]byte\n\tvar mask uint64\n\tfor method := range mset.Methods() {\n\t\tmethod := method.Obj()\n\t\tsig := method.Type().(*types.Signature)\n\t\tsum := crc32.ChecksumIEEE(fmt.Appendf(space[:], \"%s/%d/%d\",\n\t\t\tmethod.Id(),\n\t\t\tsig.Params().Len(),\n\t\t\tsig.Results().Len()))\n\t\tmask |= 1 << (sum % 64)\n\t}\n\treturn mask\n}\n\n// implements reports whether types.Implements(cinfo.C, iinfo.I),\n// but more efficiently.\nfunc implements(cinfo *concreteTypeInfo, iinfo *interfaceTypeInfo) (got bool) {\n\t// The concrete type must have at least the methods\n\t// (bits) of the interface type. Use a bitwise subset\n\t// test to reject most candidates quickly.\n\treturn iinfo.fprint & ^cinfo.fprint == 0 && types.Implements(cinfo.C, iinfo.I)\n}\n"
  },
  {
    "path": "go/callgraph/rta/rta_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage rta_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/rta\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TestRTA runs RTA on each testdata/*.txtar file containing a single\n// go file in a single package or multiple files in different packages,\n// and compares the results with the expectations expressed in the WANT\n// comment.\nfunc TestRTA(t *testing.T) {\n\tarchivePaths := []string{\n\t\t\"testdata/func.txtar\",\n\t\t\"testdata/generics.txtar\",\n\t\t\"testdata/iface.txtar\",\n\t\t\"testdata/reflectcall.txtar\",\n\t\t\"testdata/rtype.txtar\",\n\t\t\"testdata/multipkgs.txtar\",\n\t}\n\tfor _, archive := range archivePaths {\n\t\tt.Run(archive, func(t *testing.T) {\n\t\t\tar, err := txtar.ParseFile(archive)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tpkgs := testfiles.LoadPackages(t, ar, \"./...\")\n\n\t\t\t// find the file which contains the expected result\n\t\t\tvar f *ast.File\n\t\t\tfor _, p := range pkgs {\n\t\t\t\t// We assume the packages have a single file or\n\t\t\t\t// the wanted result is in the first file of the main package.\n\t\t\t\tif p.Name == \"main\" {\n\t\t\t\t\tf = p.Syntax[0]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif f == nil {\n\t\t\t\tt.Fatalf(\"failed to find the file with expected result within main package %s\", archive)\n\t\t\t}\n\n\t\t\tprog, spkgs := ssautil.Packages(pkgs, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)\n\n\t\t\t// find the main package to get functions for rta analysis\n\t\t\tvar mainPkg *ssa.Package\n\t\t\tfor _, sp := range spkgs {\n\t\t\t\tif sp.Pkg.Name() == \"main\" {\n\t\t\t\t\tmainPkg = sp\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif mainPkg == nil {\n\t\t\t\tt.Fatalf(\"failed to find main ssa package %s\", archive)\n\t\t\t}\n\n\t\t\tprog.Build()\n\n\t\t\tres := rta.Analyze([]*ssa.Function{\n\t\t\t\tmainPkg.Func(\"main\"),\n\t\t\t\tmainPkg.Func(\"init\"),\n\t\t\t}, true)\n\n\t\t\tcheck(t, f, mainPkg, res)\n\t\t})\n\t}\n}\n\n// check tests the RTA analysis results against the test expectations\n// defined by a comment starting with a line \"WANT:\".\n//\n// The rest of the comment consists of lines of the following forms:\n//\n//\tedge      <func> --kind--> <func>\t# call graph edge\n//\treachable <func>\t\t\t# reachable function\n//\trtype     <type>\t\t\t# run-time type descriptor needed\n//\n// Each line asserts that an element is found in the given set, or, if\n// the line is preceded by \"!\", that it is not in the set.\n//\n// Functions are notated as if by ssa.Function.String.\nfunc check(t *testing.T, f *ast.File, pkg *ssa.Package, res *rta.Result) {\n\ttokFile := pkg.Prog.Fset.File(f.FileStart)\n\n\t// Find the WANT comment.\n\texpectation := func(f *ast.File) (string, int) {\n\t\tfor _, c := range f.Comments {\n\t\t\ttext := strings.TrimSpace(c.Text())\n\t\t\tif t, ok := strings.CutPrefix(text, \"WANT:\\n\"); ok {\n\t\t\t\treturn t, tokFile.Line(c.Pos())\n\t\t\t}\n\t\t}\n\t\tt.Fatalf(\"No WANT: comment in %s\", tokFile.Name())\n\t\treturn \"\", 0\n\t}\n\twant, linenum := expectation(f)\n\n\t// Parse the comment into three string-to-sense maps.\n\tvar (\n\t\twantEdge      = make(map[string]bool)\n\t\twantReachable = make(map[string]bool)\n\t\twantRtype     = make(map[string]bool)\n\t)\n\tfor line := range strings.SplitSeq(want, \"\\n\") {\n\t\tlinenum++\n\t\torig := line\n\t\tbad := func() {\n\t\t\tt.Fatalf(\"%s:%d: invalid assertion: %q\", tokFile.Name(), linenum, orig)\n\t\t}\n\n\t\tline := strings.TrimSpace(line)\n\t\tif line == \"\" {\n\t\t\tcontinue // skip blanks\n\t\t}\n\n\t\t// A leading \"!\" negates the assertion.\n\t\tsense := true\n\t\tif rest, ok := strings.CutPrefix(line, \"!\"); ok {\n\t\t\tsense = false\n\t\t\tline = strings.TrimSpace(rest)\n\t\t\tif line == \"\" {\n\t\t\t\tbad()\n\t\t\t}\n\t\t}\n\n\t\t// Select the map.\n\t\tvar want map[string]bool\n\t\tkind := strings.Fields(line)[0]\n\t\tswitch kind {\n\t\tcase \"edge\":\n\t\t\twant = wantEdge\n\t\tcase \"reachable\":\n\t\t\twant = wantReachable\n\t\tcase \"rtype\":\n\t\t\twant = wantRtype\n\t\tdefault:\n\t\t\tbad()\n\t\t}\n\n\t\t// Add expectation.\n\t\tstr := strings.TrimSpace(line[len(kind):])\n\t\twant[str] = sense\n\t}\n\n\ttype stringset = map[string]bool // (sets: values are true)\n\n\t// compare checks that got matches each assertion of the form\n\t// (str, sense) in want. The sense determines whether the test\n\t// is positive or negative.\n\tcompare := func(kind string, got stringset, want map[string]bool) {\n\t\tok := true\n\t\tfor str, sense := range want {\n\t\t\tif got[str] != sense {\n\t\t\t\tok = false\n\t\t\t\tif sense {\n\t\t\t\t\tt.Errorf(\"missing %s %q\", kind, str)\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"unwanted %s %q\", kind, str)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Print the actual output in expectation form.\n\t\tif !ok {\n\t\t\tvar strs []string\n\t\t\tfor s := range got {\n\t\t\t\tstrs = append(strs, s)\n\t\t\t}\n\t\t\tsort.Strings(strs)\n\t\t\tvar buf strings.Builder\n\t\t\tfor _, str := range strs {\n\t\t\t\tfmt.Fprintf(&buf, \"%s %s\\n\", kind, str)\n\t\t\t}\n\t\t\tt.Errorf(\"got:\\n%s\", &buf)\n\t\t}\n\t}\n\n\t// Check call graph edges.\n\t{\n\t\tgot := make(stringset)\n\t\tcallgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error {\n\t\t\tedge := fmt.Sprintf(\"%s --%s--> %s\",\n\t\t\t\te.Caller.Func.RelString(pkg.Pkg),\n\t\t\t\te.Description(),\n\t\t\t\te.Callee.Func.RelString(pkg.Pkg))\n\t\t\tgot[edge] = true\n\t\t\treturn nil\n\t\t})\n\t\tcompare(\"edge\", got, wantEdge)\n\t}\n\n\t// Check reachable functions.\n\t{\n\t\tgot := make(stringset)\n\t\tfor f := range res.Reachable {\n\t\t\tgot[f.RelString(pkg.Pkg)] = true\n\t\t}\n\t\tcompare(\"reachable\", got, wantReachable)\n\t}\n\n\t// Check runtime types.\n\t{\n\t\tgot := make(stringset)\n\t\tres.RuntimeTypes.Iterate(func(key types.Type, value any) {\n\t\t\tif !value.(bool) { // accessible to reflection\n\t\t\t\ttyp := types.TypeString(types.Unalias(key), types.RelativeTo(pkg.Pkg))\n\t\t\t\tgot[typ] = true\n\t\t\t}\n\t\t})\n\t\tcompare(\"rtype\", got, wantRtype)\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/rta/testdata/func.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- func.go --\npackage main\n\n// Test of dynamic function calls.\n// No interfaces, so no runtime/reflect types.\n\nfunc A1() {\n\tA2(0)\n}\n\nfunc A2(int) {} // not address-taken\n\nfunc B() {} // unreachable\n\nvar (\n\tC = func(int) {}\n\tD = func(int) {}\n)\n\nfunc main() {\n\tA1()\n\n\tpfn := C\n\tpfn(0) // calls C and D but not A2 (same sig but not address-taken)\n}\n\n// WANT:\n//\n//  edge main --dynamic function call--> init$1\n//  edge main --dynamic function call--> init$2\n//\n//  reachable A1\n//  reachable A2\n//  reachable init$1\n//  reachable init$2\n// !reachable B\n//  reachable main"
  },
  {
    "path": "go/callgraph/rta/testdata/generics.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- generics.go --\npackage main\n\n// Test of generic function calls.\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc instantiated[X I](x X) {\n\tx.Foo()\n}\n\nvar a A\nvar b B\n\nfunc main() {\n\tinstantiated[A](a) // static call\n\tinstantiated[B](b) // static call\n\n\tlocal[C]().Foo()\n\n\tlambda[A]()()()\n}\n\nfunc local[X I]() I {\n\tvar x X\n\treturn x\n}\n\ntype C struct{}\n\nfunc (c C) Foo() {}\n\nfunc lambda[X I]() func() func() {\n\treturn func() func() {\n\t\tvar x X\n\t\treturn x.Foo\n\t}\n}\n\n// WANT:\n//\n//  edge (*C).Foo --static method call--> (C).Foo\n//  edge (A).Foo$bound --static method call--> (A).Foo\n//  edge instantiated[example.com.A] --static method call--> (A).Foo\n//  edge instantiated[example.com.B] --static method call--> (B).Foo\n//  edge main --dynamic method call--> (*C).Foo\n//  edge main --dynamic function call--> (A).Foo$bound\n//  edge main --dynamic method call--> (C).Foo\n//  edge main --static function call--> instantiated[example.com.A]\n//  edge main --static function call--> instantiated[example.com.B]\n//  edge main --static function call--> lambda[example.com.A]\n//  edge main --dynamic function call--> lambda[example.com.A]$1\n//  edge main --static function call--> local[example.com.C]\n//\n//  reachable (*C).Foo\n//  reachable (A).Foo\n//  reachable (A).Foo$bound\n//  reachable (B).Foo\n//  reachable (C).Foo\n//  reachable instantiated[example.com.A]\n//  reachable instantiated[example.com.B]\n//  reachable lambda[example.com.A]\n//  reachable lambda[example.com.A]$1\n//  reachable local[example.com.C]\n//\n//  rtype *C\n//  rtype C\n"
  },
  {
    "path": "go/callgraph/rta/testdata/iface.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- iface.go --\npackage main\n\n// Test of interface calls.\n\nfunc use(interface{})\n\ntype A byte // instantiated but not a reflect type\n\nfunc (A) f() {} // called directly\nfunc (A) F() {} // unreachable\n\ntype B int // a reflect type\n\nfunc (*B) f() {} // reachable via interface invoke\nfunc (*B) F() {} // reachable: exported method of reflect type\n\ntype B2 int // a reflect type, and *B2 also\n\nfunc (B2) f() {} // reachable via interface invoke\nfunc (B2) g() {} // reachable: exported method of reflect type\n\ntype C string // not instantiated\n\nfunc (C) f() {} // unreachable\nfunc (C) F() {} // unreachable\n\ntype D uint // instantiated only in dead code\n\nfunc (D) f() {} // unreachable\nfunc (D) F() {} // unreachable\n\nfunc main() {\n\tA(0).f()\n\n\tuse(new(B))\n\tuse(B2(0))\n\n\tvar i interface {\n\t\tf()\n\t}\n\ti.f() // calls (*B).f, (*B2).f and (B2.f)\n\n\tlive()\n}\n\nfunc live() {\n\tvar j interface {\n\t\tf()\n\t\tg()\n\t}\n\tj.f() // calls (B2).f and (*B2).f but not (*B).f (no g method).\n}\n\nfunc dead() {\n\tuse(D(0))\n}\n\n// WANT:\n//\n//  edge live --dynamic method call--> (*B2).f\n//  edge live --dynamic method call--> (B2).f\n//  edge main --dynamic method call--> (*B).f\n//  edge main --dynamic method call--> (*B2).f\n//  edge main --dynamic method call--> (B2).f\n//\n//  reachable (A).f\n// !reachable (A).F\n//  reachable (*B).f\n//  reachable (*B).F\n//  reachable (B2).f\n// !reachable (B2).g\n//  reachable (*B2).f\n// !reachable (*B2).g\n// !reachable (C).f\n// !reachable (C).F\n// !reachable (D).f\n// !reachable (D).F\n//  reachable main\n//  reachable live\n//  reachable use\n// !reachable dead\n//\n// !rtype A\n//  rtype *B\n//  rtype *B2\n//  rtype B\n//  rtype B2\n// !rtype C\n// !rtype D\n"
  },
  {
    "path": "go/callgraph/rta/testdata/multipkgs.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- iface.go --\npackage main\n\nimport (\n\t\"example.com/subpkg\"\n)\n\nfunc use(interface{})\n\n// Test of interface calls.\n\nfunc main() {\n\tuse(subpkg.A(0))\n\tuse(new(subpkg.B))\n\tuse(subpkg.B2(0))\n\n\tvar i interface {\n\t\tF()\n\t}\n\n\t// assign an interface type with a function return interface value\n\ti = subpkg.NewInterfaceF()\n\n\ti.F()\n}\n\nfunc dead() {\n\tuse(subpkg.D(0))\n}\n\n// WANT:\n//\n// edge (*example.com/subpkg.A).F --static method call--> (example.com/subpkg.A).F\n// edge (*example.com/subpkg.B2).F --static method call--> (example.com/subpkg.B2).F\n// edge (*example.com/subpkg.C).F --static method call--> (example.com/subpkg.C).F\n// edge init --static function call--> example.com/subpkg.init\n// edge main --dynamic method call--> (*example.com/subpkg.A).F\n// edge main --dynamic method call--> (*example.com/subpkg.B).F\n// edge main --dynamic method call--> (*example.com/subpkg.B2).F\n// edge main --dynamic method call--> (*example.com/subpkg.C).F\n// edge main --dynamic method call--> (example.com/subpkg.A).F\n// edge main --dynamic method call--> (example.com/subpkg.B2).F\n// edge main --dynamic method call--> (example.com/subpkg.C).F\n// edge main --static function call--> example.com/subpkg.NewInterfaceF\n// edge main --static function call--> use\n//\n// reachable (*example.com/subpkg.A).F\n// reachable (*example.com/subpkg.B).F\n// reachable (*example.com/subpkg.B2).F\n// reachable (*example.com/subpkg.C).F\n// reachable (example.com/subpkg.A).F\n// !reachable (example.com/subpkg.B).F\n// reachable (example.com/subpkg.B2).F\n// reachable (example.com/subpkg.C).F\n// reachable example.com/subpkg.NewInterfaceF\n// reachable example.com/subpkg.init\n// !reachable (*example.com/subpkg.D).F\n// !reachable (example.com/subpkg.D).F\n// reachable init\n// reachable main\n// reachable use\n//\n// rtype *example.com/subpkg.A\n// rtype *example.com/subpkg.B\n// rtype *example.com/subpkg.B2\n// rtype *example.com/subpkg.C\n// rtype example.com/subpkg.B\n// rtype example.com/subpkg.A\n// rtype example.com/subpkg.B2\n// rtype example.com/subpkg.C\n// !rtype example.com/subpkg.D\n\n-- subpkg/impl.go --\npackage subpkg\n\ntype InterfaceF interface {\n\tF()\n}\n\ntype A byte // instantiated but not a reflect type\n\nfunc (A) F() {} // reachable: exported method of reflect type\n\ntype B int // a reflect type\n\nfunc (*B) F() {} // reachable: exported method of reflect type\n\ntype B2 int // a reflect type, and *B2 also\n\nfunc (B2) F() {} // reachable: exported method of reflect type\n\ntype C string\n\nfunc (C) F() {} // reachable: exported by NewInterfaceF\n\nfunc NewInterfaceF() InterfaceF {\n\treturn C(\"\")\n}\n\ntype D uint // instantiated only in dead code\n\nfunc (*D) F() {} // unreachable"
  },
  {
    "path": "go/callgraph/rta/testdata/reflectcall.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- reflectcall.go --\n// Test of a reflective call to an address-taken function.\n//\n// Dynamically, this program executes both print statements.\n// RTA should report the hello methods as reachable,\n// even though there are no dynamic calls of type func(U)\n// and the type T is not live.\n\npackage main\n\nimport \"reflect\"\n\ntype T int\ntype U int // to ensure the hello methods' signatures are unique\n\nfunc (T) hello(U) { println(\"hello\") }\n\ntype T2 int\n\nfunc (T2) Hello(U, U) { println(\"T2.Hello\") }\n\nfunc main() {\n\tu := reflect.ValueOf(U(0))\n\n\t// reflective call to bound method closure T.hello\n\treflect.ValueOf(T(0).hello).Call([]reflect.Value{u})\n\n\t// reflective call to exported method \"Hello\" of rtype T2.\n\treflect.ValueOf(T2(0)).Method(0).Call([]reflect.Value{u, u})\n}\n\n// WANT:\n//\n//  edge (reflect.Value).Call --synthetic call--> (T).hello$bound\n//  edge (T).hello$bound --static method call--> (T).hello\n//  edge main --static function call--> reflect.ValueOf\n//  edge main --static method call--> (reflect.Value).Call\n//  edge (*T2).Hello --static method call--> (T2).Hello\n//\n//  reachable (T).hello\n//  reachable (T).hello$bound\n//  reachable (T2).Hello\n//\n// !rtype T\n//  rtype T2\n//  rtype U\n"
  },
  {
    "path": "go/callgraph/rta/testdata/rtype.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.18\n\n-- rtype.go --\npackage main\n\n// Test of runtime types (types for which descriptors are needed).\n\nfunc use(interface{})\n\ntype A byte // neither A nor byte are runtime types\n\ntype B struct{ x uint } // B and uint are runtime types, but not the struct\n\nfunc main() {\n\tvar x int // not a runtime type\n\tprint(x)\n\n\tvar y string // runtime type due to interface conversion\n\tuse(y)\n\n\tuse(struct{ uint64 }{}) // struct is a runtime type\n\n\tuse(new(B)) // *B is a runtime type\n}\n\n// WANT:\n//\n//  reachable main\n//  reachable use\n//\n// !rtype A\n// !rtype struct{uint}\n//  rtype *B\n//  rtype B\n//  rtype string\n//  rtype struct{uint64}\n//  rtype uint\n//  rtype uint64\n// !rtype int\n"
  },
  {
    "path": "go/callgraph/static/static.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package static computes the call graph of a Go program containing\n// only static call edges.\npackage static\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// CallGraph computes the static call graph of the specified program.\n//\n// The resulting graph includes:\n// - all package-level functions;\n// - all methods of package-level non-parameterized non-interface types;\n// - pointer wrappers (*C).F for source-level methods C.F;\n// - and all functions reachable from them following only static calls.\n//\n// It does not consider exportedness, nor treat main packages specially.\nfunc CallGraph(prog *ssa.Program) *callgraph.Graph {\n\tcg := callgraph.New(nil)\n\n\t// Recursively follow all static calls.\n\tseen := make(map[int]bool) // node IDs already seen\n\tvar visit func(fnode *callgraph.Node)\n\tvisit = func(fnode *callgraph.Node) {\n\t\tif !seen[fnode.ID] {\n\t\t\tseen[fnode.ID] = true\n\n\t\t\tfor _, b := range fnode.Func.Blocks {\n\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\tif site, ok := instr.(ssa.CallInstruction); ok {\n\t\t\t\t\t\tif g := site.Common().StaticCallee(); g != nil {\n\t\t\t\t\t\t\tgnode := cg.CreateNode(g)\n\t\t\t\t\t\t\tcallgraph.AddEdge(fnode, site, gnode)\n\t\t\t\t\t\t\tvisit(gnode)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If we were ever to redesign this function, we should allow\n\t// the caller to provide the set of root functions and just\n\t// perform the reachability step. This would allow them to\n\t// work forwards from main entry points:\n\t//\n\t// rootNames := []string{\"init\", \"main\"}\n\t// for _, main := range ssautil.MainPackages(prog.AllPackages()) {\n\t// \tfor _, rootName := range rootNames {\n\t// \t\tvisit(cg.CreateNode(main.Func(rootName)))\n\t// \t}\n\t// }\n\t//\n\t// or to control whether to include non-exported\n\t// functions/methods, wrapper methods, and so on.\n\t// Unfortunately that's not consistent with its historical\n\t// behavior and existing tests.\n\t//\n\t// The logic below is a slight simplification and\n\t// rationalization of ssautil.AllFunctions. (Having to include\n\t// (*T).F wrapper methods is unfortunate--they are not source\n\t// functions, and if they're reachable, they'll be in the\n\t// graph--but the existing tests will break without it.)\n\n\tmethodsOf := func(T types.Type) {\n\t\tif !types.IsInterface(T) {\n\t\t\tmset := prog.MethodSets.MethodSet(T)\n\t\t\tfor method := range mset.Methods() {\n\t\t\t\tvisit(cg.CreateNode(prog.MethodValue(method)))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Start from package-level symbols.\n\tfor _, pkg := range prog.AllPackages() {\n\t\tfor _, mem := range pkg.Members {\n\t\t\tswitch mem := mem.(type) {\n\t\t\tcase *ssa.Function:\n\t\t\t\t// package-level function\n\t\t\t\tvisit(cg.CreateNode(mem))\n\n\t\t\tcase *ssa.Type:\n\t\t\t\t// methods of package-level non-interface non-parameterized types\n\t\t\t\tif !types.IsInterface(mem.Type()) {\n\t\t\t\t\tif named, ok := mem.Type().(*types.Named); ok &&\n\t\t\t\t\t\tnamed.TypeParams() == nil {\n\t\t\t\t\t\tmethodsOf(named)                   //  T\n\t\t\t\t\t\tmethodsOf(types.NewPointer(named)) // *T\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cg\n}\n"
  },
  {
    "path": "go/callgraph/static/static_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage static_test\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/static\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nconst input = `\n\n-- go.mod --\nmodule x.io\n\ngo 1.22\n\n-- p/p.go --\npackage main\n\ntype C int\nfunc (C) f()\n\ntype I interface{f()}\n\nfunc f() {\n\tp := func() {}\n\tg()\n\tp() // SSA constant propagation => static\n\n\tif unknown {\n\t\tp = h\n\t}\n\tp() // dynamic\n\n\tC(0).f()\n}\n\nfunc g() {\n\tvar i I = C(0)\n\ti.f()\n}\n\nfunc h()\n\nvar unknown bool\n\nfunc main() {\n}\n`\n\nconst genericsInput = `\n\n-- go.mod --\nmodule x.io\n\ngo 1.22\n\n-- p/p.go --\npackage p\n\ntype I interface {\n\tF()\n}\n\ntype A struct{}\n\nfunc (a A) F() {}\n\ntype B struct{}\n\nfunc (b B) F() {}\n\nfunc instantiated[X I](x X) {\n\tx.F()\n}\n\nfunc Bar() {}\n\nfunc f(h func(), a A, b B) {\n\th()\n\n\tinstantiated[A](a)\n\tinstantiated[B](b)\n}\n`\n\nfunc TestStatic(t *testing.T) {\n\tfor _, e := range []struct {\n\t\tinput string\n\t\twant  []string\n\t}{\n\t\t{input, []string{\n\t\t\t\"(*C).f -> (C).f\",\n\t\t\t\"f -> (C).f\",\n\t\t\t\"f -> f$1\",\n\t\t\t\"f -> g\",\n\t\t}},\n\t\t{genericsInput, []string{\n\t\t\t\"(*A).F -> (A).F\",\n\t\t\t\"(*B).F -> (B).F\",\n\t\t\t\"f -> instantiated[x.io/p.A]\",\n\t\t\t\"f -> instantiated[x.io/p.B]\",\n\t\t\t\"instantiated[x.io/p.A] -> (A).F\",\n\t\t\t\"instantiated[x.io/p.B] -> (B).F\",\n\t\t}},\n\t} {\n\t\tpkgs := testfiles.LoadPackages(t, txtar.Parse([]byte(e.input)), \"./p\")\n\t\tprog, _ := ssautil.Packages(pkgs, ssa.InstantiateGenerics)\n\t\tprog.Build()\n\t\tp := pkgs[0].Types\n\n\t\tcg := static.CallGraph(prog)\n\n\t\tvar edges []string\n\t\tcallgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {\n\t\t\tedges = append(edges, fmt.Sprintf(\"%s -> %s\",\n\t\t\t\te.Caller.Func.RelString(p),\n\t\t\t\te.Callee.Func.RelString(p)))\n\t\t\treturn nil\n\t\t})\n\t\tsort.Strings(edges)\n\n\t\tif !reflect.DeepEqual(edges, e.want) {\n\t\t\tt.Errorf(\"Got edges %v, want %v\", edges, e.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/util.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage callgraph\n\nimport \"golang.org/x/tools/go/ssa\"\n\n// This file provides various utilities over call graphs, such as\n// visitation and path search.\n\n// CalleesOf returns a new set containing all direct callees of the\n// caller node.\nfunc CalleesOf(caller *Node) map[*Node]bool {\n\tcallees := make(map[*Node]bool)\n\tfor _, e := range caller.Out {\n\t\tcallees[e.Callee] = true\n\t}\n\treturn callees\n}\n\n// GraphVisitEdges visits all the edges in graph g in depth-first order.\n// The edge function is called for each edge in postorder.  If it\n// returns non-nil, visitation stops and GraphVisitEdges returns that\n// value.\nfunc GraphVisitEdges(g *Graph, edge func(*Edge) error) error {\n\tseen := make(map[*Node]bool)\n\tvar visit func(n *Node) error\n\tvisit = func(n *Node) error {\n\t\tif !seen[n] {\n\t\t\tseen[n] = true\n\t\t\tfor _, e := range n.Out {\n\t\t\t\tif err := visit(e.Callee); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif err := edge(e); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\tfor _, n := range g.Nodes {\n\t\tif err := visit(n); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// PathSearch finds an arbitrary path starting at node start and\n// ending at some node for which isEnd() returns true.  On success,\n// PathSearch returns the path as an ordered list of edges; on\n// failure, it returns nil.\nfunc PathSearch(start *Node, isEnd func(*Node) bool) []*Edge {\n\tstack := make([]*Edge, 0, 32)\n\tseen := make(map[*Node]bool)\n\tvar search func(n *Node) []*Edge\n\tsearch = func(n *Node) []*Edge {\n\t\tif !seen[n] {\n\t\t\tseen[n] = true\n\t\t\tif isEnd(n) {\n\t\t\t\treturn stack\n\t\t\t}\n\t\t\tfor _, e := range n.Out {\n\t\t\t\tstack = append(stack, e) // push\n\t\t\t\tif found := search(e.Callee); found != nil {\n\t\t\t\t\treturn found\n\t\t\t\t}\n\t\t\t\tstack = stack[:len(stack)-1] // pop\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn search(start)\n}\n\n// DeleteSyntheticNodes removes from call graph g all nodes for\n// functions that do not correspond to source syntax. For historical\n// reasons, nodes for g.Root and package initializers are always\n// kept.\n//\n// As nodes are removed, edges are created to preserve the\n// reachability relation of the remaining nodes.\nfunc (g *Graph) DeleteSyntheticNodes() {\n\t// Measurements on the standard library and go.tools show that\n\t// resulting graph has ~15% fewer nodes and 4-8% fewer edges\n\t// than the input.\n\t//\n\t// Inlining a wrapper of in-degree m, out-degree n adds m*n\n\t// and removes m+n edges.  Since most wrappers are monomorphic\n\t// (n=1) this results in a slight reduction.  Polymorphic\n\t// wrappers (n>1), e.g. from embedding an interface value\n\t// inside a struct to satisfy some interface, cause an\n\t// increase in the graph, but they seem to be uncommon.\n\n\t// Hash all existing edges to avoid creating duplicates.\n\tedges := make(map[Edge]bool)\n\tfor _, cgn := range g.Nodes {\n\t\tfor _, e := range cgn.Out {\n\t\t\tedges[*e] = true\n\t\t}\n\t}\n\tfor fn, cgn := range g.Nodes {\n\t\tif cgn == g.Root || isInit(cgn.Func) || fn.Syntax() != nil {\n\t\t\tcontinue // keep\n\t\t}\n\t\tfor _, eIn := range cgn.In {\n\t\t\tfor _, eOut := range cgn.Out {\n\t\t\t\tnewEdge := Edge{eIn.Caller, eIn.Site, eOut.Callee}\n\t\t\t\tif edges[newEdge] {\n\t\t\t\t\tcontinue // don't add duplicate\n\t\t\t\t}\n\t\t\t\tAddEdge(eIn.Caller, eIn.Site, eOut.Callee)\n\t\t\t\tedges[newEdge] = true\n\t\t\t}\n\t\t}\n\t\tg.DeleteNode(cgn)\n\t}\n}\n\nfunc isInit(fn *ssa.Function) bool {\n\treturn fn.Pkg != nil && fn.Pkg.Func(\"init\") == fn\n}\n\n// DeleteNode removes node n and its edges from the graph g.\n// (NB: not efficient for batch deletion.)\nfunc (g *Graph) DeleteNode(n *Node) {\n\tn.deleteIns()\n\tn.deleteOuts()\n\tdelete(g.Nodes, n.Func)\n}\n\n// deleteIns deletes all incoming edges to n.\nfunc (n *Node) deleteIns() {\n\tfor _, e := range n.In {\n\t\tremoveOutEdge(e)\n\t}\n\tn.In = nil\n}\n\n// deleteOuts deletes all outgoing edges from n.\nfunc (n *Node) deleteOuts() {\n\tfor _, e := range n.Out {\n\t\tremoveInEdge(e)\n\t}\n\tn.Out = nil\n}\n\n// removeOutEdge removes edge.Caller's outgoing edge 'edge'.\nfunc removeOutEdge(edge *Edge) {\n\tcaller := edge.Caller\n\tn := len(caller.Out)\n\tfor i, e := range caller.Out {\n\t\tif e == edge {\n\t\t\t// Replace it with the final element and shrink the slice.\n\t\t\tcaller.Out[i] = caller.Out[n-1]\n\t\t\tcaller.Out[n-1] = nil // aid GC\n\t\t\tcaller.Out = caller.Out[:n-1]\n\t\t\treturn\n\t\t}\n\t}\n\tpanic(\"edge not found: \" + edge.String())\n}\n\n// removeInEdge removes edge.Callee's incoming edge 'edge'.\nfunc removeInEdge(edge *Edge) {\n\tcaller := edge.Callee\n\tn := len(caller.In)\n\tfor i, e := range caller.In {\n\t\tif e == edge {\n\t\t\t// Replace it with the final element and shrink the slice.\n\t\t\tcaller.In[i] = caller.In[n-1]\n\t\t\tcaller.In[n-1] = nil // aid GC\n\t\t\tcaller.In = caller.In[:n-1]\n\t\t\treturn\n\t\t}\n\t}\n\tpanic(\"edge not found: \" + edge.String())\n}\n"
  },
  {
    "path": "go/callgraph/vta/graph.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// node interface for VTA nodes.\ntype node interface {\n\tType() types.Type\n\tString() string\n}\n\n// constant node for VTA.\ntype constant struct {\n\ttyp types.Type\n}\n\nfunc (c constant) Type() types.Type {\n\treturn c.typ\n}\n\nfunc (c constant) String() string {\n\treturn fmt.Sprintf(\"Constant(%v)\", c.Type())\n}\n\n// pointer node for VTA.\ntype pointer struct {\n\ttyp *types.Pointer\n}\n\nfunc (p pointer) Type() types.Type {\n\treturn p.typ\n}\n\nfunc (p pointer) String() string {\n\treturn fmt.Sprintf(\"Pointer(%v)\", p.Type())\n}\n\n// mapKey node for VTA, modeling reachable map key types.\ntype mapKey struct {\n\ttyp types.Type\n}\n\nfunc (mk mapKey) Type() types.Type {\n\treturn mk.typ\n}\n\nfunc (mk mapKey) String() string {\n\treturn fmt.Sprintf(\"MapKey(%v)\", mk.Type())\n}\n\n// mapValue node for VTA, modeling reachable map value types.\ntype mapValue struct {\n\ttyp types.Type\n}\n\nfunc (mv mapValue) Type() types.Type {\n\treturn mv.typ\n}\n\nfunc (mv mapValue) String() string {\n\treturn fmt.Sprintf(\"MapValue(%v)\", mv.Type())\n}\n\n// sliceElem node for VTA, modeling reachable slice and array element types.\ntype sliceElem struct {\n\ttyp types.Type\n}\n\nfunc (s sliceElem) Type() types.Type {\n\treturn s.typ\n}\n\nfunc (s sliceElem) String() string {\n\treturn fmt.Sprintf(\"Slice([]%v)\", s.Type())\n}\n\n// channelElem node for VTA, modeling reachable channel element types.\ntype channelElem struct {\n\ttyp types.Type\n}\n\nfunc (c channelElem) Type() types.Type {\n\treturn c.typ\n}\n\nfunc (c channelElem) String() string {\n\treturn fmt.Sprintf(\"Channel(chan %v)\", c.Type())\n}\n\n// field node for VTA.\ntype field struct {\n\tStructType types.Type\n\tindex      int // index of the field in the struct\n}\n\nfunc (f field) Type() types.Type {\n\ts := typeparams.CoreType(f.StructType).(*types.Struct)\n\treturn s.Field(f.index).Type()\n}\n\nfunc (f field) String() string {\n\ts := typeparams.CoreType(f.StructType).(*types.Struct)\n\treturn fmt.Sprintf(\"Field(%v:%s)\", f.StructType, s.Field(f.index).Name())\n}\n\n// global node for VTA.\ntype global struct {\n\tval *ssa.Global\n}\n\nfunc (g global) Type() types.Type {\n\treturn g.val.Type()\n}\n\nfunc (g global) String() string {\n\treturn fmt.Sprintf(\"Global(%s)\", g.val.Name())\n}\n\n// local node for VTA modeling local variables\n// and function/method parameters.\ntype local struct {\n\tval ssa.Value\n}\n\nfunc (l local) Type() types.Type {\n\treturn l.val.Type()\n}\n\nfunc (l local) String() string {\n\treturn fmt.Sprintf(\"Local(%s)\", l.val.Name())\n}\n\n// indexedLocal node for VTA node. Models indexed locals\n// related to the ssa extract instructions.\ntype indexedLocal struct {\n\tval   ssa.Value\n\tindex int\n\ttyp   types.Type\n}\n\nfunc (i indexedLocal) Type() types.Type {\n\treturn i.typ\n}\n\nfunc (i indexedLocal) String() string {\n\treturn fmt.Sprintf(\"Local(%s[%d])\", i.val.Name(), i.index)\n}\n\n// function node for VTA.\ntype function struct {\n\tf *ssa.Function\n}\n\nfunc (f function) Type() types.Type {\n\treturn f.f.Type()\n}\n\nfunc (f function) String() string {\n\treturn fmt.Sprintf(\"Function(%s)\", f.f.Name())\n}\n\n// resultVar represents the result\n// variable of a function, whether\n// named or not.\ntype resultVar struct {\n\tf     *ssa.Function\n\tindex int // valid index into result var tuple\n}\n\nfunc (o resultVar) Type() types.Type {\n\treturn o.f.Signature.Results().At(o.index).Type()\n}\n\nfunc (o resultVar) String() string {\n\tv := o.f.Signature.Results().At(o.index)\n\tif n := v.Name(); n != \"\" {\n\t\treturn fmt.Sprintf(\"Return(%s[%s])\", o.f.Name(), n)\n\t}\n\treturn fmt.Sprintf(\"Return(%s[%d])\", o.f.Name(), o.index)\n}\n\n// nestedPtrInterface node represents all references and dereferences\n// of locals and globals that have a nested pointer to interface type.\n// We merge such constructs into a single node for simplicity and without\n// much precision sacrifice as such variables are rare in practice. Both\n// a and b would be represented as the same PtrInterface(I) node in:\n//\n//\ttype I interface\n//\tvar a ***I\n//\tvar b **I\ntype nestedPtrInterface struct {\n\ttyp types.Type\n}\n\nfunc (l nestedPtrInterface) Type() types.Type {\n\treturn l.typ\n}\n\nfunc (l nestedPtrInterface) String() string {\n\treturn fmt.Sprintf(\"PtrInterface(%v)\", l.typ)\n}\n\n// nestedPtrFunction node represents all references and dereferences of locals\n// and globals that have a nested pointer to function type. We merge such\n// constructs into a single node for simplicity and without much precision\n// sacrifice as such variables are rare in practice. Both a and b would be\n// represented as the same PtrFunction(func()) node in:\n//\n//\tvar a *func()\n//\tvar b **func()\ntype nestedPtrFunction struct {\n\ttyp types.Type\n}\n\nfunc (p nestedPtrFunction) Type() types.Type {\n\treturn p.typ\n}\n\nfunc (p nestedPtrFunction) String() string {\n\treturn fmt.Sprintf(\"PtrFunction(%v)\", p.typ)\n}\n\n// panicArg models types of all arguments passed to panic.\ntype panicArg struct{}\n\nfunc (p panicArg) Type() types.Type {\n\treturn nil\n}\n\nfunc (p panicArg) String() string {\n\treturn \"Panic\"\n}\n\n// recoverReturn models types of all return values of recover().\ntype recoverReturn struct{}\n\nfunc (r recoverReturn) Type() types.Type {\n\treturn nil\n}\n\nfunc (r recoverReturn) String() string {\n\treturn \"Recover\"\n}\n\ntype empty = struct{}\n\n// idx is an index representing a unique node in a vtaGraph.\ntype idx int\n\n// vtaGraph remembers for each VTA node the set of its successors.\n// Tailored for VTA, hence does not support singleton (sub)graphs.\ntype vtaGraph struct {\n\tm    []map[idx]empty // m[i] has the successors for the node with index i.\n\tidx  map[node]idx    // idx[n] is the index for the node n.\n\tnode []node          // node[i] is the node with index i.\n}\n\nfunc (g *vtaGraph) numNodes() int {\n\treturn len(g.idx)\n}\n\nfunc (g *vtaGraph) successors(x idx) iter.Seq[idx] {\n\treturn func(yield func(y idx) bool) {\n\t\tfor y := range g.m[x] {\n\t\t\tif !yield(y) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// addEdge adds an edge x->y to the graph.\nfunc (g *vtaGraph) addEdge(x, y node) {\n\tif g.idx == nil {\n\t\tg.idx = make(map[node]idx)\n\t}\n\tlookup := func(n node) idx {\n\t\ti, ok := g.idx[n]\n\t\tif !ok {\n\t\t\ti = idx(len(g.idx))\n\t\t\tg.m = append(g.m, nil)\n\t\t\tg.idx[n] = i\n\t\t\tg.node = append(g.node, n)\n\t\t}\n\t\treturn i\n\t}\n\ta := lookup(x)\n\tb := lookup(y)\n\tsuccs := g.m[a]\n\tif succs == nil {\n\t\tsuccs = make(map[idx]empty)\n\t\tg.m[a] = succs\n\t}\n\tsuccs[b] = empty{}\n}\n\n// typePropGraph builds a VTA graph for a set of `funcs` and initial\n// `callgraph` needed to establish interprocedural edges. Returns the\n// graph and a map for unique type representatives.\nfunc typePropGraph(funcs map[*ssa.Function]bool, callees calleesFunc) (*vtaGraph, *typeutil.Map) {\n\tb := builder{callees: callees}\n\tb.visit(funcs)\n\tb.callees = nil // ensure callees is not pinned by pointers to other fields of b.\n\treturn &b.graph, &b.canon\n}\n\n// Data structure responsible for linearly traversing the\n// code and building a VTA graph.\ntype builder struct {\n\tgraph   vtaGraph\n\tcallees calleesFunc // initial call graph for creating flows at unresolved call sites.\n\n\t// Specialized type map for canonicalization of types.Type.\n\t// Semantically equivalent types can have different implementations,\n\t// i.e., they are different pointer values. The map allows us to\n\t// have one unique representative. The keys are fixed and from the\n\t// client perspective they are types. The values in our case are\n\t// types too, in particular type representatives. Each value is a\n\t// pointer so this map is not expected to take much memory.\n\tcanon typeutil.Map\n}\n\nfunc (b *builder) visit(funcs map[*ssa.Function]bool) {\n\t// Add the fixed edge Panic -> Recover\n\tb.graph.addEdge(panicArg{}, recoverReturn{})\n\n\tfor f, in := range funcs {\n\t\tif in {\n\t\t\tb.fun(f)\n\t\t}\n\t}\n}\n\nfunc (b *builder) fun(f *ssa.Function) {\n\tfor _, bl := range f.Blocks {\n\t\tfor _, instr := range bl.Instrs {\n\t\t\tb.instr(instr)\n\t\t}\n\t}\n}\n\nfunc (b *builder) instr(instr ssa.Instruction) {\n\tswitch i := instr.(type) {\n\tcase *ssa.Store:\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(i.Addr), b.nodeFromVal(i.Val))\n\tcase *ssa.MakeInterface:\n\t\tb.addInFlowEdge(b.nodeFromVal(i.X), b.nodeFromVal(i))\n\tcase *ssa.MakeClosure:\n\t\tb.closure(i)\n\tcase *ssa.UnOp:\n\t\tb.unop(i)\n\tcase *ssa.Phi:\n\t\tb.phi(i)\n\tcase *ssa.ChangeInterface:\n\t\t// Although in change interface a := A(b) command a and b are\n\t\t// the same object, the only interesting flow happens when A\n\t\t// is an interface. We create flow b -> a, but omit a -> b.\n\t\t// The latter flow is not needed: if a gets assigned concrete\n\t\t// type later on, that cannot be propagated back to b as b\n\t\t// is a separate variable. The a -> b flow can happen when\n\t\t// A is a pointer to interface, but then the command is of\n\t\t// type ChangeType, handled below.\n\t\tb.addInFlowEdge(b.nodeFromVal(i.X), b.nodeFromVal(i))\n\tcase *ssa.ChangeType:\n\t\t// change type command a := A(b) results in a and b being the\n\t\t// same value. For concrete type A, there is no interesting flow.\n\t\t//\n\t\t// When A is an interface, most interface casts are handled\n\t\t// by the ChangeInterface instruction. The relevant case here is\n\t\t// when converting a pointer to an interface type. This can happen\n\t\t// when the underlying interfaces have the same method set.\n\t\t//\n\t\t//\ttype I interface{ foo() }\n\t\t//\ttype J interface{ foo() }\n\t\t//\tvar b *I\n\t\t//\ta := (*J)(b)\n\t\t//\n\t\t// When this happens we add flows between a <--> b.\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(i), b.nodeFromVal(i.X))\n\tcase *ssa.TypeAssert:\n\t\tb.tassert(i)\n\tcase *ssa.Extract:\n\t\tb.extract(i)\n\tcase *ssa.Field:\n\t\tb.field(i)\n\tcase *ssa.FieldAddr:\n\t\tb.fieldAddr(i)\n\tcase *ssa.Send:\n\t\tb.send(i)\n\tcase *ssa.Select:\n\t\tb.selekt(i)\n\tcase *ssa.Index:\n\t\tb.index(i)\n\tcase *ssa.IndexAddr:\n\t\tb.indexAddr(i)\n\tcase *ssa.Lookup:\n\t\tb.lookup(i)\n\tcase *ssa.MapUpdate:\n\t\tb.mapUpdate(i)\n\tcase *ssa.Next:\n\t\tb.next(i)\n\tcase ssa.CallInstruction:\n\t\tb.call(i)\n\tcase *ssa.Panic:\n\t\tb.panic(i)\n\tcase *ssa.Return:\n\t\tb.rtrn(i)\n\tcase *ssa.MakeChan, *ssa.MakeMap, *ssa.MakeSlice, *ssa.BinOp,\n\t\t*ssa.Alloc, *ssa.DebugRef, *ssa.Convert, *ssa.Jump, *ssa.If,\n\t\t*ssa.Slice, *ssa.SliceToArrayPointer, *ssa.Range, *ssa.RunDefers:\n\t\t// No interesting flow here.\n\t\t// Notes on individual instructions:\n\t\t// SliceToArrayPointer: t1 = slice to array pointer *[4]T <- []T (t0)\n\t\t// No interesting flow as sliceArrayElem(t1) == sliceArrayElem(t0).\n\t\treturn\n\tcase *ssa.MultiConvert:\n\t\tb.multiconvert(i)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unsupported instruction %v\\n\", instr))\n\t}\n}\n\nfunc (b *builder) unop(u *ssa.UnOp) {\n\tswitch u.Op {\n\tcase token.MUL:\n\t\t// Multiplication operator * is used here as a dereference operator.\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(u), b.nodeFromVal(u.X))\n\tcase token.ARROW:\n\t\tt := typeparams.CoreType(u.X.Type()).(*types.Chan).Elem()\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(u), channelElem{typ: t})\n\tdefault:\n\t\t// There is no interesting type flow otherwise.\n\t}\n}\n\nfunc (b *builder) phi(p *ssa.Phi) {\n\tfor _, edge := range p.Edges {\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(p), b.nodeFromVal(edge))\n\t}\n}\n\nfunc (b *builder) tassert(a *ssa.TypeAssert) {\n\tif !a.CommaOk {\n\t\tb.addInFlowEdge(b.nodeFromVal(a.X), b.nodeFromVal(a))\n\t\treturn\n\t}\n\t// The case where a is <a.AssertedType, bool> register so there\n\t// is a flow from a.X to a[0]. Here, a[0] is represented as an\n\t// indexedLocal: an entry into local tuple register a at index 0.\n\ttup := a.Type().(*types.Tuple)\n\tt := tup.At(0).Type()\n\n\tlocal := indexedLocal{val: a, typ: t, index: 0}\n\tb.addInFlowEdge(b.nodeFromVal(a.X), local)\n}\n\n// extract instruction t1 := t2[i] generates flows between t2[i]\n// and t1 where the source is indexed local representing a value\n// from tuple register t2 at index i and the target is t1.\nfunc (b *builder) extract(e *ssa.Extract) {\n\ttup := e.Tuple.Type().(*types.Tuple)\n\tt := tup.At(e.Index).Type()\n\n\tlocal := indexedLocal{val: e.Tuple, typ: t, index: e.Index}\n\tb.addInFlowAliasEdges(b.nodeFromVal(e), local)\n}\n\nfunc (b *builder) field(f *ssa.Field) {\n\tfnode := field{StructType: f.X.Type(), index: f.Field}\n\tb.addInFlowEdge(fnode, b.nodeFromVal(f))\n}\n\nfunc (b *builder) fieldAddr(f *ssa.FieldAddr) {\n\tt := typeparams.CoreType(f.X.Type()).(*types.Pointer).Elem()\n\n\t// Since we are getting pointer to a field, make a bidirectional edge.\n\tfnode := field{StructType: t, index: f.Field}\n\tb.addInFlowEdge(fnode, b.nodeFromVal(f))\n\tb.addInFlowEdge(b.nodeFromVal(f), fnode)\n}\n\nfunc (b *builder) send(s *ssa.Send) {\n\tt := typeparams.CoreType(s.Chan.Type()).(*types.Chan).Elem()\n\tb.addInFlowAliasEdges(channelElem{typ: t}, b.nodeFromVal(s.X))\n}\n\n// selekt generates flows for select statement\n//\n//\ta = select blocking/nonblocking [c_1 <- t_1, c_2 <- t_2, ..., <- o_1, <- o_2, ...]\n//\n// between receiving channel registers c_i and corresponding input register t_i. Further,\n// flows are generated between o_i and a[2 + i]. Note that a is a tuple register of type\n// <int, bool, r_1, r_2, ...> where the type of r_i is the element type of channel o_i.\nfunc (b *builder) selekt(s *ssa.Select) {\n\trecvIndex := 0\n\tfor _, state := range s.States {\n\t\tt := typeparams.CoreType(state.Chan.Type()).(*types.Chan).Elem()\n\n\t\tif state.Dir == types.SendOnly {\n\t\t\tb.addInFlowAliasEdges(channelElem{typ: t}, b.nodeFromVal(state.Send))\n\t\t} else {\n\t\t\t// state.Dir == RecvOnly by definition of select instructions.\n\t\t\ttupEntry := indexedLocal{val: s, typ: t, index: 2 + recvIndex}\n\t\t\tb.addInFlowAliasEdges(tupEntry, channelElem{typ: t})\n\t\t\trecvIndex++\n\t\t}\n\t}\n}\n\n// index instruction a := b[c] on slices creates flows between a and\n// SliceElem(t) flow where t is an interface type of c. Arrays and\n// slice elements are both modeled as SliceElem.\nfunc (b *builder) index(i *ssa.Index) {\n\tet := sliceArrayElem(i.X.Type())\n\tb.addInFlowAliasEdges(b.nodeFromVal(i), sliceElem{typ: et})\n}\n\n// indexAddr instruction a := &b[c] fetches address of a index\n// into the field so we create bidirectional flow a <-> SliceElem(t)\n// where t is an interface type of c. Arrays and slice elements are\n// both modeled as SliceElem.\nfunc (b *builder) indexAddr(i *ssa.IndexAddr) {\n\tet := sliceArrayElem(i.X.Type())\n\tb.addInFlowEdge(sliceElem{typ: et}, b.nodeFromVal(i))\n\tb.addInFlowEdge(b.nodeFromVal(i), sliceElem{typ: et})\n}\n\n// lookup handles map query commands a := m[b] where m is of type\n// map[...]V and V is an interface. It creates flows between `a`\n// and MapValue(V).\nfunc (b *builder) lookup(l *ssa.Lookup) {\n\tt, ok := l.X.Type().Underlying().(*types.Map)\n\tif !ok {\n\t\t// No interesting flows for string lookups.\n\t\treturn\n\t}\n\n\tif !l.CommaOk {\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(l), mapValue{typ: t.Elem()})\n\t} else {\n\t\ti := indexedLocal{val: l, typ: t.Elem(), index: 0}\n\t\tb.addInFlowAliasEdges(i, mapValue{typ: t.Elem()})\n\t}\n}\n\n// mapUpdate handles map update commands m[b] = a where m is of type\n// map[K]V and K and V are interfaces. It creates flows between `a`\n// and MapValue(V) as well as between MapKey(K) and `b`.\nfunc (b *builder) mapUpdate(u *ssa.MapUpdate) {\n\tt, ok := u.Map.Type().Underlying().(*types.Map)\n\tif !ok {\n\t\t// No interesting flows for string updates.\n\t\treturn\n\t}\n\n\tb.addInFlowAliasEdges(mapKey{typ: t.Key()}, b.nodeFromVal(u.Key))\n\tb.addInFlowAliasEdges(mapValue{typ: t.Elem()}, b.nodeFromVal(u.Value))\n}\n\n// next instruction <ok, key, value> := next r, where r\n// is a range over map or string generates flow between\n// key and MapKey as well value and MapValue nodes.\nfunc (b *builder) next(n *ssa.Next) {\n\tif n.IsString {\n\t\treturn\n\t}\n\ttup := n.Type().(*types.Tuple)\n\tkt := tup.At(1).Type()\n\tvt := tup.At(2).Type()\n\n\tb.addInFlowAliasEdges(indexedLocal{val: n, typ: kt, index: 1}, mapKey{typ: kt})\n\tb.addInFlowAliasEdges(indexedLocal{val: n, typ: vt, index: 2}, mapValue{typ: vt})\n}\n\n// addInFlowAliasEdges adds an edge r -> l to b.graph if l is a node that can\n// have an inflow, i.e., a node that represents an interface or an unresolved\n// function value. Similarly for the edge l -> r with an additional condition\n// of that l and r can potentially alias.\nfunc (b *builder) addInFlowAliasEdges(l, r node) {\n\tb.addInFlowEdge(r, l)\n\n\tif canAlias(l, r) {\n\t\tb.addInFlowEdge(l, r)\n\t}\n}\n\nfunc (b *builder) closure(c *ssa.MakeClosure) {\n\tf := c.Fn.(*ssa.Function)\n\tb.addInFlowEdge(function{f: f}, b.nodeFromVal(c))\n\n\tfor i, fv := range f.FreeVars {\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(fv), b.nodeFromVal(c.Bindings[i]))\n\t}\n}\n\n// panic creates a flow from arguments to panic instructions to return\n// registers of all recover statements in the program. Introduces a\n// global panic node Panic and\n//  1. for every panic statement p: add p -> Panic\n//  2. for every recover statement r: add Panic -> r (handled in call)\n//\n// TODO(zpavlinovic): improve precision by explicitly modeling how panic\n// values flow from callees to callers and into deferred recover instructions.\nfunc (b *builder) panic(p *ssa.Panic) {\n\t// Panics often have, for instance, strings as arguments which do\n\t// not create interesting flows.\n\tif !canHaveMethods(p.X.Type()) {\n\t\treturn\n\t}\n\n\tb.addInFlowEdge(b.nodeFromVal(p.X), panicArg{})\n}\n\n// call adds flows between arguments/parameters and return values/registers\n// for both static and dynamic calls, as well as go and defer calls.\nfunc (b *builder) call(c ssa.CallInstruction) {\n\t// When c is r := recover() call register instruction, we add Recover -> r.\n\tif bf, ok := c.Common().Value.(*ssa.Builtin); ok && bf.Name() == \"recover\" {\n\t\tif v, ok := c.(ssa.Value); ok {\n\t\t\tb.addInFlowEdge(recoverReturn{}, b.nodeFromVal(v))\n\t\t}\n\t\treturn\n\t}\n\n\tfor f := range siteCallees(c, b.callees) {\n\t\taddArgumentFlows(b, c, f)\n\n\t\tsite, ok := c.(ssa.Value)\n\t\tif !ok {\n\t\t\tcontinue // go or defer\n\t\t}\n\n\t\tresults := f.Signature.Results()\n\t\tif results.Len() == 1 {\n\t\t\t// When there is only one return value, the destination register does not\n\t\t\t// have a tuple type.\n\t\t\tb.addInFlowEdge(resultVar{f: f, index: 0}, b.nodeFromVal(site))\n\t\t} else {\n\t\t\ttup := site.Type().(*types.Tuple)\n\t\t\tfor i := 0; i < results.Len(); i++ {\n\t\t\t\tlocal := indexedLocal{val: site, typ: tup.At(i).Type(), index: i}\n\t\t\t\tb.addInFlowEdge(resultVar{f: f, index: i}, local)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) {\n\t// When f has no parameters (including receiver), there is no type\n\t// flow here. Also, f's body and parameters might be missing, such\n\t// as when vta is used within the golang.org/x/tools/go/analysis\n\t// framework (see github.com/golang/go/issues/50670).\n\tif len(f.Params) == 0 {\n\t\treturn\n\t}\n\tcc := c.Common()\n\tif cc.Method != nil {\n\t\t// In principle we don't add interprocedural flows for receiver\n\t\t// objects. At a call site, the receiver object is interface\n\t\t// while the callee object is concrete. The flow from interface\n\t\t// to concrete type in general does not make sense. The exception\n\t\t// is when the concrete type is a named function type (see #57756).\n\t\t//\n\t\t// The flow other way around would bake in information from the\n\t\t// initial call graph.\n\t\tif isFunction(f.Params[0].Type()) {\n\t\t\tb.addInFlowEdge(b.nodeFromVal(cc.Value), b.nodeFromVal(f.Params[0]))\n\t\t}\n\t}\n\n\toffset := 0\n\tif cc.Method != nil {\n\t\toffset = 1\n\t}\n\tfor i, v := range cc.Args {\n\t\t// Parameters of f might not be available, as in the case\n\t\t// when vta is used within the golang.org/x/tools/go/analysis\n\t\t// framework (see github.com/golang/go/issues/50670).\n\t\t//\n\t\t// TODO: investigate other cases of missing body and parameters\n\t\tif len(f.Params) <= i+offset {\n\t\t\treturn\n\t\t}\n\t\tb.addInFlowAliasEdges(b.nodeFromVal(f.Params[i+offset]), b.nodeFromVal(v))\n\t}\n}\n\n// rtrn creates flow edges from the operands of the return\n// statement to the result variables of the enclosing function.\nfunc (b *builder) rtrn(r *ssa.Return) {\n\tfor i, rs := range r.Results {\n\t\tb.addInFlowEdge(b.nodeFromVal(rs), resultVar{f: r.Parent(), index: i})\n\t}\n}\n\nfunc (b *builder) multiconvert(c *ssa.MultiConvert) {\n\t// TODO(zpavlinovic): decide what to do on MultiConvert long term.\n\t// TODO(zpavlinovic): add unit tests.\n\ttypeSetOf := func(typ types.Type) []*types.Term {\n\t\t// This is a adaptation of x/exp/typeparams.NormalTerms which x/tools cannot depend on.\n\t\tvar terms []*types.Term\n\t\tvar err error\n\t\tswitch typ := types.Unalias(typ).(type) {\n\t\tcase *types.TypeParam:\n\t\t\tterms, err = typeparams.StructuralTerms(typ)\n\t\tcase *types.Union:\n\t\t\tterms, err = typeparams.UnionTermSet(typ)\n\t\tcase *types.Interface:\n\t\t\tterms, err = typeparams.InterfaceTermSet(typ)\n\t\tdefault:\n\t\t\t// Common case.\n\t\t\t// Specializing the len=1 case to avoid a slice\n\t\t\t// had no measurable space/time benefit.\n\t\t\tterms = []*types.Term{types.NewTerm(false, typ)}\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\treturn terms\n\t}\n\t// isValuePreserving returns true if a conversion from ut_src to\n\t// ut_dst is value-preserving, i.e. just a change of type.\n\t// Precondition: neither argument is a named or alias type.\n\tisValuePreserving := func(ut_src, ut_dst types.Type) bool {\n\t\t// Identical underlying types?\n\t\tif types.IdenticalIgnoreTags(ut_dst, ut_src) {\n\t\t\treturn true\n\t\t}\n\n\t\tswitch ut_dst.(type) {\n\t\tcase *types.Chan:\n\t\t\t// Conversion between channel types?\n\t\t\t_, ok := ut_src.(*types.Chan)\n\t\t\treturn ok\n\n\t\tcase *types.Pointer:\n\t\t\t// Conversion between pointers with identical base types?\n\t\t\t_, ok := ut_src.(*types.Pointer)\n\t\t\treturn ok\n\t\t}\n\t\treturn false\n\t}\n\tdst_terms := typeSetOf(c.Type())\n\tsrc_terms := typeSetOf(c.X.Type())\n\tfor _, s := range src_terms {\n\t\tus := s.Type().Underlying()\n\t\tfor _, d := range dst_terms {\n\t\t\tud := d.Type().Underlying()\n\t\t\tif isValuePreserving(us, ud) {\n\t\t\t\t// This is equivalent to a ChangeType.\n\t\t\t\tb.addInFlowAliasEdges(b.nodeFromVal(c), b.nodeFromVal(c.X))\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// This is equivalent to either: SliceToArrayPointer,,\n\t\t\t// SliceToArrayPointer+Deref, Size 0 Array constant, or a Convert.\n\t\t}\n\t}\n}\n\n// addInFlowEdge adds s -> d to g if d is node that can have an inflow, i.e., a node\n// that represents an interface or an unresolved function value. Otherwise, there\n// is no interesting type flow so the edge is omitted.\nfunc (b *builder) addInFlowEdge(s, d node) {\n\tif hasInFlow(d) {\n\t\tb.graph.addEdge(b.representative(s), b.representative(d))\n\t}\n}\n\n// Creates const, pointer, global, func, and local nodes based on register instructions.\nfunc (b *builder) nodeFromVal(val ssa.Value) node {\n\tif p, ok := types.Unalias(val.Type()).(*types.Pointer); ok && !types.IsInterface(p.Elem()) && !isFunction(p.Elem()) {\n\t\t// Nested pointer to interfaces are modeled as a special\n\t\t// nestedPtrInterface node.\n\t\tif i := interfaceUnderPtr(p.Elem()); i != nil {\n\t\t\treturn nestedPtrInterface{typ: i}\n\t\t}\n\t\t// The same goes for nested function types.\n\t\tif f := functionUnderPtr(p.Elem()); f != nil {\n\t\t\treturn nestedPtrFunction{typ: f}\n\t\t}\n\t\treturn pointer{typ: p}\n\t}\n\n\tswitch v := val.(type) {\n\tcase *ssa.Const:\n\t\treturn constant{typ: val.Type()}\n\tcase *ssa.Global:\n\t\treturn global{val: v}\n\tcase *ssa.Function:\n\t\treturn function{f: v}\n\tcase *ssa.Parameter, *ssa.FreeVar, ssa.Instruction:\n\t\t// ssa.Param, ssa.FreeVar, and a specific set of \"register\" instructions,\n\t\t// satisfying the ssa.Value interface, can serve as local variables.\n\t\treturn local{val: v}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unsupported value %v in node creation\", val))\n\t}\n}\n\n// representative returns a unique representative for node `n`. Since\n// semantically equivalent types can have different implementations,\n// this method guarantees the same implementation is always used.\nfunc (b *builder) representative(n node) node {\n\tif n.Type() == nil {\n\t\t// panicArg and recoverReturn do not have\n\t\t// types and are unique by definition.\n\t\treturn n\n\t}\n\tt := canonicalize(n.Type(), &b.canon)\n\n\tswitch i := n.(type) {\n\tcase constant:\n\t\treturn constant{typ: t}\n\tcase pointer:\n\t\treturn pointer{typ: t.(*types.Pointer)}\n\tcase sliceElem:\n\t\treturn sliceElem{typ: t}\n\tcase mapKey:\n\t\treturn mapKey{typ: t}\n\tcase mapValue:\n\t\treturn mapValue{typ: t}\n\tcase channelElem:\n\t\treturn channelElem{typ: t}\n\tcase nestedPtrInterface:\n\t\treturn nestedPtrInterface{typ: t}\n\tcase nestedPtrFunction:\n\t\treturn nestedPtrFunction{typ: t}\n\tcase field:\n\t\treturn field{StructType: canonicalize(i.StructType, &b.canon), index: i.index}\n\tcase indexedLocal:\n\t\treturn indexedLocal{typ: t, val: i.val, index: i.index}\n\tcase local, global, panicArg, recoverReturn, function, resultVar:\n\t\treturn n\n\tdefault:\n\t\tpanic(fmt.Errorf(\"canonicalizing unrecognized node %v\", n))\n\t}\n}\n\n// canonicalize returns a type representative of `t` unique subject\n// to type map `canon`.\nfunc canonicalize(t types.Type, canon *typeutil.Map) types.Type {\n\trep := canon.At(t)\n\tif rep != nil {\n\t\treturn rep.(types.Type)\n\t}\n\tcanon.Set(t, t)\n\treturn t\n}\n"
  },
  {
    "path": "go/callgraph/vta/graph_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph/cha\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\nfunc TestNodeInterface(t *testing.T) {\n\t// Since ssa package does not allow explicit creation of ssa\n\t// values, we use the values from the program testdata/src/simple.go:\n\t//   - basic type int\n\t//   - struct X with two int fields a and b\n\t//   - global variable \"gl\"\n\t//   - \"foo\" function\n\t//   - \"main\" function and its\n\t//   - first register instruction t0 := *gl\n\tprog, _, err := testProg(t, \"testdata/src/simple.go\", ssa.BuilderMode(0))\n\tif err != nil {\n\t\tt.Fatalf(\"couldn't load testdata/src/simple.go program: %v\", err)\n\t}\n\n\tpkg := prog.AllPackages()[0]\n\tmain := pkg.Func(\"main\")\n\tfoo := pkg.Func(\"foo\")\n\treg := firstRegInstr(main) // t0 := *gl\n\tX := pkg.Type(\"X\").Type()\n\tgl := pkg.Var(\"gl\")\n\tglPtrType, ok := types.Unalias(gl.Type()).(*types.Pointer)\n\tif !ok {\n\t\tt.Fatalf(\"could not cast gl variable to pointer type\")\n\t}\n\tbint := glPtrType.Elem()\n\n\tpint := types.NewPointer(bint)\n\ti := types.NewInterface(nil, nil)\n\n\tvoidFunc := main.Signature.Underlying()\n\n\tfor _, test := range []struct {\n\t\tn node\n\t\ts string\n\t\tt types.Type\n\t}{\n\t\t{constant{typ: bint}, \"Constant(int)\", bint},\n\t\t{pointer{typ: pint}, \"Pointer(*int)\", pint},\n\t\t{mapKey{typ: bint}, \"MapKey(int)\", bint},\n\t\t{mapValue{typ: pint}, \"MapValue(*int)\", pint},\n\t\t{sliceElem{typ: bint}, \"Slice([]int)\", bint},\n\t\t{channelElem{typ: pint}, \"Channel(chan *int)\", pint},\n\t\t{field{StructType: X, index: 0}, \"Field(testdata.X:a)\", bint},\n\t\t{field{StructType: X, index: 1}, \"Field(testdata.X:b)\", bint},\n\t\t{global{val: gl}, \"Global(gl)\", gl.Type()},\n\t\t{local{val: reg}, \"Local(t0)\", bint},\n\t\t{indexedLocal{val: reg, typ: X, index: 0}, \"Local(t0[0])\", X},\n\t\t{function{f: main}, \"Function(main)\", voidFunc},\n\t\t{resultVar{f: foo, index: 0}, \"Return(foo[r])\", bint},\n\t\t{nestedPtrInterface{typ: i}, \"PtrInterface(interface{})\", i},\n\t\t{nestedPtrFunction{typ: voidFunc}, \"PtrFunction(func())\", voidFunc},\n\t\t{panicArg{}, \"Panic\", nil},\n\t\t{recoverReturn{}, \"Recover\", nil},\n\t} {\n\t\tif removeModulePrefix(test.s) != removeModulePrefix(test.n.String()) {\n\t\t\tt.Errorf(\"want %s; got %s\", removeModulePrefix(test.s), removeModulePrefix(test.n.String()))\n\t\t}\n\t\tif test.t != test.n.Type() {\n\t\t\tt.Errorf(\"want %s; got %s\", test.t, test.n.Type())\n\t\t}\n\t}\n}\n\n// removeModulePrefix removes the \"x.io/\" module name prefix throughout s.\n// (It is added by testProg.)\nfunc removeModulePrefix(s string) string {\n\treturn strings.ReplaceAll(s, \"x.io/\", \"\")\n}\n\nfunc TestVtaGraph(t *testing.T) {\n\t// Get the basic type int from a real program.\n\tprog, _, err := testProg(t, \"testdata/src/simple.go\", ssa.BuilderMode(0))\n\tif err != nil {\n\t\tt.Fatalf(\"couldn't load testdata/src/simple.go program: %v\", err)\n\t}\n\n\tglPtrType, ok := prog.AllPackages()[0].Var(\"gl\").Type().(*types.Pointer)\n\tif !ok {\n\t\tt.Fatalf(\"could not cast gl variable to pointer type\")\n\t}\n\tbint := glPtrType.Elem()\n\n\tn1 := constant{typ: bint}\n\tn2 := pointer{typ: types.NewPointer(bint)}\n\tn3 := mapKey{typ: types.NewMap(bint, bint)}\n\tn4 := mapValue{typ: types.NewMap(bint, bint)}\n\n\t// Create graph\n\t//   n1   n2\n\t//    \\  / /\n\t//     n3 /\n\t//     | /\n\t//     n4\n\tvar g vtaGraph\n\tg.addEdge(n1, n3)\n\tg.addEdge(n2, n3)\n\tg.addEdge(n3, n4)\n\tg.addEdge(n2, n4)\n\t// for checking duplicates\n\tg.addEdge(n1, n3)\n\n\twant := vtaGraph{\n\t\tm: []map[idx]empty{\n\t\t\tmap[idx]empty{1: empty{}},\n\t\t\tmap[idx]empty{3: empty{}},\n\t\t\tmap[idx]empty{1: empty{}, 3: empty{}},\n\t\t\tnil,\n\t\t},\n\t\tidx: map[node]idx{\n\t\t\tn1: 0,\n\t\t\tn3: 1,\n\t\t\tn2: 2,\n\t\t\tn4: 3,\n\t\t},\n\t\tnode: []node{n1, n3, n2, n4},\n\t}\n\n\tif !reflect.DeepEqual(want, g) {\n\t\tt.Errorf(\"want %v; got %v\", want, g)\n\t}\n\n\tfor _, test := range []struct {\n\t\tn node\n\t\tl int\n\t}{\n\t\t{n1, 1},\n\t\t{n2, 2},\n\t\t{n3, 1},\n\t\t{n4, 0},\n\t} {\n\t\tsl := 0\n\t\tfor range g.successors(g.idx[test.n]) {\n\t\t\tsl++\n\t\t}\n\t\tif sl != test.l {\n\t\t\tt.Errorf(\"want %d successors; got %d\", test.l, sl)\n\t\t}\n\t}\n}\n\n// vtaGraphStr stringifies vtaGraph into a list of strings\n// where each string represents an edge set of the format\n// node -> succ_1, ..., succ_n. succ_1, ..., succ_n are\n// sorted in alphabetical order.\nfunc vtaGraphStr(g *vtaGraph) []string {\n\tvar vgs []string\n\tfor n := 0; n < g.numNodes(); n++ {\n\t\tvar succStr []string\n\t\tfor s := range g.successors(idx(n)) {\n\t\t\tsuccStr = append(succStr, g.node[s].String())\n\t\t}\n\n\t\tsort.Strings(succStr)\n\t\tentry := fmt.Sprintf(\"%v -> %v\", g.node[n].String(), strings.Join(succStr, \", \"))\n\t\tvgs = append(vgs, removeModulePrefix(entry))\n\t}\n\treturn vgs\n}\n\n// setdiff returns the set difference of `X-Y` or {s | s ∈ X, s ∉ Y }.\nfunc setdiff(X, Y []string) []string {\n\ty := make(map[string]bool)\n\tvar delta []string\n\tfor _, s := range Y {\n\t\ty[s] = true\n\t}\n\n\tfor _, s := range X {\n\t\tif _, ok := y[s]; !ok {\n\t\t\tdelta = append(delta, s)\n\t\t}\n\t}\n\tsort.Strings(delta)\n\treturn delta\n}\n\nfunc TestVTAGraphConstruction(t *testing.T) {\n\tfor _, file := range []string{\n\t\t\"testdata/src/store.go\",\n\t\t\"testdata/src/phi.go\",\n\t\t\"testdata/src/type_conversions.go\",\n\t\t\"testdata/src/type_assertions.go\",\n\t\t\"testdata/src/fields.go\",\n\t\t\"testdata/src/node_uniqueness.go\",\n\t\t\"testdata/src/store_load_alias.go\",\n\t\t\"testdata/src/phi_alias.go\",\n\t\t\"testdata/src/channels.go\",\n\t\t\"testdata/src/generic_channels.go\",\n\t\t\"testdata/src/select.go\",\n\t\t\"testdata/src/stores_arrays.go\",\n\t\t\"testdata/src/maps.go\",\n\t\t\"testdata/src/ranges.go\",\n\t\t\"testdata/src/closures.go\",\n\t\t\"testdata/src/function_alias.go\",\n\t\t\"testdata/src/static_calls.go\",\n\t\t\"testdata/src/dynamic_calls.go\",\n\t\t\"testdata/src/returns.go\",\n\t\t\"testdata/src/panic.go\",\n\t} {\n\t\tt.Run(file, func(t *testing.T) {\n\t\t\tprog, want, err := testProg(t, file, ssa.BuilderMode(0))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"couldn't load test file '%s': %s\", file, err)\n\t\t\t}\n\t\t\tif len(want) == 0 {\n\t\t\t\tt.Fatalf(\"couldn't find want in `%s`\", file)\n\t\t\t}\n\n\t\t\tfs := ssautil.AllFunctions(prog)\n\n\t\t\t// First test propagation with lazy-CHA initial call graph.\n\t\t\tg, _ := typePropGraph(fs, makeCalleesFunc(fs, nil))\n\t\t\tgot := vtaGraphStr(g)\n\t\t\tif diff := setdiff(want, got); len(diff) > 0 {\n\t\t\t\tt.Errorf(\"`%s`: want superset of %v;\\n got %v\\ndiff: %v\", file, want, got, diff)\n\t\t\t}\n\n\t\t\t// Repeat the test with explicit CHA initial call graph.\n\t\t\tg, _ = typePropGraph(fs, makeCalleesFunc(fs, cha.CallGraph(prog)))\n\t\t\tgot = vtaGraphStr(g)\n\t\t\tif diff := setdiff(want, got); len(diff) > 0 {\n\t\t\t\tt.Errorf(\"`%s`: want superset of %v;\\n got %v\\ndiff: %v\", file, want, got, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/helpers_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// want extracts the contents of the first comment\n// section starting with \"WANT:\\n\". The returned\n// content is split into lines without // prefix.\nfunc want(f *ast.File) []string {\n\tfor _, c := range f.Comments {\n\t\ttext := strings.TrimSpace(c.Text())\n\t\tif t, ok := strings.CutPrefix(text, \"WANT:\\n\"); ok {\n\t\t\treturn strings.Split(t, \"\\n\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// testProg returns an ssa representation of a program at\n// `path`, assumed to define package \"testdata,\" and the\n// test want result as list of strings.\nfunc testProg(t testing.TB, path string, mode ssa.BuilderMode) (*ssa.Program, []string, error) {\n\t// Set debug mode to exercise DebugRef instructions.\n\tpkg, ssapkg := loadFile(t, path, mode|ssa.GlobalDebug)\n\treturn ssapkg.Prog, want(pkg.Syntax[0]), nil\n}\n\n// loadFile loads a built SSA package for a single-file package \"x.io/testdata\".\n// (Ideally all uses would be converted over to txtar files with explicit go.mod files.)\n//\n// TODO(adonovan): factor with similar loadFile in cha/cha_test.go.\nfunc loadFile(t testing.TB, filename string, mode ssa.BuilderMode) (*packages.Package, *ssa.Package) {\n\ttestenv.NeedsGoPackages(t)\n\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdir := t.TempDir()\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadAllSyntax,\n\t\tDir:  dir,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(dir, \"go.mod\"): fmt.Appendf(nil, \"module x.io\\ngo 1.%d\", testenv.Go1Point()),\n\n\t\t\tfilepath.Join(dir, \"testdata\", filepath.Base(filename)): data,\n\t\t},\n\t}\n\tpkgs, err := packages.Load(cfg, \"./testdata\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"got %d packages, want 1\", len(pkgs))\n\t}\n\tif len(pkgs[0].Syntax) != 1 {\n\t\tt.Fatalf(\"got %d files, want 1\", len(pkgs[0].Syntax))\n\t}\n\tif num := packages.PrintErrors(pkgs); num > 0 {\n\t\tt.Fatalf(\"packages contained %d errors\", num)\n\t}\n\tprog, ssapkgs := ssautil.Packages(pkgs, mode)\n\tprog.Build()\n\treturn pkgs[0], ssapkgs[0]\n}\n\nfunc firstRegInstr(f *ssa.Function) ssa.Value {\n\tfor _, b := range f.Blocks {\n\t\tfor _, i := range b.Instrs {\n\t\t\tif v, ok := i.(ssa.Value); ok {\n\t\t\t\treturn v\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// funcName returns a name of the function `f`\n// prefixed with the name of the receiver type.\nfunc funcName(f *ssa.Function) string {\n\trecv := f.Signature.Recv()\n\tif recv == nil {\n\t\treturn f.Name()\n\t}\n\ttp := recv.Type().String()\n\treturn tp[strings.LastIndex(tp, \".\")+1:] + \".\" + f.Name()\n}\n\n// callGraphStr stringifes `g` into a list of strings where\n// each entry is of the form\n//\n//\tf: cs1 -> f1, f2, ...; ...; csw -> fx, fy, ...\n//\n// f is a function, cs1, ..., csw are call sites in f, and\n// f1, f2, ..., fx, fy, ... are the resolved callees.\nfunc callGraphStr(g *callgraph.Graph) []string {\n\tvar gs []string\n\tfor f, n := range g.Nodes {\n\t\tc := make(map[string][]string)\n\t\tfor _, edge := range n.Out {\n\t\t\tcs := edge.Site.String() // TODO(adonovan): handle Site=nil gracefully\n\t\t\tc[cs] = append(c[cs], funcName(edge.Callee.Func))\n\t\t}\n\n\t\tvar cs []string\n\t\tfor site, fs := range c {\n\t\t\tsort.Strings(fs)\n\t\t\tentry := fmt.Sprintf(\"%v -> %v\", site, strings.Join(fs, \", \"))\n\t\t\tcs = append(cs, entry)\n\t\t}\n\n\t\tsort.Strings(cs)\n\t\tentry := fmt.Sprintf(\"%v: %v\", funcName(f), strings.Join(cs, \"; \"))\n\t\tgs = append(gs, removeModulePrefix(entry))\n\t}\n\treturn gs\n}\n\n// Logs the functions of prog to t.\nfunc logFns(t testing.TB, prog *ssa.Program) {\n\tfor fn := range ssautil.AllFunctions(prog) {\n\t\tvar buf bytes.Buffer\n\t\tfn.WriteTo(&buf)\n\t\tt.Log(buf.String())\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/initial.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/callgraph/internal/chautil\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// calleesFunc abstracts call graph in one direction,\n// from call sites to callees.\ntype calleesFunc func(ssa.CallInstruction) []*ssa.Function\n\n// makeCalleesFunc returns an initial call graph for vta as a\n// calleesFunc. If c is not nil, returns callees as given by c.\n// Otherwise, it returns chautil.LazyCallees over fs.\nfunc makeCalleesFunc(fs map[*ssa.Function]bool, c *callgraph.Graph) calleesFunc {\n\tif c == nil {\n\t\treturn chautil.LazyCallees(fs)\n\t}\n\treturn func(call ssa.CallInstruction) []*ssa.Function {\n\t\tnode := c.Nodes[call.Parent()]\n\t\tif node == nil {\n\t\t\treturn nil\n\t\t}\n\t\tvar cs []*ssa.Function\n\t\tfor _, edge := range node.Out {\n\t\t\tif edge.Site == call {\n\t\t\t\tcs = append(cs, edge.Callee.Func)\n\t\t\t}\n\t\t}\n\t\treturn cs\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/bits.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage trie\n\nimport (\n\t\"math/bits\"\n)\n\n// This file contains bit twiddling functions for Patricia tries.\n// Consult this paper for details.\n//   C. Okasaki and A. Gill, “Fast mergeable integer maps,” in ACM SIGPLAN\n//   Workshop on ML, September 1998, pp. 77–86.\n\n// key is a key in a Map.\ntype key uint64\n\n// bitpos is the position of a bit. A position is represented by having a 1\n// bit in that position.\n// Examples:\n//   - 0b0010 is the position of the `1` bit in 2.\n//     It is the 3rd most specific bit position in big endian encoding\n//     (0b0 and 0b1 are more specific).\n//   - 0b0100 is the position of the bit that 1 and 5 disagree on.\n//   - 0b0 is a special value indicating that all bit agree.\ntype bitpos uint64\n\n// prefixes represent a set of keys that all agree with the\n// prefix up to a bitpos m.\n//\n// The value for a prefix is determined by the mask(k, m) function.\n// (See mask for details on the values.)\n// A `p` prefix for position `m` matches a key `k` iff mask(k, m) == p.\n// A prefix always mask(p, m) == p.\n//\n// A key is its own prefix for the bit position 64,\n// e.g. seeing a `prefix(key)` is not a problem.\n//\n// Prefixes should never be turned into keys.\ntype prefix uint64\n\n// branchingBit returns the position of the first bit in `x` and `y`\n// that are not equal.\nfunc branchingBit(x, y prefix) bitpos {\n\tp := x ^ y\n\tif p == 0 {\n\t\treturn 0\n\t}\n\treturn bitpos(1) << uint(bits.Len64(uint64(p))-1) // uint conversion needed for go1.12\n}\n\n// zeroBit returns true if k has a 0 bit at position `b`.\nfunc zeroBit(k prefix, b bitpos) bool {\n\treturn (uint64(k) & uint64(b)) == 0\n}\n\n// matchPrefix returns true if a prefix k matches a prefix p up to position `b`.\nfunc matchPrefix(k prefix, p prefix, b bitpos) bool {\n\treturn mask(k, b) == p\n}\n\n// mask returns a prefix of `k` with all bits after and including `b` zeroed out.\n//\n// In big endian encoding, this value is the [64-(m-1)] most significant bits of k\n// followed by a `0` bit at bitpos m, followed m-1 `1` bits.\n// Examples:\n//\n//\tprefix(0b1011) for a bitpos 0b0100 represents the keys:\n//\t  0b1000, 0b1001, 0b1010, 0b1011, 0b1100, 0b1101, 0b1110, 0b1111\n//\n// This mask function has the property that if matchPrefix(k, p, b), then\n// k <= p if and only if zeroBit(k, m). This induces binary search tree tries.\n// See Okasaki & Gill for more details about this choice of mask function.\n//\n// mask is idempotent for a given `b`, i.e. mask(mask(p, b), b) == mask(p,b).\nfunc mask(k prefix, b bitpos) prefix {\n\treturn prefix((uint64(k) | (uint64(b) - 1)) & (^uint64(b)))\n}\n\n// ord returns true if m comes before n in the bit ordering.\nfunc ord(m, n bitpos) bool {\n\treturn m > n // big endian encoding\n}\n\n// prefixesOverlap returns true if there is some key a prefix `p` for bitpos `m`\n// can hold that can also be held by a prefix `q` for some bitpos `n`.\n//\n// This is equivalent to:\n//\n//\tm ==n && p == q,\n//\thigher(m, n) && matchPrefix(q, p, m), or\n//\thigher(n, m) && matchPrefix(p, q, n)\nfunc prefixesOverlap(p prefix, m bitpos, q prefix, n bitpos) bool {\n\tfbb := n\n\tif ord(m, n) {\n\t\tfbb = m\n\t}\n\treturn mask(p, fbb) == mask(q, fbb)\n\t// Lemma:\n\t//   mask(p, fbb) == mask(q, fbb)\n\t// iff\n\t//   m > n && matchPrefix(q, p, m) or  (note: big endian encoding)\n\t//   m < n && matchPrefix(p, q, n) or  (note: big endian encoding)\n\t//   m ==n && p == q\n\t// Quick-n-dirty proof:\n\t// p == mask(p0, m) for some p0 by precondition.\n\t// q == mask(q0, n) for some q0 by precondition.\n\t// So mask(p, m) == p and mask(q, n) == q as mask(*, n') is idempotent.\n\t//\n\t// [=> proof]\n\t// Suppose mask(p, fbb) == mask(q, fbb).\n\t// if m ==n, p == mask(p, m) == mask(p, fbb) == mask(q, fbb) == mask(q, n) == q\n\t// if m > n, fbb = firstBranchBit(m, n) = m (big endian).\n\t//   p == mask(p, m) == mask(p, fbb) == mask(q, fbb) == mask(q, m)\n\t//   so mask(q, m) == p or matchPrefix(q, p, m)\n\t// if m < n, is symmetric to the above.\n\t//\n\t// [<= proof]\n\t// case m ==n && p == q. Then mask(p, fbb) == mask(q, fbb)\n\t//\n\t// case m > n && matchPrefix(q, p, m).\n\t// fbb == firstBranchBit(m, n) == m (by m>n).\n\t// mask(q, fbb) == mask(q, m) == p == mask(p, m) == mask(p, fbb)\n\t//\n\t// case m < n && matchPrefix(p, q, n) is symmetric.\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/bits_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.13\n\npackage trie\n\nimport (\n\t\"math/rand\"\n\t\"testing\"\n)\n\nfunc TestMask(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tp    prefix\n\t\tb    bitpos\n\t\twant prefix\n\t}{\n\t\t{\n\t\t\tp:    0b00001000,\n\t\t\tb:    0b00000100,\n\t\t\twant: 0b00001011,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00000000,\n\t\t\twant: ^prefix(0),\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00000001,\n\t\t\twant: 0b01011010,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00000010,\n\t\t\twant: 0b01011001,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00000100,\n\t\t\twant: 0b01011011,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00001000,\n\t\t\twant: 0b01010111,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00010000,\n\t\t\twant: 0b01001111,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b00100000,\n\t\t\twant: 0b01011111,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b01000000,\n\t\t\twant: 0b00111111,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b01000000,\n\t\t\twant: 0b00111111,\n\t\t}, {\n\t\t\tp:    0b01011011,\n\t\t\tb:    0b10000000,\n\t\t\twant: 0b01111111,\n\t\t},\n\t} {\n\t\tif got := mask(c.p, c.b); got != c.want {\n\t\t\tt.Errorf(\"mask(%#b,%#b) got %#b. want %#b\", c.p, c.b, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestMaskImpotent(t *testing.T) {\n\t// test mask(mask(p, b), b) == mask(p,b)\n\tfor _, p := range []prefix{\n\t\t0b0, 0b1, 0b100, ^prefix(0b0), ^prefix(0b10),\n\t} {\n\t\tfor _, b := range []bitpos{\n\t\t\t0, 0b1, 1 << 2, 1 << 63,\n\t\t} {\n\t\t\tonce := mask(p, b)\n\t\t\ttwice := mask(once, b)\n\t\t\tif once != twice {\n\t\t\t\tt.Errorf(\"mask(mask(%#b,%#b), %#b) != mask(%#b,%#b) got %#b. want %#b\",\n\t\t\t\t\tp, b, b, p, b, twice, once)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMatchPrefix(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tk prefix\n\t\tp prefix\n\t\tb bitpos\n\t}{\n\t\t{\n\t\t\tk: 0b1000,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1001,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1010,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1011,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1100,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1101,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1110,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1111,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t},\n\t} {\n\t\tif !matchPrefix(c.k, c.p, c.b) {\n\t\t\tt.Errorf(\"matchPrefix(%#b, %#b,%#b) should be true\", c.k, c.p, c.b)\n\t\t}\n\t}\n}\n\nfunc TestNotMatchPrefix(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tk prefix\n\t\tp prefix\n\t\tb bitpos\n\t}{\n\t\t{\n\t\t\tk: 0b0000,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b0010,\n\t\t\tp: 0b1011,\n\t\t\tb: 0b0100,\n\t\t},\n\t} {\n\t\tif matchPrefix(c.k, c.p, c.b) {\n\t\t\tt.Errorf(\"matchPrefix(%#b, %#b,%#b) should be false\", c.k, c.p, c.b)\n\t\t}\n\t}\n}\n\nfunc TestBranchingBit(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tx    prefix\n\t\ty    prefix\n\t\twant bitpos\n\t}{\n\t\t{\n\t\t\tx:    0b0000,\n\t\t\ty:    0b1011,\n\t\t\twant: 0b1000,\n\t\t}, {\n\t\t\tx:    0b1010,\n\t\t\ty:    0b1011,\n\t\t\twant: 0b0001,\n\t\t}, {\n\t\t\tx:    0b1011,\n\t\t\ty:    0b1111,\n\t\t\twant: 0b0100,\n\t\t}, {\n\t\t\tx:    0b1011,\n\t\t\ty:    0b1001,\n\t\t\twant: 0b0010,\n\t\t},\n\t} {\n\t\tif got := branchingBit(c.x, c.y); got != c.want {\n\t\t\tt.Errorf(\"branchingBit(%#b, %#b,) is not expected value. got %#b want %#b\",\n\t\t\t\tc.x, c.y, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestZeroBit(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tk prefix\n\t\tb bitpos\n\t}{\n\t\t{\n\t\t\tk: 0b1000,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1001,\n\t\t\tb: 0b0100,\n\t\t}, {\n\t\t\tk: 0b1010,\n\t\t\tb: 0b0100,\n\t\t},\n\t} {\n\t\tif !zeroBit(c.k, c.b) {\n\t\t\tt.Errorf(\"zeroBit(%#b, %#b) should be true\", c.k, c.b)\n\t\t}\n\t}\n}\nfunc TestZeroBitFails(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tk prefix\n\t\tb bitpos\n\t}{\n\t\t{\n\t\t\tk: 0b1000,\n\t\t\tb: 0b1000,\n\t\t}, {\n\t\t\tk: 0b1001,\n\t\t\tb: 0b0001,\n\t\t}, {\n\t\t\tk: 0b1010,\n\t\t\tb: 0b0010,\n\t\t}, {\n\t\t\tk: 0b1011,\n\t\t\tb: 0b0001,\n\t\t},\n\t} {\n\t\tif zeroBit(c.k, c.b) {\n\t\t\tt.Errorf(\"zeroBit(%#b, %#b) should be false\", c.k, c.b)\n\t\t}\n\t}\n}\n\nfunc TestOrd(t *testing.T) {\n\ta := bitpos(0b0010)\n\tb := bitpos(0b1000)\n\tif ord(a, b) {\n\t\tt.Errorf(\"ord(%#b, %#b) should be false\", a, b)\n\t}\n\tif !ord(b, a) {\n\t\tt.Errorf(\"ord(%#b, %#b) should be true\", b, a)\n\t}\n\tif ord(a, a) {\n\t\tt.Errorf(\"ord(%#b, %#b) should be false\", a, a)\n\t}\n\tif !ord(a, 0) {\n\t\tt.Errorf(\"ord(%#b, %#b) should be true\", a, 0)\n\t}\n}\n\nfunc TestPrefixesOverlapLemma(t *testing.T) {\n\t// test\n\t//   mask(p, fbb) == mask(q, fbb)\n\t// iff\n\t//   m > n && matchPrefix(q, p, m) or  (note: big endian encoding)\n\t//   m < n && matchPrefix(p, q, n) or  (note: big endian encoding)\n\t//   m ==n && p == q\n\n\t// Case 1: mask(p, fbb) == mask(q, fbb) => m > n && matchPrefix(q, p, m)\n\tm, n := bitpos(1<<2), bitpos(1<<1)\n\tp, q := mask(0b100, m), mask(0b010, n)\n\tif !(prefixesOverlap(p, m, q, n) && m > n && matchPrefix(q, p, m)) {\n\t\tt.Errorf(\"prefixesOverlap(%#b, %#b, %#b, %#b) lemma does not hold\",\n\t\t\tp, m, q, n)\n\t}\n\t// Case 2: mask(p, fbb) == mask(q, fbb) => m < n && matchPrefix(p, q, n)\n\tm, n = bitpos(1<<2), bitpos(1<<3)\n\tp, q = mask(0b100, m), mask(0b1000, n)\n\tif !(prefixesOverlap(p, m, q, n) && m < n && matchPrefix(p, q, n)) {\n\t\tt.Errorf(\"prefixesOverlap(%#b, %#b, %#b, %#b) lemma does not hold\",\n\t\t\tp, m, q, n)\n\t}\n\t// Case 3: mask(p, fbb) == mask(q, fbb) => m < n && matchPrefix(p, q, n)\n\tm, n = bitpos(1<<2), bitpos(1<<2)\n\tp, q = mask(0b100, m), mask(0b001, n)\n\tif !(prefixesOverlap(p, m, q, n) && m == n && p == q) {\n\t\tt.Errorf(\"prefixesOverlap(%#b, %#b, %#b, %#b) lemma does not hold\",\n\t\t\tp, m, q, n)\n\t}\n\t// Case 4: mask(p, fbb) != mask(q, fbb)\n\tm, n = bitpos(1<<1), bitpos(1<<1)\n\tp, q = mask(0b100, m), mask(0b001, n)\n\tif prefixesOverlap(p, m, q, n) ||\n\t\t(m > n && matchPrefix(q, p, m)) ||\n\t\t(m < n && matchPrefix(p, q, n)) ||\n\t\t(m == n && p == q) {\n\t\tt.Errorf(\"prefixesOverlap(%#b, %#b, %#b, %#b) lemma does not hold\",\n\t\t\tp, m, q, n)\n\t}\n\n\t// Do a few more random cases\n\tr := rand.New(rand.NewSource(123))\n\tN := 2000\n\tfor i := 0; i < N; i++ {\n\t\tm := bitpos(1 << (r.Uint64() % (64 + 1)))\n\t\tn := bitpos(1 << (r.Uint64() % (64 + 1)))\n\n\t\tp := mask(prefix(r.Uint64()), m)\n\t\tq := mask(prefix(r.Uint64()), n)\n\n\t\tlhs := prefixesOverlap(p, m, q, n)\n\t\trhs := (m > n && matchPrefix(q, p, m)) ||\n\t\t\t(m < n && matchPrefix(p, q, n)) ||\n\t\t\t(m == n && p == q)\n\n\t\tif lhs != rhs {\n\t\t\tt.Errorf(\"prefixesOverlap(%#b, %#b, %#b, %#b) != <lemma> got %v. want %v\",\n\t\t\t\tp, m, q, n, lhs, rhs)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/builder.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage trie\n\n// Collision functions combine a left and right hand side (lhs and rhs) values\n// the two values are associated with the same key and produces the value that\n// will be stored for the key.\n//\n// Collision functions must be idempotent:\n//\n//\tcollision(x, x) == x for all x.\n//\n// Collisions functions may be applied whenever a value is inserted\n// or two maps are merged, or intersected.\ntype Collision func(lhs any, rhs any) any\n\n// TakeLhs always returns the left value in a collision.\nfunc TakeLhs(lhs, rhs any) any { return lhs }\n\n// TakeRhs always returns the right hand side in a collision.\nfunc TakeRhs(lhs, rhs any) any { return rhs }\n\n// Builder creates new Map. Each Builder has a unique Scope.\n//\n// IMPORTANT:  Nodes are hash-consed internally to reduce memory consumption. To\n// support hash-consing Builders keep an internal Map of all of the Maps that they\n// have created. To GC any of the Maps created by the Builder, all references to\n// the Builder must be dropped. This includes MutMaps.\ntype Builder struct {\n\tscope Scope\n\n\t// hash-consing maps for each node type.\n\tempty    *empty\n\tleaves   map[leaf]*leaf\n\tbranches map[branch]*branch\n\t// It may be possible to support more types of patricia tries\n\t// (e.g. non-hash-consed) by making Builder an interface and abstracting\n\t// the mkLeaf and mkBranch functions.\n}\n\n// NewBuilder creates a new Builder with a unique Scope.\nfunc NewBuilder() *Builder {\n\ts := newScope()\n\treturn &Builder{\n\t\tscope:    s,\n\t\tempty:    &empty{s},\n\t\tleaves:   make(map[leaf]*leaf),\n\t\tbranches: make(map[branch]*branch),\n\t}\n}\n\nfunc (b *Builder) Scope() Scope { return b.scope }\n\n// Rescope changes the builder's scope to a new unique Scope.\n//\n// Any Maps created using the previous scope need to be Cloned\n// before any operation.\n//\n// This makes the old internals of the Builder eligible to be GC'ed.\nfunc (b *Builder) Rescope() {\n\ts := newScope()\n\tb.scope = s\n\tb.empty = &empty{s}\n\tb.leaves = make(map[leaf]*leaf)\n\tb.branches = make(map[branch]*branch)\n}\n\n// Empty is the empty map.\nfunc (b *Builder) Empty() Map { return Map{b.Scope(), b.empty} }\n\n// InsertWith inserts a new association from k to v into the Map m to create a new map\n// in the current scope and handle collisions using the collision function c.\n//\n// This is roughly corresponds to updating a map[uint64]interface{} by:\n//\n//\tif _, ok := m[k]; ok { m[k] = c(m[k], v} else { m[k] = v}\n//\n// An insertion or update happened whenever Insert(m, ...) != m .\nfunc (b *Builder) InsertWith(c Collision, m Map, k uint64, v any) Map {\n\tm = b.Clone(m)\n\treturn Map{b.Scope(), b.insert(c, m.n, b.mkLeaf(key(k), v), false)}\n}\n\n// Inserts a new association from key to value into the Map m to create\n// a new map in the current scope.\n//\n// If there was a previous value mapped by key, keep the previously mapped value.\n// This is roughly corresponds to updating a map[uint64]interface{} by:\n//\n//\tif _, ok := m[k]; ok { m[k] = val }\n//\n// This is equivalent to b.Merge(m, b.Create({k: v})).\nfunc (b *Builder) Insert(m Map, k uint64, v any) Map {\n\treturn b.InsertWith(TakeLhs, m, k, v)\n}\n\n// Updates a (key, value) in the map. This is roughly corresponds to\n// updating a map[uint64]interface{} by:\n//\n//\tm[key] = val\nfunc (b *Builder) Update(m Map, key uint64, val any) Map {\n\treturn b.InsertWith(TakeRhs, m, key, val)\n}\n\n// Merge two maps lhs and rhs to create a new map in the current scope.\n//\n// Whenever there is a key in both maps (a collision), the resulting value mapped by\n// the key will be `c(lhs[key], rhs[key])`.\nfunc (b *Builder) MergeWith(c Collision, lhs, rhs Map) Map {\n\tlhs, rhs = b.Clone(lhs), b.Clone(rhs)\n\treturn Map{b.Scope(), b.merge(c, lhs.n, rhs.n)}\n}\n\n// Merge two maps lhs and rhs to create a new map in the current scope.\n//\n// Whenever there is a key in both maps (a collision), the resulting value mapped by\n// the key will be the value in lhs `b.Collision(lhs[key], rhs[key])`.\nfunc (b *Builder) Merge(lhs, rhs Map) Map {\n\treturn b.MergeWith(TakeLhs, lhs, rhs)\n}\n\n// Clone returns a Map that contains the same (key, value) elements\n// within b.Scope(), i.e. return m if m.Scope() == b.Scope() or return\n// a deep copy of m within b.Scope() otherwise.\nfunc (b *Builder) Clone(m Map) Map {\n\tif m.Scope() == b.Scope() {\n\t\treturn m\n\t} else if m.n == nil {\n\t\treturn Map{b.Scope(), b.empty}\n\t}\n\treturn Map{b.Scope(), b.clone(m.n)}\n}\nfunc (b *Builder) clone(n node) node {\n\tswitch n := n.(type) {\n\tcase *empty:\n\t\treturn b.empty\n\tcase *leaf:\n\t\treturn b.mkLeaf(n.k, n.v)\n\tcase *branch:\n\t\treturn b.mkBranch(n.prefix, n.branching, b.clone(n.left), b.clone(n.right))\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n\n// Remove a key from a Map m and return the resulting Map.\nfunc (b *Builder) Remove(m Map, k uint64) Map {\n\tm = b.Clone(m)\n\treturn Map{b.Scope(), b.remove(m.n, key(k))}\n}\n\n// Intersect Maps lhs and rhs and returns a map with all of the keys in\n// both lhs and rhs and the value comes from lhs, i.e.\n//\n//\t{(k, lhs[k]) | k in lhs, k in rhs}.\nfunc (b *Builder) Intersect(lhs, rhs Map) Map {\n\treturn b.IntersectWith(TakeLhs, lhs, rhs)\n}\n\n// IntersectWith take lhs and rhs and returns the intersection\n// with the value coming from the collision function, i.e.\n//\n//\t{(k, c(lhs[k], rhs[k]) ) | k in lhs, k in rhs}.\n//\n// The elements of the resulting map are always { <k, c(lhs[k], rhs[k]) > }\n// for each key k that a key in both lhs and rhs.\nfunc (b *Builder) IntersectWith(c Collision, lhs, rhs Map) Map {\n\tl, r := b.Clone(lhs), b.Clone(rhs)\n\treturn Map{b.Scope(), b.intersect(c, l.n, r.n)}\n}\n\n// MutMap is a convenient wrapper for a Map and a *Builder that will be used to create\n// new Maps from it.\ntype MutMap struct {\n\tB *Builder\n\tM Map\n}\n\n// MutEmpty is an empty MutMap for a builder.\nfunc (b *Builder) MutEmpty() MutMap {\n\treturn MutMap{b, b.Empty()}\n}\n\n// Insert an element into the map using the collision function for the builder.\n// Returns true if the element was inserted.\nfunc (mm *MutMap) Insert(k uint64, v any) bool {\n\told := mm.M\n\tmm.M = mm.B.Insert(old, k, v)\n\treturn old != mm.M\n}\n\n// Updates an element in the map. Returns true if the map was updated.\nfunc (mm *MutMap) Update(k uint64, v any) bool {\n\told := mm.M\n\tmm.M = mm.B.Update(old, k, v)\n\treturn old != mm.M\n}\n\n// Removes a key from the map. Returns true if the element was removed.\nfunc (mm *MutMap) Remove(k uint64) bool {\n\told := mm.M\n\tmm.M = mm.B.Remove(old, k)\n\treturn old != mm.M\n}\n\n// Merge another map into the current one using the collision function\n// for the builder. Returns true if the map changed.\nfunc (mm *MutMap) Merge(other Map) bool {\n\told := mm.M\n\tmm.M = mm.B.Merge(old, other)\n\treturn old != mm.M\n}\n\n// Intersect another map into the current one using the collision function\n// for the builder. Returns true if the map changed.\nfunc (mm *MutMap) Intersect(other Map) bool {\n\told := mm.M\n\tmm.M = mm.B.Intersect(old, other)\n\treturn old != mm.M\n}\n\nfunc (b *Builder) Create(m map[uint64]any) Map {\n\tvar leaves []*leaf\n\tfor k, v := range m {\n\t\tleaves = append(leaves, b.mkLeaf(key(k), v))\n\t}\n\treturn Map{b.Scope(), b.create(leaves)}\n}\n\n// Merge another map into the current one using the collision function\n// for the builder. Returns true if the map changed.\nfunc (mm *MutMap) MergeWith(c Collision, other Map) bool {\n\told := mm.M\n\tmm.M = mm.B.MergeWith(c, old, other)\n\treturn old != mm.M\n}\n\n// creates a map for a collection of leaf nodes.\nfunc (b *Builder) create(leaves []*leaf) node {\n\tn := len(leaves)\n\tif n == 0 {\n\t\treturn b.empty\n\t} else if n == 1 {\n\t\treturn leaves[0]\n\t}\n\t// Note: we can do a more sophisticated algorithm by:\n\t// - sorting the leaves ahead of time,\n\t// - taking the prefix and branching bit of the min and max key,\n\t// - binary searching for the branching bit,\n\t// - splitting exactly where the branch will be, and\n\t// - making the branch node for this prefix + branching bit.\n\t// Skipping until this is a performance bottleneck.\n\n\tm := n / 2 // (n >= 2) ==> 1 <= m < n\n\tl, r := leaves[:m], leaves[m:]\n\treturn b.merge(nil, b.create(l), b.create(r))\n}\n\n// mkLeaf returns the hash-consed representative of (k, v) in the current scope.\nfunc (b *Builder) mkLeaf(k key, v any) *leaf {\n\trep, ok := b.leaves[leaf{k, v}]\n\tif !ok {\n\t\trep = &leaf{k, v} // heap-allocated copy\n\t\tb.leaves[leaf{k, v}] = rep\n\t}\n\treturn rep\n}\n\n// mkBranch returns the hash-consed representative of the tuple\n//\n//\t(prefix, branch, left, right)\n//\n// in the current scope.\nfunc (b *Builder) mkBranch(p prefix, bp bitpos, left node, right node) *branch {\n\tbr := branch{\n\t\tsz:        left.size() + right.size(),\n\t\tprefix:    p,\n\t\tbranching: bp,\n\t\tleft:      left,\n\t\tright:     right,\n\t}\n\trep, ok := b.branches[br]\n\tif !ok {\n\t\trep = new(branch) // heap-allocated copy\n\t\t*rep = br\n\t\tb.branches[br] = rep\n\t}\n\treturn rep\n}\n\n// join two maps with prefixes p0 and p1 that are *known* to disagree.\nfunc (b *Builder) join(p0 prefix, t0 node, p1 prefix, t1 node) *branch {\n\tm := branchingBit(p0, p1)\n\tvar left, right node\n\tif zeroBit(p0, m) {\n\t\tleft, right = t0, t1\n\t} else {\n\t\tleft, right = t1, t0\n\t}\n\tprefix := mask(p0, m)\n\treturn b.mkBranch(prefix, m, left, right)\n}\n\n// collide two leaves with the same key to create a leaf\n// with the collided value.\nfunc (b *Builder) collide(c Collision, left, right *leaf) *leaf {\n\tif left == right {\n\t\treturn left // c is idempotent: c(x, x) == x\n\t}\n\tval := left.v // keep the left value by default if c is nil\n\tif c != nil {\n\t\tval = c(left.v, right.v)\n\t}\n\tswitch val {\n\tcase left.v:\n\t\treturn left\n\tcase right.v:\n\t\treturn right\n\tdefault:\n\t\treturn b.mkLeaf(left.k, val)\n\t}\n}\n\n// inserts a leaf l into a map m and returns the resulting map.\n// When lhs is true, l is the left hand side in a collision.\n// Both l and m are in the current scope.\nfunc (b *Builder) insert(c Collision, m node, l *leaf, lhs bool) node {\n\tswitch m := m.(type) {\n\tcase *empty:\n\t\treturn l\n\tcase *leaf:\n\t\tif m.k == l.k {\n\t\t\tleft, right := l, m\n\t\t\tif !lhs {\n\t\t\t\tleft, right = right, left\n\t\t\t}\n\t\t\treturn b.collide(c, left, right)\n\t\t}\n\t\treturn b.join(prefix(l.k), l, prefix(m.k), m)\n\tcase *branch:\n\t\t// fallthrough\n\t}\n\t// m is a branch\n\tbr := m.(*branch)\n\tif !matchPrefix(prefix(l.k), br.prefix, br.branching) {\n\t\treturn b.join(prefix(l.k), l, br.prefix, br)\n\t}\n\tvar left, right node\n\tif zeroBit(prefix(l.k), br.branching) {\n\t\tleft, right = b.insert(c, br.left, l, lhs), br.right\n\t} else {\n\t\tleft, right = br.left, b.insert(c, br.right, l, lhs)\n\t}\n\tif left == br.left && right == br.right {\n\t\treturn m\n\t}\n\treturn b.mkBranch(br.prefix, br.branching, left, right)\n}\n\n// merge two maps in the current scope.\nfunc (b *Builder) merge(c Collision, lhs, rhs node) node {\n\tif lhs == rhs {\n\t\treturn lhs\n\t}\n\tswitch lhs := lhs.(type) {\n\tcase *empty:\n\t\treturn rhs\n\tcase *leaf:\n\t\treturn b.insert(c, rhs, lhs, true)\n\tcase *branch:\n\t\tswitch rhs := rhs.(type) {\n\t\tcase *empty:\n\t\t\treturn lhs\n\t\tcase *leaf:\n\t\t\treturn b.insert(c, lhs, rhs, false)\n\t\tcase *branch:\n\t\t\t// fallthrough\n\t\t}\n\t}\n\n\t// Last remaining case is branch merging.\n\t// For brevity, we adopt the Okasaki and Gill naming conventions\n\t// for branching and prefixes.\n\ts, t := lhs.(*branch), rhs.(*branch)\n\tp, m := s.prefix, s.branching\n\tq, n := t.prefix, t.branching\n\n\tif m == n && p == q { // prefixes are identical.\n\t\tleft, right := b.merge(c, s.left, t.left), b.merge(c, s.right, t.right)\n\t\treturn b.mkBranch(p, m, left, right)\n\t}\n\tif !prefixesOverlap(p, m, q, n) {\n\t\treturn b.join(p, s, q, t) // prefixes are disjoint.\n\t}\n\t// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)\n\t// By prefixesOverlap(...), either:\n\t//   higher(m, n) && matchPrefix(q, p, m), or\n\t//   higher(n, m) && matchPrefix(p, q, n)\n\t// So either s or t may can be merged with one branch or the other.\n\tswitch {\n\tcase ord(m, n) && zeroBit(q, m):\n\t\treturn b.mkBranch(p, m, b.merge(c, s.left, t), s.right)\n\tcase ord(m, n) && !zeroBit(q, m):\n\t\treturn b.mkBranch(p, m, s.left, b.merge(c, s.right, t))\n\tcase ord(n, m) && zeroBit(p, n):\n\t\treturn b.mkBranch(q, n, b.merge(c, s, t.left), t.right)\n\tdefault:\n\t\treturn b.mkBranch(q, n, t.left, b.merge(c, s, t.right))\n\t}\n}\n\nfunc (b *Builder) remove(m node, k key) node {\n\tswitch m := m.(type) {\n\tcase *empty:\n\t\treturn m\n\tcase *leaf:\n\t\tif m.k == k {\n\t\t\treturn b.empty\n\t\t}\n\t\treturn m\n\tcase *branch:\n\t\t// fallthrough\n\t}\n\tbr := m.(*branch)\n\tkp := prefix(k)\n\tif !matchPrefix(kp, br.prefix, br.branching) {\n\t\t// The prefix does not match. kp is not in br.\n\t\treturn br\n\t}\n\t// the prefix matches. try to remove from the left or right branch.\n\tleft, right := br.left, br.right\n\tif zeroBit(kp, br.branching) {\n\t\tleft = b.remove(left, k) // k may be in the left branch.\n\t} else {\n\t\tright = b.remove(right, k) // k may be in the right branch.\n\t}\n\tif left == br.left && right == br.right {\n\t\treturn br // no update\n\t} else if _, ok := left.(*empty); ok {\n\t\treturn right // left updated and is empty.\n\t} else if _, ok := right.(*empty); ok {\n\t\treturn left // right updated and is empty.\n\t}\n\t// Either left or right updated. Both left and right are not empty.\n\t// The left and right branches still share the same prefix and disagree\n\t// on the same branching bit. It is safe to directly create the branch.\n\treturn b.mkBranch(br.prefix, br.branching, left, right)\n}\n\nfunc (b *Builder) intersect(c Collision, l, r node) node {\n\tif l == r {\n\t\treturn l\n\t}\n\tswitch l := l.(type) {\n\tcase *empty:\n\t\treturn b.empty\n\tcase *leaf:\n\t\tif rleaf := r.find(l.k); rleaf != nil {\n\t\t\treturn b.collide(c, l, rleaf)\n\t\t}\n\t\treturn b.empty\n\tcase *branch:\n\t\tswitch r := r.(type) {\n\t\tcase *empty:\n\t\t\treturn b.empty\n\t\tcase *leaf:\n\t\t\tif lleaf := l.find(r.k); lleaf != nil {\n\t\t\t\treturn b.collide(c, lleaf, r)\n\t\t\t}\n\t\t\treturn b.empty\n\t\tcase *branch:\n\t\t\t// fallthrough\n\t\t}\n\t}\n\t// Last remaining case is branch intersection.\n\ts, t := l.(*branch), r.(*branch)\n\tp, m := s.prefix, s.branching\n\tq, n := t.prefix, t.branching\n\n\tif m == n && p == q {\n\t\t// prefixes are identical.\n\t\tleft, right := b.intersect(c, s.left, t.left), b.intersect(c, s.right, t.right)\n\t\tif _, ok := left.(*empty); ok {\n\t\t\treturn right\n\t\t} else if _, ok := right.(*empty); ok {\n\t\t\treturn left\n\t\t}\n\t\t// The left and right branches are both non-empty.\n\t\t// They still share the same prefix and disagree on the same branching bit.\n\t\t// It is safe to directly create the branch.\n\t\treturn b.mkBranch(p, m, left, right)\n\t}\n\n\tif !prefixesOverlap(p, m, q, n) {\n\t\treturn b.empty // The prefixes share no keys.\n\t}\n\t// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)\n\t// By prefixesOverlap(...), either:\n\t//   ord(m, n) && matchPrefix(q, p, m), or\n\t//   ord(n, m) && matchPrefix(p, q, n)\n\t// So either s or t may be a strict subtree of the other.\n\tvar lhs, rhs node\n\tswitch {\n\tcase ord(m, n) && zeroBit(q, m):\n\t\tlhs, rhs = s.left, t\n\tcase ord(m, n) && !zeroBit(q, m):\n\t\tlhs, rhs = s.right, t\n\tcase ord(n, m) && zeroBit(p, n):\n\t\tlhs, rhs = s, t.left\n\tdefault:\n\t\tlhs, rhs = s, t.right\n\t}\n\treturn b.intersect(c, lhs, rhs)\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/op_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage trie_test\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/callgraph/vta/internal/trie\"\n\t\"maps\"\n)\n\n// This file tests trie.Map by cross checking operations on a collection of\n// trie.Map's against a collection of map[uint64]interface{}. This includes\n// both limited fuzz testing for correctness and benchmarking.\n\n// mapCollection is effectively a []map[uint64]interface{}.\n// These support operations being applied to the i'th maps.\ntype mapCollection interface {\n\tElements() []map[uint64]any\n\n\tDeepEqual(l, r int) bool\n\tLookup(id int, k uint64) (any, bool)\n\n\tInsert(id int, k uint64, v any)\n\tUpdate(id int, k uint64, v any)\n\tRemove(id int, k uint64)\n\tIntersect(l int, r int)\n\tMerge(l int, r int)\n\tClear(id int)\n\n\tAverage(l int, r int)\n\tAssign(l int, r int)\n}\n\n// opCode of an operation.\ntype opCode int\n\nconst (\n\tdeepEqualsOp opCode = iota\n\tlookupOp\n\tinsert\n\tupdate\n\tremove\n\tmerge\n\tintersect\n\tclear\n\ttakeAverage\n\tassign\n)\n\nfunc (op opCode) String() string {\n\tswitch op {\n\tcase deepEqualsOp:\n\t\treturn \"DE\"\n\tcase lookupOp:\n\t\treturn \"LO\"\n\tcase insert:\n\t\treturn \"IN\"\n\tcase update:\n\t\treturn \"UP\"\n\tcase remove:\n\t\treturn \"RE\"\n\tcase merge:\n\t\treturn \"ME\"\n\tcase intersect:\n\t\treturn \"IT\"\n\tcase clear:\n\t\treturn \"CL\"\n\tcase takeAverage:\n\t\treturn \"AV\"\n\tcase assign:\n\t\treturn \"AS\"\n\tdefault:\n\t\treturn \"??\"\n\t}\n}\n\n// A mapCollection backed by MutMaps.\ntype trieCollection struct {\n\tb     *trie.Builder\n\ttries []trie.MutMap\n}\n\nfunc (c *trieCollection) Elements() []map[uint64]any {\n\tvar maps []map[uint64]any\n\tfor _, m := range c.tries {\n\t\tmaps = append(maps, trie.Elems(m.M))\n\t}\n\treturn maps\n}\nfunc (c *trieCollection) Eq(id int, m map[uint64]any) bool {\n\telems := trie.Elems(c.tries[id].M)\n\treturn !reflect.DeepEqual(elems, m)\n}\n\nfunc (c *trieCollection) Lookup(id int, k uint64) (any, bool) {\n\treturn c.tries[id].M.Lookup(k)\n}\nfunc (c *trieCollection) DeepEqual(l, r int) bool {\n\treturn c.tries[l].M.DeepEqual(c.tries[r].M)\n}\n\nfunc (c *trieCollection) Add() {\n\tc.tries = append(c.tries, c.b.MutEmpty())\n}\n\nfunc (c *trieCollection) Insert(id int, k uint64, v any) {\n\tc.tries[id].Insert(k, v)\n}\n\nfunc (c *trieCollection) Update(id int, k uint64, v any) {\n\tc.tries[id].Update(k, v)\n}\n\nfunc (c *trieCollection) Remove(id int, k uint64) {\n\tc.tries[id].Remove(k)\n}\n\nfunc (c *trieCollection) Intersect(l int, r int) {\n\tc.tries[l].Intersect(c.tries[r].M)\n}\n\nfunc (c *trieCollection) Merge(l int, r int) {\n\tc.tries[l].Merge(c.tries[r].M)\n}\n\nfunc (c *trieCollection) Average(l int, r int) {\n\tc.tries[l].MergeWith(average, c.tries[r].M)\n}\n\nfunc (c *trieCollection) Clear(id int) {\n\tc.tries[id] = c.b.MutEmpty()\n}\nfunc (c *trieCollection) Assign(l, r int) {\n\tc.tries[l] = c.tries[r]\n}\n\nfunc average(x any, y any) any {\n\tif x, ok := x.(float32); ok {\n\t\tif y, ok := y.(float32); ok {\n\t\t\treturn (x + y) / 2.0\n\t\t}\n\t}\n\treturn x\n}\n\ntype builtinCollection []map[uint64]any\n\nfunc (c builtinCollection) Elements() []map[uint64]any {\n\treturn c\n}\n\nfunc (c builtinCollection) Lookup(id int, k uint64) (any, bool) {\n\tv, ok := c[id][k]\n\treturn v, ok\n}\nfunc (c builtinCollection) DeepEqual(l, r int) bool {\n\treturn reflect.DeepEqual(c[l], c[r])\n}\n\nfunc (c builtinCollection) Insert(id int, k uint64, v any) {\n\tif _, ok := c[id][k]; !ok {\n\t\tc[id][k] = v\n\t}\n}\n\nfunc (c builtinCollection) Update(id int, k uint64, v any) {\n\tc[id][k] = v\n}\n\nfunc (c builtinCollection) Remove(id int, k uint64) {\n\tdelete(c[id], k)\n}\n\nfunc (c builtinCollection) Intersect(l int, r int) {\n\tresult := map[uint64]any{}\n\tfor k, v := range c[l] {\n\t\tif _, ok := c[r][k]; ok {\n\t\t\tresult[k] = v\n\t\t}\n\t}\n\tc[l] = result\n}\n\nfunc (c builtinCollection) Merge(l int, r int) {\n\tresult := map[uint64]any{}\n\tmaps.Copy(result, c[r])\n\tmaps.Copy(result, c[l])\n\tc[l] = result\n}\n\nfunc (c builtinCollection) Average(l int, r int) {\n\tavg := map[uint64]any{}\n\tfor k, lv := range c[l] {\n\t\tif rv, ok := c[r][k]; ok {\n\t\t\tavg[k] = average(lv, rv)\n\t\t} else {\n\t\t\tavg[k] = lv // add elements just in l\n\t\t}\n\t}\n\tfor k, rv := range c[r] {\n\t\tif _, ok := c[l][k]; !ok {\n\t\t\tavg[k] = rv // add elements just in r\n\t\t}\n\t}\n\tc[l] = avg\n}\n\nfunc (c builtinCollection) Assign(l, r int) {\n\tm := map[uint64]any{}\n\tmaps.Copy(m, c[r])\n\tc[l] = m\n}\n\nfunc (c builtinCollection) Clear(id int) {\n\tc[id] = map[uint64]any{}\n}\n\nfunc newTriesCollection(size int) *trieCollection {\n\ttc := &trieCollection{\n\t\tb:     trie.NewBuilder(),\n\t\ttries: make([]trie.MutMap, size),\n\t}\n\tfor i := range size {\n\t\ttc.tries[i] = tc.b.MutEmpty()\n\t}\n\treturn tc\n}\n\nfunc newMapsCollection(size int) *builtinCollection {\n\tmaps := make(builtinCollection, size)\n\tfor i := range size {\n\t\tmaps[i] = map[uint64]any{}\n\t}\n\treturn &maps\n}\n\n// operation on a map collection.\ntype operation struct {\n\tcode opCode\n\tl, r int\n\tk    uint64\n\tv    float32\n}\n\n// Apply the operation to maps.\nfunc (op operation) Apply(maps mapCollection) any {\n\ttype lookupresult struct {\n\t\tv  any\n\t\tok bool\n\t}\n\tswitch op.code {\n\tcase deepEqualsOp:\n\t\treturn maps.DeepEqual(op.l, op.r)\n\tcase lookupOp:\n\t\tv, ok := maps.Lookup(op.l, op.k)\n\t\treturn lookupresult{v, ok}\n\tcase insert:\n\t\tmaps.Insert(op.l, op.k, op.v)\n\tcase update:\n\t\tmaps.Update(op.l, op.k, op.v)\n\tcase remove:\n\t\tmaps.Remove(op.l, op.k)\n\tcase merge:\n\t\tmaps.Merge(op.l, op.r)\n\tcase intersect:\n\t\tmaps.Intersect(op.l, op.r)\n\tcase clear:\n\t\tmaps.Clear(op.l)\n\tcase takeAverage:\n\t\tmaps.Average(op.l, op.r)\n\tcase assign:\n\t\tmaps.Assign(op.l, op.r)\n\t}\n\treturn nil\n}\n\n// Returns a collection of op codes with dist[op] copies of op.\nfunc distribution(dist map[opCode]int) []opCode {\n\tvar codes []opCode\n\tfor op, n := range dist {\n\t\tfor range n {\n\t\t\tcodes = append(codes, op)\n\t\t}\n\t}\n\treturn codes\n}\n\n// options for generating a random operation.\ntype options struct {\n\tmaps   int\n\tmaxKey uint64\n\tmaxVal int\n\tcodes  []opCode\n}\n\n// returns a random operation using r as a source of randomness.\nfunc randOperator(r *rand.Rand, opts options) operation {\n\tid := func() int { return r.Intn(opts.maps) }\n\tkey := func() uint64 { return r.Uint64() % opts.maxKey }\n\tval := func() float32 { return float32(r.Intn(opts.maxVal)) }\n\tswitch code := opts.codes[r.Intn(len(opts.codes))]; code {\n\tcase lookupOp, remove:\n\t\treturn operation{code: code, l: id(), k: key()}\n\tcase insert, update:\n\t\treturn operation{code: code, l: id(), k: key(), v: val()}\n\tcase deepEqualsOp, merge, intersect, takeAverage, assign:\n\t\treturn operation{code: code, l: id(), r: id()}\n\tcase clear:\n\t\treturn operation{code: code, l: id()}\n\tdefault:\n\t\tpanic(\"Invalid op code\")\n\t}\n}\n\nfunc randOperators(r *rand.Rand, numops int, opts options) []operation {\n\tops := make([]operation, numops)\n\tfor i := range numops {\n\t\tops[i] = randOperator(r, opts)\n\t}\n\treturn ops\n}\n\n// TestOperations applies a series of random operations to collection of\n// trie.MutMaps and map[uint64]interface{}. It tests for the maps being equal.\nfunc TestOperations(t *testing.T) {\n\tseed := time.Now().UnixNano()\n\ts := rand.NewSource(seed)\n\tr := rand.New(s)\n\tt.Log(\"seed: \", seed)\n\n\tsize := 10\n\tN := 100000\n\tops := randOperators(r, N, options{\n\t\tmaps:   size,\n\t\tmaxKey: 128,\n\t\tmaxVal: 100,\n\t\tcodes: distribution(map[opCode]int{\n\t\t\tdeepEqualsOp: 1,\n\t\t\tlookupOp:     10,\n\t\t\tinsert:       10,\n\t\t\tupdate:       10,\n\t\t\tremove:       10,\n\t\t\tmerge:        10,\n\t\t\tintersect:    10,\n\t\t\tclear:        2,\n\t\t\ttakeAverage:  5,\n\t\t\tassign:       5,\n\t\t}),\n\t})\n\n\tvar tries mapCollection = newTriesCollection(size)\n\tvar maps mapCollection = newMapsCollection(size)\n\tcheck := func() error {\n\t\tif got, want := tries.Elements(), maps.Elements(); !reflect.DeepEqual(got, want) {\n\t\t\treturn fmt.Errorf(\"elements of tries and maps and tries differed. got %v want %v\", got, want)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfor i, op := range ops {\n\t\tgot, want := op.Apply(tries), op.Apply(maps)\n\t\tif got != want {\n\t\t\tt.Errorf(\"op[%d]: (%v).Apply(%v) != (%v).Apply(%v). got %v want %v\",\n\t\t\t\ti, op, tries, op, maps, got, want)\n\t\t}\n\t}\n\tif err := check(); err != nil {\n\t\tt.Errorf(\"%d operators failed with %s\", size, err)\n\t\tt.Log(\"Rerunning with more checking\")\n\t\ttries, maps = newTriesCollection(size), newMapsCollection(size)\n\t\tfor i, op := range ops {\n\t\t\top.Apply(tries)\n\t\t\top.Apply(maps)\n\t\t\tif err := check(); err != nil {\n\t\t\t\tt.Fatalf(\"Failed first on op[%d]=%v: %v\", i, op, err)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc run(b *testing.B, opts options, seed int64, mk func(int) mapCollection) {\n\tr := rand.New(rand.NewSource(seed))\n\tops := randOperators(r, b.N, opts)\n\tmaps := mk(opts.maps)\n\tfor _, op := range ops {\n\t\top.Apply(maps)\n\t}\n}\n\nvar standard options = options{\n\tmaps:   10,\n\tmaxKey: 128,\n\tmaxVal: 100,\n\tcodes: distribution(map[opCode]int{\n\t\tdeepEqualsOp: 1,\n\t\tlookupOp:     20,\n\t\tinsert:       20,\n\t\tupdate:       20,\n\t\tremove:       20,\n\t\tmerge:        10,\n\t\tintersect:    10,\n\t\tclear:        1,\n\t\ttakeAverage:  5,\n\t\tassign:       20,\n\t}),\n}\n\nfunc BenchmarkTrieStandard(b *testing.B) {\n\trun(b, standard, 123, func(size int) mapCollection {\n\t\treturn newTriesCollection(size)\n\t})\n}\n\nfunc BenchmarkMapsStandard(b *testing.B) {\n\trun(b, standard, 123, func(size int) mapCollection {\n\t\treturn newMapsCollection(size)\n\t})\n}\n\nvar smallWide options = options{\n\tmaps:   100,\n\tmaxKey: 100,\n\tmaxVal: 8,\n\tcodes: distribution(map[opCode]int{\n\t\tdeepEqualsOp: 0,\n\t\tlookupOp:     0,\n\t\tinsert:       30,\n\t\tupdate:       20,\n\t\tremove:       0,\n\t\tmerge:        10,\n\t\tintersect:    0,\n\t\tclear:        1,\n\t\ttakeAverage:  0,\n\t\tassign:       30,\n\t}),\n}\n\nfunc BenchmarkTrieSmallWide(b *testing.B) {\n\trun(b, smallWide, 456, func(size int) mapCollection {\n\t\treturn newTriesCollection(size)\n\t})\n}\n\nfunc BenchmarkMapsSmallWide(b *testing.B) {\n\trun(b, smallWide, 456, func(size int) mapCollection {\n\t\treturn newMapsCollection(size)\n\t})\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/scope.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage trie\n\nimport (\n\t\"strconv\"\n\t\"sync/atomic\"\n)\n\n// Scope represents a distinct collection of maps.\n// Maps with the same Scope can be equal. Maps in different scopes are distinct.\n// Each Builder creates maps within a unique Scope.\ntype Scope struct {\n\tid int32\n}\n\nvar nextScopeId int32\n\nfunc newScope() Scope {\n\tid := atomic.AddInt32(&nextScopeId, 1)\n\treturn Scope{id: id}\n}\n\nfunc (s Scope) String() string {\n\treturn strconv.Itoa(int(s.id))\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/trie.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// trie implements persistent Patricia trie maps.\n//\n// Each Map is effectively a map from uint64 to interface{}. Patricia tries are\n// a form of radix tree that are particularly appropriate when many maps will be\n// created, merged together and large amounts of sharing are expected (e.g.\n// environment abstract domains in program analysis).\n//\n// This implementation closely follows the paper:\n//\n//\tC. Okasaki and A. Gill, “Fast mergeable integer maps,” in ACM SIGPLAN\n//\tWorkshop on ML, September 1998, pp. 77–86.\n//\n// Each Map is immutable and can be read from concurrently. The map does not\n// guarantee that the value pointed to by the interface{} value is not updated\n// concurrently.\n//\n// These Maps are optimized for situations where there will be many maps created at\n// with a high degree of sharing and combining of maps together. If you do not expect,\n// significant amount of sharing, the builtin map[T]U is much better choice!\n//\n// Each Map is created by a Builder. Each Builder has a unique Scope and each node is\n// created within this scope. Maps x and y are == if they contains the same\n// (key,value) mappings and have equal scopes.\n//\n// Internally these are big endian Patricia trie nodes, and the keys are sorted.\npackage trie\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Map is effectively a finite mapping from uint64 keys to interface{} values.\n// Maps are immutable and can be read from concurrently.\n//\n// Notes on concurrency:\n//   - A Map value itself is an interface and assignments to a Map value can race.\n//   - Map does not guarantee that the value pointed to by the interface{} value\n//     is not updated concurrently.\ntype Map struct {\n\ts Scope\n\tn node\n}\n\nfunc (m Map) Scope() Scope {\n\treturn m.s\n}\nfunc (m Map) Size() int {\n\tif m.n == nil {\n\t\treturn 0\n\t}\n\treturn m.n.size()\n}\nfunc (m Map) Lookup(k uint64) (any, bool) {\n\tif m.n != nil {\n\t\tif leaf := m.n.find(key(k)); leaf != nil {\n\t\t\treturn leaf.v, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Converts the map into a {<key>: <value>[, ...]} string. This uses the default\n// %s string conversion for <value>.\nfunc (m Map) String() string {\n\tvar kvs []string\n\tm.Range(func(u uint64, i any) bool {\n\t\tkvs = append(kvs, fmt.Sprintf(\"%d: %s\", u, i))\n\t\treturn true\n\t})\n\treturn fmt.Sprintf(\"{%s}\", strings.Join(kvs, \", \"))\n}\n\n// Range over the leaf (key, value) pairs in the map in order and\n// applies cb(key, value) to each. Stops early if cb returns false.\n// Returns true if all elements were visited without stopping early.\nfunc (m Map) Range(cb func(uint64, any) bool) bool {\n\tif m.n != nil {\n\t\treturn m.n.visit(cb)\n\t}\n\treturn true\n}\n\n// DeepEqual returns true if m and other contain the same (k, v) mappings\n// [regardless of Scope].\n//\n// Equivalently m.DeepEqual(other) <=> reflect.DeepEqual(Elems(m), Elems(other))\nfunc (m Map) DeepEqual(other Map) bool {\n\tif m.Scope() == other.Scope() {\n\t\treturn m.n == other.n\n\t}\n\tif (m.n == nil) || (other.n == nil) {\n\t\treturn m.Size() == 0 && other.Size() == 0\n\t}\n\treturn m.n.deepEqual(other.n)\n}\n\n// Elems are the (k,v) elements in the Map as a map[uint64]interface{}\nfunc Elems(m Map) map[uint64]any {\n\tdest := make(map[uint64]any, m.Size())\n\tm.Range(func(k uint64, v any) bool {\n\t\tdest[k] = v\n\t\treturn true\n\t})\n\treturn dest\n}\n\n// node is an internal node within a trie map.\n// A node is either empty, a leaf or a branch.\ntype node interface {\n\tsize() int\n\n\t// visit the leaves (key, value) pairs in the map in order and\n\t// applies cb(key, value) to each. Stops early if cb returns false.\n\t// Returns true if all elements were visited without stopping early.\n\tvisit(cb func(uint64, any) bool) bool\n\n\t// Two nodes contain the same elements regardless of scope.\n\tdeepEqual(node) bool\n\n\t// find the leaf for the given key value or nil if it is not present.\n\tfind(k key) *leaf\n\n\t// implementations must implement this.\n\tnodeImpl()\n}\n\n// empty represents the empty map within a scope.\n//\n// The current builder ensure\ntype empty struct {\n\ts Scope\n}\n\n// leaf represents a single <key, value> pair.\ntype leaf struct {\n\tk key\n\tv any\n}\n\n// branch represents a tree node within the Patricia trie.\n//\n// All keys within the branch match a `prefix` of the key\n// up to a `branching` bit, and the left and right nodes\n// contain keys that disagree on the bit at the `branching` bit.\ntype branch struct {\n\tsz        int    // size. cached for O(1) lookup\n\tprefix    prefix // == mask(p0, branching) for some p0\n\tbranching bitpos\n\n\t// Invariants:\n\t// - neither is nil.\n\t// - neither is *empty.\n\t// - all keys in left are <= p.\n\t// - all keys in right are > p.\n\tleft, right node\n}\n\n// all of these types are Maps.\nvar _ node = &empty{}\nvar _ node = &leaf{}\nvar _ node = &branch{}\n\nfunc (*empty) nodeImpl()  {}\nfunc (*leaf) nodeImpl()   {}\nfunc (*branch) nodeImpl() {}\n\nfunc (*empty) find(k key) *leaf { return nil }\nfunc (l *leaf) find(k key) *leaf {\n\tif k == l.k {\n\t\treturn l\n\t}\n\treturn nil\n}\nfunc (br *branch) find(k key) *leaf {\n\tkp := prefix(k)\n\tif !matchPrefix(kp, br.prefix, br.branching) {\n\t\treturn nil\n\t}\n\tif zeroBit(kp, br.branching) {\n\t\treturn br.left.find(k)\n\t}\n\treturn br.right.find(k)\n}\n\nfunc (*empty) size() int     { return 0 }\nfunc (*leaf) size() int      { return 1 }\nfunc (br *branch) size() int { return br.sz }\n\nfunc (*empty) deepEqual(m node) bool {\n\t_, ok := m.(*empty)\n\treturn ok\n}\nfunc (l *leaf) deepEqual(m node) bool {\n\tif m, ok := m.(*leaf); ok {\n\t\treturn m == l || (l.k == m.k && l.v == m.v)\n\t}\n\treturn false\n}\n\nfunc (br *branch) deepEqual(m node) bool {\n\tif m, ok := m.(*branch); ok {\n\t\tif br == m {\n\t\t\treturn true\n\t\t}\n\t\treturn br.sz == m.sz && br.branching == m.branching && br.prefix == m.prefix &&\n\t\t\tbr.left.deepEqual(m.left) && br.right.deepEqual(m.right)\n\t}\n\t// if m is not a branch, m contains 0 or 1 elem.\n\t// br contains at least 2 keys that disagree on a prefix.\n\treturn false\n}\n\nfunc (*empty) visit(cb func(uint64, any) bool) bool {\n\treturn true\n}\nfunc (l *leaf) visit(cb func(uint64, any) bool) bool {\n\treturn cb(uint64(l.k), l.v)\n}\nfunc (br *branch) visit(cb func(uint64, any) bool) bool {\n\tif !br.left.visit(cb) {\n\t\treturn false\n\t}\n\treturn br.right.visit(cb)\n}\n"
  },
  {
    "path": "go/callgraph/vta/internal/trie/trie_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.13\n\npackage trie\n\nimport (\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n)\n\nfunc TestScope(t *testing.T) {\n\tdef := Scope{}\n\ts0, s1 := newScope(), newScope()\n\tif s0 == def || s1 == def {\n\t\tt.Error(\"newScope() should never be == to the default scope\")\n\t}\n\tif s0 == s1 {\n\t\tt.Errorf(\"newScope() %q and %q should not be ==\", s0, s1)\n\t}\n\tif s0.id == 0 {\n\t\tt.Error(\"s0.id is 0\")\n\t}\n\tif s1.id == 0 {\n\t\tt.Error(\"s1.id is 0\")\n\t}\n\tgot := s0.String()\n\tif _, err := strconv.Atoi(got); err != nil {\n\t\tt.Errorf(\"scope{%s}.String() is not an int: got %s with error %s\", s0, got, err)\n\t}\n}\n\nfunc TestCollision(t *testing.T) {\n\tvar x any = 1\n\tvar y any = 2\n\n\tif v := TakeLhs(x, y); v != x {\n\t\tt.Errorf(\"TakeLhs(%s, %s) got %s. want %s\", x, y, v, x)\n\t}\n\tif v := TakeRhs(x, y); v != y {\n\t\tt.Errorf(\"TakeRhs(%s, %s) got %s. want %s\", x, y, v, y)\n\t}\n}\n\nfunc TestDefault(t *testing.T) {\n\tdef := Map{}\n\n\tif def.Size() != 0 {\n\t\tt.Errorf(\"default node has non-0 size %d\", def.Size())\n\t}\n\tif want, got := (Scope{}), def.Scope(); got != want {\n\t\tt.Errorf(\"default is in a non default scope (%s) from b (%s)\", got, want)\n\t}\n\tif v, ok := def.Lookup(123); !(v == nil && !ok) {\n\t\tt.Errorf(\"Scope{}.Lookup() = (%s, %v) not (nil, false)\", v, ok)\n\t}\n\tif !def.Range(func(k uint64, v any) bool {\n\t\tt.Errorf(\"Scope{}.Range() called it callback on %d:%s\", k, v)\n\t\treturn true\n\t}) {\n\t\tt.Error(\"Scope{}.Range() always iterates through all elements\")\n\t}\n\n\tif got, want := def.String(), \"{}\"; got != want {\n\t\tt.Errorf(\"Scope{}.String() got %s. want %s\", got, want)\n\t}\n\n\tb := NewBuilder()\n\tif def == b.Empty() {\n\t\tt.Error(\"Scope{} == to an empty node from a builder\")\n\t}\n\tif b.Clone(def) != b.Empty() {\n\t\tt.Error(\"b.Clone(Scope{}) should equal b.Empty()\")\n\t}\n\tif !def.DeepEqual(b.Empty()) {\n\t\tt.Error(\"Scope{}.DeepEqual(b.Empty()) should hold\")\n\t}\n}\n\nfunc TestBuilders(t *testing.T) {\n\tb0, b1 := NewBuilder(), NewBuilder()\n\tif b0.Scope() == b1.Scope() {\n\t\tt.Errorf(\"builders have the same scope %s\", b0.Scope())\n\t}\n\n\tif b0.Empty() == b1.Empty() {\n\t\tt.Errorf(\"empty nodes from different scopes are disequal\")\n\t}\n\tif !b0.Empty().DeepEqual(b1.Empty()) {\n\t\tt.Errorf(\"empty nodes from different scopes are not DeepEqual\")\n\t}\n\n\tclone := b1.Clone(b0.Empty())\n\tif clone != b1.Empty() {\n\t\tt.Errorf(\"Clone() empty nodes %v != %v\", clone, b1.Empty())\n\t}\n}\n\nfunc TestEmpty(t *testing.T) {\n\tb := NewBuilder()\n\te := b.Empty()\n\tif e.Size() != 0 {\n\t\tt.Errorf(\"empty nodes has non-0 size %d\", e.Size())\n\t}\n\tif e.Scope() != b.Scope() {\n\t\tt.Errorf(\"b.Empty() is in a different scope (%s) from b (%s)\", e.Scope(), b.Scope())\n\t}\n\tif v, ok := e.Lookup(123); !(v == nil && !ok) {\n\t\tt.Errorf(\"empty.Lookup() = (%s, %v) not (nil, false)\", v, ok)\n\t}\n\tif l := e.n.find(123); l != nil {\n\t\tt.Errorf(\"empty.find(123) got %v. want nil\", l)\n\t}\n\te.Range(func(k uint64, v any) bool {\n\t\tt.Errorf(\"empty.Range() called it callback on %d:%s\", k, v)\n\t\treturn true\n\t})\n\n\twant := \"{}\"\n\tif got := e.String(); got != want {\n\t\tt.Errorf(\"empty.String(123) got %s. want %s\", got, want)\n\t}\n}\n\nfunc TestCreate(t *testing.T) {\n\t// The node orders are printed in lexicographic little-endian.\n\tb := NewBuilder()\n\tfor _, c := range []struct {\n\t\tm    map[uint64]any\n\t\twant string\n\t}{\n\t\t{\n\t\t\tmap[uint64]any{},\n\t\t\t\"{}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\"},\n\t\t\t\"{1: a}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{2: \"b\", 1: \"a\"},\n\t\t\t\"{1: a, 2: b}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\", 4: \"y\", 5: \"z\"},\n\t\t\t\"{1: x, 4: y, 5: z}\",\n\t\t},\n\t} {\n\t\tm := b.Create(c.m)\n\t\tif got := m.String(); got != c.want {\n\t\t\tt.Errorf(\"Create(%v) got %q. want %q \", c.m, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestElems(t *testing.T) {\n\tb := NewBuilder()\n\tfor _, orig := range []map[uint64]any{\n\t\t{},\n\t\t{1: \"a\"},\n\t\t{1: \"a\", 2: \"b\"},\n\t\t{1: \"x\", 4: \"y\", 5: \"z\"},\n\t\t{1: \"x\", 4: \"y\", 5: \"z\", 123: \"abc\"},\n\t} {\n\t\tm := b.Create(orig)\n\t\tif elems := Elems(m); !reflect.DeepEqual(orig, elems) {\n\t\t\tt.Errorf(\"Elems(%v) got %q. want %q \", m, elems, orig)\n\t\t}\n\t}\n}\n\nfunc TestRange(t *testing.T) {\n\tb := NewBuilder()\n\tm := b.Create(map[uint64]any{1: \"x\", 3: \"y\", 5: \"z\", 6: \"stop\", 8: \"a\"})\n\n\tcalls := 0\n\tcb := func(k uint64, v any) bool {\n\t\tt.Logf(\"visiting (%d, %v)\", k, v)\n\t\tcalls++\n\t\treturn k%2 != 0 // stop after the first even number.\n\t}\n\t// The nodes are visited in increasing order.\n\tall := m.Range(cb)\n\tif all {\n\t\tt.Error(\"expected to stop early\")\n\t}\n\twant := 4\n\tif calls != want {\n\t\tt.Errorf(\"# of callbacks (%d) was expected to equal %d (1 + # of evens)\",\n\t\t\tcalls, want)\n\t}\n}\n\nfunc TestDeepEqual(t *testing.T) {\n\tfor _, m := range []map[uint64]any{\n\t\t{},\n\t\t{1: \"x\"},\n\t\t{1: \"x\", 2: \"y\"},\n\t} {\n\t\tl := NewBuilder().Create(m)\n\t\tr := NewBuilder().Create(m)\n\t\tif !l.DeepEqual(r) {\n\t\t\tt.Errorf(\"Expect %v to be DeepEqual() to %v\", l, r)\n\t\t}\n\t}\n}\n\nfunc TestNotDeepEqual(t *testing.T) {\n\tfor _, c := range []struct {\n\t\tleft  map[uint64]any\n\t\tright map[uint64]any\n\t}{\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\tmap[uint64]any{},\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{},\n\t\t\tmap[uint64]any{1: \"y\"},\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\tmap[uint64]any{1: \"y\"},\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\tmap[uint64]any{1: \"x\", 2: \"Y\"},\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\", 2: \"Y\"},\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\", 2: \"y\"},\n\t\t\tmap[uint64]any{1: \"x\", 2: \"Y\"},\n\t\t},\n\t} {\n\t\tl := NewBuilder().Create(c.left)\n\t\tr := NewBuilder().Create(c.right)\n\t\tif l.DeepEqual(r) {\n\t\t\tt.Errorf(\"Expect %v to be !DeepEqual() to %v\", l, r)\n\t\t}\n\t}\n}\n\nfunc TestMerge(t *testing.T) {\n\tb := NewBuilder()\n\tfor _, c := range []struct {\n\t\tleft  map[uint64]any\n\t\tright map[uint64]any\n\t\twant  string\n\t}{\n\t\t{\n\t\t\tmap[uint64]any{},\n\t\t\tmap[uint64]any{},\n\t\t\t\"{}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{},\n\t\t\tmap[uint64]any{1: \"a\"},\n\t\t\t\"{1: a}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\"},\n\t\t\tmap[uint64]any{},\n\t\t\t\"{1: a}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\", 2: \"b\"},\n\t\t\tmap[uint64]any{},\n\t\t\t\"{1: a, 2: b}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\tmap[uint64]any{1: \"y\"},\n\t\t\t\"{1: x}\", // default collision is left\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\tmap[uint64]any{2: \"y\"},\n\t\t\t\"{1: x, 2: y}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{4: \"y\", 5: \"z\"},\n\t\t\tmap[uint64]any{1: \"x\"},\n\t\t\t\"{1: x, 4: y, 5: z}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\", 5: \"z\"},\n\t\t\tmap[uint64]any{4: \"y\"},\n\t\t\t\"{1: x, 4: y, 5: z}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"x\", 4: \"y\"},\n\t\t\tmap[uint64]any{5: \"z\"},\n\t\t\t\"{1: x, 4: y, 5: z}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\", 4: \"c\"},\n\t\t\tmap[uint64]any{2: \"b\", 5: \"d\"},\n\t\t\t\"{1: a, 2: b, 4: c, 5: d}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\", 4: \"c\"},\n\t\t\tmap[uint64]any{2: \"b\", 5 + 8: \"d\"},\n\t\t\t\"{1: a, 2: b, 4: c, 13: d}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{2: \"b\", 5 + 8: \"d\"},\n\t\t\tmap[uint64]any{1: \"a\", 4: \"c\"},\n\t\t\t\"{1: a, 2: b, 4: c, 13: d}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{1: \"a\", 4: \"c\"},\n\t\t\tmap[uint64]any{2: \"b\", 5 + 8: \"d\"},\n\t\t\t\"{1: a, 2: b, 4: c, 13: d}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{2: \"b\", 5 + 8: \"d\"},\n\t\t\tmap[uint64]any{1: \"a\", 4: \"c\"},\n\t\t\t\"{1: a, 2: b, 4: c, 13: d}\",\n\t\t},\n\t\t{\n\t\t\tmap[uint64]any{2: \"b\", 5 + 8: \"d\"},\n\t\t\tmap[uint64]any{2: \"\", 3: \"a\"},\n\t\t\t\"{2: b, 3: a, 13: d}\",\n\t\t},\n\n\t\t{\n\t\t\t// crafted for `!prefixesOverlap(p, m, q, n)`\n\t\t\tleft:  map[uint64]any{1: \"a\", 2 + 1: \"b\"},\n\t\t\tright: map[uint64]any{4 + 1: \"c\", 4 + 2: \"d\"},\n\t\t\t// p: 5, m: 2 q: 1, n: 2\n\t\t\twant: \"{1: a, 3: b, 5: c, 6: d}\",\n\t\t},\n\t\t{\n\t\t\t// crafted for `ord(m, n) && !zeroBit(q, m)`\n\t\t\tleft:  map[uint64]any{8 + 2 + 1: \"a\", 16 + 4: \"b\"},\n\t\t\tright: map[uint64]any{16 + 8 + 2 + 1: \"c\", 16 + 8 + 4 + 2 + 1: \"d\"},\n\t\t\t// left: p: 15, m: 16\n\t\t\t// right: q: 27, n: 4\n\t\t\twant: \"{11: a, 20: b, 27: c, 31: d}\",\n\t\t},\n\t\t{\n\t\t\t// crafted for `ord(n, m) && !zeroBit(p, n)`\n\t\t\t// p: 6, m: 1 q: 5, n: 2\n\t\t\tleft:  map[uint64]any{4 + 2: \"b\", 4 + 2 + 1: \"c\"},\n\t\t\tright: map[uint64]any{4: \"a\", 4 + 2 + 1: \"dropped\"},\n\t\t\twant:  \"{4: a, 6: b, 7: c}\",\n\t\t},\n\t} {\n\t\tl, r := b.Create(c.left), b.Create(c.right)\n\t\tm := b.Merge(l, r)\n\t\tif got := m.String(); got != c.want {\n\t\t\tt.Errorf(\"Merge(%s, %s) got %q. want %q \", l, r, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestIntersect(t *testing.T) {\n\t// Most of the test cases go after specific branches of intersect.\n\tb := NewBuilder()\n\tfor _, c := range []struct {\n\t\tleft  map[uint64]any\n\t\tright map[uint64]any\n\t\twant  string\n\t}{\n\t\t{\n\t\t\tleft:  map[uint64]any{10: \"a\", 39: \"b\"},\n\t\t\tright: map[uint64]any{10: \"A\", 39: \"B\", 75: \"C\"},\n\t\t\twant:  \"{10: a, 39: b}\",\n\t\t},\n\t\t{\n\t\t\tleft:  map[uint64]any{10: \"a\", 39: \"b\"},\n\t\t\tright: map[uint64]any{},\n\t\t\twant:  \"{}\",\n\t\t},\n\t\t{\n\t\t\tleft:  map[uint64]any{},\n\t\t\tright: map[uint64]any{10: \"A\", 39: \"B\", 75: \"C\"},\n\t\t\twant:  \"{}\",\n\t\t},\n\t\t{ // m == n && p == q  && left.(*empty) case\n\t\t\tleft:  map[uint64]any{4: 1, 6: 3, 10: 8, 15: \"on left\"},\n\t\t\tright: map[uint64]any{0: 8, 7: 6, 11: 0, 15: \"on right\"},\n\t\t\twant:  \"{15: on left}\",\n\t\t},\n\t\t{ // m == n && p == q  && right.(*empty) case\n\t\t\tleft:  map[uint64]any{0: \"on left\", 1: 2, 2: 3, 3: 1, 7: 3},\n\t\t\tright: map[uint64]any{0: \"on right\", 5: 1, 6: 8},\n\t\t\twant:  \"{0: on left}\",\n\t\t},\n\t\t{ // m == n && p == q  &&  both left and right are not empty\n\t\t\tleft:  map[uint64]any{1: \"a\", 2: \"b\", 3: \"c\"},\n\t\t\tright: map[uint64]any{0: \"A\", 1: \"B\", 2: \"C\"},\n\t\t\twant:  \"{1: a, 2: b}\",\n\t\t},\n\t\t{ // m == n && p == q  &&  both left and right are not empty\n\t\t\tleft:  map[uint64]any{1: \"a\", 2: \"b\", 3: \"c\"},\n\t\t\tright: map[uint64]any{0: \"A\", 1: \"B\", 2: \"C\"},\n\t\t\twant:  \"{1: a, 2: b}\",\n\t\t},\n\t\t{ // !prefixesOverlap(p, m, q, n)\n\t\t\t// p = 1, m = 2, q = 5, n = 2\n\t\t\tleft:  map[uint64]any{0b001: 1, 0b011: 3},\n\t\t\tright: map[uint64]any{0b100: 4, 0b111: 7},\n\t\t\twant:  \"{}\",\n\t\t},\n\t\t{ // ord(m, n) && zeroBit(q, m)\n\t\t\t// p = 3, m = 4, q = 0, n = 1\n\t\t\tleft:  map[uint64]any{0b010: 2, 0b101: 5},\n\t\t\tright: map[uint64]any{0b000: 0, 0b001: 1},\n\t\t\twant:  \"{}\",\n\t\t},\n\n\t\t{ // ord(m, n) && !zeroBit(q, m)\n\t\t\t// p = 29, m = 2, q = 30, n = 1\n\t\t\tleft: map[uint64]any{\n\t\t\t\t0b11101: \"29\",\n\t\t\t\t0b11110: \"30\",\n\t\t\t},\n\t\t\tright: map[uint64]any{\n\t\t\t\t0b11110: \"30 on right\",\n\t\t\t\t0b11111: \"31\",\n\t\t\t},\n\t\t\twant: \"{30: 30}\",\n\t\t},\n\t\t{ // ord(n, m) && zeroBit(p, n)\n\t\t\t// p = 5, m = 2, q = 3, n = 4\n\t\t\tleft:  map[uint64]any{0b000: 0, 0b001: 1},\n\t\t\tright: map[uint64]any{0b010: 2, 0b101: 5},\n\t\t\twant:  \"{}\",\n\t\t},\n\t\t{ // default case\n\t\t\t// p = 5, m = 2, q = 3, n = 4\n\t\t\tleft:  map[uint64]any{0b100: 1, 0b110: 3},\n\t\t\tright: map[uint64]any{0b000: 8, 0b111: 6},\n\t\t\twant:  \"{}\",\n\t\t},\n\t} {\n\t\tl, r := b.Create(c.left), b.Create(c.right)\n\t\tm := b.Intersect(l, r)\n\t\tif got := m.String(); got != c.want {\n\t\t\tt.Errorf(\"Intersect(%s, %s) got %q. want %q \", l, r, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestIntersectWith(t *testing.T) {\n\tb := NewBuilder()\n\tl := b.Create(map[uint64]any{10: 2.0, 39: 32.0})\n\tr := b.Create(map[uint64]any{10: 6.0, 39: 10.0, 75: 1.0})\n\n\tprodIfDifferent := func(x any, y any) any {\n\t\tif x, ok := x.(float64); ok {\n\t\t\tif y, ok := y.(float64); ok {\n\t\t\t\tif x == y {\n\t\t\t\t\treturn x\n\t\t\t\t}\n\t\t\t\treturn x * y\n\t\t\t}\n\t\t}\n\t\treturn x\n\t}\n\n\tm := b.IntersectWith(prodIfDifferent, l, r)\n\n\twant := \"{10: %!s(float64=12), 39: %!s(float64=320)}\"\n\tif got := m.String(); got != want {\n\t\tt.Errorf(\"IntersectWith(min, %s, %s) got %q. want %q \", l, r, got, want)\n\t}\n}\n\nfunc TestRemove(t *testing.T) {\n\t// Most of the test cases go after specific branches of intersect.\n\tb := NewBuilder()\n\tfor _, c := range []struct {\n\t\tm    map[uint64]any\n\t\tkey  uint64\n\t\twant string\n\t}{\n\t\t{map[uint64]any{}, 10, \"{}\"},\n\t\t{map[uint64]any{10: \"a\"}, 10, \"{}\"},\n\t\t{map[uint64]any{39: \"b\"}, 10, \"{39: b}\"},\n\t\t// Branch cases:\n\t\t// !matchPrefix(kp, br.prefix, br.branching)\n\t\t{map[uint64]any{10: \"a\", 39: \"b\"}, 128, \"{10: a, 39: b}\"},\n\t\t// case: left == br.left && right == br.right\n\t\t{map[uint64]any{10: \"a\", 39: \"b\"}, 16, \"{10: a, 39: b}\"},\n\t\t// left updated and is empty.\n\t\t{map[uint64]any{10: \"a\", 39: \"b\"}, 10, \"{39: b}\"},\n\t\t// right updated and is empty.\n\t\t{map[uint64]any{10: \"a\", 39: \"b\"}, 39, \"{10: a}\"},\n\t\t// final b.mkBranch(...) case.\n\t\t{map[uint64]any{10: \"a\", 39: \"b\", 128: \"c\"}, 39, \"{10: a, 128: c}\"},\n\t} {\n\t\tpre := b.Create(c.m)\n\t\tpost := b.Remove(pre, c.key)\n\t\tif got := post.String(); got != c.want {\n\t\t\tt.Errorf(\"Remove(%s, %d) got %q. want %q \", pre, c.key, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestRescope(t *testing.T) {\n\tb := NewBuilder()\n\tl := b.Create(map[uint64]any{10: \"a\", 39: \"b\"})\n\tr := b.Create(map[uint64]any{10: \"A\", 39: \"B\", 75: \"C\"})\n\n\tb.Rescope()\n\n\tm := b.Intersect(l, r)\n\tif got, want := m.String(), \"{10: a, 39: b}\"; got != want {\n\t\tt.Errorf(\"Intersect(%s, %s) got %q. want %q\", l, r, got, want)\n\t}\n\tif m.Scope() == l.Scope() {\n\t\tt.Errorf(\"m.Scope() = %v should not equal l.Scope() = %v\", m.Scope(), l.Scope())\n\t}\n\tif m.Scope() == r.Scope() {\n\t\tt.Errorf(\"m.Scope() = %v should not equal r.Scope() = %v\", m.Scope(), r.Scope())\n\t}\n}\n\nfunc TestSharing(t *testing.T) {\n\tb := NewBuilder()\n\tl := b.Create(map[uint64]any{0: \"a\", 1: \"b\"})\n\tr := b.Create(map[uint64]any{1: \"B\", 2: \"C\"})\n\n\trleftold := r.n.(*branch).left\n\n\tm := b.Merge(l, r)\n\tif mleft := m.n.(*branch).left; mleft != l.n {\n\t\tt.Errorf(\"unexpected value for left branch of %v. want %v got %v\", m, l, mleft)\n\t}\n\n\tif rleftnow := r.n.(*branch).left; rleftnow != rleftold {\n\t\tt.Errorf(\"r.n.(*branch).left was modified by the Merge operation. was %v now %v\", rleftold, rleftnow)\n\t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/propagation.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"go/types\"\n\t\"iter\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/callgraph/vta/internal/trie\"\n\t\"golang.org/x/tools/go/ssa\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\n// scc computes strongly connected components (SCCs) of `g` using the\n// classical Tarjan's algorithm for SCCs. The result is two slices:\n//   - sccs: the SCCs, each represented as a slice of node indices\n//   - idxToSccID: the inverse map, from node index to SCC number.\n//\n// The SCCs are sorted in reverse topological order: for SCCs\n// with ids X and Y s.t. X < Y, Y comes before X in the topological order.\nfunc scc(g *vtaGraph) (sccs [][]idx, idxToSccID []int) {\n\t// standard data structures used by Tarjan's algorithm.\n\ttype state struct {\n\t\tpre     int // preorder of the node (0 if unvisited)\n\t\tlowLink int\n\t\tonStack bool\n\t}\n\tstates := make([]state, g.numNodes())\n\tvar stack []idx\n\n\tidxToSccID = make([]int, g.numNodes())\n\tnextPre := 0\n\n\tvar doSCC func(idx)\n\tdoSCC = func(n idx) {\n\t\tnextPre++\n\t\tns := &states[n]\n\t\t*ns = state{pre: nextPre, lowLink: nextPre, onStack: true}\n\t\tstack = append(stack, n)\n\n\t\tfor s := range g.successors(n) {\n\t\t\tif ss := &states[s]; ss.pre == 0 {\n\t\t\t\t// Analyze successor s that has not been visited yet.\n\t\t\t\tdoSCC(s)\n\t\t\t\tns.lowLink = min(ns.lowLink, ss.lowLink)\n\t\t\t} else if ss.onStack {\n\t\t\t\t// The successor is on the stack, meaning it has to be\n\t\t\t\t// in the current SCC.\n\t\t\t\tns.lowLink = min(ns.lowLink, ss.pre)\n\t\t\t}\n\t\t}\n\n\t\t// if n is a root node, pop the stack and generate a new SCC.\n\t\tif ns.lowLink == ns.pre {\n\t\t\tsccStart := slicesLastIndex(stack, n)\n\t\t\tscc := slices.Clone(stack[sccStart:])\n\t\t\tstack = stack[:sccStart]\n\t\t\tsccID := len(sccs)\n\t\t\tsccs = append(sccs, scc)\n\t\t\tfor _, w := range scc {\n\t\t\t\tstates[w].onStack = false\n\t\t\t\tidxToSccID[w] = sccID\n\t\t\t}\n\t\t}\n\t}\n\n\tfor n, nn := 0, g.numNodes(); n < nn; n++ {\n\t\tif states[n].pre == 0 {\n\t\t\tdoSCC(idx(n))\n\t\t}\n\t}\n\n\treturn sccs, idxToSccID\n}\n\n// slicesLastIndex returns the index of the last occurrence of v in s, or -1 if v is\n// not present in s.\n//\n// slicesLastIndex iterates backwards through the elements of s, stopping when the ==\n// operator determines an element is equal to v.\nfunc slicesLastIndex[S ~[]E, E comparable](s S, v E) int {\n\t// TODO: move to / dedup with slices.LastIndex\n\tfor i := len(s) - 1; i >= 0; i-- {\n\t\tif s[i] == v {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// propType represents type information being propagated\n// over the vta graph. f != nil only for function nodes\n// and nodes reachable from function nodes. There, we also\n// remember the actual *ssa.Function in order to more\n// precisely model higher-order flow.\ntype propType struct {\n\ttyp types.Type\n\tf   *ssa.Function\n}\n\n// propTypeMap is an auxiliary structure that serves\n// the role of a map from nodes to a set of propTypes.\ntype propTypeMap map[node]*trie.MutMap\n\n// propTypes returns an iterator for the propTypes associated with\n// node `n` in map `ptm`.\nfunc (ptm propTypeMap) propTypes(n node) iter.Seq[propType] {\n\treturn func(yield func(propType) bool) {\n\t\tif types := ptm[n]; types != nil {\n\t\t\ttypes.M.Range(func(_ uint64, elem any) bool {\n\t\t\t\treturn yield(elem.(propType))\n\t\t\t})\n\t\t}\n\t}\n}\n\n// propagate reduces the `graph` based on its SCCs and\n// then propagates type information through the reduced\n// graph. The result is a map from nodes to a set of types\n// and functions, stemming from higher-order data flow,\n// reaching the node. `canon` is used for type uniqueness.\nfunc propagate(graph *vtaGraph, canon *typeutil.Map) propTypeMap {\n\tsccs, idxToSccID := scc(graph)\n\n\t// propTypeIds are used to create unique ids for\n\t// propType, to be used for trie-based type sets.\n\tpropTypeIds := make(map[propType]uint64)\n\t// Id creation is based on == equality, which works\n\t// as types are canonicalized (see getPropType).\n\tpropTypeId := func(p propType) uint64 {\n\t\tif id, ok := propTypeIds[p]; ok {\n\t\t\treturn id\n\t\t}\n\t\tid := uint64(len(propTypeIds))\n\t\tpropTypeIds[p] = id\n\t\treturn id\n\t}\n\tbuilder := trie.NewBuilder()\n\t// Initialize sccToTypes to avoid repeated check\n\t// for initialization later.\n\tsccToTypes := make([]*trie.MutMap, len(sccs))\n\tfor sccID, scc := range sccs {\n\t\ttypeSet := builder.MutEmpty()\n\t\tfor _, idx := range scc {\n\t\t\tif n := graph.node[idx]; hasInitialTypes(n) {\n\t\t\t\t// add the propType for idx to typeSet.\n\t\t\t\tpt := getPropType(n, canon)\n\t\t\t\ttypeSet.Update(propTypeId(pt), pt)\n\t\t\t}\n\t\t}\n\t\tsccToTypes[sccID] = &typeSet\n\t}\n\n\tfor i := len(sccs) - 1; i >= 0; i-- {\n\t\tnextSccs := make(map[int]empty)\n\t\tfor _, n := range sccs[i] {\n\t\t\tfor succ := range graph.successors(n) {\n\t\t\t\tnextSccs[idxToSccID[succ]] = empty{}\n\t\t\t}\n\t\t}\n\t\t// Propagate types to all successor SCCs.\n\t\tfor nextScc := range nextSccs {\n\t\t\tsccToTypes[nextScc].Merge(sccToTypes[i].M)\n\t\t}\n\t}\n\tnodeToTypes := make(propTypeMap, graph.numNodes())\n\tfor sccID, scc := range sccs {\n\t\ttypes := sccToTypes[sccID]\n\t\tfor _, idx := range scc {\n\t\t\tnodeToTypes[graph.node[idx]] = types\n\t\t}\n\t}\n\treturn nodeToTypes\n}\n\n// hasInitialTypes check if a node can have initial types.\n// Returns true iff `n` is not a panic, recover, nestedPtr*\n// node, nor a node whose type is an interface.\nfunc hasInitialTypes(n node) bool {\n\tswitch n.(type) {\n\tcase panicArg, recoverReturn, nestedPtrFunction, nestedPtrInterface:\n\t\treturn false\n\tdefault:\n\t\treturn !types.IsInterface(n.Type())\n\t}\n}\n\n// getPropType creates a propType for `node` based on its type.\n// propType.typ is always node.Type(). If node is function, then\n// propType.val is the underlying function; nil otherwise.\nfunc getPropType(node node, canon *typeutil.Map) propType {\n\tt := canonicalize(node.Type(), canon)\n\tif fn, ok := node.(function); ok {\n\t\treturn propType{f: fn.f, typ: t}\n\t}\n\treturn propType{f: nil, typ: t}\n}\n"
  },
  {
    "path": "go/callgraph/vta/propagation_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\t\"math\"\n\t\"reflect\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\n// val is a test data structure for creating ssa.Value\n// outside of the ssa package. Needed for manual creation\n// of vta graph nodes in testing.\ntype val struct {\n\tname string\n\ttyp  types.Type\n}\n\nfunc (v val) String() string {\n\treturn v.name\n}\n\nfunc (v val) Name() string {\n\treturn v.name\n}\n\nfunc (v val) Type() types.Type {\n\treturn v.typ\n}\n\nfunc (v val) Parent() *ssa.Function {\n\treturn nil\n}\n\nfunc (v val) Referrers() *[]ssa.Instruction {\n\treturn nil\n}\n\nfunc (v val) Pos() token.Pos {\n\treturn token.NoPos\n}\n\n// newLocal creates a new local node with ssa.Value\n// named `name` and type `t`.\nfunc newLocal(name string, t types.Type) local {\n\treturn local{val: val{name: name, typ: t}}\n}\n\n// sccString is a utility for stringifying `nodeToScc`. Every\n// scc is represented as a string where string representation\n// of scc nodes are sorted and concatenated using `;`.\nfunc sccString(sccs [][]idx, g *vtaGraph) []string {\n\tvar sccsStr []string\n\tfor _, scc := range sccs {\n\t\tvar nodesStr []string\n\t\tfor _, idx := range scc {\n\t\t\tnodesStr = append(nodesStr, g.node[idx].String())\n\t\t}\n\t\tsort.Strings(nodesStr)\n\t\tsccsStr = append(sccsStr, strings.Join(nodesStr, \";\"))\n\t}\n\treturn sccsStr\n}\n\n// nodeToTypeString is testing utility for stringifying results\n// of type propagation: propTypeMap `pMap` is converted to a map\n// from node strings to a string consisting of type stringifications\n// concatenated with `;`. We stringify reachable type information\n// that also has an accompanying function by the function name.\nfunc nodeToTypeString(pMap propTypeMap) map[string]string {\n\t// Convert propType to a string. If propType has\n\t// an attached function, return the function name.\n\t// Otherwise, return the type name.\n\tpropTypeString := func(p propType) string {\n\t\tif p.f != nil {\n\t\t\treturn p.f.Name()\n\t\t}\n\t\treturn p.typ.String()\n\t}\n\n\tnodeToTypeStr := make(map[string]string)\n\tfor node := range pMap {\n\t\tvar propStrings []string\n\t\tfor prop := range pMap.propTypes(node) {\n\t\t\ts := propTypeString(prop)\n\t\t\ts = strings.ReplaceAll(s, \"example.com.\", \"\")\n\t\t\tpropStrings = append(propStrings, s)\n\t\t}\n\t\tsort.Strings(propStrings)\n\t\tnodeToTypeStr[node.String()] = strings.Join(propStrings, \";\")\n\t}\n\n\treturn nodeToTypeStr\n}\n\n// sccEqual compares two sets of SCC stringifications.\nfunc sccEqual(sccs1 []string, sccs2 []string) bool {\n\tif len(sccs1) != len(sccs2) {\n\t\treturn false\n\t}\n\tsort.Strings(sccs1)\n\tsort.Strings(sccs2)\n\treturn reflect.DeepEqual(sccs1, sccs2)\n}\n\n// isRevTopSorted checks if sccs of `g` are sorted in reverse\n// topological order:\n//\n//\tfor every edge x -> y in g, nodeToScc[x] > nodeToScc[y]\nfunc isRevTopSorted(g *vtaGraph, idxToScc []int) bool {\n\tfor n := range idxToScc {\n\t\tfor s := range g.successors(idx(n)) {\n\t\t\tif idxToScc[n] < idxToScc[s] {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\nfunc sccMapsConsistent(sccs [][]idx, idxToSccID []int) bool {\n\tfor id, scc := range sccs {\n\t\tfor _, idx := range scc {\n\t\t\tif idxToSccID[idx] != id {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\tfor i, id := range idxToSccID {\n\t\tif !slices.Contains(sccs[id], idx(i)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// testSuite produces a named set of graphs as follows, where\n// parentheses contain node types and F nodes stand for function\n// nodes whose content is function named F:\n//\n//\t no-cycles:\n//\t\tt0 (A) -> t1 (B) -> t2 (C)\n//\n//\t trivial-cycle:\n//\t     <--------    <--------\n//\t     |       |    |       |\n//\t     t0 (A) ->    t1 (B) ->\n//\n//\t circle-cycle:\n//\t\tt0 (A) -> t1 (A) -> t2 (B)\n//\t     |                   |\n//\t     <--------------------\n//\n//\t fully-connected:\n//\t\tt0 (A) <-> t1 (B)\n//\t          \\    /\n//\t           t2(C)\n//\n//\t subsumed-scc:\n//\t\tt0 (A) -> t1 (B) -> t2(B) -> t3 (A)\n//\t     |          |         |        |\n//\t     |          <---------         |\n//\t     <-----------------------------\n//\n//\t more-realistic:\n//\t     <--------\n//\t     |        |\n//\t     t0 (A) -->\n//\t                           ---------->\n//\t                          |           |\n//\t     t1 (A) -> t2 (B) -> F1 -> F2 -> F3 -> F4\n//\t      |        |          |           |\n//\t       <-------           <------------\nfunc testSuite(t *testing.T) map[string]*vtaGraph {\n\tar := txtar.Parse([]byte(`-- go.mod --\nmodule example.com\ngo 1.24\n\n-- p.go --\npackage p\ntype A struct{}\ntype B struct{}\ntype C struct{}\nfunc F1()\nfunc F2()\nfunc F3()\nfunc F4()\n`))\n\tppkgs := testfiles.LoadPackages(t, ar, \".\")\n\tif len(ppkgs) != 1 {\n\t\tt.Fatalf(\"LoadPackages returned %d packages, want 1\", len(ppkgs))\n\t}\n\t_, ssapkgs := ssautil.Packages(ppkgs, ssa.BuilderMode(0))\n\tpkg := ssapkgs[0]\n\n\ta := pkg.Type(\"A\").Type().(*types.Named)\n\tb := pkg.Type(\"B\").Type().(*types.Named)\n\tc := pkg.Type(\"C\").Type().(*types.Named)\n\tf1 := pkg.Func(\"F1\")\n\tf2 := pkg.Func(\"F2\")\n\tf3 := pkg.Func(\"F3\")\n\tf4 := pkg.Func(\"F4\")\n\n\tgraphs := make(map[string]*vtaGraph)\n\tv := &vtaGraph{}\n\tgraphs[\"no-cycles\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t1\", b))\n\tv.addEdge(newLocal(\"t1\", b), newLocal(\"t2\", c))\n\n\tv = &vtaGraph{}\n\tgraphs[\"trivial-cycle\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t0\", a))\n\tv.addEdge(newLocal(\"t1\", b), newLocal(\"t1\", b))\n\n\tv = &vtaGraph{}\n\tgraphs[\"circle-cycle\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t1\", a))\n\tv.addEdge(newLocal(\"t1\", a), newLocal(\"t2\", b))\n\tv.addEdge(newLocal(\"t2\", b), newLocal(\"t0\", a))\n\n\tv = &vtaGraph{}\n\tgraphs[\"fully-connected\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t1\", b))\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t2\", c))\n\tv.addEdge(newLocal(\"t1\", b), newLocal(\"t0\", a))\n\tv.addEdge(newLocal(\"t1\", b), newLocal(\"t2\", c))\n\tv.addEdge(newLocal(\"t2\", c), newLocal(\"t0\", a))\n\tv.addEdge(newLocal(\"t2\", c), newLocal(\"t1\", b))\n\n\tv = &vtaGraph{}\n\tgraphs[\"subsumed-scc\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t1\", b))\n\tv.addEdge(newLocal(\"t1\", b), newLocal(\"t2\", b))\n\tv.addEdge(newLocal(\"t2\", b), newLocal(\"t1\", b))\n\tv.addEdge(newLocal(\"t2\", b), newLocal(\"t3\", a))\n\tv.addEdge(newLocal(\"t3\", a), newLocal(\"t0\", a))\n\n\tv = &vtaGraph{}\n\tgraphs[\"more-realistic\"] = v\n\tv.addEdge(newLocal(\"t0\", a), newLocal(\"t0\", a))\n\tv.addEdge(newLocal(\"t1\", a), newLocal(\"t2\", b))\n\tv.addEdge(newLocal(\"t2\", b), newLocal(\"t1\", a))\n\tv.addEdge(newLocal(\"t2\", b), function{f1})\n\tv.addEdge(function{f1}, function{f2})\n\tv.addEdge(function{f1}, function{f3})\n\tv.addEdge(function{f2}, function{f3})\n\tv.addEdge(function{f3}, function{f1})\n\tv.addEdge(function{f3}, function{f4})\n\n\treturn graphs\n}\n\nfunc TestSCC(t *testing.T) {\n\tsuite := testSuite(t)\n\tfor _, test := range []struct {\n\t\tname  string\n\t\tgraph *vtaGraph\n\t\twant  []string\n\t}{\n\t\t// No cycles results in three separate SCCs: {t0}\t{t1}\t{t2}\n\t\t{name: \"no-cycles\", graph: suite[\"no-cycles\"], want: []string{\"Local(t0)\", \"Local(t1)\", \"Local(t2)\"}},\n\t\t// The two trivial self-loop cycles results in: {t0}\t{t1}\n\t\t{name: \"trivial-cycle\", graph: suite[\"trivial-cycle\"], want: []string{\"Local(t0)\", \"Local(t1)\"}},\n\t\t// The circle cycle produce a single SCC: {t0, t1, t2}\n\t\t{name: \"circle-cycle\", graph: suite[\"circle-cycle\"], want: []string{\"Local(t0);Local(t1);Local(t2)\"}},\n\t\t// Similar holds for fully connected SCC: {t0, t1, t2}\n\t\t{name: \"fully-connected\", graph: suite[\"fully-connected\"], want: []string{\"Local(t0);Local(t1);Local(t2)\"}},\n\t\t// Subsumed SCC also has a single SCC: {t0, t1, t2, t3}\n\t\t{name: \"subsumed-scc\", graph: suite[\"subsumed-scc\"], want: []string{\"Local(t0);Local(t1);Local(t2);Local(t3)\"}},\n\t\t// The more realistic example has the following SCCs: {t0}\t{t1, t2}\t{F1, F2, F3}\t{F4}\n\t\t{name: \"more-realistic\", graph: suite[\"more-realistic\"], want: []string{\"Local(t0)\", \"Local(t1);Local(t2)\", \"Function(F1);Function(F2);Function(F3)\", \"Function(F4)\"}},\n\t} {\n\t\tsccs, idxToSccID := scc(test.graph)\n\t\tif got := sccString(sccs, test.graph); !sccEqual(test.want, got) {\n\t\t\tt.Errorf(\"want %v for graph %v; got %v\", test.want, test.name, got)\n\t\t}\n\t\tif !isRevTopSorted(test.graph, idxToSccID) {\n\t\t\tt.Errorf(\"%v not topologically sorted\", test.name)\n\t\t}\n\t\tif !sccMapsConsistent(sccs, idxToSccID) {\n\t\t\tt.Errorf(\"%v: scc maps not consistent\", test.name)\n\t\t}\n\t\tbreak\n\t}\n}\n\nfunc TestPropagation(t *testing.T) {\n\tsuite := testSuite(t)\n\tvar canon typeutil.Map\n\tfor _, test := range []struct {\n\t\tname  string\n\t\tgraph *vtaGraph\n\t\twant  map[string]string\n\t}{\n\t\t// No cycles graph pushes type information forward.\n\t\t{name: \"no-cycles\", graph: suite[\"no-cycles\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\": \"A\",\n\t\t\t\t\"Local(t1)\": \"A;B\",\n\t\t\t\t\"Local(t2)\": \"A;B;C\",\n\t\t\t},\n\t\t},\n\t\t// No interesting type flow in trivial cycle graph.\n\t\t{name: \"trivial-cycle\", graph: suite[\"trivial-cycle\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\": \"A\",\n\t\t\t\t\"Local(t1)\": \"B\",\n\t\t\t},\n\t\t},\n\t\t// Circle cycle makes type A and B get propagated everywhere.\n\t\t{name: \"circle-cycle\", graph: suite[\"circle-cycle\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\": \"A;B\",\n\t\t\t\t\"Local(t1)\": \"A;B\",\n\t\t\t\t\"Local(t2)\": \"A;B\",\n\t\t\t},\n\t\t},\n\t\t// Similarly for fully connected graph.\n\t\t{name: \"fully-connected\", graph: suite[\"fully-connected\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\": \"A;B;C\",\n\t\t\t\t\"Local(t1)\": \"A;B;C\",\n\t\t\t\t\"Local(t2)\": \"A;B;C\",\n\t\t\t},\n\t\t},\n\t\t// The outer loop of subsumed-scc pushes A and B through the graph.\n\t\t{name: \"subsumed-scc\", graph: suite[\"subsumed-scc\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\": \"A;B\",\n\t\t\t\t\"Local(t1)\": \"A;B\",\n\t\t\t\t\"Local(t2)\": \"A;B\",\n\t\t\t\t\"Local(t3)\": \"A;B\",\n\t\t\t},\n\t\t},\n\t\t// More realistic graph has a more fine grained flow.\n\t\t{name: \"more-realistic\", graph: suite[\"more-realistic\"],\n\t\t\twant: map[string]string{\n\t\t\t\t\"Local(t0)\":    \"A\",\n\t\t\t\t\"Local(t1)\":    \"A;B\",\n\t\t\t\t\"Local(t2)\":    \"A;B\",\n\t\t\t\t\"Function(F1)\": \"A;B;F1;F2;F3\",\n\t\t\t\t\"Function(F2)\": \"A;B;F1;F2;F3\",\n\t\t\t\t\"Function(F3)\": \"A;B;F1;F2;F3\",\n\t\t\t\t\"Function(F4)\": \"A;B;F1;F2;F3;F4\",\n\t\t\t},\n\t\t},\n\t} {\n\t\tif got := nodeToTypeString(propagate(test.graph, &canon)); !reflect.DeepEqual(got, test.want) {\n\t\t\tt.Errorf(\"want %v for graph %v; got %v\", test.want, test.name, got)\n\t\t}\n\t}\n}\n\nfunc testLastIndex[S ~[]E, E comparable](t *testing.T, s S, e E, want int) {\n\tif got := slicesLastIndex(s, e); got != want {\n\t\tt.Errorf(\"LastIndex(%v, %v): got %v want %v\", s, e, got, want)\n\t}\n}\n\nfunc TestLastIndex(t *testing.T) {\n\ttestLastIndex(t, []int{10, 20, 30}, 10, 0)\n\ttestLastIndex(t, []int{10, 20, 30}, 20, 1)\n\ttestLastIndex(t, []int{10, 20, 30}, 30, 2)\n\ttestLastIndex(t, []int{10, 20, 30}, 42, -1)\n\ttestLastIndex(t, []int{10, 20, 10}, 10, 2)\n\ttestLastIndex(t, []int{20, 10, 10}, 10, 2)\n\ttestLastIndex(t, []int{10, 10, 20}, 10, 1)\n\ttype foo struct {\n\t\ti int\n\t\ts string\n\t}\n\ttestLastIndex(t, []foo{{1, \"abc\"}, {2, \"abc\"}, {1, \"xyz\"}}, foo{1, \"abc\"}, 0)\n\t// Test that LastIndex doesn't use bitwise comparisons for floats.\n\tneg0 := 1 / math.Inf(-1)\n\tnan := math.NaN()\n\ttestLastIndex(t, []float64{0, neg0}, 0, 1)\n\ttestLastIndex(t, []float64{0, neg0}, neg0, 1)\n\ttestLastIndex(t, []float64{neg0, 0}, 0, 1)\n\ttestLastIndex(t, []float64{neg0, 0}, neg0, 1)\n\ttestLastIndex(t, []float64{0, nan}, 0, 0)\n\ttestLastIndex(t, []float64{0, nan}, nan, -1)\n\ttestLastIndex(t, []float64{0, nan}, 1, -1)\n}\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/arrays_generics.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype F func()\n\nfunc set[T [1]F | [2]F](arr *T, i int) {\n\t// Indexes into a pointer to an indexable type T and T does not have a coretype.\n\t// SSA instruction:\tt0 = &arr[i]\n\t(*arr)[i] = bar\n}\n\nfunc bar() {\n\tprint(\"here\")\n}\n\nfunc Foo() {\n\tvar arr [1]F\n\tset(&arr, 0)\n\tarr[0]()\n}\n\n// WANT:\n// Foo: set[[1]testdata.F](t0, 0:int) -> set[[1]testdata.F]; t3() -> bar\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_collections.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc Do(a A, b B) map[I]I {\n\tm := make(map[I]I)\n\tm[a] = B{}\n\tm[b] = b\n\treturn m\n}\n\nfunc Baz(a A, b B) {\n\tvar x []I\n\tfor k, v := range Do(a, b) {\n\t\tk.Foo()\n\t\tv.Foo()\n\n\t\tx = append(x, k)\n\t}\n\n\tx[len(x)-1].Foo()\n}\n\n// WANT:\n// Baz: Do(a, b) -> Do; invoke t16.Foo() -> A.Foo, B.Foo; invoke t5.Foo() -> A.Foo, B.Foo; invoke t6.Foo() -> B.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_comma_maps.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tName() string\n\tFoo()\n}\n\nvar is = make(map[string]I)\n\nfunc init() {\n\tregister(A{})\n\tregister(B{})\n}\n\nfunc register(i I) {\n\tis[i.Name()] = i\n}\n\ntype A struct{}\n\nfunc (a A) Foo()         {}\nfunc (a A) Name() string { return \"a\" }\n\ntype B struct{}\n\nfunc (b B) Foo()         {}\nfunc (b B) Name() string { return \"b\" }\n\nfunc Do(n string) {\n\ti, ok := is[n]\n\tif !ok {\n\t\treturn\n\t}\n\ti.Foo()\n}\n\nfunc Go(n string) {\n\tif i, ok := is[n]; !ok {\n\t\treturn\n\t} else {\n\t\ti.Foo()\n\t}\n}\n\nfunc To(n string) {\n\tvar i I\n\tvar ok bool\n\n\tif i, ok = is[n]; !ok {\n\t\treturn\n\t}\n\ti.Foo()\n}\n\nfunc Ro(n string) {\n\ti := is[n]\n\ti.Foo()\n}\n\n// Relevant SSA:\n// func Do(n string):\n//        t0 = *is\n//        t1 = t0[n],ok\n//        t2 = extract t1 #0\n//        t3 = extract t1 #1\n//        if t3 goto 2 else 1\n// 1:\n//        return\n// 2:\n//        t4 = invoke t2.Foo()\n//        return\n\n// WANT:\n// register: invoke i.Name() -> A.Name, B.Name\n// Do: invoke t2.Foo() -> A.Foo, B.Foo\n// Go: invoke t2.Foo() -> A.Foo, B.Foo\n// To: invoke t2.Foo() -> A.Foo, B.Foo\n// Ro: invoke t1.Foo() -> A.Foo, B.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_field_funcs.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype WrappedFunc struct {\n\tF func() complex64\n}\n\nfunc callWrappedFunc(f WrappedFunc) {\n\tf.F()\n}\n\nfunc foo() complex64 {\n\tprintln(\"foo\")\n\treturn -1\n}\n\nfunc Foo(b bool) {\n\tcallWrappedFunc(WrappedFunc{foo})\n\tx := func() {}\n\ty := func() {}\n\tvar a *func()\n\tif b {\n\t\ta = &x\n\t} else {\n\t\ta = &y\n\t}\n\t(*a)()\n}\n\n// Relevant SSA:\n// func Foo(b bool):\n//         t0 = local WrappedFunc (complit)\n//         t1 = &t0.F [#0]\n//         *t1 = foo\n//         t2 = *t0\n//         t3 = callWrappedFunc(t2)\n//         t4 = new func() (x)\n//         *t4 = Foo$1\n//         t5 = new func() (y)\n//         *t5 = Foo$2\n//         if b goto 1 else 3\n// 1:\n//         jump 2\n// 2:\n//         t6 = phi [1: t4, 3: t5] #a\n//         t7 = *t6\n//         t8 = t7()\n//         return\n// 3:\n//         jump 2\n//\n// func callWrappedFunc(f WrappedFunc):\n//         t0 = local WrappedFunc (f)\n//         *t0 = f\n//         t1 = &t0.F [#0]\n//         t2 = *t1\n//         t3 = t2()\n//         return\n\n// WANT:\n// callWrappedFunc: t2() -> foo\n// Foo: callWrappedFunc(t2) -> callWrappedFunc; t7() -> Foo$1, Foo$2\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_fields.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct {\n\tI\n}\n\nfunc (a *A) Do() {\n\ta.Foo()\n}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc NewA(b B) *A {\n\treturn &A{I: &b}\n}\n\nfunc Baz(b B) {\n\ta := NewA(b)\n\ta.Do()\n}\n\n// WANT:\n// Baz: (*A).Do(t0) -> A.Do; NewA(b) -> NewA\n// A.Do: invoke t1.Foo() -> B.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_generics.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\nfunc instantiated[X any](x *X) int {\n\tprint(x)\n\treturn 0\n}\n\ntype I interface {\n\tBar()\n}\n\nfunc interfaceInstantiated[X I](x X) {\n\tx.Bar()\n}\n\ntype A struct{}\n\nfunc (a A) Bar() {}\n\ntype B struct{}\n\nfunc (b B) Bar() {}\n\nfunc Foo(a A, b B) {\n\tx := true\n\tinstantiated[bool](&x)\n\ty := 1\n\tinstantiated[int](&y)\n\n\tinterfaceInstantiated[A](a)\n\tinterfaceInstantiated[B](b)\n}\n\n// Relevant SSA:\n//func Foo(a A, b B):\n//  t0 = new bool (x)\n//  *t0 = true:bool\n//  t1 = instantiated[bool](t2)\n//  t1 = new int (y)\n//  *t2 = 1:int\n//  t3 = instantiated[[int]](t4)\n//  t4 = interfaceInstantiated[testdata.A](a)\n//  t5 = interfaceInstantiated[testdata.B](b)\n//  return\n//\n//func interfaceInstantiated[[testdata.B]](x B):\n//  t0 = (B).Bar(b)\n//  return\n//\n//func interfaceInstantiated[X I](x X):\n//        (external)\n\n// WANT:\n// Foo: instantiated[bool](t0) -> instantiated[bool]; instantiated[int](t2) -> instantiated[int]; interfaceInstantiated[testdata.A](a) -> interfaceInstantiated[testdata.A]; interfaceInstantiated[testdata.B](b) -> interfaceInstantiated[testdata.B]\n// interfaceInstantiated[testdata.B]: (B).Bar(x) -> B.Bar\n// interfaceInstantiated[testdata.A]: (A).Bar(x) -> A.Bar\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_ho.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\nfunc Foo() {}\n\nfunc Do(b bool) func() {\n\tif b {\n\t\treturn Foo\n\t}\n\treturn func() {}\n}\n\nfunc Finish(h func()) {\n\th()\n}\n\nfunc Baz(b bool) {\n\tFinish(Do(b))\n}\n\n// Relevant SSA:\n// func Baz(b bool):\n//   t0 = Do(b)\n//   t1 = Finish(t0)\n//   return\n\n// func Do(b bool) func():\n//   if b goto 1 else 2\n//  1:\n//   return Foo\n//  2:\n//   return Do$1\n\n// func Finish(h func()):\n//   t0 = h()\n//   return\n\n// WANT:\n// Baz: Do(b) -> Do; Finish(t0) -> Finish\n// Finish: h() -> Do$1, Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_interfaces.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\ntype C struct{}\n\nfunc (c C) Foo() {}\n\nfunc NewB() B {\n\treturn B{}\n}\n\nfunc Do(b bool) I {\n\tif b {\n\t\treturn A{}\n\t}\n\n\tc := C{}\n\tc.Foo()\n\n\treturn NewB()\n}\n\nfunc Baz(b bool) {\n\tDo(b).Foo()\n}\n\n// Relevant SSA:\n// func Baz(b bool):\n//   t0 = Do(b)\n//   t1 = invoke t0.Foo()\n//   return\n\n// func Do(b bool) I:\n//    ...\n//   t1 = (C).Foo(C{}:C)\n//   t2 = NewB()\n//   t3 = make I <- B (t2)\n//   return t3\n\n// WANT:\n// Baz: Do(b) -> Do; invoke t0.Foo() -> A.Foo, B.Foo\n// Do: (C).Foo(C{}:C) -> C.Foo; NewB() -> NewB\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_issue_57756.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\n// Test that the values of a named function type are correctly\n// flowing from interface objects i in i.Foo() to the receiver\n// parameters of callees of i.Foo().\n\ntype H func()\n\nfunc (h H) Do() {\n\th()\n}\n\ntype I interface {\n\tDo()\n}\n\nfunc Bar() I {\n\treturn H(func() {})\n}\n\nfunc For(g G) {\n\tb := Bar()\n\tb.Do()\n\n\tg[0] = b\n\tg.Goo()\n}\n\ntype G []I\n\nfunc (g G) Goo() {\n\tg[0].Do()\n}\n\n// Relevant SSA:\n// func Bar$1():\n//   return\n//\n// func Bar() I:\n//   t0 = changetype H <- func() (Bar$1)\n//   t1 = make I <- H (t0)\n//\n// func For():\n//   t0 = Bar()\n//   t1 = invoke t0.Do()\n//   t2 = &g[0:int]\n//   *t2 = t0\n//   t3 = (G).Goo(g)\n//\n// func (h H) Do():\n//   t0 = h()\n//\n// func (g G) Goo():\n//   t0 = &g[0:int]\n//   t1 = *t0\n//   t2 = invoke t1.Do()\n\n// WANT:\n// For: (G).Goo(g) -> G.Goo; Bar() -> Bar; invoke t0.Do() -> H.Do\n// H.Do: h() -> Bar$1\n// G.Goo: invoke t1.Do() -> H.Do\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_nested_ptr.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc Do(i **I) {\n\t**i = A{}\n}\n\nfunc Bar(i **I) {\n\t**i = B{}\n}\n\nfunc Baz(i **I) {\n\tDo(i)\n\t(**i).Foo()\n}\n\n// Relevant SSA:\n//  func Baz(i **I):\n//   t0 = Do(i)\n//   t1 = *i\n//   t2 = *t1\n//   t3 = invoke t2.Foo()\n//   return\n\n//  func Bar(i **I):\n//   t0 = *i\n//   t1 = local B (complit)\n//   t2 = *t1\n//   t3 = make I <- B (t2)\n//   *t0 = t3\n//   return\n\n// func Do(i **I):\n//   t0 = *i\n//   t1 = local A (complit)\n//   t2 = *t1\n//   t3 = make I <- A (t2)\n//   *t0 = t3\n//   return\n\n// WANT:\n// Baz: Do(i) -> Do; invoke t2.Foo() -> A.Foo, B.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_pointers.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct {\n\tf *I\n}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\nfunc Do(a A, i I, c bool) *I {\n\tif c {\n\t\t*a.f = a\n\t} else {\n\t\ta.f = &i\n\t}\n\t(*a.f).Foo()\n\treturn &i\n}\n\nfunc Baz(a A, b B, c bool) {\n\tx := Do(a, b, c)\n\t(*x).Foo()\n}\n\n// The command a.f = &i introduces aliasing that results in\n// A and B reaching both *A.f and return value of Do(a, b, c).\n\n// WANT:\n// Baz: Do(a, t0, c) -> Do; invoke t2.Foo() -> A.Foo, B.Foo\n// Do: invoke t8.Foo() -> A.Foo, B.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_range_over_func.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\ntype C struct{}\n\nfunc (c C) Foo() {} // Test that this is not called.\n\ntype iset []I\n\nfunc (i iset) All() func(func(I) bool) {\n\treturn func(yield func(I) bool) {\n\t\tfor _, v := range i {\n\t\t\tif !yield(v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar x = iset([]I{A{}, B{}})\n\nfunc X() {\n\tfor i := range x.All() {\n\t\ti.Foo()\n\t}\n}\n\nfunc Y() I {\n\tfor i := range x.All() {\n\t\treturn i\n\t}\n\treturn nil\n}\n\nfunc Bar() {\n\tX()\n\ty := Y()\n\ty.Foo()\n}\n\n// Relevant SSA:\n//func X$1(I) bool:\n//\tt0 = *jump$1\n//\tt1 = t0 == 0:int\n//\tif t1 goto 1 else 2\n//1:\n//\t*jump$1 = -1:int\n//\tt2 = invoke arg0.Foo()\n//\t*jump$1 = 0:int\n//\treturn true:bool\n//2:\n//\tt3 = make interface{} <- string (\"yield function ca...\":string) interface{}\n//\tpanic t3\n//\n//func All$1(yield func(I) bool):\n//\tt0 = *i\n//\tt1 = len(t0)\n//\tjump 1\n//1:\n//\tt2 = phi [0: -1:int, 2: t3] #rangeindex\n//\tt3 = t2 + 1:int\n//\tt4 = t3 < t1\n//\tif t4 goto 2 else 3\n//2:\n//\tt5 = &t0[t3]\n//\tt6 = *t5\n//\tt7 = yield(t6)\n//\tif t7 goto 1 else 4\n//\n//func Bar():\n//\tt0 = X()\n//\tt1 = Y()\n//\tt2 = invoke t1.Foo()\n//\treturn\n\n// WANT:\n// Bar: X() -> X; Y() -> Y; invoke t1.Foo() -> A.Foo, B.Foo\n// X$1: invoke arg0.Foo() -> A.Foo, B.Foo\n// All$1: yield(t6) -> X$1, Y$1\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_recursive_types.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo() I\n}\n\ntype A struct {\n\ti int\n\ta *A\n}\n\nfunc (a *A) Foo() I {\n\treturn a\n}\n\ntype B **B\n\ntype C *D\ntype D *C\n\nfunc Bar(a *A, b *B, c *C, d *D) {\n\tBaz(a)\n\tBaz(a.a)\n\n\tsink(*b)\n\tsink(*c)\n\tsink(*d)\n}\n\nfunc Baz(i I) {\n\ti.Foo()\n}\n\nfunc sink(i interface{}) {\n\tprint(i)\n}\n\n// Relevant SSA:\n// func Baz(i I):\n//   t0 = invoke i.Foo()\n//   return\n//\n// func Bar(a *A, b *B):\n//   t0 = make I <- *A (a)\n//   t1 = Baz(t0)\n//   ...\n\n// WANT:\n// Bar: Baz(t0) -> Baz; Baz(t4) -> Baz; sink(t10) -> sink; sink(t13) -> sink; sink(t7) -> sink\n// Baz: invoke i.Foo() -> A.Foo\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_static.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype A struct{}\n\nfunc (a A) foo() {}\n\nfunc Bar() {}\n\nfunc Baz(a A) {\n\ta.foo()\n\tBar()\n\tBaz(A{})\n}\n\n// Relevant SSA:\n// func Baz(a A):\n//   t0 = (A).foo(a)\n//   t1 = Bar()\n//   t2 = Baz(A{}:A)\n\n// WANT:\n// Baz: (A).foo(a) -> A.foo; Bar() -> Bar; Baz(A{}:A) -> Baz\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/callgraph_type_aliases.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\n// This file is the same as callgraph_interfaces.go except for\n// types J, X, Y, and Z aliasing types I, A, B, and C, resp.\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\ntype B struct{}\n\nfunc (b B) Foo() {}\n\ntype C struct{}\n\nfunc (c C) Foo() {}\n\ntype J = I\ntype X = A\ntype Y = B\ntype Z = C\n\nfunc NewY() Y {\n\treturn Y{}\n}\n\nfunc Do(b bool) J {\n\tif b {\n\t\treturn X{}\n\t}\n\n\tz := Z{}\n\tz.Foo()\n\n\treturn NewY()\n}\n\nfunc Baz(b bool) {\n\tDo(b).Foo()\n}\n\n// Relevant SSA:\n// func Baz(b bool):\n//   t0 = Do(b)\n//   t1 = invoke t0.Foo()\n//   return\n\n// func Do(b bool) I:\n//    ...\n//   t1 = (C).Foo(Z{}:Z)\n//   t2 = NewY()\n//   t3 = make I <- B (t2)\n//   return t3\n\n// WANT:\n// Baz: Do(b) -> Do; invoke t0.Foo() -> A.Foo, B.Foo\n// Do: (C).Foo(Z{}:Z) -> C.Foo; NewY() -> NewY\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/channels.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\nfunc foo(c chan interface{}, j int) {\n\tc <- j + 1\n}\n\nfunc Baz(i int) {\n\tc := make(chan interface{})\n\tgo foo(c, i)\n\tx := <-c\n\tprint(x)\n}\n\n// Relevant SSA:\n//  func foo(c chan interface{}, j int):\n//  t0 = j + 1:int\n//  t1 = make interface{} <- int (t0)\n//  send c <- t1                        // t1 -> chan {}interface\n//  return\n//\n// func Baz(i int):\n//  t0 = make chan interface{} 0:int\n//  go foo(t0, i)\n//  t1 = <-t0                           // chan {}interface -> t1\n//  t2 = print(t1)\n//  return\n\n// WANT:\n// Channel(chan interface{}) -> Local(t1)\n// Local(t1) -> Channel(chan interface{})\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/closures.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\nfunc Do(i I) { i.Foo() }\n\nfunc Baz(b bool, h func(I)) {\n\tvar i I\n\ta := func(g func(I)) {\n\t\tg(i)\n\t}\n\n\tif b {\n\t\th = Do\n\t}\n\n\ta(h)\n}\n\n// Relevant SSA:\n//  func Baz(b bool, h func(I)):\n//    t0 = new I (i)\n//    t1 = make closure Baz$1 [t0]\n//    if b goto 1 else 2\n//   1:\n//         jump 2\n//   2:\n//    t2 = phi [0: h, 1: Do] #h\n//    t3 = t1(t2)\n//    return\n//\n// func Baz$1(g func(I)):\n//    t0 = *i\n//    t1 = g(t0)\n//    return\n\n// In the edge set Local(i) -> Local(t0), Local(t0) below,\n// two occurrences of t0 come from t0 in Baz and Baz$1.\n\n// WANT:\n// Function(Do) -> Local(t2)\n// Function(Baz$1) -> Local(t1)\n// Local(h) -> Local(t2)\n// Local(t0) -> Local(i)\n// Local(i) -> Local(t0), Local(t0)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/d/d.go",
    "content": "package d\n\nfunc D(i int) int {\n\treturn i + 1\n}\n\ntype Data struct {\n\tV int\n}\n\nfunc (d Data) Do() int {\n\treturn d.V - 1\n}\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/dynamic_calls.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tfoo(I)\n}\n\ntype A struct{}\n\nfunc (a A) foo(ai I) {}\n\ntype B struct{}\n\nfunc (b B) foo(bi I) {}\n\nfunc doWork() I { return nil }\nfunc close() I  { return nil }\n\nfunc Baz(x B, h func() I, i I) I {\n\ti.foo(x)\n\n\treturn h()\n}\n\nvar g *B = &B{} // ensure *B.foo is created.\n\n// Relevant SSA:\n// func Baz(x B, h func() I, i I) I:\n//   t0 = make I <- B (x)\n//   t1 = invoke i.foo(t0)\n//   t2 = h()\n//   return t2\n\n// Local(t0) has seemingly duplicates of successors. This\n// happens in stringification of type propagation graph.\n// Due to CHA, we analyze A.foo and *A.foo as well as B.foo\n// and *B.foo, which have similar bodies and hence similar\n// type flow that gets merged together during stringification.\n\n// WANT:\n// Return(doWork[0]) -> Local(t2)\n// Return(close[0]) -> Local(t2)\n// Local(t0) -> Local(ai), Local(ai), Local(bi), Local(bi)\n// Constant(testdata.I) -> Return(close[0]), Return(doWork[0])\n// Local(x) -> Local(t0)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/fields.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype J interface {\n\tI\n\tBar()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\nfunc (a A) Bar() {}\n\ntype B struct {\n\ta A\n\ti I\n}\n\nfunc Do() B {\n\tb := B{}\n\treturn b\n}\n\nfunc Baz(b B) {\n\tvar j J\n\tj = b.a\n\n\tj.Bar()\n\n\tb.i = j\n\n\tDo().i.Foo()\n}\n\n// Relevant SSA:\n// func Baz(b B):\n//   t0 = local B (b)\n//   *t0 = b\n//   t1 = &t0.a [#0]       // no flow here since a is of concrete type\n//   t2 = *t1\n//   t3 = make J <- A (t2)\n//   t4 = invoke t3.Bar()\n//   t5 = &t0.i [#1]\n//   t6 = change interface I <- J (t3)\n//   *t5 = t6\n//   t7 = Do()\n//   t8 = t7.i [#0]\n//   t9 = (A).Foo(t8)\n//   return\n\n// WANT:\n// Field(testdata.B:i) -> Local(t5), Local(t8)\n// Local(t5) -> Field(testdata.B:i)\n// Local(t2) -> Local(t3)\n// Local(t3) -> Local(t6)\n// Local(t6) -> Local(t5)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/function_alias.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype Doer func()\n\ntype A struct {\n\tfoo func()\n\tdo  Doer\n}\n\nfunc Baz(f func()) {\n\tj := &f\n\tk := &j\n\t**k = func() {}\n\ta := A{}\n\ta.foo = **k\n\ta.foo()\n\ta.do = a.foo\n\ta.do()\n}\n\n// Relevant SSA:\n// func Baz(f func()):\n//        t0 = new func() (f)\n//        *t0 = f\n//        t1 = new *func() (j)\n//        *t1 = t0\n//        t2 = *t1\n//        *t2 = Baz$1\n//        t3 = local A (a)\n//        t4 = *t1\n//        t5 = *t4\n//        t6 = &t3.foo [#0]\n//        *t6 = t5\n//        t7 = &t3.foo [#0]\n//        t8 = *t7\n//        t9 = t8()\n//        t10 = &t3.foo [#0]                                              *func()\n//        t11 = *t10                                                       func()\n//        t12 = &t3.do [#1]                                                 *Doer\n//        t13 = changetype Doer <- func() (t11)                              Doer\n//        *t12 = t13\n//        t14 = &t3.do [#1]                                                 *Doer\n//        t15 = *t14                                                         Doer\n//        t16 = t15()                                                          ()\n\n// Flow chain showing that Baz$1 reaches t8():\n//   Baz$1 -> t2 <-> PtrFunction(func()) <-> t4 -> t5 -> t6 <-> Field(testdata.A:foo) <-> t7 -> t8\n// Flow chain showing that Baz$1 reaches t15():\n//  Field(testdata.A:foo) <-> t10 -> t11 -> t13 -> t12 <-> Field(testdata.A:do) <-> t14 -> t15\n\n// WANT:\n// Local(f) -> Local(t0)\n// Local(t0) -> PtrFunction(func())\n// Function(Baz$1) -> Local(t2)\n// PtrFunction(func()) -> Local(t0), Local(t2), Local(t4)\n// Local(t2) -> PtrFunction(func())\n// Local(t6) -> Field(testdata.A:foo)\n// Local(t4) -> Local(t5), PtrFunction(func())\n// Local(t5) -> Local(t6)\n// Local(t7) -> Field(testdata.A:foo), Local(t8)\n// Field(testdata.A:foo) -> Local(t10), Local(t6), Local(t7)\n// Local(t6) -> Field(testdata.A:foo)\n// Field(testdata.A:do) -> Local(t12), Local(t14)\n// Local(t12) -> Field(testdata.A:do)\n// Local(t10) -> Field(testdata.A:foo), Local(t11)\n// Local(t11) -> Local(t13)\n// Local(t13) -> Local(t12)\n// Local(t14) -> Field(testdata.A:do), Local(t15)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/generic_channels.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I1 interface{}\ntype I2 interface{}\ntype I3 interface{}\n\nfunc Foo[C interface{ ~chan I1 | ~chan<- I1 }](c C, j int) {\n\tc <- j\n}\n\nfunc Bar[C interface{ ~chan I2 | ~<-chan I2 }](c C) {\n\tx := <-c\n\tprint(x)\n}\n\nfunc Baz[C interface{ ~chan I3 | ~<-chan I3 }](c C) {\n\tselect {\n\tcase x := <-c:\n\t\tprint(x)\n\tdefault:\n\t}\n}\n\n// WANT:\n// Local(t0) -> Channel(chan testdata.I1)\n// Channel(chan testdata.I2) -> Local(t0)\n// Channel(chan testdata.I3) -> Local(t0[2])\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/go117.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype J interface {\n\tFoo()\n\tBar()\n}\n\ntype B struct {\n\tp int\n}\n\nfunc (b B) Foo() {}\nfunc (b B) Bar() {}\n\nfunc Wobble(b *B, s []J) {\n\tx := (*[3]J)(s)\n\tx[1] = b\n\n\ta := &s[2]\n\t(*a).Bar()\n}\n\n// Relevant SSA:\n// func Wobble(b *B, s []J):\n//   t0 = slice to array pointer *[3]J <- []J (s)                      *[3]J\n//   t1 = &t0[1:int]                                                      *J\n//   t2 = make J <- *B (b)                                                 J\n//   *t1 = t2\n//   t3 = &s[2:int]                                                       *J\n//   ...\n\n// WANT:\n// Local(t1) -> Slice([]testdata.J)\n// Slice([]testdata.J) -> Local(t1), Local(t3)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/issue63146.go",
    "content": "package test\n\ntype embedded struct{}\n\ntype S struct{ embedded }\n\nfunc (_ S) M() {}\n\ntype C interface {\n\tM()\n\tS\n}\n\nfunc G[T C]() {\n\tt := T{embedded{}}\n\tt.M()\n}\n\nfunc F() {\n\tG[S]()\n}\n\n// WANT:\n// F: G[testdata.S]() -> G[testdata.S]\n// G[testdata.S]: (S).M(t2) -> S.M\n// S.M: (testdata.S).M(t1) -> S.M\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/maps.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo() string\n}\n\ntype J interface {\n\tFoo() string\n\tBar()\n}\n\ntype B struct {\n\tp string\n}\n\nfunc (b B) Foo() string { return b.p }\nfunc (b B) Bar()        {}\n\nfunc Baz(m map[I]I, b1, b2 B, n map[string]*J) *J {\n\tm[b1] = b2\n\n\treturn n[b1.Foo()]\n}\n\n// Relevant SSA:\n// func Baz(m map[I]I, b1 B, b2 B, n map[string]*J) *J:\n//   t0 = make I <- B (b1)\n//   t1 = make I <- B (b2)\n//   m[t0] = t1\n//   t2 = (B).Foo(b1)\n//   t3 = n[t2]\n//   return t3\n\n// WANT:\n// Local(b2) -> Local(t1)\n// Local(t1) -> MapValue(testdata.I)\n// Local(t0) -> MapKey(testdata.I)\n// Local(t3) -> MapValue(*testdata.J), Return(Baz[0])\n// MapValue(*testdata.J) -> Local(t3)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/node_uniqueness.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\n// TestNodeTypeUniqueness checks if semantically equivalent types\n// are being represented using the same pointer value in vta nodes.\n// If not, some edges become missing in the string representation\n// of the graph.\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {}\n\nfunc Baz(a *A) (I, I, interface{}, interface{}) {\n\tvar i I\n\ti = a\n\n\tvar ii I\n\taa := &A{}\n\tii = aa\n\n\tm := make(map[int]int)\n\tvar iii interface{}\n\tiii = m\n\n\tvar iiii interface{}\n\tiiii = m\n\n\treturn i, ii, iii, iiii\n}\n\n// Relevant SSA:\n// func Baz(a *A) (I, I, interface{}, interface{}):\n//   t0 = make I <- *A (a)\n//\t t1 = new A (complit)\n//   t2 = make I <- *A (t1)\n//   t3 = make map[int]int\n//   t4 = make interface{} <- map[int]int (t3)\n//   t5 = make interface{} <- map[int]int (t3)\n//   return t0, t2, t4, t5\n\n// Without canon approach, one of Pointer(*A) -> Local(t0) and Pointer(*A) -> Local(t2) edges is\n// missing in the graph string representation. The original graph has both of the edges but the\n// source node Pointer(*A) is not the same; two occurrences of Pointer(*A) are considered separate\n// nodes. Since they have the same string representation, one edge gets overridden by the other\n// during the graph stringification, instead of being joined together as in below.\n\n// WANT:\n// Pointer(*testdata.A) -> Local(t0), Local(t2)\n// Local(t3) -> Local(t4), Local(t5)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/panic.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tfoo()\n}\n\ntype A struct{}\n\nfunc (a A) foo() {}\n\nfunc recover1() {\n\tprint(\"only this recover should execute\")\n\tif r, ok := recover().(I); ok {\n\t\tr.foo()\n\t}\n}\n\nfunc recover2() {\n\trecover()\n}\n\nfunc Baz(a A) {\n\tdefer recover1()\n\tdefer recover()\n\tpanic(a)\n}\n\n// Relevant SSA:\n// func recover1():\n//   t0 = print(\"only this recover...\":string)\n//   t1 = recover()\n//   t2 = typeassert,ok t1.(I)\n//   t3 = extract t2 #0\n//   t4 = extract t2 #1\n//   if t4 goto 1 else 2\n//  1:\n//   t5 = invoke t3.foo()\n//   jump 2\n//  2:\n//   return\n//\n// func recover2():\n//   t0 = recover()\n//   return\n//\n// func Baz(i I):\n//   defer recover1()\n//   t0 = make interface{} <- A (a)\n//   panic t2\n\n// t0 argument to panic in Baz gets ultimately connected to recover\n// registers t1 in recover1() and t0 in recover2().\n\n// WANT:\n// Panic -> Recover\n// Local(t0) -> Panic\n// Recover -> Local(t0), Local(t1)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/phi.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype A struct{}\ntype B struct{}\n\ntype I interface{ foo() }\n\nfunc (a A) foo() {}\nfunc (b B) foo() {}\n\nfunc Baz(b B, c bool) {\n\tvar i I\n\tif c {\n\t\ti = b\n\t} else {\n\t\ta := A{}\n\t\ti = a\n\t}\n\ti.foo()\n}\n\n// Relevant SSA:\n// func Baz(b B, c bool):\n// 0:\n//  if c goto 1 else 3\n//\n// 1:\n//  t0 = make I <- B (b)\n//  jump 2\n//\n// 2:\n//  t1 = phi [1: t0, 3: t3] #i\n//  t2 = invoke t1.foo()\n//  return\n//\n// 3:\n//  t3 = make I <- A (struct{}{}:A)\n//  jump 2\n\n// WANT:\n// Local(b) -> Local(t0)\n// Local(t0) -> Local(t1)\n// Local(t3) -> Local(t1)\n// Constant(testdata.A) -> Local(t3)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/phi_alias.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype B struct {\n\tp int\n}\n\nfunc (b B) Foo() {}\n\nfunc Baz(i, j *I, b, c bool) {\n\tif b {\n\t\ti = j\n\t}\n\t*i = B{9}\n\tif c {\n\t\t(*i).Foo()\n\t} else {\n\t\t(*j).Foo()\n\t}\n}\n\n// Relevant SSA:\n// func Baz(i *I, j *I, b bool, c bool):\n//    if b goto 1 else 2\n//  1:\n//    jump 2\n//  2:\n//    t0 = phi [0: i, 1: j] #i\n//    t1 = local B (complit)\n//    t2 = &t1.p [#0]\n//    *t2 = 9:int\n//    t3 = *t1\n//    t4 = make I <- B (t3)\n//    *t0 = t4\n//    if c goto 3 else 5\n//  3:\n//    t5 = *t0\n//    t6 = invoke t5.Foo()\n//    jump 4\n//  4:\n//    return\n//  5:\n//    t7 = *j\n//    t8 = invoke t7.Foo()\n//    jump 4\n\n// Flow chain showing that B reaches (*i).foo():\n//   t3 (B) -> t4 -> t0 -> t5\n// Flow chain showing that B reaches (*j).foo():\n//   t3 (B) -> t4 -> t0 <--> j -> t7\n\n// WANT:\n// Local(t0) -> Local(i), Local(j), Local(t5)\n// Local(i) -> Local(t0)\n// Local(j) -> Local(t0), Local(t7)\n// Local(t3) -> Local(t4)\n// Local(t4) -> Local(t0)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/ranges.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo() string\n}\n\ntype B struct {\n\tp string\n}\n\nfunc (b B) Foo() string { return b.p }\n\nfunc Baz(m map[I]*I) {\n\tfor i, v := range m {\n\t\t*v = B{p: i.Foo()}\n\t}\n}\n\n// Relevant SSA:\n//  func Baz(m map[I]*I):\n//   0:\n//    t0 = range m\n//         jump 1\n//   1:\n//    t1 = next t0\n//    t2 = extract t1 #0\n//    if t2 goto 2 else 3\n//   2:\n//    t3 = extract t1 #1\n//    t4 = extract t1 #2\n//    t5 = local B (complit)\n//    t6 = &t5.p [#0]\n//    t7 = invoke t3.Foo()\n//    *t6 = t7\n//    t8 = *t5\n//    t9 = make I <- B (t8)\n//    *t4 = t9\n//    jump 1\n//   3:\n//    return\n\n// WANT:\n// MapKey(testdata.I) -> Local(t1[1])\n// Local(t1[1]) -> Local(t3)\n// MapValue(*testdata.I) -> Local(t1[2])\n// Local(t1[2]) -> Local(t4), MapValue(*testdata.I)\n// Local(t8) -> Local(t9)\n// Local(t9) -> Local(t4)\n// Local(t4) -> Local(t1[2])\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/returns.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface{}\n\nfunc Bar(ii I) (I, I) {\n\treturn Foo(ii)\n}\n\nfunc Foo(iii I) (I, I) {\n\treturn iii, iii\n}\n\nfunc Do(j I) *I {\n\treturn &j\n}\n\nfunc Baz(i I) *I {\n\tBar(i)\n\treturn Do(i)\n}\n\n// Relevant SSA:\n// func Bar(ii I) (I, I):\n//   t0 = Foo(ii)\n//   t1 = extract t0 #0\n//   t2 = extract t0 #1\n//   return t1, t2\n//\n// func Foo(iii I) (I, I):\n//   return iii, iii\n//\n// func Do(j I) *I:\n//   t0 = new I (j)\n//   *t0 = j\n//   return t0\n//\n// func Baz(i I):\n//   t0 = Bar(i)\n//   t1 = Do(i)\n//   return t1\n\n// t0 and t1 in the last edge correspond to the nodes\n// of Do and Baz. This edge is induced by Do(i).\n\n// WANT:\n// Local(i) -> Local(ii), Local(j)\n// Local(ii) -> Local(iii)\n// Local(iii) -> Return(Foo[0]), Return(Foo[1])\n// Local(t1) -> Return(Baz[0])\n// Local(t1) -> Return(Bar[0])\n// Local(t2) -> Return(Bar[1])\n// Local(t0) -> Return(Do[0])\n// Return(Do[0]) -> Local(t1)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/select.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo() string\n}\n\ntype J interface {\n\tI\n}\n\ntype B struct {\n\tp string\n}\n\nfunc (b B) Foo() string { return b.p }\n\nfunc Baz(b1, b2 B, c1 chan I, c2 chan J) {\n\tfor {\n\t\tselect {\n\t\tcase c1 <- b1:\n\t\t\tprint(\"b1\")\n\t\tcase c2 <- b2:\n\t\t\tprint(\"b2\")\n\t\tcase <-c1:\n\t\t\tprint(\"c1\")\n\t\tcase k := <-c2:\n\t\t\tprint(k.Foo())\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// Relevant SSA:\n// func Baz(b1 B, b2 B, c1 chan I, c2 chan J):\n//   ...\n//   t0 = make I <- B (b1)\n//   t1 = make J <- B (b2)\n//   t2 = select blocking [c1<-t0, c2<-t1, <-c1, <-c2] (index int, ok bool, I, J)\n//   t3 = extract t2 #0\n//   t4 = t73== 0:int\n//   if t4 goto 2 else 3\n//         ...\n//  8:\n//   t12 = extract t2 #3\n//   t13 = invoke t12.Foo()\n//   t14 = print(t15)\n\n// WANT:\n// Local(t0) -> Channel(chan testdata.I)\n// Local(t1) -> Channel(chan testdata.J)\n// Channel(chan testdata.I) -> Local(t2[2])\n// Channel(chan testdata.J) -> Local(t2[3])\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/simple.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nvar gl int\n\ntype X struct {\n\ta int\n\tb int\n}\n\nfunc main() {\n\tprint(gl)\n}\n\nfunc foo() (r int) { return gl }\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/static_calls.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface{}\n\nfunc foo(i I) (I, I) {\n\treturn i, i\n}\n\nfunc doWork(ii I) {}\n\nfunc close(iii I) {}\n\nfunc Baz(inp I) {\n\ta, b := foo(inp)\n\tdefer close(a)\n\tgo doWork(b)\n}\n\n// Relevant SSA:\n// func Baz(inp I):\n//   t0 = foo(inp)\n//   t1 = extract t0 #0\n//   t2 = extract t0 #1\n//   defer close(t1)\n//   go doWork(t2)\n//   rundefers\n//   ...\n// func foo(i I) (I, I):\n//   return i, i\n\n// WANT:\n// Local(inp) -> Local(i)\n// Local(t1) -> Local(iii)\n// Local(t2) -> Local(ii)\n// Local(i) -> Return(foo[0]), Return(foo[1])\n// Return(foo[0]) -> Local(t0[0])\n// Return(foo[1]) -> Local(t0[1])\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/store.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\n// Tests graph creation for store/load and make instructions.\n// Note that ssa package does not have a load instruction per\n// se. Yet, one is encoded as a unary instruction with the\n// * operator.\n\ntype A struct{}\n\ntype I interface{ foo() }\n\nfunc (a A) foo() {}\n\nfunc main() {\n\ta := A{}\n\tvar i I\n\ti = a\n\tii := &i\n\t(*ii).foo()\n}\n\n// Relevant SSA:\n//\tt0 = new I (i)\n//\tt1 = make I <- A (struct{}{}:A)    A  -> t1\n//\t*t0 = t1                           t1 -> t0\n//\tt2 = *t0                           t0 -> t2\n//\tt3 = invoke t2.foo()\n//\treturn\n\n// WANT:\n// Constant(testdata.A) -> Local(t1)\n// Local(t1) -> Local(t0)\n// Local(t0) -> Local(t2)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/store_load_alias.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype A struct{}\n\nfunc (a A) foo() {}\n\ntype I interface{ foo() }\n\nfunc Baz(i I) {\n\tj := &i\n\tk := &j\n\t**k = A{}\n\ti.foo()\n\t(**k).foo()\n}\n\n// Relevant SSA:\n// func Baz(i I):\n//   t0 = new I (i)\n//   *t0 = i\n//   t1 = new *I (j)\n//   *t1 = t0\n//   t2 = *t1\n// \t t3 = make I <- A (struct{}{}:A)                                       I\n//   *t2 = t3\n//   t4 = *t0\n//   t5 = invoke t4.foo()\n//   t6 = *t1\n//   t7 = *t6\n//   t8 = invoke t7.foo()\n\n// Flow chain showing that A reaches i.foo():\n//   Constant(A) -> t3 -> t2 <-> PtrInterface(I) <-> t0 -> t4\n// Flow chain showing that A reaches (**k).foo():\n//\t Constant(A) -> t3 -> t2 <-> PtrInterface(I) <-> t6 -> t7\n\n// WANT:\n// Local(i) -> Local(t0)\n// Local(t0) -> Local(t4), PtrInterface(testdata.I)\n// PtrInterface(testdata.I) -> Local(t0), Local(t2), Local(t6)\n// Local(t2) -> PtrInterface(testdata.I)\n// Constant(testdata.A) -> Local(t3)\n// Local(t3) -> Local(t2)\n// Local(t6) -> Local(t7), PtrInterface(testdata.I)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/stores_arrays.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype I interface {\n\tFoo()\n}\n\ntype J interface {\n\tFoo()\n\tBar()\n}\n\ntype B struct {\n\tp int\n}\n\nfunc (b B) Foo() {}\nfunc (b B) Bar() {}\n\nfunc Baz(b *B, S []*I, s []J) {\n\tvar x [3]I\n\tx[1] = b\n\n\ta := &s[2]\n\t(*a).Bar()\n\n\tprint([3]*I{nil, nil, nil}[2])\n}\n\n// Relevant SSA:\n// func Baz(b *B, S []*I, s []J):\n//   t0 = local [3]I (x)\n//   t1 = &t0[1:int]\n//   ...\n//   t3 = &s[2:int]\n//   t4 = *t3\n//   ...\n//   t6 = local [3]*I (complit)\n//   t7 = &t6[0:int]\n//         ...\n//   t11 = t10[2:int]\n//   ...\n\n// WANT:\n// Slice([]testdata.I) -> Local(t1)\n// Local(t1) -> Slice([]testdata.I)\n// Slice([]testdata.J) -> Local(t3)\n// Local(t3) -> Local(t4), Slice([]testdata.J)\n// Local(t11) -> Slice([]*testdata.I)\n// Slice([]*testdata.I) -> Local(t11), PtrInterface(testdata.I)\n// Constant(*testdata.I) -> PtrInterface(testdata.I)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/t/t.go",
    "content": "package t\n\nimport \"d\"\n\nfunc t(i int) int {\n\tdata := d.Data{V: i}\n\treturn d.D(i) + data.Do()\n}\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/type_assertions.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\n// Test program for testing type assertions and extract instructions.\n// The latter are tested here too since extract instruction comes\n// naturally in type assertions.\n\ntype I interface {\n\tFoo()\n}\n\ntype J interface {\n\tFoo()\n\tBar()\n}\n\ntype A struct {\n\tc int\n}\n\nfunc (a A) Foo() {}\nfunc (a A) Bar() {}\n\nfunc Baz(i I) {\n\tj, ok := i.(J)\n\tif ok {\n\t\tj.Foo()\n\t}\n\n\ta := i.(*A)\n\ta.Bar()\n}\n\n// Relevant SSA:\n// \tfunc Baz(i I):\n//    t0 = typeassert,ok i.(J)\n//    t1 = extract t0 #0\n//    t2 = extract t0 #1\n//    if t2 goto 1 else 2\n//  1:\n//    t3 = invoke t1.Foo()\n//    jump 2\n//  2:\n//    t4 = typeassert i.(*A)  // no flow since t4 is of concrete type\n//    t5 = *t4\n//    t6 = (A).Bar(t5)\n//    return\n\n// WANT:\n// Local(i) -> Local(t0[0])\n// Local(t0[0]) -> Local(t1)\n"
  },
  {
    "path": "go/callgraph/vta/testdata/src/type_conversions.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:build ignore\n\npackage testdata\n\ntype Y interface {\n\tFoo()\n\tBar(float64)\n}\n\ntype Z Y\n\ntype W interface {\n\tY\n}\n\ntype A struct{}\n\nfunc (a A) Foo()          { print(\"A:Foo\") }\nfunc (a A) Bar(f float64) { print(uint(f)) }\n\ntype B struct{}\n\nfunc (b B) Foo()          { print(\"B:Foo\") }\nfunc (b B) Bar(f float64) { print(uint(f) + 1) }\n\ntype X interface {\n\tFoo()\n}\n\nfunc Baz(y Y) {\n\tz := Z(y)\n\tz.Foo()\n\n\tx := X(y)\n\tx.Foo()\n\n\ty = A{}\n\tvar y_p *Y = &y\n\n\tw_p := (*W)(y_p)\n\t*w_p = B{}\n\n\t(*y_p).Foo() // prints B:Foo\n\t(*w_p).Foo() // prints B:Foo\n}\n\n// Relevant SSA:\n//  func Baz(y Y):\n//   t0 = new Y (y)\n//   *t0 = y\n//   t1 = *t0\n//   t2 = changetype Z <- Y (t1)\n//   t3 = invoke t2.Foo()\n//\n//   t4 = *t0\n//   t5 = change interface X <- Y (t4)\n//   t6 = invoke t5.Foo()\n//\n//   t7 = make Y <- A (struct{}{}:A)\n//   *t0 = t7\n//   t8 = changetype *W <- *Y (t0)\n//   t9 = make W <- B (struct{}{}:B)\n//   *t8 = t9\n//   t10 = *t0\n//   t11 = invoke t10.Foo()\n//   t12 = *t8\n//   t13 = invoke t12.Foo()\n//   return\n\n// WANT:\n// Local(t1) -> Local(t2)\n// Local(t4) -> Local(t5)\n// Local(t0) -> Local(t1), Local(t10), Local(t4), Local(t8)\n// Local(y) -> Local(t0)\n// Constant(testdata.A) -> Local(t7)\n// Local(t7) -> Local(t0)\n// Local(t9) -> Local(t8)\n"
  },
  {
    "path": "go/callgraph/vta/utils.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"go/types\"\n\t\"iter\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nfunc canAlias(n1, n2 node) bool {\n\treturn isReferenceNode(n1) && isReferenceNode(n2)\n}\n\nfunc isReferenceNode(n node) bool {\n\tif _, ok := n.(nestedPtrInterface); ok {\n\t\treturn true\n\t}\n\tif _, ok := n.(nestedPtrFunction); ok {\n\t\treturn true\n\t}\n\n\tif _, ok := types.Unalias(n.Type()).(*types.Pointer); ok {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// hasInFlow checks if a concrete type can flow to node `n`.\n// Returns yes iff the type of `n` satisfies one the following:\n//  1. is an interface\n//  2. is a (nested) pointer to interface (needed for, say,\n//     slice elements of nested pointers to interface type)\n//  3. is a function type (needed for higher-order type flow)\n//  4. is a (nested) pointer to function (needed for, say,\n//     slice elements of nested pointers to function type)\n//  5. is a global Recover or Panic node\nfunc hasInFlow(n node) bool {\n\tif _, ok := n.(panicArg); ok {\n\t\treturn true\n\t}\n\tif _, ok := n.(recoverReturn); ok {\n\t\treturn true\n\t}\n\n\tt := n.Type()\n\n\tif i := interfaceUnderPtr(t); i != nil {\n\t\treturn true\n\t}\n\tif f := functionUnderPtr(t); f != nil {\n\t\treturn true\n\t}\n\n\treturn types.IsInterface(t) || isFunction(t)\n}\n\nfunc isFunction(t types.Type) bool {\n\t_, ok := t.Underlying().(*types.Signature)\n\treturn ok\n}\n\n// interfaceUnderPtr checks if type `t` is a potentially nested\n// pointer to interface and if yes, returns the interface type.\n// Otherwise, returns nil.\nfunc interfaceUnderPtr(t types.Type) types.Type {\n\tseen := make(map[types.Type]bool)\n\tvar visit func(types.Type) types.Type\n\tvisit = func(t types.Type) types.Type {\n\t\tif seen[t] {\n\t\t\treturn nil\n\t\t}\n\t\tseen[t] = true\n\n\t\tp, ok := t.Underlying().(*types.Pointer)\n\t\tif !ok {\n\t\t\treturn nil\n\t\t}\n\n\t\tif types.IsInterface(p.Elem()) {\n\t\t\treturn p.Elem()\n\t\t}\n\n\t\treturn visit(p.Elem())\n\t}\n\treturn visit(t)\n}\n\n// functionUnderPtr checks if type `t` is a potentially nested\n// pointer to function type and if yes, returns the function type.\n// Otherwise, returns nil.\nfunc functionUnderPtr(t types.Type) types.Type {\n\tseen := make(map[types.Type]bool)\n\tvar visit func(types.Type) types.Type\n\tvisit = func(t types.Type) types.Type {\n\t\tif seen[t] {\n\t\t\treturn nil\n\t\t}\n\t\tseen[t] = true\n\n\t\tp, ok := t.Underlying().(*types.Pointer)\n\t\tif !ok {\n\t\t\treturn nil\n\t\t}\n\n\t\tif isFunction(p.Elem()) {\n\t\t\treturn p.Elem()\n\t\t}\n\n\t\treturn visit(p.Elem())\n\t}\n\treturn visit(t)\n}\n\n// sliceArrayElem returns the element type of type `t` that is\n// expected to be a (pointer to) array, slice or string, consistent with\n// the ssa.Index and ssa.IndexAddr instructions. Panics otherwise.\nfunc sliceArrayElem(t types.Type) types.Type {\n\tswitch u := t.Underlying().(type) {\n\tcase *types.Pointer:\n\t\tswitch e := u.Elem().Underlying().(type) {\n\t\tcase *types.Array:\n\t\t\treturn e.Elem()\n\t\tcase *types.Interface:\n\t\t\treturn sliceArrayElem(e) // e is a type param with matching element types.\n\t\tdefault:\n\t\t\tpanic(t)\n\t\t}\n\tcase *types.Array:\n\t\treturn u.Elem()\n\tcase *types.Slice:\n\t\treturn u.Elem()\n\tcase *types.Basic:\n\t\treturn types.Typ[types.Byte]\n\tcase *types.Interface: // type param.\n\t\tterms, err := typeparams.InterfaceTermSet(u)\n\t\tif err != nil || len(terms) == 0 {\n\t\t\tpanic(t)\n\t\t}\n\t\treturn sliceArrayElem(terms[0].Type()) // Element types must match.\n\tdefault:\n\t\tpanic(t)\n\t}\n}\n\n// siteCallees returns an iterator for the callees for call site `c`.\nfunc siteCallees(c ssa.CallInstruction, callees calleesFunc) iter.Seq[*ssa.Function] {\n\treturn func(yield func(*ssa.Function) bool) {\n\t\tfor _, callee := range callees(c) {\n\t\t\tif !yield(callee) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc canHaveMethods(t types.Type) bool {\n\tt = types.Unalias(t)\n\tif _, ok := t.(*types.Named); ok {\n\t\treturn true\n\t}\n\n\tu := t.Underlying()\n\tswitch u.(type) {\n\tcase *types.Interface, *types.Signature, *types.Struct:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// calls returns the set of call instructions in `f`.\nfunc calls(f *ssa.Function) []ssa.CallInstruction {\n\tvar calls []ssa.CallInstruction\n\tfor _, bl := range f.Blocks {\n\t\tfor _, instr := range bl.Instrs {\n\t\t\tif c, ok := instr.(ssa.CallInstruction); ok {\n\t\t\t\tcalls = append(calls, c)\n\t\t\t}\n\t\t}\n\t}\n\treturn calls\n}\n"
  },
  {
    "path": "go/callgraph/vta/vta.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package vta computes the call graph of a Go program using the Variable\n// Type Analysis (VTA) algorithm originally described in \"Practical Virtual\n// Method Call Resolution for Java,\" Vijay Sundaresan, Laurie Hendren,\n// Chrislain Razafimahefa, Raja Vallée-Rai, Patrick Lam, Etienne Gagnon, and\n// Charles Godin.\n//\n// Note: this package is in experimental phase and its interface is\n// subject to change.\n// TODO(zpavlinovic): reiterate on documentation.\n//\n// The VTA algorithm overapproximates the set of types (and function literals)\n// a variable can take during runtime by building a global type propagation\n// graph and propagating types (and function literals) through the graph.\n//\n// A type propagation is a directed, labeled graph. A node can represent\n// one of the following:\n//   - A field of a struct type.\n//   - A local (SSA) variable of a method/function.\n//   - All pointers to a non-interface type.\n//   - The return value of a method.\n//   - All elements in an array.\n//   - All elements in a slice.\n//   - All elements in a map.\n//   - All elements in a channel.\n//   - A global variable.\n//\n// In addition, the implementation used in this package introduces\n// a few Go specific kinds of nodes:\n//   - (De)references of nested pointers to interfaces are modeled\n//     as a unique nestedPtrInterface node in the type propagation graph.\n//   - Each function literal is represented as a function node whose\n//     internal value is the (SSA) representation of the function. This\n//     is done to precisely infer flow of higher-order functions.\n//\n// Edges in the graph represent flow of types (and function literals) through\n// the program. That is, the model 1) typing constraints that are induced by\n// assignment statements or function and method calls and 2) higher-order flow\n// of functions in the program.\n//\n// The labeling function maps each node to a set of types and functions that\n// can intuitively reach the program construct the node represents. Initially,\n// every node is assigned a type corresponding to the program construct it\n// represents. Function nodes are also assigned the function they represent.\n// The labeling function then propagates types and function through the graph.\n//\n// The result of VTA is a type propagation graph in which each node is labeled\n// with a conservative overapproximation of the set of types (and functions)\n// it may have. This information is then used to construct the call graph.\n// For each unresolved call site, vta uses the set of types and functions\n// reaching the node representing the call site to create a set of callees.\npackage vta\n\n// TODO(zpavlinovic): update VTA for how it handles generic function bodies and instantiation wrappers.\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/callgraph\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// CallGraph uses the VTA algorithm to compute call graph for all functions\n// f:true in funcs. VTA refines the results of initial call graph and uses it\n// to establish interprocedural type flow. If initial is nil, VTA uses a more\n// efficient approach to construct a CHA call graph.\n//\n// The resulting graph does not have a root node.\n//\n// CallGraph does not make any assumptions on initial types global variables\n// and function/method inputs can have. CallGraph is then sound, modulo use of\n// reflection and unsafe, if the initial call graph is sound.\nfunc CallGraph(funcs map[*ssa.Function]bool, initial *callgraph.Graph) *callgraph.Graph {\n\tcallees := makeCalleesFunc(funcs, initial)\n\tvtaG, canon := typePropGraph(funcs, callees)\n\ttypes := propagate(vtaG, canon)\n\n\tc := &constructor{types: types, callees: callees, cache: make(methodCache)}\n\treturn c.construct(funcs)\n}\n\n// constructor type linearly traverses the input program\n// and constructs a callgraph based on the results of the\n// VTA type propagation phase.\ntype constructor struct {\n\ttypes   propTypeMap\n\tcache   methodCache\n\tcallees calleesFunc\n}\n\nfunc (c *constructor) construct(funcs map[*ssa.Function]bool) *callgraph.Graph {\n\tcg := &callgraph.Graph{Nodes: make(map[*ssa.Function]*callgraph.Node)}\n\tfor f, in := range funcs {\n\t\tif in {\n\t\t\tc.constrct(cg, f)\n\t\t}\n\t}\n\treturn cg\n}\n\nfunc (c *constructor) constrct(g *callgraph.Graph, f *ssa.Function) {\n\tcaller := g.CreateNode(f)\n\tfor _, call := range calls(f) {\n\t\tfor _, c := range c.resolves(call) {\n\t\t\tcallgraph.AddEdge(caller, call, g.CreateNode(c))\n\t\t}\n\t}\n}\n\n// resolves computes the set of functions to which VTA resolves `c`. The resolved\n// functions are intersected with functions to which `c.initial` resolves `c`.\nfunc (c *constructor) resolves(call ssa.CallInstruction) []*ssa.Function {\n\tcc := call.Common()\n\tif cc.StaticCallee() != nil {\n\t\treturn []*ssa.Function{cc.StaticCallee()}\n\t}\n\n\t// Skip builtins as they are not *ssa.Function.\n\tif _, ok := cc.Value.(*ssa.Builtin); ok {\n\t\treturn nil\n\t}\n\n\t// Cover the case of dynamic higher-order and interface calls.\n\tvar res []*ssa.Function\n\tresolved := resolve(call, c.types, c.cache)\n\tfor f := range siteCallees(call, c.callees) {\n\t\tif _, ok := resolved[f]; ok {\n\t\t\tres = append(res, f)\n\t\t}\n\t}\n\treturn res\n}\n\n// resolve returns a set of functions `c` resolves to based on the\n// type propagation results in `types`.\nfunc resolve(c ssa.CallInstruction, types propTypeMap, cache methodCache) map[*ssa.Function]empty {\n\tfns := make(map[*ssa.Function]empty)\n\tn := local{val: c.Common().Value}\n\tfor p := range types.propTypes(n) {\n\t\tfor _, f := range propFunc(p, c, cache) {\n\t\t\tfns[f] = empty{}\n\t\t}\n\t}\n\treturn fns\n}\n\n// propFunc returns the functions modeled with the propagation type `p`\n// assigned to call site `c`. If no such function exists, nil is returned.\nfunc propFunc(p propType, c ssa.CallInstruction, cache methodCache) []*ssa.Function {\n\tif p.f != nil {\n\t\treturn []*ssa.Function{p.f}\n\t}\n\n\tif c.Common().Method == nil {\n\t\treturn nil\n\t}\n\n\treturn cache.methods(p.typ, c.Common().Method.Name(), c.Parent().Prog)\n}\n\n// methodCache serves as a type -> method name -> methods\n// cache when computing methods of a type using the\n// ssa.Program.MethodSets and ssa.Program.MethodValue\n// APIs. The cache is used to speed up querying of\n// methods of a type as the mentioned APIs are expensive.\ntype methodCache map[types.Type]map[string][]*ssa.Function\n\n// methods returns methods of a type `t` named `name`. First consults\n// `mc` and otherwise queries `prog` for the method. If no such method\n// exists, nil is returned.\nfunc (mc methodCache) methods(t types.Type, name string, prog *ssa.Program) []*ssa.Function {\n\tif ms, ok := mc[t]; ok {\n\t\treturn ms[name]\n\t}\n\n\tms := make(map[string][]*ssa.Function)\n\tmset := prog.MethodSets.MethodSet(t)\n\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\t// f can be nil when t is an interface or some\n\t\t// other type without any runtime methods.\n\t\tif f := prog.MethodValue(mset.At(i)); f != nil {\n\t\t\tms[f.Name()] = append(ms[f.Name()], f)\n\t\t}\n\t}\n\tmc[t] = ms\n\treturn ms[name]\n}\n"
  },
  {
    "path": "go/callgraph/vta/vta_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vta\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/analysis/passes/buildssa\"\n\t\"golang.org/x/tools/go/callgraph/cha\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestVTACallGraph(t *testing.T) {\n\terrDiff := func(t *testing.T, want, got, missing []string) {\n\t\tt.Errorf(\"got:\\n%s\\n\\nwant:\\n%s\\n\\nmissing:\\n%s\\n\\ndiff:\\n%s\",\n\t\t\tstrings.Join(got, \"\\n\"),\n\t\t\tstrings.Join(want, \"\\n\"),\n\t\t\tstrings.Join(missing, \"\\n\"),\n\t\t\tcmp.Diff(got, want)) // to aid debugging\n\t}\n\n\tfiles := []string{\n\t\t\"testdata/src/callgraph_static.go\",\n\t\t\"testdata/src/callgraph_ho.go\",\n\t\t\"testdata/src/callgraph_interfaces.go\",\n\t\t\"testdata/src/callgraph_pointers.go\",\n\t\t\"testdata/src/callgraph_collections.go\",\n\t\t\"testdata/src/callgraph_fields.go\",\n\t\t\"testdata/src/callgraph_field_funcs.go\",\n\t\t\"testdata/src/callgraph_recursive_types.go\",\n\t\t\"testdata/src/callgraph_issue_57756.go\",\n\t\t\"testdata/src/callgraph_comma_maps.go\",\n\t\t\"testdata/src/callgraph_type_aliases.go\", // https://github.com/golang/go/issues/68799\n\t}\n\tif testenv.Go1Point() >= 23 {\n\t\tfiles = append(files, \"testdata/src/callgraph_range_over_func.go\")\n\t}\n\n\tfor _, file := range files {\n\t\tt.Run(file, func(t *testing.T) {\n\t\t\tprog, want, err := testProg(t, file, ssa.BuilderMode(0))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"couldn't load test file '%s': %s\", file, err)\n\t\t\t}\n\t\t\tif len(want) == 0 {\n\t\t\t\tt.Fatalf(\"couldn't find want in `%s`\", file)\n\t\t\t}\n\n\t\t\t// First test VTA with lazy-CHA initial call graph.\n\t\t\tg := CallGraph(ssautil.AllFunctions(prog), nil)\n\t\t\tgot := callGraphStr(g)\n\t\t\tif missing := setdiff(want, got); len(missing) > 0 {\n\t\t\t\terrDiff(t, want, got, missing)\n\t\t\t}\n\n\t\t\t// Repeat the test with explicit CHA initial call graph.\n\t\t\tg = CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))\n\t\t\tgot = callGraphStr(g)\n\t\t\tif missing := setdiff(want, got); len(missing) > 0 {\n\t\t\t\terrDiff(t, want, got, missing)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestVTAProgVsFuncSet exemplifies and tests different possibilities\n// enabled by having an arbitrary function set as input to CallGraph\n// instead of the whole program (i.e., ssautil.AllFunctions(prog)).\nfunc TestVTAProgVsFuncSet(t *testing.T) {\n\tprog, want, err := testProg(t, \"testdata/src/callgraph_nested_ptr.go\", ssa.BuilderMode(0))\n\tif err != nil {\n\t\tt.Fatalf(\"couldn't load test `testdata/src/callgraph_nested_ptr.go`: %s\", err)\n\t}\n\tif len(want) == 0 {\n\t\tt.Fatal(\"couldn't find want in `testdata/src/callgraph_nested_ptr.go`\")\n\t}\n\n\tallFuncs := ssautil.AllFunctions(prog)\n\tg := CallGraph(allFuncs, cha.CallGraph(prog))\n\t// VTA over the whole program will produce a call graph that\n\t// includes Baz:(**i).Foo -> A.Foo, B.Foo.\n\tgot := callGraphStr(g)\n\tif diff := setdiff(want, got); len(diff) > 0 {\n\t\tt.Errorf(\"computed callgraph %v should contain %v (diff: %v)\", got, want, diff)\n\t}\n\n\t// Prune the set of program functions to exclude Bar(). This should\n\t// yield a call graph that includes different set of callees for Baz\n\t// Baz:(**i).Foo -> A.Foo\n\t//\n\t// Note that the exclusion of Bar can happen, for instance, if Baz is\n\t// considered an entry point of some data flow analysis and Bar is\n\t// provably (e.g., using CHA forward reachability) unreachable from Baz.\n\tnoBarFuncs := make(map[*ssa.Function]bool)\n\tfor f, in := range allFuncs {\n\t\tnoBarFuncs[f] = in && (funcName(f) != \"Bar\")\n\t}\n\twant = []string{\"Baz: Do(i) -> Do; invoke t2.Foo() -> A.Foo\"}\n\tg = CallGraph(noBarFuncs, cha.CallGraph(prog))\n\tgot = callGraphStr(g)\n\tif diff := setdiff(want, got); len(diff) > 0 {\n\t\tt.Errorf(\"pruned callgraph %v should contain %v (diff: %v)\", got, want, diff)\n\t}\n}\n\n// TestVTAPanicMissingDefinitions tests if VTA gracefully handles the case\n// where VTA panics when a definition of a function or method is not\n// available, which can happen when using analysis package. A successful\n// test simply does not panic.\nfunc TestVTAPanicMissingDefinitions(t *testing.T) {\n\trun := func(pass *analysis.Pass) (any, error) {\n\t\ts := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)\n\t\tCallGraph(ssautil.AllFunctions(s.Pkg.Prog), cha.CallGraph(s.Pkg.Prog))\n\t\treturn nil, nil\n\t}\n\n\tanalyzer := &analysis.Analyzer{\n\t\tName: \"test\",\n\t\tDoc:  \"test\",\n\t\tRun:  run,\n\t\tRequires: []*analysis.Analyzer{\n\t\t\tbuildssa.Analyzer,\n\t\t},\n\t}\n\n\ttestdata := analysistest.TestData()\n\tres := analysistest.Run(t, testdata, analyzer, \"t\", \"d\")\n\tif len(res) != 2 {\n\t\tt.Errorf(\"want analysis results for 2 packages; got %v\", len(res))\n\t}\n\tfor _, r := range res {\n\t\tif r.Err != nil {\n\t\t\tt.Errorf(\"want no error for package %v; got %v\", r.Action.Package.Types.Path(), r.Err)\n\t\t}\n\t}\n}\n\nfunc TestVTACallGraphGenerics(t *testing.T) {\n\t// TODO(zpavlinovic): add more tests\n\tfiles := []string{\n\t\t\"testdata/src/arrays_generics.go\",\n\t\t\"testdata/src/callgraph_generics.go\",\n\t\t\"testdata/src/issue63146.go\",\n\t}\n\tfor _, file := range files {\n\t\tt.Run(file, func(t *testing.T) {\n\t\t\tprog, want, err := testProg(t, file, ssa.InstantiateGenerics)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"couldn't load test file '%s': %s\", file, err)\n\t\t\t}\n\t\t\tif len(want) == 0 {\n\t\t\t\tt.Fatalf(\"couldn't find want in `%s`\", file)\n\t\t\t}\n\n\t\t\tg := CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))\n\t\t\tgot := callGraphStr(g)\n\t\t\tif diff := setdiff(want, got); len(diff) != 0 {\n\t\t\t\tt.Errorf(\"computed callgraph %v should contain %v (diff: %v)\", got, want, diff)\n\t\t\t\tlogFns(t, prog)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestVTACallGraphGo117(t *testing.T) {\n\tfile := \"testdata/src/go117.go\"\n\tprog, want, err := testProg(t, file, ssa.BuilderMode(0))\n\tif err != nil {\n\t\tt.Fatalf(\"couldn't load test file '%s': %s\", file, err)\n\t}\n\tif len(want) == 0 {\n\t\tt.Fatalf(\"couldn't find want in `%s`\", file)\n\t}\n\n\tg, _ := typePropGraph(ssautil.AllFunctions(prog), makeCalleesFunc(nil, cha.CallGraph(prog)))\n\tgot := vtaGraphStr(g)\n\tif diff := setdiff(want, got); len(diff) != 0 {\n\t\tt.Errorf(\"`%s`: want superset of %v;\\n got %v\", file, want, got)\n\t}\n}\n"
  },
  {
    "path": "go/cfg/builder.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cfg\n\n// This file implements the CFG construction pass.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n)\n\ntype builder struct {\n\tblocks    []*Block\n\tmayReturn func(*ast.CallExpr) bool\n\tcurrent   *Block\n\tlblocks   map[string]*lblock // labeled blocks\n\ttargets   *targets           // linked stack of branch targets\n}\n\nfunc (b *builder) stmt(_s ast.Stmt) {\n\t// The label of the current statement.  If non-nil, its _goto\n\t// target is always set; its _break and _continue are set only\n\t// within the body of switch/typeswitch/select/for/range.\n\t// It is effectively an additional default-nil parameter of stmt().\n\tvar label *lblock\nstart:\n\tswitch s := _s.(type) {\n\tcase *ast.BadStmt,\n\t\t*ast.SendStmt,\n\t\t*ast.IncDecStmt,\n\t\t*ast.GoStmt,\n\t\t*ast.EmptyStmt,\n\t\t*ast.AssignStmt:\n\t\t// No effect on control flow.\n\t\tb.add(s)\n\n\tcase *ast.DeferStmt:\n\t\tb.add(s)\n\t\t// Assume conservatively that this behaves like:\n\t\t//    defer func() { recover() }\n\t\t// so any subsequent panic may act like a return.\n\t\tb.current.returns = true\n\n\tcase *ast.ExprStmt:\n\t\tb.add(s)\n\t\tif call, ok := s.X.(*ast.CallExpr); ok && !b.mayReturn(call) {\n\t\t\t// Calls to panic, os.Exit, etc, never return.\n\t\t\tb.current = b.newBlock(KindUnreachable, s)\n\t\t}\n\n\tcase *ast.DeclStmt:\n\t\t// Treat each var ValueSpec as a separate statement.\n\t\td := s.Decl.(*ast.GenDecl)\n\t\tif d.Tok == token.VAR {\n\t\t\tfor _, spec := range d.Specs {\n\t\t\t\tif spec, ok := spec.(*ast.ValueSpec); ok {\n\t\t\t\t\tb.add(spec)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\tlabel = b.labeledBlock(s.Label, s)\n\t\tb.jump(label._goto)\n\t\tb.current = label._goto\n\t\t_s = s.Stmt\n\t\tgoto start // effectively: tailcall stmt(g, s.Stmt, label)\n\n\tcase *ast.ReturnStmt:\n\t\tb.current.returns = true\n\t\tb.add(s)\n\t\tb.current = b.newBlock(KindUnreachable, s)\n\n\tcase *ast.BranchStmt:\n\t\tb.branchStmt(s)\n\n\tcase *ast.BlockStmt:\n\t\tb.stmtList(s.List)\n\n\tcase *ast.IfStmt:\n\t\tif s.Init != nil {\n\t\t\tb.stmt(s.Init)\n\t\t}\n\t\tthen := b.newBlock(KindIfThen, s)\n\t\tdone := b.newBlock(KindIfDone, s)\n\t\t_else := done\n\t\tif s.Else != nil {\n\t\t\t_else = b.newBlock(KindIfElse, s)\n\t\t}\n\t\tb.add(s.Cond)\n\t\tb.ifelse(then, _else)\n\t\tb.current = then\n\t\tb.stmt(s.Body)\n\t\tb.jump(done)\n\n\t\tif s.Else != nil {\n\t\t\tb.current = _else\n\t\t\tb.stmt(s.Else)\n\t\t\tb.jump(done)\n\t\t}\n\n\t\tb.current = done\n\n\tcase *ast.SwitchStmt:\n\t\tb.switchStmt(s, label)\n\n\tcase *ast.TypeSwitchStmt:\n\t\tb.typeSwitchStmt(s, label)\n\n\tcase *ast.SelectStmt:\n\t\tb.selectStmt(s, label)\n\n\tcase *ast.ForStmt:\n\t\tb.forStmt(s, label)\n\n\tcase *ast.RangeStmt:\n\t\tb.rangeStmt(s, label)\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected statement kind: %T\", s))\n\t}\n}\n\nfunc (b *builder) stmtList(list []ast.Stmt) {\n\tfor _, s := range list {\n\t\tb.stmt(s)\n\t}\n}\n\nfunc (b *builder) branchStmt(s *ast.BranchStmt) {\n\tvar block *Block\n\tswitch s.Tok {\n\tcase token.BREAK:\n\t\tif s.Label != nil {\n\t\t\tif lb := b.labeledBlock(s.Label, nil); lb != nil {\n\t\t\t\tblock = lb._break\n\t\t\t}\n\t\t} else {\n\t\t\tfor t := b.targets; t != nil && block == nil; t = t.tail {\n\t\t\t\tblock = t._break\n\t\t\t}\n\t\t}\n\n\tcase token.CONTINUE:\n\t\tif s.Label != nil {\n\t\t\tif lb := b.labeledBlock(s.Label, nil); lb != nil {\n\t\t\t\tblock = lb._continue\n\t\t\t}\n\t\t} else {\n\t\t\tfor t := b.targets; t != nil && block == nil; t = t.tail {\n\t\t\t\tblock = t._continue\n\t\t\t}\n\t\t}\n\n\tcase token.FALLTHROUGH:\n\t\tfor t := b.targets; t != nil && block == nil; t = t.tail {\n\t\t\tblock = t._fallthrough\n\t\t}\n\n\tcase token.GOTO:\n\t\tif s.Label != nil {\n\t\t\tblock = b.labeledBlock(s.Label, nil)._goto\n\t\t}\n\t}\n\tif block == nil { // ill-typed (e.g. undefined label)\n\t\tblock = b.newBlock(KindUnreachable, s)\n\t}\n\tb.jump(block)\n\tb.current = b.newBlock(KindUnreachable, s)\n}\n\nfunc (b *builder) switchStmt(s *ast.SwitchStmt, label *lblock) {\n\tif s.Init != nil {\n\t\tb.stmt(s.Init)\n\t}\n\tif s.Tag != nil {\n\t\tb.add(s.Tag)\n\t}\n\tdone := b.newBlock(KindSwitchDone, s)\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\t// We pull the default case (if present) down to the end.\n\t// But each fallthrough label must point to the next\n\t// body block in source order, so we preallocate a\n\t// body block (fallthru) for the next case.\n\t// Unfortunately this makes for a confusing block order.\n\tvar defaultBody *[]ast.Stmt\n\tvar defaultFallthrough *Block\n\tvar fallthru, defaultBlock *Block\n\tncases := len(s.Body.List)\n\tfor i, clause := range s.Body.List {\n\t\tbody := fallthru\n\t\tif body == nil {\n\t\t\tbody = b.newBlock(KindSwitchCaseBody, clause) // first case only\n\t\t}\n\n\t\t// Preallocate body block for the next case.\n\t\tfallthru = done\n\t\tif i+1 < ncases {\n\t\t\tfallthru = b.newBlock(KindSwitchCaseBody, s.Body.List[i+1])\n\t\t}\n\n\t\tcc := clause.(*ast.CaseClause)\n\t\tif cc.List == nil {\n\t\t\t// Default case.\n\t\t\tdefaultBody = &cc.Body\n\t\t\tdefaultFallthrough = fallthru\n\t\t\tdefaultBlock = body\n\t\t\tcontinue\n\t\t}\n\n\t\tvar nextCond *Block\n\t\tfor _, cond := range cc.List {\n\t\t\tnextCond = b.newBlock(KindSwitchNextCase, cc)\n\t\t\tb.add(cond) // one half of the tag==cond condition\n\t\t\tb.ifelse(body, nextCond)\n\t\t\tb.current = nextCond\n\t\t}\n\t\tb.current = body\n\t\tb.targets = &targets{\n\t\t\ttail:         b.targets,\n\t\t\t_break:       done,\n\t\t\t_fallthrough: fallthru,\n\t\t}\n\t\tb.stmtList(cc.Body)\n\t\tb.targets = b.targets.tail\n\t\tb.jump(done)\n\t\tb.current = nextCond\n\t}\n\tif defaultBlock != nil {\n\t\tb.jump(defaultBlock)\n\t\tb.current = defaultBlock\n\t\tb.targets = &targets{\n\t\t\ttail:         b.targets,\n\t\t\t_break:       done,\n\t\t\t_fallthrough: defaultFallthrough,\n\t\t}\n\t\tb.stmtList(*defaultBody)\n\t\tb.targets = b.targets.tail\n\t}\n\tb.jump(done)\n\tb.current = done\n}\n\nfunc (b *builder) typeSwitchStmt(s *ast.TypeSwitchStmt, label *lblock) {\n\tif s.Init != nil {\n\t\tb.stmt(s.Init)\n\t}\n\tif s.Assign != nil {\n\t\tb.add(s.Assign)\n\t}\n\n\tdone := b.newBlock(KindSwitchDone, s)\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\tvar default_ *ast.CaseClause\n\tfor _, clause := range s.Body.List {\n\t\tcc := clause.(*ast.CaseClause)\n\t\tif cc.List == nil {\n\t\t\tdefault_ = cc\n\t\t\tcontinue\n\t\t}\n\t\tbody := b.newBlock(KindSwitchCaseBody, cc)\n\t\tvar next *Block\n\t\tfor _, casetype := range cc.List {\n\t\t\tnext = b.newBlock(KindSwitchNextCase, cc)\n\t\t\t// casetype is a type, so don't call b.add(casetype).\n\t\t\t// This block logically contains a type assertion,\n\t\t\t// x.(casetype), but it's unclear how to represent x.\n\t\t\t_ = casetype\n\t\t\tb.ifelse(body, next)\n\t\t\tb.current = next\n\t\t}\n\t\tb.current = body\n\t\tb.typeCaseBody(cc, done)\n\t\tb.current = next\n\t}\n\tif default_ != nil {\n\t\tb.typeCaseBody(default_, done)\n\t} else {\n\t\tb.jump(done)\n\t}\n\tb.current = done\n}\n\nfunc (b *builder) typeCaseBody(cc *ast.CaseClause, done *Block) {\n\tb.targets = &targets{\n\t\ttail:   b.targets,\n\t\t_break: done,\n\t}\n\tb.stmtList(cc.Body)\n\tb.targets = b.targets.tail\n\tb.jump(done)\n}\n\nfunc (b *builder) selectStmt(s *ast.SelectStmt, label *lblock) {\n\t// First evaluate channel expressions.\n\t// TODO(adonovan): fix: evaluate only channel exprs here.\n\tfor _, clause := range s.Body.List {\n\t\tif comm := clause.(*ast.CommClause).Comm; comm != nil {\n\t\t\tb.stmt(comm)\n\t\t}\n\t}\n\n\tdone := b.newBlock(KindSelectDone, s)\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\n\tvar defaultBody *[]ast.Stmt\n\tfor _, cc := range s.Body.List {\n\t\tclause := cc.(*ast.CommClause)\n\t\tif clause.Comm == nil {\n\t\t\tdefaultBody = &clause.Body\n\t\t\tcontinue\n\t\t}\n\t\tbody := b.newBlock(KindSelectCaseBody, clause)\n\t\tnext := b.newBlock(KindSelectAfterCase, clause)\n\t\tb.ifelse(body, next)\n\t\tb.current = body\n\t\tb.targets = &targets{\n\t\t\ttail:   b.targets,\n\t\t\t_break: done,\n\t\t}\n\t\tswitch comm := clause.Comm.(type) {\n\t\tcase *ast.ExprStmt: // <-ch\n\t\t\t// nop\n\t\tcase *ast.AssignStmt: // x := <-states[state].Chan\n\t\t\tb.add(comm.Lhs[0])\n\t\t}\n\t\tb.stmtList(clause.Body)\n\t\tb.targets = b.targets.tail\n\t\tb.jump(done)\n\t\tb.current = next\n\t}\n\tif defaultBody != nil {\n\t\tb.targets = &targets{\n\t\t\ttail:   b.targets,\n\t\t\t_break: done,\n\t\t}\n\t\tb.stmtList(*defaultBody)\n\t\tb.targets = b.targets.tail\n\t\tb.jump(done)\n\t}\n\tb.current = done\n}\n\nfunc (b *builder) forStmt(s *ast.ForStmt, label *lblock) {\n\t//\t...init...\n\t//      jump loop\n\t// loop:\n\t//      if cond goto body else done\n\t// body:\n\t//      ...body...\n\t//      jump post\n\t// post:\t\t\t\t (target of continue)\n\t//      ...post...\n\t//      jump loop\n\t// done:                                 (target of break)\n\tif s.Init != nil {\n\t\tb.stmt(s.Init)\n\t}\n\tbody := b.newBlock(KindForBody, s)\n\tdone := b.newBlock(KindForDone, s) // target of 'break'\n\tloop := body                       // target of back-edge\n\tif s.Cond != nil {\n\t\tloop = b.newBlock(KindForLoop, s)\n\t}\n\tcont := loop // target of 'continue'\n\tif s.Post != nil {\n\t\tcont = b.newBlock(KindForPost, s)\n\t}\n\tif label != nil {\n\t\tlabel._break = done\n\t\tlabel._continue = cont\n\t}\n\tb.jump(loop)\n\tb.current = loop\n\tif loop != body {\n\t\tb.add(s.Cond)\n\t\tb.ifelse(body, done)\n\t\tb.current = body\n\t}\n\tb.targets = &targets{\n\t\ttail:      b.targets,\n\t\t_break:    done,\n\t\t_continue: cont,\n\t}\n\tb.stmt(s.Body)\n\tb.targets = b.targets.tail\n\tb.jump(cont)\n\n\tif s.Post != nil {\n\t\tb.current = cont\n\t\tb.stmt(s.Post)\n\t\tb.jump(loop) // back-edge\n\t}\n\tb.current = done\n}\n\nfunc (b *builder) rangeStmt(s *ast.RangeStmt, label *lblock) {\n\tb.add(s.X)\n\n\tif s.Key != nil {\n\t\tb.add(s.Key)\n\t}\n\tif s.Value != nil {\n\t\tb.add(s.Value)\n\t}\n\n\t//      ...\n\t// loop:                                   (target of continue)\n\t// \tif ... goto body else done\n\t// body:\n\t//      ...\n\t// \tjump loop\n\t// done:                                   (target of break)\n\n\tloop := b.newBlock(KindRangeLoop, s)\n\tb.jump(loop)\n\tb.current = loop\n\n\tbody := b.newBlock(KindRangeBody, s)\n\tdone := b.newBlock(KindRangeDone, s)\n\tb.ifelse(body, done)\n\tb.current = body\n\n\tif label != nil {\n\t\tlabel._break = done\n\t\tlabel._continue = loop\n\t}\n\tb.targets = &targets{\n\t\ttail:      b.targets,\n\t\t_break:    done,\n\t\t_continue: loop,\n\t}\n\tb.stmt(s.Body)\n\tb.targets = b.targets.tail\n\tb.jump(loop) // back-edge\n\tb.current = done\n}\n\n// -------- helpers --------\n\n// Destinations associated with unlabeled for/switch/select stmts.\n// We push/pop one of these as we enter/leave each construct and for\n// each BranchStmt we scan for the innermost target of the right type.\ntype targets struct {\n\ttail         *targets // rest of stack\n\t_break       *Block\n\t_continue    *Block\n\t_fallthrough *Block\n}\n\n// Destinations associated with a labeled block.\n// We populate these as labels are encountered in forward gotos or\n// labeled statements.\ntype lblock struct {\n\t_goto     *Block\n\t_break    *Block\n\t_continue *Block\n}\n\n// labeledBlock returns the branch target associated with the\n// specified label, creating it if needed.\nfunc (b *builder) labeledBlock(label *ast.Ident, stmt *ast.LabeledStmt) *lblock {\n\tlb := b.lblocks[label.Name]\n\tif lb == nil {\n\t\tlb = &lblock{_goto: b.newBlock(KindLabel, nil)}\n\t\tif b.lblocks == nil {\n\t\t\tb.lblocks = make(map[string]*lblock)\n\t\t}\n\t\tb.lblocks[label.Name] = lb\n\t}\n\t// Fill in the label later (in case of forward goto).\n\t// Stmt may be set already if labels are duplicated (ill-typed).\n\tif stmt != nil && lb._goto.Stmt == nil {\n\t\tlb._goto.Stmt = stmt\n\t}\n\treturn lb\n}\n\n// newBlock appends a new unconnected basic block to b.cfg's block\n// slice and returns it.\n// It does not automatically become the current block.\n// comment is an optional string for more readable debugging output.\nfunc (b *builder) newBlock(kind BlockKind, stmt ast.Stmt) *Block {\n\tblock := &Block{\n\t\tIndex: int32(len(b.blocks)),\n\t\tKind:  kind,\n\t\tStmt:  stmt,\n\t}\n\tblock.Succs = block.succs2[:0]\n\tb.blocks = append(b.blocks, block)\n\treturn block\n}\n\nfunc (b *builder) add(n ast.Node) {\n\tb.current.Nodes = append(b.current.Nodes, n)\n}\n\n// jump adds an edge from the current block to the target block,\n// and sets b.current to nil.\nfunc (b *builder) jump(target *Block) {\n\tb.current.Succs = append(b.current.Succs, target)\n\tb.current = nil\n}\n\n// ifelse emits edges from the current block to the t and f blocks,\n// and sets b.current to nil.\nfunc (b *builder) ifelse(t, f *Block) {\n\tb.current.Succs = append(b.current.Succs, t, f)\n\tb.current = nil\n}\n"
  },
  {
    "path": "go/cfg/cfg.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cfg constructs a simple control-flow graph (CFG) of the\n// statements and expressions within a single function.\n//\n// Use cfg.New to construct the CFG for a function body.\n//\n// The blocks of the CFG contain all the function's non-control\n// statements.  The CFG does not contain control statements such as If,\n// Switch, Select, and Branch, but does contain their subexpressions;\n// also, each block records the control statement (Block.Stmt) that\n// gave rise to it and its relationship (Block.Kind) to that statement.\n//\n// For example, this source code:\n//\n//\tif x := f(); x != nil {\n//\t\tT()\n//\t} else {\n//\t\tF()\n//\t}\n//\n// produces this CFG:\n//\n//\t1:  x := f()\t\tBody\n//\t    x != nil\n//\t    succs: 2, 3\n//\t2:  T()\t\t\tIfThen\n//\t    succs: 4\n//\t3:  F()\t\t\tIfElse\n//\t    succs: 4\n//\t4:\t\t\tIfDone\n//\n// The CFG does contain Return statements; even implicit returns are\n// materialized (at the position of the function's closing brace).\n//\n// The CFG does not record conditions associated with conditional branch\n// edges, nor the short-circuit semantics of the && and || operators,\n// nor abnormal control flow caused by panic.  If you need this\n// information, use golang.org/x/tools/go/ssa instead.\npackage cfg\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n)\n\n// A CFG represents the control-flow graph of a single function.\n//\n// The entry point is Blocks[0]; there may be multiple return blocks.\ntype CFG struct {\n\tBlocks   []*Block // block[0] is entry; order otherwise undefined\n\tnoreturn bool     // function body lacks a reachable return statement\n}\n\n// NoReturn reports whether the function has no reachable return.\nfunc (cfg *CFG) NoReturn() bool { return cfg.noreturn }\n\n// A Block represents a basic block: a list of statements and\n// expressions that are always evaluated sequentially.\n//\n// A block may have 0-2 successors: zero for a return block or a block\n// that calls a function such as panic that never returns; one for a\n// normal (jump) block; and two for a conditional (if) block.\n//\n// In a conditional block, the last entry in Nodes is the condition and always\n// an [ast.Expr], Succs[0] is the successor if the condition is true, and\n// Succs[1] is the successor if the condition is false.\ntype Block struct {\n\tNodes   []ast.Node // statements, expressions, and ValueSpecs\n\tSuccs   []*Block   // successor nodes in the graph\n\tIndex   int32      // index within CFG.Blocks\n\tLive    bool       // block is reachable from entry\n\treturns bool       // block contains return or defer (which may recover and return)\n\tKind    BlockKind  // block kind\n\tStmt    ast.Stmt   // statement that gave rise to this block (see BlockKind for details)\n\n\tsuccs2 [2]*Block // underlying array for Succs\n}\n\n// A BlockKind identifies the purpose of a block.\n// It also determines the possible types of its Stmt field.\ntype BlockKind uint8\n\nconst (\n\tKindInvalid BlockKind = iota // Stmt=nil\n\n\tKindUnreachable     // unreachable block after {Branch,Return}Stmt / no-return call ExprStmt\n\tKindBody            // function body BlockStmt\n\tKindForBody         // body of ForStmt\n\tKindForDone         // block after ForStmt\n\tKindForLoop         // head of ForStmt\n\tKindForPost         // post condition of ForStmt\n\tKindIfDone          // block after IfStmt\n\tKindIfElse          // else block of IfStmt\n\tKindIfThen          // then block of IfStmt\n\tKindLabel           // labeled block of BranchStmt (Stmt may be nil for dangling label)\n\tKindRangeBody       // body of RangeStmt\n\tKindRangeDone       // block after RangeStmt\n\tKindRangeLoop       // head of RangeStmt\n\tKindSelectCaseBody  // body of SelectStmt\n\tKindSelectDone      // block after SelectStmt\n\tKindSelectAfterCase // block after a CommClause\n\tKindSwitchCaseBody  // body of CaseClause\n\tKindSwitchDone      // block after {Type.}SwitchStmt\n\tKindSwitchNextCase  // secondary expression of a multi-expression CaseClause\n)\n\nfunc (kind BlockKind) String() string {\n\treturn [...]string{\n\t\tKindInvalid:         \"Invalid\",\n\t\tKindUnreachable:     \"Unreachable\",\n\t\tKindBody:            \"Body\",\n\t\tKindForBody:         \"ForBody\",\n\t\tKindForDone:         \"ForDone\",\n\t\tKindForLoop:         \"ForLoop\",\n\t\tKindForPost:         \"ForPost\",\n\t\tKindIfDone:          \"IfDone\",\n\t\tKindIfElse:          \"IfElse\",\n\t\tKindIfThen:          \"IfThen\",\n\t\tKindLabel:           \"Label\",\n\t\tKindRangeBody:       \"RangeBody\",\n\t\tKindRangeDone:       \"RangeDone\",\n\t\tKindRangeLoop:       \"RangeLoop\",\n\t\tKindSelectCaseBody:  \"SelectCaseBody\",\n\t\tKindSelectDone:      \"SelectDone\",\n\t\tKindSelectAfterCase: \"SelectAfterCase\",\n\t\tKindSwitchCaseBody:  \"SwitchCaseBody\",\n\t\tKindSwitchDone:      \"SwitchDone\",\n\t\tKindSwitchNextCase:  \"SwitchNextCase\",\n\t}[kind]\n}\n\n// New returns a new control-flow graph for the specified function body,\n// which must be non-nil.\n//\n// The CFG builder calls mayReturn to determine whether a given function\n// call may return.  For example, calls to panic, os.Exit, and log.Fatal\n// do not return, so the builder can remove infeasible graph edges\n// following such calls.  The builder calls mayReturn only for a\n// CallExpr beneath an ExprStmt.\nfunc New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {\n\tb := builder{\n\t\tmayReturn: mayReturn,\n\t}\n\tb.current = b.newBlock(KindBody, body)\n\tb.stmt(body)\n\n\t// Compute liveness (reachability from entry point),\n\t// breadth-first, marking Block.Live flags.\n\tq := make([]*Block, 0, len(b.blocks))\n\tq = append(q, b.blocks[0]) // entry point\n\tfor len(q) > 0 {\n\t\tb := q[len(q)-1]\n\t\tq = q[:len(q)-1]\n\n\t\tif !b.Live {\n\t\t\tb.Live = true\n\t\t\tq = append(q, b.Succs...)\n\t\t}\n\t}\n\n\t// Does control fall off the end of the function's body?\n\t// Make implicit return explicit.\n\tif b.current != nil && b.current.Live {\n\t\tb.current.returns = true\n\t\tb.add(&ast.ReturnStmt{\n\t\t\tReturn: body.End() - 1,\n\t\t})\n\t}\n\n\t// Is any return (or defer+recover) block reachable?\n\tnoreturn := true\n\tfor _, bl := range b.blocks {\n\t\tif bl.Live && bl.returns {\n\t\t\tnoreturn = false\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn &CFG{Blocks: b.blocks, noreturn: noreturn}\n}\n\nfunc (b *Block) String() string {\n\treturn fmt.Sprintf(\"block %d (%s)\", b.Index, b.comment(nil))\n}\n\nfunc (b *Block) comment(fset *token.FileSet) string {\n\ts := b.Kind.String()\n\tif fset != nil && b.Stmt != nil {\n\t\ts = fmt.Sprintf(\"%s@L%d\", s, fset.Position(b.Stmt.Pos()).Line)\n\t}\n\treturn s\n}\n\n// Return returns the return statement at the end of this block if present, nil\n// otherwise.\n//\n// When control falls off the end of the function, the ReturnStmt is synthetic\n// and its [ast.Node.End] position may be beyond the end of the file.\n//\n// A function that contains no return statement (explicit or implied)\n// may yet return normally, and may even return a nonzero value. For example:\n//\n//\tfunc() (res any) {\n//\t\tdefer func() { res = recover() }()\n//\t\tpanic(123)\n//\t}\nfunc (b *Block) Return() (ret *ast.ReturnStmt) {\n\tif len(b.Nodes) > 0 {\n\t\tret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)\n\t}\n\treturn\n}\n\n// Format formats the control-flow graph for ease of debugging.\nfunc (g *CFG) Format(fset *token.FileSet) string {\n\tvar buf bytes.Buffer\n\tfor _, b := range g.Blocks {\n\t\tfmt.Fprintf(&buf, \".%d: # %s\\n\", b.Index, b.comment(fset))\n\t\tfor _, n := range b.Nodes {\n\t\t\tfmt.Fprintf(&buf, \"\\t%s\\n\", formatNode(fset, n))\n\t\t}\n\t\tif len(b.Succs) > 0 {\n\t\t\tfmt.Fprintf(&buf, \"\\tsuccs:\")\n\t\t\tfor _, succ := range b.Succs {\n\t\t\t\tfmt.Fprintf(&buf, \" %d\", succ.Index)\n\t\t\t}\n\t\t\tbuf.WriteByte('\\n')\n\t\t}\n\t\tbuf.WriteByte('\\n')\n\t}\n\treturn buf.String()\n}\n\n// Dot returns the control-flow graph in the [Dot graph description language].\n// Use a command such as 'dot -Tsvg' to render it in a form viewable in a browser.\n// This method is provided as a debugging aid; the details of the\n// output are unspecified and may change.\n//\n// [Dot graph description language]: ​​https://en.wikipedia.org/wiki/DOT_(graph_description_language)\nfunc (g *CFG) Dot(fset *token.FileSet) string {\n\tvar buf bytes.Buffer\n\tbuf.WriteString(\"digraph CFG {\\n\")\n\tbuf.WriteString(\"  node [shape=box];\\n\")\n\tfor _, b := range g.Blocks {\n\t\t// node label\n\t\tvar text bytes.Buffer\n\t\ttext.WriteString(b.comment(fset))\n\t\tfor _, n := range b.Nodes {\n\t\t\tfmt.Fprintf(&text, \"\\n%s\", formatNode(fset, n))\n\t\t}\n\n\t\t// node and edges\n\t\tfmt.Fprintf(&buf, \"  n%d [label=%q];\\n\", b.Index, &text)\n\t\tfor _, succ := range b.Succs {\n\t\t\tfmt.Fprintf(&buf, \"  n%d -> n%d;\\n\", b.Index, succ.Index)\n\t\t}\n\t}\n\tbuf.WriteString(\"}\\n\")\n\treturn buf.String()\n}\n\nfunc formatNode(fset *token.FileSet, n ast.Node) string {\n\tvar buf bytes.Buffer\n\tformat.Node(&buf, fset, n)\n\t// Indent secondary lines by a tab.\n\treturn string(bytes.Replace(buf.Bytes(), []byte(\"\\n\"), []byte(\"\\n\\t\"), -1))\n}\n"
  },
  {
    "path": "go/cfg/cfg_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cfg_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/cfg\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nconst src = `package main\n\nimport \"log\"\n\nfunc f1() {\n\tlive()\n\treturn\n\tdead()\n}\n\nfunc f2() {\n\tfor {\n\t\tlive()\n\t}\n\tdead()\n}\n\nfunc f3() {\n\tif true { // even known values are ignored\n\t\treturn\n\t}\n\tfor true { // even known values are ignored\n\t\tlive()\n\t}\n\tfor {\n\t\tlive()\n\t}\n\tdead()\n}\n\nfunc f4(x int) {\n\tswitch x {\n\tcase 1:\n\t\tlive()\n\t\tfallthrough\n\tcase 2:\n\t\tlive()\n\t\tlog.Fatal()\n\tdefault:\n\t\tpanic(\"oops\")\n\t}\n\tdead()\n}\n\nfunc f4(ch chan int) {\n\tselect {\n\tcase <-ch:\n\t\tlive()\n\t\treturn\n\tdefault:\n\t\tlive()\n\t\tpanic(\"oops\")\n\t}\n\tdead()\n}\n\nfunc f5(unknown bool) {\n\tfor {\n\t\tif unknown {\n\t\t\tbreak\n\t\t}\n\t\tcontinue\n\t\tdead()\n\t}\n\tlive()\n}\n\nfunc f6(unknown bool) {\nouter:\n\tfor {\n\t\tfor {\n\t\t\tbreak outer\n\t\t\tdead()\n\t\t}\n\t\tdead()\n\t}\n\tlive()\n}\n\nfunc f7() {\n\tfor {\n\t\tbreak nosuchlabel\n\t\tdead()\n\t}\n\tdead()\n}\n\nfunc f8() {\n\tselect{}\n\tdead()\n}\n\nfunc f9(ch chan int) {\n\tselect {\n\tcase <-ch:\n\t\treturn\n\t}\n\tdead()\n}\n\nfunc f10(ch chan int) {\n\tselect {\n\tcase <-ch:\n\t\treturn\n\t\tdead()\n\tdefault:\n\t}\n\tlive()\n}\n`\n\nfunc TestDeadCode(t *testing.T) {\n\t// We'll use dead code detection to verify the CFG.\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"dummy.go\", src, parser.Mode(0))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, decl := range f.Decls {\n\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\tg := cfg.New(decl.Body, mayReturn)\n\n\t\t\t// Print statements in unreachable blocks\n\t\t\t// (in order determined by builder).\n\t\t\tvar buf bytes.Buffer\n\t\t\tfor _, b := range g.Blocks {\n\t\t\t\tif !b.Live {\n\t\t\t\t\tfor _, n := range b.Nodes {\n\t\t\t\t\t\tfmt.Fprintf(&buf, \"\\t%s\\n\", formatNode(fset, n))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check that the result contains \"dead\" at least once but not \"live\".\n\t\t\tif !bytes.Contains(buf.Bytes(), []byte(\"dead\")) ||\n\t\t\t\tbytes.Contains(buf.Bytes(), []byte(\"live\")) {\n\t\t\t\tt.Errorf(\"unexpected dead statements in function %s:\\n%s\",\n\t\t\t\t\tdecl.Name.Name,\n\t\t\t\t\t&buf)\n\t\t\t\tt.Logf(\"control flow graph:\\n%s\", g.Format(fset))\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestSmoke runs the CFG builder on every FuncDecl in the standard\n// library and x/tools. (This is all well-typed code, but it gives\n// some coverage.)\nfunc TestSmoke(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// The Mode API is just hateful.\n\t// https://github.com/golang/go/issues/48226#issuecomment-1948792315\n\tmode := packages.NeedDeps | packages.NeedImports | packages.NeedSyntax | packages.NeedTypes\n\tpkgs, err := packages.Load(&packages.Config{Mode: mode}, \"std\", \"golang.org/x/tools/...\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, pkg := range pkgs {\n\t\tfor _, file := range pkg.Syntax {\n\t\t\tfor _, decl := range file.Decls {\n\t\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && decl.Body != nil {\n\t\t\t\t\tg := cfg.New(decl.Body, mayReturn)\n\n\t\t\t\t\t// Run a few quick sanity checks.\n\t\t\t\t\tfailed := false\n\t\t\t\t\tfor i, b := range g.Blocks {\n\t\t\t\t\t\terrorf := func(format string, args ...any) {\n\t\t\t\t\t\t\tif !failed {\n\t\t\t\t\t\t\t\tt.Errorf(\"%s\\n%s\", pkg.Fset.Position(decl.Pos()), g.Format(pkg.Fset))\n\t\t\t\t\t\t\t\tfailed = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmsg := fmt.Sprintf(format, args...)\n\t\t\t\t\t\t\tt.Errorf(\"block %d: %s\", i, msg)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif b.Kind == cfg.KindInvalid {\n\t\t\t\t\t\t\terrorf(\"invalid Block.Kind %v\", b.Kind)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif b.Stmt == nil && b.Kind != cfg.KindLabel {\n\t\t\t\t\t\t\terrorf(\"nil Block.Stmt (Kind=%v)\", b.Kind)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif i != int(b.Index) {\n\t\t\t\t\t\t\terrorf(\"invalid Block.Index\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// A trivial mayReturn predicate that looks only at syntax, not types.\nfunc mayReturn(call *ast.CallExpr) bool {\n\tswitch fun := call.Fun.(type) {\n\tcase *ast.Ident:\n\t\treturn fun.Name != \"panic\"\n\tcase *ast.SelectorExpr:\n\t\treturn fun.Sel.Name != \"Fatal\"\n\t}\n\treturn true\n}\n\nfunc formatNode(fset *token.FileSet, n ast.Node) string {\n\tvar buf bytes.Buffer\n\tformat.Node(&buf, fset, n)\n\t// Indent secondary lines by a tab.\n\treturn string(bytes.Replace(buf.Bytes(), []byte(\"\\n\"), []byte(\"\\n\\t\"), -1))\n}\n"
  },
  {
    "path": "go/cfg/main.go",
    "content": "//go:build ignore\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The cfg command prints the control-flow graph of the first function\n// or method whose name matches 'funcname' in the specified package.\n//\n// Usage: cfg package funcname\n//\n// Example:\n//\n//\t$ go build -o cfg ./go/cfg/main.go\n//\t$ cfg ./go/cfg stmt | dot -Tsvg > cfg.svg && open cfg.svg\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/cfg\"\n\t\"golang.org/x/tools/go/packages\"\n)\n\nfunc main() {\n\tflag.Parse()\n\tif len(flag.Args()) != 2 {\n\t\tlog.Fatal(\"Usage: package funcname\")\n\t}\n\tpattern, funcname := flag.Args()[0], flag.Args()[1]\n\tpkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax}, pattern)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tos.Exit(1)\n\t}\n\tfor _, pkg := range pkgs {\n\t\tfor _, f := range pkg.Syntax {\n\t\t\tfor _, decl := range f.Decls {\n\t\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\t\tif decl.Name.Name == funcname {\n\t\t\t\t\t\tg := cfg.New(decl.Body, mayReturn)\n\t\t\t\t\t\tfmt.Println(g.Dot(pkg.Fset))\n\t\t\t\t\t\tos.Exit(0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tlog.Fatalf(\"no function %q found in %s\", funcname, pattern)\n}\n\n// A trivial mayReturn predicate that looks only at syntax, not types.\nfunc mayReturn(call *ast.CallExpr) bool {\n\tswitch fun := call.Fun.(type) {\n\tcase *ast.Ident:\n\t\treturn fun.Name != \"panic\"\n\tcase *ast.SelectorExpr:\n\t\treturn fun.Sel.Name != \"Fatal\"\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "go/gccgoexportdata/gccgoexportdata.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gccgoexportdata provides functions for reading export data\n// files containing type information produced by the gccgo compiler.\n//\n// This package is a stop-gap until such time as gccgo uses the same\n// export data format as gc; see Go issue 17573. Once that occurs, this\n// package will be deprecated and eventually deleted.\npackage gccgoexportdata\n\n// TODO(adonovan): add Find, Write, Importer to the API,\n// for symmetry with gcexportdata.\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/internal/gccgoimporter\"\n)\n\n// CompilerInfo executes the specified gccgo compiler and returns\n// information about it: its version (e.g. \"4.8.0\"), its target triple\n// (e.g. \"x86_64-unknown-linux-gnu\"), and the list of directories it\n// searches to find standard packages. The given arguments are passed\n// directly to calls to the specified gccgo compiler.\nfunc CompilerInfo(gccgo string, args ...string) (version, triple string, dirs []string, err error) {\n\tvar inst gccgoimporter.GccgoInstallation\n\terr = inst.InitFromDriver(gccgo, args...)\n\tif err == nil {\n\t\tversion = inst.GccVersion\n\t\ttriple = inst.TargetTriple\n\t\tdirs = inst.SearchPaths()\n\t}\n\treturn\n}\n\n// NewReader returns a reader for the export data section of an object\n// (.o) or archive (.a) file read from r.\nfunc NewReader(r io.Reader) (io.Reader, error) {\n\tdata, err := io.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// If the file is an archive, extract the first section.\n\tconst archiveMagic = \"!<arch>\\n\"\n\tif bytes.HasPrefix(data, []byte(archiveMagic)) {\n\t\tsection, err := firstSection(data[len(archiveMagic):])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdata = section\n\t}\n\n\t// Data contains an ELF file with a .go_export section.\n\t// ELF magic number is \"\\x7fELF\".\n\tef, err := elf.NewFile(bytes.NewReader(data))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsec := ef.Section(\".go_export\")\n\tif sec == nil {\n\t\treturn nil, fmt.Errorf(\"no .go_export section\")\n\t}\n\treturn sec.Open(), nil\n}\n\n// firstSection returns the contents of the first regular file in an ELF\n// archive (http://www.sco.com/developers/devspecs/gabi41.pdf, §7.2).\nfunc firstSection(a []byte) ([]byte, error) {\n\tfor len(a) >= 60 {\n\t\tvar hdr []byte\n\t\thdr, a = a[:60], a[60:]\n\n\t\tname := strings.TrimSpace(string(hdr[:16]))\n\n\t\tsizeStr := string(hdr[48:58])\n\t\tsize, err := strconv.Atoi(strings.TrimSpace(sizeStr))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid size: %q\", sizeStr)\n\t\t}\n\n\t\tif len(a) < size {\n\t\t\treturn nil, fmt.Errorf(\"invalid section size: %d\", size)\n\t\t}\n\n\t\t// The payload is padded to an even number of bytes.\n\t\tvar payload []byte\n\t\tpayload, a = a[:size], a[size+size&1:]\n\n\t\t// Skip special files:\n\t\t//   \"/\"           archive symbol table\n\t\t//   \"/SYM64/\"     archive symbol table on e.g. s390x\n\t\t//   \"//\"          archive string table (if any filename is >15 bytes)\n\t\tif name == \"/\" || name == \"/SYM64/\" || name == \"//\" {\n\t\t\tcontinue\n\t\t}\n\n\t\treturn payload, nil\n\t}\n\treturn nil, fmt.Errorf(\"archive has no regular sections\")\n}\n\n// Read reads export data from in, decodes it, and returns type\n// information for the package.\n// The package name is specified by path.\n//\n// The FileSet parameter is currently unused but exists for symmetry\n// with gcexportdata.\n//\n// Read may inspect and add to the imports map to ensure that references\n// within the export data to other packages are consistent.  The caller\n// must ensure that imports[path] does not exist, or exists but is\n// incomplete (see types.Package.Complete), and Read inserts the\n// resulting package into this map entry.\n//\n// On return, the state of the reader is undefined.\nfunc Read(in io.Reader, _ *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) {\n\treturn gccgoimporter.Parse(in, imports, path)\n}\n"
  },
  {
    "path": "go/gccgoexportdata/gccgoexportdata_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gccgoexportdata_test\n\nimport (\n\t\"go/types\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/gccgoexportdata\"\n)\n\n// Test ensures this package can read gccgo export data from the\n// .go_export from a standalone ELF file or such a file in an archive\n// library.\n//\n// The testdata/{short,long}.a ELF archive files were produced by:\n//\n//\t$ echo 'package foo; func F()' > foo.go\n//\t$ gccgo -c -fgo-pkgpath blah foo.go\n//\t$ objcopy -j .go_export foo.o foo.gox\n//\t$ ar q short.a foo.gox\n//\t$ objcopy -j .go_export foo.o name-longer-than-16-bytes.gox\n//\t$ ar q long.a name-longer-than-16-bytes.gox\n//\n// The file long.a contains an archive string table.\n//\n// The errors.gox file (an ELF object file) comes from the toolchain's\n// standard library.\nfunc Test(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tfilename, path, member, wantType string\n\t}{\n\t\t{\"testdata/errors.gox\", \"errors\", \"New\", \"func(text string) error\"},\n\t\t{\"testdata/short.a\", \"short\", \"F\", \"func()\"},\n\t\t{\"testdata/long.a\", \"long\", \"F\", \"func()\"},\n\t} {\n\t\tt.Logf(\"filename = %s\", test.filename)\n\t\tf, err := os.Open(test.filename)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\t\tdefer f.Close()\n\t\tr, err := gccgoexportdata.NewReader(f)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\n\t\timports := make(map[string]*types.Package)\n\t\tpkg, err := gccgoexportdata.Read(r, nil, imports, test.path)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check type of designated package member.\n\t\tobj := pkg.Scope().Lookup(test.member)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"%s.%s not found\", test.path, test.member)\n\t\t\tcontinue\n\t\t}\n\t\tif obj.Type().String() != test.wantType {\n\t\t\tt.Errorf(\"%s.%s.Type = %s, want %s\",\n\t\t\t\ttest.path, test.member, obj.Type(), test.wantType)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/gcexportdata/example_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.7 && gc && !android && !ios && (unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || plan9 || windows)\n\npackage gcexportdata_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n)\n\n// ExampleRead uses gcexportdata.Read to load type information for the\n// \"fmt\" package from the fmt.a file produced by the gc compiler.\nfunc ExampleRead() {\n\t// Find the export data file.\n\tfilename, path := gcexportdata.Find(\"fmt\", \"\")\n\tif filename == \"\" {\n\t\tlog.Fatalf(\"can't find export data for fmt\")\n\t}\n\tfmt.Printf(\"Package path:       %s\\n\", path)\n\n\t// Open and read the file.\n\tf, err := os.Open(filename)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer f.Close()\n\tr, err := gcexportdata.NewReader(f)\n\tif err != nil {\n\t\tlog.Fatalf(\"reading export data %s: %v\", filename, err)\n\t}\n\n\t// Decode the export data.\n\tfset := token.NewFileSet()\n\timports := make(map[string]*types.Package)\n\tpkg, err := gcexportdata.Read(r, fset, imports, path)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// We can see all the names in Names.\n\tmembers := pkg.Scope().Names()\n\tfoundPrintln := slices.Contains(members, \"Println\")\n\tfmt.Print(\"Package members:    \")\n\tif foundPrintln {\n\t\tfmt.Println(\"Println found\")\n\t} else {\n\t\tfmt.Println(\"Println not found\")\n\t}\n\n\t// We can also look up a name directly using Lookup.\n\tprintln := pkg.Scope().Lookup(\"Println\")\n\t// go 1.18+ uses the 'any' alias\n\ttyp := strings.ReplaceAll(println.Type().String(), \"interface{}\", \"any\")\n\tfmt.Printf(\"Println type:       %s\\n\", typ)\n\tposn := fset.Position(println.Pos())\n\t// make example deterministic\n\tposn.Line = 123\n\tfmt.Printf(\"Println location:   %s\\n\", slashify(posn))\n\n\t// Output:\n\t//\n\t// Package path:       fmt\n\t// Package members:    Println found\n\t// Println type:       func(a ...any) (n int, err error)\n\t// Println location:   $GOROOT/src/fmt/print.go:123:1\n}\n\n// ExampleNewImporter demonstrates usage of NewImporter to provide type\n// information for dependencies when type-checking Go source code.\nfunc ExampleNewImporter() {\n\tconst src = `package myrpc\n\n// choosing a package that doesn't change across releases\nimport \"net/rpc\"\n\nconst serverError rpc.ServerError = \"\"\n`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"myrpc.go\", src, 0)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tpackages := make(map[string]*types.Package)\n\timp := gcexportdata.NewImporter(fset, packages)\n\tconf := types.Config{Importer: imp}\n\tpkg, err := conf.Check(\"myrpc\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// object from imported package\n\tpi := packages[\"net/rpc\"].Scope().Lookup(\"ServerError\")\n\tfmt.Printf(\"type %s.%s %s // %s\\n\",\n\t\tpi.Pkg().Path(),\n\t\tpi.Name(),\n\t\tpi.Type().Underlying(),\n\t\tslashify(fset.Position(pi.Pos())),\n\t)\n\n\t// object in source package\n\ttwopi := pkg.Scope().Lookup(\"serverError\")\n\tfmt.Printf(\"const %s %s = %s // %s\\n\",\n\t\ttwopi.Name(),\n\t\ttwopi.Type(),\n\t\ttwopi.(*types.Const).Val(),\n\t\tslashify(fset.Position(twopi.Pos())),\n\t)\n\n\t// Output:\n\t//\n\t// type net/rpc.ServerError string // $GOROOT/src/net/rpc/client.go:20:1\n\t// const serverError net/rpc.ServerError = \"\" // myrpc.go:6:7\n}\n\nfunc slashify(posn token.Position) token.Position {\n\tposn.Filename = filepath.ToSlash(posn.Filename) // for MS Windows portability\n\treturn posn\n}\n"
  },
  {
    "path": "go/gcexportdata/gcexportdata.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gcexportdata provides functions for reading and writing\n// export data, which is a serialized description of the API of a Go\n// package including the names, kinds, types, and locations of all\n// exported declarations.\n//\n// The standard Go compiler (cmd/compile) writes an export data file\n// for each package it compiles, which it later reads when compiling\n// packages that import the earlier one. The compiler must thus\n// contain logic to both write and read export data.\n// (See the \"Export\" section in the cmd/compile/README file.)\n//\n// The [Read] function in this package can read files produced by the\n// compiler, producing [go/types] data structures. As a matter of\n// policy, Read supports export data files produced by only the last\n// two Go releases plus tip; see https://go.dev/issue/68898. The\n// export data files produced by the compiler contain additional\n// details related to generics, inlining, and other optimizations that\n// cannot be decoded by the [Read] function.\n//\n// In files written by the compiler, the export data is not at the\n// start of the file. Before calling Read, use [NewReader] to locate\n// the desired portion of the file.\n//\n// The [Write] function in this package encodes the exported API of a\n// Go package ([types.Package]) as a file. Such files can be later\n// decoded by Read, but cannot be consumed by the compiler.\n//\n// # Future changes\n//\n// Although Read supports the formats written by both Write and the\n// compiler, the two are quite different, and there is an open\n// proposal (https://go.dev/issue/69491) to separate these APIs.\n//\n// Under that proposal, this package would ultimately provide only the\n// Read operation for compiler export data, which must be defined in\n// this module (golang.org/x/tools), not in the standard library, to\n// avoid version skew for developer tools that need to read compiler\n// export data both before and after a Go release, such as from Go\n// 1.23 to Go 1.24. Because this package lives in the tools module,\n// clients can update their version of the module some time before the\n// Go 1.24 release and rebuild and redeploy their tools, which will\n// then be able to consume both Go 1.23 and Go 1.24 export data files,\n// so they will work before and after the Go update. (See discussion\n// at https://go.dev/issue/15651.)\n//\n// The operations to import and export [go/types] data structures\n// would be defined in the go/types package as Import and Export.\n// [Write] would (eventually) delegate to Export,\n// and [Read], when it detects a file produced by Export,\n// would delegate to Import.\n//\n// # Deprecations\n//\n// The [NewImporter] and [Find] functions are deprecated and should\n// not be used in new code. The [WriteBundle] and [ReadBundle]\n// functions are experimental, and there is an open proposal to\n// deprecate them (https://go.dev/issue/69573).\npackage gcexportdata\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os/exec\"\n\n\t\"golang.org/x/tools/internal/gcimporter\"\n)\n\n// Find returns the name of an object (.o) or archive (.a) file\n// containing type information for the specified import path,\n// using the go command.\n// If no file was found, an empty filename is returned.\n//\n// A relative srcDir is interpreted relative to the current working directory.\n//\n// Find also returns the package's resolved (canonical) import path,\n// reflecting the effects of srcDir and vendoring on importPath.\n//\n// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,\n// which is more efficient.\nfunc Find(importPath, srcDir string) (filename, path string) {\n\tcmd := exec.Command(\"go\", \"list\", \"-json\", \"-export\", \"--\", importPath)\n\tcmd.Dir = srcDir\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\treturn \"\", \"\"\n\t}\n\tvar data struct {\n\t\tImportPath string\n\t\tExport     string\n\t}\n\tjson.Unmarshal(out, &data)\n\treturn data.Export, data.ImportPath\n}\n\n// NewReader returns a reader for the export data section of an object\n// (.o) or archive (.a) file read from r.  The new reader may provide\n// additional trailing data beyond the end of the export data.\nfunc NewReader(r io.Reader) (io.Reader, error) {\n\tbuf := bufio.NewReader(r)\n\tsize, err := gcimporter.FindExportData(buf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// We were given an archive and found the __.PKGDEF in it.\n\t// This tells us the size of the export data, and we don't\n\t// need to return the entire file.\n\treturn &io.LimitedReader{\n\t\tR: buf,\n\t\tN: size,\n\t}, nil\n}\n\n// readAll works the same way as io.ReadAll, but avoids allocations and copies\n// by preallocating a byte slice of the necessary size if the size is known up\n// front. This is always possible when the input is an archive. In that case,\n// NewReader will return the known size using an io.LimitedReader.\nfunc readAll(r io.Reader) ([]byte, error) {\n\tif lr, ok := r.(*io.LimitedReader); ok {\n\t\tdata := make([]byte, lr.N)\n\t\t_, err := io.ReadFull(lr, data)\n\t\treturn data, err\n\t}\n\treturn io.ReadAll(r)\n}\n\n// Read reads export data from in, decodes it, and returns type\n// information for the package.\n//\n// Read is capable of reading export data produced by [Write] at the\n// same source code version, or by the last two Go releases (plus tip)\n// of the standard Go compiler. Reading files from older compilers may\n// produce an error.\n//\n// The package path (effectively its linker symbol prefix) is\n// specified by path, since unlike the package name, this information\n// may not be recorded in the export data.\n//\n// File position information is added to fset.\n//\n// Read may inspect and add to the imports map to ensure that references\n// within the export data to other packages are consistent.  The caller\n// must ensure that imports[path] does not exist, or exists but is\n// incomplete (see types.Package.Complete), and Read inserts the\n// resulting package into this map entry.\n//\n// On return, the state of the reader is undefined.\nfunc Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) {\n\tdata, err := readAll(in)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading export data for %q: %v\", path, err)\n\t}\n\n\tif bytes.HasPrefix(data, []byte(\"!<arch>\")) {\n\t\treturn nil, fmt.Errorf(\"can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)\", path)\n\t}\n\n\t// The indexed export format starts with an 'i'; the older\n\t// binary export format starts with a 'c', 'd', or 'v'\n\t// (from \"version\"). Select appropriate importer.\n\tif len(data) > 0 {\n\t\tswitch data[0] {\n\t\tcase 'v', 'c', 'd':\n\t\t\t// binary, produced by cmd/compile till go1.10\n\t\t\treturn nil, fmt.Errorf(\"binary (%c) import format is no longer supported\", data[0])\n\n\t\tcase 'i':\n\t\t\t// indexed, produced by cmd/compile till go1.19,\n\t\t\t// and also by [Write].\n\t\t\t//\n\t\t\t// If proposal #69491 is accepted, go/types\n\t\t\t// serialization will be implemented by\n\t\t\t// types.Export, to which Write would eventually\n\t\t\t// delegate (explicitly dropping any pretence at\n\t\t\t// inter-version Write-Read compatibility).\n\t\t\t// This [Read] function would delegate to types.Import\n\t\t\t// when it detects that the file was produced by Export.\n\t\t\t_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)\n\t\t\treturn pkg, err\n\n\t\tcase 'u':\n\t\t\t// unified, produced by cmd/compile since go1.20\n\t\t\t_, pkg, err := gcimporter.UImportData(fset, imports, data[1:], path)\n\t\t\treturn pkg, err\n\n\t\tdefault:\n\t\t\tl := min(len(data), 10)\n\t\t\treturn nil, fmt.Errorf(\"unexpected export data with prefix %q for path %s\", string(data[:l]), path)\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"empty export data for %s\", path)\n}\n\n// Write writes encoded type information for the specified package to out.\n// The FileSet provides file position information for named objects.\nfunc Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error {\n\tif _, err := io.WriteString(out, \"i\"); err != nil {\n\t\treturn err\n\t}\n\treturn gcimporter.IExportData(out, fset, pkg)\n}\n\n// ReadBundle reads an export bundle from in, decodes it, and returns type\n// information for the packages.\n// File position information is added to fset.\n//\n// ReadBundle may inspect and add to the imports map to ensure that references\n// within the export bundle to other packages are consistent.\n//\n// On return, the state of the reader is undefined.\n//\n// Experimental: This API is experimental and may change in the future.\nfunc ReadBundle(in io.Reader, fset *token.FileSet, imports map[string]*types.Package) ([]*types.Package, error) {\n\tdata, err := readAll(in)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading export bundle: %v\", err)\n\t}\n\treturn gcimporter.IImportBundle(fset, imports, data)\n}\n\n// WriteBundle writes encoded type information for the specified packages to out.\n// The FileSet provides file position information for named objects.\n//\n// Experimental: This API is experimental and may change in the future.\nfunc WriteBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {\n\treturn gcimporter.IExportBundle(out, fset, pkgs)\n}\n"
  },
  {
    "path": "go/gcexportdata/importer.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcexportdata\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n)\n\n// NewImporter returns a new instance of the types.Importer interface\n// that reads type information from export data files written by gc.\n// The Importer also satisfies types.ImporterFrom.\n//\n// Export data files are located using \"go build\" workspace conventions\n// and the build.Default context.\n//\n// Use this importer instead of go/importer.For(\"gc\", ...) to avoid the\n// version-skew problems described in the documentation of this package,\n// or to control the FileSet or access the imports map populated during\n// package loading.\n//\n// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,\n// which is more efficient.\nfunc NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom {\n\treturn importer{fset, imports}\n}\n\ntype importer struct {\n\tfset    *token.FileSet\n\timports map[string]*types.Package\n}\n\nfunc (imp importer) Import(importPath string) (*types.Package, error) {\n\treturn imp.ImportFrom(importPath, \"\", 0)\n}\n\nfunc (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) {\n\tfilename, path := Find(importPath, srcDir)\n\tif filename == \"\" {\n\t\tif importPath == \"unsafe\" {\n\t\t\t// Even for unsafe, call Find first in case\n\t\t\t// the package was vendored.\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"can't find import: %s\", importPath)\n\t}\n\n\tif pkg, ok := imp.imports[path]; ok && pkg.Complete() {\n\t\treturn pkg, nil // cache hit\n\t}\n\n\t// open file\n\tf, err := os.Open(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\tf.Close()\n\t\tif err != nil {\n\t\t\t// add file name to error\n\t\t\terr = fmt.Errorf(\"reading export data: %s: %v\", filename, err)\n\t\t}\n\t}()\n\n\tr, err := NewReader(f)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn Read(r, imp.fset, imp.imports, path)\n}\n"
  },
  {
    "path": "go/gcexportdata/main.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The gcexportdata command is a diagnostic tool that displays the\n// contents of gc export data files.\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\nvar packageFlag = flag.String(\"package\", \"\", \"alternative package to print\")\n\nfunc main() {\n\tlog.SetPrefix(\"gcexportdata: \")\n\tlog.SetFlags(0)\n\tflag.Usage = func() {\n\t\tfmt.Fprintln(os.Stderr, \"usage: gcexportdata [-package path] file.a\")\n\t}\n\tflag.Parse()\n\tif flag.NArg() != 1 {\n\t\tflag.Usage()\n\t\tos.Exit(2)\n\t}\n\tfilename := flag.Args()[0]\n\n\tf, err := os.Open(filename)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tr, err := gcexportdata.NewReader(f)\n\tif err != nil {\n\t\tlog.Fatalf(\"%s: %s\", filename, err)\n\t}\n\n\t// Decode the package.\n\tconst primary = \"<primary>\"\n\timports := make(map[string]*types.Package)\n\tfset := token.NewFileSet()\n\tpkg, err := gcexportdata.Read(r, fset, imports, primary)\n\tif err != nil {\n\t\tlog.Fatalf(\"%s: %s\", filename, err)\n\t}\n\n\t// Optionally select an indirectly mentioned package.\n\tif *packageFlag != \"\" {\n\t\tpkg = imports[*packageFlag]\n\t\tif pkg == nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"export data file %s does not mention %s; has:\\n\",\n\t\t\t\tfilename, *packageFlag)\n\t\t\tfor p := range imports {\n\t\t\t\tif p != primary {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"\\t%s\\n\", p)\n\t\t\t\t}\n\t\t\t}\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\t// Print all package-level declarations, including non-exported ones.\n\tfmt.Printf(\"package %s\\n\", pkg.Name())\n\tfor _, imp := range pkg.Imports() {\n\t\tfmt.Printf(\"import %q\\n\", imp.Path())\n\t}\n\tqual := func(p *types.Package) string {\n\t\tif pkg == p {\n\t\t\treturn \"\"\n\t\t}\n\t\treturn p.Name()\n\t}\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\tfset.Position(obj.Pos()),\n\t\t\ttypes.ObjectString(obj, qual))\n\n\t\t// For types, print each method.\n\t\tif _, ok := obj.(*types.TypeName); ok {\n\t\t\tfor _, method := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {\n\t\t\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\t\t\tfset.Position(method.Obj().Pos()),\n\t\t\t\t\ttypes.SelectionString(method, qual))\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/internal/cgo/cgo.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cgo handles cgo preprocessing of files containing `import \"C\"`.\n//\n// DESIGN\n//\n// The approach taken is to run the cgo processor on the package's\n// CgoFiles and parse the output, faking the filenames of the\n// resulting ASTs so that the synthetic file containing the C types is\n// called \"C\" (e.g. \"~/go/src/net/C\") and the preprocessed files\n// have their original names (e.g. \"~/go/src/net/cgo_unix.go\"),\n// not the names of the actual temporary files.\n//\n// The advantage of this approach is its fidelity to 'go build'.  The\n// downside is that the token.Position.Offset for each AST node is\n// incorrect, being an offset within the temporary file.  Line numbers\n// should still be correct because of the //line comments.\n//\n// The logic of this file is mostly plundered from the 'go build'\n// tool, which also invokes the cgo preprocessor.\n//\n//\n// REJECTED ALTERNATIVE\n//\n// An alternative approach that we explored is to extend go/types'\n// Importer mechanism to provide the identity of the importing package\n// so that each time `import \"C\"` appears it resolves to a different\n// synthetic package containing just the objects needed in that case.\n// The loader would invoke cgo but parse only the cgo_types.go file\n// defining the package-level objects, discarding the other files\n// resulting from preprocessing.\n//\n// The benefit of this approach would have been that source-level\n// syntax information would correspond exactly to the original cgo\n// file, with no preprocessing involved, making source tools like\n// godoc, guru, and eg happy.  However, the approach was rejected\n// due to the additional complexity it would impose on go/types.  (It\n// made for a beautiful demo, though.)\n//\n// cgo files, despite their *.go extension, are not legal Go source\n// files per the specification since they may refer to unexported\n// members of package \"C\" such as C.int.  Also, a function such as\n// C.getpwent has in effect two types, one matching its C type and one\n// which additionally returns (errno C.int).  The cgo preprocessor\n// uses name mangling to distinguish these two functions in the\n// processed code, but go/types would need to duplicate this logic in\n// its handling of function calls, analogous to the treatment of map\n// lookups in which y=m[k] and y,ok=m[k] are both legal.\n\npackage cgo\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// ProcessFiles invokes the cgo preprocessor on bp.CgoFiles, parses\n// the output and returns the resulting ASTs.\nfunc ProcessFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) {\n\ttmpdir, err := os.MkdirTemp(\"\", strings.Replace(bp.ImportPath, \"/\", \"_\", -1)+\"_C\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer os.RemoveAll(tmpdir)\n\n\tpkgdir := bp.Dir\n\tif DisplayPath != nil {\n\t\tpkgdir = DisplayPath(pkgdir)\n\t}\n\n\tcgoFiles, cgoDisplayFiles, err := Run(bp, pkgdir, tmpdir, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar files []*ast.File\n\tfor i := range cgoFiles {\n\t\trd, err := os.Open(cgoFiles[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdisplay := filepath.Join(bp.Dir, cgoDisplayFiles[i])\n\t\tf, err := parser.ParseFile(fset, display, rd, mode)\n\t\trd.Close()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfiles = append(files, f)\n\t}\n\treturn files, nil\n}\n\nvar cgoRe = regexp.MustCompile(`[/\\\\:]`)\n\n// Run invokes the cgo preprocessor on bp.CgoFiles and returns two\n// lists of files: the resulting processed files (in temporary\n// directory tmpdir) and the corresponding names of the unprocessed files.\n//\n// Run is adapted from (*builder).cgo in\n// $GOROOT/src/cmd/go/build.go, but these features are unsupported:\n// Objective C, CGOPKGPATH, CGO_FLAGS.\n//\n// If useabs is set to true, absolute paths of the bp.CgoFiles will be passed in\n// to the cgo preprocessor. This in turn will set the // line comments\n// referring to those files to use absolute paths. This is needed for\n// go/packages using the legacy go list support so it is able to find\n// the original files.\nfunc Run(bp *build.Package, pkgdir, tmpdir string, useabs bool) (files, displayFiles []string, err error) {\n\tcgoCPPFLAGS, _, _, _ := cflags(bp, true)\n\t_, cgoexeCFLAGS, _, _ := cflags(bp, false)\n\n\tif len(bp.CgoPkgConfig) > 0 {\n\t\tpcCFLAGS, err := pkgConfigFlags(bp)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tcgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)\n\t}\n\n\t// Allows including _cgo_export.h from .[ch] files in the package.\n\tcgoCPPFLAGS = append(cgoCPPFLAGS, \"-I\", tmpdir)\n\n\t// _cgo_gotypes.go (displayed \"C\") contains the type definitions.\n\tfiles = append(files, filepath.Join(tmpdir, \"_cgo_gotypes.go\"))\n\tdisplayFiles = append(displayFiles, \"C\")\n\tfor _, fn := range bp.CgoFiles {\n\t\t// \"foo.cgo1.go\" (displayed \"foo.go\") is the processed Go source.\n\t\tf := cgoRe.ReplaceAllString(fn[:len(fn)-len(\"go\")], \"_\")\n\t\tfiles = append(files, filepath.Join(tmpdir, f+\"cgo1.go\"))\n\t\tdisplayFiles = append(displayFiles, fn)\n\t}\n\n\tvar cgoflags []string\n\tif bp.Goroot && bp.ImportPath == \"runtime/cgo\" {\n\t\tcgoflags = append(cgoflags, \"-import_runtime_cgo=false\")\n\t}\n\tif bp.Goroot && bp.ImportPath == \"runtime/race\" || bp.ImportPath == \"runtime/cgo\" {\n\t\tcgoflags = append(cgoflags, \"-import_syscall=false\")\n\t}\n\n\tvar cgoFiles []string = bp.CgoFiles\n\tif useabs {\n\t\tcgoFiles = make([]string, len(bp.CgoFiles))\n\t\tfor i := range cgoFiles {\n\t\t\tcgoFiles[i] = filepath.Join(pkgdir, bp.CgoFiles[i])\n\t\t}\n\t}\n\n\targs := stringList(\n\t\t\"go\", \"tool\", \"cgo\", \"-objdir\", tmpdir, cgoflags, \"--\",\n\t\tcgoCPPFLAGS, cgoexeCFLAGS, cgoFiles,\n\t)\n\tif false {\n\t\tlog.Printf(\"Running cgo for package %q: %s (dir=%s)\", bp.ImportPath, args, pkgdir)\n\t}\n\tcmd := exec.Command(args[0], args[1:]...)\n\tcmd.Dir = pkgdir\n\tcmd.Env = append(os.Environ(), \"PWD=\"+pkgdir)\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"cgo failed: %s: %s\", args, err)\n\t}\n\n\treturn files, displayFiles, nil\n}\n\n// -- unmodified from 'go build' ---------------------------------------\n\n// Return the flags to use when invoking the C or C++ compilers, or cgo.\nfunc cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {\n\tvar defaults string\n\tif def {\n\t\tdefaults = \"-g -O2\"\n\t}\n\n\tcppflags = stringList(envList(\"CGO_CPPFLAGS\", \"\"), p.CgoCPPFLAGS)\n\tcflags = stringList(envList(\"CGO_CFLAGS\", defaults), p.CgoCFLAGS)\n\tcxxflags = stringList(envList(\"CGO_CXXFLAGS\", defaults), p.CgoCXXFLAGS)\n\tldflags = stringList(envList(\"CGO_LDFLAGS\", defaults), p.CgoLDFLAGS)\n\treturn\n}\n\n// envList returns the value of the given environment variable broken\n// into fields, using the default value when the variable is empty.\nfunc envList(key, def string) []string {\n\tv := os.Getenv(key)\n\tif v == \"\" {\n\t\tv = def\n\t}\n\treturn strings.Fields(v)\n}\n\n// stringList's arguments should be a sequence of string or []string values.\n// stringList flattens them into a single []string.\nfunc stringList(args ...any) []string {\n\tvar x []string\n\tfor _, arg := range args {\n\t\tswitch arg := arg.(type) {\n\t\tcase []string:\n\t\t\tx = append(x, arg...)\n\t\tcase string:\n\t\t\tx = append(x, arg)\n\t\tdefault:\n\t\t\tpanic(\"stringList: invalid argument\")\n\t\t}\n\t}\n\treturn x\n}\n"
  },
  {
    "path": "go/internal/cgo/cgo_pkgconfig.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cgo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"os/exec\"\n\t\"strings\"\n)\n\n// pkgConfig runs pkg-config with the specified arguments and returns the flags it prints.\nfunc pkgConfig(mode string, pkgs []string) (flags []string, err error) {\n\tcmd := exec.Command(\"pkg-config\", append([]string{mode}, pkgs...)...)\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\ts := fmt.Sprintf(\"%s failed: %v\", strings.Join(cmd.Args, \" \"), err)\n\t\tif len(out) > 0 {\n\t\t\ts = fmt.Sprintf(\"%s: %s\", s, out)\n\t\t}\n\t\tif err, ok := err.(*exec.ExitError); ok && len(err.Stderr) > 0 {\n\t\t\ts = fmt.Sprintf(\"%s\\nstderr:\\n%s\", s, err.Stderr)\n\t\t}\n\t\treturn nil, errors.New(s)\n\t}\n\tif len(out) > 0 {\n\t\tflags = strings.Fields(string(out))\n\t}\n\treturn\n}\n\n// pkgConfigFlags calls pkg-config if needed and returns the cflags\n// needed to build the package.\nfunc pkgConfigFlags(p *build.Package) (cflags []string, err error) {\n\tif len(p.CgoPkgConfig) == 0 {\n\t\treturn nil, nil\n\t}\n\treturn pkgConfig(\"--cflags\", p.CgoPkgConfig)\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/ar.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter.\n\npackage gccgoimporter\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Magic strings for different archive file formats.\nconst (\n\tarmag  = \"!<arch>\\n\"\n\tarmagt = \"!<thin>\\n\"\n\tarmagb = \"<bigaf>\\n\"\n)\n\n// Offsets and sizes for fields in a standard archive header.\nconst (\n\tarNameOff  = 0\n\tarNameSize = 16\n\tarDateOff  = arNameOff + arNameSize\n\tarDateSize = 12\n\tarUIDOff   = arDateOff + arDateSize\n\tarUIDSize  = 6\n\tarGIDOff   = arUIDOff + arUIDSize\n\tarGIDSize  = 6\n\tarModeOff  = arGIDOff + arGIDSize\n\tarModeSize = 8\n\tarSizeOff  = arModeOff + arModeSize\n\tarSizeSize = 10\n\tarFmagOff  = arSizeOff + arSizeSize\n\tarFmagSize = 2\n\n\tarHdrSize = arFmagOff + arFmagSize\n)\n\n// The contents of the fmag field of a standard archive header.\nconst arfmag = \"`\\n\"\n\n// arExportData takes an archive file and returns a ReadSeeker for the\n// export data in that file. This assumes that there is only one\n// object in the archive containing export data, which is not quite\n// what gccgo does; gccgo concatenates together all the export data\n// for all the objects in the file.  In practice that case does not arise.\nfunc arExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {\n\tif _, err := archive.Seek(0, io.SeekStart); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar buf [len(armag)]byte\n\tif _, err := archive.Read(buf[:]); err != nil {\n\t\treturn nil, err\n\t}\n\n\tswitch string(buf[:]) {\n\tcase armag:\n\t\treturn standardArExportData(archive)\n\tcase armagt:\n\t\treturn nil, errors.New(\"unsupported thin archive\")\n\tcase armagb:\n\t\treturn nil, errors.New(\"unsupported AIX big archive\")\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unrecognized archive file format %q\", buf[:])\n\t}\n}\n\n// standardArExportData returns export data form a standard archive.\nfunc standardArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {\n\toff := int64(len(armag))\n\tfor {\n\t\tvar hdrBuf [arHdrSize]byte\n\t\tif _, err := archive.Read(hdrBuf[:]); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\toff += arHdrSize\n\n\t\tif !bytes.Equal(hdrBuf[arFmagOff:arFmagOff+arFmagSize], []byte(arfmag)) {\n\t\t\treturn nil, fmt.Errorf(\"archive header format header (%q)\", hdrBuf[:])\n\t\t}\n\n\t\tsize, err := strconv.ParseInt(strings.TrimSpace(string(hdrBuf[arSizeOff:arSizeOff+arSizeSize])), 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing size in archive header (%q): %v\", hdrBuf[:], err)\n\t\t}\n\n\t\tfn := hdrBuf[arNameOff : arNameOff+arNameSize]\n\t\tif fn[0] == '/' && (fn[1] == ' ' || fn[1] == '/' || bytes.Equal(fn[:8], []byte(\"/SYM64/ \"))) {\n\t\t\t// Archive symbol table or extended name table,\n\t\t\t// which we don't care about.\n\t\t} else {\n\t\t\tarchiveAt := readerAtFromSeeker(archive)\n\t\t\tret, err := elfFromAr(io.NewSectionReader(archiveAt, off, size))\n\t\t\tif ret != nil || err != nil {\n\t\t\t\treturn ret, err\n\t\t\t}\n\t\t}\n\n\t\tif size&1 != 0 {\n\t\t\tsize++\n\t\t}\n\t\toff += size\n\t\tif _, err := archive.Seek(off, io.SeekStart); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n}\n\n// elfFromAr tries to get export data from an archive member as an ELF file.\n// If there is no export data, this returns nil, nil.\nfunc elfFromAr(member *io.SectionReader) (io.ReadSeeker, error) {\n\tef, err := elf.NewFile(member)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsec := ef.Section(\".go_export\")\n\tif sec == nil {\n\t\treturn nil, nil\n\t}\n\treturn sec.Open(), nil\n}\n\n// readerAtFromSeeker turns an io.ReadSeeker into an io.ReaderAt.\n// This is only safe because there won't be any concurrent seeks\n// while this code is executing.\nfunc readerAtFromSeeker(rs io.ReadSeeker) io.ReaderAt {\n\tif ret, ok := rs.(io.ReaderAt); ok {\n\t\treturn ret\n\t}\n\treturn seekerReadAt{rs}\n}\n\ntype seekerReadAt struct {\n\tseeker io.ReadSeeker\n}\n\nfunc (sra seekerReadAt) ReadAt(p []byte, off int64) (int, error) {\n\tif _, err := sra.seeker.Seek(off, io.SeekStart); err != nil {\n\t\treturn 0, err\n\t}\n\treturn sra.seeker.Read(p)\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/backdoor.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file opens a back door to the parser for golang.org/x/tools/go/gccgoexportdata.\n\npackage gccgoimporter\n\nimport (\n\t\"go/types\"\n\t\"io\"\n)\n\n// Parse reads and parses gccgo export data from in and constructs a\n// Package, inserting it into the imports map.\nfunc Parse(in io.Reader, imports map[string]*types.Package, path string) (_ *types.Package, err error) {\n\tvar p parser\n\tp.init(path, in, imports)\n\tdefer func() {\n\t\tswitch x := recover().(type) {\n\t\tcase nil:\n\t\t\t// success\n\t\tcase importError:\n\t\t\terr = x\n\t\tdefault:\n\t\t\tpanic(x) // resume unexpected panic\n\t\t}\n\t}()\n\tpkg := p.parsePackage()\n\timports[path] = pkg\n\treturn pkg, err\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/gccgoinstallation.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter.\n\npackage gccgoimporter\n\nimport (\n\t\"bufio\"\n\t\"go/types\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// Information about a specific installation of gccgo.\ntype GccgoInstallation struct {\n\t// Version of gcc (e.g. 4.8.0).\n\tGccVersion string\n\n\t// Target triple (e.g. x86_64-unknown-linux-gnu).\n\tTargetTriple string\n\n\t// Built-in library paths used by this installation.\n\tLibPaths []string\n}\n\n// Ask the driver at the given path for information for this GccgoInstallation.\n// The given arguments are passed directly to the call of the driver.\nfunc (inst *GccgoInstallation) InitFromDriver(gccgoPath string, args ...string) (err error) {\n\targv := append([]string{\"-###\", \"-S\", \"-x\", \"go\", \"-\"}, args...)\n\tcmd := exec.Command(gccgoPath, argv...)\n\tstderr, err := cmd.StderrPipe()\n\tif err != nil {\n\t\treturn\n\t}\n\n\terr = cmd.Start()\n\tif err != nil {\n\t\treturn\n\t}\n\n\tscanner := bufio.NewScanner(stderr)\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\t\tswitch {\n\t\tcase strings.HasPrefix(line, \"Target: \"):\n\t\t\tinst.TargetTriple = line[8:]\n\n\t\tcase line[0] == ' ':\n\t\t\targs := strings.Fields(line)\n\t\t\tfor _, arg := range args[1:] {\n\t\t\t\tif strings.HasPrefix(arg, \"-L\") {\n\t\t\t\t\tinst.LibPaths = append(inst.LibPaths, arg[2:])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\targv = append([]string{\"-dumpversion\"}, args...)\n\tstdout, err := exec.Command(gccgoPath, argv...).Output()\n\tif err != nil {\n\t\treturn\n\t}\n\tinst.GccVersion = strings.TrimSpace(string(stdout))\n\n\treturn\n}\n\n// Return the list of export search paths for this GccgoInstallation.\nfunc (inst *GccgoInstallation) SearchPaths() (paths []string) {\n\tfor _, lpath := range inst.LibPaths {\n\t\tspath := filepath.Join(lpath, \"go\", inst.GccVersion)\n\t\tfi, err := os.Stat(spath)\n\t\tif err != nil || !fi.IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tpaths = append(paths, spath)\n\n\t\tspath = filepath.Join(spath, inst.TargetTriple)\n\t\tfi, err = os.Stat(spath)\n\t\tif err != nil || !fi.IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tpaths = append(paths, spath)\n\t}\n\n\tpaths = append(paths, inst.LibPaths...)\n\n\treturn\n}\n\n// Return an importer that searches incpaths followed by the gcc installation's\n// built-in search paths and the current directory.\nfunc (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer {\n\treturn GetImporter(append(append(incpaths, inst.SearchPaths()...), \".\"), initmap)\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/gccgoinstallation_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter.\n\npackage gccgoimporter\n\nimport (\n\t\"go/types\"\n\t\"runtime\"\n\t\"testing\"\n)\n\n// importablePackages is a list of packages that we verify that we can\n// import. This should be all standard library packages in all relevant\n// versions of gccgo. Note that since gccgo follows a different release\n// cycle, and since different systems have different versions installed,\n// we can't use the last-two-versions rule of the gc toolchain.\nvar importablePackages = [...]string{\n\t\"archive/tar\",\n\t\"archive/zip\",\n\t\"bufio\",\n\t\"bytes\",\n\t\"compress/bzip2\",\n\t\"compress/flate\",\n\t\"compress/gzip\",\n\t\"compress/lzw\",\n\t\"compress/zlib\",\n\t\"container/heap\",\n\t\"container/list\",\n\t\"container/ring\",\n\t\"crypto/aes\",\n\t\"crypto/cipher\",\n\t\"crypto/des\",\n\t\"crypto/dsa\",\n\t\"crypto/ecdsa\",\n\t\"crypto/elliptic\",\n\t\"crypto\",\n\t\"crypto/hmac\",\n\t\"crypto/md5\",\n\t\"crypto/rand\",\n\t\"crypto/rc4\",\n\t\"crypto/rsa\",\n\t\"crypto/sha1\",\n\t\"crypto/sha256\",\n\t\"crypto/sha512\",\n\t\"crypto/subtle\",\n\t\"crypto/tls\",\n\t\"crypto/x509\",\n\t\"crypto/x509/pkix\",\n\t\"database/sql/driver\",\n\t\"database/sql\",\n\t\"debug/dwarf\",\n\t\"debug/elf\",\n\t\"debug/gosym\",\n\t\"debug/macho\",\n\t\"debug/pe\",\n\t\"encoding/ascii85\",\n\t\"encoding/asn1\",\n\t\"encoding/base32\",\n\t\"encoding/base64\",\n\t\"encoding/binary\",\n\t\"encoding/csv\",\n\t\"encoding/gob\",\n\t// \"encoding\", // Added in GCC 4.9.\n\t\"encoding/hex\",\n\t\"encoding/json\",\n\t\"encoding/pem\",\n\t\"encoding/xml\",\n\t\"errors\",\n\t\"expvar\",\n\t\"flag\",\n\t\"fmt\",\n\t\"go/ast\",\n\t\"go/build\",\n\t\"go/doc\",\n\t// \"go/format\", // Added in GCC 4.8.\n\t\"go/parser\",\n\t\"go/printer\",\n\t\"go/scanner\",\n\t\"go/token\",\n\t\"hash/adler32\",\n\t\"hash/crc32\",\n\t\"hash/crc64\",\n\t\"hash/fnv\",\n\t\"hash\",\n\t\"html\",\n\t\"html/template\",\n\t\"image/color\",\n\t// \"image/color/palette\", // Added in GCC 4.9.\n\t\"image/draw\",\n\t\"image/gif\",\n\t\"image\",\n\t\"image/jpeg\",\n\t\"image/png\",\n\t\"index/suffixarray\",\n\t\"io\",\n\t\"io/ioutil\",\n\t\"log\",\n\t\"log/syslog\",\n\t\"math/big\",\n\t\"math/cmplx\",\n\t\"math\",\n\t\"math/rand\",\n\t\"mime\",\n\t\"mime/multipart\",\n\t\"net\",\n\t\"net/http/cgi\",\n\t// \"net/http/cookiejar\", // Added in GCC 4.8.\n\t\"net/http/fcgi\",\n\t\"net/http\",\n\t\"net/http/httptest\",\n\t\"net/http/httputil\",\n\t\"net/http/pprof\",\n\t\"net/mail\",\n\t\"net/rpc\",\n\t\"net/rpc/jsonrpc\",\n\t\"net/smtp\",\n\t\"net/textproto\",\n\t\"net/url\",\n\t\"os/exec\",\n\t\"os\",\n\t\"os/signal\",\n\t\"os/user\",\n\t\"path/filepath\",\n\t\"path\",\n\t\"reflect\",\n\t\"regexp\",\n\t\"regexp/syntax\",\n\t\"runtime/debug\",\n\t\"runtime\",\n\t\"runtime/pprof\",\n\t\"sort\",\n\t\"strconv\",\n\t\"strings\",\n\t\"sync/atomic\",\n\t\"sync\",\n\t\"syscall\",\n\t\"testing\",\n\t\"testing/iotest\",\n\t\"testing/quick\",\n\t\"text/scanner\",\n\t\"text/tabwriter\",\n\t\"text/template\",\n\t\"text/template/parse\",\n\t\"time\",\n\t\"unicode\",\n\t\"unicode/utf16\",\n\t\"unicode/utf8\",\n}\n\nfunc TestInstallationImporter(t *testing.T) {\n\t// This test relies on gccgo being around.\n\tgpath := gccgoPath()\n\tif gpath == \"\" {\n\t\tt.Skip(\"This test needs gccgo\")\n\t}\n\tif runtime.GOOS == \"aix\" {\n\t\t// We don't yet have a debug/xcoff package for reading\n\t\t// object files on AIX. Remove this skip if/when issue #29038\n\t\t// is implemented (see also issue #49445).\n\t\tt.Skip(\"no support yet for debug/xcoff\")\n\t}\n\n\tvar inst GccgoInstallation\n\terr := inst.InitFromDriver(gpath)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\timp := inst.GetImporter(nil, nil)\n\n\t// Ensure we don't regress the number of packages we can parse. First import\n\t// all packages into the same map and then each individually.\n\tpkgMap := make(map[string]*types.Package)\n\tfor _, pkg := range importablePackages {\n\t\t_, err = imp(pkgMap, pkg, \".\", nil)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\n\tfor _, pkg := range importablePackages {\n\t\t_, err = imp(make(map[string]*types.Package), pkg, \".\", nil)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\n\t// Test for certain specific entities in the imported data.\n\tfor _, test := range [...]importerTest{\n\t\t{pkgpath: \"io\", name: \"Reader\", want: \"type Reader interface{Read(p []byte) (n int, err error)}\"},\n\t\t{pkgpath: \"io\", name: \"ReadWriter\", want: \"type ReadWriter interface{Reader; Writer}\"},\n\t\t{pkgpath: \"math\", name: \"Pi\", want: \"const Pi untyped float\"},\n\t\t{pkgpath: \"math\", name: \"Sin\", want: \"func Sin(x float64) float64\"},\n\t\t{pkgpath: \"sort\", name: \"Search\", want: \"func Search(n int, f func(int) bool) int\"},\n\t\t{pkgpath: \"unsafe\", name: \"Pointer\", want: \"type Pointer\"},\n\t} {\n\t\trunImporterTest(t, imp, nil, &test)\n\t}\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/importer.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment and the import path, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter.\n\n// Package gccgoimporter implements Import for gccgo-generated object files.\npackage gccgoimporter // import \"golang.org/x/tools/go/internal/gccgoimporter\"\n\nimport (\n\t\"debug/elf\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// A PackageInit describes an imported package that needs initialization.\ntype PackageInit struct {\n\tName     string // short package name\n\tInitFunc string // name of init function\n\tPriority int    // priority of init function, see InitData.Priority\n}\n\n// The gccgo-specific init data for a package.\ntype InitData struct {\n\t// Initialization priority of this package relative to other packages.\n\t// This is based on the maximum depth of the package's dependency graph;\n\t// it is guaranteed to be greater than that of its dependencies.\n\tPriority int\n\n\t// The list of packages which this package depends on to be initialized,\n\t// including itself if needed. This is the subset of the transitive closure of\n\t// the package's dependencies that need initialization.\n\tInits []PackageInit\n}\n\n// Locate the file from which to read export data.\n// This is intended to replicate the logic in gofrontend.\nfunc findExportFile(searchpaths []string, pkgpath string) (string, error) {\n\tfor _, spath := range searchpaths {\n\t\tpkgfullpath := filepath.Join(spath, pkgpath)\n\t\tpkgdir, name := filepath.Split(pkgfullpath)\n\n\t\tfor _, filepath := range [...]string{\n\t\t\tpkgfullpath,\n\t\t\tpkgfullpath + \".gox\",\n\t\t\tpkgdir + \"lib\" + name + \".so\",\n\t\t\tpkgdir + \"lib\" + name + \".a\",\n\t\t\tpkgfullpath + \".o\",\n\t\t} {\n\t\t\tfi, err := os.Stat(filepath)\n\t\t\tif err == nil && !fi.IsDir() {\n\t\t\t\treturn filepath, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", fmt.Errorf(\"%s: could not find export data (tried %s)\", pkgpath, strings.Join(searchpaths, \":\"))\n}\n\nconst (\n\tgccgov1Magic    = \"v1;\\n\"\n\tgccgov2Magic    = \"v2;\\n\"\n\tgccgov3Magic    = \"v3;\\n\"\n\tgoimporterMagic = \"\\n$$ \"\n\tarchiveMagic    = \"!<ar\"\n)\n\n// Opens the export data file at the given path. If this is an ELF file,\n// searches for and opens the .go_export section. If this is an archive,\n// reads the export data from the first member, which is assumed to be an ELF file.\n// This is intended to replicate the logic in gofrontend.\nfunc openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {\n\tf, err := os.Open(fpath)\n\tif err != nil {\n\t\treturn\n\t}\n\tcloser = f\n\tdefer func() {\n\t\tif err != nil && closer != nil {\n\t\t\tf.Close()\n\t\t}\n\t}()\n\n\tvar magic [4]byte\n\t_, err = f.ReadAt(magic[:], 0)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tvar elfreader io.ReaderAt\n\tswitch string(magic[:]) {\n\tcase gccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic:\n\t\t// Raw export data.\n\t\treader = f\n\t\treturn\n\n\tcase archiveMagic:\n\t\treader, err = arExportData(f)\n\t\treturn\n\n\tdefault:\n\t\telfreader = f\n\t}\n\n\tef, err := elf.NewFile(elfreader)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tsec := ef.Section(\".go_export\")\n\tif sec == nil {\n\t\terr = fmt.Errorf(\"%s: .go_export section not found\", fpath)\n\t\treturn\n\t}\n\n\treader = sec.Open()\n\treturn\n}\n\n// An Importer resolves import paths to Packages. The imports map records\n// packages already known, indexed by package path.\n// An importer must determine the canonical package path and check imports\n// to see if it is already present in the map. If so, the Importer can return\n// the map entry. Otherwise, the importer must load the package data for the\n// given path into a new *Package, record it in imports map, and return the\n// package.\ntype Importer func(imports map[string]*types.Package, path, srcDir string, lookup func(string) (io.ReadCloser, error)) (*types.Package, error)\n\nfunc GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Importer {\n\treturn func(imports map[string]*types.Package, pkgpath, srcDir string, lookup func(string) (io.ReadCloser, error)) (pkg *types.Package, err error) {\n\t\t// TODO(gri): Use srcDir.\n\t\t// Or not. It's possible that srcDir will fade in importance as\n\t\t// the go command and other tools provide a translation table\n\t\t// for relative imports (like ./foo or vendored imports).\n\t\tif pkgpath == \"unsafe\" {\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\n\t\tvar reader io.ReadSeeker\n\t\tvar fpath string\n\t\tvar rc io.ReadCloser\n\t\tif lookup != nil {\n\t\t\tif p := imports[pkgpath]; p != nil && p.Complete() {\n\t\t\t\treturn p, nil\n\t\t\t}\n\t\t\trc, err = lookup(pkgpath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tif rc != nil {\n\t\t\tdefer rc.Close()\n\t\t\trs, ok := rc.(io.ReadSeeker)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"gccgo importer requires lookup to return an io.ReadSeeker, have %T\", rc)\n\t\t\t}\n\t\t\treader = rs\n\t\t\tfpath = \"<lookup \" + pkgpath + \">\"\n\t\t\t// Take name from Name method (like on os.File) if present.\n\t\t\tif n, ok := rc.(interface{ Name() string }); ok {\n\t\t\t\tfpath = n.Name()\n\t\t\t}\n\t\t} else {\n\t\t\tfpath, err = findExportFile(searchpaths, pkgpath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tr, closer, err := openExportFile(fpath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif closer != nil {\n\t\t\t\tdefer closer.Close()\n\t\t\t}\n\t\t\treader = r\n\t\t}\n\n\t\tvar magics string\n\t\tmagics, err = readMagic(reader)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tif magics == archiveMagic {\n\t\t\treader, err = arExportData(reader)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tmagics, err = readMagic(reader)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tswitch magics {\n\t\tcase gccgov1Magic, gccgov2Magic, gccgov3Magic:\n\t\t\tvar p parser\n\t\t\tp.init(fpath, reader, imports)\n\t\t\tpkg = p.parsePackage()\n\t\t\tif initmap != nil {\n\t\t\t\tinitmap[pkg] = p.initdata\n\t\t\t}\n\n\t\t// Excluded for now: Standard gccgo doesn't support this import format currently.\n\t\t// case goimporterMagic:\n\t\t// \tvar data []byte\n\t\t// \tdata, err = io.ReadAll(reader)\n\t\t// \tif err != nil {\n\t\t// \t\treturn\n\t\t// \t}\n\t\t// \tvar n int\n\t\t// \tn, pkg, err = importer.ImportData(imports, data)\n\t\t// \tif err != nil {\n\t\t// \t\treturn\n\t\t// \t}\n\n\t\t// \tif initmap != nil {\n\t\t// \t\tsuffixreader := bytes.NewReader(data[n:])\n\t\t// \t\tvar p parser\n\t\t// \t\tp.init(fpath, suffixreader, nil)\n\t\t// \t\tp.parseInitData()\n\t\t// \t\tinitmap[pkg] = p.initdata\n\t\t// \t}\n\n\t\tdefault:\n\t\t\terr = fmt.Errorf(\"unrecognized magic string: %q\", magics)\n\t\t}\n\n\t\treturn\n\t}\n}\n\n// readMagic reads the four bytes at the start of a ReadSeeker and\n// returns them as a string.\nfunc readMagic(reader io.ReadSeeker) (string, error) {\n\tvar magic [4]byte\n\tif _, err := reader.Read(magic[:]); err != nil {\n\t\treturn \"\", err\n\t}\n\tif _, err := reader.Seek(0, io.SeekStart); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(magic[:]), nil\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/importer_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter without\n// the import of \"testenv\".\n\npackage gccgoimporter\n\nimport (\n\t\"go/types\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"testing\"\n)\n\ntype importerTest struct {\n\tpkgpath, name, want, wantval string\n\twantinits                    []string\n\tgccgoVersion                 int // minimum gccgo version (0 => any)\n}\n\nfunc runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]InitData, test *importerTest) {\n\tpkg, err := imp(make(map[string]*types.Package), test.pkgpath, \".\", nil)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\n\tif test.name != \"\" {\n\t\tobj := pkg.Scope().Lookup(test.name)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"%s: object not found\", test.name)\n\t\t\treturn\n\t\t}\n\n\t\tgot := types.ObjectString(obj, types.RelativeTo(pkg))\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"%s: got %q; want %q\", test.name, got, test.want)\n\t\t}\n\n\t\tif test.wantval != \"\" {\n\t\t\tgotval := obj.(*types.Const).Val().String()\n\t\t\tif gotval != test.wantval {\n\t\t\t\tt.Errorf(\"%s: got val %q; want val %q\", test.name, gotval, test.wantval)\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(test.wantinits) > 0 {\n\t\tinitdata := initmap[pkg]\n\t\tfound := false\n\t\t// Check that the package's own init function has the package's priority\n\t\tfor _, pkginit := range initdata.Inits {\n\t\t\tif pkginit.InitFunc == test.wantinits[0] {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif !found {\n\t\t\tt.Errorf(\"%s: could not find expected function %q\", test.pkgpath, test.wantinits[0])\n\t\t}\n\n\t\t// FIXME: the original version of this test was written against\n\t\t// the v1 export data scheme for capturing init functions, so it\n\t\t// verified the priority values. We moved away from the priority\n\t\t// scheme some time ago; it is not clear how much work it would be\n\t\t// to validate the new init export data.\n\t}\n}\n\n// When adding tests to this list, be sure to set the 'gccgoVersion'\n// field if the testcases uses a \"recent\" Go addition (ex: aliases).\nvar importerTests = [...]importerTest{\n\t{pkgpath: \"pointer\", name: \"Int8Ptr\", want: \"type Int8Ptr *int8\"},\n\t{pkgpath: \"complexnums\", name: \"NN\", want: \"const NN untyped complex\", wantval: \"(-1 + -1i)\"},\n\t{pkgpath: \"complexnums\", name: \"NP\", want: \"const NP untyped complex\", wantval: \"(-1 + 1i)\"},\n\t{pkgpath: \"complexnums\", name: \"PN\", want: \"const PN untyped complex\", wantval: \"(1 + -1i)\"},\n\t{pkgpath: \"complexnums\", name: \"PP\", want: \"const PP untyped complex\", wantval: \"(1 + 1i)\"},\n\t{pkgpath: \"conversions\", name: \"Bits\", want: \"const Bits Units\", wantval: `\"bits\"`},\n\t{pkgpath: \"time\", name: \"Duration\", want: \"type Duration int64\"},\n\t{pkgpath: \"time\", name: \"Nanosecond\", want: \"const Nanosecond Duration\", wantval: \"1\"},\n\t{pkgpath: \"unicode\", name: \"IsUpper\", want: \"func IsUpper(r rune) bool\"},\n\t{pkgpath: \"unicode\", name: \"MaxRune\", want: \"const MaxRune untyped rune\", wantval: \"1114111\"},\n\t{pkgpath: \"imports\", wantinits: []string{\"imports..import\", \"fmt..import\"}},\n\t{pkgpath: \"importsar\", name: \"Hello\", want: \"var Hello string\"},\n\t{pkgpath: \"aliases\", name: \"A14\", gccgoVersion: 7, want: \"type A14 = func(int, T0) chan T2\"},\n\t{pkgpath: \"aliases\", name: \"C0\", gccgoVersion: 7, want: \"type C0 struct{f1 C1; f2 C1}\"},\n\t{pkgpath: \"escapeinfo\", name: \"NewT\", want: \"func NewT(data []byte) *T\"},\n\t{pkgpath: \"issue27856\", name: \"M\", gccgoVersion: 7, want: \"type M struct{E F}\"},\n\t{pkgpath: \"v1reflect\", name: \"Type\", want: \"type Type interface{Align() int; AssignableTo(u Type) bool; Bits() int; ChanDir() ChanDir; Elem() Type; Field(i int) StructField; FieldAlign() int; FieldByIndex(index []int) StructField; FieldByName(name string) (StructField, bool); FieldByNameFunc(match func(string) bool) (StructField, bool); Implements(u Type) bool; In(i int) Type; IsVariadic() bool; Key() Type; Kind() Kind; Len() int; Method(int) Method; MethodByName(string) (Method, bool); Name() string; NumField() int; NumIn() int; NumMethod() int; NumOut() int; Out(i int) Type; PkgPath() string; Size() uintptr; String() string; common() *commonType; rawString() string; runtimeType() *runtimeType; uncommon() *uncommonType}\"},\n\t{pkgpath: \"nointerface\", name: \"I\", want: \"type I int\"},\n\t{pkgpath: \"issue29198\", name: \"FooServer\", gccgoVersion: 7, want: \"type FooServer struct{FooServer *FooServer; user string; ctx context.Context}\"},\n\t{pkgpath: \"issue30628\", name: \"Apple\", want: \"type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}\"},\n\t{pkgpath: \"issue31540\", name: \"S\", gccgoVersion: 7, want: \"type S struct{b int; map[Y]Z}\"},\n\t{pkgpath: \"issue34182\", name: \"T1\", want: \"type T1 struct{f *T2}\"},\n\t{pkgpath: \"notinheap\", name: \"S\", want: \"type S struct{}\"},\n}\n\nfunc TestGoxImporter(t *testing.T) {\n\ttestenv.MustHaveExec(t) // this is to skip nacl, js\n\tinitmap := make(map[*types.Package]InitData)\n\timp := GetImporter([]string{\"testdata\"}, initmap)\n\n\tfor _, test := range importerTests {\n\t\trunImporterTest(t, imp, initmap, &test)\n\t}\n}\n\n// gccgoPath returns a path to gccgo if it is present (either in\n// path or specified via GCCGO environment variable), or an\n// empty string if no gccgo is available.\nfunc gccgoPath() string {\n\tgccgoname := os.Getenv(\"GCCGO\")\n\tif gccgoname == \"\" {\n\t\tgccgoname = \"gccgo\"\n\t}\n\tif gpath, gerr := exec.LookPath(gccgoname); gerr == nil {\n\t\treturn gpath\n\t}\n\treturn \"\"\n}\n\nfunc TestObjImporter(t *testing.T) {\n\t// This test relies on gccgo being around.\n\tgpath := gccgoPath()\n\tif gpath == \"\" {\n\t\tt.Skip(\"This test needs gccgo\")\n\t}\n\tif runtime.GOOS == \"aix\" {\n\t\t// We don't yet have a debug/xcoff package for reading\n\t\t// object files on AIX. Remove this skip if/when issue #29038\n\t\t// is implemented (see also issue #49445).\n\t\tt.Skip(\"no support yet for debug/xcoff\")\n\t}\n\n\tverout, err := exec.Command(gpath, \"--version\").Output()\n\tif err != nil {\n\t\tt.Logf(\"%s\", verout)\n\t\tif exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {\n\t\t\tt.Logf(\"stderr:\\n%s\", exit.Stderr)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\tvers := regexp.MustCompile(`([0-9]+)\\.([0-9]+)`).FindSubmatch(verout)\n\tif len(vers) == 0 {\n\t\tt.Fatalf(\"could not find version number in %s\", verout)\n\t}\n\tmajor, err := strconv.Atoi(string(vers[1]))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tminor, err := strconv.Atoi(string(vers[2]))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tt.Logf(\"gccgo version %d.%d\", major, minor)\n\n\ttmpdir := t.TempDir()\n\tinitmap := make(map[*types.Package]InitData)\n\timp := GetImporter([]string{tmpdir}, initmap)\n\n\tartmpdir := t.TempDir()\n\tarinitmap := make(map[*types.Package]InitData)\n\tarimp := GetImporter([]string{artmpdir}, arinitmap)\n\n\tfor _, test := range importerTests {\n\t\tif major < test.gccgoVersion {\n\t\t\t// Support for type aliases was added in GCC 7.\n\t\t\tt.Logf(\"skipping %q: not supported before gccgo version %d\", test.pkgpath, test.gccgoVersion)\n\t\t\tcontinue\n\t\t}\n\n\t\tgofile := filepath.Join(\"testdata\", test.pkgpath+\".go\")\n\t\tif _, err := os.Stat(gofile); os.IsNotExist(err) {\n\t\t\tcontinue\n\t\t}\n\t\tofile := filepath.Join(tmpdir, test.pkgpath+\".o\")\n\t\tafile := filepath.Join(artmpdir, \"lib\"+test.pkgpath+\".a\")\n\n\t\tcmd := exec.Command(gpath, \"-fgo-pkgpath=\"+test.pkgpath, \"-c\", \"-o\", ofile, gofile)\n\t\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\t\tt.Logf(\"%s\", out)\n\t\t\tt.Fatalf(\"gccgo %s failed: %s\", gofile, err)\n\t\t}\n\n\t\trunImporterTest(t, imp, initmap, &test)\n\n\t\tcmd = exec.Command(\"ar\", \"cr\", afile, ofile)\n\t\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\t\tt.Logf(\"%s\", out)\n\t\t\tt.Fatalf(\"ar cr %s %s failed: %s\", afile, ofile, err)\n\t\t}\n\n\t\trunImporterTest(t, arimp, arinitmap, &test)\n\n\t\tif err = os.Remove(ofile); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err = os.Remove(afile); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/newInterface10.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.11\n\npackage gccgoimporter\n\nimport \"go/types\"\n\nfunc newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {\n\tnamed := make([]*types.Named, len(embeddeds))\n\tfor i, e := range embeddeds {\n\t\tvar ok bool\n\t\tnamed[i], ok = e.(*types.Named)\n\t\tif !ok {\n\t\t\tpanic(\"embedding of non-defined interfaces in interfaces is not supported before Go 1.11\")\n\t\t}\n\t}\n\treturn types.NewInterface(methods, named)\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/newInterface11.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.11\n\npackage gccgoimporter\n\nimport \"go/types\"\n\nfunc newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {\n\treturn types.NewInterfaceType(methods, embeddeds)\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/parser.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter, with\n// a small modification in parseInterface to support older Go versions.\n\npackage gccgoimporter\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/scanner\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\ntype parser struct {\n\tscanner  *scanner.Scanner\n\tversion  string                    // format version\n\ttok      rune                      // current token\n\tlit      string                    // literal string; only valid for Ident, Int, String tokens\n\tpkgpath  string                    // package path of imported package\n\tpkgname  string                    // name of imported package\n\tpkg      *types.Package            // reference to imported package\n\timports  map[string]*types.Package // package path -> package object\n\ttypeList []types.Type              // type number -> type\n\ttypeData []string                  // unparsed type data (v3 and later)\n\tfixups   []fixupRecord             // fixups to apply at end of parsing\n\tinitdata InitData                  // package init priority data\n\taliases  map[int]string            // maps saved type number to alias name\n}\n\n// When reading export data it's possible to encounter a defined type\n// N1 with an underlying defined type N2 while we are still reading in\n// that defined type N2; see issues #29006 and #29198 for instances\n// of this. Example:\n//\n//   type N1 N2\n//   type N2 struct {\n//      ...\n//      p *N1\n//   }\n//\n// To handle such cases, the parser generates a fixup record (below) and\n// delays setting of N1's underlying type until parsing is complete, at\n// which point fixups are applied.\n\ntype fixupRecord struct {\n\ttoUpdate *types.Named // type to modify when fixup is processed\n\ttarget   types.Type   // type that was incomplete when fixup was created\n}\n\nfunc (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) {\n\tp.scanner = new(scanner.Scanner)\n\tp.initScanner(filename, src)\n\tp.imports = imports\n\tp.aliases = make(map[int]string)\n\tp.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16)\n}\n\nfunc (p *parser) initScanner(filename string, src io.Reader) {\n\tp.scanner.Init(src)\n\tp.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }\n\tp.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings\n\tp.scanner.Whitespace = 1<<'\\t' | 1<<' '\n\tp.scanner.Filename = filename // for good error messages\n\tp.next()\n}\n\ntype importError struct {\n\tpos scanner.Position\n\terr error\n}\n\nfunc (e importError) Error() string {\n\treturn fmt.Sprintf(\"import error %s (byte offset = %d): %s\", e.pos, e.pos.Offset, e.err)\n}\n\nfunc (p *parser) error(err any) {\n\tif s, ok := err.(string); ok {\n\t\terr = errors.New(s)\n\t}\n\t// panic with a runtime.Error if err is not an error\n\tpanic(importError{p.scanner.Pos(), err.(error)})\n}\n\nfunc (p *parser) errorf(format string, args ...any) {\n\tp.error(fmt.Errorf(format, args...))\n}\n\nfunc (p *parser) expect(tok rune) string {\n\tlit := p.lit\n\tif p.tok != tok {\n\t\tp.errorf(\"expected %s, got %s (%s)\", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)\n\t}\n\tp.next()\n\treturn lit\n}\n\nfunc (p *parser) expectEOL() {\n\tif p.version == \"v1\" || p.version == \"v2\" {\n\t\tp.expect(';')\n\t}\n\tp.expect('\\n')\n}\n\nfunc (p *parser) expectKeyword(keyword string) {\n\tlit := p.expect(scanner.Ident)\n\tif lit != keyword {\n\t\tp.errorf(\"expected keyword %s, got %q\", keyword, lit)\n\t}\n}\n\nfunc (p *parser) parseString() string {\n\tstr, err := strconv.Unquote(p.expect(scanner.String))\n\tif err != nil {\n\t\tp.error(err)\n\t}\n\treturn str\n}\n\n// parseUnquotedString parses an UnquotedString:\n//\n//\tunquotedString     = { unquotedStringChar } .\n//\tunquotedStringChar = <neither a whitespace nor a ';' char> .\nfunc (p *parser) parseUnquotedString() string {\n\tif p.tok == scanner.EOF {\n\t\tp.error(\"unexpected EOF\")\n\t}\n\tvar buf bytes.Buffer\n\tbuf.WriteString(p.scanner.TokenText())\n\t// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,\n\t// we need to let it be consumed by p.next().\n\tfor ch := p.scanner.Peek(); ch != '\\n' && ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {\n\t\tbuf.WriteRune(ch)\n\t\tp.scanner.Next()\n\t}\n\tp.next()\n\treturn buf.String()\n}\n\nfunc (p *parser) next() {\n\tp.tok = p.scanner.Scan()\n\tswitch p.tok {\n\tcase scanner.Ident, scanner.Int, scanner.Float, scanner.String, '·':\n\t\tp.lit = p.scanner.TokenText()\n\tdefault:\n\t\tp.lit = \"\"\n\t}\n}\n\nfunc (p *parser) parseQualifiedName() (path, name string) {\n\treturn p.parseQualifiedNameStr(p.parseString())\n}\n\nfunc (p *parser) parseUnquotedQualifiedName() (path, name string) {\n\treturn p.parseQualifiedNameStr(p.parseUnquotedString())\n}\n\n// parseQualifiedNameStr is given the leading name (unquoted by the caller if necessary)\n// and then parses the remainder of a qualified name:\n//\n//\tqualifiedName = [ [\".\"] unquotedString \".\" ] unquotedString .\n//\n// The above production uses greedy matching.\nfunc (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) {\n\tparts := strings.Split(unquotedName, \".\")\n\tif parts[0] == \"\" {\n\t\tparts = parts[1:]\n\t}\n\n\tswitch len(parts) {\n\tcase 0:\n\t\tp.errorf(\"malformed qualified name: %q\", unquotedName)\n\tcase 1:\n\t\t// unqualified name\n\t\tpkgpath = p.pkgpath\n\t\tname = parts[0]\n\tdefault:\n\t\t// qualified name, which may contain periods\n\t\tpkgpath = strings.Join(parts[0:len(parts)-1], \".\")\n\t\tname = parts[len(parts)-1]\n\t}\n\n\treturn\n}\n\n// getPkg returns the package for a given path. If the package is\n// not found but we have a package name, create the package and\n// add it to the p.imports map.\nfunc (p *parser) getPkg(pkgpath, name string) *types.Package {\n\t// package unsafe is not in the imports map - handle explicitly\n\tif pkgpath == \"unsafe\" {\n\t\treturn types.Unsafe\n\t}\n\tpkg := p.imports[pkgpath]\n\tif pkg == nil && name != \"\" {\n\t\tpkg = types.NewPackage(pkgpath, name)\n\t\tp.imports[pkgpath] = pkg\n\t}\n\treturn pkg\n}\n\n// parseExportedName is like parseQualifiedName, but\n// the package path is resolved to an imported *types.Package.\n//\n//\tExportedName = string [string] .\nfunc (p *parser) parseExportedName() (pkg *types.Package, name string) {\n\tpath, name := p.parseQualifiedName()\n\tvar pkgname string\n\tif p.tok == scanner.String {\n\t\tpkgname = p.parseString()\n\t}\n\tpkg = p.getPkg(path, pkgname)\n\tif pkg == nil {\n\t\tp.errorf(\"package %s (path = %q) not found\", name, path)\n\t}\n\treturn\n}\n\n// parseName parses a Name:\n//\n//\tName = QualifiedName | \"?\" .\nfunc (p *parser) parseName() string {\n\tif p.tok == '?' {\n\t\t// Anonymous.\n\t\tp.next()\n\t\treturn \"\"\n\t}\n\t// The package path is redundant for us. Don't try to parse it.\n\t_, name := p.parseUnquotedQualifiedName()\n\treturn name\n}\n\n// parseField parses a Field:\n//\n//\tField = Name Type [string] .\nfunc (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {\n\tname := p.parseName()\n\ttyp, n := p.parseTypeExtended(pkg)\n\tanon := false\n\tif name == \"\" {\n\t\tanon = true\n\t\t// Alias?\n\t\tif aname, ok := p.aliases[n]; ok {\n\t\t\tname = aname\n\t\t} else {\n\t\t\tswitch typ := types.Unalias(typesinternal.Unpointer(typ)).(type) {\n\t\t\tcase *types.Basic:\n\t\t\t\tname = typ.Name()\n\t\t\tcase *types.Named:\n\t\t\t\tname = typ.Obj().Name()\n\t\t\tdefault:\n\t\t\t\tp.error(\"embedded field expected\")\n\t\t\t}\n\t\t}\n\t}\n\tfield = types.NewField(token.NoPos, pkg, name, typ, anon)\n\tif p.tok == scanner.String {\n\t\ttag = p.parseString()\n\t}\n\treturn\n}\n\n// parseParam parses a Param:\n//\n//\tParam = Name [\"...\"] Type .\nfunc (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) {\n\tname := p.parseName()\n\t// Ignore names invented for inlinable functions.\n\tif strings.HasPrefix(name, \"p.\") || strings.HasPrefix(name, \"r.\") || strings.HasPrefix(name, \"$ret\") {\n\t\tname = \"\"\n\t}\n\tif p.tok == '<' && p.scanner.Peek() == 'e' {\n\t\t// EscInfo = \"<esc:\" int \">\" . (optional and ignored)\n\t\tp.next()\n\t\tp.expectKeyword(\"esc\")\n\t\tp.expect(':')\n\t\tp.expect(scanner.Int)\n\t\tp.expect('>')\n\t}\n\tif p.tok == '.' {\n\t\tp.next()\n\t\tp.expect('.')\n\t\tp.expect('.')\n\t\tisVariadic = true\n\t}\n\ttyp := p.parseType(pkg)\n\tif isVariadic {\n\t\ttyp = types.NewSlice(typ)\n\t}\n\tparam = types.NewParam(token.NoPos, pkg, name, typ)\n\treturn\n}\n\n// parseVar parses a Var:\n//\n//\tVar = Name Type .\nfunc (p *parser) parseVar(pkg *types.Package) *types.Var {\n\tname := p.parseName()\n\tv := types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))\n\ttypesinternal.SetVarKind(v, typesinternal.PackageVar)\n\tif name[0] == '.' || name[0] == '<' {\n\t\t// This is an unexported variable,\n\t\t// or a variable defined in a different package.\n\t\t// We only want to record exported variables.\n\t\treturn nil\n\t}\n\treturn v\n}\n\n// parseConversion parses a Conversion:\n//\n//\tConversion = \"convert\" \"(\" Type \",\" ConstValue \")\" .\nfunc (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) {\n\tp.expectKeyword(\"convert\")\n\tp.expect('(')\n\ttyp = p.parseType(pkg)\n\tp.expect(',')\n\tval, _ = p.parseConstValue(pkg)\n\tp.expect(')')\n\treturn\n}\n\n// parseConstValue parses a ConstValue:\n//\n//\tConstValue     = string | \"false\" | \"true\" | [\"-\"] (int [\"'\"] | FloatOrComplex) | Conversion .\n//\tFloatOrComplex = float [\"i\" | (\"+\"|\"-\") float \"i\"] .\nfunc (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {\n\t// v3 changed to $false, $true, $convert, to avoid confusion\n\t// with variable names in inline function bodies.\n\tif p.tok == '$' {\n\t\tp.next()\n\t\tif p.tok != scanner.Ident {\n\t\t\tp.errorf(\"expected identifier after '$', got %s (%q)\", scanner.TokenString(p.tok), p.lit)\n\t\t}\n\t}\n\n\tswitch p.tok {\n\tcase scanner.String:\n\t\tstr := p.parseString()\n\t\tval = constant.MakeString(str)\n\t\ttyp = types.Typ[types.UntypedString]\n\t\treturn\n\n\tcase scanner.Ident:\n\t\tb := false\n\t\tswitch p.lit {\n\t\tcase \"false\":\n\t\tcase \"true\":\n\t\t\tb = true\n\n\t\tcase \"convert\":\n\t\t\treturn p.parseConversion(pkg)\n\n\t\tdefault:\n\t\t\tp.errorf(\"expected const value, got %s (%q)\", scanner.TokenString(p.tok), p.lit)\n\t\t}\n\n\t\tp.next()\n\t\tval = constant.MakeBool(b)\n\t\ttyp = types.Typ[types.UntypedBool]\n\t\treturn\n\t}\n\n\tsign := \"\"\n\tif p.tok == '-' {\n\t\tp.next()\n\t\tsign = \"-\"\n\t}\n\n\tswitch p.tok {\n\tcase scanner.Int:\n\t\tval = constant.MakeFromLiteral(sign+p.lit, token.INT, 0)\n\t\tif val == nil {\n\t\t\tp.error(\"could not parse integer literal\")\n\t\t}\n\n\t\tp.next()\n\t\tif p.tok == '\\'' {\n\t\t\tp.next()\n\t\t\ttyp = types.Typ[types.UntypedRune]\n\t\t} else {\n\t\t\ttyp = types.Typ[types.UntypedInt]\n\t\t}\n\n\tcase scanner.Float:\n\t\tre := sign + p.lit\n\t\tp.next()\n\n\t\tvar im string\n\t\tswitch p.tok {\n\t\tcase '+':\n\t\t\tp.next()\n\t\t\tim = p.expect(scanner.Float)\n\n\t\tcase '-':\n\t\t\tp.next()\n\t\t\tim = \"-\" + p.expect(scanner.Float)\n\n\t\tcase scanner.Ident:\n\t\t\t// re is in fact the imaginary component. Expect \"i\" below.\n\t\t\tim = re\n\t\t\tre = \"0\"\n\n\t\tdefault:\n\t\t\tval = constant.MakeFromLiteral(re, token.FLOAT, 0)\n\t\t\tif val == nil {\n\t\t\t\tp.error(\"could not parse float literal\")\n\t\t\t}\n\t\t\ttyp = types.Typ[types.UntypedFloat]\n\t\t\treturn\n\t\t}\n\n\t\tp.expectKeyword(\"i\")\n\t\treval := constant.MakeFromLiteral(re, token.FLOAT, 0)\n\t\tif reval == nil {\n\t\t\tp.error(\"could not parse real component of complex literal\")\n\t\t}\n\t\timval := constant.MakeFromLiteral(im+\"i\", token.IMAG, 0)\n\t\tif imval == nil {\n\t\t\tp.error(\"could not parse imag component of complex literal\")\n\t\t}\n\t\tval = constant.BinaryOp(reval, token.ADD, imval)\n\t\ttyp = types.Typ[types.UntypedComplex]\n\n\tdefault:\n\t\tp.errorf(\"expected const value, got %s (%q)\", scanner.TokenString(p.tok), p.lit)\n\t}\n\n\treturn\n}\n\n// parseConst parses a Const:\n//\n//\tConst = Name [Type] \"=\" ConstValue .\nfunc (p *parser) parseConst(pkg *types.Package) *types.Const {\n\tname := p.parseName()\n\tvar typ types.Type\n\tif p.tok == '<' {\n\t\ttyp = p.parseType(pkg)\n\t}\n\tp.expect('=')\n\tval, vtyp := p.parseConstValue(pkg)\n\tif typ == nil {\n\t\ttyp = vtyp\n\t}\n\treturn types.NewConst(token.NoPos, pkg, name, typ, val)\n}\n\n// reserved is a singleton type used to fill type map slots that have\n// been reserved (i.e., for which a type number has been parsed) but\n// which don't have their actual type yet. When the type map is updated,\n// the actual type must replace a reserved entry (or we have an internal\n// error). Used for self-verification only - not required for correctness.\nvar reserved = new(struct{ types.Type })\n\n// reserve reserves the type map entry n for future use.\nfunc (p *parser) reserve(n int) {\n\t// Notes:\n\t// - for pre-V3 export data, the type numbers we see are\n\t//   guaranteed to be in increasing order, so we append a\n\t//   reserved entry onto the list.\n\t// - for V3+ export data, type numbers can appear in\n\t//   any order, however the 'types' section tells us the\n\t//   total number of types, hence typeList is pre-allocated.\n\tif len(p.typeData) == 0 {\n\t\tif n != len(p.typeList) {\n\t\t\tp.errorf(\"invalid type number %d (out of sync)\", n)\n\t\t}\n\t\tp.typeList = append(p.typeList, reserved)\n\t} else {\n\t\tif p.typeList[n] != nil {\n\t\t\tp.errorf(\"previously visited type number %d\", n)\n\t\t}\n\t\tp.typeList[n] = reserved\n\t}\n}\n\n// update sets the type map entries for the entries in nlist to t.\n// An entry in nlist can be a type number in p.typeList,\n// used to resolve named types, or it can be a *types.Pointer,\n// used to resolve pointers to named types in case they are referenced\n// by embedded fields.\nfunc (p *parser) update(t types.Type, nlist []any) {\n\tif t == reserved {\n\t\tp.errorf(\"internal error: update(%v) invoked on reserved\", nlist)\n\t}\n\tif t == nil {\n\t\tp.errorf(\"internal error: update(%v) invoked on nil\", nlist)\n\t}\n\tfor _, n := range nlist {\n\t\tswitch n := n.(type) {\n\t\tcase int:\n\t\t\tif p.typeList[n] == t {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif p.typeList[n] != reserved {\n\t\t\t\tp.errorf(\"internal error: update(%v): %d not reserved\", nlist, n)\n\t\t\t}\n\t\t\tp.typeList[n] = t\n\t\tcase *types.Pointer:\n\t\t\tif *n != (types.Pointer{}) {\n\t\t\t\telem := n.Elem()\n\t\t\t\tif elem == t {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tp.errorf(\"internal error: update: pointer already set to %v, expected %v\", elem, t)\n\t\t\t}\n\t\t\t*n = *types.NewPointer(t)\n\t\tdefault:\n\t\t\tp.errorf(\"internal error: %T on nlist\", n)\n\t\t}\n\t}\n}\n\n// parseNamedType parses a NamedType:\n//\n//\tNamedType = TypeName [ \"=\" ] Type { Method } .\n//\tTypeName  = ExportedName .\n//\tMethod    = \"func\" \"(\" Param \")\" Name ParamList ResultList [InlineBody] \";\" .\nfunc (p *parser) parseNamedType(nlist []any) types.Type {\n\tpkg, name := p.parseExportedName()\n\tscope := pkg.Scope()\n\tobj := scope.Lookup(name)\n\tif obj != nil && obj.Type() == nil {\n\t\tp.errorf(\"%v has nil type\", obj)\n\t}\n\n\tif p.tok == scanner.Ident && p.lit == \"notinheap\" {\n\t\tp.next()\n\t\t// The go/types package has no way of recording that\n\t\t// this type is marked notinheap. Presumably no user\n\t\t// of this package actually cares.\n\t}\n\n\t// type alias\n\tif p.tok == '=' {\n\t\tp.next()\n\t\tp.aliases[nlist[len(nlist)-1].(int)] = name\n\t\tif obj != nil {\n\t\t\t// use the previously imported (canonical) type\n\t\t\tt := obj.Type()\n\t\t\tp.update(t, nlist)\n\t\t\tp.parseType(pkg) // discard\n\t\t\treturn t\n\t\t}\n\t\tt := p.parseType(pkg, nlist...)\n\t\tobj = types.NewTypeName(token.NoPos, pkg, name, t)\n\t\tscope.Insert(obj)\n\t\treturn t\n\t}\n\n\t// defined type\n\tif obj == nil {\n\t\t// A named type may be referred to before the underlying type\n\t\t// is known - set it up.\n\t\ttname := types.NewTypeName(token.NoPos, pkg, name, nil)\n\t\ttypes.NewNamed(tname, nil, nil)\n\t\tscope.Insert(tname)\n\t\tobj = tname\n\t}\n\n\t// use the previously imported (canonical), or newly created type\n\tt := obj.Type()\n\tp.update(t, nlist)\n\n\tnt, ok := types.Unalias(t).(*types.Named)\n\tif !ok {\n\t\t// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.\n\t\tpt := p.parseType(pkg)\n\t\tif pt != t {\n\t\t\tp.error(\"unexpected underlying type for non-named TypeName\")\n\t\t}\n\t\treturn t\n\t}\n\n\tunderlying := p.parseType(pkg)\n\tif nt.Underlying() == nil {\n\t\tif underlying.Underlying() == nil {\n\t\t\tfix := fixupRecord{toUpdate: nt, target: underlying}\n\t\t\tp.fixups = append(p.fixups, fix)\n\t\t} else {\n\t\t\tnt.SetUnderlying(underlying.Underlying())\n\t\t}\n\t}\n\n\tif p.tok == '\\n' {\n\t\tp.next()\n\t\t// collect associated methods\n\t\tfor p.tok == scanner.Ident {\n\t\t\tp.expectKeyword(\"func\")\n\t\t\tif p.tok == '/' {\n\t\t\t\t// Skip a /*nointerface*/ or /*asm ID */ comment.\n\t\t\t\tp.expect('/')\n\t\t\t\tp.expect('*')\n\t\t\t\tif p.expect(scanner.Ident) == \"asm\" {\n\t\t\t\t\tp.parseUnquotedString()\n\t\t\t\t}\n\t\t\t\tp.expect('*')\n\t\t\t\tp.expect('/')\n\t\t\t}\n\t\t\tp.expect('(')\n\t\t\treceiver, _ := p.parseParam(pkg)\n\t\t\tp.expect(')')\n\t\t\tname := p.parseName()\n\t\t\tparams, isVariadic := p.parseParamList(pkg)\n\t\t\tresults := p.parseResultList(pkg)\n\t\t\tp.skipInlineBody()\n\t\t\tp.expectEOL()\n\n\t\t\tsig := types.NewSignatureType(receiver, nil, nil, params, results, isVariadic)\n\t\t\tnt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))\n\t\t}\n\t}\n\n\treturn nt\n}\n\nfunc (p *parser) parseInt64() int64 {\n\tlit := p.expect(scanner.Int)\n\tn, err := strconv.ParseInt(lit, 10, 64)\n\tif err != nil {\n\t\tp.error(err)\n\t}\n\treturn n\n}\n\nfunc (p *parser) parseInt() int {\n\tlit := p.expect(scanner.Int)\n\tn, err := strconv.ParseInt(lit, 10, 0 /* int */)\n\tif err != nil {\n\t\tp.error(err)\n\t}\n\treturn int(n)\n}\n\n// parseArrayOrSliceType parses an ArrayOrSliceType:\n//\n//\tArrayOrSliceType = \"[\" [ int ] \"]\" Type .\nfunc (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []any) types.Type {\n\tp.expect('[')\n\tif p.tok == ']' {\n\t\tp.next()\n\n\t\tt := new(types.Slice)\n\t\tp.update(t, nlist)\n\n\t\t*t = *types.NewSlice(p.parseType(pkg))\n\t\treturn t\n\t}\n\n\tt := new(types.Array)\n\tp.update(t, nlist)\n\n\tlen := p.parseInt64()\n\tp.expect(']')\n\n\t*t = *types.NewArray(p.parseType(pkg), len)\n\treturn t\n}\n\n// parseMapType parses a MapType:\n//\n//\tMapType = \"map\" \"[\" Type \"]\" Type .\nfunc (p *parser) parseMapType(pkg *types.Package, nlist []any) types.Type {\n\tp.expectKeyword(\"map\")\n\n\tt := new(types.Map)\n\tp.update(t, nlist)\n\n\tp.expect('[')\n\tkey := p.parseType(pkg)\n\tp.expect(']')\n\telem := p.parseType(pkg)\n\n\t*t = *types.NewMap(key, elem)\n\treturn t\n}\n\n// parseChanType parses a ChanType:\n//\n//\tChanType = \"chan\" [\"<-\" | \"-<\"] Type .\nfunc (p *parser) parseChanType(pkg *types.Package, nlist []any) types.Type {\n\tp.expectKeyword(\"chan\")\n\n\tt := new(types.Chan)\n\tp.update(t, nlist)\n\n\tdir := types.SendRecv\n\tswitch p.tok {\n\tcase '-':\n\t\tp.next()\n\t\tp.expect('<')\n\t\tdir = types.SendOnly\n\n\tcase '<':\n\t\t// don't consume '<' if it belongs to Type\n\t\tif p.scanner.Peek() == '-' {\n\t\t\tp.next()\n\t\t\tp.expect('-')\n\t\t\tdir = types.RecvOnly\n\t\t}\n\t}\n\n\t*t = *types.NewChan(dir, p.parseType(pkg))\n\treturn t\n}\n\n// parseStructType parses a StructType:\n//\n//\tStructType = \"struct\" \"{\" { Field } \"}\" .\nfunc (p *parser) parseStructType(pkg *types.Package, nlist []any) types.Type {\n\tp.expectKeyword(\"struct\")\n\n\tt := new(types.Struct)\n\tp.update(t, nlist)\n\n\tvar fields []*types.Var\n\tvar tags []string\n\n\tp.expect('{')\n\tfor p.tok != '}' && p.tok != scanner.EOF {\n\t\tfield, tag := p.parseField(pkg)\n\t\tp.expect(';')\n\t\tfields = append(fields, field)\n\t\ttags = append(tags, tag)\n\t}\n\tp.expect('}')\n\n\t*t = *types.NewStruct(fields, tags)\n\treturn t\n}\n\n// parseParamList parses a ParamList:\n//\n//\tParamList = \"(\" [ { Parameter \",\" } Parameter ] \")\" .\nfunc (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {\n\tvar list []*types.Var\n\tisVariadic := false\n\n\tp.expect('(')\n\tfor p.tok != ')' && p.tok != scanner.EOF {\n\t\tif len(list) > 0 {\n\t\t\tp.expect(',')\n\t\t}\n\t\tpar, variadic := p.parseParam(pkg)\n\t\tlist = append(list, par)\n\t\tif variadic {\n\t\t\tif isVariadic {\n\t\t\t\tp.error(\"... not on final argument\")\n\t\t\t}\n\t\t\tisVariadic = true\n\t\t}\n\t}\n\tp.expect(')')\n\n\treturn types.NewTuple(list...), isVariadic\n}\n\n// parseResultList parses a ResultList:\n//\n//\tResultList = Type | ParamList .\nfunc (p *parser) parseResultList(pkg *types.Package) *types.Tuple {\n\tswitch p.tok {\n\tcase '<':\n\t\tp.next()\n\t\tif p.tok == scanner.Ident && p.lit == \"inl\" {\n\t\t\treturn nil\n\t\t}\n\t\ttaa, _ := p.parseTypeAfterAngle(pkg)\n\t\treturn types.NewTuple(types.NewParam(token.NoPos, pkg, \"\", taa))\n\n\tcase '(':\n\t\tparams, _ := p.parseParamList(pkg)\n\t\treturn params\n\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// parseFunctionType parses a FunctionType:\n//\n//\tFunctionType = ParamList ResultList .\nfunc (p *parser) parseFunctionType(pkg *types.Package, nlist []any) *types.Signature {\n\tt := new(types.Signature)\n\tp.update(t, nlist)\n\n\tparams, isVariadic := p.parseParamList(pkg)\n\tresults := p.parseResultList(pkg)\n\n\t*t = *types.NewSignatureType(nil, nil, nil, params, results, isVariadic)\n\treturn t\n}\n\n// parseFunc parses a Func:\n//\n//\tFunc = Name FunctionType [InlineBody] .\nfunc (p *parser) parseFunc(pkg *types.Package) *types.Func {\n\tif p.tok == '/' {\n\t\t// Skip an /*asm ID */ comment.\n\t\tp.expect('/')\n\t\tp.expect('*')\n\t\tif p.expect(scanner.Ident) == \"asm\" {\n\t\t\tp.parseUnquotedString()\n\t\t}\n\t\tp.expect('*')\n\t\tp.expect('/')\n\t}\n\n\tname := p.parseName()\n\tf := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil))\n\tp.skipInlineBody()\n\n\tif name[0] == '.' || name[0] == '<' || strings.ContainsRune(name, '$') {\n\t\t// This is an unexported function,\n\t\t// or a function defined in a different package,\n\t\t// or a type$equal or type$hash function.\n\t\t// We only want to record exported functions.\n\t\treturn nil\n\t}\n\n\treturn f\n}\n\n// parseInterfaceType parses an InterfaceType:\n//\n//\tInterfaceType = \"interface\" \"{\" { (\"?\" Type | Func) \";\" } \"}\" .\nfunc (p *parser) parseInterfaceType(pkg *types.Package, nlist []any) types.Type {\n\tp.expectKeyword(\"interface\")\n\n\tt := new(types.Interface)\n\tp.update(t, nlist)\n\n\tvar methods []*types.Func\n\tvar embeddeds []types.Type\n\n\tp.expect('{')\n\tfor p.tok != '}' && p.tok != scanner.EOF {\n\t\tif p.tok == '?' {\n\t\t\tp.next()\n\t\t\tembeddeds = append(embeddeds, p.parseType(pkg))\n\t\t} else {\n\t\t\tmethod := p.parseFunc(pkg)\n\t\t\tif method != nil {\n\t\t\t\tmethods = append(methods, method)\n\t\t\t}\n\t\t}\n\t\tp.expect(';')\n\t}\n\tp.expect('}')\n\n\t*t = *newInterface(methods, embeddeds)\n\treturn t\n}\n\n// parsePointerType parses a PointerType:\n//\n//\tPointerType = \"*\" (\"any\" | Type) .\nfunc (p *parser) parsePointerType(pkg *types.Package, nlist []any) types.Type {\n\tp.expect('*')\n\tif p.tok == scanner.Ident {\n\t\tp.expectKeyword(\"any\")\n\t\tt := types.Typ[types.UnsafePointer]\n\t\tp.update(t, nlist)\n\t\treturn t\n\t}\n\n\tt := new(types.Pointer)\n\tp.update(t, nlist)\n\n\t*t = *types.NewPointer(p.parseType(pkg, t))\n\n\treturn t\n}\n\n// parseTypeSpec parses a TypeSpec:\n//\n//\tTypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .\nfunc (p *parser) parseTypeSpec(pkg *types.Package, nlist []any) types.Type {\n\tswitch p.tok {\n\tcase scanner.String:\n\t\treturn p.parseNamedType(nlist)\n\n\tcase scanner.Ident:\n\t\tswitch p.lit {\n\t\tcase \"map\":\n\t\t\treturn p.parseMapType(pkg, nlist)\n\n\t\tcase \"chan\":\n\t\t\treturn p.parseChanType(pkg, nlist)\n\n\t\tcase \"struct\":\n\t\t\treturn p.parseStructType(pkg, nlist)\n\n\t\tcase \"interface\":\n\t\t\treturn p.parseInterfaceType(pkg, nlist)\n\t\t}\n\n\tcase '*':\n\t\treturn p.parsePointerType(pkg, nlist)\n\n\tcase '[':\n\t\treturn p.parseArrayOrSliceType(pkg, nlist)\n\n\tcase '(':\n\t\treturn p.parseFunctionType(pkg, nlist)\n\t}\n\n\tp.errorf(\"expected type name or literal, got %s\", scanner.TokenString(p.tok))\n\treturn nil\n}\n\nconst (\n\t// From gofrontend/go/export.h\n\t// Note that these values are negative in the gofrontend and have been made positive\n\t// in the gccgoimporter.\n\tgccgoBuiltinINT8       = 1\n\tgccgoBuiltinINT16      = 2\n\tgccgoBuiltinINT32      = 3\n\tgccgoBuiltinINT64      = 4\n\tgccgoBuiltinUINT8      = 5\n\tgccgoBuiltinUINT16     = 6\n\tgccgoBuiltinUINT32     = 7\n\tgccgoBuiltinUINT64     = 8\n\tgccgoBuiltinFLOAT32    = 9\n\tgccgoBuiltinFLOAT64    = 10\n\tgccgoBuiltinINT        = 11\n\tgccgoBuiltinUINT       = 12\n\tgccgoBuiltinUINTPTR    = 13\n\tgccgoBuiltinBOOL       = 15\n\tgccgoBuiltinSTRING     = 16\n\tgccgoBuiltinCOMPLEX64  = 17\n\tgccgoBuiltinCOMPLEX128 = 18\n\tgccgoBuiltinERROR      = 19\n\tgccgoBuiltinBYTE       = 20\n\tgccgoBuiltinRUNE       = 21\n\tgccgoBuiltinANY        = 22\n)\n\nfunc lookupBuiltinType(typ int) types.Type {\n\treturn [...]types.Type{\n\t\tgccgoBuiltinINT8:       types.Typ[types.Int8],\n\t\tgccgoBuiltinINT16:      types.Typ[types.Int16],\n\t\tgccgoBuiltinINT32:      types.Typ[types.Int32],\n\t\tgccgoBuiltinINT64:      types.Typ[types.Int64],\n\t\tgccgoBuiltinUINT8:      types.Typ[types.Uint8],\n\t\tgccgoBuiltinUINT16:     types.Typ[types.Uint16],\n\t\tgccgoBuiltinUINT32:     types.Typ[types.Uint32],\n\t\tgccgoBuiltinUINT64:     types.Typ[types.Uint64],\n\t\tgccgoBuiltinFLOAT32:    types.Typ[types.Float32],\n\t\tgccgoBuiltinFLOAT64:    types.Typ[types.Float64],\n\t\tgccgoBuiltinINT:        types.Typ[types.Int],\n\t\tgccgoBuiltinUINT:       types.Typ[types.Uint],\n\t\tgccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],\n\t\tgccgoBuiltinBOOL:       types.Typ[types.Bool],\n\t\tgccgoBuiltinSTRING:     types.Typ[types.String],\n\t\tgccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],\n\t\tgccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],\n\t\tgccgoBuiltinERROR:      types.Universe.Lookup(\"error\").Type(),\n\t\tgccgoBuiltinBYTE:       types.Universe.Lookup(\"byte\").Type(),\n\t\tgccgoBuiltinRUNE:       types.Universe.Lookup(\"rune\").Type(),\n\t\tgccgoBuiltinANY:        types.Universe.Lookup(\"any\").Type(),\n\t}[typ]\n}\n\n// parseType parses a Type:\n//\n//\tType = \"<\" \"type\" ( \"-\" int | int [ TypeSpec ] ) \">\" .\n//\n// parseType updates the type map to t for all type numbers n.\nfunc (p *parser) parseType(pkg *types.Package, n ...any) types.Type {\n\tp.expect('<')\n\tt, _ := p.parseTypeAfterAngle(pkg, n...)\n\treturn t\n}\n\n// (*parser).Type after reading the \"<\".\nfunc (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...any) (t types.Type, n1 int) {\n\tp.expectKeyword(\"type\")\n\n\tn1 = 0\n\tswitch p.tok {\n\tcase scanner.Int:\n\t\tn1 = p.parseInt()\n\t\tif p.tok == '>' {\n\t\t\tif len(p.typeData) > 0 && p.typeList[n1] == nil {\n\t\t\t\tp.parseSavedType(pkg, n1, n)\n\t\t\t}\n\t\t\tt = p.typeList[n1]\n\t\t\tif len(p.typeData) == 0 && t == reserved {\n\t\t\t\tp.errorf(\"invalid type cycle, type %d not yet defined (nlist=%v)\", n1, n)\n\t\t\t}\n\t\t\tp.update(t, n)\n\t\t} else {\n\t\t\tp.reserve(n1)\n\t\t\tt = p.parseTypeSpec(pkg, append(n, n1))\n\t\t}\n\n\tcase '-':\n\t\tp.next()\n\t\tn1 := p.parseInt()\n\t\tt = lookupBuiltinType(n1)\n\t\tp.update(t, n)\n\n\tdefault:\n\t\tp.errorf(\"expected type number, got %s (%q)\", scanner.TokenString(p.tok), p.lit)\n\t\treturn nil, 0\n\t}\n\n\tif t == nil || t == reserved {\n\t\tp.errorf(\"internal error: bad return from parseType(%v)\", n)\n\t}\n\n\tp.expect('>')\n\treturn\n}\n\n// parseTypeExtended is identical to parseType, but if the type in\n// question is a saved type, returns the index as well as the type\n// pointer (index returned is zero if we parsed a builtin).\nfunc (p *parser) parseTypeExtended(pkg *types.Package, n ...any) (t types.Type, n1 int) {\n\tp.expect('<')\n\tt, n1 = p.parseTypeAfterAngle(pkg, n...)\n\treturn\n}\n\n// InlineBody = \"<inl:NN>\" .{NN}\n// Reports whether a body was skipped.\nfunc (p *parser) skipInlineBody() {\n\t// We may or may not have seen the '<' already, depending on\n\t// whether the function had a result type or not.\n\tif p.tok == '<' {\n\t\tp.next()\n\t\tp.expectKeyword(\"inl\")\n\t} else if p.tok != scanner.Ident || p.lit != \"inl\" {\n\t\treturn\n\t} else {\n\t\tp.next()\n\t}\n\n\tp.expect(':')\n\twant := p.parseInt()\n\tp.expect('>')\n\n\tdefer func(w uint64) {\n\t\tp.scanner.Whitespace = w\n\t}(p.scanner.Whitespace)\n\tp.scanner.Whitespace = 0\n\n\tgot := 0\n\tfor got < want {\n\t\tr := p.scanner.Next()\n\t\tif r == scanner.EOF {\n\t\t\tp.error(\"unexpected EOF\")\n\t\t}\n\t\tgot += utf8.RuneLen(r)\n\t}\n}\n\n// parseTypes parses a Types:\n//\n//\tTypes = \"types\" maxp1 exportedp1 (offset length)* .\nfunc (p *parser) parseTypes(pkg *types.Package) {\n\tmaxp1 := p.parseInt()\n\texportedp1 := p.parseInt()\n\tp.typeList = make([]types.Type, maxp1)\n\n\ttype typeOffset struct {\n\t\toffset int\n\t\tlength int\n\t}\n\tvar typeOffsets []typeOffset\n\n\ttotal := 0\n\tfor i := 1; i < maxp1; i++ {\n\t\tlen := p.parseInt()\n\t\ttypeOffsets = append(typeOffsets, typeOffset{total, len})\n\t\ttotal += len\n\t}\n\n\tdefer func(w uint64) {\n\t\tp.scanner.Whitespace = w\n\t}(p.scanner.Whitespace)\n\tp.scanner.Whitespace = 0\n\n\t// We should now have p.tok pointing to the final newline.\n\t// The next runes from the scanner should be the type data.\n\n\tvar sb strings.Builder\n\tfor sb.Len() < total {\n\t\tr := p.scanner.Next()\n\t\tif r == scanner.EOF {\n\t\t\tp.error(\"unexpected EOF\")\n\t\t}\n\t\tsb.WriteRune(r)\n\t}\n\tallTypeData := sb.String()\n\n\tp.typeData = []string{\"\"} // type 0, unused\n\tfor _, to := range typeOffsets {\n\t\tp.typeData = append(p.typeData, allTypeData[to.offset:to.offset+to.length])\n\t}\n\n\tfor i := 1; i < int(exportedp1); i++ {\n\t\tp.parseSavedType(pkg, i, nil)\n\t}\n}\n\n// parseSavedType parses one saved type definition.\nfunc (p *parser) parseSavedType(pkg *types.Package, i int, nlist []any) {\n\tdefer func(s *scanner.Scanner, tok rune, lit string) {\n\t\tp.scanner = s\n\t\tp.tok = tok\n\t\tp.lit = lit\n\t}(p.scanner, p.tok, p.lit)\n\n\tp.scanner = new(scanner.Scanner)\n\tp.initScanner(p.scanner.Filename, strings.NewReader(p.typeData[i]))\n\tp.expectKeyword(\"type\")\n\tid := p.parseInt()\n\tif id != i {\n\t\tp.errorf(\"type ID mismatch: got %d, want %d\", id, i)\n\t}\n\tif p.typeList[i] == reserved {\n\t\tp.errorf(\"internal error: %d already reserved in parseSavedType\", i)\n\t}\n\tif p.typeList[i] == nil {\n\t\tp.reserve(i)\n\t\tp.parseTypeSpec(pkg, append(nlist, i))\n\t}\n\tif p.typeList[i] == nil || p.typeList[i] == reserved {\n\t\tp.errorf(\"internal error: parseSavedType(%d,%v) reserved/nil\", i, nlist)\n\t}\n}\n\n// parsePackageInit parses a PackageInit:\n//\n//\tPackageInit = unquotedString unquotedString int .\nfunc (p *parser) parsePackageInit() PackageInit {\n\tname := p.parseUnquotedString()\n\tinitfunc := p.parseUnquotedString()\n\tpriority := -1\n\tif p.version == \"v1\" {\n\t\tpriority = p.parseInt()\n\t}\n\treturn PackageInit{Name: name, InitFunc: initfunc, Priority: priority}\n}\n\n// Create the package if we have parsed both the package path and package name.\nfunc (p *parser) maybeCreatePackage() {\n\tif p.pkgname != \"\" && p.pkgpath != \"\" {\n\t\tp.pkg = p.getPkg(p.pkgpath, p.pkgname)\n\t}\n}\n\n// parseInitDataDirective parses an InitDataDirective:\n//\n//\tInitDataDirective = ( \"v1\" | \"v2\" | \"v3\" ) \";\" |\n//\t\t\"priority\" int \";\" |\n//\t\t\"init\" { PackageInit } \";\" |\n//\t\t\"checksum\" unquotedString \";\" .\nfunc (p *parser) parseInitDataDirective() {\n\tif p.tok != scanner.Ident {\n\t\t// unexpected token kind; panic\n\t\tp.expect(scanner.Ident)\n\t}\n\n\tswitch p.lit {\n\tcase \"v1\", \"v2\", \"v3\":\n\t\tp.version = p.lit\n\t\tp.next()\n\t\tp.expect(';')\n\t\tp.expect('\\n')\n\n\tcase \"priority\":\n\t\tp.next()\n\t\tp.initdata.Priority = p.parseInt()\n\t\tp.expectEOL()\n\n\tcase \"init\":\n\t\tp.next()\n\t\tfor p.tok != '\\n' && p.tok != ';' && p.tok != scanner.EOF {\n\t\t\tp.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())\n\t\t}\n\t\tp.expectEOL()\n\n\tcase \"init_graph\":\n\t\tp.next()\n\t\t// The graph data is thrown away for now.\n\t\tfor p.tok != '\\n' && p.tok != ';' && p.tok != scanner.EOF {\n\t\t\tp.parseInt64()\n\t\t\tp.parseInt64()\n\t\t}\n\t\tp.expectEOL()\n\n\tcase \"checksum\":\n\t\t// Don't let the scanner try to parse the checksum as a number.\n\t\tdefer func(mode uint) {\n\t\t\tp.scanner.Mode = mode\n\t\t}(p.scanner.Mode)\n\t\tp.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats\n\t\tp.next()\n\t\tp.parseUnquotedString()\n\t\tp.expectEOL()\n\n\tdefault:\n\t\tp.errorf(\"unexpected identifier: %q\", p.lit)\n\t}\n}\n\n// parseDirective parses a Directive:\n//\n//\tDirective = InitDataDirective |\n//\t\t\"package\" unquotedString [ unquotedString ] [ unquotedString ] \";\" |\n//\t\t\"pkgpath\" unquotedString \";\" |\n//\t\t\"prefix\" unquotedString \";\" |\n//\t\t\"import\" unquotedString unquotedString string \";\" |\n//\t\t\"indirectimport\" unquotedString unquotedstring \";\" |\n//\t\t\"func\" Func \";\" |\n//\t\t\"type\" Type \";\" |\n//\t\t\"var\" Var \";\" |\n//\t\t\"const\" Const \";\" .\nfunc (p *parser) parseDirective() {\n\tif p.tok != scanner.Ident {\n\t\t// unexpected token kind; panic\n\t\tp.expect(scanner.Ident)\n\t}\n\n\tswitch p.lit {\n\tcase \"v1\", \"v2\", \"v3\", \"priority\", \"init\", \"init_graph\", \"checksum\":\n\t\tp.parseInitDataDirective()\n\n\tcase \"package\":\n\t\tp.next()\n\t\tp.pkgname = p.parseUnquotedString()\n\t\tp.maybeCreatePackage()\n\t\tif p.version != \"v1\" && p.tok != '\\n' && p.tok != ';' {\n\t\t\tp.parseUnquotedString()\n\t\t\tp.parseUnquotedString()\n\t\t}\n\t\tp.expectEOL()\n\n\tcase \"pkgpath\":\n\t\tp.next()\n\t\tp.pkgpath = p.parseUnquotedString()\n\t\tp.maybeCreatePackage()\n\t\tp.expectEOL()\n\n\tcase \"prefix\":\n\t\tp.next()\n\t\tp.pkgpath = p.parseUnquotedString()\n\t\tp.expectEOL()\n\n\tcase \"import\":\n\t\tp.next()\n\t\tpkgname := p.parseUnquotedString()\n\t\tpkgpath := p.parseUnquotedString()\n\t\tp.getPkg(pkgpath, pkgname)\n\t\tp.parseString()\n\t\tp.expectEOL()\n\n\tcase \"indirectimport\":\n\t\tp.next()\n\t\tpkgname := p.parseUnquotedString()\n\t\tpkgpath := p.parseUnquotedString()\n\t\tp.getPkg(pkgpath, pkgname)\n\t\tp.expectEOL()\n\n\tcase \"types\":\n\t\tp.next()\n\t\tp.parseTypes(p.pkg)\n\t\tp.expectEOL()\n\n\tcase \"func\":\n\t\tp.next()\n\t\tfun := p.parseFunc(p.pkg)\n\t\tif fun != nil {\n\t\t\tp.pkg.Scope().Insert(fun)\n\t\t}\n\t\tp.expectEOL()\n\n\tcase \"type\":\n\t\tp.next()\n\t\tp.parseType(p.pkg)\n\t\tp.expectEOL()\n\n\tcase \"var\":\n\t\tp.next()\n\t\tv := p.parseVar(p.pkg)\n\t\tif v != nil {\n\t\t\tp.pkg.Scope().Insert(v)\n\t\t}\n\t\tp.expectEOL()\n\n\tcase \"const\":\n\t\tp.next()\n\t\tc := p.parseConst(p.pkg)\n\t\tp.pkg.Scope().Insert(c)\n\t\tp.expectEOL()\n\n\tdefault:\n\t\tp.errorf(\"unexpected identifier: %q\", p.lit)\n\t}\n}\n\n// parsePackage parses a Package:\n//\n//\tPackage = { Directive } .\nfunc (p *parser) parsePackage() *types.Package {\n\tfor p.tok != scanner.EOF {\n\t\tp.parseDirective()\n\t}\n\tfor _, f := range p.fixups {\n\t\tif f.target.Underlying() == nil {\n\t\t\tp.errorf(\"internal error: fixup can't be applied, loop required\")\n\t\t}\n\t\tf.toUpdate.SetUnderlying(f.target.Underlying())\n\t}\n\tp.fixups = nil\n\tfor _, typ := range p.typeList {\n\t\tif it, ok := types.Unalias(typ).(*types.Interface); ok {\n\t\t\tit.Complete()\n\t\t}\n\t}\n\tp.pkg.MarkComplete()\n\treturn p.pkg\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/parser_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Except for this comment, this file is a verbatim copy of the file\n// with the same name in $GOROOT/src/go/internal/gccgoimporter.\n\npackage gccgoimporter\n\nimport (\n\t\"bytes\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\t\"text/scanner\"\n)\n\nvar typeParserTests = []struct {\n\tid, typ, want, underlying, methods string\n}{\n\t{id: \"foo\", typ: \"<type -1>\", want: \"int8\"},\n\t{id: \"foo\", typ: \"<type 1 *<type -19>>\", want: \"*error\"},\n\t{id: \"foo\", typ: \"<type 1 *any>\", want: \"unsafe.Pointer\"},\n\t{id: \"foo\", typ: \"<type 1 \\\"Bar\\\" <type 2 *<type 1>>>\", want: \"foo.Bar\", underlying: \"*foo.Bar\"},\n\t{id: \"foo\", typ: \"<type 1 \\\"bar.Foo\\\" \\\"bar\\\" <type -1>\\nfunc (? <type 1>) M ();\\n>\", want: \"bar.Foo\", underlying: \"int8\", methods: \"func (bar.Foo).M()\"},\n\t{id: \"foo\", typ: \"<type 1 \\\".bar.foo\\\" \\\"bar\\\" <type -1>>\", want: \"bar.foo\", underlying: \"int8\"},\n\t{id: \"foo\", typ: \"<type 1 []<type -1>>\", want: \"[]int8\"},\n\t{id: \"foo\", typ: \"<type 1 [42]<type -1>>\", want: \"[42]int8\"},\n\t{id: \"foo\", typ: \"<type 1 map [<type -1>] <type -2>>\", want: \"map[int8]int16\"},\n\t{id: \"foo\", typ: \"<type 1 chan <type -1>>\", want: \"chan int8\"},\n\t{id: \"foo\", typ: \"<type 1 chan <- <type -1>>\", want: \"<-chan int8\"},\n\t{id: \"foo\", typ: \"<type 1 chan -< <type -1>>\", want: \"chan<- int8\"},\n\t{id: \"foo\", typ: \"<type 1 struct { I8 <type -1>; I16 <type -2> \\\"i16\\\"; }>\", want: \"struct{I8 int8; I16 int16 \\\"i16\\\"}\"},\n\t{id: \"foo\", typ: \"<type 1 interface { Foo (a <type -1>, b <type -2>) <type -1>; Bar (? <type -2>, ? ...<type -1>) (? <type -2>, ? <type -1>); Baz (); }>\", want: \"interface{Bar(int16, ...int8) (int16, int8); Baz(); Foo(a int8, b int16) int8}\"},\n\t{id: \"foo\", typ: \"<type 1 (? <type -1>) <type -2>>\", want: \"func(int8) int16\"},\n}\n\nfunc TestTypeParser(t *testing.T) {\n\tfor _, test := range typeParserTests {\n\t\tvar p parser\n\t\tp.init(\"test.gox\", strings.NewReader(test.typ), make(map[string]*types.Package))\n\t\tp.version = \"v2\"\n\t\tp.pkgname = test.id\n\t\tp.pkgpath = test.id\n\t\tp.maybeCreatePackage()\n\t\ttyp := p.parseType(p.pkg)\n\n\t\tif p.tok != scanner.EOF {\n\t\t\tt.Errorf(\"expected full parse, stopped at %q\", p.lit)\n\t\t}\n\n\t\t// interfaces must be explicitly completed\n\t\tif ityp, _ := typ.(*types.Interface); ityp != nil {\n\t\t\tityp.Complete()\n\t\t}\n\n\t\tgot := typ.String()\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"got type %q, expected %q\", got, test.want)\n\t\t}\n\n\t\tif test.underlying != \"\" {\n\t\t\tunderlying := typ.Underlying().String()\n\t\t\tif underlying != test.underlying {\n\t\t\t\tt.Errorf(\"got underlying type %q, expected %q\", underlying, test.underlying)\n\t\t\t}\n\t\t}\n\n\t\tif test.methods != \"\" {\n\t\t\tnt := typ.(*types.Named)\n\t\t\tvar buf bytes.Buffer\n\t\t\tfor i := 0; i != nt.NumMethods(); i++ {\n\t\t\t\tbuf.WriteString(nt.Method(i).String())\n\t\t\t}\n\t\t\tmethods := buf.String()\n\t\t\tif methods != test.methods {\n\t\t\t\tt.Errorf(\"got methods %q, expected %q\", methods, test.methods)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/aliases.go",
    "content": "package aliases\n\ntype (\n\tT0 [10]int\n\tT1 []byte\n\tT2 struct {\n\t\tx int\n\t}\n\tT3 interface {\n\t\tm() T2\n\t}\n\tT4 func(int, T0) chan T2\n)\n\n// basic aliases\ntype (\n\tAi = int\n\tA0 = T0\n\tA1 = T1\n\tA2 = T2\n\tA3 = T3\n\tA4 = T4\n\n\tA10 = [10]int\n\tA11 = []byte\n\tA12 = struct {\n\t\tx int\n\t}\n\tA13 = interface {\n\t\tm() A2\n\t}\n\tA14 = func(int, A0) chan A2\n)\n\n// alias receiver types\nfunc (T0) m1() {}\nfunc (A0) m2() {}\n\n// alias receiver types (long type declaration chains)\ntype (\n\tV0 = V1\n\tV1 = (V2)\n\tV2 = (V3)\n\tV3 = T0\n)\n\nfunc (V1) n() {}\n\n// cycles\ntype C0 struct {\n\tf1 C1\n\tf2 C2\n}\n\ntype (\n\tC1 *C0\n\tC2 = C1\n)\n\ntype (\n\tC5 struct {\n\t\tf *C6\n\t}\n\tC6 = C5\n)\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/aliases.gox",
    "content": "v2;\npackage aliases;\nprefix go;\npackage aliases go.aliases go.aliases;\ntype <type 1 \"A0\" = <type 2 \"T0\" <type 3 [10 ] <type -11>>\n func (? <esc:0x1> <type 2>) .go.aliases.m1 ();\n func (? <esc:0x1> <type 1>) .go.aliases.m2 ();\n func (? <esc:0x1> <type 4 \"V1\" = <type 5 \"V2\" = <type 6 \"V3\" = <type 2>>>>) .go.aliases.n ();\n>>;\ntype <type 7 \"A1\" = <type 8 \"T1\" <type 9 [] <type -20>>>>;\ntype <type 10 \"A10\" = <type 11 [10 ] <type -11>>>;\ntype <type 12 \"A11\" = <type 13 [] <type -20>>>;\ntype <type 14 \"A12\" = <type 15 struct { .go.aliases.x <type -11>; }>>;\ntype <type 16 \"A13\" = <type 17 interface { .go.aliases.m () <type 18 \"A2\" = <type 19 \"T2\" <type 20 struct { .go.aliases.x <type -11>; }>>>; }>>;\ntype <type 21 \"A14\" = <type 22 (? <type -11>, ? <type 1>) <type 23 chan <type 18>>>>;\ntype <type 18>;\ntype <type 24 \"A3\" = <type 25 \"T3\" <type 26 interface { .go.aliases.m () <type 19>; }>>>;\ntype <type 27 \"A4\" = <type 28 \"T4\" <type 29 (? <type -11>, ? <type 2>) <type 30 chan <type 19>>>>>;\ntype <type 31 \"Ai\" = <type -11>>;\ntype <type 32 \"C0\" <type 33 struct { .go.aliases.f1 <type 34 \"C1\" <type 35 *<type 32>>>; .go.aliases.f2 <type 36 \"C2\" = <type 34>>; }>>;\ntype <type 34>;\ntype <type 36>;\ntype <type 37 \"C5\" <type 38 struct { .go.aliases.f <type 39 *<type 40 \"C6\" = <type 37>>>; }>>;\ntype <type 40>;\ntype <type 2>;\ntype <type 8>;\ntype <type 19>;\ntype <type 25>;\ntype <type 28>;\ntype <type 41 \"V0\" = <type 4>>;\ntype <type 4>;\ntype <type 5>;\ntype <type 6>;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/complexnums.go",
    "content": "package complexnums\n\nconst NN = -1 - 1i\nconst NP = -1 + 1i\nconst PN = 1 - 1i\nconst PP = 1 + 1i\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/complexnums.gox",
    "content": "v1;\npackage complexnums;\npkgpath complexnums;\npriority 1;\nconst NN = -0.1E1-0.1E1i ;\nconst NP = -0.1E1+0.1E1i ;\nconst PN = 0.1E1-0.1E1i ;\nconst PP = 0.1E1+0.1E1i ;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/conversions.go",
    "content": "package conversions\n\ntype Units string\n\nconst Bits = Units(\"bits\")\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/conversions.gox",
    "content": "v2;\npackage conversions;\nprefix go;\npackage conversions go.conversions go.conversions;\nconst Bits <type 1 \"Units\" <type -16>> = convert(<type 1>, \"bits\");\ntype <type 1>;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/escapeinfo.go",
    "content": "// Test case for escape info in export data. To compile and extract .gox file:\n// gccgo -fgo-optimize-allocs -c escapeinfo.go\n// objcopy -j .go_export escapeinfo.o escapeinfo.gox\n\npackage escapeinfo\n\ntype T struct{ data []byte }\n\nfunc NewT(data []byte) *T {\n\treturn &T{data}\n}\n\nfunc (*T) Read(p []byte) {}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/escapeinfo.gox",
    "content": "v2;\npackage escapeinfo;\nprefix go;\npackage escapeinfo go.escapeinfo go.escapeinfo;\nfunc NewT (data <type 1 [] <type -20>>) <type 2 *<type 3 \"T\" <type 4 struct { .go.escapeinfo.data <type 5 [] <type -20>>; }>\n func (? <type 6 *<type 3>>) Read (p <esc:0x1> <type 7 [] <type -20>>);\n>>;\ntype <type 3>;\nchecksum 3500838130783C0059CD0C81527F60E9738E3ACE;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/imports.go",
    "content": "package imports\n\nimport \"fmt\"\n\nvar Hello = fmt.Sprintf(\"Hello, world\")\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/imports.gox",
    "content": "v1;\npackage imports;\npkgpath imports;\npriority 7;\nimport fmt fmt \"fmt\";\ninit imports imports..import 7 math math..import 1 runtime runtime..import 1 strconv strconv..import 2 io io..import 3 reflect reflect..import 3 syscall syscall..import 3 time time..import 4 os os..import 5 fmt fmt..import 6;\nvar Hello <type -16>;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue27856.go",
    "content": "package lib\n\ntype M struct {\n\tE E\n}\ntype F struct {\n\t_ *M\n}\ntype E = F\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue27856.gox",
    "content": "v2;\npackage main;\npkgpath main;\nimport runtime runtime \"runtime\";\ninit runtime runtime..import sys runtime_internal_sys..import;\ninit_graph 0 1;\ntype <type 1 \"E\" = <type 2 \"F\" <type 3 struct { .main._ <type 4 *<type 5 \"M\" <type 6 struct { E <type 1>; }>>>; }>>>;\ntype <type 2>;\ntype <type 5>;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue29198.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"errors\"\n)\n\ntype A struct {\n\tx int\n}\n\nfunc (a *A) AMethod(y int) *Server {\n\treturn nil\n}\n\n// FooServer is a server that provides Foo services\ntype FooServer Server\n\nfunc (f *FooServer) WriteEvents(ctx context.Context, x int) error {\n\treturn errors.New(\"hey!\")\n}\n\ntype Server struct {\n\tFooServer *FooServer\n\tuser      string\n\tctx       context.Context\n}\n\nfunc New(sctx context.Context, u string) (*Server, error) {\n\ts := &Server{user: u, ctx: sctx}\n\ts.FooServer = (*FooServer)(s)\n\treturn s, nil\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue29198.gox",
    "content": "v2;\npackage server;\npkgpath issue29198;\nimport context context \"context\";\nimport errors errors \"errors\";\ninit context context..import fmt fmt..import poll internal_poll..import testlog internal_testlog..import io io..import os os..import reflect reflect..import runtime runtime..import sys runtime_internal_sys..import strconv strconv..import sync sync..import syscall syscall..import time time..import unicode unicode..import;\ninit_graph 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 1 12 1 13 2 4 2 7 2 8 2 10 2 11 2 12 4 7 4 8 4 10 5 2 5 3 5 4 5 7 5 8 5 10 5 11 5 12 6 7 6 8 6 9 6 10 6 13 7 8 9 7 9 8 10 7 10 8 11 7 11 8 11 10 12 7 12 8 12 10 12 11;\ntype <type 1 \"A\" <type 2 struct { .issue29198.x <type -11>; }>\n func (a <esc:0x1> <type 3 *<type 1>>) AMethod (y <type -11>) <type 4 *<type 5 \"Server\" <type 6 struct { FooServer <type 7 *<type 8 \"FooServer\" <type 5>\n func (f <esc:0x1> <type 9 *<type 8>>) WriteEvents (ctx <esc:0x1> <type 10 \"context.Context\" <type 11 interface { Deadline () (deadline <type 12 \"time.Time\" \"time\" <type 13 struct { .time.wall <type -8>; .time.ext <type -4>; .time.loc <type 14 *<type 15 \"time.Location\" <type 16 struct { .time.name <type -16>; .time.zone <type 17 [] <type 18 \".time.zone\" <type 19 struct { .time.name <type -16>; .time.offset <type -11>; .time.isDST <type -15>; }>>>; .time.tx <type 20 [] <type 21 \".time.zoneTrans\" <type 22 struct { .time.when <type -4>; .time.index <type -5>; .time.isstd <type -15>; .time.isutc <type -15>; }>>>; .time.cacheStart <type -4>; .time.cacheEnd <type -4>; .time.cacheZone <type 23 *<type 18>>; }>\n func (l <esc:0x22> <type 24 *<type 15>>) String () <type -16>;\n func (l <esc:0x1> <type 24>) .time.lookupFirstZone () <type -11>;\n func (l <esc:0x12> <type 24>) .time.get () <type 24>;\n func (l <esc:0x32> <type 24>) .time.lookup (sec <type -4>) (name <type -16>, offset <type -11>, isDST <type -15>, start <type -4>, end <type -4>);\n func (l <esc:0x1> <type 24>) .time.lookupName (name <esc:0x1> <type -16>, unix <type -4>) (offset <type -11>, ok <type -15>);\n func (l <esc:0x1> <type 24>) .time.firstZoneUsed () <type -15>;\n>>; }>\n func (t <esc:0x12> <type 12>) In (loc <type 14>) <type 12>;\n func (t <esc:0x1> <type 12>) .time.date (full <type -15>) (year <type -11>, month <type 25 \"time.Month\" <type -11>\n func (m <type 25>) String () <type -16>;\n>, day <type -11>, yday <type -11>);\n func (t <esc:0x1> <type 12>) Sub (u <esc:0x1> <type 12>) <type 26 \"time.Duration\" <type -4>\n func (d <type 26>) Truncate (m <type 26>) <type 26>;\n func (d <type 26>) String () <type -16>;\n func (d <type 26>) Round (m <type 26>) <type 26>;\n func (d <type 26>) Seconds () <type -10>;\n func (d <type 26>) Nanoseconds () <type -4>;\n func (d <type 26>) Minutes () <type -10>;\n func (d <type 26>) Hours () <type -10>;\n>;\n func (t <esc:0x12> <type 12>) Add (d <type 26>) <type 12>;\n func (t <esc:0x12> <type 12>) UTC () <type 12>;\n func (t <type 12>) AddDate (years <type -11>, months <type -11>, days <type -11>) <type 12>;\n func (t <esc:0x1> <type 12>) MarshalBinary () (? <type 27 [] <type -20>>, ? <type -19>);\n func (t <esc:0x1> <type 12>) Nanosecond () <type -11>;\n func (t <esc:0x12> <type 12>) Round (d <type 26>) <type 12>;\n func (t <esc:0x1> <type 12>) Minute () <type -11>;\n func (t <esc:0x1> <type 12>) Clock () (hour <type -11>, min <type -11>, sec <type -11>);\n func (t <esc:0x1> <type 12>) ISOWeek () (year <type -11>, week <type -11>);\n func (t <esc:0x1> <type 12>) Day () <type -11>;\n func (t <esc:0x1> <type 28 *<type 12>>) .time.mono () <type -4>;\n func (t <esc:0x1> <type 12>) UnixNano () <type -4>;\n func (t <esc:0x1> <type 28>) .time.sec () <type -4>;\n func (t <esc:0x1> <type 12>) Second () <type -11>;\n func (t <esc:0x1> <type 12>) Before (u <esc:0x1> <type 12>) <type -15>;\n func (t <esc:0x1> <type 28>) UnmarshalBinary (data <esc:0x1> <type 29 [] <type -20>>) <type -19>;\n func (t <esc:0x1> <type 12>) Month () <type 25>;\n func (t <esc:0x1> <type 12>) YearDay () <type -11>;\n func (t <esc:0x12> <type 12>) Location () <type 14>;\n func (t <esc:0x32> <type 12>) Zone () (name <type -16>, offset <type -11>);\n func (t <esc:0x12> <type 12>) Local () <type 12>;\n func (t <esc:0x1> <type 28>) .time.setLoc (loc <type 14>);\n func (t <esc:0x12> <type 12>) Truncate (d <type 26>) <type 12>;\n func (t <esc:0x1> <type 12>) MarshalJSON () (? <type 30 [] <type -20>>, ? <type -19>);\n func (t <esc:0x1> <type 12>) AppendFormat (b <esc:0x12> <type 31 [] <type -20>>, layout <esc:0x1> <type -16>) <type 32 [] <type -20>>;\n func (t <esc:0x1> <type 28>) GobDecode (data <esc:0x1> <type 33 [] <type -20>>) <type -19>;\n func (t <esc:0x1> <type 28>) UnmarshalJSON (data <esc:0x1> <type 34 [] <type -20>>) <type -19>;\n func (t <esc:0x1> <type 12>) MarshalText () (? <type 35 [] <type -20>>, ? <type -19>);\n func (t <esc:0x1> <type 12>) GobEncode () (? <type 36 [] <type -20>>, ? <type -19>);\n func (t <esc:0x1> <type 28>) .time.stripMono ();\n func (t <esc:0x1> <type 12>) After (u <esc:0x1> <type 12>) <type -15>;\n func (t <esc:0x1> <type 12>) Hour () <type -11>;\n func (t <esc:0x1> <type 28>) UnmarshalText (data <esc:0x1> <type 37 [] <type -20>>) <type -19>;\n func (t <esc:0x1> <type 12>) Equal (u <esc:0x1> <type 12>) <type -15>;\n func (t <esc:0x1> <type 28>) .time.setMono (m <type -4>);\n func (t <esc:0x1> <type 12>) Year () <type -11>;\n func (t <esc:0x1> <type 12>) IsZero () <type -15>;\n func (t <esc:0x1> <type 28>) .time.addSec (d <type -4>);\n func (t <esc:0x1> <type 12>) Weekday () <type 38 \"time.Weekday\" <type -11>\n func (d <type 38>) String () <type -16>;\n>;\n func (t <esc:0x1> <type 12>) String () <type -16>;\n func (t <esc:0x1> <type 28>) .time.nsec () <type -3>;\n func (t <esc:0x1> <type 12>) Format (layout <esc:0x1> <type -16>) <type -16>;\n func (t <esc:0x1> <type 28>) .time.unixSec () <type -4>;\n func (t <esc:0x1> <type 12>) Unix () <type -4>;\n func (t <esc:0x1> <type 12>) .time.abs () <type -8>;\n func (t <esc:0x32> <type 12>) .time.locabs () (name <type -16>, offset <type -11>, abs <type -8>);\n func (t <esc:0x1> <type 12>) Date () (year <type -11>, month <type 25>, day <type -11>);\n>, ok <type -15>); Done () <type 39 chan <- <type 40 struct { }>>; Err () <type -19>; Value (key <type 41 interface { }>) <type 42 interface { }>; }>>, x <type -11>) <type -19>;\n>>; .issue29198.user <type -16>; .issue29198.ctx <type 10>; }>>>;\n>;\ntype <type 8>;\nfunc New (sctx <type 10>, u <type -16>) (? <type 43 *<type 5>>, ? <type -19>);\ntype <type 5>;\nchecksum 86C8D76B2582F55A8BD2CA9E00060358EC1CE214;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue30628.go",
    "content": "package issue30628\n\nimport (\n\t\"os\"\n\t\"sync\"\n)\n\nconst numR = int32(os.O_TRUNC + 5)\n\ntype Apple struct {\n\they sync.RWMutex\n\tx   int\n\tRQ  [numR]struct {\n\t\tCount    uintptr\n\t\tNumBytes uintptr\n\t\tLast     uintptr\n\t}\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue30628.gox",
    "content": "v3;\npackage issue30628\npkgpath issue30628\nimport os os \"os\"\nimport sync sync \"sync\"\ninit cpu internal..z2fcpu..import poll internal..z2fpoll..import testlog internal..z2ftestlog..import io io..import os os..import runtime runtime..import sys runtime..z2finternal..z2fsys..import sync sync..import syscall syscall..import time time..import\ninit_graph 1 0 1 3 1 5 1 6 1 7 1 8 1 9 3 0 3 5 3 6 3 7 4 0 4 1 4 2 4 3 4 5 4 6 4 7 4 8 4 9 5 0 5 6 7 0 7 5 7 6 8 0 8 5 8 6 8 7 9 0 9 5 9 6 9 7 9 8\ntypes 13 2 24 84 208 17 30 41 147 86 17 64 25 75\ntype 1 \"Apple\" <type 2>\ntype 2 struct { .issue30628.hey <type 3>; .issue30628.x <type -11>; RQ <type 11>; }\ntype 3 \"sync.RWMutex\" <type 7>\n func (rw <type 4>) Lock ()\n func (rw <esc:0x12> <type 4>) RLocker () ($ret8 <type 5>)\n func (rw <type 4>) RUnlock ()\n func (rw <type 4>) Unlock ()\n func (rw <type 4>) RLock ()\ntype 4 *<type 3>\ntype 5 \"sync.Locker\" <type 6>\ntype 6 interface { Lock (); Unlock (); }\ntype 7 struct { .sync.w <type 8>; .sync.writerSem <type -7>; .sync.readerSem <type -7>; .sync.readerCount <type -3>; .sync.readerWait <type -3>; }\ntype 8 \"sync.Mutex\" <type 10>\n func (m <type 9>) Unlock ()\n func (m <type 9>) Lock ()\ntype 9 *<type 8>\ntype 10 struct { .sync.state <type -3>; .sync.sema <type -7>; }\ntype 11 [517 ] <type 12>\ntype 12 struct { Count <type -13>; NumBytes <type -13>; Last <type -13>; }\nchecksum 199DCF6D3EE2FCF39F715B4E42B5F87F5B15D3AF\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue31540.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage issue31540\n\ntype Y struct {\n\tq int\n}\n\ntype Z map[int]int\n\ntype X = map[Y]Z\n\ntype A1 = X\n\ntype A2 = A1\n\ntype S struct {\n\tb int\n\tA2\n}\n\nfunc Hallo() S {\n\treturn S{}\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue31540.gox",
    "content": "v3;\npackage issue31540\npkgpath issue31540\ntypes 11 7 23 23 20 22 20 21 57 31 45 36\ntype 1 \"A1\" = <type 4>\ntype 2 \"A2\" = <type 1>\ntype 3 \"S\" <type 7>\ntype 4 \"X\" = <type 8>\ntype 5 \"Y\" <type 9>\ntype 6 \"Z\" <type 10>\ntype 7 struct { .go.mapalias.b <type -11>; ? <type 2>; }\ntype 8 map [<type 5>] <type 6>\ntype 9 struct { .go.mapalias.q <type -11>; }\ntype 10 map [<type -11>] <type -11>\nfunc Hallo () <type 3>\nchecksum C3FAF2524A90BC11225EE65D059BF27DFB69134B\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue34182.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage issue34182\n\ntype T1 struct {\n\tf *T2\n}\n\ntype T2 struct {\n\tf T3\n}\n\ntype T3 struct {\n\t*T2\n}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/issue34182.gox",
    "content": "v3;\npackage issue34182\npkgpath issue34182\ninit issue34182 ~go.issue34182\ntypes 8 4 21 21 21 17 30 45 45\ntype 1 \"T1\" <type 6>\ntype 2 \"T2\" <type 7>\ntype 3 \"T3\" <type 5>\ntype 4 *<type 2>\ntype 5 struct { ? <type 4>; }\ntype 6 struct { .go.issue34182.f <type 4>; }\ntype 7 struct { .go.issue34182.f <type 3>; }\nchecksum FF02C49BAF44B06C087ED4E573F7CC880C79C208\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/nointerface.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nointerface\n\ntype I int\n\n//go:nointerface\nfunc (p *I) Get() int { return int(*p) }\n\nfunc (p *I) Set(v int) { *p = I(v) }\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/nointerface.gox",
    "content": "v3;\npackage nointerface\npkgpath nointerface\ntypes 3 2 133 17\ntype 1 \"I\" <type -11>\n func /*nointerface*/ (p <esc:0x1> <type 2>) Get () <type -11>\n func (p <esc:0x1> <type 2>) Set (v <type -11>)\ntype 2 *<type 1>\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/notinheap.go",
    "content": "package notinheap\n\n//go:notinheap\ntype S struct{}\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/notinheap.gox",
    "content": "v3;\npackage notinheap\npkgpath notinheap\ninit notinheap ~notinheap\ntypes 3 2 30 18\ntype 1 \"S\" notinheap <type 2>\ntype 2 struct { }\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/pointer.go",
    "content": "package pointer\n\ntype Int8Ptr *int8\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/pointer.gox",
    "content": "v1;\npackage pointer;\npkgpath pointer;\ntype <type 1 \"Int8Ptr\" <type 2 *<type -1>>>;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/time.gox",
    "content": "v2;\npackage time;\npkgpath time;\nimport errors errors \"errors\";\nimport sync sync \"sync\";\nimport syscall syscall \"syscall\";\ninit time time..import runtime runtime..import sync sync..import syscall syscall..import;\ninit_graph 0 1 0 2 0 3 2 1 3 1 3 2;\nconst ANSIC = \"Mon Jan _2 15:04:05 2006\";\nfunc After (d <type 1 \"Duration\" <type -4>\n func (d <type 1>) String () <type -16>;\n func (d <type 1>) Nanoseconds () <type -4>;\n func (d <type 1>) Seconds () <type -10>;\n func (d <type 1>) Minutes () <type -10>;\n func (d <type 1>) Hours () <type -10>;\n>) <type 2 chan <- <type 3 \"Time\" <type 4 struct { .time.sec <type -4>; .time.nsec <type -3>; .time.loc <type 5 *<type 6 \"Location\" <type 7 struct { .time.name <type -16>; .time.zone <type 8 [] <type 9 \".time.zone\" <type 10 struct { .time.name <type -16>; .time.offset <type -11>; .time.isDST <type -15>; }>>>; .time.tx <type 11 [] <type 12 \".time.zoneTrans\" <type 13 struct { .time.when <type -4>; .time.index <type -5>; .time.isstd <type -15>; .time.isutc <type -15>; }>>>; .time.cacheStart <type -4>; .time.cacheEnd <type -4>; .time.cacheZone <type 14 *<type 9>>; }>\n func (l <type 15 *<type 6>>) .time.get () <type 15>;\n func (l <type 15>) String () <type -16>;\n func (l <type 15>) .time.lookup (sec <type -4>) (name <type -16>, offset <type -11>, isDST <type -15>, start <type -4>, end <type -4>);\n func (l <type 15>) .time.lookupFirstZone () <type -11>;\n func (l <type 15>) .time.firstZoneUsed () <type -15>;\n func (l <type 15>) .time.lookupName (name <type -16>, unix <type -4>) (offset <type -11>, isDST <type -15>, ok <type -15>);\n>>; }>\n func (t <type 3>) String () <type -16>;\n func (t <type 3>) Format (layout <type -16>) <type -16>;\n func (t <type 3>) AppendFormat (b <type 16 [] <type -20>>, layout <type -16>) <type 17 [] <type -20>>;\n func (t <type 3>) After (u <type 3>) <type -15>;\n func (t <type 3>) Before (u <type 3>) <type -15>;\n func (t <type 3>) Equal (u <type 3>) <type -15>;\n func (t <type 3>) IsZero () <type -15>;\n func (t <type 3>) .time.abs () <type -8>;\n func (t <type 3>) .time.locabs () (name <type -16>, offset <type -11>, abs <type -8>);\n func (t <type 3>) Date () (year <type -11>, month <type 18 \"Month\" <type -11>\n func (m <type 18>) String () <type -16>;\n>, day <type -11>);\n func (t <type 3>) Year () <type -11>;\n func (t <type 3>) Month () <type 18>;\n func (t <type 3>) Day () <type -11>;\n func (t <type 3>) Weekday () <type 19 \"Weekday\" <type -11>\n func (d <type 19>) String () <type -16>;\n>;\n func (t <type 3>) ISOWeek () (year <type -11>, week <type -11>);\n func (t <type 3>) Clock () (hour <type -11>, min <type -11>, sec <type -11>);\n func (t <type 3>) Hour () <type -11>;\n func (t <type 3>) Minute () <type -11>;\n func (t <type 3>) Second () <type -11>;\n func (t <type 3>) Nanosecond () <type -11>;\n func (t <type 3>) YearDay () <type -11>;\n func (t <type 3>) Add (d <type 1>) <type 3>;\n func (t <type 3>) Sub (u <type 3>) <type 1>;\n func (t <type 3>) AddDate (years <type -11>, months <type -11>, days <type -11>) <type 3>;\n func (t <type 3>) .time.date (full <type -15>) (year <type -11>, month <type 18>, day <type -11>, yday <type -11>);\n func (t <type 3>) UTC () <type 3>;\n func (t <type 3>) Local () <type 3>;\n func (t <type 3>) In (loc <type 20 *<type 6>>) <type 3>;\n func (t <type 3>) Location () <type 21 *<type 6>>;\n func (t <type 3>) Zone () (name <type -16>, offset <type -11>);\n func (t <type 3>) Unix () <type -4>;\n func (t <type 3>) UnixNano () <type -4>;\n func (t <type 3>) MarshalBinary () (? <type 22 [] <type -20>>, ? <type -19>);\n func (t <type 23 *<type 3>>) UnmarshalBinary (data <type 24 [] <type -20>>) <type -19>;\n func (t <type 3>) GobEncode () (? <type 25 [] <type -20>>, ? <type -19>);\n func (t <type 23>) GobDecode (data <type 26 [] <type -20>>) <type -19>;\n func (t <type 3>) MarshalJSON () (? <type 27 [] <type -20>>, ? <type -19>);\n func (t <type 23>) UnmarshalJSON (data <type 28 [] <type -20>>) <type -19>;\n func (t <type 3>) MarshalText () (? <type 29 [] <type -20>>, ? <type -19>);\n func (t <type 23>) UnmarshalText (data <type 30 [] <type -20>>) <type -19>;\n func (t <type 3>) Truncate (d <type 1>) <type 3>;\n func (t <type 3>) Round (d <type 1>) <type 3>;\n>>;\nfunc AfterFunc (d <type 1>, f <type 31 ()>) <type 32 *<type 33 \"Timer\" <type 34 struct { C <type 35 chan <- <type 3>>; .time.r <type 36 \".time.runtimeTimer\" <type 37 struct { .time.i <type -11>; .time.when <type -4>; .time.period <type -4>; .time.f <type 38 (? <type 39 interface { }>, ? <type -13>)>; .time.arg <type 40 interface { }>; .time.seq <type -13>; }>>; }>\n func (t <type 41 *<type 33>>) Stop () <type -15>;\n func (t <type 41>) Reset (d <type 1>) <type -15>;\n>>;\nconst April <type 18> = 4 ;\nconst August <type 18> = 8 ;\nfunc Date (year <type -11>, month <type 18>, day <type -11>, hour <type -11>, min <type -11>, sec <type -11>, nsec <type -11>, loc <type 42 *<type 6>>) <type 3>;\nconst December <type 18> = 12 ;\ntype <type 1>;\nconst February <type 18> = 2 ;\nfunc FixedZone (name <type -16>, offset <type -11>) <type 15>;\nconst Friday <type 19> = 5 ;\nconst Hour <type 1> = 3600000000000 ;\nconst January <type 18> = 1 ;\nconst July <type 18> = 7 ;\nconst June <type 18> = 6 ;\nconst Kitchen = \"3:04PM\";\nfunc LoadLocation (name <type -16>) (? <type 15>, ? <type -19>);\nvar Local <type 15>;\ntype <type 6>;\nvar LocationSource <type 43 (name <type -16>) (? <type 44 [] <type -20>>, ? <type -19>)>;\nconst March <type 18> = 3 ;\nconst May <type 18> = 5 ;\nconst Microsecond <type 1> = 1000 ;\nconst Millisecond <type 1> = 1000000 ;\nconst Minute <type 1> = 60000000000 ;\nconst Monday <type 19> = 1 ;\ntype <type 18>;\nconst Nanosecond <type 1> = 1 ;\nfunc NewTicker (d <type 1>) <type 45 *<type 46 \"Ticker\" <type 47 struct { C <type 48 chan <- <type 3>>; .time.r <type 36>; }>\n func (t <type 49 *<type 46>>) Stop ();\n>>;\nfunc NewTimer (d <type 1>) <type 32>;\nconst November <type 18> = 11 ;\nfunc Now () <type 3>;\nconst October <type 18> = 10 ;\nfunc Parse (layout <type -16>, value <type -16>) (? <type 3>, ? <type -19>);\nfunc ParseDuration (s <type -16>) (? <type 1>, ? <type -19>);\ntype <type 50 \"ParseError\" <type 51 struct { Layout <type -16>; Value <type -16>; LayoutElem <type -16>; ValueElem <type -16>; Message <type -16>; }>\n func (e <type 52 *<type 50>>) Error () <type -16>;\n>;\nfunc ParseInLocation (layout <type -16>, value <type -16>, loc <type 53 *<type 6>>) (? <type 3>, ? <type -19>);\nconst RFC1123 = \"Mon, 02 Jan 2006 15:04:05 MST\";\nconst RFC1123Z = \"Mon, 02 Jan 2006 15:04:05 -0700\";\nconst RFC3339 = \"2006-01-02T15:04:05Z07:00\";\nconst RFC3339Nano = \"2006-01-02T15:04:05.999999999Z07:00\";\nconst RFC822 = \"02 Jan 06 15:04 MST\";\nconst RFC822Z = \"02 Jan 06 15:04 -0700\";\nconst RFC850 = \"Monday, 02-Jan-06 15:04:05 MST\";\nconst RubyDate = \"Mon Jan 02 15:04:05 -0700 2006\";\nconst Saturday <type 19> = 6 ;\nconst Second <type 1> = 1000000000 ;\nconst September <type 18> = 9 ;\nfunc Since (t <type 3>) <type 1>;\nfunc Sleep (d <type 1>);\nconst Stamp = \"Jan _2 15:04:05\";\nconst StampMicro = \"Jan _2 15:04:05.000000\";\nconst StampMilli = \"Jan _2 15:04:05.000\";\nconst StampNano = \"Jan _2 15:04:05.000000000\";\nconst Sunday <type 19> = 0 ;\nconst Thursday <type 19> = 4 ;\nfunc Tick (d <type 1>) <type 54 chan <- <type 3>>;\ntype <type 46>;\ntype <type 3>;\ntype <type 33>;\nconst Tuesday <type 19> = 2 ;\nvar UTC <type 15>;\nfunc Unix (sec <type -4>, nsec <type -4>) <type 3>;\nconst UnixDate = \"Mon Jan _2 15:04:05 MST 2006\";\nconst Wednesday <type 19> = 3 ;\ntype <type 19>;\nchecksum C04E7F45B20C621A25DC74E9B13EA4FF6732E226;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/unicode.gox",
    "content": "v2;\npackage unicode;\npkgpath unicode;\ninit unicode unicode..import;\nvar ASCII_Hex_Digit <type 1 *<type 2 \"RangeTable\" <type 3 struct { R16 <type 4 [] <type 5 \"Range16\" <type 6 struct { Lo <type -6>; Hi <type -6>; Stride <type -6>; }>>>; R32 <type 7 [] <type 8 \"Range32\" <type 9 struct { Lo <type -7>; Hi <type -7>; Stride <type -7>; }>>>; LatinOffset <type -11>; }>>>;\nvar Adlam <type 1>;\nvar Ahom <type 1>;\nvar Anatolian_Hieroglyphs <type 1>;\nvar Arabic <type 1>;\nvar Armenian <type 1>;\nvar Avestan <type 1>;\nvar AzeriCase <type 10 \"SpecialCase\" <type 11 [] <type 12 \"CaseRange\" <type 13 struct { Lo <type -7>; Hi <type -7>; Delta <type 14 \".unicode.d\" <type 15 [3 ] <type -21>>>; }>>>\n func (special <type 10>) ToUpper (r <type -21>) <type -21>;\n func (special <type 10>) ToTitle (r <type -21>) <type -21>;\n func (special <type 10>) ToLower (r <type -21>) <type -21>;\n>;\nvar Balinese <type 1>;\nvar Bamum <type 1>;\nvar Bassa_Vah <type 1>;\nvar Batak <type 1>;\nvar Bengali <type 1>;\nvar Bhaiksuki <type 1>;\nvar Bidi_Control <type 1>;\nvar Bopomofo <type 1>;\nvar Brahmi <type 1>;\nvar Braille <type 1>;\nvar Buginese <type 1>;\nvar Buhid <type 1>;\nvar C <type 1>;\nvar Canadian_Aboriginal <type 1>;\nvar Carian <type 1>;\ntype <type 12>;\nvar CaseRanges <type 16 [] <type 12>>;\nvar Categories <type 17 map [<type -16>] <type 1>>;\nvar Caucasian_Albanian <type 1>;\nvar Cc <type 1>;\nvar Cf <type 1>;\nvar Chakma <type 1>;\nvar Cham <type 1>;\nvar Cherokee <type 1>;\nvar Co <type 1>;\nvar Common <type 1>;\nvar Coptic <type 1>;\nvar Cs <type 1>;\nvar Cuneiform <type 1>;\nvar Cypriot <type 1>;\nvar Cyrillic <type 1>;\nvar Dash <type 1>;\nvar Deprecated <type 1>;\nvar Deseret <type 1>;\nvar Devanagari <type 1>;\nvar Diacritic <type 1>;\nvar Digit <type 1>;\nvar Duployan <type 1>;\nvar Egyptian_Hieroglyphs <type 1>;\nvar Elbasan <type 1>;\nvar Ethiopic <type 1>;\nvar Extender <type 1>;\nvar FoldCategory <type 18 map [<type -16>] <type 1>>;\nvar FoldScript <type 19 map [<type -16>] <type 1>>;\nvar Georgian <type 1>;\nvar Glagolitic <type 1>;\nvar Gothic <type 1>;\nvar Grantha <type 1>;\nvar GraphicRanges <type 20 [] <type 21 *<type 2>>>;\nvar Greek <type 1>;\nvar Gujarati <type 1>;\nvar Gurmukhi <type 1>;\nvar Han <type 1>;\nvar Hangul <type 1>;\nvar Hanunoo <type 1>;\nvar Hatran <type 1>;\nvar Hebrew <type 1>;\nvar Hex_Digit <type 1>;\nvar Hiragana <type 1>;\nvar Hyphen <type 1>;\nvar IDS_Binary_Operator <type 1>;\nvar IDS_Trinary_Operator <type 1>;\nvar Ideographic <type 1>;\nvar Imperial_Aramaic <type 1>;\nfunc In (r <type -21>, ranges ...<type 22 *<type 2>>) <type -15>;\nvar Inherited <type 1>;\nvar Inscriptional_Pahlavi <type 1>;\nvar Inscriptional_Parthian <type 1>;\nfunc Is (rangeTab <type 1>, r <type -21>) <type -15>;\nfunc IsControl (r <type -21>) <type -15>;\nfunc IsDigit (r <type -21>) <type -15>;\nfunc IsGraphic (r <type -21>) <type -15>;\nfunc IsLetter (r <type -21>) <type -15>;\nfunc IsLower (r <type -21>) <type -15>;\nfunc IsMark (r <type -21>) <type -15>;\nfunc IsNumber (r <type -21>) <type -15>;\nfunc IsOneOf (ranges <type 23 [] <type 24 *<type 2>>>, r <type -21>) <type -15>;\nfunc IsPrint (r <type -21>) <type -15>;\nfunc IsPunct (r <type -21>) <type -15>;\nfunc IsSpace (r <type -21>) <type -15>;\nfunc IsSymbol (r <type -21>) <type -15>;\nfunc IsTitle (r <type -21>) <type -15>;\nfunc IsUpper (r <type -21>) <type -15>;\nvar Javanese <type 1>;\nvar Join_Control <type 1>;\nvar Kaithi <type 1>;\nvar Kannada <type 1>;\nvar Katakana <type 1>;\nvar Kayah_Li <type 1>;\nvar Kharoshthi <type 1>;\nvar Khmer <type 1>;\nvar Khojki <type 1>;\nvar Khudawadi <type 1>;\nvar L <type 1>;\nvar Lao <type 1>;\nvar Latin <type 1>;\nvar Lepcha <type 1>;\nvar Letter <type 1>;\nvar Limbu <type 1>;\nvar Linear_A <type 1>;\nvar Linear_B <type 1>;\nvar Lisu <type 1>;\nvar Ll <type 1>;\nvar Lm <type 1>;\nvar Lo <type 1>;\nvar Logical_Order_Exception <type 1>;\nvar Lower <type 1>;\nconst LowerCase = 1 ;\nvar Lt <type 1>;\nvar Lu <type 1>;\nvar Lycian <type 1>;\nvar Lydian <type 1>;\nvar M <type 1>;\nvar Mahajani <type 1>;\nvar Malayalam <type 1>;\nvar Mandaic <type 1>;\nvar Manichaean <type 1>;\nvar Marchen <type 1>;\nvar Mark <type 1>;\nconst MaxASCII = 127' ;\nconst MaxCase = 3 ;\nconst MaxLatin1 = 255' ;\nconst MaxRune = 1114111' ;\nvar Mc <type 1>;\nvar Me <type 1>;\nvar Meetei_Mayek <type 1>;\nvar Mende_Kikakui <type 1>;\nvar Meroitic_Cursive <type 1>;\nvar Meroitic_Hieroglyphs <type 1>;\nvar Miao <type 1>;\nvar Mn <type 1>;\nvar Modi <type 1>;\nvar Mongolian <type 1>;\nvar Mro <type 1>;\nvar Multani <type 1>;\nvar Myanmar <type 1>;\nvar N <type 1>;\nvar Nabataean <type 1>;\nvar Nd <type 1>;\nvar New_Tai_Lue <type 1>;\nvar Newa <type 1>;\nvar Nko <type 1>;\nvar Nl <type 1>;\nvar No <type 1>;\nvar Noncharacter_Code_Point <type 1>;\nvar Number <type 1>;\nvar Ogham <type 1>;\nvar Ol_Chiki <type 1>;\nvar Old_Hungarian <type 1>;\nvar Old_Italic <type 1>;\nvar Old_North_Arabian <type 1>;\nvar Old_Permic <type 1>;\nvar Old_Persian <type 1>;\nvar Old_South_Arabian <type 1>;\nvar Old_Turkic <type 1>;\nvar Oriya <type 1>;\nvar Osage <type 1>;\nvar Osmanya <type 1>;\nvar Other <type 1>;\nvar Other_Alphabetic <type 1>;\nvar Other_Default_Ignorable_Code_Point <type 1>;\nvar Other_Grapheme_Extend <type 1>;\nvar Other_ID_Continue <type 1>;\nvar Other_ID_Start <type 1>;\nvar Other_Lowercase <type 1>;\nvar Other_Math <type 1>;\nvar Other_Uppercase <type 1>;\nvar P <type 1>;\nvar Pahawh_Hmong <type 1>;\nvar Palmyrene <type 1>;\nvar Pattern_Syntax <type 1>;\nvar Pattern_White_Space <type 1>;\nvar Pau_Cin_Hau <type 1>;\nvar Pc <type 1>;\nvar Pd <type 1>;\nvar Pe <type 1>;\nvar Pf <type 1>;\nvar Phags_Pa <type 1>;\nvar Phoenician <type 1>;\nvar Pi <type 1>;\nvar Po <type 1>;\nvar Prepended_Concatenation_Mark <type 1>;\nvar PrintRanges <type 25 [] <type 26 *<type 2>>>;\nvar Properties <type 27 map [<type -16>] <type 1>>;\nvar Ps <type 1>;\nvar Psalter_Pahlavi <type 1>;\nvar Punct <type 1>;\nvar Quotation_Mark <type 1>;\nvar Radical <type 1>;\ntype <type 5>;\ntype <type 8>;\ntype <type 2>;\nvar Rejang <type 1>;\nconst ReplacementChar = 65533' ;\nvar Runic <type 1>;\nvar S <type 1>;\nvar STerm <type 1>;\nvar Samaritan <type 1>;\nvar Saurashtra <type 1>;\nvar Sc <type 1>;\nvar Scripts <type 28 map [<type -16>] <type 1>>;\nvar Sentence_Terminal <type 1>;\nvar Sharada <type 1>;\nvar Shavian <type 1>;\nvar Siddham <type 1>;\nvar SignWriting <type 1>;\nfunc SimpleFold (r <type -21>) <type -21>;\nvar Sinhala <type 1>;\nvar Sk <type 1>;\nvar Sm <type 1>;\nvar So <type 1>;\nvar Soft_Dotted <type 1>;\nvar Sora_Sompeng <type 1>;\nvar Space <type 1>;\ntype <type 10>;\nvar Sundanese <type 1>;\nvar Syloti_Nagri <type 1>;\nvar Symbol <type 1>;\nvar Syriac <type 1>;\nvar Tagalog <type 1>;\nvar Tagbanwa <type 1>;\nvar Tai_Le <type 1>;\nvar Tai_Tham <type 1>;\nvar Tai_Viet <type 1>;\nvar Takri <type 1>;\nvar Tamil <type 1>;\nvar Tangut <type 1>;\nvar Telugu <type 1>;\nvar Terminal_Punctuation <type 1>;\nvar Thaana <type 1>;\nvar Thai <type 1>;\nvar Tibetan <type 1>;\nvar Tifinagh <type 1>;\nvar Tirhuta <type 1>;\nvar Title <type 1>;\nconst TitleCase = 2 ;\nfunc To (_case <type -11>, r <type -21>) <type -21>;\nfunc ToLower (r <type -21>) <type -21>;\nfunc ToTitle (r <type -21>) <type -21>;\nfunc ToUpper (r <type -21>) <type -21>;\nvar TurkishCase <type 10>;\nvar Ugaritic <type 1>;\nvar Unified_Ideograph <type 1>;\nvar Upper <type 1>;\nconst UpperCase = 0 ;\nconst UpperLower = 1114112' ;\nvar Vai <type 1>;\nvar Variation_Selector <type 1>;\nconst Version = \"9.0.0\";\nvar Warang_Citi <type 1>;\nvar White_Space <type 1>;\nvar Yi <type 1>;\nvar Z <type 1>;\nvar Zl <type 1>;\nvar Zp <type 1>;\nvar Zs <type 1>;\nchecksum 7643975C0BE2732C7557F1B2A70796673C11DF4A;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testdata/v1reflect.gox",
    "content": "v1;\npackage reflect;\npkgpath reflect;\npriority 3;\nimport math math \"math\";\nimport runtime runtime \"runtime\";\nimport strconv strconv \"strconv\";\nimport sync sync \"sync\";\nimport unsafe unsafe \"unsafe\";\ninit reflect reflect..import 3 math math..import 1 runtime runtime..import 1 strconv strconv..import 2;\nfunc Append (s <type 1 \"Value\" <type 2 struct { .reflect.typ <type 3 *<type 4 \".reflect.commonType\" <type 5 struct { .reflect.kind <type -5>; .reflect.align <type -1>; .reflect.fieldAlign <type -5>; .reflect._ <type -5>; .reflect.size <type -13>; .reflect.hash <type -7>; .reflect.hashfn <type 6 (? <type 7 \"unsafe.Pointer\" <type 8 *any>>, ? <type -13>)>; .reflect.equalfn <type 9 (? <type 7>, ? <type 7>, ? <type -13>)>; .reflect.string <type 10 *<type -16>>; ? <type 11 *<type 12 \".reflect.uncommonType\" <type 13 struct { .reflect.name <type 14 *<type -16>>; .reflect.pkgPath <type 15 *<type -16>>; .reflect.methods <type 16 [] <type 17 \".reflect.method\" <type 18 struct { .reflect.name <type 19 *<type -16>>; .reflect.pkgPath <type 20 *<type -16>>; .reflect.mtyp <type 21 *<type 22 \".reflect.runtimeType\" <type 4>>>; .reflect.typ <type 21>; .reflect.tfn <type 7>; }>>>; }>\n func (t <type 23 *<type 12>>) .reflect.uncommon () <type 23>;\n func (t <type 23>) PkgPath () <type -16>;\n func (t <type 23>) Name () <type -16>;\n func (t <type 23>) Method (i <type -11>) (m <type 24 \"Method\" <type 25 struct { Name <type -16>; PkgPath <type -16>; Type <type 26 \"Type\" <type 27 interface { Align () <type -11>; FieldAlign () <type -11>; Method (? <type -11>) <type 24>; MethodByName (? <type -16>) (? <type 24>, ? <type -15>); NumMethod () <type -11>; Name () <type -16>; PkgPath () <type -16>; Size () <type -13>; String () <type -16>; .reflect.rawString () <type -16>; Kind () <type 28 \"Kind\" <type -12>\n func (k <type 28>) String () <type -16>;\n>; Implements (u <type 26>) <type -15>; AssignableTo (u <type 26>) <type -15>; Bits () <type -11>; ChanDir () <type 29 \"ChanDir\" <type -11>\n func (d <type 29>) String () <type -16>;\n>; IsVariadic () <type -15>; Elem () <type 26>; Field (i <type -11>) <type 30 \"StructField\" <type 31 struct { Name <type -16>; PkgPath <type -16>; Type <type 26>; Tag <type 32 \"StructTag\" <type -16>\n func (tag <type 32>) Get (key <type -16>) <type -16>;\n>; Offset <type -13>; Index <type 33 [] <type -11>>; Anonymous <type -15>; }>>; FieldByIndex (index <type 34 [] <type -11>>) <type 30>; FieldByName (name <type -16>) (? <type 30>, ? <type -15>); FieldByNameFunc (match <type 35 (? <type -16>) <type -15>>) (? <type 30>, ? <type -15>); In (i <type -11>) <type 26>; Key () <type 26>; Len () <type -11>; NumField () <type -11>; NumIn () <type -11>; NumOut () <type -11>; Out (i <type -11>) <type 26>; .reflect.runtimeType () <type 36 *<type 22>>; .reflect.common () <type 37 *<type 4>>; .reflect.uncommon () <type 38 *<type 12>>; }>>; Func <type 1>; Index <type -11>; }>>);\n func (t <type 23>) NumMethod () <type -11>;\n func (t <type 23>) MethodByName (name <type -16>) (m <type 24>, ok <type -15>);\n>>; .reflect.ptrToThis <type 21>; }>\n func (t <type 39 *<type 4>>) .reflect.toType () <type 26>;\n func (t <type 39>) .reflect.rawString () <type -16>;\n func (t <type 39>) String () <type -16>;\n func (t <type 39>) Size () <type -13>;\n func (t <type 39>) Bits () <type -11>;\n func (t <type 39>) Align () <type -11>;\n func (t <type 39>) FieldAlign () <type -11>;\n func (t <type 39>) Kind () <type 28>;\n func (t <type 39>) .reflect.common () <type 39>;\n func (t <type 39>) NumMethod () <type -11>;\n func (t <type 39>) Method (i <type -11>) (m <type 24>);\n func (t <type 39>) MethodByName (name <type -16>) (m <type 24>, ok <type -15>);\n func (t <type 39>) PkgPath () <type -16>;\n func (t <type 39>) Name () <type -16>;\n func (t <type 39>) ChanDir () <type 29>;\n func (t <type 39>) IsVariadic () <type -15>;\n func (t <type 39>) Elem () <type 26>;\n func (t <type 39>) Field (i <type -11>) <type 30>;\n func (t <type 39>) FieldByIndex (index <type 40 [] <type -11>>) <type 30>;\n func (t <type 39>) FieldByName (name <type -16>) (? <type 30>, ? <type -15>);\n func (t <type 39>) FieldByNameFunc (match <type 41 (? <type -16>) <type -15>>) (? <type 30>, ? <type -15>);\n func (t <type 39>) In (i <type -11>) <type 26>;\n func (t <type 39>) Key () <type 26>;\n func (t <type 39>) Len () <type -11>;\n func (t <type 39>) NumField () <type -11>;\n func (t <type 39>) NumIn () <type -11>;\n func (t <type 39>) NumOut () <type -11>;\n func (t <type 39>) Out (i <type -11>) <type 26>;\n func (t <type 39>) .reflect.runtimeType () <type 21>;\n func (ct <type 39>) .reflect.ptrTo () <type 39>;\n func (t <type 39>) Implements (u <type 26>) <type -15>;\n func (t <type 39>) AssignableTo (u <type 26>) <type -15>;\n>>; .reflect.val <type 7>; ? <type 42 \".reflect.flag\" <type -13>\n func (f <type 42>) .reflect.kind () <type 28>;\n func (f <type 42>) .reflect.mustBe (expected <type 28>);\n func (f <type 42>) .reflect.mustBeExported ();\n func (f <type 42>) .reflect.mustBeAssignable ();\n>; }>\n func (v <type 1>) .reflect.iword () <type 43 \".reflect.iword\" <type 7>>;\n func (v <type 1>) Addr () <type 1>;\n func (v <type 1>) Bool () <type -15>;\n func (v <type 1>) Bytes () <type 44 [] <type -20>>;\n func (v <type 1>) CanAddr () <type -15>;\n func (v <type 1>) CanSet () <type -15>;\n func (v <type 1>) Call (in <type 45 [] <type 1>>) <type 46 [] <type 1>>;\n func (v <type 1>) CallSlice (in <type 47 [] <type 1>>) <type 48 [] <type 1>>;\n func (v <type 1>) .reflect.call (method <type -16>, in <type 49 [] <type 1>>) <type 50 [] <type 1>>;\n func (v <type 1>) Cap () <type -11>;\n func (v <type 1>) Close ();\n func (v <type 1>) Complex () <type -18>;\n func (v <type 1>) Elem () <type 1>;\n func (v <type 1>) Field (i <type -11>) <type 1>;\n func (v <type 1>) FieldByIndex (index <type 51 [] <type -11>>) <type 1>;\n func (v <type 1>) FieldByName (name <type -16>) <type 1>;\n func (v <type 1>) FieldByNameFunc (match <type 52 (? <type -16>) <type -15>>) <type 1>;\n func (v <type 1>) Float () <type -10>;\n func (v <type 1>) Index (i <type -11>) <type 1>;\n func (v <type 1>) Int () <type -4>;\n func (v <type 1>) CanInterface () <type -15>;\n func (v <type 1>) Interface () (i <type 53 interface { }>);\n func (v <type 1>) InterfaceData () <type 54 [2 ] <type -13>>;\n func (v <type 1>) IsNil () <type -15>;\n func (v <type 1>) IsValid () <type -15>;\n func (v <type 1>) Kind () <type 28>;\n func (v <type 1>) Len () <type -11>;\n func (v <type 1>) MapIndex (key <type 1>) <type 1>;\n func (v <type 1>) MapKeys () <type 55 [] <type 1>>;\n func (v <type 1>) Method (i <type -11>) <type 1>;\n func (v <type 1>) NumMethod () <type -11>;\n func (v <type 1>) MethodByName (name <type -16>) <type 1>;\n func (v <type 1>) NumField () <type -11>;\n func (v <type 1>) OverflowComplex (x <type -18>) <type -15>;\n func (v <type 1>) OverflowFloat (x <type -10>) <type -15>;\n func (v <type 1>) OverflowInt (x <type -4>) <type -15>;\n func (v <type 1>) OverflowUint (x <type -8>) <type -15>;\n func (v <type 1>) Pointer () <type -13>;\n func (v <type 1>) Recv () (x <type 1>, ok <type -15>);\n func (v <type 1>) .reflect.recv (nb <type -15>) (val <type 1>, ok <type -15>);\n func (v <type 1>) Send (x <type 1>);\n func (v <type 1>) .reflect.send (x <type 1>, nb <type -15>) (selected <type -15>);\n func (v <type 1>) Set (x <type 1>);\n func (v <type 1>) SetBool (x <type -15>);\n func (v <type 1>) SetBytes (x <type 56 [] <type -20>>);\n func (v <type 1>) SetComplex (x <type -18>);\n func (v <type 1>) SetFloat (x <type -10>);\n func (v <type 1>) SetInt (x <type -4>);\n func (v <type 1>) SetLen (n <type -11>);\n func (v <type 1>) SetMapIndex (key <type 1>, val <type 1>);\n func (v <type 1>) SetUint (x <type -8>);\n func (v <type 1>) SetPointer (x <type 7>);\n func (v <type 1>) SetString (x <type -16>);\n func (v <type 1>) Slice (beg <type -11>, end <type -11>) <type 1>;\n func (v <type 1>) String () <type -16>;\n func (v <type 1>) TryRecv () (x <type 1>, ok <type -15>);\n func (v <type 1>) TrySend (x <type 1>) <type -15>;\n func (v <type 1>) Type () <type 26>;\n func (v <type 1>) Uint () <type -8>;\n func (v <type 1>) UnsafeAddr () <type -13>;\n func (v <type 1>) .reflect.assignTo (context <type -16>, dst <type 3>, target <type 57 *<type 58 interface { }>>) <type 1>;\n>, x ...<type 1>) <type 1>;\nfunc AppendSlice (s <type 1>, t <type 1>) <type 1>;\nconst Array <type 28> = 17 ;\nconst Bool <type 28> = 1 ;\nconst BothDir <type 29> = 3 ;\nconst Chan <type 28> = 18 ;\ntype <type 29>;\nconst Complex128 <type 28> = 16 ;\nconst Complex64 <type 28> = 15 ;\nfunc Copy (dst <type 1>, src <type 1>) <type -11>;\nfunc DeepEqual (a1 <type 59 interface { }>, a2 <type 59>) <type -15>;\nconst Float32 <type 28> = 13 ;\nconst Float64 <type 28> = 14 ;\nconst Func <type 28> = 19 ;\nfunc Indirect (v <type 1>) <type 1>;\nconst Int <type 28> = 2 ;\nconst Int16 <type 28> = 4 ;\nconst Int32 <type 28> = 5 ;\nconst Int64 <type 28> = 6 ;\nconst Int8 <type 28> = 3 ;\nconst Interface <type 28> = 20 ;\nconst Invalid <type 28> = 0 ;\ntype <type 28>;\nfunc MakeChan (typ <type 26>, buffer <type -11>) <type 1>;\nfunc MakeMap (typ <type 26>) <type 1>;\nfunc MakeSlice (typ <type 26>, len <type -11>, cap <type -11>) <type 1>;\nconst Map <type 28> = 21 ;\ntype <type 24>;\nfunc Method$equal (key1 <type 8>, key2 <type 8>, key_size <type -13>) <type -15>;\nfunc Method$hash (key <type 8>, key_size <type -13>) <type -13>;\nfunc New (typ <type 26>) <type 1>;\nfunc NewAt (typ <type 26>, p <type 7>) <type 1>;\nconst Ptr <type 28> = 22 ;\nfunc PtrTo (t <type 26>) <type 26>;\nconst RecvDir <type 29> = 1 ;\nconst SendDir <type 29> = 2 ;\nconst Slice <type 28> = 23 ;\ntype <type 60 \"SliceHeader\" <type 61 struct { Data <type -13>; Len <type -11>; Cap <type -11>; }>>;\nconst String <type 28> = 24 ;\ntype <type 62 \"StringHeader\" <type 63 struct { Data <type -13>; Len <type -11>; }>>;\nconst Struct <type 28> = 25 ;\ntype <type 30>;\ntype <type 32>;\ntype <type 26>;\nfunc TypeOf (i <type 64 interface { }>) <type 26>;\nconst Uint <type 28> = 7 ;\nconst Uint16 <type 28> = 9 ;\nconst Uint32 <type 28> = 10 ;\nconst Uint64 <type 28> = 11 ;\nconst Uint8 <type 28> = 8 ;\nconst Uintptr <type 28> = 12 ;\nconst UnsafePointer <type 28> = 26 ;\ntype <type 1>;\ntype <type 65 \"ValueError\" <type 66 struct { Method <type -16>; Kind <type 28>; }>\n func (e <type 67 *<type 65>>) Error () <type -16>;\n>;\nfunc ValueError$equal (key1 <type 8>, key2 <type 8>, key_size <type -13>) <type -15>;\nfunc ValueError$hash (key <type 8>, key_size <type -13>) <type -13>;\nfunc ValueOf (i <type 68 interface { }>) <type 1>;\nfunc Zero (typ <type 26>) <type 1>;\nchecksum DD7720796E91D9D24ED12B75BDEA2A714D47B095;\n"
  },
  {
    "path": "go/internal/gccgoimporter/testenv_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains testing utilities copied from $GOROOT/src/internal/testenv/testenv.go.\n\npackage gccgoimporter\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\n\ttoolstestenv \"golang.org/x/tools/internal/testenv\"\n)\n\n// HasExec reports whether the current system can start new processes\n// using os.StartProcess or (more commonly) exec.Command.\nfunc HasExec() bool {\n\treturn toolstestenv.HasExec()\n}\n\n// MustHaveExec checks that the current system can start new processes\n// using os.StartProcess or (more commonly) exec.Command.\n// If not, MustHaveExec calls t.Skip with an explanation.\nfunc MustHaveExec(t *testing.T) {\n\tif !HasExec() {\n\t\tt.Skipf(\"skipping test: cannot exec subprocess on %s/%s\", runtime.GOOS, runtime.GOARCH)\n\t}\n}\n\nvar testenv = struct {\n\tMustHaveExec func(*testing.T)\n}{\n\tMustHaveExec: MustHaveExec,\n}\n"
  },
  {
    "path": "go/loader/doc.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package loader loads a complete Go program from source code, parsing\n// and type-checking the initial packages plus their transitive closure\n// of dependencies.  The ASTs and the derived facts are retained for\n// later use.\n//\n// Deprecated: This is an older API and does not have support\n// for modules. Use golang.org/x/tools/go/packages instead.\n//\n// The package defines two primary types: Config, which specifies a\n// set of initial packages to load and various other options; and\n// Program, which is the result of successfully loading the packages\n// specified by a configuration.\n//\n// The configuration can be set directly, but *Config provides various\n// convenience methods to simplify the common cases, each of which can\n// be called any number of times.  Finally, these are followed by a\n// call to Load() to actually load and type-check the program.\n//\n//\tvar conf loader.Config\n//\n//\t// Use the command-line arguments to specify\n//\t// a set of initial packages to load from source.\n//\t// See FromArgsUsage for help.\n//\trest, err := conf.FromArgs(os.Args[1:], wantTests)\n//\n//\t// Parse the specified files and create an ad hoc package with path \"foo\".\n//\t// All files must have the same 'package' declaration.\n//\tconf.CreateFromFilenames(\"foo\", \"foo.go\", \"bar.go\")\n//\n//\t// Create an ad hoc package with path \"foo\" from\n//\t// the specified already-parsed files.\n//\t// All ASTs must have the same 'package' declaration.\n//\tconf.CreateFromFiles(\"foo\", parsedFiles)\n//\n//\t// Add \"runtime\" to the set of packages to be loaded.\n//\tconf.Import(\"runtime\")\n//\n//\t// Adds \"fmt\" and \"fmt_test\" to the set of packages\n//\t// to be loaded.  \"fmt\" will include *_test.go files.\n//\tconf.ImportWithTests(\"fmt\")\n//\n//\t// Finally, load all the packages specified by the configuration.\n//\tprog, err := conf.Load()\n//\n// See examples_test.go for examples of API usage.\n//\n// # CONCEPTS AND TERMINOLOGY\n//\n// The WORKSPACE is the set of packages accessible to the loader.  The\n// workspace is defined by Config.Build, a *build.Context.  The\n// default context treats subdirectories of $GOROOT and $GOPATH as\n// packages, but this behavior may be overridden.\n//\n// An AD HOC package is one specified as a set of source files on the\n// command line.  In the simplest case, it may consist of a single file\n// such as $GOROOT/src/net/http/triv.go.\n//\n// EXTERNAL TEST packages are those comprised of a set of *_test.go\n// files all with the same 'package foo_test' declaration, all in the\n// same directory.  (go/build.Package calls these files XTestFiles.)\n//\n// An IMPORTABLE package is one that can be referred to by some import\n// spec.  Every importable package is uniquely identified by its\n// PACKAGE PATH or just PATH, a string such as \"fmt\", \"encoding/json\",\n// or \"cmd/vendor/golang.org/x/arch/x86/x86asm\".  A package path\n// typically denotes a subdirectory of the workspace.\n//\n// An import declaration uses an IMPORT PATH to refer to a package.\n// Most import declarations use the package path as the import path.\n//\n// Due to VENDORING (https://golang.org/s/go15vendor), the\n// interpretation of an import path may depend on the directory in which\n// it appears.  To resolve an import path to a package path, go/build\n// must search the enclosing directories for a subdirectory named\n// \"vendor\".\n//\n// ad hoc packages and external test packages are NON-IMPORTABLE.  The\n// path of an ad hoc package is inferred from the package\n// declarations of its files and is therefore not a unique package key.\n// For example, Config.CreatePkgs may specify two initial ad hoc\n// packages, both with path \"main\".\n//\n// An AUGMENTED package is an importable package P plus all the\n// *_test.go files with same 'package foo' declaration as P.\n// (go/build.Package calls these files TestFiles.)\n//\n// The INITIAL packages are those specified in the configuration.  A\n// DEPENDENCY is a package loaded to satisfy an import in an initial\n// package or another dependency.\npackage loader\n\n// IMPLEMENTATION NOTES\n//\n// 'go test', in-package test files, and import cycles\n// ---------------------------------------------------\n//\n// An external test package may depend upon members of the augmented\n// package that are not in the unaugmented package, such as functions\n// that expose internals.  (See bufio/export_test.go for an example.)\n// So, the loader must ensure that for each external test package\n// it loads, it also augments the corresponding non-test package.\n//\n// The import graph over n unaugmented packages must be acyclic; the\n// import graph over n-1 unaugmented packages plus one augmented\n// package must also be acyclic.  ('go test' relies on this.)  But the\n// import graph over n augmented packages may contain cycles.\n//\n// First, all the (unaugmented) non-test packages and their\n// dependencies are imported in the usual way; the loader reports an\n// error if it detects an import cycle.\n//\n// Then, each package P for which testing is desired is augmented by\n// the list P' of its in-package test files, by calling\n// (*types.Checker).Files.  This arrangement ensures that P' may\n// reference definitions within P, but P may not reference definitions\n// within P'.  Furthermore, P' may import any other package, including\n// ones that depend upon P, without an import cycle error.\n//\n// Consider two packages A and B, both of which have lists of\n// in-package test files we'll call A' and B', and which have the\n// following import graph edges:\n//    B  imports A\n//    B' imports A\n//    A' imports B\n// This last edge would be expected to create an error were it not\n// for the special type-checking discipline above.\n// Cycles of size greater than two are possible.  For example:\n//   compress/bzip2/bzip2_test.go (package bzip2)  imports \"io/ioutil\"\n//   io/ioutil/tempfile_test.go   (package ioutil) imports \"regexp\"\n//   regexp/exec_test.go          (package regexp) imports \"compress/bzip2\"\n//\n//\n// Concurrency\n// -----------\n//\n// Let us define the import dependency graph as follows.  Each node is a\n// list of files passed to (Checker).Files at once.  Many of these lists\n// are the production code of an importable Go package, so those nodes\n// are labelled by the package's path.  The remaining nodes are\n// ad hoc packages and lists of in-package *_test.go files that augment\n// an importable package; those nodes have no label.\n//\n// The edges of the graph represent import statements appearing within a\n// file.  An edge connects a node (a list of files) to the node it\n// imports, which is importable and thus always labelled.\n//\n// Loading is controlled by this dependency graph.\n//\n// To reduce I/O latency, we start loading a package's dependencies\n// asynchronously as soon as we've parsed its files and enumerated its\n// imports (scanImports).  This performs a preorder traversal of the\n// import dependency graph.\n//\n// To exploit hardware parallelism, we type-check unrelated packages in\n// parallel, where \"unrelated\" means not ordered by the partial order of\n// the import dependency graph.\n//\n// We use a concurrency-safe non-blocking cache (importer.imported) to\n// record the results of type-checking, whether success or failure.  An\n// entry is created in this cache by startLoad the first time the\n// package is imported.  The first goroutine to request an entry becomes\n// responsible for completing the task and broadcasting completion to\n// subsequent requesters, which block until then.\n//\n// Type checking occurs in (parallel) postorder: we cannot type-check a\n// set of files until we have loaded and type-checked all of their\n// immediate dependencies (and thus all of their transitive\n// dependencies). If the input were guaranteed free of import cycles,\n// this would be trivial: we could simply wait for completion of the\n// dependencies and then invoke the typechecker.\n//\n// But as we saw in the 'go test' section above, some cycles in the\n// import graph over packages are actually legal, so long as the\n// cycle-forming edge originates in the in-package test files that\n// augment the package.  This explains why the nodes of the import\n// dependency graph are not packages, but lists of files: the unlabelled\n// nodes avoid the cycles.  Consider packages A and B where B imports A\n// and A's in-package tests AT import B.  The naively constructed import\n// graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but\n// the graph over lists of files is AT --> B --> A, where AT is an\n// unlabelled node.\n//\n// Awaiting completion of the dependencies in a cyclic graph would\n// deadlock, so we must materialize the import dependency graph (as\n// importer.graph) and check whether each import edge forms a cycle.  If\n// x imports y, and the graph already contains a path from y to x, then\n// there is an import cycle, in which case the processing of x must not\n// wait for the completion of processing of y.\n//\n// When the type-checker makes a callback (doImport) to the loader for a\n// given import edge, there are two possible cases.  In the normal case,\n// the dependency has already been completely type-checked; doImport\n// does a cache lookup and returns it.  In the cyclic case, the entry in\n// the cache is still necessarily incomplete, indicating a cycle.  We\n// perform the cycle check again to obtain the error message, and return\n// the error.\n//\n// The result of using concurrency is about a 2.5x speedup for stdlib_test.\n"
  },
  {
    "path": "go/loader/loader.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage loader\n\n// See doc.go for package documentation and implementation notes.\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/internal/cgo\"\n)\n\nvar ignoreVendor build.ImportMode\n\nconst trace = false // show timing info for type-checking\n\n// Config specifies the configuration for loading a whole program from\n// Go source code.\n// The zero value for Config is a ready-to-use default configuration.\ntype Config struct {\n\t// Fset is the file set for the parser to use when loading the\n\t// program.  If nil, it may be lazily initialized by any\n\t// method of Config.\n\tFset *token.FileSet\n\n\t// ParserMode specifies the mode to be used by the parser when\n\t// loading source packages.\n\tParserMode parser.Mode\n\n\t// TypeChecker contains options relating to the type checker.\n\t//\n\t// The supplied IgnoreFuncBodies is not used; the effective\n\t// value comes from the TypeCheckFuncBodies func below.\n\t// The supplied Import function is not used either.\n\tTypeChecker types.Config\n\n\t// TypeCheckFuncBodies is a predicate over package paths.\n\t// A package for which the predicate is false will\n\t// have its package-level declarations type checked, but not\n\t// its function bodies; this can be used to quickly load\n\t// dependencies from source.  If nil, all func bodies are type\n\t// checked.\n\tTypeCheckFuncBodies func(path string) bool\n\n\t// If Build is non-nil, it is used to locate source packages.\n\t// Otherwise &build.Default is used.\n\t//\n\t// By default, cgo is invoked to preprocess Go files that\n\t// import the fake package \"C\".  This behaviour can be\n\t// disabled by setting CGO_ENABLED=0 in the environment prior\n\t// to startup, or by setting Build.CgoEnabled=false.\n\tBuild *build.Context\n\n\t// The current directory, used for resolving relative package\n\t// references such as \"./go/loader\".  If empty, os.Getwd will be\n\t// used instead.\n\tCwd string\n\n\t// If DisplayPath is non-nil, it is used to transform each\n\t// file name obtained from Build.Import().  This can be used\n\t// to prevent a virtualized build.Config's file names from\n\t// leaking into the user interface.\n\tDisplayPath func(path string) string\n\n\t// If AllowErrors is true, Load will return a Program even\n\t// if some of the its packages contained I/O, parser or type\n\t// errors; such errors are accessible via PackageInfo.Errors.  If\n\t// false, Load will fail if any package had an error.\n\tAllowErrors bool\n\n\t// CreatePkgs specifies a list of non-importable initial\n\t// packages to create.  The resulting packages will appear in\n\t// the corresponding elements of the Program.Created slice.\n\tCreatePkgs []PkgSpec\n\n\t// ImportPkgs specifies a set of initial packages to load.\n\t// The map keys are package paths.\n\t//\n\t// The map value indicates whether to load tests.  If true, Load\n\t// will add and type-check two lists of files to the package:\n\t// non-test files followed by in-package *_test.go files.  In\n\t// addition, it will append the external test package (if any)\n\t// to Program.Created.\n\tImportPkgs map[string]bool\n\n\t// FindPackage is called during Load to create the build.Package\n\t// for a given import path from a given directory.\n\t// If FindPackage is nil, (*build.Context).Import is used.\n\t// A client may use this hook to adapt to a proprietary build\n\t// system that does not follow the \"go build\" layout\n\t// conventions, for example.\n\t//\n\t// It must be safe to call concurrently from multiple goroutines.\n\tFindPackage func(ctxt *build.Context, importPath, fromDir string, mode build.ImportMode) (*build.Package, error)\n\n\t// AfterTypeCheck is called immediately after a list of files\n\t// has been type-checked and appended to info.Files.\n\t//\n\t// This optional hook function is the earliest opportunity for\n\t// the client to observe the output of the type checker,\n\t// which may be useful to reduce analysis latency when loading\n\t// a large program.\n\t//\n\t// The function is permitted to modify info.Info, for instance\n\t// to clear data structures that are no longer needed, which can\n\t// dramatically reduce peak memory consumption.\n\t//\n\t// The function may be called twice for the same PackageInfo:\n\t// once for the files of the package and again for the\n\t// in-package test files.\n\t//\n\t// It must be safe to call concurrently from multiple goroutines.\n\tAfterTypeCheck func(info *PackageInfo, files []*ast.File)\n}\n\n// A PkgSpec specifies a non-importable package to be created by Load.\n// Files are processed first, but typically only one of Files and\n// Filenames is provided.  The path needn't be globally unique.\n//\n// For vendoring purposes, the package's directory is the one that\n// contains the first file.\ntype PkgSpec struct {\n\tPath      string      // package path (\"\" => use package declaration)\n\tFiles     []*ast.File // ASTs of already-parsed files\n\tFilenames []string    // names of files to be parsed\n}\n\n// A Program is a Go program loaded from source as specified by a Config.\ntype Program struct {\n\tFset *token.FileSet // the file set for this program\n\n\t// Created[i] contains the initial package whose ASTs or\n\t// filenames were supplied by Config.CreatePkgs[i], followed by\n\t// the external test package, if any, of each package in\n\t// Config.ImportPkgs ordered by ImportPath.\n\t//\n\t// NOTE: these files must not import \"C\".  Cgo preprocessing is\n\t// only performed on imported packages, not ad hoc packages.\n\t//\n\t// TODO(adonovan): we need to copy and adapt the logic of\n\t// goFilesPackage (from $GOROOT/src/cmd/go/build.go) and make\n\t// Config.Import and Config.Create methods return the same kind\n\t// of entity, essentially a build.Package.\n\t// Perhaps we can even reuse that type directly.\n\tCreated []*PackageInfo\n\n\t// Imported contains the initially imported packages,\n\t// as specified by Config.ImportPkgs.\n\tImported map[string]*PackageInfo\n\n\t// AllPackages contains the PackageInfo of every package\n\t// encountered by Load: all initial packages and all\n\t// dependencies, including incomplete ones.\n\tAllPackages map[*types.Package]*PackageInfo\n\n\t// importMap is the canonical mapping of package paths to\n\t// packages.  It contains all Imported initial packages, but not\n\t// Created ones, and all imported dependencies.\n\timportMap map[string]*types.Package\n}\n\n// PackageInfo holds the ASTs and facts derived by the type-checker\n// for a single package.\n//\n// Not mutated once exposed via the API.\ntype PackageInfo struct {\n\tPkg                   *types.Package\n\tImportable            bool        // true if 'import \"Pkg.Path()\"' would resolve to this\n\tTransitivelyErrorFree bool        // true if Pkg and all its dependencies are free of errors\n\tFiles                 []*ast.File // syntax trees for the package's files\n\tErrors                []error     // non-nil if the package had errors\n\ttypes.Info                        // type-checker deductions.\n\tdir                   string      // package directory\n\n\tchecker   *types.Checker // transient type-checker state\n\terrorFunc func(error)\n}\n\nfunc (info *PackageInfo) String() string { return info.Pkg.Path() }\n\nfunc (info *PackageInfo) appendError(err error) {\n\tif info.errorFunc != nil {\n\t\tinfo.errorFunc(err)\n\t} else {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t}\n\tinfo.Errors = append(info.Errors, err)\n}\n\nfunc (conf *Config) fset() *token.FileSet {\n\tif conf.Fset == nil {\n\t\tconf.Fset = token.NewFileSet()\n\t}\n\treturn conf.Fset\n}\n\n// ParseFile is a convenience function (intended for testing) that invokes\n// the parser using the Config's FileSet, which is initialized if nil.\n//\n// src specifies the parser input as a string, []byte, or io.Reader, and\n// filename is its apparent name.  If src is nil, the contents of\n// filename are read from the file system.\nfunc (conf *Config) ParseFile(filename string, src any) (*ast.File, error) {\n\t// TODO(adonovan): use conf.build() etc like parseFiles does.\n\treturn parser.ParseFile(conf.fset(), filename, src, conf.ParserMode)\n}\n\n// FromArgsUsage is a partial usage message that applications calling\n// FromArgs may wish to include in their -help output.\nconst FromArgsUsage = `\n<args> is a list of arguments denoting a set of initial packages.\nIt may take one of two forms:\n\n1. A list of *.go source files.\n\n   All of the specified files are loaded, parsed and type-checked\n   as a single package.  All the files must belong to the same directory.\n\n2. A list of import paths, each denoting a package.\n\n   The package's directory is found relative to the $GOROOT and\n   $GOPATH using similar logic to 'go build', and the *.go files in\n   that directory are loaded, parsed and type-checked as a single\n   package.\n\n   In addition, all *_test.go files in the directory are then loaded\n   and parsed.  Those files whose package declaration equals that of\n   the non-*_test.go files are included in the primary package.  Test\n   files whose package declaration ends with \"_test\" are type-checked\n   as another package, the 'external' test package, so that a single\n   import path may denote two packages.  (Whether this behaviour is\n   enabled is tool-specific, and may depend on additional flags.)\n\nA '--' argument terminates the list of packages.\n`\n\n// FromArgs interprets args as a set of initial packages to load from\n// source and updates the configuration.  It returns the list of\n// unconsumed arguments.\n//\n// It is intended for use in command-line interfaces that require a\n// set of initial packages to be specified; see FromArgsUsage message\n// for details.\n//\n// Only superficial errors are reported at this stage; errors dependent\n// on I/O are detected during Load.\nfunc (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) {\n\tvar rest []string\n\tfor i, arg := range args {\n\t\tif arg == \"--\" {\n\t\t\trest = args[i+1:]\n\t\t\targs = args[:i]\n\t\t\tbreak // consume \"--\" and return the remaining args\n\t\t}\n\t}\n\n\tif len(args) > 0 && strings.HasSuffix(args[0], \".go\") {\n\t\t// Assume args is a list of a *.go files\n\t\t// denoting a single ad hoc package.\n\t\tfor _, arg := range args {\n\t\t\tif !strings.HasSuffix(arg, \".go\") {\n\t\t\t\treturn nil, fmt.Errorf(\"named files must be .go files: %s\", arg)\n\t\t\t}\n\t\t}\n\t\tconf.CreateFromFilenames(\"\", args...)\n\t} else {\n\t\t// Assume args are directories each denoting a\n\t\t// package and (perhaps) an external test, iff xtest.\n\t\tfor _, arg := range args {\n\t\t\tif xtest {\n\t\t\t\tconf.ImportWithTests(arg)\n\t\t\t} else {\n\t\t\t\tconf.Import(arg)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn rest, nil\n}\n\n// CreateFromFilenames is a convenience function that adds\n// a conf.CreatePkgs entry to create a package of the specified *.go\n// files.\nfunc (conf *Config) CreateFromFilenames(path string, filenames ...string) {\n\tconf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames})\n}\n\n// CreateFromFiles is a convenience function that adds a conf.CreatePkgs\n// entry to create package of the specified path and parsed files.\nfunc (conf *Config) CreateFromFiles(path string, files ...*ast.File) {\n\tconf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files})\n}\n\n// ImportWithTests is a convenience function that adds path to\n// ImportPkgs, the set of initial source packages located relative to\n// $GOPATH.  The package will be augmented by any *_test.go files in\n// its directory that contain a \"package x\" (not \"package x_test\")\n// declaration.\n//\n// In addition, if any *_test.go files contain a \"package x_test\"\n// declaration, an additional package comprising just those files will\n// be added to CreatePkgs.\nfunc (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) }\n\n// Import is a convenience function that adds path to ImportPkgs, the\n// set of initial packages that will be imported from source.\nfunc (conf *Config) Import(path string) { conf.addImport(path, false) }\n\nfunc (conf *Config) addImport(path string, tests bool) {\n\tif path == \"C\" {\n\t\treturn // ignore; not a real package\n\t}\n\tif conf.ImportPkgs == nil {\n\t\tconf.ImportPkgs = make(map[string]bool)\n\t}\n\tconf.ImportPkgs[path] = conf.ImportPkgs[path] || tests\n}\n\n// PathEnclosingInterval returns the PackageInfo and ast.Node that\n// contain source interval [start, end), and all the node's ancestors\n// up to the AST root.  It searches all ast.Files of all packages in prog.\n// exact is defined as for astutil.PathEnclosingInterval.\n//\n// The zero value is returned if not found.\nfunc (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {\n\tfor _, info := range prog.AllPackages {\n\t\tfor _, f := range info.Files {\n\t\t\tif !tokenFileContainsPos(prog.Fset.File(f.FileStart), start) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {\n\t\t\t\treturn info, path, exact\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil, false\n}\n\n// InitialPackages returns a new slice containing the set of initial\n// packages (Created + Imported) in unspecified order.\nfunc (prog *Program) InitialPackages() []*PackageInfo {\n\tinfos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported))\n\tinfos = append(infos, prog.Created...)\n\tfor _, info := range prog.Imported {\n\t\tinfos = append(infos, info)\n\t}\n\treturn infos\n}\n\n// Package returns the ASTs and results of type checking for the\n// specified package.\nfunc (prog *Program) Package(path string) *PackageInfo {\n\tif info, ok := prog.AllPackages[prog.importMap[path]]; ok {\n\t\treturn info\n\t}\n\tfor _, info := range prog.Created {\n\t\tif path == info.Pkg.Path() {\n\t\t\treturn info\n\t\t}\n\t}\n\treturn nil\n}\n\n// ---------- Implementation ----------\n\n// importer holds the working state of the algorithm.\ntype importer struct {\n\tconf  *Config   // the client configuration\n\tstart time.Time // for logging\n\n\tprogMu sync.Mutex // guards prog\n\tprog   *Program   // the resulting program\n\n\t// findpkg is a memoization of FindPackage.\n\tfindpkgMu sync.Mutex // guards findpkg\n\tfindpkg   map[findpkgKey]*findpkgValue\n\n\timportedMu sync.Mutex             // guards imported\n\timported   map[string]*importInfo // all imported packages (incl. failures) by import path\n\n\t// import dependency graph: graph[x][y] => x imports y\n\t//\n\t// Since non-importable packages cannot be cyclic, we ignore\n\t// their imports, thus we only need the subgraph over importable\n\t// packages.  Nodes are identified by their import paths.\n\tgraphMu sync.Mutex\n\tgraph   map[string]map[string]bool\n}\n\ntype findpkgKey struct {\n\timportPath string\n\tfromDir    string\n\tmode       build.ImportMode\n}\n\ntype findpkgValue struct {\n\tready chan struct{} // closed to broadcast readiness\n\tbp    *build.Package\n\terr   error\n}\n\n// importInfo tracks the success or failure of a single import.\n//\n// Upon completion, exactly one of info and err is non-nil:\n// info on successful creation of a package, err otherwise.\n// A successful package may still contain type errors.\ntype importInfo struct {\n\tpath     string        // import path\n\tinfo     *PackageInfo  // results of typechecking (including errors)\n\tcomplete chan struct{} // closed to broadcast that info is set.\n}\n\n// awaitCompletion blocks until ii is complete,\n// i.e. the info field is safe to inspect.\nfunc (ii *importInfo) awaitCompletion() {\n\t<-ii.complete // wait for close\n}\n\n// Complete marks ii as complete.\n// Its info and err fields will not be subsequently updated.\nfunc (ii *importInfo) Complete(info *PackageInfo) {\n\tif info == nil {\n\t\tpanic(\"info == nil\")\n\t}\n\tii.info = info\n\tclose(ii.complete)\n}\n\ntype importError struct {\n\tpath string // import path\n\terr  error  // reason for failure to create a package\n}\n\n// Load creates the initial packages specified by conf.{Create,Import}Pkgs,\n// loading their dependencies packages as needed.\n//\n// On success, Load returns a Program containing a PackageInfo for\n// each package.  On failure, it returns an error.\n//\n// If AllowErrors is true, Load will return a Program even if some\n// packages contained I/O, parser or type errors, or if dependencies\n// were missing.  (Such errors are accessible via PackageInfo.Errors.  If\n// false, Load will fail if any package had an error.\n//\n// It is an error if no packages were loaded.\nfunc (conf *Config) Load() (*Program, error) {\n\t// Create a simple default error handler for parse/type errors.\n\tif conf.TypeChecker.Error == nil {\n\t\tconf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }\n\t}\n\n\t// Set default working directory for relative package references.\n\tif conf.Cwd == \"\" {\n\t\tvar err error\n\t\tconf.Cwd, err = os.Getwd()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Install default FindPackage hook using go/build logic.\n\tif conf.FindPackage == nil {\n\t\tconf.FindPackage = (*build.Context).Import\n\t}\n\n\tprog := &Program{\n\t\tFset:        conf.fset(),\n\t\tImported:    make(map[string]*PackageInfo),\n\t\timportMap:   make(map[string]*types.Package),\n\t\tAllPackages: make(map[*types.Package]*PackageInfo),\n\t}\n\n\timp := importer{\n\t\tconf:     conf,\n\t\tprog:     prog,\n\t\tfindpkg:  make(map[findpkgKey]*findpkgValue),\n\t\timported: make(map[string]*importInfo),\n\t\tstart:    time.Now(),\n\t\tgraph:    make(map[string]map[string]bool),\n\t}\n\n\t// -- loading proper (concurrent phase) --------------------------------\n\n\tvar errpkgs []string // packages that contained errors\n\n\t// Load the initially imported packages and their dependencies,\n\t// in parallel.\n\t// No vendor check on packages imported from the command line.\n\tinfos, importErrors := imp.importAll(\"\", conf.Cwd, conf.ImportPkgs, ignoreVendor)\n\tfor _, ie := range importErrors {\n\t\tconf.TypeChecker.Error(ie.err) // failed to create package\n\t\terrpkgs = append(errpkgs, ie.path)\n\t}\n\tfor _, info := range infos {\n\t\tprog.Imported[info.Pkg.Path()] = info\n\t}\n\n\t// Augment the designated initial packages by their tests.\n\t// Dependencies are loaded in parallel.\n\tvar xtestPkgs []*build.Package\n\tfor importPath, augment := range conf.ImportPkgs {\n\t\tif !augment {\n\t\t\tcontinue\n\t\t}\n\n\t\t// No vendor check on packages imported from command line.\n\t\tbp, err := imp.findPackage(importPath, conf.Cwd, ignoreVendor)\n\t\tif err != nil {\n\t\t\t// Package not found, or can't even parse package declaration.\n\t\t\t// Already reported by previous loop; ignore it.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Needs external test package?\n\t\tif len(bp.XTestGoFiles) > 0 {\n\t\t\txtestPkgs = append(xtestPkgs, bp)\n\t\t}\n\n\t\t// Consult the cache using the canonical package path.\n\t\tpath := bp.ImportPath\n\t\timp.importedMu.Lock() // (unnecessary, we're sequential here)\n\t\tii, ok := imp.imported[path]\n\t\t// Paranoid checks added due to issue #11012.\n\t\tif !ok {\n\t\t\t// Unreachable.\n\t\t\t// The previous loop called importAll and thus\n\t\t\t// startLoad for each path in ImportPkgs, which\n\t\t\t// populates imp.imported[path] with a non-zero value.\n\t\t\tpanic(fmt.Sprintf(\"imported[%q] not found\", path))\n\t\t}\n\t\tif ii == nil {\n\t\t\t// Unreachable.\n\t\t\t// The ii values in this loop are the same as in\n\t\t\t// the previous loop, which enforced the invariant\n\t\t\t// that at least one of ii.err and ii.info is non-nil.\n\t\t\tpanic(fmt.Sprintf(\"imported[%q] == nil\", path))\n\t\t}\n\t\tif ii.info == nil {\n\t\t\t// Unreachable.\n\t\t\t// awaitCompletion has the postcondition\n\t\t\t// ii.info != nil.\n\t\t\tpanic(fmt.Sprintf(\"imported[%q].info = nil\", path))\n\t\t}\n\t\tinfo := ii.info\n\t\timp.importedMu.Unlock()\n\n\t\t// Parse the in-package test files.\n\t\tfiles, errs := imp.conf.parsePackageFiles(bp, 't')\n\t\tfor _, err := range errs {\n\t\t\tinfo.appendError(err)\n\t\t}\n\n\t\t// The test files augmenting package P cannot be imported,\n\t\t// but may import packages that import P,\n\t\t// so we must disable the cycle check.\n\t\timp.addFiles(info, files, false)\n\t}\n\n\tcreatePkg := func(path, dir string, files []*ast.File, errs []error) {\n\t\tinfo := imp.newPackageInfo(path, dir)\n\t\tfor _, err := range errs {\n\t\t\tinfo.appendError(err)\n\t\t}\n\n\t\t// Ad hoc packages are non-importable,\n\t\t// so no cycle check is needed.\n\t\t// addFiles loads dependencies in parallel.\n\t\timp.addFiles(info, files, false)\n\t\tprog.Created = append(prog.Created, info)\n\t}\n\n\t// Create packages specified by conf.CreatePkgs.\n\tfor _, cp := range conf.CreatePkgs {\n\t\tfiles, errs := parseFiles(conf.fset(), conf.build(), nil, conf.Cwd, cp.Filenames, conf.ParserMode)\n\t\tfiles = append(files, cp.Files...)\n\n\t\tpath := cp.Path\n\t\tif path == \"\" {\n\t\t\tif len(files) > 0 {\n\t\t\t\tpath = files[0].Name.Name\n\t\t\t} else {\n\t\t\t\tpath = \"(unnamed)\"\n\t\t\t}\n\t\t}\n\n\t\tdir := conf.Cwd\n\t\tif len(files) > 0 && files[0].Pos().IsValid() {\n\t\t\tdir = filepath.Dir(conf.fset().File(files[0].Pos()).Name())\n\t\t}\n\t\tcreatePkg(path, dir, files, errs)\n\t}\n\n\t// Create external test packages.\n\tsort.Sort(byImportPath(xtestPkgs))\n\tfor _, bp := range xtestPkgs {\n\t\tfiles, errs := imp.conf.parsePackageFiles(bp, 'x')\n\t\tcreatePkg(bp.ImportPath+\"_test\", bp.Dir, files, errs)\n\t}\n\n\t// -- finishing up (sequential) ----------------------------------------\n\n\tif len(prog.Imported)+len(prog.Created) == 0 {\n\t\treturn nil, errors.New(\"no initial packages were loaded\")\n\t}\n\n\t// Create infos for indirectly imported packages.\n\t// e.g. incomplete packages without syntax, loaded from export data.\n\tfor _, obj := range prog.importMap {\n\t\tinfo := prog.AllPackages[obj]\n\t\tif info == nil {\n\t\t\tprog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true}\n\t\t} else {\n\t\t\t// finished\n\t\t\tinfo.checker = nil\n\t\t\tinfo.errorFunc = nil\n\t\t}\n\t}\n\n\tif !conf.AllowErrors {\n\t\t// Report errors in indirectly imported packages.\n\t\tfor _, info := range prog.AllPackages {\n\t\t\tif len(info.Errors) > 0 {\n\t\t\t\terrpkgs = append(errpkgs, info.Pkg.Path())\n\t\t\t}\n\t\t}\n\t\tif errpkgs != nil {\n\t\t\tvar more string\n\t\t\tif len(errpkgs) > 3 {\n\t\t\t\tmore = fmt.Sprintf(\" and %d more\", len(errpkgs)-3)\n\t\t\t\terrpkgs = errpkgs[:3]\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"couldn't load packages due to errors: %s%s\",\n\t\t\t\tstrings.Join(errpkgs, \", \"), more)\n\t\t}\n\t}\n\n\tmarkErrorFreePackages(prog.AllPackages)\n\n\treturn prog, nil\n}\n\ntype byImportPath []*build.Package\n\nfunc (b byImportPath) Len() int           { return len(b) }\nfunc (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath }\nfunc (b byImportPath) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }\n\n// markErrorFreePackages sets the TransitivelyErrorFree flag on all\n// applicable packages.\nfunc markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) {\n\t// Build the transpose of the import graph.\n\timportedBy := make(map[*types.Package]map[*types.Package]bool)\n\tfor P := range allPackages {\n\t\tfor _, Q := range P.Imports() {\n\t\t\tclients, ok := importedBy[Q]\n\t\t\tif !ok {\n\t\t\t\tclients = make(map[*types.Package]bool)\n\t\t\t\timportedBy[Q] = clients\n\t\t\t}\n\t\t\tclients[P] = true\n\t\t}\n\t}\n\n\t// Find all packages reachable from some error package.\n\treachable := make(map[*types.Package]bool)\n\tvar visit func(*types.Package)\n\tvisit = func(p *types.Package) {\n\t\tif !reachable[p] {\n\t\t\treachable[p] = true\n\t\t\tfor q := range importedBy[p] {\n\t\t\t\tvisit(q)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, info := range allPackages {\n\t\tif len(info.Errors) > 0 {\n\t\t\tvisit(info.Pkg)\n\t\t}\n\t}\n\n\t// Mark the others as \"transitively error-free\".\n\tfor _, info := range allPackages {\n\t\tif !reachable[info.Pkg] {\n\t\t\tinfo.TransitivelyErrorFree = true\n\t\t}\n\t}\n}\n\n// build returns the effective build context.\nfunc (conf *Config) build() *build.Context {\n\tif conf.Build != nil {\n\t\treturn conf.Build\n\t}\n\treturn &build.Default\n}\n\n// parsePackageFiles enumerates the files belonging to package path,\n// then loads, parses and returns them, plus a list of I/O or parse\n// errors that were encountered.\n//\n// 'which' indicates which files to include:\n//\n//\t'g': include non-test *.go source files (GoFiles + processed CgoFiles)\n//\t't': include in-package *_test.go source files (TestGoFiles)\n//\t'x': include external *_test.go source files. (XTestGoFiles)\nfunc (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {\n\tif bp.ImportPath == \"unsafe\" {\n\t\treturn nil, nil\n\t}\n\tvar filenames []string\n\tswitch which {\n\tcase 'g':\n\t\tfilenames = bp.GoFiles\n\tcase 't':\n\t\tfilenames = bp.TestGoFiles\n\tcase 'x':\n\t\tfilenames = bp.XTestGoFiles\n\tdefault:\n\t\tpanic(which)\n\t}\n\n\tfiles, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode)\n\n\t// Preprocess CgoFiles and parse the outputs (sequentially).\n\tif which == 'g' && bp.CgoFiles != nil {\n\t\tcgofiles, err := cgo.ProcessFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)\n\t\tif err != nil {\n\t\t\terrs = append(errs, err)\n\t\t} else {\n\t\t\tfiles = append(files, cgofiles...)\n\t\t}\n\t}\n\n\treturn files, errs\n}\n\n// doImport imports the package denoted by path.\n// It implements the types.Importer signature.\n//\n// It returns an error if a package could not be created\n// (e.g. go/build or parse error), but type errors are reported via\n// the types.Config.Error callback (the first of which is also saved\n// in the package's PackageInfo).\n//\n// Idempotent.\nfunc (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {\n\tif to == \"C\" {\n\t\t// This should be unreachable, but ad hoc packages are\n\t\t// not currently subject to cgo preprocessing.\n\t\t// See https://golang.org/issue/11627.\n\t\treturn nil, fmt.Errorf(`the loader doesn't cgo-process ad hoc packages like %q; see Go issue 11627`,\n\t\t\tfrom.Pkg.Path())\n\t}\n\n\tbp, err := imp.findPackage(to, from.dir, 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// The standard unsafe package is handled specially,\n\t// and has no PackageInfo.\n\tif bp.ImportPath == \"unsafe\" {\n\t\treturn types.Unsafe, nil\n\t}\n\n\t// Look for the package in the cache using its canonical path.\n\tpath := bp.ImportPath\n\timp.importedMu.Lock()\n\tii := imp.imported[path]\n\timp.importedMu.Unlock()\n\tif ii == nil {\n\t\tpanic(\"internal error: unexpected import: \" + path)\n\t}\n\tif ii.info != nil {\n\t\treturn ii.info.Pkg, nil\n\t}\n\n\t// Import of incomplete package: this indicates a cycle.\n\tfromPath := from.Pkg.Path()\n\tif cycle := imp.findPath(path, fromPath); cycle != nil {\n\t\t// Normalize cycle: start from alphabetically largest node.\n\t\tpos, start := -1, \"\"\n\t\tfor i, s := range cycle {\n\t\t\tif pos < 0 || s > start {\n\t\t\t\tpos, start = i, s\n\t\t\t}\n\t\t}\n\t\tcycle = append(cycle, cycle[:pos]...)[pos:] // rotate cycle to start from largest\n\t\tcycle = append(cycle, cycle[0])             // add start node to end to show cycliness\n\t\treturn nil, fmt.Errorf(\"import cycle: %s\", strings.Join(cycle, \" -> \"))\n\t}\n\n\tpanic(\"internal error: import of incomplete (yet acyclic) package: \" + fromPath)\n}\n\n// findPackage locates the package denoted by the importPath in the\n// specified directory.\nfunc (imp *importer) findPackage(importPath, fromDir string, mode build.ImportMode) (*build.Package, error) {\n\t// We use a non-blocking duplicate-suppressing cache (gopl.io §9.7)\n\t// to avoid holding the lock around FindPackage.\n\tkey := findpkgKey{importPath, fromDir, mode}\n\timp.findpkgMu.Lock()\n\tv, ok := imp.findpkg[key]\n\tif ok {\n\t\t// cache hit\n\t\timp.findpkgMu.Unlock()\n\n\t\t<-v.ready // wait for entry to become ready\n\t} else {\n\t\t// Cache miss: this goroutine becomes responsible for\n\t\t// populating the map entry and broadcasting its readiness.\n\t\tv = &findpkgValue{ready: make(chan struct{})}\n\t\timp.findpkg[key] = v\n\t\timp.findpkgMu.Unlock()\n\n\t\tioLimit <- true\n\t\tv.bp, v.err = imp.conf.FindPackage(imp.conf.build(), importPath, fromDir, mode)\n\t\t<-ioLimit\n\n\t\tif _, ok := v.err.(*build.NoGoError); ok {\n\t\t\tv.err = nil // empty directory is not an error\n\t\t}\n\n\t\tclose(v.ready) // broadcast ready condition\n\t}\n\treturn v.bp, v.err\n}\n\n// importAll loads, parses, and type-checks the specified packages in\n// parallel and returns their completed importInfos in unspecified order.\n//\n// fromPath is the package path of the importing package, if it is\n// importable, \"\" otherwise.  It is used for cycle detection.\n//\n// fromDir is the directory containing the import declaration that\n// caused these imports.\nfunc (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) {\n\tif fromPath != \"\" {\n\t\t// We're loading a set of imports.\n\t\t//\n\t\t// We must record graph edges from the importing package\n\t\t// to its dependencies, and check for cycles.\n\t\timp.graphMu.Lock()\n\t\tdeps, ok := imp.graph[fromPath]\n\t\tif !ok {\n\t\t\tdeps = make(map[string]bool)\n\t\t\timp.graph[fromPath] = deps\n\t\t}\n\t\tfor importPath := range imports {\n\t\t\tdeps[importPath] = true\n\t\t}\n\t\timp.graphMu.Unlock()\n\t}\n\n\tvar pending []*importInfo\n\tfor importPath := range imports {\n\t\tif fromPath != \"\" {\n\t\t\tif cycle := imp.findPath(importPath, fromPath); cycle != nil {\n\t\t\t\t// Cycle-forming import: we must not check it\n\t\t\t\t// since it would deadlock.\n\t\t\t\tif trace {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"import cycle: %q\\n\", cycle)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tbp, err := imp.findPackage(importPath, fromDir, mode)\n\t\tif err != nil {\n\t\t\terrors = append(errors, importError{\n\t\t\t\tpath: importPath,\n\t\t\t\terr:  err,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tpending = append(pending, imp.startLoad(bp))\n\t}\n\n\tfor _, ii := range pending {\n\t\tii.awaitCompletion()\n\t\tinfos = append(infos, ii.info)\n\t}\n\n\treturn infos, errors\n}\n\n// findPath returns an arbitrary path from 'from' to 'to' in the import\n// graph, or nil if there was none.\nfunc (imp *importer) findPath(from, to string) []string {\n\timp.graphMu.Lock()\n\tdefer imp.graphMu.Unlock()\n\n\tseen := make(map[string]bool)\n\tvar search func(stack []string, importPath string) []string\n\tsearch = func(stack []string, importPath string) []string {\n\t\tif !seen[importPath] {\n\t\t\tseen[importPath] = true\n\t\t\tstack = append(stack, importPath)\n\t\t\tif importPath == to {\n\t\t\t\treturn stack\n\t\t\t}\n\t\t\tfor x := range imp.graph[importPath] {\n\t\t\t\tif p := search(stack, x); p != nil {\n\t\t\t\t\treturn p\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn search(make([]string, 0, 20), from)\n}\n\n// startLoad initiates the loading, parsing and type-checking of the\n// specified package and its dependencies, if it has not already begun.\n//\n// It returns an importInfo, not necessarily in a completed state.  The\n// caller must call awaitCompletion() before accessing its info field.\n//\n// startLoad is concurrency-safe and idempotent.\nfunc (imp *importer) startLoad(bp *build.Package) *importInfo {\n\tpath := bp.ImportPath\n\timp.importedMu.Lock()\n\tii, ok := imp.imported[path]\n\tif !ok {\n\t\tii = &importInfo{path: path, complete: make(chan struct{})}\n\t\timp.imported[path] = ii\n\t\tgo func() {\n\t\t\tinfo := imp.load(bp)\n\t\t\tii.Complete(info)\n\t\t}()\n\t}\n\timp.importedMu.Unlock()\n\n\treturn ii\n}\n\n// load implements package loading by parsing Go source files\n// located by go/build.\nfunc (imp *importer) load(bp *build.Package) *PackageInfo {\n\tinfo := imp.newPackageInfo(bp.ImportPath, bp.Dir)\n\tinfo.Importable = true\n\tfiles, errs := imp.conf.parsePackageFiles(bp, 'g')\n\tfor _, err := range errs {\n\t\tinfo.appendError(err)\n\t}\n\n\timp.addFiles(info, files, true)\n\n\timp.progMu.Lock()\n\timp.prog.importMap[bp.ImportPath] = info.Pkg\n\timp.progMu.Unlock()\n\n\treturn info\n}\n\n// addFiles adds and type-checks the specified files to info, loading\n// their dependencies if needed.  The order of files determines the\n// package initialization order.  It may be called multiple times on the\n// same package.  Errors are appended to the info.Errors field.\n//\n// cycleCheck determines whether the imports within files create\n// dependency edges that should be checked for potential cycles.\nfunc (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) {\n\t// Ensure the dependencies are loaded, in parallel.\n\tvar fromPath string\n\tif cycleCheck {\n\t\tfromPath = info.Pkg.Path()\n\t}\n\t// TODO(adonovan): opt: make the caller do scanImports.\n\t// Callers with a build.Package can skip it.\n\timp.importAll(fromPath, info.dir, scanImports(files), 0)\n\n\tif trace {\n\t\tfmt.Fprintf(os.Stderr, \"%s: start %q (%d)\\n\",\n\t\t\ttime.Since(imp.start), info.Pkg.Path(), len(files))\n\t}\n\n\t// Don't call checker.Files on Unsafe, even with zero files,\n\t// because it would mutate the package, which is a global.\n\tif info.Pkg == types.Unsafe {\n\t\tif len(files) > 0 {\n\t\t\tpanic(`\"unsafe\" package contains unexpected files`)\n\t\t}\n\t} else {\n\t\t// Ignore the returned (first) error since we\n\t\t// already collect them all in the PackageInfo.\n\t\tinfo.checker.Files(files)\n\t\tinfo.Files = append(info.Files, files...)\n\t}\n\n\tif imp.conf.AfterTypeCheck != nil {\n\t\timp.conf.AfterTypeCheck(info, files)\n\t}\n\n\tif trace {\n\t\tfmt.Fprintf(os.Stderr, \"%s: stop %q\\n\",\n\t\t\ttime.Since(imp.start), info.Pkg.Path())\n\t}\n}\n\nfunc (imp *importer) newPackageInfo(path, dir string) *PackageInfo {\n\tvar pkg *types.Package\n\tif path == \"unsafe\" {\n\t\tpkg = types.Unsafe\n\t} else {\n\t\tpkg = types.NewPackage(path, \"\")\n\t}\n\tinfo := &PackageInfo{\n\t\tPkg: pkg,\n\t\tInfo: types.Info{\n\t\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t},\n\t\terrorFunc: imp.conf.TypeChecker.Error,\n\t\tdir:       dir,\n\t}\n\n\t// Copy the types.Config so we can vary it across PackageInfos.\n\ttc := imp.conf.TypeChecker\n\ttc.IgnoreFuncBodies = false\n\tif f := imp.conf.TypeCheckFuncBodies; f != nil {\n\t\ttc.IgnoreFuncBodies = !f(path)\n\t}\n\ttc.Importer = closure{imp, info}\n\ttc.Error = info.appendError // appendError wraps the user's Error function\n\n\tinfo.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)\n\timp.progMu.Lock()\n\timp.prog.AllPackages[pkg] = info\n\timp.progMu.Unlock()\n\treturn info\n}\n\ntype closure struct {\n\timp  *importer\n\tinfo *PackageInfo\n}\n\nfunc (c closure) Import(to string) (*types.Package, error) { return c.imp.doImport(c.info, to) }\n"
  },
  {
    "path": "go/loader/loader_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage loader_test\n\nimport (\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/constant\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\ttestenv.ExitIfSmallMachine()\n\tos.Exit(m.Run())\n}\n\n// TestFromArgs checks that conf.FromArgs populates conf correctly.\n// It does no I/O.\nfunc TestFromArgs(t *testing.T) {\n\ttype result struct {\n\t\tErr        string\n\t\tRest       []string\n\t\tImportPkgs map[string]bool\n\t\tCreatePkgs []loader.PkgSpec\n\t}\n\tfor _, test := range []struct {\n\t\targs  []string\n\t\ttests bool\n\t\twant  result\n\t}{\n\t\t// Mix of existing and non-existent packages.\n\t\t{\n\t\t\targs: []string{\"nosuchpkg\", \"errors\"},\n\t\t\twant: result{\n\t\t\t\tImportPkgs: map[string]bool{\"errors\": false, \"nosuchpkg\": false},\n\t\t\t},\n\t\t},\n\t\t// Same, with -test flag.\n\t\t{\n\t\t\targs:  []string{\"nosuchpkg\", \"errors\"},\n\t\t\ttests: true,\n\t\t\twant: result{\n\t\t\t\tImportPkgs: map[string]bool{\"errors\": true, \"nosuchpkg\": true},\n\t\t\t},\n\t\t},\n\t\t// Surplus arguments.\n\t\t{\n\t\t\targs: []string{\"fmt\", \"errors\", \"--\", \"surplus\"},\n\t\t\twant: result{\n\t\t\t\tRest:       []string{\"surplus\"},\n\t\t\t\tImportPkgs: map[string]bool{\"errors\": false, \"fmt\": false},\n\t\t\t},\n\t\t},\n\t\t// Ad hoc package specified as *.go files.\n\t\t{\n\t\t\targs: []string{\"foo.go\", \"bar.go\"},\n\t\t\twant: result{CreatePkgs: []loader.PkgSpec{{\n\t\t\t\tFilenames: []string{\"foo.go\", \"bar.go\"},\n\t\t\t}}},\n\t\t},\n\t\t// Mixture of *.go and import paths.\n\t\t{\n\t\t\targs: []string{\"foo.go\", \"fmt\"},\n\t\t\twant: result{\n\t\t\t\tErr: \"named files must be .go files: fmt\",\n\t\t\t},\n\t\t},\n\t} {\n\t\tvar conf loader.Config\n\t\trest, err := conf.FromArgs(test.args, test.tests)\n\t\tgot := result{\n\t\t\tRest:       rest,\n\t\t\tImportPkgs: conf.ImportPkgs,\n\t\t\tCreatePkgs: conf.CreatePkgs,\n\t\t}\n\t\tif err != nil {\n\t\t\tgot.Err = err.Error()\n\t\t}\n\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\tt.Errorf(\"FromArgs(%q) = %+v, want %+v\", test.args, got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestLoad_NoInitialPackages(t *testing.T) {\n\tvar conf loader.Config\n\n\tconst wantErr = \"no initial packages were loaded\"\n\n\tprog, err := conf.Load()\n\tif err == nil {\n\t\tt.Errorf(\"Load succeeded unexpectedly, want %q\", wantErr)\n\t} else if err.Error() != wantErr {\n\t\tt.Errorf(\"Load failed with wrong error %q, want %q\", err, wantErr)\n\t}\n\tif prog != nil {\n\t\tt.Errorf(\"Load unexpectedly returned a Program\")\n\t}\n}\n\nfunc TestLoad_MissingInitialPackage(t *testing.T) {\n\tif runtime.GOOS == \"wasip1\" {\n\t\tt.Skip(\"Skipping due to golang/go#64725: fails with EBADF errors\")\n\t}\n\n\tvar conf loader.Config\n\tconf.Import(\"nosuchpkg\")\n\tconf.Import(\"errors\")\n\n\tconst wantErr = \"couldn't load packages due to errors: nosuchpkg\"\n\n\tprog, err := conf.Load()\n\tif err == nil {\n\t\tt.Errorf(\"Load succeeded unexpectedly, want %q\", wantErr)\n\t} else if err.Error() != wantErr {\n\t\tt.Errorf(\"Load failed with wrong error %q, want %q\", err, wantErr)\n\t}\n\tif prog != nil {\n\t\tt.Errorf(\"Load unexpectedly returned a Program\")\n\t}\n}\n\nfunc TestLoad_MissingInitialPackage_AllowErrors(t *testing.T) {\n\tif runtime.Compiler == \"gccgo\" {\n\t\tt.Skip(\"gccgo has no standard library test files\")\n\t}\n\n\tvar conf loader.Config\n\tconf.AllowErrors = true\n\tconf.Import(\"nosuchpkg\")\n\tconf.ImportWithTests(\"errors\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed unexpectedly: %v\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned a nil Program\")\n\t}\n\tif got, want := created(prog), \"errors_test\"; got != want {\n\t\tt.Errorf(\"Created = %s, want %s\", got, want)\n\t}\n\tif got, want := imported(prog), \"errors\"; got != want {\n\t\tt.Errorf(\"Imported = %s, want %s\", got, want)\n\t}\n}\n\nfunc TestCreateUnnamedPackage(t *testing.T) {\n\tvar conf loader.Config\n\tconf.CreateFromFilenames(\"\")\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatalf(\"Load failed: %v\", err)\n\t}\n\tif got, want := fmt.Sprint(prog.InitialPackages()), \"[(unnamed)]\"; got != want {\n\t\tt.Errorf(\"InitialPackages = %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoad_MissingFileInCreatedPackage(t *testing.T) {\n\tvar conf loader.Config\n\tconf.CreateFromFilenames(\"\", \"missing.go\")\n\n\tconst wantErr = \"couldn't load packages due to errors: (unnamed)\"\n\n\tprog, err := conf.Load()\n\tif prog != nil {\n\t\tt.Errorf(\"Load unexpectedly returned a Program\")\n\t}\n\tif err == nil {\n\t\tt.Fatalf(\"Load succeeded unexpectedly, want %q\", wantErr)\n\t}\n\tif err.Error() != wantErr {\n\t\tt.Fatalf(\"Load failed with wrong error %q, want %q\", err, wantErr)\n\t}\n}\n\nfunc TestLoad_MissingFileInCreatedPackage_AllowErrors(t *testing.T) {\n\tconf := loader.Config{AllowErrors: true}\n\tconf.CreateFromFilenames(\"\", \"missing.go\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed: %v\", err)\n\t}\n\tif got, want := fmt.Sprint(prog.InitialPackages()), \"[(unnamed)]\"; got != want {\n\t\tt.Fatalf(\"InitialPackages = %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoad_ParseError(t *testing.T) {\n\tvar conf loader.Config\n\tconf.CreateFromFilenames(\"badpkg\", \"testdata/badpkgdecl.go\")\n\n\tconst wantErr = \"couldn't load packages due to errors: badpkg\"\n\n\tprog, err := conf.Load()\n\tif prog != nil {\n\t\tt.Errorf(\"Load unexpectedly returned a Program\")\n\t}\n\tif err == nil {\n\t\tt.Fatalf(\"Load succeeded unexpectedly, want %q\", wantErr)\n\t}\n\tif err.Error() != wantErr {\n\t\tt.Fatalf(\"Load failed with wrong error %q, want %q\", err, wantErr)\n\t}\n}\n\nfunc TestLoad_ParseError_AllowErrors(t *testing.T) {\n\tvar conf loader.Config\n\tconf.AllowErrors = true\n\tconf.CreateFromFilenames(\"badpkg\", \"testdata/badpkgdecl.go\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed unexpectedly: %v\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned a nil Program\")\n\t}\n\tif got, want := created(prog), \"badpkg\"; got != want {\n\t\tt.Errorf(\"Created = %s, want %s\", got, want)\n\t}\n\n\tbadpkg := prog.Created[0]\n\tif len(badpkg.Files) != 1 {\n\t\tt.Errorf(\"badpkg has %d files, want 1\", len(badpkg.Files))\n\t}\n\twantErr := filepath.Join(\"testdata\", \"badpkgdecl.go\") + \":1:34: expected 'package', found 'EOF'\"\n\tif !hasError(badpkg.Errors, wantErr) {\n\t\tt.Errorf(\"badpkg.Errors = %v, want %s\", badpkg.Errors, wantErr)\n\t}\n}\n\nfunc TestLoad_FromSource_Success(t *testing.T) {\n\tvar conf loader.Config\n\tconf.CreateFromFilenames(\"P\", \"testdata/a.go\", \"testdata/b.go\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed unexpectedly: %v\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned a nil Program\")\n\t}\n\tif got, want := created(prog), \"P\"; got != want {\n\t\tt.Errorf(\"Created = %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoad_FromImports_Success(t *testing.T) {\n\tif runtime.Compiler == \"gccgo\" {\n\t\tt.Skip(\"gccgo has no standard library test files\")\n\t}\n\n\tvar conf loader.Config\n\tconf.ImportWithTests(\"fmt\")\n\tconf.ImportWithTests(\"errors\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed unexpectedly: %v\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned a nil Program\")\n\t}\n\tif got, want := created(prog), \"errors_test fmt_test\"; got != want {\n\t\tt.Errorf(\"Created = %q, want %s\", got, want)\n\t}\n\tif got, want := imported(prog), \"errors fmt\"; got != want {\n\t\tt.Errorf(\"Imported = %s, want %s\", got, want)\n\t}\n\t// Check set of transitive packages.\n\t// There are >30 and the set may grow over time, so only check a few.\n\twant := map[string]bool{\n\t\t\"strings\": true,\n\t\t\"time\":    true,\n\t\t\"runtime\": true,\n\t\t\"testing\": true,\n\t\t\"unicode\": true,\n\t}\n\tfor _, path := range all(prog) {\n\t\tdelete(want, path)\n\t}\n\tif len(want) > 0 {\n\t\tt.Errorf(\"AllPackages is missing these keys: %q\", keys(want))\n\t}\n}\n\nfunc TestLoad_MissingIndirectImport(t *testing.T) {\n\tpkgs := map[string]string{\n\t\t\"a\": `package a; import _ \"b\"`,\n\t\t\"b\": `package b; import _ \"c\"`,\n\t}\n\tconf := loader.Config{Build: fakeContext(pkgs)}\n\tconf.Import(\"a\")\n\n\tconst wantErr = \"couldn't load packages due to errors: b\"\n\n\tprog, err := conf.Load()\n\tif err == nil {\n\t\tt.Errorf(\"Load succeeded unexpectedly, want %q\", wantErr)\n\t} else if err.Error() != wantErr {\n\t\tt.Errorf(\"Load failed with wrong error %q, want %q\", err, wantErr)\n\t}\n\tif prog != nil {\n\t\tt.Errorf(\"Load unexpectedly returned a Program\")\n\t}\n}\n\nfunc TestLoad_BadDependency_AllowErrors(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tdescr    string\n\t\tpkgs     map[string]string\n\t\twantPkgs string\n\t}{\n\n\t\t{\n\t\t\tdescr: \"missing dependency\",\n\t\t\tpkgs: map[string]string{\n\t\t\t\t\"a\": `package a; import _ \"b\"`,\n\t\t\t\t\"b\": `package b; import _ \"c\"`,\n\t\t\t},\n\t\t\twantPkgs: \"a b\",\n\t\t},\n\t\t{\n\t\t\tdescr: \"bad package decl in dependency\",\n\t\t\tpkgs: map[string]string{\n\t\t\t\t\"a\": `package a; import _ \"b\"`,\n\t\t\t\t\"b\": `package b; import _ \"c\"`,\n\t\t\t\t\"c\": `package`,\n\t\t\t},\n\t\t\twantPkgs: \"a b\",\n\t\t},\n\t\t{\n\t\t\tdescr: \"parse error in dependency\",\n\t\t\tpkgs: map[string]string{\n\t\t\t\t\"a\": `package a; import _ \"b\"`,\n\t\t\t\t\"b\": `package b; import _ \"c\"`,\n\t\t\t\t\"c\": `package c; var x = `,\n\t\t\t},\n\t\t\twantPkgs: \"a b c\",\n\t\t},\n\t} {\n\t\tconf := loader.Config{\n\t\t\tAllowErrors: true,\n\t\t\tBuild:       fakeContext(test.pkgs),\n\t\t}\n\t\tconf.Import(\"a\")\n\n\t\tprog, err := conf.Load()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: Load failed unexpectedly: %v\", test.descr, err)\n\t\t}\n\t\tif prog == nil {\n\t\t\tt.Fatalf(\"%s: Load returned a nil Program\", test.descr)\n\t\t}\n\n\t\tif got, want := imported(prog), \"a\"; got != want {\n\t\t\tt.Errorf(\"%s: Imported = %s, want %s\", test.descr, got, want)\n\t\t}\n\t\tif got := all(prog); strings.Join(got, \" \") != test.wantPkgs {\n\t\t\tt.Errorf(\"%s: AllPackages = %s, want %s\", test.descr, got, test.wantPkgs)\n\t\t}\n\t}\n}\n\nfunc TestCwd(t *testing.T) {\n\tctxt := fakeContext(map[string]string{\"one/two/three\": `package three`})\n\tfor _, test := range []struct {\n\t\tcwd, arg, want string\n\t}{\n\t\t{cwd: \"/go/src/one\", arg: \"./two/three\", want: \"one/two/three\"},\n\t\t{cwd: \"/go/src/one\", arg: \"../one/two/three\", want: \"one/two/three\"},\n\t\t{cwd: \"/go/src/one\", arg: \"one/two/three\", want: \"one/two/three\"},\n\t\t{cwd: \"/go/src/one/two/three\", arg: \".\", want: \"one/two/three\"},\n\t\t{cwd: \"/go/src/one\", arg: \"two/three\", want: \"\"},\n\t} {\n\t\tconf := loader.Config{\n\t\t\tCwd:   test.cwd,\n\t\t\tBuild: ctxt,\n\t\t}\n\t\tconf.Import(test.arg)\n\n\t\tvar got string\n\t\tprog, err := conf.Load()\n\t\tif prog != nil {\n\t\t\tgot = imported(prog)\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"Load(%s) from %s: Imported = %s, want %s\",\n\t\t\t\ttest.arg, test.cwd, got, test.want)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Load failed: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestLoad_vendor(t *testing.T) {\n\tpkgs := map[string]string{\n\t\t\"a\":          `package a; import _ \"x\"`,\n\t\t\"a/vendor\":   ``, // mkdir a/vendor\n\t\t\"a/vendor/x\": `package xa`,\n\t\t\"b\":          `package b; import _ \"x\"`,\n\t\t\"b/vendor\":   ``, // mkdir b/vendor\n\t\t\"b/vendor/x\": `package xb`,\n\t\t\"c\":          `package c; import _ \"x\"`,\n\t\t\"x\":          `package xc`,\n\t}\n\tconf := loader.Config{Build: fakeContext(pkgs)}\n\tconf.Import(\"a\")\n\tconf.Import(\"b\")\n\tconf.Import(\"c\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check that a, b, and c see different versions of x.\n\tfor _, r := range \"abc\" {\n\t\tname := string(r)\n\t\tgot := prog.Package(name).Pkg.Imports()[0]\n\t\twant := \"x\" + name\n\t\tif got.Name() != want {\n\t\t\tt.Errorf(\"package %s import %q = %s, want %s\",\n\t\t\t\tname, \"x\", got.Name(), want)\n\t\t}\n\t}\n}\n\nfunc TestVendorCwd(t *testing.T) {\n\t// Test the interaction of cwd and vendor directories.\n\tctxt := fakeContext(map[string]string{\n\t\t\"net\":          ``, // mkdir net\n\t\t\"net/http\":     `package http; import _ \"hpack\"`,\n\t\t\"vendor\":       ``, // mkdir vendor\n\t\t\"vendor/hpack\": `package vendorhpack`,\n\t\t\"hpack\":        `package hpack`,\n\t})\n\tfor i, test := range []struct {\n\t\tcwd, arg, want string\n\t}{\n\t\t{cwd: \"/go/src/net\", arg: \"http\"}, // not found\n\t\t{cwd: \"/go/src/net\", arg: \"./http\", want: \"net/http vendor/hpack\"},\n\t\t{cwd: \"/go/src/net\", arg: \"hpack\", want: \"vendor/hpack\"},\n\t\t{cwd: \"/go/src/vendor\", arg: \"hpack\", want: \"vendor/hpack\"},\n\t\t{cwd: \"/go/src/vendor\", arg: \"./hpack\", want: \"vendor/hpack\"},\n\t} {\n\t\tconf := loader.Config{\n\t\t\tCwd:   test.cwd,\n\t\t\tBuild: ctxt,\n\t\t}\n\t\tconf.Import(test.arg)\n\n\t\tvar got string\n\t\tprog, err := conf.Load()\n\t\tif prog != nil {\n\t\t\tgot = strings.Join(all(prog), \" \")\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"#%d: Load(%s) from %s: got %s, want %s\",\n\t\t\t\ti, test.arg, test.cwd, got, test.want)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Load failed: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestVendorCwdIssue16580(t *testing.T) {\n\t// Regression test for Go issue 16580.\n\t// Import decls in \"created\" packages were vendor-resolved\n\t// w.r.t. cwd, not the parent directory of the package's files.\n\tctxt := fakeContext(map[string]string{\n\t\t\"a\":          ``, // mkdir a\n\t\t\"a/vendor\":   ``, // mkdir a/vendor\n\t\t\"a/vendor/b\": `package b; const X = true`,\n\t\t\"b\":          `package b; const X = false`,\n\t})\n\tfor _, test := range []struct {\n\t\tfilename, cwd string\n\t\twant          bool // expected value of b.X; depends on filename, not on cwd\n\t}{\n\t\t{filename: \"c.go\", cwd: \"/go/src\", want: false},\n\t\t{filename: \"c.go\", cwd: \"/go/src/a\", want: false},\n\t\t{filename: \"c.go\", cwd: \"/go/src/a/b\", want: false},\n\t\t{filename: \"c.go\", cwd: \"/go/src/a/vendor/b\", want: false},\n\n\t\t{filename: \"/go/src/a/c.go\", cwd: \"/go/src\", want: true},\n\t\t{filename: \"/go/src/a/c.go\", cwd: \"/go/src/a\", want: true},\n\t\t{filename: \"/go/src/a/c.go\", cwd: \"/go/src/a/b\", want: true},\n\t\t{filename: \"/go/src/a/c.go\", cwd: \"/go/src/a/vendor/b\", want: true},\n\n\t\t{filename: \"/go/src/c/c.go\", cwd: \"/go/src\", want: false},\n\t\t{filename: \"/go/src/c/c.go\", cwd: \"/go/src/a\", want: false},\n\t\t{filename: \"/go/src/c/c.go\", cwd: \"/go/src/a/b\", want: false},\n\t\t{filename: \"/go/src/c/c.go\", cwd: \"/go/src/a/vendor/b\", want: false},\n\t} {\n\t\tconf := loader.Config{\n\t\t\tCwd:   test.cwd,\n\t\t\tBuild: ctxt,\n\t\t}\n\t\tf, err := conf.ParseFile(test.filename, `package dummy; import \"b\"; const X = b.X`)\n\t\tif err != nil {\n\t\t\tt.Fatal(f)\n\t\t}\n\t\tconf.CreateFromFiles(\"dummy\", f)\n\n\t\tprog, err := conf.Load()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%+v: Load failed: %v\", test, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tx := constant.BoolVal(prog.Created[0].Pkg.Scope().Lookup(\"X\").(*types.Const).Val())\n\t\tif x != test.want {\n\t\t\tt.Errorf(\"%+v: b.X = %t\", test, x)\n\t\t}\n\t}\n\n\t// TODO(adonovan): also test imports within XTestGoFiles.\n}\n\n// TODO(adonovan): more Load tests:\n//\n// failures:\n// - to parse package decl of *_test.go files\n// - to parse package decl of external *_test.go files\n// - to parse whole of *_test.go files\n// - to parse whole of external *_test.go files\n// - to open a *.go file during import scanning\n// - to import from binary\n\n// features:\n// - InitialPackages\n// - PackageCreated hook\n// - TypeCheckFuncBodies hook\n\nfunc TestTransitivelyErrorFreeFlag(t *testing.T) {\n\t// Create a minimal custom build.Context\n\t// that fakes the following packages:\n\t//\n\t// a --> b --> c!   c has an error\n\t//   \\              d and e are transitively error-free.\n\t//    e --> d\n\t//\n\t// Each package [a-e] consists of one file, x.go.\n\tpkgs := map[string]string{\n\t\t\"a\": `package a; import (_ \"b\"; _ \"e\")`,\n\t\t\"b\": `package b; import _ \"c\"`,\n\t\t\"c\": `package c; func f() { _ = int(false) }`, // type error within function body\n\t\t\"d\": `package d;`,\n\t\t\"e\": `package e; import _ \"d\"`,\n\t}\n\tconf := loader.Config{\n\t\tAllowErrors: true,\n\t\tBuild:       fakeContext(pkgs),\n\t}\n\tconf.Import(\"a\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed: %s\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned nil *Program\")\n\t}\n\n\tfor pkg, info := range prog.AllPackages {\n\t\tvar wantErr, wantTEF bool\n\t\tswitch pkg.Path() {\n\t\tcase \"a\", \"b\":\n\t\tcase \"c\":\n\t\t\twantErr = true\n\t\tcase \"d\", \"e\":\n\t\t\twantTEF = true\n\t\tdefault:\n\t\t\tt.Errorf(\"unexpected package: %q\", pkg.Path())\n\t\t\tcontinue\n\t\t}\n\n\t\tif (info.Errors != nil) != wantErr {\n\t\t\tif wantErr {\n\t\t\t\tt.Errorf(\"Package %q.Error = nil, want error\", pkg.Path())\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"Package %q has unexpected Errors: %v\",\n\t\t\t\t\tpkg.Path(), info.Errors)\n\t\t\t}\n\t\t}\n\n\t\tif info.TransitivelyErrorFree != wantTEF {\n\t\t\tt.Errorf(\"Package %q.TransitivelyErrorFree=%t, want %t\",\n\t\t\t\tpkg.Path(), info.TransitivelyErrorFree, wantTEF)\n\t\t}\n\t}\n}\n\n// Test that syntax (scan/parse), type, and loader errors are recorded\n// (in PackageInfo.Errors) and reported (via Config.TypeChecker.Error).\nfunc TestErrorReporting(t *testing.T) {\n\tpkgs := map[string]string{\n\t\t\"a\": `package a; import (_ \"b\"; _ \"c\"); var x int = false`,\n\t\t\"b\": `package b; 'syntax error!`,\n\t}\n\tconf := loader.Config{\n\t\tAllowErrors: true,\n\t\tBuild:       fakeContext(pkgs),\n\t}\n\tvar mu sync.Mutex\n\tvar allErrors []error\n\tconf.TypeChecker.Error = func(err error) {\n\t\tmu.Lock()\n\t\tallErrors = append(allErrors, err)\n\t\tmu.Unlock()\n\t}\n\tconf.Import(\"a\")\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Errorf(\"Load failed: %s\", err)\n\t}\n\tif prog == nil {\n\t\tt.Fatalf(\"Load returned nil *Program\")\n\t}\n\n\t// TODO(adonovan): test keys of ImportMap.\n\n\t// Check errors recorded in each PackageInfo.\n\tfor pkg, info := range prog.AllPackages {\n\t\tswitch pkg.Path() {\n\t\tcase \"a\":\n\t\t\t// The match below is unfortunately vague, because in go1.16 the error\n\t\t\t// message in go/types changed from \"cannot convert ...\" to \"cannot use\n\t\t\t// ... as ... in assignment\".\n\t\t\tif !hasError(info.Errors, \"cannot\") {\n\t\t\t\tt.Errorf(\"a.Errors = %v, want bool assignment (type) error\", info.Errors)\n\t\t\t}\n\t\t\tif !hasError(info.Errors, \"could not import c\") {\n\t\t\t\tt.Errorf(\"a.Errors = %v, want import (loader) error\", info.Errors)\n\t\t\t}\n\t\tcase \"b\":\n\t\t\tif !hasError(info.Errors, \"rune literal not terminated\") {\n\t\t\t\tt.Errorf(\"b.Errors = %v, want unterminated literal (syntax) error\", info.Errors)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check errors reported via error handler.\n\tif !hasError(allErrors, \"cannot\") ||\n\t\t!hasError(allErrors, \"rune literal not terminated\") ||\n\t\t!hasError(allErrors, \"could not import c\") {\n\t\tt.Errorf(\"allErrors = %v, want syntax, type and loader errors\", allErrors)\n\t}\n}\n\nfunc TestCycles(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tdescr   string\n\t\tctxt    *build.Context\n\t\twantErr string\n\t}{\n\t\t{\n\t\t\t\"self-cycle\",\n\t\t\tfakeContext(map[string]string{\n\t\t\t\t\"main\":      `package main; import _ \"selfcycle\"`,\n\t\t\t\t\"selfcycle\": `package selfcycle; import _ \"selfcycle\"`,\n\t\t\t}),\n\t\t\t`import cycle: selfcycle -> selfcycle`,\n\t\t},\n\t\t{\n\t\t\t\"three-package cycle\",\n\t\t\tfakeContext(map[string]string{\n\t\t\t\t\"main\": `package main; import _ \"a\"`,\n\t\t\t\t\"a\":    `package a; import _ \"b\"`,\n\t\t\t\t\"b\":    `package b; import _ \"c\"`,\n\t\t\t\t\"c\":    `package c; import _ \"a\"`,\n\t\t\t}),\n\t\t\t`import cycle: c -> a -> b -> c`,\n\t\t},\n\t\t{\n\t\t\t\"self-cycle in dependency of test file\",\n\t\t\tbuildutil.FakeContext(map[string]map[string]string{\n\t\t\t\t\"main\": {\n\t\t\t\t\t\"main.go\":      `package main`,\n\t\t\t\t\t\"main_test.go\": `package main; import _ \"a\"`,\n\t\t\t\t},\n\t\t\t\t\"a\": {\n\t\t\t\t\t\"a.go\": `package a; import _ \"a\"`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\t`import cycle: a -> a`,\n\t\t},\n\t\t// TODO(adonovan): fix: these fail\n\t\t// {\n\t\t// \t\"two-package cycle in dependency of test file\",\n\t\t// \tbuildutil.FakeContext(map[string]map[string]string{\n\t\t// \t\t\"main\": {\n\t\t// \t\t\t\"main.go\":      `package main`,\n\t\t// \t\t\t\"main_test.go\": `package main; import _ \"a\"`,\n\t\t// \t\t},\n\t\t// \t\t\"a\": {\n\t\t// \t\t\t\"a.go\": `package a; import _ \"main\"`,\n\t\t// \t\t},\n\t\t// \t}),\n\t\t// \t`import cycle: main -> a -> main`,\n\t\t// },\n\t\t// {\n\t\t// \t\"self-cycle in augmented package\",\n\t\t// \tbuildutil.FakeContext(map[string]map[string]string{\n\t\t// \t\t\"main\": {\n\t\t// \t\t\t\"main.go\":      `package main`,\n\t\t// \t\t\t\"main_test.go\": `package main; import _ \"main\"`,\n\t\t// \t\t},\n\t\t// \t}),\n\t\t// \t`import cycle: main -> main`,\n\t\t// },\n\t} {\n\t\tconf := loader.Config{\n\t\t\tAllowErrors: true,\n\t\t\tBuild:       test.ctxt,\n\t\t}\n\t\tvar mu sync.Mutex\n\t\tvar allErrors []error\n\t\tconf.TypeChecker.Error = func(err error) {\n\t\t\tmu.Lock()\n\t\t\tallErrors = append(allErrors, err)\n\t\t\tmu.Unlock()\n\t\t}\n\t\tconf.ImportWithTests(\"main\")\n\n\t\tprog, err := conf.Load()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: Load failed: %s\", test.descr, err)\n\t\t}\n\t\tif prog == nil {\n\t\t\tt.Fatalf(\"%s: Load returned nil *Program\", test.descr)\n\t\t}\n\n\t\tif !hasError(allErrors, test.wantErr) {\n\t\t\tt.Errorf(\"%s: Load() errors = %q, want %q\",\n\t\t\t\ttest.descr, allErrors, test.wantErr)\n\t\t}\n\t}\n\n\t// TODO(adonovan):\n\t// - Test that in a legal test cycle, none of the symbols\n\t//   defined by augmentation are visible via import.\n}\n\n// ---- utilities ----\n\n// Simplifying wrapper around buildutil.FakeContext for single-file packages.\nfunc fakeContext(pkgs map[string]string) *build.Context {\n\tpkgs2 := make(map[string]map[string]string)\n\tfor path, content := range pkgs {\n\t\tpkgs2[path] = map[string]string{\"x.go\": content}\n\t}\n\treturn buildutil.FakeContext(pkgs2)\n}\n\nfunc hasError(errors []error, substr string) bool {\n\tfor _, err := range errors {\n\t\tif strings.Contains(err.Error(), substr) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc keys(m map[string]bool) (keys []string) {\n\tfor key := range m {\n\t\tkeys = append(keys, key)\n\t}\n\tsort.Strings(keys)\n\treturn\n}\n\n// Returns all loaded packages.\nfunc all(prog *loader.Program) []string {\n\tvar pkgs []string\n\tfor _, info := range prog.AllPackages {\n\t\tpkgs = append(pkgs, info.Pkg.Path())\n\t}\n\tsort.Strings(pkgs)\n\treturn pkgs\n}\n\n// Returns initially imported packages, as a string.\nfunc imported(prog *loader.Program) string {\n\tvar pkgs []string\n\tfor _, info := range prog.Imported {\n\t\tpkgs = append(pkgs, info.Pkg.Path())\n\t}\n\tsort.Strings(pkgs)\n\treturn strings.Join(pkgs, \" \")\n}\n\n// Returns initially created packages, as a string.\nfunc created(prog *loader.Program) string {\n\tvar pkgs []string\n\tfor _, info := range prog.Created {\n\t\tpkgs = append(pkgs, info.Pkg.Path())\n\t}\n\treturn strings.Join(pkgs, \" \")\n}\n\n// Load package \"io\" twice in parallel.\n// When run with -race, this is a regression test for Go issue 20718, in\n// which the global \"unsafe\" package was modified concurrently.\nfunc TestLoad1(t *testing.T) { loadIO(t) }\nfunc TestLoad2(t *testing.T) { loadIO(t) }\n\nfunc loadIO(t *testing.T) {\n\tt.Parallel()\n\tconf := &loader.Config{ImportPkgs: map[string]bool{\"io\": false}}\n\tif _, err := conf.Load(); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestCgoCwdIssue46877(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\ttestenv.NeedsTool(t, \"cgo\")\n\tvar conf loader.Config\n\tconf.Import(\"golang.org/x/tools/go/loader/testdata/issue46877\")\n\tif _, err := conf.Load(); err != nil {\n\t\tt.Errorf(\"Load failed: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "go/loader/stdlib_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage loader_test\n\n// This file enumerates all packages beneath $GOROOT, loads them, plus\n// their external tests if any, runs the type checker on them, and\n// prints some summary information.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestStdlib(t *testing.T) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"incomplete std lib on %s\", runtime.GOOS)\n\t}\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode; uses tons of memory (https://golang.org/issue/14113)\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\truntime.GC()\n\tt0 := time.Now()\n\tvar memstats runtime.MemStats\n\truntime.ReadMemStats(&memstats)\n\talloc := memstats.Alloc\n\n\t// Load, parse and type-check the program.\n\tctxt := build.Default // copy\n\tctxt.GOPATH = \"\"      // disable GOPATH\n\tconf := loader.Config{Build: &ctxt}\n\tfor _, path := range buildutil.AllPackages(conf.Build) {\n\t\tconf.ImportWithTests(path)\n\t}\n\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatalf(\"Load failed: %v\", err)\n\t}\n\n\tt1 := time.Now()\n\truntime.GC()\n\truntime.ReadMemStats(&memstats)\n\n\tnumPkgs := len(prog.AllPackages)\n\tif want := 205; numPkgs < want {\n\t\tt.Errorf(\"Loaded only %d packages, want at least %d\", numPkgs, want)\n\t}\n\n\t// Dump package members.\n\tif false {\n\t\tfor pkg := range prog.AllPackages {\n\t\t\tfmt.Printf(\"Package %s:\\n\", pkg.Path())\n\t\t\tscope := pkg.Scope()\n\t\t\tqualifier := types.RelativeTo(pkg)\n\t\t\tfor _, name := range scope.Names() {\n\t\t\t\tif ast.IsExported(name) {\n\t\t\t\t\tfmt.Printf(\"\\t%s\\n\", types.ObjectString(scope.Lookup(name), qualifier))\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Println()\n\t\t}\n\t}\n\n\t// Check that Test functions for regexp and compress/bzip2 are\n\t// simultaneously present. The apparent cycle formed when augmenting\n\t// these packages by their tests (together with io/ioutil's test, which is now\n\t// an xtest) was the original motivation or reporting golang.org/issue/7114.\n\t//\n\t// compress/bzip2.TestBitReader in bzip2_test.go    imports io/ioutil\n\t// io/ioutil.TestTempFile       in tempfile_test.go imports regexp (no longer exists)\n\t// regexp.TestRE2Search         in exec_test.go     imports compress/bzip2\n\tfor _, test := range []struct{ pkg, fn string }{\n\t\t{\"regexp\", \"TestRE2Search\"},\n\t\t{\"compress/bzip2\", \"TestBitReader\"},\n\t} {\n\t\tinfo := prog.Imported[test.pkg]\n\t\tif info == nil {\n\t\t\tt.Errorf(\"failed to load package %q\", test.pkg)\n\t\t\tcontinue\n\t\t}\n\t\tobj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"package %q has no func %q\", test.pkg, test.fn)\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// Dump some statistics.\n\n\t// determine line count\n\tvar lineCount int\n\tprog.Fset.Iterate(func(f *token.File) bool {\n\t\tlineCount += f.LineCount()\n\t\treturn true\n\t})\n\n\tt.Log(\"GOMAXPROCS:           \", runtime.GOMAXPROCS(0))\n\tt.Log(\"#Source lines:        \", lineCount)\n\tt.Log(\"Load/parse/typecheck: \", t1.Sub(t0))\n\tt.Log(\"#MB:                  \", int64(memstats.Alloc-alloc)/1000000)\n}\n\nfunc TestCgoOption(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode; uses tons of memory (https://golang.org/issue/14113)\")\n\t}\n\tswitch runtime.GOOS {\n\t// On these systems, the net and os/user packages don't use cgo\n\t// or the std library is incomplete (Android).\n\tcase \"android\", \"plan9\", \"solaris\", \"windows\":\n\t\tt.Skipf(\"no cgo or incomplete std lib on %s\", runtime.GOOS)\n\tcase \"darwin\":\n\t\tt.Skipf(\"golang/go#58493: file locations in this test are stale on darwin\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\t// In nocgo builds (e.g. linux-amd64-nocgo),\n\t// there is no \"runtime/cgo\" package,\n\t// so cgo-generated Go files will have a failing import.\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\t// Test that we can load cgo-using packages with\n\t// CGO_ENABLED=[01], which causes go/build to select pure\n\t// Go/native implementations, respectively, based on build\n\t// tags.\n\t//\n\t// Each entry specifies a package-level object and the generic\n\t// file expected to define it when cgo is disabled.\n\t// When cgo is enabled, the exact file is not specified (since\n\t// it varies by platform), but must differ from the generic one.\n\t//\n\t// The test also loads the actual file to verify that the\n\t// object is indeed defined at that location.\n\tfor _, test := range []struct {\n\t\tpkg, name, genericFile string\n\t}{\n\t\t{\"net\", \"cgoLookupHost\", \"cgo_stub.go\"},\n\t\t{\"os/user\", \"current\", \"lookup_stubs.go\"},\n\t} {\n\t\tctxt := build.Default\n\t\tfor _, ctxt.CgoEnabled = range []bool{false, true} {\n\t\t\tconf := loader.Config{Build: &ctxt}\n\t\t\tconf.Import(test.pkg)\n\t\t\tprog, err := conf.Load()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Load failed: %v\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tinfo := prog.Imported[test.pkg]\n\t\t\tif info == nil {\n\t\t\t\tt.Errorf(\"package %s not found\", test.pkg)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobj := info.Pkg.Scope().Lookup(test.name)\n\t\t\tif obj == nil {\n\t\t\t\tt.Errorf(\"no object %s.%s\", test.pkg, test.name)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tposn := prog.Fset.Position(obj.Pos())\n\t\t\tt.Logf(\"%s: %s (CgoEnabled=%t)\", posn, obj, ctxt.CgoEnabled)\n\n\t\t\tgotFile := filepath.Base(posn.Filename)\n\t\t\tfilesMatch := gotFile == test.genericFile\n\n\t\t\tif ctxt.CgoEnabled && filesMatch {\n\t\t\t\tt.Errorf(\"CGO_ENABLED=1: %s found in %s, want native file\",\n\t\t\t\t\tobj, gotFile)\n\t\t\t} else if !ctxt.CgoEnabled && !filesMatch {\n\t\t\t\tt.Errorf(\"CGO_ENABLED=0: %s found in %s, want %s\",\n\t\t\t\t\tobj, gotFile, test.genericFile)\n\t\t\t}\n\n\t\t\t// Load the file and check the object is declared at the right place.\n\t\t\tb, err := os.ReadFile(posn.Filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"can't read %s: %s\", posn.Filename, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tline := string(bytes.Split(b, []byte(\"\\n\"))[posn.Line-1])\n\t\t\tident := line[posn.Column-1:]\n\t\t\tif !strings.HasPrefix(ident, test.name) {\n\t\t\t\tt.Errorf(\"%s: %s not declared here (looking at %q)\", posn, obj, ident)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/loader/testdata/a.go",
    "content": "package P\n"
  },
  {
    "path": "go/loader/testdata/b.go",
    "content": "package P\n"
  },
  {
    "path": "go/loader/testdata/badpkgdecl.go",
    "content": "// this file has no package decl\n"
  },
  {
    "path": "go/loader/testdata/issue46877/x.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage x\n\n// #include \"x.h\"\nimport \"C\"\n\nvar _ C.myint\n"
  },
  {
    "path": "go/loader/testdata/issue46877/x.h",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\ntypedef int myint;\n"
  },
  {
    "path": "go/loader/util.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage loader\n\nimport (\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io\"\n\t\"os\"\n\t\"strconv\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n)\n\n// We use a counting semaphore to limit\n// the number of parallel I/O calls per process.\nvar ioLimit = make(chan bool, 10)\n\n// parseFiles parses the Go source files within directory dir and\n// returns the ASTs of the ones that could be at least partially parsed,\n// along with a list of I/O and parse errors encountered.\n//\n// I/O is done via ctxt, which may specify a virtual file system.\n// displayPath is used to transform the filenames attached to the ASTs.\nfunc parseFiles(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, files []string, mode parser.Mode) ([]*ast.File, []error) {\n\tif displayPath == nil {\n\t\tdisplayPath = func(path string) string { return path }\n\t}\n\tvar wg sync.WaitGroup\n\tn := len(files)\n\tparsed := make([]*ast.File, n)\n\terrors := make([]error, n)\n\tfor i, file := range files {\n\t\tif !buildutil.IsAbsPath(ctxt, file) {\n\t\t\tfile = buildutil.JoinPath(ctxt, dir, file)\n\t\t}\n\t\twg.Add(1)\n\t\tgo func(i int, file string) {\n\t\t\tioLimit <- true // wait\n\t\t\tdefer func() {\n\t\t\t\twg.Done()\n\t\t\t\t<-ioLimit // signal\n\t\t\t}()\n\t\t\tvar rd io.ReadCloser\n\t\t\tvar err error\n\t\t\tif ctxt.OpenFile != nil {\n\t\t\t\trd, err = ctxt.OpenFile(file)\n\t\t\t} else {\n\t\t\t\trd, err = os.Open(file)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\terrors[i] = err // open failed\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// ParseFile may return both an AST and an error.\n\t\t\tparsed[i], errors[i] = parser.ParseFile(fset, displayPath(file), rd, mode)\n\t\t\trd.Close()\n\t\t}(i, file)\n\t}\n\twg.Wait()\n\n\t// Eliminate nils, preserving order.\n\tvar o int\n\tfor _, f := range parsed {\n\t\tif f != nil {\n\t\t\tparsed[o] = f\n\t\t\to++\n\t\t}\n\t}\n\tparsed = parsed[:o]\n\n\to = 0\n\tfor _, err := range errors {\n\t\tif err != nil {\n\t\t\terrors[o] = err\n\t\t\to++\n\t\t}\n\t}\n\terrors = errors[:o]\n\n\treturn parsed, errors\n}\n\n// scanImports returns the set of all import paths from all\n// import specs in the specified files.\nfunc scanImports(files []*ast.File) map[string]bool {\n\timports := make(map[string]bool)\n\tfor _, f := range files {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tspec := spec.(*ast.ImportSpec)\n\n\t\t\t\t\t// NB: do not assume the program is well-formed!\n\t\t\t\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tcontinue // quietly ignore the error\n\t\t\t\t\t}\n\t\t\t\t\tif path == \"C\" {\n\t\t\t\t\t\tcontinue // skip pseudopackage\n\t\t\t\t\t}\n\t\t\t\t\timports[path] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn imports\n}\n\n// ---------- Internal helpers ----------\n\n// TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos)\nfunc tokenFileContainsPos(f *token.File, pos token.Pos) bool {\n\tp := int(pos)\n\tbase := f.Base()\n\treturn base <= p && p < base+f.Size()\n}\n"
  },
  {
    "path": "go/packages/doc.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage packages loads Go packages for inspection and analysis.\n\nThe [Load] function takes as input a list of patterns and returns a\nlist of [Package] values describing individual packages matched by those\npatterns.\nA [Config] specifies configuration options, the most important of which is\nthe [LoadMode], which controls the amount of detail in the loaded packages.\n\nLoad passes most patterns directly to the underlying build tool.\nThe default build tool is the go command.\nIts supported patterns are described at\nhttps://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.\nOther build systems may be supported by providing a \"driver\";\nsee [The driver protocol].\n\nAll patterns with the prefix \"query=\", where query is a\nnon-empty string of letters from [a-z], are reserved and may be\ninterpreted as query operators.\n\nTwo query operators are currently supported: \"file\" and \"pattern\".\n\nThe query \"file=path/to/file.go\" matches the package or packages enclosing\nthe Go source file path/to/file.go.  For example \"file=~/go/src/fmt/print.go\"\nmight return the packages \"fmt\" and \"fmt [fmt.test]\".\n\nThe query \"pattern=string\" causes \"string\" to be passed directly to\nthe underlying build tool. In most cases this is unnecessary,\nbut an application can use Load(\"pattern=\" + x) as an escaping mechanism\nto ensure that x is not interpreted as a query operator if it contains '='.\n\nAll other query operators are reserved for future use and currently\ncause Load to report an error.\n\nThe Package struct provides basic information about the package, including\n\n  - ID, a unique identifier for the package in the returned set;\n  - GoFiles, the names of the package's Go source files;\n  - Imports, a map from source import strings to the Packages they name;\n  - Types, the type information for the package's exported symbols;\n  - Syntax, the parsed syntax trees for the package's source code; and\n  - TypesInfo, the result of a complete type-check of the package syntax trees.\n\n(See the documentation for type Package for the complete list of fields\nand more detailed descriptions.)\n\nFor example,\n\n\tLoad(nil, \"bytes\", \"unicode...\")\n\nreturns four Package structs describing the standard library packages\nbytes, unicode, unicode/utf16, and unicode/utf8. Note that one pattern\ncan match multiple packages and that a package might be matched by\nmultiple patterns: in general it is not possible to determine which\npackages correspond to which patterns.\n\nNote that the list returned by Load contains only the packages matched\nby the patterns. Their dependencies can be found by walking the import\ngraph using the Imports fields.\n\nThe Load function can be configured by passing a pointer to a Config as\nthe first argument. A nil Config is equivalent to the zero Config, which\ncauses Load to run in [LoadFiles] mode, collecting minimal information.\nSee the documentation for type Config for details.\n\nAs noted earlier, the Config.Mode controls the amount of detail\nreported about the loaded packages. See the documentation for type LoadMode\nfor details.\n\nMost tools should pass their command-line arguments (after any flags)\nuninterpreted to Load, so that it can interpret them\naccording to the conventions of the underlying build system.\n\nSee the Example function for typical usage.\nSee also [golang.org/x/tools/go/packages/internal/linecount]\nfor an example application.\n\n# The driver protocol\n\nLoad may be used to load Go packages even in Go projects that use\nalternative build systems, by installing an appropriate \"driver\"\nprogram for the build system and specifying its location in the\nGOPACKAGESDRIVER environment variable.\nFor example,\nhttps://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration\nexplains how to use the driver for Bazel.\n\nThe driver program is responsible for interpreting patterns in its\npreferred notation and reporting information about the packages that\nthose patterns identify. Drivers must also support the special \"file=\"\nand \"pattern=\" patterns described above.\n\nThe patterns are provided as positional command-line arguments. A\nJSON-encoded [DriverRequest] message providing additional information\nis written to the driver's standard input. The driver must write a\nJSON-encoded [DriverResponse] message to its standard output. (This\nmessage differs from the JSON schema produced by 'go list'.)\n\nThe value of the PWD environment variable seen by the driver process\nis the preferred name of its working directory. (The working directory\nmay have other aliases due to symbolic links; see the comment on the\nDir field of [exec.Cmd] for related information.)\nWhen the driver process emits in its response the name of a file\nthat is a descendant of this directory, it must use an absolute path\nthat has the value of PWD as a prefix, to ensure that the returned\nfilenames satisfy the original query.\n*/\npackage packages // import \"golang.org/x/tools/go/packages\"\n\n/*\n\nMotivation and design considerations\n\nThe new package's design solves problems addressed by two existing\npackages: go/build, which locates and describes packages, and\ngolang.org/x/tools/go/loader, which loads, parses and type-checks them.\nThe go/build.Package structure encodes too much of the 'go build' way\nof organizing projects, leaving us in need of a data type that describes a\npackage of Go source code independent of the underlying build system.\nWe wanted something that works equally well with go build and vgo, and\nalso other build systems such as Bazel and Blaze, making it possible to\nconstruct analysis tools that work in all these environments.\nTools such as errcheck and staticcheck were essentially unavailable to\nthe Go community at Google, and some of Google's internal tools for Go\nare unavailable externally.\nThis new package provides a uniform way to obtain package metadata by\nquerying each of these build systems, optionally supporting their\npreferred command-line notations for packages, so that tools integrate\nneatly with users' build environments. The Metadata query function\nexecutes an external query tool appropriate to the current workspace.\n\nLoading packages always returns the complete import graph \"all the way down\",\neven if all you want is information about a single package, because the query\nmechanisms of all the build systems we currently support ({go,vgo} list, and\nblaze/bazel aspect-based query) cannot provide detailed information\nabout one package without visiting all its dependencies too, so there is\nno additional asymptotic cost to providing transitive information.\n(This property might not be true of a hypothetical 5th build system.)\n\nIn calls to TypeCheck, all initial packages, and any package that\ntransitively depends on one of them, must be loaded from source.\nConsider A->B->C->D->E: if A,C are initial, A,B,C must be loaded from\nsource; D may be loaded from export data, and E may not be loaded at all\n(though it's possible that D's export data mentions it, so a\ntypes.Package may be created for it and exposed.)\n\nThe old loader had a feature to suppress type-checking of function\nbodies on a per-package basis, primarily intended to reduce the work of\nobtaining type information for imported packages. Now that imports are\nsatisfied by export data, the optimization no longer seems necessary.\n\nDespite some early attempts, the old loader did not exploit export data,\ninstead always using the equivalent of WholeProgram mode. This was due\nto the complexity of mixing source and export data packages (now\nresolved by the upward traversal mentioned above), and because export data\nfiles were nearly always missing or stale. Now that 'go build' supports\ncaching, all the underlying build systems can guarantee to produce\nexport data in a reasonable (amortized) time.\n\nTest \"main\" packages synthesized by the build system are now reported as\nfirst-class packages, avoiding the need for clients (such as go/ssa) to\nreinvent this generation logic.\n\nOne way in which go/packages is simpler than the old loader is in its\ntreatment of in-package tests. In-package tests are packages that\nconsist of all the files of the library under test, plus the test files.\nThe old loader constructed in-package tests by a two-phase process of\nmutation called \"augmentation\": first it would construct and type check\nall the ordinary library packages and type-check the packages that\ndepend on them; then it would add more (test) files to the package and\ntype-check again. This two-phase approach had four major problems:\n1) in processing the tests, the loader modified the library package,\n   leaving no way for a client application to see both the test\n   package and the library package; one would mutate into the other.\n2) because test files can declare additional methods on types defined in\n   the library portion of the package, the dispatch of method calls in\n   the library portion was affected by the presence of the test files.\n   This should have been a clue that the packages were logically\n   different.\n3) this model of \"augmentation\" assumed at most one in-package test\n   per library package, which is true of projects using 'go build',\n   but not other build systems.\n4) because of the two-phase nature of test processing, all packages that\n   import the library package had to be processed before augmentation,\n   forcing a \"one-shot\" API and preventing the client from calling Load\n   in several times in sequence as is now possible in WholeProgram mode.\n   (TypeCheck mode has a similar one-shot restriction for a different reason.)\n\nEarly drafts of this package supported \"multi-shot\" operation.\nAlthough it allowed clients to make a sequence of calls (or concurrent\ncalls) to Load, building up the graph of Packages incrementally,\nit was of marginal value: it complicated the API\n(since it allowed some options to vary across calls but not others),\nit complicated the implementation,\nit cannot be made to work in Types mode, as explained above,\nand it was less efficient than making one combined call (when this is possible).\nAmong the clients we have inspected, none made multiple calls to load\nbut could not be easily and satisfactorily modified to make only a single call.\nHowever, applications changes may be required.\nFor example, the ssadump command loads the user-specified packages\nand in addition the runtime package.  It is tempting to simply append\n\"runtime\" to the user-provided list, but that does not work if the user\nspecified an ad-hoc package such as [a.go b.go].\nInstead, ssadump no longer requests the runtime package,\nbut seeks it among the dependencies of the user-specified packages,\nand emits an error if it is not found.\n\nQuestions & Tasks\n\n- Add GOARCH/GOOS?\n  They are not portable concepts, but could be made portable.\n  Our goal has been to allow users to express themselves using the conventions\n  of the underlying build system: if the build system honors GOARCH\n  during a build and during a metadata query, then so should\n  applications built atop that query mechanism.\n  Conversely, if the target architecture of the build is determined by\n  command-line flags, the application can pass the relevant\n  flags through to the build system using a command such as:\n    myapp -query_flag=\"--cpu=amd64\" -query_flag=\"--os=darwin\"\n  However, this approach is low-level, unwieldy, and non-portable.\n  GOOS and GOARCH seem important enough to warrant a dedicated option.\n\n- How should we handle partial failures such as a mixture of good and\n  malformed patterns, existing and non-existent packages, successful and\n  failed builds, import failures, import cycles, and so on, in a call to\n  Load?\n\n- Support bazel, blaze, and go1.10 list, not just go1.11 list.\n\n- Handle (and test) various partial success cases, e.g.\n  a mixture of good packages and:\n  invalid patterns\n  nonexistent packages\n  empty packages\n  packages with malformed package or import declarations\n  unreadable files\n  import cycles\n  other parse errors\n  type errors\n  Make sure we record errors at the correct place in the graph.\n\n- Missing packages among initial arguments are not reported.\n  Return bogus packages for them, like golist does.\n\n- \"undeclared name\" errors (for example) are reported out of source file\n  order. I suspect this is due to the breadth-first resolution now used\n  by go/types. Is that a bug? Discuss with gri.\n\n*/\n"
  },
  {
    "path": "go/packages/example_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages_test\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\n// Example demonstrates how to load the packages specified on the\n// command line from source syntax.\nfunc Example() {\n\tflag.Parse()\n\n\t// Many tools pass their command-line arguments (after any flags)\n\t// uninterpreted to packages.Load so that it can interpret them\n\t// according to the conventions of the underlying build system.\n\tcfg := &packages.Config{Mode: packages.NeedFiles | packages.NeedSyntax}\n\tpkgs, err := packages.Load(cfg, flag.Args()...)\n\tif err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"load: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tos.Exit(1)\n\t}\n\n\t// Print the names of the source files\n\t// for each package listed on the command line.\n\tfor _, pkg := range pkgs {\n\t\tfmt.Println(pkg.ID, pkg.GoFiles)\n\t}\n}\n"
  },
  {
    "path": "go/packages/external.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\n// This file defines the protocol that enables an external \"driver\"\n// tool to supply package metadata in place of 'go list'.\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"slices\"\n\t\"strings\"\n)\n\n// DriverRequest defines the schema of a request for package metadata\n// from an external driver program. The JSON-encoded DriverRequest\n// message is provided to the driver program's standard input. The\n// query patterns are provided as command-line arguments.\n//\n// See the package documentation for an overview.\ntype DriverRequest struct {\n\tMode LoadMode `json:\"mode\"`\n\n\t// Env specifies the environment the underlying build system should be run in.\n\tEnv []string `json:\"env\"`\n\n\t// BuildFlags are flags that should be passed to the underlying build system.\n\tBuildFlags []string `json:\"build_flags\"`\n\n\t// Tests specifies whether the patterns should also return test packages.\n\tTests bool `json:\"tests\"`\n\n\t// Overlay maps file paths (relative to the driver's working directory)\n\t// to the contents of overlay files (see Config.Overlay).\n\tOverlay map[string][]byte `json:\"overlay\"`\n}\n\n// DriverResponse defines the schema of a response from an external\n// driver program, providing the results of a query for package\n// metadata. The driver program must write a JSON-encoded\n// DriverResponse message to its standard output.\n//\n// See the package documentation for an overview.\ntype DriverResponse struct {\n\t// NotHandled is returned if the request can't be handled by the current\n\t// driver. If an external driver returns a response with NotHandled, the\n\t// rest of the DriverResponse is ignored, and go/packages will fallback\n\t// to the next driver. If go/packages is extended in the future to support\n\t// lists of multiple drivers, go/packages will fall back to the next driver.\n\tNotHandled bool\n\n\t// Compiler and Arch are the arguments pass of types.SizesFor\n\t// to get a types.Sizes to use when type checking.\n\tCompiler string\n\tArch     string\n\n\t// Roots is the set of package IDs that make up the root packages.\n\t// We have to encode this separately because when we encode a single package\n\t// we cannot know if it is one of the roots as that requires knowledge of the\n\t// graph it is part of.\n\tRoots []string `json:\",omitempty\"`\n\n\t// Packages is the full set of packages in the graph.\n\t// The packages are not connected into a graph.\n\t// The Imports if populated will be stubs that only have their ID set.\n\t// Imports will be connected and then type and syntax information added in a\n\t// later pass (see refine).\n\tPackages []*Package\n\n\t// GoVersion is the minor version number used by the driver\n\t// (e.g. the go command on the PATH) when selecting .go files.\n\t// Zero means unknown.\n\tGoVersion int\n}\n\n// driver is the type for functions that query the build system for the\n// packages named by the patterns.\ntype driver func(cfg *Config, patterns []string) (*DriverResponse, error)\n\n// findExternalDriver returns the file path of a tool that supplies\n// the build system package structure, or \"\" if not found.\n// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its\n// value, otherwise it searches for a binary named gopackagesdriver on the PATH.\nfunc findExternalDriver(cfg *Config) driver {\n\tconst toolPrefix = \"GOPACKAGESDRIVER=\"\n\ttool := \"\"\n\tfor _, env := range cfg.Env {\n\t\tif val, ok := strings.CutPrefix(env, toolPrefix); ok {\n\t\t\ttool = val\n\t\t}\n\t}\n\tif tool != \"\" && tool == \"off\" {\n\t\treturn nil\n\t}\n\tif tool == \"\" {\n\t\tvar err error\n\t\ttool, err = exec.LookPath(\"gopackagesdriver\")\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn func(cfg *Config, patterns []string) (*DriverResponse, error) {\n\t\treq, err := json.Marshal(DriverRequest{\n\t\t\tMode:       cfg.Mode,\n\t\t\tEnv:        cfg.Env,\n\t\t\tBuildFlags: cfg.BuildFlags,\n\t\t\tTests:      cfg.Tests,\n\t\t\tOverlay:    cfg.Overlay,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to encode message to driver tool: %v\", err)\n\t\t}\n\n\t\tbuf := new(bytes.Buffer)\n\t\tstderr := new(bytes.Buffer)\n\t\tcmd := exec.CommandContext(cfg.Context, tool, patterns...)\n\t\tcmd.Dir = cfg.Dir\n\t\t// The cwd gets resolved to the real path. On Darwin, where\n\t\t// /tmp is a symlink, this breaks anything that expects the\n\t\t// working directory to keep the original path, including the\n\t\t// go command when dealing with modules.\n\t\t//\n\t\t// os.Getwd stdlib has a special feature where if the\n\t\t// cwd and the PWD are the same node then it trusts\n\t\t// the PWD, so by setting it in the env for the child\n\t\t// process we fix up all the paths returned by the go\n\t\t// command.\n\t\t//\n\t\t// (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go)\n\t\tcmd.Env = append(slices.Clip(cfg.Env), \"PWD=\"+cfg.Dir)\n\t\tcmd.Stdin = bytes.NewReader(req)\n\t\tcmd.Stdout = buf\n\t\tcmd.Stderr = stderr\n\n\t\tif err := cmd.Run(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%v: %v: %s\", tool, err, cmd.Stderr)\n\t\t}\n\t\tif len(stderr.Bytes()) != 0 && os.Getenv(\"GOPACKAGESPRINTDRIVERERRORS\") != \"\" {\n\t\t\tfmt.Fprintf(os.Stderr, \"%s stderr: <<%s>>\\n\", cmdDebugStr(cmd), stderr)\n\t\t}\n\n\t\tvar response DriverResponse\n\t\tif err := json.Unmarshal(buf.Bytes(), &response); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &response, nil\n\t}\n}\n"
  },
  {
    "path": "go/packages/golist.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n)\n\n// debug controls verbose logging.\nvar debug, _ = strconv.ParseBool(os.Getenv(\"GOPACKAGESDEBUG\"))\n\n// A goTooOldError reports that the go command\n// found by exec.LookPath is too old to use the new go list behavior.\ntype goTooOldError struct {\n\terror\n}\n\n// responseDeduper wraps a DriverResponse, deduplicating its contents.\ntype responseDeduper struct {\n\tseenRoots    map[string]bool\n\tseenPackages map[string]*Package\n\tdr           *DriverResponse\n}\n\nfunc newDeduper() *responseDeduper {\n\treturn &responseDeduper{\n\t\tdr:           &DriverResponse{},\n\t\tseenRoots:    map[string]bool{},\n\t\tseenPackages: map[string]*Package{},\n\t}\n}\n\n// addAll fills in r with a DriverResponse.\nfunc (r *responseDeduper) addAll(dr *DriverResponse) {\n\tfor _, pkg := range dr.Packages {\n\t\tr.addPackage(pkg)\n\t}\n\tfor _, root := range dr.Roots {\n\t\tr.addRoot(root)\n\t}\n\tr.dr.GoVersion = dr.GoVersion\n}\n\nfunc (r *responseDeduper) addPackage(p *Package) {\n\tif prev := r.seenPackages[p.ID]; prev != nil {\n\t\t// Package already seen in a previous response. Merge the file lists,\n\t\t// removing duplicates. This can happen when the same package appears\n\t\t// in multiple driver responses that are being merged together.\n\t\tprev.GoFiles = appendUniqueStrings(prev.GoFiles, p.GoFiles)\n\t\tprev.CompiledGoFiles = appendUniqueStrings(prev.CompiledGoFiles, p.CompiledGoFiles)\n\t\tprev.OtherFiles = appendUniqueStrings(prev.OtherFiles, p.OtherFiles)\n\t\tprev.IgnoredFiles = appendUniqueStrings(prev.IgnoredFiles, p.IgnoredFiles)\n\t\tprev.EmbedFiles = appendUniqueStrings(prev.EmbedFiles, p.EmbedFiles)\n\t\tprev.EmbedPatterns = appendUniqueStrings(prev.EmbedPatterns, p.EmbedPatterns)\n\t\treturn\n\t}\n\tr.seenPackages[p.ID] = p\n\tr.dr.Packages = append(r.dr.Packages, p)\n}\n\n// appendUniqueStrings appends elements from src to dst, skipping duplicates.\nfunc appendUniqueStrings(dst, src []string) []string {\n\tif len(src) == 0 {\n\t\treturn dst\n\t}\n\n\tseen := make(map[string]bool, len(dst))\n\tfor _, s := range dst {\n\t\tseen[s] = true\n\t}\n\n\tfor _, s := range src {\n\t\tif !seen[s] {\n\t\t\tdst = append(dst, s)\n\t\t}\n\t}\n\n\treturn dst\n}\n\nfunc (r *responseDeduper) addRoot(id string) {\n\tif r.seenRoots[id] {\n\t\treturn\n\t}\n\tr.seenRoots[id] = true\n\tr.dr.Roots = append(r.dr.Roots, id)\n}\n\ntype golistState struct {\n\tcfg *Config\n\tctx context.Context\n\n\trunner *gocommand.Runner\n\n\t// overlay is the JSON file that encodes the Config.Overlay\n\t// mapping, used by 'go list -overlay=...'.\n\toverlay string\n\n\tenvOnce    sync.Once\n\tgoEnvError error\n\tgoEnv      map[string]string\n\n\trootsOnce     sync.Once\n\trootDirsError error\n\trootDirs      map[string]string\n\n\tgoVersionOnce  sync.Once\n\tgoVersionError error\n\tgoVersion      int // The X in Go 1.X.\n\n\t// vendorDirs caches the (non)existence of vendor directories.\n\tvendorDirs map[string]bool\n}\n\n// getEnv returns Go environment variables. Only specific variables are\n// populated -- computing all of them is slow.\nfunc (state *golistState) getEnv() (map[string]string, error) {\n\tstate.envOnce.Do(func() {\n\t\tvar b *bytes.Buffer\n\t\tb, state.goEnvError = state.invokeGo(\"env\", \"-json\", \"GOMOD\", \"GOPATH\")\n\t\tif state.goEnvError != nil {\n\t\t\treturn\n\t\t}\n\n\t\tstate.goEnv = make(map[string]string)\n\t\tdecoder := json.NewDecoder(b)\n\t\tif state.goEnvError = decoder.Decode(&state.goEnv); state.goEnvError != nil {\n\t\t\treturn\n\t\t}\n\t})\n\treturn state.goEnv, state.goEnvError\n}\n\n// mustGetEnv is a convenience function that can be used if getEnv has already succeeded.\nfunc (state *golistState) mustGetEnv() map[string]string {\n\tenv, err := state.getEnv()\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"mustGetEnv: %v\", err))\n\t}\n\treturn env\n}\n\n// goListDriver uses the go list command to interpret the patterns and produce\n// the build system package structure.\n// See driver for more details.\n//\n// overlay is the JSON file that encodes the cfg.Overlay\n// mapping, used by 'go list -overlay=...'\nfunc goListDriver(cfg *Config, runner *gocommand.Runner, overlay string, patterns []string) (_ *DriverResponse, err error) {\n\t// Make sure that any asynchronous go commands are killed when we return.\n\tparentCtx := cfg.Context\n\tif parentCtx == nil {\n\t\tparentCtx = context.Background()\n\t}\n\tctx, cancel := context.WithCancel(parentCtx)\n\tdefer cancel()\n\n\tresponse := newDeduper()\n\n\tstate := &golistState{\n\t\tcfg:        cfg,\n\t\tctx:        ctx,\n\t\tvendorDirs: map[string]bool{},\n\t\toverlay:    overlay,\n\t\trunner:     runner,\n\t}\n\n\t// Fill in response.Sizes asynchronously if necessary.\n\tif cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 {\n\t\terrCh := make(chan error)\n\t\tgo func() {\n\t\t\tcompiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), runner)\n\t\t\tresponse.dr.Compiler = compiler\n\t\t\tresponse.dr.Arch = arch\n\t\t\terrCh <- err\n\t\t}()\n\t\tdefer func() {\n\t\t\tif sizesErr := <-errCh; sizesErr != nil {\n\t\t\t\terr = sizesErr\n\t\t\t}\n\t\t}()\n\t}\n\n\t// Determine files requested in contains patterns\n\tvar containFiles []string\n\trestPatterns := make([]string, 0, len(patterns))\n\t// Extract file= and other [querytype]= patterns. Report an error if querytype\n\t// doesn't exist.\nextractQueries:\n\tfor _, pattern := range patterns {\n\t\teqidx := strings.Index(pattern, \"=\")\n\t\tif eqidx < 0 {\n\t\t\trestPatterns = append(restPatterns, pattern)\n\t\t} else {\n\t\t\tquery, value := pattern[:eqidx], pattern[eqidx+len(\"=\"):]\n\t\t\tswitch query {\n\t\t\tcase \"file\":\n\t\t\t\tcontainFiles = append(containFiles, value)\n\t\t\tcase \"pattern\":\n\t\t\t\trestPatterns = append(restPatterns, value)\n\t\t\tcase \"\": // not a reserved query\n\t\t\t\trestPatterns = append(restPatterns, pattern)\n\t\t\tdefault:\n\t\t\t\tfor _, rune := range query {\n\t\t\t\t\tif rune < 'a' || rune > 'z' { // not a reserved query\n\t\t\t\t\t\trestPatterns = append(restPatterns, pattern)\n\t\t\t\t\t\tcontinue extractQueries\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Reject all other patterns containing \"=\"\n\t\t\t\treturn nil, fmt.Errorf(\"invalid query type %q in query pattern %q\", query, pattern)\n\t\t\t}\n\t\t}\n\t}\n\n\t// See if we have any patterns to pass through to go list. Zero initial\n\t// patterns also requires a go list call, since it's the equivalent of\n\t// \".\".\n\tif len(restPatterns) > 0 || len(patterns) == 0 {\n\t\tdr, err := state.createDriverResponse(restPatterns...)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresponse.addAll(dr)\n\t}\n\n\tif len(containFiles) != 0 {\n\t\tif err := state.runContainsQueries(response, containFiles); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// (We may yet return an error due to defer.)\n\treturn response.dr, nil\n}\n\n// abs returns an absolute representation of path, based on cfg.Dir.\nfunc (cfg *Config) abs(path string) (string, error) {\n\tif filepath.IsAbs(path) {\n\t\treturn path, nil\n\t}\n\t// In case cfg.Dir is relative, pass it to filepath.Abs.\n\treturn filepath.Abs(filepath.Join(cfg.Dir, path))\n}\n\nfunc (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error {\n\tfor _, query := range queries {\n\t\t// TODO(matloob): Do only one query per directory.\n\t\tfdir := filepath.Dir(query)\n\t\t// Pass absolute path of directory to go list so that it knows to treat it as a directory,\n\t\t// not a package path.\n\t\tpattern, err := state.cfg.abs(fdir)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not determine absolute path of file= query path %q: %v\", query, err)\n\t\t}\n\t\tdirResponse, err := state.createDriverResponse(pattern)\n\n\t\t// If there was an error loading the package, or no packages are returned,\n\t\t// or the package is returned with errors, try to load the file as an\n\t\t// ad-hoc package.\n\t\t// Usually the error will appear in a returned package, but may not if we're\n\t\t// in module mode and the ad-hoc is located outside a module.\n\t\tif err != nil || len(dirResponse.Packages) == 0 || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 &&\n\t\t\tlen(dirResponse.Packages[0].Errors) == 1 {\n\t\t\tvar queryErr error\n\t\t\tif dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil {\n\t\t\t\treturn err // return the original error\n\t\t\t}\n\t\t}\n\t\tisRoot := make(map[string]bool, len(dirResponse.Roots))\n\t\tfor _, root := range dirResponse.Roots {\n\t\t\tisRoot[root] = true\n\t\t}\n\t\tfor _, pkg := range dirResponse.Packages {\n\t\t\t// Add any new packages to the main set\n\t\t\t// We don't bother to filter packages that will be dropped by the changes of roots,\n\t\t\t// that will happen anyway during graph construction outside this function.\n\t\t\t// Over-reporting packages is not a problem.\n\t\t\tresponse.addPackage(pkg)\n\t\t\t// if the package was not a root one, it cannot have the file\n\t\t\tif !isRoot[pkg.ID] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, pkgFile := range pkg.GoFiles {\n\t\t\t\tif filepath.Base(query) == filepath.Base(pkgFile) {\n\t\t\t\t\tresponse.addRoot(pkg.ID)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// adhocPackage attempts to load or construct an ad-hoc package for a given\n// query, if the original call to the driver produced inadequate results.\nfunc (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {\n\tresponse, err := state.createDriverResponse(query)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// If we get nothing back from `go list`,\n\t// try to make this file into its own ad-hoc package.\n\t// TODO(rstambler): Should this check against the original response?\n\tif len(response.Packages) == 0 {\n\t\tresponse.Packages = append(response.Packages, &Package{\n\t\t\tID:              \"command-line-arguments\",\n\t\t\tPkgPath:         query,\n\t\t\tGoFiles:         []string{query},\n\t\t\tCompiledGoFiles: []string{query},\n\t\t\tImports:         make(map[string]*Package),\n\t\t})\n\t\tresponse.Roots = append(response.Roots, \"command-line-arguments\")\n\t}\n\t// Handle special cases.\n\tif len(response.Packages) == 1 {\n\t\t// golang/go#33482: If this is a file= query for ad-hoc packages where\n\t\t// the file only exists on an overlay, and exists outside of a module,\n\t\t// add the file to the package and remove the errors.\n\t\tif response.Packages[0].ID == \"command-line-arguments\" ||\n\t\t\tfilepath.ToSlash(response.Packages[0].PkgPath) == filepath.ToSlash(query) {\n\t\t\tif len(response.Packages[0].GoFiles) == 0 {\n\t\t\t\tfilename := filepath.Join(pattern, filepath.Base(query)) // avoid recomputing abspath\n\t\t\t\t// TODO(matloob): check if the file is outside of a root dir?\n\t\t\t\tfor path := range state.cfg.Overlay {\n\t\t\t\t\tif path == filename {\n\t\t\t\t\t\tresponse.Packages[0].Errors = nil\n\t\t\t\t\t\tresponse.Packages[0].GoFiles = []string{path}\n\t\t\t\t\t\tresponse.Packages[0].CompiledGoFiles = []string{path}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn response, nil\n}\n\n// Fields must match go list;\n// see $GOROOT/src/cmd/go/internal/load/pkg.go.\ntype jsonPackage struct {\n\tImportPath        string\n\tDir               string\n\tName              string\n\tTarget            string\n\tExport            string\n\tGoFiles           []string\n\tCompiledGoFiles   []string\n\tIgnoredGoFiles    []string\n\tIgnoredOtherFiles []string\n\tEmbedPatterns     []string\n\tEmbedFiles        []string\n\tCFiles            []string\n\tCgoFiles          []string\n\tCXXFiles          []string\n\tMFiles            []string\n\tHFiles            []string\n\tFFiles            []string\n\tSFiles            []string\n\tSwigFiles         []string\n\tSwigCXXFiles      []string\n\tSysoFiles         []string\n\tImports           []string\n\tImportMap         map[string]string\n\tDeps              []string\n\tModule            *Module\n\tTestGoFiles       []string\n\tTestImports       []string\n\tXTestGoFiles      []string\n\tXTestImports      []string\n\tForTest           string // q in a \"p [q.test]\" package, else \"\"\n\tDepOnly           bool\n\n\tError      *packagesinternal.PackageError\n\tDepsErrors []*packagesinternal.PackageError\n}\n\nfunc otherFiles(p *jsonPackage) [][]string {\n\treturn [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}\n}\n\n// createDriverResponse uses the \"go list\" command to expand the pattern\n// words and return a response for the specified packages.\nfunc (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {\n\t// go list uses the following identifiers in ImportPath and Imports:\n\t//\n\t// \t\"p\"\t\t\t-- importable package or main (command)\n\t// \t\"q.test\"\t\t-- q's test executable\n\t// \t\"p [q.test]\"\t\t-- variant of p as built for q's test executable\n\t// \t\"q_test [q.test]\"\t-- q's external test package\n\t//\n\t// The packages p that are built differently for a test q.test\n\t// are q itself, plus any helpers used by the external test q_test,\n\t// typically including \"testing\" and all its dependencies.\n\n\t// Run \"go list\" for complete\n\t// information on the specified packages.\n\tgoVersion, err := state.getGoVersion()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbuf, err := state.invokeGo(\"list\", golistargs(state.cfg, words, goVersion)...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tseen := make(map[string]*jsonPackage)\n\tpkgs := make(map[string]*Package)\n\tadditionalErrors := make(map[string][]Error)\n\t// Decode the JSON and convert it to Package form.\n\tresponse := &DriverResponse{\n\t\tGoVersion: goVersion,\n\t}\n\tfor dec := json.NewDecoder(buf); dec.More(); {\n\t\tp := new(jsonPackage)\n\t\tif err := dec.Decode(p); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"JSON decoding failed: %v\", err)\n\t\t}\n\n\t\tif p.ImportPath == \"\" {\n\t\t\t// The documentation for go list says that “[e]rroneous packages will have\n\t\t\t// a non-empty ImportPath”. If for some reason it comes back empty, we\n\t\t\t// prefer to error out rather than silently discarding data or handing\n\t\t\t// back a package without any way to refer to it.\n\t\t\tif p.Error != nil {\n\t\t\t\treturn nil, Error{\n\t\t\t\t\tPos: p.Error.Pos,\n\t\t\t\t\tMsg: p.Error.Err,\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"package missing import path: %+v\", p)\n\t\t}\n\n\t\t// Work around https://golang.org/issue/33157:\n\t\t// go list -e, when given an absolute path, will find the package contained at\n\t\t// that directory. But when no package exists there, it will return a fake package\n\t\t// with an error and the ImportPath set to the absolute path provided to go list.\n\t\t// Try to convert that absolute path to what its package path would be if it's\n\t\t// contained in a known module or GOPATH entry. This will allow the package to be\n\t\t// properly \"reclaimed\" when overlays are processed.\n\t\tif filepath.IsAbs(p.ImportPath) && p.Error != nil {\n\t\t\tpkgPath, ok, err := state.getPkgPath(p.ImportPath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif ok {\n\t\t\t\tp.ImportPath = pkgPath\n\t\t\t}\n\t\t}\n\n\t\tif old, found := seen[p.ImportPath]; found {\n\t\t\t// If one version of the package has an error, and the other doesn't, assume\n\t\t\t// that this is a case where go list is reporting a fake dependency variant\n\t\t\t// of the imported package: When a package tries to invalidly import another\n\t\t\t// package, go list emits a variant of the imported package (with the same\n\t\t\t// import path, but with an error on it, and the package will have a\n\t\t\t// DepError set on it). An example of when this can happen is for imports of\n\t\t\t// main packages: main packages can not be imported, but they may be\n\t\t\t// separately matched and listed by another pattern.\n\t\t\t// See golang.org/issue/36188 for more details.\n\n\t\t\t// The plan is that eventually, hopefully in Go 1.15, the error will be\n\t\t\t// reported on the importing package rather than the duplicate \"fake\"\n\t\t\t// version of the imported package. Once all supported versions of Go\n\t\t\t// have the new behavior this logic can be deleted.\n\t\t\t// TODO(matloob): delete the workaround logic once all supported versions of\n\t\t\t// Go return the errors on the proper package.\n\n\t\t\t// There should be exactly one version of a package that doesn't have an\n\t\t\t// error.\n\t\t\tif old.Error == nil && p.Error == nil {\n\t\t\t\tif !reflect.DeepEqual(p, old) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"internal error: go list gives conflicting information for package %v\", p.ImportPath)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Determine if this package's error needs to be bubbled up.\n\t\t\t// This is a hack, and we expect for go list to eventually set the error\n\t\t\t// on the package.\n\t\t\tif old.Error != nil {\n\t\t\t\tvar errkind string\n\t\t\t\tif strings.Contains(old.Error.Err, \"not an importable package\") {\n\t\t\t\t\terrkind = \"not an importable package\"\n\t\t\t\t} else if strings.Contains(old.Error.Err, \"use of internal package\") && strings.Contains(old.Error.Err, \"not allowed\") {\n\t\t\t\t\terrkind = \"use of internal package not allowed\"\n\t\t\t\t}\n\t\t\t\tif errkind != \"\" {\n\t\t\t\t\tif len(old.Error.ImportStack) < 1 {\n\t\t\t\t\t\treturn nil, fmt.Errorf(`internal error: go list gave a %q error with empty import stack`, errkind)\n\t\t\t\t\t}\n\t\t\t\t\timportingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-1]\n\t\t\t\t\tif importingPkg == old.ImportPath {\n\t\t\t\t\t\t// Using an older version of Go which put this package itself on top of import\n\t\t\t\t\t\t// stack, instead of the importer. Look for importer in second from top\n\t\t\t\t\t\t// position.\n\t\t\t\t\t\tif len(old.Error.ImportStack) < 2 {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack without importing package`, errkind)\n\t\t\t\t\t\t}\n\t\t\t\t\t\timportingPkg = old.Error.ImportStack[len(old.Error.ImportStack)-2]\n\t\t\t\t\t}\n\t\t\t\t\tadditionalErrors[importingPkg] = append(additionalErrors[importingPkg], Error{\n\t\t\t\t\t\tPos:  old.Error.Pos,\n\t\t\t\t\t\tMsg:  old.Error.Err,\n\t\t\t\t\t\tKind: ListError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Make sure that if there's a version of the package without an error,\n\t\t\t// that's the one reported to the user.\n\t\t\tif old.Error == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// This package will replace the old one at the end of the loop.\n\t\t}\n\t\tseen[p.ImportPath] = p\n\n\t\tpkg := &Package{\n\t\t\tName:            p.Name,\n\t\t\tID:              p.ImportPath,\n\t\t\tDir:             p.Dir,\n\t\t\tTarget:          p.Target,\n\t\t\tGoFiles:         absJoin(p.Dir, p.GoFiles, p.CgoFiles),\n\t\t\tCompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),\n\t\t\tOtherFiles:      absJoin(p.Dir, otherFiles(p)...),\n\t\t\tEmbedFiles:      absJoin(p.Dir, p.EmbedFiles),\n\t\t\tEmbedPatterns:   absJoin(p.Dir, p.EmbedPatterns),\n\t\t\tIgnoredFiles:    absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles),\n\t\t\tForTest:         p.ForTest,\n\t\t\tdepsErrors:      p.DepsErrors,\n\t\t\tModule:          p.Module,\n\t\t}\n\n\t\tif (state.cfg.Mode&typecheckCgo) != 0 && len(p.CgoFiles) != 0 {\n\t\t\tif len(p.CompiledGoFiles) > len(p.GoFiles) {\n\t\t\t\t// We need the cgo definitions, which are in the first\n\t\t\t\t// CompiledGoFile after the non-cgo ones. This is a hack but there\n\t\t\t\t// isn't currently a better way to find it. We also need the pure\n\t\t\t\t// Go files and unprocessed cgo files, all of which are already\n\t\t\t\t// in pkg.GoFiles.\n\t\t\t\tcgoTypes := p.CompiledGoFiles[len(p.GoFiles)]\n\t\t\t\tpkg.CompiledGoFiles = append([]string{cgoTypes}, pkg.GoFiles...)\n\t\t\t} else {\n\t\t\t\t// golang/go#38990: go list silently fails to do cgo processing\n\t\t\t\tpkg.CompiledGoFiles = nil\n\t\t\t\tpkg.Errors = append(pkg.Errors, Error{\n\t\t\t\t\tMsg:  \"go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.\",\n\t\t\t\t\tKind: ListError,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Work around https://golang.org/issue/28749:\n\t\t// cmd/go puts assembly, C, and C++ files in CompiledGoFiles.\n\t\t// Remove files from CompiledGoFiles that are non-go files\n\t\t// (or are not files that look like they are from the cache).\n\t\tif len(pkg.CompiledGoFiles) > 0 {\n\t\t\tout := pkg.CompiledGoFiles[:0]\n\t\t\tfor _, f := range pkg.CompiledGoFiles {\n\t\t\t\tif ext := filepath.Ext(f); ext != \".go\" && ext != \"\" { // ext == \"\" means the file is from the cache, so probably cgo-processed file\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tout = append(out, f)\n\t\t\t}\n\t\t\tpkg.CompiledGoFiles = out\n\t\t}\n\n\t\t// Extract the PkgPath from the package's ID.\n\t\tif i := strings.IndexByte(pkg.ID, ' '); i >= 0 {\n\t\t\tpkg.PkgPath = pkg.ID[:i]\n\t\t} else {\n\t\t\tpkg.PkgPath = pkg.ID\n\t\t}\n\n\t\tif pkg.PkgPath == \"unsafe\" {\n\t\t\tpkg.CompiledGoFiles = nil // ignore fake unsafe.go file (#59929)\n\t\t} else if len(pkg.CompiledGoFiles) == 0 {\n\t\t\t// Work around for pre-go.1.11 versions of go list.\n\t\t\t// TODO(matloob): they should be handled by the fallback.\n\t\t\t// Can we delete this?\n\t\t\tpkg.CompiledGoFiles = pkg.GoFiles\n\t\t}\n\n\t\t// Assume go list emits only absolute paths for Dir.\n\t\tif p.Dir != \"\" && !filepath.IsAbs(p.Dir) {\n\t\t\tlog.Fatalf(\"internal error: go list returned non-absolute Package.Dir: %s\", p.Dir)\n\t\t}\n\n\t\tif p.Export != \"\" && !filepath.IsAbs(p.Export) {\n\t\t\tpkg.ExportFile = filepath.Join(p.Dir, p.Export)\n\t\t} else {\n\t\t\tpkg.ExportFile = p.Export\n\t\t}\n\n\t\t// imports\n\t\t//\n\t\t// Imports contains the IDs of all imported packages.\n\t\t// ImportsMap records (path, ID) only where they differ.\n\t\tids := make(map[string]bool)\n\t\tfor _, id := range p.Imports {\n\t\t\tids[id] = true\n\t\t}\n\t\tpkg.Imports = make(map[string]*Package)\n\t\tfor path, id := range p.ImportMap {\n\t\t\tpkg.Imports[path] = &Package{ID: id} // non-identity import\n\t\t\tdelete(ids, id)\n\t\t}\n\t\tfor id := range ids {\n\t\t\tif id == \"C\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tpkg.Imports[id] = &Package{ID: id} // identity import\n\t\t}\n\t\tif !p.DepOnly {\n\t\t\tresponse.Roots = append(response.Roots, pkg.ID)\n\t\t}\n\n\t\t// Temporary work-around for golang/go#39986. Parse filenames out of\n\t\t// error messages. This happens if there are unrecoverable syntax\n\t\t// errors in the source, so we can't match on a specific error message.\n\t\t//\n\t\t// TODO(rfindley): remove this heuristic, in favor of considering\n\t\t// InvalidGoFiles from the list driver.\n\t\tif err := p.Error; err != nil && state.shouldAddFilenameFromError(p) {\n\t\t\taddFilenameFromPos := func(pos string) bool {\n\t\t\t\tsplit := strings.Split(pos, \":\")\n\t\t\t\tif len(split) < 1 {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tfilename := strings.TrimSpace(split[0])\n\t\t\t\tif filename == \"\" {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tif !filepath.IsAbs(filename) {\n\t\t\t\t\tfilename = filepath.Join(state.cfg.Dir, filename)\n\t\t\t\t}\n\t\t\t\tinfo, _ := os.Stat(filename)\n\t\t\t\tif info == nil {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tpkg.CompiledGoFiles = append(pkg.CompiledGoFiles, filename)\n\t\t\t\tpkg.GoFiles = append(pkg.GoFiles, filename)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tfound := addFilenameFromPos(err.Pos)\n\t\t\t// In some cases, go list only reports the error position in the\n\t\t\t// error text, not the error position. One such case is when the\n\t\t\t// file's package name is a keyword (see golang.org/issue/39763).\n\t\t\tif !found {\n\t\t\t\taddFilenameFromPos(err.Err)\n\t\t\t}\n\t\t}\n\n\t\tif p.Error != nil {\n\t\t\tmsg := strings.TrimSpace(p.Error.Err) // Trim to work around golang.org/issue/32363.\n\t\t\t// Address golang.org/issue/35964 by appending import stack to error message.\n\t\t\tif msg == \"import cycle not allowed\" && len(p.Error.ImportStack) != 0 {\n\t\t\t\tmsg += fmt.Sprintf(\": import stack: %v\", p.Error.ImportStack)\n\t\t\t}\n\t\t\tpkg.Errors = append(pkg.Errors, Error{\n\t\t\t\tPos:  p.Error.Pos,\n\t\t\t\tMsg:  msg,\n\t\t\t\tKind: ListError,\n\t\t\t})\n\t\t}\n\n\t\tpkgs[pkg.ID] = pkg\n\t}\n\n\tfor id, errs := range additionalErrors {\n\t\tif p, ok := pkgs[id]; ok {\n\t\t\tp.Errors = append(p.Errors, errs...)\n\t\t}\n\t}\n\tfor _, pkg := range pkgs {\n\t\tresponse.Packages = append(response.Packages, pkg)\n\t}\n\tsort.Slice(response.Packages, func(i, j int) bool { return response.Packages[i].ID < response.Packages[j].ID })\n\n\treturn response, nil\n}\n\nfunc (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool {\n\tif len(p.GoFiles) > 0 || len(p.CompiledGoFiles) > 0 {\n\t\treturn false\n\t}\n\n\tgoV, err := state.getGoVersion()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// On Go 1.14 and earlier, only add filenames from errors if the import stack is empty.\n\t// The import stack behaves differently for these versions than newer Go versions.\n\tif goV < 15 {\n\t\treturn len(p.Error.ImportStack) == 0\n\t}\n\n\t// On Go 1.15 and later, only parse filenames out of error if there's no import stack,\n\t// or the current package is at the top of the import stack. This is not guaranteed\n\t// to work perfectly, but should avoid some cases where files in errors don't belong to this\n\t// package.\n\treturn len(p.Error.ImportStack) == 0 || p.Error.ImportStack[len(p.Error.ImportStack)-1] == p.ImportPath\n}\n\n// getGoVersion returns the effective minor version of the go command.\nfunc (state *golistState) getGoVersion() (int, error) {\n\tstate.goVersionOnce.Do(func() {\n\t\tstate.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.runner)\n\t})\n\treturn state.goVersion, state.goVersionError\n}\n\n// getPkgPath finds the package path of a directory if it's relative to a root\n// directory.\nfunc (state *golistState) getPkgPath(dir string) (string, bool, error) {\n\tif !filepath.IsAbs(dir) {\n\t\tpanic(\"non-absolute dir passed to getPkgPath\")\n\t}\n\troots, err := state.determineRootDirs()\n\tif err != nil {\n\t\treturn \"\", false, err\n\t}\n\n\tfor rdir, rpath := range roots {\n\t\t// Make sure that the directory is in the module,\n\t\t// to avoid creating a path relative to another module.\n\t\tif !strings.HasPrefix(dir, rdir) {\n\t\t\tcontinue\n\t\t}\n\t\t// TODO(matloob): This doesn't properly handle symlinks.\n\t\tr, err := filepath.Rel(rdir, dir)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif rpath != \"\" {\n\t\t\t// We choose only one root even though the directory even it can belong in multiple modules\n\t\t\t// or GOPATH entries. This is okay because we only need to work with absolute dirs when a\n\t\t\t// file is missing from disk, for instance when gopls calls go/packages in an overlay.\n\t\t\t// Once the file is saved, gopls, or the next invocation of the tool will get the correct\n\t\t\t// result straight from golist.\n\t\t\t// TODO(matloob): Implement module tiebreaking?\n\t\t\treturn path.Join(rpath, filepath.ToSlash(r)), true, nil\n\t\t}\n\t\treturn filepath.ToSlash(r), true, nil\n\t}\n\treturn \"\", false, nil\n}\n\n// absJoin absolutizes and flattens the lists of files.\nfunc absJoin(dir string, fileses ...[]string) (res []string) {\n\tfor _, files := range fileses {\n\t\tfor _, file := range files {\n\t\t\tif !filepath.IsAbs(file) {\n\t\t\t\tfile = filepath.Join(dir, file)\n\t\t\t}\n\t\t\tres = append(res, file)\n\t\t}\n\t}\n\treturn res\n}\n\nfunc jsonFlag(cfg *Config, goVersion int) string {\n\tif goVersion < 19 {\n\t\treturn \"-json\"\n\t}\n\tvar fields []string\n\tadded := make(map[string]bool)\n\taddFields := func(fs ...string) {\n\t\tfor _, f := range fs {\n\t\t\tif !added[f] {\n\t\t\t\tadded[f] = true\n\t\t\t\tfields = append(fields, f)\n\t\t\t}\n\t\t}\n\t}\n\taddFields(\"Name\", \"ImportPath\", \"Error\") // These fields are always needed\n\tif cfg.Mode&NeedFiles != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 {\n\t\taddFields(\"Dir\", \"GoFiles\", \"IgnoredGoFiles\", \"IgnoredOtherFiles\", \"CFiles\",\n\t\t\t\"CgoFiles\", \"CXXFiles\", \"MFiles\", \"HFiles\", \"FFiles\", \"SFiles\",\n\t\t\t\"SwigFiles\", \"SwigCXXFiles\", \"SysoFiles\")\n\t\tif cfg.Tests {\n\t\t\taddFields(\"TestGoFiles\", \"XTestGoFiles\")\n\t\t}\n\t}\n\tif cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 {\n\t\t// CompiledGoFiles seems to be required for the test case TestCgoNoSyntax,\n\t\t// even when -compiled isn't passed in.\n\t\t// TODO(#52435): Should we make the test ask for -compiled, or automatically\n\t\t// request CompiledGoFiles in certain circumstances?\n\t\taddFields(\"Dir\", \"CompiledGoFiles\")\n\t}\n\tif cfg.Mode&NeedCompiledGoFiles != 0 {\n\t\taddFields(\"Dir\", \"CompiledGoFiles\", \"Export\")\n\t}\n\tif cfg.Mode&NeedImports != 0 {\n\t\t// When imports are requested, DepOnly is used to distinguish between packages\n\t\t// explicitly requested and transitive imports of those packages.\n\t\taddFields(\"DepOnly\", \"Imports\", \"ImportMap\")\n\t\tif cfg.Tests {\n\t\t\taddFields(\"TestImports\", \"XTestImports\")\n\t\t}\n\t}\n\tif cfg.Mode&NeedDeps != 0 {\n\t\taddFields(\"DepOnly\")\n\t}\n\tif usesExportData(cfg) {\n\t\t// Request Dir in the unlikely case Export is not absolute.\n\t\taddFields(\"Dir\", \"Export\")\n\t}\n\tif cfg.Mode&NeedForTest != 0 {\n\t\taddFields(\"ForTest\")\n\t}\n\tif cfg.Mode&needInternalDepsErrors != 0 {\n\t\taddFields(\"DepsErrors\")\n\t}\n\tif cfg.Mode&NeedModule != 0 {\n\t\taddFields(\"Module\")\n\t}\n\tif cfg.Mode&NeedEmbedFiles != 0 {\n\t\taddFields(\"EmbedFiles\")\n\t}\n\tif cfg.Mode&NeedEmbedPatterns != 0 {\n\t\taddFields(\"EmbedPatterns\")\n\t}\n\tif cfg.Mode&NeedTarget != 0 {\n\t\taddFields(\"Target\")\n\t}\n\treturn \"-json=\" + strings.Join(fields, \",\")\n}\n\nfunc golistargs(cfg *Config, words []string, goVersion int) []string {\n\tconst findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo\n\tfullargs := []string{\n\t\t\"-e\", jsonFlag(cfg, goVersion),\n\t\tfmt.Sprintf(\"-compiled=%t\", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypes|NeedTypesInfo|NeedTypesSizes) != 0),\n\t\tfmt.Sprintf(\"-test=%t\", cfg.Tests),\n\t\tfmt.Sprintf(\"-export=%t\", usesExportData(cfg)),\n\t\tfmt.Sprintf(\"-deps=%t\", cfg.Mode&NeedImports != 0),\n\t\t// go list doesn't let you pass -test and -find together,\n\t\t// probably because you'd just get the TestMain.\n\t\tfmt.Sprintf(\"-find=%t\", !cfg.Tests && cfg.Mode&findFlags == 0 && !usesExportData(cfg)),\n\t\t// VCS information is not needed when not printing Stale or StaleReason fields\n\t\t\"-buildvcs=false\",\n\t}\n\n\t// golang/go#60456: with go1.21 and later, go list serves pgo variants, which\n\t// can be costly to compute and may result in redundant processing for the\n\t// caller. Disable these variants. If someone wants to add e.g. a NeedPGO\n\t// mode flag, that should be a separate proposal.\n\tif goVersion >= 21 {\n\t\tfullargs = append(fullargs, \"-pgo=off\")\n\t}\n\n\tfullargs = append(fullargs, cfg.BuildFlags...)\n\tfullargs = append(fullargs, \"--\")\n\tfullargs = append(fullargs, words...)\n\treturn fullargs\n}\n\n// cfgInvocation returns an Invocation that reflects cfg's settings.\nfunc (state *golistState) cfgInvocation() gocommand.Invocation {\n\tcfg := state.cfg\n\treturn gocommand.Invocation{\n\t\tBuildFlags: cfg.BuildFlags,\n\t\tCleanEnv:   cfg.Env != nil,\n\t\tEnv:        cfg.Env,\n\t\tLogf:       cfg.Logf,\n\t\tWorkingDir: cfg.Dir,\n\t\tOverlay:    state.overlay,\n\t}\n}\n\n// invokeGo returns the stdout of a go command invocation.\nfunc (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, error) {\n\tcfg := state.cfg\n\n\tinv := state.cfgInvocation()\n\tinv.Verb = verb\n\tinv.Args = args\n\n\tstdout, stderr, friendlyErr, err := state.runner.RunRaw(cfg.Context, inv)\n\tif err != nil {\n\t\t// Check for 'go' executable not being found.\n\t\tif ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {\n\t\t\treturn nil, fmt.Errorf(\"'go list' driver requires 'go', but %s\", exec.ErrNotFound)\n\t\t}\n\n\t\texitErr, ok := err.(*exec.ExitError)\n\t\tif !ok {\n\t\t\t// Catastrophic error:\n\t\t\t// - context cancellation\n\t\t\treturn nil, fmt.Errorf(\"couldn't run 'go': %w\", err)\n\t\t}\n\n\t\t// Old go version?\n\t\tif strings.Contains(stderr.String(), \"flag provided but not defined\") {\n\t\t\treturn nil, goTooOldError{fmt.Errorf(\"unsupported version of go: %s: %s\", exitErr, stderr)}\n\t\t}\n\n\t\t// Related to #24854\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"unexpected directory layout\") {\n\t\t\treturn nil, friendlyErr\n\t\t}\n\n\t\t// Return an error if 'go list' failed due to missing tools in\n\t\t// $GOROOT/pkg/tool/$GOOS_$GOARCH (#69606).\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), `go: no such tool`) {\n\t\t\treturn nil, friendlyErr\n\t\t}\n\n\t\t// Is there an error running the C compiler in cgo? This will be reported in the \"Error\" field\n\t\t// and should be suppressed by go list -e.\n\t\t//\n\t\t// This condition is not perfect yet because the error message can include other error messages than runtime/cgo.\n\t\tisPkgPathRune := func(r rune) bool {\n\t\t\t// From https://golang.org/ref/spec#Import_declarations:\n\t\t\t//    Implementation restriction: A compiler may restrict ImportPaths to non-empty strings\n\t\t\t//    using only characters belonging to Unicode's L, M, N, P, and S general categories\n\t\t\t//    (the Graphic characters without spaces) and may also exclude the\n\t\t\t//    characters !\"#$%&'()*,:;<=>?[\\]^`{|} and the Unicode replacement character U+FFFD.\n\t\t\treturn unicode.IsOneOf([]*unicode.RangeTable{unicode.L, unicode.M, unicode.N, unicode.P, unicode.S}, r) &&\n\t\t\t\t!strings.ContainsRune(\"!\\\"#$%&'()*,:;<=>?[\\\\]^`{|}\\uFFFD\", r)\n\t\t}\n\t\t// golang/go#36770: Handle case where cmd/go prints module download messages before the error.\n\t\tmsg := stderr.String()\n\t\tfor strings.HasPrefix(msg, \"go: downloading\") {\n\t\t\tmsg = msg[strings.IndexRune(msg, '\\n')+1:]\n\t\t}\n\t\tif len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), \"# \") {\n\t\t\tmsg := msg[len(\"# \"):]\n\t\t\tif strings.HasPrefix(strings.TrimLeftFunc(msg, isPkgPathRune), \"\\n\") {\n\t\t\t\treturn stdout, nil\n\t\t\t}\n\t\t\t// Treat pkg-config errors as a special case (golang.org/issue/36770).\n\t\t\tif strings.HasPrefix(msg, \"pkg-config\") {\n\t\t\t\treturn stdout, nil\n\t\t\t}\n\t\t}\n\n\t\t// This error only appears in stderr. See golang.org/cl/166398 for a fix in go list to show\n\t\t// the error in the Err section of stdout in case -e option is provided.\n\t\t// This fix is provided for backwards compatibility.\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"named files must be .go files\") {\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": \"command-line-arguments\",\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\tstrings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Similar to the previous error, but currently lacks a fix in Go.\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"named files must all be in one directory\") {\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": \"command-line-arguments\",\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\tstrings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Backwards compatibility for Go 1.11 because 1.12 and 1.13 put the directory in the ImportPath.\n\t\t// If the package doesn't exist, put the absolute path of the directory into the error message,\n\t\t// as Go 1.13 list does.\n\t\tconst noSuchDirectory = \"no such directory\"\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), noSuchDirectory) {\n\t\t\terrstr := stderr.String()\n\t\t\tabspath := strings.TrimSpace(errstr[strings.Index(errstr, noSuchDirectory)+len(noSuchDirectory):])\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": %q,\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\tabspath, strings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Workaround for #29280: go list -e has incorrect behavior when an ad-hoc package doesn't exist.\n\t\t// Note that the error message we look for in this case is different that the one looked for above.\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"no such file or directory\") {\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": \"command-line-arguments\",\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\tstrings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Workaround for #34273. go list -e with GO111MODULE=on has incorrect behavior when listing a\n\t\t// directory outside any module.\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"outside available modules\") {\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": %q,\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\t// TODO(matloob): command-line-arguments isn't correct here.\n\t\t\t\t\"command-line-arguments\", strings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Another variation of the previous error\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"outside module root\") {\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": %q,\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\t// TODO(matloob): command-line-arguments isn't correct here.\n\t\t\t\t\"command-line-arguments\", strings.Trim(stderr.String(), \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Workaround for an instance of golang.org/issue/26755: go list -e  will return a non-zero exit\n\t\t// status if there's a dependency on a package that doesn't exist. But it should return\n\t\t// a zero exit status and set an error on that package.\n\t\tif len(stderr.String()) > 0 && strings.Contains(stderr.String(), \"no Go files in\") {\n\t\t\t// Don't clobber stdout if `go list` actually returned something.\n\t\t\tif len(stdout.String()) > 0 {\n\t\t\t\treturn stdout, nil\n\t\t\t}\n\t\t\t// try to extract package name from string\n\t\t\tstderrStr := stderr.String()\n\t\t\tvar importPath string\n\t\t\tcolon := strings.Index(stderrStr, \":\")\n\t\t\tif colon > 0 && strings.HasPrefix(stderrStr, \"go build \") {\n\t\t\t\timportPath = stderrStr[len(\"go build \"):colon]\n\t\t\t}\n\t\t\toutput := fmt.Sprintf(`{\"ImportPath\": %q,\"Incomplete\": true,\"Error\": {\"Pos\": \"\",\"Err\": %q}}`,\n\t\t\t\timportPath, strings.Trim(stderrStr, \"\\n\"))\n\t\t\treturn bytes.NewBufferString(output), nil\n\t\t}\n\n\t\t// Export mode entails a build.\n\t\t// If that build fails, errors appear on stderr\n\t\t// (despite the -e flag) and the Export field is blank.\n\t\t// Do not fail in that case.\n\t\t// The same is true if an ad-hoc package given to go list doesn't exist.\n\t\t// TODO(matloob): Remove these once we can depend on go list to exit with a zero status with -e even when\n\t\t// packages don't exist or a build fails.\n\t\tif !usesExportData(cfg) && !containsGoFile(args) {\n\t\t\treturn nil, friendlyErr\n\t\t}\n\t}\n\treturn stdout, nil\n}\n\nfunc containsGoFile(s []string) bool {\n\tfor _, f := range s {\n\t\tif strings.HasSuffix(f, \".go\") {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc cmdDebugStr(cmd *exec.Cmd) string {\n\tenv := make(map[string]string)\n\tfor _, kv := range cmd.Env {\n\t\tsplit := strings.SplitN(kv, \"=\", 2)\n\t\tk, v := split[0], split[1]\n\t\tenv[k] = v\n\t}\n\n\tvar args []string\n\tfor _, arg := range cmd.Args {\n\t\tquoted := strconv.Quote(arg)\n\t\tif quoted[1:len(quoted)-1] != arg || strings.Contains(arg, \" \") {\n\t\t\targs = append(args, quoted)\n\t\t} else {\n\t\t\targs = append(args, arg)\n\t\t}\n\t}\n\treturn fmt.Sprintf(\"GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v\", env[\"GOROOT\"], env[\"GOPATH\"], env[\"GO111MODULE\"], env[\"GOPROXY\"], env[\"PWD\"], strings.Join(args, \" \"))\n}\n\n// getSizesForArgs queries 'go list' for the appropriate\n// Compiler and GOARCH arguments to pass to [types.SizesFor].\nfunc getSizesForArgs(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) {\n\tinv.Verb = \"list\"\n\tinv.Args = []string{\"-f\", \"{{context.GOARCH}} {{context.Compiler}}\", \"--\", \"unsafe\"}\n\tstdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)\n\tvar goarch, compiler string\n\tif rawErr != nil {\n\t\trawErrMsg := rawErr.Error()\n\t\tif strings.Contains(rawErrMsg, \"cannot find main module\") ||\n\t\t\tstrings.Contains(rawErrMsg, \"go.mod file not found\") {\n\t\t\t// User's running outside of a module.\n\t\t\t// All bets are off. Get GOARCH and guess compiler is gc.\n\t\t\t// TODO(matloob): Is this a problem in practice?\n\t\t\tinv.Verb = \"env\"\n\t\t\tinv.Args = []string{\"GOARCH\"}\n\t\t\tenvout, enverr := gocmdRunner.Run(ctx, inv)\n\t\t\tif enverr != nil {\n\t\t\t\treturn \"\", \"\", enverr\n\t\t\t}\n\t\t\tgoarch = strings.TrimSpace(envout.String())\n\t\t\tcompiler = \"gc\"\n\t\t} else if friendlyErr != nil {\n\t\t\treturn \"\", \"\", friendlyErr\n\t\t} else {\n\t\t\t// This should be unreachable, but be defensive\n\t\t\t// in case RunRaw's error results are inconsistent.\n\t\t\treturn \"\", \"\", rawErr\n\t\t}\n\t} else {\n\t\tfields := strings.Fields(stdout.String())\n\t\tif len(fields) < 2 {\n\t\t\treturn \"\", \"\", fmt.Errorf(\"could not parse GOARCH and Go compiler in format \\\"<GOARCH> <compiler>\\\":\\nstdout: <<%s>>\\nstderr: <<%s>>\",\n\t\t\t\tstdout.String(), stderr.String())\n\t\t}\n\t\tgoarch = fields[0]\n\t\tcompiler = fields[1]\n\t}\n\treturn compiler, goarch, nil\n}\n"
  },
  {
    "path": "go/packages/golist_overlay.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\nimport (\n\t\"encoding/json\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n)\n\n// determineRootDirs returns a mapping from absolute directories that could\n// contain code to their corresponding import path prefixes.\nfunc (state *golistState) determineRootDirs() (map[string]string, error) {\n\tenv, err := state.getEnv()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif env[\"GOMOD\"] != \"\" {\n\t\tstate.rootsOnce.Do(func() {\n\t\t\tstate.rootDirs, state.rootDirsError = state.determineRootDirsModules()\n\t\t})\n\t} else {\n\t\tstate.rootsOnce.Do(func() {\n\t\t\tstate.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH()\n\t\t})\n\t}\n\treturn state.rootDirs, state.rootDirsError\n}\n\nfunc (state *golistState) determineRootDirsModules() (map[string]string, error) {\n\t// List all of the modules--the first will be the directory for the main\n\t// module. Any replaced modules will also need to be treated as roots.\n\t// Editing files in the module cache isn't a great idea, so we don't\n\t// plan to ever support that.\n\tout, err := state.invokeGo(\"list\", \"-m\", \"-json\", \"all\")\n\tif err != nil {\n\t\t// 'go list all' will fail if we're outside of a module and\n\t\t// GO111MODULE=on. Try falling back without 'all'.\n\t\tvar innerErr error\n\t\tout, innerErr = state.invokeGo(\"list\", \"-m\", \"-json\")\n\t\tif innerErr != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\troots := map[string]string{}\n\tmodules := map[string]string{}\n\tvar i int\n\tfor dec := json.NewDecoder(out); dec.More(); {\n\t\tmod := new(gocommand.ModuleJSON)\n\t\tif err := dec.Decode(mod); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif mod.Dir != \"\" && mod.Path != \"\" {\n\t\t\t// This is a valid module; add it to the map.\n\t\t\tabsDir, err := state.cfg.abs(mod.Dir)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tmodules[absDir] = mod.Path\n\t\t\t// The first result is the main module.\n\t\t\tif i == 0 || mod.Replace != nil && mod.Replace.Path != \"\" {\n\t\t\t\troots[absDir] = mod.Path\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n\treturn roots, nil\n}\n\nfunc (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {\n\tm := map[string]string{}\n\tfor _, dir := range filepath.SplitList(state.mustGetEnv()[\"GOPATH\"]) {\n\t\tabsDir, err := filepath.Abs(dir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tm[filepath.Join(absDir, \"src\")] = \"\"\n\t}\n\treturn m, nil\n}\n"
  },
  {
    "path": "go/packages/gopackages/main.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The gopackages command is a diagnostic tool that demonstrates\n// how to use golang.org/x/tools/go/packages to load, parse,\n// type-check, and print one or more Go packages.\n// Its precise output is unspecified and may change.\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/drivertest\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\nfunc main() {\n\tdrivertest.RunIfChild()\n\ttool.Main(context.Background(), &application{Mode: \"imports\"}, os.Args[1:])\n}\n\ntype application struct {\n\t// Embed the basic profiling flags supported by the tool package\n\ttool.Profile\n\n\tDeps       bool            `flag:\"deps\" help:\"show dependencies too\"`\n\tTest       bool            `flag:\"test\" help:\"include any tests implied by the patterns\"`\n\tMode       string          `flag:\"mode\" help:\"mode (one of files, imports, types, syntax, allsyntax)\"`\n\tTags       string          `flag:\"tags\" help:\"comma-separated list of extra build tags (see: go help buildconstraint)\"`\n\tPrivate    bool            `flag:\"private\" help:\"show non-exported declarations too (if -mode=syntax)\"`\n\tPrintJSON  bool            `flag:\"json\" help:\"print package in JSON form\"`\n\tBuildFlags stringListValue `flag:\"buildflag\" help:\"pass argument to underlying build system (may be repeated)\"`\n\tDriver     bool            `flag:\"driver\" help:\"use golist passthrough driver (for debugging driver issues)\"`\n}\n\n// Name implements tool.Application returning the binary name.\nfunc (app *application) Name() string { return \"gopackages\" }\n\n// Usage implements tool.Application returning empty extra argument usage.\nfunc (app *application) Usage() string { return \"package...\" }\n\n// ShortHelp implements tool.Application returning the main binary help.\nfunc (app *application) ShortHelp() string {\n\treturn \"gopackages loads, parses, type-checks, and prints one or more Go packages.\"\n}\n\n// DetailedHelp implements tool.Application returning the main binary help.\nfunc (app *application) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nPackages are specified using the notation of \"go list\",\nor other underlying build system.\n\nThe mode flag determines how much information is computed and printed\nfor the specified packages. In order of increasing computational cost,\nthe legal values are:\n\n -mode=files     shows only the names of the packages' files.\n -mode=imports   also shows the imports. (This is the default.)\n -mode=types     loads the compiler's export data and displays the\n                 type of each exported declaration.\n -mode=syntax    parses and type checks syntax trees for the initial\n                 packages. (With the -private flag, the types of\n                 non-exported declarations are shown too.)\n                 Type information for dependencies is obtained from\n                 compiler export data.\n -mode=allsyntax is like -mode=syntax but applied to all dependencies.\n\nFlags:\n`)\n\tf.PrintDefaults()\n}\n\n// Run takes the args after flag processing and performs the specified query.\nfunc (app *application) Run(ctx context.Context, args ...string) error {\n\tif len(args) == 0 {\n\t\treturn tool.CommandLineErrorf(\"not enough arguments\")\n\t}\n\n\tenv := os.Environ()\n\tif app.Driver {\n\t\tenv = append(env, drivertest.Env(log.Default())...)\n\t}\n\n\t// Load, parse, and type-check the packages named on the command line.\n\tcfg := &packages.Config{\n\t\tMode:       packages.LoadSyntax,\n\t\tTests:      app.Test,\n\t\tBuildFlags: append([]string{\"-tags=\" + app.Tags}, app.BuildFlags...),\n\t\tEnv:        env,\n\t}\n\n\t// -mode flag\n\tswitch strings.ToLower(app.Mode) {\n\tcase \"files\":\n\t\tcfg.Mode = packages.LoadFiles\n\tcase \"imports\":\n\t\tcfg.Mode = packages.LoadImports\n\tcase \"types\":\n\t\tcfg.Mode = packages.LoadTypes\n\tcase \"syntax\":\n\t\tcfg.Mode = packages.LoadSyntax\n\tcase \"allsyntax\":\n\t\tcfg.Mode = packages.LoadAllSyntax\n\tdefault:\n\t\treturn tool.CommandLineErrorf(\"invalid mode: %s\", app.Mode)\n\t}\n\tcfg.Mode |= packages.NeedModule\n\n\tlpkgs, err := packages.Load(cfg, args...)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// -deps: print dependencies too.\n\tif app.Deps {\n\t\t// We can't use packages.All because\n\t\t// we need an ordered traversal.\n\t\tvar all []*packages.Package // postorder\n\t\tseen := make(map[*packages.Package]bool)\n\t\tvar visit func(*packages.Package)\n\t\tvisit = func(lpkg *packages.Package) {\n\t\t\tif !seen[lpkg] {\n\t\t\t\tseen[lpkg] = true\n\n\t\t\t\t// visit imports\n\t\t\t\tvar importPaths []string\n\t\t\t\tfor path := range lpkg.Imports {\n\t\t\t\t\timportPaths = append(importPaths, path)\n\t\t\t\t}\n\t\t\t\tsort.Strings(importPaths) // for determinism\n\t\t\t\tfor _, path := range importPaths {\n\t\t\t\t\tvisit(lpkg.Imports[path])\n\t\t\t\t}\n\n\t\t\t\tall = append(all, lpkg)\n\t\t\t}\n\t\t}\n\t\tfor _, lpkg := range lpkgs {\n\t\t\tvisit(lpkg)\n\t\t}\n\t\tlpkgs = all\n\t}\n\n\tfor _, lpkg := range lpkgs {\n\t\tapp.print(lpkg)\n\t}\n\treturn nil\n}\n\nfunc (app *application) print(lpkg *packages.Package) {\n\tif app.PrintJSON {\n\t\tdata, _ := json.MarshalIndent(lpkg, \"\", \"\\t\")\n\t\tos.Stdout.Write(data)\n\t\treturn\n\t}\n\t// title\n\tvar kind string\n\t// TODO(matloob): If IsTest is added back print \"test command\" or\n\t// \"test package\" for packages with IsTest == true.\n\tif lpkg.Name == \"main\" {\n\t\tkind += \"command\"\n\t} else {\n\t\tkind += \"package\"\n\t}\n\tfmt.Printf(\"Go %s %q:\\n\", kind, lpkg.ID) // unique ID\n\tif mod := lpkg.Module; mod != nil {\n\t\tfmt.Printf(\"\\tmodule %s@%s\\n\", mod.Path, mod.Version)\n\t}\n\tfmt.Printf(\"\\tpackage %s\\n\", lpkg.Name)\n\n\t// characterize type info\n\tif lpkg.Types == nil {\n\t\tfmt.Printf(\"\\thas no exported type info\\n\")\n\t} else if !lpkg.Types.Complete() {\n\t\tfmt.Printf(\"\\thas incomplete exported type info\\n\")\n\t} else if len(lpkg.Syntax) == 0 {\n\t\tfmt.Printf(\"\\thas complete exported type info\\n\")\n\t} else {\n\t\tfmt.Printf(\"\\thas complete exported type info and typed ASTs\\n\")\n\t}\n\tif lpkg.Types != nil && lpkg.IllTyped && len(lpkg.Errors) == 0 {\n\t\tfmt.Printf(\"\\thas an error among its dependencies\\n\")\n\t}\n\n\t// source files\n\tfor _, src := range lpkg.GoFiles {\n\t\tfmt.Printf(\"\\tfile %s\\n\", src)\n\t}\n\n\t// imports\n\tvar lines []string\n\tfor importPath, imp := range lpkg.Imports {\n\t\tvar line string\n\t\tif imp.ID == importPath {\n\t\t\tline = fmt.Sprintf(\"\\timport %q\", importPath)\n\t\t} else {\n\t\t\tline = fmt.Sprintf(\"\\timport %q => %q\", importPath, imp.ID)\n\t\t}\n\t\tlines = append(lines, line)\n\t}\n\tsort.Strings(lines)\n\tfor _, line := range lines {\n\t\tfmt.Println(line)\n\t}\n\n\t// errors\n\tfor _, err := range lpkg.Errors {\n\t\tfmt.Printf(\"\\t%s\\n\", err)\n\t}\n\n\t// types of package members\n\tif lpkg.Types != nil {\n\t\tqual := types.RelativeTo(lpkg.Types)\n\t\tscope := lpkg.Types.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\tobj := scope.Lookup(name)\n\t\t\tif !obj.Exported() && !app.Private {\n\t\t\t\tcontinue // skip unexported names\n\t\t\t}\n\n\t\t\tfmt.Printf(\"\\t%s\\n\", types.ObjectString(obj, qual))\n\t\t\tif _, ok := obj.(*types.TypeName); ok {\n\t\t\t\tfor _, meth := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {\n\t\t\t\t\tif !meth.Obj().Exported() && !app.Private {\n\t\t\t\t\t\tcontinue // skip unexported names\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Printf(\"\\t%s\\n\", types.SelectionString(meth, qual))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfmt.Println()\n}\n\n// stringListValue is a flag.Value that accumulates strings.\n// e.g. --flag=one --flag=two would produce []string{\"one\", \"two\"}.\ntype stringListValue []string\n\nfunc (ss *stringListValue) Get() any { return []string(*ss) }\n\nfunc (ss *stringListValue) String() string { return fmt.Sprintf(\"%q\", *ss) }\n\nfunc (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }\n"
  },
  {
    "path": "go/packages/internal/linecount/linecount.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The linecount command shows the number of lines of code in a set of\n// Go packages plus their dependencies. It serves as a working\n// illustration of the [packages.Load] operation.\n//\n// Example: show gopls' total source line count, and its breakdown\n// between gopls, x/tools, and the std go/* packages. (The balance\n// comes from other std packages, other x/ repos, and external\n// dependencies.)\n//\n//\t$ linecount -mode=total ./gopls\n//\t752124\n//\t$ linecount -mode=total -module=golang.org/x/tools/gopls ./gopls\n//\t103519\n//\t$ linecount -mode=total -module=golang.org/x/tools ./gopls\n//\t99504\n//\t$ linecount -mode=total -prefix=go -module=std ./gopls\n//\t47502\n//\n// Example: show the top 5 modules contributing to gopls' source line count:\n//\n//\t$ linecount -mode=module ./gopls | head -n 5\n//\t440274\tstd\n//\t103519\tgolang.org/x/tools/gopls\n//\t99504\tgolang.org/x/tools\n//\t40220\thonnef.co/go/tools\n//\t17707\tgolang.org/x/text\n//\n// Example: show the top 3 largest files in the gopls module:\n//\n//\t$ linecount -mode=file -module=golang.org/x/tools/gopls ./gopls | head -n 3\n//\t6841\tgopls/internal/protocol/tsprotocol.go\n//\t3769\tgopls/internal/golang/completion/completion.go\n//\t2202\tgopls/internal/cache/snapshot.go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"path\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/packages\"\n)\n\n// TODO(adonovan): filters:\n// - exclude generated files (-generated=false)\n// - exclude non-CompiledGoFiles\n// - include OtherFiles (asm, etc)\n// - include tests (needs care to avoid double counting)\n\nfunc usage() {\n\t// See https://go.dev/issue/63659.\n\tfmt.Fprintf(os.Stderr, \"Usage: linecount [flags] packages...\\n\")\n\tflag.PrintDefaults()\n\tfmt.Fprintf(os.Stderr, `\nDocs: go doc golang.org/x/tools/go/packages/internal/linecount\nhttps://pkg.go.dev/golang.org/x/tools/go/packages/internal/linecount\n`)\n}\n\nfunc main() {\n\t// Parse command line.\n\tlog.SetPrefix(\"linecount: \")\n\tlog.SetFlags(0)\n\tvar (\n\t\tmode       = flag.String(\"mode\", \"file\", \"group lines by 'module', 'package', or 'file', or show only 'total'\")\n\t\tprefix     = flag.String(\"prefix\", \"\", \"count files only in packages whose path has the specified prefix\")\n\t\tonlyModule = flag.String(\"module\", \"\", \"count files only in the specified module\")\n\t\tnonblank   = flag.Bool(\"nonblank\", false, \"count only non-comment, non-blank lines\")\n\t)\n\tflag.Usage = usage\n\tflag.Parse()\n\tif len(flag.Args()) == 0 {\n\t\tusage()\n\t\tos.Exit(1)\n\t}\n\n\t// Load packages.\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedModule,\n\t}\n\tpkgs, err := packages.Load(cfg, flag.Args()...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tos.Exit(1)\n\t}\n\n\t// Read files and count lines.\n\tvar (\n\t\tmu        sync.Mutex\n\t\tbyFile    = make(map[string]int)\n\t\tbyPackage = make(map[string]int)\n\t\tbyModule  = make(map[string]int)\n\t)\n\tvar g errgroup.Group\n\tg.SetLimit(20) // file system parallelism level\n\tpackages.Visit(pkgs, nil, func(p *packages.Package) {\n\t\tpkgpath := p.PkgPath\n\t\tmodule := \"std\"\n\t\tif p.Module != nil {\n\t\t\tmodule = p.Module.Path\n\t\t}\n\t\tif *prefix != \"\" && !within(pkgpath, path.Clean(*prefix)) {\n\t\t\treturn\n\t\t}\n\t\tif *onlyModule != \"\" && module != *onlyModule {\n\t\t\treturn\n\t\t}\n\t\tfor _, f := range p.GoFiles {\n\t\t\tg.Go(func() error {\n\t\t\t\tdata, err := os.ReadFile(f)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tn := count(*nonblank, data)\n\n\t\t\t\tmu.Lock()\n\t\t\t\tbyFile[f] = n\n\t\t\t\tbyPackage[pkgpath] += n\n\t\t\t\tbyModule[module] += n\n\t\t\t\tmu.Unlock()\n\n\t\t\t\treturn nil\n\t\t\t})\n\t\t}\n\t})\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Display the result.\n\tswitch *mode {\n\tcase \"file\", \"package\", \"module\":\n\t\tvar m map[string]int\n\t\tswitch *mode {\n\t\tcase \"file\":\n\t\t\tm = byFile\n\t\tcase \"package\":\n\t\t\tm = byPackage\n\t\tcase \"module\":\n\t\t\tm = byModule\n\t\t}\n\t\ttype item struct {\n\t\t\tname  string\n\t\t\tcount int\n\t\t}\n\t\tvar items []item\n\t\tfor name, count := range m {\n\t\t\titems = append(items, item{name, count})\n\t\t}\n\t\tslices.SortFunc(items, func(x, y item) int {\n\t\t\treturn -cmp.Compare(x.count, y.count)\n\t\t})\n\t\tfor _, item := range items {\n\t\t\tfmt.Printf(\"%d\\t%s\\n\", item.count, item.name)\n\t\t}\n\n\tcase \"total\":\n\t\ttotal := 0\n\t\tfor _, n := range byFile {\n\t\t\ttotal += n\n\t\t}\n\t\tfmt.Printf(\"%d\\n\", total)\n\n\tdefault:\n\t\tlog.Fatalf(\"invalid -mode %q (want file, package, module, or total)\", *mode)\n\t}\n}\n\nfunc within(file, dir string) bool {\n\treturn file == dir ||\n\t\tstrings.HasPrefix(file, dir) && file[len(dir)] == os.PathSeparator\n}\n\n// count counts lines, or non-comment non-blank lines.\nfunc count(nonblank bool, src []byte) int {\n\tif nonblank {\n\t\t// Count distinct lines containing tokens.\n\t\tvar (\n\t\t\tfset     = token.NewFileSet()\n\t\t\tf        = fset.AddFile(\"\", fset.Base(), len(src))\n\t\t\tprevLine = 0\n\t\t\tcount    = 0\n\t\t\tscan     scanner.Scanner\n\t\t)\n\t\tscan.Init(f, src, nil, 0)\n\t\tfor {\n\t\t\tpos, tok, _ := scan.Scan()\n\t\t\tif tok == token.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// This may be slow because it binary\n\t\t\t// searches the newline offset table.\n\t\t\tline := f.PositionFor(pos, false).Line // ignore //line directives\n\t\t\tif line > prevLine {\n\t\t\t\tprevLine = line\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t\treturn count\n\t}\n\n\t// Count all lines.\n\treturn bytes.Count(src, []byte(\"\\n\"))\n}\n"
  },
  {
    "path": "go/packages/internal/nodecount/nodecount.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The nodecount program illustrates the use of packages.Load to print\n// the frequency of occurrence of each type of syntax node among the\n// selected packages.\n//\n// Example usage:\n//\n//\t$ nodecount golang.org/x/tools/... std\n//\n// A typical distribution is 40% identifiers, 10% literals, 8%\n// selectors, and 6% calls; around 3% each of BinaryExpr, BlockStmt,\n// AssignStmt, Field, and Comment; and the rest accounting for 20%.\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"log\"\n\t\"reflect\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\nfunc main() {\n\tflag.Parse()\n\n\t// Parse specified packages.\n\tconfig := packages.Config{\n\t\tMode:  packages.NeedSyntax | packages.NeedFiles,\n\t\tTests: true,\n\t}\n\tpkgs, err := packages.Load(&config, flag.Args()...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Count each type of syntax node.\n\tvar (\n\t\tbyType = make(map[reflect.Type]int)\n\t\ttotal  int\n\t)\n\tpackages.Visit(pkgs, nil, func(p *packages.Package) {\n\t\tfor _, f := range p.Syntax {\n\t\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\t\tif n != nil {\n\t\t\t\t\tbyType[reflect.TypeOf(n)]++\n\t\t\t\t\ttotal++\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t})\n\n\t// Print results (percent, count, type) in descending order.\n\tvar types []reflect.Type\n\tfor t := range byType {\n\t\ttypes = append(types, t)\n\t}\n\tsort.Slice(types, func(i, j int) bool {\n\t\treturn byType[types[i]] > byType[types[j]]\n\t})\n\tfor _, t := range types {\n\t\tpercent := 100 * float64(byType[t]) / float64(total)\n\t\tfmt.Printf(\"%6.2f%%\\t%8d\\t%s\\n\", percent, byType[t], t)\n\t}\n}\n"
  },
  {
    "path": "go/packages/loadmode_string.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nvar modes = [...]struct {\n\tmode LoadMode\n\tname string\n}{\n\t{NeedName, \"NeedName\"},\n\t{NeedFiles, \"NeedFiles\"},\n\t{NeedCompiledGoFiles, \"NeedCompiledGoFiles\"},\n\t{NeedImports, \"NeedImports\"},\n\t{NeedDeps, \"NeedDeps\"},\n\t{NeedExportFile, \"NeedExportFile\"},\n\t{NeedTypes, \"NeedTypes\"},\n\t{NeedSyntax, \"NeedSyntax\"},\n\t{NeedTypesInfo, \"NeedTypesInfo\"},\n\t{NeedTypesSizes, \"NeedTypesSizes\"},\n\t{NeedForTest, \"NeedForTest\"},\n\t{NeedModule, \"NeedModule\"},\n\t{NeedEmbedFiles, \"NeedEmbedFiles\"},\n\t{NeedEmbedPatterns, \"NeedEmbedPatterns\"},\n\t{NeedTarget, \"NeedTarget\"},\n}\n\nfunc (mode LoadMode) String() string {\n\tif mode == 0 {\n\t\treturn \"LoadMode(0)\"\n\t}\n\tvar out []string\n\t// named bits\n\tfor _, item := range modes {\n\t\tif (mode & item.mode) != 0 {\n\t\t\tmode ^= item.mode\n\t\t\tout = append(out, item.name)\n\t\t}\n\t}\n\t// unnamed residue\n\tif mode != 0 {\n\t\tif out == nil {\n\t\t\treturn fmt.Sprintf(\"LoadMode(%#x)\", int(mode))\n\t\t}\n\t\tout = append(out, fmt.Sprintf(\"%#x\", int(mode)))\n\t}\n\tif len(out) == 1 {\n\t\treturn out[0]\n\t}\n\treturn \"(\" + strings.Join(out, \"|\") + \")\"\n}\n"
  },
  {
    "path": "go/packages/overlay_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages_test\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"slices\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/packagestest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nconst (\n\tcommonMode = packages.NeedName | packages.NeedFiles |\n\t\tpackages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedSyntax\n\teverythingMode = commonMode | packages.NeedDeps | packages.NeedTypes |\n\t\tpackages.NeedTypesSizes\n)\n\nfunc TestOverlayChangesPackageName(t *testing.T) {\n\ttestAllOrModulesParallel(t, testOverlayChangesPackageName)\n}\nfunc testOverlayChangesPackageName(t *testing.T, exporter packagestest.Exporter) {\n\tlog.SetFlags(log.Lshortfile)\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a.go\": \"package foo\\nfunc f(){}\\n\",\n\t\t},\n\t\tOverlay: map[string][]byte{\n\t\t\t\"a.go\": []byte(\"package foox\\nfunc f(){}\\n\"),\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = packages.NeedName\n\n\tinitial, err := packages.Load(exported.Config,\n\t\tfilepath.Dir(exported.File(\"fake\", \"a.go\")))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load: %v\", err)\n\t}\n\tif len(initial) != 1 || initial[0].ID != \"fake\" || initial[0].Name != \"foox\" {\n\t\tt.Fatalf(\"got %v, expected [fake]\", initial)\n\t}\n\tif len(initial[0].Errors) != 0 {\n\t\tt.Fatalf(\"got %v, expected no errors\", initial[0].Errors)\n\t}\n\tlog.SetFlags(0)\n}\nfunc TestOverlayChangesBothPackageNames(t *testing.T) {\n\ttestAllOrModulesParallel(t, testOverlayChangesBothPackageNames)\n}\nfunc testOverlayChangesBothPackageNames(t *testing.T, exporter packagestest.Exporter) {\n\tlog.SetFlags(log.Lshortfile)\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a.go\":      \"package foo\\nfunc g(){}\\n\",\n\t\t\t\"a_test.go\": \"package foo\\nfunc f(){}\\n\",\n\t\t},\n\t\tOverlay: map[string][]byte{\n\t\t\t\"a.go\":      []byte(\"package foox\\nfunc g(){}\\n\"),\n\t\t\t\"a_test.go\": []byte(\"package foox\\nfunc f(){}\\n\"),\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = commonMode\n\n\tinitial, err := packages.Load(exported.Config,\n\t\tfilepath.Dir(exported.File(\"fake\", \"a.go\")))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load: %v\", err)\n\t}\n\tif len(initial) != 3 {\n\t\tt.Errorf(\"got %d packages, expected 3\", len(initial))\n\t}\n\twant := []struct {\n\t\tid, name string\n\t\tcount    int\n\t}{\n\t\t{\"fake\", \"foox\", 1},\n\t\t{\"fake [fake.test]\", \"foox\", 2},\n\t\t{\"fake.test\", \"main\", 1},\n\t}\n\tif len(initial) != 3 {\n\t\tt.Fatalf(\"expected 3 packages, got %v\", len(initial))\n\t}\n\tfor i := range 3 {\n\t\tif ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {\n\t\t\tt.Errorf(\"%d: got {%s %s %d}, expected %v\", i, initial[i].ID,\n\t\t\t\tinitial[i].Name, len(initial[i].Syntax), want[i])\n\t\t}\n\t\tif len(initial[i].Errors) != 0 {\n\t\t\tt.Errorf(\"%d: got %v, expected no errors\", i, initial[i].Errors)\n\t\t}\n\t}\n\tlog.SetFlags(0)\n}\nfunc TestOverlayChangesTestPackageName(t *testing.T) {\n\ttestAllOrModulesParallel(t, testOverlayChangesTestPackageName)\n}\nfunc testOverlayChangesTestPackageName(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a_test.go\": \"package foo\\nfunc f(){}\\n\",\n\t\t},\n\t\tOverlay: map[string][]byte{\n\t\t\t\"a_test.go\": []byte(\"package foox\\nfunc f(){}\\n\"),\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = commonMode\n\n\tinitial, err := packages.Load(exported.Config,\n\t\tfilepath.Dir(exported.File(\"fake\", \"a_test.go\")))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load: %v\", err)\n\t}\n\tif len(initial) != 3 {\n\t\tt.Errorf(\"got %d packages, expected 3\", len(initial))\n\t}\n\twant := []struct {\n\t\tid, name string\n\t\tcount    int\n\t}{\n\t\t{\"fake\", \"foox\", 0},\n\t\t{\"fake [fake.test]\", \"foox\", 1},\n\t\t{\"fake.test\", \"main\", 1},\n\t}\n\tif len(initial) != 3 {\n\t\tt.Fatalf(\"expected 3 packages, got %v\", len(initial))\n\t}\n\tfor i := range 3 {\n\t\tif ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {\n\t\t\tt.Errorf(\"got {%s %s %d}, expected %v\", initial[i].ID,\n\t\t\t\tinitial[i].Name, len(initial[i].Syntax), want[i])\n\t\t}\n\t}\n\tif len(initial[0].Errors) != 0 {\n\t\tt.Fatalf(\"got %v, expected no errors\", initial[0].Errors)\n\t}\n\tlog.SetFlags(0)\n}\n\nfunc checkPkg(t *testing.T, p *packages.Package, id, name string, syntax int) bool {\n\tt.Helper()\n\tif p.ID == id && p.Name == name && len(p.Syntax) == syntax {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc TestOverlayXTests(t *testing.T) {\n\ttestAllOrModulesParallel(t, testOverlayXTests)\n}\n\n// This test checks the behavior of go/packages.Load with an overlaid\n// x test. The source of truth is the go/packages.Load results for the\n// exact same package, just on-disk.\nfunc testOverlayXTests(t *testing.T, exporter packagestest.Exporter) {\n\tconst aFile = `package a; const C = \"C\"; func Hello() {}`\n\tconst aTestVariant = `package a\n\nimport \"testing\"\n\nconst TestC = \"test\" + C\n\nfunc TestHello(){\n\tHello()\n}`\n\tconst aXTest = `package a_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/fake/a\"\n)\n\nconst xTestC = \"x\" + a.C\n\nfunc TestHello(t *testing.T) {\n\ta.Hello()\n}`\n\n\t// First, get the source of truth by loading the package, all on disk.\n\tonDisk := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":        aFile,\n\t\t\t\"a/a_test.go\":   aTestVariant,\n\t\t\t\"a/a_x_test.go\": aXTest,\n\t\t},\n\t}})\n\tdefer onDisk.Cleanup()\n\n\tonDisk.Config.Mode = commonMode\n\tonDisk.Config.Tests = true\n\tonDisk.Config.Mode = packages.LoadTypes\n\tinitial, err := packages.Load(onDisk.Config, fmt.Sprintf(\"file=%s\", onDisk.File(\"golang.org/fake\", \"a/a_x_test.go\")))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twantPkg := initial[0]\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":        aFile,\n\t\t\t\"a/a_test.go\":   aTestVariant,\n\t\t\t\"a/a_x_test.go\": ``, // empty x test on disk\n\t\t},\n\t\tOverlay: map[string][]byte{\n\t\t\t\"a/a_x_test.go\": []byte(aXTest),\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\n\tif len(initial) != 1 {\n\t\tt.Fatalf(\"expected 1 package, got %d\", len(initial))\n\t}\n\t// Confirm that the overlaid package is identical to the on-disk version.\n\tpkg := initial[0]\n\tif !reflect.DeepEqual(wantPkg, pkg) {\n\t\tt.Fatalf(\"mismatched packages: want %#v, got %#v\", wantPkg, pkg)\n\t}\n\txTestC := constant(pkg, \"xTestC\")\n\tif xTestC == nil {\n\t\tt.Fatalf(\"no value for xTestC\")\n\t}\n\tgot := xTestC.Val().String()\n\t// TODO(rstambler): Ideally, this test would check that the test variant\n\t// was imported, but that's pretty complicated.\n\tif want := `\"xC\"`; got != want {\n\t\tt.Errorf(\"got: %q, want %q\", got, want)\n\t}\n}\n\nfunc TestOverlay(t *testing.T) { testAllOrModulesParallel(t, testOverlay) }\nfunc testOverlay(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":      `package a; import \"golang.org/fake/b\"; const A = \"a\" + b.B`,\n\t\t\t\"b/b.go\":      `package b; import \"golang.org/fake/c\"; const B = \"b\" + c.C`,\n\t\t\t\"c/c.go\":      `package c; const C = \"c\"`,\n\t\t\t\"c/c_test.go\": `package c; import \"testing\"; func TestC(t *testing.T) {}`,\n\t\t\t\"d/d.go\":      `package d; const D = \"d\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tfor i, test := range []struct {\n\t\toverlay  map[string][]byte\n\t\twant     string // expected value of a.A\n\t\twantErrs []string\n\t}{\n\t\t{nil, `\"abc\"`, nil},                 // default\n\t\t{map[string][]byte{}, `\"abc\"`, nil}, // empty overlay\n\t\t{map[string][]byte{exported.File(\"golang.org/fake\", \"c/c.go\"): []byte(`package c; const C = \"C\"`)}, `\"abC\"`, nil},\n\t\t{map[string][]byte{exported.File(\"golang.org/fake\", \"b/b.go\"): []byte(`package b; import \"golang.org/fake/c\"; const B = \"B\" + c.C`)}, `\"aBc\"`, nil},\n\t\t// Overlay with an existing file in an existing package adding a new import.\n\t\t{map[string][]byte{exported.File(\"golang.org/fake\", \"b/b.go\"): []byte(`package b; import \"golang.org/fake/d\"; const B = \"B\" + d.D`)}, `\"aBd\"`, nil},\n\t\t// Overlay with an existing file in an existing package.\n\t\t{map[string][]byte{exported.File(\"golang.org/fake\", \"c/c.go\"): []byte(`package c; import \"net/http\"; const C = http.MethodGet`)}, `\"abGET\"`, nil},\n\t\t// Overlay with a new file in an existing package.\n\t\t{map[string][]byte{\n\t\t\texported.File(\"golang.org/fake\", \"c/c.go\"):                                               []byte(`package c;`),\n\t\t\tfilepath.Join(filepath.Dir(exported.File(\"golang.org/fake\", \"c/c.go\")), \"c_new_file.go\"): []byte(`package c; const C = \"Ç\"`)},\n\t\t\t`\"abÇ\"`, nil},\n\t\t// Overlay with a new file in an existing package, adding a new dependency to that package.\n\t\t{map[string][]byte{\n\t\t\texported.File(\"golang.org/fake\", \"c/c.go\"):                                               []byte(`package c;`),\n\t\t\tfilepath.Join(filepath.Dir(exported.File(\"golang.org/fake\", \"c/c.go\")), \"c_new_file.go\"): []byte(`package c; import \"golang.org/fake/d\"; const C = \"c\" + d.D`)},\n\t\t\t`\"abcd\"`, nil},\n\t} {\n\t\texported.Config.Overlay = test.overlay\n\t\texported.Config.Mode = packages.LoadAllSyntax\n\t\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check value of a.A.\n\t\ta := initial[0]\n\t\taA := constant(a, \"A\")\n\t\tif aA == nil {\n\t\t\tt.Errorf(\"%d. a.A: got nil\", i)\n\t\t\tcontinue\n\t\t}\n\t\tgot := aA.Val().String()\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"%d. a.A: got %s, want %s\", i, got, test.want)\n\t\t}\n\n\t\t// Check errors.\n\t\tvar errors []packages.Error\n\t\tfor pkg := range packages.Postorder(initial) {\n\t\t\terrors = append(errors, pkg.Errors...)\n\t\t}\n\t\tif errs := errorMessages(errors); !reflect.DeepEqual(errs, test.wantErrs) {\n\t\t\tt.Errorf(\"%d. got errors %s, want %s\", i, errs, test.wantErrs)\n\t\t}\n\t}\n}\n\nfunc TestOverlayDeps(t *testing.T) { testAllOrModulesParallel(t, testOverlayDeps) }\nfunc testOverlayDeps(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"c/c.go\":      `package c; const C = \"c\"`,\n\t\t\t\"c/c_test.go\": `package c; import \"testing\"; func TestC(t *testing.T) {}`,\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Overlay = map[string][]byte{exported.File(\"golang.org/fake\", \"c/c.go\"): []byte(`package c; import \"net/http\"; const C = http.MethodGet`)}\n\texported.Config.Mode = packages.NeedName |\n\t\tpackages.NeedFiles |\n\t\tpackages.NeedCompiledGoFiles |\n\t\tpackages.NeedImports |\n\t\tpackages.NeedDeps |\n\t\tpackages.NeedTypesSizes\n\tpkgs, err := packages.Load(exported.Config, fmt.Sprintf(\"file=%s\", exported.File(\"golang.org/fake\", \"c/c.go\")))\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\n\t// Find package golang.org/fake/c\n\tsort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })\n\tif len(pkgs) != 2 {\n\t\tt.Fatalf(\"expected 2 packages, got %v\", len(pkgs))\n\t}\n\tpkgc := pkgs[0]\n\tif pkgc.ID != \"golang.org/fake/c\" {\n\t\tt.Errorf(\"expected first package in sorted list to be \\\"golang.org/fake/c\\\", got %v\", pkgc.ID)\n\t}\n\n\t// Make sure golang.org/fake/c imports net/http, as per the overlay.\n\tcontains := func(imports map[string]*packages.Package, wantImport string) bool {\n\t\tfor imp := range imports {\n\t\t\tif imp == wantImport {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\tif !contains(pkgc.Imports, \"net/http\") {\n\t\tt.Errorf(\"expected import of %s in package %s, got the following imports: %v\",\n\t\t\t\"net/http\", pkgc.ID, pkgc.Imports)\n\t}\n\n}\n\nfunc TestNewPackagesInOverlay(t *testing.T) { testAllOrModulesParallel(t, testNewPackagesInOverlay) }\nfunc testNewPackagesInOverlay(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"; const A = \"a\" + b.B`,\n\t\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"; const B = \"b\" + c.C`,\n\t\t\t\t\"c/c.go\": `package c; const C = \"c\"`,\n\t\t\t\t\"d/d.go\": `package d; const D = \"d\"`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"example.com/extramodule\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"pkg/x.go\": \"package pkg\\n\",\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\tdir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\")))\n\n\tfor _, test := range []struct {\n\t\tname    string\n\t\toverlay map[string][]byte\n\t\twant    string // expected value of e.E\n\t}{\n\t\t{\"one_file\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"): []byte(`package e; import \"golang.org/fake/a\"; const E = \"e\" + a.A`)},\n\t\t\t`\"eabc\"`},\n\t\t{\"multiple_files_same_package\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"):      []byte(`package e; import \"golang.org/fake/a\"; const E = \"e\" + a.A + underscore`),\n\t\t\t\tfilepath.Join(dir, \"e\", \"e_util.go\"): []byte(`package e; const underscore = \"_\"`),\n\t\t\t},\n\t\t\t`\"eabc_\"`},\n\t\t{\"multiple_files_two_packages\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"):      []byte(`package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F + underscore`),\n\t\t\t\tfilepath.Join(dir, \"e\", \"e_util.go\"): []byte(`package e; const underscore = \"_\"`),\n\t\t\t\tfilepath.Join(dir, \"f\", \"f.go\"):      []byte(`package f; const F = \"f\"`),\n\t\t\t},\n\t\t\t`\"ef_\"`},\n\t\t{\"multiple_files_three_packages\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"):      []byte(`package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F + underscore`),\n\t\t\t\tfilepath.Join(dir, \"e\", \"e_util.go\"): []byte(`package e; const underscore = \"_\"`),\n\t\t\t\tfilepath.Join(dir, \"f\", \"f.go\"):      []byte(`package f; import \"golang.org/fake/g\"; const F = \"f\" + g.G`),\n\t\t\t\tfilepath.Join(dir, \"g\", \"g.go\"):      []byte(`package g; const G = \"g\"`),\n\t\t\t},\n\t\t\t`\"efg_\"`},\n\t\t{\"multiple_files_four_packages\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"):      []byte(`package e; import \"golang.org/fake/f\"; import \"golang.org/fake/h\"; const E = \"e\" + f.F + h.H + underscore`),\n\t\t\t\tfilepath.Join(dir, \"e\", \"e_util.go\"): []byte(`package e; const underscore = \"_\"`),\n\t\t\t\tfilepath.Join(dir, \"f\", \"f.go\"):      []byte(`package f; import \"golang.org/fake/g\"; const F = \"f\" + g.G`),\n\t\t\t\tfilepath.Join(dir, \"g\", \"g.go\"):      []byte(`package g; const G = \"g\"`),\n\t\t\t\tfilepath.Join(dir, \"h\", \"h.go\"):      []byte(`package h; const H = \"h\"`),\n\t\t\t},\n\t\t\t`\"efgh_\"`},\n\t\t{\"multiple_files_four_packages_again\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"e.go\"):      []byte(`package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F + underscore`),\n\t\t\t\tfilepath.Join(dir, \"e\", \"e_util.go\"): []byte(`package e; const underscore = \"_\"`),\n\t\t\t\tfilepath.Join(dir, \"f\", \"f.go\"):      []byte(`package f; import \"golang.org/fake/g\"; const F = \"f\" + g.G`),\n\t\t\t\tfilepath.Join(dir, \"g\", \"g.go\"):      []byte(`package g; import \"golang.org/fake/h\"; const G = \"g\" + h.H`),\n\t\t\t\tfilepath.Join(dir, \"h\", \"h.go\"):      []byte(`package h; const H = \"h\"`),\n\t\t\t},\n\t\t\t`\"efgh_\"`},\n\t\t{\"main_overlay\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"e\", \"main.go\"): []byte(`package main; import \"golang.org/fake/a\"; const E = \"e\" + a.A; func main(){}`)},\n\t\t\t`\"eabc\"`},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\texported.Config.Overlay = test.overlay\n\t\t\texported.Config.Mode = packages.LoadAllSyntax\n\t\t\texported.Config.Logf = t.Logf\n\n\t\t\t// With an overlay, we don't know the expected import path,\n\t\t\t// so load with the absolute path of the directory.\n\t\t\tinitial, err := packages.Load(exported.Config, filepath.Join(dir, \"e\"))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Check value of e.E.\n\t\t\te := initial[0]\n\t\t\teE := constant(e, \"E\")\n\t\t\tif eE == nil {\n\t\t\t\tt.Fatalf(\"e.E: was nil in %#v\", e)\n\t\t\t}\n\t\t\tgot := eE.Val().String()\n\t\t\tif got != test.want {\n\t\t\t\tt.Fatalf(\"e.E: got %s, want %s\", got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test that we can create a package and its test package in an overlay.\nfunc TestOverlayNewPackageAndTest(t *testing.T) {\n\ttestAllOrModulesParallel(t, testOverlayNewPackageAndTest)\n}\nfunc testOverlayNewPackageAndTest(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"foo.txt\": \"placeholder\",\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\tdir := filepath.Dir(exported.File(\"golang.org/fake\", \"foo.txt\"))\n\texported.Config.Overlay = map[string][]byte{\n\t\tfilepath.Join(dir, \"a.go\"):      []byte(`package a;`),\n\t\tfilepath.Join(dir, \"a_test.go\"): []byte(`package a; import \"testing\";`),\n\t}\n\tinitial, err := packages.Load(exported.Config, \"file=\"+filepath.Join(dir, \"a.go\"), \"file=\"+filepath.Join(dir, \"a_test.go\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) != 2 {\n\t\tt.Errorf(\"got %v packages, wanted %v\", len(initial), 2)\n\t}\n}\n\nfunc TestAdHocOverlays(t *testing.T) {\n\tt.Parallel()\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// This test doesn't use packagestest because we are testing ad-hoc packages,\n\t// which are outside of $GOPATH and outside of a module.\n\ttmp, err := os.MkdirTemp(\"\", \"testAdHocOverlays\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmp)\n\n\tfilename := filepath.Join(tmp, \"a.go\")\n\tcontent := []byte(`package a\nconst A = 1\n`)\n\n\t// Make sure that the user's value of GO111MODULE does not affect test results.\n\tfor _, go111module := range []string{\"off\", \"auto\", \"on\"} {\n\t\tt.Run(\"GO111MODULE=\"+go111module, func(t *testing.T) {\n\t\t\tconfig := &packages.Config{\n\t\t\t\tDir:  tmp,\n\t\t\t\tEnv:  append(os.Environ(), \"GOPACKAGESDRIVER=off\", fmt.Sprintf(\"GO111MODULE=%s\", go111module)),\n\t\t\t\tMode: packages.LoadAllSyntax,\n\t\t\t\tOverlay: map[string][]byte{\n\t\t\t\t\tfilename: content,\n\t\t\t\t},\n\t\t\t\tLogf: t.Logf,\n\t\t\t}\n\t\t\tinitial, err := packages.Load(config, fmt.Sprintf(\"file=%s\", filename))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(initial) == 0 {\n\t\t\t\tt.Fatalf(\"no packages for %s\", filename)\n\t\t\t}\n\t\t\t// Check value of a.A.\n\t\t\ta := initial[0]\n\t\t\tif a.Errors != nil {\n\t\t\t\tt.Fatalf(\"a: got errors %+v, want no error\", err)\n\t\t\t}\n\t\t\taA := constant(a, \"A\")\n\t\t\tif aA == nil {\n\t\t\t\tt.Errorf(\"a.A: got nil\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tgot := aA.Val().String()\n\t\t\tif want := \"1\"; got != want {\n\t\t\t\tt.Errorf(\"a.A: got %s, want %s\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestOverlayModFileChanges tests the behavior resulting from having files\n// from multiple modules in overlays.\nfunc TestOverlayModFileChanges(t *testing.T) {\n\tt.Parallel()\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Create two unrelated modules in a temporary directory.\n\ttmp, err := os.MkdirTemp(\"\", \"tmp\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmp)\n\n\t// mod1 has a dependency on golang.org/x/xerrors.\n\tmod1, err := os.MkdirTemp(tmp, \"mod1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(mod1, \"go.mod\"), []byte(`module mod1\n\n\trequire (\n\t\tgolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7\n\t)\n\t`), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// mod2 does not have any dependencies.\n\tmod2, err := os.MkdirTemp(tmp, \"mod2\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twant := `module mod2\n\ngo 1.11\n`\n\tif err := os.WriteFile(filepath.Join(mod2, \"go.mod\"), []byte(want), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Run packages.Load on mod2, while passing the contents over mod1/main.go in the overlay.\n\tconfig := &packages.Config{\n\t\tDir:  mod2,\n\t\tEnv:  append(os.Environ(), \"GOPACKAGESDRIVER=off\"),\n\t\tMode: packages.LoadImports,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(mod1, \"main.go\"): []byte(`package main\nimport \"golang.org/x/xerrors\"\nfunc main() {\n\t_ = errors.New(\"\")\n}\n`),\n\t\t\tfilepath.Join(mod2, \"main.go\"): []byte(`package main\nfunc main() {}\n`),\n\t\t},\n\t}\n\tif _, err := packages.Load(config, fmt.Sprintf(\"file=%s\", filepath.Join(mod2, \"main.go\"))); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check that mod2/go.mod has not been modified.\n\tgot, err := os.ReadFile(filepath.Join(mod2, \"go.mod\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif string(got) != want {\n\t\tt.Errorf(\"expected %s, got %s\", want, string(got))\n\t}\n}\n\nfunc TestOverlayGOPATHVendoring(t *testing.T) {\n\tt.Parallel()\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"vendor/vendor.com/foo/foo.go\": `package foo; const X = \"hi\"`,\n\t\t\t\"user/user.go\":                 `package user`,\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadAllSyntax\n\texported.Config.Logf = t.Logf\n\texported.Config.Overlay = map[string][]byte{\n\t\texported.File(\"golang.org/fake\", \"user/user.go\"): []byte(`package user; import \"vendor.com/foo\"; var x = foo.X`),\n\t}\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/user\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tuser := initial[0]\n\tif len(user.Imports) != 1 {\n\t\tt.Fatal(\"no imports for user\")\n\t}\n\tif user.Imports[\"vendor.com/foo\"].Name != \"foo\" {\n\t\tt.Errorf(\"failed to load vendored package foo, imports: %#v\", user.Imports[\"vendor.com/foo\"])\n\t}\n}\n\nfunc TestContainsOverlay(t *testing.T) { testAllOrModulesParallel(t, testContainsOverlay) }\nfunc testContainsOverlay(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\": `package c`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\tbOverlayFile := filepath.Join(filepath.Dir(exported.File(\"golang.org/fake\", \"b/b.go\")), \"b_overlay.go\")\n\texported.Config.Mode = packages.LoadImports\n\texported.Config.Overlay = map[string][]byte{bOverlayFile: []byte(`package b;`)}\n\tinitial, err := packages.Load(exported.Config, \"file=\"+bOverlayFile)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/b\n  golang.org/fake/c\n  golang.org/fake/b -> golang.org/fake/c\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\nfunc TestContainsOverlayXTest(t *testing.T) { testAllOrModulesParallel(t, testContainsOverlayXTest) }\nfunc testContainsOverlayXTest(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\": `package c`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tbOverlayXTestFile := filepath.Join(filepath.Dir(exported.File(\"golang.org/fake\", \"b/b.go\")), \"b_overlay_x_test.go\")\n\texported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedImports\n\texported.Config.Overlay = map[string][]byte{bOverlayXTestFile: []byte(`package b_test; import \"golang.org/fake/b\"`)}\n\tinitial, err := packages.Load(exported.Config, \"file=\"+bOverlayXTestFile)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n  golang.org/fake/b\n* golang.org/fake/b_test [golang.org/fake/b.test]\n  golang.org/fake/c\n  golang.org/fake/b -> golang.org/fake/c\n  golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/b\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\nfunc TestInvalidFilesBeforeOverlay(t *testing.T) {\n\ttestAllOrModulesParallel(t, testInvalidFilesBeforeOverlay)\n}\n\nfunc testInvalidFilesBeforeOverlay(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"d/d.go\":  ``,\n\t\t\t\t\"main.go\": ``,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\tdir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"d/d.go\")))\n\n\texported.Config.Mode = everythingMode\n\texported.Config.Tests = true\n\n\t// First, check that all packages returned have files associated with them.\n\t// Tests the work-around for golang/go#39986.\n\tt.Run(\"no overlay\", func(t *testing.T) {\n\t\tinitial, err := packages.Load(exported.Config, fmt.Sprintf(\"%s/...\", dir))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfor _, pkg := range initial {\n\t\t\tif len(pkg.CompiledGoFiles) == 0 {\n\t\t\t\tt.Fatalf(\"expected at least 1 CompiledGoFile for %s, got none\", pkg.PkgPath)\n\t\t\t}\n\t\t}\n\t})\n\n}\n\n// Tests golang/go#35973, fixed in Go 1.14.\nfunc TestInvalidFilesBeforeOverlayContains(t *testing.T) {\n\ttestAllOrModulesParallel(t, testInvalidFilesBeforeOverlayContains)\n}\nfunc testInvalidFilesBeforeOverlayContains(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"d/d.go\":      `package d; import \"net/http\"; const Get = http.MethodGet; const Hello = \"hello\";`,\n\t\t\t\t\"d/util.go\":   ``,\n\t\t\t\t\"d/d_test.go\": ``,\n\t\t\t\t\"main.go\":     ``,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\tdir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"d/d.go\")))\n\n\t// Additional tests for test variants.\n\tfor i, tt := range []struct {\n\t\tname    string\n\t\toverlay map[string][]byte\n\t\twant    string // expected value of d.D\n\t\twantID  string // expected value for the package ID\n\t}{\n\t\t// Overlay with a test variant.\n\t\t{\n\t\t\t\"test_variant\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"d\", \"d_test.go\"): []byte(`package d; import \"testing\"; const D = Get + \"_test\"; func TestD(t *testing.T) {};`),\n\t\t\t},\n\t\t\t`\"GET_test\"`, \"golang.org/fake/d [golang.org/fake/d.test]\",\n\t\t},\n\t\t// Overlay in package.\n\t\t{\n\t\t\t\"second_file\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"d\", \"util.go\"): []byte(`package d; const D = Get + \"_util\";`),\n\t\t\t},\n\t\t\t`\"GET_util\"`, \"golang.org/fake/d\",\n\t\t},\n\t\t// Overlay on the main file.\n\t\t{\n\t\t\t\"main\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"main.go\"): []byte(`package main; import \"golang.org/fake/d\"; const D = d.Get + \"_main\"; func main() {};`),\n\t\t\t},\n\t\t\t`\"GET_main\"`, \"golang.org/fake\",\n\t\t},\n\t\t{\n\t\t\t\"xtest\",\n\t\t\tmap[string][]byte{\n\t\t\t\tfilepath.Join(dir, \"d\", \"d_test.go\"): []byte(`package d_test; import \"golang.org/fake/d\"; import \"testing\"; const D = d.Get + \"_xtest\"; func TestD(t *testing.T) {};`),\n\t\t\t},\n\t\t\t`\"GET_xtest\"`, \"golang.org/fake/d_test [golang.org/fake/d.test]\",\n\t\t},\n\t} {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\texported.Config.Overlay = tt.overlay\n\t\t\texported.Config.Mode = everythingMode\n\t\t\texported.Config.Tests = true\n\n\t\t\tfor f := range tt.overlay {\n\t\t\t\tinitial, err := packages.Load(exported.Config, fmt.Sprintf(\"file=%s\", f))\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif len(initial) != 1 &&\n\t\t\t\t\t(len(initial) != 2 || !isTestVariant(initial[0].ID, initial[1].ID)) {\n\t\t\t\t\tt.Fatalf(\"expected 1 package (perhaps with test variant), got %v\", len(initial))\n\t\t\t\t}\n\t\t\t\tpkg := initial[0]\n\t\t\t\tif pkg.ID != tt.wantID {\n\t\t\t\t\tt.Fatalf(\"expected package ID %q, got %q\", tt.wantID, pkg.ID)\n\t\t\t\t}\n\t\t\t\tvar containsFile bool\n\t\t\t\tif slices.Contains(pkg.CompiledGoFiles, f) {\n\t\t\t\t\tcontainsFile = true\n\t\t\t\t}\n\t\t\t\tif !containsFile {\n\t\t\t\t\tt.Fatalf(\"expected %s in CompiledGoFiles, got %v\", f, pkg.CompiledGoFiles)\n\t\t\t\t}\n\t\t\t\t// Check value of d.D.\n\t\t\t\tD := constant(pkg, \"D\")\n\t\t\t\tif D == nil {\n\t\t\t\t\tt.Fatalf(\"%d. D: got nil\", i)\n\t\t\t\t}\n\t\t\t\tgot := D.Val().String()\n\t\t\t\tif got != tt.want {\n\t\t\t\t\tt.Fatalf(\"%d. D: got %s, want %s\", i, got, tt.want)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc isTestVariant(libID, testID string) bool {\n\tvariantID := fmt.Sprintf(\"%[1]s [%[1]s.test]\", libID)\n\treturn variantID == testID\n}\n\nfunc TestInvalidXTestInGOPATH(t *testing.T) {\n\ttestAllOrModulesParallel(t, testInvalidXTestInGOPATH)\n}\nfunc testInvalidXTestInGOPATH(t *testing.T, exporter packagestest.Exporter) {\n\tt.Skip(\"Not fixed yet. See golang.org/issue/40825.\")\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"x/x.go\":      `package x`,\n\t\t\t\t\"x/x_test.go\": ``,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\tdir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"x/x.go\")))\n\n\texported.Config.Mode = everythingMode\n\texported.Config.Tests = true\n\n\tinitial, err := packages.Load(exported.Config, fmt.Sprintf(\"%s/...\", dir))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpkg := initial[0]\n\tif len(pkg.CompiledGoFiles) != 2 {\n\t\tt.Fatalf(\"expected at least 2 CompiledGoFiles for %s, got %v\", pkg.PkgPath, len(pkg.CompiledGoFiles))\n\t}\n}\n\n// Reproduces golang/go#40685.\nfunc TestAddImportInOverlay(t *testing.T) {\n\ttestAllOrModulesParallel(t, testAddImportInOverlay)\n}\nfunc testAddImportInOverlay(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"a/a.go\": `package a\n\nimport (\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n\tos.Stat(\"\")\n}`,\n\t\t\t\t\"a/a_test.go\": `package a\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestA(t *testing.T) {\n\tos.Stat(\"\")\n}`,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = everythingMode\n\texported.Config.Tests = true\n\n\tdir := filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\"))\n\texported.Config.Overlay = map[string][]byte{\n\t\tfilepath.Join(dir, \"a.go\"): []byte(`package a\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n\tos.Stat(\"\")\n}\n`),\n\t}\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpkg := initial[0]\n\tvar foundOs bool\n\tfor _, imp := range pkg.Imports {\n\t\tif imp.PkgPath == \"os\" {\n\t\t\tfoundOs = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !foundOs {\n\t\tt.Fatalf(`expected import \"os\", found none: %v`, pkg.Imports)\n\t}\n}\n\n// Tests that overlays are applied for different kinds of load patterns.\nfunc TestLoadDifferentPatterns(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadDifferentPatterns)\n}\nfunc testLoadDifferentPatterns(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"foo.txt\": \"placeholder\",\n\t\t\t\t\"b/b.go\": `package b\nimport \"golang.org/fake/a\"\nfunc _() {\n\ta.Hi()\n}\n`,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = everythingMode\n\texported.Config.Tests = true\n\n\tdir := filepath.Dir(exported.File(\"golang.org/fake\", \"foo.txt\"))\n\texported.Config.Overlay = map[string][]byte{\n\t\tfilepath.Join(dir, \"a\", \"a.go\"): []byte(`package a\nimport \"fmt\"\nfunc Hi() {\n\tfmt.Println(\"\")\n}\n`),\n\t}\n\tfor _, tc := range []struct {\n\t\tpattern string\n\t}{\n\t\t{\"golang.org/fake/a\"},\n\t\t{\"golang.org/fake/...\"},\n\t\t{fmt.Sprintf(\"file=%s\", filepath.Join(dir, \"a\", \"a.go\"))},\n\t} {\n\t\tt.Run(tc.pattern, func(t *testing.T) {\n\t\t\tinitial, err := packages.Load(exported.Config, tc.pattern)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar match *packages.Package\n\t\t\tfor _, pkg := range initial {\n\t\t\t\tif pkg.PkgPath == \"golang.org/fake/a\" {\n\t\t\t\t\tmatch = pkg\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif match == nil {\n\t\t\t\tt.Fatalf(`expected package path \"golang.org/fake/a\", got none`)\n\t\t\t}\n\t\t\tif match.PkgPath != \"golang.org/fake/a\" {\n\t\t\t\tt.Fatalf(`expected package path \"golang.org/fake/a\", got %q`, match.PkgPath)\n\t\t\t}\n\t\t\tif _, ok := match.Imports[\"fmt\"]; !ok {\n\t\t\t\tt.Fatalf(`expected import \"fmt\", got none`)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Now, load \"golang.org/fake/b\" and confirm that \"golang.org/fake/a\" is\n\t// not returned as a root.\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/b\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) > 1 {\n\t\tt.Fatalf(\"expected 1 package, got %v\", initial)\n\t}\n\tpkg := initial[0]\n\tif pkg.PkgPath != \"golang.org/fake/b\" {\n\t\tt.Fatalf(`expected package path \"golang.org/fake/b\", got %q`, pkg.PkgPath)\n\t}\n\tif _, ok := pkg.Imports[\"golang.org/fake/a\"]; !ok {\n\t\tt.Fatalf(`expected import \"golang.org/fake/a\", got none`)\n\t}\n}\n\n// Tests that overlays are applied for a replaced module.\n// This does not use go/packagestest because it needs to write a replace\n// directive with an absolute path in one of the module's go.mod files.\nfunc TestOverlaysInReplace(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tt.Parallel()\n\n\t// Create module b.com in a temporary directory. Do not add any Go files\n\t// on disk.\n\ttmpPkgs, err := os.MkdirTemp(\"\", \"modules\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmpPkgs)\n\n\tdirB := filepath.Join(tmpPkgs, \"b\")\n\tif err := os.Mkdir(dirB, 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(dirB, \"go.mod\"), fmt.Appendf(nil, \"module %s.com\", dirB), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.MkdirAll(filepath.Join(dirB, \"inner\"), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Create a separate module that requires and replaces b.com.\n\ttmpWorkspace, err := os.MkdirTemp(\"\", \"workspace\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmpWorkspace)\n\tgoModContent := fmt.Sprintf(`module workspace.com\n\nrequire (\n\tb.com v0.0.0-00010101000000-000000000000\n)\n\nreplace (\n\tb.com => %s\n)\n`, dirB)\n\tif err := os.WriteFile(filepath.Join(tmpWorkspace, \"go.mod\"), []byte(goModContent), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Add Go files for b.com/inner in an overlay and try loading it from the\n\t// workspace.com module.\n\tconfig := &packages.Config{\n\t\tDir:  tmpWorkspace,\n\t\tMode: packages.LoadAllSyntax,\n\t\tLogf: t.Logf,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(dirB, \"inner\", \"b.go\"): []byte(`package inner; import \"fmt\"; func _() { fmt.Println(\"\");`),\n\t\t},\n\t}\n\tinitial, err := packages.Load(config, \"b.com/...\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\tif len(initial) != 1 {\n\t\tt.Fatalf(`expected 1 package, got %v`, len(initial))\n\t}\n\tpkg := initial[0]\n\tif pkg.PkgPath != \"b.com/inner\" {\n\t\tt.Fatalf(`expected package path \"b.com/inner\", got %q`, pkg.PkgPath)\n\t}\n\tif _, ok := pkg.Imports[\"fmt\"]; !ok {\n\t\tt.Fatalf(`expected import \"fmt\", got none`)\n\t}\n}\n"
  },
  {
    "path": "go/packages/packages.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\n// See doc.go for package documentation and implementation notes.\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// A LoadMode controls the amount of detail to return when loading.\n// The bits below can be combined to specify which fields should be\n// filled in the result packages.\n//\n// The zero value is a special case, equivalent to combining\n// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.\n//\n// ID and Errors (if present) will always be filled.\n// [Load] may return more information than requested.\n//\n// The Mode flag is a union of several bits named NeedName,\n// NeedFiles, and so on, each of which determines whether\n// a given field of Package (Name, Files, etc) should be\n// populated.\n//\n// For convenience, we provide named constants for the most\n// common combinations of Need flags:\n//\n//\t[LoadFiles]     lists of files in each package\n//\t[LoadImports]   ... plus imports\n//\t[LoadTypes]     ... plus type information\n//\t[LoadSyntax]    ... plus type-annotated syntax\n//\t[LoadAllSyntax] ... for all dependencies\n//\n// Unfortunately there are a number of open bugs related to\n// interactions among the LoadMode bits:\n//   - https://go.dev/issue/56633\n//   - https://go.dev/issue/56677\n//   - https://go.dev/issue/58726\n//   - https://go.dev/issue/63517\ntype LoadMode int\n\nconst (\n\t// NeedName adds Name and PkgPath.\n\tNeedName LoadMode = 1 << iota\n\n\t// NeedFiles adds Dir, GoFiles, OtherFiles, and IgnoredFiles\n\tNeedFiles\n\n\t// NeedCompiledGoFiles adds CompiledGoFiles.\n\tNeedCompiledGoFiles\n\n\t// NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain\n\t// \"placeholder\" Packages with only the ID set.\n\tNeedImports\n\n\t// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.\n\tNeedDeps\n\n\t// NeedExportFile adds ExportFile.\n\tNeedExportFile\n\n\t// NeedTypes adds Types, Fset, and IllTyped.\n\tNeedTypes\n\n\t// NeedSyntax adds Syntax and Fset.\n\tNeedSyntax\n\n\t// NeedTypesInfo adds TypesInfo and Fset.\n\tNeedTypesInfo\n\n\t// NeedTypesSizes adds TypesSizes.\n\tNeedTypesSizes\n\n\t// needInternalDepsErrors adds the internal deps errors field for use by gopls.\n\tneedInternalDepsErrors\n\n\t// NeedForTest adds ForTest.\n\t//\n\t// Tests must also be set on the context for this field to be populated.\n\tNeedForTest\n\n\t// typecheckCgo enables full support for type checking cgo. Requires Go 1.15+.\n\t// Modifies CompiledGoFiles and Types, and has no effect on its own.\n\ttypecheckCgo\n\n\t// NeedModule adds Module.\n\tNeedModule\n\n\t// NeedEmbedFiles adds EmbedFiles.\n\tNeedEmbedFiles\n\n\t// NeedEmbedPatterns adds EmbedPatterns.\n\tNeedEmbedPatterns\n\n\t// NeedTarget adds Target.\n\tNeedTarget\n\n\t// Be sure to update loadmode_string.go when adding new items!\n)\n\nconst (\n\t// LoadFiles loads the name and file names for the initial packages.\n\tLoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles\n\n\t// LoadImports loads the name, file names, and import mapping for the initial packages.\n\tLoadImports = LoadFiles | NeedImports\n\n\t// LoadTypes loads exported type information for the initial packages.\n\tLoadTypes = LoadImports | NeedTypes | NeedTypesSizes\n\n\t// LoadSyntax loads typed syntax for the initial packages.\n\tLoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo\n\n\t// LoadAllSyntax loads typed syntax for the initial packages and all dependencies.\n\tLoadAllSyntax = LoadSyntax | NeedDeps\n\n\t// Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile.\n\t//\n\t//go:fix inline\n\tNeedExportsFile = NeedExportFile\n)\n\n// A Config specifies details about how packages should be loaded.\n// The zero value is a valid configuration.\n//\n// Calls to [Load] do not modify this struct.\ntype Config struct {\n\t// Mode controls the level of information returned for each package.\n\tMode LoadMode\n\n\t// Context specifies the context for the load operation.\n\t// Cancelling the context may cause [Load] to abort and\n\t// return an error.\n\tContext context.Context\n\n\t// Logf is the logger for the config.\n\t// If the user provides a logger, debug logging is enabled.\n\t// If the GOPACKAGESDEBUG environment variable is set to true,\n\t// but the logger is nil, default to log.Printf.\n\tLogf func(format string, args ...any)\n\n\t// Dir is the directory in which to run the build system's query tool\n\t// that provides information about the packages.\n\t// If Dir is empty, the tool is run in the current directory.\n\tDir string\n\n\t// Env is the environment to use when invoking the build system's query tool.\n\t// If Env is nil, the current environment is used.\n\t// As in os/exec's Cmd, only the last value in the slice for\n\t// each environment key is used. To specify the setting of only\n\t// a few variables, append to the current environment, as in:\n\t//\n\t//\topt.Env = append(os.Environ(), \"GOOS=plan9\", \"GOARCH=386\")\n\t//\n\tEnv []string\n\n\t// BuildFlags is a list of command-line flags to be passed through to\n\t// the build system's query tool.\n\tBuildFlags []string\n\n\t// Fset provides source position information for syntax trees and types.\n\t// If Fset is nil, Load will use a new fileset, but preserve Fset's value.\n\tFset *token.FileSet\n\n\t// ParseFile is called to read and parse each file\n\t// when preparing a package's type-checked syntax tree.\n\t// It must be safe to call ParseFile simultaneously from multiple goroutines.\n\t// If ParseFile is nil, the loader will uses parser.ParseFile.\n\t//\n\t// ParseFile should parse the source from src and use filename only for\n\t// recording position information.\n\t//\n\t// An application may supply a custom implementation of ParseFile\n\t// to change the effective file contents or the behavior of the parser,\n\t// or to modify the syntax tree. For example, selectively eliminating\n\t// unwanted function bodies can significantly accelerate type checking.\n\tParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)\n\n\t// If Tests is set, the loader includes not just the packages\n\t// matching a particular pattern but also any related test packages,\n\t// including test-only variants of the package and the test executable.\n\t//\n\t// For example, when using the go command, loading \"fmt\" with Tests=true\n\t// returns four packages, with IDs \"fmt\" (the standard package),\n\t// \"fmt [fmt.test]\" (the package as compiled for the test),\n\t// \"fmt_test\" (the test functions from source files in package fmt_test),\n\t// and \"fmt.test\" (the test binary).\n\t//\n\t// In build systems with explicit names for tests,\n\t// setting Tests may have no effect.\n\tTests bool\n\n\t// Overlay is a mapping from absolute file paths to file contents.\n\t//\n\t// For each map entry, [Load] uses the alternative file\n\t// contents provided by the overlay mapping instead of reading\n\t// from the file system. This mechanism can be used to enable\n\t// editor-integrated tools to correctly analyze the contents\n\t// of modified but unsaved buffers, for example.\n\t//\n\t// The overlay mapping is passed to the build system's driver\n\t// (see \"The driver protocol\") so that it too can report\n\t// consistent package metadata about unsaved files. However,\n\t// drivers may vary in their level of support for overlays.\n\tOverlay map[string][]byte\n}\n\n// Load loads and returns the Go packages named by the given patterns.\n//\n// The cfg parameter specifies loading options; nil behaves the same as an empty [Config].\n//\n// The [Config.Mode] field is a set of bits that determine what kinds\n// of information should be computed and returned. Modes that require\n// more information tend to be slower. See [LoadMode] for details\n// and important caveats. Its zero value is equivalent to\n// [NeedName] | [NeedFiles] | [NeedCompiledGoFiles].\n//\n// Each call to Load returns a new set of [Package] instances.\n// The Packages and their Imports form a directed acyclic graph.\n//\n// If the [NeedTypes] mode flag was set, each call to Load uses a new\n// [types.Importer], so [types.Object] and [types.Type] values from\n// different calls to Load must not be mixed as they will have\n// inconsistent notions of type identity.\n//\n// If any of the patterns was invalid as defined by the\n// underlying build system, Load returns an error.\n// It may return an empty list of packages without an error,\n// for instance for an empty expansion of a valid wildcard.\n// Errors associated with a particular package are recorded in the\n// corresponding Package's Errors list, and do not cause Load to\n// return an error. Clients may need to handle such errors before\n// proceeding with further analysis. The [PrintErrors] function is\n// provided for convenient display of all errors.\nfunc Load(cfg *Config, patterns ...string) ([]*Package, error) {\n\tld := newLoader(cfg)\n\tresponse, external, err := defaultDriver(&ld.Config, patterns...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tld.sizes = types.SizesFor(response.Compiler, response.Arch)\n\tif ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 {\n\t\t// Type size information is needed but unavailable.\n\t\tif external {\n\t\t\t// An external driver may fail to populate the Compiler/GOARCH fields,\n\t\t\t// especially since they are relatively new (see #63700).\n\t\t\t// Provide a sensible fallback in this case.\n\t\t\tld.sizes = types.SizesFor(\"gc\", runtime.GOARCH)\n\t\t\tif ld.sizes == nil { // gccgo-only arch\n\t\t\t\tld.sizes = types.SizesFor(\"gc\", \"amd64\")\n\t\t\t}\n\t\t} else {\n\t\t\t// Go list should never fail to deliver accurate size information.\n\t\t\t// Reject the whole Load since the error is the same for every package.\n\t\t\treturn nil, fmt.Errorf(\"can't determine type sizes for compiler %q on GOARCH %q\",\n\t\t\t\tresponse.Compiler, response.Arch)\n\t\t}\n\t}\n\n\tld.externalDriver = external\n\n\treturn ld.refine(response)\n}\n\n// defaultDriver is a driver that implements go/packages' fallback behavior.\n// It will try to request to an external driver, if one exists. If there's\n// no external driver, or the driver returns a response with NotHandled set,\n// defaultDriver will fall back to the go list driver.\n// The boolean result indicates that an external driver handled the request.\nfunc defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {\n\tconst (\n\t\t// windowsArgMax specifies the maximum command line length for\n\t\t// the Windows' CreateProcess function.\n\t\twindowsArgMax = 32767\n\t\t// maxEnvSize is a very rough estimation of the maximum environment\n\t\t// size of a user.\n\t\tmaxEnvSize = 16384\n\t\t// safeArgMax specifies the maximum safe command line length to use\n\t\t// by the underlying driver excl. the environment. We choose the Windows'\n\t\t// ARG_MAX as the starting point because it's one of the lowest ARG_MAX\n\t\t// constants out of the different supported platforms,\n\t\t// e.g., https://www.in-ulm.de/~mascheck/various/argmax/#results.\n\t\tsafeArgMax = windowsArgMax - maxEnvSize\n\t)\n\tchunks, err := splitIntoChunks(patterns, safeArgMax)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\n\tif driver := findExternalDriver(cfg); driver != nil {\n\t\tresponse, err := callDriverOnChunks(driver, cfg, chunks)\n\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t} else if !response.NotHandled {\n\t\t\treturn response, true, nil\n\t\t}\n\t\t// not handled: fall through\n\t}\n\n\t// go list fallback\n\n\t// Write overlays once, as there are many calls\n\t// to 'go list' (one per chunk plus others too).\n\toverlayFile, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\tdefer cleanupOverlay()\n\n\tvar runner gocommand.Runner // (shared across many 'go list' calls)\n\tdriver := func(cfg *Config, patterns []string) (*DriverResponse, error) {\n\t\treturn goListDriver(cfg, &runner, overlayFile, patterns)\n\t}\n\tresponse, err := callDriverOnChunks(driver, cfg, chunks)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\treturn response, false, err\n}\n\n// splitIntoChunks chunks the slice so that the total number of characters\n// in a chunk is no longer than argMax.\nfunc splitIntoChunks(patterns []string, argMax int) ([][]string, error) {\n\tif argMax <= 0 {\n\t\treturn nil, errors.New(\"failed to split patterns into chunks, negative safe argMax value\")\n\t}\n\tvar chunks [][]string\n\tcharsInChunk := 0\n\tnextChunkStart := 0\n\tfor i, v := range patterns {\n\t\tvChars := len(v)\n\t\tif vChars > argMax {\n\t\t\t// a single pattern is longer than the maximum safe ARG_MAX, hardly should happen\n\t\t\treturn nil, errors.New(\"failed to split patterns into chunks, a pattern is too long\")\n\t\t}\n\t\tcharsInChunk += vChars + 1 // +1 is for a whitespace between patterns that has to be counted too\n\t\tif charsInChunk > argMax {\n\t\t\tchunks = append(chunks, patterns[nextChunkStart:i])\n\t\t\tnextChunkStart = i\n\t\t\tcharsInChunk = vChars\n\t\t}\n\t}\n\t// add the last chunk\n\tif nextChunkStart < len(patterns) {\n\t\tchunks = append(chunks, patterns[nextChunkStart:])\n\t}\n\treturn chunks, nil\n}\n\nfunc callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) {\n\tif len(chunks) == 0 {\n\t\treturn driver(cfg, nil)\n\t}\n\tresponses := make([]*DriverResponse, len(chunks))\n\terrNotHandled := errors.New(\"driver returned NotHandled\")\n\tvar g errgroup.Group\n\tfor i, chunk := range chunks {\n\t\tg.Go(func() (err error) {\n\t\t\tresponses[i], err = driver(cfg, chunk)\n\t\t\tif responses[i] != nil && responses[i].NotHandled {\n\t\t\t\terr = errNotHandled\n\t\t\t}\n\t\t\treturn err\n\t\t})\n\t}\n\tif err := g.Wait(); err != nil {\n\t\tif errors.Is(err, errNotHandled) {\n\t\t\treturn &DriverResponse{NotHandled: true}, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn mergeResponses(responses...), nil\n}\n\nfunc mergeResponses(responses ...*DriverResponse) *DriverResponse {\n\tif len(responses) == 0 {\n\t\treturn nil\n\t}\n\t// No dedup needed\n\tif len(responses) == 1 {\n\t\treturn responses[0]\n\t}\n\tresponse := newDeduper()\n\tresponse.dr.NotHandled = false\n\tresponse.dr.Compiler = responses[0].Compiler\n\tresponse.dr.Arch = responses[0].Arch\n\tresponse.dr.GoVersion = responses[0].GoVersion\n\tfor _, v := range responses {\n\t\tresponse.addAll(v)\n\t}\n\treturn response.dr\n}\n\n// A Package describes a loaded Go package.\n//\n// It also defines part of the JSON schema of [DriverResponse].\n// See the package documentation for an overview.\ntype Package struct {\n\t// ID is a unique identifier for a package,\n\t// in a syntax provided by the underlying build system.\n\t//\n\t// Because the syntax varies based on the build system,\n\t// clients should treat IDs as opaque and not attempt to\n\t// interpret them.\n\tID string\n\n\t// Name is the package name as it appears in the package source code.\n\tName string\n\n\t// PkgPath is the package path as used by the go/types package.\n\tPkgPath string\n\n\t// Dir is the directory associated with the package, if it exists.\n\t//\n\t// For packages listed by the go command, this is the directory containing\n\t// the package files.\n\tDir string\n\n\t// Errors contains any errors encountered querying the metadata\n\t// of the package, or while parsing or type-checking its files.\n\tErrors []Error\n\n\t// TypeErrors contains the subset of errors produced during type checking.\n\tTypeErrors []types.Error\n\n\t// GoFiles lists the absolute file paths of the package's Go source files.\n\t// It may include files that should not be compiled, for example because\n\t// they contain non-matching build tags, are documentary pseudo-files such as\n\t// unsafe/unsafe.go or builtin/builtin.go, or are subject to cgo preprocessing.\n\tGoFiles []string\n\n\t// CompiledGoFiles lists the absolute file paths of the package's source\n\t// files that are suitable for type checking.\n\t// This may differ from GoFiles if files are processed before compilation.\n\tCompiledGoFiles []string\n\n\t// OtherFiles lists the absolute file paths of the package's non-Go source files,\n\t// including assembly, C, C++, Fortran, Objective-C, SWIG, and so on.\n\tOtherFiles []string\n\n\t// EmbedFiles lists the absolute file paths of the package's files\n\t// embedded with go:embed.\n\tEmbedFiles []string\n\n\t// EmbedPatterns lists the absolute file patterns of the package's\n\t// files embedded with go:embed.\n\tEmbedPatterns []string\n\n\t// IgnoredFiles lists source files that are not part of the package\n\t// using the current build configuration but that might be part of\n\t// the package using other build configurations.\n\tIgnoredFiles []string\n\n\t// ExportFile is the absolute path to a file containing type\n\t// information for the package as provided by the build system.\n\tExportFile string\n\n\t// Target is the absolute install path of the .a file, for libraries,\n\t// and of the executable file, for binaries.\n\tTarget string\n\n\t// Imports maps import paths appearing in the package's Go source files\n\t// to corresponding loaded Packages.\n\tImports map[string]*Package\n\n\t// Module is the module information for the package if it exists.\n\t//\n\t// Note: it may be missing for std and cmd; see Go issue #65816.\n\tModule *Module\n\n\t// -- The following fields are not part of the driver JSON schema. --\n\n\t// Types provides type information for the package.\n\t// The NeedTypes LoadMode bit sets this field for packages matching the\n\t// patterns; type information for dependencies may be missing or incomplete,\n\t// unless NeedDeps and NeedImports are also set.\n\t//\n\t// Each call to [Load] returns a consistent set of type\n\t// symbols, as defined by the comment at [types.Identical].\n\t// Avoid mixing type information from two or more calls to [Load].\n\tTypes *types.Package `json:\"-\"`\n\n\t// Fset provides position information for Types, TypesInfo, and Syntax.\n\t// It is set only when Types is set.\n\tFset *token.FileSet `json:\"-\"`\n\n\t// IllTyped indicates whether the package or any dependency contains errors.\n\t// It is set only when Types is set.\n\tIllTyped bool `json:\"-\"`\n\n\t// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.\n\t//\n\t// The NeedSyntax LoadMode bit populates this field for packages matching the patterns.\n\t// If NeedDeps and NeedImports are also set, this field will also be populated\n\t// for dependencies.\n\t//\n\t// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are\n\t// removed.  If parsing returned nil, Syntax may be shorter than CompiledGoFiles.\n\tSyntax []*ast.File `json:\"-\"`\n\n\t// TypesInfo provides type information about the package's syntax trees.\n\t// It is set only when Syntax is set.\n\tTypesInfo *types.Info `json:\"-\"`\n\n\t// TypesSizes provides the effective size function for types in TypesInfo.\n\tTypesSizes types.Sizes `json:\"-\"`\n\n\t// -- internal --\n\n\t// ForTest is the package under test, if any.\n\tForTest string\n\n\t// depsErrors is the DepsErrors field from the go list response, if any.\n\tdepsErrors []*packagesinternal.PackageError\n}\n\n// Module provides module information for a package.\n//\n// It also defines part of the JSON schema of [DriverResponse].\n// See the package documentation for an overview.\ntype Module struct {\n\tPath      string       // module path\n\tVersion   string       // module version\n\tReplace   *Module      // replaced by this module\n\tTime      *time.Time   // time version was created\n\tMain      bool         // is this the main module?\n\tIndirect  bool         // is this module only an indirect dependency of main module?\n\tDir       string       // directory holding files for this module, if any\n\tGoMod     string       // path to go.mod file used when loading this module, if any\n\tGoVersion string       // go version used in module\n\tError     *ModuleError // error loading module\n}\n\n// ModuleError holds errors loading a module.\ntype ModuleError struct {\n\tErr string // the error itself\n}\n\nfunc init() {\n\tpackagesinternal.GetDepsErrors = func(p any) []*packagesinternal.PackageError {\n\t\treturn p.(*Package).depsErrors\n\t}\n\tpackagesinternal.TypecheckCgo = int(typecheckCgo)\n\tpackagesinternal.DepsErrors = int(needInternalDepsErrors)\n}\n\n// An Error describes a problem with a package's metadata, syntax, or types.\ntype Error struct {\n\tPos  string // \"file:line:col\" or \"file:line\" or \"\" or \"-\"\n\tMsg  string\n\tKind ErrorKind\n}\n\n// ErrorKind describes the source of the error, allowing the user to\n// differentiate between errors generated by the driver, the parser, or the\n// type-checker.\ntype ErrorKind int\n\nconst (\n\tUnknownError ErrorKind = iota\n\tListError\n\tParseError\n\tTypeError\n)\n\nfunc (err Error) Error() string {\n\tpos := err.Pos\n\tif pos == \"\" {\n\t\tpos = \"-\" // like token.Position{}.String()\n\t}\n\treturn pos + \": \" + err.Msg\n}\n\n// flatPackage is the JSON form of Package\n// It drops all the type and syntax fields, and transforms the Imports\n//\n// TODO(adonovan): identify this struct with Package, effectively\n// publishing the JSON protocol.\ntype flatPackage struct {\n\tID              string\n\tName            string            `json:\",omitempty\"`\n\tPkgPath         string            `json:\",omitempty\"`\n\tErrors          []Error           `json:\",omitempty\"`\n\tGoFiles         []string          `json:\",omitempty\"`\n\tCompiledGoFiles []string          `json:\",omitempty\"`\n\tOtherFiles      []string          `json:\",omitempty\"`\n\tEmbedFiles      []string          `json:\",omitempty\"`\n\tEmbedPatterns   []string          `json:\",omitempty\"`\n\tIgnoredFiles    []string          `json:\",omitempty\"`\n\tExportFile      string            `json:\",omitempty\"`\n\tImports         map[string]string `json:\",omitempty\"`\n}\n\n// MarshalJSON returns the Package in its JSON form.\n// For the most part, the structure fields are written out unmodified, and\n// the type and syntax fields are skipped.\n// The imports are written out as just a map of path to package id.\n// The errors are written using a custom type that tries to preserve the\n// structure of error types we know about.\n//\n// This method exists to enable support for additional build systems.  It is\n// not intended for use by clients of the API and we may change the format.\nfunc (p *Package) MarshalJSON() ([]byte, error) {\n\tflat := &flatPackage{\n\t\tID:              p.ID,\n\t\tName:            p.Name,\n\t\tPkgPath:         p.PkgPath,\n\t\tErrors:          p.Errors,\n\t\tGoFiles:         p.GoFiles,\n\t\tCompiledGoFiles: p.CompiledGoFiles,\n\t\tOtherFiles:      p.OtherFiles,\n\t\tEmbedFiles:      p.EmbedFiles,\n\t\tEmbedPatterns:   p.EmbedPatterns,\n\t\tIgnoredFiles:    p.IgnoredFiles,\n\t\tExportFile:      p.ExportFile,\n\t}\n\tif len(p.Imports) > 0 {\n\t\tflat.Imports = make(map[string]string, len(p.Imports))\n\t\tfor path, ipkg := range p.Imports {\n\t\t\tflat.Imports[path] = ipkg.ID\n\t\t}\n\t}\n\treturn json.Marshal(flat)\n}\n\n// UnmarshalJSON reads in a Package from its JSON format.\n// See MarshalJSON for details about the format accepted.\nfunc (p *Package) UnmarshalJSON(b []byte) error {\n\tflat := &flatPackage{}\n\tif err := json.Unmarshal(b, &flat); err != nil {\n\t\treturn err\n\t}\n\t*p = Package{\n\t\tID:              flat.ID,\n\t\tName:            flat.Name,\n\t\tPkgPath:         flat.PkgPath,\n\t\tErrors:          flat.Errors,\n\t\tGoFiles:         flat.GoFiles,\n\t\tCompiledGoFiles: flat.CompiledGoFiles,\n\t\tOtherFiles:      flat.OtherFiles,\n\t\tEmbedFiles:      flat.EmbedFiles,\n\t\tEmbedPatterns:   flat.EmbedPatterns,\n\t\tIgnoredFiles:    flat.IgnoredFiles,\n\t\tExportFile:      flat.ExportFile,\n\t}\n\tif len(flat.Imports) > 0 {\n\t\tp.Imports = make(map[string]*Package, len(flat.Imports))\n\t\tfor path, id := range flat.Imports {\n\t\t\tp.Imports[path] = &Package{ID: id}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (p *Package) String() string { return p.ID }\n\n// loaderPackage augments Package with state used during the loading phase\ntype loaderPackage struct {\n\t*Package\n\timportErrors    map[string]error // maps each bad import to its error\n\tpreds           []*loaderPackage // packages that import this one\n\tunfinishedSuccs atomic.Int32     // number of direct imports not yet loaded\n\tcolor           uint8            // for cycle detection\n\tneedsrc         bool             // load from source (Mode >= LoadTypes)\n\tneedtypes       bool             // type information is either requested or depended on\n\tinitial         bool             // package was matched by a pattern\n\tgoVersion       int              // minor version number of go command on PATH\n}\n\n// loader holds the working state of a single call to load.\ntype loader struct {\n\tpkgs map[string]*loaderPackage // keyed by Package.ID\n\tConfig\n\tsizes          types.Sizes // non-nil if needed by mode\n\tparseCache     map[string]*parseValue\n\tparseCacheMu   sync.Mutex\n\texportMu       sync.Mutex // enforces mutual exclusion of exportdata operations\n\texternalDriver bool       // true if an external GOPACKAGESDRIVER handled the request\n\n\t// Config.Mode contains the implied mode (see impliedLoadMode).\n\t// Implied mode contains all the fields we need the data for.\n\t// In requestedMode there are the actually requested fields.\n\t// We'll zero them out before returning packages to the user.\n\t// This makes it easier for us to get the conditions where\n\t// we need certain modes right.\n\trequestedMode LoadMode\n}\n\ntype parseValue struct {\n\tf     *ast.File\n\terr   error\n\tready chan struct{}\n}\n\nfunc newLoader(cfg *Config) *loader {\n\tld := &loader{\n\t\tparseCache: map[string]*parseValue{},\n\t}\n\tif cfg != nil {\n\t\tld.Config = *cfg\n\t\t// If the user has provided a logger, use it.\n\t\tld.Config.Logf = cfg.Logf\n\t}\n\tif ld.Config.Logf == nil {\n\t\t// If the GOPACKAGESDEBUG environment variable is set to true,\n\t\t// but the user has not provided a logger, default to log.Printf.\n\t\tif debug {\n\t\t\tld.Config.Logf = log.Printf\n\t\t} else {\n\t\t\tld.Config.Logf = func(format string, args ...any) {}\n\t\t}\n\t}\n\tif ld.Config.Mode == 0 {\n\t\tld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility.\n\t}\n\tif ld.Config.Env == nil {\n\t\tld.Config.Env = os.Environ()\n\t}\n\tif ld.Context == nil {\n\t\tld.Context = context.Background()\n\t}\n\tif ld.Dir == \"\" {\n\t\tif dir, err := os.Getwd(); err == nil {\n\t\t\tld.Dir = dir\n\t\t}\n\t}\n\n\t// Save the actually requested fields. We'll zero them out before returning packages to the user.\n\tld.requestedMode = ld.Mode\n\tld.Mode = impliedLoadMode(ld.Mode)\n\n\tif ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 {\n\t\tif ld.Fset == nil {\n\t\t\tld.Fset = token.NewFileSet()\n\t\t}\n\n\t\t// ParseFile is required even in LoadTypes mode\n\t\t// because we load source if export data is missing.\n\t\tif ld.ParseFile == nil {\n\t\t\tld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {\n\t\t\t\t// We implicitly promise to keep doing ast.Object resolution. :(\n\t\t\t\tconst mode = parser.AllErrors | parser.ParseComments\n\t\t\t\treturn parser.ParseFile(fset, filename, src, mode)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ld\n}\n\n// refine connects the supplied packages into a graph and then adds type\n// and syntax information as requested by the LoadMode.\nfunc (ld *loader) refine(response *DriverResponse) ([]*Package, error) {\n\troots := response.Roots\n\trootMap := make(map[string]int, len(roots))\n\tfor i, root := range roots {\n\t\trootMap[root] = i\n\t}\n\tld.pkgs = make(map[string]*loaderPackage)\n\t// first pass, fixup and build the map and roots\n\tvar initial = make([]*loaderPackage, len(roots))\n\tfor _, pkg := range response.Packages {\n\t\trootIndex := -1\n\t\tif i, found := rootMap[pkg.ID]; found {\n\t\t\trootIndex = i\n\t\t}\n\n\t\t// Overlays can invalidate export data.\n\t\t// TODO(matloob): make this check fine-grained based on dependencies on overlaid files\n\t\texportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == \"\" && pkg.PkgPath != \"unsafe\"\n\t\t// This package needs type information if the caller requested types and the package is\n\t\t// either a root, or it's a non-root and the user requested dependencies ...\n\t\tneedtypes := (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))\n\t\t// This package needs source if the call requested source (or types info, which implies source)\n\t\t// and the package is either a root, or itas a non- root and the user requested dependencies...\n\t\tneedsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||\n\t\t\t// ... or if we need types and the exportData is invalid. We fall back to (incompletely)\n\t\t\t// typechecking packages from source if they fail to compile.\n\t\t\t(ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && exportDataInvalid)) && pkg.PkgPath != \"unsafe\"\n\t\tlpkg := &loaderPackage{\n\t\t\tPackage:   pkg,\n\t\t\tneedtypes: needtypes,\n\t\t\tneedsrc:   needsrc,\n\t\t\tgoVersion: response.GoVersion,\n\t\t}\n\t\tld.pkgs[lpkg.ID] = lpkg\n\t\tif rootIndex >= 0 {\n\t\t\tinitial[rootIndex] = lpkg\n\t\t\tlpkg.initial = true\n\t\t}\n\t}\n\tfor i, root := range roots {\n\t\tif initial[i] == nil {\n\t\t\treturn nil, fmt.Errorf(\"root package %v is missing\", root)\n\t\t}\n\t}\n\n\t// Materialize the import graph if it is needed (NeedImports),\n\t// or if we'll be using loadPackages (Need{Syntax|Types|TypesInfo}).\n\tvar leaves []*loaderPackage // packages with no unfinished successors\n\tif ld.Mode&(NeedImports|NeedSyntax|NeedTypes|NeedTypesInfo) != 0 {\n\t\tconst (\n\t\t\twhite = 0 // new\n\t\t\tgrey  = 1 // in progress\n\t\t\tblack = 2 // complete\n\t\t)\n\n\t\t// visit traverses the import graph, depth-first,\n\t\t// and materializes the graph as Packages.Imports.\n\t\t//\n\t\t// Valid imports are saved in the Packages.Import map.\n\t\t// Invalid imports (cycles and missing nodes) are saved in the importErrors map.\n\t\t// Thus, even in the presence of both kinds of errors,\n\t\t// the Import graph remains a DAG.\n\t\t//\n\t\t// visit returns whether the package needs src or has a transitive\n\t\t// dependency on a package that does. These are the only packages\n\t\t// for which we load source code.\n\t\tvar stack []*loaderPackage\n\t\tvar visit func(from, lpkg *loaderPackage) bool\n\t\tvisit = func(from, lpkg *loaderPackage) bool {\n\t\t\tif lpkg.color == grey {\n\t\t\t\tpanic(\"internal error: grey node\")\n\t\t\t}\n\t\t\tif lpkg.color == white {\n\t\t\t\tlpkg.color = grey\n\t\t\t\tstack = append(stack, lpkg) // push\n\t\t\t\tstubs := lpkg.Imports       // the structure form has only stubs with the ID in the Imports\n\t\t\t\tlpkg.Imports = make(map[string]*Package, len(stubs))\n\t\t\t\tfor importPath, ipkg := range stubs {\n\t\t\t\t\tvar importErr error\n\t\t\t\t\timp := ld.pkgs[ipkg.ID]\n\t\t\t\t\tif imp == nil {\n\t\t\t\t\t\t// (includes package \"C\" when DisableCgo)\n\t\t\t\t\t\timportErr = fmt.Errorf(\"missing package: %q\", ipkg.ID)\n\t\t\t\t\t} else if imp.color == grey {\n\t\t\t\t\t\timportErr = fmt.Errorf(\"import cycle: %s\", stack)\n\t\t\t\t\t}\n\t\t\t\t\tif importErr != nil {\n\t\t\t\t\t\tif lpkg.importErrors == nil {\n\t\t\t\t\t\t\tlpkg.importErrors = make(map[string]error)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlpkg.importErrors[importPath] = importErr\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tif visit(lpkg, imp) {\n\t\t\t\t\t\tlpkg.needsrc = true\n\t\t\t\t\t}\n\t\t\t\t\tlpkg.Imports[importPath] = imp.Package\n\t\t\t\t}\n\n\t\t\t\t// -- postorder --\n\n\t\t\t\t// Complete type information is required for the\n\t\t\t\t// immediate dependencies of each source package.\n\t\t\t\tif lpkg.needsrc && ld.Mode&NeedTypes != 0 {\n\t\t\t\t\tfor _, ipkg := range lpkg.Imports {\n\t\t\t\t\t\tld.pkgs[ipkg.ID].needtypes = true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// NeedTypeSizes causes TypeSizes to be set even\n\t\t\t\t// on packages for which types aren't needed.\n\t\t\t\tif ld.Mode&NeedTypesSizes != 0 {\n\t\t\t\t\tlpkg.TypesSizes = ld.sizes\n\t\t\t\t}\n\n\t\t\t\t// Add packages with no imports directly to the queue of leaves.\n\t\t\t\tif len(lpkg.Imports) == 0 {\n\t\t\t\t\tleaves = append(leaves, lpkg)\n\t\t\t\t}\n\n\t\t\t\tstack = stack[:len(stack)-1] // pop\n\t\t\t\tlpkg.color = black\n\t\t\t}\n\n\t\t\t// Add edge from predecessor.\n\t\t\tif from != nil {\n\t\t\t\tfrom.unfinishedSuccs.Add(+1) // incref\n\t\t\t\tlpkg.preds = append(lpkg.preds, from)\n\t\t\t}\n\n\t\t\treturn lpkg.needsrc\n\t\t}\n\n\t\t// For each initial package, create its import DAG.\n\t\tfor _, lpkg := range initial {\n\t\t\tvisit(nil, lpkg)\n\t\t}\n\n\t} else {\n\t\t// !NeedImports: drop the stub (ID-only) import packages\n\t\t// that we are not even going to try to resolve.\n\t\tfor _, lpkg := range initial {\n\t\t\tlpkg.Imports = nil\n\t\t}\n\t}\n\n\t// Load type data and syntax if needed, starting at\n\t// the initial packages (roots of the import DAG).\n\tif ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 {\n\n\t\t// We avoid using g.SetLimit to limit concurrency as\n\t\t// it makes g.Go stop accepting work, which prevents\n\t\t// workers from enqeuing, and thus finishing, and thus\n\t\t// allowing the group to make progress: deadlock.\n\t\t//\n\t\t// Instead we use the ioLimit and cpuLimit semaphores.\n\t\tg, _ := errgroup.WithContext(ld.Context)\n\n\t\t// enqueues adds a package to the type-checking queue.\n\t\t// It must have no unfinished successors.\n\t\tvar enqueue func(*loaderPackage)\n\t\tenqueue = func(lpkg *loaderPackage) {\n\t\t\tg.Go(func() error {\n\t\t\t\t// Parse and type-check.\n\t\t\t\tld.loadPackage(lpkg)\n\n\t\t\t\t// Notify each waiting predecessor,\n\t\t\t\t// and enqueue it when it becomes a leaf.\n\t\t\t\tfor _, pred := range lpkg.preds {\n\t\t\t\t\tif pred.unfinishedSuccs.Add(-1) == 0 { // decref\n\t\t\t\t\t\tenqueue(pred)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t})\n\t\t}\n\n\t\t// Load leaves first, adding new packages\n\t\t// to the queue as they become leaves.\n\t\tfor _, leaf := range leaves {\n\t\t\tenqueue(leaf)\n\t\t}\n\n\t\tif err := g.Wait(); err != nil {\n\t\t\treturn nil, err // cancelled\n\t\t}\n\t}\n\n\t// If the context is done, return its error and\n\t// throw out [likely] incomplete packages.\n\tif err := ld.Context.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tresult := make([]*Package, len(initial))\n\tfor i, lpkg := range initial {\n\t\tresult[i] = lpkg.Package\n\t}\n\tfor i := range ld.pkgs {\n\t\t// Clear all unrequested fields,\n\t\t// to catch programs that use more than they request.\n\t\tif ld.requestedMode&NeedName == 0 {\n\t\t\tld.pkgs[i].Name = \"\"\n\t\t\tld.pkgs[i].PkgPath = \"\"\n\t\t}\n\t\tif ld.requestedMode&NeedFiles == 0 {\n\t\t\tld.pkgs[i].GoFiles = nil\n\t\t\tld.pkgs[i].OtherFiles = nil\n\t\t\tld.pkgs[i].IgnoredFiles = nil\n\t\t}\n\t\tif ld.requestedMode&NeedEmbedFiles == 0 {\n\t\t\tld.pkgs[i].EmbedFiles = nil\n\t\t}\n\t\tif ld.requestedMode&NeedEmbedPatterns == 0 {\n\t\t\tld.pkgs[i].EmbedPatterns = nil\n\t\t}\n\t\tif ld.requestedMode&NeedCompiledGoFiles == 0 {\n\t\t\tld.pkgs[i].CompiledGoFiles = nil\n\t\t}\n\t\tif ld.requestedMode&NeedImports == 0 {\n\t\t\tld.pkgs[i].Imports = nil\n\t\t}\n\t\tif ld.requestedMode&NeedExportFile == 0 {\n\t\t\tld.pkgs[i].ExportFile = \"\"\n\t\t}\n\t\tif ld.requestedMode&NeedTypes == 0 {\n\t\t\tld.pkgs[i].Types = nil\n\t\t\tld.pkgs[i].IllTyped = false\n\t\t}\n\t\tif ld.requestedMode&NeedSyntax == 0 {\n\t\t\tld.pkgs[i].Syntax = nil\n\t\t}\n\t\tif ld.requestedMode&(NeedSyntax|NeedTypes|NeedTypesInfo) == 0 {\n\t\t\tld.pkgs[i].Fset = nil\n\t\t}\n\t\tif ld.requestedMode&NeedTypesInfo == 0 {\n\t\t\tld.pkgs[i].TypesInfo = nil\n\t\t}\n\t\tif ld.requestedMode&NeedTypesSizes == 0 {\n\t\t\tld.pkgs[i].TypesSizes = nil\n\t\t}\n\t\tif ld.requestedMode&NeedModule == 0 {\n\t\t\tld.pkgs[i].Module = nil\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// loadPackage loads/parses/typechecks the specified package.\n// It must be called only once per Package,\n// after immediate dependencies are loaded.\n// Precondition: ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0.\nfunc (ld *loader) loadPackage(lpkg *loaderPackage) {\n\tif lpkg.PkgPath == \"unsafe\" {\n\t\t// To avoid surprises, fill in the blanks consistent\n\t\t// with other packages. (For example, some analyzers\n\t\t// assert that each needed types.Info map is non-nil\n\t\t// even when there is no syntax that would cause them\n\t\t// to consult the map.)\n\t\tlpkg.Types = types.Unsafe\n\t\tlpkg.Fset = ld.Fset\n\t\tlpkg.Syntax = []*ast.File{}\n\t\tlpkg.TypesInfo = ld.newTypesInfo()\n\t\tlpkg.TypesSizes = ld.sizes\n\t\treturn\n\t}\n\n\t// Call NewPackage directly with explicit name.\n\t// This avoids skew between golist and go/types when the files'\n\t// package declarations are inconsistent.\n\tlpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)\n\tlpkg.Fset = ld.Fset\n\n\t// Start shutting down if the context is done and do not load\n\t// source or export data files.\n\t// Packages that import this one will have ld.Context.Err() != nil.\n\t// ld.Context.Err() will be returned later by refine.\n\tif ld.Context.Err() != nil {\n\t\treturn\n\t}\n\n\t// Subtle: we populate all Types fields with an empty Package\n\t// before loading export data so that export data processing\n\t// never has to create a types.Package for an indirect dependency,\n\t// which would then require that such created packages be explicitly\n\t// inserted back into the Import graph as a final step after export data loading.\n\t// (Hence this return is after the Types assignment.)\n\t// The Diamond test exercises this case.\n\tif !lpkg.needtypes && !lpkg.needsrc {\n\t\treturn\n\t}\n\n\t// TODO(adonovan): this condition looks wrong:\n\t// I think it should be lpkg.needtypes && !lpg.needsrc,\n\t// so that NeedSyntax without NeedTypes can be satisfied by export data.\n\tif !lpkg.needsrc {\n\t\tif err := ld.loadFromExportData(lpkg); err != nil {\n\t\t\tlpkg.Errors = append(lpkg.Errors, Error{\n\t\t\t\tPos:  \"-\",\n\t\t\t\tMsg:  err.Error(),\n\t\t\t\tKind: UnknownError, // e.g. can't find/open/parse export data\n\t\t\t})\n\t\t}\n\t\treturn // not a source package, don't get syntax trees\n\t}\n\n\tappendError := func(err error) {\n\t\t// Convert various error types into the one true Error.\n\t\tvar errs []Error\n\t\tswitch err := err.(type) {\n\t\tcase Error:\n\t\t\t// from driver\n\t\t\terrs = append(errs, err)\n\n\t\tcase *os.PathError:\n\t\t\t// from parser\n\t\t\terrs = append(errs, Error{\n\t\t\t\tPos:  err.Path + \":1\",\n\t\t\t\tMsg:  err.Err.Error(),\n\t\t\t\tKind: ParseError,\n\t\t\t})\n\n\t\tcase scanner.ErrorList:\n\t\t\t// from parser\n\t\t\tfor _, err := range err {\n\t\t\t\terrs = append(errs, Error{\n\t\t\t\t\tPos:  err.Pos.String(),\n\t\t\t\t\tMsg:  err.Msg,\n\t\t\t\t\tKind: ParseError,\n\t\t\t\t})\n\t\t\t}\n\n\t\tcase types.Error:\n\t\t\t// from type checker\n\t\t\tlpkg.TypeErrors = append(lpkg.TypeErrors, err)\n\t\t\terrs = append(errs, Error{\n\t\t\t\tPos:  err.Fset.Position(err.Pos).String(),\n\t\t\t\tMsg:  err.Msg,\n\t\t\t\tKind: TypeError,\n\t\t\t})\n\n\t\tdefault:\n\t\t\t// unexpected impoverished error from parser?\n\t\t\terrs = append(errs, Error{\n\t\t\t\tPos:  \"-\",\n\t\t\t\tMsg:  err.Error(),\n\t\t\t\tKind: UnknownError,\n\t\t\t})\n\n\t\t\t// If you see this error message, please file a bug.\n\t\t\tlog.Printf(\"internal error: error %q (%T) without position\", err, err)\n\t\t}\n\n\t\tlpkg.Errors = append(lpkg.Errors, errs...)\n\t}\n\n\t// If the go command on the PATH is newer than the runtime,\n\t// then the go/{scanner,ast,parser,types} packages from the\n\t// standard library may be unable to process the files\n\t// selected by go list.\n\t//\n\t// There is currently no way to downgrade the effective\n\t// version of the go command (see issue 52078), so we proceed\n\t// with the newer go command but, in case of parse or type\n\t// errors, we emit an additional diagnostic.\n\t//\n\t// See:\n\t// - golang.org/issue/52078 (flag to set release tags)\n\t// - golang.org/issue/50825 (gopls legacy version support)\n\t// - golang.org/issue/55883 (go/packages confusing error)\n\t//\n\t// Should we assert a hard minimum of (currently) go1.16 here?\n\tvar runtimeVersion int\n\tif _, err := fmt.Sscanf(runtime.Version(), \"go1.%d\", &runtimeVersion); err == nil && runtimeVersion < lpkg.goVersion {\n\t\tdefer func() {\n\t\t\tif len(lpkg.Errors) > 0 {\n\t\t\t\tappendError(Error{\n\t\t\t\t\tPos:  \"-\",\n\t\t\t\t\tMsg:  fmt.Sprintf(\"This application uses version go1.%d of the source-processing packages but runs version go1.%d of 'go list'. It may fail to process source files that rely on newer language features. If so, rebuild the application using a newer version of Go.\", runtimeVersion, lpkg.goVersion),\n\t\t\t\t\tKind: UnknownError,\n\t\t\t\t})\n\t\t\t}\n\t\t}()\n\t}\n\n\tif ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != \"\" {\n\t\t// The config requested loading sources and types, but sources are missing.\n\t\t// Add an error to the package and fall back to loading from export data.\n\t\tappendError(Error{\"-\", fmt.Sprintf(\"sources missing for package %s\", lpkg.ID), ParseError})\n\t\t_ = ld.loadFromExportData(lpkg) // ignore any secondary errors\n\n\t\treturn // can't get syntax trees for this package\n\t}\n\n\tfiles, errs := ld.parseFiles(lpkg.CompiledGoFiles)\n\tfor _, err := range errs {\n\t\tappendError(err)\n\t}\n\n\tlpkg.Syntax = files\n\tif ld.Config.Mode&(NeedTypes|NeedTypesInfo) == 0 {\n\t\treturn\n\t}\n\n\t// Start shutting down if the context is done and do not type check.\n\t// Packages that import this one will have ld.Context.Err() != nil.\n\t// ld.Context.Err() will be returned later by refine.\n\tif ld.Context.Err() != nil {\n\t\treturn\n\t}\n\n\tlpkg.TypesInfo = ld.newTypesInfo()\n\tlpkg.TypesSizes = ld.sizes\n\n\timporter := importerFunc(func(path string) (*types.Package, error) {\n\t\tif path == \"unsafe\" {\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\n\t\t// The imports map is keyed by import path.\n\t\tipkg := lpkg.Imports[path]\n\t\tif ipkg == nil {\n\t\t\tif err := lpkg.importErrors[path]; err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// There was skew between the metadata and the\n\t\t\t// import declarations, likely due to an edit\n\t\t\t// race, or because the ParseFile feature was\n\t\t\t// used to supply alternative file contents.\n\t\t\treturn nil, fmt.Errorf(\"no metadata for %s\", path)\n\t\t}\n\n\t\tif ipkg.Types != nil && ipkg.Types.Complete() {\n\t\t\treturn ipkg.Types, nil\n\t\t}\n\t\tlog.Fatalf(\"internal error: package %q without types was imported from %q\", path, lpkg)\n\t\tpanic(\"unreachable\")\n\t})\n\n\t// type-check\n\ttc := &types.Config{\n\t\tImporter: importer,\n\n\t\t// Type-check bodies of functions only in initial packages.\n\t\t// Example: for import graph A->B->C and initial packages {A,C},\n\t\t// we can ignore function bodies in B.\n\t\tIgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,\n\n\t\tError: appendError,\n\t\tSizes: ld.sizes, // may be nil\n\t}\n\tif lpkg.Module != nil && lpkg.Module.GoVersion != \"\" {\n\t\ttc.GoVersion = \"go\" + lpkg.Module.GoVersion\n\t} else if ld.externalDriver && lpkg.goVersion != 0 {\n\t\t// Module information is missing when GOPACKAGESDRIVER is used,\n\t\t// so use the go version from the driver response.\n\t\ttc.GoVersion = fmt.Sprintf(\"go1.%d\", lpkg.goVersion)\n\t}\n\tif (ld.Mode & typecheckCgo) != 0 {\n\t\tif !typesinternal.SetUsesCgo(tc) {\n\t\t\tappendError(Error{\n\t\t\t\tMsg:  \"typecheckCgo requires Go 1.15+\",\n\t\t\t\tKind: ListError,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Type-checking is CPU intensive.\n\tcpuLimit <- unit{}            // acquire a token\n\tdefer func() { <-cpuLimit }() // release a token\n\n\ttypErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)\n\tlpkg.importErrors = nil // no longer needed\n\n\t// In go/types go1.21 and go1.22, Checker.Files failed fast with a\n\t// a \"too new\" error, without calling tc.Error and without\n\t// proceeding to type-check the package (#66525).\n\t// We rely on the runtimeVersion error to give the suggested remedy.\n\tif typErr != nil && len(lpkg.Errors) == 0 && len(lpkg.Syntax) > 0 {\n\t\tif msg := typErr.Error(); strings.HasPrefix(msg, \"package requires newer Go version\") {\n\t\t\tappendError(types.Error{\n\t\t\t\tFset: ld.Fset,\n\t\t\t\tPos:  lpkg.Syntax[0].Package,\n\t\t\t\tMsg:  msg,\n\t\t\t})\n\t\t}\n\t}\n\n\t// If !Cgo, the type-checker uses FakeImportC mode, so\n\t// it doesn't invoke the importer for import \"C\",\n\t// nor report an error for the import,\n\t// or for any undefined C.f reference.\n\t// We must detect this explicitly and correctly\n\t// mark the package as IllTyped (by reporting an error).\n\t// TODO(adonovan): if these errors are annoying,\n\t// we could just set IllTyped quietly.\n\tif tc.FakeImportC {\n\touter:\n\t\tfor _, f := range lpkg.Syntax {\n\t\t\tfor _, imp := range f.Imports {\n\t\t\t\tif imp.Path.Value == `\"C\"` {\n\t\t\t\t\terr := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import \"C\" ignored`}\n\t\t\t\t\tappendError(err)\n\t\t\t\t\tbreak outer\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If types.Checker.Files had an error that was unreported,\n\t// make sure to report the unknown error so the package is illTyped.\n\tif typErr != nil && len(lpkg.Errors) == 0 {\n\t\tappendError(typErr)\n\t}\n\n\t// Record accumulated errors.\n\tillTyped := len(lpkg.Errors) > 0\n\tif !illTyped {\n\t\tfor _, imp := range lpkg.Imports {\n\t\t\tif imp.IllTyped {\n\t\t\t\tillTyped = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tlpkg.IllTyped = illTyped\n}\n\nfunc (ld *loader) newTypesInfo() *types.Info {\n\t// Populate TypesInfo only if needed, as it\n\t// causes the type checker to work much harder.\n\tif ld.Config.Mode&NeedTypesInfo == 0 {\n\t\treturn nil\n\t}\n\treturn &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n}\n\n// An importFunc is an implementation of the single-method\n// types.Importer interface based on a function value.\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n\n// We use a counting semaphore to limit\n// the number of parallel I/O calls or CPU threads per process.\nvar (\n\tioLimit  = make(chan unit, 20)\n\tcpuLimit = make(chan unit, runtime.GOMAXPROCS(0))\n)\n\nfunc (ld *loader) parseFile(filename string) (*ast.File, error) {\n\tld.parseCacheMu.Lock()\n\tv, ok := ld.parseCache[filename]\n\tif ok {\n\t\t// cache hit\n\t\tld.parseCacheMu.Unlock()\n\t\t<-v.ready\n\t} else {\n\t\t// cache miss\n\t\tv = &parseValue{ready: make(chan struct{})}\n\t\tld.parseCache[filename] = v\n\t\tld.parseCacheMu.Unlock()\n\n\t\tvar src []byte\n\t\tfor f, contents := range ld.Config.Overlay {\n\t\t\t// TODO(adonovan): Inefficient for large overlays.\n\t\t\t// Do an exact name-based map lookup\n\t\t\t// (for nonexistent files) followed by a\n\t\t\t// FileID-based map lookup (for existing ones).\n\t\t\tif sameFile(f, filename) {\n\t\t\t\tsrc = contents\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tvar err error\n\t\tif src == nil {\n\t\t\tioLimit <- unit{} // acquire a token\n\t\t\tsrc, err = os.ReadFile(filename)\n\t\t\t<-ioLimit // release a token\n\t\t}\n\t\tif err != nil {\n\t\t\tv.err = err\n\t\t} else {\n\t\t\t// Parsing is CPU intensive.\n\t\t\tcpuLimit <- unit{} // acquire a token\n\t\t\tv.f, v.err = ld.ParseFile(ld.Fset, filename, src)\n\t\t\t<-cpuLimit // release a token\n\t\t}\n\n\t\tclose(v.ready)\n\t}\n\treturn v.f, v.err\n}\n\n// parseFiles reads and parses the Go source files and returns the ASTs\n// of the ones that could be at least partially parsed, along with a\n// list of I/O and parse errors encountered.\n//\n// Because files are scanned in parallel, the token.Pos\n// positions of the resulting ast.Files are not ordered.\nfunc (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {\n\tvar (\n\t\tn      = len(filenames)\n\t\tparsed = make([]*ast.File, n)\n\t\terrors = make([]error, n)\n\t)\n\tvar g errgroup.Group\n\tfor i, filename := range filenames {\n\t\t// This creates goroutines unnecessarily in the\n\t\t// cache-hit case, but that case is uncommon.\n\t\tg.Go(func() error {\n\t\t\tparsed[i], errors[i] = ld.parseFile(filename)\n\t\t\treturn nil\n\t\t})\n\t}\n\tg.Wait()\n\n\t// Eliminate nils, preserving order.\n\tvar o int\n\tfor _, f := range parsed {\n\t\tif f != nil {\n\t\t\tparsed[o] = f\n\t\t\to++\n\t\t}\n\t}\n\tparsed = parsed[:o]\n\n\to = 0\n\tfor _, err := range errors {\n\t\tif err != nil {\n\t\t\terrors[o] = err\n\t\t\to++\n\t\t}\n\t}\n\terrors = errors[:o]\n\n\treturn parsed, errors\n}\n\n// sameFile returns true if x and y have the same basename and denote\n// the same file.\nfunc sameFile(x, y string) bool {\n\tif x == y {\n\t\t// It could be the case that y doesn't exist.\n\t\t// For instance, it may be an overlay file that\n\t\t// hasn't been written to disk. To handle that case\n\t\t// let x == y through. (We added the exact absolute path\n\t\t// string to the CompiledGoFiles list, so the unwritten\n\t\t// overlay case implies x==y.)\n\t\treturn true\n\t}\n\tif strings.EqualFold(filepath.Base(x), filepath.Base(y)) { // (optimisation)\n\t\tif xi, err := os.Stat(x); err == nil {\n\t\t\tif yi, err := os.Stat(y); err == nil {\n\t\t\t\treturn os.SameFile(xi, yi)\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// loadFromExportData ensures that type information is present for the specified\n// package, loading it from an export data file on the first request.\n// On success it sets lpkg.Types to a new Package.\nfunc (ld *loader) loadFromExportData(lpkg *loaderPackage) error {\n\tif lpkg.PkgPath == \"\" {\n\t\tlog.Fatalf(\"internal error: Package %s has no PkgPath\", lpkg)\n\t}\n\n\t// Because gcexportdata.Read has the potential to create or\n\t// modify the types.Package for each node in the transitive\n\t// closure of dependencies of lpkg, all exportdata operations\n\t// must be sequential. (Finer-grained locking would require\n\t// changes to the gcexportdata API.)\n\t//\n\t// The exportMu lock guards the lpkg.Types field and the\n\t// types.Package it points to, for each loaderPackage in the graph.\n\t//\n\t// Not all accesses to Package.Pkg need to be protected by exportMu:\n\t// graph ordering ensures that direct dependencies of source\n\t// packages are fully loaded before the importer reads their Pkg field.\n\tld.exportMu.Lock()\n\tdefer ld.exportMu.Unlock()\n\n\tif tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() {\n\t\treturn nil // cache hit\n\t}\n\n\tlpkg.IllTyped = true // fail safe\n\n\tif lpkg.ExportFile == \"\" {\n\t\t// Errors while building export data will have been printed to stderr.\n\t\treturn fmt.Errorf(\"no export data file\")\n\t}\n\tf, err := os.Open(lpkg.ExportFile)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\t// Read gc export data.\n\t//\n\t// We don't currently support gccgo export data because all\n\t// underlying workspaces use the gc toolchain. (Even build\n\t// systems that support gccgo don't use it for workspace\n\t// queries.)\n\tr, err := gcexportdata.NewReader(f)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading %s: %v\", lpkg.ExportFile, err)\n\t}\n\n\t// Build the view.\n\t//\n\t// The gcexportdata machinery has no concept of package ID.\n\t// It identifies packages by their PkgPath, which although not\n\t// globally unique is unique within the scope of one invocation\n\t// of the linker, type-checker, or gcexportdata.\n\t//\n\t// So, we must build a PkgPath-keyed view of the global\n\t// (conceptually ID-keyed) cache of packages and pass it to\n\t// gcexportdata. The view must contain every existing\n\t// package that might possibly be mentioned by the\n\t// current package---its transitive closure.\n\t//\n\t// In loadPackage, we unconditionally create a types.Package for\n\t// each dependency so that export data loading does not\n\t// create new ones.\n\t//\n\t// TODO(adonovan): it would be simpler and more efficient\n\t// if the export data machinery invoked a callback to\n\t// get-or-create a package instead of a map.\n\t//\n\tview := make(map[string]*types.Package) // view seen by gcexportdata\n\tseen := make(map[*loaderPackage]bool)   // all visited packages\n\tvar visit func(pkgs map[string]*Package)\n\tvisit = func(pkgs map[string]*Package) {\n\t\tfor _, p := range pkgs {\n\t\t\tlpkg := ld.pkgs[p.ID]\n\t\t\tif !seen[lpkg] {\n\t\t\t\tseen[lpkg] = true\n\t\t\t\tview[lpkg.PkgPath] = lpkg.Types\n\t\t\t\tvisit(lpkg.Imports)\n\t\t\t}\n\t\t}\n\t}\n\tvisit(lpkg.Imports)\n\n\tviewLen := len(view) + 1 // adding the self package\n\t// Parse the export data.\n\t// (May modify incomplete packages in view but not create new ones.)\n\ttpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading %s: %v\", lpkg.ExportFile, err)\n\t}\n\tif _, ok := view[\"go.shape\"]; ok {\n\t\t// Account for the pseudopackage \"go.shape\" that gets\n\t\t// created by generic code.\n\t\tviewLen++\n\t}\n\tif viewLen != len(view) {\n\t\tlog.Panicf(\"golang.org/x/tools/go/packages: unexpected new packages during load of %s\", lpkg.PkgPath)\n\t}\n\n\tlpkg.Types = tpkg\n\tlpkg.IllTyped = false\n\treturn nil\n}\n\n// impliedLoadMode returns loadMode with its dependencies.\nfunc impliedLoadMode(loadMode LoadMode) LoadMode {\n\tif loadMode&(NeedDeps|NeedTypes|NeedTypesInfo) != 0 {\n\t\t// All these things require knowing the import graph.\n\t\tloadMode |= NeedImports\n\t}\n\tif loadMode&NeedTypes != 0 {\n\t\t// Types require the GoVersion from Module.\n\t\tloadMode |= NeedModule\n\t}\n\n\treturn loadMode\n}\n\nfunc usesExportData(cfg *Config) bool {\n\treturn cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0\n}\n\ntype unit struct{}\n"
  },
  {
    "path": "go/packages/packages_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\tconstantpkg \"go/constant\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/packagestest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestMain(m *testing.M) {\n\ttestenv.ExitIfSmallMachine()\n\n\tos.Exit(m.Run())\n}\n\nfunc skipIfShort(t *testing.T, reason string) {\n\tif testing.Short() {\n\t\tt.Skipf(\"skipping slow test in short mode: %s\", reason)\n\t}\n}\n\n// testAllOrModulesParallel tests f, in parallel, against all packagestest\n// exporters in long mode, but only against the Modules exporter in short mode.\nfunc testAllOrModulesParallel(t *testing.T, f func(*testing.T, packagestest.Exporter)) {\n\tt.Parallel()\n\tpackagestest.TestAll(t, func(t *testing.T, exporter packagestest.Exporter) {\n\t\tt.Helper()\n\n\t\tswitch exporter.Name() {\n\t\tcase \"Modules\":\n\t\tcase \"GOPATH\":\n\t\t\tif testing.Short() {\n\t\t\t\tt.Skipf(\"skipping GOPATH test in short mode\")\n\t\t\t}\n\t\tdefault:\n\t\t\tt.Fatalf(\"unexpected exporter %q\", exporter.Name())\n\t\t}\n\n\t\tt.Parallel()\n\t\tf(t, exporter)\n\t})\n}\n\n// TODO(adonovan): more test cases to write:\n//\n// - When the tests fail, make them print a 'cd & load' command\n//   that will allow the maintainer to interact with the failing scenario.\n// - errors in go-list metadata\n// - a foo.test package that cannot be built for some reason (e.g.\n//   import error) will result in a JSON blob with no name and a\n//   nonexistent testmain file in GoFiles. Test that we handle this\n//   gracefully.\n// - test more Flags.\n//\n// LoadSyntax & LoadAllSyntax modes:\n//   - Fset may be user-supplied or not.\n//   - Packages.Info is correctly set.\n//   - typechecker configuration is honored\n//   - import cycles are gracefully handled in type checker.\n//   - test typechecking of generated test main and cgo.\n\n// The zero-value of Config has LoadFiles mode.\nfunc TestLoadZeroConfig(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tt.Parallel()\n\n\tinitial, err := packages.Load(nil, \"hash\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) != 1 {\n\t\tt.Fatalf(\"got %s, want [hash]\", initial)\n\t}\n\thash := initial[0]\n\t// Even though the hash package has imports,\n\t// they are not reported.\n\tgot := fmt.Sprintf(\"srcs=%v imports=%v\", srcs(hash), hash.Imports)\n\twant := \"srcs=[hash.go] imports=map[]\"\n\tif got != want {\n\t\tt.Fatalf(\"got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoadImportsGraph(t *testing.T) { testAllOrModulesParallel(t, testLoadImportsGraph) }\nfunc testLoadImportsGraph(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":             `package a; const A = 1`,\n\t\t\t\"b/b.go\":             `package b; import (\"golang.org/fake/a\"; _ \"container/list\"); var B = a.A`,\n\t\t\t\"c/c.go\":             `package c; import (_ \"golang.org/fake/b\"; _ \"unsafe\")`,\n\t\t\t\"c/c2.go\":            \"// +build ignore\\n\\n\" + `package c; import _ \"fmt\"`,\n\t\t\t\"subdir/d/d.go\":      `package d`,\n\t\t\t\"subdir/d/d_test.go\": `package d; import _ \"math/bits\"`,\n\t\t\t\"subdir/d/x_test.go\": `package d_test; import _ \"golang.org/fake/subdir/d\"`, // TODO(adonovan): test bad import here\n\t\t\t\"subdir/e/d.go\":      `package e`,\n\t\t\t\"e/e.go\":             `package main; import _ \"golang.org/fake/b\"`,\n\t\t\t\"e/e2.go\":            `package main; import _ \"golang.org/fake/c\"`,\n\t\t\t\"f/f.go\":             `package f`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = packages.LoadImports\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/c\", \"golang.org/fake/subdir/d\", \"golang.org/fake/e\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check graph topology.\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n  container/list\n  golang.org/fake/a\n  golang.org/fake/b\n* golang.org/fake/c\n* golang.org/fake/e\n* golang.org/fake/subdir/d\n* golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n* golang.org/fake/subdir/d.test\n* golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n  math/bits\n  unsafe\n  golang.org/fake/b -> container/list\n  golang.org/fake/b -> golang.org/fake/a\n  golang.org/fake/c -> golang.org/fake/b\n  golang.org/fake/c -> unsafe\n  golang.org/fake/e -> golang.org/fake/b\n  golang.org/fake/e -> golang.org/fake/c\n  golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n`[1:]\n\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\texported.Config.Tests = true\n\tinitial, err = packages.Load(exported.Config, \"golang.org/fake/c\", \"golang.org/fake/subdir/d\", \"golang.org/fake/e\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check graph topology.\n\tgraph, all := importGraph(initial)\n\twantGraph = `\n  container/list\n  golang.org/fake/a\n  golang.org/fake/b\n* golang.org/fake/c\n* golang.org/fake/e\n* golang.org/fake/subdir/d\n* golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n* golang.org/fake/subdir/d.test\n* golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n  math/bits\n  unsafe\n  golang.org/fake/b -> container/list\n  golang.org/fake/b -> golang.org/fake/a\n  golang.org/fake/c -> golang.org/fake/b\n  golang.org/fake/c -> unsafe\n  golang.org/fake/e -> golang.org/fake/b\n  golang.org/fake/e -> golang.org/fake/c\n  golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n`[1:]\n\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\t// Check node information: kind, name, srcs.\n\tfor _, test := range []struct {\n\t\tid          string\n\t\twantName    string\n\t\twantKind    string\n\t\twantSrcs    string // = {Go,Other,Embed}Files\n\t\twantIgnored string\n\t}{\n\t\t{\"golang.org/fake/a\", \"a\", \"package\", \"a.go\", \"\"},\n\t\t{\"golang.org/fake/b\", \"b\", \"package\", \"b.go\", \"\"},\n\t\t{\"golang.org/fake/c\", \"c\", \"package\", \"c.go\", \"c2.go\"}, // c2.go is ignored\n\t\t{\"golang.org/fake/e\", \"main\", \"command\", \"e.go e2.go\", \"\"},\n\t\t{\"container/list\", \"list\", \"package\", \"list.go\", \"\"},\n\t\t{\"golang.org/fake/subdir/d\", \"d\", \"package\", \"d.go\", \"\"},\n\t\t{\"golang.org/fake/subdir/d.test\", \"main\", \"command\", \"0.go\", \"\"},\n\t\t{\"unsafe\", \"unsafe\", \"package\", \"unsafe.go\", \"\"},\n\t} {\n\t\tp, ok := all[test.id]\n\t\tif !ok {\n\t\t\tt.Errorf(\"no package %s\", test.id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Name != test.wantName {\n\t\t\tt.Errorf(\"%s.Name = %q, want %q\", test.id, p.Name, test.wantName)\n\t\t}\n\n\t\t// kind\n\t\tvar kind string\n\t\tif p.Name == \"main\" {\n\t\t\tkind += \"command\"\n\t\t} else {\n\t\t\tkind += \"package\"\n\t\t}\n\t\tif kind != test.wantKind {\n\t\t\tt.Errorf(\"%s.Kind = %q, want %q\", test.id, kind, test.wantKind)\n\t\t}\n\n\t\tif srcs := strings.Join(srcs(p), \" \"); srcs != test.wantSrcs {\n\t\t\tt.Errorf(\"%s.{Go,Other,Embed}Files = [%s], want [%s]\", test.id, srcs, test.wantSrcs)\n\t\t}\n\t\tif ignored := strings.Join(cleanPaths(p.IgnoredFiles), \" \"); ignored != test.wantIgnored {\n\t\t\tt.Errorf(\"%s.IgnoredFiles = [%s], want [%s]\", test.id, ignored, test.wantIgnored)\n\t\t}\n\t}\n\n\t// Test an ad-hoc package, analogous to \"go run hello.go\".\n\tif initial, err := packages.Load(exported.Config, exported.File(\"golang.org/fake\", \"c/c.go\")); len(initial) == 0 {\n\t\tt.Errorf(\"failed to obtain metadata for ad-hoc package: %s\", err)\n\t} else {\n\t\tgot := fmt.Sprintf(\"%s %s\", initial[0].ID, srcs(initial[0]))\n\t\tif want := \"command-line-arguments [c.go]\"; got != want {\n\t\t\tt.Errorf(\"oops: got %s, want %s\", got, want)\n\t\t}\n\t}\n\n\t// Wildcards\n\t// See StdlibTest for effective test of \"std\" wildcard.\n\t// TODO(adonovan): test \"all\" returns everything in the current module.\n\t{\n\t\t// \"...\" (subdirectory)\n\t\tinitial, err = packages.Load(exported.Config, \"golang.org/fake/subdir/...\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgraph, _ = importGraph(initial)\n\t\twantGraph = `\n* golang.org/fake/subdir/d\n* golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n* golang.org/fake/subdir/d.test\n* golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n* golang.org/fake/subdir/e\n  math/bits\n  golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]\n  golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]\n`[1:]\n\n\t\tif graph != wantGraph {\n\t\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t\t}\n\t}\n}\n\nfunc TestLoadImportsTestVariants(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadImportsTestVariants)\n}\nfunc testLoadImportsTestVariants(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":       `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\":       `package b`,\n\t\t\t\"b/b_test.go\":  `package b`,\n\t\t\t\"b/bx_test.go\": `package b_test; import _ \"golang.org/fake/a\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = packages.LoadImports\n\texported.Config.Tests = true\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/b\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check graph topology.\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/a [golang.org/fake/b.test]\n* golang.org/fake/b\n* golang.org/fake/b [golang.org/fake/b.test]\n* golang.org/fake/b.test\n* golang.org/fake/b_test [golang.org/fake/b.test]\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/a [golang.org/fake/b.test] -> golang.org/fake/b [golang.org/fake/b.test]\n  golang.org/fake/b.test -> golang.org/fake/b [golang.org/fake/b.test]\n  golang.org/fake/b.test -> golang.org/fake/b_test [golang.org/fake/b.test]\n  golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/a [golang.org/fake/b.test]\n`[1:]\n\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\nfunc TestLoadAbsolutePath(t *testing.T) {\n\tt.Parallel()\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/gopatha\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a`,\n\t\t}}, {\n\t\tName: \"golang.org/gopathb\",\n\t\tFiles: map[string]any{\n\t\t\t\"b/b.go\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tinitial, err := packages.Load(exported.Config, filepath.Dir(exported.File(\"golang.org/gopatha\", \"a/a.go\")), filepath.Dir(exported.File(\"golang.org/gopathb\", \"b/b.go\")))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load imports: %v\", err)\n\t}\n\n\tgot := []string{}\n\tfor _, p := range initial {\n\t\tgot = append(got, p.ID)\n\t}\n\tsort.Strings(got)\n\twant := []string{\"golang.org/gopatha/a\", \"golang.org/gopathb/b\"}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Fatalf(\"initial packages loaded: got [%s], want [%s]\", got, want)\n\t}\n}\n\nfunc TestLoadArgumentListIsNotTooLong(t *testing.T) {\n\t// NOTE: this test adds about 2s to the test suite running time\n\n\tt.Parallel()\n\n\t// using the real ARG_MAX for some platforms increases the running time of this test by a lot,\n\t// 1_000_000 seems like enough to break Windows and macOS if Load doesn't split provided patterns\n\targMax := 1_000_000\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/mod\",\n\t\tFiles: map[string]any{\n\t\t\t\"main.go\": `package main\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\tnumOfPatterns := argMax/16 + 1 // the pattern below is approx. 16 chars\n\tpatterns := make([]string, numOfPatterns)\n\tfor i := range numOfPatterns {\n\t\tpatterns[i] = fmt.Sprintf(\"golang.org/mod/p%d\", i)\n\t} // patterns have more than argMax number of chars combined with whitespaces b/w patterns\n\n\t_, err := packages.Load(exported.Config, patterns...)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load: %v\", err)\n\t}\n}\n\nfunc TestLoadSamePackageMultipleChunks(t *testing.T) {\n\tt.Parallel()\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/def.go\": `package a; const SharedConstant = 42`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tdefFile := exported.File(\"golang.org/fake\", \"a/def.go\")\n\n\t// Force chunking (exceed ~16KB arg limit)\n\tvar files []string\n\tfiles = append(files, defFile)\n\n\tfor i := 0; i < 200; i++ {\n\t\tfillerPath := filepath.Join(filepath.Dir(defFile), fmt.Sprintf(\"filler_%03d.go\", i))\n\t\tif err := os.WriteFile(fillerPath, []byte(\"package a\\n\"), 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfiles = append(files, fillerPath)\n\t}\n\n\texported.Config.Mode = packages.NeedFiles\n\tpkgs, err := packages.Load(exported.Config, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(pkgs) == 0 {\n\t\tt.Fatal(\"package golang.org/fake/a not found\")\n\t}\n\n\tif len(pkgs[0].GoFiles) != len(files) {\n\t\tt.Errorf(\"expected %d files, got %d\", len(files), len(pkgs[0].GoFiles))\n\t}\n}\n\n// TestLoadDoesNotInvokeGit ensures that the expensive and unnecessary VCS check is skipped;\n// see go.dev/issue/51999 and go.dev/issue/77419.\nfunc TestLoadDoesNotInvokeGit(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tt.Parallel()\n\n\texported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"main.go\": `package main; func main() {}`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\t// mock a git repository by creating a .git directory\n\tmodRoot := filepath.Dir(exported.File(\"golang.org/fake\", \"main.go\"))\n\tif err := os.MkdirAll(filepath.Join(modRoot, \".git\"), 0755); err != nil {\n\t\tt.Fatalf(\"creating .git: %v\", err)\n\t}\n\n\tfakeGitDir := buildFakeGit(t, exported.Config.Env)\n\n\tpathVar := \"PATH\"\n\tif runtime.GOOS == \"plan9\" {\n\t\tpathVar = \"path\"\n\t}\n\texported.Config.Env = prependPath(exported.Config.Env, pathVar, fakeGitDir)\n\t// NeedTypes triggers usesExportData, which sets -export=true on the go list invocation\n\texported.Config.Mode = packages.NeedTypes\n\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake\")\n\tif err != nil {\n\t\tt.Fatalf(\"packages.Load: %v\", err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"packages.Load: expected 1 package, got %d: %v\", len(pkgs), pkgs)\n\t}\n\tif len(pkgs[0].Errors) > 0 {\n\t\t// Assume the failure was due to the fake git command being executed.\n\t\tt.Fatalf(\"packages.Load: unexpected errors (git should not have been called): %v\", pkgs[0].Errors)\n\t}\n}\n\n// buildFakeGit returns a directory containing a \"git\" executable that exits 1.\nfunc buildFakeGit(t *testing.T, env []string) string {\n\tt.Helper()\n\n\ttmpdir := t.TempDir()\n\tgitName := \"git\"\n\tif runtime.GOOS == \"windows\" {\n\t\tgitName = \"git.exe\"\n\t}\n\tsrc := filepath.Join(tmpdir, \"main.go\")\n\tif err := os.WriteFile(src, []byte(`package main; func main() { panic(\"git executed\") }`), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", gitName, \"main.go\")\n\tcmd.Dir = tmpdir\n\tcmd.Env = env\n\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"building fake git: %v\\n%s\", err, out)\n\t}\n\treturn tmpdir\n}\n\nfunc prependPath(env []string, key, dir string) []string {\n\tresult := make([]string, len(env))\n\tcopy(result, env)\n\tfor i, v := range result {\n\t\tif val, ok := strings.CutPrefix(v, key+\"=\"); ok {\n\t\t\tresult[i] = key + \"=\" + dir + string(os.PathListSeparator) + val\n\t\t\treturn result\n\t\t}\n\t}\n\treturn append(result, key+\"=\"+dir)\n}\n\nfunc TestVendorImports(t *testing.T) {\n\tt.Parallel()\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":          `package a; import _ \"b\"; import _ \"golang.org/fake/c\";`,\n\t\t\t\"a/vendor/b/b.go\": `package b; import _ \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\":          `package c; import _ \"b\"`,\n\t\t\t\"c/vendor/b/b.go\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = packages.LoadImports\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, all := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/a/vendor/b\n* golang.org/fake/c\n  golang.org/fake/c/vendor/b\n  golang.org/fake/a -> golang.org/fake/a/vendor/b\n  golang.org/fake/a -> golang.org/fake/c\n  golang.org/fake/a/vendor/b -> golang.org/fake/c\n  golang.org/fake/c -> golang.org/fake/c/vendor/b\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\tfor _, test := range []struct {\n\t\tpattern     string\n\t\twantImports string\n\t}{\n\t\t{\"golang.org/fake/a\", \"b:golang.org/fake/a/vendor/b golang.org/fake/c:golang.org/fake/c\"},\n\t\t{\"golang.org/fake/c\", \"b:golang.org/fake/c/vendor/b\"},\n\t\t{\"golang.org/fake/a/vendor/b\", \"golang.org/fake/c:golang.org/fake/c\"},\n\t\t{\"golang.org/fake/c/vendor/b\", \"\"},\n\t} {\n\t\t// Test the import paths.\n\t\tpkg := all[test.pattern]\n\t\tif imports := strings.Join(imports(pkg), \" \"); imports != test.wantImports {\n\t\t\tt.Errorf(\"package %q: got %s, want %s\", test.pattern, imports, test.wantImports)\n\t\t}\n\t}\n}\n\nfunc imports(p *packages.Package) []string {\n\tif p == nil {\n\t\treturn nil\n\t}\n\tkeys := make([]string, 0, len(p.Imports))\n\tfor k, v := range p.Imports {\n\t\tkeys = append(keys, fmt.Sprintf(\"%s:%s\", k, v.ID))\n\t}\n\tsort.Strings(keys)\n\treturn keys\n}\n\nfunc TestConfigDir(t *testing.T) { testAllOrModulesParallel(t, testConfigDir) }\nfunc testConfigDir(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":   `package a; const Name = \"a\" `,\n\t\t\t\"a/b/b.go\": `package b; const Name = \"a/b\"`,\n\t\t\t\"b/b.go\":   `package b; const Name = \"b\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\taDir := filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\"))\n\tbDir := filepath.Dir(exported.File(\"golang.org/fake\", \"b/b.go\"))\n\tbaseDir := filepath.Dir(aDir)\n\n\tfor _, test := range []struct {\n\t\tdir     string\n\t\tpattern string\n\t\twant    string // value of Name constant\n\t\tfails   bool\n\t}{\n\t\t{dir: bDir, pattern: \"golang.org/fake/a\", want: `\"a\"`},\n\t\t{dir: bDir, pattern: \"golang.org/fake/b\", want: `\"b\"`},\n\t\t{dir: bDir, pattern: \"./a\", fails: true},\n\t\t{dir: bDir, pattern: \"./b\", fails: true},\n\t\t{dir: baseDir, pattern: \"golang.org/fake/a\", want: `\"a\"`},\n\t\t{dir: baseDir, pattern: \"golang.org/fake/b\", want: `\"b\"`},\n\t\t{dir: baseDir, pattern: \"./a\", want: `\"a\"`},\n\t\t{dir: baseDir, pattern: \"./b\", want: `\"b\"`},\n\t\t{dir: aDir, pattern: \"golang.org/fake/a\", want: `\"a\"`},\n\t\t{dir: aDir, pattern: \"golang.org/fake/b\", want: `\"b\"`},\n\t\t{dir: aDir, pattern: \"./a\", fails: true},\n\t\t{dir: aDir, pattern: \"./b\", want: `\"a/b\"`},\n\t} {\n\t\texported.Config.Mode = packages.LoadSyntax // Use LoadSyntax to ensure that files can be opened.\n\t\texported.Config.Dir = test.dir\n\t\tinitial, err := packages.Load(exported.Config, test.pattern)\n\t\tvar got string\n\t\tfails := false\n\t\tif err != nil {\n\t\t\tfails = true\n\t\t} else if len(initial) > 0 {\n\t\t\tif len(initial[0].Errors) > 0 {\n\t\t\t\tfails = true\n\t\t\t} else if c := constant(initial[0], \"Name\"); c != nil {\n\t\t\t\tgot = c.Val().String()\n\t\t\t}\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"dir %q, pattern %q: got %s, want %s\",\n\t\t\t\ttest.dir, test.pattern, got, test.want)\n\t\t}\n\t\tif fails != test.fails {\n\t\t\tt.Errorf(\"dir %q, pattern %q: error %v, want %v\",\n\t\t\t\ttest.dir, test.pattern, fails, test.fails)\n\t\t}\n\t}\n}\n\nfunc TestConfigFlags(t *testing.T) { testAllOrModulesParallel(t, testConfigFlags) }\nfunc testConfigFlags(t *testing.T, exporter packagestest.Exporter) {\n\t// Test satisfying +build line tags, with -tags flag.\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t// package a\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/a/b\"`,\n\t\t\t\"a/b.go\": `// +build tag\n\npackage a`,\n\t\t\t\"a/c.go\": `// +build tag tag2\n\npackage a`,\n\t\t\t\"a/d.go\": `// +build tag,tag2\n\npackage a`,\n\t\t\t// package a/b\n\t\t\t\"a/b/a.go\": `package b`,\n\t\t\t\"a/b/b.go\": `// +build tag\n\npackage b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tfor _, test := range []struct {\n\t\tpattern        string\n\t\ttags           []string\n\t\twantSrcs       string\n\t\twantImportSrcs string\n\t}{\n\t\t{`golang.org/fake/a`, []string{}, \"a.go\", \"a.go\"},\n\t\t{`golang.org/fake/a`, []string{`-tags=tag`}, \"a.go b.go c.go\", \"a.go b.go\"},\n\t\t{`golang.org/fake/a`, []string{`-tags=tag2`}, \"a.go c.go\", \"a.go\"},\n\t\t{`golang.org/fake/a`, []string{`-tags=tag tag2`}, \"a.go b.go c.go d.go\", \"a.go b.go\"},\n\t} {\n\t\texported.Config.Mode = packages.LoadImports\n\t\texported.Config.BuildFlags = test.tags\n\n\t\tinitial, err := packages.Load(exported.Config, test.pattern)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\t\tif len(initial) != 1 {\n\t\t\tt.Errorf(\"test tags %v: pattern %s, expected 1 package, got %d packages.\", test.tags, test.pattern, len(initial))\n\t\t\tcontinue\n\t\t}\n\t\tpkg := initial[0]\n\t\tif srcs := strings.Join(srcs(pkg), \" \"); srcs != test.wantSrcs {\n\t\t\tt.Errorf(\"test tags %v: srcs of package %s = [%s], want [%s]\", test.tags, test.pattern, srcs, test.wantSrcs)\n\t\t}\n\t\tfor path, ipkg := range pkg.Imports {\n\t\t\tif srcs := strings.Join(srcs(ipkg), \" \"); srcs != test.wantImportSrcs {\n\t\t\t\tt.Errorf(\"build tags %v: srcs of imported package %s = [%s], want [%s]\", test.tags, path, srcs, test.wantImportSrcs)\n\t\t\t}\n\t\t}\n\n\t}\n}\n\nfunc TestLoadTypes(t *testing.T) { testAllOrModulesParallel(t, testLoadTypes) }\nfunc testLoadTypes(t *testing.T, exporter packagestest.Exporter) {\n\t// In LoadTypes and LoadSyntax modes, the compiler will\n\t// fail to generate an export data file for c, because it has\n\t// a type error.  The loader should fall back loading a and c\n\t// from source, but use the export data for b.\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"; import \"golang.org/fake/c\"; const A = \"a\" + b.B + c.C`,\n\t\t\t\"b/b.go\": `package b; const B = \"b\"`,\n\t\t\t\"c/c.go\": `package c; const C = \"c\" + 1`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadTypes\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, all := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/b\n  golang.org/fake/c\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/a -> golang.org/fake/c\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\tfor _, id := range []string{\n\t\t\"golang.org/fake/a\",\n\t\t\"golang.org/fake/b\",\n\t\t\"golang.org/fake/c\",\n\t} {\n\t\tp := all[id]\n\t\tif p == nil {\n\t\t\tt.Errorf(\"missing package: %s\", id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Types == nil {\n\t\t\tt.Errorf(\"missing types.Package for %s\", p)\n\t\t\tcontinue\n\t\t} else if !p.Types.Complete() {\n\t\t\tt.Errorf(\"incomplete types.Package for %s\", p)\n\t\t} else if p.TypesSizes == nil {\n\t\t\tt.Errorf(\"TypesSizes is not filled in for %s\", p)\n\t\t}\n\n\t}\n}\n\n// TestLoadTypesBits is equivalent to TestLoadTypes except that it only requests\n// the types using the NeedTypes bit.\nfunc TestLoadTypesBits(t *testing.T) { testAllOrModulesParallel(t, testLoadTypesBits) }\nfunc testLoadTypesBits(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"; const A = \"a\" + b.B`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"; const B = \"b\" + c.C`,\n\t\t\t\"c/c.go\": `package c; import \"golang.org/fake/d\"; const C = \"c\" + d.D`,\n\t\t\t\"d/d.go\": `package d; import \"golang.org/fake/e\"; const D = \"d\" + e.E`,\n\t\t\t\"e/e.go\": `package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F`,\n\t\t\t\"f/f.go\": `package f; const F = \"f\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedTypes | packages.NeedImports\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, all := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/b\n* golang.org/fake/c\n  golang.org/fake/d\n  golang.org/fake/e\n  golang.org/fake/f\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/b -> golang.org/fake/c\n  golang.org/fake/c -> golang.org/fake/d\n  golang.org/fake/d -> golang.org/fake/e\n  golang.org/fake/e -> golang.org/fake/f\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\tfor _, test := range []struct {\n\t\tid string\n\t}{\n\t\t{\"golang.org/fake/a\"},\n\t\t{\"golang.org/fake/b\"},\n\t\t{\"golang.org/fake/c\"},\n\t\t{\"golang.org/fake/d\"},\n\t\t{\"golang.org/fake/e\"},\n\t\t{\"golang.org/fake/f\"},\n\t} {\n\t\tp := all[test.id]\n\t\tif p == nil {\n\t\t\tt.Errorf(\"missing package: %s\", test.id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Types == nil {\n\t\t\tt.Errorf(\"missing types.Package for %s\", p)\n\t\t\tcontinue\n\t\t}\n\t\t// We don't request the syntax, so we shouldn't get it.\n\t\tif p.Syntax != nil {\n\t\t\tt.Errorf(\"Syntax unexpectedly provided for %s\", p)\n\t\t}\n\t\tif p.Errors != nil {\n\t\t\tt.Errorf(\"errors in package: %s: %s\", p, p.Errors)\n\t\t}\n\t}\n\n\t// Check value of constant.\n\taA := constant(all[\"golang.org/fake/a\"], \"A\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tif got, want := fmt.Sprintf(\"%v %v\", aA, aA.Val()), `const golang.org/fake/a.A untyped string \"abcdef\"`; got != want {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoadSyntaxOK(t *testing.T) { testAllOrModulesParallel(t, testLoadSyntaxOK) }\nfunc testLoadSyntaxOK(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"; const A = \"a\" + b.B`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"; const B = \"b\" + c.C`,\n\t\t\t\"c/c.go\": `package c; import \"golang.org/fake/d\"; const C = \"c\" + d.D`,\n\t\t\t\"d/d.go\": `package d; import \"golang.org/fake/e\"; const D = \"d\" + e.E`,\n\t\t\t\"e/e.go\": `package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F`,\n\t\t\t\"f/f.go\": `package f; const F = \"f\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadSyntax\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, all := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/b\n* golang.org/fake/c\n  golang.org/fake/d\n  golang.org/fake/e\n  golang.org/fake/f\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/b -> golang.org/fake/c\n  golang.org/fake/c -> golang.org/fake/d\n  golang.org/fake/d -> golang.org/fake/e\n  golang.org/fake/e -> golang.org/fake/f\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n\tfor _, test := range []struct {\n\t\tid           string\n\t\twantSyntax   bool\n\t\twantComplete bool\n\t}{\n\t\t{\"golang.org/fake/a\", true, true},   // source package\n\t\t{\"golang.org/fake/b\", true, true},   // source package because depends on initial package\n\t\t{\"golang.org/fake/c\", true, true},   // source package\n\t\t{\"golang.org/fake/d\", false, true},  // export data package\n\t\t{\"golang.org/fake/e\", false, false}, // export data package\n\t\t{\"golang.org/fake/f\", false, false}, // export data package\n\t} {\n\t\t// TODO(matloob): LoadSyntax and LoadAllSyntax are now equivalent, wantSyntax and wantComplete\n\t\t// are true for all packages in the transitive dependency set. Add test cases on the individual\n\t\t// Need* fields to check the equivalents on the new API.\n\t\tp := all[test.id]\n\t\tif p == nil {\n\t\t\tt.Errorf(\"missing package: %s\", test.id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Types == nil {\n\t\t\tt.Errorf(\"missing types.Package for %s\", p)\n\t\t\tcontinue\n\t\t} else if p.Types.Complete() != test.wantComplete {\n\t\t\tif test.wantComplete {\n\t\t\t\tt.Errorf(\"incomplete types.Package for %s\", p)\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"unexpected complete types.Package for %s\", p)\n\t\t\t}\n\t\t}\n\t\tif (p.Syntax != nil) != test.wantSyntax {\n\t\t\tif test.wantSyntax {\n\t\t\t\tt.Errorf(\"missing ast.Files for %s\", p)\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"unexpected ast.Files for for %s\", p)\n\t\t\t}\n\t\t}\n\t\tif p.Errors != nil {\n\t\t\tt.Errorf(\"errors in package: %s: %s\", p, p.Errors)\n\t\t}\n\t}\n\n\t// Check value of constant.\n\taA := constant(all[\"golang.org/fake/a\"], \"A\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tif got, want := fmt.Sprintf(\"%v %v\", aA, aA.Val()), `const golang.org/fake/a.A untyped string \"abcdef\"`; got != want {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestLoadDiamondTypes(t *testing.T) { testAllOrModulesParallel(t, testLoadDiamondTypes) }\nfunc testLoadDiamondTypes(t *testing.T, exporter packagestest.Exporter) {\n\t// We make a diamond dependency and check the type d.D is the same through both paths\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import (\"golang.org/fake/b\"; \"golang.org/fake/c\"); var _ = b.B == c.C`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/d\"; var B d.D`,\n\t\t\t\"c/c.go\": `package c; import \"golang.org/fake/d\"; var C d.D`,\n\t\t\t\"d/d.go\": `package d; type D int`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadSyntax\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor pkg := range packages.Postorder(initial) {\n\t\tfor _, err := range pkg.Errors {\n\t\t\tt.Errorf(\"package %s: %v\", pkg.ID, err)\n\t\t}\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n  golang.org/fake/b\n  golang.org/fake/c\n  golang.org/fake/d\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/a -> golang.org/fake/c\n  golang.org/fake/b -> golang.org/fake/d\n  golang.org/fake/c -> golang.org/fake/d\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\nfunc TestLoadSyntaxError(t *testing.T) { testAllOrModulesParallel(t, testLoadSyntaxError) }\nfunc testLoadSyntaxError(t *testing.T, exporter packagestest.Exporter) {\n\t// A type error in a lower-level package (e) prevents go list\n\t// from producing export data for all packages that depend on it\n\t// [a-e]. Only f should be loaded from export data, and the rest\n\t// should be IllTyped.\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"; const A = \"a\" + b.B`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"; const B = \"b\" + c.C`,\n\t\t\t\"c/c.go\": `package c; import \"golang.org/fake/d\"; const C = \"c\" + d.D`,\n\t\t\t\"d/d.go\": `package d; import \"golang.org/fake/e\"; const D = \"d\" + e.E`,\n\t\t\t\"e/e.go\": `package e; import \"golang.org/fake/f\"; const E = \"e\" + f.F + 1`, // type error\n\t\t\t\"f/f.go\": `package f; const F = \"f\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadSyntax\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tall := make(map[string]*packages.Package)\n\tfor p := range packages.Postorder(initial) {\n\t\tall[p.ID] = p\n\t}\n\n\tfor _, test := range []struct {\n\t\tid           string\n\t\twantSyntax   bool\n\t\twantIllTyped bool\n\t}{\n\t\t{\"golang.org/fake/a\", true, true},\n\t\t{\"golang.org/fake/b\", true, true},\n\t\t{\"golang.org/fake/c\", true, true},\n\t\t{\"golang.org/fake/d\", true, true},\n\t\t{\"golang.org/fake/e\", true, true},\n\t\t{\"golang.org/fake/f\", false, false},\n\t} {\n\t\tp := all[test.id]\n\t\tif p == nil {\n\t\t\tt.Errorf(\"missing package: %s\", test.id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Types == nil {\n\t\t\tt.Errorf(\"missing types.Package for %s\", p)\n\t\t\tcontinue\n\t\t} else if !p.Types.Complete() {\n\t\t\tt.Errorf(\"incomplete types.Package for %s\", p)\n\t\t}\n\t\tif (p.Syntax != nil) != test.wantSyntax {\n\t\t\tif test.wantSyntax {\n\t\t\t\tt.Errorf(\"missing ast.Files for %s\", test.id)\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"unexpected ast.Files for for %s\", test.id)\n\t\t\t}\n\t\t}\n\t\tif p.IllTyped != test.wantIllTyped {\n\t\t\tt.Errorf(\"IllTyped was %t for %s\", p.IllTyped, test.id)\n\t\t}\n\t}\n\n\t// Check value of constant.\n\taA := constant(all[\"golang.org/fake/a\"], \"A\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tif got, want := aA.String(), `const golang.org/fake/a.A invalid type`; got != want {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, want)\n\t}\n}\n\n// This function tests use of the ParseFile hook to modify\n// the AST after parsing.\nfunc TestParseFileModifyAST(t *testing.T) { testAllOrModulesParallel(t, testParseFileModifyAST) }\nfunc testParseFileModifyAST(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; const A = \"a\" `,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadAllSyntax\n\texported.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {\n\t\tconst mode = parser.AllErrors | parser.ParseComments\n\t\tf, err := parser.ParseFile(fset, filename, src, mode)\n\t\t// modify AST to change `const A = \"a\"` to `const A = \"b\"`\n\t\tspec := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec)\n\t\tspec.Values[0].(*ast.BasicLit).Value = `\"b\"`\n\t\treturn f, err\n\t}\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\n\t// Check value of a.A has been set to \"b\"\n\ta := initial[0]\n\tgot := constant(a, \"A\").Val().String()\n\tif got != `\"b\"` {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, `\"b\"`)\n\t}\n}\n\nfunc TestAdHocPackagesBadImport(t *testing.T) {\n\tt.Parallel()\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// This test doesn't use packagestest because we are testing ad-hoc packages,\n\t// which are outside of $GOPATH and outside of a module.\n\ttmp, err := os.MkdirTemp(\"\", \"a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmp)\n\n\tfilename := filepath.Join(tmp, \"a.go\")\n\tcontent := []byte(`package a\nimport _ \"badimport\"\nconst A = 1\n`)\n\tif err := os.WriteFile(filename, content, 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Make sure that the user's value of GO111MODULE does not affect test results.\n\tfor _, go111module := range []string{\"off\", \"auto\", \"on\"} {\n\t\tconfig := &packages.Config{\n\t\t\tEnv:  append(os.Environ(), \"GOPACKAGESDRIVER=off\", fmt.Sprintf(\"GO111MODULE=%s\", go111module)),\n\t\t\tDir:  tmp,\n\t\t\tMode: packages.LoadAllSyntax,\n\t\t\tLogf: t.Logf,\n\t\t}\n\t\tinitial, err := packages.Load(config, fmt.Sprintf(\"file=%s\", filename))\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t\tif len(initial) == 0 {\n\t\t\tt.Fatalf(\"no packages for %s with GO111MODULE=%s\", filename, go111module)\n\t\t}\n\t\t// Check value of a.A.\n\t\ta := initial[0]\n\t\t// There's an error because there's a bad import.\n\t\taA := constant(a, \"A\")\n\t\tif aA == nil {\n\t\t\tt.Errorf(\"a.A: got nil\")\n\t\t\treturn\n\t\t}\n\t\tgot := aA.Val().String()\n\t\tif want := \"1\"; got != want {\n\t\t\tt.Errorf(\"a.A: got %s, want %s\", got, want)\n\t\t}\n\t}\n}\n\nfunc TestLoadAllSyntaxImportErrors(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadAllSyntaxImportErrors)\n}\nfunc testLoadAllSyntaxImportErrors(t *testing.T, exporter packagestest.Exporter) {\n\t// TODO(matloob): Remove this once go list -e -compiled is fixed.\n\t// See https://golang.org/issue/26755\n\tt.Skip(\"go list -compiled -e fails with non-zero exit status for empty packages\")\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"unicycle/unicycle.go\": `package unicycle; import _ \"unicycle\"`,\n\t\t\t\"bicycle1/bicycle1.go\": `package bicycle1; import _ \"bicycle2\"`,\n\t\t\t\"bicycle2/bicycle2.go\": `package bicycle2; import _ \"bicycle1\"`,\n\t\t\t\"bad/bad.go\":           `not a package declaration`,\n\t\t\t\"empty/README.txt\":     `not a go file`,\n\t\t\t\"root/root.go\": `package root\nimport (\n\t_ \"bicycle1\"\n\t_ \"unicycle\"\n\t_ \"nonesuch\"\n\t_ \"empty\"\n\t_ \"bad\"\n)`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadAllSyntax\n\tinitial, err := packages.Load(exported.Config, \"root\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Cycle-forming edges are removed from the graph:\n\t// \tbicycle2 -> bicycle1\n\t//      unicycle -> unicycle\n\tgraph, all := importGraph(initial)\n\twantGraph := `\n  bicycle1\n  bicycle2\n* root\n  unicycle\n  bicycle1 -> bicycle2\n  root -> bicycle1\n  root -> unicycle\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\tfor _, test := range []struct {\n\t\tid       string\n\t\twantErrs []string\n\t}{\n\t\t{\"bicycle1\", nil},\n\t\t{\"bicycle2\", []string{\n\t\t\t\"could not import bicycle1 (import cycle: [root bicycle1 bicycle2])\",\n\t\t}},\n\t\t{\"unicycle\", []string{\n\t\t\t\"could not import unicycle (import cycle: [root unicycle])\",\n\t\t}},\n\t\t{\"root\", []string{\n\t\t\t`could not import bad (missing package: \"bad\")`,\n\t\t\t`could not import empty (missing package: \"empty\")`,\n\t\t\t`could not import nonesuch (missing package: \"nonesuch\")`,\n\t\t}},\n\t} {\n\t\tp := all[test.id]\n\t\tif p == nil {\n\t\t\tt.Errorf(\"missing package: %s\", test.id)\n\t\t\tcontinue\n\t\t}\n\t\tif p.Types == nil {\n\t\t\tt.Errorf(\"missing types.Package for %s\", test.id)\n\t\t}\n\t\tif p.Syntax == nil {\n\t\t\tt.Errorf(\"missing ast.Files for %s\", test.id)\n\t\t}\n\t\tif !p.IllTyped {\n\t\t\tt.Errorf(\"IllTyped was false for %s\", test.id)\n\t\t}\n\t\tif errs := errorMessages(p.Errors); !reflect.DeepEqual(errs, test.wantErrs) {\n\t\t\tt.Errorf(\"in package %s, got errors %s, want %s\", p, errs, test.wantErrs)\n\t\t}\n\t}\n}\n\nfunc TestAbsoluteFilenames(t *testing.T) { testAllOrModulesParallel(t, testAbsoluteFilenames) }\nfunc testAbsoluteFilenames(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":          `package a; const A = 1`,\n\t\t\t\"b/b.go\":          `package b; import (\"golang.org/fake/a\"; _ \"errors\"); var B = a.A`,\n\t\t\t\"b/vendor/a/a.go\": `package a; const A = 1`,\n\t\t\t\"c/c.go\":          `package c; import (_ \"golang.org/fake/b\"; _ \"unsafe\")`,\n\t\t\t\"c/c2.go\":         \"// +build ignore\\n\\n\" + `package c; import _ \"fmt\"`,\n\t\t\t\"subdir/d/d.go\":   `package d`,\n\t\t\t\"subdir/e/d.go\":   `package e`,\n\t\t\t\"e/e.go\":          `package main; import _ \"golang.org/fake/b\"`,\n\t\t\t\"e/e2.go\":         `package main; import _ \"golang.org/fake/c\"`,\n\t\t\t\"f/f.go\":          `package f`,\n\t\t\t\"f/f.s\":           ``,\n\t\t\t\"g/g.go\":          `package g; import _ \"embed\";` + \"\\n//go:embed g2.txt\\n\" + `var s string`,\n\t\t\t\"g/g2.txt\":        \"hello\",\n\t\t\t\"h/h.go\":          `package g; import _ \"embed\";` + \"\\n//go:embed a*.txt\\n\" + `var s string`,\n\t\t\t\"h/aa.txt\":        \"hello\",\n\t\t}}})\n\tdefer exported.Cleanup()\n\texported.Config.Dir = filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\")))\n\n\tcheckFile := func(filename string) {\n\t\tif !filepath.IsAbs(filename) {\n\t\t\tt.Errorf(\"filename is not absolute: %s\", filename)\n\t\t}\n\t\tif _, err := os.Stat(filename); err != nil {\n\t\t\tt.Errorf(\"stat error, %s: %v\", filename, err)\n\t\t}\n\t}\n\n\tfor _, test := range []struct {\n\t\tpattern string\n\t\twant    string\n\t}{\n\t\t// Import paths\n\t\t{\"golang.org/fake/a\", \"a.go\"},\n\t\t{\"golang.org/fake/b/vendor/a\", \"a.go\"},\n\t\t{\"golang.org/fake/b\", \"b.go\"},\n\t\t{\"golang.org/fake/c\", \"c.go\"},\n\t\t{\"golang.org/fake/subdir/d\", \"d.go\"},\n\t\t{\"golang.org/fake/subdir/e\", \"d.go\"},\n\t\t{\"golang.org/fake/e\", \"e.go e2.go\"},\n\t\t{\"golang.org/fake/f\", \"f.go f.s\"},\n\t\t{\"golang.org/fake/g\", \"g.go g2.txt\"},\n\t\t{\"golang.org/fake/h\", \"h.go aa.txt\"},\n\t\t// Relative paths\n\t\t{\"./a\", \"a.go\"},\n\t\t{\"./b/vendor/a\", \"a.go\"},\n\t\t{\"./b\", \"b.go\"},\n\t\t{\"./c\", \"c.go\"},\n\t\t{\"./subdir/d\", \"d.go\"},\n\t\t{\"./subdir/e\", \"d.go\"},\n\t\t{\"./e\", \"e.go e2.go\"},\n\t\t{\"./f\", \"f.go f.s\"},\n\t\t{\"./g\", \"g.go g2.txt\"},\n\t\t{\"./h\", \"h.go aa.txt\"},\n\t} {\n\t\texported.Config.Mode = packages.LoadFiles | packages.NeedEmbedFiles\n\t\tpkgs, err := packages.Load(exported.Config, test.pattern)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"pattern %s: %v\", test.pattern, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif got := strings.Join(srcs(pkgs[0]), \" \"); got != test.want {\n\t\t\tt.Errorf(\"in package %s, got %s, want %s\", test.pattern, got, test.want)\n\t\t}\n\n\t\t// Test that files in all packages exist and are absolute paths.\n\t\t_, all := importGraph(pkgs)\n\t\tfor _, pkg := range all {\n\t\t\tfor _, filename := range pkg.GoFiles {\n\t\t\t\tcheckFile(filename)\n\t\t\t}\n\t\t\tfor _, filename := range pkg.OtherFiles {\n\t\t\t\tcheckFile(filename)\n\t\t\t}\n\t\t\tfor _, filename := range pkg.EmbedFiles {\n\t\t\t\tcheckFile(filename)\n\t\t\t}\n\t\t\tfor _, filename := range pkg.IgnoredFiles {\n\t\t\t\tcheckFile(filename)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestContains(t *testing.T) { testAllOrModulesParallel(t, testContains) }\nfunc testContains(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\": `package c`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\tbFile := exported.File(\"golang.org/fake\", \"b/b.go\")\n\texported.Config.Mode = packages.LoadImports\n\tinitial, err := packages.Load(exported.Config, \"file=\"+bFile)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/b\n  golang.org/fake/c\n  golang.org/fake/b -> golang.org/fake/c\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\n// This test ensures that the effective GOARCH variable in the\n// application determines the Sizes function used by the type checker.\n// This behavior is a stop-gap until we make the build system's query\n// tool report the correct sizes function for the actual configuration.\nfunc TestSizes(t *testing.T) { testAllOrModulesParallel(t, testSizes) }\nfunc testSizes(t *testing.T, exporter packagestest.Exporter) {\n\t// Only run this test on operating systems that have both an amd64 and 386 port.\n\tswitch runtime.GOOS {\n\tcase \"linux\", \"windows\", \"freebsd\", \"openbsd\", \"netbsd\", \"android\":\n\tdefault:\n\t\tt.Skipf(\"skipping test on %s\", runtime.GOOS)\n\t}\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"unsafe\"; const WordSize = 8*unsafe.Sizeof(int(0))`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadSyntax\n\tsavedEnv := exported.Config.Env\n\tfor arch, wantWordSize := range map[string]int64{\"386\": 32, \"amd64\": 64} {\n\t\texported.Config.Env = append(savedEnv, \"GOARCH=\"+arch)\n\t\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif packages.PrintErrors(initial) > 0 {\n\t\t\tt.Fatal(\"there were errors\")\n\t\t}\n\t\tgotWordSize, _ := constantpkg.Int64Val(constant(initial[0], \"WordSize\").Val())\n\t\tif gotWordSize != wantWordSize {\n\t\t\tt.Errorf(\"for GOARCH=%s, got word size %d, want %d\", arch, gotWordSize, wantWordSize)\n\t\t}\n\t}\n}\n\n// This is a regression test for a bug related to\n// github.com/golang/vscode-go/issues/3021: if types are needed (any\n// of NeedTypes{,Info,Sizes} and the types.Sizes cannot be obtained\n// (e.g. due to a bad GOARCH) then the Load operation must fail. It\n// must not return a nil TypesSizes, or use the default (wrong) size.\n// (The root cause of that issue turned out to be due to skew in the\n// Bazel GOPACKAGESDRIVER; see CL 537876.)\n//\n// We use a file=... query because it suppresses the bad-GOARCH check\n// that the go command would otherwise perform eagerly.\n// (Gopls relies on this as a fallback.)\nfunc TestNeedTypeSizesWithBadGOARCH(t *testing.T) {\n\ttestAllOrModulesParallel(t, func(t *testing.T, exporter packagestest.Exporter) {\n\t\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\t\tName:  \"testdata\",\n\t\t\tFiles: map[string]any{\"a/a.go\": `package a`}}})\n\t\tdefer exported.Cleanup()\n\n\t\texported.Config.Mode = packages.NeedTypesSizes // or {,Info,Sizes}\n\t\texported.Config.Env = append(exported.Config.Env, \"GOARCH=286\")\n\t\t_, err := packages.Load(exported.Config, \"file=./a/a.go\")\n\t\tgot := fmt.Sprint(err)\n\t\twant := \"can't determine type sizes\"\n\t\tif !strings.Contains(got, want) {\n\t\t\tt.Errorf(\"Load error %q does not contain substring %q\", got, want)\n\t\t}\n\t})\n}\n\n// TestContainsFallbackSticks ensures that when there are both contains and non-contains queries\n// the decision whether to fallback to the pre-1.11 go list sticks across both sets of calls to\n// go list.\nfunc TestContainsFallbackSticks(t *testing.T) {\n\ttestAllOrModulesParallel(t, testContainsFallbackSticks)\n}\nfunc testContainsFallbackSticks(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\": `package c`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadImports\n\tbFile := exported.File(\"golang.org/fake\", \"b/b.go\")\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"file=\"+bFile)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* golang.org/fake/a\n* golang.org/fake/b\n  golang.org/fake/c\n  golang.org/fake/a -> golang.org/fake/b\n  golang.org/fake/b -> golang.org/fake/c\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n}\n\n// Test that Load with no patterns is equivalent to loading \".\" via the golist\n// driver.\nfunc TestNoPatterns(t *testing.T) { testAllOrModulesParallel(t, testNoPatterns) }\nfunc testNoPatterns(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":   `package a;`,\n\t\t\t\"a/b/b.go\": `package b;`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\taDir := filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\"))\n\texported.Config.Dir = aDir\n\n\tinitial, err := packages.Load(exported.Config)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) != 1 || initial[0].Name != \"a\" {\n\t\tt.Fatalf(`Load() = %v, wanted just the package in the current directory`, initial)\n\t}\n}\n\nfunc TestJSON(t *testing.T) { testAllOrModulesParallel(t, testJSON) }\nfunc testJSON(t *testing.T, exporter packagestest.Exporter) {\n\t// TODO: add in some errors\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; const A = 1`,\n\t\t\t\"b/b.go\": `package b; import \"golang.org/fake/a\"; var B = a.A`,\n\t\t\t\"c/c.go\": `package c; import \"golang.org/fake/b\" ; var C = b.B`,\n\t\t\t\"d/d.go\": `package d; import \"golang.org/fake/b\" ; var D = b.B`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadImports\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/c\", \"golang.org/fake/d\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Visit and print all packages.\n\tbuf := &bytes.Buffer{}\n\tenc := json.NewEncoder(buf)\n\tenc.SetIndent(\"\", \"\\t\")\n\tfor pkg := range packages.Postorder(initial) {\n\t\t// trim the source lists for stable results\n\t\tpkg.GoFiles = cleanPaths(pkg.GoFiles)\n\t\tpkg.CompiledGoFiles = cleanPaths(pkg.CompiledGoFiles)\n\t\tpkg.OtherFiles = cleanPaths(pkg.OtherFiles)\n\t\tpkg.IgnoredFiles = cleanPaths(pkg.IgnoredFiles)\n\t\tif err := enc.Encode(pkg); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\twantJSON := `\n{\n\t\"ID\": \"golang.org/fake/a\",\n\t\"Name\": \"a\",\n\t\"PkgPath\": \"golang.org/fake/a\",\n\t\"GoFiles\": [\n\t\t\"a.go\"\n\t],\n\t\"CompiledGoFiles\": [\n\t\t\"a.go\"\n\t]\n}\n{\n\t\"ID\": \"golang.org/fake/b\",\n\t\"Name\": \"b\",\n\t\"PkgPath\": \"golang.org/fake/b\",\n\t\"GoFiles\": [\n\t\t\"b.go\"\n\t],\n\t\"CompiledGoFiles\": [\n\t\t\"b.go\"\n\t],\n\t\"Imports\": {\n\t\t\"golang.org/fake/a\": \"golang.org/fake/a\"\n\t}\n}\n{\n\t\"ID\": \"golang.org/fake/c\",\n\t\"Name\": \"c\",\n\t\"PkgPath\": \"golang.org/fake/c\",\n\t\"GoFiles\": [\n\t\t\"c.go\"\n\t],\n\t\"CompiledGoFiles\": [\n\t\t\"c.go\"\n\t],\n\t\"Imports\": {\n\t\t\"golang.org/fake/b\": \"golang.org/fake/b\"\n\t}\n}\n{\n\t\"ID\": \"golang.org/fake/d\",\n\t\"Name\": \"d\",\n\t\"PkgPath\": \"golang.org/fake/d\",\n\t\"GoFiles\": [\n\t\t\"d.go\"\n\t],\n\t\"CompiledGoFiles\": [\n\t\t\"d.go\"\n\t],\n\t\"Imports\": {\n\t\t\"golang.org/fake/b\": \"golang.org/fake/b\"\n\t}\n}\n`[1:]\n\n\tif buf.String() != wantJSON {\n\t\tt.Errorf(\"wrong JSON: got <<%s>>, want <<%s>>\", buf.String(), wantJSON)\n\t}\n\t// now decode it again\n\tvar decoded []*packages.Package\n\tdec := json.NewDecoder(buf)\n\tfor dec.More() {\n\t\tp := new(packages.Package)\n\t\tif err := dec.Decode(p); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdecoded = append(decoded, p)\n\t}\n\tif len(decoded) != 4 {\n\t\tt.Fatalf(\"got %d packages, want 4\", len(decoded))\n\t}\n\tfor i, want := range []*packages.Package{{\n\t\tID:   \"golang.org/fake/a\",\n\t\tName: \"a\",\n\t}, {\n\t\tID:   \"golang.org/fake/b\",\n\t\tName: \"b\",\n\t\tImports: map[string]*packages.Package{\n\t\t\t\"golang.org/fake/a\": {ID: \"golang.org/fake/a\"},\n\t\t},\n\t}, {\n\t\tID:   \"golang.org/fake/c\",\n\t\tName: \"c\",\n\t\tImports: map[string]*packages.Package{\n\t\t\t\"golang.org/fake/b\": {ID: \"golang.org/fake/b\"},\n\t\t},\n\t}, {\n\t\tID:   \"golang.org/fake/d\",\n\t\tName: \"d\",\n\t\tImports: map[string]*packages.Package{\n\t\t\t\"golang.org/fake/b\": {ID: \"golang.org/fake/b\"},\n\t\t},\n\t}} {\n\t\tgot := decoded[i]\n\t\tif got.ID != want.ID {\n\t\t\tt.Errorf(\"Package %d has ID %q want %q\", i, got.ID, want.ID)\n\t\t}\n\t\tif got.Name != want.Name {\n\t\t\tt.Errorf(\"Package %q has Name %q want %q\", got.ID, got.Name, want.Name)\n\t\t}\n\t\tif len(got.Imports) != len(want.Imports) {\n\t\t\tt.Errorf(\"Package %q has %d imports want %d\", got.ID, len(got.Imports), len(want.Imports))\n\t\t\tcontinue\n\t\t}\n\t\tfor path, ipkg := range got.Imports {\n\t\t\tif want.Imports[path] == nil {\n\t\t\t\tt.Errorf(\"Package %q has unexpected import %q\", got.ID, path)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif want.Imports[path].ID != ipkg.ID {\n\t\t\t\tt.Errorf(\"Package %q import %q is %q want %q\", got.ID, path, ipkg.ID, want.Imports[path].ID)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestRejectInvalidQueries(t *testing.T) {\n\tt.Parallel()\n\n\tqueries := []string{\"key=\", \"key=value\"}\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadImports,\n\t\tEnv:  append(os.Environ(), \"GO111MODULE=off\", \"GOPACKAGESDRIVER=off\"),\n\t}\n\tfor _, q := range queries {\n\t\tif _, err := packages.Load(cfg, q); err == nil {\n\t\t\tt.Errorf(\"packages.Load(%q) succeeded. Expected \\\"invalid query type\\\" error\", q)\n\t\t} else if !strings.Contains(err.Error(), \"invalid query type\") {\n\t\t\tt.Errorf(\"packages.Load(%q): got error %v, want \\\"invalid query type\\\" error\", q, err)\n\t\t}\n\t}\n}\n\nfunc TestPatternPassthrough(t *testing.T) { testAllOrModulesParallel(t, testPatternPassthrough) }\nfunc testPatternPassthrough(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a;`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tinitial, err := packages.Load(exported.Config, \"pattern=a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgraph, _ := importGraph(initial)\n\twantGraph := `\n* a\n`[1:]\n\tif graph != wantGraph {\n\t\tt.Errorf(\"wrong import graph: got <<%s>>, want <<%s>>\", graph, wantGraph)\n\t}\n\n}\n\nfunc TestConfigDefaultEnv(t *testing.T) {\n\t// packagestest.TestAll instead of testAllOrModulesParallel because this test\n\t// can't be parallelized (it modifies the environment).\n\tpackagestest.TestAll(t, testConfigDefaultEnv)\n}\nfunc testConfigDefaultEnv(t *testing.T, exporter packagestest.Exporter) {\n\tconst driverJSON = `{\n  \"Roots\": [\"gopackagesdriver\"],\n  \"Packages\": [{\"ID\": \"gopackagesdriver\", \"Name\": \"gopackagesdriver\"}]\n}`\n\tvar (\n\t\tpathKey      string\n\t\tdriverScript packagestest.Writer\n\t)\n\tswitch runtime.GOOS {\n\tcase \"android\":\n\t\tt.Skip(\"doesn't run on android\")\n\tcase \"windows\":\n\t\t// TODO(jayconrod): write an equivalent batch script for windows.\n\t\t// Hint: \"type\" can be used to read a file to stdout.\n\t\tt.Skip(\"test requires sh\")\n\tcase \"plan9\":\n\t\tpathKey = \"path\"\n\t\tdriverScript = packagestest.Script(`#!/bin/rc\n\ncat <<'EOF'\n` + driverJSON + `\nEOF\n`)\n\tdefault:\n\t\tpathKey = \"PATH\"\n\t\tdriverScript = packagestest.Script(`#!/bin/sh\n\ncat - <<'EOF'\n` + driverJSON + `\nEOF\n`)\n\t}\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"bin/gopackagesdriver\": driverScript,\n\t\t\t\"golist/golist.go\":     \"package golist\",\n\t\t}}})\n\tdefer exported.Cleanup()\n\tdriver := exported.File(\"golang.org/fake\", \"bin/gopackagesdriver\")\n\tbinDir := filepath.Dir(driver)\n\tif err := os.Chmod(driver, 0755); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tpath, ok := os.LookupEnv(pathKey)\n\tvar pathWithDriver string\n\tif ok {\n\t\tpathWithDriver = binDir + string(os.PathListSeparator) + path\n\t} else {\n\t\tpathWithDriver = binDir\n\t}\n\tfor _, test := range []struct {\n\t\tdesc    string\n\t\tpath    string\n\t\tdriver  string\n\t\twantIDs string\n\t}{\n\t\t{\n\t\t\tdesc:    \"driver_off\",\n\t\t\tpath:    pathWithDriver,\n\t\t\tdriver:  \"off\",\n\t\t\twantIDs: \"[golist]\",\n\t\t}, {\n\t\t\tdesc:    \"driver_unset\",\n\t\t\tpath:    pathWithDriver,\n\t\t\tdriver:  \"\",\n\t\t\twantIDs: \"[gopackagesdriver]\",\n\t\t}, {\n\t\t\tdesc:    \"driver_set\",\n\t\t\tpath:    \"\",\n\t\t\tdriver:  driver,\n\t\t\twantIDs: \"[gopackagesdriver]\",\n\t\t},\n\t} {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\toldPath := os.Getenv(pathKey)\n\t\t\tos.Setenv(pathKey, test.path)\n\t\t\tdefer os.Setenv(pathKey, oldPath)\n\t\t\t// Clone exported.Config\n\t\t\tconfig := exported.Config\n\t\t\tconfig.Env = slices.Clone(exported.Config.Env)\n\t\t\tconfig.Env = append(config.Env, \"GOPACKAGESDRIVER=\"+test.driver)\n\t\t\tpkgs, err := packages.Load(exported.Config, \"golist\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tgotIds := make([]string, len(pkgs))\n\t\t\tfor i, pkg := range pkgs {\n\t\t\t\tgotIds[i] = pkg.ID\n\t\t\t}\n\t\t\tif fmt.Sprint(pkgs) != test.wantIDs {\n\t\t\t\tt.Errorf(\"got %v; want %v\", gotIds, test.wantIDs)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// This test that a simple x test package layout loads correctly.\n// There was a bug in go list where it returned multiple copies of the same\n// package (specifically in this case of golang.org/fake/a), and this triggered\n// a bug in go/packages where it would leave an empty entry in the root package\n// list. This would then cause a nil pointer crash.\n// This bug was triggered by the simple package layout below, and thus this\n// test will make sure the bug remains fixed.\nfunc TestBasicXTest(t *testing.T) { testAllOrModulesParallel(t, testBasicXTest) }\nfunc testBasicXTest(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":      `package a;`,\n\t\t\t\"a/a_test.go\": `package a_test;`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadFiles\n\texported.Config.Tests = true\n\t_, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestErrorMissingFile(t *testing.T) { testAllOrModulesParallel(t, testErrorMissingFile) }\nfunc testErrorMissingFile(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a_test.go\": `package a;`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadSyntax\n\texported.Config.Tests = false\n\tpkgs, err := packages.Load(exported.Config, \"missing.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) == 0 && runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"Issue #31344: the ad-hoc command-line-arguments package isn't created on windows\")\n\t}\n\tif len(pkgs) != 1 || (pkgs[0].PkgPath != \"command-line-arguments\" && pkgs[0].PkgPath != \"missing.go\") {\n\t\tt.Fatalf(\"packages.Load: want [command-line-arguments] or [missing.go], got %v\", pkgs)\n\t}\n\tif len(pkgs[0].Errors) == 0 {\n\t\tt.Errorf(\"result of Load: want package with errors, got none: %+v\", pkgs[0])\n\t}\n}\n\nfunc TestReturnErrorWhenUsingNonGoFiles(t *testing.T) {\n\ttestAllOrModulesParallel(t, testReturnErrorWhenUsingNonGoFiles)\n}\nfunc testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/gopatha\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a`,\n\t\t}}, {\n\t\tName: \"golang.org/gopathb\",\n\t\tFiles: map[string]any{\n\t\t\t\"b/b.c\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\tconfig := packages.Config{Env: append(os.Environ(), \"GOPACKAGESDRIVER=off\")}\n\tpkgs, err := packages.Load(&config, \"b/b.c\")\n\tif err != nil {\n\t\treturn\n\t}\n\t// Go <1.14 calls the package command-line-arguments while Go 1.14+ uses the file names.\n\tif len(pkgs) != 1 || (pkgs[0].PkgPath != \"command-line-arguments\" && pkgs[0].PkgPath != \"b/b.c\") {\n\t\tt.Fatalf(\"packages.Load: want [command-line-arguments] or [b/b.c], got %v\", pkgs)\n\t}\n\tif len(pkgs[0].Errors) != 1 {\n\t\tt.Fatalf(\"result of Load: want package with one error, got: %+v\", pkgs[0])\n\t}\n}\n\nfunc TestReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T) {\n\ttestAllOrModulesParallel(t, testReturnErrorWhenUsingGoFilesInMultipleDirectories)\n}\nfunc testReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/gopatha\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a`,\n\t\t\t\"b/b.go\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\twant := \"named files must all be in one directory\"\n\tpkgs, err := packages.Load(exported.Config, exported.File(\"golang.org/gopatha\", \"a/a.go\"), exported.File(\"golang.org/gopatha\", \"b/b.go\"))\n\tif err != nil {\n\t\t// Check if the error returned is the one we expected.\n\t\tif !strings.Contains(err.Error(), want) {\n\t\t\tt.Fatalf(\"want error message: %s, got: %s\", want, err.Error())\n\t\t}\n\t\treturn\n\t}\n\tif len(pkgs) != 1 || pkgs[0].PkgPath != \"command-line-arguments\" {\n\t\tt.Fatalf(\"packages.Load: want [command-line-arguments], got %v\", pkgs)\n\t}\n\tif len(pkgs[0].Errors) != 1 {\n\t\tt.Fatalf(\"result of Load: want package with one error, got: %+v\", pkgs[0])\n\t}\n\tgot := pkgs[0].Errors[0].Error()\n\tif !strings.Contains(got, want) {\n\t\tt.Fatalf(\"want error message: %s, got: %s\", want, got)\n\t}\n}\n\nfunc TestReturnErrorForUnexpectedDirectoryLayout(t *testing.T) {\n\ttestAllOrModulesParallel(t, testReturnErrorForUnexpectedDirectoryLayout)\n}\nfunc testReturnErrorForUnexpectedDirectoryLayout(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/gopatha\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/testdata/a.go\": `package a; import _ \"b\"`,\n\t\t\t\"a/vendor/b/b.go\": `package b; import _ \"fmt\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\twant := \"unexpected directory layout\"\n\t// triggering this error requires a relative package path\n\texported.Config.Dir = filepath.Dir(exported.File(\"golang.org/gopatha\", \"a/testdata/a.go\"))\n\tpkgs, err := packages.Load(exported.Config, \".\")\n\n\t// This error doesn't seem to occur in module mode; so only\n\t// complain if we get zero packages while also getting no error.\n\tif err == nil {\n\t\tif len(pkgs) == 0 {\n\t\t\t// TODO(dh): we'll need to expand on the error check if/when Go stops emitting this error\n\t\t\tt.Fatalf(\"want error, got nil\")\n\t\t}\n\t\treturn\n\t}\n\t// Check if the error returned is the one we expected.\n\tif !strings.Contains(err.Error(), want) {\n\t\tt.Fatalf(\"want error message: %s, got: %s\", want, err.Error())\n\t}\n}\n\nfunc TestMissingDependency(t *testing.T) { testAllOrModulesParallel(t, testMissingDependency) }\nfunc testMissingDependency(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"this/package/doesnt/exist\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.LoadAllSyntax\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 && pkgs[0].PkgPath != \"golang.org/fake/a\" {\n\t\tt.Fatalf(\"packages.Load: want [golang.org/fake/a], got %v\", pkgs)\n\t}\n\tif len(pkgs[0].Errors) == 0 {\n\t\tt.Errorf(\"result of Load: want package with errors, got none: %+v\", pkgs[0])\n\t}\n}\n\nfunc TestAdHocContains(t *testing.T) { testAllOrModulesParallel(t, testAdHocContains) }\nfunc testAdHocContains(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a;`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\ttmpfile, err := os.CreateTemp(\"\", \"adhoc*.go\")\n\tfilename := tmpfile.Name()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfmt.Fprint(tmpfile, `package main; import \"fmt\"; func main() { fmt.Println(\"time for coffee\") }`)\n\tif err := tmpfile.Close(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := os.Remove(filename); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\texported.Config.Mode = packages.NeedImports | packages.NeedFiles\n\tpkgs, err := packages.Load(exported.Config, \"file=\"+filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 && pkgs[0].PkgPath != \"command-line-arguments\" {\n\t\tt.Fatalf(\"packages.Load: want [command-line-arguments], got %v\", pkgs)\n\t}\n\tpkg := pkgs[0]\n\tif _, ok := pkg.Imports[\"fmt\"]; !ok || len(pkg.Imports) != 1 {\n\t\tt.Fatalf(\"Imports of loaded package: want [fmt], got %v\", pkg.Imports)\n\t}\n\tif len(pkg.GoFiles) != 1 || pkg.GoFiles[0] != filename {\n\t\tt.Fatalf(\"GoFiles of loaded package: want [%s], got %v\", filename, pkg.GoFiles)\n\t}\n}\n\nfunc TestCgoNoCcompiler(t *testing.T) { testAllOrModulesParallel(t, testCgoNoCcompiler) }\nfunc testCgoNoCcompiler(t *testing.T, exporter packagestest.Exporter) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a\nimport \"net/http\"\nconst A = http.MethodGet\n`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\t// Explicitly enable cgo but configure a nonexistent C compiler.\n\texported.Config.Env = append(exported.Config.Env, \"CGO_ENABLED=1\", \"CC=doesnotexist\")\n\texported.Config.Mode = packages.LoadAllSyntax\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check value of a.A.\n\ta := initial[0]\n\taA := constant(a, \"A\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tgot := aA.Val().String()\n\tif got != \"\\\"GET\\\"\" {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, \"\\\"GET\\\"\")\n\t}\n}\n\nfunc TestCgoMissingFile(t *testing.T) { testAllOrModulesParallel(t, testCgoMissingFile) }\nfunc testCgoMissingFile(t *testing.T, exporter packagestest.Exporter) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a\n\n// #include \"foo.h\"\nimport \"C\"\n\nconst A = 4\n`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\t// Explicitly enable cgo.\n\texported.Config.Env = append(exported.Config.Env, \"CGO_ENABLED=1\")\n\texported.Config.Mode = packages.LoadAllSyntax\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check value of a.A.\n\ta := initial[0]\n\taA := constant(a, \"A\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tgot := aA.Val().String()\n\tif got != \"4\" {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, \"4\")\n\t}\n}\n\nfunc TestLoadImportsC(t *testing.T) {\n\t// This test checks that when a package depends on the\n\t// test variant of \"syscall\", \"unsafe\", or \"runtime/cgo\", that dependency\n\t// is not removed when those packages are added when it imports \"C\".\n\t//\n\t// For this test to work, the external test of syscall must have a dependency\n\t// on net, and net must import \"syscall\" and \"C\".\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skipf(\"skipping on windows; packages on windows do not satisfy conditions for test.\")\n\t}\n\tif runtime.GOOS == \"plan9\" {\n\t\t// See https://golang.org/issue/27100.\n\t\tt.Skip(`skipping on plan9; for some reason \"net [syscall.test]\" is not loaded`)\n\t}\n\tt.Parallel()\n\ttestenv.NeedsGoPackages(t)\n\n\tcfg := &packages.Config{\n\t\tContext: t.Context(),\n\t\tMode:    packages.LoadImports,\n\t\tTests:   true,\n\t}\n\tinitial, err := packages.Load(cfg, \"syscall\", \"net\")\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load imports: %v\", err)\n\t}\n\n\t_, all := importGraph(initial)\n\n\tfor _, test := range []struct {\n\t\tpattern    string\n\t\twantImport string // an import to check for\n\t}{\n\t\t{\"net\", \"syscall:syscall\"},\n\t\t{\"net [syscall.test]\", \"syscall:syscall [syscall.test]\"},\n\t\t{\"syscall_test [syscall.test]\", \"net:net [syscall.test]\"},\n\t} {\n\t\t// Test the import paths.\n\t\tpkg := all[test.pattern]\n\t\tif pkg == nil {\n\t\t\tt.Errorf(\"package %q not loaded\", test.pattern)\n\t\t\tcontinue\n\t\t}\n\t\tif imports := strings.Join(imports(pkg), \" \"); !strings.Contains(imports, test.wantImport) {\n\t\t\tt.Errorf(\"package %q: got \\n%s, \\nwant to have %s\", test.pattern, imports, test.wantImport)\n\t\t}\n\t}\n}\n\nfunc TestCgoNoSyntax(t *testing.T) {\n\ttestAllOrModulesParallel(t, testCgoNoSyntax)\n}\nfunc testCgoNoSyntax(t *testing.T, exporter packagestest.Exporter) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"c/c.go\": `package c; import \"C\"`,\n\t\t},\n\t}})\n\n\t// Explicitly enable cgo.\n\texported.Config.Env = append(exported.Config.Env, \"CGO_ENABLED=1\")\n\n\tmodes := []packages.LoadMode{\n\t\tpackages.NeedTypes,\n\t\tpackages.NeedName | packages.NeedTypes,\n\t\tpackages.NeedName | packages.NeedTypes | packages.NeedImports,\n\t\tpackages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps,\n\t\tpackages.NeedName | packages.NeedImports,\n\t}\n\tfor _, mode := range modes {\n\t\tt.Run(fmt.Sprint(mode), func(t *testing.T) {\n\t\t\texported.Config.Mode = mode\n\t\t\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/c\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(pkgs) != 1 {\n\t\t\t\tt.Fatalf(\"Expected 1 package, got %v\", pkgs)\n\t\t\t}\n\t\t\tpkg := pkgs[0]\n\t\t\tif len(pkg.Errors) != 0 {\n\t\t\t\tt.Fatalf(\"Expected no errors in package, got %v\", pkg.Errors)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCgoBadPkgConfig(t *testing.T) {\n\ttestAllOrModulesParallel(t, testCgoBadPkgConfig)\n}\nfunc testCgoBadPkgConfig(t *testing.T, exporter packagestest.Exporter) {\n\tskipIfShort(t, \"builds and links a fake pkgconfig binary\")\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"c/c.go\": `package c\n\n// #cgo pkg-config: --cflags --  foo\nimport \"C\"`,\n\t\t},\n\t}})\n\n\tdir := buildFakePkgconfig(t, exported.Config.Env)\n\tdefer os.RemoveAll(dir)\n\tenv := exported.Config.Env\n\tfor i, v := range env {\n\t\tif strings.HasPrefix(v, \"PATH=\") {\n\t\t\tenv[i] = \"PATH=\" + dir + string(os.PathListSeparator) + v[len(\"PATH=\"):]\n\t\t}\n\t}\n\n\texported.Config.Env = append(exported.Config.Env, \"CGO_ENABLED=1\")\n\n\texported.Config.Mode = packages.NeedName | packages.NeedCompiledGoFiles\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Expected 1 package, got %v\", pkgs)\n\t}\n\tif pkgs[0].Name != \"c\" {\n\t\tt.Fatalf(\"Expected package to have name \\\"c\\\", got %q\", pkgs[0].Name)\n\t}\n}\n\nfunc buildFakePkgconfig(t *testing.T, env []string) string {\n\ttmpdir, err := os.MkdirTemp(\"\", \"fakepkgconfig\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = os.WriteFile(filepath.Join(tmpdir, \"pkg-config.go\"), []byte(`\npackage main\n\nimport \"fmt\"\nimport \"os\"\n\nfunc main() {\n\tfmt.Fprintln(os.Stderr, \"bad\")\n\tos.Exit(2)\n}\n`), 0644)\n\tif err != nil {\n\t\tos.RemoveAll(tmpdir)\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", \"pkg-config\", \"pkg-config.go\")\n\tcmd.Dir = tmpdir\n\tcmd.Env = env\n\n\tif b, err := cmd.CombinedOutput(); err != nil {\n\t\tos.RemoveAll(tmpdir)\n\t\tfmt.Println(os.Environ())\n\t\tt.Log(string(b))\n\t\tt.Fatal(err)\n\t}\n\treturn tmpdir\n}\n\nfunc TestIssue32814(t *testing.T) { testAllOrModulesParallel(t, testIssue32814) }\nfunc testIssue32814(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName:  \"golang.org/fake\",\n\t\tFiles: map[string]any{}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedName | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes\n\tpkgs, err := packages.Load(exported.Config, \"fmt\")\n\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(pkgs) != 1 && pkgs[0].PkgPath != \"fmt\" {\n\t\tt.Fatalf(\"packages.Load: want [fmt], got %v\", pkgs)\n\t}\n\tpkg := pkgs[0]\n\tif len(pkg.Errors) != 0 {\n\t\tt.Fatalf(\"Errors for fmt pkg: got %v, want none\", pkg.Errors)\n\t}\n\tif !pkg.Types.Complete() {\n\t\tt.Fatalf(\"Types.Complete() for fmt pkg: got %v, want true\", pkgs[0].Types.Complete())\n\n\t}\n}\n\nfunc TestLoadTypesInfoWithoutNeedDeps(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadTypesInfoWithoutNeedDeps)\n}\nfunc testLoadTypesInfoWithoutNeedDeps(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpkg := pkgs[0]\n\tif pkg.IllTyped {\n\t\tt.Fatal(\"Loaded package is ill typed\")\n\t}\n\tconst expectedImport = \"golang.org/fake/b\"\n\tif _, ok := pkg.Imports[expectedImport]; !ok || len(pkg.Imports) != 1 {\n\t\tt.Fatalf(\"Imports of loaded package: want [%s], got %v\", expectedImport, pkg.Imports)\n\t}\n}\n\nfunc TestLoadWithNeedDeps(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadWithNeedDeps)\n}\nfunc testLoadWithNeedDeps(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import _ \"golang.org/fake/c\"`,\n\t\t\t\"c/c.go\": `package c`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Expected 1 package, got %d\", len(pkgs))\n\t}\n\n\tpkgA := pkgs[0]\n\tif pkgA.IllTyped {\n\t\tt.Fatal(\"Loaded package is ill typed\")\n\t}\n\n\tpkgB := pkgA.Imports[\"golang.org/fake/b\"]\n\tif pkgB == nil || len(pkgA.Imports) != 1 {\n\t\tt.Fatalf(\"Imports of loaded package 'a' are invalid: %v\", pkgA.Imports)\n\t}\n\tif pkgB.Types == nil || !pkgB.Types.Complete() || pkgB.TypesInfo == nil {\n\t\tt.Fatalf(\"Types of package 'b' are nil or incomplete: %v, %v\", pkgB.Types, pkgB.TypesInfo)\n\t}\n\n\tpkgC := pkgB.Imports[\"golang.org/fake/c\"]\n\tif pkgC == nil || len(pkgB.Imports) != 1 {\n\t\tt.Fatalf(\"Imports of loaded package 'c' are invalid: %v\", pkgB.Imports)\n\t}\n\tif pkgC.Types == nil || !pkgC.Types.Complete() || pkgC.TypesInfo == nil {\n\t\tt.Fatalf(\"Types of package 'b' are nil or incomplete: %v, %v\", pkgC.Types, pkgC.TypesInfo)\n\t}\n}\n\nfunc TestImpliedLoadMode(t *testing.T) {\n\ttestAllOrModulesParallel(t, testImpliedLoadMode)\n}\nfunc testImpliedLoadMode(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Expected 1 package, got %d\", len(pkgs))\n\t}\n\n\tpkg := pkgs[0]\n\tif pkg.IllTyped {\n\t\tt.Fatalf(\"Loaded package is ill typed: %v\", pkg.Errors)\n\t}\n\n\t// Check that packages.NeedTypesInfo worked well.\n\tif !pkg.Types.Complete() {\n\t\tt.Fatalf(\"Loaded package types are incomplete\")\n\t}\n\n\t// Check that implied packages.NeedImports by packages.NeedTypesInfo\n\t// didn't add Imports.\n\tif len(pkg.Imports) != 0 {\n\t\tt.Fatalf(\"Package imports weren't requested but were returned: %v\", pkg.Imports)\n\t}\n}\n\nfunc TestIssue35331(t *testing.T) {\n\ttestAllOrModulesParallel(t, testIssue35331)\n}\nfunc testIssue35331(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |\n\t\tpackages.NeedImports | packages.NeedDeps | packages.NeedSyntax\n\texported.Config.Tests = false\n\tpkgs, err := packages.Load(exported.Config, \"strconv\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Expected 1 package, got %v\", pkgs)\n\t}\n\tfor pkg := range packages.Postorder(pkgs) {\n\t\tif len(pkg.Errors) > 0 {\n\t\t\tt.Errorf(\"Expected no errors in package %q, got %v\", pkg.ID, pkg.Errors)\n\t\t}\n\t\tif len(pkg.Syntax) == 0 && pkg.ID != \"unsafe\" {\n\t\t\tt.Errorf(\"Expected syntax on package %q, got none.\", pkg.ID)\n\t\t}\n\t}\n}\n\nfunc TestMultiplePackageVersionsIssue36188(t *testing.T) {\n\ttestAllOrModulesParallel(t, testMultiplePackageVersionsIssue36188)\n}\n\nfunc testMultiplePackageVersionsIssue36188(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package main`,\n\t\t}}})\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\", \"golang.org/fake/b\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tsort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })\n\tif len(pkgs) != 2 {\n\t\tt.Fatalf(\"expected two packages, got %v\", pkgs)\n\t}\n\tif pkgs[0].ID != \"golang.org/fake/a\" && pkgs[1].ID != \"golang.org/fake/b\" {\n\t\tt.Fatalf(`expected (sorted) IDs \"golang.org/fake/a\" and \"golang.org/fake/b\", got %q and %q`,\n\t\t\tpkgs[0].ID, pkgs[1].ID)\n\t}\n\tif pkgs[0].Errors == nil {\n\t\tt.Errorf(`expected error on package \"golang.org/fake/a\", got none`)\n\t}\n\tif pkgs[1].Errors != nil {\n\t\tt.Errorf(`expected no errors on package \"golang.org/fake/b\", got %v`, pkgs[1].Errors)\n\t}\n\tdefer exported.Cleanup()\n}\n\nfunc TestLoadModeStrings(t *testing.T) {\n\ttestcases := []struct {\n\t\tmode     packages.LoadMode\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tpackages.LoadMode(0),\n\t\t\t\"LoadMode(0)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName,\n\t\t\t\"NeedName\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedFiles,\n\t\t\t\"NeedFiles\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedCompiledGoFiles,\n\t\t\t\"NeedCompiledGoFiles\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedImports,\n\t\t\t\"NeedImports\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedDeps,\n\t\t\t\"NeedDeps\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedExportFile,\n\t\t\t\"NeedExportFile\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedTypes,\n\t\t\t\"NeedTypes\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedSyntax,\n\t\t\t\"NeedSyntax\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedTypesInfo,\n\t\t\t\"NeedTypesInfo\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedTypesSizes,\n\t\t\t\"NeedTypesSizes\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName | packages.NeedExportFile,\n\t\t\t\"(NeedName|NeedExportFile)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedForTest | packages.NeedTarget | packages.NeedEmbedFiles | packages.NeedEmbedPatterns,\n\t\t\t\"(NeedForTest|NeedEmbedFiles|NeedEmbedPatterns|NeedTarget)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedExportFile | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,\n\t\t\t\"(NeedName|NeedFiles|NeedCompiledGoFiles|NeedImports|NeedDeps|NeedExportFile|NeedTypes|NeedSyntax|NeedTypesInfo|NeedTypesSizes)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName | packages.NeedModule,\n\t\t\t\"(NeedName|NeedModule)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName | 0x100000, // off the end (future use)\n\t\t\t\"(NeedName|0x100000)\",\n\t\t},\n\t\t{\n\t\t\tpackages.NeedName | 0x400, // needInternalDepsErrors\n\t\t\t\"(NeedName|0x400)\",\n\t\t},\n\t\t{\n\t\t\t0x1000,\n\t\t\t\"LoadMode(0x1000)\",\n\t\t},\n\t}\n\n\tfor tcInd, tc := range testcases {\n\t\tt.Run(fmt.Sprintf(\"test-%d\", tcInd), func(t *testing.T) {\n\t\t\tactual := tc.mode.String()\n\t\t\tif tc.expected != actual {\n\t\t\t\tt.Errorf(\"want %#v, got %#v\", tc.expected, actual)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCycleImportStack(t *testing.T) {\n\ttestAllOrModulesParallel(t, testCycleImportStack)\n}\nfunc testCycleImportStack(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a; import _ \"golang.org/fake/b\"`,\n\t\t\t\"b/b.go\": `package b; import _ \"golang.org/fake/a\"`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedName | packages.NeedImports\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Expected 1 package, got %v\", pkgs)\n\t}\n\tpkg := pkgs[0]\n\tif len(pkg.Errors) != 1 {\n\t\tt.Fatalf(\"Expected one error in package, got %v\", pkg.Errors)\n\t}\n\texpected := \"import cycle not allowed: import stack: [golang.org/fake/a golang.org/fake/b golang.org/fake/a]\"\n\tif pkg.Errors[0].Msg != expected {\n\t\tt.Fatalf(\"Expected error %q, got %q\", expected, pkg.Errors[0].Msg)\n\t}\n}\n\nfunc TestForTestField(t *testing.T) {\n\ttestAllOrModulesParallel(t, testForTestField)\n}\nfunc testForTestField(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\":      `package a; func hello() {};`,\n\t\t\t\"a/a_test.go\": `package a; import \"testing\"; func TestA1(t *testing.T) {};`,\n\t\t\t\"a/x_test.go\": `package a_test; import \"testing\"; func TestA2(t *testing.T) {};`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\t// Add overlays to make sure they don't affect anything.\n\texported.Config.Overlay = map[string][]byte{\n\t\t\"a/a_test.go\": []byte(`package a; import \"testing\"; func TestA1(t *testing.T) { hello(); };`),\n\t\t\"a/x_test.go\": []byte(`package a_test; import \"testing\"; func TestA2(t *testing.T) { hello(); };`),\n\t}\n\texported.Config.Tests = true\n\texported.Config.Mode = packages.NeedName | packages.NeedImports\n\tforTest := \"golang.org/fake/a\"\n\tpkgs, err := packages.Load(exported.Config, forTest)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 4 {\n\t\tt.Errorf(\"expected 4 packages, got %v\", len(pkgs))\n\t}\n\tfor _, pkg := range pkgs {\n\t\tvar hasTestFile bool\n\t\tfor _, f := range pkg.CompiledGoFiles {\n\t\t\tif strings.Contains(f, \"a_test.go\") || strings.Contains(f, \"x_test.go\") {\n\t\t\t\thasTestFile = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !hasTestFile {\n\t\t\tcontinue\n\t\t}\n\t\tif got := pkg.ForTest; got != forTest {\n\t\t\tt.Errorf(\"expected %q, got %q\", forTest, got)\n\t\t}\n\t}\n}\n\nfunc TestIssue37629(t *testing.T) {\n\ttestAllOrModulesParallel(t, testIssue37629)\n}\nfunc testIssue37629(t *testing.T, exporter packagestest.Exporter) {\n\t// Tests #37629. When automatic vendoring is triggered, and we try to determine\n\t// the module root dir for a new overlay package, we previously would do a go list -m all,\n\t// which is incompatible with automatic vendoring.\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"c/c2.go\":             `package c`,\n\t\t\t\"a/a.go\":              `package a; import \"b.com/b\"; const A = b.B`,\n\t\t\t\"vendor/b.com/b/b.go\": `package b; const B = 4`,\n\t\t\t\"vendor/modules.txt\": `# b.com/b v1.0.0\n## explicit\nb.com/b`,\n\t\t}}, {\n\t\tName: \"b.com/b@v1.0.0\",\n\t\tFiles: map[string]any{\n\t\t\t\"arbitrary.txt\": \"\",\n\t\t}},\n\t})\n\trootDir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\")))\n\texported.Config.Overlay = map[string][]byte{\n\t\tfilepath.Join(rootDir, \"c/c.go\"): []byte(`package c; import \"golang.org/fake/a\"; const C = a.A`),\n\t}\n\texported.Config.Env = append(exported.Config.Env, \"GOFLAGS=-mod=vendor\")\n\texported.Config.Mode = packages.LoadAllSyntax\n\n\tdefer exported.Cleanup()\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/c\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check value of a.A.\n\ta := initial[0]\n\taA := constant(a, \"C\")\n\tif aA == nil {\n\t\tt.Fatalf(\"a.A: got nil\")\n\t}\n\tgot := aA.Val().String()\n\tif got != \"4\" {\n\t\tt.Errorf(\"a.A: got %s, want %s\", got, \"4\")\n\t}\n}\n\nfunc TestIssue37098(t *testing.T) { testAllOrModulesParallel(t, testIssue37098) }\nfunc testIssue37098(t *testing.T, exporter packagestest.Exporter) {\n\t// packages.Load should only return Go sources in\n\t// (*Package).CompiledGoFiles.  This tests #37098, where using SWIG to\n\t// causes C++ sources to be inadvertently included in\n\t// (*Package).CompiledGoFiles.\n\n\tif _, err := exec.LookPath(\"swig\"); err != nil {\n\t\tt.Skip(\"skipping test: swig not available\")\n\t}\n\tif _, err := exec.LookPath(\"g++\"); err != nil {\n\t\tt.Skip(\"skipping test: g++ not available\")\n\t}\n\n\t// Create a fake package with an empty Go source, and a SWIG interface\n\t// file.\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t// The \"package\" statement must be included for SWIG sources to\n\t\t\t// be generated.\n\t\t\t\"a/a.go\":      \"package a\",\n\t\t\t\"a/a.swigcxx\": \"\",\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load the package: %v\", err)\n\t}\n\t// Try and parse each of the files\n\tfor _, pkg := range initial {\n\t\tfor _, file := range pkg.CompiledGoFiles {\n\n\t\t\t// Validate that each file can be parsed as a Go source.\n\t\t\tfset := token.NewFileSet()\n\t\t\t_, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Failed to parse file '%s' as a Go source: %v\", file, err)\n\n\t\t\t\tcontents, err := os.ReadFile(file)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"Failed to read the un-parsable file '%s': %v\", file, err)\n\t\t\t\t}\n\n\t\t\t\t// Print out some of the un-parsable file to aid in debugging.\n\t\t\t\tn := len(contents)\n\n\t\t\t\t// Don't print the whole file if it is too large.\n\t\t\t\tconst maxBytes = 1000\n\t\t\t\tif n > maxBytes {\n\t\t\t\t\tn = maxBytes\n\t\t\t\t}\n\n\t\t\t\tt.Logf(\"First %d bytes of un-parsable file: %s\", n, contents[:n])\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestIssue56632 checks that CompiledGoFiles does not contain non-go files regardless of\n// whether the NeedFiles mode bit is set.\nfunc TestIssue56632(t *testing.T) {\n\tt.Parallel()\n\ttestenv.NeedsGoBuild(t)\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName: \"golang.org/issue56632\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a`,\n\t\t\t\"a/a_cgo.go\": `package a\n\nimport \"C\"`,\n\t\t\t\"a/a.s\": ``,\n\t\t\t\"a/a.c\": ``,\n\t\t}}})\n\tdefer exported.Cleanup()\n\n\tmodes := []packages.LoadMode{packages.NeedCompiledGoFiles, packages.NeedCompiledGoFiles | packages.NeedFiles, packages.NeedImports | packages.NeedCompiledGoFiles, packages.NeedImports | packages.NeedFiles | packages.NeedCompiledGoFiles}\n\tfor _, mode := range modes {\n\t\texported.Config.Mode = mode\n\n\t\tinitial, err := packages.Load(exported.Config, \"golang.org/issue56632/a\")\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"failed to load package: %v\", err)\n\t\t}\n\n\t\tif len(initial) != 1 {\n\t\t\tt.Errorf(\"expected 3 packages, got %d\", len(initial))\n\t\t}\n\n\t\tp := initial[0]\n\n\t\tif len(p.Errors) != 0 {\n\t\t\tt.Errorf(\"expected no errors, got %v\", p.Errors)\n\t\t}\n\n\t\tfor _, f := range p.CompiledGoFiles {\n\t\t\tif strings.HasSuffix(f, \".s\") || strings.HasSuffix(f, \".c\") {\n\t\t\t\tt.Errorf(\"expected no non-Go CompiledGoFiles, got file %q in CompiledGoFiles\", f)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestInvalidFilesInXTest checks the fix for golang/go#37971 in Go 1.15.\nfunc TestInvalidFilesInXTest(t *testing.T) { testAllOrModulesParallel(t, testInvalidFilesInXTest) }\nfunc testInvalidFilesInXTest(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"d/d.go\":      `package d; import \"net/http\"; const d = http.MethodGet; func Get() string { return d; }`,\n\t\t\t\t\"d/d2.go\":     ``, // invalid file\n\t\t\t\t\"d/d_test.go\": `package d_test; import \"testing\"; import \"golang.org/fake/d\"; func TestD(t *testing.T) { d.Get(); }`,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedName | packages.NeedFiles\n\texported.Config.Tests = true\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/d\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) != 3 {\n\t\tt.Errorf(\"expected 3 packages, got %d\", len(initial))\n\t}\n}\n\nfunc TestTypecheckCgo(t *testing.T) { testAllOrModulesParallel(t, testTypecheckCgo) }\nfunc testTypecheckCgo(t *testing.T, exporter packagestest.Exporter) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\tconst cgo = `package cgo\n\t\timport \"C\"\n\n\t\tfunc Example() {\n\t\t\tC.CString(\"hi\")\n\t\t}\n\t`\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"cgo/cgo.go\": cgo,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedFiles | packages.NeedCompiledGoFiles |\n\t\tpackages.NeedSyntax | packages.NeedDeps | packages.NeedTypes |\n\t\tpackages.LoadMode(packagesinternal.TypecheckCgo)\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/cgo\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpkg := initial[0]\n\tif len(pkg.Errors) != 0 {\n\t\tt.Fatalf(\"package has errors: %v\", pkg.Errors)\n\t}\n\n\texpos := pkg.Types.Scope().Lookup(\"Example\").Pos()\n\tfname := pkg.Fset.File(expos).Name()\n\tif !strings.HasSuffix(fname, \"cgo.go\") {\n\t\tt.Errorf(\"position for cgo package was loaded from %v, wanted cgo.go\", fname)\n\t}\n}\n\n// TestIssue48226 ensures that when NeedSyntax is provided we do not nullify the\n// Fset, which is needed to resolve the syntax tree element positions to files.\nfunc TestIssue48226(t *testing.T) { testAllOrModulesParallel(t, testIssue48226) }\nfunc testIssue48226(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake/syntax\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"syntax.go\": `package test`,\n\t\t\t},\n\t\t},\n\t})\n\tdefer exported.Cleanup()\n\n\texported.Config.Mode = packages.NeedFiles | packages.NeedSyntax\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/syntax\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(initial) != 1 {\n\t\tt.Fatalf(\"expected 1 package, got %d\", len(initial))\n\t}\n\tpkg := initial[0]\n\n\tif len(pkg.Errors) != 0 {\n\t\tt.Fatalf(\"package has errors: %v\", pkg.Errors)\n\t}\n\n\tfname := pkg.Fset.File(pkg.Syntax[0].FileStart).Name()\n\tif filepath.Base(fname) != \"syntax.go\" {\n\t\tt.Errorf(\"expected the package declaration position \"+\n\t\t\t\"to resolve to \\\"syntax.go\\\", got %q instead\", fname)\n\t}\n}\n\nfunc TestModule(t *testing.T) {\n\ttestAllOrModulesParallel(t, testModule)\n}\nfunc testModule(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName:  \"golang.org/fake\",\n\t\tFiles: map[string]any{\"a/a.go\": `package a`}}})\n\texported.Config.Mode = packages.NeedModule\n\trootDir := filepath.Dir(filepath.Dir(exported.File(\"golang.org/fake\", \"a/a.go\")))\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(initial) != 1 {\n\t\tt.Fatal(\"want exactly one package, got \", initial)\n\t}\n\ta := initial[0]\n\tswitch exported.Exporter.Name() {\n\tcase \"GOPATH\":\n\t\tif a.Module != nil {\n\t\t\tt.Fatal(\"package.Module: want nil, got \", a.Module)\n\t\t}\n\tcase \"Modules\":\n\t\t// Make sure Modules field is set, and spot check a few of its fields.\n\t\tif a.Module == nil {\n\t\t\tt.Fatal(\"package.Module: want non-nil, got nil\")\n\t\t}\n\t\tif a.Module.Path != \"golang.org/fake\" {\n\t\t\tt.Fatalf(\"package.Module.Path: want \\\"golang.org/fake\\\", got %q\", a.Module.Path)\n\t\t}\n\t\tif a.Module.GoMod != filepath.Join(rootDir, \"go.mod\") {\n\t\t\tt.Fatalf(\"package.Module.GoMod: want %q, got %q\", filepath.Join(rootDir, \"go.mod\"), a.Module.GoMod)\n\t\t}\n\tdefault:\n\t\tt.Fatalf(\"Expected exporter to be GOPATH or Modules, got %v\", exported.Exporter.Name())\n\t}\n}\n\nfunc TestExternal_NotHandled(t *testing.T) {\n\ttestAllOrModulesParallel(t, testExternal_NotHandled)\n}\nfunc testExternal_NotHandled(t *testing.T, exporter packagestest.Exporter) {\n\tskipIfShort(t, \"builds and links fake driver binaries\")\n\ttestenv.NeedsGoBuild(t)\n\n\ttempdir, err := os.MkdirTemp(\"\", \"testexternal\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tempdir)\n\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a`,\n\t\t\t\"empty_driver/main.go\": `package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\nfunc main() {\n\tio.ReadAll(os.Stdin)\n\tfmt.Println(\"{}\")\n}\n`,\n\t\t\t\"nothandled_driver/main.go\": `package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\nfunc main() {\n\tio.ReadAll(os.Stdin)\n\tfmt.Println(\"{\\\"NotHandled\\\": true}\")\n}\n`,\n\t\t}}})\n\tbaseEnv := exported.Config.Env\n\n\t// As a control, create a fake driver that always returns an empty response.\n\temptyDriverPath := filepath.Join(tempdir, \"empty_driver.exe\") // Add .exe because Windows expects it.\n\tcmd := exec.Command(\"go\", \"build\", \"-o\", emptyDriverPath, \"golang.org/fake/empty_driver\")\n\tcmd.Env = baseEnv\n\tcmd.Dir = exported.Config.Dir\n\tif b, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Log(string(b))\n\t\tt.Fatal(err)\n\t}\n\n\texported.Config.Env = append(slices.Clone(baseEnv), \"GOPACKAGESDRIVER=\"+emptyDriverPath)\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(initial) != 0 {\n\t\tt.Errorf(\"package.Load with empty driver: want [], got %v\", initial)\n\t}\n\n\t// Create a fake driver that always returns a NotHandled response.\n\tnotHandledDriverPath := filepath.Join(tempdir, \"nothandled_driver.exe\")\n\tcmd = exec.Command(\"go\", \"build\", \"-o\", notHandledDriverPath, \"golang.org/fake/nothandled_driver\")\n\tcmd.Env = baseEnv\n\tcmd.Dir = exported.Config.Dir\n\tif b, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Log(string(b))\n\t\tt.Fatal(err)\n\t}\n\n\texported.Config.Env = append(slices.Clone(baseEnv), \"GOPACKAGESDRIVER=\"+notHandledDriverPath)\n\tinitial, err = packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(initial) != 1 || initial[0].PkgPath != \"golang.org/fake/a\" {\n\t\tt.Errorf(\"package.Load: want [golang.org/fake/a], got %v\", initial)\n\t}\n}\n\nfunc TestInvalidPackageName(t *testing.T) {\n\ttestAllOrModulesParallel(t, testInvalidPackageName)\n}\n\nfunc testInvalidPackageName(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"main.go\": `package default\n\nfunc main() {\n}\n`,\n\t\t},\n\t}})\n\tdefer exported.Cleanup()\n\n\tinitial, err := packages.Load(exported.Config, \"golang.org/fake\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpkg := initial[0]\n\tif len(pkg.CompiledGoFiles) != 1 {\n\t\tt.Fatalf(\"expected 1 Go file in package %s, got %v\", pkg.ID, len(pkg.CompiledGoFiles))\n\t}\n}\n\nfunc TestEmptyEnvironment(t *testing.T) {\n\tt.Parallel()\n\n\tcfg := &packages.Config{\n\t\tEnv: []string{\"FOO=BAR\"},\n\t}\n\t_, err := packages.Load(cfg, \"fmt\")\n\tif err == nil {\n\t\tt.Fatal(\"Load with explicitly empty environment should fail\")\n\t}\n}\n\nfunc TestPackageLoadSingleFile(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\ttmp, err := os.MkdirTemp(\"\", \"a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmp)\n\n\tfilename := filepath.Join(tmp, \"a.go\")\n\n\tif err := os.WriteFile(filename, []byte(`package main; func main() { println(\"hello world\") }`), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tpkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax, Dir: tmp}, \"file=\"+filename)\n\tif err != nil {\n\t\tt.Fatalf(\"could not load package: %v\", err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"expected one package to be loaded, got %d\", len(pkgs))\n\t}\n\tif len(pkgs[0].CompiledGoFiles) != 1 || pkgs[0].CompiledGoFiles[0] != filename {\n\t\tt.Fatalf(\"expected one compiled go file (%q), got %v\", filename, pkgs[0].CompiledGoFiles)\n\t}\n}\n\nfunc errorMessages(errors []packages.Error) []string {\n\tvar msgs []string\n\tfor _, err := range errors {\n\t\tmsgs = append(msgs, err.Msg)\n\t}\n\treturn msgs\n}\n\nfunc srcs(p *packages.Package) []string {\n\tvar files []string\n\tfiles = append(files, p.GoFiles...)\n\tfiles = append(files, p.OtherFiles...)\n\tfiles = append(files, p.EmbedFiles...)\n\treturn cleanPaths(files)\n}\n\n// cleanPaths attempts to reduce path names to stable forms\nfunc cleanPaths(paths []string) []string {\n\tresult := make([]string, len(paths))\n\tfor i, src := range paths {\n\t\t// If the source file doesn't have an extension like .go or .s,\n\t\t// it comes from GOCACHE. The names there aren't predictable.\n\t\tname := filepath.Base(src)\n\t\tif !strings.Contains(name, \".\") {\n\t\t\tresult[i] = fmt.Sprintf(\"%d.go\", i) // make cache names predictable\n\t\t} else {\n\t\t\tresult[i] = name\n\t\t}\n\t}\n\treturn result\n}\n\n// importGraph returns the import graph as a user-friendly string,\n// and a map containing all packages keyed by ID.\nfunc importGraph(initial []*packages.Package) (string, map[string]*packages.Package) {\n\tout := new(bytes.Buffer)\n\n\tinitialSet := make(map[*packages.Package]bool)\n\tfor _, p := range initial {\n\t\tinitialSet[p] = true\n\t}\n\n\t// We can't use Visit or Postorder because we need to prune\n\t// the traversal of specific edges, not just nodes.\n\tvar nodes, edges []string\n\tres := make(map[string]*packages.Package)\n\tseen := make(map[*packages.Package]bool)\n\tvar visit func(p *packages.Package)\n\tvisit = func(p *packages.Package) {\n\t\tif !seen[p] {\n\t\t\tseen[p] = true\n\t\t\tif res[p.ID] != nil {\n\t\t\t\tpanic(\"duplicate ID: \" + p.ID)\n\t\t\t}\n\t\t\tres[p.ID] = p\n\n\t\t\tstar := ' ' // mark initial packages with a star\n\t\t\tif initialSet[p] {\n\t\t\t\tstar = '*'\n\t\t\t}\n\t\t\tnodes = append(nodes, fmt.Sprintf(\"%c %s\", star, p.ID))\n\n\t\t\t// To avoid a lot of noise,\n\t\t\t// we prune uninteresting dependencies of testmain packages,\n\t\t\t// which we identify by this import:\n\t\t\tisTestMain := p.Imports[\"testing/internal/testdeps\"] != nil\n\n\t\t\tfor _, imp := range p.Imports {\n\t\t\t\tif isTestMain {\n\t\t\t\t\tswitch imp.ID {\n\t\t\t\t\tcase \"os\", \"reflect\", \"testing\", \"testing/internal/testdeps\":\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// math/bits took on a dependency on unsafe in 1.12, which breaks some\n\t\t\t\t// tests. As a short term hack, prune that edge.\n\t\t\t\t// ditto for (\"errors\", \"internal/reflectlite\") in 1.13.\n\t\t\t\t// TODO(matloob): think of a cleaner solution, or remove math/bits from the test.\n\t\t\t\tif p.ID == \"math/bits\" && imp.ID == \"unsafe\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tedges = append(edges, fmt.Sprintf(\"%s -> %s\", p, imp))\n\t\t\t\tvisit(imp)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, p := range initial {\n\t\tvisit(p)\n\t}\n\n\t// Sort, ignoring leading optional star prefix.\n\tsort.Slice(nodes, func(i, j int) bool { return nodes[i][2:] < nodes[j][2:] })\n\tfor _, node := range nodes {\n\t\tfmt.Fprintf(out, \"%s\\n\", node)\n\t}\n\n\tsort.Strings(edges)\n\tfor _, edge := range edges {\n\t\tfmt.Fprintf(out, \"  %s\\n\", edge)\n\t}\n\n\treturn out.String(), res\n}\n\nfunc constant(p *packages.Package, name string) *types.Const {\n\tif p == nil || p.Types == nil {\n\t\treturn nil\n\t}\n\tc := p.Types.Scope().Lookup(name)\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.(*types.Const)\n}\n\nfunc TestExportFile(t *testing.T) {\n\t// This used to trigger the log.Fatal in loadFromExportData.\n\t// See go.dev/issue/45584.\n\tcfg := new(packages.Config)\n\tcfg.Mode = packages.NeedTypes\n\tpackages.Load(cfg, \"fmt\")\n}\n\n// TestLoadEitherSucceedsOrFails is an attempt to reproduce a sporadic\n// failure observed on the Android emu builders in which Load would\n// return an empty list of packages but no error. We don't expect\n// packages.Load to succeed on that platform, and testenv.NeedsGoBuild\n// would ordinarily suppress the attempt if called early. But\n// regardless of whether the 'go' command is functional, Load should\n// never return an empty set of packages but no error.\nfunc TestLoadEitherSucceedsOrFails(t *testing.T) {\n\tconst src = `package p`\n\tdir := t.TempDir()\n\tcfg := &packages.Config{\n\t\tDir:  dir,\n\t\tMode: packages.LoadSyntax,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(dir, \"p.go\"): []byte(src),\n\t\t},\n\t}\n\tinitial, err := packages.Load(cfg, \"./p.go\")\n\tif err != nil {\n\t\t// If Load failed because it needed 'go' and the\n\t\t// platform doesn't have it, silently skip the test.\n\t\ttestenv.NeedsGoBuild(t)\n\n\t\t// Otherwise, it's a real failure.\n\t\tt.Fatal(err)\n\t}\n\n\t// If Load returned without error,\n\t// it had better give us error-free packages.\n\tif packages.PrintErrors(initial) > 0 {\n\t\tt.Errorf(\"packages contain errors\")\n\t}\n\n\t// If Load returned without error,\n\t// it had better give us the correct number packages.\n\tif len(initial) != 1 {\n\t\tt.Errorf(\"Load returned %d packages (want 1) and no error\", len(initial))\n\t}\n}\n\n// TestLoadOverlayGoMod ensures that overlays containing go.mod files\n// are effective for all 'go list' calls made by go/packages (#67644).\nfunc TestLoadOverlayGoMod(t *testing.T) {\n\ttestenv.NeedsGoBuild(t)\n\n\tcwd, _ := os.Getwd()\n\n\t// This test ensures that the overlaid go.mod file is seen by\n\t// all runs of 'go list', in particular the early run that\n\t// enumerates the modules: if the go.mod file were absent,\n\t// it would ascend to the parent directory (x/tools) and\n\t// then (falsely) report inconsistent vendoring.\n\t//\n\t// (Ideally the testdata would be constructed from nothing\n\t// rather than rely on the go/packages source tree, but it is\n\t// turned out to a bigger project than bargained for.)\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadSyntax,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(cwd, \"go.mod\"): []byte(\"module example.com\\ngo 1.0\"),\n\t\t},\n\t\tEnv: append(os.Environ(), \"GOFLAGS=-mod=vendor\", \"GOWORK=off\"),\n\t}\n\n\tpkgs, err := packages.Load(cfg, \"./testdata\")\n\tif err != nil {\n\t\tt.Fatal(err) // (would previously fail here with \"inconsistent vendoring\")\n\t}\n\tgot := fmt.Sprint(pkgs)\n\twant := `[./testdata]`\n\tif got != want {\n\t\tt.Errorf(\"Load: got %s, want %v\", got, want)\n\t}\n}\n\nfunc overlayFS(overlay map[string][]byte) fstest.MapFS {\n\tfs := make(fstest.MapFS)\n\tfor name, data := range overlay {\n\t\tfs[name] = &fstest.MapFile{Data: data}\n\t}\n\treturn fs\n}\n\n// TestIssue69606a tests when tools in $GOROOT/pkg/tool/$GOOS_$GOARCH are missing,\n// Load should return an error.\nfunc TestIssue69606a(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\toverlay := overlayFS(map[string][]byte{\n\t\t\"io/io.go\":         []byte(\"package io\"),\n\t\t\"unsafe/unsafe.go\": []byte(\"package unsafe\"),\n\t})\n\tgoroot := testfiles.CopyToTmp(t, overlay)\n\n\tt.Logf(\"custom GOROOT: %s\", goroot)\n\n\t// load the std packages under a custom GOROOT\n\t_, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedTypes,\n\t\tEnv: append(\n\t\t\tos.Environ(),\n\t\t\t\"GO111MODULES=on\",\n\t\t\t\"GOPATH=\",\n\t\t\t\"GOWORK=off\",\n\t\t\t\"GOPROXY=off\",\n\t\t\tfmt.Sprintf(\"GOROOT=%s\", goroot)),\n\t}, \"std\")\n\n\tif err == nil {\n\t\tt.Fatal(\"Expected to get an error because missing tool 'compile' but got a nil error\")\n\t}\n}\n\n// TestIssue69606b tests when loading std from a fake goroot without a unsafe package,\n// Load should return an error.\nfunc TestIssue69606b(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\toverlay := overlayFS(map[string][]byte{\n\t\t\"io/io.go\": []byte(\"package io\"),\n\t})\n\tgoroot := testfiles.CopyToTmp(t, overlay)\n\n\tt.Logf(\"custom GOROOT: %s\", goroot)\n\n\t// load the std packages under a custom GOROOT\n\t_, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedTypes,\n\t\tEnv: append(\n\t\t\tos.Environ(),\n\t\t\t\"GO111MODULES=on\",\n\t\t\t\"GOPATH=\",\n\t\t\t\"GOWORK=off\",\n\t\t\t\"GOPROXY=off\",\n\t\t\tfmt.Sprintf(\"GOROOT=%s\", goroot)),\n\t}, \"std\")\n\n\tif err == nil {\n\t\tt.Fatal(\"Expected to get an error because missing unsafe package but got a nil error\")\n\t}\n}\n\n// TestIssue70394 tests materializing an alias type defined in a package (m/a)\n// in another package (m/b) where the types for m/b are coming from the compiler,\n// e.g. `go list -compiled=true ... m/b`.\nfunc TestIssue70394(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\ttestenv.NeedsTool(t, \"go\") // requires go list.\n\ttestenv.NeedsGoBuild(t)    // requires the compiler for export data.\n\n\tdir := t.TempDir()\n\toverlay := map[string][]byte{\n\t\tfilepath.Join(dir, \"go.mod\"): []byte(\"module m\"), // go version of the module does not matter.\n\t\tfilepath.Join(dir, \"a/a.go\"): []byte(`package a; type A = int32`),\n\t\tfilepath.Join(dir, \"b/b.go\"): []byte(`package b; import \"m/a\"; var V a.A`),\n\t}\n\tcfg := &packages.Config{\n\t\tDir:     dir,\n\t\tMode:    packages.NeedTypes, // just NeedsTypes allows for loading export data.\n\t\tOverlay: overlay,\n\t\tEnv:     append(os.Environ(), \"GOFLAGS=-mod=vendor\", \"GOWORK=off\"),\n\t}\n\tpkgs, err := packages.Load(cfg, \"m/b\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif errs := packages.PrintErrors(pkgs); errs > 0 {\n\t\tt.Fatalf(\"Got %d errors while loading packages.\", errs)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"Loaded %d packages. expected 1\", len(pkgs))\n\t}\n\n\tpkg := pkgs[0]\n\tscope := pkg.Types.Scope()\n\tobj := scope.Lookup(\"V\")\n\tif obj == nil {\n\t\tt.Fatalf(\"Failed to find object %q in package %q\", \"V\", pkg)\n\t}\n\tif _, ok := obj.Type().(*types.Alias); !ok {\n\t\tt.Errorf(\"Object %q has type %q. expected an alias\", obj, obj.Type())\n\t}\n}\n\n// TestLoadTypesInfoWithoutSyntaxOrTypes tests when NeedTypesInfo was set and NeedSyntax & NeedTypes were not,\n// Load should include the TypesInfo of packages properly\nfunc TestLoadTypesInfoWithoutSyntaxOrTypes(t *testing.T) {\n\ttestAllOrModulesParallel(t, testLoadTypesInfoWithoutSyntaxOrTypes)\n}\n\nfunc testLoadTypesInfoWithoutSyntaxOrTypes(t *testing.T, exporter packagestest.Exporter) {\n\texported := packagestest.Export(t, exporter, []packagestest.Module{{\n\t\tName: \"golang.org/fake\",\n\t\tFiles: map[string]any{\n\t\t\t\"a/a.go\": `package a;\n\nfunc foo() int {\n\ti := 0\n\ts := \"abc\"\n\treturn i + len(s)\n}\n`,\n\t\t}}})\n\tdefer exported.Cleanup()\n\texported.Config.Mode = packages.NeedTypesInfo\n\n\tpkgs, err := packages.Load(exported.Config, \"golang.org/fake/a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// check if types info is present\n\tif pkgs[0].TypesInfo == nil {\n\t\tt.Errorf(\"expected types info to be present but got nil\")\n\t}\n}\n\n// TestDirAndForTest tests the new fields added as part of golang/go#38445.\nfunc TestDirAndForTest(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tdir := writeTree(t, `\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc Foo() int { return 1 }\n\n-- a/a_test.go --\npackage a\n\nfunc Bar() int { return 2 }\n\n-- a/a_x_test.go --\npackage a_test\n\nimport (\n\t\"example.com/a\"\n\t\"example.com/b\"\n)\n\nfunc _() {\n\tif got := a.Foo() + a.Bar() + b.Baz(); got != 6 {\n\t\tpanic(\"whoops\")\n\t}\n}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc Baz() int { return 3 }\n\nfunc Foo() int { return a.Foo() }\n`)\n\n\tpkgs, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedForTest |\n\t\t\tpackages.NeedImports,\n\t\tDir:   dir,\n\t\tTests: true,\n\t}, \"./...\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttype result struct{ Dir, ForTest string }\n\tgot := make(map[string]result)\n\tfor pkg := range packages.Postorder(pkgs) {\n\t\tif !packagepath.IsStdPackage(pkg.PkgPath) {\n\t\t\trel, err := filepath.Rel(dir, pkg.Dir)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Rel(%q, %q) failed: %v\", dir, pkg.Dir, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tgot[pkg.ID] = result{\n\t\t\t\tDir:     rel,\n\t\t\t\tForTest: pkg.ForTest,\n\t\t\t}\n\t\t}\n\t}\n\twant := map[string]result{\n\t\t\"example.com/a\":                           {\"a\", \"\"},\n\t\t\"example.com/a.test\":                      {\"a\", \"\"},\n\t\t\"example.com/a [example.com/a.test]\":      {\"a\", \"example.com/a\"}, // test variant\n\t\t\"example.com/a_test [example.com/a.test]\": {\"a\", \"example.com/a\"}, // x_test\n\t\t\"example.com/b [example.com/a.test]\":      {\"b\", \"example.com/a\"}, // intermediate test variant\n\t\t\"example.com/b\":                           {\"b\", \"\"},\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"Load returned mismatching ForTest fields (ID->result -want +got):\\n%s\", diff)\n\t}\n\tt.Logf(\"Packages: %+v\", pkgs)\n}\n\n// TestTarget tests the new field added as part of golang/go#38445.\n// The test uses GOPATH mode because non-main packages don't usually\n// have install targets in module mode.\nfunc TestTarget(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tdir := writeTree(t, `\n-- gopath/src/a/a.go --\npackage a\n\nfunc Foo() {}\n-- gopath/src/b/b.go --\npackage main\n\nimport \"a\"\n\nfunc main() {\n\ta.Foo()\n}\n`)\n\tgopath := filepath.Join(dir, \"gopath\")\n\n\tpkgs, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedName | packages.NeedTarget,\n\t\tEnv:  append(os.Environ(), \"GOPATH=\"+gopath, \"GO111MODULE=off\"),\n\t}, filepath.Join(gopath, \"src\", \"...\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar goexe string\n\tif runtime.GOOS == \"windows\" {\n\t\tgoexe = \".exe\"\n\t}\n\twant := map[string]string{\n\t\t\"a\": filepath.Join(gopath, \"pkg\", runtime.GOOS+\"_\"+runtime.GOARCH, \"a.a\"),\n\t\t\"b\": filepath.Join(gopath, \"bin\", \"b\"+goexe),\n\t}\n\tgot := make(map[string]string)\n\tfor pkg := range packages.Postorder(pkgs) {\n\t\tgot[pkg.PkgPath] = pkg.Target\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"Load returned mismatching Target fields (pkgpath->target -want +got):\\n%s\", diff)\n\t}\n\tt.Logf(\"Packages: %+v\", pkgs)\n}\n\n// TestMainPackagePathInModeTypes tests (*types.Package).Path() for\n// main packages in mode NeedTypes, a regression test for #70742, a\n// bug in cmd/compile's export data that caused them to appear as\n// \"main\". (The PkgPath field was always correct.)\nfunc TestMainPackagePathInModeTypes(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tcfg := &packages.Config{Mode: packages.NeedName | packages.NeedTypes}\n\tpkgs, err := packages.Load(cfg, \"cmd/go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tp := pkgs[0]\n\tif p.PkgPath != \"cmd/go\" ||\n\t\tp.Name != \"main\" ||\n\t\tp.Types.Path() != \"cmd/go\" ||\n\t\tp.Types.Name() != \"main\" {\n\t\tt.Errorf(\"PkgPath=%q Name=%q Types.Path=%q Types.Name=%q; want (cmd/go, main) both times)\",\n\t\t\tp.PkgPath,\n\t\t\tp.Name,\n\t\t\tp.Types.Name(),\n\t\t\tp.Types.Path())\n\t}\n}\n\nfunc writeTree(t *testing.T, archive string) string {\n\troot := t.TempDir()\n\n\tfor _, f := range txtar.Parse([]byte(archive)).Files {\n\t\tfilename := filepath.Join(root, f.Name)\n\t\tif err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(filename, f.Data, 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\treturn root\n}\n\nfunc TestLoadFileRelativePath(t *testing.T) {\n\texported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{\n\t\t{\n\t\t\tName: \"fake/pkg\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"pkg.go\": \"package pkg; type A int\",\n\t\t\t},\n\t\t},\n\t})\n\tt.Cleanup(exported.Cleanup)\n\n\texported.Config.Mode = packages.LoadSyntax\n\tpkgs, err := packages.Load(exported.Config, \"file=pkg.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"len(pkgs) = %v; want = 1\", len(pkgs))\n\t}\n\tif pkgs[0].ID != \"fake/pkg\" {\n\t\tt.Fatalf(`pkgs[0].Id = %q; want \"fake/pkg\"`, pkgs[0].ID)\n\t}\n}\n\nfunc TestLoad_populatesInfoMapsForUnsafePackage(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tpkgs, err := packages.Load(&packages.Config{Mode: packages.LoadAllSyntax}, \"unsafe\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tinfo := pkgs[0].TypesInfo\n\n\tif info.Defs == nil ||\n\t\tinfo.Uses == nil ||\n\t\tinfo.Selections == nil ||\n\t\tinfo.Types == nil ||\n\t\tinfo.FileVersions == nil ||\n\t\tinfo.Implicits == nil ||\n\t\tinfo.Instances == nil ||\n\t\tinfo.Scopes == nil {\n\t\tt.Errorf(\"types.Info for package unsafe has one or more nil maps: %#v\", *info)\n\t}\n}\n"
  },
  {
    "path": "go/packages/stdlib_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages_test\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// This test loads the metadata for the standard library,\nfunc TestStdlibMetadata(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\truntime.GC()\n\tt0 := time.Now()\n\tvar memstats runtime.MemStats\n\truntime.ReadMemStats(&memstats)\n\talloc := memstats.Alloc\n\n\t// Load, parse and type-check the program.\n\tcfg := &packages.Config{Mode: packages.LoadAllSyntax}\n\tpkgs, err := packages.Load(cfg, \"std\")\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load metadata: %v\", err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tt.Fatal(\"there were errors loading standard library\")\n\t}\n\n\tt1 := time.Now()\n\truntime.GC()\n\truntime.ReadMemStats(&memstats)\n\truntime.KeepAlive(pkgs)\n\n\tt.Logf(\"Loaded %d packages\", len(pkgs))\n\tnumPkgs := len(pkgs)\n\n\twant := 150 // 186 on linux, 185 on windows.\n\tif numPkgs < want {\n\t\tt.Errorf(\"Loaded only %d packages, want at least %d\", numPkgs, want)\n\t}\n\n\tt.Log(\"GOMAXPROCS: \", runtime.GOMAXPROCS(0))\n\tt.Log(\"Metadata:   \", t1.Sub(t0))                          // ~800ms on 12 threads\n\tt.Log(\"#MB:        \", int64(memstats.Alloc-alloc)/1000000) // ~1MB\n}\n\n// BenchmarkNetHTTP measures the time to load/parse/typecheck the\n// net/http package and all dependencies.\nfunc BenchmarkNetHTTP(b *testing.B) {\n\ttestenv.NeedsGoPackages(b)\n\tb.ReportAllocs()\n\n\tvar bytes int64\n\n\tfor i := range b.N {\n\t\tcfg := &packages.Config{Mode: packages.LoadAllSyntax}\n\t\tpkgs, err := packages.Load(cfg, \"net/http\")\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"failed to load metadata: %v\", err)\n\t\t}\n\t\tif packages.PrintErrors(pkgs) > 0 {\n\t\t\tb.Fatal(\"there were errors loading net/http\")\n\t\t}\n\n\t\tif i == 0 {\n\t\t\tfor pkg := range packages.Postorder(pkgs) {\n\t\t\t\tfor _, f := range pkg.Syntax {\n\t\t\t\t\tbytes += int64(f.FileEnd - f.FileStart)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tb.SetBytes(bytes) // total source bytes\n}\n"
  },
  {
    "path": "go/packages/visit.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packages\n\nimport (\n\t\"cmp\"\n\t\"fmt\"\n\t\"iter\"\n\t\"os\"\n\t\"slices\"\n)\n\n// Visit visits all the packages in the import graph whose roots are\n// pkgs, calling the optional pre function the first time each package\n// is encountered (preorder), and the optional post function after a\n// package's dependencies have been visited (postorder).\n// The boolean result of pre(pkg) determines whether\n// the imports of package pkg are visited.\n//\n// Example:\n//\n//\tpkgs, err := Load(...)\n//\tif err != nil { ... }\n//\tVisit(pkgs, nil, func(pkg *Package) {\n//\t\tlog.Println(pkg)\n//\t})\n//\n// In most cases, it is more convenient to use [Postorder]:\n//\n//\tfor pkg := range Postorder(pkgs) {\n//\t\tlog.Println(pkg)\n//\t}\nfunc Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {\n\tseen := make(map[*Package]bool)\n\tvar visit func(*Package)\n\tvisit = func(pkg *Package) {\n\t\tif !seen[pkg] {\n\t\t\tseen[pkg] = true\n\n\t\t\tif pre == nil || pre(pkg) {\n\t\t\t\tfor _, imp := range sorted(pkg.Imports) { // for determinism\n\t\t\t\t\tvisit(imp)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif post != nil {\n\t\t\t\tpost(pkg)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, pkg := range pkgs {\n\t\tvisit(pkg)\n\t}\n}\n\n// PrintErrors prints to os.Stderr the accumulated errors of all\n// packages in the import graph rooted at pkgs, dependencies first.\n// PrintErrors returns the number of errors printed.\nfunc PrintErrors(pkgs []*Package) int {\n\tvar n int\n\terrModules := make(map[*Module]bool)\n\tfor pkg := range Postorder(pkgs) {\n\t\tfor _, err := range pkg.Errors {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tn++\n\t\t}\n\n\t\t// Print pkg.Module.Error once if present.\n\t\tmod := pkg.Module\n\t\tif mod != nil && mod.Error != nil && !errModules[mod] {\n\t\t\terrModules[mod] = true\n\t\t\tfmt.Fprintln(os.Stderr, mod.Error.Err)\n\t\t\tn++\n\t\t}\n\t}\n\treturn n\n}\n\n// Postorder returns an iterator over the packages in\n// the import graph whose roots are pkg.\n// Packages are enumerated in dependencies-first order.\nfunc Postorder(pkgs []*Package) iter.Seq[*Package] {\n\treturn func(yield func(*Package) bool) {\n\t\tseen := make(map[*Package]bool)\n\t\tvar visit func(*Package) bool\n\t\tvisit = func(pkg *Package) bool {\n\t\t\tif !seen[pkg] {\n\t\t\t\tseen[pkg] = true\n\t\t\t\tfor _, imp := range sorted(pkg.Imports) { // for determinism\n\t\t\t\t\tif !visit(imp) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(pkg) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\tfor _, pkg := range pkgs {\n\t\t\tif !visit(pkg) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// -- copied from golang.org.x/tools/gopls/internal/util/moremaps --\n\n// sorted returns an iterator over the entries of m in key order.\nfunc sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] {\n\t// TODO(adonovan): use maps.Sorted if proposal #68598 is accepted.\n\treturn func(yield func(K, V) bool) {\n\t\tkeys := keySlice(m)\n\t\tslices.Sort(keys)\n\t\tfor _, k := range keys {\n\t\t\tif !yield(k, m[k]) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)).\nfunc keySlice[M ~map[K]V, K comparable, V any](m M) []K {\n\tr := make([]K, 0, len(m))\n\tfor k := range m {\n\t\tr = append(r, k)\n\t}\n\treturn r\n}\n"
  },
  {
    "path": "go/ssa/TODO",
    "content": "-*- text -*-\n\nSSA Generics to-do list\n===========================\n\nDOCUMENTATION:\n- Read me for internals\n\nTYPE PARAMETERIZED GENERIC FUNCTIONS:\n- sanity.go updates.\n- Check source functions going to generics.\n- Tests, tests, tests...\n\nUSAGE:\n- Back fill users for handling ssa.InstantiateGenerics being off.\n\n"
  },
  {
    "path": "go/ssa/block.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport \"fmt\"\n\n// This file implements the BasicBlock type.\n\n// addEdge adds a control-flow graph edge from from to to.\nfunc addEdge(from, to *BasicBlock) {\n\tfrom.Succs = append(from.Succs, to)\n\tto.Preds = append(to.Preds, from)\n}\n\n// Parent returns the function that contains block b.\nfunc (b *BasicBlock) Parent() *Function { return b.parent }\n\n// String returns a human-readable label of this block.\n// It is not guaranteed unique within the function.\nfunc (b *BasicBlock) String() string {\n\treturn fmt.Sprintf(\"%d\", b.Index)\n}\n\n// emit appends an instruction to the current basic block.\n// If the instruction defines a Value, it is returned.\nfunc (b *BasicBlock) emit(i Instruction) Value {\n\ti.setBlock(b)\n\tb.Instrs = append(b.Instrs, i)\n\tv, _ := i.(Value)\n\treturn v\n}\n\n// predIndex returns the i such that b.Preds[i] == c or panics if\n// there is none.\nfunc (b *BasicBlock) predIndex(c *BasicBlock) int {\n\tfor i, pred := range b.Preds {\n\t\tif pred == c {\n\t\t\treturn i\n\t\t}\n\t}\n\tpanic(fmt.Sprintf(\"no edge %s -> %s\", c, b))\n}\n\n// hasPhi returns true if b.Instrs contains φ-nodes.\nfunc (b *BasicBlock) hasPhi() bool {\n\t_, ok := b.Instrs[0].(*Phi)\n\treturn ok\n}\n\n// phis returns the prefix of b.Instrs containing all the block's φ-nodes.\nfunc (b *BasicBlock) phis() []Instruction {\n\tfor i, instr := range b.Instrs {\n\t\tif _, ok := instr.(*Phi); !ok {\n\t\t\treturn b.Instrs[:i]\n\t\t}\n\t}\n\treturn nil // unreachable in well-formed blocks\n}\n\n// replacePred replaces all occurrences of p in b's predecessor list with q.\n// Ordinarily there should be at most one.\nfunc (b *BasicBlock) replacePred(p, q *BasicBlock) {\n\tfor i, pred := range b.Preds {\n\t\tif pred == p {\n\t\t\tb.Preds[i] = q\n\t\t}\n\t}\n}\n\n// replaceSucc replaces all occurrences of p in b's successor list with q.\n// Ordinarily there should be at most one.\nfunc (b *BasicBlock) replaceSucc(p, q *BasicBlock) {\n\tfor i, succ := range b.Succs {\n\t\tif succ == p {\n\t\t\tb.Succs[i] = q\n\t\t}\n\t}\n}\n\n// removePred removes all occurrences of p in b's\n// predecessor list and φ-nodes.\n// Ordinarily there should be at most one.\nfunc (b *BasicBlock) removePred(p *BasicBlock) {\n\tphis := b.phis()\n\n\t// We must preserve edge order for φ-nodes.\n\tj := 0\n\tfor i, pred := range b.Preds {\n\t\tif pred != p {\n\t\t\tb.Preds[j] = b.Preds[i]\n\t\t\t// Strike out φ-edge too.\n\t\t\tfor _, instr := range phis {\n\t\t\t\tphi := instr.(*Phi)\n\t\t\t\tphi.Edges[j] = phi.Edges[i]\n\t\t\t}\n\t\t\tj++\n\t\t}\n\t}\n\t// Nil out b.Preds[j:] and φ-edges[j:] to aid GC.\n\tfor i := j; i < len(b.Preds); i++ {\n\t\tb.Preds[i] = nil\n\t\tfor _, instr := range phis {\n\t\t\tinstr.(*Phi).Edges[i] = nil\n\t\t}\n\t}\n\tb.Preds = b.Preds[:j]\n\tfor _, instr := range phis {\n\t\tphi := instr.(*Phi)\n\t\tphi.Edges = phi.Edges[:j]\n\t}\n}\n"
  },
  {
    "path": "go/ssa/blockopt.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// Simple block optimizations to simplify the control flow graph.\n\n// TODO(adonovan): opt: instead of creating several \"unreachable\" blocks\n// per function in the Builder, reuse a single one (e.g. at Blocks[1])\n// to reduce garbage.\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\n// If true, perform sanity checking and show progress at each\n// successive iteration of optimizeBlocks.  Very verbose.\nconst debugBlockOpt = false\n\n// markReachable sets Index=-1 for all blocks reachable from b.\nfunc markReachable(b *BasicBlock) {\n\tb.Index = -1\n\tfor _, succ := range b.Succs {\n\t\tif succ.Index == 0 {\n\t\t\tmarkReachable(succ)\n\t\t}\n\t}\n}\n\n// deleteUnreachableBlocks marks all reachable blocks of f and\n// eliminates (nils) all others, including possibly cyclic subgraphs.\nfunc deleteUnreachableBlocks(f *Function) {\n\tconst white, black = 0, -1\n\t// We borrow b.Index temporarily as the mark bit.\n\tfor _, b := range f.Blocks {\n\t\tb.Index = white\n\t}\n\tmarkReachable(f.Blocks[0])\n\tif f.Recover != nil {\n\t\tmarkReachable(f.Recover)\n\t}\n\tfor i, b := range f.Blocks {\n\t\tif b.Index == white {\n\t\t\tfor _, c := range b.Succs {\n\t\t\t\tif c.Index == black {\n\t\t\t\t\tc.removePred(b) // delete white->black edge\n\t\t\t\t}\n\t\t\t}\n\t\t\tif debugBlockOpt {\n\t\t\t\tfmt.Fprintln(os.Stderr, \"unreachable\", b)\n\t\t\t}\n\t\t\tf.Blocks[i] = nil // delete b\n\t\t}\n\t}\n\tf.removeNilBlocks()\n}\n\n// jumpThreading attempts to apply simple jump-threading to block b,\n// in which a->b->c become a->c if b is just a Jump.\n// The result is true if the optimization was applied.\nfunc jumpThreading(f *Function, b *BasicBlock) bool {\n\tif b.Index == 0 {\n\t\treturn false // don't apply to entry block\n\t}\n\tif b.Instrs == nil {\n\t\treturn false\n\t}\n\tif _, ok := b.Instrs[0].(*Jump); !ok {\n\t\treturn false // not just a jump\n\t}\n\tc := b.Succs[0]\n\tif c == b {\n\t\treturn false // don't apply to degenerate jump-to-self.\n\t}\n\tif c.hasPhi() {\n\t\treturn false // not sound without more effort\n\t}\n\tfor j, a := range b.Preds {\n\t\ta.replaceSucc(b, c)\n\n\t\t// If a now has two edges to c, replace its degenerate If by Jump.\n\t\tif len(a.Succs) == 2 && a.Succs[0] == c && a.Succs[1] == c {\n\t\t\tjump := new(Jump)\n\t\t\tjump.setBlock(a)\n\t\t\ta.Instrs[len(a.Instrs)-1] = jump\n\t\t\ta.Succs = a.Succs[:1]\n\t\t\tc.removePred(b)\n\t\t} else {\n\t\t\tif j == 0 {\n\t\t\t\tc.replacePred(b, a)\n\t\t\t} else {\n\t\t\t\tc.Preds = append(c.Preds, a)\n\t\t\t}\n\t\t}\n\n\t\tif debugBlockOpt {\n\t\t\tfmt.Fprintln(os.Stderr, \"jumpThreading\", a, b, c)\n\t\t}\n\t}\n\tf.Blocks[b.Index] = nil // delete b\n\treturn true\n}\n\n// fuseBlocks attempts to apply the block fusion optimization to block\n// a, in which a->b becomes ab if len(a.Succs)==len(b.Preds)==1.\n// The result is true if the optimization was applied.\nfunc fuseBlocks(f *Function, a *BasicBlock) bool {\n\tif len(a.Succs) != 1 {\n\t\treturn false\n\t}\n\tb := a.Succs[0]\n\tif len(b.Preds) != 1 {\n\t\treturn false\n\t}\n\n\t// Degenerate &&/|| ops may result in a straight-line CFG\n\t// containing φ-nodes. (Ideally we'd replace such them with\n\t// their sole operand but that requires Referrers, built later.)\n\tif b.hasPhi() {\n\t\treturn false // not sound without further effort\n\t}\n\n\t// Eliminate jump at end of A, then copy all of B across.\n\ta.Instrs = append(a.Instrs[:len(a.Instrs)-1], b.Instrs...)\n\tfor _, instr := range b.Instrs {\n\t\tinstr.setBlock(a)\n\t}\n\n\t// A inherits B's successors\n\ta.Succs = append(a.succs2[:0], b.Succs...)\n\n\t// Fix up Preds links of all successors of B.\n\tfor _, c := range b.Succs {\n\t\tc.replacePred(b, a)\n\t}\n\n\tif debugBlockOpt {\n\t\tfmt.Fprintln(os.Stderr, \"fuseBlocks\", a, b)\n\t}\n\n\tf.Blocks[b.Index] = nil // delete b\n\treturn true\n}\n\n// optimizeBlocks() performs some simple block optimizations on a\n// completed function: dead block elimination, block fusion, jump\n// threading.\nfunc optimizeBlocks(f *Function) {\n\tdeleteUnreachableBlocks(f)\n\n\t// Loop until no further progress.\n\tchanged := true\n\tfor changed {\n\t\tchanged = false\n\n\t\tif debugBlockOpt {\n\t\t\tf.WriteTo(os.Stderr)\n\t\t\tmustSanityCheck(f, nil)\n\t\t}\n\n\t\tfor _, b := range f.Blocks {\n\t\t\t// f.Blocks will temporarily contain nils to indicate\n\t\t\t// deleted blocks; we remove them at the end.\n\t\t\tif b == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Fuse blocks.  b->c becomes bc.\n\t\t\tif fuseBlocks(f, b) {\n\t\t\t\tchanged = true\n\t\t\t}\n\n\t\t\t// a->b->c becomes a->c if b contains only a Jump.\n\t\t\tif jumpThreading(f, b) {\n\t\t\t\tchanged = true\n\t\t\t\tcontinue // (b was disconnected)\n\t\t\t}\n\t\t}\n\t}\n\tf.removeNilBlocks()\n}\n"
  },
  {
    "path": "go/ssa/builder.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines the builder, which builds SSA-form IR for function bodies.\n//\n// SSA construction has two phases, \"create\" and \"build\". First, one\n// or more packages are created in any order by a sequence of calls to\n// CreatePackage, either from syntax or from mere type information.\n// Each created package has a complete set of Members (const, var,\n// type, func) that can be accessed through methods like\n// Program.FuncValue.\n//\n// It is not necessary to call CreatePackage for all dependencies of\n// each syntax package, only for its direct imports. (In future\n// perhaps even this restriction may be lifted.)\n//\n// Second, packages created from syntax are built, by one or more\n// calls to Package.Build, which may be concurrent; or by a call to\n// Program.Build, which builds all packages in parallel. Building\n// traverses the type-annotated syntax tree of each function body and\n// creates SSA-form IR, a control-flow graph of instructions,\n// populating fields such as Function.Body, .Params, and others.\n//\n// Building may create additional methods, including:\n// - wrapper methods (e.g. for embedding, or implicit &recv)\n// - bound method closures (e.g. for use(recv.f))\n// - thunks (e.g. for use(I.f) or use(T.f))\n// - generic instances (e.g. to produce f[int] from f[any]).\n// As these methods are created, they are added to the build queue,\n// and then processed in turn, until a fixed point is reached,\n// Since these methods might belong to packages that were not\n// created (by a call to CreatePackage), their Pkg field is unset.\n//\n// Instances of generic functions may be either instantiated (f[int]\n// is a copy of f[T] with substitutions) or wrapped (f[int] delegates\n// to f[T]), depending on the availability of generic syntax and the\n// InstantiateGenerics mode flag.\n//\n// Each package has an initializer function named \"init\" that calls\n// the initializer functions of each direct import, computes and\n// assigns the initial value of each global variable, and calls each\n// source-level function named \"init\". (These generate SSA functions\n// named \"init#1\", \"init#2\", etc.)\n//\n// Runtime types\n//\n// Each MakeInterface operation is a conversion from a non-interface\n// type to an interface type. The semantics of this operation requires\n// a runtime type descriptor, which is the type portion of an\n// interface, and the value abstracted by reflect.Type.\n//\n// The program accumulates all non-parameterized types that are\n// encountered as MakeInterface operands, along with all types that\n// may be derived from them using reflection. This set is available as\n// Program.RuntimeTypes, and the methods of these types may be\n// reachable via interface calls or reflection even if they are never\n// referenced from the SSA IR. (In practice, algorithms such as RTA\n// that compute reachability from package main perform their own\n// tracking of runtime types at a finer grain, so this feature is not\n// very useful.)\n//\n// Function literals\n//\n// Anonymous functions must be built as soon as they are encountered,\n// as it may affect locals of the enclosing function, but they are not\n// marked 'built' until the end of the outermost enclosing function.\n// (Among other things, this causes them to be logged in top-down order.)\n//\n// The Function.build fields determines the algorithm for building the\n// function body. It is cleared to mark that building is complete.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"runtime\"\n\t\"sync\"\n\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\ntype opaqueType struct{ name string }\n\nfunc (t *opaqueType) String() string         { return t.name }\nfunc (t *opaqueType) Underlying() types.Type { return t }\n\nvar (\n\tvarOk    = newVar(\"ok\", tBool)\n\tvarIndex = newVar(\"index\", tInt)\n\n\t// Type constants.\n\ttBool       = types.Typ[types.Bool]\n\ttByte       = types.Typ[types.Byte]\n\ttInt        = types.Typ[types.Int]\n\ttInvalid    = types.Typ[types.Invalid]\n\ttString     = types.Typ[types.String]\n\ttUntypedNil = types.Typ[types.UntypedNil]\n\n\ttRangeIter  = &opaqueType{\"iter\"}                         // the type of all \"range\" iterators\n\ttDeferStack = types.NewPointer(&opaqueType{\"deferStack\"}) // the type of a \"deferStack\" from ssa:deferstack()\n\ttEface      = types.NewInterfaceType(nil, nil).Complete()\n\n\t// SSA Value constants.\n\tvZero     = intConst(0)\n\tvOne      = intConst(1)\n\tvTrue     = NewConst(constant.MakeBool(true), tBool)\n\tvFalse    = NewConst(constant.MakeBool(false), tBool)\n\tvNoReturn = NewConst(constant.MakeString(\"noreturn\"), tString)\n\n\tjReady = intConst(0)  // range-over-func jump is READY\n\tjBusy  = intConst(-1) // range-over-func jump is BUSY\n\tjDone  = intConst(-2) // range-over-func jump is DONE\n\n\t// The ssa:deferstack intrinsic returns the current function's defer stack.\n\tvDeferStack = &Builtin{\n\t\tname: \"ssa:deferstack\",\n\t\tsig:  types.NewSignatureType(nil, nil, nil, nil, types.NewTuple(anonVar(tDeferStack)), false),\n\t}\n)\n\n// builder holds state associated with the package currently being built.\n// Its methods contain all the logic for AST-to-SSA conversion.\n//\n// All Functions belong to the same Program.\n//\n// builders are not thread-safe.\ntype builder struct {\n\tfns []*Function // Functions that have finished their CREATE phases.\n\n\tfinished int // finished is the length of the prefix of fns containing built functions.\n\n\t// The task of building shared functions within the builder.\n\t// Shared functions are ones the builder may either create or lookup.\n\t// These may be built by other builders in parallel.\n\t// The task is done when the builder has finished iterating, and it\n\t// waits for all shared functions to finish building.\n\t// nil implies there are no hared functions to wait on.\n\tbuildshared *task\n}\n\n// shared is done when the builder has built all of the\n// enqueued functions to a fixed-point.\nfunc (b *builder) shared() *task {\n\tif b.buildshared == nil { // lazily-initialize\n\t\tb.buildshared = &task{done: make(chan unit)}\n\t}\n\treturn b.buildshared\n}\n\n// enqueue fn to be built by the builder.\nfunc (b *builder) enqueue(fn *Function) {\n\tb.fns = append(b.fns, fn)\n}\n\n// waitForSharedFunction indicates that the builder should wait until\n// the potentially shared function fn has finished building.\n//\n// This should include any functions that may be built by other\n// builders.\nfunc (b *builder) waitForSharedFunction(fn *Function) {\n\tif fn.buildshared != nil { // maybe need to wait?\n\t\ts := b.shared()\n\t\ts.addEdge(fn.buildshared)\n\t}\n}\n\n// cond emits to fn code to evaluate boolean condition e and jump\n// to t or f depending on its value, performing various simplifications.\n//\n// Postcondition: fn.currentBlock is nil.\nfunc (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {\n\tswitch e := e.(type) {\n\tcase *ast.ParenExpr:\n\t\tb.cond(fn, e.X, t, f)\n\t\treturn\n\n\tcase *ast.BinaryExpr:\n\t\tswitch e.Op {\n\t\tcase token.LAND:\n\t\t\tltrue := fn.newBasicBlock(\"cond.true\")\n\t\t\tb.cond(fn, e.X, ltrue, f)\n\t\t\tfn.currentBlock = ltrue\n\t\t\tb.cond(fn, e.Y, t, f)\n\t\t\treturn\n\n\t\tcase token.LOR:\n\t\t\tlfalse := fn.newBasicBlock(\"cond.false\")\n\t\t\tb.cond(fn, e.X, t, lfalse)\n\t\t\tfn.currentBlock = lfalse\n\t\t\tb.cond(fn, e.Y, t, f)\n\t\t\treturn\n\t\t}\n\n\tcase *ast.UnaryExpr:\n\t\tif e.Op == token.NOT {\n\t\t\tb.cond(fn, e.X, f, t)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// A traditional compiler would simplify \"if false\" (etc) here\n\t// but we do not, for better fidelity to the source code.\n\t//\n\t// The value of a constant condition may be platform-specific,\n\t// and may cause blocks that are reachable in some configuration\n\t// to be hidden from subsequent analyses such as bug-finding tools.\n\temitIf(fn, b.expr(fn, e), t, f)\n}\n\n// logicalBinop emits code to fn to evaluate e, a &&- or\n// ||-expression whose reified boolean value is wanted.\n// The value is returned.\nfunc (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {\n\trhs := fn.newBasicBlock(\"binop.rhs\")\n\tdone := fn.newBasicBlock(\"binop.done\")\n\n\t// T(e) = T(e.X) = T(e.Y) after untyped constants have been\n\t// eliminated.\n\t// TODO(adonovan): not true; MyBool==MyBool yields UntypedBool.\n\tt := fn.typeOf(e)\n\n\tvar short Value // value of the short-circuit path\n\tswitch e.Op {\n\tcase token.LAND:\n\t\tb.cond(fn, e.X, rhs, done)\n\t\tshort = NewConst(constant.MakeBool(false), t)\n\n\tcase token.LOR:\n\t\tb.cond(fn, e.X, done, rhs)\n\t\tshort = NewConst(constant.MakeBool(true), t)\n\t}\n\n\t// Is rhs unreachable?\n\tif rhs.Preds == nil {\n\t\t// Simplify false&&y to false, true||y to true.\n\t\tfn.currentBlock = done\n\t\treturn short\n\t}\n\n\t// Is done unreachable?\n\tif done.Preds == nil {\n\t\t// Simplify true&&y (or false||y) to y.\n\t\tfn.currentBlock = rhs\n\t\treturn b.expr(fn, e.Y)\n\t}\n\n\t// All edges from e.X to done carry the short-circuit value.\n\tvar edges []Value\n\tfor range done.Preds {\n\t\tedges = append(edges, short)\n\t}\n\n\t// The edge from e.Y to done carries the value of e.Y.\n\tfn.currentBlock = rhs\n\tedges = append(edges, b.expr(fn, e.Y))\n\temitJump(fn, done)\n\tfn.currentBlock = done\n\n\tphi := &Phi{Edges: edges, Comment: e.Op.String()}\n\tphi.pos = e.OpPos\n\tphi.typ = t\n\treturn done.emit(phi)\n}\n\n// exprN lowers a multi-result expression e to SSA form, emitting code\n// to fn and returning a single Value whose type is a *types.Tuple.\n// The caller must access the components via Extract.\n//\n// Multi-result expressions include CallExprs in a multi-value\n// assignment or return statement, and \"value,ok\" uses of\n// TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op\n// is token.ARROW).\nfunc (b *builder) exprN(fn *Function, e ast.Expr) Value {\n\ttyp := fn.typeOf(e).(*types.Tuple)\n\tswitch e := e.(type) {\n\tcase *ast.ParenExpr:\n\t\treturn b.exprN(fn, e.X)\n\n\tcase *ast.CallExpr:\n\t\t// Currently, no built-in function nor type conversion\n\t\t// has multiple results, so we can avoid some of the\n\t\t// cases for single-valued CallExpr.\n\t\tvar c Call\n\t\tb.setCall(fn, e, &c.Call)\n\t\tc.typ = typ\n\t\treturn emitCall(fn, &c)\n\n\tcase *ast.IndexExpr:\n\t\tmapt := typeparams.CoreType(fn.typeOf(e.X)).(*types.Map) // ,ok must be a map.\n\t\tlookup := &Lookup{\n\t\t\tX:       b.expr(fn, e.X),\n\t\t\tIndex:   emitConv(fn, b.expr(fn, e.Index), mapt.Key()),\n\t\t\tCommaOk: true,\n\t\t}\n\t\tlookup.setType(typ)\n\t\tlookup.setPos(e.Lbrack)\n\t\treturn fn.emit(lookup)\n\n\tcase *ast.TypeAssertExpr:\n\t\treturn emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)\n\n\tcase *ast.UnaryExpr: // must be receive <-\n\t\tunop := &UnOp{\n\t\t\tOp:      token.ARROW,\n\t\t\tX:       b.expr(fn, e.X),\n\t\t\tCommaOk: true,\n\t\t}\n\t\tunop.setType(typ)\n\t\tunop.setPos(e.OpPos)\n\t\treturn fn.emit(unop)\n\t}\n\tpanic(fmt.Sprintf(\"exprN(%T) in %s\", e, fn))\n}\n\n// builtin emits to fn SSA instructions to implement a call to the\n// built-in function obj with the specified arguments\n// and return type.  It returns the value defined by the result.\n//\n// The result is nil if no special handling was required; in this case\n// the caller should treat this like an ordinary library function\n// call.\nfunc (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {\n\ttyp = fn.typ(typ)\n\tswitch obj.Name() {\n\tcase \"make\":\n\t\tswitch ct := typeparams.CoreType(typ).(type) {\n\t\tcase *types.Slice:\n\t\t\tn := b.expr(fn, args[1])\n\t\t\tm := n\n\t\t\tif len(args) == 3 {\n\t\t\t\tm = b.expr(fn, args[2])\n\t\t\t}\n\t\t\tif m, ok := m.(*Const); ok {\n\t\t\t\t// treat make([]T, n, m) as new([m]T)[:n]\n\t\t\t\tcap := m.Int64()\n\t\t\t\tat := types.NewArray(ct.Elem(), cap)\n\t\t\t\tv := &Slice{\n\t\t\t\t\tX:    emitNew(fn, at, pos, \"makeslice\"),\n\t\t\t\t\tHigh: n,\n\t\t\t\t}\n\t\t\t\tv.setPos(pos)\n\t\t\t\tv.setType(typ)\n\t\t\t\treturn fn.emit(v)\n\t\t\t}\n\t\t\tv := &MakeSlice{\n\t\t\t\tLen: n,\n\t\t\t\tCap: m,\n\t\t\t}\n\t\t\tv.setPos(pos)\n\t\t\tv.setType(typ)\n\t\t\treturn fn.emit(v)\n\n\t\tcase *types.Map:\n\t\t\tvar res Value\n\t\t\tif len(args) == 2 {\n\t\t\t\tres = b.expr(fn, args[1])\n\t\t\t}\n\t\t\tv := &MakeMap{Reserve: res}\n\t\t\tv.setPos(pos)\n\t\t\tv.setType(typ)\n\t\t\treturn fn.emit(v)\n\n\t\tcase *types.Chan:\n\t\t\tvar sz Value = vZero\n\t\t\tif len(args) == 2 {\n\t\t\t\tsz = b.expr(fn, args[1])\n\t\t\t}\n\t\t\tv := &MakeChan{Size: sz}\n\t\t\tv.setPos(pos)\n\t\t\tv.setType(typ)\n\t\t\treturn fn.emit(v)\n\t\t}\n\n\tcase \"new\":\n\t\talloc := emitNew(fn, typeparams.MustDeref(typ), pos, \"new\")\n\t\tif !fn.info.Types[args[0]].IsType() {\n\t\t\t// new(expr), requires go1.26\n\t\t\tv := b.expr(fn, args[0])\n\t\t\temitStore(fn, alloc, v, pos)\n\t\t}\n\t\treturn alloc\n\n\tcase \"len\", \"cap\":\n\t\t// Special case: len or cap of an array or *array is\n\t\t// based on the type, not the value which may be nil.\n\t\t// We must still evaluate the value, though.  (If it\n\t\t// was side-effect free, the whole call would have\n\t\t// been constant-folded.)\n\t\tt := typeparams.Deref(fn.typeOf(args[0]))\n\t\tif at, ok := typeparams.CoreType(t).(*types.Array); ok {\n\t\t\tb.expr(fn, args[0]) // for effects only\n\t\t\treturn intConst(at.Len())\n\t\t}\n\t\t// Otherwise treat as normal.\n\n\tcase \"panic\":\n\t\tfn.emit(&Panic{\n\t\t\tX:   emitConv(fn, b.expr(fn, args[0]), tEface),\n\t\t\tpos: pos,\n\t\t})\n\t\tfn.currentBlock = fn.newBasicBlock(\"unreachable\")\n\t\treturn vTrue // any non-nil Value will do\n\t}\n\treturn nil // treat all others as a regular function call\n}\n\n// addr lowers a single-result addressable expression e to SSA form,\n// emitting code to fn and returning the location (an lvalue) defined\n// by the expression.\n//\n// If escaping is true, addr marks the base variable of the\n// addressable expression e as being a potentially escaping pointer\n// value.  For example, in this code:\n//\n//\ta := A{\n//\t  b: [1]B{B{c: 1}}\n//\t}\n//\treturn &a.b[0].c\n//\n// the application of & causes a.b[0].c to have its address taken,\n// which means that ultimately the local variable a must be\n// heap-allocated.  This is a simple but very conservative escape\n// analysis.\n//\n// Operations forming potentially escaping pointers include:\n// - &x, including when implicit in method call or composite literals.\n// - a[:] iff a is an array (not *array)\n// - references to variables in lexically enclosing functions.\nfunc (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {\n\tswitch e := e.(type) {\n\tcase *ast.Ident:\n\t\tif isBlankIdent(e) {\n\t\t\treturn blank{}\n\t\t}\n\t\tobj := fn.objectOf(e).(*types.Var)\n\t\tvar v Value\n\t\tif g := fn.Prog.packageLevelMember(obj); g != nil {\n\t\t\tv = g.(*Global) // var (address)\n\t\t} else {\n\t\t\tv = fn.lookup(obj, escaping)\n\t\t}\n\t\treturn &address{addr: v, pos: e.Pos(), expr: e}\n\n\tcase *ast.CompositeLit:\n\t\ttyp := typeparams.Deref(fn.typeOf(e))\n\t\tvar v *Alloc\n\t\tif escaping {\n\t\t\tv = emitNew(fn, typ, e.Lbrace, \"complit\")\n\t\t} else {\n\t\t\tv = emitLocal(fn, typ, e.Lbrace, \"complit\")\n\t\t}\n\t\tvar sb storebuf\n\t\tb.compLit(fn, v, e, true, &sb)\n\t\tsb.emit(fn)\n\t\treturn &address{addr: v, pos: e.Lbrace, expr: e}\n\n\tcase *ast.ParenExpr:\n\t\treturn b.addr(fn, e.X, escaping)\n\n\tcase *ast.SelectorExpr:\n\t\tsel := fn.selection(e)\n\t\tif sel == nil {\n\t\t\t// qualified identifier\n\t\t\treturn b.addr(fn, e.Sel, escaping)\n\t\t}\n\t\tif sel.kind != types.FieldVal {\n\t\t\tpanic(sel)\n\t\t}\n\t\twantAddr := true\n\t\tv := b.receiver(fn, e.X, wantAddr, escaping, sel)\n\t\tindex := sel.index[len(sel.index)-1]\n\t\tfld := fieldOf(typeparams.MustDeref(v.Type()), index) // v is an addr.\n\n\t\t// Due to the two phases of resolving AssignStmt, a panic from x.f = p()\n\t\t// when x is nil is required to come after the side-effects of\n\t\t// evaluating x and p().\n\t\temit := func(fn *Function) Value {\n\t\t\treturn emitFieldSelection(fn, v, index, true, e.Sel)\n\t\t}\n\t\treturn &lazyAddress{addr: emit, t: fld.Type(), pos: e.Sel.Pos(), expr: e.Sel}\n\n\tcase *ast.IndexExpr:\n\t\txt := fn.typeOf(e.X)\n\t\telem, mode := indexType(xt)\n\t\tvar x Value\n\t\tvar et types.Type\n\t\tswitch mode {\n\t\tcase ixArrVar: // array, array|slice, array|*array, or array|*array|slice.\n\t\t\tx = b.addr(fn, e.X, escaping).address(fn)\n\t\t\tet = types.NewPointer(elem)\n\t\tcase ixVar: // *array, slice, *array|slice\n\t\t\tx = b.expr(fn, e.X)\n\t\t\tet = types.NewPointer(elem)\n\t\tcase ixMap:\n\t\t\tmt := typeparams.CoreType(xt).(*types.Map)\n\t\t\treturn &element{\n\t\t\t\tm:   b.expr(fn, e.X),\n\t\t\t\tk:   emitConv(fn, b.expr(fn, e.Index), mt.Key()),\n\t\t\t\tt:   mt.Elem(),\n\t\t\t\tpos: e.Lbrack,\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unexpected container type in IndexExpr: \" + xt.String())\n\t\t}\n\t\tindex := b.expr(fn, e.Index)\n\t\tif isUntyped(index.Type()) {\n\t\t\tindex = emitConv(fn, index, tInt)\n\t\t}\n\t\t// Due to the two phases of resolving AssignStmt, a panic from x[i] = p()\n\t\t// when x is nil or i is out-of-bounds is required to come after the\n\t\t// side-effects of evaluating x, i and p().\n\t\temit := func(fn *Function) Value {\n\t\t\tv := &IndexAddr{\n\t\t\t\tX:     x,\n\t\t\t\tIndex: index,\n\t\t\t}\n\t\t\tv.setPos(e.Lbrack)\n\t\t\tv.setType(et)\n\t\t\treturn fn.emit(v)\n\t\t}\n\t\treturn &lazyAddress{addr: emit, t: typeparams.MustDeref(et), pos: e.Lbrack, expr: e}\n\n\tcase *ast.StarExpr:\n\t\treturn &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}\n\t}\n\n\tpanic(fmt.Sprintf(\"unexpected address expression: %T\", e))\n}\n\ntype store struct {\n\tlhs lvalue\n\trhs Value\n}\n\ntype storebuf struct{ stores []store }\n\nfunc (sb *storebuf) store(lhs lvalue, rhs Value) {\n\tsb.stores = append(sb.stores, store{lhs, rhs})\n}\n\nfunc (sb *storebuf) emit(fn *Function) {\n\tfor _, s := range sb.stores {\n\t\ts.lhs.store(fn, s.rhs)\n\t}\n}\n\n// assign emits to fn code to initialize the lvalue loc with the value\n// of expression e.  If isZero is true, assign assumes that loc holds\n// the zero value for its type.\n//\n// This is equivalent to loc.store(fn, b.expr(fn, e)), but may generate\n// better code in some cases, e.g., for composite literals in an\n// addressable location.\n//\n// If sb is not nil, assign generates code to evaluate expression e, but\n// not to update loc.  Instead, the necessary stores are appended to the\n// storebuf sb so that they can be executed later.  This allows correct\n// in-place update of existing variables when the RHS is a composite\n// literal that may reference parts of the LHS.\nfunc (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) {\n\t// Can we initialize it in place?\n\tif e, ok := ast.Unparen(e).(*ast.CompositeLit); ok {\n\t\t// A CompositeLit never evaluates to a pointer,\n\t\t// so if the type of the location is a pointer,\n\t\t// an &-operation is implied.\n\t\tif !is[blank](loc) && isPointerCore(loc.typ()) { // avoid calling blank.typ()\n\t\t\tptr := b.addr(fn, e, true).address(fn)\n\t\t\t// copy address\n\t\t\tif sb != nil {\n\t\t\t\tsb.store(loc, ptr)\n\t\t\t} else {\n\t\t\t\tloc.store(fn, ptr)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif _, ok := loc.(*address); ok {\n\t\t\tif isNonTypeParamInterface(loc.typ()) {\n\t\t\t\t// e.g. var x interface{} = T{...}\n\t\t\t\t// Can't in-place initialize an interface value.\n\t\t\t\t// Fall back to copying.\n\t\t\t} else {\n\t\t\t\t// x = T{...} or x := T{...}\n\t\t\t\taddr := loc.address(fn)\n\t\t\t\tif sb != nil {\n\t\t\t\t\tb.compLit(fn, addr, e, isZero, sb)\n\t\t\t\t} else {\n\t\t\t\t\tvar sb storebuf\n\t\t\t\t\tb.compLit(fn, addr, e, isZero, &sb)\n\t\t\t\t\tsb.emit(fn)\n\t\t\t\t}\n\n\t\t\t\t// Subtle: emit debug ref for aggregate types only;\n\t\t\t\t// slice and map are handled by store ops in compLit.\n\t\t\t\tswitch typeparams.CoreType(loc.typ()).(type) {\n\t\t\t\tcase *types.Struct, *types.Array:\n\t\t\t\t\temitDebugRef(fn, e, addr, true)\n\t\t\t\t}\n\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t// simple case: just copy\n\trhs := b.expr(fn, e)\n\tif sb != nil {\n\t\tsb.store(loc, rhs)\n\t} else {\n\t\tloc.store(fn, rhs)\n\t}\n}\n\n// expr lowers a single-result expression e to SSA form, emitting code\n// to fn and returning the Value defined by the expression.\nfunc (b *builder) expr(fn *Function, e ast.Expr) Value {\n\te = ast.Unparen(e)\n\n\ttv := fn.info.Types[e]\n\n\t// Is expression a constant?\n\tif tv.Value != nil {\n\t\treturn NewConst(tv.Value, fn.typ(tv.Type))\n\t}\n\n\tvar v Value\n\tif tv.Addressable() {\n\t\t// Prefer pointer arithmetic ({Index,Field}Addr) followed\n\t\t// by Load over subelement extraction (e.g. Index, Field),\n\t\t// to avoid large copies.\n\t\tv = b.addr(fn, e, false).load(fn)\n\t} else {\n\t\tv = b.expr0(fn, e, tv)\n\t}\n\tif fn.debugInfo() {\n\t\temitDebugRef(fn, e, v, false)\n\t}\n\treturn v\n}\n\nfunc (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {\n\tswitch e := e.(type) {\n\tcase *ast.BasicLit:\n\t\tpanic(\"non-constant BasicLit\") // unreachable\n\n\tcase *ast.FuncLit:\n\t\t/* function literal */\n\t\tanon := &Function{\n\t\t\tname:           fmt.Sprintf(\"%s$%d\", fn.Name(), 1+len(fn.AnonFuncs)),\n\t\t\tSignature:      fn.typeOf(e.Type).(*types.Signature),\n\t\t\tpos:            e.Type.Func,\n\t\t\tparent:         fn,\n\t\t\tanonIdx:        int32(len(fn.AnonFuncs)),\n\t\t\tPkg:            fn.Pkg,\n\t\t\tProg:           fn.Prog,\n\t\t\tsyntax:         e,\n\t\t\tinfo:           fn.info,\n\t\t\tgoversion:      fn.goversion,\n\t\t\tbuild:          (*builder).buildFromSyntax,\n\t\t\ttopLevelOrigin: nil,           // use anonIdx to lookup an anon instance's origin.\n\t\t\ttypeparams:     fn.typeparams, // share the parent's type parameters.\n\t\t\ttypeargs:       fn.typeargs,   // share the parent's type arguments.\n\t\t\tsubst:          fn.subst,      // share the parent's type substitutions.\n\t\t\tuniq:           fn.uniq,       // start from parent's unique values\n\t\t}\n\t\tfn.AnonFuncs = append(fn.AnonFuncs, anon)\n\t\t// Build anon immediately, as it may cause fn's locals to escape.\n\t\t// (It is not marked 'built' until the end of the enclosing FuncDecl.)\n\t\tanon.build(b, anon)\n\t\tfn.uniq = anon.uniq // resume after anon's unique values\n\t\tif anon.FreeVars == nil {\n\t\t\treturn anon\n\t\t}\n\t\tv := &MakeClosure{Fn: anon}\n\t\tv.setType(fn.typ(tv.Type))\n\t\tfor _, fv := range anon.FreeVars {\n\t\t\tv.Bindings = append(v.Bindings, fv.outer)\n\t\t\tfv.outer = nil\n\t\t}\n\t\treturn fn.emit(v)\n\n\tcase *ast.TypeAssertExpr: // single-result form only\n\t\treturn emitTypeAssert(fn, b.expr(fn, e.X), fn.typ(tv.Type), e.Lparen)\n\n\tcase *ast.CallExpr:\n\t\tif fn.info.Types[e.Fun].IsType() {\n\t\t\t// Explicit type conversion, e.g. string(x) or big.Int(x)\n\t\t\tx := b.expr(fn, e.Args[0])\n\t\t\ty := emitConv(fn, x, fn.typ(tv.Type))\n\t\t\tif y != x {\n\t\t\t\tswitch y := y.(type) {\n\t\t\t\tcase *Convert:\n\t\t\t\t\ty.pos = e.Lparen\n\t\t\t\tcase *ChangeType:\n\t\t\t\t\ty.pos = e.Lparen\n\t\t\t\tcase *MakeInterface:\n\t\t\t\t\ty.pos = e.Lparen\n\t\t\t\tcase *SliceToArrayPointer:\n\t\t\t\t\ty.pos = e.Lparen\n\t\t\t\tcase *UnOp: // conversion from slice to array.\n\t\t\t\t\ty.pos = e.Lparen\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn y\n\t\t}\n\t\t// Call to \"intrinsic\" built-ins, e.g. new, make, panic.\n\t\tif id, ok := ast.Unparen(e.Fun).(*ast.Ident); ok {\n\t\t\tif obj, ok := fn.info.Uses[id].(*types.Builtin); ok {\n\t\t\t\tif v := b.builtin(fn, obj, e.Args, fn.typ(tv.Type), e.Lparen); v != nil {\n\t\t\t\t\treturn v\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Regular function call.\n\t\tvar v Call\n\t\tb.setCall(fn, e, &v.Call)\n\t\tv.setType(fn.typ(tv.Type))\n\t\treturn emitCall(fn, &v)\n\n\tcase *ast.UnaryExpr:\n\t\tswitch e.Op {\n\t\tcase token.AND: // &X --- potentially escaping.\n\t\t\taddr := b.addr(fn, e.X, true)\n\t\t\tif _, ok := ast.Unparen(e.X).(*ast.StarExpr); ok {\n\t\t\t\t// &*p must panic if p is nil (http://golang.org/s/go12nil).\n\t\t\t\t// For simplicity, we'll just (suboptimally) rely\n\t\t\t\t// on the side effects of a load.\n\t\t\t\t// TODO(adonovan): emit dedicated nilcheck.\n\t\t\t\taddr.load(fn)\n\t\t\t}\n\t\t\treturn addr.address(fn)\n\t\tcase token.ADD:\n\t\t\treturn b.expr(fn, e.X)\n\t\tcase token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^\n\t\t\tv := &UnOp{\n\t\t\t\tOp: e.Op,\n\t\t\t\tX:  b.expr(fn, e.X),\n\t\t\t}\n\t\t\tv.setPos(e.OpPos)\n\t\t\tv.setType(fn.typ(tv.Type))\n\t\t\treturn fn.emit(v)\n\t\tdefault:\n\t\t\tpanic(e.Op)\n\t\t}\n\n\tcase *ast.BinaryExpr:\n\t\tswitch e.Op {\n\t\tcase token.LAND, token.LOR:\n\t\t\treturn b.logicalBinop(fn, e)\n\t\tcase token.SHL, token.SHR:\n\t\t\tfallthrough\n\t\tcase token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:\n\t\t\treturn emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), fn.typ(tv.Type), e.OpPos)\n\n\t\tcase token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:\n\t\t\tcmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)\n\t\t\t// The type of x==y may be UntypedBool.\n\t\t\treturn emitConv(fn, cmp, types.Default(fn.typ(tv.Type)))\n\t\tdefault:\n\t\t\tpanic(\"illegal op in BinaryExpr: \" + e.Op.String())\n\t\t}\n\n\tcase *ast.SliceExpr:\n\t\tvar low, high, max Value\n\t\tvar x Value\n\t\txtyp := fn.typeOf(e.X)\n\t\tswitch typeparams.CoreType(xtyp).(type) {\n\t\tcase *types.Array:\n\t\t\t// Potentially escaping.\n\t\t\tx = b.addr(fn, e.X, true).address(fn)\n\t\tcase *types.Basic, *types.Slice, *types.Pointer: // *array\n\t\t\tx = b.expr(fn, e.X)\n\t\tdefault:\n\t\t\t// core type exception?\n\t\t\tif isBytestring(xtyp) {\n\t\t\t\tx = b.expr(fn, e.X) // bytestring is handled as string and []byte.\n\t\t\t} else {\n\t\t\t\tpanic(\"unexpected sequence type in SliceExpr\")\n\t\t\t}\n\t\t}\n\t\tif e.Low != nil {\n\t\t\tlow = b.expr(fn, e.Low)\n\t\t}\n\t\tif e.High != nil {\n\t\t\thigh = b.expr(fn, e.High)\n\t\t}\n\t\tif e.Slice3 {\n\t\t\tmax = b.expr(fn, e.Max)\n\t\t}\n\t\tv := &Slice{\n\t\t\tX:    x,\n\t\t\tLow:  low,\n\t\t\tHigh: high,\n\t\t\tMax:  max,\n\t\t}\n\t\tv.setPos(e.Lbrack)\n\t\tv.setType(fn.typ(tv.Type))\n\t\treturn fn.emit(v)\n\n\tcase *ast.Ident:\n\t\tobj := fn.info.Uses[e]\n\t\t// Universal built-in or nil?\n\t\tswitch obj := obj.(type) {\n\t\tcase *types.Builtin:\n\t\t\treturn &Builtin{name: obj.Name(), sig: fn.instanceType(e).(*types.Signature)}\n\t\tcase *types.Nil:\n\t\t\treturn zeroConst(fn.instanceType(e))\n\t\t}\n\n\t\t// Package-level func or var?\n\t\t// (obj must belong to same package or a direct import.)\n\t\tif v := fn.Prog.packageLevelMember(obj); v != nil {\n\t\t\tif g, ok := v.(*Global); ok {\n\t\t\t\treturn emitLoad(fn, g) // var (address)\n\t\t\t}\n\t\t\tcallee := v.(*Function) // (func)\n\t\t\tif callee.typeparams.Len() > 0 {\n\t\t\t\ttargs := fn.subst.types(instanceArgs(fn.info, e))\n\t\t\t\tcallee = callee.instance(targs, b)\n\t\t\t}\n\t\t\treturn callee\n\t\t}\n\t\t// Local var.\n\t\treturn emitLoad(fn, fn.lookup(obj.(*types.Var), false)) // var (address)\n\n\tcase *ast.SelectorExpr:\n\t\tsel := fn.selection(e)\n\t\tif sel == nil {\n\t\t\t// builtin unsafe.{Add,Slice}\n\t\t\tif obj, ok := fn.info.Uses[e.Sel].(*types.Builtin); ok {\n\t\t\t\treturn &Builtin{name: obj.Name(), sig: fn.typ(tv.Type).(*types.Signature)}\n\t\t\t}\n\t\t\t// qualified identifier\n\t\t\treturn b.expr(fn, e.Sel)\n\t\t}\n\t\tswitch sel.kind {\n\t\tcase types.MethodExpr:\n\t\t\t// (*T).f or T.f, the method f from the method-set of type T.\n\t\t\t// The result is a \"thunk\".\n\t\t\tthunk := createThunk(fn.Prog, sel)\n\t\t\tb.enqueue(thunk)\n\t\t\treturn emitConv(fn, thunk, fn.typ(tv.Type))\n\n\t\tcase types.MethodVal:\n\t\t\t// e.f where e is an expression and f is a method.\n\t\t\t// The result is a \"bound\".\n\t\t\tobj := sel.obj.(*types.Func)\n\t\t\trt := fn.typ(recvType(obj))\n\t\t\twantAddr := isPointer(rt)\n\t\t\tescaping := true\n\t\t\tv := b.receiver(fn, e.X, wantAddr, escaping, sel)\n\n\t\t\tif types.IsInterface(rt) {\n\t\t\t\t// If v may be an interface type I (after instantiating),\n\t\t\t\t// we must emit a check that v is non-nil.\n\t\t\t\tif recv, ok := types.Unalias(sel.recv).(*types.TypeParam); ok {\n\t\t\t\t\t// Emit a nil check if any possible instantiation of the\n\t\t\t\t\t// type parameter is an interface type.\n\t\t\t\t\tif !typeSetIsEmpty(recv) {\n\t\t\t\t\t\t// recv has a concrete term its typeset.\n\t\t\t\t\t\t// So it cannot be instantiated as an interface.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Example:\n\t\t\t\t\t\t// func _[T interface{~int; Foo()}] () {\n\t\t\t\t\t\t//    var v T\n\t\t\t\t\t\t//    _ = v.Foo // <-- MethodVal\n\t\t\t\t\t\t// }\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// rt may be instantiated as an interface.\n\t\t\t\t\t\t// Emit nil check: typeassert (any(v)).(any).\n\t\t\t\t\t\temitTypeAssert(fn, emitConv(fn, v, tEface), tEface, token.NoPos)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// non-type param interface\n\t\t\t\t\t// Emit nil check: typeassert v.(I).\n\t\t\t\t\temitTypeAssert(fn, v, rt, e.Sel.Pos())\n\t\t\t\t}\n\t\t\t}\n\t\t\tif targs := receiverTypeArgs(obj); len(targs) > 0 {\n\t\t\t\t// obj is generic.\n\t\t\t\tobj = fn.Prog.canon.instantiateMethod(obj, fn.subst.types(targs), fn.Prog.ctxt)\n\t\t\t}\n\t\t\tbound := createBound(fn.Prog, obj)\n\t\t\tb.enqueue(bound)\n\n\t\t\tc := &MakeClosure{\n\t\t\t\tFn:       bound,\n\t\t\t\tBindings: []Value{v},\n\t\t\t}\n\t\t\tc.setPos(e.Sel.Pos())\n\t\t\tc.setType(fn.typ(tv.Type))\n\t\t\treturn fn.emit(c)\n\n\t\tcase types.FieldVal:\n\t\t\tindices := sel.index\n\t\t\tlast := len(indices) - 1\n\t\t\tv := b.expr(fn, e.X)\n\t\t\tv = emitImplicitSelections(fn, v, indices[:last], e.Pos())\n\t\t\tv = emitFieldSelection(fn, v, indices[last], false, e.Sel)\n\t\t\treturn v\n\t\t}\n\n\t\tpanic(\"unexpected expression-relative selector\")\n\n\tcase *ast.IndexListExpr:\n\t\t// f[X, Y] must be a generic function\n\t\tif !instance(fn.info, e.X) {\n\t\t\tpanic(\"unexpected expression-could not match index list to instantiation\")\n\t\t}\n\t\treturn b.expr(fn, e.X) // Handle instantiation within the *Ident or *SelectorExpr cases.\n\n\tcase *ast.IndexExpr:\n\t\tif instance(fn.info, e.X) {\n\t\t\treturn b.expr(fn, e.X) // Handle instantiation within the *Ident or *SelectorExpr cases.\n\t\t}\n\t\t// not a generic instantiation.\n\t\txt := fn.typeOf(e.X)\n\t\tswitch et, mode := indexType(xt); mode {\n\t\tcase ixVar:\n\t\t\t// Addressable slice/array; use IndexAddr and Load.\n\t\t\treturn b.addr(fn, e, false).load(fn)\n\n\t\tcase ixArrVar, ixValue:\n\t\t\t// An array in a register, a string or a combined type that contains\n\t\t\t// either an [_]array (ixArrVar) or string (ixValue).\n\n\t\t\t// Note: for ixArrVar and CoreType(xt)==nil can be IndexAddr and Load.\n\t\t\tindex := b.expr(fn, e.Index)\n\t\t\tif isUntyped(index.Type()) {\n\t\t\t\tindex = emitConv(fn, index, tInt)\n\t\t\t}\n\t\t\tv := &Index{\n\t\t\t\tX:     b.expr(fn, e.X),\n\t\t\t\tIndex: index,\n\t\t\t}\n\t\t\tv.setPos(e.Lbrack)\n\t\t\tv.setType(et)\n\t\t\treturn fn.emit(v)\n\n\t\tcase ixMap:\n\t\t\tct := typeparams.CoreType(xt).(*types.Map)\n\t\t\tv := &Lookup{\n\t\t\t\tX:     b.expr(fn, e.X),\n\t\t\t\tIndex: emitConv(fn, b.expr(fn, e.Index), ct.Key()),\n\t\t\t}\n\t\t\tv.setPos(e.Lbrack)\n\t\t\tv.setType(ct.Elem())\n\t\t\treturn fn.emit(v)\n\t\tdefault:\n\t\t\tpanic(\"unexpected container type in IndexExpr: \" + xt.String())\n\t\t}\n\n\tcase *ast.CompositeLit, *ast.StarExpr:\n\t\t// Addressable types (lvalues)\n\t\treturn b.addr(fn, e, false).load(fn)\n\t}\n\n\tpanic(fmt.Sprintf(\"unexpected expr: %T\", e))\n}\n\n// stmtList emits to fn code for all statements in list.\nfunc (b *builder) stmtList(fn *Function, list []ast.Stmt) {\n\tfor _, s := range list {\n\t\tb.stmt(fn, s)\n\t}\n}\n\n// receiver emits to fn code for expression e in the \"receiver\"\n// position of selection e.f (where f may be a field or a method) and\n// returns the effective receiver after applying the implicit field\n// selections of sel.\n//\n// wantAddr requests that the result is an address.  If\n// !sel.indirect, this may require that e be built in addr() mode; it\n// must thus be addressable.\n//\n// escaping is defined as per builder.addr().\nfunc (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *selection) Value {\n\tvar v Value\n\tif wantAddr && !sel.indirect && !isPointerCore(fn.typeOf(e)) {\n\t\tv = b.addr(fn, e, escaping).address(fn)\n\t} else {\n\t\tv = b.expr(fn, e)\n\t}\n\n\tlast := len(sel.index) - 1\n\t// The position of implicit selection is the position of the inducing receiver expression.\n\tv = emitImplicitSelections(fn, v, sel.index[:last], e.Pos())\n\tif types.IsInterface(v.Type()) {\n\t\t// When v is an interface, sel.Kind()==MethodValue and v.f is invoked.\n\t\t// So v is not loaded, even if v has a pointer core type.\n\t} else if !wantAddr && isPointerCore(v.Type()) {\n\t\tv = emitLoad(fn, v)\n\t}\n\treturn v\n}\n\n// setCallFunc populates the function parts of a CallCommon structure\n// (Func, Method, Recv, Args[0]) based on the kind of invocation\n// occurring in e.\nfunc (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {\n\tc.pos = e.Lparen\n\n\t// Is this a method call?\n\tif selector, ok := ast.Unparen(e.Fun).(*ast.SelectorExpr); ok {\n\t\tsel := fn.selection(selector)\n\t\tif sel != nil && sel.kind == types.MethodVal {\n\t\t\tobj := sel.obj.(*types.Func)\n\t\t\trecv := recvType(obj)\n\n\t\t\twantAddr := isPointer(recv)\n\t\t\tescaping := true\n\t\t\tv := b.receiver(fn, selector.X, wantAddr, escaping, sel)\n\t\t\tif types.IsInterface(recv) {\n\t\t\t\t// Invoke-mode call.\n\t\t\t\tc.Value = v // possibly type param\n\t\t\t\tc.Method = obj\n\t\t\t} else {\n\t\t\t\t// \"Call\"-mode call.\n\t\t\t\tc.Value = fn.Prog.objectMethod(obj, b)\n\t\t\t\tc.Args = append(c.Args, v)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// sel.kind==MethodExpr indicates T.f() or (*T).f():\n\t\t// a statically dispatched call to the method f in the\n\t\t// method-set of T or *T.  T may be an interface.\n\t\t//\n\t\t// e.Fun would evaluate to a concrete method, interface\n\t\t// wrapper function, or promotion wrapper.\n\t\t//\n\t\t// For now, we evaluate it in the usual way.\n\t\t//\n\t\t// TODO(adonovan): opt: inline expr() here, to make the\n\t\t// call static and to avoid generation of wrappers.\n\t\t// It's somewhat tricky as it may consume the first\n\t\t// actual parameter if the call is \"invoke\" mode.\n\t\t//\n\t\t// Examples:\n\t\t//  type T struct{}; func (T) f() {}   // \"call\" mode\n\t\t//  type T interface { f() }           // \"invoke\" mode\n\t\t//\n\t\t//  type S struct{ T }\n\t\t//\n\t\t//  var s S\n\t\t//  S.f(s)\n\t\t//  (*S).f(&s)\n\t\t//\n\t\t// Suggested approach:\n\t\t// - consume the first actual parameter expression\n\t\t//   and build it with b.expr().\n\t\t// - apply implicit field selections.\n\t\t// - use MethodVal logic to populate fields of c.\n\t}\n\n\t// Evaluate the function operand in the usual way.\n\tc.Value = b.expr(fn, e.Fun)\n}\n\n// emitCallArgs emits to f code for the actual parameters of call e to\n// a (possibly built-in) function of effective type sig.\n// The argument values are appended to args, which is then returned.\nfunc (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {\n\t// f(x, y, z...): pass slice z straight through.\n\tif e.Ellipsis != 0 {\n\t\tfor i, arg := range e.Args {\n\t\t\tv := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())\n\t\t\targs = append(args, v)\n\t\t}\n\t\treturn args\n\t}\n\n\toffset := len(args) // 1 if call has receiver, 0 otherwise\n\n\t// Evaluate actual parameter expressions.\n\t//\n\t// If this is a chained call of the form f(g()) where g has\n\t// multiple return values (MRV), they are flattened out into\n\t// args; a suffix of them may end up in a varargs slice.\n\tfor _, arg := range e.Args {\n\t\tv := b.expr(fn, arg)\n\t\tif ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain\n\t\t\tfor i, n := 0, ttuple.Len(); i < n; i++ {\n\t\t\t\targs = append(args, emitExtract(fn, v, i))\n\t\t\t}\n\t\t} else {\n\t\t\targs = append(args, v)\n\t\t}\n\t}\n\n\t// Actual->formal assignability conversions for normal parameters.\n\tnp := sig.Params().Len() // number of normal parameters\n\tif sig.Variadic() {\n\t\tnp--\n\t}\n\tfor i := 0; i < np; i++ {\n\t\targs[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())\n\t}\n\n\t// Actual->formal assignability conversions for variadic parameter,\n\t// and construction of slice.\n\tif sig.Variadic() {\n\t\tvarargs := args[offset+np:]\n\t\tst := sig.Params().At(np).Type().(*types.Slice)\n\t\tvt := st.Elem()\n\t\tif len(varargs) == 0 {\n\t\t\targs = append(args, zeroConst(st))\n\t\t} else {\n\t\t\t// Replace a suffix of args with a slice containing it.\n\t\t\tat := types.NewArray(vt, int64(len(varargs)))\n\t\t\ta := emitNew(fn, at, token.NoPos, \"varargs\")\n\t\t\ta.setPos(e.Rparen)\n\t\t\tfor i, arg := range varargs {\n\t\t\t\tiaddr := &IndexAddr{\n\t\t\t\t\tX:     a,\n\t\t\t\t\tIndex: intConst(int64(i)),\n\t\t\t\t}\n\t\t\t\tiaddr.setType(types.NewPointer(vt))\n\t\t\t\tfn.emit(iaddr)\n\t\t\t\temitStore(fn, iaddr, arg, arg.Pos())\n\t\t\t}\n\t\t\ts := &Slice{X: a}\n\t\t\ts.setType(st)\n\t\t\targs[offset+np] = fn.emit(s)\n\t\t\targs = args[:offset+np+1]\n\t\t}\n\t}\n\treturn args\n}\n\n// setCall emits to fn code to evaluate all the parameters of a function\n// call e, and populates *c with those values.\nfunc (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {\n\t// First deal with the f(...) part and optional receiver.\n\tb.setCallFunc(fn, e, c)\n\n\t// Then append the other actual parameters.\n\tsig, _ := typeparams.CoreType(fn.typeOf(e.Fun)).(*types.Signature)\n\tif sig == nil {\n\t\tpanic(fmt.Sprintf(\"no signature for call of %s\", e.Fun))\n\t}\n\tc.Args = b.emitCallArgs(fn, sig, e, c.Args)\n}\n\n// assignOp emits to fn code to perform loc <op>= val.\nfunc (b *builder) assignOp(fn *Function, loc lvalue, val Value, op token.Token, pos token.Pos) {\n\tloc.store(fn, emitArith(fn, op, loc.load(fn), val, loc.typ(), pos))\n}\n\n// localValueSpec emits to fn code to define all of the vars in the\n// function-local ValueSpec, spec.\nfunc (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {\n\tswitch {\n\tcase len(spec.Values) == len(spec.Names):\n\t\t// e.g. var x, y = 0, 1\n\t\t// 1:1 assignment\n\t\tfor i, id := range spec.Names {\n\t\t\tif !isBlankIdent(id) {\n\t\t\t\temitLocalVar(fn, identVar(fn, id))\n\t\t\t}\n\t\t\tlval := b.addr(fn, id, false) // non-escaping\n\t\t\tb.assign(fn, lval, spec.Values[i], true, nil)\n\t\t}\n\n\tcase len(spec.Values) == 0:\n\t\t// e.g. var x, y int\n\t\t// Locals are implicitly zero-initialized.\n\t\tfor _, id := range spec.Names {\n\t\t\tif !isBlankIdent(id) {\n\t\t\t\tlhs := emitLocalVar(fn, identVar(fn, id))\n\t\t\t\tif fn.debugInfo() {\n\t\t\t\t\temitDebugRef(fn, id, lhs, true)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\t// e.g. var x, y = pos()\n\t\ttuple := b.exprN(fn, spec.Values[0])\n\t\tfor i, id := range spec.Names {\n\t\t\tif !isBlankIdent(id) {\n\t\t\t\temitLocalVar(fn, identVar(fn, id))\n\t\t\t\tlhs := b.addr(fn, id, false) // non-escaping\n\t\t\t\tlhs.store(fn, emitExtract(fn, tuple, i))\n\t\t\t}\n\t\t}\n\t}\n}\n\n// assignStmt emits code to fn for a parallel assignment of rhss to lhss.\n// isDef is true if this is a short variable declaration (:=).\n//\n// Note the similarity with localValueSpec.\nfunc (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {\n\t// Side effects of all LHSs and RHSs must occur in left-to-right order.\n\tlvals := make([]lvalue, len(lhss))\n\tisZero := make([]bool, len(lhss))\n\tfor i, lhs := range lhss {\n\t\tvar lval lvalue = blank{}\n\t\tif !isBlankIdent(lhs) {\n\t\t\tif isDef {\n\t\t\t\tif obj, ok := fn.info.Defs[lhs.(*ast.Ident)].(*types.Var); ok {\n\t\t\t\t\temitLocalVar(fn, obj)\n\t\t\t\t\tisZero[i] = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tlval = b.addr(fn, lhs, false) // non-escaping\n\t\t}\n\t\tlvals[i] = lval\n\t}\n\tif len(lhss) == len(rhss) {\n\t\t// Simple assignment:   x     = f()        (!isDef)\n\t\t// Parallel assignment: x, y  = f(), g()   (!isDef)\n\t\t// or short var decl:   x, y := f(), g()   (isDef)\n\t\t//\n\t\t// In all cases, the RHSs may refer to the LHSs,\n\t\t// so we need a storebuf.\n\t\tvar sb storebuf\n\t\tfor i := range rhss {\n\t\t\tb.assign(fn, lvals[i], rhss[i], isZero[i], &sb)\n\t\t}\n\t\tsb.emit(fn)\n\t} else {\n\t\t// e.g. x, y = pos()\n\t\ttuple := b.exprN(fn, rhss[0])\n\t\temitDebugRef(fn, rhss[0], tuple, false)\n\t\tfor i, lval := range lvals {\n\t\t\tlval.store(fn, emitExtract(fn, tuple, i))\n\t\t}\n\t}\n}\n\n// arrayLen returns the length of the array whose composite literal elements are elts.\nfunc (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {\n\tvar max int64 = -1\n\tvar i int64 = -1\n\tfor _, e := range elts {\n\t\tif kv, ok := e.(*ast.KeyValueExpr); ok {\n\t\t\ti = b.expr(fn, kv.Key).(*Const).Int64()\n\t\t} else {\n\t\t\ti++\n\t\t}\n\t\tif i > max {\n\t\t\tmax = i\n\t\t}\n\t}\n\treturn max + 1\n}\n\n// compLit emits to fn code to initialize a composite literal e at\n// address addr with type typ.\n//\n// Nested composite literals are recursively initialized in place\n// where possible. If isZero is true, compLit assumes that addr\n// holds the zero value for typ.\n//\n// Because the elements of a composite literal may refer to the\n// variables being updated, as in the second line below,\n//\n//\tx := T{a: 1}\n//\tx = T{a: x.a}\n//\n// all the reads must occur before all the writes.  Thus all stores to\n// loc are emitted to the storebuf sb for later execution.\n//\n// A CompositeLit may have pointer type only in the recursive (nested)\n// case when the type name is implicit.  e.g. in []*T{{}}, the inner\n// literal has type *T behaves like &T{}.\n// In that case, addr must hold a T, not a *T.\nfunc (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) {\n\ttyp := typeparams.Deref(fn.typeOf(e)) // retain the named/alias/param type, if any\n\tswitch t := typeparams.CoreType(typ).(type) {\n\tcase *types.Struct:\n\t\tif !isZero && len(e.Elts) != t.NumFields() {\n\t\t\t// memclear\n\t\t\tzt := typeparams.MustDeref(addr.Type())\n\t\t\tsb.store(&address{addr, e.Lbrace, nil}, zeroConst(zt))\n\t\t\tisZero = true\n\t\t}\n\t\tfor i, e := range e.Elts {\n\t\t\tfieldIndex := i\n\t\t\tpos := e.Pos()\n\t\t\tif kv, ok := e.(*ast.KeyValueExpr); ok {\n\t\t\t\tfname := kv.Key.(*ast.Ident).Name\n\t\t\t\tfor i, n := 0, t.NumFields(); i < n; i++ {\n\t\t\t\t\tsf := t.Field(i)\n\t\t\t\t\tif sf.Name() == fname {\n\t\t\t\t\t\tfieldIndex = i\n\t\t\t\t\t\tpos = kv.Colon\n\t\t\t\t\t\te = kv.Value\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsf := t.Field(fieldIndex)\n\t\t\tfaddr := &FieldAddr{\n\t\t\t\tX:     addr,\n\t\t\t\tField: fieldIndex,\n\t\t\t}\n\t\t\tfaddr.setPos(pos)\n\t\t\tfaddr.setType(types.NewPointer(sf.Type()))\n\t\t\tfn.emit(faddr)\n\t\t\tb.assign(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero, sb)\n\t\t}\n\n\tcase *types.Array, *types.Slice:\n\t\tvar at *types.Array\n\t\tvar array Value\n\t\tswitch t := t.(type) {\n\t\tcase *types.Slice:\n\t\t\tat = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))\n\t\t\tarray = emitNew(fn, at, e.Lbrace, \"slicelit\")\n\t\tcase *types.Array:\n\t\t\tat = t\n\t\t\tarray = addr\n\n\t\t\tif !isZero && int64(len(e.Elts)) != at.Len() {\n\t\t\t\t// memclear\n\t\t\t\tzt := typeparams.MustDeref(array.Type())\n\t\t\t\tsb.store(&address{array, e.Lbrace, nil}, zeroConst(zt))\n\t\t\t}\n\t\t}\n\n\t\tvar idx *Const\n\t\tfor _, e := range e.Elts {\n\t\t\tpos := e.Pos()\n\t\t\tif kv, ok := e.(*ast.KeyValueExpr); ok {\n\t\t\t\tidx = b.expr(fn, kv.Key).(*Const)\n\t\t\t\tpos = kv.Colon\n\t\t\t\te = kv.Value\n\t\t\t} else {\n\t\t\t\tvar idxval int64\n\t\t\t\tif idx != nil {\n\t\t\t\t\tidxval = idx.Int64() + 1\n\t\t\t\t}\n\t\t\t\tidx = intConst(idxval)\n\t\t\t}\n\t\t\tiaddr := &IndexAddr{\n\t\t\t\tX:     array,\n\t\t\t\tIndex: idx,\n\t\t\t}\n\t\t\tiaddr.setType(types.NewPointer(at.Elem()))\n\t\t\tfn.emit(iaddr)\n\t\t\tif t != at { // slice\n\t\t\t\t// backing array is unaliased => storebuf not needed.\n\t\t\t\tb.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, nil)\n\t\t\t} else {\n\t\t\t\tb.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, sb)\n\t\t\t}\n\t\t}\n\n\t\tif t != at { // slice\n\t\t\ts := &Slice{X: array}\n\t\t\ts.setPos(e.Lbrace)\n\t\t\ts.setType(typ)\n\t\t\tsb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, fn.emit(s))\n\t\t}\n\n\tcase *types.Map:\n\t\tm := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}\n\t\tm.setPos(e.Lbrace)\n\t\tm.setType(typ)\n\t\tfn.emit(m)\n\t\tfor _, e := range e.Elts {\n\t\t\te := e.(*ast.KeyValueExpr)\n\n\t\t\t// If a key expression in a map literal is itself a\n\t\t\t// composite literal, the type may be omitted.\n\t\t\t// For example:\n\t\t\t//\tmap[*struct{}]bool{{}: true}\n\t\t\t// An &-operation may be implied:\n\t\t\t//\tmap[*struct{}]bool{&struct{}{}: true}\n\t\t\twantAddr := false\n\t\t\tif _, ok := ast.Unparen(e.Key).(*ast.CompositeLit); ok {\n\t\t\t\twantAddr = isPointerCore(t.Key())\n\t\t\t}\n\n\t\t\tvar key Value\n\t\t\tif wantAddr {\n\t\t\t\t// A CompositeLit never evaluates to a pointer,\n\t\t\t\t// so if the type of the location is a pointer,\n\t\t\t\t// an &-operation is implied.\n\t\t\t\tkey = b.addr(fn, e.Key, true).address(fn)\n\t\t\t} else {\n\t\t\t\tkey = b.expr(fn, e.Key)\n\t\t\t}\n\n\t\t\tloc := element{\n\t\t\t\tm:   m,\n\t\t\t\tk:   emitConv(fn, key, t.Key()),\n\t\t\t\tt:   t.Elem(),\n\t\t\t\tpos: e.Colon,\n\t\t\t}\n\n\t\t\t// We call assign() only because it takes care\n\t\t\t// of any &-operation required in the recursive\n\t\t\t// case, e.g.,\n\t\t\t// map[int]*struct{}{0: {}} implies &struct{}{}.\n\t\t\t// In-place update is of course impossible,\n\t\t\t// and no storebuf is needed.\n\t\t\tb.assign(fn, &loc, e.Value, true, nil)\n\t\t}\n\t\tsb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, m)\n\n\tdefault:\n\t\tpanic(\"unexpected CompositeLit type: \" + typ.String())\n\t}\n}\n\n// switchStmt emits to fn code for the switch statement s, optionally\n// labelled by label.\nfunc (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {\n\t// We treat SwitchStmt like a sequential if-else chain.\n\t// Multiway dispatch can be recovered later by ssautil.Switches()\n\t// to those cases that are free of side effects.\n\tif s.Init != nil {\n\t\tb.stmt(fn, s.Init)\n\t}\n\tvar tag Value = vTrue\n\tif s.Tag != nil {\n\t\ttag = b.expr(fn, s.Tag)\n\t}\n\tdone := fn.newBasicBlock(\"switch.done\")\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\t// We pull the default case (if present) down to the end.\n\t// But each fallthrough label must point to the next\n\t// body block in source order, so we preallocate a\n\t// body block (fallthru) for the next case.\n\t// Unfortunately this makes for a confusing block order.\n\tvar dfltBody *[]ast.Stmt\n\tvar dfltFallthrough *BasicBlock\n\tvar fallthru, dfltBlock *BasicBlock\n\tncases := len(s.Body.List)\n\tfor i, clause := range s.Body.List {\n\t\tbody := fallthru\n\t\tif body == nil {\n\t\t\tbody = fn.newBasicBlock(\"switch.body\") // first case only\n\t\t}\n\n\t\t// Preallocate body block for the next case.\n\t\tfallthru = done\n\t\tif i+1 < ncases {\n\t\t\tfallthru = fn.newBasicBlock(\"switch.body\")\n\t\t}\n\n\t\tcc := clause.(*ast.CaseClause)\n\t\tif cc.List == nil {\n\t\t\t// Default case.\n\t\t\tdfltBody = &cc.Body\n\t\t\tdfltFallthrough = fallthru\n\t\t\tdfltBlock = body\n\t\t\tcontinue\n\t\t}\n\n\t\tvar nextCond *BasicBlock\n\t\tfor _, cond := range cc.List {\n\t\t\tnextCond = fn.newBasicBlock(\"switch.next\")\n\t\t\t// For boolean switches, emit short-circuit control flow,\n\t\t\t// just like an if/else-chain.\n\t\t\tif tag == vTrue && !isNonTypeParamInterface(fn.info.Types[cond].Type) {\n\t\t\t\tb.cond(fn, cond, body, nextCond)\n\t\t\t} else {\n\t\t\t\tc := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), cond.Pos())\n\t\t\t\temitIf(fn, c, body, nextCond)\n\t\t\t}\n\t\t\tfn.currentBlock = nextCond\n\t\t}\n\t\tfn.currentBlock = body\n\t\tfn.targets = &targets{\n\t\t\ttail:         fn.targets,\n\t\t\t_break:       done,\n\t\t\t_fallthrough: fallthru,\n\t\t}\n\t\tb.stmtList(fn, cc.Body)\n\t\tfn.targets = fn.targets.tail\n\t\temitJump(fn, done)\n\t\tfn.currentBlock = nextCond\n\t}\n\tif dfltBlock != nil {\n\t\temitJump(fn, dfltBlock)\n\t\tfn.currentBlock = dfltBlock\n\t\tfn.targets = &targets{\n\t\t\ttail:         fn.targets,\n\t\t\t_break:       done,\n\t\t\t_fallthrough: dfltFallthrough,\n\t\t}\n\t\tb.stmtList(fn, *dfltBody)\n\t\tfn.targets = fn.targets.tail\n\t}\n\temitJump(fn, done)\n\tfn.currentBlock = done\n}\n\n// typeSwitchStmt emits to fn code for the type switch statement s, optionally\n// labelled by label.\nfunc (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {\n\t// We treat TypeSwitchStmt like a sequential if-else chain.\n\t// Multiway dispatch can be recovered later by ssautil.Switches().\n\n\t// Typeswitch lowering:\n\t//\n\t// var x X\n\t// switch y := x.(type) {\n\t// case T1, T2: S1                  // >1 \t(y := x)\n\t// case nil:    SN                  // nil \t(y := x)\n\t// default:     SD                  // 0 types \t(y := x)\n\t// case T3:     S3                  // 1 type \t(y := x.(T3))\n\t// }\n\t//\n\t//      ...s.Init...\n\t// \tx := eval x\n\t// .caseT1:\n\t// \tt1, ok1 := typeswitch,ok x <T1>\n\t// \tif ok1 then goto S1 else goto .caseT2\n\t// .caseT2:\n\t// \tt2, ok2 := typeswitch,ok x <T2>\n\t// \tif ok2 then goto S1 else goto .caseNil\n\t// .S1:\n\t//      y := x\n\t// \t...S1...\n\t// \tgoto done\n\t// .caseNil:\n\t// \tif t2, ok2 := typeswitch,ok x <T2>\n\t// \tif x == nil then goto SN else goto .caseT3\n\t// .SN:\n\t//      y := x\n\t// \t...SN...\n\t// \tgoto done\n\t// .caseT3:\n\t// \tt3, ok3 := typeswitch,ok x <T3>\n\t// \tif ok3 then goto S3 else goto default\n\t// .S3:\n\t//      y := t3\n\t// \t...S3...\n\t// \tgoto done\n\t// .default:\n\t//      y := x\n\t// \t...SD...\n\t// \tgoto done\n\t// .done:\n\tif s.Init != nil {\n\t\tb.stmt(fn, s.Init)\n\t}\n\n\tvar x Value\n\tswitch ass := s.Assign.(type) {\n\tcase *ast.ExprStmt: // x.(type)\n\t\tx = b.expr(fn, ast.Unparen(ass.X).(*ast.TypeAssertExpr).X)\n\tcase *ast.AssignStmt: // y := x.(type)\n\t\tx = b.expr(fn, ast.Unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)\n\t}\n\n\tdone := fn.newBasicBlock(\"typeswitch.done\")\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\tvar default_ *ast.CaseClause\n\tfor _, clause := range s.Body.List {\n\t\tcc := clause.(*ast.CaseClause)\n\t\tif cc.List == nil {\n\t\t\tdefault_ = cc\n\t\t\tcontinue\n\t\t}\n\t\tbody := fn.newBasicBlock(\"typeswitch.body\")\n\t\tvar next *BasicBlock\n\t\tvar casetype types.Type\n\t\tvar ti Value // ti, ok := typeassert,ok x <Ti>\n\t\tfor _, cond := range cc.List {\n\t\t\tnext = fn.newBasicBlock(\"typeswitch.next\")\n\t\t\tcasetype = fn.typeOf(cond)\n\t\t\tvar condv Value\n\t\t\tif casetype == tUntypedNil {\n\t\t\t\tcondv = emitCompare(fn, token.EQL, x, zeroConst(x.Type()), cond.Pos())\n\t\t\t\tti = x\n\t\t\t} else {\n\t\t\t\tyok := emitTypeTest(fn, x, casetype, cc.Case)\n\t\t\t\tti = emitExtract(fn, yok, 0)\n\t\t\t\tcondv = emitExtract(fn, yok, 1)\n\t\t\t}\n\t\t\temitIf(fn, condv, body, next)\n\t\t\tfn.currentBlock = next\n\t\t}\n\t\tif len(cc.List) != 1 {\n\t\t\tti = x\n\t\t}\n\t\tfn.currentBlock = body\n\t\tb.typeCaseBody(fn, cc, ti, done)\n\t\tfn.currentBlock = next\n\t}\n\tif default_ != nil {\n\t\tb.typeCaseBody(fn, default_, x, done)\n\t} else {\n\t\temitJump(fn, done)\n\t}\n\tfn.currentBlock = done\n}\n\nfunc (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) {\n\tif obj, ok := fn.info.Implicits[cc].(*types.Var); ok {\n\t\t// In a switch y := x.(type), each case clause\n\t\t// implicitly declares a distinct object y.\n\t\t// In a single-type case, y has that type.\n\t\t// In multi-type cases, 'case nil' and default,\n\t\t// y has the same type as the interface operand.\n\t\temitStore(fn, emitLocalVar(fn, obj), x, obj.Pos())\n\t}\n\tfn.targets = &targets{\n\t\ttail:   fn.targets,\n\t\t_break: done,\n\t}\n\tb.stmtList(fn, cc.Body)\n\tfn.targets = fn.targets.tail\n\temitJump(fn, done)\n}\n\n// selectStmt emits to fn code for the select statement s, optionally\n// labelled by label.\nfunc (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {\n\t// A blocking select of a single case degenerates to a\n\t// simple send or receive.\n\t// TODO(adonovan): opt: is this optimization worth its weight?\n\tif len(s.Body.List) == 1 {\n\t\tclause := s.Body.List[0].(*ast.CommClause)\n\t\tif clause.Comm != nil {\n\t\t\tb.stmt(fn, clause.Comm)\n\t\t\tdone := fn.newBasicBlock(\"select.done\")\n\t\t\tif label != nil {\n\t\t\t\tlabel._break = done\n\t\t\t}\n\t\t\tfn.targets = &targets{\n\t\t\t\ttail:   fn.targets,\n\t\t\t\t_break: done,\n\t\t\t}\n\t\t\tb.stmtList(fn, clause.Body)\n\t\t\tfn.targets = fn.targets.tail\n\t\t\temitJump(fn, done)\n\t\t\tfn.currentBlock = done\n\t\t\treturn\n\t\t}\n\t}\n\n\t// First evaluate all channels in all cases, and find\n\t// the directions of each state.\n\tvar states []*SelectState\n\tblocking := true\n\tdebugInfo := fn.debugInfo()\n\tfor _, clause := range s.Body.List {\n\t\tvar st *SelectState\n\t\tswitch comm := clause.(*ast.CommClause).Comm.(type) {\n\t\tcase nil: // default case\n\t\t\tblocking = false\n\t\t\tcontinue\n\n\t\tcase *ast.SendStmt: // ch<- i\n\t\t\tch := b.expr(fn, comm.Chan)\n\t\t\tchtyp := typeparams.CoreType(fn.typ(ch.Type())).(*types.Chan)\n\t\t\tst = &SelectState{\n\t\t\t\tDir:  types.SendOnly,\n\t\t\t\tChan: ch,\n\t\t\t\tSend: emitConv(fn, b.expr(fn, comm.Value), chtyp.Elem()),\n\t\t\t\tPos:  comm.Arrow,\n\t\t\t}\n\t\t\tif debugInfo {\n\t\t\t\tst.DebugNode = comm\n\t\t\t}\n\n\t\tcase *ast.AssignStmt: // x := <-ch\n\t\t\trecv := ast.Unparen(comm.Rhs[0]).(*ast.UnaryExpr)\n\t\t\tst = &SelectState{\n\t\t\t\tDir:  types.RecvOnly,\n\t\t\t\tChan: b.expr(fn, recv.X),\n\t\t\t\tPos:  recv.OpPos,\n\t\t\t}\n\t\t\tif debugInfo {\n\t\t\t\tst.DebugNode = recv\n\t\t\t}\n\n\t\tcase *ast.ExprStmt: // <-ch\n\t\t\trecv := ast.Unparen(comm.X).(*ast.UnaryExpr)\n\t\t\tst = &SelectState{\n\t\t\t\tDir:  types.RecvOnly,\n\t\t\t\tChan: b.expr(fn, recv.X),\n\t\t\t\tPos:  recv.OpPos,\n\t\t\t}\n\t\t\tif debugInfo {\n\t\t\t\tst.DebugNode = recv\n\t\t\t}\n\t\t}\n\t\tstates = append(states, st)\n\t}\n\n\t// We dispatch on the (fair) result of Select using a\n\t// sequential if-else chain, in effect:\n\t//\n\t// idx, recvOk, r0...r_n-1 := select(...)\n\t// if idx == 0 {  // receive on channel 0  (first receive => r0)\n\t//     x, ok := r0, recvOk\n\t//     ...state0...\n\t// } else if v == 1 {   // send on channel 1\n\t//     ...state1...\n\t// } else {\n\t//     ...default...\n\t// }\n\tsel := &Select{\n\t\tStates:   states,\n\t\tBlocking: blocking,\n\t}\n\tsel.setPos(s.Select)\n\tvar vars []*types.Var\n\tvars = append(vars, varIndex, varOk)\n\tfor _, st := range states {\n\t\tif st.Dir == types.RecvOnly {\n\t\t\tchtyp := typeparams.CoreType(fn.typ(st.Chan.Type())).(*types.Chan)\n\t\t\tvars = append(vars, anonVar(chtyp.Elem()))\n\t\t}\n\t}\n\tsel.setType(types.NewTuple(vars...))\n\n\tfn.emit(sel)\n\tidx := emitExtract(fn, sel, 0)\n\n\tdone := fn.newBasicBlock(\"select.done\")\n\tif label != nil {\n\t\tlabel._break = done\n\t}\n\n\tvar defaultBody *[]ast.Stmt\n\tstate := 0\n\tr := 2 // index in 'sel' tuple of value; increments if st.Dir==RECV\n\tfor _, cc := range s.Body.List {\n\t\tclause := cc.(*ast.CommClause)\n\t\tif clause.Comm == nil {\n\t\t\tdefaultBody = &clause.Body\n\t\t\tcontinue\n\t\t}\n\t\tbody := fn.newBasicBlock(\"select.body\")\n\t\tnext := fn.newBasicBlock(\"select.next\")\n\t\temitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next)\n\t\tfn.currentBlock = body\n\t\tfn.targets = &targets{\n\t\t\ttail:   fn.targets,\n\t\t\t_break: done,\n\t\t}\n\t\tswitch comm := clause.Comm.(type) {\n\t\tcase *ast.ExprStmt: // <-ch\n\t\t\tif debugInfo {\n\t\t\t\tv := emitExtract(fn, sel, r)\n\t\t\t\temitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)\n\t\t\t}\n\t\t\tr++\n\n\t\tcase *ast.AssignStmt: // x := <-states[state].Chan\n\t\t\tif comm.Tok == token.DEFINE {\n\t\t\t\temitLocalVar(fn, identVar(fn, comm.Lhs[0].(*ast.Ident)))\n\t\t\t}\n\t\t\tx := b.addr(fn, comm.Lhs[0], false) // non-escaping\n\t\t\tv := emitExtract(fn, sel, r)\n\t\t\tif debugInfo {\n\t\t\t\temitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)\n\t\t\t}\n\t\t\tx.store(fn, v)\n\n\t\t\tif len(comm.Lhs) == 2 { // x, ok := ...\n\t\t\t\tif comm.Tok == token.DEFINE {\n\t\t\t\t\temitLocalVar(fn, identVar(fn, comm.Lhs[1].(*ast.Ident)))\n\t\t\t\t}\n\t\t\t\tok := b.addr(fn, comm.Lhs[1], false) // non-escaping\n\t\t\t\tok.store(fn, emitExtract(fn, sel, 1))\n\t\t\t}\n\t\t\tr++\n\t\t}\n\t\tb.stmtList(fn, clause.Body)\n\t\tfn.targets = fn.targets.tail\n\t\temitJump(fn, done)\n\t\tfn.currentBlock = next\n\t\tstate++\n\t}\n\tif defaultBody != nil {\n\t\tfn.targets = &targets{\n\t\t\ttail:   fn.targets,\n\t\t\t_break: done,\n\t\t}\n\t\tb.stmtList(fn, *defaultBody)\n\t\tfn.targets = fn.targets.tail\n\t} else {\n\t\t// A blocking select must match some case.\n\t\t// (This should really be a runtime.errorString, not a string.)\n\t\tfn.emit(&Panic{\n\t\t\tX: emitConv(fn, stringConst(\"blocking select matched no case\"), tEface),\n\t\t})\n\t\tfn.currentBlock = fn.newBasicBlock(\"unreachable\")\n\t}\n\temitJump(fn, done)\n\tfn.currentBlock = done\n}\n\n// forStmt emits to fn code for the for statement s, optionally\n// labelled by label.\nfunc (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {\n\t// Use forStmtGo122 instead if it applies.\n\tif s.Init != nil {\n\t\tif assign, ok := s.Init.(*ast.AssignStmt); ok && assign.Tok == token.DEFINE {\n\t\t\tif versions.AtLeast(fn.goversion, versions.Go1_22) {\n\t\t\t\tb.forStmtGo122(fn, s, label)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t//     ...init...\n\t//     jump loop\n\t// loop:\n\t//     if cond goto body else done\n\t// body:\n\t//     ...body...\n\t//     jump post\n\t// post:                                 (target of continue)\n\t//     ...post...\n\t//     jump loop\n\t// done:                                 (target of break)\n\tif s.Init != nil {\n\t\tb.stmt(fn, s.Init)\n\t}\n\n\tbody := fn.newBasicBlock(\"for.body\")\n\tdone := fn.newBasicBlock(\"for.done\") // target of 'break'\n\tloop := body                         // target of back-edge\n\tif s.Cond != nil {\n\t\tloop = fn.newBasicBlock(\"for.loop\")\n\t}\n\tcont := loop // target of 'continue'\n\tif s.Post != nil {\n\t\tcont = fn.newBasicBlock(\"for.post\")\n\t}\n\tif label != nil {\n\t\tlabel._break = done\n\t\tlabel._continue = cont\n\t}\n\temitJump(fn, loop)\n\tfn.currentBlock = loop\n\tif loop != body {\n\t\tb.cond(fn, s.Cond, body, done)\n\t\tfn.currentBlock = body\n\t}\n\tfn.targets = &targets{\n\t\ttail:      fn.targets,\n\t\t_break:    done,\n\t\t_continue: cont,\n\t}\n\tb.stmt(fn, s.Body)\n\tfn.targets = fn.targets.tail\n\temitJump(fn, cont)\n\n\tif s.Post != nil {\n\t\tfn.currentBlock = cont\n\t\tb.stmt(fn, s.Post)\n\t\temitJump(fn, loop) // back-edge\n\t}\n\tfn.currentBlock = done\n}\n\n// forStmtGo122 emits to fn code for the for statement s, optionally\n// labelled by label. s must define its variables.\n//\n// This allocates once per loop iteration. This is only correct in\n// GoVersions >= go1.22.\nfunc (b *builder) forStmtGo122(fn *Function, s *ast.ForStmt, label *lblock) {\n\t//     i_outer = alloc[T]\n\t//     *i_outer = ...init...        // under objects[i] = i_outer\n\t//     jump loop\n\t// loop:\n\t//     i = phi [head: i_outer, loop: i_next]\n\t//     ...cond...                   // under objects[i] = i\n\t//     if cond goto body else done\n\t// body:\n\t//     ...body...                   // under objects[i] = i (same as loop)\n\t//     jump post\n\t// post:\n\t//     tmp = *i\n\t//     i_next = alloc[T]\n\t//     *i_next = tmp\n\t//     ...post...                   // under objects[i] = i_next\n\t//     goto loop\n\t// done:\n\n\tinit := s.Init.(*ast.AssignStmt)\n\tstartingBlocks := len(fn.Blocks)\n\n\tpre := fn.currentBlock               // current block before starting\n\tloop := fn.newBasicBlock(\"for.loop\") // target of back-edge\n\tbody := fn.newBasicBlock(\"for.body\")\n\tpost := fn.newBasicBlock(\"for.post\") // target of 'continue'\n\tdone := fn.newBasicBlock(\"for.done\") // target of 'break'\n\n\t// For each of the n loop variables, we create five SSA values,\n\t// outer, phi, next, load, and store in pre, loop, and post.\n\t// There is no limit on n.\n\ttype loopVar struct {\n\t\tobj   *types.Var\n\t\touter *Alloc\n\t\tphi   *Phi\n\t\tload  *UnOp\n\t\tnext  *Alloc\n\t\tstore *Store\n\t}\n\tvars := make([]loopVar, len(init.Lhs))\n\tfor i, lhs := range init.Lhs {\n\t\tv := identVar(fn, lhs.(*ast.Ident))\n\t\ttyp := fn.typ(v.Type())\n\n\t\tfn.currentBlock = pre\n\t\touter := emitLocal(fn, typ, v.Pos(), v.Name())\n\n\t\tfn.currentBlock = loop\n\t\tphi := &Phi{Comment: v.Name()}\n\t\tphi.pos = v.Pos()\n\t\tphi.typ = outer.Type()\n\t\tfn.emit(phi)\n\n\t\tfn.currentBlock = post\n\t\t// If next is local, it reuses the address and zeroes the old value so\n\t\t// load before allocating next.\n\t\tload := emitLoad(fn, phi)\n\t\tnext := emitLocal(fn, typ, v.Pos(), v.Name())\n\t\tstore := emitStore(fn, next, load, token.NoPos)\n\n\t\tphi.Edges = []Value{outer, next} // pre edge is emitted before post edge.\n\n\t\tvars[i] = loopVar{v, outer, phi, load, next, store}\n\t}\n\n\t// ...init... under fn.objects[v] = i_outer\n\tfn.currentBlock = pre\n\tfor _, v := range vars {\n\t\tfn.vars[v.obj] = v.outer\n\t}\n\tconst isDef = false // assign to already-allocated outers\n\tb.assignStmt(fn, init.Lhs, init.Rhs, isDef)\n\tif label != nil {\n\t\tlabel._break = done\n\t\tlabel._continue = post\n\t}\n\temitJump(fn, loop)\n\n\t// ...cond... under fn.objects[v] = i\n\tfn.currentBlock = loop\n\tfor _, v := range vars {\n\t\tfn.vars[v.obj] = v.phi\n\t}\n\tif s.Cond != nil {\n\t\tb.cond(fn, s.Cond, body, done)\n\t} else {\n\t\temitJump(fn, body)\n\t}\n\n\t// ...body... under fn.objects[v] = i\n\tfn.currentBlock = body\n\tfn.targets = &targets{\n\t\ttail:      fn.targets,\n\t\t_break:    done,\n\t\t_continue: post,\n\t}\n\tb.stmt(fn, s.Body)\n\tfn.targets = fn.targets.tail\n\temitJump(fn, post)\n\n\t// ...post... under fn.objects[v] = i_next\n\tfor _, v := range vars {\n\t\tfn.vars[v.obj] = v.next\n\t}\n\tfn.currentBlock = post\n\tif s.Post != nil {\n\t\tb.stmt(fn, s.Post)\n\t}\n\temitJump(fn, loop) // back-edge\n\tfn.currentBlock = done\n\n\t// For each loop variable that does not escape,\n\t// (the common case), fuse its next cells into its\n\t// (local) outer cell as they have disjoint live ranges.\n\t//\n\t// It is sufficient to test whether i_next escapes,\n\t// because its Heap flag will be marked true if either\n\t// the cond or post expression causes i to escape\n\t// (because escape distributes over phi).\n\tvar nlocals int\n\tfor _, v := range vars {\n\t\tif !v.next.Heap {\n\t\t\tnlocals++\n\t\t}\n\t}\n\tif nlocals > 0 {\n\t\treplace := make(map[Value]Value, 2*nlocals)\n\t\tdead := make(map[Instruction]bool, 4*nlocals)\n\t\tfor _, v := range vars {\n\t\t\tif !v.next.Heap {\n\t\t\t\treplace[v.next] = v.outer\n\t\t\t\treplace[v.phi] = v.outer\n\t\t\t\tdead[v.phi], dead[v.next], dead[v.load], dead[v.store] = true, true, true, true\n\t\t\t}\n\t\t}\n\n\t\t// Replace all uses of i_next and phi with i_outer.\n\t\t// Referrers have not been built for fn yet so only update Instruction operands.\n\t\t// We need only look within the blocks added by the loop.\n\t\tvar operands []*Value // recycle storage\n\t\tfor _, b := range fn.Blocks[startingBlocks:] {\n\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\toperands = instr.Operands(operands[:0])\n\t\t\t\tfor _, ptr := range operands {\n\t\t\t\t\tk := *ptr\n\t\t\t\t\tif v := replace[k]; v != nil {\n\t\t\t\t\t\t*ptr = v\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove instructions for phi, load, and store.\n\t\t// lift() will remove the unused i_next *Alloc.\n\t\tisDead := func(i Instruction) bool { return dead[i] }\n\t\tloop.Instrs = slices.DeleteFunc(loop.Instrs, isDead)\n\t\tpost.Instrs = slices.DeleteFunc(post.Instrs, isDead)\n\t}\n}\n\n// rangeIndexed emits to fn the header for an integer-indexed loop\n// over array, *array or slice value x.\n// The v result is defined only if tv is non-nil.\n// forPos is the position of the \"for\" token.\nfunc (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {\n\t//\n\t//     length = len(x)\n\t//     index = -1\n\t// loop:                                     (target of continue)\n\t//     index++\n\t//     if index < length goto body else done\n\t// body:\n\t//     k = index\n\t//     v = x[index]\n\t//     ...body...\n\t//     jump loop\n\t// done:                                     (target of break)\n\n\t// Determine number of iterations.\n\tvar length Value\n\tdt := typeparams.Deref(x.Type())\n\tif arr, ok := typeparams.CoreType(dt).(*types.Array); ok {\n\t\t// For array or *array, the number of iterations is\n\t\t// known statically thanks to the type.  We avoid a\n\t\t// data dependence upon x, permitting later dead-code\n\t\t// elimination if x is pure, static unrolling, etc.\n\t\t// Ranging over a nil *array may have >0 iterations.\n\t\t// We still generate code for x, in case it has effects.\n\t\tlength = intConst(arr.Len())\n\t} else {\n\t\t// length = len(x).\n\t\tvar c Call\n\t\tc.Call.Value = makeLen(x.Type())\n\t\tc.Call.Args = []Value{x}\n\t\tc.setType(tInt)\n\t\tlength = fn.emit(&c)\n\t}\n\n\tindex := emitLocal(fn, tInt, token.NoPos, \"rangeindex\")\n\temitStore(fn, index, intConst(-1), pos)\n\n\tloop = fn.newBasicBlock(\"rangeindex.loop\")\n\temitJump(fn, loop)\n\tfn.currentBlock = loop\n\n\tincr := &BinOp{\n\t\tOp: token.ADD,\n\t\tX:  emitLoad(fn, index),\n\t\tY:  vOne,\n\t}\n\tincr.setType(tInt)\n\temitStore(fn, index, fn.emit(incr), pos)\n\n\tbody := fn.newBasicBlock(\"rangeindex.body\")\n\tdone = fn.newBasicBlock(\"rangeindex.done\")\n\temitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)\n\tfn.currentBlock = body\n\n\tk = emitLoad(fn, index)\n\tif tv != nil {\n\t\tswitch t := typeparams.CoreType(x.Type()).(type) {\n\t\tcase *types.Array:\n\t\t\tinstr := &Index{\n\t\t\t\tX:     x,\n\t\t\t\tIndex: k,\n\t\t\t}\n\t\t\tinstr.setType(t.Elem())\n\t\t\tinstr.setPos(x.Pos())\n\t\t\tv = fn.emit(instr)\n\n\t\tcase *types.Pointer: // *array\n\t\t\tinstr := &IndexAddr{\n\t\t\t\tX:     x,\n\t\t\t\tIndex: k,\n\t\t\t}\n\t\t\tinstr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))\n\t\t\tinstr.setPos(x.Pos())\n\t\t\tv = emitLoad(fn, fn.emit(instr))\n\n\t\tcase *types.Slice:\n\t\t\tinstr := &IndexAddr{\n\t\t\t\tX:     x,\n\t\t\t\tIndex: k,\n\t\t\t}\n\t\t\tinstr.setType(types.NewPointer(t.Elem()))\n\t\t\tinstr.setPos(x.Pos())\n\t\t\tv = emitLoad(fn, fn.emit(instr))\n\n\t\tdefault:\n\t\t\tpanic(\"rangeIndexed x:\" + t.String())\n\t\t}\n\t}\n\treturn\n}\n\n// rangeIter emits to fn the header for a loop using\n// Range/Next/Extract to iterate over map or string value x.\n// tk and tv are the types of the key/value results k and v, or nil\n// if the respective component is not wanted.\nfunc (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {\n\t//\n\t//     it = range x\n\t// loop:                                   (target of continue)\n\t//     okv = next it                       (ok, key, value)\n\t//     ok = extract okv #0\n\t//     if ok goto body else done\n\t// body:\n\t//     k = extract okv #1\n\t//     v = extract okv #2\n\t//     ...body...\n\t//     jump loop\n\t// done:                                   (target of break)\n\t//\n\n\tif tk == nil {\n\t\ttk = tInvalid\n\t}\n\tif tv == nil {\n\t\ttv = tInvalid\n\t}\n\n\trng := &Range{X: x}\n\trng.setPos(pos)\n\trng.setType(tRangeIter)\n\tit := fn.emit(rng)\n\n\tloop = fn.newBasicBlock(\"rangeiter.loop\")\n\temitJump(fn, loop)\n\tfn.currentBlock = loop\n\n\tokv := &Next{\n\t\tIter:     it,\n\t\tIsString: isBasic(typeparams.CoreType(x.Type())),\n\t}\n\tokv.setType(types.NewTuple(\n\t\tvarOk,\n\t\tnewVar(\"k\", tk),\n\t\tnewVar(\"v\", tv),\n\t))\n\tfn.emit(okv)\n\n\tbody := fn.newBasicBlock(\"rangeiter.body\")\n\tdone = fn.newBasicBlock(\"rangeiter.done\")\n\temitIf(fn, emitExtract(fn, okv, 0), body, done)\n\tfn.currentBlock = body\n\n\tif tk != tInvalid {\n\t\tk = emitExtract(fn, okv, 1)\n\t}\n\tif tv != tInvalid {\n\t\tv = emitExtract(fn, okv, 2)\n\t}\n\treturn\n}\n\n// rangeChan emits to fn the header for a loop that receives from\n// channel x until it fails.\n// tk is the channel's element type, or nil if the k result is\n// not wanted\n// pos is the position of the '=' or ':=' token.\nfunc (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {\n\t//\n\t// loop:                                   (target of continue)\n\t//     ko = <-x                            (key, ok)\n\t//     ok = extract ko #1\n\t//     if ok goto body else done\n\t// body:\n\t//     k = extract ko #0\n\t//     ...body...\n\t//     goto loop\n\t// done:                                   (target of break)\n\n\tloop = fn.newBasicBlock(\"rangechan.loop\")\n\temitJump(fn, loop)\n\tfn.currentBlock = loop\n\trecv := &UnOp{\n\t\tOp:      token.ARROW,\n\t\tX:       x,\n\t\tCommaOk: true,\n\t}\n\trecv.setPos(pos)\n\trecv.setType(types.NewTuple(\n\t\tnewVar(\"k\", typeparams.CoreType(x.Type()).(*types.Chan).Elem()),\n\t\tvarOk,\n\t))\n\tko := fn.emit(recv)\n\tbody := fn.newBasicBlock(\"rangechan.body\")\n\tdone = fn.newBasicBlock(\"rangechan.done\")\n\temitIf(fn, emitExtract(fn, ko, 1), body, done)\n\tfn.currentBlock = body\n\tif tk != nil {\n\t\tk = emitExtract(fn, ko, 0)\n\t}\n\treturn\n}\n\n// rangeInt emits to fn the header for a range loop with an integer operand.\n// tk is the key value's type, or nil if the k result is not wanted.\n// pos is the position of the \"for\" token.\nfunc (b *builder) rangeInt(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {\n\t//\n\t//     iter = 0\n\t//     if 0 < x goto body else done\n\t// loop:                                   (target of continue)\n\t//     iter++\n\t//     if iter < x goto body else done\n\t// body:\n\t//     k = x\n\t//     ...body...\n\t//     jump loop\n\t// done:                                   (target of break)\n\n\tif isUntyped(x.Type()) {\n\t\tx = emitConv(fn, x, tInt)\n\t}\n\n\tT := x.Type()\n\titer := emitLocal(fn, T, token.NoPos, \"rangeint.iter\")\n\t// x may be unsigned. Avoid initializing x to -1.\n\n\tbody := fn.newBasicBlock(\"rangeint.body\")\n\tdone = fn.newBasicBlock(\"rangeint.done\")\n\temitIf(fn, emitCompare(fn, token.LSS, zeroConst(T), x, token.NoPos), body, done)\n\n\tloop = fn.newBasicBlock(\"rangeint.loop\")\n\tfn.currentBlock = loop\n\n\tincr := &BinOp{\n\t\tOp: token.ADD,\n\t\tX:  emitLoad(fn, iter),\n\t\tY:  emitConv(fn, vOne, T),\n\t}\n\tincr.setType(T)\n\temitStore(fn, iter, fn.emit(incr), pos)\n\temitIf(fn, emitCompare(fn, token.LSS, incr, x, token.NoPos), body, done)\n\tfn.currentBlock = body\n\n\tif tk != nil {\n\t\t// Integer types (int, uint8, etc.) are named and\n\t\t// we know that k is assignable to x when tk != nil.\n\t\t// This implies tk and T are identical so no conversion is needed.\n\t\tk = emitLoad(fn, iter)\n\t}\n\n\treturn\n}\n\n// rangeStmt emits to fn code for the range statement s, optionally\n// labelled by label.\nfunc (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {\n\tvar tk, tv types.Type\n\tif s.Key != nil && !isBlankIdent(s.Key) {\n\t\ttk = fn.typeOf(s.Key)\n\t}\n\tif s.Value != nil && !isBlankIdent(s.Value) {\n\t\ttv = fn.typeOf(s.Value)\n\t}\n\n\t// create locals for s.Key and s.Value.\n\tcreateVars := func() {\n\t\t// Unlike a short variable declaration, a RangeStmt\n\t\t// using := never redeclares an existing variable; it\n\t\t// always creates a new one.\n\t\tif tk != nil {\n\t\t\temitLocalVar(fn, identVar(fn, s.Key.(*ast.Ident)))\n\t\t}\n\t\tif tv != nil {\n\t\t\temitLocalVar(fn, identVar(fn, s.Value.(*ast.Ident)))\n\t\t}\n\t}\n\n\tafterGo122 := versions.AtLeast(fn.goversion, versions.Go1_22)\n\tif s.Tok == token.DEFINE && !afterGo122 {\n\t\t// pre-go1.22: If iteration variables are defined (:=), this\n\t\t// occurs once outside the loop.\n\t\tcreateVars()\n\t}\n\n\tx := b.expr(fn, s.X)\n\n\tvar k, v Value\n\tvar loop, done *BasicBlock\n\tswitch rt := typeparams.CoreType(x.Type()).(type) {\n\tcase *types.Slice, *types.Array, *types.Pointer: // *array\n\t\tk, v, loop, done = b.rangeIndexed(fn, x, tv, s.For)\n\n\tcase *types.Chan:\n\t\tk, loop, done = b.rangeChan(fn, x, tk, s.For)\n\n\tcase *types.Map:\n\t\tk, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)\n\n\tcase *types.Basic:\n\t\tswitch {\n\t\tcase rt.Info()&types.IsString != 0:\n\t\t\tk, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)\n\n\t\tcase rt.Info()&types.IsInteger != 0:\n\t\t\tk, loop, done = b.rangeInt(fn, x, tk, s.For)\n\n\t\tdefault:\n\t\t\tpanic(\"Cannot range over basic type: \" + rt.String())\n\t\t}\n\n\tcase *types.Signature:\n\t\t// Special case rewrite (fn.goversion >= go1.23):\n\t\t// \tfor x := range f { ... }\n\t\t// into\n\t\t// \tf(func(x T) bool { ... })\n\t\tb.rangeFunc(fn, x, s, label)\n\t\treturn\n\n\tdefault:\n\t\tpanic(\"Cannot range over: \" + rt.String())\n\t}\n\n\tif s.Tok == token.DEFINE && afterGo122 {\n\t\t// go1.22: If iteration variables are defined (:=), this occurs inside the loop.\n\t\tcreateVars()\n\t}\n\n\t// Evaluate both LHS expressions before we update either.\n\tvar kl, vl lvalue\n\tif tk != nil {\n\t\tkl = b.addr(fn, s.Key, false) // non-escaping\n\t}\n\tif tv != nil {\n\t\tvl = b.addr(fn, s.Value, false) // non-escaping\n\t}\n\tif tk != nil {\n\t\tkl.store(fn, k)\n\t}\n\tif tv != nil {\n\t\tvl.store(fn, v)\n\t}\n\n\tif label != nil {\n\t\tlabel._break = done\n\t\tlabel._continue = loop\n\t}\n\n\tfn.targets = &targets{\n\t\ttail:      fn.targets,\n\t\t_break:    done,\n\t\t_continue: loop,\n\t}\n\tb.stmt(fn, s.Body)\n\tfn.targets = fn.targets.tail\n\temitJump(fn, loop) // back-edge\n\tfn.currentBlock = done\n}\n\n// rangeFunc emits to fn code for the range-over-func rng.Body of the iterator\n// function x, optionally labelled by label. It creates a new anonymous function\n// yield for rng and builds the function.\nfunc (b *builder) rangeFunc(fn *Function, x Value, rng *ast.RangeStmt, label *lblock) {\n\t// Consider the SSA code for the outermost range-over-func in fn:\n\t//\n\t//   func fn(...) (ret R) {\n\t//     ...\n\t//     for k, v = range x {\n\t// \t     ...\n\t//     }\n\t//     ...\n\t//   }\n\t//\n\t// The code emitted into fn will look something like this.\n\t//\n\t// loop:\n\t//     jump := READY\n\t//     y := make closure yield [ret, deferstack, jump, k, v]\n\t//     x(y)\n\t//     switch jump {\n\t//        [see resuming execution]\n\t//     }\n\t//     goto done\n\t// done:\n\t//     ...\n\t//\n\t// where yield is a new synthetic yield function:\n\t//\n\t// func yield(_k tk, _v tv) bool\n\t//   free variables: [ret, stack, jump, k, v]\n\t// {\n\t//    entry:\n\t//      if jump != READY then goto invalid else valid\n\t//    invalid:\n\t//      panic(\"iterator called when it is not in a ready state\")\n\t//    valid:\n\t//      jump = BUSY\n\t//      k = _k\n\t//      v = _v\n\t//    ...\n\t//    cont:\n\t//      jump = READY\n\t//      return true\n\t// }\n\t//\n\t// Yield state:\n\t//\n\t// Each range loop has an associated jump variable that records\n\t// the state of the iterator. A yield function is initially\n\t// in a READY (0) and callable state.  If the yield function is called\n\t// and is not in READY state, it panics. When it is called in a callable\n\t// state, it becomes BUSY. When execution reaches the end of the body\n\t// of the loop (or a continue statement targeting the loop is executed),\n\t// the yield function returns true and resumes being in a READY state.\n\t// After the iterator function x(y) returns, then if the yield function\n\t// is in a READY state, the yield enters the DONE state.\n\t//\n\t// Each lowered control statement (break X, continue X, goto Z, or return)\n\t// that exits the loop sets the variable to a unique positive EXIT value,\n\t// before returning false from the yield function.\n\t//\n\t// If the yield function returns abruptly due to a panic or GoExit,\n\t// it remains in a BUSY state. The generated code asserts that, after\n\t// the iterator call x(y) returns normally, the jump variable state\n\t// is DONE.\n\t//\n\t// Resuming execution:\n\t//\n\t// The code generated for the range statement checks the jump\n\t// variable to determine how to resume execution.\n\t//\n\t//    switch jump {\n\t//    case BUSY:  panic(\"...\")\n\t//    case DONE:  goto done\n\t//    case READY: state = DONE; goto done\n\t//    case 123:   ... // action for exit 123.\n\t//    case 456:   ... // action for exit 456.\n\t//    ...\n\t//    }\n\t//\n\t// Forward goto statements within a yield are jumps to labels that\n\t// have not yet been traversed in fn. They may be in the Body of the\n\t// function. What we emit for these is:\n\t//\n\t//    goto target\n\t//  target:\n\t//    ...\n\t//\n\t// We leave an unresolved exit in yield.exits to check at the end\n\t// of building yield if it encountered target in the body. If it\n\t// encountered target, no additional work is required. Otherwise,\n\t// the yield emits a new early exit in the basic block for target.\n\t// We expect that blockopt will fuse the early exit into the case\n\t// block later. The unresolved exit is then added to yield.parent.exits.\n\n\tloop := fn.newBasicBlock(\"rangefunc.loop\")\n\tdone := fn.newBasicBlock(\"rangefunc.done\")\n\n\t// These are targets within y.\n\tfn.targets = &targets{\n\t\ttail:   fn.targets,\n\t\t_break: done,\n\t\t// _continue is within y.\n\t}\n\tif label != nil {\n\t\tlabel._break = done\n\t\t// _continue is within y\n\t}\n\n\temitJump(fn, loop)\n\tfn.currentBlock = loop\n\n\t// loop:\n\t//     jump := READY\n\n\tanonIdx := len(fn.AnonFuncs)\n\n\tjump := newVar(fmt.Sprintf(\"jump$%d\", anonIdx+1), tInt)\n\temitLocalVar(fn, jump) // zero value is READY\n\n\txsig := typeparams.CoreType(x.Type()).(*types.Signature)\n\tysig := typeparams.CoreType(xsig.Params().At(0).Type()).(*types.Signature)\n\n\t/* synthetic yield function for body of range-over-func loop */\n\ty := &Function{\n\t\tname:           fmt.Sprintf(\"%s$%d\", fn.Name(), anonIdx+1),\n\t\tSignature:      ysig,\n\t\tSynthetic:      \"range-over-func yield\",\n\t\tpos:            rng.Range,\n\t\tparent:         fn,\n\t\tanonIdx:        int32(len(fn.AnonFuncs)),\n\t\tPkg:            fn.Pkg,\n\t\tProg:           fn.Prog,\n\t\tsyntax:         rng,\n\t\tinfo:           fn.info,\n\t\tgoversion:      fn.goversion,\n\t\tbuild:          (*builder).buildYieldFunc,\n\t\ttopLevelOrigin: nil,\n\t\ttypeparams:     fn.typeparams,\n\t\ttypeargs:       fn.typeargs,\n\t\tsubst:          fn.subst,\n\t\tjump:           jump,\n\t\tdeferstack:     fn.deferstack,\n\t\treturnVars:     fn.returnVars, // use the parent's return variables\n\t\tuniq:           fn.uniq,       // start from parent's unique values\n\t}\n\n\t// If the RangeStmt has a label, this is how it is passed to buildYieldFunc.\n\tif label != nil {\n\t\ty.lblocks = map[*types.Label]*lblock{label.label: nil}\n\t}\n\tfn.AnonFuncs = append(fn.AnonFuncs, y)\n\n\t// Build y immediately. It may:\n\t// * cause fn's locals to escape, and\n\t// * create new exit nodes in exits.\n\t// (y is not marked 'built' until the end of the enclosing FuncDecl.)\n\tunresolved := len(fn.exits)\n\ty.build(b, y)\n\tfn.uniq = y.uniq // resume after y's unique values\n\n\t// Emit the call of y.\n\t//   c := MakeClosure y\n\t//   x(c)\n\tc := &MakeClosure{Fn: y}\n\tc.setType(ysig)\n\tfor _, fv := range y.FreeVars {\n\t\tc.Bindings = append(c.Bindings, fv.outer)\n\t\tfv.outer = nil\n\t}\n\tfn.emit(c)\n\tcall := Call{\n\t\tCall: CallCommon{\n\t\t\tValue: x,\n\t\t\tArgs:  []Value{c},\n\t\t\tpos:   token.NoPos,\n\t\t},\n\t}\n\tcall.setType(xsig.Results())\n\tfn.emit(&call)\n\n\texits := fn.exits[unresolved:]\n\tb.buildYieldResume(fn, jump, exits, done)\n\n\temitJump(fn, done)\n\tfn.currentBlock = done\n\t// pop the stack for the range-over-func\n\tfn.targets = fn.targets.tail\n}\n\n// buildYieldResume emits to fn code for how to resume execution once a call to\n// the iterator function over the yield function returns x(y). It does this by building\n// a switch over the value of jump for when it is READY, BUSY, or EXIT(id).\nfunc (b *builder) buildYieldResume(fn *Function, jump *types.Var, exits []*exit, done *BasicBlock) {\n\t//    v := *jump\n\t//    switch v {\n\t//    case BUSY:    panic(\"...\")\n\t//    case READY:   jump = DONE; goto done\n\t//    case EXIT(a): ...\n\t//    case EXIT(b): ...\n\t//    ...\n\t//    }\n\tv := emitLoad(fn, fn.lookup(jump, false))\n\n\t// case BUSY: panic(\"...\")\n\tisbusy := fn.newBasicBlock(\"rangefunc.resume.busy\")\n\tifready := fn.newBasicBlock(\"rangefunc.resume.ready.check\")\n\temitIf(fn, emitCompare(fn, token.EQL, v, jBusy, token.NoPos), isbusy, ifready)\n\tfn.currentBlock = isbusy\n\tfn.emit(&Panic{\n\t\tX: emitConv(fn, stringConst(\"iterator call did not preserve panic\"), tEface),\n\t})\n\tfn.currentBlock = ifready\n\n\t// case READY: jump = DONE; goto done\n\tisready := fn.newBasicBlock(\"rangefunc.resume.ready\")\n\tifexit := fn.newBasicBlock(\"rangefunc.resume.exits\")\n\temitIf(fn, emitCompare(fn, token.EQL, v, jReady, token.NoPos), isready, ifexit)\n\tfn.currentBlock = isready\n\tstoreVar(fn, jump, jDone, token.NoPos)\n\temitJump(fn, done)\n\tfn.currentBlock = ifexit\n\n\tfor _, e := range exits {\n\t\tid := intConst(e.id)\n\n\t\t//  case EXIT(id): { /* do e */ }\n\t\tcond := emitCompare(fn, token.EQL, v, id, e.pos)\n\t\tmatchb := fn.newBasicBlock(\"rangefunc.resume.match\")\n\t\tcndb := fn.newBasicBlock(\"rangefunc.resume.cnd\")\n\t\temitIf(fn, cond, matchb, cndb)\n\t\tfn.currentBlock = matchb\n\n\t\t// Cases to fill in the { /* do e */ } bit.\n\t\tswitch {\n\t\tcase e.label != nil: // forward goto?\n\t\t\t// case EXIT(id): goto lb // label\n\t\t\tlb := fn.lblockOf(e.label)\n\t\t\t// Do not mark lb as resolved.\n\t\t\t// If fn does not contain label, lb remains unresolved and\n\t\t\t// fn must itself be a range-over-func function. lb will be:\n\t\t\t//   lb:\n\t\t\t//     fn.jump = id\n\t\t\t//     return false\n\t\t\temitJump(fn, lb._goto)\n\n\t\tcase e.to != fn: // e jumps to an ancestor of fn?\n\t\t\t// case EXIT(id): { fn.jump = id; return false }\n\t\t\t// fn is a range-over-func function.\n\t\t\tstoreVar(fn, fn.jump, id, token.NoPos)\n\t\t\tfn.emit(&Return{Results: []Value{vFalse}, pos: e.pos})\n\n\t\tcase e.block == nil && e.label == nil: // return from fn?\n\t\t\t// case EXIT(id): { return ... }\n\t\t\tfn.emit(new(RunDefers))\n\t\t\tresults := make([]Value, len(fn.results))\n\t\t\tfor i, r := range fn.results {\n\t\t\t\tresults[i] = emitLoad(fn, r)\n\t\t\t}\n\t\t\tfn.emit(&Return{Results: results, pos: e.pos})\n\n\t\tcase e.block != nil:\n\t\t\t// case EXIT(id): goto block\n\t\t\temitJump(fn, e.block)\n\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t\tfn.currentBlock = cndb\n\t}\n}\n\n// stmt lowers statement s to SSA form, emitting code to fn.\nfunc (b *builder) stmt(fn *Function, _s ast.Stmt) {\n\t// The label of the current statement.  If non-nil, its _goto\n\t// target is always set; its _break and _continue are set only\n\t// within the body of switch/typeswitch/select/for/range.\n\t// It is effectively an additional default-nil parameter of stmt().\n\tvar label *lblock\nstart:\n\tswitch s := _s.(type) {\n\tcase *ast.EmptyStmt:\n\t\t// ignore.  (Usually removed by gofmt.)\n\n\tcase *ast.DeclStmt: // Con, Var or Typ\n\t\td := s.Decl.(*ast.GenDecl)\n\t\tif d.Tok == token.VAR {\n\t\t\tfor _, spec := range d.Specs {\n\t\t\t\tif vs, ok := spec.(*ast.ValueSpec); ok {\n\t\t\t\t\tb.localValueSpec(fn, vs)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\tif s.Label.Name == \"_\" {\n\t\t\t// Blank labels can't be the target of a goto, break,\n\t\t\t// or continue statement, so we don't need a new block.\n\t\t\t_s = s.Stmt\n\t\t\tgoto start\n\t\t}\n\t\tlabel = fn.lblockOf(fn.label(s.Label))\n\t\tlabel.resolved = true\n\t\temitJump(fn, label._goto)\n\t\tfn.currentBlock = label._goto\n\t\t_s = s.Stmt\n\t\tgoto start // effectively: tailcall stmt(fn, s.Stmt, label)\n\n\tcase *ast.ExprStmt:\n\t\tb.expr(fn, s.X)\n\n\tcase *ast.SendStmt:\n\t\tchtyp := typeparams.CoreType(fn.typeOf(s.Chan)).(*types.Chan)\n\t\tfn.emit(&Send{\n\t\t\tChan: b.expr(fn, s.Chan),\n\t\t\tX:    emitConv(fn, b.expr(fn, s.Value), chtyp.Elem()),\n\t\t\tpos:  s.Arrow,\n\t\t})\n\n\tcase *ast.IncDecStmt:\n\t\top := token.ADD\n\t\tif s.Tok == token.DEC {\n\t\t\top = token.SUB\n\t\t}\n\t\tloc := b.addr(fn, s.X, false)\n\t\tb.assignOp(fn, loc, NewConst(constant.MakeInt64(1), loc.typ()), op, s.Pos())\n\n\tcase *ast.AssignStmt:\n\t\tswitch s.Tok {\n\t\tcase token.ASSIGN, token.DEFINE:\n\t\t\tb.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE)\n\n\t\tdefault: // +=, etc.\n\t\t\top := s.Tok + token.ADD - token.ADD_ASSIGN\n\t\t\tb.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op, s.Pos())\n\t\t}\n\n\tcase *ast.GoStmt:\n\t\t// The \"intrinsics\" new/make/len/cap are forbidden here.\n\t\t// panic is treated like an ordinary function call.\n\t\tv := Go{pos: s.Go}\n\t\tb.setCall(fn, s.Call, &v.Call)\n\t\tfn.emit(&v)\n\n\tcase *ast.DeferStmt:\n\t\t// The \"intrinsics\" new/make/len/cap are forbidden here.\n\t\t// panic is treated like an ordinary function call.\n\t\tdeferstack := emitLoad(fn, fn.lookup(fn.deferstack, false))\n\t\tv := Defer{pos: s.Defer, DeferStack: deferstack}\n\t\tb.setCall(fn, s.Call, &v.Call)\n\t\tfn.emit(&v)\n\n\t\t// A deferred call can cause recovery from panic,\n\t\t// and control resumes at the Recover block.\n\t\tcreateRecoverBlock(fn.source)\n\n\tcase *ast.ReturnStmt:\n\t\tb.returnStmt(fn, s)\n\n\tcase *ast.BranchStmt:\n\t\tb.branchStmt(fn, s)\n\n\tcase *ast.BlockStmt:\n\t\tb.stmtList(fn, s.List)\n\n\tcase *ast.IfStmt:\n\t\tif s.Init != nil {\n\t\t\tb.stmt(fn, s.Init)\n\t\t}\n\t\tthen := fn.newBasicBlock(\"if.then\")\n\t\tdone := fn.newBasicBlock(\"if.done\")\n\t\tels := done\n\t\tif s.Else != nil {\n\t\t\tels = fn.newBasicBlock(\"if.else\")\n\t\t}\n\t\tb.cond(fn, s.Cond, then, els)\n\t\tfn.currentBlock = then\n\t\tb.stmt(fn, s.Body)\n\t\temitJump(fn, done)\n\n\t\tif s.Else != nil {\n\t\t\tfn.currentBlock = els\n\t\t\tb.stmt(fn, s.Else)\n\t\t\temitJump(fn, done)\n\t\t}\n\n\t\tfn.currentBlock = done\n\n\tcase *ast.SwitchStmt:\n\t\tb.switchStmt(fn, s, label)\n\n\tcase *ast.TypeSwitchStmt:\n\t\tb.typeSwitchStmt(fn, s, label)\n\n\tcase *ast.SelectStmt:\n\t\tb.selectStmt(fn, s, label)\n\n\tcase *ast.ForStmt:\n\t\tb.forStmt(fn, s, label)\n\n\tcase *ast.RangeStmt:\n\t\tb.rangeStmt(fn, s, label)\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected statement kind: %T\", s))\n\t}\n}\n\nfunc (b *builder) branchStmt(fn *Function, s *ast.BranchStmt) {\n\tvar block *BasicBlock\n\tif s.Label == nil {\n\t\tblock = targetedBlock(fn, s.Tok)\n\t} else {\n\t\ttarget := fn.label(s.Label)\n\t\tblock = labelledBlock(fn, target, s.Tok)\n\t\tif block == nil { // forward goto\n\t\t\tlb := fn.lblockOf(target)\n\t\t\tblock = lb._goto // jump to lb._goto\n\t\t\tif fn.jump != nil {\n\t\t\t\t// fn is a range-over-func and the goto may exit fn.\n\t\t\t\t// Create an exit and resolve it at the end of\n\t\t\t\t// builder.buildYieldFunc.\n\t\t\t\tlabelExit(fn, target, s.Pos())\n\t\t\t}\n\t\t}\n\t}\n\tto := block.parent\n\n\tif to == fn {\n\t\temitJump(fn, block)\n\t} else { // break outside of fn.\n\t\t// fn must be a range-over-func\n\t\te := blockExit(fn, block, s.Pos())\n\t\tstoreVar(fn, fn.jump, intConst(e.id), e.pos)\n\t\tfn.emit(&Return{Results: []Value{vFalse}, pos: e.pos})\n\t}\n\tfn.currentBlock = fn.newBasicBlock(\"unreachable\")\n}\n\nfunc (b *builder) returnStmt(fn *Function, s *ast.ReturnStmt) {\n\tvar results []Value\n\n\tsig := fn.source.Signature // signature of the enclosing source function\n\n\t// Convert return operands to result type.\n\tif len(s.Results) == 1 && sig.Results().Len() > 1 {\n\t\t// Return of one expression in a multi-valued function.\n\t\ttuple := b.exprN(fn, s.Results[0])\n\t\tttuple := tuple.Type().(*types.Tuple)\n\t\tfor i, n := 0, ttuple.Len(); i < n; i++ {\n\t\t\tresults = append(results,\n\t\t\t\temitConv(fn, emitExtract(fn, tuple, i),\n\t\t\t\t\tsig.Results().At(i).Type()))\n\t\t}\n\t} else {\n\t\t// 1:1 return, or no-arg return in non-void function.\n\t\tfor i, r := range s.Results {\n\t\t\tv := emitConv(fn, b.expr(fn, r), sig.Results().At(i).Type())\n\t\t\tresults = append(results, v)\n\t\t}\n\t}\n\n\t// Store the results.\n\tfor i, r := range results {\n\t\tvar result Value // fn.source.result[i] conceptually\n\t\tif fn == fn.source {\n\t\t\tresult = fn.results[i]\n\t\t} else { // lookup needed?\n\t\t\tresult = fn.lookup(fn.returnVars[i], false)\n\t\t}\n\t\temitStore(fn, result, r, s.Return)\n\t}\n\n\tif fn.jump != nil {\n\t\t// Return from body of a range-over-func.\n\t\t// The return statement is syntactically within the loop,\n\t\t// but the generated code is in the 'switch jump {...}' after it.\n\t\te := returnExit(fn, s.Pos())\n\t\tstoreVar(fn, fn.jump, intConst(e.id), e.pos)\n\t\tfn.emit(&Return{Results: []Value{vFalse}, pos: e.pos})\n\t\tfn.currentBlock = fn.newBasicBlock(\"unreachable\")\n\t\treturn\n\t}\n\n\t// Run function calls deferred in this\n\t// function when explicitly returning from it.\n\tfn.emit(new(RunDefers))\n\t// Reload (potentially) named result variables to form the result tuple.\n\tresults = results[:0]\n\tfor _, nr := range fn.results {\n\t\tresults = append(results, emitLoad(fn, nr))\n\t}\n\tfn.emit(&Return{Results: results, pos: s.Return})\n\tfn.currentBlock = fn.newBasicBlock(\"unreachable\")\n}\n\n// A buildFunc is a strategy for building the SSA body for a function.\ntype buildFunc = func(*builder, *Function)\n\n// iterate causes all created but unbuilt functions to be built. As\n// this may create new methods, the process is iterated until it\n// converges.\n//\n// Waits for any dependencies to finish building.\nfunc (b *builder) iterate() {\n\tfor ; b.finished < len(b.fns); b.finished++ {\n\t\tfn := b.fns[b.finished]\n\t\tb.buildFunction(fn)\n\t}\n\n\tb.buildshared.markDone()\n\tb.buildshared.wait()\n}\n\n// buildFunction builds SSA code for the body of function fn.  Idempotent.\nfunc (b *builder) buildFunction(fn *Function) {\n\tif fn.build != nil {\n\t\tassert(fn.parent == nil, \"anonymous functions should not be built by buildFunction()\")\n\n\t\tif fn.Prog.mode&LogSource != 0 {\n\t\t\tdefer logStack(\"build %s @ %s\", fn, fn.Prog.Fset.Position(fn.pos))()\n\t\t}\n\t\tfn.build(b, fn)\n\t\tfn.done()\n\t}\n}\n\n// buildParamsOnly builds fn.Params from fn.Signature, but does not build fn.Body.\nfunc (b *builder) buildParamsOnly(fn *Function) {\n\t// For external (C, asm) functions or functions loaded from\n\t// export data, we must set fn.Params even though there is no\n\t// body code to reference them.\n\tif recv := fn.Signature.Recv(); recv != nil {\n\t\tfn.addParamVar(recv)\n\t}\n\tparams := fn.Signature.Params()\n\tfor i, n := 0, params.Len(); i < n; i++ {\n\t\tfn.addParamVar(params.At(i))\n\t}\n\n\t// clear out other function state (keep consistent with finishBody)\n\tfn.subst = nil\n}\n\n// buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil.\nfunc (b *builder) buildFromSyntax(fn *Function) {\n\tvar (\n\t\trecvField *ast.FieldList\n\t\tbody      *ast.BlockStmt\n\t\tfunctype  *ast.FuncType\n\t)\n\tswitch syntax := fn.syntax.(type) {\n\tcase *ast.FuncDecl:\n\t\tfunctype = syntax.Type\n\t\trecvField = syntax.Recv\n\t\tbody = syntax.Body\n\t\tif body == nil {\n\t\t\tb.buildParamsOnly(fn) // no body (non-Go function)\n\t\t\treturn\n\t\t}\n\tcase *ast.FuncLit:\n\t\tfunctype = syntax.Type\n\t\tbody = syntax.Body\n\tcase nil:\n\t\tpanic(\"no syntax\")\n\tdefault:\n\t\tpanic(syntax) // unexpected syntax\n\t}\n\tfn.source = fn\n\tfn.startBody()\n\tfn.createSyntacticParams(recvField, functype)\n\tfn.createDeferStack()\n\tb.stmt(fn, body)\n\tif cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {\n\t\t// Control fell off the end of the function's body block.\n\t\t//\n\t\t// Block optimizations eliminate the current block, if\n\t\t// unreachable.  It is a builder invariant that\n\t\t// if this no-arg return is ill-typed for\n\t\t// fn.Signature.Results, this block must be\n\t\t// unreachable.  The sanity checker checks this.\n\t\tfn.emit(new(RunDefers))\n\t\tfn.emit(new(Return))\n\t}\n\tfn.finishBody()\n}\n\n// buildYieldFunc builds the body of the yield function created\n// from a range-over-func *ast.RangeStmt.\nfunc (b *builder) buildYieldFunc(fn *Function) {\n\t// See builder.rangeFunc for detailed documentation on how fn is set up.\n\t//\n\t// In pseudo-Go this roughly builds:\n\t// func yield(_k tk, _v tv) bool {\n\t// \t   if jump != READY { panic(\"yield function called after range loop exit\") }\n\t//     jump = BUSY\n\t//     k, v = _k, _v // assign the iterator variable (if needed)\n\t//     ... // rng.Body\n\t//   continue:\n\t//     jump = READY\n\t//     return true\n\t// }\n\ts := fn.syntax.(*ast.RangeStmt)\n\tfn.source = fn.parent.source\n\tfn.startBody()\n\tparams := fn.Signature.Params()\n\tfor v := range params.Variables() {\n\t\tfn.addParamVar(v)\n\t}\n\n\t// Initial targets\n\tycont := fn.newBasicBlock(\"yield-continue\")\n\t// lblocks is either {} or is {label: nil} where label is the label of syntax.\n\tfor label := range fn.lblocks {\n\t\tfn.lblocks[label] = &lblock{\n\t\t\tlabel:     label,\n\t\t\tresolved:  true,\n\t\t\t_goto:     ycont,\n\t\t\t_continue: ycont,\n\t\t\t// `break label` statement targets fn.parent.targets._break\n\t\t}\n\t}\n\tfn.targets = &targets{\n\t\ttail:      fn.targets,\n\t\t_continue: ycont,\n\t\t// `break` statement targets fn.parent.targets._break.\n\t}\n\n\t// continue:\n\t//   jump = READY\n\t//   return true\n\tsaved := fn.currentBlock\n\tfn.currentBlock = ycont\n\tstoreVar(fn, fn.jump, jReady, s.Body.Rbrace)\n\t// A yield function's own deferstack is always empty, so rundefers is not needed.\n\tfn.emit(&Return{Results: []Value{vTrue}, pos: token.NoPos})\n\n\t// Emit header:\n\t//\n\t//   if jump != READY { panic(\"yield iterator accessed after exit\") }\n\t//   jump = BUSY\n\t//   k, v = _k, _v\n\tfn.currentBlock = saved\n\tyloop := fn.newBasicBlock(\"yield-loop\")\n\tinvalid := fn.newBasicBlock(\"yield-invalid\")\n\n\tjumpVal := emitLoad(fn, fn.lookup(fn.jump, true))\n\temitIf(fn, emitCompare(fn, token.EQL, jumpVal, jReady, token.NoPos), yloop, invalid)\n\tfn.currentBlock = invalid\n\tfn.emit(&Panic{\n\t\tX: emitConv(fn, stringConst(\"yield function called after range loop exit\"), tEface),\n\t})\n\n\tfn.currentBlock = yloop\n\tstoreVar(fn, fn.jump, jBusy, s.Body.Rbrace)\n\n\t// Initialize k and v from params.\n\tvar tk, tv types.Type\n\tif s.Key != nil && !isBlankIdent(s.Key) {\n\t\ttk = fn.typeOf(s.Key) // fn.parent.typeOf is identical\n\t}\n\tif s.Value != nil && !isBlankIdent(s.Value) {\n\t\ttv = fn.typeOf(s.Value)\n\t}\n\tif s.Tok == token.DEFINE {\n\t\tif tk != nil {\n\t\t\temitLocalVar(fn, identVar(fn, s.Key.(*ast.Ident)))\n\t\t}\n\t\tif tv != nil {\n\t\t\temitLocalVar(fn, identVar(fn, s.Value.(*ast.Ident)))\n\t\t}\n\t}\n\tvar k, v Value\n\tif len(fn.Params) > 0 {\n\t\tk = fn.Params[0]\n\t}\n\tif len(fn.Params) > 1 {\n\t\tv = fn.Params[1]\n\t}\n\tvar kl, vl lvalue\n\tif tk != nil {\n\t\tkl = b.addr(fn, s.Key, false) // non-escaping\n\t}\n\tif tv != nil {\n\t\tvl = b.addr(fn, s.Value, false) // non-escaping\n\t}\n\tif tk != nil {\n\t\tkl.store(fn, k)\n\t}\n\tif tv != nil {\n\t\tvl.store(fn, v)\n\t}\n\n\t// Build the body of the range loop.\n\tb.stmt(fn, s.Body)\n\tif cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {\n\t\t// Control fell off the end of the function's body block.\n\t\t// Block optimizations eliminate the current block, if\n\t\t// unreachable.\n\t\temitJump(fn, ycont)\n\t}\n\t// pop the stack for the yield function\n\tfn.targets = fn.targets.tail\n\n\t// Clean up exits and promote any unresolved exits to fn.parent.\n\tfor _, e := range fn.exits {\n\t\tif e.label != nil {\n\t\t\tlb := fn.lblocks[e.label]\n\t\t\tif lb.resolved {\n\t\t\t\t// label was resolved. Do not turn lb into an exit.\n\t\t\t\t// e does not need to be handled by the parent.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// _goto becomes an exit.\n\t\t\t//   _goto:\n\t\t\t//     jump = id\n\t\t\t//     return false\n\t\t\tfn.currentBlock = lb._goto\n\t\t\tid := intConst(e.id)\n\t\t\tstoreVar(fn, fn.jump, id, e.pos)\n\t\t\tfn.emit(&Return{Results: []Value{vFalse}, pos: e.pos})\n\t\t}\n\n\t\tif e.to != fn { // e needs to be handled by the parent too.\n\t\t\tfn.parent.exits = append(fn.parent.exits, e)\n\t\t}\n\t}\n\n\tfn.finishBody()\n}\n\n// addMakeInterfaceType records non-interface type t as the type of\n// the operand a MakeInterface operation, for [Program.RuntimeTypes].\n//\n// Acquires prog.makeInterfaceTypesMu.\nfunc addMakeInterfaceType(prog *Program, t types.Type) {\n\tprog.makeInterfaceTypesMu.Lock()\n\tdefer prog.makeInterfaceTypesMu.Unlock()\n\tif prog.makeInterfaceTypes == nil {\n\t\tprog.makeInterfaceTypes = make(map[types.Type]unit)\n\t}\n\tprog.makeInterfaceTypes[t] = unit{}\n}\n\n// Build calls Package.Build for each package in prog.\n// Building occurs in parallel unless the BuildSerially mode flag was set.\n//\n// Build is intended for whole-program analysis; a typical compiler\n// need only build a single package.\n//\n// Build is idempotent and thread-safe.\nfunc (prog *Program) Build() {\n\tvar wg sync.WaitGroup\n\tfor _, p := range prog.packages {\n\t\tif prog.mode&BuildSerially != 0 {\n\t\t\tp.Build()\n\t\t} else {\n\t\t\twg.Add(1)\n\t\t\tcpuLimit <- unit{} // acquire a token\n\t\t\tgo func(p *Package) {\n\t\t\t\tp.Build()\n\t\t\t\twg.Done()\n\t\t\t\t<-cpuLimit // release a token\n\t\t\t}(p)\n\t\t}\n\t}\n\twg.Wait()\n}\n\n// cpuLimit is a counting semaphore to limit CPU parallelism.\nvar cpuLimit = make(chan unit, runtime.GOMAXPROCS(0))\n\n// Build builds SSA code for all functions and vars in package p.\n//\n// CreatePackage must have been called for all of p's direct imports\n// (and hence its direct imports must have been error-free). It is not\n// necessary to call CreatePackage for indirect dependencies.\n// Functions will be created for all necessary methods in those\n// packages on demand.\n//\n// Build is idempotent and thread-safe.\nfunc (p *Package) Build() { p.buildOnce.Do(p.build) }\n\nfunc (p *Package) build() {\n\tif p.info == nil {\n\t\treturn // synthetic package, e.g. \"testmain\"\n\t}\n\tif p.Prog.mode&LogSource != 0 {\n\t\tdefer logStack(\"build %s\", p)()\n\t}\n\n\tb := builder{fns: p.created}\n\tb.iterate()\n\n\t// We no longer need transient information: ASTs or go/types deductions.\n\tp.info = nil\n\tp.created = nil\n\tp.files = nil\n\tp.initVersion = nil\n\n\tif p.Prog.mode&SanityCheckFunctions != 0 {\n\t\tsanityCheckPackage(p)\n\t}\n}\n\n// buildPackageInit builds fn.Body for the synthetic package initializer.\nfunc (b *builder) buildPackageInit(fn *Function) {\n\tp := fn.Pkg\n\tfn.startBody()\n\n\tvar done *BasicBlock\n\n\tif p.Prog.mode&BareInits == 0 {\n\t\t// Make init() skip if package is already initialized.\n\t\tinitguard := p.Var(\"init$guard\")\n\t\tdoinit := fn.newBasicBlock(\"init.start\")\n\t\tdone = fn.newBasicBlock(\"init.done\")\n\t\temitIf(fn, emitLoad(fn, initguard), done, doinit)\n\t\tfn.currentBlock = doinit\n\t\temitStore(fn, initguard, vTrue, token.NoPos)\n\n\t\t// Call the init() function of each package we import.\n\t\tfor _, pkg := range p.Pkg.Imports() {\n\t\t\tprereq := p.Prog.packages[pkg]\n\t\t\tif prereq == nil {\n\t\t\t\tpanic(fmt.Sprintf(\"Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called\", p.Pkg.Path(), pkg.Path()))\n\t\t\t}\n\t\t\tvar v Call\n\t\t\tv.Call.Value = prereq.init\n\t\t\tv.Call.pos = fn.pos\n\t\t\tv.setType(types.NewTuple())\n\t\t\tfn.emit(&v)\n\t\t}\n\t}\n\n\t// Initialize package-level vars in correct order.\n\tif len(p.info.InitOrder) > 0 && len(p.files) == 0 {\n\t\tpanic(\"no source files provided for package. cannot initialize globals\")\n\t}\n\n\tfor _, varinit := range p.info.InitOrder {\n\t\tif fn.Prog.mode&LogSource != 0 {\n\t\t\tfmt.Fprintf(os.Stderr, \"build global initializer %v @ %s\\n\",\n\t\t\t\tvarinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos()))\n\t\t}\n\t\t// Initializers for global vars are evaluated in dependency\n\t\t// order, but may come from arbitrary files of the package\n\t\t// with different versions, so we transiently update\n\t\t// fn.goversion for each one. (Since init is a synthetic\n\t\t// function it has no syntax of its own that needs a version.)\n\t\tfn.goversion = p.initVersion[varinit.Rhs]\n\t\tif len(varinit.Lhs) == 1 {\n\t\t\t// 1:1 initialization: var x, y = a(), b()\n\t\t\tvar lval lvalue\n\t\t\tif v := varinit.Lhs[0]; v.Name() != \"_\" {\n\t\t\t\tlval = &address{addr: p.objects[v].(*Global), pos: v.Pos()}\n\t\t\t} else {\n\t\t\t\tlval = blank{}\n\t\t\t}\n\t\t\tb.assign(fn, lval, varinit.Rhs, true, nil)\n\t\t} else {\n\t\t\t// n:1 initialization: var x, y :=  f()\n\t\t\ttuple := b.exprN(fn, varinit.Rhs)\n\t\t\tfor i, v := range varinit.Lhs {\n\t\t\t\tif v.Name() == \"_\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\temitStore(fn, p.objects[v].(*Global), emitExtract(fn, tuple, i), v.Pos())\n\t\t\t}\n\t\t}\n\t}\n\n\t// The rest of the init function is synthetic:\n\t// no syntax, info, goversion.\n\tfn.info = nil\n\tfn.goversion = \"\"\n\n\t// Call all of the declared init() functions in source order.\n\tfor _, file := range p.files {\n\t\tfor _, decl := range file.Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\tid := decl.Name\n\t\t\t\tif !isBlankIdent(id) && id.Name == \"init\" && decl.Recv == nil {\n\t\t\t\t\tdeclaredInit := p.objects[p.info.Defs[id]].(*Function)\n\t\t\t\t\tvar v Call\n\t\t\t\t\tv.Call.Value = declaredInit\n\t\t\t\t\tv.setType(types.NewTuple())\n\t\t\t\t\tp.init.emit(&v)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Finish up init().\n\tif p.Prog.mode&BareInits == 0 {\n\t\temitJump(fn, done)\n\t\tfn.currentBlock = done\n\t}\n\tfn.emit(new(Return))\n\tfn.finishBody()\n}\n"
  },
  {
    "path": "go/ssa/builder_generic_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/expect\"\n)\n\n// TestGenericBodies tests that bodies of generic functions and methods containing\n// different constructs can be built in BuilderMode(0).\n//\n// Each test specifies the contents of package containing a single go file.\n// Each call print(arg0, arg1, ...) to the builtin print function\n// in ssa is correlated a comment at the end of the line of the form:\n//\n//\t//@ types(a, b, c)\n//\n// where a, b and c are the types of the arguments to the print call\n// serialized using go/types.Type.String().\n// See x/tools/internal/expect for details on the syntax.\nfunc TestGenericBodies(t *testing.T) {\n\tfor _, content := range []string{\n\t\t`\n\t\tpackage p00\n\n\t\tfunc f(x int) {\n\t\t\tvar i interface{}\n\t\t\tprint(i, 0) //@ types(\"interface{}\", int)\n\t\t\tprint()     //@ types()\n\t\t\tprint(x)    //@ types(int)\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p01\n\n\t\tfunc f[T any](x T) {\n\t\t\tprint(x) //@ types(T)\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p02\n\n\t\tfunc f[T ~int]() {\n\t\t\tvar x T\n\t\t\tprint(x) //@ types(T)\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p03\n\n\t\tfunc a[T ~[4]byte](x T) {\n\t\t\tfor k, v := range x {\n\t\t\t\tprint(x, k, v) //@ types(T, int, byte)\n\t\t\t}\n\t\t}\n\t\tfunc b[T ~*[4]byte](x T) {\n\t\t\tfor k, v := range x {\n\t\t\t\tprint(x, k, v) //@ types(T, int, byte)\n\t\t\t}\n\t\t}\n\t\tfunc c[T ~[]byte](x T) {\n\t\t\tfor k, v := range x {\n\t\t\t\tprint(x, k, v) //@ types(T, int, byte)\n\t\t\t}\n\t\t}\n\t\tfunc d[T ~string](x T) {\n\t\t\tfor k, v := range x {\n\t\t\t\tprint(x, k, v) //@ types(T, int, rune)\n\t\t\t}\n\t\t}\n\t\tfunc e[T ~map[int]string](x T) {\n\t\t\tfor k, v := range x {\n\t\t\t\tprint(x, k, v) //@ types(T, int, string)\n\t\t\t}\n\t\t}\n\t\tfunc f[T ~chan string](x T) {\n\t\t\tfor v := range x {\n\t\t\t\tprint(x, v) //@ types(T, string)\n\t\t\t}\n\t\t}\n\n\t\tfunc From() {\n\t\t\ttype A [4]byte\n\t\t\tprint(a[A]) //@ types(\"func(x p03.A)\")\n\n\t\t\ttype B *[4]byte\n\t\t\tprint(b[B]) //@ types(\"func(x p03.B)\")\n\n\t\t\ttype C []byte\n\t\t\tprint(c[C]) //@ types(\"func(x p03.C)\")\n\n\t\t\ttype D string\n\t\t\tprint(d[D]) //@ types(\"func(x p03.D)\")\n\n\t\t\ttype E map[int]string\n\t\t\tprint(e[E]) //@ types(\"func(x p03.E)\")\n\n\t\t\ttype F chan string\n\t\t\tprint(f[F]) //@ types(\"func(x p03.F)\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p05\n\n\t\tfunc f[S any, T ~chan S](x T) {\n\t\t\tfor v := range x {\n\t\t\t\tprint(x, v) //@ types(T, S)\n\t\t\t}\n\t\t}\n\n\t\tfunc From() {\n\t\t\ttype F chan string\n\t\t\tprint(f[string, F]) //@ types(\"func(x p05.F)\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p06\n\n\t\tfunc fibonacci[T ~chan int](c, quit T) {\n\t\t\tx, y := 0, 1\n\t\t\tfor {\n\t\t\t\tselect {\n\t\t\t\tcase c <- x:\n\t\t\t\t\tx, y = y, x+y\n\t\t\t\tcase <-quit:\n\t\t\t\t\tprint(c, quit, x, y) //@ types(T, T, int, int)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfunc start[T ~chan int](c, quit T) {\n\t\t\tgo func() {\n\t\t\t\tfor i := 0; i < 10; i++ {\n\t\t\t\t\tprint(<-c) //@ types(int)\n\t\t\t\t}\n\t\t\t\tquit <- 0\n\t\t\t}()\n\t\t}\n\t\tfunc From() {\n\t\t\ttype F chan int\n\t\t\tc := make(F)\n\t\t\tquit := make(F)\n\t\t\tprint(start[F], c, quit)     //@ types(\"func(c p06.F, quit p06.F)\", \"p06.F\", \"p06.F\")\n\t\t\tprint(fibonacci[F], c, quit) //@ types(\"func(c p06.F, quit p06.F)\", \"p06.F\", \"p06.F\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p07\n\n\t\tfunc f[T ~struct{ x int; y string }](i int) T {\n\t\t\tu := []T{ T{0, \"lorem\"},  T{1, \"ipsum\"}}\n\t\t\treturn u[i]\n\t\t}\n\t\tfunc From() {\n\t\t\ttype S struct{ x int; y string }\n\t\t\tprint(f[S])     //@ types(\"func(i int) p07.S\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p08\n\n\t\tfunc f[T ~[4]int8](x T, l, h int) []int8 {\n\t\t\treturn x[l:h]\n\t\t}\n\t\tfunc g[T ~*[4]int16](x T, l, h int) []int16 {\n\t\t\treturn x[l:h]\n\t\t}\n\t\tfunc h[T ~[]int32](x T, l, h int) T {\n\t\t\treturn x[l:h]\n\t\t}\n\t\tfunc From() {\n\t\t\ttype F [4]int8\n\t\t\ttype G *[4]int16\n\t\t\ttype H []int32\n\t\t\tprint(f[F](F{}, 0, 0))  //@ types(\"[]int8\")\n\t\t\tprint(g[G](nil, 0, 0)) //@ types(\"[]int16\")\n\t\t\tprint(h[H](nil, 0, 0)) //@ types(\"p08.H\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p09\n\n\t\tfunc h[E any, T ~[]E](x T, l, h int) []E {\n\t\t\ts := x[l:h]\n\t\t\tprint(s) //@ types(\"T\")\n\t\t\treturn s\n\t\t}\n\t\tfunc From() {\n\t\t\ttype H []int32\n\t\t\tprint(h[int32, H](nil, 0, 0)) //@ types(\"[]int32\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p10\n\n\t\t// Test \"make\" builtin with different forms on core types and\n\t\t// when capacities are constants or variable.\n\t\tfunc h[E any, T ~[]E](m, n int) {\n\t\t\tprint(make(T, 3))    //@ types(T)\n\t\t\tprint(make(T, 3, 5)) //@ types(T)\n\t\t\tprint(make(T, m))    //@ types(T)\n\t\t\tprint(make(T, m, n)) //@ types(T)\n\t\t}\n\t\tfunc i[K comparable, E any, T ~map[K]E](m int) {\n\t\t\tprint(make(T))    //@ types(T)\n\t\t\tprint(make(T, 5)) //@ types(T)\n\t\t\tprint(make(T, m)) //@ types(T)\n\t\t}\n\t\tfunc j[E any, T ~chan E](m int) {\n\t\t\tprint(make(T))    //@ types(T)\n\t\t\tprint(make(T, 6)) //@ types(T)\n\t\t\tprint(make(T, m)) //@ types(T)\n\t\t}\n\t\tfunc From() {\n\t\t\ttype H []int32\n\t\t\th[int32, H](3, 4)\n\t\t\ttype I map[int8]H\n\t\t\ti[int8, H, I](5)\n\t\t\ttype J chan I\n\t\t\tj[I, J](6)\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p11\n\n\t\tfunc h[T ~[4]int](x T) {\n\t\t\tprint(len(x), cap(x)) //@ types(int, int)\n\t\t}\n\t\tfunc i[T ~[4]byte | []int | ~chan uint8](x T) {\n\t\t\tprint(len(x), cap(x)) //@ types(int, int)\n\t\t}\n\t\tfunc j[T ~[4]int | any | map[string]int]() {\n\t\t\tprint(new(T)) //@ types(\"*T\")\n\t\t}\n\t\tfunc k[T ~[4]int | any | map[string]int](x T) {\n\t\t\tprint(x) //@ types(T)\n\t\t\tpanic(x)\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p12\n\n\t\tfunc f[E any, F ~func() E](x F) {\n\t\t\tprint(x, x()) //@ types(F, E)\n\t\t}\n\t\tfunc From() {\n\t\t\ttype T func() int\n\t\t\tf[int, T](func() int { return 0 })\n\t\t\tf[int, func() int](func() int { return 1 })\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p13\n\n\t\tfunc f[E any, M ~map[string]E](m M) {\n\t\t\ty, ok := m[\"lorem\"]\n\t\t\tprint(m, y, ok) //@ types(M, E, bool)\n\t\t}\n\t\tfunc From() {\n\t\t\ttype O map[string][]int\n\t\t\tf(O{\"lorem\": []int{0, 1, 2, 3}})\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p14\n\n\t\tfunc a[T interface{ []int64 | [5]int64 }](x T) int64 {\n\t\t\tprint(x, x[2], x[3]) //@ types(T, int64, int64)\n\t\t\tx[2] = 5\n\t\t\treturn x[3]\n\t\t}\n\t\tfunc b[T interface{ []byte | string }](x T) byte {\n\t\t\tprint(x, x[3]) //@ types(T, byte)\n\t\t\treturn x[3]\n\t\t}\n\t\tfunc c[T interface{ []byte }](x T) byte {\n\t\t\tprint(x, x[2], x[3]) //@ types(T, byte, byte)\n\t\t\tx[2] = 'b'\n\t\t\treturn x[3]\n\t\t}\n\t\tfunc d[T interface{ map[int]int64 }](x T) int64 {\n\t\t\tprint(x, x[2], x[3]) //@ types(T, int64, int64)\n\t\t\tx[2] = 43\n\t\t\treturn x[3]\n\t\t}\n\t\tfunc e[T ~string](t T) {\n\t\t\tprint(t, t[0]) //@ types(T, uint8)\n\t\t}\n\t\tfunc f[T ~string|[]byte](t T) {\n\t\t\tprint(t, t[0]) //@ types(T, uint8)\n\t\t}\n\t\tfunc g[T []byte](t T) {\n\t\t\tprint(t, t[0]) //@ types(T, byte)\n\t\t}\n\t\tfunc h[T ~[4]int|[]int](t T) {\n\t\t\tprint(t, t[0]) //@ types(T, int)\n\t\t}\n\t\tfunc i[T ~[4]int|*[4]int|[]int](t T) {\n\t\t\tprint(t, t[0]) //@ types(T, int)\n\t\t}\n\t\tfunc j[T ~[4]int|*[4]int|[]int](t T) {\n\t\t\tprint(t, &t[0]) //@ types(T, \"*int\")\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p15\n\n\t\ttype MyInt int\n\t\ttype Other int\n\t\ttype MyInterface interface{ foo() }\n\n\t\t// ChangeType tests\n\t\tfunc ct0(x int) { v := MyInt(x);  print(x, v) /*@ types(int, \"p15.MyInt\")*/ }\n\t\tfunc ct1[T MyInt | Other, S int ](x S) { v := T(x);  print(x, v) /*@ types(S, T)*/ }\n\t\tfunc ct2[T int, S MyInt | int ](x S) { v := T(x); print(x, v) /*@ types(S, T)*/ }\n\t\tfunc ct3[T MyInt | Other, S MyInt | int ](x S) { v := T(x) ; print(x, v) /*@ types(S, T)*/ }\n\n\t\t// Convert tests\n\t\tfunc co0[T int | int8](x MyInt) { v := T(x); print(x, v) /*@ types(\"p15.MyInt\", T)*/}\n\t\tfunc co1[T int | int8](x T) { v := MyInt(x); print(x, v) /*@ types(T, \"p15.MyInt\")*/ }\n\t\tfunc co2[S, T int | int8](x T) { v := S(x); print(x, v) /*@ types(T, S)*/ }\n\n\t\t// MakeInterface tests\n\t\tfunc mi0[T MyInterface](x T) { v := MyInterface(x); print(x, v) /*@ types(T, \"p15.MyInterface\")*/ }\n\n\t\t// NewConst tests\n\t\tfunc nc0[T any]() { v := (*T)(nil); print(v) /*@ types(\"*T\")*/}\n\n\t\t// SliceToArrayPointer\n\t\tfunc sl0[T *[4]int | *[2]int](x []int) { v := T(x); print(x, v) /*@ types(\"[]int\", T)*/ }\n\t\tfunc sl1[T *[4]int | *[2]int, S []int](x S) { v := T(x); print(x, v) /*@ types(S, T)*/ }\n\t\t`,\n\t\t`\n\t\tpackage p16\n\n\t\tfunc c[T interface{ foo() string }](x T) {\n\t\t\tprint(x, x.foo, x.foo())  /*@ types(T, \"func() string\", string)*/\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p17\n\n\t\tfunc eq[T comparable](t T, i interface{}) bool {\n\t\t\treturn t == i\n\t\t}\n\t\t`,\n\t\t// TODO(59983): investigate why writing g.c panics in (*FieldAddr).String.\n\t\t`\n\t\tpackage p18\n\n\t\ttype S struct{ f int }\n\t\tfunc c[P *S]() []P { return []P{{f: 1}} }\n\t\t`,\n\t\t`\n\t\tpackage p19\n\n\t\tfunc sign[bytes []byte | string](s bytes) (bool, bool) {\n\t\t\tneg := false\n\t\t\tif len(s) > 0 && (s[0] == '-' || s[0] == '+') {\n\t\t\t\tneg = s[0] == '-'\n\t\t\t\ts = s[1:]\n\t\t\t}\n\t\t\treturn !neg, len(s) > 0\n\t\t}\n\t\t`,\n\t\t`package p20\n\n\t\tfunc digits[bytes []byte | string](s bytes) bool {\n\t\t\tfor _, c := range []byte(s) {\n\t\t\t\tif c < '0' || '9' < c {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p21\n\n\t\ttype E interface{}\n\n\t\tfunc Foo[T E, PT interface{ *T }]() T {\n\t\t\tpt := PT(new(T))\n\t\t\tx := *pt\n\t\t\tprint(x)  /*@ types(T)*/\n\t\t\treturn x\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p22\n\n\t\tfunc f[M any, PM *M](p PM) {\n\t\t\tvar m M\n\t\t\t*p = m\n\t\t\tprint(m)  /*@ types(M)*/\n\t\t\tprint(p)  /*@ types(PM)*/\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p23\n\n\t\ttype A struct{int}\n\t\tfunc (*A) Marker() {}\n\n\t\ttype B struct{string}\n\t\tfunc (*B) Marker() {}\n\n\t\ttype C struct{float32}\n\t\tfunc (*C) Marker() {}\n\n\t\tfunc process[T interface {\n\t\t\t*A\n\t\t\t*B\n\t\t\t*C\n\t\t\tMarker()\n\t\t}](v T) {\n\t\t\tv.Marker()\n\t\t\ta := *(any(v).(*A)); print(a)  /*@ types(\"p23.A\")*/\n\t\t\tb := *(any(v).(*B)); print(b)  /*@ types(\"p23.B\")*/\n\t\t\tc := *(any(v).(*C)); print(c)  /*@ types(\"p23.C\")*/\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p24\n\n\t\tfunc a[T any](f func() [4]T) {\n\t\t\tx := len(f())\n\t\t\tprint(x) /*@ types(\"int\")*/\n\t\t}\n\n\t\tfunc b[T [4]any](f func() T) {\n\t\t\tx := len(f())\n\t\t\tprint(x) /*@ types(\"int\")*/\n\t\t}\n\n\t\tfunc c[T any](f func() *[4]T) {\n\t\t\tx := len(f())\n\t\t\tprint(x) /*@ types(\"int\")*/\n\t\t}\n\n\t\tfunc d[T *[4]any](f func() T) {\n\t\t\tx := len(f())\n\t\t\tprint(x) /*@ types(\"int\")*/\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage p25\n\n\t\tfunc a[T any]() {\n\t\t\tvar f func() [4]T\n\t\t\tfor i, v := range f() {\n\t\t\t\tprint(i, v) /*@ types(\"int\", \"T\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc b[T [4]any](f func() T) {\n\t\t\tfor i, v := range f() {\n\t\t\t\tprint(i, v) /*@ types(\"int\", \"any\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc c[T any](f func() *[4]T) {\n\t\t\tfor i, v := range f() {\n\t\t\t\tprint(i, v) /*@ types(\"int\", \"T\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc d[T *[4]any](f func() T) {\n\t\t\tfor i, v := range f() {\n\t\t\t\tprint(i, v) /*@ types(\"int\", \"any\")*/\n\t\t\t}\n\t\t}\n\t\t`,\n\t\t`\n\t\tpackage issue64324\n\n\t\ttype bar[T any] interface {\n\t\t\tBar(int) T\n\t\t}\n\t\ttype foo[T any] interface {\n\t\t\tbar[[]T]\n\t\t\t*T\n\t\t}\n\t\tfunc Foo[T any, F foo[T]](d int) {\n\t\t\tm := new(T)\n\t\t\tf := F(m)\n\t\t\tprint(f.Bar(d)) /*@ types(\"[]T\")*/\n\t\t}\n\t\t`, `\n\t\tpackage issue64324b\n\n\t\ttype bar[T any] interface {\n\t\t\tBar(int) T\n\t\t}\n\t\ttype baz[T any] interface {\n\t\t\tbar[*int]\n\t\t\t*int\n\t\t}\n\n\t\tfunc Baz[I baz[string]](d int) {\n\t\t\tm := new(int)\n\t\t\tf := I(m)\n\t\t\tprint(f.Bar(d)) /*@ types(\"*int\")*/\n\t\t}\n\t\t`,\n\t} {\n\t\tpkgname := parsePackageClause(t, content)\n\t\tt.Run(pkgname, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tssapkg, ppkg := buildPackage(t, content, ssa.SanityCheckFunctions)\n\t\t\tfset := ssapkg.Prog.Fset\n\t\t\tfile := ppkg.Syntax[0]\n\n\t\t\t// Collect all notes in f, i.e. comments starting with \"//@ types\".\n\t\t\tnotes, err := expect.ExtractGo(fset.File(file.Pos()), file)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"expect.ExtractGo: %v\", err)\n\t\t\t}\n\n\t\t\t// Collect calls to the builtin print function.\n\t\t\tfns := make(map[*ssa.Function]bool)\n\t\t\tfor _, mem := range ssapkg.Members {\n\t\t\t\tif fn, ok := mem.(*ssa.Function); ok {\n\t\t\t\t\tfns[fn] = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tprobes := callsTo(fns, \"print\")\n\t\t\texpectations := matchNotes(fset, notes, probes)\n\n\t\t\tfor call := range probes {\n\t\t\t\tif expectations[call] == nil {\n\t\t\t\t\tt.Errorf(\"Unmatched call: %v\", call)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check each expectation.\n\t\t\tfor call, note := range expectations {\n\t\t\t\tvar args []string\n\t\t\t\tfor _, a := range call.Args {\n\t\t\t\t\targs = append(args, a.Type().String())\n\t\t\t\t}\n\t\t\t\tif got, want := fmt.Sprint(args), fmt.Sprint(note.Args); got != want {\n\t\t\t\t\tt.Errorf(\"Arguments to print() were expected to be %q. got %q\", want, got)\n\t\t\t\t\tlogFunction(t, probes[call])\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// callsTo finds all calls to an SSA value named fname,\n// and returns a map from each call site to its enclosing function.\nfunc callsTo(fns map[*ssa.Function]bool, fname string) map[*ssa.CallCommon]*ssa.Function {\n\tcallsites := make(map[*ssa.CallCommon]*ssa.Function)\n\tfor fn := range fns {\n\t\tfor _, bb := range fn.Blocks {\n\t\t\tfor _, i := range bb.Instrs {\n\t\t\t\tif i, ok := i.(ssa.CallInstruction); ok {\n\t\t\t\t\tcall := i.Common()\n\t\t\t\t\tif call.Value.Name() == fname {\n\t\t\t\t\t\tcallsites[call] = fn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn callsites\n}\n\n// matchNotes returns a mapping from call sites (found by callsTo)\n// to the first \"//@ note\" comment on the same line.\nfunc matchNotes(fset *token.FileSet, notes []*expect.Note, calls map[*ssa.CallCommon]*ssa.Function) map[*ssa.CallCommon]*expect.Note {\n\t// Matches each probe with a note that has the same line.\n\tsameLine := func(x, y token.Pos) bool {\n\t\txp := fset.Position(x)\n\t\typ := fset.Position(y)\n\t\treturn xp.Filename == yp.Filename && xp.Line == yp.Line\n\t}\n\texpectations := make(map[*ssa.CallCommon]*expect.Note)\n\tfor call := range calls {\n\t\tfor _, note := range notes {\n\t\t\tif sameLine(call.Pos(), note.Pos) {\n\t\t\t\texpectations[call] = note\n\t\t\t\tbreak // first match is good enough.\n\t\t\t}\n\t\t}\n\t}\n\treturn expectations\n}\n\n// TestInstructionString tests serializing instructions via Instruction.String().\nfunc TestInstructionString(t *testing.T) {\n\t// Tests (ssa.Instruction).String(). Instructions are from a single go file.\n\t// The Instructions tested are those that match a comment of the form:\n\t//\n\t//\t//@ instrs(f, kind, strs...)\n\t//\n\t// where f is the name of the function, kind is the type of the instructions matched\n\t// within the function, and tests that the String() value for all of the instructions\n\t// matched of String() is strs (in some order).\n\t// See x/tools/go/expect for details on the syntax.\n\n\tconst contents = `\n\tpackage p\n\n\t//@ instrs(\"f0\", \"*ssa.TypeAssert\")\n\t//@ instrs(\"f0\", \"*ssa.Call\", \"print(nil:interface{}, 0:int)\")\n\tfunc f0(x int) { // non-generic smoke test.\n\t\tvar i interface{}\n\t\tprint(i, 0)\n\t}\n\n\t//@ instrs(\"f1\", \"*ssa.Alloc\", \"local T (u)\")\n\t//@ instrs(\"f1\", \"*ssa.FieldAddr\", \"&t0.x [#0]\")\n\tfunc f1[T ~struct{ x string }]() T {\n\t\tu := T{\"lorem\"}\n\t\treturn u\n\t}\n\n\t//@ instrs(\"f1b\", \"*ssa.Alloc\", \"new T (complit)\")\n\t//@ instrs(\"f1b\", \"*ssa.FieldAddr\", \"&t0.x [#0]\")\n\tfunc f1b[T ~struct{ x string }]() *T {\n\t\tu := &T{\"lorem\"}\n\t\treturn u\n\t}\n\n\t//@ instrs(\"f2\", \"*ssa.TypeAssert\", \"typeassert t0.(interface{})\")\n\t//@ instrs(\"f2\", \"*ssa.Call\", \"invoke x.foo()\")\n\tfunc f2[T interface{ foo() string }](x T) {\n\t\t_ = x.foo\n\t\t_ = x.foo()\n\t}\n\n\t//@ instrs(\"f3\", \"*ssa.TypeAssert\", \"typeassert t0.(interface{})\")\n\t//@ instrs(\"f3\", \"*ssa.Call\", \"invoke x.foo()\")\n\tfunc f3[T interface{ foo() string; comparable }](x T) {\n\t\t_ = x.foo\n\t\t_ = x.foo()\n\t}\n\n\t//@ instrs(\"f4\", \"*ssa.BinOp\", \"t1 + 1:int\", \"t2 < 4:int\")\n\t//@ instrs(\"f4\", \"*ssa.Call\", \"f()\", \"print(t2, t4)\")\n\tfunc f4[T [4]string](f func() T) {\n\t\tfor i, v := range f() {\n\t\t\tprint(i, v)\n\t\t}\n\t}\n\n\t//@ instrs(\"f5\", \"*ssa.Call\", \"nil:func()()\")\n\tfunc f5() {\n\t\tvar f func()\n\t\tf()\n\t}\n\n\ttype S struct{ f int }\n\n\t//@ instrs(\"f6\", \"*ssa.Alloc\", \"new [1]P (slicelit)\", \"new S (complit)\")\n\t//@ instrs(\"f6\", \"*ssa.IndexAddr\", \"&t0[0:int]\")\n\t//@ instrs(\"f6\", \"*ssa.FieldAddr\", \"&t2.f [#0]\")\n\tfunc f6[P *S]() []P { return []P{{f: 1}} }\n\n\t//@ instrs(\"f7\", \"*ssa.Alloc\", \"local S (complit)\")\n\t//@ instrs(\"f7\", \"*ssa.FieldAddr\", \"&t0.f [#0]\")\n\tfunc f7[T any, S struct{f T}](x T) S { return S{f: x} }\n\n\t//@ instrs(\"f8\", \"*ssa.Alloc\", \"new [1]P (slicelit)\", \"new struct{f T} (complit)\")\n\t//@ instrs(\"f8\", \"*ssa.IndexAddr\", \"&t0[0:int]\")\n\t//@ instrs(\"f8\", \"*ssa.FieldAddr\", \"&t2.f [#0]\")\n\tfunc f8[T any, P *struct{f T}](x T) []P { return []P{{f: x}} }\n\n\t//@ instrs(\"f9\", \"*ssa.Alloc\", \"new [1]PS (slicelit)\", \"new S (complit)\")\n\t//@ instrs(\"f9\", \"*ssa.IndexAddr\", \"&t0[0:int]\")\n\t//@ instrs(\"f9\", \"*ssa.FieldAddr\", \"&t2.f [#0]\")\n\tfunc f9[T any, S struct{f T}, PS *S](x T) {\n\t\t_ = []PS{{f: x}}\n\t}\n\n\t//@ instrs(\"f10\", \"*ssa.FieldAddr\", \"&t0.x [#0]\")\n\t//@ instrs(\"f10\", \"*ssa.Store\", \"*t0 = *new(T):T\", \"*t1 = 4:int\")\n\tfunc f10[T ~struct{ x, y int }]() T {\n\t\tvar u T\n\t\tu = T{x: 4}\n\t\treturn u\n\t}\n\n\t//@ instrs(\"f11\", \"*ssa.FieldAddr\", \"&t1.y [#1]\")\n\t//@ instrs(\"f11\", \"*ssa.Store\", \"*t1 = *new(T):T\", \"*t2 = 5:int\")\n\tfunc f11[T ~struct{ x, y int }, PT *T]() PT {\n\t\tvar u PT = new(T)\n\t\t*u = T{y: 5}\n\t\treturn u\n\t}\n\n\t//@ instrs(\"f12\", \"*ssa.Alloc\", \"new struct{f T} (complit)\")\n\t//@ instrs(\"f12\", \"*ssa.MakeMap\", \"make map[P]bool 1:int\")\n\tfunc f12[T any, P *struct{f T}](x T) map[P]bool { return map[P]bool{{}: true} }\n\n\t//@ instrs(\"f13\", \"*ssa.IndexAddr\", \"&v[0:int]\")\n\t//@ instrs(\"f13\", \"*ssa.Store\", \"*t0 = 7:int\", \"*v = *new(A):A\")\n\tfunc f13[A [3]int, PA *A](v PA) {\n\t\t*v = A{7}\n\t}\n\n\t//@ instrs(\"f14\", \"*ssa.Call\", \"invoke t1.Set(0:int)\")\n\tfunc f14[T any, PT interface {\n\t\tSet(int)\n\t\t*T\n\t}]() {\n\t\tvar t T\n\t\tp := PT(&t)\n\t\tp.Set(0)\n\t}\n\n\t//@ instrs(\"f15\", \"*ssa.MakeClosure\", \"make closure (interface{Set(int); *T}).Set$bound [t1]\")\n\tfunc f15[T any, PT interface {\n\t\tSet(int)\n\t\t*T\n\t}]() func(int) {\n\t\tvar t T\n\t\tp := PT(&t)\n\t\treturn p.Set\n\t}\n\t`\n\n\t// Parse\n\tconf := loader.Config{ParserMode: parser.ParseComments}\n\tconst fname = \"p.go\"\n\tf, err := conf.ParseFile(fname, contents)\n\tif err != nil {\n\t\tt.Fatalf(\"parse: %v\", err)\n\t}\n\tconf.CreateFromFiles(\"p\", f)\n\n\t// Load\n\tlprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatalf(\"Load: %v\", err)\n\t}\n\n\t// Create and build SSA\n\tprog := ssa.NewProgram(lprog.Fset, ssa.SanityCheckFunctions)\n\tfor _, info := range lprog.AllPackages {\n\t\tif info.TransitivelyErrorFree {\n\t\t\tprog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable)\n\t\t}\n\t}\n\tp := prog.Package(lprog.Package(\"p\").Pkg)\n\tp.Build()\n\n\t// Collect all notes in f, i.e. comments starting with \"//@ instr\".\n\tnotes, err := expect.ExtractGo(prog.Fset.File(f.Pos()), f)\n\tif err != nil {\n\t\tt.Errorf(\"expect.ExtractGo: %v\", err)\n\t}\n\n\t// Expectation is a {function, type string} -> {want, matches}\n\t// where matches is all Instructions.String() that match the key.\n\t// Each expectation is that some permutation of matches is wants.\n\ttype expKey struct {\n\t\tfunction string\n\t\tkind     string\n\t}\n\ttype expValue struct {\n\t\twants   []string\n\t\tmatches []string\n\t}\n\texpectations := make(map[expKey]*expValue)\n\tfor _, note := range notes {\n\t\tif note.Name == \"instrs\" {\n\t\t\tif len(note.Args) < 2 {\n\t\t\t\tt.Error(\"Had @instrs annotation without at least 2 arguments\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfn, kind := fmt.Sprint(note.Args[0]), fmt.Sprint(note.Args[1])\n\t\t\tvar wants []string\n\t\t\tfor _, arg := range note.Args[2:] {\n\t\t\t\twants = append(wants, fmt.Sprint(arg))\n\t\t\t}\n\t\t\texpectations[expKey{fn, kind}] = &expValue{wants, nil}\n\t\t}\n\t}\n\n\t// Collect all Instructions that match the expectations.\n\tfor _, mem := range p.Members {\n\t\tif fn, ok := mem.(*ssa.Function); ok {\n\t\t\tfor _, bb := range fn.Blocks {\n\t\t\t\tfor _, i := range bb.Instrs {\n\t\t\t\t\tkind := fmt.Sprintf(\"%T\", i)\n\t\t\t\t\tif e := expectations[expKey{fn.Name(), kind}]; e != nil {\n\t\t\t\t\t\te.matches = append(e.matches, i.String())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check each expectation.\n\tfor key, value := range expectations {\n\t\tfn, ok := p.Members[key.function].(*ssa.Function)\n\t\tif !ok {\n\t\t\tt.Errorf(\"Expectation on %s does not match a member in %s\", key.function, p.Pkg.Name())\n\t\t}\n\t\tgot, want := value.matches, value.wants\n\t\tsort.Strings(got)\n\t\tsort.Strings(want)\n\t\tif !reflect.DeepEqual(want, got) {\n\t\t\tt.Errorf(\"Within %s wanted instructions of kind %s: %q. got %q\", key.function, key.kind, want, got)\n\t\t\tlogFunction(t, fn)\n\t\t}\n\t}\n}\n\nfunc logFunction(t testing.TB, fn *ssa.Function) {\n\t// TODO: Consider adding a ssa.Function.GoString() so this can be logged to t via '%#v'.\n\tvar buf bytes.Buffer\n\tssa.WriteFunction(&buf, fn)\n\tt.Log(buf.String())\n}\n"
  },
  {
    "path": "go/ssa/builder_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc isEmpty(f *ssa.Function) bool { return f.Blocks == nil }\n\n// Tests that programs partially loaded from gc object files contain\n// functions with no code for the external portions, but are otherwise ok.\nfunc TestBuildPackage(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for importer.Default()\n\n\tinput := `\npackage main\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"testing\"\n)\n\nfunc main() {\n        var t testing.T\n\t    t.Parallel()    // static call to external declared method\n        t.Fail()        // static call to promoted external declared method\n        testing.Short() // static call to external package-level function\n\n        var w io.Writer = new(bytes.Buffer)\n        w.Write(nil)    // interface invoke of external declared method\n}\n`\n\n\t// Parse the file.\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"input.go\", input, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\n\t// Build an SSA program from the parsed file.\n\t// Load its dependencies from gc binary export data.\n\tmode := ssa.SanityCheckFunctions\n\tmainPkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset,\n\t\ttypes.NewPackage(\"main\", \"\"), []*ast.File{f}, mode)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\n\t// The main package, its direct and indirect dependencies are loaded.\n\tdeps := []string{\n\t\t// directly imported dependencies:\n\t\t\"bytes\", \"io\", \"testing\",\n\t\t// indirect dependencies mentioned by\n\t\t// the direct imports' export data\n\t\t\"sync\", \"unicode\", \"time\",\n\t}\n\n\tprog := mainPkg.Prog\n\tall := prog.AllPackages()\n\tif len(all) <= len(deps) {\n\t\tt.Errorf(\"unexpected set of loaded packages: %q\", all)\n\t}\n\tfor _, path := range deps {\n\t\tpkg := prog.ImportedPackage(path)\n\t\tif pkg == nil {\n\t\t\tt.Errorf(\"package not loaded: %q\", path)\n\t\t\tcontinue\n\t\t}\n\n\t\t// External packages should have no function bodies (except for wrappers).\n\t\tisExt := pkg != mainPkg\n\n\t\t// init()\n\t\tif isExt && !isEmpty(pkg.Func(\"init\")) {\n\t\t\tt.Errorf(\"external package %s has non-empty init\", pkg)\n\t\t} else if !isExt && isEmpty(pkg.Func(\"init\")) {\n\t\t\tt.Errorf(\"main package %s has empty init\", pkg)\n\t\t}\n\n\t\tfor _, mem := range pkg.Members {\n\t\t\tswitch mem := mem.(type) {\n\t\t\tcase *ssa.Function:\n\t\t\t\t// Functions at package level.\n\t\t\t\tif isExt && !isEmpty(mem) {\n\t\t\t\t\tt.Errorf(\"external function %s is non-empty\", mem)\n\t\t\t\t} else if !isExt && isEmpty(mem) {\n\t\t\t\t\tt.Errorf(\"function %s is empty\", mem)\n\t\t\t\t}\n\n\t\t\tcase *ssa.Type:\n\t\t\t\t// Methods of named types T.\n\t\t\t\t// (In this test, all exported methods belong to *T not T.)\n\t\t\t\tif !isExt {\n\t\t\t\t\tt.Fatalf(\"unexpected name type in main package: %s\", mem)\n\t\t\t\t}\n\t\t\t\tmset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))\n\t\t\t\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\t\t\t\tm := prog.MethodValue(mset.At(i))\n\t\t\t\t\t// For external types, only synthetic wrappers have code.\n\t\t\t\t\texpExt := !strings.Contains(m.Synthetic, \"wrapper\")\n\t\t\t\t\tif expExt && !isEmpty(m) {\n\t\t\t\t\t\tt.Errorf(\"external method %s is non-empty: %s\",\n\t\t\t\t\t\t\tm, m.Synthetic)\n\t\t\t\t\t} else if !expExt && isEmpty(m) {\n\t\t\t\t\t\tt.Errorf(\"method function %s is empty: %s\",\n\t\t\t\t\t\t\tm, m.Synthetic)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texpectedCallee := []string{\n\t\t\"(*testing.T).Parallel\",\n\t\t\"(*testing.common).Fail\",\n\t\t\"testing.Short\",\n\t\t\"N/A\",\n\t}\n\tcallNum := 0\n\tfor _, b := range mainPkg.Func(\"main\").Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\tswitch instr := instr.(type) {\n\t\t\tcase ssa.CallInstruction:\n\t\t\t\tcall := instr.Common()\n\t\t\t\tif want := expectedCallee[callNum]; want != \"N/A\" {\n\t\t\t\t\tgot := call.StaticCallee().String()\n\t\t\t\t\tif want != got {\n\t\t\t\t\t\tt.Errorf(\"call #%d from main.main: got callee %s, want %s\",\n\t\t\t\t\t\t\tcallNum, got, want)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcallNum++\n\t\t\t}\n\t\t}\n\t}\n\tif callNum != 4 {\n\t\tt.Errorf(\"in main.main: got %d calls, want %d\", callNum, 4)\n\t}\n}\n\n// Tests that methods from indirect dependencies not subject to\n// CreatePackage are created as needed.\nfunc TestNoIndirectCreatePackage(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for go/packages\n\n\tfs := openTxtar(t, filepath.Join(analysistest.TestData(), \"indirect.txtar\"))\n\tpkgs := loadPackages(t, fs, \"testdata/a\")\n\ta := pkgs[0]\n\n\t// Create a from syntax, its direct deps b from types, but not indirect deps c.\n\tprog := ssa.NewProgram(a.Fset, ssa.SanityCheckFunctions|ssa.PrintFunctions)\n\taSSA := prog.CreatePackage(a.Types, a.Syntax, a.TypesInfo, false)\n\tfor _, p := range a.Types.Imports() {\n\t\tprog.CreatePackage(p, nil, nil, true)\n\t}\n\n\t// Build SSA for package a.\n\taSSA.Build()\n\n\t// Find the function in the sole call in the sole block of function a.A.\n\tvar got string\n\tfor _, instr := range aSSA.Members[\"A\"].(*ssa.Function).Blocks[0].Instrs {\n\t\tif call, ok := instr.(*ssa.Call); ok {\n\t\t\tf := call.Call.Value.(*ssa.Function)\n\t\t\tgot = fmt.Sprintf(\"%v # %s\", f, f.Synthetic)\n\t\t\tbreak\n\t\t}\n\t}\n\twant := \"(testdata/c.C).F # from type information (on demand)\"\n\tif got != want {\n\t\tt.Errorf(\"for sole call in a.A, got: <<%s>>, want <<%s>>\", got, want)\n\t}\n}\n\n// TestRuntimeTypes tests that (*Program).RuntimeTypes() includes all necessary types.\nfunc TestRuntimeTypes(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for importer.Default()\n\n\t// TODO(adonovan): these test cases don't really make logical\n\t// sense any more. Rethink.\n\n\ttests := []struct {\n\t\tinput string\n\t\twant  []string\n\t}{\n\t\t// A package-level type is needed.\n\t\t{`package A; type T struct{}; func (T) f() {}; var x any = T{}`,\n\t\t\t[]string{\"*p.T\", \"p.T\"},\n\t\t},\n\t\t// An unexported package-level type is not needed.\n\t\t{`package B; type t struct{}; func (t) f() {}`,\n\t\t\tnil,\n\t\t},\n\t\t// Subcomponents of type of exported package-level var are needed.\n\t\t{`package C; import \"bytes\"; var V struct {*bytes.Buffer}; var x any = &V`,\n\t\t\t[]string{\"*bytes.Buffer\", \"*struct{*bytes.Buffer}\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Subcomponents of type of unexported package-level var are not needed.\n\t\t{`package D; import \"bytes\"; var v struct {*bytes.Buffer}; var x any = v`,\n\t\t\t[]string{\"*bytes.Buffer\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Subcomponents of type of exported package-level function are needed.\n\t\t{`package E; import \"bytes\"; func F(struct {*bytes.Buffer}) {}; var v any = F`,\n\t\t\t[]string{\"*bytes.Buffer\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Subcomponents of type of unexported package-level function are not needed.\n\t\t{`package F; import \"bytes\"; func f(struct {*bytes.Buffer}) {}; var v any = f`,\n\t\t\t[]string{\"*bytes.Buffer\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Subcomponents of type of exported method of uninstantiated unexported type are not needed.\n\t\t{`package G; import \"bytes\"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v x`,\n\t\t\tnil,\n\t\t},\n\t\t// ...unless used by MakeInterface.\n\t\t{`package G2; import \"bytes\"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v interface{} = x{}`,\n\t\t\t[]string{\"*bytes.Buffer\", \"*p.x\", \"p.x\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Subcomponents of type of unexported method are not needed.\n\t\t{`package I; import \"bytes\"; type X struct{}; func (X) G(struct {*bytes.Buffer}) {}; var x any = X{}`,\n\t\t\t[]string{\"*bytes.Buffer\", \"*p.X\", \"p.X\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// Local types aren't needed.\n\t\t{`package J; import \"bytes\"; func f() { type T struct {*bytes.Buffer}; var t T; _ = t }`,\n\t\t\tnil,\n\t\t},\n\t\t// ...unless used by MakeInterface.\n\t\t{`package K; import \"bytes\"; func f() { type T struct {*bytes.Buffer}; _ = interface{}(T{}) }`,\n\t\t\t[]string{\"*bytes.Buffer\", \"*p.T\", \"p.T\"},\n\t\t},\n\t\t// Types used as operand of MakeInterface are needed.\n\t\t{`package L; import \"bytes\"; func f() { _ = interface{}(struct{*bytes.Buffer}{}) }`,\n\t\t\t[]string{\"*bytes.Buffer\", \"struct{*bytes.Buffer}\"},\n\t\t},\n\t\t// MakeInterface is optimized away when storing to a blank.\n\t\t{`package M; import \"bytes\"; var _ interface{} = struct{*bytes.Buffer}{}`,\n\t\t\tnil,\n\t\t},\n\t\t// MakeInterface does not create runtime type for parameterized types.\n\t\t{`package N; var g interface{}; func f[S any]() { var v []S; g = v }; `,\n\t\t\tnil,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\t// Parse the file.\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"input.go\", test.input, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"test %q: %s\", test.input[:15], err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Create a single-file main package.\n\t\t// Load dependencies from gc binary export data.\n\t\tmode := ssa.SanityCheckFunctions\n\t\tssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset,\n\t\t\ttypes.NewPackage(\"p\", \"\"), []*ast.File{f}, mode)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"test %q: %s\", test.input[:15], err)\n\t\t\tcontinue\n\t\t}\n\n\t\tvar typstrs []string\n\t\tfor _, T := range ssapkg.Prog.RuntimeTypes() {\n\t\t\tif types.IsInterface(T) || types.NewMethodSet(T).Len() == 0 {\n\t\t\t\tcontinue // skip interfaces and types without methods\n\t\t\t}\n\t\t\ttypstrs = append(typstrs, T.String())\n\t\t}\n\t\tsort.Strings(typstrs)\n\n\t\tif !reflect.DeepEqual(typstrs, test.want) {\n\t\t\tt.Errorf(\"test 'package %s': got %q, want %q\",\n\t\t\t\tf.Name.Name, typstrs, test.want)\n\t\t}\n\t}\n}\n\n// TestInit tests that synthesized init functions are correctly formed.\n// Bare init functions omit calls to dependent init functions and the use of\n// an init guard. They are useful in cases where the client uses a different\n// calling convention for init functions, or cases where it is easier for a\n// client to analyze bare init functions. Both of these aspects are used by\n// the llgo compiler for simpler integration with gccgo's runtime library,\n// and to simplify the analysis whereby it deduces which stores to globals\n// can be lowered to global initializers.\nfunc TestInit(t *testing.T) {\n\ttests := []struct {\n\t\tmode        ssa.BuilderMode\n\t\tinput, want string\n\t}{\n\t\t{0, `package A; import _ \"errors\"; var i int = 42`,\n\t\t\t`# Name: A.init\n# Package: A\n# Synthetic: package initializer\nfunc init():\n0:                                                                entry P:0 S:2\n\tt0 = *init$guard                                                   bool\n\tif t0 goto 2 else 1\n1:                                                    init.start P:1 S:1 idom:0\n\t*init$guard = true:bool\n\tt1 = errors.init()                                                   ()\n\t*i = 42:int\n\tjump 2\n2:                                                     init.done P:2 S:0 idom:0\n\treturn\n\n`},\n\t\t{ssa.BareInits, `package B; import _ \"errors\"; var i int = 42`,\n\t\t\t`# Name: B.init\n# Package: B\n# Synthetic: package initializer\nfunc init():\n0:                                                                entry P:0 S:0\n\t*i = 42:int\n\treturn\n\n`},\n\t}\n\tfor _, test := range tests {\n\t\t// Create a single-file main package.\n\t\tmainPkg, _ := buildPackage(t, test.input, test.mode)\n\t\tname := mainPkg.Pkg.Name()\n\t\tinitFunc := mainPkg.Func(\"init\")\n\t\tif initFunc == nil {\n\t\t\tt.Errorf(\"test 'package %s': no init function\", name)\n\t\t\tcontinue\n\t\t}\n\n\t\tvar initbuf bytes.Buffer\n\t\t_, err := initFunc.WriteTo(&initbuf)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"test 'package %s': WriteTo: %s\", name, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif initbuf.String() != test.want {\n\t\t\tt.Errorf(\"test 'package %s': got %s, want %s\", name, initbuf.String(), test.want)\n\t\t}\n\t}\n}\n\n// TestSyntheticFuncs checks that the expected synthetic functions are\n// created, reachable, and not duplicated.\nfunc TestSyntheticFuncs(t *testing.T) {\n\tconst input = `package P\ntype T int\nfunc (T) f() int\nfunc (*T) g() int\nvar (\n\t// thunks\n\ta = T.f\n\tb = T.f\n\tc = (struct{T}).f\n\td = (struct{T}).f\n\te = (*T).g\n\tf = (*T).g\n\tg = (struct{*T}).g\n\th = (struct{*T}).g\n\n\t// bounds\n\ti = T(0).f\n\tj = T(0).f\n\tk = new(T).g\n\tl = new(T).g\n\n\t// wrappers\n\tm interface{} = struct{T}{}\n\tn interface{} = struct{T}{}\n\to interface{} = struct{*T}{}\n\tp interface{} = struct{*T}{}\n\tq interface{} = new(struct{T})\n\tr interface{} = new(struct{T})\n\ts interface{} = new(struct{*T})\n\tt interface{} = new(struct{*T})\n)\n`\n\tpkg, _ := buildPackage(t, input, ssa.BuilderMode(0))\n\n\t// Enumerate reachable synthetic functions\n\twant := map[string]string{\n\t\t\"(*P.T).g$bound\": \"bound method wrapper for func (*P.T).g() int\",\n\t\t\"(P.T).f$bound\":  \"bound method wrapper for func (P.T).f() int\",\n\n\t\t\"(*P.T).g$thunk\":         \"thunk for func (*P.T).g() int\",\n\t\t\"(P.T).f$thunk\":          \"thunk for func (P.T).f() int\",\n\t\t\"(struct{*P.T}).g$thunk\": \"thunk for func (*P.T).g() int\",\n\t\t\"(struct{P.T}).f$thunk\":  \"thunk for func (P.T).f() int\",\n\n\t\t\"(*P.T).f\":          \"wrapper for func (P.T).f() int\",\n\t\t\"(*struct{*P.T}).f\": \"wrapper for func (P.T).f() int\",\n\t\t\"(*struct{*P.T}).g\": \"wrapper for func (*P.T).g() int\",\n\t\t\"(*struct{P.T}).f\":  \"wrapper for func (P.T).f() int\",\n\t\t\"(*struct{P.T}).g\":  \"wrapper for func (*P.T).g() int\",\n\t\t\"(struct{*P.T}).f\":  \"wrapper for func (P.T).f() int\",\n\t\t\"(struct{*P.T}).g\":  \"wrapper for func (*P.T).g() int\",\n\t\t\"(struct{P.T}).f\":   \"wrapper for func (P.T).f() int\",\n\n\t\t\"P.init\": \"package initializer\",\n\t}\n\tvar seen []string // may contain dups\n\tfor fn := range ssautil.AllFunctions(pkg.Prog) {\n\t\tif fn.Synthetic == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tname := fn.String()\n\t\twantDescr, ok := want[name]\n\t\tif !ok {\n\t\t\tt.Errorf(\"got unexpected/duplicate func: %q: %q\", name, fn.Synthetic)\n\t\t\tcontinue\n\t\t}\n\t\tseen = append(seen, name)\n\n\t\tif wantDescr != fn.Synthetic {\n\t\t\tt.Errorf(\"(%s).Synthetic = %q, want %q\", name, fn.Synthetic, wantDescr)\n\t\t}\n\t}\n\n\tfor _, name := range seen {\n\t\tdelete(want, name)\n\t}\n\tfor fn, descr := range want {\n\t\tt.Errorf(\"want func: %q: %q\", fn, descr)\n\t}\n}\n\n// TestPhiElimination ensures that dead phis, including those that\n// participate in a cycle, are properly eliminated.\nfunc TestPhiElimination(t *testing.T) {\n\tconst input = `\npackage p\n\nfunc f() error\n\nfunc g(slice []int) {\n\tfor {\n\t\tfor range slice {\n\t\t\t// e should not be lifted to a dead φ-node.\n\t\t\te := f()\n\t\t\th(e)\n\t\t}\n\t}\n}\n\nfunc h(error)\n`\n\t// The SSA code for this function should look something like this:\n\t// 0:\n\t//         jump 1\n\t// 1:\n\t//         t0 = len(slice)\n\t//         jump 2\n\t// 2:\n\t//         t1 = phi [1: -1:int, 3: t2]\n\t//         t2 = t1 + 1:int\n\t//         t3 = t2 < t0\n\t//         if t3 goto 3 else 1\n\t// 3:\n\t//         t4 = f()\n\t//         t5 = h(t4)\n\t//         jump 2\n\t//\n\t// But earlier versions of the SSA construction algorithm would\n\t// additionally generate this cycle of dead phis:\n\t//\n\t// 1:\n\t//         t7 = phi [0: nil:error, 2: t8] #e\n\t//         ...\n\t// 2:\n\t//         t8 = phi [1: t7, 3: t4] #e\n\t//         ...\n\n\tp, _ := buildPackage(t, input, ssa.BuilderMode(0))\n\tg := p.Func(\"g\")\n\n\tphis := 0\n\tfor _, b := range g.Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\tif _, ok := instr.(*ssa.Phi); ok {\n\t\t\t\tphis++\n\t\t\t}\n\t\t}\n\t}\n\tif phis != 1 {\n\t\tg.WriteTo(os.Stderr)\n\t\tt.Errorf(\"expected a single Phi (for the range index), got %d\", phis)\n\t}\n}\n\n// TestGenericDecls ensures that *unused* generic types, methods and functions\n// signatures can be built.\n//\n// TODO(taking): Add calls from non-generic functions to instantiations of generic functions.\n// TODO(taking): Add globals with types that are instantiations of generic functions.\nfunc TestGenericDecls(t *testing.T) {\n\tconst input = `\npackage p\n\nimport \"unsafe\"\n\ntype Pointer[T any] struct {\n\tv unsafe.Pointer\n}\n\nfunc (x *Pointer[T]) Load() *T {\n\treturn (*T)(LoadPointer(&x.v))\n}\n\nfunc Load[T any](x *Pointer[T]) *T {\n\treturn x.Load()\n}\n\nfunc LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)\n`\n\t// The SSA members for this package should look something like this:\n\t//          func  LoadPointer func(addr *unsafe.Pointer) (val unsafe.Pointer)\n\t//      type  Pointer     struct{v unsafe.Pointer}\n\t//        method (*Pointer[T any]) Load() *T\n\t//      func  init        func()\n\t//      var   init$guard  bool\n\n\tp, _ := buildPackage(t, input, ssa.BuilderMode(0))\n\n\tif load := p.Func(\"Load\"); load.Signature.TypeParams().Len() != 1 {\n\t\tt.Errorf(\"expected a single type param T for Load got %q\", load.Signature)\n\t}\n\tif ptr := p.Type(\"Pointer\"); ptr.Type().(*types.Named).TypeParams().Len() != 1 {\n\t\tt.Errorf(\"expected a single type param T for Pointer got %q\", ptr.Type())\n\t}\n}\n\nfunc TestGenericWrappers(t *testing.T) {\n\tconst input = `\npackage p\n\ntype S[T any] struct {\n\tt *T\n}\n\nfunc (x S[T]) M() T {\n\treturn *(x.t)\n}\n\nvar thunk = S[int].M\n\nvar g S[int]\nvar bound = g.M\n\ntype R[T any] struct{ S[T] }\n\nvar indirect = R[int].M\n`\n\t// The relevant SSA members for this package should look something like this:\n\t// var   bound      func() int\n\t// var   thunk      func(S[int]) int\n\t// var   wrapper    func(R[int]) int\n\n\tfor _, mode := range []ssa.BuilderMode{ssa.BuilderMode(0), ssa.InstantiateGenerics} {\n\t\tp, _ := buildPackage(t, input, mode)\n\n\t\tfor _, entry := range []struct {\n\t\t\tname    string // name of the package variable\n\t\t\ttyp     string // type of the package variable\n\t\t\twrapper string // wrapper function to which the package variable is set\n\t\t\tcallee  string // callee within the wrapper function\n\t\t}{\n\t\t\t{\n\t\t\t\t\"bound\",\n\t\t\t\t\"*func() int\",\n\t\t\t\t\"(p.S[int]).M$bound\",\n\t\t\t\t\"(p.S[int]).M[int]\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"thunk\",\n\t\t\t\t\"*func(p.S[int]) int\",\n\t\t\t\t\"(p.S[int]).M$thunk\",\n\t\t\t\t\"(p.S[int]).M[int]\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"indirect\",\n\t\t\t\t\"*func(p.R[int]) int\",\n\t\t\t\t\"(p.R[int]).M$thunk\",\n\t\t\t\t\"(p.S[int]).M[int]\",\n\t\t\t},\n\t\t} {\n\t\t\tt.Run(entry.name, func(t *testing.T) {\n\t\t\t\tv := p.Var(entry.name)\n\t\t\t\tif v == nil {\n\t\t\t\t\tt.Fatalf(\"Did not find variable for %q in %s\", entry.name, p.String())\n\t\t\t\t}\n\t\t\t\tif v.Type().String() != entry.typ {\n\t\t\t\t\tt.Errorf(\"Expected type for variable %s: %q. got %q\", v, entry.typ, v.Type())\n\t\t\t\t}\n\n\t\t\t\t// Find the wrapper for v. This is stored exactly once in init.\n\t\t\t\tvar wrapper *ssa.Function\n\t\t\t\tfor _, bb := range p.Func(\"init\").Blocks {\n\t\t\t\t\tfor _, i := range bb.Instrs {\n\t\t\t\t\t\tif store, ok := i.(*ssa.Store); ok && v == store.Addr {\n\t\t\t\t\t\t\tswitch val := store.Val.(type) {\n\t\t\t\t\t\t\tcase *ssa.Function:\n\t\t\t\t\t\t\t\twrapper = val\n\t\t\t\t\t\t\tcase *ssa.MakeClosure:\n\t\t\t\t\t\t\t\twrapper = val.Fn.(*ssa.Function)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif wrapper == nil {\n\t\t\t\t\tt.Fatalf(\"failed to find wrapper function for %s\", entry.name)\n\t\t\t\t}\n\t\t\t\tif wrapper.String() != entry.wrapper {\n\t\t\t\t\tt.Errorf(\"Expected wrapper function %q. got %q\", wrapper, entry.wrapper)\n\t\t\t\t}\n\n\t\t\t\t// Find the callee within the wrapper. There should be exactly one call.\n\t\t\t\tvar callee *ssa.Function\n\t\t\t\tfor _, bb := range wrapper.Blocks {\n\t\t\t\t\tfor _, i := range bb.Instrs {\n\t\t\t\t\t\tif call, ok := i.(*ssa.Call); ok {\n\t\t\t\t\t\t\tcallee = call.Call.StaticCallee()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif callee == nil {\n\t\t\t\t\tt.Fatalf(\"failed to find callee within wrapper %s\", wrapper)\n\t\t\t\t}\n\t\t\t\tif callee.String() != entry.callee {\n\t\t\t\t\tt.Errorf(\"Expected callee in wrapper %q is %q. got %q\", v, entry.callee, callee)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n}\n\n// TestTypeparamTest builds SSA over compilable examples in $GOROOT/test/typeparam/*.go.\n\nfunc TestTypeparamTest(t *testing.T) {\n\ttestenv.NeedsGOROOTDir(t, \"test\")\n\n\t// Tests use a fake goroot to stub out standard libraries with declarations in\n\t// testdata/src. Decreases runtime from ~80s to ~1s.\n\n\tif runtime.GOARCH == \"wasm\" {\n\t\t// Consistent flakes on wasm (#64726, #69409, #69410).\n\t\t// Needs more investigation, but more likely a wasm issue\n\t\t// Disabling for now.\n\t\tt.Skip(\"Consistent flakes on wasm (e.g. https://go.dev/issues/64726)\")\n\t}\n\n\t// located GOROOT based on the relative path of errors in $GOROOT/src/errors\n\tstdPkgs, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedFiles,\n\t}, \"errors\")\n\tif err != nil {\n\t\tt.Fatalf(\"Failed to load errors package from std: %s\", err)\n\t}\n\tgoroot := filepath.Dir(filepath.Dir(filepath.Dir(stdPkgs[0].GoFiles[0])))\n\tdir := filepath.Join(goroot, \"test\", \"typeparam\")\n\tif _, err = os.Stat(dir); errors.Is(err, os.ErrNotExist) {\n\t\tt.Skipf(\"test/typeparam doesn't exist under GOROOT %s\", goroot)\n\t}\n\n\t// Collect all of the .go files in\n\tfsys := os.DirFS(dir)\n\tentries, err := fs.ReadDir(fsys, \".\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Each call to buildPackage calls package.Load, which invokes \"go list\",\n\t// and with over 300 subtests this can be very slow (minutes, or tens\n\t// on some platforms). So, we use an overlay to map each test file to a\n\t// distinct single-file package and load them all at once.\n\toverlay := map[string][]byte{\n\t\t\"go.mod\": goMod(\"example.com\", -1),\n\t}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() || !strings.HasSuffix(entry.Name(), \".go\") {\n\t\t\tcontinue // Consider standalone go files.\n\t\t}\n\t\tsrc, err := fs.ReadFile(fsys, entry.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// Only build test files that can be compiled, or compiled and run.\n\t\tif !bytes.HasPrefix(src, []byte(\"// run\")) && !bytes.HasPrefix(src, []byte(\"// compile\")) {\n\t\t\tt.Logf(\"%s: not detected as a run test\", entry.Name())\n\t\t\tcontinue\n\t\t}\n\n\t\tfilename := fmt.Sprintf(\"%s/main.go\", entry.Name())\n\t\toverlay[filename] = src\n\t}\n\n\t// load all packages inside the overlay so 'go list' will be triggered only once.\n\tpkgs := loadPackages(t, overlayFS(overlay), \"./...\")\n\tfor _, p := range pkgs {\n\t\toriginFilename := filepath.Base(filepath.Dir(p.GoFiles[0]))\n\t\tt.Run(originFilename, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tprog, _ := ssautil.Packages([]*packages.Package{p}, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)\n\t\t\tprog.Package(p.Types).Build()\n\t\t})\n\t}\n}\n\n// TestOrderOfOperations ensures order of operations are as intended.\nfunc TestOrderOfOperations(t *testing.T) {\n\t// Testing for the order of operations within an expression is done\n\t// by collecting the sequence of direct function calls within a *Function.\n\t// Callees are all external functions so they cannot be safely re-ordered by ssa.\n\tconst input = `\npackage p\n\nfunc a() int\nfunc b() int\nfunc c() int\n\nfunc slice(s []int) []int { return s[a():b()] }\nfunc sliceMax(s []int) []int { return s[a():b():c()] }\n\n`\n\n\tp, _ := buildPackage(t, input, ssa.BuilderMode(0))\n\n\tfor _, item := range []struct {\n\t\tfn   string\n\t\twant string // sequence of calls within the function.\n\t}{\n\t\t{\"sliceMax\", \"[a() b() c()]\"},\n\t\t{\"slice\", \"[a() b()]\"},\n\t} {\n\t\tfn := p.Func(item.fn)\n\t\twant := item.want\n\t\tt.Run(item.fn, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tvar calls []string\n\t\t\tfor _, b := range fn.Blocks {\n\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\tif call, ok := instr.(ssa.CallInstruction); ok {\n\t\t\t\t\t\tcalls = append(calls, call.String())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif got := fmt.Sprint(calls); got != want {\n\t\t\t\tfn.WriteTo(os.Stderr)\n\t\t\t\tt.Errorf(\"Expected sequence of function calls in %s was %s. got %s\", fn, want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestGenericFunctionSelector ensures generic functions from other packages can be selected.\nfunc TestGenericFunctionSelector(t *testing.T) {\n\tfsys := overlayFS(map[string][]byte{\n\t\t\"go.mod\":  goMod(\"example.com\", -1),\n\t\t\"main.go\": []byte(`package main; import \"example.com/a\"; func main() { a.F[int](); a.G[int,string](); a.H(0) }`),\n\t\t\"a/a.go\":  []byte(`package a; func F[T any](){}; func G[S, T any](){}; func H[T any](a T){} `),\n\t})\n\n\tfor _, mode := range []ssa.BuilderMode{\n\t\tssa.SanityCheckFunctions,\n\t\tssa.SanityCheckFunctions | ssa.InstantiateGenerics,\n\t} {\n\n\t\tpkgs := loadPackages(t, fsys, \"example.com\") // package main\n\t\tif len(pkgs) != 1 {\n\t\t\tt.Fatalf(\"Expected 1 root package but got %d\", len(pkgs))\n\t\t}\n\t\tprog, _ := ssautil.Packages(pkgs, mode)\n\t\tp := prog.Package(pkgs[0].Types)\n\t\tp.Build()\n\n\t\tif p.Pkg.Name() != \"main\" {\n\t\t\tt.Fatalf(\"Expected the second package is main but got %s\", p.Pkg.Name())\n\t\t}\n\t\tp.Build()\n\n\t\tvar callees []string // callees of the CallInstruction.String() in main().\n\t\tfor _, b := range p.Func(\"main\").Blocks {\n\t\t\tfor _, i := range b.Instrs {\n\t\t\t\tif call, ok := i.(ssa.CallInstruction); ok {\n\t\t\t\t\tif callee := call.Common().StaticCallee(); call != nil {\n\t\t\t\t\t\tcallees = append(callees, callee.String())\n\t\t\t\t\t} else {\n\t\t\t\t\t\tt.Errorf(\"CallInstruction without StaticCallee() %q\", call)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsort.Strings(callees) // ignore the order in the code.\n\n\t\twant := \"[example.com/a.F[int] example.com/a.G[int string] example.com/a.H[int]]\"\n\t\tif got := fmt.Sprint(callees); got != want {\n\t\t\tt.Errorf(\"Expected main() to contain calls %v. got %v\", want, got)\n\t\t}\n\t}\n}\n\nfunc TestIssue58491(t *testing.T) {\n\t// Test that a local type reaches type param in instantiation.\n\tsrc := `\n\t\tpackage p\n\n\t\tfunc foo[T any](blocking func() (T, error)) error {\n\t\t\ttype result struct {\n\t\t\t\tres T\n\t\t\t\terror // ensure the method set of result is non-empty\n\t\t\t}\n\n\t\t\tres := make(chan result, 1)\n\t\t\tgo func() {\n\t\t\t\tvar r result\n\t\t\t\tr.res, r.error = blocking()\n\t\t\t\tres <- r\n\t\t\t}()\n\t\t\tr := <-res\n\t\t\terr := r // require the rtype for result when instantiated\n\t\t\treturn err\n\t\t}\n\t\tvar Inst = foo[int]\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfiles := []*ast.File{f}\n\n\tpkg := types.NewPackage(\"p\", \"\")\n\tconf := &types.Config{}\n\tp, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)\n\tif err != nil {\n\t\tt.Fatalf(\"unexpected error: %v\", err)\n\t}\n\n\t// Find the local type result instantiated with int.\n\tvar found bool\n\tfor _, rt := range p.Prog.RuntimeTypes() {\n\t\tif n, ok := rt.(*types.Named); ok {\n\t\t\tif u, ok := n.Underlying().(*types.Struct); ok {\n\t\t\t\tfound = true\n\t\t\t\tif got, want := n.String(), \"p.result\"; got != want {\n\t\t\t\t\tt.Errorf(\"Expected the name %s got: %s\", want, got)\n\t\t\t\t}\n\t\t\t\tif got, want := u.String(), \"struct{res int; error}\"; got != want {\n\t\t\t\t\tt.Errorf(\"Expected the underlying type of %s to be %s. got %s\", n, want, got)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif !found {\n\t\tt.Error(\"Failed to find any Named to struct types\")\n\t}\n}\n\nfunc TestIssue58491Rec(t *testing.T) {\n\t// Roughly the same as TestIssue58491 but with a recursive type.\n\tsrc := `\n\t\tpackage p\n\n\t\tfunc foo[T any]() error {\n\t\t\ttype result struct {\n\t\t\t\tres T\n\t\t\t\tnext *result\n\t\t\t\terror // ensure the method set of result is non-empty\n\t\t\t}\n\n\t\t\tr := &result{}\n\t\t\terr := r // require the rtype for result when instantiated\n\t\t\treturn err\n\t\t}\n\t\tvar Inst = foo[int]\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfiles := []*ast.File{f}\n\n\tpkg := types.NewPackage(\"p\", \"\")\n\tconf := &types.Config{}\n\tp, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)\n\tif err != nil {\n\t\tt.Fatalf(\"unexpected error: %v\", err)\n\t}\n\n\t// Find the local type result instantiated with int.\n\tvar found bool\n\tfor _, rt := range p.Prog.RuntimeTypes() {\n\t\tif n, ok := types.Unalias(rt).(*types.Named); ok {\n\t\t\tif u, ok := n.Underlying().(*types.Struct); ok {\n\t\t\t\tfound = true\n\t\t\t\tif got, want := n.String(), \"p.result\"; got != want {\n\t\t\t\t\tt.Errorf(\"Expected the name %s got: %s\", want, got)\n\t\t\t\t}\n\t\t\t\tif got, want := u.String(), \"struct{res int; next *p.result; error}\"; got != want {\n\t\t\t\t\tt.Errorf(\"Expected the underlying type of %s to be %s. got %s\", n, want, got)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif !found {\n\t\tt.Error(\"Failed to find any Named to struct types\")\n\t}\n}\n\n// TestSyntax ensures that a function's Syntax is available.\nfunc TestSyntax(t *testing.T) {\n\tconst input = `package p\n\n\ttype P int\n\tfunc (x *P) g() *P { return x }\n\n\tfunc F[T ~int]() *T {\n\t\ttype S1 *T\n\t\ttype S2 *T\n\t\ttype S3 *T\n\t\tf1 := func() S1 {\n\t\t\tf2 := func() S2 {\n\t\t\t\treturn S2(nil)\n\t\t\t}\n\t\t\treturn S1(f2())\n\t\t}\n\t\tf3 := func() S3 {\n\t\t\treturn S3(f1())\n\t\t}\n\t\treturn (*T)(f3())\n\t}\n\tvar g = F[int]\n\tvar _ = F[P] // unreferenced => not instantiated\n\t`\n\n\tp, _ := buildPackage(t, input, ssa.InstantiateGenerics)\n\tprog := p.Prog\n\n\t// Collect syntax information for all of the functions.\n\tgot := make(map[string]string)\n\tfor fn := range ssautil.AllFunctions(prog) {\n\t\tif fn.Name() == \"init\" {\n\t\t\tcontinue\n\t\t}\n\t\tsyntax := fn.Syntax()\n\t\tif got[fn.Name()] != \"\" {\n\t\t\tt.Error(\"dup\")\n\t\t}\n\t\tgot[fn.Name()] = fmt.Sprintf(\"%T : %s @ %d\", syntax, fn.Signature, prog.Fset.Position(syntax.Pos()).Line)\n\t}\n\n\twant := map[string]string{\n\t\t\"g\":          \"*ast.FuncDecl : func() *p.P @ 4\",\n\t\t\"F\":          \"*ast.FuncDecl : func[T ~int]() *T @ 6\",\n\t\t\"F$1\":        \"*ast.FuncLit : func() p.S1 @ 10\",\n\t\t\"F$1$1\":      \"*ast.FuncLit : func() p.S2 @ 11\",\n\t\t\"F$2\":        \"*ast.FuncLit : func() p.S3 @ 16\",\n\t\t\"F[int]\":     \"*ast.FuncDecl : func() *int @ 6\",\n\t\t\"F[int]$1\":   \"*ast.FuncLit : func() p.S1 @ 10\",\n\t\t\"F[int]$1$1\": \"*ast.FuncLit : func() p.S2 @ 11\",\n\t\t\"F[int]$2\":   \"*ast.FuncLit : func() p.S3 @ 16\",\n\t\t// ...but no F[P] etc as they are unreferenced.\n\t\t// (NB: GlobalDebug mode would cause them to be referenced.)\n\t}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"Expected the functions with signature to be:\\n\\t%#v.\\n Got:\\n\\t%#v\", want, got)\n\t}\n}\n\nfunc TestGo117Builtins(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tsrc      string\n\t\timporter types.Importer\n\t}{\n\t\t{\"slice to array pointer\", \"package p; var s []byte; var _ = (*[4]byte)(s)\", nil},\n\t\t{\"unsafe slice\", `package p; import \"unsafe\"; var _ = unsafe.Add(nil, 0)`, importer.Default()},\n\t\t{\"unsafe add\", `package p; import \"unsafe\"; var _ = unsafe.Slice((*int)(nil), 0)`, importer.Default()},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, \"p.go\", tc.src, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t\tfiles := []*ast.File{f}\n\n\t\t\tpkg := types.NewPackage(\"p\", \"\")\n\t\t\tconf := &types.Config{Importer: tc.importer}\n\t\t\tif _, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions); err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestLabels just tests that anonymous labels are handled.\nfunc TestLabels(t *testing.T) {\n\ttests := []string{\n\t\t`package main\n\t\t  func main() { _:println(1) }`,\n\t\t`package main\n\t\t  func main() { _:println(1); _:println(2)}`,\n\t}\n\tfor _, test := range tests {\n\t\tbuildPackage(t, test, ssa.BuilderMode(0))\n\t}\n}\n\nfunc TestFixedBugs(t *testing.T) {\n\tfor _, name := range []string{\n\t\t\"issue66783a\",\n\t\t\"issue66783b\",\n\t\t\"issue73594\",\n\t} {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tbase := name + \".go\"\n\t\t\tpath := filepath.Join(analysistest.TestData(), \"fixedbugs\", base)\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, path, nil, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfiles := []*ast.File{f}\n\t\t\tpkg := types.NewPackage(name, name)\n\t\t\tmode := ssa.SanityCheckFunctions | ssa.InstantiateGenerics\n\t\t\t// mode |= ssa.PrintFunctions // debug mode\n\t\t\tif _, _, err := ssautil.BuildPackage(&types.Config{}, fset, pkg, files, mode); err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIssue67079(t *testing.T) {\n\t// This test reproduced a race in the SSA builder nearly 100% of the time.\n\n\t// Load the package.\n\tconst src = `package p; type T int; func (T) f() {}; var _ = (*T).f`\n\tspkg, ppkg := buildPackage(t, src, ssa.BuilderMode(0))\n\tprog := spkg.Prog\n\tvar g errgroup.Group\n\n\t// Access bodies of all functions.\n\tg.Go(func() error {\n\t\tfor fn := range ssautil.AllFunctions(prog) {\n\t\t\tfor _, b := range fn.Blocks {\n\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\tif call, ok := instr.(*ssa.Call); ok {\n\t\t\t\t\t\tcall.Common().StaticCallee() // access call.Value\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Force building of wrappers.\n\tg.Go(func() error {\n\t\tptrT := types.NewPointer(ppkg.Types.Scope().Lookup(\"T\").Type())\n\t\tptrTf := types.NewMethodSet(ptrT).At(0) // (*T).f symbol\n\t\tprog.MethodValue(ptrTf)\n\t\treturn nil\n\t})\n\n\tg.Wait() // ignore error\n}\n\nfunc TestGenericAliases(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\n\tif os.Getenv(\"GENERICALIASTEST_CHILD\") == \"1\" {\n\t\ttestGenericAliases(t)\n\t\treturn\n\t}\n\n\ttestenv.NeedsExec(t)\n\ttestenv.NeedsTool(t, \"go\")\n\n\tcmd := exec.Command(os.Args[0], \"-test.run=TestGenericAliases\")\n\tcmd.Env = append(os.Environ(), \"GENERICALIASTEST_CHILD=1\")\n\tif testenv.Go1Point() == 23 {\n\t\tcmd.Env = append(cmd.Env, \"GOEXPERIMENT=aliastypeparams\")\n\t}\n\tout, err := cmd.CombinedOutput()\n\tif len(out) > 0 {\n\t\tt.Logf(\"out=<<%s>>\", out)\n\t}\n\tvar exitcode int\n\tif err, ok := err.(*exec.ExitError); ok {\n\t\texitcode = err.ExitCode()\n\t}\n\tconst want = 0\n\tif exitcode != want {\n\t\tt.Errorf(\"exited %d, want %d\", exitcode, want)\n\t}\n}\n\nfunc testGenericAliases(t *testing.T) {\n\ttestenv.NeedsGoExperiment(t, \"aliastypeparams\")\n\n\tconst source = `\npackage p\n\ntype A = uint8\ntype B[T any] = [4]T\n\nvar F = f[string]\n\nfunc f[S any]() {\n\t// Two copies of f are made: p.f[S] and p.f[string]\n\n\tvar v A // application of A that is declared outside of f without no type arguments\n\tprint(\"p.f\", \"String\", \"p.A\", v)\n\tprint(\"p.f\", \"==\", v, uint8(0))\n\tprint(\"p.f[string]\", \"String\", \"p.A\", v)\n\tprint(\"p.f[string]\", \"==\", v, uint8(0))\n\n\n\tvar u B[S] // application of B that is declared outside declared outside of f with type arguments\n\tprint(\"p.f\", \"String\", \"p.B[S]\", u)\n\tprint(\"p.f\", \"==\", u, [4]S{})\n\tprint(\"p.f[string]\", \"String\", \"p.B[string]\", u)\n\tprint(\"p.f[string]\", \"==\", u, [4]string{})\n\n\ttype C[T any] = struct{ s S; ap *B[T]} // declaration within f with type params\n\tvar w C[int] // application of C with type arguments\n\tprint(\"p.f\", \"String\", \"p.C[int]\", w)\n\tprint(\"p.f\", \"==\", w, struct{ s S; ap *[4]int}{})\n\tprint(\"p.f[string]\", \"String\", \"p.C[int]\", w)\n\tprint(\"p.f[string]\", \"==\", w, struct{ s string; ap *[4]int}{})\n}\n`\n\n\tp, _ := buildPackage(t, source, ssa.InstantiateGenerics)\n\n\tprobes := callsTo(ssautil.AllFunctions(p.Prog), \"print\")\n\tif got, want := len(probes), 3*4*2; got != want {\n\t\tt.Errorf(\"Found %v probes, expected %v\", got, want)\n\t}\n\n\tconst debug = false // enable to debug skips\n\tskipped := 0\n\tfor probe, fn := range probes {\n\t\t// Each probe is of the form:\n\t\t// \t\tprint(\"within\", \"test\", head, tail)\n\t\t// The probe only matches within a function whose fn.String() is within.\n\t\t// This allows for different instantiations of fn to match different probes.\n\t\t// On a match, it applies the test named \"test\" to head::tail.\n\t\tif len(probe.Args) < 3 {\n\t\t\tt.Fatalf(\"probe %v did not have enough arguments\", probe)\n\t\t}\n\t\twithin, test, head, tail := constString(probe.Args[0]), probe.Args[1], probe.Args[2], probe.Args[3:]\n\t\tif within != fn.String() {\n\t\t\tskipped++\n\t\t\tif debug {\n\t\t\t\tt.Logf(\"Skipping %q within %q\", within, fn.String())\n\t\t\t}\n\t\t\tcontinue // does not match function\n\t\t}\n\n\t\tswitch test := constString(test); test {\n\t\tcase \"==\": // All of the values are types.Identical.\n\t\t\tfor _, v := range tail {\n\t\t\t\tif !types.Identical(head.Type(), v.Type()) {\n\t\t\t\t\tt.Errorf(\"Expected %v and %v to have identical types\", head, v)\n\t\t\t\t}\n\t\t\t}\n\t\tcase \"String\": // head is a string constant that all values in tail must match Type().String()\n\t\t\twant := constString(head)\n\t\t\tfor _, v := range tail {\n\t\t\t\tif got := v.Type().String(); got != want {\n\t\t\t\t\tt.Errorf(\"%s: %v had the Type().String()=%q. expected %q\", within, v, got, want)\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tt.Errorf(\"%q is not a test subcommand\", test)\n\t\t}\n\t}\n\tif want := 3 * 4; skipped != want {\n\t\tt.Errorf(\"Skipped %d probes, expected to skip %d\", skipped, want)\n\t}\n}\n\n// constString returns the value of a string constant\n// or \"<not a constant string>\" if the value is not a string constant.\nfunc constString(v ssa.Value) string {\n\tif c, ok := v.(*ssa.Const); ok {\n\t\tstr := c.Value.String()\n\t\treturn strings.Trim(str, `\"`)\n\t}\n\treturn \"<not a constant string>\"\n}\n\n// TestMultipleGoversions tests that globals initialized to equivalent\n// function literals are compiled based on the different GoVersion in each file.\nfunc TestMultipleGoversions(t *testing.T) {\n\tvar contents = map[string]string{\n\t\t\"post.go\": `\n\t//go:build go1.22\n\tpackage p\n\n\tvar distinct = func(l []int) {\n\t\tfor i := range l {\n\t\t\tprint(&i)\n\t\t}\n\t}\n\t`,\n\t\t\"pre.go\": `\n\tpackage p\n\n\tvar same = func(l []int) {\n\t\tfor i := range l {\n\t\t\tprint(&i)\n\t\t}\n\t}\n\t`,\n\t}\n\n\tfset := token.NewFileSet()\n\tvar files []*ast.File\n\tfor _, fname := range []string{\"post.go\", \"pre.go\"} {\n\t\tfile, err := parser.ParseFile(fset, fname, contents[fname], 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfiles = append(files, file)\n\t}\n\n\tpkg := types.NewPackage(\"p\", \"\")\n\tconf := &types.Config{Importer: nil, GoVersion: \"go1.21\"}\n\tp, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Test that global is initialized to a function literal that was\n\t// compiled to have the expected for loop range variable lifetime for i.\n\tfor _, test := range []struct {\n\t\tglobal *ssa.Global\n\t\twant   string // basic block to []*ssa.Alloc.\n\t}{\n\t\t{p.Var(\"same\"), \"map[entry:[new int (i)]]\"},               // i is allocated in the entry block.\n\t\t{p.Var(\"distinct\"), \"map[rangeindex.body:[new int (i)]]\"}, // i is allocated in the body block.\n\t} {\n\t\t// Find the function the test.name global is initialized to.\n\t\tvar fn *ssa.Function\n\t\tfor _, b := range p.Func(\"init\").Blocks {\n\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\tif s, ok := instr.(*ssa.Store); ok && s.Addr == test.global {\n\t\t\t\t\tfn, _ = s.Val.(*ssa.Function)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif fn == nil {\n\t\t\tt.Fatalf(\"Failed to find *ssa.Function for initial value of global %s\", test.global)\n\t\t}\n\n\t\tallocs := make(map[string][]string) // block comments -> []Alloc\n\t\tfor _, b := range fn.Blocks {\n\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\tif a, ok := instr.(*ssa.Alloc); ok {\n\t\t\t\t\tallocs[b.Comment] = append(allocs[b.Comment], a.String())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif got := fmt.Sprint(allocs); got != test.want {\n\t\t\tt.Errorf(\"[%s:=%s] expected the allocations to be in the basic blocks %q, got %q\", test.global, fn, test.want, got)\n\t\t}\n\t}\n}\n\n// TestRangeOverInt tests that, in a range-over-int (#61405),\n// the type of each range var v (identified by print(v) calls)\n// has the expected type.\nfunc TestRangeOverInt(t *testing.T) {\n\tconst rangeOverIntSrc = `\n\t\tpackage p\n\n\t\ttype I uint8\n\n\t\tfunc noKey(x int) {\n\t\t\tfor range x {\n\t\t\t\t// does not crash\n\t\t\t}\n\t\t}\n\n\t\tfunc untypedConstantOperand() {\n\t\t\tfor i := range 10 {\n\t\t\t\tprint(i) /*@ types(\"int\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc unsignedOperand(x uint64) {\n\t\t\tfor i := range x {\n\t\t\t\tprint(i) /*@ types(\"uint64\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc namedOperand(x I) {\n\t\t\tfor i := range x {\n\t\t\t\tprint(i)  /*@ types(\"p.I\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc typeparamOperand[T int](x T) {\n\t\t\tfor i := range x {\n\t\t\t\tprint(i)  /*@ types(\"T\")*/\n\t\t\t}\n\t\t}\n\n\t\tfunc assignment(x I) {\n\t\t\tvar k I\n\t\t\tfor k = range x {\n\t\t\t\tprint(k) /*@ types(\"p.I\")*/\n\t\t\t}\n\t\t}\n\t`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", rangeOverIntSrc, parser.ParseComments)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tpkg := types.NewPackage(\"p\", \"\")\n\tconf := &types.Config{}\n\tp, _, err := ssautil.BuildPackage(conf, fset, pkg, []*ast.File{f}, ssa.SanityCheckFunctions)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Collect all notes in f, i.e. comments starting with \"//@ types\".\n\tnotes, err := expect.ExtractGo(fset.File(f.Pos()), f)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Collect calls to the built-in print function.\n\tfns := make(map[*ssa.Function]bool)\n\tfor _, mem := range p.Members {\n\t\tif fn, ok := mem.(*ssa.Function); ok {\n\t\t\tfns[fn] = true\n\t\t}\n\t}\n\tprobes := callsTo(fns, \"print\")\n\texpectations := matchNotes(fset, notes, probes)\n\n\tfor call := range probes {\n\t\tif expectations[call] == nil {\n\t\t\tt.Errorf(\"Unmatched call: %v @ %s\", call, fset.Position(call.Pos()))\n\t\t}\n\t}\n\n\t// Check each expectation.\n\tfor call, note := range expectations {\n\t\tvar args []string\n\t\tfor _, a := range call.Args {\n\t\t\targs = append(args, a.Type().String())\n\t\t}\n\t\tif got, want := fmt.Sprint(args), fmt.Sprint(note.Args); got != want {\n\t\t\tat := fset.Position(call.Pos())\n\t\t\tt.Errorf(\"%s: arguments to print had types %s, want %s\", at, got, want)\n\t\t\tlogFunction(t, probes[call])\n\t\t}\n\t}\n}\n\nfunc TestBuildPackageGo120(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tsrc      string\n\t\timporter types.Importer\n\t}{\n\t\t{\"slice to array\", \"package p; var s []byte; var _ = ([4]byte)(s)\", nil},\n\t\t{\"slice to zero length array\", \"package p; var s []byte; var _ = ([0]byte)(s)\", nil},\n\t\t{\"slice to zero length array type parameter\", \"package p; var s []byte; func f[T ~[0]byte]() { tmp := (T)(s); var z T; _ = tmp == z}\", nil},\n\t\t{\"slice to non-zero length array type parameter\", \"package p; var s []byte; func h[T ~[1]byte | [4]byte]() { tmp := T(s); var z T; _ = tmp == z}\", nil},\n\t\t{\"slice to maybe-zero length array type parameter\", \"package p; var s []byte; func g[T ~[0]byte | [4]byte]() { tmp := T(s); var z T; _ = tmp == z}\", nil},\n\t\t{\n\t\t\t\"rune sequence to sequence cast patterns\", `\n\t\t\tpackage p\n\t\t\t// Each of fXX functions describes a 1.20 legal cast between sequences of runes\n\t\t\t// as []rune, pointers to rune arrays, rune arrays, or strings.\n\t\t\t//\n\t\t\t// Comments listed given the current emitted instructions [approximately].\n\t\t\t// If multiple conversions are needed, these are separated by |.\n\t\t\t// rune was selected as it leads to string casts (byte is similar).\n\t\t\t// The length 2 is not significant.\n\t\t\t// Multiple array lengths may occur in a cast in practice (including 0).\n\t\t\tfunc f00[S string, D string](s S)                               { _ = D(s) } // ChangeType\n\t\t\tfunc f01[S string, D []rune](s S)                               { _ = D(s) } // Convert\n\t\t\tfunc f02[S string, D []rune | string](s S)                      { _ = D(s) } // ChangeType | Convert\n\t\t\tfunc f03[S [2]rune, D [2]rune](s S)                             { _ = D(s) } // ChangeType\n\t\t\tfunc f04[S *[2]rune, D *[2]rune](s S)                           { _ = D(s) } // ChangeType\n\t\t\tfunc f05[S []rune, D string](s S)                               { _ = D(s) } // Convert\n\t\t\tfunc f06[S []rune, D [2]rune](s S)                              { _ = D(s) } // SliceToArrayPointer; Deref\n\t\t\tfunc f07[S []rune, D [2]rune | string](s S)                     { _ = D(s) } // SliceToArrayPointer; Deref | Convert\n\t\t\tfunc f08[S []rune, D *[2]rune](s S)                             { _ = D(s) } // SliceToArrayPointer\n\t\t\tfunc f09[S []rune, D *[2]rune | string](s S)                    { _ = D(s) } // SliceToArrayPointer; Deref | Convert\n\t\t\tfunc f10[S []rune, D *[2]rune | [2]rune](s S)                   { _ = D(s) } // SliceToArrayPointer | SliceToArrayPointer; Deref\n\t\t\tfunc f11[S []rune, D *[2]rune | [2]rune | string](s S)          { _ = D(s) } // SliceToArrayPointer | SliceToArrayPointer; Deref | Convert\n\t\t\tfunc f12[S []rune, D []rune](s S)                               { _ = D(s) } // ChangeType\n\t\t\tfunc f13[S []rune, D []rune | string](s S)                      { _ = D(s) } // Convert | ChangeType\n\t\t\tfunc f14[S []rune, D []rune | [2]rune](s S)                     { _ = D(s) } // ChangeType | SliceToArrayPointer; Deref\n\t\t\tfunc f15[S []rune, D []rune | [2]rune | string](s S)            { _ = D(s) } // ChangeType | SliceToArrayPointer; Deref | Convert\n\t\t\tfunc f16[S []rune, D []rune | *[2]rune](s S)                    { _ = D(s) } // ChangeType | SliceToArrayPointer\n\t\t\tfunc f17[S []rune, D []rune | *[2]rune | string](s S)           { _ = D(s) } // ChangeType | SliceToArrayPointer | Convert\n\t\t\tfunc f18[S []rune, D []rune | *[2]rune | [2]rune](s S)          { _ = D(s) } // ChangeType | SliceToArrayPointer | SliceToArrayPointer; Deref\n\t\t\tfunc f19[S []rune, D []rune | *[2]rune | [2]rune | string](s S) { _ = D(s) } // ChangeType | SliceToArrayPointer | SliceToArrayPointer; Deref | Convert\n\t\t\tfunc f20[S []rune | string, D string](s S)                      { _ = D(s) } // Convert | ChangeType\n\t\t\tfunc f21[S []rune | string, D []rune](s S)                      { _ = D(s) } // Convert | ChangeType\n\t\t\tfunc f22[S []rune | string, D []rune | string](s S)             { _ = D(s) } // ChangeType | Convert | Convert | ChangeType\n\t\t\tfunc f23[S []rune | [2]rune, D [2]rune](s S)                    { _ = D(s) } // SliceToArrayPointer; Deref | ChangeType\n\t\t\tfunc f24[S []rune | *[2]rune, D *[2]rune](s S)                  { _ = D(s) } // SliceToArrayPointer | ChangeType\n\t\t\t`, nil,\n\t\t},\n\t\t{\n\t\t\t\"matching named and underlying types\", `\n\t\t\tpackage p\n\t\t\ttype a string\n\t\t\ttype b string\n\t\t\tfunc g0[S []rune | a | b, D []rune | a | b](s S)      { _ = D(s) }\n\t\t\tfunc g1[S []rune | ~string, D []rune | a | b](s S)    { _ = D(s) }\n\t\t\tfunc g2[S []rune | a | b, D []rune | ~string](s S)    { _ = D(s) }\n\t\t\tfunc g3[S []rune | ~string, D []rune |~string](s S)   { _ = D(s) }\n\t\t\t`, nil,\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, \"p.go\", tc.src, 0)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t\tfiles := []*ast.File{f}\n\n\t\t\tpkg := types.NewPackage(\"p\", \"\")\n\t\t\tconf := &types.Config{Importer: tc.importer}\n\t\t\t_, _, err = ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"unexpected error: %v\", err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/ssa/const.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines the Const SSA value type.\n\nimport (\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// NewConst returns a new constant of the specified value and type.\n// val must be valid according to the specification of Const.Value.\nfunc NewConst(val constant.Value, typ types.Type) *Const {\n\tif val == nil {\n\t\tswitch soleTypeKind(typ) {\n\t\tcase types.IsBoolean:\n\t\t\tval = constant.MakeBool(false)\n\t\tcase types.IsInteger:\n\t\t\tval = constant.MakeInt64(0)\n\t\tcase types.IsString:\n\t\t\tval = constant.MakeString(\"\")\n\t\t}\n\t}\n\treturn &Const{typ, val}\n}\n\n// soleTypeKind returns a BasicInfo for which constant.Value can\n// represent all zero values for the types in the type set.\n//\n//\ttypes.IsBoolean for false is a representative.\n//\ttypes.IsInteger for 0\n//\ttypes.IsString for \"\"\n//\t0 otherwise.\nfunc soleTypeKind(typ types.Type) types.BasicInfo {\n\t// State records the set of possible zero values (false, 0, \"\").\n\t// Candidates (perhaps all) are eliminated during the type-set\n\t// iteration, which executes at least once.\n\tstate := types.IsBoolean | types.IsInteger | types.IsString\n\tunderIs(typ, func(ut types.Type) bool {\n\t\tvar c types.BasicInfo\n\t\tif t, ok := ut.(*types.Basic); ok {\n\t\t\tc = t.Info()\n\t\t}\n\t\tif c&types.IsNumeric != 0 { // int/float/complex\n\t\t\tc = types.IsInteger\n\t\t}\n\t\tstate = state & c\n\t\treturn state != 0\n\t})\n\treturn state\n}\n\n// intConst returns an 'int' constant that evaluates to i.\n// (i is an int64 in case the host is narrower than the target.)\nfunc intConst(i int64) *Const {\n\treturn NewConst(constant.MakeInt64(i), tInt)\n}\n\n// stringConst returns a 'string' constant that evaluates to s.\nfunc stringConst(s string) *Const {\n\treturn NewConst(constant.MakeString(s), tString)\n}\n\n// zeroConst returns a new \"zero\" constant of the specified type.\nfunc zeroConst(t types.Type) *Const {\n\treturn NewConst(nil, t)\n}\n\nfunc (c *Const) RelString(from *types.Package) string {\n\tvar s string\n\tif c.Value == nil {\n\t\ts, _ = typesinternal.ZeroString(c.typ, types.RelativeTo(from))\n\t} else if c.Value.Kind() == constant.String {\n\t\ts = constant.StringVal(c.Value)\n\t\tconst max = 20\n\t\t// TODO(adonovan): don't cut a rune in half.\n\t\tif len(s) > max {\n\t\t\ts = s[:max-3] + \"...\" // abbreviate\n\t\t}\n\t\ts = strconv.Quote(s)\n\t} else {\n\t\ts = c.Value.String()\n\t}\n\treturn s + \":\" + relType(c.Type(), from)\n}\n\nfunc (c *Const) Name() string {\n\treturn c.RelString(nil)\n}\n\nfunc (c *Const) String() string {\n\treturn c.Name()\n}\n\nfunc (c *Const) Type() types.Type {\n\treturn c.typ\n}\n\nfunc (c *Const) Referrers() *[]Instruction {\n\treturn nil\n}\n\nfunc (c *Const) Parent() *Function { return nil }\n\nfunc (c *Const) Pos() token.Pos {\n\treturn token.NoPos\n}\n\n// IsNil returns true if this constant is a nil value of\n// a nillable reference type (pointer, slice, channel, map, or function),\n// a basic interface type, or\n// a type parameter all of whose possible instantiations are themselves nillable.\nfunc (c *Const) IsNil() bool {\n\treturn c.Value == nil && nillable(c.typ)\n}\n\n// nillable reports whether *new(T) == nil is legal for type T.\nfunc nillable(t types.Type) bool {\n\tif typeparams.IsTypeParam(t) {\n\t\treturn underIs(t, func(u types.Type) bool {\n\t\t\t// empty type set (u==nil) => any underlying types => not nillable\n\t\t\treturn u != nil && nillable(u)\n\t\t})\n\t}\n\tswitch t.Underlying().(type) {\n\tcase *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:\n\t\treturn true\n\tcase *types.Interface:\n\t\treturn true // basic interface.\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// TODO(adonovan): move everything below into golang.org/x/tools/go/ssa/interp.\n\n// Int64 returns the numeric value of this constant truncated to fit\n// a signed 64-bit integer.\nfunc (c *Const) Int64() int64 {\n\tswitch x := constant.ToInt(c.Value); x.Kind() {\n\tcase constant.Int:\n\t\tif i, ok := constant.Int64Val(x); ok {\n\t\t\treturn i\n\t\t}\n\t\treturn 0\n\tcase constant.Float:\n\t\tf, _ := constant.Float64Val(x)\n\t\treturn int64(f)\n\t}\n\tpanic(fmt.Sprintf(\"unexpected constant value: %T\", c.Value))\n}\n\n// Uint64 returns the numeric value of this constant truncated to fit\n// an unsigned 64-bit integer.\nfunc (c *Const) Uint64() uint64 {\n\tswitch x := constant.ToInt(c.Value); x.Kind() {\n\tcase constant.Int:\n\t\tif u, ok := constant.Uint64Val(x); ok {\n\t\t\treturn u\n\t\t}\n\t\treturn 0\n\tcase constant.Float:\n\t\tf, _ := constant.Float64Val(x)\n\t\treturn uint64(f)\n\t}\n\tpanic(fmt.Sprintf(\"unexpected constant value: %T\", c.Value))\n}\n\n// Float64 returns the numeric value of this constant truncated to fit\n// a float64.\nfunc (c *Const) Float64() float64 {\n\tx := constant.ToFloat(c.Value) // (c.Value == nil) => x.Kind() == Unknown\n\tf, _ := constant.Float64Val(x)\n\treturn f\n}\n\n// Complex128 returns the complex value of this constant truncated to\n// fit a complex128.\nfunc (c *Const) Complex128() complex128 {\n\tx := constant.ToComplex(c.Value) // (c.Value == nil) => x.Kind() == Unknown\n\tre, _ := constant.Float64Val(constant.Real(x))\n\tim, _ := constant.Float64Val(constant.Imag(x))\n\treturn complex(re, im)\n}\n"
  },
  {
    "path": "go/ssa/const_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math/big\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ssa\"\n)\n\nfunc TestConstString(t *testing.T) {\n\tconst source = `\n\tpackage P\n\n\ttype Named string\n\n\tfunc fn() (int, bool, string) \n\tfunc gen[T int]() {}\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\texpr     string // type expression\n\t\tconstant any    // constant value\n\t\twant     string // expected String() value\n\t}{\n\t\t{\"int\", int64(0), \"0:int\"},\n\t\t{\"int64\", int64(0), \"0:int64\"},\n\t\t{\"float32\", int64(0), \"0:float32\"},\n\t\t{\"float32\", big.NewFloat(1.5), \"1.5:float32\"},\n\t\t{\"bool\", false, \"false:bool\"},\n\t\t{\"string\", \"\", `\"\":string`},\n\t\t{\"Named\", \"\", `\"\":P.Named`},\n\t\t{\"struct{x string}\", nil, \"struct{x string}{}:struct{x string}\"},\n\t\t{\"[]int\", nil, \"nil:[]int\"},\n\t\t{\"[3]int\", nil, \"[3]int{}:[3]int\"},\n\t\t{\"*int\", nil, \"nil:*int\"},\n\t\t{\"interface{}\", nil, \"nil:interface{}\"},\n\t\t{\"interface{string}\", nil, `\"\":interface{string}`},\n\t\t{\"interface{int|int64}\", nil, \"0:interface{int|int64}\"},\n\t\t{\"interface{bool}\", nil, \"false:interface{bool}\"},\n\t\t{\"interface{bool|int}\", nil, \"invalid:interface{bool|int}\"},\n\t\t{\"interface{int|string}\", nil, \"invalid:interface{int|string}\"},\n\t\t{\"interface{bool|string}\", nil, \"invalid:interface{bool|string}\"},\n\t\t{\"interface{struct{x string}}\", nil, \"invalid:interface{struct{x string}}\"},\n\t\t{\"interface{int|int64}\", int64(1), \"1:interface{int|int64}\"},\n\t\t{\"interface{~bool}\", true, \"true:interface{~bool}\"},\n\t\t{\"interface{Named}\", \"lorem ipsum\", `\"lorem ipsum\":interface{P.Named}`},\n\t\t{\"func() (int, bool, string)\", nil, \"nil:func() (int, bool, string)\"},\n\t} {\n\t\t// Eval() expr for its type.\n\t\ttv, err := types.Eval(fset, pkg, 0, test.expr)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\t\tvar val constant.Value\n\t\tif test.constant != nil {\n\t\t\tval = constant.Make(test.constant)\n\t\t}\n\t\tc := ssa.NewConst(val, tv.Type)\n\t\tgot := strings.ReplaceAll(c.String(), \" | \", \"|\") // Accept both interface{a | b} and interface{a|b}.\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"ssa.NewConst(%v, %s).String() = %v, want %v\", val, tv.Type, got, test.want)\n\t\t}\n\t}\n\n\t// Test tuples\n\tfn := pkg.Scope().Lookup(\"fn\")\n\ttup := fn.Type().(*types.Signature).Results()\n\tif got, want := ssa.NewConst(nil, tup).String(), `(0, false, \"\"):(int, bool, string)`; got != want {\n\t\tt.Errorf(\"ssa.NewConst(%v, %s).String() = %v, want %v\", nil, tup, got, want)\n\t}\n\n\t// Test type-param\n\tgen := pkg.Scope().Lookup(\"gen\")\n\ttp := gen.Type().(*types.Signature).TypeParams().At(0)\n\tif got, want := ssa.NewConst(nil, tp).String(), \"0:T\"; got != want {\n\t\tt.Errorf(\"ssa.NewConst(%v, %s).String() = %v, want %v\", nil, tup, got, want)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/create.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file implements the CREATE phase of SSA construction.\n// See builder.go for explanation.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// NewProgram returns a new SSA Program.\n//\n// mode controls diagnostics and checking during SSA construction.\n//\n// To construct an SSA program:\n//\n//   - Call NewProgram to create an empty Program.\n//   - Call CreatePackage providing typed syntax for each package\n//     you want to build, and call it with types but not\n//     syntax for each of those package's direct dependencies.\n//   - Call [Package.Build] on each syntax package you wish to build,\n//     or [Program.Build] to build all of them.\n//\n// See the Example tests for simple examples.\nfunc NewProgram(fset *token.FileSet, mode BuilderMode) *Program {\n\treturn &Program{\n\t\tFset:     fset,\n\t\timported: make(map[string]*Package),\n\t\tpackages: make(map[*types.Package]*Package),\n\t\tmode:     mode,\n\t\tcanon:    newCanonizer(),\n\t\tctxt:     types.NewContext(),\n\t}\n}\n\n// memberFromObject populates package pkg with a member for the\n// typechecker object obj.\n//\n// For objects from Go source code, syntax is the associated syntax\n// tree (for funcs and vars only) and goversion defines the\n// appropriate interpretation; they will be used during the build\n// phase.\nfunc memberFromObject(pkg *Package, obj types.Object, syntax ast.Node, goversion string) {\n\tname := obj.Name()\n\tswitch obj := obj.(type) {\n\tcase *types.Builtin:\n\t\tif pkg.Pkg != types.Unsafe {\n\t\t\tpanic(\"unexpected builtin object: \" + obj.String())\n\t\t}\n\n\tcase *types.TypeName:\n\t\tif name != \"_\" {\n\t\t\tpkg.Members[name] = &Type{\n\t\t\t\tobject: obj,\n\t\t\t\tpkg:    pkg,\n\t\t\t}\n\t\t}\n\n\tcase *types.Const:\n\t\tc := &NamedConst{\n\t\t\tobject: obj,\n\t\t\tValue:  NewConst(obj.Val(), obj.Type()),\n\t\t\tpkg:    pkg,\n\t\t}\n\t\tpkg.objects[obj] = c\n\t\tif name != \"_\" {\n\t\t\tpkg.Members[name] = c\n\t\t}\n\n\tcase *types.Var:\n\t\tg := &Global{\n\t\t\tPkg:    pkg,\n\t\t\tname:   name,\n\t\t\tobject: obj,\n\t\t\ttyp:    types.NewPointer(obj.Type()), // address\n\t\t\tpos:    obj.Pos(),\n\t\t}\n\t\tpkg.objects[obj] = g\n\t\tif name != \"_\" {\n\t\t\tpkg.Members[name] = g\n\t\t}\n\n\tcase *types.Func:\n\t\tsig := obj.Type().(*types.Signature)\n\t\tif sig.Recv() == nil && name == \"init\" {\n\t\t\tpkg.ninit++\n\t\t\tname = fmt.Sprintf(\"init#%d\", pkg.ninit)\n\t\t}\n\t\tfn := createFunction(pkg.Prog, obj, name, syntax, pkg.info, goversion)\n\t\tfn.Pkg = pkg\n\t\tpkg.created = append(pkg.created, fn)\n\t\tpkg.objects[obj] = fn\n\t\tif name != \"_\" && sig.Recv() == nil {\n\t\t\tpkg.Members[name] = fn // package-level function\n\t\t}\n\n\tdefault: // (incl. *types.Package)\n\t\tpanic(\"unexpected Object type: \" + obj.String())\n\t}\n}\n\n// createFunction creates a function or method. It supports both\n// CreatePackage (with or without syntax) and the on-demand creation\n// of methods in non-created packages based on their types.Func.\nfunc createFunction(prog *Program, obj *types.Func, name string, syntax ast.Node, info *types.Info, goversion string) *Function {\n\tsig := obj.Type().(*types.Signature)\n\n\t// Collect type parameters.\n\tvar tparams *types.TypeParamList\n\tif rtparams := sig.RecvTypeParams(); rtparams.Len() > 0 {\n\t\ttparams = rtparams // method of generic type\n\t} else if sigparams := sig.TypeParams(); sigparams.Len() > 0 {\n\t\ttparams = sigparams // generic function\n\t}\n\n\t/* declared function/method (from syntax or export data) */\n\tfn := &Function{\n\t\tname:       name,\n\t\tobject:     obj,\n\t\tSignature:  sig,\n\t\tbuild:      (*builder).buildFromSyntax,\n\t\tsyntax:     syntax,\n\t\tinfo:       info,\n\t\tgoversion:  goversion,\n\t\tpos:        obj.Pos(),\n\t\tPkg:        nil, // may be set by caller\n\t\tProg:       prog,\n\t\ttypeparams: tparams,\n\t}\n\tif fn.syntax == nil {\n\t\tfn.Synthetic = \"from type information\"\n\t\tfn.build = (*builder).buildParamsOnly\n\t}\n\tif tparams.Len() > 0 {\n\t\tfn.generic = new(generic)\n\t}\n\treturn fn\n}\n\n// membersFromDecl populates package pkg with members for each\n// typechecker object (var, func, const or type) associated with the\n// specified decl.\nfunc membersFromDecl(pkg *Package, decl ast.Decl, goversion string) {\n\tswitch decl := decl.(type) {\n\tcase *ast.GenDecl: // import, const, type or var\n\t\tswitch decl.Tok {\n\t\tcase token.CONST:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tfor _, id := range spec.(*ast.ValueSpec).Names {\n\t\t\t\t\tmemberFromObject(pkg, pkg.info.Defs[id], nil, \"\")\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase token.VAR:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tfor _, rhs := range spec.(*ast.ValueSpec).Values {\n\t\t\t\t\tpkg.initVersion[rhs] = goversion\n\t\t\t\t}\n\t\t\t\tfor _, id := range spec.(*ast.ValueSpec).Names {\n\t\t\t\t\tmemberFromObject(pkg, pkg.info.Defs[id], spec, goversion)\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase token.TYPE:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tid := spec.(*ast.TypeSpec).Name\n\t\t\t\tmemberFromObject(pkg, pkg.info.Defs[id], nil, \"\")\n\t\t\t}\n\t\t}\n\n\tcase *ast.FuncDecl:\n\t\tid := decl.Name\n\t\tmemberFromObject(pkg, pkg.info.Defs[id], decl, goversion)\n\t}\n}\n\n// CreatePackage creates and returns an SSA Package from the\n// specified type-checked, error-free file ASTs, and populates its\n// Members mapping.\n//\n// importable determines whether this package should be returned by a\n// subsequent call to ImportedPackage(pkg.Path()).\n//\n// The real work of building SSA form for each function is not done\n// until a subsequent call to Package.Build.\nfunc (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {\n\tif pkg == nil {\n\t\tpanic(\"nil pkg\") // otherwise pkg.Scope below returns types.Universe!\n\t}\n\tp := &Package{\n\t\tProg:    prog,\n\t\tMembers: make(map[string]Member),\n\t\tobjects: make(map[types.Object]Member),\n\t\tPkg:     pkg,\n\t\tsyntax:  info != nil,\n\t\t// transient values (cleared after Package.Build)\n\t\tinfo:        info,\n\t\tfiles:       files,\n\t\tinitVersion: make(map[ast.Expr]string),\n\t}\n\n\t/* synthesized package initializer */\n\tp.init = &Function{\n\t\tname:      \"init\",\n\t\tSignature: new(types.Signature),\n\t\tSynthetic: \"package initializer\",\n\t\tPkg:       p,\n\t\tProg:      prog,\n\t\tbuild:     (*builder).buildPackageInit,\n\t\tinfo:      p.info,\n\t\tgoversion: \"\", // See Package.build for details.\n\t}\n\tp.Members[p.init.name] = p.init\n\tp.created = append(p.created, p.init)\n\n\t// Allocate all package members: vars, funcs, consts and types.\n\tif len(files) > 0 {\n\t\t// Go source package.\n\t\tfor _, file := range files {\n\t\t\tgoversion := versions.Lang(versions.FileVersion(p.info, file))\n\t\t\tfor _, decl := range file.Decls {\n\t\t\t\tmembersFromDecl(p, decl, goversion)\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// GC-compiled binary package (or \"unsafe\")\n\t\t// No code.\n\t\t// No position information.\n\t\tscope := p.Pkg.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\tobj := scope.Lookup(name)\n\t\t\tmemberFromObject(p, obj, nil, \"\")\n\t\t\tif obj, ok := obj.(*types.TypeName); ok {\n\t\t\t\t// No Unalias: aliases should not duplicate methods.\n\t\t\t\tif named, ok := obj.Type().(*types.Named); ok {\n\t\t\t\t\tfor i, n := 0, named.NumMethods(); i < n; i++ {\n\t\t\t\t\t\tmemberFromObject(p, named.Method(i), nil, \"\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif prog.mode&BareInits == 0 {\n\t\t// Add initializer guard variable.\n\t\tinitguard := &Global{\n\t\t\tPkg:  p,\n\t\t\tname: \"init$guard\",\n\t\t\ttyp:  types.NewPointer(tBool),\n\t\t}\n\t\tp.Members[initguard.Name()] = initguard\n\t}\n\n\tif prog.mode&GlobalDebug != 0 {\n\t\tp.SetDebugMode(true)\n\t}\n\n\tif prog.mode&PrintPackages != 0 {\n\t\tprintMu.Lock()\n\t\tp.WriteTo(os.Stdout)\n\t\tprintMu.Unlock()\n\t}\n\n\tif importable {\n\t\tprog.imported[p.Pkg.Path()] = p\n\t}\n\tprog.packages[p.Pkg] = p\n\n\treturn p\n}\n\n// printMu serializes printing of Packages/Functions to stdout.\nvar printMu sync.Mutex\n\n// AllPackages returns a new slice containing all packages created by\n// prog.CreatePackage in unspecified order.\nfunc (prog *Program) AllPackages() []*Package {\n\tpkgs := make([]*Package, 0, len(prog.packages))\n\tfor _, pkg := range prog.packages {\n\t\tpkgs = append(pkgs, pkg)\n\t}\n\treturn pkgs\n}\n\n// ImportedPackage returns the importable Package whose PkgPath\n// is path, or nil if no such Package has been created.\n//\n// A parameter to CreatePackage determines whether a package should be\n// considered importable. For example, no import declaration can resolve\n// to the ad-hoc main package created by 'go build foo.go'.\n//\n// TODO(adonovan): rethink this function and the \"importable\" concept;\n// most packages are importable. This function assumes that all\n// types.Package.Path values are unique within the ssa.Program, which is\n// false---yet this function remains very convenient.\n// Clients should use (*Program).Package instead where possible.\n// SSA doesn't really need a string-keyed map of packages.\n//\n// Furthermore, the graph of packages may contain multiple variants\n// (e.g. \"p\" vs \"p as compiled for q.test\"), and each has a different\n// view of its dependencies.\nfunc (prog *Program) ImportedPackage(path string) *Package {\n\treturn prog.imported[path]\n}\n\n// SetNoReturn sets the predicate used when building the ssa.Program\n// prog that reports whether a given function cannot return.\n// This may be used to prune spurious control flow edges\n// after (e.g.) log.Fatal, improving the precision of analyses.\n//\n// A typical implementation is the [ctrlflow.CFGs.NoReturn] method from\n// [golang.org/x/tools/go/analysis/passes/ctrlflow].\nfunc (prog *Program) SetNoReturn(noReturn func(*types.Func) bool) {\n\tprog.noReturn = noReturn\n}\n"
  },
  {
    "path": "go/ssa/doc.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package ssa defines a representation of the elements of Go programs\n// (packages, types, functions, variables and constants) using a\n// static single-assignment (SSA) form intermediate representation\n// (IR) for the bodies of functions.\n//\n// For an introduction to SSA form, see\n// http://en.wikipedia.org/wiki/Static_single_assignment_form.\n// This page provides a broader reading list:\n// http://www.dcs.gla.ac.uk/~jsinger/ssa.html.\n//\n// The level of abstraction of the SSA form is intentionally close to\n// the source language to facilitate construction of source analysis\n// tools.  It is not intended for machine code generation.\n//\n// All looping, branching and switching constructs are replaced with\n// unstructured control flow.  Higher-level control flow constructs\n// such as multi-way branch can be reconstructed as needed; see\n// [golang.org/x/tools/go/ssa/ssautil.Switches] for an example.\n//\n// The simplest way to create the SSA representation of a package is\n// to load typed syntax trees using [golang.org/x/tools/go/packages], then\n// invoke the [golang.org/x/tools/go/ssa/ssautil.Packages] helper function.\n// (See the package-level Examples named LoadPackages and LoadWholeProgram.)\n// The resulting [ssa.Program] contains all the packages and their\n// members, but SSA code is not created for function bodies until a\n// subsequent call to [Package.Build] or [Program.Build].\n//\n// The builder initially builds a naive SSA form in which all local\n// variables are addresses of stack locations with explicit loads and\n// stores.  Registerisation of eligible locals and φ-node insertion\n// using dominance and dataflow are then performed as a second pass\n// called \"lifting\" to improve the accuracy and performance of\n// subsequent analyses; this pass can be skipped by setting the\n// NaiveForm builder flag.\n//\n// The primary interfaces of this package are:\n//\n//   - [Member]: a named member of a Go package.\n//   - [Value]: an expression that yields a value.\n//   - [Instruction]: a statement that consumes values and performs computation.\n//   - [Node]: a [Value] or [Instruction] (emphasizing its membership in the SSA value graph)\n//\n// A computation that yields a result implements both the [Value] and\n// [Instruction] interfaces.  The following table shows for each\n// concrete type which of these interfaces it implements.\n//\n//\t                   Value?          Instruction?      Member?\n//\t*Alloc                ✔               ✔\n//\t*BinOp                ✔               ✔\n//\t*Builtin              ✔\n//\t*Call                 ✔               ✔\n//\t*ChangeInterface      ✔               ✔\n//\t*ChangeType           ✔               ✔\n//\t*Const                ✔\n//\t*Convert              ✔               ✔\n//\t*DebugRef                             ✔\n//\t*Defer                                ✔\n//\t*Extract              ✔               ✔\n//\t*Field                ✔               ✔\n//\t*FieldAddr            ✔               ✔\n//\t*FreeVar              ✔\n//\t*Function             ✔                               ✔ (func)\n//\t*Global               ✔                               ✔ (var)\n//\t*Go                                   ✔\n//\t*If                                   ✔\n//\t*Index                ✔               ✔\n//\t*IndexAddr            ✔               ✔\n//\t*Jump                                 ✔\n//\t*Lookup               ✔               ✔\n//\t*MakeChan             ✔               ✔\n//\t*MakeClosure          ✔               ✔\n//\t*MakeInterface        ✔               ✔\n//\t*MakeMap              ✔               ✔\n//\t*MakeSlice            ✔               ✔\n//\t*MapUpdate                            ✔\n//\t*MultiConvert         ✔               ✔\n//\t*NamedConst                                           ✔ (const)\n//\t*Next                 ✔               ✔\n//\t*Panic                                ✔\n//\t*Parameter            ✔\n//\t*Phi                  ✔               ✔\n//\t*Range                ✔               ✔\n//\t*Return                               ✔\n//\t*RunDefers                            ✔\n//\t*Select               ✔               ✔\n//\t*Send                                 ✔\n//\t*Slice                ✔               ✔\n//\t*SliceToArrayPointer  ✔               ✔\n//\t*Store                                ✔\n//\t*Type                                                 ✔ (type)\n//\t*TypeAssert           ✔               ✔\n//\t*UnOp                 ✔               ✔\n//\n// Other key types in this package include: [Program], [Package], [Function]\n// and [BasicBlock].\n//\n// The program representation constructed by this package is fully\n// resolved internally, i.e. it does not rely on the names of Values,\n// Packages, Functions, Types or BasicBlocks for the correct\n// interpretation of the program.  Only the identities of objects and\n// the topology of the SSA and type graphs are semantically\n// significant.  (There is one exception: [types.Id] values, which identify field\n// and method names, contain strings.)  Avoidance of name-based\n// operations simplifies the implementation of subsequent passes and\n// can make them very efficient.  Many objects are nonetheless named\n// to aid in debugging, but it is not essential that the names be\n// either accurate or unambiguous.  The public API exposes a number of\n// name-based maps for client convenience.\n//\n// The [golang.org/x/tools/go/ssa/ssautil] package provides various\n// helper functions, for example to simplify loading a Go program into\n// SSA form.\n//\n// TODO(adonovan): write a how-to document for all the various cases\n// of trying to determine corresponding elements across the four\n// domains of source locations, ast.Nodes, types.Objects,\n// ssa.Values/Instructions.\npackage ssa // import \"golang.org/x/tools/go/ssa\"\n"
  },
  {
    "path": "go/ssa/dom.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines algorithms related to dominance.\n\n// Dominator tree construction ----------------------------------------\n//\n// We use the algorithm described in Lengauer & Tarjan. 1979.  A fast\n// algorithm for finding dominators in a flowgraph.\n// http://doi.acm.org/10.1145/357062.357071\n//\n// We also apply the optimizations to SLT described in Georgiadis et\n// al, Finding Dominators in Practice, JGAA 2006,\n// http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf\n// to avoid the need for buckets of size > 1.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"os\"\n\t\"slices\"\n\t\"sort\"\n)\n\n// Idom returns the block that immediately dominates b:\n// its parent in the dominator tree, if any.\n// Neither the entry node (b.Index==0) nor recover node\n// (b==b.Parent().Recover()) have a parent.\nfunc (b *BasicBlock) Idom() *BasicBlock { return b.dom.idom }\n\n// Dominees returns the list of blocks that b immediately dominates:\n// its children in the dominator tree.\nfunc (b *BasicBlock) Dominees() []*BasicBlock { return b.dom.children }\n\n// Dominates reports whether b dominates c.\nfunc (b *BasicBlock) Dominates(c *BasicBlock) bool {\n\treturn b.dom.pre <= c.dom.pre && c.dom.post <= b.dom.post\n}\n\n// DomPreorder returns a new slice containing the blocks of f\n// in a preorder traversal of the dominator tree.\nfunc (f *Function) DomPreorder() []*BasicBlock {\n\tslice := slices.Clone(f.Blocks)\n\tsort.Slice(slice, func(i, j int) bool {\n\t\treturn slice[i].dom.pre < slice[j].dom.pre\n\t})\n\treturn slice\n}\n\n// DomPostorder returns a new slice containing the blocks of f\n// in a postorder traversal of the dominator tree.\n// (This is not the same as a postdominance order.)\nfunc (f *Function) DomPostorder() []*BasicBlock {\n\tslice := slices.Clone(f.Blocks)\n\tsort.Slice(slice, func(i, j int) bool {\n\t\treturn slice[i].dom.post < slice[j].dom.post\n\t})\n\treturn slice\n}\n\n// domInfo contains a BasicBlock's dominance information.\ntype domInfo struct {\n\tidom      *BasicBlock   // immediate dominator (parent in domtree)\n\tchildren  []*BasicBlock // nodes immediately dominated by this one\n\tpre, post int32         // pre- and post-order numbering within domtree\n}\n\n// ltState holds the working state for Lengauer-Tarjan algorithm\n// (during which domInfo.pre is repurposed for CFG DFS preorder number).\ntype ltState struct {\n\t// Each slice is indexed by b.Index.\n\tsdom     []*BasicBlock // b's semidominator\n\tparent   []*BasicBlock // b's parent in DFS traversal of CFG\n\tancestor []*BasicBlock // b's ancestor with least sdom\n}\n\n// dfs implements the depth-first search part of the LT algorithm.\nfunc (lt *ltState) dfs(v *BasicBlock, i int32, preorder []*BasicBlock) int32 {\n\tpreorder[i] = v\n\tv.dom.pre = i // For now: DFS preorder of spanning tree of CFG\n\ti++\n\tlt.sdom[v.Index] = v\n\tlt.link(nil, v)\n\tfor _, w := range v.Succs {\n\t\tif lt.sdom[w.Index] == nil {\n\t\t\tlt.parent[w.Index] = v\n\t\t\ti = lt.dfs(w, i, preorder)\n\t\t}\n\t}\n\treturn i\n}\n\n// eval implements the EVAL part of the LT algorithm.\nfunc (lt *ltState) eval(v *BasicBlock) *BasicBlock {\n\t// TODO(adonovan): opt: do path compression per simple LT.\n\tu := v\n\tfor ; lt.ancestor[v.Index] != nil; v = lt.ancestor[v.Index] {\n\t\tif lt.sdom[v.Index].dom.pre < lt.sdom[u.Index].dom.pre {\n\t\t\tu = v\n\t\t}\n\t}\n\treturn u\n}\n\n// link implements the LINK part of the LT algorithm.\nfunc (lt *ltState) link(v, w *BasicBlock) {\n\tlt.ancestor[w.Index] = v\n}\n\n// buildDomTree computes the dominator tree of f using the LT algorithm.\n// Precondition: all blocks are reachable (e.g. optimizeBlocks has been run).\nfunc buildDomTree(f *Function) {\n\t// The step numbers refer to the original LT paper; the\n\t// reordering is due to Georgiadis.\n\n\t// Clear any previous domInfo.\n\tfor _, b := range f.Blocks {\n\t\tb.dom = domInfo{}\n\t}\n\n\tn := len(f.Blocks)\n\t// Allocate space for 5 contiguous [n]*BasicBlock arrays:\n\t// sdom, parent, ancestor, preorder, buckets.\n\tspace := make([]*BasicBlock, 5*n)\n\tlt := ltState{\n\t\tsdom:     space[0:n],\n\t\tparent:   space[n : 2*n],\n\t\tancestor: space[2*n : 3*n],\n\t}\n\n\t// Step 1.  Number vertices by depth-first preorder.\n\tpreorder := space[3*n : 4*n]\n\troot := f.Blocks[0]\n\tprenum := lt.dfs(root, 0, preorder)\n\trecover := f.Recover\n\tif recover != nil {\n\t\tlt.dfs(recover, prenum, preorder)\n\t}\n\n\tbuckets := space[4*n : 5*n]\n\tcopy(buckets, preorder)\n\n\t// In reverse preorder...\n\tfor i := int32(n) - 1; i > 0; i-- {\n\t\tw := preorder[i]\n\n\t\t// Step 3. Implicitly define the immediate dominator of each node.\n\t\tfor v := buckets[i]; v != w; v = buckets[v.dom.pre] {\n\t\t\tu := lt.eval(v)\n\t\t\tif lt.sdom[u.Index].dom.pre < i {\n\t\t\t\tv.dom.idom = u\n\t\t\t} else {\n\t\t\t\tv.dom.idom = w\n\t\t\t}\n\t\t}\n\n\t\t// Step 2. Compute the semidominators of all nodes.\n\t\tlt.sdom[w.Index] = lt.parent[w.Index]\n\t\tfor _, v := range w.Preds {\n\t\t\tu := lt.eval(v)\n\t\t\tif lt.sdom[u.Index].dom.pre < lt.sdom[w.Index].dom.pre {\n\t\t\t\tlt.sdom[w.Index] = lt.sdom[u.Index]\n\t\t\t}\n\t\t}\n\n\t\tlt.link(lt.parent[w.Index], w)\n\n\t\tif lt.parent[w.Index] == lt.sdom[w.Index] {\n\t\t\tw.dom.idom = lt.parent[w.Index]\n\t\t} else {\n\t\t\tbuckets[i] = buckets[lt.sdom[w.Index].dom.pre]\n\t\t\tbuckets[lt.sdom[w.Index].dom.pre] = w\n\t\t}\n\t}\n\n\t// The final 'Step 3' is now outside the loop.\n\tfor v := buckets[0]; v != root; v = buckets[v.dom.pre] {\n\t\tv.dom.idom = root\n\t}\n\n\t// Step 4. Explicitly define the immediate dominator of each\n\t// node, in preorder.\n\tfor _, w := range preorder[1:] {\n\t\tif w == root || w == recover {\n\t\t\tw.dom.idom = nil\n\t\t} else {\n\t\t\tif w.dom.idom != lt.sdom[w.Index] {\n\t\t\t\tw.dom.idom = w.dom.idom.dom.idom\n\t\t\t}\n\t\t\t// Calculate Children relation as inverse of Idom.\n\t\t\tw.dom.idom.dom.children = append(w.dom.idom.dom.children, w)\n\t\t}\n\t}\n\n\tpre, post := numberDomTree(root, 0, 0)\n\tif recover != nil {\n\t\tnumberDomTree(recover, pre, post)\n\t}\n\n\t// printDomTreeDot(os.Stderr, f)        // debugging\n\t// printDomTreeText(os.Stderr, root, 0) // debugging\n\n\tif f.Prog.mode&SanityCheckFunctions != 0 {\n\t\tsanityCheckDomTree(f)\n\t}\n}\n\n// numberDomTree sets the pre- and post-order numbers of a depth-first\n// traversal of the dominator tree rooted at v.  These are used to\n// answer dominance queries in constant time.\nfunc numberDomTree(v *BasicBlock, pre, post int32) (int32, int32) {\n\tv.dom.pre = pre\n\tpre++\n\tfor _, child := range v.dom.children {\n\t\tpre, post = numberDomTree(child, pre, post)\n\t}\n\tv.dom.post = post\n\tpost++\n\treturn pre, post\n}\n\n// Testing utilities ----------------------------------------\n\n// sanityCheckDomTree checks the correctness of the dominator tree\n// computed by the LT algorithm by comparing against the dominance\n// relation computed by a naive Kildall-style forward dataflow\n// analysis (Algorithm 10.16 from the \"Dragon\" book).\nfunc sanityCheckDomTree(f *Function) {\n\tn := len(f.Blocks)\n\n\t// D[i] is the set of blocks that dominate f.Blocks[i],\n\t// represented as a bit-set of block indices.\n\tD := make([]big.Int, n)\n\n\tone := big.NewInt(1)\n\n\t// all is the set of all blocks; constant.\n\tvar all big.Int\n\tall.Set(one).Lsh(&all, uint(n)).Sub(&all, one)\n\n\t// Initialization.\n\tfor i, b := range f.Blocks {\n\t\tif i == 0 || b == f.Recover {\n\t\t\t// A root is dominated only by itself.\n\t\t\tD[i].SetBit(&D[0], 0, 1)\n\t\t} else {\n\t\t\t// All other blocks are (initially) dominated\n\t\t\t// by every block.\n\t\t\tD[i].Set(&all)\n\t\t}\n\t}\n\n\t// Iteration until fixed point.\n\tfor changed := true; changed; {\n\t\tchanged = false\n\t\tfor i, b := range f.Blocks {\n\t\t\tif i == 0 || b == f.Recover {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Compute intersection across predecessors.\n\t\t\tvar x big.Int\n\t\t\tx.Set(&all)\n\t\t\tfor _, pred := range b.Preds {\n\t\t\t\tx.And(&x, &D[pred.Index])\n\t\t\t}\n\t\t\tx.SetBit(&x, i, 1) // a block always dominates itself.\n\t\t\tif D[i].Cmp(&x) != 0 {\n\t\t\t\tD[i].Set(&x)\n\t\t\t\tchanged = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check the entire relation.  O(n^2).\n\t// The Recover block (if any) must be treated specially so we skip it.\n\tok := true\n\tfor i := range n {\n\t\tfor j := range n {\n\t\t\tb, c := f.Blocks[i], f.Blocks[j]\n\t\t\tif c == f.Recover {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tactual := b.Dominates(c)\n\t\t\texpected := D[j].Bit(i) == 1\n\t\t\tif actual != expected {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"dominates(%s, %s)==%t, want %t\\n\", b, c, actual, expected)\n\t\t\t\tok = false\n\t\t\t}\n\t\t}\n\t}\n\n\tpreorder := f.DomPreorder()\n\tfor _, b := range f.Blocks {\n\t\tif got := preorder[b.dom.pre]; got != b {\n\t\t\tfmt.Fprintf(os.Stderr, \"preorder[%d]==%s, want %s\\n\", b.dom.pre, got, b)\n\t\t\tok = false\n\t\t}\n\t}\n\n\tif !ok {\n\t\tpanic(\"sanityCheckDomTree failed for \" + f.String())\n\t}\n\n}\n\n// Printing functions ----------------------------------------\n\n// printDomTreeText prints the dominator tree as text, using indentation.\nfunc printDomTreeText(buf *bytes.Buffer, v *BasicBlock, indent int) {\n\tfmt.Fprintf(buf, \"%*s%s\\n\", 4*indent, \"\", v)\n\tfor _, child := range v.dom.children {\n\t\tprintDomTreeText(buf, child, indent+1)\n\t}\n}\n\n// printDomTreeDot prints the dominator tree of f in AT&T GraphViz\n// (.dot) format.\n// (unused; retained for debugging)\nfunc printDomTreeDot(buf *bytes.Buffer, f *Function) {\n\tfmt.Fprintln(buf, \"//\", f)\n\tfmt.Fprintln(buf, \"digraph domtree {\")\n\tfor i, b := range f.Blocks {\n\t\tv := b.dom\n\t\tfmt.Fprintf(buf, \"\\tn%d [label=\\\"%s (%d, %d)\\\",shape=\\\"rectangle\\\"];\\n\", v.pre, b, v.pre, v.post)\n\t\t// TODO(adonovan): improve appearance of edges\n\t\t// belonging to both dominator tree and CFG.\n\n\t\t// Dominator tree edge.\n\t\tif i != 0 {\n\t\t\tfmt.Fprintf(buf, \"\\tn%d -> n%d [style=\\\"solid\\\",weight=100];\\n\", v.idom.dom.pre, v.pre)\n\t\t}\n\t\t// CFG edges.\n\t\tfor _, pred := range b.Preds {\n\t\t\tfmt.Fprintf(buf, \"\\tn%d -> n%d [style=\\\"dotted\\\",weight=0];\\n\", pred.dom.pre, v.pre)\n\t\t}\n\t}\n\tfmt.Fprintln(buf, \"}\")\n}\n"
  },
  {
    "path": "go/ssa/dom_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestDominatorOrder(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for go/packages\n\n\tconst src = `package p\n\nfunc f(cond bool) {\n\t// (Print operands match BasicBlock IDs.)\n\tprint(0)\n\tif cond {\n\t\tprint(1)\n\t} else {\n\t\tprint(2)\n\t}\n\tprint(3)\n}\n`\n\tdir := t.TempDir()\n\tcfg := &packages.Config{\n\t\tDir:  dir,\n\t\tMode: packages.LoadSyntax,\n\t\tOverlay: map[string][]byte{\n\t\t\tfilepath.Join(dir, \"p.go\"): []byte(src),\n\t\t},\n\t}\n\tinitial, err := packages.Load(cfg, \"./p.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif packages.PrintErrors(initial) > 0 {\n\t\tt.Fatal(\"packages contain errors\")\n\t}\n\t_, pkgs := ssautil.Packages(initial, 0)\n\tp := pkgs[0]\n\tp.Build()\n\tf := p.Func(\"f\")\n\n\tif got, want := fmt.Sprint(f.DomPreorder()), \"[0 1 2 3]\"; got != want {\n\t\tt.Errorf(\"DomPreorder: got %v, want %s\", got, want)\n\t}\n\tif got, want := fmt.Sprint(f.DomPostorder()), \"[1 2 3 0]\"; got != want {\n\t\tt.Errorf(\"DomPostorder: got %v, want %s\", got, want)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/emit.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// Helpers for emitting SSA instructions.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// emitAlloc emits to f a new Alloc instruction allocating a variable\n// of type typ.\n//\n// The caller must set Alloc.Heap=true (for a heap-allocated variable)\n// or add the Alloc to f.Locals (for a frame-allocated variable).\n//\n// During building, a variable in f.Locals may have its Heap flag\n// set when it is discovered that its address is taken.\n// These Allocs are removed from f.Locals at the end.\n//\n// The builder should generally call one of the emit{New,Local,LocalVar} wrappers instead.\nfunc emitAlloc(f *Function, typ types.Type, pos token.Pos, comment string) *Alloc {\n\tv := &Alloc{Comment: comment}\n\tv.setType(types.NewPointer(typ))\n\tv.setPos(pos)\n\tf.emit(v)\n\treturn v\n}\n\n// emitNew emits to f a new Alloc instruction heap-allocating a\n// variable of type typ. pos is the optional source location.\nfunc emitNew(f *Function, typ types.Type, pos token.Pos, comment string) *Alloc {\n\talloc := emitAlloc(f, typ, pos, comment)\n\talloc.Heap = true\n\treturn alloc\n}\n\n// emitLocal creates a local var for (t, pos, comment) and\n// emits an Alloc instruction for it.\n//\n// (Use this function or emitNew for synthetic variables;\n// for source-level variables in the same function, use emitLocalVar.)\nfunc emitLocal(f *Function, t types.Type, pos token.Pos, comment string) *Alloc {\n\tlocal := emitAlloc(f, t, pos, comment)\n\tf.Locals = append(f.Locals, local)\n\treturn local\n}\n\n// emitLocalVar creates a local var for v and emits an Alloc instruction for it.\n// Subsequent calls to f.lookup(v) return it.\n// It applies the appropriate generic instantiation to the type.\nfunc emitLocalVar(f *Function, v *types.Var) *Alloc {\n\talloc := emitLocal(f, f.typ(v.Type()), v.Pos(), v.Name())\n\tf.vars[v] = alloc\n\treturn alloc\n}\n\n// emitLoad emits to f an instruction to load the address addr into a\n// new temporary, and returns the value so defined.\nfunc emitLoad(f *Function, addr Value) *UnOp {\n\tv := &UnOp{Op: token.MUL, X: addr}\n\tv.setType(typeparams.MustDeref(addr.Type()))\n\tf.emit(v)\n\treturn v\n}\n\n// emitDebugRef emits to f a DebugRef pseudo-instruction associating\n// expression e with value v.\nfunc emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {\n\tif !f.debugInfo() {\n\t\treturn // debugging not enabled\n\t}\n\tif v == nil || e == nil {\n\t\tpanic(\"nil\")\n\t}\n\tvar obj types.Object\n\te = ast.Unparen(e)\n\tif id, ok := e.(*ast.Ident); ok {\n\t\tif isBlankIdent(id) {\n\t\t\treturn\n\t\t}\n\t\tobj = f.objectOf(id)\n\t\tswitch obj.(type) {\n\t\tcase *types.Nil, *types.Const, *types.Builtin:\n\t\t\treturn\n\t\t}\n\t}\n\tf.emit(&DebugRef{\n\t\tX:      v,\n\t\tExpr:   e,\n\t\tIsAddr: isAddr,\n\t\tobject: obj,\n\t})\n}\n\n// emitArith emits to f code to compute the binary operation op(x, y)\n// where op is an eager shift, logical or arithmetic operation.\n// (Use emitCompare() for comparisons and Builder.logicalBinop() for\n// non-eager operations.)\nfunc emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {\n\tswitch op {\n\tcase token.SHL, token.SHR:\n\t\tx = emitConv(f, x, t)\n\t\t// y may be signed or an 'untyped' constant.\n\n\t\t// There is a runtime panic if y is signed and <0. Instead of inserting a check for y<0\n\t\t// and converting to an unsigned value (like the compiler) leave y as is.\n\n\t\tif isUntyped(y.Type().Underlying()) {\n\t\t\t// Untyped conversion:\n\t\t\t// Spec https://go.dev/ref/spec#Operators:\n\t\t\t// The right operand in a shift expression must have integer type or be an untyped constant\n\t\t\t// representable by a value of type uint.\n\t\t\ty = emitConv(f, y, types.Typ[types.Uint])\n\t\t}\n\n\tcase token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:\n\t\tx = emitConv(f, x, t)\n\t\ty = emitConv(f, y, t)\n\n\tdefault:\n\t\tpanic(\"illegal op in emitArith: \" + op.String())\n\n\t}\n\tv := &BinOp{\n\t\tOp: op,\n\t\tX:  x,\n\t\tY:  y,\n\t}\n\tv.setPos(pos)\n\tv.setType(t)\n\treturn f.emit(v)\n}\n\n// emitCompare emits to f code compute the boolean result of\n// comparison 'x op y'.\nfunc emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {\n\txt := x.Type().Underlying()\n\tyt := y.Type().Underlying()\n\n\t// Special case to optimise a tagless SwitchStmt so that\n\t// these are equivalent\n\t//   switch { case e: ...}\n\t//   switch true { case e: ... }\n\t//   if e==true { ... }\n\t// even in the case when e's type is an interface.\n\t// TODO(adonovan): opt: generalise to x==true, false!=y, etc.\n\tif x == vTrue && op == token.EQL {\n\t\tif yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {\n\t\t\treturn y\n\t\t}\n\t}\n\n\tif types.Identical(xt, yt) {\n\t\t// no conversion necessary\n\t} else if isNonTypeParamInterface(x.Type()) {\n\t\ty = emitConv(f, y, x.Type())\n\t} else if isNonTypeParamInterface(y.Type()) {\n\t\tx = emitConv(f, x, y.Type())\n\t} else if _, ok := x.(*Const); ok {\n\t\tx = emitConv(f, x, y.Type())\n\t} else if _, ok := y.(*Const); ok {\n\t\ty = emitConv(f, y, x.Type())\n\t} else {\n\t\t// other cases, e.g. channels.  No-op.\n\t}\n\n\tv := &BinOp{\n\t\tOp: op,\n\t\tX:  x,\n\t\tY:  y,\n\t}\n\tv.setPos(pos)\n\tv.setType(tBool)\n\treturn f.emit(v)\n}\n\n// isValuePreserving returns true if a conversion from ut_src to\n// ut_dst is value-preserving, i.e. just a change of type.\n// Precondition: neither argument is a named or alias type.\nfunc isValuePreserving(ut_src, ut_dst types.Type) bool {\n\t// Identical underlying types?\n\tif types.IdenticalIgnoreTags(ut_dst, ut_src) {\n\t\treturn true\n\t}\n\n\tswitch ut_dst.(type) {\n\tcase *types.Chan:\n\t\t// Conversion between channel types?\n\t\t_, ok := ut_src.(*types.Chan)\n\t\treturn ok\n\n\tcase *types.Pointer:\n\t\t// Conversion between pointers with identical base types?\n\t\t_, ok := ut_src.(*types.Pointer)\n\t\treturn ok\n\t}\n\treturn false\n}\n\n// emitConv emits to f code to convert Value val to exactly type typ,\n// and returns the converted value.  Implicit conversions are required\n// by language assignability rules in assignments, parameter passing,\n// etc.\nfunc emitConv(f *Function, val Value, typ types.Type) Value {\n\tt_src := val.Type()\n\n\t// Identical types?  Conversion is a no-op.\n\tif types.Identical(t_src, typ) {\n\t\treturn val\n\t}\n\tut_dst := typ.Underlying()\n\tut_src := t_src.Underlying()\n\n\t// Conversion to, or construction of a value of, an interface type?\n\tif isNonTypeParamInterface(typ) {\n\t\t// Interface name change?\n\t\tif isValuePreserving(ut_src, ut_dst) {\n\t\t\tc := &ChangeType{X: val}\n\t\t\tc.setType(typ)\n\t\t\treturn f.emit(c)\n\t\t}\n\n\t\t// Assignment from one interface type to another?\n\t\tif isNonTypeParamInterface(t_src) {\n\t\t\tc := &ChangeInterface{X: val}\n\t\t\tc.setType(typ)\n\t\t\treturn f.emit(c)\n\t\t}\n\n\t\t// Untyped nil constant?  Return interface-typed nil constant.\n\t\tif ut_src == tUntypedNil {\n\t\t\treturn zeroConst(typ)\n\t\t}\n\n\t\t// Convert (non-nil) \"untyped\" literals to their default type.\n\t\tif t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {\n\t\t\tval = emitConv(f, val, types.Default(ut_src))\n\t\t}\n\n\t\t// Record the types of operands to MakeInterface, if\n\t\t// non-parameterized, as they are the set of runtime types.\n\t\tt := val.Type()\n\t\tif f.typeparams.Len() == 0 || !f.Prog.isParameterized(t) {\n\t\t\taddMakeInterfaceType(f.Prog, t)\n\t\t}\n\n\t\tmi := &MakeInterface{X: val}\n\t\tmi.setType(typ)\n\t\treturn f.emit(mi)\n\t}\n\n\t// conversionCase describes an instruction pattern that maybe emitted to\n\t// model d <- s for d in dst_terms and s in src_terms.\n\t// Multiple conversions can match the same pattern.\n\ttype conversionCase uint8\n\tconst (\n\t\tchangeType conversionCase = 1 << iota\n\t\tsliceToArray\n\t\tsliceToArrayPtr\n\t\tsliceTo0Array\n\t\tsliceTo0ArrayPtr\n\t\tconvert\n\t)\n\t// classify the conversion case of a source type us to a destination type ud.\n\t// us and ud are underlying types (not *Named or *Alias)\n\tclassify := func(us, ud types.Type) conversionCase {\n\t\t// Just a change of type, but not value or representation?\n\t\tif isValuePreserving(us, ud) {\n\t\t\treturn changeType\n\t\t}\n\n\t\t// Conversion from slice to array or slice to array pointer?\n\t\tif slice, ok := us.(*types.Slice); ok {\n\t\t\tvar arr *types.Array\n\t\t\tvar ptr bool\n\t\t\t// Conversion from slice to array pointer?\n\t\t\tswitch d := ud.(type) {\n\t\t\tcase *types.Array:\n\t\t\t\tarr = d\n\t\t\tcase *types.Pointer:\n\t\t\t\tarr, _ = d.Elem().Underlying().(*types.Array)\n\t\t\t\tptr = true\n\t\t\t}\n\t\t\tif arr != nil && types.Identical(slice.Elem(), arr.Elem()) {\n\t\t\t\tif arr.Len() == 0 {\n\t\t\t\t\tif ptr {\n\t\t\t\t\t\treturn sliceTo0ArrayPtr\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn sliceTo0Array\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ptr {\n\t\t\t\t\treturn sliceToArrayPtr\n\t\t\t\t} else {\n\t\t\t\t\treturn sliceToArray\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// The only remaining case in well-typed code is a representation-\n\t\t// changing conversion of basic types (possibly with []byte/[]rune).\n\t\tif !isBasic(us) && !isBasic(ud) {\n\t\t\tpanic(fmt.Sprintf(\"in %s: cannot convert term %s (%s [within %s]) to type %s [within %s]\", f, val, val.Type(), us, typ, ud))\n\t\t}\n\t\treturn convert\n\t}\n\n\tvar classifications conversionCase\n\tunderIs(ut_src, func(us types.Type) bool {\n\t\treturn underIs(ut_dst, func(ud types.Type) bool {\n\t\t\tif us != nil && ud != nil {\n\t\t\t\tclassifications |= classify(us, ud)\n\t\t\t}\n\t\t\treturn classifications != 0\n\t\t})\n\t})\n\tif classifications == 0 {\n\t\tpanic(fmt.Sprintf(\"in %s: cannot convert %s (%s) to %s\", f, val, val.Type(), typ))\n\t}\n\n\t// Conversion of a compile-time constant value?\n\tif c, ok := val.(*Const); ok {\n\t\t// Conversion to a basic type?\n\t\tif isBasic(ut_dst) {\n\t\t\t// Conversion of a compile-time constant to\n\t\t\t// another constant type results in a new\n\t\t\t// constant of the destination type and\n\t\t\t// (initially) the same abstract value.\n\t\t\t// We don't truncate the value yet.\n\t\t\treturn NewConst(c.Value, typ)\n\t\t}\n\t\t// Can we always convert from zero value without panicking?\n\t\tconst mayPanic = sliceToArray | sliceToArrayPtr\n\t\tif c.Value == nil && classifications&mayPanic == 0 {\n\t\t\treturn NewConst(nil, typ)\n\t\t}\n\n\t\t// We're converting from constant to non-constant type,\n\t\t// e.g. string -> []byte/[]rune.\n\t}\n\n\tswitch classifications {\n\tcase changeType: // representation-preserving change\n\t\tc := &ChangeType{X: val}\n\t\tc.setType(typ)\n\t\treturn f.emit(c)\n\n\tcase sliceToArrayPtr, sliceTo0ArrayPtr: // slice to array pointer\n\t\tc := &SliceToArrayPointer{X: val}\n\t\tc.setType(typ)\n\t\treturn f.emit(c)\n\n\tcase sliceToArray: // slice to arrays (not zero-length)\n\t\tptype := types.NewPointer(typ)\n\t\tp := &SliceToArrayPointer{X: val}\n\t\tp.setType(ptype)\n\t\tx := f.emit(p)\n\t\tunOp := &UnOp{Op: token.MUL, X: x}\n\t\tunOp.setType(typ)\n\t\treturn f.emit(unOp)\n\n\tcase sliceTo0Array: // slice to zero-length arrays (constant)\n\t\treturn zeroConst(typ)\n\n\tcase convert: // representation-changing conversion\n\t\tc := &Convert{X: val}\n\t\tc.setType(typ)\n\t\treturn f.emit(c)\n\n\tdefault: // The conversion represents a cross product.\n\t\tc := &MultiConvert{X: val, from: t_src, to: typ}\n\t\tc.setType(typ)\n\t\treturn f.emit(c)\n\t}\n}\n\n// emitTypeCoercion emits to f code to coerce the type of a\n// Value v to exactly type typ, and returns the coerced value.\n//\n// Requires that coercing v.Typ() to typ is a value preserving change.\n//\n// Currently used only when v.Type() is a type instance of typ or vice versa.\n// A type v is a type instance of a type t if there exists a\n// type parameter substitution σ s.t. σ(v) == t. Example:\n//\n//\tσ(func(T) T) == func(int) int for σ == [T ↦ int]\n//\n// This happens in instantiation wrappers for conversion\n// from an instantiation to a parameterized type (and vice versa)\n// with σ substituting f.typeparams by f.typeargs.\nfunc emitTypeCoercion(f *Function, v Value, typ types.Type) Value {\n\tif types.Identical(v.Type(), typ) {\n\t\treturn v // no coercion needed\n\t}\n\t// TODO(taking): for instances should we record which side is the instance?\n\tc := &ChangeType{\n\t\tX: v,\n\t}\n\tc.setType(typ)\n\tf.emit(c)\n\treturn c\n}\n\n// emitStore emits to f an instruction to store value val at location\n// addr, applying implicit conversions as required by assignability rules.\nfunc emitStore(f *Function, addr, val Value, pos token.Pos) *Store {\n\ttyp := typeparams.MustDeref(addr.Type())\n\ts := &Store{\n\t\tAddr: addr,\n\t\tVal:  emitConv(f, val, typ),\n\t\tpos:  pos,\n\t}\n\tf.emit(s)\n\treturn s\n}\n\n// emitJump emits to f a jump to target, and updates the control-flow graph.\n// Postcondition: f.currentBlock is nil.\nfunc emitJump(f *Function, target *BasicBlock) {\n\tb := f.currentBlock\n\tb.emit(new(Jump))\n\taddEdge(b, target)\n\tf.currentBlock = nil\n}\n\n// emitIf emits to f a conditional jump to tblock or fblock based on\n// cond, and updates the control-flow graph.\n// Postcondition: f.currentBlock is nil.\nfunc emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {\n\tb := f.currentBlock\n\tb.emit(&If{Cond: cond})\n\taddEdge(b, tblock)\n\taddEdge(b, fblock)\n\tf.currentBlock = nil\n}\n\n// emitExtract emits to f an instruction to extract the index'th\n// component of tuple.  It returns the extracted value.\nfunc emitExtract(f *Function, tuple Value, index int) Value {\n\te := &Extract{Tuple: tuple, Index: index}\n\te.setType(tuple.Type().(*types.Tuple).At(index).Type())\n\treturn f.emit(e)\n}\n\n// emitTypeAssert emits to f a type assertion value := x.(t) and\n// returns the value.  x.Type() must be an interface.\nfunc emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {\n\ta := &TypeAssert{X: x, AssertedType: t}\n\ta.setPos(pos)\n\ta.setType(t)\n\treturn f.emit(a)\n}\n\n// emitTypeTest emits to f a type test value,ok := x.(t) and returns\n// a (value, ok) tuple.  x.Type() must be an interface.\nfunc emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {\n\ta := &TypeAssert{\n\t\tX:            x,\n\t\tAssertedType: t,\n\t\tCommaOk:      true,\n\t}\n\ta.setPos(pos)\n\ta.setType(types.NewTuple(\n\t\tnewVar(\"value\", t),\n\t\tvarOk,\n\t))\n\treturn f.emit(a)\n}\n\n// emitTailCall emits to f a function call in tail position.  The\n// caller is responsible for all fields of 'call' except its type.\n// Intended for wrapper methods.\n// Precondition: f does/will not use deferred procedure calls.\n// Postcondition: f.currentBlock is nil.\nfunc emitTailCall(f *Function, call *Call) {\n\ttresults := f.Signature.Results()\n\tnr := tresults.Len()\n\tif nr == 1 {\n\t\tcall.typ = tresults.At(0).Type()\n\t} else {\n\t\tcall.typ = tresults\n\t}\n\ttuple := emitCall(f, call)\n\tvar ret Return\n\tswitch nr {\n\tcase 0:\n\t\t// no-op\n\tcase 1:\n\t\tret.Results = []Value{tuple}\n\tdefault:\n\t\tfor i := range nr {\n\t\t\tv := emitExtract(f, tuple, i)\n\t\t\t// TODO(adonovan): in principle, this is required:\n\t\t\t//   v = emitConv(f, o.Type, f.Signature.Results[i].Type)\n\t\t\t// but in practice emitTailCall is only used when\n\t\t\t// the types exactly match.\n\t\t\tret.Results = append(ret.Results, v)\n\t\t}\n\t}\n\tf.emit(&ret)\n\tf.currentBlock = nil\n}\n\n// emitCall emits a call instruction. If the callee is \"no return\",\n// it also emits a panic to eliminate infeasible CFG edges.\nfunc emitCall(fn *Function, call *Call) Value {\n\tres := fn.emit(call)\n\n\tcallee := call.Call.StaticCallee()\n\tif callee != nil &&\n\t\tcallee.object != nil &&\n\t\tfn.Prog.noReturn != nil &&\n\t\tfn.Prog.noReturn(callee.object) {\n\t\t// Call cannot return. Insert a panic after it.\n\t\tfn.emit(&Panic{\n\t\t\tX:   emitConv(fn, vNoReturn, tEface),\n\t\t\tpos: call.Pos(),\n\t\t})\n\t\tfn.currentBlock = fn.newBasicBlock(\"unreachable.noreturn\")\n\t}\n\n\treturn res\n}\n\n// emitImplicitSelections emits to f code to apply the sequence of\n// implicit field selections specified by indices to base value v, and\n// returns the selected value.\n//\n// If v is the address of a struct, the result will be the address of\n// a field; if it is the value of a struct, the result will be the\n// value of a field.\nfunc emitImplicitSelections(f *Function, v Value, indices []int, pos token.Pos) Value {\n\tfor _, index := range indices {\n\t\tif isPointerCore(v.Type()) {\n\t\t\tfld := fieldOf(typeparams.MustDeref(v.Type()), index)\n\t\t\tinstr := &FieldAddr{\n\t\t\t\tX:     v,\n\t\t\t\tField: index,\n\t\t\t}\n\t\t\tinstr.setPos(pos)\n\t\t\tinstr.setType(types.NewPointer(fld.Type()))\n\t\t\tv = f.emit(instr)\n\t\t\t// Load the field's value iff indirectly embedded.\n\t\t\tif isPointerCore(fld.Type()) {\n\t\t\t\tv = emitLoad(f, v)\n\t\t\t}\n\t\t} else {\n\t\t\tfld := fieldOf(v.Type(), index)\n\t\t\tinstr := &Field{\n\t\t\t\tX:     v,\n\t\t\t\tField: index,\n\t\t\t}\n\t\t\tinstr.setPos(pos)\n\t\t\tinstr.setType(fld.Type())\n\t\t\tv = f.emit(instr)\n\t\t}\n\t}\n\treturn v\n}\n\n// emitFieldSelection emits to f code to select the index'th field of v.\n//\n// If wantAddr, the input must be a pointer-to-struct and the result\n// will be the field's address; otherwise the result will be the\n// field's value.\n// Ident id is used for position and debug info.\nfunc emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {\n\tif isPointerCore(v.Type()) {\n\t\tfld := fieldOf(typeparams.MustDeref(v.Type()), index)\n\t\tinstr := &FieldAddr{\n\t\t\tX:     v,\n\t\t\tField: index,\n\t\t}\n\t\tinstr.setPos(id.Pos())\n\t\tinstr.setType(types.NewPointer(fld.Type()))\n\t\tv = f.emit(instr)\n\t\t// Load the field's value iff we don't want its address.\n\t\tif !wantAddr {\n\t\t\tv = emitLoad(f, v)\n\t\t}\n\t} else {\n\t\tfld := fieldOf(v.Type(), index)\n\t\tinstr := &Field{\n\t\t\tX:     v,\n\t\t\tField: index,\n\t\t}\n\t\tinstr.setPos(id.Pos())\n\t\tinstr.setType(fld.Type())\n\t\tv = f.emit(instr)\n\t}\n\temitDebugRef(f, id, v, wantAddr)\n\treturn v\n}\n\n// createRecoverBlock emits to f a block of code to return after a\n// recovered panic, and sets f.Recover to it.\n//\n// If f's result parameters are named, the code loads and returns\n// their current values, otherwise it returns the zero values of their\n// type.\n//\n// Idempotent.\nfunc createRecoverBlock(f *Function) {\n\tif f.Recover != nil {\n\t\treturn // already created\n\t}\n\tsaved := f.currentBlock\n\n\tf.Recover = f.newBasicBlock(\"recover\")\n\tf.currentBlock = f.Recover\n\n\tvar results []Value\n\t// Reload NRPs to form value tuple.\n\tfor _, nr := range f.results {\n\t\tresults = append(results, emitLoad(f, nr))\n\t}\n\n\tf.emit(&Return{Results: results})\n\n\tf.currentBlock = saved\n}\n"
  },
  {
    "path": "go/ssa/example_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !android && !ios && (unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || plan9 || windows)\n\npackage ssa_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\nconst hello = `\npackage main\n\nimport \"fmt\"\n\nconst message = \"Hello, World!\"\n\nfunc main() {\n\tfmt.Println(message)\n}\n`\n\n// This program demonstrates how to run the SSA builder on a single\n// package of one or more already-parsed files. Its dependencies are\n// loaded from compiler export data. This is what you'd typically use\n// for a compiler; it does not depend on the obsolete\n// [golang.org/x/tools/go/loader].\n//\n// It shows the printed representation of packages, functions, and\n// instructions.  Within the function listing, the name of each\n// BasicBlock such as \".0.entry\" is printed left-aligned, followed by\n// the block's Instructions.\n//\n// For each instruction that defines an SSA virtual register\n// (i.e. implements Value), the type of that value is shown in the\n// right column.\n//\n// Build and run the ssadump.go program if you want a standalone tool\n// with similar functionality. It is located at\n// [golang.org/x/tools/cmd/ssadump].\n//\n// Use ssautil.BuildPackage only if you have parsed--but not\n// type-checked--syntax trees. Typically, clients already have typed\n// syntax, perhaps obtained from golang.org/x/tools/go/packages.\n// In that case, see the other examples for simpler approaches.\nfunc Example_buildPackage() {\n\t// Parse the source files.\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", hello, parser.ParseComments)\n\tif err != nil {\n\t\tfmt.Print(err) // parse error\n\t\treturn\n\t}\n\tfiles := []*ast.File{f}\n\n\t// Create the type-checker's package.\n\tpkg := types.NewPackage(\"hello\", \"\")\n\n\t// Type-check the package, load dependencies.\n\t// Create and build the SSA program.\n\thello, _, err := ssautil.BuildPackage(\n\t\t&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)\n\tif err != nil {\n\t\tfmt.Print(err) // type error in some package\n\t\treturn\n\t}\n\n\t// Print out the package.\n\thello.WriteTo(os.Stdout)\n\n\t// Print out the package-level functions.\n\thello.Func(\"init\").WriteTo(os.Stdout)\n\thello.Func(\"main\").WriteTo(os.Stdout)\n\n\t// Output:\n\t//\n\t// package hello:\n\t//   func  init       func()\n\t//   var   init$guard bool\n\t//   func  main       func()\n\t//   const message    message = \"Hello, World!\":untyped string\n\t//\n\t// # Name: hello.init\n\t// # Package: hello\n\t// # Synthetic: package initializer\n\t// func init():\n\t// 0:                                                                entry P:0 S:2\n\t// \tt0 = *init$guard                                                   bool\n\t// \tif t0 goto 2 else 1\n\t// 1:                                                    init.start P:1 S:1 idom:0\n\t// \t*init$guard = true:bool\n\t// \tt1 = fmt.init()                                                      ()\n\t// \tjump 2\n\t// 2:                                                     init.done P:2 S:0 idom:0\n\t// \treturn\n\t//\n\t// # Name: hello.main\n\t// # Package: hello\n\t// # Location: hello.go:8:6\n\t// func main():\n\t// 0:                                                                entry P:0 S:0\n\t// \tt0 = new [1]any (varargs)                                       *[1]any\n\t// \tt1 = &t0[0:int]                                                    *any\n\t// \tt2 = make any <- string (\"Hello, World!\":string)                    any\n\t// \t*t1 = t2\n\t// \tt3 = slice t0[:]                                                  []any\n\t// \tt4 = fmt.Println(t3...)                              (n int, err error)\n\t// \treturn\n}\n\n// This example builds SSA code for a set of packages using the\n// [golang.org/x/tools/go/packages] API. This is what you would typically use for a\n// analysis capable of operating on a single package.\nfunc Example_loadPackages() {\n\t// Load, parse, and type-check the initial packages.\n\tcfg := &packages.Config{Mode: packages.LoadSyntax}\n\tinitial, err := packages.Load(cfg, \"fmt\", \"net/http\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Stop if any package had errors.\n\t// This step is optional; without it, the next step\n\t// will create SSA for only a subset of packages.\n\tif packages.PrintErrors(initial) > 0 {\n\t\tlog.Fatalf(\"packages contain errors\")\n\t}\n\n\t// Create SSA packages for all well-typed packages.\n\tprog, pkgs := ssautil.Packages(initial, ssa.PrintPackages)\n\t_ = prog\n\n\t// Build SSA code for the well-typed initial packages.\n\tfor _, p := range pkgs {\n\t\tif p != nil {\n\t\t\tp.Build()\n\t\t}\n\t}\n}\n\n// This example builds SSA code for a set of packages plus all their dependencies,\n// using the [golang.org/x/tools/go/packages] API.\n// This is what you'd typically use for a whole-program analysis.\nfunc Example_loadWholeProgram() {\n\t// Load, parse, and type-check the whole program.\n\tcfg := packages.Config{Mode: packages.LoadAllSyntax}\n\tinitial, err := packages.Load(&cfg, \"fmt\", \"net/http\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Create SSA packages for well-typed packages and their dependencies.\n\tprog, pkgs := ssautil.AllPackages(initial, ssa.PrintPackages|ssa.InstantiateGenerics)\n\t_ = pkgs\n\n\t// Build SSA code for the whole program.\n\tprog.Build()\n}\n"
  },
  {
    "path": "go/ssa/func.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file implements the Function type.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"iter\"\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// Like ObjectOf, but panics instead of returning nil.\n// Only valid during f's create and build phases.\nfunc (f *Function) objectOf(id *ast.Ident) types.Object {\n\tif o := f.info.ObjectOf(id); o != nil {\n\t\treturn o\n\t}\n\tpanic(fmt.Sprintf(\"no types.Object for ast.Ident %s @ %s\",\n\t\tid.Name, f.Prog.Fset.Position(id.Pos())))\n}\n\n// Like TypeOf, but panics instead of returning nil.\n// Only valid during f's create and build phases.\nfunc (f *Function) typeOf(e ast.Expr) types.Type {\n\tif T := f.info.TypeOf(e); T != nil {\n\t\treturn f.typ(T)\n\t}\n\tpanic(fmt.Sprintf(\"no type for %T @ %s\", e, f.Prog.Fset.Position(e.Pos())))\n}\n\n// typ is the locally instantiated type of T.\n// If f is not an instantiation, then f.typ(T)==T.\nfunc (f *Function) typ(T types.Type) types.Type {\n\treturn f.subst.typ(T)\n}\n\n// If id is an Instance, returns info.Instances[id].Type.\n// Otherwise returns f.typeOf(id).\nfunc (f *Function) instanceType(id *ast.Ident) types.Type {\n\tif t, ok := f.info.Instances[id]; ok {\n\t\treturn t.Type\n\t}\n\treturn f.typeOf(id)\n}\n\n// selection returns a *selection corresponding to f.info.Selections[selector]\n// with potential updates for type substitution.\nfunc (f *Function) selection(selector *ast.SelectorExpr) *selection {\n\tsel := f.info.Selections[selector]\n\tif sel == nil {\n\t\treturn nil\n\t}\n\n\tswitch sel.Kind() {\n\tcase types.MethodExpr, types.MethodVal:\n\t\tif recv := f.typ(sel.Recv()); recv != sel.Recv() {\n\t\t\t// recv changed during type substitution.\n\t\t\tpkg := f.declaredPackage().Pkg\n\t\t\tobj, index, indirect := types.LookupFieldOrMethod(recv, true, pkg, sel.Obj().Name())\n\n\t\t\t// sig replaces sel.Type(). See (types.Selection).Typ() for details.\n\t\t\tsig := obj.Type().(*types.Signature)\n\t\t\tsig = changeRecv(sig, newVar(sig.Recv().Name(), recv))\n\t\t\tif sel.Kind() == types.MethodExpr {\n\t\t\t\tsig = recvAsFirstArg(sig)\n\t\t\t}\n\t\t\treturn &selection{\n\t\t\t\tkind:     sel.Kind(),\n\t\t\t\trecv:     recv,\n\t\t\t\ttyp:      sig,\n\t\t\t\tobj:      obj,\n\t\t\t\tindex:    index,\n\t\t\t\tindirect: indirect,\n\t\t\t}\n\t\t}\n\t}\n\treturn toSelection(sel)\n}\n\n// Destinations associated with unlabelled for/switch/select stmts.\n// We push/pop one of these as we enter/leave each construct and for\n// each BranchStmt we scan for the innermost target of the right type.\ntype targets struct {\n\ttail         *targets // rest of stack\n\t_break       *BasicBlock\n\t_continue    *BasicBlock\n\t_fallthrough *BasicBlock\n}\n\n// Destinations associated with a labelled block.\n// We populate these as labels are encountered in forward gotos or\n// labelled statements.\n// Forward gotos are resolved once it is known which statement they\n// are associated with inside the Function.\ntype lblock struct {\n\tlabel     *types.Label // Label targeted by the blocks.\n\tresolved  bool         // _goto block encountered (back jump or resolved fwd jump)\n\t_goto     *BasicBlock\n\t_break    *BasicBlock\n\t_continue *BasicBlock\n}\n\n// label returns the symbol denoted by a label identifier.\n//\n// label should be a non-blank identifier (label.Name != \"_\").\nfunc (f *Function) label(label *ast.Ident) *types.Label {\n\treturn f.objectOf(label).(*types.Label)\n}\n\n// lblockOf returns the branch target associated with the\n// specified label, creating it if needed.\nfunc (f *Function) lblockOf(label *types.Label) *lblock {\n\tlb := f.lblocks[label]\n\tif lb == nil {\n\t\tlb = &lblock{\n\t\t\tlabel: label,\n\t\t\t_goto: f.newBasicBlock(label.Name()),\n\t\t}\n\t\tif f.lblocks == nil {\n\t\t\tf.lblocks = make(map[*types.Label]*lblock)\n\t\t}\n\t\tf.lblocks[label] = lb\n\t}\n\treturn lb\n}\n\n// labelledBlock searches f for the block of the specified label.\n//\n// If f is a yield function, it additionally searches ancestor Functions\n// corresponding to enclosing range-over-func statements within the\n// same source function, so the returned block may belong to a different Function.\nfunc labelledBlock(f *Function, label *types.Label, tok token.Token) *BasicBlock {\n\tif lb := f.lblocks[label]; lb != nil {\n\t\tvar block *BasicBlock\n\t\tswitch tok {\n\t\tcase token.BREAK:\n\t\t\tblock = lb._break\n\t\tcase token.CONTINUE:\n\t\t\tblock = lb._continue\n\t\tcase token.GOTO:\n\t\t\tblock = lb._goto\n\t\t}\n\t\tif block != nil {\n\t\t\treturn block\n\t\t}\n\t}\n\t// Search ancestors if this is a yield function.\n\tif f.jump != nil {\n\t\treturn labelledBlock(f.parent, label, tok)\n\t}\n\treturn nil\n}\n\n// targetedBlock looks for the nearest block in f.targets\n// (and f's ancestors) that matches tok's type, and returns\n// the block and function it was found in.\nfunc targetedBlock(f *Function, tok token.Token) *BasicBlock {\n\tif f == nil {\n\t\treturn nil\n\t}\n\tfor t := f.targets; t != nil; t = t.tail {\n\t\tvar block *BasicBlock\n\t\tswitch tok {\n\t\tcase token.BREAK:\n\t\t\tblock = t._break\n\t\tcase token.CONTINUE:\n\t\t\tblock = t._continue\n\t\tcase token.FALLTHROUGH:\n\t\t\tblock = t._fallthrough\n\t\t}\n\t\tif block != nil {\n\t\t\treturn block\n\t\t}\n\t}\n\t// Search f's ancestors (in case f is a yield function).\n\treturn targetedBlock(f.parent, tok)\n}\n\n// instrs returns an iterator that returns each reachable instruction of the SSA function.\nfunc (f *Function) instrs() iter.Seq[Instruction] {\n\treturn func(yield func(i Instruction) bool) {\n\t\tfor _, block := range f.Blocks {\n\t\t\tfor _, instr := range block.Instrs {\n\t\t\t\tif !yield(instr) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// addResultVar adds a result for a variable v to f.results and v to f.returnVars.\nfunc (f *Function) addResultVar(v *types.Var) {\n\tresult := emitLocalVar(f, v)\n\tf.results = append(f.results, result)\n\tf.returnVars = append(f.returnVars, v)\n}\n\n// addParamVar adds a parameter to f.Params.\nfunc (f *Function) addParamVar(v *types.Var) *Parameter {\n\tname := v.Name()\n\tif name == \"\" {\n\t\tname = fmt.Sprintf(\"arg%d\", len(f.Params))\n\t}\n\tparam := &Parameter{\n\t\tname:   name,\n\t\tobject: v,\n\t\ttyp:    f.typ(v.Type()),\n\t\tparent: f,\n\t}\n\tf.Params = append(f.Params, param)\n\treturn param\n}\n\n// addSpilledParam declares a parameter that is pre-spilled to the\n// stack; the function body will load/store the spilled location.\n// Subsequent lifting will eliminate spills where possible.\nfunc (f *Function) addSpilledParam(obj *types.Var) {\n\tparam := f.addParamVar(obj)\n\tspill := emitLocalVar(f, obj)\n\tf.emit(&Store{Addr: spill, Val: param})\n}\n\n// startBody initializes the function prior to generating SSA code for its body.\n// Precondition: f.Type() already set.\nfunc (f *Function) startBody() {\n\tf.currentBlock = f.newBasicBlock(\"entry\")\n\tf.vars = make(map[*types.Var]Value) // needed for some synthetics, e.g. init\n}\n\n// createSyntacticParams populates f.Params and generates code (spills\n// and named result locals) for all the parameters declared in the\n// syntax.  In addition it populates the f.objects mapping.\n//\n// Preconditions:\n// f.startBody() was called. f.info != nil.\n// Postcondition:\n// len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)\nfunc (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {\n\t// Receiver (at most one inner iteration).\n\tif recv != nil {\n\t\tfor _, field := range recv.List {\n\t\t\tfor _, n := range field.Names {\n\t\t\t\tf.addSpilledParam(identVar(f, n))\n\t\t\t}\n\t\t\t// Anonymous receiver?  No need to spill.\n\t\t\tif field.Names == nil {\n\t\t\t\tf.addParamVar(f.Signature.Recv())\n\t\t\t}\n\t\t}\n\t}\n\n\t// Parameters.\n\tif functype.Params != nil {\n\t\tn := len(f.Params) // 1 if has recv, 0 otherwise\n\t\tfor _, field := range functype.Params.List {\n\t\t\tfor _, n := range field.Names {\n\t\t\t\tf.addSpilledParam(identVar(f, n))\n\t\t\t}\n\t\t\t// Anonymous parameter?  No need to spill.\n\t\t\tif field.Names == nil {\n\t\t\t\tf.addParamVar(f.Signature.Params().At(len(f.Params) - n))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Results.\n\tif functype.Results != nil {\n\t\tfor _, field := range functype.Results.List {\n\t\t\t// Implicit \"var\" decl of locals for named results.\n\t\t\tfor _, n := range field.Names {\n\t\t\t\tv := identVar(f, n)\n\t\t\t\tf.addResultVar(v)\n\t\t\t}\n\t\t\t// Implicit \"var\" decl of local for an unnamed result.\n\t\t\tif field.Names == nil {\n\t\t\t\tv := f.Signature.Results().At(len(f.results))\n\t\t\t\tf.addResultVar(v)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// createDeferStack initializes fn.deferstack to local variable\n// initialized to a ssa:deferstack() call.\nfunc (fn *Function) createDeferStack() {\n\t// Each syntactic function makes a call to ssa:deferstack,\n\t// which is spilled to a local. Unused ones are later removed.\n\tfn.deferstack = newVar(\"defer$stack\", tDeferStack)\n\tcall := &Call{Call: CallCommon{Value: vDeferStack}}\n\tcall.setType(tDeferStack)\n\tdeferstack := fn.emit(call)\n\tspill := emitLocalVar(fn, fn.deferstack)\n\temitStore(fn, spill, deferstack, token.NoPos)\n}\n\ntype setNumable interface {\n\tsetNum(int)\n}\n\n// numberRegisters assigns numbers to all SSA registers\n// (value-defining Instructions) in f, to aid debugging.\n// (Non-Instruction Values are named at construction.)\nfunc numberRegisters(f *Function) {\n\tv := 0\n\tfor _, b := range f.Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\tswitch instr.(type) {\n\t\t\tcase Value:\n\t\t\t\tinstr.(setNumable).setNum(v)\n\t\t\t\tv++\n\t\t\t}\n\t\t}\n\t}\n}\n\n// buildReferrers populates the def/use information in all non-nil\n// Value.Referrers slice.\n// Precondition: all such slices are initially empty.\nfunc buildReferrers(f *Function) {\n\tvar rands []*Value\n\tfor _, b := range f.Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\trands = instr.Operands(rands[:0]) // recycle storage\n\t\t\tfor _, rand := range rands {\n\t\t\t\tif r := *rand; r != nil {\n\t\t\t\t\tif ref := r.Referrers(); ref != nil {\n\t\t\t\t\t\t*ref = append(*ref, instr)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// finishBody() finalizes the contents of the function after SSA code generation of its body.\n//\n// The function is not done being built until done() is called.\nfunc (f *Function) finishBody() {\n\tf.currentBlock = nil\n\tf.lblocks = nil\n\tf.returnVars = nil\n\tf.jump = nil\n\tf.source = nil\n\tf.exits = nil\n\n\t// Remove from f.Locals any Allocs that escape to the heap.\n\tj := 0\n\tfor _, l := range f.Locals {\n\t\tif !l.Heap {\n\t\t\tf.Locals[j] = l\n\t\t\tj++\n\t\t}\n\t}\n\t// Nil out f.Locals[j:] to aid GC.\n\tfor i := j; i < len(f.Locals); i++ {\n\t\tf.Locals[i] = nil\n\t}\n\tf.Locals = f.Locals[:j]\n\n\toptimizeBlocks(f)\n\n\tbuildReferrers(f)\n\n\tbuildDomTree(f)\n\n\tif f.Prog.mode&NaiveForm == 0 {\n\t\t// For debugging pre-state of lifting pass:\n\t\t// numberRegisters(f)\n\t\t// f.WriteTo(os.Stderr)\n\t\tlift(f)\n\t}\n\n\t// clear remaining builder state\n\tf.results = nil    // (used by lifting)\n\tf.deferstack = nil // (used by lifting)\n\tf.vars = nil       // (used by lifting)\n\n\t// clear out other function state (keep consistent with buildParamsOnly)\n\tf.subst = nil\n\n\tnumberRegisters(f) // uses f.namedRegisters\n}\n\n// done marks the building of f's SSA body complete,\n// along with any nested functions, and optionally prints them.\nfunc (f *Function) done() {\n\tassert(f.parent == nil, \"done called on an anonymous function\")\n\n\tvar visit func(*Function)\n\tvisit = func(f *Function) {\n\t\tfor _, anon := range f.AnonFuncs {\n\t\t\tvisit(anon) // anon is done building before f.\n\t\t}\n\n\t\tf.uniq = 0    // done with uniq\n\t\tf.build = nil // function is built\n\n\t\tif f.Prog.mode&PrintFunctions != 0 {\n\t\t\tprintMu.Lock()\n\t\t\tf.WriteTo(os.Stdout)\n\t\t\tprintMu.Unlock()\n\t\t}\n\n\t\tif f.Prog.mode&SanityCheckFunctions != 0 {\n\t\t\tmustSanityCheck(f, nil)\n\t\t}\n\t}\n\tvisit(f)\n}\n\n// removeNilBlocks eliminates nils from f.Blocks and updates each\n// BasicBlock.Index.  Use this after any pass that may delete blocks.\nfunc (f *Function) removeNilBlocks() {\n\tj := 0\n\tfor _, b := range f.Blocks {\n\t\tif b != nil {\n\t\t\tb.Index = j\n\t\t\tf.Blocks[j] = b\n\t\t\tj++\n\t\t}\n\t}\n\t// Nil out f.Blocks[j:] to aid GC.\n\tfor i := j; i < len(f.Blocks); i++ {\n\t\tf.Blocks[i] = nil\n\t}\n\tf.Blocks = f.Blocks[:j]\n}\n\n// SetDebugMode sets the debug mode for package pkg.  If true, all its\n// functions will include full debug info.  This greatly increases the\n// size of the instruction stream, and causes Functions to depend upon\n// the ASTs, potentially keeping them live in memory for longer.\nfunc (pkg *Package) SetDebugMode(debug bool) {\n\tpkg.debug = debug\n}\n\n// debugInfo reports whether debug info is wanted for this function.\nfunc (f *Function) debugInfo() bool {\n\t// debug info for instantiations follows the debug info of their origin.\n\tp := f.declaredPackage()\n\treturn p != nil && p.debug\n}\n\n// lookup returns the address of the named variable identified by obj\n// that is local to function f or one of its enclosing functions.\n// If escaping, the reference comes from a potentially escaping pointer\n// expression and the referent must be heap-allocated.\n// We assume the referent is a *Alloc or *Phi.\n// (The only Phis at this stage are those created directly by go1.22 \"for\" loops.)\nfunc (f *Function) lookup(obj *types.Var, escaping bool) Value {\n\tif v, ok := f.vars[obj]; ok {\n\t\tif escaping {\n\t\t\tswitch v := v.(type) {\n\t\t\tcase *Alloc:\n\t\t\t\tv.Heap = true\n\t\t\tcase *Phi:\n\t\t\t\tfor _, edge := range v.Edges {\n\t\t\t\t\tif alloc, ok := edge.(*Alloc); ok {\n\t\t\t\t\t\talloc.Heap = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn v // function-local var (address)\n\t}\n\n\t// Definition must be in an enclosing function;\n\t// plumb it through intervening closures.\n\tif f.parent == nil {\n\t\tpanic(\"no ssa.Value for \" + obj.String())\n\t}\n\touter := f.parent.lookup(obj, true) // escaping\n\tv := &FreeVar{\n\t\tname:   obj.Name(),\n\t\ttyp:    outer.Type(),\n\t\tpos:    outer.Pos(),\n\t\touter:  outer,\n\t\tparent: f,\n\t}\n\tf.vars[obj] = v\n\tf.FreeVars = append(f.FreeVars, v)\n\treturn v\n}\n\n// emit emits the specified instruction to function f.\nfunc (f *Function) emit(instr Instruction) Value {\n\treturn f.currentBlock.emit(instr)\n}\n\n// RelString returns the full name of this function, qualified by\n// package name, receiver type, etc.\n//\n// The specific formatting rules are not guaranteed and may change.\n//\n// Examples:\n//\n//\t\"math.IsNaN\"                  // a package-level function\n//\t\"(*bytes.Buffer).Bytes\"       // a declared method or a wrapper\n//\t\"(*bytes.Buffer).Bytes$thunk\" // thunk (func wrapping method; receiver is param 0)\n//\t\"(*bytes.Buffer).Bytes$bound\" // bound (func wrapping method; receiver supplied by closure)\n//\t\"main.main$1\"                 // an anonymous function in main\n//\t\"main.init#1\"                 // a declared init function\n//\t\"main.init\"                   // the synthesized package initializer\n//\n// When these functions are referred to from within the same package\n// (i.e. from == f.Pkg.Object), they are rendered without the package path.\n// For example: \"IsNaN\", \"(*Buffer).Bytes\", etc.\n//\n// All non-synthetic functions have distinct package-qualified names.\n// (But two methods may have the same name \"(T).f\" if one is a synthetic\n// wrapper promoting a non-exported method \"f\" from another package; in\n// that case, the strings are equal but the identifiers \"f\" are distinct.)\nfunc (f *Function) RelString(from *types.Package) string {\n\t// Anonymous?\n\tif f.parent != nil {\n\t\t// An anonymous function's Name() looks like \"parentName$1\",\n\t\t// but its String() should include the type/package/etc.\n\t\tparent := f.parent.RelString(from)\n\t\tfor i, anon := range f.parent.AnonFuncs {\n\t\t\tif anon == f {\n\t\t\t\treturn fmt.Sprintf(\"%s$%d\", parent, 1+i)\n\t\t\t}\n\t\t}\n\n\t\treturn f.name // should never happen\n\t}\n\n\t// Method (declared or wrapper)?\n\tif recv := f.Signature.Recv(); recv != nil {\n\t\treturn f.relMethod(from, recv.Type())\n\t}\n\n\t// Thunk?\n\tif f.method != nil {\n\t\treturn f.relMethod(from, f.method.recv)\n\t}\n\n\t// Bound?\n\tif len(f.FreeVars) == 1 && strings.HasSuffix(f.name, \"$bound\") {\n\t\treturn f.relMethod(from, f.FreeVars[0].Type())\n\t}\n\n\t// Package-level function?\n\t// Prefix with package name for cross-package references only.\n\tif p := f.relPkg(); p != nil && p != from {\n\t\treturn fmt.Sprintf(\"%s.%s\", p.Path(), f.name)\n\t}\n\n\t// Unknown.\n\treturn f.name\n}\n\nfunc (f *Function) relMethod(from *types.Package, recv types.Type) string {\n\treturn fmt.Sprintf(\"(%s).%s\", relType(recv, from), f.name)\n}\n\n// writeSignature writes to buf the signature sig in declaration syntax.\nfunc writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature) {\n\tbuf.WriteString(\"func \")\n\tif recv := sig.Recv(); recv != nil {\n\t\tbuf.WriteString(\"(\")\n\t\tif name := recv.Name(); name != \"\" {\n\t\t\tbuf.WriteString(name)\n\t\t\tbuf.WriteString(\" \")\n\t\t}\n\t\ttypes.WriteType(buf, recv.Type(), types.RelativeTo(from))\n\t\tbuf.WriteString(\") \")\n\t}\n\tbuf.WriteString(name)\n\ttypes.WriteSignature(buf, sig, types.RelativeTo(from))\n}\n\n// declaredPackage returns the package fn is declared in or nil if the\n// function is not declared in a package.\nfunc (fn *Function) declaredPackage() *Package {\n\tswitch {\n\tcase fn.Pkg != nil:\n\t\treturn fn.Pkg // non-generic function  (does that follow??)\n\tcase fn.topLevelOrigin != nil:\n\t\treturn fn.topLevelOrigin.Pkg // instance of a named generic function\n\tcase fn.parent != nil:\n\t\treturn fn.parent.declaredPackage() // instance of an anonymous [generic] function\n\tdefault:\n\t\treturn nil // function is not declared in a package, e.g. a wrapper.\n\t}\n}\n\n// relPkg returns types.Package fn is printed in relationship to.\nfunc (fn *Function) relPkg() *types.Package {\n\tif p := fn.declaredPackage(); p != nil {\n\t\treturn p.Pkg\n\t}\n\treturn nil\n}\n\nvar _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer\n\nfunc (f *Function) WriteTo(w io.Writer) (int64, error) {\n\tvar buf bytes.Buffer\n\tWriteFunction(&buf, f)\n\tn, err := w.Write(buf.Bytes())\n\treturn int64(n), err\n}\n\n// WriteFunction writes to buf a human-readable \"disassembly\" of f.\nfunc WriteFunction(buf *bytes.Buffer, f *Function) {\n\tfmt.Fprintf(buf, \"# Name: %s\\n\", f.String())\n\tif f.Pkg != nil {\n\t\tfmt.Fprintf(buf, \"# Package: %s\\n\", f.Pkg.Pkg.Path())\n\t}\n\tif syn := f.Synthetic; syn != \"\" {\n\t\tfmt.Fprintln(buf, \"# Synthetic:\", syn)\n\t}\n\tif pos := f.Pos(); pos.IsValid() {\n\t\tfmt.Fprintf(buf, \"# Location: %s\\n\", f.Prog.Fset.Position(pos))\n\t}\n\n\tif f.parent != nil {\n\t\tfmt.Fprintf(buf, \"# Parent: %s\\n\", f.parent.Name())\n\t}\n\n\tif f.Recover != nil {\n\t\tfmt.Fprintf(buf, \"# Recover: %s\\n\", f.Recover)\n\t}\n\n\tfrom := f.relPkg()\n\n\tif f.FreeVars != nil {\n\t\tbuf.WriteString(\"# Free variables:\\n\")\n\t\tfor i, fv := range f.FreeVars {\n\t\t\tfmt.Fprintf(buf, \"# % 3d:\\t%s %s\\n\", i, fv.Name(), relType(fv.Type(), from))\n\t\t}\n\t}\n\n\tif len(f.Locals) > 0 {\n\t\tbuf.WriteString(\"# Locals:\\n\")\n\t\tfor i, l := range f.Locals {\n\t\t\tfmt.Fprintf(buf, \"# % 3d:\\t%s %s\\n\", i, l.Name(), relType(typeparams.MustDeref(l.Type()), from))\n\t\t}\n\t}\n\twriteSignature(buf, from, f.Name(), f.Signature)\n\tbuf.WriteString(\":\\n\")\n\n\tif f.Blocks == nil {\n\t\tbuf.WriteString(\"\\t(external)\\n\")\n\t}\n\n\t// NB. column calculations are confused by non-ASCII\n\t// characters and assume 8-space tabs.\n\tconst punchcard = 80 // for old time's sake.\n\tconst tabwidth = 8\n\tfor _, b := range f.Blocks {\n\t\tif b == nil {\n\t\t\t// Corrupt CFG.\n\t\t\tfmt.Fprintf(buf, \".nil:\\n\")\n\t\t\tcontinue\n\t\t}\n\t\tn, _ := fmt.Fprintf(buf, \"%d:\", b.Index)\n\t\t// (|predecessors|, |successors|, immediate dominator)\n\t\tbmsg := fmt.Sprintf(\"%s P:%d S:%d\", b.Comment, len(b.Preds), len(b.Succs))\n\t\tif b.Idom() != nil {\n\t\t\tbmsg = fmt.Sprintf(\"%s idom:%d\", bmsg, b.Idom().Index)\n\t\t}\n\t\tfmt.Fprintf(buf, \"%*s%s\\n\", punchcard-1-n-len(bmsg), \"\", bmsg)\n\n\t\tif false { // CFG debugging\n\t\t\tfmt.Fprintf(buf, \"\\t# CFG: %s --> %s --> %s\\n\", b.Preds, b, b.Succs)\n\t\t}\n\t\tfor _, instr := range b.Instrs {\n\t\t\tbuf.WriteString(\"\\t\")\n\t\t\tswitch v := instr.(type) {\n\t\t\tcase Value:\n\t\t\t\tl := punchcard - tabwidth\n\t\t\t\t// Left-align the instruction.\n\t\t\t\tif name := v.Name(); name != \"\" {\n\t\t\t\t\tn, _ := fmt.Fprintf(buf, \"%s = \", name)\n\t\t\t\t\tl -= n\n\t\t\t\t}\n\t\t\t\tn, _ := buf.WriteString(instr.String())\n\t\t\t\tl -= n\n\t\t\t\t// Right-align the type if there's space.\n\t\t\t\tif t := v.Type(); t != nil {\n\t\t\t\t\tbuf.WriteByte(' ')\n\t\t\t\t\tts := relType(t, from)\n\t\t\t\t\tl -= len(ts) + len(\"  \") // (spaces before and after type)\n\t\t\t\t\tif l > 0 {\n\t\t\t\t\t\tfmt.Fprintf(buf, \"%*s\", l, \"\")\n\t\t\t\t\t}\n\t\t\t\t\tbuf.WriteString(ts)\n\t\t\t\t}\n\t\t\tcase nil:\n\t\t\t\t// Be robust against bad transforms.\n\t\t\t\tbuf.WriteString(\"<deleted>\")\n\t\t\tdefault:\n\t\t\t\tbuf.WriteString(instr.String())\n\t\t\t}\n\t\t\t// -mode=S: show line numbers\n\t\t\tif f.Prog.mode&LogSource != 0 {\n\t\t\t\tif pos := instr.Pos(); pos.IsValid() {\n\t\t\t\t\tfmt.Fprintf(buf, \" L%d\", f.Prog.Fset.Position(pos).Line)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuf.WriteString(\"\\n\")\n\t\t}\n\t}\n\tfmt.Fprintf(buf, \"\\n\")\n}\n\n// newBasicBlock adds to f a new basic block and returns it.  It does\n// not automatically become the current block for subsequent calls to emit.\n// comment is an optional string for more readable debugging output.\nfunc (f *Function) newBasicBlock(comment string) *BasicBlock {\n\tb := &BasicBlock{\n\t\tIndex:   len(f.Blocks),\n\t\tComment: comment,\n\t\tparent:  f,\n\t}\n\tb.Succs = b.succs2[:0]\n\tf.Blocks = append(f.Blocks, b)\n\treturn b\n}\n\n// NewFunction returns a new synthetic Function instance belonging to\n// prog, with its name and signature fields set as specified.\n//\n// The caller is responsible for initializing the remaining fields of\n// the function object, e.g. Pkg, Params, Blocks.\n//\n// It is practically impossible for clients to construct well-formed\n// SSA functions/packages/programs directly, so we assume this is the\n// job of the Builder alone.  NewFunction exists to provide clients a\n// little flexibility.  For example, analysis tools may wish to\n// construct fake Functions for the root of the callgraph, a fake\n// \"reflect\" package, etc.\n//\n// TODO(adonovan): think harder about the API here.\nfunc (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {\n\treturn &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}\n}\n\n// Syntax returns the function's syntax (*ast.Func{Decl,Lit})\n// if it was produced from syntax or an *ast.RangeStmt if\n// it is a range-over-func yield function.\nfunc (f *Function) Syntax() ast.Node { return f.syntax }\n\n// identVar returns the variable defined by id.\nfunc identVar(fn *Function, id *ast.Ident) *types.Var {\n\treturn fn.info.Defs[id].(*types.Var)\n}\n\n// unique returns a unique positive int within the source tree of f.\n// The source tree of f includes all of f's ancestors by parent and all\n// of the AnonFuncs contained within these.\nfunc unique(f *Function) int64 {\n\tf.uniq++\n\treturn f.uniq\n}\n\n// exit is a change of control flow going from a range-over-func\n// yield function to an ancestor function caused by a break, continue,\n// goto, or return statement.\n//\n// There are 3 types of exits:\n// * return from the source function (from ReturnStmt),\n// * jump to a block (from break and continue statements [labelled/unlabelled]),\n// * go to a label (from goto statements).\n//\n// As the builder does one pass over the ast, it is unclear whether\n// a forward goto statement will leave a range-over-func body.\n// The function being exited to is unresolved until the end\n// of building the range-over-func body.\ntype exit struct {\n\tid   int64     // unique value for exit within from and to\n\tfrom *Function // the function the exit starts from\n\tto   *Function // the function being exited to (nil if unresolved)\n\tpos  token.Pos\n\n\tblock *BasicBlock  // basic block within to being jumped to.\n\tlabel *types.Label // forward label being jumped to via goto.\n\t// block == nil && label == nil => return\n}\n\n// storeVar emits to function f code to store a value v to a *types.Var x.\nfunc storeVar(f *Function, x *types.Var, v Value, pos token.Pos) {\n\temitStore(f, f.lookup(x, true), v, pos)\n}\n\n// labelExit creates a new exit to a yield fn to exit the function using a label.\nfunc labelExit(fn *Function, label *types.Label, pos token.Pos) *exit {\n\te := &exit{\n\t\tid:    unique(fn),\n\t\tfrom:  fn,\n\t\tto:    nil,\n\t\tpos:   pos,\n\t\tlabel: label,\n\t}\n\tfn.exits = append(fn.exits, e)\n\treturn e\n}\n\n// blockExit creates a new exit to a yield fn that jumps to a basic block.\nfunc blockExit(fn *Function, block *BasicBlock, pos token.Pos) *exit {\n\te := &exit{\n\t\tid:    unique(fn),\n\t\tfrom:  fn,\n\t\tto:    block.parent,\n\t\tpos:   pos,\n\t\tblock: block,\n\t}\n\tfn.exits = append(fn.exits, e)\n\treturn e\n}\n\n// returnExit creates a new exit to a yield fn that returns the source function.\nfunc returnExit(fn *Function, pos token.Pos) *exit {\n\te := &exit{\n\t\tid:   unique(fn),\n\t\tfrom: fn,\n\t\tto:   fn.source,\n\t\tpos:  pos,\n\t}\n\tfn.exits = append(fn.exits, e)\n\treturn e\n}\n"
  },
  {
    "path": "go/ssa/instantiate.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"slices\"\n\t\"sync\"\n)\n\n// A generic records information about a generic origin function,\n// including a cache of existing instantiations.\ntype generic struct {\n\tinstancesMu sync.Mutex\n\tinstances   map[*typeList]*Function // canonical type arguments to an instance.\n}\n\n// instance returns a Function that is the instantiation of generic\n// origin function fn with the type arguments targs.\n//\n// Any created instance is added to cr.\n//\n// Acquires fn.generic.instancesMu.\nfunc (fn *Function) instance(targs []types.Type, b *builder) *Function {\n\tkey := fn.Prog.canon.List(targs)\n\n\tgen := fn.generic\n\n\tgen.instancesMu.Lock()\n\tdefer gen.instancesMu.Unlock()\n\tinst, ok := gen.instances[key]\n\tif !ok {\n\t\tinst = createInstance(fn, targs)\n\t\tinst.buildshared = b.shared()\n\t\tb.enqueue(inst)\n\n\t\tif gen.instances == nil {\n\t\t\tgen.instances = make(map[*typeList]*Function)\n\t\t}\n\t\tgen.instances[key] = inst\n\t} else {\n\t\tb.waitForSharedFunction(inst)\n\t}\n\treturn inst\n}\n\n// createInstance returns the instantiation of generic function fn using targs.\n//\n// Requires fn.generic.instancesMu.\nfunc createInstance(fn *Function, targs []types.Type) *Function {\n\tprog := fn.Prog\n\n\t// Compute signature.\n\tvar sig *types.Signature\n\tvar obj *types.Func\n\tif recv := fn.Signature.Recv(); recv != nil {\n\t\t// method\n\t\tobj = prog.canon.instantiateMethod(fn.object, targs, prog.ctxt)\n\t\tsig = obj.Type().(*types.Signature)\n\t} else {\n\t\t// function\n\t\tinstSig, err := types.Instantiate(prog.ctxt, fn.Signature, targs, false)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tinstance, ok := instSig.(*types.Signature)\n\t\tif !ok {\n\t\t\tpanic(\"Instantiate of a Signature returned a non-signature\")\n\t\t}\n\t\tobj = fn.object // instantiation does not exist yet\n\t\tsig = prog.canon.Type(instance).(*types.Signature)\n\t}\n\n\t// Choose strategy (instance or wrapper).\n\tvar (\n\t\tsynthetic string\n\t\tsubst     *subster\n\t\tbuild     buildFunc\n\t)\n\tif prog.mode&InstantiateGenerics != 0 && !prog.isParameterized(targs...) {\n\t\tsynthetic = fmt.Sprintf(\"instance of %s\", fn.Name())\n\t\tif fn.syntax != nil {\n\t\t\tsubst = makeSubster(prog.ctxt, obj, fn.typeparams, targs)\n\t\t\tbuild = (*builder).buildFromSyntax\n\t\t} else {\n\t\t\tbuild = (*builder).buildParamsOnly\n\t\t}\n\t} else {\n\t\tsynthetic = fmt.Sprintf(\"instantiation wrapper of %s\", fn.Name())\n\t\tbuild = (*builder).buildInstantiationWrapper\n\t}\n\n\t/* generic instance or instantiation wrapper */\n\treturn &Function{\n\t\tname:           fmt.Sprintf(\"%s%s\", fn.Name(), targs), // may not be unique\n\t\tobject:         obj,\n\t\tSignature:      sig,\n\t\tSynthetic:      synthetic,\n\t\tsyntax:         fn.syntax,    // \\\n\t\tinfo:           fn.info,      //  } empty for non-created packages\n\t\tgoversion:      fn.goversion, // /\n\t\tbuild:          build,\n\t\ttopLevelOrigin: fn,\n\t\tpos:            obj.Pos(),\n\t\tPkg:            nil,\n\t\tProg:           fn.Prog,\n\t\ttypeparams:     fn.typeparams, // share with origin\n\t\ttypeargs:       targs,\n\t\tsubst:          subst,\n\t}\n}\n\n// isParameterized reports whether any of the specified types contains\n// a free type parameter. It is safe to call concurrently.\nfunc (prog *Program) isParameterized(ts ...types.Type) bool {\n\tprog.hasParamsMu.Lock()\n\tdefer prog.hasParamsMu.Unlock()\n\n\t// TODO(adonovan): profile. If this operation is expensive,\n\t// handle the most common but shallow cases such as T, pkg.T,\n\t// *T without consulting the cache under the lock.\n\n\treturn slices.ContainsFunc(ts, prog.hasParams.Has)\n}\n"
  },
  {
    "path": "go/ssa/instantiate_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\n// TestNeedsInstance ensures that new method instances can be created via MethodValue.\nfunc TestNeedsInstance(t *testing.T) {\n\tconst input = `\npackage p\n\nimport \"unsafe\"\n\ntype Pointer[T any] struct {\n\tv unsafe.Pointer\n}\n\nfunc (x *Pointer[T]) Load() *T {\n\treturn (*T)(LoadPointer(&x.v))\n}\n\nfunc LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)\n`\n\t// The SSA members for this package should look something like this:\n\t//      func  LoadPointer func(addr *unsafe.Pointer) (val unsafe.Pointer)\n\t//      type  Pointer     struct{v unsafe.Pointer}\n\t//        method (*Pointer[T any]) Load() *T\n\t//      func  init        func()\n\t//      var   init$guard  bool\n\n\tfor _, mode := range []ssa.BuilderMode{\n\t\tssa.SanityCheckFunctions,\n\t\tssa.SanityCheckFunctions | ssa.InstantiateGenerics,\n\t} {\n\t\tp, _ := buildPackage(t, input, mode)\n\t\tprog := p.Prog\n\n\t\tptr := p.Type(\"Pointer\").Type().(*types.Named)\n\t\tif ptr.NumMethods() != 1 {\n\t\t\tt.Fatalf(\"Expected Pointer to have 1 method. got %d\", ptr.NumMethods())\n\t\t}\n\n\t\tobj := ptr.Method(0)\n\t\tif obj.Name() != \"Load\" {\n\t\t\tt.Errorf(\"Expected Pointer to have method named 'Load'. got %q\", obj.Name())\n\t\t}\n\n\t\tmeth := prog.FuncValue(obj)\n\n\t\t// instantiateLoadMethod returns the first method (Load) of the instantiation *Pointer[T].\n\t\tinstantiateLoadMethod := func(T types.Type) *ssa.Function {\n\t\t\tptrT, err := types.Instantiate(nil, ptr, []types.Type{T}, false)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Failed to Instantiate %q by %q\", ptr, T)\n\t\t\t}\n\t\t\tmethods := types.NewMethodSet(types.NewPointer(ptrT))\n\t\t\tif methods.Len() != 1 {\n\t\t\t\tt.Fatalf(\"Expected 1 method for %q. got %d\", ptrT, methods.Len())\n\t\t\t}\n\t\t\treturn prog.MethodValue(methods.At(0))\n\t\t}\n\n\t\tintSliceTyp := types.NewSlice(types.Typ[types.Int])\n\t\tinstance := instantiateLoadMethod(intSliceTyp) // (*Pointer[[]int]).Load\n\t\tif instance.Origin() != meth {\n\t\t\tt.Errorf(\"Expected Origin of %s to be %s. got %s\", instance, meth, instance.Origin())\n\t\t}\n\t\tif len(instance.TypeArgs()) != 1 || !types.Identical(instance.TypeArgs()[0], intSliceTyp) {\n\t\t\tt.Errorf(\"Expected TypeArgs of %s to be %v. got %v\", instance, []types.Type{intSliceTyp}, instance.TypeArgs())\n\t\t}\n\n\t\t// A second request with an identical type returns the same Function.\n\t\tsecond := instantiateLoadMethod(types.NewSlice(types.Typ[types.Int]))\n\t\tif second != instance {\n\t\t\tt.Error(\"Expected second identical instantiation to be the same function\")\n\t\t}\n\n\t\t// (*Pointer[[]uint]).Load\n\t\tinst2 := instantiateLoadMethod(types.NewSlice(types.Typ[types.Uint]))\n\n\t\tif instance.Name() >= inst2.Name() {\n\t\t\tt.Errorf(\"Expected name of instance %s to be before instance %v\", instance, inst2)\n\t\t}\n\t}\n}\n\n// TestCallsToInstances checks that calles of calls to generic functions,\n// without monomorphization, are wrappers around the origin generic function.\nfunc TestCallsToInstances(t *testing.T) {\n\tconst input = `\npackage p\n\ntype I interface {\n\tFoo()\n}\n\ntype A int\nfunc (a A) Foo() {}\n\ntype J[T any] interface{ Bar() T }\ntype K[T any] struct{ J[T] }\n\nfunc Id[T any] (t T) T {\n\treturn t\n}\n\nfunc Lambda[T I]() func() func(T) {\n\treturn func() func(T) {\n\t\treturn T.Foo\n\t}\n}\n\nfunc NoOp[T any]() {}\n\nfunc Bar[T interface { Foo(); ~int | ~string }, U any] (t T, u U) {\n\tId[U](u)\n\tId[T](t)\n}\n\nfunc Make[T any]() interface{} {\n\tNoOp[K[T]]()\n\treturn nil\n}\n\nfunc entry(i int, a A) int {\n\tLambda[A]()()(a)\n\n\tx := Make[int]()\n\tif j, ok := x.(interface{ Bar() int }); ok {\n\t\tprint(j)\n\t}\n\n\tBar[A, int](a, i)\n\n\treturn Id[int](i)\n}\n`\n\tp, _ := buildPackage(t, input, ssa.SanityCheckFunctions)\n\tall := ssautil.AllFunctions(p.Prog)\n\n\tfor _, ti := range []struct {\n\t\torig         string\n\t\tinstance     string\n\t\ttparams      string\n\t\ttargs        string\n\t\tchTypeInstrs int // number of ChangeType instructions in f's body\n\t}{\n\t\t{\"Id\", \"Id[int]\", \"[T]\", \"[int]\", 2},\n\t\t{\"Lambda\", \"Lambda[p.A]\", \"[T]\", \"[p.A]\", 1},\n\t\t{\"Make\", \"Make[int]\", \"[T]\", \"[int]\", 0},\n\t\t{\"NoOp\", \"NoOp[p.K[T]]\", \"[T]\", \"[p.K[T]]\", 0},\n\t} {\n\t\ttest := ti\n\t\tt.Run(test.instance, func(t *testing.T) {\n\t\t\tf := p.Members[test.orig].(*ssa.Function)\n\t\t\tif f == nil {\n\t\t\t\tt.Fatalf(\"origin function not found\")\n\t\t\t}\n\n\t\t\tvar i *ssa.Function\n\t\t\tfor _, fn := range instancesOf(all, f) {\n\t\t\t\tif fn.Name() == test.instance {\n\t\t\t\t\ti = fn\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i == nil {\n\t\t\t\tt.Fatalf(\"instance not found\")\n\t\t\t}\n\n\t\t\t// for logging on failures\n\t\t\tvar body strings.Builder\n\t\t\ti.WriteTo(&body)\n\t\t\tt.Log(body.String())\n\n\t\t\tif len(i.Blocks) != 1 {\n\t\t\t\tt.Fatalf(\"body has more than 1 block\")\n\t\t\t}\n\n\t\t\tif instrs := changeTypeInstrs(i.Blocks[0]); instrs != test.chTypeInstrs {\n\t\t\t\tt.Errorf(\"want %v instructions; got %v\", test.chTypeInstrs, instrs)\n\t\t\t}\n\n\t\t\tif test.tparams != tparams(i) {\n\t\t\t\tt.Errorf(\"want %v type params; got %v\", test.tparams, tparams(i))\n\t\t\t}\n\n\t\t\tif test.targs != targs(i) {\n\t\t\t\tt.Errorf(\"want %v type arguments; got %v\", test.targs, targs(i))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc tparams(f *ssa.Function) string {\n\ttplist := f.TypeParams()\n\tvar tps []string\n\tfor tparam := range tplist.TypeParams() {\n\t\ttps = append(tps, tparam.String())\n\t}\n\treturn fmt.Sprint(tps)\n}\n\nfunc targs(f *ssa.Function) string {\n\tvar tas []string\n\tfor _, ta := range f.TypeArgs() {\n\t\ttas = append(tas, ta.String())\n\t}\n\treturn fmt.Sprint(tas)\n}\n\nfunc changeTypeInstrs(b *ssa.BasicBlock) int {\n\tcnt := 0\n\tfor _, i := range b.Instrs {\n\t\tif _, ok := i.(*ssa.ChangeType); ok {\n\t\t\tcnt++\n\t\t}\n\t}\n\treturn cnt\n}\n\nfunc TestInstanceUniqueness(t *testing.T) {\n\tconst input = `\npackage p\n\nfunc H[T any](t T) {\n\tprint(t)\n}\n\nfunc F[T any](t T) {\n\tH[T](t)\n\tH[T](t)\n\tH[T](t)\n}\n\nfunc G[T any](t T) {\n\tH[T](t)\n\tH[T](t)\n}\n\nfunc Foo[T any, S any](t T, s S) {\n\tFoo[S, T](s, t)\n\tFoo[T, S](t, s)\n}\n`\n\tp, _ := buildPackage(t, input, ssa.SanityCheckFunctions)\n\n\tall := ssautil.AllFunctions(p.Prog)\n\tfor _, test := range []struct {\n\t\torig      string\n\t\tinstances string\n\t}{\n\t\t{\"H\", \"[p.H[T] p.H[T]]\"},\n\t\t{\"Foo\", \"[p.Foo[S T] p.Foo[T S]]\"},\n\t} {\n\t\tt.Run(test.orig, func(t *testing.T) {\n\t\t\tf := p.Members[test.orig].(*ssa.Function)\n\t\t\tif f == nil {\n\t\t\t\tt.Fatalf(\"origin function not found\")\n\t\t\t}\n\n\t\t\tinstances := instancesOf(all, f)\n\t\t\tsort.Slice(instances, func(i, j int) bool { return instances[i].Name() < instances[j].Name() })\n\n\t\t\tif got := fmt.Sprintf(\"%v\", instances); !reflect.DeepEqual(got, test.instances) {\n\t\t\t\tt.Errorf(\"got %v instances, want %v\", got, test.instances)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// instancesOf returns a new unordered slice of all instances of the\n// specified function g in fns.\nfunc instancesOf(fns map[*ssa.Function]bool, g *ssa.Function) []*ssa.Function {\n\tvar instances []*ssa.Function\n\tfor fn := range fns {\n\t\tif fn != g && fn.Origin() == g {\n\t\t\tinstances = append(instances, fn)\n\t\t}\n\t}\n\treturn instances\n}\n"
  },
  {
    "path": "go/ssa/interp/external.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp\n\n// Emulated functions that we cannot interpret because they are\n// external or because they use \"unsafe\" or \"reflect\" operations.\n\nimport (\n\t\"bytes\"\n\t\"maps\"\n\t\"math\"\n\t\"os\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode/utf8\"\n)\n\ntype externalFn func(fr *frame, args []value) value\n\n// TODO(adonovan): fix: reflect.Value abstracts an lvalue or an\n// rvalue; Set() causes mutations that can be observed via aliases.\n// We have not captured that correctly here.\n\n// Key strings are from Function.String().\nvar externals = make(map[string]externalFn)\n\nfunc init() {\n\t// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].\n\tmaps.Copy(externals, map[string]externalFn{\n\t\t\"(reflect.Value).Bool\":            ext۰reflect۰Value۰Bool,\n\t\t\"(reflect.Value).CanAddr\":         ext۰reflect۰Value۰CanAddr,\n\t\t\"(reflect.Value).CanInterface\":    ext۰reflect۰Value۰CanInterface,\n\t\t\"(reflect.Value).Elem\":            ext۰reflect۰Value۰Elem,\n\t\t\"(reflect.Value).Field\":           ext۰reflect۰Value۰Field,\n\t\t\"(reflect.Value).Float\":           ext۰reflect۰Value۰Float,\n\t\t\"(reflect.Value).Index\":           ext۰reflect۰Value۰Index,\n\t\t\"(reflect.Value).Int\":             ext۰reflect۰Value۰Int,\n\t\t\"(reflect.Value).Interface\":       ext۰reflect۰Value۰Interface,\n\t\t\"(reflect.Value).IsNil\":           ext۰reflect۰Value۰IsNil,\n\t\t\"(reflect.Value).IsValid\":         ext۰reflect۰Value۰IsValid,\n\t\t\"(reflect.Value).Kind\":            ext۰reflect۰Value۰Kind,\n\t\t\"(reflect.Value).Len\":             ext۰reflect۰Value۰Len,\n\t\t\"(reflect.Value).MapIndex\":        ext۰reflect۰Value۰MapIndex,\n\t\t\"(reflect.Value).MapKeys\":         ext۰reflect۰Value۰MapKeys,\n\t\t\"(reflect.Value).NumField\":        ext۰reflect۰Value۰NumField,\n\t\t\"(reflect.Value).NumMethod\":       ext۰reflect۰Value۰NumMethod,\n\t\t\"(reflect.Value).Pointer\":         ext۰reflect۰Value۰Pointer,\n\t\t\"(reflect.Value).Set\":             ext۰reflect۰Value۰Set,\n\t\t\"(reflect.Value).String\":          ext۰reflect۰Value۰String,\n\t\t\"(reflect.Value).Type\":            ext۰reflect۰Value۰Type,\n\t\t\"(reflect.Value).Uint\":            ext۰reflect۰Value۰Uint,\n\t\t\"(reflect.error).Error\":           ext۰reflect۰error۰Error,\n\t\t\"(reflect.rtype).Bits\":            ext۰reflect۰rtype۰Bits,\n\t\t\"(reflect.rtype).Elem\":            ext۰reflect۰rtype۰Elem,\n\t\t\"(reflect.rtype).Field\":           ext۰reflect۰rtype۰Field,\n\t\t\"(reflect.rtype).In\":              ext۰reflect۰rtype۰In,\n\t\t\"(reflect.rtype).Kind\":            ext۰reflect۰rtype۰Kind,\n\t\t\"(reflect.rtype).NumField\":        ext۰reflect۰rtype۰NumField,\n\t\t\"(reflect.rtype).NumIn\":           ext۰reflect۰rtype۰NumIn,\n\t\t\"(reflect.rtype).NumMethod\":       ext۰reflect۰rtype۰NumMethod,\n\t\t\"(reflect.rtype).NumOut\":          ext۰reflect۰rtype۰NumOut,\n\t\t\"(reflect.rtype).Out\":             ext۰reflect۰rtype۰Out,\n\t\t\"(reflect.rtype).Size\":            ext۰reflect۰rtype۰Size,\n\t\t\"(reflect.rtype).String\":          ext۰reflect۰rtype۰String,\n\t\t\"bytes.Equal\":                     ext۰bytes۰Equal,\n\t\t\"bytes.IndexByte\":                 ext۰bytes۰IndexByte,\n\t\t\"fmt.Sprint\":                      ext۰fmt۰Sprint,\n\t\t\"math.Abs\":                        ext۰math۰Abs,\n\t\t\"math.Copysign\":                   ext۰math۰Copysign,\n\t\t\"math.Exp\":                        ext۰math۰Exp,\n\t\t\"math.Float32bits\":                ext۰math۰Float32bits,\n\t\t\"math.Float32frombits\":            ext۰math۰Float32frombits,\n\t\t\"math.Float64bits\":                ext۰math۰Float64bits,\n\t\t\"math.Float64frombits\":            ext۰math۰Float64frombits,\n\t\t\"math.Inf\":                        ext۰math۰Inf,\n\t\t\"math.IsNaN\":                      ext۰math۰IsNaN,\n\t\t\"math.Ldexp\":                      ext۰math۰Ldexp,\n\t\t\"math.Log\":                        ext۰math۰Log,\n\t\t\"math.Min\":                        ext۰math۰Min,\n\t\t\"math.NaN\":                        ext۰math۰NaN,\n\t\t\"math.Sqrt\":                       ext۰math۰Sqrt,\n\t\t\"os.Exit\":                         ext۰os۰Exit,\n\t\t\"os.Getenv\":                       ext۰os۰Getenv,\n\t\t\"reflect.New\":                     ext۰reflect۰New,\n\t\t\"reflect.SliceOf\":                 ext۰reflect۰SliceOf,\n\t\t\"reflect.TypeOf\":                  ext۰reflect۰TypeOf,\n\t\t\"reflect.ValueOf\":                 ext۰reflect۰ValueOf,\n\t\t\"reflect.Zero\":                    ext۰reflect۰Zero,\n\t\t\"runtime.Breakpoint\":              ext۰runtime۰Breakpoint,\n\t\t\"runtime.GC\":                      ext۰runtime۰GC,\n\t\t\"runtime.GOMAXPROCS\":              ext۰runtime۰GOMAXPROCS,\n\t\t\"runtime.GOROOT\":                  ext۰runtime۰GOROOT,\n\t\t\"runtime.Goexit\":                  ext۰runtime۰Goexit,\n\t\t\"runtime.Gosched\":                 ext۰runtime۰Gosched,\n\t\t\"runtime.NumCPU\":                  ext۰runtime۰NumCPU,\n\t\t\"sort.Float64s\":                   ext۰sort۰Float64s,\n\t\t\"sort.Ints\":                       ext۰sort۰Ints,\n\t\t\"sort.Strings\":                    ext۰sort۰Strings,\n\t\t\"strconv.Atoi\":                    ext۰strconv۰Atoi,\n\t\t\"strconv.Itoa\":                    ext۰strconv۰Itoa,\n\t\t\"strconv.FormatFloat\":             ext۰strconv۰FormatFloat,\n\t\t\"strings.Count\":                   ext۰strings۰Count,\n\t\t\"strings.EqualFold\":               ext۰strings۰EqualFold,\n\t\t\"strings.Index\":                   ext۰strings۰Index,\n\t\t\"strings.IndexByte\":               ext۰strings۰IndexByte,\n\t\t\"strings.Replace\":                 ext۰strings۰Replace,\n\t\t\"strings.ToLower\":                 ext۰strings۰ToLower,\n\t\t\"time.Sleep\":                      ext۰time۰Sleep,\n\t\t\"unicode/utf8.DecodeRuneInString\": ext۰unicode۰utf8۰DecodeRuneInString,\n\t})\n}\n\nfunc ext۰bytes۰Equal(fr *frame, args []value) value {\n\t// func Equal(a, b []byte) bool\n\ta := args[0].([]value)\n\tb := args[1].([]value)\n\treturn slices.Equal(a, b)\n}\n\nfunc ext۰bytes۰IndexByte(fr *frame, args []value) value {\n\t// func IndexByte(s []byte, c byte) int\n\ts := args[0].([]value)\n\tc := args[1].(byte)\n\tfor i, b := range s {\n\t\tif b.(byte) == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\nfunc ext۰math۰Float64frombits(fr *frame, args []value) value {\n\treturn math.Float64frombits(args[0].(uint64))\n}\n\nfunc ext۰math۰Float64bits(fr *frame, args []value) value {\n\treturn math.Float64bits(args[0].(float64))\n}\n\nfunc ext۰math۰Float32frombits(fr *frame, args []value) value {\n\treturn math.Float32frombits(args[0].(uint32))\n}\n\nfunc ext۰math۰Abs(fr *frame, args []value) value {\n\treturn math.Abs(args[0].(float64))\n}\n\nfunc ext۰math۰Copysign(fr *frame, args []value) value {\n\treturn math.Copysign(args[0].(float64), args[1].(float64))\n}\n\nfunc ext۰math۰Exp(fr *frame, args []value) value {\n\treturn math.Exp(args[0].(float64))\n}\n\nfunc ext۰math۰Float32bits(fr *frame, args []value) value {\n\treturn math.Float32bits(args[0].(float32))\n}\n\nfunc ext۰math۰Min(fr *frame, args []value) value {\n\treturn math.Min(args[0].(float64), args[1].(float64))\n}\n\nfunc ext۰math۰NaN(fr *frame, args []value) value {\n\treturn math.NaN()\n}\n\nfunc ext۰math۰IsNaN(fr *frame, args []value) value {\n\treturn math.IsNaN(args[0].(float64))\n}\n\nfunc ext۰math۰Inf(fr *frame, args []value) value {\n\treturn math.Inf(args[0].(int))\n}\n\nfunc ext۰math۰Ldexp(fr *frame, args []value) value {\n\treturn math.Ldexp(args[0].(float64), args[1].(int))\n}\n\nfunc ext۰math۰Log(fr *frame, args []value) value {\n\treturn math.Log(args[0].(float64))\n}\n\nfunc ext۰math۰Sqrt(fr *frame, args []value) value {\n\treturn math.Sqrt(args[0].(float64))\n}\n\nfunc ext۰runtime۰Breakpoint(fr *frame, args []value) value {\n\truntime.Breakpoint()\n\treturn nil\n}\n\nfunc ext۰sort۰Ints(fr *frame, args []value) value {\n\tx := args[0].([]value)\n\tsort.Slice(x, func(i, j int) bool {\n\t\treturn x[i].(int) < x[j].(int)\n\t})\n\treturn nil\n}\nfunc ext۰sort۰Strings(fr *frame, args []value) value {\n\tx := args[0].([]value)\n\tsort.Slice(x, func(i, j int) bool {\n\t\treturn x[i].(string) < x[j].(string)\n\t})\n\treturn nil\n}\nfunc ext۰sort۰Float64s(fr *frame, args []value) value {\n\tx := args[0].([]value)\n\tsort.Slice(x, func(i, j int) bool {\n\t\treturn x[i].(float64) < x[j].(float64)\n\t})\n\treturn nil\n}\n\nfunc ext۰strconv۰Atoi(fr *frame, args []value) value {\n\ti, e := strconv.Atoi(args[0].(string))\n\tif e != nil {\n\t\treturn tuple{i, iface{fr.i.runtimeErrorString, e.Error()}}\n\t}\n\treturn tuple{i, iface{}}\n}\nfunc ext۰strconv۰Itoa(fr *frame, args []value) value {\n\treturn strconv.Itoa(args[0].(int))\n}\nfunc ext۰strconv۰FormatFloat(fr *frame, args []value) value {\n\treturn strconv.FormatFloat(args[0].(float64), args[1].(byte), args[2].(int), args[3].(int))\n}\n\nfunc ext۰strings۰Count(fr *frame, args []value) value {\n\treturn strings.Count(args[0].(string), args[1].(string))\n}\n\nfunc ext۰strings۰EqualFold(fr *frame, args []value) value {\n\treturn strings.EqualFold(args[0].(string), args[1].(string))\n}\nfunc ext۰strings۰IndexByte(fr *frame, args []value) value {\n\treturn strings.IndexByte(args[0].(string), args[1].(byte))\n}\n\nfunc ext۰strings۰Index(fr *frame, args []value) value {\n\treturn strings.Index(args[0].(string), args[1].(string))\n}\n\nfunc ext۰strings۰Replace(fr *frame, args []value) value {\n\t// func Replace(s, old, new string, n int) string\n\ts := args[0].(string)\n\tnew := args[1].(string)\n\told := args[2].(string)\n\tn := args[3].(int)\n\treturn strings.Replace(s, old, new, n)\n}\n\nfunc ext۰strings۰ToLower(fr *frame, args []value) value {\n\treturn strings.ToLower(args[0].(string))\n}\n\nfunc ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {\n\t// Ignore args[0]; don't let the interpreted program\n\t// set the interpreter's GOMAXPROCS!\n\treturn runtime.GOMAXPROCS(0)\n}\n\nfunc ext۰runtime۰Goexit(fr *frame, args []value) value {\n\t// TODO(adonovan): don't kill the interpreter's main goroutine.\n\truntime.Goexit()\n\treturn nil\n}\n\nfunc ext۰runtime۰GOROOT(fr *frame, args []value) value {\n\treturn runtime.GOROOT()\n}\n\nfunc ext۰runtime۰GC(fr *frame, args []value) value {\n\truntime.GC()\n\treturn nil\n}\n\nfunc ext۰runtime۰Gosched(fr *frame, args []value) value {\n\truntime.Gosched()\n\treturn nil\n}\n\nfunc ext۰runtime۰NumCPU(fr *frame, args []value) value {\n\treturn runtime.NumCPU()\n}\n\nfunc ext۰time۰Sleep(fr *frame, args []value) value {\n\ttime.Sleep(time.Duration(args[0].(int64)))\n\treturn nil\n}\n\nfunc ext۰os۰Getenv(fr *frame, args []value) value {\n\tname := args[0].(string)\n\tswitch name {\n\tcase \"GOSSAINTERP\":\n\t\treturn \"1\"\n\t}\n\treturn os.Getenv(name)\n}\n\nfunc ext۰os۰Exit(fr *frame, args []value) value {\n\tpanic(exitPanic(args[0].(int)))\n}\n\nfunc ext۰unicode۰utf8۰DecodeRuneInString(fr *frame, args []value) value {\n\tr, n := utf8.DecodeRuneInString(args[0].(string))\n\treturn tuple{r, n}\n}\n\n// A fake function for turning an arbitrary value into a string.\n// Handles only the cases needed by the tests.\n// Uses same logic as 'print' built-in.\nfunc ext۰fmt۰Sprint(fr *frame, args []value) value {\n\tbuf := new(bytes.Buffer)\n\twasStr := false\n\tfor i, arg := range args[0].([]value) {\n\t\tx := arg.(iface).v\n\t\t_, isStr := x.(string)\n\t\tif i > 0 && !wasStr && !isStr {\n\t\t\tbuf.WriteByte(' ')\n\t\t}\n\t\twasStr = isStr\n\t\tbuf.WriteString(toString(x))\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "go/ssa/interp/interp.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package ssa/interp defines an interpreter for the SSA\n// representation of Go programs.\n//\n// This interpreter is provided as an adjunct for testing the SSA\n// construction algorithm.  Its purpose is to provide a minimal\n// metacircular implementation of the dynamic semantics of each SSA\n// instruction.  It is not, and will never be, a production-quality Go\n// interpreter.\n//\n// The following is a partial list of Go features that are currently\n// unsupported or incomplete in the interpreter.\n//\n// * Unsafe operations, including all uses of unsafe.Pointer, are\n// impossible to support given the \"boxed\" value representation we\n// have chosen.\n//\n// * The reflect package is only partially implemented.\n//\n// * The \"testing\" package is no longer supported because it\n// depends on low-level details that change too often.\n//\n// * \"sync/atomic\" operations are not atomic due to the \"boxed\" value\n// representation: it is not possible to read, modify and write an\n// interface value atomically. As a consequence, Mutexes are currently\n// broken.\n//\n// * recover is only partially implemented.  Also, the interpreter\n// makes no attempt to distinguish target panics from interpreter\n// crashes.\n//\n// * the sizes of the int, uint and uintptr types in the target\n// program are assumed to be the same as those of the interpreter\n// itself.\n//\n// * all values occupy space, even those of types defined by the spec\n// to have zero size, e.g. struct{}.  This can cause asymptotic\n// performance degradation.\n//\n// * os.Exit is implemented using panic, causing deferred functions to\n// run.\npackage interp // import \"golang.org/x/tools/go/ssa/interp\"\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sync/atomic\"\n\t_ \"unsafe\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\ntype continuation int\n\nconst (\n\tkNext continuation = iota\n\tkReturn\n\tkJump\n)\n\n// Mode is a bitmask of options affecting the interpreter.\ntype Mode uint\n\nconst (\n\tDisableRecover Mode = 1 << iota // Disable recover() in target programs; show interpreter crash instead.\n\tEnableTracing                   // Print a trace of all instructions as they are interpreted.\n)\n\ntype methodSet map[string]*ssa.Function\n\n// State shared between all interpreted goroutines.\ntype interpreter struct {\n\tosArgs             []value                // the value of os.Args\n\tprog               *ssa.Program           // the SSA program\n\tglobals            map[*ssa.Global]*value // addresses of global variables (immutable)\n\tmode               Mode                   // interpreter options\n\treflectPackage     *ssa.Package           // the fake reflect package\n\terrorMethods       methodSet              // the method set of reflect.error, which implements the error interface.\n\trtypeMethods       methodSet              // the method set of rtype, which implements the reflect.Type interface.\n\truntimeErrorString types.Type             // the runtime.errorString type\n\tsizes              types.Sizes            // the effective type-sizing function\n\tgoroutines         int32                  // atomically updated\n}\n\ntype deferred struct {\n\tfn    value\n\targs  []value\n\tinstr *ssa.Defer\n\ttail  *deferred\n}\n\ntype frame struct {\n\ti                *interpreter\n\tcaller           *frame\n\tfn               *ssa.Function\n\tblock, prevBlock *ssa.BasicBlock\n\tenv              map[ssa.Value]value // dynamic values of SSA variables\n\tlocals           []value\n\tdefers           *deferred\n\tresult           value\n\tpanicking        bool\n\tpanic            any\n\tphitemps         []value // temporaries for parallel phi assignment\n}\n\nfunc (fr *frame) get(key ssa.Value) value {\n\tswitch key := key.(type) {\n\tcase nil:\n\t\t// Hack; simplifies handling of optional attributes\n\t\t// such as ssa.Slice.{Low,High}.\n\t\treturn nil\n\tcase *ssa.Function, *ssa.Builtin:\n\t\treturn key\n\tcase *ssa.Const:\n\t\treturn constValue(key)\n\tcase *ssa.Global:\n\t\tif r, ok := fr.i.globals[key]; ok {\n\t\t\treturn r\n\t\t}\n\t}\n\tif r, ok := fr.env[key]; ok {\n\t\treturn r\n\t}\n\tpanic(fmt.Sprintf(\"get: no value for %T: %v\", key, key.Name()))\n}\n\n// runDefer runs a deferred call d.\n// It always returns normally, but may set or clear fr.panic.\nfunc (fr *frame) runDefer(d *deferred) {\n\tif fr.i.mode&EnableTracing != 0 {\n\t\tfmt.Fprintf(os.Stderr, \"%s: invoking deferred function call\\n\",\n\t\t\tfr.i.prog.Fset.Position(d.instr.Pos()))\n\t}\n\tvar ok bool\n\tdefer func() {\n\t\tif !ok {\n\t\t\t// Deferred call created a new state of panic.\n\t\t\tfr.panicking = true\n\t\t\tfr.panic = recover()\n\t\t}\n\t}()\n\tcall(fr.i, fr, d.instr.Pos(), d.fn, d.args)\n\tok = true\n}\n\n// runDefers executes fr's deferred function calls in LIFO order.\n//\n// On entry, fr.panicking indicates a state of panic; if\n// true, fr.panic contains the panic value.\n//\n// On completion, if a deferred call started a panic, or if no\n// deferred call recovered from a previous state of panic, then\n// runDefers itself panics after the last deferred call has run.\n//\n// If there was no initial state of panic, or it was recovered from,\n// runDefers returns normally.\nfunc (fr *frame) runDefers() {\n\tfor d := fr.defers; d != nil; d = d.tail {\n\t\tfr.runDefer(d)\n\t}\n\tfr.defers = nil\n\tif fr.panicking {\n\t\tpanic(fr.panic) // new panic, or still panicking\n\t}\n}\n\n// lookupMethod returns the method set for type typ, which may be one\n// of the interpreter's fake types.\nfunc lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function {\n\tswitch typ {\n\tcase rtypeType:\n\t\treturn i.rtypeMethods[meth.Id()]\n\tcase errorType:\n\t\treturn i.errorMethods[meth.Id()]\n\t}\n\treturn i.prog.LookupMethod(typ, meth.Pkg(), meth.Name())\n}\n\n// visitInstr interprets a single ssa.Instruction within the activation\n// record frame.  It returns a continuation value indicating where to\n// read the next instruction from.\nfunc visitInstr(fr *frame, instr ssa.Instruction) continuation {\n\tswitch instr := instr.(type) {\n\tcase *ssa.DebugRef:\n\t\t// no-op\n\n\tcase *ssa.UnOp:\n\t\tfr.env[instr] = unop(instr, fr.get(instr.X))\n\n\tcase *ssa.BinOp:\n\t\tfr.env[instr] = binop(instr.Op, instr.X.Type(), fr.get(instr.X), fr.get(instr.Y))\n\n\tcase *ssa.Call:\n\t\tfn, args := prepareCall(fr, &instr.Call)\n\t\tfr.env[instr] = call(fr.i, fr, instr.Pos(), fn, args)\n\n\tcase *ssa.ChangeInterface:\n\t\tfr.env[instr] = fr.get(instr.X)\n\n\tcase *ssa.ChangeType:\n\t\tfr.env[instr] = fr.get(instr.X) // (can't fail)\n\n\tcase *ssa.Convert:\n\t\tfr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))\n\n\tcase *ssa.SliceToArrayPointer:\n\t\tfr.env[instr] = sliceToArrayPointer(instr.Type(), instr.X.Type(), fr.get(instr.X))\n\n\tcase *ssa.MakeInterface:\n\t\tfr.env[instr] = iface{t: instr.X.Type(), v: fr.get(instr.X)}\n\n\tcase *ssa.Extract:\n\t\tfr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]\n\n\tcase *ssa.Slice:\n\t\tfr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))\n\n\tcase *ssa.Return:\n\t\tswitch len(instr.Results) {\n\t\tcase 0:\n\t\tcase 1:\n\t\t\tfr.result = fr.get(instr.Results[0])\n\t\tdefault:\n\t\t\tvar res []value\n\t\t\tfor _, r := range instr.Results {\n\t\t\t\tres = append(res, fr.get(r))\n\t\t\t}\n\t\t\tfr.result = tuple(res)\n\t\t}\n\t\tfr.block = nil\n\t\treturn kReturn\n\n\tcase *ssa.RunDefers:\n\t\tfr.runDefers()\n\n\tcase *ssa.Panic:\n\t\tpanic(targetPanic{fr.get(instr.X)})\n\n\tcase *ssa.Send:\n\t\tfr.get(instr.Chan).(chan value) <- fr.get(instr.X)\n\n\tcase *ssa.Store:\n\t\tstore(typeparams.MustDeref(instr.Addr.Type()), fr.get(instr.Addr).(*value), fr.get(instr.Val))\n\n\tcase *ssa.If:\n\t\tsucc := 1\n\t\tif fr.get(instr.Cond).(bool) {\n\t\t\tsucc = 0\n\t\t}\n\t\tfr.prevBlock, fr.block = fr.block, fr.block.Succs[succ]\n\t\treturn kJump\n\n\tcase *ssa.Jump:\n\t\tfr.prevBlock, fr.block = fr.block, fr.block.Succs[0]\n\t\treturn kJump\n\n\tcase *ssa.Defer:\n\t\tfn, args := prepareCall(fr, &instr.Call)\n\t\tdefers := &fr.defers\n\t\tif into := fr.get(instr.DeferStack); into != nil {\n\t\t\tdefers = into.(**deferred)\n\t\t}\n\t\t*defers = &deferred{\n\t\t\tfn:    fn,\n\t\t\targs:  args,\n\t\t\tinstr: instr,\n\t\t\ttail:  *defers,\n\t\t}\n\n\tcase *ssa.Go:\n\t\tfn, args := prepareCall(fr, &instr.Call)\n\t\tatomic.AddInt32(&fr.i.goroutines, 1)\n\t\tgo func() {\n\t\t\tcall(fr.i, nil, instr.Pos(), fn, args)\n\t\t\tatomic.AddInt32(&fr.i.goroutines, -1)\n\t\t}()\n\n\tcase *ssa.MakeChan:\n\t\tfr.env[instr] = make(chan value, asInt64(fr.get(instr.Size)))\n\n\tcase *ssa.Alloc:\n\t\tvar addr *value\n\t\tif instr.Heap {\n\t\t\t// new\n\t\t\taddr = new(value)\n\t\t\tfr.env[instr] = addr\n\t\t} else {\n\t\t\t// local\n\t\t\taddr = fr.env[instr].(*value)\n\t\t}\n\t\t*addr = zero(typeparams.MustDeref(instr.Type()))\n\n\tcase *ssa.MakeSlice:\n\t\tslice := make([]value, asInt64(fr.get(instr.Cap)))\n\t\ttElt := instr.Type().Underlying().(*types.Slice).Elem()\n\t\tfor i := range slice {\n\t\t\tslice[i] = zero(tElt)\n\t\t}\n\t\tfr.env[instr] = slice[:asInt64(fr.get(instr.Len))]\n\n\tcase *ssa.MakeMap:\n\t\tvar reserve int64\n\t\tif instr.Reserve != nil {\n\t\t\treserve = asInt64(fr.get(instr.Reserve))\n\t\t}\n\t\tif !fitsInt(reserve, fr.i.sizes) {\n\t\t\tpanic(fmt.Sprintf(\"ssa.MakeMap.Reserve value %d does not fit in int\", reserve))\n\t\t}\n\t\tfr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)\n\n\tcase *ssa.Range:\n\t\tfr.env[instr] = rangeIter(fr.get(instr.X))\n\n\tcase *ssa.Next:\n\t\tfr.env[instr] = fr.get(instr.Iter).(iter).next()\n\n\tcase *ssa.FieldAddr:\n\t\tfr.env[instr] = &(*fr.get(instr.X).(*value)).(structure)[instr.Field]\n\n\tcase *ssa.Field:\n\t\tfr.env[instr] = fr.get(instr.X).(structure)[instr.Field]\n\n\tcase *ssa.IndexAddr:\n\t\tx := fr.get(instr.X)\n\t\tidx := fr.get(instr.Index)\n\t\tswitch x := x.(type) {\n\t\tcase []value:\n\t\t\tfr.env[instr] = &x[asInt64(idx)]\n\t\tcase *value: // *array\n\t\t\tfr.env[instr] = &(*x).(array)[asInt64(idx)]\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected x type in IndexAddr: %T\", x))\n\t\t}\n\n\tcase *ssa.Index:\n\t\tx := fr.get(instr.X)\n\t\tidx := fr.get(instr.Index)\n\n\t\tswitch x := x.(type) {\n\t\tcase array:\n\t\t\tfr.env[instr] = x[asInt64(idx)]\n\t\tcase string:\n\t\t\tfr.env[instr] = x[asInt64(idx)]\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected x type in Index: %T\", x))\n\t\t}\n\n\tcase *ssa.Lookup:\n\t\tfr.env[instr] = lookup(instr, fr.get(instr.X), fr.get(instr.Index))\n\n\tcase *ssa.MapUpdate:\n\t\tm := fr.get(instr.Map)\n\t\tkey := fr.get(instr.Key)\n\t\tv := fr.get(instr.Value)\n\t\tswitch m := m.(type) {\n\t\tcase map[value]value:\n\t\t\tm[key] = v\n\t\tcase *hashmap:\n\t\t\tm.insert(key.(hashable), v)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"illegal map type: %T\", m))\n\t\t}\n\n\tcase *ssa.TypeAssert:\n\t\tfr.env[instr] = typeAssert(instr, fr.get(instr.X).(iface))\n\n\tcase *ssa.MakeClosure:\n\t\tvar bindings []value\n\t\tfor _, binding := range instr.Bindings {\n\t\t\tbindings = append(bindings, fr.get(binding))\n\t\t}\n\t\tfr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}\n\n\tcase *ssa.Phi:\n\t\tlog.Fatal(\"unreachable\") // phis are processed at block entry\n\n\tcase *ssa.Select:\n\t\tvar cases []reflect.SelectCase\n\t\tif !instr.Blocking {\n\t\t\tcases = append(cases, reflect.SelectCase{\n\t\t\t\tDir: reflect.SelectDefault,\n\t\t\t})\n\t\t}\n\t\tfor _, state := range instr.States {\n\t\t\tvar dir reflect.SelectDir\n\t\t\tif state.Dir == types.RecvOnly {\n\t\t\t\tdir = reflect.SelectRecv\n\t\t\t} else {\n\t\t\t\tdir = reflect.SelectSend\n\t\t\t}\n\t\t\tvar send reflect.Value\n\t\t\tif state.Send != nil {\n\t\t\t\tsend = reflect.ValueOf(fr.get(state.Send))\n\t\t\t}\n\t\t\tcases = append(cases, reflect.SelectCase{\n\t\t\t\tDir:  dir,\n\t\t\t\tChan: reflect.ValueOf(fr.get(state.Chan)),\n\t\t\t\tSend: send,\n\t\t\t})\n\t\t}\n\t\tchosen, recv, recvOk := reflect.Select(cases)\n\t\tif !instr.Blocking {\n\t\t\tchosen-- // default case should have index -1.\n\t\t}\n\t\tr := tuple{chosen, recvOk}\n\t\tfor i, st := range instr.States {\n\t\t\tif st.Dir == types.RecvOnly {\n\t\t\t\tvar v value\n\t\t\t\tif i == chosen && recvOk {\n\t\t\t\t\t// No need to copy since send makes an unaliased copy.\n\t\t\t\t\tv = recv.Interface().(value)\n\t\t\t\t} else {\n\t\t\t\t\tv = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())\n\t\t\t\t}\n\t\t\t\tr = append(r, v)\n\t\t\t}\n\t\t}\n\t\tfr.env[instr] = r\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected instruction: %T\", instr))\n\t}\n\n\t// if val, ok := instr.(ssa.Value); ok {\n\t// \tfmt.Println(toString(fr.env[val])) // debugging\n\t// }\n\n\treturn kNext\n}\n\n// prepareCall determines the function value and argument values for a\n// function call in a Call, Go or Defer instruction, performing\n// interface method lookup if needed.\nfunc prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {\n\tv := fr.get(call.Value)\n\tif call.Method == nil {\n\t\t// Function call.\n\t\tfn = v\n\t} else {\n\t\t// Interface method invocation.\n\t\trecv := v.(iface)\n\t\tif recv.t == nil {\n\t\t\tpanic(\"method invoked on nil interface\")\n\t\t}\n\t\tif f := lookupMethod(fr.i, recv.t, call.Method); f == nil {\n\t\t\t// Unreachable in well-typed programs.\n\t\t\tpanic(fmt.Sprintf(\"method set for dynamic type %v does not contain %s\", recv.t, call.Method))\n\t\t} else {\n\t\t\tfn = f\n\t\t}\n\t\targs = append(args, recv.v)\n\t}\n\tfor _, arg := range call.Args {\n\t\targs = append(args, fr.get(arg))\n\t}\n\treturn\n}\n\n// call interprets a call to a function (function, builtin or closure)\n// fn with arguments args, returning its result.\n// callpos is the position of the callsite.\nfunc call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {\n\tswitch fn := fn.(type) {\n\tcase *ssa.Function:\n\t\tif fn == nil {\n\t\t\tpanic(\"call of nil function\") // nil of func type\n\t\t}\n\t\treturn callSSA(i, caller, callpos, fn, args, nil)\n\tcase *closure:\n\t\treturn callSSA(i, caller, callpos, fn.Fn, args, fn.Env)\n\tcase *ssa.Builtin:\n\t\treturn callBuiltin(caller, fn, args)\n\t}\n\tpanic(fmt.Sprintf(\"cannot call %T\", fn))\n}\n\nfunc loc(fset *token.FileSet, pos token.Pos) string {\n\tif pos == token.NoPos {\n\t\treturn \"\"\n\t}\n\treturn \" at \" + fset.Position(pos).String()\n}\n\n// callSSA interprets a call to function fn with arguments args,\n// and lexical environment env, returning its result.\n// callpos is the position of the callsite.\nfunc callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {\n\tif i.mode&EnableTracing != 0 {\n\t\tfset := fn.Prog.Fset\n\t\t// TODO(adonovan): fix: loc() lies for external functions.\n\t\tfmt.Fprintf(os.Stderr, \"Entering %s%s.\\n\", fn, loc(fset, fn.Pos()))\n\t\tsuffix := \"\"\n\t\tif caller != nil {\n\t\t\tsuffix = \", resuming \" + caller.fn.String() + loc(fset, callpos)\n\t\t}\n\t\tdefer fmt.Fprintf(os.Stderr, \"Leaving %s%s.\\n\", fn, suffix)\n\t}\n\tfr := &frame{\n\t\ti:      i,\n\t\tcaller: caller, // for panic/recover\n\t\tfn:     fn,\n\t}\n\tif fn.Parent() == nil {\n\t\tname := fn.String()\n\t\tif ext := externals[name]; ext != nil {\n\t\t\tif i.mode&EnableTracing != 0 {\n\t\t\t\tfmt.Fprintln(os.Stderr, \"\\t(external)\")\n\t\t\t}\n\t\t\treturn ext(fr, args)\n\t\t}\n\t\tif fn.Blocks == nil {\n\t\t\tpanic(\"no code for function: \" + name)\n\t\t}\n\t}\n\n\t// generic function body?\n\tif fn.TypeParams().Len() > 0 && len(fn.TypeArgs()) == 0 {\n\t\tpanic(\"interp requires ssa.BuilderMode to include InstantiateGenerics to execute generics\")\n\t}\n\n\tfr.env = make(map[ssa.Value]value)\n\tfr.block = fn.Blocks[0]\n\tfr.locals = make([]value, len(fn.Locals))\n\tfor i, l := range fn.Locals {\n\t\tfr.locals[i] = zero(typeparams.MustDeref(l.Type()))\n\t\tfr.env[l] = &fr.locals[i]\n\t}\n\tfor i, p := range fn.Params {\n\t\tfr.env[p] = args[i]\n\t}\n\tfor i, fv := range fn.FreeVars {\n\t\tfr.env[fv] = env[i]\n\t}\n\tfor fr.block != nil {\n\t\trunFrame(fr)\n\t}\n\t// Destroy the locals to avoid accidental use after return.\n\tfor i := range fn.Locals {\n\t\tfr.locals[i] = bad{}\n\t}\n\treturn fr.result\n}\n\n// runFrame executes SSA instructions starting at fr.block and\n// continuing until a return, a panic, or a recovered panic.\n//\n// After a panic, runFrame panics.\n//\n// After a normal return, fr.result contains the result of the call\n// and fr.block is nil.\n//\n// A recovered panic in a function without named return parameters\n// (NRPs) becomes a normal return of the zero value of the function's\n// result type.\n//\n// After a recovered panic in a function with NRPs, fr.result is\n// undefined and fr.block contains the block at which to resume\n// control.\nfunc runFrame(fr *frame) {\n\tdefer func() {\n\t\tif fr.block == nil {\n\t\t\treturn // normal return\n\t\t}\n\t\tif fr.i.mode&DisableRecover != 0 {\n\t\t\treturn // let interpreter crash\n\t\t}\n\t\tfr.panicking = true\n\t\tfr.panic = recover()\n\t\tif fr.i.mode&EnableTracing != 0 {\n\t\t\tfmt.Fprintf(os.Stderr, \"Panicking: %T %v.\\n\", fr.panic, fr.panic)\n\t\t}\n\t\tfr.runDefers()\n\t\tfr.block = fr.fn.Recover\n\t}()\n\n\tfor {\n\t\tif fr.i.mode&EnableTracing != 0 {\n\t\t\tfmt.Fprintf(os.Stderr, \".%s:\\n\", fr.block)\n\t\t}\n\n\t\tnonPhis := executePhis(fr)\n\t\tfor _, instr := range nonPhis {\n\t\t\tif fr.i.mode&EnableTracing != 0 {\n\t\t\t\tif v, ok := instr.(ssa.Value); ok {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, \"\\t\", v.Name(), \"=\", instr)\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, \"\\t\", instr)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif visitInstr(fr, instr) == kReturn {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Inv: kNext (continue) or kJump (last instr)\n\t\t}\n\t}\n}\n\n// executePhis executes the phi-nodes at the start of the current\n// block and returns the non-phi instructions.\nfunc executePhis(fr *frame) []ssa.Instruction {\n\tfirstNonPhi := -1\n\tfor i, instr := range fr.block.Instrs {\n\t\tif _, ok := instr.(*ssa.Phi); !ok {\n\t\t\tfirstNonPhi = i\n\t\t\tbreak\n\t\t}\n\t}\n\t// Inv: 0 <= firstNonPhi; every block contains a non-phi.\n\n\tnonPhis := fr.block.Instrs[firstNonPhi:]\n\tif firstNonPhi > 0 {\n\t\tphis := fr.block.Instrs[:firstNonPhi]\n\t\t// Execute parallel assignment of phis.\n\t\t//\n\t\t// See \"the swap problem\" in Briggs et al's \"Practical Improvements\n\t\t// to the Construction and Destruction of SSA Form\" for discussion.\n\t\tpredIndex := slices.Index(fr.block.Preds, fr.prevBlock)\n\t\tfr.phitemps = fr.phitemps[:0]\n\t\tfor _, phi := range phis {\n\t\t\tphi := phi.(*ssa.Phi)\n\t\t\tif fr.i.mode&EnableTracing != 0 {\n\t\t\t\tfmt.Fprintln(os.Stderr, \"\\t\", phi.Name(), \"=\", phi)\n\t\t\t}\n\t\t\tfr.phitemps = append(fr.phitemps, fr.get(phi.Edges[predIndex]))\n\t\t}\n\t\tfor i, phi := range phis {\n\t\t\tfr.env[phi.(*ssa.Phi)] = fr.phitemps[i]\n\t\t}\n\t}\n\treturn nonPhis\n}\n\n// doRecover implements the recover() built-in.\nfunc doRecover(caller *frame) value {\n\t// recover() must be exactly one level beneath the deferred\n\t// function (two levels beneath the panicking function) to\n\t// have any effect.  Thus we ignore both \"defer recover()\" and\n\t// \"defer f() -> g() -> recover()\".\n\tif caller.i.mode&DisableRecover == 0 &&\n\t\tcaller != nil && !caller.panicking &&\n\t\tcaller.caller != nil && caller.caller.panicking {\n\t\tcaller.caller.panicking = false\n\t\tp := caller.caller.panic\n\t\tcaller.caller.panic = nil\n\n\t\t// TODO(adonovan): support runtime.Goexit.\n\t\tswitch p := p.(type) {\n\t\tcase targetPanic:\n\t\t\t// The target program explicitly called panic().\n\t\t\treturn p.v\n\t\tcase runtime.Error:\n\t\t\t// The interpreter encountered a runtime error.\n\t\t\treturn iface{caller.i.runtimeErrorString, p.Error()}\n\t\tcase string:\n\t\t\t// The interpreter explicitly called panic().\n\t\t\treturn iface{caller.i.runtimeErrorString, p}\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected panic type %T in target call to recover()\", p))\n\t\t}\n\t}\n\treturn iface{}\n}\n\n// Interpret interprets the Go program whose main package is mainpkg.\n// mode specifies various interpreter options.  filename and args are\n// the initial values of os.Args for the target program.  sizes is the\n// effective type-sizing function for this program.\n//\n// Interpret returns the exit code of the program: 2 for panic (like\n// gc does), or the argument to os.Exit for normal termination.\n//\n// The SSA program must include the \"runtime\" package.\n//\n// Type parameterized functions must have been built with\n// InstantiateGenerics in the ssa.BuilderMode to be interpreted.\nfunc Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {\n\ti := &interpreter{\n\t\tprog:       mainpkg.Prog,\n\t\tglobals:    make(map[*ssa.Global]*value),\n\t\tmode:       mode,\n\t\tsizes:      sizes,\n\t\tgoroutines: 1,\n\t}\n\truntimePkg := i.prog.ImportedPackage(\"runtime\")\n\tif runtimePkg == nil {\n\t\tpanic(\"ssa.Program doesn't include runtime package\")\n\t}\n\ti.runtimeErrorString = runtimePkg.Type(\"errorString\").Object().Type()\n\n\tinitReflect(i)\n\n\ti.osArgs = append(i.osArgs, filename)\n\tfor _, arg := range args {\n\t\ti.osArgs = append(i.osArgs, arg)\n\t}\n\n\tfor _, pkg := range i.prog.AllPackages() {\n\t\t// Initialize global storage.\n\t\tfor _, m := range pkg.Members {\n\t\t\tswitch v := m.(type) {\n\t\t\tcase *ssa.Global:\n\t\t\t\tcell := zero(typeparams.MustDeref(v.Type()))\n\t\t\t\ti.globals[v] = &cell\n\t\t\t}\n\t\t}\n\t}\n\n\t// Top-level error handler.\n\texitCode = 2\n\tdefer func() {\n\t\tif exitCode != 2 || i.mode&DisableRecover != 0 {\n\t\t\treturn\n\t\t}\n\t\tswitch p := recover().(type) {\n\t\tcase exitPanic:\n\t\t\texitCode = int(p)\n\t\t\treturn\n\t\tcase targetPanic:\n\t\t\tfmt.Fprintln(os.Stderr, \"panic:\", toString(p.v))\n\t\tcase runtime.Error:\n\t\t\tfmt.Fprintln(os.Stderr, \"panic:\", p.Error())\n\t\tcase string:\n\t\t\tfmt.Fprintln(os.Stderr, \"panic:\", p)\n\t\tdefault:\n\t\t\tfmt.Fprintf(os.Stderr, \"panic: unexpected type: %T: %v\\n\", p, p)\n\t\t}\n\n\t\t// TODO(adonovan): dump panicking interpreter goroutine?\n\t\t// buf := make([]byte, 0x10000)\n\t\t// runtime.Stack(buf, false)\n\t\t// fmt.Fprintln(os.Stderr, string(buf))\n\t\t// (Or dump panicking target goroutine?)\n\t}()\n\n\t// Run!\n\tcall(i, nil, token.NoPos, mainpkg.Func(\"init\"), nil)\n\tif mainFn := mainpkg.Func(\"main\"); mainFn != nil {\n\t\tcall(i, nil, token.NoPos, mainFn, nil)\n\t\texitCode = 0\n\t} else {\n\t\tfmt.Fprintln(os.Stderr, \"No main function.\")\n\t\texitCode = 1\n\t}\n\treturn\n}\n"
  },
  {
    "path": "go/ssa/interp/interp_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp_test\n\n// This test runs the SSA interpreter over sample Go programs.\n// Because the interpreter requires intrinsics for assembly\n// functions and many low-level runtime routines, it is inherently\n// not robust to evolutionary change in the standard library.\n// Therefore the test cases are restricted to programs that\n// use a fake standard library in testdata/src containing a tiny\n// subset of simple functions useful for writing assertions.\n//\n// We no longer attempt to interpret any real standard packages such as\n// fmt or testing, as it proved too fragile.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/interp\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// Each line contains a space-separated list of $GOROOT/test/\n// filenames comprising the main package of a program.\n// They are ordered quickest-first, roughly.\n//\n// If a test in this list fails spuriously, remove it.\nvar gorootTestTests = []string{\n\t\"235.go\",\n\t\"alias1.go\",\n\t\"func5.go\",\n\t\"func6.go\",\n\t\"func7.go\",\n\t\"func8.go\",\n\t\"helloworld.go\",\n\t\"varinit.go\",\n\t\"escape3.go\",\n\t\"initcomma.go\",\n\t\"cmp.go\",\n\t\"compos.go\",\n\t\"turing.go\",\n\t\"indirect.go\",\n\t\"complit.go\",\n\t\"for.go\",\n\t\"struct0.go\",\n\t\"intcvt.go\",\n\t\"printbig.go\",\n\t\"deferprint.go\",\n\t\"escape.go\",\n\t\"range.go\",\n\t\"const4.go\",\n\t\"float_lit.go\",\n\t\"bigalg.go\",\n\t\"decl.go\",\n\t\"if.go\",\n\t\"named.go\",\n\t\"bigmap.go\",\n\t\"func.go\",\n\t\"reorder2.go\",\n\t\"gc.go\",\n\t\"simassign.go\",\n\t\"iota.go\",\n\t\"nilptr2.go\",\n\t\"utf.go\",\n\t\"method.go\",\n\t\"char_lit.go\",\n\t\"env.go\",\n\t\"int_lit.go\",\n\t\"string_lit.go\",\n\t\"defer.go\",\n\t\"typeswitch.go\",\n\t\"stringrange.go\",\n\t\"reorder.go\",\n\t\"method3.go\",\n\t\"literal.go\",\n\t\"nul1.go\", // doesn't actually assert anything (errorcheckoutput)\n\t\"zerodivide.go\",\n\t\"convert.go\",\n\t\"convT2X.go\",\n\t\"switch.go\",\n\t\"ddd.go\",\n\t\"blank.go\", // partly disabled\n\t\"closedchan.go\",\n\t\"divide.go\",\n\t\"rename.go\",\n\t\"nil.go\",\n\t\"recover1.go\",\n\t\"recover2.go\",\n\t\"recover3.go\",\n\t\"typeswitch1.go\",\n\t\"floatcmp.go\",\n\t\"crlf.go\", // doesn't actually assert anything (runoutput)\n}\n\n// These are files in testdata/.\nvar testdataTests = []string{\n\t\"boundmeth.go\",\n\t\"complit.go\",\n\t\"convert.go\",\n\t\"coverage.go\",\n\t\"deepequal.go\",\n\t\"defer.go\",\n\t\"fieldprom.go\",\n\t\"fixedbugs/issue52342.go\",\n\t\"fixedbugs/issue52835.go\",\n\t\"fixedbugs/issue55086.go\",\n\t\"fixedbugs/issue55115.go\",\n\t\"fixedbugs/issue66783.go\",\n\t\"fixedbugs/issue69929.go\",\n\t\"forvarlifetime_go122.go\",\n\t\"forvarlifetime_old.go\",\n\t\"ifaceconv.go\",\n\t\"ifaceprom.go\",\n\t\"initorder.go\",\n\t\"methprom.go\",\n\t\"minmax.go\",\n\t\"mrvchain.go\",\n\t\"newexpr_go126.go\",\n\t\"range.go\",\n\t\"rangeoverint.go\",\n\t\"rangevarlifetime_go122.go\",\n\t\"rangevarlifetime_old.go\",\n\t\"recover.go\",\n\t\"reflect.go\",\n\t\"slice2array.go\",\n\t\"slice2arrayptr.go\",\n\t\"static.go\",\n\t\"typeassert.go\",\n\t\"width32.go\",\n\t\"zeros.go\",\n}\n\nfunc init() {\n\t// GOROOT/test used to assume that GOOS and GOARCH were explicitly set in the\n\t// environment, so do that here for TestGorootTest.\n\tos.Setenv(\"GOOS\", runtime.GOOS)\n\tos.Setenv(\"GOARCH\", runtime.GOARCH)\n}\n\n// run runs a single test. On success it returns the captured std{out,err}.\nfunc run(t *testing.T, input string, goroot string) string {\n\ttestenv.NeedsExec(t) // really we just need os.Pipe, but os/exec uses pipes\n\n\tt.Logf(\"Input: %s\\n\", input)\n\n\tstart := time.Now()\n\n\tctx := build.Default // copy\n\tctx.GOROOT = goroot\n\tctx.GOOS = runtime.GOOS\n\tctx.GOARCH = runtime.GOARCH\n\tif filepath.Base(input) == \"width32.go\" && unsafe.Sizeof(int(0)) > 4 {\n\t\tt.Skipf(\"skipping: width32.go checks behavior for a 32-bit int\")\n\t}\n\n\tgover := \"\"\n\tif p := testenv.Go1Point(); p > 0 {\n\t\tgover = fmt.Sprintf(\"go1.%d\", p)\n\t}\n\n\t// Check build tags, since FromArgs doesn't do this part.\n\t// TODO(adonovan): use go/packages.\n\tif match, err := ctx.MatchFile(filepath.Dir(input), filepath.Base(input)); err != nil {\n\t\tt.Fatalf(\"MatchFile %v: %v\", input, err)\n\t} else if !match {\n\t\tt.Skipf(\"file %s doesn't match this build configuration\", input)\n\t}\n\n\tconf := loader.Config{Build: &ctx, TypeChecker: types.Config{GoVersion: gover}}\n\tif _, err := conf.FromArgs([]string{input}, true); err != nil {\n\t\tt.Fatalf(\"FromArgs(%s) failed: %s\", input, err)\n\t}\n\n\tconf.Import(\"runtime\")\n\n\t// Print a helpful hint if we don't make it to the end.\n\tvar hint string\n\tdefer func() {\n\t\tt.Logf(\"Duration: %v\", time.Since(start))\n\t\tif hint != \"\" {\n\t\t\tt.Log(\"FAIL\")\n\t\t\tt.Log(hint)\n\t\t} else {\n\t\t\tt.Log(\"PASS\")\n\t\t}\n\t}()\n\n\thint = fmt.Sprintf(\"To dump SSA representation, run:\\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\\n\", input)\n\n\tiprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatalf(\"conf.Load(%s) failed: %s\", input, err)\n\t}\n\n\tbmode := ssa.InstantiateGenerics | ssa.SanityCheckFunctions\n\t// bmode |= ssa.PrintFunctions // enable for debugging\n\tprog := ssautil.CreateProgram(iprog, bmode)\n\tprog.Build()\n\n\tmainPkg := prog.Package(iprog.Created[0].Pkg)\n\tif mainPkg == nil {\n\t\tt.Fatalf(\"not a main package: %s\", input)\n\t}\n\n\tsizes := types.SizesFor(\"gc\", ctx.GOARCH)\n\tif sizes.Sizeof(types.Typ[types.Int]) < 4 {\n\t\tpanic(\"bogus SizesFor\")\n\t}\n\thint = fmt.Sprintf(\"To trace execution, run:\\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -test -run --interp=T %s\\n\", input)\n\n\t// Capture anything written by the interpreter to os.Std{out,err}\n\t// by temporarily redirecting them to a buffer via a pipe.\n\t//\n\t// While capturing is in effect, we must not write any\n\t// test-related stuff to stderr (including log.Print, t.Log, etc).\n\tvar restore func() string // restore files and log+return the mixed out/err.\n\t{\n\t\t// Connect std{out,err} to pipe.\n\t\tr, w, err := os.Pipe()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"can't create pipe for stderr: %v\", err)\n\t\t}\n\t\tsavedStdout := os.Stdout\n\t\tsavedStderr := os.Stderr\n\t\tos.Stdout = w\n\t\tos.Stderr = w\n\n\t\t// Buffer what is written.\n\t\tvar buf strings.Builder\n\t\tdone := make(chan struct{})\n\t\tgo func() {\n\t\t\tif _, err := io.Copy(&buf, r); err != nil {\n\t\t\t\tfmt.Fprintf(savedStderr, \"io.Copy: %v\", err)\n\t\t\t}\n\t\t\tclose(done)\n\t\t}()\n\n\t\t// Finally, restore the files and log what was captured.\n\t\trestore = func() string {\n\t\t\tos.Stdout = savedStdout\n\t\t\tos.Stderr = savedStderr\n\t\t\tw.Close()\n\t\t\t<-done\n\t\t\tcaptured := buf.String()\n\t\t\tt.Logf(\"Interpreter's stdout+stderr:\\n%s\", captured)\n\t\t\treturn captured\n\t\t}\n\t}\n\n\tvar imode interp.Mode // default mode\n\t// imode |= interp.DisableRecover // enable for debugging\n\t// imode |= interp.EnableTracing // enable for debugging\n\texitCode := interp.Interpret(mainPkg, imode, sizes, input, []string{})\n\tcapturedOutput := restore()\n\tif exitCode != 0 {\n\t\tt.Fatalf(\"interpreting %s: exit code was %d\", input, exitCode)\n\t}\n\t// $GOROOT/test tests use this convention:\n\tif strings.Contains(capturedOutput, \"BUG\") {\n\t\tt.Fatalf(\"interpreting %s: exited zero but output contained 'BUG'\", input)\n\t}\n\n\thint = \"\" // call off the hounds\n\n\treturn capturedOutput\n}\n\n// makeGoroot copies testdata/src into the \"src\" directory of a temporary\n// location to mimic GOROOT/src, and adds a file \"runtime/consts.go\" containing\n// declarations for GOOS and GOARCH that match the GOOS and GOARCH of this test.\n//\n// It returns the directory that should be used for GOROOT.\nfunc makeGoroot(t *testing.T) string {\n\tgoroot := t.TempDir()\n\tsrc := filepath.Join(goroot, \"src\")\n\n\terr := filepath.Walk(\"testdata/src\", func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\trel, err := filepath.Rel(\"testdata/src\", path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttarg := filepath.Join(src, rel)\n\n\t\tif info.IsDir() {\n\t\t\treturn os.Mkdir(targ, info.Mode().Perm()|0700)\n\t\t}\n\n\t\tb, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn os.WriteFile(targ, b, info.Mode().Perm())\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconstsGo := fmt.Sprintf(`package runtime\nconst GOOS = %q\nconst GOARCH = %q\n`, runtime.GOOS, runtime.GOARCH)\n\terr = os.WriteFile(filepath.Join(src, \"runtime/consts.go\"), []byte(constsGo), 0644)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\treturn goroot\n}\n\n// TestTestdataFiles runs the interpreter on testdata/*.go.\nfunc TestTestdataFiles(t *testing.T) {\n\tgoroot := makeGoroot(t)\n\tfor _, input := range testdataTests {\n\t\tt.Run(input, func(t *testing.T) {\n\t\t\trun(t, filepath.Join(\"testdata\", input), goroot)\n\t\t})\n\t}\n}\n\n// TestGorootTest runs the interpreter on $GOROOT/test/*.go.\nfunc TestGorootTest(t *testing.T) {\n\ttestenv.NeedsGOROOTDir(t, \"test\")\n\n\tgoroot := makeGoroot(t)\n\tfor _, input := range gorootTestTests {\n\t\tt.Run(input, func(t *testing.T) {\n\t\t\trun(t, filepath.Join(build.Default.GOROOT, \"test\", input), goroot)\n\t\t})\n\t}\n}\n\n// TestTypeparamTest runs the interpreter on runnable examples\n// in $GOROOT/test/typeparam/*.go.\n\nfunc TestTypeparamTest(t *testing.T) {\n\ttestenv.NeedsGOROOTDir(t, \"test\")\n\n\tif runtime.GOARCH == \"wasm\" {\n\t\t// See ssa/TestTypeparamTest.\n\t\tt.Skip(\"Consistent flakes on wasm (e.g. https://go.dev/issues/64726)\")\n\t}\n\n\tgoroot := makeGoroot(t)\n\n\t// Skip known failures for the given reason.\n\t// TODO(taking): Address these.\n\tskip := map[string]string{\n\t\t\"chans.go\":      \"interp tests do not support runtime.SetFinalizer\",\n\t\t\"issue23536.go\": \"unknown reason\",\n\t\t\"issue48042.go\": \"interp tests do not handle reflect.Value.SetInt\",\n\t\t\"issue47716.go\": \"interp tests do not handle unsafe.Sizeof\",\n\t\t\"issue50419.go\": \"interp tests do not handle dispatch to String() correctly\",\n\t\t\"issue51733.go\": \"interp does not handle unsafe casts\",\n\t\t\"ordered.go\":    \"math.NaN() comparisons not being handled correctly\",\n\t\t\"orderedmap.go\": \"interp tests do not support runtime.SetFinalizer\",\n\t\t\"stringer.go\":   \"unknown reason\",\n\t\t\"issue48317.go\": \"interp tests do not support encoding/json\",\n\t\t\"issue48318.go\": \"interp tests do not support encoding/json\",\n\t\t\"issue58513.go\": \"interp tests do not support runtime.Caller\",\n\t}\n\t// Collect all of the .go files in dir that are runnable.\n\tdir := filepath.Join(build.Default.GOROOT, \"test\", \"typeparam\")\n\tlist, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, entry := range list {\n\t\tif entry.IsDir() || !strings.HasSuffix(entry.Name(), \".go\") {\n\t\t\tcontinue // Consider standalone go files.\n\t\t}\n\t\tt.Run(entry.Name(), func(t *testing.T) {\n\t\t\tinput := filepath.Join(dir, entry.Name())\n\t\t\tsrc, err := os.ReadFile(input)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Only build test files that can be compiled, or compiled and run.\n\t\t\tif !bytes.HasPrefix(src, []byte(\"// run\")) || bytes.HasPrefix(src, []byte(\"// rundir\")) {\n\t\t\t\tt.Logf(\"Not a `// run` file: %s\", entry.Name())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif reason := skip[entry.Name()]; reason != \"\" {\n\t\t\t\tt.Skipf(\"skipping: %s\", reason)\n\t\t\t}\n\n\t\t\trun(t, input, goroot)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/map.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp\n\n// Custom hashtable atop map.\n// For use when the key's equivalence relation is not consistent with ==.\n\n// The Go specification doesn't address the atomicity of map operations.\n// The FAQ states that an implementation is permitted to crash on\n// concurrent map access.\n\nimport (\n\t\"go/types\"\n)\n\ntype hashable interface {\n\thash(t types.Type) int\n\teq(t types.Type, x any) bool\n}\n\ntype entry struct {\n\tkey   hashable\n\tvalue value\n\tnext  *entry\n}\n\n// A hashtable atop the built-in map.  Since each bucket contains\n// exactly one hash value, there's no need to perform hash-equality\n// tests when walking the linked list.  Rehashing is done by the\n// underlying map.\ntype hashmap struct {\n\tkeyType types.Type\n\ttable   map[int]*entry\n\tlength  int // number of entries in map\n}\n\n// makeMap returns an empty initialized map of key type kt,\n// preallocating space for reserve elements.\nfunc makeMap(kt types.Type, reserve int64) value {\n\tif usesBuiltinMap(kt) {\n\t\treturn make(map[value]value, reserve)\n\t}\n\treturn &hashmap{keyType: kt, table: make(map[int]*entry, reserve)}\n}\n\n// delete removes the association for key k, if any.\nfunc (m *hashmap) delete(k hashable) {\n\tif m != nil {\n\t\thash := k.hash(m.keyType)\n\t\thead := m.table[hash]\n\t\tif head != nil {\n\t\t\tif k.eq(m.keyType, head.key) {\n\t\t\t\tm.table[hash] = head.next\n\t\t\t\tm.length--\n\t\t\t\treturn\n\t\t\t}\n\t\t\tprev := head\n\t\t\tfor e := head.next; e != nil; e = e.next {\n\t\t\t\tif k.eq(m.keyType, e.key) {\n\t\t\t\t\tprev.next = e.next\n\t\t\t\t\tm.length--\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tprev = e\n\t\t\t}\n\t\t}\n\t}\n}\n\n// lookup returns the value associated with key k, if present, or\n// value(nil) otherwise.\nfunc (m *hashmap) lookup(k hashable) value {\n\tif m != nil {\n\t\thash := k.hash(m.keyType)\n\t\tfor e := m.table[hash]; e != nil; e = e.next {\n\t\t\tif k.eq(m.keyType, e.key) {\n\t\t\t\treturn e.value\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// insert updates the map to associate key k with value v.  If there\n// was already an association for an eq() (though not necessarily ==)\n// k, the previous key remains in the map and its associated value is\n// updated.\nfunc (m *hashmap) insert(k hashable, v value) {\n\thash := k.hash(m.keyType)\n\thead := m.table[hash]\n\tfor e := head; e != nil; e = e.next {\n\t\tif k.eq(m.keyType, e.key) {\n\t\t\te.value = v\n\t\t\treturn\n\t\t}\n\t}\n\tm.table[hash] = &entry{\n\t\tkey:   k,\n\t\tvalue: v,\n\t\tnext:  head,\n\t}\n\tm.length++\n}\n\n// len returns the number of key/value associations in the map.\nfunc (m *hashmap) len() int {\n\tif m != nil {\n\t\treturn m.length\n\t}\n\treturn 0\n}\n\n// entries returns a rangeable map of entries.\nfunc (m *hashmap) entries() map[int]*entry {\n\tif m != nil {\n\t\treturn m.table\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "go/ssa/interp/ops.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// If the target program panics, the interpreter panics with this type.\ntype targetPanic struct {\n\tv value\n}\n\nfunc (p targetPanic) String() string {\n\treturn toString(p.v)\n}\n\n// If the target program calls exit, the interpreter panics with this type.\ntype exitPanic int\n\n// constValue returns the value of the constant with the\n// dynamic type tag appropriate for c.Type().\nfunc constValue(c *ssa.Const) value {\n\tif c.Value == nil {\n\t\treturn zero(c.Type()) // typed zero\n\t}\n\t// c is not a type parameter so it's underlying type is basic.\n\n\tif t, ok := c.Type().Underlying().(*types.Basic); ok {\n\t\t// TODO(adonovan): eliminate untyped constants from SSA form.\n\t\tswitch t.Kind() {\n\t\tcase types.Bool, types.UntypedBool:\n\t\t\treturn constant.BoolVal(c.Value)\n\t\tcase types.Int, types.UntypedInt:\n\t\t\t// Assume sizeof(int) is same on host and target.\n\t\t\treturn int(c.Int64())\n\t\tcase types.Int8:\n\t\t\treturn int8(c.Int64())\n\t\tcase types.Int16:\n\t\t\treturn int16(c.Int64())\n\t\tcase types.Int32, types.UntypedRune:\n\t\t\treturn int32(c.Int64())\n\t\tcase types.Int64:\n\t\t\treturn c.Int64()\n\t\tcase types.Uint:\n\t\t\t// Assume sizeof(uint) is same on host and target.\n\t\t\treturn uint(c.Uint64())\n\t\tcase types.Uint8:\n\t\t\treturn uint8(c.Uint64())\n\t\tcase types.Uint16:\n\t\t\treturn uint16(c.Uint64())\n\t\tcase types.Uint32:\n\t\t\treturn uint32(c.Uint64())\n\t\tcase types.Uint64:\n\t\t\treturn c.Uint64()\n\t\tcase types.Uintptr:\n\t\t\t// Assume sizeof(uintptr) is same on host and target.\n\t\t\treturn uintptr(c.Uint64())\n\t\tcase types.Float32:\n\t\t\treturn float32(c.Float64())\n\t\tcase types.Float64, types.UntypedFloat:\n\t\t\treturn c.Float64()\n\t\tcase types.Complex64:\n\t\t\treturn complex64(c.Complex128())\n\t\tcase types.Complex128, types.UntypedComplex:\n\t\t\treturn c.Complex128()\n\t\tcase types.String, types.UntypedString:\n\t\t\tif c.Value.Kind() == constant.String {\n\t\t\t\treturn constant.StringVal(c.Value)\n\t\t\t}\n\t\t\treturn string(rune(c.Int64()))\n\t\t}\n\t}\n\n\tpanic(fmt.Sprintf(\"constValue: %s\", c))\n}\n\n// fitsInt returns true if x fits in type int according to sizes.\nfunc fitsInt(x int64, sizes types.Sizes) bool {\n\tintSize := sizes.Sizeof(types.Typ[types.Int])\n\tif intSize < sizes.Sizeof(types.Typ[types.Int64]) {\n\t\tmaxInt := int64(1)<<((intSize*8)-1) - 1\n\t\tminInt := -int64(1) << ((intSize * 8) - 1)\n\t\treturn minInt <= x && x <= maxInt\n\t}\n\treturn true\n}\n\n// asInt64 converts x, which must be an integer, to an int64.\n//\n// Callers that need a value directly usable as an int should combine this with fitsInt().\nfunc asInt64(x value) int64 {\n\tswitch x := x.(type) {\n\tcase int:\n\t\treturn int64(x)\n\tcase int8:\n\t\treturn int64(x)\n\tcase int16:\n\t\treturn int64(x)\n\tcase int32:\n\t\treturn int64(x)\n\tcase int64:\n\t\treturn x\n\tcase uint:\n\t\treturn int64(x)\n\tcase uint8:\n\t\treturn int64(x)\n\tcase uint16:\n\t\treturn int64(x)\n\tcase uint32:\n\t\treturn int64(x)\n\tcase uint64:\n\t\treturn int64(x)\n\tcase uintptr:\n\t\treturn int64(x)\n\t}\n\tpanic(fmt.Sprintf(\"cannot convert %T to int64\", x))\n}\n\n// asUint64 converts x, which must be an unsigned integer, to a uint64\n// suitable for use as a bitwise shift count.\nfunc asUint64(x value) uint64 {\n\tswitch x := x.(type) {\n\tcase uint:\n\t\treturn uint64(x)\n\tcase uint8:\n\t\treturn uint64(x)\n\tcase uint16:\n\t\treturn uint64(x)\n\tcase uint32:\n\t\treturn uint64(x)\n\tcase uint64:\n\t\treturn x\n\tcase uintptr:\n\t\treturn uint64(x)\n\t}\n\tpanic(fmt.Sprintf(\"cannot convert %T to uint64\", x))\n}\n\n// asUnsigned returns the value of x, which must be an integer type, as its equivalent unsigned type,\n// and returns true if x is non-negative.\nfunc asUnsigned(x value) (value, bool) {\n\tswitch x := x.(type) {\n\tcase int:\n\t\treturn uint(x), x >= 0\n\tcase int8:\n\t\treturn uint8(x), x >= 0\n\tcase int16:\n\t\treturn uint16(x), x >= 0\n\tcase int32:\n\t\treturn uint32(x), x >= 0\n\tcase int64:\n\t\treturn uint64(x), x >= 0\n\tcase uint, uint8, uint32, uint64, uintptr:\n\t\treturn x, true\n\t}\n\tpanic(fmt.Sprintf(\"cannot convert %T to unsigned\", x))\n}\n\n// zero returns a new \"zero\" value of the specified type.\nfunc zero(t types.Type) value {\n\tswitch t := t.(type) {\n\tcase *types.Basic:\n\t\tif t.Kind() == types.UntypedNil {\n\t\t\tpanic(\"untyped nil has no zero value\")\n\t\t}\n\t\tif t.Info()&types.IsUntyped != 0 {\n\t\t\t// TODO(adonovan): make it an invariant that\n\t\t\t// this is unreachable.  Currently some\n\t\t\t// constants have 'untyped' types when they\n\t\t\t// should be defaulted by the typechecker.\n\t\t\tt = types.Default(t).(*types.Basic)\n\t\t}\n\t\tswitch t.Kind() {\n\t\tcase types.Bool:\n\t\t\treturn false\n\t\tcase types.Int:\n\t\t\treturn int(0)\n\t\tcase types.Int8:\n\t\t\treturn int8(0)\n\t\tcase types.Int16:\n\t\t\treturn int16(0)\n\t\tcase types.Int32:\n\t\t\treturn int32(0)\n\t\tcase types.Int64:\n\t\t\treturn int64(0)\n\t\tcase types.Uint:\n\t\t\treturn uint(0)\n\t\tcase types.Uint8:\n\t\t\treturn uint8(0)\n\t\tcase types.Uint16:\n\t\t\treturn uint16(0)\n\t\tcase types.Uint32:\n\t\t\treturn uint32(0)\n\t\tcase types.Uint64:\n\t\t\treturn uint64(0)\n\t\tcase types.Uintptr:\n\t\t\treturn uintptr(0)\n\t\tcase types.Float32:\n\t\t\treturn float32(0)\n\t\tcase types.Float64:\n\t\t\treturn float64(0)\n\t\tcase types.Complex64:\n\t\t\treturn complex64(0)\n\t\tcase types.Complex128:\n\t\t\treturn complex128(0)\n\t\tcase types.String:\n\t\t\treturn \"\"\n\t\tcase types.UnsafePointer:\n\t\t\treturn unsafe.Pointer(nil)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprint(\"zero for unexpected type:\", t))\n\t\t}\n\tcase *types.Pointer:\n\t\treturn (*value)(nil)\n\tcase *types.Array:\n\t\ta := make(array, t.Len())\n\t\tfor i := range a {\n\t\t\ta[i] = zero(t.Elem())\n\t\t}\n\t\treturn a\n\tcase *types.Named:\n\t\treturn zero(t.Underlying())\n\tcase *types.Alias:\n\t\treturn zero(types.Unalias(t))\n\tcase *types.Interface:\n\t\treturn iface{} // nil type, methodset and value\n\tcase *types.Slice:\n\t\treturn []value(nil)\n\tcase *types.Struct:\n\t\ts := make(structure, t.NumFields())\n\t\tfor i := range s {\n\t\t\ts[i] = zero(t.Field(i).Type())\n\t\t}\n\t\treturn s\n\tcase *types.Tuple:\n\t\tif t.Len() == 1 {\n\t\t\treturn zero(t.At(0).Type())\n\t\t}\n\t\ts := make(tuple, t.Len())\n\t\tfor i := range s {\n\t\t\ts[i] = zero(t.At(i).Type())\n\t\t}\n\t\treturn s\n\tcase *types.Chan:\n\t\treturn chan value(nil)\n\tcase *types.Map:\n\t\tif usesBuiltinMap(t.Key()) {\n\t\t\treturn map[value]value(nil)\n\t\t}\n\t\treturn (*hashmap)(nil)\n\tcase *types.Signature:\n\t\treturn (*ssa.Function)(nil)\n\t}\n\tpanic(fmt.Sprint(\"zero: unexpected \", t))\n}\n\n// slice returns x[lo:hi:max].  Any of lo, hi and max may be nil.\nfunc slice(x, lo, hi, max value) value {\n\tvar Len, Cap int\n\tswitch x := x.(type) {\n\tcase string:\n\t\tLen = len(x)\n\tcase []value:\n\t\tLen = len(x)\n\t\tCap = cap(x)\n\tcase *value: // *array\n\t\ta := (*x).(array)\n\t\tLen = len(a)\n\t\tCap = cap(a)\n\t}\n\n\tl := int64(0)\n\tif lo != nil {\n\t\tl = asInt64(lo)\n\t}\n\n\th := int64(Len)\n\tif hi != nil {\n\t\th = asInt64(hi)\n\t}\n\n\tm := int64(Cap)\n\tif max != nil {\n\t\tm = asInt64(max)\n\t}\n\n\tswitch x := x.(type) {\n\tcase string:\n\t\treturn x[l:h]\n\tcase []value:\n\t\treturn x[l:h:m]\n\tcase *value: // *array\n\t\ta := (*x).(array)\n\t\treturn []value(a)[l:h:m]\n\t}\n\tpanic(fmt.Sprintf(\"slice: unexpected X type: %T\", x))\n}\n\n// lookup returns x[idx] where x is a map.\nfunc lookup(instr *ssa.Lookup, x, idx value) value {\n\tswitch x := x.(type) { // map or string\n\tcase map[value]value, *hashmap:\n\t\tvar v value\n\t\tvar ok bool\n\t\tswitch x := x.(type) {\n\t\tcase map[value]value:\n\t\t\tv, ok = x[idx]\n\t\tcase *hashmap:\n\t\t\tv = x.lookup(idx.(hashable))\n\t\t\tok = v != nil\n\t\t}\n\t\tif !ok {\n\t\t\tv = zero(instr.X.Type().Underlying().(*types.Map).Elem())\n\t\t}\n\t\tif instr.CommaOk {\n\t\t\tv = tuple{v, ok}\n\t\t}\n\t\treturn v\n\t}\n\tpanic(fmt.Sprintf(\"unexpected x type in Lookup: %T\", x))\n}\n\n// binop implements all arithmetic and logical binary operators for\n// numeric datatypes and strings.  Both operands must have identical\n// dynamic type.\nfunc binop(op token.Token, t types.Type, x, y value) value {\n\tswitch op {\n\tcase token.ADD:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) + y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) + y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) + y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) + y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) + y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) + y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) + y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) + y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) + y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) + y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) + y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) + y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) + y.(float64)\n\t\tcase complex64:\n\t\t\treturn x.(complex64) + y.(complex64)\n\t\tcase complex128:\n\t\t\treturn x.(complex128) + y.(complex128)\n\t\tcase string:\n\t\t\treturn x.(string) + y.(string)\n\t\t}\n\n\tcase token.SUB:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) - y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) - y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) - y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) - y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) - y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) - y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) - y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) - y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) - y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) - y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) - y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) - y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) - y.(float64)\n\t\tcase complex64:\n\t\t\treturn x.(complex64) - y.(complex64)\n\t\tcase complex128:\n\t\t\treturn x.(complex128) - y.(complex128)\n\t\t}\n\n\tcase token.MUL:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) * y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) * y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) * y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) * y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) * y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) * y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) * y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) * y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) * y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) * y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) * y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) * y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) * y.(float64)\n\t\tcase complex64:\n\t\t\treturn x.(complex64) * y.(complex64)\n\t\tcase complex128:\n\t\t\treturn x.(complex128) * y.(complex128)\n\t\t}\n\n\tcase token.QUO:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) / y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) / y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) / y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) / y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) / y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) / y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) / y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) / y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) / y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) / y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) / y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) / y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) / y.(float64)\n\t\tcase complex64:\n\t\t\treturn x.(complex64) / y.(complex64)\n\t\tcase complex128:\n\t\t\treturn x.(complex128) / y.(complex128)\n\t\t}\n\n\tcase token.REM:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) % y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) % y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) % y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) % y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) % y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) % y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) % y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) % y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) % y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) % y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) % y.(uintptr)\n\t\t}\n\n\tcase token.AND:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) & y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) & y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) & y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) & y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) & y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) & y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) & y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) & y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) & y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) & y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) & y.(uintptr)\n\t\t}\n\n\tcase token.OR:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) | y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) | y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) | y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) | y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) | y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) | y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) | y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) | y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) | y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) | y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) | y.(uintptr)\n\t\t}\n\n\tcase token.XOR:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) ^ y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) ^ y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) ^ y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) ^ y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) ^ y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) ^ y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) ^ y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) ^ y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) ^ y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) ^ y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) ^ y.(uintptr)\n\t\t}\n\n\tcase token.AND_NOT:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) &^ y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) &^ y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) &^ y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) &^ y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) &^ y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) &^ y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) &^ y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) &^ y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) &^ y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) &^ y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) &^ y.(uintptr)\n\t\t}\n\n\tcase token.SHL:\n\t\tu, ok := asUnsigned(y)\n\t\tif !ok {\n\t\t\tpanic(\"negative shift amount\")\n\t\t}\n\t\ty := asUint64(u)\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) << y\n\t\tcase int8:\n\t\t\treturn x.(int8) << y\n\t\tcase int16:\n\t\t\treturn x.(int16) << y\n\t\tcase int32:\n\t\t\treturn x.(int32) << y\n\t\tcase int64:\n\t\t\treturn x.(int64) << y\n\t\tcase uint:\n\t\t\treturn x.(uint) << y\n\t\tcase uint8:\n\t\t\treturn x.(uint8) << y\n\t\tcase uint16:\n\t\t\treturn x.(uint16) << y\n\t\tcase uint32:\n\t\t\treturn x.(uint32) << y\n\t\tcase uint64:\n\t\t\treturn x.(uint64) << y\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) << y\n\t\t}\n\n\tcase token.SHR:\n\t\tu, ok := asUnsigned(y)\n\t\tif !ok {\n\t\t\tpanic(\"negative shift amount\")\n\t\t}\n\t\ty := asUint64(u)\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) >> y\n\t\tcase int8:\n\t\t\treturn x.(int8) >> y\n\t\tcase int16:\n\t\t\treturn x.(int16) >> y\n\t\tcase int32:\n\t\t\treturn x.(int32) >> y\n\t\tcase int64:\n\t\t\treturn x.(int64) >> y\n\t\tcase uint:\n\t\t\treturn x.(uint) >> y\n\t\tcase uint8:\n\t\t\treturn x.(uint8) >> y\n\t\tcase uint16:\n\t\t\treturn x.(uint16) >> y\n\t\tcase uint32:\n\t\t\treturn x.(uint32) >> y\n\t\tcase uint64:\n\t\t\treturn x.(uint64) >> y\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) >> y\n\t\t}\n\n\tcase token.LSS:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) < y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) < y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) < y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) < y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) < y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) < y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) < y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) < y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) < y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) < y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) < y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) < y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) < y.(float64)\n\t\tcase string:\n\t\t\treturn x.(string) < y.(string)\n\t\t}\n\n\tcase token.LEQ:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) <= y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) <= y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) <= y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) <= y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) <= y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) <= y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) <= y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) <= y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) <= y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) <= y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) <= y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) <= y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) <= y.(float64)\n\t\tcase string:\n\t\t\treturn x.(string) <= y.(string)\n\t\t}\n\n\tcase token.EQL:\n\t\treturn eqnil(t, x, y)\n\n\tcase token.NEQ:\n\t\treturn !eqnil(t, x, y)\n\n\tcase token.GTR:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) > y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) > y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) > y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) > y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) > y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) > y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) > y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) > y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) > y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) > y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) > y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) > y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) > y.(float64)\n\t\tcase string:\n\t\t\treturn x.(string) > y.(string)\n\t\t}\n\n\tcase token.GEQ:\n\t\tswitch x.(type) {\n\t\tcase int:\n\t\t\treturn x.(int) >= y.(int)\n\t\tcase int8:\n\t\t\treturn x.(int8) >= y.(int8)\n\t\tcase int16:\n\t\t\treturn x.(int16) >= y.(int16)\n\t\tcase int32:\n\t\t\treturn x.(int32) >= y.(int32)\n\t\tcase int64:\n\t\t\treturn x.(int64) >= y.(int64)\n\t\tcase uint:\n\t\t\treturn x.(uint) >= y.(uint)\n\t\tcase uint8:\n\t\t\treturn x.(uint8) >= y.(uint8)\n\t\tcase uint16:\n\t\t\treturn x.(uint16) >= y.(uint16)\n\t\tcase uint32:\n\t\t\treturn x.(uint32) >= y.(uint32)\n\t\tcase uint64:\n\t\t\treturn x.(uint64) >= y.(uint64)\n\t\tcase uintptr:\n\t\t\treturn x.(uintptr) >= y.(uintptr)\n\t\tcase float32:\n\t\t\treturn x.(float32) >= y.(float32)\n\t\tcase float64:\n\t\t\treturn x.(float64) >= y.(float64)\n\t\tcase string:\n\t\t\treturn x.(string) >= y.(string)\n\t\t}\n\t}\n\tpanic(fmt.Sprintf(\"invalid binary op: %T %s %T\", x, op, y))\n}\n\n// eqnil returns the comparison x == y using the equivalence relation\n// appropriate for type t.\n// If t is a reference type, at most one of x or y may be a nil value\n// of that type.\nfunc eqnil(t types.Type, x, y value) bool {\n\tswitch t.Underlying().(type) {\n\tcase *types.Map, *types.Signature, *types.Slice:\n\t\t// Since these types don't support comparison,\n\t\t// one of the operands must be a literal nil.\n\t\tswitch x := x.(type) {\n\t\tcase *hashmap:\n\t\t\treturn (x != nil) == (y.(*hashmap) != nil)\n\t\tcase map[value]value:\n\t\t\treturn (x != nil) == (y.(map[value]value) != nil)\n\t\tcase *ssa.Function:\n\t\t\tswitch y := y.(type) {\n\t\t\tcase *ssa.Function:\n\t\t\t\treturn (x != nil) == (y != nil)\n\t\t\tcase *closure:\n\t\t\t\treturn true\n\t\t\t}\n\t\tcase *closure:\n\t\t\treturn (x != nil) == (y.(*ssa.Function) != nil)\n\t\tcase []value:\n\t\t\treturn (x != nil) == (y.([]value) != nil)\n\t\t}\n\t\tpanic(fmt.Sprintf(\"eqnil(%s): illegal dynamic type: %T\", t, x))\n\t}\n\n\treturn equals(t, x, y)\n}\n\nfunc unop(instr *ssa.UnOp, x value) value {\n\tswitch instr.Op {\n\tcase token.ARROW: // receive\n\t\tv, ok := <-x.(chan value)\n\t\tif !ok {\n\t\t\tv = zero(instr.X.Type().Underlying().(*types.Chan).Elem())\n\t\t}\n\t\tif instr.CommaOk {\n\t\t\tv = tuple{v, ok}\n\t\t}\n\t\treturn v\n\tcase token.SUB:\n\t\tswitch x := x.(type) {\n\t\tcase int:\n\t\t\treturn -x\n\t\tcase int8:\n\t\t\treturn -x\n\t\tcase int16:\n\t\t\treturn -x\n\t\tcase int32:\n\t\t\treturn -x\n\t\tcase int64:\n\t\t\treturn -x\n\t\tcase uint:\n\t\t\treturn -x\n\t\tcase uint8:\n\t\t\treturn -x\n\t\tcase uint16:\n\t\t\treturn -x\n\t\tcase uint32:\n\t\t\treturn -x\n\t\tcase uint64:\n\t\t\treturn -x\n\t\tcase uintptr:\n\t\t\treturn -x\n\t\tcase float32:\n\t\t\treturn -x\n\t\tcase float64:\n\t\t\treturn -x\n\t\tcase complex64:\n\t\t\treturn -x\n\t\tcase complex128:\n\t\t\treturn -x\n\t\t}\n\tcase token.MUL:\n\t\treturn load(typeparams.MustDeref(instr.X.Type()), x.(*value))\n\tcase token.NOT:\n\t\treturn !x.(bool)\n\tcase token.XOR:\n\t\tswitch x := x.(type) {\n\t\tcase int:\n\t\t\treturn ^x\n\t\tcase int8:\n\t\t\treturn ^x\n\t\tcase int16:\n\t\t\treturn ^x\n\t\tcase int32:\n\t\t\treturn ^x\n\t\tcase int64:\n\t\t\treturn ^x\n\t\tcase uint:\n\t\t\treturn ^x\n\t\tcase uint8:\n\t\t\treturn ^x\n\t\tcase uint16:\n\t\t\treturn ^x\n\t\tcase uint32:\n\t\t\treturn ^x\n\t\tcase uint64:\n\t\t\treturn ^x\n\t\tcase uintptr:\n\t\t\treturn ^x\n\t\t}\n\t}\n\tpanic(fmt.Sprintf(\"invalid unary op %s %T\", instr.Op, x))\n}\n\n// typeAssert checks whether dynamic type of itf is instr.AssertedType.\n// It returns the extracted value on success, and panics on failure,\n// unless instr.CommaOk, in which case it always returns a \"value,ok\" tuple.\nfunc typeAssert(instr *ssa.TypeAssert, itf iface) value {\n\tvar v value\n\terr := \"\"\n\tif itf.t == nil {\n\t\terr = fmt.Sprintf(\"interface conversion: interface is nil, not %s\", instr.AssertedType)\n\n\t} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {\n\t\tv = itf\n\t\terr = checkInterface(idst, itf)\n\n\t} else if types.Identical(itf.t, instr.AssertedType) {\n\t\tv = itf.v // extract value\n\n\t} else {\n\t\terr = fmt.Sprintf(\"interface conversion: interface is %s, not %s\", itf.t, instr.AssertedType)\n\t}\n\t// Note: if instr.Underlying==true ever becomes reachable from interp check that\n\t// types.Identical(itf.t.Underlying(), instr.AssertedType)\n\n\tif err != \"\" {\n\t\tif !instr.CommaOk {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn tuple{zero(instr.AssertedType), false}\n\t}\n\tif instr.CommaOk {\n\t\treturn tuple{v, true}\n\t}\n\treturn v\n}\n\n// This variable is no longer used but remains to prevent build breakage.\nvar CapturedOutput *bytes.Buffer\n\n// callBuiltin interprets a call to builtin fn with arguments args,\n// returning its result.\nfunc callBuiltin(caller *frame, fn *ssa.Builtin, args []value) value {\n\tswitch fn.Name() {\n\tcase \"append\":\n\t\tif len(args) == 1 {\n\t\t\treturn args[0]\n\t\t}\n\t\tif s, ok := args[1].(string); ok {\n\t\t\t// append([]byte, ...string) []byte\n\t\t\targ0 := args[0].([]value)\n\t\t\tfor i := 0; i < len(s); i++ {\n\t\t\t\targ0 = append(arg0, s[i])\n\t\t\t}\n\t\t\treturn arg0\n\t\t}\n\t\t// append([]T, ...[]T) []T\n\t\treturn append(args[0].([]value), args[1].([]value)...)\n\n\tcase \"copy\": // copy([]T, []T) int or copy([]byte, string) int\n\t\tsrc := args[1]\n\t\tif _, ok := src.(string); ok {\n\t\t\tparams := fn.Type().(*types.Signature).Params()\n\t\t\tsrc = conv(params.At(0).Type(), params.At(1).Type(), src)\n\t\t}\n\t\treturn copy(args[0].([]value), src.([]value))\n\n\tcase \"close\": // close(chan T)\n\t\tclose(args[0].(chan value))\n\t\treturn nil\n\n\tcase \"delete\": // delete(map[K]value, K)\n\t\tswitch m := args[0].(type) {\n\t\tcase map[value]value:\n\t\t\tdelete(m, args[1])\n\t\tcase *hashmap:\n\t\t\tm.delete(args[1].(hashable))\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"illegal map type: %T\", m))\n\t\t}\n\t\treturn nil\n\n\tcase \"print\", \"println\": // print(any, ...)\n\t\tln := fn.Name() == \"println\"\n\t\tvar buf bytes.Buffer\n\t\tfor i, arg := range args {\n\t\t\tif i > 0 && ln {\n\t\t\t\tbuf.WriteRune(' ')\n\t\t\t}\n\t\t\tbuf.WriteString(toString(arg))\n\t\t}\n\t\tif ln {\n\t\t\tbuf.WriteRune('\\n')\n\t\t}\n\t\tos.Stderr.Write(buf.Bytes())\n\t\treturn nil\n\n\tcase \"len\":\n\t\tswitch x := args[0].(type) {\n\t\tcase string:\n\t\t\treturn len(x)\n\t\tcase array:\n\t\t\treturn len(x)\n\t\tcase *value:\n\t\t\treturn len((*x).(array))\n\t\tcase []value:\n\t\t\treturn len(x)\n\t\tcase map[value]value:\n\t\t\treturn len(x)\n\t\tcase *hashmap:\n\t\t\treturn x.len()\n\t\tcase chan value:\n\t\t\treturn len(x)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"len: illegal operand: %T\", x))\n\t\t}\n\n\tcase \"cap\":\n\t\tswitch x := args[0].(type) {\n\t\tcase array:\n\t\t\treturn cap(x)\n\t\tcase *value:\n\t\t\treturn cap((*x).(array))\n\t\tcase []value:\n\t\t\treturn cap(x)\n\t\tcase chan value:\n\t\t\treturn cap(x)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"cap: illegal operand: %T\", x))\n\t\t}\n\n\tcase \"min\":\n\t\treturn foldLeft(min, args)\n\tcase \"max\":\n\t\treturn foldLeft(max, args)\n\n\tcase \"real\":\n\t\tswitch c := args[0].(type) {\n\t\tcase complex64:\n\t\t\treturn real(c)\n\t\tcase complex128:\n\t\t\treturn real(c)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"real: illegal operand: %T\", c))\n\t\t}\n\n\tcase \"imag\":\n\t\tswitch c := args[0].(type) {\n\t\tcase complex64:\n\t\t\treturn imag(c)\n\t\tcase complex128:\n\t\t\treturn imag(c)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"imag: illegal operand: %T\", c))\n\t\t}\n\n\tcase \"complex\":\n\t\tswitch f := args[0].(type) {\n\t\tcase float32:\n\t\t\treturn complex(f, args[1].(float32))\n\t\tcase float64:\n\t\t\treturn complex(f, args[1].(float64))\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"complex: illegal operand: %T\", f))\n\t\t}\n\n\tcase \"panic\":\n\t\t// ssa.Panic handles most cases; this is only for \"go\n\t\t// panic\" or \"defer panic\".\n\t\tpanic(targetPanic{args[0]})\n\n\tcase \"recover\":\n\t\treturn doRecover(caller)\n\n\tcase \"ssa:wrapnilchk\":\n\t\trecv := args[0]\n\t\tif recv.(*value) == nil {\n\t\t\trecvType := args[1]\n\t\t\tmethodName := args[2]\n\t\t\tpanic(fmt.Sprintf(\"value method (%s).%s called using nil *%s pointer\",\n\t\t\t\trecvType, methodName, recvType))\n\t\t}\n\t\treturn recv\n\n\tcase \"ssa:deferstack\":\n\t\treturn &caller.defers\n\t}\n\n\tpanic(\"unknown built-in: \" + fn.Name())\n}\n\nfunc rangeIter(x value) iter {\n\tswitch x := x.(type) {\n\tcase map[value]value:\n\t\treturn &mapIter{iter: reflect.ValueOf(x).MapRange()}\n\tcase *hashmap:\n\t\treturn &hashmapIter{iter: reflect.ValueOf(x.entries()).MapRange()}\n\tcase string:\n\t\treturn &stringIter{Reader: strings.NewReader(x)}\n\t}\n\tpanic(fmt.Sprintf(\"cannot range over %T\", x))\n}\n\n// widen widens a basic typed value x to the widest type of its\n// category, one of:\n//\n//\tbool, int64, uint64, float64, complex128, string.\n//\n// This is inefficient but reduces the size of the cross-product of\n// cases we have to consider.\nfunc widen(x value) value {\n\tswitch y := x.(type) {\n\tcase bool, int64, uint64, float64, complex128, string, unsafe.Pointer:\n\t\treturn x\n\tcase int:\n\t\treturn int64(y)\n\tcase int8:\n\t\treturn int64(y)\n\tcase int16:\n\t\treturn int64(y)\n\tcase int32:\n\t\treturn int64(y)\n\tcase uint:\n\t\treturn uint64(y)\n\tcase uint8:\n\t\treturn uint64(y)\n\tcase uint16:\n\t\treturn uint64(y)\n\tcase uint32:\n\t\treturn uint64(y)\n\tcase uintptr:\n\t\treturn uint64(y)\n\tcase float32:\n\t\treturn float64(y)\n\tcase complex64:\n\t\treturn complex128(y)\n\t}\n\tpanic(fmt.Sprintf(\"cannot widen %T\", x))\n}\n\n// conv converts the value x of type t_src to type t_dst and returns\n// the result.\n// Possible cases are described with the ssa.Convert operator.\nfunc conv(t_dst, t_src types.Type, x value) value {\n\tut_src := t_src.Underlying()\n\tut_dst := t_dst.Underlying()\n\n\t// Destination type is not an \"untyped\" type.\n\tif b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {\n\t\tpanic(\"oops: conversion to 'untyped' type: \" + b.String())\n\t}\n\n\t// Nor is it an interface type.\n\tif _, ok := ut_dst.(*types.Interface); ok {\n\t\tif _, ok := ut_src.(*types.Interface); ok {\n\t\t\tpanic(\"oops: Convert should be ChangeInterface\")\n\t\t} else {\n\t\t\tpanic(\"oops: Convert should be MakeInterface\")\n\t\t}\n\t}\n\n\t// Remaining conversions:\n\t//    + untyped string/number/bool constant to a specific\n\t//      representation.\n\t//    + conversions between non-complex numeric types.\n\t//    + conversions between complex numeric types.\n\t//    + integer/[]byte/[]rune -> string.\n\t//    + string -> []byte/[]rune.\n\t//\n\t// All are treated the same: first we extract the value to the\n\t// widest representation (int64, uint64, float64, complex128,\n\t// or string), then we convert it to the desired type.\n\n\tswitch ut_src := ut_src.(type) {\n\tcase *types.Pointer:\n\t\tswitch ut_dst := ut_dst.(type) {\n\t\tcase *types.Basic:\n\t\t\t// *value to unsafe.Pointer?\n\t\t\tif ut_dst.Kind() == types.UnsafePointer {\n\t\t\t\treturn unsafe.Pointer(x.(*value))\n\t\t\t}\n\t\t}\n\n\tcase *types.Slice:\n\t\t// []byte or []rune -> string\n\t\tswitch ut_src.Elem().Underlying().(*types.Basic).Kind() {\n\t\tcase types.Byte:\n\t\t\tx := x.([]value)\n\t\t\tb := make([]byte, 0, len(x))\n\t\t\tfor i := range x {\n\t\t\t\tb = append(b, x[i].(byte))\n\t\t\t}\n\t\t\treturn string(b)\n\n\t\tcase types.Rune:\n\t\t\tx := x.([]value)\n\t\t\tr := make([]rune, 0, len(x))\n\t\t\tfor i := range x {\n\t\t\t\tr = append(r, x[i].(rune))\n\t\t\t}\n\t\t\treturn string(r)\n\t\t}\n\n\tcase *types.Basic:\n\t\tx = widen(x)\n\n\t\t// integer -> string?\n\t\tif ut_src.Info()&types.IsInteger != 0 {\n\t\t\tif ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String {\n\t\t\t\treturn fmt.Sprintf(\"%c\", x)\n\t\t\t}\n\t\t}\n\n\t\t// string -> []rune, []byte or string?\n\t\tif s, ok := x.(string); ok {\n\t\t\tswitch ut_dst := ut_dst.(type) {\n\t\t\tcase *types.Slice:\n\t\t\t\tvar res []value\n\t\t\t\tswitch ut_dst.Elem().Underlying().(*types.Basic).Kind() {\n\t\t\t\tcase types.Rune:\n\t\t\t\t\tfor _, r := range []rune(s) {\n\t\t\t\t\t\tres = append(res, r)\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\tcase types.Byte:\n\t\t\t\t\tfor _, b := range []byte(s) {\n\t\t\t\t\t\tres = append(res, b)\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\n\t\t\tcase *types.Basic:\n\t\t\t\tif ut_dst.Kind() == types.String {\n\t\t\t\t\treturn x.(string)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak // fail: no other conversions for string\n\t\t}\n\n\t\t// unsafe.Pointer -> *value\n\t\tif ut_src.Kind() == types.UnsafePointer {\n\t\t\t// TODO(adonovan): this is wrong and cannot\n\t\t\t// really be fixed with the current design.\n\t\t\t//\n\t\t\t// return (*value)(x.(unsafe.Pointer))\n\t\t\t// creates a new pointer of a different\n\t\t\t// type but the underlying interface value\n\t\t\t// knows its \"true\" type and so cannot be\n\t\t\t// meaningfully used through the new pointer.\n\t\t\t//\n\t\t\t// To make this work, the interpreter needs to\n\t\t\t// simulate the memory layout of a real\n\t\t\t// compiled implementation.\n\t\t\t//\n\t\t\t// To at least preserve type-safety, we'll\n\t\t\t// just return the zero value of the\n\t\t\t// destination type.\n\t\t\treturn zero(t_dst)\n\t\t}\n\n\t\t// Conversions between complex numeric types?\n\t\tif ut_src.Info()&types.IsComplex != 0 {\n\t\t\tswitch ut_dst.(*types.Basic).Kind() {\n\t\t\tcase types.Complex64:\n\t\t\t\treturn complex64(x.(complex128))\n\t\t\tcase types.Complex128:\n\t\t\t\treturn x.(complex128)\n\t\t\t}\n\t\t\tbreak // fail: no other conversions for complex\n\t\t}\n\n\t\t// Conversions between non-complex numeric types?\n\t\tif ut_src.Info()&types.IsNumeric != 0 {\n\t\t\tkind := ut_dst.(*types.Basic).Kind()\n\t\t\tswitch x := x.(type) {\n\t\t\tcase int64: // signed integer -> numeric?\n\t\t\t\tswitch kind {\n\t\t\t\tcase types.Int:\n\t\t\t\t\treturn int(x)\n\t\t\t\tcase types.Int8:\n\t\t\t\t\treturn int8(x)\n\t\t\t\tcase types.Int16:\n\t\t\t\t\treturn int16(x)\n\t\t\t\tcase types.Int32:\n\t\t\t\t\treturn int32(x)\n\t\t\t\tcase types.Int64:\n\t\t\t\t\treturn int64(x)\n\t\t\t\tcase types.Uint:\n\t\t\t\t\treturn uint(x)\n\t\t\t\tcase types.Uint8:\n\t\t\t\t\treturn uint8(x)\n\t\t\t\tcase types.Uint16:\n\t\t\t\t\treturn uint16(x)\n\t\t\t\tcase types.Uint32:\n\t\t\t\t\treturn uint32(x)\n\t\t\t\tcase types.Uint64:\n\t\t\t\t\treturn uint64(x)\n\t\t\t\tcase types.Uintptr:\n\t\t\t\t\treturn uintptr(x)\n\t\t\t\tcase types.Float32:\n\t\t\t\t\treturn float32(x)\n\t\t\t\tcase types.Float64:\n\t\t\t\t\treturn float64(x)\n\t\t\t\t}\n\n\t\t\tcase uint64: // unsigned integer -> numeric?\n\t\t\t\tswitch kind {\n\t\t\t\tcase types.Int:\n\t\t\t\t\treturn int(x)\n\t\t\t\tcase types.Int8:\n\t\t\t\t\treturn int8(x)\n\t\t\t\tcase types.Int16:\n\t\t\t\t\treturn int16(x)\n\t\t\t\tcase types.Int32:\n\t\t\t\t\treturn int32(x)\n\t\t\t\tcase types.Int64:\n\t\t\t\t\treturn int64(x)\n\t\t\t\tcase types.Uint:\n\t\t\t\t\treturn uint(x)\n\t\t\t\tcase types.Uint8:\n\t\t\t\t\treturn uint8(x)\n\t\t\t\tcase types.Uint16:\n\t\t\t\t\treturn uint16(x)\n\t\t\t\tcase types.Uint32:\n\t\t\t\t\treturn uint32(x)\n\t\t\t\tcase types.Uint64:\n\t\t\t\t\treturn uint64(x)\n\t\t\t\tcase types.Uintptr:\n\t\t\t\t\treturn uintptr(x)\n\t\t\t\tcase types.Float32:\n\t\t\t\t\treturn float32(x)\n\t\t\t\tcase types.Float64:\n\t\t\t\t\treturn float64(x)\n\t\t\t\t}\n\n\t\t\tcase float64: // floating point -> numeric?\n\t\t\t\tswitch kind {\n\t\t\t\tcase types.Int:\n\t\t\t\t\treturn int(x)\n\t\t\t\tcase types.Int8:\n\t\t\t\t\treturn int8(x)\n\t\t\t\tcase types.Int16:\n\t\t\t\t\treturn int16(x)\n\t\t\t\tcase types.Int32:\n\t\t\t\t\treturn int32(x)\n\t\t\t\tcase types.Int64:\n\t\t\t\t\treturn int64(x)\n\t\t\t\tcase types.Uint:\n\t\t\t\t\treturn uint(x)\n\t\t\t\tcase types.Uint8:\n\t\t\t\t\treturn uint8(x)\n\t\t\t\tcase types.Uint16:\n\t\t\t\t\treturn uint16(x)\n\t\t\t\tcase types.Uint32:\n\t\t\t\t\treturn uint32(x)\n\t\t\t\tcase types.Uint64:\n\t\t\t\t\treturn uint64(x)\n\t\t\t\tcase types.Uintptr:\n\t\t\t\t\treturn uintptr(x)\n\t\t\t\tcase types.Float32:\n\t\t\t\t\treturn float32(x)\n\t\t\t\tcase types.Float64:\n\t\t\t\t\treturn float64(x)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpanic(fmt.Sprintf(\"unsupported conversion: %s  -> %s, dynamic type %T\", t_src, t_dst, x))\n}\n\n// sliceToArrayPointer converts the value x of type slice to type t_dst\n// a pointer to array and returns the result.\nfunc sliceToArrayPointer(t_dst, t_src types.Type, x value) value {\n\tif _, ok := t_src.Underlying().(*types.Slice); ok {\n\t\tif ptr, ok := t_dst.Underlying().(*types.Pointer); ok {\n\t\t\tif arr, ok := ptr.Elem().Underlying().(*types.Array); ok {\n\t\t\t\tx := x.([]value)\n\t\t\t\tif arr.Len() > int64(len(x)) {\n\t\t\t\t\tpanic(\"array length is greater than slice length\")\n\t\t\t\t}\n\t\t\t\tif x == nil {\n\t\t\t\t\treturn zero(t_dst)\n\t\t\t\t}\n\t\t\t\tv := value(array(x[:arr.Len()]))\n\t\t\t\treturn &v\n\t\t\t}\n\t\t}\n\t}\n\n\tpanic(fmt.Sprintf(\"unsupported conversion: %s  -> %s, dynamic type %T\", t_src, t_dst, x))\n}\n\n// checkInterface checks that the method set of x implements the\n// interface itype.\n// On success it returns \"\", on failure, an error message.\nfunc checkInterface(itype *types.Interface, x iface) string {\n\tif meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {\n\t\treturn fmt.Sprintf(\"interface conversion: %v is not %v: missing method %s\",\n\t\t\tx.t, itype, meth.Name())\n\t}\n\treturn \"\" // ok\n}\n\nfunc foldLeft(op func(value, value) value, args []value) value {\n\tx := args[0]\n\tfor _, arg := range args[1:] {\n\t\tx = op(x, arg)\n\t}\n\treturn x\n}\n\nfunc min(x, y value) value {\n\tswitch x := x.(type) {\n\tcase float32:\n\t\treturn fmin(x, y.(float32))\n\tcase float64:\n\t\treturn fmin(x, y.(float64))\n\t}\n\n\t// return (y < x) ? y : x\n\tif binop(token.LSS, nil, y, x).(bool) {\n\t\treturn y\n\t}\n\treturn x\n}\n\nfunc max(x, y value) value {\n\tswitch x := x.(type) {\n\tcase float32:\n\t\treturn fmax(x, y.(float32))\n\tcase float64:\n\t\treturn fmax(x, y.(float64))\n\t}\n\n\t// return (y > x) ? y : x\n\tif binop(token.GTR, nil, y, x).(bool) {\n\t\treturn y\n\t}\n\treturn x\n}\n\n// copied from $GOROOT/src/runtime/minmax.go\n\ntype floaty interface{ ~float32 | ~float64 }\n\nfunc fmin[F floaty](x, y F) F {\n\tif y != y || y < x {\n\t\treturn y\n\t}\n\tif x != x || x < y || x != 0 {\n\t\treturn x\n\t}\n\t// x and y are both ±0\n\t// if either is -0, return -0; else return +0\n\treturn forbits(x, y)\n}\n\nfunc fmax[F floaty](x, y F) F {\n\tif y != y || y > x {\n\t\treturn y\n\t}\n\tif x != x || x > y || x != 0 {\n\t\treturn x\n\t}\n\t// x and y are both ±0\n\t// if both are -0, return -0; else return +0\n\treturn fandbits(x, y)\n}\n\nfunc forbits[F floaty](x, y F) F {\n\tswitch unsafe.Sizeof(x) {\n\tcase 4:\n\t\t*(*uint32)(unsafe.Pointer(&x)) |= *(*uint32)(unsafe.Pointer(&y))\n\tcase 8:\n\t\t*(*uint64)(unsafe.Pointer(&x)) |= *(*uint64)(unsafe.Pointer(&y))\n\t}\n\treturn x\n}\n\nfunc fandbits[F floaty](x, y F) F {\n\tswitch unsafe.Sizeof(x) {\n\tcase 4:\n\t\t*(*uint32)(unsafe.Pointer(&x)) &= *(*uint32)(unsafe.Pointer(&y))\n\tcase 8:\n\t\t*(*uint64)(unsafe.Pointer(&x)) &= *(*uint64)(unsafe.Pointer(&y))\n\t}\n\treturn x\n}\n"
  },
  {
    "path": "go/ssa/interp/rangefunc_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp_test\n\nimport (\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestIssue69298(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\n\tgoroot := makeGoroot(t)\n\trun(t, filepath.Join(\"testdata\", \"fixedbugs\", \"issue69298.go\"), goroot)\n}\n\nfunc TestRangeFunc(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\n\tgoroot := makeGoroot(t)\n\tout := run(t, filepath.Join(\"testdata\", \"rangefunc.go\"), goroot)\n\n\t// Check the output of the tests.\n\tconst (\n\t\tRERR_DONE      = \"Saw expected panic: yield function called after range loop exit\"\n\t\tRERR_MISSING   = \"Saw expected panic: iterator call did not preserve panic\"\n\t\tRERR_EXHAUSTED = RERR_DONE // ssa does not distinguish. Same message as RERR_DONE.\n\n\t\tCERR_DONE      = \"Saw expected panic: checked rangefunc error: loop iteration after body done\"\n\t\tCERR_EXHAUSTED = \"Saw expected panic: checked rangefunc error: loop iteration after iterator exit\"\n\t\tCERR_MISSING   = \"Saw expected panic: checked rangefunc error: loop iterator swallowed panic\"\n\n\t\tpanickyIterMsg = \"Saw expected panic: Panicky iterator panicking\"\n\t)\n\texpected := map[string][]string{\n\t\t// rangefunc.go\n\t\t\"TestCheck\":                           {\"i = 45\", CERR_DONE},\n\t\t\"TestCooperativeBadOfSliceIndex\":      {RERR_EXHAUSTED, \"i = 36\"},\n\t\t\"TestCooperativeBadOfSliceIndexCheck\": {CERR_EXHAUSTED, \"i = 36\"},\n\t\t\"TestTrickyIterAll\":                   {\"i = 36\", RERR_EXHAUSTED},\n\t\t\"TestTrickyIterOne\":                   {\"i = 1\", RERR_EXHAUSTED},\n\t\t\"TestTrickyIterZero\":                  {\"i = 0\", RERR_EXHAUSTED},\n\t\t\"TestTrickyIterZeroCheck\":             {\"i = 0\", CERR_EXHAUSTED},\n\t\t\"TestTrickyIterEcho\": {\n\t\t\t\"first loop i=0\",\n\t\t\t\"first loop i=1\",\n\t\t\t\"first loop i=3\",\n\t\t\t\"first loop i=6\",\n\t\t\t\"i = 10\",\n\t\t\t\"second loop i=0\",\n\t\t\tRERR_EXHAUSTED,\n\t\t\t\"end i=0\",\n\t\t},\n\t\t\"TestTrickyIterEcho2\": {\n\t\t\t\"k=0,x=1,i=0\",\n\t\t\t\"k=0,x=2,i=1\",\n\t\t\t\"k=0,x=3,i=3\",\n\t\t\t\"k=0,x=4,i=6\",\n\t\t\t\"i = 10\",\n\t\t\t\"k=1,x=1,i=0\",\n\t\t\tRERR_EXHAUSTED,\n\t\t\t\"end i=1\",\n\t\t},\n\t\t\"TestBreak1\":                {\"[1 2 -1 1 2 -2 1 2 -3]\"},\n\t\t\"TestBreak2\":                {\"[1 2 -1 1 2 -2 1 2 -3]\"},\n\t\t\"TestContinue\":              {\"[-1 1 2 -2 1 2 -3 1 2 -4]\"},\n\t\t\"TestBreak3\":                {\"[100 10 2 4 200 10 2 4 20 2 4 300 10 2 4 20 2 4 30]\"},\n\t\t\"TestBreak1BadA\":            {\"[1 2 -1 1 2 -2 1 2 -3]\", RERR_DONE},\n\t\t\"TestBreak1BadB\":            {\"[1 2]\", RERR_DONE},\n\t\t\"TestMultiCont0\":            {\"[1000 10 2 4 2000]\"},\n\t\t\"TestMultiCont1\":            {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiCont2\":            {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiCont3\":            {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiBreak0\":           {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiBreak1\":           {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiBreak2\":           {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestMultiBreak3\":           {\"[1000 10 2 4]\", RERR_DONE},\n\t\t\"TestPanickyIterator1\":      {panickyIterMsg},\n\t\t\"TestPanickyIterator1Check\": {panickyIterMsg},\n\t\t\"TestPanickyIterator2\":      {RERR_MISSING},\n\t\t\"TestPanickyIterator2Check\": {CERR_MISSING},\n\t\t\"TestPanickyIterator3\":      {\"[100 10 1 2 200 10 1 2]\"},\n\t\t\"TestPanickyIterator3Check\": {\"[100 10 1 2 200 10 1 2]\"},\n\t\t\"TestPanickyIterator4\":      {RERR_MISSING},\n\t\t\"TestPanickyIterator4Check\": {CERR_MISSING},\n\t\t\"TestVeryBad1\":              {\"[1 10]\"},\n\t\t\"TestVeryBad2\":              {\"[1 10]\"},\n\t\t\"TestVeryBadCheck\":          {\"[1 10]\"},\n\t\t\"TestOk\":                    {\"[1 10]\"},\n\t\t\"TestBreak1BadDefer\":        {RERR_DONE, \"[1 2 -1 1 2 -2 1 2 -3 -30 -20 -10]\"},\n\t\t\"TestReturns\":               {\"[-1 1 2 -10]\", \"[-1 1 2 -10]\", RERR_DONE, \"[-1 1 2 -10]\", RERR_DONE},\n\t\t\"TestGotoA\":                 {\"testGotoA1[-1 1 2 -2 1 2 -3 1 2 -4 -30 -20 -10]\", \"testGotoA2[-1 1 2 -2 1 2 -3 1 2 -4 -30 -20 -10]\", RERR_DONE, \"testGotoA3[-1 1 2 -10]\", RERR_DONE},\n\t\t\"TestGotoB\":                 {\"testGotoB1[-1 1 2 999 -10]\", \"testGotoB2[-1 1 2 -10]\", RERR_DONE, \"testGotoB3[-1 1 2 -10]\", RERR_DONE},\n\t\t\"TestPanicReturns\": {\n\t\t\t\"Got expected 'f return'\",\n\t\t\t\"Got expected 'g return'\",\n\t\t\t\"Got expected 'h return'\",\n\t\t\t\"Got expected 'k return'\",\n\t\t\t\"Got expected 'j return'\",\n\t\t\t\"Got expected 'm return'\",\n\t\t\t\"Got expected 'n return and n closure return'\",\n\t\t},\n\t}\n\tgot := make(map[string][]string)\n\tfor ln := range strings.SplitSeq(out, \"\\n\") {\n\t\tif ind := strings.Index(ln, \" \\t \"); ind >= 0 {\n\t\t\tn, m := ln[:ind], ln[ind+3:]\n\t\t\tgot[n] = append(got[n], m)\n\t\t}\n\t}\n\tfor n, es := range expected {\n\t\tif gs := got[n]; !reflect.DeepEqual(es, gs) {\n\t\t\tt.Errorf(\"Output of test %s did not match expected output %v. got %v\", n, es, gs)\n\t\t}\n\t}\n\tfor n, gs := range got {\n\t\tif expected[n] == nil {\n\t\t\tt.Errorf(\"No expected output for test %s. got %v\", n, gs)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/reflect.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp\n\n// Emulated \"reflect\" package.\n//\n// We completely replace the built-in \"reflect\" package.\n// The only thing clients can depend upon are that reflect.Type is an\n// interface and reflect.Value is an (opaque) struct.\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/ssa\"\n)\n\ntype opaqueType struct {\n\ttypes.Type\n\tname string\n}\n\nfunc (t *opaqueType) String() string { return t.name }\n\n// A bogus \"reflect\" type-checker package.  Shared across interpreters.\nvar reflectTypesPackage = types.NewPackage(\"reflect\", \"reflect\")\n\n// rtype is the concrete type the interpreter uses to implement the\n// reflect.Type interface.\n//\n// type rtype <opaque>\nvar rtypeType = makeNamedType(\"rtype\", &opaqueType{nil, \"rtype\"})\n\n// error is an (interpreted) named type whose underlying type is string.\n// The interpreter uses it for all implementations of the built-in error\n// interface that it creates.\n// We put it in the \"reflect\" package for expedience.\n//\n// type error string\nvar errorType = makeNamedType(\"error\", &opaqueType{nil, \"error\"})\n\nfunc makeNamedType(name string, underlying types.Type) *types.Named {\n\tobj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil)\n\treturn types.NewNamed(obj, underlying, nil)\n}\n\nfunc makeReflectValue(t types.Type, v value) value {\n\treturn structure{rtype{t}, v}\n}\n\n// Given a reflect.Value, returns its rtype.\nfunc rV2T(v value) rtype {\n\treturn v.(structure)[0].(rtype)\n}\n\n// Given a reflect.Value, returns the underlying interpreter value.\nfunc rV2V(v value) value {\n\treturn v.(structure)[1]\n}\n\n// makeReflectType boxes up an rtype in a reflect.Type interface.\nfunc makeReflectType(rt rtype) value {\n\treturn iface{rtypeType, rt}\n}\n\nfunc ext۰reflect۰rtype۰Bits(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) int\n\trt := args[0].(rtype).t\n\tbasic, ok := rt.Underlying().(*types.Basic)\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"reflect.Type.Bits(%T): non-basic type\", rt))\n\t}\n\treturn int(fr.i.sizes.Sizeof(basic)) * 8\n}\n\nfunc ext۰reflect۰rtype۰Elem(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) reflect.Type\n\treturn makeReflectType(rtype{args[0].(rtype).t.Underlying().(interface {\n\t\tElem() types.Type\n\t}).Elem()})\n}\n\nfunc ext۰reflect۰rtype۰Field(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype, i int) reflect.StructField\n\tst := args[0].(rtype).t.Underlying().(*types.Struct)\n\ti := args[1].(int)\n\tf := st.Field(i)\n\treturn structure{\n\t\tf.Name(),\n\t\tf.Pkg().Path(),\n\t\tmakeReflectType(rtype{f.Type()}),\n\t\tst.Tag(i),\n\t\t0,         // TODO(adonovan): offset\n\t\t[]value{}, // TODO(adonovan): indices\n\t\tf.Anonymous(),\n\t}\n}\n\nfunc ext۰reflect۰rtype۰In(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype, i int) int\n\ti := args[1].(int)\n\treturn makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Params().At(i).Type()})\n}\n\nfunc ext۰reflect۰rtype۰Kind(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) uint\n\treturn uint(reflectKind(args[0].(rtype).t))\n}\n\nfunc ext۰reflect۰rtype۰NumField(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) int\n\treturn args[0].(rtype).t.Underlying().(*types.Struct).NumFields()\n}\n\nfunc ext۰reflect۰rtype۰NumIn(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) int\n\treturn args[0].(rtype).t.Underlying().(*types.Signature).Params().Len()\n}\n\nfunc ext۰reflect۰rtype۰NumMethod(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) int\n\treturn fr.i.prog.MethodSets.MethodSet(args[0].(rtype).t).Len()\n}\n\nfunc ext۰reflect۰rtype۰NumOut(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) int\n\treturn args[0].(rtype).t.Underlying().(*types.Signature).Results().Len()\n}\n\nfunc ext۰reflect۰rtype۰Out(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype, i int) int\n\ti := args[1].(int)\n\treturn makeReflectType(rtype{args[0].(rtype).t.Underlying().(*types.Signature).Results().At(i).Type()})\n}\n\nfunc ext۰reflect۰rtype۰Size(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) uintptr\n\treturn uintptr(fr.i.sizes.Sizeof(args[0].(rtype).t))\n}\n\nfunc ext۰reflect۰rtype۰String(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) string\n\treturn args[0].(rtype).t.String()\n}\n\nfunc ext۰reflect۰New(fr *frame, args []value) value {\n\t// Signature: func (t reflect.Type) reflect.Value\n\tt := args[0].(iface).v.(rtype).t\n\talloc := zero(t)\n\treturn makeReflectValue(types.NewPointer(t), &alloc)\n}\n\nfunc ext۰reflect۰SliceOf(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) Type\n\treturn makeReflectType(rtype{types.NewSlice(args[0].(iface).v.(rtype).t)})\n}\n\nfunc ext۰reflect۰TypeOf(fr *frame, args []value) value {\n\t// Signature: func (t reflect.rtype) Type\n\treturn makeReflectType(rtype{args[0].(iface).t})\n}\n\nfunc ext۰reflect۰ValueOf(fr *frame, args []value) value {\n\t// Signature: func (interface{}) reflect.Value\n\titf := args[0].(iface)\n\treturn makeReflectValue(itf.t, itf.v)\n}\n\nfunc ext۰reflect۰Zero(fr *frame, args []value) value {\n\t// Signature: func (t reflect.Type) reflect.Value\n\tt := args[0].(iface).v.(rtype).t\n\treturn makeReflectValue(t, zero(t))\n}\n\nfunc reflectKind(t types.Type) reflect.Kind {\n\tswitch t := t.(type) {\n\tcase *types.Named, *types.Alias:\n\t\treturn reflectKind(t.Underlying())\n\tcase *types.Basic:\n\t\tswitch t.Kind() {\n\t\tcase types.Bool:\n\t\t\treturn reflect.Bool\n\t\tcase types.Int:\n\t\t\treturn reflect.Int\n\t\tcase types.Int8:\n\t\t\treturn reflect.Int8\n\t\tcase types.Int16:\n\t\t\treturn reflect.Int16\n\t\tcase types.Int32:\n\t\t\treturn reflect.Int32\n\t\tcase types.Int64:\n\t\t\treturn reflect.Int64\n\t\tcase types.Uint:\n\t\t\treturn reflect.Uint\n\t\tcase types.Uint8:\n\t\t\treturn reflect.Uint8\n\t\tcase types.Uint16:\n\t\t\treturn reflect.Uint16\n\t\tcase types.Uint32:\n\t\t\treturn reflect.Uint32\n\t\tcase types.Uint64:\n\t\t\treturn reflect.Uint64\n\t\tcase types.Uintptr:\n\t\t\treturn reflect.Uintptr\n\t\tcase types.Float32:\n\t\t\treturn reflect.Float32\n\t\tcase types.Float64:\n\t\t\treturn reflect.Float64\n\t\tcase types.Complex64:\n\t\t\treturn reflect.Complex64\n\t\tcase types.Complex128:\n\t\t\treturn reflect.Complex128\n\t\tcase types.String:\n\t\t\treturn reflect.String\n\t\tcase types.UnsafePointer:\n\t\t\treturn reflect.UnsafePointer\n\t\t}\n\tcase *types.Array:\n\t\treturn reflect.Array\n\tcase *types.Chan:\n\t\treturn reflect.Chan\n\tcase *types.Signature:\n\t\treturn reflect.Func\n\tcase *types.Interface:\n\t\treturn reflect.Interface\n\tcase *types.Map:\n\t\treturn reflect.Map\n\tcase *types.Pointer:\n\t\treturn reflect.Pointer\n\tcase *types.Slice:\n\t\treturn reflect.Slice\n\tcase *types.Struct:\n\t\treturn reflect.Struct\n\t}\n\tpanic(fmt.Sprint(\"unexpected type: \", t))\n}\n\nfunc ext۰reflect۰Value۰Kind(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) uint\n\treturn uint(reflectKind(rV2T(args[0]).t))\n}\n\nfunc ext۰reflect۰Value۰String(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) string\n\treturn toString(rV2V(args[0]))\n}\n\nfunc ext۰reflect۰Value۰Type(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) reflect.Type\n\treturn makeReflectType(rV2T(args[0]))\n}\n\nfunc ext۰reflect۰Value۰Uint(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) uint64\n\tswitch v := rV2V(args[0]).(type) {\n\tcase uint:\n\t\treturn uint64(v)\n\tcase uint8:\n\t\treturn uint64(v)\n\tcase uint16:\n\t\treturn uint64(v)\n\tcase uint32:\n\t\treturn uint64(v)\n\tcase uint64:\n\t\treturn uint64(v)\n\tcase uintptr:\n\t\treturn uint64(v)\n\t}\n\tpanic(\"reflect.Value.Uint\")\n}\n\nfunc ext۰reflect۰Value۰Len(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) int\n\tswitch v := rV2V(args[0]).(type) {\n\tcase string:\n\t\treturn len(v)\n\tcase array:\n\t\treturn len(v)\n\tcase chan value:\n\t\treturn cap(v)\n\tcase []value:\n\t\treturn len(v)\n\tcase *hashmap:\n\t\treturn v.len()\n\tcase map[value]value:\n\t\treturn len(v)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).Len(%v)\", v))\n\t}\n}\n\nfunc ext۰reflect۰Value۰MapIndex(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) Value\n\ttValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()\n\tk := rV2V(args[1])\n\tswitch m := rV2V(args[0]).(type) {\n\tcase map[value]value:\n\t\tif v, ok := m[k]; ok {\n\t\t\treturn makeReflectValue(tValue, v)\n\t\t}\n\n\tcase *hashmap:\n\t\tif v := m.lookup(k.(hashable)); v != nil {\n\t\t\treturn makeReflectValue(tValue, v)\n\t\t}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"(reflect.Value).MapIndex(%T, %T)\", m, k))\n\t}\n\treturn makeReflectValue(nil, nil)\n}\n\nfunc ext۰reflect۰Value۰MapKeys(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) []Value\n\tvar keys []value\n\ttKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()\n\tswitch v := rV2V(args[0]).(type) {\n\tcase map[value]value:\n\t\tfor k := range v {\n\t\t\tkeys = append(keys, makeReflectValue(tKey, k))\n\t\t}\n\n\tcase *hashmap:\n\t\tfor _, e := range v.entries() {\n\t\t\tfor ; e != nil; e = e.next {\n\t\t\t\tkeys = append(keys, makeReflectValue(tKey, e.key))\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"(reflect.Value).MapKeys(%T)\", v))\n\t}\n\treturn keys\n}\n\nfunc ext۰reflect۰Value۰NumField(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) int\n\treturn len(rV2V(args[0]).(structure))\n}\n\nfunc ext۰reflect۰Value۰NumMethod(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) int\n\treturn fr.i.prog.MethodSets.MethodSet(rV2T(args[0]).t).Len()\n}\n\nfunc ext۰reflect۰Value۰Pointer(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value) uintptr\n\tswitch v := rV2V(args[0]).(type) {\n\tcase *value:\n\t\treturn uintptr(unsafe.Pointer(v))\n\tcase chan value:\n\t\treturn reflect.ValueOf(v).Pointer()\n\tcase []value:\n\t\treturn reflect.ValueOf(v).Pointer()\n\tcase *hashmap:\n\t\treturn reflect.ValueOf(v.entries()).Pointer()\n\tcase map[value]value:\n\t\treturn reflect.ValueOf(v).Pointer()\n\tcase *ssa.Function:\n\t\treturn uintptr(unsafe.Pointer(v))\n\tcase *closure:\n\t\treturn uintptr(unsafe.Pointer(v))\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).Pointer(%T)\", v))\n\t}\n}\n\nfunc ext۰reflect۰Value۰Index(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value, i int) Value\n\ti := args[1].(int)\n\tt := rV2T(args[0]).t.Underlying()\n\tswitch v := rV2V(args[0]).(type) {\n\tcase array:\n\t\treturn makeReflectValue(t.(*types.Array).Elem(), v[i])\n\tcase []value:\n\t\treturn makeReflectValue(t.(*types.Slice).Elem(), v[i])\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).Index(%T)\", v))\n\t}\n}\n\nfunc ext۰reflect۰Value۰Bool(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) bool\n\treturn rV2V(args[0]).(bool)\n}\n\nfunc ext۰reflect۰Value۰CanAddr(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value) bool\n\t// Always false for our representation.\n\treturn false\n}\n\nfunc ext۰reflect۰Value۰CanInterface(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value) bool\n\t// Always true for our representation.\n\treturn true\n}\n\nfunc ext۰reflect۰Value۰Elem(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value) reflect.Value\n\tswitch x := rV2V(args[0]).(type) {\n\tcase iface:\n\t\treturn makeReflectValue(x.t, x.v)\n\tcase *value:\n\t\tvar v value\n\t\tif x != nil {\n\t\t\tv = *x\n\t\t}\n\t\treturn makeReflectValue(rV2T(args[0]).t.Underlying().(*types.Pointer).Elem(), v)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).Elem(%T)\", x))\n\t}\n}\n\nfunc ext۰reflect۰Value۰Field(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value, i int) reflect.Value\n\tv := args[0]\n\ti := args[1].(int)\n\treturn makeReflectValue(rV2T(v).t.Underlying().(*types.Struct).Field(i).Type(), rV2V(v).(structure)[i])\n}\n\nfunc ext۰reflect۰Value۰Float(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) float64\n\tswitch v := rV2V(args[0]).(type) {\n\tcase float32:\n\t\treturn float64(v)\n\tcase float64:\n\t\treturn float64(v)\n\t}\n\tpanic(\"reflect.Value.Float\")\n}\n\nfunc ext۰reflect۰Value۰Interface(fr *frame, args []value) value {\n\t// Signature: func (v reflect.Value) interface{}\n\treturn ext۰reflect۰valueInterface(args)\n}\n\nfunc ext۰reflect۰Value۰Int(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) int64\n\tswitch x := rV2V(args[0]).(type) {\n\tcase int:\n\t\treturn int64(x)\n\tcase int8:\n\t\treturn int64(x)\n\tcase int16:\n\t\treturn int64(x)\n\tcase int32:\n\t\treturn int64(x)\n\tcase int64:\n\t\treturn x\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).Int(%T)\", x))\n\t}\n}\n\nfunc ext۰reflect۰Value۰IsNil(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) bool\n\tswitch x := rV2V(args[0]).(type) {\n\tcase *value:\n\t\treturn x == nil\n\tcase chan value:\n\t\treturn x == nil\n\tcase map[value]value:\n\t\treturn x == nil\n\tcase *hashmap:\n\t\treturn x == nil\n\tcase iface:\n\t\treturn x.t == nil\n\tcase []value:\n\t\treturn x == nil\n\tcase *ssa.Function:\n\t\treturn x == nil\n\tcase *ssa.Builtin:\n\t\treturn x == nil\n\tcase *closure:\n\t\treturn x == nil\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect.(Value).IsNil(%T)\", x))\n\t}\n}\n\nfunc ext۰reflect۰Value۰IsValid(fr *frame, args []value) value {\n\t// Signature: func (reflect.Value) bool\n\treturn rV2V(args[0]) != nil\n}\n\nfunc ext۰reflect۰Value۰Set(fr *frame, args []value) value {\n\t// TODO(adonovan): implement.\n\treturn nil\n}\n\nfunc ext۰reflect۰valueInterface(args []value) value {\n\t// Signature: func (v reflect.Value, safe bool) interface{}\n\tv := args[0].(structure)\n\treturn iface{rV2T(v).t, rV2V(v)}\n}\n\nfunc ext۰reflect۰error۰Error(fr *frame, args []value) value {\n\treturn args[0]\n}\n\n// newMethod creates a new method of the specified name, package and receiver type.\nfunc newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {\n\t// TODO(adonovan): fix: hack: currently the only part of Signature\n\t// that is needed is the \"pointerness\" of Recv.Type, and for\n\t// now, we'll set it to always be false since we're only\n\t// concerned with rtype.  Encapsulate this better.\n\tsig := types.NewSignatureType(types.NewParam(token.NoPos, nil, \"recv\", recvType), nil, nil, nil, nil, false)\n\tfn := pkg.Prog.NewFunction(name, sig, \"fake reflect method\")\n\tfn.Pkg = pkg\n\treturn fn\n}\n\nfunc initReflect(i *interpreter) {\n\ti.reflectPackage = &ssa.Package{\n\t\tProg:    i.prog,\n\t\tPkg:     reflectTypesPackage,\n\t\tMembers: make(map[string]ssa.Member),\n\t}\n\n\t// Clobber the type-checker's notion of reflect.Value's\n\t// underlying type so that it more closely matches the fake one\n\t// (at least in the number of fields---we lie about the type of\n\t// the rtype field).\n\t//\n\t// We must ensure that calls to (ssa.Value).Type() return the\n\t// fake type so that correct \"shape\" is used when allocating\n\t// variables, making zero values, loading, and storing.\n\t//\n\t// TODO(adonovan): obviously this is a hack.  We need a cleaner\n\t// way to fake the reflect package (almost---DeepEqual is fine).\n\t// One approach would be not to even load its source code, but\n\t// provide fake source files.  This would guarantee that no bad\n\t// information leaks into other packages.\n\tif r := i.prog.ImportedPackage(\"reflect\"); r != nil {\n\t\trV := r.Pkg.Scope().Lookup(\"Value\").Type().(*types.Named)\n\n\t\t// delete bodies of the old methods\n\t\tmset := i.prog.MethodSets.MethodSet(rV)\n\t\tfor method := range mset.Methods() {\n\t\t\ti.prog.MethodValue(method).Blocks = nil\n\t\t}\n\n\t\ttEface := types.NewInterface(nil, nil).Complete()\n\t\trV.SetUnderlying(types.NewStruct([]*types.Var{\n\t\t\ttypes.NewField(token.NoPos, r.Pkg, \"t\", tEface, false), // a lie\n\t\t\ttypes.NewField(token.NoPos, r.Pkg, \"v\", tEface, false),\n\t\t}, nil))\n\t}\n\n\ti.rtypeMethods = methodSet{\n\t\t\"Bits\":      newMethod(i.reflectPackage, rtypeType, \"Bits\"),\n\t\t\"Elem\":      newMethod(i.reflectPackage, rtypeType, \"Elem\"),\n\t\t\"Field\":     newMethod(i.reflectPackage, rtypeType, \"Field\"),\n\t\t\"In\":        newMethod(i.reflectPackage, rtypeType, \"In\"),\n\t\t\"Kind\":      newMethod(i.reflectPackage, rtypeType, \"Kind\"),\n\t\t\"NumField\":  newMethod(i.reflectPackage, rtypeType, \"NumField\"),\n\t\t\"NumIn\":     newMethod(i.reflectPackage, rtypeType, \"NumIn\"),\n\t\t\"NumMethod\": newMethod(i.reflectPackage, rtypeType, \"NumMethod\"),\n\t\t\"NumOut\":    newMethod(i.reflectPackage, rtypeType, \"NumOut\"),\n\t\t\"Out\":       newMethod(i.reflectPackage, rtypeType, \"Out\"),\n\t\t\"Size\":      newMethod(i.reflectPackage, rtypeType, \"Size\"),\n\t\t\"String\":    newMethod(i.reflectPackage, rtypeType, \"String\"),\n\t}\n\ti.errorMethods = methodSet{\n\t\t\"Error\": newMethod(i.reflectPackage, errorType, \"Error\"),\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/boundmeth.go",
    "content": "// Tests of bound method closures.\n\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc assert(b bool) {\n\tif !b {\n\t\tpanic(\"oops\")\n\t}\n}\n\ntype I int\n\nfunc (i I) add(x int) int {\n\treturn int(i) + x\n}\n\nfunc valueReceiver() {\n\tvar three I = 3\n\tassert(three.add(5) == 8)\n\tvar add3 func(int) int = three.add\n\tassert(add3(5) == 8)\n}\n\ntype S struct{ x int }\n\nfunc (s *S) incr() {\n\ts.x++\n}\n\nfunc (s *S) get() int {\n\treturn s.x\n}\n\nfunc pointerReceiver() {\n\tps := new(S)\n\tincr := ps.incr\n\tget := ps.get\n\tassert(get() == 0)\n\tincr()\n\tincr()\n\tincr()\n\tassert(get() == 3)\n}\n\nfunc addressibleValuePointerReceiver() {\n\tvar s S\n\tincr := s.incr\n\tget := s.get\n\tassert(get() == 0)\n\tincr()\n\tincr()\n\tincr()\n\tassert(get() == 3)\n}\n\ntype S2 struct {\n\tS\n}\n\nfunc promotedReceiver() {\n\tvar s2 S2\n\tincr := s2.incr\n\tget := s2.get\n\tassert(get() == 0)\n\tincr()\n\tincr()\n\tincr()\n\tassert(get() == 3)\n}\n\nfunc anonStruct() {\n\tvar s struct{ S }\n\tincr := s.incr\n\tget := s.get\n\tassert(get() == 0)\n\tincr()\n\tincr()\n\tincr()\n\tassert(get() == 3)\n}\n\nfunc typeCheck() {\n\tvar i interface{}\n\ti = (*S).incr\n\t_ = i.(func(*S)) // type assertion: receiver type prepended to params\n\n\tvar s S\n\ti = s.incr\n\t_ = i.(func()) // type assertion: receiver type disappears\n}\n\ntype errString string\n\nfunc (err errString) Error() string {\n\treturn string(err)\n}\n\n// Regression test for a builder crash.\nfunc regress1(x error) func() string {\n\treturn x.Error\n}\n\n// Regression test for b/7269:\n// taking the value of an interface method performs a nil check.\nfunc nilInterfaceMethodValue() {\n\terr := errors.New(\"ok\")\n\tf := err.Error\n\tif got := f(); got != \"ok\" {\n\t\tpanic(got)\n\t}\n\n\terr = nil\n\tif got := f(); got != \"ok\" {\n\t\tpanic(got)\n\t}\n\n\tdefer func() {\n\t\tr := fmt.Sprint(recover())\n\t\t// runtime panic string varies across toolchains\n\t\tif r != \"interface conversion: interface is nil, not error\" &&\n\t\t\tr != \"runtime error: invalid memory address or nil pointer dereference\" &&\n\t\t\tr != \"method value: interface is nil\" {\n\t\t\tpanic(\"want runtime panic from nil interface method value, got \" + r)\n\t\t}\n\t}()\n\tf = err.Error // runtime panic: err is nil\n\tpanic(\"unreachable\")\n}\n\nfunc main() {\n\tvalueReceiver()\n\tpointerReceiver()\n\taddressibleValuePointerReceiver()\n\tpromotedReceiver()\n\tanonStruct()\n\ttypeCheck()\n\n\tif e := regress1(errString(\"hi\"))(); e != \"hi\" {\n\t\tpanic(e)\n\t}\n\n\tnilInterfaceMethodValue()\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/complit.go",
    "content": "package main\n\n// Tests of composite literals.\n\nimport \"fmt\"\n\n// Map literals.\n// TODO(adonovan): we can no longer print maps\n// until the interpreter supports (reflect.Value).MapRange.\nfunc _() {\n\ttype M map[int]int\n\tm1 := []*M{{1: 1}, &M{2: 2}}\n\twant := \"map[1:1] map[2:2]\"\n\tif got := fmt.Sprint(*m1[0], *m1[1]); got != want {\n\t\tpanic(got)\n\t}\n\tm2 := []M{{1: 1}, M{2: 2}}\n\tif got := fmt.Sprint(m2[0], m2[1]); got != want {\n\t\tpanic(got)\n\t}\n}\n\n// Nonliteral keys in composite literal.\nfunc init() {\n\tconst zero int = 1\n\tvar v = []int{1 + zero: 42}\n\tif x := fmt.Sprint(v); x != \"[0 0 42]\" {\n\t\tpanic(x)\n\t}\n}\n\n// Test for in-place initialization.\nfunc init() {\n\t// struct\n\ttype S struct {\n\t\ta, b int\n\t}\n\ts := S{1, 2}\n\ts = S{b: 3}\n\tif s.a != 0 {\n\t\tpanic(\"s.a != 0\")\n\t}\n\tif s.b != 3 {\n\t\tpanic(\"s.b != 3\")\n\t}\n\ts = S{}\n\tif s.a != 0 {\n\t\tpanic(\"s.a != 0\")\n\t}\n\tif s.b != 0 {\n\t\tpanic(\"s.b != 0\")\n\t}\n\n\t// array\n\ttype A [4]int\n\ta := A{2, 4, 6, 8}\n\ta = A{1: 6, 2: 4}\n\tif a[0] != 0 {\n\t\tpanic(\"a[0] != 0\")\n\t}\n\tif a[1] != 6 {\n\t\tpanic(\"a[1] != 6\")\n\t}\n\tif a[2] != 4 {\n\t\tpanic(\"a[2] != 4\")\n\t}\n\tif a[3] != 0 {\n\t\tpanic(\"a[3] != 0\")\n\t}\n\ta = A{}\n\tif a[0] != 0 {\n\t\tpanic(\"a[0] != 0\")\n\t}\n\tif a[1] != 0 {\n\t\tpanic(\"a[1] != 0\")\n\t}\n\tif a[2] != 0 {\n\t\tpanic(\"a[2] != 0\")\n\t}\n\tif a[3] != 0 {\n\t\tpanic(\"a[3] != 0\")\n\t}\n}\n\n// Regression test for https://golang.org/issue/10127:\n// composite literal clobbers destination before reading from it.\nfunc init() {\n\t// map\n\t{\n\t\ttype M map[string]int\n\t\tm := M{\"x\": 1, \"y\": 2}\n\t\tm = M{\"x\": m[\"y\"], \"y\": m[\"x\"]}\n\t\tif m[\"x\"] != 2 || m[\"y\"] != 1 {\n\t\t\tpanic(fmt.Sprint(m))\n\t\t}\n\n\t\tn := M{\"x\": 3}\n\t\tm, n = M{\"x\": n[\"x\"]}, M{\"x\": m[\"x\"]} // parallel assignment\n\t\tif got := fmt.Sprint(m[\"x\"], n[\"x\"]); got != \"3 2\" {\n\t\t\tpanic(got)\n\t\t}\n\t}\n\n\t// struct\n\t{\n\t\ttype T struct{ x, y, z int }\n\t\tt := T{x: 1, y: 2, z: 3}\n\n\t\tt = T{x: t.y, y: t.z, z: t.x} // all fields\n\t\tif got := fmt.Sprint(t); got != \"{2 3 1}\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\tt = T{x: t.y, y: t.z + 3} // not all fields\n\t\tif got := fmt.Sprint(t); got != \"{3 4 0}\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\tu := T{x: 5, y: 6, z: 7}\n\t\tt, u = T{x: u.x}, T{x: t.x} // parallel assignment\n\t\tif got := fmt.Sprint(t, u); got != \"{5 0 0} {3 0 0}\" {\n\t\t\tpanic(got)\n\t\t}\n\t}\n\n\t// array\n\t{\n\t\ta := [3]int{0: 1, 1: 2, 2: 3}\n\n\t\ta = [3]int{0: a[1], 1: a[2], 2: a[0]} //  all elements\n\t\tif got := fmt.Sprint(a); got != \"[2 3 1]\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\ta = [3]int{0: a[1], 1: a[2] + 3} //  not all elements\n\t\tif got := fmt.Sprint(a); got != \"[3 4 0]\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\tb := [3]int{0: 5, 1: 6, 2: 7}\n\t\ta, b = [3]int{0: b[0]}, [3]int{0: a[0]} // parallel assignment\n\t\tif got := fmt.Sprint(a, b); got != \"[5 0 0] [3 0 0]\" {\n\t\t\tpanic(got)\n\t\t}\n\t}\n\n\t// slice\n\t{\n\t\ts := []int{0: 1, 1: 2, 2: 3}\n\n\t\ts = []int{0: s[1], 1: s[2], 2: s[0]} //  all elements\n\t\tif got := fmt.Sprint(s); got != \"[2 3 1]\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\ts = []int{0: s[1], 1: s[2] + 3} //  not all elements\n\t\tif got := fmt.Sprint(s); got != \"[3 4]\" {\n\t\t\tpanic(got)\n\t\t}\n\n\t\tt := []int{0: 5, 1: 6, 2: 7}\n\t\ts, t = []int{0: t[0]}, []int{0: s[0]} // parallel assignment\n\t\tif got := fmt.Sprint(s, t); got != \"[5] [3]\" {\n\t\t\tpanic(got)\n\t\t}\n\t}\n}\n\n// Regression test for https://golang.org/issue/13341:\n// within a map literal, if a key expression is a composite literal,\n// Go 1.5 allows its type to be omitted.  An & operation may be implied.\nfunc init() {\n\ttype S struct{ x int }\n\t// same as map[*S]bool{&S{x: 1}: true}\n\tm := map[*S]bool{{x: 1}: true}\n\tfor s := range m {\n\t\tif s.x != 1 {\n\t\t\tpanic(s) // wrong key\n\t\t}\n\t\treturn\n\t}\n\tpanic(\"map is empty\")\n}\n\nfunc main() {\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/convert.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test conversion operations.\n\npackage main\n\nfunc left(x int)  { _ = 1 << x }\nfunc right(x int) { _ = 1 >> x }\n\nfunc main() {\n\twantPanic(\n\t\tfunc() {\n\t\t\tleft(-1)\n\t\t},\n\t\t\"runtime error: negative shift amount\",\n\t)\n\twantPanic(\n\t\tfunc() {\n\t\t\tright(-1)\n\t\t},\n\t\t\"runtime error: negative shift amount\",\n\t)\n\twantPanic(\n\t\tfunc() {\n\t\t\tconst maxInt32 = 1<<31 - 1\n\t\t\tvar idx int64 = maxInt32*2 + 8\n\t\t\tx := make([]int, 16)\n\t\t\t_ = x[idx]\n\t\t},\n\t\t\"runtime error: runtime error: index out of range [4294967302] with length 16\",\n\t)\n}\n\nfunc wantPanic(fn func(), s string) {\n\tdefer func() {\n\t\terr := recover()\n\t\tif err == nil {\n\t\t\tpanic(\"expected panic\")\n\t\t}\n\t\tif got := err.(error).Error(); got != s {\n\t\t\tpanic(\"expected panic \" + s + \" got \" + got)\n\t\t}\n\t}()\n\tfn()\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/coverage.go",
    "content": "// This interpreter test is designed to run very quickly yet provide\n// some coverage of a broad selection of constructs.\n//\n// Validate this file with 'go run' after editing.\n// TODO(adonovan): break this into small files organized by theme.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n)\n\nfunc init() {\n\t// Call of variadic function with (implicit) empty slice.\n\tif x := fmt.Sprint(); x != \"\" {\n\t\tpanic(x)\n\t}\n}\n\ntype empty interface{}\n\ntype I interface {\n\tf() int\n}\n\ntype T struct{ z int }\n\nfunc (t T) f() int { return t.z }\n\nfunc use(interface{}) {}\n\nvar counter = 2\n\n// Test initialization, including init blocks containing 'return'.\n// Assertion is in main.\nfunc init() {\n\tcounter *= 3\n\treturn\n\tcounter *= 3\n}\n\nfunc init() {\n\tcounter *= 5\n\treturn\n\tcounter *= 5\n}\n\n// Recursion.\nfunc fib(x int) int {\n\tif x < 2 {\n\t\treturn x\n\t}\n\treturn fib(x-1) + fib(x-2)\n}\n\nfunc fibgen(ch chan int) {\n\tfor x := 0; x < 10; x++ {\n\t\tch <- fib(x)\n\t}\n\tclose(ch)\n}\n\n// Goroutines and channels.\nfunc init() {\n\tch := make(chan int)\n\tgo fibgen(ch)\n\tvar fibs []int\n\tfor v := range ch {\n\t\tfibs = append(fibs, v)\n\t\tif len(fibs) == 10 {\n\t\t\tbreak\n\t\t}\n\t}\n\tif x := fmt.Sprint(fibs); x != \"[0 1 1 2 3 5 8 13 21 34]\" {\n\t\tpanic(x)\n\t}\n}\n\n// Test of aliasing.\nfunc init() {\n\ttype S struct {\n\t\ta, b string\n\t}\n\n\ts1 := []string{\"foo\", \"bar\"}\n\ts2 := s1 // creates an alias\n\ts2[0] = \"wiz\"\n\tif x := fmt.Sprint(s1, s2); x != \"[wiz bar] [wiz bar]\" {\n\t\tpanic(x)\n\t}\n\n\tpa1 := &[2]string{\"foo\", \"bar\"}\n\tpa2 := pa1 // creates an alias\n\tpa2[0] = \"wiz\"\n\tif x := fmt.Sprint(*pa1, *pa2); x != \"[wiz bar] [wiz bar]\" {\n\t\tpanic(x)\n\t}\n\n\ta1 := [2]string{\"foo\", \"bar\"}\n\ta2 := a1 // creates a copy\n\ta2[0] = \"wiz\"\n\tif x := fmt.Sprint(a1, a2); x != \"[foo bar] [wiz bar]\" {\n\t\tpanic(x)\n\t}\n\n\tt1 := S{\"foo\", \"bar\"}\n\tt2 := t1 // copy\n\tt2.a = \"wiz\"\n\tif x := fmt.Sprint(t1, t2); x != \"{foo bar} {wiz bar}\" {\n\t\tpanic(x)\n\t}\n}\n\nfunc main() {\n\tprint() // legal\n\n\tif counter != 2*3*5 {\n\t\tpanic(counter)\n\t}\n\n\t// Test builtins (e.g. complex) preserve named argument types.\n\ttype N complex128\n\tvar n N\n\tn = complex(1.0, 2.0)\n\tif n != complex(1.0, 2.0) {\n\t\tpanic(n)\n\t}\n\tif x := reflect.TypeOf(n).String(); x != \"main.N\" {\n\t\tpanic(x)\n\t}\n\tif real(n) != 1.0 || imag(n) != 2.0 {\n\t\tpanic(n)\n\t}\n\n\t// Channel + select.\n\tch := make(chan int, 1)\n\tselect {\n\tcase ch <- 1:\n\t\t// ok\n\tdefault:\n\t\tpanic(\"couldn't send\")\n\t}\n\tif <-ch != 1 {\n\t\tpanic(\"couldn't receive\")\n\t}\n\t// A \"receive\" select-case that doesn't declare its vars.  (regression test)\n\tanint := 0\n\tok := false\n\tselect {\n\tcase anint, ok = <-ch:\n\tcase anint = <-ch:\n\tdefault:\n\t}\n\t_ = anint\n\t_ = ok\n\n\t// Anon structs with methods.\n\tanon := struct{ T }{T: T{z: 1}}\n\tif x := anon.f(); x != 1 {\n\t\tpanic(x)\n\t}\n\tvar i I = anon\n\tif x := i.f(); x != 1 {\n\t\tpanic(x)\n\t}\n\t// NB. precise output of reflect.Type.String is undefined.\n\tif x := reflect.TypeOf(i).String(); x != \"struct { main.T }\" && x != \"struct{main.T}\" {\n\t\tpanic(x)\n\t}\n\n\t// fmt.\n\tconst message = \"Hello, World!\"\n\tif fmt.Sprint(\"Hello\", \", \", \"World\", \"!\") != message {\n\t\tpanic(\"oops\")\n\t}\n\n\t// Type assertion.\n\ttype S struct {\n\t\tf int\n\t}\n\tvar e empty = S{f: 42}\n\tswitch v := e.(type) {\n\tcase S:\n\t\tif v.f != 42 {\n\t\t\tpanic(v.f)\n\t\t}\n\tdefault:\n\t\tpanic(reflect.TypeOf(v))\n\t}\n\tif i, ok := e.(I); ok {\n\t\tpanic(i)\n\t}\n\n\t// Switch.\n\tvar x int\n\tswitch x {\n\tcase 1:\n\t\tpanic(x)\n\t\tfallthrough\n\tcase 2, 3:\n\t\tpanic(x)\n\tdefault:\n\t\t// ok\n\t}\n\t// empty switch\n\tswitch {\n\t}\n\t// empty switch\n\tswitch {\n\tdefault:\n\t}\n\t// empty switch\n\tswitch {\n\tdefault:\n\t\tfallthrough\n\tcase false:\n\t}\n\n\t// string -> []rune conversion.\n\tuse([]rune(\"foo\"))\n\n\t// Calls of form x.f().\n\ttype S2 struct {\n\t\tf func() int\n\t}\n\tS2{f: func() int { return 1 }}.f() // field is a func value\n\tT{}.f()                            // method call\n\ti.f()                              // interface method invocation\n\t(interface {\n\t\tf() int\n\t}(T{})).f() // anon interface method invocation\n\n\t// Map lookup.\n\tif v, ok := map[string]string{}[\"foo5\"]; v != \"\" || ok {\n\t\tpanic(\"oops\")\n\t}\n\n\t// Regression test: implicit address-taken struct literal\n\t// inside literal map element.\n\t_ = map[int]*struct{}{0: {}}\n}\n\ntype mybool bool\n\nfunc (mybool) f() {}\n\nfunc init() {\n\ttype mybool bool\n\tvar b mybool\n\tvar i interface{} = b || b // result preserves types of operands\n\t_ = i.(mybool)\n\n\ti = false && b // result preserves type of \"typed\" operand\n\t_ = i.(mybool)\n\n\ti = b || true // result preserves type of \"typed\" operand\n\t_ = i.(mybool)\n}\n\nfunc init() {\n\tvar x, y int\n\tvar b mybool = x == y // x==y is an untyped bool\n\tb.f()\n}\n\n// Simple closures.\nfunc init() {\n\tb := 3\n\tf := func(a int) int {\n\t\treturn a + b\n\t}\n\tb++\n\tif x := f(1); x != 5 { // 1+4 == 5\n\t\tpanic(x)\n\t}\n\tb++\n\tif x := f(2); x != 7 { // 2+5 == 7\n\t\tpanic(x)\n\t}\n\tif b := f(1) < 16 || f(2) < 17; !b {\n\t\tpanic(\"oops\")\n\t}\n}\n\n// Shifts.\nfunc init() {\n\tvar i int64 = 1\n\tvar u uint64 = 1 << 32\n\tif x := i << uint32(u); x != 1 {\n\t\tpanic(x)\n\t}\n\tif x := i << uint64(u); x != 0 {\n\t\tpanic(x)\n\t}\n}\n\n// Implicit conversion of delete() key operand.\nfunc init() {\n\ttype I interface{}\n\tm := make(map[I]bool)\n\tm[1] = true\n\tm[I(2)] = true\n\tif len(m) != 2 {\n\t\tpanic(m)\n\t}\n\tdelete(m, I(1))\n\tdelete(m, 2)\n\tif len(m) != 0 {\n\t\tpanic(m)\n\t}\n}\n\n// An I->I conversion always succeeds.\nfunc init() {\n\tvar x I\n\tif I(x) != I(nil) {\n\t\tpanic(\"I->I conversion failed\")\n\t}\n}\n\n// An I->I type-assert fails iff the value is nil.\nfunc init() {\n\tdefer func() {\n\t\tr := fmt.Sprint(recover())\n\t\t// Exact error varies by toolchain.\n\t\tif r != \"runtime error: interface conversion: interface is nil, not main.I\" &&\n\t\t\tr != \"interface conversion: interface is nil, not main.I\" {\n\t\t\tpanic(\"I->I type assertion succeeded for nil value\")\n\t\t}\n\t}()\n\tvar x I\n\t_ = x.(I)\n}\n\n//////////////////////////////////////////////////////////////////////\n// Variadic bridge methods and interface thunks.\n\ntype VT int\n\nvar vcount = 0\n\nfunc (VT) f(x int, y ...string) {\n\tvcount++\n\tif x != 1 {\n\t\tpanic(x)\n\t}\n\tif len(y) != 2 || y[0] != \"foo\" || y[1] != \"bar\" {\n\t\tpanic(y)\n\t}\n}\n\ntype VS struct {\n\tVT\n}\n\ntype VI interface {\n\tf(x int, y ...string)\n}\n\nfunc init() {\n\tfoobar := []string{\"foo\", \"bar\"}\n\tvar s VS\n\ts.f(1, \"foo\", \"bar\")\n\ts.f(1, foobar...)\n\tif vcount != 2 {\n\t\tpanic(\"s.f not called twice\")\n\t}\n\n\tfn := VI.f\n\tfn(s, 1, \"foo\", \"bar\")\n\tfn(s, 1, foobar...)\n\tif vcount != 4 {\n\t\tpanic(\"I.f not called twice\")\n\t}\n}\n\n// Multiple labels on same statement.\nfunc multipleLabels() {\n\tvar trace []int\n\ti := 0\none:\ntwo:\n\tfor ; i < 3; i++ {\n\t\ttrace = append(trace, i)\n\t\tswitch i {\n\t\tcase 0:\n\t\t\tcontinue two\n\t\tcase 1:\n\t\t\ti++\n\t\t\tgoto one\n\t\tcase 2:\n\t\t\tbreak two\n\t\t}\n\t}\n\tif x := fmt.Sprint(trace); x != \"[0 1 2]\" {\n\t\tpanic(x)\n\t}\n}\n\nfunc init() {\n\tmultipleLabels()\n}\n\nfunc init() {\n\t// Struct equivalence ignores blank fields.\n\ttype s struct{ x, _, z int }\n\ts1 := s{x: 1, z: 3}\n\ts2 := s{x: 1, z: 3}\n\tif s1 != s2 {\n\t\tpanic(\"not equal\")\n\t}\n}\n\nfunc init() {\n\t// A slice var can be compared to const []T nil.\n\tvar i interface{} = []string{\"foo\"}\n\tvar j interface{} = []string(nil)\n\tif i.([]string) == nil {\n\t\tpanic(\"expected i non-nil\")\n\t}\n\tif j.([]string) != nil {\n\t\tpanic(\"expected j nil\")\n\t}\n\t// But two slices cannot be compared, even if one is nil.\n\tdefer func() {\n\t\tr := fmt.Sprint(recover())\n\t\tif !(strings.Contains(r, \"compar\") && strings.Contains(r, \"[]string\")) {\n\t\t\tpanic(\"want panic from slice comparison, got \" + r)\n\t\t}\n\t}()\n\t_ = i == j // interface comparison recurses on types\n}\n\nfunc init() {\n\t// Regression test for SSA renaming bug.\n\tvar ints []int\n\tfor range \"foo\" {\n\t\tvar x int\n\t\tx++\n\t\tints = append(ints, x)\n\t}\n\tif fmt.Sprint(ints) != \"[1 1 1]\" {\n\t\tpanic(ints)\n\t}\n}\n\n// Regression test for issue 6949:\n// []byte(\"foo\") is not a constant since it allocates memory.\nfunc init() {\n\tvar r string\n\tfor i, b := range \"ABC\" {\n\t\tx := []byte(\"abc\")\n\t\tx[i] = byte(b)\n\t\tr += string(x)\n\t}\n\tif r != \"AbcaBcabC\" {\n\t\tpanic(r)\n\t}\n}\n\n// Test of 3-operand x[lo:hi:max] slice.\nfunc init() {\n\ts := []int{0, 1, 2, 3}\n\tlenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }\n\tif got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {\n\t\tpanic(got)\n\t}\n\tif got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {\n\t\tpanic(got)\n\t}\n\tmax := 3\n\tif \"a\"[0] == 'a' {\n\t\tmax = 2 // max is non-constant, even in SSA form\n\t}\n\tif got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {\n\t\tpanic(got)\n\t}\n}\n\nvar one = 1 // not a constant\n\n// Test makeslice.\nfunc init() {\n\tcheck := func(s []string, wantLen, wantCap int) {\n\t\tif len(s) != wantLen {\n\t\t\tpanic(len(s))\n\t\t}\n\t\tif cap(s) != wantCap {\n\t\t\tpanic(cap(s))\n\t\t}\n\t}\n\t//                                       SSA form:\n\tcheck(make([]string, 10), 10, 10)     // new([10]string)[:10]\n\tcheck(make([]string, one), 1, 1)      // make([]string, one, one)\n\tcheck(make([]string, 0, 10), 0, 10)   // new([10]string)[:0]\n\tcheck(make([]string, 0, one), 0, 1)   // make([]string, 0, one)\n\tcheck(make([]string, one, 10), 1, 10) // new([10]string)[:one]\n\tcheck(make([]string, one, one), 1, 1) // make([]string, one, one)\n}\n\n// Test that a nice error is issued by indirection wrappers.\nfunc init() {\n\tvar ptr *T\n\tvar i I = ptr\n\n\tdefer func() {\n\t\tr := fmt.Sprint(recover())\n\t\t// Exact error varies by toolchain:\n\t\tif r != \"runtime error: value method (main.T).f called using nil *main.T pointer\" &&\n\t\t\tr != \"value method (main.T).f called using nil *main.T pointer\" {\n\t\t\tpanic(\"want panic from call with nil receiver, got \" + r)\n\t\t}\n\t}()\n\ti.f()\n\tpanic(\"unreachable\")\n}\n\n// Regression test for a subtle bug in which copying values would causes\n// subcomponents of aggregate variables to change address, breaking\n// aliases.\nfunc init() {\n\ttype T struct{ f int }\n\tvar x T\n\tp := &x.f\n\tx = T{}\n\t*p = 1\n\tif x.f != 1 {\n\t\tpanic(\"lost store\")\n\t}\n\tif p != &x.f {\n\t\tpanic(\"unstable address\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/deepequal.go",
    "content": "// This interpreter test is designed to test the test copy of DeepEqual.\n//\n// Validate this file with 'go run' after editing.\n\npackage main\n\nimport \"reflect\"\n\nfunc assert(cond bool) {\n\tif !cond {\n\t\tpanic(\"failed\")\n\t}\n}\n\ntype X int\ntype Y struct {\n\ty *Y\n\tz [3]int\n}\n\nvar (\n\ta = []int{0, 1, 2, 3}\n\tb = []X{0, 1, 2, 3}\n\tc = map[int]string{0: \"zero\", 1: \"one\"}\n\td = map[X]string{0: \"zero\", 1: \"one\"}\n\te = &Y{}\n\tf = (*Y)(nil)\n\tg = &Y{y: e}\n\th *Y\n)\n\nfunc init() {\n\th = &Y{} // h->h\n\th.y = h\n}\n\nfunc main() {\n\tassert(reflect.DeepEqual(nil, nil))\n\tassert(reflect.DeepEqual((*int)(nil), (*int)(nil)))\n\tassert(!reflect.DeepEqual(nil, (*int)(nil)))\n\n\tassert(reflect.DeepEqual(0, 0))\n\tassert(!reflect.DeepEqual(0, int64(0)))\n\n\tassert(!reflect.DeepEqual(\"\", 0))\n\n\tassert(reflect.DeepEqual(a, []int{0, 1, 2, 3}))\n\tassert(!reflect.DeepEqual(a, []int{0, 1, 2}))\n\tassert(!reflect.DeepEqual(a, []int{0, 1, 0, 3}))\n\n\tassert(reflect.DeepEqual(b, []X{0, 1, 2, 3}))\n\tassert(!reflect.DeepEqual(b, []X{0, 1, 0, 3}))\n\n\tassert(reflect.DeepEqual(c, map[int]string{0: \"zero\", 1: \"one\"}))\n\tassert(!reflect.DeepEqual(c, map[int]string{0: \"zero\", 1: \"one\", 2: \"two\"}))\n\tassert(!reflect.DeepEqual(c, map[int]string{1: \"one\", 2: \"two\"}))\n\tassert(!reflect.DeepEqual(c, map[int]string{1: \"one\"}))\n\n\tassert(reflect.DeepEqual(d, map[X]string{0: \"zero\", 1: \"one\"}))\n\tassert(!reflect.DeepEqual(d, map[int]string{0: \"zero\", 1: \"one\"}))\n\n\tassert(reflect.DeepEqual(e, &Y{}))\n\tassert(reflect.DeepEqual(e, &Y{z: [3]int{0, 0, 0}}))\n\tassert(!reflect.DeepEqual(e, &Y{z: [3]int{0, 1, 0}}))\n\n\tassert(reflect.DeepEqual(f, (*Y)(nil)))\n\tassert(!reflect.DeepEqual(f, nil))\n\n\t// eq_h -> eq_h. Pointer structure and elements are equal so DeepEqual.\n\teq_h := &Y{}\n\teq_h.y = eq_h\n\tassert(reflect.DeepEqual(h, eq_h))\n\n\t// deepeq_h->h->h. Pointed to elem of (deepeq_h, h) are (h,h). (h,h) are deep equal so h and deepeq_h are DeepEqual.\n\tdeepeq_h := &Y{}\n\tdeepeq_h.y = h\n\tassert(reflect.DeepEqual(h, deepeq_h))\n\n\tdistinct := []interface{}{a, b, c, d, e, f, g, h}\n\tfor x := range distinct {\n\t\tfor y := range distinct {\n\t\t\tassert((x == y) == reflect.DeepEqual(distinct[x], distinct[y]))\n\t\t}\n\t}\n\n\t// anonymous struct types.\n\tassert(reflect.DeepEqual(struct{}{}, struct{}{}))\n\tassert(reflect.DeepEqual(struct{ x int }{1}, struct{ x int }{1}))\n\tassert(!reflect.DeepEqual(struct{ x int }{}, struct{ x int }{5}))\n\tassert(!reflect.DeepEqual(struct{ x, y int }{0, 1}, struct{ x int }{0}))\n\tassert(reflect.DeepEqual(struct{ x, y int }{2, 3}, struct{ x, y int }{2, 3}))\n\tassert(!reflect.DeepEqual(struct{ x, y int }{4, 5}, struct{ x, y int }{4, 6}))\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/defer.go",
    "content": "package main\n\n// Tests of defer.  (Deferred recover() belongs is recover.go.)\n\nimport \"fmt\"\n\nfunc deferMutatesResults(noArgReturn bool) (a, b int) {\n\tdefer func() {\n\t\tif a != 1 || b != 2 {\n\t\t\tpanic(fmt.Sprint(a, b))\n\t\t}\n\t\ta, b = 3, 4\n\t}()\n\tif noArgReturn {\n\t\ta, b = 1, 2\n\t\treturn\n\t}\n\treturn 1, 2\n}\n\nfunc init() {\n\ta, b := deferMutatesResults(true)\n\tif a != 3 || b != 4 {\n\t\tpanic(fmt.Sprint(a, b))\n\t}\n\ta, b = deferMutatesResults(false)\n\tif a != 3 || b != 4 {\n\t\tpanic(fmt.Sprint(a, b))\n\t}\n}\n\n// We concatenate init blocks to make a single function, but we must\n// run defers at the end of each block, not the combined function.\nvar deferCount = 0\n\nfunc init() {\n\tdeferCount = 1\n\tdefer func() {\n\t\tdeferCount++\n\t}()\n\t// defer runs HERE\n}\n\nfunc init() {\n\t// Strictly speaking the spec says deferCount may be 0 or 2\n\t// since the relative order of init blocks is unspecified.\n\tif deferCount != 2 {\n\t\tpanic(deferCount) // defer call has not run!\n\t}\n}\n\nfunc main() {\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fieldprom.go",
    "content": "package main\n\n// Tests of field promotion logic.\n\ntype A struct {\n\tx int\n\ty *int\n}\n\ntype B struct {\n\tp int\n\tq *int\n}\n\ntype C struct {\n\tA\n\t*B\n}\n\ntype D struct {\n\ta int\n\tC\n}\n\nfunc assert(cond bool) {\n\tif !cond {\n\t\tpanic(\"failed\")\n\t}\n}\n\nfunc f1(c C) {\n\tassert(c.x == c.A.x)\n\tassert(c.y == c.A.y)\n\tassert(&c.x == &c.A.x)\n\tassert(&c.y == &c.A.y)\n\n\tassert(c.p == c.B.p)\n\tassert(c.q == c.B.q)\n\tassert(&c.p == &c.B.p)\n\tassert(&c.q == &c.B.q)\n\n\tc.x = 1\n\t*c.y = 1\n\tc.p = 1\n\t*c.q = 1\n}\n\nfunc f2(c *C) {\n\tassert(c.x == c.A.x)\n\tassert(c.y == c.A.y)\n\tassert(&c.x == &c.A.x)\n\tassert(&c.y == &c.A.y)\n\n\tassert(c.p == c.B.p)\n\tassert(c.q == c.B.q)\n\tassert(&c.p == &c.B.p)\n\tassert(&c.q == &c.B.q)\n\n\tc.x = 1\n\t*c.y = 1\n\tc.p = 1\n\t*c.q = 1\n}\n\nfunc f3(d D) {\n\tassert(d.x == d.C.A.x)\n\tassert(d.y == d.C.A.y)\n\tassert(&d.x == &d.C.A.x)\n\tassert(&d.y == &d.C.A.y)\n\n\tassert(d.p == d.C.B.p)\n\tassert(d.q == d.C.B.q)\n\tassert(&d.p == &d.C.B.p)\n\tassert(&d.q == &d.C.B.q)\n\n\td.x = 1\n\t*d.y = 1\n\td.p = 1\n\t*d.q = 1\n}\n\nfunc f4(d *D) {\n\tassert(d.x == d.C.A.x)\n\tassert(d.y == d.C.A.y)\n\tassert(&d.x == &d.C.A.x)\n\tassert(&d.y == &d.C.A.y)\n\n\tassert(d.p == d.C.B.p)\n\tassert(d.q == d.C.B.q)\n\tassert(&d.p == &d.C.B.p)\n\tassert(&d.q == &d.C.B.q)\n\n\td.x = 1\n\t*d.y = 1\n\td.p = 1\n\t*d.q = 1\n}\n\nfunc main() {\n\ty := 123\n\tc := C{\n\t\tA{x: 42, y: &y},\n\t\t&B{p: 42, q: &y},\n\t}\n\n\tassert(&c.x == &c.A.x)\n\n\tf1(c)\n\tf2(&c)\n\n\td := D{C: c}\n\tf3(d)\n\tf4(&d)\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue52342.go",
    "content": "package main\n\nfunc main() {\n\tvar d byte\n\n\td = 1\n\td <<= 256\n\tif d != 0 {\n\t\tpanic(d)\n\t}\n\n\td = 1\n\td >>= 256\n\tif d != 0 {\n\t\tpanic(d)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue52835.go",
    "content": "package main\n\nvar called bool\n\ntype I interface {\n\tFoo()\n}\n\ntype A struct{}\n\nfunc (a A) Foo() {\n\tcalled = true\n}\n\nfunc lambda[X I]() func() func() {\n\treturn func() func() {\n\t\tvar x X\n\t\treturn x.Foo\n\t}\n}\n\nfunc main() {\n\tlambda[A]()()()\n\tif !called {\n\t\tpanic(called)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue55086.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nfunc a() (r string) {\n\ts := \"initial\"\n\tvar p *struct{ i int }\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\n\ts, p.i = \"set\", 2 // s must be set before p.i panics\n\treturn \"unreachable\"\n}\n\nfunc b() (r string) {\n\ts := \"initial\"\n\tfn := func() []int { panic(\"\") }\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\n\ts, fn()[0] = \"set\", 2 // fn() panics before any assignment occurs\n\treturn \"unreachable\"\n}\n\nfunc c() (r string) {\n\ts := \"initial\"\n\tvar p map[int]int\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\n\ts, p[0] = \"set\", 2 //s must be set before p[0] index panics\"\n\treturn \"unreachable\"\n}\n\nfunc d() (r string) {\n\ts := \"initial\"\n\tvar p map[int]int\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\tfn := func() int { panic(\"\") }\n\n\ts, p[0] = \"set\", fn() // fn() panics before s is set\n\treturn \"unreachable\"\n}\n\nfunc e() (r string) {\n\ts := \"initial\"\n\tp := map[int]int{}\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\tfn := func() int { panic(\"\") }\n\n\ts, p[fn()] = \"set\", 0 // fn() panics before any assignment occurs\n\treturn \"unreachable\"\n}\n\nfunc f() (r string) {\n\ts := \"initial\"\n\tp := []int{}\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\n\ts, p[1] = \"set\", 0 // p[1] panics after s is set\n\treturn \"unreachable\"\n}\n\nfunc g() (r string) {\n\ts := \"initial\"\n\tp := map[any]any{}\n\tdefer func() {\n\t\trecover()\n\t\tr = s\n\t}()\n\tvar i any = func() {}\n\ts, p[i] = \"set\", 0 // p[i] panics after s is set\n\treturn \"unreachable\"\n}\n\nfunc h() (r string) {\n\tfail := false\n\tdefer func() {\n\t\trecover()\n\t\tif fail {\n\t\t\tr = \"fail\"\n\t\t} else {\n\t\t\tr = \"success\"\n\t\t}\n\t}()\n\n\ttype T struct{ f int }\n\tvar p *struct{ *T }\n\n\t// The implicit \"p.T\" operand should be evaluated in phase 1 (and panic),\n\t// before the \"fail = true\" assignment in phase 2.\n\tfail, p.f = true, 0\n\treturn \"unreachable\"\n}\n\nfunc main() {\n\tfor _, test := range []struct {\n\t\tfn   func() string\n\t\twant string\n\t\tdesc string\n\t}{\n\t\t{a, \"set\", \"s must be set before p.i panics\"},\n\t\t{b, \"initial\", \"p() panics before s is set\"},\n\t\t{c, \"set\", \"s must be set before p[0] index panics\"},\n\t\t{d, \"initial\", \"fn() panics before s is set\"},\n\t\t{e, \"initial\", \"fn() panics before s is set\"},\n\t\t{f, \"set\", \"p[1] panics after s is set\"},\n\t\t{g, \"set\", \"p[i] panics after s is set\"},\n\t\t{h, \"success\", \"p.T panics before fail is set\"},\n\t} {\n\t\tif test.fn() != test.want {\n\t\t\tpanic(test.desc)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue55115.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport \"reflect\"\n\nfunc main() {\n\ttype MyByte byte\n\ttype MyRune rune\n\ttype MyString string\n\n\ta := []MyByte{'a', 'b', 'c'}\n\tif s := string(a); s != \"abc\" {\n\t\tpanic(s)\n\t}\n\n\tb := []MyRune{'五', '五'}\n\tif s := string(b); s != \"五五\" {\n\t\tpanic(s)\n\t}\n\n\tc := []MyByte{'l', 'o', 'r', 'e', 'm'}\n\tif s := MyString(c); s != MyString(\"lorem\") {\n\t\tpanic(s)\n\t}\n\n\td := \"lorem\"\n\tif a := []MyByte(d); !reflect.DeepEqual(a, []MyByte{'l', 'o', 'r', 'e', 'm'}) {\n\t\tpanic(a)\n\t}\n\n\te := 42\n\tif s := MyString(e); s != \"*\" {\n\t\tpanic(s)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue66783.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc Fn[N any]() (any, any, any) {\n\t// Very recursive type to exercise substitution.\n\ttype t[x any, ignored *N] struct {\n\t\tf  x\n\t\tg  N\n\t\tnx *t[x, *N]\n\t\tnn *t[N, *N]\n\t}\n\tn := t[N, *N]{}\n\ts := t[string, *N]{}\n\ti := t[int, *N]{}\n\treturn n, s, i\n}\n\nfunc main() {\n\n\tsn, ss, si := Fn[string]()\n\tin, is, ii := Fn[int]()\n\n\tfor i, t := range []struct {\n\t\tx, y any\n\t\twant bool\n\t}{\n\t\t{sn, ss, true},  // main.t[string;string,*string] == main.t[string;string,*string]\n\t\t{sn, si, false}, // main.t[string;string,*string] != main.t[string;int,*string]\n\t\t{sn, in, false}, // main.t[string;string,*string] != main.t[int;int,*int]\n\t\t{sn, is, false}, // main.t[string;string,*string] != main.t[int;string,*int]\n\t\t{sn, ii, false}, // main.t[string;string,*string] != main.t[int;int,*int]\n\n\t\t{ss, si, false}, // main.t[string;string,*string] != main.t[string;int,*string]\n\t\t{ss, in, false}, // main.t[string;string,*string] != main.t[int;int,*int]\n\t\t{ss, is, false}, // main.t[string;string,*string] != main.t[int;string,*int]\n\t\t{ss, ii, false}, // main.t[string;string,*string] != main.t[int;int,*int]\n\n\t\t{si, in, false}, // main.t[string;int,*string] != main.t[int;int,*int]\n\t\t{si, is, false}, // main.t[string;int,*string] != main.t[int;string,*int]\n\t\t{si, ii, false}, // main.t[string;int,*string] != main.t[int;int,*int]\n\n\t\t{in, is, false}, // main.t[int;int,*int] != main.t[int;string,*int]\n\t\t{in, ii, true},  // main.t[int;int,*int] == main.t[int;int,*int]\n\n\t\t{is, ii, false}, // main.t[int;string,*int] != main.t[int;int,*int]\n\t} {\n\t\tx, y, want := t.x, t.y, t.want\n\t\tif got := x == y; got != want {\n\t\t\tmsg := fmt.Sprintf(\"(case %d) %T == %T. got %v. wanted %v\", i, x, y, got, want)\n\t\t\tpanic(msg)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue69298.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n)\n\ntype Seq[V any] func(yield func(V) bool)\n\nfunc AppendSeq[Slice ~[]E, E any](s Slice, seq Seq[E]) Slice {\n\tfor v := range seq {\n\t\ts = append(s, v)\n\t}\n\treturn s\n}\n\nfunc main() {\n\tseq := func(yield func(int) bool) {\n\t\tfor i := 0; i < 10; i += 2 {\n\t\t\tif !yield(i) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\ts := AppendSeq([]int{1, 2}, seq)\n\tfmt.Println(s)\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/fixedbugs/issue69929.go",
    "content": "package main\n\n// This is a regression test for a bug (#69929) in\n// the SSA interpreter in which it would not execute phis in parallel.\n//\n// The insert function below has interdependent phi nodes:\n//\n//\t  entry:\n//\t\tt0 = *root       // t0 is x or y before loop\n//\t\tjump test\n//\t  body:\n//\t\tprint(t5)      // t5 is x at loop entry\n//\t\tt3 = t5.Child    // t3 is x after loop\n//\t\tjump test\n//\t  test:\n//\t\tt5 = phi(t0, t3) // t5 is x at loop entry\n//\t\tt6 = phi(t0, t5) // t6 is y at loop entry\n//\t\tif t5 != nil goto body else done\n//\t  done:\n//\t\tprint(t6)\n//\t\treturn\n//\n// The two phis:\n//\n//\tt5 = phi(t0, t3)\n//\tt6 = phi(t0, t5)\n//\n// must be executed in parallel as if they were written in Go\n// as:\n//\n//\tt5, t6 = phi(t0, t3), phi(t0, t5)\n//\n// with the second phi node observing the original, not\n// updated, value of t5. (In more complex examples, the phi\n// nodes may be mutually recursive, breaking partial solutions\n// based on simple reordering of the phi instructions. See the\n// Briggs paper for detail.)\n//\n// The correct behavior is print(1, root); print(2, root); print(3, root).\n// The previous incorrect behavior had print(2, nil).\n\nfunc main() {\n\tinsert()\n\tprint(3, root)\n}\n\nvar root = new(node)\n\ntype node struct{ child *node }\n\nfunc insert() {\n\tx := root\n\ty := x\n\tfor x != nil {\n\t\ty = x\n\t\tprint(1, y)\n\t\tx = x.child\n\t}\n\tprint(2, y)\n}\n\nfunc print(order int, ptr *node) {\n\tprintln(order, ptr)\n\tif ptr != root {\n\t\tpanic(ptr)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/forvarlifetime_go122.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"reflect\"\n)\n\nfunc main() {\n\ttest_init()\n\tbound()\n\tmanyvars()\n\tnocond()\n\tnopost()\n\taddress_sequences()\n\tpost_escapes()\n\n\t// Clones from cmd/compile/internal/loopvar/testdata .\n\tfor_complicated_esc_address()\n\tfor_esc_address()\n\tfor_esc_closure()\n\tfor_esc_method()\n}\n\n// After go1.22, each i will have a distinct address and value.\nvar distinct = func(m, n int) []*int {\n\tvar r []*int\n\tfor i := m; i <= n; i++ {\n\t\tr = append(r, &i)\n\t}\n\treturn r\n}(3, 5)\n\nfunc test_init() {\n\tif len(distinct) != 3 {\n\t\tpanic(distinct)\n\t}\n\tfor i, v := range []int{3, 4, 5} {\n\t\tif v != *(distinct[i]) {\n\t\t\tpanic(distinct)\n\t\t}\n\t}\n}\n\nfunc bound() {\n\tb := func(k int) func() int {\n\t\tvar f func() int\n\t\tfor i := 0; i < k; i++ {\n\t\t\tf = func() int { return i } // address before post updates i. So last value in the body.\n\t\t}\n\t\treturn f\n\t}\n\n\tif got := b(0); got != nil {\n\t\tpanic(got)\n\t}\n\tif got := b(5); got() != 4 {\n\t\tpanic(got())\n\t}\n}\n\nfunc manyvars() {\n\t// Tests declaring many variables and having one in the middle escape.\n\tvar f func() int\n\tfor i, j, k, l, m, n, o, p := 7, 6, 5, 4, 3, 2, 1, 0; p < 6; l, p = l+1, p+1 {\n\t\t_, _, _, _, _, _, _, _ = i, j, k, l, m, n, o, p\n\t\tf = func() int { return l } // address *before* post updates l\n\t}\n\tif f() != 9 { // l == p+4\n\t\tpanic(f())\n\t}\n}\n\nfunc nocond() {\n\tvar c, b, e *int\n\tfor p := 0; ; p++ {\n\t\tif p%7 == 0 {\n\t\t\tc = &p\n\t\t\tcontinue\n\t\t} else if p == 20 {\n\t\t\tb = &p\n\t\t\tbreak\n\t\t}\n\t\te = &p\n\t}\n\n\tif *c != 14 {\n\t\tpanic(c)\n\t}\n\tif *b != 20 {\n\t\tpanic(b)\n\t}\n\tif *e != 19 {\n\t\tpanic(e)\n\t}\n}\n\nfunc nopost() {\n\tvar first, last *int\n\tfor p := 0; p < 20; {\n\t\tif first == nil {\n\t\t\tfirst = &p\n\t\t}\n\t\tlast = &p\n\n\t\tp++\n\t}\n\n\tif *first != 1 {\n\t\tpanic(first)\n\t}\n\tif *last != 20 {\n\t\tpanic(last)\n\t}\n}\n\nfunc address_sequences() {\n\tvar c, b, p []*int\n\n\tcond := func(x *int) bool {\n\t\tc = append(c, x)\n\t\treturn *x < 5\n\t}\n\tbody := func(x *int) {\n\t\tb = append(b, x)\n\t}\n\tpost := func(x *int) {\n\t\tp = append(p, x)\n\t\t(*x)++\n\t}\n\tfor i := 0; cond(&i); post(&i) {\n\t\tbody(&i)\n\t}\n\n\tif c[0] == c[1] {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(c[:5], b) {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(c[1:], p) {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(b[1:], p[:4]) {\n\t\tpanic(b)\n\t}\n}\n\nfunc post_escapes() {\n\tvar p []*int\n\tpost := func(x *int) {\n\t\tp = append(p, x)\n\t\t(*x)++\n\t}\n\n\tfor i := 0; i < 5; post(&i) {\n\t}\n\n\tvar got []int\n\tfor _, x := range p {\n\t\tgot = append(got, *x)\n\t}\n\tif want := []int{1, 2, 3, 4, 5}; !reflect.DeepEqual(got, want) {\n\t\tpanic(got)\n\t}\n}\n\nfunc for_complicated_esc_address() {\n\t// Clone of for_complicated_esc_adress.go\n\tss, sa := shared(23)\n\tps, pa := private(23)\n\tes, ea := experiment(23)\n\n\tif ss != ps || ss != es || ea != pa || sa == pa {\n\t\tprintln(\"shared s, a\", ss, sa, \"; private, s, a\", ps, pa, \"; experiment s, a\", es, ea)\n\t\tpanic(\"for_complicated_esc_address\")\n\t}\n}\n\nfunc experiment(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\tfor i := x; i != 1; i = i / 2 {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\n\treturn sum, asum\n}\n\nfunc private(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\tI := x\n\tfor ; I != 1; I = I / 2 {\n\t\ti := I\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t\tI = i\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\n\treturn sum, asum\n}\n\nfunc shared(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\ti := x\n\tfor ; i != 1; i = i / 2 {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\treturn sum, asum\n}\n\nfunc for_esc_address() {\n\t// Clone of for_esc_address.go\n\tsum := 0\n\tvar is []*int\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, pi := range is {\n\t\tsum += *pi\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected \", 20, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_address\")\n\t}\n}\n\nfunc for_esc_closure() {\n\tvar is []func() int\n\n\t// Clone of for_esc_closure.go\n\tsum := 0\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, func() int {\n\t\t\t\tif i%17 == 15 {\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\treturn i\n\t\t\t})\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected \", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, f := range is {\n\t\tsum += f()\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected \", 20, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_closure\")\n\t}\n}\n\ntype I int\n\nfunc (x *I) method() int {\n\treturn int(*x)\n}\n\nfunc for_esc_method() {\n\t// Clone of for_esc_method.go\n\tvar is []func() int\n\tsum := 0\n\tfor i := I(0); int(i) < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif int(i) == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, i.method)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected \", 90, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, m := range is {\n\t\tsum += m()\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected \", 20, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_method\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/forvarlifetime_old.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.21\n\n// goversion can be pinned to anything strictly before 1.22.\n\npackage main\n\nimport (\n\t\"reflect\"\n)\n\nfunc main() {\n\ttest_init()\n\tbound()\n\tmanyvars()\n\tnocond()\n\tnopost()\n\taddress_sequences()\n\tpost_escapes()\n\n\t// Clones from cmd/compile/internal/loopvar/testdata .\n\tfor_complicated_esc_address()\n\tfor_esc_address()\n\tfor_esc_closure()\n\tfor_esc_method()\n}\n\n// pre-go1.22 all of i will have the same address and the value of 6.\nvar same = func(m, n int) []*int {\n\tvar r []*int\n\tfor i := m; i <= n; i++ {\n\t\tr = append(r, &i)\n\t}\n\treturn r\n}(3, 5)\n\nfunc test_init() {\n\tif len(same) != 3 {\n\t\tpanic(same)\n\t}\n\tfor i := range same {\n\t\tfor j := range same {\n\t\t\tif !(same[i] == same[j]) {\n\t\t\t\tpanic(same)\n\t\t\t}\n\t\t}\n\t}\n\tfor i := range same {\n\t\tif *(same[i]) != 6 {\n\t\t\tpanic(same)\n\t\t}\n\t}\n}\n\nfunc bound() {\n\tb := func(k int) func() int {\n\t\tvar f func() int\n\t\tfor i := 0; i < k; i++ {\n\t\t\tf = func() int { return i } // shared address will equal k.\n\t\t}\n\t\treturn f\n\t}\n\n\tif got := b(0); got != nil {\n\t\tpanic(got)\n\t}\n\tif got := b(5); got() != 5 {\n\t\tpanic(got())\n\t}\n}\n\nfunc manyvars() {\n\t// Tests declaring many variables and having one in the middle escape.\n\tvar f func() int\n\tfor i, j, k, l, m, n, o, p := 7, 6, 5, 4, 3, 2, 1, 0; p < 6; l, p = l+1, p+1 {\n\t\t_, _, _, _, _, _, _, _ = i, j, k, l, m, n, o, p\n\t\tf = func() int { return l } // address *after* post updates l\n\t}\n\tif f() != 10 { // l == p+4\n\t\tpanic(f())\n\t}\n}\n\nfunc nocond() {\n\tvar c, b, e *int\n\tfor p := 0; ; p++ {\n\t\tif p%7 == 0 {\n\t\t\tc = &p\n\t\t\tcontinue\n\t\t} else if p == 20 {\n\t\t\tb = &p\n\t\t\tbreak\n\t\t}\n\t\te = &p\n\t}\n\n\tif *c != 20 {\n\t\tpanic(c)\n\t}\n\tif *b != 20 {\n\t\tpanic(b)\n\t}\n\tif *e != 20 {\n\t\tpanic(e)\n\t}\n}\n\nfunc nopost() {\n\tvar first, last *int\n\tfor p := 0; p < 20; {\n\t\tif first == nil {\n\t\t\tfirst = &p\n\t\t}\n\t\tlast = &p\n\n\t\tp++\n\t}\n\n\tif *first != 20 {\n\t\tpanic(first)\n\t}\n\tif *last != 20 {\n\t\tpanic(last)\n\t}\n}\n\nfunc address_sequences() {\n\tvar c, b, p []*int\n\n\tcond := func(x *int) bool {\n\t\tc = append(c, x)\n\t\treturn *x < 5\n\t}\n\tbody := func(x *int) {\n\t\tb = append(b, x)\n\t}\n\tpost := func(x *int) {\n\t\tp = append(p, x)\n\t\t(*x)++\n\t}\n\tfor i := 0; cond(&i); post(&i) {\n\t\tbody(&i)\n\t}\n\n\tif c[0] != c[1] {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(c[:5], b) {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(c[1:], p) {\n\t\tpanic(c)\n\t}\n\n\tif !reflect.DeepEqual(b[1:], p[:4]) {\n\t\tpanic(b)\n\t}\n}\n\nfunc post_escapes() {\n\tvar p []*int\n\tpost := func(x *int) {\n\t\tp = append(p, x)\n\t\t(*x)++\n\t}\n\n\tfor i := 0; i < 5; post(&i) {\n\t}\n\n\tvar got []int\n\tfor _, x := range p {\n\t\tgot = append(got, *x)\n\t}\n\tif want := []int{5, 5, 5, 5, 5}; !reflect.DeepEqual(got, want) {\n\t\tpanic(got)\n\t}\n}\n\nfunc for_complicated_esc_address() {\n\t// Clone of for_complicated_esc_adress.go\n\tss, sa := shared(23)\n\tps, pa := private(23)\n\tes, ea := experiment(23)\n\n\tif ss != ps || ss != es || sa != ea || pa != 188 {\n\t\tprintln(\"shared s, a\", ss, sa, \"; private, s, a\", ps, pa, \"; experiment s, a\", es, ea)\n\t\tpanic(\"for_complicated_esc_address\")\n\t}\n}\n\nfunc experiment(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\tfor i := x; i != 1; i = i / 2 {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\n\treturn sum, asum\n}\n\nfunc private(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\tI := x\n\tfor ; I != 1; I = I / 2 {\n\t\ti := I\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t\tI = i\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\n\treturn sum, asum\n}\n\nfunc shared(x int) (int, int) {\n\tsum := 0\n\tvar is []*int\n\ti := x\n\tfor ; i != 1; i = i / 2 {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\ti = i*3 + 1\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t\tfor i&2 == 0 {\n\t\t\t\ti = i >> 1\n\t\t\t}\n\t\t} else {\n\t\t\ti = i + i\n\t\t}\n\t}\n\n\tasum := 0\n\tfor _, pi := range is {\n\t\tasum += *pi\n\t}\n\treturn sum, asum\n}\n\nfunc for_esc_address() {\n\t// Clone of for_esc_address.go\n\tsum := 0\n\tvar is []*int\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, pi := range is {\n\t\tsum += *pi\n\t}\n\tif sum != 10+10+10+10+10 {\n\t\tprintln(\"wrong sum, expected \", 50, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_address\")\n\t}\n}\n\nfunc for_esc_closure() {\n\t// Clone of for_esc_closure.go\n\tvar is []func() int\n\tsum := 0\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, func() int {\n\t\t\t\tif i%17 == 15 {\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\treturn i\n\t\t\t})\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected \", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, f := range is {\n\t\tsum += f()\n\t}\n\tif sum != 10+10+10+10+10 {\n\t\tprintln(\"wrong sum, expected \", 50, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_closure\")\n\t}\n}\n\ntype I int\n\nfunc (x *I) method() int {\n\treturn int(*x)\n}\n\nfunc for_esc_method() {\n\t// Clone of for_esc_method.go\n\tsum := 0\n\tvar is []func() int\n\tfor i := I(0); int(i) < 10; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif int(i) == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, i.method)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected \", 90, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, m := range is {\n\t\tsum += m()\n\t}\n\tif sum != 10+10+10+10+10 {\n\t\tprintln(\"wrong sum, expected \", 50, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"for_esc_method\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/ifaceconv.go",
    "content": "package main\n\n// Tests of interface conversions and type assertions.\n\ntype I0 interface {\n}\ntype I1 interface {\n\tf()\n}\ntype I2 interface {\n\tf()\n\tg()\n}\n\ntype C0 struct{}\ntype C1 struct{}\n\nfunc (C1) f() {}\n\ntype C2 struct{}\n\nfunc (C2) f() {}\nfunc (C2) g() {}\n\nfunc main() {\n\tvar i0 I0\n\tvar i1 I1\n\tvar i2 I2\n\n\t// Nil always causes a type assertion to fail, even to the\n\t// same type.\n\tif _, ok := i0.(I0); ok {\n\t\tpanic(\"nil i0.(I0) succeeded\")\n\t}\n\tif _, ok := i1.(I1); ok {\n\t\tpanic(\"nil i1.(I1) succeeded\")\n\t}\n\tif _, ok := i2.(I2); ok {\n\t\tpanic(\"nil i2.(I2) succeeded\")\n\t}\n\n\t// Conversions can't fail, even with nil.\n\t_ = I0(i0)\n\n\t_ = I0(i1)\n\t_ = I1(i1)\n\n\t_ = I0(i2)\n\t_ = I1(i2)\n\t_ = I2(i2)\n\n\t// Non-nil type assertions pass or fail based on the concrete type.\n\ti1 = C1{}\n\tif _, ok := i1.(I0); !ok {\n\t\tpanic(\"C1 i1.(I0) failed\")\n\t}\n\tif _, ok := i1.(I1); !ok {\n\t\tpanic(\"C1 i1.(I1) failed\")\n\t}\n\tif _, ok := i1.(I2); ok {\n\t\tpanic(\"C1 i1.(I2) succeeded\")\n\t}\n\n\ti1 = C2{}\n\tif _, ok := i1.(I0); !ok {\n\t\tpanic(\"C2 i1.(I0) failed\")\n\t}\n\tif _, ok := i1.(I1); !ok {\n\t\tpanic(\"C2 i1.(I1) failed\")\n\t}\n\tif _, ok := i1.(I2); !ok {\n\t\tpanic(\"C2 i1.(I2) failed\")\n\t}\n\n\t// Conversions can't fail.\n\ti1 = C1{}\n\tif I0(i1) == nil {\n\t\tpanic(\"C1 I0(i1) was nil\")\n\t}\n\tif I1(i1) == nil {\n\t\tpanic(\"C1 I1(i1) was nil\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/ifaceprom.go",
    "content": "package main\n\n// Test of promotion of methods of an interface embedded within a\n// struct.  In particular, this test exercises that the correct\n// method is called.\n\ntype I interface {\n\tone() int\n\ttwo() string\n}\n\ntype S struct {\n\tI\n}\n\ntype impl struct{}\n\nfunc (impl) one() int {\n\treturn 1\n}\n\nfunc (impl) two() string {\n\treturn \"two\"\n}\n\nfunc main() {\n\tvar s S\n\ts.I = impl{}\n\tif one := s.I.one(); one != 1 {\n\t\tpanic(one)\n\t}\n\tif one := s.one(); one != 1 {\n\t\tpanic(one)\n\t}\n\tclosOne := s.I.one\n\tif one := closOne(); one != 1 {\n\t\tpanic(one)\n\t}\n\tclosOne = s.one\n\tif one := closOne(); one != 1 {\n\t\tpanic(one)\n\t}\n\n\tif two := s.I.two(); two != \"two\" {\n\t\tpanic(two)\n\t}\n\tif two := s.two(); two != \"two\" {\n\t\tpanic(two)\n\t}\n\tclosTwo := s.I.two\n\tif two := closTwo(); two != \"two\" {\n\t\tpanic(two)\n\t}\n\tclosTwo = s.two\n\tif two := closTwo(); two != \"two\" {\n\t\tpanic(two)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/initorder.go",
    "content": "package main\n\nimport \"fmt\"\n\n// Test of initialization order of package-level vars.\n\nvar counter int\n\nfunc next() int {\n\tc := counter\n\tcounter++\n\treturn c\n}\n\nfunc next2() (x int, y int) {\n\tx = next()\n\ty = next()\n\treturn\n}\n\nfunc makeOrder() int {\n\t_, _, _, _ = f, b, d, e\n\treturn 0\n}\n\nfunc main() {\n\t// Initialization constraints:\n\t// - {f,b,c/d,e} < order  (ref graph traversal)\n\t// - order < {a}          (lexical order)\n\t// - b < c/d < e < f      (lexical order)\n\t// Solution: a b c/d e f\n\tabcdef := [6]int{a, b, c, d, e, f}\n\tif abcdef != [6]int{0, 1, 2, 3, 4, 5} {\n\t\tpanic(abcdef)\n\t}\n\n\t// Initializers of even blank globals are evaluated.\n\tif g != 1 {\n\t\tpanic(g)\n\t}\n}\n\nvar order = makeOrder()\n\nvar a, b = next(), next()\nvar c, d = next2()\nvar e, f = next(), next()\n\nvar (\n\tg int\n\t_ = func() int { g = 1; return 0 }()\n)\n\n// ------------------------------------------------------------------------\n\nvar order2 []string\n\nfunc create(x int, name string) int {\n\torder2 = append(order2, name)\n\treturn x\n}\n\nvar C = create(B+1, \"C\")\nvar A, B = create(1, \"A\"), create(2, \"B\")\n\n// Initialization order of package-level value specs.\nfunc init() {\n\tx := fmt.Sprint(order2)\n\t// Result varies by toolchain.  This is a spec bug.\n\tif x != \"[B C A]\" && // gc\n\t\tx != \"[A B C]\" { // go/types\n\t\tpanic(x)\n\t}\n\tif C != 3 {\n\t\tpanic(c)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/methprom.go",
    "content": "package main\n\n// Tests of method promotion logic.\n\ntype A struct{ magic int }\n\nfunc (a A) x() {\n\tif a.magic != 1 {\n\t\tpanic(a.magic)\n\t}\n}\nfunc (a *A) y() *A {\n\treturn a\n}\n\ntype B struct{ magic int }\n\nfunc (b B) p() {\n\tif b.magic != 2 {\n\t\tpanic(b.magic)\n\t}\n}\nfunc (b *B) q() {\n\tif b != theC.B {\n\t\tpanic(\"oops\")\n\t}\n}\n\ntype I interface {\n\tf()\n}\n\ntype impl struct{ magic int }\n\nfunc (i impl) f() {\n\tif i.magic != 3 {\n\t\tpanic(\"oops\")\n\t}\n}\n\ntype C struct {\n\tA\n\t*B\n\tI\n}\n\nfunc assert(cond bool) {\n\tif !cond {\n\t\tpanic(\"failed\")\n\t}\n}\n\nvar theC = C{\n\tA: A{1},\n\tB: &B{2},\n\tI: impl{3},\n}\n\nfunc addr() *C {\n\treturn &theC\n}\n\nfunc value() C {\n\treturn theC\n}\n\nfunc main() {\n\t// address\n\taddr().x()\n\tif addr().y() != &theC.A {\n\t\tpanic(\"oops\")\n\t}\n\taddr().p()\n\taddr().q()\n\taddr().f()\n\n\t// addressable value\n\tvar c C = value()\n\tc.x()\n\tif c.y() != &c.A {\n\t\tpanic(\"oops\")\n\t}\n\tc.p()\n\tc.q()\n\tc.f()\n\n\t// non-addressable value\n\tvalue().x()\n\t// value().y() // not in method set\n\tvalue().p()\n\tvalue().q()\n\tvalue().f()\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/minmax.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc main() {\n\tTestMinFloat()\n\tTestMaxFloat()\n\tTestMinMaxInt()\n\tTestMinMaxUint8()\n\tTestMinMaxString()\n}\n\nfunc errorf(format string, args ...any) { panic(fmt.Sprintf(format, args...)) }\nfunc fatalf(format string, args ...any) { panic(fmt.Sprintf(format, args...)) }\n\n// derived from $GOROOT/src/runtime/minmax_test.go\n\nvar (\n\tzero    = math.Copysign(0, +1)\n\tnegZero = math.Copysign(0, -1)\n\tinf     = math.Inf(+1)\n\tnegInf  = math.Inf(-1)\n\tnan     = math.NaN()\n)\n\nvar tests = []struct{ min, max float64 }{\n\t{1, 2},\n\t{-2, 1},\n\t{negZero, zero},\n\t{zero, inf},\n\t{negInf, zero},\n\t{negInf, inf},\n\t{1, inf},\n\t{negInf, 1},\n}\n\nvar all = []float64{1, 2, -1, -2, zero, negZero, inf, negInf, nan}\n\nfunc eq(x, y float64) bool {\n\treturn x == y && math.Signbit(x) == math.Signbit(y)\n}\n\nfunc TestMinFloat() {\n\tfor _, tt := range tests {\n\t\tif z := min(tt.min, tt.max); !eq(z, tt.min) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", tt.min, tt.max, z, tt.min)\n\t\t}\n\t\tif z := min(tt.max, tt.min); !eq(z, tt.min) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", tt.max, tt.min, z, tt.min)\n\t\t}\n\t}\n\tfor _, x := range all {\n\t\tif z := min(nan, x); !math.IsNaN(z) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", nan, x, z, nan)\n\t\t}\n\t\tif z := min(x, nan); !math.IsNaN(z) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", nan, x, z, nan)\n\t\t}\n\t}\n}\n\nfunc TestMaxFloat() {\n\tfor _, tt := range tests {\n\t\tif z := max(tt.min, tt.max); !eq(z, tt.max) {\n\t\t\terrorf(\"max(%v, %v) = %v, want %v\", tt.min, tt.max, z, tt.max)\n\t\t}\n\t\tif z := max(tt.max, tt.min); !eq(z, tt.max) {\n\t\t\terrorf(\"max(%v, %v) = %v, want %v\", tt.max, tt.min, z, tt.max)\n\t\t}\n\t}\n\tfor _, x := range all {\n\t\tif z := max(nan, x); !math.IsNaN(z) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", nan, x, z, nan)\n\t\t}\n\t\tif z := max(x, nan); !math.IsNaN(z) {\n\t\t\terrorf(\"min(%v, %v) = %v, want %v\", nan, x, z, nan)\n\t\t}\n\t}\n}\n\n// testMinMax tests that min/max behave correctly on every pair of\n// values in vals.\n//\n// vals should be a sequence of values in strictly ascending order.\nfunc testMinMax[T int | uint8 | string](vals ...T) {\n\tfor i, x := range vals {\n\t\tfor _, y := range vals[i+1:] {\n\t\t\tif !(x < y) {\n\t\t\t\tfatalf(\"values out of order: !(%v < %v)\", x, y)\n\t\t\t}\n\n\t\t\tif z := min(x, y); z != x {\n\t\t\t\terrorf(\"min(%v, %v) = %v, want %v\", x, y, z, x)\n\t\t\t}\n\t\t\tif z := min(y, x); z != x {\n\t\t\t\terrorf(\"min(%v, %v) = %v, want %v\", y, x, z, x)\n\t\t\t}\n\n\t\t\tif z := max(x, y); z != y {\n\t\t\t\terrorf(\"max(%v, %v) = %v, want %v\", x, y, z, y)\n\t\t\t}\n\t\t\tif z := max(y, x); z != y {\n\t\t\t\terrorf(\"max(%v, %v) = %v, want %v\", y, x, z, y)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMinMaxInt()    { testMinMax[int](-7, 0, 9) }\nfunc TestMinMaxUint8()  { testMinMax[uint8](0, 1, 2, 4, 7) }\nfunc TestMinMaxString() { testMinMax[string](\"a\", \"b\", \"c\") }\n"
  },
  {
    "path": "go/ssa/interp/testdata/mrvchain.go",
    "content": "// Tests of call chaining f(g()) when g has multiple return values (MRVs).\n// See https://code.google.com/p/go/issues/detail?id=4573.\n\npackage main\n\nfunc assert(actual, expected int) {\n\tif actual != expected {\n\t\tpanic(actual)\n\t}\n}\n\nfunc g() (int, int) {\n\treturn 5, 7\n}\n\nfunc g2() (float64, float64) {\n\treturn 5, 7\n}\n\nfunc f1v(x int, v ...int) {\n\tassert(x, 5)\n\tassert(v[0], 7)\n}\n\nfunc f2(x, y int) {\n\tassert(x, 5)\n\tassert(y, 7)\n}\n\nfunc f2v(x, y int, v ...int) {\n\tassert(x, 5)\n\tassert(y, 7)\n\tassert(len(v), 0)\n}\n\nfunc complexArgs() (float64, float64) {\n\treturn 5, 7\n}\n\nfunc appendArgs() ([]string, string) {\n\treturn []string{\"foo\"}, \"bar\"\n}\n\nfunc h() (i interface{}, ok bool) {\n\tm := map[int]string{1: \"hi\"}\n\ti, ok = m[1] // string->interface{} conversion within multi-valued expression\n\treturn\n}\n\nfunc h2() (i interface{}, ok bool) {\n\tch := make(chan string, 1)\n\tch <- \"hi\"\n\ti, ok = <-ch // string->interface{} conversion within multi-valued expression\n\treturn\n}\n\nfunc main() {\n\tf1v(g())\n\tf2(g())\n\tf2v(g())\n\tif c := complex(complexArgs()); c != 5+7i {\n\t\tpanic(c)\n\t}\n\tif s := append(appendArgs()); len(s) != 2 || s[0] != \"foo\" || s[1] != \"bar\" {\n\t\tpanic(s)\n\t}\n\ti, ok := h()\n\tif !ok || i.(string) != \"hi\" {\n\t\tpanic(i)\n\t}\n\ti, ok = h2()\n\tif !ok || i.(string) != \"hi\" {\n\t\tpanic(i)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/newexpr_go126.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.26\n\npackage main\n\nfunc main() {\n\t// Test new(expr), introduced in go1.26.\n\tvar ptr *int = new(123)\n\tif *ptr != 123 {\n\t\tpanic(\"wrong value\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/range.go",
    "content": "package main\n\n// Tests of range loops.\n\nimport \"fmt\"\n\n// Range over string.\nfunc init() {\n\tif x := len(\"Hello, 世界\"); x != 13 { // bytes\n\t\tpanic(x)\n\t}\n\tvar indices []int\n\tvar runes []rune\n\tfor i, r := range \"Hello, 世界\" {\n\t\trunes = append(runes, r)\n\t\tindices = append(indices, i)\n\t}\n\tif x := fmt.Sprint(runes); x != \"[72 101 108 108 111 44 32 19990 30028]\" {\n\t\tpanic(x)\n\t}\n\tif x := fmt.Sprint(indices); x != \"[0 1 2 3 4 5 6 7 10]\" {\n\t\tpanic(x)\n\t}\n\ts := \"\"\n\tfor _, r := range runes {\n\t\ts += string(r)\n\t}\n\tif s != \"Hello, 世界\" {\n\t\tpanic(s)\n\t}\n\n\tvar x int\n\tfor range \"Hello, 世界\" {\n\t\tx++\n\t}\n\tif x != len(indices) {\n\t\tpanic(x)\n\t}\n}\n\n// Regression test for range of pointer to named array type.\nfunc init() {\n\ttype intarr [3]int\n\tia := intarr{1, 2, 3}\n\tvar count int\n\tfor _, x := range &ia {\n\t\tcount += x\n\t}\n\tif count != 6 {\n\t\tpanic(count)\n\t}\n}\n\nfunc main() {\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/rangefunc.go",
    "content": "// Range over functions.\n\n// Currently requires 1.22 and GOEXPERIMENT=rangefunc.\n\n// Fork of src/cmd/compile/internal/rangefunc/rangefunc_test.go\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc main() {\n\tTestCheck(\"TestCheck\")\n\tTestCooperativeBadOfSliceIndex(\"TestCooperativeBadOfSliceIndex\")\n\tTestCooperativeBadOfSliceIndexCheck(\"TestCooperativeBadOfSliceIndexCheck\")\n\tTestTrickyIterAll(\"TestTrickyIterAll\")\n\tTestTrickyIterOne(\"TestTrickyIterOne\")\n\tTestTrickyIterZero(\"TestTrickyIterZero\")\n\tTestTrickyIterZeroCheck(\"TestTrickyIterZeroCheck\")\n\tTestTrickyIterEcho(\"TestTrickyIterEcho\")\n\tTestTrickyIterEcho2(\"TestTrickyIterEcho2\")\n\tTestBreak1(\"TestBreak1\")\n\tTestBreak2(\"TestBreak2\")\n\tTestContinue(\"TestContinue\")\n\tTestBreak3(\"TestBreak3\")\n\tTestBreak1BadA(\"TestBreak1BadA\")\n\tTestBreak1BadB(\"TestBreak1BadB\")\n\tTestMultiCont0(\"TestMultiCont0\")\n\tTestMultiCont1(\"TestMultiCont1\")\n\tTestMultiCont2(\"TestMultiCont2\")\n\tTestMultiCont3(\"TestMultiCont3\")\n\tTestMultiBreak0(\"TestMultiBreak0\")\n\tTestMultiBreak1(\"TestMultiBreak1\")\n\tTestMultiBreak2(\"TestMultiBreak2\")\n\tTestMultiBreak3(\"TestMultiBreak3\")\n\tTestPanickyIterator1(\"TestPanickyIterator1\")\n\tTestPanickyIterator1Check(\"TestPanickyIterator1Check\")\n\tTestPanickyIterator2(\"TestPanickyIterator2\")\n\tTestPanickyIterator2Check(\"TestPanickyIterator2Check\")\n\tTestPanickyIterator3(\"TestPanickyIterator3\")\n\tTestPanickyIterator3Check(\"TestPanickyIterator3Check\")\n\tTestPanickyIterator4(\"TestPanickyIterator4\")\n\tTestPanickyIterator4Check(\"TestPanickyIterator4Check\")\n\tTestVeryBad1(\"TestVeryBad1\")\n\tTestVeryBad2(\"TestVeryBad2\")\n\tTestVeryBadCheck(\"TestVeryBadCheck\")\n\tTestOk(\"TestOk\")\n\tTestBreak1BadDefer(\"TestBreak1BadDefer\")\n\tTestReturns(\"TestReturns\")\n\tTestGotoA(\"TestGotoA\")\n\tTestGotoB(\"TestGotoB\")\n\tTestPanicReturns(\"TestPanicReturns\")\n}\n\ntype testingT string\n\nfunc (t testingT) Log(args ...any) {\n\ts := fmt.Sprint(args...)\n\tprintln(t, \"\\t\", s)\n}\n\nfunc (t testingT) Error(args ...any) {\n\ts := string(t) + \"\\terror: \" + fmt.Sprint(args...)\n\tpanic(s)\n}\n\n// slicesEqual is a clone of slices.Equal\nfunc slicesEqual[S ~[]E, E comparable](s1, s2 S) bool {\n\tif len(s1) != len(s2) {\n\t\treturn false\n\t}\n\tfor i := range s1 {\n\t\tif s1[i] != s2[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\ntype Seq[T any] func(yield func(T) bool)\ntype Seq2[T1, T2 any] func(yield func(T1, T2) bool)\n\n// OfSliceIndex returns a Seq2 over the elements of s. It is equivalent\n// to range s.\nfunc OfSliceIndex[T any, S ~[]T](s S) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tif !yield(i, v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n}\n\n// BadOfSliceIndex is \"bad\" because it ignores the return value from yield\n// and just keeps on iterating.\nfunc BadOfSliceIndex[T any, S ~[]T](s S) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tyield(i, v)\n\t\t}\n\t\treturn\n\t}\n}\n\n// VeryBadOfSliceIndex is \"very bad\" because it ignores the return value from yield\n// and just keeps on iterating, and also wraps that call in a defer-recover so it can\n// keep on trying after the first panic.\nfunc VeryBadOfSliceIndex[T any, S ~[]T](s S) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tfunc() {\n\t\t\t\tdefer func() {\n\t\t\t\t\trecover()\n\t\t\t\t}()\n\t\t\t\tyield(i, v)\n\t\t\t}()\n\t\t}\n\t\treturn\n\t}\n}\n\n// SwallowPanicOfSliceIndex hides panics and converts them to normal return\nfunc SwallowPanicOfSliceIndex[T any, S ~[]T](s S) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tdone := false\n\t\t\tfunc() {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tdone = true\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tdone = !yield(i, v)\n\t\t\t}()\n\t\t\tif done {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n}\n\n// PanickyOfSliceIndex iterates the slice but panics if it exits the loop early\nfunc PanickyOfSliceIndex[T any, S ~[]T](s S) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tif !yield(i, v) {\n\t\t\t\tpanic(\"Panicky iterator panicking\")\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n}\n\n// CooperativeBadOfSliceIndex calls the loop body from a goroutine after\n// a ping on a channel, and returns recover()on that same channel.\nfunc CooperativeBadOfSliceIndex[T any, S ~[]T](s S, proceed chan any) Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tfor i, v := range s {\n\t\t\tif !yield(i, v) {\n\t\t\t\t// if the body breaks, call yield just once in a goroutine\n\t\t\t\tgo func() {\n\t\t\t\t\t<-proceed\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tproceed <- recover()\n\t\t\t\t\t}()\n\t\t\t\t\tyield(0, s[0])\n\t\t\t\t}()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n}\n\n// TrickyIterator is a type intended to test whether an iterator that\n// calls a yield function after loop exit must inevitably escape the\n// closure; this might be relevant to future checking/optimization.\ntype TrickyIterator struct {\n\tyield func(int, int) bool\n}\n\nfunc (ti *TrickyIterator) iterEcho(s []int) Seq2[int, int] {\n\treturn func(yield func(int, int) bool) {\n\t\tfor i, v := range s {\n\t\t\tif !yield(i, v) {\n\t\t\t\tti.yield = yield\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif ti.yield != nil && !ti.yield(i, v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tti.yield = yield\n\t\treturn\n\t}\n}\n\nfunc (ti *TrickyIterator) iterAll(s []int) Seq2[int, int] {\n\treturn func(yield func(int, int) bool) {\n\t\tti.yield = yield // Save yield for future abuse\n\t\tfor i, v := range s {\n\t\t\tif !yield(i, v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n}\nfunc (ti *TrickyIterator) iterOne(s []int) Seq2[int, int] {\n\treturn func(yield func(int, int) bool) {\n\t\tti.yield = yield // Save yield for future abuse\n\t\tif len(s) > 0 {  // Not in a loop might escape differently\n\t\t\tyield(0, s[0])\n\t\t}\n\t\treturn\n\t}\n}\nfunc (ti *TrickyIterator) iterZero(s []int) Seq2[int, int] {\n\treturn func(yield func(int, int) bool) {\n\t\tti.yield = yield // Save yield for future abuse\n\t\t// Don't call it at all, maybe it won't escape\n\t\treturn\n\t}\n}\nfunc (ti *TrickyIterator) fail() {\n\tif ti.yield != nil {\n\t\tti.yield(1, 1)\n\t}\n}\n\nfunc matchError(r any, x string) bool {\n\tif r == nil {\n\t\treturn false\n\t}\n\tif x == \"\" {\n\t\treturn true\n\t}\n\tswitch p := r.(type) {\n\tcase string:\n\t\treturn p == x\n\tcase errorString:\n\t\treturn p.Error() == x\n\tcase error:\n\t\treturn strings.Contains(p.Error(), x)\n\t}\n\treturn false\n}\n\nfunc matchErrorHelper(t testingT, r any, x string) {\n\tif matchError(r, x) {\n\t\tt.Log(\"Saw expected panic: \", r)\n\t} else {\n\t\tt.Error(\"Saw wrong panic: '\", r, \"' . expected '\", x, \"'\")\n\t}\n}\n\nconst DONE = 0          // body of loop has exited in a non-panic way\nconst READY = 1         // body of loop has not exited yet, is not running\nconst PANIC = 2         // body of loop is either currently running, or has panicked\nconst EXHAUSTED = 3     // iterator function return, i.e., sequence is \"exhausted\"\nconst MISSING_PANIC = 4 // overload \"READY\" for panic call\n\n// An errorString represents a runtime error described by a single string.\ntype errorString string\n\nfunc (e errorString) Error() string {\n\treturn string(e)\n}\n\nconst (\n\t// RERR_ is for runtime error, and may be regexps/substrings, to simplify use of tests with tools\n\tRERR_DONE      = \"yield function called after range loop exit\"\n\tRERR_PANIC     = \"range function continued iteration after loop body panic\"\n\tRERR_EXHAUSTED = \"yield function called after range loop exit\" // ssa does not distinguish DONE and EXHAUSTED\n\tRERR_MISSING   = \"iterator call did not preserve panic\"\n\n\t// CERR_ is for checked errors in the Check combinator defined above, and should be literal strings\n\tCERR_PFX       = \"checked rangefunc error: \"\n\tCERR_DONE      = CERR_PFX + \"loop iteration after body done\"\n\tCERR_PANIC     = CERR_PFX + \"loop iteration after panic\"\n\tCERR_EXHAUSTED = CERR_PFX + \"loop iteration after iterator exit\"\n\tCERR_MISSING   = CERR_PFX + \"loop iterator swallowed panic\"\n)\n\nvar fail []error = []error{\n\terrorString(CERR_DONE),\n\terrorString(CERR_PFX + \"loop iterator, unexpected error\"),\n\terrorString(CERR_PANIC),\n\terrorString(CERR_EXHAUSTED),\n\terrorString(CERR_MISSING),\n}\n\n// Check wraps the function body passed to iterator forall\n// in code that ensures that it cannot (successfully) be called\n// either after body return false (control flow out of loop) or\n// forall itself returns (the iteration is now done).\n//\n// Note that this can catch errors before the inserted checks.\nfunc Check[U, V any](forall Seq2[U, V]) Seq2[U, V] {\n\treturn func(body func(U, V) bool) {\n\t\tstate := READY\n\t\tforall(func(u U, v V) bool {\n\t\t\tif state != READY {\n\t\t\t\tpanic(fail[state])\n\t\t\t}\n\t\t\tstate = PANIC\n\t\t\tret := body(u, v)\n\t\t\tif ret {\n\t\t\t\tstate = READY\n\t\t\t} else {\n\t\t\t\tstate = DONE\n\t\t\t}\n\t\t\treturn ret\n\t\t})\n\t\tif state == PANIC {\n\t\t\tpanic(fail[MISSING_PANIC])\n\t\t}\n\t\tstate = EXHAUSTED\n\t}\n}\n\nfunc TestCheck(t testingT) {\n\ti := 0\n\tdefer func() {\n\t\tt.Log(\"i = \", i) // 45\n\t\tmatchErrorHelper(t, recover(), CERR_DONE)\n\t}()\n\tfor _, x := range Check(BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})) {\n\t\ti += x\n\t\tif i > 4*9 {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc TestCooperativeBadOfSliceIndex(t testingT) {\n\ti := 0\n\tproceed := make(chan any)\n\tfor _, x := range CooperativeBadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, proceed) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\tproceed <- true\n\tr := <-proceed\n\tmatchErrorHelper(t, r, RERR_EXHAUSTED)\n\tif i != 36 {\n\t\tt.Error(\"Expected i == 36, saw \", i, \"instead\")\n\t} else {\n\t\tt.Log(\"i = \", i)\n\t}\n}\n\nfunc TestCooperativeBadOfSliceIndexCheck(t testingT) {\n\ti := 0\n\tproceed := make(chan any)\n\tfor _, x := range Check(CooperativeBadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, proceed)) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\tproceed <- true\n\tr := <-proceed\n\tmatchErrorHelper(t, r, CERR_EXHAUSTED)\n\n\tif i != 36 {\n\t\tt.Error(\"Expected i == 36, saw \", i, \"instead\")\n\t} else {\n\t\tt.Log(\"i = \", i)\n\t}\n}\n\nfunc TestTrickyIterAll(t testingT) {\n\ttrickItAll := TrickyIterator{}\n\ti := 0\n\tfor _, x := range trickItAll.iterAll([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\tif i != 36 {\n\t\tt.Error(\"Expected i == 36, saw \", i, \" instead\")\n\t} else {\n\t\tt.Log(\"i = \", i)\n\t}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_EXHAUSTED)\n\t}()\n\ttrickItAll.fail()\n}\n\nfunc TestTrickyIterOne(t testingT) {\n\ttrickItOne := TrickyIterator{}\n\ti := 0\n\tfor _, x := range trickItOne.iterOne([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\tif i != 1 {\n\t\tt.Error(\"Expected i == 1, saw \", i, \" instead\")\n\t} else {\n\t\tt.Log(\"i = \", i)\n\t}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_EXHAUSTED)\n\t}()\n\ttrickItOne.fail()\n}\n\nfunc TestTrickyIterZero(t testingT) {\n\ttrickItZero := TrickyIterator{}\n\ti := 0\n\tfor _, x := range trickItZero.iterZero([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\t// Don't care about value, ought to be 0 anyhow.\n\tt.Log(\"i = \", i)\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_EXHAUSTED)\n\t}()\n\ttrickItZero.fail()\n}\n\nfunc TestTrickyIterZeroCheck(t testingT) {\n\ttrickItZero := TrickyIterator{}\n\ti := 0\n\tfor _, x := range Check(trickItZero.iterZero([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})) {\n\t\ti += x\n\t\tif i >= 36 {\n\t\t\tbreak\n\t\t}\n\t}\n\t// Don't care about value, ought to be 0 anyhow.\n\tt.Log(\"i = \", i)\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), CERR_EXHAUSTED)\n\t}()\n\ttrickItZero.fail()\n}\n\nfunc TestTrickyIterEcho(t testingT) {\n\ttrickItAll := TrickyIterator{}\n\ti := 0\n\tfor _, x := range trickItAll.iterAll([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\tt.Log(\"first loop i=\", i)\n\t\ti += x\n\t\tif i >= 10 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif i != 10 {\n\t\tt.Error(\"Expected i == 10, saw\", i, \"instead\")\n\t} else {\n\t\tt.Log(\"i = \", i)\n\t}\n\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_EXHAUSTED)\n\t\tt.Log(\"end i=\", i)\n\t}()\n\n\ti = 0\n\tfor _, x := range trickItAll.iterEcho([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\tt.Log(\"second loop i=\", i)\n\t\tif x >= 5 {\n\t\t\tbreak\n\t\t}\n\t}\n\n}\n\nfunc TestTrickyIterEcho2(t testingT) {\n\ttrickItAll := TrickyIterator{}\n\tvar i int\n\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_EXHAUSTED)\n\t\tt.Log(\"end i=\", i)\n\t}()\n\n\tfor k := range 2 {\n\t\ti = 0\n\t\tfor _, x := range trickItAll.iterEcho([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Log(\"k=\", k, \",x=\", x, \",i=\", i)\n\t\t\ti += x\n\t\t\tif i >= 10 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tt.Log(\"i = \", i)\n\n\t\tif i != 10 {\n\t\t\tt.Error(\"Expected i == 10, saw \", i, \"instead\")\n\t\t}\n\t}\n}\n\n// TestBreak1 should just work, with well-behaved iterators.\n// (The misbehaving iterator detector should not trigger.)\nfunc TestBreak1(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, -1, 1, 2, -2, 1, 2, -3}\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4}) {\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \" got \", result)\n\t}\n}\n\n// TestBreak2 should just work, with well-behaved iterators.\n// (The misbehaving iterator detector should not trigger.)\nfunc TestBreak2(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, -1, 1, 2, -2, 1, 2, -3}\nouter:\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4}) {\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif x == -4 {\n\t\t\t\tbreak outer\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t}\n}\n\n// TestContinue should just work, with well-behaved iterators.\n// (The misbehaving iterator detector should not trigger.)\nfunc TestContinue(t testingT) {\n\tvar result []int\n\tvar expect = []int{-1, 1, 2, -2, 1, 2, -3, 1, 2, -4}\nouter:\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4}) {\n\t\tresult = append(result, x)\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tcontinue outer\n\t\t\t}\n\t\t\tif x == -4 {\n\t\t\t\tbreak outer\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x-10)\n\t}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t}\n}\n\n// TestBreak3 should just work, with well-behaved iterators.\n// (The misbehaving iterator detector should not trigger.)\nfunc TestBreak3(t testingT) {\n\tvar result []int\n\tvar expect = []int{100, 10, 2, 4, 200, 10, 2, 4, 20, 2, 4, 300, 10, 2, 4, 20, 2, 4, 30}\nX:\n\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\tY:\n\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\tif 10*y >= x {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t\tif y == 30 {\n\t\t\t\tcontinue X\n\t\t\t}\n\t\tZ:\n\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\tif z&1 == 1 {\n\t\t\t\t\tcontinue Z\n\t\t\t\t}\n\t\t\t\tresult = append(result, z)\n\t\t\t\tif z >= 4 {\n\t\t\t\t\tcontinue Y\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult = append(result, -y) // should never be executed\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t}\n}\n\n// TestBreak1BadA should end in a panic when the outer-loop's\n// single-level break is ignore by BadOfSliceIndex\nfunc TestBreak1BadA(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, -1, 1, 2, -2, 1, 2, -3}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range BadOfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n}\n\n// TestBreak1BadB should end in a panic, sooner, when the inner-loop's\n// (nested) single-level break is ignored by BadOfSliceIndex\nfunc TestBreak1BadB(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2} // inner breaks, panics, after before outer appends\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, y := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n}\n\n// TestMultiCont0 tests multilevel continue with no bad iterators\n// (it should just work)\nfunc TestMultiCont0(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4, 2000}\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tcontinue W // modified to be multilevel\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got %v\", expect, result)\n\t}\n}\n\n// TestMultiCont1 tests multilevel continue with a bad iterator\n// in the outermost loop exited by the continue.\nfunc TestMultiCont1(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range BadOfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tcontinue W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiCont2 tests multilevel continue with a bad iterator\n// in a middle loop exited by the continue.\nfunc TestMultiCont2(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range BadOfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tcontinue W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiCont3 tests multilevel continue with a bad iterator\n// in the innermost loop exited by the continue.\nfunc TestMultiCont3(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tcontinue W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiBreak0 tests multilevel break with a bad iterator\n// in the outermost loop exited by the break (the outermost loop).\nfunc TestMultiBreak0(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range BadOfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tbreak W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiBreak1 tests multilevel break with a bad iterator\n// in an intermediate loop exited by the break.\nfunc TestMultiBreak1(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range BadOfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tbreak W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiBreak2 tests multilevel break with two bad iterators\n// in intermediate loops exited by the break.\nfunc TestMultiBreak2(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range BadOfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range BadOfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tbreak W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestMultiBreak3 tests multilevel break with the bad iterator\n// in the innermost loop exited by the break.\nfunc TestMultiBreak3(t testingT) {\n\tvar result []int\n\tvar expect = []int{1000, 10, 2, 4}\n\tdefer func() {\n\t\tt.Log(result)\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t\t}\n\t}()\nW:\n\tfor _, w := range OfSliceIndex([]int{1000, 2000}) {\n\t\tresult = append(result, w)\n\t\tif w == 2000 {\n\t\t\tbreak\n\t\t}\n\t\tfor _, x := range OfSliceIndex([]int{100, 200, 300, 400}) {\n\t\t\tfor _, y := range OfSliceIndex([]int{10, 20, 30, 40}) {\n\t\t\t\tresult = append(result, y)\n\t\t\t\tfor _, z := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\t\t\tif z&1 == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, z)\n\t\t\t\t\tif z >= 4 {\n\t\t\t\t\t\tbreak W\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = append(result, -y) // should never be executed\n\t\t\t}\n\t\t\tresult = append(result, x)\n\t\t}\n\t}\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\nfunc TestPanickyIterator1(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, 3, 4}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), \"Panicky iterator panicking\")\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, z := range PanickyOfSliceIndex([]int{1, 2, 3, 4}) {\n\t\tresult = append(result, z)\n\t\tif z == 4 {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc TestPanickyIterator1Check(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, 3, 4}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), \"Panicky iterator panicking\")\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, z := range Check(PanickyOfSliceIndex([]int{1, 2, 3, 4})) {\n\t\tresult = append(result, z)\n\t\tif z == 4 {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc TestPanickyIterator2(t testingT) {\n\tvar result []int\n\tvar expect = []int{100, 10, 1, 2}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_MISSING)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range OfSliceIndex([]int{100, 200}) {\n\t\tresult = append(result, x)\n\tY:\n\t\t// swallows panics and iterates to end BUT `break Y` disables the body, so--> 10, 1, 2\n\t\tfor _, y := range VeryBadOfSliceIndex([]int{10, 20}) {\n\t\t\tresult = append(result, y)\n\n\t\t\t// converts early exit into a panic --> 1, 2\n\t\t\tfor k, z := range PanickyOfSliceIndex([]int{1, 2}) { // iterator panics\n\t\t\t\tresult = append(result, z)\n\t\t\t\tif k == 1 {\n\t\t\t\t\tbreak Y\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestPanickyIterator2Check(t testingT) {\n\tvar result []int\n\tvar expect = []int{100, 10, 1, 2}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), CERR_MISSING)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range Check(OfSliceIndex([]int{100, 200})) {\n\t\tresult = append(result, x)\n\tY:\n\t\t// swallows panics and iterates to end BUT `break Y` disables the body, so--> 10, 1, 2\n\t\tfor _, y := range Check(VeryBadOfSliceIndex([]int{10, 20})) {\n\t\t\tresult = append(result, y)\n\n\t\t\t// converts early exit into a panic --> 1, 2\n\t\t\tfor k, z := range Check(PanickyOfSliceIndex([]int{1, 2})) { // iterator panics\n\t\t\t\tresult = append(result, z)\n\t\t\t\tif k == 1 {\n\t\t\t\t\tbreak Y\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestPanickyIterator3(t testingT) {\n\tvar result []int\n\tvar expect = []int{100, 10, 1, 2, 200, 10, 1, 2}\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tt.Error(\"Unexpected panic \", r)\n\t\t}\n\t\tt.Log(result)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range OfSliceIndex([]int{100, 200}) {\n\t\tresult = append(result, x)\n\tY:\n\t\t// swallows panics and iterates to end BUT `break Y` disables the body, so--> 10, 1, 2\n\t\t// This is cross-checked against the checked iterator below; the combinator should behave the same.\n\t\tfor _, y := range VeryBadOfSliceIndex([]int{10, 20}) {\n\t\t\tresult = append(result, y)\n\n\t\t\tfor k, z := range OfSliceIndex([]int{1, 2}) { // iterator does not panic\n\t\t\t\tresult = append(result, z)\n\t\t\t\tif k == 1 {\n\t\t\t\t\tbreak Y\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nfunc TestPanickyIterator3Check(t testingT) {\n\tvar result []int\n\tvar expect = []int{100, 10, 1, 2, 200, 10, 1, 2}\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tt.Error(\"Unexpected panic \", r)\n\t\t}\n\t\tt.Log(result)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range Check(OfSliceIndex([]int{100, 200})) {\n\t\tresult = append(result, x)\n\tY:\n\t\t// swallows panics and iterates to end BUT `break Y` disables the body, so--> 10, 1, 2\n\t\tfor _, y := range Check(VeryBadOfSliceIndex([]int{10, 20})) {\n\t\t\tresult = append(result, y)\n\n\t\t\tfor k, z := range Check(OfSliceIndex([]int{1, 2})) { // iterator does not panic\n\t\t\t\tresult = append(result, z)\n\t\t\t\tif k == 1 {\n\t\t\t\t\tbreak Y\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestPanickyIterator4(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, 3}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_MISSING)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range SwallowPanicOfSliceIndex([]int{1, 2, 3, 4}) {\n\t\tresult = append(result, x)\n\t\tif x == 3 {\n\t\t\tpanic(\"x is 3\")\n\t\t}\n\t}\n\n}\n\nfunc TestPanickyIterator4Check(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, 3}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), CERR_MISSING)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"Expected \", expect, \", got \", result)\n\t\t}\n\t}()\n\tfor _, x := range Check(SwallowPanicOfSliceIndex([]int{1, 2, 3, 4})) {\n\t\tresult = append(result, x)\n\t\tif x == 3 {\n\t\t\tpanic(\"x is 3\")\n\t\t}\n\t}\n\n}\n\n// veryBad tests that a loop nest behaves sensibly in the face of a\n// \"very bad\" iterator.  In this case, \"sensibly\" means that the\n// break out of X still occurs after the very bad iterator finally\n// quits running (the control flow bread crumbs remain.)\nfunc veryBad(s []int) []int {\n\tvar result []int\nX:\n\tfor _, x := range OfSliceIndex([]int{1, 2, 3}) {\n\t\tresult = append(result, x)\n\t\tfor _, y := range VeryBadOfSliceIndex(s) {\n\t\t\tresult = append(result, y)\n\t\t\tbreak X\n\t\t}\n\t\tfor _, z := range OfSliceIndex([]int{100, 200, 300}) {\n\t\t\tresult = append(result, z)\n\t\t\tif z == 100 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\n// veryBadCheck wraps a \"very bad\" iterator with Check,\n// demonstrating that the very bad iterator also hides panics\n// thrown by Check.\nfunc veryBadCheck(s []int) []int {\n\tvar result []int\nX:\n\tfor _, x := range OfSliceIndex([]int{1, 2, 3}) {\n\t\tresult = append(result, x)\n\t\tfor _, y := range Check(VeryBadOfSliceIndex(s)) {\n\t\t\tresult = append(result, y)\n\t\t\tbreak X\n\t\t}\n\t\tfor _, z := range OfSliceIndex([]int{100, 200, 300}) {\n\t\t\tresult = append(result, z)\n\t\t\tif z == 100 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\n// okay is the not-bad version of veryBad.\n// They should behave the same.\nfunc okay(s []int) []int {\n\tvar result []int\nX:\n\tfor _, x := range OfSliceIndex([]int{1, 2, 3}) {\n\t\tresult = append(result, x)\n\t\tfor _, y := range OfSliceIndex(s) {\n\t\t\tresult = append(result, y)\n\t\t\tbreak X\n\t\t}\n\t\tfor _, z := range OfSliceIndex([]int{100, 200, 300}) {\n\t\t\tresult = append(result, z)\n\t\t\tif z == 100 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\n// TestVeryBad1 checks the behavior of an extremely poorly behaved iterator.\nfunc TestVeryBad1(t testingT) {\n\tresult := veryBad([]int{10, 20, 30, 40, 50}) // odd length\n\texpect := []int{1, 10}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestVeryBad2 checks the behavior of an extremely poorly behaved iterator.\nfunc TestVeryBad2(t testingT) {\n\tresult := veryBad([]int{10, 20, 30, 40}) // even length\n\texpect := []int{1, 10}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestVeryBadCheck checks the behavior of an extremely poorly behaved iterator,\n// which also suppresses the exceptions from \"Check\"\nfunc TestVeryBadCheck(t testingT) {\n\tresult := veryBadCheck([]int{10, 20, 30, 40}) // even length\n\texpect := []int{1, 10}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// TestOk is the nice version of the very bad iterator.\nfunc TestOk(t testingT) {\n\tresult := okay([]int{10, 20, 30, 40, 50}) // odd length\n\texpect := []int{1, 10}\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n}\n\n// testBreak1BadDefer checks that defer behaves properly even in\n// the presence of loop bodies panicking out of bad iterators.\n// (i.e., the instrumentation did not break defer in these loops)\nfunc testBreak1BadDefer(t testingT) (result []int) {\n\tvar expect = []int{1, 2, -1, 1, 2, -2, 1, 2, -3, -30, -20, -10}\n\tdefer func() {\n\t\tmatchErrorHelper(t, recover(), RERR_DONE)\n\t\tif !slicesEqual(expect, result) {\n\t\t\tt.Error(\"(Inner) Expected \", expect, \", got\", result)\n\t\t}\n\t}()\n\tfor _, x := range BadOfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\treturn\n}\n\nfunc TestBreak1BadDefer(t testingT) {\n\tvar result []int\n\tvar expect = []int{1, 2, -1, 1, 2, -2, 1, 2, -3, -30, -20, -10}\n\tresult = testBreak1BadDefer(t)\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"(Outer) Expected \", expect, \", got \", result)\n\t}\n}\n\n// testReturn1 has no bad iterators.\nfunc testReturn1() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\treturn\n}\n\n// testReturn2 has an outermost bad iterator\nfunc testReturn2() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range BadOfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\treturn\n}\n\n// testReturn3 has an innermost bad iterator\nfunc testReturn3() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t}\n\treturn\n}\n\n// testReturn4 has no bad iterators, but exercises  return variable rewriting\n// differs from testReturn1 because deferred append to \"result\" does not change\n// the return value in this case.\nfunc testReturn4(t testingT) (_ []int, _ []int, err any) {\n\tvar result []int\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\treturn result, result, nil\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\n\treturn\n}\n\n// TestReturns checks that returns through bad iterators behave properly,\n// for inner and outer bad iterators.\nfunc TestReturns(t testingT) {\n\tvar result []int\n\tvar result2 []int\n\tvar expect = []int{-1, 1, 2, -10}\n\tvar expect2 = []int{-1, 1, 2}\n\tvar err any\n\tresult, err = testReturn1()\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err != nil {\n\t\tt.Error(\"Unexpected error: \", err)\n\t}\n\tresult, err = testReturn2()\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n\tresult, err = testReturn3()\n\tt.Log(result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n\n\tresult, result2, err = testReturn4(t)\n\tif !slicesEqual(expect2, result) {\n\t\tt.Error(\"Expected \", expect2, \"got\", result)\n\t}\n\tif !slicesEqual(expect2, result2) {\n\t\tt.Error(\"Expected \", expect2, \"got\", result2)\n\t}\n\tif err != nil {\n\t\tt.Error(\"Unexpected error \", err)\n\t}\n}\n\n// testGotoA1 tests loop-nest-internal goto, no bad iterators.\nfunc testGotoA1() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto A\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\tA:\n\t}\n\treturn\n}\n\n// testGotoA2 tests loop-nest-internal goto, outer bad iterator.\nfunc testGotoA2() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range BadOfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto A\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\tA:\n\t}\n\treturn\n}\n\n// testGotoA3 tests loop-nest-internal goto, inner bad iterator.\nfunc testGotoA3() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto A\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\tA:\n\t}\n\treturn\n}\nfunc TestGotoA(t testingT) {\n\tvar result []int\n\tvar expect = []int{-1, 1, 2, -2, 1, 2, -3, 1, 2, -4, -30, -20, -10}\n\tvar expect3 = []int{-1, 1, 2, -10} // first goto becomes a panic\n\tvar err any\n\tresult, err = testGotoA1()\n\tt.Log(\"testGotoA1\", result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err != nil {\n\t\tt.Error(\"Unexpected error: \", err)\n\t}\n\tresult, err = testGotoA2()\n\tt.Log(\"testGotoA2\", result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n\tresult, err = testGotoA3()\n\tt.Log(\"testGotoA3\", result)\n\tif !slicesEqual(expect3, result) {\n\t\tt.Error(\"Expected %v, got %v\", expect3, result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n}\n\n// testGotoB1 tests loop-nest-exiting goto, no bad iterators.\nfunc testGotoB1() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto B\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\nB:\n\tresult = append(result, 999)\n\treturn\n}\n\n// testGotoB2 tests loop-nest-exiting goto, outer bad iterator.\nfunc testGotoB2() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range BadOfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range OfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto B\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\nB:\n\tresult = append(result, 999)\n\treturn\n}\n\n// testGotoB3 tests loop-nest-exiting goto, inner bad iterator.\nfunc testGotoB3() (result []int, err any) {\n\tdefer func() {\n\t\terr = recover()\n\t}()\n\tfor _, x := range OfSliceIndex([]int{-1, -2, -3, -4, -5}) {\n\t\tresult = append(result, x)\n\t\tif x == -4 {\n\t\t\tbreak\n\t\t}\n\t\tdefer func() {\n\t\t\tresult = append(result, x*10)\n\t\t}()\n\t\tfor _, y := range BadOfSliceIndex([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tif y == 3 {\n\t\t\t\tgoto B\n\t\t\t}\n\t\t\tresult = append(result, y)\n\t\t}\n\t\tresult = append(result, x)\n\t}\nB:\n\tresult = append(result, 999)\n\treturn\n}\n\nfunc TestGotoB(t testingT) {\n\tvar result []int\n\tvar expect = []int{-1, 1, 2, 999, -10}\n\tvar expectX = []int{-1, 1, 2, -10}\n\tvar err any\n\tresult, err = testGotoB1()\n\tt.Log(\"testGotoB1\", result)\n\tif !slicesEqual(expect, result) {\n\t\tt.Error(\"Expected \", expect, \", got\", result)\n\t}\n\tif err != nil {\n\t\tt.Error(\"Unexpected error: \", err)\n\t}\n\tresult, err = testGotoB2()\n\tt.Log(\"testGotoB2\", result)\n\tif !slicesEqual(expectX, result) {\n\t\tt.Error(\"Expected %v, got %v\", expectX, result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n\n\tresult, err = testGotoB3()\n\tt.Log(\"testGotoB3\", result)\n\tif !slicesEqual(expectX, result) {\n\t\tt.Error(\"Expected %v, got %v\", expectX, result)\n\t}\n\tif err == nil {\n\t\tt.Error(\"Missing expected error\")\n\t} else {\n\t\tmatchErrorHelper(t, err, RERR_DONE)\n\t}\n}\n\n// once returns an iterator that runs its loop body once with the supplied value\nfunc once[T any](x T) Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tyield(x)\n\t}\n}\n\n// terrify converts an iterator into one that panics with the supplied string\n// if/when the loop body terminates early (returns false, for break, goto, outer\n// continue, or return).\nfunc terrify[T any](s string, forall Seq[T]) Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tforall(func(v T) bool {\n\t\t\tif !yield(v) {\n\t\t\t\tpanic(s)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n}\n\nfunc use[T any](T) {\n}\n\n// f runs a not-rangefunc iterator that recovers from a panic that follows execution of a return.\n// what does f return?\nfunc f() string {\n\tdefer func() { recover() }()\n\tdefer panic(\"f panic\")\n\tfor _, s := range []string{\"f return\"} {\n\t\treturn s\n\t}\n\treturn \"f not reached\"\n}\n\n// g runs a rangefunc iterator that recovers from a panic that follows execution of a return.\n// what does g return?\nfunc g() string {\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"g panic\", once(\"g return\")) {\n\t\treturn s\n\t}\n\treturn \"g not reached\"\n}\n\n// h runs a rangefunc iterator that recovers from a panic that follows execution of a return.\n// the panic occurs in the rangefunc iterator itself.\n// what does h return?\nfunc h() (hashS string) {\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"h panic\", once(\"h return\")) {\n\t\thashS := s\n\t\tuse(hashS)\n\t\treturn s\n\t}\n\treturn \"h not reached\"\n}\n\nfunc j() (hashS string) {\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"j panic\", once(\"j return\")) {\n\t\thashS = s\n\t\treturn\n\t}\n\treturn \"j not reached\"\n}\n\n// k runs a rangefunc iterator that recovers from a panic that follows execution of a return.\n// the panic occurs in the rangefunc iterator itself.\n// k includes an additional mechanism to for making the return happen\n// what does k return?\nfunc k() (hashS string) {\n\t_return := func(s string) { hashS = s }\n\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"k panic\", once(\"k return\")) {\n\t\t_return(s)\n\t\treturn\n\t}\n\treturn \"k not reached\"\n}\n\nfunc m() (hashS string) {\n\t_return := func(s string) { hashS = s }\n\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"m panic\", once(\"m return\")) {\n\t\tdefer _return(s)\n\t\treturn s + \", but should be replaced in a defer\"\n\t}\n\treturn \"m not reached\"\n}\n\nfunc n() string {\n\tdefer func() { recover() }()\n\tfor s := range terrify(\"n panic\", once(\"n return\")) {\n\t\treturn s + func(s string) string {\n\t\t\tdefer func() { recover() }()\n\t\t\tfor s := range terrify(\"n closure panic\", once(s)) {\n\t\t\t\treturn s\n\t\t\t}\n\t\t\treturn \"n closure not reached\"\n\t\t}(\" and n closure return\")\n\t}\n\treturn \"n not reached\"\n}\n\ntype terrifyTestCase struct {\n\tf func() string\n\te string\n}\n\nfunc TestPanicReturns(t testingT) {\n\ttcs := []terrifyTestCase{\n\t\t{f, \"f return\"},\n\t\t{g, \"g return\"},\n\t\t{h, \"h return\"},\n\t\t{k, \"k return\"},\n\t\t{j, \"j return\"},\n\t\t{m, \"m return\"},\n\t\t{n, \"n return and n closure return\"},\n\t}\n\n\tfor _, tc := range tcs {\n\t\tgot := tc.f()\n\t\tif got != tc.e {\n\t\t\tt.Error(\"Got '\", got, \"' expected \", tc.e)\n\t\t} else {\n\t\t\tt.Log(\"Got expected '\", got, \"'\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/rangeoverint.go",
    "content": "package main\n\n// Range over integers (Go 1.22).\n\nimport \"fmt\"\n\nfunc f() {\n\ts := \"AB\"\n\tfor range 5 {\n\t\ts += s\n\t}\n\tif s != \"ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB\" {\n\t\tpanic(s)\n\t}\n\n\tvar t []int\n\tfor i := range 10 {\n\t\tt = append(t, i)\n\t}\n\tif got, want := fmt.Sprint(t), \"[0 1 2 3 4 5 6 7 8 9]\"; got != want {\n\t\tpanic(got)\n\t}\n\n\tvar u []uint\n\tfor i := range uint(3) {\n\t\tu = append(u, i)\n\t}\n\tif got, want := fmt.Sprint(u), \"[0 1 2]\"; got != want {\n\t\tpanic(got)\n\t}\n\n\tfor i := range 0 {\n\t\tpanic(i)\n\t}\n\n\tfor i := range int(-1) {\n\t\tpanic(i)\n\t}\n\n\tfor _, test := range []struct {\n\t\tx    int\n\t\tb, c bool\n\t\twant string\n\t}{\n\t\t{-1, false, false, \"[-123 -123]\"},\n\t\t{0, false, false, \"[-123 -123]\"},\n\t\t{1, false, false, \"[-123 0 333 333]\"},\n\t\t{2, false, false, \"[-123 0 333 1 333 333]\"},\n\t\t{2, false, true, \"[-123 0 222 1 222 222]\"},\n\t\t{2, true, false, \"[-123 0 111 111]\"},\n\t\t{3, false, false, \"[-123 0 333 1 333 2 333 333]\"},\n\t} {\n\t\tgot := fmt.Sprint(valueSequence(test.x, test.b, test.c))\n\t\tif got != test.want {\n\t\t\tpanic(fmt.Sprint(test, got))\n\t\t}\n\t}\n}\n\n// valueSequence returns a sequence of the values of i.\n// b causes an early break and c causes a continue.\nfunc valueSequence(x int, b, c bool) []int {\n\tvar vals []int\n\tvar i int = -123\n\tvals = append(vals, i)\n\tfor i = range x {\n\t\tvals = append(vals, i)\n\t\tif b {\n\t\t\ti = 111\n\t\t\tvals = append(vals, i)\n\t\t\tbreak\n\t\t} else if c {\n\t\t\ti = 222\n\t\t\tvals = append(vals, i)\n\t\t\tcontinue\n\t\t}\n\t\ti = 333\n\t\tvals = append(vals, i)\n\t}\n\tvals = append(vals, i)\n\treturn vals\n}\n\nfunc main() { f() }\n"
  },
  {
    "path": "go/ssa/interp/testdata/rangevarlifetime_go122.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.22\n\npackage main\n\nfunc main() {\n\ttest_init()\n\n\t// Clones from cmd/compile/internal/loopvar/testdata .\n\trange_esc_address()\n\trange_esc_closure()\n\trange_esc_method()\n}\n\n// After go1.22, each i will have a distinct address.\nvar distinct = func(a [3]int) []*int {\n\tvar r []*int\n\tfor i := range a {\n\t\tr = append(r, &i)\n\t}\n\treturn r\n}([3]int{})\n\nfunc test_init() {\n\tif len(distinct) != 3 {\n\t\tpanic(distinct)\n\t}\n\tfor i := 0; i < 3; i++ {\n\t\tif i != *(distinct[i]) {\n\t\t\tpanic(distinct)\n\t\t}\n\t}\n}\n\nfunc range_esc_address() {\n\t// Clone of range_esc_address.go\n\tints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n\tsum := 0\n\tvar is []*int\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, pi := range is {\n\t\tsum += *pi\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected\", 20, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_address\")\n\t}\n}\n\nfunc range_esc_closure() {\n\t// Clone of range_esc_closure.go\n\tvar ints = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\tvar is []func() int\n\n\tsum := 0\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, func() int {\n\t\t\t\tif i%17 == 15 {\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\treturn i\n\t\t\t})\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, f := range is {\n\t\tsum += f()\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected \", 20, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_closure\")\n\t}\n}\n\ntype I int\n\nfunc (x *I) method() int {\n\treturn int(*x)\n}\n\nfunc range_esc_method() {\n\t// Clone of range_esc_method.go\n\tvar ints = []I{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n\tsum := 0\n\tvar is []func() int\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif int(i) == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, i.method)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, m := range is {\n\t\tsum += m()\n\t}\n\tif sum != 0+2+4+6+8 {\n\t\tprintln(\"wrong sum, expected \", 20, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_method\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/rangevarlifetime_old.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.21\n\n// goversion can be pinned to anything strictly before 1.22.\n\npackage main\n\nfunc main() {\n\ttest_init()\n\n\t// Clones from cmd/compile/internal/loopvar/testdata .\n\trange_esc_address()\n\trange_esc_closure()\n\trange_esc_method()\n}\n\n// pre-go1.22 all of i will have the same address.\nvar same = func(a [3]int) []*int {\n\tvar r []*int\n\tfor i := range a {\n\t\tr = append(r, &i)\n\t}\n\treturn r\n}([3]int{})\n\nfunc test_init() {\n\tif len(same) != 3 {\n\t\tpanic(same)\n\t}\n\tfor i := range same {\n\t\tfor j := range same {\n\t\t\tif !(same[i] == same[j]) {\n\t\t\t\tpanic(same)\n\t\t\t}\n\t\t}\n\t}\n\tfor i := range same {\n\t\tif *(same[i]) != 2 {\n\t\t\tpanic(same)\n\t\t}\n\t}\n}\n\nfunc range_esc_address() {\n\t// Clone of range_esc_address.go\n\tints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n\tsum := 0\n\tvar is []*int\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, &i)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, pi := range is {\n\t\tsum += *pi\n\t}\n\tif sum != 9+9+9+9+9 {\n\t\tprintln(\"wrong sum, expected\", 45, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_address\")\n\t}\n}\n\nfunc range_esc_closure() {\n\t// Clone of range_esc_closure.go\n\tvar ints = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\tvar is []func() int\n\n\tsum := 0\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif i == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, func() int {\n\t\t\t\tif i%17 == 15 {\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\treturn i\n\t\t\t})\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, f := range is {\n\t\tsum += f()\n\t}\n\tif sum != 9+9+9+9+9 {\n\t\tprintln(\"wrong sum, expected \", 45, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_closure\")\n\t}\n}\n\ntype I int\n\nfunc (x *I) method() int {\n\treturn int(*x)\n}\n\nfunc range_esc_method() {\n\t// Clone of range_esc_method.go\n\tvar ints = []I{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n\tsum := 0\n\tvar is []func() int\n\tfor _, i := range ints {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tif int(i) == j { // 10 skips\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsum++\n\t\t}\n\t\tif i&1 == 0 {\n\t\t\tis = append(is, i.method)\n\t\t}\n\t}\n\n\tbug := false\n\tif sum != 100-10 {\n\t\tprintln(\"wrong sum, expected\", 90, \", saw\", sum)\n\t\tbug = true\n\t}\n\tif len(is) != 5 {\n\t\tprintln(\"wrong iterations, expected \", 5, \", saw\", len(is))\n\t\tbug = true\n\t}\n\tsum = 0\n\tfor _, m := range is {\n\t\tsum += m()\n\t}\n\tif sum != 9+9+9+9+9 {\n\t\tprintln(\"wrong sum, expected \", 45, \", saw \", sum)\n\t\tbug = true\n\t}\n\tif bug {\n\t\tpanic(\"range_esc_method\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/recover.go",
    "content": "package main\n\n// Tests of panic/recover.\n\nimport \"fmt\"\n\nfunc fortyTwo() (r int) {\n\tr = 42\n\t// The next two statements simulate a 'return' statement.\n\tdefer func() { recover() }()\n\tpanic(nil)\n}\n\nfunc zero() int {\n\tdefer func() { recover() }()\n\tpanic(1)\n}\n\nfunc zeroEmpty() (int, string) {\n\tdefer func() { recover() }()\n\tpanic(1)\n}\n\nfunc main() {\n\tif r := fortyTwo(); r != 42 {\n\t\tpanic(r)\n\t}\n\tif r := zero(); r != 0 {\n\t\tpanic(r)\n\t}\n\tif r, s := zeroEmpty(); r != 0 || s != \"\" {\n\t\tpanic(fmt.Sprint(r, s))\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/reflect.go",
    "content": "package main\n\nimport \"reflect\"\n\nfunc main() {\n\t// Regression test for issue 9462.\n\tgot := reflect.SliceOf(reflect.TypeOf(byte(0))).String()\n\tif got != \"[]uint8\" && got != \"[]byte\" { // result varies by toolchain\n\t\tprintln(\"BUG: \" + got)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/slice2array.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test for slice to array conversion introduced in go1.20\n// See: https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer\n\npackage main\n\nfunc main() {\n\ts := make([]byte, 3, 4)\n\ts[0], s[1], s[2] = 2, 3, 5\n\ta := ([2]byte)(s)\n\ts[0] = 7\n\n\tif a != [2]byte{2, 3} {\n\t\tpanic(\"converted from non-nil slice to array\")\n\t}\n\n\t{\n\t\tvar s []int\n\t\ta := ([0]int)(s)\n\t\tif a != [0]int{} {\n\t\t\tpanic(\"zero len array is not equal\")\n\t\t}\n\t}\n\n\tif emptyToEmptyDoesNotPanic() {\n\t\tpanic(\"no panic expected from emptyToEmptyDoesNotPanic()\")\n\t}\n\tif !threeToFourDoesPanic() {\n\t\tpanic(\"panic expected from threeToFourDoesPanic()\")\n\t}\n\n\tif !fourPanicsWhileOneDoesNot[[4]int]() {\n\t\tpanic(\"panic expected from fourPanicsWhileOneDoesNot[[4]int]()\")\n\t}\n\tif fourPanicsWhileOneDoesNot[[1]int]() {\n\t\tpanic(\"no panic expected from fourPanicsWhileOneDoesNot[[1]int]()\")\n\t}\n\n\tif !fourPanicsWhileZeroDoesNot[[4]int]() {\n\t\tpanic(\"panic expected from fourPanicsWhileZeroDoesNot[[4]int]()\")\n\t}\n\tif fourPanicsWhileZeroDoesNot[[0]int]() {\n\t\tpanic(\"no panic expected from fourPanicsWhileZeroDoesNot[[0]int]()\")\n\t}\n}\n\nfunc emptyToEmptyDoesNotPanic() (raised bool) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\traised = true\n\t\t}\n\t}()\n\tvar s []int\n\t_ = ([0]int)(s)\n\treturn false\n}\n\nfunc threeToFourDoesPanic() (raised bool) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\traised = true\n\t\t}\n\t}()\n\ts := make([]int, 3, 5)\n\t_ = ([4]int)(s)\n\treturn false\n}\n\nfunc fourPanicsWhileOneDoesNot[T [1]int | [4]int]() (raised bool) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\traised = true\n\t\t}\n\t}()\n\ts := make([]int, 3, 5)\n\t_ = T(s)\n\treturn false\n}\n\nfunc fourPanicsWhileZeroDoesNot[T [0]int | [4]int]() (raised bool) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\traised = true\n\t\t}\n\t}()\n\tvar s []int\n\t_ = T(s)\n\treturn false\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/slice2arrayptr.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test for slice to array pointer conversion introduced in go1.17\n// See: https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer\n\npackage main\n\nfunc main() {\n\ts := make([]byte, 2, 4)\n\tif s0 := (*[0]byte)(s); s0 == nil {\n\t\tpanic(\"converted from non-nil slice result in nil array pointer\")\n\t}\n\tif s2 := (*[2]byte)(s); &s2[0] != &s[0] {\n\t\tpanic(\"the converted array is not slice underlying array\")\n\t}\n\twantPanic(\n\t\tfunc() {\n\t\t\t_ = (*[4]byte)(s) // panics: len([4]byte) > len(s)\n\t\t},\n\t\t\"runtime error: array length is greater than slice length\",\n\t)\n\n\tvar t []string\n\tif t0 := (*[0]string)(t); t0 != nil {\n\t\tpanic(\"nil slice converted to *[0]byte should be nil\")\n\t}\n\twantPanic(\n\t\tfunc() {\n\t\t\t_ = (*[1]string)(t) // panics: len([1]string) > len(t)\n\t\t},\n\t\t\"runtime error: array length is greater than slice length\",\n\t)\n\n\tf()\n}\n\ntype arr [2]int\n\nfunc f() {\n\ts := []int{1, 2, 3, 4}\n\t_ = *(*arr)(s)\n}\n\nfunc wantPanic(fn func(), s string) {\n\tdefer func() {\n\t\terr := recover()\n\t\tif err == nil {\n\t\t\tpanic(\"expected panic\")\n\t\t}\n\t\tif got := err.(error).Error(); got != s {\n\t\t\tpanic(\"expected panic \" + s + \" got \" + got)\n\t\t}\n\t}()\n\tfn()\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/encoding/encoding.go",
    "content": "package encoding\n\ntype BinaryMarshaler interface {\n\tMarshalBinary() (data []byte, err error)\n}\ntype BinaryUnmarshaler interface {\n\tUnmarshalBinary(data []byte) error\n}\n\ntype TextMarshaler interface {\n\tMarshalText() (text []byte, err error)\n}\ntype TextUnmarshaler interface {\n\tUnmarshalText(text []byte) error\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/errors/errors.go",
    "content": "package errors\n\nfunc New(text string) error { return errorString{text} }\n\ntype errorString struct{ s string }\n\nfunc (e errorString) Error() string { return e.s }\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/fmt/fmt.go",
    "content": "package fmt\n\nimport (\n\t\"errors\"\n\t\"strings\"\n)\n\nfunc Sprint(args ...interface{}) string\n\nfunc Sprintln(args ...interface{}) string {\n\treturn Sprint(args...) + \"\\n\"\n}\n\nfunc Print(args ...interface{}) (int, error) {\n\tvar n int\n\tfor i, arg := range args {\n\t\tif i > 0 {\n\t\t\tprint(\" \")\n\t\t\tn++\n\t\t}\n\t\tmsg := Sprint(arg)\n\t\tn += len(msg)\n\t\tprint(msg)\n\t}\n\treturn n, nil\n}\n\nfunc Println(args ...interface{}) {\n\tPrint(args...)\n\tprintln()\n}\n\n// formatting is too complex to fake\n// handle the bare minimum needed for tests\n\nfunc Printf(format string, args ...interface{}) (int, error) {\n\tmsg := Sprintf(format, args...)\n\tprint(msg)\n\treturn len(msg), nil\n}\n\nfunc Sprintf(format string, args ...interface{}) string {\n\t// handle extremely simple cases that appear in tests.\n\tif len(format) == 0 {\n\t\treturn \"\"\n\t}\n\tswitch {\n\tcase strings.HasPrefix(\"%v\", format) || strings.HasPrefix(\"%s\", format):\n\t\treturn Sprint(args[0]) + Sprintf(format[2:], args[1:]...)\n\tcase !strings.HasPrefix(\"%\", format):\n\t\treturn format[:1] + Sprintf(format[1:], args...)\n\tdefault:\n\t\tpanic(\"unsupported format string for testing Sprintf\")\n\t}\n}\n\nfunc Errorf(format string, args ...interface{}) error {\n\tmsg := Sprintf(format, args...)\n\treturn errors.New(msg)\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/io/io.go",
    "content": "package io\n\nimport \"errors\"\n\nvar EOF = errors.New(\"EOF\")\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/log/log.go",
    "content": "package log\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc Println(v ...interface{}) {\n\tfmt.Println(v...)\n}\nfunc Printf(format string, v ...interface{}) {\n\tfmt.Printf(format, v...)\n}\n\nfunc Fatalln(v ...interface{}) {\n\tPrintln(v...)\n\tos.Exit(1)\n}\n\nfunc Fatalf(format string, v ...interface{}) {\n\tPrintf(format, v...)\n\tos.Exit(1)\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/math/math.go",
    "content": "package math\n\nfunc Copysign(float64, float64) float64\n\nfunc NaN() float64\n\nfunc Inf(int) float64\n\nfunc IsNaN(float64) bool\n\nfunc Float64bits(float64) uint64\n\nfunc Signbit(x float64) bool {\n\treturn Float64bits(x)&(1<<63) != 0\n}\n\nfunc Sqrt(x float64) float64\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/os/os.go",
    "content": "package os\n\nfunc Getenv(string) string\n\nfunc Exit(int)\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/reflect/deepequal.go",
    "content": "package reflect\n\n// Not an actual implementation of DeepEqual. This is a model that supports\n// the bare minimum needed to get through testing interp.\n//\n// Does not handle cycles.\n//\n// Note: unclear if reflect.go can support this.\nfunc DeepEqual(x, y interface{}) bool {\n\tif x == nil || y == nil {\n\t\treturn x == y\n\t}\n\tv1 := ValueOf(x)\n\tv2 := ValueOf(y)\n\n\treturn deepValueEqual(v1, v2, make(map[visit]bool))\n}\n\n// Key for the visitedMap in deepValueEqual.\ntype visit struct {\n\ta1, a2 uintptr\n\ttyp    Type\n}\n\nfunc deepValueEqual(v1, v2 Value, visited map[visit]bool) bool {\n\tif !v1.IsValid() || !v2.IsValid() {\n\t\treturn v1.IsValid() == v2.IsValid()\n\t}\n\tif v1.Type() != v2.Type() {\n\t\treturn false\n\t}\n\n\t// Short circuit on reference types that can lead to cycles in comparison.\n\tswitch v1.Kind() {\n\tcase Pointer, Map, Slice, Interface:\n\t\tk := visit{v1.Pointer(), v2.Pointer(), v1.Type()} // Not safe for moving GC.\n\t\tif visited[k] {\n\t\t\t// The comparison algorithm assumes that all checks in progress are true when it reencounters them.\n\t\t\treturn true\n\t\t}\n\t\tvisited[k] = true\n\t}\n\n\tswitch v1.Kind() {\n\tcase Array:\n\t\tfor i := 0; i < v1.Len(); i++ {\n\t\t\tif !deepValueEqual(v1.Index(i), v2.Index(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Slice:\n\t\tif v1.IsNil() != v2.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Len() != v2.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Pointer() == v2.Pointer() {\n\t\t\treturn true\n\t\t}\n\t\tfor i := 0; i < v1.Len(); i++ {\n\t\t\tif !deepValueEqual(v1.Index(i), v2.Index(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Interface:\n\t\tif v1.IsNil() || v2.IsNil() {\n\t\t\treturn v1.IsNil() == v2.IsNil()\n\t\t}\n\t\treturn deepValueEqual(v1.Elem(), v2.Elem(), visited)\n\tcase Ptr:\n\t\tif v1.Pointer() == v2.Pointer() {\n\t\t\treturn true\n\t\t}\n\t\treturn deepValueEqual(v1.Elem(), v2.Elem(), visited)\n\tcase Struct:\n\t\tfor i, n := 0, v1.NumField(); i < n; i++ {\n\t\t\tif !deepValueEqual(v1.Field(i), v2.Field(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Map:\n\t\tif v1.IsNil() != v2.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Len() != v2.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Pointer() == v2.Pointer() {\n\t\t\treturn true\n\t\t}\n\t\tfor _, k := range v1.MapKeys() {\n\t\t\tval1 := v1.MapIndex(k)\n\t\t\tval2 := v2.MapIndex(k)\n\t\t\tif !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1, val2, visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Func:\n\t\treturn v1.IsNil() && v2.IsNil()\n\tdefault:\n\t\t// Normal equality suffices\n\t\treturn v1.Interface() == v2.Interface() // try interface comparison as a fallback.\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/reflect/reflect.go",
    "content": "package reflect\n\ntype Type interface {\n\tString() string\n\tKind() Kind\n\tElem() Type\n}\n\ntype Value struct {\n}\n\nfunc (Value) String() string\n\nfunc (Value) Elem() Value\nfunc (Value) Kind() Kind\nfunc (Value) Int() int64\nfunc (Value) IsValid() bool\nfunc (Value) IsNil() bool\nfunc (Value) Len() int\nfunc (Value) Pointer() uintptr\nfunc (Value) Index(i int) Value\nfunc (Value) Type() Type\nfunc (Value) Field(int) Value\nfunc (Value) MapIndex(Value) Value\nfunc (Value) MapKeys() []Value\nfunc (Value) NumField() int\nfunc (Value) Interface() interface{}\n\nfunc SliceOf(Type) Type\n\nfunc TypeOf(interface{}) Type\n\nfunc ValueOf(interface{}) Value\n\ntype Kind uint\n\n// Constants need to be kept in sync with the actual definitions for comparisons in tests.\nconst (\n\tInvalid Kind = iota\n\tBool\n\tInt\n\tInt8\n\tInt16\n\tInt32\n\tInt64\n\tUint\n\tUint8\n\tUint16\n\tUint32\n\tUint64\n\tUintptr\n\tFloat32\n\tFloat64\n\tComplex64\n\tComplex128\n\tArray\n\tChan\n\tFunc\n\tInterface\n\tMap\n\tPointer\n\tSlice\n\tString\n\tStruct\n\tUnsafePointer\n)\n\nconst Ptr = Pointer\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/runtime/runtime.go",
    "content": "package runtime\n\n// An errorString represents a runtime error described by a single string.\ntype errorString string\n\nfunc (e errorString) RuntimeError() {}\n\nfunc (e errorString) Error() string {\n\treturn \"runtime error: \" + string(e)\n}\n\nfunc Breakpoint()\n\ntype Error interface {\n\terror\n\tRuntimeError()\n}\n\nfunc GC()\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/sort/sort.go",
    "content": "package sort\n\nfunc Strings(x []string)\nfunc Ints(x []int)\nfunc Float64s(x []float64)\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/strconv/strconv.go",
    "content": "package strconv\n\nfunc Itoa(i int) string\nfunc Atoi(s string) (int, error)\n\nfunc FormatFloat(float64, byte, int, int) string\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/strings/strings.go",
    "content": "package strings\n\nfunc Replace(s, old, new string, n int) string\n\nfunc Index(haystack, needle string) int\n\nfunc Contains(haystack, needle string) bool {\n\treturn Index(haystack, needle) >= 0\n}\n\nfunc HasPrefix(s, prefix string) bool {\n\treturn len(s) >= len(prefix) && s[0:len(prefix)] == prefix\n}\n\nfunc EqualFold(s, t string) bool\nfunc ToLower(s string) string\n\ntype Builder struct {\n\ts string\n}\n\nfunc (b *Builder) WriteString(s string) (int, error) {\n\tb.s += s\n\treturn len(s), nil\n}\nfunc (b *Builder) String() string { return b.s }\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/sync/sync.go",
    "content": "package sync\n\n// Rudimentary implementation of a mutex for interp tests.\ntype Mutex struct {\n\tc chan int // Mutex is held when held c!=nil and is empty. Access is guarded by g.\n}\n\nfunc (m *Mutex) Lock() {\n\tc := ch(m)\n\t<-c\n}\n\nfunc (m *Mutex) Unlock() {\n\tc := ch(m)\n\tc <- 1\n}\n\n// sequentializes Mutex.c access.\nvar g = make(chan int, 1)\n\nfunc init() {\n\tg <- 1\n}\n\n// ch initializes the m.c field if needed and returns it.\nfunc ch(m *Mutex) chan int {\n\t<-g\n\tdefer func() {\n\t\tg <- 1\n\t}()\n\tif m.c == nil {\n\t\tm.c = make(chan int, 1)\n\t\tm.c <- 1\n\t}\n\treturn m.c\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/time/time.go",
    "content": "package time\n\ntype Duration int64\n\nfunc Sleep(Duration)\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/unicode/utf8/utf8.go",
    "content": "package utf8\n\nfunc DecodeRuneInString(string) (rune, int)\n\nfunc DecodeRune(b []byte) (rune, int) {\n\treturn DecodeRuneInString(string(b))\n}\n\nconst RuneError = '\\uFFFD'\n"
  },
  {
    "path": "go/ssa/interp/testdata/src/unsafe/unsafe.go",
    "content": "package unsafe\n"
  },
  {
    "path": "go/ssa/interp/testdata/static.go",
    "content": "package main\n\n// Static tests of SSA builder (via the sanity checker).\n// Dynamic semantics are not exercised.\n\nfunc init() {\n\t// Regression test for issue 6806.\n\tch := make(chan int)\n\tselect {\n\tcase n, _ := <-ch:\n\t\t_ = n\n\tdefault:\n\t\t// The default case disables the simplification of\n\t\t// select to a simple receive statement.\n\t}\n\n\t// value,ok-form receive where TypeOf(ok) is a named boolean.\n\ttype mybool bool\n\tvar x int\n\tvar y mybool\n\tselect {\n\tcase x, y = <-ch:\n\tdefault:\n\t\t// The default case disables the simplification of\n\t\t// select to a simple receive statement.\n\t}\n\t_ = x\n\t_ = y\n}\n\nvar a int\n\n// Regression test for issue 7840 (covered by SSA sanity checker).\nfunc bug7840() bool {\n\t// This creates a single-predecessor block with a φ-node.\n\treturn false && a == 0 && a == 0\n}\n\n// A blocking select (sans \"default:\") cannot fall through.\n// Regression test for issue 7022.\nfunc bug7022() int {\n\tvar c1, c2 chan int\n\tselect {\n\tcase <-c1:\n\t\treturn 123\n\tcase <-c2:\n\t\treturn 456\n\t}\n}\n\n// Parens should not prevent intrinsic treatment of built-ins.\n// (Regression test for a crash.)\nfunc init() {\n\t_ = (new)(int)\n\t_ = (make)([]int, 0)\n}\n\nfunc main() {}\n"
  },
  {
    "path": "go/ssa/interp/testdata/typeassert.go",
    "content": "// Tests of type asserts.\n// Requires type parameters.\npackage typeassert\n\ntype fooer interface{ foo() string }\n\ntype X int\n\nfunc (_ X) foo() string { return \"x\" }\n\nfunc f[T fooer](x T) func() string {\n\treturn x.foo\n}\n\nfunc main() {\n\tif f[X](0)() != \"x\" {\n\t\tpanic(\"f[X]() != 'x'\")\n\t}\n\n\tp := false\n\tfunc() {\n\t\tdefer func() {\n\t\t\tif recover() != nil {\n\t\t\t\tp = true\n\t\t\t}\n\t\t}()\n\t\tf[fooer](nil) // panics on x.foo when T is an interface and nil.\n\t}()\n\tif !p {\n\t\tpanic(\"f[fooer] did not panic\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/width32.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test interpretation on 32 bit widths.\n\npackage main\n\nfunc main() {\n\tmapSize()\n}\n\nfunc mapSize() {\n\t// Tests for the size argument of make on a map type.\n\tconst tooBigFor32 = 1<<33 - 1\n\twantPanic(\n\t\tfunc() {\n\t\t\t_ = make(map[int]int, int64(tooBigFor32))\n\t\t},\n\t\t\"runtime error: ssa.MakeMap.Reserve value 8589934591 does not fit in int\",\n\t)\n\n\t// TODO: Enable the following if sizeof(int) can be different for host and target.\n\t// _ = make(map[int]int, tooBigFor32)\n\t//\n\t// Second arg to make in `make(map[int]int, tooBigFor32)` is an untyped int and\n\t// is converted into an int explicitly in ssa.\n\t// This has a different value on 32 and 64 bit systems.\n}\n\nfunc wantPanic(fn func(), s string) {\n\tdefer func() {\n\t\terr := recover()\n\t\tif err == nil {\n\t\t\tpanic(\"expected panic\")\n\t\t}\n\t\tif got := err.(error).Error(); got != s {\n\t\t\tpanic(\"expected panic \" + s + \" got \" + got)\n\t\t}\n\t}()\n\tfn()\n}\n"
  },
  {
    "path": "go/ssa/interp/testdata/zeros.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test interpretation on zero values with type params.\npackage zeros\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n\nfunc tp0[T int | string | float64]() T { return T(0) }\n\nfunc tpFalse[T ~bool]() T { return T(false) }\n\nfunc tpEmptyString[T string | []byte]() T { return T(\"\") }\n\nfunc tpNil[T *int | []byte]() T { return T(nil) }\n\nfunc main() {\n\t// zero values\n\tvar zi int\n\tvar zf float64\n\tvar zs string\n\n\tassert(zi == int(0), \"zero value of int is int(0)\")\n\tassert(zf == float64(0), \"zero value of float64 is float64(0)\")\n\tassert(zs != string(0), \"zero value of string is not string(0)\")\n\n\tassert(zi == tp0[int](), \"zero value of int is int(0)\")\n\tassert(zf == tp0[float64](), \"zero value of float64 is float64(0)\")\n\tassert(zs != tp0[string](), \"zero value of string is not string(0)\")\n\n\tassert(zf == -0.0, \"constant -0.0 is converted to 0.0\")\n\n\tassert(!tpFalse[bool](), \"zero value of bool is false\")\n\n\tassert(tpEmptyString[string]() == zs, `zero value of string is string(\"\")`)\n\tassert(len(tpEmptyString[[]byte]()) == 0, `[]byte(\"\") is empty`)\n\n\tassert(tpNil[*int]() == nil, \"nil is nil\")\n\tassert(tpNil[[]byte]() == nil, \"nil is nil\")\n}\n"
  },
  {
    "path": "go/ssa/interp/value.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage interp\n\n// Values\n//\n// All interpreter values are \"boxed\" in the empty interface, value.\n// The range of possible dynamic types within value are:\n//\n// - bool\n// - numbers (all built-in int/float/complex types are distinguished)\n// - string\n// - map[value]value --- maps for which  usesBuiltinMap(keyType)\n//   *hashmap        --- maps for which !usesBuiltinMap(keyType)\n// - chan value\n// - []value --- slices\n// - iface --- interfaces.\n// - structure --- structs.  Fields are ordered and accessed by numeric indices.\n// - array --- arrays.\n// - *value --- pointers.  Careful: *value is a distinct type from *array etc.\n// - *ssa.Function \\\n//   *ssa.Builtin   } --- functions.  A nil 'func' is always of type *ssa.Function.\n//   *closure      /\n// - tuple --- as returned by Return, Next, \"value,ok\" modes, etc.\n// - iter --- iterators from 'range' over map or string.\n// - bad --- a poison pill for locals that have gone out of scope.\n// - rtype -- the interpreter's concrete implementation of reflect.Type\n// - **deferred -- the address of a frame's defer stack for a Defer._Stack.\n//\n// Note that nil is not on this list.\n//\n// Pay close attention to whether or not the dynamic type is a pointer.\n// The compiler cannot help you since value is an empty interface.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"io\"\n\t\"reflect\"\n\t\"strings\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\ntype value any\n\ntype tuple []value\n\ntype array []value\n\ntype iface struct {\n\tt types.Type // never an \"untyped\" type\n\tv value\n}\n\ntype structure []value\n\n// For map, array, *array, slice, string or channel.\ntype iter interface {\n\t// next returns a Tuple (key, value, ok).\n\t// key and value are unaliased, e.g. copies of the sequence element.\n\tnext() tuple\n}\n\ntype closure struct {\n\tFn  *ssa.Function\n\tEnv []value\n}\n\ntype bad struct{}\n\ntype rtype struct {\n\tt types.Type\n}\n\n// Hash functions and equivalence relation:\n\n// hashString computes the FNV hash of s.\nfunc hashString(s string) int {\n\tvar h uint32\n\tfor i := 0; i < len(s); i++ {\n\t\th ^= uint32(s[i])\n\t\th *= 16777619\n\t}\n\treturn int(h)\n}\n\nvar hasher = typeutil.MakeHasher()\n\n// hashType returns a hash for t such that\n// types.Identical(x, y) => hashType(x) == hashType(y).\nfunc hashType(t types.Type) int {\n\treturn int(hasher.Hash(t))\n}\n\n// usesBuiltinMap returns true if the built-in hash function and\n// equivalence relation for type t are consistent with those of the\n// interpreter's representation of type t.  Such types are: all basic\n// types (bool, numbers, string), pointers and channels.\n//\n// usesBuiltinMap returns false for types that require a custom map\n// implementation: interfaces, arrays and structs.\n//\n// Panic ensues if t is an invalid map key type: function, map or slice.\nfunc usesBuiltinMap(t types.Type) bool {\n\tswitch t := t.(type) {\n\tcase *types.Basic, *types.Chan, *types.Pointer:\n\t\treturn true\n\tcase *types.Named, *types.Alias:\n\t\treturn usesBuiltinMap(t.Underlying())\n\tcase *types.Interface, *types.Array, *types.Struct:\n\t\treturn false\n\t}\n\tpanic(fmt.Sprintf(\"invalid map key type: %T\", t))\n}\n\nfunc (x array) eq(t types.Type, _y any) bool {\n\ty := _y.(array)\n\ttElt := t.Underlying().(*types.Array).Elem()\n\tfor i, xi := range x {\n\t\tif !equals(tElt, xi, y[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (x array) hash(t types.Type) int {\n\th := 0\n\ttElt := t.Underlying().(*types.Array).Elem()\n\tfor _, xi := range x {\n\t\th += hash(t, tElt, xi)\n\t}\n\treturn h\n}\n\nfunc (x structure) eq(t types.Type, _y any) bool {\n\ty := _y.(structure)\n\ttStruct := t.Underlying().(*types.Struct)\n\tfor i, n := 0, tStruct.NumFields(); i < n; i++ {\n\t\tif f := tStruct.Field(i); !f.Anonymous() {\n\t\t\tif !equals(f.Type(), x[i], y[i]) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (x structure) hash(t types.Type) int {\n\ttStruct := t.Underlying().(*types.Struct)\n\th := 0\n\tfor i, n := 0, tStruct.NumFields(); i < n; i++ {\n\t\tif f := tStruct.Field(i); !f.Anonymous() {\n\t\t\th += hash(t, f.Type(), x[i])\n\t\t}\n\t}\n\treturn h\n}\n\n// nil-tolerant variant of types.Identical.\nfunc sameType(x, y types.Type) bool {\n\tif x == nil {\n\t\treturn y == nil\n\t}\n\treturn y != nil && types.Identical(x, y)\n}\n\nfunc (x iface) eq(t types.Type, _y any) bool {\n\ty := _y.(iface)\n\treturn sameType(x.t, y.t) && (x.t == nil || equals(x.t, x.v, y.v))\n}\n\nfunc (x iface) hash(outer types.Type) int {\n\treturn hashType(x.t)*8581 + hash(outer, x.t, x.v)\n}\n\nfunc (x rtype) hash(_ types.Type) int {\n\treturn hashType(x.t)\n}\n\nfunc (x rtype) eq(_ types.Type, y any) bool {\n\treturn types.Identical(x.t, y.(rtype).t)\n}\n\n// equals returns true iff x and y are equal according to Go's\n// linguistic equivalence relation for type t.\n// In a well-typed program, the dynamic types of x and y are\n// guaranteed equal.\nfunc equals(t types.Type, x, y value) bool {\n\tswitch x := x.(type) {\n\tcase bool:\n\t\treturn x == y.(bool)\n\tcase int:\n\t\treturn x == y.(int)\n\tcase int8:\n\t\treturn x == y.(int8)\n\tcase int16:\n\t\treturn x == y.(int16)\n\tcase int32:\n\t\treturn x == y.(int32)\n\tcase int64:\n\t\treturn x == y.(int64)\n\tcase uint:\n\t\treturn x == y.(uint)\n\tcase uint8:\n\t\treturn x == y.(uint8)\n\tcase uint16:\n\t\treturn x == y.(uint16)\n\tcase uint32:\n\t\treturn x == y.(uint32)\n\tcase uint64:\n\t\treturn x == y.(uint64)\n\tcase uintptr:\n\t\treturn x == y.(uintptr)\n\tcase float32:\n\t\treturn x == y.(float32)\n\tcase float64:\n\t\treturn x == y.(float64)\n\tcase complex64:\n\t\treturn x == y.(complex64)\n\tcase complex128:\n\t\treturn x == y.(complex128)\n\tcase string:\n\t\treturn x == y.(string)\n\tcase *value:\n\t\treturn x == y.(*value)\n\tcase chan value:\n\t\treturn x == y.(chan value)\n\tcase structure:\n\t\treturn x.eq(t, y)\n\tcase array:\n\t\treturn x.eq(t, y)\n\tcase iface:\n\t\treturn x.eq(t, y)\n\tcase rtype:\n\t\treturn x.eq(t, y)\n\t}\n\n\t// Since map, func and slice don't support comparison, this\n\t// case is only reachable if one of x or y is literally nil\n\t// (handled in eqnil) or via interface{} values.\n\tpanic(fmt.Sprintf(\"comparing uncomparable type %s\", t))\n}\n\n// Returns an integer hash of x such that equals(x, y) => hash(x) == hash(y).\n// The outer type is used only for the \"unhashable\" panic message.\nfunc hash(outer, t types.Type, x value) int {\n\tswitch x := x.(type) {\n\tcase bool:\n\t\tif x {\n\t\t\treturn 1\n\t\t}\n\t\treturn 0\n\tcase int:\n\t\treturn x\n\tcase int8:\n\t\treturn int(x)\n\tcase int16:\n\t\treturn int(x)\n\tcase int32:\n\t\treturn int(x)\n\tcase int64:\n\t\treturn int(x)\n\tcase uint:\n\t\treturn int(x)\n\tcase uint8:\n\t\treturn int(x)\n\tcase uint16:\n\t\treturn int(x)\n\tcase uint32:\n\t\treturn int(x)\n\tcase uint64:\n\t\treturn int(x)\n\tcase uintptr:\n\t\treturn int(x)\n\tcase float32:\n\t\treturn int(x)\n\tcase float64:\n\t\treturn int(x)\n\tcase complex64:\n\t\treturn int(real(x))\n\tcase complex128:\n\t\treturn int(real(x))\n\tcase string:\n\t\treturn hashString(x)\n\tcase *value:\n\t\treturn int(uintptr(unsafe.Pointer(x)))\n\tcase chan value:\n\t\treturn int(uintptr(reflect.ValueOf(x).Pointer()))\n\tcase structure:\n\t\treturn x.hash(t)\n\tcase array:\n\t\treturn x.hash(t)\n\tcase iface:\n\t\treturn x.hash(t)\n\tcase rtype:\n\t\treturn x.hash(t)\n\t}\n\tpanic(fmt.Sprintf(\"unhashable type %v\", outer))\n}\n\n// reflect.Value struct values don't have a fixed shape, since the\n// payload can be a scalar or an aggregate depending on the instance.\n// So store (and load) can't simply use recursion over the shape of the\n// rhs value, or the lhs, to copy the value; we need the static type\n// information.  (We can't make reflect.Value a new basic data type\n// because its \"structness\" is exposed to Go programs.)\n\n// load returns the value of type T in *addr.\nfunc load(T types.Type, addr *value) value {\n\tswitch T := T.Underlying().(type) {\n\tcase *types.Struct:\n\t\tv := (*addr).(structure)\n\t\ta := make(structure, len(v))\n\t\tfor i := range a {\n\t\t\ta[i] = load(T.Field(i).Type(), &v[i])\n\t\t}\n\t\treturn a\n\tcase *types.Array:\n\t\tv := (*addr).(array)\n\t\ta := make(array, len(v))\n\t\tfor i := range a {\n\t\t\ta[i] = load(T.Elem(), &v[i])\n\t\t}\n\t\treturn a\n\tdefault:\n\t\treturn *addr\n\t}\n}\n\n// store stores value v of type T into *addr.\nfunc store(T types.Type, addr *value, v value) {\n\tswitch T := T.Underlying().(type) {\n\tcase *types.Struct:\n\t\tlhs := (*addr).(structure)\n\t\trhs := v.(structure)\n\t\tfor i := range lhs {\n\t\t\tstore(T.Field(i).Type(), &lhs[i], rhs[i])\n\t\t}\n\tcase *types.Array:\n\t\tlhs := (*addr).(array)\n\t\trhs := v.(array)\n\t\tfor i := range lhs {\n\t\t\tstore(T.Elem(), &lhs[i], rhs[i])\n\t\t}\n\tdefault:\n\t\t*addr = v\n\t}\n}\n\n// Prints in the style of built-in println.\n// (More or less; in gc println is actually a compiler intrinsic and\n// can distinguish println(1) from println(interface{}(1)).)\nfunc writeValue(buf *bytes.Buffer, v value) {\n\tswitch v := v.(type) {\n\tcase nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string:\n\t\tfmt.Fprintf(buf, \"%v\", v)\n\n\tcase map[value]value:\n\t\tbuf.WriteString(\"map[\")\n\t\tsep := \"\"\n\t\tfor k, e := range v {\n\t\t\tbuf.WriteString(sep)\n\t\t\tsep = \" \"\n\t\t\twriteValue(buf, k)\n\t\t\tbuf.WriteString(\":\")\n\t\t\twriteValue(buf, e)\n\t\t}\n\t\tbuf.WriteString(\"]\")\n\n\tcase *hashmap:\n\t\tbuf.WriteString(\"map[\")\n\t\tsep := \" \"\n\t\tfor _, e := range v.entries() {\n\t\t\tfor e != nil {\n\t\t\t\tbuf.WriteString(sep)\n\t\t\t\tsep = \" \"\n\t\t\t\twriteValue(buf, e.key)\n\t\t\t\tbuf.WriteString(\":\")\n\t\t\t\twriteValue(buf, e.value)\n\t\t\t\te = e.next\n\t\t\t}\n\t\t}\n\t\tbuf.WriteString(\"]\")\n\n\tcase chan value:\n\t\tfmt.Fprintf(buf, \"%v\", v) // (an address)\n\n\tcase *value:\n\t\tif v == nil {\n\t\t\tbuf.WriteString(\"<nil>\")\n\t\t} else {\n\t\t\tfmt.Fprintf(buf, \"%p\", v)\n\t\t}\n\n\tcase iface:\n\t\tfmt.Fprintf(buf, \"(%s, \", v.t)\n\t\twriteValue(buf, v.v)\n\t\tbuf.WriteString(\")\")\n\n\tcase structure:\n\t\tbuf.WriteString(\"{\")\n\t\tfor i, e := range v {\n\t\t\tif i > 0 {\n\t\t\t\tbuf.WriteString(\" \")\n\t\t\t}\n\t\t\twriteValue(buf, e)\n\t\t}\n\t\tbuf.WriteString(\"}\")\n\n\tcase array:\n\t\tbuf.WriteString(\"[\")\n\t\tfor i, e := range v {\n\t\t\tif i > 0 {\n\t\t\t\tbuf.WriteString(\" \")\n\t\t\t}\n\t\t\twriteValue(buf, e)\n\t\t}\n\t\tbuf.WriteString(\"]\")\n\n\tcase []value:\n\t\tbuf.WriteString(\"[\")\n\t\tfor i, e := range v {\n\t\t\tif i > 0 {\n\t\t\t\tbuf.WriteString(\" \")\n\t\t\t}\n\t\t\twriteValue(buf, e)\n\t\t}\n\t\tbuf.WriteString(\"]\")\n\n\tcase *ssa.Function, *ssa.Builtin, *closure:\n\t\tfmt.Fprintf(buf, \"%p\", v) // (an address)\n\n\tcase rtype:\n\t\tbuf.WriteString(v.t.String())\n\n\tcase tuple:\n\t\t// Unreachable in well-formed Go programs\n\t\tbuf.WriteString(\"(\")\n\t\tfor i, e := range v {\n\t\t\tif i > 0 {\n\t\t\t\tbuf.WriteString(\", \")\n\t\t\t}\n\t\t\twriteValue(buf, e)\n\t\t}\n\t\tbuf.WriteString(\")\")\n\n\tdefault:\n\t\tfmt.Fprintf(buf, \"<%T>\", v)\n\t}\n}\n\n// Implements printing of Go values in the style of built-in println.\nfunc toString(v value) string {\n\tvar b bytes.Buffer\n\twriteValue(&b, v)\n\treturn b.String()\n}\n\n// ------------------------------------------------------------------------\n// Iterators\n\ntype stringIter struct {\n\t*strings.Reader\n\ti int\n}\n\nfunc (it *stringIter) next() tuple {\n\tokv := make(tuple, 3)\n\tch, n, err := it.ReadRune()\n\tok := err != io.EOF\n\tokv[0] = ok\n\tif ok {\n\t\tokv[1] = it.i\n\t\tokv[2] = ch\n\t}\n\tit.i += n\n\treturn okv\n}\n\ntype mapIter struct {\n\titer *reflect.MapIter\n\tok   bool\n}\n\nfunc (it *mapIter) next() tuple {\n\tit.ok = it.iter.Next()\n\tif !it.ok {\n\t\treturn []value{false, nil, nil}\n\t}\n\tk, v := it.iter.Key().Interface(), it.iter.Value().Interface()\n\treturn []value{true, k, v}\n}\n\ntype hashmapIter struct {\n\titer *reflect.MapIter\n\tok   bool\n\tcur  *entry\n}\n\nfunc (it *hashmapIter) next() tuple {\n\tfor {\n\t\tif it.cur != nil {\n\t\t\tk, v := it.cur.key, it.cur.value\n\t\t\tit.cur = it.cur.next\n\t\t\treturn []value{true, k, v}\n\t\t}\n\t\tit.ok = it.iter.Next()\n\t\tif !it.ok {\n\t\t\treturn []value{false, nil, nil}\n\t\t}\n\t\tit.cur = it.iter.Value().Interface().(*entry)\n\t}\n}\n"
  },
  {
    "path": "go/ssa/lift.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines the lifting pass which tries to \"lift\" Alloc\n// cells (new/local variables) into SSA registers, replacing loads\n// with the dominating stored value, eliminating loads and stores, and\n// inserting φ-nodes as needed.\n\n// Cited papers and resources:\n//\n// Ron Cytron et al. 1991. Efficiently computing SSA form...\n// http://doi.acm.org/10.1145/115372.115320\n//\n// Cooper, Harvey, Kennedy.  2001.  A Simple, Fast Dominance Algorithm.\n// Software Practice and Experience 2001, 4:1-10.\n// http://www.hipersoft.rice.edu/grads/publications/dom14.pdf\n//\n// Daniel Berlin, llvmdev mailing list, 2012.\n// http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-January/046638.html\n// (Be sure to expand the whole thread.)\n\n// TODO(adonovan): opt: there are many optimizations worth evaluating, and\n// the conventional wisdom for SSA construction is that a simple\n// algorithm well engineered often beats those of better asymptotic\n// complexity on all but the most egregious inputs.\n//\n// Danny Berlin suggests that the Cooper et al. algorithm for\n// computing the dominance frontier is superior to Cytron et al.\n// Furthermore he recommends that rather than computing the DF for the\n// whole function then renaming all alloc cells, it may be cheaper to\n// compute the DF for each alloc cell separately and throw it away.\n//\n// Consider exploiting liveness information to avoid creating dead\n// φ-nodes which we then immediately remove.\n//\n// Also see many other \"TODO: opt\" suggestions in the code.\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"math/big\"\n\t\"os\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// If true, show diagnostic information at each step of lifting.\n// Very verbose.\nconst debugLifting = false\n\n// domFrontier maps each block to the set of blocks in its dominance\n// frontier.  The outer slice is conceptually a map keyed by\n// Block.Index.  The inner slice is conceptually a set, possibly\n// containing duplicates.\n//\n// TODO(adonovan): opt: measure impact of dups; consider a packed bit\n// representation, e.g. big.Int, and bitwise parallel operations for\n// the union step in the Children loop.\n//\n// domFrontier's methods mutate the slice's elements but not its\n// length, so their receivers needn't be pointers.\ntype domFrontier [][]*BasicBlock\n\nfunc (df domFrontier) add(u, v *BasicBlock) {\n\tp := &df[u.Index]\n\t*p = append(*p, v)\n}\n\n// build builds the dominance frontier df for the dominator (sub)tree\n// rooted at u, using the Cytron et al. algorithm.\n//\n// TODO(adonovan): opt: consider Berlin approach, computing pruned SSA\n// by pruning the entire IDF computation, rather than merely pruning\n// the DF -> IDF step.\nfunc (df domFrontier) build(u *BasicBlock) {\n\t// Encounter each node u in postorder of dom tree.\n\tfor _, child := range u.dom.children {\n\t\tdf.build(child)\n\t}\n\tfor _, vb := range u.Succs {\n\t\tif v := vb.dom; v.idom != u {\n\t\t\tdf.add(u, vb)\n\t\t}\n\t}\n\tfor _, w := range u.dom.children {\n\t\tfor _, vb := range df[w.Index] {\n\t\t\t// TODO(adonovan): opt: use word-parallel bitwise union.\n\t\t\tif v := vb.dom; v.idom != u {\n\t\t\t\tdf.add(u, vb)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc buildDomFrontier(fn *Function) domFrontier {\n\tdf := make(domFrontier, len(fn.Blocks))\n\tdf.build(fn.Blocks[0])\n\tif fn.Recover != nil {\n\t\tdf.build(fn.Recover)\n\t}\n\treturn df\n}\n\nfunc removeInstr(refs []Instruction, instr Instruction) []Instruction {\n\treturn slices.DeleteFunc(refs, func(i Instruction) bool { return i == instr })\n}\n\n// lift replaces local and new Allocs accessed only with\n// load/store by SSA registers, inserting φ-nodes where necessary.\n// The result is a program in classical pruned SSA form.\n//\n// Preconditions:\n// - fn has no dead blocks (blockopt has run).\n// - Def/use info (Operands and Referrers) is up-to-date.\n// - The dominator tree is up-to-date.\nfunc lift(fn *Function) {\n\t// TODO(adonovan): opt: lots of little optimizations may be\n\t// worthwhile here, especially if they cause us to avoid\n\t// buildDomFrontier.  For example:\n\t//\n\t// - Alloc never loaded?  Eliminate.\n\t// - Alloc never stored?  Replace all loads with a zero constant.\n\t// - Alloc stored once?  Replace loads with dominating store;\n\t//   don't forget that an Alloc is itself an effective store\n\t//   of zero.\n\t// - Alloc used only within a single block?\n\t//   Use degenerate algorithm avoiding φ-nodes.\n\t// - Consider synergy with scalar replacement of aggregates (SRA).\n\t//   e.g. *(&x.f) where x is an Alloc.\n\t//   Perhaps we'd get better results if we generated this as x.f\n\t//   i.e. Field(x, .f) instead of Load(FieldIndex(x, .f)).\n\t//   Unclear.\n\t//\n\t// But we will start with the simplest correct code.\n\tdf := buildDomFrontier(fn)\n\n\tif debugLifting {\n\t\ttitle := false\n\t\tfor i, blocks := range df {\n\t\t\tif blocks != nil {\n\t\t\t\tif !title {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"Dominance frontier of %s:\\n\", fn)\n\t\t\t\t\ttitle = true\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(os.Stderr, \"\\t%s: %s\\n\", fn.Blocks[i], blocks)\n\t\t\t}\n\t\t}\n\t}\n\n\tnewPhis := make(newPhiMap)\n\n\t// During this pass we will replace some BasicBlock.Instrs\n\t// (allocs, loads and stores) with nil, keeping a count in\n\t// BasicBlock.gaps.  At the end we will reset Instrs to the\n\t// concatenation of all non-dead newPhis and non-nil Instrs\n\t// for the block, reusing the original array if space permits.\n\n\t// While we're here, we also eliminate 'rundefers'\n\t// instructions and ssa:deferstack() in functions that contain no\n\t// 'defer' instructions. For now, we also eliminate\n\t// 's = ssa:deferstack()' calls if s doesn't escape, replacing s\n\t// with nil in Defer{DeferStack: s}. This has the same meaning,\n\t// but allows eliminating the intrinsic function `ssa:deferstack()`\n\t// (unless it is needed due to range-over-func instances). This gives\n\t// ssa users more time to support range-over-func.\n\tusesDefer := false\n\tdeferstackAlloc, deferstackCall := deferstackPreamble(fn)\n\teliminateDeferStack := deferstackAlloc != nil && !deferstackAlloc.Heap\n\n\t// A counter used to generate ~unique ids for Phi nodes, as an\n\t// aid to debugging.  We use large numbers to make them highly\n\t// visible.  All nodes are renumbered later.\n\tfresh := 1000\n\n\t// Determine which allocs we can lift and number them densely.\n\t// The renaming phase uses this numbering for compact maps.\n\tnumAllocs := 0\n\tfor _, b := range fn.Blocks {\n\t\tb.gaps = 0\n\t\tb.rundefers = 0\n\t\tfor _, instr := range b.Instrs {\n\t\t\tswitch instr := instr.(type) {\n\t\t\tcase *Alloc:\n\t\t\t\tindex := -1\n\t\t\t\tif liftAlloc(df, instr, newPhis, &fresh) {\n\t\t\t\t\tindex = numAllocs\n\t\t\t\t\tnumAllocs++\n\t\t\t\t}\n\t\t\t\tinstr.index = index\n\t\t\tcase *Defer:\n\t\t\t\tusesDefer = true\n\t\t\t\tif eliminateDeferStack {\n\t\t\t\t\t// Clear DeferStack and remove references to loads\n\t\t\t\t\tif instr.DeferStack != nil {\n\t\t\t\t\t\tif refs := instr.DeferStack.Referrers(); refs != nil {\n\t\t\t\t\t\t\t*refs = removeInstr(*refs, instr)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinstr.DeferStack = nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *RunDefers:\n\t\t\t\tb.rundefers++\n\t\t\t}\n\t\t}\n\t}\n\n\t// renaming maps an alloc (keyed by index) to its replacement\n\t// value.  Initially the renaming contains nil, signifying the\n\t// zero constant of the appropriate type; we construct the\n\t// Const lazily at most once on each path through the domtree.\n\t// TODO(adonovan): opt: cache per-function not per subtree.\n\trenaming := make([]Value, numAllocs)\n\n\t// Renaming.\n\trename(fn.Blocks[0], renaming, newPhis)\n\n\t// Eliminate dead φ-nodes.\n\tremoveDeadPhis(fn.Blocks, newPhis)\n\n\t// Eliminate ssa:deferstack() call.\n\tif eliminateDeferStack {\n\t\tb := deferstackCall.block\n\t\tfor i, instr := range b.Instrs {\n\t\t\tif instr == deferstackCall {\n\t\t\t\tb.Instrs[i] = nil\n\t\t\t\tb.gaps++\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Prepend remaining live φ-nodes to each block.\n\tfor _, b := range fn.Blocks {\n\t\tnps := newPhis[b]\n\t\tj := len(nps)\n\n\t\trundefersToKill := b.rundefers\n\t\tif usesDefer {\n\t\t\trundefersToKill = 0\n\t\t}\n\n\t\tif j+b.gaps+rundefersToKill == 0 {\n\t\t\tcontinue // fast path: no new phis or gaps\n\t\t}\n\n\t\t// Compact nps + non-nil Instrs into a new slice.\n\t\t// TODO(adonovan): opt: compact in situ (rightwards)\n\t\t// if Instrs has sufficient space or slack.\n\t\tdst := make([]Instruction, len(b.Instrs)+j-b.gaps-rundefersToKill)\n\t\tfor i, np := range nps {\n\t\t\tdst[i] = np.phi\n\t\t}\n\t\tfor _, instr := range b.Instrs {\n\t\t\tif instr == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !usesDefer {\n\t\t\t\tif _, ok := instr.(*RunDefers); ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tdst[j] = instr\n\t\t\tj++\n\t\t}\n\t\tb.Instrs = dst\n\t}\n\n\t// Remove any fn.Locals that were lifted.\n\tj := 0\n\tfor _, l := range fn.Locals {\n\t\tif l.index < 0 {\n\t\t\tfn.Locals[j] = l\n\t\t\tj++\n\t\t}\n\t}\n\t// Nil out fn.Locals[j:] to aid GC.\n\tfor i := j; i < len(fn.Locals); i++ {\n\t\tfn.Locals[i] = nil\n\t}\n\tfn.Locals = fn.Locals[:j]\n}\n\n// removeDeadPhis removes φ-nodes not transitively needed by a\n// non-Phi, non-DebugRef instruction.\nfunc removeDeadPhis(blocks []*BasicBlock, newPhis newPhiMap) {\n\t// First pass: find the set of \"live\" φ-nodes: those reachable\n\t// from some non-Phi instruction.\n\t//\n\t// We compute reachability in reverse, starting from each φ,\n\t// rather than forwards, starting from each live non-Phi\n\t// instruction, because this way visits much less of the\n\t// Value graph.\n\tlivePhis := make(map[*Phi]bool)\n\tfor _, npList := range newPhis {\n\t\tfor _, np := range npList {\n\t\t\tphi := np.phi\n\t\t\tif !livePhis[phi] && phiHasDirectReferrer(phi) {\n\t\t\t\tmarkLivePhi(livePhis, phi)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Existing φ-nodes due to && and || operators\n\t// are all considered live (see Go issue 19622).\n\tfor _, b := range blocks {\n\t\tfor _, phi := range b.phis() {\n\t\t\tmarkLivePhi(livePhis, phi.(*Phi))\n\t\t}\n\t}\n\n\t// Second pass: eliminate unused phis from newPhis.\n\tfor block, npList := range newPhis {\n\t\tj := 0\n\t\tfor _, np := range npList {\n\t\t\tif livePhis[np.phi] {\n\t\t\t\tnpList[j] = np\n\t\t\t\tj++\n\t\t\t} else {\n\t\t\t\t// discard it, first removing it from referrers\n\t\t\t\tfor _, val := range np.phi.Edges {\n\t\t\t\t\tif refs := val.Referrers(); refs != nil {\n\t\t\t\t\t\t*refs = removeInstr(*refs, np.phi)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnp.phi.block = nil\n\t\t\t}\n\t\t}\n\t\tnewPhis[block] = npList[:j]\n\t}\n}\n\n// markLivePhi marks phi, and all φ-nodes transitively reachable via\n// its Operands, live.\nfunc markLivePhi(livePhis map[*Phi]bool, phi *Phi) {\n\tlivePhis[phi] = true\n\tfor _, rand := range phi.Operands(nil) {\n\t\tif q, ok := (*rand).(*Phi); ok {\n\t\t\tif !livePhis[q] {\n\t\t\t\tmarkLivePhi(livePhis, q)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// phiHasDirectReferrer reports whether phi is directly referred to by\n// a non-Phi instruction.  Such instructions are the\n// roots of the liveness traversal.\nfunc phiHasDirectReferrer(phi *Phi) bool {\n\tfor _, instr := range *phi.Referrers() {\n\t\tif _, ok := instr.(*Phi); !ok {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\ntype blockSet struct{ big.Int } // (inherit methods from Int)\n\n// add adds b to the set and returns true if the set changed.\nfunc (s *blockSet) add(b *BasicBlock) bool {\n\ti := b.Index\n\tif s.Bit(i) != 0 {\n\t\treturn false\n\t}\n\ts.SetBit(&s.Int, i, 1)\n\treturn true\n}\n\n// take removes an arbitrary element from a set s and\n// returns its index, or returns -1 if empty.\nfunc (s *blockSet) take() int {\n\tl := s.BitLen()\n\tfor i := range l {\n\t\tif s.Bit(i) == 1 {\n\t\t\ts.SetBit(&s.Int, i, 0)\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// newPhi is a pair of a newly introduced φ-node and the lifted Alloc\n// it replaces.\ntype newPhi struct {\n\tphi   *Phi\n\talloc *Alloc\n}\n\n// newPhiMap records for each basic block, the set of newPhis that\n// must be prepended to the block.\ntype newPhiMap map[*BasicBlock][]newPhi\n\n// liftAlloc determines whether alloc can be lifted into registers,\n// and if so, it populates newPhis with all the φ-nodes it may require\n// and returns true.\n//\n// fresh is a source of fresh ids for phi nodes.\nfunc liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool {\n\t// Don't lift result values in functions that defer\n\t// calls that may recover from panic.\n\tif fn := alloc.Parent(); fn.Recover != nil {\n\t\tif slices.Contains(fn.results, alloc) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Compute defblocks, the set of blocks containing a\n\t// definition of the alloc cell.\n\tvar defblocks blockSet\n\tfor _, instr := range *alloc.Referrers() {\n\t\t// Bail out if we discover the alloc is not liftable;\n\t\t// the only operations permitted to use the alloc are\n\t\t// loads/stores into the cell, and DebugRef.\n\t\tswitch instr := instr.(type) {\n\t\tcase *Store:\n\t\t\tif instr.Val == alloc {\n\t\t\t\treturn false // address used as value\n\t\t\t}\n\t\t\tif instr.Addr != alloc {\n\t\t\t\tpanic(\"Alloc.Referrers is inconsistent\")\n\t\t\t}\n\t\t\tdefblocks.add(instr.Block())\n\t\tcase *UnOp:\n\t\t\tif instr.Op != token.MUL {\n\t\t\t\treturn false // not a load\n\t\t\t}\n\t\t\tif instr.X != alloc {\n\t\t\t\tpanic(\"Alloc.Referrers is inconsistent\")\n\t\t\t}\n\t\tcase *DebugRef:\n\t\t\t// ok\n\t\tdefault:\n\t\t\treturn false // some other instruction\n\t\t}\n\t}\n\t// The Alloc itself counts as a (zero) definition of the cell.\n\tdefblocks.add(alloc.Block())\n\n\tif debugLifting {\n\t\tfmt.Fprintln(os.Stderr, \"\\tlifting \", alloc, alloc.Name())\n\t}\n\n\tfn := alloc.Parent()\n\n\t// Φ-insertion.\n\t//\n\t// What follows is the body of the main loop of the insert-φ\n\t// function described by Cytron et al, but instead of using\n\t// counter tricks, we just reset the 'hasAlready' and 'work'\n\t// sets each iteration.  These are bitmaps so it's pretty cheap.\n\t//\n\t// TODO(adonovan): opt: recycle slice storage for W,\n\t// hasAlready, defBlocks across liftAlloc calls.\n\tvar hasAlready blockSet\n\n\t// Initialize W and work to defblocks.\n\tvar work blockSet = defblocks // blocks seen\n\tvar W blockSet                // blocks to do\n\tW.Set(&defblocks.Int)\n\n\t// Traverse iterated dominance frontier, inserting φ-nodes.\n\tfor i := W.take(); i != -1; i = W.take() {\n\t\tu := fn.Blocks[i]\n\t\tfor _, v := range df[u.Index] {\n\t\t\tif hasAlready.add(v) {\n\t\t\t\t// Create φ-node.\n\t\t\t\t// It will be prepended to v.Instrs later, if needed.\n\t\t\t\tphi := &Phi{\n\t\t\t\t\tEdges:   make([]Value, len(v.Preds)),\n\t\t\t\t\tComment: alloc.Comment,\n\t\t\t\t}\n\t\t\t\t// This is merely a debugging aid:\n\t\t\t\tphi.setNum(*fresh)\n\t\t\t\t*fresh++\n\n\t\t\t\tphi.pos = alloc.Pos()\n\t\t\t\tphi.setType(typeparams.MustDeref(alloc.Type()))\n\t\t\t\tphi.block = v\n\t\t\t\tif debugLifting {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"\\tplace %s = %s at block %s\\n\", phi.Name(), phi, v)\n\t\t\t\t}\n\t\t\t\tnewPhis[v] = append(newPhis[v], newPhi{phi, alloc})\n\n\t\t\t\tif work.add(v) {\n\t\t\t\t\tW.add(v)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true\n}\n\n// replaceAll replaces all intraprocedural uses of x with y,\n// updating x.Referrers and y.Referrers.\n// Precondition: x.Referrers() != nil, i.e. x must be local to some function.\nfunc replaceAll(x, y Value) {\n\tvar rands []*Value\n\tpxrefs := x.Referrers()\n\tpyrefs := y.Referrers()\n\tfor _, instr := range *pxrefs {\n\t\trands = instr.Operands(rands[:0]) // recycle storage\n\t\tfor _, rand := range rands {\n\t\t\tif *rand != nil {\n\t\t\t\tif *rand == x {\n\t\t\t\t\t*rand = y\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif pyrefs != nil {\n\t\t\t*pyrefs = append(*pyrefs, instr) // dups ok\n\t\t}\n\t}\n\t*pxrefs = nil // x is now unreferenced\n}\n\n// renamed returns the value to which alloc is being renamed,\n// constructing it lazily if it's the implicit zero initialization.\nfunc renamed(renaming []Value, alloc *Alloc) Value {\n\tv := renaming[alloc.index]\n\tif v == nil {\n\t\tv = zeroConst(typeparams.MustDeref(alloc.Type()))\n\t\trenaming[alloc.index] = v\n\t}\n\treturn v\n}\n\n// rename implements the (Cytron et al) SSA renaming algorithm, a\n// preorder traversal of the dominator tree replacing all loads of\n// Alloc cells with the value stored to that cell by the dominating\n// store instruction.  For lifting, we need only consider loads,\n// stores and φ-nodes.\n//\n// renaming is a map from *Alloc (keyed by index number) to its\n// dominating stored value; newPhis[x] is the set of new φ-nodes to be\n// prepended to block x.\nfunc rename(u *BasicBlock, renaming []Value, newPhis newPhiMap) {\n\t// Each φ-node becomes the new name for its associated Alloc.\n\tfor _, np := range newPhis[u] {\n\t\tphi := np.phi\n\t\talloc := np.alloc\n\t\trenaming[alloc.index] = phi\n\t}\n\n\t// Rename loads and stores of allocs.\n\tfor i, instr := range u.Instrs {\n\t\tswitch instr := instr.(type) {\n\t\tcase *Alloc:\n\t\t\tif instr.index >= 0 { // store of zero to Alloc cell\n\t\t\t\t// Replace dominated loads by the zero value.\n\t\t\t\trenaming[instr.index] = nil\n\t\t\t\tif debugLifting {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"\\tkill alloc %s\\n\", instr)\n\t\t\t\t}\n\t\t\t\t// Delete the Alloc.\n\t\t\t\tu.Instrs[i] = nil\n\t\t\t\tu.gaps++\n\t\t\t}\n\n\t\tcase *Store:\n\t\t\tif alloc, ok := instr.Addr.(*Alloc); ok && alloc.index >= 0 { // store to Alloc cell\n\t\t\t\t// Replace dominated loads by the stored value.\n\t\t\t\trenaming[alloc.index] = instr.Val\n\t\t\t\tif debugLifting {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"\\tkill store %s; new value: %s\\n\",\n\t\t\t\t\t\tinstr, instr.Val.Name())\n\t\t\t\t}\n\t\t\t\t// Remove the store from the referrer list of the stored value.\n\t\t\t\tif refs := instr.Val.Referrers(); refs != nil {\n\t\t\t\t\t*refs = removeInstr(*refs, instr)\n\t\t\t\t}\n\t\t\t\t// Delete the Store.\n\t\t\t\tu.Instrs[i] = nil\n\t\t\t\tu.gaps++\n\t\t\t}\n\n\t\tcase *UnOp:\n\t\t\tif instr.Op == token.MUL {\n\t\t\t\tif alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // load of Alloc cell\n\t\t\t\t\tnewval := renamed(renaming, alloc)\n\t\t\t\t\tif debugLifting {\n\t\t\t\t\t\tfmt.Fprintf(os.Stderr, \"\\tupdate load %s = %s with %s\\n\",\n\t\t\t\t\t\t\tinstr.Name(), instr, newval.Name())\n\t\t\t\t\t}\n\t\t\t\t\t// Replace all references to\n\t\t\t\t\t// the loaded value by the\n\t\t\t\t\t// dominating stored value.\n\t\t\t\t\treplaceAll(instr, newval)\n\t\t\t\t\t// Delete the Load.\n\t\t\t\t\tu.Instrs[i] = nil\n\t\t\t\t\tu.gaps++\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *DebugRef:\n\t\t\tif alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // ref of Alloc cell\n\t\t\t\tif instr.IsAddr {\n\t\t\t\t\tinstr.X = renamed(renaming, alloc)\n\t\t\t\t\tinstr.IsAddr = false\n\n\t\t\t\t\t// Add DebugRef to instr.X's referrers.\n\t\t\t\t\tif refs := instr.X.Referrers(); refs != nil {\n\t\t\t\t\t\t*refs = append(*refs, instr)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// A source expression denotes the address\n\t\t\t\t\t// of an Alloc that was optimized away.\n\t\t\t\t\tinstr.X = nil\n\n\t\t\t\t\t// Delete the DebugRef.\n\t\t\t\t\tu.Instrs[i] = nil\n\t\t\t\t\tu.gaps++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// For each φ-node in a CFG successor, rename the edge.\n\tfor _, v := range u.Succs {\n\t\tphis := newPhis[v]\n\t\tif len(phis) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\ti := v.predIndex(u)\n\t\tfor _, np := range phis {\n\t\t\tphi := np.phi\n\t\t\talloc := np.alloc\n\t\t\tnewval := renamed(renaming, alloc)\n\t\t\tif debugLifting {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"\\tsetphi %s edge %s -> %s (#%d) (alloc=%s) := %s\\n\",\n\t\t\t\t\tphi.Name(), u, v, i, alloc.Name(), newval.Name())\n\t\t\t}\n\t\t\tphi.Edges[i] = newval\n\t\t\tif prefs := newval.Referrers(); prefs != nil {\n\t\t\t\t*prefs = append(*prefs, phi)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Continue depth-first recursion over domtree, pushing a\n\t// fresh copy of the renaming map for each subtree.\n\tfor i, v := range u.dom.children {\n\t\tr := renaming\n\t\tif i < len(u.dom.children)-1 {\n\t\t\t// On all but the final iteration, we must make\n\t\t\t// a copy to avoid destructive update.\n\t\t\tr = make([]Value, len(renaming))\n\t\t\tcopy(r, renaming)\n\t\t}\n\t\trename(v, r, newPhis)\n\t}\n\n}\n\n// deferstackPreamble returns the *Alloc and ssa:deferstack() call for fn.deferstack.\nfunc deferstackPreamble(fn *Function) (*Alloc, *Call) {\n\tif alloc, _ := fn.vars[fn.deferstack].(*Alloc); alloc != nil {\n\t\tfor _, ref := range *alloc.Referrers() {\n\t\t\tif ref, _ := ref.(*Store); ref != nil && ref.Addr == alloc {\n\t\t\t\tif call, _ := ref.Val.(*Call); call != nil {\n\t\t\t\t\treturn alloc, call\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "go/ssa/lvalue.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// lvalues are the union of addressable expressions and map-index\n// expressions.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// An lvalue represents an assignable location that may appear on the\n// left-hand side of an assignment.  This is a generalization of a\n// pointer to permit updates to elements of maps.\ntype lvalue interface {\n\tstore(fn *Function, v Value) // stores v into the location\n\tload(fn *Function) Value     // loads the contents of the location\n\taddress(fn *Function) Value  // address of the location\n\ttyp() types.Type             // returns the type of the location\n}\n\n// An address is an lvalue represented by a true pointer.\ntype address struct {\n\taddr Value     // must have a pointer core type.\n\tpos  token.Pos // source position\n\texpr ast.Expr  // source syntax of the value (not address) [debug mode]\n}\n\nfunc (a *address) load(fn *Function) Value {\n\tload := emitLoad(fn, a.addr)\n\tload.pos = a.pos\n\treturn load\n}\n\nfunc (a *address) store(fn *Function, v Value) {\n\tstore := emitStore(fn, a.addr, v, a.pos)\n\tif a.expr != nil {\n\t\t// store.Val is v, converted for assignability.\n\t\temitDebugRef(fn, a.expr, store.Val, false)\n\t}\n}\n\nfunc (a *address) address(fn *Function) Value {\n\tif a.expr != nil {\n\t\temitDebugRef(fn, a.expr, a.addr, true)\n\t}\n\treturn a.addr\n}\n\nfunc (a *address) typ() types.Type {\n\treturn typeparams.MustDeref(a.addr.Type())\n}\n\n// An element is an lvalue represented by m[k], the location of an\n// element of a map.  These locations are not addressable\n// since pointers cannot be formed from them, but they do support\n// load() and store().\ntype element struct {\n\tm, k Value      // map\n\tt    types.Type // map element type\n\tpos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)\n}\n\nfunc (e *element) load(fn *Function) Value {\n\tl := &Lookup{\n\t\tX:     e.m,\n\t\tIndex: e.k,\n\t}\n\tl.setPos(e.pos)\n\tl.setType(e.t)\n\treturn fn.emit(l)\n}\n\nfunc (e *element) store(fn *Function, v Value) {\n\tup := &MapUpdate{\n\t\tMap:   e.m,\n\t\tKey:   e.k,\n\t\tValue: emitConv(fn, v, e.t),\n\t}\n\tup.pos = e.pos\n\tfn.emit(up)\n}\n\nfunc (e *element) address(fn *Function) Value {\n\tpanic(\"map elements are not addressable\")\n}\n\nfunc (e *element) typ() types.Type {\n\treturn e.t\n}\n\n// A lazyAddress is an lvalue whose address is the result of an instruction.\n// These work like an *address except a new address.address() Value\n// is created on each load, store and address call.\n// A lazyAddress can be used to control when a side effect (nil pointer\n// dereference, index out of bounds) of using a location happens.\ntype lazyAddress struct {\n\taddr func(fn *Function) Value // emit to fn the computation of the address\n\tt    types.Type               // type of the location\n\tpos  token.Pos                // source position\n\texpr ast.Expr                 // source syntax of the value (not address) [debug mode]\n}\n\nfunc (l *lazyAddress) load(fn *Function) Value {\n\tload := emitLoad(fn, l.addr(fn))\n\tload.pos = l.pos\n\treturn load\n}\n\nfunc (l *lazyAddress) store(fn *Function, v Value) {\n\tstore := emitStore(fn, l.addr(fn), v, l.pos)\n\tif l.expr != nil {\n\t\t// store.Val is v, converted for assignability.\n\t\temitDebugRef(fn, l.expr, store.Val, false)\n\t}\n}\n\nfunc (l *lazyAddress) address(fn *Function) Value {\n\taddr := l.addr(fn)\n\tif l.expr != nil {\n\t\temitDebugRef(fn, l.expr, addr, true)\n\t}\n\treturn addr\n}\n\nfunc (l *lazyAddress) typ() types.Type { return l.t }\n\n// A blank is a dummy variable whose name is \"_\".\n// It is not reified: loads are illegal and stores are ignored.\ntype blank struct{}\n\nfunc (bl blank) load(fn *Function) Value {\n\tpanic(\"blank.load is illegal\")\n}\n\nfunc (bl blank) store(fn *Function, v Value) {\n\t// no-op\n}\n\nfunc (bl blank) address(fn *Function) Value {\n\tpanic(\"blank var is not addressable\")\n}\n\nfunc (bl blank) typ() types.Type {\n\t// This should be the type of the blank Ident; the typechecker\n\t// doesn't provide this yet, but fortunately, we don't need it\n\t// yet either.\n\tpanic(\"blank.typ is unimplemented\")\n}\n"
  },
  {
    "path": "go/ssa/methods.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines utilities for population of method sets.\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// MethodValue returns the Function implementing method sel, building\n// wrapper methods on demand. It returns nil if sel denotes an\n// interface or generic method.\n//\n// Precondition: sel.Kind() == MethodVal.\n//\n// Thread-safe.\n//\n// Acquires prog.methodsMu.\nfunc (prog *Program) MethodValue(sel *types.Selection) *Function {\n\tif sel.Kind() != types.MethodVal {\n\t\tpanic(fmt.Sprintf(\"MethodValue(%s) kind != MethodVal\", sel))\n\t}\n\tT := sel.Recv()\n\tif types.IsInterface(T) {\n\t\treturn nil // interface method or type parameter\n\t}\n\n\tif prog.isParameterized(T) {\n\t\treturn nil // generic method\n\t}\n\n\tif prog.mode&LogSource != 0 {\n\t\tdefer logStack(\"MethodValue %s %v\", T, sel)()\n\t}\n\n\tvar b builder\n\n\tm := func() *Function {\n\t\tprog.methodsMu.Lock()\n\t\tdefer prog.methodsMu.Unlock()\n\n\t\t// Get or create SSA method set.\n\t\tmset, ok := prog.methodSets.At(T).(*methodSet)\n\t\tif !ok {\n\t\t\tmset = &methodSet{mapping: make(map[string]*Function)}\n\t\t\tprog.methodSets.Set(T, mset)\n\t\t}\n\n\t\t// Get or create SSA method.\n\t\tid := sel.Obj().Id()\n\t\tfn, ok := mset.mapping[id]\n\t\tif !ok {\n\t\t\tobj := sel.Obj().(*types.Func)\n\t\t\tneedsPromotion := len(sel.Index()) > 1\n\t\t\tneedsIndirection := !isPointer(recvType(obj)) && isPointer(T)\n\t\t\tif needsPromotion || needsIndirection {\n\t\t\t\tfn = createWrapper(prog, toSelection(sel))\n\t\t\t\tfn.buildshared = b.shared()\n\t\t\t\tb.enqueue(fn)\n\t\t\t} else {\n\t\t\t\tfn = prog.objectMethod(obj, &b)\n\t\t\t}\n\t\t\tif fn.Signature.Recv() == nil {\n\t\t\t\tpanic(fn)\n\t\t\t}\n\t\t\tmset.mapping[id] = fn\n\t\t} else {\n\t\t\tb.waitForSharedFunction(fn)\n\t\t}\n\n\t\treturn fn\n\t}()\n\n\tb.iterate()\n\n\treturn m\n}\n\n// objectMethod returns the Function for a given method symbol.\n// The symbol may be an instance of a generic function. It need not\n// belong to an existing SSA package created by a call to\n// prog.CreatePackage.\n//\n// objectMethod panics if the function is not a method.\n//\n// Acquires prog.objectMethodsMu.\nfunc (prog *Program) objectMethod(obj *types.Func, b *builder) *Function {\n\tsig := obj.Type().(*types.Signature)\n\tif sig.Recv() == nil {\n\t\tpanic(\"not a method: \" + obj.String())\n\t}\n\n\t// Belongs to a created package?\n\tif fn := prog.FuncValue(obj); fn != nil {\n\t\treturn fn\n\t}\n\n\t// Instantiation of generic?\n\tif originObj := obj.Origin(); originObj != obj {\n\t\torigin := prog.objectMethod(originObj, b)\n\t\tassert(origin.typeparams.Len() > 0, \"origin is not generic\")\n\t\ttargs := receiverTypeArgs(obj)\n\t\treturn origin.instance(targs, b)\n\t}\n\n\t// Consult/update cache of methods created from types.Func.\n\tprog.objectMethodsMu.Lock()\n\tdefer prog.objectMethodsMu.Unlock()\n\tfn, ok := prog.objectMethods[obj]\n\tif !ok {\n\t\tfn = createFunction(prog, obj, obj.Name(), nil, nil, \"\")\n\t\tfn.Synthetic = \"from type information (on demand)\"\n\t\tfn.buildshared = b.shared()\n\t\tb.enqueue(fn)\n\n\t\tif prog.objectMethods == nil {\n\t\t\tprog.objectMethods = make(map[*types.Func]*Function)\n\t\t}\n\t\tprog.objectMethods[obj] = fn\n\t} else {\n\t\tb.waitForSharedFunction(fn)\n\t}\n\treturn fn\n}\n\n// LookupMethod returns the implementation of the method of type T\n// identified by (pkg, name).  It returns nil if the method exists but\n// is an interface method or generic method, and panics if T has no such method.\nfunc (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {\n\tsel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)\n\tif sel == nil {\n\t\tpanic(fmt.Sprintf(\"%s has no method %s\", T, types.Id(pkg, name)))\n\t}\n\treturn prog.MethodValue(sel)\n}\n\n// methodSet contains the (concrete) methods of a concrete type (non-interface, non-parameterized).\ntype methodSet struct {\n\tmapping map[string]*Function // populated lazily\n}\n\n// RuntimeTypes returns a new unordered slice containing all types in\n// the program for which a runtime type is required.\n//\n// A runtime type is required for any non-parameterized, non-interface\n// type that is converted to an interface, or for any type (including\n// interface types) derivable from one through reflection.\n//\n// The methods of such types may be reachable through reflection or\n// interface calls even if they are never called directly.\n//\n// Thread-safe.\n//\n// Acquires prog.makeInterfaceTypesMu.\nfunc (prog *Program) RuntimeTypes() []types.Type {\n\tprog.makeInterfaceTypesMu.Lock()\n\tdefer prog.makeInterfaceTypesMu.Unlock()\n\n\t// Compute the derived types on demand, since many SSA clients\n\t// never call RuntimeTypes, and those that do typically call\n\t// it once (often within ssautil.AllFunctions, which will\n\t// eventually not use it; see Go issue #69291.) This\n\t// eliminates the need to eagerly compute all the element\n\t// types during SSA building.\n\tvar runtimeTypes []types.Type\n\tadd := func(t types.Type) { runtimeTypes = append(runtimeTypes, t) }\n\tvar set typeutil.Map // for de-duping identical types\n\tfor t := range prog.makeInterfaceTypes {\n\t\ttypesinternal.ForEachElement(&set, &prog.MethodSets, t, add)\n\t}\n\n\treturn runtimeTypes\n}\n"
  },
  {
    "path": "go/ssa/methods_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n)\n\n// Tests that MethodValue returns the expected method.\nfunc TestMethodValue(t *testing.T) {\n\tinput := `\npackage p\n\ntype I interface{ M() }\n\ntype S int\nfunc (S) M() {}\ntype R[T any] struct{ S }\n\nvar i I\nvar s S\nvar r R[string]\n\nfunc selections[T any]() {\n\t_ = i.M\n\t_ = s.M\n\t_ = r.M\n\n\tvar v R[T]\n\t_ = v.M\n}\n`\n\n\t// Parse the file.\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"input.go\", input, 0)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\n\t// Build an SSA program from the parsed file.\n\tp, info, err := ssautil.BuildPackage(&types.Config{}, fset,\n\t\ttypes.NewPackage(\"p\", \"\"), []*ast.File{f}, ssa.SanityCheckFunctions)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\n\t// Collect all of the *types.Selection in the function \"selections\".\n\tvar selections []*types.Selection\n\tfor _, decl := range f.Decls {\n\t\tif fn, ok := decl.(*ast.FuncDecl); ok && fn.Name.Name == \"selections\" {\n\t\t\tfor _, stmt := range fn.Body.List {\n\t\t\t\tif assign, ok := stmt.(*ast.AssignStmt); ok {\n\t\t\t\t\tsel := assign.Rhs[0].(*ast.SelectorExpr)\n\t\t\t\t\tselections = append(selections, info.Selections[sel])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\twants := map[string]string{\n\t\t\"method (p.S) M()\":         \"(p.S).M\",\n\t\t\"method (p.R[string]) M()\": \"(p.R[string]).M\",\n\t\t\"method (p.I) M()\":         \"nil\", // interface\n\t\t\"method (p.R[T]) M()\":      \"nil\", // parameterized\n\t}\n\tif len(wants) != len(selections) {\n\t\tt.Fatalf(\"Wanted %d selections. got %d\", len(wants), len(selections))\n\t}\n\tfor _, selection := range selections {\n\t\tvar got string\n\t\tif m := p.Prog.MethodValue(selection); m != nil {\n\t\t\tgot = m.String()\n\t\t} else {\n\t\t\tgot = \"nil\"\n\t\t}\n\t\tif want := wants[selection.String()]; want != got {\n\t\t\tt.Errorf(\"p.Prog.MethodValue(%s) expected %q. got %q\", selection, want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/mode.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines the BuilderMode type and its command-line flag.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// BuilderMode is a bitmask of options for diagnostics and checking.\n//\n// *BuilderMode satisfies the flag.Value interface.  Example:\n//\n//\tvar mode = ssa.BuilderMode(0)\n//\tfunc init() { flag.Var(&mode, \"build\", ssa.BuilderModeDoc) }\ntype BuilderMode uint\n\nconst (\n\tPrintPackages        BuilderMode = 1 << iota // Print package inventory to stdout\n\tPrintFunctions                               // Print function SSA code to stdout\n\tLogSource                                    // Log source locations as SSA builder progresses\n\tSanityCheckFunctions                         // Perform sanity checking of function bodies\n\tNaiveForm                                    // Build naïve SSA form: don't replace local loads/stores with registers\n\tBuildSerially                                // Build packages serially, not in parallel.\n\tGlobalDebug                                  // Enable debug info for all packages\n\tBareInits                                    // Build init functions without guards or calls to dependent inits\n\tInstantiateGenerics                          // Instantiate generics functions (monomorphize) while building\n)\n\nconst BuilderModeDoc = `Options controlling the SSA builder.\nThe value is a sequence of zero or more of these letters:\nC\tperform sanity [C]hecking of the SSA form.\nD\tinclude [D]ebug info for every function.\nP\tprint [P]ackage inventory.\nF\tprint [F]unction SSA code.\nS\tlog [S]ource locations as SSA builder progresses.\nL\tbuild distinct packages seria[L]ly instead of in parallel.\nN\tbuild [N]aive SSA form: don't replace local loads/stores with registers.\nI\tbuild bare [I]nit functions: no init guards or calls to dependent inits.\nG   instantiate [G]eneric function bodies via monomorphization\n`\n\nfunc (m BuilderMode) String() string {\n\tvar buf bytes.Buffer\n\tif m&GlobalDebug != 0 {\n\t\tbuf.WriteByte('D')\n\t}\n\tif m&PrintPackages != 0 {\n\t\tbuf.WriteByte('P')\n\t}\n\tif m&PrintFunctions != 0 {\n\t\tbuf.WriteByte('F')\n\t}\n\tif m&LogSource != 0 {\n\t\tbuf.WriteByte('S')\n\t}\n\tif m&SanityCheckFunctions != 0 {\n\t\tbuf.WriteByte('C')\n\t}\n\tif m&NaiveForm != 0 {\n\t\tbuf.WriteByte('N')\n\t}\n\tif m&BuildSerially != 0 {\n\t\tbuf.WriteByte('L')\n\t}\n\tif m&BareInits != 0 {\n\t\tbuf.WriteByte('I')\n\t}\n\tif m&InstantiateGenerics != 0 {\n\t\tbuf.WriteByte('G')\n\t}\n\treturn buf.String()\n}\n\n// Set parses the flag characters in s and updates *m.\nfunc (m *BuilderMode) Set(s string) error {\n\tvar mode BuilderMode\n\tfor _, c := range s {\n\t\tswitch c {\n\t\tcase 'D':\n\t\t\tmode |= GlobalDebug\n\t\tcase 'P':\n\t\t\tmode |= PrintPackages\n\t\tcase 'F':\n\t\t\tmode |= PrintFunctions\n\t\tcase 'S':\n\t\t\tmode |= LogSource | BuildSerially\n\t\tcase 'C':\n\t\t\tmode |= SanityCheckFunctions\n\t\tcase 'N':\n\t\t\tmode |= NaiveForm\n\t\tcase 'L':\n\t\t\tmode |= BuildSerially\n\t\tcase 'I':\n\t\t\tmode |= BareInits\n\t\tcase 'G':\n\t\t\tmode |= InstantiateGenerics\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown BuilderMode option: %q\", c)\n\t\t}\n\t}\n\t*m = mode\n\treturn nil\n}\n\n// Get returns m.\nfunc (m BuilderMode) Get() any { return m }\n"
  },
  {
    "path": "go/ssa/print.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file implements the String() methods for all Value and\n// Instruction types.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"io\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// relName returns the name of v relative to i.\n// In most cases, this is identical to v.Name(), but references to\n// Functions (including methods) and Globals use RelString and\n// all types are displayed with relType, so that only cross-package\n// references are package-qualified.\nfunc relName(v Value, i Instruction) string {\n\tvar from *types.Package\n\tif i != nil {\n\t\tfrom = i.Parent().relPkg()\n\t}\n\tswitch v := v.(type) {\n\tcase Member: // *Function or *Global\n\t\treturn v.RelString(from)\n\tcase *Const:\n\t\treturn v.RelString(from)\n\t}\n\treturn v.Name()\n}\n\nfunc relType(t types.Type, from *types.Package) string {\n\treturn types.TypeString(t, types.RelativeTo(from))\n}\n\nfunc relTerm(term *types.Term, from *types.Package) string {\n\ts := relType(term.Type(), from)\n\tif term.Tilde() {\n\t\treturn \"~\" + s\n\t}\n\treturn s\n}\n\nfunc relString(m Member, from *types.Package) string {\n\t// NB: not all globals have an Object (e.g. init$guard),\n\t// so use Package().Object not Object.Package().\n\tif pkg := m.Package().Pkg; pkg != nil && pkg != from {\n\t\treturn fmt.Sprintf(\"%s.%s\", pkg.Path(), m.Name())\n\t}\n\treturn m.Name()\n}\n\n// Value.String()\n//\n// This method is provided only for debugging.\n// It never appears in disassembly, which uses Value.Name().\n\nfunc (v *Parameter) String() string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"parameter %s : %s\", v.Name(), relType(v.Type(), from))\n}\n\nfunc (v *FreeVar) String() string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"freevar %s : %s\", v.Name(), relType(v.Type(), from))\n}\n\nfunc (v *Builtin) String() string {\n\treturn fmt.Sprintf(\"builtin %s\", v.Name())\n}\n\n// Instruction.String()\n\nfunc (v *Alloc) String() string {\n\top := \"local\"\n\tif v.Heap {\n\t\top = \"new\"\n\t}\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"%s %s (%s)\", op, relType(typeparams.MustDeref(v.Type()), from), v.Comment)\n}\n\nfunc (v *Phi) String() string {\n\tvar b bytes.Buffer\n\tb.WriteString(\"phi [\")\n\tfor i, edge := range v.Edges {\n\t\tif i > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\t// Be robust against malformed CFG.\n\t\tif v.block == nil {\n\t\t\tb.WriteString(\"??\")\n\t\t\tcontinue\n\t\t}\n\t\tblock := -1\n\t\tif i < len(v.block.Preds) {\n\t\t\tblock = v.block.Preds[i].Index\n\t\t}\n\t\tfmt.Fprintf(&b, \"%d: \", block)\n\t\tedgeVal := \"<nil>\" // be robust\n\t\tif edge != nil {\n\t\t\tedgeVal = relName(edge, v)\n\t\t}\n\t\tb.WriteString(edgeVal)\n\t}\n\tb.WriteString(\"]\")\n\tif v.Comment != \"\" {\n\t\tb.WriteString(\" #\")\n\t\tb.WriteString(v.Comment)\n\t}\n\treturn b.String()\n}\n\nfunc printCall(v *CallCommon, prefix string, instr Instruction) string {\n\tvar b bytes.Buffer\n\tb.WriteString(prefix)\n\tif !v.IsInvoke() {\n\t\tb.WriteString(relName(v.Value, instr))\n\t} else {\n\t\tfmt.Fprintf(&b, \"invoke %s.%s\", relName(v.Value, instr), v.Method.Name())\n\t}\n\tb.WriteString(\"(\")\n\tfor i, arg := range v.Args {\n\t\tif i > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tb.WriteString(relName(arg, instr))\n\t}\n\tif v.Signature().Variadic() {\n\t\tb.WriteString(\"...\")\n\t}\n\tb.WriteString(\")\")\n\treturn b.String()\n}\n\nfunc (c *CallCommon) String() string {\n\treturn printCall(c, \"\", nil)\n}\n\nfunc (v *Call) String() string {\n\treturn printCall(&v.Call, \"\", v)\n}\n\nfunc (v *BinOp) String() string {\n\treturn fmt.Sprintf(\"%s %s %s\", relName(v.X, v), v.Op.String(), relName(v.Y, v))\n}\n\nfunc (v *UnOp) String() string {\n\treturn fmt.Sprintf(\"%s%s%s\", v.Op, relName(v.X, v), commaOk(v.CommaOk))\n}\n\nfunc printConv(prefix string, v, x Value) string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"%s %s <- %s (%s)\",\n\t\tprefix,\n\t\trelType(v.Type(), from),\n\t\trelType(x.Type(), from),\n\t\trelName(x, v.(Instruction)))\n}\n\nfunc (v *ChangeType) String() string          { return printConv(\"changetype\", v, v.X) }\nfunc (v *Convert) String() string             { return printConv(\"convert\", v, v.X) }\nfunc (v *ChangeInterface) String() string     { return printConv(\"change interface\", v, v.X) }\nfunc (v *SliceToArrayPointer) String() string { return printConv(\"slice to array pointer\", v, v.X) }\nfunc (v *MakeInterface) String() string       { return printConv(\"make\", v, v.X) }\n\nfunc (v *MultiConvert) String() string {\n\tfrom := v.Parent().relPkg()\n\n\tvar b strings.Builder\n\tb.WriteString(printConv(\"multiconvert\", v, v.X))\n\tb.WriteString(\" [\")\n\tfor i, s := range termListOf(v.from) {\n\t\tfor j, d := range termListOf(v.to) {\n\t\t\tif i != 0 || j != 0 {\n\t\t\t\tb.WriteString(\" | \")\n\t\t\t}\n\t\t\tfmt.Fprintf(&b, \"%s <- %s\", relTerm(d, from), relTerm(s, from))\n\t\t}\n\t}\n\tb.WriteString(\"]\")\n\treturn b.String()\n}\n\nfunc (v *MakeClosure) String() string {\n\tvar b bytes.Buffer\n\tfmt.Fprintf(&b, \"make closure %s\", relName(v.Fn, v))\n\tif v.Bindings != nil {\n\t\tb.WriteString(\" [\")\n\t\tfor i, c := range v.Bindings {\n\t\t\tif i > 0 {\n\t\t\t\tb.WriteString(\", \")\n\t\t\t}\n\t\t\tb.WriteString(relName(c, v))\n\t\t}\n\t\tb.WriteString(\"]\")\n\t}\n\treturn b.String()\n}\n\nfunc (v *MakeSlice) String() string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"make %s %s %s\",\n\t\trelType(v.Type(), from),\n\t\trelName(v.Len, v),\n\t\trelName(v.Cap, v))\n}\n\nfunc (v *Slice) String() string {\n\tvar b bytes.Buffer\n\tb.WriteString(\"slice \")\n\tb.WriteString(relName(v.X, v))\n\tb.WriteString(\"[\")\n\tif v.Low != nil {\n\t\tb.WriteString(relName(v.Low, v))\n\t}\n\tb.WriteString(\":\")\n\tif v.High != nil {\n\t\tb.WriteString(relName(v.High, v))\n\t}\n\tif v.Max != nil {\n\t\tb.WriteString(\":\")\n\t\tb.WriteString(relName(v.Max, v))\n\t}\n\tb.WriteString(\"]\")\n\treturn b.String()\n}\n\nfunc (v *MakeMap) String() string {\n\tres := \"\"\n\tif v.Reserve != nil {\n\t\tres = relName(v.Reserve, v)\n\t}\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"make %s %s\", relType(v.Type(), from), res)\n}\n\nfunc (v *MakeChan) String() string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"make %s %s\", relType(v.Type(), from), relName(v.Size, v))\n}\n\nfunc (v *FieldAddr) String() string {\n\t// Be robust against a bad index.\n\tname := \"?\"\n\tif fld := fieldOf(typeparams.MustDeref(v.X.Type()), v.Field); fld != nil {\n\t\tname = fld.Name()\n\t}\n\treturn fmt.Sprintf(\"&%s.%s [#%d]\", relName(v.X, v), name, v.Field)\n}\n\nfunc (v *Field) String() string {\n\t// Be robust against a bad index.\n\tname := \"?\"\n\tif fld := fieldOf(v.X.Type(), v.Field); fld != nil {\n\t\tname = fld.Name()\n\t}\n\treturn fmt.Sprintf(\"%s.%s [#%d]\", relName(v.X, v), name, v.Field)\n}\n\nfunc (v *IndexAddr) String() string {\n\treturn fmt.Sprintf(\"&%s[%s]\", relName(v.X, v), relName(v.Index, v))\n}\n\nfunc (v *Index) String() string {\n\treturn fmt.Sprintf(\"%s[%s]\", relName(v.X, v), relName(v.Index, v))\n}\n\nfunc (v *Lookup) String() string {\n\treturn fmt.Sprintf(\"%s[%s]%s\", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))\n}\n\nfunc (v *Range) String() string {\n\treturn \"range \" + relName(v.X, v)\n}\n\nfunc (v *Next) String() string {\n\treturn \"next \" + relName(v.Iter, v)\n}\n\nfunc (v *TypeAssert) String() string {\n\tfrom := v.Parent().relPkg()\n\treturn fmt.Sprintf(\"typeassert%s %s.(%s)\", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))\n}\n\nfunc (v *Extract) String() string {\n\treturn fmt.Sprintf(\"extract %s #%d\", relName(v.Tuple, v), v.Index)\n}\n\nfunc (s *Jump) String() string {\n\t// Be robust against malformed CFG.\n\tblock := -1\n\tif s.block != nil && len(s.block.Succs) == 1 {\n\t\tblock = s.block.Succs[0].Index\n\t}\n\treturn fmt.Sprintf(\"jump %d\", block)\n}\n\nfunc (s *If) String() string {\n\t// Be robust against malformed CFG.\n\ttblock, fblock := -1, -1\n\tif s.block != nil && len(s.block.Succs) == 2 {\n\t\ttblock = s.block.Succs[0].Index\n\t\tfblock = s.block.Succs[1].Index\n\t}\n\treturn fmt.Sprintf(\"if %s goto %d else %d\", relName(s.Cond, s), tblock, fblock)\n}\n\nfunc (s *Go) String() string {\n\treturn printCall(&s.Call, \"go \", s)\n}\n\nfunc (s *Panic) String() string {\n\treturn \"panic \" + relName(s.X, s)\n}\n\nfunc (s *Return) String() string {\n\tvar b bytes.Buffer\n\tb.WriteString(\"return\")\n\tfor i, r := range s.Results {\n\t\tif i == 0 {\n\t\t\tb.WriteString(\" \")\n\t\t} else {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tb.WriteString(relName(r, s))\n\t}\n\treturn b.String()\n}\n\nfunc (*RunDefers) String() string {\n\treturn \"rundefers\"\n}\n\nfunc (s *Send) String() string {\n\treturn fmt.Sprintf(\"send %s <- %s\", relName(s.Chan, s), relName(s.X, s))\n}\n\nfunc (s *Defer) String() string {\n\tprefix := \"defer \"\n\tif s.DeferStack != nil {\n\t\tprefix += \"[\" + relName(s.DeferStack, s) + \"] \"\n\t}\n\tc := printCall(&s.Call, prefix, s)\n\treturn c\n}\n\nfunc (s *Select) String() string {\n\tvar b bytes.Buffer\n\tfor i, st := range s.States {\n\t\tif i > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tif st.Dir == types.RecvOnly {\n\t\t\tb.WriteString(\"<-\")\n\t\t\tb.WriteString(relName(st.Chan, s))\n\t\t} else {\n\t\t\tb.WriteString(relName(st.Chan, s))\n\t\t\tb.WriteString(\"<-\")\n\t\t\tb.WriteString(relName(st.Send, s))\n\t\t}\n\t}\n\tnon := \"\"\n\tif !s.Blocking {\n\t\tnon = \"non\"\n\t}\n\treturn fmt.Sprintf(\"select %sblocking [%s]\", non, b.String())\n}\n\nfunc (s *Store) String() string {\n\treturn fmt.Sprintf(\"*%s = %s\", relName(s.Addr, s), relName(s.Val, s))\n}\n\nfunc (s *MapUpdate) String() string {\n\treturn fmt.Sprintf(\"%s[%s] = %s\", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))\n}\n\nfunc (s *DebugRef) String() string {\n\tp := s.Parent().Prog.Fset.Position(s.Pos())\n\tvar descr any\n\tif s.object != nil {\n\t\tdescr = s.object // e.g. \"var x int\"\n\t} else {\n\t\tdescr = reflect.TypeOf(s.Expr) // e.g. \"*ast.CallExpr\"\n\t}\n\tvar addr string\n\tif s.IsAddr {\n\t\taddr = \"address of \"\n\t}\n\treturn fmt.Sprintf(\"; %s%s @ %d:%d is %s\", addr, descr, p.Line, p.Column, s.X.Name())\n}\n\nfunc (p *Package) String() string {\n\treturn \"package \" + p.Pkg.Path()\n}\n\nvar _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer\n\nfunc (p *Package) WriteTo(w io.Writer) (int64, error) {\n\tvar buf bytes.Buffer\n\tWritePackage(&buf, p)\n\tn, err := w.Write(buf.Bytes())\n\treturn int64(n), err\n}\n\n// WritePackage writes to buf a human-readable summary of p.\nfunc WritePackage(buf *bytes.Buffer, p *Package) {\n\tfmt.Fprintf(buf, \"%s:\\n\", p)\n\n\tvar names []string\n\tmaxname := 0\n\tfor name := range p.Members {\n\t\tif l := len(name); l > maxname {\n\t\t\tmaxname = l\n\t\t}\n\t\tnames = append(names, name)\n\t}\n\n\tfrom := p.Pkg\n\tsort.Strings(names)\n\tfor _, name := range names {\n\t\tswitch mem := p.Members[name].(type) {\n\t\tcase *NamedConst:\n\t\t\tfmt.Fprintf(buf, \"  const %-*s %s = %s\\n\",\n\t\t\t\tmaxname, name, mem.Name(), mem.Value.RelString(from))\n\n\t\tcase *Function:\n\t\t\tfmt.Fprintf(buf, \"  func  %-*s %s\\n\",\n\t\t\t\tmaxname, name, relType(mem.Type(), from))\n\n\t\tcase *Type:\n\t\t\tfmt.Fprintf(buf, \"  type  %-*s %s\\n\",\n\t\t\t\tmaxname, name, relType(mem.Type().Underlying(), from))\n\t\t\tfor _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {\n\t\t\t\tfmt.Fprintf(buf, \"    %s\\n\", types.SelectionString(meth, types.RelativeTo(from)))\n\t\t\t}\n\n\t\tcase *Global:\n\t\t\tfmt.Fprintf(buf, \"  var   %-*s %s\\n\",\n\t\t\t\tmaxname, name, relType(typeparams.MustDeref(mem.Type()), from))\n\t\t}\n\t}\n\n\tfmt.Fprintf(buf, \"\\n\")\n}\n\nfunc commaOk(x bool) string {\n\tif x {\n\t\treturn \",ok\"\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "go/ssa/sanity.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// An optional pass for sanity-checking invariants of the SSA representation.\n// Currently it checks CFG invariants but little at the instruction level.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"slices\"\n\t\"strings\"\n)\n\ntype sanity struct {\n\treporter io.Writer\n\tfn       *Function\n\tblock    *BasicBlock\n\tinstrs   map[Instruction]unit\n\tinsane   bool\n}\n\n// sanityCheck performs integrity checking of the SSA representation\n// of the function fn (which must have been \"built\") and returns true\n// if it was valid. Diagnostics are written to reporter if non-nil,\n// os.Stderr otherwise. Some diagnostics are only warnings and do not\n// imply a negative result.\n//\n// Sanity-checking is intended to facilitate the debugging of code\n// transformation passes.\nfunc sanityCheck(fn *Function, reporter io.Writer) bool {\n\tif reporter == nil {\n\t\treporter = os.Stderr\n\t}\n\treturn (&sanity{reporter: reporter}).checkFunction(fn)\n}\n\n// mustSanityCheck is like sanityCheck but panics instead of returning\n// a negative result.\nfunc mustSanityCheck(fn *Function, reporter io.Writer) {\n\tif !sanityCheck(fn, reporter) {\n\t\tfn.WriteTo(os.Stderr)\n\t\tpanic(\"SanityCheck failed\")\n\t}\n}\n\nfunc (s *sanity) diagnostic(prefix, format string, args ...any) {\n\tfmt.Fprintf(s.reporter, \"%s: function %s\", prefix, s.fn)\n\tif s.block != nil {\n\t\tfmt.Fprintf(s.reporter, \", block %s\", s.block)\n\t}\n\tio.WriteString(s.reporter, \": \")\n\tfmt.Fprintf(s.reporter, format, args...)\n\tio.WriteString(s.reporter, \"\\n\")\n}\n\nfunc (s *sanity) errorf(format string, args ...any) {\n\ts.insane = true\n\ts.diagnostic(\"Error\", format, args...)\n}\n\nfunc (s *sanity) warnf(format string, args ...any) {\n\ts.diagnostic(\"Warning\", format, args...)\n}\n\n// findDuplicate returns an arbitrary basic block that appeared more\n// than once in blocks, or nil if all were unique.\nfunc findDuplicate(blocks []*BasicBlock) *BasicBlock {\n\tif len(blocks) < 2 {\n\t\treturn nil\n\t}\n\tif blocks[0] == blocks[1] {\n\t\treturn blocks[0]\n\t}\n\t// Slow path:\n\tm := make(map[*BasicBlock]bool)\n\tfor _, b := range blocks {\n\t\tif m[b] {\n\t\t\treturn b\n\t\t}\n\t\tm[b] = true\n\t}\n\treturn nil\n}\n\nfunc (s *sanity) checkInstr(idx int, instr Instruction) {\n\tswitch instr := instr.(type) {\n\tcase *If, *Jump, *Return, *Panic:\n\t\ts.errorf(\"control flow instruction not at end of block\")\n\tcase *Phi:\n\t\tif idx == 0 {\n\t\t\t// It suffices to apply this check to just the first phi node.\n\t\t\tif dup := findDuplicate(s.block.Preds); dup != nil {\n\t\t\t\ts.errorf(\"phi node in block with duplicate predecessor %s\", dup)\n\t\t\t}\n\t\t} else {\n\t\t\tprev := s.block.Instrs[idx-1]\n\t\t\tif _, ok := prev.(*Phi); !ok {\n\t\t\t\ts.errorf(\"Phi instruction follows a non-Phi: %T\", prev)\n\t\t\t}\n\t\t}\n\t\tif ne, np := len(instr.Edges), len(s.block.Preds); ne != np {\n\t\t\ts.errorf(\"phi node has %d edges but %d predecessors\", ne, np)\n\n\t\t} else {\n\t\t\tfor i, e := range instr.Edges {\n\t\t\t\tif e == nil {\n\t\t\t\t\ts.errorf(\"phi node '%s' has no value for edge #%d from %s\", instr.Comment, i, s.block.Preds[i])\n\t\t\t\t} else if !types.Identical(instr.typ, e.Type()) {\n\t\t\t\t\ts.errorf(\"phi node '%s' has a different type (%s) for edge #%d from %s (%s)\",\n\t\t\t\t\t\tinstr.Comment, instr.Type(), i, s.block.Preds[i], e.Type())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase *Alloc:\n\t\tif !instr.Heap {\n\t\t\tfound := slices.Contains(s.fn.Locals, instr)\n\t\t\tif !found {\n\t\t\t\ts.errorf(\"local alloc %s = %s does not appear in Function.Locals\", instr.Name(), instr)\n\t\t\t}\n\t\t}\n\n\tcase *BinOp:\n\tcase *Call:\n\t\tif common := instr.Call; common.IsInvoke() {\n\t\t\tif !types.IsInterface(common.Value.Type()) {\n\t\t\t\ts.errorf(\"invoke on %s (%s) which is not an interface type (or type param)\", common.Value, common.Value.Type())\n\t\t\t}\n\t\t}\n\tcase *ChangeInterface:\n\tcase *ChangeType:\n\tcase *SliceToArrayPointer:\n\tcase *Convert:\n\t\tif from := instr.X.Type(); !isBasicConvTypes(from) {\n\t\t\tif to := instr.Type(); !isBasicConvTypes(to) {\n\t\t\t\ts.errorf(\"convert %s -> %s: at least one type must be basic (or all basic, []byte, or []rune)\", from, to)\n\t\t\t}\n\t\t}\n\tcase *MultiConvert:\n\tcase *Defer:\n\tcase *Extract:\n\tcase *Field:\n\tcase *FieldAddr:\n\tcase *Go:\n\tcase *Index:\n\tcase *IndexAddr:\n\tcase *Lookup:\n\tcase *MakeChan:\n\tcase *MakeClosure:\n\t\tnumFree := len(instr.Fn.(*Function).FreeVars)\n\t\tnumBind := len(instr.Bindings)\n\t\tif numFree != numBind {\n\t\t\ts.errorf(\"MakeClosure has %d Bindings for function %s with %d free vars\",\n\t\t\t\tnumBind, instr.Fn, numFree)\n\n\t\t}\n\t\tif recv := instr.Type().(*types.Signature).Recv(); recv != nil {\n\t\t\ts.errorf(\"MakeClosure's type includes receiver %s\", recv.Type())\n\t\t}\n\n\tcase *MakeInterface:\n\tcase *MakeMap:\n\tcase *MakeSlice:\n\tcase *MapUpdate:\n\tcase *Next:\n\tcase *Range:\n\tcase *RunDefers:\n\tcase *Select:\n\tcase *Send:\n\tcase *Slice:\n\tcase *Store:\n\tcase *TypeAssert:\n\tcase *UnOp:\n\tcase *DebugRef:\n\t\t// TODO(adonovan): implement checks.\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"Unknown instruction type: %T\", instr))\n\t}\n\n\tif call, ok := instr.(CallInstruction); ok {\n\t\tif call.Common().Signature() == nil {\n\t\t\ts.errorf(\"nil signature: %s\", call)\n\t\t}\n\t}\n\n\t// Check that value-defining instructions have valid types\n\t// and a valid referrer list.\n\tif v, ok := instr.(Value); ok {\n\t\tt := v.Type()\n\t\tif t == nil {\n\t\t\ts.errorf(\"no type: %s = %s\", v.Name(), v)\n\t\t} else if t == tRangeIter || t == tDeferStack {\n\t\t\t// not a proper type; ignore.\n\t\t} else if b, ok := t.Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {\n\t\t\ts.errorf(\"instruction has 'untyped' result: %s = %s : %s\", v.Name(), v, t)\n\t\t}\n\t\ts.checkReferrerList(v)\n\t}\n\n\t// Untyped constants are legal as instruction Operands(),\n\t// for example:\n\t//   _ = \"foo\"[0]\n\t// or:\n\t//   if wordsize==64 {...}\n\n\t// All other non-Instruction Values can be found via their\n\t// enclosing Function or Package.\n}\n\nfunc (s *sanity) checkFinalInstr(instr Instruction) {\n\tswitch instr := instr.(type) {\n\tcase *If:\n\t\tif nsuccs := len(s.block.Succs); nsuccs != 2 {\n\t\t\ts.errorf(\"If-terminated block has %d successors; expected 2\", nsuccs)\n\t\t\treturn\n\t\t}\n\t\tif s.block.Succs[0] == s.block.Succs[1] {\n\t\t\ts.errorf(\"If-instruction has same True, False target blocks: %s\", s.block.Succs[0])\n\t\t\treturn\n\t\t}\n\n\tcase *Jump:\n\t\tif nsuccs := len(s.block.Succs); nsuccs != 1 {\n\t\t\ts.errorf(\"Jump-terminated block has %d successors; expected 1\", nsuccs)\n\t\t\treturn\n\t\t}\n\n\tcase *Return:\n\t\tif nsuccs := len(s.block.Succs); nsuccs != 0 {\n\t\t\ts.errorf(\"Return-terminated block has %d successors; expected none\", nsuccs)\n\t\t\treturn\n\t\t}\n\t\tif na, nf := len(instr.Results), s.fn.Signature.Results().Len(); nf != na {\n\t\t\ts.errorf(\"%d-ary return in %d-ary function\", na, nf)\n\t\t}\n\n\tcase *Panic:\n\t\tif nsuccs := len(s.block.Succs); nsuccs != 0 {\n\t\t\ts.errorf(\"Panic-terminated block has %d successors; expected none\", nsuccs)\n\t\t\treturn\n\t\t}\n\n\tdefault:\n\t\ts.errorf(\"non-control flow instruction at end of block\")\n\t}\n}\n\nfunc (s *sanity) checkBlock(b *BasicBlock, index int) {\n\ts.block = b\n\n\tif b.Index != index {\n\t\ts.errorf(\"block has incorrect Index %d\", b.Index)\n\t}\n\tif b.parent != s.fn {\n\t\ts.errorf(\"block has incorrect parent %s\", b.parent)\n\t}\n\n\t// Check all blocks are reachable.\n\t// (The entry block is always implicitly reachable,\n\t// as is the Recover block, if any.)\n\tif (index > 0 && b != b.parent.Recover) && len(b.Preds) == 0 {\n\t\ts.warnf(\"unreachable block\")\n\t\tif b.Instrs == nil {\n\t\t\t// Since this block is about to be pruned,\n\t\t\t// tolerating transient problems in it\n\t\t\t// simplifies other optimizations.\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Check predecessor and successor relations are dual,\n\t// and that all blocks in CFG belong to same function.\n\tfor _, a := range b.Preds {\n\t\tfound := slices.Contains(a.Succs, b)\n\t\tif !found {\n\t\t\ts.errorf(\"expected successor edge in predecessor %s; found only: %s\", a, a.Succs)\n\t\t}\n\t\tif a.parent != s.fn {\n\t\t\ts.errorf(\"predecessor %s belongs to different function %s\", a, a.parent)\n\t\t}\n\t}\n\tfor _, c := range b.Succs {\n\t\tfound := slices.Contains(c.Preds, b)\n\t\tif !found {\n\t\t\ts.errorf(\"expected predecessor edge in successor %s; found only: %s\", c, c.Preds)\n\t\t}\n\t\tif c.parent != s.fn {\n\t\t\ts.errorf(\"successor %s belongs to different function %s\", c, c.parent)\n\t\t}\n\t}\n\n\t// Check each instruction is sane.\n\tn := len(b.Instrs)\n\tif n == 0 {\n\t\ts.errorf(\"basic block contains no instructions\")\n\t}\n\tvar rands [10]*Value // reuse storage\n\tfor j, instr := range b.Instrs {\n\t\tif instr == nil {\n\t\t\ts.errorf(\"nil instruction at index %d\", j)\n\t\t\tcontinue\n\t\t}\n\t\tif b2 := instr.Block(); b2 == nil {\n\t\t\ts.errorf(\"nil Block() for instruction at index %d\", j)\n\t\t\tcontinue\n\t\t} else if b2 != b {\n\t\t\ts.errorf(\"wrong Block() (%s) for instruction at index %d \", b2, j)\n\t\t\tcontinue\n\t\t}\n\t\tif j < n-1 {\n\t\t\ts.checkInstr(j, instr)\n\t\t} else {\n\t\t\ts.checkFinalInstr(instr)\n\t\t}\n\n\t\t// Check Instruction.Operands.\n\toperands:\n\t\tfor i, op := range instr.Operands(rands[:0]) {\n\t\t\tif op == nil {\n\t\t\t\ts.errorf(\"nil operand pointer %d of %s\", i, instr)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tval := *op\n\t\t\tif val == nil {\n\t\t\t\tcontinue // a nil operand is ok\n\t\t\t}\n\n\t\t\t// Check that \"untyped\" types only appear on constant operands.\n\t\t\tif _, ok := (*op).(*Const); !ok {\n\t\t\t\tif basic, ok := (*op).Type().Underlying().(*types.Basic); ok {\n\t\t\t\t\tif basic.Info()&types.IsUntyped != 0 {\n\t\t\t\t\t\ts.errorf(\"operand #%d of %s is untyped: %s\", i, instr, basic)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check that Operands that are also Instructions belong to same function.\n\t\t\t// TODO(adonovan): also check their block dominates block b.\n\t\t\tif val, ok := val.(Instruction); ok {\n\t\t\t\tif val.Block() == nil {\n\t\t\t\t\ts.errorf(\"operand %d of %s is an instruction (%s) that belongs to no block\", i, instr, val)\n\t\t\t\t} else if val.Parent() != s.fn {\n\t\t\t\t\ts.errorf(\"operand %d of %s is an instruction (%s) from function %s\", i, instr, val, val.Parent())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check that each function-local operand of\n\t\t\t// instr refers back to instr.  (NB: quadratic)\n\t\t\tswitch val := val.(type) {\n\t\t\tcase *Const, *Global, *Builtin:\n\t\t\t\tcontinue // not local\n\t\t\tcase *Function:\n\t\t\t\tif val.parent == nil {\n\t\t\t\t\tcontinue // only anon functions are local\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// TODO(adonovan): check val.Parent() != nil <=> val.Referrers() is defined.\n\n\t\t\tif refs := val.Referrers(); refs != nil {\n\t\t\t\tfor _, ref := range *refs {\n\t\t\t\t\tif ref == instr {\n\t\t\t\t\t\tcontinue operands\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ts.errorf(\"operand %d of %s (%s) does not refer to us\", i, instr, val)\n\t\t\t} else {\n\t\t\t\ts.errorf(\"operand %d of %s (%s) has no referrers\", i, instr, val)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (s *sanity) checkReferrerList(v Value) {\n\trefs := v.Referrers()\n\tif refs == nil {\n\t\ts.errorf(\"%s has missing referrer list\", v.Name())\n\t\treturn\n\t}\n\tfor i, ref := range *refs {\n\t\tif _, ok := s.instrs[ref]; !ok {\n\t\t\ts.errorf(\"%s.Referrers()[%d] = %s is not an instruction belonging to this function\", v.Name(), i, ref)\n\t\t}\n\t}\n}\n\nfunc (s *sanity) checkFunctionParams() {\n\tsignature := s.fn.Signature\n\tparams := s.fn.Params\n\n\t// startSigParams is the start of signature.Params() within params.\n\tstartSigParams := 0\n\tif signature.Recv() != nil {\n\t\tstartSigParams = 1\n\t}\n\n\tif startSigParams+signature.Params().Len() != len(params) {\n\t\ts.errorf(\"function has %d parameters in signature but has %d after building\",\n\t\t\tstartSigParams+signature.Params().Len(), len(params))\n\t\treturn\n\t}\n\n\tfor i, param := range params {\n\t\tvar sigType types.Type\n\t\tsi := i - startSigParams\n\t\tif si < 0 {\n\t\t\tsigType = signature.Recv().Type()\n\t\t} else {\n\t\t\tsigType = signature.Params().At(si).Type()\n\t\t}\n\n\t\tif !types.Identical(sigType, param.Type()) {\n\t\t\ts.errorf(\"expect type %s in signature but got type %s in param %d\", param.Type(), sigType, i)\n\t\t}\n\t}\n}\n\n// checkTransientFields checks whether all transient fields of Function are cleared.\nfunc (s *sanity) checkTransientFields() {\n\tfn := s.fn\n\tif fn.build != nil {\n\t\ts.errorf(\"function transient field 'build' is not nil\")\n\t}\n\tif fn.currentBlock != nil {\n\t\ts.errorf(\"function transient field 'currentBlock' is not nil\")\n\t}\n\tif fn.vars != nil {\n\t\ts.errorf(\"function transient field 'vars' is not nil\")\n\t}\n\tif fn.results != nil {\n\t\ts.errorf(\"function transient field 'results' is not nil\")\n\t}\n\tif fn.returnVars != nil {\n\t\ts.errorf(\"function transient field 'returnVars' is not nil\")\n\t}\n\tif fn.targets != nil {\n\t\ts.errorf(\"function transient field 'targets' is not nil\")\n\t}\n\tif fn.lblocks != nil {\n\t\ts.errorf(\"function transient field 'lblocks' is not nil\")\n\t}\n\tif fn.subst != nil {\n\t\ts.errorf(\"function transient field 'subst' is not nil\")\n\t}\n\tif fn.jump != nil {\n\t\ts.errorf(\"function transient field 'jump' is not nil\")\n\t}\n\tif fn.deferstack != nil {\n\t\ts.errorf(\"function transient field 'deferstack' is not nil\")\n\t}\n\tif fn.source != nil {\n\t\ts.errorf(\"function transient field 'source' is not nil\")\n\t}\n\tif fn.exits != nil {\n\t\ts.errorf(\"function transient field 'exits' is not nil\")\n\t}\n\tif fn.uniq != 0 {\n\t\ts.errorf(\"function transient field 'uniq' is not zero\")\n\t}\n}\n\nfunc (s *sanity) checkFunction(fn *Function) bool {\n\ts.fn = fn\n\ts.checkFunctionParams()\n\ts.checkTransientFields()\n\n\t// TODO(taking): Sanity check origin, typeparams, and typeargs.\n\tif fn.Prog == nil {\n\t\ts.errorf(\"nil Prog\")\n\t}\n\n\tvar buf bytes.Buffer\n\t_ = fn.String()               // must not crash\n\t_ = fn.RelString(fn.relPkg()) // must not crash\n\tWriteFunction(&buf, fn)       // must not crash\n\n\t// All functions have a package, except delegates (which are\n\t// shared across packages, or duplicated as weak symbols in a\n\t// separate-compilation model), and error.Error.\n\tif fn.Pkg == nil {\n\t\tif strings.HasPrefix(fn.Synthetic, \"from type information (on demand)\") ||\n\t\t\tstrings.HasPrefix(fn.Synthetic, \"wrapper \") ||\n\t\t\tstrings.HasPrefix(fn.Synthetic, \"bound \") ||\n\t\t\tstrings.HasPrefix(fn.Synthetic, \"thunk \") ||\n\t\t\tstrings.HasSuffix(fn.name, \"Error\") ||\n\t\t\tstrings.HasPrefix(fn.Synthetic, \"instance \") ||\n\t\t\tstrings.HasPrefix(fn.Synthetic, \"instantiation \") ||\n\t\t\t(fn.parent != nil && len(fn.typeargs) > 0) /* anon fun in instance */ {\n\t\t\t// ok\n\t\t} else {\n\t\t\ts.errorf(\"nil Pkg\")\n\t\t}\n\t}\n\tif src, syn := fn.Synthetic == \"\", fn.Syntax() != nil; src != syn {\n\t\tif len(fn.typeargs) > 0 && fn.Prog.mode&InstantiateGenerics != 0 {\n\t\t\t// ok (instantiation with InstantiateGenerics on)\n\t\t} else if fn.topLevelOrigin != nil && len(fn.typeargs) > 0 {\n\t\t\t// ok (we always have the syntax set for instantiation)\n\t\t} else if _, rng := fn.syntax.(*ast.RangeStmt); rng && fn.Synthetic == \"range-over-func yield\" {\n\t\t\t// ok (range-func-yields are both synthetic and keep syntax)\n\t\t} else {\n\t\t\ts.errorf(\"got fromSource=%t, hasSyntax=%t; want same values\", src, syn)\n\t\t}\n\t}\n\n\t// Build the set of valid referrers.\n\ts.instrs = make(map[Instruction]unit)\n\n\t// instrs are the instructions that are present in the function.\n\tfor instr := range fn.instrs() {\n\t\ts.instrs[instr] = unit{}\n\t}\n\n\t// Check all Locals allocations appear in the function instruction.\n\tfor i, l := range fn.Locals {\n\t\tif _, present := s.instrs[l]; !present {\n\t\t\ts.warnf(\"function doesn't contain Local alloc %s\", l.Name())\n\t\t}\n\n\t\tif l.Parent() != fn {\n\t\t\ts.errorf(\"Local %s at index %d has wrong parent\", l.Name(), i)\n\t\t}\n\t\tif l.Heap {\n\t\t\ts.errorf(\"Local %s at index %d has Heap flag set\", l.Name(), i)\n\t\t}\n\t}\n\tfor i, p := range fn.Params {\n\t\tif p.Parent() != fn {\n\t\t\ts.errorf(\"Param %s at index %d has wrong parent\", p.Name(), i)\n\t\t}\n\t\t// Check common suffix of Signature and Params match type.\n\t\tif sig := fn.Signature; sig != nil {\n\t\t\tj := i - len(fn.Params) + sig.Params().Len() // index within sig.Params\n\t\t\tif j < 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !types.Identical(p.Type(), sig.Params().At(j).Type()) {\n\t\t\t\ts.errorf(\"Param %s at index %d has wrong type (%s, versus %s in Signature)\", p.Name(), i, p.Type(), sig.Params().At(j).Type())\n\n\t\t\t}\n\t\t}\n\t\ts.checkReferrerList(p)\n\t}\n\tfor i, fv := range fn.FreeVars {\n\t\tif fv.Parent() != fn {\n\t\t\ts.errorf(\"FreeVar %s at index %d has wrong parent\", fv.Name(), i)\n\t\t}\n\t\ts.checkReferrerList(fv)\n\t}\n\n\tif fn.Blocks != nil && len(fn.Blocks) == 0 {\n\t\t// Function _had_ blocks (so it's not external) but\n\t\t// they were \"optimized\" away, even the entry block.\n\t\ts.errorf(\"Blocks slice is non-nil but empty\")\n\t}\n\tfor i, b := range fn.Blocks {\n\t\tif b == nil {\n\t\t\ts.warnf(\"nil *BasicBlock at f.Blocks[%d]\", i)\n\t\t\tcontinue\n\t\t}\n\t\ts.checkBlock(b, i)\n\t}\n\tif fn.Recover != nil && fn.Blocks[fn.Recover.Index] != fn.Recover {\n\t\ts.errorf(\"Recover block is not in Blocks slice\")\n\t}\n\n\ts.block = nil\n\tfor i, anon := range fn.AnonFuncs {\n\t\tif anon.Parent() != fn {\n\t\t\ts.errorf(\"AnonFuncs[%d]=%s but %s.Parent()=%s\", i, anon, anon, anon.Parent())\n\t\t}\n\t\tif i != int(anon.anonIdx) {\n\t\t\ts.errorf(\"AnonFuncs[%d]=%s but %s.anonIdx=%d\", i, anon, anon, anon.anonIdx)\n\t\t}\n\t}\n\ts.fn = nil\n\treturn !s.insane\n}\n\n// sanityCheckPackage checks invariants of packages upon creation.\n// It does not require that the package is built.\n// Unlike sanityCheck (for functions), it just panics at the first error.\nfunc sanityCheckPackage(pkg *Package) {\n\tif pkg.Pkg == nil {\n\t\tpanic(fmt.Sprintf(\"Package %s has no Object\", pkg))\n\t}\n\tif pkg.info != nil {\n\t\tpanic(fmt.Sprintf(\"package %s field 'info' is not cleared\", pkg))\n\t}\n\tif pkg.files != nil {\n\t\tpanic(fmt.Sprintf(\"package %s field 'files' is not cleared\", pkg))\n\t}\n\tif pkg.created != nil {\n\t\tpanic(fmt.Sprintf(\"package %s field 'created' is not cleared\", pkg))\n\t}\n\tif pkg.initVersion != nil {\n\t\tpanic(fmt.Sprintf(\"package %s field 'initVersion' is not cleared\", pkg))\n\t}\n\n\t_ = pkg.String() // must not crash\n\n\tfor name, mem := range pkg.Members {\n\t\tif name != mem.Name() {\n\t\t\tpanic(fmt.Sprintf(\"%s: %T.Name() = %s, want %s\",\n\t\t\t\tpkg.Pkg.Path(), mem, mem.Name(), name))\n\t\t}\n\t\tobj := mem.Object()\n\t\tif obj == nil {\n\t\t\t// This check is sound because fields\n\t\t\t// {Global,Function}.object have type\n\t\t\t// types.Object.  (If they were declared as\n\t\t\t// *types.{Var,Func}, we'd have a non-empty\n\t\t\t// interface containing a nil pointer.)\n\n\t\t\tcontinue // not all members have typechecker objects\n\t\t}\n\t\tif obj.Name() != name {\n\t\t\tif obj.Name() == \"init\" && strings.HasPrefix(mem.Name(), \"init#\") {\n\t\t\t\t// Ok.  The name of a declared init function varies between\n\t\t\t\t// its types.Func (\"init\") and its ssa.Function (\"init#%d\").\n\t\t\t} else {\n\t\t\t\tpanic(fmt.Sprintf(\"%s: %T.Object().Name() = %s, want %s\",\n\t\t\t\t\tpkg.Pkg.Path(), mem, obj.Name(), name))\n\t\t\t}\n\t\t}\n\t\tif obj.Pos() != mem.Pos() {\n\t\t\tpanic(fmt.Sprintf(\"%s Pos=%d obj.Pos=%d\", mem, mem.Pos(), obj.Pos()))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/source.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines utilities for working with source positions\n// or source-level named entities (\"objects\").\n\n// TODO(adonovan): test that {Value,Instruction}.Pos() positions match\n// the originating syntax, as specified.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// EnclosingFunction returns the function that contains the syntax\n// node denoted by path.\n//\n// Syntax associated with package-level variable specifications is\n// enclosed by the package's init() function.\n//\n// Returns nil if not found; reasons might include:\n//   - the node is not enclosed by any function.\n//   - the node is within an anonymous function (FuncLit) and\n//     its SSA function has not been created yet\n//     (pkg.Build() has not yet been called).\nfunc EnclosingFunction(pkg *Package, path []ast.Node) *Function {\n\t// Start with package-level function...\n\tfn := findEnclosingPackageLevelFunction(pkg, path)\n\tif fn == nil {\n\t\treturn nil // not in any function\n\t}\n\n\t// ...then walk down the nested anonymous functions.\n\tn := len(path)\nouter:\n\tfor i := range path {\n\t\tif lit, ok := path[n-1-i].(*ast.FuncLit); ok {\n\t\t\tfor _, anon := range fn.AnonFuncs {\n\t\t\t\tif anon.Pos() == lit.Type.Func {\n\t\t\t\t\tfn = anon\n\t\t\t\t\tcontinue outer\n\t\t\t\t}\n\t\t\t}\n\t\t\t// SSA function not found:\n\t\t\t// - package not yet built, or maybe\n\t\t\t// - builder skipped FuncLit in dead block\n\t\t\t//   (in principle; but currently the Builder\n\t\t\t//   generates even dead FuncLits).\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fn\n}\n\n// HasEnclosingFunction returns true if the AST node denoted by path\n// is contained within the declaration of some function or\n// package-level variable.\n//\n// Unlike EnclosingFunction, the behaviour of this function does not\n// depend on whether SSA code for pkg has been built, so it can be\n// used to quickly reject check inputs that will cause\n// EnclosingFunction to fail, prior to SSA building.\nfunc HasEnclosingFunction(pkg *Package, path []ast.Node) bool {\n\treturn findEnclosingPackageLevelFunction(pkg, path) != nil\n}\n\n// findEnclosingPackageLevelFunction returns the Function\n// corresponding to the package-level function enclosing path.\nfunc findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {\n\tif n := len(path); n >= 2 { // [... {Gen,Func}Decl File]\n\t\tswitch decl := path[n-2].(type) {\n\t\tcase *ast.GenDecl:\n\t\t\tif decl.Tok == token.VAR && n >= 3 {\n\t\t\t\t// Package-level 'var' initializer.\n\t\t\t\treturn pkg.init\n\t\t\t}\n\n\t\tcase *ast.FuncDecl:\n\t\t\tif decl.Recv == nil && decl.Name.Name == \"init\" {\n\t\t\t\t// Explicit init() function.\n\t\t\t\tfor _, b := range pkg.init.Blocks {\n\t\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\t\tif instr, ok := instr.(*Call); ok {\n\t\t\t\t\t\t\tif callee, ok := instr.Call.Value.(*Function); ok && callee.Pkg == pkg && callee.Pos() == decl.Name.NamePos {\n\t\t\t\t\t\t\t\treturn callee\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Hack: return non-nil when SSA is not yet\n\t\t\t\t// built so that HasEnclosingFunction works.\n\t\t\t\treturn pkg.init\n\t\t\t}\n\t\t\t// Declared function/method.\n\t\t\treturn findNamedFunc(pkg, decl.Name.NamePos)\n\t\t}\n\t}\n\treturn nil // not in any function\n}\n\n// findNamedFunc returns the named function whose FuncDecl.Ident is at\n// position pos.\nfunc findNamedFunc(pkg *Package, pos token.Pos) *Function {\n\t// Look at all package members and method sets of named types.\n\t// Not very efficient.\n\tfor _, mem := range pkg.Members {\n\t\tswitch mem := mem.(type) {\n\t\tcase *Function:\n\t\t\tif mem.Pos() == pos {\n\t\t\t\treturn mem\n\t\t\t}\n\t\tcase *Type:\n\t\t\tmset := pkg.Prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))\n\t\t\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\t\t\t// Don't call Program.Method: avoid creating wrappers.\n\t\t\t\tobj := mset.At(i).Obj().(*types.Func)\n\t\t\t\tif obj.Pos() == pos {\n\t\t\t\t\t// obj from MethodSet may not be the origin type.\n\t\t\t\t\tm := obj.Origin()\n\t\t\t\t\treturn pkg.objects[m].(*Function)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// ValueForExpr returns the SSA Value that corresponds to non-constant\n// expression e.\n//\n// It returns nil if no value was found, e.g.\n//   - the expression is not lexically contained within f;\n//   - f was not built with debug information; or\n//   - e is a constant expression.  (For efficiency, no debug\n//     information is stored for constants. Use\n//     go/types.Info.Types[e].Value instead.)\n//   - e is a reference to nil or a built-in function.\n//   - the value was optimised away.\n//\n// If e is an addressable expression used in an lvalue context,\n// value is the address denoted by e, and isAddr is true.\n//\n// The types of e (or &e, if isAddr) and the result are equal\n// (modulo \"untyped\" bools resulting from comparisons).\n//\n// (Tip: to find the ssa.Value given a source position, use\n// astutil.PathEnclosingInterval to locate the ast.Node, then\n// EnclosingFunction to locate the Function, then ValueForExpr to find\n// the ssa.Value.)\nfunc (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {\n\tif f.debugInfo() { // (opt)\n\t\te = ast.Unparen(e)\n\t\tfor _, b := range f.Blocks {\n\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\tif ref, ok := instr.(*DebugRef); ok {\n\t\t\t\t\tif ref.Expr == e {\n\t\t\t\t\t\treturn ref.X, ref.IsAddr\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// --- Lookup functions for source-level named entities (types.Objects) ---\n\n// Package returns the SSA Package corresponding to the specified\n// type-checker package. It returns nil if no such Package was\n// created by a prior call to prog.CreatePackage.\nfunc (prog *Program) Package(pkg *types.Package) *Package {\n\treturn prog.packages[pkg]\n}\n\n// packageLevelMember returns the package-level member corresponding\n// to the specified symbol, which may be a package-level const\n// (*NamedConst), var (*Global) or func/method (*Function) of some\n// package in prog.\n//\n// It returns nil if the object belongs to a package that has not been\n// created by prog.CreatePackage.\nfunc (prog *Program) packageLevelMember(obj types.Object) Member {\n\tif pkg, ok := prog.packages[obj.Pkg()]; ok {\n\t\treturn pkg.objects[obj]\n\t}\n\treturn nil\n}\n\n// FuncValue returns the SSA function or (non-interface) method\n// denoted by the specified func symbol. It returns nil if the symbol\n// denotes an interface method, or belongs to a package that was not\n// created by prog.CreatePackage.\nfunc (prog *Program) FuncValue(obj *types.Func) *Function {\n\tfn, _ := prog.packageLevelMember(obj).(*Function)\n\treturn fn\n}\n\n// ConstValue returns the SSA constant denoted by the specified const symbol.\nfunc (prog *Program) ConstValue(obj *types.Const) *Const {\n\t// TODO(adonovan): opt: share (don't reallocate)\n\t// Consts for const objects and constant ast.Exprs.\n\n\t// Universal constant? {true,false,nil}\n\tif obj.Parent() == types.Universe {\n\t\treturn NewConst(obj.Val(), obj.Type())\n\t}\n\t// Package-level named constant?\n\tif v := prog.packageLevelMember(obj); v != nil {\n\t\treturn v.(*NamedConst).Value\n\t}\n\treturn NewConst(obj.Val(), obj.Type())\n}\n\n// VarValue returns the SSA Value that corresponds to a specific\n// identifier denoting the specified var symbol.\n//\n// VarValue returns nil if a local variable was not found, perhaps\n// because its package was not built, the debug information was not\n// requested during SSA construction, or the value was optimized away.\n//\n// ref is the path to an ast.Ident (e.g. from PathEnclosingInterval),\n// and that ident must resolve to obj.\n//\n// pkg is the package enclosing the reference.  (A reference to a var\n// always occurs within a function, so we need to know where to find it.)\n//\n// If the identifier is a field selector and its base expression is\n// non-addressable, then VarValue returns the value of that field.\n// For example:\n//\n//\tfunc f() struct {x int}\n//\tf().x  // VarValue(x) returns a *Field instruction of type int\n//\n// All other identifiers denote addressable locations (variables).\n// For them, VarValue may return either the variable's address or its\n// value, even when the expression is evaluated only for its value; the\n// situation is reported by isAddr, the second component of the result.\n//\n// If !isAddr, the returned value is the one associated with the\n// specific identifier.  For example,\n//\n//\tvar x int    // VarValue(x) returns Const 0 here\n//\tx = 1        // VarValue(x) returns Const 1 here\n//\n// It is not specified whether the value or the address is returned in\n// any particular case, as it may depend upon optimizations performed\n// during SSA code generation, such as registerization, constant\n// folding, avoidance of materialization of subexpressions, etc.\nfunc (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {\n\t// All references to a var are local to some function, possibly init.\n\tfn := EnclosingFunction(pkg, ref)\n\tif fn == nil {\n\t\treturn // e.g. def of struct field; SSA not built?\n\t}\n\n\tid := ref[0].(*ast.Ident)\n\n\t// Defining ident of a parameter?\n\tif id.Pos() == obj.Pos() {\n\t\tfor _, param := range fn.Params {\n\t\t\tif param.Object() == obj {\n\t\t\t\treturn param, false\n\t\t\t}\n\t\t}\n\t}\n\n\t// Other ident?\n\tfor _, b := range fn.Blocks {\n\t\tfor _, instr := range b.Instrs {\n\t\t\tif dr, ok := instr.(*DebugRef); ok {\n\t\t\t\tif dr.Pos() == id.Pos() {\n\t\t\t\t\treturn dr.X, dr.IsAddr\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Defining ident of package-level var?\n\tif v := prog.packageLevelMember(obj); v != nil {\n\t\treturn v.(*Global), true\n\t}\n\n\treturn // e.g. debug info not requested, or var optimized away\n}\n"
  },
  {
    "path": "go/ssa/source_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa_test\n\n// This file defines tests of source-level debugging utilities.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/internal/expect\"\n)\n\nfunc TestObjValueLookup(t *testing.T) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"no testdata directory on %s\", runtime.GOOS)\n\t}\n\n\tsrc, err := os.ReadFile(\"testdata/objlookup.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treadFile := func(filename string) ([]byte, error) { return src, nil }\n\n\tvar (\n\t\tmode          = ssa.GlobalDebug /*|ssa.PrintFunctions*/\n\t\tmainPkg, ppkg = buildPackage(t, string(src), mode)\n\t\tf             = ppkg.Syntax[0]\n\t\ttokFile       = ppkg.Fset.File(f.Pos())\n\t)\n\n\t// Maps each var Ident (represented \"name:linenum\") to the\n\t// kind of ssa.Value we expect (represented \"Constant\", \"&Alloc\").\n\texpectations := make(map[string]string)\n\n\t// Each note of the form @ssa(x, \"BinOp\") in testdata/objlookup.go\n\t// specifies an expectation that an object named x declared on the\n\t// same line is associated with an ssa.Value of type *ssa.BinOp.\n\tnotes, err := expect.ExtractGo(tokFile, f)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, n := range notes {\n\t\tif n.Name != \"ssa\" {\n\t\t\tt.Errorf(\"%v: unexpected note type %q, want \\\"ssa\\\"\", tokFile.Position(n.Pos), n.Name)\n\t\t\tcontinue\n\t\t}\n\t\tif len(n.Args) != 2 {\n\t\t\tt.Errorf(\"%v: ssa has %d args, want 2\", tokFile.Position(n.Pos), len(n.Args))\n\t\t\tcontinue\n\t\t}\n\t\tident, ok := n.Args[0].(expect.Identifier)\n\t\tif !ok {\n\t\t\tt.Errorf(\"%v: got %v for arg 1, want identifier\", tokFile.Position(n.Pos), n.Args[0])\n\t\t\tcontinue\n\t\t}\n\t\texp, ok := n.Args[1].(string)\n\t\tif !ok {\n\t\t\tt.Errorf(\"%v: got %v for arg 2, want string\", tokFile.Position(n.Pos), n.Args[1])\n\t\t\tcontinue\n\t\t}\n\t\tp, _, err := expect.MatchBefore(tokFile, readFile, n.Pos, string(ident))\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\t\tpos := tokFile.Position(p)\n\t\tkey := fmt.Sprintf(\"%s:%d\", ident, pos.Line)\n\t\texpectations[key] = exp\n\t}\n\n\tvar varIds []*ast.Ident\n\tvar varObjs []*types.Var\n\tfor id, obj := range ppkg.TypesInfo.Defs {\n\t\t// Check invariants for func and const objects.\n\t\tswitch obj := obj.(type) {\n\t\tcase *types.Func:\n\t\t\tcheckFuncValue(t, mainPkg.Prog, obj)\n\n\t\tcase *types.Const:\n\t\t\tcheckConstValue(t, mainPkg.Prog, obj)\n\n\t\tcase *types.Var:\n\t\t\tif id.Name == \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvarIds = append(varIds, id)\n\t\t\tvarObjs = append(varObjs, obj)\n\t\t}\n\t}\n\tfor id, obj := range ppkg.TypesInfo.Uses {\n\t\tif obj, ok := obj.(*types.Var); ok {\n\t\t\tvarIds = append(varIds, id)\n\t\t\tvarObjs = append(varObjs, obj)\n\t\t}\n\t}\n\n\t// Check invariants for var objects.\n\t// The result varies based on the specific Ident.\n\tfor i, id := range varIds {\n\t\tobj := varObjs[i]\n\t\tref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())\n\t\tpos := tokFile.Position(id.Pos())\n\t\texp := expectations[fmt.Sprintf(\"%s:%d\", id.Name, pos.Line)]\n\t\tif exp == \"\" {\n\t\t\tt.Errorf(\"%s: no expectation for var ident %s \", pos, id.Name)\n\t\t\tcontinue\n\t\t}\n\t\twantAddr := false\n\t\tif exp[0] == '&' {\n\t\t\twantAddr = true\n\t\t\texp = exp[1:]\n\t\t}\n\t\tcheckVarValue(t, mainPkg, ref, obj, exp, wantAddr)\n\t}\n}\n\nfunc checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {\n\tfn := prog.FuncValue(obj)\n\t// fmt.Printf(\"FuncValue(%s) = %s\\n\", obj, fn) // debugging\n\tif fn == nil {\n\t\tif obj.Name() != \"interfaceMethod\" {\n\t\t\tt.Errorf(\"FuncValue(%s) == nil\", obj)\n\t\t}\n\t\treturn\n\t}\n\tif fnobj := fn.Object(); fnobj != obj {\n\t\tt.Errorf(\"FuncValue(%s).Object() == %s; value was %s\",\n\t\t\tobj, fnobj, fn.Name())\n\t\treturn\n\t}\n\tif !types.Identical(fn.Type(), obj.Type()) {\n\t\tt.Errorf(\"FuncValue(%s).Type() == %s\", obj, fn.Type())\n\t\treturn\n\t}\n}\n\nfunc checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) {\n\tc := prog.ConstValue(obj)\n\t// fmt.Printf(\"ConstValue(%s) = %s\\n\", obj, c) // debugging\n\tif c == nil {\n\t\tt.Errorf(\"ConstValue(%s) == nil\", obj)\n\t\treturn\n\t}\n\tif !types.Identical(c.Type(), obj.Type()) {\n\t\tt.Errorf(\"ConstValue(%s).Type() == %s\", obj, c.Type())\n\t\treturn\n\t}\n\tif obj.Name() != \"nil\" {\n\t\tif !constant.Compare(c.Value, token.EQL, obj.Val()) {\n\t\t\tt.Errorf(\"ConstValue(%s).Value (%s) != %s\",\n\t\t\t\tobj, c.Value, obj.Val())\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc checkVarValue(t *testing.T, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) {\n\t// The prefix of all assertions messages.\n\tprefix := fmt.Sprintf(\"VarValue(%s @ L%d)\",\n\t\tobj, pkg.Prog.Fset.Position(ref[0].Pos()).Line)\n\n\tv, gotAddr := pkg.Prog.VarValue(obj, pkg, ref)\n\n\t// Kind is the concrete type of the ssa Value.\n\tgotKind := \"nil\"\n\tif v != nil {\n\t\tgotKind = fmt.Sprintf(\"%T\", v)[len(\"*ssa.\"):]\n\t}\n\n\t// fmt.Printf(\"%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\\n\", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging\n\n\t// Check the kinds match.\n\t// \"nil\" indicates expected failure (e.g. optimized away).\n\tif expKind != gotKind {\n\t\tt.Errorf(\"%s concrete type == %s, want %s\", prefix, gotKind, expKind)\n\t}\n\n\t// Check the types match.\n\t// If wantAddr, the expected type is the object's address.\n\tif v != nil {\n\t\texpType := obj.Type()\n\t\tif wantAddr {\n\t\t\texpType = types.NewPointer(expType)\n\t\t\tif !gotAddr {\n\t\t\t\tt.Errorf(\"%s: got value, want address\", prefix)\n\t\t\t}\n\t\t} else if gotAddr {\n\t\t\tt.Errorf(\"%s: got address, want value\", prefix)\n\t\t}\n\t\tif !types.Identical(v.Type(), expType) {\n\t\t\tt.Errorf(\"%s.Type() == %s, want %s\", prefix, v.Type(), expType)\n\t\t}\n\t}\n}\n\n// Ensure that, in debug mode, we can determine the ssa.Value\n// corresponding to every ast.Expr.\nfunc TestValueForExpr(t *testing.T) {\n\ttestValueForExpr(t, \"testdata/valueforexpr.go\")\n}\n\nfunc TestValueForExprStructConv(t *testing.T) {\n\ttestValueForExpr(t, \"testdata/structconv.go\")\n}\n\nfunc testValueForExpr(t *testing.T, testfile string) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"no testdata dir on %s\", runtime.GOOS)\n\t}\n\n\tsrc, err := os.ReadFile(testfile)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar (\n\t\tmode          = ssa.GlobalDebug /*|ssa.PrintFunctions*/\n\t\tmainPkg, ppkg = buildPackage(t, string(src), mode)\n\t\tfile          = ppkg.Syntax[0]\n\t\ttokFile       = ppkg.Fset.File(file.Pos())\n\t)\n\n\tif false {\n\t\t// debugging\n\t\tfor _, mem := range mainPkg.Members {\n\t\t\tif fn, ok := mem.(*ssa.Function); ok {\n\t\t\t\tfn.WriteTo(os.Stderr)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar parenExprs []*ast.ParenExpr\n\tast.Inspect(file, func(n ast.Node) bool {\n\t\tif n != nil {\n\t\t\tif e, ok := n.(*ast.ParenExpr); ok {\n\t\t\t\tparenExprs = append(parenExprs, e)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\tnotes, err := expect.ExtractGo(tokFile, file)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, n := range notes {\n\t\twant := n.Name\n\t\tif want == \"nil\" {\n\t\t\twant = \"<nil>\"\n\t\t}\n\t\tposition := tokFile.Position(n.Pos)\n\t\tvar e ast.Expr\n\t\tfor _, paren := range parenExprs {\n\t\t\tif paren.Pos() > n.Pos {\n\t\t\t\te = paren.X\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif e == nil {\n\t\t\tt.Errorf(\"%s: note doesn't precede ParenExpr: %q\", position, want)\n\t\t\tcontinue\n\t\t}\n\n\t\tpath, _ := astutil.PathEnclosingInterval(file, n.Pos, n.Pos)\n\t\tif path == nil {\n\t\t\tt.Errorf(\"%s: can't find AST path from root to comment: %s\", position, want)\n\t\t\tcontinue\n\t\t}\n\n\t\tfn := ssa.EnclosingFunction(mainPkg, path)\n\t\tif fn == nil {\n\t\t\tt.Errorf(\"%s: can't find enclosing function\", position)\n\t\t\tcontinue\n\t\t}\n\n\t\tv, gotAddr := fn.ValueForExpr(e) // (may be nil)\n\t\tgot := strings.TrimPrefix(fmt.Sprintf(\"%T\", v), \"*ssa.\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"%s: got value %q, want %q\", position, got, want)\n\t\t}\n\t\tif v != nil {\n\t\t\tT := v.Type()\n\t\t\tif gotAddr {\n\t\t\t\tT = T.Underlying().(*types.Pointer).Elem() // deref\n\t\t\t}\n\t\t\tif etyp := ppkg.TypesInfo.TypeOf(e); !types.Identical(T, etyp) {\n\t\t\t\tt.Errorf(\"%s: got type %s, want %s\", position, etyp, T)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestEnclosingFunction(t *testing.T) {\n\ttests := []struct {\n\t\tdesc   string\n\t\tinput  string // the input file\n\t\tsubstr string // first occurrence of this string denotes interval\n\t\tfn     string // name of expected containing function\n\t}{\n\t\t// We use distinctive numbers as syntactic landmarks.\n\t\t{\"Ordinary function\", `\n\t\t  package main\n\t\t  func f() { println(1003) }`,\n\t\t\t\"100\", \"main.f\"},\n\t\t{\"Methods\", `\n\t\t  package main\n          type T int\n\t\t  func (t T) f() { println(200) }`,\n\t\t\t\"200\", \"(main.T).f\"},\n\t\t{\"Function literal\", `\n\t\t  package main\n\t\t  func f() { println(func() { print(300) }) }`,\n\t\t\t\"300\", \"main.f$1\"},\n\t\t{\"Doubly nested\", `\n\t\t  package main\n\t\t  func f() { println(func() { print(func() { print(350) })})}`,\n\t\t\t\"350\", \"main.f$1$1\"},\n\t\t{\"Implicit init for package-level var initializer\", `\n\t\t  package main; var a = 400`,\n\t\t\t\"400\", \"main.init\"},\n\t\t{\"No code for constants\", \"package main; const a = 500\", \"500\", \"(none)\"},\n\t\t{\" Explicit init\", \"package main; func init() { println(600) }\", \"600\", \"main.init#1\"},\n\t\t{\"Multiple explicit init functions\", `\n\t\t  package main\n\t\t  func init() { println(\"foo\") }\n\t\t  func init() { println(800) }`,\n\t\t\t\"800\", \"main.init#2\"},\n\t\t{\"init containing FuncLit\", `\n\t\t  package main\n\t\t  func init() { println(func(){print(900)}) }`,\n\t\t\t\"900\", \"main.init#1$1\"},\n\t\t{\"generic\", `\n\t\t    package main\n\t\t\ttype S[T any] struct{}\n\t\t\tfunc (*S[T]) Foo() { println(1000) }\n\t\t\ttype P[T any] struct{ *S[T] }`,\n\t\t\t\"1000\", \"(*main.S[T]).Foo\",\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tpkg, ppkg := buildPackage(t, test.input, ssa.BuilderMode(0))\n\t\t\tfset, file := ppkg.Fset, ppkg.Syntax[0]\n\n\t\t\t// Find [start,end) positions of the first occurrence of substr in file.\n\t\t\tindex := strings.Index(test.input, test.substr)\n\t\t\tif index < 0 {\n\t\t\t\tt.Fatalf(\"%q is not a substring of input\", test.substr)\n\t\t\t}\n\t\t\tfilePos := fset.File(file.Package)\n\t\t\tstart, end := filePos.Pos(index), filePos.Pos(index+len(test.substr))\n\n\t\t\tpath, exact := astutil.PathEnclosingInterval(file, start, end)\n\t\t\tif !exact {\n\t\t\t\tt.Fatalf(\"PathEnclosingInterval(%q) not exact\", test.substr)\n\t\t\t}\n\n\t\t\tname := \"(none)\"\n\t\t\tfn := ssa.EnclosingFunction(pkg, path)\n\t\t\tif fn != nil {\n\t\t\t\tname = fn.String()\n\t\t\t}\n\n\t\t\tif name != test.fn {\n\t\t\t\tt.Errorf(\"EnclosingFunction(%q in %q) got %s, want %s\",\n\t\t\t\t\ttest.substr, test.input, name, test.fn)\n\t\t\t}\n\n\t\t\t// While we're here: test HasEnclosingFunction.\n\t\t\tif has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {\n\t\t\t\tt.Errorf(\"HasEnclosingFunction(%q in %q) got %v, want %v\",\n\t\t\t\t\ttest.substr, test.input, has, fn != nil)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "go/ssa/ssa.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This package defines a high-level intermediate representation for\n// Go programs using static single-assignment (SSA) form.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// A Program is a partial or complete Go program converted to SSA form.\ntype Program struct {\n\tFset       *token.FileSet              // position information for the files of this Program\n\timported   map[string]*Package         // all importable Packages, keyed by import path\n\tpackages   map[*types.Package]*Package // all created Packages\n\tmode       BuilderMode                 // set of mode bits for SSA construction\n\tMethodSets typeutil.MethodSetCache     // cache of type-checker's method-sets\n\n\tcanon *canonizer     // type canonicalization map\n\tctxt  *types.Context // cache for type checking instantiations\n\n\tmethodsMu  sync.Mutex\n\tmethodSets typeutil.Map // maps type to its concrete *methodSet\n\n\t// memoization of whether a type refers to type parameters\n\thasParamsMu sync.Mutex\n\thasParams   typeparams.Free\n\n\t// set of concrete types used as MakeInterface operands\n\tmakeInterfaceTypesMu sync.Mutex\n\tmakeInterfaceTypes   map[types.Type]unit // (may contain redundant identical types)\n\n\t// objectMethods is a memoization of objectMethod\n\t// to avoid creation of duplicate methods from type information.\n\tobjectMethodsMu sync.Mutex\n\tobjectMethods   map[*types.Func]*Function\n\n\tnoReturn func(*types.Func) bool // (optional) predicate that decides whether a given call cannot return\n}\n\n// A Package is a single analyzed Go package containing Members for\n// all package-level functions, variables, constants and types it\n// declares.  These may be accessed directly via Members, or via the\n// type-specific accessor methods Func, Type, Var and Const.\n//\n// Members also contains entries for \"init\" (the synthetic package\n// initializer) and \"init#%d\", the nth declared init function,\n// and unspecified other things too.\ntype Package struct {\n\tProg    *Program                // the owning program\n\tPkg     *types.Package          // the corresponding go/types.Package\n\tMembers map[string]Member       // all package members keyed by name (incl. init and init#%d)\n\tobjects map[types.Object]Member // mapping of package objects to members (incl. methods). Contains *NamedConst, *Global, *Function (values but not types)\n\tinit    *Function               // Func(\"init\"); the package's init function\n\tdebug   bool                    // include full debug info in this package\n\tsyntax  bool                    // package was loaded from syntax\n\n\t// The following fields are set transiently, then cleared\n\t// after building.\n\tbuildOnce   sync.Once           // ensures package building occurs once\n\tninit       int32               // number of init functions\n\tinfo        *types.Info         // package type information\n\tfiles       []*ast.File         // package ASTs\n\tcreated     []*Function         // members created as a result of building this package (includes declared functions, wrappers)\n\tinitVersion map[ast.Expr]string // goversion to use for each global var init expr\n}\n\n// A Member is a member of a Go package, implemented by *NamedConst,\n// *Global, *Function, or *Type; they are created by package-level\n// const, var, func and type declarations respectively.\ntype Member interface {\n\tName() string                    // declared name of the package member\n\tString() string                  // package-qualified name of the package member\n\tRelString(*types.Package) string // like String, but relative refs are unqualified\n\tObject() types.Object            // typechecker's object for this member, if any\n\tPos() token.Pos                  // position of member's declaration, if known\n\tType() types.Type                // type of the package member\n\tToken() token.Token              // token.{VAR,FUNC,CONST,TYPE}\n\tPackage() *Package               // the containing package\n}\n\n// A Type is a Member of a Package representing a package-level named type.\ntype Type struct {\n\tobject *types.TypeName\n\tpkg    *Package\n}\n\n// A NamedConst is a Member of a Package representing a package-level\n// named constant.\n//\n// Pos() returns the position of the declaring ast.ValueSpec.Names[*]\n// identifier.\n//\n// NB: a NamedConst is not a Value; it contains a constant Value, which\n// it augments with the name and position of its 'const' declaration.\ntype NamedConst struct {\n\tobject *types.Const\n\tValue  *Const\n\tpkg    *Package\n}\n\n// A Value is an SSA value that can be referenced by an instruction.\ntype Value interface {\n\t// Name returns the name of this value, and determines how\n\t// this Value appears when used as an operand of an\n\t// Instruction.\n\t//\n\t// This is the same as the source name for Parameters,\n\t// Builtins, Functions, FreeVars, Globals.\n\t// For constants, it is a representation of the constant's value\n\t// and type.  For all other Values this is the name of the\n\t// virtual register defined by the instruction.\n\t//\n\t// The name of an SSA Value is not semantically significant,\n\t// and may not even be unique within a function.\n\tName() string\n\n\t// If this value is an Instruction, String returns its\n\t// disassembled form; otherwise it returns unspecified\n\t// human-readable information about the Value, such as its\n\t// kind, name and type.\n\tString() string\n\n\t// Type returns the type of this value.  Many instructions\n\t// (e.g. IndexAddr) change their behaviour depending on the\n\t// types of their operands.\n\tType() types.Type\n\n\t// Parent returns the function to which this Value belongs.\n\t// It returns nil for named Functions, Builtin, Const and Global.\n\tParent() *Function\n\n\t// Referrers returns the list of instructions that have this\n\t// value as one of their operands; it may contain duplicates\n\t// if an instruction has a repeated operand.\n\t//\n\t// Referrers actually returns a pointer through which the\n\t// caller may perform mutations to the object's state.\n\t//\n\t// Referrers is currently only defined if Parent()!=nil,\n\t// i.e. for the function-local values FreeVar, Parameter,\n\t// Functions (iff anonymous) and all value-defining instructions.\n\t// It returns nil for named Functions, Builtin, Const and Global.\n\t//\n\t// Instruction.Operands contains the inverse of this relation.\n\tReferrers() *[]Instruction\n\n\t// Pos returns the location of the AST token most closely\n\t// associated with the operation that gave rise to this value,\n\t// or token.NoPos if it was not explicit in the source.\n\t//\n\t// For each ast.Node type, a particular token is designated as\n\t// the closest location for the expression, e.g. the Lparen\n\t// for an *ast.CallExpr.  This permits a compact but\n\t// approximate mapping from Values to source positions for use\n\t// in diagnostic messages, for example.\n\t//\n\t// (Do not use this position to determine which Value\n\t// corresponds to an ast.Expr; use Function.ValueForExpr\n\t// instead.  NB: it requires that the function was built with\n\t// debug information.)\n\tPos() token.Pos\n}\n\n// An Instruction is an SSA instruction that computes a new Value or\n// has some effect.\n//\n// An Instruction that defines a value (e.g. BinOp) also implements\n// the Value interface; an Instruction that only has an effect (e.g. Store)\n// does not.\ntype Instruction interface {\n\t// String returns the disassembled form of this value.\n\t//\n\t// Examples of Instructions that are Values:\n\t//       \"x + y\"     (BinOp)\n\t//       \"len([])\"   (Call)\n\t// Note that the name of the Value is not printed.\n\t//\n\t// Examples of Instructions that are not Values:\n\t//       \"return x\"  (Return)\n\t//       \"*y = x\"    (Store)\n\t//\n\t// (The separation Value.Name() from Value.String() is useful\n\t// for some analyses which distinguish the operation from the\n\t// value it defines, e.g., 'y = local int' is both an allocation\n\t// of memory 'local int' and a definition of a pointer y.)\n\tString() string\n\n\t// Parent returns the function to which this instruction\n\t// belongs.\n\tParent() *Function\n\n\t// Block returns the basic block to which this instruction\n\t// belongs.\n\tBlock() *BasicBlock\n\n\t// setBlock sets the basic block to which this instruction belongs.\n\tsetBlock(*BasicBlock)\n\n\t// Operands returns the operands of this instruction: the\n\t// set of Values it references.\n\t//\n\t// Specifically, it appends their addresses to rands, a\n\t// user-provided slice, and returns the resulting slice,\n\t// permitting avoidance of memory allocation.\n\t//\n\t// The operands are appended in undefined order, but the order\n\t// is consistent for a given Instruction; the addresses are\n\t// always non-nil but may point to a nil Value.  Clients may\n\t// store through the pointers, e.g. to effect a value\n\t// renaming.\n\t//\n\t// Value.Referrers is a subset of the inverse of this\n\t// relation.  (Referrers are not tracked for all types of\n\t// Values.)\n\tOperands(rands []*Value) []*Value\n\n\t// Pos returns the location of the AST token most closely\n\t// associated with the operation that gave rise to this\n\t// instruction, or token.NoPos if it was not explicit in the\n\t// source.\n\t//\n\t// For each ast.Node type, a particular token is designated as\n\t// the closest location for the expression, e.g. the Go token\n\t// for an *ast.GoStmt.  This permits a compact but approximate\n\t// mapping from Instructions to source positions for use in\n\t// diagnostic messages, for example.\n\t//\n\t// (Do not use this position to determine which Instruction\n\t// corresponds to an ast.Expr; see the notes for Value.Pos.\n\t// This position may be used to determine which non-Value\n\t// Instruction corresponds to some ast.Stmts, but not all: If\n\t// and Jump instructions have no Pos(), for example.)\n\tPos() token.Pos\n}\n\n// A Node is a node in the SSA value graph.  Every concrete type that\n// implements Node is also either a Value, an Instruction, or both.\n//\n// Node contains the methods common to Value and Instruction, plus the\n// Operands and Referrers methods generalized to return nil for\n// non-Instructions and non-Values, respectively.\n//\n// Node is provided to simplify SSA graph algorithms.  Clients should\n// use the more specific and informative Value or Instruction\n// interfaces where appropriate.\ntype Node interface {\n\t// Common methods:\n\tString() string\n\tPos() token.Pos\n\tParent() *Function\n\n\t// Partial methods:\n\tOperands(rands []*Value) []*Value // nil for non-Instructions\n\tReferrers() *[]Instruction        // nil for non-Values\n}\n\n// Function represents the parameters, results, and code of a function\n// or method.\n//\n// If Blocks is nil, this indicates an external function for which no\n// Go source code is available.  In this case, FreeVars, Locals, and\n// Params are nil too.  Clients performing whole-program analysis must\n// handle external functions specially.\n//\n// Blocks contains the function's control-flow graph (CFG).\n// Blocks[0] is the function entry point; block order is not otherwise\n// semantically significant, though it may affect the readability of\n// the disassembly.\n// To iterate over the blocks in dominance order, use DomPreorder().\n//\n// Recover is an optional second entry point to which control resumes\n// after a recovered panic.  The Recover block may contain only a return\n// statement, preceded by a load of the function's named return\n// parameters, if any.\n//\n// A nested function (Parent()!=nil) that refers to one or more\n// lexically enclosing local variables (\"free variables\") has FreeVars.\n// Such functions cannot be called directly but require a\n// value created by MakeClosure which, via its Bindings, supplies\n// values for these parameters.\n//\n// If the function is a method (Signature.Recv() != nil) then the first\n// element of Params is the receiver parameter.\n//\n// A Go package may declare many functions called \"init\".\n// For each one, Object().Name() returns \"init\" but Name() returns\n// \"init#1\", etc, in declaration order.\n//\n// Pos() returns the declaring ast.FuncLit.Type.Func or the position\n// of the ast.FuncDecl.Name, if the function was explicit in the\n// source. Synthetic wrappers, for which Synthetic != \"\", may share\n// the same position as the function they wrap.\n// Syntax.Pos() always returns the position of the declaring \"func\" token.\n//\n// When the operand of a range statement is an iterator function,\n// the loop body is transformed into a synthetic anonymous function\n// that is passed as the yield argument in a call to the iterator.\n// In that case, Function.Pos is the position of the \"range\" token,\n// and Function.Syntax is the ast.RangeStmt.\n//\n// Synthetic functions, for which Synthetic != \"\", are functions\n// that do not appear in the source AST. These include:\n//   - method wrappers,\n//   - thunks,\n//   - bound functions,\n//   - empty functions built from loaded type information,\n//   - yield functions created from range-over-func loops,\n//   - package init functions, and\n//   - instantiations of generic functions.\n//\n// Synthetic wrapper functions may share the same position\n// as the function they wrap.\n//\n// Type() returns the function's Signature.\n//\n// A generic function is a function or method that has uninstantiated type\n// parameters (TypeParams() != nil). Consider a hypothetical generic\n// method, (*Map[K,V]).Get. It may be instantiated with all\n// non-parameterized types as (*Map[string,int]).Get or with\n// parameterized types as (*Map[string,U]).Get, where U is a type parameter.\n// In both instantiations, Origin() refers to the instantiated generic\n// method, (*Map[K,V]).Get, TypeParams() refers to the parameters [K,V] of\n// the generic method. TypeArgs() refers to [string,U] or [string,int],\n// respectively, and is nil in the generic method.\ntype Function struct {\n\tname      string\n\tobject    *types.Func // symbol for declared function (nil for FuncLit or synthetic init)\n\tmethod    *selection  // info about provenance of synthetic methods; thunk => non-nil\n\tSignature *types.Signature\n\tpos       token.Pos\n\n\t// source information\n\tSynthetic string      // provenance of synthetic function; \"\" for true source functions\n\tsyntax    ast.Node    // *ast.Func{Decl,Lit}, if from syntax (incl. generic instances) or (*ast.RangeStmt if a yield function)\n\tinfo      *types.Info // type annotations (if syntax != nil)\n\tgoversion string      // Go version of syntax (NB: init is special)\n\n\tparent *Function // enclosing function if anon; nil if global\n\tPkg    *Package  // enclosing package; nil for shared funcs (wrappers and error.Error)\n\tProg   *Program  // enclosing program\n\n\tbuildshared *task // wait for a shared function to be done building (may be nil if <=1 builder ever needs to wait)\n\n\t// These fields are populated only when the function body is built:\n\n\tParams    []*Parameter  // function parameters; for methods, includes receiver\n\tFreeVars  []*FreeVar    // free variables whose values must be supplied by closure\n\tLocals    []*Alloc      // frame-allocated variables of this function\n\tBlocks    []*BasicBlock // basic blocks of the function; nil => external\n\tRecover   *BasicBlock   // optional; control transfers here after recovered panic\n\tAnonFuncs []*Function   // anonymous functions (from FuncLit,RangeStmt) directly beneath this one\n\treferrers []Instruction // referring instructions (iff Parent() != nil)\n\tanonIdx   int32         // position of a nested function in parent's AnonFuncs. fn.Parent()!=nil => fn.Parent().AnonFunc[fn.anonIdx] == fn.\n\n\ttypeparams     *types.TypeParamList // type parameters of this function. typeparams.Len() > 0 => generic or instance of generic function\n\ttypeargs       []types.Type         // type arguments that instantiated typeparams. len(typeargs) > 0 => instance of generic function\n\ttopLevelOrigin *Function            // the origin function if this is an instance of a source function. nil if Parent()!=nil.\n\tgeneric        *generic             // instances of this function, if generic\n\n\t// The following fields are cleared after building.\n\tbuild        buildFunc                // algorithm to build function body (nil => built)\n\tcurrentBlock *BasicBlock              // where to emit code\n\tvars         map[*types.Var]Value     // addresses of local variables\n\tresults      []*Alloc                 // result allocations of the current function\n\treturnVars   []*types.Var             // variables for a return statement. Either results or for range-over-func a parent's results\n\ttargets      *targets                 // linked stack of branch targets\n\tlblocks      map[*types.Label]*lblock // labelled blocks\n\tsubst        *subster                 // type parameter substitutions (if non-nil)\n\tjump         *types.Var               // synthetic variable for the yield state (non-nil => range-over-func)\n\tdeferstack   *types.Var               // synthetic variable holding enclosing ssa:deferstack()\n\tsource       *Function                // nearest enclosing source function\n\texits        []*exit                  // exits of the function that need to be resolved\n\tuniq         int64                    // source of unique ints within the source tree while building\n}\n\n// BasicBlock represents an SSA basic block.\n//\n// The final element of Instrs is always an explicit transfer of\n// control (If, Jump, Return, or Panic).\n//\n// A block may contain no Instructions only if it is unreachable,\n// i.e., Preds is nil.  Empty blocks are typically pruned.\n//\n// BasicBlocks and their Preds/Succs relation form a (possibly cyclic)\n// graph independent of the SSA Value graph: the control-flow graph or\n// CFG.  It is illegal for multiple edges to exist between the same\n// pair of blocks.\n//\n// Each BasicBlock is also a node in the dominator tree of the CFG.\n// The tree may be navigated using Idom()/Dominees() and queried using\n// Dominates().\n//\n// The order of Preds and Succs is significant (to Phi and If\n// instructions, respectively).\ntype BasicBlock struct {\n\tIndex        int            // index of this block within Parent().Blocks\n\tComment      string         // optional label; no semantic significance\n\tparent       *Function      // parent function\n\tInstrs       []Instruction  // instructions in order\n\tPreds, Succs []*BasicBlock  // predecessors and successors\n\tsuccs2       [2]*BasicBlock // initial space for Succs\n\tdom          domInfo        // dominator tree info\n\tgaps         int            // number of nil Instrs (transient)\n\trundefers    int            // number of rundefers (transient)\n}\n\n// Pure values ----------------------------------------\n\n// A FreeVar represents a free variable of the function to which it\n// belongs.\n//\n// FreeVars are used to implement anonymous functions, whose free\n// variables are lexically captured in a closure formed by\n// MakeClosure.  The value of such a free var is an Alloc or another\n// FreeVar and is considered a potentially escaping heap address, with\n// pointer type.\n//\n// FreeVars are also used to implement bound method closures.  Such a\n// free var represents the receiver value and may be of any type that\n// has concrete methods.\n//\n// Pos() returns the position of the value that was captured, which\n// belongs to an enclosing function.\ntype FreeVar struct {\n\tname      string\n\ttyp       types.Type\n\tpos       token.Pos\n\tparent    *Function\n\treferrers []Instruction\n\n\t// Transiently needed during building.\n\touter Value // the Value captured from the enclosing context.\n}\n\n// A Parameter represents an input parameter of a function.\ntype Parameter struct {\n\tname      string\n\tobject    *types.Var // non-nil\n\ttyp       types.Type\n\tparent    *Function\n\treferrers []Instruction\n}\n\n// A Const represents a value known at build time.\n//\n// Consts include true constants of boolean, numeric, and string types, as\n// defined by the Go spec; these are represented by a non-nil Value field.\n//\n// Consts also include the \"zero\" value of any type, of which the nil values\n// of various pointer-like types are a special case; these are represented\n// by a nil Value field.\n//\n// Pos() returns token.NoPos.\n//\n// Example printed forms:\n//\n//\t\t42:int\n//\t\t\"hello\":untyped string\n//\t\t3+4i:MyComplex\n//\t\tnil:*int\n//\t\tnil:[]string\n//\t\t[3]int{}:[3]int\n//\t\tstruct{x string}{}:struct{x string}\n//\t    0:interface{int|int64}\n//\t    nil:interface{bool|int} // no go/constant representation\ntype Const struct {\n\ttyp   types.Type\n\tValue constant.Value\n}\n\n// A Global is a named Value holding the address of a package-level\n// variable.\n//\n// Pos() returns the position of the ast.ValueSpec.Names[*]\n// identifier.\ntype Global struct {\n\tname   string\n\tobject types.Object // a *types.Var; may be nil for synthetics e.g. init$guard\n\ttyp    types.Type\n\tpos    token.Pos\n\n\tPkg *Package\n}\n\n// A Builtin represents a specific use of a built-in function, e.g. len.\n//\n// Builtins are immutable values.  Builtins do not have addresses.\n// Builtins can only appear in CallCommon.Value.\n//\n// Name() indicates the function: one of the built-in functions from the\n// Go spec (excluding \"make\" and \"new\") or one of these ssa-defined\n// intrinsics:\n//\n//\t// wrapnilchk returns ptr if non-nil, panics otherwise.\n//\t// (For use in indirection wrappers.)\n//\tfunc ssa:wrapnilchk(ptr *T, recvType, methodName string) *T\n//\n// Object() returns a *types.Builtin for built-ins defined by the spec,\n// nil for others.\n//\n// Type() returns a *types.Signature representing the effective\n// signature of the built-in for this call.\ntype Builtin struct {\n\tname string\n\tsig  *types.Signature\n}\n\n// Value-defining instructions  ----------------------------------------\n\n// The Alloc instruction reserves space for a variable of the given type,\n// zero-initializes it, and yields its address.\n//\n// Alloc values are always addresses, and have pointer types, so the\n// type of the allocated variable is actually\n// Type().Underlying().(*types.Pointer).Elem().\n//\n// If Heap is false, Alloc zero-initializes the same local variable in\n// the call frame and returns its address; in this case the Alloc must\n// be present in Function.Locals. We call this a \"local\" alloc.\n//\n// If Heap is true, Alloc allocates a new zero-initialized variable\n// each time the instruction is executed. We call this a \"new\" alloc.\n//\n// When Alloc is applied to a channel, map or slice type, it returns\n// the address of an uninitialized (nil) reference of that kind; store\n// the result of MakeSlice, MakeMap or MakeChan in that location to\n// instantiate these types.\n//\n// Pos() returns the ast.CompositeLit.Lbrace for a composite literal,\n// or the ast.CallExpr.Rparen for a call to new() or for a call that\n// allocates a varargs slice.\n//\n// Example printed form:\n//\n//\tt0 = local int\n//\tt1 = new int\ntype Alloc struct {\n\tregister\n\tComment string\n\tHeap    bool\n\tindex   int // dense numbering; for lifting\n}\n\n// The Phi instruction represents an SSA φ-node, which combines values\n// that differ across incoming control-flow edges and yields a new\n// value.  Within a block, all φ-nodes must appear before all non-φ\n// nodes.\n//\n// Pos() returns the position of the && or || for short-circuit\n// control-flow joins, or that of the *Alloc for φ-nodes inserted\n// during SSA renaming.\n//\n// Example printed form:\n//\n//\tt2 = phi [0: t0, 1: t1]\ntype Phi struct {\n\tregister\n\tComment string  // a hint as to its purpose\n\tEdges   []Value // Edges[i] is value for Block().Preds[i]\n}\n\n// The Call instruction represents a function or method call.\n//\n// The Call instruction yields the function result if there is exactly\n// one.  Otherwise it returns a tuple, the components of which are\n// accessed via Extract.\n//\n// See CallCommon for generic function call documentation.\n//\n// Pos() returns the ast.CallExpr.Lparen, if explicit in the source.\n//\n// Example printed form:\n//\n//\tt2 = println(t0, t1)\n//\tt4 = t3()\n//\tt7 = invoke t5.Println(...t6)\ntype Call struct {\n\tregister\n\tCall CallCommon\n}\n\n// The BinOp instruction yields the result of binary operation X Op Y.\n//\n// Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source.\n//\n// Example printed form:\n//\n//\tt1 = t0 + 1:int\ntype BinOp struct {\n\tregister\n\t// One of:\n\t// ADD SUB MUL QUO REM          + - * / %\n\t// AND OR XOR SHL SHR AND_NOT   & | ^ << >> &^\n\t// EQL NEQ LSS LEQ GTR GEQ      == != < <= < >=\n\tOp   token.Token\n\tX, Y Value\n}\n\n// The UnOp instruction yields the result of Op X.\n// ARROW is channel receive.\n// MUL is pointer indirection (load).\n// XOR is bitwise complement.\n// SUB is negation.\n// NOT is logical negation.\n//\n// If CommaOk and Op=ARROW, the result is a 2-tuple of the value above\n// and a boolean indicating the success of the receive.  The\n// components of the tuple are accessed using Extract.\n//\n// Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source.\n// For receive operations (ARROW) implicit in ranging over a channel,\n// Pos() returns the ast.RangeStmt.For.\n// For implicit memory loads (STAR), Pos() returns the position of the\n// most closely associated source-level construct; the details are not\n// specified.\n//\n// Example printed form:\n//\n//\tt0 = *x\n//\tt2 = <-t1,ok\ntype UnOp struct {\n\tregister\n\tOp      token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^\n\tX       Value\n\tCommaOk bool\n}\n\n// The ChangeType instruction applies to X a value-preserving type\n// change to Type().\n//\n// Type changes are permitted:\n//   - between a named type and its underlying type.\n//   - between two named types of the same underlying type.\n//   - between (possibly named) pointers to identical base types.\n//   - from a bidirectional channel to a read- or write-channel,\n//     optionally adding/removing a name.\n//   - between a type (t) and an instance of the type (tσ), i.e.\n//     Type() == σ(X.Type()) (or X.Type()== σ(Type())) where\n//     σ is the type substitution of Parent().TypeParams by\n//     Parent().TypeArgs.\n//\n// This operation cannot fail dynamically.\n//\n// Type changes may to be to or from a type parameter (or both). All\n// types in the type set of X.Type() have a value-preserving type\n// change to all types in the type set of Type().\n//\n// Pos() returns the ast.CallExpr.Lparen, if the instruction arose\n// from an explicit conversion in the source.\n//\n// Example printed form:\n//\n//\tt1 = changetype *int <- IntPtr (t0)\ntype ChangeType struct {\n\tregister\n\tX Value\n}\n\n// The Convert instruction yields the conversion of value X to type\n// Type().  One or both of those types is basic (but possibly named).\n//\n// A conversion may change the value and representation of its operand.\n// Conversions are permitted:\n//   - between real numeric types.\n//   - between complex numeric types.\n//   - between string and []byte or []rune.\n//   - between pointers and unsafe.Pointer.\n//   - between unsafe.Pointer and uintptr.\n//   - from (Unicode) integer to (UTF-8) string.\n//\n// A conversion may imply a type name change also.\n//\n// Conversions may to be to or from a type parameter. All types in\n// the type set of X.Type() can be converted to all types in the type\n// set of Type().\n//\n// This operation cannot fail dynamically.\n//\n// Conversions of untyped string/number/bool constants to a specific\n// representation are eliminated during SSA construction.\n//\n// Pos() returns the ast.CallExpr.Lparen, if the instruction arose\n// from an explicit conversion in the source.\n//\n// Example printed form:\n//\n//\tt1 = convert []byte <- string (t0)\ntype Convert struct {\n\tregister\n\tX Value\n}\n\n// The MultiConvert instruction yields the conversion of value X to type\n// Type(). Either X.Type() or Type() must be a type parameter. Each\n// type in the type set of X.Type() can be converted to each type in the\n// type set of Type().\n//\n// See the documentation for Convert, ChangeType, and SliceToArrayPointer\n// for the conversions that are permitted. Additionally conversions of\n// slices to arrays are permitted.\n//\n// This operation can fail dynamically (see SliceToArrayPointer).\n//\n// Pos() returns the ast.CallExpr.Lparen, if the instruction arose\n// from an explicit conversion in the source.\n//\n// Example printed form:\n//\n//\tt1 = multiconvert D <- S (t0) [*[2]rune <- []rune | string <- []rune]\ntype MultiConvert struct {\n\tregister\n\tX        Value\n\tfrom, to types.Type\n}\n\n// ChangeInterface constructs a value of one interface type from a\n// value of another interface type known to be assignable to it.\n// This operation cannot fail.\n//\n// Pos() returns the ast.CallExpr.Lparen if the instruction arose from\n// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the\n// instruction arose from an explicit e.(T) operation; or token.NoPos\n// otherwise.\n//\n// Example printed form:\n//\n//\tt1 = change interface interface{} <- I (t0)\ntype ChangeInterface struct {\n\tregister\n\tX Value\n}\n\n// The SliceToArrayPointer instruction yields the conversion of slice X to\n// array pointer.\n//\n// Pos() returns the ast.CallExpr.Lparen, if the instruction arose\n// from an explicit conversion in the source.\n//\n// Conversion may to be to or from a type parameter. All types in\n// the type set of X.Type() must be a slice types that can be converted to\n// all types in the type set of Type() which must all be pointer to array\n// types.\n//\n// This operation can fail dynamically if the length of the slice is less\n// than the length of the array.\n//\n// Example printed form:\n//\n//\tt1 = slice to array pointer *[4]byte <- []byte (t0)\ntype SliceToArrayPointer struct {\n\tregister\n\tX Value\n}\n\n// MakeInterface constructs an instance of an interface type from a\n// value of a concrete type.\n//\n// Use Program.MethodSets.MethodSet(X.Type()) to find the method-set\n// of X, and Program.MethodValue(m) to find the implementation of a method.\n//\n// To construct the zero value of an interface type T, use:\n//\n//\tNewConst(constant.MakeNil(), T, pos)\n//\n// Pos() returns the ast.CallExpr.Lparen, if the instruction arose\n// from an explicit conversion in the source.\n//\n// Example printed form:\n//\n//\tt1 = make interface{} <- int (42:int)\n//\tt2 = make Stringer <- t0\ntype MakeInterface struct {\n\tregister\n\tX Value\n}\n\n// The MakeClosure instruction yields a closure value whose code is\n// Fn and whose free variables' values are supplied by Bindings.\n//\n// Type() returns a (possibly named) *types.Signature.\n//\n// Pos() returns the ast.FuncLit.Type.Func for a function literal\n// closure or the ast.SelectorExpr.Sel for a bound method closure.\n//\n// Example printed form:\n//\n//\tt0 = make closure anon@1.2 [x y z]\n//\tt1 = make closure bound$(main.I).add [i]\ntype MakeClosure struct {\n\tregister\n\tFn       Value   // always a *Function\n\tBindings []Value // values for each free variable in Fn.FreeVars\n}\n\n// The MakeMap instruction creates a new hash-table-based map object\n// and yields a value of kind map.\n//\n// Type() returns a (possibly named) *types.Map.\n//\n// Pos() returns the ast.CallExpr.Lparen, if created by make(map), or\n// the ast.CompositeLit.Lbrack if created by a literal.\n//\n// Example printed form:\n//\n//\tt1 = make map[string]int t0\n//\tt1 = make StringIntMap t0\ntype MakeMap struct {\n\tregister\n\tReserve Value // initial space reservation; nil => default\n}\n\n// The MakeChan instruction creates a new channel object and yields a\n// value of kind chan.\n//\n// Type() returns a (possibly named) *types.Chan.\n//\n// Pos() returns the ast.CallExpr.Lparen for the make(chan) that\n// created it.\n//\n// Example printed form:\n//\n//\tt0 = make chan int 0\n//\tt0 = make IntChan 0\ntype MakeChan struct {\n\tregister\n\tSize Value // int; size of buffer; zero => synchronous.\n}\n\n// The MakeSlice instruction yields a slice of length Len backed by a\n// newly allocated array of length Cap.\n//\n// Both Len and Cap must be non-nil Values of integer type.\n//\n// (Alloc(types.Array) followed by Slice will not suffice because\n// Alloc can only create arrays of constant length.)\n//\n// Type() returns a (possibly named) *types.Slice.\n//\n// Pos() returns the ast.CallExpr.Lparen for the make([]T) that\n// created it.\n//\n// Example printed form:\n//\n//\tt1 = make []string 1:int t0\n//\tt1 = make StringSlice 1:int t0\ntype MakeSlice struct {\n\tregister\n\tLen Value\n\tCap Value\n}\n\n// The Slice instruction yields a slice of an existing string, slice\n// or *array X between optional integer bounds Low and High.\n//\n// Dynamically, this instruction panics if X evaluates to a nil *array\n// pointer.\n//\n// Type() returns string if the type of X was string, otherwise a\n// *types.Slice with the same element type as X.\n//\n// Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice\n// operation, the ast.CompositeLit.Lbrace if created by a literal, or\n// NoPos if not explicit in the source (e.g. a variadic argument slice).\n//\n// Example printed form:\n//\n//\tt1 = slice t0[1:]\ntype Slice struct {\n\tregister\n\tX              Value // slice, string, or *array\n\tLow, High, Max Value // each may be nil\n}\n\n// The FieldAddr instruction yields the address of Field of *struct X.\n//\n// The field is identified by its index within the field list of the\n// struct type of X.\n//\n// Dynamically, this instruction panics if X evaluates to a nil\n// pointer.\n//\n// Type() returns a (possibly named) *types.Pointer.\n//\n// Pos() returns the position of the ast.SelectorExpr.Sel for the\n// field, if explicit in the source. For implicit selections, returns\n// the position of the inducing explicit selection. If produced for a\n// struct literal S{f: e}, it returns the position of the colon; for\n// S{e} it returns the start of expression e.\n//\n// Example printed form:\n//\n//\tt1 = &t0.name [#1]\ntype FieldAddr struct {\n\tregister\n\tX     Value // *struct\n\tField int   // index into CoreType(CoreType(X.Type()).(*types.Pointer).Elem()).(*types.Struct).Fields\n}\n\n// The Field instruction yields the Field of struct X.\n//\n// The field is identified by its index within the field list of the\n// struct type of X; by using numeric indices we avoid ambiguity of\n// package-local identifiers and permit compact representations.\n//\n// Pos() returns the position of the ast.SelectorExpr.Sel for the\n// field, if explicit in the source. For implicit selections, returns\n// the position of the inducing explicit selection.\n\n// Example printed form:\n//\n//\tt1 = t0.name [#1]\ntype Field struct {\n\tregister\n\tX     Value // struct\n\tField int   // index into CoreType(X.Type()).(*types.Struct).Fields\n}\n\n// The IndexAddr instruction yields the address of the element at\n// index Index of collection X.  Index is an integer expression.\n//\n// The elements of maps and strings are not addressable; use Lookup (map),\n// Index (string), or MapUpdate instead.\n//\n// Dynamically, this instruction panics if X evaluates to a nil *array\n// pointer.\n//\n// Type() returns a (possibly named) *types.Pointer.\n//\n// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if\n// explicit in the source.\n//\n// Example printed form:\n//\n//\tt2 = &t0[t1]\ntype IndexAddr struct {\n\tregister\n\tX     Value // *array, slice or type parameter with types array, *array, or slice.\n\tIndex Value // numeric index\n}\n\n// The Index instruction yields element Index of collection X, an array,\n// string or type parameter containing an array, a string, a pointer to an,\n// array or a slice.\n//\n// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if\n// explicit in the source.\n//\n// Example printed form:\n//\n//\tt2 = t0[t1]\ntype Index struct {\n\tregister\n\tX     Value // array, string or type parameter with types array, *array, slice, or string.\n\tIndex Value // integer index\n}\n\n// The Lookup instruction yields element Index of collection map X.\n// Index is the appropriate key type.\n//\n// If CommaOk, the result is a 2-tuple of the value above and a\n// boolean indicating the result of a map membership test for the key.\n// The components of the tuple are accessed using Extract.\n//\n// Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source.\n//\n// Example printed form:\n//\n//\tt2 = t0[t1]\n//\tt5 = t3[t4],ok\ntype Lookup struct {\n\tregister\n\tX       Value // map\n\tIndex   Value // key-typed index\n\tCommaOk bool  // return a value,ok pair\n}\n\n// SelectState is a helper for Select.\n// It represents one goal state and its corresponding communication.\ntype SelectState struct {\n\tDir       types.ChanDir // direction of case (SendOnly or RecvOnly)\n\tChan      Value         // channel to use (for send or receive)\n\tSend      Value         // value to send (for send)\n\tPos       token.Pos     // position of token.ARROW\n\tDebugNode ast.Node      // ast.SendStmt or ast.UnaryExpr(<-) [debug mode]\n}\n\n// The Select instruction tests whether (or blocks until) one\n// of the specified sent or received states is entered.\n//\n// Let n be the number of States for which Dir==RECV and T_i (0<=i<n)\n// be the element type of each such state's Chan.\n// Select returns an n+2-tuple\n//\n//\t(index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)\n//\n// The tuple's components, described below, must be accessed via the\n// Extract instruction.\n//\n// If Blocking, select waits until exactly one state holds, i.e. a\n// channel becomes ready for the designated operation of sending or\n// receiving; select chooses one among the ready states\n// pseudorandomly, performs the send or receive operation, and sets\n// 'index' to the index of the chosen channel.\n//\n// If !Blocking, select doesn't block if no states hold; instead it\n// returns immediately with index equal to -1.\n//\n// If the chosen channel was used for a receive, the r_i component is\n// set to the received value, where i is the index of that state among\n// all n receive states; otherwise r_i has the zero value of type T_i.\n// Note that the receive index i is not the same as the state\n// index index.\n//\n// The second component of the triple, recvOk, is a boolean whose value\n// is true iff the selected operation was a receive and the receive\n// successfully yielded a value.\n//\n// Pos() returns the ast.SelectStmt.Select.\n//\n// Example printed form:\n//\n//\tt3 = select nonblocking [<-t0, t1<-t2]\n//\tt4 = select blocking []\ntype Select struct {\n\tregister\n\tStates   []*SelectState\n\tBlocking bool\n}\n\n// The Range instruction yields an iterator over the domain and range\n// of X, which must be a string or map.\n//\n// Elements are accessed via Next.\n//\n// Type() returns an opaque and degenerate \"rangeIter\" type.\n//\n// Pos() returns the ast.RangeStmt.For.\n//\n// Example printed form:\n//\n//\tt0 = range \"hello\":string\ntype Range struct {\n\tregister\n\tX Value // string or map\n}\n\n// The Next instruction reads and advances the (map or string)\n// iterator Iter and returns a 3-tuple value (ok, k, v).  If the\n// iterator is not exhausted, ok is true and k and v are the next\n// elements of the domain and range, respectively.  Otherwise ok is\n// false and k and v are undefined.\n//\n// Components of the tuple are accessed using Extract.\n//\n// The IsString field distinguishes iterators over strings from those\n// over maps, as the Type() alone is insufficient: consider\n// map[int]rune.\n//\n// Type() returns a *types.Tuple for the triple (ok, k, v).\n// The types of k and/or v may be types.Invalid.\n//\n// Example printed form:\n//\n//\tt1 = next t0\ntype Next struct {\n\tregister\n\tIter     Value\n\tIsString bool // true => string iterator; false => map iterator.\n}\n\n// The TypeAssert instruction tests whether interface value X has type\n// AssertedType.\n//\n// If !CommaOk, on success it returns v, the result of the conversion\n// (defined below); on failure it panics.\n//\n// If CommaOk: on success it returns a pair (v, true) where v is the\n// result of the conversion; on failure it returns (z, false) where z\n// is AssertedType's zero value.  The components of the pair must be\n// accessed using the Extract instruction.\n//\n// If Underlying: tests whether interface value X has the underlying\n// type AssertedType.\n//\n// If AssertedType is a concrete type, TypeAssert checks whether the\n// dynamic type in interface X is equal to it, and if so, the result\n// of the conversion is a copy of the value in the interface.\n//\n// If AssertedType is an interface, TypeAssert checks whether the\n// dynamic type of the interface is assignable to it, and if so, the\n// result of the conversion is a copy of the interface value X.\n// If AssertedType is a superinterface of X.Type(), the operation will\n// fail iff the operand is nil.  (Contrast with ChangeInterface, which\n// performs no nil-check.)\n//\n// Type() reflects the actual type of the result, possibly a\n// 2-types.Tuple; AssertedType is the asserted type.\n//\n// Depending on the TypeAssert's purpose, Pos may return:\n//   - the ast.CallExpr.Lparen of an explicit T(e) conversion;\n//   - the ast.TypeAssertExpr.Lparen of an explicit e.(T) operation;\n//   - the ast.CaseClause.Case of a case of a type-switch statement;\n//   - the Ident(m).NamePos of an interface method value i.m\n//     (for which TypeAssert may be used to effect the nil check).\n//\n// Example printed form:\n//\n//\tt1 = typeassert t0.(int)\n//\tt3 = typeassert,ok t2.(T)\ntype TypeAssert struct {\n\tregister\n\tX            Value\n\tAssertedType types.Type\n\tCommaOk      bool\n}\n\n// The Extract instruction yields component Index of Tuple.\n//\n// This is used to access the results of instructions with multiple\n// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and\n// IndexExpr(Map).\n//\n// Example printed form:\n//\n//\tt1 = extract t0 #1\ntype Extract struct {\n\tregister\n\tTuple Value\n\tIndex int\n}\n\n// Instructions executed for effect.  They do not yield a value. --------------------\n\n// The Jump instruction transfers control to the sole successor of its\n// owning block.\n//\n// A Jump must be the last instruction of its containing BasicBlock.\n//\n// Pos() returns NoPos.\n//\n// Example printed form:\n//\n//\tjump done\ntype Jump struct {\n\tanInstruction\n}\n\n// The If instruction transfers control to one of the two successors\n// of its owning block, depending on the boolean Cond: the first if\n// true, the second if false.\n//\n// An If instruction must be the last instruction of its containing\n// BasicBlock.\n//\n// Pos() returns NoPos.\n//\n// Example printed form:\n//\n//\tif t0 goto done else body\ntype If struct {\n\tanInstruction\n\tCond Value\n}\n\n// The Return instruction returns values and control back to the calling\n// function.\n//\n// len(Results) is always equal to the number of results in the\n// function's signature.\n//\n// If len(Results) > 1, Return returns a tuple value with the specified\n// components which the caller must access using Extract instructions.\n//\n// There is no instruction to return a ready-made tuple like those\n// returned by a \"value,ok\"-mode TypeAssert, Lookup or UnOp(ARROW) or\n// a tail-call to a function with multiple result parameters.\n//\n// Return must be the last instruction of its containing BasicBlock.\n// Such a block has no successors.\n//\n// Pos() returns the ast.ReturnStmt.Return, if explicit in the source.\n//\n// Example printed form:\n//\n//\treturn\n//\treturn nil:I, 2:int\ntype Return struct {\n\tanInstruction\n\tResults []Value\n\tpos     token.Pos\n}\n\n// The RunDefers instruction pops and invokes the entire stack of\n// procedure calls pushed by Defer instructions in this function.\n//\n// It is legal to encounter multiple 'rundefers' instructions in a\n// single control-flow path through a function; this is useful in\n// the combined init() function, for example.\n//\n// Pos() returns NoPos.\n//\n// Example printed form:\n//\n//\trundefers\ntype RunDefers struct {\n\tanInstruction\n}\n\n// The Panic instruction initiates a panic with value X.\n//\n// A Panic instruction must be the last instruction of its containing\n// BasicBlock, which must have no successors.\n//\n// NB: 'go panic(x)' and 'defer panic(x)' do not use this instruction;\n// they are treated as calls to a built-in function.\n//\n// Pos() returns the ast.CallExpr.Lparen if this panic was explicit\n// in the source.\n//\n// Example printed form:\n//\n//\tpanic t0\ntype Panic struct {\n\tanInstruction\n\tX   Value // an interface{}\n\tpos token.Pos\n}\n\n// The Go instruction creates a new goroutine and calls the specified\n// function within it.\n//\n// See CallCommon for generic function call documentation.\n//\n// Pos() returns the ast.GoStmt.Go.\n//\n// Example printed form:\n//\n//\tgo println(t0, t1)\n//\tgo t3()\n//\tgo invoke t5.Println(...t6)\ntype Go struct {\n\tanInstruction\n\tCall CallCommon\n\tpos  token.Pos\n}\n\n// The Defer instruction pushes the specified call onto a stack of\n// functions to be called by a RunDefers instruction or by a panic.\n//\n// If DeferStack != nil, it indicates the defer list that the defer is\n// added to. Defer list values come from the Builtin function\n// ssa:deferstack. Calls to ssa:deferstack() produces the defer stack\n// of the current function frame. DeferStack allows for deferring into an\n// alternative function stack than the current function.\n//\n// See CallCommon for generic function call documentation.\n//\n// Pos() returns the ast.DeferStmt.Defer.\n//\n// Example printed form:\n//\n//\tdefer println(t0, t1)\n//\tdefer t3()\n//\tdefer invoke t5.Println(...t6)\ntype Defer struct {\n\tanInstruction\n\tCall       CallCommon\n\tDeferStack Value // stack of deferred functions (from ssa:deferstack() intrinsic) onto which this function is pushed\n\tpos        token.Pos\n}\n\n// The Send instruction sends X on channel Chan.\n//\n// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.\n//\n// Example printed form:\n//\n//\tsend t0 <- t1\ntype Send struct {\n\tanInstruction\n\tChan, X Value\n\tpos     token.Pos\n}\n\n// The Store instruction stores Val at address Addr.\n// Stores can be of arbitrary types.\n//\n// Pos() returns the position of the source-level construct most closely\n// associated with the memory store operation.\n// Since implicit memory stores are numerous and varied and depend upon\n// implementation choices, the details are not specified.\n//\n// Example printed form:\n//\n//\t*x = y\ntype Store struct {\n\tanInstruction\n\tAddr Value\n\tVal  Value\n\tpos  token.Pos\n}\n\n// The MapUpdate instruction updates the association of Map[Key] to\n// Value.\n//\n// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,\n// if explicit in the source.\n//\n// Example printed form:\n//\n//\tt0[t1] = t2\ntype MapUpdate struct {\n\tanInstruction\n\tMap   Value\n\tKey   Value\n\tValue Value\n\tpos   token.Pos\n}\n\n// A DebugRef instruction maps a source-level expression Expr to the\n// SSA value X that represents the value (!IsAddr) or address (IsAddr)\n// of that expression.\n//\n// DebugRef is a pseudo-instruction: it has no dynamic effect.\n//\n// Pos() returns Expr.Pos(), the start position of the source-level\n// expression.  This is not the same as the \"designated\" token as\n// documented at Value.Pos(). e.g. CallExpr.Pos() does not return the\n// position of the (\"designated\") Lparen token.\n//\n// If Expr is an *ast.Ident denoting a var or func, Object() returns\n// the object; though this information can be obtained from the type\n// checker, including it here greatly facilitates debugging.\n// For non-Ident expressions, Object() returns nil.\n//\n// DebugRefs are generated only for functions built with debugging\n// enabled; see Package.SetDebugMode() and the GlobalDebug builder\n// mode flag.\n//\n// DebugRefs are not emitted for ast.Idents referring to constants or\n// predeclared identifiers, since they are trivial and numerous.\n// Nor are they emitted for ast.ParenExprs.\n//\n// (By representing these as instructions, rather than out-of-band,\n// consistency is maintained during transformation passes by the\n// ordinary SSA renaming machinery.)\n//\n// Example printed form:\n//\n//\t; *ast.CallExpr @ 102:9 is t5\n//\t; var x float64 @ 109:72 is x\n//\t; address of *ast.CompositeLit @ 216:10 is t0\ntype DebugRef struct {\n\t// TODO(generics): Reconsider what DebugRefs are for generics.\n\tanInstruction\n\tExpr   ast.Expr     // the referring expression (never *ast.ParenExpr)\n\tobject types.Object // the identity of the source var/func\n\tIsAddr bool         // Expr is addressable and X is the address it denotes\n\tX      Value        // the value or address of Expr\n}\n\n// Embeddable mix-ins and helpers for common parts of other structs. -----------\n\n// register is a mix-in embedded by all SSA values that are also\n// instructions, i.e. virtual registers, and provides a uniform\n// implementation of most of the Value interface: Value.Name() is a\n// numbered register (e.g. \"t0\"); the other methods are field accessors.\n//\n// Temporary names are automatically assigned to each register on\n// completion of building a function in SSA form.\n//\n// Clients must not assume that the 'id' value (and the Name() derived\n// from it) is unique within a function.  As always in this API,\n// semantics are determined only by identity; names exist only to\n// facilitate debugging.\ntype register struct {\n\tanInstruction\n\tnum       int        // \"name\" of virtual register, e.g. \"t0\".  Not guaranteed unique.\n\ttyp       types.Type // type of virtual register\n\tpos       token.Pos  // position of source expression, or NoPos\n\treferrers []Instruction\n}\n\n// anInstruction is a mix-in embedded by all Instructions.\n// It provides the implementations of the Block and setBlock methods.\ntype anInstruction struct {\n\tblock *BasicBlock // the basic block of this instruction\n}\n\n// CallCommon is contained by Go, Defer and Call to hold the\n// common parts of a function or method call.\n//\n// Each CallCommon exists in one of two modes, function call and\n// interface method invocation, or \"call\" and \"invoke\" for short.\n//\n// 1. \"call\" mode: when Method is nil (!IsInvoke), a CallCommon\n// represents an ordinary function call of the value in Value,\n// which may be a *Builtin, a *Function or any other value of kind\n// 'func'.\n//\n// Value may be one of:\n//\n//\t(a) a *Function, indicating a statically dispatched call\n//\t    to a package-level function, an anonymous function, or\n//\t    a method of a named type.\n//\t(b) a *MakeClosure, indicating an immediately applied\n//\t    function literal with free variables.\n//\t(c) a *Builtin, indicating a statically dispatched call\n//\t    to a built-in function.\n//\t(d) any other value, indicating a dynamically dispatched\n//\t    function call.\n//\n// StaticCallee returns the identity of the callee in cases\n// (a) and (b), nil otherwise.\n//\n// Args contains the arguments to the call.  If Value is a method,\n// Args[0] contains the receiver parameter.\n//\n// Example printed form:\n//\n//\tt2 = println(t0, t1)\n//\tgo t3()\n//\tdefer t5(...t6)\n//\n// 2. \"invoke\" mode: when Method is non-nil (IsInvoke), a CallCommon\n// represents a dynamically dispatched call to an interface method.\n// In this mode, Value is the interface value and Method is the\n// interface's abstract method. The interface value may be a type\n// parameter. Note: an interface method may be shared by multiple\n// interfaces due to embedding; Value.Type() provides the specific\n// interface used for this call.\n//\n// Value is implicitly supplied to the concrete method implementation\n// as the receiver parameter; in other words, Args[0] holds not the\n// receiver but the first true argument.\n//\n// Example printed form:\n//\n//\tt1 = invoke t0.String()\n//\tgo invoke t3.Run(t2)\n//\tdefer invoke t4.Handle(...t5)\n//\n// For all calls to variadic functions (Signature().Variadic()),\n// the last element of Args is a slice.\ntype CallCommon struct {\n\tValue  Value       // receiver (invoke mode) or func value (call mode)\n\tMethod *types.Func // interface method (invoke mode)\n\tArgs   []Value     // actual parameters (in static method call, includes receiver)\n\tpos    token.Pos   // position of CallExpr.Lparen, iff explicit in source\n}\n\n// IsInvoke returns true if this call has \"invoke\" (not \"call\") mode.\nfunc (c *CallCommon) IsInvoke() bool {\n\treturn c.Method != nil\n}\n\nfunc (c *CallCommon) Pos() token.Pos { return c.pos }\n\n// Signature returns the signature of the called function.\n//\n// For an \"invoke\"-mode call, the signature of the interface method is\n// returned.\n//\n// In either \"call\" or \"invoke\" mode, if the callee is a method, its\n// receiver is represented by sig.Recv, not sig.Params().At(0).\nfunc (c *CallCommon) Signature() *types.Signature {\n\tif c.Method != nil {\n\t\treturn c.Method.Type().(*types.Signature)\n\t}\n\treturn typeparams.CoreType(c.Value.Type()).(*types.Signature)\n}\n\n// StaticCallee returns the callee if this is a trivially static\n// \"call\"-mode call to a function.\nfunc (c *CallCommon) StaticCallee() *Function {\n\tswitch fn := c.Value.(type) {\n\tcase *Function:\n\t\treturn fn\n\tcase *MakeClosure:\n\t\treturn fn.Fn.(*Function)\n\t}\n\treturn nil\n}\n\n// Description returns a description of the mode of this call suitable\n// for a user interface, e.g., \"static method call\".\nfunc (c *CallCommon) Description() string {\n\tswitch fn := c.Value.(type) {\n\tcase *Builtin:\n\t\treturn \"built-in function call\"\n\tcase *MakeClosure:\n\t\treturn \"static function closure call\"\n\tcase *Function:\n\t\tif fn.Signature.Recv() != nil {\n\t\t\treturn \"static method call\"\n\t\t}\n\t\treturn \"static function call\"\n\t}\n\tif c.IsInvoke() {\n\t\treturn \"dynamic method call\" // (\"invoke\" mode)\n\t}\n\treturn \"dynamic function call\"\n}\n\n// The CallInstruction interface, implemented by *Go, *Defer and *Call,\n// exposes the common parts of function-calling instructions,\n// yet provides a way back to the Value defined by *Call alone.\ntype CallInstruction interface {\n\tInstruction\n\tCommon() *CallCommon // returns the common parts of the call\n\tValue() *Call        // returns the result value of the call (*Call) or nil (*Go, *Defer)\n}\n\nfunc (s *Call) Common() *CallCommon  { return &s.Call }\nfunc (s *Defer) Common() *CallCommon { return &s.Call }\nfunc (s *Go) Common() *CallCommon    { return &s.Call }\n\nfunc (s *Call) Value() *Call  { return s }\nfunc (s *Defer) Value() *Call { return nil }\nfunc (s *Go) Value() *Call    { return nil }\n\nfunc (v *Builtin) Type() types.Type        { return v.sig }\nfunc (v *Builtin) Name() string            { return v.name }\nfunc (*Builtin) Referrers() *[]Instruction { return nil }\nfunc (v *Builtin) Pos() token.Pos          { return token.NoPos }\nfunc (v *Builtin) Object() types.Object    { return types.Universe.Lookup(v.name) }\nfunc (v *Builtin) Parent() *Function       { return nil }\n\nfunc (v *FreeVar) Type() types.Type          { return v.typ }\nfunc (v *FreeVar) Name() string              { return v.name }\nfunc (v *FreeVar) Referrers() *[]Instruction { return &v.referrers }\nfunc (v *FreeVar) Pos() token.Pos            { return v.pos }\nfunc (v *FreeVar) Parent() *Function         { return v.parent }\n\nfunc (v *Global) Type() types.Type                     { return v.typ }\nfunc (v *Global) Name() string                         { return v.name }\nfunc (v *Global) Parent() *Function                    { return nil }\nfunc (v *Global) Pos() token.Pos                       { return v.pos }\nfunc (v *Global) Referrers() *[]Instruction            { return nil }\nfunc (v *Global) Token() token.Token                   { return token.VAR }\nfunc (v *Global) Object() types.Object                 { return v.object }\nfunc (v *Global) String() string                       { return v.RelString(nil) }\nfunc (v *Global) Package() *Package                    { return v.Pkg }\nfunc (v *Global) RelString(from *types.Package) string { return relString(v, from) }\n\nfunc (v *Function) Name() string       { return v.name }\nfunc (v *Function) Type() types.Type   { return v.Signature }\nfunc (v *Function) Pos() token.Pos     { return v.pos }\nfunc (v *Function) Token() token.Token { return token.FUNC }\nfunc (v *Function) Object() types.Object {\n\tif v.object != nil {\n\t\treturn types.Object(v.object)\n\t}\n\treturn nil\n}\nfunc (v *Function) String() string    { return v.RelString(nil) }\nfunc (v *Function) Package() *Package { return v.Pkg }\nfunc (v *Function) Parent() *Function { return v.parent }\nfunc (v *Function) Referrers() *[]Instruction {\n\tif v.parent != nil {\n\t\treturn &v.referrers\n\t}\n\treturn nil\n}\n\n// TypeParams are the function's type parameters if generic or the\n// type parameters that were instantiated if fn is an instantiation.\nfunc (fn *Function) TypeParams() *types.TypeParamList {\n\treturn fn.typeparams\n}\n\n// TypeArgs are the types that TypeParams() were instantiated by to create fn\n// from fn.Origin().\nfunc (fn *Function) TypeArgs() []types.Type { return fn.typeargs }\n\n// Origin returns the generic function from which fn was instantiated,\n// or nil if fn is not an instantiation.\nfunc (fn *Function) Origin() *Function {\n\tif fn.parent != nil && len(fn.typeargs) > 0 {\n\t\t// Nested functions are BUILT at a different time than their instances.\n\t\t// Build declared package if not yet BUILT. This is not an expected use\n\t\t// case, but is simple and robust.\n\t\tfn.declaredPackage().Build()\n\t}\n\treturn origin(fn)\n}\n\n// origin is the function that fn is an instantiation of. Returns nil if fn is\n// not an instantiation.\n//\n// Precondition: fn and the origin function are done building.\nfunc origin(fn *Function) *Function {\n\tif fn.parent != nil && len(fn.typeargs) > 0 {\n\t\treturn origin(fn.parent).AnonFuncs[fn.anonIdx]\n\t}\n\treturn fn.topLevelOrigin\n}\n\nfunc (v *Parameter) Type() types.Type          { return v.typ }\nfunc (v *Parameter) Name() string              { return v.name }\nfunc (v *Parameter) Object() types.Object      { return v.object }\nfunc (v *Parameter) Referrers() *[]Instruction { return &v.referrers }\nfunc (v *Parameter) Pos() token.Pos            { return v.object.Pos() }\nfunc (v *Parameter) Parent() *Function         { return v.parent }\n\nfunc (v *Alloc) Type() types.Type          { return v.typ }\nfunc (v *Alloc) Referrers() *[]Instruction { return &v.referrers }\nfunc (v *Alloc) Pos() token.Pos            { return v.pos }\n\nfunc (v *register) Type() types.Type          { return v.typ }\nfunc (v *register) setType(typ types.Type)    { v.typ = typ }\nfunc (v *register) Name() string              { return fmt.Sprintf(\"t%d\", v.num) }\nfunc (v *register) setNum(num int)            { v.num = num }\nfunc (v *register) Referrers() *[]Instruction { return &v.referrers }\nfunc (v *register) Pos() token.Pos            { return v.pos }\nfunc (v *register) setPos(pos token.Pos)      { v.pos = pos }\n\nfunc (v *anInstruction) Parent() *Function          { return v.block.parent }\nfunc (v *anInstruction) Block() *BasicBlock         { return v.block }\nfunc (v *anInstruction) setBlock(block *BasicBlock) { v.block = block }\nfunc (v *anInstruction) Referrers() *[]Instruction  { return nil }\n\nfunc (t *Type) Name() string                         { return t.object.Name() }\nfunc (t *Type) Pos() token.Pos                       { return t.object.Pos() }\nfunc (t *Type) Type() types.Type                     { return t.object.Type() }\nfunc (t *Type) Token() token.Token                   { return token.TYPE }\nfunc (t *Type) Object() types.Object                 { return t.object }\nfunc (t *Type) String() string                       { return t.RelString(nil) }\nfunc (t *Type) Package() *Package                    { return t.pkg }\nfunc (t *Type) RelString(from *types.Package) string { return relString(t, from) }\n\nfunc (c *NamedConst) Name() string                         { return c.object.Name() }\nfunc (c *NamedConst) Pos() token.Pos                       { return c.object.Pos() }\nfunc (c *NamedConst) String() string                       { return c.RelString(nil) }\nfunc (c *NamedConst) Type() types.Type                     { return c.object.Type() }\nfunc (c *NamedConst) Token() token.Token                   { return token.CONST }\nfunc (c *NamedConst) Object() types.Object                 { return c.object }\nfunc (c *NamedConst) Package() *Package                    { return c.pkg }\nfunc (c *NamedConst) RelString(from *types.Package) string { return relString(c, from) }\n\nfunc (d *DebugRef) Object() types.Object { return d.object }\n\n// Func returns the package-level function of the specified name,\n// or nil if not found.\nfunc (p *Package) Func(name string) (f *Function) {\n\tf, _ = p.Members[name].(*Function)\n\treturn\n}\n\n// Var returns the package-level variable of the specified name,\n// or nil if not found.\nfunc (p *Package) Var(name string) (g *Global) {\n\tg, _ = p.Members[name].(*Global)\n\treturn\n}\n\n// Const returns the package-level constant of the specified name,\n// or nil if not found.\nfunc (p *Package) Const(name string) (c *NamedConst) {\n\tc, _ = p.Members[name].(*NamedConst)\n\treturn\n}\n\n// Type returns the package-level type of the specified name,\n// or nil if not found.\nfunc (p *Package) Type(name string) (t *Type) {\n\tt, _ = p.Members[name].(*Type)\n\treturn\n}\n\nfunc (v *Call) Pos() token.Pos      { return v.Call.pos }\nfunc (s *Defer) Pos() token.Pos     { return s.pos }\nfunc (s *Go) Pos() token.Pos        { return s.pos }\nfunc (s *MapUpdate) Pos() token.Pos { return s.pos }\nfunc (s *Panic) Pos() token.Pos     { return s.pos }\nfunc (s *Return) Pos() token.Pos    { return s.pos }\nfunc (s *Send) Pos() token.Pos      { return s.pos }\nfunc (s *Store) Pos() token.Pos     { return s.pos }\nfunc (s *If) Pos() token.Pos        { return token.NoPos }\nfunc (s *Jump) Pos() token.Pos      { return token.NoPos }\nfunc (s *RunDefers) Pos() token.Pos { return token.NoPos }\nfunc (s *DebugRef) Pos() token.Pos  { return s.Expr.Pos() }\n\n// Operands.\n\nfunc (v *Alloc) Operands(rands []*Value) []*Value {\n\treturn rands\n}\n\nfunc (v *BinOp) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X, &v.Y)\n}\n\nfunc (c *CallCommon) Operands(rands []*Value) []*Value {\n\trands = append(rands, &c.Value)\n\tfor i := range c.Args {\n\t\trands = append(rands, &c.Args[i])\n\t}\n\treturn rands\n}\n\nfunc (s *Go) Operands(rands []*Value) []*Value {\n\treturn s.Call.Operands(rands)\n}\n\nfunc (s *Call) Operands(rands []*Value) []*Value {\n\treturn s.Call.Operands(rands)\n}\n\nfunc (s *Defer) Operands(rands []*Value) []*Value {\n\treturn append(s.Call.Operands(rands), &s.DeferStack)\n}\n\nfunc (v *ChangeInterface) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *ChangeType) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *Convert) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *MultiConvert) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *SliceToArrayPointer) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (s *DebugRef) Operands(rands []*Value) []*Value {\n\treturn append(rands, &s.X)\n}\n\nfunc (v *Extract) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Tuple)\n}\n\nfunc (v *Field) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *FieldAddr) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (s *If) Operands(rands []*Value) []*Value {\n\treturn append(rands, &s.Cond)\n}\n\nfunc (v *Index) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X, &v.Index)\n}\n\nfunc (v *IndexAddr) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X, &v.Index)\n}\n\nfunc (*Jump) Operands(rands []*Value) []*Value {\n\treturn rands\n}\n\nfunc (v *Lookup) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X, &v.Index)\n}\n\nfunc (v *MakeChan) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Size)\n}\n\nfunc (v *MakeClosure) Operands(rands []*Value) []*Value {\n\trands = append(rands, &v.Fn)\n\tfor i := range v.Bindings {\n\t\trands = append(rands, &v.Bindings[i])\n\t}\n\treturn rands\n}\n\nfunc (v *MakeInterface) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *MakeMap) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Reserve)\n}\n\nfunc (v *MakeSlice) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Len, &v.Cap)\n}\n\nfunc (v *MapUpdate) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Map, &v.Key, &v.Value)\n}\n\nfunc (v *Next) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.Iter)\n}\n\nfunc (s *Panic) Operands(rands []*Value) []*Value {\n\treturn append(rands, &s.X)\n}\n\nfunc (v *Phi) Operands(rands []*Value) []*Value {\n\tfor i := range v.Edges {\n\t\trands = append(rands, &v.Edges[i])\n\t}\n\treturn rands\n}\n\nfunc (v *Range) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (s *Return) Operands(rands []*Value) []*Value {\n\tfor i := range s.Results {\n\t\trands = append(rands, &s.Results[i])\n\t}\n\treturn rands\n}\n\nfunc (*RunDefers) Operands(rands []*Value) []*Value {\n\treturn rands\n}\n\nfunc (v *Select) Operands(rands []*Value) []*Value {\n\tfor i := range v.States {\n\t\trands = append(rands, &v.States[i].Chan, &v.States[i].Send)\n\t}\n\treturn rands\n}\n\nfunc (s *Send) Operands(rands []*Value) []*Value {\n\treturn append(rands, &s.Chan, &s.X)\n}\n\nfunc (v *Slice) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X, &v.Low, &v.High, &v.Max)\n}\n\nfunc (s *Store) Operands(rands []*Value) []*Value {\n\treturn append(rands, &s.Addr, &s.Val)\n}\n\nfunc (v *TypeAssert) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\nfunc (v *UnOp) Operands(rands []*Value) []*Value {\n\treturn append(rands, &v.X)\n}\n\n// Non-Instruction Values:\nfunc (v *Builtin) Operands(rands []*Value) []*Value   { return rands }\nfunc (v *FreeVar) Operands(rands []*Value) []*Value   { return rands }\nfunc (v *Const) Operands(rands []*Value) []*Value     { return rands }\nfunc (v *Function) Operands(rands []*Value) []*Value  { return rands }\nfunc (v *Global) Operands(rands []*Value) []*Value    { return rands }\nfunc (v *Parameter) Operands(rands []*Value) []*Value { return rands }\n"
  },
  {
    "path": "go/ssa/ssautil/deprecated.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil\n\n// This file contains deprecated public APIs.\n// We discourage their use.\n\nimport (\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// CreateProgram returns a new program in SSA form, given a program\n// loaded from source.  An SSA package is created for each transitively\n// error-free package of lprog.\n//\n// Code for bodies of functions is not built until Build is called\n// on the result.\n//\n// The mode parameter controls diagnostics and checking during SSA construction.\n//\n// Deprecated: Use [golang.org/x/tools/go/packages] and the [Packages]\n// function instead; see ssa.Example_loadPackages.\nfunc CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program {\n\tprog := ssa.NewProgram(lprog.Fset, mode)\n\n\tfor _, info := range lprog.AllPackages {\n\t\tif info.TransitivelyErrorFree {\n\t\t\tprog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable)\n\t\t}\n\t}\n\n\treturn prog\n}\n"
  },
  {
    "path": "go/ssa/ssautil/deprecated_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil_test\n\n// Tests of deprecated public APIs.\n// We are keeping some tests around to have some test of the public API.\n\nimport (\n\t\"go/parser\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestCreateProgram tests CreateProgram which has an x/tools/go/loader.Program.\nfunc TestCreateProgram(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for importer.Default()\n\n\tconf := loader.Config{ParserMode: parser.ParseComments}\n\tf, err := conf.ParseFile(\"hello.go\", hello)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconf.CreateFromFiles(\"main\", f)\n\tiprog, err := conf.Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(iprog.Created) != 1 {\n\t\tt.Fatalf(\"Expected 1 Created package. got %d\", len(iprog.Created))\n\t}\n\tpkg := iprog.Created[0].Pkg\n\n\tprog := ssautil.CreateProgram(iprog, ssa.BuilderMode(0))\n\tssapkg := prog.Package(pkg)\n\tssapkg.Build()\n\n\tif pkg.Name() != \"main\" {\n\t\tt.Errorf(\"pkg.Name() = %s, want main\", pkg.Name())\n\t}\n\tif ssapkg.Func(\"main\") == nil {\n\t\tssapkg.WriteTo(os.Stderr)\n\t\tt.Errorf(\"ssapkg has no main function\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/ssautil/load.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil\n\n// This file defines utility functions for constructing programs in SSA form.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// Packages creates an SSA program for a set of packages.\n//\n// The packages must have been loaded from source syntax using the\n// [packages.Load] function in [packages.LoadSyntax] or\n// [packages.LoadAllSyntax] mode.\n//\n// Packages creates an SSA package for each well-typed package in the\n// initial list, plus all their dependencies. The resulting list of\n// packages corresponds to the list of initial packages, and may contain\n// a nil if SSA code could not be constructed for the corresponding initial\n// package due to type errors.\n//\n// Code for bodies of functions is not built until [Program.Build] is\n// called on the resulting Program. SSA code is constructed only for\n// the initial packages with well-typed syntax trees.\n//\n// The mode parameter controls diagnostics and checking during SSA construction.\nfunc Packages(initial []*packages.Package, mode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {\n\t// TODO(adonovan): opt: this calls CreatePackage far more than\n\t// necessary: for all dependencies, not just the (non-initial)\n\t// direct dependencies of the initial packages.\n\t//\n\t// But can it reasonably be changed without breaking the\n\t// spirit and/or letter of the law above? Clients may notice\n\t// if we call CreatePackage less, as methods like\n\t// Program.FuncValue will return nil. Or must we provide a new\n\t// function (and perhaps deprecate this one)? Is it worth it?\n\t//\n\t// Tim King makes the interesting point that it would be\n\t// possible to entirely alleviate the client from the burden\n\t// of calling CreatePackage for non-syntax packages, if we\n\t// were to treat vars and funcs lazily in the same way we now\n\t// treat methods. (In essence, try to move away from the\n\t// notion of ssa.Packages, and make the Program answer\n\t// all reasonable questions about any types.Object.)\n\n\treturn doPackages(initial, mode, false)\n}\n\n// AllPackages creates an SSA program for a set of packages plus all\n// their dependencies.\n//\n// The packages must have been loaded from source syntax using the\n// [packages.Load] function in [packages.LoadAllSyntax] mode.\n//\n// AllPackages creates an SSA package for each well-typed package in the\n// initial list, plus all their dependencies. The resulting list of\n// packages corresponds to the list of initial packages, and may contain\n// a nil if SSA code could not be constructed for the corresponding\n// initial package due to type errors.\n//\n// Code for bodies of functions is not built until Build is called on\n// the resulting Program. SSA code is constructed for all packages with\n// well-typed syntax trees.\n//\n// The mode parameter controls diagnostics and checking during SSA construction.\nfunc AllPackages(initial []*packages.Package, mode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {\n\treturn doPackages(initial, mode, true)\n}\n\nfunc doPackages(initial []*packages.Package, mode ssa.BuilderMode, deps bool) (*ssa.Program, []*ssa.Package) {\n\n\tvar fset *token.FileSet\n\tif len(initial) > 0 {\n\t\tfset = initial[0].Fset\n\t}\n\n\tprog := ssa.NewProgram(fset, mode)\n\n\tisInitial := make(map[*packages.Package]bool, len(initial))\n\tfor _, p := range initial {\n\t\tisInitial[p] = true\n\t}\n\n\tssamap := make(map[*packages.Package]*ssa.Package)\n\tpackages.Visit(initial, nil, func(p *packages.Package) {\n\t\tif p.Types != nil && !p.IllTyped {\n\t\t\tvar files []*ast.File\n\t\t\tvar info *types.Info\n\t\t\tif deps || isInitial[p] {\n\t\t\t\tfiles = p.Syntax\n\t\t\t\tinfo = p.TypesInfo\n\t\t\t}\n\t\t\tssamap[p] = prog.CreatePackage(p.Types, files, info, true)\n\t\t}\n\t})\n\n\tvar ssapkgs []*ssa.Package\n\tfor _, p := range initial {\n\t\tssapkgs = append(ssapkgs, ssamap[p]) // may be nil\n\t}\n\treturn prog, ssapkgs\n}\n\n// BuildPackage builds an SSA program with SSA intermediate\n// representation (IR) for all functions of a single package.\n//\n// It populates pkg by type-checking the specified file syntax trees.  All\n// dependencies are loaded using the importer specified by tc, which\n// typically loads compiler export data; SSA code cannot be built for\n// those packages.  BuildPackage then constructs an [ssa.Program] with all\n// dependency packages created, and builds and returns the SSA package\n// corresponding to pkg.\n//\n// The caller must have set pkg.Path to the import path.\n//\n// The operation fails if there were any type-checking or import errors.\n//\n// See ../example_test.go for an example.\nfunc BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {\n\tif fset == nil {\n\t\tpanic(\"no token.FileSet\")\n\t}\n\tif pkg.Path() == \"\" {\n\t\tpanic(\"package has no import path\")\n\t}\n\n\tinfo := &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\tif err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tprog := ssa.NewProgram(fset, mode)\n\n\t// Create SSA packages for all imports.\n\t// Order is not significant.\n\tcreated := make(map[*types.Package]bool)\n\tvar createAll func(pkgs []*types.Package)\n\tcreateAll = func(pkgs []*types.Package) {\n\t\tfor _, p := range pkgs {\n\t\t\tif !created[p] {\n\t\t\t\tcreated[p] = true\n\t\t\t\tprog.CreatePackage(p, nil, nil, true)\n\t\t\t\tcreateAll(p.Imports())\n\t\t\t}\n\t\t}\n\t}\n\tcreateAll(pkg.Imports())\n\n\t// TODO(adonovan): we could replace createAll with just:\n\t//\n\t// // Create SSA packages for all imports.\n\t// for _, p := range pkg.Imports() {\n\t// \tprog.CreatePackage(p, nil, nil, true)\n\t// }\n\t//\n\t// (with minor changes to changes to ../builder_test.go as\n\t// shown in CL 511715 PS 10.) But this would strictly violate\n\t// the letter of the doc comment above, which says \"all\n\t// dependencies created\".\n\t//\n\t// Tim makes the good point with some extra work we could\n\t// remove the need for any CreatePackage calls except the\n\t// ones with syntax (i.e. primary packages). Of course\n\t// You wouldn't have ssa.Packages and Members for as\n\t// many things but no-one really uses that anyway.\n\t// I wish I had done this from the outset.\n\n\t// Create and build the primary package.\n\tssapkg := prog.CreatePackage(pkg, files, info, false)\n\tssapkg.Build()\n\treturn ssapkg, info, nil\n}\n"
  },
  {
    "path": "go/ssa/ssautil/load_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil_test\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/packagestest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nconst hello = `package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, world\")\n}\n`\n\nfunc TestBuildPackage(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // for importer.Default()\n\n\t// There is a more substantial test of BuildPackage and the\n\t// SSA program it builds in ../ssa/builder_test.go.\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", hello, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, mode := range []ssa.BuilderMode{\n\t\tssa.SanityCheckFunctions,\n\t\tssa.InstantiateGenerics | ssa.SanityCheckFunctions,\n\t} {\n\t\tpkg := types.NewPackage(\"hello\", \"\")\n\t\tssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, mode)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif pkg.Name() != \"main\" {\n\t\t\tt.Errorf(\"pkg.Name() = %s, want main\", pkg.Name())\n\t\t}\n\t\tif ssapkg.Func(\"main\") == nil {\n\t\t\tssapkg.WriteTo(os.Stderr)\n\t\t\tt.Errorf(\"ssapkg has no main function\")\n\t\t}\n\n\t}\n}\n\nfunc TestPackages(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tcfg := &packages.Config{Mode: packages.LoadSyntax}\n\tinitial, err := packages.Load(cfg, \"bytes\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif packages.PrintErrors(initial) > 0 {\n\t\tt.Fatal(\"there were errors\")\n\t}\n\n\tfor _, mode := range []ssa.BuilderMode{\n\t\tssa.SanityCheckFunctions,\n\t\tssa.SanityCheckFunctions | ssa.InstantiateGenerics,\n\t} {\n\t\tprog, pkgs := ssautil.Packages(initial, mode)\n\t\tbytesNewBuffer := pkgs[0].Func(\"NewBuffer\")\n\t\tbytesNewBuffer.Pkg.Build()\n\n\t\t// We'll dump the SSA of bytes.NewBuffer because it is small and stable.\n\t\tout := new(bytes.Buffer)\n\t\tbytesNewBuffer.WriteTo(out)\n\n\t\t// For determinism, sanitize the location.\n\t\tlocation := prog.Fset.Position(bytesNewBuffer.Pos()).String()\n\t\tgot := strings.Replace(out.String(), location, \"$GOROOT/src/bytes/buffer.go:1\", -1)\n\n\t\twant := `\n# Name: bytes.NewBuffer\n# Package: bytes\n# Location: $GOROOT/src/bytes/buffer.go:1\nfunc NewBuffer(buf []byte) *Buffer:\n0:                                                                entry P:0 S:0\n\tt0 = new Buffer (complit)                                       *Buffer\n\tt1 = &t0.buf [#0]                                               *[]byte\n\t*t1 = buf\n\treturn t0\n\n`[1:]\n\t\tif got != want {\n\t\t\tt.Errorf(\"bytes.NewBuffer SSA = <<%s>>, want <<%s>>\", got, want)\n\t\t}\n\t}\n}\n\nfunc TestBuildPackage_MissingImport(t *testing.T) {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"bad.go\", `package bad; import \"missing\"`, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tpkg := types.NewPackage(\"bad\", \"\")\n\tssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, ssa.BuilderMode(0))\n\tif err == nil || ssapkg != nil {\n\t\tt.Fatal(\"BuildPackage succeeded unexpectedly\")\n\t}\n}\n\nfunc TestIssue28106(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\t// In go1.10, go/packages loads all packages from source, not\n\t// export data, but does not type check function bodies of\n\t// imported packages. This test ensures that we do not attempt\n\t// to run the SSA builder on functions without type information.\n\tcfg := &packages.Config{Mode: packages.LoadSyntax}\n\tpkgs, err := packages.Load(cfg, \"runtime\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tprog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))\n\tprog.Build() // no crash\n}\n\nfunc TestIssue53604(t *testing.T) {\n\t// Tests that variable initializers are not added to init() when syntax\n\t// is not present but types.Info is available.\n\t//\n\t// Packages x, y, z are loaded with mode `packages.LoadSyntax`.\n\t// Package x imports y, and y imports z.\n\t// Packages are built using ssautil.Packages() with x and z as roots.\n\t// This setup creates y using CreatePackage(pkg, files, info, ...)\n\t// where len(files) == 0 but info != nil.\n\t//\n\t// Tests that globals from y are not initialized.\n\te := packagestest.Export(t, packagestest.Modules, []packagestest.Module{\n\t\t{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: map[string]any{\n\t\t\t\t\"x/x.go\": `package x; import \"golang.org/fake/y\"; var V = y.F()`,\n\t\t\t\t\"y/y.go\": `package y; import \"golang.org/fake/z\"; var F = func () *int { return &z.Z } `,\n\t\t\t\t\"z/z.go\": `package z; var Z int`,\n\t\t\t},\n\t\t},\n\t})\n\tdefer e.Cleanup()\n\n\t// Load x and z as entry packages using packages.LoadSyntax\n\te.Config.Mode = packages.LoadSyntax\n\tpkgs, err := packages.Load(e.Config, path.Join(e.Temp(), \"fake/x\"), path.Join(e.Temp(), \"fake/z\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, p := range pkgs {\n\t\tif len(p.Errors) > 0 {\n\t\t\tt.Fatalf(\"%v\", p.Errors)\n\t\t}\n\t}\n\n\tprog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))\n\tprog.Build()\n\n\t// y does not initialize F.\n\ty := prog.ImportedPackage(\"golang.org/fake/y\")\n\tif y == nil {\n\t\tt.Fatal(\"Failed to load intermediate package y\")\n\t}\n\tyinit := y.Members[\"init\"].(*ssa.Function)\n\tfor _, bb := range yinit.Blocks {\n\t\tfor _, i := range bb.Instrs {\n\t\t\tif store, ok := i.(*ssa.Store); ok && store.Addr == y.Var(\"F\") {\n\t\t\t\tt.Errorf(\"y.init() stores to F %v\", store)\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "go/ssa/ssautil/switch.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil\n\n// This file implements discovery of switch and type-switch constructs\n// from low-level control flow.\n//\n// Many techniques exist for compiling a high-level switch with\n// constant cases to efficient machine code.  The optimal choice will\n// depend on the data type, the specific case values, the code in the\n// body of each case, and the hardware.\n// Some examples:\n// - a lookup table (for a switch that maps constants to constants)\n// - a computed goto\n// - a binary tree\n// - a perfect hash\n// - a two-level switch (to partition constant strings by their first byte).\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// A ConstCase represents a single constant comparison.\n// It is part of a Switch.\ntype ConstCase struct {\n\tBlock *ssa.BasicBlock // block performing the comparison\n\tBody  *ssa.BasicBlock // body of the case\n\tValue *ssa.Const      // case comparand\n}\n\n// A TypeCase represents a single type assertion.\n// It is part of a Switch.\ntype TypeCase struct {\n\tBlock   *ssa.BasicBlock // block performing the type assert\n\tBody    *ssa.BasicBlock // body of the case\n\tType    types.Type      // case type\n\tBinding ssa.Value       // value bound by this case\n}\n\n// A Switch is a logical high-level control flow operation\n// (a multiway branch) discovered by analysis of a CFG containing\n// only if/else chains.  It is not part of the ssa.Instruction set.\n//\n// One of ConstCases and TypeCases has length >= 2;\n// the other is nil.\n//\n// In a value switch, the list of cases may contain duplicate constants.\n// A type switch may contain duplicate types, or types assignable\n// to an interface type also in the list.\n// TODO(adonovan): eliminate such duplicates.\ntype Switch struct {\n\tStart      *ssa.BasicBlock // block containing start of if/else chain\n\tX          ssa.Value       // the switch operand\n\tConstCases []ConstCase     // ordered list of constant comparisons\n\tTypeCases  []TypeCase      // ordered list of type assertions\n\tDefault    *ssa.BasicBlock // successor if all comparisons fail\n}\n\nfunc (sw *Switch) String() string {\n\t// We represent each block by the String() of its\n\t// first Instruction, e.g. \"print(42:int)\".\n\tvar buf bytes.Buffer\n\tif sw.ConstCases != nil {\n\t\tfmt.Fprintf(&buf, \"switch %s {\\n\", sw.X.Name())\n\t\tfor _, c := range sw.ConstCases {\n\t\t\tfmt.Fprintf(&buf, \"case %s: %s\\n\", c.Value, c.Body.Instrs[0])\n\t\t}\n\t} else {\n\t\tfmt.Fprintf(&buf, \"switch %s.(type) {\\n\", sw.X.Name())\n\t\tfor _, c := range sw.TypeCases {\n\t\t\tfmt.Fprintf(&buf, \"case %s %s: %s\\n\",\n\t\t\t\tc.Binding.Name(), c.Type, c.Body.Instrs[0])\n\t\t}\n\t}\n\tif sw.Default != nil {\n\t\tfmt.Fprintf(&buf, \"default: %s\\n\", sw.Default.Instrs[0])\n\t}\n\tfmt.Fprintf(&buf, \"}\")\n\treturn buf.String()\n}\n\n// Switches examines the control-flow graph of fn and returns the\n// set of inferred value and type switches.  A value switch tests an\n// ssa.Value for equality against two or more compile-time constant\n// values.  Switches involving link-time constants (addresses) are\n// ignored.  A type switch type-asserts an ssa.Value against two or\n// more types.\n//\n// The switches are returned in dominance order.\n//\n// The resulting switches do not necessarily correspond to uses of the\n// 'switch' keyword in the source: for example, a single source-level\n// switch statement with non-constant cases may result in zero, one or\n// many Switches, one per plural sequence of constant cases.\n// Switches may even be inferred from if/else- or goto-based control flow.\n// (In general, the control flow constructs of the source program\n// cannot be faithfully reproduced from the SSA representation.)\nfunc Switches(fn *ssa.Function) []Switch {\n\t// Traverse the CFG in dominance order, so we don't\n\t// enter an if/else-chain in the middle.\n\tvar switches []Switch\n\tseen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet\n\tfor _, b := range fn.DomPreorder() {\n\t\tif x, k := isComparisonBlock(b); x != nil {\n\t\t\t// Block b starts a switch.\n\t\t\tsw := Switch{Start: b, X: x}\n\t\t\tvalueSwitch(&sw, k, seen)\n\t\t\tif len(sw.ConstCases) > 1 {\n\t\t\t\tswitches = append(switches, sw)\n\t\t\t}\n\t\t}\n\n\t\tif y, x, T := isTypeAssertBlock(b); y != nil {\n\t\t\t// Block b starts a type switch.\n\t\t\tsw := Switch{Start: b, X: x}\n\t\t\ttypeSwitch(&sw, y, T, seen)\n\t\t\tif len(sw.TypeCases) > 1 {\n\t\t\t\tswitches = append(switches, sw)\n\t\t\t}\n\t\t}\n\t}\n\treturn switches\n}\n\nfunc valueSwitch(sw *Switch, k *ssa.Const, seen map[*ssa.BasicBlock]bool) {\n\tb := sw.Start\n\tx := sw.X\n\tfor x == sw.X {\n\t\tif seen[b] {\n\t\t\tbreak\n\t\t}\n\t\tseen[b] = true\n\n\t\tsw.ConstCases = append(sw.ConstCases, ConstCase{\n\t\t\tBlock: b,\n\t\t\tBody:  b.Succs[0],\n\t\t\tValue: k,\n\t\t})\n\t\tb = b.Succs[1]\n\t\tif len(b.Instrs) > 2 {\n\t\t\t// Block b contains not just 'if x == k',\n\t\t\t// so it may have side effects that\n\t\t\t// make it unsafe to elide.\n\t\t\tbreak\n\t\t}\n\t\tif len(b.Preds) != 1 {\n\t\t\t// Block b has multiple predecessors,\n\t\t\t// so it cannot be treated as a case.\n\t\t\tbreak\n\t\t}\n\t\tx, k = isComparisonBlock(b)\n\t}\n\tsw.Default = b\n}\n\nfunc typeSwitch(sw *Switch, y ssa.Value, T types.Type, seen map[*ssa.BasicBlock]bool) {\n\tb := sw.Start\n\tx := sw.X\n\tfor x == sw.X {\n\t\tif seen[b] {\n\t\t\tbreak\n\t\t}\n\t\tseen[b] = true\n\n\t\tsw.TypeCases = append(sw.TypeCases, TypeCase{\n\t\t\tBlock:   b,\n\t\t\tBody:    b.Succs[0],\n\t\t\tType:    T,\n\t\t\tBinding: y,\n\t\t})\n\t\tb = b.Succs[1]\n\t\tif len(b.Instrs) > 4 {\n\t\t\t// Block b contains not just\n\t\t\t//  {TypeAssert; Extract #0; Extract #1; If}\n\t\t\t// so it may have side effects that\n\t\t\t// make it unsafe to elide.\n\t\t\tbreak\n\t\t}\n\t\tif len(b.Preds) != 1 {\n\t\t\t// Block b has multiple predecessors,\n\t\t\t// so it cannot be treated as a case.\n\t\t\tbreak\n\t\t}\n\t\ty, x, T = isTypeAssertBlock(b)\n\t}\n\tsw.Default = b\n}\n\n// isComparisonBlock returns the operands (v, k) if a block ends with\n// a comparison v==k, where k is a compile-time constant.\nfunc isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {\n\tif n := len(b.Instrs); n >= 2 {\n\t\tif i, ok := b.Instrs[n-1].(*ssa.If); ok {\n\t\t\tif binop, ok := i.Cond.(*ssa.BinOp); ok && binop.Block() == b && binop.Op == token.EQL {\n\t\t\t\tif k, ok := binop.Y.(*ssa.Const); ok {\n\t\t\t\t\treturn binop.X, k\n\t\t\t\t}\n\t\t\t\tif k, ok := binop.X.(*ssa.Const); ok {\n\t\t\t\t\treturn binop.Y, k\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// isTypeAssertBlock returns the operands (y, x, T) if a block ends with\n// a type assertion \"if y, ok := x.(T); ok {\".\nfunc isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {\n\tif n := len(b.Instrs); n >= 4 {\n\t\tif i, ok := b.Instrs[n-1].(*ssa.If); ok {\n\t\t\tif ext1, ok := i.Cond.(*ssa.Extract); ok && ext1.Block() == b && ext1.Index == 1 {\n\t\t\t\tif ta, ok := ext1.Tuple.(*ssa.TypeAssert); ok && ta.Block() == b {\n\t\t\t\t\t// hack: relies upon instruction ordering.\n\t\t\t\t\tif ext0, ok := b.Instrs[n-3].(*ssa.Extract); ok {\n\t\t\t\t\t\treturn ext0, ta.X, ta.AssertedType\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "go/ssa/ssautil/switch_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage ssautil_test\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestSwitches(t *testing.T) {\n\tarchive, err := txtar.ParseFile(\"testdata/switches.txtar\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tppkgs := testfiles.LoadPackages(t, archive, \".\")\n\tif len(ppkgs) != 1 {\n\t\tt.Fatalf(\"Expected to load one package but got %d\", len(ppkgs))\n\t}\n\tf := ppkgs[0].Syntax[0]\n\n\tprog, _ := ssautil.Packages(ppkgs, ssa.BuilderMode(0))\n\tmainPkg := prog.Package(ppkgs[0].Types)\n\tmainPkg.Build()\n\n\tfor _, mem := range mainPkg.Members {\n\t\tif fn, ok := mem.(*ssa.Function); ok {\n\t\t\tif fn.Synthetic != \"\" {\n\t\t\t\tcontinue // e.g. init()\n\t\t\t}\n\t\t\t// Each (multi-line) \"switch\" comment within\n\t\t\t// this function must match the printed form\n\t\t\t// of a ConstSwitch.\n\t\t\tvar wantSwitches []string\n\t\t\tfor _, c := range f.Comments {\n\t\t\t\tif fn.Syntax().Pos() <= c.Pos() && c.Pos() < fn.Syntax().End() {\n\t\t\t\t\ttext := strings.TrimSpace(c.Text())\n\t\t\t\t\tif strings.HasPrefix(text, \"switch \") {\n\t\t\t\t\t\twantSwitches = append(wantSwitches, text)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tswitches := ssautil.Switches(fn)\n\t\t\tif len(switches) != len(wantSwitches) {\n\t\t\t\tt.Errorf(\"in %s, found %d switches, want %d\", fn, len(switches), len(wantSwitches))\n\t\t\t}\n\t\t\tfor i, sw := range switches {\n\t\t\t\tgot := sw.String()\n\t\t\t\tif i >= len(wantSwitches) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\twant := wantSwitches[i]\n\t\t\t\tif got != want {\n\t\t\t\t\tt.Errorf(\"in %s, found switch %d: got <<%s>>, want <<%s>>\", fn, i, got, want)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/ssautil/testdata/switches.txtar",
    "content": "-- go.mod --\nmodule example.com\ngo 1.22\n\n-- switches.go --\npackage main\n\n// This file is the input to TestSwitches in switch_test.go.\n// Each multiway conditional with constant or type cases (Switch)\n// discovered by Switches is printed, and compared with the\n// comments.\n//\n// The body of each case is printed as the value of its first\n// instruction.\n\n// -------- Value switches --------\n\nfunc SimpleSwitch(x, y int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(23:int)\n\t// case 3:int: print(23:int)\n\t// case 4:int: print(3:int)\n\t// default: x == y\n\t// }\n\tswitch x {\n\tcase 1:\n\t\tprint(1)\n\tcase 2, 3:\n\t\tprint(23)\n\t\tfallthrough\n\tcase 4:\n\t\tprint(3)\n\tdefault:\n\t\tprint(4)\n\tcase y:\n\t\tprint(5)\n\t}\n\tprint(6)\n}\n\nfunc four() int { return 4 }\n\n// A non-constant case makes a switch \"impure\", but its pure\n// cases form two separate switches.\nfunc SwitchWithNonConstantCase(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(23:int)\n\t// case 3:int: print(23:int)\n\t// default: four()\n\t// }\n\n\t// switch x {\n\t// case 5:int: print(5:int)\n\t// case 6:int: print(6:int)\n\t// default: print(\"done\":string)\n\t// }\n\tswitch x {\n\tcase 1:\n\t\tprint(1)\n\tcase 2, 3:\n\t\tprint(23)\n\tcase four():\n\t\tprint(3)\n\tcase 5:\n\t\tprint(5)\n\tcase 6:\n\t\tprint(6)\n\t}\n\tprint(\"done\")\n}\n\n// Switches may be found even where the source\n// program doesn't have a switch statement.\n\nfunc ImplicitSwitches(x, y int) {\n\t// switch x {\n\t// case 1:int: print(12:int)\n\t// case 2:int: print(12:int)\n\t// default: x < 5:int\n\t// }\n\tif x == 1 || 2 == x || x < 5 {\n\t\tprint(12)\n\t}\n\n\t// switch x {\n\t// case 3:int: print(34:int)\n\t// case 4:int: print(34:int)\n\t// default: x == y\n\t// }\n\tif x == 3 || 4 == x || x == y {\n\t\tprint(34)\n\t}\n\n\t// Not a switch: no consistent variable.\n\tif x == 5 || y == 6 {\n\t\tprint(56)\n\t}\n\n\t// Not a switch: only one constant comparison.\n\tif x == 7 || x == y {\n\t\tprint(78)\n\t}\n}\n\nfunc IfElseBasedSwitch(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(2:int)\n\t// default: print(\"else\":string)\n\t// }\n\tif x == 1 {\n\t\tprint(1)\n\t} else if x == 2 {\n\t\tprint(2)\n\t} else {\n\t\tprint(\"else\")\n\t}\n}\n\nfunc GotoBasedSwitch(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(2:int)\n\t// default: print(\"else\":string)\n\t// }\n\tif x == 1 {\n\t\tgoto L1\n\t}\n\tif x == 2 {\n\t\tgoto L2\n\t}\n\tprint(\"else\")\nL1:\n\tprint(1)\n\tgoto end\nL2:\n\tprint(2)\nend:\n}\n\nfunc SwitchInAForLoop(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(2:int)\n\t// default: print(\"head\":string)\n\t// }\nloop:\n\tfor {\n\t\tprint(\"head\")\n\t\tswitch x {\n\t\tcase 1:\n\t\t\tprint(1)\n\t\t\tbreak loop\n\t\tcase 2:\n\t\t\tprint(2)\n\t\t\tbreak loop\n\t\t}\n\t}\n}\n\n// This case is a switch in a for-loop, both constructed using goto.\n// As before, the default case points back to the block containing the\n// switch, but that's ok.\nfunc SwitchInAForLoopUsingGoto(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: print(2:int)\n\t// default: print(\"head\":string)\n\t// }\nloop:\n\tprint(\"head\")\n\tif x == 1 {\n\t\tgoto L1\n\t}\n\tif x == 2 {\n\t\tgoto L2\n\t}\n\tgoto loop\nL1:\n\tprint(1)\n\tgoto end\nL2:\n\tprint(2)\nend:\n}\n\nfunc UnstructuredSwitchInAForLoop(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 2:int: x == 1:int\n\t// default: print(\"end\":string)\n\t// }\n\tfor {\n\t\tif x == 1 {\n\t\t\tprint(1)\n\t\t\treturn\n\t\t}\n\t\tif x == 2 {\n\t\t\tcontinue\n\t\t}\n\t\tbreak\n\t}\n\tprint(\"end\")\n}\n\nfunc CaseWithMultiplePreds(x int) {\n\tfor {\n\t\tif x == 1 {\n\t\t\tprint(1)\n\t\t\treturn\n\t\t}\n\tloop:\n\t\t// This block has multiple predecessors,\n\t\t// so can't be treated as a switch case.\n\t\tif x == 2 {\n\t\t\tgoto loop\n\t\t}\n\t\tbreak\n\t}\n\tprint(\"end\")\n}\n\nfunc DuplicateConstantsAreNotEliminated(x int) {\n\t// switch x {\n\t// case 1:int: print(1:int)\n\t// case 1:int: print(\"1a\":string)\n\t// case 2:int: print(2:int)\n\t// default: return\n\t// }\n\tif x == 1 {\n\t\tprint(1)\n\t} else if x == 1 { // duplicate => unreachable\n\t\tprint(\"1a\")\n\t} else if x == 2 {\n\t\tprint(2)\n\t}\n}\n\n// Interface values (created by comparisons) are not constants,\n// so ConstSwitch.X is never of interface type.\nfunc MakeInterfaceIsNotAConstant(x interface{}) {\n\tif x == \"foo\" {\n\t\tprint(\"foo\")\n\t} else if x == 1 {\n\t\tprint(1)\n\t}\n}\n\nfunc ZeroInitializedVarsAreConstants(x int) {\n\t// switch x {\n\t// case 0:int: print(1:int)\n\t// case 2:int: print(2:int)\n\t// default: print(\"end\":string)\n\t// }\n\tvar zero int // SSA construction replaces zero with 0\n\tif x == zero {\n\t\tprint(1)\n\t} else if x == 2 {\n\t\tprint(2)\n\t}\n\tprint(\"end\")\n}\n\n// -------- Select --------\n\n// NB, potentially fragile reliance on register number.\nfunc SelectDesugarsToSwitch(ch chan int) {\n\t// switch t1 {\n\t// case 0:int: extract t0 #2\n\t// case 1:int: println(0:int)\n\t// case 2:int: println(1:int)\n\t// default: println(\"default\":string)\n\t// }\n\tselect {\n\tcase x := <-ch:\n\t\tprintln(x)\n\tcase <-ch:\n\t\tprintln(0)\n\tcase ch <- 1:\n\t\tprintln(1)\n\tdefault:\n\t\tprintln(\"default\")\n\t}\n}\n\n// NB, potentially fragile reliance on register number.\nfunc NonblockingSelectDefaultCasePanics(ch chan int) {\n\t// switch t1 {\n\t// case 0:int: extract t0 #2\n\t// case 1:int: println(0:int)\n\t// case 2:int: println(1:int)\n\t// default: make interface{} <- string (\"blocking select m...\":string)\n\t// }\n\tselect {\n\tcase x := <-ch:\n\t\tprintln(x)\n\tcase <-ch:\n\t\tprintln(0)\n\tcase ch <- 1:\n\t\tprintln(1)\n\t}\n}\n\n// -------- Type switches --------\n\n// NB, reliance on fragile register numbering.\nfunc SimpleTypeSwitch(x interface{}) {\n\t// switch x.(type) {\n\t// case t3 int: println(x)\n\t// case t7 bool: println(x)\n\t// case t10 string: println(t10)\n\t// default: println(x)\n\t// }\n\tswitch y := x.(type) {\n\tcase nil:\n\t\tprintln(y)\n\tcase int, bool:\n\t\tprintln(y)\n\tcase string:\n\t\tprintln(y)\n\tdefault:\n\t\tprintln(y)\n\t}\n}\n\n// NB, potentially fragile reliance on register number.\nfunc DuplicateTypesAreNotEliminated(x interface{}) {\n\t// switch x.(type) {\n\t// case t1 string: println(1:int)\n\t// case t5 interface{}: println(t5)\n\t// case t9 int: println(3:int)\n\t// default: return\n\t// }\n\tswitch y := x.(type) {\n\tcase string:\n\t\tprintln(1)\n\tcase interface{}:\n\t\tprintln(y)\n\tcase int:\n\t\tprintln(3) // unreachable!\n\t}\n}\n\n// NB, potentially fragile reliance on register number.\nfunc AdHocTypeSwitch(x interface{}) {\n\t// switch x.(type) {\n\t// case t1 int: println(t1)\n\t// case t5 string: println(t5)\n\t// default: print(\"default\":string)\n\t// }\n\tif i, ok := x.(int); ok {\n\t\tprintln(i)\n\t} else if s, ok := x.(string); ok {\n\t\tprintln(s)\n\t} else {\n\t\tprint(\"default\")\n\t}\n}\n"
  },
  {
    "path": "go/ssa/ssautil/visit.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssautil // import \"golang.org/x/tools/go/ssa/ssautil\"\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\n\t_ \"unsafe\" // for linkname hack\n)\n\n// This file defines utilities for visiting the SSA representation of\n// a Program.\n//\n// TODO(adonovan): test coverage.\n\n// AllFunctions finds and returns the set of functions potentially\n// needed by program prog, as determined by a simple linker-style\n// reachability algorithm starting from the members and method-sets of\n// each package.  The result may include anonymous functions and\n// synthetic wrappers.\n//\n// Precondition: all packages are built.\n//\n// TODO(adonovan): this function is underspecified. It doesn't\n// actually work like a linker, which computes reachability from main\n// using something like go/callgraph/cha (without materializing the\n// call graph). In fact, it treats all public functions and all\n// methods of public non-parameterized types as roots, even though\n// they may be unreachable--but only in packages created from syntax.\n//\n// I think we should deprecate AllFunctions function in favor of two\n// clearly defined ones:\n//\n//  1. The first would efficiently compute CHA reachability from a set\n//     of main packages, making it suitable for a whole-program\n//     analysis context with InstantiateGenerics, in conjunction with\n//     Program.Build.\n//\n//  2. The second would return only the set of functions corresponding\n//     to source Func{Decl,Lit} syntax, like SrcFunctions in\n//     go/analysis/passes/buildssa; this is suitable for\n//     package-at-a-time (or handful of packages) context.\n//     ssa.Package could easily expose it as a field.\n//\n// We could add them unexported for now and use them via the linkname hack.\nfunc AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {\n\tseen := make(map[*ssa.Function]bool)\n\n\tvar function func(fn *ssa.Function)\n\tfunction = func(fn *ssa.Function) {\n\t\tif !seen[fn] {\n\t\t\tseen[fn] = true\n\t\t\tvar buf [10]*ssa.Value // avoid alloc in common case\n\t\t\tfor _, b := range fn.Blocks {\n\t\t\t\tfor _, instr := range b.Instrs {\n\t\t\t\t\tfor _, op := range instr.Operands(buf[:0]) {\n\t\t\t\t\t\tif fn, ok := (*op).(*ssa.Function); ok {\n\t\t\t\t\t\t\tfunction(fn)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(adonovan): opt: provide a way to share a builder\n\t// across a sequence of MethodValue calls.\n\n\tmethodsOf := func(T types.Type) {\n\t\tif !types.IsInterface(T) {\n\t\t\tmset := prog.MethodSets.MethodSet(T)\n\t\t\tfor method := range mset.Methods() {\n\t\t\t\tfunction(prog.MethodValue(method))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Historically, Program.RuntimeTypes used to include the type\n\t// of any exported member of a package loaded from syntax that\n\t// has a non-parameterized type, plus all types\n\t// reachable from that type using reflection, even though\n\t// these runtime types may not be required for them.\n\t//\n\t// Rather than break existing programs that rely on\n\t// AllFunctions visiting extra methods that are unreferenced\n\t// by IR and unreachable via reflection, we moved the logic\n\t// here, unprincipled though it is.\n\t// (See doc comment for better ideas.)\n\t//\n\t// Nonetheless, after the move, we no longer visit every\n\t// method of any type recursively reachable from T, only the\n\t// methods of T and *T themselves, and we only apply this to\n\t// named types T, and not to the type of every exported\n\t// package member.\n\texportedTypeHack := func(t *ssa.Type) {\n\t\tif isSyntactic(t.Package()) &&\n\t\t\tast.IsExported(t.Name()) &&\n\t\t\t!types.IsInterface(t.Type()) {\n\t\t\t// Consider only named types.\n\t\t\t// (Ignore aliases and unsafe.Pointer.)\n\t\t\tif named, ok := t.Type().(*types.Named); ok {\n\t\t\t\tif named.TypeParams() == nil {\n\t\t\t\t\tmethodsOf(named)                   //  T\n\t\t\t\t\tmethodsOf(types.NewPointer(named)) // *T\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, pkg := range prog.AllPackages() {\n\t\tfor _, mem := range pkg.Members {\n\t\t\tswitch mem := mem.(type) {\n\t\t\tcase *ssa.Function:\n\t\t\t\t// Visit all package-level declared functions.\n\t\t\t\tfunction(mem)\n\n\t\t\tcase *ssa.Type:\n\t\t\t\texportedTypeHack(mem)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Visit all methods of types for which runtime types were\n\t// materialized, as they are reachable through reflection.\n\tfor _, T := range prog.RuntimeTypes() {\n\t\tmethodsOf(T)\n\t}\n\n\treturn seen\n}\n\n// MainPackages returns the subset of the specified packages\n// named \"main\" that define a main function.\n// The result may include synthetic \"testmain\" packages.\nfunc MainPackages(pkgs []*ssa.Package) []*ssa.Package {\n\tvar mains []*ssa.Package\n\tfor _, pkg := range pkgs {\n\t\tif pkg.Pkg.Name() == \"main\" && pkg.Func(\"main\") != nil {\n\t\t\tmains = append(mains, pkg)\n\t\t}\n\t}\n\treturn mains\n}\n\n// TODO(adonovan): propose a principled API for this. One possibility\n// is a new field, Package.SrcFunctions []*Function, which would\n// contain the list of SrcFunctions described in point 2 of the\n// AllFunctions doc comment, or nil if the package is not from syntax.\n// But perhaps overloading nil vs empty slice is too subtle.\n//\n//go:linkname isSyntactic golang.org/x/tools/go/ssa.isSyntactic\nfunc isSyntactic(pkg *ssa.Package) bool\n"
  },
  {
    "path": "go/ssa/stdlib_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Incomplete source tree on Android.\n\n//go:build !android\n\npackage ssa_test\n\n// This file runs the SSA builder in sanity-checking mode on all\n// packages beneath $GOROOT and prints some summary information.\n//\n// Run with \"go test -cpu=8 to\" set GOMAXPROCS.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc bytesAllocated() uint64 {\n\truntime.GC()\n\tvar stats runtime.MemStats\n\truntime.ReadMemStats(&stats)\n\treturn stats.Alloc\n}\n\n// TestStdlib loads the entire standard library and its tools and all\n// their dependencies.\n//\n// (As of go1.23, std is transitively closed, so adding the -deps flag\n// doesn't increase its result set. The cmd pseudomodule of course\n// depends on a good chunk of std, but the std+cmd set is also\n// transitively closed, so long as -pgo=off.)\n//\n// Apart from a small number of internal packages that are not\n// returned by the 'std' query, the set is essentially transitively\n// closed, so marginal per-dependency costs are invisible.\nfunc TestStdlib(t *testing.T) {\n\ttestLoad(t, 500, \"std\", \"cmd\")\n}\n\n// TestNetHTTP builds a single SSA package but not its dependencies.\n// It may help reveal costs related to dependencies (e.g. unnecessary building).\nfunc TestNetHTTP(t *testing.T) {\n\ttestLoad(t, 120, \"net/http\")\n}\n\n// TestCycles loads two standard libraries that depend on the same\n// generic instantiations.\n// internal/trace/testtrace and net/http both depend on\n// slices.Contains[[]string string] and slices.Index[[]string string]\n// This can under some schedules create a cycle of dependencies\n// where both need to wait on the other to finish building.\nfunc TestCycles(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23) // internal/trace/testtrace was added in 1.23.\n\ttestLoad(t, 120, \"net/http\", \"internal/trace/testtrace\")\n}\n\nfunc testLoad(t *testing.T, minPkgs int, patterns ...string) {\n\t// Note: most of the commentary below applies to TestStdlib.\n\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode; too slow (https://golang.org/issue/14113)\") // ~5s\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Load, parse and type-check the program.\n\tt0 := time.Now()\n\talloc0 := bytesAllocated()\n\n\tcfg := &packages.Config{Mode: packages.LoadSyntax}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tt.Fatal(\"there were errors loading the packages\")\n\t}\n\n\tt1 := time.Now()\n\talloc1 := bytesAllocated()\n\n\t// Create SSA packages.\n\tvar mode ssa.BuilderMode\n\t// Comment out these lines during benchmarking.  Approx SSA build costs are noted.\n\tmode |= ssa.SanityCheckFunctions // + 2% space, + 4% time\n\tmode |= ssa.GlobalDebug          // +30% space, +18% time\n\tmode |= ssa.InstantiateGenerics  // + 0% space, + 2% time (unlikely to reproduce outside of stdlib)\n\tprog, _ := ssautil.Packages(pkgs, mode)\n\n\tt2 := time.Now()\n\n\t// Build SSA.\n\tprog.Build()\n\n\tt3 := time.Now()\n\talloc3 := bytesAllocated()\n\n\t// Sanity check to ensure we haven't dropped large numbers of packages.\n\tnumPkgs := len(prog.AllPackages())\n\tif numPkgs < minPkgs {\n\t\tt.Errorf(\"Loaded only %d packages, want at least %d\", numPkgs, minPkgs)\n\t}\n\n\t// Keep pkgs reachable until after we've measured memory usage.\n\tif len(pkgs) == 0 {\n\t\tpanic(\"unreachable\")\n\t}\n\n\tsrcFuncs := srcFunctions(prog, pkgs)\n\tallFuncs := ssautil.AllFunctions(prog)\n\n\t// The assertion below is not valid if the program contains\n\t// variants of the same package, such as the test variants\n\t// (e.g. package p as compiled for test executable x) obtained\n\t// when cfg.Tests=true. Profile-guided optimization may\n\t// lead to similar variation for non-test executables.\n\t//\n\t// Ideally, the test would assert that all functions within\n\t// each executable (more generally: within any singly rooted\n\t// transitively closed subgraph of the import graph) have\n\t// distinct names, but that isn't so easy to compute efficiently.\n\t// Disabling for now.\n\tif false {\n\t\t// Check that all non-synthetic functions have distinct names.\n\t\t// Synthetic wrappers for exported methods should be distinct too,\n\t\t// except for unexported ones (explained at (*Function).RelString).\n\t\tbyName := make(map[string]*ssa.Function)\n\t\tfor fn := range allFuncs {\n\t\t\tif fn.Synthetic == \"\" || ast.IsExported(fn.Name()) {\n\t\t\t\tstr := fn.String()\n\t\t\t\tprev := byName[str]\n\t\t\t\tbyName[str] = fn\n\t\t\t\tif prev != nil {\n\t\t\t\t\tt.Errorf(\"%s: duplicate function named %s\",\n\t\t\t\t\t\tprog.Fset.Position(fn.Pos()), str)\n\t\t\t\t\tt.Errorf(\"%s:   (previously defined here)\",\n\t\t\t\t\t\tprog.Fset.Position(prev.Pos()))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Dump some statistics.\n\tvar numInstrs int\n\tfor fn := range allFuncs {\n\t\tfor _, b := range fn.Blocks {\n\t\t\tnumInstrs += len(b.Instrs)\n\t\t}\n\t}\n\n\t// determine line count\n\tvar lineCount int\n\tprog.Fset.Iterate(func(f *token.File) bool {\n\t\tlineCount += f.LineCount()\n\t\treturn true\n\t})\n\n\t// NB: when benchmarking, don't forget to clear the debug +\n\t// sanity builder flags for better performance.\n\n\tt.Log(\"GOMAXPROCS:           \", runtime.GOMAXPROCS(0))\n\tt.Log(\"#Source lines:        \", lineCount)\n\tt.Log(\"Load/parse/typecheck: \", t1.Sub(t0))\n\tt.Log(\"SSA create:           \", t2.Sub(t1))\n\tt.Log(\"SSA build:            \", t3.Sub(t2))\n\n\t// SSA stats:\n\tt.Log(\"#Packages:            \", numPkgs)\n\tt.Log(\"#SrcFunctions:        \", len(srcFuncs))\n\tt.Log(\"#AllFunctions:        \", len(allFuncs))\n\tt.Log(\"#Instructions:        \", numInstrs)\n\tt.Log(\"#MB AST+types:        \", int64(alloc1-alloc0)/1e6)\n\tt.Log(\"#MB SSA:              \", int64(alloc3-alloc1)/1e6)\n}\n\n// srcFunctions gathers all ssa.Functions corresponding to syntax.\n// (Includes generics but excludes instances and all wrappers.)\n//\n// This is essentially identical to the SrcFunctions logic in\n// go/analysis/passes/buildssa.\nfunc srcFunctions(prog *ssa.Program, pkgs []*packages.Package) (res []*ssa.Function) {\n\tvar addSrcFunc func(fn *ssa.Function)\n\taddSrcFunc = func(fn *ssa.Function) {\n\t\tres = append(res, fn)\n\t\tfor _, anon := range fn.AnonFuncs {\n\t\t\taddSrcFunc(anon)\n\t\t}\n\t}\n\tfor _, pkg := range pkgs {\n\t\tfor _, file := range pkg.Syntax {\n\t\t\tfor _, decl := range file.Decls {\n\t\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\t\t\tobj := pkg.TypesInfo.Defs[decl.Name].(*types.Func)\n\t\t\t\t\tif obj == nil {\n\t\t\t\t\t\tpanic(\"nil *types.Func: \" + decl.Name.Name)\n\t\t\t\t\t}\n\t\t\t\t\tfn := prog.FuncValue(obj)\n\t\t\t\t\tif fn == nil {\n\t\t\t\t\t\tpanic(\"nil *ssa.Function: \" + obj.String())\n\t\t\t\t\t}\n\t\t\t\t\taddSrcFunc(fn)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "go/ssa/subst.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/aliases\"\n)\n\n// subster defines a type substitution operation of a set of type parameters\n// to type parameter free replacement types. Substitution is done within\n// the context of a package-level function instantiation. *Named types\n// declared in the function are unique to the instantiation.\n//\n// For example, given a parameterized function F\n//\n//\t  func F[S, T any]() any {\n//\t    type X struct{ s S; next *X }\n//\t\tvar p *X\n//\t    return p\n//\t  }\n//\n// calling the instantiation F[string, int]() returns an interface\n// value (*X[string,int], nil) where the underlying value of\n// X[string,int] is a struct{s string; next *X[string,int]}.\n//\n// A nil *subster is a valid, empty substitution map. It always acts as\n// the identity function. This allows for treating parameterized and\n// non-parameterized functions identically while compiling to ssa.\n//\n// Not concurrency-safe.\n//\n// Note: Some may find it helpful to think through some of the most\n// complex substitution cases using lambda calculus inspired notation.\n// subst.typ() solves evaluating a type expression E\n// within the body of a function Fn[m] with the type parameters m\n// once we have applied the type arguments N.\n// We can succinctly write this as a function application:\n//\n//\t((λm. E) N)\n//\n// go/types does not provide this interface directly.\n// So what subster provides is a type substitution operation\n//\n//\tE[m:=N]\ntype subster struct {\n\treplacements map[*types.TypeParam]types.Type // values should contain no type params\n\tcache        map[types.Type]types.Type       // cache of subst results\n\torigin       *types.Func                     // types.Objects declared within this origin function are unique within this context\n\tctxt         *types.Context                  // speeds up repeated instantiations\n\tuniqueness   typeutil.Map                    // determines the uniqueness of the instantiations within the function\n\t// TODO(taking): consider adding Pos\n}\n\n// Returns a subster that replaces tparams[i] with targs[i]. Uses ctxt as a cache.\n// targs should not contain any types in tparams.\n// fn is the generic function for which we are substituting.\nfunc makeSubster(ctxt *types.Context, fn *types.Func, tparams *types.TypeParamList, targs []types.Type) *subster {\n\tassert(tparams.Len() == len(targs), \"makeSubster argument count must match\")\n\n\tsubst := &subster{\n\t\treplacements: make(map[*types.TypeParam]types.Type, tparams.Len()),\n\t\tcache:        make(map[types.Type]types.Type),\n\t\torigin:       fn.Origin(),\n\t\tctxt:         ctxt,\n\t}\n\tfor i := 0; i < tparams.Len(); i++ {\n\t\tsubst.replacements[tparams.At(i)] = targs[i]\n\t}\n\treturn subst\n}\n\n// typ returns the type of t with the type parameter tparams[i] substituted\n// for the type targs[i] where subst was created using tparams and targs.\nfunc (subst *subster) typ(t types.Type) (res types.Type) {\n\tif subst == nil {\n\t\treturn t // A nil subst is type preserving.\n\t}\n\tif r, ok := subst.cache[t]; ok {\n\t\treturn r\n\t}\n\tdefer func() {\n\t\tsubst.cache[t] = res\n\t}()\n\n\tswitch t := t.(type) {\n\tcase *types.TypeParam:\n\t\tif r := subst.replacements[t]; r != nil {\n\t\t\treturn r\n\t\t}\n\t\treturn t\n\n\tcase *types.Basic:\n\t\treturn t\n\n\tcase *types.Array:\n\t\tif r := subst.typ(t.Elem()); r != t.Elem() {\n\t\t\treturn types.NewArray(r, t.Len())\n\t\t}\n\t\treturn t\n\n\tcase *types.Slice:\n\t\tif r := subst.typ(t.Elem()); r != t.Elem() {\n\t\t\treturn types.NewSlice(r)\n\t\t}\n\t\treturn t\n\n\tcase *types.Pointer:\n\t\tif r := subst.typ(t.Elem()); r != t.Elem() {\n\t\t\treturn types.NewPointer(r)\n\t\t}\n\t\treturn t\n\n\tcase *types.Tuple:\n\t\treturn subst.tuple(t)\n\n\tcase *types.Struct:\n\t\treturn subst.struct_(t)\n\n\tcase *types.Map:\n\t\tkey := subst.typ(t.Key())\n\t\telem := subst.typ(t.Elem())\n\t\tif key != t.Key() || elem != t.Elem() {\n\t\t\treturn types.NewMap(key, elem)\n\t\t}\n\t\treturn t\n\n\tcase *types.Chan:\n\t\tif elem := subst.typ(t.Elem()); elem != t.Elem() {\n\t\t\treturn types.NewChan(t.Dir(), elem)\n\t\t}\n\t\treturn t\n\n\tcase *types.Signature:\n\t\treturn subst.signature(t)\n\n\tcase *types.Union:\n\t\treturn subst.union(t)\n\n\tcase *types.Interface:\n\t\treturn subst.interface_(t)\n\n\tcase *types.Alias:\n\t\treturn subst.alias(t)\n\n\tcase *types.Named:\n\t\treturn subst.named(t)\n\n\tcase *opaqueType:\n\t\treturn t // opaque types are never substituted\n\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n\n// types returns the result of {subst.typ(ts[i])}.\nfunc (subst *subster) types(ts []types.Type) []types.Type {\n\tres := make([]types.Type, len(ts))\n\tfor i := range ts {\n\t\tres[i] = subst.typ(ts[i])\n\t}\n\treturn res\n}\n\nfunc (subst *subster) tuple(t *types.Tuple) *types.Tuple {\n\tif t != nil {\n\t\tif vars := subst.varlist(t); vars != nil {\n\t\t\treturn types.NewTuple(vars...)\n\t\t}\n\t}\n\treturn t\n}\n\ntype varlist interface {\n\tAt(i int) *types.Var\n\tLen() int\n}\n\n// fieldlist is an adapter for structs for the varlist interface.\ntype fieldlist struct {\n\tstr *types.Struct\n}\n\nfunc (fl fieldlist) At(i int) *types.Var { return fl.str.Field(i) }\nfunc (fl fieldlist) Len() int            { return fl.str.NumFields() }\n\nfunc (subst *subster) struct_(t *types.Struct) *types.Struct {\n\tif t != nil {\n\t\tif fields := subst.varlist(fieldlist{t}); fields != nil {\n\t\t\ttags := make([]string, t.NumFields())\n\t\t\tfor i, n := 0, t.NumFields(); i < n; i++ {\n\t\t\t\ttags[i] = t.Tag(i)\n\t\t\t}\n\t\t\treturn types.NewStruct(fields, tags)\n\t\t}\n\t}\n\treturn t\n}\n\n// varlist returns subst(in[i]) or return nils if subst(v[i]) == v[i] for all i.\nfunc (subst *subster) varlist(in varlist) []*types.Var {\n\tvar out []*types.Var // nil => no updates\n\tfor i, n := 0, in.Len(); i < n; i++ {\n\t\tv := in.At(i)\n\t\tw := subst.var_(v)\n\t\tif v != w && out == nil {\n\t\t\tout = make([]*types.Var, n)\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\tout[j] = in.At(j)\n\t\t\t}\n\t\t}\n\t\tif out != nil {\n\t\t\tout[i] = w\n\t\t}\n\t}\n\treturn out\n}\n\nfunc (subst *subster) var_(v *types.Var) *types.Var {\n\tif v != nil {\n\t\tif typ := subst.typ(v.Type()); typ != v.Type() {\n\t\t\tif v.IsField() {\n\t\t\t\treturn types.NewField(v.Pos(), v.Pkg(), v.Name(), typ, v.Embedded())\n\t\t\t}\n\t\t\treturn types.NewParam(v.Pos(), v.Pkg(), v.Name(), typ)\n\t\t}\n\t}\n\treturn v\n}\n\nfunc (subst *subster) union(u *types.Union) *types.Union {\n\tvar out []*types.Term // nil => no updates\n\n\tfor i, n := 0, u.Len(); i < n; i++ {\n\t\tt := u.Term(i)\n\t\tr := subst.typ(t.Type())\n\t\tif r != t.Type() && out == nil {\n\t\t\tout = make([]*types.Term, n)\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\tout[j] = u.Term(j)\n\t\t\t}\n\t\t}\n\t\tif out != nil {\n\t\t\tout[i] = types.NewTerm(t.Tilde(), r)\n\t\t}\n\t}\n\n\tif out != nil {\n\t\treturn types.NewUnion(out)\n\t}\n\treturn u\n}\n\nfunc (subst *subster) interface_(iface *types.Interface) *types.Interface {\n\tif iface == nil {\n\t\treturn nil\n\t}\n\n\t// methods for the interface. Initially nil if there is no known change needed.\n\t// Signatures for the method where recv is nil. NewInterfaceType fills in the receivers.\n\tvar methods []*types.Func\n\tinitMethods := func(n int) { // copy first n explicit methods\n\t\tmethods = make([]*types.Func, iface.NumExplicitMethods())\n\t\tfor i := range n {\n\t\t\tf := iface.ExplicitMethod(i)\n\t\t\tnorecv := changeRecv(f.Type().(*types.Signature), nil)\n\t\t\tmethods[i] = types.NewFunc(f.Pos(), f.Pkg(), f.Name(), norecv)\n\t\t}\n\t}\n\tfor i := 0; i < iface.NumExplicitMethods(); i++ {\n\t\tf := iface.ExplicitMethod(i)\n\t\t// On interfaces, we need to cycle break on anonymous interface types\n\t\t// being in a cycle with their signatures being in cycles with their receivers\n\t\t// that do not go through a Named.\n\t\tnorecv := changeRecv(f.Type().(*types.Signature), nil)\n\t\tsig := subst.typ(norecv)\n\t\tif sig != norecv && methods == nil {\n\t\t\tinitMethods(i)\n\t\t}\n\t\tif methods != nil {\n\t\t\tmethods[i] = types.NewFunc(f.Pos(), f.Pkg(), f.Name(), sig.(*types.Signature))\n\t\t}\n\t}\n\n\tvar embeds []types.Type\n\tinitEmbeds := func(n int) { // copy first n embedded types\n\t\tembeds = make([]types.Type, iface.NumEmbeddeds())\n\t\tfor i := range n {\n\t\t\tembeds[i] = iface.EmbeddedType(i)\n\t\t}\n\t}\n\tfor i := 0; i < iface.NumEmbeddeds(); i++ {\n\t\te := iface.EmbeddedType(i)\n\t\tr := subst.typ(e)\n\t\tif e != r && embeds == nil {\n\t\t\tinitEmbeds(i)\n\t\t}\n\t\tif embeds != nil {\n\t\t\tembeds[i] = r\n\t\t}\n\t}\n\n\tif methods == nil && embeds == nil {\n\t\treturn iface\n\t}\n\tif methods == nil {\n\t\tinitMethods(iface.NumExplicitMethods())\n\t}\n\tif embeds == nil {\n\t\tinitEmbeds(iface.NumEmbeddeds())\n\t}\n\treturn types.NewInterfaceType(methods, embeds).Complete()\n}\n\nfunc (subst *subster) alias(t *types.Alias) types.Type {\n\t// See subster.named. This follows the same strategy.\n\ttparams := t.TypeParams()\n\ttargs := t.TypeArgs()\n\ttname := t.Obj()\n\ttorigin := t.Origin()\n\n\tif !declaredWithin(tname, subst.origin) {\n\t\t// t is declared outside of the function origin. So t is a package level type alias.\n\t\tif targs.Len() == 0 {\n\t\t\t// No type arguments so no instantiation needed.\n\t\t\treturn t\n\t\t}\n\n\t\t// Instantiate with the substituted type arguments.\n\t\tnewTArgs := subst.typelist(targs)\n\t\treturn subst.instantiate(torigin, newTArgs)\n\t}\n\n\tif targs.Len() == 0 {\n\t\t// t is declared within the function origin and has no type arguments.\n\t\t//\n\t\t// Example: This corresponds to A or B in F, but not A[int]:\n\t\t//\n\t\t//     func F[T any]() {\n\t\t//       type A[S any] = struct{t T, s S}\n\t\t//       type B = T\n\t\t//       var x A[int]\n\t\t//       ...\n\t\t//     }\n\t\t//\n\t\t// This is somewhat different than *Named as *Alias cannot be created recursively.\n\n\t\t// Copy and substitute type params.\n\t\tvar newTParams []*types.TypeParam\n\t\tfor cur := range tparams.TypeParams() {\n\t\t\tcobj := cur.Obj()\n\t\t\tcname := types.NewTypeName(cobj.Pos(), cobj.Pkg(), cobj.Name(), nil)\n\t\t\tntp := types.NewTypeParam(cname, nil)\n\t\t\tsubst.cache[cur] = ntp // See the comment \"Note: Subtle\" in subster.named.\n\t\t\tnewTParams = append(newTParams, ntp)\n\t\t}\n\n\t\t// Substitute rhs.\n\t\trhs := subst.typ(t.Rhs())\n\n\t\t// Create the fresh alias.\n\t\tobj := aliases.New(tname.Pos(), tname.Pkg(), tname.Name(), rhs, newTParams)\n\n\t\t// Substitute into all of the constraints after they are created.\n\t\tfor i, ntp := range newTParams {\n\t\t\tbound := tparams.At(i).Constraint()\n\t\t\tntp.SetConstraint(subst.typ(bound))\n\t\t}\n\t\treturn obj.Type()\n\t}\n\n\t// t is declared within the function origin and has type arguments.\n\t//\n\t// Example: This corresponds to A[int] in F. Cases A and B are handled above.\n\t//     func F[T any]() {\n\t//       type A[S any] = struct{t T, s S}\n\t//       type B = T\n\t//       var x A[int]\n\t//       ...\n\t//     }\n\tsubOrigin := subst.typ(torigin)\n\tsubTArgs := subst.typelist(targs)\n\treturn subst.instantiate(subOrigin, subTArgs)\n}\n\nfunc (subst *subster) named(t *types.Named) types.Type {\n\t// A Named type is a user defined type.\n\t// Ignoring generics, Named types are canonical: they are identical if\n\t// and only if they have the same defining symbol.\n\t// Generics complicate things, both if the type definition itself is\n\t// parameterized, and if the type is defined within the scope of a\n\t// parameterized function. In this case, two named types are identical if\n\t// and only if their identifying symbols are identical, and all type\n\t// arguments bindings in scope of the named type definition (including the\n\t// type parameters of the definition itself) are equivalent.\n\t//\n\t// Notably:\n\t// 1. For type definition type T[P1 any] struct{}, T[A] and T[B] are identical\n\t//    only if A and B are identical.\n\t// 2. Inside the generic func Fn[m any]() any { type T struct{}; return T{} },\n\t//    the result of Fn[A] and Fn[B] have identical type if and only if A and\n\t//    B are identical.\n\t// 3. Both 1 and 2 could apply, such as in\n\t//    func F[m any]() any { type T[x any] struct{}; return T{} }\n\t//\n\t// A subster replaces type parameters within a function scope, and therefore must\n\t// also replace free type parameters in the definitions of local types.\n\t//\n\t// Note: There are some detailed notes sprinkled throughout that borrow from\n\t// lambda calculus notation. These contain some over simplifying math.\n\t//\n\t// LC: One way to think about subster is that it is  a way of evaluating\n\t//   ((λm. E) N) as E[m:=N].\n\t// Each Named type t has an object *TypeName within a scope S that binds an\n\t// underlying type expression U. U can refer to symbols within S (+ S's ancestors).\n\t// Let x = t.TypeParams() and A = t.TypeArgs().\n\t// Each Named type t is then either:\n\t//   U              where len(x) == 0 && len(A) == 0\n\t//   λx. U          where len(x) != 0 && len(A) == 0\n\t//   ((λx. U) A)    where len(x) == len(A)\n\t// In each case, we will evaluate t[m:=N].\n\ttparams := t.TypeParams() // x\n\ttargs := t.TypeArgs()     // A\n\n\tif !declaredWithin(t.Obj(), subst.origin) {\n\t\t// t is declared outside of Fn[m].\n\t\t//\n\t\t// In this case, we can skip substituting t.Underlying().\n\t\t// The underlying type cannot refer to the type parameters.\n\t\t//\n\t\t// LC: Let free(E) be the set of free type parameters in an expression E.\n\t\t// Then whenever m ∉ free(E), then E = E[m:=N].\n\t\t// t ∉ Scope(fn) so therefore m ∉ free(U) and m ∩ x = ∅.\n\t\tif targs.Len() == 0 {\n\t\t\t// t has no type arguments. So it does not need to be instantiated.\n\t\t\t//\n\t\t\t// This is the normal case in real Go code, where t is not parameterized,\n\t\t\t// declared at some package scope, and m is a TypeParam from a parameterized\n\t\t\t// function F[m] or method.\n\t\t\t//\n\t\t\t// LC: m ∉ free(A) lets us conclude m ∉ free(t). So t=t[m:=N].\n\t\t\treturn t\n\t\t}\n\n\t\t// t is declared outside of Fn[m] and has type arguments.\n\t\t// The type arguments may contain type parameters m so\n\t\t// substitute the type arguments, and instantiate the substituted\n\t\t// type arguments.\n\t\t//\n\t\t// LC: Evaluate this as ((λx. U) A') where A' = A[m := N].\n\t\tnewTArgs := subst.typelist(targs)\n\t\treturn subst.instantiate(t.Origin(), newTArgs)\n\t}\n\n\t// t is declared within Fn[m].\n\n\tif targs.Len() == 0 { // no type arguments?\n\t\tassert(t == t.Origin(), \"local parameterized type abstraction must be an origin type\")\n\n\t\t// t has no type arguments.\n\t\t// The underlying type of t may contain the function's type parameters,\n\t\t// replace these, and create a new type.\n\t\t//\n\t\t// Subtle: We short circuit substitution and use a newly created type in\n\t\t// subst, i.e. cache[t]=fresh, to preemptively replace t with fresh\n\t\t// in recursive types during traversal. This both breaks infinite cycles\n\t\t// and allows for constructing types with the replacement applied in\n\t\t// subst.typ(U).\n\t\t//\n\t\t// A new copy of the Named and Typename (and constraints) per function\n\t\t// instantiation matches the semantics of Go, which treats all function\n\t\t// instantiations F[N] as having distinct local types.\n\t\t//\n\t\t// LC: x.Len()=0 can be thought of as a special case of λx. U.\n\t\t// LC: Evaluate (λx. U)[m:=N] as (λx'. U') where U'=U[x:=x',m:=N].\n\t\ttname := t.Obj()\n\t\tobj := types.NewTypeName(tname.Pos(), tname.Pkg(), tname.Name(), nil)\n\t\tfresh := types.NewNamed(obj, nil, nil)\n\t\tvar newTParams []*types.TypeParam\n\t\tfor cur := range tparams.TypeParams() {\n\t\t\tcobj := cur.Obj()\n\t\t\tcname := types.NewTypeName(cobj.Pos(), cobj.Pkg(), cobj.Name(), nil)\n\t\t\tntp := types.NewTypeParam(cname, nil)\n\t\t\tsubst.cache[cur] = ntp\n\t\t\tnewTParams = append(newTParams, ntp)\n\t\t}\n\t\tfresh.SetTypeParams(newTParams)\n\t\tsubst.cache[t] = fresh\n\t\tsubst.cache[fresh] = fresh\n\t\tfresh.SetUnderlying(subst.typ(t.Underlying()))\n\t\t// Substitute into all of the constraints after they are created.\n\t\tfor i, ntp := range newTParams {\n\t\t\tbound := tparams.At(i).Constraint()\n\t\t\tntp.SetConstraint(subst.typ(bound))\n\t\t}\n\t\treturn fresh\n\t}\n\n\t// t is defined within Fn[m] and t has type arguments (an instantiation).\n\t// We reduce this to the two cases above:\n\t// (1) substitute the function's type parameters into t.Origin().\n\t// (2) substitute t's type arguments A and instantiate the updated t.Origin() with these.\n\t//\n\t// LC: Evaluate ((λx. U) A)[m:=N] as (t' A') where t' = (λx. U)[m:=N] and A'=A [m:=N]\n\tsubOrigin := subst.typ(t.Origin())\n\tsubTArgs := subst.typelist(targs)\n\treturn subst.instantiate(subOrigin, subTArgs)\n}\n\nfunc (subst *subster) instantiate(orig types.Type, targs []types.Type) types.Type {\n\ti, err := types.Instantiate(subst.ctxt, orig, targs, false)\n\tassert(err == nil, \"failed to Instantiate named (Named or Alias) type\")\n\tif c, _ := subst.uniqueness.At(i).(types.Type); c != nil {\n\t\treturn c.(types.Type)\n\t}\n\tsubst.uniqueness.Set(i, i)\n\treturn i\n}\n\nfunc (subst *subster) typelist(l *types.TypeList) []types.Type {\n\tres := make([]types.Type, l.Len())\n\tfor i := 0; i < l.Len(); i++ {\n\t\tres[i] = subst.typ(l.At(i))\n\t}\n\treturn res\n}\n\nfunc (subst *subster) signature(t *types.Signature) types.Type {\n\ttparams := t.TypeParams()\n\n\t// We are choosing not to support tparams.Len() > 0 until a need has been observed in practice.\n\t//\n\t// There are some known usages for types.Types coming from types.{Eval,CheckExpr}.\n\t// To support tparams.Len() > 0, we just need to do the following [pseudocode]:\n\t//   targs := {subst.replacements[tparams[i]]]}; Instantiate(ctxt, t, targs, false)\n\n\tassert(tparams.Len() == 0, \"Substituting types.Signatures with generic functions are currently unsupported.\")\n\n\t// Either:\n\t// (1)non-generic function.\n\t//    no type params to substitute\n\t// (2)generic method and recv needs to be substituted.\n\n\t// Receivers can be either:\n\t// named\n\t// pointer to named\n\t// interface\n\t// nil\n\t// interface is the problematic case. We need to cycle break there!\n\trecv := subst.var_(t.Recv())\n\tparams := subst.tuple(t.Params())\n\tresults := subst.tuple(t.Results())\n\tif recv != t.Recv() || params != t.Params() || results != t.Results() {\n\t\treturn types.NewSignatureType(recv, nil, nil, params, results, t.Variadic())\n\t}\n\treturn t\n}\n"
  },
  {
    "path": "go/ssa/subst_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n)\n\nfunc TestSubst(t *testing.T) {\n\tconst source = `\npackage P\n\nfunc within(){\n\t// Pretend that the instantiation happens within this function.\n}\n\ntype t0 int\nfunc (t0) f()\ntype t1 interface{ f() }\ntype t2 interface{ g() }\ntype t3 interface{ ~int }\n\nfunc Fn0[T t1](x T) T {\n\tx.f()\n\treturn x\n}\n\ntype A[T any] [4]T\ntype B[T any] []T\ntype C[T, S any] []struct{s S; t T}\ntype D[T, S any] *struct{s S; t *T}\ntype E[T, S any] interface{ F() (T, S) }\ntype F[K comparable, V any] map[K]V\ntype G[T any] chan *T\ntype H[T any] func() T\ntype I[T any] struct{x, y, z int; t T}\ntype J[T any] interface{ t1 }\ntype K[T any] interface{ t1; F() T }\ntype L[T any] interface{ F() T; J[T] }\n\nvar _ L[int] = Fn0[L[int]](nil)\n`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twithin, _ := pkg.Scope().Lookup(\"within\").(*types.Func)\n\tif within == nil {\n\t\tt.Fatal(\"Failed to find the function within()\")\n\t}\n\n\tfor _, test := range []struct {\n\t\texpr string   // type expression of Named parameterized type\n\t\targs []string // type expressions of args for named\n\t\twant string   // expected underlying value after substitution\n\t}{\n\t\t{\"A\", []string{\"string\"}, \"[4]string\"},\n\t\t{\"A\", []string{\"int\"}, \"[4]int\"},\n\t\t{\"B\", []string{\"int\"}, \"[]int\"},\n\t\t{\"B\", []string{\"int8\"}, \"[]int8\"},\n\t\t{\"C\", []string{\"int8\", \"string\"}, \"[]struct{s string; t int8}\"},\n\t\t{\"C\", []string{\"string\", \"int8\"}, \"[]struct{s int8; t string}\"},\n\t\t{\"D\", []string{\"int16\", \"string\"}, \"*struct{s string; t *int16}\"},\n\t\t{\"E\", []string{\"int32\", \"string\"}, \"interface{F() (int32, string)}\"},\n\t\t{\"F\", []string{\"int64\", \"string\"}, \"map[int64]string\"},\n\t\t{\"G\", []string{\"uint64\"}, \"chan *uint64\"},\n\t\t{\"H\", []string{\"uintptr\"}, \"func() uintptr\"},\n\t\t{\"I\", []string{\"t0\"}, \"struct{x int; y int; z int; t P.t0}\"},\n\t\t{\"J\", []string{\"t0\"}, \"interface{P.t1}\"},\n\t\t{\"K\", []string{\"t0\"}, \"interface{F() P.t0; P.t1}\"},\n\t\t{\"L\", []string{\"t0\"}, \"interface{F() P.t0; P.J[P.t0]}\"},\n\t\t{\"L\", []string{\"L[t0]\"}, \"interface{F() P.L[P.t0]; P.J[P.L[P.t0]]}\"},\n\t} {\n\t\t// Eval() expr for its type.\n\t\ttv, err := types.Eval(fset, pkg, 0, test.expr)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\t\t// Eval() test.args[i] to get the i'th type arg.\n\t\tvar targs []types.Type\n\t\tfor _, astr := range test.args {\n\t\t\ttv, err := types.Eval(fset, pkg, 0, astr)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Eval(%s) failed: %v\", astr, err)\n\t\t\t}\n\t\t\ttargs = append(targs, tv.Type)\n\t\t}\n\n\t\tT := tv.Type.(*types.Named)\n\n\t\tsubst := makeSubster(types.NewContext(), within, T.TypeParams(), targs)\n\t\tsub := subst.typ(T.Underlying())\n\t\tif got := sub.String(); got != test.want {\n\t\t\tt.Errorf(\"subst{%v->%v}.typ(%s) = %v, want %v\", test.expr, test.args, T.Underlying(), got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/task.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport (\n\t\"sync/atomic\"\n)\n\n// Each task has two states: it is initially \"active\",\n// and transitions to \"done\".\n//\n// tasks form a directed graph. An edge from x to y (with y in x.edges)\n// indicates that the task x waits on the task y to be done.\n// Cycles are permitted.\n//\n// Calling x.wait() blocks the calling goroutine until task x,\n// and all the tasks transitively reachable from x are done.\n//\n// The nil *task is always considered done.\ntype task struct {\n\tdone       chan unit      // close when the task is done.\n\tedges      map[*task]unit // set of predecessors of this task.\n\ttransitive atomic.Bool    // true once it is known all predecessors are done.\n}\n\nfunc (x *task) isTransitivelyDone() bool { return x == nil || x.transitive.Load() }\n\n// addEdge creates an edge from x to y, indicating that\n// x.wait() will not return before y is done.\n// All calls to x.addEdge(...) should happen before x.markDone().\nfunc (x *task) addEdge(y *task) {\n\tif x == y || y.isTransitivelyDone() {\n\t\treturn // no work remaining\n\t}\n\n\t// heuristic done check\n\tselect {\n\tcase <-x.done:\n\t\tpanic(\"cannot add an edge to a done task\")\n\tdefault:\n\t}\n\n\tif x.edges == nil {\n\t\tx.edges = make(map[*task]unit)\n\t}\n\tx.edges[y] = unit{}\n}\n\n// markDone changes the task's state to markDone.\nfunc (x *task) markDone() {\n\tif x != nil {\n\t\tclose(x.done)\n\t}\n}\n\n// wait blocks until x and all the tasks it can reach through edges are done.\nfunc (x *task) wait() {\n\tif x.isTransitivelyDone() {\n\t\treturn // already known to be done. Skip allocations.\n\t}\n\n\t// Use BFS to wait on u.done to be closed, for all u transitively\n\t// reachable from x via edges.\n\t//\n\t// This work can be repeated by multiple workers doing wait().\n\t//\n\t// Note: Tarjan's SCC algorithm is able to mark SCCs as transitively done\n\t// as soon as the SCC has been visited. This is theoretically faster, but is\n\t// a more complex algorithm. Until we have evidence, we need the more complex\n\t// algorithm, the simpler algorithm BFS is implemented.\n\t//\n\t// In Go 1.23, ssa/TestStdlib reaches <=3 *tasks per wait() in most schedules\n\t// On some schedules, there is a cycle building net/http and internal/trace/testtrace\n\t// due to slices functions.\n\twork := []*task{x}\n\tenqueued := map[*task]unit{x: {}}\n\tfor i := 0; i < len(work); i++ {\n\t\tu := work[i]\n\t\tif u.isTransitivelyDone() { // already transitively done\n\t\t\twork[i] = nil\n\t\t\tcontinue\n\t\t}\n\t\t<-u.done // wait for u to be marked done.\n\n\t\tfor v := range u.edges {\n\t\t\tif _, ok := enqueued[v]; !ok {\n\t\t\t\tenqueued[v] = unit{}\n\t\t\t\twork = append(work, v)\n\t\t\t}\n\t\t}\n\t}\n\n\t// work is transitively closed over dependencies.\n\t// u in work is done (or transitively done and skipped).\n\t// u is transitively done.\n\tfor _, u := range work {\n\t\tif u != nil {\n\t\t\tx.transitive.Store(true)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/ssa/testdata/fixedbugs/issue66783a.go",
    "content": "//go:build ignore\n// +build ignore\n\npackage issue66783a\n\ntype S[T any] struct {\n\ta T\n}\n\nfunc (s S[T]) M() {\n\ttype A S[T]\n\ttype B[U any] A\n\t_ = B[rune](s)\n}\n\n// M[int]\n\n// panic: in (issue66783a.S[int]).M[int]:\n// cannot convert term *t0 (issue66783a.S[int] [within struct{a int}])\n// to type issue66783a.B[rune] [within struct{a T}] [recovered]\n\nfunc M() {\n\tS[int]{}.M()\n}\n"
  },
  {
    "path": "go/ssa/testdata/fixedbugs/issue66783b.go",
    "content": "//go:build ignore\n// +build ignore\n\npackage issue66783b\n\ntype I1[T any] interface {\n\tM(T)\n}\n\ntype I2[T any] I1[T]\n\nfunc foo[T any](i I2[T]) {\n\t_ = i.M\n}\n\ntype S[T any] struct{}\n\nfunc (s S[T]) M(t T) {}\n\nfunc M2() {\n\tfoo[int](I2[int](S[int]{}))\n}\n"
  },
  {
    "path": "go/ssa/testdata/fixedbugs/issue73594.go",
    "content": "package issue73594\n\n// Regression test for sanity-check failure caused by not clearing\n// Function.subst after building a body-less instantiated function.\n\ntype genericType[T any] struct{}\n\nfunc (genericType[T]) methodWithoutBody()\n\nfunc callMethodWithoutBody() {\n\tmsg := &genericType[int]{}\n\tmsg.methodWithoutBody()\n}\n"
  },
  {
    "path": "go/ssa/testdata/indirect.txtar",
    "content": "-- go.mod --\nmodule testdata\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc A() {\n\tvar x b.B\n\tx.F()\n}\n\n-- b/b.go --\npackage b\n\nimport \"testdata/c\"\n\ntype B struct { c.C }\n\n-- c/c.go --\npackage c\n\ntype C int\nfunc (C) F() {}"
  },
  {
    "path": "go/ssa/testdata/objlookup.go",
    "content": "package main\n\n// This file is the input to TestObjValueLookup in source_test.go,\n// which ensures that each occurrence of an ident defining or\n// referring to a func, var or const object can be mapped to its\n// corresponding SSA Value.\n//\n// For every reference to a var object, we use annotations in comments\n// to denote both the expected SSA Value kind, and whether to expect\n// its value (x) or its address (&x).\n//\n// For const and func objects, the results don't vary by reference and\n// are always values not addresses, so no annotations are needed.  The\n// declaration is enough.\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\ntype J int\n\nfunc (*J) method() {}\n\nconst globalConst = 0\n\nvar globalVar int //@ ssa(globalVar,\"&Global\")\n\nfunc globalFunc() {}\n\ntype I interface {\n\tinterfaceMethod()\n}\n\ntype S struct {\n\tx int //@ ssa(x,\"nil\")\n}\n\nfunc main() {\n\tprint(globalVar) //@ ssa(globalVar,\"UnOp\")\n\tglobalVar = 1    //@ ssa(globalVar,\"Const\")\n\n\tvar v0 int = 1 //@ ssa(v0,\"Const\") // simple local value spec\n\tif v0 > 0 {    //@ ssa(v0,\"Const\")\n\t\tv0 = 2 //@ ssa(v0,\"Const\")\n\t}\n\tprint(v0) //@ ssa(v0,\"Phi\")\n\n\t// v1 is captured and thus implicitly address-taken.\n\tvar v1 int = 1         //@ ssa(v1,\"Const\")\n\tv1 = 2                 //@ ssa(v1,\"Const\")\n\tfmt.Println(v1)        //@ ssa(v1,\"UnOp\") // load\n\tf := func(param int) { //@ ssa(f,\"MakeClosure\"), ssa(param,\"Parameter\")\n\t\tif y := 1; y > 0 { //@ ssa(y,\"Const\")\n\t\t\tprint(v1, param) //@ ssa(v1,\"UnOp\") /*load*/, ssa(param,\"Parameter\")\n\t\t}\n\t\tparam = 2      //@ ssa(param,\"Const\")\n\t\tprintln(param) //@ ssa(param,\"Const\")\n\t}\n\n\tf(0) //@ ssa(f,\"MakeClosure\")\n\n\tvar v2 int //@ ssa(v2,\"Const\") // implicitly zero-initialized local value spec\n\tprint(v2)  //@ ssa(v2,\"Const\")\n\n\tm := make(map[string]int) //@ ssa(m,\"MakeMap\")\n\n\t// Local value spec with multi-valued RHS:\n\tvar v3, v4 = m[\"\"] //@ ssa(v3,\"Extract\"), ssa(v4,\"Extract\"), ssa(m,\"MakeMap\")\n\tprint(v3)          //@ ssa(v3,\"Extract\")\n\tprint(v4)          //@ ssa(v4,\"Extract\")\n\n\tv3++    //@ ssa(v3,\"BinOp\") // assign with op\n\tv3 += 2 //@ ssa(v3,\"BinOp\") // assign with op\n\n\tv5, v6 := false, \"\" //@ ssa(v5,\"Const\"), ssa(v6,\"Const\") // defining assignment\n\tprint(v5)           //@ ssa(v5,\"Const\")\n\tprint(v6)           //@ ssa(v6,\"Const\")\n\n\tvar v7 S    //@ ssa(v7,\"&Alloc\")\n\tv7.x = 1    //@ ssa(v7,\"&Alloc\"), ssa(x,\"&FieldAddr\")\n\tprint(v7.x) //@ ssa(v7,\"&Alloc\"), ssa(x,\"&FieldAddr\")\n\n\tvar v8 [1]int //@ ssa(v8,\"&Alloc\")\n\tv8[0] = 0     //@ ssa(v8,\"&Alloc\")\n\tprint(v8[:])  //@ ssa(v8,\"&Alloc\")\n\t_ = v8[0]     //@ ssa(v8,\"&Alloc\")\n\t_ = v8[:][0]  //@ ssa(v8,\"&Alloc\")\n\tv8ptr := &v8  //@ ssa(v8ptr,\"Alloc\"), ssa(v8,\"&Alloc\")\n\t_ = v8ptr[0]  //@ ssa(v8ptr,\"Alloc\")\n\t_ = *v8ptr    //@ ssa(v8ptr,\"Alloc\")\n\n\tv8a := make([]int, 1) //@ ssa(v8a,\"Slice\")\n\tv8a[0] = 0            //@ ssa(v8a,\"Slice\")\n\tprint(v8a[:])         //@ ssa(v8a,\"Slice\")\n\n\tv9 := S{} //@ ssa(v9,\"&Alloc\")\n\n\tv10 := &v9 //@ ssa(v10,\"Alloc\"), ssa(v9,\"&Alloc\")\n\t_ = v10    //@ ssa(v10,\"Alloc\")\n\n\tvar v11 *J = nil //@ ssa(v11,\"Const\")\n\tv11.method()     //@ ssa(v11,\"Const\")\n\n\tvar v12 J    //@ ssa(v12,\"&Alloc\")\n\tv12.method() //@ ssa(v12,\"&Alloc\") // implicitly address-taken\n\n\t// NB, in the following, 'method' resolves to the *types.Func\n\t// of (*J).method, so it doesn't help us locate the specific\n\t// ssa.Values here: a bound-method closure and a promotion\n\t// wrapper.\n\t_ = v11.method            //@ ssa(v11,\"Const\")\n\t_ = (*struct{ J }).method //@ ssa(J,\"nil\")\n\n\t// These vars are not optimised away.\n\tif false {\n\t\tv13 := 0     //@ ssa(v13,\"Const\")\n\t\tprintln(v13) //@ ssa(v13,\"Const\")\n\t}\n\n\tswitch x := 1; x { //@ ssa(x,\"Const\")\n\tcase v0: //@ ssa(v0,\"Phi\")\n\t}\n\n\tfor k, v := range m { //@ ssa(k,\"Extract\"), ssa(v,\"Extract\"), ssa(m,\"MakeMap\")\n\t\t_ = k //@ ssa(k,\"Extract\")\n\t\tv++   //@ ssa(v,\"BinOp\")\n\t}\n\n\tif y := 0; y > 1 { //@ ssa(y,\"Const\"), ssa(y,\"Const\")\n\t}\n\n\tvar i interface{}      //@ ssa(i,\"Const\") // nil interface\n\ti = 1                  //@ ssa(i,\"MakeInterface\")\n\tswitch i := i.(type) { //@ ssa(i,\"MakeInterface\"), ssa(i,\"MakeInterface\")\n\tcase int:\n\t\tprintln(i) //@ ssa(i,\"Extract\")\n\t}\n\n\tch := make(chan int) //@ ssa(ch,\"MakeChan\")\n\tselect {\n\tcase x := <-ch: //@ ssa(x,\"UnOp\") /*receive*/, ssa(ch,\"MakeChan\")\n\t\t_ = x //@ ssa(x,\"UnOp\")\n\t}\n\n\t// .Op is an inter-package FieldVal-selection.\n\tvar err os.PathError //@ ssa(err,\"&Alloc\")\n\t_ = err.Op           //@ ssa(err,\"&Alloc\"), ssa(Op,\"&FieldAddr\")\n\t_ = &err.Op          //@ ssa(err,\"&Alloc\"), ssa(Op,\"&FieldAddr\")\n\n\t// Exercise corner-cases of lvalues vs rvalues.\n\t// (Guessing IsAddr from the 'pointerness' won't cut it here.)\n\ttype N *N\n\tvar n N    //@ ssa(n,\"Const\")\n\tn1 := n    //@ ssa(n1,\"Const\"), ssa(n,\"Const\")\n\tn2 := &n1  //@ ssa(n2,\"Alloc\"), ssa(n1,\"&Alloc\")\n\tn3 := *n2  //@ ssa(n3,\"UnOp\"), ssa(n2,\"Alloc\")\n\tn4 := **n3 //@ ssa(n4,\"UnOp\"), ssa(n3,\"UnOp\")\n\t_ = n4     //@ ssa(n4,\"UnOp\")\n}\n"
  },
  {
    "path": "go/ssa/testdata/src/README.txt",
    "content": "These files are present to test building ssa on go files that use signatures from standard library packages.\n\nOnly the exported members used by the tests are needed.\n\nProviding these decreases testing time ~10x (90s -> 8s) compared to building the standard library packages form source during tests."
  },
  {
    "path": "go/ssa/testdata/src/bytes/bytes.go",
    "content": "package bytes\n\nfunc Compare(a, b []byte) int\n"
  },
  {
    "path": "go/ssa/testdata/src/context/context.go",
    "content": "package context\n\ntype Context interface {\n\tDone() <-chan struct{}\n}\n\nfunc Background() Context\n"
  },
  {
    "path": "go/ssa/testdata/src/encoding/encoding.go",
    "content": "package encoding\n\ntype BinaryMarshaler interface {\n\tMarshalBinary() (data []byte, err error)\n}\n\ntype BinaryUnmarshaler interface {\n\tUnmarshalBinary(data []byte) error\n}\n"
  },
  {
    "path": "go/ssa/testdata/src/encoding/json/json.go",
    "content": "package json\n\nfunc Marshal(v any) ([]byte, error)\nfunc Unmarshal(data []byte, v any) error\n"
  },
  {
    "path": "go/ssa/testdata/src/encoding/xml/xml.go",
    "content": "package xml\n\nfunc Marshal(v any) ([]byte, error)\nfunc Unmarshal(data []byte, v any) error\n"
  },
  {
    "path": "go/ssa/testdata/src/errors/errors.go",
    "content": "package errors\n\nfunc New(text string) error\n"
  },
  {
    "path": "go/ssa/testdata/src/fmt/fmt.go",
    "content": "package fmt\n\nfunc Sprint(args ...interface{}) string\nfunc Sprintln(args ...interface{}) string\nfunc Sprintf(format string, args ...interface{}) string\n\nfunc Print(args ...interface{}) (int, error)\nfunc Println(args ...interface{})\nfunc Printf(format string, args ...interface{}) (int, error)\n\nfunc Errorf(format string, args ...interface{}) error\n"
  },
  {
    "path": "go/ssa/testdata/src/io/io.go",
    "content": "package io\n\nimport \"errors\"\n\nvar EOF = errors.New(\"EOF\")\n"
  },
  {
    "path": "go/ssa/testdata/src/log/log.go",
    "content": "package log\n\nfunc Println(v ...interface{})\nfunc Fatalln(v ...interface{})\nfunc Fatalf(format string, v ...any)\n"
  },
  {
    "path": "go/ssa/testdata/src/math/math.go",
    "content": "package math\n\nfunc NaN() float64\n\nfunc Inf(int) float64\n\nfunc IsNaN(float64) bool\n\nfunc Float64bits(float64) uint64\n\nfunc Signbit(x float64) bool\n\nfunc Sqrt(x float64) float64\n\nfunc Sin(x float64) float64\n"
  },
  {
    "path": "go/ssa/testdata/src/os/os.go",
    "content": "package os\n\nfunc Getenv(string) string\n\nfunc Exit(int)\n"
  },
  {
    "path": "go/ssa/testdata/src/reflect/reflect.go",
    "content": "package reflect\n\ntype Type interface {\n\tElem() Type\n\tKind() Kind\n\tString() string\n}\n\ntype Value struct{}\n\nfunc (Value) String() string\nfunc (Value) Elem() Value\nfunc (Value) Field(int) Value\nfunc (Value) Index(i int) Value\nfunc (Value) Int() int64\nfunc (Value) Interface() interface{}\nfunc (Value) IsNil() bool\nfunc (Value) IsValid() bool\nfunc (Value) Kind() Kind\nfunc (Value) Len() int\nfunc (Value) MapIndex(Value) Value\nfunc (Value) MapKeys() []Value\nfunc (Value) NumField() int\nfunc (Value) Pointer() uintptr\nfunc (Value) SetInt(int64)\nfunc (Value) Type() Type\n\nfunc SliceOf(Type) Type\nfunc TypeOf(interface{}) Type\nfunc ValueOf(interface{}) Value\n\ntype Kind uint\n\nconst (\n\tInvalid Kind = iota\n\tInt\n\tPointer\n)\n\nfunc DeepEqual(x, y interface{}) bool\n"
  },
  {
    "path": "go/ssa/testdata/src/runtime/runtime.go",
    "content": "package runtime\n\nfunc GC()\n\nfunc SetFinalizer(obj, finalizer any)\n\nfunc Caller(skip int) (pc uintptr, file string, line int, ok bool)\n"
  },
  {
    "path": "go/ssa/testdata/src/sort/sort.go",
    "content": "package sort\n\nfunc Strings(x []string)\nfunc Ints(x []int)\nfunc Float64s(x []float64)\n\nfunc Sort(data Interface)\n\ntype Interface interface {\n\tLen() int\n\tLess(i, j int) bool\n\tSwap(i, j int)\n}\n"
  },
  {
    "path": "go/ssa/testdata/src/strconv/strconv.go",
    "content": "package strconv\n\nfunc Itoa(i int) string\nfunc Atoi(s string) (int, error)\n\nfunc FormatFloat(float64, byte, int, int) string\n"
  },
  {
    "path": "go/ssa/testdata/src/strings/strings.go",
    "content": "package strings\n\nfunc Replace(s, old, new string, n int) string\nfunc Index(haystack, needle string) int\nfunc Contains(haystack, needle string) bool\nfunc HasPrefix(s, prefix string) bool\nfunc EqualFold(s, t string) bool\nfunc ToLower(s string) string\n\ntype Builder struct{}\n\nfunc (b *Builder) WriteString(s string) (int, error)\nfunc (b *Builder) String() string\n"
  },
  {
    "path": "go/ssa/testdata/src/sync/atomic/atomic.go",
    "content": "package atomic\n\nimport \"unsafe\"\n\nfunc LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)\n"
  },
  {
    "path": "go/ssa/testdata/src/sync/sync.go",
    "content": "package sync\n\ntype Mutex struct{}\n\nfunc (m *Mutex) Lock()\nfunc (m *Mutex) Unlock()\n\ntype WaitGroup struct{}\n\nfunc (wg *WaitGroup) Add(delta int)\nfunc (wg *WaitGroup) Done()\nfunc (wg *WaitGroup) Wait()\n"
  },
  {
    "path": "go/ssa/testdata/src/time/time.go",
    "content": "package time\n\ntype Duration int64\n\nfunc Sleep(Duration)\n\nfunc NewTimer(d Duration) *Timer\n\ntype Timer struct {\n\tC <-chan Time\n}\n\nfunc (t *Timer) Stop() bool\n\ntype Time struct{}\n\nfunc After(d Duration) <-chan Time\n\nconst (\n\tNanosecond Duration = iota // Specific values do not matter here.\n\tSecond\n\tMinute\n\tHour\n)\n"
  },
  {
    "path": "go/ssa/testdata/src/unsafe/unsafe.go",
    "content": "package unsafe\n\n// Empty unsafe package helps other packages load.\n// TODO(taking): determine why.\n"
  },
  {
    "path": "go/ssa/testdata/structconv.go",
    "content": "// This file is the input to TestValueForExprStructConv in identical_test.go,\n// which uses the same framework as TestValueForExpr does in source_test.go.\n//\n// In Go 1.8, struct conversions are permitted even when the struct types have\n// different tags. This wasn't permitted in earlier versions of Go, so this file\n// exists separately from valueforexpr.go to just test this behavior in Go 1.8\n// and later.\n\npackage main\n\ntype t1 struct {\n\tx int\n}\ntype t2 struct {\n\tx int `tag`\n}\n\nfunc main() {\n\tvar tv1 t1\n\tvar tv2 t2 = /*@ChangeType*/ (t2(tv1))\n\t_ = tv2\n}\n"
  },
  {
    "path": "go/ssa/testdata/valueforexpr.go",
    "content": "package main\n\n// This file is the input to TestValueForExpr in source_test.go, which\n// ensures that each expression e immediately following a /*@kind*/(x)\n// annotation, when passed to Function.ValueForExpr(e), returns a\n// non-nil Value of the same type as e and of kind 'kind'.\n\nfunc f(spilled, unspilled int) {\n\t_ = /*@UnOp*/ (spilled)\n\t_ = /*@Parameter*/ (unspilled)\n\t_ = /*@nil*/ (1 + 2) // (constant)\n\ti := 0\n\n\tf := func() (int, int) { return 0, 0 }\n\n\t/*@Call*/\n\t(print( /*@BinOp*/ (i + 1)))\n\t_, _ = /*@Call*/ (f())\n\tch := /*@MakeChan*/ (make(chan int))\n\t/*@UnOp*/ (<-ch)\n\tx := /*@UnOp*/ (<-ch)\n\t_ = x\n\tselect {\n\tcase /*@Extract*/ (<-ch):\n\tcase x := /*@Extract*/ (<-ch):\n\t\t_ = x\n\t}\n\tdefer /*@Function*/ (func() {\n\t})()\n\tgo /*@Function*/ (func() {\n\t})()\n\ty := 0\n\tif true && /*@BinOp*/ (bool(y > 0)) {\n\t\ty = 1\n\t}\n\t_ = /*@Phi*/ (y)\n\tmap1 := /*@MakeMap*/ (make(map[string]string))\n\t_ = map1\n\t_ = /*@Slice*/ (make([]int, 0))\n\t_ = /*@MakeClosure*/ (func() { print(spilled) })\n\n\tsl := []int{}\n\t_ = /*@Slice*/ (sl[:0])\n\n\t_ = /*@nil*/ (new(int)) // optimized away\n\ttmp := /*@Alloc*/ (new(int))\n\t_ = tmp\n\tvar iface interface{}\n\t_ = /*@TypeAssert*/ (iface.(int))\n\t_ = /*@UnOp*/ (sl[0])\n\t_ = /*@IndexAddr*/ (&sl[0])\n\t_ = /*@Index*/ ([2]int{}[0])\n\tvar p *int\n\t_ = /*@UnOp*/ (*p)\n\n\t_ = /*@UnOp*/ (global)\n\t/*@UnOp*/ (global)[\"\"] = \"\"\n\t/*@Global*/ (global) = map[string]string{}\n\n\tvar local t\n\t/*UnOp*/ (local.x) = 1\n\n\t// Exercise corner-cases of lvalues vs rvalues.\n\ttype N *N\n\tvar n N\n\t/*@UnOp*/ (n) = /*@UnOp*/ (n)\n\t/*@ChangeType*/ (n) = /*@Alloc*/ (&n)\n\t/*@UnOp*/ (n) = /*@UnOp*/ (*n)\n\t/*@UnOp*/ (n) = /*@UnOp*/ (**n)\n}\n\nfunc complit() {\n\t// Composite literals.\n\t// We get different results for\n\t// - composite literal as value (e.g. operand to print)\n\t// - composite literal initializer for addressable value\n\t// - composite literal value assigned to blank var\n\n\t// 1. Slices\n\tprint( /*@Slice*/ ([]int{}))\n\tprint( /*@Alloc*/ (&[]int{}))\n\tprint(& /*@Slice*/ ([]int{}))\n\n\tsl1 := /*@Slice*/ ([]int{})\n\tsl2 := /*@Alloc*/ (&[]int{})\n\tsl3 := & /*@Slice*/ ([]int{})\n\t_, _, _ = sl1, sl2, sl3\n\n\t_ = /*@Slice*/ ([]int{})\n\t_ = /*@nil*/ (& /*@Slice*/ ([]int{})) // & optimized away\n\t_ = & /*@Slice*/ ([]int{})\n\n\t// 2. Arrays\n\tprint( /*@Const*/ ([1]int{}))\n\tprint( /*@Alloc*/ (&[1]int{}))\n\tprint(& /*@Alloc*/ ([1]int{}))\n\n\tarr1 := /*@Const*/ ([1]int{})\n\tarr2 := /*@Alloc*/ (&[1]int{})\n\tarr3 := & /*@Alloc*/ ([1]int{})\n\t_, _, _ = arr1, arr2, arr3\n\n\t_ = /*@Const*/ ([1]int{})\n\t_ = /*@nil*/ (& /*@Const*/ ([1]int{})) // & optimized away\n\t_ = & /*@Const*/ ([1]int{})\n\n\t// 3. Maps\n\ttype M map[int]int\n\tprint( /*@MakeMap*/ (M{}))\n\tprint( /*@Alloc*/ (&M{}))\n\tprint(& /*@MakeMap*/ (M{}))\n\n\tm1 := /*@MakeMap*/ (M{})\n\tm2 := /*@Alloc*/ (&M{})\n\tm3 := & /*@MakeMap*/ (M{})\n\t_, _, _ = m1, m2, m3\n\n\t_ = /*@MakeMap*/ (M{})\n\t_ = /*@nil*/ (& /*@MakeMap*/ (M{})) // & optimized away\n\t_ = & /*@MakeMap*/ (M{})\n\n\t// 4. Structs\n\tprint( /*@Const*/ (struct{}{}))\n\tprint( /*@Alloc*/ (&struct{}{}))\n\tprint(& /*@Alloc*/ (struct{}{}))\n\n\ts1 := /*@Const*/ (struct{}{})\n\ts2 := /*@Alloc*/ (&struct{}{})\n\ts3 := & /*@Alloc*/ (struct{}{})\n\t_, _, _ = s1, s2, s3\n\n\t_ = /*@Const*/ (struct{}{})\n\t_ = /*@nil*/ (& /*@Const*/ (struct{}{})) // & optimized away\n\t_ = & /*@Const*/ (struct{}{})\n}\n\ntype t struct{ x int }\n\n// Ensure we can locate methods of named types.\nfunc (t) f(param int) {\n\t_ = /*@Parameter*/ (param)\n}\n\n// Ensure we can locate init functions.\nfunc init() {\n\tm := /*@MakeMap*/ (make(map[string]string))\n\t_ = m\n}\n\n// Ensure we can locate variables in initializer expressions.\nvar global = /*@MakeMap*/ (make(map[string]string))\n"
  },
  {
    "path": "go/ssa/testutil_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file defines helper functions for SSA tests.\n\npackage ssa_test\n\nimport (\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io/fs\"\n\t\"os\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/ssa/ssautil\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// goMod returns a go.mod file containing a name and a go directive\n// for the major version. If major < 0, use the current go toolchain\n// version.\nfunc goMod(name string, major int) []byte {\n\tif major < 0 {\n\t\tmajor = testenv.Go1Point()\n\t}\n\treturn fmt.Appendf(nil, \"module %s\\ngo 1.%d\", name, major)\n}\n\n// overlayFS returns a simple in-memory filesystem.\nfunc overlayFS(overlay map[string][]byte) fstest.MapFS {\n\t// taking: Maybe loadPackages should take an overlay instead?\n\tfs := make(fstest.MapFS)\n\tfor name, data := range overlay {\n\t\tfs[name] = &fstest.MapFile{Data: data}\n\t}\n\treturn fs\n}\n\n// openTxtar opens a txtar file as a filesystem.\nfunc openTxtar(t testing.TB, file string) fs.FS {\n\t// TODO(taking): Move to testfiles?\n\tt.Helper()\n\n\tar, err := txtar.ParseFile(file)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfs, err := txtar.FS(ar)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\treturn fs\n}\n\n// loadPackages copies the files in a source file system to a unique temporary\n// directory and loads packages matching the given patterns from the temporary directory.\n//\n// TODO(69556): Migrate loader tests to loadPackages.\nfunc loadPackages(t testing.TB, src fs.FS, patterns ...string) []*packages.Package {\n\tt.Helper()\n\ttestenv.NeedsGoBuild(t) // for go/packages\n\n\t// TODO(taking): src and overlays are very similar. Overlays could have nicer paths.\n\t// Look into migrating src to overlays.\n\tdir := testfiles.CopyToTmp(t, src)\n\n\tcfg := &packages.Config{\n\t\tDir: dir,\n\t\tMode: packages.NeedSyntax |\n\t\t\tpackages.NeedTypesInfo |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedCompiledGoFiles |\n\t\t\tpackages.NeedTypes,\n\t\tEnv: append(os.Environ(),\n\t\t\t\"GO111MODULES=on\",\n\t\t\t\"GOPATH=\",\n\t\t\t\"GOWORK=off\",\n\t\t\t\"GOPROXY=off\"),\n\t}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tt.Fatal(\"there were errors\")\n\t}\n\treturn pkgs\n}\n\n// buildPackage builds the content of a go file into:\n// * a module with the same name as the package at the current go version,\n// * loads the *package.Package,\n// * checks that (*packages.Packages).Syntax contains one file,\n// * builds the *ssa.Package (and not its dependencies), and\n// * returns the built *ssa.Package and the loaded packages.Package.\n//\n// TODO(adonovan): factor with similar loadFile (2x) in cha/cha_test.go and vta/helpers_test.go.\nfunc buildPackage(t testing.TB, content string, mode ssa.BuilderMode) (*ssa.Package, *packages.Package) {\n\tname := parsePackageClause(t, content)\n\n\tfs := overlayFS(map[string][]byte{\n\t\t\"go.mod\":   goMod(name, -1),\n\t\t\"input.go\": []byte(content),\n\t})\n\tppkgs := loadPackages(t, fs, name)\n\tif len(ppkgs) != 1 {\n\t\tt.Fatalf(\"Expected to load 1 package from pattern %q. got %d\", name, len(ppkgs))\n\t}\n\tppkg := ppkgs[0]\n\n\tif len(ppkg.Syntax) != 1 {\n\t\tt.Fatalf(\"Expected 1 file in package %q. got %d\", ppkg, len(ppkg.Syntax))\n\t}\n\n\tprog, _ := ssautil.Packages(ppkgs, mode)\n\n\tssapkg := prog.Package(ppkg.Types)\n\tif ssapkg == nil {\n\t\tt.Fatalf(\"Failed to find ssa package for %q\", ppkg.Types)\n\t}\n\tssapkg.Build()\n\n\treturn ssapkg, ppkg\n}\n\n// parsePackageClause is a test helper to extract the package name from a string\n// containing the content of a go file.\nfunc parsePackageClause(t testing.TB, content string) string {\n\tf, err := parser.ParseFile(token.NewFileSet(), \"\", content, parser.PackageClauseOnly)\n\tif err != nil {\n\t\tt.Fatalf(\"parsing the file %q failed with error: %s\", content, err)\n\t}\n\treturn f.Name.Name\n}\n"
  },
  {
    "path": "go/ssa/typeset.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// Utilities for dealing with type sets.\n\nconst debug = false\n\n// typeset is an iterator over the (type/underlying type) pairs of the\n// specific type terms of the type set implied by t.\n// If t is a type parameter, the implied type set is the type set of t's constraint.\n// In that case, if there are no specific terms, typeset calls yield with (nil, nil).\n// If t is not a type parameter, the implied type set consists of just t.\n// In any case, typeset is guaranteed to call yield at least once.\nfunc typeset(typ types.Type, yield func(t, u types.Type) bool) {\n\tswitch typ := types.Unalias(typ).(type) {\n\tcase *types.TypeParam, *types.Interface:\n\t\tterms := termListOf(typ)\n\t\tif len(terms) == 0 {\n\t\t\tyield(nil, nil)\n\t\t\treturn\n\t\t}\n\t\tfor _, term := range terms {\n\t\t\tu := types.Unalias(term.Type())\n\t\t\tif !term.Tilde() {\n\t\t\t\tu = u.Underlying()\n\t\t\t}\n\t\t\tif debug {\n\t\t\t\tassert(types.Identical(u, u.Underlying()), \"Unalias(x) == under(x) for ~x terms\")\n\t\t\t}\n\t\t\tif !yield(term.Type(), u) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\treturn\n\tdefault:\n\t\tyield(typ, typ.Underlying())\n\t}\n}\n\n// termListOf returns the type set of typ as a normalized term set. Returns an empty set on an error.\nfunc termListOf(typ types.Type) []*types.Term {\n\tterms, err := typeparams.NormalTerms(typ)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn terms\n}\n\n// typeSetIsEmpty returns true if a typeset is empty.\nfunc typeSetIsEmpty(typ types.Type) bool {\n\tvar empty bool\n\ttypeset(typ, func(t, _ types.Type) bool {\n\t\tempty = t == nil\n\t\treturn false\n\t})\n\treturn empty\n}\n\n// isBytestring returns true if T has the same terms as interface{[]byte | string}.\n// These act like a core type for some operations: slice expressions, append and copy.\n//\n// See https://go.dev/ref/spec#Core_types for the details on bytestring.\nfunc isBytestring(T types.Type) bool {\n\tU := T.Underlying()\n\tif _, ok := U.(*types.Interface); !ok {\n\t\treturn false\n\t}\n\n\thasBytes, hasString := false, false\n\tok := underIs(U, func(t types.Type) bool {\n\t\tswitch {\n\t\tcase isString(t):\n\t\t\thasString = true\n\t\t\treturn true\n\t\tcase isByteSlice(t):\n\t\t\thasBytes = true\n\t\t\treturn true\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t})\n\treturn ok && hasBytes && hasString\n}\n\n// underIs calls f with the underlying types of the type terms\n// of the type set of typ and reports whether all calls to f returned true.\n// If there are no specific terms, underIs returns the result of f(nil).\nfunc underIs(typ types.Type, f func(types.Type) bool) bool {\n\tvar ok bool\n\ttypeset(typ, func(t, u types.Type) bool {\n\t\tok = f(u)\n\t\treturn ok\n\t})\n\treturn ok\n}\n\n// indexType returns the element type and index mode of a IndexExpr over a type.\n// It returns an invalid mode if the type is not indexable; this should never occur in a well-typed program.\nfunc indexType(typ types.Type) (types.Type, indexMode) {\n\tswitch U := typ.Underlying().(type) {\n\tcase *types.Array:\n\t\treturn U.Elem(), ixArrVar\n\tcase *types.Pointer:\n\t\tif arr, ok := U.Elem().Underlying().(*types.Array); ok {\n\t\t\treturn arr.Elem(), ixVar\n\t\t}\n\tcase *types.Slice:\n\t\treturn U.Elem(), ixVar\n\tcase *types.Map:\n\t\treturn U.Elem(), ixMap\n\tcase *types.Basic:\n\t\treturn tByte, ixValue // must be a string\n\tcase *types.Interface:\n\t\tvar elem types.Type\n\t\tmode := ixInvalid\n\t\ttypeset(typ, func(t, _ types.Type) bool {\n\t\t\tif t == nil {\n\t\t\t\treturn false // empty set\n\t\t\t}\n\t\t\te, m := indexType(t)\n\t\t\tif elem == nil {\n\t\t\t\telem, mode = e, m\n\t\t\t}\n\t\t\tif debug && !types.Identical(elem, e) { // if type checked, just a sanity check\n\t\t\t\tmode = ixInvalid\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Update the mode to the most constrained address type.\n\t\t\tmode = mode.meet(m)\n\t\t\treturn mode != ixInvalid\n\t\t})\n\t\treturn elem, mode\n\t}\n\treturn nil, ixInvalid\n}\n\n// An indexMode specifies the (addressing) mode of an index operand.\n//\n// Addressing mode of an index operation is based on the set of\n// underlying types.\n// Hasse diagram of the indexMode meet semi-lattice:\n//\n//\tixVar     ixMap\n//\t  |          |\n//\tixArrVar     |\n//\t  |          |\n//\tixValue      |\n//\t   \\        /\n//\t  ixInvalid\ntype indexMode byte\n\nconst (\n\tixInvalid indexMode = iota // index is invalid\n\tixValue                    // index is a computed value (not addressable)\n\tixArrVar                   // like ixVar, but index operand contains an array\n\tixVar                      // index is an addressable variable\n\tixMap                      // index is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)\n)\n\n// meet is the address type that is constrained by both x and y.\nfunc (x indexMode) meet(y indexMode) indexMode {\n\tif (x == ixMap || y == ixMap) && x != y {\n\t\treturn ixInvalid\n\t}\n\t// Use int representation and return min.\n\tif x < y {\n\t\treturn y\n\t}\n\treturn x\n}\n"
  },
  {
    "path": "go/ssa/util.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines a number of miscellaneous utility functions.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"sync\"\n\t_ \"unsafe\" // for go:linkname hack\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\ntype unit struct{}\n\n//// Sanity checking utilities\n\n// assert panics with the message msg if p is false.\n// Avoid combining with expensive string formatting.\nfunc assert(p bool, msg string) {\n\tif !p {\n\t\tpanic(msg)\n\t}\n}\n\n//// AST utilities\n\n// isBlankIdent returns true iff e is an Ident with name \"_\".\n// They have no associated types.Object, and thus no type.\nfunc isBlankIdent(e ast.Expr) bool {\n\tid, ok := e.(*ast.Ident)\n\treturn ok && id.Name == \"_\"\n}\n\n//// Type utilities.  Some of these belong in go/types.\n\n// isNonTypeParamInterface reports whether t is an interface type but not a type parameter.\nfunc isNonTypeParamInterface(t types.Type) bool {\n\treturn !typeparams.IsTypeParam(t) && types.IsInterface(t)\n}\n\n// isBasic reports whether t is a basic type.\n// t is assumed to be an Underlying type (not Named or Alias).\nfunc isBasic(t types.Type) bool {\n\t_, ok := t.(*types.Basic)\n\treturn ok\n}\n\n// isString reports whether t is exactly a string type.\n// t is assumed to be an Underlying type (not Named or Alias).\nfunc isString(t types.Type) bool {\n\tbasic, ok := t.(*types.Basic)\n\treturn ok && basic.Info()&types.IsString != 0\n}\n\n// isByteSlice reports whether t is of the form []~bytes.\n// t is assumed to be an Underlying type (not Named or Alias).\nfunc isByteSlice(t types.Type) bool {\n\tif b, ok := t.(*types.Slice); ok {\n\t\te, _ := b.Elem().Underlying().(*types.Basic)\n\t\treturn e != nil && e.Kind() == types.Byte\n\t}\n\treturn false\n}\n\n// isRuneSlice reports whether t is of the form []~runes.\n// t is assumed to be an Underlying type (not Named or Alias).\nfunc isRuneSlice(t types.Type) bool {\n\tif b, ok := t.(*types.Slice); ok {\n\t\te, _ := b.Elem().Underlying().(*types.Basic)\n\t\treturn e != nil && e.Kind() == types.Rune\n\t}\n\treturn false\n}\n\n// isBasicConvTypes returns true when the type set of a type\n// can be one side of a Convert operation. This is when:\n// - All are basic, []byte, or []rune.\n// - At least 1 is basic.\n// - At most 1 is []byte or []rune.\nfunc isBasicConvTypes(typ types.Type) bool {\n\tbasics, cnt := 0, 0\n\tok := underIs(typ, func(t types.Type) bool {\n\t\tcnt++\n\t\tif isBasic(t) {\n\t\t\tbasics++\n\t\t\treturn true\n\t\t}\n\t\treturn isByteSlice(t) || isRuneSlice(t)\n\t})\n\treturn ok && basics >= 1 && cnt-basics <= 1\n}\n\n// isPointer reports whether t's underlying type is a pointer.\nfunc isPointer(t types.Type) bool {\n\treturn is[*types.Pointer](t.Underlying())\n}\n\n// isPointerCore reports whether t's core type is a pointer.\n//\n// (Most pointer manipulation is related to receivers, in which case\n// isPointer is appropriate. tecallers can use isPointer(t).\nfunc isPointerCore(t types.Type) bool {\n\treturn is[*types.Pointer](typeparams.CoreType(t))\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\n// recvType returns the receiver type of method obj.\nfunc recvType(obj *types.Func) types.Type {\n\treturn obj.Signature().Recv().Type()\n}\n\n// fieldOf returns the index'th field of the (core type of) a struct type;\n// otherwise returns nil.\nfunc fieldOf(typ types.Type, index int) *types.Var {\n\tif st, ok := typeparams.CoreType(typ).(*types.Struct); ok {\n\t\tif 0 <= index && index < st.NumFields() {\n\t\t\treturn st.Field(index)\n\t\t}\n\t}\n\treturn nil\n}\n\n// isUntyped reports whether typ is the type of an untyped constant.\nfunc isUntyped(typ types.Type) bool {\n\t// No Underlying/Unalias: untyped constant types cannot be Named or Alias.\n\tb, ok := typ.(*types.Basic)\n\treturn ok && b.Info()&types.IsUntyped != 0\n}\n\n// declaredWithin reports whether an object is declared within a function.\n//\n// obj must not be a method or a field.\nfunc declaredWithin(obj types.Object, fn *types.Func) bool {\n\tif obj.Pos() != token.NoPos {\n\t\treturn fn.Scope().Contains(obj.Pos()) // trust the positions if they exist.\n\t}\n\tif fn.Pkg() != obj.Pkg() {\n\t\treturn false // fast path for different packages\n\t}\n\n\t// Traverse Parent() scopes for fn.Scope().\n\tfor p := obj.Parent(); p != nil; p = p.Parent() {\n\t\tif p == fn.Scope() {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// logStack prints the formatted \"start\" message to stderr and\n// returns a closure that prints the corresponding \"end\" message.\n// Call using 'defer logStack(...)()' to show builder stack on panic.\n// Don't forget trailing parens!\nfunc logStack(format string, args ...any) func() {\n\tmsg := fmt.Sprintf(format, args...)\n\tio.WriteString(os.Stderr, msg)\n\tio.WriteString(os.Stderr, \"\\n\")\n\treturn func() {\n\t\tio.WriteString(os.Stderr, msg)\n\t\tio.WriteString(os.Stderr, \" end\\n\")\n\t}\n}\n\n// newVar creates a 'var' for use in a types.Tuple.\nfunc newVar(name string, typ types.Type) *types.Var {\n\treturn types.NewParam(token.NoPos, nil, name, typ)\n}\n\n// anonVar creates an anonymous 'var' for use in a types.Tuple.\nfunc anonVar(typ types.Type) *types.Var {\n\treturn newVar(\"\", typ)\n}\n\nvar lenResults = types.NewTuple(anonVar(tInt))\n\n// makeLen returns the len builtin specialized to type func(T)int.\nfunc makeLen(T types.Type) *Builtin {\n\tlenParams := types.NewTuple(anonVar(T))\n\treturn &Builtin{\n\t\tname: \"len\",\n\t\tsig:  types.NewSignatureType(nil, nil, nil, lenParams, lenResults, false),\n\t}\n}\n\n// receiverTypeArgs returns the type arguments to a method's receiver.\n// Returns an empty list if the receiver does not have type arguments.\nfunc receiverTypeArgs(method *types.Func) []types.Type {\n\trecv := method.Signature().Recv()\n\t_, named := typesinternal.ReceiverNamed(recv)\n\tif named == nil {\n\t\treturn nil // recv is anonymous struct/interface\n\t}\n\tts := named.TypeArgs()\n\tif ts.Len() == 0 {\n\t\treturn nil\n\t}\n\ttargs := make([]types.Type, ts.Len())\n\tfor i := 0; i < ts.Len(); i++ {\n\t\ttargs[i] = ts.At(i)\n\t}\n\treturn targs\n}\n\n// recvAsFirstArg takes a method signature and returns a function\n// signature with receiver as the first parameter.\nfunc recvAsFirstArg(sig *types.Signature) *types.Signature {\n\tparams := make([]*types.Var, 0, 1+sig.Params().Len())\n\tparams = append(params, sig.Recv())\n\tfor v := range sig.Params().Variables() {\n\t\tparams = append(params, v)\n\t}\n\treturn types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())\n}\n\n// instance returns whether an expression is a simple or qualified identifier\n// that is a generic instantiation.\nfunc instance(info *types.Info, expr ast.Expr) bool {\n\t// Compare the logic here against go/types.instantiatedIdent,\n\t// which also handles  *IndexExpr and *IndexListExpr.\n\tvar id *ast.Ident\n\tswitch x := expr.(type) {\n\tcase *ast.Ident:\n\t\tid = x\n\tcase *ast.SelectorExpr:\n\t\tid = x.Sel\n\tdefault:\n\t\treturn false\n\t}\n\t_, ok := info.Instances[id]\n\treturn ok\n}\n\n// instanceArgs returns the Instance[id].TypeArgs as a slice.\nfunc instanceArgs(info *types.Info, id *ast.Ident) []types.Type {\n\ttargList := info.Instances[id].TypeArgs\n\tif targList == nil {\n\t\treturn nil\n\t}\n\n\ttargs := make([]types.Type, targList.Len())\n\tfor i, n := 0, targList.Len(); i < n; i++ {\n\t\ttargs[i] = targList.At(i)\n\t}\n\treturn targs\n}\n\n// Mapping of a type T to a canonical instance C s.t. types.Identical(T, C).\n// Thread-safe.\ntype canonizer struct {\n\tmu    sync.Mutex\n\ttypes typeutil.Map // map from type to a canonical instance\n\tlists typeListMap  // map from a list of types to a canonical instance\n}\n\nfunc newCanonizer() *canonizer {\n\tc := &canonizer{}\n\th := typeutil.MakeHasher()\n\tc.types.SetHasher(h)\n\tc.lists.hasher = h\n\treturn c\n}\n\n// List returns a canonical representative of a list of types.\n// Representative of the empty list is nil.\nfunc (c *canonizer) List(ts []types.Type) *typeList {\n\tif len(ts) == 0 {\n\t\treturn nil\n\t}\n\n\tunaliasAll := func(ts []types.Type) []types.Type {\n\t\t// Is there some top level alias?\n\t\tvar found bool\n\t\tfor _, t := range ts {\n\t\t\tif _, ok := t.(*types.Alias); ok {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\treturn ts // no top level alias\n\t\t}\n\n\t\tcp := make([]types.Type, len(ts)) // copy with top level aliases removed.\n\t\tfor i, t := range ts {\n\t\t\tcp[i] = types.Unalias(t)\n\t\t}\n\t\treturn cp\n\t}\n\tl := unaliasAll(ts)\n\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\treturn c.lists.rep(l)\n}\n\n// Type returns a canonical representative of type T.\n// Removes top-level aliases.\n//\n// For performance, reasons the canonical instance is order-dependent,\n// and may contain deeply nested aliases.\nfunc (c *canonizer) Type(T types.Type) types.Type {\n\tT = types.Unalias(T) // remove the top level alias.\n\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tif r := c.types.At(T); r != nil {\n\t\treturn r.(types.Type)\n\t}\n\tc.types.Set(T, T)\n\treturn T\n}\n\n// A type for representing a canonized list of types.\ntype typeList []types.Type\n\nfunc (l *typeList) identical(ts []types.Type) bool {\n\tif l == nil {\n\t\treturn len(ts) == 0\n\t}\n\tn := len(*l)\n\tif len(ts) != n {\n\t\treturn false\n\t}\n\tfor i, left := range *l {\n\t\tright := ts[i]\n\t\tif !types.Identical(left, right) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\ntype typeListMap struct {\n\thasher  typeutil.Hasher\n\tbuckets map[uint32][]*typeList\n}\n\n// rep returns a canonical representative of a slice of types.\nfunc (m *typeListMap) rep(ts []types.Type) *typeList {\n\tif m == nil || len(ts) == 0 {\n\t\treturn nil\n\t}\n\n\tif m.buckets == nil {\n\t\tm.buckets = make(map[uint32][]*typeList)\n\t}\n\n\th := m.hash(ts)\n\tbucket := m.buckets[h]\n\tfor _, l := range bucket {\n\t\tif l.identical(ts) {\n\t\t\treturn l\n\t\t}\n\t}\n\n\t// not present. create a representative.\n\tcp := make(typeList, len(ts))\n\tcopy(cp, ts)\n\trep := &cp\n\n\tm.buckets[h] = append(bucket, rep)\n\treturn rep\n}\n\nfunc (m *typeListMap) hash(ts []types.Type) uint32 {\n\tif m == nil {\n\t\treturn 0\n\t}\n\t// Some smallish prime far away from typeutil.Hash.\n\tn := len(ts)\n\th := uint32(13619) + 2*uint32(n)\n\tfor i := range n {\n\t\th += 3 * m.hasher.Hash(ts[i])\n\t}\n\treturn h\n}\n\n// instantiateMethod instantiates m with targs and returns a canonical representative for this method.\nfunc (canon *canonizer) instantiateMethod(m *types.Func, targs []types.Type, ctxt *types.Context) *types.Func {\n\trecv := recvType(m)\n\tif p, ok := types.Unalias(recv).(*types.Pointer); ok {\n\t\trecv = p.Elem()\n\t}\n\tnamed := types.Unalias(recv).(*types.Named)\n\tinst, err := types.Instantiate(ctxt, named.Origin(), targs, false)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\trep := canon.Type(inst)\n\tobj, _, _ := types.LookupFieldOrMethod(rep, true, m.Pkg(), m.Name())\n\treturn obj.(*types.Func)\n}\n\n// Exposed to ssautil using the linkname hack.\n//\n//go:linkname isSyntactic golang.org/x/tools/go/ssa.isSyntactic\nfunc isSyntactic(pkg *Package) bool { return pkg.syntax }\n"
  },
  {
    "path": "go/ssa/wrappers.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage ssa\n\n// This file defines synthesis of Functions that delegate to declared\n// methods; they come in three kinds:\n//\n// (1) wrappers: methods that wrap declared methods, performing\n//     implicit pointer indirections and embedded field selections.\n//\n// (2) thunks: funcs that wrap declared methods.  Like wrappers,\n//     thunks perform indirections and field selections. The thunk's\n//     first parameter is used as the receiver for the method call.\n//\n// (3) bounds: funcs that wrap declared methods.  The bound's sole\n//     free variable, supplied by a closure, is used as the receiver\n//     for the method call.  No indirections or field selections are\n//     performed since they can be done before the call.\n\nimport (\n\t\"fmt\"\n\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// -- wrappers -----------------------------------------------------------\n\n// createWrapper returns a synthetic method that delegates to the\n// declared method denoted by meth.Obj(), first performing any\n// necessary pointer indirections or field selections implied by meth.\n//\n// The resulting method's receiver type is meth.Recv().\n//\n// This function is versatile but quite subtle!  Consider the\n// following axes of variation when making changes:\n//   - optional receiver indirection\n//   - optional implicit field selections\n//   - meth.Obj() may denote a concrete or an interface method\n//   - the result may be a thunk or a wrapper.\nfunc createWrapper(prog *Program, sel *selection) *Function {\n\tobj := sel.obj.(*types.Func)      // the declared function\n\tsig := sel.typ.(*types.Signature) // type of this wrapper\n\n\tvar recv *types.Var // wrapper's receiver or thunk's params[0]\n\tname := obj.Name()\n\tvar description string\n\tif sel.kind == types.MethodExpr {\n\t\tname += \"$thunk\"\n\t\tdescription = \"thunk\"\n\t\trecv = sig.Params().At(0)\n\t} else {\n\t\tdescription = \"wrapper\"\n\t\trecv = sig.Recv()\n\t}\n\n\tdescription = fmt.Sprintf(\"%s for %s\", description, sel.obj)\n\tif prog.mode&LogSource != 0 {\n\t\tdefer logStack(\"create %s to (%s)\", description, recv.Type())()\n\t}\n\t/* method wrapper */\n\treturn &Function{\n\t\tname:      name,\n\t\tmethod:    sel,\n\t\tobject:    obj,\n\t\tSignature: sig,\n\t\tSynthetic: description,\n\t\tProg:      prog,\n\t\tpos:       obj.Pos(),\n\t\t// wrappers have no syntax\n\t\tbuild:     (*builder).buildWrapper,\n\t\tsyntax:    nil,\n\t\tinfo:      nil,\n\t\tgoversion: \"\",\n\t}\n}\n\n// buildWrapper builds fn.Body for a method wrapper.\nfunc (b *builder) buildWrapper(fn *Function) {\n\tvar recv *types.Var // wrapper's receiver or thunk's params[0]\n\tvar start int       // first regular param\n\tif fn.method.kind == types.MethodExpr {\n\t\trecv = fn.Signature.Params().At(0)\n\t\tstart = 1\n\t} else {\n\t\trecv = fn.Signature.Recv()\n\t}\n\n\tfn.startBody()\n\tfn.addSpilledParam(recv)\n\tcreateParams(fn, start)\n\n\tindices := fn.method.index\n\n\tvar v Value = fn.Locals[0] // spilled receiver\n\tif isPointer(fn.method.recv) {\n\t\tv = emitLoad(fn, v)\n\n\t\t// For simple indirection wrappers, perform an informative nil-check:\n\t\t// \"value method (T).f called using nil *T pointer\"\n\t\tif len(indices) == 1 && !isPointer(recvType(fn.object)) {\n\t\t\tvar c Call\n\t\t\tc.Call.Value = &Builtin{\n\t\t\t\tname: \"ssa:wrapnilchk\",\n\t\t\t\tsig:  types.NewSignatureType(nil, nil, nil, types.NewTuple(anonVar(fn.method.recv), anonVar(tString), anonVar(tString)), types.NewTuple(anonVar(fn.method.recv)), false),\n\t\t\t}\n\t\t\tc.Call.Args = []Value{\n\t\t\t\tv,\n\t\t\t\tstringConst(typeparams.MustDeref(fn.method.recv).String()),\n\t\t\t\tstringConst(fn.method.obj.Name()),\n\t\t\t}\n\t\t\tc.setType(v.Type())\n\t\t\tv = fn.emit(&c)\n\t\t}\n\t}\n\n\t// Invariant: v is a pointer, either\n\t//   value of *A receiver param, or\n\t// address of  A spilled receiver.\n\n\t// We use pointer arithmetic (FieldAddr possibly followed by\n\t// Load) in preference to value extraction (Field possibly\n\t// preceded by Load).\n\n\tv = emitImplicitSelections(fn, v, indices[:len(indices)-1], token.NoPos)\n\n\t// Invariant: v is a pointer, either\n\t//   value of implicit *C field, or\n\t// address of implicit  C field.\n\n\tvar c Call\n\tif r := recvType(fn.object); !types.IsInterface(r) { // concrete method\n\t\tif !isPointer(r) {\n\t\t\tv = emitLoad(fn, v)\n\t\t}\n\t\tc.Call.Value = fn.Prog.objectMethod(fn.object, b)\n\t\tc.Call.Args = append(c.Call.Args, v)\n\t} else {\n\t\tc.Call.Method = fn.object\n\t\tc.Call.Value = emitLoad(fn, v) // interface (possibly a typeparam)\n\t}\n\tfor _, arg := range fn.Params[1:] {\n\t\tc.Call.Args = append(c.Call.Args, arg)\n\t}\n\temitTailCall(fn, &c)\n\tfn.finishBody()\n}\n\n// createParams creates parameters for wrapper method fn based on its\n// Signature.Params, which do not include the receiver.\n// start is the index of the first regular parameter to use.\nfunc createParams(fn *Function, start int) {\n\ttparams := fn.Signature.Params()\n\tfor i, n := start, tparams.Len(); i < n; i++ {\n\t\tfn.addParamVar(tparams.At(i))\n\t}\n}\n\n// -- bounds -----------------------------------------------------------\n\n// createBound returns a bound method wrapper (or \"bound\"), a synthetic\n// function that delegates to a concrete or interface method denoted\n// by obj.  The resulting function has no receiver, but has one free\n// variable which will be used as the method's receiver in the\n// tail-call.\n//\n// Use MakeClosure with such a wrapper to construct a bound method\n// closure.  e.g.:\n//\n//\ttype T int          or:  type T interface { meth() }\n//\tfunc (t T) meth()\n//\tvar t T\n//\tf := t.meth\n//\tf() // calls t.meth()\n//\n// f is a closure of a synthetic wrapper defined as if by:\n//\n//\tf := func() { return t.meth() }\n//\n// Unlike createWrapper, createBound need perform no indirection or field\n// selections because that can be done before the closure is\n// constructed.\nfunc createBound(prog *Program, obj *types.Func) *Function {\n\tdescription := fmt.Sprintf(\"bound method wrapper for %s\", obj)\n\tif prog.mode&LogSource != 0 {\n\t\tdefer logStack(\"%s\", description)()\n\t}\n\t/* bound method wrapper */\n\tfn := &Function{\n\t\tname:      obj.Name() + \"$bound\",\n\t\tobject:    obj,\n\t\tSignature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver\n\t\tSynthetic: description,\n\t\tProg:      prog,\n\t\tpos:       obj.Pos(),\n\t\t// wrappers have no syntax\n\t\tbuild:     (*builder).buildBound,\n\t\tsyntax:    nil,\n\t\tinfo:      nil,\n\t\tgoversion: \"\",\n\t}\n\tfn.FreeVars = []*FreeVar{{name: \"recv\", typ: recvType(obj), parent: fn}} // (cyclic)\n\treturn fn\n}\n\n// buildBound builds fn.Body for a bound method closure.\nfunc (b *builder) buildBound(fn *Function) {\n\tfn.startBody()\n\tcreateParams(fn, 0)\n\tvar c Call\n\n\trecv := fn.FreeVars[0]\n\tif !types.IsInterface(recvType(fn.object)) { // concrete\n\t\tc.Call.Value = fn.Prog.objectMethod(fn.object, b)\n\t\tc.Call.Args = []Value{recv}\n\t} else {\n\t\tc.Call.Method = fn.object\n\t\tc.Call.Value = recv // interface (possibly a typeparam)\n\t}\n\tfor _, arg := range fn.Params {\n\t\tc.Call.Args = append(c.Call.Args, arg)\n\t}\n\temitTailCall(fn, &c)\n\tfn.finishBody()\n}\n\n// -- thunks -----------------------------------------------------------\n\n// createThunk returns a thunk, a synthetic function that delegates to a\n// concrete or interface method denoted by sel.obj.  The resulting\n// function has no receiver, but has an additional (first) regular\n// parameter.\n//\n// Precondition: sel.kind == types.MethodExpr.\n//\n//\ttype T int          or:  type T interface { meth() }\n//\tfunc (t T) meth()\n//\tf := T.meth\n//\tvar t T\n//\tf(t) // calls t.meth()\n//\n// f is a synthetic wrapper defined as if by:\n//\n//\tf := func(t T) { return t.meth() }\nfunc createThunk(prog *Program, sel *selection) *Function {\n\tif sel.kind != types.MethodExpr {\n\t\tpanic(sel)\n\t}\n\n\tfn := createWrapper(prog, sel)\n\tif fn.Signature.Recv() != nil {\n\t\tpanic(fn) // unexpected receiver\n\t}\n\n\treturn fn\n}\n\nfunc changeRecv(s *types.Signature, recv *types.Var) *types.Signature {\n\treturn types.NewSignatureType(recv, nil, nil, s.Params(), s.Results(), s.Variadic())\n}\n\n// A local version of *types.Selection.\n// Needed for some additional control, such as creating a MethodExpr for an instantiation.\ntype selection struct {\n\tkind     types.SelectionKind\n\trecv     types.Type\n\ttyp      types.Type\n\tobj      types.Object\n\tindex    []int\n\tindirect bool\n}\n\nfunc toSelection(sel *types.Selection) *selection {\n\treturn &selection{\n\t\tkind:     sel.Kind(),\n\t\trecv:     sel.Recv(),\n\t\ttyp:      sel.Type(),\n\t\tobj:      sel.Obj(),\n\t\tindex:    sel.Index(),\n\t\tindirect: sel.Indirect(),\n\t}\n}\n\n// -- instantiations --------------------------------------------------\n\n// buildInstantiationWrapper builds the body of an instantiation\n// wrapper fn. The body calls the original generic function,\n// bracketed by ChangeType conversions on its arguments and results.\nfunc (b *builder) buildInstantiationWrapper(fn *Function) {\n\torig := fn.topLevelOrigin\n\tsig := fn.Signature\n\n\tfn.startBody()\n\tif sig.Recv() != nil {\n\t\tfn.addParamVar(sig.Recv())\n\t}\n\tcreateParams(fn, 0)\n\n\t// Create body. Add a call to origin generic function\n\t// and make type changes between argument and parameters,\n\t// as well as return values.\n\tvar c Call\n\tc.Call.Value = orig\n\tif res := orig.Signature.Results(); res.Len() == 1 {\n\t\tc.typ = res.At(0).Type()\n\t} else {\n\t\tc.typ = res\n\t}\n\n\t// parameter of instance becomes an argument to the call\n\t// to the original generic function.\n\targOffset := 0\n\tfor i, arg := range fn.Params {\n\t\tvar typ types.Type\n\t\tif i == 0 && sig.Recv() != nil {\n\t\t\ttyp = orig.Signature.Recv().Type()\n\t\t\targOffset = 1\n\t\t} else {\n\t\t\ttyp = orig.Signature.Params().At(i - argOffset).Type()\n\t\t}\n\t\tc.Call.Args = append(c.Call.Args, emitTypeCoercion(fn, arg, typ))\n\t}\n\n\tresults := fn.emit(&c)\n\tvar ret Return\n\tswitch res := sig.Results(); res.Len() {\n\tcase 0:\n\t\t// no results, do nothing.\n\tcase 1:\n\t\tret.Results = []Value{emitTypeCoercion(fn, results, res.At(0).Type())}\n\tdefault:\n\t\tfor i := 0; i < sig.Results().Len(); i++ {\n\t\t\tv := emitExtract(fn, results, i)\n\t\t\tret.Results = append(ret.Results, emitTypeCoercion(fn, v, res.At(i).Type()))\n\t\t}\n\t}\n\n\tfn.emit(&ret)\n\tfn.currentBlock = nil\n\n\tfn.finishBody()\n}\n"
  },
  {
    "path": "go/types/internal/play/play.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.23\n\n// The play program is a playground for go/types: a simple web-based\n// text editor into which the user can enter a Go program, select a\n// region, and see type information about it.\n//\n// It is intended for convenient exploration and debugging of\n// go/types. The command and its web interface are not officially\n// supported and they may be changed arbitrarily in the future.\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// TODO(adonovan):\n// - show line numbers next to textarea.\n// - mention this in the go/types tutorial.\n// - display versions of go/types and go command.\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handleRoot)\n\thttp.HandleFunc(\"/main.js\", handleJS)\n\thttp.HandleFunc(\"/main.css\", handleCSS)\n\thttp.HandleFunc(\"/select.json\", handleSelectJSON)\n\tconst addr = \"localhost:9999\"\n\tlog.Printf(\"Listening on http://%s\", addr)\n\tlog.Fatal(http.ListenAndServe(addr, nil))\n}\n\nfunc handleSelectJSON(w http.ResponseWriter, req *http.Request) {\n\t// Parse request.\n\tif err := req.ParseForm(); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\tstartOffset, err := strconv.Atoi(req.Form.Get(\"start\"))\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"start: %v\", err), http.StatusBadRequest)\n\t\treturn\n\t}\n\tendOffset, err := strconv.Atoi(req.Form.Get(\"end\"))\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"end: %v\", err), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Write Go program to temporary file.\n\tf, err := os.CreateTemp(\"\", \"play-*.go\")\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif _, err := io.Copy(f, req.Body); err != nil {\n\t\tf.Close() // ignore error\n\t\thttp.Error(w, fmt.Sprintf(\"can't read body: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif err := f.Close(); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer func() {\n\t\t_ = os.Remove(f.Name()) // ignore error\n\t}()\n\n\t// Load and type check it.\n\tcfg := &packages.Config{\n\t\tFset: token.NewFileSet(),\n\t\tMode: packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo,\n\t\tDir:  filepath.Dir(f.Name()),\n\t}\n\tpkgs, err := packages.Load(cfg, \"file=\"+f.Name())\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"load: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tpkg := pkgs[0]\n\n\t// -- Format the response --\n\n\tout := new(strings.Builder)\n\n\t// Parse/type error information.\n\tif len(pkg.Errors) > 0 {\n\t\tfmt.Fprintf(out, \"Errors:\\n\")\n\t\tfor _, err := range pkg.Errors {\n\t\t\tfmt.Fprintf(out, \"%s: %s\\n\", err.Pos, err.Msg)\n\t\t}\n\t\tfmt.Fprintf(out, \"\\n\")\n\t}\n\n\tfset := pkg.Fset\n\tfile := pkg.Syntax[0]\n\ttokFile := fset.File(file.FileStart)\n\tstartPos := tokFile.Pos(startOffset)\n\tendPos := tokFile.Pos(endOffset)\n\n\t// Syntax information\n\tpath, exact := goastutil.PathEnclosingInterval(file, startPos, endPos)\n\tfmt.Fprintf(out, \"Path enclosing interval #%d-%d [exact=%t]:\\n\",\n\t\tstartOffset, endOffset, exact)\n\tvar innermostExpr ast.Expr\n\tfor i, n := range path {\n\t\t// Show set of names defined in each scope.\n\t\tscopeNames := \"\"\n\t\t{\n\t\t\tnode := n\n\t\t\tprefix := \"\"\n\n\t\t\t// A function (Func{Decl.Lit}) doesn't have a scope of its\n\t\t\t// own, nor does its Body: only nested BlockStmts do.\n\t\t\t// The type parameters, parameters, and locals are all\n\t\t\t// in the scope associated with the FuncType; show it.\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tnode = n.Type\n\t\t\t\tprefix = \"Type.\"\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tnode = n.Type\n\t\t\t\tprefix = \"Type.\"\n\t\t\t}\n\n\t\t\tif scope := pkg.TypesInfo.Scopes[node]; scope != nil {\n\t\t\t\tscopeNames = fmt.Sprintf(\" %sScope={%s}\",\n\t\t\t\t\tprefix,\n\t\t\t\t\tstrings.Join(scope.Names(), \", \"))\n\t\t\t}\n\t\t}\n\n\t\t// TODO(adonovan): turn these into links to highlight the source.\n\t\tstart, end := fset.Position(n.Pos()), fset.Position(n.End())\n\t\tfmt.Fprintf(out, \"[%d] %T @ %d:%d-%d:%d (#%d-%d)%s\\n\",\n\t\t\ti, n,\n\t\t\tstart.Line, start.Column, end.Line,\n\t\t\tend.Column, start.Offset, end.Offset,\n\t\t\tscopeNames)\n\t\tif e, ok := n.(ast.Expr); ok && innermostExpr == nil {\n\t\t\tinnermostExpr = e\n\t\t}\n\t}\n\t// Show the Cursor.Enclosing stack too.\n\t// It's usually the same, but may differ in edge\n\t// cases (e.g. around FuncType.Func).\n\tcurFile, _ := inspector.New([]*ast.File{file}).Root().FirstChild()\n\tif cur, ok := curFile.FindByPos(startPos, endPos); ok {\n\t\tfmt.Fprintf(out, \"Cursor.FindByPos().Enclosing() = %v\\n\",\n\t\t\tslices.Collect(cur.Enclosing()))\n\t} else {\n\t\tfmt.Fprintf(out, \"Cursor.FindPos() failed\\n\")\n\t}\n\t// And show the astutil.Select result (enclosing, leftmost & rightmost enclosed).\n\tif curEnclosing, curStart, curEnd, err := astutil.Select(curFile, startPos, endPos); err == nil {\n\t\tformat := func(cur inspector.Cursor) string {\n\t\t\treturn fmt.Sprintf(\"%T@%v\", cur.Node(), fset.Position(cur.Node().Pos()))\n\t\t}\n\t\tfmt.Fprintf(out, \"astutil.Select() = (%s, %s, %s)\\n\",\n\t\t\tformat(curEnclosing), format(curStart), format(curEnd))\n\t} else {\n\t\tfmt.Fprintf(out, \"astutil.Select() = %v\", err)\n\t}\n\tfmt.Fprintf(out, \"\\n\")\n\n\t// Expression type information\n\tif innermostExpr != nil {\n\t\tif tv, ok := pkg.TypesInfo.Types[innermostExpr]; ok {\n\t\t\tvar modes []string\n\t\t\tfor _, mode := range []struct {\n\t\t\t\tname      string\n\t\t\t\tcondition func(types.TypeAndValue) bool\n\t\t\t}{\n\t\t\t\t{\"IsVoid\", types.TypeAndValue.IsVoid},\n\t\t\t\t{\"IsType\", types.TypeAndValue.IsType},\n\t\t\t\t{\"IsBuiltin\", types.TypeAndValue.IsBuiltin},\n\t\t\t\t{\"IsValue\", types.TypeAndValue.IsValue},\n\t\t\t\t{\"IsNil\", types.TypeAndValue.IsNil},\n\t\t\t\t{\"Addressable\", types.TypeAndValue.Addressable},\n\t\t\t\t{\"Assignable\", types.TypeAndValue.Assignable},\n\t\t\t\t{\"HasOk\", types.TypeAndValue.HasOk},\n\t\t\t} {\n\t\t\t\tif mode.condition(tv) {\n\t\t\t\t\tmodes = append(modes, mode.name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(out, \"%T has type %v, mode %s\",\n\t\t\t\tinnermostExpr, tv.Type, modes)\n\t\t\tif tu := tv.Type.Underlying(); tu != tv.Type {\n\t\t\t\tfmt.Fprintf(out, \", underlying type %v\", tu)\n\t\t\t}\n\t\t\tif tc := typeparams.CoreType(tv.Type); tc != tv.Type {\n\t\t\t\tfmt.Fprintf(out, \", core type %v\", tc)\n\t\t\t}\n\t\t\tif tv.Value != nil {\n\t\t\t\tfmt.Fprintf(out, \", and constant value %v\", tv.Value)\n\t\t\t}\n\t\t} else {\n\t\t\tfmt.Fprintf(out, \"%T has no type\", innermostExpr)\n\t\t}\n\t\tfmt.Fprintf(out, \"\\n\\n\")\n\t}\n\n\t// selection x.f information (if cursor is over .f)\n\tfor _, n := range path[:min(2, len(path))] {\n\t\tif sel, ok := n.(*ast.SelectorExpr); ok {\n\t\t\tseln, ok := pkg.TypesInfo.Selections[sel]\n\t\t\tif ok {\n\t\t\t\tfmt.Fprintf(out, \"Selection: %s recv=%v obj=%v type=%v indirect=%t index=%d\\n\\n\",\n\t\t\t\t\tstrings.Fields(\"FieldVal MethodVal MethodExpr\")[seln.Kind()],\n\t\t\t\t\tseln.Recv(),\n\t\t\t\t\tseln.Obj(),\n\t\t\t\t\tseln.Type(),\n\t\t\t\t\tseln.Indirect(),\n\t\t\t\t\tseln.Index())\n\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(out, \"Selector is qualified identifier.\\n\\n\")\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Object type information.\n\tswitch n := path[0].(type) {\n\tcase *ast.Ident:\n\t\t// An embedded field is both a def and a use.\n\t\tif obj, ok := pkg.TypesInfo.Defs[n]; ok {\n\t\t\tif obj == nil {\n\t\t\t\tfmt.Fprintf(out, \"nil def\") // e.g. package name, \"_\", type switch\n\t\t\t} else {\n\t\t\t\tformatObj(out, fset, \"def\", obj)\n\t\t\t}\n\t\t}\n\t\tif obj, ok := pkg.TypesInfo.Uses[n]; ok {\n\t\t\tformatObj(out, fset, \"use\", obj)\n\t\t}\n\tdefault:\n\t\tif obj, ok := pkg.TypesInfo.Implicits[n]; ok {\n\t\t\tformatObj(out, fset, \"implicit def\", obj)\n\t\t}\n\t}\n\tfmt.Fprintf(out, \"\\n\")\n\n\t// Pretty-print of selected syntax.\n\tfmt.Fprintf(out, \"Pretty-printed:\\n\")\n\tformat.Node(out, fset, path[0])\n\tfmt.Fprintf(out, \"\\n\\n\")\n\n\t// Syntax debug output.\n\tfmt.Fprintf(out, \"Syntax:\\n\")\n\tast.Fprint(out, fset, path[0], nil) // ignore errors\n\tfmt.Fprintf(out, \"\\n\\n\")\n\n\t// Show inventory of all objects, including addresses to disambiguate.\n\tfmt.Fprintf(out, \"Objects:\\n\")\n\tfor curId := range curFile.Preorder((*ast.Ident)(nil)) {\n\t\tid := curId.Node().(*ast.Ident)\n\t\tif obj := pkg.TypesInfo.Defs[id]; obj != nil {\n\t\t\tfmt.Fprintf(out, \"%s: def %v (%p)\\n\", fset.Position(id.Pos()), obj, obj)\n\t\t}\n\t\tif obj, ok := pkg.TypesInfo.Uses[id]; ok {\n\t\t\tfmt.Fprintf(out, \"%s: use %v (%p)\\n\", fset.Position(id.Pos()), obj, obj)\n\t\t}\n\t}\n\tfmt.Fprintf(out, \"\\n\\n\")\n\n\t// Clean up the messy temp file name.\n\toutStr := strings.ReplaceAll(out.String(), f.Name(), \"play.go\")\n\n\t// Send response.\n\tvar respJSON struct {\n\t\tOut string\n\t}\n\trespJSON.Out = outStr\n\n\tdata, _ := json.Marshal(respJSON) // can't fail\n\tw.Write(data)                     // ignore error\n}\n\nfunc formatObj(out *strings.Builder, fset *token.FileSet, ref string, obj types.Object) {\n\t// e.g. *types.Func -> \"func\"\n\tkind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), \"*types.\"))\n\n\t// Show origin of generics, and refine kind.\n\tvar origin types.Object\n\tswitch obj := obj.(type) {\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\tkind = \"field\"\n\t\t}\n\t\torigin = obj.Origin()\n\n\tcase *types.Func:\n\t\tif recv := obj.Signature().Recv(); recv != nil {\n\t\t\tkind = fmt.Sprintf(\"method (with recv %v)\", recv.Type())\n\t\t}\n\t\torigin = obj.Origin()\n\n\tcase *types.TypeName:\n\t\tif obj.IsAlias() {\n\t\t\tkind = \"type alias\"\n\t\t}\n\t\tif named, ok := types.Unalias(obj.Type()).(*types.Named); ok {\n\t\t\torigin = named.Obj()\n\t\t}\n\t}\n\n\t// Include the pointer value to help distinguish fn and fn.Origin().\n\t// (Beware that every invocation creates new pointers so they are\n\t// only comparable within a single result page. Hence the need\n\t// for the inventory of objects below.)\n\tfmt.Fprintf(out, \"%s of %s %s of type %v declared at %v (%p)\",\n\t\tref, kind, obj.Name(), obj.Type(), fset.Position(obj.Pos()), obj)\n\tif origin != nil && origin != obj {\n\t\tfmt.Fprintf(out, \" (instantiation of %v)\", origin.Type())\n\t}\n\tfmt.Fprintf(out, \"\\n\\n\")\n\n\tfmt.Fprintf(out, \"Type:\\n\")\n\tdescribeType(out, obj.Type())\n\tfmt.Fprintf(out, \"\\n\")\n\n\t// method set\n\tif methods := typeutil.IntuitiveMethodSet(obj.Type(), nil); len(methods) > 0 {\n\t\tfmt.Fprintf(out, \"Methods:\\n\")\n\t\tfor _, m := range methods {\n\t\t\tfmt.Fprintln(out, m)\n\t\t}\n\t\tfmt.Fprintf(out, \"\\n\")\n\t}\n\n\t// scope tree\n\tfmt.Fprintf(out, \"Scopes:\\n\")\n\tfor scope := obj.Parent(); scope != nil; scope = scope.Parent() {\n\t\tvar (\n\t\t\tstart = fset.Position(scope.Pos())\n\t\t\tend   = fset.Position(scope.End())\n\t\t)\n\t\tfmt.Fprintf(out, \"%d:%d-%d:%d: %s\\n\",\n\t\t\tstart.Line, start.Column, end.Line, end.Column, scope)\n\t}\n}\n\n// describeType formats t to out in a way that makes it clear what methods to call on t to\n// get at its parts.\n// describeType assumes t was constructed by the type checker, so it doesn't check\n// for recursion. The type checker replaces recursive alias types, which are illegal,\n// with a BasicType that says as much. Other types that it constructs are recursive\n// only via a name, and this function does not traverse names.\nfunc describeType(out *strings.Builder, t types.Type) {\n\tdepth := -1\n\n\tvar ft func(string, types.Type)\n\tft = func(prefix string, t types.Type) {\n\t\tdepth++\n\t\tdefer func() { depth-- }()\n\n\t\tfor range depth {\n\t\t\tfmt.Fprint(out, \".  \")\n\t\t}\n\n\t\tfmt.Fprintf(out, \"%s%T:\", prefix, t)\n\t\tswitch t := t.(type) {\n\t\tcase *types.Basic:\n\t\t\tfmt.Fprintf(out, \" Name: %q\\n\", t.Name())\n\t\tcase *types.Pointer:\n\t\t\tfmt.Fprintln(out)\n\t\t\tft(\"Elem: \", t.Elem())\n\t\tcase *types.Slice:\n\t\t\tfmt.Fprintln(out)\n\t\t\tft(\"Elem: \", t.Elem())\n\t\tcase *types.Array:\n\t\t\tfmt.Fprintf(out, \" Len: %d\\n\", t.Len())\n\t\t\tft(\"Elem: \", t.Elem())\n\t\tcase *types.Map:\n\t\t\tfmt.Fprintln(out)\n\t\t\tft(\"Key:  \", t.Key())\n\t\t\tft(\"Elem: \", t.Elem())\n\t\tcase *types.Chan:\n\t\t\tfmt.Fprintf(out, \" Dir: %s\\n\", chanDirs[t.Dir()])\n\t\t\tft(\"Elem: \", t.Elem())\n\t\tcase *types.Alias:\n\t\t\tfmt.Fprintf(out, \" Name: %q\\n\", t.Obj().Name())\n\t\t\tft(\"Rhs: \", t.Rhs())\n\t\tdefault:\n\t\t\t// For types we may have missed or which have too much to bother with,\n\t\t\t// print their string representation.\n\t\t\t// TODO(jba): print more about struct types (their fields) and interface and named\n\t\t\t// types (their methods).\n\t\t\tfmt.Fprintf(out, \" %s\\n\", t)\n\t\t}\n\t}\n\n\tft(\"\", t)\n}\n\nvar chanDirs = []string{\n\t\"SendRecv\",\n\t\"SendOnly\",\n\t\"RecvOnly\",\n}\n\nfunc handleRoot(w http.ResponseWriter, req *http.Request) { io.WriteString(w, mainHTML) }\nfunc handleJS(w http.ResponseWriter, req *http.Request)   { io.WriteString(w, mainJS) }\nfunc handleCSS(w http.ResponseWriter, req *http.Request)  { io.WriteString(w, mainCSS) }\n\n// TODO(adonovan): avoid CSS reliance on quirks mode and enable strict mode (<!DOCTYPE html>).\nconst mainHTML = `<html>\n<head>\n<script src=\"/main.js\"></script>\n<link rel=\"stylesheet\" href=\"/main.css\"></link>\n</head>\n<body onload=\"onLoad()\">\n<h1>go/types playground</h1>\n<p>Select an expression to see information about it.</p>\n<textarea rows='25' id='src'>\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, world!\")\n}\n</textarea>\n<div id='out'/>\n</body>\n</html>\n`\n\nconst mainJS = `\nfunction onSelectionChange() {\n\tvar start = document.activeElement.selectionStart;\n\tvar end = document.activeElement.selectionEnd;\n\tvar req = new XMLHttpRequest();\n\treq.open(\"POST\", \"/select.json?start=\" + start + \"&end=\" + end, false);\n\treq.send(document.activeElement.value);\n\tvar resp = JSON.parse(req.responseText);\n\tdocument.getElementById('out').innerText = resp.Out;\n}\n\nfunction onLoad() {\n\tdocument.getElementById(\"src\").addEventListener('select', onSelectionChange)\n}\n`\n\nconst mainCSS = `\ntextarea { width: 6in; }\nbody { color: gray; }\ndiv#out { font-family: monospace; font-size: 80%; }\n`\n"
  },
  {
    "path": "go/types/objectpath/objectpath.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package objectpath defines a naming scheme for types.Objects\n// (that is, named entities in Go programs) relative to their enclosing\n// package.\n//\n// Type-checker objects are canonical, so they are usually identified by\n// their address in memory (a pointer), but a pointer has meaning only\n// within one address space. By contrast, objectpath names allow the\n// identity of an object to be sent from one program to another,\n// establishing a correspondence between types.Object variables that are\n// distinct but logically equivalent.\n//\n// A single object may have multiple paths. In this example,\n//\n//\ttype A struct{ X int }\n//\ttype B A\n//\n// the field X has two paths due to its membership of both A and B.\n// The For(obj) function always returns one of these paths, arbitrarily\n// but consistently.\npackage objectpath\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// TODO(adonovan): think about generic aliases.\n\n// A Path is an opaque name that identifies a types.Object\n// relative to its package. Conceptually, the name consists of a\n// sequence of destructuring operations applied to the package scope\n// to obtain the original object.\n// The name does not include the package itself.\ntype Path string\n\n// Encoding\n//\n// An object path is a textual and (with training) human-readable encoding\n// of a sequence of destructuring operators, starting from a types.Package.\n// The sequences represent a path through the package/object/type graph.\n// We classify these operators by their type:\n//\n//\tPO package->object\tPackage.Scope.Lookup\n//\tOT  object->type \tObject.Type\n//\tTT    type->type \tType.{Elem,Key,{,{,Recv}Type}Params,Results,Underlying,Rhs} [EKPRUTrCa]\n//\tTO   type->object\tType.{At,Field,Method,Obj} [AFMO]\n//\n// All valid paths start with a package and end at an object\n// and thus may be defined by the regular language:\n//\n//\tobjectpath = PO (OT TT* TO)*\n//\n// The concrete encoding follows directly:\n//   - The only PO operator is Package.Scope.Lookup, which requires an identifier.\n//   - The only OT operator is Object.Type,\n//     which we encode as '.' because dot cannot appear in an identifier.\n//   - The TT operators are encoded as [EKPRUTrCa];\n//     two of these ({,Recv}TypeParams) require an integer operand,\n//     which is encoded as a string of decimal digits.\n//   - The TO operators are encoded as [AFMO];\n//     three of these (At,Field,Method) require an integer operand,\n//     which is encoded as a string of decimal digits.\n//     These indices are stable across different representations\n//     of the same package, even source and export data.\n//     The indices used are implementation specific and may not correspond to\n//     the argument to the go/types function.\n//\n// In the example below,\n//\n//\tpackage p\n//\n//\ttype T interface {\n//\t\tf() (a string, b struct{ X int })\n//\t}\n//\n// field X has the path \"T.UM0.RA1.F0\",\n// representing the following sequence of operations:\n//\n//\tp.Lookup(\"T\")\t\t\t\t\tT\n//\t.Type().Underlying().Method(0).\t\t\tf\n//\t.Type().Results().At(1)\t\t\t\tb\n//\t.Type().Field(0)\t\t\t\t\tX\n//\n// The encoding is not maximally compact---every R or P is\n// followed by an A, for example---but this simplifies the\n// encoder and decoder.\nconst (\n\t// object->type operators\n\topType = '.' // .Type()\t\t  (Object)\n\n\t// type->type operators\n\topElem          = 'E' // .Elem()\t\t(Pointer, Slice, Array, Chan, Map)\n\topKey           = 'K' // .Key()\t\t\t(Map)\n\topParams        = 'P' // .Params()\t\t(Signature)\n\topResults       = 'R' // .Results()\t\t(Signature)\n\topUnderlying    = 'U' // .Underlying()\t\t(Named)\n\topTypeParam     = 'T' // .TypeParams.At(i)\t(Named, Signature)\n\topRecvTypeParam = 'r' // .RecvTypeParams.At(i)\t(Signature)\n\topConstraint    = 'C' // .Constraint()\t\t(TypeParam)\n\topRhs           = 'a' // .Rhs()\t\t\t(Alias)\n\n\t// type->object operators\n\topAt     = 'A' // .At(i)\t(Tuple)\n\topField  = 'F' // .Field(i)\t(Struct)\n\topMethod = 'M' // .Method(i)\t(Named or Interface; not Struct: \"promoted\" names are ignored)\n\topObj    = 'O' // .Obj()\t(Named, TypeParam)\n)\n\n// For is equivalent to new(Encoder).For(obj).\n//\n// It may be more efficient to reuse a single Encoder across several calls.\nfunc For(obj types.Object) (Path, error) {\n\treturn new(Encoder).For(obj)\n}\n\n// An Encoder amortizes the cost of encoding the paths of multiple objects.\n// The zero value of an Encoder is ready to use.\ntype Encoder struct {\n\tscopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects\n}\n\n// For returns the path to an object relative to its package,\n// or an error if the object is not accessible from the package's Scope.\n//\n// The For function guarantees to return a path only for the following objects:\n// - package-level types\n// - exported package-level non-types\n// - methods\n// - parameter and result variables\n// - struct fields\n// These objects are sufficient to define the API of their package.\n// The objects described by a package's export data are drawn from this set.\n//\n// The set of objects accessible from a package's Scope depends on\n// whether the package was produced by type-checking syntax, or\n// reading export data; the latter may have a smaller Scope since\n// export data trims objects that are not reachable from an exported\n// declaration. For example, the For function will return a path for\n// an exported method of an unexported type that is not reachable\n// from any public declaration; this path will cause the Object\n// function to fail if called on a package loaded from export data.\n// TODO(adonovan): is this a bug or feature? Should this package\n// compute accessibility in the same way?\n//\n// For does not return a path for predeclared names, imported package\n// names, local names, and unexported package-level names (except\n// types).\n//\n// Example: given this definition,\n//\n//\tpackage p\n//\n//\ttype T interface {\n//\t\tf() (a string, b struct{ X int })\n//\t}\n//\n// For(X) would return a path that denotes the following sequence of operations:\n//\n//\tp.Scope().Lookup(\"T\")\t\t\t\t(TypeName T)\n//\t.Type().Underlying().Method(0).\t\t\t(method Func f)\n//\t.Type().Results().At(1)\t\t\t\t(field Var b)\n//\t.Type().Field(0)\t\t\t\t\t(field Var X)\n//\n// where p is the package (*types.Package) to which X belongs.\nfunc (enc *Encoder) For(obj types.Object) (Path, error) {\n\tpkg := obj.Pkg()\n\n\t// This table lists the cases of interest.\n\t//\n\t// Object\t\t\t\tAction\n\t// ------                               ------\n\t// nil\t\t\t\t\treject\n\t// builtin\t\t\t\treject\n\t// pkgname\t\t\t\treject\n\t// label\t\t\t\treject\n\t// var\n\t//    package-level\t\t\taccept\n\t//    func param/result\t\t\taccept\n\t//    local\t\t\t\treject\n\t//    struct field\t\t\taccept\n\t// const\n\t//    package-level\t\t\taccept\n\t//    local\t\t\t\treject\n\t// func\n\t//    package-level\t\t\taccept\n\t//    init functions\t\t\treject\n\t//    concrete method\t\t\taccept\n\t//    interface method\t\t\taccept\n\t// type\n\t//    package-level\t\t\taccept\n\t//    local\t\t\t\treject\n\t//\n\t// The only accessible package-level objects are members of pkg itself.\n\t//\n\t// The cases are handled in four steps:\n\t//\n\t// 1. reject nil and builtin\n\t// 2. accept package-level objects\n\t// 3. reject obviously invalid objects\n\t// 4. search the API for the path to the param/result/field/method.\n\n\t// 1. reference to nil or builtin?\n\tif pkg == nil {\n\t\treturn \"\", fmt.Errorf(\"predeclared %s has no path\", obj)\n\t}\n\tscope := pkg.Scope()\n\n\t// 2. package-level object?\n\tif scope.Lookup(obj.Name()) == obj {\n\t\t// Only exported objects (and non-exported types) have a path.\n\t\t// Non-exported types may be referenced by other objects.\n\t\tif _, ok := obj.(*types.TypeName); !ok && !obj.Exported() {\n\t\t\treturn \"\", fmt.Errorf(\"no path for non-exported %v\", obj)\n\t\t}\n\t\treturn Path(obj.Name()), nil\n\t}\n\n\t// 3. Not a package-level object.\n\t//    Reject obviously non-viable cases.\n\tswitch obj := obj.(type) {\n\tcase *types.TypeName:\n\t\tif _, ok := types.Unalias(obj.Type()).(*types.TypeParam); !ok {\n\t\t\t// With the exception of type parameters, only package-level type names\n\t\t\t// have a path.\n\t\t\treturn \"\", fmt.Errorf(\"no path for %v\", obj)\n\t\t}\n\tcase *types.Const, // Only package-level constants have a path.\n\t\t*types.Label,   // Labels are function-local.\n\t\t*types.PkgName: // PkgNames are file-local.\n\t\treturn \"\", fmt.Errorf(\"no path for %v\", obj)\n\n\tcase *types.Var:\n\t\t// Could be:\n\t\t// - a field (obj.IsField())\n\t\t// - a func parameter or result\n\t\t// - a local var.\n\t\t// Sadly there is no way to distinguish\n\t\t// a param/result from a local\n\t\t// so we must proceed to the find.\n\n\tcase *types.Func:\n\t\t// A func, if not package-level, must be a method.\n\t\tif recv := obj.Signature().Recv(); recv == nil {\n\t\t\treturn \"\", fmt.Errorf(\"func is not a method: %v\", obj)\n\t\t}\n\n\t\tif path, ok := enc.concreteMethod(obj); ok {\n\t\t\t// Fast path for concrete methods that avoids looping over scope.\n\t\t\treturn path, nil\n\t\t}\n\n\tdefault:\n\t\tpanic(obj)\n\t}\n\n\t// 4. Search the API for the path to the var (field/param/result) or method.\n\n\t// First inspect package-level named types.\n\t// In the presence of path aliases, these give\n\t// the best paths because non-types may\n\t// refer to types, but not the reverse.\n\tempty := make([]byte, 0, 48) // initial space\n\tobjs := enc.scopeObjects(scope)\n\tfor _, o := range objs {\n\t\ttname, ok := o.(*types.TypeName)\n\t\tif !ok {\n\t\t\tcontinue // handle non-types in second pass\n\t\t}\n\n\t\tpath := append(empty, o.Name()...)\n\t\tpath = append(path, opType)\n\n\t\tT := o.Type()\n\t\tif alias, ok := T.(*types.Alias); ok {\n\t\t\tif r := findTypeParam(obj, alias.TypeParams(), path, opTypeParam); r != nil {\n\t\t\t\treturn Path(r), nil\n\t\t\t}\n\t\t\tif r := find(obj, alias.Rhs(), append(path, opRhs)); r != nil {\n\t\t\t\treturn Path(r), nil\n\t\t\t}\n\n\t\t} else if tname.IsAlias() {\n\t\t\t// legacy alias\n\t\t\tif r := find(obj, T, path); r != nil {\n\t\t\t\treturn Path(r), nil\n\t\t\t}\n\n\t\t} else if named, ok := T.(*types.Named); ok {\n\t\t\t// defined (named) type\n\t\t\tif r := findTypeParam(obj, named.TypeParams(), path, opTypeParam); r != nil {\n\t\t\t\treturn Path(r), nil\n\t\t\t}\n\t\t\tif r := find(obj, named.Underlying(), append(path, opUnderlying)); r != nil {\n\t\t\t\treturn Path(r), nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Then inspect everything else:\n\t// non-types, and declared methods of defined types.\n\tfor _, o := range objs {\n\t\tpath := append(empty, o.Name()...)\n\t\tif _, ok := o.(*types.TypeName); !ok {\n\t\t\tif o.Exported() {\n\t\t\t\t// exported non-type (const, var, func)\n\t\t\t\tif r := find(obj, o.Type(), append(path, opType)); r != nil {\n\t\t\t\t\treturn Path(r), nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Inspect declared methods of defined types.\n\t\tif T, ok := types.Unalias(o.Type()).(*types.Named); ok {\n\t\t\tpath = append(path, opType)\n\t\t\t// The method index here is always with respect\n\t\t\t// to the underlying go/types data structures,\n\t\t\t// which ultimately derives from source order\n\t\t\t// and must be preserved by export data.\n\t\t\tfor i := 0; i < T.NumMethods(); i++ {\n\t\t\t\tm := T.Method(i)\n\t\t\t\tpath2 := appendOpArg(path, opMethod, i)\n\t\t\t\tif m == obj {\n\t\t\t\t\treturn Path(path2), nil // found declared method\n\t\t\t\t}\n\t\t\t\tif r := find(obj, m.Type(), append(path2, opType)); r != nil {\n\t\t\t\t\treturn Path(r), nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", fmt.Errorf(\"can't find path for %v in %s\", obj, pkg.Path())\n}\n\nfunc appendOpArg(path []byte, op byte, arg int) []byte {\n\tpath = append(path, op)\n\tpath = strconv.AppendInt(path, int64(arg), 10)\n\treturn path\n}\n\n// concreteMethod returns the path for meth, which must have a non-nil receiver.\n// The second return value indicates success and may be false if the method is\n// an interface method or if it is an instantiated method.\n//\n// This function is just an optimization that avoids the general scope walking\n// approach. You are expected to fall back to the general approach if this\n// function fails.\nfunc (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {\n\t// Concrete methods can only be declared on package-scoped named types. For\n\t// that reason we can skip the expensive walk over the package scope: the\n\t// path will always be package -> named type -> method. We can trivially get\n\t// the type name from the receiver, and only have to look over the type's\n\t// methods to find the method index.\n\t//\n\t// Methods on generic types require special consideration, however. Consider\n\t// the following package:\n\t//\n\t// \tL1: type S[T any] struct{}\n\t// \tL2: func (recv S[A]) Foo() { recv.Bar() }\n\t// \tL3: func (recv S[B]) Bar() { }\n\t// \tL4: type Alias = S[int]\n\t// \tL5: func _[T any]() { var s S[int]; s.Foo() }\n\t//\n\t// The receivers of methods on generic types are instantiations. L2 and L3\n\t// instantiate S with the type-parameters A and B, which are scoped to the\n\t// respective methods. L4 and L5 each instantiate S with int. Each of these\n\t// instantiations has its own method set, full of methods (and thus objects)\n\t// with receivers whose types are the respective instantiations. In other\n\t// words, we have\n\t//\n\t// S[A].Foo, S[A].Bar\n\t// S[B].Foo, S[B].Bar\n\t// S[int].Foo, S[int].Bar\n\t//\n\t// We may thus be trying to produce object paths for any of these objects.\n\t//\n\t// S[A].Foo and S[B].Bar are the origin methods, and their paths are S.Foo\n\t// and S.Bar, which are the paths that this function naturally produces.\n\t//\n\t// S[A].Bar, S[B].Foo, and both methods on S[int] are instantiations that\n\t// don't correspond to the origin methods. For S[int], this is significant.\n\t// The most precise object path for S[int].Foo, for example, is Alias.Foo,\n\t// not S.Foo. Our function, however, would produce S.Foo, which would\n\t// resolve to a different object.\n\t//\n\t// For S[A].Bar and S[B].Foo it could be argued that S.Bar and S.Foo are\n\t// still the correct paths, since only the origin methods have meaningful\n\t// paths. But this is likely only true for trivial cases and has edge cases.\n\t// Since this function is only an optimization, we err on the side of giving\n\t// up, deferring to the slower but definitely correct algorithm. Most users\n\t// of objectpath will only be giving us origin methods, anyway, as referring\n\t// to instantiated methods is usually not useful.\n\n\tif meth.Origin() != meth {\n\t\treturn \"\", false\n\t}\n\n\t_, named := typesinternal.ReceiverNamed(meth.Signature().Recv())\n\tif named == nil {\n\t\treturn \"\", false\n\t}\n\n\tif types.IsInterface(named) {\n\t\t// Named interfaces don't have to be package-scoped\n\t\t//\n\t\t// TODO(dominikh): opt: if scope.Lookup(name) == named, then we can apply this optimization to interface\n\t\t// methods, too, I think.\n\t\treturn \"\", false\n\t}\n\n\t// Preallocate space for the name, opType, opMethod, and some digits.\n\tname := named.Obj().Name()\n\tpath := make([]byte, 0, len(name)+8)\n\tpath = append(path, name...)\n\tpath = append(path, opType)\n\n\t// Method indices are w.r.t. the go/types data structures,\n\t// ultimately deriving from source order,\n\t// which is preserved by export data.\n\tfor i := 0; i < named.NumMethods(); i++ {\n\t\tif named.Method(i) == meth {\n\t\t\tpath = appendOpArg(path, opMethod, i)\n\t\t\treturn Path(path), true\n\t\t}\n\t}\n\n\t// Due to golang/go#59944, go/types fails to associate the receiver with\n\t// certain methods on cgo types.\n\t//\n\t// TODO(rfindley): replace this panic once golang/go#59944 is fixed in all Go\n\t// versions gopls supports.\n\treturn \"\", false\n\t// panic(fmt.Sprintf(\"couldn't find method %s on type %s; methods: %#v\", meth, named, enc.namedMethods(named)))\n}\n\n// find finds obj within type T, returning the path to it, or nil if not found.\n//\n// The seen map is used to short circuit cycles through type parameters. If\n// nil, it will be allocated as necessary.\n//\n// The seenMethods map is used internally to short circuit cycles through\n// interface methods, such as occur in the following example:\n//\n//\ttype I interface { f() interface{I} }\n//\n// See golang/go#68046 for details.\nfunc find(obj types.Object, T types.Type, path []byte) []byte {\n\treturn (&finder{obj: obj}).find(T, path)\n}\n\n// finder closes over search state for a call to find.\ntype finder struct {\n\tobj             types.Object             // the sought object\n\tseenTParamNames map[*types.TypeName]bool // for cycle breaking through type parameters\n\tseenMethods     map[*types.Func]bool     // for cycle breaking through recursive interfaces\n}\n\nfunc (f *finder) find(T types.Type, path []byte) []byte {\n\tswitch T := T.(type) {\n\tcase *types.Alias:\n\t\treturn f.find(types.Unalias(T), path)\n\tcase *types.Basic, *types.Named:\n\t\t// Named types belonging to pkg were handled already,\n\t\t// so T must belong to another package. No path.\n\t\treturn nil\n\tcase *types.Pointer:\n\t\treturn f.find(T.Elem(), append(path, opElem))\n\tcase *types.Slice:\n\t\treturn f.find(T.Elem(), append(path, opElem))\n\tcase *types.Array:\n\t\treturn f.find(T.Elem(), append(path, opElem))\n\tcase *types.Chan:\n\t\treturn f.find(T.Elem(), append(path, opElem))\n\tcase *types.Map:\n\t\tif r := f.find(T.Key(), append(path, opKey)); r != nil {\n\t\t\treturn r\n\t\t}\n\t\treturn f.find(T.Elem(), append(path, opElem))\n\tcase *types.Signature:\n\t\tif r := f.findTypeParam(T.RecvTypeParams(), path, opRecvTypeParam); r != nil {\n\t\t\treturn r\n\t\t}\n\t\tif r := f.findTypeParam(T.TypeParams(), path, opTypeParam); r != nil {\n\t\t\treturn r\n\t\t}\n\t\tif r := f.find(T.Params(), append(path, opParams)); r != nil {\n\t\t\treturn r\n\t\t}\n\t\treturn f.find(T.Results(), append(path, opResults))\n\tcase *types.Struct:\n\t\tfor i := 0; i < T.NumFields(); i++ {\n\t\t\tfld := T.Field(i)\n\t\t\tpath2 := appendOpArg(path, opField, i)\n\t\t\tif fld == f.obj {\n\t\t\t\treturn path2 // found field var\n\t\t\t}\n\t\t\tif r := f.find(fld.Type(), append(path2, opType)); r != nil {\n\t\t\t\treturn r\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase *types.Tuple:\n\t\tfor i := 0; i < T.Len(); i++ {\n\t\t\tv := T.At(i)\n\t\t\tpath2 := appendOpArg(path, opAt, i)\n\t\t\tif v == f.obj {\n\t\t\t\treturn path2 // found param/result var\n\t\t\t}\n\t\t\tif r := f.find(v.Type(), append(path2, opType)); r != nil {\n\t\t\t\treturn r\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase *types.Interface:\n\t\tfor i := 0; i < T.NumMethods(); i++ {\n\t\t\tm := T.Method(i)\n\t\t\tif f.seenMethods[m] {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tpath2 := appendOpArg(path, opMethod, i)\n\t\t\tif m == f.obj {\n\t\t\t\treturn path2 // found interface method\n\t\t\t}\n\t\t\tif f.seenMethods == nil {\n\t\t\t\tf.seenMethods = make(map[*types.Func]bool)\n\t\t\t}\n\t\t\tf.seenMethods[m] = true\n\t\t\tif r := f.find(m.Type(), append(path2, opType)); r != nil {\n\t\t\t\treturn r\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase *types.TypeParam:\n\t\tname := T.Obj()\n\t\tif f.seenTParamNames[name] {\n\t\t\treturn nil\n\t\t}\n\t\tif name == f.obj {\n\t\t\treturn append(path, opObj)\n\t\t}\n\t\tif f.seenTParamNames == nil {\n\t\t\tf.seenTParamNames = make(map[*types.TypeName]bool)\n\t\t}\n\t\tf.seenTParamNames[name] = true\n\t\tif r := f.find(T.Constraint(), append(path, opConstraint)); r != nil {\n\t\t\treturn r\n\t\t}\n\t\treturn nil\n\t}\n\tpanic(T)\n}\n\nfunc findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte) []byte {\n\treturn (&finder{obj: obj}).findTypeParam(list, path, op)\n}\n\nfunc (f *finder) findTypeParam(list *types.TypeParamList, path []byte, op byte) []byte {\n\tfor i := 0; i < list.Len(); i++ {\n\t\ttparam := list.At(i)\n\t\tpath2 := appendOpArg(path, op, i)\n\t\tif r := f.find(tparam, path2); r != nil {\n\t\t\treturn r\n\t\t}\n\t}\n\treturn nil\n}\n\n// Object returns the object denoted by path p within the package pkg.\nfunc Object(pkg *types.Package, p Path) (types.Object, error) {\n\tpathstr := string(p)\n\tif pathstr == \"\" {\n\t\treturn nil, fmt.Errorf(\"empty path\")\n\t}\n\n\tvar pkgobj, suffix string\n\tif dot := strings.IndexByte(pathstr, opType); dot < 0 {\n\t\tpkgobj = pathstr\n\t} else {\n\t\tpkgobj = pathstr[:dot]\n\t\tsuffix = pathstr[dot:] // suffix starts with \".\"\n\t}\n\n\tobj := pkg.Scope().Lookup(pkgobj)\n\tif obj == nil {\n\t\treturn nil, fmt.Errorf(\"package %s does not contain %q\", pkg.Path(), pkgobj)\n\t}\n\n\t// abstraction of *types.{Pointer,Slice,Array,Chan,Map}\n\ttype hasElem interface {\n\t\tElem() types.Type\n\t}\n\t// abstraction of *types.{Named,Signature}\n\ttype hasTypeParams interface {\n\t\tTypeParams() *types.TypeParamList\n\t}\n\t// abstraction of *types.{Alias,Named,TypeParam}\n\ttype hasObj interface {\n\t\tObj() *types.TypeName\n\t}\n\n\t// The loop state is the pair (t, obj),\n\t// exactly one of which is non-nil, initially obj.\n\t// All suffixes start with '.' (the only object->type operation),\n\t// followed by optional type->type operations,\n\t// then a type->object operation.\n\t// The cycle then repeats.\n\tvar t types.Type\n\tfor suffix != \"\" {\n\t\tcode := suffix[0]\n\t\tsuffix = suffix[1:]\n\n\t\t// Codes [AFMTr] have an integer operand.\n\t\tvar index int\n\t\tswitch code {\n\t\tcase opAt, opField, opMethod, opTypeParam, opRecvTypeParam:\n\t\t\trest := strings.TrimLeft(suffix, \"0123456789\")\n\t\t\tnumerals := suffix[:len(suffix)-len(rest)]\n\t\t\tsuffix = rest\n\t\t\ti, err := strconv.Atoi(numerals)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid path: bad numeric operand %q for code %q\", numerals, code)\n\t\t\t}\n\t\t\tindex = int(i)\n\t\tcase opObj:\n\t\t\t// no operand\n\t\tdefault:\n\t\t\t// The suffix must end with a type->object operation.\n\t\t\tif suffix == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid path: ends with %q, want [AFMO]\", code)\n\t\t\t}\n\t\t}\n\n\t\tif code == opType {\n\t\t\tif t != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid path: unexpected %q in type context\", opType)\n\t\t\t}\n\t\t\tt = obj.Type()\n\t\t\tobj = nil\n\t\t\tcontinue\n\t\t}\n\n\t\tif t == nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid path: code %q in object context\", code)\n\t\t}\n\n\t\t// Inv: t != nil, obj == nil\n\n\t\tt = types.Unalias(t)\n\t\tswitch code {\n\t\tcase opElem:\n\t\t\thasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want pointer, slice, array, chan or map)\", code, t, t)\n\t\t\t}\n\t\t\tt = hasElem.Elem()\n\n\t\tcase opKey:\n\t\t\tmapType, ok := t.(*types.Map)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want map)\", code, t, t)\n\t\t\t}\n\t\t\tt = mapType.Key()\n\n\t\tcase opParams:\n\t\t\tsig, ok := t.(*types.Signature)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want signature)\", code, t, t)\n\t\t\t}\n\t\t\tt = sig.Params()\n\n\t\tcase opResults:\n\t\t\tsig, ok := t.(*types.Signature)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want signature)\", code, t, t)\n\t\t\t}\n\t\t\tt = sig.Results()\n\n\t\tcase opUnderlying:\n\t\t\tnamed, ok := t.(*types.Named)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want named)\", code, t, t)\n\t\t\t}\n\t\t\tt = named.Underlying()\n\n\t\tcase opRhs:\n\t\t\tif alias, ok := t.(*types.Alias); ok {\n\t\t\t\tt = alias.Rhs()\n\t\t\t} else if false {\n\t\t\t\t// Now that go1.24 is assured, we should be able to\n\t\t\t\t// replace this with \"if true {\", but it causes objectpath\n\t\t\t\t// tests to fail. TODO(adonovan): investigate.\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want alias)\", code, t, t)\n\t\t\t}\n\n\t\tcase opTypeParam:\n\t\t\thasTypeParams, ok := t.(hasTypeParams) // Named, Signature\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want named or signature)\", code, t, t)\n\t\t\t}\n\t\t\ttparams := hasTypeParams.TypeParams()\n\t\t\tif n := tparams.Len(); index >= n {\n\t\t\t\treturn nil, fmt.Errorf(\"tuple index %d out of range [0-%d)\", index, n)\n\t\t\t}\n\t\t\tt = tparams.At(index)\n\n\t\tcase opRecvTypeParam:\n\t\t\tsig, ok := t.(*types.Signature) // Signature\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want signature)\", code, t, t)\n\t\t\t}\n\t\t\trtparams := sig.RecvTypeParams()\n\t\t\tif n := rtparams.Len(); index >= n {\n\t\t\t\treturn nil, fmt.Errorf(\"tuple index %d out of range [0-%d)\", index, n)\n\t\t\t}\n\t\t\tt = rtparams.At(index)\n\n\t\tcase opConstraint:\n\t\t\ttparam, ok := t.(*types.TypeParam)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want type parameter)\", code, t, t)\n\t\t\t}\n\t\t\tt = tparam.Constraint()\n\n\t\tcase opAt:\n\t\t\ttuple, ok := t.(*types.Tuple)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want tuple)\", code, t, t)\n\t\t\t}\n\t\t\tif n := tuple.Len(); index >= n {\n\t\t\t\treturn nil, fmt.Errorf(\"tuple index %d out of range [0-%d)\", index, n)\n\t\t\t}\n\t\t\tobj = tuple.At(index)\n\t\t\tt = nil\n\n\t\tcase opField:\n\t\t\tstructType, ok := t.(*types.Struct)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want struct)\", code, t, t)\n\t\t\t}\n\t\t\tif n := structType.NumFields(); index >= n {\n\t\t\t\treturn nil, fmt.Errorf(\"field index %d out of range [0-%d)\", index, n)\n\t\t\t}\n\t\t\tobj = structType.Field(index)\n\t\t\tt = nil\n\n\t\tcase opMethod:\n\t\t\tswitch t := t.(type) {\n\t\t\tcase *types.Interface:\n\t\t\t\tif index >= t.NumMethods() {\n\t\t\t\t\treturn nil, fmt.Errorf(\"method index %d out of range [0-%d)\", index, t.NumMethods())\n\t\t\t\t}\n\t\t\t\tobj = t.Method(index) // Id-ordered\n\n\t\t\tcase *types.Named:\n\t\t\t\tif index >= t.NumMethods() {\n\t\t\t\t\treturn nil, fmt.Errorf(\"method index %d out of range [0-%d)\", index, t.NumMethods())\n\t\t\t\t}\n\t\t\t\tobj = t.Method(index)\n\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want interface or named)\", code, t, t)\n\t\t\t}\n\t\t\tt = nil\n\n\t\tcase opObj:\n\t\t\thasObj, ok := t.(hasObj)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot apply %q to %s (got %T, want named or type param)\", code, t, t)\n\t\t\t}\n\t\t\tobj = hasObj.Obj()\n\t\t\tt = nil\n\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid path: unknown code %q\", code)\n\t\t}\n\t}\n\n\tif obj == nil {\n\t\tpanic(p) // path does not end in an object-valued operator\n\t}\n\n\tif obj.Pkg() != pkg {\n\t\treturn nil, fmt.Errorf(\"path denotes %s, which belongs to a different package\", obj)\n\t}\n\n\treturn obj, nil // success\n}\n\n// scopeObjects is a memoization of scope objects.\n// Callers must not modify the result.\nfunc (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object {\n\tm := enc.scopeMemo\n\tif m == nil {\n\t\tm = make(map[*types.Scope][]types.Object)\n\t\tenc.scopeMemo = m\n\t}\n\tobjs, ok := m[scope]\n\tif !ok {\n\t\tnames := scope.Names() // allocates and sorts\n\t\tobjs = make([]types.Object, len(names))\n\t\tfor i, name := range names {\n\t\t\tobjs[i] = scope.Lookup(name)\n\t\t}\n\t\tm[scope] = objs\n\t}\n\treturn objs\n}\n"
  },
  {
    "path": "go/types/objectpath/objectpath_go118_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage objectpath_test\n\nimport (\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n)\n\n// TODO(adonovan): merge this back into objectpath_test.go.\nfunc TestGenericPaths(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule x.io\ngo 1.18\n\n-- b/b.go --\npackage b\n\nconst C int = 1\n\ntype T[TP0 any, TP1 interface{ M0(); M1() }] struct{}\n\nfunc (T[RP0, RP1]) M() {}\n\ntype N int\n\nfunc (N) M0()\nfunc (N) M1()\n\ntype A = T[int, N]\n\nfunc F[FP0 any, FP1 interface{ M() }](FP0, FP1) {}\n`\n\n\tpkgmap := loadPackages(t, src, \"./b\")\n\n\tpaths := []pathTest{\n\t\t// Good paths\n\t\t{\"b\", \"T\", \"type b.T[TP0 any, TP1 interface{M0(); M1()}] struct{}\", \"\"},\n\t\t{\"b\", \"T.O\", \"type b.T[TP0 any, TP1 interface{M0(); M1()}] struct{}\", \"\"},\n\t\t{\"b\", \"T.M0\", \"func (b.T[RP0, RP1]).M()\", \"\"},\n\t\t{\"b\", \"T.M0.r1O\", \"type parameter RP1 interface{M0(); M1()}\", \"\"},\n\t\t{\"b\", \"T.M0.r1CM1\", \"func (interface).M1()\", \"\"},\n\t\t{\"b\", \"T.T0O\", \"type parameter TP0 any\", \"\"},\n\t\t{\"b\", \"T.T1O\", \"type parameter TP1 interface{M0(); M1()}\", \"\"},\n\t\t{\"b\", \"T.T1CM0\", \"func (interface).M0()\", \"\"},\n\t\t{\"b\", \"F.T0O\", \"type parameter FP0 any\", \"\"},\n\t\t{\"b\", \"F.T1CM0\", \"func (interface).M()\", \"\"},\n\t\t// Obj of an instance is the generic declaration.\n\t\t{\"b\", \"A.O\", \"type b.T[TP0 any, TP1 interface{M0(); M1()}] struct{}\", \"\"},\n\t\t{\"b\", \"A.M0\", \"func (b.T[int, b.N]).M()\", \"\"},\n\n\t\t// Bad paths\n\t\t{\"b\", \"N.C\", \"\", \"invalid path: ends with 'C', want [AFMO]\"},\n\t\t{\"b\", \"N.CO\", \"\", \"cannot apply 'C' to b.N (got *types.Named, want type parameter)\"},\n\t\t{\"b\", \"N.T\", \"\", `invalid path: bad numeric operand \"\" for code 'T'`},\n\t\t{\"b\", \"N.T0\", \"\", \"tuple index 0 out of range [0-0)\"},\n\t\t{\"b\", \"T.T2O\", \"\", \"tuple index 2 out of range [0-2)\"},\n\t\t{\"b\", \"T.T1M0\", \"\", \"cannot apply 'M' to TP1 (got *types.TypeParam, want interface or named)\"},\n\t\t{\"b\", \"C.T0\", \"\", \"cannot apply 'T' to int (got *types.Basic, want named or signature)\"},\n\t}\n\tfor _, test := range paths {\n\t\tif err := testPath(pkgmap, test); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\n\t// bad objects\n\tfor _, test := range []struct {\n\t\tobj     types.Object\n\t\twantErr string\n\t}{\n\t\t{types.Universe.Lookup(\"any\"), \"predeclared type any = interface{} has no path\"},\n\t\t{types.Universe.Lookup(\"comparable\"), \"predeclared type comparable interface{comparable} has no path\"},\n\t} {\n\t\tpath, err := objectpath.For(test.obj)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"Object(%s) = %q, want error\", test.obj, path)\n\t\t\tcontinue\n\t\t}\n\t\tif err.Error() != test.wantErr {\n\t\t\tt.Errorf(\"Object(%s) error was %q, want %q\", test.obj, err, test.wantErr)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc TestGenericPaths_Issue51717(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule x.io\ngo 1.18\n\n-- p/p.go --\npackage p\n\ntype S struct{}\n\nfunc (_ S) M() {\n\t// The go vet stackoverflow crash disappears when the following line is removed\n\tpanic(\"\")\n}\n\nfunc F[WL interface{ N(item W) WL }, W any]() {\n}\n\nfunc main() {}\n`\n\tpkgmap := loadPackages(t, src, \"./p\")\n\n\tpaths := []pathTest{\n\t\t{\"p\", \"F.T0CM0.RA0\", \"var  WL\", \"\"},\n\t\t{\"p\", \"F.T0CM0.RA0.CM0\", \"func (interface).N(item W) WL\", \"\"},\n\n\t\t// Finding S.M0 reproduced the infinite recursion reported in #51717,\n\t\t// because F is searched before S.\n\t\t{\"p\", \"S.M0\", \"func (p.S).M()\", \"\"},\n\t}\n\tfor _, test := range paths {\n\t\tif err := testPath(pkgmap, test); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/types/objectpath/objectpath_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage objectpath_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestPaths(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule x.io\n\n-- b/b.go --\npackage b\n\nimport \"x.io/a\"\n\nconst C = a.Int(0)\n\nfunc F(a, b, c int, d a.T)\n\ntype T struct{ A int; b int; a.T }\n\nfunc (T) M() *interface{ f() }\n\ntype U T\n\ntype A = struct{ x int }\n\ntype unexported2 struct { z int }\ntype AN = unexported2 // alias of named\n\n// type GA[T any] = T // see below\n\nvar V []*a.T\n\ntype M map[struct{x int}]struct{y int}\n\nfunc unexportedFunc()\ntype unexportedType struct{}\n\nfunc (unexportedType) F() {} // not reachable from package's public API (export data)\n\ntype S struct{t struct{x int}}\ntype R []struct{y int}\ntype Q [2]struct{z int}\n\n-- a/a.go --\npackage a\n\ntype Int int\n\ntype T struct{x, y int}\n\ntype Issue68046 interface { f(x int) interface{Issue68046} }\n`\n\n\tpkgmap := loadPackages(t, src, \"./a\", \"./b\")\n\n\tpaths := []pathTest{\n\t\t// Good paths\n\t\t{\"b\", \"C\", \"const b.C a.Int\", \"\"},\n\t\t{\"b\", \"F\", \"func b.F(a int, b int, c int, d a.T)\", \"\"},\n\t\t{\"b\", \"F.PA0\", \"var a int\", \"\"},\n\t\t{\"b\", \"F.PA1\", \"var b int\", \"\"},\n\t\t{\"b\", \"F.PA2\", \"var c int\", \"\"},\n\t\t{\"b\", \"F.PA3\", \"var d a.T\", \"\"},\n\t\t{\"b\", \"T\", \"type b.T struct{A int; b int; a.T}\", \"\"},\n\t\t{\"b\", \"T.O\", \"type b.T struct{A int; b int; a.T}\", \"\"},\n\t\t{\"b\", \"T.UF0\", \"field A int\", \"\"},\n\t\t{\"b\", \"T.UF1\", \"field b int\", \"\"},\n\t\t{\"b\", \"T.UF2\", \"field T a.T\", \"\"},\n\t\t{\"b\", \"U.UF2\", \"field T a.T\", \"\"},          // U.U... are aliases for T.U...\n\t\t{\"b\", \"A\", \"type b.A = struct{x int}\", \"\"}, // go1.22/alias=1: \"type b.A = b.A\"\n\t\t{\"b\", \"A.aF0\", \"field x int\", \"\"},\n\t\t{\"b\", \"A.F0\", \"field x int\", \"\"},\n\t\t{\"b\", \"AN\", \"type b.AN = b.unexported2\", \"\"}, // go1.22/alias=1: \"type b.AN = b.AN\"\n\t\t{\"b\", \"AN.UF0\", \"field z int\", \"\"},\n\t\t{\"b\", \"AN.aO\", \"type b.unexported2 struct{z int}\", \"\"},\n\t\t{\"b\", \"AN.O\", \"type b.unexported2 struct{z int}\", \"\"},\n\t\t{\"b\", \"AN.aUF0\", \"field z int\", \"\"},\n\t\t{\"b\", \"AN.UF0\", \"field z int\", \"\"},\n\t\t// {\"b\", \"GA\", \"type parameter b.GA = T\", \"\"}, // TODO(adonovan): enable once GOEXPERIMENT=aliastypeparams has gone\n\t\t{\"b\", \"V\", \"var b.V []*a.T\", \"\"},\n\t\t{\"b\", \"M\", \"type b.M map[struct{x int}]struct{y int}\", \"\"},\n\t\t{\"b\", \"M.UKF0\", \"field x int\", \"\"},\n\t\t{\"b\", \"M.UEF0\", \"field y int\", \"\"},\n\t\t{\"b\", \"T.M0\", \"func (b.T).M() *interface{f()}\", \"\"}, // concrete method\n\t\t{\"b\", \"T.M0.RA0\", \"var  *interface{f()}\", \"\"},       // parameter\n\t\t{\"b\", \"T.M0.RA0.EM0\", \"func (interface).f()\", \"\"},   // interface method\n\t\t{\"b\", \"unexportedType\", \"type b.unexportedType struct{}\", \"\"},\n\t\t{\"b\", \"unexportedType.M0\", \"func (b.unexportedType).F()\", \"\"},\n\t\t{\"b\", \"S.UF0.F0\", \"field x int\", \"\"},\n\t\t{\"b\", \"R.UEF0\", \"field y int\", \"\"},\n\t\t{\"b\", \"Q.UEF0\", \"field z int\", \"\"},\n\t\t{\"a\", \"T\", \"type a.T struct{x int; y int}\", \"\"},\n\t\t{\"a\", \"Issue68046.UM0\", \"func (a.Issue68046).f(x int) interface{a.Issue68046}\", \"\"},\n\t\t{\"a\", \"Issue68046.UM0.PA0\", \"var x int\", \"\"},\n\n\t\t// Bad paths\n\t\t{\"b\", \"\", \"\", \"empty path\"},\n\t\t{\"b\", \"missing\", \"\", `package b does not contain \"missing\"`},\n\t\t{\"b\", \"F.U\", \"\", \"invalid path: ends with 'U', want [AFMO]\"},\n\t\t{\"b\", \"F.PA3.O\", \"\", \"path denotes type a.T struct{x int; y int}, which belongs to a different package\"},\n\t\t{\"b\", \"F.PA!\", \"\", `invalid path: bad numeric operand \"\" for code 'A'`},\n\t\t{\"b\", \"F.PA3.UF0\", \"\", \"path denotes field x int, which belongs to a different package\"},\n\t\t{\"b\", \"F.PA3.UF5\", \"\", \"field index 5 out of range [0-2)\"},\n\t\t{\"b\", \"V.EE\", \"\", \"invalid path: ends with 'E', want [AFMO]\"},\n\t\t{\"b\", \"F..O\", \"\", \"invalid path: unexpected '.' in type context\"},\n\t\t{\"b\", \"T.OO\", \"\", \"invalid path: code 'O' in object context\"},\n\t\t{\"b\", \"T.EO\", \"\", \"cannot apply 'E' to b.T (got *types.Named, want pointer, slice, array, chan or map)\"},\n\t\t{\"b\", \"A.O\", \"\", \"cannot apply 'O' to struct{x int} (got *types.Struct, want named or type param)\"},\n\t\t{\"b\", \"A.UF0\", \"\", \"cannot apply 'U' to struct{x int} (got *types.Struct, want named)\"},\n\t\t{\"b\", \"M.UPO\", \"\", \"cannot apply 'P' to map[struct{x int}]struct{y int} (got *types.Map, want signature)\"},\n\t\t{\"b\", \"C.O\", \"\", \"path denotes type a.Int int, which belongs to a different package\"},\n\t\t{\"b\", \"T.M9\", \"\", \"method index 9 out of range [0-1)\"},\n\t\t{\"b\", \"M.UF0\", \"\", \"cannot apply 'F' to map[struct{x int}]struct{y int} (got *types.Map, want struct)\"},\n\t\t{\"b\", \"V.KO\", \"\", \"cannot apply 'K' to []*a.T (got *types.Slice, want map)\"},\n\t\t{\"b\", \"V.A4\", \"\", \"cannot apply 'A' to []*a.T (got *types.Slice, want tuple)\"},\n\t\t{\"b\", \"V.RA0\", \"\", \"cannot apply 'R' to []*a.T (got *types.Slice, want signature)\"},\n\t\t{\"b\", \"F.PA4\", \"\", \"tuple index 4 out of range [0-4)\"},\n\t\t{\"b\", \"F.XO\", \"\", \"invalid path: unknown code 'X'\"},\n\t}\n\tfor _, test := range paths {\n\t\tif err := testPath(pkgmap, test); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\n\t// bad objects\n\tb := pkgmap[\"x.io/b\"]\n\tfor _, test := range []struct {\n\t\tobj     types.Object\n\t\twantErr string\n\t}{\n\t\t{types.Universe.Lookup(\"nil\"), \"predeclared nil has no path\"},\n\t\t{types.Universe.Lookup(\"len\"), \"predeclared builtin len has no path\"},\n\t\t{types.Universe.Lookup(\"int\"), \"predeclared type int has no path\"},\n\t\t{b.TypesInfo.Implicits[b.Syntax[0].Imports[0]], \"no path for package a (\\\"a\\\")\"}, // import \"a\"\n\t\t{b.Types.Scope().Lookup(\"unexportedFunc\"), \"no path for non-exported func b.unexportedFunc()\"},\n\t} {\n\t\tpath, err := objectpath.For(test.obj)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"Object(%s) = %q, want error\", test.obj, path)\n\t\t\tcontinue\n\t\t}\n\t\tgotErr := strings.ReplaceAll(err.Error(), \"x.io/\", \"\")\n\t\tif gotErr != test.wantErr {\n\t\t\tt.Errorf(\"Object(%s) error was %q, want %q\", test.obj, gotErr, test.wantErr)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\n// loadPackages expands the archive and loads the package patterns relative to its root.\nfunc loadPackages(t *testing.T, archive string, patterns ...string) map[string]*packages.Package {\n\t// TODO(adonovan): ExtractTxtarToTmp (sans File) would be useful.\n\tar := txtar.Parse([]byte(archive))\n\tpkgs := testfiles.LoadPackages(t, ar, patterns...)\n\tm := make(map[string]*packages.Package)\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tm[pkg.Types.Path()] = pkg\n\t})\n\treturn m\n}\n\ntype pathTest struct {\n\tpkg     string // sans \"x.io/\" module prefix\n\tpath    objectpath.Path\n\twantobj string\n\twantErr string // after each \"x.io/\" replaced with \"\"\n}\n\nfunc testPath(pkgmap map[string]*packages.Package, test pathTest) error {\n\t// We test objectpath by enumerating a set of paths\n\t// and ensuring that Path(pkg, Object(pkg, path)) == path.\n\t//\n\t// It might seem more natural to invert the test:\n\t// identify a set of objects and for each one,\n\t// ensure that Object(pkg, Path(pkg, obj)) == obj.\n\t// However, for most interesting test cases there is no\n\t// easy way to identify the object short of applying\n\t// a series of destructuring operations to pkg---which\n\t// is essentially what objectpath.Object does.\n\t// (We do a little of that when testing bad paths, below.)\n\t//\n\t// The downside is that the test depends on the path encoding.\n\t// The upside is that the test exercises the encoding.\n\tpkg := pkgmap[\"x.io/\"+test.pkg].Types\n\n\t// check path -> object\n\tobj, err := objectpath.Object(pkg, test.path)\n\tif (test.wantErr != \"\") != (err != nil) {\n\t\treturn fmt.Errorf(\"Object(%s, %q) returned error %q, want %q\", pkg.Path(), test.path, err, test.wantErr)\n\t}\n\tif test.wantErr != \"\" {\n\t\tgotErr := strings.ReplaceAll(err.Error(), \"x.io/\", \"\")\n\t\tif gotErr != test.wantErr {\n\t\t\treturn fmt.Errorf(\"Object(%s, %q) error was %q, want %q\",\n\t\t\t\tpkg.Path(), test.path, gotErr, test.wantErr)\n\t\t}\n\t\treturn nil\n\t}\n\t// Inv: err == nil\n\n\tif objString := types.ObjectString(obj, (*types.Package).Name); objString != test.wantobj {\n\t\treturn fmt.Errorf(\"Object(%s, %q) = %s, want %s\", pkg.Path(), test.path, objString, test.wantobj)\n\t}\n\tif obj.Pkg() != pkg {\n\t\treturn fmt.Errorf(\"Object(%s, %q) = %v, which belongs to package %s\",\n\t\t\tpkg.Path(), test.path, obj, obj.Pkg().Path())\n\t}\n\n\t// check object -> path\n\tpath2, err := objectpath.For(obj)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"For(%v) failed: %v, want %q\", obj, err, test.path)\n\t}\n\t// We do not require that test.path == path2. Aliases are legal.\n\t// But we do require that Object(path2) finds the same object.\n\tobj2, err := objectpath.Object(pkg, path2)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Object(%s, %q) failed: %v (roundtrip from %q)\", pkg.Path(), path2, err, test.path)\n\t}\n\tif obj2 != obj {\n\t\treturn fmt.Errorf(\"Object(%s, For(obj)) != obj: got %s, obj is %s (path1=%q, path2=%q)\", pkg.Path(), obj2, obj, test.path, path2)\n\t}\n\treturn nil\n}\n\n// TestSourceAndExportData uses objectpath to compute a correspondence\n// of objects between two versions of the same package, one loaded from\n// source, the other from export data.\nfunc TestSourceAndExportData(t *testing.T) {\n\tconst src = `\npackage p\n\ntype I int\n\nfunc (I) F() *struct{ X, Y int } {\n\treturn nil\n}\n\ntype Foo interface {\n\tMethod() (string, func(int) struct{ X int })\n}\n\nvar X chan struct{ Z int }\nvar Z map[string]struct{ A int }\n\nvar V unexported\ntype unexported struct{}\nfunc (unexported) F() {} // reachable via V\n\n// The name 'unreachable' has special meaning to the test.\ntype unreachable struct{}\nfunc (unreachable) F() {} // not reachable in export data\n`\n\n\t// Parse source file and type-check it as a package, \"src\".\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"src.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tconf := types.Config{Importer: importer.ForCompiler(token.NewFileSet(), \"source\", nil)}\n\tinfo := &types.Info{\n\t\tDefs: make(map[*ast.Ident]types.Object),\n\t}\n\tsrcpkg, err := conf.Check(\"src/p\", fset, []*ast.File{f}, info)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Export binary export data then reload it as a new package, \"bin\".\n\tvar buf bytes.Buffer\n\tif err := gcexportdata.Write(&buf, fset, srcpkg); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\timports := make(map[string]*types.Package)\n\tbinpkg, err := gcexportdata.Read(&buf, fset, imports, \"bin/p\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Now find the correspondences between them.\n\tfor _, srcobj := range info.Defs {\n\t\tif srcobj == nil {\n\t\t\tcontinue // e.g. package declaration\n\t\t}\n\t\tif _, ok := srcobj.(*types.PkgName); ok {\n\t\t\tcontinue // PkgName has no objectpath\n\t\t}\n\n\t\tpath, err := objectpath.For(srcobj)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"For(%v): %v\", srcobj, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Do we expect to find this object in the export data?\n\t\treachable := !strings.Contains(string(path), \"unreachable\")\n\n\t\tbinobj, err := objectpath.Object(binpkg, path)\n\t\tif err != nil {\n\t\t\tif reachable {\n\t\t\t\tt.Errorf(\"Object(%s, %q): %v\", binpkg.Path(), path, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif !reachable {\n\t\t\tt.Errorf(\"Object(%s, %q) = %v (unexpectedly reachable)\", binpkg.Path(), path, binobj)\n\t\t}\n\n\t\t// Check the object strings match.\n\t\t// (We can't check that types are identical because the\n\t\t// objects belong to different type-checker realms.)\n\t\tsrcstr := objectString(srcobj)\n\t\tbinstr := objectString(binobj)\n\t\tif srcstr != binstr {\n\t\t\tt.Errorf(\"ObjectStrings do not match: Object(For(%q)) = %s, want %s\",\n\t\t\t\tpath, srcstr, binstr)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc objectString(obj types.Object) string {\n\ts := types.ObjectString(obj, (*types.Package).Name)\n\n\t// The printing of interface methods changed in go1.11.\n\t// This work-around makes the specific test pass with earlier versions.\n\ts = strings.Replace(s, \"func (interface).Method\", \"func (p.Foo).Method\", -1)\n\n\treturn s\n}\n\n// TestOrdering uses objectpath over two Named types with the same method\n// names but in a different source order and checks that objectpath is the\n// same for methods with the same name.\nfunc TestOrdering(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule x.io\n\n-- p/p.go --\npackage p\n\ntype T struct{ A int }\n\nfunc (T) M() { }\nfunc (T) N() { }\nfunc (T) X() { }\nfunc (T) Y() { }\n\n-- q/q.go --\npackage q\n\ntype T struct{ A int }\n\nfunc (T) N() { }\nfunc (T) M() { }\nfunc (T) Y() { }\nfunc (T) X() { }\n`\n\n\tpkgmap := loadPackages(t, src, \"./p\", \"./q\")\n\tp := pkgmap[\"x.io/p\"].Types\n\tq := pkgmap[\"x.io/q\"].Types\n\n\t// From here, the objectpaths generated for p and q should be the\n\t// same. If they are not, then we are generating an ordering that is\n\t// dependent on the declaration of the types within the file.\n\tfor _, test := range []struct {\n\t\tpath objectpath.Path\n\t}{\n\t\t{\"T.M0\"},\n\t\t{\"T.M1\"},\n\t\t{\"T.M2\"},\n\t\t{\"T.M3\"},\n\t} {\n\t\tpobj, err := objectpath.Object(p, test.path)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Object(%s) failed in a1: %v\", test.path, err)\n\t\t\tcontinue\n\t\t}\n\t\tqobj, err := objectpath.Object(q, test.path)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Object(%s) failed in a2: %v\", test.path, err)\n\t\t\tcontinue\n\t\t}\n\t\tif pobj.Name() != pobj.Name() {\n\t\t\tt.Errorf(\"Objects(%s) not equal, got a1 = %v, a2 = %v\", test.path, pobj.Name(), qobj.Name())\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/types/typeutil/callee.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t_ \"unsafe\" // for linkname\n)\n\n// Callee returns the named target of a function call, if any:\n// a function, method, builtin, or variable.\n// It returns nil for a T(x) conversion.\n//\n// Functions and methods may potentially have type parameters.\n//\n// Note: for calls of instantiated functions and methods, Callee returns\n// the corresponding generic function or method on the generic type.\nfunc Callee(info *types.Info, call *ast.CallExpr) types.Object {\n\tobj := info.Uses[usedIdent(info, call.Fun)]\n\tif obj == nil {\n\t\treturn nil\n\t}\n\tif _, ok := obj.(*types.TypeName); ok {\n\t\treturn nil\n\t}\n\treturn obj\n}\n\n// StaticCallee returns the target (function or method) of a static function\n// call, if any. It returns nil for calls to builtins.\n//\n// Note: for calls of instantiated functions and methods, StaticCallee returns\n// the corresponding generic function or method on the generic type.\nfunc StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {\n\tobj := info.Uses[usedIdent(info, call.Fun)]\n\tfn, _ := obj.(*types.Func)\n\tif fn == nil || interfaceMethod(fn) {\n\t\treturn nil\n\t}\n\treturn fn\n}\n\n// usedIdent is the implementation of [internal/typesinternal.UsedIdent].\n// It returns the identifier associated with e.\n// See typesinternal.UsedIdent for a fuller description.\n// This function should live in typesinternal, but cannot because it would\n// create an import cycle.\n//\n//go:linkname usedIdent golang.org/x/tools/go/types/typeutil.usedIdent\nfunc usedIdent(info *types.Info, e ast.Expr) *ast.Ident {\n\tif info.Types == nil || info.Uses == nil {\n\t\tpanic(\"one of info.Types or info.Uses is nil; both must be populated\")\n\t}\n\t// Look through type instantiation if necessary.\n\tswitch d := ast.Unparen(e).(type) {\n\tcase *ast.IndexExpr:\n\t\tif info.Types[d.Index].IsType() {\n\t\t\te = d.X\n\t\t}\n\tcase *ast.IndexListExpr:\n\t\te = d.X\n\t}\n\n\tswitch e := ast.Unparen(e).(type) {\n\t// info.Uses always has the object we want, even for selector expressions.\n\t// We don't need info.Selections.\n\t// See go/types/recording.go:recordSelection.\n\tcase *ast.Ident:\n\t\treturn e\n\tcase *ast.SelectorExpr:\n\t\treturn e.Sel\n\t}\n\treturn nil\n}\n\n// interfaceMethod reports whether its argument is a method of an interface.\n// This function should live in typesinternal, but cannot because it would create an import cycle.\n//\n//go:linkname interfaceMethod golang.org/x/tools/go/types/typeutil.interfaceMethod\nfunc interfaceMethod(f *types.Func) bool {\n\trecv := f.Signature().Recv()\n\treturn recv != nil && types.IsInterface(recv.Type())\n}\n"
  },
  {
    "path": "go/types/typeutil/callee_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\nfunc TestStaticCallee(t *testing.T) {\n\ttestStaticCallee(t, []string{\n\t\t`package q;\n\t\tfunc Abs(x int) int {\n\t\t\tif x < 0 {\n\t\t\t\treturn -x\n\t\t\t}\n\t\t\treturn x\n\t\t}`,\n\t\t`package p\n\t\timport \"q\"\n\n\t\ttype T int\n\n\t\tfunc g(int)\n\n\t\tvar f = g\n\n\t\tvar x int\n\n\t\ttype s struct{ f func(int) }\n\t\tfunc (s) g(int)\n\n\t\ttype I interface{ f(int) }\n\n\t\tvar a struct{b struct{c s}}\n\n\t\tvar n map[int]func()\n\t\tvar m []func()\n\n\t\tfunc calls() {\n\t\t\tg(x)           // a declared func\n\t\t\ts{}.g(x)       // a concrete method\n\t\t\ta.b.c.g(x)     // same\n\t\t\t_ = q.Abs(x)   // declared func, qualified identifier\n\t\t}\n\n\t\tfunc noncalls() {\n\t\t\t_ = T(x)    // a type\n\t\t\tf(x)        // a var\n\t\t\tpanic(x)    // a built-in\n\t\t\ts{}.f(x)    // a field\n\t\t\tI(nil).f(x) // interface method\n\t\t\tm[0]()      // a map\n\t\t\tn[0]()      // a slice\n\t\t}\n\t\t`})\n}\n\nfunc TestTypeParamStaticCallee(t *testing.T) {\n\ttestStaticCallee(t, []string{\n\t\t`package q\n\t\tfunc R[T any]() {}\n\t\t`,\n\t\t`package p\n\t\timport \"q\"\n\t\ttype I interface{\n\t\t\ti()\n\t\t}\n\n\t\ttype G[T any] func() T\n\t\tfunc F[T any]() T { var x T; return x }\n\n\t\ttype M[T I] struct{ t T }\n\t\tfunc (m M[T]) noncalls() {\n\t\t\tm.t.i()   // method on a type parameter\n\t\t}\n\n\t\tfunc (m M[T]) calls() {\n\t\t\tm.calls() // method on a generic type\n\t\t}\n\n\t\ttype Chain[T I] struct{ r struct { s M[T] } }\n\n\t\ttype S int\n\t\tfunc (S) i() {}\n\n\t\tfunc Multi[TP0, TP1 any](){}\n\n\t\tfunc calls() {\n\t\t\t_ = F[int]()            // instantiated function\n\t\t\t_ = (F[int])()          // go through parens\n\t\t\tM[S]{}.calls()          // instantiated method\n\t\t\tChain[S]{}.r.s.calls()  // same as above\n\t\t\tMulti[int,string]()     // multiple type parameters\n\t\t\tq.R[int]()              // different package\n\t\t}\n\n\t\tfunc noncalls() {\n\t\t\t_ = G[int](nil)()  // instantiated function\n\t\t}\n\t\t`})\n}\n\n// testStaticCallee parses and type checks each file content in contents\n// as a single file package in order. Within functions that have the suffix\n// \"calls\" it checks that the CallExprs within have a static callee.\n// If the function's name == \"calls\" all calls must have static callees,\n// and if the name != \"calls\", the calls must not have static callees.\n// Failures are reported on t.\nfunc testStaticCallee(t *testing.T, contents []string) {\n\tfset := token.NewFileSet()\n\tpackages := make(map[string]*types.Package)\n\tcfg := &types.Config{Importer: closure(packages)}\n\tinfo := &types.Info{\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\n\tvar files []*ast.File\n\tfor i, content := range contents {\n\t\t// parse\n\t\tf, err := parser.ParseFile(fset, fmt.Sprintf(\"%d.go\", i), content, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfiles = append(files, f)\n\n\t\t// type-check\n\t\tpkg, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tpackages[pkg.Path()] = pkg\n\t}\n\n\t// check\n\tfor _, f := range files {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && strings.HasSuffix(decl.Name.Name, \"calls\") {\n\t\t\t\twantCallee := decl.Name.Name == \"calls\" // false within func noncalls()\n\t\t\t\tast.Inspect(decl.Body, func(n ast.Node) bool {\n\t\t\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\t\tfn := typeutil.StaticCallee(info, call)\n\t\t\t\t\t\tif fn == nil && wantCallee {\n\t\t\t\t\t\t\tt.Errorf(\"%s: StaticCallee returned nil\",\n\t\t\t\t\t\t\t\tfset.Position(call.Lparen))\n\t\t\t\t\t\t} else if fn != nil && !wantCallee {\n\t\t\t\t\t\t\tt.Errorf(\"%s: StaticCallee returned %s, want nil\",\n\t\t\t\t\t\t\t\tfset.Position(call.Lparen), fn)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/types/typeutil/example_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\nfunc ExampleMap() {\n\tconst source = `package P\n\nvar X []string\nvar Y []string\n\nconst p, q = 1.0, 2.0\n\nfunc f(offset int32) (value byte, ok bool)\nfunc g(rune) (uint8, bool)\n`\n\n\t// Parse and type-check the package.\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"P.go\", source, 0)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tpkg, err := new(types.Config).Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tscope := pkg.Scope()\n\n\t// Group names of package-level objects by their type.\n\tvar namesByType typeutil.Map // value is []string\n\tfor _, name := range scope.Names() {\n\t\tT := scope.Lookup(name).Type()\n\n\t\tnames, _ := namesByType.At(T).([]string)\n\t\tnames = append(names, name)\n\t\tnamesByType.Set(T, names)\n\t}\n\n\t// Format, sort, and print the map entries.\n\tvar lines []string\n\tnamesByType.Iterate(func(T types.Type, names any) {\n\t\tlines = append(lines, fmt.Sprintf(\"%s   %s\", names, T))\n\t})\n\tsort.Strings(lines)\n\tfor _, line := range lines {\n\t\tfmt.Println(line)\n\t}\n\n\t// Output:\n\t// [X Y]   []string\n\t// [f g]   func(offset int32) (value byte, ok bool)\n\t// [p q]   untyped float\n}\n"
  },
  {
    "path": "go/types/typeutil/imports.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil\n\nimport \"go/types\"\n\n// Dependencies returns all dependencies of the specified packages.\n//\n// Dependent packages appear in topological order: if package P imports\n// package Q, Q appears earlier than P in the result.\n// The algorithm follows import statements in the order they\n// appear in the source code, so the result is a total order.\nfunc Dependencies(pkgs ...*types.Package) []*types.Package {\n\tvar result []*types.Package\n\tseen := make(map[*types.Package]bool)\n\tvar visit func(pkgs []*types.Package)\n\tvisit = func(pkgs []*types.Package) {\n\t\tfor _, p := range pkgs {\n\t\t\tif !seen[p] {\n\t\t\t\tseen[p] = true\n\t\t\t\tvisit(p.Imports())\n\t\t\t\tresult = append(result, p)\n\t\t\t}\n\t\t}\n\t}\n\tvisit(pkgs)\n\treturn result\n}\n"
  },
  {
    "path": "go/types/typeutil/imports_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\ntype closure map[string]*types.Package\n\nfunc (c closure) Import(path string) (*types.Package, error) { return c[path], nil }\n\nfunc TestDependencies(t *testing.T) {\n\tpackages := make(map[string]*types.Package)\n\tconf := types.Config{\n\t\tImporter: closure(packages),\n\t}\n\tfset := token.NewFileSet()\n\n\t// All edges go to the right.\n\t//  /--D--B--A\n\t// F    \\_C_/\n\t//  \\__E_/\n\tfor i, content := range []string{\n\t\t`package a`,\n\t\t`package c; import (_ \"a\")`,\n\t\t`package b; import (_ \"a\")`,\n\t\t`package e; import (_ \"c\")`,\n\t\t`package d; import (_ \"b\"; _ \"c\")`,\n\t\t`package f; import (_ \"d\"; _ \"e\")`,\n\t} {\n\t\tf, err := parser.ParseFile(fset, fmt.Sprintf(\"%d.go\", i), content, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tpkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tpackages[pkg.Path()] = pkg\n\t}\n\n\tfor _, test := range []struct {\n\t\troots, want string\n\t}{\n\t\t{\"a\", \"a\"},\n\t\t{\"b\", \"ab\"},\n\t\t{\"c\", \"ac\"},\n\t\t{\"d\", \"abcd\"},\n\t\t{\"e\", \"ace\"},\n\t\t{\"f\", \"abcdef\"},\n\n\t\t{\"be\", \"abce\"},\n\t\t{\"eb\", \"aceb\"},\n\t\t{\"de\", \"abcde\"},\n\t\t{\"ed\", \"acebd\"},\n\t\t{\"ef\", \"acebdf\"},\n\t} {\n\t\tvar pkgs []*types.Package\n\t\tfor _, r := range test.roots {\n\t\t\tpkgs = append(pkgs, packages[string(r)])\n\t\t}\n\t\tvar got string\n\t\tfor _, p := range typeutil.Dependencies(pkgs...) {\n\t\t\tgot += p.Path()\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"Dependencies(%q) = %q, want %q\", test.roots, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/types/typeutil/map.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typeutil defines various utilities for types, such as [Map],\n// a hash table that maps [types.Type] to any value.\npackage typeutil\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"hash/maphash\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// Map is a hash-table-based mapping from types (types.Type) to\n// arbitrary values.  The concrete types that implement\n// the Type interface are pointers.  Since they are not canonicalized,\n// == cannot be used to check for equivalence, and thus we cannot\n// simply use a Go map.\n//\n// Just as with map[K]V, a nil *Map is a valid empty map.\n//\n// Read-only map operations ([Map.At], [Map.Len], and so on) may\n// safely be called concurrently.\n//\n// TODO(adonovan): deprecate in favor of https://go.dev/issues/69420\n// and 69559, if the latter proposals for a generic hash-map type and\n// a types.Hash function are accepted.\ntype Map struct {\n\ttable  map[uint32][]entry // maps hash to bucket; entry.key==nil means unused\n\tlength int                // number of map entries\n}\n\n// entry is an entry (key/value association) in a hash bucket.\ntype entry struct {\n\tkey   types.Type\n\tvalue any\n}\n\n// SetHasher has no effect.\n//\n// It is a relic of an optimization that is no longer profitable. Do\n// not use [Hasher], [MakeHasher], or [SetHasher] in new code.\nfunc (m *Map) SetHasher(Hasher) {}\n\n// Delete removes the entry with the given key, if any.\n// It returns true if the entry was found.\nfunc (m *Map) Delete(key types.Type) bool {\n\tif m != nil && m.table != nil {\n\t\thash := hash(key)\n\t\tbucket := m.table[hash]\n\t\tfor i, e := range bucket {\n\t\t\tif e.key != nil && types.Identical(key, e.key) {\n\t\t\t\t// We can't compact the bucket as it\n\t\t\t\t// would disturb iterators.\n\t\t\t\tbucket[i] = entry{}\n\t\t\t\tm.length--\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// At returns the map entry for the given key.\n// The result is nil if the entry is not present.\nfunc (m *Map) At(key types.Type) any {\n\tif m != nil && m.table != nil {\n\t\tfor _, e := range m.table[hash(key)] {\n\t\t\tif e.key != nil && types.Identical(key, e.key) {\n\t\t\t\treturn e.value\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// Set sets the map entry for key to val,\n// and returns the previous entry, if any.\nfunc (m *Map) Set(key types.Type, value any) (prev any) {\n\tif m.table != nil {\n\t\thash := hash(key)\n\t\tbucket := m.table[hash]\n\t\tvar hole *entry\n\t\tfor i, e := range bucket {\n\t\t\tif e.key == nil {\n\t\t\t\thole = &bucket[i]\n\t\t\t} else if types.Identical(key, e.key) {\n\t\t\t\tprev = e.value\n\t\t\t\tbucket[i].value = value\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif hole != nil {\n\t\t\t*hole = entry{key, value} // overwrite deleted entry\n\t\t} else {\n\t\t\tm.table[hash] = append(bucket, entry{key, value})\n\t\t}\n\t} else {\n\t\thash := hash(key)\n\t\tm.table = map[uint32][]entry{hash: {entry{key, value}}}\n\t}\n\n\tm.length++\n\treturn\n}\n\n// Len returns the number of map entries.\nfunc (m *Map) Len() int {\n\tif m != nil {\n\t\treturn m.length\n\t}\n\treturn 0\n}\n\n// Iterate calls function f on each entry in the map in unspecified order.\n//\n// If f should mutate the map, Iterate provides the same guarantees as\n// Go maps: if f deletes a map entry that Iterate has not yet reached,\n// f will not be invoked for it, but if f inserts a map entry that\n// Iterate has not yet reached, whether or not f will be invoked for\n// it is unspecified.\nfunc (m *Map) Iterate(f func(key types.Type, value any)) {\n\tif m != nil {\n\t\tfor _, bucket := range m.table {\n\t\t\tfor _, e := range bucket {\n\t\t\t\tif e.key != nil {\n\t\t\t\t\tf(e.key, e.value)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Keys returns a new slice containing the set of map keys.\n// The order is unspecified.\nfunc (m *Map) Keys() []types.Type {\n\tkeys := make([]types.Type, 0, m.Len())\n\tm.Iterate(func(key types.Type, _ any) {\n\t\tkeys = append(keys, key)\n\t})\n\treturn keys\n}\n\nfunc (m *Map) toString(values bool) string {\n\tif m == nil {\n\t\treturn \"{}\"\n\t}\n\tvar buf bytes.Buffer\n\tfmt.Fprint(&buf, \"{\")\n\tsep := \"\"\n\tm.Iterate(func(key types.Type, value any) {\n\t\tfmt.Fprint(&buf, sep)\n\t\tsep = \", \"\n\t\tfmt.Fprint(&buf, key)\n\t\tif values {\n\t\t\tfmt.Fprintf(&buf, \": %q\", value)\n\t\t}\n\t})\n\tfmt.Fprint(&buf, \"}\")\n\treturn buf.String()\n}\n\n// String returns a string representation of the map's entries.\n// Values are printed using fmt.Sprintf(\"%v\", v).\n// Order is unspecified.\nfunc (m *Map) String() string {\n\treturn m.toString(true)\n}\n\n// KeysString returns a string representation of the map's key set.\n// Order is unspecified.\nfunc (m *Map) KeysString() string {\n\treturn m.toString(false)\n}\n\n// -- Hasher --\n\n// hash returns the hash of type t.\n// TODO(adonovan): replace by types.Hash when Go proposal #69420 is accepted.\nfunc hash(t types.Type) uint32 {\n\treturn theHasher.Hash(t)\n}\n\n// A Hasher provides a [Hasher.Hash] method to map a type to its hash value.\n// Hashers are stateless, and all are equivalent.\ntype Hasher struct{}\n\nvar theHasher Hasher\n\n// MakeHasher returns Hasher{}.\n// Hashers are stateless; all are equivalent.\nfunc MakeHasher() Hasher { return theHasher }\n\n// Hash computes a hash value for the given type t such that\n// Identical(t, t') => Hash(t) == Hash(t').\nfunc (h Hasher) Hash(t types.Type) uint32 {\n\treturn hasher{inGenericSig: false}.hash(t)\n}\n\n// hasher holds the state of a single Hash traversal: whether we are\n// inside the signature of a generic function; this is used to\n// optimize [hasher.hashTypeParam].\ntype hasher struct{ inGenericSig bool }\n\n// hashString computes the Fowler–Noll–Vo hash of s.\nfunc hashString(s string) uint32 {\n\tvar h uint32\n\tfor i := 0; i < len(s); i++ {\n\t\th ^= uint32(s[i])\n\t\th *= 16777619\n\t}\n\treturn h\n}\n\n// hash computes the hash of t.\nfunc (h hasher) hash(t types.Type) uint32 {\n\t// See Identical for rationale.\n\tswitch t := t.(type) {\n\tcase *types.Basic:\n\t\treturn uint32(t.Kind())\n\n\tcase *types.Alias:\n\t\treturn h.hash(types.Unalias(t))\n\n\tcase *types.Array:\n\t\treturn 9043 + 2*uint32(t.Len()) + 3*h.hash(t.Elem())\n\n\tcase *types.Slice:\n\t\treturn 9049 + 2*h.hash(t.Elem())\n\n\tcase *types.Struct:\n\t\tvar hash uint32 = 9059\n\t\tfor i, n := 0, t.NumFields(); i < n; i++ {\n\t\t\tf := t.Field(i)\n\t\t\tif f.Anonymous() {\n\t\t\t\thash += 8861\n\t\t\t}\n\t\t\thash += hashString(t.Tag(i))\n\t\t\thash += hashString(f.Name()) // (ignore f.Pkg)\n\t\t\thash += h.hash(f.Type())\n\t\t}\n\t\treturn hash\n\n\tcase *types.Pointer:\n\t\treturn 9067 + 2*h.hash(t.Elem())\n\n\tcase *types.Signature:\n\t\tvar hash uint32 = 9091\n\t\tif t.Variadic() {\n\t\t\thash *= 8863\n\t\t}\n\n\t\ttparams := t.TypeParams()\n\t\tif n := tparams.Len(); n > 0 {\n\t\t\th.inGenericSig = true // affects constraints, params, and results\n\n\t\t\tfor i := range n {\n\t\t\t\ttparam := tparams.At(i)\n\t\t\t\thash += 7 * h.hash(tparam.Constraint())\n\t\t\t}\n\t\t}\n\n\t\treturn hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())\n\n\tcase *types.Union:\n\t\treturn h.hashUnion(t)\n\n\tcase *types.Interface:\n\t\t// Interfaces are identical if they have the same set of methods, with\n\t\t// identical names and types, and they have the same set of type\n\t\t// restrictions. See go/types.identical for more details.\n\t\tvar hash uint32 = 9103\n\n\t\t// Hash methods.\n\t\tfor i, n := 0, t.NumMethods(); i < n; i++ {\n\t\t\t// Method order is not significant.\n\t\t\t// Ignore m.Pkg().\n\t\t\tm := t.Method(i)\n\t\t\t// Use shallow hash on method signature to\n\t\t\t// avoid anonymous interface cycles.\n\t\t\thash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type())\n\t\t}\n\n\t\t// Hash type restrictions.\n\t\tterms, err := typeparams.InterfaceTermSet(t)\n\t\t// if err != nil t has invalid type restrictions.\n\t\tif err == nil {\n\t\t\thash += h.hashTermSet(terms)\n\t\t}\n\n\t\treturn hash\n\n\tcase *types.Map:\n\t\treturn 9109 + 2*h.hash(t.Key()) + 3*h.hash(t.Elem())\n\n\tcase *types.Chan:\n\t\treturn 9127 + 2*uint32(t.Dir()) + 3*h.hash(t.Elem())\n\n\tcase *types.Named:\n\t\thash := h.hashTypeName(t.Obj())\n\t\ttargs := t.TypeArgs()\n\t\tfor targ := range targs.Types() {\n\t\t\thash += 2 * h.hash(targ)\n\t\t}\n\t\treturn hash\n\n\tcase *types.TypeParam:\n\t\treturn h.hashTypeParam(t)\n\n\tcase *types.Tuple:\n\t\treturn h.hashTuple(t)\n\t}\n\n\tpanic(fmt.Sprintf(\"%T: %v\", t, t))\n}\n\nfunc (h hasher) hashTuple(tuple *types.Tuple) uint32 {\n\t// See go/types.identicalTypes for rationale.\n\tn := tuple.Len()\n\thash := 9137 + 2*uint32(n)\n\tfor i := range n {\n\t\thash += 3 * h.hash(tuple.At(i).Type())\n\t}\n\treturn hash\n}\n\nfunc (h hasher) hashUnion(t *types.Union) uint32 {\n\t// Hash type restrictions.\n\tterms, err := typeparams.UnionTermSet(t)\n\t// if err != nil t has invalid type restrictions. Fall back on a non-zero\n\t// hash.\n\tif err != nil {\n\t\treturn 9151\n\t}\n\treturn h.hashTermSet(terms)\n}\n\nfunc (h hasher) hashTermSet(terms []*types.Term) uint32 {\n\thash := 9157 + 2*uint32(len(terms))\n\tfor _, term := range terms {\n\t\t// term order is not significant.\n\t\ttermHash := h.hash(term.Type())\n\t\tif term.Tilde() {\n\t\t\ttermHash *= 9161\n\t\t}\n\t\thash += 3 * termHash\n\t}\n\treturn hash\n}\n\n// hashTypeParam returns the hash of a type parameter.\nfunc (h hasher) hashTypeParam(t *types.TypeParam) uint32 {\n\t// Within the signature of a generic function, TypeParams are\n\t// identical if they have the same index and constraint, so we\n\t// hash them based on index.\n\t//\n\t// When we are outside a generic function, free TypeParams are\n\t// identical iff they are the same object, so we can use a\n\t// more discriminating hash consistent with object identity.\n\t// This optimization saves [Map] about 4% when hashing all the\n\t// types.Info.Types in the forward closure of net/http.\n\tif !h.inGenericSig {\n\t\t// Optimization: outside a generic function signature,\n\t\t// use a more discrimating hash consistent with object identity.\n\t\treturn h.hashTypeName(t.Obj())\n\t}\n\treturn 9173 + 3*uint32(t.Index())\n}\n\nvar theSeed = maphash.MakeSeed()\n\n// hashTypeName hashes the pointer of tname.\nfunc (hasher) hashTypeName(tname *types.TypeName) uint32 {\n\t// Since types.Identical uses == to compare TypeNames,\n\t// the Hash function uses maphash.Comparable.\n\thash := maphash.Comparable(theSeed, tname)\n\treturn uint32(hash ^ (hash >> 32))\n}\n\n// shallowHash computes a hash of t without looking at any of its\n// element Types, to avoid potential anonymous cycles in the types of\n// interface methods.\n//\n// When an unnamed non-empty interface type appears anywhere among the\n// arguments or results of an interface method, there is a potential\n// for endless recursion. Consider:\n//\n//\ttype X interface { m() []*interface { X } }\n//\n// The problem is that the Methods of the interface in m's result type\n// include m itself; there is no mention of the named type X that\n// might help us break the cycle.\n// (See comment in go/types.identical, case *Interface, for more.)\nfunc (h hasher) shallowHash(t types.Type) uint32 {\n\t// t is the type of an interface method (Signature),\n\t// its params or results (Tuples), or their immediate\n\t// elements (mostly Slice, Pointer, Basic, Named),\n\t// so there's no need to optimize anything else.\n\tswitch t := t.(type) {\n\tcase *types.Alias:\n\t\treturn h.shallowHash(types.Unalias(t))\n\n\tcase *types.Signature:\n\t\tvar hash uint32 = 604171\n\t\tif t.Variadic() {\n\t\t\thash *= 971767\n\t\t}\n\t\t// The Signature/Tuple recursion is always finite\n\t\t// and invariably shallow.\n\t\treturn hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results())\n\n\tcase *types.Tuple:\n\t\tn := t.Len()\n\t\thash := 9137 + 2*uint32(n)\n\t\tfor i := range n {\n\t\t\thash += 53471161 * h.shallowHash(t.At(i).Type())\n\t\t}\n\t\treturn hash\n\n\tcase *types.Basic:\n\t\treturn 45212177 * uint32(t.Kind())\n\n\tcase *types.Array:\n\t\treturn 1524181 + 2*uint32(t.Len())\n\n\tcase *types.Slice:\n\t\treturn 2690201\n\n\tcase *types.Struct:\n\t\treturn 3326489\n\n\tcase *types.Pointer:\n\t\treturn 4393139\n\n\tcase *types.Union:\n\t\treturn 562448657\n\n\tcase *types.Interface:\n\t\treturn 2124679 // no recursion here\n\n\tcase *types.Map:\n\t\treturn 9109\n\n\tcase *types.Chan:\n\t\treturn 9127\n\n\tcase *types.Named:\n\t\treturn h.hashTypeName(t.Obj())\n\n\tcase *types.TypeParam:\n\t\treturn h.hashTypeParam(t)\n\t}\n\tpanic(fmt.Sprintf(\"shallowHash: %T: %v\", t, t))\n}\n"
  },
  {
    "path": "go/types/typeutil/map_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil_test\n\n// TODO(adonovan):\n// - test use of explicit hasher across two maps.\n// - test hashcodes are consistent with equals for a range of types\n//   (e.g. all types generated by type-checking some body of real code).\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar (\n\ttStr      = types.Typ[types.String]             // string\n\ttPStr1    = types.NewPointer(tStr)              // *string\n\ttPStr2    = types.NewPointer(tStr)              // *string, again\n\ttInt      = types.Typ[types.Int]                // int\n\ttChanInt1 = types.NewChan(types.RecvOnly, tInt) // <-chan int\n\ttChanInt2 = types.NewChan(types.RecvOnly, tInt) // <-chan int, again\n)\n\nfunc checkEqualButNotIdentical(t *testing.T, x, y types.Type, comment string) {\n\tif !types.Identical(x, y) {\n\t\tt.Errorf(\"%s: not equal: %s, %s\", comment, x, y)\n\t}\n\tif x == y {\n\t\tt.Errorf(\"%s: identical: %v, %v\", comment, x, y)\n\t}\n}\n\nfunc TestAxioms(t *testing.T) {\n\tcheckEqualButNotIdentical(t, tPStr1, tPStr2, \"tPstr{1,2}\")\n\tcheckEqualButNotIdentical(t, tChanInt1, tChanInt2, \"tChanInt{1,2}\")\n}\n\nfunc TestMap(t *testing.T) {\n\tvar tmap *typeutil.Map\n\n\t// All methods but Set are safe on (*T)(nil).\n\ttmap.Len()\n\ttmap.At(tPStr1)\n\ttmap.Delete(tPStr1)\n\ttmap.KeysString()\n\t_ = tmap.String()\n\n\ttmap = new(typeutil.Map)\n\n\t// Length of empty map.\n\tif l := tmap.Len(); l != 0 {\n\t\tt.Errorf(\"Len() on empty Map: got %d, want 0\", l)\n\t}\n\t// At of missing key.\n\tif v := tmap.At(tPStr1); v != nil {\n\t\tt.Errorf(\"At() on empty Map: got %v, want nil\", v)\n\t}\n\t// Deletion of missing key.\n\tif tmap.Delete(tPStr1) {\n\t\tt.Errorf(\"Delete() on empty Map: got true, want false\")\n\t}\n\t// Set of new key.\n\tif prev := tmap.Set(tPStr1, \"*string\"); prev != nil {\n\t\tt.Errorf(\"Set() on empty Map returned non-nil previous value %s\", prev)\n\t}\n\n\t// Now: {*string: \"*string\"}\n\n\t// Length of non-empty map.\n\tif l := tmap.Len(); l != 1 {\n\t\tt.Errorf(\"Len(): got %d, want 1\", l)\n\t}\n\t// At via insertion key.\n\tif v := tmap.At(tPStr1); v != \"*string\" {\n\t\tt.Errorf(\"At(): got %q, want \\\"*string\\\"\", v)\n\t}\n\t// At via equal key.\n\tif v := tmap.At(tPStr2); v != \"*string\" {\n\t\tt.Errorf(\"At(): got %q, want \\\"*string\\\"\", v)\n\t}\n\t// Iteration over sole entry.\n\ttmap.Iterate(func(key types.Type, value any) {\n\t\tif key != tPStr1 {\n\t\t\tt.Errorf(\"Iterate: key: got %s, want %s\", key, tPStr1)\n\t\t}\n\t\tif want := \"*string\"; value != want {\n\t\t\tt.Errorf(\"Iterate: value: got %s, want %s\", value, want)\n\t\t}\n\t})\n\n\t// Setion with key equal to present one.\n\tif prev := tmap.Set(tPStr2, \"*string again\"); prev != \"*string\" {\n\t\tt.Errorf(\"Set() previous value: got %s, want \\\"*string\\\"\", prev)\n\t}\n\n\t// Setion of another association.\n\tif prev := tmap.Set(tChanInt1, \"<-chan int\"); prev != nil {\n\t\tt.Errorf(\"Set() previous value: got %s, want nil\", prev)\n\t}\n\n\t// Now: {*string: \"*string again\", <-chan int: \"<-chan int\"}\n\n\twant1 := \"{*string: \\\"*string again\\\", <-chan int: \\\"<-chan int\\\"}\"\n\twant2 := \"{<-chan int: \\\"<-chan int\\\", *string: \\\"*string again\\\"}\"\n\tif s := tmap.String(); s != want1 && s != want2 {\n\t\tt.Errorf(\"String(): got %s, want %s\", s, want1)\n\t}\n\n\twant1 = \"{*string, <-chan int}\"\n\twant2 = \"{<-chan int, *string}\"\n\tif s := tmap.KeysString(); s != want1 && s != want2 {\n\t\tt.Errorf(\"KeysString(): got %s, want %s\", s, want1)\n\t}\n\n\t// Keys().\n\tI := types.Identical\n\tswitch k := tmap.Keys(); {\n\tcase I(k[0], tChanInt1) && I(k[1], tPStr1): // ok\n\tcase I(k[1], tChanInt1) && I(k[0], tPStr1): // ok\n\tdefault:\n\t\tt.Errorf(\"Keys(): got %v, want %s\", k, want2)\n\t}\n\n\tif l := tmap.Len(); l != 2 {\n\t\tt.Errorf(\"Len(): got %d, want 1\", l)\n\t}\n\t// At via original key.\n\tif v := tmap.At(tPStr1); v != \"*string again\" {\n\t\tt.Errorf(\"At(): got %q, want \\\"*string again\\\"\", v)\n\t}\n\thamming := 1\n\ttmap.Iterate(func(key types.Type, value any) {\n\t\tswitch {\n\t\tcase I(key, tChanInt1):\n\t\t\thamming *= 2 // ok\n\t\tcase I(key, tPStr1):\n\t\t\thamming *= 3 // ok\n\t\t}\n\t})\n\tif hamming != 6 {\n\t\tt.Errorf(\"Iterate: hamming: got %d, want %d\", hamming, 6)\n\t}\n\n\tif v := tmap.At(tChanInt2); v != \"<-chan int\" {\n\t\tt.Errorf(\"At(): got %q, want \\\"<-chan int\\\"\", v)\n\t}\n\t// Deletion with key equal to present one.\n\tif !tmap.Delete(tChanInt2) {\n\t\tt.Errorf(\"Delete() of existing key: got false, want true\")\n\t}\n\n\t// Now: {*string: \"*string again\"}\n\n\tif l := tmap.Len(); l != 1 {\n\t\tt.Errorf(\"Len(): got %d, want 1\", l)\n\t}\n\t// Deletion again.\n\tif !tmap.Delete(tPStr2) {\n\t\tt.Errorf(\"Delete() of existing key: got false, want true\")\n\t}\n\n\t// Now: {}\n\n\tif l := tmap.Len(); l != 0 {\n\t\tt.Errorf(\"Len(): got %d, want %d\", l, 0)\n\t}\n\tif s := tmap.String(); s != \"{}\" {\n\t\tt.Errorf(\"Len(): got %q, want %q\", s, \"\")\n\t}\n}\n\nfunc TestMapGenerics(t *testing.T) {\n\tconst src = `\npackage p\n\n// Basic defined types.\ntype T1 int\ntype T2 int\n\n// Identical methods.\nfunc (T1) M(int) {}\nfunc (T2) M(int) {}\n\n// A constraint interface.\ntype C interface {\n\t~int | string\n}\n\ntype I interface {\n}\n\n// A generic type.\ntype G[P C] int\n\n// Generic functions with identical signature.\nfunc Fa1[P C](p P) {}\nfunc Fa2[Q C](q Q) {}\n\n// Fb1 and Fb2 are identical and should be mapped to the same entry, even if we\n// map their arguments first.\nfunc Fb1[P any](x *P) {\n\tvar y *P // Map this first.\n\t_ = y\n}\nfunc Fb2[Q any](x *Q) {\n}\n\n// G1 and G2 are mutually recursive, and have identical methods.\ntype G1[P any] struct{\n\tField *G2[P]\n}\nfunc (G1[P]) M(G1[P], G2[P]) {}\ntype G2[Q any] struct{\n\tField *G1[Q]\n}\nfunc (G2[P]) M(G1[P], G2[P]) {}\n\n// Method type expressions on different generic types are different.\nvar ME1 = G1[int].M\nvar ME2 = G2[int].M\n\n// ME1Type should have identical type as ME1.\nvar ME1Type func(G1[int], G1[int], G2[int])\n\n// Examples from issue #51314\ntype Constraint[T any] any\nfunc Foo[T Constraint[T]]() {}\nfunc Fn[T1 ~*T2, T2 ~*T1](t1 T1, t2 T2) {}\n\n// Bar and Baz are identical to Foo.\nfunc Bar[P Constraint[P]]() {}\nfunc Baz[Q any]() {} // The underlying type of Constraint[P] is any.\n// But Quux is not.\nfunc Quux[Q interface{ quux() }]() {}\n\n\ntype Issue56048_I interface{ m() interface { Issue56048_I } }\nvar Issue56048 = Issue56048_I.m\n\ntype Issue56048_Ib interface{ m() chan []*interface { Issue56048_Ib } }\nvar Issue56048b = Issue56048_Ib.m\n\n// Non-generic alias\ntype NonAlias int\ntype Alias1 = NonAlias\ntype Alias2 = NonAlias\n\n// Generic alias (requires go1.23)\n// type SetOfInt = map[int]bool\n// type Set[T comparable] = map[K]bool\n// type SetOfInt2 = Set[int]\n`\n\n\tfset := token.NewFileSet()\n\tfile, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"\", fset, []*ast.File{file}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Collect types.\n\tscope := pkg.Scope()\n\tvar (\n\t\tT1      = scope.Lookup(\"T1\").Type().(*types.Named)\n\t\tT2      = scope.Lookup(\"T2\").Type().(*types.Named)\n\t\tT1M     = T1.Method(0).Type()\n\t\tT2M     = T2.Method(0).Type()\n\t\tG       = scope.Lookup(\"G\").Type()\n\t\tGInt1   = instantiate(t, G, types.Typ[types.Int])\n\t\tGInt2   = instantiate(t, G, types.Typ[types.Int])\n\t\tGStr    = instantiate(t, G, types.Typ[types.String])\n\t\tC       = scope.Lookup(\"C\").Type()\n\t\tCI      = C.Underlying().(*types.Interface)\n\t\tI       = scope.Lookup(\"I\").Type()\n\t\tII      = I.Underlying().(*types.Interface)\n\t\tU       = CI.EmbeddedType(0).(*types.Union)\n\t\tFa1     = scope.Lookup(\"Fa1\").Type().(*types.Signature)\n\t\tFa2     = scope.Lookup(\"Fa2\").Type().(*types.Signature)\n\t\tFa1P    = Fa1.TypeParams().At(0)\n\t\tFa2Q    = Fa2.TypeParams().At(0)\n\t\tFb1     = scope.Lookup(\"Fb1\").Type().(*types.Signature)\n\t\tFb1x    = Fb1.Params().At(0).Type()\n\t\tFb1y    = scope.Lookup(\"Fb1\").(*types.Func).Scope().Lookup(\"y\").Type()\n\t\tFb2     = scope.Lookup(\"Fb2\").Type().(*types.Signature)\n\t\tFb2x    = Fb2.Params().At(0).Type()\n\t\tG1      = scope.Lookup(\"G1\").Type().(*types.Named)\n\t\tG1M     = G1.Method(0).Type()\n\t\tG1IntM1 = instantiate(t, G1, types.Typ[types.Int]).(*types.Named).Method(0).Type()\n\t\tG1IntM2 = instantiate(t, G1, types.Typ[types.Int]).(*types.Named).Method(0).Type()\n\t\tG1StrM  = instantiate(t, G1, types.Typ[types.String]).(*types.Named).Method(0).Type()\n\t\tG2      = scope.Lookup(\"G2\").Type()\n\t\t// See below.\n\t\t// G2M     = G2.Method(0).Type()\n\t\tG2IntM  = instantiate(t, G2, types.Typ[types.Int]).(*types.Named).Method(0).Type()\n\t\tME1     = scope.Lookup(\"ME1\").Type()\n\t\tME1Type = scope.Lookup(\"ME1Type\").Type()\n\t\tME2     = scope.Lookup(\"ME2\").Type()\n\n\t\tConstraint  = scope.Lookup(\"Constraint\").Type()\n\t\tFoo         = scope.Lookup(\"Foo\").Type()\n\t\tFn          = scope.Lookup(\"Fn\").Type()\n\t\tBar         = scope.Lookup(\"Foo\").Type()\n\t\tBaz         = scope.Lookup(\"Foo\").Type()\n\t\tQuux        = scope.Lookup(\"Quux\").Type()\n\t\tIssue56048  = scope.Lookup(\"Issue56048\").Type()\n\t\tIssue56048b = scope.Lookup(\"Issue56048b\").Type()\n\n\t\t// In go1.23 these will be *types.Alias; for now they are all int.\n\t\tNonAlias = scope.Lookup(\"NonAlias\").Type()\n\t\tAlias1   = scope.Lookup(\"Alias1\").Type()\n\t\tAlias2   = scope.Lookup(\"Alias2\").Type()\n\n\t\t// Requires go1.23.\n\t\t// SetOfInt    = scope.Lookup(\"SetOfInt\").Type()\n\t\t// Set         = scope.Lookup(\"Set\").Type().(*types.Alias)\n\t\t// SetOfInt2   = scope.Lookup(\"SetOfInt2\").Type()\n\t)\n\n\ttmap := new(typeutil.Map)\n\n\tsteps := []struct {\n\t\ttyp      types.Type\n\t\tname     string\n\t\tnewEntry bool\n\t}{\n\t\t{T1, \"T1\", true},\n\t\t{T2, \"T2\", true},\n\t\t{G, \"G\", true},\n\t\t{C, \"C\", true},\n\t\t{CI, \"CI\", true},\n\t\t{U, \"U\", true},\n\t\t{I, \"I\", true},\n\t\t{II, \"II\", true}, // should not be identical to CI\n\n\t\t// Methods can be identical, even with distinct receivers.\n\t\t{T1M, \"T1M\", true},\n\t\t{T2M, \"T2M\", false},\n\n\t\t// Identical instances should map to the same entry.\n\t\t{GInt1, \"GInt1\", true},\n\t\t{GInt2, \"GInt2\", false},\n\t\t// ..but instantiating with different arguments should yield a new entry.\n\t\t{GStr, \"GStr\", true},\n\n\t\t// F1 and F2 should have identical signatures.\n\t\t{Fa1, \"F1\", true},\n\t\t{Fa2, \"F2\", false},\n\n\t\t// The identity of P and Q should not have been affected by type parameter\n\t\t// masking during signature hashing.\n\t\t{Fa1P, \"F1P\", true},\n\t\t{Fa2Q, \"F2Q\", true},\n\n\t\t{Fb1y, \"Fb1y\", true},\n\t\t{Fb1x, \"Fb1x\", false},\n\t\t{Fb2x, \"Fb2x\", true},\n\t\t{Fb1, \"Fb1\", true},\n\n\t\t// Mapping elements of the function scope should not affect the identity of\n\t\t// Fb2 or Fb1.\n\t\t{Fb2, \"Fb1\", false},\n\n\t\t{G1, \"G1\", true},\n\t\t{G1M, \"G1M\", true},\n\t\t{G2, \"G2\", true},\n\n\t\t// See golang/go#49912: receiver type parameter names should be ignored\n\t\t// when comparing method identity.\n\t\t// {G2M, \"G2M\", false},\n\t\t{G1IntM1, \"G1IntM1\", true},\n\t\t{G1IntM2, \"G1IntM2\", false},\n\t\t{G1StrM, \"G1StrM\", true},\n\t\t{G2IntM, \"G2IntM\", false}, // identical to G1IntM1\n\n\t\t{ME1, \"ME1\", true},\n\t\t{ME1Type, \"ME1Type\", false},\n\t\t{ME2, \"ME2\", true},\n\n\t\t// See golang/go#51314: avoid infinite recursion on cyclic type constraints.\n\t\t{Constraint, \"Constraint\", true},\n\t\t{Foo, \"Foo\", true},\n\t\t{Fn, \"Fn\", true},\n\t\t{Bar, \"Bar\", false},\n\t\t{Baz, \"Baz\", false},\n\t\t{Quux, \"Quux\", true},\n\n\t\t{Issue56048, \"Issue56048\", true},   // (not actually about generics)\n\t\t{Issue56048b, \"Issue56048b\", true}, // (not actually about generics)\n\n\t\t// All three types are identical.\n\t\t{NonAlias, \"NonAlias\", true},\n\t\t{Alias1, \"Alias1\", false},\n\t\t{Alias2, \"Alias2\", false},\n\n\t\t// Generic aliases: requires go1.23.\n\t\t// {SetOfInt, \"SetOfInt\", true},\n\t\t// {Set, \"Set\", false},\n\t\t// {SetOfInt2, \"SetOfInt2\", false},\n\t}\n\n\tfor _, step := range steps {\n\t\texisting := tmap.At(step.typ)\n\t\tif (existing == nil) != step.newEntry {\n\t\t\tt.Errorf(\"At(%s) = %v, want new entry: %t\", step.name, existing, step.newEntry)\n\t\t}\n\t\ttmap.Set(step.typ, step.name)\n\t}\n}\n\nfunc instantiate(t *testing.T, origin types.Type, targs ...types.Type) types.Type {\n\tinst, err := types.Instantiate(nil, origin, targs, true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn inst\n}\n\n// BenchmarkMap stores the type of every expression in the net/http\n// package in a map.\nfunc BenchmarkMap(b *testing.B) {\n\ttestenv.NeedsGoPackages(b)\n\n\t// Load all dependencies of net/http.\n\tcfg := &packages.Config{Mode: packages.LoadAllSyntax}\n\tpkgs, err := packages.Load(cfg, \"net/http\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\n\t// Gather all unique types.Type pointers (>67K) annotating the syntax.\n\tallTypes := make(map[types.Type]bool)\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tfor _, tv := range pkg.TypesInfo.Types {\n\t\t\tallTypes[tv.Type] = true\n\t\t}\n\t})\n\n\tfor b.Loop() {\n\t\t// De-duplicate the logically identical types.\n\t\tvar tmap typeutil.Map\n\t\tfor t := range allTypes {\n\t\t\ttmap.Set(t, nil)\n\t\t}\n\n\t\t// For sanity, ensure we find a minimum number\n\t\t// of distinct type equivalence classes.\n\t\tif want := 12000; tmap.Len() < want {\n\t\t\tb.Errorf(\"too few types (from %d types.Type values, got %d logically distinct types, want >=%d)\",\n\t\t\t\tlen(allTypes),\n\t\t\t\ttmap.Len(),\n\t\t\t\twant)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/types/typeutil/methodsetcache.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements a cache of method sets.\n\npackage typeutil\n\nimport (\n\t\"go/types\"\n\t\"sync\"\n)\n\n// A MethodSetCache records the method set of each type T for which\n// MethodSet(T) is called so that repeat queries are fast.\n// The zero value is a ready-to-use cache instance.\ntype MethodSetCache struct {\n\tmu     sync.Mutex\n\tnamed  map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N\n\tothers map[types.Type]*types.MethodSet                            // all other types\n}\n\n// MethodSet returns the method set of type T.  It is thread-safe.\n//\n// If cache is nil, this function is equivalent to types.NewMethodSet(T).\n// Utility functions can thus expose an optional *MethodSetCache\n// parameter to clients that care about performance.\nfunc (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {\n\tif cache == nil {\n\t\treturn types.NewMethodSet(T)\n\t}\n\tcache.mu.Lock()\n\tdefer cache.mu.Unlock()\n\n\tswitch T := types.Unalias(T).(type) {\n\tcase *types.Named:\n\t\treturn cache.lookupNamed(T).value\n\n\tcase *types.Pointer:\n\t\tif N, ok := types.Unalias(T.Elem()).(*types.Named); ok {\n\t\t\treturn cache.lookupNamed(N).pointer\n\t\t}\n\t}\n\n\t// all other types\n\t// (The map uses pointer equivalence, not type identity.)\n\tmset := cache.others[T]\n\tif mset == nil {\n\t\tmset = types.NewMethodSet(T)\n\t\tif cache.others == nil {\n\t\t\tcache.others = make(map[types.Type]*types.MethodSet)\n\t\t}\n\t\tcache.others[T] = mset\n\t}\n\treturn mset\n}\n\nfunc (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {\n\tif cache.named == nil {\n\t\tcache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })\n\t}\n\t// Avoid recomputing mset(*T) for each distinct Pointer\n\t// instance whose underlying type is a named type.\n\tmsets, ok := cache.named[named]\n\tif !ok {\n\t\tmsets.value = types.NewMethodSet(named)\n\t\tmsets.pointer = types.NewMethodSet(types.NewPointer(named))\n\t\tcache.named[named] = msets\n\t}\n\treturn msets\n}\n"
  },
  {
    "path": "go/types/typeutil/ui.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil\n\n// This file defines utilities for user interfaces that display types.\n\nimport (\n\t\"go/types\"\n)\n\n// IntuitiveMethodSet returns the intuitive method set of a type T,\n// which is the set of methods you can call on an addressable value of\n// that type.\n//\n// The result always contains MethodSet(T), and is exactly MethodSet(T)\n// for interface types and for pointer-to-concrete types.\n// For all other concrete types T, the result additionally\n// contains each method belonging to *T if there is no identically\n// named method on T itself.\n//\n// This corresponds to user intuition about method sets;\n// this function is intended only for user interfaces.\n//\n// The order of the result is as for types.MethodSet(T).\nfunc IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {\n\tisPointerToConcrete := func(T types.Type) bool {\n\t\tptr, ok := types.Unalias(T).(*types.Pointer)\n\t\treturn ok && !types.IsInterface(ptr.Elem())\n\t}\n\n\tvar result []*types.Selection\n\tmset := msets.MethodSet(T)\n\tif types.IsInterface(T) || isPointerToConcrete(T) {\n\t\tfor i, n := 0, mset.Len(); i < n; i++ {\n\t\t\tresult = append(result, mset.At(i))\n\t\t}\n\t} else {\n\t\t// T is some other concrete type.\n\t\t// Report methods of T and *T, preferring those of T.\n\t\tpmset := msets.MethodSet(types.NewPointer(T))\n\t\tfor i, n := 0, pmset.Len(); i < n; i++ {\n\t\t\tmeth := pmset.At(i)\n\t\t\tif m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {\n\t\t\t\tmeth = m\n\t\t\t}\n\t\t\tresult = append(result, meth)\n\t\t}\n\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "go/types/typeutil/ui_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeutil_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\nfunc TestIntuitiveMethodSet(t *testing.T) {\n\tconst source = `\npackage P\ntype A int\nfunc (A) f()\nfunc (*A) g()\n`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tqual := types.RelativeTo(pkg)\n\n\tfor _, test := range []struct {\n\t\texpr string // type expression\n\t\twant string // intuitive method set\n\t}{\n\t\t{\"A\", \"(A).f (*A).g\"},\n\t\t{\"*A\", \"(*A).f (*A).g\"},\n\t\t{\"error\", \"(error).Error\"},\n\t\t{\"*error\", \"\"},\n\t\t{\"struct{A}\", \"(struct{A}).f (*struct{A}).g\"},\n\t\t{\"*struct{A}\", \"(*struct{A}).f (*struct{A}).g\"},\n\t} {\n\t\ttv, err := types.Eval(fset, pkg, 0, test.expr)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\t\tvar names []string\n\t\tfor _, m := range typeutil.IntuitiveMethodSet(tv.Type, nil) {\n\t\t\tname := fmt.Sprintf(\"(%s).%s\", types.TypeString(m.Recv(), qual), m.Obj().Name())\n\t\t\tnames = append(names, name)\n\t\t}\n\t\tgot := strings.Join(names, \" \")\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"IntuitiveMethodSet(%s) = %q, want %q\", test.expr, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module golang.org/x/tools\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/google/go-cmp v0.6.0\n\tgithub.com/yuin/goldmark v1.4.13\n\tgolang.org/x/mod v0.34.0\n\tgolang.org/x/net v0.52.0\n\tgolang.org/x/sync v0.20.0\n\tgolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c\n)\n\nrequire golang.org/x/sys v0.42.0 // indirect\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngolang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=\ngolang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=\ngolang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=\ngolang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=\ngolang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=\ngolang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=\ngolang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=\ngolang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=\ngolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc=\ngolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw=\n"
  },
  {
    "path": "gopls/README.md",
    "content": "# `gopls`, the language server for Go\n\n[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools/gopls)](https://pkg.go.dev/golang.org/x/tools/gopls)\n\n`gopls` (pronounced \"Go please\") is the official [language\nserver](https://langserver.org) for Go, developed and maintained by\nthe Go team.\nIt provides a wide variety of [IDE features](doc/features/)\nto any [LSP](https://microsoft.github.io/language-server-protocol/)-compatible\neditor.\n\n- Documentation for [users](https://go.dev/gopls)\n- Documentation for [contributors](doc/contributing.md)\n"
  },
  {
    "path": "gopls/contributors.txt",
    "content": "# This list is used to help generate the GitHub handles in the\n# contributor shout-out of each gopls release note.\n#\n# Use a command such as this to convert a range of git commits:\n#\n# $ join -o 2.2 <(git log --format=\"format: %aE\" gopls/v0.18.1..gopls/v0.19.0-pre.3 | sort -u) \\\n#               <(grep '^[^#]' ~/w/xtools/gopls/contributors.txt | sort)\n#\n# Use -v 1 instead of -o 2.2 to detect any missing entries.\n\nacehinnnqru@gmail.com\t\tacehinnnqru\nadonovan@google.com \t\tadonovan\nalbertofanjul@gmail.com\t\talbfan\nalessandro.arzilli@gmail.com \taarzilli\nashurbekovz23@gmail.com \tashurbekovz\ncuong.manhle.vn@gmail.com       cuonglm\ndmitshur@golang.org \t\tdmitshur\ndneil@google.com \t\tneild\negonelbre@gmail.com \t\tegonelbre\nemail@ssnk.in\t\t\tshashank-priyadarshi\nethan.reesor@gmail.com\t\tfirelizzard18\ngobot@golang.org\t\tgopherbot\nhxjiang@golang.org\t\th9jiang\nimcusg@gmail.com\t\tcuishuang\njacob.b.bailey@gmail.com\tjakebailey\njba@google.com                  jba\nmkalil@google.com               madelinekalil\nmrnk3078@gmail.com\t\tkaramaru-alpha\nnguyenbao1917@gmail.com\t\tdanztran\nnick.ripley@datadoghq.com \tnsrip-dd\npjw@google.com \t\t\tpjweinb\nrfindley@google.com \t\tfindleyr\nsamthanawalla@google.com \tsamthanawalla\nsean@liao.dev \t\t\tseankhliao\ntklauser@distanz.ch \t\ttklauser\nveblomqvist@gmail.com\t\tvikblom\nweingartner@google.com\t\tkwjw\nxieyuschen@gmail.com\t\txieyuschen\n\n# GitHub ID unknown:\n# - shibinxf@gmail.com\n"
  },
  {
    "path": "gopls/doc/README.md",
    "content": "See [index.md](index.md).\n"
  },
  {
    "path": "gopls/doc/advanced.md",
    "content": "---\ntitle: \"Gopls: Advanced topics\"\n---\n\nThis documentation is for advanced `gopls` users, who may want to test\nunreleased versions or try out special features.\n\n## Installing unreleased versions\n\nTo get a specific version of `gopls` (for example, to test a prerelease\nversion), run:\n\n```sh\n$ go install golang.org/x/tools/gopls@vX.Y.Z\n```\n\nWhere `vX.Y.Z` is the desired version.\n\n### Unstable versions\n\nTo update `gopls` to the latest **unstable** version, use the following\ncommands.\n\n```sh\n# Create an empty go.mod file, only for tracking requirements.\ncd $(mktemp -d)\ngo mod init gopls-unstable\n\n# Use 'go get' to add requirements and to ensure they work together.\ngo get -d golang.org/x/tools/gopls@master golang.org/x/tools@master\n\ngo install golang.org/x/tools/gopls\n```\n\n## Working on the Go source distribution\n\nIf you are working on the [Go project] itself, the `go` command that `gopls`\ninvokes will have to correspond to the version of the source you are working\non. That is, if you have checked out the Go project to `$HOME/go-tip`, your\n`go` command should be the `$HOME/go-tip/bin/go` executable that you built\nwith `make.bash` or equivalent.\n\nYou can achieve this by adding the right version of `go` to your `PATH`\n(`export PATH=$HOME/go-tip/bin:$PATH` on Unix systems) or by configuring your\neditor.\n\nTo work on both `std` and `cmd` simultaneously, add a `go.work` file to\n`GOROOT/src`:\n\n```\ncd $(go env GOROOT)/src\ngo work init . cmd\n```\n\nNote that you must work inside the `GOROOT/src` subdirectory, as the `go`\ncommand does not recognize `go.work` files in a parent of `GOROOT/src`\n(https://go.dev/issue/59429).\n\n[Go project]: https://go.googlesource.com/go\n"
  },
  {
    "path": "gopls/doc/analyzers.md",
    "content": "---\ntitle: \"Gopls: Analyzers\"\n---\n\n<!-- No Table of Contents: GitHub's Markdown renderer synthesizes it. -->\n\nGopls contains a driver for pluggable, modular static\n[analyzers](https://pkg.go.dev/golang.org/x/tools/go/analysis#hdr-Analyzer),\nsuch as those used by [go vet](https://pkg.go.dev/cmd/vet).\n\nMost analyzers report mistakes in your code;\nsome suggest \"quick fixes\" that can be directly applied in your editor.\nEvery time you edit your code, gopls re-runs its analyzers.\nAnalyzer diagnostics help you detect bugs sooner,\nbefore you run your tests, or even before you save your files.\n\nThis document describes the suite of analyzers available in gopls,\nwhich aggregates analyzers from a variety of sources:\n\n- all the usual bug-finding analyzers from the `go vet` suite (e.g. `printf`; see [`go tool vet help`](https://pkg.go.dev/cmd/vet) for the complete list);\n- a number of analyzers with more substantial dependencies that prevent them from being used in `go vet` (e.g. `nilness`);\n- analyzers that augment compilation errors by suggesting quick fixes to common mistakes (e.g. `fillreturns`); and\n- a handful of analyzers that suggest possible style improvements (e.g. `simplifyrange`).\n\nTo enable or disable analyzers, use the [analyses](settings.md#analyses) setting.\n\nIn addition, gopls includes the [`staticcheck` suite](https://staticcheck.dev/docs/checks).\nWhen the [`staticcheck`](settings.md#staticcheck`) boolean option is\nunset, slightly more than half of these analyzers are enabled by\ndefault; this subset has been chosen for precision and efficiency. Set\n`staticcheck` to `true` to enable the complete set, or to `false` to\ndisable the complete set.\n\nStaticcheck analyzers, like all other analyzers, can be explicitly\nenabled or disabled using the `analyzers` configuration setting; this\nsetting takes precedence over the `staticcheck` setting, so,\nregardless of what value of `staticcheck` you use (true/false/unset),\nyou can make adjustments to your preferred set of analyzers.\n\n\n<!-- BEGIN Analyzers: DO NOT MANUALLY EDIT THIS SECTION -->\n<a id='QF1001'></a>\n## `QF1001`: Apply De Morgan's law\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1001\": true}`.\n\nPackage documentation: [QF1001](https://staticcheck.dev/docs/checks/#QF1001)\n\n<a id='QF1002'></a>\n## `QF1002`: Convert untagged switch to tagged switch\n\nAn untagged switch that compares a single variable against a series of values can be replaced with a tagged switch.\n\nBefore:\n\n\tswitch {\n\tcase x == 1 || x == 2, x == 3:\n\t    ...\n\tcase x == 4:\n\t    ...\n\tdefault:\n\t    ...\n\t}\n\nAfter:\n\n\tswitch x {\n\tcase 1, 2, 3:\n\t    ...\n\tcase 4:\n\t    ...\n\tdefault:\n\t    ...\n\t}\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [QF1002](https://staticcheck.dev/docs/checks/#QF1002)\n\n<a id='QF1003'></a>\n## `QF1003`: Convert if/else-if chain to tagged switch\n\nA series of if/else-if checks comparing the same variable against values can be replaced with a tagged switch.\n\nBefore:\n\n\tif x == 1 || x == 2 {\n\t    ...\n\t} else if x == 3 {\n\t    ...\n\t} else {\n\t    ...\n\t}\n\nAfter:\n\n\tswitch x {\n\tcase 1, 2:\n\t    ...\n\tcase 3:\n\t    ...\n\tdefault:\n\t    ...\n\t}\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [QF1003](https://staticcheck.dev/docs/checks/#QF1003)\n\n<a id='QF1004'></a>\n## `QF1004`: Use strings.ReplaceAll instead of strings.Replace with n == -1\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [QF1004](https://staticcheck.dev/docs/checks/#QF1004)\n\n<a id='QF1005'></a>\n## `QF1005`: Expand call to math.Pow\n\nSome uses of math.Pow can be simplified to basic multiplication.\n\nBefore:\n\n\tmath.Pow(x, 2)\n\nAfter:\n\n\tx * x\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1005\": true}`.\n\nPackage documentation: [QF1005](https://staticcheck.dev/docs/checks/#QF1005)\n\n<a id='QF1006'></a>\n## `QF1006`: Lift if+break into loop condition\n\nBefore:\n\n\tfor {\n\t    if done {\n\t        break\n\t    }\n\t    ...\n\t}\n\nAfter:\n\n\tfor !done {\n\t    ...\n\t}\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1006\": true}`.\n\nPackage documentation: [QF1006](https://staticcheck.dev/docs/checks/#QF1006)\n\n<a id='QF1007'></a>\n## `QF1007`: Merge conditional assignment into variable declaration\n\nBefore:\n\n\tx := false\n\tif someCondition {\n\t    x = true\n\t}\n\nAfter:\n\n\tx := someCondition\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1007\": true}`.\n\nPackage documentation: [QF1007](https://staticcheck.dev/docs/checks/#QF1007)\n\n<a id='QF1008'></a>\n## `QF1008`: Omit embedded fields from selector expression\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1008\": true}`.\n\nPackage documentation: [QF1008](https://staticcheck.dev/docs/checks/#QF1008)\n\n<a id='QF1009'></a>\n## `QF1009`: Use time.Time.Equal instead of == operator\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [QF1009](https://staticcheck.dev/docs/checks/#QF1009)\n\n<a id='QF1010'></a>\n## `QF1010`: Convert slice of bytes to string when printing it\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [QF1010](https://staticcheck.dev/docs/checks/#QF1010)\n\n<a id='QF1011'></a>\n## `QF1011`: Omit redundant type from variable declaration\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"QF1011\": true}`.\n\nPackage documentation: [QF1011](https://staticcheck.dev/docs/checks/#)\n\n<a id='QF1012'></a>\n## `QF1012`: Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))\n\nAvailable since\n\n\t2022.1\n\n\nDefault: on.\n\nPackage documentation: [QF1012](https://staticcheck.dev/docs/checks/#QF1012)\n\n<a id='S1000'></a>\n## `S1000`: Use plain channel send or receive instead of single-case select\n\nSelect statements with a single case can be replaced with a simple send or receive.\n\nBefore:\n\n\tselect {\n\tcase x := <-ch:\n\t    fmt.Println(x)\n\t}\n\nAfter:\n\n\tx := <-ch\n\tfmt.Println(x)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1000](https://staticcheck.dev/docs/checks/#S1000)\n\n<a id='S1001'></a>\n## `S1001`: Replace for loop with call to copy\n\nUse copy() for copying elements from one slice to another. For arrays of identical size, you can use simple assignment.\n\nBefore:\n\n\tfor i, x := range src {\n\t    dst[i] = x\n\t}\n\nAfter:\n\n\tcopy(dst, src)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1001](https://staticcheck.dev/docs/checks/#S1001)\n\n<a id='S1002'></a>\n## `S1002`: Omit comparison with boolean constant\n\nBefore:\n\n\tif x == true {}\n\nAfter:\n\n\tif x {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1002\": true}`.\n\nPackage documentation: [S1002](https://staticcheck.dev/docs/checks/#S1002)\n\n<a id='S1003'></a>\n## `S1003`: Replace call to strings.Index with strings.Contains\n\nBefore:\n\n\tif strings.Index(x, y) != -1 {}\n\nAfter:\n\n\tif strings.Contains(x, y) {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1003](https://staticcheck.dev/docs/checks/#S1003)\n\n<a id='S1004'></a>\n## `S1004`: Replace call to bytes.Compare with bytes.Equal\n\nBefore:\n\n\tif bytes.Compare(x, y) == 0 {}\n\nAfter:\n\n\tif bytes.Equal(x, y) {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1004](https://staticcheck.dev/docs/checks/#S1004)\n\n<a id='S1005'></a>\n## `S1005`: Drop unnecessary use of the blank identifier\n\nIn many cases, assigning to the blank identifier is unnecessary.\n\nBefore:\n\n\tfor _ = range s {}\n\tx, _ = someMap[key]\n\t_ = <-ch\n\nAfter:\n\n\tfor range s{}\n\tx = someMap[key]\n\t<-ch\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1005\": true}`.\n\nPackage documentation: [S1005](https://staticcheck.dev/docs/checks/#S1005)\n\n<a id='S1006'></a>\n## `S1006`: Use 'for { ... }' for infinite loops\n\nFor infinite loops, using for { ... } is the most idiomatic choice.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1006\": true}`.\n\nPackage documentation: [S1006](https://staticcheck.dev/docs/checks/#S1006)\n\n<a id='S1007'></a>\n## `S1007`: Simplify regular expression by using raw string literal\n\nRaw string literals use backticks instead of quotation marks and do not support any escape sequences. This means that the backslash can be used freely, without the need of escaping.\n\nSince regular expressions have their own escape sequences, raw strings can improve their readability.\n\nBefore:\n\n\tregexp.Compile(\"\\\\A(\\\\w+) profile: total \\\\d+\\\\n\\\\z\")\n\nAfter:\n\n\tregexp.Compile(`\\A(\\w+) profile: total \\d+\\n\\z`)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1007](https://staticcheck.dev/docs/checks/#S1007)\n\n<a id='S1008'></a>\n## `S1008`: Simplify returning boolean expression\n\nBefore:\n\n\tif <expr> {\n\t    return true\n\t}\n\treturn false\n\nAfter:\n\n\treturn <expr>\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1008\": true}`.\n\nPackage documentation: [S1008](https://staticcheck.dev/docs/checks/#S1008)\n\n<a id='S1009'></a>\n## `S1009`: Omit redundant nil check on slices, maps, and channels\n\nThe len function is defined for all slices, maps, and channels, even nil ones, which have a length of zero. It is not necessary to check for nil before checking that their length is not zero.\n\nBefore:\n\n\tif x != nil && len(x) != 0 {}\n\nAfter:\n\n\tif len(x) != 0 {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1009](https://staticcheck.dev/docs/checks/#S1009)\n\n<a id='S1010'></a>\n## `S1010`: Omit default slice index\n\nWhen slicing, the second index defaults to the length of the value, making s\\[n:len(s)] and s\\[n:] equivalent.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1010](https://staticcheck.dev/docs/checks/#S1010)\n\n<a id='S1011'></a>\n## `S1011`: Use a single append to concatenate two slices\n\nBefore:\n\n\tfor _, e := range y {\n\t    x = append(x, e)\n\t}\n\n\tfor i := range y {\n\t    x = append(x, y[i])\n\t}\n\n\tfor i := range y {\n\t    v := y[i]\n\t    x = append(x, v)\n\t}\n\nAfter:\n\n\tx = append(x, y...)\n\tx = append(x, y...)\n\tx = append(x, y...)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1011\": true}`.\n\nPackage documentation: [S1011](https://staticcheck.dev/docs/checks/#S1011)\n\n<a id='S1012'></a>\n## `S1012`: Replace time.Now().Sub(x) with time.Since(x)\n\nThe time.Since helper has the same effect as using time.Now().Sub(x) but is easier to read.\n\nBefore:\n\n\ttime.Now().Sub(x)\n\nAfter:\n\n\ttime.Since(x)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1012](https://staticcheck.dev/docs/checks/#S1012)\n\n<a id='S1016'></a>\n## `S1016`: Use a type conversion instead of manually copying struct fields\n\nTwo struct types with identical fields can be converted between each other. In older versions of Go, the fields had to have identical struct tags. Since Go 1.8, however, struct tags are ignored during conversions. It is thus not necessary to manually copy every field individually.\n\nBefore:\n\n\tvar x T1\n\ty := T2{\n\t    Field1: x.Field1,\n\t    Field2: x.Field2,\n\t}\n\nAfter:\n\n\tvar x T1\n\ty := T2(x)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1016\": true}`.\n\nPackage documentation: [S1016](https://staticcheck.dev/docs/checks/#S1016)\n\n<a id='S1017'></a>\n## `S1017`: Replace manual trimming with strings.TrimPrefix\n\nInstead of using strings.HasPrefix and manual slicing, use the strings.TrimPrefix function. If the string doesn't start with the prefix, the original string will be returned. Using strings.TrimPrefix reduces complexity, and avoids common bugs, such as off-by-one mistakes.\n\nBefore:\n\n\tif strings.HasPrefix(str, prefix) {\n\t    str = str[len(prefix):]\n\t}\n\nAfter:\n\n\tstr = strings.TrimPrefix(str, prefix)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1017](https://staticcheck.dev/docs/checks/#S1017)\n\n<a id='S1018'></a>\n## `S1018`: Use 'copy' for sliding elements\n\ncopy() permits using the same source and destination slice, even with overlapping ranges. This makes it ideal for sliding elements in a slice.\n\nBefore:\n\n\tfor i := 0; i < n; i++ {\n\t    bs[i] = bs[offset+i]\n\t}\n\nAfter:\n\n\tcopy(bs[:n], bs[offset:])\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1018](https://staticcheck.dev/docs/checks/#S1018)\n\n<a id='S1019'></a>\n## `S1019`: Simplify 'make' call by omitting redundant arguments\n\nThe 'make' function has default values for the length and capacity arguments. For channels, the length defaults to zero, and for slices, the capacity defaults to the length.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1019](https://staticcheck.dev/docs/checks/#S1019)\n\n<a id='S1020'></a>\n## `S1020`: Omit redundant nil check in type assertion\n\nBefore:\n\n\tif _, ok := i.(T); ok && i != nil {}\n\nAfter:\n\n\tif _, ok := i.(T); ok {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1020](https://staticcheck.dev/docs/checks/#S1020)\n\n<a id='S1021'></a>\n## `S1021`: Merge variable declaration and assignment\n\nBefore:\n\n\tvar x uint\n\tx = 1\n\nAfter:\n\n\tvar x uint = 1\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1021\": true}`.\n\nPackage documentation: [S1021](https://staticcheck.dev/docs/checks/#S1021)\n\n<a id='S1023'></a>\n## `S1023`: Omit redundant control flow\n\nFunctions that have no return value do not need a return statement as the final statement of the function.\n\nSwitches in Go do not have automatic fallthrough, unlike languages like C. It is not necessary to have a break statement as the final statement in a case block.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1023](https://staticcheck.dev/docs/checks/#S1023)\n\n<a id='S1024'></a>\n## `S1024`: Replace x.Sub(time.Now()) with time.Until(x)\n\nThe time.Until helper has the same effect as using x.Sub(time.Now()) but is easier to read.\n\nBefore:\n\n\tx.Sub(time.Now())\n\nAfter:\n\n\ttime.Until(x)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1024](https://staticcheck.dev/docs/checks/#S1024)\n\n<a id='S1025'></a>\n## `S1025`: Don't use fmt.Sprintf(\"%s\", x) unnecessarily\n\nIn many instances, there are easier and more efficient ways of getting a value's string representation. Whenever a value's underlying type is a string already, or the type has a String method, they should be used directly.\n\nGiven the following shared definitions\n\n\ttype T1 string\n\ttype T2 int\n\n\tfunc (T2) String() string { return \"Hello, world\" }\n\n\tvar x string\n\tvar y T1\n\tvar z T2\n\nwe can simplify\n\n\tfmt.Sprintf(\"%s\", x)\n\tfmt.Sprintf(\"%s\", y)\n\tfmt.Sprintf(\"%s\", z)\n\nto\n\n\tx\n\tstring(y)\n\tz.String()\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1025\": true}`.\n\nPackage documentation: [S1025](https://staticcheck.dev/docs/checks/#S1025)\n\n<a id='S1028'></a>\n## `S1028`: Simplify error construction with fmt.Errorf\n\nBefore:\n\n\terrors.New(fmt.Sprintf(...))\n\nAfter:\n\n\tfmt.Errorf(...)\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1028](https://staticcheck.dev/docs/checks/#S1028)\n\n<a id='S1029'></a>\n## `S1029`: Range over the string directly\n\nRanging over a string will yield byte offsets and runes. If the offset isn't used, this is functionally equivalent to converting the string to a slice of runes and ranging over that. Ranging directly over the string will be more performant, however, as it avoids allocating a new slice, the size of which depends on the length of the string.\n\nBefore:\n\n\tfor _, r := range []rune(s) {}\n\nAfter:\n\n\tfor _, r := range s {}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"S1029\": true}`.\n\nPackage documentation: [S1029](https://staticcheck.dev/docs/checks/#S1029)\n\n<a id='S1030'></a>\n## `S1030`: Use bytes.Buffer.String or bytes.Buffer.Bytes\n\nbytes.Buffer has both a String and a Bytes method. It is almost never necessary to use string(buf.Bytes()) or \\[]byte(buf.String()) – simply use the other method.\n\nThe only exception to this are map lookups. Due to a compiler optimization, m\\[string(buf.Bytes())] is more efficient than m\\[buf.String()].\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1030](https://staticcheck.dev/docs/checks/#S1030)\n\n<a id='S1031'></a>\n## `S1031`: Omit redundant nil check around loop\n\nYou can use range on nil slices and maps, the loop will simply never execute. This makes an additional nil check around the loop unnecessary.\n\nBefore:\n\n\tif s != nil {\n\t    for _, x := range s {\n\t        ...\n\t    }\n\t}\n\nAfter:\n\n\tfor _, x := range s {\n\t    ...\n\t}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [S1031](https://staticcheck.dev/docs/checks/#S1031)\n\n<a id='S1032'></a>\n## `S1032`: Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)\n\nThe sort.Ints, sort.Float64s and sort.Strings functions are easier to read than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x)) and sort.Sort(sort.StringSlice(x)).\n\nBefore:\n\n\tsort.Sort(sort.StringSlice(x))\n\nAfter:\n\n\tsort.Strings(x)\n\nAvailable since\n\n\t2019.1\n\n\nDefault: on.\n\nPackage documentation: [S1032](https://staticcheck.dev/docs/checks/#S1032)\n\n<a id='S1033'></a>\n## `S1033`: Unnecessary guard around call to 'delete'\n\nCalling delete on a nil map is a no-op.\n\nAvailable since\n\n\t2019.2\n\n\nDefault: on.\n\nPackage documentation: [S1033](https://staticcheck.dev/docs/checks/#S1033)\n\n<a id='S1034'></a>\n## `S1034`: Use result of type assertion to simplify cases\n\nAvailable since\n\n\t2019.2\n\n\nDefault: on.\n\nPackage documentation: [S1034](https://staticcheck.dev/docs/checks/#S1034)\n\n<a id='S1035'></a>\n## `S1035`: Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header\n\nThe methods on net/http.Header, namely Add, Del, Get and Set, already canonicalize the given header name.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [S1035](https://staticcheck.dev/docs/checks/#S1035)\n\n<a id='S1036'></a>\n## `S1036`: Unnecessary guard around map access\n\nWhen accessing a map key that doesn't exist yet, one receives a zero value. Often, the zero value is a suitable value, for example when using append or doing integer math.\n\nThe following\n\n\tif _, ok := m[\"foo\"]; ok {\n\t    m[\"foo\"] = append(m[\"foo\"], \"bar\")\n\t} else {\n\t    m[\"foo\"] = []string{\"bar\"}\n\t}\n\ncan be simplified to\n\n\tm[\"foo\"] = append(m[\"foo\"], \"bar\")\n\nand\n\n\tif _, ok := m2[\"k\"]; ok {\n\t    m2[\"k\"] += 4\n\t} else {\n\t    m2[\"k\"] = 4\n\t}\n\ncan be simplified to\n\n\tm[\"k\"] += 4\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [S1036](https://staticcheck.dev/docs/checks/#S1036)\n\n<a id='S1037'></a>\n## `S1037`: Elaborate way of sleeping\n\nUsing a select statement with a single case receiving from the result of time.After is a very elaborate way of sleeping that can much simpler be expressed with a simple call to time.Sleep.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [S1037](https://staticcheck.dev/docs/checks/#S1037)\n\n<a id='S1038'></a>\n## `S1038`: Unnecessarily complex way of printing formatted string\n\nInstead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [S1038](https://staticcheck.dev/docs/checks/#S1038)\n\n<a id='S1039'></a>\n## `S1039`: Unnecessary use of fmt.Sprint\n\nCalling fmt.Sprint with a single string argument is unnecessary and identical to using the string directly.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [S1039](https://staticcheck.dev/docs/checks/#S1039)\n\n<a id='S1040'></a>\n## `S1040`: Type assertion to current type\n\nThe type assertion x.(SomeInterface), when x already has type SomeInterface, can only fail if x is nil. Usually, this is left-over code from when x had a different type and you can safely delete the type assertion. If you want to check that x is not nil, consider being explicit and using an actual if x == nil comparison instead of relying on the type assertion panicking.\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [S1040](https://staticcheck.dev/docs/checks/#S1040)\n\n<a id='SA1000'></a>\n## `SA1000`: Invalid regular expression\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1000\": true}`.\n\nPackage documentation: [SA1000](https://staticcheck.dev/docs/checks/#SA1000)\n\n<a id='SA1001'></a>\n## `SA1001`: Invalid template\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1001](https://staticcheck.dev/docs/checks/#SA1001)\n\n<a id='SA1002'></a>\n## `SA1002`: Invalid format in time.Parse\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1002\": true}`.\n\nPackage documentation: [SA1002](https://staticcheck.dev/docs/checks/#SA1002)\n\n<a id='SA1003'></a>\n## `SA1003`: Unsupported argument to functions in encoding/binary\n\nThe encoding/binary package can only serialize types with known sizes. This precludes the use of the int and uint types, as their sizes differ on different architectures. Furthermore, it doesn't support serializing maps, channels, strings, or functions.\n\nBefore Go 1.8, bool wasn't supported, either.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1003\": true}`.\n\nPackage documentation: [SA1003](https://staticcheck.dev/docs/checks/#SA1003)\n\n<a id='SA1004'></a>\n## `SA1004`: Suspiciously small untyped constant in time.Sleep\n\nThe time.Sleep function takes a time.Duration as its only argument. Durations are expressed in nanoseconds. Thus, calling time.Sleep(1) will sleep for 1 nanosecond. This is a common source of bugs, as sleep functions in other languages often accept seconds or milliseconds.\n\nThe time package provides constants such as time.Second to express large durations. These can be combined with arithmetic to express arbitrary durations, for example 5 \\* time.Second for 5 seconds.\n\nIf you truly meant to sleep for a tiny amount of time, use n \\* time.Nanosecond to signal to Staticcheck that you did mean to sleep for some amount of nanoseconds.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1004](https://staticcheck.dev/docs/checks/#SA1004)\n\n<a id='SA1005'></a>\n## `SA1005`: Invalid first argument to exec.Command\n\nos/exec runs programs directly (using variants of the fork and exec system calls on Unix systems). This shouldn't be confused with running a command in a shell. The shell will allow for features such as input redirection, pipes, and general scripting. The shell is also responsible for splitting the user's input into a program name and its arguments. For example, the equivalent to\n\n\tls / /tmp\n\nwould be\n\n\texec.Command(\"ls\", \"/\", \"/tmp\")\n\nIf you want to run a command in a shell, consider using something like the following – but be aware that not all systems, particularly Windows, will have a /bin/sh program:\n\n\texec.Command(\"/bin/sh\", \"-c\", \"ls | grep Awesome\")\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1005](https://staticcheck.dev/docs/checks/#SA1005)\n\n<a id='SA1007'></a>\n## `SA1007`: Invalid URL in net/url.Parse\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1007\": true}`.\n\nPackage documentation: [SA1007](https://staticcheck.dev/docs/checks/#SA1007)\n\n<a id='SA1008'></a>\n## `SA1008`: Non-canonical key in http.Header map\n\nKeys in http.Header maps are canonical, meaning they follow a specific combination of uppercase and lowercase letters. Methods such as http.Header.Add and http.Header.Del convert inputs into this canonical form before manipulating the map.\n\nWhen manipulating http.Header maps directly, as opposed to using the provided methods, care should be taken to stick to canonical form in order to avoid inconsistencies. The following piece of code demonstrates one such inconsistency:\n\n\th := http.Header{}\n\th[\"etag\"] = []string{\"1234\"}\n\th.Add(\"etag\", \"5678\")\n\tfmt.Println(h)\n\n\t// Output:\n\t// map[Etag:[5678] etag:[1234]]\n\nThe easiest way of obtaining the canonical form of a key is to use http.CanonicalHeaderKey.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1008](https://staticcheck.dev/docs/checks/#SA1008)\n\n<a id='SA1010'></a>\n## `SA1010`: (*regexp.Regexp).FindAll called with n == 0, which will always return zero results\n\nIf n >= 0, the function returns at most n matches/submatches. To return all results, specify a negative number.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1010\": true}`.\n\nPackage documentation: [SA1010](https://staticcheck.dev/docs/checks/#SA1010)\n\n<a id='SA1011'></a>\n## `SA1011`: Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1011\": true}`.\n\nPackage documentation: [SA1011](https://staticcheck.dev/docs/checks/#SA1011)\n\n<a id='SA1012'></a>\n## `SA1012`: A nil context.Context is being passed to a function, consider using context.TODO instead\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1012](https://staticcheck.dev/docs/checks/#SA1012)\n\n<a id='SA1013'></a>\n## `SA1013`: io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1013](https://staticcheck.dev/docs/checks/#SA1013)\n\n<a id='SA1014'></a>\n## `SA1014`: Non-pointer value passed to Unmarshal or Decode\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1014\": true}`.\n\nPackage documentation: [SA1014](https://staticcheck.dev/docs/checks/#SA1014)\n\n<a id='SA1015'></a>\n## `SA1015`: Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions\n\nBefore Go 1.23, time.Tickers had to be closed to be able to be garbage collected. Since time.Tick doesn't make it possible to close the underlying ticker, using it repeatedly would leak memory.\n\nGo 1.23 fixes this by allowing tickers to be collected even if they weren't closed.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1015\": true}`.\n\nPackage documentation: [SA1015](https://staticcheck.dev/docs/checks/#SA1015)\n\n<a id='SA1016'></a>\n## `SA1016`: Trapping a signal that cannot be trapped\n\nNot all signals can be intercepted by a process. Specifically, on UNIX-like systems, the syscall.SIGKILL and syscall.SIGSTOP signals are never passed to the process, but instead handled directly by the kernel. It is therefore pointless to try and handle these signals.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA1016](https://staticcheck.dev/docs/checks/#SA1016)\n\n<a id='SA1017'></a>\n## `SA1017`: Channels used with os/signal.Notify should be buffered\n\nThe os/signal package uses non-blocking channel sends when delivering signals. If the receiving end of the channel isn't ready and the channel is either unbuffered or full, the signal will be dropped. To avoid missing signals, the channel should be buffered and of the appropriate size. For a channel used for notification of just one signal value, a buffer of size 1 is sufficient.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1017\": true}`.\n\nPackage documentation: [SA1017](https://staticcheck.dev/docs/checks/#SA1017)\n\n<a id='SA1018'></a>\n## `SA1018`: strings.Replace called with n == 0, which does nothing\n\nWith n == 0, zero instances will be replaced. To replace all instances, use a negative number, or use strings.ReplaceAll.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1018\": true}`.\n\nPackage documentation: [SA1018](https://staticcheck.dev/docs/checks/#SA1018)\n\n<a id='SA1020'></a>\n## `SA1020`: Using an invalid host:port pair with a net.Listen-related function\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1020\": true}`.\n\nPackage documentation: [SA1020](https://staticcheck.dev/docs/checks/#SA1020)\n\n<a id='SA1021'></a>\n## `SA1021`: Using bytes.Equal to compare two net.IP\n\nA net.IP stores an IPv4 or IPv6 address as a slice of bytes. The length of the slice for an IPv4 address, however, can be either 4 or 16 bytes long, using different ways of representing IPv4 addresses. In order to correctly compare two net.IPs, the net.IP.Equal method should be used, as it takes both representations into account.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1021\": true}`.\n\nPackage documentation: [SA1021](https://staticcheck.dev/docs/checks/#SA1021)\n\n<a id='SA1023'></a>\n## `SA1023`: Modifying the buffer in an io.Writer implementation\n\nWrite must not modify the slice data, even temporarily.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1023\": true}`.\n\nPackage documentation: [SA1023](https://staticcheck.dev/docs/checks/#SA1023)\n\n<a id='SA1024'></a>\n## `SA1024`: A string cutset contains duplicate characters\n\nThe strings.TrimLeft and strings.TrimRight functions take cutsets, not prefixes. A cutset is treated as a set of characters to remove from a string. For example,\n\n\tstrings.TrimLeft(\"42133word\", \"1234\")\n\nwill result in the string \"word\" – any characters that are 1, 2, 3 or 4 are cut from the left of the string.\n\nIn order to remove one string from another, use strings.TrimPrefix instead.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1024\": true}`.\n\nPackage documentation: [SA1024](https://staticcheck.dev/docs/checks/#SA1024)\n\n<a id='SA1025'></a>\n## `SA1025`: It is not possible to use (*time.Timer).Reset's return value correctly\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1025\": true}`.\n\nPackage documentation: [SA1025](https://staticcheck.dev/docs/checks/#SA1025)\n\n<a id='SA1026'></a>\n## `SA1026`: Cannot marshal channels or functions\n\nAvailable since\n\n\t2019.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1026\": true}`.\n\nPackage documentation: [SA1026](https://staticcheck.dev/docs/checks/#SA1026)\n\n<a id='SA1027'></a>\n## `SA1027`: Atomic access to 64-bit variable must be 64-bit aligned\n\nOn ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to arrange for 64-bit alignment of 64-bit words accessed atomically. The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned.\n\nYou can use the structlayout tool to inspect the alignment of fields in a struct.\n\nAvailable since\n\n\t2019.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1027\": true}`.\n\nPackage documentation: [SA1027](https://staticcheck.dev/docs/checks/#SA1027)\n\n<a id='SA1028'></a>\n## `SA1028`: sort.Slice can only be used on slices\n\nThe first argument of sort.Slice must be a slice.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1028\": true}`.\n\nPackage documentation: [SA1028](https://staticcheck.dev/docs/checks/#SA1028)\n\n<a id='SA1029'></a>\n## `SA1029`: Inappropriate key in call to context.WithValue\n\nThe provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys.\n\nTo avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1029\": true}`.\n\nPackage documentation: [SA1029](https://staticcheck.dev/docs/checks/#SA1029)\n\n<a id='SA1030'></a>\n## `SA1030`: Invalid argument in call to a strconv function\n\nThis check validates the format, number base and bit size arguments of the various parsing and formatting functions in strconv.\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1030\": true}`.\n\nPackage documentation: [SA1030](https://staticcheck.dev/docs/checks/#SA1030)\n\n<a id='SA1031'></a>\n## `SA1031`: Overlapping byte slices passed to an encoder\n\nIn an encoding function of the form Encode(dst, src), dst and src were found to reference the same memory. This can result in src bytes being overwritten before they are read, when the encoder writes more than one byte per src byte.\n\nAvailable since\n\n\t2024.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1031\": true}`.\n\nPackage documentation: [SA1031](https://staticcheck.dev/docs/checks/#SA1031)\n\n<a id='SA1032'></a>\n## `SA1032`: Wrong order of arguments to errors.Is\n\nThe first argument of the function errors.Is is the error that we have and the second argument is the error we're trying to match against. For example:\n\n\tif errors.Is(err, io.EOF) { ... }\n\nThis check detects some cases where the two arguments have been swapped. It flags any calls where the first argument is referring to a package-level error variable, such as\n\n\tif errors.Is(io.EOF, err) { /* this is wrong */ }\n\nAvailable since\n\n\t2024.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA1032\": true}`.\n\nPackage documentation: [SA1032](https://staticcheck.dev/docs/checks/#SA1032)\n\n<a id='SA2001'></a>\n## `SA2001`: Empty critical section, did you mean to defer the unlock?\n\nEmpty critical sections of the kind\n\n\tmu.Lock()\n\tmu.Unlock()\n\nare very often a typo, and the following was intended instead:\n\n\tmu.Lock()\n\tdefer mu.Unlock()\n\nDo note that sometimes empty critical sections can be useful, as a form of signaling to wait on another goroutine. Many times, there are simpler ways of achieving the same effect. When that isn't the case, the code should be amply commented to avoid confusion. Combining such comments with a //lint:ignore directive can be used to suppress this rare false positive.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA2001](https://staticcheck.dev/docs/checks/#SA2001)\n\n<a id='SA2002'></a>\n## `SA2002`: Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA2002\": true}`.\n\nPackage documentation: [SA2002](https://staticcheck.dev/docs/checks/#SA2002)\n\n<a id='SA2003'></a>\n## `SA2003`: Deferred Lock right after locking, likely meant to defer Unlock instead\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA2003\": true}`.\n\nPackage documentation: [SA2003](https://staticcheck.dev/docs/checks/#SA2003)\n\n<a id='SA3000'></a>\n## `SA3000`: TestMain doesn't call os.Exit, hiding test failures\n\nTest executables (and in turn 'go test') exit with a non-zero status code if any tests failed. When specifying your own TestMain function, it is your responsibility to arrange for this, by calling os.Exit with the correct code. The correct code is returned by (\\*testing.M).Run, so the usual way of implementing TestMain is to end it with os.Exit(m.Run()).\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA3000](https://staticcheck.dev/docs/checks/#SA3000)\n\n<a id='SA3001'></a>\n## `SA3001`: Assigning to b.N in benchmarks distorts the results\n\nThe testing package dynamically sets b.N to improve the reliability of benchmarks and uses it in computations to determine the duration of a single operation. Benchmark code must not alter b.N as this would falsify results.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA3001](https://staticcheck.dev/docs/checks/#SA3001)\n\n<a id='SA4000'></a>\n## `SA4000`: Binary operator has identical expressions on both sides\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4000](https://staticcheck.dev/docs/checks/#SA4000)\n\n<a id='SA4001'></a>\n## `SA4001`: &*x gets simplified to x, it does not copy x\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4001](https://staticcheck.dev/docs/checks/#SA4001)\n\n<a id='SA4003'></a>\n## `SA4003`: Comparing unsigned values against negative values is pointless\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4003](https://staticcheck.dev/docs/checks/#SA4003)\n\n<a id='SA4004'></a>\n## `SA4004`: The loop exits unconditionally after one iteration\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4004](https://staticcheck.dev/docs/checks/#SA4004)\n\n<a id='SA4005'></a>\n## `SA4005`: Field assignment that will never be observed. Did you mean to use a pointer receiver?\n\nAvailable since\n\n\t2021.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4005\": true}`.\n\nPackage documentation: [SA4005](https://staticcheck.dev/docs/checks/#SA4005)\n\n<a id='SA4006'></a>\n## `SA4006`: A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4006\": true}`.\n\nPackage documentation: [SA4006](https://staticcheck.dev/docs/checks/#SA4006)\n\n<a id='SA4008'></a>\n## `SA4008`: The variable in the loop condition never changes, are you incrementing the wrong variable?\n\nFor example:\n\n\tfor i := 0; i < 10; j++ { ... }\n\nThis may also occur when a loop can only execute once because of unconditional control flow that terminates the loop. For example, when a loop body contains an unconditional break, return, or panic:\n\n\tfunc f() {\n\t\tpanic(\"oops\")\n\t}\n\tfunc g() {\n\t\tfor i := 0; i < 10; i++ {\n\t\t\t// f unconditionally calls panic, which means \"i\" is\n\t\t\t// never incremented.\n\t\t\tf()\n\t\t}\n\t}\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4008\": true}`.\n\nPackage documentation: [SA4008](https://staticcheck.dev/docs/checks/#SA4008)\n\n<a id='SA4009'></a>\n## `SA4009`: A function argument is overwritten before its first use\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4009\": true}`.\n\nPackage documentation: [SA4009](https://staticcheck.dev/docs/checks/#SA4009)\n\n<a id='SA4010'></a>\n## `SA4010`: The result of append will never be observed anywhere\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4010\": true}`.\n\nPackage documentation: [SA4010](https://staticcheck.dev/docs/checks/#SA4010)\n\n<a id='SA4011'></a>\n## `SA4011`: Break statement with no effect. Did you mean to break out of an outer loop?\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4011](https://staticcheck.dev/docs/checks/#SA4011)\n\n<a id='SA4012'></a>\n## `SA4012`: Comparing a value against NaN even though no value is equal to NaN\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4012\": true}`.\n\nPackage documentation: [SA4012](https://staticcheck.dev/docs/checks/#SA4012)\n\n<a id='SA4013'></a>\n## `SA4013`: Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4013](https://staticcheck.dev/docs/checks/#SA4013)\n\n<a id='SA4014'></a>\n## `SA4014`: An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4014](https://staticcheck.dev/docs/checks/#SA4014)\n\n<a id='SA4015'></a>\n## `SA4015`: Calling functions like math.Ceil on floats converted from integers doesn't do anything useful\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4015\": true}`.\n\nPackage documentation: [SA4015](https://staticcheck.dev/docs/checks/#SA4015)\n\n<a id='SA4016'></a>\n## `SA4016`: Certain bitwise operations, such as x ^ 0, do not do anything useful\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4016](https://staticcheck.dev/docs/checks/#SA4016)\n\n<a id='SA4017'></a>\n## `SA4017`: Discarding the return values of a function without side effects, making the call pointless\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4017\": true}`.\n\nPackage documentation: [SA4017](https://staticcheck.dev/docs/checks/#SA4017)\n\n<a id='SA4018'></a>\n## `SA4018`: Self-assignment of variables\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4018\": true}`.\n\nPackage documentation: [SA4018](https://staticcheck.dev/docs/checks/#SA4018)\n\n<a id='SA4019'></a>\n## `SA4019`: Multiple, identical build constraints in the same file\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA4019](https://staticcheck.dev/docs/checks/#SA4019)\n\n<a id='SA4020'></a>\n## `SA4020`: Unreachable case clause in a type switch\n\nIn a type switch like the following\n\n\ttype T struct{}\n\tfunc (T) Read(b []byte) (int, error) { return 0, nil }\n\n\tvar v any = T{}\n\n\tswitch v.(type) {\n\tcase io.Reader:\n\t    // ...\n\tcase T:\n\t    // unreachable\n\t}\n\nthe second case clause can never be reached because T implements io.Reader and case clauses are evaluated in source order.\n\nAnother example:\n\n\ttype T struct{}\n\tfunc (T) Read(b []byte) (int, error) { return 0, nil }\n\tfunc (T) Close() error { return nil }\n\n\tvar v any = T{}\n\n\tswitch v.(type) {\n\tcase io.Reader:\n\t    // ...\n\tcase io.ReadCloser:\n\t    // unreachable\n\t}\n\nEven though T has a Close method and thus implements io.ReadCloser, io.Reader will always match first. The method set of io.Reader is a subset of io.ReadCloser. Thus it is impossible to match the second case without matching the first case.\n\n### Structurally equivalent interfaces {#hdr-Structurally_equivalent_interfaces}\n\nA special case of the previous example are structurally identical interfaces. Given these declarations\n\n\ttype T error\n\ttype V error\n\n\tfunc doSomething() error {\n\t    err, ok := doAnotherThing()\n\t    if ok {\n\t        return T(err)\n\t    }\n\n\t    return U(err)\n\t}\n\nthe following type switch will have an unreachable case clause:\n\n\tswitch doSomething().(type) {\n\tcase T:\n\t    // ...\n\tcase V:\n\t    // unreachable\n\t}\n\nT will always match before V because they are structurally equivalent and therefore doSomething()'s return value implements both.\n\nAvailable since\n\n\t2019.2\n\n\nDefault: on.\n\nPackage documentation: [SA4020](https://staticcheck.dev/docs/checks/#SA4020)\n\n<a id='SA4022'></a>\n## `SA4022`: Comparing the address of a variable against nil\n\nCode such as 'if &x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: on.\n\nPackage documentation: [SA4022](https://staticcheck.dev/docs/checks/#SA4022)\n\n<a id='SA4023'></a>\n## `SA4023`: Impossible comparison of interface value with untyped nil\n\nUnder the covers, interfaces are implemented as two elements, a type T and a value V. V is a concrete value such as an int, struct or pointer, never an interface itself, and has type T. For instance, if we store the int value 3 in an interface, the resulting interface value has, schematically, (T=int, V=3). The value V is also known as the interface's dynamic value, since a given interface variable might hold different values V (and corresponding types T) during the execution of the program.\n\nAn interface value is nil only if the V and T are both unset, (T=nil, V is not set), In particular, a nil interface will always hold a nil type. If we store a nil pointer of type \\*int inside an interface value, the inner type will be \\*int regardless of the value of the pointer: (T=\\*int, V=nil). Such an interface value will therefore be non-nil even when the pointer value V inside is nil.\n\nThis situation can be confusing, and arises when a nil value is stored inside an interface value such as an error return:\n\n\tfunc returnsError() error {\n\t    var p *MyError = nil\n\t    if bad() {\n\t        p = ErrBad\n\t    }\n\t    return p // Will always return a non-nil error.\n\t}\n\nIf all goes well, the function returns a nil p, so the return value is an error interface value holding (T=\\*MyError, V=nil). This means that if the caller compares the returned error to nil, it will always look as if there was an error even if nothing bad happened. To return a proper nil error to the caller, the function must return an explicit nil:\n\n\tfunc returnsError() error {\n\t    if bad() {\n\t        return ErrBad\n\t    }\n\t    return nil\n\t}\n\nIt's a good idea for functions that return errors always to use the error type in their signature (as we did above) rather than a concrete type such as \\*MyError, to help guarantee the error is created correctly. As an example, os.Open returns an error even though, if not nil, it's always of concrete type \\*os.PathError.\n\nSimilar situations to those described here can arise whenever interfaces are used. Just keep in mind that if any concrete value has been stored in the interface, the interface will not be nil. For more information, see The Laws of Reflection at [https://golang.org/doc/articles/laws\\_of\\_reflection.html](https://golang.org/doc/articles/laws_of_reflection.html).\n\nThis text has been copied from [https://golang.org/doc/faq#nil\\_error](https://golang.org/doc/faq#nil_error), licensed under the Creative Commons Attribution 3.0 License.\n\nAvailable since\n\n\t2020.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4023\": true}`.\n\nPackage documentation: [SA4023](https://staticcheck.dev/docs/checks/#SA4023)\n\n<a id='SA4024'></a>\n## `SA4024`: Checking for impossible return value from a builtin function\n\nReturn values of the len and cap builtins cannot be negative.\n\nSee [https://golang.org/pkg/builtin/#len](https://golang.org/pkg/builtin/#len) and [https://golang.org/pkg/builtin/#cap](https://golang.org/pkg/builtin/#cap).\n\nExample:\n\n\tif len(slice) < 0 {\n\t    fmt.Println(\"unreachable code\")\n\t}\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [SA4024](https://staticcheck.dev/docs/checks/#SA4024)\n\n<a id='SA4025'></a>\n## `SA4025`: Integer division of literals that results in zero\n\nWhen dividing two integer constants, the result will also be an integer. Thus, a division such as 2 / 3 results in 0. This is true for all of the following examples:\n\n\t_ = 2 / 3\n\tconst _ = 2 / 3\n\tconst _ float64 = 2 / 3\n\t_ = float64(2 / 3)\n\nStaticcheck will flag such divisions if both sides of the division are integer literals, as it is highly unlikely that the division was intended to truncate to zero. Staticcheck will not flag integer division involving named constants, to avoid noisy positives.\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [SA4025](https://staticcheck.dev/docs/checks/#SA4025)\n\n<a id='SA4026'></a>\n## `SA4026`: Go constants cannot express negative zero\n\nIn IEEE 754 floating point math, zero has a sign and can be positive or negative. This can be useful in certain numerical code.\n\nGo constants, however, cannot express negative zero. This means that the literals -0.0 and 0.0 have the same ideal value (zero) and will both represent positive zero at runtime.\n\nTo explicitly and reliably create a negative zero, you can use the math.Copysign function: math.Copysign(0, -1).\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [SA4026](https://staticcheck.dev/docs/checks/#SA4026)\n\n<a id='SA4027'></a>\n## `SA4027`: (*net/url.URL).Query returns a copy, modifying it doesn't change the URL\n\n(\\*net/url.URL).Query parses the current value of net/url.URL.RawQuery and returns it as a map of type net/url.Values. Subsequent changes to this map will not affect the URL unless the map gets encoded and assigned to the URL's RawQuery.\n\nAs a consequence, the following code pattern is an expensive no-op: u.Query().Add(key, value).\n\nAvailable since\n\n\t2021.1\n\n\nDefault: on.\n\nPackage documentation: [SA4027](https://staticcheck.dev/docs/checks/#SA4027)\n\n<a id='SA4028'></a>\n## `SA4028`: x % 1 is always zero\n\nAvailable since\n\n\t2022.1\n\n\nDefault: on.\n\nPackage documentation: [SA4028](https://staticcheck.dev/docs/checks/#SA4028)\n\n<a id='SA4029'></a>\n## `SA4029`: Ineffective attempt at sorting slice\n\nsort.Float64Slice, sort.IntSlice, and sort.StringSlice are types, not functions. Doing x = sort.StringSlice(x) does nothing, especially not sort any values. The correct usage is sort.Sort(sort.StringSlice(x)) or sort.StringSlice(x).Sort(), but there are more convenient helpers, namely sort.Float64s, sort.Ints, and sort.Strings.\n\nAvailable since\n\n\t2022.1\n\n\nDefault: on.\n\nPackage documentation: [SA4029](https://staticcheck.dev/docs/checks/#SA4029)\n\n<a id='SA4030'></a>\n## `SA4030`: Ineffective attempt at generating random number\n\nFunctions in the math/rand package that accept upper limits, such as Intn, generate random numbers in the half-open interval \\[0,n). In other words, the generated numbers will be >= 0 and \\< n – they don't include n. rand.Intn(1) therefore doesn't generate 0 or 1, it always generates 0.\n\nAvailable since\n\n\t2022.1\n\n\nDefault: on.\n\nPackage documentation: [SA4030](https://staticcheck.dev/docs/checks/#SA4030)\n\n<a id='SA4031'></a>\n## `SA4031`: Checking never-nil value against nil\n\nAvailable since\n\n\t2022.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA4031\": true}`.\n\nPackage documentation: [SA4031](https://staticcheck.dev/docs/checks/#SA4031)\n\n<a id='SA4032'></a>\n## `SA4032`: Comparing runtime.GOOS or runtime.GOARCH against impossible value\n\nAvailable since\n\n\t2024.1\n\n\nDefault: on.\n\nPackage documentation: [SA4032](https://staticcheck.dev/docs/checks/#SA4032)\n\n<a id='SA5000'></a>\n## `SA5000`: Assignment to nil map\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5000\": true}`.\n\nPackage documentation: [SA5000](https://staticcheck.dev/docs/checks/#SA5000)\n\n<a id='SA5001'></a>\n## `SA5001`: Deferring Close before checking for a possible error\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA5001](https://staticcheck.dev/docs/checks/#SA5001)\n\n<a id='SA5002'></a>\n## `SA5002`: The empty for loop ('for {}') spins and can block the scheduler\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5002\": true}`.\n\nPackage documentation: [SA5002](https://staticcheck.dev/docs/checks/#SA5002)\n\n<a id='SA5003'></a>\n## `SA5003`: Defers in infinite loops will never execute\n\nDefers are scoped to the surrounding function, not the surrounding block. In a function that never returns, i.e. one containing an infinite loop, defers will never execute.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA5003](https://staticcheck.dev/docs/checks/#SA5003)\n\n<a id='SA5004'></a>\n## `SA5004`: 'for { select { ...' with an empty default branch spins\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA5004](https://staticcheck.dev/docs/checks/#SA5004)\n\n<a id='SA5005'></a>\n## `SA5005`: The finalizer references the finalized object, preventing garbage collection\n\nA finalizer is a function associated with an object that runs when the garbage collector is ready to collect said object, that is when the object is no longer referenced by anything.\n\nIf the finalizer references the object, however, it will always remain as the final reference to that object, preventing the garbage collector from collecting the object. The finalizer will never run, and the object will never be collected, leading to a memory leak. That is why the finalizer should instead use its first argument to operate on the object. That way, the number of references can temporarily go to zero before the object is being passed to the finalizer.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5005\": true}`.\n\nPackage documentation: [SA5005](https://staticcheck.dev/docs/checks/#SA5005)\n\n<a id='SA5007'></a>\n## `SA5007`: Infinite recursive call\n\nA function that calls itself recursively needs to have an exit condition. Otherwise it will recurse forever, until the system runs out of memory.\n\nThis issue can be caused by simple bugs such as forgetting to add an exit condition. It can also happen \"on purpose\". Some languages have tail call optimization which makes certain infinite recursive calls safe to use. Go, however, does not implement TCO, and as such a loop should be used instead.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5007\": true}`.\n\nPackage documentation: [SA5007](https://staticcheck.dev/docs/checks/#SA5007)\n\n<a id='SA5008'></a>\n## `SA5008`: Invalid struct tag\n\nAvailable since\n\n\t2019.2\n\n\nDefault: on.\n\nPackage documentation: [SA5008](https://staticcheck.dev/docs/checks/#SA5008)\n\n<a id='SA5010'></a>\n## `SA5010`: Impossible type assertion\n\nSome type assertions can be statically proven to be impossible. This is the case when the method sets of both arguments of the type assertion conflict with each other, for example by containing the same method with different signatures.\n\nThe Go compiler already applies this check when asserting from an interface value to a concrete type. If the concrete type misses methods from the interface, or if function signatures don't match, then the type assertion can never succeed.\n\nThis check applies the same logic when asserting from one interface to another. If both interface types contain the same method but with different signatures, then the type assertion can never succeed, either.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5010\": true}`.\n\nPackage documentation: [SA5010](https://staticcheck.dev/docs/checks/#SA5010)\n\n<a id='SA5011'></a>\n## `SA5011`: Possible nil pointer dereference\n\nA pointer is being dereferenced unconditionally, while also being checked against nil in another place. This suggests that the pointer may be nil and dereferencing it may panic. This is commonly a result of improperly ordered code or missing return statements. Consider the following examples:\n\n\tfunc fn(x *int) {\n\t    fmt.Println(*x)\n\n\t    // This nil check is equally important for the previous dereference\n\t    if x != nil {\n\t        foo(*x)\n\t    }\n\t}\n\n\tfunc TestFoo(t *testing.T) {\n\t    x := compute()\n\t    if x == nil {\n\t        t.Errorf(\"nil pointer received\")\n\t    }\n\n\t    // t.Errorf does not abort the test, so if x is nil, the next line will panic.\n\t    foo(*x)\n\t}\n\nStaticcheck tries to deduce which functions abort control flow. For example, it is aware that a function will not continue execution after a call to panic or log.Fatal. However, sometimes this detection fails, in particular in the presence of conditionals. Consider the following example:\n\n\tfunc Log(msg string, level int) {\n\t    fmt.Println(msg)\n\t    if level == levelFatal {\n\t        os.Exit(1)\n\t    }\n\t}\n\n\tfunc Fatal(msg string) {\n\t    Log(msg, levelFatal)\n\t}\n\n\tfunc fn(x *int) {\n\t    if x == nil {\n\t        Fatal(\"unexpected nil pointer\")\n\t    }\n\t    fmt.Println(*x)\n\t}\n\nStaticcheck will flag the dereference of x, even though it is perfectly safe. Staticcheck is not able to deduce that a call to Fatal will exit the program. For the time being, the easiest workaround is to modify the definition of Fatal like so:\n\n\tfunc Fatal(msg string) {\n\t    Log(msg, levelFatal)\n\t    panic(\"unreachable\")\n\t}\n\nWe also hard-code functions from common logging packages such as logrus. Please file an issue if we're missing support for a popular package.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5011\": true}`.\n\nPackage documentation: [SA5011](https://staticcheck.dev/docs/checks/#SA5011)\n\n<a id='SA5012'></a>\n## `SA5012`: Passing odd-sized slice to function expecting even size\n\nSome functions that take slices as parameters expect the slices to have an even number of elements.  Often, these functions treat elements in a slice as pairs.  For example, strings.NewReplacer takes pairs of old and new strings,  and calling it with an odd number of elements would be an error.\n\nAvailable since\n\n\t2020.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA5012\": true}`.\n\nPackage documentation: [SA5012](https://staticcheck.dev/docs/checks/#SA5012)\n\n<a id='SA6000'></a>\n## `SA6000`: Using regexp.Match or related in a loop, should use regexp.Compile\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA6000\": true}`.\n\nPackage documentation: [SA6000](https://staticcheck.dev/docs/checks/#SA6000)\n\n<a id='SA6001'></a>\n## `SA6001`: Missing an optimization opportunity when indexing maps by byte slices\n\nMap keys must be comparable, which precludes the use of byte slices. This usually leads to using string keys and converting byte slices to strings.\n\nNormally, a conversion of a byte slice to a string needs to copy the data and causes allocations. The compiler, however, recognizes m\\[string(b)] and uses the data of b directly, without copying it, because it knows that the data can't change during the map lookup. This leads to the counter-intuitive situation that\n\n\tk := string(b)\n\tprintln(m[k])\n\tprintln(m[k])\n\nwill be less efficient than\n\n\tprintln(m[string(b)])\n\tprintln(m[string(b)])\n\nbecause the first version needs to copy and allocate, while the second one does not.\n\nFor some history on this optimization, check out commit f5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA6001\": true}`.\n\nPackage documentation: [SA6001](https://staticcheck.dev/docs/checks/#SA6001)\n\n<a id='SA6002'></a>\n## `SA6002`: Storing non-pointer values in sync.Pool allocates memory\n\nA sync.Pool is used to avoid unnecessary allocations and reduce the amount of work the garbage collector has to do.\n\nWhen passing a value that is not a pointer to a function that accepts an interface, the value needs to be placed on the heap, which means an additional allocation. Slices are a common thing to put in sync.Pools, and they're structs with 3 fields (length, capacity, and a pointer to an array). In order to avoid the extra allocation, one should store a pointer to the slice instead.\n\nSee the comments on [https://go-review.googlesource.com/c/go/+/24371](https://go-review.googlesource.com/c/go/+/24371) that discuss this problem.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA6002\": true}`.\n\nPackage documentation: [SA6002](https://staticcheck.dev/docs/checks/#SA6002)\n\n<a id='SA6003'></a>\n## `SA6003`: Converting a string to a slice of runes before ranging over it\n\nYou may want to loop over the runes in a string. Instead of converting the string to a slice of runes and looping over that, you can loop over the string itself. That is,\n\n\tfor _, r := range s {}\n\nand\n\n\tfor _, r := range []rune(s) {}\n\nwill yield the same values. The first version, however, will be faster and avoid unnecessary memory allocations.\n\nDo note that if you are interested in the indices, ranging over a string and over a slice of runes will yield different indices. The first one yields byte offsets, while the second one yields indices in the slice of runes.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA6003\": true}`.\n\nPackage documentation: [SA6003](https://staticcheck.dev/docs/checks/#SA6003)\n\n<a id='SA6005'></a>\n## `SA6005`: Inefficient string comparison with strings.ToLower or strings.ToUpper\n\nConverting two strings to the same case and comparing them like so\n\n\tif strings.ToLower(s1) == strings.ToLower(s2) {\n\t    ...\n\t}\n\nis significantly more expensive than comparing them with strings.EqualFold(s1, s2). This is due to memory usage as well as computational complexity.\n\nstrings.ToLower will have to allocate memory for the new strings, as well as convert both strings fully, even if they differ on the very first byte. strings.EqualFold, on the other hand, compares the strings one character at a time. It doesn't need to create two intermediate strings and can return as soon as the first non-matching character has been found.\n\nFor a more in-depth explanation of this issue, see [https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/](https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/)\n\nAvailable since\n\n\t2019.2\n\n\nDefault: on.\n\nPackage documentation: [SA6005](https://staticcheck.dev/docs/checks/#SA6005)\n\n<a id='SA6006'></a>\n## `SA6006`: Using io.WriteString to write []byte\n\nUsing io.WriteString to write a slice of bytes, as in\n\n\tio.WriteString(w, string(b))\n\nis both unnecessary and inefficient. Converting from \\[]byte to string has to allocate and copy the data, and we could simply use w.Write(b) instead.\n\nAvailable since\n\n\t2024.1\n\n\nDefault: on.\n\nPackage documentation: [SA6006](https://staticcheck.dev/docs/checks/#SA6006)\n\n<a id='SA9001'></a>\n## `SA9001`: Defers in range loops may not run when you expect them to\n\nAvailable since\n\n\t2017.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA9001\": true}`.\n\nPackage documentation: [SA9001](https://staticcheck.dev/docs/checks/#SA9001)\n\n<a id='SA9002'></a>\n## `SA9002`: Using a non-octal os.FileMode that looks like it was meant to be in octal.\n\nAvailable since\n\n\t2017.1\n\n\nDefault: on.\n\nPackage documentation: [SA9002](https://staticcheck.dev/docs/checks/#SA9002)\n\n<a id='SA9003'></a>\n## `SA9003`: Empty body in an if or else branch\n\nAvailable since\n\n\t2017.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA9003\": true}`.\n\nPackage documentation: [SA9003](https://staticcheck.dev/docs/checks/#SA9003)\n\n<a id='SA9004'></a>\n## `SA9004`: Only the first constant has an explicit type\n\nIn a constant declaration such as the following:\n\n\tconst (\n\t    First byte = 1\n\t    Second     = 2\n\t)\n\nthe constant Second does not have the same type as the constant First. This construct shouldn't be confused with\n\n\tconst (\n\t    First byte = iota\n\t    Second\n\t)\n\nwhere First and Second do indeed have the same type. The type is only passed on when no explicit value is assigned to the constant.\n\nWhen declaring enumerations with explicit values it is therefore important not to write\n\n\tconst (\n\t      EnumFirst EnumType = 1\n\t      EnumSecond         = 2\n\t      EnumThird          = 3\n\t)\n\nThis discrepancy in types can cause various confusing behaviors and bugs.\n\n### Wrong type in variable declarations {#hdr-Wrong_type_in_variable_declarations}\n\nThe most obvious issue with such incorrect enumerations expresses itself as a compile error:\n\n\tpackage pkg\n\n\tconst (\n\t    EnumFirst  uint8 = 1\n\t    EnumSecond       = 2\n\t)\n\n\tfunc fn(useFirst bool) {\n\t    x := EnumSecond\n\t    if useFirst {\n\t        x = EnumFirst\n\t    }\n\t}\n\nfails to compile with\n\n\t./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment\n\n### Losing method sets {#hdr-Losing_method_sets}\n\nA more subtle issue occurs with types that have methods and optional interfaces. Consider the following:\n\n\tpackage main\n\n\timport \"fmt\"\n\n\ttype Enum int\n\n\tfunc (e Enum) String() string {\n\t    return \"an enum\"\n\t}\n\n\tconst (\n\t    EnumFirst  Enum = 1\n\t    EnumSecond      = 2\n\t)\n\n\tfunc main() {\n\t    fmt.Println(EnumFirst)\n\t    fmt.Println(EnumSecond)\n\t}\n\nThis code will output\n\n\tan enum\n\t2\n\nas EnumSecond has no explicit type, and thus defaults to int.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: on.\n\nPackage documentation: [SA9004](https://staticcheck.dev/docs/checks/#SA9004)\n\n<a id='SA9005'></a>\n## `SA9005`: Trying to marshal a struct with no public fields nor custom marshaling\n\nThe encoding/json and encoding/xml packages only operate on exported fields in structs, not unexported ones. It is usually an error to try to (un)marshal structs that only consist of unexported fields.\n\nThis check will not flag calls involving types that define custom marshaling behavior, e.g. via MarshalJSON methods. It will also not flag empty structs.\n\nAvailable since\n\n\t2019.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA9005\": true}`.\n\nPackage documentation: [SA9005](https://staticcheck.dev/docs/checks/#SA9005)\n\n<a id='SA9006'></a>\n## `SA9006`: Dubious bit shifting of a fixed size integer value\n\nBit shifting a value past its size will always clear the value.\n\nFor instance:\n\n\tv := int8(42)\n\tv >>= 8\n\nwill always result in 0.\n\nThis check flags bit shifting operations on fixed size integer values only. That is, int, uint and uintptr are never flagged to avoid potential false positives in somewhat exotic but valid bit twiddling tricks:\n\n\t// Clear any value above 32 bits if integers are more than 32 bits.\n\tfunc f(i int) int {\n\t    v := i >> 32\n\t    v = v << 32\n\t    return i-v\n\t}\n\nAvailable since\n\n\t2020.2\n\n\nDefault: on.\n\nPackage documentation: [SA9006](https://staticcheck.dev/docs/checks/#SA9006)\n\n<a id='SA9007'></a>\n## `SA9007`: Deleting a directory that shouldn't be deleted\n\nIt is virtually never correct to delete system directories such as /tmp or the user's home directory. However, it can be fairly easy to do by mistake, for example by mistakenly using os.TempDir instead of ioutil.TempDir, or by forgetting to add a suffix to the result of os.UserHomeDir.\n\nWriting\n\n\td := os.TempDir()\n\tdefer os.RemoveAll(d)\n\nin your unit tests will have a devastating effect on the stability of your system.\n\nThis check flags attempts at deleting the following directories:\n\n\\- os.TempDir - os.UserCacheDir - os.UserConfigDir - os.UserHomeDir\n\nAvailable since\n\n\t2022.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA9007\": true}`.\n\nPackage documentation: [SA9007](https://staticcheck.dev/docs/checks/#SA9007)\n\n<a id='SA9008'></a>\n## `SA9008`: else branch of a type assertion is probably not reading the right value\n\nWhen declaring variables as part of an if statement (like in 'if foo := ...; foo {'), the same variables will also be in the scope of the else branch. This means that in the following example\n\n\tif x, ok := x.(int); ok {\n\t    // ...\n\t} else {\n\t    fmt.Printf(\"unexpected type %T\", x)\n\t}\n\nx in the else branch will refer to the x from x, ok :=; it will not refer to the x that is being type-asserted. The result of a failed type assertion is the zero value of the type that is being asserted to, so x in the else branch will always have the value 0 and the type int.\n\nAvailable since\n\n\t2022.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"SA9008\": true}`.\n\nPackage documentation: [SA9008](https://staticcheck.dev/docs/checks/#SA9008)\n\n<a id='SA9009'></a>\n## `SA9009`: Ineffectual Go compiler directive\n\nA potential Go compiler directive was found, but is ineffectual as it begins with whitespace.\n\nAvailable since\n\n\t2024.1\n\n\nDefault: on.\n\nPackage documentation: [SA9009](https://staticcheck.dev/docs/checks/#SA9009)\n\n<a id='ST1000'></a>\n## `ST1000`: Incorrect or missing package comment\n\nPackages must have a package comment that is formatted according to the guidelines laid out in [https://go.dev/wiki/CodeReviewComments#package-comments](https://go.dev/wiki/CodeReviewComments#package-comments).\n\nAvailable since\n\n\t2019.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1000\": true}`.\n\nPackage documentation: [ST1000](https://staticcheck.dev/docs/checks/#ST1000)\n\n<a id='ST1001'></a>\n## `ST1001`: Dot imports are discouraged\n\nDot imports that aren't in external test packages are discouraged.\n\nThe dot\\_import\\_whitelist option can be used to whitelist certain imports.\n\nQuoting Go Code Review Comments:\n\n> The import . form can be useful in tests that, due to circular > dependencies, cannot be made part of the package being tested: >  >     package foo\\_test >  >     import ( >         \"bar/testutil\" // also imports \"foo\" >         . \"foo\" >     ) >  > In this case, the test file cannot be in package foo because it > uses bar/testutil, which imports foo. So we use the import . > form to let the file pretend to be part of package foo even though > it is not. Except for this one case, do not use import . in your > programs. It makes the programs much harder to read because it is > unclear whether a name like Quux is a top-level identifier in the > current package or in an imported package.\n\nAvailable since\n\n\t2019.1\n\nOptions\n\n\tdot_import_whitelist\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1001\": true}`.\n\nPackage documentation: [ST1001](https://staticcheck.dev/docs/checks/#ST1001)\n\n<a id='ST1003'></a>\n## `ST1003`: Poorly chosen identifier\n\nIdentifiers, such as variable and package names, follow certain rules.\n\nSee the following links for details:\n\n\\- [https://go.dev/doc/effective\\_go#package-names](https://go.dev/doc/effective_go#package-names) - [https://go.dev/doc/effective\\_go#mixed-caps](https://go.dev/doc/effective_go#mixed-caps) - [https://go.dev/wiki/CodeReviewComments#initialisms](https://go.dev/wiki/CodeReviewComments#initialisms) - [https://go.dev/wiki/CodeReviewComments#variable-names](https://go.dev/wiki/CodeReviewComments#variable-names)\n\nAvailable since\n\n\t2019.1, non-default\n\nOptions\n\n\tinitialisms\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1003\": true}`.\n\nPackage documentation: [ST1003](https://staticcheck.dev/docs/checks/#ST1003)\n\n<a id='ST1005'></a>\n## `ST1005`: Incorrectly formatted error string\n\nError strings follow a set of guidelines to ensure uniformity and good composability.\n\nQuoting Go Code Review Comments:\n\n> Error strings should not be capitalized (unless beginning with > proper nouns or acronyms) or end with punctuation, since they are > usually printed following other context. That is, use > fmt.Errorf(\"something bad\") not fmt.Errorf(\"Something bad\"), so > that log.Printf(\"Reading %s: %v\", filename, err) formats without a > spurious capital letter mid-message.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1005\": true}`.\n\nPackage documentation: [ST1005](https://staticcheck.dev/docs/checks/#ST1005)\n\n<a id='ST1006'></a>\n## `ST1006`: Poorly chosen receiver name\n\nQuoting Go Code Review Comments:\n\n> The name of a method's receiver should be a reflection of its > identity; often a one or two letter abbreviation of its type > suffices (such as \"c\" or \"cl\" for \"Client\"). Don't use generic > names such as \"me\", \"this\" or \"self\", identifiers typical of > object-oriented languages that place more emphasis on methods as > opposed to functions. The name need not be as descriptive as that > of a method argument, as its role is obvious and serves no > documentary purpose. It can be very short as it will appear on > almost every line of every method of the type; familiarity admits > brevity. Be consistent, too: if you call the receiver \"c\" in one > method, don't call it \"cl\" in another.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1006\": true}`.\n\nPackage documentation: [ST1006](https://staticcheck.dev/docs/checks/#ST1006)\n\n<a id='ST1008'></a>\n## `ST1008`: A function's error value should be its last return value\n\nA function's error value should be its last return value.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1008\": true}`.\n\nPackage documentation: [ST1008](https://staticcheck.dev/docs/checks/#ST1008)\n\n<a id='ST1011'></a>\n## `ST1011`: Poorly chosen name for variable of type time.Duration\n\ntime.Duration values represent an amount of time, which is represented as a count of nanoseconds. An expression like 5 \\* time.Microsecond yields the value 5000. It is therefore not appropriate to suffix a variable of type time.Duration with any time unit, such as Msec or Milli.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1011\": true}`.\n\nPackage documentation: [ST1011](https://staticcheck.dev/docs/checks/#ST1011)\n\n<a id='ST1012'></a>\n## `ST1012`: Poorly chosen name for error variable\n\nError variables that are part of an API should be called errFoo or ErrFoo.\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1012\": true}`.\n\nPackage documentation: [ST1012](https://staticcheck.dev/docs/checks/#ST1012)\n\n<a id='ST1013'></a>\n## `ST1013`: Should use constants for HTTP error codes, not magic numbers\n\nHTTP has a tremendous number of status codes. While some of those are well known (200, 400, 404, 500), most of them are not. The net/http package provides constants for all status codes that are part of the various specifications. It is recommended to use these constants instead of hard-coding magic numbers, to vastly improve the readability of your code.\n\nAvailable since\n\n\t2019.1\n\nOptions\n\n\thttp_status_code_whitelist\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1013\": true}`.\n\nPackage documentation: [ST1013](https://staticcheck.dev/docs/checks/#ST1013)\n\n<a id='ST1015'></a>\n## `ST1015`: A switch's default case should be the first or last case\n\nAvailable since\n\n\t2019.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1015\": true}`.\n\nPackage documentation: [ST1015](https://staticcheck.dev/docs/checks/#ST1015)\n\n<a id='ST1016'></a>\n## `ST1016`: Use consistent method receiver names\n\nAvailable since\n\n\t2019.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1016\": true}`.\n\nPackage documentation: [ST1016](https://staticcheck.dev/docs/checks/#ST1016)\n\n<a id='ST1017'></a>\n## `ST1017`: Don't use Yoda conditions\n\nYoda conditions are conditions of the kind 'if 42 == x', where the literal is on the left side of the comparison. These are a common idiom in languages in which assignment is an expression, to avoid bugs of the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of bug, we prefer the more idiomatic 'if x == 42'.\n\nAvailable since\n\n\t2019.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1017\": true}`.\n\nPackage documentation: [ST1017](https://staticcheck.dev/docs/checks/#ST1017)\n\n<a id='ST1018'></a>\n## `ST1018`: Avoid zero-width and control characters in string literals\n\nAvailable since\n\n\t2019.2\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1018\": true}`.\n\nPackage documentation: [ST1018](https://staticcheck.dev/docs/checks/#ST1018)\n\n<a id='ST1019'></a>\n## `ST1019`: Importing the same package multiple times\n\nGo allows importing the same package multiple times, as long as different import aliases are being used. That is, the following bit of code is valid:\n\n\timport (\n\t    \"fmt\"\n\t    fumpt \"fmt\"\n\t    format \"fmt\"\n\t)\n\nHowever, this is very rarely done on purpose. Usually, it is a sign of code that got refactored, accidentally adding duplicate import statements. It is also a rarely known feature, which may contribute to confusion.\n\nDo note that sometimes, this feature may be used intentionally (see for example [https://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d](https://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)) – if you want to allow this pattern in your code base, you're advised to disable this check.\n\nIt is acceptable to import the same package twice if one of the imports uses the blank identifier. This is allowed in order to increase resilience against erroneous changes when using the same package for its side effects as well as its exported API.\n\nAvailable since\n\n\t2020.1\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1019\": true}`.\n\nPackage documentation: [ST1019](https://staticcheck.dev/docs/checks/#ST1019)\n\n<a id='ST1020'></a>\n## `ST1020`: The documentation of an exported function should start with the function's name\n\nDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.\n\nIf every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.\n\nSee [https://go.dev/doc/effective\\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.\n\nAvailable since\n\n\t2020.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1020\": true}`.\n\nPackage documentation: [ST1020](https://staticcheck.dev/docs/checks/#ST1020)\n\n<a id='ST1021'></a>\n## `ST1021`: The documentation of an exported type should start with type's name\n\nDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.\n\nIf every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.\n\nSee [https://go.dev/doc/effective\\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.\n\nAvailable since\n\n\t2020.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1021\": true}`.\n\nPackage documentation: [ST1021](https://staticcheck.dev/docs/checks/#ST1021)\n\n<a id='ST1022'></a>\n## `ST1022`: The documentation of an exported variable or constant should start with variable's name\n\nDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.\n\nIf every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.\n\nSee [https://go.dev/doc/effective\\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.\n\nAvailable since\n\n\t2020.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1022\": true}`.\n\nPackage documentation: [ST1022](https://staticcheck.dev/docs/checks/#ST1022)\n\n<a id='ST1023'></a>\n## `ST1023`: Redundant type in variable declaration\n\nAvailable since\n\n\t2021.1, non-default\n\n\nDefault: off. Enable by setting `\"analyses\": {\"ST1023\": true}`.\n\nPackage documentation: [ST1023](https://staticcheck.dev/docs/checks/#)\n\n<a id='any'></a>\n## `any`: replace interface{} with any\n\nThe any analyzer suggests replacing uses of the empty interface type, \\`interface{}\\`, with the \\`any\\` alias, which was introduced in Go 1.18. This is a purely stylistic change that makes code more readable.\n\n\nDefault: on.\n\nPackage documentation: [any](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any)\n\n<a id='appendclipped'></a>\n## `appendclipped`: simplify append chains using slices.Concat\n\nThe appendclipped analyzer suggests replacing chains of append calls with a single call to slices.Concat, which was added in Go 1.21. For example, append(append(s, s1...), s2...) would be simplified to slices.Concat(s, s1, s2).\n\nIn the simple case of appending to a newly allocated slice, such as append(\\[]T(nil), s...), the analyzer suggests the more concise slices.Clone(s). For byte slices, it will prefer bytes.Clone if the \"bytes\" package is already imported.\n\nThis fix is only applied when the base of the append tower is a \"clipped\" slice, meaning its length and capacity are equal (e.g. x\\[:0:0] or \\[]T{}). This is to avoid changing program behavior by eliminating intended side effects on the base slice's underlying array.\n\nThis analyzer is currently disabled by default as the transformation does not preserve the nilness of the base slice in all cases; see [https://go.dev/issue/73557](https://go.dev/issue/73557).\n\n\nDefault: off. Enable by setting `\"analyses\": {\"appendclipped\": true}`.\n\nPackage documentation: [appendclipped](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped)\n\n<a id='appends'></a>\n## `appends`: check for missing values after append\n\nThis checker reports calls to append that pass no values to be appended to the slice.\n\n\ts := []string{\"a\", \"b\", \"c\"}\n\t_ = append(s)\n\nSuch calls are always no-ops and often indicate an underlying mistake.\n\n\nDefault: on.\n\nPackage documentation: [appends](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends)\n\n<a id='asmdecl'></a>\n## `asmdecl`: report mismatches between assembly files and Go declarations\n\n\n\nDefault: on.\n\nPackage documentation: [asmdecl](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/asmdecl)\n\n<a id='assign'></a>\n## `assign`: check for useless assignments\n\nThis checker reports assignments of the form x = x or a\\[i] = a\\[i]. These are almost always useless, and even when they aren't they are usually a mistake.\n\n\nDefault: on.\n\nPackage documentation: [assign](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign)\n\n<a id='atomic'></a>\n## `atomic`: check for common mistakes using the sync/atomic package\n\nThe atomic checker looks for assignment statements of the form:\n\n\tx = atomic.AddUint64(&x, 1)\n\nwhich are not atomic.\n\n\nDefault: on.\n\nPackage documentation: [atomic](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic)\n\n<a id='atomicalign'></a>\n## `atomicalign`: check for non-64-bits-aligned arguments to sync/atomic functions\n\n\n\nDefault: on.\n\nPackage documentation: [atomicalign](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomicalign)\n\n<a id='atomictypes'></a>\n## `atomictypes`: replace basic types in sync/atomic calls with atomic types\n\nThe atomictypes analyzer suggests replacing the primitive sync/atomic functions with the strongly typed atomic wrapper types introduced in Go1.19 (e.g. atomic.Int32). For example,\n\n\tvar x int32\n\tatomic.AddInt32(&x, 1)\n\nwould become\n\n\tvar x atomic.Int32\n\tx.Add(1)\n\nThe atomic types are safer because they don't allow non-atomic access, which is a common source of bugs. These types also resolve memory alignment issues that plagued the old atomic functions on 32-bit architectures.\n\n\nDefault: on.\n\nPackage documentation: [atomictypes](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#atomictypes)\n\n<a id='bloop'></a>\n## `bloop`: replace for-range over b.N with b.Loop\n\nThe bloop analyzer suggests replacing benchmark loops of the form \\`for i := 0; i \\< b.N; i++\\` or \\`for range b.N\\` with the more modern \\`for b.Loop()\\`, which was added in Go 1.24.\n\nThis change makes benchmark code more readable and also removes the need for manual timer control, so any preceding calls to b.StartTimer, b.StopTimer, or b.ResetTimer within the same function will also be removed.\n\nCaveats: The b.Loop() method is designed to prevent the compiler from optimizing away the benchmark loop, which can occasionally result in slower execution due to increased allocations in some specific cases. Since its fix may change the performance of nanosecond-scale benchmarks, bloop is disabled by default in the \\`go fix\\` analyzer suite; see golang/go#74967.\n\n\nDefault: on.\n\nPackage documentation: [bloop](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#bloop)\n\n<a id='bools'></a>\n## `bools`: check for common mistakes involving boolean operators\n\n\n\nDefault: on.\n\nPackage documentation: [bools](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/bools)\n\n<a id='buildtag'></a>\n## `buildtag`: check //go:build and // +build directives\n\n\n\nDefault: on.\n\nPackage documentation: [buildtag](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildtag)\n\n<a id='cgocall'></a>\n## `cgocall`: detect some violations of the cgo pointer passing rules\n\nCheck for invalid cgo pointer passing. This looks for code that uses cgo to call C code passing values whose types are almost always invalid according to the cgo pointer sharing rules. Specifically, it warns about attempts to pass a Go chan, map, func, or slice to C, either directly, or via a pointer, array, or struct.\n\n\nDefault: on.\n\nPackage documentation: [cgocall](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/cgocall)\n\n<a id='composites'></a>\n## `composites`: check for unkeyed composite literals\n\nThis analyzer reports a diagnostic for composite literals of struct types imported from another package that do not use the field-keyed syntax. Such literals are fragile because the addition of a new field (even if unexported) to the struct will cause compilation to fail.\n\nAs an example,\n\n\terr = &net.DNSConfigError{err}\n\nshould be replaced by:\n\n\terr = &net.DNSConfigError{Err: err}\n\n\nDefault: on.\n\nPackage documentation: [composites](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/composite)\n\n<a id='copylocks'></a>\n## `copylocks`: check for locks erroneously passed by value\n\nInadvertently copying a value containing a lock, such as sync.Mutex or sync.WaitGroup, may cause both copies to malfunction. Generally such values should be referred to through a pointer.\n\n\nDefault: on.\n\nPackage documentation: [copylocks](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylock)\n\n<a id='deepequalerrors'></a>\n## `deepequalerrors`: check for calls of reflect.DeepEqual on error values\n\nThe deepequalerrors checker looks for calls of the form:\n\n\treflect.DeepEqual(err1, err2)\n\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare errors is discouraged.\n\n\nDefault: on.\n\nPackage documentation: [deepequalerrors](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/deepequalerrors)\n\n<a id='defers'></a>\n## `defers`: report common mistakes in defer statements\n\nThe defers analyzer reports a diagnostic when a defer statement would result in a non-deferred call to time.Since, as experience has shown that this is nearly always a mistake.\n\nFor example:\n\n\tstart := time.Now()\n\t...\n\tdefer recordLatency(time.Since(start)) // error: call to time.Since is not deferred\n\nThe correct code is:\n\n\tdefer func() { recordLatency(time.Since(start)) }()\n\n\nDefault: on.\n\nPackage documentation: [defers](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers)\n\n<a id='deprecated'></a>\n## `deprecated`: check for use of deprecated identifiers\n\nThe deprecated analyzer looks for deprecated symbols and package imports.\n\nSee [https://go.dev/wiki/Deprecated](https://go.dev/wiki/Deprecated) to learn about Go's convention for documenting and signaling deprecated identifiers.\n\n\nDefault: on.\n\nPackage documentation: [deprecated](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/deprecated)\n\n<a id='directive'></a>\n## `directive`: check Go toolchain directives such as //go:debug\n\nThis analyzer checks for problems with known Go toolchain directives in all Go source files in a package directory, even those excluded by //go:build constraints, and all non-Go source files too.\n\nFor //go:debug (see [https://go.dev/doc/godebug](https://go.dev/doc/godebug)), the analyzer checks that the directives are placed only in Go source files, only above the package comment, and only in package main or \\*\\_test.go files.\n\nSupport for other known directives may be added in the future.\n\nThis analyzer does not check //go:build, which is handled by the buildtag analyzer.\n\n\nDefault: on.\n\nPackage documentation: [directive](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/directive)\n\n<a id='embed'></a>\n## `embed`: check //go:embed directive usage\n\nThis analyzer checks that the embed package is imported if //go:embed directives are present, providing a suggested fix to add the import if it is missing.\n\nThis analyzer also checks that //go:embed directives precede the declaration of a single variable.\n\n\nDefault: on.\n\nPackage documentation: [embed](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/embeddirective)\n\n<a id='errorsas'></a>\n## `errorsas`: report passing non-pointer or non-error values to errors.As\n\nThe errorsas analyzer reports calls to errors.As where the type of the second argument is not a pointer to a type implementing error.\n\n\nDefault: on.\n\nPackage documentation: [errorsas](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas)\n\n<a id='errorsastype'></a>\n## `errorsastype`: replace errors.As with errors.AsType[T]\n\nThis analyzer suggests fixes to simplify uses of [errors.As](/errors#As) of this form:\n\n\tvar myerr *MyErr\n\tif errors.As(err, &myerr) {\n\t\thandle(myerr)\n\t}\n\nby using the less error-prone generic [errors.AsType](/errors#AsType) function, introduced in Go 1.26:\n\n\tif myerr, ok := errors.AsType[*MyErr](err); ok {\n\t\thandle(myerr)\n\t}\n\nThe fix is only offered if the var declaration has the form shown and there are no uses of myerr outside the if statement.\n\n\nDefault: on.\n\nPackage documentation: [errorsastype](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype)\n\n<a id='fieldalignment'></a>\n## `fieldalignment`: find structs that would use less memory if their fields were sorted\n\nThis analyzer finds structs that can be rearranged to use less memory, and provides a suggested edit with the most compact order.\n\nNote that there are two different diagnostics reported. One checks struct size, and the other reports \"pointer bytes\" used. Pointer bytes is how many bytes of the object that the garbage collector has to potentially scan for pointers, for example:\n\n\tstruct { uint32; string }\n\nhave 16 pointer bytes because the garbage collector has to scan up through the string's inner pointer.\n\n\tstruct { string; *uint32 }\n\nhas 24 pointer bytes because it has to scan further through the \\*uint32.\n\n\tstruct { string; uint32 }\n\nhas 8 because it can stop immediately after the string pointer.\n\nBe aware that the most compact order is not always the most efficient. In rare cases it may cause two variables each updated by its own goroutine to occupy the same CPU cache line, inducing a form of memory contention known as \"false sharing\" that slows down both goroutines.\n\nUnlike most analyzers, which report likely mistakes, the diagnostics produced by fieldanalyzer very rarely indicate a significant problem, so the analyzer is not included in typical suites such as vet or gopls. Use this standalone command to run it on your code:\n\n\t$ go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest\n\t$ fieldalignment [packages]\n\n\nDefault: off. Enable by setting `\"analyses\": {\"fieldalignment\": true}`.\n\nPackage documentation: [fieldalignment](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/fieldalignment)\n\n<a id='fillreturns'></a>\n## `fillreturns`: suggest fixes for errors due to an incorrect number of return values\n\nThis checker provides suggested fixes for type errors of the type \"wrong number of return values (want %d, got %d)\". For example:\n\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to [https://github.com/sqs/goreturns](https://github.com/sqs/goreturns).\n\n\nDefault: on.\n\nPackage documentation: [fillreturns](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns)\n\n<a id='fmtappendf'></a>\n## `fmtappendf`: replace []byte(fmt.Sprintf) with fmt.Appendf\n\nThe fmtappendf analyzer suggests replacing \\`\\[]byte(fmt.Sprintf(...))\\` with \\`fmt.Appendf(nil, ...)\\`. This avoids the intermediate allocation of a string by Sprintf, making the code more efficient. The suggestion also applies to fmt.Sprint and fmt.Sprintln.\n\n\nDefault: on.\n\nPackage documentation: [fmtappendf](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#fmtappendf)\n\n<a id='forvar'></a>\n## `forvar`: remove redundant re-declaration of loop variables\n\nThe forvar analyzer removes unnecessary shadowing of loop variables. Before Go 1.22, it was common to write \\`for \\_, x := range s { x := x ... }\\` to create a fresh variable for each iteration. Go 1.22 changed the semantics of \\`for\\` loops, making this pattern redundant. This analyzer removes the unnecessary \\`x := x\\` statement.\n\nThis fix only applies to \\`range\\` loops.\n\n\nDefault: on.\n\nPackage documentation: [forvar](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar)\n\n<a id='framepointer'></a>\n## `framepointer`: report assembly that clobbers the frame pointer before saving it\n\n\n\nDefault: on.\n\nPackage documentation: [framepointer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer)\n\n<a id='hostport'></a>\n## `hostport`: check format of addresses passed to net.Dial\n\nThis analyzer flags code that produce network address strings using fmt.Sprintf, as in this example:\n\n\taddr := fmt.Sprintf(\"%s:%d\", host, 12345) // \"will not work with IPv6\"\n\t...\n\tconn, err := net.Dial(\"tcp\", addr)       // \"when passed to dial here\"\n\nThe analyzer suggests a fix to use the correct approach, a call to net.JoinHostPort:\n\n\taddr := net.JoinHostPort(host, \"12345\")\n\t...\n\tconn, err := net.Dial(\"tcp\", addr)\n\nA similar diagnostic and fix are produced for a format string of \"%s:%s\".\n\n\nDefault: on.\n\nPackage documentation: [hostport](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/hostport)\n\n<a id='httpresponse'></a>\n## `httpresponse`: check for mistakes using HTTP responses\n\nA common mistake when using the net/http package is to defer a function call to close the http.Response Body before checking the error that determines whether the response is valid:\n\n\tresp, err := http.Head(url)\n\tdefer resp.Body.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// (defer statement belongs here)\n\nThis checker helps uncover latent nil dereference bugs by reporting a diagnostic for such mistakes.\n\n\nDefault: on.\n\nPackage documentation: [httpresponse](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpresponse)\n\n<a id='ifaceassert'></a>\n## `ifaceassert`: detect impossible interface-to-interface type assertions\n\nThis checker flags type assertions v.(T) and corresponding type-switch cases in which the static type V of v is an interface that cannot possibly implement the target interface T. This occurs when V and T contain methods with the same name but different signatures. Example:\n\n\tvar v interface {\n\t\tRead()\n\t}\n\t_ = v.(io.Reader)\n\nThe Read method in v has a different signature than the Read method in io.Reader, so this assertion cannot succeed.\n\n\nDefault: on.\n\nPackage documentation: [ifaceassert](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert)\n\n<a id='infertypeargs'></a>\n## `infertypeargs`: check for unnecessary type arguments in call expressions\n\nExplicit type arguments may be omitted from call expressions if they can be inferred from function arguments, or from other type arguments:\n\n\tfunc f[T any](T) {}\n\n\tfunc _() {\n\t\tf[string](\"foo\") // string could be inferred\n\t}\n\n\nDefault: on.\n\nPackage documentation: [infertypeargs](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs)\n\n<a id='inline'></a>\n## `inline`: apply fixes based on 'go:fix inline' comment directives\n\nThe inline analyzer inlines functions and constants that are marked for inlining.\n\n\\## Functions\n\nGiven a function that is marked for inlining, like this one:\n\n\t//go:fix inline\n\tfunc Square(x int) int { return Pow(x, 2) }\n\nthis analyzer will recommend that calls to the function elsewhere, in the same or other packages, should be inlined.\n\nInlining can be used to move off of a deprecated function:\n\n\t// Deprecated: prefer Pow(x, 2).\n\t//go:fix inline\n\tfunc Square(x int) int { return Pow(x, 2) }\n\nIt can also be used to move off of an obsolete package, as when the import path has changed or a higher major version is available:\n\n\tpackage pkg\n\n\timport pkg2 \"pkg/v2\"\n\n\t//go:fix inline\n\tfunc F() { pkg2.F(nil) }\n\nReplacing a call pkg.F() by pkg2.F(nil) can have no effect on the program, so this mechanism provides a low-risk way to update large numbers of calls. We recommend, where possible, expressing the old API in terms of the new one to enable automatic migration.\n\nThe inliner takes care to avoid behavior changes, even subtle ones, such as changes to the order in which argument expressions are evaluated. When it cannot safely eliminate all parameter variables, it may introduce a \"binding declaration\" of the form\n\n\tvar params = args\n\nto evaluate argument expressions in the correct order and bind them to parameter variables. Since the resulting code transformation may be stylistically suboptimal, such inlinings may be disabled by specifying the -inline.allow\\_binding\\_decl=false flag to the analyzer driver.\n\n(In cases where it is not safe to \"reduce\" a call—that is, to replace a call f(x) by the body of function f, suitably substituted—the inliner machinery is capable of replacing f by a function literal, func(){...}(). However, the inline analyzer discards all such \"literalizations\" unconditionally, again on grounds of style.)\n\n\\## Constants\n\nGiven a constant that is marked for inlining, like this one:\n\n\t//go:fix inline\n\tconst Ptr = Pointer\n\nthis analyzer will recommend that uses of Ptr should be replaced with Pointer.\n\nAs with functions, inlining can be used to replace deprecated constants and constants in obsolete packages.\n\nA constant definition can be marked for inlining only if it refers to another named constant.\n\nThe \"//go:fix inline\" comment must appear before a single const declaration on its own, as above; before a const declaration that is part of a group, as in this case:\n\n\tconst (\n\t   C = 1\n\t   //go:fix inline\n\t   Ptr = Pointer\n\t)\n\nor before a group, applying to every constant in the group:\n\n\t//go:fix inline\n\tconst (\n\t\tPtr = Pointer\n\t    Val = Value\n\t)\n\nThe proposal [https://go.dev/issue/32816](https://go.dev/issue/32816) introduces the \"//go:fix inline\" directives.\n\nYou can use this command to apply inline fixes en masse:\n\n\t$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...\n\n\nDefault: on.\n\nPackage documentation: [inline](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline)\n\n<a id='loopclosure'></a>\n## `loopclosure`: check references to loop variables from within nested functions\n\nThis analyzer reports places where a function literal references the iteration variable of an enclosing loop, and the loop calls the function in such a way (e.g. with go or defer) that it may outlive the loop iteration and possibly observe the wrong value of the variable.\n\nNote: An iteration variable can only outlive a loop iteration in Go versions \\<=1.21. In Go 1.22 and later, the loop variable lifetimes changed to create a new iteration variable per loop iteration. (See go.dev/issue/60078.)\n\nIn this example, all the deferred functions run after the loop has completed, so all observe the final value of v \\[\\<go1.22].\n\n\tfor _, v := range list {\n\t    defer func() {\n\t        use(v) // incorrect\n\t    }()\n\t}\n\nOne fix is to create a new variable for each iteration of the loop:\n\n\tfor _, v := range list {\n\t    v := v // new var per iteration\n\t    defer func() {\n\t        use(v) // ok\n\t    }()\n\t}\n\nAfter Go version 1.22, the previous two for loops are equivalent and both are correct.\n\nThe next example uses a go statement and has a similar problem \\[\\<go1.22]. In addition, it has a data race because the loop updates v concurrent with the goroutines accessing it.\n\n\tfor _, v := range elem {\n\t    go func() {\n\t        use(v)  // incorrect, and a data race\n\t    }()\n\t}\n\nA fix is the same as before. The checker also reports problems in goroutines started by golang.org/x/sync/errgroup.Group. A hard-to-spot variant of this form is common in parallel tests:\n\n\tfunc Test(t *testing.T) {\n\t    for _, test := range tests {\n\t        t.Run(test.name, func(t *testing.T) {\n\t            t.Parallel()\n\t            use(test) // incorrect, and a data race\n\t        })\n\t    }\n\t}\n\nThe t.Parallel() call causes the rest of the function to execute concurrent with the loop \\[\\<go1.22].\n\nThe analyzer reports references only in the last statement, as it is not deep enough to understand the effects of subsequent statements that might render the reference benign. (\"Last statement\" is defined recursively in compound statements such as if, switch, and select.)\n\nSee: [https://golang.org/doc/go\\_faq.html#closures\\_and\\_goroutines](https://golang.org/doc/go_faq.html#closures_and_goroutines)\n\n\nDefault: on.\n\nPackage documentation: [loopclosure](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure)\n\n<a id='lostcancel'></a>\n## `lostcancel`: check cancel func returned by context.WithCancel is called\n\nThe cancellation function returned by context.WithCancel, WithTimeout, WithDeadline and variants such as WithCancelCause must be called, or the new context will remain live until its parent context is cancelled. (The background context is never cancelled.)\n\n\nDefault: on.\n\nPackage documentation: [lostcancel](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel)\n\n<a id='maprange'></a>\n## `maprange`: checks for unnecessary calls to maps.Keys and maps.Values in range statements\n\nConsider a loop written like this:\n\n\tfor val := range maps.Values(m) {\n\t\tfmt.Println(val)\n\t}\n\nThis should instead be written without the call to maps.Values:\n\n\tfor _, val := range m {\n\t\tfmt.Println(val)\n\t}\n\ngolang.org/x/exp/maps returns slices for Keys/Values instead of iterators, but unnecessary calls should similarly be removed:\n\n\tfor _, key := range maps.Keys(m) {\n\t\tfmt.Println(key)\n\t}\n\nshould be rewritten as:\n\n\tfor key := range m {\n\t\tfmt.Println(key)\n\t}\n\n\nDefault: on.\n\nPackage documentation: [maprange](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange)\n\n<a id='mapsloop'></a>\n## `mapsloop`: replace explicit loops over maps with calls to maps package\n\nThe mapsloop analyzer replaces loops of the form\n\n\tfor k, v := range x { m[k] = v }\n\nwith a single call to a function from the \\`maps\\` package, added in Go 1.23. Depending on the context, this could be \\`maps.Copy\\`, \\`maps.Insert\\`, \\`maps.Clone\\`, or \\`maps.Collect\\`.\n\nThe transformation to \\`maps.Clone\\` is applied conservatively, as it preserves the nilness of the source map, which may be a subtle change in behavior if the original code did not handle a nil map in the same way.\n\n\nDefault: on.\n\nPackage documentation: [mapsloop](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop)\n\n<a id='minmax'></a>\n## `minmax`: replace if/else statements with calls to min or max\n\nThe minmax analyzer simplifies conditional assignments by suggesting the use of the built-in \\`min\\` and \\`max\\` functions, introduced in Go 1.21. For example,\n\n\tif a < b { x = a } else { x = b }\n\nis replaced by\n\n\tx = min(a, b).\n\nThis analyzer avoids making suggestions for floating-point types, as the behavior of \\`min\\` and \\`max\\` with NaN values can differ from the original if/else statement.\n\n\nDefault: on.\n\nPackage documentation: [minmax](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#minmax)\n\n<a id='newexpr'></a>\n## `newexpr`: simplify code by using go1.26's new(expr)\n\nThis analyzer finds declarations of functions of this form:\n\n\tfunc varOf(x int) *int { return &x }\n\nand suggests a fix to turn them into inlinable wrappers around go1.26's built-in new(expr) function:\n\n\t//go:fix inline\n\tfunc varOf(x int) *int { return new(x) }\n\n(The directive comment causes the 'inline' analyzer to suggest that calls to such functions are inlined.)\n\nIn addition, this analyzer suggests a fix for each call to one of the functions before it is transformed, so that\n\n\tuse(varOf(123))\n\nis replaced by:\n\n\tuse(new(123))\n\nWrapper functions such as varOf are common when working with Go serialization packages such as for JSON or protobuf, where pointers are often used to express optionality.\n\n\nDefault: on.\n\nPackage documentation: [newexpr](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#newexpr)\n\n<a id='nilfunc'></a>\n## `nilfunc`: check for useless comparisons between functions and nil\n\nA useless comparison is one like f == nil as opposed to f() == nil.\n\n\nDefault: on.\n\nPackage documentation: [nilfunc](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc)\n\n<a id='nilness'></a>\n## `nilness`: check for redundant or impossible nil comparisons\n\nThe nilness checker inspects the control-flow graph of each function in a package and reports nil pointer dereferences, degenerate nil pointers, and panics with nil values. A degenerate comparison is of the form x==nil or x!=nil where x is statically known to be nil or non-nil. These are often a mistake, especially in control flow related to errors. Panics with nil values are checked because they are not detectable by\n\n\tif r := recover(); r != nil {\n\nThis check reports conditions such as:\n\n\tif f == nil { // impossible condition (f is a function)\n\t}\n\nand:\n\n\tp := &v\n\t...\n\tif p != nil { // tautological condition\n\t}\n\nand:\n\n\tif p == nil {\n\t\tprint(*p) // nil dereference\n\t}\n\nand:\n\n\tif p == nil {\n\t\tpanic(p)\n\t}\n\nSometimes the control flow may be quite complex, making bugs hard to spot. In the example below, the err.Error expression is guaranteed to panic because, after the first return, err must be nil. The intervening loop is just a distraction.\n\n\t...\n\terr := g.Wait()\n\tif err != nil {\n\t\treturn err\n\t}\n\tpartialSuccess := false\n\tfor _, err := range errs {\n\t\tif err == nil {\n\t\t\tpartialSuccess = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif partialSuccess {\n\t\treportStatus(StatusMessage{\n\t\t\tCode:   code.ERROR,\n\t\t\tDetail: err.Error(), // \"nil dereference in dynamic method call\"\n\t\t})\n\t\treturn nil\n\t}\n\n...\n\n\nDefault: on.\n\nPackage documentation: [nilness](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilness)\n\n<a id='nonewvars'></a>\n## `nonewvars`: suggested fixes for \"no new vars on left side of :=\"\n\nThis checker provides suggested fixes for type errors of the type \"no new vars on left side of :=\". For example:\n\n\tz := 1\n\tz := 2\n\nwill turn into\n\n\tz := 1\n\tz = 2\n\n\nDefault: on.\n\nPackage documentation: [nonewvars](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars)\n\n<a id='noresultvalues'></a>\n## `noresultvalues`: suggested fixes for unexpected return values\n\nThis checker provides suggested fixes for type errors of the type \"no result values expected\" or \"too many return values\". For example:\n\n\tfunc z() { return nil }\n\nwill turn into\n\n\tfunc z() { return }\n\n\nDefault: on.\n\nPackage documentation: [noresultvalues](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvalues)\n\n<a id='omitzero'></a>\n## `omitzero`: suggest replacing omitempty with omitzero for struct fields\n\nThe omitzero analyzer identifies uses of the \\`omitempty\\` JSON struct tag on fields that are themselves structs. For struct-typed fields, the \\`omitempty\\` tag has no effect on the behavior of json.Marshal and json.Unmarshal. The analyzer offers two suggestions: either remove the tag, or replace it with \\`omitzero\\` (added in Go 1.24), which correctly omits the field if the struct value is zero.\n\nHowever, some other serialization packages (notably kubebuilder, see [https://book.kubebuilder.io/reference/markers.html](https://book.kubebuilder.io/reference/markers.html)) may have their own interpretation of the \\`json:\",omitzero\"\\` tag, so removing it may affect program behavior. For this reason, the omitzero modernizer will not make changes in any package that contains +kubebuilder annotations.\n\nReplacing \\`omitempty\\` with \\`omitzero\\` is a change in behavior. The original code would always encode the struct field, whereas the modified code will omit it if it is a zero-value.\n\n\nDefault: on.\n\nPackage documentation: [omitzero](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero)\n\n<a id='plusbuild'></a>\n## `plusbuild`: remove obsolete //+build comments\n\nThe plusbuild analyzer suggests a fix to remove obsolete build tags of the form:\n\n\t//+build linux,amd64\n\nin files that also contain a Go 1.18-style tag such as:\n\n\t//go:build linux && amd64\n\n(It does not check that the old and new tags are consistent; that is the job of the 'buildtag' analyzer in the vet suite.)\n\n\nDefault: on.\n\nPackage documentation: [plusbuild](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild)\n\n<a id='printf'></a>\n## `printf`: check consistency of Printf format strings and arguments\n\nThe check applies to calls of the formatting functions such as [fmt.Printf](/fmt#Printf) and [fmt.Sprintf](/fmt#Sprintf), as well as any detected wrappers of those functions such as [log.Printf](/log#Printf). It reports a variety of mistakes such as syntax errors in the format string and mismatches (of number and type) between the verbs and their arguments.\n\nSee the documentation of the fmt package for the complete set of format operators and their operand types.\n\n\nDefault: on.\n\nPackage documentation: [printf](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf)\n\n<a id='rangeint'></a>\n## `rangeint`: replace 3-clause for loops with for-range over integers\n\nThe rangeint analyzer suggests replacing traditional for loops such as\n\n\tfor i := 0; i < n; i++ { ... }\n\nwith the more idiomatic Go 1.22 style:\n\n\tfor i := range n { ... }\n\nThis transformation is applied only if (a) the loop variable is not modified within the loop body and (b) the loop's limit expression is not modified within the loop, as \\`for range\\` evaluates its operand only once.\n\n\nDefault: on.\n\nPackage documentation: [rangeint](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#rangeint)\n\n<a id='recursiveiter'></a>\n## `recursiveiter`: check for inefficient recursive iterators\n\nThis analyzer reports when a function that returns an iterator (iter.Seq or iter.Seq2) calls itself as the operand of a range statement, as this is inefficient.\n\nWhen implementing an iterator (e.g. iter.Seq\\[T]) for a recursive data type such as a tree or linked list, it is tempting to recursively range over the iterator for each child element.\n\nHere's an example of a naive iterator over a binary tree:\n\n\ttype tree struct {\n\t\tvalue       int\n\t\tleft, right *tree\n\t}\n\n\tfunc (t *tree) All() iter.Seq[int] {\n\t\treturn func(yield func(int) bool) {\n\t\t\tif t != nil {\n\t\t\t\tfor elem := range t.left.All() { // \"inefficient recursive iterator\"\n\t\t\t\t\tif !yield(elem) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(t.value) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfor elem := range t.right.All() { // \"inefficient recursive iterator\"\n\t\t\t\t\tif !yield(elem) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\nThough it correctly enumerates the elements of the tree, it hides a significant performance problem--two, in fact. Consider a balanced tree of N nodes. Iterating the root node will cause All to be called once on every node of the tree. This results in a chain of nested active range-over-func statements when yield(t.value) is called on a leaf node.\n\nThe first performance problem is that each range-over-func statement must typically heap-allocate a variable, so iteration of the tree allocates as many variables as there are elements in the tree, for a total of O(N) allocations, all unnecessary.\n\nThe second problem is that each call to yield for a leaf of the tree causes each of the enclosing range loops to receive a value, which they then immediately pass on to their respective yield function. This results in a chain of log(N) dynamic yield calls per element, a total of O(N\\*log N) dynamic calls overall, when only O(N) are necessary.\n\nA better implementation strategy for recursive iterators is to first define the \"every\" operator for your recursive data type, where every(f) reports whether an arbitrary predicate f(x) is true for every element x in the data type. For our tree, the every function would be:\n\n\tfunc (t *tree) every(f func(int) bool) bool {\n\t\treturn t == nil ||\n\t\t\tt.left.every(f) && f(t.value) && t.right.every(f)\n\t}\n\nFor example, this use of the every operator prints whether every element in the tree is an even number:\n\n\teven := func(x int) bool { return x&1 == 0 }\n\tprintln(t.every(even))\n\nThen the iterator can be simply expressed as a trivial wrapper around the every operator:\n\n\tfunc (t *tree) All() iter.Seq[int] {\n\t\treturn func(yield func(int) bool) {\n\t\t\t_ = t.every(yield)\n\t\t}\n\t}\n\nIn effect, tree.All computes whether yield returns true for each element, short-circuiting if it ever returns false, then discards the final boolean result.\n\nThis has much better performance characteristics: it makes one dynamic call per element of the tree, and it doesn't heap-allocate anything. It is also clearer.\n\n\nDefault: on.\n\nPackage documentation: [recursiveiter](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/recursiveiter)\n\n<a id='reflecttypefor'></a>\n## `reflecttypefor`: replace reflect.TypeOf(x) with TypeFor[T]()\n\nThis analyzer suggests fixes to replace uses of reflect.TypeOf(x) with reflect.TypeFor, introduced in go1.22, when the desired runtime type is known at compile time, for example:\n\n\treflect.TypeOf(uint32(0))        -> reflect.TypeFor[uint32]()\n\treflect.TypeOf((*ast.File)(nil)) -> reflect.TypeFor[*ast.File]()\n\nIt also offers a fix to simplify the constructions below, which use reflect.TypeOf to return the runtime type for an interface type,\n\n\treflect.TypeOf((*io.Reader)(nil)).Elem()\n\nor:\n\n\treflect.TypeOf([]io.Reader(nil)).Elem()\n\nto:\n\n\treflect.TypeFor[io.Reader]()\n\nNo fix is offered in cases when the runtime type is dynamic, such as:\n\n\tvar r io.Reader = ...\n\treflect.TypeOf(r)\n\nor when the operand has potential side effects.\n\n\nDefault: on.\n\nPackage documentation: [reflecttypefor](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#reflecttypefor)\n\n<a id='shadow'></a>\n## `shadow`: check for possible unintended shadowing of variables\n\nThis analyzer check for shadowed variables. A shadowed variable is a variable declared in an inner scope with the same name and type as a variable in an outer scope, and where the outer variable is mentioned after the inner one is declared.\n\n(This definition can be refined; the module generates too many false positives and is not yet enabled by default.)\n\nFor example:\n\n\tfunc BadRead(f *os.File, buf []byte) error {\n\t\tvar err error\n\t\tfor {\n\t\t\tn, err := f.Read(buf) // shadows the function variable 'err'\n\t\t\tif err != nil {\n\t\t\t\tbreak // causes return of wrong value\n\t\t\t}\n\t\t\tfoo(buf)\n\t\t}\n\t\treturn err\n\t}\n\n\nDefault: off. Enable by setting `\"analyses\": {\"shadow\": true}`.\n\nPackage documentation: [shadow](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shadow)\n\n<a id='shift'></a>\n## `shift`: check for shifts that equal or exceed the width of the integer\n\n\n\nDefault: on.\n\nPackage documentation: [shift](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shift)\n\n<a id='sigchanyzer'></a>\n## `sigchanyzer`: check for unbuffered channel of os.Signal\n\nThis checker reports call expression of the form\n\n\tsignal.Notify(c <-chan os.Signal, sig ...os.Signal),\n\nwhere c is an unbuffered channel, which can be at risk of missing the signal.\n\n\nDefault: on.\n\nPackage documentation: [sigchanyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer)\n\n<a id='simplifycompositelit'></a>\n## `simplifycompositelit`: check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\n\t[]T{T{}, T{}}\n\nwill be simplified to:\n\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.\n\n\nDefault: on.\n\nPackage documentation: [simplifycompositelit](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit)\n\n<a id='simplifyrange'></a>\n## `simplifyrange`: check for range statement simplifications\n\nA range of the form:\n\n\tfor x, _ = range v {...}\n\nwill be simplified to:\n\n\tfor x = range v {...}\n\nA range of the form:\n\n\tfor _ = range v {...}\n\nwill be simplified to:\n\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.\n\n\nDefault: on.\n\nPackage documentation: [simplifyrange](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange)\n\n<a id='simplifyslice'></a>\n## `simplifyslice`: check for slice simplifications\n\nA slice expression of the form:\n\n\ts[a:len(s)]\n\nwill be simplified to:\n\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.\n\n\nDefault: on.\n\nPackage documentation: [simplifyslice](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice)\n\n<a id='slicescontains'></a>\n## `slicescontains`: replace loops with slices.Contains or slices.ContainsFunc\n\nThe slicescontains analyzer simplifies loops that check for the existence of an element in a slice. It replaces them with calls to \\`slices.Contains\\` or \\`slices.ContainsFunc\\`, which were added in Go 1.21.\n\nIf the expression for the target element has side effects, this transformation will cause those effects to occur only once, not once per tested slice element.\n\n\nDefault: on.\n\nPackage documentation: [slicescontains](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains)\n\n<a id='slicesdelete'></a>\n## `slicesdelete`: replace append-based slice deletion with slices.Delete\n\nThe slicesdelete analyzer suggests replacing the idiom\n\n\ts = append(s[:i], s[j:]...)\n\nwith the more explicit\n\n\ts = slices.Delete(s, i, j)\n\nintroduced in Go 1.21.\n\nThis analyzer is disabled by default. The \\`slices.Delete\\` function zeros the elements between the new length and the old length of the slice to prevent memory leaks, which is a subtle difference in behavior compared to the append-based idiom; see [https://go.dev/issue/73686](https://go.dev/issue/73686).\n\n\nDefault: off. Enable by setting `\"analyses\": {\"slicesdelete\": true}`.\n\nPackage documentation: [slicesdelete](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete)\n\n<a id='slicessort'></a>\n## `slicessort`: replace sort.Slice with slices.Sort for basic types\n\nThe slicessort analyzer simplifies sorting slices of basic ordered types. It replaces\n\n\tsort.Slice(s, func(i, j int) bool { return s[i] < s[j] })\n\nwith the simpler \\`slices.Sort(s)\\`, which was added in Go 1.21.\n\n\nDefault: on.\n\nPackage documentation: [slicessort](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicessort)\n\n<a id='slog'></a>\n## `slog`: check for invalid structured logging calls\n\nThe slog checker looks for calls to functions from the log/slog package that take alternating key-value pairs. It reports calls where an argument in a key position is neither a string nor a slog.Attr, and where a final key is missing its value. For example,it would report\n\n\tslog.Warn(\"message\", 11, \"k\") // slog.Warn arg \"11\" should be a string or a slog.Attr\n\nand\n\n\tslog.Info(\"message\", \"k1\", v1, \"k2\") // call to slog.Info missing a final value\n\n\nDefault: on.\n\nPackage documentation: [slog](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog)\n\n<a id='sortslice'></a>\n## `sortslice`: check the argument type of sort.Slice\n\nsort.Slice requires an argument of a slice type. Check that the interface{} value passed to sort.Slice is actually a slice.\n\n\nDefault: on.\n\nPackage documentation: [sortslice](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sortslice)\n\n<a id='stditerators'></a>\n## `stditerators`: use iterators instead of Len/At-style APIs\n\nThis analyzer suggests a fix to replace each loop of the form:\n\n\tfor i := 0; i < x.Len(); i++ {\n\t\tuse(x.At(i))\n\t}\n\nor its \"for elem := range x.Len()\" equivalent by a range loop over an iterator offered by the same data type:\n\n\tfor elem := range x.All() {\n\t\tuse(x.At(i)\n\t}\n\nwhere x is one of various well-known types in the standard library.\n\n\nDefault: on.\n\nPackage documentation: [stditerators](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stditerators)\n\n<a id='stdmethods'></a>\n## `stdmethods`: check signature of methods of well-known interfaces\n\nSometimes a type may be intended to satisfy an interface but may fail to do so because of a mistake in its method signature. For example, the result of this WriteTo method should be (int64, error), not error, to satisfy io.WriterTo:\n\n\ttype myWriterTo struct{...}\n\tfunc (myWriterTo) WriteTo(w io.Writer) error { ... }\n\nThis check ensures that each method whose name matches one of several well-known interface methods from the standard library has the correct signature for that interface.\n\nChecked method names include:\n\n\tFormat GobEncode GobDecode MarshalJSON MarshalXML\n\tPeek ReadByte ReadFrom ReadRune Scan Seek\n\tUnmarshalJSON UnreadByte UnreadRune WriteByte\n\tWriteTo\n\n\nDefault: on.\n\nPackage documentation: [stdmethods](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods)\n\n<a id='stdversion'></a>\n## `stdversion`: report uses of too-new standard library symbols\n\nThe stdversion analyzer reports references to symbols in the standard library that were introduced by a Go release higher than the one in force in the referring file. (Recall that the file's Go version is defined by the 'go' directive its module's go.mod file, or by a \"//go:build go1.X\" build tag at the top of the file.)\n\nThe analyzer does not report a diagnostic for a reference to a \"too new\" field or method of a type that is itself \"too new\", as this may have false positives, for example if fields or methods are accessed through a type alias that is guarded by a Go version constraint.\n\n\nDefault: on.\n\nPackage documentation: [stdversion](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion)\n\n<a id='stringintconv'></a>\n## `stringintconv`: check for string(int) conversions\n\nThis checker flags conversions of the form string(x) where x is an integer (but not byte or rune) type. Such conversions are discouraged because they return the UTF-8 representation of the Unicode code point x, and not a decimal string representation of x as one might expect. Furthermore, if x denotes an invalid code point, the conversion cannot be statically rejected.\n\nFor conversions that intend on using the code point, consider replacing them with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the string representation of the value in the desired base.\n\n\nDefault: on.\n\nPackage documentation: [stringintconv](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv)\n\n<a id='stringsbuilder'></a>\n## `stringsbuilder`: replace += with strings.Builder\n\nThis analyzer replaces repeated string += string concatenation operations with calls to Go 1.10's strings.Builder.\n\nFor example:\n\n\tvar s = \"[\"\n\tfor x := range seq {\n\t\ts += x\n\t\ts += \".\"\n\t}\n\ts += \"]\"\n\tuse(s)\n\nis replaced by:\n\n\tvar s strings.Builder\n\ts.WriteString(\"[\")\n\tfor x := range seq {\n\t\ts.WriteString(x)\n\t\ts.WriteString(\".\")\n\t}\n\ts.WriteString(\"]\")\n\tuse(s.String())\n\nThis avoids quadratic memory allocation and improves performance.\n\nThe analyzer requires that all references to s before the final uses are += operations. To avoid warning about trivial cases, at least one must appear within a loop. The variable s must be a local variable, not a global or parameter.\n\nAll uses of the finished string must come after the last += operation. Each such use will be replaced by a call to strings.Builder's String method. (These may appear within an intervening loop or function literal, since even if s.String() is called repeatedly, it does not allocate memory.)\n\nOften the addend is a call to fmt.Sprintf, as in this example:\n\n\tvar s string\n\tfor x := range seq {\n\t\ts += fmt.Sprintf(\"%v\", x)\n\t}\n\nwhich, once the suggested fix is applied, becomes:\n\n\tvar s strings.Builder\n\tfor x := range seq {\n\t\ts.WriteString(fmt.Sprintf(\"%v\", x))\n\t}\n\nThe WriteString call can be further simplified to the more efficient fmt.Fprintf(&s, \"%v\", x), avoiding the allocation of an intermediary. However, stringsbuilder does not perform this simplification; it requires staticcheck analyzer QF1012. (See [https://go.dev/issue/76918](https://go.dev/issue/76918).)\n\n\nDefault: on.\n\nPackage documentation: [stringsbuilder](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringbuilder)\n\n<a id='stringscut'></a>\n## `stringscut`: replace strings.Index etc. with strings.Cut\n\nThis analyzer replaces certain patterns of use of [strings.Index](/strings#Index) and string slicing by [strings.Cut](/strings#Cut), added in go1.18.\n\nFor example:\n\n\tidx := strings.Index(s, substr)\n\tif idx >= 0 {\n\t    return s[:idx]\n\t}\n\nis replaced by:\n\n\tbefore, _, ok := strings.Cut(s, substr)\n\tif ok {\n\t    return before\n\t}\n\nAnd:\n\n\tidx := strings.Index(s, substr)\n\tif idx >= 0 {\n\t    return\n\t}\n\nis replaced by:\n\n\tfound := strings.Contains(s, substr)\n\tif found {\n\t    return\n\t}\n\nIt also handles variants using [strings.IndexByte](/strings#IndexByte) instead of Index, or the bytes package instead of strings.\n\nFixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.\n\n\nDefault: on.\n\nPackage documentation: [stringscut](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscut)\n\n<a id='stringscutprefix'></a>\n## `stringscutprefix`: replace HasPrefix/TrimPrefix with CutPrefix\n\nThe stringscutprefix analyzer simplifies a common pattern where code first checks for a prefix with \\`strings.HasPrefix\\` and then removes it with \\`strings.TrimPrefix\\`. It replaces this two-step process with a single call to \\`strings.CutPrefix\\`, introduced in Go 1.20. The analyzer also handles the equivalent functions in the \\`bytes\\` package.\n\nFor example, this input:\n\n\tif strings.HasPrefix(s, prefix) {\n\t    use(strings.TrimPrefix(s, prefix))\n\t}\n\nis fixed to:\n\n\tif after, ok := strings.CutPrefix(s, prefix); ok {\n\t    use(after)\n\t}\n\nThe analyzer also offers fixes to use CutSuffix in a similar way. This input:\n\n\tif strings.HasSuffix(s, suffix) {\n\t    use(strings.TrimSuffix(s, suffix))\n\t}\n\nis fixed to:\n\n\tif before, ok := strings.CutSuffix(s, suffix); ok {\n\t    use(before)\n\t}\n\n\nDefault: on.\n\nPackage documentation: [stringscutprefix](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscutprefix)\n\n<a id='stringsseq'></a>\n## `stringsseq`: replace ranging over Split/Fields with SplitSeq/FieldsSeq\n\nThe stringsseq analyzer improves the efficiency of iterating over substrings. It replaces\n\n\tfor range strings.Split(...)\n\nwith the more efficient\n\n\tfor range strings.SplitSeq(...)\n\nwhich was added in Go 1.24 and avoids allocating a slice for the substrings. The analyzer also handles strings.Fields and the equivalent functions in the bytes package.\n\n\nDefault: on.\n\nPackage documentation: [stringsseq](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringsseq)\n\n<a id='structtag'></a>\n## `structtag`: check that struct field tags conform to reflect.StructTag.Get\n\nAlso report certain struct tags (json, xml) used with unexported fields.\n\n\nDefault: on.\n\nPackage documentation: [structtag](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/structtag)\n\n<a id='testingcontext'></a>\n## `testingcontext`: replace context.WithCancel with t.Context in tests\n\nThe testingcontext analyzer simplifies context management in tests. It replaces the manual creation of a cancellable context,\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\nwith a single call to t.Context(), which was added in Go 1.24.\n\nThis change is only suggested if the \\`cancel\\` function is not used for any other purpose.\n\n\nDefault: on.\n\nPackage documentation: [testingcontext](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#testingcontext)\n\n<a id='testinggoroutine'></a>\n## `testinggoroutine`: report calls to (*testing.T).Fatal from goroutines started by a test\n\nFunctions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and Skip{,f,Now} methods of \\*testing.T, must be called from the test goroutine itself. This checker detects calls to these functions that occur within a goroutine started by the test. For example:\n\n\tfunc TestFoo(t *testing.T) {\n\t    go func() {\n\t        t.Fatal(\"oops\") // error: (*T).Fatal called from non-test goroutine\n\t    }()\n\t}\n\n\nDefault: on.\n\nPackage documentation: [testinggoroutine](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine)\n\n<a id='tests'></a>\n## `tests`: check for common mistaken usages of tests and examples\n\nThe tests checker walks Test, Benchmark, Fuzzing and Example functions checking malformed names, wrong signatures and examples documenting non-existent identifiers.\n\nPlease see the documentation for package testing in golang.org/pkg/testing for the conventions that are enforced for Tests, Benchmarks, and Examples.\n\n\nDefault: on.\n\nPackage documentation: [tests](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests)\n\n<a id='timeformat'></a>\n## `timeformat`: check for calls of (time.Time).Format or time.Parse with 2006-02-01\n\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm) format. Internationally, \"yyyy-dd-mm\" does not occur in common calendar date standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\n\n\nDefault: on.\n\nPackage documentation: [timeformat](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat)\n\n<a id='unmarshal'></a>\n## `unmarshal`: report passing non-pointer or non-interface values to unmarshal\n\nThe unmarshal analysis reports calls to functions such as json.Unmarshal in which the argument type is not a pointer or an interface.\n\n\nDefault: on.\n\nPackage documentation: [unmarshal](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal)\n\n<a id='unreachable'></a>\n## `unreachable`: check for unreachable code\n\nThe unreachable analyzer finds statements that execution can never reach because they are preceded by a return statement, a call to panic, an infinite loop, or similar constructs.\n\n\nDefault: on.\n\nPackage documentation: [unreachable](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable)\n\n<a id='unsafefuncs'></a>\n## `unsafefuncs`: replace unsafe pointer arithmetic with function calls\n\nThe unsafefuncs analyzer simplifies pointer arithmetic expressions by replacing them with calls to helper functions such as unsafe.Add, added in Go 1.17.\n\nExample:\n\n\tunsafe.Pointer(uintptr(ptr) + uintptr(n))\n\nwhere ptr is an unsafe.Pointer, is replaced by:\n\n\tunsafe.Add(ptr, n)\n\n\nDefault: on.\n\nPackage documentation: [unsafefuncs](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs)\n\n<a id='unsafeptr'></a>\n## `unsafeptr`: check for invalid conversions of uintptr to unsafe.Pointer\n\nThe unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer to convert integers to pointers. A conversion from uintptr to unsafe.Pointer is invalid if it implies that there is a uintptr-typed word in memory that holds a pointer value, because that word will be invisible to stack copying and to the garbage collector.\n\n\nDefault: on.\n\nPackage documentation: [unsafeptr](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr)\n\n<a id='unusedfunc'></a>\n## `unusedfunc`: check for unused functions, methods, etc\n\nThe unusedfunc analyzer reports functions and methods that are never referenced outside of their own declaration.\n\nA function is considered unused if it is unexported and not referenced (except within its own declaration).\n\nA method is considered unused if it is unexported, not referenced (except within its own declaration), and its name does not match that of any method of an interface type declared within the same package.\n\nThe tool may report false positives in some situations, for example:\n\n  - for a declaration of an unexported function that is referenced from another package using the go:linkname mechanism, if the declaration's doc comment does not also have a go:linkname comment.\n\n    (Such code is in any case strongly discouraged: linkname annotations, if they must be used at all, should be used on both the declaration and the alias.)\n\n  - for compiler intrinsics in the \"runtime\" package that, though never referenced, are known to the compiler and are called indirectly by compiled object code.\n\n  - for functions called only from assembly.\n\n  - for functions called only from files whose build tags are not selected in the current build configuration.\n\nSince these situations are relatively common in the low-level parts of the runtime, this analyzer ignores the standard library. See [https://go.dev/issue/71686](https://go.dev/issue/71686) and [https://go.dev/issue/74130](https://go.dev/issue/74130) for further discussion of these limitations.\n\nThe unusedfunc algorithm is not as precise as the golang.org/x/tools/cmd/deadcode tool, but it has the advantage that it runs within the modular analysis framework, enabling near real-time feedback within gopls.\n\nThe unusedfunc analyzer also reports unused types, vars, and constants. Enums--constants defined with iota--are ignored since even the unused values must remain present to preserve the logical ordering.\n\n\nDefault: on.\n\nPackage documentation: [unusedfunc](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc)\n\n<a id='unusedparams'></a>\n## `unusedparams`: check for unused parameters of functions\n\nThe unusedparams analyzer checks functions to see if there are any parameters that are not being used.\n\nTo ensure soundness, it ignores:\n\n  - \"address-taken\" functions, that is, functions that are used as a value rather than being called directly; their signatures may be required to conform to a func type.\n  - exported functions or methods, since they may be address-taken in another package.\n  - unexported methods whose name matches an interface method declared in the same package, since the method's signature may be required to conform to the interface type.\n  - functions with empty bodies, or containing just a call to panic.\n  - parameters that are unnamed, or named \"\\_\", the blank identifier.\n\nThe analyzer suggests a fix of replacing the parameter name by \"\\_\", but in such cases a deeper fix can be obtained by invoking the \"Refactor: remove unused parameter\" code action, which will eliminate the parameter entirely, along with all corresponding arguments at call sites, while taking care to preserve any side effects in the argument expressions; see [https://github.com/golang/tools/releases/tag/gopls%2Fv0.14](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14).\n\nThis analyzer ignores generated code.\n\n\nDefault: on.\n\nPackage documentation: [unusedparams](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams)\n\n<a id='unusedresult'></a>\n## `unusedresult`: check for unused results of calls to some functions\n\nSome functions like fmt.Errorf return a result and have no side effects, so it is always a mistake to discard the result. Other functions may return an error that must not be ignored, or a cleanup operation that must be called. This analyzer reports calls to functions like these when the result of the call is ignored.\n\nThe set of functions may be controlled using flags.\n\n\nDefault: on.\n\nPackage documentation: [unusedresult](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult)\n\n<a id='unusedvariable'></a>\n## `unusedvariable`: check for unused variables and suggest fixes\n\n\n\nDefault: on.\n\nPackage documentation: [unusedvariable](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable)\n\n<a id='unusedwrite'></a>\n## `unusedwrite`: checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and arrays that are never read. Specifically, when a struct object or an array is copied, its elements are copied implicitly by the compiler, and any element write to this copy does nothing with the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\n\tfunc f(input []T) {\n\t\tfor i, v := range input {  // v is a copy\n\t\t\tv.x = i  // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}\n\n\nDefault: on.\n\nPackage documentation: [unusedwrite](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite)\n\n<a id='waitgroup'></a>\n## `waitgroup`: check for misuses of sync.WaitGroup\n\nThis analyzer detects mistaken calls to the (\\*sync.WaitGroup).Add method from inside a new goroutine, causing Add to race with Wait:\n\n\t// WRONG\n\tvar wg sync.WaitGroup\n\tgo func() {\n\t        wg.Add(1) // \"WaitGroup.Add called from inside new goroutine\"\n\t        defer wg.Done()\n\t        ...\n\t}()\n\twg.Wait() // (may return prematurely before new goroutine starts)\n\nThe correct code calls Add before starting the goroutine:\n\n\t// RIGHT\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\t...\n\t}()\n\twg.Wait()\n\n\nDefault: on.\n\nPackage documentation: [waitgroup](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup)\n\n<a id='waitgroupgo'></a>\n## `waitgroupgo`: replace wg.Add(1)/go/wg.Done() with wg.Go\n\nThe waitgroupgo analyzer simplifies goroutine management with \\`sync.WaitGroup\\`. It replaces the common pattern\n\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\t...\n\t}()\n\nwith a single call to\n\n\twg.Go(func(){ ... })\n\nwhich was added in Go 1.25.\n\n\nDefault: on.\n\nPackage documentation: [waitgroupgo](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#waitgroupgo)\n\n<a id='writestring'></a>\n## `writestring`: detect inefficient string concatenation in uses of WriteString\n\nThe writestring analyzer offers to replace a call to WriteString(x + y) by two calls WriteString(x); WriteString(y). This is more efficient because it avoids the additional memory allocation produced by string concatenation; instead we just write each string into the buffer directly.\n\nIt explicitly looks for calls to certain well-known writers such as bytes.Buffer, strings.Builder and bufio.Writer. The analyzer will not suggest a fix for calls to, say, (\\*os.File).WriteString, because for certain kinds of file such as a UDP socket, it could split a single message into two. Similarly it does not offer fixes when the type of the writer is unknown (as in calls to io.WriteString).\n\nFor example:\n\n\tfunc f(a string, b string) string {\n\t\t var s strings.Builder\n\t\t s.WriteString(a+b)\n\t\t return s.String()\n\t}\n\nwould become:\n\n\tfunc f(a string, b string) string {\n\t\tvar s strings.Builder\n\t\ts.WriteString(a)\n\t\ts.WriteString(b)\n\t\treturn s.String()\n\t}\n\n\nDefault: on.\n\nPackage documentation: [writestring](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/writestring)\n\n<a id='yield'></a>\n## `yield`: report calls to yield where the result is ignored\n\nAfter a yield function returns false, the caller should not call the yield function again; generally the iterator should return promptly.\n\nThis example fails to check the result of the call to yield, causing this analyzer to report a diagnostic:\n\n\tyield(1) // yield may be called again (on L2) after returning false\n\tyield(2)\n\nThe corrected code is either this:\n\n\tif yield(1) { yield(2) }\n\nor simply:\n\n\t_ = yield(1) && yield(2)\n\nIt is not always a mistake to ignore the result of yield. For example, this is a valid single-element iterator:\n\n\tyield(1) // ok to ignore result\n\treturn\n\nIt is only a mistake when the yield call that returned false may be followed by another call.\n\n\nDefault: on.\n\nPackage documentation: [yield](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/yield)\n\n<!-- END Analyzers: DO NOT MANUALLY EDIT THIS SECTION -->\n"
  },
  {
    "path": "gopls/doc/assets/assets.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package assets is an empty package to appease \"go test ./...\",\n// as run by our CI builders, which doesn't like an empty module.\npackage assets\n"
  },
  {
    "path": "gopls/doc/assets/go.mod",
    "content": "// This module contains no Go code, but serves to carve out a hole in\n// its parent module to avoid bloating it with large image files that\n// would otherwise be downloaded by \"go install golang.org/x/tools/gopls@latest\".\n\nmodule golang.org/x/tools/gopls/doc/assets\n\ngo 1.25.0\n"
  },
  {
    "path": "gopls/doc/codelenses.md",
    "content": "---\ntitle: \"Gopls: Code lenses\"\n---\n\nA \"code lens\" is a command associated with a range of a source file.\nThe VS Code manual describes code lenses as\n\"[actionable, contextual information, interspersed in your source\ncode](https://code.visualstudio.com/blogs/2017/02/12/code-lens-roundup)\".\nThe LSP [`textDocument/codeLens`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeLens) operation requests the\ncurrent set of code lenses for a file.\n\nGopls generates code lenses from a number of sources.\nThis document describes them.\n\nThey can be enabled and disabled using the\n[`codelenses`](settings.md#codelenses) setting.\nTheir features are subject to change.\n\nClient support:\n- **VS Code**: Code Lenses appear as small text links above a line of source code.\n- **Emacs + eglot**: Not supported, but prototype exists at https://github.com/joaotavora/eglot/pull/71.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls codelens`. For example, `gopls codelens -exec file.go:123 \"run test\"` runs the test at the specified line.\n\n\n<!-- This portion is generated by doc/generate from the ../internal/settings package. -->\n<!-- BEGIN Lenses: DO NOT MANUALLY EDIT THIS SECTION -->\n## `generate`: Run `go generate`\n\n\nThis codelens source annotates any `//go:generate` comments\nwith commands to run `go generate` in this directory, on\nall directories recursively beneath this one.\n\nSee [Generating code](https://go.dev/blog/generate) for\nmore details.\n\n\nDefault: on\n\nFile type: Go\n\n## `regenerate_cgo`: Re-generate cgo declarations\n\n\nThis codelens source annotates an `import \"C\"` declaration\nwith a command to re-run the [cgo\ncommand](https://pkg.go.dev/cmd/cgo) to regenerate the\ncorresponding Go declarations.\n\nUse this after editing the C code in comments attached to\nthe import, or in C header files included by it.\n\n\nDefault: on\n\nFile type: Go\n\n## `test`: Run tests and benchmarks\n\n\nThis codelens source annotates each `Test` and `Benchmark`\nfunction in a `*_test.go` file with a command to run it.\n\nThis source is off by default because VS Code has\na client-side custom UI for testing, and because progress\nnotifications are not a great UX for streamed test output.\nSee:\n- golang/go#67400 for a discussion of this feature.\n- https://github.com/joaotavora/eglot/discussions/1402\n  for an alternative approach.\n\n\nDefault: off\n\nFile type: Go\n\n## `run_govulncheck`: Run govulncheck (legacy)\n\n\nThis codelens source annotates the `module` directive in a go.mod file\nwith a command to run Govulncheck asynchronously.\n\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\ncomputes the set of functions reachable within your application, including\ndependencies; queries a database of known security vulnerabilities; and\nreports any potential problems it finds.\n\n\nDefault: on\n\nFile type: go.mod\n\n## `tidy`: Tidy go.mod file\n\n\nThis codelens source annotates the `module` directive in a\ngo.mod file with a command to run [`go mod\ntidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures\nthat the go.mod file matches the source code in the module.\n\n\nDefault: on\n\nFile type: go.mod\n\n## `upgrade_dependency`: Update dependencies\n\n\nThis codelens source annotates the `module` directive in a\ngo.mod file with commands to:\n\n- check for available upgrades,\n- upgrade direct dependencies, and\n- upgrade all dependencies transitively.\n\n\nDefault: on\n\nFile type: go.mod\n\n## `vendor`: Update vendor directory\n\n\nThis codelens source annotates the `module` directive in a\ngo.mod file with a command to run [`go mod\nvendor`](https://go.dev/ref/mod#go-mod-vendor), which\ncreates or updates the directory named `vendor` in the\nmodule root so that it contains an up-to-date copy of all\nnecessary package dependencies.\n\n\nDefault: on\n\nFile type: go.mod\n\n## `vulncheck`: Run govulncheck\n\n**This setting is experimental and may be deleted.**\n\n\nThis codelens source annotates the `module` directive in a go.mod file\nwith a command to run govulncheck synchronously.\n\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\ncomputes the set of functions reachable within your application, including\ndependencies; queries a database of known security vulnerabilities; and\nreports any potential problems it finds.\n\n\nDefault: off\n\nFile type: go.mod\n\n<!-- END Lenses: DO NOT MANUALLY EDIT THIS SECTION -->\n"
  },
  {
    "path": "gopls/doc/command-line.md",
    "content": "---\ntitle: \"Gopls: Command-line interface\"\n---\n\nThe `gopls` command provides a number of subcommands that expose much\nof the server's functionality. However, the interface is currently\n**experimental** and **subject to change at any point.**\nIt is not efficient, complete, flexible, or officially supported.\n\nIts primary use is as a debugging aid.\nFor example, this command reports the location of references to the\nsymbol at the specified file/line/column:\n\n```\n$ gopls references ./gopls/main.go:35:8\nLog: Loading packages...\nInfo: Finished loading packages.\n/home/gopher/xtools/go/packages/gopackages/main.go:27:7-11\n/home/gopher/xtools/gopls/internal/cmd/integration_test.go:1062:7-11\n/home/gopher/xtools/gopls/internal/test/integration/bench/bench_test.go:59:8-12\n/home/gopher/xtools/gopls/internal/test/integration/regtest.go:140:8-12\n/home/gopher/xtools/gopls/main.go:35:7-11\n```\n\nSee https://go.dev/issue/63693 for a discussion of its future.\n\nLearn about available commands and flags by running `gopls help`.\n\nPositions within files are specified as `file.go:line:column` triples,\nwhere the line and column start at 1, and columns are measured in\nbytes of the UTF-8 encoding.\nAlternatively, positions may be specified by the byte offset within\nthe UTF-8 encoding of the file, starting from zero, for example\n`file.go:#1234`.\n(When working in non-ASCII files, beware that your editor may report a\nposition's offset within its file using a different measure such as\nUTF-16 codes, Unicode code points, or graphemes).\n"
  },
  {
    "path": "gopls/doc/contributing.md",
    "content": "---\ntitle: \"Gopls: Contributing\"\n---\n\nContributions are welcome! However, development is fast moving,\nand we are limited in our capacity to review contributions.\nSo, before sending a CL, please please please:\n\n- **file an issue** for a bug or feature request, if one does not\n  exist already. This allows us to identify redundant requests, or to\n  merge a specific problem into a more general one, and to assess the\n  importance of the problem.\n- **claim it for yourself** by commenting on the issue or, if you are\n  able, by assigning the issue to yourself. This helps us avoid two\n  people working on the same problem.\n- **propose an implementation plan** in the issue tracker for CLs of\n  any complexity. It is much more efficient to discuss the plan at a\n  high level before we start getting bogged down in the details of\n  a code review.\n\nWhen you send a CL, it should include:\n\n- a **CL description** that summarizes the change,\n  motivates why it is necessary,\n  explains it at a high level,\n  contrasts it with more obvious or simpler approaches, and\n  links to relevant issues;\n- **tests** (integration tests or marker tests);\n- **documentation**, for new or modified features; and\n- **release notes**, for new features or significant changes.\n\nDuring code review, please address all reviewer comments.\nSome comments result in straightforward code changes;\nothers demand a more complex response.\nWhen a reviewer asks a question, the best response is\noften not to respond to it directly, but to change the\ncode to avoid raising the question,\nfor example by making the code self-explanatory.\nIt's fine to disagree with a comment,\npoint out a reviewer's mistake,\nor offer to address a comment in a follow-up change,\nleaving a `TODO` comment in the current CL.\nBut please don't dismiss or quietly ignore a comment without action,\nas it may lead reviewers to repeat themselves,\nor to serious problems being neglected.\n\nFor more detail, see the Go project's\n[contribution guidelines](https://golang.org/doc/contribute.html).\n\n## Finding issues\n\nAll `gopls` issues are labeled as such (see the [`gopls` label][issue-gopls]).\nIssues that are suitable for contributors are additionally tagged with the\n[`help-wanted` label][issue-wanted].\n\nBefore you begin working on an issue, please leave a comment that you are\nclaiming it.\n\n## Getting started\n\n[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools/gopls/internal)](https://pkg.go.dev/golang.org/x/tools/gopls/internal)\n\nMost of the `gopls` logic is in the `golang.org/x/tools/gopls/internal` directory.\nSee [design/implementation.md](./design/implementation.md) for an overview of the code organization.\n\n## Build\n\nTo build a version of `gopls` with your changes applied:\n\n```bash\ncd /path/to/tools/gopls\ngo install\n```\n\nTo confirm that you are testing with the correct `gopls` version, check that\nyour `gopls` version looks like this:\n\n```bash\n$ gopls version\ngolang.org/x/tools/gopls master\n    golang.org/x/tools/gopls@(devel)\n```\n\n## Getting help\n\nThe best way to contact the gopls team directly is via the\n[#gopls-dev](https://app.slack.com/client/T029RQSE6/CRWSN9NCD) channel on the\ngophers slack. Please feel free to ask any questions about your contribution or\nabout contributing in general.\n\n\n## Error handling\n\nIt is important for the user experience that, whenever practical,\nminor logic errors in a particular feature don't cause the server to\ncrash.\n\nThe representation of a Go program is complex. The import graph of\npackage metadata, the syntax trees of parsed files, and their\nassociated type information together form a huge API surface area.\nEven when the input is valid, there are many edge cases to consider,\nand this grows by an order of magnitude when you consider missing\nimports, parse errors, and type errors.\n\nWhat should you do when your logic must handle an error that you\nbelieve \"can't happen\"?\n\n- If it's possible to return an error, then use the `bug.Errorf`\n  function to return an error to the user, but also record the bug in\n  gopls' cache so that it is less likely to be ignored.\n\n- If it's safe to proceed, you can call `bug.Reportf` to record the\n  error and continue as normal.\n\n- If there's no way to proceed, call `bug.Fatalf` to record the error\n  and then stop the program with `log.Fatalf`. You can also use\n  `bug.Panicf` if there's a chance that a recover handler might save\n  the situation.\n\n- Only if you can prove locally that an error is impossible should you\n  call `log.Fatal`. If the error may happen for some input, however\n  unlikely, then you should use one of the approaches above. Also, if\n  the proof of safety depends on invariants broadly distributed across\n  the code base, then you should instead use `bug.Panicf`.\n\nNote also that panicking is preferable to `log.Fatal` because it\nallows VS Code's crash reporting to recognize and capture the stack.\n\nBugs reported through `bug.Errorf` and friends are retrieved using the\n`gopls bug` command, which opens a GitHub Issue template and populates\nit with a summary of each bug and its frequency.\nThe text of the bug is rather fastidiously printed to stdout to avoid\nsharing user names and error message strings (which could contain\nproject identifiers) with GitHub.\nUsers are invited to share it if they are willing.\n\n## Testing\n\nThe normal command you should use to run the tests after a change is:\n\n```bash\ngopls$ go test -short ./...\n```\n\n(The `-short` flag skips some slow-running ones. The trybot builders\nrun the complete set, on a wide range of platforms.)\n\nGopls tests are a mix of two kinds.\n\n- [Marker tests](https://golang.org/x/tools/gopls/internal/test/marker) express each test scenario\n  in a standalone text file that contains the target .go, go.mod, and\n  go.work files, in which special annotations embedded in comments\n  drive the test. These tests are generally easy to write and fast\n  to iterate, but have limitations on what they can express.\n\n- [Integration tests](https://golang.org/x/tools/gopls/internal/test/integration) are regular Go\n  `func Test(*testing.T)` functions that make a series of calls to an\n  API for a fake LSP-enabled client editor. The API allows you to open\n  and edit a file, navigate to a definition, invoke other LSP\n  operations, and assert properties about the state.\n\n  Due to the asynchronous nature of the LSP, integration tests make\n  assertions about states that the editor must achieve eventually,\n  even when the program goes wrong quickly, it may take a while before\n  the error is reported as a failure to achieve the desired state\n  within several minutes. We recommend that you set\n  `GOPLS_INTEGRATION_TEST_TIMEOUT=10s` to reduce the timeout for\n  integration tests when debugging.\n\n  When they fail, the integration tests print the log of the LSP\n  session between client and server. Though verbose, they are very\n  helpful for debugging once you know how to read them.\n\nDon't hesitate to [reach out](#getting-help) to the gopls team if you\nneed help.\n\n### CI\n\nWhen you mail your CL and you or a fellow contributor assigns the\n`Run-TryBot=1` label in Gerrit, the\n[TryBots](https://golang.org/doc/contribute.html#trybots) will run tests in\nboth the `golang.org/x/tools` and `golang.org/x/tools/gopls` modules, as\ndescribed above.\n\nFurthermore, an additional \"gopls-CI\" pass will be run by _Kokoro_, which is a\nJenkins-like Google infrastructure for running Dockerized tests. This allows us\nto run gopls tests in various environments that would be difficult to add to\nthe TryBots. Notably, Kokoro runs tests on\n[older Go versions](index.md#supported-go-versions) that are no longer supported\nby the TryBots. Per that policy, support for these older Go versions is\nbest-effort, and test failures may be skipped rather than fixed.\n\nKokoro runs are triggered by the `Run-TryBot=1` label, just like TryBots, but\nunlike TryBots they do not automatically re-run if the \"gopls-CI\" result is\nremoved in Gerrit. To force a re-run of the Kokoro CI on a CL containing the\n`Run-TryBot=1` label, you can reply in Gerrit with the comment \"kokoro rerun\".\n\n## Debugging\n\nThe easiest way to debug your change is to run a single `gopls` test with a\ndebugger.\n\nSee also [Troubleshooting](troubleshooting.md#troubleshooting).\n\n### Debug Server\n\nGopls includes a built-in debug server that exposes metrics, traces, and\nprofiling information. Start it by passing the `-debug` flag, e.q. `gopls serve -debug=localhost:6060`. When using `:0`, gopls logs the assigned address to stderr.\n\nYou can also start the server in a running gopls process by executing a StartDebugging LSP command. In VS Code this is bound to the \"Go: Start language server maintainer's interface\" command.\n\n**Key endpoints:**\n\n| Endpoint | Description |\n|----------|-------------|\n| `/` | Overview of caches, sessions and clients |\n| `/rpc/` | RPC statistics with latency and status codes |\n| `/trace/` | Recent spans and operation traces |\n| `/metrics/` | Prometheus-compatible metrics |\n| `/memory` | Memory usage statistics |\n| `/debug/pprof/` | Go pprof profiling |\n\n### OpenTelemetry\n\nGopls supports periodical export of traces and metrics by POSTing JSON messages to an OpenTelemetry collector process such as Jaeger/Grafana. \nUse the `-otel` flag to specify the collector endpoint to enable exporting:\n\n```bash\ngopls serve -otel=http://localhost:4318\n```\n\nThe data are discarded if no collector is listening at that address.\n\nFor example, to view traces locally with Jaeger:\n```sh\n$ podman run --rm --name jaeger \\\n  -p 16686:16686 \\\n  -p 4318:4318 \\\n  jaegertracing/all-in-one:1.76.0\n```\n\nThen open http://localhost:16686 to view traces.\n\n\n[issue-gopls]: https://github.com/golang/go/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Agopls \"gopls issues\"\n[issue-wanted]: https://github.com/golang/go/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Agopls+label%3A\"help+wanted\" \"help wanted\"\n\n## Documentation\n\nEach CL that adds or changes a feature should include, in addition to\na test that exercises the new behavior:\n\n- a **release note** that briefly explains the change, and\n- **comprehensive documentation** in the [index of features](features/).\n\nThe release note should go in the file named for the forthcoming\nrelease, for example [release/v0.16.0.md](release/v0.16.0.md). (Create\nthe file if your feature is the first to be added after a release.)\n\n## Design documentation\n\n* [Integrating `gopls` with an editor](design/integrating.md)\n* [Design requirements and decisions](design/design.md)\n* [Implementation overview](design/implementation.md)\n"
  },
  {
    "path": "gopls/doc/daemon.md",
    "content": "---\ntitle: \"Gopls: Running as a daemon\"\n---\n\n**Note: this feature is new. If you encounter bugs, please [file an\nissue](troubleshooting.md#file-an-issue).**\n\nIf you just want to try this out, skip ahead to the [quickstart](#quickstart).\n\n## Background: gopls execution modes\n\nGopls was originally implemented as an LSP sidecar: a process started by\neditors or editor plugins, and communicated with using jsonrpc 2.0 over\nstdin/stdout. By executing as a stateful process, gopls can maintain a\nsignificant amount of cache and can eagerly perform analysis on the source code\nbeing edited.\n\nThis execution mode does not work as well when there are many separate editor\nprocesses or when editor processes are short-lived, as is often the case for\nusers of non-IDE editors such as Vim or Emacs. Having many processes means\nhaving many caches, consuming a significant amount of system resources. Using\nshort-lived sessions means paying a start-up cost each time a session is\ncreated.\n\nTo support these types of workflows, a new mode of gopls execution is supported\nwherein a single, persistent, shared gopls \"daemon\" process is responsible for\nmanaging all gopls sessions. In this mode, editors still start a gopls sidecar,\nbut this sidecar merely acts as a thin \"forwarder\", responsible for forwarding\nthe LSP to the shared gopls instance and recording metrics, logs, and rpc\ntraces.\n\n## Quickstart\n\nTo use a shared gopls instance you must either manage the daemon process\nyourself, or let the gopls forwarder processes start the shared daemon as\nneeded.\n\n### Running with `-remote=auto`\n\nAutomatic management of the daemon is easiest, and can be done by passing the\nflag `-remote=auto` to the gopls process started by your editor. This will\ncause this process to auto-start the gopls daemon if needed, connect to it, and\nforward the LSP. For example, here is a reasonable gopls invocation, that sets\nsome additional flags for easier [debugging](#debugging):\n\n```bash\ngopls -remote=auto -logfile=auto -debug=:0 -remote.debug=:0 -rpc.trace\n```\n\nNote that the shared gopls process will automatically shut down after one\nminute with no connected clients.\n\n### Managing the daemon manually\n\nTo manage the gopls daemon process via external means rather than having the\nforwarders manage it, you must start a gopls daemon process with the\n`-listen=<addr>` flag, and then pass `-remote=<addr>` to the gopls processes\nstarted by your editor.\n\nFor example, to host the daemon on the TCP port `37374`, do:\n\n```bash\ngopls -listen=:37374 -logfile=auto -debug=:0\n```\n\nAnd then from the editor, run\n\n```bash\ngopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace\n```\n\nIf you are on a POSIX system, you can also use unix domain sockets by prefixing\nthe flag values with `unix;`. For example:\n\n```bash\ngopls -listen=\"unix;/tmp/gopls-daemon-socket\" -logfile=auto -debug=:0\n```\n\nAnd connect via:\n\n```bash\ngopls -remote=\"unix;/tmp/gopls-daemon-socket\" -logfile=auto -debug=:0 -rpc.trace\n```\n\n(Note that these flag values MUST be enclosed in quotes, because ';' is a\nspecial shell character. For this reason, this syntax is subject to change in\nthe future.)\n\n## Debugging\n\nDebugging a shared gopls session is more complicated than a singleton session,\nbecause there are now two gopls processes involved with handling the LSP. Here\nare some tips:\n\n### Finding logfiles and debug addresses\n\nWhen running in daemon mode, you can use the `gopls inspect sessions` command\nto find the logfile and debug port for your gopls daemon instance (as well as\nfor all its connected clients). By default, this inspects the default daemon\n(i.e. `-remote=auto`). To inspect a different daemon, use the `-remote` flag\nexplicitly: `gopls -remote=localhost:12345 inspect sessions`.\n\nThis works whether or not you have enabled `-remote.debug`.\n\n### Traversing debug pages\n\nWhen `-debug=:0` is passed to gopls, it runs a webserver that serves stateful\ndebug pages (see [troubleshooting.md](troubleshooting.md)). You can find the\nactual port hosting these pages by either using the `gopls inspect sessions`\ncommand, or by checking the start of the logfile -- it will be one of the first\nlog messages. For example, if using `-logfile=auto`, find the debug address by\nchecking `head /tmp/gopls-<pid>.log`.\n\nBy default, the gopls daemon is not started with `-debug`. To enable it, set\nthe `-remote.debug` flag on the forwarder instance, so that it invokes gopls\nwith `-debug` when starting the daemon.\n\nThe debug pages of the forwarder process will have a link to the debug pages of\nthe daemon server process. Correspondingly, the debug pages of the daemon\nprocess will have a link to each of its clients.\n\nThis can help you find metrics, traces, and log files for all of the various\nservers and clients.\n\n### Using logfiles\n\nThe gopls daemon is started with logging disabled by default. To customize\nthis, pass `-remote.logfile` to the gopls forwarder. Using\n`-remote.logfile=auto`, the daemon will log to a default location (on posix\nsystems: `/tmp/gopls-daemon-<pid>.log`).\n\nThe gopls daemon does not log session-scoped messages: those are instead\nreflected back to the forwarder so that they can be accessed by the editor.\nDaemon logs will only contain global messages, for example logs when sessions\nconnect and disconnect.\n\nIt is recommended to start the forwarder gopls process with `-rpc.trace`, so\nthat its logfile will contain rpc trace logs specific to the LSP session.\n\n## Using multiple shared gopls instances\n\nThere may be environments where it is desirable to have more than one shared\ngopls instance. If managing the daemon manually, this can be done by simply\nchoosing different `-listen` addresses for each distinct daemon process.\n\nOn POSIX systems, there is also support for automatic management of distinct\nshared gopls processes: distinct daemons can be selected by passing\n`-remote=\"auto;<id>\"`. Any gopls forwarder passing the same value for `<id>`\nwill use the same shared daemon.\n\n## FAQ\n\n**Q: Why am I not saving as much memory as I expected when using a shared gopls?**\n\nA: As described in [implementation.md](design/implementation.md), gopls has a\nconcept of view/session/cache. Each session and view map onto exactly one\neditor session (because they contain things like edited but unsaved buffers).\nThe cache contains things that are independent of any editor session, and can\ntherefore be shared.\n\nWhen, for example, three editor session are sharing a single gopls process,\nthey will share the cache but will each have their own session and view. The\nmemory savings in this mode, when compared to three separate gopls processes,\ncorresponds to the amount of cache overlap across sessions.\n\nBecause this hasn't mattered much in the past, it is likely that there is state\nthat can be moved out of the session/view, and into the cache, thereby\nincreasing the amount of memory savings in the shared mode.\n\n**Q: How do I customize the daemon instance when using `-remote=auto`?**\n\nThe daemon may be customized using flags of the form `-remote.*` on the\nforwarder gopls. This causes the forwarder to invoke gopls with these settings\nwhen starting the daemon. As of writing, we expose the following configuration:\n\n* `-remote.logfile`: the location of the daemon logfile\n* `-remote.debug`: the daemon's debug address\n* `-remote.listen.timeout`: the amount of time the daemon should wait for new\n  connections while there are no current connections, before shutting down.\n  Must be set to a valid `time.Duration` (e.g. `30s` or `5m`). If `0`, listen\n  indefinitely. Default: `1m`.\n\nNote that once the daemon is already running, setting these flags will not\nchange its configuration. These flags only matter for the forwarder process\nthat actually starts the daemon.\n"
  },
  {
    "path": "gopls/doc/default.tmpl",
    "content": "{{- /* For golang.org/x/website/cmd/golangorg */ -}}\n{{define \"layout\"}}\n{{doclayout .}}\n{{end}}\n"
  },
  {
    "path": "gopls/doc/design/design.md",
    "content": "---\ntitle: \"Gopls: Design\"\n---\n\n## _A note from the future_\n\nWhat follows below is the original design document for gopls, aggregated from\nvarious sources spanning 2018 and 2019. Since then, all of the features listed\nbelow have been implemented, along with many others. The first two goals have\nbeen achieved: gopls is a full implementation of the LSP, and the default\nbackend for VS Code Go and many other editors. The third goal has only been\npartially realized: while gopls has gained many features, it is not extensible\nin the sense used in this document: the only way to extend gopls is to modify\ngopls. The fourth goal is not achieved: while some notable companies are able\nto use gopls with Bazel, the experience is subpar, and the Go command is the\nonly officially supported build system.\n\nOn the other hand, two of the explicit non-goals have been reconsidered. One is\nminor: syntax highlighting is now supported in the LSP by way of semantic\ntokens. The other is major: as gopls gained popularity, it became apparent that\nits memory footprint was a problem. The size of developer workspaces was\nincreasing faster than the RAM available in typically development environments\n(particularly with containerized development). Gopls now uses a hybrid of\non-disk indexes and in-memory caches, described in more detail in our\n[blog post on scalability](https://go.dev/blog/gopls-scalability).\n\nNotably, in anticipating difficulties this doc turned out to be prescient.\nGopls has indeed struggled against the core standary library packages upon\nwhich it is built, and its user experience is still limited by the LSP.\nNevertheless, sticking with the standard library and LSP was the right\napproach, as despite our small team these decisions have helped gopls keep up\nwith the evolving Go language (i.e. generics), and to integrate with many new\ntext editors.\n\nGopls development continues, more than four years later, with a focus on\nsimplicity, reliability, and extensibility. The new, opt-in\n[Go telemetry](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.0)\nwill help us attain a higher standard of stability in our releases than we've\nbeen able to achieve through Github issues alone. Furthermore, telemetry will\nallow us to focus on high-priority features, and deprecate historical\nworkarounds that burden the codebase. With greater velocity, we look forward\nto working with the community on improved refactoring, static analysis, and\nwhatever else the future brings.\n\n- _Rob Findley (rfindley@google.com), 2023_\n\n## Goals\n\n* `gopls` should **become the default editor backend** for the major editors used by Go programmers, fully supported by the Go team.\n* `gopls` will be a **full implementation of LSP**, as described in the [LSP specification], to standardize as many of its features as possible.\n* `gopls` will be **clean and extensible** so that it can encompass additional features in the future, allowing Go tooling to become best in class once more.\n* `gopls` will **support alternate build systems and file layouts**, allowing Go development to be simpler and more powerful in any environment.\n\n## Context\n\nWhile Go has a number of excellent and useful command-line tools that enhance the developer experience, it has become clear that integrating these tools with IDEs can pose challenges.\n\nSupport of these tools has relied on the goodwill of community members, and they have been put under a large burden of support at times as the language, toolchain and environments change. As a result many tools have ceased to work, have had support problems, or become confusing with forks and replacements, or provided an experience that is not as good as it could be.\nSee the section below on [existing solutions](#existing-solutions) for more problems and details.\n\nThis is fine for tools used occasionally, but for core IDE features, this is not acceptable.\nAutocompletion, jump to definition, formatting, and other such features should always work, as they are key for Go development.\n\nThe Go team will create an editor backend that works in any build system.\nIt will also be able to improve upon the latency of Go tools, since each tool will no longer have to individually run the type-checker on each invocation, instead there will be a long-running process and data can be shared between the definitions, completions, diagnostics, and other features.\n\nBy taking ownership of these tools and packaging them together in the form of gopls, the Go team will ensure that the Go development experience isn’t unnecessarily complicated for Go users.\nHaving one editor backend will simplify the lives of Go developers, the Go team, and the maintainers of Go editor plugins.\n\nSee Rebecca's excellent GopherCon keynote [talk] and [slides] for some more context.\n\n## Non-Goals\n\n* Command line speed\n\n  Although gopls will have a command line mode, it will be optimized for long running and not command responsiveness, as such it may not be the right tool for things like CI systems.\n  For such cases there will have to be an alternate tool using the same underlying libraries for consistency.\n\n* Low memory environments\n\n  In order to do a good job of processing large projects with very low latencies gopls will be holding a lot of information in memory.\n  It is presumed that developers are normally working on systems with significant RAM and this will not be a problem.\n  In general this is upheld by the large memory usage of existing IDE solutions (like IntelliJ)\n\n* Syntax highlighting\n\n  At the moment there is no editor that delegates this functionality to a separate binary, and no standard way of doing it.\n\n## Existing solutions\n\nEvery year the Go team conducts a survey, asking developers about their experiences with the language.\n\nOne question that is asked is “How do you feel about your editor?”.\n\nThe responses told a very negative story. Some categorized quotes:\n\n* Setup\n  * \"Hard to install and configure\"\n  * \"Inadequate documentation\"\n* Performance\n  * \"Performance is very poor\"\n  * \"Pretty slow in large projects\"\n* Reliability\n  * \"Features work one day, but not the next\"\n  * \"Tooling is not updated with new language features\"\n\nEach editor has its own plugin that shells out to a variety of tools, many of which break with new Go releases or because they are no longer maintained.\n\nThe individual tools each have to do the work to understand the code and all its transitive dependencies.\n\nEach feature is a different tool, with a different set of patterns for its command line, a different way to accept input and parse output, a different way of specifying source code locations.\nTo support its existing feature set, VSCode installed 24 different command line tools, many of which have options or forks to configure. When looking at the set of tools that needed to be migrated to modules, across all the editors, there were 63 separate tools.\n\nAll these tools need to understand the code, and they use the same standard libraries to do it. Those libraries are optimized for these kinds of tools, but even so processing that much code takes a lot of time time. Almost none of the tools are capable of returning results within 100ms.\nAs developers type in their editor, multiple of these features need to activate, which means they are not just paying the cost once, but many times. The overall effect is an editing experience that feels sluggish, and features that are either not enabled or sometimes produce results that appear so slowly they are no longer useful when they arrive. This is a problem that increases with the size of the code base, which means it is getting worse over time, and is especially bad for the kinds of large code bases companies are dealing with as they use Go for more major tasks.\n\n## Requirements\n\n### Complete feature set\n\nFor gopls to be considered a success it has to implement the full feature set discussed [below](#Features).\nThis is the set of features that users need in order to feel as productive as they were with the tooling it is replacing. It does not include every feature of previous implementations, there are some features that are almost never used that should be dropped (like guru's pointer analysis) and some other features that do not easily fit and will have to be worked around (replacing the save hook/linter).\n\n### Equivalent or better experience\n\nFor all of those features, the user experience must match or exceed the current one available in all editors.\nThis is an easy statement to make, but a hard one to validate or measure. Many of the possible measures fail to capture the experience.\n\nFor instance, if an attempt was made to measure the latency of a jump to definition call, the results would be fairly consistent from the old godef tool. From the gopls implementation there may be a much larger range of latencies, with the best being orders of magnitude faster, and the worse slightly worse, because gopls attempts to do far more work, but manages to cache it across calls.\n\nOr for a completion call, it might be slower but produce a better first match such that users accept it more often, resulting in an overall better experience.\n\nFor the most part this has to rely on user reports. If users are refusing to switch because the experience is not better, it is clearly not done, if they are switching but most people are complaining, there are probably enough areas that are better to make the switch compelling but other areas which are worse. If most people are switching and either staying silent or being positive, it is probably done. When writing tools, the user is all that matters.\n\n### Solid community of contributors\n\nThe scope and scale of the problem gopls is trying to solve is untenable for the core Go team, it is going to require a strong community to make it all happen.\n\nThis implies the code must be easy to contribute to, and easy for many developers to work on in parallel. The functionality needs to be well decoupled, and have a thorough testing story.\n\n### Latencies that fall within user tolerance\n\nThere has been a lot of research on acceptable latencies for user actions.\n<!-- TODO: research links -->\nThe main result that affects gopls is that feedback in direct response to continuous user actions needs to be under 100ms to be imperceptible, and anything above 200ms aggravates the user.\nThis means in general the aim has to be <100ms for anything that happens as the developer types.\nThere will always be cases where gopls fails to meet this deadline, and there needs to be ways to make the user experience okay in those cases, but in general the point of this deadline is to inform the basic architecture design, any solution that cannot theoretically meet this goal in the long term is the wrong answer.\n\n### Easy to configure\n\nDevelopers are very particular, and have very differing desires in their coding experience. gopls is going to have to support a significant amount of flexibility, in order to meet those desires.\nThe default settings however with no configuration at all must be the one that is best experience for most users, and where possible the features must be flexible without configuration so that the client can easily make the choices about treatment without changing its communication with gopls.\n\n## Difficulties\n\n### Volume of data\n\n<!-- TODO: project sizes -->\n* Small:\n* Medium:\n* Large:\n* Corporate mono-repo: Much much bigger\n\nParsing and type checking large amounts of code is quite expensive, and the converted forms use a lot of space. As gopls has to keep updating this information while the developer types, it needs to manage how it caches the converted forms very carefully to balance memory use vs speed.\n\n### Cache invalidation\n\nThe basic unit of operation for the type checking is the package, but the basic unit of operation for an editor is the file.\ngopls needs to be able to map files to packages efficiently, so that when files change it knows which packages need to be updated (along with any other packages that transitively depended on them).\nThis is made especially difficult by the fact that changing the content of a file can modify which packages it is considered part of (either by changing the package declaration or the build tags), a file can be in more than one package, and changes can be made to files without using the editor, in which case it will not notify us of the changes.\n\n### Inappropriate core functionality\n\nThe base libraries for Go (things like [go/token], [go/ast] and [go/types]) are all designed for compiler-like applications.\nThey tend to worry more about throughput than memory use, they have structures that are intended to grow and then be thrown away at program exit, and they are not designed to keep going in the presence of errors in the source they are handling.\nThey also have no abilities to do incremental changes.\n\nMaking a long running service work well with those libraries is a very large challenge, but writing new libraries would be far more work, and cause a significant long term cost as both sets of libraries would have to be maintained. Right now it is more important to get a working tool into the hands of users. In the long term this decision may have to be revisited, new low level libraries may be the only way to keep pushing the capabilities forwards.\n\n### Build system capabilities\n\ngopls is supposed to be build system agnostic, but it must use the build system to discover how files map to packages. When it tries to do so, even when the functionality is the same, the costs (in time, CPU and memory) are very different, and can significantly impact the user experience. Designing how gopls interacts with the build system to try to minimize or hide these differences is hard.\n\n### Build tags\n\nThe build tag system in Go is quite powerful, and has many use cases. Source files can exclude themselves using powerful boolean logic on the set of active tags.\nIt is however designed for specifying the set of active tags on the command line, and the libraries are all designed to cope with only one valid combination at a time. There is also no way to work out the set of valid combinations.\n\nType checking a file requires knowledge of all the other files in the same package, and that set of files is modified by the build tags. The set of exported identifiers of a package is also affected by which files are in the package, and thus its build tags.\n\nThis means that even for files or packages that have no build tag controls it is not possible to produce correct results without knowing the set of build tags to consider.\nThis makes it very hard to produce useful results when viewing a file.\n\n### Features not supported by LSP\n\nThere are some things it would be good to be able to do that do not fit easily into the existing LSP protocol.\nFor instance, displaying control flow information, automatic struct tags, complex refactoring...\n\nEach feature will have to be considered carefully, and either propose a change to LSP, or add a way to have gopls specific extensions to the protocol that are still easy to use in all the editor plugins.\n\nTo avoid these at the start, only core LSP features will be implemented, as they are sufficient to meet the baseline requirements anyway, but the potential features need to be kept in mind in the core architecture.\n\n### Distribution\n\nMaking sure that users are using the right version of gopls is going to be a problem. Each editor plugin is probably going to install the tools in its own way, some will choose to install it system wide, some will keep their own copy.\n\nBecause it is a brand new tool, it will be changing rapidly. If users are not informed they are on an old version they will be experiencing problems that have already been fixed, which is worse for them, and then probably reporting them, which wastes time for the gopls team. There needs to be a mechanism for gopls to check if is up to date, and a recommended way to install an up to date version.\n\n### Debugging user problems\n\ngopls is essentially a very stateful long running server on the developer's machine. Its basic operation is affected by many things, from the users environment to the contents of the local build cache. The data it is operating on is often a confidential code base that cannot be shared.\nAll of these things make it hard for users to report a bug usefully, or create a minimal reproduction.\n\nThere needs to be easy ways for users to report what information they can, and ways to attempt to reproduce problems without their entire state. This is also needed to produce regression tests.\n\n## Basic design decisions\n\nThere are some fundamental architecture decisions that affect much of the rest of the design of the tool, making fundamental trade offs that impact the user experience.\n\n### Process lifetime: *managed by the editor*\n\nProcessing a large code base to fully type check and then analyze it within the latency requirements is not feasible, and is one of the primary problems with the existing solutions. This remains true even if the computed information was cached on disk, as running analyzers and type checkers ends up requiring the full AST of all files in the dependency graph.\nIt is theoretically possible to do better, but only with a major re-write of the existing parsing and type checking libraries, something that is not feasible at this time.\n\nThis implies that gopls should be a long running process, that is able to cache and pre-calculate results in memory so that when a request arrives it can produce the answer much faster.\n\nIt could run as a daemon on the user's machine, but there are a lot of issues with managing a daemon. It may well be the right choice in the long term, and it should be allowed for in the fundamental architecture design, but to start with it will instead have a process that lasts as long as the editor that starts it, and that can easily be restarted.\n\n### Caching: *in memory*\n\nPersistent disk caches are very expensive to maintain, and require solving a lot of extra problems.\nAlthough building the information required is expensive compared to the latencies required of the requests, it is fairly minor compared to the startup times of an editor, so it is expected that rebuilding the information when gopls is restarted will be acceptable.\n\nThe advantage gained from this is that gopls becomes stateless across restarts which means if it has issues or gets its state confused, a simple restart will often fix the problem.\nIt also means that when users report problems, the entire state of the on disk cache is not needed to diagnose and reproduce the issue.\n\n### Communication: *stdin/stdout JSON*\n\nThe LSP specification defines the JSON messages that are normally used, but it does not define how those message should be sent, and there are implementations of the LSP that do not use JSON (for instance, Protocol buffers are an option).\n\nThe constraints on gopls are that it must be easy to integrate into *every editor* on *all operating systems*, and that it should not have large external dependencies.\n\nJSON is part of the Go standard library, and is also the native language of LSP, so it makes the most sense. By far the best supported communication mechanism is the standard input and output of a process, and the common client implementations all have ways of using [JSON rpc 2] in this mode.  There were no complete and low dependency implementations of this protocol in Go, but it is a fairly small protocol on top of the JSON library that can be implemented with a moderate effort, and would be a generally useful library to have anyway.\n\nIn the future it is expected to run in separated client server mode, so writing it in a way that could use sockets instead of stdin/stdout from the start was the best way to make sure it remained possible. It was also a huge debugging aid to be able to run the gopls server by hand and watch/debug it outside the editor.\n\n### Running other tools: *no*\n\n<!--- TODO: subprocess discuss --->\n\n## Features\n\n<!--TODO(rstambler): Generate a file that lists all of the supported features.-->\n\nThere is a set of features that gopls needs to expose to be a comprehensive IDE solution.\nThe following is the minimum set of features, along with their existing solutions and how they should map to the LSP.\n\n### Introspection\n\nIntrospection features tell developers information about their code while they work. They do not make or suggest changes.\n\n---\nDiagnostics | Static analysis results of the code, including compilation and lint errors\n----------- | ---\nRequires    | Full go/analysis run, which needs full AST, type and SSA information\nLSP         | [`textDocument/publishDiagnostics`]\nPrevious    | `go build`, `go vet`, `golint`, [errcheck], [staticcheck] <!-- TODO: and all the rest -->\n|           | This is one of the most important IDE features, allowing fast turn around without having to run compilers and checkers in the shell. Often used to power problem lists, gutter markers and squiggle underlines in the IDE. <br/> There is some complicated design work to do in order to let users customize the set of checks being run, preferably without having to recompile the main LSP binary.\n\n---\nHover    | Information about the code under the cursor.\n-------- | ---\nRequires | AST and type information for the file and all dependencies\nLSP      | [`textDocument/hover`]\nPrevious | [godoc], [gogetdoc]\n|        | Used when reading code to display information known to the compiler but not always obvious from the code. For instance it may return the types of identifiers, or the documentation.\n\n---\nSignature help | Function parameter information and documentation\n-------------- | ---\nRequires       | AST and type information for the file and all dependencies\nLSP            | [`textDocument/signatureHelp`]\nPrevious       | [gogetdoc]\n|              | As a function call is being typed into code, it is helpful to know the parameters of that call to enable the developer to call it correctly.\n\n### Navigation\n\nNavigation features are designed to make it easier for a developer to find their way round a code base.\n\n---\nDefinition | Select an identifier, and jump to the code where that identifier was defined.\n---------- | ---\nRequires   | Full type information for file and all dependencies\nLSP        | [`textDocument/declaration`]\n|          | [`textDocument/definition`]\n|          | [`textDocument/typeDefinition`]\nPrevious   | [godef] |\n|          | Asking the editor to open the place where a symbol was defined is one of the most commonly used code navigation tools inside an IDE when available. It is especially valuable when exploring an unfamiliar code base.<br/>Due to a limitation of the compiler output, it is not possible to use the binary data for this task (specifically it does not know column information) and thus it must parse from source.\n\n---\nImplementation | Reports the types that implement an interface\n-------------- | ---\nRequires       | Full workspace type knowledge\nLSP            | [`textDocument/implementation`]\nPrevious       | [impl]\n|              | This feature is hard to scale up to large code bases, and is going to take thought to get right. It may be feasible to implemented a more limited form in the meantime.\n\n---\nDocument symbols | Provides the set of top level symbols in the current file.\n---------------- | ---\nRequires         | AST of the current file only\nLSP              | [`textDocument/documentSymbol`]\nPrevious         | [go-outline], [go-symbols]\n|                | Used to drive things like outline mode.\n\n---\nReferences | Find all references to the symbol under the cursor.\n---------- | ---\nRequires   | AST and type information for the **reverse** transitive closure\nLSP        | [`textDocument/references`]\nPrevious   | [guru]\n|          | This requires knowledge of every package that could possible depend on any packages the current file is part of. In the past this has been implemented either by global knowledge, which does not scale, or by specifying a \"scope\" which confused users to the point where they just did not use the tools. gopls is probably going to need a more powerful solution in the long term, but to start with automatically limiting the scope may produce acceptable results. This would probably be the module if known, or some sensible parent directory otherwise.\n\n---\nFolding  | Report logical hierarchies of blocks\n-------- | ---\nRequires | AST of the current file only\nLSP      | [`textDocument/foldingRange`]\nPrevious | [go-outline]\n|        | This is normally used to provide expand and collapse behavior in editors.\n\n---\nSelection | Report regions of logical selection around the cursor\n--------- | ---\nRequires  | AST of the current file only\nLSP       | [`textDocument/selectionRange`]\nPrevious  | [guru]\n|         | Used in editor features like expand selection.\n\n\n### Edit assistance\n\nThese features suggest or apply edits to the code for the user, including refactoring features, for which there are many potential use cases.\nRefactoring is one of the places where Go tools could potentially be very strong, but have not been so far, and thus there is huge potential for improvements in the developer experience.\nThere is not yet a clear understanding of the kinds of refactoring people need or how they should express them however, and there are weaknesses in the LSP protocol around this.\nThis means it may be much more of a research project.\n\n\n---\nFormat   | Fix the formatting of the file\n-------- | ---\nRequires | AST of current file\nLSP      | [`textDocument/formatting`]\n|        | [`textDocument/rangeFormatting`]\n|        | [`textDocument/onTypeFormatting`]\nPrevious | [gofmt], [goimports], [goreturns]\n|        | It will use the standard format package. <br/> Current limitations are that it does not work on malformed code. It may need some very careful changes to the formatter to allow for formatting an invalid AST or changes to force the AST to a valid mode. These changes would improve range and file mode as well, but are basically vital to onTypeFormatting\n\n---\nImports  | Rewrite the imports block automatically to match the symbols used.\n-------- | ---\nRequires | AST of the current file and full symbol knowledge for all candidate packages.\nLSP      | [`textDocument/codeAction`]\nPrevious | [goimports], [goreturns]\n|        | This needs knowledge of packages that are not yet in use, and the ability to find those packages by name. <br/> It also needs exported symbol information for all the packages it discovers. <br/> It should be implemented using the standard imports package, but there may need to be exposed a more fine grained API than just a file rewrite for some of the interactions.\n\n---\nAutocompletion | Makes suggestions to complete the entity currently being typed.\n-------------- | ---\nRequires       | AST and type information for the file and all dependencies<br/> Also full exported symbol knowledge for all packages.\nLSP            | [`textDocument/completion`]\n|              | [`completionItem/resolve`]\nPrevious       | [gocode]\n|              | Autocomplete is one of the most complicated features, and the more it knows the better its suggestions can be. For instance it can autocomplete into packages that are not yet being imported if it has their public symbols. It can make better suggestions of options if it knows what kind of program you are writing. It can suggest better arguments if it knows how you normally call a function. It can suggest entire patterns of code if it knows they are common. Unlike many other features, which have a specific task, and once it is doing that task the feature is done, autocomplete will never be finished. Balancing and improving both the candidates and how they are ranked will be a research problem for a long time to come.\n\n---\nRename   | Rename an identifier\n-------- | ---\nRequires | AST and type information for the **reverse** transitive closure\nLSP      | [`textDocument/rename`]\n|        | [`textDocument/prepareRename`]\nPrevious | golang.org/x/tools/cmd/gorename\n|        | This uses the same information that find references does, with all the same problems and limitations. It is slightly worse because the changes it suggests make it intolerant of incorrect results. It is also dangerous using it to change the public API of a package.\n\n---\nSuggested fixes | Suggestions that can be manually or automatically accepted to change the code\n--------------- | ---\nRequires        | Full go/analysis run, which needs full AST, type and SSA information\nLSP             | [`textDocument/codeAction`]\nPrevious        | N/A\n|               | This is a brand new feature powered by the new go/analysis engine, and it should allow a huge amount of automated refactoring.\n\n[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/\n[talk]: https://www.youtube.com/watch?v=EFJfdWzBHwE\n[slides]: https://github.com/gophercon/2019-talks/blob/master/RebeccaStambler-GoPleaseStopBreakingMyEditor/slides.pdf \"Go, please stop breaking my editor!\"\n[JSON rpc 2]: https://www.jsonrpc.org/specification\n\n[errcheck]: https://github.com/kisielk/errcheck\n[go-outline]: https://github.com/lukehoban/go-outline\n[go-symbols]: https://github.com/acroca/go-symbols\n[gocode]: https://github.com/stamblerre/gocode\n[godef]: https://github.com/rogpeppe/godef\n[godoc]: https://golang.org/cmd/godoc\n[gofmt]: https://golang.org/cmd/gofmt\n[gogetdoc]: https://github.com/zmb3/gogetdoc\n[goimports]: https://pkg.go.dev/golang.org/x/tools/cmd/goimports\n[goreturns]: https://github.com/sqs/goreturns\n[gotags]: https://github.com/jstemmer/gotags\n[guru]: https://pkg.go.dev/golang.org/x/tools/cmd/guru\n[impl]: https://github.com/josharian/impl\n[staticcheck]: https://staticcheck.io/docs/\n[go/types]: https://golang.org/pkg/go/types/\n[go/ast]: https://golang.org/pkg/go/ast/\n[go/token]: https://golang.org/pkg/go/token/\n\n[`completionItem/resolve`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#completionItem_resolve\n[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction\n[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion\n[`textDocument/declaration`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_declaration\n[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition\n[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink\n[`textDocument/documentSymbol`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbol\n[`textDocument/foldingRange`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_foldingRange\n[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting\n[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight\n[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover\n[`textDocument/implementation`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_implementation\n[`textDocument/onTypeFormatting`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_onTypeFormatting\n[`textDocument/prepareRename`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_prepareRename\n[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics\n[`textDocument/rangeFormatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rangeFormatting\n[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references\n[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename\n[`textDocument/selectionRange`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_selectionRange\n[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp\n[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition\n[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles\n"
  },
  {
    "path": "gopls/doc/design/implementation.md",
    "content": "---\ntitle: \"Gopls: Implementation\"\n---\n\nLast major update: Jan 16 2024\n\nThis doc presents a high-level overview of the structure of gopls to\nhelp new contributors find their way. It is not intended to be a\ncomplete description of the implementation, nor even of any key\ncomponents; for that, the package documentation (linked below) and\nother comments within the code are a better guide.\n\nThe diagram below shows selected components of the gopls module and\ntheir relationship to each other according to the Go import graph.\nTests and test infrastructure are not shown, nor are utility packages,\nnor packages from the [x/tools] module. For brevity, packages are\nreferred to by their last segment, which is usually unambiguous.\n\nThe height of each blob corresponds loosely to its technical depth.\nSome blocks are wide and shallow, such as [protocol], which declares\nGo types for the entire LSP protocol. Others are deep, such as [cache]\nand [golang], as they contain a lot of dense logic and algorithms.\n\n<!-- Source: https://docs.google.com/drawings/d/1CK6YSLt7G3svRoZf7skJI-lxRol2VI90YOxHcYS0DP4 -->\n![Gopls architecture](architecture.svg)\n\nStarting from the bottom, we'll describe the various components.\n\nThe lowest layer defines the request and response types of the\nLanguage Server Protocol:\n\n- The [protocol] package defines the standard protocol; it is mostly\n  generated mechanically from the schema definition provided by\n  Microsoft.\n  The most important type is DocumentURI, which represents a `file:`\n  URL that identifies a client editor document. It also provides\n  `Mapper`, which maps between the different coordinate systems used\n  for source positions: UTF-8, UTF-16, and token.Pos.\n\n- The [command] package defines Gopls's non-standard commands, which\n  are all invoked through the `workspace/executeCommand` extension\n  mechanism. These commands are typically returned by the server as\n  continuations of Code Actions or Code Lenses; most clients do not\n  construct calls to them directly.\n\nThe next layer defines a number of important and very widely used data structures:\n\n- The [file] package defines the primary abstractions of a client\n  file: its `Identity` (URI and content hash), and its `Handle` (which\n  additionally provides the version and content of a particular\n  snapshot of the file.\n\n- The [parsego] package defines `File`, the parsed form of a Go source\n  file, including its content, syntax tree, and coordinary mappings\n  (Mapper and token.File). The package performs various kinds of tree\n  repair to work around error-recovery shortcomings of the Go parser.\n\n- The [metadata] package defines `Package`, an abstraction of the\n  metadata of a Go package, similar to the output of `go list -json`.\n  Metadata is produced from [go/packages], which takes\n  care of invoking `go list`. (Users report that it works to some extent\n  with a GOPACKAGESDRIVER for Bazel, though we maintain no tests for this\n  scenario.)\n\n  The package also provides `Graph`, the complete import graph for a\n  workspace; each graph node is a `Package`.\n\nThe [settings] layer defines the data structure (effectively a large\ntree) for gopls configuration options, along with its JSON encoding.\n\nThe [cache] layer is the largest and most complex component of gopls.\nIt is concerned with state management, dependency analysis, and invalidation:\nthe `Session` of communication with the client;\nthe `Folder`s that the client has opened;\nthe `View` of a particular workspace tree with particular build\noptions;\nthe `Snapshot` of the state of all files in the workspace after a\nparticular edit operation;\nthe contents of all files, whether saved to disk (`DiskFile`) or\nedited and unsaved (`Overlay`);\nthe `Cache` of in-memory memoized computations,\nsuch as parsing go.mod files or build the symbol index;\nand the `Package`, which holds the results of type checking a package\nfrom Go syntax.\n\nThe cache layer depends on various auxiliary packages, including:\n\n- The [filecache] package, which manages gopls' persistent, transactional,\n  file-based key/value store.\n  \n- The [xrefs], [methodsets], and [typerefs] packages define algorithms\n  for constructing indexes of information derived from type-checking,\n  and for encoding and decoding these serializable indexes in the file\n  cache.\n\n  Together these packages enable the fast restart, reduced memory\n  consumption, and synergy across processes that were delivered by the\n  v0.12 redesign and described in [\"Scaling gopls for the growing Go\n  ecosystem\"](https://go.dev/blog/gopls-scalability).\n\nThe cache also defines gopls's [go/analysis] driver, which runs\nmodular analysis (similar to `go vet`) across the workspace.\nGopls also includes a number of analysis passes that are not part of vet.\n\nThe next layer defines four packages, each for handling files in a\nparticular language:\n[mod] for go.mod files;\n[work] for go.work files;\n[template] for files in `text/template` syntax; and\n[golang], for files in Go itself.\nThis package, by far the largest, provides the main features of gopls:\nnavigation, analysis, and refactoring of Go code.\nAs most users imagine it, this package _is_ gopls.\n\nThe [server] package defines the LSP service implementation, with one\nhandler method per LSP request type. Each handler switches on the type\nof the file and dispatches to one of the four language-specific\npackages.\n\nThe [lsprpc] package connects the service interface to our [jsonrpc2](https://www.jsonrpc.org/specification) server.\n\nBear in mind that the diagram is a dependency graph, a \"static\"\nviewpoint of the program's structure. A more dynamic viewpoint would\norder the packages based on the sequence in which they are encountered\nduring processing of a particular request; in such a view, the bottom\nlayer would represent the \"wire\" (protocol and command), the next\nlayer up would hold the RPC-related packages (lsprpc and server), and\nfeatures (e.g. golang, mod, work, template) would be at the top.\n\n<!--\nA dynamic view would be an interesting topic for another article.\nThis slide deck [requires Google network]\nThe Life of a (gopls) Query (Oct 2021)\nhttps://docs.google.com/presentation/d/1c8XJaIldzii-F3YvEOPWHK_MQJ_o8ua5Bct1yDa3ZlU\nprovides useful (if somewhat out of date) information.\n-->\n\nThe [cmd] package defines the command-line interface of the `gopls`\ncommand, around which gopls's main package is just a trivial wrapper.\nIt is usually run without arguments, causing it to start a server and\nlisten indefinitely.\nIt also provides a number of subcommands that start a server, make a\nsingle request to it, and exit, providing traditional batch-command\naccess to server functionality. These subcommands are primarily\nprovided as a debugging aid; but see https://go.dev/issue/63693.\n\n[cache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache\n[cmd]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cmd\n[command]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol/command\n[debug]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/debug\n[file]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/file\n[filecache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/filecache\n[go/analysis]: https://pkg.go.dev/golang.org/x/tools@master/go/analysis\n[go/packages]: https://pkg.go.dev/golang.org/x/tools@master/go/packages\n[gopls]: https://pkg.go.dev/golang.org/x/tools/gopls@master\n[jsonrpc]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc\n[jsonrpc2]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc2\n[lsprpc]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsprpc\n[memoize]: https://github.com/golang/tools/tree/master/internal/memoize\n[metadata]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/metadata\n[methodsets]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/methodsets\n[mod]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/mod\n[parsego]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/parsego\n[protocol]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol\n[server]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/server\n[settings]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/settings\n[golang]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/golang\n[template]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/template\n[typerefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/typerefs\n[work]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/work\n[x/tools]: https://github.com/golang/tools@master\n[xrefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/xrefs\n"
  },
  {
    "path": "gopls/doc/design/integrating.md",
    "content": "---\ntitle: \"Documentation for plugin authors\"\n---\n\nIf you are integrating `gopls` into an editor by writing an editor plugin, there are quite a few semantics of the communication between the editor and `gopls` that are not specified by the [LSP specification].\n\nWe attempt to document those details along with any other information that has been helpful to other plugin authors here.\n\nIf you are implementing a plugin yourself and have questions this page does not answer, please reach out to us to ask, and then also contribute your findings back to this page.\n\n## Supported features\n\nFor the most part you should look at the [Index of features](../features/)\nto know whether gopls supports a feature.\n\nFor a truly authoritative answer you should check the [result][InitializeResult] of the [initialize] request, where gopls enumerates its support in the [ServerCapabilities].\n\n\n## Positions and ranges\n\nMany LSP requests pass position or range information. This is described in the [LSP specification][lsp-text-documents]:\n\n> A position inside a document (see Position definition below) is expressed as a zero-based line and character offset. The offsets are based on a UTF-16 string representation. So a string of the form a𐐀b the character offset of the character a is 0, the character offset of 𐐀 is 1 and the character offset of b is 3 since 𐐀 is represented using two code units in UTF-16.\n\nThis means that integrators will need to calculate UTF-16 based column offsets.\nUse `protocol.Mapper` for all the conversions.\n\n## Edits\n\nIn order to deliver changes from gopls to the editor, the LSP supports arrays of [`TextEdit`][lsp-textedit]s in responses.\nThe spec specifies exactly how these should be applied:\n\n> All text edits ranges refer to positions in the original document. Text edits ranges must never overlap, that means no part of the original document must be manipulated by more than one edit. However, it is possible that multiple edits have the same start position: multiple inserts, or any number of inserts followed by a single remove or replace edit. If multiple inserts have the same position, the order in the array defines the order in which the inserted strings appear in the resulting text.\n\nAll `[]TextEdit` are sorted such that applying the array of deltas received in reverse order achieves the desired result that holds with the spec.\n\n## Errors\n\nVarious error codes are described in the [LSP specification][lsp-response]. We are still determining what it means for a method to return an error; are errors only for low-level LSP/transport issues or can other conditions cause errors to be returned? See some of this discussion on [#31526].\n\nThe method chosen is currently influenced by the exact treatment in the currently popular editor integrations. It may well change, and ideally would become more coherent across requests.\n\n* [`textDocument/codeAction`]: Return error if there was an error computing code actions.\n* [`textDocument/completion`]: Log errors, return empty result list.\n* [`textDocument/definition`]: Return error if there was an error computing the definition for the position.\n* [`textDocument/typeDefinition`]: Return error if there was an error computing the type definition for the position.\n* [`textDocument/formatting`]: Return error if there was an error formatting the file.\n* [`textDocument/highlight`]: Log errors, return empty result.\n* [`textDocument/hover`]: Return empty result.\n* [`textDocument/documentLink`]: Log errors, return nil result.\n* [`textDocument/publishDiagnostics`]: Log errors if there were any while computing diagnostics.\n* [`textDocument/references`]: Log errors, return empty result.\n* [`textDocument/rename`]: Return error if there was an error computing renames.\n* [`textDocument/signatureHelp`]: Log errors, return nil result.\n* [`textDocument/documentSymbols`]: Return error if there was an error computing document symbols.\n\n## Watching files\n\nIt is fairly normal for files that affect `gopls` to be modified outside of the editor it is associated with.\n\nFor instance, files that are needed to do correct type checking are modified by switching branches in git, or updated by a code generator.\n\nMonitoring files inside gopls directly has a lot of awkward problems, but the [LSP specification] has methods that allow gopls to request that the client notify it of file system changes, specifically [`workspace/didChangeWatchedFiles`].\nThis is currently being added to gopls by a community member, and tracked in [#31553]\n\n[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#InitializeResult\n[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#ServerCapabilities\n[`golang.org/x/tools/gopls/internal/protocol`]: https://pkg.go.dev/golang.org/x/tools/internal/protocol#NewPoint\n\n[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/\n[lsp-response]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#response-message\n[initialize]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#initialize\n[lsp-text-documents]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#text-documents\n[lsp-textedit]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textedit\n\n[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction\n[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion\n[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition\n[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition\n[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting\n[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight\n[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover\n[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink\n[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics\n[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references\n[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename\n[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp\n[`textDocument/documentSymbols`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbols\n[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles\n\n[#31080]: https://github.com/golang/go/issues/31080\n[#31553]: https://github.com/golang/go/issues/31553\n[#31526]: https://github.com/golang/go/issues/31526\n"
  },
  {
    "path": "gopls/doc/editor/emacs.md",
    "content": "---\ntitle: \"Gopls: Using Emacs\"\n---\n\n## Installing `gopls`\n\nTo use `gopls` with Emacs, you must first\n[install the `gopls` executable](../index.md#installation) and ensure that the directory\ncontaining the resulting binary (either `$(go env GOBIN)` or `$(go env\nGOPATH)/bin`) is in your `PATH`.\n\n## Choosing an Emacs LSP client\n\nTo use `gopls` with Emacs, you will need to choose and install an Emacs LSP\nclient package. Two popular client packages are [LSP Mode] and [Eglot].\n\nLSP Mode takes a batteries-included approach, with many integrations enabled\n“out of the box” and several additional behaviors provided by `lsp-mode` itself.\n\nEglot takes a minimally-intrusive approach, focusing on smooth integration with\nother established packages. It provides a few of its own `eglot-` commands but\nno additional keybindings by default.\n\nOnce you have selected which client you want to use, install it per the packages\ninstructions: see [Eglot 1-2-3](https://github.com/joaotavora/eglot#1-2-3) or\n[LSP Mode Installation](https://emacs-lsp.github.io/lsp-mode/page/installation/).\n\n## Common configuration\n\nBoth Eglot and LSP Mode can integrate with popular packages in the Emacs\necosystem:\n\n* The built-in [`xref`] package provides cross-references.\n* The built-in [Flymake] package provides an on-the-fly diagnostic overlay.\n* [Company] mode displays code completion candidates (with a richer UI than\n  the built-in [`completion-at-point`]).\n\nEglot provides documentation using the built-in [ElDoc] minor mode, while LSP\nMode by default provides documentation using its own [`lsp-ui`] mode.\n\nEglot by default locates the project root using the [`project`] package. In LSP\nMode, this behavior can be configured using the `lsp-auto-guess-root` setting.\n\n## Configuring LSP Mode\n\n### Loading LSP Mode in `.emacs`\n\n```elisp\n(require 'lsp-mode)\n(add-hook 'go-mode-hook #'lsp-deferred)\n\n;; Set up before-save hooks to format buffer and add/delete imports.\n;; Make sure you don't have other gofmt/goimports hooks enabled.\n(defun lsp-go-install-save-hooks ()\n  (add-hook 'before-save-hook #'lsp-format-buffer t t)\n  (add-hook 'before-save-hook #'lsp-organize-imports t t))\n(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)\n```\n\n### Configuring `gopls` via LSP Mode\n\nSee [settings](../settings) for information about available gopls settings.\n\nStable gopls settings have corresponding configuration variables in `lsp-mode`.\nFor example, `(setq lsp-gopls-use-placeholders nil)` will disable placeholders\nin completion snippets. See [`lsp-go`] for a list of available variables.\n\nExperimental settings can be configured via `lsp-register-custom-settings`:\n\n```lisp\n(lsp-register-custom-settings\n '((\"gopls.completeUnimported\" t t)\n   (\"gopls.staticcheck\" t t)))\n```\n\nNote that after changing settings you must restart gopls using e.g. `M-x\nlsp-restart-workspace`.\n\n## Configuring Eglot\n\n### Configuring `project` for Go modules in `.emacs`\n\nEglot uses the built-in `project` package to identify the LSP workspace for a\nnewly-opened buffer. The `project` package does not natively know about `GOPATH`\nor Go modules. Fortunately, you can give it a custom hook to tell it to look for\nthe nearest parent `go.mod` file (that is, the root of the Go module) as the\nproject root.\n\n```elisp\n(require 'project)\n\n(defun project-find-go-module (dir)\n  (when-let ((root (locate-dominating-file dir \"go.mod\")))\n    (cons 'go-module root)))\n\n(cl-defmethod project-root ((project (head go-module)))\n  (cdr project))\n\n(add-hook 'project-find-functions #'project-find-go-module)\n```\n\n### Loading Eglot in `.emacs`\n\n```elisp\n;; Optional: load other packages before eglot to enable eglot integrations.\n(require 'company)\n(require 'yasnippet)\n\n(require 'go-mode)\n(require 'eglot)\n(add-hook 'go-mode-hook 'eglot-ensure)\n\n;; Optional: install eglot-format-buffer as a save hook.\n;; The depth of -10 places this before eglot's willSave notification,\n;; so that notification reports the actual contents that will be saved.\n(defun eglot-format-buffer-before-save ()\n  (add-hook 'before-save-hook #'eglot-format-buffer -10 t))\n(add-hook 'go-mode-hook #'eglot-format-buffer-before-save)\n```\n\nUse `M-x eglot-upgrade-eglot` to upgrade to the latest version of\nEglot.\n\n### Configuring `gopls` via Eglot\n\nSee [settings](../settings) for information about available gopls settings.\n\nLSP server settings are controlled by the `eglot-workspace-configuration`\nvariable, which can be set either globally in `.emacs` or in a `.dir-locals.el` file in the project root.\n\n`.emacs`:\n```elisp\n(setq-default eglot-workspace-configuration\n    '((:gopls .\n        ((staticcheck . t)\n         (matcher . \"CaseSensitive\")))))\n```\n\n`.dir-locals.el`:\n```elisp\n((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t)\n\t\t\t\t\t\t  (matcher . \"CaseSensitive\")))))))\n```\n\n### Organizing imports with Eglot\n\n`gopls` provides the import-organizing functionality of `goimports` as an LSP\ncode action, which you can invoke as needed by running `M-x eglot-code-actions`\n(or a key of your choice bound to the `eglot-code-actions` function) and\nselecting `Organize Imports` at the prompt.\n\nTo automatically organize imports before saving, add a hook:\n\n```elisp\n(add-hook 'before-save-hook\n    (lambda ()\n        (call-interactively 'eglot-code-action-organize-imports))\n    nil t)\n```\n\n## Troubleshooting\n\nCommon errors:\n\n* When prompted by Emacs for your project folder, if you are using modules you\n  must select the module's root folder (i.e. the directory with the \"go.mod\").\n  If you are using GOPATH, select your $GOPATH as your folder.\n* Emacs must have your environment set properly (PATH, GOPATH, etc). You can\n  run `M-x getenv <RET> PATH <RET>` to see if your PATH is set in Emacs. If\n  not, you can try starting Emacs from your terminal, using [this\n  package][exec-path-from-shell], or moving your shell config from `.bashrc`\n  into `.profile` and logging out and back in.\n* Make sure only one LSP client mode is installed. (For example, if using\n  `lsp-mode`, ensure that you are not _also_ enabling `eglot`.)\n* Look for errors in the `*lsp-log*` buffer or run `M-x eglot-events-buffer`.\n* Ask for help in the `#emacs` channel on the [Gophers slack].\n\n[LSP Mode]: https://emacs-lsp.github.io/lsp-mode/\n[Eglot]: https://github.com/joaotavora/eglot/blob/master/README.md\n[`xref`]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html\n[Flymake]: https://www.gnu.org/software/emacs/manual/html_node/flymake/Using-Flymake.html#Using-Flymake\n[Company]: https://company-mode.github.io/\n[`completion-at-point`]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html\n[ElDoc]: https://elpa.gnu.org/packages/eldoc.html\n[`lsp-ui`]: https://emacs-lsp.github.io/lsp-ui/\n[`lsp-go`]: https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-go.el\n[`use-package`]: https://github.com/jwiegley/use-package\n[`exec-path-from-shell`]: https://github.com/purcell/exec-path-from-shell\n[settings]: settings.md\n[Gophers slack]: https://invite.slack.golangbridge.org/\n"
  },
  {
    "path": "gopls/doc/editor/helix.md",
    "content": "---\ntitle: \"Gopls: Using Helix\"\n---\n\nConfiguring `gopls` to work with Helix is rather straightforward. Install `gopls`, and then add it to the `PATH` variable. If it is in the `PATH` variable, Helix will be able to detect it automatically.\n\nThe documentation explaining how to install the default language servers for Helix can be found [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers)\n\n## Installing `gopls`\n\nThe first step is to install `gopls` on your machine.\nYou can follow installation instructions [here](https://github.com/golang/tools/tree/master/gopls#installation).\n\n## Setting your path to include `gopls`\n\nSet your `PATH` environment variable to point to `gopls`.\nIf you used `go install` to download `gopls`, it should be in `$GOPATH/bin`.\nIf you don't have `GOPATH` set, you can use `go env GOPATH` to find it.\n\n## Additional information\n\nYou can find more information about how to set up the LSP formatter [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers#autoformatting).\n\nIt is possible to use `hx --health go` to see that the language server is properly set up.\n\n### Configuration\n\nThe settings for `gopls` can be configured in the `languages.toml` file.\nThe official Helix documentation for this can be found [here](https://docs.helix-editor.com/languages.html)\n\nConfiguration pertaining to `gopls` should be in the table `language-server.gopls`.\n\n#### How to set flags\n\nTo set flags, add them to the `args` array in the `language-server.gopls` section of the `languages.toml` file.\n\n#### How to set LSP configuration\n\nConfiguration options can be set in the `language-server.gopls.config` section of the `languages.toml` file, or in the `config` key of the `language-server.gopls` section of the `languages.toml` file.\n\n#### A minimal config example\n\nIn the `~/.config/helix/languages.toml` file, the following snippet would set up `gopls` with a logfile located at `/tmp/gopls.log` and enable staticcheck.\n\n```toml\n[language-server.gopls]\ncommand = \"gopls\"\nargs = [\"-logfile=/tmp/gopls.log\",  \"serve\"]\n[language-server.gopls.config]\n\"ui.diagnostic.staticcheck\" = true\n```\n\n\n"
  },
  {
    "path": "gopls/doc/editor/sublime.md",
    "content": "---\ntitle: \"Gopls: Using Sublime Text\"\n---\n\nUse the [LSP] package. After installing it using Package Control, do the following:\n\n* Open the **Command Palette**\n* Find and run the command **LSP: Enable Language Server Globally**\n* Select the **gopls** item. Be careful not to select the similarly named *golsp* by mistake.\n\nFinally, you should familiarise yourself with the LSP package's *Settings* and *Key Bindings*. Find them under the menu item **Preferences > Package Settings > LSP**.\n\n## Examples\nMinimal global LSP settings, that assume **gopls** and **go** appear on the PATH seen by Sublime Text:<br>\n```\n{\n    \"clients\": {\n        \"gopls\": {\n             \"enabled\": true,\n         }\n    }\n}\n```\n\nGlobal LSP settings that supply a specific PATH for finding **gopls** and **go**, as well as some settings for Sublime LSP itself:\n```\n{\n    \"clients\": {\n        \"gopls\": {\n            \"enabled\": true,\n            \"env\": {\n                \"PATH\": \"/path/to/your/go/bin\",\n            }\n        }\n    },\n    // Recommended by https://agniva.me/gopls/2021/01/02/setting-up-gopls-sublime.html\n    // except log_stderr mentioned there is no longer recognized.\n    \"show_references_in_quick_panel\": true,\n    \"log_debug\": true,\n    // These two are recommended by LSP-json as replacement for deprecated only_show_lsp_completions\n    \"inhibit_snippet_completions\": true,\n    \"inhibit_word_completions\": true,\n }\n ```\n\nLSP and gopls settings can also be adjusted on a per-project basis to override global settings.\n```\n{\n    \"folders\": [\n        {\n            \"path\": \"/path/to/a/folder/one\"\n        },\n        {\n            // If you happen to be working on Go itself, this can be helpful; go-dev/bin should be on PATH.\n            \"path\": \"/path/to/your/go-dev/src/cmd\"\n        }\n     ],\n    \"settings\": {\n        \"LSP\": {\n            \"gopls\": {\n                // To use a specific version of gopls with Sublime Text LSP (e.g., to try new features in development)\n                \"command\": [\n                    \"/path/to/your/go/bin/gopls\"\n                ],\n                \"env\": {\n                    \"PATH\": \"/path/to/your/go-dev/bin:/path/to/your/go/bin\",\n                    \"GOPATH\": \"\",\n                },\n                \"settings\": {\n                    \"experimentalWorkspaceModule\": true\n                }\n            }\n        },\n        // This will apply for all languages in this project that have\n        // LSP servers, not just Go, however cannot enable just for Go.\n        \"lsp_format_on_save\": true,\n    }\n}\n```\n\nUsually changes to these settings are recognized after saving the project file, but it may sometimes be necessary to either restart the server(s) (**Tools > LSP > Restart Servers**) or quit and restart Sublime Text itself.\n\n[LSP]: https://packagecontrol.io/packages/LSP\n"
  },
  {
    "path": "gopls/doc/editor/vim.md",
    "content": "---\ntitle: \"Gopls: Using Vim or Neovim\"\n---\n\n* [vim-go](#vimgo)\n* [LanguageClient-neovim](#lcneovim)\n* [Ale](#ale)\n* [vim-lsp](#vimlsp)\n* [vim-lsc](#vimlsc)\n* [coc.nvim](#cocnvim)\n* [govim](#govim)\n* [Neovim v0.5.0+](#neovim)\n  * [Installation](#neovim-install)\n  * [Custom Configuration](#neovim-config)\n  * [Imports](#neovim-imports)\n  * [Omnifunc](#neovim-omnifunc)\n  * [Additional Links](#neovim-links)\n\n## <a href=\"#vimgo\" id=\"vimgo\">vim-go</a>\n\nUse [vim-go] ver 1.20+, with the following configuration:\n\n```vim\nlet g:go_def_mode='gopls'\nlet g:go_info_mode='gopls'\n```\n\n## <a href=\"#lcneovim\" id=\"lcneovim\">LanguageClient-neovim</a>\n\nUse [LanguageClient-neovim], with the following configuration:\n\n```vim\n\" Launch gopls when Go files are in use\nlet g:LanguageClient_serverCommands = {\n       \\ 'go': ['gopls']\n       \\ }\n\" Run gofmt on save\nautocmd BufWritePre *.go :call LanguageClient#textDocument_formatting_sync()\n```\n\n## <a href=\"#ale\" id=\"ale\">Ale</a>\n\nUse [ale]:\n\n```vim\nlet g:ale_linters = {\n  \\ 'go': ['gopls'],\n  \\}\n```\n\nsee [this issue][ale-issue-2179]\n\n## <a href=\"#vimlsp\" id=\"vimlsp\">vim-lsp</a>\n\nUse [prabirshrestha/vim-lsp], with the following configuration:\n\n```vim\naugroup LspGo\n  au!\n  autocmd User lsp_setup call lsp#register_server({\n      \\ 'name': 'gopls',\n      \\ 'cmd': {server_info->['gopls']},\n      \\ 'whitelist': ['go'],\n      \\ })\n  autocmd FileType go setlocal omnifunc=lsp#complete\n  \"autocmd FileType go nmap <buffer> gd <plug>(lsp-definition)\n  \"autocmd FileType go nmap <buffer> ,n <plug>(lsp-next-error)\n  \"autocmd FileType go nmap <buffer> ,p <plug>(lsp-previous-error)\naugroup END\n```\n\n## <a href=\"#vimlsc\" id=\"vimlsc\">vim-lsc</a>\n\nUse [natebosch/vim-lsc], with the following configuration:\n\n```vim\nlet g:lsc_server_commands = {\n\\  \"go\": {\n\\    \"command\": \"gopls serve\",\n\\    \"log_level\": -1,\n\\    \"suppress_stderr\": v:true,\n\\  },\n\\}\n```\n\nThe `log_level` and `suppress_stderr` parts are needed to prevent breakage from logging. See\nissues [#180](https://github.com/natebosch/vim-lsc/issues/180) and\n[#213](https://github.com/natebosch/vim-lsc/issues/213).\n\n## <a href=\"#cocnvim\" id=\"cocnvim\">coc.nvim</a>\n\nUse [coc.nvim], with the following `coc-settings.json` configuration:\n\n```json\n  \"languageserver\": {\n    \"go\": {\n      \"command\": \"gopls\",\n      \"rootPatterns\": [\"go.work\", \"go.mod\", \".vim/\", \".git/\", \".hg/\"],\n      \"filetypes\": [\"go\"],\n      \"initializationOptions\": {\n        \"usePlaceholders\": true\n      }\n    }\n  }\n```\n\nIf you use `go.work` files, you may want to set the\n`workspace.workspaceFolderCheckCwd` option. This will force coc.nvim to search\nparent directories for `go.work` files, even if the current open directory has\na `go.mod` file. See the\n[coc.nvim documentation](https://github.com/neoclide/coc.nvim/wiki/Using-workspaceFolders)\nfor more details.\n\nOther [settings](../settings) can be added in `initializationOptions` too.\n\nThe `editor.action.organizeImport` code action will auto-format code and add missing imports. To run this automatically on save, add the following line to your `init.vim`:\n\n```vim\nautocmd BufWritePre *.go :call CocAction('runCommand', 'editor.action.organizeImport')\n```\n\n## <a href=\"#govim\" id=\"govim\">govim</a>\n\nIn vim classic only, use the experimental [`govim`], simply follow the [install steps][govim-install].\n\n## <a href=\"#neovim\" id=\"neovim\">Neovim v0.5.0+</a>\n\nTo use the new native LSP client in Neovim, make sure you\n[install][nvim-install] Neovim v.0.5.0+,\nthe `nvim-lspconfig` configuration helper plugin, and check the\n[`gopls` configuration section][nvim-lspconfig] there.\n\n### <a href=\"#neovim-install\" id=\"neovim-install\">Installation</a>\n\nYou can use Neovim's native plugin system.  On a Unix system, you can do that by\ncloning the `nvim-lspconfig` repository into the correct directory:\n\n```sh\ndir=\"${HOME}/.local/share/nvim/site/pack/nvim-lspconfig/opt/nvim-lspconfig/\"\nmkdir -p \"$dir\"\ncd \"$dir\"\ngit clone 'https://github.com/neovim/nvim-lspconfig.git' .\n```\n\n### <a href=\"#neovim-config\" id=\"neovim-config\">Configuration</a>\n\nnvim-lspconfig aims to provide reasonable defaults, so your setup can be very\nbrief.\n\n```lua\nlocal lspconfig = require(\"lspconfig\")\nlspconfig.gopls.setup({})\n```\n\nHowever, you can also configure `gopls` for your preferences. Here's an\nexample that enables `unusedparams`, `staticcheck`, and `gofumpt`.\n\n```lua\nlocal lspconfig = require(\"lspconfig\")\nlspconfig.gopls.setup({\n  settings = {\n    gopls = {\n      analyses = {\n        unusedparams = true,\n      },\n      staticcheck = true,\n      gofumpt = true,\n    },\n  },\n})\n```\n\n### <a href=\"#neovim-imports\" id=\"neovim-imports\">Imports and Formatting</a>\n\nUse the following configuration to have your imports organized on save using\nthe logic of `goimports` and your code formatted.\n\n```lua\nautocmd(\"BufWritePre\", {\n  pattern = \"*.go\",\n  callback = function()\n    local params = vim.lsp.util.make_range_params()\n    params.context = {only = {\"source.organizeImports\"}}\n    -- buf_request_sync defaults to a 1000ms timeout. Depending on your\n    -- machine and codebase, you may want longer. Add an additional\n    -- argument after params if you find that you have to write the file\n    -- twice for changes to be saved.\n    -- E.g., vim.lsp.buf_request_sync(0, \"textDocument/codeAction\", params, 3000)\n    local result = vim.lsp.buf_request_sync(0, \"textDocument/codeAction\", params)\n    for cid, res in pairs(result or {}) do\n      for _, r in pairs(res.result or {}) do\n        if r.edit then\n          local enc = (vim.lsp.get_client_by_id(cid) or {}).offset_encoding or \"utf-16\"\n          vim.lsp.util.apply_workspace_edit(r.edit, enc)\n        end\n      end\n    end\n    vim.lsp.buf.format({async = false})\n  end\n})\n```\n\n### <a href=\"#neovim-omnifunc\" id=\"neovim-omnifunc\">Omnifunc</a>\n\nIn Neovim v0.8.1 and later if you don't set the option `omnifunc`, it will auto\nset to `v:lua.vim.lsp.omnifunc`. If you are using an earlier version, you can\nconfigure it manually:\n\n```lua\nlocal on_attach = function(client, bufnr)\n  -- Enable completion triggered by <c-x><c-o>\n  vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')\nend\nrequire('lspconfig').gopls.setup({\n   on_attach = on_attach\n})\n```\n\n### <a href=\"#neovim-links\" id=\"neovim-links\">Additional Links</a>\n\n* [Neovim's official LSP documentation][nvim-docs].\n\n[vim-go]: https://github.com/fatih/vim-go\n[LanguageClient-neovim]: https://github.com/autozimu/LanguageClient-neovim\n[ale]: https://github.com/w0rp/ale\n[ale-issue-2179]: https://github.com/w0rp/ale/issues/2179\n[prabirshrestha/vim-lsp]: https://github.com/prabirshrestha/vim-lsp/\n[natebosch/vim-lsc]: https://github.com/natebosch/vim-lsc/\n[natebosch/vim-lsc#180]: https://github.com/natebosch/vim-lsc/issues/180\n[coc.nvim]: https://github.com/neoclide/coc.nvim/\n[`govim`]: https://github.com/myitcv/govim\n[govim-install]: https://github.com/myitcv/govim/blob/master/README.md#govim---go-development-plugin-for-vim8\n[nvim-docs]: https://neovim.io/doc/user/lsp.html\n[nvim-install]: https://github.com/neovim/neovim/wiki/Installing-Neovim\n[nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#gopls\n[nvim-lspconfig-imports]: https://github.com/neovim/nvim-lspconfig/issues/115\n"
  },
  {
    "path": "gopls/doc/editor/zed.md",
    "content": "---\ntitle: \"Gopls: Using Zed\"\n---\n\n## Install `gopls`\n\nTo use `gopls` with [Zed](https://zed.dev/), first\n[install the `gopls` executable](../index.md#installation) and ensure that the directory\ncontaining the resulting binary (either `$(go env GOBIN)` or `$(go env\nGOPATH)/bin`) is in your `PATH`.\n\n## That's it\n\nZed has a built-in LSP client and knows to run `gopls` when visiting a\nGo source file, so most features work right out of the box.\n\nZed does not yet support external `window/showDocument` requests,\nso web-based features will not work;\nsee [Zed issue 24852](https://github.com/zed-industries/zed/discussions/24852).\n"
  },
  {
    "path": "gopls/doc/features/README.md",
    "content": "See [index.md](index.md).\n"
  },
  {
    "path": "gopls/doc/features/assembly.md",
    "content": "---\ntitle: \"Gopls: Support for Go *.s assembly files\"\n---\n\nGopls has rudimentary support for LSP operations in Go assembly files.\n\nGo assembly files have a `.s` file name extension. LSP clients need to\nbe configured to recognize `.s` files as Go assembly files, since this\nfile name extension is also used for assembly files in other\nlanguages. A good heuristic is that if a file named `*.s` belongs to a\ndirectory containing at least one `*.go` file, then the `.s` file is\nGo assembly, and its appropriate language server is gopls.\n\nOnly Definition (`textDocument/definition`) requests are currently\nsupported. For example, a Definition request on the `sigpanic`\nsymbol in this file in GOROOT/src/runtime/asm.s:\n\n```asm\n\tJMP\t·sigpanic<ABIInternal>(SB)\n```\n\nreturns the location of the function declaration in\nGOROOT/src/runtime/signal_unix.go:\n\n```go\n//go:linkname sigpanic\nfunc sigpanic() {\n```\n\nSee also issue https://go.dev/issue/71754, which tracks the development of LSP\nfeatures in Go assembly files."
  },
  {
    "path": "gopls/doc/features/completion.md",
    "content": "---\ntitle: \"Gopls: Completion\"\n---\n\nTODO(https://go.dev/issue/62022): document\n"
  },
  {
    "path": "gopls/doc/features/diagnostics.md",
    "content": "---\ntitle: \"Gopls: Diagnostics\"\n---\n\nGopls continuously annotates all your open files of source code with a\nvariety of diagnostics. Every time you edit a file or make a\nconfiguration change, gopls asynchronously recomputes these\ndiagnostics and sends them to the client using the LSP\n[`publishDiagnostics`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_publishDiagnostics)\nnotification, giving you real-time feedback that reduces the cost of\ncommon mistakes.\n\nDiagnostics come from two main sources: compilation errors and analysis findings.\n\n- **Compilation errors** are those that you would obtain from running `go\nbuild`. Gopls doesn't actually run the compiler; that would be too\n  slow. Instead it runs `go list` (when needed) to compute the\n  metadata of the compilation, then processes those packages in a similar\n  manner to the compiler front-end: reading, scanning, and parsing the\n  source files, then type-checking them. Each of these steps can\n  produce errors that gopls will surface as a diagnostic.\n\n  The `source` field of the LSP `Diagnostic` record indicates where\n  the diagnostic came from: those with source `\"go list\"` come from\n  the `go list` command, and those with source `\"compiler\"` come from\n  gopls' parsing or type checking phases, which are similar to those\n  used in the Go compiler.\n\n  ![A diagnostic due to a type error](../assets/diagnostic-typeerror.png)\n\n  The example above shows a `string + int` addition, causes the type\n  checker to report a `MismatchedTypes` error. The diagnostic contains\n  a link to the documentation about this class of type error.\n\n- **Analysis findings** come from the [**Go analysis\n  framework**](https://golang.org/x/tools/go/analysis), the system\n  used by `go vet` to apply a variety of additional static checks to\n  your Go code. The best-known example is the [`printf`\n  analyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf),\n  which reports calls to [`fmt.Printf`](https://pkg.go.dev/fmt#Printf)\n  where the format \"verb\" doesn't match the argument, such as\n  `fmt.Printf(\"%d\", \"three\")`.\n\n  Gopls provides dozens of analyzers aggregated from a variety of\n  suites; see [Analyzers](../analyzers.md) for the complete list. The\n  `source` field of each diagnostic produced by an analyzer records\n  the name of the analyzer that produced it.\n\n  ![A diagnostic due to an analysis finding](../assets/diagnostic-analysis.png)\n\n  The example above shows a `printf` formatting mistake. The diagnostic contains\n  a link to the documentation for the `printf` analyzer.\n\nThere is an optional third source of diagnostics:\n\n<a id='toggleCompilerOptDetails'></a>\n\n- **Compiler optimization details** are diagnostics that report\n  details relevant to optimization decisions made by the Go\n  compiler, such as whether a variable escapes or a slice index\n  requires a bounds check.\n\n  Optimization decisions include:\n  whether a variable escapes, and how escape is inferred;\n  whether a nil-pointer check is implied or eliminated; and\n  whether a function can be inlined.\n\n  This source is disabled by default but can be enabled on a\n  package-by-package basis by invoking the\n  `source.toggleCompilerOptDetails` (\"{Show,Hide} compiler optimization\n  details\") code action.\n\n  Remember that the compiler's optimizer runs only on packages that\n  are transitively free from errors, so optimization diagnostics\n  will not be shown on packages that do not build.\n\n\n## Recomputation of diagnostics\n\nBy default, diagnostics are automatically recomputed each time the source files\nare edited.\n\nCompilation errors in open files are updated after a very short delay\n(tens of milliseconds) after each file change, potentially after every keystroke.\nThis ensures rapid feedback of syntax and type errors while editing.\n\nCompilation and analysis diagnostics for the whole workspace are much\nmore expensive to compute, so they are usually recomputed after a\nshort idle period (around 1s) following an edit.\n\nThe [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines\nthis period.\nAlternatively, diagnostics may be triggered only after an edited file\nis saved, using the\n[`diagnosticsTrigger`](../settings.md#diagnosticsTrigger) setting.\n\nWhen initialized with `\"pullDiagnostics\": true`, gopls also supports\n[\"pull diagnostics\"](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics),\nan alternative mechanism for recomputing diagnostics in which the client\nrequests diagnostics from gopls explicitly using the `textDocument/diagnostic`\nrequest. This feature is off by default until the performance of pull\ndiagnostics is comparable to push diagnostics.\n\n## Quick fixes\n\nEach analyzer diagnostic may suggest one or more alternative\nways to fix the problem by editing the code.\nFor example, when a `return` statement has too few operands,\nthe [`fillreturns`](../analyzers.md#fillreturns) analyzer\nsuggests a fix that heuristically fills in the missing ones\nwith suitable values. Applying the fix eliminates the compilation error.\n\n![An analyzer diagnostic with two alternative fixes](../assets/remove-unusedparam-before.png)\n\nThe screenshot above shows VS Code's Quick Fix menu for an \"unused\nparameter\" analysis diagnostic with two alternative fixes.\n(See [Remove unused parameter](transformation.md#remove-unused-parameter) for more detail.)\n\nSuggested fixes that are indisputably safe are [code\nactions](transformation.md#code-actions) whose kind is\n`\"source.fixAll\"`.\nMany client editors have a shortcut to apply all such fixes.\n\n<!-- Note: each Code Action has exactly one kind, so a server\n     must offer each \"safe\" action twice, once with its usual kind\n     and once with kind \"source.fixAll\".\n     The only ones in gopls are simplify{compositelit,range,slice},\n     which are fixAll + quickfix.\n-->\n\nTODO(adonovan): audit all the analyzers to ensure that their\ndocumentation is up-to-date w.r.t. any fixes they suggest.\n\nSettings:\n\n- The [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines\n  the idle period after an edit before diagnostics are recomputed.\n- The [`diagnosticsTriggerr`](../settings.md#diagnosticsTrigger) setting determines\n  what events cause recomputation of diagnostics.\n- The [`linkTarget`](../settings.md#linkTarget) setting specifies\n  the base URI for Go package links in the Diagnostic.CodeDescription field.\n\nClient support:\n\n- **VS Code**: Each diagnostic appears as a squiggly underline.\n  Hovering reveals the details, along with any suggested fixes.\n- **Emacs + eglot**: Each diagnostic appears as a squiggly underline.\n  Hovering reveals the details. Use `M-x eglot-code-action-quickfix`\n  to apply available fixes; it will prompt if there are more than one.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls check file.go`\n\n<!-- Below we list any quick fixes (by their internal fix name)\n     that aren't analyzers. -->\n\n### `stubMissingInterfaceMethods`: Declare missing methods of I\n\nWhen a value of a concrete type is assigned to a variable of an\ninterface type, but the concrete type does not possess all the\nnecessary methods, the type checker will report a \"missing method\"\nerror.\n\nIn this situation, gopls offers a quick fix to add stub declarations\nof all the missing methods to the concrete type so that it implements\nthe interface.\n\nFor example, this function will not compile because the value\n`NegativeErr{}` does not implement the \"error\" interface:\n\n```go\nfunc sqrt(x float64) (float64, error) {\n\tif x < 0 {\n\t\treturn 0, NegativeErr{} // error: missing method\n\t}\n\t...\n}\n\ntype NegativeErr struct{}\n```\n\nGopls will offer a quick fix to declare this method:\n\n```go\n\n// Error implements [error.Error].\nfunc (NegativeErr) Error() string {\n\tpanic(\"unimplemented\")\n}\n```\n\nBeware that the new declarations appear alongside the concrete type,\nwhich may be in a different file or even package from the cursor\nposition.\n(Perhaps gopls should send a `showDocument` request to navigate the\nclient there, or a progress notification indicating that something\nhappened.)\n\n### `StubMissingCalledFunction`: Declare missing method T.f\n\nWhen you attempt to call a method on a type that does not have that method,\nthe compiler will report an error such as \"type X has no field or method Y\".\nIn this scenario, gopls now offers a quick fix to generate a stub declaration of\nthe missing method, inferring its type from the call.\n\nConsider the following code where `Foo` does not have a method `bar`:\n\n```go\ntype Foo struct{}\n\nfunc main() {\n  var s string\n  f := Foo{}\n  s = f.bar(\"str\", 42) // error: f.bar undefined (type Foo has no field or method bar)\n}\n```\n\nGopls will offer a quick fix, \"Declare missing method Foo.bar\".\nWhen invoked, it creates the following declaration:\n\n```go\nfunc (f Foo) bar(s string, i int) string {\n\tpanic(\"unimplemented\")\n}\n```\n\n### `CreateUndeclared`: Create missing declaration for \"undeclared name: X\"\n\nA Go compiler error \"undeclared name: X\" indicates that a variable or function is being used before\nit has been declared in the current scope. In this scenario, gopls offers a quick fix to create the declaration.\n\n#### Declare a new variable\n\nWhen you reference a variable that hasn't been declared:\n\n```go\nfunc main() {\n  x := 42\n  min(x, y) // error: undefined: y\n}\n```\n\nThe quick fix would insert a declaration with a default\nvalue inferring its type from the context:\n\n```go\nfunc main() {\n  x := 42\n  y := 0\n  min(x, y)\n}\n```\n\n#### Declare a new function\n\nSimilarly, if you call a function that hasn't been declared:\n\n```go\nfunc main() {\n  var s string\n  s = doSomething(42) // error: undefined: doSomething\n}\n```\n\nGopls will insert a new function declaration below,\ninferring its type from the call:\n\n```go\nfunc main() {\n  var s string\n  s = doSomething(42)\n}\n\nfunc doSomething(i int) string {\n  panic(\"unimplemented\")\n}\n```\n<!--\n\ndorky details and deletia:\n\n- The **vet suite**, of about thirty analyzers\n  designed to catch likely mistakes in your code.\n\n- **Type-error fixers**. These are gopls-specific analyzers that\n  enrich diagnostics from the type checker by suggesting fixes for\n  simple problems.\n\n  For example, when a return statement has too few operands, the\n  [fillreturns](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns) analyzer can heuristically fill in the missing ones\n  with suitable values.\n\n  The actual diagnostics are produced by the type checker,\n  so these analyzers won't cause you to see any new diagnostics;\n  but they add fixes to existing ones.\n  (The user needs to know this because the settings expose it.)\n\n  currently: fillreturns nonewvars noresultvalues stubmethods undeclaredname unusedvariable\n\n- **Simplifiers**. These are gopls-specific analyzers that\n  suggest ways to rewrite your code more simply.\n  They do not indicate a mistake in your code,\n  which is why they are not part of `go vet`.\n\n  For example, the `simplifyrange` analyzer will eliminate the\n  unnecessary blank variable in `for _ = range v {...}`.\n\n  currently: simplifycompositelit simplifyrange simplifyslice unusedparams infertypeargs\n\n- **Bug detectors**. Gopls has a suite of bug-detecting analyzers that\n    can't be part of vet for some reason. That might be because they\n    have dependencies that vet cannot have (e.g. nilness and\n    unusedwrite, which construct SSA), or because they are tightly\n    integrated with gopls (e.g. embeddirective, which produces lazy\n    fixes through the code action mechanism\n    [But others do that too:  undeclaredname embeddirective unusedparams stubmethods]\n\n  currently: atomicalign deepequalerrors nilness sortslice unusedwrite embeddirective\n\n- **staticcheck**: four suites (S=simple, SA=static analysis, QF=quickfix, ST=stylecheck)\n  Only a hand-picked subset of them are enabled by default.\n\n- **Experimental analyzers**. Gopls has some analyzers that are not\n  enabled by default, because they produce too high a rate of false\n  positives. For example, fieldalignment, shadow.\n\nNote: fillstruct is not a real analyzer.\n\n-->\n"
  },
  {
    "path": "gopls/doc/features/index.md",
    "content": "---\ntitle: \"Gopls: Index of features\"\n---\n\nThis page provides an index of all supported features of gopls that\nare accessible through the [language server protocol](https://microsoft.github.io/language-server-protocol/) (LSP).\nIt is intended for:\n- **users of gopls** learning its capabilities so that they get the most out of their editor;\n- **editor maintainers** adding or improving Go support in an LSP-capable editor; and\n- **contributors to gopls** trying to understand how it works.\n\nIn an ideal world, Go users would not need to know that gopls or even\nLSP exists, as their LSP-enabled editors would implement every facet\nof the protocol and expose each feature in a natural and discoverable\nway. In reality, editors vary widely in their support for LSP, so\nunfortunately these documents necessarily involve many details of the\nprotocol.\n\nWe also list [settings](../settings.md) that affect each feature.\n\nMost features are illustrated with reference to VS Code, but we will\nbriefly mention whether each feature is supported in other popular\nclients, and if so, how to find it. We welcome contributions, edits,\nand updates from users of any editor.\n\nContributors should [update this documentation](../contributing.md#documentation)\nwhen making significant changes to existing features or when adding new ones.\n\n- [Passive](passive.md): features that are always on and require no special action\n  - [Hover](passive.md#hover): information about the symbol under the cursor\n  - [Signature Help](passive.md#signature-help): type information about the enclosing function call\n  - [Document Highlight](passive.md#document-highlight): highlight identifiers referring to the same symbol\n  - [Inlay Hint](passive.md#inlay-hint): show implicit names of struct fields and parameter names\n  - [Semantic Tokens](passive.md#semantic-tokens): report syntax information used by editors to color the text\n  - [Folding Range](passive.md#folding-range): report text regions that can be \"folded\" (expanded/collapsed) in an editor\n  - [Document Link](passive.md#document-link): extracts URLs from doc comments, strings in current file so client can linkify\n- [Diagnostics](diagnostics.md): compile errors and static analysis findings\n- [Navigation](navigation.md): navigation of cross-references, types, and symbols\n  - [Definition](navigation.md#definition): go to definition of selected symbol\n  - [Type Definition](navigation.md#type-definition): go to definition of type of selected symbol\n  - [References](navigation.md#references): list references to selected symbol\n  - [Implementation](navigation.md#implementation): show \"implements\" relationships of selected type\n  - [Document Symbol](navigation.md#document-symbol): outline of symbols defined in current file\n  - [Symbol](navigation.md#symbol): fuzzy search for symbol by name\n  - [Selection Range](navigation.md#selection-range): select enclosing unit of syntax\n  - [Call Hierarchy](navigation.md#call-hierarchy): show outgoing/incoming calls to the current function\n  - [Type Hierarchy](navigation.md#type-hierarchy): show interfaces/implementations of the current type\n- [Completion](completion.md): context-aware completion of identifiers, statements\n- [Code transformation](transformation.md): fixes and refactorings\n  - [Formatting](transformation.md#formatting): format the source code\n  - [Rename](transformation.md#rename): rename a symbol or package\n  - [Organize imports](transformation.md#source.organizeImports): organize the import declaration\n  - [Extract](transformation.md#refactor.extract): extract selection to a new file/function/variable\n  - [Inline](transformation.md#refactor.inline.call): inline a call to a function or method\n  - [Miscellaneous rewrites](transformation.md#refactor.rewrite): various Go-specific refactorings\n  - [Add test for func](transformation.md#source.addTest): create a test for the selected function\n- [Web-based queries](web.md): commands that open a browser page\n  - [Package documentation](web.md#doc): browse documentation for current Go package\n  - [Free symbols](web.md#freesymbols): show symbols used by a selected block of code\n  - [Assembly](web.md#assembly): show listing of assembly code for selected function\n  - [Split package](web.md#splitpkg): split a package into two or more components\n- Support for non-Go files:\n  - [Template files](templates.md): files parsed by `text/template` and `html/template`\n  - [go.mod and go.work files](modfiles.md): Go module and workspace manifests\n  - [Go *.s assembly files](assembly.md): Go assembly files\n- [Command-line interface](../command-line.md): CLI for debugging and scripting (unstable)\n- [Model Context Protocol (MCP)](mcp.md): use some features in AI-assisted environments\n\nYou can find this page from within your editor by executing the\n`gopls.doc.features` [code action](transformation.md#code-actions),\nwhich opens it in a web browser.\nIn VS Code, you can find it on the \"Quick fix\" menu.\n"
  },
  {
    "path": "gopls/doc/features/mcp.md",
    "content": "---\ntitle: \"Gopls: Model Context Protocol support\"\n---\n\nGopls includes an experimental built-in server for the [Model Context\nProtocol](https://modelcontextprotocol.io/introduction) (MCP), allowing it to\nexpose a subset of its functionality to AI assistants in the form of MCP tools.\n\n## Running the MCP server\n\nThere are two modes for running this server: 'attached' and 'detached'. In\nattached mode, the MCP server operates in the context of an active gopls LSP\nsession, and so is able to share memory with your LSP session and observe the\ncurrent unsaved buffer state. In detached mode, gopls interacts with a headless\nLSP session, and therefore only sees saved files on disk.\n\n### Attached mode\n\nTo use the 'attached' mode, run gopls with the `-mcp.listen` flag. For\nexample:\n\n```\ngopls serve -mcp.listen=localhost:8092\n```\n\nThis exposes an HTTP based MCP server using the server-sent event transport\n(SSE), available at `http://localhost:8092/sessions/1` (assuming you have only\none [session](../daemon.md) on your gopls instance).\n\n### Detached mode\n\nTo use the 'detached' mode, run the `mcp` subcommand:\n\n```\ngopls mcp\n```\n\nThis runs a standalone gopls instance that speaks MCP over stdin/stdout.\n\n## Instructions to the model\n\nThis gopls MCP server includes model instructions for its usage, describing\nworkflows for interacting with Go code using its available tools. These\ninstructions are automatically published during the MCP server initialization,\nbut you may want to also load them as additional context in your AI-assisted\nsession, to emphasize their importance. The `-instructions` flag causes them to\nbe printed, so that you can do, for example:\n\n```\ngopls mcp -instructions > /path/to/contextFile.md\n```\n\n## Coding assistant setup\n\nTo use the gopls MCP server with an LLM-based coding assistant,\nyou need to configure the assistant's MCP client to talk to `gopls`.\nBelow are guides for popular assistants.\n\nFirst ensure that gopls v0.20 or higher is installed and available in\nyour `$PATH`. Use this command to install the latest version:\n\n```bash\n$ go install golang.org/x/tools/gopls@latest\n```\n\n### Gemini CLI\n\nFor Gemini CLI, add the following configuration to\n`$HOME/.gemini/extensions/go/gemini-extension.json`:\n\n```json\n{\n  \"name\": \"go\",\n  \"version\": \"0.0.1\",\n  \"mcpServers\": {\n    \"go\": {\n      \"command\": \"gopls\",\n      \"args\": [\"mcp\"]\n    }\n  },\n  \"contextFileName\": \"GEMINI.md\"\n}\n```\n\nThen run this command to emit the model instructions:\n\n```bash\n$ gopls mcp -instructions > ~/.gemini/extensions/go/GEMINI.md\n```\n\nTo verify the connection, use the `/mcp list` command in your Gemini\nsession to view available tools. Alternatively, run `gemini mcp list`\nfrom your shell to inspect active MCP servers and connection status.\n\n### Claude Code\n\nFor Claude Code, run the following command to add `gopls` as an MCP server:\n\n```bash\n$ claude mcp add gopls -- gopls mcp\n```\n\nTo verify the connection and explore available tools:\n\n*   Type `/mcp` inside your Claude session to view the list of tools offering.\n*   Run `claude mcp list` to inspect currently active MCP servers.\n*   Run `claude mcp get gopls` to inspect the configuration details of the server.\n\n## Security considerations\n\nThe gopls MCP server is a wrapper around the functionality ordinarily exposed\nby gopls through the Language Server Protocol (LSP). As such, gopls' tools\nmay perform any of the operations gopls normally performs, including:\n\n- reading files from the file system, and returning their contents in tool\n  results (such as when providing context);\n- executing the `go` command to load package information, which may result in\n  calls to https://proxy.golang.org to download Go modules, and writes to go\n  caches;\n- writing to gopls' cache or persistent configuration files; and\n- uploading weekly telemetry data **if you have opted in** to [Go telemetry](https://go.dev/doc/telemetry).\n\nThe gopls MCP server does not perform any operations not already performed by\ngopls in an ordinary IDE session. Like most LSP servers, gopls does not\ngenerally write directly to your source tree, though it may instruct the client\nto apply edits. Nor does it make arbitrary requests over the network, though it\nmay make narrowly scoped requests to certain services such as the Go module\nmirror or the Go vulnerability database, which can't readily be exploited as a\nvehicle for exfiltration by a confused agent. Nevertheless, these capabilities\nmay require additional consideration when used as part of an AI-enabled system.\n"
  },
  {
    "path": "gopls/doc/features/modfiles.md",
    "content": "---\ntitle: \"Gopls: Support for go.mod and go.work files\"\n---\n\nTODO: document these features for go.{mod,work} files:\n- hover\n- vulncheck\n- add dependency\n- update dependency\n- diagnostics\n\n"
  },
  {
    "path": "gopls/doc/features/navigation.md",
    "content": "---\ntitle: \"Gopls: Navigation features\"\n---\n\nThis page documents gopls features for navigating your source code.\n\n<!-- TODO: screenshots -->\n\n## Definition\n\nThe LSP [`textDocument/definition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition)\nrequest returns the location of the declaration of the symbol under the cursor.\nMost editors provide a command to navigate directly to that location.\n\nA definition query also works in these unexpected places:\n\n- On an **import path**, it returns the list of locations, of\n  each package declaration in the files of the imported package.\n- On a **package declaration**, it returns the location of\n  the package declaration that provides the documentation of that package.\n- On a symbol in a **[`go:linkname` directive](https://pkg.go.dev/cmd/compile)**,\n  it returns the location of that symbol's declaration.\n- On a **[doc link](https://tip.golang.org/doc/comment#doclinks)**, it returns\n  (like [`hover`](passive.md#hover)) the location of the linked symbol.\n- On a file name in a **[`go:embed` directive](https://pkg.go.dev/embed)**,\n  it returns the location of the embedded file.\n- On the declaration of a non-Go function (a `func` with no body),\n  it returns the location of the assembly implementation, if any,\n- On a **return statement**, it returns the location of the function's result variables.\n- On a **goto**, **break**, or **continue** statement, it returns the\n  location of the label, the closing brace of the relevant block statement, or the\n  start of the relevant loop, respectively.\n\n<!-- On a built-in symbol such as `append` or `unsafe.Pointer`, `definition` reports\nthe location of the declaration in the builtin or unsafe pseudo-packages,\nwhich are just documentation. -->\n\nClient support:\n- **VS Code**: Use [Go to Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) (`F12` or `⌘`-click).\n  If the cursor is already at the declaration, the request is instead interpreted as \"Go to References\".\n- **Emacs + eglot**: use [`M-x xref-find-definitions`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html).\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls definition file.go:#offset`\n\n## References\n\nThe LSP [`textDocument/references`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references)\nrequest returns the locations of all identifiers that refer to the symbol under the cursor.\n\nThe references algorithm handles various parts of syntax as follows:\n\n- The references to a **symbol** report all uses of that symbol.\n  In the case of exported symbols this may include locations in other packages.\n- The references to a **package declaration** are all the\n  direct imports of the package, along with all the other package\n  declarations in the same package.\n- It is an error to request the references to a **built-in symbol**\n  such as `int` or `append`,\n  as they are presumed too numerous to be of interest.\n- The references to an **interface method** include references to\n  concrete types that implement the interface. Similarly, the\n  references to a **method of a concrete type** include references to\n  corresponding interface methods.\n- An **embedded field** `T` in a struct type such as `struct{T}` is\n  unique in Go in that it is both a reference (to a type) and a\n  definition (of a field).\n  The `references` operation reports only the references to it [as a field](https://go.dev/issue/63521).\n  To find references to the type, jump to the type declararation first.\n- The references to a module in a **require** directive in a **go.mod** file are\n  the **import** statements in packages of the main module (defined by the go.mod file) that\n  import packages of the required module.\n\nBe aware that a references query returns information only about the\nbuild configuration used to analyze the selected file, so if you ask\nfor the references to a symbol defined in `foo_windows.go`, the result\nwill never include the file `bar_linux.go`, even if that file refers\nto a symbol of the same name; see https://go.dev/issue/65755.\n\nClients can request that the declaration be included among the\nreferences; most do.\n\nClient support:\n- **VS Code**: Use [`Go to References`](https://code.visualstudio.com/docs/editor/editingevolved#_peek) to quickly \"peek\" at the references,\n  or `Find all References` to open the references panel.\n- **Emacs + eglot**: Via [`xref` package](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html): use `M-x xref-find-references`.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls references file.go:#offset`\n\n## Implementation\n\nThe LSP\n[`textDocument/implementation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation)\nrequest queries the relation between abstract and concrete types and\ntheir methods.\n\nInterfaces and concrete types are matched using method sets:\n\n- When invoked on a reference to an **interface type**, it returns the\n  location of the declaration of each type that implements\n  the interface.\n- When invoked on a **concrete type**,\n  it returns the locations of the matching interface types.\n- When invoked on an **interface method**, it returns the corresponding\n  methods of the types that satisfy the interface.\n- When invoked on a **concrete method**,\n  it returns the locations of the matching interface methods.\n\nFor example:\n- `implementation(io.Reader)` includes subinterfaces such as `io.ReadCloser`,\n  and concrete implementations such as `*os.File`. It also includes\n  other declarations equivalent to `io.Reader`.\n- `implementation(os.File)` includes only interfaces, such as\n  `io.Reader` and `io.ReadCloser`.\n\nThe LSP's Implementation feature has a built-in bias towards subtypes,\npossibly because in languages such as Java and C++ the relationship\nbetween a type and its supertypes is explicit in the syntax, so the\ncorresponding \"Go to interfaces\" operation can be achieved as sequence\nof two or more \"Go to definition\" steps: the first to visit the type\ndeclaration, and the rest to sequentially visit ancestors.\n(See https://github.com/microsoft/language-server-protocol/issues/2037.)\n\nIn Go, where there is no syntactic relationship between two types, a\nsearch is required when navigating in either direction between\nsubtypes and supertypes. The heuristic above works well in many cases,\nbut it is not possible to ask for the superinterfaces of\n`io.ReadCloser`. For more explicit navigation between subtypes and\nsupertypes, use the [Type Hierarchy](#Type Hierarchy) feature.\n\nOnly non-trivial interfaces are considered; no implementations are\nreported for type `any`.\n\nWithin the same package, all matching types/methods are reported.\nHowever, across packages, only exported package-level types and their\nmethods are reported, so local types (whether interfaces, or struct\ntypes with methods due to embedding) may be missing from the results.\n<!-- Reason: assignability of local types such as I and J defined thus:\n     package p; func P() {type I interface {...}}\n     package q; func Q() {type J struct {...}}\n     depends on them both being in the same types.Importer \"realm\",\n     but that is not consistent with the \"scalable\" gopls design.\n-->\n\nFunctions, `func` types, and dynamic function calls are matched using signatures:\n\n- When invoked on the `func` token of a **function definition**,\n  it returns the locations of the matching signature types\n  and dynamic call expressions.\n- When invoked on the `func` token of a **signature type**,\n  it returns the locations of the matching concrete function definitions.\n- When invoked on the `(` token of a **dynamic function call**,\n  it returns the locations of the matching concrete function\n  definitions.\n\nIf either the target type or the candidate type are generic, the\nresults will include the candidate type if there is any instantiation\nof the two types that would allow one to implement the other.\n(Note: the matcher doesn't current implement full unification, so type\nparameters are treated like wildcards that may match arbitrary\ntypes, without regard to consistency of substitutions across the\nmethod set or even within a single method.\nThis may lead to occasional spurious matches.)\n\nSince a type may be both a function type and a named type with methods\n(for example, `http.HandlerFunc`), it may participate in both kinds of\nimplementation queries (by method-sets and function signatures).\nQueries using method-sets should be invoked on the type or method name,\nand queries using signatures should be invoked on a `func` or `(` token.\n\nClient support:\n- **VS Code**: Use [Go to Implementations](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation) (`⌘F12`).\n- **Emacs + eglot**: Use `M-x eglot-find-implementation`.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls implementation file.go:#offset`\n\n\n## Type Definition\n\nThe LSP\n[`textDocument/typeDefinition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_typeDefinition)\nrequest returns the location of the type of the selected symbol.\n\nFor example, if the selection is the name `buf` of a local variable of\ntype `*bytes.Buffer`, a `typeDefinition` query will return the\nlocation of the type `bytes.Buffer`.\nClients typically navigate to that location.\n\nType constructors such as pointer, array, slice, channel, and map are\nstripped off the selected type in the search for a named type. For\nexample, if x is of type `chan []*T`, the reported type definition\nwill be that of `T`.\nSimilarly, if the symbol's type is a function with one \"interesting\"\n(named, non-`error`) result type, the function's result type is used.\n\nGopls currently requires that a `typeDefinition` query be applied to a\nsymbol, not to an arbitrary expression; see https://go.dev/issue/67890 for\npotential extensions of this functionality.\n<!-- e.g. selecting a struct field, package name, or other piece of syntax. -->\n\nClient support:\n- **VS Code**: Use [Go to Type Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation).\n- **Emacs + eglot**: Use `M-x eglot-find-typeDefinition`.\n- **Vim + coc.nvim**: ??\n- **CLI**: not supported\n\n## Document Symbol\n\nThe `textDocument/documentSymbol` LSP query reports the list of\ntop-level declarations in this file. Clients may use this information\nto present an overview of the file, and an index for faster navigation.\n\nGopls responds with the\n[`DocumentSymbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbol)\ntype if the client indicates\n[`hierarchicalDocumentSymbolSupport`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolClientCapabilities);\notherwise it returns a\n[`SymbolInformation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#symbolInformation).\n\nClient support:\n- **VS Code**: Use the [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view) for navigation.\n- **Emacs + eglot**: Use [`M-x imenu`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html#Imenu) to jump to a symbol.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls links file.go`\n\n\n## Symbol\n\nThe\n[`workspace/symbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_symbol)\nLSP query searches an index of all the symbols in the workspace.\n\nThe default symbol matching algorithm (`fastFuzzy`), inspired by the\npopular fuzzy matcher [FZF](https://github.com/junegunn/fzf), attempts\na variety of inexact matches to correct for misspellings or abbreviations in your\nquery. For example, it considers `DocSym` a match for `DocumentSymbol`.\n\n<!--\nIt also supports the following special characters within queries:\n\n| Character | Usage     | Match        |\n| --------- | --------- | ------------ |\n| `'`       | `'abc`    | exact        |\n| `^`       | `^printf` | exact prefix |\n| `$`       | `printf$` | exact suffix |\n\nHowever, VS Code does its own fuzzy matching afterward, so these\naren't effective in that client; see golang/vscode-go#647.\n-->\n\nSettings:\n- The [`symbolMatcher`](../settings.md#symbolMatcher) setting controls the algorithm used for symbol matching.\n- The [`symbolStyle`](../settings.md#symbolStyle) setting controls how symbols are qualified in symbol responses.\n- The [`symbolScope`](../settings.md#symbolScope) setting determines the scope of the query.\n- The [`directoryFilters`](../settings.md#directoryFilters) setting specifies directories to be excluded from the search.\n\nClient support:\n- **VS Code**: Use ⌘T to open [Go to Symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol) with workspace scope.  (Alternatively, use Ctrl-Shift-O, and add a `@` prefix to search within the file or a `#` prefix to search throughout the workspace.)\n- **Emacs + eglot**: Use [`M-x xref-find-apropos`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Looking-Up-Identifiers.html) to show symbols that match a search term.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls links file.go`\n\n\n## Selection Range\n\nThe\n[`textDocument/selectionRange`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_selectionRange)\nLSP query returns information about the lexical extent of each piece\nof syntax enclosing the current selection.\nClients may use it to provide an operation to expand the selection\nto successively larger expressions.\n\nClient support:\n- **VSCode**: Use `⌘⇧^→` to expand the selection or `⌘⇧^←` to contract it again; watch this [video](https://www.youtube.com/watch?v=dO4SGAMl7uQ).\n- **Emacs + eglot**: Not standard. Use `M-x eglot-expand-selection` defined in [this configuration snippet](https://github.com/joaotavora/eglot/discussions/1220#discussioncomment-9321061).\n- **Vim + coc.nvim**: ??\n- **CLI**: not supported\n\n## Call Hierarchy\n\nThe LSP CallHierarchy mechanism consists of three queries that\ntogether enable clients to present a hierarchical view of a portion of\nthe static call graph:\n\n- [`textDocument/prepareCallHierarchy`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareCallHierarchy) returns a list of [items](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyItem) for a given position, each representing a named function or method enclosing the position;\n- [`callHierarchyItem/incomingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of call sites that call the selected item; and\n- [`callHierarchy/outgoingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of functions called by the selected item.\n\nInvoke the command while selecting the name in a function declaration.\n\nDynamic calls are not included, because it is not analytically\npractical to detect them. So, beware that the results may not be\nexhaustive, and perform a [References](#references) query if necessary.\n\nThe hierarchy does not consider a nested function distinct from its\nenclosing named function. (Without the ability to detect dynamic\ncalls, it would make little sense do so.)\n\nThe screenshot below shows the outgoing call tree rooted at `f`. The\ntree has been expanded to show a path from `f` to the `String` method\nof `fmt.Stringer` through the guts of `fmt.Sprint:`\n\n<img title=\"Outgoing calls of f\" src=\"../assets/outgoingcalls.png\" width=\"640\">\n\nClient support:\n- **VS Code**: `Show Call Hierarchy` menu item (`⌥⇧H`) opens [Call hierarchy view](https://code.visualstudio.com/docs/cpp/cpp-ide#_call-hierarchy) (note: docs refer to C++ but the idea is the same for Go).\n- **Emacs + eglot**: Not standard; install with `(package-vc-install \"https://github.com/dolmens/eglot-hierarchy\")`. Use `M-x eglot-hierarchy-call-hierarchy` to show the direct incoming calls to the selected function; use a prefix argument (`C-u`) to show the direct outgoing calls. There is no way to expand the tree.\n- **CLI**: `gopls call_hierarchy file.go:#offset` shows outgoing and incoming calls.\n\n\n## Type Hierarchy\n\nThe LSP TypeHierarchy mechanism consists of three queries that\ntogether enable clients to present a hierarchical view of a portion of\nthe subtyping relation over named types.\n\n- [`textDocument/prepareTypeHierarchy`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareTypeHierarchy) returns an [item](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyItem) describing the named type at the current position;\n- [`typeHierarchyItem/subtypes`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_subtypes) returns the set of subtypes of the selected (interface) type; and\n- [`typeHierarchy/supertypes`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_supertypes) returns the set of supertypes (interface types) of the selected type.\n\nInvoke the command while selecting the name of a type.\n\nAs with an Implementation query, a type hierarchy query reports\nfunction-local types only within the same package as the query type.\nAlso the result does not include alias types, only defined types.\n\n<img title=\"Type Hierarchy: supertypes of net.Conn\" src=\"../assets/supertypes.png\" width=\"400\">\n\n<img title=\"Type Hierarchy: subtypes of io.Writer\" src=\"../assets/subtypes.png\" width=\"400\">\n\nCaveats:\n\n- The type hierarchy supports only named types and their assignability\n  relation. By contrast, the Implementations request also reports the\n  relation between unnamed `func` types and function declarations,\n  function literals, and dynamic calls of values of those types.\n\nClient support:\n- **VS Code**: `Show Type Hierarchy` menu item opens [Type hierarchy view](https://code.visualstudio.com/docs/java/java-editing#_type-hierarchy) (note: docs refer to Java but the idea is the same for Go).\n- **Emacs + eglot**: Support added in March 2025. Use `M-x eglot-show-call-hierarchy`.\n- **CLI**: not yet supported.\n"
  },
  {
    "path": "gopls/doc/features/passive.md",
    "content": "---\ntitle: \"Gopls: Passive features\"\n---\n\nThis page documents the fundamental LSP features of gopls that may be\ndescribed as \"passive\", since many editors use them to continuously\nprovide information about your source files without requiring any\nspecial action.\n\nSee also [Code Lenses](../codelenses.md), some of which annotate your\nsource code with additional information and may thus also be\nconsidered passive features.\n\n\n## Hover\n\nThe LSP [`textDocument/hover`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover)\nquery returns a\tdescription of the code currently under the cursor, such\nas its name, kind, type, value (for a constant), abbreviated\ndeclaration (for a type), doc comment (if any), and a link to the\nsymbol's documentation on `pkg.go.dev`. The client may request either\nplain text or Markdown.\n\n<img src='../assets/hover-basic.png'>\n\nDepending on the selection, the response may include additional information.\nFor example, hovering over a type shows its declared methods,\nplus any methods promoted from embedded fields.\n\n**Doc links**: A doc comment may refer to another symbol using square\nbrackets, for example `[fmt.Printf]`. Hovering over one of these\n[doc links](https://go.dev/doc/comment#doclinks) reveals\ninformation about the referenced symbol.\n\n<img src='../assets/hover-doclink.png'>\n\n**Struct size/offset info**: for declarations of struct types,\nhovering over the name reveals the struct's size in bytes:\n\n<img title=\"struct size info\" src=\"../assets/hover-size-struct.png\">\n\nAnd hovering over each field name shows the size and offset of that field:\n\n<img title=\"field size/offset info\" src=\"../assets/hover-size-field.png\">\n\nThis information may be useful when optimizing the layout of your data\nstructures, or when reading assembly files or stack traces that refer\nto each field by its cryptic byte offset.\n\nIn addition, Hover reports:\n- the struct's size class, which is the number of bytes actually\n  allocated by the Go runtime for a single object of this type; and\n- the percentage of wasted space due to suboptimal ordering of struct\n  fields, if this figure is 20% or higher:\n\n<img title=\"a struct with wasted space\" src=\"../assets/hover-size-wasteful.png\">\n\nIn the struct above, alignment rules require each of the two boolean\nfields (1 byte) to occupy a complete word (8 bytes), leading to (7 +\n7) / (3 * 8) = 58% waste.\nPlacing the two booleans together would save a word.\n(In most structures clarity is more important than compactness, so you\nshould reorder fields to save space only in data structures that have\nbeen shown by profiling to be very frequently allocated.)\n\n**Embed directives**: hovering over the file name pattern in\n[`//go:embed` directive](https://pkg.go.dev/embed), for example\n`*.html`, reveals the list of file names to which the wildcard\nexpands.\n\n<img src='../assets/hover-embed.png'>\n<!-- NB: Emacs+eglot displays only the first line of markdown, not the useful part! -->\n\n**Linkname directives**: a [`//go:linkname` directive](https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives) creates a linker-level alias for another symbol.\nHovering over the directive shows information about the other symbol.\n\n<img src='../assets/hover-linkname.png'>\n\nThe hover information for symbols from the standard library added\nafter Go 1.0 states the Go release that added the symbol.\n\nSettings:\n- The [`hoverKind`](../settings.md#hoverKind) setting controls the verbosity of documentation.\n- The [`linkTarget`](../settings.md#linkTarget) setting specifies\n  the base URI for Go package links\n\nCaveats:\n- It is an unfortunate limitation of the LSP that a `Hover` request\n  currently includes only a position but not a selection, as this\n  means it is impossible to request information about the type and\n  methods of, say, the `f(x)` portion of the larger expression\n  `f(x).y`. Please upvote microsoft/language-server-protocol#1466 if\n  you would like to see this addressed.\n\nClient support:\n- **VS Code**: enabled by default. Displays rendered Markdown in a panel near the cursor.\n- **Emacs + eglot**: enabled by default. Displays a one-line summary in the echo area.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls definition file.go:#start-#end` includes information from a Hover query.\n\n\n## Signature Help\n\nThe LSP [`textDocument/signatureHelp`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_signatureHelp)\nquery returns information about the innermost function call enclosing\nthe cursor or selection, including the signature of the function and\nthe names, types, and documentation of each parameter.\n\nClients may provide this information to help remind the user of the\npurpose of each parameter and their order, while reading or editing a\nfunction call.\n\n<img src='../assets/signature-help.png'>\n\nCall parens are not necessary if the cursor is within an identifier\nthat denotes a function or method. For example, Signature Help at\n`once.Do(initialize‸)` will describe `initialize`, not `once.Do`.\n\nClient support:\n- **VS Code**: enabled by default.\n  Also known as \"[parameter hints](https://code.visualstudio.com/api/references/vscode-api#SignatureHelpProvider)\" in the [IntelliSense settings](https://code.visualstudio.com/docs/editor/intellisense#_settings).\n  Displays signature and doc comment alongside Hover information.\n- **Emacs + eglot**: enabled by default. Displays signature in the echo area.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls signature file.go:#start-#end`\n\n\n## Document Highlight\n\nThe LSP [`textDocument/documentHighlight`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight)\nquery reports a set of source ranges that should be highlighted based\non the current cursor position or selection, to emphasize the\nrelationship between them.\n\nEach of the following parts of syntax forms a set so that if you\nselect any one member, gopls will highlight the complete set:\n\n- each identifier that refers to the same symbol (as in the screenshot below);\n- a named result variable and all its corresponding operands of `return` statements;\n- the `for`, `break`, and `continue` tokens of the same loop;\n- the `switch` and `break` tokens of the same switch statement;\n- the `func` keyword of a function and all of its `return` statements.\n\nMore than one of these rules may be activated by a single selection,\nfor example, by an identifier that is also a return operand.\n\nDifferent occurrences of the same identifier may be color-coded to distinguish\n\"read\" from \"write\" references to a given variable symbol.\n\n<img src='../assets/document-highlight.png'>\n\nClient support:\n- **VS Code**: enabled by default. Triggered by cursor motion, or single click.\n  (Note: double clicking activates a simple syntax-oblivious textual match.)\n- **Emacs + eglot**: enabled by default. Triggered by cursor motion or selection.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls signature file.go:#start-#end`\n\n\n## Inlay Hint\n\nThe LSP [`textDocument/inlayHint`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint)\nquery returns a set of annotations to be spliced into the current file\nthat reveal implicit information.\n\n<img src='../assets/inlayhint-parameternames.png'>\n\nExamples:\n\n- In a function call `f(1, 2)`, hints provide the\n  names of the parameters (`parameterNames`), as in the screenshot above.\n- In a call to a generic function, hints provide the type arguments\n  (`functionTypeParameters`).\n- In an assignment `x, y = 1, 2`, hints provide the types of the\n  variables (`assignVariableTypes`).\n- In a struct literal such as `Point2D{1, 2}`, hints provide the field\n  names (`compositeLiteralFields`).\n- In a nested composite literal `T{{...}}`, a hint provides the type of\n  the inner literal, `{...}` (`compositeLiteralTypes`).\n- In a `for k, v := range x {}` loop, hints provide the types of the\n  variables k and v (`rangeVariableTypes`).\n- For a constant expression (perhaps using `iota`), a hint provides\n  its computed value (`constantValues`).\n\nSee [Inlay hints](../inlayHints.md) for a complete list with examples.\n\n<!--\nTODO: Do we really need that separate doc? We could put all the\n     information here with much less fuss. It changes so rarely that a\n     culture of \"update the tests and docs in every CL\" should be sufficient.\n     IIUC, VS Code needs only the api-json representation.\n-->\n\nSettings:\n- The [`hints`](../settings.md#hints) setting indicates the desired set of hints.\n  To reduce distractions, its default value is empty.\n  To enable hints, add one or more of the identifiers above to the hints\n  map. For example:\n  ```json5\n  \"hints\": {\"parameterNames\": true}\n  ```\n\nClient  support:\n- **VS Code**: in addition to the `hints` configuration value, VS Code provides a graphical\n  configuration menu (\"Preferences: Open Settings (UI)\" the search for \"Go Inlay Hints\")\n  for each supported kind of inlay hint.\n- **Emacs + eglot**: disabled by default. Needs `M-x eglot-inlay-hints-mode` plus the configuration [described here](https://www.reddit.com/r/emacs/comments/11bqzvk/emacs29_and_eglot_inlay_hints/)\n- **Vim + coc.nvim**: ??\n- **CLI**: not supported\n\n## Semantic Tokens\n\nThe LSP [`textDocument/semanticTokens`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens)\nquery reports information about all the tokens in the current file, or\na portion of it.\nThe client may use this information to provide syntax highlighting\nthat conveys semantic distinctions between, for example, functions and\ntypes, constants and variables, or library functions and built-ins.\n\nThe client must specify the sets of types and modifiers it is interested in.\n\nGopls reports the following token types:\n\n- `\"comment\"`: a comment\n- `\"function\"`: a function\n- `\"keyword\"`: a keyword\n- `\"label\"`: a control label (not an LSP standard type)\n- `\"macro\"`: text/template tokens\n- `\"method\"`: a method\n- `\"namespace\"`: an imported package name\n- `\"number\"`: a numeric literal\n- `\"operator\"`: an operator\n- `\"parameter\"`: a parameter variable\n- `\"string\"`:  a string literal\n- `\"type\"`: a type name (plus other uses)\n- `\"typeParameter\"`: a type parameter\n- `\"variable\"`: a var or const (see `readonly` modifier)\n\nGopls also reports the following standard modifiers:\n\n- `\"defaultLibrary\"`: predeclared symbols\n- `\"definition\"`: the declaring identifier of a symbol\n- `\"readonly\"`: for constants\n\nplus these non-standard modifiers each representing the top-level\nconstructor of each symbols's type:\n\n- `\"array\"`\n- `\"bool\"`\n- `\"chan\"`\n- `\"interface\"`\n- `\"map\"`\n- `\"number\"`\n- `\"pointer\"`\n- `\"signature\"`\n- `\"slice\"`\n- `\"string\"`\n- `\"struct\"`\n\nSettings:\n- The [`semanticTokens`](../settings.md#semanticTokens) setting determines whether\n  gopls responds to semantic token requests. This option allows users to disable\n  semantic tokens even when their client provides no client-side control over the\n  feature. Because gopls' semantic-tokens algorithm depends on type checking,\n  which adds a tangible latency, this feature is currently disabled by default\n  to avoid any delay in syntax highlighting; see https://go.dev/issue/#45313, https://go.dev/issue/#47465.\n- The experimental [`noSemanticString`](../settings.md#noSemanticString) and\n  [`noSemanticNumber`](../settings.md#noSemanticNumber) settings cause the server\n  to exclude the `string` and `number` kinds from the response, as some clients\n  may do a more colorful job highlighting these tokens; see https://go.dev/issue/45753.\n\nClient Support:\n- **VS Code**: See [Semantic Highlighting Guide](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide).\n- **Emacs + eglot**: Not supported; see joaotavora/eglot#615.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls semtok file.go`\n\n## Folding Range\n\nThe LSP [`textDocument/foldingRange`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange)\nquery reports the list of regions in the current file that may be\nindependently collapsed or expanded. For example, it may be convenient\nto collapse large comments or functions when studying some code so\nthat more of it fits in a single screen.\n\n<img title=\"A function FoldingRange, collapsed, in VS Code\" src=\"../assets/foldingrange.png\" width=\"640\">\n\nThe protocol [allows](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#foldingRangeClientCapabilities) clients to indicate whether they prefer\nfine-grained ranges such as matched pairs of brackets, or only ranges\nconsisting of complete lines.\n\nClient support:\n- **VS Code**: displayed in left margin. Toggle the chevrons (`∨` and `>`) to collapse or expand.\n- **Emacs + eglot**: not supported.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls folding_ranges file.go`\n\n## Document Link\n\nThe LSP [`textDocument/documentLink`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink)\nquery uses heuristics to extracts URLs from doc comments and string\nliterals in the current file so that the client can present them as\nclickable links.\n\n<img src='../assets/documentlink.png'>\n\nIn addition to explicit URLs, gopls also turns string literals in\nimport declarations into links to the pkg.go.dev documentation for the\nimported package.\n\nSettings:\n- The [`importShortcut`](../settings.md#importShortcut) setting determines\n  what kind of link is returned for an `import` declaration.\n- The [`linkTarget`](../settings.md#linkTarget) setting specifies\n  the base URI for Go package links.\n\nClient support:\n- **VS Code**: Hovering over a link displays a \"Follow link (cmd+click)\" popup.\n- **Emacs + eglot**: not currently used.\n- **Vim + coc.nvim**: ??\n- **CLI**: `gopls links file.go`\n"
  },
  {
    "path": "gopls/doc/features/templates.md",
    "content": "---\ntitle: \"Gopls: Support for template files\"\n---\n\nGopls provides some support for Go template files, that is, files that\nare parsed by [`text/template`](https://pkg.go.dev/text/template) or\n[`html/template`](https://pkg.go.dev/html/template).\n\n## Enabling template support\n\nGopls recognizes template files based on their file extension, which\nmay be configured by the\n[`templateExtensions`](../settings.md#templateExtensions) setting. If\nthis list is empty, template support is disabled. (This is the default\nvalue, since Go templates don't have a canonical file extension.)\n\nAdditional configuration may be necessary to ensure that your client\nchooses the correct language kind when opening template files.\nGopls recognizes both `\"tmpl\"` and `\"gotmpl\"` for template files.\nFor example, in `VS Code` you will also need to add an\nentry to the\n[`files.associations`](https://code.visualstudio.com/docs/languages/identifiers)\nmapping:\n```json\n\"files.associations\": {\n  \".mytemplate\": \"gotmpl\"\n},\n```\n\n\n## Features\nIn template files, template support works inside\nthe default `{{` delimiters. (Go template parsing\nallows the user to specify other delimiters, but\ngopls does not know how to do that.)\n\nGopls template support includes the following features:\n+ **Diagnostics**: if template parsing returns an error,\nit is presented as a diagnostic. (Missing functions do not produce errors.)\n+ **Syntax Highlighting**: syntax highlighting is provided for template files.\n+ **Definitions**: gopls provides jump-to-definition inside templates, though it does not understand scoping (all templates are considered to be in one global scope).\n+ **References**: gopls provides find-references, with the same scoping limitation as definitions.\n+ **Completions**: gopls will attempt to suggest completions inside templates.\n\nTODO: also\n+ Hover\n+ SemanticTokens\n+ Symbol search\n+ DocumentHighlight\n\n\n"
  },
  {
    "path": "gopls/doc/features/transformation.md",
    "content": "---\ntitle: \"Gopls: Code transformation features\"\n---\n\nThis document describes gopls' features for code transformation, which\ninclude a range of behavior-preserving changes (refactorings,\nformatting, simplifications), code repair (fixes), and editing support\n(filling in struct literals and switch statements).\n\nCode transformations are not a single category in the LSP:\n\n- A few, such as Formatting and Rename, are primary operations in the\n  protocol.\n- Some transformations are exposed through [Code Lenses](../codelenses.md),\n  which return _commands_, arbitrary server\n  operations invoked for their side effects through a\n  [`workspace/executeCommand`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_executeCommand) request;\n  however, no current code lenses are transformations of Go syntax.\n  <!-- Generate, RegenerateCgo (Go); Tidy, UpgradeDependency, Vendor (go.mod) -->\n- Most transformations are defined as *code actions*.\n\n## Code Actions\n\nA **code action** is an action associated with a portion of the file.\nEach time the selection changes, a typical client makes a\n[`textDocument/codeAction`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction)\nrequest for the set of available actions, then updates its UI\nelements (menus, icons, tooltips) to reflect them.\nThe VS Code manual describes code actions as\n\"[Quick fixes + Refactorings](https://code.visualstudio.com/docs/editor/refactoring#_code-actions-quick-fixes-and-refactorings)\".\n\nA `codeAction` request delivers the menu, so to speak, but it does\nnot order the meal. Once the user chooses an action, one of two things happens.\nIn trivial cases, the action itself contains an edit that the\nclient can directly apply to the file.\nBut in most cases the action contains a command,\nsimilar to the command associated with a code lens.\nThis allows the work of computing the patch to be done lazily, only\nwhen actually needed. (Most aren't.)\nThe server may then compute the edit and send the client a\n[`workspace/applyEdit`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_applyEdit)\nrequest to patch the files.\nNot all code actions' commands have an `applyEdit` side effect: some\nmay change the state of the server, for example to toggle a variable\nor to cause the server to send other requests to the client,\nsuch as a `showDocument` request to open a report in a web browser.\n\nThe main difference between code lenses and code actions is this:\n\n- a `codeLens` request obtains commands for the entire file.\n  Each command specifies its applicable source range,\n  and typically appears as an annotation on that source range.\n- a `codeAction` request obtains commands only for a particular range: the current selection.\n  All the commands are presented together in a menu at that location.\n\nEach action has a _kind_,\nwhich is a hierarchical identifier such as `refactor.inline.call`.\nClients may filter actions based on their kind.\nFor example, VS Code has:\ntwo menus, \"Refactor...\" and \"Source action...\", each populated by\ndifferent kinds of code actions (`refactor` and `source`);\na lightbulb icon that triggers a menu of \"quick fixes\" (of kind `quickfix`);\nand a \"Fix All\" command that executes all code actions of\nkind `source.fixAll`, which are those deemed unambiguously safe to apply.\n\nGopls supports the following code actions:\n\n- `quickfix`, which applies unambiguously safe fixes <!-- TODO: document -->\n- [`source.organizeImports`](#source.organizeImports)\n- [`source.assembly`](web.md#assembly)\n- [`source.doc`](web.md#doc)\n- [`source.freesymbols`](web.md#freesymbols)\n- `source.test` (undocumented) <!-- TODO: fix that -->\n- [`source.addTest`](#source.addTest)\n- [`source.toggleCompilerOptDetails`](diagnostics.md#toggleCompilerOptDetails)\n- [`gopls.doc.features`](README.md), which opens gopls' index of features in a browser\n- [`refactor.extract.constant`](#extract)\n- [`refactor.extract.function`](#extract)\n- [`refactor.extract.method`](#extract)\n- [`refactor.extract.toNewFile`](#extract.toNewFile)\n- [`refactor.extract.variable`](#extract)\n- [`refactor.extract.variable-all`](#extract)\n- [`refactor.inline.call`](#refactor.inline.call)\n- [`refactor.inline.variable`](#refactor.inline.variable)\n- [`refactor.rewrite.addTags`](#refactor.rewrite.addTags)\n- [`refactor.rewrite.changeQuote`](#refactor.rewrite.changeQuote)\n- [`refactor.rewrite.fillStruct`](#refactor.rewrite.fillStruct)\n- [`refactor.rewrite.fillSwitch`](#refactor.rewrite.fillSwitch)\n- [`refactor.rewrite.invertIf`](#refactor.rewrite.invertIf)\n- [`refactor.rewrite.joinLines`](#refactor.rewrite.joinLines)\n- [`refactor.rewrite.moveParamLeft`](#refactor.rewrite.moveParamLeft)\n- [`refactor.rewrite.moveParamRight`](#refactor.rewrite.moveParamRight)\n- [`refactor.rewrite.removeTags`](#refactor.rewrite.removeTags)\n- [`refactor.rewrite.removeUnusedParam`](#refactor.rewrite.removeUnusedParam)\n- [`refactor.rewrite.splitLines`](#refactor.rewrite.splitLines)\n\nGopls reports some code actions twice, with two different kinds, so\nthat they appear in multiple UI elements: simplifications,\nfor example from `for _ = range m` to `for range m`,\nhave kinds `quickfix` and `source.fixAll`,\nso they appear in the \"Quick Fix\" menu and\nare activated by the \"Fix All\" command.\n\n<!-- In principle the filter may include the trigger event\n     e.g. auto (cursor motion) vs. invoked (open a menu)\n     but gopls currently ignores it. -->\n\nMany transformations are computed by [analyzers](../analyzers.md)\nthat, in the course of reporting a diagnostic about a problem,\nalso suggest a fix.\nA `codeActions` request will return any fixes accompanying diagnostics\nfor the current selection.\n\n<!-- Some gopls-internal analyzers compute fixes lazily by\n     reporting an empty list of TextEdits and a Diagnostic.Category\n     recognized by gopls that enables corresponding logic in the\n     server's ApplyFix command handler. -->\n\n<!-- The source.test (\"Run this test\") code action (not a\n     transformation) runs the selected test. However, it is not\n     offered by default because:\n     (a) VS Code has a richer test UX (with richer ones to come--see\n         https://github.com/golang/vscode-go/issues/1641) and\n     (b) LSP has no good way to display the streaming output of a test\n         in the client's natural UX (see last paragraph of first note\n\t of https://github.com/golang/go/issues/67400).\n     It is only offered when the \"only\" field includes kind source.test.\n     Should it be documented? If so, where?\n-->\n\nCaveats:\n\n- Many of gopls code transformations are limited by Go's syntax tree\n  representation, which currently records comments not in the tree\n  but in a side table; consequently, transformations such as Extract\n  and Inline are prone to losing comments. This is issue\n  https://go.dev/issue/20744, and it is a priority for us to fix in 2024.\n\n- Generated files, as identified by the conventional\n  [DO NOT EDIT](https://go.dev/s/generatedcode) comment,\n  are not offered code actions for transformations.\n  <!-- TODO: this is frankly a nuisance. It is often convenient to modify generated files -->\n\nClient support for code actions:\n\n- **VS Code**: Depending on their kind, code actions are found in\n  the \"Refactor...\" menu (`^⇧R`),\n  the \"Source action...\" menu,\n  the 💡 (light bulb) icon's menu, or\n  the \"Quick fix\" (`⌘.`) menu.\n  The \"Fix All\" command applies all actions of kind `source.fixAll`.\n- **Emacs + eglot**: Code actions are invisible.\n  Use `M-x eglot-code-actions` to select one from those that are\n  available (if there are multiple) and execute it.\n  Some action kinds have filtering shortcuts,\n  e.g. [`M-x eglot-code-action-{inline,extract,rewrite}`](https://joaotavora.github.io/eglot/#index-M_002dx-eglot_002dcode_002daction_002dinline).\n- **CLI**: `gopls codeaction -exec -kind k,... -diff file.go:#123-#456` executes code actions of the specified\n  kinds (e.g. `refactor.inline`) on the selected range, specified using zero-based byte offsets, and displays the diff.\n\n<a name='formatting'></a>\n## Formatting\n\nThe LSP\n[`textDocument/formatting`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting)\nrequest returns edits that format a file.\nGopls applies Go's canonical formatting algorithm,\n[`go fmt`](https://pkg.go.dev/cmd/gofmt).\nLSP formatting options are ignored.\n\nMost clients are configured to format files and organize imports\nwhenever a file is saved.\n\nSettings:\n\n- The [`gofumpt`](../settings.md#gofumpt) setting causes gopls to use an\n  alternative formatter, [`github.com/mvdan/gofumpt`](https://pkg.go.dev/mvdan.cc/gofumpt).\n\nClient support:\n\n- **VS Code**: Formats on save by default. Use `Format document` menu item (`⌥⇧F`) to invoke manually.\n- **Emacs + eglot**: Use `M-x eglot-format-buffer` to format. Attach it to `before-save-hook` to format on save. For formatting combined with organize-imports, many users take the legacy approach of setting `\"goimports\"` as their `gofmt-command` using [go-mode](https://github.com/dominikh/go-mode.el), and adding `gofmt-before-save` to `before-save-hook`. An LSP-based solution requires code such as https://github.com/joaotavora/eglot/discussions/1409.\n- **CLI**: `gopls format file.go`\n\n<a name='source.organizeImports'></a>\n## `source.organizeImports`: Organize imports\n\nA `codeActions` request in a file whose imports are not organized will\nreturn an action of the standard kind `source.organizeImports`.\nIts command has the effect of organizing the imports:\ndeleting existing imports that are duplicate or unused,\nadding new ones for undefined symbols,\nand sorting them into the conventional order.\n\nThe addition of new imports is based on heuristics that depend on\nyour workspace and the contents of your GOMODCACHE directory; they may\nsometimes make surprising choices.\n\nMany editors automatically organize imports and format the code before\nsaving any edited file.\n\nSome users dislike the automatic removal of imports that are\nunreferenced because, for example, the sole line that refers to the\nimport is temporarily commented out for debugging; see https://go.dev/issue/54362.\n\nSettings:\n\n- The [`local`](../settings.md#local) setting is a comma-separated list of\n  prefixes of import paths that are \"local\" to the current file and\n  should appear after standard and third-party packages in the sort order.\n\nClient support:\n\n- **VS Code**: automatically invokes `source.organizeImports` before save.\n  To disable it, use the snippet below, and invoke the \"Organize Imports\" command manually as needed.\n  ```\n  \"[go]\": {\n    \"editor.codeActionsOnSave\": { \"source.organizeImports\": false }\n  }\n  ```\n- **Emacs + eglot**: Use `M-x eglot-code-action-organize-imports` to invoke manually.\n  Many users of [go-mode](https://github.com/dominikh/go-mode.el) use these lines to\n  organize imports and reformat each modified file before saving it, but this\n  approach is based on the legacy\n  [`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) tool, not gopls:\n  ```lisp\n  (setq gofmt-command \"goimports\")\n  (add-hook 'before-save-hook 'gofmt-before-save)\n  ```\n- **CLI**: `gopls fix -a file.go:#offset source.organizeImports`\n\n<a name='source.addTest'></a>\n## `source.addTest`: Add test for function or method\n\nIf the selected chunk of code is part of a function or method declaration F,\ngopls will offer the \"Add test for F\" code action, which adds a new test for the\nselected function in the corresponding `_test.go` file. The generated test takes\ninto account its signature, including input parameters and results.\n\n**Test file**: if the `_test.go` file does not exist, gopls creates it, based on\nthe name of the current file (`a.go` -> `a_test.go`), copying any copyright and\nbuild constraint comments from the original file.\n\n**Test package**: for new files that test code in package `p`, the test file\nuses `p_test` package name whenever possible, to encourage testing only exported\nfunctions. (If the test file already exists, the new test is added to that file.)\n\n**Parameters**: each of the function's non-blank parameters becomes an item in\nthe struct used for the table-driven test. (For each blank `_` parameter, the\nvalue has no effect, so the test provides a zero-valued argument.)\n\n**Contexts**: If the first parameter is `context.Context`, the test passes\n`context.Background()`.\n\n**Results**: the function's results are assigned to variables (`got`, `got2`,\nand so on) and compared with expected values (`want`, `want2`, etc.`) defined in\nthe test case struct. The user should edit the logic to perform the appropriate\ncomparison. If the final result is an `error`, the test case defines a `wantErr`\nboolean.\n\n**Method receivers**: When testing a method `T.F` or `(*T).F`, the test must\nconstruct an instance of T to pass as the receiver. Gopls searches the package\nfor a suitable function that constructs a value of type T or \\*T, optionally with\nan error, preferring a function named `NewT`.\n\n**Imports**: Gopls adds missing imports to the test file, using the last\ncorresponding import specifier from the original file. It avoids duplicate\nimports, preserving any existing imports in the test file.\n\n<img title=\"Add test for func\" src=\"../assets/add-test-for-func.png\" width='80%'>\n\n<a name='rename'></a>\n## Rename\n\nThe LSP\n[`textDocument/rename`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename)\nrequest renames a symbol.\n\nRenaming is a two-stage process. The first step, a\n[`prepareRename`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename) query, returns the current\nname of the identifier under the cursor (if indeed there is one).\nThe client then displays a dialog prompting the user to choose a new\nname by editing the old one. The second step, `rename` proper, applies\nthe changes. (This simple dialog support is unique among LSP\nrefactoring operations; see microsoft/language-server-protocol#1164.)\n\nGopls' renaming algorithm takes great care to detect situations in\nwhich renaming might introduce a compilation error.\nFor example, changing a name may cause a symbol to become \"shadowed\",\nso that some existing references are no longer in scope. Gopls will\nreport an error, stating the pair of symbols and the shadowed reference:\n\n<img title=\"Renamed failed due to a shadowing conflict\" src=\"../assets/rename-conflict.png\">\n\nAs another example, consider renaming a method of a concrete type.\nRenaming may cause the type to no longer satisfy the same interfaces\nas before, which could cause the program to fail to compile.\nTo avoid this, gopls inspects each conversion (explicit or implicit)\nfrom the affected type to an interface type, and checks whether it\nwould remain valid after the renaming. If not, it aborts the renaming\nwith an error.\n\nIf you intend to rename both the original method and the corresponding\nmethods of any matching interface types (as well as any methods of\ntypes matching them in turn), you can indicate this by invoking the\nrename operation on the interface method.\n\nSimilarly, gopls will report an error if you rename a field of a\nstruct that happens to be an \"anonymous\" field that embeds a type,\nsince that would require a larger renaming involving the type as well.\nIf that is what you intend, you can again indicate this by\ninvoking the rename operation on the type.\n\nRenaming should never introduce a compilation error, but it may\nintroduce dynamic errors. For example, in a method renaming, if there\nis no direct conversion of the affected type to the interface type,\nbut there is an intermediate conversion to a broader type (such as `any`) followed by a\ntype assertion to the interface type, then gopls may proceed to rename\nthe method, causing the type assertion to fail at run time.\nSimilar problems may arise with packages that use reflection, such as\n`encoding/json` or `text/template`. There is no substitute for good\njudgment and testing.\n\nSpecial cases:\n\n- When renaming the declaration of a method receiver, the tool also\n  attempts to rename the receivers of all other methods associated\n  with the same named type. Each other receiver that cannot be fully\n  renamed is quietly skipped. Renaming any _use_ of a receiver affects\n  only that variable.\n\n  ```go\n  type Counter struct { x int }\n\n                   Rename here to affect only this method\n                            ↓\n  func (c *Counter) Inc() { c.x++ }\n  func (c *Counter) Dec() { c.x++ }\n        ↑\n    Rename here to affect all methods\n  ```\n\nUsing Rename to move a package:\nTo rename a package, execute the Rename operation over the `p` in a\n`package p` declaration at the start of a file.\nYou will be prompted to edit the package's path and choose its new location.\nThe Rename operation will move all the package's files to the resulting directory,\ncreating it if necessary.\nBy default, subpackages will remain where they are. To include subpackages\nin the renaming, set [renameMovesSubpackages](../settings.md#renamemovessubpackages-bool) to true.\nExisting imports of the package will be updated to reflect its new path.\n\nPackage moves are rejected if they would break the build. For example:\n- Packages cannot move across a module boundary.\n- Packages cannot be moved into existing packages; gopls does not support package merging.\n- Packages cannot be moved to internal directories that would make them inaccessible to any of their current importers.\n\nRenaming package main is not supported, because the main package has special meaning to the linker.\nRenaming x_test packages is currently not supported.\n\nSome tips for best results:\n\n- The safety checks performed by the Rename algorithm require type\n  information. If the program is grossly malformed, there may be\n  insufficient information for it to run (https://go.dev/issue/41870),\n  and renaming cannot generally be used to fix a type error (https://go.dev/issue/41851).\n  When refactoring, we recommend working in small steps, repairing any\n  problems as you go, so that as much as possible of the program\n  compiles at each step.\n- Sometimes it may be desirable for a renaming operation to change the\n  reference structure of the program, for example to intentionally\n  combine two variables x and y by renaming y to x.\n  The renaming tool is too strict to help in this case (https://go.dev/issue/41852).\n\n<!-- known issue: when renaming an interface method, gopls doesn't properly\n     traverse W-shaped import graphs looking for matching types; see https://go.dev/issue/58461. -->\n\nFor the gory details of gopls' rename algorithm, you may be interested\nin the latter half of this 2015 GothamGo talk:\n[Using go/types for Code Comprehension and Refactoring Tools](https://www.youtube.com/watch?v=p_cz7AxVdfg).\n\nClient support:\n\n- **VS Code**: Use \"[Rename symbol](https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol)\" menu item (`F2`).\n- **Emacs + eglot**: Use `M-x eglot-rename`, or `M-x go-rename` from [go-mode](https://github.com/dominikh/go-mode.el).\n- **Vim + coc.nvim**: Use the `coc-rename` command.\n- **CLI**: `gopls rename file.go:#offset newname`\n\n<a name='refactor.extract'></a>\n## `refactor.extract`: Extract function/method/variable\n\nThe `refactor.extract` family of code actions all return commands that\nreplace the selected expression or statements with a reference to a\nnewly created declaration that contains the selected code:\n\n- **`refactor.extract.function`** replaces one or more complete statements by a\n  call to a new function named `newFunction` whose body contains the\n  statements. The selection must enclose fewer statements than the\n  entire body of the existing function.\n\n  ![Before extracting a function](../assets/extract-function-before.png)\n  ![After extracting a function](../assets/extract-function-after.png)\n\n- **`refactor.extract.method`** is a variant of \"Extract function\" offered when\n  the selected statements belong to a method. The newly created function\n  will be a method of the same receiver type.\n\n- **`refactor.extract.variable`** replaces an expression by a reference to a new\n  local variable named `newVar` initialized by the expression:\n\n  ![Before extracting a var](../assets/extract-var-before.png)\n  ![After extracting a var](../assets/extract-var-after.png)\n\n- **`refactor.extract.constant** does the same thing for a constant\n  expression, introducing a local const declaration.\n- **`refactor.extract.variable-all`** replaces all occurrences of the selected expression\nwithin the function with a reference to a new local variable named `newVar`.\nThis extracts the expression once and reuses it wherever it appears in the function.\n\n  ![Before extracting all occurrences of EXPR](../assets/extract-var-all-before.png)\n  ![After extracting all occurrences of EXPR](../assets/extract-var-all-after.png)\n\n  - **`refactor.extract.constant-all** does the same thing for a constant\n  expression, introducing a local const declaration.\nIf the default name for the new declaration is already in use, gopls\ngenerates a fresh name.\n\nExtraction is a challenging problem requiring consideration of\nidentifier scope and shadowing, control\nflow such as `break`/`continue` in a loop or `return` in a\nfunction, cardinality of variables, and even subtle issues of style.\nIn each case, the tool will try to update the extracted statements\nas needed to avoid build breakage or behavior changes.\nUnfortunately, gopls' Extract algorithms are considerably less\nrigorous than the Rename and Inline operations, and we are aware of a\nnumber of cases where it falls short, including:\n\n- https://github.com/golang/go/issues/66289\n- https://github.com/golang/go/issues/65944\n- https://github.com/golang/go/issues/63394\n- https://github.com/golang/go/issues/61496\n\nThe following Extract features are planned for 2024 but not yet supported:\n\n- **Extract parameter struct** will replace two or more parameters of a\n  function by a struct type with one field per parameter; see https://go.dev/issue/65552.\n  <!-- TODO(adonovan): review and land https://go.dev/cl/620995. -->\n  <!-- Should this operation update all callers? That's more of a Change Signature. -->\n- **Extract interface for type** will create a declaration of an\n  interface type with all the methods of the selected concrete type;\n  see https://go.dev/issue/65721 and https://go.dev/issue/46665.\n\n<a name='refactor.extract.toNewFile'></a>\n## `refactor.extract.toNewFile`: Extract declarations to new file\n\n(Available from gopls/v0.17.0)\n\nIf you select one or more top-level declarations, gopls will offer an\n\"Extract declarations to new file\" code action that moves the selected\ndeclarations into a new file whose name is based on the first declared\nsymbol.\nImport declarations are created as needed.\nGopls also offers this code action when the selection is just the\nfirst token of the declaration, such as `func` or `type`.\n\n![Before: select the declarations to move](../assets/extract-to-new-file-before.png)\n![After: the new file is based on the first symbol name](../assets/extract-to-new-file-after.png)\n\n<a name='refactor.inline.call'></a>\n\n## `refactor.inline.call`: Inline call to function\n\nFor a `codeActions` request where the selection is (or is within) a\ncall of a function or method, gopls will return a command of kind\n`refactor.inline.call`, whose effect is to inline the function call.\n\nThe screenshots below show a call to `sum` before and after inlining:\n\n<!-- source code used for images:\n\nfunc six() int {\n\treturn sum(1, 2, 3)\n}\n\nfunc sum(values ...int) int {\n\ttotal := 0\n\tfor _, v := range values {\n\t\ttotal += v\n\t}\n\treturn total\n}\n-->\n\n![Before: select Refactor... Inline call to sum](../assets/inline-before.png)\n![After: the call has been replaced by the sum logic](../assets/inline-after.png)\n\nInlining replaces the call expression by a copy of the function body,\nwith parameters replaced by arguments.\nInlining is useful for a number of reasons.\nPerhaps you want to eliminate a call to a deprecated\nfunction such as `ioutil.ReadFile` by replacing it with a call to the\nnewer `os.ReadFile`; inlining will do that for you.\nOr perhaps you want to copy and modify an existing function in some\nway; inlining can provide a starting point.\nThe inlining logic also provides a building block for\nother refactorings, such as \"change signature\".\n\nNot every call can be inlined.\nOf course, the tool needs to know which function is being called, so\nyou can't inline a dynamic call through a function value or interface\nmethod; but static calls to methods are fine.\nNor can you inline a call if the callee is declared in another package\nand refers to non-exported parts of that package, or to [internal\npackages](https://go.dev/doc/go1.4#internalpackages) that are\ninaccessible to the caller.\nCalls to generic functions are not yet supported\n(https://go.dev/issue/63352), though we plan to fix that.\n\nWhen inlining is possible, it's critical that the tool preserve\nthe original behavior of the program.\nWe don't want refactoring to break the build, or, worse, to introduce\nsubtle latent bugs.\nThis is especially important when inlining tools are used to perform\nautomated clean-ups in large code bases;\nwe must be able to trust the tool.\nOur inliner is very careful not to make guesses or unsound\nassumptions about the behavior of the code.\nHowever, that does mean it sometimes produces a change that differs\nfrom what someone with expert knowledge of the same code might have\nwritten by hand.\n\nIn the most difficult cases, especially with complex control flow, it\nmay not be safe to eliminate the function call at all.\nFor example, the behavior of a `defer` statement is intimately tied to\nits enclosing function call, and `defer` is the only control\nconstruct that can be used to handle panics, so it cannot be reduced\ninto simpler constructs.\nSo, for example, given a function f defined as:\n\n```go\nfunc f(s string) {\n\tdefer fmt.Println(\"goodbye\")\n\tfmt.Println(s)\n}\n```\n\na call `f(\"hello\")` will be inlined to:\n\n```go\n\tfunc() {\n\t\tdefer fmt.Println(\"goodbye\")\n\t\tfmt.Println(\"hello\")\n\t}()\n```\n\nAlthough the parameter was eliminated, the function call remains.\n\nAn inliner is a bit like an optimizing compiler.\nA compiler is considered \"correct\" if it doesn't change the meaning of\nthe program in translation from source language to target language.\nAn _optimizing_ compiler exploits the particulars of the input to\ngenerate better code, where \"better\" usually means more efficient.\nAs users report inputs that cause the compiler to emit suboptimal\ncode, the compiler is improved to recognize more cases, or more rules,\nand more exceptions to rules---but this process has no end.\nInlining is similar, except that \"better\" code means tidier code.\nThe most conservative translation provides a simple but (hopefully)\ncorrect foundation, on top of which endless rules, and exceptions to\nrules, can embellish and improve the quality of the output.\n\nHere are some of the technical challenges involved in sound inlining:\n\n- **Effects:** When replacing a parameter by its argument expression,\n  we must be careful not to change the effects of the call. For\n  example, if we call a function `func twice(x int) int { return x + x }`\n  with `twice(g())`, we do not want to see `g() + g()`, which would\n  cause g's effects to occur twice, and potentially each call might\n  return a different value. All effects must occur the same number of\n  times, and in the same order. This requires analyzing both the\n  arguments and the callee function to determine whether they are\n  \"pure\", whether they read variables, or whether (and when) they\n  update them too. The inliner will introduce a declaration such as\n  `var x int = g()` when it cannot prove that it is safe to substitute\n  the argument throughout.\n\n- **Constants:** If inlining always replaced a parameter by its argument\n  when the value is constant, some programs would no longer build\n  because checks previously done at run time would happen at compile time.\n  For example `func index(s string, i int) byte { return s[i] }`\n  is a valid function, but if inlining were to replace the call `index(\"abc\", 3)`\n  by the expression `\"abc\"[3]`, the compiler will report that the\n  index `3` is out of bounds for the string `\"abc\"`.\n  The inliner will prevent substitution of parameters by problematic\n  constant arguments, again introducing a `var` declaration instead.\n\n- **Referential integrity:** When a parameter variable is replaced by\n  its argument expression, we must ensure that any names in the\n  argument expression continue to refer to the same thing---not to a\n  different declaration in the callee function body that happens to\n  use the same name. The inliner must replace local references such as\n  `Printf` by qualified references such as `fmt.Printf`, and add an\n  import of package `fmt` as needed.\n\n- **Implicit conversions:** When passing an argument to a function, it is\n  implicitly converted to the parameter type. If we eliminate the parameter\n  variable, we don't want to lose the conversion as it may be important. For\n  example, in `func f(x any) { y := x; fmt.Printf(\"%T\", &y) }` the type of\n  variable y is `any`, so the program prints `\"*interface{}\"`. But if inlining\n  the call `f(1)` were to produce the statement `y := 1`, then the type of y\n  would have changed to `int`, which could cause a compile error or, as in this\n  case, a bug, as the program now prints `\"*int\"`. When the inliner substitutes\n  a parameter variable by its argument value, it may need to introduce explicit\n  conversions of each value to the original parameter type, such as `y :=\n  any(1)`.\n\n- **Last reference:** When an argument expression has no effects\n  and its corresponding parameter is never used, the expression\n  may be eliminated. However, if the expression contains the last\n  reference to a local variable at the caller, this may cause a compile\n  error because the variable is now unused. So the inliner must be\n  cautious about eliminating references to local variables.\n\nThis is just a taste of the problem domain. If you're curious, the\ndocumentation for [golang.org/x/tools/internal/refactor/inline](https://pkg.go.dev/golang.org/x/tools/internal/refactor/inline) has\nmore detail. All of this is to say, it's a complex problem, and we aim\nfor correctness first of all. We've already implemented a number of\nimportant \"tidiness optimizations\" and we expect more to follow.\n\n<a name='refactor.inline.variable'></a>\n\n## `refactor.inline.variable`: Inline local variable\n\nFor a `codeActions` request where the selection is (or is within) an\nidentifier that is a use of a local variable whose declaration has an\ninitializer expression, gopls will return a code action of kind\n`refactor.inline.variable`, whose effect is to inline the variable:\nthat is, to replace the reference by the variable's initializer\nexpression.\n\nFor example, if invoked on the identifier `s` in the call `println(s)`:\n```go\nfunc f(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(s)\n}\n```\nthe code action transforms the code to:\n\n```go\nfunc f(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(fmt.Sprintf(\"+%d\", x))\n}\n```\n\n(In this instance, `s` becomes an unreferenced variable which you will\nneed to remove.)\n\nThe code action always replaces the reference by the initializer\nexpression, even if there are later assignments to the variable (such\nas `s = \"\"`).\n\nThe code action reports an error if it is not possible to make the\ntransformation because one of the identifiers within the initializer\nexpression (e.g. `x` in the example above) is shadowed by an\nintervening declaration, as in this example:\n\n```go\nfunc f(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\t{\n\t\tx := 123\n\t\tprintln(s, x) // error: cannot replace s with fmt.Sprintf(...) since x is shadowed\n\t}\n}\n```\n\n<a name='refactor.rewrite'></a>\n## `refactor.rewrite`: Miscellaneous rewrites\n\nThis section covers a number of transformations that are accessible as\ncode actions whose kinds are children of `refactor.rewrite`.\n\n<a name='refactor.rewrite.removeUnusedParam'></a>\n### `refactor.rewrite.removeUnusedParam`: Remove unused parameter\n\nThe [`unusedparams` analyzer](../analyzers.md#unusedparams) reports a\ndiagnostic for each parameter that is not used within the function body.\nFor example:\n\n```go\nfunc f(x, y int) { // \"unused parameter: x\"\n\tfmt.Println(y)\n}\n```\n\nIt does _not_ report diagnostics for address-taken functions, which\nmay need all their parameters, even unused ones, in order to conform\nto a particular function signature.\nNor does it report diagnostics for exported functions,\nwhich may be address-taken by another package.\n(A function is _address-taken_ if it is used other than in call position, `f(...)`.)\n\nIn addition to the diagnostic, it suggests two possible fixes:\n\n1. rename the parameter to `_` to emphasize that it is unreferenced (an immediate edit); or\n2. delete the parameter altogether, using a `ChangeSignature` command, updating all callers.\n\nFix \\#2 uses the same machinery as \"Inline function call\" (see above)\nto ensure that the behavior of all existing calls is preserved, even\nwhen the argument expression for the deleted parameter has side\neffects, as in the example below.\n\n![The parameter x is unused](../assets/remove-unusedparam-before.png)\n![The parameter x has been deleted](../assets/remove-unusedparam-after.png)\n\nObserve that in the first call, the argument `chargeCreditCard()` was\nnot deleted because of potential side effects, whereas in the second\ncall, the argument 2, a constant, was safely deleted.\n\n<a name='refactor.rewrite.moveParamLeft'></a>\n<a name='refactor.rewrite.moveParamRight'></a>\n### `refactor.rewrite.moveParam{Left,Right}`: Move function parameters\n\nWhen the selection is a parameter in a function or method signature, gopls\noffers a code action to move the parameter left or right (if feasible),\nupdating all callers accordingly.\n\nFor example:\n\n```go\nfunc Foo(x, y int) int {\n    return x + y\n}\n\nfunc _() {\n    _ = Foo(0, 1)\n}\n```\n\nbecomes\n\n```go\nfunc Foo(y, x int) int {\n    return x + y\n}\n\nfunc _() {\n    _ = Foo(1, 0)\n}\n```\n\nfollowing a request to move `x` right, or `y` left.\n\nThis is a primitive building block of more general \"Change signature\"\noperations. We plan to generalize this to arbitrary signature rewriting, but\nthe language server protocol does not currently offer good support for user\ninput into refactoring operations (see\n[microsoft/language-server-protocol#1164](https://github.com/microsoft/language-server-protocol/issues/1164)).\nTherefore, any such refactoring will require custom client-side logic. (As a\nvery hacky workaround, you can express arbitrary parameter movement by invoking\nRename on the `func` keyword of a function declaration, but this interface is\njust a temporary stopgap.)\n\n<a name='refactor.rewrite.changeQuote'></a>\n### `refactor.rewrite.changeQuote`: Convert string literal between raw and interpreted\n\nWhen the selection is a string literal, gopls offers a code action\nto convert the string between raw form (`` `abc` ``) and interpreted\nform (`\"abc\"`) where this is possible:\n\n![Convert to interpreted](../assets/convert-string-interpreted.png)\n![Convert to raw](../assets/convert-string-raw.png)\n\nApplying the code action a second time reverts back to the original\nform.\n\n<a name='refactor.rewrite.invertIf'></a>\n### `refactor.rewrite.invertIf`: Invert 'if' condition\n\nWhen the selection is within an `if`/`else` statement that is not\nfollowed by `else if`, gopls offers a code action to invert the\nstatement, negating the condition and swapping the `if` and and `else`\nblocks.\n\n![Before \"Invert if condition\"](../assets/invert-if-before.png)\n![After \"Invert if condition\"](../assets/invert-if-after.png)\n\n<!-- The output of this transformation is often stylistically poor.\n     For example, it will drop the \"else\" and outdent an if/else\n     if the else block ends with a return statement; and thus applying\n     the operation twice does not get you back to where you started. -->\n\n<a name='refactor.rewrite.splitLines'></a>\n<a name='refactor.rewrite.joinLines'></a>\n### `refactor.rewrite.{split,join}Lines`: Split elements into separate lines\n\nWhen the selection is within a bracketed list of items such as:\n\n- the **elements** of a composite literal, `[]T{a, b, c}`,\n- the **arguments** of a function call, `f(a, b, c)`,\n- the **groups of parameters** of a function signature, `func(a, b, c int, d, e bool)`, or\n- its **groups of results**, `func() (x, y string, z rune)`,\n\ngopls will offer the \"Split [items] into separate lines\" code\naction, which would transform the forms above into these forms:\n\n```go\n[]T{\n\ta,\n\tb,\n\tc,\n}\n\nf(\n\ta,\n\tb,\n\tc,\n)\n\nfunc(\n\ta, b, c int,\n\td, e bool,\n)\n\nfunc() (\n\tx, y string,\n\tz rune,\n)\n```\n\nObserve that in the last two cases, each\n[group](https://pkg.go.dev/go/ast#Field) of parameters or results is\ntreated as a single item.\n\nThe opposite code action, \"Join [items] into one line\", undoes the operation.\nNeither action is offered if the list is already full split or joined,\nrespectively, or trivial (fewer than two items).\n\nThese code actions are not offered for lists containing `//`-style\ncomments, which run to the end of the line.\n\n<!-- Strictly, line comments make only \"join\" (but not \"split\") infeasible. -->\n\n<a name='refactor.rewrite.fillStruct'></a>\n### `refactor.rewrite.fillStruct`: Fill struct literal\n\nWhen the cursor is within a struct literal `S{}`, gopls offers the\n\"Fill S\" code action, which populates each missing field of the\nliteral that is accessible.\n\nIt uses the following heuristic to choose the value assigned to each\nfield: it finds candidate variables, constants, and functions that are\nassignable to the field, and picks the one whose name is the closest\nmatch to the field name.\nIf there are none, it uses the zero value (such as `0`, `\"\"`, or\n`nil`) of the field's type.\n\nIn the example below, a\n[`slog.HandlerOptions`](https://pkg.go.dev/golang.org/x/exp/slog#HandlerOptions)\nstruct literal is filled in using two local variables (`level` and\n`add`) and a function (`replace`):\n\n![Before \"Fill slog.HandlerOptions\"](../assets/fill-struct-before.png)\n![After \"Fill slog.HandlerOptions\"](../assets/fill-struct-after.png)\n\nCaveats:\n\n- This code action requires type information for the struct type, so\n  if it is defined in another package that is not yet imported, you\n  may need to \"organize imports\" first, for example by saving the\n  file.\n- Candidate declarations are sought only in the current file, and only\n  above the current point. Symbols declared beneath the current point,\n  or in other files in the package, are not considered; see\n  https://go.dev/issue/68224.\n\n<a name='refactor.rewrite.fillSwitch'></a>\n### `refactor.rewrite.fillSwitch`: Fill switch\n\nWhen the cursor is within a switch statement whose operand type is an\n_enum_ (a finite set of named constants), or within a type switch,\ngopls offers the \"Add cases for T\" code action, which populates the\nswitch statement by adding a case for each accessible named constant\nof the enum type, or, for a type switch, by adding a case for each\naccessible named non-interface type that implements the interface.\nOnly missing cases are added.\n\nThe screenshots below show a type switch whose operand has the\n[`net.Addr`](https://pkg.go.dev/net#Addr) interface type. The code\naction adds one case per concrete network address type, plus a default\ncase that panics with an informative message if an unexpected operand\nis encountered.\n\n![Before \"Add cases for Addr\"](../assets/fill-switch-before.png)\n![After \"Add cases for Addr\"](../assets/fill-switch-after.png)\n\nAnd these screenshots illustrate the code action adding cases for each\nvalue of the\n[`html.TokenType`](https://pkg.go.dev/golang.org/x/net/html#TokenType)\nenum type, which represents the various types of token from\nwhich HTML documents are composed:\n\n![Before \"Add cases for Addr\"](../assets/fill-switch-enum-before.png)\n![After \"Add cases for Addr\"](../assets/fill-switch-enum-after.png)\n\n\n<a name='refactor.rewrite.eliminateDotImport'></a>\n### `refactor.rewrite.eliminateDotImport`: Eliminate dot import\n\nWhen the cursor is on a dot import gopls can offer the \"Eliminate dot import\"\ncode action, which removes the dot from the import and qualifies uses of the\npackage throughout the file. This code action is offered only if\neach use of the package can be qualified without collisions with existing names.\n\n<a name='refactor.rewrite.addTags'></a>\n### `refactor.rewrite.addTags`: Add struct tags\n\nWhen the cursor is within a struct, this code action adds to each field a `json`\nstruct tag that specifies its JSON name, using lower case with underscores\n(e.g. LinkTarget becomes link_target). For a highlighted selection, it only\nadds tags on selected fields.\n\n<a name='refactor.rewrite.removeTags'></a>\n### `refactor.rewrite.removeTags`: Remove struct tags\n\nWhen the cursor is within a struct, this code action clears struct tags on\nall struct fields. For a highlighted selection, it removes tags from only\nthe selected fields.\n"
  },
  {
    "path": "gopls/doc/features/web.md",
    "content": "---\ntitle: \"Gopls: Web-based features\"\n---\n\nThe LSP\n[`window.showDocument`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument) request\nallows the server to instruct the client to open a file in the editor\nor a web page in a browser. It is the basis for a number of gopls\nfeatures that report information about your program through a web\ninterface.\n\nWe recognize that a web interface is not ideal for everyone: some\nusers prefer a full-screen editor layout and dislike switching\nwindows; others may work in a text-only terminal without a window\nsystem, perhaps over remote ssh or on the Linux console.\nUnfortunately, the LSP lacks several natural kinds of extensibility,\nincluding the ability for servers to define:\n\n- queries that [generalize a References\n  query](https://github.com/microsoft/language-server-protocol/issues/1911),\n  displaying results using similar UI elements;\n- commands that [produce a stream of\n  text](https://github.com/joaotavora/eglot/discussions/1402), like a\n  typical shell command or compiler, that the client can redirect to\n  the editor's usual terminal-like UI element; or\n- refactoring operations that, like Rename, [prompt the\n  user](https://github.com/microsoft/language-server-protocol/issues/1164)\n  for additional information.\n\nThe web-based UI can help fill these gaps until such time as the LSP\nprovides standard ways of implementing these features.\n\nGopls' web server listens on a `localhost` port. For security, all its\nendpoints include a random string that serves as an authentication\ntoken. The client, provided authenticated URLs by the server, will be\nable to access your source code, but arbitrary processes running on\nyour machine will not.\nRestarting the gopls process causes this secret to change, rendering\nall existing previous URLs invalid; existing pages will display a banner\nindicating that they have become disconnected.\n\nTODO: combine the web server and the debug server; see https://go.dev/issue/68229.\n\nGopls supports two-way communication between the web browser and the\nclient editor. All of the web-based reports contain links to\ndeclarations in your source code. Clicking on one of these links\ncauses gopls to send a `showDocument` request to your editor to open\nthe relevant source file at the appropriate line. This works even when\nyour source code has been modified but not saved.\n(VS Code users: please upvote microsoft/vscode#208093 if you would\nlike your editor to raise its window when handling this event.)\n\n<a name='doc'></a>\n## `source.doc`: Browse package documentation\n\nIn any Go source file, a code action request returns a command to\n\"Browse package documentation\". This command opens a browser window\nshowing the documentation for the current Go package, presented using\na similar design to https://pkg.go.dev.\n\nThis allows you to preview the documentation for your packages, even\ninternal ones that may be unpublished externally. Reloading the page\nupdates the documentation to reflect your changes. It is not necessary\nto save modified Go source files.\n\n<img title=\"Browse package documentation\" src=\"../assets/browse-pkg-doc.png\" width='80%'>\n\nClicking on the link for a package-level symbol or method, which in\n`pkg.go.dev` would ordinarily take you to a source-code viewer such as\nGitHub or Google Code Search, causes your editor to navigate to the\nrelevant source file and line.\n\nClient support:\n- **VS Code**: Use the \"Source Action... > Browse documentation for package P\" menu.\n- **Emacs + eglot**: Use `M-x go-browse-doc` in [go-mode](https://github.com/dominikh/go-mode.el).\n- **Vim + coc.nvim**: ??\n\n\n<a name='freesymbols'></a>\n## `source.freesymbols`: Browse free symbols\n\nWhen studying code, either to understand it or to evaluate a different\norganization or factoring, it is common to need to know what the\n\"inputs\" are to a given chunk of code, either because you are\nconsidering extracting it into its own function and want to know what\nparameters it would take, or just to understand how one piece of a long\nfunction relates to the preceding pieces.\n\nIf you select a chunk of code, and invoke the \"Browse free symbols\"\n[code action](transformation.md#code-actions), your editor will\nopen a browser displaying a report on the free symbols of the\nselection. A symbol is \"free\" if it is referenced from within the\nselection but defined outside of it. In essence, these are the inputs\nto the selected chunk.\n\n<img title=\"Browse free symbols\" src=\"../assets/browse-free-symbols.png\" width='80%'>\n\nThe report classifies the symbols into imported, local, and\npackage-level symbols. The imported symbols are grouped by package,\nand link to the documentation for the package, as described above.\nEach of the remaining symbols is presented as a link that causes your\neditor to navigate to its declaration.\n\nTODO: explain dotted paths.\n\nClient support:\n- **VS Code**: Use the \"Source Action... > Browse free symbols\" menu.\n- **Emacs + eglot**: Use `M-x go-browse-freesymbols` in [go-mode](https://github.com/dominikh/go-mode.el).\n- **Vim + coc.nvim**: ??\n\n\n<a name='assembly'></a>\n## `source.assembly`: Browse assembly\n\nWhen you're optimizing the performance of your code or investigating\nan unexpected crash, it may sometimes be helpful to inspect the\nassembly code produced by the compiler for a given Go function.\n\nIf you position the cursor or selection within a function f,\ngopls offers the \"Browse assembly for f\" [code action](transformation.md#code-actions).\nThis opens a web-based listing of the assembly for the function, plus\nany functions nested within it.\n\nEach time you edit your source and reload the page, the current\npackage is recompiled and the listing is updated. It is not necessary\nto save your modified files.\n\nThe compiler's target architecture is the same as the one gopls uses\nwhen analyzing the file: typically, this is your machine's GOARCH, but\nwhen viewing a file with a build tag, such as one named `foo_amd64.go`\nor containing the comment `//go:build amd64`, the tags determine the\narchitecture.\n\nEach instruction is displayed with a link that causes your editor to\nnavigate to the source line responsible for the instruction, according\nto the debug information.\n\n<img title=\"Browse assembly\" src=\"../assets/browse-assembly.png\" width=\"80%\">\n\nThe example above shows the arm64 assembly listing of\n[`time.NewTimer`](https://pkg.go.dev/time#NewTimer).\nObserve that the indicated instruction links to a source location\ninside a different function, `syncTimer`, because the compiler\ninlined the call from `NewTimer` to `syncTimer`.\n\nBrowsing assembly is not yet supported for generic functions, package\ninitializers (`func init`), or functions in test packages.\n(Contributions welcome!)\n\nClient support:\n- **VS Code**: Use the \"Source Action... > Browse GOARCH assembly for f\" menu.\n- **Emacs + eglot**: Use `M-x go-browse-assembly` in [go-mode](https://github.com/dominikh/go-mode.el).\n- **Vim + coc.nvim**: ??\n\n\n<a name='splitpkg'></a>\n## `source.splitPackage`: Split package into components\n\nThe web-based \"Split package\" tool can help you split a complex\npackage into two or more components, ensuring that the dependencies\namong those components are acyclic.\n\nFollow the instructions on the page to choose a set of named components,\nassign each declaration to the most appropriate component, and then\nvisualize the dependencies between those components created by references\nfrom one symbol to another.\n\nThe figure below shows the tool operating on the `fmt` package, which\ncould (in principle) be split into three subpackages, one for\nformatting (`Printf` and friends), one for scanning (`Scanf`), and one\nfor their common dependencies.\n\n<img title=\"Split package 'fmt'\" src=\"../assets/splitpkg.png\" width=\"55%\">\n\n(Try playing with the tool on this package: it's an instructive\nexercise. The figure below shows the solution.)\n\n<img title=\"Split package 'fmt'\" src=\"../assets/splitpkg-deps.png\" width=\"55%\">\n\nThe tool does not currently perform the code transformation (moving\ndeclarations to new packages, renaming symbols to export them as\nneeded), but we hope to add that in a future release.\n\nClient support:\n- **VS Code**: Use the \"Source Action... > Split package P\" menu.\n"
  },
  {
    "path": "gopls/doc/index.md",
    "content": "---\ntitle: \"Gopls: The language server for Go\"\n---\n<!--\n  This is the main landing page for gopls users.\n\n  To preview locally edited markdown files, use:\n    $ GOLANGORG_LOCAL_X_TOOLS=$(pwd) go run golang.org/x/website/cmd/golangorg@master &\n    $ open http://localhost:6060/go.dev/gopls\n-->\n\n`gopls` (pronounced \"Go please\") is the official [language\nserver](https://langserver.org) for Go, developed by the Go team. It\nprovides a wide variety of [IDE features](features/) to any\n[LSP](https://microsoft.github.io/language-server-protocol/)-compatible\neditor.\n\n<!--TODO(rfindley): Add gifs here.-->\n\nYou should not need to interact with `gopls` directly--it will be automatically\nintegrated into your editor. The specific features and settings vary slightly\nby editor, so we recommend that you proceed to the\n[documentation for your editor](#editors) below.\nAlso, the gopls documentation for each feature describes whether it is\nsupported in each client editor.\n\nThis documentation (https://go.dev/gopls) describes the most recent release of gopls.\nTo preview documentation for the release under development, visit https://tip.golang.org/gopls.\n\n## Features\n\nGopls supports a wide range of standard LSP features for navigation,\ncompletion, diagnostics, analysis, and refactoring, and a number of\nadditional features not found in other language servers.\n\nSee the [Index of features](features/) for complete\ndocumentation on what Gopls can do for you.\n\n## Editors\n\nTo get started with `gopls`, install an LSP plugin in your editor of choice.\n\n<!-- TODO: be more consistent about editor (e.g. Emacs) vs. client (e.g. eglot). -->\n\n* [Acme](https://github.com/9fans/acme-lsp/blob/master/README.md)\n* [Atom](https://github.com/MordFustang21/ide-gopls/blob/master/README.md)\n* [Emacs](editor/emacs.md)\n* [Helix](editor/helix.md)\n* [Lapce](https://github.com/lapce-community/lapce-go/blob/master/README.md)\n* [Sublime Text](editor/sublime.md)\n* [VS Code](https://github.com/golang/vscode-go/blob/master/README.md)\n* [Vim or Neovim](editor/vim.md)\n* [Zed](editor/zed.md)\n\nIf you use `gopls` with an editor that is not on this list, please send us a CL\n[updating this documentation](contributing.md).\n\n## Installation\n\nTo install the latest stable release of `gopls`, run the following command:\n\n```sh\ngo install golang.org/x/tools/gopls@latest\n```\n\nSome editors, such as VS Code, will handle this step for you, and\nensure that Gopls is updated when a new stable version is released.\n\nAfter updating, you may need to restart running Gopls processes to\nobserve the effect. Each client has its own way to restart the server.\n(On a UNIX machine, you can use the command `killall gopls`.)\n\nLearn more in the\n[advanced installation instructions](advanced.md#installing-unreleased-versions).\n\n## Releases\n\nGopls [releases](release/) follow [semantic versioning](http://semver.org), with\nmajor changes and new features introduced only in new minor versions\n(i.e. versions of the form `v*.N.0` for some N). Subsequent patch\nreleases contain only cherry-picked fixes or superficial updates.\n\nIn order to align with the\n[Go release timeline](https://github.com/golang/go/wiki/Go-Release-Cycle#timeline),\nwe aim to release a new minor version of Gopls approximately every three\nmonths, with patch releases approximately every month, according to the\nfollowing table:\n\n| Month   | Version(s)   |\n| ----    | -------      |\n| Jan     | `v*.<N+0>.0` |\n| Jan-Mar | `v*.<N+0>.*` |\n| Apr     | `v*.<N+1>.0` |\n| Apr-Jun | `v*.<N+1>.*` |\n| Jul     | `v*.<N+2>.0` |\n| Jul-Sep | `v*.<N+2>.*` |\n| Oct     | `v*.<N+3>.0` |\n| Oct-Dec | `v*.<N+3>.*` |\n\nFor more background on this policy, see https://go.dev/issue/55267.\n\n## Setting up your workspace\n\n`gopls` supports both Go module, multi-module and GOPATH modes. See the\n[workspace documentation](workspace.md) for information on supported\nworkspace layouts.\n\n## Configuration\n\nYou can configure `gopls` to change your editor experience or view additional\ndebugging information. Configuration options will be made available by your\neditor, so see your [editor's instructions](#editors) for specific details. A\nfull list of `gopls` settings can be found in the [settings documentation](settings.md).\n\n### Environment variables\n\n`gopls` inherits your editor's environment, so be aware of any environment\nvariables you configure. Some editors, such as VS Code, allow users to\nselectively override the values of some environment variables.\n\n## Support policy\n\nGopls is maintained by engineers on the\n[Go tools team](https://github.com/orgs/golang/teams/tools-team/members),\nwho actively monitor the\n[Go](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)\nand\n[VS Code Go](https://github.com/golang/vscode-go/issues) issue trackers.\n\n### Supported Go versions\n\n`gopls` follows the\n[Go Release Policy](https://go.dev/doc/devel/release#policy), meaning\nthat it officially supports only the two most recent major Go releases.\n\nWhen using gopls, there are three versions to be aware of:\n1. The _gopls build go version_: the version of Go used to build gopls.\n2. The _go command version_: the version of the go list command executed by\n   gopls to load information about your workspace.\n3. The _language version_: the version in the go directive of the current\n   file's enclosing go.mod file, which determines the file's Go language\n   semantics.\n\nStarting with the release of Go 1.23.0 and gopls@v0.17.0 in August 2024, we\nwill only support the most recent Go version as the _gopls build go version_.\nHowever, due to the [forward compatibility](https://go.dev/blog/toolchain)\nsupport added in Go 1.21, as long as Go 1.21 or later are used to install\ngopls, any necessary toolchain upgrade will be handled automatically, just like\nany other dependency.\n\nAdditionally, starting with gopls@v0.17.0, the _go command version_ will narrow\nfrom 4 versions to 3. This is more consistent with the Go Release Policy.\n\nGopls supports **all** Go versions as its _language version_, by providing\ncompiler errors based on the language version and filtering available standard\nlibrary symbols based on the standard library APIs available at that Go\nversion.\n\nMaintaining support for building gopls with legacy versions of Go caused\n[significant friction](https://go.dev/issue/50825) for gopls maintainers and\nheld back other improvements. If you are unable to install a supported version\nof Go on your system, you can still install an older version of gopls. The\nfollowing table shows the final gopls version that supports a given Go version.\nGo releases more recent than those in the table can be used with any version of\ngopls.\n\n| Go Version  | Final gopls version with support (without warnings) |\n| ----------- | --------------------------------------------------- |\n| Go 1.12     | [gopls@v0.7.5](https://github.com/golang/tools/releases/tag/gopls%2Fv0.7.5) |\n| Go 1.15     | [gopls@v0.9.5](https://github.com/golang/tools/releases/tag/gopls%2Fv0.9.5) |\n| Go 1.17     | [gopls@v0.11.0](https://github.com/golang/tools/releases/tag/gopls%2Fv0.11.0) |\n| Go 1.18     | [gopls@v0.14.2](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.2) |\n| Go 1.20     | [gopls@v0.15.3](https://github.com/golang/tools/releases/tag/gopls%2Fv0.15.3) |\n\n### Supported build systems\n\n`gopls` currently only supports the `go` command, so if you are using\na different build system, `gopls` will not work well. Bazel is not officially\nsupported, but may be made to work with an appropriately configured\n[go/packages driver](https://pkg.go.dev/golang.org/x/tools/go/packages#hdr-The_driver_protocol).\nSee [bazelbuild/rules_go#512](https://github.com/bazelbuild/rules_go/issues/512)\nfor more information.\nYou can follow [these instructions](https://github.com/bazelbuild/rules_go/wiki/Editor-setup)\nto configure your `gopls` to work with Bazel.\n\n### Troubleshooting\n\nIf you are having issues with `gopls`, please follow the steps described in the\n[troubleshooting guide](troubleshooting.md).\n\n## Additional information\n\n* [Command-line interface](command-line.md)\n* [Advanced topics](advanced.md)\n* [Open issues](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)\n* [Contributing to `gopls`](contributing.md)\n"
  },
  {
    "path": "gopls/doc/inlayHints.md",
    "content": "---\ntitle: \"Gopls: Inlay hints\"\n---\n\nInlay hints are helpful annotations that the editor can optionally\ndisplay in-line in the source code, such as the names of parameters in\na function call. This document describes the inlay hints available\nfrom `gopls`.\n\n<!-- This portion is generated by doc/generate from golang.AllInlayHints. -->\n<!-- BEGIN Hints: DO NOT MANUALLY EDIT THIS SECTION -->\n## **assignVariableTypes**\n\n`\"assignVariableTypes\"` controls inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"assignVariableTypes\": true}`.**\n\n## **compositeLiteralFields**\n\n`\"compositeLiteralFields\"` inlay hints for composite literal field names:\n```go\n\t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"compositeLiteralFields\": true}`.**\n\n## **compositeLiteralTypes**\n\n`\"compositeLiteralTypes\"` controls inlay hints for composite literal types:\n```go\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t}\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"compositeLiteralTypes\": true}`.**\n\n## **constantValues**\n\n`\"constantValues\"` controls inlay hints for constant values:\n```go\n\tconst (\n\t\tKindNone   Kind = iota/* = 0*/\n\t\tKindPrint/*  = 1*/\n\t\tKindPrintf/* = 2*/\n\t\tKindErrorf/* = 3*/\n\t)\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"constantValues\": true}`.**\n\n## **functionTypeParameters**\n\n`\"functionTypeParameters\"` inlay hints for implicit type parameters on generic functions:\n```go\n\tmyFoo/*[int, string]*/(1, \"hello\")\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"functionTypeParameters\": true}`.**\n\n## **ignoredError**\n\n`\"ignoredError\"` inlay hints for implicitly discarded errors:\n```go\n\tf.Close() // ignore error\n```\nThis check inserts an `// ignore error` hint following any\nstatement that is a function call whose error result is\nimplicitly ignored.\n\nTo suppress the hint, write an actual comment containing\n\"ignore error\" following the call statement, or explicitly\nassign the result to a blank variable. A handful of common\nfunctions such as `fmt.Println` are excluded from the\ncheck.\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"ignoredError\": true}`.**\n\n## **parameterNames**\n\n`\"parameterNames\"` controls inlay hints for parameter names:\n```go\n\tparseInt(/* str: */ \"123\", /* radix: */ 8)\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"parameterNames\": true}`.**\n\n## **rangeVariableTypes**\n\n`\"rangeVariableTypes\"` controls inlay hints for variable types in range statements:\n```go\n\tfor k/* int*/, v/* string*/ := range []string{} {\n\t\tfmt.Println(k, v)\n\t}\n```\n\n\n**Disabled by default. Enable it by setting `\"hints\": {\"rangeVariableTypes\": true}`.**\n\n<!-- END Hints: DO NOT MANUALLY EDIT THIS SECTION -->\n"
  },
  {
    "path": "gopls/doc/release/README",
    "content": "This directory contains the draft release notes for each upcoming release.\n\nBe sure to update the file for the forthcoming release in the same CL\nthat you add new features or fix noteworthy bugs.\n\nSee https://github.com/golang/tools/releases for all past releases.\n\nTip: when reviewing edits to markdown files in Gerrit, to see the\nrendered form, click the \"Open in Code Search\" link (magnifying glass\nin blue square) then click \"View in > gitiles\" (shortcut: `v g`).\n"
  },
  {
    "path": "gopls/doc/release/v0.16.0.md",
    "content": "---\ntitle: \"Gopls release v0.16.0\"\n---\n\n```\ngo install golang.org/x/tools/gopls@v0.16.2\n```\n\nThis release includes several features and bug fixes, and is the first\nversion of gopls to support Go 1.23. To install it, run:\n\n## New support policy; end of support for Go 1.19 and Go 1.20\n\n**TL;DR: We are narrowing gopls' support window, but this is unlikely to\naffect you as long as you use at least Go 1.21 to build gopls. This doesn't\naffect gopls' support for the code you are writing.**\n\nThis is the last release of gopls that may be built with Go 1.19 or Go 1.20,\nand also the last to support integrating with go command versions 1.19 and\n1.20. If built or used with either of these Go versions, it will display\na message advising the user to upgrade.\n\nWhen using gopls, there are three versions to be aware of:\n\n1. The _gopls build go version_: the version of Go used to build gopls.\n2. The _go command version_: the version of the go list command executed by\n   gopls to load information about your workspace.\n3. The _language version_: the version in the go directive of the current\n   file's enclosing go.mod file, which determines the file's Go language\n   semantics.\n\nThis gopls release, v0.16.0, is the final release to support Go 1.19 and Go\n1.20 as the _gopls build go version_ or _go command version_. There is no\nchange to gopls' support for all _language versions_--in fact this support has\nsomewhat improved with the addition of the `stdversion` analyzer (see below).\n\nStarting with gopls@v0.17.0, which will be released after Go 1.23.0 is released\nin August, gopls will only support the latest version of Go as the\n_gopls build go version_.\nHowever, thanks to the [forward compatibility](https://go.dev/blog/toolchain)\nadded to Go 1.21, any necessary toolchain upgrade should be handled\nautomatically for users of Go 1.21 or later, just like any other dependency.\nAdditionally, we are reducing our _go command version_ support window from\n4 versions to 3. Note that this means if you have at least Go 1.21 installed on\nyour system, you should still be able to `go install` and use gopls@v0.17.0.\n\nWe have no plans to ever change our _language version_ support: we expect that\ngopls will always support developing programs that target _any_ Go version.\n\nBy focusing on building gopls with the latest Go version, we can significantly\nreduce our maintenance burden and help improve the stability of future gopls\nreleases. See the newly updated\n[support policy](https://github.com/golang/tools/tree/master/gopls#support-policy)\nfor details. Please comment on golang/go#65917 if\nyou have concerns about this change.\n\n## Configuration changes\n\n- The experimental `allowImplicitNetworkAccess` setting is deprecated (but not\n  yet removed). Please comment on golang/go#66861 if you use this\n  setting and would be impacted by its removal.\n\n## New features\n\n### Go 1.23 support\n\nThis version of gopls is the first to support the new language features of Go 1.23,\nincluding\n[range-over-func](https://go.dev/wiki/RangefuncExperiment) iterators\nand support for the\n[`godebug` directive](https://go.dev/ref/mod#go-mod-file-godebug)\nin go.mod files.\n\n### Integrated documentation viewer\n\nGopls now offers a \"Browse documentation\" code action that opens a\nlocal web page displaying the generated documentation for Go packages\nand symbols in a form similar to https://pkg.go.dev.\nThe package or symbol is chosen based on the current selection.\n\nUse this feature to preview the marked-up documentation as you prepare API\nchanges, or to read the documentation for locally edited packages,\neven ones that have not yet been saved. Reload the page after an edit\nto see updated documentation.\n\n<img title=\"Browse documentation for package\" src=\"../assets/code-action-doc.png\" width=\"80%\">\n\nAs in `pkg.go.dev`, the heading for each symbol contains a link to the\nsource code of its declaration. In `pkg.go.dev`, these links would refer\nto a source code page on a site such as GitHub or Google Code Search.\nHowever, in gopls' internal viewer, clicking on one of these links will\ncause your editor to navigate to the declaration.\n(This feature requires that your LSP client honors the `showDocument` downcall.)\n\n<img title=\"Symbol links navigate your editor to the declaration\" src=\"../assets/browse-pkg-doc.png\" width=\"80%\">\n\nEditor support:\n\n- VS Code: use the \"Source action > Browse documentation for func fmt.Println\" menu item.\n  Note: source links navigate the editor but don't yet raise the window yet.\n  Please upvote microsoft/vscode#208093 and microsoft/vscode#207634 (temporarily closed).\n- Emacs: requires eglot v1.17. Use `M-x go-browse-doc` from github.com/dominikh/go-mode.el.\n\nThe `linksInHover` setting now supports a new value, `\"gopls\"`,\nthat causes documentation links in the Markdown output\nof the Hover operation to link to gopls' internal doc viewer.\n\n### Browse free symbols\n\nGopls offers another web-based code action, \"Browse free symbols\",\nwhich displays the free symbols referenced by the selected code.\n\nA symbol is \"free\" if it is referenced within the selection but\ndeclared outside of it. The free symbols that are variables are\napproximately the set of parameters that would be needed if the block\nwere extracted into its own function.\n\nEven when you don't intend to extract a block into a new function,\nthis information can help you to tell at a glance what names a block\nof code depends on.\n\nEach dotted path of identifiers (such as `file.Name.Pos`) is reported\nas a separate item, so that you can see which parts of a complex\ntype are actually needed.\n\nThe free symbols of the body of a function may reveal that\nonly a small part (a single field of a struct, say) of one of the\nfunction's parameters is used, allowing you to simplify and generalize\nthe function by choosing a different type for that parameter.\n\n<img title=\"Browse free symbols\" src=\"../assets/browse-free-symbols.png\" width=\"80%\">\n\nEditor support:\n\n- VS Code: use the `Source action > Browse free symbols` menu item.\n- Emacs: requires eglot v1.17. Use `M-x go-browse-freesymbols` from github.com/dominikh/go-mode.el.\n\n### Browse assembly\n\nGopls offers a third web-based code action, \"Browse assembly for f\",\nwhich displays an assembly listing of the declaration of the function\nf enclosing the selected code, plus any nested functions such as\nfunction literals or deferred calls.\n\nGopls invokes the compiler to generate the report;\nreloading the page updates the report.\n\nThe machine architecture is determined by the build\nconfiguration that gopls selects for the current file.\nThis is usually the same as your machine's GOARCH unless you are\nworking in a file with `go:build` tags for a different architecture.\n\n<img title=\"Browse assembly for function\" src=\"../assets/browse-assembly.png\" width=\"80%\">\n\nGopls cannot yet display assembly for generic functions:\ngeneric functions are not fully compiled until they are instantiated,\nbut any function declaration enclosing the selection cannot be an\ninstantiated generic function.\n\n<!-- Clearly the ideal UX for generic functions is to use the function\n     symbol under the cursor, e.g. Vector[string], rather than the\n     enclosing function; but computing the name of the linker symbol\n     remains a challenge. -->\n\nEditor support:\n\n- VS Code: use the \"Source action > Browse assembly for f\" menu item.\n- Emacs: requires eglot v1.17. Use `M-x go-browse-assembly` from github.com/dominikh/go-mode.el.\n\n### `unusedwrite` analyzer\n\nThe new\n[unusedwrite](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite)\nanalyzer reports assignments, often to fields of structs, that have no\neffect because, for example, the struct is never used again:\n\n```go\nfunc scheme(host string) string {\n\tu := &url.URL{\n\t\tHost:   host, // \"unused write to field Host\" (no need to construct a URL)\n\t\tScheme: \"https:\",\n\t}\n\treturn u.Scheme\n}\n```\n\nThis is at best an indication that the code is unnecessarily complex\n(for instance, some dead code could be removed), but often indicates a\nbug, as in this example:\n\n```go\ntype S struct { x int }\n\nfunc (s S) set(x int) {\n\ts.x = x // \"unused write to field x\" (s should be a *S pointer)\n}\n```\n\n### `stdversion` analyzer\n\nThe new\n[`stdversion`](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion)\nanalyzer warns about the use of too-new standard library symbols based on the\nversion of the `go` directive in your `go.mod` file. This improves our support\nfor older _language versions_ (see above), even when gopls is built with\na recent Go version.\n\nConsider the go.mod file and Go file below.\nThe declaration of `var `alias refers to a type, `types.Alias`,\nintroduced in go1.22, but the file belongs to a module that requires\nonly go1.21, so the analyzer reports a diagnostic:\n\n```\nmodule example.com\ngo 1.21\n```\n\n```go\npackage p\n\nimport \"go/types\"\n\nvar alias types.Alias // types.Alias requires go1.22 or later (module is go1.21)\n```\n\nWhen an individual file is build-tagged for a release of Go other than\nthan module's version, the analyzer will apply appropriate checks for\nthe file's version.\n\n### Two more vet analyzers\n\nThe [framepointer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer)\nand [sigchanyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer)\nanalyzers have long been part of go vet's suite,\nbut had been overlooked in previous versions of gopls.\n\nHenceforth, gopls will always include any analyzers run by vet.\n\n### Hover shows size/offset info, and struct tags\n\nHovering over the identifier that declares a type or struct field now\ndisplays the size information for the type:\n\n<img title=\"struct size info\" src=\"../assets/hover-size-struct.png\">\n\nand the offset information for the field:\n\n<img title=\"field size/offset info\" src=\"../assets/hover-size-field.png\">\n\nIn addition, it reports the percentage of wasted space due to\nsuboptimal ordering of struct fields, if this figure is 20% or higher:\n\n<img title=\"a struct with wasted space\" src=\"../assets/hover-size-wasteful.png\">\n\nIn the struct above, alignment rules require each of the two boolean\nfields (1 byte) to occupy a complete word (8 bytes), leading to (7 + 7) / (3 \\* 8) = 58% waste.\nPlacing the two booleans together would save a word.\n\nThis information may be helpful when making space optimizations to\nyour data structures, or when reading assembly code.\n\nAlso, hovering over a reference to a field with a struct tag now also\ndisplay the tag:\n\n<img title=\"hover shows field tag\" src=\"../assets/hover-field-tag.png\">\n\n### Hover and \"Go to Definition\" work on symbols in doc comments\n\nGo 1.19 added support for [doc links](https://go.dev/doc/comment#links),\nallowing the doc comment for one symbol to reference another.\n\nGopls' Hover and Definition operations now treat these links just\nlike identifiers, so hovering over one will display information about\nthe symbol:\n\n<img title=\"hover shows field tag\" src=\"../assets/hover-doclink.png\">\n\nSimilarly, \"Go to definition\" will navigate to its declaration.\nThanks to @rogeryk for contributing this feature.\n\n## Bugs fixed\n\n## Thank you to our contributors!\n\n@guodongli-google for the `unusedwrite` analyzer.\nTODO: they're a xoogler; is there a more current GH account?\n\n@rogeryk\n"
  },
  {
    "path": "gopls/doc/release/v0.17.0.md",
    "content": "---\ntitle: \"Gopls release v0.17.0\"\n---\n\n<!-- TODO: update this instruction once v0.17.0 is released\n\n    Also, tweak the img URLs when publishing to GitHub Releases.\n-->\n\n```\ngo install golang.org/x/tools/gopls@v0.17.0-pre.4\n```\n\n## New support policies\n\nWith this release, we are narrowing our official support window to align with\nthe [Go support policy](https://go.dev/doc/devel/release#policy). This will\nreduce the considerable costs to us of testing against older Go versions,\nallowing us to spend more time fixing bugs and adding features that benefit the\nmajority of gopls users who run recent versions of Go.\n\nThis narrowing is occurring in two dimensions: **build compatibility** refers to\nthe versions of the Go toolchain that can be used to build gopls, and **go\ncommand compatibility** refers to the versions of the `go` command that can be\nused by gopls to list information about packages and modules in your workspace.\n\n### Build compatibility: the most recent major Go version\n\nAs described in the [v0.16.0 release\nnotes](https://github.com/golang/tools/releases/tag/gopls%2Fv0.16.0), building the\nlatest version of gopls will now require the latest major version of the Go\ntoolchain. Therefore this release (gopls@v0.17.0) must be built with Go 1.23.0\nor later. Thanks to [automatic toolchain\nupgrades](https://go.dev/blog/toolchain), if your system Go version is at least\nGo 1.21.0 and you have `GOTOOLCHAIN=auto` set (the default), the `go` command\nwill automatically download the new Go toolchain as needed, similar to\nupgrading a module dependency.\n\n### Go command compatibility: the 2 most recent major Go versions\n\nThe gopls@v0.17.x releases will be the final versions of gopls to nominally\nsupport integrating with more than the 2 most recent Go releases. In the past,\nwe implied \"best effort\" support for up to 4 versions, though in practice we\ndid not have resources to fix bugs that were present only with older Go\nversions. With gopls@v0.17.0, we narrowed this best effort support to 3\nversions, primarily because users need at least Go 1.21 to benefit from\nautomatic toolchain upgrades (see above).\n\nStarting with gopls@v0.18.0, we will officially support integrating with only\nthe 2 most recent major versions of the `go` command. This is consistent with\nthe Go support policy. See golang/go#69321 (or [this\ncomment](https://github.com/golang/go/issues/69321#issuecomment-2344996677)\nspecifically) for details.\n\nWe won't prevent gopls from being used with older Go versions (just as we\ndon't disallow integration with arbitrary\n[`go/packages`](https://pkg.go.dev/golang.org/x/tools/go/packages) drivers),\nbut we won't run integration tests against older Go versions, and won't fix\nbugs that are only present when used with old Go versions.\n\n## Configuration Changes\n\n- The `fieldalignment` analyzer, previously disabled by default, has\n  been removed: it is redundant with the hover size/offset information\n  displayed by v0.16.0 and its diagnostics were confusing.\n- The `undeclaredname` analyzer has been replaced with an ordinary code action.\n- The kind (identifiers) of all of gopls' code actions have changed\n  to use more specific hierarchical names. For example, \"Inline call\"\n  has changed from `refactor.inline` to `refactor.inline.call`.\n  This allows clients to request particular code actions more precisely.\n  The user manual now includes the identifier in the documentation for each code action.\n- The experimental `allowImplicitNetworkAccess` setting is removed, following\n  its deprecation in gopls@v0.16.0. See golang/go#66861 for details.\n\n## New features\n\n### Refactoring\n\nThis release contains a number of new features related to refactoring.\nAdditionally, it fixes [many\nbugs](https://github.com/golang/go/issues?q=is%3Aissue+milestone%3Agopls%2Fv0.17.0+label%3ARefactoring+is%3Aclosed)\nin existing refactoring operations, primarily related to **extract**, and **inline**.\n\nThese improvements move us toward a longer term goal of offering a more robust\nand complete set of refactoring tools. We still have [much to\ndo](https://github.com/golang/go/issues?q=is%3Aissue+label%3Agopls+label%3ARefactoring+is%3Aopen+),\nand this effort will continue into 2025.\n\n#### Move parameter refactorings\n\nGopls now offers code actions to move function and method parameters left or\nright in the function signature, updating all callers.\n\nUnfortunately, there is no native LSP operation that provides a good user\ninterface for arbitrary \"change signature\" refactoring. We plan to build such\nan interface within VS Code. In the short term, we have made it possible to\nexpress more complicated parameter transformations by invoking 'rename' on the\n'func' keyword. This user interface is a temporary stop-gap until a better\nmechanism is available for LSP commands that enable client-side dialogs.\n\n#### Extract declarations to new file\n\nGopls now offers another code action,\n\"Extract declarations to new file\" (`refactor.extract.toNewFile`),\nwhich moves selected code sections to a newly created file within the\nsame package. The created filename is chosen as the first {function, type,\nconst, var} name encountered. In addition, import declarations are added or\nremoved as needed.\n\nThe user can invoke this code action by selecting a function name, the keywords\n`func`, `const`, `var`, `type`, or by placing the caret on them without selecting,\nor by selecting a whole declaration or multiple declarations.\n\nIn order to avoid ambiguity and surprise about what to extract, some kinds\nof partial selection of a declaration cannot invoke this code action.\n\n#### Extract constant\n\nWhen the selection is a constant expression, gopls now offers \"Extract\nconstant\" instead of \"Extract variable\", and generates a `const`\ndeclaration instead of a local variable.\n\nAlso, extraction of a constant or variable now works at top-level,\noutside of any function.\n\n#### Generate missing method from function call\n\nWhen you attempt to call a method on a type that lacks that method, the\ncompiler will report an error like “type T has no field or method f”. Gopls now\noffers a new code action, “Declare missing method of T.f”, where T is the\nconcrete type and f is the undefined method. The stub method's signature is\ninferred from the context of the call.\n\n#### Generate a test for a function or method\n\nIf the selected chunk of code is part of a function or method declaration F,\ngopls will offer the \"Add test for F\" code action, which adds a new test for the\nselected function in the corresponding `_test.go` file. The generated test takes\ninto account its signature, including input parameters and results.\n\nSince this feature is implemented by the server (gopls), it is compatible with\nall LSP-compliant editors. VS Code users may continue to use the client-side\n`Go: Generate Unit Tests For file/function/package` command, which runs the\n[gotests](https://github.com/cweill/gotests) tool.\n\n### Initial support for pull diagnostics\n\nWhen initialized with the option `\"pullDiagnostics\": true`, gopls will advertise support for the\n`textDocument.diagnostic`\n[client capability](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics),\nwhich allows editors to request diagnostics directly from gopls using a\n`textDocument/diagnostic` request, rather than wait for a\n`textDocument/publishDiagnostics` notification. This feature is off by default\nuntil the feature set of pull diagnostics is comparable to push diagnostics.\n\n### Hover improvements\n\nThe `textDocument/hover` response has slightly tweaked markdown rendering, and\nincludes the following additional information:\n\n- Hovering over a standard library symbol now displays information about the\n  first Go release containing the symbol. For example, hovering over\n  `errors.As` shows \"Added in go1.13\".\n- Hovering over the package name in a package declaration includes additional\n  package metadata.\n\n### Semantic token modifiers of top-level constructor of types\n\nThe semantic tokens response now includes additional modifiers for the top-level\nconstructor of the type of each symbol:\n`interface`, `struct`, `signature`, `pointer`, `array`, `map`, `slice`, `chan`, `string`, `number`, `bool`, and `invalid`.\nEditors may use this for syntax coloring.\n\n### SignatureHelp for ident and values.\n\nNow, function signature help can be used on any identifier with a function\nsignature, not just within the parentheses of a function being called.\n\n### Jump to assembly definition\n\nA Definition query on a reference to a function jumps to the\nfunction's Go `func` declaration. If the function is implemented in C\nor assembly, the function has no body. Executing a second Definition\nquery (while already at the Go declaration) will navigate you to the\nassembly implementation.\n\n### `yield` analyzer\n\nThe new `yield` analyzer detects mistakes using the `yield` function\nin a Go 1.23 iterator, such as failure to check its boolean result and\nbreak out of a loop.\n\n### `waitgroup` analyzer\n\nThe new `waitgroup` analyzer detects calls to the `Add` method of\n`sync.WaitGroup` that are (mistakenly) made within the new goroutine,\ncausing `Add` to race with `Wait`.\n(This check is equivalent to\n[staticcheck's SA2000](https://staticcheck.dev/docs/checks#SA2000),\nbut is enabled by default.)\n"
  },
  {
    "path": "gopls/doc/release/v0.18.0.md",
    "content": "---\ntitle: \"Gopls release v0.18.0\"\n---\n\n## Configuration Changes\n\n<!-- TODO(rfindley): add links to relevant settings documentation -->\n\n- The experimental `Structured` value for the `hoverKind` option is no longer\n  supported.\n\n- The `gc_details` code lens has been deleted. (It was previously disabled by\n  default.) This functionality is now available through the\n  `toggleCompilerOptDetails` code action (documented below), as code\n  actions are better supported than code lenses across a range of clients.\n\n  VS Code's special \"Go: Toggle GC details\" command continues to work.\n\n- The experimental `semanticTokenTypes` and `semanticTokenModifiers` options\n  allow selectively disabling certain types of tokens or token modifiers in\n  `textDocument/semanticTokens` responses.\n\n  These options supersede the `noSemanticString` and `noSemanticTokenNumber`\n  options, which are now deprecated. Users can instead set\n  `\"semanticTokenTypes\": {\"string\": false, \"number\": false}` to achieve the\n  same result. For now, gopls still honors `noSemanticTokenString` and\n  `noSemanticToken`, but will stop supporting them in a future release.\n\n- The new `workspaceFiles` option allows configuring glob patterns matching\n  files that define the logical build of the workspace. This option is only\n  needed in environments that use a custom golang.org/x/tools/go/packages\n  driver.\n\n## New features\n\n### \"{Show,Hide} compiler optimization details\" code action\n\nThis code action, accessible through the \"Source Action\" menu in VS\nCode, toggles a per-directory flag that causes Go compiler optimization\ndetails to be reported as diagnostics. For example, it indicates which\nvariables escape to the heap, and which array accesses require bounds\nchecks.\n\nTODO: add links to the complete manual for each item.\n\n### New `modernize` analyzer\n\nGopls now reports when code could be simplified or clarified by\nusing more modern features of Go, and provides a quick fix to apply\nthe change.\n\nFor example, a conditional assignment using an if/else statement may\nbe replaced by a call to the `min` or `max` built-in functions added\nin Go 1.18.\n\nUse this command to apply modernization fixes en masse:\n```\n$ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...\n```\n\n### New `unusedfunc` analyzer\n\nGopls now reports unused functions and methods, giving you near\nreal-time feedback about dead code that may be safely deleted.\nBecause the analysis is local to each package, only unexported\nfunctions and methods are candidates.\n(For a more precise analysis that may report unused exported\nfunctions too, use the `golang.org/x/tools/cmd/deadcode` command.)\n\n### New `hostport` analyzer\n\nWith the growing use of IPv6, forming a \"host:port\" string using\n`fmt.Sprintf(\"%s:%d\")` is no longer appropriate because host names may\ncontain colons. Gopls now reports places where a string constructed in\nthis fashion (or with `%s` for the port) is passed to `net.Dial` or a\nrelated function, and offers a fix to use `net.JoinHostPort`\ninstead.\n\n### Other analyzer changes\n\n- The `unusedvariable` quickfix is now on by default.\n- The `unusedparams` analyzer no longer reports finding for generated files.\n\n### New `gofix` analyzer\n\nGopls now reports when a function call or a use of a constant should be inlined.\nThese diagnostics and the associated code actions are triggered by \"//go:fix inline\"\ndirectives at the function and constant definitions.\n(See [the go:fix proposal](https://go.dev/issue/32816).)\n\nFor example, consider a package `intmath` with a function `Square(int) int`.\nLater the more general `Pow(int, int) int` is introduced, and `Square` is deprecated\nin favor of calling `Pow` with a second argument of 2. The author of `intmath`\ncan write this:\n```\n//go:fix inline\nfunc Square(x int) int { return Pow(x, 2) }\n```\nIf gopls sees a call to `intmath.Square` in your code, it will suggest inlining\nit, and will offer a code action to do so.\n\nThe same feature works for constants.\nWith a constant definition like this:\n```\n//go:fix inline\nconst Ptr = Pointer\n```\ngopls will suggest replacing `Ptr` in your code with `Pointer`.\n\nUse this command to apply such fixes en masse:\n\n```\n$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...\n```\n\n### \"Implementations\" supports generics\n\nAt long last, the \"Go to Implementations\" feature now fully supports\ngeneric types and functions (#59224).\n\nFor example, invoking the feature on the interface method `Stack.Push`\nbelow will report the concrete method `C[T].Push`, and vice versa.\n\n```go\npackage p\n\ntype Stack[T any] interface {\n\tPush(T) error\n\tPop() (T, bool)\n}\n\ntype C[T any] struct{}\n\nfunc (C[T]) Push(t T) error { ... }\nfunc (C[T]) Pop() (T, bool) { ... }\n\nvar _ Stack[int] = C[int]{}\n```\n\n### Extract all occurrences of the same expression under selection\n\nWhen you have multiple instances of the same expression in a function,\nyou can use this code action to extract it into a variable.\nAll occurrences of the expression will be replaced with a reference to the new variable.\n\n### Improvements to \"Definition\"\n\nThe Definition query now supports additional locations:\n\n- When invoked on a return statement, it reports the location\n  of the function's result variables.\n- When invoked on a break, goto, or continue statement, it reports\n  the location of the label, the closing brace of the relevant\n  block statement, or the start of the relevant loop, respectively.\n\n### Improvements to \"Hover\"\n\nWhen invoked on a return statement, hover reports the types of\nthe function's result variables.\n\n### UX improvements to format strings\n\n#### \"DocumentHighlight\"\n\nWhen your cursor is inside a printf-like function, gopls now highlights the relationship between\nformatting verbs and arguments as visual cues to differentiate how operands are used in the format string.\n\n```go\nfmt.Printf(\"Hello %s, you scored %d\", name, score)\n```\n\nIf the cursor is either on `%s` or `name`, gopls will highlight `%s` as a write operation,\nand `name` as a read operation.\n\n#### \"SemanticHighlight\"\n\nSimilar to the improvements to DocumentHighlight, gopls also reports formatting verbs\nas \"format\" modifier for token type \"string\" to better distinguish them with other parts of the format string.\n\n```go\nfmt.Printf(\"Hello %s, you scored %d\", name, score)\n```\n\n`%s` and `%d` will have token type \"string\" and modifier \"format\".\n"
  },
  {
    "path": "gopls/doc/release/v0.19.0.md",
    "content": "---\ntitle: \"Gopls release v0.19.0\"\n---\n\n## Configuration Changes\n\n- The `gopls check` subcommand now accepts a `-severity` flag to set a minimum\n  severity for the diagnostics it reports. By default, the minimum severity\n  is \"warning\", so `gopls check` may report fewer diagnostics than before. Set\n  `-severity=hint` to reproduce the previous behavior.\n\n## Navigation features\n\n### \"Implementations\" supports signature types (within same package)\n\n<!-- golang/go#56572 -->\n\nThe Implementations query reports the correspondence between abstract\nand concrete types and their methods based on their method sets.\nNow, it also reports the correspondence between function types,\ndynamic function calls, and function definitions, based on their signatures.\n\nTo use it, invoke an Implementations query on the `func` token of the\ndefinition of a named function, named method, or function literal.\nGopls reports the set of function signature types that abstract this\nfunction, and the set of dynamic calls through values of such types.\n\nConversely, an Implementations query on the `func` token of a\nsignature type, or on the `(` paren of a dynamic function call,\nreports the set of concrete functions that the signature abstracts\nor that the call dispatches to.\n\nSince a type may be both a function type and a named type with methods\n(for example, `http.HandlerFunc`), it may participate in both kinds of\nImplements queries (method-sets and function signatures).\nQueries using method-sets should be invoked on the type or method name,\nand queries using signatures should be invoked on a `func` or `(` token.\n\nOnly the local (same-package) algorithm is currently supported.\n(https://go.dev/issue/56572 tracks the global algorithm.)\n\n### \"Go to Implementation\" reports interface-to-interface relations\n\n<!-- golang/go#68641 -->\n\nThe \"Go to Implementation\" operation now reports relationships between\ninterfaces. Gopls now uses the concreteness of the query type to\ndetermine whether a query is \"downwards\" (from an interface to the\ntypes that implement it) or \"upwards\" (from a concrete type to the\ninterfaces to which it may be assigned). So, for example:\n\n- `implementation(io.Reader)` subinterfaces such as `io.ReadCloser`,\n  and concrete implementations such as `*os.File`.\n\n- `implementation(os.File)` includes only interfaces, such as\n  `io.Reader` and `io.ReadCloser`.\n\nTo request an \"upwards\" query starting from an interface, for example\nto find the superinterfaces of `io.ReadCloser`, use the Type Hierarchy\nfeature described below.\n(See https://github.com/microsoft/language-server-protocol/issues/2037.)\n\n### Support for Type Hierarchy\n\n<!-- golang/go#72142 -->\n\nGopls now implements the three LSP methods related to the Type\nHierarchy viewer: `textDocument/prepareTypeHierarchy`,\n`typeHierarchy/supertypes`, `typeHierarchy/subtypes`.\n\nIn VS Code, select \"Show Type Hierarchy\" from the context menu\nto see a tree widget displaying all the supertypes or subtypes\nof the selected named type.\n\n<img title=\"Type Hierarchy: supertypes of net.Conn\" src=\"../assets/supertypes.png\" width=\"400\">\n\n<img title=\"Type Hierarchy: subtypes of io.Writer\" src=\"../assets/subtypes.png\" width=\"400\">\n\n\n## Editing features\n\n### Completion: auto-complete package clause for new Go files\n\nGopls now automatically adds the appropriate `package` clause to newly created Go files,\nso that you can immediately get started writing the interesting part.\n\nIt requires client support for `workspace/didCreateFiles`\n\n### New GOMODCACHE index for faster Organize Imports and unimported completions\n\nBy default, gopls now builds and maintains a persistent index of\npackages in the module cache (GOMODCACHE). The operations of Organize\nImports and completion of symbols from unimported packages are an\norder of magnitude faster.\n\nTo revert to the old behavior, set the `importsSource` option (whose\nnew default is `\"gopls\"`) to `\"goimports\"`. Users who don't want the\nmodule cache used at all for imports or completions can change the\noption to \"off\".\n\n## Analysis features\n\n### Most `staticcheck` analyzers are enabled by default\n\nSlightly more than half of the analyzers in the\n[Staticcheck](https://staticcheck.dev/docs/checks) suite are now\nenabled by default. This subset has been chosen for precision and\nefficiency.\n\nPreviously, Staticcheck analyzers (all of them) would be run only if\nthe experimental `staticcheck` boolean option was set to `true`. This\nvalue continues to enable the complete set, and a value of `false`\ncontinues to disable the complete set. Leaving the option unspecified\nenables the preferred subset of analyzers.\n\nStaticcheck analyzers, like all other analyzers, can be explicitly\nenabled or disabled using the `analyzers` configuration setting; this\nsetting now takes precedence over the `staticcheck` setting, so,\nregardless of what value of `staticcheck` you use (true/false/unset),\nyou can make adjustments to your preferred set of analyzers.\n\n### `recursiveiter`: \"inefficient recursive iterator\"\n\nA common pitfall when writing a function that returns an iterator\n(`iter.Seq`) for a recursive data type is to recursively call the\nfunction from its own implementation, leading to a stack of nested\ncoroutines, which is inefficient.\n\nThe new `recursiveiter` analyzer detects such mistakes; see\n[its documentation](https://golang.org/x/tools/gopls/internal/analysis/recursiveiter)\nfor details, including tips on how to define simple and efficient\nrecursive iterators.\n\n### `maprange`: \"inefficient range over maps.Keys/Values\"\n\nThe new `maprange` analyzer detects redundant calls to `maps.Keys` or\n`maps.Values` as the operand of a range loop; maps can of course be\nranged over directly. See\n[its documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange)\nfor details).\n\n## Code transformation features\n\n### Rename method receivers\n\n<!-- golang/go#41892 -->\n\nThe Rename operation, when applied to the declaration of a method\nreceiver, now also attempts to rename the receivers of all other\nmethods associated with the same named type. Each other receiver that\ncannot be fully renamed is quietly skipped.\n\nRenaming a _use_ of a method receiver continues to affect only that\nvariable.\n\n```go\ntype Counter struct { x int }\n\n                 Rename here to affect only this method\n                          ↓\nfunc (c *Counter) Inc() { c.x++ }\nfunc (c *Counter) Dec() { c.x++ }\n      ↑\n  Rename here to affect all methods\n```\n\n### \"Eliminate dot import\" code action\n\n<!-- golang/go#70319 -->\n\nThis code action, available on a dotted import, will offer to replace\nthe import with a regular one and qualify each use of the package\nwith its name.\n\n### Add/remove tags from struct fields\n\nGopls now provides two new code actions, available on an entire struct\nor some of its fields, that allow you to add and remove struct tags.\nIt adds only 'json' tags with a snakecase naming format, or clears all\ntags within the selection.\n\nAdd tags example:\n```go\ntype Info struct {\n    LinkTarget string        ->      LinkTarget string `json:\"link_target\"`\n    ...\n}\n```\n\n### Inline local variable\n\n<!-- golang/go#70085 -->\n\nThe new `refactor.inline.variable` code action replaces a reference to\na local variable by that variable's initializer expression. For\nexample, when applied to `s` in `println(s)`:\n\n```go\nfunc f(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(s)\n}\n```\nit transforms the code to:\n```go\nfunc f(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(fmt.Sprintf(\"+%d\", x))\n}\n```\n\nOnly a single reference is replaced; issue https://go.dev/issue/70085\ntracks the feature to \"inline all\" uses of the variable and eliminate\nit.\n\n\n## Thank you to our contributors!\n\n[@acehinnnqru](https://github.com/acehinnnqru)\n[@adonovan](https://github.com/adonovan)\n[@albfan](https://github.com/albfan)\n[@aarzilli](https://github.com/aarzilli)\n[@ashurbekovz](https://github.com/ashurbekovz)\n[@cuonglm](https://github.com/cuonglm)\n[@dmitshur](https://github.com/dmitshur)\n[@neild](https://github.com/neild)\n[@egonelbre](https://github.com/egonelbre)\n[@shashank](https://github.com/shashank)\n[priyadarshi](https://github.compriyadarshi)\n[@firelizzard18](https://github.com/firelizzard18)\n[@gopherbot](https://github.com/gopherbot)\n[@h9jiang](https://github.com/h9jiang)\n[@cuishuang](https://github.com/cuishuang)\n[@jakebailey](https://github.com/jakebailey)\n[@jba](https://github.com/jba)\n[@madelinekalil](https://github.com/madelinekalil)\n[@karamaru](https://github.com/karamaru)\n[alpha](https://github.comalpha)\n[@danztran](https://github.com/danztran)\n[@nsrip](https://github.com/nsrip)\n[dd](https://github.comdd)\n[@pjweinb](https://github.com/pjweinb)\n[@findleyr](https://github.com/findleyr)\n[@samthanawalla](https://github.com/samthanawalla)\n[@seankhliao](https://github.com/seankhliao)\n[@tklauser](https://github.com/tklauser)\n[@vikblom](https://github.com/vikblom)\n[@kwjw](https://github.com/kwjw)\n[@xieyuschen](https://github.com/xieyuschen)\n"
  },
  {
    "path": "gopls/doc/release/v0.20.0.md",
    "content": "---\ntitle: \"Gopls release v0.20.0\"\n---\n\nThis release contains a new experimental Model Context Protocol (MCP)\nserver for gopls, which may be used to integrate a subset of gopls'\nfeatures in AI-assisted environments.\n\nGopls' documentation is now available on the Go project's website at\nhttps://go.dev/gopls. (This link reflects the latest gopls release;\nuse https://tip.golang.org/gopls to see docs for the latest commit.)\nUnlike Markdown files in GitHub, these pages are crawled by Google's\nweb search index.\n\n## Configuration changes\n\nThis release enables by default the new persistent index of packages\nin the module cache. This was first attempted in [v0.19](./v0.19.0.md) but reverted\ndue to problems that have since been fixed.\n\n## Web-based features\n\n### \"Split package\" tool\n\nThe `source.splitPackage` code action opens a web-based tool that\nhelps you split a package into two or more components whose\ndependencies are acyclic.\n\nTo use it, name a set of components, assign each declaration to a\ncomponent, then visualize the dependencies among the components\n(including whether they form a cycle).\nRefresh the page each time you edit your code to see the latest\ninformation.\n\n<p align=\"center\"><img title=\"Split package 'fmt'\" src=\"../assets/splitpkg.png\" width=\"600\"></p>\n\nThe tool makes it easy to iterate over potential decompositions\nuntil you find one you are happy with. A future version of\nthe tool will automate the code transformation, but for now\nyou must do that step by hand.\n\n\n## Editing features\n\n### Model Context Protocol server\n\nGopls now includes an experimental built-in server for the Model Context\nProtocol (MCP), allowing it to expose a subset of its functionality to\nAI assistants in the form of MCP tools.\n\nSee the [documentation](../features/mcp.md) for more information.\n\n**Caveats:** This is a brand new mode of operation for gopls, and so we're\nstill experimenting with the best set of tools and instructions to provide.\nPlease let us know how well it works for you. Also, please be aware that\nallowing LLMs to execute operations in your workspace entails additional\nsecurity considerations, as discussed in the documentation above.\n\n## Analysis features\n\n### `ignoredError` inlay hint\n\nThe new `ignoredError` inlay hint helps catch mistakenly discarded\nerrors. It inserts an `// ignore error` hint following any statement\nthat is a function call whose error result is implicitly ignored. For\nexample, this code:\n\n```go\nf.Close()\n```\nwill appear as:\n```go\nf.Close() // ignore error\n```\n\nTo suppress the hint, write an actual comment containing `ignore\nerror` following the call statement, or explicitly assign the result\nto a blank `_` variable. A handful of common functions such as\n`fmt.Println` are excluded from the check.\n\nEnable it using this configuration: `{\"hints\": {\"ignoredError\": true}}`.\n\n### `unusedfunc` reports unused `type`, `var`, and `const` declarations too\n\n<!-- golang/go#40862 -->\n\nThe\n[unusedfunc](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc/)\nanalyzer now reports any unexported types, variables, and constants\nthat are unreferenced within their declaring package.\n(The problem of unreferenced exported symbols can't be expressed in\nthe analysis framework since it depends on the entire workspace.)\n\n## Code transformation features\n\n<!-- golang/go#45199 -->\nThe Rename operation now allows you to rename an embedded field, such\nas T in `struct{ T }`, so long as the operation is requested at the\nfield declaration (T). Both the field and its type will be renamed.\n"
  },
  {
    "path": "gopls/doc/release/v0.21.0.md",
    "content": "---\ntitle: \"Gopls release v0.21.0 (expected Dec 2025)\"\n---\n\n## Configuration changes\n\n- The new `newGoFileHeader` option allows toggling automatic insertion of the copyright comment\n  and package declaration in a newly created Go file.\n\n- The default value of the `codelenses` setting now includes\n  `run_govulncheck: true`, causing gopls to offer a \"Run govulncheck\"\n  command associated with the `module` declaration in a go.mod file.\n\n- The experimental `vulncheck` setting now supports the enum value\n  `\"Prompt\"`, meaning that vulncheck can be triggered via a prompt;\n  this is now the default.\n\n- The new, experimental `renameMovesSubpackages` setting determines\n  whether a rename package operation applies to subdirectories; see\n  below for details.\n\n## Navigational features:\n\nHover can now report information about selected subexpressions (#69058).\nFor example, selecting the region indicated below:\n\n\t x[i].f()\n\t ~~~~\n\nwill report information about the subexpression `x[i]`, such as its\ntype, constant value (if appropriate), and methods.\nPreviously, Hover would report only about `x`, `i`, or `f`.\n\nThis feature requires the client to supply an extra field in the\n`textDocumentPositionParams` part of its LSP `textDocument/hover`\nrequest: the standard struct has a single `position` of type\n`Position`, but gopls can also handle a `range` field of type\n`Range` that specifies the extent of the text selection.\n(If supplied, it must enclose the `position`.)\n\nThe VS Code code extension already populates this field. We plan to\nuse it across various requests, and to lobby for its adoption by the\nLSP standard.\n\nOther features in brief:\n\n- Definition now works for fields in doc links in comments (#75038).\n- Hover adds navigation to doc links in hovers (golang/vscode-go#3827).\n- Hover now reports information (size, etc) about embedded fields, not just their types (#75975).\n- Folding Range now displays closing parens (#75229) and more ranges (#73735).\n\n## Analysis features\n\n### `reflecttypefor` analyzer\n\n<!-- golang/go#60088 -->\n\nThe new `reflecttypefor` analyzer modernizes calls to `reflect.TypeOf`\nto use `reflect.TypeFor` when the runtime type is known at compile\ntime. For example:\n\n\treflect.TypeOf(uint32(0))\n\nbecomes:\n\n\treflect.TypeFor[uint32]()\n\n### `newexpr` analyzer\n\n<!-- golang/go#45624 -->\n\nThe `newexpr` analyzer finds declarations of and calls to functions\nof this form:\n```go\nfunc varOf(x int) *int { return &x }\n\nuse(varOf(123))\n```\nmodernizing them when appropriate to use the `new(expr)` feature of Go 1.26:\n```go\n//go:fix inline\nfunc varOf(x int) *int { return new(x) }\n\nuse(new(123))\n```\n\nSuch wrapper functions are widely used in serialization packages,\nfor instance the proto.{Int64,String,Bool} helpers used with\nprotobufs.\n\n### `stditerators` analyzer\n\n<!-- golang/go#75693 -->\n\nThe `stditerators` analyzer replaces loops of this form,\n\n      for i := 0; i < x.Len(); i++ {\n          use(x.At(i))\n      }\n\nor their \"range x.Len()\" equivalent, by\n\n      for elem := range x.All() {\n          use(elem)\n      }\n\nfor various types in the standard library that now offer a\nmodern iterator-based API.\n\n### `stringscut` analyzer\n\n<!-- golang/go#71369 -->\n\nThe `stringscut` analyzer modernizes various patterns of use of\n`strings.Index` such as:\n\n\ti := strings.Index(s, sep)\n\tif i >= 0 {\n\t\tuse(s[i:])\n\t}\n\nby a call to `strings.Cut`, introduced in Go 1.25:\n\n\tbefore, after, ok := strings.Cut(s, sep)\n\tif ok {\n\t\tuse(after)\n\t}\n\n### `plusbuild` analyzer\n\n<!-- golang/go#73605 -->\n\nThe `plusbuild` analyzer removes old-style `+build` build-tag comments\nwhen they are redundant with the newer form:\n\n\t//go:build linux\n\t// +build linux\n\n### `errorsastype` analyzer\n\n<!-- golang/go#75692 -->\n\nThe `errorsastype` analyzer replaces calls to `errors.As`:\n\n\tvar myErr *MyError\n\tif errors.As(err, &myErr) { ... }\n\nby the more modern `errors.AsType`, when the type is known statically:\n\n\tif myErr, ok := errors.AsType[*MyError](err) { ... }\n\n\n### `unsafefuncs` analyzer\n\n<!-- golang/go#76648 -->\n\nThe `unsafefuncs` analyzer replaces arithmetic such as:\n\n\tunsafe.Pointer(uintptr(ptr) + uintptr(n))\n\nwhere ptr is an unsafe.Pointer, by calls to `unsafe.Add`, added in Go 1.17.\n\n\tunsafe.Add(ptr, n)\n\n### Miscellaneous\n\n- The `minmax` modernizer now removes user-defined min/max functions when they are redundant.\n- The `stringscutprefix` modernizer now handles `strings.CutSuffix` too. <!-- #75205 -->\n- The `yield` and `nilness` analyzers handle control-flow booleans more precisely. <!-- #74136, #75924 -->\n- The `printf` analyzer now checks calls to local anonymous printf-wrapper functions too.\n- The `staticcheck` suite has been updated to v0.7.\n\n## Code transformation features\n\n### Generalized package renaming\n\n<!-- #57171 #75812 -->\n\nThe Rename operation, invoked on a `package p` declaration, now\nprompts you to edit the entire package path. This allows you to choose\nnot just a new name for the package, but a new directory anywhere\nwithin the same module. For example, you can rename `example.com/foo`\nto `example.com/internal/bar`, and the tool will move files and update\nimports as needed.\n\nBy default, subpackages are no longer moved with the renamed package.\nEnable the new (experimental) `renameMovesSubpackages` setting if you\nwant subpackages to move too. (In due course, we will add LSP support\nfor dialogs so that the server can query the user's intent\ninteractively.)\n\nThis feature requires client support for the LSP\n[`textDocument/prepareRename`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename) operation.\n\n### Renaming from a doc link\n\n<!-- golang/go#42301 -->\nThe Rename operation now treats [doc links](https://tip.golang.org/doc/comment#doclinks)\nlike identifiers, so you can initiate a renaming from a doc link.\n\n## Model context protocol (MCP) features\n\nThe MCP server now supports the `go_rename_symbol` tool, which permits\nan agent to rename a symbol based on its name (e.g. `fmt.Println` or\n`bytes.Buffer.WriteString`). The tool uses the symbol index to resolve\nthe name to a declaration and then initiates a renaming.\n\nThe server also supports the `gopls.vulncheck` tool, allowing agents\nto scan packages for security vulnerabilities.\n\n## Closed issues\n\nhttps://github.com/golang/go/milestone/399?closed=1\n\n"
  },
  {
    "path": "gopls/doc/release/v0.22.0.md",
    "content": "---\ntitle: \"Gopls release v0.22.0 (forthcoming)\"\n---\n\n## Configuration changes\n## Navigation features\n<!-- golang/go#75810 -->\n\n- Asking for references while hovering over the name of a required module in a `go.mod` file\n  will show all the imports of that module in the main module (the go.mod's module).\n## Web-based features\n## Editing features\n## Analysis features\n\n### `atomictypes` analyzer\n<!-- golang/go#77352 -->\n\nThe new atomictypes analyzer suggests replacing the primitive `sync/atomic` functions with\nthe strongly typed atomic wrapper types introduced in Go1.19 (e.g.\natomic.Int32). It refactors declarations like `var x int32` to\n`var x atomic.Int32` and updates all corresponding call sites from\n`atomic.AddInt32(&x, 1)` to method calls like `x.Add(1)`.\n\n### `fieldassignment` analyzer\n<!-- golang/go#76237 -->\nThe fieldassignment analyzer, which reports diagnostics about memory layout and\nwas disabled in v0.17.0, has been restored. It is disabled by default.\n\n\n### `writestring` analyzer\n<!-- golang/go#77369 -->\n\nThe new writestring analyzer detects inefficient string concatenation in uses of WriteString,\nof the form WriteString(a+b), and offers to replace them with WriteString(a); WriteString(b).\n\n### `waitgroup` modernizer renamed to `waitgroupgo`\n<!-- golang/go#77560 -->\n\nPreviously there were two analyzers named `waitgroup`: an analyzer that checks\nfor misuses of `sync.WaitGroup`, and a modernizer that simplifies goroutine\nmanagement with `sync.WaitGroup`. We have renamed the modernizer to `waitgroupgo`.\n\n## Code transformation features\n\n### $feature\n\nhttps://go.dev/issue#xxxxx\n"
  },
  {
    "path": "gopls/doc/settings.md",
    "content": "---\ntitle: \"Gopls: Settings\"\n---\n\nThis document describes gopls' configuration settings.\n\nGopls settings are defined by a JSON object whose valid fields are\ndescribed below. These fields are gopls-specific, and generic LSP\nclients have no knowledge of them.\n\nDifferent clients present configuration settings in their user\ninterfaces in a wide variety of ways.\nFor example, some expect the user to edit the raw JSON object while\nothers use a data structure in the editor's configuration language;\nstill others (such as VS Code) have a graphical configuration system.\nBe sure to consult the documentation for how to express configuration\nsettings in your client.\nSome clients also permit settings to be configured differently for\neach workspace folder.\n\nAny settings that are experimental or for debugging purposes are\nmarked as such.\n\n<!--\nAll settings are uniquely identified by name such as `semanticTokens`\nor `templateExtensions`.\nHowever, for convenience of VS Code, each setting also has an\nundocumented alias whose form is a dotted path such as\n`ui.semanticTokens` or `build.templateExtensions`.\nHowever, only the final segment is actually significant, so\n`build.templateExtensions` is equivalent to `templateExtensions`.\nAll clients but VS Code should use the short form.\n-->\n\n<!-- This portion is generated by doc/generate from the ../internal/settings package. -->\n<!-- BEGIN User: DO NOT MANUALLY EDIT THIS SECTION -->\n\n* [Build](#build)\n* [Formatting](#formatting)\n* [UI](#ui)\n  * [Completion](#completion)\n  * [Diagnostic](#diagnostic)\n  * [Documentation](#documentation)\n  * [Inlayhint](#inlayhint)\n  * [Navigation](#navigation)\n\n<a id='build'></a>\n## Build\n\n<a id='buildFlags'></a>\n### `buildFlags []string`\n\nbuildFlags is the set of flags passed on to the build system when invoked.\nIt is applied to queries like `go list`, which is used when discovering files.\nThe most common use is to set `-tags`.\n\nDefault: `[]`.\n\n<a id='env'></a>\n### `env map[string]string`\n\nenv adds environment variables to external commands run by `gopls`, most notably `go list`.\n\nDefault: `{}`.\n\n<a id='directoryFilters'></a>\n### `directoryFilters []string`\n\ndirectoryFilters can be used to exclude unwanted directories from the\nworkspace. By default, all directories are included. Filters are an\noperator, `+` to include and `-` to exclude, followed by a path prefix\nrelative to the workspace folder. They are evaluated in order, and\nthe last filter that applies to a path controls whether it is included.\nThe path prefix can be empty, so an initial `-` excludes everything.\n\nDirectoryFilters also supports the `**` operator to match 0 or more directories.\n\nExamples:\n\nExclude node_modules at current depth: `-node_modules`\n\nExclude node_modules at any depth: `-**/node_modules`\n\nInclude only project_a: `-` (exclude everything), `+project_a`\n\nInclude only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`\n\nDefault: `[\"-**/node_modules\"]`.\n\n<a id='templateExtensions'></a>\n### `templateExtensions []string`\n\ntemplateExtensions gives the extensions of file names that are treated\nas template files. (The extension\nis the part of the file name after the final dot.)\n\nDefault: `[]`.\n\n<a id='memoryMode'></a>\n### `memoryMode string`\n\n**This setting is experimental and may be deleted.**\n\nobsolete, no effect\n\nDefault: `\"\"`.\n\n<a id='expandWorkspaceToModule'></a>\n### `expandWorkspaceToModule bool`\n\n**This setting is experimental and may be deleted.**\n\nexpandWorkspaceToModule determines which packages are considered\n\"workspace packages\" when the workspace is using modules.\n\nWorkspace packages affect the scope of workspace-wide operations. Notably,\ngopls diagnoses all packages considered to be part of the workspace after\nevery keystroke, so by setting \"ExpandWorkspaceToModule\" to false, and\nopening a nested workspace directory, you can reduce the amount of work\ngopls has to do to keep your workspace up to date.\n\nDefault: `true`.\n\n<a id='standaloneTags'></a>\n### `standaloneTags []string`\n\nstandaloneTags specifies a set of build constraints that identify\nindividual Go source files that make up the entire main package of an\nexecutable.\n\nA common example of standalone main files is the convention of using the\ndirective `//go:build ignore` to denote files that are not intended to be\nincluded in any package, for example because they are invoked directly by\nthe developer using `go run`.\n\nGopls considers a file to be a standalone main file if and only if it has\npackage name \"main\" and has a build directive of the exact form\n\"//go:build tag\" or \"// +build tag\", where tag is among the list of tags\nconfigured by this setting. Notably, if the build constraint is more\ncomplicated than a simple tag (such as the composite constraint\n`//go:build tag && go1.18`), the file is not considered to be a standalone\nmain file.\n\nThis setting is only supported when gopls is built with Go 1.16 or later.\n\nDefault: `[\"ignore\"]`.\n\n<a id='workspaceFiles'></a>\n### `workspaceFiles []string`\n\nworkspaceFiles configures the set of globs that match files defining the\nlogical build of the current workspace. Any on-disk changes to any files\nmatching a glob specified here will trigger a reload of the workspace.\n\nThis setting need only be customized in environments with a custom\nGOPACKAGESDRIVER.\n\nDefault: `[]`.\n\n<a id='formatting'></a>\n## Formatting\n\n<a id='local'></a>\n### `local string`\n\nlocal is the equivalent of the `goimports -local` flag, which puts\nimports beginning with this string after third-party packages. It should\nbe the prefix of the import path whose imports should be grouped\nseparately.\n\nIt is used when tidying imports (during an LSP Organize\nImports request) or when inserting new ones (for example,\nduring completion); an LSP Formatting request merely sorts the\nexisting imports.\n\nDefault: `\"\"`.\n\n<a id='gofumpt'></a>\n### `gofumpt bool`\n\ngofumpt indicates if we should run gofumpt formatting.\n\nDefault: `false`.\n\n<a id='ui'></a>\n## UI\n\n<a id='codelenses'></a>\n### `codelenses map[enum]bool`\n\ncodelenses overrides the enabled/disabled state of each of gopls'\nsources of [Code Lenses](codelenses.md).\n\nExample Usage:\n\n```json5\n\"gopls\": {\n...\n  \"codelenses\": {\n    \"generate\": false,  // Don't show the `go generate` lens.\n  }\n...\n}\n```\n\nDefault: `{\"generate\":true,\"regenerate_cgo\":true,\"run_govulncheck\":true,\"tidy\":true,\"upgrade_dependency\":true,\"vendor\":true}`.\n\n<a id='semanticTokens'></a>\n### `semanticTokens bool`\n\n**This setting is experimental and may be deleted.**\n\nsemanticTokens determines whether gopls will return a\nSemanticTokensProvider at initialization, or respond\nto request for semantic tokens.\n\nDefault: `false`.\n\n<a id='noSemanticString'></a>\n### `noSemanticString bool`\n\n**This setting is experimental and may be deleted.**\n\nnoSemanticString turns off the sending of the semantic token 'string'\n\nDeprecated: Use SemanticTokenTypes[\"string\"] = false instead. See\ngolang/vscode-go#3632\n\nDefault: `false`.\n\n<a id='noSemanticNumber'></a>\n### `noSemanticNumber bool`\n\n**This setting is experimental and may be deleted.**\n\nnoSemanticNumber turns off the sending of the semantic token 'number'\n\nDeprecated: Use SemanticTokenTypes[\"number\"] = false instead. See\ngolang/vscode-go#3632.\n\nDefault: `false`.\n\n<a id='semanticTokenTypes'></a>\n### `semanticTokenTypes map[string]bool`\n\n**This setting is experimental and may be deleted.**\n\nsemanticTokenTypes configures the semantic token types. It allows\ndisabling types by setting each value to false.\nBy default, all types are enabled.\n\nDefault: `{}`.\n\n<a id='semanticTokenModifiers'></a>\n### `semanticTokenModifiers map[string]bool`\n\n**This setting is experimental and may be deleted.**\n\nsemanticTokenModifiers configures the semantic token modifiers. It allows\ndisabling modifiers by setting each value to false.\nBy default, all modifiers are enabled.\n\nDefault: `{}`.\n\n<a id='newGoFileHeader'></a>\n### `newGoFileHeader bool`\n\nnewGoFileHeader enables automatic insertion of the copyright comment\nand package declaration in a newly created Go file.\n\nDefault: `true`.\n\n<a id='renameMovesSubpackages'></a>\n### `renameMovesSubpackages bool`\n\n**This setting is experimental and may be deleted.**\n\nrenameMovesSubpackages enables Rename operations on packages to\nmove subdirectories of the target package.\n\nDefault: `false`.\n\n<a id='completion'></a>\n## Completion\n\n<a id='usePlaceholders'></a>\n### `usePlaceholders bool`\n\nplaceholders enables placeholders for function parameters or struct\nfields in completion responses.\n\nDefault: `false`.\n\n<a id='completionBudget'></a>\n### `completionBudget time.Duration`\n\n**This setting is for debugging purposes only.**\n\ncompletionBudget is the soft latency goal for completion requests. Most\nrequests finish in a couple milliseconds, but in some cases deep\ncompletions can take much longer. As we use up our budget we\ndynamically reduce the search scope to ensure we return timely\nresults. Zero means unlimited.\n\nDefault: `\"100ms\"`.\n\n<a id='matcher'></a>\n### `matcher enum`\n\n**This is an advanced setting and should not be configured by most `gopls` users.**\n\nmatcher sets the algorithm that is used when calculating completion\ncandidates.\n\nMust be one of:\n\n* `\"CaseInsensitive\"`\n* `\"CaseSensitive\"`\n* `\"Fuzzy\"`\n\nDefault: `\"Fuzzy\"`.\n\n<a id='experimentalPostfixCompletions'></a>\n### `experimentalPostfixCompletions bool`\n\n**This setting is experimental and may be deleted.**\n\nexperimentalPostfixCompletions enables artificial method snippets\nsuch as \"someSlice.sort!\".\n\nDefault: `true`.\n\n<a id='completeFunctionCalls'></a>\n### `completeFunctionCalls bool`\n\ncompleteFunctionCalls enables function call completion.\n\nWhen completing a statement, or when a function return type matches the\nexpected of the expression being completed, completion may suggest call\nexpressions (i.e. may include parentheses).\n\nDefault: `true`.\n\n<a id='diagnostic'></a>\n## Diagnostic\n\n<a id='analyses'></a>\n### `analyses map[string]bool`\n\nanalyses specify analyses that the user would like to enable or disable.\nA map of the names of analysis passes that should be enabled/disabled.\nA full list of analyzers that gopls uses can be found in\n[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\n\nExample Usage:\n\n```json5\n...\n\"analyses\": {\n  \"unreachable\": false, // Disable the unreachable analyzer.\n  \"unusedvariable\": true  // Enable the unusedvariable analyzer.\n}\n...\n```\n\nDefault: `{}`.\n\n<a id='staticcheck'></a>\n### `staticcheck bool`\n\n**This setting is experimental and may be deleted.**\n\nstaticcheck configures the default set of analyses staticcheck.io.\nThese analyses are documented on\n[Staticcheck's website](https://staticcheck.io/docs/checks/).\n\nThe \"staticcheck\" option has three values:\n- false: disable all staticcheck analyzers\n- true: enable all staticcheck analyzers\n- unset: enable a subset of staticcheck analyzers\n  selected by gopls maintainers for runtime efficiency\n  and analytic precision.\n\nRegardless of this setting, individual analyzers can be\nselectively enabled or disabled using the `analyses` setting.\n\nDefault: `false`.\n\n<a id='staticcheckProvided'></a>\n### `staticcheckProvided bool`\n\n**This setting is experimental and may be deleted.**\n\n\nDefault: `false`.\n\n<a id='annotations'></a>\n### `annotations map[enum]bool`\n\nannotations specifies the various kinds of compiler\noptimization details that should be reported as diagnostics\nwhen enabled for a package by the \"Toggle compiler\noptimization details\" (`gopls.gc_details`) command.\n\n(Some users care only about one kind of annotation in their\nprofiling efforts. More importantly, in large packages, the\nnumber of annotations can sometimes overwhelm the user\ninterface and exceed the per-file diagnostic limit.)\n\nTODO(adonovan): rename this field to CompilerOptDetail.\n\nEach enum must be one of:\n\n* `\"bounds\"` controls bounds checking diagnostics.\n* `\"escape\"` controls diagnostics about escape choices.\n* `\"inline\"` controls diagnostics about inlining choices.\n* `\"nil\"` controls nil checks.\n\nDefault: `{\"bounds\":true,\"escape\":true,\"inline\":true,\"nil\":true}`.\n\n<a id='vulncheck'></a>\n### `vulncheck enum`\n\n**This setting is experimental and may be deleted.**\n\nvulncheck enables vulnerability scanning.\n\nMust be one of:\n\n* `\"Imports\"`: In Imports mode, `gopls` will report vulnerabilities that affect packages\ndirectly and indirectly used by the analyzed main module.\n* `\"Off\"`: Disable vulnerability analysis.\n* `\"Prompt\"`: Vulncheck can be triggered via prompt.\n\nDefault: `\"Prompt\"`.\n\n<a id='diagnosticsDelay'></a>\n### `diagnosticsDelay time.Duration`\n\n**This is an advanced setting and should not be configured by most `gopls` users.**\n\ndiagnosticsDelay controls the amount of time that gopls waits\nafter the most recent file modification before computing deep diagnostics.\nSimple diagnostics (parsing and type-checking) are always run immediately\non recently modified packages.\n\nThis option must be set to a valid duration string, for example `\"250ms\"`.\n\nDefault: `\"1s\"`.\n\n<a id='diagnosticsTrigger'></a>\n### `diagnosticsTrigger enum`\n\n**This setting is experimental and may be deleted.**\n\ndiagnosticsTrigger controls when to run diagnostics.\n\nMust be one of:\n\n* `\"Edit\"`: Trigger diagnostics on file edit and save. (default)\n* `\"Save\"`: Trigger diagnostics only on file save. Events like initial workspace load\nor configuration change will still trigger diagnostics.\n\nDefault: `\"Edit\"`.\n\n<a id='analysisProgressReporting'></a>\n### `analysisProgressReporting bool`\n\nanalysisProgressReporting controls whether gopls sends progress\nnotifications when construction of its index of analysis facts is taking a\nlong time. Cancelling these notifications will cancel the indexing task,\nthough it will restart after the next change in the workspace.\n\nWhen a package is opened for the first time and heavyweight analyses such as\nstaticcheck are enabled, it can take a while to construct the index of\nanalysis facts for all its dependencies. The index is cached in the\nfilesystem, so subsequent analysis should be faster.\n\nDefault: `true`.\n\n<a id='documentation'></a>\n## Documentation\n\n<a id='hoverKind'></a>\n### `hoverKind enum`\n\nhoverKind controls the information that appears in the hover text.\nSingleLine is intended for use only by authors of editor plugins.\n\nMust be one of:\n\n* `\"FullDocumentation\"`\n* `\"NoDocumentation\"`\n* `\"SingleLine\"`\n* `\"Structured\"` is a misguided experimental setting that returns a JSON\nhover format. This setting should not be used, as it will be removed in a\nfuture release of gopls.\n* `\"SynopsisDocumentation\"`\n\nDefault: `\"FullDocumentation\"`.\n\n<a id='linkTarget'></a>\n### `linkTarget string`\n\nlinkTarget is the base URL for links to Go package\ndocumentation returned by LSP operations such as Hover and\nDocumentLinks and in the CodeDescription field of each\nDiagnostic.\n\nIt might be one of:\n\n* `\"godoc.org\"`\n* `\"pkg.go.dev\"`\n\nIf company chooses to use its own `godoc.org`, its address can be used as well.\n\nModules matching the GOPRIVATE environment variable will not have\ndocumentation links in hover.\n\nDefault: `\"pkg.go.dev\"`.\n\n<a id='linksInHover'></a>\n### `linksInHover enum`\n\nlinksInHover controls the presence of documentation links in hover markdown.\n\nMust be one of:\n\n* false: do not show links\n* true: show links to the `linkTarget` domain\n* `\"gopls\"`: show links to gopls' internal documentation viewer\n\nDefault: `true`.\n\n<a id='inlayhint'></a>\n## Inlayhint\n\n<a id='hints'></a>\n### `hints map[enum]bool`\n\n**This setting is experimental and may be deleted.**\n\nhints specify inlay hints that users want to see. A full list of hints\nthat gopls uses can be found in\n[inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).\n\nDefault: `{}`.\n\n<a id='navigation'></a>\n## Navigation\n\n<a id='importShortcut'></a>\n### `importShortcut enum`\n\nimportShortcut specifies whether import statements should link to\ndocumentation or go to definitions.\n\nMust be one of:\n\n* `\"Both\"`\n* `\"Definition\"`\n* `\"Link\"`\n\nDefault: `\"Both\"`.\n\n<a id='symbolMatcher'></a>\n### `symbolMatcher enum`\n\n**This is an advanced setting and should not be configured by most `gopls` users.**\n\nsymbolMatcher sets the algorithm that is used when finding workspace symbols.\n\nMust be one of:\n\n* `\"CaseInsensitive\"`\n* `\"CaseSensitive\"`\n* `\"FastFuzzy\"`\n* `\"Fuzzy\"`\n\nDefault: `\"FastFuzzy\"`.\n\n<a id='symbolStyle'></a>\n### `symbolStyle enum`\n\n**This is an advanced setting and should not be configured by most `gopls` users.**\n\nsymbolStyle controls how symbols are qualified in symbol responses.\n\nExample Usage:\n\n```json5\n\"gopls\": {\n...\n  \"symbolStyle\": \"Dynamic\",\n...\n}\n```\n\nMust be one of:\n\n* `\"Dynamic\"` uses whichever qualifier results in the highest scoring\nmatch for the given symbol query. Here a \"qualifier\" is any \"/\" or \".\"\ndelimited suffix of the fully qualified symbol. i.e. \"to/pkg.Foo.Field\" or\njust \"Foo.Field\".\n* `\"Full\"` is fully qualified symbols, i.e.\n\"path/to/pkg.Foo.Field\".\n* `\"Package\"` is package qualified symbols i.e.\n\"pkg.Foo.Field\".\n\nDefault: `\"Dynamic\"`.\n\n<a id='symbolScope'></a>\n### `symbolScope enum`\n\nsymbolScope controls which packages are searched for workspace/symbol\nrequests. When the scope is \"workspace\", gopls searches only workspace\npackages. When the scope is \"all\", gopls searches all loaded packages,\nincluding dependencies and the standard library.\n\nMust be one of:\n\n* `\"all\"` matches symbols in any loaded package, including\ndependencies.\n* `\"workspace\"` matches symbols in workspace packages only.\n\nDefault: `\"all\"`.\n\n<a id='maxFileCacheBytes'></a>\n### `maxFileCacheBytes int64`\n\n**This setting is experimental and may be deleted.**\n\nmaxFileCacheBytes sets a soft limit on the file cache size in bytes.\nIf zero, the default budget is used.\n\nThe cache may temporarily use more than this amount.\nAlso, this parameter limits file contents; disk block usage\nas measured by du(1) may be significantly higher.\n\nDefault: `0`.\n\n<a id='verboseOutput'></a>\n### `verboseOutput bool`\n\n**This setting is for debugging purposes only.**\n\nverboseOutput enables additional debug logging.\n\nDefault: `false`.\n\n<!-- END User: DO NOT MANUALLY EDIT THIS SECTION -->\n"
  },
  {
    "path": "gopls/doc/troubleshooting.md",
    "content": "---\ntitle: \"Gopls: Troubleshooting\"\n---\n\nIf you suspect that `gopls` is crashing or not working correctly, please follow the troubleshooting steps below.\n\nIf `gopls` is using too much memory, please follow the steps under [Memory usage](#debug-memory-usage).\n\n## Steps\n\nVS Code users should follow [their troubleshooting guide](https://github.com/golang/vscode-go/blob/master/docs/troubleshooting.md), which has more a more specific version of these instructions.\n\n1. Verify that your project is in good shape by working with it outside of your editor. Running a command like `go build ./...` in the workspace directory will compile everything. For modules, `go mod tidy` is another good check, though it may modify your `go.mod`.\n1. Check that your editor isn't showing any diagnostics that indicate a problem with your workspace. They may appear as diagnostics on a Go file's package declaration, diagnostics in a go.mod file, or as a status or progress message. Problems in the workspace configuration can cause many different symptoms. See the [workspace setup instructions](workspace.md) for help.\n1. Make sure `gopls` is up to date by following the [installation instructions](index.md#installation), then [restarting gopls](#restart-gopls).\n1. Optionally, [ask for help](#ask-for-help) on Gophers Slack.\n1. Finally, [report the issue](#file-an-issue) to the `gopls` developers.\n\n## Restart `gopls`\n\n`gopls` has no persistent state, so restarting it will fix transient problems. This is good and bad: good, because you can keep working, and bad, because you won't be able to debug the issue until it recurs.\n\nIn most cases, closing all your open editors will guarantee that `gopls` is killed and restarted. If you don't want to do that, there may be an editor command you can use to restart only `gopls`. Note that some `vim` configurations keep the server alive for a while after the editor exits; you may need to explicitly kill `gopls` if you use `vim`.\n\n## Ask for help\n\nGophers Slack has active editor-specific channels like [#emacs](https://gophers.slack.com/archives/C0HKHULEM), [#vim](https://gophers.slack.com/archives/C07GBR52P), and [#vscode](https://gophers.slack.com/archives/C2B4L99RS) that can help debug further. If you're confident the problem is with `gopls`, you can go straight to [#gopls](https://gophers.slack.com/archives/CJZH85XCZ). Invites are [available to everyone](https://invite.slack.golangbridge.org). Come prepared with a short description of the issue, and try to be available to answer questions for a while afterward.\n\n## File an issue\n\nWe can't diagnose a problem from just a description. When filing an issue, please include as much as possible of the following information:\n\n1. Your editor and any settings you have configured (for example, your VSCode `settings.json` file).\n1. A sample program that reproduces the issue, if possible.\n1. The output of `gopls version` on the command line.\n1. A complete gopls log file from a session where the issue occurred. It should have a `go env for <workspace folder>` log line near the beginning. It's also helpful to tell us the timestamp the problem occurred, so we can find it the log. See the [instructions](#capture-logs) for information on how to capture gopls logs.\n\nYour editor may have a command that fills out some of the necessary information, such as `:GoReportGitHubIssue` in `vim-go`. Otherwise, you can use `gopls bug` on the command line. If neither of those work you can start from scratch directly on the [Go issue tracker](https://github.com/golang/go/issues/new?title=x%2Ftools%2Fgopls%3A%20%3Cfill%20this%20in%3E).\n\n## Capture logs\n\nYou may have to change your editor's configuration to pass a `-logfile` flag to gopls.\n\nTo increase the level of detail in your logs, start `gopls` with the `-rpc.trace` flag. To start a debug server that will allow you to see profiles and memory usage, start `gopls` with `serve --debug=localhost:6060`. You will then be able to view debug information by navigating to `localhost:6060`.\n\nIf you are unsure of how to pass a flag to `gopls` through your editor, please see the [documentation for your editor](index.md#editors).\n\n## Debug memory usage\n\n`gopls` automatically writes out memory debug information when your usage exceeds 1GB. This information can be found in your temporary directory with names like `gopls.1234-5GiB-withnames.zip`. On Windows, your temporary directory will be located at `%TMP%`, and on Unixes, it will be `$TMPDIR`, which is usually `/tmp`. Please [file an issue](#file-an-issue) with this memory debug information attached. If you are uncomfortable sharing the package names of your code, you can share the `-nonames` zip instead, but it's much less useful.\n"
  },
  {
    "path": "gopls/doc/workspace.md",
    "content": "---\ntitle: \"Gopls: Setting up your workspace\"\n---\n\nIn the language server protocol, a \"workspace\" consists of a folder along with\nper-folder configuration. Some LSP clients such as VS Code allow configuring\nworkspaces explicitly, while others do so automatically by looking for special\nfiles defining a workspace root (such as a `.git` directory or `go.mod` file).\n\nIn order to function, gopls needs a defined scope in which language features\nlike references, rename, and implementation should operate. Put differently,\ngopls needs to infer from the LSP workspace which  `go build` invocations you\nwould use to build your workspace, including the working directory,\nenvironment, and build flags.\n\nIn the past, it could be tricky to set up your workspace so that gopls would\ninfer the correct build information. It required opening the correct directory\nor using a `go.work` file to tell gopls about the modules you're working on,\nand configuring the correct operating system and architecture in advance.\nWhen this didn't work as expected, gopls would often fail in mysterious\nways--the dreaded \"No packages found\" error.\n\nStarting with gopls v0.15.0, workspace configuration is much simpler, and gopls\nwill typically work when you open a Go file anywhere in your workspace. If it\nisn't working for you, or if you want to better understand how gopls models\nyour workspace, please read on.\n\n## Workspace builds\n\nStarting with gopls v0.15.0, gopls will guess the builds you are working on\nbased on the set of open files. When you open a file in a workspace folder,\ngopls checks whether the file is contained in a module, `go.work` workspace, or\nGOPATH directory, and configures the build accordingly. Additionally, if you\nopen a file that is constrained to a different operating system or\narchitecture, for example opening `foo_windows.go` when working on Linux, gopls\nwill create a scope with `GOOS` and `GOARCH` set to a value that matches the\nfile.\n\nFor example, suppose we had a repository with three modules: `moda`, `modb`,\nand `modc`, and a `go.work` file using modules `moda` and `modb`. If we open\nthe files `moda/a.go`, `modb/b.go`, `moda/a_windows.go`, and `modc/c.go`, gopls\nwill automatically create three builds:\n\n![Zero Config gopls](assets/zeroconfig.png)\n\nThis allows gopls to _just work_ when you open a Go file, but it does come with\nseveral caveats:\n\n- It causes gopls to do more work, since it is now tracking three builds\n  instead of one. However, the recent\n  [scalability redesign](https://go.dev/blog/gopls-scalability)\n  allows much of this work to be avoided through efficient caching.\n- For operations invoked from a given file, such as \"References\"\n  or \"Implementations\", gopls executes the operation in\n  _the default build for that file_. For example, finding references to\n  a symbol `S` from `foo_linux.go` will return references from the Linux build,\n  and finding references to the same symbol `S` from `foo_windows.go` will\n  return references from the Windows build. Gopls searches the default build\n  for the file, but it doesn't search all the other possible builds (even\n  though that would be nice) because it is liable to be too expensive.\n  Issues [#65757](https://go.dev/issue/65757) and\n  [#65755](https://go.dev/issue/65755) propose improvements to this behavior.\n- When selecting a `GOOS/GOARCH` combination to match a build-constrained file,\n  gopls will choose the first matching combination from\n  [this list](https://cs.opensource.google/go/x/tools/+/master:gopls/internal/cache/port.go;l=30;drc=f872b3d6f05822d290bc7bdd29db090fd9d89f5c).\n  In some cases, that may be surprising.\n- When working in a `GOOS/GOARCH` constrained file that does not match your\n  default toolchain, `CGO_ENABLED=0` is implicitly set, since a C toolchain for\n  that target is unlikely to be available. This means that gopls will not\n  work in files including `import \"C\"`. Issue\n  [#65758](https://go.dev/issue/65758) may lead to improvements in this\n  behavior.\n- Gopls is currently unable to guess build flags that include arbitrary\n  user-defined build constraints, such as a file with the build directive\n  `//go:build mytag`. Issue [#65089](https://go.dev/issue/65089) proposes\n  a heuristic by which gopls could handle this automatically.\n\nPlease provide feedback on this behavior by upvoting or commenting the issues\nmentioned above, or opening a [new issue](https://go.dev/issue/new) for other\nimprovements you'd like to see.\n\n## When to use a `go.work` file for development\n\nStarting with Go 1.18, the `go` command has built-in support for multi-module\nworkspaces specified by [`go.work`](https://go.dev/ref/mod#workspaces) files.\nGopls will recognize these files if they are present in your workspace.\n\nUse a `go.work` file when:\n\n- you want to work on multiple modules simultaneously in a single logical\n  build, for example if you want changes to one module to be reflected in\n  another.\n- you want to improve gopls' memory usage or performance by reducing the number\n  of builds it must track.\n- you want gopls to know which modules you are working on in a multi-module\n  workspace, without opening any files. For example, it may be convenient to use\n  `workspace/symbol` queries before any files are open.\n- you are using gopls v0.14.2 or earlier, and want to work on multiple\n  modules.\n\nFor example, suppose this repo is checked out into the `$WORK/tools` directory,\nand [`x/mod`](https://pkg.go.dev/golang.org/x/mod) is checked out into\n`$WORK/mod`, and you are working on a new `x/mod` API for editing `go.mod`\nfiles that you want to simultaneously integrate into gopls.\n\nYou can work on both `golang.org/x/tools/gopls` and `golang.org/x/mod`\nsimultaneously by creating a `go.work` file:\n\n```sh\ncd $WORK\ngo work init\ngo work use tools/gopls mod\n```\n\nthen opening the `$WORK` directory in your editor.\n\n## When to manually configure `GOOS`, `GOARCH`, or `-tags`\n\nAs described in the first section, gopls v0.15.0 and later will try to\nconfigure a new build scope automatically when you open a file that doesn't\nmatch the system default operating system (`GOOS`) or architecture (`GOARCH`).\n\nHowever, per the caveats listed in that section, this automatic behavior comes\nwith limitations. Customize your gopls environment by setting `GOOS` or\n`GOARCH` in your\n[`\"build.env\"`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#env)\nor `-tags=...` in your\"\n[\"build.buildFlags\"](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#buildflags)\nwhen:\n\n- You want to modify the default build environment.\n- Gopls is not guessing the `GOOS/GOARCH` combination you want to use for\n  cross platform development.\n- You need to work on a file that is constrained by a user-defined build tags,\n  such as the build directive `//go:build mytag`.\n\n## GOPATH mode\n\nWhen opening a directory within a `GOPATH` directory, the workspace scope will\nbe just that directory and all directories contained within it. Note that\nopening a large GOPATH directory can make gopls very slow to start.\n"
  },
  {
    "path": "gopls/go.mod",
    "content": "module golang.org/x/tools/gopls\n\ngo 1.26.0\n\nrequire (\n\tgithub.com/fatih/gomodifytags v1.17.1-0.20250423142747-f3939df9aa3c\n\tgithub.com/fsnotify/fsnotify v1.9.0\n\tgithub.com/google/go-cmp v0.7.0\n\tgithub.com/google/jsonschema-go v0.4.2\n\tgithub.com/jba/templatecheck v0.7.1\n\tgithub.com/modelcontextprotocol/go-sdk v1.4.0\n\tgolang.org/x/mod v0.34.0\n\tgolang.org/x/sync v0.20.0\n\tgolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c\n\tgolang.org/x/text v0.35.0\n\tgolang.org/x/tools v0.42.0\n\tgolang.org/x/vuln v1.1.4\n\tgopkg.in/yaml.v3 v3.0.1\n\thonnef.co/go/tools v0.7.0\n\tmvdan.cc/gofumpt v0.9.2\n\tmvdan.cc/xurls/v2 v2.6.0\n)\n\nrequire (\n\tgithub.com/BurntSushi/toml v1.6.0 // indirect\n\tgithub.com/fatih/camelcase v1.0.0 // indirect\n\tgithub.com/fatih/structtag v1.2.0 // indirect\n\tgithub.com/google/safehtml v0.1.0 // indirect\n\tgithub.com/segmentio/asm v1.2.1 // indirect\n\tgithub.com/segmentio/encoding v0.5.3 // indirect\n\tgithub.com/yosida95/uritemplate/v3 v3.0.2 // indirect\n\tgolang.org/x/exp/typeparams v0.0.0-20260218203240-3dfff04db8fa // indirect\n\tgolang.org/x/oauth2 v0.36.0 // indirect\n\tgolang.org/x/sys v0.42.0 // indirect\n\tgolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect\n\tgopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect\n)\n\nreplace golang.org/x/tools => ../\n"
  },
  {
    "path": "gopls/go.sum",
    "content": "github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=\ngithub.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=\ngithub.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=\ngithub.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=\ngithub.com/fatih/gomodifytags v1.17.1-0.20250423142747-f3939df9aa3c h1:dDSgAjoOMp8da3egfz0t2S+t8RGOpEmEXZubcGuc0Bg=\ngithub.com/fatih/gomodifytags v1.17.1-0.20250423142747-f3939df9aa3c/go.mod h1:YVLagR57bBxMai8IAEc7V4E/MWUYi0oUutLrZcTcnI8=\ngithub.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=\ngithub.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=\ngithub.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=\ngithub.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=\ngithub.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=\ngithub.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=\ngithub.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=\ngithub.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=\ngithub.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=\ngithub.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8=\ngithub.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=\ngithub.com/jba/templatecheck v0.7.1 h1:yOEIFazBEwzdTPYHZF3Pm81NF1ksxx1+vJncSEwvjKc=\ngithub.com/jba/templatecheck v0.7.1/go.mod h1:n1Etw+Rrw1mDDD8dDRsEKTwMZsJ98EkktgNJC6wLUGo=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/modelcontextprotocol/go-sdk v1.4.0 h1:u0kr8lbJc1oBcawK7Df+/ajNMpIDFE41OEPxdeTLOn8=\ngithub.com/modelcontextprotocol/go-sdk v1.4.0/go.mod h1:Nxc2n+n/GdCebUaqCOhTetptS17SXXNu9IfNTaLDi1E=\ngithub.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=\ngithub.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=\ngithub.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=\ngithub.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=\ngithub.com/segmentio/encoding v0.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w=\ngithub.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=\ngithub.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=\ngithub.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngolang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=\ngolang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=\ngolang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=\ngolang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=\ngolang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=\ngolang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=\ngolang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=\ngolang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=\ngolang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=\ngolang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=\ngolang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=\ngolang.org/x/exp/typeparams v0.0.0-20260218203240-3dfff04db8fa h1:6Wi43P0isP8Nl8D4qJmA3VC4FswVH0RJkr5cauo67SQ=\ngolang.org/x/exp/typeparams v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:PqrXSW65cXDZH0k4IeUbhmg/bcAZDbzNz3byBpKCsXo=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=\ngolang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=\ngolang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=\ngolang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=\ngolang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=\ngolang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=\ngolang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=\ngolang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=\ngolang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=\ngolang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=\ngolang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=\ngolang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=\ngolang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=\ngolang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=\ngolang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=\ngolang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=\ngolang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=\ngolang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=\ngolang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=\ngolang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=\ngolang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=\ngolang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=\ngolang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=\ngolang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=\ngolang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=\ngolang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=\ngolang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=\ngolang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=\ngolang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=\ngolang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=\ngolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc=\ngolang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw=\ngolang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=\ngolang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=\ngolang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=\ngolang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=\ngolang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=\ngolang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=\ngolang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=\ngolang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=\ngolang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=\ngolang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=\ngolang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=\ngolang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=\ngolang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=\ngolang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=\ngolang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=\ngolang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=\ngolang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=\ngolang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=\ngolang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=\ngolang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=\ngolang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=\ngolang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=\ngolang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=\ngolang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=\ngolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=\ngolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=\ngolang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=\ngolang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nhonnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU=\nhonnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc=\nmvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4=\nmvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s=\nmvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=\nmvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=\n"
  },
  {
    "path": "gopls/integration/govim/Dockerfile",
    "content": "# Copyright 2019 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\n# govim requires a more recent version of vim than is available in most\n# distros, so we build from their base image.\nFROM govim/govim:latest-vim\nARG GOVIM_REF\n\nENV GOPROXY=https://proxy.golang.org GOPATH=/go VIM_FLAVOR=vim\nWORKDIR /src\n\n# Clone govim. In order to use the go command for resolving latest, we download\n# a redundant copy of govim to the build cache using `go mod download`.\nRUN git clone https://github.com/govim/govim /src/govim && cd /src/govim && \\\n    git checkout $GOVIM_REF\n"
  },
  {
    "path": "gopls/integration/govim/README.md",
    "content": "# govim integration tests\n\nFiles in this directory configure Cloud Build to run [govim] integration tests\nagainst a gopls binary built from source.\n\n## Running on GCP\n\nTo run these integration tests in Cloud Build, use the following steps.  Here\nwe assume that `$PROJECT_ID` is a valid GCP project and `$BUCKET` is a cloud\nstorage bucket owned by that project.\n\n- `cd` to the root directory of the tools project.\n- (at least once per GCP project) Build the test harness:\n```\n$ gcloud builds submit \\\n\t--project=\"${PROJECT_ID}\" \\\n\t--config=gopls/integration/govim/cloudbuild.harness.yaml\n```\n- Run the integration tests:\n```\n$ gcloud builds submit \\\n\t--project=\"${PROJECT_ID}\" \\\n\t--config=gopls/integration/govim/cloudbuild.yaml \\\n\t--substitutions=_RESULT_BUCKET=\"${BUCKET}\"\n```\n\n## Fetching Artifacts\n\nAssuming the artifacts bucket is world readable, you can fetch integration from\nGCS. They are located at:\n\n- logs: `https://storage.googleapis.com/${BUCKET}/log-${EVALUATION_ID}.txt`\n- artifact tarball: `https://storage.googleapis.com/${BUCKET}/govim/${EVALUATION_ID}/artifacts.tar.gz`\n\nThe `artifacts.go` command can be used to fetch both artifacts using an\nevaluation id.\n\n## Running locally\n\nRun `gopls/integration/govim/run_local.sh`. This may take a while the first\ntime it is run, as it will require building the test harness. This script\naccepts two flags to modify its behavior:\n\n**--sudo**: run docker with `sudo`\n**--short**: run `go test -short`\n\n[govim]: https://github.com/govim/govim\n"
  },
  {
    "path": "gopls/integration/govim/artifacts.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n)\n\nvar bucket = flag.String(\"bucket\", \"golang-gopls_integration_tests\", \"GCS bucket holding test artifacts.\")\n\nconst usage = `\nartifacts [--bucket=<bucket ID>] <cloud build evaluation ID>\n\nFetch artifacts from an integration test run. Evaluation ID should be extracted\nfrom the cloud build notification.\n\nIn order for this to work, the GCS bucket that artifacts were written to must\nbe publicly readable. By default, this fetches from the\ngolang-gopls_integration_tests bucket.\n`\n\nfunc main() {\n\tflag.Usage = func() {\n\t\tfmt.Fprint(flag.CommandLine.Output(), usage)\n\t}\n\tflag.Parse()\n\tif flag.NArg() != 1 {\n\t\tflag.Usage()\n\t\tos.Exit(2)\n\t}\n\tevalID := flag.Arg(0)\n\tlogURL := fmt.Sprintf(\"https://storage.googleapis.com/%s/log-%s.txt\", *bucket, evalID)\n\tif err := download(logURL); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"downloading logs: %v\", err)\n\t}\n\ttarURL := fmt.Sprintf(\"https://storage.googleapis.com/%s/govim/%s/artifacts.tar.gz\", *bucket, evalID)\n\tif err := download(tarURL); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"downloading artifact tarball: %v\", err)\n\t}\n}\n\nfunc download(artifactURL string) error {\n\tname := path.Base(artifactURL)\n\tresp, err := http.Get(artifactURL)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fetching from GCS: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"got status code %d from GCS\", resp.StatusCode)\n\t}\n\tdata, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading result: %v\", err)\n\t}\n\tif err := os.WriteFile(name, data, 0644); err != nil {\n\t\treturn fmt.Errorf(\"writing artifact: %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/integration/govim/cloudbuild.harness.yaml",
    "content": "# Copyright 2019 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\n# Build the govim test harness that will be used to run govim integration tests\n# for gopls. See README.md for instructions on how to use this.\nsteps:\n  - name: 'gcr.io/cloud-builders/docker'\n    args: ['build',\n      # To allow for breaking changes to this test harness, tag with a major\n      # version number.\n      '-t', 'gcr.io/$PROJECT_ID/govim-harness:latest',\n      '-t', 'gcr.io/$PROJECT_ID/govim-harness:3',\n      # It is assumed that this build is running from the root directory of the\n      # tools repository.\n      '-f', 'gopls/integration/govim/Dockerfile',\n      # Use the integration test directory as build context: the test harness\n      # doesn't actually require any local files.\n      'gopls/integration/govim']\nimages:\n  - gcr.io/$PROJECT_ID/govim-harness\n"
  },
  {
    "path": "gopls/integration/govim/cloudbuild.yaml",
    "content": "# Copyright 2019 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\n# Build gopls, and run the govim integration tests.  See README.md for\n# instructions on how to use this.\n\nsubstitutions:\n  # This bucket must be owned by the GCP project executing the build. If\n  # you are running this from your own project, override using --substitutions.\n  _RESULT_BUCKET: 'golang-gopls_integration_tests'\n\nsteps:\n  # Build gopls from source, to use with the govim integration tests.\n  - name: 'golang:1.14'\n    env: ['GOPROXY=https://proxy.golang.org']\n    dir: 'gopls'\n    args: ['go', 'build']\n\n  # Run the tests. Note that the script in this step does not return the exit\n  # code from `go test`, but rather saves it for use in the final step after\n  # uploading artifacts.\n  - name: 'gcr.io/$PROJECT_ID/govim-harness:3'\n    dir: '/src/govim'\n    volumes:\n      - name: artifacts\n        path: /artifacts\n    env:\n      - GOVIM_TESTSCRIPT_WORKDIR_ROOT=/artifacts\n      - VIM_FLAVOR=vim\n    args: ['/workspace/gopls/integration/govim/run_tests_for_cloudbuild.sh']\n\n  # The govim tests produce a large number of artifacts; tarball/gzip to reduce\n  # roundtrips and save space.\n  - name: 'ubuntu'\n    volumes:\n      - name: artifacts\n        path: /artifacts\n    args: ['tar', '-czf', 'artifacts.tar.gz', '/artifacts']\n\n  # Upload artifacts to GCS.\n  - name: 'gcr.io/cloud-builders/gcloud'\n    args: ['storage', 'cp', 'artifacts.tar.gz', 'gs://${_RESULT_BUCKET}/govim/${BUILD_ID}/artifacts.tar.gz']\n\n  # Exit with the actual exit code of the integration tests.\n  - name: 'ubuntu'\n    args: ['bash', 'govim_test_result.sh']\n\n# Write build logs to the same bucket as artifacts, so they can be more easily\n# shared.\nlogsBucket: 'gs://${_RESULT_BUCKET}'\n"
  },
  {
    "path": "gopls/integration/govim/run_local.sh",
    "content": "#!/bin/bash -e\n\n# Copyright 2019 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\n# Run govim integration tests against a local gopls.\n\nusage() {\n  cat <<EOUSAGE\nUsage: $0 [--sudo] [--short] [--version (semver|latest)]\n\nArgs:\n  --sudo     run docker with sudo\n  --short    run `go test` with `-short`\n  --version  run on the specific tagged govim version (or latest) rather\n             than the default branch\n\nRun govim tests against HEAD using local docker.\nEOUSAGE\n}\n\nSUDO_IF_NEEDED=\nTEST_SHORT=\nDOCKERFILE=gopls/integration/govim/Dockerfile\nGOVIM_REF=main\nwhile [[ $# -gt 0 ]]; do\n  case \"$1\" in\n    \"-h\" | \"--help\" | \"help\")\n      usage\n      exit 0\n      ;;\n    \"--sudo\")\n      SUDO_IF_NEEDED=\"sudo \"\n      shift\n      ;;\n    \"--short\")\n      TEST_SHORT=\"-short\"\n      shift\n      ;;\n    \"--version\")\n      if [[ -z \"$2\" ]]; then\n        usage\n        exit 1\n      fi\n      GOVIM_REF=$2\n      if [[ \"${GOVIM_REF}\" == \"latest\" ]]; then\n        TMPGOPATH=$(mktemp -d)\n        trap \"GOPATH=${TMPGOPATH} go clean -modcache && rm -r ${TMPGOPATH}\" EXIT\n        GOVIM_REF=$(GOPATH=${TMPGOPATH} go mod download -json \\\n          github.com/govim/govim@latest | jq -r .Version)\n      fi\n      shift 2\n      ;;\n    *)\n      usage\n      exit 1\n  esac\ndone\n\n# Find the tools root, so that this script can be run from any directory.\nscript_dir=$(dirname \"$(readlink -f \"$0\")\")\ntools_dir=$(readlink -f \"${script_dir}/../../..\")\n\n# Build gopls.\ncd \"${tools_dir}/gopls\"\ntemp_gopls=$(mktemp -p \"$PWD\")\ntrap \"rm -f \\\"${temp_gopls}\\\"\" EXIT\n# For consistency across environments, use golang docker to build rather than\n# the local go command.\n${SUDO_IF_NEEDED}docker run --rm -t \\\n  -v \"${tools_dir}:/src/tools\" \\\n  -w \"/src/tools/gopls\" \\\n  golang:rc \\\n  go build -o $(basename ${temp_gopls})\n\n# Build the test harness. Here we are careful to pass in a very limited build\n# context so as to optimize caching.\necho \"Checking out govim@${GOVIM_REF}\"\ncd \"${tools_dir}\"\n${SUDO_IF_NEEDED}docker build \\\n  --build-arg GOVIM_REF=\"${GOVIM_REF}\" \\\n  -t gopls-govim-harness:${GOVIM_REF} \\\n  -f gopls/integration/govim/Dockerfile \\\n  gopls/integration/govim\n\n# Run govim integration tests.\necho \"running govim integration tests using ${temp_gopls}\"\ntemp_gopls_name=$(basename \"${temp_gopls}\")\n${SUDO_IF_NEEDED}docker run --rm -t \\\n  -v \"${tools_dir}:/src/tools\" \\\n  -w \"/src/govim\" \\\n  --ulimit memlock=-1:-1 \\\n  gopls-govim-harness:${GOVIM_REF} \\\n  go test ${TEST_SHORT} ./cmd/govim \\\n    -gopls \"/src/tools/gopls/${temp_gopls_name}\"\n"
  },
  {
    "path": "gopls/integration/govim/run_tests_for_cloudbuild.sh",
    "content": "#!/bin/bash\n\n# Copyright 2020 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\n# This script runs govim integration tests but always succeeds, instead writing\n# their result to a file so that any test failure can be deferred to a later\n# build step. We do this so that we can capture govim test artifacts regardless\n# of the test results.\n\n# Substitute the locally built gopls binary for use in govim integration tests.\ngo test -short ./cmd/govim -gopls /workspace/gopls/gopls\n\n# Stash the error, for use in a later build step.\necho \"exit $?\" > /workspace/govim_test_result.sh\n\n# Clean up unnecessary artifacts. This is based on govim/_scripts/tidyUp.bash.\n# Since we're fetching govim using the go command, we won't have this non-go\n# source directory available to us.\nif [[ -n \"$GOVIM_TESTSCRIPT_WORKDIR_ROOT\" ]]; then\n  echo \"Cleaning up build artifacts...\"\n  # Make artifacts writable so that rm -rf doesn't complain.\n  chmod -R u+w \"$GOVIM_TESTSCRIPT_WORKDIR_ROOT\"\n\n  # Remove directories we don't care about.\n  find \"$GOVIM_TESTSCRIPT_WORKDIR_ROOT\" -type d \\( -name .vim -o -name gopath \\) -prune -exec rm -rf '{}' \\;\nfi\n"
  },
  {
    "path": "gopls/internal/analysis/deprecated/deprecated.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage deprecated\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t_ \"embed\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\tinternalastutil \"golang.org/x/tools/internal/astutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"deprecated\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"deprecated\"),\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRun:              checkDeprecated,\n\tFactTypes:        []analysis.Fact{(*deprecationFact)(nil)},\n\tRunDespiteErrors: true,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/deprecated\",\n}\n\n// checkDeprecated is a simplified copy of staticcheck.CheckDeprecated.\nfunc checkDeprecated(pass *analysis.Pass) (any, error) {\n\tinspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tdeprs, err := collectDeprecatedNames(pass, inspector)\n\tif err != nil || (len(deprs.packages) == 0 && len(deprs.objects) == 0) {\n\t\treturn nil, err\n\t}\n\n\treportDeprecation := func(depr *deprecationFact, node ast.Node) {\n\t\t// TODO(hyangah): staticcheck.CheckDeprecated has more complex logic. Do we need it here?\n\t\t// TODO(hyangah): Scrub depr.Msg. depr.Msg may contain Go comments\n\t\t// markdown syntaxes but LSP diagnostics do not support markdown syntax.\n\n\t\tbuf := new(bytes.Buffer)\n\t\tif err := format.Node(buf, pass.Fset, node); err != nil {\n\t\t\t// This shouldn't happen but let's be conservative.\n\t\t\tbuf.Reset()\n\t\t\tbuf.WriteString(\"declaration\")\n\t\t}\n\t\tpass.ReportRangef(node, \"%s is deprecated: %s\", buf, depr.Msg)\n\t}\n\n\tnodeFilter := []ast.Node{(*ast.SelectorExpr)(nil)}\n\tinspector.Preorder(nodeFilter, func(node ast.Node) {\n\t\t// Caveat: this misses dot-imported objects\n\t\tsel, ok := node.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\n\t\tobj := pass.TypesInfo.ObjectOf(sel.Sel)\n\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\tobj = fn.Origin()\n\t\t}\n\t\tif obj == nil || obj.Pkg() == nil {\n\t\t\t// skip invalid sel.Sel.\n\t\t\treturn\n\t\t}\n\n\t\tif obj.Pkg() == pass.Pkg {\n\t\t\t// A package is allowed to use its own deprecated objects\n\t\t\treturn\n\t\t}\n\n\t\t// A package \"foo\" has two related packages \"foo_test\" and \"foo.test\", for external tests and the package main\n\t\t// generated by 'go test' respectively. \"foo_test\" can import and use \"foo\", \"foo.test\" imports and uses \"foo\"\n\t\t// and \"foo_test\".\n\n\t\tif strings.TrimSuffix(pass.Pkg.Path(), \"_test\") == obj.Pkg().Path() {\n\t\t\t// foo_test (the external tests of foo) can use objects from foo.\n\t\t\treturn\n\t\t}\n\t\tif strings.TrimSuffix(pass.Pkg.Path(), \".test\") == obj.Pkg().Path() {\n\t\t\t// foo.test (the main package of foo's tests) can use objects from foo.\n\t\t\treturn\n\t\t}\n\t\tif strings.TrimSuffix(pass.Pkg.Path(), \".test\") == strings.TrimSuffix(obj.Pkg().Path(), \"_test\") {\n\t\t\t// foo.test (the main package of foo's tests) can use objects from foo's external tests.\n\t\t\treturn\n\t\t}\n\n\t\tif depr, ok := deprs.objects[obj]; ok {\n\t\t\treportDeprecation(depr, sel)\n\t\t}\n\t})\n\n\tfor _, f := range pass.Files {\n\t\tfor _, spec := range f.Imports {\n\t\t\tvar imp *types.Package\n\t\t\tvar obj types.Object\n\t\t\tif spec.Name != nil {\n\t\t\t\tobj = pass.TypesInfo.ObjectOf(spec.Name)\n\t\t\t} else {\n\t\t\t\tobj = pass.TypesInfo.Implicits[spec]\n\t\t\t}\n\t\t\tpkgName, ok := obj.(*types.PkgName)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timp = pkgName.Imported()\n\n\t\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpkgPath := pass.Pkg.Path()\n\t\t\tif strings.TrimSuffix(pkgPath, \"_test\") == path {\n\t\t\t\t// foo_test can import foo\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif strings.TrimSuffix(pkgPath, \".test\") == path {\n\t\t\t\t// foo.test can import foo\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif strings.TrimSuffix(pkgPath, \".test\") == strings.TrimSuffix(path, \"_test\") {\n\t\t\t\t// foo.test can import foo_test\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif depr, ok := deprs.packages[imp]; ok {\n\t\t\t\treportDeprecation(depr, spec.Path)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\ntype deprecationFact struct{ Msg string }\n\nfunc (*deprecationFact) AFact()           {}\nfunc (d *deprecationFact) String() string { return \"Deprecated: \" + d.Msg }\n\ntype deprecatedNames struct {\n\tobjects  map[types.Object]*deprecationFact\n\tpackages map[*types.Package]*deprecationFact\n}\n\n// collectDeprecatedNames collects deprecated identifiers and publishes\n// them both as Facts and the return value. This is a simplified copy\n// of staticcheck's fact_deprecated analyzer.\nfunc collectDeprecatedNames(pass *analysis.Pass, ins *inspector.Inspector) (deprecatedNames, error) {\n\tdoDocs := func(names []*ast.Ident, docs *ast.CommentGroup) {\n\t\talt := strings.TrimPrefix(internalastutil.Deprecation(docs), \"Deprecated: \")\n\t\tif alt == \"\" {\n\t\t\treturn\n\t\t}\n\n\t\tfor _, name := range names {\n\t\t\tobj := pass.TypesInfo.ObjectOf(name)\n\t\t\tpass.ExportObjectFact(obj, &deprecationFact{alt})\n\t\t}\n\t}\n\n\t// Is package deprecated?\n\t//\n\t// Don't mark package syscall as deprecated, even though\n\t// it is. A lot of people still use it for simple\n\t// constants like SIGKILL, and I am not comfortable\n\t// telling them to use x/sys for that.\n\tif pass.Pkg.Path() != \"syscall\" {\n\t\tfor _, f := range pass.Files {\n\t\t\tif depr := internalastutil.Deprecation(f.Doc); depr != \"\" {\n\t\t\t\tpass.ExportPackageFact(&deprecationFact{depr})\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tnodeFilter := []ast.Node{\n\t\t(*ast.GenDecl)(nil),\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.TypeSpec)(nil),\n\t\t(*ast.ValueSpec)(nil),\n\t\t(*ast.File)(nil),\n\t\t(*ast.StructType)(nil),\n\t\t(*ast.InterfaceType)(nil),\n\t}\n\tins.Preorder(nodeFilter, func(node ast.Node) {\n\t\tvar names []*ast.Ident\n\t\tvar docs *ast.CommentGroup\n\t\tswitch node := node.(type) {\n\t\tcase *ast.GenDecl:\n\t\t\tswitch node.Tok {\n\t\t\tcase token.TYPE, token.CONST, token.VAR:\n\t\t\t\tdocs = node.Doc\n\t\t\t\tfor i := range node.Specs {\n\t\t\t\t\tswitch n := node.Specs[i].(type) {\n\t\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t\tnames = append(names, n.Names...)\n\t\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t\tnames = append(names, n.Name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn\n\t\t\t}\n\t\tcase *ast.FuncDecl:\n\t\t\tdocs = node.Doc\n\t\t\tnames = []*ast.Ident{node.Name}\n\t\tcase *ast.TypeSpec:\n\t\t\tdocs = node.Doc\n\t\t\tnames = []*ast.Ident{node.Name}\n\t\tcase *ast.ValueSpec:\n\t\t\tdocs = node.Doc\n\t\t\tnames = node.Names\n\t\tcase *ast.StructType:\n\t\t\tfor _, field := range node.Fields.List {\n\t\t\t\tdoDocs(field.Names, field.Doc)\n\t\t\t}\n\t\tcase *ast.InterfaceType:\n\t\t\tfor _, field := range node.Methods.List {\n\t\t\t\tdoDocs(field.Names, field.Doc)\n\t\t\t}\n\t\t}\n\t\tif docs != nil && len(names) > 0 {\n\t\t\tdoDocs(names, docs)\n\t\t}\n\t})\n\n\t// Every identifier is potentially deprecated, so we will need\n\t// to look up facts a lot. Construct maps of all facts propagated\n\t// to this pass for fast lookup.\n\tout := deprecatedNames{\n\t\tobjects:  map[types.Object]*deprecationFact{},\n\t\tpackages: map[*types.Package]*deprecationFact{},\n\t}\n\tfor _, fact := range pass.AllObjectFacts() {\n\t\tout.objects[fact.Object] = fact.Fact.(*deprecationFact)\n\t}\n\tfor _, fact := range pass.AllPackageFacts() {\n\t\tout.packages[fact.Package] = fact.Fact.(*deprecationFact)\n\t}\n\n\treturn out, nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/deprecated/deprecated_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage deprecated\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/deprecated/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package deprecated defines an Analyzer that marks deprecated symbols and package imports.\n//\n// # Analyzer deprecated\n//\n// deprecated: check for use of deprecated identifiers\n//\n// The deprecated analyzer looks for deprecated symbols and package\n// imports.\n//\n// See https://go.dev/wiki/Deprecated to learn about Go's convention\n// for documenting and signaling deprecated identifiers.\npackage deprecated\n"
  },
  {
    "path": "gopls/internal/analysis/deprecated/testdata/src/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage usedeprecated\n\nimport \"io/ioutil\" // want \"\\\"io/ioutil\\\" is deprecated: .*\"\n\nfunc x() {\n\t_, _ = ioutil.ReadFile(\"\") // want \"ioutil.ReadFile is deprecated: As of Go 1.16, .*\"\n\tLegacy()                   // expect no deprecation notice.\n}\n\n// Legacy is deprecated.\n//\n// Deprecated: use X instead.\nfunc Legacy() {} // want Legacy:\"Deprecated: use X instead.\"\n"
  },
  {
    "path": "gopls/internal/analysis/deprecated/testdata/src/a/a_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage usedeprecated\n\nimport \"testing\"\n\nfunc TestF(t *testing.T) {\n\tLegacy() // expect no deprecation notice.\n\tx()\n}\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package embeddirective defines an Analyzer that validates //go:embed directives.\n// The analyzer defers fixes to its parent golang.Analyzer.\n//\n// # Analyzer embed\n//\n// embed: check //go:embed directive usage\n//\n// This analyzer checks that the embed package is imported if //go:embed\n// directives are present, providing a suggested fix to add the import if\n// it is missing.\n//\n// This analyzer also checks that //go:embed directives precede the\n// declaration of a single variable.\npackage embeddirective\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/embeddirective.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage embeddirective\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/refactor\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"embed\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"embed\"),\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/embeddirective\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tfor _, f := range pass.Files {\n\t\tcomments := embedDirectiveComments(f)\n\t\tif len(comments) == 0 {\n\t\t\tcontinue // nothing to check\n\t\t}\n\n\t\thasEmbedImport := false\n\t\tfor _, imp := range f.Imports {\n\t\t\tif imp.Path.Value == `\"embed\"` {\n\t\t\t\thasEmbedImport = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor _, c := range comments {\n\t\t\tpos, end := c.Pos(), c.Pos()+token.Pos(len(\"//go:embed\"))\n\n\t\t\tif !hasEmbedImport {\n\t\t\t\t// Add blank import of \"embed\".\n\t\t\t\t_, edits := refactor.AddImport(pass.TypesInfo, f, \"_\", \"embed\", \"\", c.Pos())\n\t\t\t\tif len(edits) > 0 {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     pos,\n\t\t\t\t\t\tEnd:     end,\n\t\t\t\t\t\tMessage: `must import \"embed\" when using go:embed directives`,\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\tMessage:   `Add missing \"embed\" import`,\n\t\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t\t}},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar msg string\n\t\t\tspec := nextVarSpec(c, f)\n\t\t\tswitch {\n\t\t\tcase spec == nil:\n\t\t\t\tmsg = `go:embed directives must precede a \"var\" declaration`\n\t\t\tcase len(spec.Names) != 1:\n\t\t\t\tmsg = \"declarations following go:embed directives must define a single variable\"\n\t\t\tcase len(spec.Values) > 0:\n\t\t\t\tmsg = \"declarations following go:embed directives must not specify a value\"\n\t\t\tcase !embeddableType(pass.TypesInfo.Defs[spec.Names[0]]):\n\t\t\t\tmsg = \"declarations following go:embed directives must be of type string, []byte or embed.FS\"\n\t\t\t}\n\t\t\tif msg != \"\" {\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\tPos:     pos,\n\t\t\t\t\tEnd:     end,\n\t\t\t\t\tMessage: msg,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// embedDirectiveComments returns all comments in f that contains a //go:embed directive.\nfunc embedDirectiveComments(f *ast.File) []*ast.Comment {\n\tcomments := []*ast.Comment{}\n\tfor _, cg := range f.Comments {\n\t\tfor _, c := range cg.List {\n\t\t\tif strings.HasPrefix(c.Text, \"//go:embed \") {\n\t\t\t\tcomments = append(comments, c)\n\t\t\t}\n\t\t}\n\t}\n\treturn comments\n}\n\n// nextVarSpec returns the ValueSpec for the variable declaration immediately following\n// the go:embed comment, or nil if the next declaration is not a variable declaration.\nfunc nextVarSpec(com *ast.Comment, f *ast.File) *ast.ValueSpec {\n\t// Embed directives must be followed by a declaration of one variable with no value.\n\t// There may be comments and empty lines between the directive and the declaration.\n\tvar nextDecl ast.Decl\n\tfor _, d := range f.Decls {\n\t\tif com.End() < d.End() {\n\t\t\tnextDecl = d\n\t\t\tbreak\n\t\t}\n\t}\n\tif nextDecl == nil || nextDecl.Pos() == token.NoPos {\n\t\treturn nil\n\t}\n\tdecl, ok := nextDecl.(*ast.GenDecl)\n\tif !ok {\n\t\treturn nil\n\t}\n\tif decl.Tok != token.VAR {\n\t\treturn nil\n\t}\n\n\t// var declarations can be both freestanding and blocks (with parenthesis).\n\t// Only the first variable spec following the directive is interesting.\n\tvar nextSpec ast.Spec\n\tfor _, s := range decl.Specs {\n\t\tif com.End() < s.End() {\n\t\t\tnextSpec = s\n\t\t\tbreak\n\t\t}\n\t}\n\tif nextSpec == nil {\n\t\treturn nil\n\t}\n\tspec, ok := nextSpec.(*ast.ValueSpec)\n\tif !ok {\n\t\t// Invalid AST, but keep going.\n\t\treturn nil\n\t}\n\treturn spec\n}\n\n// embeddableType in go:embed directives are string, []byte or embed.FS.\nfunc embeddableType(o types.Object) bool {\n\tif o == nil {\n\t\treturn false\n\t}\n\n\t// For embed.FS the underlying type is an implementation detail.\n\t// As long as the named type resolves to embed.FS, it is OK.\n\tif named, ok := types.Unalias(o.Type()).(*types.Named); ok {\n\t\tobj := named.Obj()\n\t\tif obj.Pkg() != nil && obj.Pkg().Path() == \"embed\" && obj.Name() == \"FS\" {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tswitch v := o.Type().Underlying().(type) {\n\tcase *types.Basic:\n\t\treturn types.Identical(v, types.Typ[types.String])\n\tcase *types.Slice:\n\t\treturn types.Identical(v.Elem(), types.Typ[types.Byte])\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/embeddirective_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage embeddirective\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/testdata/src/a/embedText",
    "content": "Hello World"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/testdata/src/a/import_missing.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"fmt\"\n)\n\n//go:embed embedtext // want \"must import \\\"embed\\\" when using go:embed directives\"\nvar s string\n\n// This is main function\nfunc main() {\n\tfmt.Println(s)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/testdata/src/a/import_missing.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n)\n\n//go:embed embedtext // want \"must import \\\"embed\\\" when using go:embed directives\"\nvar s string\n\n// This is main function\nfunc main() {\n\tfmt.Println(s)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/testdata/src/a/import_present.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\n// Misplaced, above imports.\n//go:embed embedText // want \"go:embed directives must precede a \\\"var\\\" declaration\"\n\nimport (\n\t\"embed\"\n\tembedPkg \"embed\"\n\t\"fmt\"\n\n\t_ \"embed\"\n)\n\n//go:embed embedText // ok\nvar e1 string\n\n// The analyzer does not check for many directives using the same var.\n//\n//go:embed embedText // ok\n//go:embed embedText // ok\nvar e2 string\n\n// Comments and blank lines between are OK. All types OK.\n//\n//go:embed embedText // ok\n//\n// foo\n\nvar e3 string\n\n//go:embed embedText //ok\nvar e4 []byte\n\n//go:embed embedText //ok\nvar e5 embed.FS\n\n// Followed by wrong kind of decl.\n//\n//go:embed embedText // want \"go:embed directives must precede a \\\"var\\\" declaration\"\nfunc fooFunc() {}\n\n// Multiple variable specs.\n//\n//go:embed embedText // want \"declarations following go:embed directives must define a single variable\"\nvar e6, e7 []byte\n\n// Specifying a value is not allowed.\n//\n//go:embed embedText // want \"declarations following go:embed directives must not specify a value\"\nvar e8 string = \"foo\"\n\n// TODO: This should not be OK, misplaced according to compiler.\n//\n//go:embed embedText // ok\nvar (\n\te9  string\n\te10 string\n)\n\n// Type definition.\ntype fooType []byte\n\n//go:embed embedText //ok\nvar e11 fooType\n\n// Type alias.\ntype barType = string\n\n//go:embed embedText //ok\nvar e12 barType\n\n// Renamed embed package.\n\n//go:embed embedText //ok\nvar e13 embedPkg.FS\n\n// Renamed embed package alias.\ntype embedAlias = embedPkg.FS\n\n//go:embed embedText //ok\nvar e14 embedAlias\n\n// var blocks are OK as long as the variable following the directive is OK.\nvar (\n\tx, y, z string\n\t//go:embed embedText // ok\n\te20     string\n\tq, r, t string\n)\n\n//go:embed embedText // want \"go:embed directives must precede a \\\"var\\\" declaration\"\nvar ()\n\n// Incorrect types.\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e16 byte\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e17 []string\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e18 embed.Foo\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e19 foo.FS\n\ntype byteAlias byte\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e15 byteAlias\n\n// A type declaration of embed.FS is not accepted by the compiler, in contrast to an alias.\ntype embedDecl embed.FS\n\n//go:embed embedText // want `declarations following go:embed directives must be of type string, \\[\\]byte or embed.FS`\nvar e16 embedDecl\n\n// This is main function\nfunc main() {\n\tfmt.Println(s)\n}\n\n// No declaration following.\n//go:embed embedText // want \"go:embed directives must precede a \\\"var\\\" declaration\"\n"
  },
  {
    "path": "gopls/internal/analysis/embeddirective/testdata/src/a/import_present_go120.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.20\n// +build go1.20\n\npackage a\n\nvar (\n\t// Okay directive wise but the compiler will complain that\n\t// imports must appear before other declarations.\n\t//go:embed embedText // ok\n\tfoo string\n)\n\nimport (\n\t\"fmt\"\n\n\t_ \"embed\"\n)\n\n// This is main function\nfunc main() {\n\tfmt.Println(s)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fillreturns defines an Analyzer that will attempt to\n// automatically fill in a return statement that has missing\n// values with zero value elements.\n//\n// # Analyzer fillreturns\n//\n// fillreturns: suggest fixes for errors due to an incorrect number of return values\n//\n// This checker provides suggested fixes for type errors of the\n// type \"wrong number of return values (want %d, got %d)\". For example:\n//\n//\tfunc m() (int, string, *bool, error) {\n//\t\treturn\n//\t}\n//\n// will turn into\n//\n//\tfunc m() (int, string, *bool, error) {\n//\t\treturn 0, \"\", nil, nil\n//\t}\n//\n// This functionality is similar to https://github.com/sqs/goreturns.\npackage fillreturns\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/fillreturns.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillreturns\n\nimport (\n\t\"bytes\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"fillreturns\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"fillreturns\"),\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tinfo := pass.TypesInfo\n\nouter:\n\tfor _, typeErr := range pass.TypeErrors {\n\t\tif !fixesError(typeErr) {\n\t\t\tcontinue // irrelevant type error\n\t\t}\n\t\t_, start, end, ok := typesinternal.ErrorCodeStartEnd(typeErr)\n\t\tif !ok {\n\t\t\tcontinue // no position information\n\t\t}\n\t\tcurErr, ok := inspect.Root().FindByPos(start, end)\n\t\tif !ok {\n\t\t\tcontinue // can't find node\n\t\t}\n\n\t\t// Find cursor for enclosing return statement (which may be curErr itself).\n\t\tret, curRet := cursorutil.FirstEnclosing[*ast.ReturnStmt](curErr)\n\t\tif ret == nil {\n\t\t\tcontinue // no enclosing return\n\t\t}\n\n\t\t// Skip if any return argument is a tuple-valued function call.\n\t\tfor _, expr := range ret.Results {\n\t\t\te, ok := expr.(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif tup, ok := info.TypeOf(e).(*types.Tuple); ok && tup.Len() > 1 {\n\t\t\t\tcontinue outer\n\t\t\t}\n\t\t}\n\n\t\t// Get type of innermost enclosing function.\n\t\tvar funcType *ast.FuncType\n\t\tcurFunc, _ := enclosingFunc(curRet) // can't fail\n\t\tswitch fn := curFunc.Node().(type) {\n\t\tcase *ast.FuncLit:\n\t\t\tfuncType = fn.Type\n\t\tcase *ast.FuncDecl:\n\t\t\tfuncType = fn.Type\n\n\t\t\t// Skip generic functions since type parameters don't have zero values.\n\t\t\t// TODO(rfindley): We should be able to handle this if the return\n\t\t\t// values are all concrete types.\n\t\t\tif funcType.TypeParams.NumFields() > 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif funcType.Results == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Duplicate the return values to track which values have been matched.\n\t\tremaining := make([]ast.Expr, len(ret.Results))\n\t\tcopy(remaining, ret.Results)\n\n\t\tfixed := make([]ast.Expr, len(funcType.Results.List))\n\n\t\t// For each value in the return function declaration, find the leftmost element\n\t\t// in the return statement that has the desired type. If no such element exists,\n\t\t// fill in the missing value with the appropriate \"zero\" value.\n\t\t// Beware that type information may be incomplete.\n\t\tvar retTyps []types.Type\n\t\tfor _, ret := range funcType.Results.List {\n\t\t\tretTyp := info.TypeOf(ret.Type)\n\t\t\tif retTyp == nil {\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tretTyps = append(retTyps, retTyp)\n\t\t}\n\n\t\tfile, _ := cursorutil.FirstEnclosing[*ast.File](curRet)\n\t\tmatches := MatchingIdents(retTyps, file, ret.Pos(), info, pass.Pkg)\n\t\tqual := typesinternal.FileQualifier(file, pass.Pkg)\n\t\tfor i, retTyp := range retTyps {\n\t\t\tvar match ast.Expr\n\t\t\tvar idx int\n\t\t\tfor j, val := range remaining {\n\t\t\t\tif t := info.TypeOf(val); t == nil || !matchingTypes(t, retTyp) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif !isZeroExpr(val) {\n\t\t\t\t\tmatch, idx = val, j\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// If the current match is a \"zero\" value, we keep searching in\n\t\t\t\t// case we find a non-\"zero\" value match. If we do not find a\n\t\t\t\t// non-\"zero\" value, we will use the \"zero\" value.\n\t\t\t\tmatch, idx = val, j\n\t\t\t}\n\n\t\t\tif match != nil {\n\t\t\t\tfixed[i] = match\n\t\t\t\tremaining = slices.Delete(remaining, idx, idx+1)\n\t\t\t} else {\n\t\t\t\tnames, ok := matches[retTyp]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"invalid return type: %v\", retTyp)\n\t\t\t\t}\n\t\t\t\t// Find the identifier most similar to the return type.\n\t\t\t\t// If no identifier matches the pattern, generate a zero value.\n\t\t\t\tif best := fuzzy.BestMatch(retTyp.String(), names); best != \"\" {\n\t\t\t\t\tfixed[i] = ast.NewIdent(best)\n\t\t\t\t} else if zero, isValid := typesinternal.ZeroExpr(retTyp, qual); isValid {\n\t\t\t\t\tfixed[i] = zero\n\t\t\t\t} else {\n\t\t\t\t\treturn nil, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove any non-matching \"zero values\" from the leftover values.\n\t\tvar nonZeroRemaining []ast.Expr\n\t\tfor _, expr := range remaining {\n\t\t\tif !isZeroExpr(expr) {\n\t\t\t\tnonZeroRemaining = append(nonZeroRemaining, expr)\n\t\t\t}\n\t\t}\n\t\t// Append leftover return values to end of new return statement.\n\t\tfixed = append(fixed, nonZeroRemaining...)\n\n\t\tnewRet := &ast.ReturnStmt{\n\t\t\tReturn:  ret.Pos(),\n\t\t\tResults: fixed,\n\t\t}\n\n\t\t// Convert the new return statement AST to text.\n\t\tvar newBuf bytes.Buffer\n\t\tif err := format.Node(&newBuf, pass.Fset, newRet); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     start,\n\t\t\tEnd:     end,\n\t\t\tMessage: typeErr.Msg,\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Fill in return values\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     ret.Pos(),\n\t\t\t\t\tEnd:     ret.End(),\n\t\t\t\t\tNewText: newBuf.Bytes(),\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil, nil\n}\n\nfunc matchingTypes(want, got types.Type) bool {\n\tif want == got || types.Identical(want, got) {\n\t\treturn true\n\t}\n\t// Code segment to help check for untyped equality from (golang/go#32146).\n\tif rhs, ok := want.(*types.Basic); ok && rhs.Info()&types.IsUntyped > 0 {\n\t\tif lhs, ok := got.Underlying().(*types.Basic); ok {\n\t\t\treturn rhs.Info()&types.IsConstType == lhs.Info()&types.IsConstType\n\t\t}\n\t}\n\treturn types.AssignableTo(want, got) || types.ConvertibleTo(want, got)\n}\n\n// Error messages have changed across Go versions. These regexps capture recent\n// incarnations.\n//\n// TODO(rfindley): once error codes are exported and exposed via go/packages,\n// use error codes rather than string matching here.\nvar wrongReturnNumRegexes = []*regexp.Regexp{\n\tregexp.MustCompile(`wrong number of return values \\(want (\\d+), got (\\d+)\\)`),\n\tregexp.MustCompile(`too many return values`),\n\tregexp.MustCompile(`not enough return values`),\n}\n\nfunc fixesError(err types.Error) bool {\n\tmsg := strings.TrimSpace(err.Msg)\n\tfor _, rx := range wrongReturnNumRegexes {\n\t\tif rx.MatchString(msg) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// enclosingFunc returns the cursor for the innermost Func{Decl,Lit}\n// that encloses c, if any.\nfunc enclosingFunc(c inspector.Cursor) (inspector.Cursor, bool) {\n\treturn moreiters.First(c.Enclosing((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)))\n}\n\n// isZeroExpr uses simple syntactic heuristics to report whether expr\n// is a obvious zero value, such as 0, \"\", nil, or false.\n// It cannot do better without type information.\nfunc isZeroExpr(expr ast.Expr) bool {\n\tswitch e := expr.(type) {\n\tcase *ast.BasicLit:\n\t\treturn e.Value == \"0\" || e.Value == `\"\"`\n\tcase *ast.Ident:\n\t\treturn e.Name == \"nil\" || e.Name == \"false\"\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// MatchingIdents finds the names of all identifiers in 'node' that match any of the given types.\n// 'pos' represents the position at which the identifiers may be inserted. 'pos' must be within\n// the scope of each of identifier we select. Otherwise, we will insert a variable at 'pos' that\n// is unrecognized.\n//\n// This function is shared with the 'fillstruct' analyzer.\nfunc MatchingIdents(typs []types.Type, node ast.Node, pos token.Pos, info *types.Info, pkg *types.Package) map[types.Type][]string {\n\n\t// Initialize matches to contain the variable types we are searching for.\n\tmatches := make(map[types.Type][]string)\n\tfor _, typ := range typs {\n\t\tif typ == nil {\n\t\t\tcontinue // TODO(adonovan): is this reachable?\n\t\t}\n\t\tmatches[typ] = nil // create entry\n\t}\n\n\tseen := map[types.Object]struct{}{}\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\t// Prevent circular definitions. If 'pos' is within an assignment statement, do not\n\t\t// allow any identifiers in that assignment statement to be selected. Otherwise,\n\t\t// we could do the following, where 'x' satisfies the type of 'f0':\n\t\t//\n\t\t// x := fakeStruct{f0: x}\n\t\t//\n\t\tif assign, ok := n.(*ast.AssignStmt); ok && pos > assign.Pos() && pos <= assign.End() {\n\t\t\treturn false\n\t\t}\n\t\tif n.End() > pos {\n\t\t\treturn n.Pos() <= pos\n\t\t}\n\t\tident, ok := n.(*ast.Ident)\n\t\tif !ok || ident.Name == \"_\" {\n\t\t\treturn true\n\t\t}\n\t\tobj := info.Defs[ident]\n\t\tif obj == nil || obj.Type() == nil {\n\t\t\treturn true\n\t\t}\n\t\tif _, ok := obj.(*types.TypeName); ok {\n\t\t\treturn true\n\t\t}\n\t\t// Prevent duplicates in matches' values.\n\t\tif _, ok = seen[obj]; ok {\n\t\t\treturn true\n\t\t}\n\t\tseen[obj] = struct{}{}\n\t\t// Find the scope for the given position. Then, check whether the object\n\t\t// exists within the scope.\n\t\tinnerScope := pkg.Scope().Innermost(pos)\n\t\tif innerScope == nil {\n\t\t\treturn true\n\t\t}\n\t\t_, foundObj := innerScope.LookupParent(ident.Name, pos)\n\t\tif foundObj != obj {\n\t\t\treturn true\n\t\t}\n\t\t// The object must match one of the types that we are searching for.\n\t\t// TODO(adonovan): opt: use typeutil.Map?\n\t\tif names, ok := matches[obj.Type()]; ok {\n\t\t\tmatches[obj.Type()] = append(names, ident.Name)\n\t\t} else {\n\t\t\t// If the object type does not exactly match\n\t\t\t// any of the target types, greedily find the first\n\t\t\t// target type that the object type can satisfy.\n\t\t\tfor typ := range matches {\n\t\t\t\tif equivalentTypes(obj.Type(), typ) {\n\t\t\t\t\tmatches[typ] = append(matches[typ], ident.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\treturn matches\n}\n\nfunc equivalentTypes(want, got types.Type) bool {\n\tif types.Identical(want, got) {\n\t\treturn true\n\t}\n\t// Code segment to help check for untyped equality from (golang/go#32146).\n\tif rhs, ok := want.(*types.Basic); ok && rhs.Info()&types.IsUntyped > 0 {\n\t\tif lhs, ok := got.Underlying().(*types.Basic); ok {\n\t\t\treturn rhs.Info()&types.IsConstType == lhs.Info()&types.IsConstType\n\t\t}\n\t}\n\treturn types.AssignableTo(want, got)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/fillreturns_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillreturns_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillreturns\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, fillreturns.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillreturns\n\nimport (\n\t\"errors\"\n\t\"go/ast\"\n\tast2 \"go/ast\"\n\t\"io\"\n\t\"net/http\"\n\t. \"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n)\n\ntype T struct{}\ntype T1 = T\ntype I interface{}\ntype I1 = I\ntype z func(string, http.Handler) error\n\nfunc x() error {\n\treturn errors.New(\"foo\")\n}\n\n// The error messages below changed in 1.18; \"return values\" covers both forms.\n\nfunc b() (string, int, error) {\n\treturn \"\", errors.New(\"foo\") // want \"return values\"\n}\n\nfunc c() (string, int, error) {\n\treturn 7, errors.New(\"foo\") // want \"return values\"\n}\n\nfunc d() (string, int, error) {\n\treturn \"\", 7 // want \"return values\"\n}\n\nfunc e() (T, error, *bool) {\n\treturn (z(http.ListenAndServe))(\"\", nil) // want \"return values\"\n}\n\nfunc preserveLeft() (int, int, error) {\n\treturn 1, errors.New(\"foo\") // want \"return values\"\n}\n\nfunc matchValues() (int, error, string) {\n\treturn errors.New(\"foo\"), 3 // want \"return values\"\n}\n\nfunc preventDataOverwrite() (int, string) {\n\treturn errors.New(\"foo\") // want \"return values\"\n}\n\nfunc closure() (string, error) {\n\t_ = func() (int, error) {\n\t\treturn // want \"return values\"\n\t}\n\treturn // want \"return values\"\n}\n\nfunc basic() (uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64, complex64, complex128, byte, rune, uint, int, uintptr, string, bool, error) {\n\treturn // want \"return values\"\n}\n\nfunc complex() (*int, []int, [2]int, map[int]int) {\n\treturn // want \"return values\"\n}\n\nfunc structsAndInterfaces() (T, url.URL, T1, I, I1, io.Reader, Client, ast2.Stmt) {\n\treturn // want \"return values\"\n}\n\nfunc m() (int, error) {\n\tif 1 == 2 {\n\t\treturn // want \"return values\"\n\t} else if 1 == 3 {\n\t\treturn errors.New(\"foo\") // want \"return values\"\n\t} else {\n\t\treturn 1 // want \"return values\"\n\t}\n\treturn // want \"return values\"\n}\n\nfunc convertibleTypes() (ast2.Expr, int) {\n\treturn &ast2.ArrayType{} // want \"return values\"\n}\n\nfunc assignableTypes() (map[string]int, int) {\n\ttype X map[string]int\n\tvar x X\n\treturn x // want \"return values\"\n}\n\nfunc interfaceAndError() (I, int) {\n\treturn errors.New(\"foo\") // want \"return values\"\n}\n\nfunc funcOneReturn() (string, error) {\n\treturn strconv.Itoa(1) // want \"return values\"\n}\n\nfunc funcMultipleReturn() (int, error, string) {\n\treturn strconv.Atoi(\"1\")\n}\n\nfunc localFuncMultipleReturn() (string, int, error, string) {\n\treturn b()\n}\n\nfunc multipleUnused() (int, string, string, string) {\n\treturn 3, 4, 5 // want \"return values\"\n}\n\nfunc gotTooMany() int {\n\tif true {\n\t\treturn 0, \"\" // want \"return values\"\n\t} else {\n\t\treturn 1, 0, nil // want \"return values\"\n\t}\n\treturn 0, 5, false // want \"return values\"\n}\n\nfunc fillVars() (int, string, ast.Node, bool, error) {\n\teint := 0\n\ts := \"a\"\n\tvar t bool\n\tif true {\n\t\terr := errors.New(\"fail\")\n\t\treturn // want \"return values\"\n\t}\n\tn := ast.NewIdent(\"ident\")\n\tint := 3\n\tvar b bool\n\treturn \"\" // want \"return values\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillreturns\n\nimport (\n\t\"errors\"\n\t\"go/ast\"\n\tast2 \"go/ast\"\n\t\"io\"\n\t\"net/http\"\n\t. \"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n)\n\ntype T struct{}\ntype T1 = T\ntype I interface{}\ntype I1 = I\ntype z func(string, http.Handler) error\n\nfunc x() error {\n\treturn errors.New(\"foo\")\n}\n\n// The error messages below changed in 1.18; \"return values\" covers both forms.\n\nfunc b() (string, int, error) {\n\treturn \"\", 0, errors.New(\"foo\") // want \"return values\"\n}\n\nfunc c() (string, int, error) {\n\treturn \"\", 7, errors.New(\"foo\") // want \"return values\"\n}\n\nfunc d() (string, int, error) {\n\treturn \"\", 7, nil // want \"return values\"\n}\n\nfunc e() (T, error, *bool) {\n\treturn T{}, (z(http.ListenAndServe))(\"\", nil), nil // want \"return values\"\n}\n\nfunc preserveLeft() (int, int, error) {\n\treturn 1, 0, errors.New(\"foo\") // want \"return values\"\n}\n\nfunc matchValues() (int, error, string) {\n\treturn 3, errors.New(\"foo\"), \"\" // want \"return values\"\n}\n\nfunc preventDataOverwrite() (int, string) {\n\treturn 0, \"\", errors.New(\"foo\") // want \"return values\"\n}\n\nfunc closure() (string, error) {\n\t_ = func() (int, error) {\n\t\treturn 0, nil // want \"return values\"\n\t}\n\treturn \"\", nil // want \"return values\"\n}\n\nfunc basic() (uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64, complex64, complex128, byte, rune, uint, int, uintptr, string, bool, error) {\n\treturn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \"\", false, nil // want \"return values\"\n}\n\nfunc complex() (*int, []int, [2]int, map[int]int) {\n\treturn nil, nil, [2]int{}, nil // want \"return values\"\n}\n\nfunc structsAndInterfaces() (T, url.URL, T1, I, I1, io.Reader, Client, ast2.Stmt) {\n\treturn T{}, url.URL{}, T1{}, nil, nil, nil, Client{}, nil // want \"return values\"\n}\n\nfunc m() (int, error) {\n\tif 1 == 2 {\n\t\treturn 0, nil // want \"return values\"\n\t} else if 1 == 3 {\n\t\treturn 0, errors.New(\"foo\") // want \"return values\"\n\t} else {\n\t\treturn 1, nil // want \"return values\"\n\t}\n\treturn 0, nil // want \"return values\"\n}\n\nfunc convertibleTypes() (ast2.Expr, int) {\n\treturn &ast2.ArrayType{}, 0 // want \"return values\"\n}\n\nfunc assignableTypes() (map[string]int, int) {\n\ttype X map[string]int\n\tvar x X\n\treturn x, 0 // want \"return values\"\n}\n\nfunc interfaceAndError() (I, int) {\n\treturn errors.New(\"foo\"), 0 // want \"return values\"\n}\n\nfunc funcOneReturn() (string, error) {\n\treturn strconv.Itoa(1), nil // want \"return values\"\n}\n\nfunc funcMultipleReturn() (int, error, string) {\n\treturn strconv.Atoi(\"1\")\n}\n\nfunc localFuncMultipleReturn() (string, int, error, string) {\n\treturn b()\n}\n\nfunc multipleUnused() (int, string, string, string) {\n\treturn 3, \"\", \"\", \"\", 4, 5 // want \"return values\"\n}\n\nfunc gotTooMany() int {\n\tif true {\n\t\treturn 0 // want \"return values\"\n\t} else {\n\t\treturn 1 // want \"return values\"\n\t}\n\treturn 5 // want \"return values\"\n}\n\nfunc fillVars() (int, string, ast.Node, bool, error) {\n\teint := 0\n\ts := \"a\"\n\tvar t bool\n\tif true {\n\t\terr := errors.New(\"fail\")\n\t\treturn eint, s, nil, false, err // want \"return values\"\n\t}\n\tn := ast.NewIdent(\"ident\")\n\tint := 3\n\tvar b bool\n\treturn int, \"\", n, b, nil // want \"return values\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/testdata/src/typeparams/a.go",
    "content": "package fillreturns\n\nfunc hello[T any]() int {\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillreturns/testdata/src/typeparams/a.go.golden",
    "content": "package fillreturns\n\nfunc hello[T any]() int {\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillstruct/fillstruct.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fillstruct defines an Analyzer that automatically\n// fills in a struct declaration with zero value elements for each field.\n//\n// The analyzer's diagnostic is merely a prompt.\n// The actual fix is created by a separate direct call from gopls to\n// the SuggestedFixes function.\n// Tests of Analyzer.Run can be found in ./testdata/src.\n// Tests of the SuggestedFixes logic live in ../../testdata/fillstruct.\npackage fillstruct\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillreturns\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// Diagnose computes diagnostics for fillable struct literals overlapping with\n// the provided start and end position of file f.\n//\n// The diagnostic contains a lazy fix; the actual patch is computed\n// (via the ApplyFix command) by a call to [SuggestedFix].\n//\n// If either start or end is invalid, the entire file is inspected.\nfunc Diagnose(f *ast.File, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {\n\tvar diags []analysis.Diagnostic\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn true // pop\n\t\t}\n\t\tif start.IsValid() && n.End() < start || end.IsValid() && n.Pos() > end {\n\t\t\treturn false // skip non-overlapping subtree\n\t\t}\n\t\texpr, ok := n.(*ast.CompositeLit)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\ttyp := info.TypeOf(expr)\n\t\tif typ == nil {\n\t\t\treturn true\n\t\t}\n\n\t\t// Find reference to the type declaration of the struct being initialized.\n\t\ttyp = typeparams.Deref(typ)\n\t\ttStruct, ok := typeparams.CoreType(typ).(*types.Struct)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\t// Inv: typ is the possibly-named struct type.\n\n\t\tfieldCount := tStruct.NumFields()\n\n\t\t// Skip any struct that is already populated or that has no fields.\n\t\tif fieldCount == 0 || fieldCount == len(expr.Elts) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Are any fields in need of filling?\n\t\tvar fillableFields []string\n\t\tfor i := range fieldCount {\n\t\t\tfield := tStruct.Field(i)\n\t\t\t// Ignore fields that are not accessible in the current package.\n\t\t\tif field.Pkg() != nil && field.Pkg() != pkg && !field.Exported() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfillableFields = append(fillableFields, fmt.Sprintf(\"%s: %s\", field.Name(), field.Type().String()))\n\t\t}\n\t\tif len(fillableFields) == 0 {\n\t\t\treturn true\n\t\t}\n\n\t\t// Derive a name for the struct type.\n\t\tvar name string\n\t\tif typ != tStruct {\n\t\t\t// named struct type (e.g. pkg.S[T])\n\t\t\tname = types.TypeString(typ, typesinternal.NameRelativeTo(pkg))\n\t\t} else {\n\t\t\t// anonymous struct type\n\t\t\ttotalFields := len(fillableFields)\n\t\t\tconst maxLen = 20\n\t\t\t// Find the index to cut off printing of fields.\n\t\t\tvar i, fieldLen int\n\t\t\tfor i = range fillableFields {\n\t\t\t\tif fieldLen > maxLen {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tfieldLen += len(fillableFields[i])\n\t\t\t}\n\t\t\tfillableFields = fillableFields[:i]\n\t\t\tif i < totalFields {\n\t\t\t\tfillableFields = append(fillableFields, \"...\")\n\t\t\t}\n\t\t\tname = fmt.Sprintf(\"anonymous struct{ %s }\", strings.Join(fillableFields, \", \"))\n\t\t}\n\t\tdiags = append(diags, analysis.Diagnostic{\n\t\t\tMessage:  fmt.Sprintf(\"%s literal has missing fields\", name),\n\t\t\tPos:      expr.Pos(),\n\t\t\tEnd:      expr.End(),\n\t\t\tCategory: FixCategory,\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: fmt.Sprintf(\"Fill %s\", name),\n\t\t\t\t// No TextEdits => computed later by gopls.\n\t\t\t}},\n\t\t})\n\t\treturn true\n\t})\n\n\treturn diags\n}\n\nconst FixCategory = \"fillstruct\" // recognized by gopls ApplyFix\n\n// SuggestedFix computes the suggested fix for the kinds of\n// diagnostics produced by the Analyzer above.\nfunc SuggestedFix(cpkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tvar (\n\t\tfile = pgf.File\n\t\tfset = cpkg.FileSet()\n\t\tpkg  = cpkg.Types()\n\t\tinfo = cpkg.TypesInfo()\n\t\tpos  = start // don't use end\n\t)\n\tcur, ok := pgf.Cursor().FindByPos(pos, pos)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"no enclosing ast.Node\")\n\t}\n\texpr, _ := cursorutil.FirstEnclosing[*ast.CompositeLit](cur)\n\ttyp := info.TypeOf(expr)\n\tif typ == nil {\n\t\treturn nil, nil, fmt.Errorf(\"no composite literal\")\n\t}\n\n\t// Find reference to the type declaration of the struct being initialized.\n\ttyp = typeparams.Deref(typ)\n\ttStruct, ok := typ.Underlying().(*types.Struct)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"%s is not a (pointer to) struct type\",\n\t\t\ttypes.TypeString(typ, typesinternal.NameRelativeTo(pkg)))\n\t}\n\t// Inv: typ is the possibly-named struct type.\n\n\tfieldCount := tStruct.NumFields()\n\n\t// Check which types have already been filled in. (we only want to fill in\n\t// the unfilled types, or else we'll blat user-supplied details)\n\tprefilledFields := map[string]ast.Expr{}\n\tvar elts []ast.Expr\n\tfor _, e := range expr.Elts {\n\t\tif kv, ok := e.(*ast.KeyValueExpr); ok {\n\t\t\tif key, ok := kv.Key.(*ast.Ident); ok {\n\t\t\t\tprefilledFields[key.Name] = kv.Value\n\t\t\t\telts = append(elts, kv)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar fieldTyps []types.Type\n\tfor i := range fieldCount {\n\t\tfield := tStruct.Field(i)\n\t\t// Ignore fields that are not accessible in the current package.\n\t\tif field.Pkg() != nil && field.Pkg() != pkg && !field.Exported() {\n\t\t\tfieldTyps = append(fieldTyps, nil)\n\t\t\tcontinue\n\t\t}\n\t\tfieldTyps = append(fieldTyps, field.Type())\n\t}\n\tmatches := fillreturns.MatchingIdents(fieldTyps, file, start, info, pkg)\n\tqual := typesinternal.FileQualifier(file, pkg)\n\n\tfor i, fieldTyp := range fieldTyps {\n\t\tif fieldTyp == nil {\n\t\t\tcontinue // TODO(adonovan): is this reachable?\n\t\t}\n\t\tfieldName := tStruct.Field(i).Name()\n\t\tif _, ok := prefilledFields[fieldName]; ok {\n\t\t\t// We already stored these when looping over expr.Elt.\n\t\t\t// Want to preserve the original order of prefilled fields\n\t\t\tcontinue\n\t\t}\n\n\t\tkv := &ast.KeyValueExpr{\n\t\t\tKey: &ast.Ident{\n\t\t\t\tName: fieldName,\n\t\t\t},\n\t\t}\n\n\t\tnames, ok := matches[fieldTyp]\n\t\tif !ok {\n\t\t\treturn nil, nil, fmt.Errorf(\"invalid struct field type: %v\", fieldTyp)\n\t\t}\n\n\t\t// Find the name most similar to the field name.\n\t\t// If no name matches the pattern, generate a zero value.\n\t\t// NOTE: We currently match on the name of the field key rather than the field type.\n\t\tif best := fuzzy.BestMatch(fieldName, names); best != \"\" {\n\t\t\tkv.Value = ast.NewIdent(best)\n\t\t} else if expr, isValid := populateValue(fieldTyp, qual); isValid {\n\t\t\tkv.Value = expr\n\t\t} else {\n\t\t\treturn nil, nil, nil // no fix to suggest\n\t\t}\n\n\t\telts = append(elts, kv)\n\t}\n\n\t// If all of the struct's fields are unexported, we have nothing to do.\n\tif len(elts) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"no elements to fill\")\n\t}\n\n\t// Find the line on which the composite literal is declared.\n\tsplit := bytes.Split(pgf.Src, []byte(\"\\n\"))\n\tlineNumber := safetoken.StartPosition(fset, expr.Lbrace).Line\n\tfirstLine := split[lineNumber-1] // lines are 1-indexed\n\n\t// Trim the whitespace from the left of the line, and use the index\n\t// to get the amount of whitespace on the left.\n\ttrimmed := bytes.TrimLeftFunc(firstLine, unicode.IsSpace)\n\tindex := bytes.Index(firstLine, trimmed)\n\twhitespace := firstLine[:index]\n\n\t// Write a new composite literal \"_{...}\" composed of all prefilled and new elements,\n\t// preserving existing formatting and comments.\n\t// An alternative would be to only format the new fields,\n\t// but by printing the entire composite literal, we ensure\n\t// that the result is gofmt'ed.\n\tvar buf bytes.Buffer\n\tbuf.WriteString(\"_{\\n\")\n\tfcmap := ast.NewCommentMap(fset, file, file.Comments)\n\tcomments := fcmap.Filter(expr).Comments() // comments inside the expr, in source order\n\tfor _, elt := range elts {\n\t\t// Print comments before the current elt\n\t\tfor len(comments) > 0 && comments[0].Pos() < elt.Pos() {\n\t\t\tfor _, co := range comments[0].List {\n\t\t\t\tfmt.Fprintln(&buf, co.Text)\n\t\t\t}\n\t\t\tcomments = comments[1:]\n\t\t}\n\n\t\t// Print the current elt with comments\n\t\teltcomments := fcmap.Filter(elt).Comments()\n\t\tif err := format.Node(&buf, fset, &printer.CommentedNode{Node: elt, Comments: eltcomments}); err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tbuf.WriteString(\",\")\n\n\t\t// Prune comments up to the end of the elt\n\t\tfor len(comments) > 0 && comments[0].Pos() < elt.End() {\n\t\t\tcomments = comments[1:]\n\t\t}\n\n\t\t// Write comments associated with the current elt that appear after it\n\t\t// printer.CommentedNode only prints comments inside the elt.\n\t\tfor _, cg := range eltcomments {\n\t\t\tfor _, co := range cg.List {\n\t\t\t\tif co.Pos() >= elt.End() {\n\t\t\t\t\tfmt.Fprintln(&buf, co.Text)\n\t\t\t\t\tif len(comments) > 0 {\n\t\t\t\t\t\tcomments = comments[1:]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbuf.WriteString(\"\\n\")\n\t}\n\tbuf.WriteString(\"}\")\n\tformatted, err := format.Source(buf.Bytes())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tsug := indent(formatted, whitespace)\n\t// Remove _\n\tidx := bytes.IndexByte(sug, '{') // cannot fail\n\tsug = sug[idx:]\n\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: []analysis.TextEdit{\n\t\t\t{\n\t\t\t\tPos:     expr.Lbrace,\n\t\t\t\tEnd:     expr.Rbrace + token.Pos(len(\"}\")),\n\t\t\t\tNewText: sug,\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\n// indent works line by line through str, indenting (prefixing) each line with\n// ind.\nfunc indent(str, ind []byte) []byte {\n\tsplit := bytes.Split(str, []byte(\"\\n\"))\n\tnewText := bytes.NewBuffer(nil)\n\tfor i, s := range split {\n\t\tif len(s) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// Don't add the extra indentation to the first line.\n\t\tif i != 0 {\n\t\t\tnewText.Write(ind)\n\t\t}\n\t\tnewText.Write(s)\n\t\tif i < len(split)-1 {\n\t\t\tnewText.WriteByte('\\n')\n\t\t}\n\t}\n\treturn newText.Bytes()\n}\n\n// populateValue constructs an expression to fill the value of a struct field.\n//\n// When the type of a struct field is a basic literal or interface, we return\n// default values. For other types, such as maps, slices, and channels, we create\n// empty expressions such as []T{} or make(chan T) rather than using default values.\n//\n// The reasoning here is that users will call fillstruct with the intention of\n// initializing the struct, in which case setting these fields to nil has no effect.\n//\n// If the input contains an invalid type, populateValue may panic or return\n// expression that may not compile.\nfunc populateValue(typ types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {\n\tswitch t := typ.(type) {\n\tcase *types.TypeParam, *types.Interface, *types.Struct, *types.Basic:\n\t\treturn typesinternal.ZeroExpr(t, qual)\n\n\tcase *types.Alias, *types.Named:\n\t\tswitch t.Underlying().(type) {\n\t\t// Avoid typesinternal.ZeroExpr here as we don't want to return nil.\n\t\tcase *types.Map, *types.Slice:\n\t\t\treturn &ast.CompositeLit{\n\t\t\t\tType: typesinternal.TypeExpr(t, qual),\n\t\t\t}, true\n\t\tdefault:\n\t\t\treturn typesinternal.ZeroExpr(t, qual)\n\t\t}\n\n\t// Avoid typesinternal.ZeroExpr here as we don't want to return nil.\n\tcase *types.Map, *types.Slice:\n\t\treturn &ast.CompositeLit{\n\t\t\tType: typesinternal.TypeExpr(t, qual),\n\t\t}, true\n\n\tcase *types.Array:\n\t\treturn &ast.CompositeLit{\n\t\t\tType: &ast.ArrayType{\n\t\t\t\tElt: typesinternal.TypeExpr(t.Elem(), qual),\n\t\t\t\tLen: &ast.BasicLit{\n\t\t\t\t\tKind: token.INT, Value: fmt.Sprintf(\"%v\", t.Len()),\n\t\t\t\t},\n\t\t\t},\n\t\t}, true\n\n\tcase *types.Chan:\n\t\tdir := ast.ChanDir(t.Dir())\n\t\tif t.Dir() == types.SendRecv {\n\t\t\tdir = ast.SEND | ast.RECV\n\t\t}\n\t\treturn &ast.CallExpr{\n\t\t\tFun: ast.NewIdent(\"make\"),\n\t\t\tArgs: []ast.Expr{\n\t\t\t\t&ast.ChanType{\n\t\t\t\t\tDir:   dir,\n\t\t\t\t\tValue: typesinternal.TypeExpr(t.Elem(), qual),\n\t\t\t\t},\n\t\t\t},\n\t\t}, true\n\n\tcase *types.Signature:\n\t\treturn &ast.FuncLit{\n\t\t\tType: typesinternal.TypeExpr(t, qual).(*ast.FuncType),\n\t\t\t// The body of the function literal contains a panic statement to\n\t\t\t// avoid type errors.\n\t\t\tBody: &ast.BlockStmt{\n\t\t\t\tList: []ast.Stmt{\n\t\t\t\t\t&ast.ExprStmt{\n\t\t\t\t\t\tX: &ast.CallExpr{\n\t\t\t\t\t\t\tFun: ast.NewIdent(\"panic\"),\n\t\t\t\t\t\t\tArgs: []ast.Expr{\n\t\t\t\t\t\t\t\t&ast.BasicLit{\n\t\t\t\t\t\t\t\t\tKind:  token.STRING,\n\t\t\t\t\t\t\t\t\tValue: `\"TODO\"`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}, true\n\n\tcase *types.Pointer:\n\t\tswitch tt := types.Unalias(t.Elem()).(type) {\n\t\tcase *types.Basic:\n\t\t\treturn &ast.CallExpr{\n\t\t\t\tFun: &ast.Ident{\n\t\t\t\t\tName: \"new\",\n\t\t\t\t},\n\t\t\t\tArgs: []ast.Expr{\n\t\t\t\t\t&ast.Ident{\n\t\t\t\t\t\tName: t.Elem().String(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, true\n\t\t// Pointer to type parameter should return new(T) instead of &*new(T).\n\t\tcase *types.TypeParam:\n\t\t\treturn &ast.CallExpr{\n\t\t\t\tFun: &ast.Ident{\n\t\t\t\t\tName: \"new\",\n\t\t\t\t},\n\t\t\t\tArgs: []ast.Expr{\n\t\t\t\t\t&ast.Ident{\n\t\t\t\t\t\tName: tt.Obj().Name(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, true\n\t\tdefault:\n\t\t\t// TODO(hxjiang): & prefix only works if populateValue returns a\n\t\t\t// composite literal T{} or the expression new(T).\n\t\t\texpr, isValid := populateValue(t.Elem(), qual)\n\t\t\treturn &ast.UnaryExpr{\n\t\t\t\tOp: token.AND,\n\t\t\t\tX:  expr,\n\t\t\t}, isValid\n\t\t}\n\t}\n\treturn nil, false\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillstruct/fillstruct_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillstruct_test\n\nimport (\n\t\"go/token\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillstruct\"\n)\n\n// analyzer allows us to test the fillstruct code action using the analysistest\n// harness. (fillstruct used to be a gopls analyzer.)\nvar analyzer = &analysis.Analyzer{\n\tName: \"fillstruct\",\n\tDoc:  \"test only\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tfor _, f := range pass.Files {\n\t\t\tfor _, diag := range fillstruct.Diagnose(f, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {\n\t\t\t\tpass.Report(diag)\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\t},\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillstruct\",\n\tRunDespiteErrors: true,\n}\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillstruct/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillstruct\n\nimport (\n\tdata \"b\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"unsafe\"\n)\n\ntype emptyStruct struct{}\n\nvar _ = emptyStruct{}\n\ntype basicStruct struct {\n\tfoo int\n}\n\nvar _ = basicStruct{} // want `basicStruct literal has missing fields`\n\ntype twoArgStruct struct {\n\tfoo int\n\tbar string\n}\n\nvar _ = twoArgStruct{} // want `twoArgStruct literal has missing fields`\n\nvar _ = twoArgStruct{ // want `twoArgStruct literal has missing fields`\n\tbar: \"bar\",\n}\n\ntype nestedStruct struct {\n\tbar   string\n\tbasic basicStruct\n}\n\nvar _ = nestedStruct{} // want `nestedStruct literal has missing fields`\n\nvar _ = data.B{} // want `fillstruct.B literal has missing fields`\n\ntype typedStruct struct {\n\tm  map[string]int\n\ts  []int\n\tc  chan int\n\tc1 <-chan int\n\ta  [2]string\n}\n\nvar _ = typedStruct{} // want `typedStruct literal has missing fields`\n\ntype funStruct struct {\n\tfn func(i int) int\n}\n\nvar _ = funStruct{} // want `funStruct literal has missing fields`\n\ntype funStructComplex struct {\n\tfn func(i int, s string) (string, int)\n}\n\nvar _ = funStructComplex{} // want `funStructComplex literal has missing fields`\n\ntype funStructEmpty struct {\n\tfn func()\n}\n\nvar _ = funStructEmpty{} // want `funStructEmpty literal has missing fields`\n\ntype Foo struct {\n\tA int\n}\n\ntype Bar struct {\n\tX *Foo\n\tY *Foo\n}\n\nvar _ = Bar{} // want `Bar literal has missing fields`\n\ntype importedStruct struct {\n\tm  map[*ast.CompositeLit]ast.Field\n\ts  []ast.BadExpr\n\ta  [3]token.Token\n\tc  chan ast.EmptyStmt\n\tfn func(ast_decl ast.DeclStmt) ast.Ellipsis\n\tst ast.CompositeLit\n}\n\nvar _ = importedStruct{} // want `importedStruct literal has missing fields`\n\ntype pointerBuiltinStruct struct {\n\tb *bool\n\ts *string\n\ti *int\n}\n\nvar _ = pointerBuiltinStruct{} // want `pointerBuiltinStruct literal has missing fields`\n\nvar _ = []ast.BasicLit{\n\t{}, // want `ast.BasicLit literal has missing fields`\n}\n\nvar _ = []ast.BasicLit{{}} // want \"ast.BasicLit literal has missing fields\"\n\ntype unsafeStruct struct {\n\tfoo unsafe.Pointer\n}\n\nvar _ = unsafeStruct{} // want `unsafeStruct literal has missing fields`\n"
  },
  {
    "path": "gopls/internal/analysis/fillstruct/testdata/src/b/b.go",
    "content": "package fillstruct\n\ntype B struct {\n\tExportedInt   int\n\tunexportedInt int\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillstruct/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillstruct\n\ntype emptyStruct[A any] struct{}\n\nvar _ = emptyStruct[int]{}\n\ntype basicStruct[T any] struct {\n\tfoo T\n}\n\nvar _ = basicStruct[int]{} // want `basicStruct\\[int\\] literal has missing fields`\n\ntype twoArgStruct[F, B any] struct {\n\tfoo F\n\tbar B\n}\n\nvar _ = twoArgStruct[string, int]{} // want `twoArgStruct\\[string, int\\] literal has missing fields`\n\nvar _ = twoArgStruct[int, string]{ // want `twoArgStruct\\[int, string\\] literal has missing fields`\n\tbar: \"bar\",\n}\n\ntype nestedStruct struct {\n\tbar   string\n\tbasic basicStruct[int]\n}\n\nvar _ = nestedStruct{} // want \"nestedStruct literal has missing fields\"\n\nfunc _[T any]() {\n\ttype S struct{ t T }\n\tx := S{} // want \"S\"\n\t_ = x\n}\n\nfunc Test() {\n\tvar tests = []struct {\n\t\ta, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p string\n\t}{\n\t\t{}, // want \"anonymous struct{ a: string, b: string, c: string, ... } literal has missing fields\"\n\t}\n\tfor _, test := range tests {\n\t\t_ = test\n\t}\n}\n\nfunc _[T twoArgStruct[int, int]]() {\n\t_ = T{} // want \"T literal has missing fields\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillswitch/doc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fillswitch identifies switches with missing cases.\n//\n// It reports a diagnostic for each type switch or 'enum' switch that\n// has missing cases, and suggests a fix to fill them in.\n//\n// The possible cases are: for a type switch, each accessible named\n// type T or pointer *T that is assignable to the interface type; and\n// for an 'enum' switch, each accessible named constant of the same\n// type as the switch value.\n//\n// For an 'enum' switch, it will suggest cases for all possible values of the\n// type.\n//\n//\ttype Suit int8\n//\tconst (\n//\t\t Spades Suit = iota\n//\t\t Hearts\n//\t\t Diamonds\n//\t\t Clubs\n//\t)\n//\n//\tvar s Suit\n//\tswitch s {\n//\tcase Spades:\n//\t}\n//\n// It will report a diagnostic with a suggested fix to fill in the remaining\n// cases:\n//\n//\tvar s Suit\n//\tswitch s {\n//\tcase Spades:\n//\tcase Hearts:\n//\tcase Diamonds:\n//\tcase Clubs:\n//\tdefault:\n//\t\t panic(fmt.Sprintf(\"unexpected Suit: %v\", s))\n//\t}\n//\n// For a type switch, it will suggest cases for all types that implement the\n// interface.\n//\n//\tvar stmt ast.Stmt\n//\tswitch stmt.(type) {\n//\tcase *ast.IfStmt:\n//\t}\n//\n// It will report a diagnostic with a suggested fix to fill in the remaining\n// cases:\n//\n//\tvar stmt ast.Stmt\n//\tswitch stmt.(type) {\n//\tcase *ast.IfStmt:\n//\tcase *ast.ForStmt:\n//\tcase *ast.RangeStmt:\n//\tcase *ast.AssignStmt:\n//\tcase *ast.GoStmt:\n//\t...\n//\tdefault:\n//\t\t panic(fmt.Sprintf(\"unexpected ast.Stmt: %T\", stmt))\n//\t}\npackage fillswitch\n"
  },
  {
    "path": "gopls/internal/analysis/fillswitch/fillswitch.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillswitch\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// Diagnose computes diagnostics for switch statements with missing cases\n// overlapping with the provided start and end position of file f.\n//\n// If either start or end is invalid, the entire file is inspected.\nfunc Diagnose(f *ast.File, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {\n\tvar diags []analysis.Diagnostic\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn true // pop\n\t\t}\n\t\tif start.IsValid() && n.End() < start ||\n\t\t\tend.IsValid() && n.Pos() > end {\n\t\t\treturn false // skip non-overlapping subtree\n\t\t}\n\t\tvar fix *analysis.SuggestedFix\n\t\tswitch n := n.(type) {\n\t\tcase *ast.SwitchStmt:\n\t\t\tfix = suggestedFixSwitch(n, pkg, info)\n\t\tcase *ast.TypeSwitchStmt:\n\t\t\tfix = suggestedFixTypeSwitch(n, pkg, info)\n\t\t}\n\t\tif fix != nil {\n\t\t\tdiags = append(diags, analysis.Diagnostic{\n\t\t\t\tMessage:        fix.Message,\n\t\t\t\tPos:            n.Pos(),\n\t\t\t\tEnd:            n.Pos() + token.Pos(len(\"switch\")),\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{*fix},\n\t\t\t})\n\t\t}\n\t\treturn true\n\t})\n\n\treturn diags\n}\n\nfunc suggestedFixTypeSwitch(stmt *ast.TypeSwitchStmt, pkg *types.Package, info *types.Info) *analysis.SuggestedFix {\n\tif hasDefaultCase(stmt.Body) {\n\t\treturn nil\n\t}\n\n\tnamedType := namedTypeFromTypeSwitch(stmt, info)\n\tif namedType == nil {\n\t\treturn nil\n\t}\n\n\texistingCases := caseTypes(stmt.Body, info)\n\t// Gather accessible package-level concrete types\n\t// that implement the switch interface type.\n\tscope := namedType.Obj().Pkg().Scope()\n\tvar buf bytes.Buffer\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif tname, ok := obj.(*types.TypeName); !ok || tname.IsAlias() {\n\t\t\tcontinue // not a defined type\n\t\t}\n\n\t\tif types.IsInterface(obj.Type()) {\n\t\t\tcontinue\n\t\t}\n\n\t\tsamePkg := obj.Pkg() == pkg\n\t\tif !samePkg && !obj.Exported() {\n\t\t\tcontinue // inaccessible\n\t\t}\n\n\t\tvar key caseType\n\t\tif types.AssignableTo(obj.Type(), namedType.Obj().Type()) {\n\t\t\tkey.named = obj.Type().(*types.Named)\n\t\t} else if ptr := types.NewPointer(obj.Type()); types.AssignableTo(ptr, namedType.Obj().Type()) {\n\t\t\tkey.named = obj.Type().(*types.Named)\n\t\t\tkey.ptr = true\n\t\t}\n\n\t\tif key.named != nil {\n\t\t\tif existingCases[key] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif buf.Len() > 0 {\n\t\t\t\tbuf.WriteString(\"\\t\")\n\t\t\t}\n\n\t\t\tbuf.WriteString(\"case \")\n\t\t\tif key.ptr {\n\t\t\t\tbuf.WriteByte('*')\n\t\t\t}\n\n\t\t\tif p := key.named.Obj().Pkg(); p != pkg {\n\t\t\t\t// TODO: use the correct package name when the import is renamed\n\t\t\t\tbuf.WriteString(p.Name())\n\t\t\t\tbuf.WriteByte('.')\n\t\t\t}\n\t\t\tbuf.WriteString(key.named.Obj().Name())\n\t\t\tbuf.WriteString(\":\\n\")\n\t\t}\n\t}\n\n\tif buf.Len() == 0 {\n\t\treturn nil\n\t}\n\n\tswitch assign := stmt.Assign.(type) {\n\tcase *ast.AssignStmt:\n\t\taddDefaultCase(&buf, namedType, assign.Lhs[0])\n\tcase *ast.ExprStmt:\n\t\tif assert, ok := assign.X.(*ast.TypeAssertExpr); ok {\n\t\t\taddDefaultCase(&buf, namedType, assert.X)\n\t\t}\n\t}\n\n\treturn &analysis.SuggestedFix{\n\t\tMessage: \"Add cases for \" + types.TypeString(namedType, typesinternal.NameRelativeTo(pkg)),\n\t\tTextEdits: []analysis.TextEdit{{\n\t\t\tPos:     stmt.End() - token.Pos(len(\"}\")),\n\t\t\tEnd:     stmt.End() - token.Pos(len(\"}\")),\n\t\t\tNewText: buf.Bytes(),\n\t\t}},\n\t}\n}\n\nfunc suggestedFixSwitch(stmt *ast.SwitchStmt, pkg *types.Package, info *types.Info) *analysis.SuggestedFix {\n\tif hasDefaultCase(stmt.Body) {\n\t\treturn nil\n\t}\n\n\tnamedType, ok := info.TypeOf(stmt.Tag).(*types.Named)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\texistingCases := caseConsts(stmt.Body, info)\n\t// Gather accessible named constants of the same type as the switch value.\n\tscope := namedType.Obj().Pkg().Scope()\n\tvar buf bytes.Buffer\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif c, ok := obj.(*types.Const); ok &&\n\t\t\t(obj.Pkg() == pkg || obj.Exported()) && // accessible\n\t\t\ttypes.Identical(obj.Type(), namedType.Obj().Type()) &&\n\t\t\t!existingCases[c] {\n\n\t\t\tif buf.Len() > 0 {\n\t\t\t\tbuf.WriteString(\"\\t\")\n\t\t\t}\n\n\t\t\tbuf.WriteString(\"case \")\n\t\t\tif c.Pkg() != pkg {\n\t\t\t\tbuf.WriteString(c.Pkg().Name())\n\t\t\t\tbuf.WriteByte('.')\n\t\t\t}\n\t\t\tbuf.WriteString(c.Name())\n\t\t\tbuf.WriteString(\":\\n\")\n\t\t}\n\t}\n\n\tif buf.Len() == 0 {\n\t\treturn nil\n\t}\n\n\taddDefaultCase(&buf, namedType, stmt.Tag)\n\n\treturn &analysis.SuggestedFix{\n\t\tMessage: \"Add cases for \" + types.TypeString(namedType, typesinternal.NameRelativeTo(pkg)),\n\t\tTextEdits: []analysis.TextEdit{{\n\t\t\tPos:     stmt.End() - token.Pos(len(\"}\")),\n\t\t\tEnd:     stmt.End() - token.Pos(len(\"}\")),\n\t\t\tNewText: buf.Bytes(),\n\t\t}},\n\t}\n}\n\nfunc addDefaultCase(buf *bytes.Buffer, named *types.Named, expr ast.Expr) {\n\tvar dottedBuf bytes.Buffer\n\t// writeDotted emits a dotted path a.b.c.\n\tvar writeDotted func(e ast.Expr) bool\n\twriteDotted = func(e ast.Expr) bool {\n\t\tswitch e := e.(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\tif !writeDotted(e.X) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdottedBuf.WriteByte('.')\n\t\t\tdottedBuf.WriteString(e.Sel.Name)\n\t\t\treturn true\n\t\tcase *ast.Ident:\n\t\t\tdottedBuf.WriteString(e.Name)\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tbuf.WriteString(\"\\tdefault:\\n\")\n\ttypeName := fmt.Sprintf(\"%s.%s\", named.Obj().Pkg().Name(), named.Obj().Name())\n\tif writeDotted(expr) {\n\t\t// Switch tag expression is a dotted path.\n\t\t// It is safe to re-evaluate it in the default case.\n\t\tformat := fmt.Sprintf(\"unexpected %s: %%#v\", typeName)\n\t\tfmt.Fprintf(buf, \"\\t\\tpanic(fmt.Sprintf(%q, %s))\\n\\t\", format, dottedBuf.String())\n\t} else {\n\t\t// Emit simpler message, without re-evaluating tag expression.\n\t\tfmt.Fprintf(buf, \"\\t\\tpanic(%q)\\n\\t\", \"unexpected \"+typeName)\n\t}\n}\n\nfunc namedTypeFromTypeSwitch(stmt *ast.TypeSwitchStmt, info *types.Info) *types.Named {\n\tswitch assign := stmt.Assign.(type) {\n\tcase *ast.ExprStmt:\n\t\tif typ, ok := assign.X.(*ast.TypeAssertExpr); ok {\n\t\t\tif named, ok := info.TypeOf(typ.X).(*types.Named); ok {\n\t\t\t\treturn named\n\t\t\t}\n\t\t}\n\n\tcase *ast.AssignStmt:\n\t\tif typ, ok := assign.Rhs[0].(*ast.TypeAssertExpr); ok {\n\t\t\tif named, ok := info.TypeOf(typ.X).(*types.Named); ok {\n\t\t\t\treturn named\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc hasDefaultCase(body *ast.BlockStmt) bool {\n\tfor _, clause := range body.List {\n\t\tif len(clause.(*ast.CaseClause).List) == 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc caseConsts(body *ast.BlockStmt, info *types.Info) map[*types.Const]bool {\n\tout := map[*types.Const]bool{}\n\tfor _, stmt := range body.List {\n\t\tfor _, e := range stmt.(*ast.CaseClause).List {\n\t\t\tif info.Types[e].Value == nil {\n\t\t\t\tcontinue // not a constant\n\t\t\t}\n\n\t\t\tif sel, ok := e.(*ast.SelectorExpr); ok {\n\t\t\t\te = sel.Sel // replace pkg.C with C\n\t\t\t}\n\n\t\t\tif e, ok := e.(*ast.Ident); ok {\n\t\t\t\tif c, ok := info.Uses[e].(*types.Const); ok {\n\t\t\t\t\tout[c] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn out\n}\n\ntype caseType struct {\n\tnamed *types.Named\n\tptr   bool\n}\n\nfunc caseTypes(body *ast.BlockStmt, info *types.Info) map[caseType]bool {\n\tout := map[caseType]bool{}\n\tfor _, stmt := range body.List {\n\t\tfor _, e := range stmt.(*ast.CaseClause).List {\n\t\t\tif tv, ok := info.Types[e]; ok && tv.IsType() {\n\t\t\t\tt := tv.Type\n\t\t\t\tptr := false\n\t\t\t\tif p, ok := t.(*types.Pointer); ok {\n\t\t\t\t\tt = p.Elem()\n\t\t\t\t\tptr = true\n\t\t\t\t}\n\n\t\t\t\tif named, ok := t.(*types.Named); ok {\n\t\t\t\t\tout[caseType{named, ptr}] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn out\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillswitch/fillswitch_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillswitch_test\n\nimport (\n\t\"go/token\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillswitch\"\n)\n\n// analyzer allows us to test the fillswitch code action using the analysistest\n// harness.\nvar analyzer = &analysis.Analyzer{\n\tName: \"fillswitch\",\n\tDoc:  \"test only\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tfor _, f := range pass.Files {\n\t\t\tfor _, diag := range fillswitch.Diagnose(f, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {\n\t\t\t\tpass.Report(diag)\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\t},\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillswitch\",\n\tRunDespiteErrors: true,\n}\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillswitch/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fillswitch\n\nimport altb \"b\"\n\ntype typeA int\n\nconst (\n\ttypeAOne typeA = iota\n\ttypeATwo\n\ttypeAThree\n)\n\nfunc doSwitch() {\n\tvar a typeA\n\tswitch a { // want `Add cases for typeA`\n\t}\n\n\tswitch a { // want `Add cases for typeA`\n\tcase typeAOne:\n\t}\n\n\tswitch a {\n\tcase typeAOne:\n\tdefault:\n\t}\n\n\tswitch a {\n\tcase typeAOne:\n\tcase typeATwo:\n\tcase typeAThree:\n\t}\n\n\tvar b altb.TypeB\n\tswitch b { // want `Add cases for b.TypeB`\n\tcase altb.TypeBOne:\n\t}\n}\n\ntype notification interface {\n\tisNotification()\n}\n\ntype notificationOne struct{}\n\nfunc (notificationOne) isNotification() {}\n\ntype notificationTwo struct{}\n\nfunc (notificationTwo) isNotification() {}\n\nfunc doTypeSwitch() {\n\tvar not notification\n\tswitch not.(type) { // want `Add cases for notification`\n\t}\n\n\tswitch not.(type) { // want `Add cases for notification`\n\tcase notificationOne:\n\t}\n\n\tswitch not.(type) {\n\tcase notificationOne:\n\tcase notificationTwo:\n\t}\n\n\tswitch not.(type) {\n\tdefault:\n\t}\n\n\tvar t data.ExportedInterface\n\tswitch t {\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/fillswitch/testdata/src/b/b.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage b\n\ntype TypeB int\n\nconst (\n\tTypeBOne TypeB = iota\n\tTypeBTwo\n\tTypeBThree\n)\n\ntype ExportedInterface interface {\n\tisExportedInterface()\n}\n\ntype notExportedType struct{}\n\nfunc (notExportedType) isExportedInterface() {}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/infertypeargs.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage infertypeargs\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nconst Doc = `check for unnecessary type arguments in call expressions\n\nExplicit type arguments may be omitted from call expressions if they can be\ninferred from function arguments, or from other type arguments:\n\n\tfunc f[T any](T) {}\n\t\n\tfunc _() {\n\t\tf[string](\"foo\") // string could be inferred\n\t}\n`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"infertypeargs\",\n\tDoc:      Doc,\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tfor _, diag := range diagnose(pass.Fset, inspect, token.NoPos, token.NoPos, pass.Pkg, pass.TypesInfo) {\n\t\tpass.Report(diag)\n\t}\n\treturn nil, nil\n}\n\n// Diagnose reports diagnostics describing simplifications to type\n// arguments overlapping with the provided start and end position.\n//\n// If start or end is token.NoPos, the corresponding bound is not checked\n// (i.e. if both start and end are NoPos, all call expressions are considered).\nfunc diagnose(fset *token.FileSet, inspect *inspector.Inspector, start, end token.Pos, pkg *types.Package, info *types.Info) []analysis.Diagnostic {\n\tvar diags []analysis.Diagnostic\n\n\tnodeFilter := []ast.Node{(*ast.CallExpr)(nil)}\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tcall := node.(*ast.CallExpr)\n\t\tx, lbrack, indices, rbrack := typeparams.UnpackIndexExpr(call.Fun)\n\t\tident := calledIdent(x)\n\t\tif ident == nil || len(indices) == 0 {\n\t\t\treturn // no explicit args, nothing to do\n\t\t}\n\n\t\tif (start.IsValid() && call.End() < start) || (end.IsValid() && call.Pos() > end) {\n\t\t\treturn // non-overlapping\n\t\t}\n\n\t\t// Confirm that instantiation actually occurred at this ident.\n\t\tidata, ok := info.Instances[ident]\n\t\tif !ok {\n\t\t\treturn // something went wrong, but fail open\n\t\t}\n\t\tinstance := idata.Type\n\n\t\t// Start removing argument expressions from the right, and check if we can\n\t\t// still infer the call expression.\n\t\trequired := len(indices) // number of type expressions that are required\n\t\tfor i := len(indices) - 1; i >= 0; i-- {\n\t\t\tvar fun ast.Expr\n\t\t\tif i == 0 {\n\t\t\t\t// No longer an index expression: just use the parameterized operand.\n\t\t\t\tfun = x\n\t\t\t} else {\n\t\t\t\tfun = typeparams.PackIndexExpr(x, lbrack, indices[:i], indices[i-1].End())\n\t\t\t}\n\t\t\tnewCall := &ast.CallExpr{\n\t\t\t\tFun:      fun,\n\t\t\t\tLparen:   call.Lparen,\n\t\t\t\tArgs:     call.Args,\n\t\t\t\tEllipsis: call.Ellipsis,\n\t\t\t\tRparen:   call.Rparen,\n\t\t\t}\n\t\t\tinfo := &types.Info{\n\t\t\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t\t}\n\t\t\tif err := types.CheckExpr(fset, pkg, call.Pos(), newCall, info); err != nil {\n\t\t\t\t// Most likely inference failed.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tnewIData := info.Instances[ident]\n\t\t\tnewInstance := newIData.Type\n\t\t\tif !types.Identical(instance, newInstance) {\n\t\t\t\t// The inferred result type does not match the original result type, so\n\t\t\t\t// this simplification is not valid.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\trequired = i\n\t\t}\n\t\tif required < len(indices) {\n\t\t\tvar s, e token.Pos\n\t\t\tvar edit analysis.TextEdit\n\t\t\tif required == 0 {\n\t\t\t\ts, e = lbrack, rbrack+1 // erase the entire index\n\t\t\t\tedit = analysis.TextEdit{Pos: s, End: e}\n\t\t\t} else {\n\t\t\t\ts = indices[required].Pos()\n\t\t\t\te = rbrack\n\t\t\t\t//  erase from end of last arg to include last comma & white-spaces\n\t\t\t\tedit = analysis.TextEdit{Pos: indices[required-1].End(), End: e}\n\t\t\t}\n\t\t\t// Recheck that our (narrower) fixes overlap with the requested range.\n\t\t\tif (start.IsValid() && e < start) || (end.IsValid() && s > end) {\n\t\t\t\treturn // non-overlapping\n\t\t\t}\n\t\t\tdiags = append(diags, analysis.Diagnostic{\n\t\t\t\tPos:     s,\n\t\t\t\tEnd:     e,\n\t\t\t\tMessage: \"unnecessary type arguments\",\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage:   \"Simplify type arguments\",\n\t\t\t\t\tTextEdits: []analysis.TextEdit{edit},\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t})\n\n\treturn diags\n}\n\nfunc calledIdent(x ast.Expr) *ast.Ident {\n\tswitch x := x.(type) {\n\tcase *ast.Ident:\n\t\treturn x\n\tcase *ast.SelectorExpr:\n\t\treturn x.Sel\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/infertypeargs_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage infertypeargs_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/infertypeargs\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, infertypeargs.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/basic.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the infertyepargs checker.\n\npackage a\n\nfunc f[T any](T) {}\n\nfunc g[T any]() T { var x T; return x }\n\nfunc h[P interface{ ~*T }, T any]() {}\n\nfunc _() {\n\tf[string](\"hello\") // want \"unnecessary type arguments\"\n\tf[int](2)          // want \"unnecessary type arguments\"\n\t_ = g[int]()\n\th[*int, int]() // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/basic.go.golden",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains tests for the infertyepargs checker.\n\npackage a\n\nfunc f[T any](T) {}\n\nfunc g[T any]() T { var x T; return x }\n\nfunc h[P interface{ ~*T }, T any]() {}\n\nfunc _() {\n\tf(\"hello\") // want \"unnecessary type arguments\"\n\tf(2)       // want \"unnecessary type arguments\"\n\t_ = g[int]()\n\th[*int]() // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/imported/imported.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imported\n\nfunc F[T any](T) {}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/imported.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport \"a/imported\"\n\nfunc _() {\n\tvar x int\n\timported.F[int](x) // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/imported.go.golden",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport \"a/imported\"\n\nfunc _() {\n\tvar x int\n\timported.F(x) // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/notypechange.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// We should not suggest removing type arguments if doing so would change the\n// resulting type.\n\npackage a\n\nfunc id[T any](t T) T { return t }\n\nvar _ = id[int](1)        // want \"unnecessary type arguments\"\nvar _ = id[string](\"foo\") // want \"unnecessary type arguments\"\nvar _ = id[int64](2)\n\nfunc pair[T any](t T) (T, T) { return t, t }\n\nvar _, _ = pair[int](3) // want \"unnecessary type arguments\"\nvar _, _ = pair[int64](3)\n\nfunc noreturn[T any](t T) {}\n\nfunc _() {\n\tnoreturn[int64](4)\n\tnoreturn[int](4) // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/infertypeargs/testdata/src/a/notypechange.go.golden",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// We should not suggest removing type arguments if doing so would change the\n// resulting type.\n\npackage a\n\nfunc id[T any](t T) T { return t }\n\nvar _ = id(1)     // want \"unnecessary type arguments\"\nvar _ = id(\"foo\") // want \"unnecessary type arguments\"\nvar _ = id[int64](2)\n\nfunc pair[T any](t T) (T, T) { return t, t }\n\nvar _, _ = pair(3) // want \"unnecessary type arguments\"\nvar _, _ = pair[int64](3)\n\nfunc noreturn[T any](t T) {}\n\nfunc _() {\n\tnoreturn[int64](4)\n\tnoreturn(4) // want \"unnecessary type arguments\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/cmd/maprange/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The maprange command applies the golang.org/x/tools/gopls/internal/analysis/maprange\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/maprange\"\n)\n\nfunc main() { singlechecker.Main(maprange.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package maprange defines an Analyzer that checks for redundant use\n// of the functions maps.Keys and maps.Values in \"for\" statements with\n// \"range\" clauses.\n//\n// # Analyzer maprange\n//\n// maprange: checks for unnecessary calls to maps.Keys and maps.Values in range statements\n//\n// Consider a loop written like this:\n//\n//\tfor val := range maps.Values(m) {\n//\t\tfmt.Println(val)\n//\t}\n//\n// This should instead be written without the call to maps.Values:\n//\n//\tfor _, val := range m {\n//\t\tfmt.Println(val)\n//\t}\n//\n// golang.org/x/exp/maps returns slices for Keys/Values instead of iterators,\n// but unnecessary calls should similarly be removed:\n//\n//\tfor _, key := range maps.Keys(m) {\n//\t\tfmt.Println(key)\n//\t}\n//\n// should be rewritten as:\n//\n//\tfor key := range m {\n//\t\tfmt.Println(key)\n//\t}\npackage maprange\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The unusedfunc command runs the maprange analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/maprange\"\n)\n\nfunc main() { singlechecker.Main(maprange.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/maprange.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage maprange\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"maprange\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"maprange\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange\",\n\tRequires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},\n\tRun:      run,\n}\n\n// This is a variable because the package name is different in Google's code base.\nvar xmaps = \"golang.org/x/exp/maps\"\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tswitch pass.Pkg.Path() {\n\tcase \"maps\", xmaps:\n\t\t// These packages know how to use their own APIs.\n\t\treturn nil, nil\n\t}\n\tvar (\n\t\tindex       = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tmapsKeys    = index.Object(\"maps\", \"Keys\")\n\t\tmapsValues  = index.Object(\"maps\", \"Values\")\n\t\txmapsKeys   = index.Object(xmaps, \"Keys\")\n\t\txmapsValues = index.Object(xmaps, \"Values\")\n\t)\n\tfor _, callee := range []types.Object{mapsKeys, mapsValues, xmapsKeys, xmapsValues} {\n\t\tfor curCall := range index.Calls(callee) {\n\t\t\tif curCall.ParentEdgeKind() == edge.RangeStmt_X {\n\t\t\t\tanalyzeRangeStmt(pass, callee, curCall)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// analyzeRangeStmt analyzes range statements iterating over calls to maps.Keys\n// or maps.Values (from the standard library \"maps\" or \"golang.org/x/exp/maps\").\n//\n// It reports a diagnostic with a suggested fix to simplify the loop by removing\n// the unnecessary function call and adjusting range variables, if possible.\n// For certain patterns involving x/exp/maps.Keys before Go 1.22, it reports\n// a diagnostic about potential incorrect usage without a suggested fix.\n// No diagnostic is reported if the range statement doesn't require changes.\nfunc analyzeRangeStmt(pass *analysis.Pass, callee types.Object, curCall inspector.Cursor) {\n\tvar (\n\t\tcall      = curCall.Node().(*ast.CallExpr)\n\t\trangeStmt = curCall.Parent().Node().(*ast.RangeStmt)\n\t\tpkg       = callee.Pkg().Path()\n\t\tfn        = callee.Name()\n\t)\n\tvar edits []analysis.TextEdit\n\n\t// Check if the call to maps.Keys or maps.Values can be removed/replaced.\n\t// Example:\n\t//  for range maps.Keys(m)\n\t//            ^^^^^^^^^ removeCall\n\t//  for i, _ := range maps.Keys(m)\n\t//                    ^^^^^^^^^ replace with `len`\n\t//\n\t// If we have: for i, k := range maps.Keys(m) (only possible using x/exp/maps)\n\t//         or: for i, v = range maps.Values(m)\n\t// do not remove the call.\n\tremoveCall := !isSet(rangeStmt.Key) || !isSet(rangeStmt.Value)\n\treplace := \"\"\n\tif pkg == xmaps && isSet(rangeStmt.Key) && rangeStmt.Value == nil {\n\t\t// If we have:   for i := range maps.Keys(m) (using x/exp/maps),\n\t\t// Replace with: for i := range len(m)\n\t\t// (This requires Go 1.22.)\n\t\treplace = \"len\"\n\t\tif !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curCall), versions.Go1_22) {\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     call.Pos(),\n\t\t\t\tEnd:     call.End(),\n\t\t\t\tMessage: fmt.Sprintf(\"likely incorrect use of %s.%s (returns a slice)\", pkg, fn),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n\tif removeCall {\n\t\tedits = append(edits, analysis.TextEdit{\n\t\t\tPos:     call.Fun.Pos(),\n\t\t\tEnd:     call.Fun.End(),\n\t\t\tNewText: []byte(replace)})\n\t}\n\t// Check if the key of the range statement should be removed.\n\t// Example:\n\t//  for _, k := range maps.Keys(m)\n\t//      ^^^ removeKey ^^^^^^^^^ removeCall\n\tremoveKey := pkg == xmaps && fn == \"Keys\" && !isSet(rangeStmt.Key) && isSet(rangeStmt.Value)\n\tif removeKey {\n\t\tedits = append(edits, analysis.TextEdit{\n\t\t\tPos: rangeStmt.Key.Pos(),\n\t\t\tEnd: rangeStmt.Value.Pos(),\n\t\t})\n\t}\n\t// Check if a key should be inserted to the range statement.\n\t// Example:\n\t//  for _, v := range maps.Values(m)\n\t//      ^^^ addKey    ^^^^^^^^^^^ removeCall\n\taddKey := pkg == \"maps\" && fn == \"Values\" && isSet(rangeStmt.Key)\n\tif addKey {\n\t\tedits = append(edits, analysis.TextEdit{\n\t\t\tPos:     rangeStmt.Key.Pos(),\n\t\t\tEnd:     rangeStmt.Key.Pos(),\n\t\t\tNewText: []byte(\"_, \"),\n\t\t})\n\t}\n\n\tif len(edits) > 0 {\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Pos(),\n\t\t\tEnd:     call.End(),\n\t\t\tMessage: fmt.Sprintf(\"unnecessary and inefficient call of %s.%s\", pkg, fn),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   fmt.Sprintf(\"Remove unnecessary call to %s.%s\", pkg, fn),\n\t\t\t\tTextEdits: edits,\n\t\t\t}},\n\t\t})\n\t}\n}\n\n// isSet reports whether an ast.Expr is a non-nil expression that is not the blank identifier.\nfunc isSet(expr ast.Expr) bool {\n\tident, ok := expr.(*ast.Ident)\n\treturn expr != nil && (!ok || ident.Name != \"_\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/maprange_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage maprange_test\n\nimport (\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/maprange\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestBasic(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"basic.txtar\"))\n\tanalysistest.RunWithSuggestedFixes(t, dir, maprange.Analyzer, \"maprange\")\n}\n\nfunc TestOld(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"old.txtar\"))\n\tanalysistest.RunWithSuggestedFixes(t, dir, maprange.Analyzer, \"maprange\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/maprange/testdata/basic.txtar",
    "content": "Test of fixing redundant calls to maps.Keys and maps.Values\n(both stdlib \"maps\" and \"golang.org/x/exp/maps\") for Go 1.24.\n\n-- go.mod --\nmodule maprange\n\nrequire golang.org/x/exp v0.0.0\n\nreplace golang.org/x/exp => ./exp\n\ngo 1.24\n\n-- basic.go --\npackage basic\n\nimport \"maps\"\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor range maps.Keys(m) { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor range maps.Values(m) { // want `unnecessary and inefficient call of maps.Values`\n\t}\n\n\tvar x struct {\n\t\tMap map[int]int\n\t}\n\tx.Map = make(map[int]int)\n\tfor x.Map[1] = range maps.Keys(m) { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor x.Map[2] = range maps.Values(m) { // want `unnecessary and inefficient call of maps.Values`\n\t}\n\n\tfor k := range maps.Keys(m) { // want `unnecessary and inefficient call of maps.Keys`\n\t\t_ = k\n\t}\n\n\tfor v := range maps.Values(m) { // want `unnecessary and inefficient call of maps.Values`\n\t\t_ = v\n\t}\n\n\tfor range maps.Keys(x.Map) { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor /* comment */ k := range /* comment */ maps.Keys(/* comment */ m) { // want `unnecessary and inefficient call of maps.Keys`\n\t\t_ = k\n\t}\n}\n\n-- basic.go.golden --\npackage basic\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor range m { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor range m { // want `unnecessary and inefficient call of maps.Values`\n\t}\n\n\tvar x struct {\n\t\tMap map[int]int\n\t}\n\tx.Map = make(map[int]int)\n\tfor x.Map[1] = range m { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor _, x.Map[2] = range m { // want `unnecessary and inefficient call of maps.Values`\n\t}\n\n\tfor k := range m { // want `unnecessary and inefficient call of maps.Keys`\n\t\t_ = k\n\t}\n\n\tfor _, v := range m { // want `unnecessary and inefficient call of maps.Values`\n\t\t_ = v\n\t}\n\n\tfor range x.Map { // want `unnecessary and inefficient call of maps.Keys`\n\t}\n\n\tfor /* comment */ k := range /* comment */ /* comment */ m { // want `unnecessary and inefficient call of maps.Keys`\n\t\t_ = k\n\t}\n}\n\n-- xmaps.go --\npackage basic\n\nimport \"golang.org/x/exp/maps\"\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor range maps.Keys(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor range maps.Values(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n\n\tfor i := range maps.Values(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t\t_ = i\n\t}\n\n\tvar x struct {\n\t\tMap map[int]int\n\t}\n\tx.Map = make(map[int]int)\n\tfor _, x.Map[1] = range maps.Keys(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor _, x.Map[2] = range maps.Values(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n\n\tfor _, k := range maps.Keys(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t\t_ = k\n\t}\n\n\tfor _, v := range maps.Values(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t\t_ = v\n\t}\n\n\tfor range maps.Keys(x.Map) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor i, k := range maps.Keys(m) { // ok: this can't be straightforwardly rewritten\n\t\t_, _ = i, k\n\t}\n\n\tfor _, _ = range maps.Values(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n}\n\n-- xmaps.go.golden --\npackage basic\n\nimport \"golang.org/x/exp/maps\"\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n\n\tfor i := range len(m) { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t\t_ = i\n\t}\n\n\tvar x struct {\n\t\tMap map[int]int\n\t}\n\tx.Map = make(map[int]int)\n\tfor x.Map[1] = range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor _, x.Map[2] = range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n\n\tfor k := range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t\t_ = k\n\t}\n\n\tfor _, v := range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t\t_ = v\n\t}\n\n\tfor range x.Map { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Keys`\n\t}\n\n\tfor i, k := range maps.Keys(m) { // ok: this can't be straightforwardly rewritten\n\t\t_, _ = i, k\n\t}\n\n\tfor _, _ = range m { // want `unnecessary and inefficient call of golang.org/x/exp/maps.Values`\n\t}\n}\n\n-- exp/go.mod --\nmodule golang.org/x/exp\n\ngo 1.24\n\n-- exp/maps/maps.go --\npackage maps\n\nfunc Keys[M ~map[K]V, K comparable, V any](m M) []K {\n\tr := make([]K, 0, len(m))\n\tfor k := range m {\n\t\tr = append(r, k)\n\t}\n\treturn r\n}\n\nfunc Values[M ~map[K]V, K comparable, V any](m M) []V {\n\tr := make([]V, 0, len(m))\n\tfor _, v := range m {\n\t\tr = append(r, v)\n\t}\n\treturn r\n}"
  },
  {
    "path": "gopls/internal/analysis/maprange/testdata/old.txtar",
    "content": "Test of fixing redundant calls to maps.Keys and maps.Values\n(both stdlib \"maps\" and \"golang.org/x/exp/maps\") for Go 1.21,\nbefore range over int made suggesting a fix for a rare case easier.\n\n-- go.mod --\nmodule maprange\n\nrequire golang.org/x/exp v0.0.0\n\nreplace golang.org/x/exp => ./exp\n\ngo 1.21\n\n-- old.go --\npackage old\n\nimport \"golang.org/x/exp/maps\"\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor i := range maps.Keys(m) { // want `likely incorrect use of golang.org/x/exp/maps.Keys \\(returns a slice\\)`\n\t\t_ = i\n\t}\n}\n\n-- old.go.golden --\npackage old\n\nimport \"golang.org/x/exp/maps\"\n\nfunc _() {\n\tm := make(map[int]int)\n\n\tfor i := range maps.Keys(m) { // want `likely incorrect use of golang.org/x/exp/maps.Keys \\(returns a slice\\)`\n\t\t_ = i\n\t}\n}\n\n-- exp/go.mod --\nmodule golang.org/x/exp\n\ngo 1.21\n\n-- exp/maps/maps.go --\npackage maps\n\nfunc Keys[M ~map[K]V, K comparable, V any](m M) []K {\n\tr := make([]K, 0, len(m))\n\tfor k := range m {\n\t\tr = append(r, k)\n\t}\n\treturn r\n}\n\nfunc Values[M ~map[K]V, K comparable, V any](m M) []V {\n\tr := make([]V, 0, len(m))\n\tfor _, v := range m {\n\t\tr = append(r, v)\n\t}\n\treturn r\n}"
  },
  {
    "path": "gopls/internal/analysis/modernize/cmd/modernize/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The modernize command suggests (or, with -fix, applies) fixes that\n// clarify Go code by using more modern features.\n//\n// See [golang.org/x/tools/go/analysis/passes/modernize] for details.\n//\n// Deprecated: use 'go run\n// golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize' instead. In\n// due course the modernizer suite will be accessed through \"go fix\";\n// see https://go.dev/issue/71859.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/passes/modernize\"\n)\n\nfunc main() { multichecker.Main(modernize.Suite...) }\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/doc.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package nonewvars defines an Analyzer that applies suggested fixes\n// to errors of the type \"no new variables on left side of :=\".\n//\n// # Analyzer nonewvars\n//\n// nonewvars: suggested fixes for \"no new vars on left side of :=\"\n//\n// This checker provides suggested fixes for type errors of the\n// type \"no new vars on left side of :=\". For example:\n//\n//\tz := 1\n//\tz := 2\n//\n// will turn into\n//\n//\tz := 1\n//\tz = 2\npackage nonewvars\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/nonewvars.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package nonewvars defines an Analyzer that applies suggested fixes\n// to errors of the type \"no new variables on left side of :=\".\npackage nonewvars\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"nonewvars\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"nonewvars\"),\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tfor _, typeErr := range pass.TypeErrors {\n\t\tif typeErr.Msg != \"no new variables on left side of :=\" {\n\t\t\tcontinue // irrelevant error\n\t\t}\n\t\t_, start, end, ok := typesinternal.ErrorCodeStartEnd(typeErr)\n\t\tif !ok {\n\t\t\tcontinue // can't get position info\n\t\t}\n\t\tcurErr, ok := inspect.Root().FindByPos(start, end)\n\t\tif !ok {\n\t\t\tcontinue // can't find errant node\n\t\t}\n\n\t\t// Find enclosing assignment (which may be curErr itself).\n\t\tassign, _ := cursorutil.FirstEnclosing[*ast.AssignStmt](curErr)\n\t\tif assign == nil {\n\t\t\tcontinue // no enclosing assignment\n\t\t}\n\t\tif assign.Tok != token.DEFINE {\n\t\t\tcontinue // not a := statement\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     assign.TokPos,\n\t\t\tEnd:     assign.TokPos + token.Pos(len(\":=\")),\n\t\t\tMessage: typeErr.Msg,\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Change ':=' to '='\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos: assign.TokPos,\n\t\t\t\t\tEnd: assign.TokPos + token.Pos(len(\":\")),\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/nonewvars_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nonewvars_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/nonewvars\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, nonewvars.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nonewvars\n\nimport \"log\"\n\nfunc x() {\n\tz := 1\n\tz := 2 // want \"no new variables on left side of :=\"\n\n\t_, z := 3, 100 // want \"no new variables on left side of :=\"\n\n\tlog.Println(z)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage nonewvars\n\nimport \"log\"\n\nfunc x() {\n\tz := 1\n\tz = 2 // want \"no new variables on left side of :=\"\n\n\t_, z = 3, 100 // want \"no new variables on left side of :=\"\n\n\tlog.Println(z)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/testdata/src/typeparams/a.go",
    "content": "package nonewvars\n\nfunc hello[T any]() int {\n\tvar z T\n\tz := 1 // want \"no new variables on left side of :=\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/nonewvars/testdata/src/typeparams/a.go.golden",
    "content": "package nonewvars\n\nfunc hello[T any]() int {\n\tvar z T\n\tz = 1 // want \"no new variables on left side of :=\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package noresultvalues defines an Analyzer that applies suggested fixes\n// to errors of the type \"no result values expected\".\n//\n// # Analyzer noresultvalues\n//\n// noresultvalues: suggested fixes for unexpected return values\n//\n// This checker provides suggested fixes for type errors of the\n// type \"no result values expected\" or \"too many return values\".\n// For example:\n//\n//\tfunc z() { return nil }\n//\n// will turn into\n//\n//\tfunc z() { return }\npackage noresultvalues\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/noresultvalues.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage noresultvalues\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strings\"\n\n\t_ \"embed\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"noresultvalues\",\n\tDoc:              analyzerutil.MustExtractDoc(doc, \"noresultvalues\"),\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRun:              run,\n\tRunDespiteErrors: true,\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvalues\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tfor _, typErr := range pass.TypeErrors {\n\t\tif !fixesError(typErr.Msg) {\n\t\t\tcontinue // irrelevant error\n\t\t}\n\t\t_, start, end, ok := typesinternal.ErrorCodeStartEnd(typErr)\n\t\tif !ok {\n\t\t\tcontinue // can't get position info\n\t\t}\n\t\tcurErr, ok := inspect.Root().FindByPos(start, end)\n\t\tif !ok {\n\t\t\tcontinue // can't find errant node\n\t\t}\n\t\t// Find first enclosing return statement, if any.\n\t\tret, _ := cursorutil.FirstEnclosing[*ast.ReturnStmt](curErr)\n\t\tif ret != nil {\n\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\tPos:     start,\n\t\t\t\tEnd:     end,\n\t\t\t\tMessage: typErr.Msg,\n\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\tMessage: \"Delete return values\",\n\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\tPos: ret.Pos() + token.Pos(len(\"return\")),\n\t\t\t\t\t\tEnd: ret.End(),\n\t\t\t\t\t}},\n\t\t\t\t}},\n\t\t\t})\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc fixesError(msg string) bool {\n\treturn msg == \"no result values expected\" ||\n\t\tstrings.HasPrefix(msg, \"too many return values\") && strings.Contains(msg, \"want ()\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/noresultvalues_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage noresultvalues_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/noresultvalues\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, noresultvalues.Analyzer, \"a\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage noresultvalues\n\nfunc x() { return nil } // want `no result values expected|too many return values`\n\nfunc y() { return nil, \"hello\" } // want `no result values expected|too many return values`\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage noresultvalues\n\nfunc x() { return } // want `no result values expected|too many return values`\n\nfunc y() { return } // want `no result values expected|too many return values`\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/testdata/src/typeparams/a.go",
    "content": "package noresult\n\nfunc hello[T any]() {\n\tvar z T\n\treturn z // want `no result values expected|too many return values`\n}\n"
  },
  {
    "path": "gopls/internal/analysis/noresultvalues/testdata/src/typeparams/a.go.golden",
    "content": "package noresult\n\nfunc hello[T any]() {\n\tvar z T\n\treturn // want `no result values expected|too many return values`\n}\n"
  },
  {
    "path": "gopls/internal/analysis/recursiveiter/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package recursiveiter defines an Analyzer that checks for mistakes\n// in iterators for recursive data structures.\n//\n// # Analyzer recursiveiter\n//\n// recursiveiter: check for inefficient recursive iterators\n//\n// This analyzer reports when a function that returns an iterator\n// (iter.Seq or iter.Seq2) calls itself as the operand of a range\n// statement, as this is inefficient.\n//\n// When implementing an iterator (e.g. iter.Seq[T]) for a recursive\n// data type such as a tree or linked list, it is tempting to\n// recursively range over the iterator for each child element.\n//\n// Here's an example of a naive iterator over a binary tree:\n//\n//\ttype tree struct {\n//\t\tvalue       int\n//\t\tleft, right *tree\n//\t}\n//\n//\tfunc (t *tree) All() iter.Seq[int] {\n//\t\treturn func(yield func(int) bool) {\n//\t\t\tif t != nil {\n//\t\t\t\tfor elem := range t.left.All() { // \"inefficient recursive iterator\"\n//\t\t\t\t\tif !yield(elem) {\n//\t\t\t\t\t\treturn\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\t\t\t\tif !yield(t.value) {\n//\t\t\t\t\treturn\n//\t\t\t\t}\n//\t\t\t\tfor elem := range t.right.All() { // \"inefficient recursive iterator\"\n//\t\t\t\t\tif !yield(elem) {\n//\t\t\t\t\t\treturn\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\t}\n//\n// Though it correctly enumerates the elements of the tree, it hides a\n// significant performance problem--two, in fact. Consider a balanced\n// tree of N nodes. Iterating the root node will cause All to be\n// called once on every node of the tree. This results in a chain of\n// nested active range-over-func statements when yield(t.value) is\n// called on a leaf node.\n//\n// The first performance problem is that each range-over-func\n// statement must typically heap-allocate a variable, so iteration of\n// the tree allocates as many variables as there are elements in the\n// tree, for a total of O(N) allocations, all unnecessary.\n//\n// The second problem is that each call to yield for a leaf of the\n// tree causes each of the enclosing range loops to receive a value,\n// which they then immediately pass on to their respective yield\n// function. This results in a chain of log(N) dynamic yield calls per\n// element, a total of O(N*log N) dynamic calls overall, when only\n// O(N) are necessary.\n//\n// A better implementation strategy for recursive iterators is to\n// first define the \"every\" operator for your recursive data type,\n// where every(f) reports whether an arbitrary predicate f(x) is true\n// for every element x in the data type. For our tree, the every\n// function would be:\n//\n//\tfunc (t *tree) every(f func(int) bool) bool {\n//\t\treturn t == nil ||\n//\t\t\tt.left.every(f) && f(t.value) && t.right.every(f)\n//\t}\n//\n// For example, this use of the every operator prints whether every\n// element in the tree is an even number:\n//\n//\teven := func(x int) bool { return x&1 == 0 }\n//\tprintln(t.every(even))\n//\n// Then the iterator can be simply expressed as a trivial wrapper\n// around the every operator:\n//\n//\tfunc (t *tree) All() iter.Seq[int] {\n//\t\treturn func(yield func(int) bool) {\n//\t\t\t_ = t.every(yield)\n//\t\t}\n//\t}\n//\n// In effect, tree.All computes whether yield returns true for each\n// element, short-circuiting if it ever returns false, then discards\n// the final boolean result.\n//\n// This has much better performance characteristics: it makes one\n// dynamic call per element of the tree, and it doesn't heap-allocate\n// anything. It is also clearer.\npackage recursiveiter\n"
  },
  {
    "path": "gopls/internal/analysis/recursiveiter/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The recursiveiter command applies the yield analyzer to the\n// specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/recursiveiter\"\n)\n\nfunc main() { singlechecker.Main(recursiveiter.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/recursiveiter/recursiveiter.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage recursiveiter\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"recursiveiter\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"recursiveiter\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer, typeindexanalyzer.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/recursiveiter\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tvar (\n\t\tinspector = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tindex     = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t\tinfo      = pass.TypesInfo\n\t\titerSeq   = index.Object(\"iter\", \"Seq\")\n\t\titerSeq2  = index.Object(\"iter\", \"Seq2\")\n\t)\n\tif iterSeq == nil || iterSeq2 == nil {\n\t\treturn nil, nil // fast path: no iterators\n\t}\n\n\t// Search for a function or method f that returns an iter.Seq\n\t// or Seq2 and calls itself recursively within a range stmt:\n\t//\n\t// func f(...) iter.Seq[E] {\n\t//\treturn func(yield func(E) bool) {\n\t//\t\t...\n\t//\t\tfor range f(...) { ... }\n\t// \t}\n\t// }\n\tfor curDecl := range inspector.Root().Preorder((*ast.FuncDecl)(nil)) {\n\t\tdecl := curDecl.Node().(*ast.FuncDecl)\n\t\tfn := info.Defs[decl.Name].(*types.Func)\n\t\tresults := fn.Signature().Results()\n\t\tif results.Len() != 1 {\n\t\t\tcontinue // result not a singleton\n\t\t}\n\t\tretType, ok := results.At(0).Type().(*types.Named)\n\t\tif !ok {\n\t\t\tcontinue // result not a named type\n\t\t}\n\t\tswitch retType.Origin().Obj() {\n\t\tcase iterSeq, iterSeq2:\n\t\tdefault:\n\t\t\tcontinue // result not iter.Seq{,2}\n\t\t}\n\t\t// Have: a FuncDecl that returns an iterator.\n\t\tfor curRet := range curDecl.Preorder((*ast.ReturnStmt)(nil)) {\n\t\t\tret := curRet.Node().(*ast.ReturnStmt)\n\t\t\tif len(ret.Results) != 1 || !is[*ast.FuncLit](ret.Results[0]) {\n\t\t\t\tcontinue // not \"return func(){...}\"\n\t\t\t}\n\t\t\tfor curRange := range curRet.Preorder((*ast.RangeStmt)(nil)) {\n\t\t\t\trng := curRange.Node().(*ast.RangeStmt)\n\t\t\t\tcall, ok := rng.X.(*ast.CallExpr)\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif typeutil.StaticCallee(info, call) == fn {\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:     rng.Range,\n\t\t\t\t\t\tEnd:     rng.X.End(),\n\t\t\t\t\t\tMessage: fmt.Sprintf(\"inefficient recursion in iterator %s\", fn.Name()),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n"
  },
  {
    "path": "gopls/internal/analysis/recursiveiter/recursiveiter_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage recursiveiter_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/recursiveiter\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, recursiveiter.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/recursiveiter/testdata/src/a/a.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage recursiveiter\n\nimport \"iter\"\n\ntype cons struct {\n\tcar int\n\tcdr *cons\n}\n\nfunc (cons *cons) All() iter.Seq[int] {\n\treturn func(yield func(int) bool) {\n\t\t// The correct recursion is:\n\t\t//   func (cons *cons) all(f func(int) bool) {\n\t\t//     return cons == nil || yield(cons.car) && cons.cdr.all()\n\t\t//   }\n\t\t// then:\n\t\t//   _ = cons.all(yield)\n\t\tif cons != nil && yield(cons.car) {\n\t\t\tfor elem := range cons.All() { // want \"inefficient recursion in iterator All\"\n\t\t\t\tif !yield(elem) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package simplifycompositelit defines an Analyzer that simplifies composite literals.\n// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go\n// https://golang.org/cmd/gofmt/#hdr-The_simplify_command\n//\n// # Analyzer simplifycompositelit\n//\n// simplifycompositelit: check for composite literal simplifications\n//\n// An array, slice, or map composite literal of the form:\n//\n//\t[]T{T{}, T{}}\n//\n// will be simplified to:\n//\n//\t[]T{{}, {}}\n//\n// This is one of the simplifications that \"gofmt -s\" applies.\n//\n// This analyzer ignores generated code.\npackage simplifycompositelit\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package simplifycompositelit defines an Analyzer that simplifies composite literals.\n// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go\n// https://golang.org/cmd/gofmt/#hdr-The_simplify_command\npackage simplifycompositelit\n\nimport (\n\t\"bytes\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"simplifycompositelit\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"simplifycompositelit\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Gather information whether file is generated or not\n\tgenerated := make(map[*token.File]bool)\n\tfor _, file := range pass.Files {\n\t\tif ast.IsGenerated(file) {\n\t\t\tgenerated[pass.Fset.File(file.FileStart)] = true\n\t\t}\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tif _, ok := generated[pass.Fset.File(n.Pos())]; ok {\n\t\t\treturn // skip checking if it's generated code\n\t\t}\n\n\t\texpr := n.(*ast.CompositeLit)\n\n\t\touter := expr\n\t\tvar keyType, eltType ast.Expr\n\t\tswitch typ := outer.Type.(type) {\n\t\tcase *ast.ArrayType:\n\t\t\teltType = typ.Elt\n\t\tcase *ast.MapType:\n\t\t\tkeyType = typ.Key\n\t\t\teltType = typ.Value\n\t\t}\n\n\t\tif eltType == nil {\n\t\t\treturn\n\t\t}\n\t\tvar ktyp reflect.Value\n\t\tif keyType != nil {\n\t\t\tktyp = reflect.ValueOf(keyType)\n\t\t}\n\t\ttyp := reflect.ValueOf(eltType)\n\t\tfor _, x := range outer.Elts {\n\t\t\t// look at value of indexed/named elements\n\t\t\tif t, ok := x.(*ast.KeyValueExpr); ok {\n\t\t\t\tif keyType != nil {\n\t\t\t\t\tsimplifyLiteral(pass, ktyp, keyType, t.Key)\n\t\t\t\t}\n\t\t\t\tx = t.Value\n\t\t\t}\n\t\t\tsimplifyLiteral(pass, typ, eltType, x)\n\t\t}\n\t})\n\treturn nil, nil\n}\n\nfunc simplifyLiteral(pass *analysis.Pass, typ reflect.Value, astType, x ast.Expr) {\n\t// if the element is a composite literal and its literal type\n\t// matches the outer literal's element type exactly, the inner\n\t// literal type may be omitted\n\tif inner, ok := x.(*ast.CompositeLit); ok && match(typ, reflect.ValueOf(inner.Type)) {\n\t\tvar b bytes.Buffer\n\t\tprinter.Fprint(&b, pass.Fset, inner.Type) // ignore error\n\t\tcreateDiagnostic(pass, inner.Type.Pos(), inner.Type.End(), b.String())\n\t}\n\t// if the outer literal's element type is a pointer type *T\n\t// and the element is & of a composite literal of type T,\n\t// the inner &T may be omitted.\n\tif ptr, ok := astType.(*ast.StarExpr); ok {\n\t\tif addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {\n\t\t\tif inner, ok := addr.X.(*ast.CompositeLit); ok {\n\t\t\t\tif match(reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {\n\t\t\t\t\tvar b bytes.Buffer\n\t\t\t\t\tprinter.Fprint(&b, pass.Fset, inner.Type) // ignore error\n\t\t\t\t\t// Account for the & by subtracting 1 from typ.Pos().\n\t\t\t\t\tcreateDiagnostic(pass, inner.Type.Pos()-1, inner.Type.End(), \"&\"+b.String())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc createDiagnostic(pass *analysis.Pass, start, end token.Pos, typ string) {\n\tpass.Report(analysis.Diagnostic{\n\t\tPos:     start,\n\t\tEnd:     end,\n\t\tMessage: \"redundant type from array, slice, or map composite literal\",\n\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\tMessage: fmt.Sprintf(\"Remove '%s'\", typ),\n\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\tPos:     start,\n\t\t\t\tEnd:     end,\n\t\t\t\tNewText: []byte{},\n\t\t\t}},\n\t\t}},\n\t})\n}\n\n// match reports whether pattern matches val,\n// recording wildcard submatches in m.\n// If m == nil, match checks whether pattern == val.\n// from https://github.com/golang/go/blob/26154f31ad6c801d8bad5ef58df1e9263c6beec7/src/cmd/gofmt/rewrite.go#L160\nfunc match(pattern, val reflect.Value) bool {\n\t// Otherwise, pattern and val must match recursively.\n\tif !pattern.IsValid() || !val.IsValid() {\n\t\treturn !pattern.IsValid() && !val.IsValid()\n\t}\n\tif pattern.Type() != val.Type() {\n\t\treturn false\n\t}\n\n\t// Special cases.\n\tswitch pattern.Type() {\n\tcase identType:\n\t\t// For identifiers, only the names need to match\n\t\t// (and none of the other *ast.Object information).\n\t\t// This is a common case, handle it all here instead\n\t\t// of recursing down any further via reflection.\n\t\tp := pattern.Interface().(*ast.Ident)\n\t\tv := val.Interface().(*ast.Ident)\n\t\treturn p == nil && v == nil || p != nil && v != nil && p.Name == v.Name\n\tcase objectPtrType, positionType:\n\t\t// object pointers and token positions always match\n\t\treturn true\n\tcase callExprType:\n\t\t// For calls, the Ellipsis fields (token.Position) must\n\t\t// match since that is how f(x) and f(x...) are different.\n\t\t// Check them here but fall through for the remaining fields.\n\t\tp := pattern.Interface().(*ast.CallExpr)\n\t\tv := val.Interface().(*ast.CallExpr)\n\t\tif p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tp := reflect.Indirect(pattern)\n\tv := reflect.Indirect(val)\n\tif !p.IsValid() || !v.IsValid() {\n\t\treturn !p.IsValid() && !v.IsValid()\n\t}\n\n\tswitch p.Kind() {\n\tcase reflect.Slice:\n\t\tif p.Len() != v.Len() {\n\t\t\treturn false\n\t\t}\n\t\tfor i := 0; i < p.Len(); i++ {\n\t\t\tif !match(p.Index(i), v.Index(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase reflect.Struct:\n\t\tfor i := 0; i < p.NumField(); i++ {\n\t\t\tif !match(p.Field(i), v.Field(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase reflect.Interface:\n\t\treturn match(p.Elem(), v.Elem())\n\t}\n\n\t// Handle token integers, etc.\n\treturn p.Interface() == v.Interface()\n}\n\n// Values/types for special cases.\nvar (\n\tidentType     = reflect.TypeFor[*ast.Ident]()\n\tobjectPtrType = reflect.TypeFor[*ast.Object]()\n\tpositionType  = reflect.TypeFor[token.Pos]()\n\tcallExprType  = reflect.TypeFor[*ast.CallExpr]()\n)\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/simplifycompositelit_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage simplifycompositelit_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifycompositelit\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, simplifycompositelit.Analyzer, \"a\", \"generatedcode\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\ntype T struct {\n\tx, y int\n}\n\ntype T2 struct {\n\tw, z int\n}\n\nvar _ = [42]T{\n\tT{},     // want \"redundant type from array, slice, or map composite literal\"\n\tT{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\tT{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [...]T{\n\tT{},     // want \"redundant type from array, slice, or map composite literal\"\n\tT{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\tT{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []T{\n\tT{},     // want \"redundant type from array, slice, or map composite literal\"\n\tT{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\tT{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []T{\n\tT{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10:  T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20:  T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []struct {\n\tx, y int\n}{\n\tstruct{ x, y int }{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10:                   struct{ x, y int }{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20:                   struct{ x, y int }{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []interface{}{\n\tT{},\n\t10: T{1, 2},\n\t20: T{3, 4},\n}\n\nvar _ = [][]int{\n\t[]int{},     // want \"redundant type from array, slice, or map composite literal\"\n\t[]int{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [][]int{\n\t([]int{}),\n\t([]int{1, 2}),\n\t[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [][][]int{\n\t[][]int{}, // want \"redundant type from array, slice, or map composite literal\"\n\t[][]int{ // want \"redundant type from array, slice, or map composite literal\"\n\t\t[]int{},           // want \"redundant type from array, slice, or map composite literal\"\n\t\t[]int{0, 1, 2, 3}, // want \"redundant type from array, slice, or map composite literal\"\n\t\t[]int{4, 5},       // want \"redundant type from array, slice, or map composite literal\"\n\t},\n}\n\nvar _ = map[string]T{\n\t\"foo\": T{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]struct {\n\tx, y int\n}{\n\t\"foo\": struct{ x, y int }{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": struct{ x, y int }{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": struct{ x, y int }{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]interface{}{\n\t\"foo\": T{},\n\t\"bar\": T{1, 2},\n\t\"bal\": T{3, 4},\n}\n\nvar _ = map[string][]int{\n\t\"foo\": []int{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": []int{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": []int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string][]int{\n\t\"foo\": ([]int{}),\n\t\"bar\": ([]int{1, 2}),\n\t\"bal\": []int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\ntype Point struct {\n\ta int\n\tb int\n}\n\ntype Piece struct {\n\ta int\n\tb int\n\tc Point\n\td []Point\n\te *Point\n\tf *Point\n}\n\n// from exp/4s/data.go\nvar pieces3 = []Piece{\n\tPiece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\tPiece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\tPiece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\tPiece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [42]*T{\n\t&T{},     // want \"redundant type from array, slice, or map composite literal\"\n\t&T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t&T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [...]*T{\n\t&T{},     // want \"redundant type from array, slice, or map composite literal\"\n\t&T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t&T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*T{\n\t&T{},     // want \"redundant type from array, slice, or map composite literal\"\n\t&T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t&T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*T{\n\t&T{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10:   &T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20:   &T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*struct {\n\tx, y int\n}{\n\t&struct{ x, y int }{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10:                    &struct{ x, y int }{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20:                    &struct{ x, y int }{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []interface{}{\n\t&T{},\n\t10: &T{1, 2},\n\t20: &T{3, 4},\n}\n\nvar _ = []*[]int{\n\t&[]int{},     // want \"redundant type from array, slice, or map composite literal\"\n\t&[]int{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t&[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*[]int{\n\t(&[]int{}),\n\t(&[]int{1, 2}),\n\t&[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*[]*[]int{\n\t&[]*[]int{}, // want \"redundant type from array, slice, or map composite literal\"\n\t&[]*[]int{ // want \"redundant type from array, slice, or map composite literal\"\n\t\t&[]int{},           // want \"redundant type from array, slice, or map composite literal\"\n\t\t&[]int{0, 1, 2, 3}, // want \"redundant type from array, slice, or map composite literal\"\n\t\t&[]int{4, 5},       // want \"redundant type from array, slice, or map composite literal\"\n\t},\n}\n\nvar _ = map[string]*T{\n\t\"foo\": &T{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": &T{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": &T{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]*struct {\n\tx, y int\n}{\n\t\"foo\": &struct{ x, y int }{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": &struct{ x, y int }{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": &struct{ x, y int }{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]interface{}{\n\t\"foo\": &T{},\n\t\"bar\": &T{1, 2},\n\t\"bal\": &T{3, 4},\n}\n\nvar _ = map[string]*[]int{\n\t\"foo\": &[]int{},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": &[]int{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": &[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]*[]int{\n\t\"foo\": (&[]int{}),\n\t\"bar\": (&[]int{1, 2}),\n\t\"bal\": &[]int{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar pieces4 = []*Piece{\n\t&Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t&Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t&Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t&Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[T]T2{\n\tT{1, 2}: T2{3, 4}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\tT{5, 6}: T2{7, 8}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[*T]*T2{\n\t&T{1, 2}: &T2{3, 4}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t&T{5, 6}: &T2{7, 8}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\ntype T struct {\n\tx, y int\n}\n\ntype T2 struct {\n\tw, z int\n}\n\nvar _ = [42]T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [...]T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []T{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10: {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20: {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []struct {\n\tx, y int\n}{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10: {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20: {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []interface{}{\n\tT{},\n\t10: T{1, 2},\n\t20: T{3, 4},\n}\n\nvar _ = [][]int{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [][]int{\n\t([]int{}),\n\t([]int{1, 2}),\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [][][]int{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t{ // want \"redundant type from array, slice, or map composite literal\"\n\t\t{},           // want \"redundant type from array, slice, or map composite literal\"\n\t\t{0, 1, 2, 3}, // want \"redundant type from array, slice, or map composite literal\"\n\t\t{4, 5},       // want \"redundant type from array, slice, or map composite literal\"\n\t},\n}\n\nvar _ = map[string]T{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]struct {\n\tx, y int\n}{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]interface{}{\n\t\"foo\": T{},\n\t\"bar\": T{1, 2},\n\t\"bal\": T{3, 4},\n}\n\nvar _ = map[string][]int{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string][]int{\n\t\"foo\": ([]int{}),\n\t\"bar\": ([]int{1, 2}),\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\ntype Point struct {\n\ta int\n\tb int\n}\n\ntype Piece struct {\n\ta int\n\tb int\n\tc Point\n\td []Point\n\te *Point\n\tf *Point\n}\n\n// from exp/4s/data.go\nvar pieces3 = []Piece{\n\t{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [42]*T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = [...]*T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*T{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*T{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10: {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20: {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*struct {\n\tx, y int\n}{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t10: {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t20: {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []interface{}{\n\t&T{},\n\t10: &T{1, 2},\n\t20: &T{3, 4},\n}\n\nvar _ = []*[]int{\n\t{},     // want \"redundant type from array, slice, or map composite literal\"\n\t{1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*[]int{\n\t(&[]int{}),\n\t(&[]int{1, 2}),\n\t{3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = []*[]*[]int{\n\t{}, // want \"redundant type from array, slice, or map composite literal\"\n\t{ // want \"redundant type from array, slice, or map composite literal\"\n\t\t{},           // want \"redundant type from array, slice, or map composite literal\"\n\t\t{0, 1, 2, 3}, // want \"redundant type from array, slice, or map composite literal\"\n\t\t{4, 5},       // want \"redundant type from array, slice, or map composite literal\"\n\t},\n}\n\nvar _ = map[string]*T{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]*struct {\n\tx, y int\n}{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]interface{}{\n\t\"foo\": &T{},\n\t\"bar\": &T{1, 2},\n\t\"bal\": &T{3, 4},\n}\n\nvar _ = map[string]*[]int{\n\t\"foo\": {},     // want \"redundant type from array, slice, or map composite literal\"\n\t\"bar\": {1, 2}, // want \"redundant type from array, slice, or map composite literal\"\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[string]*[]int{\n\t\"foo\": (&[]int{}),\n\t\"bar\": (&[]int{1, 2}),\n\t\"bal\": {3, 4}, // want \"redundant type from array, slice, or map composite literal\"\n}\n\nvar pieces4 = []*Piece{\n\t{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[T]T2{\n\t{1, 2}: {3, 4}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{5, 6}: {7, 8}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n\nvar _ = map[*T]*T2{\n\t{1, 2}: {3, 4}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n\t{5, 6}: {7, 8}, // want \"redundant type from array, slice, or map composite literal\" \"redundant type from array, slice, or map composite literal\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\ntype T struct {\n\tx, y int\n}\n\nvar _ = [42]T{\n\tT{}, // No simplification fix is offered in generated code.\n\tT{1, 2}, // No simplification fix is offered in generated code.\n\tT{3, 4}, // No simplification fix is offered in generated code.\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go.golden",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\ntype T struct {\n\tx, y int\n}\n\nvar _ = [42]T{\n\tT{}, // No simplification fix is offered in generated code.\n\tT{1, 2}, // No simplification fix is offered in generated code.\n\tT{3, 4}, // No simplification fix is offered in generated code.\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package simplifyrange defines an Analyzer that simplifies range statements.\n// https://golang.org/cmd/gofmt/#hdr-The_simplify_command\n// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go\n//\n// # Analyzer simplifyrange\n//\n// simplifyrange: check for range statement simplifications\n//\n// A range of the form:\n//\n//\tfor x, _ = range v {...}\n//\n// will be simplified to:\n//\n//\tfor x = range v {...}\n//\n// A range of the form:\n//\n//\tfor _ = range v {...}\n//\n// will be simplified to:\n//\n//\tfor range v {...}\n//\n// This is one of the simplifications that \"gofmt -s\" applies.\n//\n// This analyzer ignores generated code.\npackage simplifyrange\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/simplifyrange.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage simplifyrange\n\nimport (\n\t_ \"embed\"\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"simplifyrange\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"simplifyrange\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Gather information whether file is generated or not\n\tgenerated := make(map[*token.File]bool)\n\tfor _, file := range pass.Files {\n\t\tif ast.IsGenerated(file) {\n\t\t\tgenerated[pass.Fset.File(file.FileStart)] = true\n\t\t}\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.RangeStmt)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\trng := n.(*ast.RangeStmt)\n\n\t\tkblank := isBlank(rng.Key)\n\t\tvblank := isBlank(rng.Value)\n\t\tvar start, end token.Pos\n\t\tswitch {\n\t\tcase kblank && (rng.Value == nil || vblank):\n\t\t\t// for _    = range x {}\n\t\t\t// for _, _ = range x {}\n\t\t\t//     ^^^^^^^\n\t\t\tstart, end = rng.Key.Pos(), rng.Range\n\n\t\tcase vblank:\n\t\t\t// for k, _ := range x {}\n\t\t\t//      ^^^\n\t\t\tstart, end = rng.Key.End(), rng.Value.End()\n\n\t\tdefault:\n\t\t\treturn\n\t\t}\n\n\t\tif generated[pass.Fset.File(n.Pos())] {\n\t\t\treturn\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     start,\n\t\t\tEnd:     end,\n\t\t\tMessage: \"simplify range expression\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Remove empty value\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos: start,\n\t\t\t\t\tEnd: end,\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t})\n\treturn nil, nil\n}\n\nfunc isBlank(e ast.Expr) bool {\n\tid, ok := e.(*ast.Ident)\n\treturn ok && id.Name == \"_\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/simplifyrange_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage simplifyrange_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifyrange\"\n)\n\nfunc Test(t *testing.T) {\n\tanalysistest.RunWithSuggestedFixes(t, analysistest.TestData(), simplifyrange.Analyzer,\n\t\t\"a\",\n\t\t\"generatedcode\",\n\t\t\"rangeoverfunc\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nimport \"log\"\n\nfunc m() {\n\tmaps := make(map[string]string)\n\tfor k, _ := range maps { // want \"simplify range expression\"\n\t\tlog.Println(k)\n\t}\n\tfor _ = range maps { // want \"simplify range expression\"\n\t}\n\tfor _, _ = range maps { // want \"simplify range expression\"\n\t}\n\tfor _, v := range maps { // nope\n\t\tprintln(v)\n\t}\n\tfor range maps { // nope\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nimport \"log\"\n\nfunc m() {\n\tmaps := make(map[string]string)\n\tfor k := range maps { // want \"simplify range expression\"\n\t\tlog.Println(k)\n\t}\n\tfor range maps { // want \"simplify range expression\"\n\t}\n\tfor range maps { // want \"simplify range expression\"\n\t}\n\tfor _, v := range maps { // nope\n\t\tprintln(v)\n\t}\n\tfor range maps { // nope\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\nimport \"log\"\n\nfunc mgeneratedcode() {\n\tmaps := make(map[string]string)\n\tfor k, _ := range maps { // No simplification fix is offered in generated code.\n\t\tlog.Println(k)\n\t}\n\tfor _ = range maps { // No simplification fix is offered in generated code.\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go.golden",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\nimport \"log\"\n\nfunc mgeneratedcode() {\n\tmaps := make(map[string]string)\n\tfor k, _ := range maps { // No simplification fix is offered in generated code.\n\t\tlog.Println(k)\n\t}\n\tfor _ = range maps { // No simplification fix is offered in generated code.\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/rangeoverfunc/rangeoverfunc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nimport \"iter\"\n\nfunc _(seq1 iter.Seq[int], seq2 iter.Seq2[int, int]) {\n\t// range-over-func is (once again) consistent with other types (#65236)\n\tfor _ = range \"\" { // want \"simplify range expression\"\n\t}\n\tfor _ = range seq1 { // want `simplify range expression`\n\t}\n\tfor _, v := range seq2 { // silence\n\t\t_ = v\n\t}\n\tfor _, _ = range seq2 { // want `simplify range expression`\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyrange/testdata/src/rangeoverfunc/rangeoverfunc.go.golden",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nimport \"iter\"\n\nfunc _(seq1 iter.Seq[int], seq2 iter.Seq2[int, int]) {\n\t// range-over-func is (once again) consistent with other types (#65236)\n\tfor range \"\" { // want \"simplify range expression\"\n\t}\n\tfor range seq1 { // want `simplify range expression`\n\t}\n\tfor _, v := range seq2 { // silence\n\t\t_ = v\n\t}\n\tfor range seq2 { // want `simplify range expression`\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package simplifyslice defines an Analyzer that simplifies slice statements.\n// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go\n// https://golang.org/cmd/gofmt/#hdr-The_simplify_command\n//\n// # Analyzer simplifyslice\n//\n// simplifyslice: check for slice simplifications\n//\n// A slice expression of the form:\n//\n//\ts[a:len(s)]\n//\n// will be simplified to:\n//\n//\ts[a:]\n//\n// This is one of the simplifications that \"gofmt -s\" applies.\n//\n// This analyzer ignores generated code.\npackage simplifyslice\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/simplifyslice.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage simplifyslice\n\nimport (\n\t\"bytes\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"simplifyslice\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"simplifyslice\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice\",\n}\n\n// Note: We could also simplify slice expressions of the form s[0:b] to s[:b]\n//       but we leave them as is since sometimes we want to be very explicit\n//       about the lower bound.\n// An example where the 0 helps:\n//       x, y, z := b[0:2], b[2:4], b[4:6]\n// An example where it does not:\n//       x, y := b[:n], b[n:]\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// Gather information whether file is generated or not\n\tgenerated := make(map[*token.File]bool)\n\tfor _, file := range pass.Files {\n\t\tif ast.IsGenerated(file) {\n\t\t\tgenerated[pass.Fset.File(file.FileStart)] = true\n\t\t}\n\t}\n\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\tnodeFilter := []ast.Node{\n\t\t(*ast.SliceExpr)(nil),\n\t}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tif _, ok := generated[pass.Fset.File(n.Pos())]; ok {\n\t\t\treturn // skip checking if it's generated code\n\t\t}\n\n\t\texpr := n.(*ast.SliceExpr)\n\t\t// - 3-index slices always require the 2nd and 3rd index\n\t\tif expr.Max != nil {\n\t\t\treturn\n\t\t}\n\t\ts, ok := expr.X.(*ast.Ident)\n\t\t// the array/slice object is a single, resolved identifier\n\t\tif !ok || s.Obj == nil {\n\t\t\treturn\n\t\t}\n\t\tcall, ok := expr.High.(*ast.CallExpr)\n\t\t// the high expression is a function call with a single argument\n\t\tif !ok || len(call.Args) != 1 || call.Ellipsis.IsValid() {\n\t\t\treturn\n\t\t}\n\t\tfun, ok := call.Fun.(*ast.Ident)\n\t\t// the function called is \"len\" and it is not locally defined; and\n\t\t// because we don't have dot imports, it must be the predefined len()\n\t\tif !ok || fun.Name != \"len\" || fun.Obj != nil {\n\t\t\treturn\n\t\t}\n\t\targ, ok := call.Args[0].(*ast.Ident)\n\t\t// the len argument is the array/slice object\n\t\tif !ok || arg.Obj != s.Obj {\n\t\t\treturn\n\t\t}\n\t\tvar b bytes.Buffer\n\t\tprinter.Fprint(&b, pass.Fset, expr.High) // ignore error\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     expr.High.Pos(),\n\t\t\tEnd:     expr.High.End(),\n\t\t\tMessage: fmt.Sprintf(\"unneeded: %s\", b.String()),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: fmt.Sprintf(\"Remove '%s'\", b.String()),\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     expr.High.Pos(),\n\t\t\t\t\tEnd:     expr.High.End(),\n\t\t\t\t\tNewText: []byte{},\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t})\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/simplifyslice_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage simplifyslice_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifyslice\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, simplifyslice.Analyzer, \"a\", \"generatedcode\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/a/a.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\ts []int\n\tt struct {\n\t\ts []byte\n\t}\n\n\t_ = a[0:]\n\t_ = a[1:10]\n\t_ = a[2:len(a)] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[3:(len(a))]\n\t_ = a[len(a)-1 : len(a)] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[2:len(a):len(a)]\n\n\t_ = a[:]\n\t_ = a[:10]\n\t_ = a[:len(a)] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[:(len(a))]\n\t_ = a[:len(a)-1]\n\t_ = a[:len(a):len(a)]\n\n\t_ = s[0:]\n\t_ = s[1:10]\n\t_ = s[2:len(s)] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s[3:(len(s))]\n\t_ = s[len(a) : len(s)-1]\n\t_ = s[0:len(b)]\n\t_ = s[2:len(s):len(s)]\n\n\t_ = s[:]\n\t_ = s[:10]\n\t_ = s[:len(s)] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s[:(len(s))]\n\t_ = s[:len(s)-1]\n\t_ = s[:len(b)]\n\t_ = s[:len(s):len(s)]\n\n\t_ = t.s[0:]\n\t_ = t.s[1:10]\n\t_ = t.s[2:len(t.s)]\n\t_ = t.s[3:(len(t.s))]\n\t_ = t.s[len(a) : len(t.s)-1]\n\t_ = t.s[0:len(b)]\n\t_ = t.s[2:len(t.s):len(t.s)]\n\n\t_ = t.s[:]\n\t_ = t.s[:10]\n\t_ = t.s[:len(t.s)]\n\t_ = t.s[:(len(t.s))]\n\t_ = t.s[:len(t.s)-1]\n\t_ = t.s[:len(b)]\n\t_ = t.s[:len(t.s):len(t.s)]\n)\n\nfunc _() {\n\ts := s[0:len(s)] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s\n}\n\nfunc m() {\n\tmaps := []int{}\n\t_ = maps[1:len(maps)] // want \"unneeded: len\\\\(maps\\\\)\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/a/a.go.golden",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\ts []int\n\tt struct {\n\t\ts []byte\n\t}\n\n\t_ = a[0:]\n\t_ = a[1:10]\n\t_ = a[2:] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[3:(len(a))]\n\t_ = a[len(a)-1:] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[2:len(a):len(a)]\n\n\t_ = a[:]\n\t_ = a[:10]\n\t_ = a[:] // want \"unneeded: len\\\\(a\\\\)\"\n\t_ = a[:(len(a))]\n\t_ = a[:len(a)-1]\n\t_ = a[:len(a):len(a)]\n\n\t_ = s[0:]\n\t_ = s[1:10]\n\t_ = s[2:] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s[3:(len(s))]\n\t_ = s[len(a) : len(s)-1]\n\t_ = s[0:len(b)]\n\t_ = s[2:len(s):len(s)]\n\n\t_ = s[:]\n\t_ = s[:10]\n\t_ = s[:] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s[:(len(s))]\n\t_ = s[:len(s)-1]\n\t_ = s[:len(b)]\n\t_ = s[:len(s):len(s)]\n\n\t_ = t.s[0:]\n\t_ = t.s[1:10]\n\t_ = t.s[2:len(t.s)]\n\t_ = t.s[3:(len(t.s))]\n\t_ = t.s[len(a) : len(t.s)-1]\n\t_ = t.s[0:len(b)]\n\t_ = t.s[2:len(t.s):len(t.s)]\n\n\t_ = t.s[:]\n\t_ = t.s[:10]\n\t_ = t.s[:len(t.s)]\n\t_ = t.s[:(len(t.s))]\n\t_ = t.s[:len(t.s)-1]\n\t_ = t.s[:len(b)]\n\t_ = t.s[:len(t.s):len(t.s)]\n)\n\nfunc _() {\n\ts := s[0:] // want \"unneeded: len\\\\(s\\\\)\"\n\t_ = s\n}\n\nfunc m() {\n\tmaps := []int{}\n\t_ = maps[1:] // want \"unneeded: len\\\\(maps\\\\)\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\ts []int\n\tt struct {\n\t\ts []byte\n\t}\n\n\t_ = a[0:]\n\t_ = a[1:10]\n\t_ = a[2:len(a)] // No simplification fix is offered in generated code.\n\t_ = a[3:(len(a))]\n\t_ = a[len(a)-1 : len(a)] // No simplification fix is offered in generated code.\n\t_ = a[2:len(a):len(a)]\n\n\t_ = a[:]\n\t_ = a[:10]\n\t_ = a[:len(a)] // No simplification fix is offered in generated code.\n\t_ = a[:(len(a))]\n\t_ = a[:len(a)-1]\n\t_ = a[:len(a):len(a)]\n\n\t_ = s[0:]\n\t_ = s[1:10]\n\t_ = s[2:len(s)] // No simplification fix is offered in generated code.\n\t_ = s[3:(len(s))]\n\t_ = s[len(a) : len(s)-1]\n\t_ = s[0:len(b)]\n\t_ = s[2:len(s):len(s)]\n\n\t_ = s[:]\n\t_ = s[:10]\n\t_ = s[:len(s)] // No simplification fix is offered in generated code.\n\t_ = s[:(len(s))]\n\t_ = s[:len(s)-1]\n\t_ = s[:len(b)]\n\t_ = s[:len(s):len(s)]\n\n\t_ = t.s[0:]\n\t_ = t.s[1:10]\n\t_ = t.s[2:len(t.s)]\n\t_ = t.s[3:(len(t.s))]\n\t_ = t.s[len(a) : len(t.s)-1]\n\t_ = t.s[0:len(b)]\n\t_ = t.s[2:len(t.s):len(t.s)]\n\n\t_ = t.s[:]\n\t_ = t.s[:10]\n\t_ = t.s[:len(t.s)]\n\t_ = t.s[:(len(t.s))]\n\t_ = t.s[:len(t.s)-1]\n\t_ = t.s[:len(b)]\n\t_ = t.s[:len(t.s):len(t.s)]\n)\n\nfunc _() {\n\ts := s[0:len(s)] // No simplification fix is offered in generated code.\n\t_ = s\n}\n\nfunc m() {\n\tmaps := []int{}\n\t_ = maps[1:len(maps)] // No simplification fix is offered in generated code.\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go.golden",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated with somegen DO NOT EDIT.\n\npackage testdata\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\ts []int\n\tt struct {\n\t\ts []byte\n\t}\n\n\t_ = a[0:]\n\t_ = a[1:10]\n\t_ = a[2:len(a)] // No simplification fix is offered in generated code.\n\t_ = a[3:(len(a))]\n\t_ = a[len(a)-1 : len(a)] // No simplification fix is offered in generated code.\n\t_ = a[2:len(a):len(a)]\n\n\t_ = a[:]\n\t_ = a[:10]\n\t_ = a[:len(a)] // No simplification fix is offered in generated code.\n\t_ = a[:(len(a))]\n\t_ = a[:len(a)-1]\n\t_ = a[:len(a):len(a)]\n\n\t_ = s[0:]\n\t_ = s[1:10]\n\t_ = s[2:len(s)] // No simplification fix is offered in generated code.\n\t_ = s[3:(len(s))]\n\t_ = s[len(a) : len(s)-1]\n\t_ = s[0:len(b)]\n\t_ = s[2:len(s):len(s)]\n\n\t_ = s[:]\n\t_ = s[:10]\n\t_ = s[:len(s)] // No simplification fix is offered in generated code.\n\t_ = s[:(len(s))]\n\t_ = s[:len(s)-1]\n\t_ = s[:len(b)]\n\t_ = s[:len(s):len(s)]\n\n\t_ = t.s[0:]\n\t_ = t.s[1:10]\n\t_ = t.s[2:len(t.s)]\n\t_ = t.s[3:(len(t.s))]\n\t_ = t.s[len(a) : len(t.s)-1]\n\t_ = t.s[0:len(b)]\n\t_ = t.s[2:len(t.s):len(t.s)]\n\n\t_ = t.s[:]\n\t_ = t.s[:10]\n\t_ = t.s[:len(t.s)]\n\t_ = t.s[:(len(t.s))]\n\t_ = t.s[:len(t.s)-1]\n\t_ = t.s[:len(b)]\n\t_ = t.s[:len(t.s):len(t.s)]\n)\n\nfunc _() {\n\ts := s[0:len(s)] // No simplification fix is offered in generated code.\n\t_ = s\n}\n\nfunc m() {\n\tmaps := []int{}\n\t_ = maps[1:len(maps)] // No simplification fix is offered in generated code.\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\ntype List[E any] []E\n\n// TODO(suzmue): add a test for generic slice expressions when https://github.com/golang/go/issues/48618 is closed.\n// type S interface{ ~[]int }\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\tp List[int]\n\n\t_ = p[0:]\n\t_ = p[1:10]\n\t_ = p[2:len(p)] // want \"unneeded: len\\\\(p\\\\)\"\n\t_ = p[3:(len(p))]\n\t_ = p[len(a) : len(p)-1]\n\t_ = p[0:len(b)]\n\t_ = p[2:len(p):len(p)]\n\n\t_ = p[:]\n\t_ = p[:10]\n\t_ = p[:len(p)] // want \"unneeded: len\\\\(p\\\\)\"\n\t_ = p[:(len(p))]\n\t_ = p[:len(p)-1]\n\t_ = p[:len(b)]\n\t_ = p[:len(p):len(p)]\n)\n\nfunc foo[E any](a List[E]) {\n\t_ = a[0:len(a)] // want \"unneeded: len\\\\(a\\\\)\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/simplifyslice/testdata/src/typeparams/typeparams.go.golden",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testdata\n\ntype List[E any] []E\n\n// TODO(suzmue): add a test for generic slice expressions when https://github.com/golang/go/issues/48618 is closed.\n// type S interface{ ~[]int }\n\nvar (\n\ta [10]byte\n\tb [20]float32\n\tp List[int]\n\n\t_ = p[0:]\n\t_ = p[1:10]\n\t_ = p[2:] // want \"unneeded: len\\\\(p\\\\)\"\n\t_ = p[3:(len(p))]\n\t_ = p[len(a) : len(p)-1]\n\t_ = p[0:len(b)]\n\t_ = p[2:len(p):len(p)]\n\n\t_ = p[:]\n\t_ = p[:10]\n\t_ = p[:] // want \"unneeded: len\\\\(p\\\\)\"\n\t_ = p[:(len(p))]\n\t_ = p[:len(p)-1]\n\t_ = p[:len(b)]\n\t_ = p[:len(p):len(p)]\n)\n\nfunc foo[E any](a List[E]) {\n\t_ = a[0:] // want \"unneeded: len\\\\(a\\\\)\"\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedfunc/doc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedfunc defines an analyzer that checks for unused\n// functions and methods\n//\n// # Analyzer unusedfunc\n//\n// unusedfunc: check for unused functions, methods, etc\n//\n// The unusedfunc analyzer reports functions and methods that are\n// never referenced outside of their own declaration.\n//\n// A function is considered unused if it is unexported and not\n// referenced (except within its own declaration).\n//\n// A method is considered unused if it is unexported, not referenced\n// (except within its own declaration), and its name does not match\n// that of any method of an interface type declared within the same\n// package.\n//\n// The tool may report false positives in some situations, for\n// example:\n//\n//   - for a declaration of an unexported function that is referenced\n//     from another package using the go:linkname mechanism, if the\n//     declaration's doc comment does not also have a go:linkname\n//     comment.\n//\n//     (Such code is in any case strongly discouraged: linkname\n//     annotations, if they must be used at all, should be used on both\n//     the declaration and the alias.)\n//\n//   - for compiler intrinsics in the \"runtime\" package that, though\n//     never referenced, are known to the compiler and are called\n//     indirectly by compiled object code.\n//\n//   - for functions called only from assembly.\n//\n//   - for functions called only from files whose build tags are not\n//     selected in the current build configuration.\n//\n// Since these situations are relatively common in the low-level parts\n// of the runtime, this analyzer ignores the standard library.\n// See https://go.dev/issue/71686 and https://go.dev/issue/74130 for\n// further discussion of these limitations.\n//\n// The unusedfunc algorithm is not as precise as the\n// golang.org/x/tools/cmd/deadcode tool, but it has the advantage that\n// it runs within the modular analysis framework, enabling near\n// real-time feedback within gopls.\n//\n// The unusedfunc analyzer also reports unused types, vars, and\n// constants. Enums--constants defined with iota--are ignored since\n// even the unused values must remain present to preserve the logical\n// ordering.\npackage unusedfunc\n"
  },
  {
    "path": "gopls/internal/analysis/unusedfunc/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The unusedfunc command runs the unusedfunc analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedfunc\"\n)\n\nfunc main() { singlechecker.Main(unusedfunc.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/unusedfunc/testdata/basic.txtar",
    "content": "Basic test of unusedfunc.\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\nfunc main() {\n\t_ = live\n}\n\n// -- functions --\n\nfunc Exported() {}\n\nfunc dead() { // want `function \"dead\" is unused`\n}\n\nfunc deadRecursive() int { // want `function \"deadRecursive\" is unused`\n\treturn deadRecursive()\n}\n\nfunc live() {}\n\n//go:linkname foo\nfunc apparentlyDeadButHasPrecedingLinknameComment() {}\n\n// -- methods --\n\ntype ExportedType int\ntype unexportedType int\n\nfunc (ExportedType) Exported()   {}\nfunc (unexportedType) Exported() {}\n\nfunc (x ExportedType) dead() { // want `method \"dead\" is unused`\n\tx.dead()\n}\n\nfunc (u unexportedType) dead() { // want `method \"dead\" is unused`\n\tu.dead()\n}\n\nfunc (x ExportedType) dynamic() {} // matches name of interface method => live\n\ntype _ interface{ dynamic() }\n\n// -- types without methods --\n\ntype ExportedType2 int\n\n// self-references don't count\ntype unusedUnexportedType2 struct{ *unusedUnexportedType2 } // want `type \"unusedUnexportedType2\" is unused`\n\ntype (\n\tone int\n\ttwo one // want `type \"two\" is unused`\n)\n\n// -- generic methods --\n\ntype g[T any] int\n\nfunc (g[T]) method() {} // want `method \"method\" is unused`\n\n// -- constants --\n\nconst unusedConst = 1 // want `const \"unusedConst\" is unused`\n\nconst (\n\tunusedEnum = iota // want `const \"unusedEnum\" is unused`\n)\n\nconst constOne = 1\nconst unusedConstTwo = constOne // want `const \"unusedConstTwo\" is unused`\nconst _, unusedConstThree = 0, 3 // want `const \"unusedConstThree\" is unused`\nconst unusedConstFour, _ = 4, 0 // want `const \"unusedConstFour\" is unused`\nconst unusedConstFive, UsedConst6 = 4, 6 // want `const \"unusedConstFive\" is unused`\n\n// This test verifies the fix for golang/go#76924.\n// We no longer produce unused variable warnings for a group\n// of unused constants if all constants have the same type and\n// at least one is used.\n\nconst (\n\ta = \"a\"\n\tb = \"b\"\n\tc = \"c\"\n)\n\nfunc _() {\n\tprint(a)\n}\n\nconst ( // want `all values in this set of constants are unused`\n\td = \"d\"\n\te = \"e\"\n)\n\n// -- vars --\n\nvar unusedVar = 1 // want `var \"unusedVar\" is unused`\n\nvar (\n\tunusedVar2 = 1 // want `var \"unusedVar2\" is unused`\n)\n\nvar (\n\tusedVar int\n\tunusedVar3 = usedVar // want `var \"unusedVar3\" is unused`\n\t_, unusedVar4, _ = Triple() // want `var \"unusedVar4\" is unused`\n)\n\nfunc Triple() (int, int, int)\n\n-- a/a.go.golden --\npackage a\n\nfunc main() {\n\t_ = live\n}\n\n// -- functions --\n\nfunc Exported() {}\n\nfunc live() {}\n\n//go:linkname foo\nfunc apparentlyDeadButHasPrecedingLinknameComment() {}\n\n// -- methods --\n\ntype ExportedType int\ntype unexportedType int\n\nfunc (ExportedType) Exported()   {}\nfunc (unexportedType) Exported() {}\n\nfunc (x ExportedType) dynamic() {} // matches name of interface method => live\n\ntype _ interface{ dynamic() }\n\n\n// -- types without methods --\n\ntype ExportedType2 int\n\ntype (\n\tone int\n)\n\n// -- generic methods --\n\ntype g[T any] int\n\n// -- constants --\n\nconst constOne = 1\n\nconst UsedConst6 = 6 // want `const \"unusedConstFive\" is unused`\n\n// This test verifies the fix for golang/go#76924.\n// We no longer produce unused variable warnings for a group\n// of unused constants if all constants have the same type and\n// at least one is used.\n\nconst (\n\ta = \"a\"\n\tb = \"b\"\n\tc = \"c\"\n)\n\nfunc _() {\n\tprint(a)\n}\n\n// -- vars --\n\nvar (\n\tusedVar int\n\t_, _, _ = Triple() // want `var \"unusedVar4\" is unused`\n)\n\nfunc Triple() (int, int, int)\n"
  },
  {
    "path": "gopls/internal/analysis/unusedfunc/unusedfunc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedfunc\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\ttypeindexanalyzer \"golang.org/x/tools/internal/analysis/typeindex\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\n// Assumptions\n//\n// Like unusedparams, this analyzer depends on the invariant of the\n// gopls analysis driver that only the \"widest\" package (the one with\n// the most files) for a given file is analyzed. This invariant allows\n// the algorithm to make \"closed world\" assumptions about the target\n// package. (In general, analysis of Go test packages cannot make that\n// assumption because in-package tests add new files to existing\n// packages, potentially invalidating results.) Consequently, running\n// this analyzer in, say, unitchecker or multichecker may produce\n// incorrect results.\n//\n// A function is unreferenced if it is never referenced except within\n// its own declaration, and it is unexported. (Exported functions must\n// be assumed to be referenced from other packages.)\n//\n// For methods, we assume that the receiver type is \"live\" (variables\n// of that type are created) and \"address taken\" (its rtype ends up in\n// an at least one interface value). This means exported methods may\n// be called via reflection or by interfaces defined in other\n// packages, so again we are concerned only with unexported methods.\n//\n// To discount the possibility of a method being called via an\n// interface, we must additionally ensure that no literal interface\n// type within the package has a method of the same name.\n// (Unexported methods cannot be called through interfaces declared\n// in other packages because each package has a private namespace\n// for unexported identifiers.)\n//\n// Types (sans methods), constants, and vars are more straightforward.\n//\n// For enums (defined here as const decls where all consts have the same type),\n// we only require that one of the names in the group is used, since it is\n// common for at least some values to be unused when they are added for\n// symmetry, future use, or to conform to some external pattern.\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unusedfunc\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unusedfunc\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer, typeindexanalyzer.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\t// The standard library makes heavy use of intrinsics, linknames, etc,\n\t// that confuse this algorithm; so skip it (#74130).\n\tif packagepath.IsStdPackage(pass.Pkg.Path()) {\n\t\treturn nil, nil\n\t}\n\n\tvar (\n\t\tinspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\tindex   = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)\n\t)\n\n\t// Gather names of unexported interface methods declared in this package.\n\tlocalIfaceMethods := make(map[string]bool)\n\tnodeFilter := []ast.Node{(*ast.InterfaceType)(nil)}\n\tinspect.Preorder(nodeFilter, func(n ast.Node) {\n\t\tiface := n.(*ast.InterfaceType)\n\t\tfor _, field := range iface.Methods.List {\n\t\t\tif len(field.Names) > 0 {\n\t\t\t\tid := field.Names[0]\n\t\t\t\tif !id.IsExported() {\n\t\t\t\t\t// TODO(adonovan): check not just name but signature too.\n\t\t\t\t\tlocalIfaceMethods[id.Name] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\t// used reports whether the object declared at id is (potentially) used.\n\t// References within curSelf are ignored.\n\tused := func(id *ast.Ident, curSelf inspector.Cursor) bool {\n\t\t// Exported functions may be called from other packages.\n\t\tif id.IsExported() {\n\t\t\treturn true\n\t\t}\n\n\t\t// Blank functions are exempt from diagnostics.\n\t\tif id.Name == \"_\" {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check for uses (including selections).\n\t\tobj := pass.TypesInfo.Defs[id]\n\t\tfor curId := range index.Uses(obj) {\n\t\t\t// Ignore self references.\n\t\t\tif !curSelf.Contains(curId) {\n\t\t\t\treturn true // symbol is referenced\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// checkUnused reports a diagnostic if the object declared at id\n\t// is unexported and unused. References within curSelf are ignored.\n\tcheckUnused := func(noun string, id *ast.Ident, curSelf inspector.Cursor, delete func() []analysis.TextEdit) {\n\t\tif used(id, curSelf) {\n\t\t\treturn\n\t\t}\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     id.Pos(),\n\t\t\tEnd:     id.End(),\n\t\t\tMessage: fmt.Sprintf(\"%s %q is unused\", noun, id.Name),\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage:   fmt.Sprintf(\"Delete %s %q\", noun, id.Name),\n\t\t\t\tTextEdits: delete(),\n\t\t\t}},\n\t\t})\n\t}\n\n\t// isEnum returns true if the decl curGenDecl is a const decl with more than one\n\t// spec where all consts are the same type.\n\tisEnum := func(curGenDecl inspector.Cursor) bool {\n\t\tdecl := curGenDecl.Node().(*ast.GenDecl)\n\t\tif decl.Tok != token.CONST || len(decl.Specs) < 2 {\n\t\t\treturn false\n\t\t}\n\t\tvar prevType types.Type\n\t\tfor _, spec := range decl.Specs {\n\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\tfor _, id := range spec.Names {\n\t\t\t\tcurType := pass.TypesInfo.TypeOf(id)\n\t\t\t\tif prevType != nil && !types.Identical(curType, prevType) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tprevType = curType\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\t// Check each package-level declaration (and method) for uses.\n\tfor curFile := range inspect.Root().Preorder((*ast.File)(nil)) {\n\t\tfile := curFile.Node().(*ast.File)\n\t\tif ast.IsGenerated(file) {\n\t\t\tcontinue // skip generated files\n\t\t}\n\t\ttokFile := pass.Fset.File(file.Pos())\n\n\tnextDecl:\n\t\tfor i := range file.Decls {\n\t\t\tcurDecl := curFile.ChildAt(edge.File_Decls, i)\n\t\t\tdecl := curDecl.Node().(ast.Decl)\n\n\t\t\t// Skip if there's a preceding //go:linkname directive.\n\t\t\t// (This is relevant only to func and var decls.)\n\t\t\t//\n\t\t\t// (A program can link fine without such a directive,\n\t\t\t// but it is bad style; and the directive may\n\t\t\t// appear anywhere, not just on the preceding line,\n\t\t\t// but again that is poor form.)\n\t\t\tif doc := astutil.DocComment(decl); doc != nil {\n\t\t\t\tfor _, comment := range doc.List {\n\t\t\t\t\t// TODO(adonovan): use ast.ParseDirective when #68021 lands.\n\t\t\t\t\tif strings.HasPrefix(comment.Text, \"//go:linkname \") {\n\t\t\t\t\t\tcontinue nextDecl\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tid := decl.Name\n\t\t\t\t// An (unexported) method whose name matches an\n\t\t\t\t// interface method declared in the same package\n\t\t\t\t// may be dynamically called via that interface.\n\t\t\t\tif decl.Recv != nil && localIfaceMethods[id.Name] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// main and init functions are implicitly always used\n\t\t\t\tif decl.Recv == nil && (id.Name == \"init\" || id.Name == \"main\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tnoun := cond(decl.Recv == nil, \"function\", \"method\")\n\t\t\t\tcheckUnused(noun, decl.Name, curDecl, func() []analysis.TextEdit {\n\t\t\t\t\treturn refactor.DeleteDecl(tokFile, curDecl)\n\t\t\t\t})\n\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tswitch decl.Tok {\n\t\t\t\tcase token.TYPE:\n\t\t\t\t\tfor i, spec := range decl.Specs {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tspec    = spec.(*ast.TypeSpec)\n\t\t\t\t\t\t\tid      = spec.Name\n\t\t\t\t\t\t\tcurSpec = curDecl.ChildAt(edge.GenDecl_Specs, i)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcheckUnused(\"type\", id, curSpec, func() []analysis.TextEdit {\n\t\t\t\t\t\t\treturn refactor.DeleteSpec(tokFile, curSpec)\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\tcase token.CONST, token.VAR:\n\t\t\t\t\tif isEnum(curDecl) {\n\t\t\t\t\t\t// For enum-like constants, a use of any\n\t\t\t\t\t\t// name acts as a use of the whole.\n\t\t\t\t\t\t// TODO(mkalil): This results in false negatives, for example:\n\t\t\t\t\t\t// const (\n\t\t\t\t\t\t//\t a = 0\n\t\t\t\t\t\t//\t b = a + 1\n\t\t\t\t\t\t// )\n\t\t\t\t\t\t// We report that a is \"used\" even though is not used outside the const\n\t\t\t\t\t\t// decl, and since we do not report errors in enums that have at least one\n\t\t\t\t\t\t// used name, we do not report a diagnostic at all.\n\t\t\t\t\t\tallUnused := true\n\t\t\t\t\t\tfor i, spec := range decl.Specs {\n\t\t\t\t\t\t\tcurSpec := curDecl.ChildAt(edge.GenDecl_Specs, i)\n\t\t\t\t\t\t\tfor _, id := range spec.(*ast.ValueSpec).Names {\n\t\t\t\t\t\t\t\tif used(id, curSpec) {\n\t\t\t\t\t\t\t\t\tallUnused = false\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif allUnused {\n\t\t\t\t\t\t\tedits := refactor.DeleteDecl(tokFile, curDecl)\n\t\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t\tPos:     decl.Pos(),\n\t\t\t\t\t\t\t\tEnd:     decl.End(),\n\t\t\t\t\t\t\t\tMessage: \"all values in this set of constants are unused\",\n\t\t\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\t\t\t\tMessage:   \"Delete the constants declaration\",\n\t\t\t\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor i, spec := range decl.Specs {\n\t\t\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\t\t\tcurSpec := curDecl.ChildAt(edge.GenDecl_Specs, i)\n\n\t\t\t\t\t\t\tfor j, id := range spec.Names {\n\t\t\t\t\t\t\t\tcheckUnused(decl.Tok.String(), id, curSpec, func() []analysis.TextEdit {\n\t\t\t\t\t\t\t\t\tcurId := curSpec.ChildAt(edge.ValueSpec_Names, j)\n\t\t\t\t\t\t\t\t\treturn refactor.DeleteVar(tokFile, pass.TypesInfo, curId)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\nfunc cond[T any](cond bool, t, f T) T {\n\tif cond {\n\t\treturn t\n\t} else {\n\t\treturn f\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedfunc/unusedfunc_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedfunc_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedfunc\"\n\t\"golang.org/x/tools/internal/testfiles\"\n)\n\nfunc Test(t *testing.T) {\n\tdir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), \"basic.txtar\"))\n\tanalysistest.RunWithSuggestedFixes(t, dir, unusedfunc.Analyzer, \"example.com/a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/cmd/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The unusedparams command runs the unusedparams analyzer.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedparams\"\n)\n\nfunc main() { singlechecker.Main(unusedparams.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedparams defines an analyzer that checks for unused\n// parameters of functions.\n//\n// # Analyzer unusedparams\n//\n// unusedparams: check for unused parameters of functions\n//\n// The unusedparams analyzer checks functions to see if there are\n// any parameters that are not being used.\n//\n// To ensure soundness, it ignores:\n//   - \"address-taken\" functions, that is, functions that are used as\n//     a value rather than being called directly; their signatures may\n//     be required to conform to a func type.\n//   - exported functions or methods, since they may be address-taken\n//     in another package.\n//   - unexported methods whose name matches an interface method\n//     declared in the same package, since the method's signature\n//     may be required to conform to the interface type.\n//   - functions with empty bodies, or containing just a call to panic.\n//   - parameters that are unnamed, or named \"_\", the blank identifier.\n//\n// The analyzer suggests a fix of replacing the parameter name by \"_\",\n// but in such cases a deeper fix can be obtained by invoking the\n// \"Refactor: remove unused parameter\" code action, which will\n// eliminate the parameter entirely, along with all corresponding\n// arguments at call sites, while taking care to preserve any side\n// effects in the argument expressions; see\n// https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.\n//\n// This analyzer ignores generated code.\npackage unusedparams\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/a/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype parent interface {\n\tn(f bool)\n}\n\ntype yuh struct {\n\ta int\n}\n\nfunc (y *yuh) n(f bool) {\n\tfor i := 0; i < 10; i++ {\n\t\tfmt.Println(i)\n\t}\n}\n\nfunc a(i1 int, i2 int, i3 int) int { // want \"unused parameter: i2\"\n\ti3 += i1\n\t_ = func(z int) int { // want \"unused parameter: z\"\n\t\t_ = 1\n\t\treturn 1\n\t}\n\treturn i3\n}\n\nfunc b(c bytes.Buffer) { // want \"unused parameter: c\"\n\t_ = 1\n}\n\nfunc z(h http.ResponseWriter, _ *http.Request) { // no report: func z is address-taken\n\tfmt.Println(\"Before\")\n}\n\nfunc l(h http.Handler) http.Handler { // want \"unused parameter: h\"\n\treturn http.HandlerFunc(z)\n}\n\nfunc mult(a, b int) int { // want \"unused parameter: b\"\n\ta += 1\n\treturn a\n}\n\nfunc y(a int) {\n\tpanic(\"yo\")\n}\n\nvar _ = func(x int) {} // empty body: no diagnostic\n\nvar _ = func(x int) { println() } // want \"unused parameter: x\"\n\nvar (\n\tcalledGlobal       = func(x int) { println() } // want \"unused parameter: x\"\n\taddressTakenGlobal = func(x int) { println() } // no report: function is address-taken\n)\n\nfunc _() {\n\tcalledGlobal(1)\n\tprintln(addressTakenGlobal)\n}\n\nfunc Exported(unused int) {} // no finding: an exported function may be address-taken\n\ntype T int\n\nfunc (T) m(f bool) { println() } // want \"unused parameter: f\"\nfunc (T) n(f bool) { println() } // no finding: n may match the interface method parent.n\n\nfunc _() {\n\tvar fib func(x, y int) int\n\tfib = func(x, y int) int { // want \"unused parameter: y\"\n\t\tif x < 2 {\n\t\t\treturn x\n\t\t}\n\t\treturn fib(x-1, 123) + fib(x-2, 456)\n\t}\n\tfib(10, 42)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/a/a.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype parent interface {\n\tn(f bool)\n}\n\ntype yuh struct {\n\ta int\n}\n\nfunc (y *yuh) n(f bool) {\n\tfor i := 0; i < 10; i++ {\n\t\tfmt.Println(i)\n\t}\n}\n\nfunc a(i1 int, _ int, i3 int) int { // want \"unused parameter: i2\"\n\ti3 += i1\n\t_ = func(_ int) int { // want \"unused parameter: z\"\n\t\t_ = 1\n\t\treturn 1\n\t}\n\treturn i3\n}\n\nfunc b(_ bytes.Buffer) { // want \"unused parameter: c\"\n\t_ = 1\n}\n\nfunc z(h http.ResponseWriter, _ *http.Request) { // no report: func z is address-taken\n\tfmt.Println(\"Before\")\n}\n\nfunc l(_ http.Handler) http.Handler { // want \"unused parameter: h\"\n\treturn http.HandlerFunc(z)\n}\n\nfunc mult(a, _ int) int { // want \"unused parameter: b\"\n\ta += 1\n\treturn a\n}\n\nfunc y(a int) {\n\tpanic(\"yo\")\n}\n\nvar _ = func(x int) {} // empty body: no diagnostic\n\nvar _ = func(_ int) { println() } // want \"unused parameter: x\"\n\nvar (\n\tcalledGlobal       = func(_ int) { println() } // want \"unused parameter: x\"\n\taddressTakenGlobal = func(x int) { println() } // no report: function is address-taken\n)\n\nfunc _() {\n\tcalledGlobal(1)\n\tprintln(addressTakenGlobal)\n}\n\nfunc Exported(unused int) {} // no finding: an exported function may be address-taken\n\ntype T int\n\nfunc (T) m(_ bool) { println() } // want \"unused parameter: f\"\nfunc (T) n(f bool) { println() } // no finding: n may match the interface method parent.n\n\nfunc _() {\n\tvar fib func(x, y int) int\n\tfib = func(x, _ int) int { // want \"unused parameter: y\"\n\t\tif x < 2 {\n\t\t\treturn x\n\t\t}\n\t\treturn fib(x-1, 123) + fib(x-2, 456)\n\t}\n\tfib(10, 42)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/generatedcode/generatedcode.go",
    "content": "// Code generated with somegen DO NOT EDIT.\n//\n// Because this file is generated, there should be no diagnostics\n// reported for any unused parameters.\n\npackage generatedcode\n\n// generatedInterface exists to ensure that the generated code\n// is considered when determining whether parameters are used\n// in non-generated code.\ntype generatedInterface interface{ n(f bool) }\n\nfunc a(x bool) { println() }\n\nvar v = func(x bool) { println() }\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/generatedcode/generatedcode.go.golden",
    "content": "// Code generated with somegen DO NOT EDIT.\n//\n// Because this file is generated, there should be no diagnostics\n// reported for any unused parameters.\n\npackage generatedcode\n\n// generatedInterface exists to ensure that the generated code\n// is considered when determining whether parameters are used\n// in non-generated code.\ntype generatedInterface interface{ n(f bool) }\n\nfunc a(x bool) { println() }\n\nvar v = func(x bool) { println() }\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/generatedcode/nongeneratedcode.go",
    "content": "package generatedcode\n\n// This file does not have the generated code comment.\n// It exists to ensure that generated code is considered\n// when determining whether or not function parameters\n// are used.\n\ntype implementsGeneratedInterface struct{}\n\n// The f parameter should not be reported as unused,\n// because this method implements the parent interface defined\n// in the generated code.\nfunc (implementsGeneratedInterface) n(f bool) {\n\t// The body must not be empty, otherwise unusedparams will\n\t// not report the unused parameter regardless of the\n\t// interface.\n\tprintln()\n}\n\nfunc b(x bool) { println() } // want \"unused parameter: x\"\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/generatedcode/nongeneratedcode.go.golden",
    "content": "package generatedcode\n\n// This file does not have the generated code comment.\n// It exists to ensure that generated code is considered\n// when determining whether or not function parameters\n// are used.\n\ntype implementsGeneratedInterface struct{}\n\n// The f parameter should not be reported as unused,\n// because this method implements the parent interface defined\n// in the generated code.\nfunc (implementsGeneratedInterface) n(f bool) {\n\t// The body must not be empty, otherwise unusedparams will\n\t// not report the unused parameter regardless of the\n\t// interface.\n\tprintln()\n}\n\nfunc b(_ bool) { println() } // want \"unused parameter: x\"\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype parent[T any] interface {\n\tn(f T)\n}\n\ntype yuh[T any] struct {\n\ta T\n}\n\nfunc (y *yuh[int]) n(f bool) {\n\tfor i := 0; i < 10; i++ {\n\t\tfmt.Println(i)\n\t}\n}\n\nfunc a[T comparable](i1 int, i2 T, i3 int) int { // want \"unused parameter: i2\"\n\ti3 += i1\n\t_ = func(z int) int { // want \"unused parameter: z\"\n\t\t_ = 1\n\t\treturn 1\n\t}\n\treturn i3\n}\n\nfunc b[T any](c bytes.Buffer) { // want \"unused parameter: c\"\n\t_ = 1\n}\n\nfunc z[T http.ResponseWriter](h T, _ *http.Request) { // no report: func z is address-taken\n\tfmt.Println(\"Before\")\n}\n\nfunc l(h http.Handler) http.Handler { // want \"unused parameter: h\"\n\treturn http.HandlerFunc(z[http.ResponseWriter])\n}\n\nfunc mult(a, b int) int { // want \"unused parameter: b\"\n\ta += 1\n\treturn a\n}\n\nfunc y[T any](a T) {\n\tpanic(\"yo\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype parent[T any] interface {\n\tn(f T)\n}\n\ntype yuh[T any] struct {\n\ta T\n}\n\nfunc (y *yuh[int]) n(f bool) {\n\tfor i := 0; i < 10; i++ {\n\t\tfmt.Println(i)\n\t}\n}\n\nfunc a[T comparable](i1 int, _ T, i3 int) int { // want \"unused parameter: i2\"\n\ti3 += i1\n\t_ = func(_ int) int { // want \"unused parameter: z\"\n\t\t_ = 1\n\t\treturn 1\n\t}\n\treturn i3\n}\n\nfunc b[T any](_ bytes.Buffer) { // want \"unused parameter: c\"\n\t_ = 1\n}\n\nfunc z[T http.ResponseWriter](h T, _ *http.Request) { // no report: func z is address-taken\n\tfmt.Println(\"Before\")\n}\n\nfunc l(_ http.Handler) http.Handler { // want \"unused parameter: h\"\n\treturn http.HandlerFunc(z[http.ResponseWriter])\n}\n\nfunc mult(a, _ int) int { // want \"unused parameter: b\"\n\ta += 1\n\treturn a\n}\n\nfunc y[T any](a T) {\n\tpanic(\"yo\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/unusedparams.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedparams\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/util/moreslices\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"unusedparams\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"unusedparams\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams\",\n}\n\nconst FixCategory = \"unusedparams\" // recognized by gopls ApplyFix\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// First find all \"address-taken\" functions.\n\t// We must conservatively assume that their parameters\n\t// are all required to conform to some signature.\n\t//\n\t// A named function is address-taken if it is somewhere\n\t// used not in call position:\n\t//\n\t//\tf(...)\t\t// not address-taken\n\t//      use(f)          // address-taken\n\t//\n\t// A literal function is address-taken if it is not\n\t// immediately bound to a variable, or if that variable is\n\t// used not in call position:\n\t//\n\t//    f := func() { ... }; f()     \t\t\tused only in call position\n\t//    var f func(); f = func() { ...f()... }; f()     \tditto\n\t//    use(func() { ... })\t\t\t\taddress-taken\n\t//\n\n\t// Note: this algorithm relies on the assumption that the\n\t// analyzer is called only for the \"widest\" package for a\n\t// given file: that is, p_test in preference to p, if both\n\t// exist. Analyzing only package p may produce diagnostics\n\t// that would be falsified based on declarations in p_test.go\n\t// files. The gopls analysis driver does this, but most\n\t// drivers to not, so running this command in, say,\n\t// unitchecker or multichecker may produce incorrect results.\n\n\t// Gather global information:\n\t// - uses of functions not in call position\n\t// - unexported interface methods\n\t// - all referenced variables\n\n\tusesOutsideCall := make(map[types.Object][]*ast.Ident)\n\tunexportedIMethodNames := make(map[string]bool)\n\t{\n\t\tcallPosn := make(map[*ast.Ident]bool) // all idents f appearing in f() calls\n\t\tfilter := []ast.Node{\n\t\t\t(*ast.CallExpr)(nil),\n\t\t\t(*ast.InterfaceType)(nil),\n\t\t}\n\t\tinspect.Preorder(filter, func(n ast.Node) {\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.CallExpr:\n\t\t\t\tid := typesinternal.UsedIdent(pass.TypesInfo, n.Fun)\n\t\t\t\t// Find object:\n\t\t\t\t// record non-exported function, method, or func-typed var.\n\t\t\t\tif id != nil && !id.IsExported() {\n\t\t\t\t\tswitch pass.TypesInfo.Uses[id].(type) {\n\t\t\t\t\tcase *types.Func, *types.Var:\n\t\t\t\t\t\tcallPosn[id] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.InterfaceType:\n\t\t\t\t// Record the set of names of unexported interface methods.\n\t\t\t\t// (It would be more precise to record signatures but\n\t\t\t\t// generics makes it tricky, and this conservative\n\t\t\t\t// heuristic is close enough.)\n\t\t\t\tt := pass.TypesInfo.TypeOf(n).(*types.Interface)\n\t\t\t\tfor m := range t.ExplicitMethods() {\n\t\t\t\t\tif !m.Exported() && m.Name() != \"_\" {\n\t\t\t\t\t\tunexportedIMethodNames[m.Name()] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tfor id, obj := range pass.TypesInfo.Uses {\n\t\t\tif !callPosn[id] {\n\t\t\t\t// This includes \"f = func() {...}\", which we deal with below.\n\t\t\t\tusesOutsideCall[obj] = append(usesOutsideCall[obj], id)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find all vars (notably parameters) that are used.\n\tusedVars := make(map[*types.Var]bool)\n\tfor _, obj := range pass.TypesInfo.Uses {\n\t\tif v, ok := obj.(*types.Var); ok {\n\t\t\tif v.IsField() {\n\t\t\t\tcontinue // no point gathering these\n\t\t\t}\n\t\t\tusedVars[v] = true\n\t\t}\n\t}\n\n\t// Check each non-address-taken function's parameters are all used.\nfuncloop:\n\tfor c := range inspect.Root().Preorder((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {\n\t\tvar (\n\t\t\tfn    types.Object // function symbol (*Func, possibly *Var for a FuncLit)\n\t\t\tftype *ast.FuncType\n\t\t\tbody  *ast.BlockStmt\n\t\t)\n\t\tswitch n := c.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\t// We can't analyze non-Go functions.\n\t\t\tif n.Body == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Ignore exported functions and methods: we\n\t\t\t// must assume they may be address-taken in\n\t\t\t// another package.\n\t\t\tif n.Name.IsExported() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Ignore methods that match the name of any\n\t\t\t// interface method declared in this package,\n\t\t\t// as the method's signature may need to conform\n\t\t\t// to the interface.\n\t\t\tif n.Recv != nil && unexportedIMethodNames[n.Name.Name] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfn = pass.TypesInfo.Defs[n.Name].(*types.Func)\n\t\t\tftype, body = n.Type, n.Body\n\n\t\tcase *ast.FuncLit:\n\t\t\t// Find the symbol for the variable (if any)\n\t\t\t// to which the FuncLit is bound.\n\t\t\t// (We don't bother to allow ParenExprs.)\n\t\t\tswitch parent := c.Parent().Node().(type) {\n\t\t\tcase *ast.AssignStmt:\n\t\t\t\t// f  = func() {...}\n\t\t\t\t// f := func() {...}\n\t\t\t\tif ek, idx := c.ParentEdge(); ek == edge.AssignStmt_Rhs {\n\t\t\t\t\t// Inv: n == AssignStmt.Rhs[idx]\n\t\t\t\t\tif id, ok := parent.Lhs[idx].(*ast.Ident); ok {\n\t\t\t\t\t\tfn = pass.TypesInfo.ObjectOf(id)\n\n\t\t\t\t\t\t// Edge case: f = func() {...}\n\t\t\t\t\t\t// should not count as a use.\n\t\t\t\t\t\tif pass.TypesInfo.Uses[id] != nil {\n\t\t\t\t\t\t\tusesOutsideCall[fn] = moreslices.Remove(usesOutsideCall[fn], id)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif fn == nil && id.Name == \"_\" {\n\t\t\t\t\t\t\t// Edge case: _ = func() {...}\n\t\t\t\t\t\t\t// has no local var. Fake one.\n\t\t\t\t\t\t\tv := types.NewVar(id.Pos(), pass.Pkg, id.Name, pass.TypesInfo.TypeOf(n))\n\t\t\t\t\t\t\tv.SetKind(types.LocalVar)\n\t\t\t\t\t\t\tfn = v\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.ValueSpec:\n\t\t\t\t// var f = func() { ... }\n\t\t\t\t// (unless f is an exported package-level var)\n\t\t\t\tfor i, val := range parent.Values {\n\t\t\t\t\tif val == n {\n\t\t\t\t\t\tv := pass.TypesInfo.Defs[parent.Names[i]]\n\t\t\t\t\t\tif !(v.Parent() == pass.Pkg.Scope() && v.Exported()) {\n\t\t\t\t\t\t\tfn = v\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tftype, body = n.Type, n.Body\n\t\t}\n\n\t\t// Ignore address-taken functions and methods: unused\n\t\t// parameters may be needed to conform to a func type.\n\t\tif fn == nil || len(usesOutsideCall[fn]) > 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// If there are no parameters, there are no unused parameters.\n\t\tif ftype.Params.NumFields() == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// To reduce false positives, ignore functions with an\n\t\t// empty or panic body.\n\t\t//\n\t\t// We choose not to ignore functions whose body is a\n\t\t// single return statement (as earlier versions did)\n\t\t// \tfunc f() { return }\n\t\t// \tfunc f() { return g(...) }\n\t\t// as we suspect that was just heuristic to reduce\n\t\t// false positives in the earlier unsound algorithm.\n\t\tswitch len(body.List) {\n\t\tcase 0:\n\t\t\t// Empty body. Although the parameter is\n\t\t\t// unnecessary, it's pretty obvious to the\n\t\t\t// reader that that's the case, so we allow it.\n\t\t\tcontinue // func f() {}\n\t\tcase 1:\n\t\t\tif stmt, ok := body.List[0].(*ast.ExprStmt); ok {\n\t\t\t\t// We allow a panic body, as it is often a\n\t\t\t\t// placeholder for a future implementation:\n\t\t\t\t// \tfunc f() { panic(...) }\n\t\t\t\tif call, ok := stmt.X.(*ast.CallExpr); ok {\n\t\t\t\t\tif fun, ok := call.Fun.(*ast.Ident); ok && fun.Name == \"panic\" {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Don't report diagnostics on generated files.\n\t\t// (We can't skip analysis of generated files, though.)\n\t\tif ast.IsGenerated(astutil.EnclosingFile(c)) {\n\t\t\tcontinue funcloop\n\t\t}\n\n\t\t// Report each unused parameter.\n\t\tfor _, field := range ftype.Params.List {\n\t\t\tfor _, id := range field.Names {\n\t\t\t\tif id.Name == \"_\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tparam := pass.TypesInfo.Defs[id].(*types.Var)\n\t\t\t\tif !usedVars[param] {\n\t\t\t\t\tstart, end := field.Pos(), field.End()\n\t\t\t\t\tif len(field.Names) > 1 {\n\t\t\t\t\t\tstart, end = id.Pos(), id.End()\n\t\t\t\t\t}\n\n\t\t\t\t\t// This diagnostic carries both an edit-based fix to\n\t\t\t\t\t// rename the unused parameter, and a command-based fix\n\t\t\t\t\t// to remove it (see golang.RemoveUnusedParameter).\n\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\tPos:      start,\n\t\t\t\t\t\tEnd:      end,\n\t\t\t\t\t\tMessage:  fmt.Sprintf(\"unused parameter: %s\", id.Name),\n\t\t\t\t\t\tCategory: FixCategory,\n\t\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tMessage: `Rename parameter to \"_\"`,\n\t\t\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\t\t\tPos:     id.Pos(),\n\t\t\t\t\t\t\t\t\tEnd:     id.End(),\n\t\t\t\t\t\t\t\t\tNewText: []byte(\"_\"),\n\t\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"Remove unused parameter %q\", id.Name),\n\t\t\t\t\t\t\t\t// No TextEdits => computed by gopls command\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedparams/unusedparams_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedparams_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedparams\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.RunWithSuggestedFixes(t, testdata, unusedparams.Analyzer, \"a\", \"generatedcode\", \"typeparams\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/testdata/src/assign/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\ntype A struct {\n\tb int\n}\n\nfunc singleAssignment() {\n\tv := \"s\" // want `declared (and|but) not used`\n\n\ts := []int{ // want `declared (and|but) not used`\n\t\t1,\n\t\t2,\n\t}\n\n\ta := func(s string) bool { // want `declared (and|but) not used`\n\t\treturn false\n\t}\n\n\tif 1 == 1 {\n\t\ts := \"v\" // want `declared (and|but) not used`\n\t}\n\n\tpanic(\"I should survive\")\n}\n\nfunc noOtherStmtsInBlock() {\n\tv := \"s\" // want `declared (and|but) not used`\n}\n\nfunc partOfMultiAssignment() {\n\tf, err := os.Open(\"file\") // want `declared (and|but) not used`\n\tpanic(err)\n}\n\nfunc sideEffects(cBool chan bool, cInt chan int) {\n\tb := <-c            // want `declared (and|but) not used`\n\ts := fmt.Sprint(\"\") // want `declared (and|but) not used`\n\ta := A{             // want `declared (and|but) not used`\n\t\tb: func() int {\n\t\t\treturn 1\n\t\t}(),\n\t}\n\tc := A{<-cInt}          // want `declared (and|but) not used`\n\td := fInt() + <-cInt    // want `declared (and|but) not used`\n\te := fBool() && <-cBool // want `declared (and|but) not used`\n\tf := map[int]int{       // want `declared (and|but) not used`\n\t\tfInt(): <-cInt,\n\t}\n\tg := []int{<-cInt}     // want `declared (and|but) not used`\n\th := func(s string) {} // want `declared (and|but) not used`\n\n\t// (ill-typed)\n\ti := func(s string) {}() // want `declared (and|but) not used`\n}\n\nfunc commentAbove() {\n\t// v is a variable\n\tv := \"s\" // want `declared (and|but) not used`\n}\n\nfunc commentBelow() {\n\tv := \"s\" // want `declared (and|but) not used`\n\t// v is a variable\n}\n\nfunc commentSpaceBelow() {\n\tv := \"s\" // want `declared (and|but) not used`\n\n\t// v is a variable\n}\n\nfunc fBool() bool {\n\treturn true\n}\n\nfunc fInt() int {\n\treturn 1\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/testdata/src/assign/a.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\ntype A struct {\n\tb int\n}\n\nfunc singleAssignment() {\n\n\n\n\tif 1 == 1 {\n\t}\n\n\tpanic(\"I should survive\")\n}\n\nfunc noOtherStmtsInBlock() {\n}\n\nfunc partOfMultiAssignment() {\n\t_, err := os.Open(\"file\") // want `declared (and|but) not used`\n\tpanic(err)\n}\n\nfunc sideEffects(cBool chan bool, cInt chan int) {\n\t_ = <-c            // want `declared (and|but) not used`\n\t_ = fmt.Sprint(\"\") // want `declared (and|but) not used`\n\t_ = A{             // want `declared (and|but) not used`\n\t\tb: func() int {\n\t\t\treturn 1\n\t\t}(),\n\t}\n\t_ = A{<-cInt}          // want `declared (and|but) not used`\n\t_ = fInt() + <-cInt    // want `declared (and|but) not used`\n\t_ = fBool() && <-cBool // want `declared (and|but) not used`\n\t_ = map[int]int{       // want `declared (and|but) not used`\n\t\tfInt(): <-cInt,\n\t}\n\t_ = []int{<-cInt}       // want `declared (and|but) not used`\n\n\t// (ill-typed)\n\t_ = func(s string) {}() // want `declared (and|but) not used`\n}\n\nfunc commentAbove() {\n\t// v is a variable\n}\n\nfunc commentBelow() {\n\t// v is a variable\n}\n\nfunc commentSpaceBelow() {\n\n\t// v is a variable\n}\n\nfunc fBool() bool {\n\treturn true\n}\n\nfunc fInt() int {\n\treturn 1\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/testdata/src/decl/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage decl\n\nfunc a() {\n\tvar b, c bool // want `declared (and|but) not used`\n\tpanic(c)\n\n\tif 1 == 1 {\n\t\tvar s string // want `declared (and|but) not used`\n\t}\n}\n\nfunc b() {\n\t// b is a variable\n\tvar b bool // want `declared (and|but) not used`\n}\n\nfunc c() {\n\tvar (\n\t\td string\n\n\t\t// some comment for c\n\t\tc bool // want `declared (and|but) not used`\n\t)\n\n\tpanic(d)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/testdata/src/decl/a.go.golden",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage decl\n\nfunc a() {\n\tvar c bool // want `declared (and|but) not used`\n\tpanic(c)\n\n\tif 1 == 1 {\n\t}\n}\n\nfunc b() {\n\t// b is a variable\n}\n\nfunc c() {\n\tvar (\n\t\td string\n\t)\n\t\n\tpanic(d)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/unusedvariable.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package unusedvariable defines an analyzer that checks for unused variables.\npackage unusedvariable\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/refactor\"\n)\n\nconst Doc = `check for unused variables and suggest fixes`\n\nvar Analyzer = &analysis.Analyzer{\n\tName:             \"unusedvariable\",\n\tDoc:              Doc,\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tRun:              run,\n\tRunDespiteErrors: true, // an unusedvariable diagnostic is a compile error\n\tURL:              \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable\",\n}\n\n// The suffix for this error message changed in Go 1.20 and Go 1.23.\nvar unusedVariableRegexp = []*regexp.Regexp{\n\tregexp.MustCompile(\"^(.*) declared and not used$\"),  // Go 1.20+\n\tregexp.MustCompile(\"^declared and not used: (.*)$\"), // Go 1.23+\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tfor _, typeErr := range pass.TypeErrors {\n\t\tfor _, re := range unusedVariableRegexp {\n\t\t\tmatch := re.FindStringSubmatch(typeErr.Msg)\n\t\t\tif len(match) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Since Go 1.23, go/types' error messages quote vars as `v'.\n\t\t\tvarName := strings.Trim(match[1], \"`'\")\n\n\t\t\tcurId, ok := inspect.Root().FindByPos(typeErr.Pos, typeErr.Pos)\n\t\t\tif !ok {\n\t\t\t\tcontinue // can't find error node\n\t\t\t}\n\t\t\tident, ok := curId.Node().(*ast.Ident)\n\t\t\tif !ok || ident.Name != varName {\n\t\t\t\tcontinue // not the right identifier\n\t\t\t}\n\n\t\t\ttokFile := pass.Fset.File(ident.Pos())\n\t\t\tedits := refactor.DeleteVar(tokFile, pass.TypesInfo, curId)\n\t\t\tif len(edits) > 0 {\n\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\tPos:     ident.Pos(),\n\t\t\t\t\tEnd:     ident.End(),\n\t\t\t\t\tMessage: typeErr.Msg,\n\t\t\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\t\t\tMessage:   fmt.Sprintf(\"Remove variable %s\", ident.Name),\n\t\t\t\t\t\tTextEdits: edits,\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/analysis/unusedvariable/unusedvariable_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage unusedvariable_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedvariable\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\n\tt.Run(\"decl\", func(t *testing.T) {\n\t\tanalysistest.RunWithSuggestedFixes(t, testdata, unusedvariable.Analyzer, \"decl\")\n\t})\n\n\tt.Run(\"assign\", func(t *testing.T) {\n\t\tanalysistest.RunWithSuggestedFixes(t, testdata, unusedvariable.Analyzer, \"assign\")\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/doc.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package writestring defines an Analyzer that detects\n// inefficient string concatenation in uses of WriteString.\n//\n// # Analyzer writestring\n//\n// writestring: detect inefficient string concatenation in uses of WriteString\n//\n// The writestring analyzer offers to replace a call to WriteString(x + y) by\n// two calls WriteString(x); WriteString(y). This is more efficient because it\n// avoids the additional memory allocation produced by string concatenation;\n// instead we just write each string into the buffer directly.\n//\n// It explicitly looks for calls to certain well-known writers such as\n// bytes.Buffer, strings.Builder and bufio.Writer. The analyzer will not suggest\n// a fix for calls to, say, (*os.File).WriteString, because for certain kinds of\n// file such as a UDP socket, it could split a single message into two.\n// Similarly it does not offer fixes when the type of the writer is unknown (as\n// in calls to io.WriteString).\n//\n// For example:\n//\n//\tfunc f(a string, b string) string {\n//\t\t var s strings.Builder\n//\t\t s.WriteString(a+b)\n//\t\t return s.String()\n//\t}\n//\n// would become:\n//\n//\tfunc f(a string, b string) string {\n//\t\tvar s strings.Builder\n//\t\ts.WriteString(a)\n//\t\ts.WriteString(b)\n//\t\treturn s.String()\n//\t}\npackage writestring\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/main.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The writestring command applies the golang.org/x/tools/go/analysis/passes/writestring\n// analysis to the specified packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/passes/writestring\"\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n)\n\nfunc main() { singlechecker.Main(writestring.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/testdata/src/a/a.go",
    "content": "package a\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"hash/maphash\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc _(v string) {\n\tvar s strings.Builder\n\ta := \"a\"\n\tb := \"b\"\n\ts.WriteString(a + b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar p *string\n\ts.WriteString(a + (\"b\" + *p)) // want \"Inefficient string concatenation in call to WriteString\"\n\n\ttype S struct{ B bytes.Buffer }\n\tvar sb S\n\tsb.B.WriteString(a + b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar bufw bufio.Writer\n\tconst k = \"k\"\n\tbufw.WriteString(a + getString() + \"b\") // want \"Inefficient string concatenation in call to WriteString\"\n\tbufw.WriteString(k + \"b\" + v + \"c\")     // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar h maphash.Hash\n\th.WriteString(a + b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar buf bytes.Buffer\n\tbuf.WriteString(a)            // nope - nothing to extract\n\tbuf.WriteString(\"a\" + \"b\")    // nope - no need to split because the concatenation is resolved without allocations\n\tf(buf.WriteString(a + b))     // nope - inside function call\n\t_, _ = buf.WriteString(a + b) // nope - inside assignment\n\tgetBuf().WriteString(a + b)   // nope - function call in receiver\n\tvar bufs []bytes.Buffer\n\tbufs[getIndex()].WriteString(a + b) // nope - index expression in receiver\n\n\tvar f *os.File\n\tf.WriteString(a + b) // nope - os.File is not an allowed writer for this analyzer\n}\n\nfunc f(i int, err error) {}\n\nfunc getIndex() int {\n\treturn 0\n}\n\nfunc getString() string {\n\treturn \"string\"\n}\n\nfunc getBuf() *bytes.Buffer { return &bytes.Buffer{} }\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/testdata/src/a/a.go.golden",
    "content": "package a\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"hash/maphash\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc _(v string) {\n\tvar s strings.Builder\n\ta := \"a\"\n\tb := \"b\"\n\ts.WriteString(a)\n\ts.WriteString(b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar p *string\n\ts.WriteString(a)\n\ts.WriteString(\"b\")\n\ts.WriteString(*p) // want \"Inefficient string concatenation in call to WriteString\"\n\n\ttype S struct{ B bytes.Buffer }\n\tvar sb S\n\tsb.B.WriteString(a)\n\tsb.B.WriteString(b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar bufw bufio.Writer\n\tconst k = \"k\"\n\tbufw.WriteString(a)\n\tbufw.WriteString(getString())\n\tbufw.WriteString(\"b\") // want \"Inefficient string concatenation in call to WriteString\"\n\tbufw.WriteString(k + \"b\")\n\tbufw.WriteString(v)\n\tbufw.WriteString(\"c\") // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar h maphash.Hash\n\th.WriteString(a)\n\th.WriteString(b) // want \"Inefficient string concatenation in call to WriteString\"\n\n\tvar buf bytes.Buffer\n\tbuf.WriteString(a)            // nope - nothing to extract\n\tbuf.WriteString(\"a\" + \"b\")    // nope - no need to split because the concatenation is resolved without allocations\n\tf(buf.WriteString(a + b))     // nope - inside function call\n\t_, _ = buf.WriteString(a + b) // nope - inside assignment\n\tgetBuf().WriteString(a + b)   // nope - function call in receiver\n\tvar bufs []bytes.Buffer\n\tbufs[getIndex()].WriteString(a + b) // nope - index expression in receiver\n\n\tvar f *os.File\n\tf.WriteString(a + b) // nope - os.File is not an allowed writer for this analyzer\n}\n\nfunc f(i int, err error) {}\n\nfunc getIndex() int {\n\treturn 0\n}\n\nfunc getString() string {\n\treturn \"string\"\n}\n\nfunc getBuf() *bytes.Buffer { return &bytes.Buffer{} }\n\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/writestring.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package writestring defines an Analyzer that detects\n// inefficient string concatenation in uses of WriteString.\npackage writestring\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"writestring\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"writestring\"),\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/writestring\",\n\tRequires: []*analysis.Analyzer{inspect.Analyzer},\n\tRun:      run,\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\tfor curCall := range inspect.Root().Preorder((*ast.CallExpr)(nil)) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tinfo := pass.TypesInfo\n\t\tcallee := typeutil.Callee(info, call)\n\t\tif callee == nil || callee.Name() != \"WriteString\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// We intervene only for io.Writer types where we know that WriteString\n\t\t// is cheap and distributes over string concatenation.\n\t\t// (This is not the case for, say, file descriptors, where each write\n\t\t// is expensive, and splitting one UDP write into two is a behavior change.)\n\t\t// TODO(mkalil): This doesn't detect calls to aliases of w.WriteString.\n\t\t// I think it's okay to skip that case because it's uncommon and also\n\t\t// would increase the complexity to determine the type of the writer.\n\t\tif !(typesinternal.IsMethodNamed(callee, \"strings\", \"Builder\", \"WriteString\") ||\n\t\t\ttypesinternal.IsMethodNamed(callee, \"bytes\", \"Buffer\", \"WriteString\") ||\n\t\t\ttypesinternal.IsMethodNamed(callee, \"bufio\", \"Writer\", \"WriteString\") ||\n\t\t\ttypesinternal.IsMethodNamed(callee, \"hash/maphash\", \"Hash\", \"WriteString\")) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// curCall must be a standalone statement. We skip calls used in\n\t\t// assignments, control flow expressions, or defer/go statements, since\n\t\t// splitting them requires complex rewriting of the surrounding logic.\n\t\tif curCall.ParentEdgeKind() != edge.ExprStmt_X {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check that the receiver \"w\" in the call to w.WriteString has no side\n\t\t// effects. For example, if the receiver involves some function call F,\n\t\t// we cannot suggest a fix because duplicate calls to F may result in\n\t\t// unintended behavior.\n\t\t// returnsBuffer().WriteString(...) --> reject\n\t\t// a.B.w.WriteString(...) --> ok\n\t\tif !typesinternal.NoEffects(info, call.Fun) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(call.Args) != 1 {\n\t\t\tcontinue // can't happen\n\t\t}\n\t\targ := call.Args[0]\n\t\tif _, ok := arg.(*ast.BinaryExpr); !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\toperands := stringConcatenands(info, arg)\n\t\tif len(operands) < 2 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Format the separate WriteString calls.\n\t\tvar newStmts []string\n\t\tfor _, operand := range operands {\n\t\t\tstmt := fmt.Sprintf(\"%s(%s)\",\n\t\t\t\tastutil.Format(pass.Fset, call.Fun),\n\t\t\t\tastutil.Format(pass.Fset, operand))\n\t\t\tnewStmts = append(newStmts, stmt)\n\t\t}\n\t\treplacement := strings.Join(newStmts, \";\")\n\n\t\tpass.Report(analysis.Diagnostic{\n\t\t\tPos:     call.Pos(),\n\t\t\tEnd:     call.End(),\n\t\t\tMessage: \"Inefficient string concatenation in call to WriteString\",\n\t\t\tSuggestedFixes: []analysis.SuggestedFix{{\n\t\t\t\tMessage: \"Split into separate WriteString calls\",\n\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\tPos:     call.Pos(),\n\t\t\t\t\tEnd:     call.End(),\n\t\t\t\t\tNewText: []byte(replacement),\n\t\t\t\t}},\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil, nil\n}\n\n// stringConcatenands flattens a string concatenation expression expr\n// (e.g., \"a\" + \"b\" + c) into a sequence of individual operands. It combines\n// adjacent constants or basic literals, whose combined value evaluates to a\n// constant, into a single expression. For example, \"a\" + k + v would return\n// [(\"a\" + k), v]. Writing k and \"a\" separately would be a de-optimization, as\n// we already evaluate the value of this expression at compile time. If the\n// expression cannot be safely flattened, it returns nil.\nfunc stringConcatenands(info *types.Info, expr ast.Expr) (operands []ast.Expr) {\n\tif info.Types[expr].Value != nil {\n\t\treturn []ast.Expr{expr}\n\t}\n\tif bin, ok := ast.Unparen(expr).(*ast.BinaryExpr); ok {\n\t\tif bin.Op != token.ADD {\n\t\t\t// Valid Go code only allows string concatenation via the add\n\t\t\t// operator.\n\t\t\tpanic(\"invalid concatenation operator\")\n\t\t}\n\t\topsX := stringConcatenands(info, bin.X)\n\t\tif opsX == nil {\n\t\t\treturn nil\n\t\t}\n\t\topsY := stringConcatenands(info, bin.Y)\n\t\tif opsY == nil {\n\t\t\treturn nil\n\t\t}\n\t\treturn append(opsX, opsY...)\n\t}\n\treturn []ast.Expr{expr}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/writestring/writestring_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage writestring_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/writestring\"\n)\n\nfunc Test(t *testing.T) {\n\tanalysistest.RunWithSuggestedFixes(t, analysistest.TestData(), writestring.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/analysis/yield/doc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package yield defines an Analyzer that checks for mistakes related\n// to the yield function used in iterators.\n//\n// # Analyzer yield\n//\n// yield: report calls to yield where the result is ignored\n//\n// After a yield function returns false, the caller should not call\n// the yield function again; generally the iterator should return\n// promptly.\n//\n// This example fails to check the result of the call to yield,\n// causing this analyzer to report a diagnostic:\n//\n//\tyield(1) // yield may be called again (on L2) after returning false\n//\tyield(2)\n//\n// The corrected code is either this:\n//\n//\tif yield(1) { yield(2) }\n//\n// or simply:\n//\n//\t_ = yield(1) && yield(2)\n//\n// It is not always a mistake to ignore the result of yield.\n// For example, this is a valid single-element iterator:\n//\n//\tyield(1) // ok to ignore result\n//\treturn\n//\n// It is only a mistake when the yield call that returned false may be\n// followed by another call.\npackage yield\n"
  },
  {
    "path": "gopls/internal/analysis/yield/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The yield command applies the yield analyzer to the specified\n// packages of Go source code.\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis/singlechecker\"\n\t\"golang.org/x/tools/gopls/internal/analysis/yield\"\n)\n\nfunc main() { singlechecker.Main(yield.Analyzer) }\n"
  },
  {
    "path": "gopls/internal/analysis/yield/testdata/src/a/a.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage yield\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"iter\"\n\t\"runtime\"\n)\n\n// Modify this block of comment lines as needed when changing imports\n// to avoid perturbing subsequent line numbers (and thus error messages).\n//\n// This is L16.\n\nfunc goodIter(yield func(int) bool) {\n\t_ = yield(1) && yield(2) && yield(3) // ok\n}\n\nfunc badIterOR(yield func(int) bool) {\n\t_ = yield(1) || // want `yield may be called again \\(on L25\\) after returning false`\n\t\tyield(2) || // want `yield may be called again \\(on L26\\) after returning false`\n\t\tyield(3)\n}\n\nfunc badIterSeq(yield func(int) bool) {\n\tyield(1) // want `yield may be called again \\(on L31\\) after returning false`\n\tyield(2) // want `yield may be called again \\(on L32\\) after returning false`\n\tyield(3) // ok\n}\n\nfunc badIterLoop(yield func(int) bool) {\n\tfor {\n\t\tyield(1) // want `yield may be called again after returning false`\n\t}\n}\n\nfunc goodIterLoop(yield func(int) bool) {\n\tfor {\n\t\tif !yield(1) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc badIterIf(yield func(int) bool) {\n\tok := yield(1) // want `yield may be called again \\(on L52\\) after returning false`\n\tif !ok {\n\t\tyield(2)\n\t} else {\n\t\tyield(3)\n\t}\n}\n\nfunc singletonIter(yield func(int) bool) {\n\tyield(1) // ok\n}\n\nfunc twoArgumentYield(yield func(int, int) bool) {\n\t_ = yield(1, 1) || // want `yield may be called again \\(on L64\\) after returning false`\n\t\tyield(2, 2)\n}\n\nfunc zeroArgumentYield(yield func() bool) {\n\t_ = yield() || // want `yield may be called again \\(on L69\\) after returning false`\n\t\tyield()\n}\n\nfunc tricky(in io.ReadCloser) func(yield func(string, error) bool) {\n\treturn func(yield func(string, error) bool) {\n\t\tscan := bufio.NewScanner(in)\n\t\tfor scan.Scan() {\n\t\t\tif !yield(scan.Text(), nil) { // want `yield may be called again \\(on L82\\) after returning false`\n\t\t\t\t_ = in.Close()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif err := scan.Err(); err != nil {\n\t\t\tyield(\"\", err)\n\t\t}\n\t}\n}\n\n// Regression test for issue #70598.\nfunc shortCircuitAND(yield func(int) bool) {\n\tok := yield(1)\n\tok = ok && yield(2)\n\tok = ok && yield(3)\n\tok = ok && yield(4)\n}\n\n// This example has a bug because a false yield(2) may be followed by yield(3).\nfunc tricky2(yield func(int) bool) {\n\tcleanup := func() {}\n\tok := yield(1)          // want \"yield may be called again .on L104\"\n\tstop := !ok || yield(2) // want \"yield may be called again .on L104\"\n\tif stop {\n\t\tcleanup()\n\t} else {\n\t\t// dominated by !stop => !(!ok || yield(2)) => yield(1) && !yield(2): bad.\n\t\tyield(3)\n\t}\n}\n\n// This case from issue #74136 is sound, and should produce no diagnostic.\nfunc tricky3(yield func(int) bool) {\n\tcleanup := func() {}\n\tok := yield(1)\n\tstop := !ok || !yield(2)\n\tif stop {\n\t\tcleanup()\n\t} else {\n\t\t// dominated by !stop => !(!ok || !yield(2)) => yield(1) && yield(2): good.\n\t\tyield(3)\n\t}\n}\n\n// So is this one, from issue #75924\nfunc tricky5(list []string, cond bool) iter.Seq[string] {\n\treturn func(yield func(string) bool) {\n\t\tfor _, s := range list {\n\t\t\tvar ok bool\n\t\t\tif cond {\n\t\t\t\tok = yield(s)\n\t\t\t} else {\n\t\t\t\tok = yield(s)\n\t\t\t}\n\t\t\tif !ok {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// This one is from the tests of the \"iter\" package.\nfunc tricky6() iter.Seq[int] {\n\treturn func(yield func(int) bool) {\n\t\tfor {\n\t\t\tif !yield(55) { // nope\n\t\t\t\truntime.Goexit()\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Regression test for issue #77681. A boolean switch is now\n// handled just like an if/else chain in the SSA builder.\nfunc switchShortCircuit(seq iter.Seq[int]) iter.Seq[int] {\n\treturn func(yield func(int) bool) {\n\t\tfor item := range seq {\n\t\t\tisZero := item == 0\n\t\t\tswitch {\n\t\t\tcase !isZero && !yield(item): // ok\n\t\t\t\treturn\n\t\t\tcase !isZero:\n\t\t\t\tcontinue\n\t\t\tcase !yield(0): // ok\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/analysis/yield/yield.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage yield\n\n// TODO(adonovan): also check for this pattern:\n//\n// \tfor x := range seq {\n// \t\tyield(x)\n// \t}\n//\n// which should be entirely rewritten as\n//\n// \tseq(yield)\n//\n// to avoid unnecessary range desugaring and chains of dynamic calls.\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/buildssa\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\n//go:embed doc.go\nvar doc string\n\nvar Analyzer = &analysis.Analyzer{\n\tName:     \"yield\",\n\tDoc:      analyzerutil.MustExtractDoc(doc, \"yield\"),\n\tRequires: []*analysis.Analyzer{inspect.Analyzer, buildssa.Analyzer},\n\tRun:      run,\n\tURL:      \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/yield\",\n}\n\nfunc run(pass *analysis.Pass) (any, error) {\n\tinspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\n\t// Find all calls to yield of the right type.\n\tyieldCalls := make(map[token.Pos]*ast.CallExpr) // keyed by CallExpr.Lparen.\n\tnodeFilter := []ast.Node{(*ast.CallExpr)(nil)}\n\tinspector.Preorder(nodeFilter, func(n ast.Node) {\n\t\tcall := n.(*ast.CallExpr)\n\t\tif id, ok := call.Fun.(*ast.Ident); ok && id.Name == \"yield\" {\n\t\t\tif sig, ok := pass.TypesInfo.TypeOf(id).(*types.Signature); ok &&\n\t\t\t\tsig.Params().Len() < 3 &&\n\t\t\t\tsig.Results().Len() == 1 &&\n\t\t\t\ttypes.Identical(sig.Results().At(0).Type(), types.Typ[types.Bool]) {\n\t\t\t\tyieldCalls[call.Lparen] = call\n\t\t\t}\n\t\t}\n\t})\n\n\t// Common case: nothing to do.\n\tif len(yieldCalls) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t// Study the control flow using SSA.\n\tbuildssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)\n\tfor _, fn := range buildssa.SrcFuncs {\n\t\t// TODO(adonovan): opt: skip functions that don't contain any yield calls.\n\n\t\t// Find the yield calls in SSA.\n\t\ttype callInfo struct {\n\t\t\tsyntax   *ast.CallExpr\n\t\t\tindex    int // index of instruction within its block\n\t\t\treported bool\n\t\t}\n\t\tssaYieldCalls := make(map[*ssa.Call]*callInfo)\n\t\tfor _, b := range fn.Blocks {\n\t\t\tfor i, instr := range b.Instrs {\n\t\t\t\tif call, ok := instr.(*ssa.Call); ok {\n\t\t\t\t\tif syntax, ok := yieldCalls[call.Pos()]; ok {\n\t\t\t\t\t\tssaYieldCalls[call] = &callInfo{syntax: syntax, index: i}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tisYieldCall := func(v ssa.Value) bool {\n\t\t\tcall, ok := v.(*ssa.Call)\n\t\t\treturn ok && ssaYieldCalls[call] != nil\n\t\t}\n\n\t\t// Now search for a control path from the instruction after a\n\t\t// yield call to another yield call--possible the same one,\n\t\t// following all block successors except \"if yield() { ... }\";\n\t\t// in such cases we know that yield returned true.\n\t\t//\n\t\t// Note that this is a \"may\" dataflow analysis: it\n\t\t// reports when a yield function _may_ be called again\n\t\t// without a positive intervening check, but it is\n\t\t// possible that the check is beyond the ability of\n\t\t// the representation to detect, perhaps involving\n\t\t// sophisticated use of booleans, indirect state (not\n\t\t// in SSA registers), or multiple flow paths some of\n\t\t// which are infeasible.\n\t\t//\n\t\t// A \"must\" analysis (which would report when a second\n\t\t// yield call can only be reached after failing the\n\t\t// boolean check) would be too conservative.\n\t\t// In particular, the most common mistake is to\n\t\t// forget to check the boolean at all.\n\t\tfor call, info := range ssaYieldCalls {\n\t\t\tvisited := make([]bool, len(fn.Blocks)) // visited BasicBlock.Indexes\n\n\t\t\t// visit visits the instructions of a block (or a suffix if start > 0).\n\t\t\tvar visit func(b *ssa.BasicBlock, start int)\n\t\t\tvisit = func(b *ssa.BasicBlock, start int) {\n\t\t\t\tif visited[b.Index] {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif start == 0 {\n\t\t\t\t\tvisited[b.Index] = true\n\t\t\t\t}\n\t\t\t\tfor _, instr := range b.Instrs[start:] {\n\t\t\t\t\tswitch instr := instr.(type) {\n\t\t\t\t\tcase *ssa.Call:\n\n\t\t\t\t\t\t// Precondition: v has a pos within a CallExpr.\n\t\t\t\t\t\tenclosingCall := func(v ssa.Value) ast.Node {\n\t\t\t\t\t\t\tpos := v.Pos()\n\t\t\t\t\t\t\tcur, ok := inspector.Root().FindByPos(pos, pos)\n\t\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\t\tpanic(fmt.Sprintf(\"can't find node at %v\", safetoken.StartPosition(pass.Fset, pos)))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcall, _ := cursorutil.FirstEnclosing[*ast.CallExpr](cur)\n\t\t\t\t\t\t\tif call == nil {\n\t\t\t\t\t\t\t\tpanic(fmt.Sprintf(\"no call enclosing %v\", safetoken.StartPosition(pass.Fset, pos)))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn call\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif !info.reported && ssaYieldCalls[instr] != nil {\n\t\t\t\t\t\t\tinfo.reported = true\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\twhere   = \"\" // \"\" => same yield call (a loop)\n\t\t\t\t\t\t\t\trelated []analysis.RelatedInformation\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t// Also report location of reached yield call, if distinct.\n\t\t\t\t\t\t\tif instr != call {\n\t\t\t\t\t\t\t\totherLine := safetoken.StartPosition(pass.Fset, instr.Pos()).Line\n\t\t\t\t\t\t\t\twhere = fmt.Sprintf(\"(on L%d) \", otherLine)\n\t\t\t\t\t\t\t\totherCallExpr := enclosingCall(instr)\n\t\t\t\t\t\t\t\trelated = []analysis.RelatedInformation{{\n\t\t\t\t\t\t\t\t\tPos:     otherCallExpr.Pos(),\n\t\t\t\t\t\t\t\t\tEnd:     otherCallExpr.End(),\n\t\t\t\t\t\t\t\t\tMessage: \"other call here\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcallExpr := enclosingCall(call)\n\t\t\t\t\t\t\tpass.Report(analysis.Diagnostic{\n\t\t\t\t\t\t\t\tPos:     callExpr.Pos(),\n\t\t\t\t\t\t\t\tEnd:     callExpr.End(),\n\t\t\t\t\t\t\t\tMessage: fmt.Sprintf(\"yield may be called again %safter returning false\", where),\n\t\t\t\t\t\t\t\tRelated: related,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ssa.If:\n\t\t\t\t\t\t// Visit both successors, unless cond is yield() or its negation.\n\t\t\t\t\t\t// In that case visit only the \"if !yield()\" block.\n\t\t\t\t\t\tt, f := reachableSuccs(instr.Cond, isYieldCall)\n\t\t\t\t\t\tif t {\n\t\t\t\t\t\t\tvisit(b.Succs[0], 0)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif f {\n\t\t\t\t\t\t\tvisit(b.Succs[1], 0)\n\t\t\t\t\t\t}\n\n\t\t\t\t\tcase *ssa.Jump:\n\t\t\t\t\t\tvisit(b.Succs[0], 0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start at the instruction after the yield call.\n\t\t\tvisit(call.Block(), info.index+1)\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n\n// reachableSuccs reports whether the (true, false) outcomes of the\n// condition are possible.\nfunc reachableSuccs(cond ssa.Value, isYieldCall func(ssa.Value) bool) (_t, _f bool) {\n\t// If the condition is...\n\t//\n\t// ...a constant, we know only one successor is reachable.\n\t//\n\t// ...a yield call, we assume that it returned false,\n\t// and treat it like a constant.\n\t//\n\t// ...a negation !v, we strip the negation and flip the sense\n\t// of the result.\n\t//\n\t// ...a phi node, we recursively find all non-phi leaves\n\t// of the phi graph and treat them like a conjunction,\n\t// e.g. if false || true || yield || yield { ... }.\n\t//\n\t// (We don't actually analyze || and && in this way,\n\t// but we could do them too.)\n\n\t// This logic addresses cases where conditions are\n\t// materialized as booleans such as this\n\t//\n\t//   ok := yield()\n\t//   ok = ok && yield()\n\t//   ok = ok && yield()\n\t//\n\t// which in SSA becomes:\n\t//\n\t//   yield()\n\t//   phi(false, yield())\n\t//   phi(false, yield())\n\t//\n\t// and we can reduce each phi(false, x) to just x.\n\t//\n\t// Similarly this case:\n\t//\n\t//\tvar ok bool\n\t//\tif foo { ok = yield() }\n\t//\telse   { ok = yield() }\n\t//\tif ok { ... }\n\t//\n\t// can be analyzed as \"if yield || yield\".\n\n\t// all[false] => all cases are false\n\t// all[true]  => all cases are true\n\tall := [2]bool{true, true}\n\tfor v := range unphi(cond) {\n\t\tsense := 1 // 0=false 1=true\n\n\t\t// Strip off any NOT operators.\n\t\tfor {\n\t\t\tunop, ok := v.(*ssa.UnOp)\n\t\t\tif !(ok && unop.Op == token.NOT) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tv = unop.X\n\t\t\tsense = 1 - sense\n\t\t}\n\n\t\tswitch {\n\t\tcase is[*ssa.Const](v):\n\t\t\t// \"if false\" means not all cases are true,\n\t\t\t// and vice versa.\n\t\t\tif constant.BoolVal(v.(*ssa.Const).Value) {\n\t\t\t\tsense = 1 - sense\n\t\t\t}\n\t\t\tall[sense] = false\n\n\t\tcase isYieldCall(v):\n\t\t\t// \"if yield\" is assumed to be false.\n\t\t\tall[sense] = false // ¬ all cases are true\n\n\t\tdefault:\n\t\t\t// Unknown condition:\n\t\t\t// ¬ all cases are false\n\t\t\t// ¬ all cases are true\n\t\t\treturn true, true\n\t\t}\n\t}\n\tif all[0] && all[1] {\n\t\tpanic(\"unphi returned empty sequence\")\n\t}\n\treturn !all[0], !all[1]\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\n// -- SSA helpers --\n\n// unphi returns the sequence of values formed by recursively\n// replacing phi nodes in v by their non-phi operands.\nfunc unphi(v ssa.Value) iter.Seq[ssa.Value] {\n\treturn func(yield func(ssa.Value) bool) {\n\t\t_ = every(v, yield)\n\t}\n}\n\n// every reports whether predicate f is true of each value in the\n// sequence formed by recursively replacing phi nodes in v by their\n// operands.\nfunc every(v ssa.Value, f func(ssa.Value) bool) bool {\n\tvar seen map[*ssa.Phi]bool\n\tvar visit func(v ssa.Value) bool\n\tvisit = func(v ssa.Value) bool {\n\t\tif phi, ok := v.(*ssa.Phi); ok {\n\t\t\tif !seen[phi] {\n\t\t\t\tif seen == nil {\n\t\t\t\t\tseen = make(map[*ssa.Phi]bool)\n\t\t\t\t}\n\t\t\t\tseen[phi] = true\n\t\t\t\tfor _, edge := range phi.Edges {\n\t\t\t\t\tif !visit(edge) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\treturn f(v)\n\t}\n\treturn visit(v)\n}\n"
  },
  {
    "path": "gopls/internal/analysis/yield/yield_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage yield_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/gopls/internal/analysis/yield\"\n)\n\nfunc Test(t *testing.T) {\n\ttestdata := analysistest.TestData()\n\tanalysistest.Run(t, testdata, yield.Analyzer, \"a\")\n}\n"
  },
  {
    "path": "gopls/internal/bloom/filter.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bloom\n\nimport (\n\t\"hash/maphash\"\n\t\"math\"\n)\n\n// block is the element type of the filter bitfield.\ntype block = uint8\n\nconst blockBits = 8\n\n// Filter is a bloom filter for a set of strings.\ntype Filter struct {\n\tseeds  []maphash.Seed\n\tblocks []block\n}\n\n// NewFilter constructs a new Filter with the given elements.\nfunc NewFilter(elems []string) *Filter {\n\t// Tolerate a 5% false positive rate.\n\tnblocks, nseeds := calibrate(0.05, len(elems))\n\tf := &Filter{\n\t\tblocks: make([]block, nblocks),\n\t\tseeds:  make([]maphash.Seed, nseeds),\n\t}\n\tfor i := range nseeds {\n\t\tf.seeds[i] = maphash.MakeSeed()\n\t}\n\tfor _, elem := range elems {\n\t\tfor _, seed := range f.seeds {\n\t\t\tindex, bit := f.locate(seed, elem)\n\t\t\tf.blocks[index] |= bit\n\t\t}\n\t}\n\treturn f\n}\n\n// locate returns the block index and bit corresponding to the given hash seed and\n// string.\nfunc (f *Filter) locate(seed maphash.Seed, s string) (index int, bit block) {\n\th := uint(maphash.String(seed, s))\n\tblk := h / blockBits % uint(len(f.blocks))\n\tbit = block(1 << (h % blockBits))\n\treturn int(blk), bit\n}\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n\n// calibrate approximates the number of blocks and seeds to use for a bloom\n// filter with desired false positive rate fpRate, given n elements.\nfunc calibrate(fpRate float64, n int) (blocks, seeds int) {\n\t// We following the terms of https://en.wikipedia.org/wiki/Bloom_filter:\n\t// - k is the number of hash functions,\n\t// - m is the size of the bit field;\n\t// - n is the number of set bits.\n\n\tassert(0 < fpRate && fpRate < 1, \"invalid false positive rate\")\n\tassert(n >= 0, \"invalid set size\")\n\n\tif n == 0 {\n\t\t// degenerate case; use the simplest filter\n\t\treturn 1, 1\n\t}\n\n\t// Calibrate the number of blocks based on the optimal number of bits per\n\t// element. In this case we round up, as more bits leads to fewer false\n\t// positives.\n\tlogFpRate := math.Log(fpRate) // reused for k below\n\tm := -(float64(n) * logFpRate) / (math.Ln2 * math.Ln2)\n\tblocks = int(m) / blockBits\n\tif float64(blocks*blockBits) < m {\n\t\tblocks += 1\n\t}\n\n\t// Estimate the number of hash functions (=seeds). This is imprecise, not\n\t// least since the formula in the article above assumes that the number of\n\t// bits per element is not rounded.\n\t//\n\t// Here we round to the nearest integer (not unconditionally round up), since\n\t// more hash functions do not always lead to better results.\n\tk := -logFpRate / math.Ln2\n\tseeds = max(int(math.Round(k)), 1)\n\n\treturn blocks, seeds\n}\n\n// MayContain reports whether the filter may contain s.\nfunc (f *Filter) MayContain(s string) bool {\n\tfor _, seed := range f.seeds {\n\t\tindex, bit := f.locate(seed, s)\n\t\tif f.blocks[index]&bit == 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "gopls/internal/bloom/filter_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bloom\n\nimport (\n\t\"math\"\n\t\"math/rand/v2\"\n\t\"testing\"\n)\n\nfunc TestFilter(t *testing.T) {\n\telems := []string{\n\t\t\"a\", \"apple\", \"b\", \"banana\", \"an arbitrarily long string\", \"\", \"世界\",\n\t}\n\n\t// First, sanity check that the filter contains all the given elements.\n\tf := NewFilter(elems)\n\tfor _, elem := range elems {\n\t\tif got := f.MayContain(elem); !got {\n\t\t\tt.Errorf(\"MayContain(%q) = %t, want true\", elem, got)\n\t\t}\n\t}\n\n\t// Measure the false positives rate.\n\t//\n\t// Of course, we can't assert on the results, since they are probabilistic,\n\t// but this can be useful for interactive use.\n\n\tfpRate := falsePositiveRate(len(f.blocks), len(f.seeds), len(elems))\n\tt.Logf(\"%d blocks, %d seeds, %.2g%% expected false positives\", len(f.blocks), len(f.seeds), 100*fpRate)\n\n\t// In practice, all positives below will be false, but be precise anyway.\n\ttruePositive := make(map[string]bool)\n\tfor _, e := range elems {\n\t\ttruePositive[e] = true\n\t}\n\n\t// Generate a large number of random strings to measure the false positive\n\t// rate.\n\tg := newStringGenerator()\n\tconst samples = 1000\n\tfalsePositives := 0\n\tfor range samples {\n\t\ts := g.next()\n\t\tgot := f.MayContain(s)\n\t\tif false {\n\t\t\tt.Logf(\"MayContain(%q) = %t\", s, got)\n\t\t}\n\t\tif got && !truePositive[s] {\n\t\t\tfalsePositives++\n\t\t}\n\t}\n\tt.Logf(\"false positives: %.1f%% (%d/%d)\", 100*float64(falsePositives)/float64(samples), falsePositives, samples)\n}\n\n// falsePositiveRate estimates the expected false positive rate for a filter\n// with the given number of blocks, seeds, and elements.\nfunc falsePositiveRate(block, seeds, elems int) float64 {\n\tk, m, n := float64(seeds), float64(block*blockBits), float64(elems)\n\treturn math.Pow(1-math.Exp(-k*n/m), k)\n}\n\ntype stringGenerator struct {\n\tr *rand.Rand\n}\n\nfunc newStringGenerator() *stringGenerator {\n\treturn &stringGenerator{rand.New(rand.NewPCG(1, 2))}\n}\n\nfunc (g *stringGenerator) next() string {\n\tl := g.r.IntN(50) // length\n\tvar runes []rune\n\tfor range l {\n\t\trunes = append(runes, rune(' '+rand.IntN('~'-' ')))\n\t}\n\treturn string(runes)\n}\n\n// TestDegenerateFilter checks that the degenerate filter with no elements\n// results in no false positives.\nfunc TestDegenerateFilter(t *testing.T) {\n\tf := NewFilter(nil)\n\tg := newStringGenerator()\n\tfor range 100 {\n\t\ts := g.next()\n\t\tif f.MayContain(s) {\n\t\t\tt.Errorf(\"MayContain(%q) = true, want false\", s)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/analysis.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\n// This file defines gopls' driver for modular static analysis (go/analysis).\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\turlpkg \"net/url\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/persistent\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/facts\"\n)\n\n/*\n\n   DESIGN\n\n   An analysis request ([Snapshot.Analyze]) computes diagnostics for the\n   requested packages using the set of analyzers enabled in this view. Each\n   request constructs a transitively closed DAG of nodes, each representing a\n   package, then works bottom up in parallel postorder calling\n   [analysisNode.runCached] to ensure that each node's analysis summary is up\n   to date. The summary contains the analysis diagnostics and serialized facts.\n\n   The entire DAG is ephemeral. Each node in the DAG records the set of\n   analyzers to run: the complete set for the root packages, and the \"facty\"\n   subset for dependencies. Each package is thus analyzed at most once.\n\n   Each node has a cryptographic key, which is either memoized in the Snapshot\n   or computed by [analysisNode.cacheKey]. This key is a hash of the \"recipe\"\n   for the analysis step, including the inputs into the type checked package\n   (and its reachable dependencies), the set of analyzers, and importable\n   facts.\n\n   The key is sought in a machine-global persistent file-system based cache. If\n   this gopls process, or another gopls process on the same machine, has\n   already performed this analysis step, runCached will make a cache hit and\n   load the serialized summary of the results. If not, it will have to proceed\n   to run() to parse and type-check the package and then apply a set of\n   analyzers to it. (The set of analyzers applied to a single package itself\n   forms a graph of \"actions\", and it too is evaluated in parallel postorder;\n   these dependency edges within the same package are called \"horizontal\".)\n   Finally it writes a new cache entry containing serialized diagnostics and\n   analysis facts.\n\n   The summary must record whether a package is transitively error-free\n   (whether it would compile) because many analyzers are not safe to run on\n   packages with inconsistent types.\n\n   For fact encoding, we use the same fact set as the unitchecker (vet) to\n   record and serialize analysis facts. The fact serialization mechanism is\n   analogous to \"deep\" export data.\n\n*/\n\n// TODO(adonovan):\n// - Add a (white-box) test of pruning when a change doesn't affect export data.\n// - Optimise pruning based on subset of packages mentioned in exportdata.\n// - Better logging so that it is possible to deduce why an analyzer is not\n//   being run--often due to very indirect failures. Even if the ultimate\n//   consumer decides to ignore errors, tests and other situations want to be\n//   assured of freedom from errors, not just missing results. This should be\n//   recorded.\n\n// AnalysisProgressTitle is the title of the progress report for ongoing\n// analysis. It is sought by regression tests for the progress reporting\n// feature.\nconst AnalysisProgressTitle = \"Analyzing Dependencies\"\n\n// Analyze applies the set of enabled analyzers to the packages in the pkgs\n// map, and returns their diagnostics.\n//\n// Notifications of progress may be sent to the optional reporter.\nfunc (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Package, reporter *progress.Tracker) ([]*Diagnostic, error) {\n\tstart := time.Now() // for progress reporting\n\n\tvar tagStr string // sorted comma-separated list of PackageIDs\n\t{\n\t\tkeys := make([]string, 0, len(pkgs))\n\t\tfor id := range pkgs {\n\t\t\tkeys = append(keys, string(id))\n\t\t}\n\t\tsort.Strings(keys)\n\t\ttagStr = strings.Join(keys, \",\")\n\t}\n\tctx, done := event.Start(ctx, \"snapshot.Analyze\", label.Package.Of(tagStr))\n\tdefer done()\n\n\t// Filter and sort enabled root analyzers.\n\t// A disabled analyzer may still be run if required by another.\n\tvar (\n\t\ttoSrc            = make(map[*analysis.Analyzer]*settings.Analyzer)\n\t\tenabledAnalyzers []*analysis.Analyzer // enabled subset + transitive requirements\n\t)\n\tfor _, a := range settings.AllAnalyzers {\n\t\tif a.Enabled(s.Options()) {\n\t\t\ttoSrc[a.Analyzer()] = a\n\t\t\tenabledAnalyzers = append(enabledAnalyzers, a.Analyzer())\n\t\t}\n\t}\n\tsort.Slice(enabledAnalyzers, func(i, j int) bool {\n\t\treturn enabledAnalyzers[i].Name < enabledAnalyzers[j].Name\n\t})\n\n\tenabledAnalyzers = requiredAnalyzers(enabledAnalyzers)\n\n\t// Perform basic sanity checks.\n\t// (Ideally we would do this only once.)\n\tif err := analysis.Validate(enabledAnalyzers); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid analyzer configuration: %v\", err)\n\t}\n\n\tstableNames := make(map[*analysis.Analyzer]string)\n\n\tvar facty []*analysis.Analyzer // facty subset of enabled + transitive requirements\n\tfor _, a := range enabledAnalyzers {\n\t\t// TODO(adonovan): reject duplicate stable names (very unlikely).\n\t\tstableNames[a] = stableName(a)\n\n\t\t// Register fact types of all required analyzers.\n\t\tif len(a.FactTypes) > 0 {\n\t\t\tfacty = append(facty, a)\n\t\t\tfor _, f := range a.FactTypes {\n\t\t\t\tgob.Register(f) // <2us\n\t\t\t}\n\t\t}\n\t}\n\tfacty = requiredAnalyzers(facty)\n\n\tbatch, release := s.acquireTypeChecking()\n\tdefer release()\n\n\tids := moremaps.KeySlice(pkgs)\n\thandles, err := s.getPackageHandles(ctx, ids)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbatch.addHandles(handles)\n\n\t// Starting from the root packages and following DepsByPkgPath,\n\t// build the DAG of packages we're going to analyze.\n\t//\n\t// Root nodes will run the enabled set of analyzers,\n\t// whereas dependencies will run only the facty set.\n\t// Because (by construction) enabled is a superset of facty,\n\t// we can analyze each node with exactly one set of analyzers.\n\tnodes := make(map[PackageID]*analysisNode)\n\tvar leaves []*analysisNode // nodes with no unfinished successors\n\tvar makeNode func(from *analysisNode, id PackageID) (*analysisNode, error)\n\tmakeNode = func(from *analysisNode, id PackageID) (*analysisNode, error) {\n\t\tan, ok := nodes[id]\n\t\tif !ok {\n\t\t\tph := handles[id]\n\t\t\tif ph == nil {\n\t\t\t\treturn nil, bug.Errorf(\"no metadata for %s\", id)\n\t\t\t}\n\n\t\t\t// -- preorder --\n\n\t\t\tan = &analysisNode{\n\t\t\t\tparseCache:  s.view.parseCache,\n\t\t\t\tfsource:     s, // expose only ReadFile\n\t\t\t\tbatch:       batch,\n\t\t\t\tph:          ph,\n\t\t\t\tanalyzers:   facty, // all nodes run at least the facty analyzers\n\t\t\t\tstableNames: stableNames,\n\t\t\t}\n\t\t\tnodes[id] = an\n\n\t\t\t// -- recursion --\n\n\t\t\t// Build subgraphs for dependencies.\n\t\t\tan.succs = make(map[PackageID]*analysisNode, len(ph.mp.DepsByPkgPath))\n\t\t\tfor _, depID := range ph.mp.DepsByPkgPath {\n\t\t\t\tdep, err := makeNode(an, depID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tan.succs[depID] = dep\n\t\t\t}\n\n\t\t\t// -- postorder --\n\n\t\t\t// Add leaf nodes (no successors) directly to queue.\n\t\t\tif len(an.succs) == 0 {\n\t\t\t\tleaves = append(leaves, an)\n\t\t\t}\n\t\t}\n\t\t// Add edge from predecessor.\n\t\tif from != nil {\n\t\t\tfrom.unfinishedSuccs.Add(+1) // incref\n\t\t\tan.preds = append(an.preds, from)\n\t\t}\n\t\t// Increment unfinishedPreds even for root nodes (from==nil), so that their\n\t\t// Action summaries are never cleared.\n\t\tan.unfinishedPreds.Add(+1)\n\t\treturn an, nil\n\t}\n\n\t// For root packages, we run the enabled set of analyzers.\n\tvar roots []*analysisNode\n\tfor id := range pkgs {\n\t\troot, err := makeNode(nil, id)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\troot.analyzers = enabledAnalyzers\n\t\troots = append(roots, root)\n\t}\n\n\t// Progress reporting. If supported, gopls reports progress on analysis\n\t// passes that are taking a long time.\n\tmaybeReport := func(completed int64) {}\n\n\t// Enable progress reporting if enabled by the user\n\t// and we have a capable reporter.\n\tif reporter != nil && reporter.SupportsWorkDoneProgress() && s.Options().AnalysisProgressReporting {\n\t\tvar reportAfter = s.Options().ReportAnalysisProgressAfter // tests may set this to 0\n\t\tconst reportEvery = 1 * time.Second\n\n\t\tctx, cancel := context.WithCancel(ctx)\n\t\tdefer cancel()\n\n\t\tvar (\n\t\t\treportMu   sync.Mutex\n\t\t\tlastReport time.Time\n\t\t\twd         *progress.WorkDone\n\t\t)\n\t\tdefer func() {\n\t\t\treportMu.Lock()\n\t\t\tdefer reportMu.Unlock()\n\n\t\t\tif wd != nil {\n\t\t\t\twd.End(ctx, \"Done.\") // ensure that the progress report exits\n\t\t\t}\n\t\t}()\n\t\tmaybeReport = func(completed int64) {\n\t\t\tnow := time.Now()\n\t\t\tif now.Sub(start) < reportAfter {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\treportMu.Lock()\n\t\t\tdefer reportMu.Unlock()\n\n\t\t\tif wd == nil {\n\t\t\t\twd = reporter.Start(ctx, AnalysisProgressTitle, \"\", nil, cancel)\n\t\t\t}\n\n\t\t\tif now.Sub(lastReport) > reportEvery {\n\t\t\t\tlastReport = now\n\t\t\t\t// Trailing space is intentional: some LSP clients strip newlines.\n\t\t\t\tmsg := fmt.Sprintf(`Indexed %d/%d packages. (Set \"analysisProgressReporting\" to false to disable notifications.)`,\n\t\t\t\t\tcompleted, len(nodes))\n\t\t\t\twd.Report(ctx, msg, float64(completed)/float64(len(nodes)))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Execute phase: run leaves first, adding\n\t// new nodes to the queue as they become leaves.\n\tvar g errgroup.Group\n\n\t// Analysis is CPU-bound.\n\t//\n\t// Note: avoid g.SetLimit here: it makes g.Go stop accepting work, which\n\t// prevents workers from enqeuing, and thus finishing, and thus allowing the\n\t// group to make progress: deadlock.\n\tlimiter := make(chan unit, runtime.GOMAXPROCS(0))\n\tvar completed atomic.Int64\n\n\tvar enqueue func(*analysisNode)\n\tenqueue = func(an *analysisNode) {\n\t\tg.Go(func() error {\n\t\t\tlimiter <- unit{}\n\t\t\tdefer func() { <-limiter }()\n\n\t\t\t// Check to see if we already have a valid cache key. If not, compute it.\n\t\t\t//\n\t\t\t// The snapshot field that memoizes keys depends on whether this key is\n\t\t\t// for the analysis result including all enabled analyzer, or just facty analyzers.\n\t\t\tvar keys *persistent.Map[PackageID, file.Hash]\n\t\t\tif _, root := pkgs[an.ph.mp.ID]; root {\n\t\t\t\tkeys = s.fullAnalysisKeys\n\t\t\t} else {\n\t\t\t\tkeys = s.factyAnalysisKeys\n\t\t\t}\n\n\t\t\t// As keys is referenced by a snapshot field, it's guarded by s.mu.\n\t\t\ts.mu.Lock()\n\t\t\tkey, keyFound := keys.Get(an.ph.mp.ID)\n\t\t\ts.mu.Unlock()\n\n\t\t\tif !keyFound {\n\t\t\t\tkey = an.cacheKey()\n\t\t\t\ts.mu.Lock()\n\t\t\t\tkeys.Set(an.ph.mp.ID, key, nil)\n\t\t\t\ts.mu.Unlock()\n\t\t\t}\n\n\t\t\tsummary, err := an.runCached(ctx, key)\n\t\t\tif err != nil {\n\t\t\t\treturn err // cancelled, or failed to produce a package\n\t\t\t}\n\n\t\t\tmaybeReport(completed.Add(1))\n\t\t\tan.summary = summary\n\n\t\t\t// Notify each waiting predecessor,\n\t\t\t// and enqueue it when it becomes a leaf.\n\t\t\tfor _, pred := range an.preds {\n\t\t\t\tif pred.unfinishedSuccs.Add(-1) == 0 { // decref\n\t\t\t\t\tenqueue(pred)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Notify each successor that we no longer need\n\t\t\t// its action summaries, which hold Result values.\n\t\t\t// After the last one, delete it, so that we\n\t\t\t// free up large results such as SSA.\n\t\t\tfor _, succ := range an.succs {\n\t\t\t\tsucc.decrefPreds()\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tfor _, leaf := range leaves {\n\t\tenqueue(leaf)\n\t}\n\tif err := g.Wait(); err != nil {\n\t\treturn nil, err // cancelled, or failed to produce a package\n\t}\n\n\t// Inv: all root nodes now have a summary (#66732).\n\t//\n\t// We know this is falsified empirically. This means either\n\t// the summary was \"successfully\" set to nil (above), or there\n\t// is a problem with the graph such the enqueuing leaves does\n\t// not lead to completion of roots (or an error).\n\tfor _, root := range roots {\n\t\tif root.summary == nil {\n\t\t\tbug.Report(\"root analysisNode has nil summary\")\n\t\t}\n\t}\n\n\t// Report diagnostics only from enabled actions that succeeded.\n\t// Errors from creating or analyzing packages are ignored.\n\t// Diagnostics are reported in the order of the analyzers argument.\n\t//\n\t// TODO(adonovan): ignoring action errors gives the caller no way\n\t// to distinguish \"there are no problems in this code\" from\n\t// \"the code (or analyzers!) are so broken that we couldn't even\n\t// begin the analysis you asked for\".\n\t// Even if current callers choose to discard the\n\t// results, we should propagate the per-action errors.\n\tvar results []*Diagnostic\n\tfor _, root := range roots {\n\t\tfor _, a := range enabledAnalyzers {\n\t\t\t// Skip analyzers that were added only to\n\t\t\t// fulfil requirements of the original set.\n\t\t\tsrcAnalyzer, ok := toSrc[a]\n\t\t\tif !ok {\n\t\t\t\t// Although this 'skip' operation is logically sound,\n\t\t\t\t// it is nonetheless surprising that its absence should\n\t\t\t\t// cause #60909 since none of the analyzers currently added for\n\t\t\t\t// requirements (e.g. ctrlflow, inspect, buildssa)\n\t\t\t\t// is capable of reporting diagnostics.\n\t\t\t\tif summary := root.summary.Actions[stableNames[a]]; summary != nil {\n\t\t\t\t\tif n := len(summary.Diagnostics); n > 0 {\n\t\t\t\t\t\tbug.Reportf(\"Internal error: got %d unexpected diagnostics from analyzer %s. This analyzer was added only to fulfil the requirements of the requested set of analyzers, and it is not expected that such analyzers report diagnostics. Please report this in issue #60909.\", n, a)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Inv: root.summary is the successful result of run (via runCached).\n\t\t\t// TODO(adonovan): fix: root.summary is sometimes nil! (#66732).\n\t\t\tsummary, ok := root.summary.Actions[stableNames[a]]\n\t\t\tif summary == nil {\n\t\t\t\tpanic(fmt.Sprintf(\"analyzeSummary.Actions[%q] = (nil, %t); got %v (#60551)\",\n\t\t\t\t\tstableNames[a], ok, root.summary.Actions))\n\t\t\t}\n\t\t\tif summary.Err != \"\" {\n\t\t\t\tcontinue // action failed\n\t\t\t}\n\t\t\tfor _, gobDiag := range summary.Diagnostics {\n\t\t\t\tresults = append(results, toSourceDiagnostic(srcAnalyzer, &gobDiag))\n\t\t\t}\n\t\t}\n\t}\n\treturn results, nil\n}\n\nfunc (an *analysisNode) decrefPreds() {\n\tif an.unfinishedPreds.Add(-1) == 0 {\n\t\tan.summary.Actions = nil\n\t}\n}\n\n// An analysisNode is a node in a doubly-linked DAG isomorphic to the\n// import graph. Each node represents a single package, and the DAG\n// represents a batch of analysis work done at once using a single\n// realm of token.Pos or types.Object values.\n//\n// A complete DAG is created anew for each batch of analysis;\n// subgraphs are not reused over time.\n// TODO(rfindley): with cached keys we can typically avoid building the full\n// DAG, so as an optimization we should rewrite this using a top-down\n// traversal, rather than bottom-up.\n//\n// Each node's run method is called in parallel postorder. On success,\n// its summary field is populated, either from the cache (hit), or by\n// type-checking and analyzing syntax (miss).\ntype analysisNode struct {\n\tparseCache      *parseCache                 // shared parse cache\n\tfsource         file.Source                 // Snapshot.ReadFile, for use by Pass.ReadFile\n\tbatch           *typeCheckBatch             // type checking batch, for shared type checking\n\tph              *packageHandle              // package handle, for key and reachability analysis\n\tanalyzers       []*analysis.Analyzer        // set of analyzers to run\n\tpreds           []*analysisNode             // graph edges:\n\tsuccs           map[PackageID]*analysisNode //   (preds -> self -> succs)\n\tunfinishedSuccs atomic.Int32\n\tunfinishedPreds atomic.Int32                  // effectively a summary.Actions refcount\n\tsummary         *analyzeSummary               // serializable result of analyzing this package\n\tstableNames     map[*analysis.Analyzer]string // cross-process stable names for Analyzers\n\n\tsummaryHashOnce sync.Once\n\t_summaryHash    file.Hash // memoized hash of data affecting dependents\n}\n\nfunc (an *analysisNode) String() string { return string(an.ph.mp.ID) }\n\n// summaryHash computes the hash of the node summary, which may affect other\n// nodes depending on this node.\n//\n// The result is memoized to avoid redundant work when analyzing multiple\n// dependents.\nfunc (an *analysisNode) summaryHash() file.Hash {\n\tan.summaryHashOnce.Do(func() {\n\t\thasher := sha256.New()\n\t\tfmt.Fprintf(hasher, \"dep: %s\\n\", an.ph.mp.PkgPath)\n\t\tfmt.Fprintf(hasher, \"compiles: %t\\n\", an.summary.Compiles)\n\n\t\t// action results: errors and facts\n\t\tfor name, summary := range moremaps.Sorted(an.summary.Actions) {\n\t\t\tfmt.Fprintf(hasher, \"action %s\\n\", name)\n\t\t\tif summary.Err != \"\" {\n\t\t\t\tfmt.Fprintf(hasher, \"error %s\\n\", summary.Err)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(hasher, \"facts %s\\n\", summary.FactsHash)\n\t\t\t\t// We can safely omit summary.diagnostics\n\t\t\t\t// from the key since they have no downstream effect.\n\t\t\t}\n\t\t}\n\t\thasher.Sum(an._summaryHash[:0])\n\t})\n\treturn an._summaryHash\n}\n\n// analyzeSummary is a gob-serializable summary of successfully\n// applying a list of analyzers to a package.\ntype analyzeSummary struct {\n\tCompiles bool      // transitively free of list/parse/type errors\n\tActions  actionMap // maps analyzer stablename to analysis results (*actionSummary)\n}\n\n// actionMap defines a stable Gob encoding for a map.\n// TODO(adonovan): generalize and move to a library when we can use generics.\ntype actionMap map[string]*actionSummary\n\nvar (\n\t_ gob.GobEncoder = (actionMap)(nil)\n\t_ gob.GobDecoder = (*actionMap)(nil)\n)\n\ntype actionsMapEntry struct {\n\tK string\n\tV *actionSummary\n}\n\nfunc (m actionMap) GobEncode() ([]byte, error) {\n\tentries := make([]actionsMapEntry, 0, len(m))\n\tfor k, v := range m {\n\t\tentries = append(entries, actionsMapEntry{k, v})\n\t}\n\tsort.Slice(entries, func(i, j int) bool {\n\t\treturn entries[i].K < entries[j].K\n\t})\n\tvar buf bytes.Buffer\n\terr := gob.NewEncoder(&buf).Encode(entries)\n\treturn buf.Bytes(), err\n}\n\nfunc (m *actionMap) GobDecode(data []byte) error {\n\tvar entries []actionsMapEntry\n\tif err := gob.NewDecoder(bytes.NewReader(data)).Decode(&entries); err != nil {\n\t\treturn err\n\t}\n\t*m = make(actionMap, len(entries))\n\tfor _, e := range entries {\n\t\t(*m)[e.K] = e.V\n\t}\n\treturn nil\n}\n\n// actionSummary is a gob-serializable summary of one possibly failed analysis action.\n// If Err is non-empty, the other fields are undefined.\ntype actionSummary struct {\n\tFacts       []byte    // the encoded facts.Set\n\tFactsHash   file.Hash // hash(Facts)\n\tDiagnostics []gobDiagnostic\n\tErr         string // \"\" => success\n}\n\nvar (\n\t// inFlightAnalyses records active analysis operations so that later requests\n\t// can be satisfied by joining onto earlier requests that are still active.\n\t//\n\t// Note that persistent=false, so results are cleared once they are delivered\n\t// to awaiting goroutines.\n\tinFlightAnalyses = newFutureCache[file.Hash, *analyzeSummary](false)\n\n\t// cacheLimit reduces parallelism of filecache updates.\n\t// We allow more than typical GOMAXPROCS as it's a mix of CPU and I/O.\n\tcacheLimit = make(chan unit, 32)\n)\n\n// runCached applies a list of analyzers (plus any others\n// transitively required by them) to a package.  It succeeds as long\n// as it could produce a types.Package, even if there were direct or\n// indirect list/parse/type errors, and even if all the analysis\n// actions failed. It usually fails only if the package was unknown,\n// a file was missing, or the operation was cancelled.\n//\n// The provided key is the cache key for this package.\nfunc (an *analysisNode) runCached(ctx context.Context, key file.Hash) (*analyzeSummary, error) {\n\t// At this point we have the action results (serialized packages and facts)\n\t// of our immediate dependencies, and the metadata and content of this\n\t// package.\n\t//\n\t// We now consult a global cache of promised results. If nothing material has\n\t// changed, we'll make a hit in the shared cache.\n\n\t// Access the cache.\n\tvar summary *analyzeSummary\n\tconst cacheKind = \"analysis\"\n\tif data, err := filecache.Get(cacheKind, key); err == nil {\n\t\t// cache hit\n\t\tanalyzeSummaryCodec.Decode(data, &summary)\n\t\tif summary == nil { // debugging #66732\n\t\t\tbug.Reportf(\"analyzeSummaryCodec.Decode yielded nil *analyzeSummary\")\n\t\t}\n\t} else if err != filecache.ErrNotFound {\n\t\treturn nil, bug.Errorf(\"internal error reading shared cache: %v\", err)\n\t} else {\n\t\t// Cache miss: do the work.\n\t\tcachedSummary, err := inFlightAnalyses.get(ctx, key, func(ctx context.Context) (*analyzeSummary, error) {\n\t\t\tsummary, err := an.run(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif summary == nil { // debugging #66732 (can't happen)\n\t\t\t\tbug.Reportf(\"analyzeNode.run returned nil *analyzeSummary\")\n\t\t\t}\n\t\t\tgo func() {\n\t\t\t\tcacheLimit <- unit{}            // acquire token\n\t\t\t\tdefer func() { <-cacheLimit }() // release token\n\n\t\t\t\tdata := analyzeSummaryCodec.Encode(summary)\n\t\t\t\tif false {\n\t\t\t\t\tlog.Printf(\"Set key=%d value=%d id=%s\\n\", len(key), len(data), an.ph.mp.ID)\n\t\t\t\t}\n\t\t\t\tif err := filecache.Set(cacheKind, key, data); err != nil {\n\t\t\t\t\tevent.Error(ctx, \"internal error updating analysis shared cache\", err)\n\t\t\t\t}\n\t\t\t}()\n\t\t\treturn summary, nil\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Copy the computed summary. In decrefPreds, we may zero out\n\t\t// summary.actions, but can't mutate a shared result.\n\t\tcopy := *cachedSummary\n\t\tsummary = &copy\n\t}\n\n\treturn summary, nil\n}\n\n// cacheKey returns a cache key that is a cryptographic digest\n// of the all the values that might affect type checking and analysis:\n// the analyzer names, package metadata, names and contents of\n// compiled Go files, and vdeps (successor) information\n// (export data and facts).\nfunc (an *analysisNode) cacheKey() file.Hash {\n\thasher := sha256.New()\n\n\t// In principle, a key must be the hash of an\n\t// unambiguous encoding of all the relevant data.\n\t// If it's ambiguous, we risk collisions.\n\n\t// analyzers\n\tfmt.Fprintf(hasher, \"analyzers: %d\\n\", len(an.analyzers))\n\tfor _, a := range an.analyzers {\n\t\tfmt.Fprintln(hasher, a.Name)\n\t}\n\n\t// type checked package\n\tfmt.Fprintf(hasher, \"package: %s\\n\", an.ph.key)\n\n\t// metadata errors: used for 'compiles' field\n\tfmt.Fprintf(hasher, \"errors: %d\", len(an.ph.mp.Errors))\n\n\t// vdeps, in PackageID order\n\tfor _, vdep := range moremaps.Sorted(an.succs) {\n\t\thash := vdep.summaryHash()\n\t\thasher.Write(hash[:])\n\t}\n\n\tvar hash file.Hash\n\thasher.Sum(hash[:0])\n\treturn hash\n}\n\n// run implements the cache-miss case.\n// This function does not access the snapshot.\n//\n// Postcondition: on success, the analyzeSummary.Actions\n// key set is {a.Name for a in analyzers}.\nfunc (an *analysisNode) run(ctx context.Context) (*analyzeSummary, error) {\n\t// Type-check the package syntax.\n\tpkg, err := an.typeCheck(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Poll cancellation state.\n\tif err := ctx.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// -- analysis --\n\n\t// Build action graph for this package.\n\t// Each graph node (action) is one unit of analysis.\n\tactions := make(map[*analysis.Analyzer]*action)\n\tvar mkAction func(a *analysis.Analyzer) *action\n\tmkAction = func(a *analysis.Analyzer) *action {\n\t\tact, ok := actions[a]\n\t\tif !ok {\n\t\t\tvar hdeps []*action\n\t\t\tfor _, req := range a.Requires {\n\t\t\t\thdeps = append(hdeps, mkAction(req))\n\t\t\t}\n\t\t\tact = &action{\n\t\t\t\ta:          a,\n\t\t\t\tfsource:    an.fsource,\n\t\t\t\tstableName: an.stableNames[a],\n\t\t\t\tpkg:        pkg,\n\t\t\t\tvdeps:      an.succs,\n\t\t\t\thdeps:      hdeps,\n\t\t\t}\n\t\t\tactions[a] = act\n\t\t}\n\t\treturn act\n\t}\n\n\t// Build actions for initial package.\n\tvar roots []*action\n\tfor _, a := range an.analyzers {\n\t\troots = append(roots, mkAction(a))\n\t}\n\n\t// Execute the graph in parallel.\n\texecActions(ctx, roots)\n\t// Inv: each root's summary is set (whether success or error).\n\n\t// Don't return (or cache) the result in case of cancellation.\n\tif err := ctx.Err(); err != nil {\n\t\treturn nil, err // cancelled\n\t}\n\n\t// Return summaries only for the requested actions.\n\tsummaries := make(map[string]*actionSummary)\n\tfor _, root := range roots {\n\t\tif root.summary == nil {\n\t\t\tpanic(\"root has nil action.summary (#60551)\")\n\t\t}\n\t\tsummaries[root.stableName] = root.summary\n\t}\n\n\treturn &analyzeSummary{\n\t\tCompiles: pkg.compiles,\n\t\tActions:  summaries,\n\t}, nil\n}\n\nfunc (an *analysisNode) typeCheck(ctx context.Context) (*analysisPackage, error) {\n\tppkg, err := an.batch.getPackage(ctx, an.ph)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcompiles := len(an.ph.mp.Errors) == 0 && len(ppkg.TypeErrors()) == 0\n\n\t// The go/analysis framework implicitly promises to deliver\n\t// trees with legacy ast.Object resolution. Do that now.\n\tfiles := make([]*ast.File, len(ppkg.CompiledGoFiles()))\n\tfor i, p := range ppkg.CompiledGoFiles() {\n\t\tp.Resolve()\n\t\tfiles[i] = p.File\n\t\tif p.ParseErr != nil {\n\t\t\tcompiles = false // parse error\n\t\t}\n\t}\n\n\t// The fact decoder needs a means to look up a Package by path.\n\tpkgLookup := typesLookup(ppkg.Types())\n\tfactsDecoder := facts.NewDecoderFunc(ppkg.Types(), func(path string) *types.Package {\n\t\t// Note: Decode is called concurrently, and thus so is this function.\n\n\t\t// Does the fact relate to a package reachable through imports?\n\t\tif !an.ph.reachable.MayContain(path) {\n\t\t\treturn nil\n\t\t}\n\n\t\treturn pkgLookup(path)\n\t})\n\n\tvar typeErrors []types.Error\nfilterErrors:\n\tfor _, typeError := range ppkg.TypeErrors() {\n\t\t// Suppress type errors in files with parse errors\n\t\t// as parser recovery can be quite lossy (#59888).\n\t\tfor _, p := range ppkg.CompiledGoFiles() {\n\t\t\tif p.ParseErr != nil && astutil.NodeContainsPos(p.File, typeError.Pos) {\n\t\t\t\tcontinue filterErrors\n\t\t\t}\n\t\t}\n\t\ttypeErrors = append(typeErrors, typeError)\n\t}\n\n\tfor _, vdep := range an.succs {\n\t\tif !vdep.summary.Compiles {\n\t\t\tcompiles = false // transitive error\n\t\t}\n\t}\n\n\treturn &analysisPackage{\n\t\tpkg:          ppkg,\n\t\tfiles:        files,\n\t\ttypeErrors:   typeErrors,\n\t\tcompiles:     compiles,\n\t\tfactsDecoder: factsDecoder,\n\t}, nil\n}\n\n// typesLookup implements a concurrency safe depth-first traversal searching\n// imports of pkg for a given package path.\nfunc typesLookup(pkg *types.Package) func(string) *types.Package {\n\tvar (\n\t\tmu sync.Mutex // guards impMap and pending\n\n\t\t// impMap memoizes the lookup of package paths.\n\t\timpMap = map[string]*types.Package{\n\t\t\tpkg.Path(): pkg,\n\t\t}\n\t\t// pending is a FIFO queue of packages that have yet to have their\n\t\t// dependencies fully scanned.\n\t\t// Invariant: all entries in pending are already mapped in impMap.\n\t\tpending = []*types.Package{pkg}\n\t)\n\n\t// search scans children the next package in pending, looking for pkgPath.\n\tsearch := func(pkgPath string) (sought *types.Package, numPending int) {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\n\t\tif p, ok := impMap[pkgPath]; ok {\n\t\t\treturn p, len(pending)\n\t\t}\n\n\t\tif len(pending) == 0 {\n\t\t\treturn nil, 0\n\t\t}\n\n\t\tpkg := pending[0]\n\t\tpending = pending[1:]\n\t\tfor _, dep := range pkg.Imports() {\n\t\t\tdepPath := dep.Path()\n\t\t\tif _, ok := impMap[depPath]; ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timpMap[depPath] = dep\n\n\t\t\tpending = append(pending, dep)\n\t\t\tif depPath == pkgPath {\n\t\t\t\t// Don't return early; finish processing pkg's deps.\n\t\t\t\tsought = dep\n\t\t\t}\n\t\t}\n\t\treturn sought, len(pending)\n\t}\n\n\treturn func(pkgPath string) *types.Package {\n\t\tp, np := (*types.Package)(nil), 1\n\t\tfor p == nil && np > 0 {\n\t\t\tp, np = search(pkgPath)\n\t\t}\n\t\treturn p\n\t}\n}\n\n// analysisPackage contains information about a package, including\n// syntax trees, used transiently during its type-checking and analysis.\ntype analysisPackage struct {\n\tpkg          *Package\n\tfiles        []*ast.File   // same as parsed[i].File\n\ttypeErrors   []types.Error // filtered type checker errors\n\tcompiles     bool          // package is transitively free of list/parse/type errors\n\tfactsDecoder *facts.Decoder\n}\n\n// An action represents one unit of analysis work: the application of\n// one analysis to one package. Actions form a DAG, both within a\n// package (as different analyzers are applied, either in sequence or\n// parallel), and across packages (as dependencies are analyzed).\ntype action struct {\n\tonce       sync.Once\n\ta          *analysis.Analyzer\n\tfsource    file.Source // Snapshot.ReadFile, for Pass.ReadFile\n\tstableName string      // cross-process stable name of analyzer\n\tpkg        *analysisPackage\n\thdeps      []*action                   // horizontal dependencies\n\tvdeps      map[PackageID]*analysisNode // vertical dependencies\n\n\t// results of action.exec():\n\tresult  any // result of Run function, of type a.ResultType\n\tsummary *actionSummary\n\terr     error\n}\n\nfunc (act *action) String() string {\n\treturn fmt.Sprintf(\"%s@%s\", act.a.Name, act.pkg.pkg.metadata.ID)\n}\n\n// execActions executes a set of action graph nodes in parallel.\n// Postcondition: each action.summary is set, even in case of error.\nfunc execActions(ctx context.Context, actions []*action) {\n\tvar wg sync.WaitGroup\n\tfor _, act := range actions {\n\t\twg.Go(func() {\n\t\t\tact.once.Do(func() {\n\t\t\t\texecActions(ctx, act.hdeps) // analyze \"horizontal\" dependencies\n\t\t\t\tact.result, act.summary, act.err = act.exec(ctx)\n\t\t\t\tif act.err != nil {\n\t\t\t\t\tact.summary = &actionSummary{Err: act.err.Error()}\n\t\t\t\t\t// TODO(adonovan): suppress logging. But\n\t\t\t\t\t// shouldn't the root error's causal chain\n\t\t\t\t\t// include this information?\n\t\t\t\t\tif false { // debugging\n\t\t\t\t\t\tlog.Printf(\"act.exec(%v) failed: %v\", act, act.err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\tif act.summary == nil {\n\t\t\t\tpanic(\"nil action.summary (#60551)\")\n\t\t\t}\n\t\t})\n\t}\n\twg.Wait()\n}\n\n// exec defines the execution of a single action.\n// It returns the (ephemeral) result of the analyzer's Run function,\n// along with its (serializable) facts and diagnostics.\n// Or it returns an error if the analyzer did not run to\n// completion and deliver a valid result.\nfunc (act *action) exec(ctx context.Context) (any, *actionSummary, error) {\n\tanalyzer := act.a\n\tapkg := act.pkg\n\n\thasFacts := len(analyzer.FactTypes) > 0\n\n\t// Report an error if any action dependency (vertical or horizontal) failed.\n\t// To avoid long error messages describing chains of failure,\n\t// we return the dependencies' error' unadorned.\n\tif hasFacts {\n\t\t// TODO(adonovan): use deterministic order.\n\t\tfor _, vdep := range act.vdeps {\n\t\t\tif summ := vdep.summary.Actions[act.stableName]; summ.Err != \"\" {\n\t\t\t\treturn nil, nil, errors.New(summ.Err)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, dep := range act.hdeps {\n\t\tif dep.err != nil {\n\t\t\treturn nil, nil, dep.err\n\t\t}\n\t}\n\t// Inv: all action dependencies succeeded.\n\n\t// Were there list/parse/type errors that might prevent analysis?\n\tif !apkg.compiles && !analyzer.RunDespiteErrors {\n\t\treturn nil, nil, fmt.Errorf(\"skipping analysis %q because package %q does not compile\", analyzer.Name, apkg.pkg.metadata.ID)\n\t}\n\t// Inv: package is well-formed enough to proceed with analysis.\n\n\tif false { // debugging\n\t\tlog.Println(\"action.exec\", act)\n\t}\n\n\t// Gather analysis Result values from horizontal dependencies.\n\tinputs := make(map[*analysis.Analyzer]any)\n\tfor _, dep := range act.hdeps {\n\t\tinputs[dep.a] = dep.result\n\t}\n\n\t// TODO(adonovan): opt: facts.Set works but it may be more\n\t// efficient to fork and tailor it to our precise needs.\n\t//\n\t// We've already sharded the fact encoding by action\n\t// so that it can be done in parallel.\n\t// We could eliminate locking.\n\t// We could also dovetail more closely with the export data\n\t// decoder to obtain a more compact representation of\n\t// packages and objects (e.g. its internal IDs, instead\n\t// of PkgPaths and objectpaths.)\n\t// More importantly, we should avoid re-export of\n\t// facts that related to objects that are discarded\n\t// by \"deep\" export data. Better still, use a \"shallow\" approach.\n\n\t// Read and decode analysis facts for each direct import.\n\tfactset, err := apkg.factsDecoder.Decode(func(pkgPath string) ([]byte, error) {\n\t\tif !hasFacts {\n\t\t\treturn nil, nil // analyzer doesn't use facts, so no vdeps\n\t\t}\n\n\t\t// Package.Imports() may contain a fake \"C\" package. Ignore it.\n\t\tif pkgPath == \"C\" {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tid, ok := apkg.pkg.metadata.DepsByPkgPath[PackagePath(pkgPath)]\n\t\tif !ok {\n\t\t\t// This may mean imp was synthesized by the type\n\t\t\t// checker because it failed to import it for any reason\n\t\t\t// (e.g. bug processing export data; metadata ignoring\n\t\t\t// a cycle-forming import).\n\t\t\t// In that case, the fake package's imp.Path\n\t\t\t// is set to the failed importPath (and thus\n\t\t\t// it may lack a \"vendor/\" prefix).\n\t\t\t//\n\t\t\t// For now, silently ignore it on the assumption\n\t\t\t// that the error is already reported elsewhere.\n\t\t\t// return nil, fmt.Errorf(\"missing metadata\")\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tvdep := act.vdeps[id]\n\t\tif vdep == nil {\n\t\t\treturn nil, bug.Errorf(\"internal error in %s: missing vdep for id=%s\", apkg.pkg.Types().Path(), id)\n\t\t}\n\n\t\treturn vdep.summary.Actions[act.stableName].Facts, nil\n\t})\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"internal error decoding analysis facts: %w\", err)\n\t}\n\n\t// TODO(adonovan): make Export*Fact panic rather than discarding\n\t// undeclared fact types, so that we discover bugs in analyzers.\n\tfactFilter := make(map[reflect.Type]bool)\n\tfor _, f := range analyzer.FactTypes {\n\t\tfactFilter[reflect.TypeOf(f)] = true\n\t}\n\n\t// Now run the (pkg, analyzer) action.\n\tvar diagnostics []gobDiagnostic\n\n\tpass := &analysis.Pass{\n\t\tAnalyzer:     analyzer,\n\t\tFset:         apkg.pkg.FileSet(),\n\t\tFiles:        apkg.files,\n\t\tOtherFiles:   nil, // since gopls doesn't handle non-Go (e.g. asm) files\n\t\tIgnoredFiles: nil, // zero-config gopls should analyze these files in another view\n\t\tPkg:          apkg.pkg.Types(),\n\t\tTypesInfo:    apkg.pkg.TypesInfo(),\n\t\tTypesSizes:   apkg.pkg.TypesSizes(),\n\t\tTypeErrors:   apkg.typeErrors,\n\t\tResultOf:     inputs,\n\t\tReport: func(d analysis.Diagnostic) {\n\t\t\t// Assert that SuggestedFixes are well formed.\n\t\t\t//\n\t\t\t// ValidateFixes allows a fix.End to be slightly beyond\n\t\t\t// EOF to avoid spurious assertions when reporting\n\t\t\t// fixes as the end of truncated files; see #71659.\n\t\t\tif err := driverutil.ValidateFixes(apkg.pkg.FileSet(), analyzer, d.SuggestedFixes); err != nil {\n\t\t\t\tbug.Reportf(\"invalid SuggestedFixes: %v\", err)\n\t\t\t\td.SuggestedFixes = nil\n\t\t\t}\n\t\t\tdiagnostic, err := toGobDiagnostic(apkg.pkg, analyzer, d)\n\t\t\tif err != nil {\n\t\t\t\t// Don't bug.Report here: these errors all originate in\n\t\t\t\t// posToLocation, and we can more accurately discriminate\n\t\t\t\t// severe errors from benign ones in that function.\n\t\t\t\tevent.Error(ctx, fmt.Sprintf(\"internal error converting diagnostic from analyzer %q\", analyzer.Name), err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdiagnostics = append(diagnostics, diagnostic)\n\t\t},\n\t\tImportObjectFact:  factset.ImportObjectFact,\n\t\tExportObjectFact:  factset.ExportObjectFact,\n\t\tImportPackageFact: factset.ImportPackageFact,\n\t\tExportPackageFact: factset.ExportPackageFact,\n\t\tAllObjectFacts:    func() []analysis.ObjectFact { return factset.AllObjectFacts(factFilter) },\n\t\tAllPackageFacts:   func() []analysis.PackageFact { return factset.AllPackageFacts(factFilter) },\n\t}\n\n\tpass.ReadFile = func(filename string) ([]byte, error) {\n\t\t// Read file from snapshot, to ensure reads are consistent.\n\t\t//\n\t\t// TODO(adonovan): make the dependency analysis sound by\n\t\t// incorporating these additional files into the analysis\n\t\t// hash. This requires either (a) preemptively reading and\n\t\t// hashing a potentially large number of mostly irrelevant\n\t\t// files; or (b) some kind of dynamic dependency discovery\n\t\t// system like used in Bazel for C++ headers. Neither entices.\n\t\tif err := driverutil.CheckReadable(pass, filename); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\th, err := act.fsource.ReadFile(ctx, protocol.URIFromPath(filename))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcontent, err := h.Content()\n\t\tif err != nil {\n\t\t\treturn nil, err // file doesn't exist\n\t\t}\n\t\treturn slices.Clone(content), nil // follow ownership of os.ReadFile\n\t}\n\n\t// Recover from panics (only) within the analyzer logic.\n\t// (Use an anonymous function to limit the recover scope.)\n\tvar result any\n\tfunc() {\n\t\tstart := time.Now()\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\t// An Analyzer panicked, likely due to a bug.\n\t\t\t\t//\n\t\t\t\t// In general we want to discover and fix such panics quickly,\n\t\t\t\t// so we don't suppress them, but some bugs in third-party\n\t\t\t\t// analyzers cannot be quickly fixed, so we use an allowlist\n\t\t\t\t// to suppress panics.\n\t\t\t\tconst strict = true\n\t\t\t\tif strict && bug.PanicOnBugs &&\n\t\t\t\t\tanalyzer.Name != \"buildir\" { // see https://github.com/dominikh/go-tools/issues/1343\n\t\t\t\t\t// Uncomment this when debugging suspected failures\n\t\t\t\t\t// in the driver, not the analyzer.\n\t\t\t\t\tif false {\n\t\t\t\t\t\tdebug.SetTraceback(\"all\") // show all goroutines\n\t\t\t\t\t}\n\t\t\t\t\tpanic(r)\n\t\t\t\t} else {\n\t\t\t\t\t// In production, suppress the panic and press on.\n\t\t\t\t\terr = fmt.Errorf(\"analysis %s for package %s panicked: %v\", analyzer.Name, pass.Pkg.Path(), r)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Accumulate running time for each checker.\n\t\t\tanalyzerRunTimesMu.Lock()\n\t\t\tanalyzerRunTimes[analyzer] += time.Since(start)\n\t\t\tanalyzerRunTimesMu.Unlock()\n\t\t}()\n\n\t\tresult, err = pass.Analyzer.Run(pass)\n\t}()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {\n\t\treturn nil, nil, bug.Errorf(\n\t\t\t\"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v\",\n\t\t\tpass.Pkg.Path(), pass.Analyzer, got, want)\n\t}\n\n\t// Disallow Export*Fact calls after Run.\n\t// (A panic means the Analyzer is abusing concurrency.)\n\tpass.ExportObjectFact = func(obj types.Object, fact analysis.Fact) {\n\t\tpanic(fmt.Sprintf(\"%v: Pass.ExportObjectFact(%s, %T) called after Run\", act, obj, fact))\n\t}\n\tpass.ExportPackageFact = func(fact analysis.Fact) {\n\t\tpanic(fmt.Sprintf(\"%v: Pass.ExportPackageFact(%T) called after Run\", act, fact))\n\t}\n\n\tfactsdata := factset.Encode()\n\treturn result, &actionSummary{\n\t\tDiagnostics: diagnostics,\n\t\tFacts:       factsdata,\n\t\tFactsHash:   file.HashOf(factsdata),\n\t}, nil\n}\n\nvar (\n\tanalyzerRunTimesMu sync.Mutex\n\tanalyzerRunTimes   = make(map[*analysis.Analyzer]time.Duration)\n)\n\ntype LabelDuration struct {\n\tLabel    string\n\tDuration time.Duration\n}\n\n// AnalyzerRunTimes returns the accumulated time spent in each Analyzer's\n// Run function since process start, in descending order.\nfunc AnalyzerRunTimes() []LabelDuration {\n\tanalyzerRunTimesMu.Lock()\n\tdefer analyzerRunTimesMu.Unlock()\n\n\tslice := make([]LabelDuration, 0, len(analyzerRunTimes))\n\tfor a, t := range analyzerRunTimes {\n\t\tslice = append(slice, LabelDuration{Label: a.Name, Duration: t})\n\t}\n\tsort.Slice(slice, func(i, j int) bool {\n\t\treturn slice[i].Duration > slice[j].Duration\n\t})\n\treturn slice\n}\n\n// requiredAnalyzers returns the transitive closure of required analyzers in preorder.\nfunc requiredAnalyzers(analyzers []*analysis.Analyzer) []*analysis.Analyzer {\n\tvar result []*analysis.Analyzer\n\tseen := make(map[*analysis.Analyzer]bool)\n\tvar visitAll func([]*analysis.Analyzer)\n\tvisitAll = func(analyzers []*analysis.Analyzer) {\n\t\tfor _, a := range analyzers {\n\t\t\tif !seen[a] {\n\t\t\t\tseen[a] = true\n\t\t\t\tresult = append(result, a)\n\t\t\t\tvisitAll(a.Requires)\n\t\t\t}\n\t\t}\n\t}\n\tvisitAll(analyzers)\n\treturn result\n}\n\nvar analyzeSummaryCodec = frob.CodecFor[*analyzeSummary]()\n\n// -- data types for serialization of analysis.Diagnostic and golang.Diagnostic --\n\n// (The name says gob but we use frob.)\nvar diagnosticsCodec = frob.CodecFor[[]gobDiagnostic]()\n\ntype gobDiagnostic struct {\n\tLocation       protocol.Location\n\tSeverity       protocol.DiagnosticSeverity\n\tCode           string\n\tCodeHref       string\n\tSource         string\n\tMessage        string\n\tSuggestedFixes []gobSuggestedFix\n\tRelated        []gobRelatedInformation\n\tTags           []protocol.DiagnosticTag\n}\n\ntype gobRelatedInformation struct {\n\tLocation protocol.Location\n\tMessage  string\n}\n\ntype gobSuggestedFix struct {\n\tMessage    string\n\tTextEdits  []gobTextEdit\n\tCommand    *gobCommand\n\tActionKind protocol.CodeActionKind\n}\n\ntype gobCommand struct {\n\tTitle     string\n\tCommand   string\n\tArguments []json.RawMessage\n}\n\ntype gobTextEdit struct {\n\tLocation protocol.Location\n\tNewText  []byte\n}\n\n// toGobDiagnostic converts an analysis.Diagnosic to a serializable gobDiagnostic,\n// which requires expanding token.Pos positions into protocol.Location form.\nfunc toGobDiagnostic(pkg *Package, a *analysis.Analyzer, diag analysis.Diagnostic) (gobDiagnostic, error) {\n\tvar fixes []gobSuggestedFix\n\tfor _, fix := range diag.SuggestedFixes {\n\t\tvar gobEdits []gobTextEdit\n\t\tfor _, textEdit := range fix.TextEdits {\n\t\t\tloc, err := diagnosticPosToLocation(pkg, false, textEdit.Pos, textEdit.End)\n\t\t\tif err != nil {\n\t\t\t\treturn gobDiagnostic{}, fmt.Errorf(\"in SuggestedFixes: %w\", err)\n\t\t\t}\n\t\t\tgobEdits = append(gobEdits, gobTextEdit{\n\t\t\t\tLocation: loc,\n\t\t\t\tNewText:  textEdit.NewText,\n\t\t\t})\n\t\t}\n\t\tfixes = append(fixes, gobSuggestedFix{\n\t\t\tMessage:   fix.Message,\n\t\t\tTextEdits: gobEdits,\n\t\t})\n\t}\n\n\tvar related []gobRelatedInformation\n\tfor _, r := range diag.Related {\n\t\t// The position of RelatedInformation may be\n\t\t// within another (dependency) package.\n\t\tconst allowDeps = true\n\t\tloc, err := diagnosticPosToLocation(pkg, allowDeps, r.Pos, r.End)\n\t\tif err != nil {\n\t\t\treturn gobDiagnostic{}, fmt.Errorf(\"in Related: %w\", err)\n\t\t}\n\t\trelated = append(related, gobRelatedInformation{\n\t\t\tLocation: loc,\n\t\t\tMessage:  r.Message,\n\t\t})\n\t}\n\n\tloc, err := diagnosticPosToLocation(pkg, false, diag.Pos, diag.End)\n\tif err != nil {\n\t\treturn gobDiagnostic{}, err\n\t}\n\n\t// The Code column of VSCode's Problems table renders this\n\t// information as \"Source(Code)\" where code is a link to CodeHref.\n\t// (The code field must be nonempty for anything to appear.)\n\tdiagURL := effectiveURL(a, diag)\n\tcode := \"default\"\n\tif diag.Category != \"\" {\n\t\tcode = diag.Category\n\t}\n\n\treturn gobDiagnostic{\n\t\tLocation: loc,\n\t\t// Severity for analysis diagnostics is dynamic,\n\t\t// based on user configuration per analyzer.\n\t\tCode:           code,\n\t\tCodeHref:       diagURL,\n\t\tSource:         a.Name,\n\t\tMessage:        diag.Message,\n\t\tSuggestedFixes: fixes,\n\t\tRelated:        related,\n\t\t// Analysis diagnostics do not contain tags.\n\t}, nil\n}\n\n// diagnosticPosToLocation converts from token.Pos to protocol form, in the\n// context of the specified package and, optionally, its dependencies.\nfunc diagnosticPosToLocation(pkg *Package, allowDeps bool, start, end token.Pos) (protocol.Location, error) {\n\tif end == token.NoPos {\n\t\tend = start\n\t}\n\n\tfset := pkg.FileSet()\n\ttokFile := fset.File(start)\n\n\t// Find existing mapper by file name.\n\t// (Don't require an exact token.File match\n\t// as the analyzer may have re-parsed the file.)\n\tvar (\n\t\tmapper *protocol.Mapper\n\t\tfixed  bool\n\t)\n\tfor _, p := range pkg.CompiledGoFiles() {\n\t\tif p.Tok.Name() == tokFile.Name() {\n\t\t\tmapper = p.Mapper\n\t\t\tfixed = p.Fixed() // suppress some assertions after parser recovery\n\t\t\tbreak\n\t\t}\n\t}\n\t// TODO(adonovan): search pkg.AsmFiles too; see #71754.\n\tif mapper != nil {\n\t\t// debugging #64547\n\t\tfileStart := token.Pos(tokFile.Base())\n\t\tfileEnd := fileStart + token.Pos(tokFile.Size())\n\t\tif start < fileStart {\n\t\t\tif !fixed {\n\t\t\t\tbug.Reportf(\"start < start of file\")\n\t\t\t}\n\t\t\tstart = fileStart\n\t\t}\n\t\tif end < start {\n\t\t\t// This can happen if End is zero (#66683)\n\t\t\t// or a small positive displacement from zero\n\t\t\t// due to recursive Node.End() computation.\n\t\t\t// This usually arises from poor parser recovery\n\t\t\t// of an incomplete term at EOF.\n\t\t\tif !fixed {\n\t\t\t\tbug.Reportf(\"end < start of file\")\n\t\t\t}\n\t\t\tend = fileEnd\n\t\t}\n\t\tif end > fileEnd+1 {\n\t\t\tif !fixed {\n\t\t\t\tbug.Reportf(\"end > end of file + 1\")\n\t\t\t}\n\t\t\tend = fileEnd\n\t\t}\n\n\t\treturn mapper.PosLocation(tokFile, start, end)\n\t}\n\n\t// Inv: the positions are not within this package.\n\n\tif allowDeps {\n\t\t// Positions in Diagnostic.RelatedInformation may belong to a\n\t\t// dependency package. We cannot accurately map them to\n\t\t// protocol.Location coordinates without a Mapper for the\n\t\t// relevant file, but none exists if the file was loaded from\n\t\t// export data, and we have no means (Snapshot) of loading it.\n\t\t//\n\t\t// So, fall back to approximate conversion to UTF-16:\n\t\t// for non-ASCII text, the column numbers may be wrong.\n\t\tvar (\n\t\t\tstartPosn = safetoken.StartPosition(fset, start)\n\t\t\tendPosn   = safetoken.EndPosition(fset, end)\n\t\t)\n\t\treturn protocol.Location{\n\t\t\tURI: protocol.URIFromPath(startPosn.Filename),\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{\n\t\t\t\t\tLine:      uint32(startPosn.Line - 1),\n\t\t\t\t\tCharacter: uint32(startPosn.Column - 1),\n\t\t\t\t},\n\t\t\t\tEnd: protocol.Position{\n\t\t\t\t\tLine:      uint32(endPosn.Line - 1),\n\t\t\t\t\tCharacter: uint32(endPosn.Column - 1),\n\t\t\t\t},\n\t\t\t},\n\t\t}, nil\n\t}\n\n\t// The start position was not among the package's parsed\n\t// Go files, indicating that the analyzer added new files\n\t// to the FileSet.\n\t//\n\t// For example, the cgocall analyzer re-parses and\n\t// type-checks some of the files in a special environment;\n\t// and asmdecl and other low-level runtime analyzers call\n\t// ReadFile to parse non-Go files.\n\t// (This is a supported feature, documented at go/analysis.)\n\t//\n\t// In principle these files could be:\n\t//\n\t// - OtherFiles (non-Go files such as asm).\n\t//   However, we set Pass.OtherFiles=[] because\n\t//   gopls won't service \"diagnose\" requests\n\t//   for non-Go files, so there's no point\n\t//   reporting diagnostics in them.\n\t//\n\t// - IgnoredFiles (files tagged for other configs).\n\t//   However, we set Pass.IgnoredFiles=[] because,\n\t//   in most cases, zero-config gopls should create\n\t//   another view that covers these files.\n\t//\n\t// - Referents of //line directives, as in cgo packages.\n\t//   The file names in this case are not known a priori.\n\t//   gopls generally tries to avoid honoring line directives,\n\t//   but analyzers such as cgocall may honor them.\n\t//\n\t// In short, it's unclear how this can be reached\n\t// other than due to an analyzer bug.\n\n\treturn protocol.Location{}, bug.Errorf(\"diagnostic location is not among files of package: %s\", tokFile.Name())\n}\n\n// effectiveURL computes the effective URL of diag,\n// using the algorithm specified at Diagnostic.URL.\nfunc effectiveURL(a *analysis.Analyzer, diag analysis.Diagnostic) string {\n\tu := diag.URL\n\tif u == \"\" && diag.Category != \"\" {\n\t\tu = \"#\" + diag.Category\n\t}\n\tif base, err := urlpkg.Parse(a.URL); err == nil {\n\t\tif rel, err := urlpkg.Parse(u); err == nil {\n\t\t\tu = base.ResolveReference(rel).String()\n\t\t}\n\t}\n\treturn u\n}\n\n// stableName returns a name for the analyzer that is unique and\n// stable across address spaces.\n//\n// Analyzer names are not unique. For example, gopls includes\n// both x/tools/passes/nilness and staticcheck/nilness.\n// For serialization, we must assign each analyzer a unique identifier\n// that two gopls processes accessing the cache can agree on.\nfunc stableName(a *analysis.Analyzer) string {\n\t// Incorporate the file and line of the analyzer's Run function.\n\taddr := reflect.ValueOf(a.Run).Pointer()\n\tfn := runtime.FuncForPC(addr)\n\tfile, line := fn.FileLine(addr)\n\n\t// It is tempting to use just a.Name as the stable name when\n\t// it is unique, but making them always differ helps avoid\n\t// name/stablename confusion.\n\treturn fmt.Sprintf(\"%s(%s:%d)\", a.Name, filepath.Base(file), line)\n}\n"
  },
  {
    "path": "gopls/internal/cache/cache.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"reflect\"\n\t\"strconv\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\n// ballast is a 100MB unused byte slice that exists only to reduce garbage\n// collector CPU in small workspaces and at startup.\n//\n// The redesign of gopls described at https://go.dev/blog/gopls-scalability\n// moved gopls to a model where it has a significantly smaller heap, yet still\n// allocates many short-lived data structures during parsing and type checking.\n// As a result, for some workspaces, particularly when opening a low-level\n// package, the steady-state heap may be a small fraction of total allocation\n// while rechecking the workspace, paradoxically causing the GC to consume much\n// more CPU. For example, in one benchmark that analyzes the starlark\n// repository, the steady-state heap was ~10MB, and the process of diagnosing\n// the workspace allocated 100-200MB.\n//\n// The reason for this paradoxical behavior is that GC pacing\n// (https://tip.golang.org/doc/gc-guide#GOGC) causes the collector to trigger\n// at some multiple of the steady-state heap size, so a small steady-state heap\n// causes GC to trigger sooner and more often when allocating the ephemeral\n// structures.\n//\n// Allocating a 100MB ballast avoids this problem by ensuring a minimum heap\n// size. The value of 100MB was chosen to be proportional to the in-memory\n// cache in front the filecache package, and the throughput of type checking.\n// Gopls already requires hundreds of megabytes of RAM to function.\n//\n// Note that while other use cases for a ballast were made obsolete by\n// GOMEMLIMIT, ours is not. GOMEMLIMIT helps in cases where you have a\n// containerized service and want to optimize its latency and throughput by\n// taking advantage of available memory. However, in our case gopls is running\n// on the developer's machine alongside other applications, and can have a wide\n// range of memory footprints depending on the size of the user's workspace.\n// Setting GOMEMLIMIT to too low a number would make gopls perform poorly on\n// large repositories, and setting it to too high a number would make gopls a\n// badly behaved tenant. Short of calibrating GOMEMLIMIT based on the user's\n// workspace (an intractible problem), there is no way for gopls to use\n// GOMEMLIMIT to solve its GC CPU problem.\n//\n// Because this allocation is large and occurs early, there is a good chance\n// that rather than being recycled, it comes directly from the OS already\n// zeroed, and since it is never accessed, the memory region may avoid being\n// backed by pages of RAM. But see\n// https://groups.google.com/g/golang-nuts/c/66d0cItfkjY/m/3NvgzL_sAgAJ\n//\n// For more details on this technique, see:\n// https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap/\nvar ballast = make([]byte, 100*1e6)\n\n// New Creates a new cache for gopls operation results, using the given file\n// set, shared store, and session options.\n//\n// Both the fset and store may be nil, but if store is non-nil so must be fset\n// (and they must always be used together), otherwise it may be possible to get\n// cached data referencing token.Pos values not mapped by the FileSet.\nfunc New(store *memoize.Store) *Cache {\n\tindex := atomic.AddInt64(&cacheIndex, 1)\n\n\tif store == nil {\n\t\tstore = &memoize.Store{}\n\t}\n\n\tc := &Cache{\n\t\tid:         strconv.FormatInt(index, 10),\n\t\tstore:      store,\n\t\tmemoizedFS: newMemoizedFS(),\n\t\tmodCache: &sharedModCache{\n\t\t\tcaches: make(map[string]*imports.DirInfoCache),\n\t\t\ttimers: make(map[string]*refreshTimer),\n\t\t},\n\t}\n\treturn c\n}\n\n// A Cache holds content that is shared across multiple gopls sessions.\ntype Cache struct {\n\tid string\n\n\t// store holds cached calculations.\n\t//\n\t// TODO(rfindley): at this point, these are not important, as we've moved our\n\t// content-addressable cache to the file system (the filecache package). It\n\t// is unlikely that this shared cache provides any shared value. We should\n\t// consider removing it, replacing current uses with a simpler futures cache,\n\t// as we've done for e.g. type-checked packages.\n\tstore *memoize.Store\n\n\t// memoizedFS holds a shared file.Source that caches reads.\n\t//\n\t// Reads are invalidated when *any* session gets a didChangeWatchedFile\n\t// notification. This is fine: it is the responsibility of memoizedFS to hold\n\t// our best knowledge of the current file system state.\n\t*memoizedFS\n\n\t// modCache holds the shared goimports state for GOMODCACHE directories\n\tmodCache *sharedModCache\n}\n\nvar cacheIndex, sessionIndex, viewIndex int64\n\nfunc (c *Cache) ID() string                     { return c.id }\nfunc (c *Cache) MemStats() map[reflect.Type]int { return c.store.Stats() }\n\n// FileStats returns information about the set of files stored in the cache.\n// It is intended for debugging only.\nfunc (c *Cache) FileStats() (stats command.FileStats) {\n\tstats.Total, stats.Largest, stats.Errs = c.fileStats()\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/cache/check.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/bloom\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/gcimporter\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\ntype unit = struct{}\n\n// A typeCheckBatch holds data for a logical type-checking operation, which may\n// type check many unrelated packages.\n//\n// It shares state such as parsed files and imports, to optimize type-checking\n// for packages with overlapping dependency graphs.\ntype typeCheckBatch struct {\n\t// handleMu guards _handles, which must only be accessed via addHandles or\n\t// getHandle.\n\t//\n\t// An alternative would be to simply verify that package handles are present\n\t// on the Snapshot, and access them directly, rather than copying maps for\n\t// each caller. However, handles are accessed very frequently during type\n\t// checking, and ordinary go maps are measurably faster than the\n\t// persistent.Map used to store handles on the snapshot.\n\thandleMu sync.Mutex\n\t_handles map[PackageID]*packageHandle\n\n\tparseCache       *parseCache\n\tfset             *token.FileSet                          // describes all parsed or imported files\n\tcpulimit         chan unit                               // concurrency limiter for CPU-bound operations\n\tsyntaxPackages   *futureCache[PackageID, *Package]       // transient cache of in-progress syntax futures\n\timportPackages   *futureCache[PackageID, *types.Package] // persistent cache of imports\n\tgopackagesdriver bool                                    // for bug reporting: were packages loaded with a driver?\n}\n\n// addHandles is called by each goroutine joining the type check batch, to\n// ensure that the batch has all inputs necessary for type checking.\nfunc (b *typeCheckBatch) addHandles(handles map[PackageID]*packageHandle) {\n\tb.handleMu.Lock()\n\tdefer b.handleMu.Unlock()\n\tfor id, ph := range handles {\n\t\tassert(ph.state >= validKey, \"invalid handle\")\n\n\t\tif alt, ok := b._handles[id]; !ok || alt.state < ph.state {\n\t\t\tb._handles[id] = ph\n\t\t}\n\t}\n}\n\n// getHandle retrieves the packageHandle for the given id.\nfunc (b *typeCheckBatch) getHandle(id PackageID) *packageHandle {\n\tb.handleMu.Lock()\n\tdefer b.handleMu.Unlock()\n\treturn b._handles[id]\n}\n\n// TypeCheck parses and type-checks the specified packages,\n// and returns them in the same order as the ids.\n// The resulting packages' types may belong to different importers,\n// so types from different packages are incommensurable.\n//\n// The resulting packages slice always contains len(ids) entries, though some\n// of them may be nil if (and only if) the resulting error is non-nil.\n//\n// An error is returned if any of the requested packages fail to type-check.\n// This is different from having type-checking errors: a failure to type-check\n// indicates context cancellation or otherwise significant failure to perform\n// the type-checking operation.\n//\n// In general, clients should never need to type-checked syntax for an\n// intermediate test variant (ITV) package. Callers should apply\n// RemoveIntermediateTestVariants (or equivalent) before this method, or any\n// of the potentially type-checking methods below.\nfunc (s *Snapshot) TypeCheck(ctx context.Context, ids ...PackageID) ([]*Package, error) {\n\tpkgs := make([]*Package, len(ids))\n\tpost := func(i int, pkg *Package) {\n\t\tpkgs[i] = pkg\n\t}\n\treturn pkgs, s.forEachPackage(ctx, ids, nil, post)\n}\n\n// Package visiting functions used by forEachPackage; see the documentation of\n// forEachPackage for details.\ntype (\n\tpreTypeCheck  = func(int, *packageHandle) bool // false => don't type check\n\tpostTypeCheck = func(int, *Package)\n)\n\n// forEachPackage does a pre- and post- order traversal of the packages\n// specified by ids using the provided pre and post functions.\n//\n// The pre func is optional. If set, pre is evaluated after the package\n// handle has been constructed, but before type-checking. If pre returns false,\n// type-checking is skipped for this package handle.\n//\n// post is called with a syntax package after type-checking completes\n// successfully. It is only called if pre returned true.\n//\n// Both pre and post may be called concurrently.\nfunc (s *Snapshot) forEachPackage(ctx context.Context, ids []PackageID, pre preTypeCheck, post postTypeCheck) error {\n\tctx, done := event.Start(ctx, \"cache.forEachPackage\", label.PackageCount.Of(len(ids)))\n\tdefer done()\n\n\tvar (\n\t\tneedIDs []PackageID // ids to type-check\n\t\tindexes []int       // original index of requested ids\n\t)\n\n\t// Check for existing active packages.\n\t//\n\t// Since gopls can't depend on package identity, any instance of the\n\t// requested package must be ok to return.\n\t//\n\t// This is an optimization to avoid redundant type-checking: following\n\t// changes to an open package many LSP clients send several successive\n\t// requests for package information for the modified package (semantic\n\t// tokens, code lens, inlay hints, etc.)\n\tfor i, id := range ids {\n\t\ts.mu.Lock()\n\t\tph, ok := s.packages.Get(id)\n\t\ts.mu.Unlock()\n\t\tif ok && ph.state >= validPackage {\n\t\t\tpost(i, ph.pkgData.pkg)\n\t\t} else {\n\t\t\tneedIDs = append(needIDs, id)\n\t\t\tindexes = append(indexes, i)\n\t\t}\n\t}\n\n\tif len(needIDs) == 0 {\n\t\treturn nil // short cut: many call sites do not handle empty ids\n\t}\n\n\tb, release := s.acquireTypeChecking()\n\tdefer release()\n\n\thandles, err := s.getPackageHandles(ctx, needIDs)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Wrap the pre- and post- funcs to translate indices.\n\tvar pre2 preTypeCheck\n\tif pre != nil {\n\t\tpre2 = func(i int, ph *packageHandle) bool {\n\t\t\treturn pre(indexes[i], ph)\n\t\t}\n\t}\n\tpost2 := func(i int, pkg *Package) {\n\t\tid := pkg.metadata.ID\n\t\tif ph := handles[id]; ph.isOpen && ph.state < validPackage {\n\t\t\t// Cache open type checked packages.\n\t\t\tph = ph.clone()\n\t\t\tph.pkgData = &packageData{\n\t\t\t\tfset:    pkg.FileSet(),\n\t\t\t\timports: pkg.Types().Imports(),\n\t\t\t\tpkg:     pkg,\n\t\t\t}\n\t\t\tph.state = validPackage\n\n\t\t\ts.mu.Lock()\n\t\t\tif alt, ok := s.packages.Get(id); !ok || alt.state < ph.state {\n\t\t\t\ts.packages.Set(id, ph, nil)\n\t\t\t}\n\t\t\ts.mu.Unlock()\n\t\t}\n\n\t\tpost(indexes[i], pkg)\n\t}\n\n\treturn b.query(ctx, needIDs, pre2, post2, handles)\n}\n\n// acquireTypeChecking joins or starts a concurrent type checking batch.\n//\n// The batch may be queried for package information using [typeCheckBatch.query].\n// The second result must be called when the batch is no longer needed, to\n// release the resource.\nfunc (s *Snapshot) acquireTypeChecking() (*typeCheckBatch, func()) {\n\ts.typeCheckMu.Lock()\n\tdefer s.typeCheckMu.Unlock()\n\n\tif s.batch == nil {\n\t\tassert(s.batchRef == 0, \"miscounted type checking\")\n\t\ts.batch = newTypeCheckBatch(s.view.parseCache, s.view.typ == GoPackagesDriverView)\n\t}\n\ts.batchRef++\n\n\treturn s.batch, func() {\n\t\ts.typeCheckMu.Lock()\n\t\tdefer s.typeCheckMu.Unlock()\n\t\tassert(s.batchRef > 0, \"miscounted type checking 2\")\n\t\ts.batchRef--\n\t\tif s.batchRef == 0 {\n\t\t\ts.batch = nil\n\t\t}\n\t}\n}\n\n// newTypeCheckBatch creates a new type checking batch using the provided\n// shared parseCache.\n//\n// If a non-nil importGraph is provided, imports in this graph will be reused.\nfunc newTypeCheckBatch(parseCache *parseCache, gopackagesdriver bool) *typeCheckBatch {\n\treturn &typeCheckBatch{\n\t\t_handles:         make(map[PackageID]*packageHandle),\n\t\tparseCache:       parseCache,\n\t\tfset:             fileSetWithBase(reservedForParsing),\n\t\tcpulimit:         make(chan unit, runtime.GOMAXPROCS(0)),\n\t\tsyntaxPackages:   newFutureCache[PackageID, *Package](false),      // don't persist syntax packages\n\t\timportPackages:   newFutureCache[PackageID, *types.Package](true), // ...but DO persist imports\n\t\tgopackagesdriver: gopackagesdriver,\n\t}\n}\n\n// query executes a traversal of package information in the given typeCheckBatch.\n// For each package in importIDs, the package will be loaded \"for import\" (sans\n// syntax).\n//\n// For each package in syntaxIDs, the package will be handled following the\n// pre- and post- traversal logic of [Snapshot.forEachPackage].\n//\n// Package handles must be provided for each package in the forward transitive\n// closure of either importIDs or syntaxIDs.\n//\n// TODO(rfindley): simplify this API by clarifying shared import graph and\n// package handle logic.\nfunc (b *typeCheckBatch) query(ctx context.Context, syntaxIDs []PackageID, pre preTypeCheck, post postTypeCheck, handles map[PackageID]*packageHandle) error {\n\tb.addHandles(handles)\n\n\t// Start a single goroutine for each requested package.\n\t//\n\t// Other packages are reached recursively, and will not be evaluated if they\n\t// are not needed.\n\tvar g errgroup.Group\n\tfor i, id := range syntaxIDs {\n\t\tg.Go(func() error {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t\treturn b.handleSyntaxPackage(ctx, i, id, pre, post)\n\t\t})\n\t}\n\treturn g.Wait()\n}\n\n// TODO(rfindley): re-order the declarations below to read better from top-to-bottom.\n\n// getImportPackage returns the *types.Package to use for importing the\n// package referenced by id.\n//\n// This may be the package produced by type-checking syntax (as in the case\n// where id is in the set of requested IDs), a package loaded from export data,\n// or a package type-checked for import only.\nfunc (b *typeCheckBatch) getImportPackage(ctx context.Context, id PackageID) (pkg *types.Package, err error) {\n\treturn b.importPackages.get(ctx, id, func(ctx context.Context) (*types.Package, error) {\n\t\tph := b.getHandle(id)\n\n\t\t// \"unsafe\" cannot be imported or type-checked.\n\t\t//\n\t\t// We check PkgPath, not id, as the structure of the ID\n\t\t// depends on the build system (in particular,\n\t\t// Bazel+gopackagesdriver appears to use something other than\n\t\t// \"unsafe\", though we aren't sure what; even 'go list' can\n\t\t// use \"p [q.test]\" for testing or if PGO is enabled.\n\t\t// See golang/go#60890.\n\t\tif ph.mp.PkgPath == \"unsafe\" {\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\n\t\tdata, err := filecache.Get(exportDataKind, ph.key)\n\t\tif err == filecache.ErrNotFound {\n\t\t\t// No cached export data: type-check as fast as possible.\n\t\t\treturn b.checkPackageForImport(ctx, ph)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read cache data for %s: %v\", ph.mp.ID, err)\n\t\t}\n\t\treturn b.importPackage(ctx, ph.mp, data)\n\t})\n}\n\n// handleSyntaxPackage handles one package from the ids slice.\n//\n// If type checking occurred while handling the package, it returns the\n// resulting types.Package so that it may be used for importing.\n//\n// handleSyntaxPackage returns (nil, nil) if pre returned false.\nfunc (b *typeCheckBatch) handleSyntaxPackage(ctx context.Context, i int, id PackageID, pre preTypeCheck, post postTypeCheck) error {\n\tph := b.getHandle(id)\n\tif pre != nil && !pre(i, ph) {\n\t\treturn nil // skip: not needed\n\t}\n\n\t// Check if we have a syntax package stored on ph.\n\t//\n\t// This was checked in [Snapshot.forEachPackage], but may have since changed.\n\tif ph.state >= validPackage {\n\t\tpost(i, ph.pkgData.pkg)\n\t\treturn nil\n\t}\n\n\tpkg, err := b.getPackage(ctx, ph)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpost(i, pkg)\n\treturn nil\n}\n\n// getPackage type checks one [Package] in the batch.\nfunc (b *typeCheckBatch) getPackage(ctx context.Context, ph *packageHandle) (*Package, error) {\n\treturn b.syntaxPackages.get(ctx, ph.mp.ID, func(ctx context.Context) (*Package, error) {\n\t\t// Wait for predecessors.\n\t\t// Record imports of this package to avoid redundant work in typesConfig.\n\t\timports := make(map[PackagePath]*types.Package)\n\t\tfset := b.fset\n\t\tif ph.state >= validImports {\n\t\t\tfor _, imp := range ph.pkgData.imports {\n\t\t\t\timports[PackagePath(imp.Path())] = imp\n\t\t\t}\n\t\t\t// Reusing imports requires that their positions are mapped by the FileSet.\n\t\t\tfset = tokeninternal.CloneFileSet(ph.pkgData.fset)\n\t\t} else {\n\t\t\tvar impMu sync.Mutex\n\t\t\tvar g errgroup.Group\n\t\t\tfor depPath, depID := range ph.mp.DepsByPkgPath {\n\t\t\t\tg.Go(func() error {\n\t\t\t\t\timp, err := b.getImportPackage(ctx, depID)\n\t\t\t\t\tif err == nil {\n\t\t\t\t\t\timpMu.Lock()\n\t\t\t\t\t\timports[depPath] = imp\n\t\t\t\t\t\timpMu.Unlock()\n\t\t\t\t\t}\n\t\t\t\t\treturn err\n\t\t\t\t})\n\t\t\t}\n\t\t\tif err := g.Wait(); err != nil {\n\t\t\t\t// Failure to import a package should not abort the whole operation.\n\t\t\t\t// Stop only if the context was cancelled, a likely cause.\n\t\t\t\t// Import errors will be reported as type diagnostics.\n\t\t\t\tif ctx.Err() != nil {\n\t\t\t\t\treturn nil, ctx.Err()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Wait to acquire a CPU token.\n\t\t//\n\t\t// Note: it is important to acquire this token only after awaiting\n\t\t// predecessors, to avoid starvation.\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, ctx.Err()\n\t\tcase b.cpulimit <- unit{}:\n\t\t\tdefer func() {\n\t\t\t\t<-b.cpulimit // release CPU token\n\t\t\t}()\n\t\t}\n\n\t\t// Compute the syntax package.\n\t\tp, err := b.checkPackage(ctx, fset, ph, imports)\n\t\tif err != nil {\n\t\t\treturn nil, err // e.g. I/O error, cancelled\n\t\t}\n\n\t\t// Update caches.\n\t\tgo storePackageResults(ctx, ph, p) // ...and write all packages to disk\n\t\treturn p, nil\n\t})\n}\n\n// storePackageResults serializes and writes information derived from p to the\n// file cache.\n// The context is used only for logging; cancellation does not affect the operation.\nfunc storePackageResults(ctx context.Context, ph *packageHandle, p *Package) {\n\ttoCache := map[string][]byte{\n\t\txrefsKind:       p.pkg.xrefs(),\n\t\tmethodSetsKind:  p.pkg.methodsets().Encode(),\n\t\ttestsKind:       p.pkg.tests().Encode(),\n\t\tdiagnosticsKind: encodeDiagnostics(p.pkg.diagnostics),\n\t}\n\n\tif p.metadata.PkgPath != \"unsafe\" { // unsafe cannot be exported\n\t\texportData, err := gcimporter.IExportShallow(p.pkg.fset, p.pkg.types, bug.Reportf)\n\t\tif err != nil {\n\t\t\tbug.Reportf(\"exporting package %v: %v\", p.metadata.ID, err)\n\t\t} else {\n\t\t\ttoCache[exportDataKind] = exportData\n\t\t}\n\t}\n\n\tfor kind, data := range toCache {\n\t\tif err := filecache.Set(kind, ph.key, data); err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"storing %s data for %s\", kind, ph.mp.ID), err)\n\t\t}\n\t}\n}\n\n// Metadata implements the [metadata.Source] interface.\nfunc (b *typeCheckBatch) Metadata(id PackageID) *metadata.Package {\n\tph := b.getHandle(id)\n\tif ph == nil {\n\t\treturn nil\n\t}\n\treturn ph.mp\n}\n\n// importPackage loads the given package from its export data in p.exportData\n// (which must already be populated).\nfunc (b *typeCheckBatch) importPackage(ctx context.Context, mp *metadata.Package, data []byte) (*types.Package, error) {\n\tctx, done := event.Start(ctx, \"cache.typeCheckBatch.importPackage\", label.Package.Of(string(mp.ID)))\n\tdefer done()\n\n\timportLookup := importLookup(mp, b)\n\n\tthisPackage := types.NewPackage(string(mp.PkgPath), string(mp.Name))\n\tgetPackages := func(items []gcimporter.GetPackagesItem) error {\n\t\tfor i, item := range items {\n\t\t\tvar id PackageID\n\t\t\tvar pkg *types.Package\n\t\t\tif item.Path == string(mp.PkgPath) {\n\t\t\t\tid = mp.ID\n\t\t\t\tpkg = thisPackage\n\n\t\t\t\t// debugging issues #60904, #64235\n\t\t\t\tif pkg.Name() != item.Name {\n\t\t\t\t\t// This would mean that mp.Name != item.Name, so the\n\t\t\t\t\t// manifest in the export data of mp.PkgPath is\n\t\t\t\t\t// inconsistent with mp.Name. Or perhaps there\n\t\t\t\t\t// are duplicate PkgPath items in the manifest?\n\t\t\t\t\tif b.gopackagesdriver {\n\t\t\t\t\t\treturn bug.Errorf(\"internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904) (using GOPACKAGESDRIVER)\",\n\t\t\t\t\t\t\tpkg.Name(), item.Name, id, item.Path)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// There's a package in the export data with the same path as the\n\t\t\t\t\t\t// imported package, but a different name.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// This is observed to occur (very frequently!) in telemetry, yet\n\t\t\t\t\t\t// we don't yet have a plausible explanation: any self import or\n\t\t\t\t\t\t// circular import should have resulted in a broken import, which\n\t\t\t\t\t\t// can't be referenced by export data. (Any type qualified by the\n\t\t\t\t\t\t// broken import name will be invalid.)\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// However, there are some mechanisms that could potentially be\n\t\t\t\t\t\t// involved:\n\t\t\t\t\t\t//  1. go/types will synthesize package names based on the import\n\t\t\t\t\t\t//     path for fake packages (but as mentioned above, I don't think\n\t\t\t\t\t\t//     these can be referenced by export data.)\n\t\t\t\t\t\t//  2. Test variants have the same path as non-test variant. Could\n\t\t\t\t\t\t//     that somehow be involved? (I don't see how, particularly using\n\t\t\t\t\t\t//     the go list driver, but nevertheless it's worth considering.)\n\t\t\t\t\t\t//  3. Command-line arguments and main packages may have special\n\t\t\t\t\t\t//     handling that we don't fully understand.\n\t\t\t\t\t\t// Try to sort these potential causes into unique stacks, as well\n\t\t\t\t\t\t// as a few other pathological scenarios.\n\t\t\t\t\t\treport := func() error {\n\t\t\t\t\t\t\treturn bug.Errorf(\"internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904)\",\n\t\t\t\t\t\t\t\tpkg.Name(), item.Name, id, item.Path)\n\t\t\t\t\t\t}\n\t\t\t\t\t\timpliedName := \"\"\n\t\t\t\t\t\tif i := strings.LastIndex(item.Path, \"/\"); i >= 0 {\n\t\t\t\t\t\t\timpliedName = item.Path[i+1:]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tswitch {\n\t\t\t\t\t\tcase pkg.Name() == \"\":\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase item.Name == \"\":\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase metadata.IsCommandLineArguments(mp.ID):\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase mp.ForTest != \"\":\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase len(mp.CompiledGoFiles) == 0:\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase len(mp.Errors) > 0:\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase impliedName != \"\" && impliedName != string(mp.Name):\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase len(mp.CompiledGoFiles) != len(mp.GoFiles):\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase mp.Module == nil:\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tcase mp.Name == \"main\":\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\treturn report()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar alt PackageID\n\t\t\t\tid, alt = importLookup(PackagePath(item.Path))\n\t\t\t\tif alt != \"\" {\n\t\t\t\t\t// Any bug leading to this scenario would have already been reported\n\t\t\t\t\t// in importLookup.\n\t\t\t\t\treturn fmt.Errorf(\"inconsistent metadata during import: for package path %q, found both IDs %q and %q\", item.Path, id, alt)\n\t\t\t\t}\n\t\t\t\tvar err error\n\t\t\t\tpkg, err = b.getImportPackage(ctx, id)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\t// We intentionally duplicate the bug.Errorf calls because\n\t\t\t\t// telemetry tells us only the program counter, not the message.\n\n\t\t\t\t// debugging issues #60904, #64235\n\t\t\t\tif pkg.Name() != item.Name {\n\t\t\t\t\t// This means that, while reading the manifest of the\n\t\t\t\t\t// export data of mp.PkgPath, one of its indirect\n\t\t\t\t\t// dependencies had a name that differs from the\n\t\t\t\t\t// Metadata.Name\n\t\t\t\t\treturn bug.Errorf(\"internal error: package name is %q, want %q (id=%q, path=%q) (see issue #60904)\",\n\t\t\t\t\t\tpkg.Name(), item.Name, id, item.Path)\n\t\t\t\t}\n\t\t\t}\n\t\t\titems[i].Pkg = pkg\n\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Importing is potentially expensive, and might not encounter cancellations\n\t// via dependencies (e.g. if they have already been evaluated).\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\timported, err := gcimporter.IImportShallow(b.fset, getPackages, data, string(mp.PkgPath), bug.Reportf)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"import failed for %q: %v\", mp.ID, err)\n\t}\n\treturn imported, nil\n}\n\n// checkPackageForImport type checks, but skips function bodies and does not\n// record syntax information.\nfunc (b *typeCheckBatch) checkPackageForImport(ctx context.Context, ph *packageHandle) (*types.Package, error) {\n\tctx, done := event.Start(ctx, \"cache.typeCheckBatch.checkPackageForImport\", label.Package.Of(string(ph.mp.ID)))\n\tdefer done()\n\n\tonError := func(e error) {\n\t\t// Ignore errors for exporting.\n\t}\n\tcfg := b.typesConfig(ctx, ph.localInputs, nil, onError)\n\tcfg.IgnoreFuncBodies = true\n\n\t// Parse the compiled go files, bypassing the parse cache as packages checked\n\t// for import are unlikely to get cache hits. Additionally, we can optimize\n\t// parsing slightly by not passing parser.ParseComments.\n\tpgfs := make([]*parsego.File, len(ph.localInputs.compiledGoFiles))\n\t{\n\t\tvar group errgroup.Group\n\t\t// Set an arbitrary concurrency limit; we want some parallelism but don't\n\t\t// need GOMAXPROCS, as there is already a lot of concurrency among calls to\n\t\t// checkPackageForImport.\n\t\t//\n\t\t// TODO(rfindley): is there a better way to limit parallelism here? We could\n\t\t// have a global limit on the type-check batch, but would have to be very\n\t\t// careful to avoid starvation.\n\t\tgroup.SetLimit(4)\n\t\tfor i, fh := range ph.localInputs.compiledGoFiles {\n\t\t\tgroup.Go(func() error {\n\t\t\t\tpgf, err := parseGoImpl(ctx, b.fset, fh, parser.SkipObjectResolution, false)\n\t\t\t\tpgfs[i] = pgf\n\t\t\t\treturn err\n\t\t\t})\n\t\t}\n\t\tif err := group.Wait(); err != nil {\n\t\t\treturn nil, err // cancelled, or catastrophic error (e.g. missing file)\n\t\t}\n\t}\n\tpkg := types.NewPackage(string(ph.localInputs.pkgPath), string(ph.localInputs.name))\n\tcheck := types.NewChecker(cfg, b.fset, pkg, nil)\n\n\tfiles := make([]*ast.File, len(pgfs))\n\tfor i, pgf := range pgfs {\n\t\tfiles[i] = pgf.File\n\t}\n\n\t// Type checking is expensive, and we may not have encountered cancellations\n\t// via parsing (e.g. if we got nothing but cache hits for parsed files).\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\t_ = check.Files(files) // ignore errors\n\n\t// If the context was cancelled, we may have returned a ton of transient\n\t// errors to the type checker. Swallow them.\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\t// Asynchronously record export data.\n\tgo func() {\n\t\texportData, err := gcimporter.IExportShallow(b.fset, pkg, bug.Reportf)\n\t\tif err != nil {\n\t\t\t// Internal error; the stack will have been reported via\n\t\t\t// bug.Reportf within IExportShallow, so there's not much\n\t\t\t// to do here (issue #71067).\n\t\t\tevent.Error(ctx, \"IExportShallow failed\", err, label.Package.Of(string(ph.mp.ID)))\n\t\t\treturn\n\t\t}\n\t\tif err := filecache.Set(exportDataKind, ph.key, exportData); err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"storing export data for %s\", ph.mp.ID), err)\n\t\t}\n\t}()\n\treturn pkg, nil\n}\n\n// importLookup returns a function that may be used to look up a package ID for\n// a given package path, based on the forward transitive closure of the initial\n// package (id).\n//\n// If the second result is non-empty, it is another ID discovered in the import\n// graph for the same package path. This means the import graph is\n// incoherent--see #63822 and the long comment below.\n//\n// The resulting function is not concurrency safe.\nfunc importLookup(mp *metadata.Package, source metadata.Source) func(PackagePath) (id, altID PackageID) {\n\tassert(mp != nil, \"nil metadata\")\n\n\t// This function implements an incremental depth first scan through the\n\t// package imports. Previous implementations of import mapping built the\n\t// entire PackagePath->PackageID mapping eagerly, but that resulted in a\n\t// large amount of unnecessary work: most imports are either directly\n\t// imported, or found through a shallow scan.\n\n\t// impMap memoizes the lookup of package paths.\n\timpMap := map[PackagePath]PackageID{\n\t\tmp.PkgPath: mp.ID,\n\t}\n\n\t// altIDs records alternative IDs for the given path, to report inconsistent\n\t// metadata.\n\tvar altIDs map[PackagePath]PackageID\n\n\t// pending is a FIFO queue of package metadata that has yet to have its\n\t// dependencies fully scanned.\n\t// Invariant: all entries in pending are already mapped in impMap.\n\tpending := []*metadata.Package{mp}\n\n\t// search scans children the next package in pending, looking for pkgPath.\n\t// Invariant: whenever search is called, pkgPath is not yet mapped.\n\tsearch := func(pkgPath PackagePath) (id PackageID, found bool) {\n\t\tpkg := pending[0]\n\t\tpending = pending[1:]\n\t\tfor depPath, depID := range pkg.DepsByPkgPath {\n\t\t\tif prevID, ok := impMap[depPath]; ok {\n\t\t\t\t// debugging #63822\n\t\t\t\tif prevID != depID {\n\t\t\t\t\tif altIDs == nil {\n\t\t\t\t\t\taltIDs = make(map[PackagePath]PackageID)\n\t\t\t\t\t}\n\t\t\t\t\tif _, ok := altIDs[depPath]; !ok {\n\t\t\t\t\t\taltIDs[depPath] = depID\n\t\t\t\t\t}\n\t\t\t\t\tprev := source.Metadata(prevID)\n\t\t\t\t\tcurr := source.Metadata(depID)\n\t\t\t\t\tswitch {\n\t\t\t\t\tcase prev == nil || curr == nil:\n\t\t\t\t\t\tbug.Reportf(\"inconsistent view of dependencies (missing dep)\")\n\t\t\t\t\tcase prev.ForTest != curr.ForTest:\n\t\t\t\t\t\t// This case is unfortunately understood to be possible.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To explain this, consider a package a_test testing the package\n\t\t\t\t\t\t// a, and for brevity denote by b' the intermediate test variant of\n\t\t\t\t\t\t// the package b, which is created for the import graph of a_test,\n\t\t\t\t\t\t// if b imports a.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Now imagine that we have the following import graph, where\n\t\t\t\t\t\t// higher packages import lower ones.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t//       a_test\n\t\t\t\t\t\t//      / \\\n\t\t\t\t\t\t//     b'  c\n\t\t\t\t\t\t//    / \\ /\n\t\t\t\t\t\t//   a   d\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// In this graph, there is one intermediate test variant b',\n\t\t\t\t\t\t// because b imports a and so b' must hold the test variant import.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Now, imagine that an on-disk change (perhaps due to a branch\n\t\t\t\t\t\t// switch) affects the above import graph such that d imports a.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t//       a_test\n\t\t\t\t\t\t//      / \\\n\t\t\t\t\t\t//     b'  c*\n\t\t\t\t\t\t//    / \\ /\n\t\t\t\t\t\t//   /   d*\n\t\t\t\t\t\t//  a---/\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// In this case, c and d should really be intermediate test\n\t\t\t\t\t\t// variants, because they reach a. However, suppose that gopls does\n\t\t\t\t\t\t// not know this yet (as indicated by '*').\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Now suppose that the metadata of package c is invalidated, for\n\t\t\t\t\t\t// example due to a change in an unrelated import or an added file.\n\t\t\t\t\t\t// This will invalidate the metadata of c and a_test (but NOT b),\n\t\t\t\t\t\t// and now gopls observes this graph:\n\t\t\t\t\t\t//\n\t\t\t\t\t\t//       a_test\n\t\t\t\t\t\t//      / \\\n\t\t\t\t\t\t//     b'  c'\n\t\t\t\t\t\t//    /|   |\n\t\t\t\t\t\t//   / d   d'\n\t\t\t\t\t\t//  a-----/\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// That is: a_test now sees c', which sees d', but since b was not\n\t\t\t\t\t\t// invalidated, gopls still thinks that b' imports d (not d')!\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// The problem, of course, is that gopls never observed the change\n\t\t\t\t\t\t// to d, which would have invalidated b. This may be due to racing\n\t\t\t\t\t\t// file watching events, in which case the problem should\n\t\t\t\t\t\t// self-correct when gopls sees the change to d, or it may be due\n\t\t\t\t\t\t// to d being outside the coverage of gopls' file watching glob\n\t\t\t\t\t\t// patterns, or it may be due to buggy or entirely absent\n\t\t\t\t\t\t// client-side file watching.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// TODO(rfindley): fix this, one way or another. It would be hard\n\t\t\t\t\t\t// or impossible to repair gopls' state here, during type checking.\n\t\t\t\t\t\t// However, we could perhaps reload metadata in Snapshot.load until\n\t\t\t\t\t\t// we achieve a consistent state, or better, until the loaded state\n\t\t\t\t\t\t// is consistent with our view of the filesystem, by making the Go\n\t\t\t\t\t\t// command report digests of the files it reads. Both of those are\n\t\t\t\t\t\t// tricker than they may seem, and have significant performance\n\t\t\t\t\t\t// implications.\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbug.Reportf(\"inconsistent view of dependencies\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timpMap[depPath] = depID\n\n\t\t\tdep := source.Metadata(depID)\n\t\t\tassert(dep != nil, \"missing dep metadata\")\n\n\t\t\tpending = append(pending, dep)\n\t\t\tif depPath == pkgPath {\n\t\t\t\t// Don't return early; finish processing pkg's deps.\n\t\t\t\tid = depID\n\t\t\t\tfound = true\n\t\t\t}\n\t\t}\n\t\treturn id, found\n\t}\n\n\treturn func(pkgPath PackagePath) (id, altID PackageID) {\n\t\tif id, ok := impMap[pkgPath]; ok {\n\t\t\treturn id, altIDs[pkgPath]\n\t\t}\n\t\tfor len(pending) > 0 {\n\t\t\tif id, found := search(pkgPath); found {\n\t\t\t\treturn id, altIDs[pkgPath]\n\t\t\t}\n\t\t}\n\t\treturn \"\", \"\"\n\t}\n}\n\n// A packageState is the state of a [packageHandle]; see below for details.\ntype packageState uint8\n\nconst (\n\tvalidMetadata  packageState = iota // the package has valid metadata\n\tvalidLocalData                     // local package files have been analyzed\n\tvalidKey                           // dependencies have been analyzed, and key produced\n\tvalidImports                       // pkgData.fset and pkgData.imports are valid\n\tvalidPackage                       // pkgData.pkg is valid\n)\n\n// A packageHandle holds information derived from a metadata.Package, and\n// records its degree of validity as state changes occur: successful analysis\n// causes the state to progress; invalidation due to changes causes it to\n// regress.\n//\n// In the initial state (validMetadata), all we know is the metadata for the\n// package itself. This is the lowest state, and it cannot become invalid\n// because the metadata for a given snapshot never changes. (Each handle is\n// implicitly associated with a Snapshot.)\n//\n// After the files of the package have been read (validLocalData), we can\n// perform computations that are local to that package, such as parsing, or\n// building the symbol reference graph (SRG). This information is invalidated\n// by a change to any file in the package. The local information is thus\n// sufficient to form a cache key for saved parsed trees or the SRG.\n//\n// Once all dependencies have been analyzed (validKey), we can type-check the\n// package. This information is invalidated by any change to the package\n// itself, or to any dependency that is transitively reachable through the SRG.\n// The cache key for saved type information must thus incorporate information\n// from all reachable dependencies. This reachability analysis implements what\n// we sometimes refer to as \"precise pruning\", or fine-grained invalidation:\n// https://go.dev/blog/gopls-scalability#invalidation\n//\n// After type checking, package information for open packages is cached in the\n// pkgData field (validPackage), to optimize subsequent requests oriented\n// around open files.\n//\n// Following a change, the packageHandle is cloned in the new snapshot with a\n// new state set to its least known valid state, as described above: if package\n// files changed, it is reset to validMetadata; if dependencies changed, it is\n// reset to validLocalData. However, the derived data from its previous state\n// is not yet removed, as keys may not have changed after they are reevaluated,\n// in which case we can avoid recomputing the derived data. In particular, if\n// the cache key did not change, the pkgData field (if set) remains valid. As a\n// special case, if the cache key did change, but none of the keys of\n// dependencies changed, the pkgData.fset and pkgData.imports fields are still\n// valid, though the pkgData.pkg field is not (validImports).\n//\n// See [packageHandleBuilder.evaluatePackageHandle] for more details of the\n// reevaluation algorithm.\n//\n// packageHandles are immutable once they are stored in the Snapshot.packages\n// map: any changes to packageHandle fields evaluatePackageHandle must be made\n// to a cloned packageHandle, and inserted back into Snapshot.packages. Data\n// referred to by the packageHandle may be shared by multiple clones, and so\n// referents must not be mutated.\ntype packageHandle struct {\n\tmp *metadata.Package\n\n\t// state indicates which data below are still valid.\n\tstate packageState\n\n\t// Local data:\n\n\t// loadDiagnostics memoizes the result of processing error messages from\n\t// go/packages (i.e. `go list`).\n\t//\n\t// These are derived from metadata using a snapshot. Since they depend on\n\t// file contents (for translating positions), they should theoretically be\n\t// invalidated by file changes, but historically haven't been. In practice\n\t// they are rare and indicate a fundamental error that needs to be corrected\n\t// before development can continue, so it may not be worth significant\n\t// engineering effort to implement accurate invalidation here.\n\t//\n\t// TODO(rfindley): loadDiagnostics are out of place here, as they don't\n\t// directly relate to type checking. We should perhaps move the caching of\n\t// load diagnostics to an entirely separate component, so that Packages need\n\t// only be concerned with parsing and type checking.\n\t// (Nevertheless, since the lifetime of load diagnostics matches that of the\n\t// Metadata, it is convenient to memoize them here.)\n\tloadDiagnostics []*Diagnostic\n\t// localInputs holds all local type-checking localInputs, excluding\n\t// dependencies.\n\tlocalInputs *typeCheckInputs\n\t// isOpen reports whether the package has any open files.\n\tisOpen bool\n\t// localKey is a hash of localInputs.\n\tlocalKey file.Hash\n\t// refs is the result of syntactic dependency analysis produced by the\n\t// typerefs package. Derived from localInputs.\n\trefs map[string][]typerefs.Symbol\n\n\t// Keys, computed through reachability analysis of dependencies.\n\n\t// depKeys records the key of each dependency that was used to calculate the\n\t// key below. If state < validKey, we must re-check that each still matches.\n\tdepKeys map[PackageID]file.Hash\n\n\t// reachable is used to filter reachable package paths for go/analysis fact\n\t// importing.\n\treachable *bloom.Filter\n\n\t// key is the hashed key for the package.\n\t//\n\t// It includes the all bits of the transitive closure of\n\t// dependencies's sources.\n\tkey file.Hash\n\n\t// pkgData caches data derived from type checking the package.\n\t// This data is set during [Snapshot.forEachPackage], and may be partially\n\t// invalidated in [packageHandleBuilder.evaluatePackageHandle].\n\t//\n\t// If state == validPackage, all fields of pkgData are valid. If state ==\n\t// validImports, only fset and imports are valid.\n\tpkgData *packageData\n}\n\n// packageData holds the (possibly partial) result of type checking this\n// package. See the pkgData field of [packageHandle].\n//\n// packageData instances are immutable.\ntype packageData struct {\n\tfset    *token.FileSet   // pkg.FileSet()\n\timports []*types.Package // pkg.Types().Imports()\n\tpkg     *Package         // pkg, if state==validPackage; nil in lower states\n}\n\n// clone returns a shallow copy of the receiver.\nfunc (ph *packageHandle) clone() *packageHandle {\n\tclone := *ph\n\treturn &clone\n}\n\n// getPackageHandles gets package handles for all given ids and their\n// dependencies, recursively. The resulting [packageHandle] values are fully\n// evaluated (their state will be at least validKey).\nfunc (s *Snapshot) getPackageHandles(ctx context.Context, ids []PackageID) (map[PackageID]*packageHandle, error) {\n\t// perform a two-pass traversal.\n\t//\n\t// On the first pass, build up a bidirectional graph of handle nodes, and collect leaves.\n\t// Then build package handles from bottom up.\n\tb := &packageHandleBuilder{\n\t\ts:              s,\n\t\ttransitiveRefs: make(map[typerefs.IndexID]*partialRefs),\n\t\tnodes:          make(map[typerefs.IndexID]*handleNode),\n\t}\n\n\tmeta := s.MetadataGraph()\n\n\tvar leaves []*handleNode\n\tvar makeNode func(*handleNode, PackageID) *handleNode\n\tmakeNode = func(from *handleNode, id PackageID) *handleNode {\n\t\tidxID := s.view.pkgIndex.IndexID(id)\n\t\tn, ok := b.nodes[idxID]\n\t\tif !ok {\n\t\t\tmp := meta.Packages[id]\n\t\t\tif mp == nil {\n\t\t\t\tpanic(fmt.Sprintf(\"nil metadata for %q\", id))\n\t\t\t}\n\t\t\tn = &handleNode{\n\t\t\t\tmp:              mp,\n\t\t\t\tidxID:           idxID,\n\t\t\t\tunfinishedSuccs: int32(len(mp.DepsByPkgPath)),\n\t\t\t}\n\t\t\tif n.unfinishedSuccs == 0 {\n\t\t\t\tleaves = append(leaves, n)\n\t\t\t} else {\n\t\t\t\tn.succs = make(map[PackageID]*handleNode, n.unfinishedSuccs)\n\t\t\t}\n\t\t\tb.nodes[idxID] = n\n\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\tn.succs[depID] = makeNode(n, depID)\n\t\t\t}\n\t\t}\n\t\t// Add edge from predecessor.\n\t\tif from != nil {\n\t\t\tn.preds = append(n.preds, from)\n\t\t}\n\t\treturn n\n\t}\n\tfor _, id := range ids {\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t\tmakeNode(nil, id)\n\t}\n\n\tg, ctx := errgroup.WithContext(ctx)\n\n\t// files are preloaded, so building package handles is CPU-bound.\n\t//\n\t// Note that we can't use g.SetLimit, as that could result in starvation:\n\t// g.Go blocks until a slot is available, and so all existing goroutines\n\t// could be blocked trying to enqueue a predecessor.\n\tlimiter := make(chan unit, runtime.GOMAXPROCS(0))\n\n\tvar enqueue func(*handleNode)\n\tenqueue = func(n *handleNode) {\n\t\tg.Go(func() error {\n\t\t\tlimiter <- unit{}\n\t\t\tdefer func() { <-limiter }()\n\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\n\t\t\tif err := b.evaluatePackageHandle(ctx, n); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tfor _, pred := range n.preds {\n\t\t\t\tif atomic.AddInt32(&pred.unfinishedSuccs, -1) == 0 {\n\t\t\t\t\tenqueue(pred)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tfor _, leaf := range leaves {\n\t\tenqueue(leaf)\n\t}\n\n\tif err := g.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Copy handles into the result map.\n\thandles := make(map[PackageID]*packageHandle, len(b.nodes))\n\tfor _, v := range b.nodes {\n\t\tassert(v.ph != nil, \"nil handle\")\n\t\thandles[v.mp.ID] = v.ph\n\t}\n\n\treturn handles, nil\n}\n\n// A packageHandleBuilder computes a batch of packageHandles concurrently,\n// sharing computed transitive reachability sets used to compute package keys.\ntype packageHandleBuilder struct {\n\ts *Snapshot\n\n\t// nodes are assembled synchronously.\n\tnodes map[typerefs.IndexID]*handleNode\n\n\t// transitiveRefs is incrementally evaluated as package handles are built.\n\ttransitiveRefsMu sync.Mutex\n\ttransitiveRefs   map[typerefs.IndexID]*partialRefs // see getTransitiveRefs\n}\n\n// A handleNode represents a to-be-computed packageHandle within a graph of\n// predecessors and successors.\n//\n// It is used to implement a bottom-up construction of packageHandles.\ntype handleNode struct {\n\tmp              *metadata.Package\n\tidxID           typerefs.IndexID\n\tph              *packageHandle\n\tpreds           []*handleNode\n\tsuccs           map[PackageID]*handleNode\n\tunfinishedSuccs int32\n}\n\n// partialRefs maps names declared by a given package to their set of\n// transitive references.\n//\n// If complete is set, refs is known to be complete for the package in\n// question. Otherwise, it may only map a subset of all names declared by the\n// package.\ntype partialRefs struct {\n\trefs     map[string]*typerefs.PackageSet\n\tcomplete bool\n}\n\n// getTransitiveRefs gets or computes the set of transitively reachable\n// packages for each exported name in the package specified by id.\n//\n// The operation may fail if building a predecessor failed. If and only if this\n// occurs, the result will be nil.\nfunc (b *packageHandleBuilder) getTransitiveRefs(pkgID PackageID) map[string]*typerefs.PackageSet {\n\tb.transitiveRefsMu.Lock()\n\tdefer b.transitiveRefsMu.Unlock()\n\n\tidxID := b.s.view.pkgIndex.IndexID(pkgID)\n\ttrefs, ok := b.transitiveRefs[idxID]\n\tif !ok {\n\t\ttrefs = &partialRefs{\n\t\t\trefs: make(map[string]*typerefs.PackageSet),\n\t\t}\n\t\tb.transitiveRefs[idxID] = trefs\n\t}\n\n\tif !trefs.complete {\n\t\ttrefs.complete = true\n\t\tnode := b.nodes[idxID]\n\t\tfor name := range node.ph.refs {\n\t\t\tif ('A' <= name[0] && name[0] <= 'Z') || token.IsExported(name) {\n\t\t\t\tif _, ok := trefs.refs[name]; !ok {\n\t\t\t\t\tpkgs := b.s.view.pkgIndex.NewSet()\n\t\t\t\t\tfor _, sym := range node.ph.refs[name] {\n\t\t\t\t\t\tpkgs.Add(sym.Package)\n\t\t\t\t\t\totherSet := b.getOneTransitiveRefLocked(sym)\n\t\t\t\t\t\tpkgs.Union(otherSet)\n\t\t\t\t\t}\n\t\t\t\t\ttrefs.refs[name] = pkgs\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn trefs.refs\n}\n\n// getOneTransitiveRefLocked computes the full set packages transitively\n// reachable through the given sym reference.\n//\n// It may return nil if the reference is invalid (i.e. the referenced name does\n// not exist).\nfunc (b *packageHandleBuilder) getOneTransitiveRefLocked(sym typerefs.Symbol) *typerefs.PackageSet {\n\tassert(token.IsExported(sym.Name), \"expected exported symbol\")\n\n\ttrefs := b.transitiveRefs[sym.Package]\n\tif trefs == nil {\n\t\ttrefs = &partialRefs{\n\t\t\trefs:     make(map[string]*typerefs.PackageSet),\n\t\t\tcomplete: false,\n\t\t}\n\t\tb.transitiveRefs[sym.Package] = trefs\n\t}\n\n\tpkgs, ok := trefs.refs[sym.Name]\n\tif ok && pkgs == nil {\n\t\t// See below, where refs is set to nil before recursing.\n\t\tbug.Reportf(\"cycle detected to %q in reference graph\", sym.Name)\n\t}\n\n\t// Note that if (!ok && trefs.complete), the name does not exist in the\n\t// referenced package, and we should not write to trefs as that may introduce\n\t// a race.\n\tif !ok && !trefs.complete {\n\t\tn := b.nodes[sym.Package]\n\t\tif n == nil {\n\t\t\t// We should always have IndexID in our node set, because symbol references\n\t\t\t// should only be recorded for packages that actually exist in the import graph.\n\t\t\t//\n\t\t\t// However, it is not easy to prove this (typerefs are serialized and\n\t\t\t// deserialized), so make this code temporarily defensive while we are on a\n\t\t\t// point release.\n\t\t\t//\n\t\t\t// TODO(rfindley): in the future, we should turn this into an assertion.\n\t\t\tbug.Reportf(\"missing reference to package %s\", b.s.view.pkgIndex.PackageID(sym.Package))\n\t\t\treturn nil\n\t\t}\n\n\t\t// Break cycles. This is perhaps overly defensive as cycles should not\n\t\t// exist at this point: metadata cycles should have been broken at load\n\t\t// time, and intra-package reference cycles should have been contracted by\n\t\t// the typerefs algorithm.\n\t\t//\n\t\t// See the \"cycle detected\" bug report above.\n\t\ttrefs.refs[sym.Name] = nil\n\n\t\tpkgs := b.s.view.pkgIndex.NewSet()\n\t\tfor _, sym2 := range n.ph.refs[sym.Name] {\n\t\t\tpkgs.Add(sym2.Package)\n\t\t\totherSet := b.getOneTransitiveRefLocked(sym2)\n\t\t\tpkgs.Union(otherSet)\n\t\t}\n\t\ttrefs.refs[sym.Name] = pkgs\n\t}\n\n\treturn pkgs\n}\n\n// evaluatePackageHandle recomputes the derived information in the package handle.\n// On success, the handle's state is validKey.\n//\n// evaluatePackageHandle must only be called from getPackageHandles.\nfunc (b *packageHandleBuilder) evaluatePackageHandle(ctx context.Context, n *handleNode) (err error) {\n\tb.s.mu.Lock()\n\tph, hit := b.s.packages.Get(n.mp.ID)\n\tb.s.mu.Unlock()\n\n\tdefer func() {\n\t\tif err == nil {\n\t\t\tassert(ph.state >= validKey, \"invalid handle\")\n\n\t\t\t// Record the now valid key in the snapshot.\n\t\t\t// There may be a race, so avoid the write if the recorded handle is\n\t\t\t// already valid.\n\t\t\tb.s.mu.Lock()\n\t\t\tif alt, ok := b.s.packages.Get(n.mp.ID); !ok || alt.state < ph.state {\n\t\t\t\tb.s.packages.Set(n.mp.ID, ph, nil)\n\t\t\t} else {\n\t\t\t\tph = alt\n\t\t\t}\n\t\t\tb.s.mu.Unlock()\n\n\t\t\t// Initialize n.ph.\n\t\t\tn.ph = ph\n\t\t}\n\t}()\n\n\tif hit && ph.state >= validKey {\n\t\treturn nil // already valid\n\t} else {\n\t\t// We'll need to update the package handle. Since this could happen\n\t\t// concurrently, make a copy.\n\t\tif hit {\n\t\t\tph = ph.clone() // state < validKey\n\t\t} else {\n\t\t\tph = &packageHandle{\n\t\t\t\tmp:    n.mp,\n\t\t\t\tstate: validMetadata,\n\t\t\t}\n\t\t}\n\t}\n\n\t// Invariant: ph is either\n\t// - a new handle in state validMetadata, or\n\t// - a clone of an existing handle in state validMetadata or validLocalData.\n\n\t// State transition: validMetadata -> validLocalInputs.\n\tlocalKeyChanged := false\n\tif ph.state < validLocalData {\n\t\tprevLocalKey := ph.localKey // may be zero\n\t\t// No package handle: read and analyze the package syntax.\n\t\tinputs, err := b.s.typeCheckInputs(ctx, n.mp)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trefs, err := b.s.typerefs(ctx, n.mp, inputs.compiledGoFiles)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tph.loadDiagnostics = computeLoadDiagnostics(ctx, b.s, n.mp)\n\t\tph.localInputs = inputs\n\n\tcheckOpen:\n\t\tfor _, files := range [][]file.Handle{inputs.goFiles, inputs.compiledGoFiles} {\n\t\t\tfor _, fh := range files {\n\t\t\t\tif _, ok := fh.(*overlay); ok {\n\t\t\t\t\tph.isOpen = true\n\t\t\t\t\tbreak checkOpen\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif !ph.isOpen {\n\t\t\t// ensure we don't hold data for closed packages\n\t\t\tph.pkgData = nil\n\t\t}\n\t\tph.localKey = localPackageKey(inputs)\n\t\tph.refs = refs\n\t\tph.state = validLocalData\n\t\tlocalKeyChanged = ph.localKey != prevLocalKey\n\t}\n\n\tassert(ph.state == validLocalData, \"unexpected handle state\")\n\n\t// State transition: validLocalInputs -> validKey\n\n\t// Check if any dependencies have actually changed.\n\tdepsChanged := true\n\tif ph.depKeys != nil { // ph was previously evaluated\n\t\tdepsChanged = len(ph.depKeys) != len(n.succs)\n\t\tif !depsChanged {\n\t\t\tfor id, succ := range n.succs {\n\t\t\t\toldKey, ok := ph.depKeys[id]\n\t\t\t\tassert(ok, \"missing dep\")\n\t\t\t\tif oldKey != succ.ph.key {\n\t\t\t\t\tdepsChanged = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Optimization: if the local package information did not change, nor did any\n\t// of the dependencies, we don't need to re-run the reachability algorithm.\n\t//\n\t// Concretely: suppose A -> B -> C -> D, where '->' means \"imports\". If I\n\t// type in a function body of D, I will probably invalidate types in D that C\n\t// uses, because positions change, and therefore the package key of C will\n\t// change. But B probably doesn't reach any types in D, and therefore the\n\t// package key of B will not change. We still need to re-run the reachability\n\t// algorithm on B to confirm. But if the key of B did not change, we don't\n\t// even need to run the reachability algorithm on A.\n\tif !localKeyChanged && !depsChanged {\n\t\tph.state = validKey\n\t}\n\n\tkeyChanged := false\n\tif ph.state < validKey {\n\t\tprevKey := ph.key\n\n\t\t// If we get here, it must be the case that deps have changed, so we must\n\t\t// run the reachability algorithm.\n\t\tph.depKeys = make(map[PackageID]file.Hash)\n\n\t\t// See the typerefs package: the reachable set of packages is defined to be\n\t\t// the set of packages containing syntax that is reachable through the\n\t\t// symbol reference graph starting at the exported symbols in the\n\t\t// dependencies of ph.\n\t\treachable := b.s.view.pkgIndex.NewSet()\n\t\tfor depID, succ := range n.succs {\n\t\t\tph.depKeys[depID] = succ.ph.key\n\t\t\treachable.Add(succ.idxID)\n\t\t\ttrefs := b.getTransitiveRefs(succ.mp.ID)\n\t\t\tassert(trefs != nil, \"nil trefs\")\n\t\t\tfor _, set := range trefs {\n\t\t\t\treachable.Union(set)\n\t\t\t}\n\t\t}\n\n\t\t// Collect reachable nodes.\n\t\tvar reachableNodes []*handleNode\n\t\t// In the presence of context cancellation, any package may be missing.\n\t\t// We need all dependencies to produce a key.\n\t\treachable.Elems(func(id typerefs.IndexID) {\n\t\t\tdh := b.nodes[id]\n\t\t\tif dh == nil {\n\t\t\t\t// Previous code reported an error (not a bug) here.\n\t\t\t\tbug.Reportf(\"missing reachable node for %v\", id)\n\t\t\t} else {\n\t\t\t\treachableNodes = append(reachableNodes, dh)\n\t\t\t}\n\t\t})\n\n\t\t// Sort for stability.\n\t\tsort.Slice(reachableNodes, func(i, j int) bool {\n\t\t\treturn reachableNodes[i].mp.ID < reachableNodes[j].mp.ID\n\t\t})\n\n\t\t// Key is the hash of the local key of this package, and the local key of\n\t\t// all reachable packages.\n\t\tdepHasher := sha256.New()\n\t\tdepHasher.Write(ph.localKey[:])\n\t\treachablePaths := make([]string, len(reachableNodes))\n\t\tfor i, dh := range reachableNodes {\n\t\t\tdepHasher.Write(dh.ph.localKey[:])\n\t\t\treachablePaths[i] = string(dh.ph.mp.PkgPath)\n\t\t}\n\t\tdepHasher.Sum(ph.key[:0])\n\t\tph.reachable = bloom.NewFilter(reachablePaths)\n\t\tph.state = validKey\n\t\tkeyChanged = ph.key != prevKey\n\t}\n\n\tassert(ph.state == validKey, \"unexpected handle state\")\n\n\t// Validate ph.pkgData, upgrading state if the package or its imports are\n\t// still valid.\n\tif ph.pkgData != nil {\n\t\tpkgData := *ph.pkgData // make a copy\n\t\tph.pkgData = &pkgData\n\t\tph.state = validPackage\n\t\tif keyChanged || ph.pkgData.pkg == nil {\n\t\t\tph.pkgData.pkg = nil // ensure we don't hold on to stale packages\n\t\t\tph.state = validImports\n\t\t}\n\t\tif depsChanged {\n\t\t\tph.pkgData = nil\n\t\t\tph.state = validKey\n\t\t}\n\t}\n\n\t// Postcondition: state >= validKey\n\n\treturn nil\n}\n\n// typerefs returns typerefs for the package described by m and cgfs, after\n// either computing it or loading it from the file cache.\nfunc (s *Snapshot) typerefs(ctx context.Context, mp *metadata.Package, cgfs []file.Handle) (map[string][]typerefs.Symbol, error) {\n\timports := make(map[ImportPath]*metadata.Package)\n\tfor impPath, id := range mp.DepsByImpPath {\n\t\tif id != \"\" {\n\t\t\timports[impPath] = s.Metadata(id)\n\t\t}\n\t}\n\n\tdata, err := s.typerefData(ctx, mp.ID, imports, cgfs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tclasses := typerefs.Decode(s.view.pkgIndex, data)\n\trefs := make(map[string][]typerefs.Symbol)\n\tfor _, class := range classes {\n\t\tfor _, decl := range class.Decls {\n\t\t\trefs[decl] = class.Refs\n\t\t}\n\t}\n\treturn refs, nil\n}\n\n// typerefData retrieves encoded typeref data from the filecache, or computes it on\n// a cache miss.\nfunc (s *Snapshot) typerefData(ctx context.Context, id PackageID, imports map[ImportPath]*metadata.Package, cgfs []file.Handle) ([]byte, error) {\n\tkey := typerefsKey(id, imports, cgfs)\n\tif data, err := filecache.Get(typerefsKind, key); err == nil {\n\t\treturn data, nil\n\t} else if err != filecache.ErrNotFound {\n\t\tbug.Reportf(\"internal error reading typerefs data: %v\", err)\n\t\t// Unexpected error: treat as cache miss, and fall through.\n\t}\n\n\tpgfs, err := s.view.parseCache.parseFiles(ctx, token.NewFileSet(), parsego.Full&^parser.ParseComments, true, cgfs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdata := typerefs.Encode(pgfs, imports)\n\n\t// Store the resulting data in the cache.\n\tgo func() {\n\t\tif err := filecache.Set(typerefsKind, key, data); err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"storing typerefs data for %s\", id), err)\n\t\t}\n\t}()\n\n\treturn data, nil\n}\n\n// typerefsKey produces a key for the reference information produced by the\n// typerefs package.\nfunc typerefsKey(id PackageID, imports map[ImportPath]*metadata.Package, compiledGoFiles []file.Handle) file.Hash {\n\thasher := sha256.New()\n\n\tfmt.Fprintf(hasher, \"typerefs: %s\\n\", id)\n\n\tfor importPath, imp := range moremaps.Sorted(imports) {\n\t\t// TODO(rfindley): strength reduce the typerefs.Export API to guarantee\n\t\t// that it only depends on these attributes of dependencies.\n\t\tfmt.Fprintf(hasher, \"import %s %s %s\", importPath, imp.ID, imp.Name)\n\t}\n\n\tfmt.Fprintf(hasher, \"compiledGoFiles: %d\\n\", len(compiledGoFiles))\n\tfor _, fh := range compiledGoFiles {\n\t\tfmt.Fprintln(hasher, fh.Identity())\n\t}\n\n\tvar hash [sha256.Size]byte\n\thasher.Sum(hash[:0])\n\treturn hash\n}\n\n// typeCheckInputs contains the inputs of a call to typeCheckImpl, which\n// type-checks a package.\n//\n// Part of the purpose of this type is to keep type checking in-sync with the\n// package handle key, by explicitly identifying the inputs to type checking.\ntype typeCheckInputs struct {\n\tid PackageID\n\n\t// Used for type checking:\n\tpkgPath                  PackagePath\n\tname                     PackageName\n\tgoFiles, compiledGoFiles []file.Handle\n\tsizes                    types.Sizes\n\tdepsByImpPath            map[ImportPath]PackageID\n\tgoVersion                string // packages.Module.GoVersion, e.g. \"1.18\"\n\n\t// Used for type check diagnostics:\n\t// TODO(rfindley): consider storing less data in gobDiagnostics, and\n\t// interpreting each diagnostic in the context of a fixed set of options.\n\t// Then these fields need not be part of the type checking inputs.\n\tsupportsRelatedInformation bool\n\tlinkTarget                 string\n\tviewType                   ViewType\n}\n\nfunc (s *Snapshot) typeCheckInputs(ctx context.Context, mp *metadata.Package) (*typeCheckInputs, error) {\n\t// Read both lists of files of this package.\n\t//\n\t// Parallelism is not necessary here as the files will have already been\n\t// pre-read at load time.\n\t//\n\t// goFiles aren't presented to the type checker--nor\n\t// are they included in the key, unsoundly--but their\n\t// syntax trees are available from (*pkg).File(URI).\n\t// TODO(adonovan): consider parsing them on demand?\n\t// The need should be rare.\n\tgoFiles, err := readFiles(ctx, s, mp.GoFiles)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcompiledGoFiles, err := readFiles(ctx, s, mp.CompiledGoFiles)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tgoVersion := \"\"\n\tif mp.Module != nil && mp.Module.GoVersion != \"\" {\n\t\tgoVersion = mp.Module.GoVersion\n\t} else {\n\t\t// Fall back on the go version implied by the ambient Go command.\n\t\tgoVersion = fmt.Sprintf(\"1.%d\", s.View().GoVersion())\n\t}\n\n\treturn &typeCheckInputs{\n\t\tid:              mp.ID,\n\t\tpkgPath:         mp.PkgPath,\n\t\tname:            mp.Name,\n\t\tgoFiles:         goFiles,\n\t\tcompiledGoFiles: compiledGoFiles,\n\t\tsizes:           mp.TypesSizes,\n\t\tdepsByImpPath:   mp.DepsByImpPath,\n\t\tgoVersion:       goVersion,\n\n\t\tsupportsRelatedInformation: s.Options().RelatedInformationSupported,\n\t\tlinkTarget:                 s.Options().LinkTarget,\n\t\tviewType:                   s.view.typ,\n\t}, nil\n}\n\n// readFiles reads the content of each file URL from the source\n// (e.g. snapshot or cache).\nfunc readFiles(ctx context.Context, fs file.Source, uris []protocol.DocumentURI) (_ []file.Handle, err error) {\n\tfhs := make([]file.Handle, len(uris))\n\tfor i, uri := range uris {\n\t\tfhs[i], err = fs.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn fhs, nil\n}\n\n// localPackageKey returns a key for local inputs into type-checking, excluding\n// dependency information: files, metadata, and configuration.\nfunc localPackageKey(inputs *typeCheckInputs) file.Hash {\n\thasher := sha256.New()\n\n\t// In principle, a key must be the hash of an\n\t// unambiguous encoding of all the relevant data.\n\t// If it's ambiguous, we risk collisions.\n\n\t// package identifiers\n\tfmt.Fprintf(hasher, \"package: %s %s %s\\n\", inputs.id, inputs.name, inputs.pkgPath)\n\n\t// module Go version\n\tfmt.Fprintf(hasher, \"go %s\\n\", inputs.goVersion)\n\n\t// import map\n\tfor impPath, depID := range moremaps.Sorted(inputs.depsByImpPath) {\n\t\tfmt.Fprintf(hasher, \"import %s %s\", impPath, depID)\n\t}\n\n\t// file names and contents\n\tfmt.Fprintf(hasher, \"compiledGoFiles: %d\\n\", len(inputs.compiledGoFiles))\n\tfor _, fh := range inputs.compiledGoFiles {\n\t\tfmt.Fprintln(hasher, fh.Identity())\n\t}\n\tfmt.Fprintf(hasher, \"goFiles: %d\\n\", len(inputs.goFiles))\n\tfor _, fh := range inputs.goFiles {\n\t\tfmt.Fprintln(hasher, fh.Identity())\n\t}\n\n\t// types sizes\n\twordSize := inputs.sizes.Sizeof(types.Typ[types.Int])\n\tmaxAlign := inputs.sizes.Alignof(types.NewPointer(types.Typ[types.Int64]))\n\tfmt.Fprintf(hasher, \"sizes: %d %d\\n\", wordSize, maxAlign)\n\n\tfmt.Fprintf(hasher, \"relatedInformation: %t\\n\", inputs.supportsRelatedInformation)\n\tfmt.Fprintf(hasher, \"linkTarget: %s\\n\", inputs.linkTarget)\n\tfmt.Fprintf(hasher, \"viewType: %d\\n\", inputs.viewType)\n\n\tvar hash [sha256.Size]byte\n\thasher.Sum(hash[:0])\n\treturn hash\n}\n\n// checkPackage type checks the parsed source files in compiledGoFiles.\n// (The resulting pkg also holds the parsed but not type-checked goFiles.)\n// deps holds the future results of type-checking the direct dependencies.\nfunc (b *typeCheckBatch) checkPackage(ctx context.Context, fset *token.FileSet, ph *packageHandle, imports map[PackagePath]*types.Package) (*Package, error) {\n\tinputs := ph.localInputs\n\tctx, done := event.Start(ctx, \"cache.typeCheckBatch.checkPackage\", label.Package.Of(string(inputs.id)))\n\tdefer done()\n\n\tpkg := &syntaxPackage{\n\t\tid:         inputs.id,\n\t\tfset:       fset, // must match parse call below\n\t\ttypes:      types.NewPackage(string(inputs.pkgPath), string(inputs.name)),\n\t\ttypesSizes: inputs.sizes,\n\t\ttypesInfo: &types.Info{\n\t\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t},\n\t}\n\n\t// Collect parsed files from the type check pass, capturing parse errors from\n\t// compiled files.\n\tvar err error\n\tpkg.goFiles, err = b.parseCache.parseFiles(ctx, pkg.fset, parsego.Full, false, inputs.goFiles...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpkg.compiledGoFiles, err = b.parseCache.parseFiles(ctx, pkg.fset, parsego.Full, false, inputs.compiledGoFiles...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, pgf := range pkg.compiledGoFiles {\n\t\tif pgf.ParseErr != nil {\n\t\t\tpkg.parseErrors = append(pkg.parseErrors, pgf.ParseErr)\n\t\t}\n\t}\n\n\t// Use the default type information for the unsafe package.\n\tif inputs.pkgPath == \"unsafe\" {\n\t\t// Don't type check Unsafe: it's unnecessary, and doing so exposes a data\n\t\t// race to Unsafe.completed.\n\t\tpkg.types = types.Unsafe\n\t} else {\n\n\t\tif len(pkg.compiledGoFiles) == 0 {\n\t\t\t// No files most likely means go/packages failed.\n\t\t\t//\n\t\t\t// TODO(rfindley): in the past, we would capture go list errors in this\n\t\t\t// case, to present go list errors to the user. However we had no tests for\n\t\t\t// this behavior. It is unclear if anything better can be done here.\n\t\t\treturn nil, fmt.Errorf(\"no parsed files for package %s\", inputs.pkgPath)\n\t\t}\n\n\t\tonError := func(e error) {\n\t\t\tpkg.typeErrors = append(pkg.typeErrors, e.(types.Error))\n\t\t}\n\t\tcfg := b.typesConfig(ctx, inputs, imports, onError)\n\t\tcheck := types.NewChecker(cfg, pkg.fset, pkg.types, pkg.typesInfo)\n\n\t\tvar files []*ast.File\n\t\tfor _, cgf := range pkg.compiledGoFiles {\n\t\t\tfiles = append(files, cgf.File)\n\t\t}\n\n\t\t// Type checking is expensive, and we may not have encountered cancellations\n\t\t// via parsing (e.g. if we got nothing but cache hits for parsed files).\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\n\t\t// Type checking errors are handled via the config, so ignore them here.\n\t\t_ = check.Files(files) // 50us-15ms, depending on size of package\n\n\t\t// If the context was cancelled, we may have returned a ton of transient\n\t\t// errors to the type checker. Swallow them.\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\n\t\t// Collect imports by package path for the DependencyTypes API.\n\t\tpkg.importMap = make(map[PackagePath]*types.Package)\n\t\tvar collectDeps func(*types.Package)\n\t\tcollectDeps = func(p *types.Package) {\n\t\t\tpkgPath := PackagePath(p.Path())\n\t\t\tif _, ok := pkg.importMap[pkgPath]; ok {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpkg.importMap[pkgPath] = p\n\t\t\tfor _, imp := range p.Imports() {\n\t\t\t\tcollectDeps(imp)\n\t\t\t}\n\t\t}\n\t\tcollectDeps(pkg.types)\n\n\t\t// Work around golang/go#61561: interface instances aren't concurrency-safe\n\t\t// as they are not completed by the type checker.\n\t\tfor _, inst := range pkg.typesInfo.Instances {\n\t\t\tif iface, _ := inst.Type.Underlying().(*types.Interface); iface != nil {\n\t\t\t\tiface.Complete()\n\t\t\t}\n\t\t}\n\t}\n\n\t// Our heuristic for whether to show type checking errors is:\n\t//  + If there is a parse error _in the current file_, suppress type\n\t//    errors in that file.\n\t//  + Otherwise, show type errors even in the presence of parse errors in\n\t//    other package files. go/types attempts to suppress follow-on errors\n\t//    due to bad syntax, so on balance type checking errors still provide\n\t//    a decent signal/noise ratio as long as the file in question parses.\n\n\t// Track URIs with parse errors so that we can suppress type errors for these\n\t// files.\n\tunparsable := map[protocol.DocumentURI]bool{}\n\tfor _, e := range pkg.parseErrors {\n\t\tdiags, err := parseErrorDiagnostics(pkg, e)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"unable to compute positions for parse errors\", err, label.Package.Of(string(inputs.id)))\n\t\t\tcontinue\n\t\t}\n\t\tfor _, diag := range diags {\n\t\t\tunparsable[diag.URI] = true\n\t\t\tpkg.diagnostics = append(pkg.diagnostics, diag)\n\t\t}\n\t}\n\n\tdiags := typeErrorsToDiagnostics(pkg, inputs, pkg.typeErrors)\n\tfor _, diag := range diags {\n\t\t// If the file didn't parse cleanly, it is highly likely that type\n\t\t// checking errors will be confusing or redundant. But otherwise, type\n\t\t// checking usually provides a good enough signal to include.\n\t\tif !unparsable[diag.URI] {\n\t\t\tpkg.diagnostics = append(pkg.diagnostics, diag)\n\t\t}\n\t}\n\n\treturn &Package{ph.mp, ph.loadDiagnostics, pkg}, nil\n}\n\n// e.g. \"go1\" or \"go1.2\" or \"go1.2.3\"\nvar goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*(?:\\.(0|[1-9][0-9]*)){0,2}$`)\n\nfunc (b *typeCheckBatch) typesConfig(ctx context.Context, inputs *typeCheckInputs, imports map[PackagePath]*types.Package, onError func(e error)) *types.Config {\n\tcfg := &types.Config{\n\t\tSizes: inputs.sizes,\n\t\tError: onError,\n\t\tImporter: importerFunc(func(path string) (*types.Package, error) {\n\t\t\t// While all of the import errors could be reported\n\t\t\t// based on the metadata before we start type checking,\n\t\t\t// reporting them via types.Importer places the errors\n\t\t\t// at the correct source location.\n\t\t\tid, ok := inputs.depsByImpPath[ImportPath(path)]\n\t\t\tif !ok {\n\t\t\t\t// If the import declaration is broken,\n\t\t\t\t// go list may fail to report metadata about it.\n\t\t\t\t// See TestFixImportDecl for an example.\n\t\t\t\treturn nil, fmt.Errorf(\"missing metadata for import of %q\", path)\n\t\t\t}\n\t\t\tdepPH := b.getHandle(id)\n\t\t\tif depPH == nil {\n\t\t\t\t// e.g. missing metadata for dependencies in buildPackageHandle\n\t\t\t\treturn nil, missingPkgError(inputs.id, path, inputs.viewType)\n\t\t\t}\n\t\t\tif !metadata.IsValidImport(inputs.pkgPath, depPH.mp.PkgPath, inputs.viewType != GoPackagesDriverView) {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid use of internal package %q\", path)\n\t\t\t}\n\t\t\t// For syntax packages, the set of required imports is known and\n\t\t\t// precomputed. For import packages (checkPackageForImport), imports are\n\t\t\t// constructed lazily, because they may not have been needed if we could\n\t\t\t// have imported from export data.\n\t\t\t//\n\t\t\t// TODO(rfindley): refactor to move this logic to the callsite.\n\t\t\tif imports != nil {\n\t\t\t\timp, ok := imports[depPH.mp.PkgPath]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"missing import %s\", id)\n\t\t\t\t}\n\t\t\t\treturn imp, nil\n\t\t\t}\n\t\t\treturn b.getImportPackage(ctx, id)\n\t\t}),\n\t}\n\n\tif inputs.goVersion != \"\" {\n\t\tgoVersion := \"go\" + inputs.goVersion\n\t\tif validGoVersion(goVersion) {\n\t\t\tcfg.GoVersion = goVersion\n\t\t}\n\t}\n\n\t// We want to type check cgo code if go/types supports it.\n\t// We passed typecheckCgo to go/packages when we Loaded.\n\ttypesinternal.SetUsesCgo(cfg)\n\treturn cfg\n}\n\n// validGoVersion reports whether goVersion is a valid Go version for go/types.\n// types.NewChecker panics if GoVersion is invalid.\n//\n// Note that, prior to go1.21, go/types required exactly two components to the\n// version number. For example, go types would panic with the Go version\n// go1.21.1. validGoVersion handles this case when built with go1.20 or earlier.\nfunc validGoVersion(goVersion string) bool {\n\tif !goVersionRx.MatchString(goVersion) {\n\t\treturn false // malformed version string\n\t}\n\n\tif relVer := releaseVersion(); relVer != \"\" && versions.Before(versions.Lang(relVer), versions.Lang(goVersion)) {\n\t\treturn false // 'go list' is too new for go/types\n\t}\n\n\treturn true\n}\n\n// releaseVersion reports the Go language version used to compile gopls, or \"\"\n// if it cannot be determined.\nfunc releaseVersion() string {\n\tif len(build.Default.ReleaseTags) > 0 {\n\t\tv := build.Default.ReleaseTags[len(build.Default.ReleaseTags)-1]\n\t\tvar dummy int\n\t\tif _, err := fmt.Sscanf(v, \"go1.%d\", &dummy); err == nil {\n\t\t\treturn v\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// depsErrors creates diagnostics for each metadata error (e.g. import cycle).\n// These may be attached to import declarations in the transitive source files\n// of pkg, or to 'requires' declarations in the package's go.mod file.\n//\n// TODO(rfindley): move this to load.go\nfunc depsErrors(ctx context.Context, snapshot *Snapshot, mp *metadata.Package) ([]*Diagnostic, error) {\n\t// Select packages that can't be found, and were imported in non-workspace packages.\n\t// Workspace packages already show their own errors.\n\tvar relevantErrors []*packagesinternal.PackageError\n\tfor _, depsError := range mp.DepsErrors {\n\t\t// Up to Go 1.15, the missing package was included in the stack, which\n\t\t// was presumably a bug. We want the next one up.\n\t\tdirectImporterIdx := len(depsError.ImportStack) - 1\n\t\tif directImporterIdx < 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tdirectImporter := depsError.ImportStack[directImporterIdx]\n\t\tif snapshot.IsWorkspacePackage(PackageID(directImporter)) {\n\t\t\tcontinue\n\t\t}\n\t\trelevantErrors = append(relevantErrors, depsError)\n\t}\n\n\t// Don't build the import index for nothing.\n\tif len(relevantErrors) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t// Subsequent checks require Go files.\n\tif len(mp.CompiledGoFiles) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t// Build an index of all imports in the package.\n\ttype fileImport struct {\n\t\tcgf *parsego.File\n\t\timp *ast.ImportSpec\n\t}\n\tallImports := map[string][]fileImport{}\n\tfor _, uri := range mp.CompiledGoFiles {\n\t\tpgf, err := parseGoURI(ctx, snapshot, uri, parsego.Header)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\t// TODO(adonovan): modify Imports() to accept a single token.File (cgf.Tok).\n\t\tfor _, group := range astutil.Imports(fset, pgf.File) {\n\t\t\tfor _, imp := range group {\n\t\t\t\tif imp.Path == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tpath := strings.Trim(imp.Path.Value, `\"`)\n\t\t\t\tallImports[path] = append(allImports[path], fileImport{pgf, imp})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply a diagnostic to any import involved in the error, stopping once\n\t// we reach the workspace.\n\tvar errors []*Diagnostic\n\tfor _, depErr := range relevantErrors {\n\t\tfor i := len(depErr.ImportStack) - 1; i >= 0; i-- {\n\t\t\titem := depErr.ImportStack[i]\n\t\t\tif snapshot.IsWorkspacePackage(PackageID(item)) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tfor _, imp := range allImports[item] {\n\t\t\t\trng, err := imp.cgf.NodeRange(imp.imp)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tdiag := &Diagnostic{\n\t\t\t\t\tURI:            imp.cgf.URI,\n\t\t\t\t\tRange:          rng,\n\t\t\t\t\tSeverity:       protocol.SeverityError,\n\t\t\t\t\tSource:         TypeError,\n\t\t\t\t\tMessage:        fmt.Sprintf(\"error while importing %v: %v\", item, depErr.Err),\n\t\t\t\t\tSuggestedFixes: goGetQuickFixes(mp.Module != nil, imp.cgf.URI, item),\n\t\t\t\t}\n\t\t\t\tif !bundleLazyFixes(diag) {\n\t\t\t\t\tbug.Reportf(\"failed to bundle fixes for diagnostic %q\", diag.Message)\n\t\t\t\t}\n\t\t\t\terrors = append(errors, diag)\n\t\t\t}\n\t\t}\n\t}\n\n\tmodFile, err := findRootPattern(ctx, mp.CompiledGoFiles[0].Dir(), \"go.mod\", snapshot)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpm, err := parseModURI(ctx, snapshot, modFile)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Add a diagnostic to the module that contained the lowest-level import of\n\t// the missing package.\n\tfor _, depErr := range relevantErrors {\n\t\tfor i := len(depErr.ImportStack) - 1; i >= 0; i-- {\n\t\t\titem := depErr.ImportStack[i]\n\t\t\tmp := snapshot.Metadata(PackageID(item))\n\t\t\tif mp == nil || mp.Module == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmodVer := module.Version{Path: mp.Module.Path, Version: mp.Module.Version}\n\t\t\treference := findModuleReference(pm.File, modVer)\n\t\t\tif reference == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trng, err := pm.Mapper.OffsetRange(reference.Start.Byte, reference.End.Byte)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdiag := &Diagnostic{\n\t\t\t\tURI:            pm.URI,\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityError,\n\t\t\t\tSource:         TypeError,\n\t\t\t\tMessage:        fmt.Sprintf(\"error while importing %v: %v\", item, depErr.Err),\n\t\t\t\tSuggestedFixes: goGetQuickFixes(true, pm.URI, item),\n\t\t\t}\n\t\t\tif !bundleLazyFixes(diag) {\n\t\t\t\tbug.Reportf(\"failed to bundle fixes for diagnostic %q\", diag.Message)\n\t\t\t}\n\t\t\terrors = append(errors, diag)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn errors, nil\n}\n\n// missingPkgError returns an error message for a missing package that varies\n// based on the user's workspace mode.\nfunc missingPkgError(from PackageID, pkgPath string, viewType ViewType) error {\n\tswitch viewType {\n\tcase GoModView, GoWorkView:\n\t\tif metadata.IsCommandLineArguments(from) {\n\t\t\treturn fmt.Errorf(\"current file is not included in a workspace module\")\n\t\t} else {\n\t\t\t// Previously, we would present the initialization error here.\n\t\t\treturn fmt.Errorf(\"no required module provides package %q\", pkgPath)\n\t\t}\n\tcase AdHocView:\n\t\treturn fmt.Errorf(\"cannot find package %q in GOROOT\", pkgPath)\n\tcase GoPackagesDriverView:\n\t\treturn fmt.Errorf(\"go/packages driver could not load %q\", pkgPath)\n\tcase GOPATHView:\n\t\treturn fmt.Errorf(\"cannot find package %q in GOROOT or GOPATH\", pkgPath)\n\tdefault:\n\t\treturn fmt.Errorf(\"unable to load package\")\n\t}\n}\n\n// typeErrorsToDiagnostics translates a slice of types.Errors into a slice of\n// Diagnostics.\n//\n// In addition to simply mapping data such as position information and error\n// codes, this function interprets related go/types \"continuation\" errors as\n// protocol.DiagnosticRelatedInformation. Continuation errors are go/types\n// errors whose messages starts with \"\\t\". By convention, these errors relate\n// to the previous error in the errs slice (such as if they were printed in\n// sequence to a terminal).\n//\n// Fields in typeCheckInputs may affect the resulting diagnostics.\nfunc typeErrorsToDiagnostics(pkg *syntaxPackage, inputs *typeCheckInputs, errs []types.Error) []*Diagnostic {\n\tvar result []*Diagnostic\n\n\t// batch records diagnostics for a set of related types.Errors.\n\t// (related[0] is the primary error.)\n\tbatch := func(related []types.Error) {\n\t\tvar diags []*Diagnostic\n\t\tfor i, e := range related {\n\t\t\tcode, start, end, ok := typesinternal.ErrorCodeStartEnd(e)\n\t\t\tif !ok || !start.IsValid() || !end.IsValid() {\n\t\t\t\tstart, end = e.Pos, e.Pos\n\t\t\t\tcode = 0\n\t\t\t}\n\t\t\tif !start.IsValid() {\n\t\t\t\t// Type checker errors may be missing position information if they\n\t\t\t\t// relate to synthetic syntax, such as if the file were fixed. In that\n\t\t\t\t// case, we should have a parse error anyway, so skipping the type\n\t\t\t\t// checker error is likely benign.\n\t\t\t\t//\n\t\t\t\t// TODO(golang/go#64335): we should eventually verify that all type\n\t\t\t\t// checked syntax has valid positions, and promote this skip to a bug\n\t\t\t\t// report.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Invariant: both start and end are IsValid.\n\t\t\tif !end.IsValid() {\n\t\t\t\tpanic(\"end is invalid\")\n\t\t\t}\n\n\t\t\tposn := safetoken.StartPosition(e.Fset, start)\n\t\t\tif !posn.IsValid() {\n\t\t\t\t// All valid positions produced by the type checker should described by\n\t\t\t\t// its fileset, yet since type checker errors are associated with\n\t\t\t\t// positions in the AST, and AST nodes can overflow the file\n\t\t\t\t// (golang/go#48300), we can't rely on this.\n\t\t\t\t//\n\t\t\t\t// We should fix the parser, but in the meantime type errors are not\n\t\t\t\t// significant if there are parse errors, so we can safely ignore this\n\t\t\t\t// case.\n\t\t\t\tif len(pkg.parseErrors) == 0 {\n\t\t\t\t\tbug.Reportf(\"internal error: type checker error %q outside its Fset\", e)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpgf, err := pkg.File(protocol.URIFromPath(posn.Filename))\n\t\t\tif err != nil {\n\t\t\t\t// Sometimes type-checker errors refer to positions in other packages,\n\t\t\t\t// such as when a declaration duplicates a dot-imported name.\n\t\t\t\t//\n\t\t\t\t// In these cases, we don't want to report an error in the other\n\t\t\t\t// package (the message would be rather confusing), but we do want to\n\t\t\t\t// report an error in the current package (golang/go#59005).\n\t\t\t\tif i == 0 {\n\t\t\t\t\tif pkg.hasFixedFiles() {\n\t\t\t\t\t\tbug.Reportf(\"internal error: could not locate file for primary type checker error %v: %v (fixed files)\", e, err)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbug.Reportf(\"internal error: could not locate file for primary type checker error %v: %v\", e, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// debugging golang/go#65960\n\t\t\t//\n\t\t\t// At this point, we know 'start' IsValid, and\n\t\t\t// StartPosition(start) worked (with e.Fset).\n\t\t\t//\n\t\t\t// If the asserted condition is true, 'start'\n\t\t\t// is also in range for pgf.Tok, which means\n\t\t\t// the PosRange failure must be caused by 'end'.\n\t\t\tif pgf.Tok != e.Fset.File(start) {\n\t\t\t\tif pkg.hasFixedFiles() {\n\t\t\t\t\tbug.Reportf(\"internal error: inconsistent token.Files for pos (fixed files)\")\n\t\t\t\t} else {\n\t\t\t\t\tbug.Reportf(\"internal error: inconsistent token.Files for pos\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif end == start {\n\t\t\t\t// Expand the end position to a more meaningful span.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): It is the type checker's responsibility\n\t\t\t\t// to ensure that (start, end) are meaningful; see #71803.\n\t\t\t\tend = typeErrorEndPos(pgf.Tok, pgf.Src, start)\n\n\t\t\t\t// debugging golang/go#65960\n\t\t\t\tif _, err := safetoken.Offset(pgf.Tok, end); err != nil {\n\t\t\t\t\tif pkg.hasFixedFiles() {\n\t\t\t\t\t\tbug.Reportf(\"TypeErrorEndPos returned invalid end: %v (fixed files)\", err)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbug.Reportf(\"TypeErrorEndPos returned invalid end: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// TODO(adonovan): check File(start)==File(end).\n\n\t\t\t\t// debugging golang/go#65960\n\t\t\t\tif _, err := safetoken.Offset(pgf.Tok, end); err != nil {\n\t\t\t\t\tif pkg.hasFixedFiles() {\n\t\t\t\t\t\tbug.Reportf(\"ErrorCodeStartEnd returned invalid end: %v (fixed files)\", err)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbug.Reportf(\"ErrorCodeStartEnd returned invalid end: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trng, err := pgf.Mapper.PosRange(pgf.Tok, start, end)\n\t\t\tif err != nil {\n\t\t\t\tbug.Reportf(\"internal error: could not compute pos to range for %v: %v\", e, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmsg := related[0].Msg // primary\n\t\t\tif i > 0 {\n\t\t\t\tif inputs.supportsRelatedInformation {\n\t\t\t\t\tmsg += \" (see details)\"\n\t\t\t\t} else {\n\t\t\t\t\tmsg += fmt.Sprintf(\" (this error: %v)\", e.Msg)\n\t\t\t\t}\n\t\t\t}\n\t\t\tdiag := &Diagnostic{\n\t\t\t\tURI:      pgf.URI,\n\t\t\t\tRange:    rng,\n\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\tSource:   TypeError,\n\t\t\t\tMessage:  msg,\n\t\t\t}\n\t\t\tif code != 0 {\n\t\t\t\tdiag.Code = code.String()\n\t\t\t\tdiag.CodeHref = typesCodeHref(inputs.linkTarget, code)\n\t\t\t}\n\t\t\tif code == typesinternal.UnusedVar || code == typesinternal.UnusedImport {\n\t\t\t\tdiag.Tags = append(diag.Tags, protocol.Unnecessary)\n\t\t\t}\n\t\t\tif match := importErrorRe.FindStringSubmatch(e.Msg); match != nil {\n\t\t\t\tdiag.SuggestedFixes = append(diag.SuggestedFixes, goGetQuickFixes(inputs.viewType.usesModules(), pgf.URI, match[1])...)\n\t\t\t}\n\t\t\tif match := unsupportedFeatureRe.FindStringSubmatch(e.Msg); match != nil {\n\t\t\t\tdiag.SuggestedFixes = append(diag.SuggestedFixes, editGoDirectiveQuickFix(inputs.viewType.usesModules(), pgf.URI, match[1])...)\n\t\t\t}\n\n\t\t\t// Link up related information. For the primary error, all related errors\n\t\t\t// are treated as related information. For secondary errors, only the\n\t\t\t// primary is related.\n\t\t\t//\n\t\t\t// This is because go/types assumes that errors are read top-down, such as\n\t\t\t// in the cycle error \"A refers to...\". The structure of the secondary\n\t\t\t// error set likely only makes sense for the primary error.\n\t\t\t//\n\t\t\t// NOTE: len(diags) == 0 if the primary diagnostic has invalid positions.\n\t\t\t// See also golang/go#66731.\n\t\t\tif i > 0 && len(diags) > 0 {\n\t\t\t\tprimary := diags[0]\n\t\t\t\tprimary.Related = append(primary.Related, protocol.DiagnosticRelatedInformation{\n\t\t\t\t\tLocation: diag.URI.Location(diag.Range),\n\t\t\t\t\tMessage:  related[i].Msg, // use the unmodified secondary error for related errors.\n\t\t\t\t})\n\t\t\t\tdiag.Related = []protocol.DiagnosticRelatedInformation{{\n\t\t\t\t\tLocation: primary.URI.Location(primary.Range),\n\t\t\t\t}}\n\t\t\t}\n\t\t\tdiags = append(diags, diag)\n\t\t}\n\t\tresult = append(result, diags...)\n\t}\n\n\t// Process batches of related errors.\n\tfor len(errs) > 0 {\n\t\trelated := []types.Error{errs[0]}\n\t\tfor i := 1; i < len(errs); i++ {\n\t\t\tspl := errs[i]\n\t\t\tif len(spl.Msg) == 0 || spl.Msg[0] != '\\t' {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tspl.Msg = spl.Msg[len(\"\\t\"):]\n\t\t\trelated = append(related, spl)\n\t\t}\n\t\tbatch(related)\n\t\terrs = errs[len(related):]\n\t}\n\n\treturn result\n}\n\n// This heuristic is ill-defined.\nfunc typeErrorEndPos(tokFile *token.File, src []byte, start token.Pos) token.Pos {\n\t// Get the end position for the type error.\n\toffset, err := safetoken.Offset(tokFile, start)\n\tif err != nil || offset > len(src) {\n\t\treturn start\n\t}\n\tsrc = src[offset:]\n\n\t// Attempt to find a reasonable end position for the type error.\n\t//\n\t// TODO(rfindley): the heuristic implemented here is unclear. It looks like\n\t// it seeks the end of the primary operand starting at start, but that is not\n\t// quite implemented (for example, given a func literal this heuristic will\n\t// return the range of the func keyword).\n\t//\n\t// We should formalize this heuristic, or deprecate it by finally proposing\n\t// to add end position to all type checker errors.\n\t//\n\t// Nevertheless, ensure that the end position at least spans the current\n\t// token at the cursor (this was golang/go#69505).\n\tend := start\n\t{\n\t\tvar s scanner.Scanner\n\t\tfset := token.NewFileSet()\n\t\tf := fset.AddFile(\"\", fset.Base(), len(src))\n\t\ts.Init(f, src, nil /* no error handler */, scanner.ScanComments)\n\t\tpos, tok, lit := s.Scan()\n\t\tif tok != token.SEMICOLON {\n\t\t\tif off, err := safetoken.Offset(f, pos); err == nil {\n\t\t\t\toff += len(lit)\n\t\t\t\tsrc = src[off:]\n\t\t\t\tend += token.Pos(off)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Look for bytes that might terminate the current operand. See note above:\n\t// this is imprecise.\n\tif width := bytes.IndexAny(src, \" \\n,():;[]+-*/\"); width > 0 {\n\t\tend += token.Pos(width)\n\t}\n\treturn end\n}\n\n// An importFunc is an implementation of the single-method\n// types.Importer interface based on a function value.\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n"
  },
  {
    "path": "gopls/internal/cache/constraints.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"go/ast\"\n\t\"go/build/constraint\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"slices\"\n)\n\n// isStandaloneFile reports whether a file with the given contents should be\n// considered a 'standalone main file', meaning a package that consists of only\n// a single file.\nfunc isStandaloneFile(src []byte, standaloneTags []string) bool {\n\tf, err := parser.ParseFile(token.NewFileSet(), \"\", src, parser.PackageClauseOnly|parser.ParseComments)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tif f.Name == nil || f.Name.Name != \"main\" {\n\t\treturn false\n\t}\n\n\tfound := false\n\twalkConstraints(f, func(c constraint.Expr) bool {\n\t\tif tag, ok := c.(*constraint.TagExpr); ok {\n\t\t\tif slices.Contains(standaloneTags, tag.Tag) {\n\t\t\t\tfound = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\treturn found\n}\n\n// walkConstraints calls f for each constraint expression in the file, until\n// all constraints are exhausted or f returns false.\nfunc walkConstraints(file *ast.File, f func(constraint.Expr) bool) {\n\tfor _, cg := range file.Comments {\n\t\t// Even with PackageClauseOnly the parser consumes the semicolon following\n\t\t// the package clause, so we must guard against comments that come after\n\t\t// the package name.\n\t\tif cg.Pos() > file.Name.Pos() {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, comment := range cg.List {\n\t\t\tif c, err := constraint.Parse(comment.Text); err == nil {\n\t\t\t\tif !f(c) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/constraints_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"testing\"\n)\n\nfunc TestIsStandaloneFile(t *testing.T) {\n\ttests := []struct {\n\t\tdesc           string\n\t\tcontents       string\n\t\tstandaloneTags []string\n\t\twant           bool\n\t}{\n\t\t{\n\t\t\t\"new syntax\",\n\t\t\t\"//go:build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"legacy syntax\",\n\t\t\t\"// +build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"multiple tags\",\n\t\t\t\"//go:build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"exclude\", \"ignore\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"invalid tag\",\n\t\t\t\"// +build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"script\"},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"non-main package\",\n\t\t\t\"//go:build ignore\\n\\npackage p\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"alternate tag\",\n\t\t\t\"// +build script\\n\\npackage main\\n\",\n\t\t\t[]string{\"script\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"both syntax\",\n\t\t\t\"//go:build ignore\\n// +build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"after comments\",\n\t\t\t\"// A non-directive comment\\n//go:build ignore\\n\\npackage main\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"after package decl\",\n\t\t\t\"package main //go:build ignore\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"on line after package decl\",\n\t\t\t\"package main\\n\\n//go:build ignore\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"combined with other expressions\",\n\t\t\t\"\\n\\n//go:build ignore || darwin\\n\\npackage main\\n\",\n\t\t\t[]string{\"ignore\"},\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tif got := isStandaloneFile([]byte(test.contents), test.standaloneTags); got != test.want {\n\t\t\t\tt.Errorf(\"isStandaloneFile(%q, %v) = %t, want %t\", test.contents, test.standaloneTags, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestVersionRegexp(t *testing.T) {\n\t// good\n\tfor _, s := range []string{\n\t\t\"go1\",\n\t\t\"go1.2\",\n\t\t\"go1.2.3\",\n\t\t\"go1.0.33\",\n\t} {\n\t\tif !goVersionRx.MatchString(s) {\n\t\t\tt.Errorf(\"Valid Go version %q does not match the regexp\", s)\n\t\t}\n\t}\n\n\t// bad\n\tfor _, s := range []string{\n\t\t\"go\",          // missing numbers\n\t\t\"go0\",         // Go starts at 1\n\t\t\"go01\",        // leading zero\n\t\t\"go1.π\",       // non-decimal\n\t\t\"go1.-1\",      // negative\n\t\t\"go1.02.3\",    // leading zero\n\t\t\"go1.2.3.4\",   // too many segments\n\t\t\"go1.2.3-pre\", // textual suffix\n\t} {\n\t\tif goVersionRx.MatchString(s) {\n\t\t\tt.Errorf(\"Invalid Go version %q unexpectedly matches the regexp\", s)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/debug.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\n// assert panics with the given msg if cond is not true.\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/diagnostics.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\n// A InitializationError is an error that causes snapshot initialization to fail.\n// It is either the error returned from go/packages.Load, or an error parsing a\n// workspace go.work or go.mod file.\n//\n// Such an error generally indicates that the View is malformed, and will never\n// be usable.\ntype InitializationError struct {\n\t// MainError is the primary error. Must be non-nil.\n\tMainError error\n\n\t// Diagnostics contains any supplemental (structured) diagnostics extracted\n\t// from the load error.\n\tDiagnostics map[protocol.DocumentURI][]*Diagnostic\n}\n\nfunc byURI(d *Diagnostic) protocol.DocumentURI { return d.URI } // For use in maps.Group.\n\n// A Diagnostic corresponds to an LSP Diagnostic.\n// https://microsoft.github.io/language-server-protocol/specification#diagnostic\n//\n// It is (effectively) gob-serializable; see {encode,decode}Diagnostics.\ntype Diagnostic struct {\n\tURI      protocol.DocumentURI // of diagnosed file (not diagnostic documentation)\n\tRange    protocol.Range\n\tSeverity protocol.DiagnosticSeverity\n\tCode     string // analysis.Diagnostic.Category (or \"default\" if empty) or hidden go/types error code\n\tCodeHref string\n\n\t// Source is a human-readable description of the source of the error.\n\t// Diagnostics generated by an analysis.Analyzer set it to Analyzer.Name.\n\tSource DiagnosticSource\n\n\tMessage string\n\n\tTags    []protocol.DiagnosticTag\n\tRelated []protocol.DiagnosticRelatedInformation\n\n\t// Fields below are used internally to generate lazy fixes. They aren't\n\t// part of the LSP spec and historically didn't leave the server.\n\t//\n\t// Update(2023-05): version 3.16 of the LSP spec included support for the\n\t// Diagnostic.data field, which holds arbitrary data preserved in the\n\t// diagnostic for codeAction requests. This field allows bundling additional\n\t// information for lazy fixes, and gopls can (and should) use this\n\t// information to avoid re-evaluating diagnostics in code-action handlers.\n\t//\n\t// In order to stage this transition incrementally, the 'BundledFixes' field\n\t// may store a 'bundled' (=json-serialized) form of the associated\n\t// SuggestedFixes. Not all diagnostics have their fixes bundled.\n\tBundledFixes   *json.RawMessage\n\tSuggestedFixes []SuggestedFix\n}\n\nfunc (d *Diagnostic) String() string {\n\treturn fmt.Sprintf(\"%v: %s\", d.Range, d.Message)\n}\n\n// Hash computes a hash to identify the diagnostic.\n// The hash is for deduplicating within a file, so does not incorporate d.URI.\nfunc (d *Diagnostic) Hash() file.Hash {\n\th := sha256.New()\n\tfor _, t := range d.Tags {\n\t\tfmt.Fprintf(h, \"tag: %s\\n\", t)\n\t}\n\tfor _, r := range d.Related {\n\t\tfmt.Fprintf(h, \"related: %s %s %s\\n\", r.Location.URI, r.Message, r.Location.Range)\n\t}\n\tfmt.Fprintf(h, \"code: %s\\n\", d.Code)\n\tfmt.Fprintf(h, \"codeHref: %s\\n\", d.CodeHref)\n\tfmt.Fprintf(h, \"message: %s\\n\", d.Message)\n\tfmt.Fprintf(h, \"range: %s\\n\", d.Range)\n\tfmt.Fprintf(h, \"severity: %s\\n\", d.Severity)\n\tfmt.Fprintf(h, \"source: %s\\n\", d.Source)\n\tif d.BundledFixes != nil {\n\t\tfmt.Fprintf(h, \"fixes: %s\\n\", *d.BundledFixes)\n\t}\n\tvar hash [sha256.Size]byte\n\th.Sum(hash[:0])\n\treturn hash\n}\n\nfunc ToProtocolDiagnostics(diagnostics ...*Diagnostic) []protocol.Diagnostic {\n\t// TODO(rfindley): support bundling edits, and bundle all suggested fixes here.\n\t// (see cache.bundleLazyFixes).\n\n\treports := []protocol.Diagnostic{}\n\tfor _, diag := range diagnostics {\n\t\tpdiag := protocol.Diagnostic{\n\t\t\t// diag.Message might start with \\n or \\t\n\t\t\tMessage:            strings.TrimSpace(diag.Message),\n\t\t\tRange:              diag.Range,\n\t\t\tSeverity:           diag.Severity,\n\t\t\tSource:             string(diag.Source),\n\t\t\tTags:               protocol.NonNilSlice(diag.Tags),\n\t\t\tRelatedInformation: diag.Related,\n\t\t\tData:               diag.BundledFixes,\n\t\t}\n\t\tif diag.Code != \"\" {\n\t\t\tpdiag.Code = diag.Code\n\t\t}\n\t\tif diag.CodeHref != \"\" {\n\t\t\tpdiag.CodeDescription = &protocol.CodeDescription{Href: diag.CodeHref}\n\t\t}\n\t\treports = append(reports, pdiag)\n\t}\n\treturn reports\n}\n\n// A DiagnosticSource identifies the source of a diagnostic.\n//\n// Its value may be one of the distinguished string values below, or\n// the Name of an [analysis.Analyzer].\ntype DiagnosticSource string\n\nconst (\n\tUnknownError           DiagnosticSource = \"<Unknown source>\"\n\tListError              DiagnosticSource = \"go list\"\n\tParseError             DiagnosticSource = \"syntax\"\n\tTypeError              DiagnosticSource = \"compiler\"\n\tModTidyError           DiagnosticSource = \"go mod tidy\"\n\tCompilerOptDetailsInfo DiagnosticSource = \"optimizer details\" // cmd/compile -json=0,dir\n\tUpgradeNotification    DiagnosticSource = \"upgrade available\"\n\tVulncheck              DiagnosticSource = \"vulncheck imports\"\n\tGovulncheck            DiagnosticSource = \"govulncheck\"\n\tTemplateError          DiagnosticSource = \"template\"\n\tWorkFileError          DiagnosticSource = \"go.work file\"\n)\n\n// A SuggestedFix represents a suggested fix (for a diagnostic)\n// produced by analysis, in protocol form.\n//\n// The fixes are reported to the client as a set of code actions in\n// response to a CodeAction query for a set of diagnostics. Multiple\n// SuggestedFixes may be produced for the same logical fix, varying\n// only in ActionKind. For example, a fix may be both a Refactor\n// (which should appear on the refactoring menu) and a SourceFixAll (a\n// clear fix that can be safely applied without explicit consent).\ntype SuggestedFix struct {\n\tTitle      string\n\tEdits      map[protocol.DocumentURI][]protocol.TextEdit\n\tCommand    *protocol.Command\n\tActionKind protocol.CodeActionKind\n}\n\n// SuggestedFixFromCommand returns a suggested fix to run the given command.\nfunc SuggestedFixFromCommand(cmd *protocol.Command, kind protocol.CodeActionKind) SuggestedFix {\n\treturn SuggestedFix{\n\t\tTitle:      cmd.Title,\n\t\tCommand:    cmd,\n\t\tActionKind: kind,\n\t}\n}\n\n// lazyFixesJSON is a JSON-serializable list of code actions (arising\n// from \"lazy\" SuggestedFixes with no Edits) to be saved in the\n// protocol.Diagnostic.Data field. Computation of the edits is thus\n// deferred until the action's command is invoked.\ntype lazyFixesJSON struct {\n\t// TODO(rfindley): pack some sort of identifier here for later\n\t// lookup/validation?\n\tActions []protocol.CodeAction\n}\n\n// bundleLazyFixes attempts to bundle sd.SuggestedFixes into the\n// sd.BundledFixes field, so that it can be round-tripped through the client.\n// It returns false if the fixes cannot be bundled.\nfunc bundleLazyFixes(sd *Diagnostic) bool {\n\tif len(sd.SuggestedFixes) == 0 {\n\t\treturn true\n\t}\n\tvar actions []protocol.CodeAction\n\tfor _, fix := range sd.SuggestedFixes {\n\t\tif fix.Edits != nil {\n\t\t\t// For now, we only support bundled code actions that execute commands.\n\t\t\t//\n\t\t\t// In order to cleanly support bundled edits, we'd have to guarantee that\n\t\t\t// the edits were generated on the current snapshot. But this naively\n\t\t\t// implies that every fix would have to include a snapshot ID, which\n\t\t\t// would require us to republish all diagnostics on each new snapshot.\n\t\t\t//\n\t\t\t// TODO(rfindley): in order to avoid this additional chatter, we'd need\n\t\t\t// to build some sort of registry or other mechanism on the snapshot to\n\t\t\t// check whether a diagnostic is still valid.\n\t\t\treturn false\n\t\t}\n\t\taction := protocol.CodeAction{\n\t\t\tTitle:   fix.Title,\n\t\t\tKind:    fix.ActionKind,\n\t\t\tCommand: fix.Command,\n\t\t}\n\t\tactions = append(actions, action)\n\t}\n\tfixes := lazyFixesJSON{\n\t\tActions: actions,\n\t}\n\tdata, err := json.Marshal(fixes)\n\tif err != nil {\n\t\tbug.Reportf(\"marshalling lazy fixes: %v\", err)\n\t\treturn false\n\t}\n\tmsg := json.RawMessage(data)\n\tsd.BundledFixes = &msg\n\treturn true\n}\n\n// BundledLazyFixes extracts any bundled codeActions from the\n// diag.Data field.\nfunc BundledLazyFixes(diag protocol.Diagnostic) ([]protocol.CodeAction, error) {\n\tvar fix lazyFixesJSON\n\tif diag.Data != nil {\n\t\terr := protocol.UnmarshalJSON(*diag.Data, &fix)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unmarshalling fix from diagnostic data: %v\", err)\n\t\t}\n\t}\n\n\tvar actions []protocol.CodeAction\n\tfor _, action := range fix.Actions {\n\t\t// See bundleLazyFixes: for now we only support bundling commands.\n\t\tif action.Edit != nil {\n\t\t\treturn nil, fmt.Errorf(\"bundled fix %q includes workspace edits\", action.Title)\n\t\t}\n\t\t// associate the action with the incoming diagnostic\n\t\t// (Note that this does not mutate the fix.Fixes slice).\n\t\taction.Diagnostics = []protocol.Diagnostic{diag}\n\t\tactions = append(actions, action)\n\t}\n\n\treturn actions, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/errors.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\n// This file defines routines to convert diagnostics from go list, go\n// get, go/packages, parsing, type checking, and analysis into\n// golang.Diagnostic form, and suggesting quick fixes.\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// goPackagesErrorDiagnostics translates the given go/packages Error into a\n// diagnostic, using the provided metadata and filesource.\n//\n// The slice of diagnostics may be empty.\nfunc goPackagesErrorDiagnostics(ctx context.Context, e packages.Error, mp *metadata.Package, fs file.Source) ([]*Diagnostic, error) {\n\tif diag, err := parseGoListImportCycleError(ctx, e, mp, fs); err != nil {\n\t\treturn nil, err\n\t} else if diag != nil {\n\t\treturn []*Diagnostic{diag}, nil\n\t}\n\n\t// Parse error location and attempt to convert to protocol form.\n\tloc, err := func() (protocol.Location, error) {\n\t\tfilename, line, col8 := parseGoListError(e, mp.LoadDir)\n\t\turi := protocol.URIFromPath(filename)\n\n\t\tfh, err := fs.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn protocol.Location{}, err\n\t\t}\n\t\tcontent, err := fh.Content()\n\t\tif err != nil {\n\t\t\treturn protocol.Location{}, err\n\t\t}\n\t\tmapper := protocol.NewMapper(uri, content)\n\t\tposn, err := mapper.LineCol8Position(line, col8)\n\t\tif err != nil {\n\t\t\treturn protocol.Location{}, err\n\t\t}\n\t\treturn protocol.Location{\n\t\t\tURI: uri,\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: posn,\n\t\t\t\tEnd:   posn,\n\t\t\t},\n\t\t}, nil\n\t}()\n\n\t// TODO(rfindley): in some cases the go command outputs invalid spans, for\n\t// example (from TestGoListErrors):\n\t//\n\t//   package a\n\t//   import\n\t//\n\t// In this case, the go command will complain about a.go:2:8, which is after\n\t// the trailing newline but still considered to be on the second line, most\n\t// likely because *token.File lacks information about newline termination.\n\t//\n\t// We could do better here by handling that case.\n\tif err != nil {\n\t\t// Unable to parse a valid position.\n\t\t// Apply the error to all files to be safe.\n\t\tvar diags []*Diagnostic\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\tdiags = append(diags, &Diagnostic{\n\t\t\t\tURI:      uri,\n\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\tSource:   ListError,\n\t\t\t\tMessage:  e.Msg,\n\t\t\t})\n\t\t}\n\t\treturn diags, nil\n\t}\n\treturn []*Diagnostic{{\n\t\tURI:      loc.URI,\n\t\tRange:    loc.Range,\n\t\tSeverity: protocol.SeverityError,\n\t\tSource:   ListError,\n\t\tMessage:  e.Msg,\n\t}}, nil\n}\n\nfunc parseErrorDiagnostics(pkg *syntaxPackage, errList scanner.ErrorList) ([]*Diagnostic, error) {\n\t// The first parser error is likely the root cause of the problem.\n\tif errList.Len() <= 0 {\n\t\treturn nil, fmt.Errorf(\"no errors in %v\", errList)\n\t}\n\te := errList[0]\n\tpgf, err := pkg.File(protocol.URIFromPath(e.Pos.Filename))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\trng, err := pgf.Mapper.OffsetRange(e.Pos.Offset, e.Pos.Offset)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn []*Diagnostic{{\n\t\tURI:      pgf.URI,\n\t\tRange:    rng,\n\t\tSeverity: protocol.SeverityError,\n\t\tSource:   ParseError,\n\t\tMessage:  e.Msg,\n\t}}, nil\n}\n\nvar importErrorRe = regexp.MustCompile(`could not import ([^\\s]+)`)\nvar unsupportedFeatureRe = regexp.MustCompile(`.*require.* go(\\d+\\.\\d+) or later`)\n\nfunc goGetQuickFixes(haveModule bool, uri protocol.DocumentURI, pkg string) []SuggestedFix {\n\t// Go get only supports module mode for now.\n\tif !haveModule {\n\t\treturn nil\n\t}\n\ttitle := fmt.Sprintf(\"go get package %v\", pkg)\n\tcmd := command.NewGoGetPackageCommand(title, command.GoGetPackageArgs{\n\t\tURI:        uri,\n\t\tAddRequire: true,\n\t\tPkg:        pkg,\n\t})\n\treturn []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)}\n}\n\nfunc editGoDirectiveQuickFix(haveModule bool, uri protocol.DocumentURI, version string) []SuggestedFix {\n\t// Go mod edit only supports module mode.\n\tif !haveModule {\n\t\treturn nil\n\t}\n\ttitle := fmt.Sprintf(\"go mod edit -go=%s\", version)\n\tcmd := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{\n\t\tURI:     uri,\n\t\tVersion: version,\n\t})\n\treturn []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)}\n}\n\n// encodeDiagnostics gob-encodes the given diagnostics.\nfunc encodeDiagnostics(srcDiags []*Diagnostic) []byte {\n\tvar gobDiags []gobDiagnostic\n\tfor _, srcDiag := range srcDiags {\n\t\tvar gobFixes []gobSuggestedFix\n\t\tfor _, srcFix := range srcDiag.SuggestedFixes {\n\t\t\tgobFix := gobSuggestedFix{\n\t\t\t\tMessage:    srcFix.Title,\n\t\t\t\tActionKind: srcFix.ActionKind,\n\t\t\t}\n\t\t\tfor uri, srcEdits := range srcFix.Edits {\n\t\t\t\tfor _, srcEdit := range srcEdits {\n\t\t\t\t\tgobFix.TextEdits = append(gobFix.TextEdits, gobTextEdit{\n\t\t\t\t\t\tLocation: uri.Location(srcEdit.Range),\n\t\t\t\t\t\tNewText:  []byte(srcEdit.NewText),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif srcCmd := srcFix.Command; srcCmd != nil {\n\t\t\t\tgobFix.Command = &gobCommand{\n\t\t\t\t\tTitle:     srcCmd.Title,\n\t\t\t\t\tCommand:   srcCmd.Command,\n\t\t\t\t\tArguments: srcCmd.Arguments,\n\t\t\t\t}\n\t\t\t}\n\t\t\tgobFixes = append(gobFixes, gobFix)\n\t\t}\n\t\tvar gobRelated []gobRelatedInformation\n\t\tfor _, srcRel := range srcDiag.Related {\n\t\t\tgobRel := gobRelatedInformation(srcRel)\n\t\t\tgobRelated = append(gobRelated, gobRel)\n\t\t}\n\t\tgobDiag := gobDiagnostic{\n\t\t\tLocation:       srcDiag.URI.Location(srcDiag.Range),\n\t\t\tSeverity:       srcDiag.Severity,\n\t\t\tCode:           srcDiag.Code,\n\t\t\tCodeHref:       srcDiag.CodeHref,\n\t\t\tSource:         string(srcDiag.Source),\n\t\t\tMessage:        srcDiag.Message,\n\t\t\tSuggestedFixes: gobFixes,\n\t\t\tRelated:        gobRelated,\n\t\t\tTags:           srcDiag.Tags,\n\t\t}\n\t\tgobDiags = append(gobDiags, gobDiag)\n\t}\n\treturn diagnosticsCodec.Encode(gobDiags)\n}\n\n// decodeDiagnostics decodes the given gob-encoded diagnostics.\nfunc decodeDiagnostics(data []byte) []*Diagnostic {\n\tvar gobDiags []gobDiagnostic\n\tdiagnosticsCodec.Decode(data, &gobDiags)\n\tvar srcDiags []*Diagnostic\n\tfor _, gobDiag := range gobDiags {\n\t\tvar srcFixes []SuggestedFix\n\t\tfor _, gobFix := range gobDiag.SuggestedFixes {\n\t\t\tsrcFix := SuggestedFix{\n\t\t\t\tTitle:      gobFix.Message,\n\t\t\t\tActionKind: gobFix.ActionKind,\n\t\t\t}\n\t\t\tfor _, gobEdit := range gobFix.TextEdits {\n\t\t\t\tif srcFix.Edits == nil {\n\t\t\t\t\tsrcFix.Edits = make(map[protocol.DocumentURI][]protocol.TextEdit)\n\t\t\t\t}\n\t\t\t\tsrcEdit := protocol.TextEdit{\n\t\t\t\t\tRange:   gobEdit.Location.Range,\n\t\t\t\t\tNewText: string(gobEdit.NewText),\n\t\t\t\t}\n\t\t\t\turi := gobEdit.Location.URI\n\t\t\t\tsrcFix.Edits[uri] = append(srcFix.Edits[uri], srcEdit)\n\t\t\t}\n\t\t\tif gobCmd := gobFix.Command; gobCmd != nil {\n\t\t\t\tsrcFix.Command = &protocol.Command{\n\t\t\t\t\tTitle:     gobCmd.Title,\n\t\t\t\t\tCommand:   gobCmd.Command,\n\t\t\t\t\tArguments: gobCmd.Arguments,\n\t\t\t\t}\n\t\t\t}\n\t\t\tsrcFixes = append(srcFixes, srcFix)\n\t\t}\n\t\tvar srcRelated []protocol.DiagnosticRelatedInformation\n\t\tfor _, gobRel := range gobDiag.Related {\n\t\t\tsrcRel := protocol.DiagnosticRelatedInformation(gobRel)\n\t\t\tsrcRelated = append(srcRelated, srcRel)\n\t\t}\n\t\tsrcDiag := &Diagnostic{\n\t\t\tURI:            gobDiag.Location.URI,\n\t\t\tRange:          gobDiag.Location.Range,\n\t\t\tSeverity:       gobDiag.Severity,\n\t\t\tCode:           gobDiag.Code,\n\t\t\tCodeHref:       gobDiag.CodeHref,\n\t\t\tSource:         DiagnosticSource(gobDiag.Source),\n\t\t\tMessage:        gobDiag.Message,\n\t\t\tTags:           gobDiag.Tags,\n\t\t\tRelated:        srcRelated,\n\t\t\tSuggestedFixes: srcFixes,\n\t\t}\n\t\tsrcDiags = append(srcDiags, srcDiag)\n\t}\n\treturn srcDiags\n}\n\n// toSourceDiagnostic converts a gobDiagnostic to \"source\" form.\nfunc toSourceDiagnostic(srcAnalyzer *settings.Analyzer, gobDiag *gobDiagnostic) *Diagnostic {\n\tvar related []protocol.DiagnosticRelatedInformation\n\tfor _, gobRelated := range gobDiag.Related {\n\t\trelated = append(related, protocol.DiagnosticRelatedInformation(gobRelated))\n\t}\n\n\tdiag := &Diagnostic{\n\t\tURI:      gobDiag.Location.URI,\n\t\tRange:    gobDiag.Location.Range,\n\t\tSeverity: srcAnalyzer.Severity(),\n\t\tCode:     gobDiag.Code,\n\t\tCodeHref: gobDiag.CodeHref,\n\t\tSource:   DiagnosticSource(gobDiag.Source),\n\t\tMessage:  gobDiag.Message,\n\t\tRelated:  related,\n\t\tTags:     srcAnalyzer.Tags(),\n\t}\n\n\t// We cross the set of fixes (whether edit- or command-based)\n\t// with the set of kinds, as a single fix may represent more\n\t// than one kind of action (e.g. refactor, quickfix, fixall),\n\t// each corresponding to a distinct client UI element\n\t// or operation.\n\tkinds := srcAnalyzer.ActionKinds()\n\tif len(kinds) == 0 {\n\t\tkinds = []protocol.CodeActionKind{protocol.QuickFix}\n\t}\n\n\tvar fixes []SuggestedFix\n\tfor _, fix := range gobDiag.SuggestedFixes {\n\t\tif len(fix.TextEdits) > 0 {\n\t\t\t// Accumulate edit-based fixes supplied by the diagnostic itself.\n\t\t\tedits := make(map[protocol.DocumentURI][]protocol.TextEdit)\n\t\t\tfor _, e := range fix.TextEdits {\n\t\t\t\turi := e.Location.URI\n\t\t\t\tedits[uri] = append(edits[uri], protocol.TextEdit{\n\t\t\t\t\tRange:   e.Location.Range,\n\t\t\t\t\tNewText: string(e.NewText),\n\t\t\t\t})\n\t\t\t}\n\t\t\tfor _, kind := range kinds {\n\t\t\t\tfixes = append(fixes, SuggestedFix{\n\t\t\t\t\tTitle:      fix.Message,\n\t\t\t\t\tEdits:      edits,\n\t\t\t\t\tActionKind: kind,\n\t\t\t\t})\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Accumulate command-based fixes, whose edits\n\t\t\t// are not provided by the analyzer but are computed on demand\n\t\t\t// by logic \"adjacent to\" the analyzer.\n\t\t\t//\n\t\t\t// The analysis.Diagnostic.Category is used as the fix name.\n\t\t\tcmd := command.NewApplyFixCommand(fix.Message, command.ApplyFixArgs{\n\t\t\t\tFix:      diag.Code,\n\t\t\t\tLocation: gobDiag.Location,\n\t\t\t})\n\t\t\tfor _, kind := range kinds {\n\t\t\t\tfixes = append(fixes, SuggestedFixFromCommand(cmd, kind))\n\t\t\t}\n\n\t\t\t// Ensure that the analyzer specifies a category for all its no-edit fixes.\n\t\t\t// This is asserted by analysistest.RunWithSuggestedFixes, but there\n\t\t\t// may be gaps in test coverage.\n\t\t\tif diag.Code == \"\" || diag.Code == \"default\" {\n\t\t\t\tbug.Reportf(\"missing Diagnostic.Code: %#v\", *diag)\n\t\t\t}\n\t\t}\n\t}\n\tdiag.SuggestedFixes = fixes\n\n\t// If the fixes only delete code, assume that the diagnostic is reporting dead code.\n\tif onlyDeletions(diag.SuggestedFixes) {\n\t\tdiag.Tags = append(diag.Tags, protocol.Unnecessary)\n\t}\n\treturn diag\n}\n\n// onlyDeletions returns true if fixes is non-empty and all of the suggested\n// fixes are deletions.\nfunc onlyDeletions(fixes []SuggestedFix) bool {\n\tfor _, fix := range fixes {\n\t\tif fix.Command != nil {\n\t\t\treturn false\n\t\t}\n\t\tfor _, edits := range fix.Edits {\n\t\t\tfor _, edit := range edits {\n\t\t\t\tif edit.NewText != \"\" {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tif protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn len(fixes) > 0\n}\n\nfunc typesCodeHref(linkTarget string, code typesinternal.ErrorCode) string {\n\treturn BuildLink(linkTarget, \"golang.org/x/tools/internal/typesinternal\", code.String())\n}\n\n// BuildLink constructs a URL with the given target, path, and anchor.\nfunc BuildLink(target, path, anchor string) protocol.URI {\n\tlink := fmt.Sprintf(\"https://%s/%s\", target, path)\n\tif anchor == \"\" {\n\t\treturn link\n\t}\n\treturn link + \"#\" + anchor\n}\n\nfunc parseGoListError(e packages.Error, dir string) (filename string, line, col8 int) {\n\tinput := e.Pos\n\tif input == \"\" {\n\t\t// No position. Attempt to parse one out of a\n\t\t// go list error of the form \"file:line:col:\n\t\t// message\" by stripping off the message.\n\t\tinput = strings.TrimSpace(e.Msg)\n\t\tif i := strings.Index(input, \": \"); i >= 0 {\n\t\t\tinput = input[:i]\n\t\t}\n\t}\n\n\tfilename, line, col8 = splitFileLineCol(input)\n\tif !filepath.IsAbs(filename) {\n\t\tfilename = filepath.Join(dir, filename)\n\t}\n\treturn filename, line, col8\n}\n\n// splitFileLineCol splits s into \"filename:line:col\",\n// where line and col consist of decimal digits.\nfunc splitFileLineCol(s string) (file string, line, col8 int) {\n\t// Beware that the filename may contain colon on Windows.\n\n\t// stripColonDigits removes a \":%d\" suffix, if any.\n\tstripColonDigits := func(s string) (rest string, num int) {\n\t\tif i := strings.LastIndex(s, \":\"); i >= 0 {\n\t\t\tif v, err := strconv.ParseInt(s[i+1:], 10, 32); err == nil {\n\t\t\t\treturn s[:i], int(v)\n\t\t\t}\n\t\t}\n\t\treturn s, -1\n\t}\n\n\t// strip col \":%d\"\n\ts, n1 := stripColonDigits(s)\n\tif n1 < 0 {\n\t\treturn s, 1, 1 // \"filename\"\n\t}\n\n\t// strip line \":%d\"\n\ts, n2 := stripColonDigits(s)\n\tif n2 < 0 {\n\t\treturn s, n1, 1 // \"filename:line\"\n\t}\n\n\treturn s, n2, n1 // \"filename:line:col\"\n}\n\n// parseGoListImportCycleError attempts to parse the given go/packages error as\n// an import cycle, returning a diagnostic if successful.\n//\n// If the error is not detected as an import cycle error, it returns nil, nil.\nfunc parseGoListImportCycleError(ctx context.Context, e packages.Error, mp *metadata.Package, fs file.Source) (*Diagnostic, error) {\n\tre := regexp.MustCompile(`(.*): import stack: \\[(.+)\\]`)\n\tmatches := re.FindStringSubmatch(strings.TrimSpace(e.Msg))\n\tif len(matches) < 3 {\n\t\treturn nil, nil\n\t}\n\tmsg := matches[1]\n\timportList := strings.Split(matches[2], \" \")\n\t// Since the error is relative to the current package. The import that is causing\n\t// the import cycle error is the second one in the list.\n\tif len(importList) < 2 {\n\t\treturn nil, nil\n\t}\n\t// Imports have quotation marks around them.\n\tcircImp := strconv.Quote(importList[1])\n\tfor _, uri := range mp.CompiledGoFiles {\n\t\tpgf, err := parseGoURI(ctx, fs, uri, parsego.Header)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Search file imports for the import that is causing the import cycle.\n\t\tfor _, imp := range pgf.File.Imports {\n\t\t\tif imp.Path.Value == circImp {\n\t\t\t\trng, err := pgf.NodeRange(imp)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil\n\t\t\t\t}\n\n\t\t\t\treturn &Diagnostic{\n\t\t\t\t\tURI:      pgf.URI,\n\t\t\t\t\tRange:    rng,\n\t\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\t\tSource:   ListError,\n\t\t\t\t\tMessage:  msg,\n\t\t\t\t}, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// parseGoURI is a helper to parse the Go file at the given URI from the file\n// source fs. The resulting syntax and token.File belong to an ephemeral,\n// encapsulated FileSet, so this file stands only on its own: it's not suitable\n// to use in a list of file of a package, for example.\n//\n// It returns an error if the file could not be read.\n//\n// TODO(rfindley): eliminate this helper.\nfunc parseGoURI(ctx context.Context, fs file.Source, uri protocol.DocumentURI, mode parser.Mode) (*parsego.File, error) {\n\tfh, err := fs.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn parseGoImpl(ctx, token.NewFileSet(), fh, mode, false)\n}\n\n// parseModURI is a helper to parse the Mod file at the given URI from the file\n// source fs.\n//\n// It returns an error if the file could not be read.\nfunc parseModURI(ctx context.Context, fs file.Source, uri protocol.DocumentURI) (*ParsedModule, error) {\n\tfh, err := fs.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn parseModImpl(ctx, fh)\n}\n"
  },
  {
    "path": "gopls/internal/cache/errors_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestParseErrorMessage(t *testing.T) {\n\ttests := []struct {\n\t\tname             string\n\t\tin               string\n\t\texpectedFileName string\n\t\texpectedLine     int // (missing => 1)\n\t\texpectedColumn   int // (missing => 1)\n\t}{\n\t\t{\n\t\t\tname:             \"from go list output\",\n\t\t\tin:               \"\\nattributes.go:13:1: expected 'package', found 'type'\",\n\t\t\texpectedFileName: \"attributes.go\",\n\t\t\texpectedLine:     13,\n\t\t\texpectedColumn:   1,\n\t\t},\n\t\t{\n\t\t\tname:             \"windows driver letter\",\n\t\t\tin:               \"C:\\\\foo\\\\bar.go:13: message\",\n\t\t\texpectedFileName: \"bar.go\",\n\t\t\texpectedLine:     13,\n\t\t\texpectedColumn:   1,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tfn, line, col8 := parseGoListError(packages.Error{Msg: tt.in}, \".\")\n\n\t\t\tif !strings.HasSuffix(fn, tt.expectedFileName) {\n\t\t\t\tt.Errorf(\"expected filename with suffix %v but got %v\", tt.expectedFileName, fn)\n\t\t\t}\n\t\t\tif line != tt.expectedLine {\n\t\t\t\tt.Errorf(\"expected line %v but got %v\", tt.expectedLine, line)\n\t\t\t}\n\t\t\tif col8 != tt.expectedColumn {\n\t\t\t\tt.Errorf(\"expected col %v but got %v\", tt.expectedLine, col8)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestDiagnosticEncoding(t *testing.T) {\n\tdiags := []*Diagnostic{\n\t\t{}, // empty\n\t\t{\n\t\t\tURI: \"file///foo\",\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 4, Character: 2},\n\t\t\t\tEnd:   protocol.Position{Line: 6, Character: 7},\n\t\t\t},\n\t\t\tSeverity: protocol.SeverityWarning,\n\t\t\tCode:     \"red\",\n\t\t\tCodeHref: \"https://go.dev\",\n\t\t\tSource:   \"test\",\n\t\t\tMessage:  \"something bad happened\",\n\t\t\tTags:     []protocol.DiagnosticTag{81},\n\t\t\tRelated: []protocol.DiagnosticRelatedInformation{\n\t\t\t\t{\n\t\t\t\t\tLocation: protocol.Location{\n\t\t\t\t\t\tURI: \"file:///other\",\n\t\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\t\tStart: protocol.Position{Line: 3, Character: 6},\n\t\t\t\t\t\t\tEnd:   protocol.Position{Line: 4, Character: 9},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tMessage: \"psst, over here\",\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Fields below are used internally to generate quick fixes. They aren't\n\t\t\t// part of the LSP spec and don't leave the server.\n\t\t\tSuggestedFixes: []SuggestedFix{\n\t\t\t\t{\n\t\t\t\t\tTitle: \"fix it!\",\n\t\t\t\t\tEdits: map[protocol.DocumentURI][]protocol.TextEdit{\n\t\t\t\t\t\t\"file:///foo\": {{\n\t\t\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\t\t\tStart: protocol.Position{Line: 4, Character: 2},\n\t\t\t\t\t\t\t\tEnd:   protocol.Position{Line: 6, Character: 7},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tNewText: \"abc\",\n\t\t\t\t\t\t}},\n\t\t\t\t\t\t\"file:///other\": {{\n\t\t\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\t\t\tStart: protocol.Position{Line: 4, Character: 2},\n\t\t\t\t\t\t\t\tEnd:   protocol.Position{Line: 6, Character: 7},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tNewText: \"!@#!\",\n\t\t\t\t\t\t}},\n\t\t\t\t\t},\n\t\t\t\t\tCommand: &protocol.Command{\n\t\t\t\t\t\tTitle:     \"run a command\",\n\t\t\t\t\t\tCommand:   \"gopls.fix\",\n\t\t\t\t\t\tArguments: []json.RawMessage{json.RawMessage(`{\"a\":1}`)},\n\t\t\t\t\t},\n\t\t\t\t\tActionKind: protocol.QuickFix,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tURI: \"file//bar\",\n\t\t\t// other fields tested above\n\t\t},\n\t}\n\n\tdata := encodeDiagnostics(diags)\n\tdiags2 := decodeDiagnostics(data)\n\n\tif diff := cmp.Diff(diags, diags2); diff != \"\" {\n\t\tt.Errorf(\"decoded diagnostics do not match (-original +decoded):\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/filemap.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"iter\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/persistent\"\n)\n\n// A fileMap maps files in the snapshot, with some additional bookkeeping:\n// It keeps track of overlays as well as directories containing any observed\n// file.\ntype fileMap struct {\n\tfiles    *persistent.Map[protocol.DocumentURI, file.Handle]\n\toverlays *persistent.Map[protocol.DocumentURI, *overlay] // the subset of files that are overlays\n\tdirs     *persistent.Set[string]                         // all dirs containing files; if nil, dirs have not been initialized\n}\n\nfunc newFileMap() *fileMap {\n\treturn &fileMap{\n\t\tfiles:    new(persistent.Map[protocol.DocumentURI, file.Handle]),\n\t\toverlays: new(persistent.Map[protocol.DocumentURI, *overlay]),\n\t\tdirs:     new(persistent.Set[string]),\n\t}\n}\n\n// clone creates a copy of the fileMap, incorporating the changes specified by\n// the changes map.\nfunc (m *fileMap) clone(changes map[protocol.DocumentURI]file.Handle) *fileMap {\n\tm2 := &fileMap{\n\t\tfiles:    m.files.Clone(),\n\t\toverlays: m.overlays.Clone(),\n\t}\n\tif m.dirs != nil {\n\t\tm2.dirs = m.dirs.Clone()\n\t}\n\n\t// Handle file changes.\n\t//\n\t// Note, we can't simply delete the file unconditionally and let it be\n\t// re-read by the snapshot, as (1) the snapshot must always observe all\n\t// overlays, and (2) deleting a file forces directories to be reevaluated, as\n\t// it may be the last file in a directory. We want to avoid that work in the\n\t// common case where a file has simply changed.\n\t//\n\t// For that reason, we also do this in two passes, processing deletions\n\t// first, as a set before a deletion would result in pointless work.\n\tfor uri, fh := range changes {\n\t\tif !fileExists(fh) {\n\t\t\tm2.delete(uri)\n\t\t}\n\t}\n\tfor uri, fh := range changes {\n\t\tif fileExists(fh) {\n\t\t\tm2.set(uri, fh)\n\t\t}\n\t}\n\treturn m2\n}\n\nfunc (m *fileMap) destroy() {\n\tm.files.Destroy()\n\tm.overlays.Destroy()\n\tif m.dirs != nil {\n\t\tm.dirs.Destroy()\n\t}\n}\n\n// get returns the file handle mapped by the given key, or (nil, false) if the\n// key is not present.\nfunc (m *fileMap) get(key protocol.DocumentURI) (file.Handle, bool) {\n\treturn m.files.Get(key)\n}\n\n// all returns the sequence of (uri, fh) entries in the map.\nfunc (m *fileMap) all() iter.Seq2[protocol.DocumentURI, file.Handle] {\n\treturn m.files.All()\n}\n\n// set stores the given file handle for key, updating overlays and directories\n// accordingly.\nfunc (m *fileMap) set(key protocol.DocumentURI, fh file.Handle) {\n\tm.files.Set(key, fh, nil)\n\n\t// update overlays\n\tif o, ok := fh.(*overlay); ok {\n\t\tm.overlays.Set(key, o, nil)\n\t} else {\n\t\t// Setting a non-overlay must delete the corresponding overlay, to preserve\n\t\t// the accuracy of the overlay set.\n\t\tm.overlays.Delete(key)\n\t}\n\n\t// update dirs, if they have been computed\n\tif m.dirs != nil {\n\t\tm.addDirs(key)\n\t}\n}\n\n// addDirs adds all directories containing u to the dirs set.\nfunc (m *fileMap) addDirs(u protocol.DocumentURI) {\n\tdir := u.DirPath()\n\tfor dir != \"\" && !m.dirs.Contains(dir) {\n\t\tm.dirs.Add(dir)\n\t\tdir = filepath.Dir(dir)\n\t}\n}\n\n// delete removes a file from the map, and updates overlays and dirs\n// accordingly.\nfunc (m *fileMap) delete(key protocol.DocumentURI) {\n\tm.files.Delete(key)\n\tm.overlays.Delete(key)\n\n\t// Deleting a file may cause the set of dirs to shrink; therefore we must\n\t// re-evaluate the dir set.\n\t//\n\t// Do this lazily, to avoid work if there are multiple deletions in a row.\n\tif m.dirs != nil {\n\t\tm.dirs.Destroy()\n\t\tm.dirs = nil\n\t}\n}\n\n// getOverlays returns a new unordered array of overlay files.\nfunc (m *fileMap) getOverlays() []*overlay {\n\tvar overlays []*overlay\n\tfor _, o := range m.overlays.All() {\n\t\toverlays = append(overlays, o)\n\t}\n\treturn overlays\n}\n\n// getDirs reports returns the set of dirs observed by the fileMap.\n//\n// This operation mutates the fileMap.\n// The result must not be mutated by the caller.\nfunc (m *fileMap) getDirs() *persistent.Set[string] {\n\tif m.dirs == nil {\n\t\tm.dirs = new(persistent.Set[string])\n\t\tfor uri := range m.files.All() {\n\t\t\tm.addDirs(uri)\n\t\t}\n\t}\n\treturn m.dirs\n}\n"
  },
  {
    "path": "gopls/internal/cache/filemap_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"path/filepath\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestFileMap(t *testing.T) {\n\tconst (\n\t\tset = iota\n\t\tdel\n\t)\n\ttype op struct {\n\t\top      int // set or remove\n\t\tpath    string\n\t\toverlay bool\n\t}\n\ttests := []struct {\n\t\tlabel        string\n\t\tops          []op\n\t\twantFiles    []string\n\t\twantOverlays []string\n\t\twantDirs     []string\n\t}{\n\t\t{\"empty\", nil, nil, nil, nil},\n\t\t{\"singleton\", []op{\n\t\t\t{set, \"/a/b\", false},\n\t\t}, []string{\"/a/b\"}, nil, []string{\"/\", \"/a\"}},\n\t\t{\"overlay\", []op{\n\t\t\t{set, \"/a/b\", true},\n\t\t}, []string{\"/a/b\"}, []string{\"/a/b\"}, []string{\"/\", \"/a\"}},\n\t\t{\"replace overlay\", []op{\n\t\t\t{set, \"/a/b\", true},\n\t\t\t{set, \"/a/b\", false},\n\t\t}, []string{\"/a/b\"}, nil, []string{\"/\", \"/a\"}},\n\t\t{\"multi dir\", []op{\n\t\t\t{set, \"/a/b\", false},\n\t\t\t{set, \"/c/d\", false},\n\t\t}, []string{\"/a/b\", \"/c/d\"}, nil, []string{\"/\", \"/a\", \"/c\"}},\n\t\t{\"empty dir\", []op{\n\t\t\t{set, \"/a/b\", false},\n\t\t\t{set, \"/c/d\", false},\n\t\t\t{del, \"/a/b\", false},\n\t\t}, []string{\"/c/d\"}, nil, []string{\"/\", \"/c\"}},\n\t}\n\n\t// Normalize paths for windows compatibility.\n\tnormalize := func(path string) string {\n\t\ty := filepath.ToSlash(path)\n\t\t// Windows paths may start with a drive letter\n\t\tif len(y) > 2 && y[1] == ':' && y[0] >= 'A' && y[0] <= 'Z' {\n\t\t\ty = y[2:]\n\t\t}\n\t\treturn y\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tm := newFileMap()\n\t\t\tfor _, op := range test.ops {\n\t\t\t\turi := protocol.URIFromPath(filepath.FromSlash(op.path))\n\t\t\t\tswitch op.op {\n\t\t\t\tcase set:\n\t\t\t\t\tvar fh file.Handle\n\t\t\t\t\tif op.overlay {\n\t\t\t\t\t\tfh = &overlay{uri: uri}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfh = &diskFile{uri: uri}\n\t\t\t\t\t}\n\t\t\t\t\tm.set(uri, fh)\n\t\t\t\tcase del:\n\t\t\t\t\tm.delete(uri)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar gotFiles []string\n\t\t\tfor uri := range m.all() {\n\t\t\t\tgotFiles = append(gotFiles, normalize(uri.Path()))\n\t\t\t}\n\t\t\tsort.Strings(gotFiles)\n\t\t\tif diff := cmp.Diff(test.wantFiles, gotFiles); diff != \"\" {\n\t\t\t\tt.Errorf(\"Files mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\n\t\t\tvar gotOverlays []string\n\t\t\tfor _, o := range m.getOverlays() {\n\t\t\t\tgotOverlays = append(gotOverlays, normalize(o.URI().Path()))\n\t\t\t}\n\t\t\tif diff := cmp.Diff(test.wantOverlays, gotOverlays); diff != \"\" {\n\t\t\t\tt.Errorf(\"Overlays mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\n\t\t\tvar gotDirs []string\n\t\t\tfor dir := range m.getDirs().All() {\n\t\t\t\tgotDirs = append(gotDirs, normalize(dir))\n\t\t\t}\n\t\t\tsort.Strings(gotDirs)\n\t\t\tif diff := cmp.Diff(test.wantDirs, gotDirs); diff != \"\" {\n\t\t\t\tt.Errorf(\"Dirs mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/filterer.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// PathIncludeFunc creates a function that determines if a given file path\n// should be included based on a set of inclusion/exclusion rules.\n//\n// The `rules` parameter is a slice of strings, where each string represents a\n// filtering rule. Each rule consists of an operator (`+` for inclusion, `-`\n// for exclusion) followed by a path pattern. See more detail of rules syntax\n// at [settings.BuildOptions.DirectoryFilters].\n//\n// Rules are evaluated in order, and the last matching rule determines\n// whether a path is included or excluded.\n//\n// Examples:\n//   - []{\"-foo\"}: Exclude \"foo\" at the current depth.\n//   - []{\"-**foo\"}: Exclude \"foo\" at any depth.\n//   - []{\"+bar\"}: Include \"bar\" at the current depth.\n//   - []{\"-foo\", \"+foo/**/bar\"}: Exclude all \"foo\" at current depth except\n//     directory \"bar\" under \"foo\" at any depth.\nfunc PathIncludeFunc(rules []string) func(string) bool {\n\tvar matchers []*regexp.Regexp\n\tvar included []bool\n\tfor _, filter := range rules {\n\t\tfilter = path.Clean(filepath.ToSlash(filter))\n\t\t// TODO(dungtuanle): fix: validate [+-] prefix.\n\t\top, prefix := filter[0], filter[1:]\n\t\t// convertFilterToRegexp adds \"/\" at the end of prefix to handle cases\n\t\t// where a filter is a prefix of another filter.\n\t\t// For example, it prevents [+foobar, -foo] from excluding \"foobar\".\n\t\tmatchers = append(matchers, convertFilterToRegexp(filepath.ToSlash(prefix)))\n\t\tincluded = append(included, op == '+')\n\t}\n\n\treturn func(path string) bool {\n\t\t// Ensure leading and trailing slashes.\n\t\tif !strings.HasPrefix(path, \"/\") {\n\t\t\tpath = \"/\" + path\n\t\t}\n\t\tif !strings.HasSuffix(path, \"/\") {\n\t\t\tpath += \"/\"\n\t\t}\n\n\t\t// TODO(adonovan): opt: iterate in reverse and break at first match.\n\t\tinclude := true\n\t\tfor i, filter := range matchers {\n\t\t\tif filter.MatchString(path) {\n\t\t\t\tinclude = included[i] // last match wins\n\t\t\t}\n\t\t}\n\t\treturn include\n\t}\n}\n\n// convertFilterToRegexp replaces glob-like operator substrings in a string file path to their equivalent regex forms.\n// Supporting glob-like operators:\n//   - **: match zero or more complete path segments\nfunc convertFilterToRegexp(filter string) *regexp.Regexp {\n\tif filter == \"\" {\n\t\treturn regexp.MustCompile(\".*\")\n\t}\n\tvar ret strings.Builder\n\tret.WriteString(\"^/\")\n\tsegs := strings.SplitSeq(filter, \"/\")\n\tfor seg := range segs {\n\t\t// Inv: seg != \"\" since path is clean.\n\t\tif seg == \"**\" {\n\t\t\tret.WriteString(\".*\")\n\t\t} else {\n\t\t\tret.WriteString(regexp.QuoteMeta(seg))\n\t\t}\n\t\tret.WriteString(\"/\")\n\t}\n\tpattern := ret.String()\n\n\t// Remove unnecessary \"^.*\" prefix, which increased\n\t// BenchmarkWorkspaceSymbols time by ~20% (even though\n\t// filter CPU time increased by only by ~2.5%) when the\n\t// default filter was changed to \"**/node_modules\".\n\tpattern = strings.TrimPrefix(pattern, \"^/.*\")\n\n\treturn regexp.MustCompile(pattern)\n}\n"
  },
  {
    "path": "gopls/internal/cache/fs_memoized.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/robustio\"\n)\n\n// A memoizedFS is a file source that memoizes reads, to reduce IO.\ntype memoizedFS struct {\n\tmu sync.Mutex\n\n\t// filesByID maps existing file inodes to the result of a read.\n\t// (The read may have failed, e.g. due to EACCES or a delete between stat+read.)\n\t// Each slice is a non-empty list of aliases: different URIs.\n\tfilesByID map[robustio.FileID][]*diskFile\n}\n\nfunc newMemoizedFS() *memoizedFS {\n\treturn &memoizedFS{filesByID: make(map[robustio.FileID][]*diskFile)}\n}\n\n// A diskFile is a file in the filesystem, or a failure to read one.\n// It implements the file.Source interface.\ntype diskFile struct {\n\turi     protocol.DocumentURI\n\tmodTime time.Time\n\tcontent []byte\n\thash    file.Hash\n\terr     error\n}\n\nfunc (h *diskFile) String() string { return h.uri.Path() }\n\nfunc (h *diskFile) URI() protocol.DocumentURI { return h.uri }\n\nfunc (h *diskFile) Identity() file.Identity {\n\treturn file.Identity{\n\t\tURI:  h.uri,\n\t\tHash: h.hash,\n\t}\n}\n\nfunc (h *diskFile) SameContentsOnDisk() bool    { return true }\nfunc (h *diskFile) Version() int32              { return 0 }\nfunc (h *diskFile) Content() ([]byte, error)    { return h.content, h.err }\nfunc (h *diskFile) ModTime() (time.Time, error) { return h.modTime, h.err }\n\n// ReadFile stats and (maybe) reads the file, updates the cache, and returns it.\nfunc (fs *memoizedFS) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) {\n\tid, mtime, err := robustio.GetFileID(uri.Path())\n\tif err != nil {\n\t\t// file does not exist\n\t\treturn &diskFile{\n\t\t\terr: err,\n\t\t\turi: uri,\n\t\t}, nil\n\t}\n\n\t// We check if the file has changed by comparing modification times. Notably,\n\t// this is an imperfect heuristic as various systems have low resolution\n\t// mtimes (as much as 1s on WSL or s390x builders), so we only cache\n\t// filehandles if mtime is old enough to be reliable, meaning that we don't\n\t// expect a subsequent write to have the same mtime.\n\t//\n\t// The coarsest mtime precision we've seen in practice is 1s, so consider\n\t// mtime to be unreliable if it is less than 2s old. Capture this before\n\t// doing anything else.\n\trecentlyModified := time.Since(mtime) < 2*time.Second\n\n\tfs.mu.Lock()\n\tfhs, ok := fs.filesByID[id]\n\tif ok && fhs[0].modTime.Equal(mtime) {\n\t\tvar fh *diskFile\n\t\t// We have already seen this file and it has not changed.\n\t\tfor _, h := range fhs {\n\t\t\tif h.uri == uri {\n\t\t\t\tfh = h\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t// No file handle for this exact URI. Create an alias, but share content.\n\t\tif fh == nil {\n\t\t\tnewFH := *fhs[0]\n\t\t\tnewFH.uri = uri\n\t\t\tfh = &newFH\n\t\t\tfhs = append(fhs, fh)\n\t\t\tfs.filesByID[id] = fhs\n\t\t}\n\t\tfs.mu.Unlock()\n\t\treturn fh, nil\n\t}\n\tfs.mu.Unlock()\n\n\t// Unknown file, or file has changed. Read (or re-read) it.\n\tfh, err := readFile(ctx, uri, mtime) // ~25us\n\tif err != nil {\n\t\treturn nil, err // e.g. cancelled (not: read failed)\n\t}\n\n\tfs.mu.Lock()\n\tif !recentlyModified {\n\t\tfs.filesByID[id] = []*diskFile{fh}\n\t} else {\n\t\tdelete(fs.filesByID, id)\n\t}\n\tfs.mu.Unlock()\n\treturn fh, nil\n}\n\n// fileStats returns information about the set of files stored in fs. It is\n// intended for debugging only.\nfunc (fs *memoizedFS) fileStats() (files, largest, errs int) {\n\tfs.mu.Lock()\n\tdefer fs.mu.Unlock()\n\n\tfiles = len(fs.filesByID)\n\tlargest = 0\n\terrs = 0\n\n\tfor _, files := range fs.filesByID {\n\t\trep := files[0]\n\t\tif len(rep.content) > largest {\n\t\t\tlargest = len(rep.content)\n\t\t}\n\t\tif rep.err != nil {\n\t\t\terrs++\n\t\t}\n\t}\n\treturn files, largest, errs\n}\n\n// ioLimit limits the number of parallel file reads per process.\nvar ioLimit = make(chan struct{}, 128)\n\nfunc readFile(ctx context.Context, uri protocol.DocumentURI, mtime time.Time) (*diskFile, error) {\n\tselect {\n\tcase ioLimit <- struct{}{}:\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\t}\n\tdefer func() { <-ioLimit }()\n\n\tctx, done := event.Start(ctx, \"cache.readFile\", label.File.Of(uri.Path()))\n\t_ = ctx\n\tdefer done()\n\n\t// It is possible that a race causes us to read a file with different file\n\t// ID, or whose mtime differs from the given mtime. However, in these cases\n\t// we expect the client to notify of a subsequent file change, and the file\n\t// content should be eventually consistent.\n\tcontent, err := os.ReadFile(uri.Path()) // ~20us\n\tif err != nil {\n\t\tcontent = nil // just in case\n\t}\n\treturn &diskFile{\n\t\tmodTime: mtime,\n\t\turi:     uri,\n\t\tcontent: content,\n\t\thash:    file.HashOf(content),\n\t\terr:     err,\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/fs_overlay.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// An overlayFS is a file.Source that keeps track of overlays on top of a\n// delegate FileSource.\ntype overlayFS struct {\n\tdelegate file.Source\n\n\tmu       sync.Mutex\n\toverlays map[protocol.DocumentURI]*overlay\n}\n\nfunc newOverlayFS(delegate file.Source) *overlayFS {\n\treturn &overlayFS{\n\t\tdelegate: delegate,\n\t\toverlays: make(map[protocol.DocumentURI]*overlay),\n\t}\n}\n\n// Overlays returns a new unordered array of overlays.\nfunc (fs *overlayFS) Overlays() []*overlay {\n\tfs.mu.Lock()\n\tdefer fs.mu.Unlock()\n\toverlays := make([]*overlay, 0, len(fs.overlays))\n\tfor _, overlay := range fs.overlays {\n\t\toverlays = append(overlays, overlay)\n\t}\n\treturn overlays\n}\n\nfunc (fs *overlayFS) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) {\n\tfs.mu.Lock()\n\toverlay, ok := fs.overlays[uri]\n\tfs.mu.Unlock()\n\tif ok {\n\t\treturn overlay, nil\n\t}\n\treturn fs.delegate.ReadFile(ctx, uri)\n}\n\n// An overlay is a file open in the editor. It may have unsaved edits.\n// It implements the file.Handle interface, and the implicit contract\n// of the debug.FileTmpl template.\ntype overlay struct {\n\turi     protocol.DocumentURI\n\tcontent []byte\n\tmodTime time.Time\n\thash    file.Hash\n\tversion int32\n\tkind    file.Kind\n\n\t// saved is true if a file matches the state on disk,\n\t// and therefore does not need to be part of the overlay sent to go/packages.\n\tsaved bool\n}\n\nfunc (o *overlay) String() string { return o.uri.Path() }\n\nfunc (o *overlay) URI() protocol.DocumentURI { return o.uri }\n\nfunc (o *overlay) Identity() file.Identity {\n\treturn file.Identity{\n\t\tURI:  o.uri,\n\t\tHash: o.hash,\n\t}\n}\n\nfunc (o *overlay) Content() ([]byte, error)    { return o.content, nil }\nfunc (o *overlay) ModTime() (time.Time, error) { return o.modTime, nil }\nfunc (o *overlay) Version() int32              { return o.version }\nfunc (o *overlay) SameContentsOnDisk() bool    { return o.saved }\nfunc (o *overlay) Kind() file.Kind             { return o.kind }\n"
  },
  {
    "path": "gopls/internal/cache/future.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"sync\"\n)\n\n// A futureCache is a key-value store of \"futures\", which are values that might\n// not yet be processed. By accessing values using [futureCache.get], the\n// caller may share work with other goroutines that require the same key.\n//\n// This is a relatively common pattern, though this implementation includes the\n// following two non-standard additions:\n//\n//  1. futures are cancellable and retryable. If the context being used to\n//     compute the future is cancelled, it will abort the computation. If other\n//     goroutes are awaiting the future, they will acquire the right to compute\n//     it, and start anew.\n//  2. futures may be either persistent or transient. Persistent futures are\n//     the standard pattern: the results of the computation are preserved for\n//     the lifetime of the cache. However, if the cache is transient\n//     (persistent=false), the futures will be discarded once their value has\n//     been passed to all awaiting goroutines.\n//\n// These specific extensions are used to implement the concurrency model of the\n// [typeCheckBatch], which allows multiple operations to piggy-back on top of\n// an ongoing type checking operation, requesting new packages asynchronously\n// without unduly increasing the in-use memory required by the type checking\n// pass.\ntype futureCache[K comparable, V any] struct {\n\tpersistent bool\n\n\tmu    sync.Mutex\n\tcache map[K]*future[V]\n}\n\n// newFutureCache returns a futureCache that is ready to coordinate\n// computations via [futureCache.get].\n//\n// If persistent is true, the results of these computations are stored for the\n// lifecycle of cache. Otherwise, results are discarded after they have been\n// passed to all awaiting goroutines.\nfunc newFutureCache[K comparable, V any](persistent bool) *futureCache[K, V] {\n\treturn &futureCache[K, V]{\n\t\tpersistent: persistent,\n\t\tcache:      make(map[K]*future[V]),\n\t}\n}\n\ntype future[V any] struct {\n\t// refs is the number of goroutines awaiting this future, to be used for\n\t// cleaning up transient cache entries.\n\t//\n\t// Guarded by futureCache.mu.\n\trefs int\n\n\t// done is closed when the future has been fully computed.\n\tdone chan unit\n\n\t// acquire used to select an awaiting goroutine to run the computation.\n\t// acquire is 1-buffered, and initialized with one unit, so that the first\n\t// requester starts a computation. If that computation is cancelled, the\n\t// requester pushes the unit back to acquire, so that another goroutine may\n\t// execute the computation.\n\tacquire chan unit\n\n\t// v and err store the result of the computation, guarded by done.\n\tv   V\n\terr error\n}\n\n// cacheFunc is the type of a future computation function.\ntype cacheFunc[V any] func(context.Context) (V, error)\n\n// get retrieves or computes the value corresponding to k.\n//\n// If the cache if persistent and the value has already been computed, get\n// returns the result of the previous computation. Otherwise, get either starts\n// a computation or joins an ongoing computation. If that computation is\n// cancelled, get will reassign the computation to a new goroutine as long as\n// there are awaiters.\n//\n// Once the computation completes, the result is passed to all awaiting\n// goroutines. If the cache is transient (persistent=false), the corresponding\n// cache entry is removed, and the next call to get will execute a new\n// computation.\n//\n// It is therefore the responsibility of the caller to ensure that the given\n// compute function is safely retryable, and always returns the same value.\nfunc (c *futureCache[K, V]) get(ctx context.Context, k K, compute cacheFunc[V]) (V, error) {\n\tc.mu.Lock()\n\tf, ok := c.cache[k]\n\tif !ok {\n\t\tf = &future[V]{\n\t\t\tdone:    make(chan unit),\n\t\t\tacquire: make(chan unit, 1),\n\t\t}\n\t\tf.acquire <- unit{} // make available for computation\n\t\tc.cache[k] = f\n\t}\n\tf.refs++\n\tc.mu.Unlock()\n\n\tdefer func() {\n\t\tc.mu.Lock()\n\t\tdefer c.mu.Unlock()\n\t\tf.refs--\n\t\tif f.refs == 0 && !c.persistent {\n\t\t\tdelete(c.cache, k)\n\t\t}\n\t}()\n\n\tvar zero V\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn zero, ctx.Err()\n\tcase <-f.done:\n\t\treturn f.v, f.err\n\tcase <-f.acquire:\n\t}\n\n\tv, err := compute(ctx)\n\tif err := ctx.Err(); err != nil {\n\t\tf.acquire <- unit{} // hand off work to the next requester\n\t\treturn zero, err\n\t}\n\n\tf.v = v\n\tf.err = err\n\tclose(f.done)\n\treturn v, err\n}\n"
  },
  {
    "path": "gopls/internal/cache/future_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n)\n\nfunc TestFutureCache_Persistent(t *testing.T) {\n\tc := newFutureCache[int, int](true)\n\tctx := context.Background()\n\n\tvar computed atomic.Int32\n\tcompute := func(i int) cacheFunc[int] {\n\t\treturn func(context.Context) (int, error) {\n\t\t\tcomputed.Add(1)\n\t\t\treturn i, ctx.Err()\n\t\t}\n\t}\n\n\ttestFutureCache(t, ctx, c, compute)\n\n\t// Since this cache is persistent, we should get exactly 10 computations,\n\t// since there are 10 distinct keys in [testFutureCache].\n\tif got := computed.Load(); got != 10 {\n\t\tt.Errorf(\"computed %d times, want 10\", got)\n\t}\n}\n\nfunc TestFutureCache_Ephemeral(t *testing.T) {\n\tc := newFutureCache[int, int](false)\n\tctx := context.Background()\n\n\tvar computed atomic.Int32\n\tcompute := func(i int) cacheFunc[int] {\n\t\treturn func(context.Context) (int, error) {\n\t\t\ttime.Sleep(1 * time.Millisecond)\n\t\t\tcomputed.Add(1)\n\t\t\treturn i, ctx.Err()\n\t\t}\n\t}\n\n\ttestFutureCache(t, ctx, c, compute)\n\n\t// Since this cache is ephemeral, we should get at least 30 computations,\n\t// since there are 10 distinct keys and three synchronous passes in\n\t// [testFutureCache].\n\tif got := computed.Load(); got < 30 {\n\t\tt.Errorf(\"computed %d times, want at least 30\", got)\n\t} else {\n\t\tt.Logf(\"compute ran %d times\", got)\n\t}\n}\n\n// testFutureCache starts 100 goroutines concurrently, indexed by j, each\n// getting key j%10 from the cache. It repeats this three times, synchronizing\n// after each.\n//\n// This is designed to exercise both concurrent and synchronous access to the\n// cache.\nfunc testFutureCache(t *testing.T, ctx context.Context, c *futureCache[int, int], compute func(int) cacheFunc[int]) {\n\tfor range 3 {\n\t\tvar g errgroup.Group\n\t\tfor j := range 100 {\n\t\t\tmod := j % 10\n\t\t\tcompute := compute(mod)\n\t\t\tg.Go(func() error {\n\t\t\t\tgot, err := c.get(ctx, mod, compute)\n\t\t\t\tif err == nil && got != mod {\n\t\t\t\t\tt.Errorf(\"get() = %d, want %d\", got, mod)\n\t\t\t\t}\n\t\t\t\treturn err\n\t\t\t})\n\t\t}\n\t\tif err := g.Wait(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestFutureCache_Retrying(t *testing.T) {\n\t// This test verifies the retry behavior of cache entries,\n\t// by checking that cancelled work is handed off to the next awaiter.\n\t//\n\t// The setup is a little tricky: 10 goroutines are started, and the first 9\n\t// are cancelled whereas the 10th is allowed to finish. As a result, the\n\t// computation should always succeed with value 9.\n\n\tctx := context.Background()\n\n\tfor _, persistent := range []bool{true, false} {\n\t\tt.Run(fmt.Sprintf(\"persistent=%t\", persistent), func(t *testing.T) {\n\t\t\tc := newFutureCache[int, int](persistent)\n\n\t\t\tvar started atomic.Int32\n\n\t\t\t// compute returns a new cacheFunc that produces the value i, after the\n\t\t\t// provided done channel is closed.\n\t\t\tcompute := func(i int, done <-chan struct{}) cacheFunc[int] {\n\t\t\t\treturn func(ctx context.Context) (int, error) {\n\t\t\t\t\tstarted.Add(1)\n\t\t\t\t\tselect {\n\t\t\t\t\tcase <-ctx.Done():\n\t\t\t\t\t\treturn 0, ctx.Err()\n\t\t\t\t\tcase <-done:\n\t\t\t\t\t\treturn i, nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// goroutines are either cancelled, or allowed to complete,\n\t\t\t// as controlled by cancels and dones.\n\t\t\tvar (\n\t\t\t\tcancels = make([]func(), 10)\n\t\t\t\tdones   = make([]chan struct{}, 10)\n\t\t\t)\n\n\t\t\tvar g errgroup.Group\n\t\t\tvar lastValue atomic.Int32 // keep track of the last successfully computed value\n\t\t\tfor i := range 10 {\n\t\t\t\tctx, cancel := context.WithCancel(ctx)\n\t\t\t\tdone := make(chan struct{})\n\t\t\t\tcancels[i] = cancel\n\t\t\t\tdones[i] = done\n\t\t\t\tcompute := compute(i, done)\n\t\t\t\tg.Go(func() error {\n\t\t\t\t\tv, err := c.get(ctx, 0, compute)\n\t\t\t\t\tif err == nil {\n\t\t\t\t\t\tlastValue.Store(int32(v))\n\t\t\t\t\t}\n\t\t\t\t\treturn nil\n\t\t\t\t})\n\t\t\t}\n\t\t\tfor _, cancel := range cancels[:9] {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\tdefer cancels[9]()\n\n\t\t\tdones[9] <- struct{}{}\n\t\t\t_ = g.Wait() // can't fail\n\n\t\t\tt.Logf(\"started %d computations\", started.Load())\n\t\t\tif got := lastValue.Load(); got != 9 {\n\t\t\t\tt.Errorf(\"after cancelling computation 0-8, got %d, want 9\", got)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/imports.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/modindex\"\n)\n\n// refreshTimer implements delayed asynchronous refreshing of state.\n//\n// See the [refreshTimer.schedule] documentation for more details.\ntype refreshTimer struct {\n\tmu        sync.Mutex\n\tduration  time.Duration\n\ttimer     *time.Timer\n\trefreshFn func()\n}\n\n// newRefreshTimer constructs a new refresh timer which schedules refreshes\n// using the given function.\nfunc newRefreshTimer(refresh func()) *refreshTimer {\n\treturn &refreshTimer{\n\t\trefreshFn: refresh,\n\t}\n}\n\n// stop stops any future scheduled refresh.\nfunc (t *refreshTimer) stop() {\n\tt.mu.Lock()\n\tdefer t.mu.Unlock()\n\n\tif t.timer != nil {\n\t\tt.timer.Stop()\n\t\tt.timer = nil\n\t\tt.refreshFn = nil // release resources\n\t}\n}\n\n// schedule schedules the refresh function to run at some point in the future,\n// if no existing refresh is already scheduled.\n//\n// At a minimum, scheduled refreshes are delayed by 30s, but they may be\n// delayed longer to keep their expected execution time under 2% of wall clock\n// time.\nfunc (t *refreshTimer) schedule() {\n\tt.mu.Lock()\n\tdefer t.mu.Unlock()\n\n\tif t.timer == nil {\n\t\t// Don't refresh more than twice per minute.\n\t\t// Don't spend more than ~2% of the time refreshing.\n\t\tdelay := max(30*time.Second, 50*t.duration)\n\t\tt.timer = time.AfterFunc(delay, func() {\n\t\t\tstart := time.Now()\n\t\t\tt.mu.Lock()\n\t\t\trefreshFn := t.refreshFn\n\t\t\tt.mu.Unlock()\n\t\t\tif refreshFn != nil { // timer may be stopped.\n\t\t\t\trefreshFn()\n\t\t\t\tt.mu.Lock()\n\t\t\t\tt.duration = time.Since(start)\n\t\t\t\tt.timer = nil\n\t\t\t\tt.mu.Unlock()\n\t\t\t}\n\t\t})\n\t}\n}\n\n// A sharedModCache tracks goimports state for GOMODCACHE directories\n// (each session may have its own GOMODCACHE).\n//\n// This state is refreshed independently of view-specific imports state.\ntype sharedModCache struct {\n\tmu     sync.Mutex\n\tcaches map[string]*imports.DirInfoCache // GOMODCACHE -> cache content; never invalidated\n\t// TODO(rfindley): consider stopping these timers when the session shuts down.\n\ttimers map[string]*refreshTimer // GOMODCACHE -> timer\n}\n\nfunc (c *sharedModCache) dirCache(dir string) *imports.DirInfoCache {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tcache, ok := c.caches[dir]\n\tif !ok {\n\t\tcache = imports.NewDirInfoCache()\n\t\tc.caches[dir] = cache\n\t}\n\treturn cache\n}\n\n// refreshDir schedules a refresh of the given directory, which must be a\n// module cache.\nfunc (c *sharedModCache) refreshDir(ctx context.Context, dir string, logf func(string, ...any)) {\n\tcache := c.dirCache(dir)\n\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\ttimer, ok := c.timers[dir]\n\tif !ok {\n\t\ttimer = newRefreshTimer(func() {\n\t\t\t_, done := event.Start(ctx, \"cache.sharedModCache.refreshDir\", label.Directory.Of(dir))\n\t\t\tdefer done()\n\t\t\timports.ScanModuleCache(dir, cache, logf)\n\t\t})\n\t\tc.timers[dir] = timer\n\t}\n\n\ttimer.schedule()\n}\n\n// importsState tracks view-specific imports state.\ntype importsState struct {\n\tctx          context.Context\n\tmodCache     *sharedModCache\n\trefreshTimer *refreshTimer\n\n\tmu                sync.Mutex\n\tprocessEnv        *imports.ProcessEnv\n\tcachedModFileHash file.Hash\n}\n\n// newImportsState constructs a new imports state for running goimports\n// functions via [runProcessEnvFunc].\n//\n// The returned state will automatically refresh itself following a delay.\nfunc newImportsState(backgroundCtx context.Context, modCache *sharedModCache, env *imports.ProcessEnv) *importsState {\n\ts := &importsState{\n\t\tctx:        backgroundCtx,\n\t\tmodCache:   modCache,\n\t\tprocessEnv: env,\n\t}\n\ts.refreshTimer = newRefreshTimer(s.refreshProcessEnv)\n\ts.refreshTimer.schedule()\n\treturn s\n}\n\n// modcacheState holds a modindex.Index and controls its updates\ntype modcacheState struct {\n\tgomodcache   string\n\trefreshTimer *refreshTimer\n\n\t// (index, indexErr) is zero in the initial state.\n\t// Thereafter they hold the memoized result pair for getIndex.\n\tmu       sync.Mutex\n\tindex    *modindex.Index\n\tindexErr error\n}\n\n// newModcacheState constructs a new modcacheState for goimports.\n// The returned state is automatically updated until [modcacheState.stopTimer] is called.\nfunc newModcacheState(gomodcache string) *modcacheState {\n\ts := &modcacheState{\n\t\tgomodcache: gomodcache,\n\t}\n\ts.refreshTimer = newRefreshTimer(s.refreshIndex)\n\tgo s.refreshIndex()\n\treturn s\n}\n\n// getIndex reads the module cache index.\nfunc (s *modcacheState) getIndex() (*modindex.Index, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif s.index == nil && s.indexErr == nil {\n\t\t// getIndex was called before refreshIndex finished.\n\t\t// Read, but don't update, whatever index is present.\n\t\ts.index, s.indexErr = modindex.Read(s.gomodcache)\n\t}\n\n\treturn s.index, s.indexErr\n}\n\nfunc (s *modcacheState) refreshIndex() {\n\tindex, err := modindex.Update(s.gomodcache)\n\ts.mu.Lock()\n\tif err != nil {\n\t\tif s.indexErr != nil {\n\t\t\ts.indexErr = err // prefer most recent error\n\t\t} else if s.index != nil {\n\t\t\t// Keep using stale s.index.\n\t\t\tlog.Printf(\"modcacheState.refreshIndex: %v\", err)\n\t\t}\n\t} else {\n\t\ts.index, s.indexErr = index, nil // success\n\t}\n\ts.mu.Unlock()\n}\n\nfunc (s *modcacheState) stopTimer() {\n\ts.refreshTimer.stop()\n}\n\n// stopTimer stops scheduled refreshes of this imports state.\nfunc (s *importsState) stopTimer() {\n\ts.refreshTimer.stop()\n}\n\n// runProcessEnvFunc runs goimports.\n//\n// Any call to runProcessEnvFunc will schedule a refresh of the imports state\n// at some point in the future, if such a refresh is not already scheduled. See\n// [refreshTimer] for more details.\nfunc (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *Snapshot, fn func(context.Context, *imports.Options) error) error {\n\tctx, done := event.Start(ctx, \"cache.importsState.runProcessEnvFunc\")\n\tdefer done()\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\t// Find the hash of active mod files, if any. Using the unsaved content\n\t// is slightly wasteful, since we'll drop caches a little too often, but\n\t// the mod file shouldn't be changing while people are autocompleting.\n\t//\n\t// TODO(rfindley): consider instead hashing on-disk modfiles here.\n\tvar modFileHash file.Hash\n\tfor m := range snapshot.view.workspaceModFiles {\n\t\tfh, err := snapshot.ReadFile(ctx, m)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tmodFileHash.XORWith(fh.Identity().Hash)\n\t}\n\n\t// If anything relevant to imports has changed, clear caches and\n\t// update the processEnv. Clearing caches blocks on any background\n\t// scans.\n\tif modFileHash != s.cachedModFileHash {\n\t\ts.processEnv.ClearModuleInfo()\n\t\ts.cachedModFileHash = modFileHash\n\t}\n\n\t// Run the user function.\n\topts := &imports.Options{\n\t\t// Defaults.\n\t\tAllErrors:   true,\n\t\tComments:    true,\n\t\tFragment:    true,\n\t\tFormatOnly:  false,\n\t\tTabIndent:   true,\n\t\tTabWidth:    8,\n\t\tEnv:         s.processEnv,\n\t\tLocalPrefix: snapshot.Options().Local,\n\t}\n\n\tif err := fn(ctx, opts); err != nil {\n\t\treturn err\n\t}\n\n\t// Refresh the imports resolver after usage. This may seem counterintuitive,\n\t// since it means the first ProcessEnvFunc after a long period of inactivity\n\t// may be stale, but in practice we run ProcessEnvFuncs frequently during\n\t// active development (e.g. during completion), and so this mechanism will be\n\t// active while gopls is in use, and inactive when gopls is idle.\n\ts.refreshTimer.schedule()\n\n\t// TODO(rfindley): the GOMODCACHE value used here isn't directly tied to the\n\t// ProcessEnv.Env[\"GOMODCACHE\"], though they should theoretically always\n\t// agree. It would be better if we guaranteed this, possibly by setting all\n\t// required environment variables in ProcessEnv.Env, to avoid the redundant\n\t// Go command invocation.\n\tgomodcache := snapshot.view.folder.Env.GOMODCACHE\n\ts.modCache.refreshDir(s.ctx, gomodcache, s.processEnv.Logf)\n\n\treturn nil\n}\n\nfunc (s *importsState) refreshProcessEnv() {\n\tctx, done := event.Start(s.ctx, \"cache.importsState.refreshProcessEnv\")\n\tdefer done()\n\n\tstart := time.Now()\n\n\ts.mu.Lock()\n\tresolver, err := s.processEnv.GetResolver()\n\ts.mu.Unlock()\n\tif err != nil {\n\t\tevent.Error(s.ctx, \"failed to get import resolver\", err)\n\t\treturn\n\t}\n\n\tevent.Log(s.ctx, \"background imports cache refresh starting\")\n\tresolver2 := resolver.ClearForNewScan()\n\n\t// Prime the new resolver before updating the processEnv, so that gopls\n\t// doesn't wait on an unprimed cache.\n\tif err := imports.PrimeCache(context.Background(), resolver2); err == nil {\n\t\tevent.Log(ctx, fmt.Sprintf(\"background refresh finished after %v\", time.Since(start)))\n\t} else {\n\t\tevent.Log(ctx, fmt.Sprintf(\"background refresh finished after %v\", time.Since(start)), keys.Err.Of(err))\n\t}\n\n\ts.mu.Lock()\n\ts.processEnv.UpdateResolver(resolver2)\n\ts.mu.Unlock()\n}\n"
  },
  {
    "path": "gopls/internal/cache/keys.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\n// session event tracing\n\nimport (\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nvar (\n\tKeyCreateSession   = NewSessionKey(\"create_session\", \"A new session was added\")\n\tKeyUpdateSession   = NewSessionKey(\"update_session\", \"Updated information about a session\")\n\tKeyShutdownSession = NewSessionKey(\"shutdown_session\", \"A session was shut down\")\n)\n\n// SessionKey represents an event label key that has a *Session value.\ntype SessionKey struct {\n\tname        string\n\tdescription string\n}\n\n// NewSessionKey creates a new Key for *Session values.\nfunc NewSessionKey(name, description string) *SessionKey {\n\treturn &SessionKey{name: name, description: description}\n}\n\nfunc (k *SessionKey) Name() string        { return k.name }\nfunc (k *SessionKey) Description() string { return k.description }\n\nfunc (k *SessionKey) Append(buf []byte, l label.Label) []byte {\n\treturn append(buf, k.From(l).ID()...)\n}\n\n// Of creates a new Label with this key and the supplied session.\nfunc (k *SessionKey) Of(v *Session) label.Label { return label.OfValue(k, v) }\n\n// Get can be used to get the session for the key from a label.Map.\nfunc (k *SessionKey) Get(lm label.Map) *Session {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn nil\n}\n\n// From can be used to get the session value from a Label.\nfunc (k *SessionKey) From(t label.Label) *Session {\n\terr, _ := t.UnpackValue().(*Session)\n\treturn err\n}\n"
  },
  {
    "path": "gopls/internal/cache/load.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/immutable\"\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\nvar loadID uint64 // atomic identifier for loads\n\n// errNoPackages indicates that a load query matched no packages.\nvar errNoPackages = errors.New(\"no packages returned\")\n\n// load calls packages.Load for the given scopes, updating package metadata,\n// import graph, and mapped files with the result.\n//\n// The resulting error may wrap the moduleErrorMap error type, representing\n// errors associated with specific modules.\n//\n// If scopes contains a file scope there must be exactly one scope.\nfunc (s *Snapshot) load(ctx context.Context, allowNetwork AllowNetwork, scopes ...loadScope) (err error) {\n\tif ctx.Err() != nil {\n\t\t// Check context cancellation before incrementing id below: a load on a\n\t\t// cancelled context should be a no-op.\n\t\treturn ctx.Err()\n\t}\n\tid := atomic.AddUint64(&loadID, 1)\n\teventName := fmt.Sprintf(\"go/packages.Load #%d\", id) // unique name for logging\n\n\tvar query []string\n\tvar standalone bool // whether this is a load of a standalone file\n\n\t// Keep track of module query -> module path so that we can later correlate query\n\t// errors with errors.\n\tmoduleQueries := make(map[string]string)\n\n\tfor _, scope := range scopes {\n\t\tswitch scope := scope.(type) {\n\t\tcase packageLoadScope:\n\t\t\t// The only time we pass package paths is when we're doing a\n\t\t\t// partial workspace load. In those cases, the paths came back from\n\t\t\t// go list and should already be GOPATH-vendorized when appropriate.\n\t\t\tquery = append(query, string(scope))\n\n\t\tcase fileLoadScope:\n\t\t\t// Given multiple scopes, the resulting load might contain inaccurate\n\t\t\t// information. For example go/packages returns at most one command-line\n\t\t\t// arguments package, and does not handle a combination of standalone\n\t\t\t// files and packages.\n\t\t\turi := protocol.DocumentURI(scope)\n\t\t\tif len(scopes) > 1 {\n\t\t\t\tpanic(fmt.Sprintf(\"internal error: load called with multiple scopes when a file scope is present (file: %s)\", uri))\n\t\t\t}\n\t\t\tfh, err := s.ReadFile(ctx, uri)\n\t\t\tif err != nil || fh == nil || s.FileKind(fh) != file.Go {\n\t\t\t\t// Don't try to load a file that doesn't exist, or isn't a go file.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcontents, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif isStandaloneFile(contents, s.Options().StandaloneTags) {\n\t\t\t\tstandalone = true\n\t\t\t\tquery = append(query, uri.Path())\n\t\t\t} else {\n\t\t\t\tquery = append(query, fmt.Sprintf(\"file=%s\", uri.Path()))\n\t\t\t}\n\n\t\tcase moduleLoadScope:\n\t\t\tmodQuery := fmt.Sprintf(\"%s%c...\", scope.dir, filepath.Separator)\n\t\t\tquery = append(query, modQuery)\n\t\t\tmoduleQueries[modQuery] = scope.modulePath\n\n\t\tcase viewLoadScope:\n\t\t\t// If we are outside of GOPATH, a module, or some other known\n\t\t\t// build system, don't load subdirectories.\n\t\t\tif s.view.typ == AdHocView {\n\t\t\t\tquery = append(query, \"./\")\n\t\t\t} else {\n\t\t\t\tquery = append(query, \"./...\")\n\t\t\t}\n\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unknown scope type %T\", scope))\n\t\t}\n\t}\n\tif len(query) == 0 {\n\t\treturn nil\n\t}\n\tsort.Strings(query) // for determinism\n\n\tctx, done := event.Start(ctx, \"cache.snapshot.load\", label.Query.Of(query))\n\tdefer done()\n\n\tstartTime := time.Now()\n\n\t// Set a last resort deadline on packages.Load since it calls the go\n\t// command, which may hang indefinitely if it has a bug. golang/go#42132\n\t// and golang/go#42255 have more context.\n\tctx, cancel := context.WithTimeout(ctx, 10*time.Minute)\n\tdefer cancel()\n\n\tcfg := s.config(ctx, allowNetwork)\n\tpkgs, err := packages.Load(cfg, query...)\n\n\t// If the context was canceled, return early. Otherwise, we might be\n\t// type-checking an incomplete result. Check the context directly,\n\t// because go/packages adds extra information to the error.\n\tif ctx.Err() != nil {\n\t\treturn ctx.Err()\n\t}\n\n\t// This log message is sought for by TestReloadOnlyOnce.\n\t{\n\t\tlbls := append(s.Labels(),\n\t\t\tlabel.Query.Of(query),\n\t\t\tlabel.PackageCount.Of(len(pkgs)),\n\t\t\tlabel.Duration.Of(time.Since(startTime)),\n\t\t)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, eventName, err, lbls...)\n\t\t} else {\n\t\t\tevent.Log(ctx, eventName, lbls...)\n\t\t}\n\t}\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"packages.Load error: %w\", err)\n\t}\n\n\tif standalone {\n\t\t// Handle standalone package result.\n\t\t//\n\t\t// In general, this should just be a single \"command-line-arguments\"\n\t\t// package containing the requested file. However, if the file is a test\n\t\t// file, go/packages may return test variants of the command-line-arguments\n\t\t// package. We don't support this; theoretically we could, but it seems\n\t\t// unnecessarily complicated.\n\t\t//\n\t\t// It's possible that we get no packages here, for example if the file is a\n\t\t// cgo file and cgo is not enabled.\n\t\tvar standalonePkg *packages.Package\n\t\tfor _, pkg := range pkgs {\n\t\t\tif pkg.ID == \"command-line-arguments\" {\n\t\t\t\tif standalonePkg != nil {\n\t\t\t\t\treturn fmt.Errorf(\"go/packages returned multiple standalone packages\")\n\t\t\t\t}\n\t\t\t\tstandalonePkg = pkg\n\t\t\t} else if pkg.ForTest == \"\" && !strings.HasSuffix(pkg.ID, \".test\") {\n\t\t\t\treturn fmt.Errorf(\"go/packages returned unexpected package %q for standalone file\", pkg.ID)\n\t\t\t}\n\t\t}\n\t\tif standalonePkg == nil {\n\t\t\treturn fmt.Errorf(\"go/packages failed to return non-test standalone package\")\n\t\t}\n\t\tif len(standalonePkg.CompiledGoFiles) > 0 {\n\t\t\tpkgs = []*packages.Package{standalonePkg}\n\t\t} else {\n\t\t\tpkgs = nil\n\t\t}\n\t}\n\n\tif len(pkgs) == 0 {\n\t\treturn fmt.Errorf(\"packages.Load error: %w\", errNoPackages)\n\t}\n\n\tmoduleErrs := make(map[string][]packages.Error) // module path -> errors\n\tfilterFunc := s.view.filterFunc()\n\tnewMetadata := make(map[PackageID]*metadata.Package)\n\tfor _, pkg := range pkgs {\n\t\tif pkg.Module != nil && strings.Contains(pkg.Module.Path, \"command-line-arguments\") {\n\t\t\t// golang/go#61543: modules containing \"command-line-arguments\" cause\n\t\t\t// gopls to get all sorts of confused, because anything containing the\n\t\t\t// string \"command-line-arguments\" is treated as a script. And yes, this\n\t\t\t// happened in practice! (https://xkcd.com/327). Rather than try to work\n\t\t\t// around this very rare edge case, just fail loudly.\n\t\t\treturn fmt.Errorf(`load failed: module name in %s contains \"command-line-arguments\", which is disallowed`, pkg.Module.GoMod)\n\t\t}\n\t\t// The Go command returns synthetic list results for module queries that\n\t\t// encountered module errors.\n\t\t//\n\t\t// For example, given a module path a.mod, we'll query for \"a.mod/...\" and\n\t\t// the go command will return a package named \"a.mod/...\" holding this\n\t\t// error. Save it for later interpretation.\n\t\t//\n\t\t// See golang/go#50862 for more details.\n\t\tif mod := moduleQueries[pkg.PkgPath]; mod != \"\" { // a synthetic result for the unloadable module\n\t\t\tif len(pkg.Errors) > 0 {\n\t\t\t\tmoduleErrs[mod] = pkg.Errors\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif s.Options().VerboseOutput {\n\t\t\tevent.Log(ctx, eventName, append(\n\t\t\t\ts.Labels(),\n\t\t\t\tlabel.Package.Of(pkg.ID),\n\t\t\t\tlabel.Files.Of(pkg.CompiledGoFiles))...)\n\t\t}\n\n\t\t// Ignore packages with no sources, since we will never be able to\n\t\t// correctly invalidate that metadata.\n\t\tif len(pkg.GoFiles) == 0 && len(pkg.CompiledGoFiles) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// Special case for the builtin package, as it has no dependencies.\n\t\tif pkg.PkgPath == \"builtin\" {\n\t\t\tif len(pkg.GoFiles) != 1 {\n\t\t\t\treturn fmt.Errorf(\"only expected 1 file for builtin, got %v\", len(pkg.GoFiles))\n\t\t\t}\n\t\t\ts.setBuiltin(pkg.GoFiles[0])\n\t\t\tcontinue\n\t\t}\n\t\tif pkg.ForTest == \"builtin\" {\n\t\t\t// We don't care about test variants of builtin. This caused test\n\t\t\t// failures in https://go.dev/cl/620196, when a test file was added to\n\t\t\t// builtin.\n\t\t\tcontinue\n\t\t}\n\t\t// Skip test main packages.\n\t\tif isTestMain(pkg, s.view.folder.Env.GOCACHE) {\n\t\t\tcontinue\n\t\t}\n\t\t// Skip filtered packages. They may be added anyway if they're\n\t\t// dependencies of non-filtered packages.\n\t\t//\n\t\t// TODO(rfindley): why exclude metadata arbitrarily here? It should be safe\n\t\t// to capture all metadata.\n\t\t// TODO(rfindley): what about compiled go files?\n\t\tif allFilesExcluded(pkg.GoFiles, filterFunc) {\n\t\t\tcontinue\n\t\t}\n\t\tbuildMetadata(newMetadata, cfg.Dir, standalone, pkg)\n\t}\n\n\ts.mu.Lock()\n\n\t// Assert the invariant s.packages.Get(id).m == s.meta.metadata[id].\n\tfor id, ph := range s.packages.All() {\n\t\tif s.meta.Packages[id] != ph.mp {\n\t\t\tpanic(\"inconsistent metadata\")\n\t\t}\n\t}\n\n\t// Compute the minimal metadata updates (for Clone)\n\t// required to preserve the above invariant.\n\tvar files []protocol.DocumentURI // files to preload\n\tseenFiles := make(map[protocol.DocumentURI]bool)\n\tupdates := make(map[PackageID]*metadata.Package)\n\tfor _, mp := range newMetadata {\n\t\tif existing := s.meta.Packages[mp.ID]; existing == nil {\n\t\t\t// Record any new files we should pre-load.\n\t\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\t\tif !seenFiles[uri] {\n\t\t\t\t\tseenFiles[uri] = true\n\t\t\t\t\tfiles = append(files, uri)\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdates[mp.ID] = mp\n\t\t\ts.shouldLoad.Delete(mp.ID)\n\t\t}\n\t}\n\n\tif s.Options().VerboseOutput {\n\t\tevent.Log(ctx, fmt.Sprintf(\"%s: updating metadata for %d packages\", eventName, len(updates)))\n\t}\n\n\tmeta := s.meta.Update(updates)\n\tworkspacePackages := computeWorkspacePackagesLocked(ctx, s, meta)\n\ts.meta = meta\n\ts.workspacePackages = workspacePackages\n\n\ts.mu.Unlock()\n\n\t// Opt: preLoad files in parallel.\n\t//\n\t// Requesting files in batch optimizes the underlying filesystem reads.\n\t// However, this is also currently necessary for correctness: populating all\n\t// files in the snapshot is necessary for certain operations that rely on the\n\t// completeness of the file map, e.g. computing the set of directories to\n\t// watch.\n\t//\n\t// TODO(rfindley, golang/go#57558): determine the set of directories based on\n\t// loaded packages, so that reading files here is not necessary for\n\t// correctness.\n\ts.preloadFiles(ctx, files)\n\n\tif len(moduleErrs) > 0 {\n\t\treturn &moduleErrorMap{moduleErrs}\n\t}\n\n\treturn nil\n}\n\ntype moduleErrorMap struct {\n\terrs map[string][]packages.Error // module path -> errors\n}\n\nfunc (m *moduleErrorMap) Error() string {\n\tvar paths []string // sort for stability\n\tfor path, errs := range m.errs {\n\t\tif len(errs) > 0 { // should always be true, but be cautious\n\t\t\tpaths = append(paths, path)\n\t\t}\n\t}\n\tsort.Strings(paths)\n\n\tvar buf bytes.Buffer\n\tfmt.Fprintf(&buf, \"%d modules have errors:\\n\", len(paths))\n\tfor _, path := range paths {\n\t\tfmt.Fprintf(&buf, \"\\t%s:%s\\n\", path, m.errs[path][0].Msg)\n\t}\n\n\treturn buf.String()\n}\n\n// config returns the configuration used for the snapshot's interaction with\n// the go/packages API. It uses the given working directory.\n//\n// TODO(rstambler): go/packages requires that we do not provide overlays for\n// multiple modules in one config, so buildOverlay needs to filter overlays by\n// module.\n// TODO(rfindley): ^^ is this still true?\nfunc (s *Snapshot) config(ctx context.Context, allowNetwork AllowNetwork) *packages.Config {\n\tcfg := &packages.Config{\n\t\tContext:    ctx,\n\t\tDir:        s.view.root.Path(),\n\t\tEnv:        s.view.Env(),\n\t\tBuildFlags: slices.Clone(s.view.folder.Options.BuildFlags),\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedCompiledGoFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedTypesSizes |\n\t\t\tpackages.NeedModule |\n\t\t\tpackages.NeedEmbedFiles |\n\t\t\tpackages.LoadMode(packagesinternal.DepsErrors) |\n\t\t\tpackages.NeedForTest,\n\t\tFset:    nil, // we do our own parsing\n\t\tOverlay: s.buildOverlays(),\n\t\tLogf: func(format string, args ...any) {\n\t\t\tif s.view.folder.Options.VerboseOutput {\n\t\t\t\tevent.Log(ctx, fmt.Sprintf(format, args...))\n\t\t\t}\n\t\t},\n\t\tTests: true,\n\t}\n\tif !allowNetwork {\n\t\tcfg.Env = append(cfg.Env, \"GOPROXY=off\")\n\t}\n\t// We want to type check cgo code if go/types supports it.\n\tif typesinternal.SetUsesCgo(&types.Config{}) {\n\t\tcfg.Mode |= packages.LoadMode(packagesinternal.TypecheckCgo)\n\t}\n\treturn cfg\n}\n\n// buildMetadata populates the updates map with metadata updates to\n// apply, based on the given pkg. It recurs through pkg.Imports to ensure that\n// metadata exists for all dependencies.\n//\n// Returns the metadata.Package that was built (or which was already present in\n// updates), or nil if the package could not be built. Notably, the resulting\n// metadata.Package may have an ID that differs from pkg.ID.\nfunc buildMetadata(updates map[PackageID]*metadata.Package, loadDir string, standalone bool, pkg *packages.Package) *metadata.Package {\n\t// Allow for multiple ad-hoc packages in the workspace (see #47584).\n\tpkgPath := PackagePath(pkg.PkgPath)\n\tid := PackageID(pkg.ID)\n\n\tif metadata.IsCommandLineArguments(id) {\n\t\tvar f string // file to use as disambiguating suffix\n\t\tif len(pkg.GoFiles) > 0 {\n\t\t\tf = pkg.GoFiles[0]\n\n\t\t\t// If there are multiple files, we can't use only the first. Note that we\n\t\t\t// consider GoFiles, rather than CompiledGoFiles, as there can be\n\t\t\t// multiple CompiledGoFiles in the presence of cgo processing, whereas a\n\t\t\t// command-line-arguments package should always have exactly one nominal\n\t\t\t// Go source file. (See golang/go#64557.)\n\t\t\tif len(pkg.GoFiles) > 1 {\n\t\t\t\tbug.Reportf(\"unexpected files in command-line-arguments package: %v\", pkg.GoFiles)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t} else if len(pkg.IgnoredFiles) > 0 {\n\t\t\t// A file=empty.go query results in IgnoredFiles=[empty.go].\n\t\t\tf = pkg.IgnoredFiles[0]\n\t\t} else {\n\t\t\tbug.Reportf(\"command-line-arguments package has neither GoFiles nor IgnoredFiles\")\n\t\t\treturn nil\n\t\t}\n\t\tid = PackageID(pkg.ID + f)\n\t\tpkgPath = PackagePath(pkg.PkgPath + f)\n\t}\n\n\t// Duplicate?\n\tif existing, ok := updates[id]; ok {\n\t\t// A package was encountered twice due to shared\n\t\t// subgraphs (common) or cycles (rare). Although \"go\n\t\t// list\" usually breaks cycles, we don't rely on it.\n\t\t// breakImportCycles in metadataGraph.Clone takes care\n\t\t// of it later.\n\t\treturn existing\n\t}\n\n\tif pkg.TypesSizes == nil {\n\t\tpanic(id + \".TypeSizes is nil\")\n\t}\n\n\t// Recreate the metadata rather than reusing it to avoid locking.\n\tmp := &metadata.Package{\n\t\tID:         id,\n\t\tPkgPath:    pkgPath,\n\t\tName:       PackageName(pkg.Name),\n\t\tForTest:    PackagePath(pkg.ForTest),\n\t\tTypesSizes: pkg.TypesSizes,\n\t\tLoadDir:    loadDir,\n\t\tModule:     pkg.Module,\n\t\tErrors:     pkg.Errors,\n\t\tDepsErrors: packagesinternal.GetDepsErrors(pkg),\n\t\tStandalone: standalone,\n\t}\n\n\tupdates[id] = mp\n\n\tcopyURIs := func(dst *[]protocol.DocumentURI, src []string) {\n\t\tfor _, filename := range src {\n\t\t\t*dst = append(*dst, protocol.URIFromPath(filename))\n\t\t}\n\t}\n\tcopyURIs(&mp.CompiledGoFiles, pkg.CompiledGoFiles)\n\tcopyURIs(&mp.GoFiles, pkg.GoFiles)\n\tcopyURIs(&mp.IgnoredFiles, pkg.IgnoredFiles)\n\tcopyURIs(&mp.OtherFiles, pkg.OtherFiles)\n\n\tdepsByImpPath := make(map[ImportPath]PackageID)\n\tdepsByPkgPath := make(map[PackagePath]PackageID)\n\tfor importPath, imported := range pkg.Imports {\n\t\timportPath := ImportPath(importPath)\n\n\t\t// It is not an invariant that importPath == imported.PkgPath.\n\t\t// For example, package \"net\" imports \"golang.org/x/net/dns/dnsmessage\"\n\t\t// which refers to the package whose ID and PkgPath are both\n\t\t// \"vendor/golang.org/x/net/dns/dnsmessage\". Notice the ImportMap,\n\t\t// which maps ImportPaths to PackagePaths:\n\t\t//\n\t\t// $ go list -json net vendor/golang.org/x/net/dns/dnsmessage\n\t\t// {\n\t\t// \t\"ImportPath\": \"net\",\n\t\t// \t\"Name\": \"net\",\n\t\t// \t\"Imports\": [\n\t\t// \t\t\"C\",\n\t\t// \t\t\"vendor/golang.org/x/net/dns/dnsmessage\",\n\t\t// \t\t\"vendor/golang.org/x/net/route\",\n\t\t// \t\t...\n\t\t// \t],\n\t\t// \t\"ImportMap\": {\n\t\t// \t\t\"golang.org/x/net/dns/dnsmessage\": \"vendor/golang.org/x/net/dns/dnsmessage\",\n\t\t// \t\t\"golang.org/x/net/route\": \"vendor/golang.org/x/net/route\"\n\t\t// \t},\n\t\t//      ...\n\t\t// }\n\t\t// {\n\t\t// \t\"ImportPath\": \"vendor/golang.org/x/net/dns/dnsmessage\",\n\t\t// \t\"Name\": \"dnsmessage\",\n\t\t//      ...\n\t\t// }\n\t\t//\n\t\t// (Beware that, for historical reasons, go list uses\n\t\t// the JSON field \"ImportPath\" for the package's\n\t\t// path--effectively the linker symbol prefix.)\n\t\t//\n\t\t// The example above is slightly special to go list\n\t\t// because it's in the std module.  Otherwise,\n\t\t// vendored modules are simply modules whose directory\n\t\t// is vendor/ instead of GOMODCACHE, and the\n\t\t// import path equals the package path.\n\t\t//\n\t\t// But in GOPATH (non-module) mode, it's possible for\n\t\t// package vendoring to cause a non-identity ImportMap,\n\t\t// as in this example:\n\t\t//\n\t\t// $ cd $HOME/src\n\t\t// $ find . -type f\n\t\t// ./b/b.go\n\t\t// ./vendor/example.com/a/a.go\n\t\t// $ cat ./b/b.go\n\t\t// package b\n\t\t// import _ \"example.com/a\"\n\t\t// $ cat ./vendor/example.com/a/a.go\n\t\t// package a\n\t\t// $ GOPATH=$HOME GO111MODULE=off go list -json ./b | grep -A2 ImportMap\n\t\t//     \"ImportMap\": {\n\t\t//         \"example.com/a\": \"vendor/example.com/a\"\n\t\t//     },\n\n\t\t// Don't remember any imports with significant errors.\n\t\t//\n\t\t// The len=0 condition is a heuristic check for imports of\n\t\t// non-existent packages (for which go/packages will create\n\t\t// an edge to a synthesized node). The heuristic is unsound\n\t\t// because some valid packages have zero files, for example,\n\t\t// a directory containing only the file p_test.go defines an\n\t\t// empty package p.\n\t\t// TODO(adonovan): clarify this. Perhaps go/packages should\n\t\t// report which nodes were synthesized.\n\t\tif importPath != \"unsafe\" && len(imported.CompiledGoFiles) == 0 {\n\t\t\tdepsByImpPath[importPath] = \"\" // missing\n\t\t\tcontinue\n\t\t}\n\n\t\t// Don't record self-import edges.\n\t\t// (This simplifies metadataGraph's cycle check.)\n\t\tif PackageID(imported.ID) == id {\n\t\t\tif len(pkg.Errors) == 0 {\n\t\t\t\tbug.Reportf(\"self-import without error in package %s\", id)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tdep := buildMetadata(updates, loadDir, false, imported) // only top level packages can be standalone\n\n\t\t// Don't record edges to packages with no name, as they cause trouble for\n\t\t// the importer (golang/go#60952).\n\t\t//\n\t\t// Also don't record edges to packages whose ID was modified (i.e.\n\t\t// command-line-arguments packages), as encountered in golang/go#66109. In\n\t\t// this case, we could theoretically keep the edge through dep.ID, but\n\t\t// since this import doesn't make any sense in the first place, we instead\n\t\t// choose to consider it invalid.\n\t\t//\n\t\t// However, we do want to insert these packages into the update map\n\t\t// (buildMetadata above), so that we get type-checking diagnostics for the\n\t\t// invalid packages.\n\t\tif dep == nil || dep.ID != PackageID(imported.ID) || imported.Name == \"\" {\n\t\t\tdepsByImpPath[importPath] = \"\" // missing\n\t\t\tcontinue\n\t\t}\n\n\t\tdepsByImpPath[importPath] = PackageID(imported.ID)\n\t\tdepsByPkgPath[PackagePath(imported.PkgPath)] = PackageID(imported.ID)\n\t}\n\tmp.DepsByImpPath = depsByImpPath\n\tmp.DepsByPkgPath = depsByPkgPath\n\treturn mp\n\n\t// m.Diagnostics is set later in the loading pass, using\n\t// computeLoadDiagnostics.\n}\n\n// computeLoadDiagnostics computes and sets m.Diagnostics for the given metadata m.\n//\n// It should only be called during package handle construction in buildPackageHandle.\nfunc computeLoadDiagnostics(ctx context.Context, snapshot *Snapshot, mp *metadata.Package) []*Diagnostic {\n\tvar diags []*Diagnostic\n\tfor _, packagesErr := range mp.Errors {\n\t\t// Filter out parse errors from go list. We'll get them when we\n\t\t// actually parse, and buggy overlay support may generate spurious\n\t\t// errors. (See TestNewModule_Issue38207.)\n\t\tif strings.Contains(packagesErr.Msg, \"expected '\") {\n\t\t\tcontinue\n\t\t}\n\t\tpkgDiags, err := goPackagesErrorDiagnostics(ctx, packagesErr, mp, snapshot)\n\t\tif err != nil {\n\t\t\t// There are certain cases where the go command returns invalid\n\t\t\t// positions, so we cannot panic or even bug.Reportf here.\n\t\t\tevent.Error(ctx, \"unable to compute positions for list errors\", err, label.Package.Of(string(mp.ID)))\n\t\t\tcontinue\n\t\t}\n\t\tdiags = append(diags, pkgDiags...)\n\t}\n\n\t// TODO(rfindley): this is buggy: an insignificant change to a modfile\n\t// (or an unsaved modfile) could affect the position of deps errors,\n\t// without invalidating the package.\n\tdepsDiags, err := depsErrors(ctx, snapshot, mp)\n\tif err != nil {\n\t\tif ctx.Err() == nil {\n\t\t\t// TODO(rfindley): consider making this a bug.Reportf. depsErrors should\n\t\t\t// not normally fail.\n\t\t\tevent.Error(ctx, \"unable to compute deps errors\", err, label.Package.Of(string(mp.ID)))\n\t\t}\n\t} else {\n\t\tdiags = append(diags, depsDiags...)\n\t}\n\treturn diags\n}\n\n// isWorkspacePackageLocked reports whether p is a workspace package for the\n// snapshot s.\n//\n// Workspace packages are packages that we consider the user to be actively\n// working on. As such, they are re-diagnosed on every keystroke, and searched\n// for various workspace-wide queries such as references or workspace symbols.\n//\n// See the commentary inline for a description of the workspace package\n// heuristics.\n//\n// s.mu must be held while calling this function.\n//\n// TODO(rfindley): remove 'meta' from this function signature. Whether or not a\n// package is a workspace package should depend only on the package, view\n// definition, and snapshot file source. While useful, the heuristic\n// \"allFilesHaveRealPackages\" does not add that much value and is path\n// dependent as it depends on the timing of loads.\nfunc isWorkspacePackageLocked(ctx context.Context, s *Snapshot, meta *metadata.Graph, pkg *metadata.Package) bool {\n\tif metadata.IsCommandLineArguments(pkg.ID) {\n\t\t// Ad-hoc command-line-arguments packages aren't workspace packages.\n\t\t// With zero-config gopls (golang/go#57979) they should be very rare, as\n\t\t// they should only arise when the user opens a file outside the workspace\n\t\t// which isn't present in the import graph of a workspace package.\n\t\t//\n\t\t// Considering them as workspace packages tends to be racy, as they don't\n\t\t// deterministically belong to any view.\n\t\tif !pkg.Standalone {\n\t\t\treturn false\n\t\t}\n\n\t\t// If all the files contained in pkg have a real package, we don't need to\n\t\t// keep pkg as a workspace package.\n\t\tif allFilesHaveRealPackages(meta, pkg) {\n\t\t\treturn false\n\t\t}\n\n\t\t// For now, allow open standalone packages (i.e. go:build ignore) to be\n\t\t// workspace packages, but this means they could belong to multiple views.\n\t\treturn containsOpenFileLocked(s, pkg)\n\t}\n\n\t// If a real package is open, consider it to be part of the workspace.\n\t//\n\t// TODO(rfindley): reconsider this. In golang/go#66145, we saw that even if a\n\t// View sees a real package for a file, it doesn't mean that View is able to\n\t// cleanly diagnose the package. Yet, we do want to show diagnostics for open\n\t// packages outside the workspace. Is there a better way to ensure that only\n\t// the 'best' View gets a workspace package for the open file?\n\tif containsOpenFileLocked(s, pkg) {\n\t\treturn true\n\t}\n\n\t// Apply filtering logic.\n\t//\n\t// Workspace packages must contain at least one non-filtered file.\n\tfilterFunc := s.view.filterFunc()\n\turis := make(map[protocol.DocumentURI]unit) // filtered package URIs\n\tfor _, uri := range slices.Concat(pkg.CompiledGoFiles, pkg.GoFiles) {\n\t\tif !strings.Contains(string(uri), \"/vendor/\") && !filterFunc(uri) {\n\t\t\turis[uri] = struct{}{}\n\t\t}\n\t}\n\tif len(uris) == 0 {\n\t\treturn false // no non-filtered files\n\t}\n\n\t// For non-module views (of type GOPATH or AdHoc), or if\n\t// expandWorkspaceToModule is unset, workspace packages must be contained in\n\t// the workspace folder.\n\t//\n\t// For module views (of type GoMod or GoWork), packages must in any case be\n\t// in a workspace module (enforced below).\n\tif !s.view.typ.usesModules() || !s.Options().ExpandWorkspaceToModule {\n\t\tfolder := s.view.folder.Dir.Path()\n\t\tinFolder := false\n\t\tfor uri := range uris {\n\t\t\tif pathutil.InDir(folder, uri.Path()) {\n\t\t\t\tinFolder = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !inFolder {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// In module mode, a workspace package must be contained in a workspace\n\t// module.\n\tif s.view.typ.usesModules() {\n\t\tvar modURI protocol.DocumentURI\n\t\tif pkg.Module != nil {\n\t\t\tmodURI = protocol.URIFromPath(pkg.Module.GoMod)\n\t\t} else {\n\t\t\t// golang/go#65816: for std and cmd, Module is nil.\n\t\t\t// Fall back to an inferior heuristic.\n\t\t\tif len(pkg.CompiledGoFiles) == 0 {\n\t\t\t\treturn false // need at least one file to guess the go.mod file\n\t\t\t}\n\t\t\tdir := pkg.CompiledGoFiles[0].Dir()\n\t\t\tvar err error\n\t\t\tmodURI, err = findRootPattern(ctx, dir, \"go.mod\", lockedSnapshot{s})\n\t\t\tif err != nil || modURI == \"\" {\n\t\t\t\t// err != nil implies context cancellation, in which case the result of\n\t\t\t\t// this query does not matter.\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\t_, ok := s.view.workspaceModFiles[modURI]\n\t\treturn ok\n\t}\n\n\treturn true // an ad-hoc package or GOPATH package\n}\n\n// containsOpenFileLocked reports whether any file referenced by m is open in\n// the snapshot s.\n//\n// s.mu must be held while calling this function.\nfunc containsOpenFileLocked(s *Snapshot, mp *metadata.Package) bool {\n\turis := map[protocol.DocumentURI]struct{}{}\n\tfor _, uri := range mp.CompiledGoFiles {\n\t\turis[uri] = struct{}{}\n\t}\n\tfor _, uri := range mp.GoFiles {\n\t\turis[uri] = struct{}{}\n\t}\n\n\tfor uri := range uris {\n\t\tfh, _ := s.files.get(uri)\n\t\tif _, open := fh.(*overlay); open {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// computeWorkspacePackagesLocked computes workspace packages in the\n// snapshot s for the given metadata graph. The result does not\n// contain intermediate test variants.\n//\n// s.mu must be held while calling this function.\nfunc computeWorkspacePackagesLocked(ctx context.Context, s *Snapshot, meta *metadata.Graph) immutable.Map[PackageID, PackagePath] {\n\t// The provided context is used for reading snapshot files, which can only\n\t// fail due to context cancellation. Don't let this happen as it could lead\n\t// to inconsistent results.\n\tctx = xcontext.Detach(ctx)\n\tworkspacePackages := make(map[PackageID]PackagePath)\n\tfor _, mp := range meta.Packages {\n\t\tif !isWorkspacePackageLocked(ctx, s, meta, mp) {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch {\n\t\tcase mp.ForTest == \"\":\n\t\t\t// A normal package.\n\t\t\tworkspacePackages[mp.ID] = mp.PkgPath\n\t\tcase mp.ForTest == mp.PkgPath, mp.ForTest+\"_test\" == mp.PkgPath:\n\t\t\t// The test variant of some workspace package or its x_test.\n\t\t\t// To load it, we need to load the non-test variant with -test.\n\t\t\t//\n\t\t\t// Notably, this excludes intermediate test variants from workspace\n\t\t\t// packages.\n\t\t\tassert(!mp.IsIntermediateTestVariant(), \"unexpected ITV\")\n\t\t\tworkspacePackages[mp.ID] = mp.ForTest\n\t\t}\n\t}\n\treturn immutable.MapOf(workspacePackages)\n}\n\n// allFilesHaveRealPackages reports whether all files referenced by m are\n// contained in a \"real\" package (not command-line-arguments).\n//\n// If m is valid but all \"real\" packages containing any file are invalid, this\n// function returns false.\n//\n// If m is not a command-line-arguments package, this is trivially true.\nfunc allFilesHaveRealPackages(g *metadata.Graph, mp *metadata.Package) bool {\n\tn := len(mp.CompiledGoFiles)\ncheckURIs:\n\tfor _, uri := range slices.Concat(mp.CompiledGoFiles[0:n:n], mp.GoFiles) {\n\t\tfor _, pkg := range g.ForFile[uri] {\n\t\t\tif !metadata.IsCommandLineArguments(pkg.ID) {\n\t\t\t\tcontinue checkURIs\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc isTestMain(pkg *packages.Package, gocache string) bool {\n\t// Test mains must have an import path that ends with \".test\".\n\tif !strings.HasSuffix(pkg.PkgPath, \".test\") {\n\t\treturn false\n\t}\n\t// Test main packages are always named \"main\".\n\tif pkg.Name != \"main\" {\n\t\treturn false\n\t}\n\t// Test mains always have exactly one GoFile that is in the build cache.\n\tif len(pkg.GoFiles) > 1 {\n\t\treturn false\n\t}\n\tif !pathutil.InDir(gocache, pkg.GoFiles[0]) {\n\t\treturn false\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "gopls/internal/cache/metadata/cycle_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage metadata\n\nimport (\n\t\"maps\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc init() {\n\tbug.PanicOnBugs = true\n}\n\n// This is an internal test of the breakImportCycles logic.\nfunc TestBreakImportCycles(t *testing.T) {\n\n\t// parse parses an import dependency graph.\n\t// The input is a semicolon-separated list of node descriptions.\n\t// Each node description is a package ID, optionally followed by\n\t// \"->\" and a comma-separated list of successor IDs.\n\t// Thus \"a->b;b->c,d;e\" represents the set of nodes {a,b,e}\n\t// and the set of edges {a->b, b->c, b->d}.\n\tparse := func(s string) map[PackageID]*Package {\n\t\tm := make(map[PackageID]*Package)\n\t\tmakeNode := func(name string) *Package {\n\t\t\tid := PackageID(name)\n\t\t\tn, ok := m[id]\n\t\t\tif !ok {\n\t\t\t\tn = &Package{\n\t\t\t\t\tID:            id,\n\t\t\t\t\tDepsByPkgPath: make(map[PackagePath]PackageID),\n\t\t\t\t}\n\t\t\t\tm[id] = n\n\t\t\t}\n\t\t\treturn n\n\t\t}\n\t\tif s != \"\" {\n\t\t\tfor item := range strings.SplitSeq(s, \";\") {\n\t\t\t\tnodeID, succIDs, ok := strings.Cut(item, \"->\")\n\t\t\t\tnode := makeNode(nodeID)\n\t\t\t\tif ok {\n\t\t\t\t\tfor succID := range strings.SplitSeq(succIDs, \",\") {\n\t\t\t\t\t\tnode.DepsByPkgPath[PackagePath(succID)] = PackageID(succID)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn m\n\t}\n\n\t// Sanity check of cycle detector.\n\t{\n\t\tgot := cyclic(parse(\"a->b;b->c;c->a,d\"))\n\t\thas := func(s string) bool { return strings.Contains(got, s) }\n\t\tif !(has(\"a->b\") && has(\"b->c\") && has(\"c->a\") && !has(\"d\")) {\n\t\t\tt.Fatalf(\"cyclic: got %q, want a->b->c->a or equivalent\", got)\n\t\t}\n\t}\n\n\t// format formats an import graph, in lexicographic order,\n\t// in the notation of parse, but with a \"!\" after the name\n\t// of each node that has errors.\n\tformat := func(graph map[PackageID]*Package) string {\n\t\tvar items []string\n\t\tfor _, mp := range graph {\n\t\t\titem := string(mp.ID)\n\t\t\tif len(mp.Errors) > 0 {\n\t\t\t\titem += \"!\"\n\t\t\t}\n\t\t\tvar succs []string\n\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\tsuccs = append(succs, string(depID))\n\t\t\t}\n\t\t\tif succs != nil {\n\t\t\t\tsort.Strings(succs)\n\t\t\t\titem += \"->\" + strings.Join(succs, \",\")\n\t\t\t}\n\t\t\titems = append(items, item)\n\t\t}\n\t\tsort.Strings(items)\n\t\treturn strings.Join(items, \";\")\n\t}\n\n\t// We needn't test self-cycles as they are eliminated at Metadata construction.\n\tfor _, test := range []struct {\n\t\tmetadata, updates, want string\n\t}{\n\t\t// Simple 2-cycle.\n\t\t{\"a->b\", \"b->a\",\n\t\t\t\"a->b;b!\"}, // broke b->a\n\n\t\t{\"a->b;b->c;c\", \"b->a,c\",\n\t\t\t\"a->b;b!->c;c\"}, // broke b->a\n\n\t\t// Reversing direction of p->s edge creates pqrs cycle.\n\t\t{\"a->p,q,r,s;p->q,s,z;q->r,z;r->s,z;s->z\", \"p->q,z;s->p,z\",\n\t\t\t\"a->p,q,r,s;p!->z;q->r,z;r->s,z;s!->z\"}, // broke p->q, s->p\n\n\t\t// We break all intra-SCC edges from updated nodes,\n\t\t// which may be more than necessary (e.g. a->b).\n\t\t{\"a->b;b->c;c;d->a\", \"a->b,e;c->d\",\n\t\t\t\"a!->e;b->c;c!;d->a\"}, // broke a->b, c->d\n\t} {\n\t\tmetadata := parse(test.metadata)\n\t\tupdates := parse(test.updates)\n\n\t\tif cycle := cyclic(metadata); cycle != \"\" {\n\t\t\tt.Errorf(\"initial metadata %s has cycle %s: \", format(metadata), cycle)\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Log(\"initial\", format(metadata))\n\n\t\t// Apply updates.\n\t\t// (parse doesn't have a way to express node deletions,\n\t\t// but they aren't very interesting.)\n\t\tmaps.Copy(metadata, updates)\n\n\t\tt.Log(\"updated\", format(metadata))\n\n\t\t// breakImportCycles accesses only these fields of Metadata:\n\t\t//    DepsByImpPath, ID - read\n\t\t//    DepsByPkgPath     - read, updated\n\t\t//    Errors            - updated\n\t\tbreakImportCycles(metadata, updates)\n\n\t\tt.Log(\"acyclic\", format(metadata))\n\n\t\tif cycle := cyclic(metadata); cycle != \"\" {\n\t\t\tt.Errorf(\"resulting metadata %s has cycle %s: \", format(metadata), cycle)\n\t\t}\n\n\t\tgot := format(metadata)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"test.metadata=%s test.updates=%s: got=%s want=%s\",\n\t\t\t\ttest.metadata, test.updates, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/metadata/graph.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage metadata\n\nimport (\n\t\"cmp\"\n\t\"iter\"\n\t\"maps\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\n// A Graph is an immutable and transitively closed graph of [Package] data.\ntype Graph struct {\n\t// Packages maps package IDs to their associated Packages.\n\tPackages map[PackageID]*Package\n\n\t// Each of the three maps below is an index of the pointer values held\n\t// by the Packages map. However, Package pointers are not generally canonical.\n\n\t// ImportedBy maps package IDs to the list of packages that import them.\n\tImportedBy map[PackageID][]*Package\n\n\t// ForPackagePath maps package by their package path to their package ID.\n\t// Non-test packages appear before test packages, and within each of those\n\t// categories, packages with fewer CompiledGoFiles appear first.\n\tForPackagePath map[PackagePath][]*Package\n\n\t// ForFile maps file URIs to packages, sorted by (!valid, cli, packageID).\n\t// A single file may belong to multiple packages due to tests packages.\n\tForFile map[protocol.DocumentURI][]*Package\n}\n\n// Metadata implements the [Source] interface\nfunc (g *Graph) Metadata(id PackageID) *Package {\n\treturn g.Packages[id]\n}\n\n// Update creates a new Graph containing the result of applying the given\n// updates to the receiver, though the receiver is not itself mutated. As a\n// special case, if updates is empty, Update just returns the receiver.\n//\n// A nil map value is used to indicate a deletion.\nfunc (g *Graph) Update(updates map[PackageID]*Package) *Graph {\n\tif len(updates) == 0 {\n\t\t// Optimization: since the graph is immutable, we can return the receiver.\n\t\treturn g\n\t}\n\n\t// Debugging golang/go#64227, golang/vscode-go#3126:\n\t// Assert that the existing metadata graph is acyclic.\n\tif cycle := cyclic(g.Packages); cycle != \"\" {\n\t\tbug.Reportf(\"metadata is cyclic even before updates: %s\", cycle)\n\t}\n\t// Assert that the updates contain no self-cycles.\n\tfor id, mp := range updates {\n\t\tif mp != nil {\n\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\tif depID == id {\n\t\t\t\t\tbug.Reportf(\"self-cycle in metadata update: %s\", id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Copy pkgs map then apply updates.\n\tpkgs := make(map[PackageID]*Package, len(g.Packages))\n\tmaps.Copy(pkgs, g.Packages)\n\tfor id, mp := range updates {\n\t\tif mp == nil {\n\t\t\tdelete(pkgs, id)\n\t\t} else {\n\t\t\tpkgs[id] = mp\n\t\t}\n\t}\n\n\t// Break import cycles involving updated nodes.\n\tbreakImportCycles(pkgs, updates)\n\n\treturn newGraph(pkgs)\n}\n\n// newGraph returns a new metadataGraph,\n// deriving relations from the specified metadata.\nfunc newGraph(pkgs map[PackageID]*Package) *Graph {\n\t// Build the import graph.\n\timportedBy := make(map[PackageID][]*Package)\n\tbyPackagePath := make(map[PackagePath][]*Package)\n\tfor _, mp := range pkgs {\n\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\timportedBy[depID] = append(importedBy[depID], mp)\n\t\t}\n\t\tbyPackagePath[mp.PkgPath] = append(byPackagePath[mp.PkgPath], mp)\n\t}\n\n\t// Collect file associations.\n\turiPkgs := make(map[protocol.DocumentURI][]*Package)\n\tfor _, mp := range pkgs {\n\t\turis := map[protocol.DocumentURI]struct{}{}\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\turis[uri] = struct{}{}\n\t\t}\n\t\tfor _, uri := range mp.GoFiles {\n\t\t\turis[uri] = struct{}{}\n\t\t}\n\t\tfor _, uri := range mp.OtherFiles {\n\t\t\tif strings.HasSuffix(string(uri), \".s\") { // assembly\n\t\t\t\turis[uri] = struct{}{}\n\t\t\t}\n\t\t}\n\t\tfor uri := range uris {\n\t\t\turiPkgs[uri] = append(uriPkgs[uri], mp)\n\t\t}\n\t}\n\n\t// Sort and filter file associations.\n\tfor uri, pkgs := range uriPkgs {\n\t\tsort.Slice(pkgs, func(i, j int) bool {\n\t\t\tcli := IsCommandLineArguments(pkgs[i].ID)\n\t\t\tclj := IsCommandLineArguments(pkgs[j].ID)\n\t\t\tif cli != clj {\n\t\t\t\treturn clj\n\t\t\t}\n\n\t\t\t// 2. packages appear in name order.\n\t\t\treturn pkgs[i].ID < pkgs[j].ID\n\t\t})\n\n\t\t// Choose the best packages for each URI, according to the following rules:\n\t\t//  - If there are any valid real packages, choose them.\n\t\t//  - Else, choose the first valid command-line-argument package, if it exists.\n\t\t//\n\t\t// TODO(rfindley): it might be better to track all packages here, and exclude\n\t\t// them later when type checking, but this is the existing behavior.\n\t\tfor i, pkg := range pkgs {\n\t\t\t// If we've seen *anything* prior to command-line arguments package, take\n\t\t\t// it. Note that pkgs[0] may itself be command-line-arguments.\n\t\t\tif i > 0 && IsCommandLineArguments(pkg.ID) {\n\t\t\t\turiPkgs[uri] = pkgs[:i]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, mps := range byPackagePath {\n\t\tslices.SortFunc(mps, func(a, b *Package) int {\n\t\t\tif (a.ForTest == \"\") != (b.ForTest == \"\") {\n\t\t\t\tif a.ForTest == \"\" {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tif c := cmp.Compare(len(a.CompiledGoFiles), len(b.CompiledGoFiles)); c != 0 {\n\t\t\t\treturn c\n\t\t\t}\n\t\t\treturn cmp.Compare(a.ID, b.ID)\n\t\t})\n\t}\n\n\treturn &Graph{\n\t\tPackages:       pkgs,\n\t\tImportedBy:     importedBy,\n\t\tForPackagePath: byPackagePath,\n\t\tForFile:        uriPkgs,\n\t}\n}\n\n// ReverseReflexiveTransitiveClosure returns a new mapping containing the\n// metadata for the specified packages along with any package that\n// transitively imports one of them, keyed by ID, including all the initial packages.\nfunc (g *Graph) ReverseReflexiveTransitiveClosure(ids ...PackageID) map[PackageID]*Package {\n\tseen := make(map[PackageID]*Package)\n\tvar visitAll func([]*Package)\n\tvisitAll = func(pkgs []*Package) {\n\t\tfor _, pkg := range pkgs {\n\t\t\tif seen[pkg.ID] == nil {\n\t\t\t\tseen[pkg.ID] = pkg\n\t\t\t\tvisitAll(g.ImportedBy[pkg.ID])\n\t\t\t}\n\t\t}\n\t}\n\tvar initial []*Package\n\tfor _, id := range ids {\n\t\tif pkg := g.Packages[id]; pkg != nil {\n\t\t\tinitial = append(initial, pkg)\n\t\t}\n\t}\n\tvisitAll(initial)\n\treturn seen\n}\n\n// ForwardReflexiveTransitiveClosure returns an iterator over the\n// specified nodes and all their forward dependencies, in an arbitrary\n// topological (dependencies-first) order. The order may vary.\nfunc (g *Graph) ForwardReflexiveTransitiveClosure(ids ...PackageID) iter.Seq[*Package] {\n\treturn func(yield func(*Package) bool) {\n\t\tseen := make(map[PackageID]bool)\n\t\tvar visit func(PackageID) bool\n\t\tvisit = func(id PackageID) bool {\n\t\t\tif !seen[id] {\n\t\t\t\tseen[id] = true\n\t\t\t\tif mp := g.Packages[id]; mp != nil {\n\t\t\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\t\t\tif !visit(depID) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif !yield(mp) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\tfor _, id := range ids {\n\t\t\tvisit(id)\n\t\t}\n\t}\n}\n\n// breakImportCycles breaks import cycles in the metadata by deleting\n// Deps* edges. It modifies only metadata present in the 'updates'\n// subset. This function has an internal test.\nfunc breakImportCycles(metadata, updates map[PackageID]*Package) {\n\t// 'go list' should never report a cycle without flagging it\n\t// as such, but we're extra cautious since we're combining\n\t// information from multiple runs of 'go list'. Also, Bazel\n\t// may silently report cycles.\n\tcycles := detectImportCycles(metadata, updates)\n\tif len(cycles) > 0 {\n\t\t// There were cycles (uncommon). Break them.\n\t\t//\n\t\t// The naive way to break cycles would be to perform a\n\t\t// depth-first traversal and to detect and delete\n\t\t// cycle-forming edges as we encounter them.\n\t\t// However, we're not allowed to modify the existing\n\t\t// Metadata records, so we can only break edges out of\n\t\t// the 'updates' subset.\n\t\t//\n\t\t// Another possibility would be to delete not the\n\t\t// cycle forming edge but the topmost edge on the\n\t\t// stack whose tail is an updated node.\n\t\t// However, this would require that we retroactively\n\t\t// undo all the effects of the traversals that\n\t\t// occurred since that edge was pushed on the stack.\n\t\t//\n\t\t// We use a simpler scheme: we compute the set of cycles.\n\t\t// All cyclic paths necessarily involve at least one\n\t\t// updated node, so it is sufficient to break all\n\t\t// edges from each updated node to other members of\n\t\t// the strong component.\n\t\t//\n\t\t// This may result in the deletion of dominating\n\t\t// edges, causing some dependencies to appear\n\t\t// spuriously unreachable. Consider A <-> B -> C\n\t\t// where updates={A,B}. The cycle is {A,B} so the\n\t\t// algorithm will break both A->B and B->A, causing\n\t\t// A to no longer depend on B or C.\n\t\t//\n\t\t// But that's ok: any error in Metadata.Errors is\n\t\t// conservatively assumed by snapshot.clone to be a\n\t\t// potential import cycle error, and causes special\n\t\t// invalidation so that if B later drops its\n\t\t// cycle-forming import of A, both A and B will be\n\t\t// invalidated.\n\t\tfor _, cycle := range cycles {\n\t\t\tcyclic := make(map[PackageID]bool)\n\t\t\tfor _, mp := range cycle {\n\t\t\t\tcyclic[mp.ID] = true\n\t\t\t}\n\t\t\tfor id := range cyclic {\n\t\t\t\tif mp := updates[id]; mp != nil {\n\t\t\t\t\tfor path, depID := range mp.DepsByImpPath {\n\t\t\t\t\t\tif cyclic[depID] {\n\t\t\t\t\t\t\tdelete(mp.DepsByImpPath, path)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor path, depID := range mp.DepsByPkgPath {\n\t\t\t\t\t\tif cyclic[depID] {\n\t\t\t\t\t\t\tdelete(mp.DepsByPkgPath, path)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set m.Errors to enable special\n\t\t\t\t\t// invalidation logic in snapshot.clone.\n\t\t\t\t\tif len(mp.Errors) == 0 {\n\t\t\t\t\t\tmp.Errors = []packages.Error{{\n\t\t\t\t\t\t\tMsg:  \"detected import cycle\",\n\t\t\t\t\t\t\tKind: packages.ListError,\n\t\t\t\t\t\t}}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// double-check when debugging\n\t\tif false {\n\t\t\tif cycles := detectImportCycles(metadata, updates); len(cycles) > 0 {\n\t\t\t\tbug.Reportf(\"unbroken cycle: %v\", cycles)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// cyclic returns a description of a cycle,\n// if the graph is cyclic, otherwise \"\".\nfunc cyclic(graph map[PackageID]*Package) string {\n\tconst (\n\t\tunvisited = 0\n\t\tvisited   = 1\n\t\tonstack   = 2\n\t)\n\tcolor := make(map[PackageID]int)\n\tvar visit func(id PackageID) string\n\tvisit = func(id PackageID) string {\n\t\tswitch color[id] {\n\t\tcase unvisited:\n\t\t\tcolor[id] = onstack\n\t\tcase onstack:\n\t\t\treturn string(id) // cycle!\n\t\tcase visited:\n\t\t\treturn \"\"\n\t\t}\n\t\tif mp := graph[id]; mp != nil {\n\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\tif cycle := visit(depID); cycle != \"\" {\n\t\t\t\t\treturn string(id) + \"->\" + cycle\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcolor[id] = visited\n\t\treturn \"\"\n\t}\n\tfor id := range graph {\n\t\tif cycle := visit(id); cycle != \"\" {\n\t\t\treturn cycle\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// detectImportCycles reports cycles in the metadata graph. It returns a new\n// unordered array of all cycles (nontrivial strong components) in the\n// metadata graph reachable from a non-nil 'updates' value.\nfunc detectImportCycles(metadata, updates map[PackageID]*Package) [][]*Package {\n\t// We use the depth-first algorithm of Tarjan.\n\t// https://doi.org/10.1137/0201010\n\t//\n\t// TODO(adonovan): when we can use generics, consider factoring\n\t// in common with the other implementation of Tarjan (in typerefs),\n\t// abstracting over the node and edge representation.\n\n\t// A node wraps a Metadata with its working state.\n\t// (Unfortunately we can't intrude on shared Metadata.)\n\ttype node struct {\n\t\trep            *node\n\t\tmp             *Package\n\t\tindex, lowlink int32\n\t\tscc            int8 // TODO(adonovan): opt: cram these 1.5 bits into previous word\n\t}\n\tnodes := make(map[PackageID]*node, len(metadata))\n\tnodeOf := func(id PackageID) *node {\n\t\tn, ok := nodes[id]\n\t\tif !ok {\n\t\t\tmp := metadata[id]\n\t\t\tif mp == nil {\n\t\t\t\t// Dangling import edge.\n\t\t\t\t// Not sure whether a go/packages driver ever\n\t\t\t\t// emits this, but create a dummy node in case.\n\t\t\t\t// Obviously it won't be part of any cycle.\n\t\t\t\tmp = &Package{ID: id}\n\t\t\t}\n\t\t\tn = &node{mp: mp}\n\t\t\tn.rep = n\n\t\t\tnodes[id] = n\n\t\t}\n\t\treturn n\n\t}\n\n\t// find returns the canonical node decl.\n\t// (The nodes form a disjoint set forest.)\n\tvar find func(*node) *node\n\tfind = func(n *node) *node {\n\t\trep := n.rep\n\t\tif rep != n {\n\t\t\trep = find(rep)\n\t\t\tn.rep = rep // simple path compression (no union-by-rank)\n\t\t}\n\t\treturn rep\n\t}\n\n\t// global state\n\tvar (\n\t\tindex int32 = 1\n\t\tstack []*node\n\t\tsccs  [][]*Package // set of nontrivial strongly connected components\n\t)\n\n\t// visit implements the depth-first search of Tarjan's SCC algorithm\n\t// Precondition: x is canonical.\n\tvar visit func(*node)\n\tvisit = func(x *node) {\n\t\tx.index = index\n\t\tx.lowlink = index\n\t\tindex++\n\n\t\tstack = append(stack, x) // push\n\t\tx.scc = -1\n\n\t\tfor _, yid := range x.mp.DepsByPkgPath {\n\t\t\ty := nodeOf(yid)\n\t\t\t// Loop invariant: x is canonical.\n\t\t\ty = find(y)\n\t\t\tif x == y {\n\t\t\t\tcontinue // nodes already combined (self-edges are impossible)\n\t\t\t}\n\n\t\t\tswitch {\n\t\t\tcase y.scc > 0:\n\t\t\t\t// y is already a collapsed SCC\n\n\t\t\tcase y.scc < 0:\n\t\t\t\t// y is on the stack, and thus in the current SCC.\n\t\t\t\tif y.index < x.lowlink {\n\t\t\t\t\tx.lowlink = y.index\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\t// y is unvisited; visit it now.\n\t\t\t\tvisit(y)\n\t\t\t\t// Note: x and y are now non-canonical.\n\t\t\t\tx = find(x)\n\t\t\t\tif y.lowlink < x.lowlink {\n\t\t\t\t\tx.lowlink = y.lowlink\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Is x the root of an SCC?\n\t\tif x.lowlink == x.index {\n\t\t\t// Gather all metadata in the SCC (if nontrivial).\n\t\t\tvar scc []*Package\n\t\t\tfor {\n\t\t\t\t// Pop y from stack.\n\t\t\t\ti := len(stack) - 1\n\t\t\t\ty := stack[i]\n\t\t\t\tstack = stack[:i]\n\t\t\t\tif x != y || scc != nil {\n\t\t\t\t\tscc = append(scc, y.mp)\n\t\t\t\t}\n\t\t\t\tif x == y {\n\t\t\t\t\tbreak // complete\n\t\t\t\t}\n\t\t\t\t// x becomes y's canonical representative.\n\t\t\t\ty.rep = x\n\t\t\t}\n\t\t\tif scc != nil {\n\t\t\t\tsccs = append(sccs, scc)\n\t\t\t}\n\t\t\tx.scc = 1\n\t\t}\n\t}\n\n\t// Visit only the updated nodes:\n\t// the existing metadata graph has no cycles,\n\t// so any new cycle must involve an updated node.\n\tfor id, mp := range updates {\n\t\tif mp != nil {\n\t\t\tif n := nodeOf(id); n.index == 0 { // unvisited\n\t\t\t\tvisit(n)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn sccs\n}\n"
  },
  {
    "path": "gopls/internal/cache/metadata/metadata.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The metadata package defines types and functions for working with package\n// metadata, which describes Go packages and their relationships.\n//\n// Package metadata is loaded by gopls using go/packages, and the [Package]\n// type is itself a projection and translation of data from\n// go/packages.Package.\n//\n// Packages are assembled into an immutable [Graph]\npackage metadata\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n)\n\n// Declare explicit types for package paths, names, and IDs to ensure that we\n// never use an ID where a path belongs, and vice versa. If we confused these,\n// it would result in confusing errors because package IDs often look like\n// package paths.\ntype (\n\tPackageID   string // go list's unique identifier for a package (e.g. \"vendor/example.com/foo [vendor/example.com/bar.test]\")\n\tPackagePath string // name used to prefix linker symbols (e.g. \"vendor/example.com/foo\")\n\tPackageName string // identifier in 'package' declaration (e.g. \"foo\")\n\tImportPath  string // path that appears in an import declaration (e.g. \"example.com/foo\")\n)\n\n// Package represents package metadata retrieved from go/packages.\n// The DepsBy{Imp,Pkg}Path maps do not contain self-import edges.\n//\n// An ad-hoc package (without go.mod or GOPATH) has its ID, PkgPath,\n// and LoadDir equal to the absolute path of its directory.\ntype Package struct {\n\tID      PackageID\n\tPkgPath PackagePath\n\tName    PackageName\n\n\t// These fields are as defined by go/packages.Package\n\tGoFiles         []protocol.DocumentURI\n\tCompiledGoFiles []protocol.DocumentURI\n\tIgnoredFiles    []protocol.DocumentURI\n\tOtherFiles      []protocol.DocumentURI\n\n\tForTest       PackagePath // q in a \"p [q.test]\" package, else \"\"\n\tTypesSizes    types.Sizes\n\tErrors        []packages.Error          // must be set for packages in import cycles\n\tDepsByImpPath map[ImportPath]PackageID  // may contain dups; empty ID => missing\n\tDepsByPkgPath map[PackagePath]PackageID // values are unique and non-empty\n\tModule        *packages.Module          // may be missing for std and cmd; see Go issue #65816.\n\tDepsErrors    []*packagesinternal.PackageError\n\tLoadDir       string // directory from which go/packages was run\n\tStandalone    bool   // package synthesized for a standalone file (e.g. ignore-tagged)\n}\n\nfunc (mp *Package) String() string { return string(mp.ID) }\n\n// IsIntermediateTestVariant reports whether the given package is an\n// intermediate test variant (ITV), e.g. \"net/http [net/url.test]\".\n//\n// An ITV has identical syntax to the regular variant, but different\n// import metadata (DepsBy{Imp,Pkg}Path).\n//\n// Such test variants arise when an x_test package (in this case net/url_test)\n// imports a package (in this case net/http) that itself imports the\n// non-x_test package (in this case net/url).\n//\n// This is done so that the forward transitive closure of net/url_test has\n// only one package for the \"net/url\" import.\n// The ITV exists to hold the test variant import:\n//\n// net/url_test [net/url.test]\n//\n//\t| \"net/http\" -> net/http [net/url.test]\n//\t| \"net/url\" -> net/url [net/url.test]\n//\t| ...\n//\n// net/http [net/url.test]\n//\n//\t| \"net/url\" -> net/url [net/url.test]\n//\t| ...\n//\n// This restriction propagates throughout the import graph of net/http: for\n// every package imported by net/http that imports net/url, there must be an\n// intermediate test variant that instead imports \"net/url [net/url.test]\".\n//\n// As one can see from the example of net/url and net/http, intermediate test\n// variants can result in many additional packages that are essentially (but\n// not quite) identical. For this reason, we filter these variants wherever\n// possible.\n//\n// # Why we mostly ignore intermediate test variants\n//\n// In projects with complicated tests, there may be a very large\n// number of ITVs--asymptotically more than the number of ordinary\n// variants. Since they have identical syntax, it is fine in most\n// cases to ignore them since the results of analyzing the ordinary\n// variant suffice. However, this is not entirely sound.\n//\n// Consider this package:\n//\n//\t// p/p.go -- in all variants of p\n//\tpackage p\n//\ttype T struct { io.Closer }\n//\n//\t// p/p_test.go -- in test variant of p\n//\tpackage p\n//\tfunc (T) Close() error { ... }\n//\n// The ordinary variant \"p\" defines T with a Close method promoted\n// from io.Closer. But its test variant \"p [p.test]\" defines a type T\n// with a Close method from p_test.go.\n//\n// Now consider a package q that imports p, perhaps indirectly. Within\n// it, T.Close will resolve to the first Close method:\n//\n//\t// q/q.go -- in all variants of q\n//\tpackage q\n//\timport \"p\"\n//\tvar _ = new(p.T).Close\n//\n// Let's assume p also contains this file defining an external test (xtest):\n//\n//\t// p/p_x_test.go -- external test of p\n//\tpackage p_test\n//\timport ( \"q\"; \"testing\" )\n//\tfunc Test(t *testing.T) { ... }\n//\n// Note that q imports p, but p's xtest imports q. Now, in \"q\n// [p.test]\", the intermediate test variant of q built for p's\n// external test, T.Close resolves not to the io.Closer.Close\n// interface method, but to the concrete method of T.Close\n// declared in p_test.go.\n//\n// If we now request all references to the T.Close declaration in\n// p_test.go, the result should include the reference from q's ITV.\n// (It's not just methods that can be affected; fields can too, though\n// it requires bizarre code to achieve.)\n//\n// As a matter of policy, gopls mostly ignores this subtlety,\n// because to account for it would require that we type-check every\n// intermediate test variant of p, of which there could be many.\n// Good code doesn't rely on such trickery.\n//\n// Most callers of MetadataForFile set removeIntermediateTestVariants parameter\n// to discard them before requesting type checking, or the products of\n// type-checking such as the cross-reference index or method set index.\n//\n// MetadataForFile doesn't do this filtering itself because in some\n// cases we need to make a reverse dependency query on the metadata\n// graph, and it's important to include the rdeps of ITVs in that\n// query. But the filtering of ITVs should be applied after that step,\n// before type checking.\n//\n// In general, we should never type check an ITV.\nfunc (mp *Package) IsIntermediateTestVariant() bool {\n\treturn mp.ForTest != \"\" && mp.ForTest != mp.PkgPath && mp.ForTest+\"_test\" != mp.PkgPath\n}\n\n// A Source maps package IDs to metadata for the packages.\ntype Source interface {\n\t// Metadata returns the [Package] for the given package ID, or nil if it does\n\t// not exist.\n\t// TODO(rfindley): consider returning (*Metadata, bool)\n\t// TODO(rfindley): consider renaming this method.\n\tMetadata(PackageID) *Package\n}\n\n// TODO(rfindley): move the utility functions below to a util.go file.\n\n// IsCommandLineArguments reports whether a given value denotes\n// \"command-line-arguments\" package, which is a package with an unknown ID\n// created by the go command. It can have a test variant, which is why callers\n// should not check that a value equals \"command-line-arguments\" directly.\nfunc IsCommandLineArguments(id PackageID) bool {\n\treturn strings.Contains(string(id), \"command-line-arguments\")\n}\n\n// SortPostOrder sorts the IDs so that if x depends on y, then y appears before x.\nfunc SortPostOrder(meta Source, ids []PackageID) {\n\tpostorder := make(map[PackageID]int)\n\torder := 0\n\tvar visit func(PackageID)\n\tvisit = func(id PackageID) {\n\t\tif _, ok := postorder[id]; !ok {\n\t\t\tpostorder[id] = -1 // break recursion\n\t\t\tif mp := meta.Metadata(id); mp != nil {\n\t\t\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\t\t\tvisit(depID)\n\t\t\t\t}\n\t\t\t}\n\t\t\torder++\n\t\t\tpostorder[id] = order\n\t\t}\n\t}\n\tfor _, id := range ids {\n\t\tvisit(id)\n\t}\n\tsort.Slice(ids, func(i, j int) bool {\n\t\treturn postorder[ids[i]] < postorder[ids[j]]\n\t})\n}\n\n// UnquoteImportPath returns the unquoted import path of s,\n// or \"\" if the path is not properly quoted.\nfunc UnquoteImportPath(spec *ast.ImportSpec) ImportPath {\n\tpath, err := strconv.Unquote(spec.Path.Value)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn ImportPath(path)\n}\n\n// RemoveIntermediateTestVariants removes intermediate test variants, modifying\n// the array. We use a pointer to a slice make it impossible to forget to use\n// the result.\nfunc RemoveIntermediateTestVariants(pmetas *[]*Package) {\n\tmetas := *pmetas\n\tres := metas[:0]\n\tfor _, mp := range metas {\n\t\tif !mp.IsIntermediateTestVariant() {\n\t\t\tres = append(res, mp)\n\t\t}\n\t}\n\t*pmetas = res\n}\n\n// IsValidImport returns whether from may import to.\nfunc IsValidImport(from, to PackagePath, goList bool) bool {\n\t// If the metadata came from a build system other than go list\n\t// (e.g. bazel) it is beyond our means to compute visibility.\n\tif !goList {\n\t\treturn true\n\t}\n\ti := strings.LastIndex(string(to), \"/internal/\")\n\tif i == -1 {\n\t\treturn true\n\t}\n\t// TODO(rfindley): this looks wrong: IsCommandLineArguments is meant to\n\t// operate on package IDs, not package paths.\n\tif IsCommandLineArguments(PackageID(from)) {\n\t\treturn true\n\t}\n\t// TODO(rfindley): this is wrong. mod.testx/p should not be able to\n\t// import mod.test/internal: https://go.dev/play/p/-Ca6P-E4V4q\n\treturn strings.HasPrefix(string(from), string(to[:i]))\n}\n"
  },
  {
    "path": "gopls/internal/cache/methodsets/methodsets.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package methodsets defines an incremental, serializable index of\n// method-set information that allows efficient 'implements' queries\n// across packages of the workspace without using the type checker.\n//\n// This package provides only the \"global\" (all workspace) search; the\n// \"local\" search within a given package uses a different\n// implementation based on type-checker data structures for a single\n// package plus variants; see ../implementation.go.\n// The local algorithm is more precise as it tests function-local types too.\n//\n// A global index of function-local types is challenging since they\n// may reference other local types, for which we would need to invent\n// stable names, an unsolved problem described in passing in Go issue\n// 57497. The global algorithm also does not index anonymous interface\n// types, even outside function bodies.\n//\n// Consequently, global results are not symmetric: applying the\n// operation twice may not get you back where you started.\npackage methodsets\n\n// DESIGN\n//\n// See https://go.dev/cl/452060 for a minimal exposition of the algorithm.\n//\n// For each method, we compute a fingerprint: a string representing\n// the method name and type such that equal fingerprint strings mean\n// identical method types.\n//\n// For efficiency, the fingerprint is reduced to a single bit\n// of a uint64, so that the method set can be represented as\n// the union of those method bits (a uint64 bitmask).\n// Assignability thus reduces to a subset check on bitmasks\n// followed by equality checks on fingerprints.\n//\n// In earlier experiments, using 128-bit masks instead of 64 reduced\n// the number of candidates by about 2x. Using (like a Bloom filter) a\n// different hash function to compute a second 64-bit mask and\n// performing a second mask test reduced it by about 4x.\n// Neither had much effect on the running time, presumably because a\n// single 64-bit mask is quite effective. See CL 452060 for details.\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\t\"hash/crc32\"\n\t\"slices\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/fingerprint\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// An Index records the non-empty method sets of all package-level\n// types in a package in a form that permits assignability queries\n// without the type checker.\ntype Index struct {\n\tpkg     gobPackage\n\tPkgPath metadata.PackagePath\n}\n\n// Decode decodes the given gob-encoded data as an Index.\nfunc Decode(pkgpath metadata.PackagePath, data []byte) *Index {\n\tvar pkg gobPackage\n\tpackageCodec.Decode(data, &pkg)\n\treturn &Index{pkg: pkg, PkgPath: pkgpath}\n}\n\n// Encode encodes the receiver as gob-encoded data.\nfunc (index *Index) Encode() []byte {\n\treturn packageCodec.Encode(index.pkg)\n}\n\n// NewIndex returns a new index of method-set information for all\n// package-level types in the specified package.\nfunc NewIndex(fset *token.FileSet, pkg *types.Package) *Index {\n\treturn new(indexBuilder).build(fset, pkg)\n}\n\n// A Location records the extent of an identifier in byte-offset form.\n//\n// Conversion to protocol (UTF-16) form is done by the caller after a\n// search, not during index construction.\ntype Location struct {\n\tFilename   string\n\tStart, End int // byte offsets\n}\n\n// A Key represents the method set of a given type in a form suitable\n// to pass to the (*Index).Search method of many different Indexes.\ntype Key struct {\n\tmset *gobMethodSet // note: lacks position information\n}\n\n// KeyOf returns the search key for the method sets of a given type.\n// It returns false if the type has no methods.\nfunc KeyOf(t types.Type) (Key, bool) {\n\tmset := methodSetInfo(t, nil)\n\tif mset.Mask == 0 {\n\t\treturn Key{}, false // no methods\n\t}\n\treturn Key{mset}, true\n}\n\n// A Result reports a matching type or method in a method-set search.\ntype Result struct {\n\tTypeName    string   // name of the named type\n\tIsInterface bool     // matched type (or method) is abstract\n\tLocation    Location // location of the type or method\n\n\t// methods only:\n\tPkgPath    string          // path of declaring package (may differ due to embedding)\n\tObjectPath objectpath.Path // path of method within declaring package\n}\n\n// TypeRelation indicates the direction of subtyping relation,\n// if any, between two types.\n//\n// It is a bitset, so that clients of Implementations may use\n// Supertype|Subtype to request an undirected match.\ntype TypeRelation int8\n\nconst (\n\tSupertype TypeRelation = 0x1\n\tSubtype   TypeRelation = 0x2\n)\n\n// Search reports each type that implements (Supertype ∈ want) or is\n// implemented by (Subtype ∈ want) the type that produced the search key.\n//\n// If method is non-nil, only that method of each type is reported.\n//\n// The result does not include the error.Error method.\n// TODO(adonovan): give this special case a more systematic treatment.\nfunc (index *Index) Search(key Key, want TypeRelation, method *types.Func) []Result {\n\tvar results []Result\n\tfor _, candidate := range index.pkg.MethodSets {\n\t\t// Test the direction of the relation.\n\t\t// The client may request either direction or both\n\t\t// (e.g. when the client is References),\n\t\t// and the Result reports each test independently;\n\t\t// both tests succeed when comparing identical\n\t\t// interface types.\n\t\tvar got TypeRelation\n\t\tif want&Subtype != 0 && implements(candidate, key.mset) {\n\t\t\tgot |= Subtype\n\t\t}\n\t\tif want&Supertype != 0 && implements(key.mset, candidate) {\n\t\t\tgot |= Supertype\n\t\t}\n\t\tif got == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\ttypeName := index.pkg.Strings[candidate.TypeName]\n\t\tif method == nil {\n\t\t\tresults = append(results, Result{\n\t\t\t\tTypeName:    typeName,\n\t\t\t\tIsInterface: candidate.IsInterface,\n\t\t\t\tLocation:    index.location(candidate.Posn),\n\t\t\t})\n\t\t} else {\n\t\t\tfor _, m := range candidate.Methods {\n\t\t\t\tif m.ID == method.Id() {\n\t\t\t\t\t// Don't report error.Error among the results:\n\t\t\t\t\t// it has no true source location, no package,\n\t\t\t\t\t// and is excluded from the xrefs index.\n\t\t\t\t\tif m.PkgPath == 0 || m.ObjectPath == 0 {\n\t\t\t\t\t\tif m.ID != \"Error\" {\n\t\t\t\t\t\t\tpanic(\"missing info for\" + m.ID)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tresults = append(results, Result{\n\t\t\t\t\t\tTypeName:    typeName,\n\t\t\t\t\t\tIsInterface: candidate.IsInterface,\n\t\t\t\t\t\tLocation:    index.location(m.Posn),\n\t\t\t\t\t\tPkgPath:     index.pkg.Strings[m.PkgPath],\n\t\t\t\t\t\tObjectPath:  objectpath.Path(index.pkg.Strings[m.ObjectPath]),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn results\n}\n\n// implements reports whether x implements y.\nfunc implements(x, y *gobMethodSet) bool {\n\tif !y.IsInterface {\n\t\treturn false\n\t}\n\n\t// Fast path: neither method set is tricky, so all methods can\n\t// be compared by equality of ID and Fingerprint, and the\n\t// entire subset check can be done using the bit mask.\n\tif !x.Tricky && !y.Tricky {\n\t\tif x.Mask&y.Mask != y.Mask {\n\t\t\treturn false // x lacks a method of interface y\n\t\t}\n\t}\n\n\t// At least one operand is tricky (e.g. contains a type parameter),\n\t// so we must used tree-based matching (unification).\n\n\t// nonmatching reports whether interface method 'my' lacks\n\t// a matching method in set x. (The sense is inverted for use\n\t// with slice.ContainsFunc below.)\n\tnonmatching := func(my *gobMethod) bool {\n\t\tfor _, mx := range x.Methods {\n\t\t\tif mx.ID == my.ID {\n\t\t\t\tvar match bool\n\t\t\t\tif !mx.Tricky && !my.Tricky {\n\t\t\t\t\t// Fast path: neither method is tricky,\n\t\t\t\t\t// so a string match is sufficient.\n\t\t\t\t\tmatch = mx.Sum&my.Sum == my.Sum && mx.Fingerprint == my.Fingerprint\n\t\t\t\t} else {\n\t\t\t\t\tmatch = fingerprint.Matches(mx.parse(), my.parse())\n\t\t\t\t}\n\t\t\t\treturn !match\n\t\t\t}\n\t\t}\n\t\treturn true // method of y not found in x\n\t}\n\n\t// Each interface method must have a match.\n\t// (This would be more readable with a DeMorganized\n\t// variant of ContainsFunc.)\n\treturn !slices.ContainsFunc(y.Methods, nonmatching)\n}\n\nfunc (index *Index) location(posn gobPosition) Location {\n\treturn Location{\n\t\tFilename: index.pkg.Strings[posn.File],\n\t\tStart:    posn.Offset,\n\t\tEnd:      posn.Offset + posn.Len,\n\t}\n}\n\n// An indexBuilder builds an index for a single package.\ntype indexBuilder struct {\n\tgobPackage\n\tstringIndex map[string]int\n}\n\n// build adds to the index all package-level named types of the specified package.\nfunc (b *indexBuilder) build(fset *token.FileSet, pkg *types.Package) *Index {\n\t_ = b.string(\"\") // 0 => \"\"\n\n\tobjectPos := func(obj types.Object) gobPosition {\n\t\tposn := safetoken.StartPosition(fset, obj.Pos())\n\t\treturn gobPosition{b.string(posn.Filename), posn.Offset, len(obj.Name())}\n\t}\n\n\tobjectpathFor := new(objectpath.Encoder).For\n\n\t// setindexInfo sets the (Posn, PkgPath, ObjectPath) fields for each method declaration.\n\tsetIndexInfo := func(m *gobMethod, method *types.Func) {\n\t\t// error.Error has empty Position, PkgPath, and ObjectPath.\n\t\tif method.Pkg() == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// Instantiations of generic methods don't have an\n\t\t// object path, so we use the generic.\n\t\tp, err := objectpathFor(method.Origin())\n\t\tif err != nil {\n\t\t\t// This should never happen for a method of a package-level type.\n\t\t\t// ...but it does (golang/go#70418).\n\t\t\t// Refine the crash into various bug reports.\n\t\t\treport := func() {\n\t\t\t\tbug.Reportf(\"missing object path for %s\", method.FullName())\n\t\t\t}\n\t\t\tsig := method.Signature()\n\t\t\tif sig.Recv() == nil {\n\t\t\t\treport()\n\t\t\t\treturn\n\t\t\t}\n\t\t\t_, named := typesinternal.ReceiverNamed(sig.Recv())\n\t\t\tswitch {\n\t\t\tcase named == nil:\n\t\t\t\treport()\n\t\t\tcase sig.TypeParams().Len() > 0:\n\t\t\t\treport()\n\t\t\tcase method.Origin() != method:\n\t\t\t\treport() // instantiated?\n\t\t\tcase sig.RecvTypeParams().Len() > 0:\n\t\t\t\treport() // generic?\n\t\t\tdefault:\n\t\t\t\treport()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tm.Posn = objectPos(method)\n\t\tm.PkgPath = b.string(method.Pkg().Path())\n\t\tm.ObjectPath = b.string(string(p))\n\t}\n\n\t// We ignore aliases, though in principle they could define a\n\t// struct{...}  or interface{...} type, or an instantiation of\n\t// a generic, that has a novel method set.\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tif tname, ok := scope.Lookup(name).(*types.TypeName); ok && !tname.IsAlias() {\n\t\t\tif mset := methodSetInfo(tname.Type(), setIndexInfo); mset.Mask != 0 {\n\t\t\t\tmset.TypeName = b.string(name)\n\t\t\t\tmset.Posn = objectPos(tname)\n\t\t\t\t// Only record types with non-trivial method sets.\n\t\t\t\tb.MethodSets = append(b.MethodSets, mset)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn &Index{\n\t\tpkg:     b.gobPackage,\n\t\tPkgPath: metadata.PackagePath(pkg.Path()),\n\t}\n}\n\n// string returns a small integer that encodes the string.\nfunc (b *indexBuilder) string(s string) int {\n\ti, ok := b.stringIndex[s]\n\tif !ok {\n\t\ti = len(b.Strings)\n\t\tif b.stringIndex == nil {\n\t\t\tb.stringIndex = make(map[string]int)\n\t\t}\n\t\tb.stringIndex[s] = i\n\t\tb.Strings = append(b.Strings, s)\n\t}\n\treturn i\n}\n\n// methodSetInfo returns the method-set fingerprint of a type.\n// It calls the optional setIndexInfo function for each gobMethod.\n// This is used during index construction, but not search (KeyOf),\n// to store extra information.\nfunc methodSetInfo(t types.Type, setIndexInfo func(*gobMethod, *types.Func)) *gobMethodSet {\n\t// For non-interface types, use *T\n\t// (if T is not already a pointer)\n\t// since it may have more methods.\n\tmset := types.NewMethodSet(EnsurePointer(t))\n\n\t// Convert the method set into a compact summary.\n\tvar mask uint64\n\ttricky := false\n\tvar buf []byte\n\tmethods := make([]*gobMethod, mset.Len())\n\tfor i := 0; i < mset.Len(); i++ {\n\t\tm := mset.At(i).Obj().(*types.Func)\n\t\tid := m.Id()\n\t\tfp, isTricky := fingerprint.Encode(m.Signature())\n\t\tif isTricky {\n\t\t\ttricky = true\n\t\t}\n\t\tbuf = append(append(buf[:0], id...), fp...)\n\t\tsum := crc32.ChecksumIEEE(buf)\n\t\tmethods[i] = &gobMethod{ID: id, Fingerprint: fp, Sum: sum, Tricky: isTricky}\n\t\tif setIndexInfo != nil {\n\t\t\tsetIndexInfo(methods[i], m) // set Position, PkgPath, ObjectPath\n\t\t}\n\t\tmask |= 1 << uint64(((sum>>24)^(sum>>16)^(sum>>8)^sum)&0x3f)\n\t}\n\treturn &gobMethodSet{\n\t\tIsInterface: types.IsInterface(t),\n\t\tTricky:      tricky,\n\t\tMask:        mask,\n\t\tMethods:     methods,\n\t}\n}\n\n// EnsurePointer wraps T in a types.Pointer if T is a named, non-interface type.\n// This is useful to make sure you consider a named type's full method set.\nfunc EnsurePointer(T types.Type) types.Type {\n\tif _, ok := types.Unalias(T).(*types.Named); ok && !types.IsInterface(T) {\n\t\treturn types.NewPointer(T)\n\t}\n\n\treturn T\n}\n\n// -- serial format of index --\n\n// (The name says gob but in fact we use frob.)\nvar packageCodec = frob.CodecFor[gobPackage]()\n\n// A gobPackage records the method set of each package-level type for a single package.\ntype gobPackage struct {\n\tStrings    []string // index of strings used by gobPosition.File, gobMethod.{Pkg,Object}Path\n\tMethodSets []*gobMethodSet\n}\n\n// A gobMethodSet records the method set of a single type.\ntype gobMethodSet struct {\n\tTypeName    int // name (string index) of the package-level type\n\tPosn        gobPosition\n\tIsInterface bool\n\tTricky      bool   // at least one method is tricky; fingerprint must be parsed + unified\n\tMask        uint64 // mask with 1 bit from each of methods[*].sum\n\tMethods     []*gobMethod\n}\n\n// A gobMethod records the name, type, and position of a single method.\ntype gobMethod struct {\n\tID          string // (*types.Func).Id() value of method\n\tFingerprint string // encoding of types as string of form \"(params)(results)\"\n\tSum         uint32 // checksum of ID + fingerprint\n\tTricky      bool   // method type contains tricky features (type params, interface types)\n\n\t// index records only (zero in KeyOf; also for index of error.Error).\n\tPosn       gobPosition // location of method declaration\n\tPkgPath    int         // path of package containing method declaration\n\tObjectPath int         // object path of method relative to PkgPath\n\n\t// internal fields (not serialized)\n\ttree atomic.Pointer[fingerprint.Tree] // fingerprint tree, parsed on demand\n}\n\n// A gobPosition records the file, offset, and length of an identifier.\ntype gobPosition struct {\n\tFile        int // index into gobPackage.Strings\n\tOffset, Len int // in bytes\n}\n\n// parse returns the method's parsed fingerprint tree.\n// It may return a new instance or a cached one.\nfunc (m *gobMethod) parse() fingerprint.Tree {\n\tptr := m.tree.Load()\n\tif ptr == nil {\n\t\ttree := fingerprint.Parse(m.Fingerprint)\n\t\tptr = &tree\n\t\tm.tree.Store(ptr) // may race; that's ok\n\t}\n\treturn *ptr\n}\n"
  },
  {
    "path": "gopls/internal/cache/mod.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// A ParsedModule contains the results of parsing a go.mod file.\ntype ParsedModule struct {\n\tURI         protocol.DocumentURI\n\tFile        *modfile.File // maybe absent in case of error\n\tReplaceMap  map[module.Version]module.Version\n\tMapper      *protocol.Mapper\n\tParseErrors []*Diagnostic\n}\n\n// ParseMod parses a go.mod file, using a cache. It may return partial results and an error.\nfunc (s *Snapshot) ParseMod(ctx context.Context, fh file.Handle) (*ParsedModule, error) {\n\turi := fh.URI()\n\n\ts.mu.Lock()\n\tentry, hit := s.parseModHandles.Get(uri)\n\ts.mu.Unlock()\n\n\ttype parseModKey file.Identity\n\ttype parseModResult struct {\n\t\tparsed *ParsedModule\n\t\terr    error\n\t}\n\n\t// cache miss?\n\tif !hit {\n\t\tpromise, release := s.store.Promise(parseModKey(fh.Identity()), func(ctx context.Context, _ any) any {\n\t\t\tparsed, err := parseModImpl(ctx, fh)\n\t\t\treturn parseModResult{parsed, err}\n\t\t})\n\n\t\tentry = promise\n\t\ts.mu.Lock()\n\t\ts.parseModHandles.Set(uri, entry, func(_, _ any) { release() })\n\t\ts.mu.Unlock()\n\t}\n\n\t// Await result.\n\tv, err := s.awaitPromise(ctx, entry)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := v.(parseModResult)\n\treturn res.parsed, res.err\n}\n\n// parseModImpl parses the go.mod file whose name and contents are in fh.\n// It may return partial results and an error.\nfunc parseModImpl(ctx context.Context, fh file.Handle) (*ParsedModule, error) {\n\t_, done := event.Start(ctx, \"cache.ParseMod\", label.URI.Of(fh.URI()))\n\tdefer done()\n\n\tcontents, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := protocol.NewMapper(fh.URI(), contents)\n\tfile, parseErr := modfile.Parse(fh.URI().Path(), contents, nil)\n\t// Attempt to convert the error to a standardized parse error.\n\tvar parseErrors []*Diagnostic\n\tif parseErr != nil {\n\t\tmfErrList, ok := parseErr.(modfile.ErrorList)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unexpected parse error type %v\", parseErr)\n\t\t}\n\t\tfor _, mfErr := range mfErrList {\n\t\t\trng, err := m.OffsetRange(mfErr.Pos.Byte, mfErr.Pos.Byte)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tparseErrors = append(parseErrors, &Diagnostic{\n\t\t\t\tURI:      fh.URI(),\n\t\t\t\tRange:    rng,\n\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\tSource:   ParseError,\n\t\t\t\tMessage:  mfErr.Err.Error(),\n\t\t\t})\n\t\t}\n\t}\n\n\treplaceMap := make(map[module.Version]module.Version)\n\tif parseErr == nil {\n\t\tfor _, rep := range file.Replace {\n\t\t\treplaceMap[rep.Old] = rep.New\n\t\t}\n\t}\n\n\treturn &ParsedModule{\n\t\tURI:         fh.URI(),\n\t\tMapper:      m,\n\t\tFile:        file,\n\t\tReplaceMap:  replaceMap,\n\t\tParseErrors: parseErrors,\n\t}, parseErr\n}\n\n// A ParsedWorkFile contains the results of parsing a go.work file.\ntype ParsedWorkFile struct {\n\tURI         protocol.DocumentURI\n\tFile        *modfile.WorkFile\n\tMapper      *protocol.Mapper\n\tParseErrors []*Diagnostic\n}\n\n// ParseWork parses a go.work file, using a cache. It may return partial results and an error.\n// TODO(adonovan): move to new work.go file.\nfunc (s *Snapshot) ParseWork(ctx context.Context, fh file.Handle) (*ParsedWorkFile, error) {\n\turi := fh.URI()\n\n\ts.mu.Lock()\n\tentry, hit := s.parseWorkHandles.Get(uri)\n\ts.mu.Unlock()\n\n\ttype parseWorkKey file.Identity\n\ttype parseWorkResult struct {\n\t\tparsed *ParsedWorkFile\n\t\terr    error\n\t}\n\n\t// cache miss?\n\tif !hit {\n\t\thandle, release := s.store.Promise(parseWorkKey(fh.Identity()), func(ctx context.Context, _ any) any {\n\t\t\tparsed, err := parseWorkImpl(ctx, fh)\n\t\t\treturn parseWorkResult{parsed, err}\n\t\t})\n\n\t\tentry = handle\n\t\ts.mu.Lock()\n\t\ts.parseWorkHandles.Set(uri, entry, func(_, _ any) { release() })\n\t\ts.mu.Unlock()\n\t}\n\n\t// Await result.\n\tv, err := s.awaitPromise(ctx, entry)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := v.(parseWorkResult)\n\treturn res.parsed, res.err\n}\n\n// parseWorkImpl parses a go.work file. It may return partial results and an error.\nfunc parseWorkImpl(ctx context.Context, fh file.Handle) (*ParsedWorkFile, error) {\n\t_, done := event.Start(ctx, \"cache.ParseWork\", label.URI.Of(fh.URI()))\n\tdefer done()\n\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := protocol.NewMapper(fh.URI(), content)\n\tfile, parseErr := modfile.ParseWork(fh.URI().Path(), content, nil)\n\t// Attempt to convert the error to a standardized parse error.\n\tvar parseErrors []*Diagnostic\n\tif parseErr != nil {\n\t\tmfErrList, ok := parseErr.(modfile.ErrorList)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unexpected parse error type %v\", parseErr)\n\t\t}\n\t\tfor _, mfErr := range mfErrList {\n\t\t\trng, err := m.OffsetRange(mfErr.Pos.Byte, mfErr.Pos.Byte)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tparseErrors = append(parseErrors, &Diagnostic{\n\t\t\t\tURI:      fh.URI(),\n\t\t\t\tRange:    rng,\n\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\tSource:   ParseError,\n\t\t\t\tMessage:  mfErr.Err.Error(),\n\t\t\t})\n\t\t}\n\t}\n\treturn &ParsedWorkFile{\n\t\tURI:         fh.URI(),\n\t\tMapper:      m,\n\t\tFile:        file,\n\t\tParseErrors: parseErrors,\n\t}, parseErr\n}\n\n// ModWhy returns the \"go mod why\" result for each module named in a\n// require statement in the go.mod file.\n// TODO(adonovan): move to new mod_why.go file.\nfunc (s *Snapshot) ModWhy(ctx context.Context, fh file.Handle) (map[string]string, error) {\n\turi := fh.URI()\n\n\tif s.FileKind(fh) != file.Mod {\n\t\treturn nil, fmt.Errorf(\"%s is not a go.mod file\", uri)\n\t}\n\n\ts.mu.Lock()\n\tentry, hit := s.modWhyHandles.Get(uri)\n\ts.mu.Unlock()\n\n\ttype modWhyResult struct {\n\t\twhy map[string]string\n\t\terr error\n\t}\n\n\t// cache miss?\n\tif !hit {\n\t\thandle := memoize.NewPromise(\"modWhy\", func(ctx context.Context, arg any) any {\n\t\t\twhy, err := modWhyImpl(ctx, arg.(*Snapshot), fh)\n\t\t\treturn modWhyResult{why, err}\n\t\t})\n\n\t\tentry = handle\n\t\ts.mu.Lock()\n\t\ts.modWhyHandles.Set(uri, entry, nil)\n\t\ts.mu.Unlock()\n\t}\n\n\t// Await result.\n\tv, err := s.awaitPromise(ctx, entry)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := v.(modWhyResult)\n\treturn res.why, res.err\n}\n\n// modWhyImpl returns the result of \"go mod why -m\" on the specified go.mod file.\nfunc modWhyImpl(ctx context.Context, snapshot *Snapshot, fh file.Handle) (map[string]string, error) {\n\tctx, done := event.Start(ctx, \"cache.ModWhy\", label.URI.Of(fh.URI()))\n\tdefer done()\n\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// No requires to explain.\n\tif len(pm.File.Require) == 0 {\n\t\treturn nil, nil // empty result\n\t}\n\t// Run `go mod why` on all the dependencies.\n\targs := []string{\"why\", \"-m\"}\n\tfor _, req := range pm.File.Require {\n\t\targs = append(args, req.Mod.Path)\n\t}\n\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(NoNetwork, fh.URI().DirPath(), \"mod\", args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cleanupInvocation()\n\tstdout, err := snapshot.View().GoCommandRunner().Run(ctx, *inv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\twhyList := strings.Split(stdout.String(), \"\\n\\n\")\n\tif len(whyList) != len(pm.File.Require) {\n\t\treturn nil, fmt.Errorf(\"mismatched number of results: got %v, want %v\", len(whyList), len(pm.File.Require))\n\t}\n\twhy := make(map[string]string, len(pm.File.Require))\n\tfor i, req := range pm.File.Require {\n\t\twhy[req.Mod.Path] = whyList[i]\n\t}\n\treturn why, nil\n}\n\n// extractGoCommandErrors tries to parse errors that come from the go command\n// and shape them into go.mod diagnostics.\n// TODO: rename this to 'load errors'\nfunc (s *Snapshot) extractGoCommandErrors(ctx context.Context, goCmdError error) []*Diagnostic {\n\tif goCmdError == nil {\n\t\treturn nil\n\t}\n\n\ttype locatedErr struct {\n\t\tloc protocol.Location\n\t\tmsg string\n\t}\n\tdiagLocations := map[*ParsedModule]locatedErr{}\n\tbackupDiagLocations := map[*ParsedModule]locatedErr{}\n\n\t// If moduleErrs is non-nil, go command errors are scoped to specific\n\t// modules.\n\tvar moduleErrs *moduleErrorMap\n\t_ = errors.As(goCmdError, &moduleErrs)\n\n\t// Match the error against all the mod files in the workspace.\n\tfor _, uri := range s.View().ModFiles() {\n\t\tfh, err := s.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"getting modfile for Go command error\", err)\n\t\t\tcontinue\n\t\t}\n\t\tpm, err := s.ParseMod(ctx, fh)\n\t\tif err != nil {\n\t\t\t// Parsing errors are reported elsewhere\n\t\t\treturn nil\n\t\t}\n\t\tvar msgs []string // error messages to consider\n\t\tif moduleErrs != nil {\n\t\t\tif pm.File.Module != nil {\n\t\t\t\tfor _, mes := range moduleErrs.errs[pm.File.Module.Mod.Path] {\n\t\t\t\t\tmsgs = append(msgs, mes.Error())\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tmsgs = append(msgs, goCmdError.Error())\n\t\t}\n\t\tfor _, msg := range msgs {\n\t\t\tif strings.Contains(goCmdError.Error(), \"errors parsing go.mod\") {\n\t\t\t\t// The go command emits parse errors for completely invalid go.mod files.\n\t\t\t\t// Those are reported by our own diagnostics and can be ignored here.\n\t\t\t\t// As of writing, we are not aware of any other errors that include\n\t\t\t\t// file/position information, so don't even try to find it.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tloc, found, err := s.matchErrorToModule(pm, msg)\n\t\t\tif err != nil {\n\t\t\t\tevent.Error(ctx, \"matching error to module\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tle := locatedErr{\n\t\t\t\tloc: loc,\n\t\t\t\tmsg: msg,\n\t\t\t}\n\t\t\tif found {\n\t\t\t\tdiagLocations[pm] = le\n\t\t\t} else {\n\t\t\t\tbackupDiagLocations[pm] = le\n\t\t\t}\n\t\t}\n\t}\n\n\t// If we didn't find any good matches, assign diagnostics to all go.mod files.\n\tif len(diagLocations) == 0 {\n\t\tdiagLocations = backupDiagLocations\n\t}\n\n\tvar srcErrs []*Diagnostic\n\tfor pm, le := range diagLocations {\n\t\tdiag, err := s.goCommandDiagnostic(pm, le.loc, le.msg)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"building go command diagnostic\", err)\n\t\t\tcontinue\n\t\t}\n\t\tsrcErrs = append(srcErrs, diag)\n\t}\n\treturn srcErrs\n}\n\nvar moduleVersionInErrorRe = regexp.MustCompile(`[:\\s]([+-._~0-9A-Za-z]+)@([+-._~0-9A-Za-z]+)[:\\s]`)\n\n// matchErrorToModule matches a go command error message to a go.mod file.\n// Some examples:\n//\n//\texample.com@v1.2.2: reading example.com/@v/v1.2.2.mod: no such file or directory\n//\tgo: github.com/cockroachdb/apd/v2@v2.0.72: reading github.com/cockroachdb/apd/go.mod at revision v2.0.72: unknown revision v2.0.72\n//\tgo: example.com@v1.2.3 requires\\n\\trandom.org@v1.2.3: parsing go.mod:\\n\\tmodule declares its path as: bob.org\\n\\tbut was required as: random.org\n//\n// It returns the location of a reference to the one of the modules and true\n// if one exists. If none is found it returns a fallback location and false.\nfunc (s *Snapshot) matchErrorToModule(pm *ParsedModule, goCmdError string) (protocol.Location, bool, error) {\n\tvar reference *modfile.Line\n\tmatches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1)\n\n\tfor i := len(matches) - 1; i >= 0; i-- {\n\t\tver := module.Version{Path: matches[i][1], Version: matches[i][2]}\n\t\tif err := module.Check(ver.Path, ver.Version); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treference = findModuleReference(pm.File, ver)\n\t\tif reference != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif reference == nil {\n\t\t// No match for the module path was found in the go.mod file.\n\t\t// Show the error on the module declaration, if one exists, or\n\t\t// just the first line of the file.\n\t\tvar start, end int\n\t\tif pm.File.Module != nil && pm.File.Module.Syntax != nil {\n\t\t\tsyntax := pm.File.Module.Syntax\n\t\t\tstart, end = syntax.Start.Byte, syntax.End.Byte\n\t\t}\n\t\tloc, err := pm.Mapper.OffsetLocation(start, end)\n\t\treturn loc, false, err\n\t}\n\n\tloc, err := pm.Mapper.OffsetLocation(reference.Start.Byte, reference.End.Byte)\n\treturn loc, true, err\n}\n\n// goCommandDiagnostic creates a diagnostic for a given go command error.\nfunc (s *Snapshot) goCommandDiagnostic(pm *ParsedModule, loc protocol.Location, goCmdError string) (*Diagnostic, error) {\n\tmatches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1)\n\tvar innermost *module.Version\n\tfor i := len(matches) - 1; i >= 0; i-- {\n\t\tver := module.Version{Path: matches[i][1], Version: matches[i][2]}\n\t\tif err := module.Check(ver.Path, ver.Version); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tinnermost = &ver\n\t\tbreak\n\t}\n\n\tswitch {\n\tcase strings.Contains(goCmdError, \"inconsistent vendoring\"):\n\t\tcmd := command.NewVendorCommand(\"Run go mod vendor\", command.URIArg{URI: pm.URI})\n\t\treturn &Diagnostic{\n\t\t\tURI:      pm.URI,\n\t\t\tRange:    loc.Range,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tSource:   ListError,\n\t\t\tMessage: `Inconsistent vendoring detected. Please re-run \"go mod vendor\".\nSee https://github.com/golang/go/issues/39164 for more detail on this issue.`,\n\t\t\tSuggestedFixes: []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)},\n\t\t}, nil\n\n\tcase strings.Contains(goCmdError, \"updates to go.sum needed\"), strings.Contains(goCmdError, \"missing go.sum entry\"):\n\t\tvar args []protocol.DocumentURI\n\t\targs = append(args, s.View().ModFiles()...)\n\t\ttidyCmd := command.NewTidyCommand(\"Run go mod tidy\", command.URIArgs{URIs: args})\n\t\tupdateCmd := command.NewUpdateGoSumCommand(\"Update go.sum\", command.URIArgs{URIs: args})\n\t\tmsg := \"go.sum is out of sync with go.mod. Please update it by applying the quick fix.\"\n\t\tif innermost != nil {\n\t\t\tmsg = fmt.Sprintf(\"go.sum is out of sync with go.mod: entry for %v is missing. Please updating it by applying the quick fix.\", innermost)\n\t\t}\n\t\treturn &Diagnostic{\n\t\t\tURI:      pm.URI,\n\t\t\tRange:    loc.Range,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tSource:   ListError,\n\t\t\tMessage:  msg,\n\t\t\tSuggestedFixes: []SuggestedFix{\n\t\t\t\tSuggestedFixFromCommand(tidyCmd, protocol.QuickFix),\n\t\t\t\tSuggestedFixFromCommand(updateCmd, protocol.QuickFix),\n\t\t\t},\n\t\t}, nil\n\tcase strings.Contains(goCmdError, \"disabled by GOPROXY=off\") && innermost != nil:\n\t\ttitle := fmt.Sprintf(\"Download %v@%v\", innermost.Path, innermost.Version)\n\t\tcmd := command.NewAddDependencyCommand(title, command.DependencyArgs{\n\t\t\tURI:        pm.URI,\n\t\t\tAddRequire: false,\n\t\t\tGoCmdArgs:  []string{fmt.Sprintf(\"%v@%v\", innermost.Path, innermost.Version)},\n\t\t})\n\t\treturn &Diagnostic{\n\t\t\tURI:            pm.URI,\n\t\t\tRange:          loc.Range,\n\t\t\tSeverity:       protocol.SeverityError,\n\t\t\tMessage:        fmt.Sprintf(\"%v@%v has not been downloaded\", innermost.Path, innermost.Version),\n\t\t\tSource:         ListError,\n\t\t\tSuggestedFixes: []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)},\n\t\t}, nil\n\tdefault:\n\t\treturn &Diagnostic{\n\t\t\tURI:      pm.URI,\n\t\t\tRange:    loc.Range,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tSource:   ListError,\n\t\t\tMessage:  goCmdError,\n\t\t}, nil\n\t}\n}\n\nfunc findModuleReference(mf *modfile.File, ver module.Version) *modfile.Line {\n\tfor _, req := range mf.Require {\n\t\tif req.Mod == ver {\n\t\t\treturn req.Syntax\n\t\t}\n\t}\n\tfor _, ex := range mf.Exclude {\n\t\tif ex.Mod == ver {\n\t\t\treturn ex.Syntax\n\t\t}\n\t}\n\tfor _, rep := range mf.Replace {\n\t\tif rep.New == ver || rep.Old == ver {\n\t\t\treturn rep.Syntax\n\t\t}\n\t}\n\treturn nil\n}\n\n// ResolvedVersion returns the version used for a module, which considers replace directive.\nfunc ResolvedVersion(module *packages.Module) string {\n\t// don't visit replace recursively as src/cmd/go/internal/modinfo/info.go\n\t// visits replace field only once.\n\tif module.Replace != nil {\n\t\treturn module.Replace.Version\n\t}\n\treturn module.Version\n}\n\n// ResolvedPath returns the module path, which considers replace directive.\nfunc ResolvedPath(module *packages.Module) string {\n\tif module.Replace != nil {\n\t\treturn module.Replace.Path\n\t}\n\treturn module.Path\n}\n\n// ResolvedString returns a representation of the Version suitable for logging\n// (Path@Version, or just Path if Version is empty),\n// which considers replace directive.\nfunc ResolvedString(module *packages.Module) string {\n\tif ResolvedVersion(module) == \"\" {\n\t\tResolvedPath(module)\n\t}\n\treturn ResolvedPath(module) + \"@\" + ResolvedVersion(module)\n}\n"
  },
  {
    "path": "gopls/internal/cache/mod_tidy.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// This error is sought by mod diagnostics.\nvar ErrNoModOnDisk = errors.New(\"go.mod file is not on disk\")\n\n// A TidiedModule contains the results of running `go mod tidy` on a module.\ntype TidiedModule struct {\n\t// Diagnostics representing changes made by `go mod tidy`.\n\tDiagnostics []*Diagnostic\n\t// The bytes of the go.mod file after it was tidied.\n\tTidiedContent []byte\n}\n\n// ModTidy returns the go.mod file that would be obtained by running\n// \"go mod tidy\". Concurrent requests are combined into a single command.\nfunc (s *Snapshot) ModTidy(ctx context.Context, pm *ParsedModule) (*TidiedModule, error) {\n\tctx, done := event.Start(ctx, \"cache.snapshot.ModTidy\")\n\tdefer done()\n\n\turi := pm.URI\n\tif pm.File == nil {\n\t\treturn nil, fmt.Errorf(\"cannot tidy unparsable go.mod file: %v\", uri)\n\t}\n\n\ts.mu.Lock()\n\tentry, hit := s.modTidyHandles.Get(uri)\n\ts.mu.Unlock()\n\n\ttype modTidyResult struct {\n\t\ttidied *TidiedModule\n\t\terr    error\n\t}\n\n\t// Cache miss?\n\tif !hit {\n\t\t// If the file handle is an overlay, it may not be written to disk.\n\t\t// The go.mod file has to be on disk for `go mod tidy` to work.\n\t\t// TODO(rfindley): is this still true with Go 1.16 overlay support?\n\t\tfh, err := s.ReadFile(ctx, pm.URI)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif _, ok := fh.(*overlay); ok {\n\t\t\tif info, _ := os.Stat(uri.Path()); info == nil {\n\t\t\t\treturn nil, ErrNoModOnDisk\n\t\t\t}\n\t\t}\n\n\t\tif err := s.awaitLoaded(ctx); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\thandle := memoize.NewPromise(\"modTidy\", func(ctx context.Context, arg any) any {\n\t\t\ttidied, err := modTidyImpl(ctx, arg.(*Snapshot), pm)\n\t\t\treturn modTidyResult{tidied, err}\n\t\t})\n\n\t\tentry = handle\n\t\ts.mu.Lock()\n\t\ts.modTidyHandles.Set(uri, entry, nil)\n\t\ts.mu.Unlock()\n\t}\n\n\t// Await result.\n\tv, err := s.awaitPromise(ctx, entry)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := v.(modTidyResult)\n\treturn res.tidied, res.err\n}\n\n// modTidyImpl runs \"go mod tidy\" on a go.mod file.\nfunc modTidyImpl(ctx context.Context, snapshot *Snapshot, pm *ParsedModule) (*TidiedModule, error) {\n\tctx, done := event.Start(ctx, \"cache.ModTidy\", label.URI.Of(pm.URI))\n\tdefer done()\n\n\ttempDir, cleanup, err := TempModDir(ctx, snapshot, pm.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cleanup()\n\n\targs := []string{\"tidy\", \"-modfile=\" + filepath.Join(tempDir, \"go.mod\")}\n\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(NoNetwork, pm.URI.DirPath(), \"mod\", args, \"GOWORK=off\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cleanupInvocation()\n\tif _, err := snapshot.view.gocmdRunner.Run(ctx, *inv); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Go directly to disk to get the temporary mod file,\n\t// since it is always on disk.\n\ttempMod := filepath.Join(tempDir, \"go.mod\")\n\ttempContents, err := os.ReadFile(tempMod)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tideal, err := modfile.Parse(tempMod, tempContents, nil)\n\tif err != nil {\n\t\t// We do not need to worry about the temporary file's parse errors\n\t\t// since it has been \"tidied\".\n\t\treturn nil, err\n\t}\n\n\t// Compare the original and tidied go.mod files to compute errors and\n\t// suggested fixes.\n\tdiagnostics, err := modTidyDiagnostics(ctx, snapshot, pm, ideal)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &TidiedModule{\n\t\tDiagnostics:   diagnostics,\n\t\tTidiedContent: tempContents,\n\t}, nil\n}\n\n// modTidyDiagnostics computes the differences between the original and tidied\n// go.mod files to produce diagnostic and suggested fixes. Some diagnostics\n// may appear on the Go files that import packages from missing modules.\nfunc modTidyDiagnostics(ctx context.Context, snapshot *Snapshot, pm *ParsedModule, ideal *modfile.File) (diagnostics []*Diagnostic, err error) {\n\t// First, determine which modules are unused and which are missing from the\n\t// original go.mod file.\n\tvar (\n\t\tunused          = make(map[string]*modfile.Require, len(pm.File.Require))\n\t\tmissing         = make(map[string]*modfile.Require, len(ideal.Require))\n\t\twrongDirectness = make(map[string]*modfile.Require, len(pm.File.Require))\n\t)\n\tfor _, req := range pm.File.Require {\n\t\tunused[req.Mod.Path] = req\n\t}\n\tfor _, req := range ideal.Require {\n\t\torigReq := unused[req.Mod.Path]\n\t\tif origReq == nil {\n\t\t\tmissing[req.Mod.Path] = req\n\t\t\tcontinue\n\t\t} else if origReq.Indirect != req.Indirect {\n\t\t\twrongDirectness[req.Mod.Path] = origReq\n\t\t}\n\t\tdelete(unused, req.Mod.Path)\n\t}\n\tfor _, req := range wrongDirectness {\n\t\t// Handle dependencies that are incorrectly labeled indirect and\n\t\t// vice versa.\n\t\tsrcDiag, err := directnessDiagnostic(pm.Mapper, req)\n\t\tif err != nil {\n\t\t\t// We're probably in a bad state if we can't compute a\n\t\t\t// directnessDiagnostic, but try to keep going so as to not suppress\n\t\t\t// other, valid diagnostics.\n\t\t\tevent.Error(ctx, \"computing directness diagnostic\", err)\n\t\t\tcontinue\n\t\t}\n\t\tdiagnostics = append(diagnostics, srcDiag)\n\t}\n\t// Next, compute any diagnostics for modules that are missing from the\n\t// go.mod file. The fixes will be for the go.mod file, but the\n\t// diagnostics should also appear in both the go.mod file and the import\n\t// statements in the Go files in which the dependencies are used.\n\t// Finally, add errors for any unused dependencies.\n\tif len(missing) > 0 {\n\t\tmissingModuleDiagnostics, err := missingModuleDiagnostics(ctx, snapshot, pm, ideal, missing)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdiagnostics = append(diagnostics, missingModuleDiagnostics...)\n\t}\n\n\t// Opt: if this is the only diagnostic, we can avoid textual edits and just\n\t// run the Go command.\n\t//\n\t// See also the documentation for command.RemoveDependencyArgs.OnlyDiagnostic.\n\tonlyDiagnostic := len(diagnostics) == 0 && len(unused) == 1\n\tfor _, req := range unused {\n\t\tsrcErr, err := unusedDiagnostic(pm.Mapper, req, onlyDiagnostic)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdiagnostics = append(diagnostics, srcErr)\n\t}\n\treturn diagnostics, nil\n}\n\nfunc missingModuleDiagnostics(ctx context.Context, snapshot *Snapshot, pm *ParsedModule, ideal *modfile.File, missing map[string]*modfile.Require) ([]*Diagnostic, error) {\n\tmissingModuleFixes := map[*modfile.Require][]SuggestedFix{}\n\tvar diagnostics []*Diagnostic\n\tfor _, req := range missing {\n\t\tsrcDiag, err := missingModuleDiagnostic(pm, req)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmissingModuleFixes[req] = srcDiag.SuggestedFixes\n\t\tdiagnostics = append(diagnostics, srcDiag)\n\t}\n\n\t// Add diagnostics for missing modules anywhere they are imported in the\n\t// workspace.\n\tmetas, err := snapshot.WorkspaceMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// TODO(adonovan): opt: opportunities for parallelism abound.\n\tfor _, mp := range metas {\n\t\t// Read both lists of files of this package.\n\t\t//\n\t\t// Parallelism is not necessary here as the files will have already been\n\t\t// pre-read at load time.\n\t\tgoFiles, err := readFiles(ctx, snapshot, mp.GoFiles)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcompiledGoFiles, err := readFiles(ctx, snapshot, mp.CompiledGoFiles)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tmissingImports := map[string]*modfile.Require{}\n\n\t\t// If -mod=readonly is not set we may have successfully imported\n\t\t// packages from missing modules. Otherwise they'll be in\n\t\t// MissingDependencies. Combine both.\n\t\timps, err := parseImports(ctx, snapshot, goFiles)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor imp := range imps {\n\t\t\tif req, ok := missing[imp]; ok {\n\t\t\t\tmissingImports[imp] = req\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// If the import is a package of the dependency, then add the\n\t\t\t// package to the map, this will eliminate the need to do this\n\t\t\t// prefix package search on each import for each file.\n\t\t\t// Example:\n\t\t\t//\n\t\t\t// import (\n\t\t\t//   \"golang.org/x/tools/internal/expect\"\n\t\t\t//   \"golang.org/x/tools/go/packages\"\n\t\t\t// )\n\t\t\t// They both are related to the same module: \"golang.org/x/tools\".\n\t\t\tvar match string\n\t\t\tfor _, req := range ideal.Require {\n\t\t\t\tif strings.HasPrefix(imp, req.Mod.Path) && len(req.Mod.Path) > len(match) {\n\t\t\t\t\tmatch = req.Mod.Path\n\t\t\t\t}\n\t\t\t}\n\t\t\tif req, ok := missing[match]; ok {\n\t\t\t\tmissingImports[imp] = req\n\t\t\t}\n\t\t}\n\t\t// None of this package's imports are from missing modules.\n\t\tif len(missingImports) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, goFile := range compiledGoFiles {\n\t\t\tpgf, err := snapshot.ParseGo(ctx, goFile, parsego.Header)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfile, m := pgf.File, pgf.Mapper\n\t\t\tif file == nil || m == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timports := make(map[string]*ast.ImportSpec)\n\t\t\tfor _, imp := range file.Imports {\n\t\t\t\tif imp.Path == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif target, err := strconv.Unquote(imp.Path.Value); err == nil {\n\t\t\t\t\timports[target] = imp\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(imports) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor importPath, req := range missingImports {\n\t\t\t\timp, ok := imports[importPath]\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfixes, ok := missingModuleFixes[req]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"no missing module fix for %q (%q)\", importPath, req.Mod.Path)\n\t\t\t\t}\n\t\t\t\tsrcErr, err := missingModuleForImport(pgf, imp, req, fixes)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tdiagnostics = append(diagnostics, srcErr)\n\t\t\t}\n\t\t}\n\t}\n\treturn diagnostics, nil\n}\n\n// unusedDiagnostic returns a Diagnostic for an unused require.\nfunc unusedDiagnostic(m *protocol.Mapper, req *modfile.Require, onlyDiagnostic bool) (*Diagnostic, error) {\n\trng, err := m.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttitle := fmt.Sprintf(\"Remove dependency: %s\", req.Mod.Path)\n\tcmd := command.NewRemoveDependencyCommand(title, command.RemoveDependencyArgs{\n\t\tURI:            m.URI,\n\t\tOnlyDiagnostic: onlyDiagnostic,\n\t\tModulePath:     req.Mod.Path,\n\t})\n\treturn &Diagnostic{\n\t\tURI:            m.URI,\n\t\tRange:          rng,\n\t\tSeverity:       protocol.SeverityWarning,\n\t\tSource:         ModTidyError,\n\t\tMessage:        fmt.Sprintf(\"%s is not used in this module\", req.Mod.Path),\n\t\tSuggestedFixes: []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)},\n\t}, nil\n}\n\n// directnessDiagnostic extracts errors when a dependency is labeled indirect when\n// it should be direct and vice versa.\nfunc directnessDiagnostic(m *protocol.Mapper, req *modfile.Require) (*Diagnostic, error) {\n\trng, err := m.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdirection := \"indirect\"\n\tif req.Indirect {\n\t\tdirection = \"direct\"\n\n\t\t// If the dependency should be direct, just highlight the // indirect.\n\t\tif comments := req.Syntax.Comment(); comments != nil && len(comments.Suffix) > 0 {\n\t\t\tend := comments.Suffix[0].Start\n\t\t\tend.LineRune += len(comments.Suffix[0].Token)\n\t\t\tend.Byte += len(comments.Suffix[0].Token)\n\t\t\trng, err = m.OffsetRange(comments.Suffix[0].Start.Byte, end.Byte)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\t// If the dependency should be indirect, add the // indirect.\n\tedits, err := switchDirectness(req, m)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Diagnostic{\n\t\tURI:      m.URI,\n\t\tRange:    rng,\n\t\tSeverity: protocol.SeverityWarning,\n\t\tSource:   ModTidyError,\n\t\tMessage:  fmt.Sprintf(\"%s should be %s\", req.Mod.Path, direction),\n\t\tSuggestedFixes: []SuggestedFix{{\n\t\t\tTitle: fmt.Sprintf(\"Change %s to %s\", req.Mod.Path, direction),\n\t\t\tEdits: map[protocol.DocumentURI][]protocol.TextEdit{\n\t\t\t\tm.URI: edits,\n\t\t\t},\n\t\t\tActionKind: protocol.QuickFix,\n\t\t}},\n\t}, nil\n}\n\nfunc missingModuleDiagnostic(pm *ParsedModule, req *modfile.Require) (*Diagnostic, error) {\n\tvar rng protocol.Range\n\t// Default to the start of the file if there is no module declaration.\n\tif pm.File != nil && pm.File.Module != nil && pm.File.Module.Syntax != nil {\n\t\tstart, end := pm.File.Module.Syntax.Span()\n\t\tvar err error\n\t\trng, err = pm.Mapper.OffsetRange(start.Byte, end.Byte)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\ttitle := fmt.Sprintf(\"Add %s to your go.mod file\", req.Mod.Path)\n\tcmd := command.NewAddDependencyCommand(title, command.DependencyArgs{\n\t\tURI:        pm.Mapper.URI,\n\t\tAddRequire: !req.Indirect,\n\t\tGoCmdArgs:  []string{req.Mod.Path + \"@\" + req.Mod.Version},\n\t})\n\treturn &Diagnostic{\n\t\tURI:            pm.Mapper.URI,\n\t\tRange:          rng,\n\t\tSeverity:       protocol.SeverityError,\n\t\tSource:         ModTidyError,\n\t\tMessage:        fmt.Sprintf(\"%s is not in your go.mod file\", req.Mod.Path),\n\t\tSuggestedFixes: []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)},\n\t}, nil\n}\n\n// switchDirectness gets the edits needed to change an indirect dependency to\n// direct and vice versa.\nfunc switchDirectness(req *modfile.Require, m *protocol.Mapper) ([]protocol.TextEdit, error) {\n\t// We need a private copy of the parsed go.mod file, since we're going to\n\t// modify it.\n\tcopied, err := modfile.Parse(\"\", m.Content, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Change the directness in the matching require statement. To avoid\n\t// reordering the require statements, rewrite all of them.\n\tvar requires []*modfile.Require\n\tseenVersions := make(map[string]string)\n\tfor _, r := range copied.Require {\n\t\tif seen := seenVersions[r.Mod.Path]; seen != \"\" && seen != r.Mod.Version {\n\t\t\t// Avoid a panic in SetRequire below, which panics on conflicting\n\t\t\t// versions.\n\t\t\treturn nil, fmt.Errorf(\"%q has conflicting versions: %q and %q\", r.Mod.Path, seen, r.Mod.Version)\n\t\t}\n\t\tseenVersions[r.Mod.Path] = r.Mod.Version\n\t\tif r.Mod.Path == req.Mod.Path {\n\t\t\trequires = append(requires, &modfile.Require{\n\t\t\t\tMod:      r.Mod,\n\t\t\t\tSyntax:   r.Syntax,\n\t\t\t\tIndirect: !r.Indirect,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\trequires = append(requires, r)\n\t}\n\tcopied.SetRequire(requires)\n\tnewContent, err := copied.Format()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Calculate the edits to be made due to the change.\n\tedits := diff.Bytes(m.Content, newContent)\n\treturn protocol.EditsFromDiffEdits(m, edits)\n}\n\n// missingModuleForImport creates an error for a given import path that comes\n// from a missing module.\nfunc missingModuleForImport(pgf *parsego.File, imp *ast.ImportSpec, req *modfile.Require, fixes []SuggestedFix) (*Diagnostic, error) {\n\tif req.Syntax == nil {\n\t\treturn nil, fmt.Errorf(\"no syntax for %v\", req)\n\t}\n\trng, err := pgf.NodeRange(imp.Path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Diagnostic{\n\t\tURI:            pgf.URI,\n\t\tRange:          rng,\n\t\tSeverity:       protocol.SeverityError,\n\t\tSource:         ModTidyError,\n\t\tMessage:        fmt.Sprintf(\"%s is not in your go.mod file\", req.Mod.Path),\n\t\tSuggestedFixes: fixes,\n\t}, nil\n}\n\n// parseImports parses the headers of the specified files and returns\n// the set of strings that appear in import declarations within\n// GoFiles. Errors are ignored.\n//\n// (We can't simply use Metadata.Imports because it is based on\n// CompiledGoFiles, after cgo processing.)\n//\n// TODO(rfindley): this should key off ImportPath.\nfunc parseImports(ctx context.Context, s *Snapshot, files []file.Handle) (map[string]bool, error) {\n\tpgfs, err := s.view.parseCache.parseFiles(ctx, token.NewFileSet(), parsego.Header, false, files...)\n\tif err != nil { // e.g. context cancellation\n\t\treturn nil, err\n\t}\n\n\tseen := make(map[string]bool)\n\tfor _, pgf := range pgfs {\n\t\tfor _, spec := range pgf.File.Imports {\n\t\t\tpath, _ := strconv.Unquote(spec.Path.Value)\n\t\t\tseen[path] = true\n\t\t}\n\t}\n\treturn seen, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/mod_vuln.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n\tisem \"golang.org/x/tools/gopls/internal/vulncheck/semver\"\n\t\"golang.org/x/vuln/scan\"\n)\n\n// ModVuln returns import vulnerability analysis for the given go.mod URI.\n// Concurrent requests are combined into a single command.\nfunc (s *Snapshot) ModVuln(ctx context.Context, modURI protocol.DocumentURI) (*vulncheck.Result, error) {\n\ts.mu.Lock()\n\tentry, hit := s.modVulnHandles.Get(modURI)\n\ts.mu.Unlock()\n\n\ttype modVuln struct {\n\t\tresult *vulncheck.Result\n\t\terr    error\n\t}\n\n\t// Cache miss?\n\tif !hit {\n\t\thandle := memoize.NewPromise(\"modVuln\", func(ctx context.Context, arg any) any {\n\t\t\tresult, err := modVulnImpl(ctx, arg.(*Snapshot))\n\t\t\treturn modVuln{result, err}\n\t\t})\n\n\t\tentry = handle\n\t\ts.mu.Lock()\n\t\ts.modVulnHandles.Set(modURI, entry, nil)\n\t\ts.mu.Unlock()\n\t}\n\n\t// Await result.\n\tv, err := s.awaitPromise(ctx, entry)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := v.(modVuln)\n\treturn res.result, res.err\n}\n\n// GoVersionForVulnTest is an internal environment variable used in gopls\n// testing to examine govulncheck behavior with a go version different\n// than what `go version` returns in the system.\nconst GoVersionForVulnTest = \"_GOPLS_TEST_VULNCHECK_GOVERSION\"\n\n// modVulnImpl queries the vulndb and reports which vulnerabilities\n// apply to this snapshot. The result contains a set of packages,\n// grouped by vuln ID and by module. This implements the \"import-based\"\n// vulnerability report on go.mod files.\nfunc modVulnImpl(ctx context.Context, snapshot *Snapshot) (*vulncheck.Result, error) {\n\t// TODO(hyangah): can we let 'govulncheck' take a package list\n\t// used in the workspace and implement this function?\n\n\t// We want to report the intersection of vulnerable packages in the vulndb\n\t// and packages transitively imported by this module ('go list -deps all').\n\t// We use snapshot.AllMetadata to retrieve the list of packages\n\t// as an approximation.\n\t//\n\t// TODO(hyangah): snapshot.AllMetadata is a superset of\n\t// `go list all` - e.g. when the workspace has multiple main modules\n\t// (multiple go.mod files), that can include packages that are not\n\t// used by this module. Vulncheck behavior with go.work is not well\n\t// defined. Figure out the meaning, and if we decide to present\n\t// the result as if each module is analyzed independently, make\n\t// gopls track a separate build list for each module and use that\n\t// information instead of snapshot.AllMetadata.\n\tallMeta, err := snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// TODO(hyangah): handle vulnerabilities in the standard library.\n\n\t// Group packages by modules since vuln db is keyed by module.\n\tpackagesByModule := map[metadata.PackagePath][]*metadata.Package{}\n\tfor _, mp := range allMeta {\n\t\tmodulePath := metadata.PackagePath(osv.GoStdModulePath)\n\t\tif mi := mp.Module; mi != nil {\n\t\t\tmodulePath = metadata.PackagePath(mi.Path)\n\t\t}\n\t\tpackagesByModule[modulePath] = append(packagesByModule[modulePath], mp)\n\t}\n\n\tvar (\n\t\tmu sync.Mutex\n\t\t// Keys are osv.Entry.ID\n\t\tosvs     = map[string]*osv.Entry{}\n\t\tfindings []*govulncheck.Finding\n\t)\n\n\tgoVersion := snapshot.Options().Env[GoVersionForVulnTest]\n\tif goVersion == \"\" {\n\t\tgoVersion = snapshot.GoVersionString()\n\t}\n\n\tstdlibModule := &packages.Module{\n\t\tPath:    osv.GoStdModulePath,\n\t\tVersion: goVersion,\n\t}\n\n\t// GOVULNDB may point the test db URI.\n\tdb := GetEnv(snapshot, \"GOVULNDB\")\n\n\tvar group errgroup.Group\n\tgroup.SetLimit(10) // limit govulncheck api runs\n\tfor _, mps := range packagesByModule {\n\t\tgroup.Go(func() error {\n\t\t\teffectiveModule := stdlibModule\n\t\t\tif m := mps[0].Module; m != nil {\n\t\t\t\teffectiveModule = m\n\t\t\t}\n\t\t\tfor effectiveModule.Replace != nil {\n\t\t\t\teffectiveModule = effectiveModule.Replace\n\t\t\t}\n\t\t\tver := effectiveModule.Version\n\t\t\tif ver == \"\" || !isem.Valid(ver) {\n\t\t\t\t// skip invalid version strings. the underlying scan api is strict.\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// TODO(hyangah): batch these requests and add in-memory cache for efficiency.\n\t\t\tvulns, err := osvsByModule(ctx, db, effectiveModule.Path+\"@\"+ver)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif len(vulns) == 0 { // No known vulnerability.\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// set of packages in this module known to gopls.\n\t\t\t// This will be lazily initialized when we need it.\n\t\t\tvar knownPkgs map[metadata.PackagePath]bool\n\n\t\t\t// Report vulnerabilities that affect packages of this module.\n\t\t\tfor _, entry := range vulns {\n\t\t\t\tvar vulnerablePkgs []*govulncheck.Finding\n\t\t\t\tfixed := fixedVersion(effectiveModule.Path, entry.Affected)\n\n\t\t\t\tfor _, a := range entry.Affected {\n\t\t\t\t\tif a.Module.Ecosystem != osv.GoEcosystem || a.Module.Path != effectiveModule.Path {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tfor _, imp := range a.EcosystemSpecific.Packages {\n\t\t\t\t\t\tif knownPkgs == nil {\n\t\t\t\t\t\t\tknownPkgs = toPackagePathSet(mps)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif knownPkgs[metadata.PackagePath(imp.Path)] {\n\t\t\t\t\t\t\tvulnerablePkgs = append(vulnerablePkgs, &govulncheck.Finding{\n\t\t\t\t\t\t\t\tOSV:          entry.ID,\n\t\t\t\t\t\t\t\tFixedVersion: fixed,\n\t\t\t\t\t\t\t\tTrace: []*govulncheck.Frame{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tModule:  effectiveModule.Path,\n\t\t\t\t\t\t\t\t\t\tVersion: effectiveModule.Version,\n\t\t\t\t\t\t\t\t\t\tPackage: imp.Path,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(vulnerablePkgs) == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tmu.Lock()\n\t\t\t\tosvs[entry.ID] = entry\n\t\t\t\tfindings = append(findings, vulnerablePkgs...)\n\t\t\t\tmu.Unlock()\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := group.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Sort so the results are deterministic.\n\tsort.Slice(findings, func(i, j int) bool {\n\t\tx, y := findings[i], findings[j]\n\t\tif x.OSV != y.OSV {\n\t\t\treturn x.OSV < y.OSV\n\t\t}\n\t\treturn x.Trace[0].Package < y.Trace[0].Package\n\t})\n\tret := &vulncheck.Result{\n\t\tEntries:  osvs,\n\t\tFindings: findings,\n\t\tMode:     vulncheck.ModeImports,\n\t}\n\treturn ret, nil\n}\n\n// TODO(rfindley): this function was exposed during refactoring. Reconsider it.\nfunc GetEnv(snapshot *Snapshot, key string) string {\n\tval, ok := snapshot.Options().Env[key]\n\tif ok {\n\t\treturn val\n\t}\n\treturn os.Getenv(key)\n}\n\n// toPackagePathSet transforms the metadata to a set of package paths.\nfunc toPackagePathSet(mds []*metadata.Package) map[metadata.PackagePath]bool {\n\tpkgPaths := make(map[metadata.PackagePath]bool, len(mds))\n\tfor _, md := range mds {\n\t\tpkgPaths[md.PkgPath] = true\n\t}\n\treturn pkgPaths\n}\n\nfunc fixedVersion(modulePath string, affected []osv.Affected) string {\n\tfixed := latestFixed(modulePath, affected)\n\tif fixed != \"\" {\n\t\tfixed = versionString(modulePath, fixed)\n\t}\n\treturn fixed\n}\n\n// latestFixed returns the latest fixed version in the list of affected ranges,\n// or the empty string if there are no fixed versions.\nfunc latestFixed(modulePath string, as []osv.Affected) string {\n\tv := \"\"\n\tfor _, a := range as {\n\t\tif a.Module.Path != modulePath {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, r := range a.Ranges {\n\t\t\tif r.Type == osv.RangeTypeSemver {\n\t\t\t\tfor _, e := range r.Events {\n\t\t\t\t\tif e.Fixed != \"\" && (v == \"\" ||\n\t\t\t\t\t\tsemver.Compare(isem.CanonicalizeSemverPrefix(e.Fixed), isem.CanonicalizeSemverPrefix(v)) > 0) {\n\t\t\t\t\t\tv = e.Fixed\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn v\n}\n\n// versionString prepends a version string prefix (`v` or `go`\n// depending on the modulePath) to the given semver-style version string.\nfunc versionString(modulePath, version string) string {\n\tif version == \"\" {\n\t\treturn \"\"\n\t}\n\tv := \"v\" + version\n\t// These are internal Go module paths used by the vuln DB\n\t// when listing vulns in standard library and the go command.\n\tif modulePath == \"stdlib\" || modulePath == \"toolchain\" {\n\t\treturn semverToGoTag(v)\n\t}\n\treturn v\n}\n\n// semverToGoTag returns the Go standard library repository tag corresponding\n// to semver, a version string without the initial \"v\".\n// Go tags differ from standard semantic versions in a few ways,\n// such as beginning with \"go\" instead of \"v\".\nfunc semverToGoTag(v string) string {\n\tif strings.HasPrefix(v, \"v0.0.0\") {\n\t\treturn \"master\"\n\t}\n\t// Special case: v1.0.0 => go1.\n\tif v == \"v1.0.0\" {\n\t\treturn \"go1\"\n\t}\n\tif !semver.IsValid(v) {\n\t\treturn fmt.Sprintf(\"<!%s:invalid semver>\", v)\n\t}\n\tgoVersion := semver.Canonical(v)\n\tprerelease := semver.Prerelease(goVersion)\n\tversionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)\n\tpatch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+\".\")\n\tif patch == \"0\" {\n\t\tversionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, \".0\")\n\t}\n\tgoVersion = fmt.Sprintf(\"go%s\", strings.TrimPrefix(versionWithoutPrerelease, \"v\"))\n\tif prerelease != \"\" {\n\t\t// Go prereleases look like  \"beta1\" instead of \"beta.1\".\n\t\t// \"beta1\" is bad for sorting (since beta10 comes before beta9), so\n\t\t// require the dot form.\n\t\ti := finalDigitsIndex(prerelease)\n\t\tif i >= 1 {\n\t\t\tif prerelease[i-1] != '.' {\n\t\t\t\treturn fmt.Sprintf(\"<!%s:final digits in a prerelease must follow a period>\", v)\n\t\t\t}\n\t\t\t// Remove the dot.\n\t\t\tprerelease = prerelease[:i-1] + prerelease[i:]\n\t\t}\n\t\tgoVersion += strings.TrimPrefix(prerelease, \"-\")\n\t}\n\treturn goVersion\n}\n\n// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.\n// If s doesn't end in digits, it returns -1.\nfunc finalDigitsIndex(s string) int {\n\t// Assume ASCII (since the semver package does anyway).\n\tvar i int\n\tfor i = len(s) - 1; i >= 0; i-- {\n\t\tif s[i] < '0' || s[i] > '9' {\n\t\t\tbreak\n\t\t}\n\t}\n\tif i == len(s)-1 {\n\t\treturn -1\n\t}\n\treturn i + 1\n}\n\n// osvsByModule runs a govulncheck database query.\nfunc osvsByModule(ctx context.Context, db, moduleVersion string) ([]*osv.Entry, error) {\n\tvar args []string\n\targs = append(args, \"-mode=query\", \"-json\")\n\tif db != \"\" {\n\t\targs = append(args, \"-db=\"+db)\n\t}\n\targs = append(args, moduleVersion)\n\n\tir, iw := io.Pipe()\n\thandler := &osvReader{}\n\n\tvar g errgroup.Group\n\tg.Go(func() error {\n\t\tdefer iw.Close() // scan API doesn't close cmd.Stderr/cmd.Stdout.\n\t\tcmd := scan.Command(ctx, args...)\n\t\tcmd.Stdout = iw\n\t\t// TODO(hakim): Do we need to set cmd.Env = getEnvSlices(),\n\t\t// or is the process environment good enough?\n\t\tif err := cmd.Start(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn cmd.Wait()\n\t})\n\tg.Go(func() error {\n\t\treturn govulncheck.HandleJSON(ir, handler)\n\t})\n\n\tif err := g.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn handler.entry, nil\n}\n\n// osvReader implements govulncheck.Handler.\ntype osvReader struct {\n\tentry []*osv.Entry\n}\n\nfunc (h *osvReader) OSV(entry *osv.Entry) error {\n\th.entry = append(h.entry, entry)\n\treturn nil\n}\n\nfunc (h *osvReader) Config(config *govulncheck.Config) error {\n\treturn nil\n}\n\nfunc (h *osvReader) Finding(finding *govulncheck.Finding) error {\n\treturn nil\n}\n\nfunc (h *osvReader) Progress(progress *govulncheck.Progress) error {\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/os_darwin.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc init() {\n\tcheckPathValid = darwinCheckPathValid\n}\n\nfunc darwinCheckPathValid(path string) error {\n\t// Darwin provides fcntl(F_GETPATH) to get a path for an arbitrary FD.\n\t// Conveniently for our purposes, it gives the canonical case back. But\n\t// there's no guarantee that it will follow the same route through the\n\t// filesystem that the original path did.\n\n\tpath, err := filepath.Abs(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfd, err := syscall.Open(path, os.O_RDONLY, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer syscall.Close(fd)\n\tbuf := make([]byte, 4096) // No MAXPATHLEN in syscall, I think it's 1024, this is bigger.\n\n\t// Wheeee! syscall doesn't expose a way to call Fcntl except FcntlFlock.\n\t// As of writing, it just passes the pointer through, so we can just lie.\n\tif err := syscall.FcntlFlock(uintptr(fd), syscall.F_GETPATH, (*syscall.Flock_t)(unsafe.Pointer(&buf[0]))); err != nil {\n\t\treturn err\n\t}\n\tbuf = buf[:bytes.IndexByte(buf, 0)]\n\n\tisRoot := func(p string) bool {\n\t\treturn p[len(p)-1] == filepath.Separator\n\t}\n\t// Darwin seems to like having multiple names for the same folder. Match as much of the suffix as we can.\n\tfor got, want := path, string(buf); !isRoot(got) && !isRoot(want); got, want = filepath.Dir(got), filepath.Dir(want) {\n\t\tg, w := filepath.Base(got), filepath.Base(want)\n\t\tif !strings.EqualFold(g, w) {\n\t\t\tbreak\n\t\t}\n\t\tif g != w {\n\t\t\treturn fmt.Errorf(\"invalid path %q: component %q is listed by macOS as %q\", path, g, w)\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/os_windows.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"syscall\"\n)\n\nfunc init() {\n\tcheckPathValid = windowsCheckPathValid\n}\n\nfunc windowsCheckPathValid(path string) error {\n\t// Back in the day, Windows used to have short and long filenames, and\n\t// it still supports those APIs. GetLongPathName gets the real case for a\n\t// path, so we can use it here. Inspired by\n\t// http://stackoverflow.com/q/2113822.\n\n\tnamep, err := syscall.UTF16PtrFromString(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Short paths can be longer than long paths, and unicode, so be generous.\n\tplenty := 4 * len(path)\n\n\tshort := make([]uint16, plenty)\n\tn, err := syscall.GetShortPathName(namep, &short[0], uint32(len(short)))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif int(n) > len(short) {\n\t\treturn fmt.Errorf(\"short buffer too short: %v vs %v\", n, len(short))\n\t}\n\n\tlong := make([]uint16, plenty)\n\tn, err = syscall.GetLongPathName(&short[0], &long[0], uint32(len(long)))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif int(n) > len(long) {\n\t\treturn fmt.Errorf(\"long buffer too short: %v vs %v\", n, len(long))\n\t}\n\tlongstr := syscall.UTF16ToString(long)\n\n\t// Check that the the path -> short -> long roundtrip was idempotent.\n\tisRoot := func(p string) bool {\n\t\treturn p[len(p)-1] == filepath.Separator\n\t}\n\tfor got, want := path, longstr; !isRoot(got) && !isRoot(want); got, want = filepath.Dir(got), filepath.Dir(want) {\n\t\tif g, w := filepath.Base(got), filepath.Base(want); g != w {\n\t\t\treturn fmt.Errorf(\"invalid path %q: component %q is listed by Windows as %q\", path, g, w)\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/package.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/methodsets\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/testfuncs\"\n\t\"golang.org/x/tools/gopls/internal/cache/xrefs\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// Convenient aliases for very heavily used types.\ntype (\n\tPackageID   = metadata.PackageID\n\tPackagePath = metadata.PackagePath\n\tPackageName = metadata.PackageName\n\tImportPath  = metadata.ImportPath\n)\n\n// A Package is the union of package metadata and type checking results.\n//\n// TODO(rfindley): for now, we do not persist the post-processing of\n// loadDiagnostics, because the value of the snapshot.packages map is just the\n// package handle. Fix this.\ntype Package struct {\n\tmetadata        *metadata.Package\n\tloadDiagnostics []*Diagnostic\n\tpkg             *syntaxPackage\n}\n\n// syntaxPackage contains parse trees and type information for a package.\ntype syntaxPackage struct {\n\t// -- identifiers --\n\tid PackageID\n\n\t// -- outputs --\n\tfset            *token.FileSet // for now, same as the snapshot's FileSet\n\tgoFiles         []*parsego.File\n\tcompiledGoFiles []*parsego.File\n\tdiagnostics     []*Diagnostic\n\tparseErrors     []scanner.ErrorList\n\ttypeErrors      []types.Error\n\ttypes           *types.Package\n\ttypesInfo       *types.Info\n\ttypesSizes      types.Sizes\n\timportMap       map[PackagePath]*types.Package\n\n\txrefsOnce sync.Once\n\t_xrefs    []byte // only used by the xrefs method\n\n\tmethodsetsOnce sync.Once\n\t_methodsets    *methodsets.Index // only used by the methodsets method\n\n\ttestsOnce sync.Once\n\t_tests    *testfuncs.Index // only used by the tests method\n}\n\nfunc (p *syntaxPackage) xrefs() []byte {\n\tp.xrefsOnce.Do(func() {\n\t\tp._xrefs = xrefs.Index(p.compiledGoFiles, p.types, p.typesInfo)\n\t})\n\treturn p._xrefs\n}\n\nfunc (p *syntaxPackage) methodsets() *methodsets.Index {\n\tp.methodsetsOnce.Do(func() {\n\t\tp._methodsets = methodsets.NewIndex(p.fset, p.types)\n\t})\n\treturn p._methodsets\n}\n\nfunc (p *syntaxPackage) tests() *testfuncs.Index {\n\tp.testsOnce.Do(func() {\n\t\tp._tests = testfuncs.NewIndex(p.compiledGoFiles, p.typesInfo)\n\t})\n\treturn p._tests\n}\n\n// hasFixedFiles reports whether there are any 'fixed' compiled go files in the\n// package.\n//\n// Intended to be used to refine bug reports.\nfunc (p *syntaxPackage) hasFixedFiles() bool {\n\treturn slices.ContainsFunc(p.compiledGoFiles, (*parsego.File).Fixed)\n}\n\nfunc (p *Package) String() string { return string(p.metadata.ID) }\n\nfunc (p *Package) Metadata() *metadata.Package { return p.metadata }\n\n// A loadScope defines a package loading scope for use with go/packages.\n//\n// TODO(rfindley): move this to load.go.\ntype loadScope interface {\n\taScope()\n}\n\n// TODO(rfindley): move to load.go\ntype (\n\tfileLoadScope    protocol.DocumentURI // load packages containing a file (including command-line-arguments)\n\tpackageLoadScope string               // load a specific package (the value is its PackageID)\n\tmoduleLoadScope  struct {\n\t\tdir        string // dir containing the go.mod file\n\t\tmodulePath string // parsed module path\n\t}\n\tviewLoadScope struct{} // load the workspace\n)\n\n// Implement the loadScope interface.\nfunc (fileLoadScope) aScope()    {}\nfunc (packageLoadScope) aScope() {}\nfunc (moduleLoadScope) aScope()  {}\nfunc (viewLoadScope) aScope()    {}\n\nfunc (p *Package) CompiledGoFiles() []*parsego.File {\n\treturn p.pkg.compiledGoFiles\n}\n\nfunc (p *Package) File(uri protocol.DocumentURI) (*parsego.File, error) {\n\treturn p.pkg.File(uri)\n}\n\n// FileEnclosing returns the file of pkg that encloses the specified position,\n// which must be mapped by p.FileSet().\nfunc (p *Package) FileEnclosing(pos token.Pos) (*parsego.File, error) {\n\tfor _, files := range [...][]*parsego.File{p.pkg.compiledGoFiles, p.pkg.goFiles} {\n\t\tfor _, pgf := range files {\n\t\t\tif pgf.File.FileStart <= pos && pos <= pgf.File.FileEnd {\n\t\t\t\treturn pgf, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"no parsed file for position %d (%s) in %v\",\n\t\tpos, safetoken.StartPosition(p.FileSet(), pos), p.pkg.id)\n}\n\nfunc (pkg *syntaxPackage) File(uri protocol.DocumentURI) (*parsego.File, error) {\n\tfor _, files := range [...][]*parsego.File{pkg.compiledGoFiles, pkg.goFiles} {\n\t\tfor _, pgf := range files {\n\t\t\tif pgf.URI == uri {\n\t\t\t\treturn pgf, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"no parsed file for %s in %v\", uri, pkg.id)\n}\n\n// Syntax returns parsed compiled Go files contained in this package.\nfunc (p *Package) Syntax() []*ast.File {\n\tvar syntax []*ast.File\n\tfor _, pgf := range p.pkg.compiledGoFiles {\n\t\tsyntax = append(syntax, pgf.File)\n\t}\n\treturn syntax\n}\n\n// FileSet returns the FileSet describing this package's positions.\n//\n// The returned FileSet is guaranteed to describe all Syntax, but may also\n// describe additional files.\nfunc (p *Package) FileSet() *token.FileSet {\n\treturn p.pkg.fset\n}\n\n// Types returns the type checked go/types.Package.\nfunc (p *Package) Types() *types.Package {\n\treturn p.pkg.types\n}\n\n// TypesInfo returns the go/types.Info annotating the Syntax of this package\n// with type information.\n//\n// All fields in the resulting Info are populated.\nfunc (p *Package) TypesInfo() *types.Info {\n\treturn p.pkg.typesInfo\n}\n\n// TypesSizes returns the sizing function used for types in this package.\nfunc (p *Package) TypesSizes() types.Sizes {\n\treturn p.pkg.typesSizes\n}\n\n// DependencyTypes returns the type checker's symbol for the specified\n// package. It returns nil if path is not among the transitive\n// dependencies of p, or if no symbols from that package were\n// referenced during the type-checking of p.\nfunc (p *Package) DependencyTypes(path PackagePath) *types.Package {\n\treturn p.pkg.importMap[path]\n}\n\n// ParseErrors returns a slice containing all non-empty parse errors produces\n// while parsing p.Syntax, or nil if the package contains no parse errors.\nfunc (p *Package) ParseErrors() []scanner.ErrorList {\n\treturn p.pkg.parseErrors\n}\n\n// TypeErrors returns the go/types.Errors produced during type checking this\n// package, if any.\nfunc (p *Package) TypeErrors() []types.Error {\n\treturn p.pkg.typeErrors\n}\n"
  },
  {
    "path": "gopls/internal/cache/parse.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n)\n\n// ParseGo parses the file whose contents are provided by fh.\n// The resulting tree may have been fixed up.\n// If the file is not available, returns nil and an error.\nfunc (s *Snapshot) ParseGo(ctx context.Context, fh file.Handle, mode parser.Mode) (*parsego.File, error) {\n\tpgfs, err := s.view.parseCache.parseFiles(ctx, token.NewFileSet(), mode, false, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pgfs[0], nil\n}\n\n// parseGoImpl parses the Go source file whose content is provided by fh.\nfunc parseGoImpl(ctx context.Context, fset *token.FileSet, fh file.Handle, mode parser.Mode, purgeFuncBodies bool) (*parsego.File, error) {\n\text := filepath.Ext(fh.URI().Path())\n\tif ext != \".go\" && ext != \"\" { // files generated by cgo have no extension\n\t\treturn nil, fmt.Errorf(\"cannot parse non-Go file %s\", fh.URI())\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Check for context cancellation before actually doing the parse.\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tpgf, _ := parsego.Parse(ctx, fset, fh.URI(), content, mode, purgeFuncBodies) // ignore 'fixes'\n\treturn pgf, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/parse_cache.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"container/heap\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"math/bits\"\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n)\n\n// This file contains an implementation of an LRU parse cache, that offsets the\n// base token.Pos value of each cached file so that they may be later described\n// by a single dedicated FileSet.\n//\n// This is achieved by tracking a monotonic offset in the token.Pos space, that\n// is incremented before parsing allow room for the resulting parsed file.\n\n// reservedForParsing defines the room in the token.Pos space reserved for\n// cached parsed files.\n//\n// Files parsed through the parseCache are guaranteed not to have overlapping\n// spans: the parseCache tracks a monotonic base for newly parsed files.\n//\n// By offsetting the initial base of a FileSet, we can allow other operations\n// accepting the FileSet (such as the gcimporter) to add new files using the\n// normal FileSet APIs without overlapping with cached parsed files.\n//\n// Note that 1<<60 represents an exabyte of parsed data, more than any gopls\n// process can ever parse.\n//\n// On 32-bit systems we don't cache parse results (see parseFiles).\nconst reservedForParsing = 1 << (bits.UintSize - 4)\n\n// fileSetWithBase returns a new token.FileSet with Base() equal to the\n// requested base.\n//\n// If base < 1, fileSetWithBase panics.\n// (1 is the smallest permitted FileSet base).\nfunc fileSetWithBase(base int) *token.FileSet {\n\tfset := token.NewFileSet()\n\tif base > 1 {\n\t\t// Add a dummy file to set the base of fset. We won't ever use the\n\t\t// resulting FileSet, so it doesn't matter how we achieve this.\n\t\t//\n\t\t// FileSets leave a 1-byte padding between files, so we set the base by\n\t\t// adding a zero-length file at base-1.\n\t\tfset.AddFile(\"\", base-1, 0)\n\t}\n\tif fset.Base() != base {\n\t\tpanic(\"unexpected FileSet.Base\")\n\t}\n\treturn fset\n}\n\nconst (\n\t// Always keep 100 recent files, independent of their wall-clock age, to\n\t// optimize the case where the user resumes editing after a delay.\n\tparseCacheMinFiles = 100\n)\n\n// parsePadding is additional padding allocated to allow for increases in\n// length (such as appending missing braces) caused by fixAST.\n//\n// This is used to mitigate a chicken and egg problem: we must know the base\n// offset of the file we're about to parse, before we start parsing, and yet\n// src fixups may affect the actual size of the parsed content (and therefore\n// the offsets of subsequent files).\n//\n// When we encounter a file that no longer fits in its allocated space in the\n// fileset, we have no choice but to re-parse it. Leaving a generous padding\n// reduces the likelihood of this \"slow path\".\n//\n// This value is mutable for testing, so that we can exercise the slow path.\nvar parsePadding = 1000 // mutable for testing\n\n// A parseCache holds recently accessed parsed Go files. After new files are\n// stored, older files may be evicted from the cache via garbage collection.\n//\n// The parseCache.parseFiles method exposes a batch API for parsing (and\n// caching) multiple files. This is necessary for type-checking, where files\n// must be parsed in a common fileset.\ntype parseCache struct {\n\texpireAfter time.Duration // interval at which to collect expired cache entries\n\tdone        chan struct{} // closed when GC is stopped\n\n\tmu       sync.Mutex\n\tm        map[parseKey]*parseCacheEntry\n\tlru      queue  // min-atime priority queue of *parseCacheEntry\n\tclock    uint64 // clock time, incremented when the cache is updated\n\tnextBase int    // base offset for the next parsed file\n}\n\n// newParseCache creates a new parse cache and starts a goroutine to garbage\n// collect entries whose age is at least expireAfter.\n//\n// Callers must call parseCache.stop when the parse cache is no longer in use.\nfunc newParseCache(expireAfter time.Duration) *parseCache {\n\tc := &parseCache{\n\t\texpireAfter: expireAfter,\n\t\tm:           make(map[parseKey]*parseCacheEntry),\n\t\tdone:        make(chan struct{}),\n\t}\n\tgo c.gc()\n\treturn c\n}\n\n// stop causes the GC goroutine to exit.\nfunc (c *parseCache) stop() {\n\tclose(c.done)\n}\n\n// parseKey uniquely identifies a parsed Go file.\ntype parseKey struct {\n\turi             protocol.DocumentURI\n\tmode            parser.Mode\n\tpurgeFuncBodies bool\n}\n\ntype parseCacheEntry struct {\n\tkey      parseKey\n\thash     file.Hash\n\tpromise  *memoize.Promise // memoize.Promise[*parsego.File]\n\tatime    uint64           // clock time of last access, for use in LRU sorting\n\twalltime time.Time        // actual time of last access, for use in time-based eviction; too coarse for LRU on some systems\n\tlruIndex int              // owned by the queue implementation\n}\n\n// startParse prepares a parsing pass, creating new promises in the cache for\n// any cache misses.\n//\n// The resulting slice has an entry for every given file handle, though some\n// entries may be nil if there was an error reading the file (in which case the\n// resulting error will be non-nil).\nfunc (c *parseCache) startParse(mode parser.Mode, purgeFuncBodies bool, fhs ...file.Handle) ([]*memoize.Promise, error) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\t// Any parsing pass increments the clock, as we'll update access times.\n\t// (technically, if fhs is empty this isn't necessary, but that's a degenerate case).\n\t//\n\t// All entries parsed from a single call get the same access time.\n\tc.clock++\n\twalltime := time.Now()\n\n\t// Read file data and collect cacheable files.\n\tvar (\n\t\tdata           = make([][]byte, len(fhs)) // file content for each readable file\n\t\tpromises       = make([]*memoize.Promise, len(fhs))\n\t\tfirstReadError error // first error from fh.Read, or nil\n\t)\n\tfor i, fh := range fhs {\n\t\tcontent, err := fh.Content()\n\t\tif err != nil {\n\t\t\tif firstReadError == nil {\n\t\t\t\tfirstReadError = err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tdata[i] = content\n\n\t\tkey := parseKey{\n\t\t\turi:             fh.URI(),\n\t\t\tmode:            mode,\n\t\t\tpurgeFuncBodies: purgeFuncBodies,\n\t\t}\n\n\t\tif e, ok := c.m[key]; ok {\n\t\t\tif e.hash == fh.Identity().Hash { // cache hit\n\t\t\t\te.atime = c.clock\n\t\t\t\te.walltime = walltime\n\t\t\t\theap.Fix(&c.lru, e.lruIndex)\n\t\t\t\tpromises[i] = e.promise\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\t// A cache hit, for a different version. Delete it.\n\t\t\t\tdelete(c.m, e.key)\n\t\t\t\theap.Remove(&c.lru, e.lruIndex)\n\t\t\t}\n\t\t}\n\n\t\turi := fh.URI()\n\t\tpromise := memoize.NewPromise(\"parseCache.parse\", func(ctx context.Context, _ any) any {\n\t\t\t// Allocate 2*len(content)+parsePadding to allow for re-parsing once\n\t\t\t// inside of parseGoSrc without exceeding the allocated space.\n\t\t\tbase, nextBase := c.allocateSpace(2*len(content) + parsePadding)\n\n\t\t\tpgf, fixes1 := parsego.Parse(ctx, fileSetWithBase(base), uri, content, mode, purgeFuncBodies)\n\t\t\tfile := pgf.Tok\n\t\t\tif file.Base()+file.Size()+1 > nextBase {\n\t\t\t\t// The parsed file exceeds its allocated space, likely due to multiple\n\t\t\t\t// passes of src fixing. In this case, we have no choice but to re-do\n\t\t\t\t// the operation with the correct size.\n\t\t\t\t//\n\t\t\t\t// Even though the final successful parse requires only file.Size()\n\t\t\t\t// bytes of Pos space, we need to accommodate all the missteps to get\n\t\t\t\t// there, as parseGoSrc will repeat them.\n\t\t\t\tactual := file.Base() + file.Size() - base // actual size consumed, after re-parsing\n\t\t\t\tbase2, nextBase2 := c.allocateSpace(actual)\n\t\t\t\tpgf2, fixes2 := parsego.Parse(ctx, fileSetWithBase(base2), uri, content, mode, purgeFuncBodies)\n\n\t\t\t\t// In golang/go#59097 we observed that this panic condition was hit.\n\t\t\t\t// One bug was found and fixed, but record more information here in\n\t\t\t\t// case there is still a bug here.\n\t\t\t\tif end := pgf2.Tok.Base() + pgf2.Tok.Size(); end != nextBase2-1 {\n\t\t\t\t\tvar errBuf bytes.Buffer\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"internal error: non-deterministic parsing result:\\n\")\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\t%q (%d-%d) does not span %d-%d\\n\", uri, pgf2.Tok.Base(), base2, end, nextBase2-1)\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\tfirst %q (%d-%d)\\n\", pgf.URI, pgf.Tok.Base(), pgf.Tok.Base()+pgf.Tok.Size())\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\tfirst space: (%d-%d), second space: (%d-%d)\\n\", base, nextBase, base2, nextBase2)\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\tfirst mode: %v, second mode: %v\", pgf.Mode, pgf2.Mode)\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\tfirst err: %v, second err: %v\", pgf.ParseErr, pgf2.ParseErr)\n\t\t\t\t\tfmt.Fprintf(&errBuf, \"\\tfirst fixes: %v, second fixes: %v\", fixes1, fixes2)\n\t\t\t\t\tpanic(errBuf.String())\n\t\t\t\t}\n\t\t\t\tpgf = pgf2\n\t\t\t}\n\t\t\treturn pgf\n\t\t})\n\t\tpromises[i] = promise\n\n\t\t// add new entry; entries are gc'ed asynchronously\n\t\te := &parseCacheEntry{\n\t\t\tkey:      key,\n\t\t\thash:     fh.Identity().Hash,\n\t\t\tpromise:  promise,\n\t\t\tatime:    c.clock,\n\t\t\twalltime: walltime,\n\t\t}\n\t\tc.m[e.key] = e\n\t\theap.Push(&c.lru, e)\n\t}\n\n\tif len(c.m) != len(c.lru) {\n\t\tpanic(\"map and LRU are inconsistent\")\n\t}\n\n\treturn promises, firstReadError\n}\n\nfunc (c *parseCache) gc() {\n\tconst period = 10 * time.Second // gc period\n\ttimer := time.NewTicker(period)\n\tdefer timer.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-c.done:\n\t\t\treturn\n\t\tcase <-timer.C:\n\t\t}\n\n\t\tc.gcOnce()\n\t}\n}\n\nfunc (c *parseCache) gcOnce() {\n\tnow := time.Now()\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tfor len(c.m) > parseCacheMinFiles {\n\t\te := heap.Pop(&c.lru).(*parseCacheEntry)\n\t\tif now.Sub(e.walltime) >= c.expireAfter {\n\t\t\tdelete(c.m, e.key)\n\t\t} else {\n\t\t\theap.Push(&c.lru, e)\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// allocateSpace reserves the next n bytes of token.Pos space in the\n// cache.\n//\n// It returns the resulting file base, next base, and an offset FileSet to use\n// for parsing.\nfunc (c *parseCache) allocateSpace(size int) (int, int) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tif c.nextBase == 0 {\n\t\t// FileSet base values must be at least 1.\n\t\tc.nextBase = 1\n\t}\n\tbase := c.nextBase\n\tc.nextBase += size + 1\n\treturn base, c.nextBase\n}\n\n// parseFiles returns a parsego.File for each file handle in fhs, in the\n// requested parse mode.\n//\n// For parsed files that already exists in the cache, access time will be\n// updated. For others, parseFiles will parse and store as many results in the\n// cache as space allows.\n//\n// The token.File for each resulting parsed file will be added to the provided\n// FileSet, using the tokeninternal.AddExistingFiles API. Consequently, the\n// given fset should only be used in other APIs if its base is >=\n// reservedForParsing.\n//\n// If parseFiles returns an error, it still returns a slice,\n// but with a nil entry for each file that could not be parsed.\nfunc (c *parseCache) parseFiles(ctx context.Context, fset *token.FileSet, mode parser.Mode, purgeFuncBodies bool, fhs ...file.Handle) ([]*parsego.File, error) {\n\tpgfs := make([]*parsego.File, len(fhs))\n\n\t// Temporary fall-back for 32-bit systems, where reservedForParsing is too\n\t// small to be viable. We don't actually support 32-bit systems, so this\n\t// workaround is only for tests and can be removed when we stop running\n\t// 32-bit TryBots for gopls.\n\tif bits.UintSize == 32 {\n\t\tfor i, fh := range fhs {\n\t\t\tvar err error\n\t\t\tpgfs[i], err = parseGoImpl(ctx, fset, fh, mode, purgeFuncBodies)\n\t\t\tif err != nil {\n\t\t\t\treturn pgfs, err\n\t\t\t}\n\t\t}\n\t\treturn pgfs, nil\n\t}\n\n\tpromises, firstErr := c.startParse(mode, purgeFuncBodies, fhs...)\n\n\t// Await all parsing.\n\tvar g errgroup.Group\n\tg.SetLimit(runtime.GOMAXPROCS(-1)) // parsing is CPU-bound.\n\tfor i, promise := range promises {\n\t\tif promise == nil {\n\t\t\tcontinue\n\t\t}\n\t\ti := i\n\t\tpromise := promise\n\t\tg.Go(func() error {\n\t\t\tresult, err := promise.Get(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpgfs[i] = result.(*parsego.File)\n\t\t\treturn nil\n\t\t})\n\t}\n\n\tif err := g.Wait(); err != nil && firstErr == nil {\n\t\tfirstErr = err\n\t}\n\n\t// Augment the FileSet to map all parsed files.\n\tvar tokenFiles []*token.File\n\tfor _, pgf := range pgfs {\n\t\tif pgf == nil {\n\t\t\tcontinue\n\t\t}\n\t\ttokenFiles = append(tokenFiles, pgf.Tok)\n\t}\n\tfset.AddExistingFiles(tokenFiles...)\n\n\tconst debugIssue59080 = true\n\tif debugIssue59080 {\n\t\tfor _, f := range tokenFiles {\n\t\t\tpos := token.Pos(f.Base())\n\t\t\tf2 := fset.File(pos)\n\t\t\tif f2 != f {\n\t\t\t\tpanic(fmt.Sprintf(\"internal error: File(%d (start)) = %v, not %v\", pos, f2, f))\n\t\t\t}\n\t\t\tpos = token.Pos(f.Base() + f.Size())\n\t\t\tf2 = fset.File(pos)\n\t\t\tif f2 != f {\n\t\t\t\tpanic(fmt.Sprintf(\"internal error: File(%d (end)) = %v, not %v\", pos, f2, f))\n\t\t\t}\n\t\t}\n\t}\n\n\treturn pgfs, firstErr\n}\n\n// -- priority queue boilerplate --\n\n// queue is a min-atime priority queue of cache entries.\ntype queue []*parseCacheEntry\n\nfunc (q queue) Len() int { return len(q) }\n\nfunc (q queue) Less(i, j int) bool { return q[i].atime < q[j].atime }\n\nfunc (q queue) Swap(i, j int) {\n\tq[i], q[j] = q[j], q[i]\n\tq[i].lruIndex = i\n\tq[j].lruIndex = j\n}\n\nfunc (q *queue) Push(x any) {\n\te := x.(*parseCacheEntry)\n\te.lruIndex = len(*q)\n\t*q = append(*q, e)\n}\n\nfunc (q *queue) Pop() any {\n\tlast := len(*q) - 1\n\te := (*q)[last]\n\t(*q)[last] = nil // aid GC\n\t*q = (*q)[:last]\n\treturn e\n}\n"
  },
  {
    "path": "gopls/internal/cache/parse_cache_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"math/bits\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc skipIfNoParseCache(t *testing.T) {\n\tif bits.UintSize == 32 {\n\t\tt.Skip(\"the parse cache is not supported on 32-bit systems\")\n\t}\n}\n\nfunc TestParseCache(t *testing.T) {\n\tskipIfNoParseCache(t)\n\n\tctx := context.Background()\n\turi := protocol.DocumentURI(\"file:///myfile\")\n\tfh := makeFakeFileHandle(uri, []byte(\"package p\\n\\nconst _ = \\\"foo\\\"\"))\n\tfset := token.NewFileSet()\n\n\tcache := newParseCache(0)\n\tpgfs1, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpgf1 := pgfs1[0]\n\tpgfs2, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh)\n\tpgf2 := pgfs2[0]\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif pgf1 != pgf2 {\n\t\tt.Errorf(\"parseFiles(%q): unexpected cache miss on repeated call\", uri)\n\t}\n\n\t// Fill up the cache with other files, but don't evict the file above.\n\tcache.gcOnce()\n\tfiles := []file.Handle{fh}\n\tfiles = append(files, dummyFileHandles(parseCacheMinFiles-1)...)\n\n\tpgfs3, err := cache.parseFiles(ctx, fset, parsego.Full, false, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpgf3 := pgfs3[0]\n\tif pgf3 != pgf1 {\n\t\tt.Errorf(\"parseFiles(%q, ...): unexpected cache miss\", uri)\n\t}\n\tif pgf3.Tok.Base() != pgf1.Tok.Base() || pgf3.Tok.Size() != pgf1.Tok.Size() {\n\t\tt.Errorf(\"parseFiles(%q, ...): result.Tok has base: %d, size: %d, want (%d, %d)\", uri, pgf3.Tok.Base(), pgf3.Tok.Size(), pgf1.Tok.Base(), pgf1.Tok.Size())\n\t}\n\tif tok := fset.File(token.Pos(pgf3.Tok.Base())); tok != pgf3.Tok {\n\t\tt.Errorf(\"parseFiles(%q, ...): result.Tok not contained in FileSet\", uri)\n\t}\n\n\t// Now overwrite the cache, after which we should get new results.\n\tcache.gcOnce()\n\tfiles = dummyFileHandles(parseCacheMinFiles)\n\t_, err = cache.parseFiles(ctx, fset, parsego.Full, false, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// force a GC, which should collect the recently parsed files\n\tcache.gcOnce()\n\tpgfs4, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif pgfs4[0] == pgf1 {\n\t\tt.Errorf(\"parseFiles(%q): unexpected cache hit after overwriting cache\", uri)\n\t}\n}\n\nfunc TestParseCache_Reparsing(t *testing.T) {\n\tskipIfNoParseCache(t)\n\n\tdefer func(padding int) {\n\t\tparsePadding = padding\n\t}(parsePadding)\n\tparsePadding = 0\n\n\tfiles := dummyFileHandles(parseCacheMinFiles)\n\tdanglingSelector := []byte(\"package p\\nfunc _() {\\n\\tx.\\n}\")\n\tfiles = append(files, makeFakeFileHandle(\"file:///bad1\", danglingSelector))\n\tfiles = append(files, makeFakeFileHandle(\"file:///bad2\", danglingSelector))\n\n\t// Parsing should succeed even though we overflow the padding.\n\tcache := newParseCache(0)\n\t_, err := cache.parseFiles(context.Background(), token.NewFileSet(), parsego.Full, false, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\n// Re-parsing the first file should not panic.\nfunc TestParseCache_Issue59097(t *testing.T) {\n\tskipIfNoParseCache(t)\n\n\tdefer func(padding int) {\n\t\tparsePadding = padding\n\t}(parsePadding)\n\tparsePadding = 0\n\n\tdanglingSelector := []byte(\"package p\\nfunc _() {\\n\\tx.\\n}\")\n\tfiles := []file.Handle{makeFakeFileHandle(\"file:///bad\", danglingSelector)}\n\n\t// Parsing should succeed even though we overflow the padding.\n\tcache := newParseCache(0)\n\t_, err := cache.parseFiles(context.Background(), token.NewFileSet(), parsego.Full, false, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestParseCache_TimeEviction(t *testing.T) {\n\tskipIfNoParseCache(t)\n\n\tctx := context.Background()\n\tfset := token.NewFileSet()\n\turi := protocol.DocumentURI(\"file:///myfile\")\n\tfh := makeFakeFileHandle(uri, []byte(\"package p\\n\\nconst _ = \\\"foo\\\"\"))\n\n\tconst gcDuration = 10 * time.Millisecond\n\tcache := newParseCache(gcDuration)\n\tcache.stop() // we'll manage GC manually, for testing.\n\n\tpgfs0, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfiles := dummyFileHandles(parseCacheMinFiles)\n\t_, err = cache.parseFiles(ctx, fset, parsego.Full, false, files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Even after filling up the 'min' files, we get a cache hit for our original file.\n\tpgfs1, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif pgfs0[0] != pgfs1[0] {\n\t\tt.Errorf(\"before GC, got unexpected cache miss\")\n\t}\n\n\t// But after GC, we get a cache miss.\n\t_, err = cache.parseFiles(ctx, fset, parsego.Full, false, files...) // mark dummy files as newer\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttime.Sleep(gcDuration)\n\tcache.gcOnce()\n\n\tpgfs2, err := cache.parseFiles(ctx, fset, parsego.Full, false, fh, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif pgfs0[0] == pgfs2[0] {\n\t\tt.Errorf(\"after GC, got unexpected cache hit for %s\", pgfs0[0].URI)\n\t}\n}\n\nfunc TestParseCache_Duplicates(t *testing.T) {\n\tskipIfNoParseCache(t)\n\n\tctx := context.Background()\n\turi := protocol.DocumentURI(\"file:///myfile\")\n\tfh := makeFakeFileHandle(uri, []byte(\"package p\\n\\nconst _ = \\\"foo\\\"\"))\n\n\tcache := newParseCache(0)\n\tpgfs, err := cache.parseFiles(ctx, token.NewFileSet(), parsego.Full, false, fh, fh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif pgfs[0] != pgfs[1] {\n\t\tt.Errorf(\"parseFiles(fh, fh): = [%p, %p], want duplicate files\", pgfs[0].File, pgfs[1].File)\n\t}\n}\n\nfunc dummyFileHandles(n int) []file.Handle {\n\tvar fhs []file.Handle\n\tfor i := range n {\n\t\turi := protocol.DocumentURI(fmt.Sprintf(\"file:///_%d\", i))\n\t\tsrc := fmt.Appendf(nil, \"package p\\nvar _ = %d\", i)\n\t\tfhs = append(fhs, makeFakeFileHandle(uri, src))\n\t}\n\treturn fhs\n}\n\nfunc makeFakeFileHandle(uri protocol.DocumentURI, src []byte) fakeFileHandle {\n\treturn fakeFileHandle{\n\t\turi:  uri,\n\t\tdata: src,\n\t\thash: file.HashOf(src),\n\t}\n}\n\ntype fakeFileHandle struct {\n\tfile.Handle\n\turi  protocol.DocumentURI\n\tdata []byte\n\thash file.Hash\n}\n\nfunc (h fakeFileHandle) String() string {\n\treturn h.uri.Path()\n}\n\nfunc (h fakeFileHandle) URI() protocol.DocumentURI {\n\treturn h.uri\n}\n\nfunc (h fakeFileHandle) Content() ([]byte, error) {\n\treturn h.data, nil\n}\n\nfunc (h fakeFileHandle) Identity() file.Identity {\n\treturn file.Identity{\n\t\tURI:  h.uri,\n\t\tHash: h.hash,\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/file.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage parsego\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"sync\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// A File contains the results of parsing a Go file.\ntype File struct {\n\tURI  protocol.DocumentURI\n\tMode parser.Mode\n\n\t// File is the file resulting from parsing. It is always non-nil.\n\t//\n\t// Clients must not access the AST's legacy ast.Object-related\n\t// fields without first ensuring that [File.Resolve] was\n\t// already called.\n\tFile *ast.File\n\tTok  *token.File\n\t// Source code used to build the AST. It may be different from the\n\t// actual content of the file if we have fixed the AST.\n\tSrc []byte\n\n\tcursor     inspector.Cursor // cursor of *ast.File, sans sibling files\n\tcursorOnce sync.Once\n\n\t// fixedSrc and fixedAST report on \"fixing\" that occurred during parsing of\n\t// this file.\n\t//\n\t// fixedSrc means Src holds file content that was modified to improve parsing.\n\t// fixedAST means File was modified after parsing, so AST positions may not\n\t// reflect the content of Src.\n\t//\n\t// TODO(rfindley): there are many places where we haphazardly use the Src or\n\t// positions without checking these fields. Audit these places and guard\n\t// accordingly. After doing so, we may find that we don't need to\n\t// differentiate fixedSrc and fixedAST.\n\tfixedSrc bool\n\tfixedAST bool\n\tMapper   *protocol.Mapper // may map fixed Src, not file content\n\tParseErr scanner.ErrorList\n\n\t// resolveOnce guards the lazy ast.Object resolution. See [File.Resolve].\n\tresolveOnce sync.Once\n}\n\nfunc (pgf *File) String() string { return string(pgf.URI) }\n\n// Cursor returns a cursor for pgf.File, for fast and convenient navigation.\nfunc (pgf *File) Cursor() inspector.Cursor {\n\tpgf.cursorOnce.Do(func() {\n\t\tinspect := inspector.New([]*ast.File{pgf.File})\n\t\tpgf.cursor, _ = inspect.Root().FirstChild()\n\t\t_ = pgf.cursor.Node().(*ast.File)\n\t})\n\treturn pgf.cursor\n}\n\n// Fixed reports whether p was \"Fixed\", meaning that its source or positions\n// may not correlate with the original file.\nfunc (pgf *File) Fixed() bool {\n\treturn pgf.fixedSrc || pgf.fixedAST\n}\n\n// -- go/token domain convenience helpers --\n\n// PositionPos returns the token.Pos of protocol position p within the file.\nfunc (pgf *File) PositionPos(p protocol.Position) (token.Pos, error) {\n\toffset, err := pgf.Mapper.PositionOffset(p)\n\tif err != nil {\n\t\treturn token.NoPos, err\n\t}\n\treturn safetoken.Pos(pgf.Tok, offset)\n}\n\n// PosPosition returns a protocol Position for the token.Pos in this file.\nfunc (pgf *File) PosPosition(pos token.Pos) (protocol.Position, error) {\n\treturn pgf.Mapper.PosPosition(pgf.Tok, pos)\n}\n\n// PosRange returns a protocol Range for the token.Pos interval in this file.\nfunc (pgf *File) PosRange(start, end token.Pos) (protocol.Range, error) {\n\treturn pgf.Mapper.PosRange(pgf.Tok, start, end)\n}\n\n// PosLocation returns a protocol Location for the token.Pos interval in this file.\nfunc (pgf *File) PosLocation(start, end token.Pos) (protocol.Location, error) {\n\treturn pgf.Mapper.PosLocation(pgf.Tok, start, end)\n}\n\n// PosText returns the source text for the token.Pos interval in this file.\nfunc (pgf *File) PosText(start, end token.Pos) ([]byte, error) {\n\treturn pgf.Mapper.PosText(pgf.Tok, start, end)\n}\n\n// NodeRange returns a protocol Range for the ast.Node interval in this file.\nfunc (pgf *File) NodeRange(node ast.Node) (protocol.Range, error) {\n\treturn pgf.Mapper.NodeRange(pgf.Tok, node)\n}\n\n// NodeOffsets returns offsets for the ast.Node.\nfunc (pgf *File) NodeOffsets(node ast.Node) (start int, end int, _ error) {\n\treturn safetoken.Offsets(pgf.Tok, node.Pos(), node.End())\n}\n\n// NodeLocation returns a protocol Location for the ast.Node interval in this file.\nfunc (pgf *File) NodeLocation(node ast.Node) (protocol.Location, error) {\n\treturn pgf.Mapper.PosLocation(pgf.Tok, node.Pos(), node.End())\n}\n\n// NodeText returns the source text for the ast.Node interval in this file.\nfunc (pgf *File) NodeText(node ast.Node) ([]byte, error) {\n\treturn pgf.Mapper.NodeText(pgf.Tok, node)\n}\n\n// RangePos parses a protocol Range back into the go/token domain.\nfunc (pgf *File) RangePos(r protocol.Range) (token.Pos, token.Pos, error) {\n\tstart, end, err := pgf.Mapper.RangeOffsets(r)\n\tif err != nil {\n\t\treturn token.NoPos, token.NoPos, err\n\t}\n\treturn pgf.Tok.Pos(start), pgf.Tok.Pos(end), nil\n}\n\n// CheckNode asserts that the Node's positions are valid w.r.t. pgf.Tok.\nfunc (pgf *File) CheckNode(node ast.Node) {\n\t// Avoid safetoken.Offsets, and put each assertion on its own source line.\n\tpgf.CheckPos(node.Pos())\n\tpgf.CheckPos(node.End())\n}\n\n// CheckPos asserts that the position is valid w.r.t. pgf.Tok.\nfunc (pgf *File) CheckPos(pos token.Pos) {\n\tif !pos.IsValid() {\n\t\tbug.Report(\"invalid token.Pos\")\n\t} else if _, err := safetoken.Offset(pgf.Tok, pos); err != nil {\n\t\tbug.Report(\"token.Pos out of range\")\n\t}\n}\n\n// Resolve lazily resolves ast.Ident.Objects in the enclosed syntax tree.\n//\n// Resolve must be called before accessing any of:\n//   - pgf.File.Scope\n//   - pgf.File.Unresolved\n//   - Ident.Obj, for any Ident in pgf.File\nfunc (pgf *File) Resolve() {\n\tpgf.resolveOnce.Do(func() {\n\t\tif pgf.File.Scope != nil {\n\t\t\treturn // already resolved by parsing without SkipObjectResolution.\n\t\t}\n\t\tdefer func() {\n\t\t\t// (panic handler duplicated from go/parser)\n\t\t\tif e := recover(); e != nil {\n\t\t\t\t// A bailout indicates the resolution stack has exceeded max depth.\n\t\t\t\tif _, ok := e.(bailout); !ok {\n\t\t\t\t\tpanic(e)\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\t\tdeclErr := func(token.Pos, string) {}\n\t\tresolveFile(pgf.File, pgf.Tok, declErr)\n\t})\n}\n\n// Indentation returns the string of spaces representing the indentation\n// of the line containing the specified position.\n// This can be used to ensure that inserted code maintains consistent indentation\n// and column alignment.\nfunc (pgf *File) Indentation(pos token.Pos) (string, error) {\n\tline := safetoken.Line(pgf.Tok, pos)\n\tstart, end, err := safetoken.Offsets(pgf.Tok, pgf.Tok.LineStart(line), pos)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\ts := string(pgf.Src[start:end])\n\tfor i, r := range s {\n\t\tif !unicode.IsSpace(r) {\n\t\t\treturn s[:i], nil // prefix of spaces\n\t\t}\n\t}\n\treturn s, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/parse.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run resolver_gen.go\n\n// The parsego package defines the [File] type, a wrapper around a go/ast.File\n// that is useful for answering LSP queries. Notably, it bundles the\n// *token.File and *protocol.Mapper necessary for token.Pos locations to and\n// from UTF-16 LSP positions.\n//\n// Run `go generate` to update resolver.go from GOROOT.\npackage parsego\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"reflect\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Common parse modes; these should be reused wherever possible to increase\n// cache hits.\nconst (\n\t// Header specifies that the main package declaration and imports are needed.\n\t// This is the mode used when attempting to examine the package graph structure.\n\tHeader = parser.AllErrors | parser.ParseComments | parser.ImportsOnly | parser.SkipObjectResolution\n\n\t// Full specifies the full AST is needed.\n\t// This is used for files of direct interest where the entire contents must\n\t// be considered.\n\tFull = parser.AllErrors | parser.ParseComments | parser.SkipObjectResolution\n)\n\n// Parse parses a buffer of Go source, repairing the tree if necessary.\n//\n// The provided ctx is used only for logging.\nfunc Parse(ctx context.Context, fset *token.FileSet, uri protocol.DocumentURI, src []byte, mode parser.Mode, purgeFuncBodies bool) (res *File, fixes []FixType) {\n\tif purgeFuncBodies {\n\t\tsrc = astutil.PurgeFuncBodies(src)\n\t}\n\tctx, done := event.Start(ctx, \"cache.ParseGoSrc\", label.File.Of(uri.Path()))\n\tdefer done()\n\n\tfile, err := parser.ParseFile(fset, uri.Path(), src, mode)\n\tvar parseErr scanner.ErrorList\n\tif err != nil {\n\t\t// We passed a byte slice, so the only possible error is a parse error.\n\t\tparseErr = err.(scanner.ErrorList)\n\t}\n\t// Inv: file != nil.\n\n\ttokenFile := func(file *ast.File) *token.File {\n\t\treturn fset.File(file.FileStart)\n\t}\n\n\ttok := tokenFile(file)\n\n\tfixedSrc := false\n\tfixedAST := false\n\t// If there were parse errors, attempt to fix them up.\n\tif parseErr != nil {\n\t\t// Fix any badly parsed parts of the AST.\n\t\tastFixes := fixAST(file, tok, src)\n\t\tfixedAST = len(astFixes) > 0\n\t\tif fixedAST {\n\t\t\tfixes = append(fixes, astFixes...)\n\t\t}\n\n\t\tfor i := range 10 {\n\t\t\t// Fix certain syntax errors that render the file unparsable.\n\t\t\tnewSrc, srcFix := fixSrc(file, tok, src)\n\t\t\tif newSrc == nil {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// If we thought there was something to fix 10 times in a row,\n\t\t\t// it is likely we got stuck in a loop somehow. Log out a diff\n\t\t\t// of the last changes we made to aid in debugging.\n\t\t\tif i == 9 {\n\t\t\t\tunified := diff.Unified(\"before\", \"after\", string(src), string(newSrc))\n\t\t\t\tevent.Log(ctx, fmt.Sprintf(\"fixSrc loop - last diff:\\n%v\", unified), label.File.Of(tok.Name()))\n\t\t\t}\n\n\t\t\tnewFile, newErr := parser.ParseFile(fset, uri.Path(), newSrc, mode)\n\t\t\tassert(newFile != nil, \"ParseFile returned nil\") // I/O error can't happen\n\n\t\t\t// Maintain the original parseError so we don't try formatting the\n\t\t\t// doctored file.\n\t\t\tfile = newFile\n\t\t\tsrc = newSrc\n\t\t\ttok = tokenFile(file)\n\n\t\t\t// Only now that we accept the fix do we record the src fix from above.\n\t\t\tfixes = append(fixes, srcFix)\n\t\t\tfixedSrc = true\n\n\t\t\tif newErr == nil {\n\t\t\t\tbreak // nothing to fix\n\t\t\t}\n\n\t\t\t// Note that fixedAST is reset after we fix src.\n\t\t\tastFixes = fixAST(file, tok, src)\n\t\t\tfixedAST = len(astFixes) > 0\n\t\t\tif fixedAST {\n\t\t\t\tfixes = append(fixes, astFixes...)\n\t\t\t}\n\t\t}\n\t}\n\tassert(file != nil, \"nil *ast.File\")\n\n\treturn &File{\n\t\tURI:      uri,\n\t\tMode:     mode,\n\t\tSrc:      src,\n\t\tfixedSrc: fixedSrc,\n\t\tfixedAST: fixedAST,\n\t\tFile:     file,\n\t\tTok:      tok,\n\t\tMapper:   protocol.NewMapper(uri, src),\n\t\tParseErr: parseErr,\n\t}, fixes\n}\n\n// fixAST inspects the AST and potentially modifies any *ast.BadStmts so that it can be\n// type-checked more effectively.\n//\n// If fixAST returns true, the resulting AST is considered \"fixed\", meaning\n// positions have been mangled, and type checker errors may not make sense.\nfunc fixAST(n ast.Node, tok *token.File, src []byte) (fixes []FixType) {\n\tvar err error\n\tast.PreorderStack(n, nil, func(n ast.Node, stack []ast.Node) bool {\n\t\tvar parent ast.Node\n\t\tif len(stack) > 0 {\n\t\t\tparent = stack[len(stack)-1]\n\t\t}\n\n\t\tswitch n := n.(type) {\n\t\tcase *ast.BadStmt:\n\t\t\tif fixDeferOrGoStmt(n, parent, tok, src) {\n\t\t\t\tfixes = append(fixes, FixedDeferOrGo)\n\t\t\t\t// Recursively fix in our fixed node.\n\t\t\t\tmoreFixes := fixAST(parent, tok, src)\n\t\t\t\tfixes = append(fixes, moreFixes...)\n\t\t\t} else {\n\t\t\t\terr = fmt.Errorf(\"unable to parse defer or go from *ast.BadStmt: %v\", err)\n\t\t\t}\n\t\t\treturn false\n\t\tcase *ast.BadExpr:\n\t\t\tif fixArrayType(n, parent, tok, src) {\n\t\t\t\tfixes = append(fixes, FixedArrayType)\n\t\t\t\t// Recursively fix in our fixed node.\n\t\t\t\tmoreFixes := fixAST(parent, tok, src)\n\t\t\t\tfixes = append(fixes, moreFixes...)\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Fix cases where parser interprets if/for/switch \"init\"\n\t\t\t// statement as \"cond\" expression, e.g.:\n\t\t\t//\n\t\t\t//   // \"i := foo\" is init statement, not condition.\n\t\t\t//   for i := foo\n\t\t\t//\n\t\t\tif fixInitStmt(n, parent, tok, src) {\n\t\t\t\tfixes = append(fixes, FixedInit)\n\t\t\t}\n\t\t\treturn false\n\t\tcase *ast.SelectorExpr:\n\t\t\t// Fix cases where a keyword prefix results in a phantom \"_\" selector, e.g.:\n\t\t\t//\n\t\t\t//   foo.var<> // want to complete to \"foo.variance\"\n\t\t\t//\n\t\t\tif fixPhantomSelector(n, tok, src) {\n\t\t\t\tfixes = append(fixes, FixedPhantomSelector)\n\t\t\t}\n\t\t\treturn true\n\n\t\tcase *ast.BlockStmt:\n\t\t\tswitch parent.(type) {\n\t\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\t\t\t// Adjust closing curly brace of empty switch/select\n\t\t\t\t// statements so we can complete inside them.\n\t\t\t\tif fixEmptySwitch(n, tok, src) {\n\t\t\t\t\tfixes = append(fixes, FixedEmptySwitch)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true\n\t\tdefault:\n\t\t\treturn true\n\t\t}\n\t})\n\treturn fixes\n}\n\n// TODO(rfindley): revert this instrumentation once we're certain the crash in\n// #59097 is fixed.\ntype FixType int\n\nconst (\n\tnoFix FixType = iota\n\tFixedCurlies\n\tFixedDanglingSelector\n\tFixedDeferOrGo\n\tFixedArrayType\n\tFixedInit\n\tFixedPhantomSelector\n\tFixedEmptySwitch\n)\n\n// fixSrc attempts to modify the file's source code to fix certain\n// syntax errors that leave the rest of the file unparsed.\n//\n// fixSrc returns a non-nil result if and only if a fix was applied.\nfunc fixSrc(f *ast.File, tf *token.File, src []byte) (newSrc []byte, fix FixType) {\n\tast.PreorderStack(f, nil, func(n ast.Node, stack []ast.Node) bool {\n\t\tif newSrc != nil {\n\t\t\treturn false\n\t\t}\n\n\t\tswitch n := n.(type) {\n\t\tcase *ast.BlockStmt:\n\t\t\tparent := stack[len(stack)-1]\n\t\t\tnewSrc = fixMissingCurlies(f, n, parent, tf, src)\n\t\t\tif newSrc != nil {\n\t\t\t\tfix = FixedCurlies\n\t\t\t}\n\t\tcase *ast.SelectorExpr:\n\t\t\tnewSrc = fixDanglingSelector(n, tf, src)\n\t\t\tif newSrc != nil {\n\t\t\t\tfix = FixedDanglingSelector\n\t\t\t}\n\t\t}\n\n\t\treturn newSrc == nil\n\t})\n\n\treturn newSrc, fix\n}\n\n// fixMissingCurlies adds in curly braces for block statements that\n// are missing curly braces. For example:\n//\n//\tif foo\n//\n// becomes\n//\n//\tif foo {}\nfunc fixMissingCurlies(f *ast.File, b *ast.BlockStmt, parent ast.Node, tok *token.File, src []byte) []byte {\n\t// If the \"{\" is already in the source code, there isn't anything to\n\t// fix since we aren't missing curlies.\n\tif b.Lbrace.IsValid() {\n\t\tbraceOffset, err := safetoken.Offset(tok, b.Lbrace)\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tif braceOffset < len(src) && src[braceOffset] == '{' {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tparentLine := safetoken.Line(tok, parent.Pos())\n\n\tif parentLine >= tok.LineCount() {\n\t\t// If we are the last line in the file, no need to fix anything.\n\t\treturn nil\n\t}\n\n\t// Insert curlies at the end of parent's starting line. The parent\n\t// is the statement that contains the block, e.g. *ast.IfStmt. The\n\t// block's Pos()/End() can't be relied upon because they are based\n\t// on the (missing) curly braces. We assume the statement is a\n\t// single line for now and try sticking the curly braces at the end.\n\tinsertPos := tok.LineStart(parentLine+1) - 1\n\n\t// Scootch position backwards until it's not in a comment. For example:\n\t//\n\t// if foo<> // some amazing comment |\n\t// someOtherCode()\n\t//\n\t// insertPos will be located at \"|\", so we back it out of the comment.\n\tdidSomething := true\n\tfor didSomething {\n\t\tdidSomething = false\n\t\tfor _, c := range f.Comments {\n\t\t\tif c.Pos() < insertPos && insertPos <= c.End() {\n\t\t\t\tinsertPos = c.Pos()\n\t\t\t\tdidSomething = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Bail out if line doesn't end in an ident or \".\". This is to avoid\n\t// cases like below where we end up making things worse by adding\n\t// curlies:\n\t//\n\t//   if foo &&\n\t//     bar<>\n\tswitch precedingToken(insertPos, tok, src) {\n\tcase token.IDENT, token.PERIOD:\n\t\t// ok\n\tdefault:\n\t\treturn nil\n\t}\n\n\tvar buf bytes.Buffer\n\tbuf.Grow(len(src) + 3)\n\toffset, err := safetoken.Offset(tok, insertPos)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tbuf.Write(src[:offset])\n\n\t// Detect if we need to insert a semicolon to fix \"for\" loop situations like:\n\t//\n\t//   for i := foo(); foo<>\n\t//\n\t// Just adding curlies is not sufficient to make things parse well.\n\tif fs, ok := parent.(*ast.ForStmt); ok {\n\t\tif _, ok := fs.Cond.(*ast.BadExpr); !ok {\n\t\t\tif xs, ok := fs.Post.(*ast.ExprStmt); ok {\n\t\t\t\tif _, ok := xs.X.(*ast.BadExpr); ok {\n\t\t\t\t\tbuf.WriteByte(';')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Insert \"{}\" at insertPos.\n\tbuf.WriteByte('{')\n\tbuf.WriteByte('}')\n\tbuf.Write(src[offset:])\n\treturn buf.Bytes()\n}\n\n// fixEmptySwitch moves empty switch/select statements' closing curly\n// brace down one line. This allows us to properly detect incomplete\n// \"case\" and \"default\" keywords as inside the switch statement. For\n// example:\n//\n//\tswitch {\n//\tdef<>\n//\t}\n//\n// gets parsed like:\n//\n//\tswitch {\n//\t}\n//\n// Later we manually pull out the \"def\" token, but we need to detect\n// that our \"<>\" position is inside the switch block. To do that we\n// move the curly brace so it looks like:\n//\n//\tswitch {\n//\n//\t}\n//\n// The resulting bool reports whether any fixing occurred.\nfunc fixEmptySwitch(body *ast.BlockStmt, tok *token.File, src []byte) bool {\n\t// We only care about empty switch statements.\n\tif len(body.List) > 0 || !body.Rbrace.IsValid() {\n\t\treturn false\n\t}\n\n\t// If the right brace is actually in the source code at the\n\t// specified position, don't mess with it.\n\tbraceOffset, err := safetoken.Offset(tok, body.Rbrace)\n\tif err != nil {\n\t\treturn false\n\t}\n\tif braceOffset < len(src) && src[braceOffset] == '}' {\n\t\treturn false\n\t}\n\n\tbraceLine := safetoken.Line(tok, body.Rbrace)\n\tif braceLine >= tok.LineCount() {\n\t\t// If we are the last line in the file, no need to fix anything.\n\t\treturn false\n\t}\n\n\t// Move the right brace down one line.\n\tbody.Rbrace = tok.LineStart(braceLine + 1)\n\treturn true\n}\n\n// fixDanglingSelector inserts a real \"_\" selector expression in place\n// of a phantom parser-inserted \"_\" selector so that the parser will\n// not consume the following non-identifier token.\n// For example:\n//\n//\tfunc _() {\n//\t\tx.<>\n//\t}\n//\n// var x struct { i int }\n//\n// To fix completion at \"<>\", we insert a real \"_\" after the \".\" so the\n// following declaration of \"x\" can be parsed and type checked\n// normally.\nfunc fixDanglingSelector(s *ast.SelectorExpr, tf *token.File, src []byte) []byte {\n\tif !isPhantomUnderscore(s.Sel, tf, src) {\n\t\treturn nil\n\t}\n\n\tif !s.X.End().IsValid() {\n\t\treturn nil\n\t}\n\n\tinsertOffset, err := safetoken.Offset(tf, s.X.End())\n\tif err != nil {\n\t\treturn nil\n\t}\n\t// Insert directly after the selector's \".\".\n\tinsertOffset++\n\tif src[insertOffset-1] != '.' {\n\t\treturn nil\n\t}\n\n\treturn slices.Concat(src[:insertOffset], []byte(\"_\"), src[insertOffset:])\n}\n\n// fixPhantomSelector tries to fix selector expressions whose Sel is a\n// phantom (parser-invented) \"_\". If the text after the '.' is a\n// keyword, it updates Sel to a fake ast.Ident of that name. For\n// example:\n//\n// foo.var\n//\n// yields a \"_\" selector instead of \"var\" since \"var\" is a keyword.\n//\n// TODO(rfindley): should this constitute an ast 'fix'?\n//\n// The resulting bool reports whether any fixing occurred.\nfunc fixPhantomSelector(sel *ast.SelectorExpr, tf *token.File, src []byte) bool {\n\tif !isPhantomUnderscore(sel.Sel, tf, src) {\n\t\treturn false\n\t}\n\n\t// Only consider selectors directly abutting the selector \".\". This\n\t// avoids false positives in cases like:\n\t//\n\t//   foo. // don't think \"var\" is our selector\n\t//   var bar = 123\n\t//\n\tif sel.Sel.Pos() != sel.X.End()+1 {\n\t\treturn false\n\t}\n\n\tmaybeKeyword := readKeyword(sel.Sel.Pos(), tf, src)\n\tif maybeKeyword == \"\" {\n\t\treturn false\n\t}\n\n\treturn replaceNode(sel, sel.Sel, &ast.Ident{\n\t\tName:    maybeKeyword,\n\t\tNamePos: sel.Sel.Pos(),\n\t})\n}\n\n// isPhantomUnderscore reports whether the given ident from a\n// SelectorExpr.Sel was invented by the parser and is not present in\n// source text. The parser creates a blank \"_\" identifier when the\n// syntax (e.g. a selector) demands one but none is present. The fixer\n// also inserts them.\nfunc isPhantomUnderscore(id *ast.Ident, tok *token.File, src []byte) bool {\n\tswitch id.Name {\n\tcase \"_\": // go1.24 parser\n\t\toffset, err := safetoken.Offset(tok, id.Pos())\n\t\treturn err == nil && offset < len(src) && src[offset] != '_'\n\t}\n\treturn false // real\n}\n\n// fixInitStmt fixes cases where the parser misinterprets an\n// if/for/switch \"init\" statement as the \"cond\" conditional. In cases\n// like \"if i := 0\" the user hasn't typed the semicolon yet so the\n// parser is looking for the conditional expression. However, \"i := 0\"\n// are not valid expressions, so we get a BadExpr.\n//\n// The resulting bool reports whether any fixing occurred.\nfunc fixInitStmt(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) bool {\n\tif !bad.Pos().IsValid() || !bad.End().IsValid() {\n\t\treturn false\n\t}\n\n\t// Try to extract a statement from the BadExpr.\n\tstart, end, err := safetoken.Offsets(tok, bad.Pos(), bad.End())\n\tif err != nil {\n\t\treturn false\n\t}\n\tassert(end <= len(src), \"offset overflow\") // golang/go#72026\n\tstmtBytes := src[start:end]\n\tstmt, err := parseStmt(tok, bad.Pos(), stmtBytes)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// If the parent statement doesn't already have an \"init\" statement,\n\t// move the extracted statement into the \"init\" field and insert a\n\t// dummy expression into the required \"cond\" field.\n\tswitch p := parent.(type) {\n\tcase *ast.IfStmt:\n\t\tif p.Init != nil {\n\t\t\treturn false\n\t\t}\n\t\tp.Init = stmt\n\t\tp.Cond = &ast.Ident{\n\t\t\tName:    \"_\",\n\t\t\tNamePos: stmt.End(),\n\t\t}\n\t\treturn true\n\tcase *ast.ForStmt:\n\t\tif p.Init != nil {\n\t\t\treturn false\n\t\t}\n\t\tp.Init = stmt\n\t\tp.Cond = &ast.Ident{\n\t\t\tName:    \"_\",\n\t\t\tNamePos: stmt.End(),\n\t\t}\n\t\treturn true\n\tcase *ast.SwitchStmt:\n\t\tif p.Init != nil {\n\t\t\treturn false\n\t\t}\n\t\tp.Init = stmt\n\t\tp.Tag = nil\n\t\treturn true\n\t}\n\treturn false\n}\n\n// readKeyword reads the keyword starting at pos, if any.\nfunc readKeyword(pos token.Pos, tok *token.File, src []byte) string {\n\tvar kwBytes []byte\n\toffset, err := safetoken.Offset(tok, pos)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\tfor i := offset; i < len(src); i++ {\n\t\t// Use a simplified identifier check since keywords are always lowercase ASCII.\n\t\tif src[i] < 'a' || src[i] > 'z' {\n\t\t\tbreak\n\t\t}\n\t\tkwBytes = append(kwBytes, src[i])\n\n\t\t// Stop search at arbitrarily chosen too-long-for-a-keyword length.\n\t\tif len(kwBytes) > 15 {\n\t\t\treturn \"\"\n\t\t}\n\t}\n\n\tif kw := string(kwBytes); token.Lookup(kw).IsKeyword() {\n\t\treturn kw\n\t}\n\n\treturn \"\"\n}\n\n// fixArrayType tries to parse an *ast.BadExpr into an *ast.ArrayType.\n// go/parser often turns lone array types like \"[]int\" into BadExprs\n// if it isn't expecting a type.\nfunc fixArrayType(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) bool {\n\t// Our expected input is a bad expression that looks like \"[]someExpr\".\n\n\tfrom, to := bad.Pos(), bad.End()\n\tfromOffset, toOffset, err := safetoken.Offsets(tok, from, to)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\texprBytes := bytes.TrimSpace(slices.Clone(src[fromOffset:toOffset]))\n\n\t// If our expression ends in \"]\" (e.g. \"[]\"), add a phantom selector\n\t// so we can complete directly after the \"[]\".\n\tif bytes.HasSuffix(exprBytes, []byte(\"]\")) {\n\t\texprBytes = append(exprBytes, '_')\n\t}\n\n\t// Add \"{}\" to turn our ArrayType into a CompositeLit. This is to\n\t// handle the case of \"[...]int\" where we must make it a composite\n\t// literal to be parseable.\n\texprBytes = append(exprBytes, '{', '}')\n\n\texpr, err := parseExpr(tok, from, exprBytes)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tcl, _ := expr.(*ast.CompositeLit)\n\tif cl == nil {\n\t\treturn false\n\t}\n\n\tat, _ := cl.Type.(*ast.ArrayType)\n\tif at == nil {\n\t\treturn false\n\t}\n\n\treturn replaceNode(parent, bad, at)\n}\n\n// precedingToken scans src to find the token preceding pos.\nfunc precedingToken(pos token.Pos, tok *token.File, src []byte) token.Token {\n\ts := &scanner.Scanner{}\n\ts.Init(tok, src, nil, 0)\n\n\tvar lastTok token.Token\n\tfor {\n\t\tp, t, _ := s.Scan()\n\t\tif t == token.EOF || p >= pos {\n\t\t\tbreak\n\t\t}\n\n\t\tlastTok = t\n\t}\n\treturn lastTok\n}\n\n// fixDeferOrGoStmt tries to parse an *ast.BadStmt into a defer or a go statement.\n//\n// go/parser packages a statement of the form \"defer x.\" as an *ast.BadStmt because\n// it does not include a call expression. This means that go/types skips type-checking\n// this statement entirely, and we can't use the type information when completing.\n// Here, we try to generate a fake *ast.DeferStmt or *ast.GoStmt to put into the AST,\n// instead of the *ast.BadStmt.\nfunc fixDeferOrGoStmt(bad *ast.BadStmt, parent ast.Node, tok *token.File, src []byte) bool {\n\t// Check if we have a bad statement containing either a \"go\" or \"defer\".\n\ts := &scanner.Scanner{}\n\ts.Init(tok, src, nil, 0)\n\n\tvar (\n\t\tpos token.Pos\n\t\ttkn token.Token\n\t)\n\tfor {\n\t\tif tkn == token.EOF {\n\t\t\treturn false\n\t\t}\n\t\tif pos >= bad.From {\n\t\t\tbreak\n\t\t}\n\t\tpos, tkn, _ = s.Scan()\n\t}\n\n\tvar stmt ast.Stmt\n\tswitch tkn {\n\tcase token.DEFER:\n\t\tstmt = &ast.DeferStmt{\n\t\t\tDefer: pos,\n\t\t}\n\tcase token.GO:\n\t\tstmt = &ast.GoStmt{\n\t\t\tGo: pos,\n\t\t}\n\tdefault:\n\t\treturn false\n\t}\n\n\tvar (\n\t\tfrom, to, last   token.Pos\n\t\tlastToken        token.Token\n\t\tbraceDepth       int\n\t\tphantomSelectors []token.Pos\n\t)\nFindTo:\n\tfor {\n\t\tto, tkn, _ = s.Scan()\n\n\t\tif from == token.NoPos {\n\t\t\tfrom = to\n\t\t}\n\n\t\tswitch tkn {\n\t\tcase token.EOF:\n\t\t\tbreak FindTo\n\t\tcase token.SEMICOLON:\n\t\t\t// If we aren't in nested braces, end of statement means\n\t\t\t// end of expression.\n\t\t\tif braceDepth == 0 {\n\t\t\t\tbreak FindTo\n\t\t\t}\n\t\tcase token.LBRACE:\n\t\t\tbraceDepth++\n\t\t}\n\n\t\t// This handles the common dangling selector case. For example in\n\t\t//\n\t\t// defer fmt.\n\t\t// y := 1\n\t\t//\n\t\t// we notice the dangling period and end our expression.\n\t\t//\n\t\t// If the previous token was a \".\" and we are looking at a \"}\",\n\t\t// the period is likely a dangling selector and needs a phantom\n\t\t// \"_\". Likewise if the current token is on a different line than\n\t\t// the period, the period is likely a dangling selector.\n\t\tif lastToken == token.PERIOD && (tkn == token.RBRACE || safetoken.Line(tok, to) > safetoken.Line(tok, last)) {\n\t\t\t// Insert phantom \"_\" selector after the dangling \".\".\n\t\t\tphantomSelectors = append(phantomSelectors, last+1)\n\t\t\t// If we aren't in a block then end the expression after the \".\".\n\t\t\tif braceDepth == 0 {\n\t\t\t\tto = last + 1\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tlastToken = tkn\n\t\tlast = to\n\n\t\tswitch tkn {\n\t\tcase token.RBRACE:\n\t\t\tbraceDepth--\n\t\t\tif braceDepth <= 0 {\n\t\t\t\tif braceDepth == 0 {\n\t\t\t\t\t// +1 to include the \"}\" itself.\n\t\t\t\t\tto += 1\n\t\t\t\t}\n\t\t\t\tbreak FindTo\n\t\t\t}\n\t\t}\n\t}\n\n\tfromOffset, toOffset, err := safetoken.Offsets(tok, from, to)\n\tif err != nil {\n\t\treturn false\n\t}\n\tif !from.IsValid() || fromOffset >= len(src) {\n\t\treturn false\n\t}\n\tif !to.IsValid() || toOffset >= len(src) {\n\t\treturn false\n\t}\n\n\t// Insert any phantom selectors needed to prevent dangling \".\" from messing\n\t// up the AST.\n\texprBytes := make([]byte, 0, int(to-from)+len(phantomSelectors))\n\tfor i, b := range src[fromOffset:toOffset] {\n\t\tif len(phantomSelectors) > 0 && from+token.Pos(i) == phantomSelectors[0] {\n\t\t\texprBytes = append(exprBytes, '_')\n\t\t\tphantomSelectors = phantomSelectors[1:]\n\t\t}\n\t\texprBytes = append(exprBytes, b)\n\t}\n\n\tif len(phantomSelectors) > 0 {\n\t\texprBytes = append(exprBytes, '_')\n\t}\n\n\texpr, err := parseExpr(tok, from, exprBytes)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// Package the expression into a fake *ast.CallExpr and re-insert\n\t// into the function.\n\tcall := &ast.CallExpr{\n\t\tFun:    expr,\n\t\tLparen: to,\n\t\tRparen: to,\n\t}\n\n\tswitch stmt := stmt.(type) {\n\tcase *ast.DeferStmt:\n\t\tstmt.Call = call\n\tcase *ast.GoStmt:\n\t\tstmt.Call = call\n\t}\n\n\treturn replaceNode(parent, bad, stmt)\n}\n\n// parseStmt parses the statement in src and updates its position to\n// start at pos.\n//\n// tok is the original file containing pos. Used to ensure that all adjusted\n// positions are valid.\nfunc parseStmt(tok *token.File, pos token.Pos, src []byte) (ast.Stmt, error) {\n\t// Wrap our expression to make it a valid Go file we can pass to ParseFile.\n\tfileSrc := slices.Concat([]byte(\"package fake;func _(){\"), src, []byte(\"}\"))\n\n\t// Use ParseFile instead of ParseExpr because ParseFile has\n\t// best-effort behavior, whereas ParseExpr fails hard on any error.\n\tfakeFile, err := parser.ParseFile(token.NewFileSet(), \"\", fileSrc, parser.SkipObjectResolution)\n\tif fakeFile == nil {\n\t\treturn nil, fmt.Errorf(\"error reading fake file source: %v\", err)\n\t}\n\n\t// Extract our expression node from inside the fake file.\n\tif len(fakeFile.Decls) == 0 {\n\t\treturn nil, fmt.Errorf(\"error parsing fake file: %v\", err)\n\t}\n\n\tfakeDecl, _ := fakeFile.Decls[0].(*ast.FuncDecl)\n\tif fakeDecl == nil || len(fakeDecl.Body.List) == 0 {\n\t\treturn nil, fmt.Errorf(\"no statement in %s: %v\", src, err)\n\t}\n\n\tstmt := fakeDecl.Body.List[0]\n\n\t// parser.ParseFile returns undefined positions.\n\t// Adjust them for the current file.\n\toffsetPositions(tok, stmt, pos-1-(stmt.Pos()-1))\n\n\treturn stmt, nil\n}\n\n// parseExpr parses the expression in src and updates its position to\n// start at pos.\nfunc parseExpr(tok *token.File, pos token.Pos, src []byte) (ast.Expr, error) {\n\tstmt, err := parseStmt(tok, pos, src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\texprStmt, ok := stmt.(*ast.ExprStmt)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no expr in %s: %v\", src, err)\n\t}\n\n\treturn exprStmt.X, nil\n}\n\nvar tokenPosType = reflect.TypeFor[token.Pos]()\n\n// offsetPositions applies an offset to the positions in an ast.Node.\nfunc offsetPositions(tok *token.File, n ast.Node, offset token.Pos) {\n\tfileBase := token.Pos(tok.Base())\n\tfileEnd := fileBase + token.Pos(tok.Size())\n\tast.Inspect(n, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\n\t\tv := reflect.ValueOf(n).Elem()\n\n\t\tswitch v.Kind() {\n\t\tcase reflect.Struct:\n\t\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\t\tf := v.Field(i)\n\t\t\t\tif f.Type() != tokenPosType {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif !f.CanSet() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tpos := token.Pos(f.Int())\n\n\t\t\t\t// Don't offset invalid positions: they should stay invalid.\n\t\t\t\tif !pos.IsValid() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Clamp value to valid range; see #64335.\n\t\t\t\t//\n\t\t\t\t// TODO(golang/go#64335): this is a hack, because our fixes should not\n\t\t\t\t// produce positions that overflow (but they do; see golang/go#64488,\n\t\t\t\t// #73438, #66790, #66683, #67704).\n\t\t\t\tpos = min(max(pos+offset, fileBase), fileEnd)\n\n\t\t\t\tf.SetInt(int64(pos))\n\t\t\t}\n\t\t}\n\n\t\treturn true\n\t})\n}\n\n// replaceNode updates parent's child oldChild to be newChild. It\n// returns whether it replaced successfully.\nfunc replaceNode(parent, oldChild, newChild ast.Node) bool {\n\tif parent == nil || oldChild == nil || newChild == nil {\n\t\treturn false\n\t}\n\n\tparentVal := reflect.ValueOf(parent).Elem()\n\tif parentVal.Kind() != reflect.Struct {\n\t\treturn false\n\t}\n\n\tnewChildVal := reflect.ValueOf(newChild)\n\n\ttryReplace := func(v reflect.Value) bool {\n\t\tif !v.CanSet() || !v.CanInterface() {\n\t\t\treturn false\n\t\t}\n\n\t\t// If the existing value is oldChild, we found our child. Make\n\t\t// sure our newChild is assignable and then make the swap.\n\t\tif v.Interface() == oldChild && newChildVal.Type().AssignableTo(v.Type()) {\n\t\t\tv.Set(newChildVal)\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t// Loop over parent's struct fields.\n\tfor i := 0; i < parentVal.NumField(); i++ {\n\t\tf := parentVal.Field(i)\n\n\t\tswitch f.Kind() {\n\t\t// Check interface and pointer fields.\n\t\tcase reflect.Interface, reflect.Pointer:\n\t\t\tif tryReplace(f) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t// Search through any slice fields.\n\t\tcase reflect.Slice:\n\t\t\tfor i := 0; i < f.Len(); i++ {\n\t\t\t\tif tryReplace(f.Index(i)) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/parse_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage parsego_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"reflect\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\n// TODO(golang/go#64335): we should have many more tests for fixed syntax.\n\nfunc TestFixPosition_Issue64488(t *testing.T) {\n\t// This test reproduces the conditions of golang/go#64488, where a type error\n\t// on fixed syntax overflows the token.File.\n\tconst src = `\npackage foo\n\nfunc _() {\n\ttype myThing struct{}\n\tvar foo []myThing\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`\n\n\tpgf, _ := parsego.Parse(context.Background(), token.NewFileSet(), \"file://foo.go\", []byte(src), parsego.Full, false)\n\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\tast.Inspect(pgf.File, func(n ast.Node) bool {\n\t\tif n != nil {\n\t\t\tposn := safetoken.StartPosition(fset, n.Pos())\n\t\t\tif !posn.IsValid() {\n\t\t\t\tt.Fatalf(\"invalid position for %T (%v): %v not in [%d, %d]\", n, n, n.Pos(), pgf.Tok.Base(), pgf.Tok.Base()+pgf.Tok.Size())\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\nfunc TestFixGoAndDefer(t *testing.T) {\n\tvar testCases = []struct {\n\t\tsource  string\n\t\tfixes   []parsego.FixType\n\t\twantFix string\n\t}{\n\t\t{source: \"\", fixes: nil}, // keyword alone\n\t\t{source: \"a.b(\", fixes: nil},\n\t\t{source: \"a.b()\", fixes: nil},\n\t\t{source: \"func {\", fixes: nil},\n\t\t{\n\t\t\tsource:  \"f\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"f()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"func\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"(func())()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"func {}\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"(func())()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"func {}(\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"(func())()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"func {}()\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"(func())()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"a.\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo, parsego.FixedDanglingSelector, parsego.FixedDeferOrGo},\n\t\t\twantFix: \"a._()\",\n\t\t},\n\t\t{\n\t\t\tsource:  \"a.b\",\n\t\t\tfixes:   []parsego.FixType{parsego.FixedDeferOrGo},\n\t\t\twantFix: \"a.b()\",\n\t\t},\n\t}\n\n\tfor _, keyword := range []string{\"go\", \"defer\"} {\n\t\tfor _, tc := range testCases {\n\t\t\tsource := fmt.Sprintf(\"%s %s\", keyword, tc.source)\n\t\t\tt.Run(source, func(t *testing.T) {\n\t\t\t\tsrc := filesrc(source)\n\t\t\t\tpgf, fixes := parsego.Parse(context.Background(), token.NewFileSet(), \"file://foo.go\", src, parsego.Full, false)\n\t\t\t\tif !slices.Equal(fixes, tc.fixes) {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", fixes, tc.fixes)\n\t\t\t\t}\n\t\t\t\tif tc.fixes == nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\t\t\tinspect(t, pgf, func(stmt ast.Stmt) {\n\t\t\t\t\tvar call *ast.CallExpr\n\t\t\t\t\tswitch stmt := stmt.(type) {\n\t\t\t\t\tcase *ast.DeferStmt:\n\t\t\t\t\t\tcall = stmt.Call\n\t\t\t\t\tcase *ast.GoStmt:\n\t\t\t\t\t\tcall = stmt.Call\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif got := astutil.Format(fset, call); got != tc.wantFix {\n\t\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, tc.wantFix)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t}\n}\n\n// TestFixInit tests the init stmt after if/for/switch which is put under cond after parsing\n// will be fixed and moved to Init.\nfunc TestFixInit(t *testing.T) {\n\tvar testCases = []struct {\n\t\tname        string\n\t\tsource      string\n\t\tfixes       []parsego.FixType\n\t\twantInitFix string\n\t}{\n\t\t{\n\t\t\tname:        \"simple define\",\n\t\t\tsource:      \"i := 0\",\n\t\t\tfixes:       []parsego.FixType{parsego.FixedInit},\n\t\t\twantInitFix: \"i := 0\",\n\t\t},\n\t\t{\n\t\t\tname:        \"simple assign\",\n\t\t\tsource:      \"i = 0\",\n\t\t\tfixes:       []parsego.FixType{parsego.FixedInit},\n\t\t\twantInitFix: \"i = 0\",\n\t\t},\n\t\t{\n\t\t\tname:        \"define with function call\",\n\t\t\tsource:      \"i := f()\",\n\t\t\tfixes:       []parsego.FixType{parsego.FixedInit},\n\t\t\twantInitFix: \"i := f()\",\n\t\t},\n\t\t{\n\t\t\tname:        \"assign with function call\",\n\t\t\tsource:      \"i = f()\",\n\t\t\tfixes:       []parsego.FixType{parsego.FixedInit},\n\t\t\twantInitFix: \"i = f()\",\n\t\t},\n\t\t{\n\t\t\tname:        \"assign with receiving chan\",\n\t\t\tsource:      \"i = <-ch\",\n\t\t\tfixes:       []parsego.FixType{parsego.FixedInit},\n\t\t\twantInitFix: \"i = <-ch\",\n\t\t},\n\n\t\t// fixInitStmt won't fix the following cases.\n\t\t{\n\t\t\tname:   \"call in if\",\n\t\t\tsource: `fmt.Println(\"helloworld\")`,\n\t\t\tfixes:  nil,\n\t\t},\n\t\t{\n\t\t\tname:   \"receive chan\",\n\t\t\tsource: `<- ch`,\n\t\t\tfixes:  nil,\n\t\t},\n\t}\n\n\t// currently, switch will leave its Tag empty after fix because it allows empty,\n\t// and if and for will leave an underscore in Cond.\n\tgetWantCond := func(keyword string) string {\n\t\tif keyword == \"switch\" {\n\t\t\treturn \"\"\n\t\t}\n\t\treturn \"_\"\n\t}\n\n\tfor _, keyword := range []string{\"if\", \"for\", \"switch\"} {\n\t\tfor _, tc := range testCases {\n\t\t\tcaseName := fmt.Sprintf(\"%s %s\", keyword, tc.name)\n\t\t\tt.Run(caseName, func(t *testing.T) {\n\t\t\t\t// the init stmt is treated as a cond.\n\t\t\t\tsrc := filesrc(fmt.Sprintf(\"%s %s {}\", keyword, tc.source))\n\t\t\t\tpgf, fixes := parsego.Parse(context.Background(), token.NewFileSet(), \"file://foo.go\", src, parsego.Full, false)\n\t\t\t\tif !slices.Equal(fixes, tc.fixes) {\n\t\t\t\t\tt.Fatalf(\"TestFixArrayType(): got %v want %v\", fixes, tc.fixes)\n\t\t\t\t}\n\t\t\t\tif tc.fixes == nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ensure the init stmt is parsed to a BadExpr.\n\t\t\t\tensureSource(t, src, func(bad *ast.BadExpr) {})\n\n\t\t\t\tinfo := func(n ast.Node, wantStmt string) (init ast.Stmt, cond ast.Expr, has bool) {\n\t\t\t\t\tswitch wantStmt {\n\t\t\t\t\tcase \"if\":\n\t\t\t\t\t\tif e, ok := n.(*ast.IfStmt); ok {\n\t\t\t\t\t\t\treturn e.Init, e.Cond, true\n\t\t\t\t\t\t}\n\t\t\t\t\tcase \"switch\":\n\t\t\t\t\t\tif e, ok := n.(*ast.SwitchStmt); ok {\n\t\t\t\t\t\t\treturn e.Init, e.Tag, true\n\t\t\t\t\t\t}\n\t\t\t\t\tcase \"for\":\n\t\t\t\t\t\tif e, ok := n.(*ast.ForStmt); ok {\n\t\t\t\t\t\t\treturn e.Init, e.Cond, true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn nil, nil, false\n\t\t\t\t}\n\t\t\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\t\t\tinspect(t, pgf, func(n ast.Stmt) {\n\t\t\t\t\tif init, cond, ok := info(n, keyword); ok {\n\t\t\t\t\t\tif got := astutil.Format(fset, init); got != tc.wantInitFix {\n\t\t\t\t\t\t\tt.Fatalf(\"%s: Init got %v want %v\", tc.source, got, tc.wantInitFix)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twantCond := getWantCond(keyword)\n\t\t\t\t\t\tif got := astutil.Format(fset, cond); got != wantCond {\n\t\t\t\t\t\t\tt.Fatalf(\"%s: Cond got %v want %v\", tc.source, got, wantCond)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc TestFixPhantomSelector(t *testing.T) {\n\twantFixes := []parsego.FixType{parsego.FixedPhantomSelector}\n\tvar testCases = []struct {\n\t\tsource string\n\t\tfixes  []parsego.FixType\n\t}{\n\t\t{source: \"a.break\", fixes: wantFixes},\n\t\t{source: \"_.break\", fixes: wantFixes},\n\t\t{source: \"a.case\", fixes: wantFixes},\n\t\t{source: \"a.chan\", fixes: wantFixes},\n\t\t{source: \"a.const\", fixes: wantFixes},\n\t\t{source: \"a.continue\", fixes: wantFixes},\n\t\t{source: \"a.default\", fixes: wantFixes},\n\t\t{source: \"a.defer\", fixes: wantFixes},\n\t\t{source: \"a.else\", fixes: wantFixes},\n\t\t{source: \"a.fallthrough\", fixes: wantFixes},\n\t\t{source: \"a.for\", fixes: wantFixes},\n\t\t{source: \"a.func\", fixes: wantFixes},\n\t\t{source: \"a.go\", fixes: wantFixes},\n\t\t{source: \"a.goto\", fixes: wantFixes},\n\t\t{source: \"a.if\", fixes: wantFixes},\n\t\t{source: \"a.import\", fixes: wantFixes},\n\t\t{source: \"a.interface\", fixes: wantFixes},\n\t\t{source: \"a.map\", fixes: wantFixes},\n\t\t{source: \"a.package\", fixes: wantFixes},\n\t\t{source: \"a.range\", fixes: wantFixes},\n\t\t{source: \"a.return\", fixes: wantFixes},\n\t\t{source: \"a.select\", fixes: wantFixes},\n\t\t{source: \"a.struct\", fixes: wantFixes},\n\t\t{source: \"a.switch\", fixes: wantFixes},\n\t\t{source: \"a.type\", fixes: wantFixes},\n\t\t{source: \"a.var\", fixes: wantFixes},\n\n\t\t{source: \"break.break\"},\n\t\t{source: \"a.BREAK\"},\n\t\t{source: \"a.break_\"},\n\t\t{source: \"a.breaka\"},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.source, func(t *testing.T) {\n\t\t\tsrc := filesrc(tc.source)\n\t\t\tpgf, fixes := parsego.Parse(context.Background(), token.NewFileSet(), \"file://foo.go\", src, parsego.Full, false)\n\t\t\tif !slices.Equal(fixes, tc.fixes) {\n\t\t\t\tt.Fatalf(\"got %v want %v\", fixes, tc.fixes)\n\t\t\t}\n\n\t\t\t// some fixes don't fit the fix scenario, but we want to confirm it.\n\t\t\tif fixes == nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// ensure the selector has been converted to underscore by parser.\n\t\t\tensureSource(t, src, func(sel *ast.SelectorExpr) {\n\t\t\t\tif sel.Sel.Name != \"_\" {\n\t\t\t\t\tt.Errorf(\"%s: selector name is %q, want _\", tc.source, sel.Sel.Name)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\t\tinspect(t, pgf, func(sel *ast.SelectorExpr) {\n\t\t\t\t// the fix should restore the selector as is.\n\t\t\t\tif got, want := astutil.Format(fset, sel), tc.source; got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// inspect helps to go through each node of pgf and trigger checkFn if the type matches T.\nfunc inspect[T ast.Node](t *testing.T, pgf *parsego.File, checkFn func(n T)) {\n\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\tvar visited bool\n\tast.Inspect(pgf.File, func(node ast.Node) bool {\n\t\tif node != nil {\n\t\t\tposn := safetoken.StartPosition(fset, node.Pos())\n\t\t\tif !posn.IsValid() {\n\t\t\t\tt.Fatalf(\"invalid position for %T (%v): %v not in [%d, %d]\", node, node, node.Pos(), pgf.Tok.Base(), pgf.Tok.Base()+pgf.Tok.Size())\n\t\t\t}\n\t\t\tif n, ok := node.(T); ok {\n\t\t\t\tvisited = true\n\t\t\t\tcheckFn(n)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\tif !visited {\n\t\tvar n T\n\t\tt.Fatalf(\"got no %s node but want at least one\", reflect.TypeOf(n))\n\t}\n}\n\n// ensureSource helps to parse src into an ast.File by go/parser and trigger checkFn if the type matches T.\nfunc ensureSource[T ast.Node](t *testing.T, src []byte, checkFn func(n T)) {\n\t// tolerate error as usually the src is problematic.\n\toriginFile, _ := parser.ParseFile(token.NewFileSet(), \"file://foo.go\", src, parsego.Full)\n\tvar visited bool\n\tast.Inspect(originFile, func(node ast.Node) bool {\n\t\tif n, ok := node.(T); ok {\n\t\t\tvisited = true\n\t\t\tcheckFn(n)\n\t\t}\n\t\treturn true\n\t})\n\n\tif !visited {\n\t\tvar n T\n\t\tt.Fatalf(\"got no %s node but want at least one\", reflect.TypeOf(n))\n\t}\n}\n\nfunc filesrc(expressions string) []byte {\n\tconst srcTmpl = `package foo\n\nfunc _() {\n\t%s\n}`\n\treturn fmt.Appendf(nil, srcTmpl, expressions)\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/resolver.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by resolver_gen.go. DO NOT EDIT.\n\npackage parsego\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strings\"\n)\n\nconst debugResolve = false\n\n// resolveFile walks the given file to resolve identifiers within the file\n// scope, updating ast.Ident.Obj fields with declaration information.\n//\n// If declErr is non-nil, it is used to report declaration errors during\n// resolution. tok is used to format position in error messages.\nfunc resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {\n\tpkgScope := ast.NewScope(nil)\n\tr := &resolver{\n\t\thandle:   handle,\n\t\tdeclErr:  declErr,\n\t\ttopScope: pkgScope,\n\t\tpkgScope: pkgScope,\n\t\tdepth:    1,\n\t}\n\n\tfor _, decl := range file.Decls {\n\t\tast.Walk(r, decl)\n\t}\n\n\tr.closeScope()\n\tassert(r.topScope == nil, \"unbalanced scopes\")\n\tassert(r.labelScope == nil, \"unbalanced label scopes\")\n\n\t// resolve global identifiers within the same file\n\ti := 0\n\tfor _, ident := range r.unresolved {\n\t\t// i <= index for current ident\n\t\tassert(ident.Obj == unresolved, \"object already resolved\")\n\t\tident.Obj = r.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel\n\t\tif ident.Obj == nil {\n\t\t\tr.unresolved[i] = ident\n\t\t\ti++\n\t\t} else if debugResolve {\n\t\t\tpos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()\n\t\t\tr.trace(\"resolved %s@%v to package object %v\", ident.Name, ident.Pos(), pos)\n\t\t}\n\t}\n\tfile.Scope = r.pkgScope\n\tfile.Unresolved = r.unresolved[0:i]\n}\n\nconst maxScopeDepth int = 1e3\n\ntype resolver struct {\n\thandle  *token.File\n\tdeclErr func(token.Pos, string)\n\n\t// Ordinary identifier scopes\n\tpkgScope   *ast.Scope   // pkgScope.Outer == nil\n\ttopScope   *ast.Scope   // top-most scope; may be pkgScope\n\tunresolved []*ast.Ident // unresolved identifiers\n\tdepth      int          // scope depth\n\n\t// Label scopes\n\t// (maintained by open/close LabelScope)\n\tlabelScope  *ast.Scope     // label scope for current function\n\ttargetStack [][]*ast.Ident // stack of unresolved labels\n}\n\nfunc (r *resolver) trace(format string, args ...any) {\n\tfmt.Println(strings.Repeat(\". \", r.depth) + r.sprintf(format, args...))\n}\n\nfunc (r *resolver) sprintf(format string, args ...any) string {\n\tfor i, arg := range args {\n\t\tswitch arg := arg.(type) {\n\t\tcase token.Pos:\n\t\t\targs[i] = r.handle.Position(arg)\n\t\t}\n\t}\n\treturn fmt.Sprintf(format, args...)\n}\n\nfunc (r *resolver) openScope(pos token.Pos) {\n\tr.depth++\n\tif r.depth > maxScopeDepth {\n\t\tpanic(bailout{pos: pos, msg: \"exceeded max scope depth during object resolution\"})\n\t}\n\tif debugResolve {\n\t\tr.trace(\"opening scope @%v\", pos)\n\t}\n\tr.topScope = ast.NewScope(r.topScope)\n}\n\nfunc (r *resolver) closeScope() {\n\tr.depth--\n\tif debugResolve {\n\t\tr.trace(\"closing scope\")\n\t}\n\tr.topScope = r.topScope.Outer\n}\n\nfunc (r *resolver) openLabelScope() {\n\tr.labelScope = ast.NewScope(r.labelScope)\n\tr.targetStack = append(r.targetStack, nil)\n}\n\nfunc (r *resolver) closeLabelScope() {\n\t// resolve labels\n\tn := len(r.targetStack) - 1\n\tscope := r.labelScope\n\tfor _, ident := range r.targetStack[n] {\n\t\tident.Obj = scope.Lookup(ident.Name)\n\t\tif ident.Obj == nil && r.declErr != nil {\n\t\t\tr.declErr(ident.Pos(), fmt.Sprintf(\"label %s undefined\", ident.Name))\n\t\t}\n\t}\n\t// pop label scope\n\tr.targetStack = r.targetStack[0:n]\n\tr.labelScope = r.labelScope.Outer\n}\n\nfunc (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {\n\tfor _, ident := range idents {\n\t\tif ident.Obj != nil {\n\t\t\tpanic(fmt.Sprintf(\"%v: identifier %s already declared or resolved\", ident.Pos(), ident.Name))\n\t\t}\n\t\tobj := ast.NewObj(kind, ident.Name)\n\t\t// remember the corresponding declaration for redeclaration\n\t\t// errors and global variable resolution/typechecking phase\n\t\tobj.Decl = decl\n\t\tobj.Data = data\n\t\t// Identifiers (for receiver type parameters) are written to the scope, but\n\t\t// never set as the resolved object. See go.dev/issue/50956.\n\t\tif _, ok := decl.(*ast.Ident); !ok {\n\t\t\tident.Obj = obj\n\t\t}\n\t\tif ident.Name != \"_\" {\n\t\t\tif debugResolve {\n\t\t\t\tr.trace(\"declaring %s@%v\", ident.Name, ident.Pos())\n\t\t\t}\n\t\t\tif alt := scope.Insert(obj); alt != nil && r.declErr != nil {\n\t\t\t\tprevDecl := \"\"\n\t\t\t\tif pos := alt.Pos(); pos.IsValid() {\n\t\t\t\t\tprevDecl = r.sprintf(\"\\n\\tprevious declaration at %v\", pos)\n\t\t\t\t}\n\t\t\t\tr.declErr(ident.Pos(), fmt.Sprintf(\"%s redeclared in this block%s\", ident.Name, prevDecl))\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (r *resolver) shortVarDecl(decl *ast.AssignStmt) {\n\t// Go spec: A short variable declaration may redeclare variables\n\t// provided they were originally declared in the same block with\n\t// the same type, and at least one of the non-blank variables is new.\n\tn := 0 // number of new variables\n\tfor _, x := range decl.Lhs {\n\t\tif ident, isIdent := x.(*ast.Ident); isIdent {\n\t\t\tassert(ident.Obj == nil, \"identifier already declared or resolved\")\n\t\t\tobj := ast.NewObj(ast.Var, ident.Name)\n\t\t\t// remember corresponding assignment for other tools\n\t\t\tobj.Decl = decl\n\t\t\tident.Obj = obj\n\t\t\tif ident.Name != \"_\" {\n\t\t\t\tif debugResolve {\n\t\t\t\t\tr.trace(\"declaring %s@%v\", ident.Name, ident.Pos())\n\t\t\t\t}\n\t\t\t\tif alt := r.topScope.Insert(obj); alt != nil {\n\t\t\t\t\tident.Obj = alt // redeclaration\n\t\t\t\t} else {\n\t\t\t\t\tn++ // new declaration\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif n == 0 && r.declErr != nil {\n\t\tr.declErr(decl.Lhs[0].Pos(), \"no new variables on left side of :=\")\n\t}\n}\n\n// The unresolved object is a sentinel to mark identifiers that have been added\n// to the list of unresolved identifiers. The sentinel is only used for verifying\n// internal consistency.\nvar unresolved = new(ast.Object)\n\n// If x is an identifier, resolve attempts to resolve x by looking up\n// the object it denotes. If no object is found and collectUnresolved is\n// set, x is marked as unresolved and collected in the list of unresolved\n// identifiers.\nfunc (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {\n\tif ident.Obj != nil {\n\t\tpanic(r.sprintf(\"%v: identifier %s already declared or resolved\", ident.Pos(), ident.Name))\n\t}\n\t// '_' should never refer to existing declarations, because it has special\n\t// handling in the spec.\n\tif ident.Name == \"_\" {\n\t\treturn\n\t}\n\tfor s := r.topScope; s != nil; s = s.Outer {\n\t\tif obj := s.Lookup(ident.Name); obj != nil {\n\t\t\tif debugResolve {\n\t\t\t\tr.trace(\"resolved %v:%s to %v\", ident.Pos(), ident.Name, obj)\n\t\t\t}\n\t\t\tassert(obj.Name != \"\", \"obj with no name\")\n\t\t\t// Identifiers (for receiver type parameters) are written to the scope,\n\t\t\t// but never set as the resolved object. See go.dev/issue/50956.\n\t\t\tif _, ok := obj.Decl.(*ast.Ident); !ok {\n\t\t\t\tident.Obj = obj\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\t// all local scopes are known, so any unresolved identifier\n\t// must be found either in the file scope, package scope\n\t// (perhaps in another file), or universe scope --- collect\n\t// them so that they can be resolved later\n\tif collectUnresolved {\n\t\tident.Obj = unresolved\n\t\tr.unresolved = append(r.unresolved, ident)\n\t}\n}\n\nfunc (r *resolver) walkExprs(list []ast.Expr) {\n\tfor _, node := range list {\n\t\tast.Walk(r, node)\n\t}\n}\n\nfunc (r *resolver) walkLHS(list []ast.Expr) {\n\tfor _, expr := range list {\n\t\texpr := ast.Unparen(expr)\n\t\tif _, ok := expr.(*ast.Ident); !ok && expr != nil {\n\t\t\tast.Walk(r, expr)\n\t\t}\n\t}\n}\n\nfunc (r *resolver) walkStmts(list []ast.Stmt) {\n\tfor _, stmt := range list {\n\t\tast.Walk(r, stmt)\n\t}\n}\n\nfunc (r *resolver) Visit(node ast.Node) ast.Visitor {\n\tif debugResolve && node != nil {\n\t\tr.trace(\"node %T@%v\", node, node.Pos())\n\t}\n\n\tswitch n := node.(type) {\n\n\t// Expressions.\n\tcase *ast.Ident:\n\t\tr.resolve(n, true)\n\n\tcase *ast.FuncLit:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkFuncType(n.Type)\n\t\tr.walkBody(n.Body)\n\n\tcase *ast.SelectorExpr:\n\t\tast.Walk(r, n.X)\n\t\t// Note: don't try to resolve n.Sel, as we don't support qualified\n\t\t// resolution.\n\n\tcase *ast.StructType:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkFieldList(n.Fields, ast.Var)\n\n\tcase *ast.FuncType:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkFuncType(n)\n\n\tcase *ast.CompositeLit:\n\t\tif n.Type != nil {\n\t\t\tast.Walk(r, n.Type)\n\t\t}\n\t\tfor _, e := range n.Elts {\n\t\t\tif kv, _ := e.(*ast.KeyValueExpr); kv != nil {\n\t\t\t\t// See go.dev/issue/45160: try to resolve composite lit keys, but don't\n\t\t\t\t// collect them as unresolved if resolution failed. This replicates\n\t\t\t\t// existing behavior when resolving during parsing.\n\t\t\t\tif ident, _ := kv.Key.(*ast.Ident); ident != nil {\n\t\t\t\t\tr.resolve(ident, false)\n\t\t\t\t} else {\n\t\t\t\t\tast.Walk(r, kv.Key)\n\t\t\t\t}\n\t\t\t\tast.Walk(r, kv.Value)\n\t\t\t} else {\n\t\t\t\tast.Walk(r, e)\n\t\t\t}\n\t\t}\n\n\tcase *ast.InterfaceType:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkFieldList(n.Methods, ast.Fun)\n\n\t// Statements\n\tcase *ast.LabeledStmt:\n\t\tr.declare(n, nil, r.labelScope, ast.Lbl, n.Label)\n\t\tast.Walk(r, n.Stmt)\n\n\tcase *ast.AssignStmt:\n\t\tr.walkExprs(n.Rhs)\n\t\tif n.Tok == token.DEFINE {\n\t\t\tr.shortVarDecl(n)\n\t\t} else {\n\t\t\tr.walkExprs(n.Lhs)\n\t\t}\n\n\tcase *ast.BranchStmt:\n\t\t// add to list of unresolved targets\n\t\tif n.Tok != token.FALLTHROUGH && n.Label != nil {\n\t\t\tdepth := len(r.targetStack) - 1\n\t\t\tr.targetStack[depth] = append(r.targetStack[depth], n.Label)\n\t\t}\n\n\tcase *ast.BlockStmt:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkStmts(n.List)\n\n\tcase *ast.IfStmt:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tif n.Init != nil {\n\t\t\tast.Walk(r, n.Init)\n\t\t}\n\t\tast.Walk(r, n.Cond)\n\t\tast.Walk(r, n.Body)\n\t\tif n.Else != nil {\n\t\t\tast.Walk(r, n.Else)\n\t\t}\n\n\tcase *ast.CaseClause:\n\t\tr.walkExprs(n.List)\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tr.walkStmts(n.Body)\n\n\tcase *ast.SwitchStmt:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tif n.Init != nil {\n\t\t\tast.Walk(r, n.Init)\n\t\t}\n\t\tif n.Tag != nil {\n\t\t\t// The scope below reproduces some unnecessary behavior of the parser,\n\t\t\t// opening an extra scope in case this is a type switch. It's not needed\n\t\t\t// for expression switches.\n\t\t\t// TODO: remove this once we've matched the parser resolution exactly.\n\t\t\tif n.Init != nil {\n\t\t\t\tr.openScope(n.Tag.Pos())\n\t\t\t\tdefer r.closeScope()\n\t\t\t}\n\t\t\tast.Walk(r, n.Tag)\n\t\t}\n\t\tif n.Body != nil {\n\t\t\tr.walkStmts(n.Body.List)\n\t\t}\n\n\tcase *ast.TypeSwitchStmt:\n\t\tif n.Init != nil {\n\t\t\tr.openScope(n.Pos())\n\t\t\tdefer r.closeScope()\n\t\t\tast.Walk(r, n.Init)\n\t\t}\n\t\tr.openScope(n.Assign.Pos())\n\t\tdefer r.closeScope()\n\t\tast.Walk(r, n.Assign)\n\t\t// s.Body consists only of case clauses, so does not get its own\n\t\t// scope.\n\t\tif n.Body != nil {\n\t\t\tr.walkStmts(n.Body.List)\n\t\t}\n\n\tcase *ast.CommClause:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tif n.Comm != nil {\n\t\t\tast.Walk(r, n.Comm)\n\t\t}\n\t\tr.walkStmts(n.Body)\n\n\tcase *ast.SelectStmt:\n\t\t// as for switch statements, select statement bodies don't get their own\n\t\t// scope.\n\t\tif n.Body != nil {\n\t\t\tr.walkStmts(n.Body.List)\n\t\t}\n\n\tcase *ast.ForStmt:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tif n.Init != nil {\n\t\t\tast.Walk(r, n.Init)\n\t\t}\n\t\tif n.Cond != nil {\n\t\t\tast.Walk(r, n.Cond)\n\t\t}\n\t\tif n.Post != nil {\n\t\t\tast.Walk(r, n.Post)\n\t\t}\n\t\tast.Walk(r, n.Body)\n\n\tcase *ast.RangeStmt:\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\t\tast.Walk(r, n.X)\n\t\tvar lhs []ast.Expr\n\t\tif n.Key != nil {\n\t\t\tlhs = append(lhs, n.Key)\n\t\t}\n\t\tif n.Value != nil {\n\t\t\tlhs = append(lhs, n.Value)\n\t\t}\n\t\tif len(lhs) > 0 {\n\t\t\tif n.Tok == token.DEFINE {\n\t\t\t\t// Note: we can't exactly match the behavior of object resolution\n\t\t\t\t// during the parsing pass here, as it uses the position of the RANGE\n\t\t\t\t// token for the RHS OpPos. That information is not contained within\n\t\t\t\t// the AST.\n\t\t\t\tas := &ast.AssignStmt{\n\t\t\t\t\tLhs:    lhs,\n\t\t\t\t\tTok:    token.DEFINE,\n\t\t\t\t\tTokPos: n.TokPos,\n\t\t\t\t\tRhs:    []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},\n\t\t\t\t}\n\t\t\t\t// TODO(rFindley): this walkLHS reproduced the parser resolution, but\n\t\t\t\t// is it necessary? By comparison, for a normal AssignStmt we don't\n\t\t\t\t// walk the LHS in case there is an invalid identifier list.\n\t\t\t\tr.walkLHS(lhs)\n\t\t\t\tr.shortVarDecl(as)\n\t\t\t} else {\n\t\t\t\tr.walkExprs(lhs)\n\t\t\t}\n\t\t}\n\t\tast.Walk(r, n.Body)\n\n\t// Declarations\n\tcase *ast.GenDecl:\n\t\tswitch n.Tok {\n\t\tcase token.CONST, token.VAR:\n\t\t\tfor i, spec := range n.Specs {\n\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\tkind := ast.Con\n\t\t\t\tif n.Tok == token.VAR {\n\t\t\t\t\tkind = ast.Var\n\t\t\t\t}\n\t\t\t\tr.walkExprs(spec.Values)\n\t\t\t\tif spec.Type != nil {\n\t\t\t\t\tast.Walk(r, spec.Type)\n\t\t\t\t}\n\t\t\t\tr.declare(spec, i, r.topScope, kind, spec.Names...)\n\t\t\t}\n\t\tcase token.TYPE:\n\t\t\tfor _, spec := range n.Specs {\n\t\t\t\tspec := spec.(*ast.TypeSpec)\n\t\t\t\t// Go spec: The scope of a type identifier declared inside a function begins\n\t\t\t\t// at the identifier in the TypeSpec and ends at the end of the innermost\n\t\t\t\t// containing block.\n\t\t\t\tr.declare(spec, nil, r.topScope, ast.Typ, spec.Name)\n\t\t\t\tif spec.TypeParams != nil {\n\t\t\t\t\tr.openScope(spec.Pos())\n\t\t\t\t\tdefer r.closeScope()\n\t\t\t\t\tr.walkTParams(spec.TypeParams)\n\t\t\t\t}\n\t\t\t\tast.Walk(r, spec.Type)\n\t\t\t}\n\t\t}\n\n\tcase *ast.FuncDecl:\n\t\t// Open the function scope.\n\t\tr.openScope(n.Pos())\n\t\tdefer r.closeScope()\n\n\t\tr.walkRecv(n.Recv)\n\n\t\t// Type parameters are walked normally: they can reference each other, and\n\t\t// can be referenced by normal parameters.\n\t\tif n.Type.TypeParams != nil {\n\t\t\tr.walkTParams(n.Type.TypeParams)\n\t\t\t// TODO(rFindley): need to address receiver type parameters.\n\t\t}\n\n\t\t// Resolve and declare parameters in a specific order to get duplicate\n\t\t// declaration errors in the correct location.\n\t\tr.resolveList(n.Type.Params)\n\t\tr.resolveList(n.Type.Results)\n\t\tr.declareList(n.Recv, ast.Var)\n\t\tr.declareList(n.Type.Params, ast.Var)\n\t\tr.declareList(n.Type.Results, ast.Var)\n\n\t\tr.walkBody(n.Body)\n\t\tif n.Recv == nil && n.Name.Name != \"init\" {\n\t\t\tr.declare(n, nil, r.pkgScope, ast.Fun, n.Name)\n\t\t}\n\n\tdefault:\n\t\treturn r\n\t}\n\n\treturn nil\n}\n\nfunc (r *resolver) walkFuncType(typ *ast.FuncType) {\n\t// typ.TypeParams must be walked separately for FuncDecls.\n\tr.resolveList(typ.Params)\n\tr.resolveList(typ.Results)\n\tr.declareList(typ.Params, ast.Var)\n\tr.declareList(typ.Results, ast.Var)\n}\n\nfunc (r *resolver) resolveList(list *ast.FieldList) {\n\tif list == nil {\n\t\treturn\n\t}\n\tfor _, f := range list.List {\n\t\tif f.Type != nil {\n\t\t\tast.Walk(r, f.Type)\n\t\t}\n\t}\n}\n\nfunc (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {\n\tif list == nil {\n\t\treturn\n\t}\n\tfor _, f := range list.List {\n\t\tr.declare(f, nil, r.topScope, kind, f.Names...)\n\t}\n}\n\nfunc (r *resolver) walkRecv(recv *ast.FieldList) {\n\t// If our receiver has receiver type parameters, we must declare them before\n\t// trying to resolve the rest of the receiver, and avoid re-resolving the\n\t// type parameter identifiers.\n\tif recv == nil || len(recv.List) == 0 {\n\t\treturn // nothing to do\n\t}\n\ttyp := recv.List[0].Type\n\tif ptr, ok := typ.(*ast.StarExpr); ok {\n\t\ttyp = ptr.X\n\t}\n\n\tvar declareExprs []ast.Expr // exprs to declare\n\tvar resolveExprs []ast.Expr // exprs to resolve\n\tswitch typ := typ.(type) {\n\tcase *ast.IndexExpr:\n\t\tdeclareExprs = []ast.Expr{typ.Index}\n\t\tresolveExprs = append(resolveExprs, typ.X)\n\tcase *ast.IndexListExpr:\n\t\tdeclareExprs = typ.Indices\n\t\tresolveExprs = append(resolveExprs, typ.X)\n\tdefault:\n\t\tresolveExprs = append(resolveExprs, typ)\n\t}\n\tfor _, expr := range declareExprs {\n\t\tif id, _ := expr.(*ast.Ident); id != nil {\n\t\t\tr.declare(expr, nil, r.topScope, ast.Typ, id)\n\t\t} else {\n\t\t\t// The receiver type parameter expression is invalid, but try to resolve\n\t\t\t// it anyway for consistency.\n\t\t\tresolveExprs = append(resolveExprs, expr)\n\t\t}\n\t}\n\tfor _, expr := range resolveExprs {\n\t\tif expr != nil {\n\t\t\tast.Walk(r, expr)\n\t\t}\n\t}\n\t// The receiver is invalid, but try to resolve it anyway for consistency.\n\tfor _, f := range recv.List[1:] {\n\t\tif f.Type != nil {\n\t\t\tast.Walk(r, f.Type)\n\t\t}\n\t}\n}\n\nfunc (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {\n\tif list == nil {\n\t\treturn\n\t}\n\tr.resolveList(list)\n\tr.declareList(list, kind)\n}\n\n// walkTParams is like walkFieldList, but declares type parameters eagerly so\n// that they may be resolved in the constraint expressions held in the field\n// Type.\nfunc (r *resolver) walkTParams(list *ast.FieldList) {\n\tr.declareList(list, ast.Typ)\n\tr.resolveList(list)\n}\n\nfunc (r *resolver) walkBody(body *ast.BlockStmt) {\n\tif body == nil {\n\t\treturn\n\t}\n\tr.openLabelScope()\n\tdefer r.closeLabelScope()\n\tr.walkStmts(body.List)\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/resolver_compat.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains declarations needed for compatibility with resolver.go\n// copied from GOROOT.\n\npackage parsego\n\nimport \"go/token\"\n\n// assert panics with the given msg if cond is not true.\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n\n// A bailout panic is raised to indicate early termination. pos and msg are\n// only populated when bailing out of object resolution.\ntype bailout struct {\n\tpos token.Pos\n\tmsg string\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/resolver_gen.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc main() {\n\toutput, err := exec.Command(\"go\", \"env\", \"GOROOT\").Output()\n\tif err != nil {\n\t\tlog.Fatalf(\"resolving GOROOT: %v\", err)\n\t}\n\tgoroot := strings.TrimSpace(string(output))\n\tdata, err := os.ReadFile(filepath.Join(goroot, \"src/go/parser/resolver.go\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"reading resolver.go: %v\", err)\n\t}\n\tdata = bytes.Replace(data, []byte(\"\\npackage parser\"), []byte(\"\\n// Code generated by resolver_gen.go. DO NOT EDIT.\\n\\npackage parsego\"), 1)\n\tif err := os.WriteFile(\"resolver.go\", data, 0666); err != nil {\n\t\tlog.Fatalf(\"writing resolver.go: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/parsego/resolver_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage parsego\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestGoplsSourceDoesNotUseObjectResolution verifies that gopls does not\n// read fields that are set during syntactic object resolution, except in\n// locations where we can guarantee that object resolution has occurred. This\n// is achieved via static analysis of gopls source code to find references to\n// the legacy Object symbols, checking the results against an allowlist\n//\n// Reading these fields would introduce a data race, due to the lazy\n// resolution implemented by File.Resolve.\nfunc TestGoplsSourceDoesNotUseObjectResolution(t *testing.T) {\n\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.NeedsLocalXTools(t)\n\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedName | packages.NeedModule | packages.NeedCompiledGoFiles | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,\n\t}\n\tcfg.Env = os.Environ()\n\tcfg.Env = append(cfg.Env,\n\t\t\"GOPACKAGESDRIVER=off\",\n\t\t\"GOWORK=off\", // necessary for -mod=mod below\n\t\t\"GOFLAGS=-mod=mod\",\n\t)\n\n\tpkgs, err := packages.Load(cfg,\n\t\t\"go/ast\",\n\t\t\"golang.org/x/tools/go/ast/astutil\",\n\t\t\"golang.org/x/tools/gopls/...\")\n\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar astPkg, astutilPkg *packages.Package\n\tfor _, pkg := range pkgs {\n\t\tswitch pkg.PkgPath {\n\t\tcase \"go/ast\":\n\t\t\tastPkg = pkg\n\t\tcase \"golang.org/x/tools/go/ast/astutil\":\n\t\t\tastutilPkg = pkg\n\t\t}\n\t}\n\tif astPkg == nil {\n\t\tt.Fatal(\"missing package go/ast\")\n\t}\n\tif astutilPkg == nil {\n\t\tt.Fatal(\"missing package golang.org/x/tools/go/ast/astutil\")\n\t}\n\n\tFile := astPkg.Types.Scope().Lookup(\"File\").Type()\n\tIdent := astPkg.Types.Scope().Lookup(\"Ident\").Type()\n\n\tScope, _, _ := types.LookupFieldOrMethod(File, true, astPkg.Types, \"Scope\")\n\tassert(Scope != nil, \"nil Scope\")\n\tUnresolved, _, _ := types.LookupFieldOrMethod(File, true, astPkg.Types, \"Unresolved\")\n\tassert(Unresolved != nil, \"nil unresolved\")\n\tObj, _, _ := types.LookupFieldOrMethod(Ident, true, astPkg.Types, \"Obj\")\n\tassert(Obj != nil, \"nil Obj\")\n\tUsesImport := astutilPkg.Types.Scope().Lookup(\"UsesImport\")\n\tassert(UsesImport != nil, \"nil UsesImport\")\n\n\tdisallowed := map[types.Object]bool{\n\t\tScope:      true,\n\t\tUnresolved: true,\n\t\tObj:        true,\n\t\tUsesImport: true,\n\t}\n\n\t// exceptions catalogues packages or declarations that are allowed to use\n\t// forbidden symbols, with a rationale.\n\t//\n\t// - If the exception ends with '/', it is a prefix.\n\t// - If it ends with a qualified name, it is a declaration.\n\t// - Otherwise, it is an exact package path.\n\t//\n\t// TODO(rfindley): some sort of callgraph analysis would make these\n\t// exceptions much easier to maintain.\n\texceptions := []string{\n\t\t\"golang.org/x/tools/go/analysis/passes/\",                             // analyzers may rely on object resolution\n\t\t\"golang.org/x/tools/gopls/internal/analysis/simplifyslice\",           // restrict ourselves to one blessed analyzer\n\t\t\"golang.org/x/tools/gopls/internal/cache/parsego\",                    // used by parsego.File.Resolve, of course\n\t\t\"golang.org/x/tools/gopls/internal/golang.builtinDecl\",               // the builtin file is resolved\n\t\t\"golang.org/x/tools/gopls/internal/golang.NewBuiltinSignature\",       // ditto\n\t\t\"golang.org/x/tools/gopls/internal/golang/completion.builtinArgKind\", // ditto\n\t\t\"golang.org/x/tools/internal/imports\",                                // goimports does its own parsing\n\t\t\"golang.org/x/tools/go/ast/astutil.UsesImport\",                       // disallowed\n\t\t\"golang.org/x/tools/go/ast/astutil.isTopName\",                        // only reached from astutil.UsesImport\n\t\t\"go/ast\",\n\t\t\"go/parser\",\n\t\t\"go/doc\", // manually verified that our usage is safe\n\t}\n\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tfor _, exception := range exceptions {\n\t\t\tif strings.HasSuffix(exception, \"/\") {\n\t\t\t\tif strings.HasPrefix(pkg.PkgPath, exception) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else if pkg.PkgPath == exception {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\tsearchUses:\n\t\tfor ident, obj := range pkg.TypesInfo.Uses {\n\t\t\tif disallowed[obj] {\n\t\t\t\tdecl := findEnclosingFuncDecl(ident, pkg)\n\t\t\t\tif decl == \"\" {\n\t\t\t\t\tposn := safetoken.Position(pkg.Fset.File(ident.Pos()), ident.Pos())\n\t\t\t\t\tt.Fatalf(\"%s: couldn't find enclosing decl for use of %s\", posn, ident.Name)\n\t\t\t\t}\n\t\t\t\tqualified := pkg.PkgPath + \".\" + decl\n\t\t\t\tfor _, exception := range exceptions {\n\t\t\t\t\tif exception == qualified {\n\t\t\t\t\t\tcontinue searchUses\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tposn := safetoken.StartPosition(pkg.Fset, ident.Pos())\n\t\t\t\tt.Errorf(\"%s: forbidden use of %v in %s\", posn, obj, qualified)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// findEnclosingFuncDecl finds the name of the func decl enclosing the usage,\n// or \"\".\n//\n// (Usage could theoretically exist in e.g. var initializers, but that would be\n// odd.)\nfunc findEnclosingFuncDecl(ident *ast.Ident, pkg *packages.Package) string {\n\tfor _, file := range pkg.Syntax {\n\t\tif file.FileStart <= ident.Pos() && ident.Pos() < file.FileEnd {\n\t\t\tpath, _ := astutil.PathEnclosingInterval(file, ident.Pos(), ident.End())\n\t\t\tdecl, ok := path[len(path)-2].(*ast.FuncDecl)\n\t\t\tif ok {\n\t\t\t\treturn decl.Name.Name\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "gopls/internal/cache/port.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"go/build\"\n\t\"go/build/constraint\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\ntype port struct{ GOOS, GOARCH string }\n\nvar (\n\t// preferredPorts holds GOOS/GOARCH combinations for which we dynamically\n\t// create new Views, by setting GOOS=... and GOARCH=... on top of\n\t// user-provided configuration when we detect that the default build\n\t// configuration does not match an open file. Ports are matched in the order\n\t// defined below, so that when multiple ports match a file we use the port\n\t// occurring at a lower index in the slice. For that reason, we sort first\n\t// class ports ahead of secondary ports, and (among first class ports) 64-bit\n\t// ports ahead of the less common 32-bit ports.\n\tpreferredPorts = []port{\n\t\t// First class ports, from https://go.dev/wiki/PortingPolicy.\n\t\t{\"darwin\", \"amd64\"},\n\t\t{\"darwin\", \"arm64\"},\n\t\t{\"linux\", \"amd64\"},\n\t\t{\"linux\", \"arm64\"},\n\t\t{\"windows\", \"amd64\"},\n\t\t{\"linux\", \"arm\"},\n\t\t{\"linux\", \"386\"},\n\t\t{\"windows\", \"386\"},\n\n\t\t// Secondary ports, from GOROOT/src/internal/platform/zosarch.go.\n\t\t// (First class ports are commented out.)\n\t\t{\"aix\", \"ppc64\"},\n\t\t{\"dragonfly\", \"amd64\"},\n\t\t{\"freebsd\", \"386\"},\n\t\t{\"freebsd\", \"amd64\"},\n\t\t{\"freebsd\", \"arm\"},\n\t\t{\"freebsd\", \"arm64\"},\n\t\t{\"illumos\", \"amd64\"},\n\t\t{\"linux\", \"ppc64\"},\n\t\t{\"linux\", \"ppc64le\"},\n\t\t{\"linux\", \"mips\"},\n\t\t{\"linux\", \"mipsle\"},\n\t\t{\"linux\", \"mips64\"},\n\t\t{\"linux\", \"mips64le\"},\n\t\t{\"linux\", \"riscv64\"},\n\t\t{\"linux\", \"s390x\"},\n\t\t{\"android\", \"386\"},\n\t\t{\"android\", \"amd64\"},\n\t\t{\"android\", \"arm\"},\n\t\t{\"android\", \"arm64\"},\n\t\t{\"ios\", \"arm64\"},\n\t\t{\"ios\", \"amd64\"},\n\t\t{\"js\", \"wasm\"},\n\t\t{\"netbsd\", \"386\"},\n\t\t{\"netbsd\", \"amd64\"},\n\t\t{\"netbsd\", \"arm\"},\n\t\t{\"netbsd\", \"arm64\"},\n\t\t{\"openbsd\", \"386\"},\n\t\t{\"openbsd\", \"amd64\"},\n\t\t{\"openbsd\", \"arm\"},\n\t\t{\"openbsd\", \"arm64\"},\n\t\t{\"openbsd\", \"mips64\"},\n\t\t{\"plan9\", \"386\"},\n\t\t{\"plan9\", \"amd64\"},\n\t\t{\"plan9\", \"arm\"},\n\t\t{\"solaris\", \"amd64\"},\n\t\t{\"windows\", \"arm\"},\n\t\t{\"windows\", \"arm64\"},\n\n\t\t{\"aix\", \"ppc64\"},\n\t\t{\"android\", \"386\"},\n\t\t{\"android\", \"amd64\"},\n\t\t{\"android\", \"arm\"},\n\t\t{\"android\", \"arm64\"},\n\t\t// {\"darwin\", \"amd64\"},\n\t\t// {\"darwin\", \"arm64\"},\n\t\t{\"dragonfly\", \"amd64\"},\n\t\t{\"freebsd\", \"386\"},\n\t\t{\"freebsd\", \"amd64\"},\n\t\t{\"freebsd\", \"arm\"},\n\t\t{\"freebsd\", \"arm64\"},\n\t\t{\"freebsd\", \"riscv64\"},\n\t\t{\"illumos\", \"amd64\"},\n\t\t{\"ios\", \"amd64\"},\n\t\t{\"ios\", \"arm64\"},\n\t\t{\"js\", \"wasm\"},\n\t\t// {\"linux\", \"386\"},\n\t\t// {\"linux\", \"amd64\"},\n\t\t// {\"linux\", \"arm\"},\n\t\t// {\"linux\", \"arm64\"},\n\t\t{\"linux\", \"loong64\"},\n\t\t{\"linux\", \"mips\"},\n\t\t{\"linux\", \"mips64\"},\n\t\t{\"linux\", \"mips64le\"},\n\t\t{\"linux\", \"mipsle\"},\n\t\t{\"linux\", \"ppc64\"},\n\t\t{\"linux\", \"ppc64le\"},\n\t\t{\"linux\", \"riscv64\"},\n\t\t{\"linux\", \"s390x\"},\n\t\t{\"linux\", \"sparc64\"},\n\t\t{\"netbsd\", \"386\"},\n\t\t{\"netbsd\", \"amd64\"},\n\t\t{\"netbsd\", \"arm\"},\n\t\t{\"netbsd\", \"arm64\"},\n\t\t{\"openbsd\", \"386\"},\n\t\t{\"openbsd\", \"amd64\"},\n\t\t{\"openbsd\", \"arm\"},\n\t\t{\"openbsd\", \"arm64\"},\n\t\t{\"openbsd\", \"mips64\"},\n\t\t{\"openbsd\", \"ppc64\"},\n\t\t{\"openbsd\", \"riscv64\"},\n\t\t{\"plan9\", \"386\"},\n\t\t{\"plan9\", \"amd64\"},\n\t\t{\"plan9\", \"arm\"},\n\t\t{\"solaris\", \"amd64\"},\n\t\t{\"wasip1\", \"wasm\"},\n\t\t// {\"windows\", \"386\"},\n\t\t// {\"windows\", \"amd64\"},\n\t\t{\"windows\", \"arm\"},\n\t\t{\"windows\", \"arm64\"},\n\t}\n)\n\n// matches reports whether the port matches a file with the given absolute path\n// and content.\n//\n// Note that this function accepts content rather than e.g. a file.Handle,\n// because we trim content before matching for performance reasons, and\n// therefore need to do this outside of matches when considering multiple ports.\nfunc (p port) matches(path string, content []byte) bool {\n\tctxt := build.Default // make a copy\n\tctxt.UseAllFiles = false\n\tpath = filepath.Clean(path)\n\tif !filepath.IsAbs(path) {\n\t\tbug.Reportf(\"non-abs file path %q\", path)\n\t\treturn false // fail closed\n\t}\n\tdir, name := filepath.Split(path)\n\n\t// The only virtualized operation called by MatchFile is OpenFile.\n\tctxt.OpenFile = func(p string) (io.ReadCloser, error) {\n\t\tif p != path {\n\t\t\treturn nil, bug.Errorf(\"unexpected file %q\", p)\n\t\t}\n\t\treturn io.NopCloser(bytes.NewReader(content)), nil\n\t}\n\n\tctxt.GOOS = p.GOOS\n\tctxt.GOARCH = p.GOARCH\n\tok, err := ctxt.MatchFile(dir, name)\n\treturn err == nil && ok\n}\n\n// trimContentForPortMatch trims the given Go file content to a minimal file\n// containing the same build constraints, if any.\n//\n// This is an unfortunate but necessary optimization, as matching build\n// constraints using go/build has significant overhead, and involves parsing\n// more than just the build constraint.\n//\n// TestMatchingPortsConsistency enforces consistency by comparing results\n// without trimming content.\nfunc trimContentForPortMatch(content []byte) []byte {\n\tbuildComment := buildComment(content)\n\t// The package name does not matter, but +build lines\n\t// require a blank line before the package declaration.\n\treturn []byte(buildComment + \"\\n\\npackage p\")\n}\n\n// buildComment returns the first matching //go:build comment in the given\n// content, or \"\" if none exists.\nfunc buildComment(content []byte) string {\n\tvar lines []string\n\n\tf, err := parser.ParseFile(token.NewFileSet(), \"\", content, parser.PackageClauseOnly|parser.ParseComments)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\n\tfor _, cg := range f.Comments {\n\t\tfor _, c := range cg.List {\n\t\t\tif constraint.IsGoBuild(c.Text) {\n\t\t\t\t// A file must have only one //go:build line.\n\t\t\t\treturn c.Text\n\t\t\t}\n\t\t\tif constraint.IsPlusBuild(c.Text) {\n\t\t\t\t// A file may have several // +build lines.\n\t\t\t\tlines = append(lines, c.Text)\n\t\t\t}\n\t\t}\n\t}\n\treturn strings.Join(lines, \"\\n\")\n}\n"
  },
  {
    "path": "gopls/internal/cache/port_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(m.Run())\n}\n\nfunc TestMatchingPortsStdlib(t *testing.T) {\n\t// This test checks that we don't encounter a bug when matching ports, and\n\t// sanity checks that the optimization to use trimmed/fake file content\n\t// before delegating to go/build.Context.MatchFile does not affect\n\t// correctness.\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode: takes to long on slow file systems\")\n\t}\n\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Load, parse and type-check the program.\n\tcfg := &packages.Config{\n\t\tMode:  packages.LoadFiles,\n\t\tTests: true,\n\t}\n\tpkgs, err := packages.Load(cfg, \"std\", \"cmd\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar g errgroup.Group\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tfor _, f := range pkg.CompiledGoFiles {\n\t\t\tg.Go(func() error {\n\t\t\t\tcontent, err := os.ReadFile(f)\n\t\t\t\t// We report errors via t.Error, not by returning,\n\t\t\t\t// so that a single test can report multiple test failures.\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"failed to read %s: %v\", f, err)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tfh := makeFakeFileHandle(protocol.URIFromPath(f), content)\n\t\t\t\tfastPorts := matchingPreferredPorts(t, fh, true)\n\t\t\t\tslowPorts := matchingPreferredPorts(t, fh, false)\n\t\t\t\tif diff := cmp.Diff(fastPorts, slowPorts); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"%s: ports do not match (-trimmed +untrimmed):\\n%s\", f, diff)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t})\n\t\t}\n\t})\n\t_ = g.Wait() // can't fail\n}\n\nfunc matchingPreferredPorts(tb testing.TB, fh file.Handle, trimContent bool) map[port]unit {\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\ttb.Fatal(err)\n\t}\n\tif trimContent {\n\t\tcontent = trimContentForPortMatch(content)\n\t}\n\tpath := fh.URI().Path()\n\tmatching := make(map[port]unit)\n\tfor _, port := range preferredPorts {\n\t\tif port.matches(path, content) {\n\t\t\tmatching[port] = unit{}\n\t\t}\n\t}\n\treturn matching\n}\n\nfunc BenchmarkMatchingPreferredPorts(b *testing.B) {\n\t// Copy of robustio_posix.go\n\tconst src = `\n// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build unix\n// +build unix\n\npackage robustio\n\nimport (\n\t\"os\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc getFileID(filename string) (FileID, time.Time, error) {\n\tfi, err := os.Stat(filename)\n\tif err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\tstat := fi.Sys().(*syscall.Stat_t)\n\treturn FileID{\n\t\tdevice: uint64(stat.Dev), // (int32 on darwin, uint64 on linux)\n\t\tinode:  stat.Ino,\n\t}, fi.ModTime(), nil\n}\n`\n\tfh := makeFakeFileHandle(\"file:///path/to/test/file.go\", []byte(src))\n\tfor b.Loop() {\n\t\t_ = matchingPreferredPorts(b, fh, true)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/session.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/gopls/internal/util/persistent\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// NewSession creates a new gopls session with the given cache.\nfunc NewSession(ctx context.Context, c *Cache) *Session {\n\tindex := atomic.AddInt64(&sessionIndex, 1)\n\ts := &Session{\n\t\tid:          strconv.FormatInt(index, 10),\n\t\tcache:       c,\n\t\tgocmdRunner: &gocommand.Runner{},\n\t\toverlayFS:   newOverlayFS(c),\n\t\tparseCache:  newParseCache(1 * time.Minute), // keep recently parsed files for a minute, to optimize typing CPU\n\t\tviewMap:     make(map[protocol.DocumentURI]*View),\n\t}\n\tevent.Log(ctx, \"New session\", KeyCreateSession.Of(s))\n\treturn s\n}\n\n// A Session holds the state (views, file contents, parse cache,\n// memoized computations) of a gopls server process.\n//\n// It implements the file.Source interface.\ntype Session struct {\n\t// Unique identifier for this session.\n\tid string\n\n\t// Immutable attributes shared across views.\n\tcache       *Cache            // shared cache\n\tgocmdRunner *gocommand.Runner // limits go command concurrency\n\n\tviewMu  sync.Mutex\n\tviews   []*View\n\tviewMap map[protocol.DocumentURI]*View // file->best view or nil; nil after shutdown; the key must be a clean uri.\n\n\t// snapshots is a counting semaphore that records the number\n\t// of unreleased snapshots associated with this session.\n\t// Shutdown waits for it to fall to zero.\n\tsnapshotWG sync.WaitGroup\n\n\tparseCache *parseCache\n\n\t*overlayFS\n}\n\n// ID returns the unique identifier for this session on this server.\nfunc (s *Session) ID() string     { return s.id }\nfunc (s *Session) String() string { return s.id }\n\n// GoCommandRunner returns the gocommand Runner for this session.\nfunc (s *Session) GoCommandRunner() *gocommand.Runner {\n\treturn s.gocmdRunner\n}\n\n// Shutdown the session and all views it has created.\nfunc (s *Session) Shutdown(ctx context.Context) {\n\tvar views []*View\n\ts.viewMu.Lock()\n\tviews = append(views, s.views...)\n\ts.views = nil\n\ts.viewMap = nil\n\ts.viewMu.Unlock()\n\tfor _, view := range views {\n\t\tview.shutdown()\n\t}\n\ts.parseCache.stop()\n\ts.snapshotWG.Wait() // wait for all work on associated snapshots to finish\n\tevent.Log(ctx, \"Shutdown session\", KeyShutdownSession.Of(s))\n}\n\n// Cache returns the cache that created this session, for debugging only.\nfunc (s *Session) Cache() *Cache {\n\treturn s.cache\n}\n\n// TODO(rfindley): is the logic surrounding this error actually necessary?\nvar ErrViewExists = errors.New(\"view already exists for session\")\n\n// NewView creates a new View, returning it and its first snapshot. If a\n// non-empty tempWorkspace directory is provided, the View will record a copy\n// of its gopls workspace module in that directory, so that client tooling\n// can execute in the same main module.  On success it also returns a release\n// function that must be called when the Snapshot is no longer needed.\nfunc (s *Session) NewView(ctx context.Context, folder *Folder) (*View, *Snapshot, func(), error) {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\tif s.viewMap == nil {\n\t\treturn nil, nil, nil, fmt.Errorf(\"session is shut down\")\n\t}\n\n\t// Querying the file system to check whether\n\t// two folders denote the same existing directory.\n\tif inode1, err := os.Stat(filepath.FromSlash(folder.Dir.Path())); err == nil {\n\t\tfor _, view := range s.views {\n\t\t\tinode2, err := os.Stat(filepath.FromSlash(view.folder.Dir.Path()))\n\t\t\tif err == nil && os.SameFile(inode1, inode2) {\n\t\t\t\treturn nil, nil, nil, ErrViewExists\n\t\t\t}\n\t\t}\n\t}\n\n\tdef, err := defineView(ctx, s, folder, nil)\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\tview, snapshot, release := s.createView(ctx, def)\n\ts.views = append(s.views, view)\n\ts.viewMap[folder.Dir.Clean()] = view\n\treturn view, snapshot, release, nil\n}\n\n// HasView checks whether the uri's view exists.\nfunc (s *Session) HasView(uri protocol.DocumentURI) bool {\n\turi = uri.Clean()\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\t_, ok := s.viewMap[uri]\n\treturn ok\n}\n\n// createView creates a new view, with an initial snapshot that retains the\n// supplied context, detached from events and cancellation.\n//\n// The caller is responsible for calling the release function once.\nfunc (s *Session) createView(ctx context.Context, def *viewDefinition) (*View, *Snapshot, func()) {\n\tindex := atomic.AddInt64(&viewIndex, 1)\n\n\t// We want a true background context and not a detached context here\n\t// the spans need to be unrelated and no tag values should pollute it.\n\tbaseCtx := event.Detach(xcontext.Detach(ctx))\n\tbackgroundCtx, cancel := context.WithCancel(baseCtx)\n\n\t// Compute a skip function to use for module cache scanning.\n\t//\n\t// Note that unlike other filtering operations, we definitely don't want to\n\t// exclude the gomodcache here, even if it is contained in the workspace\n\t// folder.\n\t//\n\t// TODO(rfindley): consolidate with relPathExcludedByFilter(Func), Filterer,\n\t// View.filterFunc.\n\tvar skipPath func(string) bool\n\t{\n\t\t// Compute a prefix match, respecting segment boundaries, by ensuring\n\t\t// the pattern (dir) has a trailing slash.\n\t\tdirPrefix := strings.TrimSuffix(string(def.folder.Dir), \"/\") + \"/\"\n\t\tpathIncluded := PathIncludeFunc(def.folder.Options.DirectoryFilters)\n\t\tskipPath = func(dir string) bool {\n\t\t\turi := strings.TrimSuffix(string(protocol.URIFromPath(dir)), \"/\")\n\t\t\t// Note that the logic below doesn't handle the case where uri ==\n\t\t\t// v.folder.Dir, because there is no point in excluding the entire\n\t\t\t// workspace folder!\n\t\t\tif rel, ok := strings.CutPrefix(uri, dirPrefix); ok {\n\t\t\t\treturn !pathIncluded(rel)\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\n\tvar ignoreFilter *ignoreFilter\n\t{\n\t\tvar dirs []string\n\t\tif len(def.workspaceModFiles) == 0 {\n\t\t\tfor _, entry := range filepath.SplitList(def.folder.Env.GOPATH) {\n\t\t\t\tdirs = append(dirs, filepath.Join(entry, \"src\"))\n\t\t\t}\n\t\t} else {\n\t\t\tdirs = append(dirs, def.folder.Env.GOMODCACHE)\n\t\t\tfor m := range def.workspaceModFiles {\n\t\t\t\tdirs = append(dirs, m.DirPath())\n\t\t\t}\n\t\t}\n\t\tignoreFilter = newIgnoreFilter(dirs)\n\t}\n\n\tvar pe *imports.ProcessEnv\n\t{\n\t\tenv := make(map[string]string)\n\t\tenvSlice := slices.Concat(os.Environ(), def.folder.Options.EnvSlice(), []string{\"GO111MODULE=\" + def.adjustedGO111MODULE()})\n\t\tfor _, kv := range envSlice {\n\t\t\tif k, v, ok := strings.Cut(kv, \"=\"); ok {\n\t\t\t\tenv[k] = v\n\t\t\t}\n\t\t}\n\t\tpe = &imports.ProcessEnv{\n\t\t\tGocmdRunner: s.gocmdRunner,\n\t\t\tBuildFlags:  slices.Clone(def.folder.Options.BuildFlags),\n\t\t\t// TODO(rfindley): an old comment said \"processEnv operations should not mutate the modfile\"\n\t\t\t// But shouldn't we honor the default behavior of mod vendoring?\n\t\t\tModFlag:        \"readonly\",\n\t\t\tSkipPathInScan: skipPath,\n\t\t\tEnv:            env,\n\t\t\tWorkingDir:     def.root.Path(),\n\t\t\tModCache:       s.cache.modCache.dirCache(def.folder.Env.GOMODCACHE),\n\t\t}\n\t\tif def.folder.Options.VerboseOutput {\n\t\t\tpe.Logf = func(format string, args ...any) {\n\t\t\t\tevent.Log(ctx, fmt.Sprintf(format, args...))\n\t\t\t}\n\t\t}\n\t}\n\n\tv := &View{\n\t\tid:                   strconv.FormatInt(index, 10),\n\t\tgocmdRunner:          s.gocmdRunner,\n\t\tinitialWorkspaceLoad: make(chan struct{}),\n\t\tinitializationSema:   make(chan struct{}, 1),\n\t\tbaseCtx:              baseCtx,\n\t\tpkgIndex:             typerefs.NewPackageIndex(),\n\t\tparseCache:           s.parseCache,\n\t\tignoreFilter:         ignoreFilter,\n\t\tfs:                   s.overlayFS,\n\t\tviewDefinition:       def,\n\t\timportsState:         newImportsState(backgroundCtx, s.cache.modCache, pe),\n\t}\n\n\t// Keep this in sync with golang.computeImportEdits.\n\t//\n\t// TODO(rfindley): encapsulate the imports state logic so that the handling\n\t// for Options.ImportsSource is in a single location.\n\tif def.folder.Options.ImportsSource == settings.ImportsSourceGopls {\n\t\tv.modcacheState = newModcacheState(def.folder.Env.GOMODCACHE)\n\t}\n\n\ts.snapshotWG.Add(1)\n\tv.snapshot = &Snapshot{\n\t\tview:              v,\n\t\tbackgroundCtx:     backgroundCtx,\n\t\tcancel:            cancel,\n\t\tstore:             s.cache.store,\n\t\trefcount:          1, // Snapshots are born referenced.\n\t\tdone:              s.snapshotWG.Done,\n\t\tpackages:          new(persistent.Map[PackageID, *packageHandle]),\n\t\tfullAnalysisKeys:  new(persistent.Map[PackageID, file.Hash]),\n\t\tfactyAnalysisKeys: new(persistent.Map[PackageID, file.Hash]),\n\t\tmeta:              new(metadata.Graph),\n\t\tfiles:             newFileMap(),\n\t\tshouldLoad:        new(persistent.Map[PackageID, []PackagePath]),\n\t\tunloadableFiles:   new(persistent.Set[protocol.DocumentURI]),\n\t\tparseModHandles:   new(persistent.Map[protocol.DocumentURI, *memoize.Promise]),\n\t\tparseWorkHandles:  new(persistent.Map[protocol.DocumentURI, *memoize.Promise]),\n\t\tmodTidyHandles:    new(persistent.Map[protocol.DocumentURI, *memoize.Promise]),\n\t\tmodVulnHandles:    new(persistent.Map[protocol.DocumentURI, *memoize.Promise]),\n\t\tmodWhyHandles:     new(persistent.Map[protocol.DocumentURI, *memoize.Promise]),\n\t\tmoduleUpgrades:    new(persistent.Map[protocol.DocumentURI, map[string]string]),\n\t\tvulns:             new(persistent.Map[protocol.DocumentURI, *vulncheck.Result]),\n\t}\n\n\t// Snapshots must observe all open files, as there are some caching\n\t// heuristics that change behavior depending on open files.\n\tfor _, o := range s.overlayFS.Overlays() {\n\t\t_, _ = v.snapshot.ReadFile(ctx, o.URI())\n\t}\n\n\t// Record the environment of the newly created view in the log.\n\tevent.Log(ctx, fmt.Sprintf(\"Created View (#%s)\", v.id),\n\t\tlabel.Directory.Of(v.folder.Dir.Path()),\n\t\tviewTypeKey.Of(v.typ.String()),\n\t\trootDirKey.Of(string(v.root)),\n\t\tgoVersionKey.Of(strings.TrimRight(v.folder.Env.GoVersionOutput, \"\\n\")),\n\t\tbuildFlagsKey.Of(fmt.Sprint(v.folder.Options.BuildFlags)),\n\t\tenvKey.Of(fmt.Sprintf(\"%+v\", v.folder.Env)),\n\t\tenvOverlayKey.Of(v.EnvOverlay()),\n\t)\n\n\t// Initialize the view without blocking.\n\tinitCtx, initCancel := context.WithCancel(xcontext.Detach(ctx))\n\tv.cancelInitialWorkspaceLoad = initCancel\n\tsnapshot := v.snapshot\n\n\t// Pass a second reference to the background goroutine.\n\tbgRelease := snapshot.Acquire()\n\tgo func() {\n\t\tdefer bgRelease()\n\t\tsnapshot.initialize(initCtx, true)\n\t}()\n\n\t// Return a third reference to the caller.\n\treturn v, snapshot, snapshot.Acquire()\n}\n\n// These keys are used to log view metadata in createView.\nvar (\n\tviewTypeKey   = keys.NewString(\"view_type\", \"\")\n\trootDirKey    = keys.NewString(\"root_dir\", \"\")\n\tgoVersionKey  = keys.NewString(\"go_version\", \"\")\n\tbuildFlagsKey = keys.New(\"build_flags\", \"\")\n\tenvKey        = keys.New(\"env\", \"\")\n\tenvOverlayKey = keys.New(\"env_overlay\", \"\")\n)\n\n// RemoveView removes from the session the view rooted at the specified directory.\n// It reports whether a view of that directory was removed.\nfunc (s *Session) RemoveView(ctx context.Context, dir protocol.DocumentURI) bool {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\tif s.viewMap == nil {\n\t\treturn false // Session is shutdown.\n\t}\n\ts.viewMap = make(map[protocol.DocumentURI]*View) // reset view associations\n\n\tvar newViews []*View\n\tfor _, view := range s.views {\n\t\tif view.folder.Dir == dir {\n\t\t\tview.shutdown()\n\t\t} else {\n\t\t\tnewViews = append(newViews, view)\n\t\t}\n\t}\n\tremoved := len(s.views) - len(newViews)\n\tif removed != 1 {\n\t\t// This isn't a bug report, because it could be a client-side bug.\n\t\tevent.Error(ctx, \"removing view\", fmt.Errorf(\"removed %d views, want exactly 1\", removed))\n\t}\n\ts.views = newViews\n\treturn removed > 0\n}\n\n// View returns the view with a matching id, if present.\nfunc (s *Session) View(id string) (*View, error) {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\tfor _, view := range s.views {\n\t\tif view.ID() == id {\n\t\t\treturn view, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"no view with ID %q\", id)\n}\n\n// SnapshotOf returns a Snapshot corresponding to the given URI.\n//\n// In the case where the file can be  can be associated with a View by\n// [RelevantViews] (based on directory information alone, without package\n// metadata), SnapshotOf returns the current Snapshot for that View. Otherwise,\n// it awaits loading package metadata and returns a Snapshot for the first View\n// containing a real (=not command-line-arguments) package for the file.\n//\n// If that also fails to find a View, SnapshotOf returns a Snapshot for the\n// first view in s.views that is not shut down (i.e. s.views[0] unless we lose\n// a race), for determinism in tests and so that we tend to aggregate the\n// resulting command-line-arguments packages into a single view.\n//\n// SnapshotOf returns an error if a failure occurs along the way (most likely due\n// to context cancellation), or if there are no Views in the Session.\n//\n// On success, the caller must call the returned function to release the snapshot.\nfunc (s *Session) SnapshotOf(ctx context.Context, uri protocol.DocumentURI) (*Snapshot, func(), error) {\n\turi = uri.Clean()\n\t// Fast path: if the uri has a static association with a view, return it.\n\ts.viewMu.Lock()\n\tv, err := s.viewOfLocked(ctx, uri)\n\ts.viewMu.Unlock()\n\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif v != nil {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err == nil {\n\t\t\treturn snapshot, release, nil\n\t\t}\n\t\t// View is shut down. Forget this association.\n\t\ts.viewMu.Lock()\n\t\tif s.viewMap[uri] == v {\n\t\t\tdelete(s.viewMap, uri)\n\t\t}\n\t\ts.viewMu.Unlock()\n\t}\n\n\t// Fall-back: none of the views could be associated with uri based on\n\t// directory information alone.\n\t//\n\t// Don't memoize the view association in viewMap, as it is not static: Views\n\t// may change as metadata changes.\n\t//\n\t// TODO(rfindley): we could perhaps optimize this case by peeking at existing\n\t// metadata before awaiting the load (after all, a load only adds metadata).\n\t// But that seems potentially tricky, when in the common case no loading\n\t// should be required.\n\tviews := s.Views()\n\tfor _, v := range views {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // view was shut down\n\t\t}\n\t\t// We don't check the error from awaitLoaded, because a load failure (that\n\t\t// doesn't result from context cancellation) should not prevent us from\n\t\t// continuing to search for the best view.\n\t\t_ = snapshot.awaitLoaded(ctx)\n\t\tg := snapshot.MetadataGraph()\n\t\tif ctx.Err() != nil {\n\t\t\trelease()\n\t\t\treturn nil, nil, ctx.Err()\n\t\t}\n\t\t// Special handling for the builtin file, since it doesn't have packages.\n\t\tif snapshot.IsBuiltin(uri) {\n\t\t\treturn snapshot, release, nil\n\t\t}\n\t\t// Only match this view if it loaded a real package for the file.\n\t\t//\n\t\t// Any view can load a command-line-arguments package; aggregate those into\n\t\t// views[0] below.\n\t\tfor _, pkg := range g.ForFile[uri] {\n\t\t\tif !metadata.IsCommandLineArguments(pkg.ID) || pkg.Standalone {\n\t\t\t\treturn snapshot, release, nil\n\t\t\t}\n\t\t}\n\t\trelease()\n\t}\n\n\tfor _, v := range views {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err == nil {\n\t\t\treturn snapshot, release, nil // first valid snapshot\n\t\t}\n\t}\n\treturn nil, nil, errNoViews\n}\n\n// FileOf returns the file for a given URI and its snapshot.\n// On success, the returned function must be called to release the snapshot.\nfunc (s *Session) FileOf(ctx context.Context, uri protocol.DocumentURI) (file.Handle, *Snapshot, func(), error) {\n\tsnapshot, release, err := s.SnapshotOf(ctx, uri)\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\trelease()\n\t\treturn nil, nil, nil, err\n\t}\n\treturn fh, snapshot, release, nil\n}\n\n// errNoViews is sought by orphaned file diagnostics, to detect the case where\n// we have no view containing a file.\nvar errNoViews = errors.New(\"no views\")\n\n// viewOfLocked evaluates the best view for uri, memoizing its result in\n// s.viewMap.\n//\n// Precondition: caller holds s.viewMu lock; uri must be clean.\n//\n// May return (nil, nil) if no best view can be determined.\nfunc (s *Session) viewOfLocked(ctx context.Context, uri protocol.DocumentURI) (*View, error) {\n\tif s.viewMap == nil {\n\t\treturn nil, errors.New(\"session is shut down\")\n\t}\n\tv, hit := s.viewMap[uri]\n\tif !hit {\n\t\t// Cache miss: compute (and memoize) the best view.\n\t\tfh, err := s.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trelevantViews, err := RelevantViews(ctx, s, fh.URI(), s.views)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv = matchingView(fh, relevantViews)\n\t\tif v == nil && len(relevantViews) > 0 {\n\t\t\t// If we have relevant views, but none of them matched the file's build\n\t\t\t// constraints, then we are still better off using one of them here.\n\t\t\t// Otherwise, logic may fall back to an inferior view, which lacks\n\t\t\t// relevant module information, leading to misleading diagnostics.\n\t\t\t// (as in golang/go#60776).\n\t\t\tv = relevantViews[0]\n\t\t}\n\t\ts.viewMap[uri] = v // may be nil\n\t}\n\treturn v, nil\n}\n\nfunc (s *Session) Views() []*View {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\tresult := make([]*View, len(s.views))\n\tcopy(result, s.views)\n\treturn result\n}\n\n// selectViewDefs constructs the best set of views covering the provided workspace\n// folders and open files.\n//\n// This implements the zero-config algorithm of golang/go#57979.\nfunc selectViewDefs(ctx context.Context, fs file.Source, folders []*Folder, openFiles []protocol.DocumentURI) ([]*viewDefinition, error) {\n\tvar defs []*viewDefinition\n\n\t// First, compute a default view for each workspace folder.\n\t// TODO(golang/go#57979): technically, this is path dependent, since\n\t// DidChangeWorkspaceFolders could introduce a path-dependent ordering on\n\t// folders. We should keep folders sorted, or sort them here.\n\tfor _, folder := range folders {\n\t\tdef, err := defineView(ctx, fs, folder, nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefs = append(defs, def)\n\t}\n\n\t// Next, ensure that the set of views covers all open files contained in a\n\t// workspace folder.\n\t//\n\t// We only do this for files contained in a workspace folder, because other\n\t// open files are most likely the result of jumping to a definition from a\n\t// workspace file; we don't want to create additional views in those cases:\n\t// they should be resolved after initialization.\n\n\tfolderForFile := func(uri protocol.DocumentURI) *Folder {\n\t\tvar longest *Folder\n\t\tfor _, folder := range folders {\n\t\t\t// Check that this is a better match than longest, but not through a\n\t\t\t// vendor directory. Count occurrences of \"/vendor/\" as a quick check\n\t\t\t// that the vendor directory is between the folder and the file. Note the\n\t\t\t// addition of a trailing \"/\" to handle the odd case where the folder is named\n\t\t\t// vendor (which I hope is exceedingly rare in any case).\n\t\t\t//\n\t\t\t// Vendored packages are, by definition, part of an existing view.\n\t\t\tif (longest == nil || len(folder.Dir) > len(longest.Dir)) &&\n\t\t\t\tfolder.Dir.Encloses(uri) &&\n\t\t\t\tstrings.Count(string(uri), \"/vendor/\") == strings.Count(string(folder.Dir)+\"/\", \"/vendor/\") {\n\n\t\t\t\tlongest = folder\n\t\t\t}\n\t\t}\n\t\treturn longest\n\t}\n\ncheckFiles:\n\tfor _, uri := range openFiles {\n\t\tfolder := folderForFile(uri)\n\t\tif folder == nil || !folder.Options.ZeroConfig {\n\t\t\tcontinue // only guess views for open files\n\t\t}\n\t\tfh, err := fs.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trelevantViews, err := RelevantViews(ctx, fs, fh.URI(), defs)\n\t\tif err != nil {\n\t\t\t// We should never call selectViewDefs with a cancellable context, so\n\t\t\t// this should never fail.\n\t\t\treturn nil, bug.Errorf(\"failed to find best view for open file: %v\", err)\n\t\t}\n\t\tdef := matchingView(fh, relevantViews)\n\t\tif def != nil {\n\t\t\tcontinue // file covered by an existing view\n\t\t}\n\t\tdef, err = defineView(ctx, fs, folder, fh)\n\t\tif err != nil {\n\t\t\t// e.g. folder path is invalid?\n\t\t\treturn nil, fmt.Errorf(\"failed to define view for open file: %v\", err)\n\t\t}\n\t\t// It need not strictly be the case that the best view for a file is\n\t\t// distinct from other views, as the logic of getViewDefinition and\n\t\t// [RelevantViews] does not align perfectly. This is not necessarily a bug:\n\t\t// there may be files for which we can't construct a valid view.\n\t\t//\n\t\t// Nevertheless, we should not create redundant views.\n\t\tfor _, alt := range defs {\n\t\t\tif viewDefinitionsEqual(alt, def) {\n\t\t\t\tcontinue checkFiles\n\t\t\t}\n\t\t}\n\t\tdefs = append(defs, def)\n\t}\n\n\treturn defs, nil\n}\n\n// The viewDefiner interface allows the [RelevantViews] algorithm to operate on both\n// Views and viewDefinitions.\ntype viewDefiner interface{ definition() *viewDefinition }\n\n// RelevantViews returns the views that may contain the given URI, or nil if\n// none exist. A view is \"relevant\" if, ignoring build constraints, it may have\n// a workspace package containing uri. Therefore, the definition of relevance\n// depends on the view type.\nfunc RelevantViews[V viewDefiner](ctx context.Context, fs file.Source, uri protocol.DocumentURI, views []V) ([]V, error) {\n\tif len(views) == 0 {\n\t\treturn nil, nil // avoid the call to findRootPattern\n\t}\n\tdir := uri.Dir()\n\tmodURI, err := findRootPattern(ctx, dir, \"go.mod\", fs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Prefer GoWork > GoMod > GOPATH > GoPackages > AdHoc.\n\tvar (\n\t\tgoPackagesViews []V // prefer longest\n\t\tworkViews       []V // prefer longest\n\t\tmodViews        []V // exact match\n\t\tgopathViews     []V // prefer longest\n\t\tadHocViews      []V // exact match\n\t)\n\n\t// pushView updates the views slice with the matching view v, using the\n\t// heuristic that views with a longer root are preferable. Accordingly,\n\t// pushView may be a no op if v's root is shorter than the roots in the views\n\t// slice.\n\t//\n\t// Invariant: the length of all roots in views is the same.\n\tpushView := func(views *[]V, v V) {\n\t\tif len(*views) == 0 {\n\t\t\t*views = []V{v}\n\t\t\treturn\n\t\t}\n\t\tbetter := func(l, r V) bool {\n\t\t\treturn len(l.definition().root) > len(r.definition().root)\n\t\t}\n\t\texisting := (*views)[0]\n\t\tswitch {\n\t\tcase better(existing, v):\n\t\tcase better(v, existing):\n\t\t\t*views = []V{v}\n\t\tdefault:\n\t\t\t*views = append(*views, v)\n\t\t}\n\t}\n\n\tfor _, view := range views {\n\t\tswitch def := view.definition(); def.Type() {\n\t\tcase GoPackagesDriverView:\n\t\t\tif def.root.Encloses(dir) {\n\t\t\t\tpushView(&goPackagesViews, view)\n\t\t\t}\n\t\tcase GoWorkView:\n\t\t\tif _, ok := def.workspaceModFiles[modURI]; ok || uri == def.gowork {\n\t\t\t\tpushView(&workViews, view)\n\t\t\t}\n\t\tcase GoModView:\n\t\t\tif _, ok := def.workspaceModFiles[modURI]; ok {\n\t\t\t\tmodViews = append(modViews, view)\n\t\t\t}\n\t\tcase GOPATHView:\n\t\t\tif def.root.Encloses(dir) {\n\t\t\t\tpushView(&gopathViews, view)\n\t\t\t}\n\t\tcase AdHocView:\n\t\t\tif def.root == dir {\n\t\t\t\tadHocViews = append(adHocViews, view)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Now that we've collected matching views, choose the best match,\n\t// considering ports.\n\t//\n\t// We only consider one type of view, since the matching view created by\n\t// defineView should be of the best type.\n\tvar relevantViews []V\n\tswitch {\n\tcase len(workViews) > 0:\n\t\trelevantViews = workViews\n\tcase len(modViews) > 0:\n\t\trelevantViews = modViews\n\tcase len(gopathViews) > 0:\n\t\trelevantViews = gopathViews\n\tcase len(goPackagesViews) > 0:\n\t\trelevantViews = goPackagesViews\n\tcase len(adHocViews) > 0:\n\t\trelevantViews = adHocViews\n\t}\n\n\treturn relevantViews, nil\n}\n\n// matchingView returns the View or viewDefinition out of relevantViews that\n// matches the given file's build constraints, or nil if no match is found.\n//\n// Making this function generic is convenient so that we can avoid mapping view\n// definitions back to views inside Session.DidModifyFiles, where performance\n// matters. It is, however, not the cleanest application of generics.\n//\n// Note: keep this function in sync with defineView.\nfunc matchingView[V viewDefiner](fh file.Handle, relevantViews []V) V {\n\tvar zero V\n\n\tif len(relevantViews) == 0 {\n\t\treturn zero\n\t}\n\n\tcontent, err := fh.Content()\n\n\t// Port matching doesn't apply to non-go files, or files that no longer exist.\n\t// Note that the behavior here on non-existent files shouldn't matter much,\n\t// since there will be a subsequent failure.\n\tif fileKind(fh) != file.Go || err != nil {\n\t\treturn relevantViews[0]\n\t}\n\n\t// Find the first view that matches constraints.\n\t// Content trimming is nontrivial, so do this outside of the loop below.\n\tpath := fh.URI().Path()\n\tcontent = trimContentForPortMatch(content)\n\tfor _, v := range relevantViews {\n\t\tdef := v.definition()\n\t\tviewPort := port{def.GOOS(), def.GOARCH()}\n\t\tif viewPort.matches(path, content) {\n\t\t\treturn v\n\t\t}\n\t}\n\n\treturn zero // no view found\n}\n\n// ResetView resets the best view for the given URI.\nfunc (s *Session) ResetView(ctx context.Context, uri protocol.DocumentURI) (*View, error) {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\tif s.viewMap == nil {\n\t\treturn nil, fmt.Errorf(\"session is shut down\")\n\t}\n\n\tview, err := s.viewOfLocked(ctx, uri.Clean())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif view == nil {\n\t\treturn nil, fmt.Errorf(\"no view for %s\", uri)\n\t}\n\n\ts.viewMap = make(map[protocol.DocumentURI]*View)\n\tfor i, v := range s.views {\n\t\tif v == view {\n\t\t\tv2, _, release := s.createView(ctx, view.viewDefinition)\n\t\t\trelease() // don't need the snapshot\n\t\t\tv.shutdown()\n\t\t\ts.views[i] = v2\n\t\t\treturn v2, nil\n\t\t}\n\t}\n\n\treturn nil, bug.Errorf(\"missing view\") // can't happen...\n}\n\n// DidModifyFiles reports a file modification to the session. It returns\n// the new snapshots after the modifications have been applied, paired with\n// the affected file URIs for those snapshots.\n// On success, it returns a release function that\n// must be called when the snapshots are no longer needed.\n//\n// TODO(rfindley): what happens if this function fails? It must leave us in a\n// broken state, which we should surface to the user, probably as a request to\n// restart gopls.\nfunc (s *Session) DidModifyFiles(ctx context.Context, modifications []file.Modification) (map[*View][]protocol.DocumentURI, error) {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\t// Short circuit the logic below if s is shut down.\n\tif s.viewMap == nil {\n\t\treturn nil, fmt.Errorf(\"session is shut down\")\n\t}\n\n\t// Update overlays.\n\t//\n\t// This is done while holding viewMu because the set of open files affects\n\t// the set of views, and to prevent views from seeing updated file content\n\t// before they have processed invalidations.\n\treplaced, err := s.updateOverlays(ctx, modifications)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// checkViews controls whether the set of views needs to be recomputed, for\n\t// example because a go.mod file was created or deleted, or a go.work file\n\t// changed on disk.\n\tcheckViews := false\n\n\t// Hack: collect folders from existing views.\n\t// TODO(golang/go#57979): we really should track folders independent of\n\t// Views, but since we always have a default View for each folder, this\n\t// works for now.\n\tvar folders []*Folder // preserve folder order\n\tworkspaceFileGlobsSet := make(map[string]bool)\n\tseen := make(map[*Folder]unit)\n\tfor _, v := range s.views {\n\t\tif _, ok := seen[v.folder]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseen[v.folder] = unit{}\n\t\tfolders = append(folders, v.folder)\n\t\tfor _, glob := range v.folder.Options.WorkspaceFiles {\n\t\t\tworkspaceFileGlobsSet[glob] = true\n\t\t}\n\t}\n\tworkspaceFileGlobs := slices.Collect(maps.Keys(workspaceFileGlobsSet))\n\n\tchanged := make(map[protocol.DocumentURI]file.Handle)\n\tfor _, c := range modifications {\n\t\tfh := mustReadFile(ctx, s, c.URI)\n\t\tchanged[c.URI] = fh\n\n\t\t// Any change to the set of open files causes views to be recomputed.\n\t\tif c.Action == file.Open || c.Action == file.Close {\n\t\t\tcheckViews = true\n\t\t}\n\n\t\t// Any on-disk change to a go.work or go.mod file causes recomputing views.\n\t\t//\n\t\t// TODO(rfindley): go.work files need not be named \"go.work\" -- we need to\n\t\t// check each view's source to handle the case of an explicit GOWORK value.\n\t\t// Write a test that fails, and fix this.\n\t\tif (isGoWork(c.URI) || isGoMod(c.URI) || isWorkspaceFile(c.URI, workspaceFileGlobs)) && (c.Action == file.Save || c.OnDisk) {\n\t\t\tcheckViews = true\n\t\t}\n\n\t\t// Any change to the set of supported ports in a file may affect view\n\t\t// selection. This is perhaps more subtle than it first seems: since the\n\t\t// algorithm for selecting views considers open files in a deterministic\n\t\t// order, a change in supported ports may cause a different port to be\n\t\t// chosen, even if all open files still match an existing View!\n\t\t//\n\t\t// We endeavor to avoid that sort of path dependence, so must re-run the\n\t\t// view selection algorithm whenever any input changes.\n\t\t//\n\t\t// However, extracting the build comment is nontrivial, so we don't want to\n\t\t// pay this cost when e.g. processing a bunch of on-disk changes due to a\n\t\t// branch change. Be careful to only do this if both files are open Go\n\t\t// files.\n\t\tif old, ok := replaced[c.URI]; ok && !checkViews && fileKind(fh) == file.Go {\n\t\t\tif new, ok := fh.(*overlay); ok {\n\t\t\t\tif buildComment(old.content) != buildComment(new.content) {\n\t\t\t\t\tcheckViews = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif checkViews {\n\t\tvar openFiles []protocol.DocumentURI\n\t\tfor _, o := range s.Overlays() {\n\t\t\topenFiles = append(openFiles, o.URI())\n\t\t}\n\t\t// Sort for determinism.\n\t\tslices.Sort(openFiles)\n\n\t\t// TODO(rfindley): can we avoid running the go command (go env)\n\t\t// synchronously to change processing? Can we assume that the env did not\n\t\t// change, and derive go.work using a combination of the configured\n\t\t// GOWORK value and filesystem?\n\t\tdefs, err := selectViewDefs(ctx, s, folders, openFiles)\n\t\tif err != nil {\n\t\t\t// Catastrophic failure, equivalent to a failure of session\n\t\t\t// initialization and therefore should almost never happen. One\n\t\t\t// scenario where this failure mode could occur is if some file\n\t\t\t// permissions have changed preventing us from reading go.mod\n\t\t\t// files.\n\t\t\t//\n\t\t\t// TODO(rfindley): consider surfacing this error more loudly. We\n\t\t\t// could report a bug, but it's not really a bug.\n\t\t\tevent.Error(ctx, \"selecting new views\", err)\n\t\t} else {\n\t\t\tkept := make(map[*View]unit)\n\t\t\tvar newViews []*View\n\t\t\tfor _, def := range defs {\n\t\t\t\tvar newView *View\n\t\t\t\t// Reuse existing view?\n\t\t\t\tfor _, v := range s.views {\n\t\t\t\t\tif viewDefinitionsEqual(def, v.viewDefinition) {\n\t\t\t\t\t\tnewView = v\n\t\t\t\t\t\tkept[v] = unit{}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif newView == nil {\n\t\t\t\t\tv, _, release := s.createView(ctx, def)\n\t\t\t\t\trelease()\n\t\t\t\t\tnewView = v\n\t\t\t\t}\n\t\t\t\tnewViews = append(newViews, newView)\n\t\t\t}\n\t\t\tfor _, v := range s.views {\n\t\t\t\tif _, ok := kept[v]; !ok {\n\t\t\t\t\tv.shutdown()\n\t\t\t\t}\n\t\t\t}\n\t\t\ts.views = newViews\n\t\t\ts.viewMap = make(map[protocol.DocumentURI]*View)\n\t\t}\n\t}\n\n\t// We only want to run fast-path diagnostics (i.e. diagnoseChangedFiles) once\n\t// for each changed file, in its best view.\n\tviewsToDiagnose := map[*View][]protocol.DocumentURI{}\n\tfor _, mod := range modifications {\n\t\tv, err := s.viewOfLocked(ctx, mod.URI)\n\t\tif err != nil {\n\t\t\t// viewOfLocked only returns an error in the event of context\n\t\t\t// cancellation, or if the session is shut down. Since state changes\n\t\t\t// should occur on an uncancellable context, and s.viewMap was checked at\n\t\t\t// the top of this function, an error here is a bug.\n\t\t\tbug.Reportf(\"finding best view for change: %v\", err)\n\t\t\tcontinue\n\t\t}\n\t\tif v != nil {\n\t\t\tviewsToDiagnose[v] = append(viewsToDiagnose[v], mod.URI)\n\t\t}\n\t}\n\n\t// ...but changes may be relevant to other views, for example if they are\n\t// changes to a shared package.\n\tfor _, v := range s.views {\n\t\t_, release, needsDiagnosis := s.invalidateViewLocked(ctx, v, StateChange{Modifications: modifications, Files: changed})\n\t\trelease()\n\n\t\tif needsDiagnosis || checkViews {\n\t\t\tif _, ok := viewsToDiagnose[v]; !ok {\n\t\t\t\tviewsToDiagnose[v] = nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn viewsToDiagnose, nil\n}\n\n// ExpandModificationsToDirectories returns the set of changes with the\n// directory changes removed and expanded to include all of the files in\n// the directory.\nfunc (s *Session) ExpandModificationsToDirectories(ctx context.Context, changes []file.Modification) []file.Modification {\n\tvar snapshots []*Snapshot\n\ts.viewMu.Lock()\n\tfor _, v := range s.views {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // view is shut down; continue with others\n\t\t}\n\t\tdefer release()\n\t\tsnapshots = append(snapshots, snapshot)\n\t}\n\ts.viewMu.Unlock()\n\n\t// Expand the modification to any file we could care about, which we define\n\t// to be any file observed by any of the snapshots.\n\t//\n\t// There may be other files in the directory, but if we haven't read them yet\n\t// we don't need to invalidate them.\n\tvar result []file.Modification\n\tfor _, c := range changes {\n\t\texpanded := make(map[protocol.DocumentURI]bool)\n\t\tfor _, snapshot := range snapshots {\n\t\t\tfor _, uri := range snapshot.filesInDir(c.URI) {\n\t\t\t\texpanded[uri] = true\n\t\t\t}\n\t\t}\n\t\tif len(expanded) == 0 {\n\t\t\tresult = append(result, c)\n\t\t} else {\n\t\t\tfor uri := range expanded {\n\t\t\t\tresult = append(result, file.Modification{\n\t\t\t\t\tURI:        uri,\n\t\t\t\t\tAction:     c.Action,\n\t\t\t\t\tLanguageID: \"\",\n\t\t\t\t\tOnDisk:     c.OnDisk,\n\t\t\t\t\t// changes to directories cannot include text or versions\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\n// updateOverlays updates the set of overlays and returns a map of any existing\n// overlay values that were replaced.\n//\n// Precondition: caller holds s.viewMu lock.\n// TODO(rfindley): move this to fs_overlay.go.\nfunc (fs *overlayFS) updateOverlays(ctx context.Context, changes []file.Modification) (map[protocol.DocumentURI]*overlay, error) {\n\tfs.mu.Lock()\n\tdefer fs.mu.Unlock()\n\n\treplaced := make(map[protocol.DocumentURI]*overlay)\n\tfor _, c := range changes {\n\t\to, ok := fs.overlays[c.URI]\n\t\tif ok {\n\t\t\treplaced[c.URI] = o\n\t\t}\n\n\t\t// If the file is not opened in an overlay and the change is on disk,\n\t\t// there's no need to update an overlay. If there is an overlay, we\n\t\t// may need to update the overlay's saved value.\n\t\tif !ok && c.OnDisk {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Determine the file kind on open, otherwise, assume it has been cached.\n\t\tvar kind file.Kind\n\t\tswitch c.Action {\n\t\tcase file.Open:\n\t\t\tkind = file.KindForLang(c.LanguageID)\n\t\tdefault:\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"updateOverlays: modifying unopened overlay %v\", c.URI)\n\t\t\t}\n\t\t\tkind = o.kind\n\t\t}\n\n\t\t// Closing a file just deletes its overlay.\n\t\tif c.Action == file.Close {\n\t\t\tdelete(fs.overlays, c.URI)\n\t\t\tcontinue\n\t\t}\n\n\t\t// If the file is on disk, check if its content is the same as in the\n\t\t// overlay. Saves and on-disk file changes don't come with the file's\n\t\t// content.\n\t\ttext := c.Text\n\t\tif text == nil && (c.Action == file.Save || c.OnDisk) {\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"no known content for overlay for %s\", c.Action)\n\t\t\t}\n\t\t\ttext = o.content\n\t\t}\n\t\t// On-disk changes don't come with versions.\n\t\tversion := c.Version\n\t\tif c.OnDisk || c.Action == file.Save {\n\t\t\tversion = o.version\n\t\t}\n\t\thash := file.HashOf(text)\n\t\tvar sameContentOnDisk bool\n\t\tswitch c.Action {\n\t\tcase file.Delete:\n\t\t\t// Do nothing. sameContentOnDisk should be false.\n\t\tcase file.Save:\n\t\t\t// Make sure the version and content (if present) is the same.\n\t\t\tif false && o.version != version { // Client no longer sends the version\n\t\t\t\treturn nil, fmt.Errorf(\"updateOverlays: saving %s at version %v, currently at %v\", c.URI, c.Version, o.version)\n\t\t\t}\n\t\t\tif c.Text != nil && o.hash != hash {\n\t\t\t\treturn nil, fmt.Errorf(\"updateOverlays: overlay %s changed on save\", c.URI)\n\t\t\t}\n\t\t\tsameContentOnDisk = true\n\t\tdefault:\n\t\t\tfh := mustReadFile(ctx, fs.delegate, c.URI)\n\t\t\t_, readErr := fh.Content()\n\t\t\tsameContentOnDisk = (readErr == nil && fh.Identity().Hash == hash)\n\t\t}\n\t\to = &overlay{\n\t\t\turi:     c.URI,\n\t\t\tversion: version,\n\t\t\tcontent: text,\n\t\t\tmodTime: time.Now(),\n\t\t\tkind:    kind,\n\t\t\thash:    hash,\n\t\t\tsaved:   sameContentOnDisk,\n\t\t}\n\n\t\t// NOTE: previous versions of this code checked here that the overlay had a\n\t\t// view and file kind (but we don't know why).\n\n\t\tfs.overlays[c.URI] = o\n\t}\n\n\treturn replaced, nil\n}\n\nfunc mustReadFile(ctx context.Context, fs file.Source, uri protocol.DocumentURI) file.Handle {\n\tctx = xcontext.Detach(ctx)\n\tfh, err := fs.ReadFile(ctx, uri)\n\tif err != nil {\n\t\t// ReadFile cannot fail with an uncancellable context.\n\t\tbug.Reportf(\"reading file failed unexpectedly: %v\", err)\n\t\treturn brokenFile{uri, err}\n\t}\n\treturn fh\n}\n\n// A brokenFile represents an unexpected failure to read a file.\ntype brokenFile struct {\n\turi protocol.DocumentURI\n\terr error\n}\n\nfunc (b brokenFile) String() string              { return b.uri.Path() }\nfunc (b brokenFile) URI() protocol.DocumentURI   { return b.uri }\nfunc (b brokenFile) Identity() file.Identity     { return file.Identity{URI: b.uri} }\nfunc (b brokenFile) SameContentsOnDisk() bool    { return false }\nfunc (b brokenFile) Version() int32              { return 0 }\nfunc (b brokenFile) Content() ([]byte, error)    { return nil, b.err }\nfunc (b brokenFile) ModTime() (time.Time, error) { return time.Time{}, b.err }\n\n// FileWatchingGlobPatterns returns a set of glob patterns that the client is\n// required to watch for changes, and notify the server of them, in order to\n// keep the server's state up to date.\n//\n// This set includes\n//  1. all go.mod and go.work files in the workspace; and\n//  2. all files defined by the WorkspaceFiles option in BuildOptions (to support custom GOPACKAGESDRIVERS); and\n//  3. for each Snapshot, its modules (or directory for ad-hoc views). In\n//     module mode, this is the set of active modules (and for VS Code, all\n//     workspace directories within them, due to golang/go#42348).\n//\n// The watch for workspace files in (1) is sufficient to\n// capture changes to the repo structure that may affect the set of views.\n// Whenever this set changes, we reload the workspace and invalidate memoized\n// files.\n//\n// The watch for workspace directories in (2) should keep each View up to date,\n// as it should capture any newly added/modified/deleted Go files.\n//\n// Patterns are returned as a set of protocol.RelativePatterns, since they can\n// always be later translated to glob patterns (i.e. strings) if the client\n// lacks relative pattern support. By convention, any pattern returned with\n// empty baseURI should be served as a glob pattern.\n//\n// In general, we prefer to serve relative patterns, as they work better on\n// most clients that support both, and do not have issues with Windows driver\n// letter casing:\n// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#relativePattern\n//\n// TODO(golang/go#57979): we need to reset the memoizedFS when a view changes.\n// Consider the case where we incidentally read a file, then it moved outside\n// of an active module, and subsequently changed: we would still observe the\n// original file state.\nfunc (s *Session) FileWatchingGlobPatterns(ctx context.Context) map[protocol.RelativePattern]unit {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\t// Always watch files that may change the set of views.\n\tpatterns := map[protocol.RelativePattern]unit{\n\t\t{Pattern: \"**/*.{mod,work}\"}: {},\n\t}\n\n\tfor _, view := range s.views {\n\t\tsnapshot, release, err := view.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // view is shut down; continue with others\n\t\t}\n\t\tmaps.Copy(patterns, snapshot.fileWatchingGlobPatterns())\n\t\trelease()\n\t}\n\treturn patterns\n}\n\n// OrphanedFileDiagnostics reports diagnostics describing why open files have\n// no packages or have only command-line-arguments packages.\n//\n// If the resulting diagnostic is nil, the file is either not orphaned or we\n// can't produce a good diagnostic.\n//\n// The caller must not mutate the result.\nfunc (s *Session) OrphanedFileDiagnostics(ctx context.Context) (map[protocol.DocumentURI][]*Diagnostic, error) {\n\tif err := ctx.Err(); err != nil {\n\t\t// Avoid collecting diagnostics if the context is cancelled.\n\t\t// (Previously, it was possible to get all the way to packages.Load on a cancelled context)\n\t\treturn nil, err\n\t}\n\t// Note: diagnostics holds a slice for consistency with other diagnostic\n\t// funcs.\n\tdiagnostics := make(map[protocol.DocumentURI][]*Diagnostic)\n\n\tbyView := make(map[*View][]*overlay)\n\tfor _, o := range s.Overlays() {\n\t\turi := o.URI()\n\t\tsnapshot, release, err := s.SnapshotOf(ctx, uri)\n\t\tif err != nil {\n\t\t\t// TODO(golang/go#57979): we have to use the .go suffix as an approximation for\n\t\t\t// file kind here, because we don't have access to Options if no View was\n\t\t\t// matched.\n\t\t\t//\n\t\t\t// But Options are really a property of Folder, not View, and we could\n\t\t\t// match a folder here.\n\t\t\t//\n\t\t\t// Refactor so that Folders are tracked independently of Views, and use\n\t\t\t// the correct options here to get the most accurate file kind.\n\t\t\t//\n\t\t\t// TODO(golang/go#57979): once we switch entirely to the zeroconfig\n\t\t\t// logic, we should use this diagnostic for the fallback case of\n\t\t\t// s.views[0] in the ViewOf logic.\n\t\t\tif errors.Is(err, errNoViews) {\n\t\t\t\tif strings.HasSuffix(string(uri), \".go\") {\n\t\t\t\t\tif _, rng, ok := orphanedFileDiagnosticRange(ctx, s.parseCache, o); ok {\n\t\t\t\t\t\tdiagnostics[uri] = []*Diagnostic{{\n\t\t\t\t\t\t\tURI:      uri,\n\t\t\t\t\t\t\tRange:    rng,\n\t\t\t\t\t\t\tSeverity: protocol.SeverityWarning,\n\t\t\t\t\t\t\tSource:   ListError,\n\t\t\t\t\t\t\tMessage:  fmt.Sprintf(\"No active builds contain %s: consider opening a new workspace folder containing it\", uri.Path()),\n\t\t\t\t\t\t}}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tv := snapshot.View()\n\t\trelease()\n\t\tbyView[v] = append(byView[v], o)\n\t}\n\n\tfor view, overlays := range byView {\n\t\tsnapshot, release, err := view.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // view is shutting down\n\t\t}\n\t\tdefer release()\n\t\tdiags, err := snapshot.orphanedFileDiagnostics(ctx, overlays)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, d := range diags {\n\t\t\tdiagnostics[d.URI] = append(diagnostics[d.URI], d)\n\t\t}\n\t}\n\treturn diagnostics, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/session_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestZeroConfigAlgorithm(t *testing.T) {\n\ttestenv.NeedsExec(t) // executes the Go command\n\tt.Setenv(\"GOPACKAGESDRIVER\", \"off\")\n\n\ttype viewSummary struct {\n\t\t// fields exported for cmp.Diff\n\t\tType ViewType\n\t\tRoot string\n\t\tEnv  []string\n\t}\n\n\ttype folderSummary struct {\n\t\tdir     string\n\t\toptions func(dir string) map[string]any // options may refer to the temp dir\n\t}\n\n\tincludeReplaceInWorkspace := func(string) map[string]any {\n\t\treturn map[string]any{\n\t\t\t\"includeReplaceInWorkspace\": true,\n\t\t}\n\t}\n\n\ttype test struct {\n\t\tname    string\n\t\tfiles   map[string]string // use a map rather than txtar as file content is tiny\n\t\tfolders []folderSummary\n\t\topen    []string // open files\n\t\twant    []viewSummary\n\t}\n\n\ttests := []test{\n\t\t// TODO(rfindley): add a test for GOPACKAGESDRIVER.\n\t\t// Doing so doesn't yet work using options alone (user env is not honored)\n\n\t\t// TODO(rfindley): add a test for degenerate cases, such as missing\n\t\t// workspace folders (once we decide on the correct behavior).\n\t\t{\n\t\t\t\"basic go.work workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.work\":  \"go 1.18\\nuse (\\n\\t./a\\n\\t./b\\n)\\n\",\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\tnil,\n\t\t\t[]viewSummary{{GoWorkView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"basic go.mod workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\tnil,\n\t\t\t[]viewSummary{{GoModView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"basic GOPATH workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"src/golang.org/a/a.go\": \"package a\",\n\t\t\t\t\"src/golang.org/b/b.go\": \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{\n\t\t\t\tdir: \"src\",\n\t\t\t\toptions: func(dir string) map[string]any {\n\t\t\t\t\treturn map[string]any{\n\t\t\t\t\t\t\"env\": map[string]any{\n\t\t\t\t\t\t\t\"GO111MODULE\": \"\", // golang/go#70196: must be unset\n\t\t\t\t\t\t\t\"GOPATH\":      dir,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}},\n\t\t\t[]string{\"src/golang.org/a//a.go\", \"src/golang.org/b/b.go\"},\n\t\t\t[]viewSummary{{GOPATHView, \"src\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"basic AdHoc workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"foo.go\": \"package foo\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\tnil,\n\t\t\t[]viewSummary{{AdHocView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"multi-folder workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \"a\"}, {dir: \"b\"}},\n\t\t\tnil,\n\t\t\t[]viewSummary{{GoModView, \"a\", nil}, {GoModView, \"b\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"multi-module workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\tnil,\n\t\t\t[]viewSummary{{AdHocView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"zero-config open module\",\n\t\t\tmap[string]string{\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":   \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\"},\n\t\t\t[]viewSummary{\n\t\t\t\t{AdHocView, \".\", nil},\n\t\t\t\t{GoModView, \"a\", nil},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"zero-config open modules\",\n\t\t\tmap[string]string{\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":   \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{\n\t\t\t\t{AdHocView, \".\", nil},\n\t\t\t\t{GoModView, \"a\", nil},\n\t\t\t\t{GoModView, \"b\", nil},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"unified workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.work\":  \"go 1.18\\nuse (\\n\\t./a\\n\\t./b\\n)\\n\",\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":   \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoWorkView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"go.work from env\",\n\t\t\tmap[string]string{\n\t\t\t\t\"nested/go.work\": \"go 1.18\\nuse (\\n\\t../a\\n\\t../b\\n)\\n\",\n\t\t\t\t\"a/go.mod\":       \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":         \"package a\",\n\t\t\t\t\"b/go.mod\":       \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":         \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{\n\t\t\t\tdir: \".\",\n\t\t\t\toptions: func(dir string) map[string]any {\n\t\t\t\t\treturn map[string]any{\n\t\t\t\t\t\t\"env\": map[string]any{\n\t\t\t\t\t\t\t\"GOWORK\": filepath.Join(dir, \"nested\", \"go.work\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoWorkView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"independent module view\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.work\":  \"go 1.18\\nuse (\\n\\t./a\\n)\\n\", // not using b\n\t\t\t\t\"a/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":   \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{\n\t\t\t\t{GoWorkView, \".\", nil},\n\t\t\t\t{GoModView, \"b\", []string{\"GOWORK=off\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"multiple go.work\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.work\":    \"go 1.18\\nuse (\\n\\t./a\\n\\t./b\\n)\\n\",\n\t\t\t\t\"a/go.mod\":   \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":     \"package a\",\n\t\t\t\t\"b/go.work\":  \"go 1.18\\nuse (\\n\\t.\\n\\t./c\\n)\\n\",\n\t\t\t\t\"b/go.mod\":   \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":     \"package b\",\n\t\t\t\t\"b/c/go.mod\": \"module golang.org/c\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\", \"b/c/c.go\"},\n\t\t\t[]viewSummary{{GoWorkView, \".\", nil}, {GoWorkView, \"b\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"multiple go.work, c unused\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.work\":    \"go 1.18\\nuse (\\n\\t./a\\n\\t./b\\n)\\n\",\n\t\t\t\t\"a/go.mod\":   \"module golang.org/a\\ngo 1.18\\n\",\n\t\t\t\t\"a/a.go\":     \"package a\",\n\t\t\t\t\"b/go.work\":  \"go 1.18\\nuse (\\n\\t.\\n)\\n\",\n\t\t\t\t\"b/go.mod\":   \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":     \"package b\",\n\t\t\t\t\"b/c/go.mod\": \"module golang.org/c\\ngo 1.18\\n\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\"}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\", \"b/c/c.go\"},\n\t\t\t[]viewSummary{{GoWorkView, \".\", nil}, {GoModView, \"b/c\", []string{\"GOWORK=off\"}}},\n\t\t},\n\t\t{\n\t\t\t\"go.mod with nested replace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\":   \"module golang.org/a\\n require golang.org/b v1.2.3\\nreplace example.com/b => ./b\",\n\t\t\t\t\"a.go\":     \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\", options: includeReplaceInWorkspace}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoModView, \".\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"go.mod with parent replace, parent folder\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\":   \"module golang.org/a\",\n\t\t\t\t\"a.go\":     \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\nrequire golang.org/a v1.2.3\\nreplace golang.org/a => ../\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\", options: includeReplaceInWorkspace}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoModView, \".\", nil}, {GoModView, \"b\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"go.mod with multiple replace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\": `\nmodule golang.org/root\n\nrequire (\n\tgolang.org/a v1.2.3\n\tgolang.org/b v1.2.3\n\tgolang.org/c v1.2.3\n)\n\nreplace (\n\tgolang.org/b => ./b\n\tgolang.org/c => ./c\n\t// Note: d is not replaced\n)\n`,\n\t\t\t\t\"a.go\":     \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t\t\"c/go.mod\": \"module golang.org/c\\ngo 1.18\",\n\t\t\t\t\"c/c.go\":   \"package c\",\n\t\t\t\t\"d/go.mod\": \"module golang.org/d\\ngo 1.18\",\n\t\t\t\t\"d/d.go\":   \"package d\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \".\", options: includeReplaceInWorkspace}},\n\t\t\t[]string{\"b/b.go\", \"c/c.go\", \"d/d.go\"},\n\t\t\t[]viewSummary{{GoModView, \".\", nil}, {GoModView, \"d\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"go.mod with replace outside the workspace\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\":   \"module golang.org/a\\ngo 1.18\",\n\t\t\t\t\"a.go\":     \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\nrequire golang.org/a v1.2.3\\nreplace golang.org/a => ../\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{dir: \"b\"}},\n\t\t\t[]string{\"a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoModView, \"b\", nil}},\n\t\t},\n\t\t{\n\t\t\t\"go.mod with replace directive; workspace replace off\",\n\t\t\tmap[string]string{\n\t\t\t\t\"go.mod\":   \"module golang.org/a\\n require golang.org/b v1.2.3\\nreplace example.com/b => ./b\",\n\t\t\t\t\"a.go\":     \"package a\",\n\t\t\t\t\"b/go.mod\": \"module golang.org/b\\ngo 1.18\\n\",\n\t\t\t\t\"b/b.go\":   \"package b\",\n\t\t\t},\n\t\t\t[]folderSummary{{\n\t\t\t\tdir: \".\",\n\t\t\t\toptions: func(string) map[string]any {\n\t\t\t\t\treturn map[string]any{\n\t\t\t\t\t\t\"includeReplaceInWorkspace\": false,\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}},\n\t\t\t[]string{\"a/a.go\", \"b/b.go\"},\n\t\t\t[]viewSummary{{GoModView, \".\", nil}, {GoModView, \"b\", nil}},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tctx := context.Background()\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tdir := writeFiles(t, test.files)\n\t\t\trel := fake.RelativeTo(dir)\n\t\t\tfs := newMemoizedFS()\n\n\t\t\ttoURI := func(path string) protocol.DocumentURI {\n\t\t\t\treturn protocol.URIFromPath(rel.AbsPath(path))\n\t\t\t}\n\n\t\t\tvar folders []*Folder\n\t\t\tfor _, f := range test.folders {\n\t\t\t\topts := settings.DefaultOptions()\n\t\t\t\tif f.options != nil {\n\t\t\t\t\t_, errs := opts.Set(f.options(dir))\n\t\t\t\t\tfor _, err := range errs {\n\t\t\t\t\t\tt.Fatal(err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\turi := toURI(f.dir)\n\t\t\t\tenv, err := FetchGoEnv(ctx, uri, opts)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"FetchGoEnv failed: %v\", err)\n\t\t\t\t}\n\t\t\t\tt.Logf(\"FetchGoEnv(%q) = %+v\", uri, env)\n\t\t\t\tfolders = append(folders, &Folder{\n\t\t\t\t\tDir:     uri,\n\t\t\t\t\tName:    path.Base(f.dir),\n\t\t\t\t\tOptions: opts,\n\t\t\t\t\tEnv:     *env,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tvar openFiles []protocol.DocumentURI\n\t\t\tfor _, path := range test.open {\n\t\t\t\topenFiles = append(openFiles, toURI(path))\n\t\t\t}\n\n\t\t\tdefs, err := selectViewDefs(ctx, fs, folders, openFiles)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar got []viewSummary\n\t\t\tfor _, def := range defs {\n\t\t\t\tgot = append(got, viewSummary{\n\t\t\t\t\tType: def.Type(),\n\t\t\t\t\tRoot: rel.RelPath(def.root.Path()),\n\t\t\t\t\tEnv:  def.EnvOverlay(),\n\t\t\t\t})\n\t\t\t}\n\t\t\tif diff := cmp.Diff(test.want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"selectViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TODO(rfindley): this function could be meaningfully factored with the\n// various other test helpers of this nature.\nfunc writeFiles(t *testing.T, files map[string]string) string {\n\troot := t.TempDir()\n\n\t// This unfortunate step is required because gopls output\n\t// expands symbolic links in its input file names (arguably it\n\t// should not), and on macOS the temp dir is in /var -> private/var.\n\troot, err := filepath.EvalSymlinks(root)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor name, content := range files {\n\t\tfilename := filepath.Join(root, name)\n\t\tif err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(filename, []byte(content), 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\treturn root\n}\n"
  },
  {
    "path": "gopls/internal/cache/snapshot.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build/constraint\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/methodsets\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/testfuncs\"\n\t\"golang.org/x/tools/gopls/internal/cache/xrefs\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\tlabel1 \"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/constraints\"\n\t\"golang.org/x/tools/gopls/internal/util/immutable\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n\t\"golang.org/x/tools/gopls/internal/util/persistent\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/label\"\n\t\"golang.org/x/tools/internal/gocommand\"\n)\n\n// A Snapshot represents the current state for a given view.\n//\n// It is first and foremost an idempotent implementation of file.Source whose\n// ReadFile method returns consistent information about the existence and\n// content of each file throughout its lifetime.\n//\n// However, the snapshot also manages additional state (such as parsed files\n// and packages) that are derived from file content.\n//\n// Snapshots are responsible for bookkeeping and invalidation of this state,\n// implemented in Snapshot.clone.\ntype Snapshot struct {\n\t// sequenceID is the monotonically increasing ID of this snapshot within its View.\n\t//\n\t// Sequence IDs for Snapshots from different Views cannot be compared.\n\tsequenceID uint64\n\n\t// TODO(rfindley): the snapshot holding a reference to the view poses\n\t// lifecycle problems: a view may be shut down and waiting for work\n\t// associated with this snapshot to complete. While most accesses of the view\n\t// are benign (options or workspace information), this is not formalized and\n\t// it is wrong for the snapshot to use a shutdown view.\n\t//\n\t// Fix this by passing options and workspace information to the snapshot,\n\t// both of which should be immutable for the snapshot.\n\tview *View\n\n\tcancel        func()\n\tbackgroundCtx context.Context\n\n\tstore *memoize.Store // cache of handles shared by all snapshots\n\n\trefMu sync.Mutex\n\n\t// refcount holds the number of outstanding references to the current\n\t// Snapshot. When refcount is decremented to 0, the Snapshot maps are\n\t// destroyed and the done function is called.\n\t//\n\t// TODO(rfindley): use atomic.Int32 on Go 1.19+.\n\trefcount int\n\tdone     func() // for implementing Session.Shutdown\n\n\t// mu guards all of the maps in the snapshot, as well as the builtin URI and\n\t// initialized.\n\tmu sync.Mutex\n\n\t// initialized reports whether the snapshot has been initialized. Concurrent\n\t// initialization is guarded by the view.initializationSema. Each snapshot is\n\t// initialized at most once: concurrent initialization is guarded by\n\t// view.initializationSema.\n\tinitialized bool\n\n\t// initialErr holds the last error resulting from initialization. If\n\t// initialization fails, we only retry when the workspace modules change,\n\t// to avoid too many go/packages calls.\n\t// If initialized is false, initialErr still holds the error resulting from\n\t// the previous initialization.\n\t// TODO(rfindley): can we unify the lifecycle of initialized and initialErr.\n\tinitialErr *InitializationError\n\n\t// builtin is the location of builtin.go in GOROOT.\n\t//\n\t// TODO(rfindley): would it make more sense to eagerly parse builtin, and\n\t// instead store a *parsego.File here?\n\tbuiltin protocol.DocumentURI\n\n\t// meta holds loaded metadata.\n\t//\n\t// meta is guarded by mu, but the Graph itself is immutable.\n\t//\n\t// TODO(rfindley): in many places we hold mu while operating on meta, even\n\t// though we only need to hold mu while reading the pointer.\n\tmeta *metadata.Graph\n\n\t// files maps file URIs to their corresponding FileHandles.\n\t// It may invalidated when a file's content changes.\n\tfiles *fileMap\n\n\t// packages maps a packageKey to a *packageHandle.\n\t// It may be invalidated when a file's content changes.\n\t//\n\t// Invariants to preserve:\n\t//  - packages.Get(id).meta == meta.metadata[id] for all ids\n\t//  - if a package is in packages, then all of its dependencies should also\n\t//    be in packages, unless there is a missing import\n\tpackages *persistent.Map[PackageID, *packageHandle]\n\n\t// fullAnalysisKeys and factyAnalysisKeys hold memoized cache keys for\n\t// analysis packages. \"full\" refers to the cache key including all enabled\n\t// analyzers, whereas \"facty\" is the key including only the subset of enabled\n\t// analyzers that produce facts, such as is required for transitively\n\t// imported packages.\n\t//\n\t// These keys are memoized because they can be quite expensive to compute.\n\tfullAnalysisKeys  *persistent.Map[PackageID, file.Hash]\n\tfactyAnalysisKeys *persistent.Map[PackageID, file.Hash]\n\n\t// workspacePackages contains the workspace's packages, which are loaded\n\t// when the view is created. It does not contain intermediate test variants.\n\tworkspacePackages immutable.Map[PackageID, PackagePath]\n\n\t// shouldLoad tracks packages that need to be reloaded, mapping a PackageID\n\t// to the package paths that should be used to reload it\n\t//\n\t// When we try to load a package, we clear it from the shouldLoad map\n\t// regardless of whether the load succeeded, to prevent endless loads.\n\tshouldLoad *persistent.Map[PackageID, []PackagePath]\n\n\t// unloadableFiles keeps track of files that we've failed to load.\n\tunloadableFiles *persistent.Set[protocol.DocumentURI]\n\n\t// TODO(rfindley): rename the handles below to \"promises\". A promise is\n\t// different from a handle (we mutate the package handle.)\n\n\t// parseModHandles keeps track of any parseModHandles for the snapshot.\n\t// The handles need not refer to only the view's go.mod file.\n\tparseModHandles *persistent.Map[protocol.DocumentURI, *memoize.Promise] // *memoize.Promise[parseModResult]\n\n\t// parseWorkHandles keeps track of any parseWorkHandles for the snapshot.\n\t// The handles need not refer to only the view's go.work file.\n\tparseWorkHandles *persistent.Map[protocol.DocumentURI, *memoize.Promise] // *memoize.Promise[parseWorkResult]\n\n\t// Preserve go.mod-related handles to avoid garbage-collecting the results\n\t// of various calls to the go command. The handles need not refer to only\n\t// the view's go.mod file.\n\tmodTidyHandles *persistent.Map[protocol.DocumentURI, *memoize.Promise] // *memoize.Promise[modTidyResult]\n\tmodWhyHandles  *persistent.Map[protocol.DocumentURI, *memoize.Promise] // *memoize.Promise[modWhyResult]\n\tmodVulnHandles *persistent.Map[protocol.DocumentURI, *memoize.Promise] // *memoize.Promise[modVulnResult]\n\n\t// moduleUpgrades tracks known upgrades for module paths in each modfile.\n\t// Each modfile has a map of module name to upgrade version.\n\tmoduleUpgrades *persistent.Map[protocol.DocumentURI, map[string]string]\n\n\t// vulns maps each go.mod file's URI to its known vulnerabilities.\n\tvulns *persistent.Map[protocol.DocumentURI, *vulncheck.Result]\n\n\t// compilerOptDetails is the set of directories whose packages\n\t// and tests need compiler optimization details in the diagnostics.\n\tcompilerOptDetails map[protocol.DocumentURI]unit\n\n\t// Concurrent type checking:\n\t// typeCheckMu guards the ongoing type checking batch, and reference count of\n\t// ongoing type checking operations.\n\t// When the batch is no longer needed (batchRef=0), it is discarded.\n\ttypeCheckMu sync.Mutex\n\tbatchRef    int\n\tbatch       *typeCheckBatch\n}\n\nvar _ memoize.RefCounted = (*Snapshot)(nil) // snapshots are reference-counted\n\nfunc (s *Snapshot) awaitPromise(ctx context.Context, p *memoize.Promise) (any, error) {\n\treturn p.Get(ctx, s)\n}\n\n// Acquire prevents the snapshot from being destroyed until the returned\n// function is called.\n//\n// (s.Acquire().release() could instead be expressed as a pair of\n// method calls s.IncRef(); s.DecRef(). The latter has the advantage\n// that the DecRefs are fungible and don't require holding anything in\n// addition to the refcounted object s, but paradoxically that is also\n// an advantage of the current approach, which forces the caller to\n// consider the release function at every stage, making a reference\n// leak more obvious.)\nfunc (s *Snapshot) Acquire() func() {\n\ts.refMu.Lock()\n\tdefer s.refMu.Unlock()\n\tassert(s.refcount > 0, \"non-positive refs\")\n\ts.refcount++\n\n\treturn s.decref\n}\n\n// decref should only be referenced by Acquire, and by View when it frees its\n// reference to View.snapshot.\nfunc (s *Snapshot) decref() {\n\ts.refMu.Lock()\n\tdefer s.refMu.Unlock()\n\n\tassert(s.refcount > 0, \"non-positive refs\")\n\ts.refcount--\n\tif s.refcount == 0 {\n\t\ts.packages.Destroy()\n\t\ts.files.destroy()\n\t\ts.parseModHandles.Destroy()\n\t\ts.parseWorkHandles.Destroy()\n\t\ts.modTidyHandles.Destroy()\n\t\ts.modVulnHandles.Destroy()\n\t\ts.modWhyHandles.Destroy()\n\t\ts.unloadableFiles.Destroy()\n\t\ts.moduleUpgrades.Destroy()\n\t\ts.vulns.Destroy()\n\t\ts.done()\n\t}\n}\n\n// SequenceID is the sequence id of this snapshot within its containing\n// view.\n//\n// Relative to their view sequence ids are monotonically increasing, but this\n// does not hold globally: when new views are created their initial snapshot\n// has sequence ID 0.\nfunc (s *Snapshot) SequenceID() uint64 {\n\treturn s.sequenceID\n}\n\n// Labels returns a new slice of labels that should be used for events\n// related to a snapshot.\nfunc (s *Snapshot) Labels() []label.Label {\n\treturn []label.Label{\n\t\tlabel1.ViewID.Of(s.view.id),\n\t\tlabel1.Snapshot.Of(s.SequenceID()),\n\t\tlabel1.Directory.Of(s.Folder().Path()),\n\t}\n}\n\n// Folder returns the folder at the base of this snapshot.\nfunc (s *Snapshot) Folder() protocol.DocumentURI {\n\treturn s.view.folder.Dir\n}\n\n// View returns the View associated with this snapshot.\nfunc (s *Snapshot) View() *View {\n\treturn s.view\n}\n\n// FileKind returns the kind of a file.\n//\n// We can't reliably deduce the kind from the file name alone,\n// as some editors can be told to interpret a buffer as\n// language different from the file name heuristic, e.g. that\n// an .html file actually contains Go \"html/template\" syntax,\n// or even that a .go file contains Python.\nfunc (s *Snapshot) FileKind(fh file.Handle) file.Kind {\n\tif k := fileKind(fh); k != file.UnknownKind {\n\t\treturn k\n\t}\n\tfext := filepath.Ext(fh.URI().Path())\n\texts := s.Options().TemplateExtensions\n\tfor _, ext := range exts {\n\t\tif fext == ext || fext == \".\"+ext {\n\t\t\treturn file.Tmpl\n\t\t}\n\t}\n\n\t// and now what? This should never happen, but it does for cgo before go1.15\n\t//\n\t// TODO(rfindley): this doesn't look right. We should default to UnknownKind.\n\t// Also, I don't understand the comment above, though I'd guess before go1.15\n\t// we encountered cgo files without the .go extension.\n\treturn file.Go\n}\n\n// fileKind returns the default file kind for a file, before considering\n// template file extensions. See [Snapshot.FileKind].\nfunc fileKind(fh file.Handle) file.Kind {\n\t// The kind of an unsaved buffer comes from the\n\t// TextDocumentItem.LanguageID field in the didChange event,\n\t// not from the file name. They may differ.\n\tif o, ok := fh.(*overlay); ok {\n\t\tif o.kind != file.UnknownKind {\n\t\t\treturn o.kind\n\t\t}\n\t}\n\n\tfext := filepath.Ext(fh.URI().Path())\n\tswitch fext {\n\tcase \".go\":\n\t\treturn file.Go\n\tcase \".mod\":\n\t\treturn file.Mod\n\tcase \".sum\":\n\t\treturn file.Sum\n\tcase \".work\":\n\t\treturn file.Work\n\tcase \".s\":\n\t\treturn file.Asm\n\t}\n\treturn file.UnknownKind\n}\n\n// Options returns the options associated with this snapshot.\nfunc (s *Snapshot) Options() *settings.Options {\n\treturn s.view.folder.Options\n}\n\n// BackgroundContext returns a context used for all background processing\n// on behalf of this snapshot.\nfunc (s *Snapshot) BackgroundContext() context.Context {\n\treturn s.backgroundCtx\n}\n\n// Templates returns the .tmpl files.\nfunc (s *Snapshot) Templates() map[protocol.DocumentURI]file.Handle {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\ttmpls := map[protocol.DocumentURI]file.Handle{}\n\tfor k, fh := range s.files.all() {\n\t\tif s.FileKind(fh) == file.Tmpl {\n\t\t\ttmpls[k] = fh\n\t\t}\n\t}\n\treturn tmpls\n}\n\n// RunGoModUpdateCommands runs a series of `go` commands that updates the go.mod\n// and go.sum file for wd, and returns their updated contents.\n//\n// TODO(rfindley): the signature of RunGoModUpdateCommands is very confusing,\n// and is the only thing forcing the ModFlag and ModFile indirection.\n// Simplify it.\nfunc (s *Snapshot) RunGoModUpdateCommands(ctx context.Context, modURI protocol.DocumentURI, run func(invoke func(...string) (*bytes.Buffer, error)) error) ([]byte, []byte, error) {\n\ttempDir, cleanupModDir, err := TempModDir(ctx, s, modURI)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer cleanupModDir()\n\n\t// TODO(rfindley): we must use ModFlag and ModFile here (rather than simply\n\t// setting Args), because without knowing the verb, we can't know whether\n\t// ModFlag is appropriate. Refactor so that args can be set by the caller.\n\tinv, cleanupInvocation, err := s.GoCommandInvocation(NetworkOK, modURI.DirPath(), \"\", nil, \"GOWORK=off\")\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer cleanupInvocation()\n\n\tinv.ModFlag = \"mod\"\n\tinv.ModFile = filepath.Join(tempDir, \"go.mod\")\n\tinvoke := func(args ...string) (*bytes.Buffer, error) {\n\t\tinv.Verb = args[0]\n\t\tinv.Args = args[1:]\n\t\treturn s.view.gocmdRunner.Run(ctx, *inv)\n\t}\n\tif err := run(invoke); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tvar modBytes, sumBytes []byte\n\tmodBytes, err = os.ReadFile(filepath.Join(tempDir, \"go.mod\"))\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn nil, nil, err\n\t}\n\tsumBytes, err = os.ReadFile(filepath.Join(tempDir, \"go.sum\"))\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn nil, nil, err\n\t}\n\treturn modBytes, sumBytes, nil\n}\n\n// TempModDir creates a temporary directory with the contents of the provided\n// modURI, as well as its corresponding go.sum file, if it exists. On success,\n// it is the caller's responsibility to call the cleanup function to remove the\n// directory when it is no longer needed.\nfunc TempModDir(ctx context.Context, fs file.Source, modURI protocol.DocumentURI) (dir string, _ func(), rerr error) {\n\tdir, err := os.MkdirTemp(\"\", \"gopls-tempmod\")\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tcleanup := func() {\n\t\tif err := os.RemoveAll(dir); err != nil {\n\t\t\tevent.Error(ctx, \"cleaning temp dir\", err)\n\t\t}\n\t}\n\tdefer func() {\n\t\tif rerr != nil {\n\t\t\tcleanup()\n\t\t}\n\t}()\n\n\t// If go.mod exists, write it.\n\tmodFH, err := fs.ReadFile(ctx, modURI)\n\tif err != nil {\n\t\treturn \"\", nil, err // context cancelled\n\t}\n\tif data, err := modFH.Content(); err == nil {\n\t\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), data, 0666); err != nil {\n\t\t\treturn \"\", nil, err\n\t\t}\n\t}\n\n\t// If go.sum exists, write it.\n\tsumURI := protocol.DocumentURI(strings.TrimSuffix(string(modURI), \".mod\") + \".sum\")\n\tsumFH, err := fs.ReadFile(ctx, sumURI)\n\tif err != nil {\n\t\treturn \"\", nil, err // context cancelled\n\t}\n\tif data, err := sumFH.Content(); err == nil {\n\t\tif err := os.WriteFile(filepath.Join(dir, \"go.sum\"), data, 0666); err != nil {\n\t\t\treturn \"\", nil, err\n\t\t}\n\t}\n\n\treturn dir, cleanup, nil\n}\n\n// AllowNetwork determines whether Go commands are permitted to use the\n// network. (Controlled via GOPROXY=off.)\ntype AllowNetwork bool\n\nconst (\n\tNoNetwork AllowNetwork = false\n\tNetworkOK AllowNetwork = true\n)\n\n// GoCommandInvocation populates inv with configuration for running go commands\n// on the snapshot.\n//\n// On success, the caller must call the cleanup function exactly once\n// when the invocation is no longer needed.\n//\n// TODO(rfindley): although this function has been simplified significantly,\n// additional refactoring is still required: the responsibility for Env and\n// BuildFlags should be more clearly expressed in the API.\n//\n// If allowNetwork is NoNetwork, set GOPROXY=off.\nfunc (s *Snapshot) GoCommandInvocation(allowNetwork AllowNetwork, dir, verb string, args []string, env ...string) (_ *gocommand.Invocation, cleanup func(), _ error) {\n\tinv := &gocommand.Invocation{\n\t\tVerb:       verb,\n\t\tArgs:       args,\n\t\tWorkingDir: dir,\n\t\tEnv:        append(s.view.Env(), env...),\n\t\tBuildFlags: slices.Clone(s.Options().BuildFlags),\n\t}\n\tif !allowNetwork {\n\t\tinv.Env = append(inv.Env, \"GOPROXY=off\")\n\t}\n\n\t// Write overlay files for unsaved editor buffers.\n\toverlay, cleanup, err := gocommand.WriteOverlays(s.buildOverlays())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tinv.Overlay = overlay\n\treturn inv, cleanup, nil\n}\n\n// buildOverlays returns a new mapping from logical file name to\n// effective content, for each unsaved editor buffer, in the same form\n// as [packages.Cfg]'s Overlay field.\nfunc (s *Snapshot) buildOverlays() map[string][]byte {\n\toverlays := make(map[string][]byte)\n\tfor _, overlay := range s.Overlays() {\n\t\tif overlay.saved {\n\t\t\tcontinue\n\t\t}\n\t\t// TODO(rfindley): previously, there was a todo here to make sure we don't\n\t\t// send overlays outside of the current view. IMO we should instead make\n\t\t// sure this doesn't matter.\n\t\toverlays[overlay.URI().Path()] = overlay.content\n\t}\n\treturn overlays\n}\n\n// Overlays returns the set of overlays at this snapshot.\n//\n// Note that this may differ from the set of overlays on the server, if the\n// snapshot observed a historical state.\nfunc (s *Snapshot) Overlays() []*overlay {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\treturn s.files.getOverlays()\n}\n\n// Package data kinds, identifying various package data that may be stored in\n// the file cache.\nconst (\n\txrefsKind       = \"xrefs\"\n\tmethodSetsKind  = \"methodsets\"\n\ttestsKind       = \"tests\"\n\texportDataKind  = \"export\"\n\tdiagnosticsKind = \"diagnostics\"\n\ttyperefsKind    = \"typerefs\"\n\tsymbolsKind     = \"symbols\"\n)\n\n// PackageDiagnostics returns diagnostics for files contained in specified\n// packages.\n//\n// If these diagnostics cannot be loaded from cache, the requested packages\n// may be type-checked.\nfunc (s *Snapshot) PackageDiagnostics(ctx context.Context, ids ...PackageID) (map[protocol.DocumentURI][]*Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"cache.snapshot.PackageDiagnostics\")\n\tdefer done()\n\n\tvar mu sync.Mutex\n\tperFile := make(map[protocol.DocumentURI][]*Diagnostic)\n\tcollect := func(diags []*Diagnostic) {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\tfor _, diag := range diags {\n\t\t\tperFile[diag.URI] = append(perFile[diag.URI], diag)\n\t\t}\n\t}\n\tpre := func(_ int, ph *packageHandle) bool {\n\t\tdata, err := filecache.Get(diagnosticsKind, ph.key)\n\t\tif err == nil { // hit\n\t\t\tcollect(ph.loadDiagnostics)\n\t\t\tcollect(decodeDiagnostics(data))\n\t\t\treturn false\n\t\t} else if err != filecache.ErrNotFound {\n\t\t\tevent.Error(ctx, \"reading diagnostics from filecache\", err)\n\t\t}\n\t\treturn true\n\t}\n\tpost := func(_ int, pkg *Package) {\n\t\tcollect(pkg.loadDiagnostics)\n\t\tcollect(pkg.pkg.diagnostics)\n\t}\n\treturn perFile, s.forEachPackage(ctx, ids, pre, post)\n}\n\n// References returns cross-reference indexes for the specified packages.\n//\n// If these indexes cannot be loaded from cache, the requested packages may\n// be type-checked.\nfunc (s *Snapshot) References(ctx context.Context, ids ...PackageID) ([]xrefIndex, error) {\n\tctx, done := event.Start(ctx, \"cache.snapshot.References\")\n\tdefer done()\n\n\tindexes := make([]xrefIndex, len(ids))\n\tpre := func(i int, ph *packageHandle) bool {\n\t\tdata, err := filecache.Get(xrefsKind, ph.key)\n\t\tif err == nil { // hit\n\t\t\tindexes[i] = xrefIndex{mp: ph.mp, data: data}\n\t\t\treturn false\n\t\t} else if err != filecache.ErrNotFound {\n\t\t\tevent.Error(ctx, \"reading xrefs from filecache\", err)\n\t\t}\n\t\treturn true\n\t}\n\tpost := func(i int, pkg *Package) {\n\t\tindexes[i] = xrefIndex{mp: pkg.metadata, data: pkg.pkg.xrefs()}\n\t}\n\treturn indexes, s.forEachPackage(ctx, ids, pre, post)\n}\n\n// An xrefIndex is a helper for looking up references in a given package.\ntype xrefIndex struct {\n\tmp   *metadata.Package\n\tdata []byte\n}\n\nfunc (index xrefIndex) Lookup(targets map[PackagePath]map[objectpath.Path]struct{}) []protocol.Location {\n\treturn xrefs.Lookup(index.mp, index.data, targets)\n}\n\n// MethodSets returns method-set indexes for the specified packages.\n//\n// If these indexes cannot be loaded from cache, the requested packages may\n// be type-checked.\nfunc (s *Snapshot) MethodSets(ctx context.Context, ids ...PackageID) ([]*methodsets.Index, error) {\n\tctx, done := event.Start(ctx, \"cache.snapshot.MethodSets\")\n\tdefer done()\n\n\tindexes := make([]*methodsets.Index, len(ids))\n\tpre := func(i int, ph *packageHandle) bool {\n\t\tdata, err := filecache.Get(methodSetsKind, ph.key)\n\t\tif err == nil { // hit\n\t\t\tindexes[i] = methodsets.Decode(ph.mp.PkgPath, data)\n\t\t\treturn false\n\t\t} else if err != filecache.ErrNotFound {\n\t\t\tevent.Error(ctx, \"reading methodsets from filecache\", err)\n\t\t}\n\t\treturn true\n\t}\n\tpost := func(i int, pkg *Package) {\n\t\tindexes[i] = pkg.pkg.methodsets()\n\t}\n\treturn indexes, s.forEachPackage(ctx, ids, pre, post)\n}\n\n// Tests returns test-set indexes for the specified packages. There is a\n// one-to-one correspondence between ID and Index.\n//\n// If these indexes cannot be loaded from cache, the requested packages may be\n// type-checked.\nfunc (s *Snapshot) Tests(ctx context.Context, ids ...PackageID) ([]*testfuncs.Index, error) {\n\tctx, done := event.Start(ctx, \"cache.snapshot.Tests\")\n\tdefer done()\n\n\tindexes := make([]*testfuncs.Index, len(ids))\n\tpre := func(i int, ph *packageHandle) bool {\n\t\tdata, err := filecache.Get(testsKind, ph.key)\n\t\tif err == nil { // hit\n\t\t\tindexes[i] = testfuncs.Decode(data)\n\t\t\treturn false\n\t\t} else if err != filecache.ErrNotFound {\n\t\t\tevent.Error(ctx, \"reading tests from filecache\", err)\n\t\t}\n\t\treturn true\n\t}\n\tpost := func(i int, pkg *Package) {\n\t\tindexes[i] = pkg.pkg.tests()\n\t}\n\treturn indexes, s.forEachPackage(ctx, ids, pre, post)\n}\n\n// NarrowestMetadataForFile returns metadata for the narrowest package\n// (the one with the fewest files) that encloses the specified file.\n// The result may be a test variant, but never an intermediate test variant.\nfunc (snapshot *Snapshot) NarrowestMetadataForFile(ctx context.Context, uri protocol.DocumentURI) (*metadata.Package, error) {\n\tmps, err := snapshot.MetadataForFile(ctx, uri, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(mps) == 0 {\n\t\treturn nil, fmt.Errorf(\"no package metadata for file %s\", uri)\n\t}\n\treturn mps[0], nil\n}\n\n// MetadataForFile returns a new slice containing metadata for each\n// package containing the Go file identified by uri, ordered by the\n// number of CompiledGoFiles (i.e. \"narrowest\" to \"widest\" package),\n// and secondarily by IsIntermediateTestVariant (false < true).\n// The result may include tests and intermediate test variants of\n// importable packages. If removeIntermediateTestVariants is provided,\n// intermediate test variants will be excluded.\n// It returns an error if the context was cancelled.\nfunc (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI, removeIntermediateTestVariants bool) ([]*metadata.Package, error) {\n\tif s.view.typ == AdHocView {\n\t\t// As described in golang/go#57209, in ad-hoc workspaces (where we load ./\n\t\t// rather than ./...), preempting the directory load with file loads can\n\t\t// lead to an inconsistent outcome, where certain files are loaded with\n\t\t// command-line-arguments packages and others are loaded only in the ad-hoc\n\t\t// package. Therefore, ensure that the workspace is loaded before doing any\n\t\t// file loads.\n\t\tif err := s.awaitLoaded(ctx); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\ts.mu.Lock()\n\n\t// Start with the set of package associations derived from the last load.\n\tpkgs := s.meta.ForFile[uri]\n\n\tshouldLoad := false // whether any packages containing uri are marked 'shouldLoad'\n\tfor _, pkg := range pkgs {\n\t\tif p, _ := s.shouldLoad.Get(pkg.ID); len(p) > 0 {\n\t\t\tshouldLoad = true\n\t\t}\n\t}\n\n\t// Check if uri is known to be unloadable.\n\tunloadable := s.unloadableFiles.Contains(uri)\n\n\ts.mu.Unlock()\n\n\t// Reload if loading is likely to improve the package associations for uri:\n\t//  - uri is not contained in any valid packages\n\t//  - ...or one of the packages containing uri is marked 'shouldLoad'\n\t//  - ...but uri is not unloadable\n\tif (shouldLoad || len(pkgs) == 0) && !unloadable {\n\t\tscope := fileLoadScope(uri)\n\t\terr := s.load(ctx, NoNetwork, scope)\n\n\t\t// Return the context error here as the current operation is no longer\n\t\t// valid.\n\t\tif err != nil {\n\t\t\t// Guard against failed loads due to context cancellation. We don't want\n\t\t\t// to mark loads as completed if they failed due to context cancellation.\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\n\t\t\t// Don't return an error here, as we may still return stale IDs.\n\t\t\t// Furthermore, the result of MetadataForFile should be consistent upon\n\t\t\t// subsequent calls, even if the file is marked as unloadable.\n\t\t\tif !errors.Is(err, errNoPackages) {\n\t\t\t\tevent.Error(ctx, \"MetadataForFile\", err)\n\t\t\t}\n\t\t}\n\n\t\t// We must clear scopes after loading.\n\t\t//\n\t\t// TODO(rfindley): unlike reloadWorkspace, this is simply marking loaded\n\t\t// packages as loaded. We could do this from snapshot.load and avoid\n\t\t// raciness.\n\t\ts.clearShouldLoad(scope)\n\t}\n\n\t// Retrieve the metadata.\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\t// TODO(rfindley): is there any reason not to make the sorting below the\n\t// canonical sorting, so that we don't need to mutate this slice?\n\tmetas := slices.Clone(s.meta.ForFile[uri])\n\n\t// Metadata is only ever added by loading,\n\t// so if we get here and still have\n\t// no packages, uri is unloadable.\n\tif !unloadable && len(metas) == 0 {\n\t\ts.unloadableFiles.Add(uri)\n\t}\n\n\tif removeIntermediateTestVariants {\n\t\tmetadata.RemoveIntermediateTestVariants(&metas)\n\t}\n\n\t// Sort packages \"narrowest\" to \"widest\" (in practice:\n\t// non-tests before tests), and regular packages before\n\t// their intermediate test variants (which have the same\n\t// files but different imports).\n\tslices.SortFunc(metas, func(x, y *metadata.Package) int {\n\t\tif sign := cmp.Compare(len(x.CompiledGoFiles), len(y.CompiledGoFiles)); sign != 0 {\n\t\t\treturn sign\n\t\t}\n\t\t// Skip ITV-specific ordering if they were removed.\n\t\tif removeIntermediateTestVariants {\n\t\t\treturn 0\n\t\t}\n\t\treturn boolCompare(x.IsIntermediateTestVariant(), y.IsIntermediateTestVariant())\n\t})\n\n\treturn metas, nil\n}\n\n// btoi returns int(b) as proposed in #64825.\nfunc btoi(b bool) int {\n\tif b {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\n// boolCompare is a comparison function for booleans, returning -1 if x < y, 0\n// if x == y, and 1 if x > y, where false < true.\nfunc boolCompare(x, y bool) int {\n\treturn btoi(x) - btoi(y)\n}\n\n// ReverseDependencies returns a new mapping whose entries are\n// the ID and Metadata of each package in the workspace that\n// directly or transitively depend on the package denoted by id,\n// excluding id itself.\nfunc (s *Snapshot) ReverseDependencies(ctx context.Context, id PackageID, transitive bool) (map[PackageID]*metadata.Package, error) {\n\tif err := s.awaitLoaded(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\n\tmeta := s.MetadataGraph()\n\tvar rdeps map[PackageID]*metadata.Package\n\tif transitive {\n\t\trdeps = meta.ReverseReflexiveTransitiveClosure(id)\n\n\t\t// Remove the original package ID from the map.\n\t\t// (Callers all want irreflexivity but it's easier\n\t\t// to compute reflexively then subtract.)\n\t\tdelete(rdeps, id)\n\n\t} else {\n\t\t// direct reverse dependencies\n\t\trdeps = make(map[PackageID]*metadata.Package)\n\t\tfor _, rdep := range meta.ImportedBy[id] {\n\t\t\trdeps[rdep.ID] = rdep\n\t\t}\n\t}\n\n\treturn rdeps, nil\n}\n\n// See Session.FileWatchingGlobPatterns for a description of gopls' file\n// watching heuristic.\nfunc (s *Snapshot) fileWatchingGlobPatterns() map[protocol.RelativePattern]unit {\n\t// Always watch files that may change the view definition.\n\tpatterns := make(map[protocol.RelativePattern]unit)\n\n\t// If GOWORK is outside the folder, ensure we are watching it.\n\tif s.view.gowork != \"\" && !s.view.folder.Dir.Encloses(s.view.gowork) {\n\t\tworkPattern := protocol.RelativePattern{\n\t\t\tBaseURI: s.view.gowork.Dir(),\n\t\t\tPattern: path.Base(string(s.view.gowork)),\n\t\t}\n\t\tpatterns[workPattern] = unit{}\n\t}\n\n\tfor _, glob := range s.Options().WorkspaceFiles {\n\t\tpatterns[protocol.RelativePattern{Pattern: glob}] = unit{}\n\t}\n\n\tvar extensions strings.Builder\n\textensions.WriteString(\"go,mod,sum,work\")\n\tfor _, ext := range s.Options().TemplateExtensions {\n\t\textensions.WriteString(\",\")\n\t\textensions.WriteString(ext)\n\t}\n\twatchGoFiles := fmt.Sprintf(\"**/*.{%s}\", extensions.String())\n\n\tvar dirs []string\n\tif s.view.typ.usesModules() {\n\t\tif s.view.typ == GoWorkView {\n\t\t\tworkVendorDir := filepath.Join(s.view.gowork.DirPath(), \"vendor\")\n\t\t\tworkVendorURI := protocol.URIFromPath(workVendorDir)\n\t\t\tpatterns[protocol.RelativePattern{BaseURI: workVendorURI, Pattern: watchGoFiles}] = unit{}\n\t\t}\n\n\t\t// In module mode, watch directories containing active modules, and collect\n\t\t// these dirs for later filtering the set of known directories.\n\t\t//\n\t\t// The assumption is that the user is not actively editing non-workspace\n\t\t// modules, so don't pay the price of file watching.\n\t\tfor modFile := range s.view.workspaceModFiles {\n\t\t\tdirs = append(dirs, modFile.DirPath())\n\n\t\t\t// TODO(golang/go#64724): thoroughly test these patterns, particularly on\n\t\t\t// on Windows.\n\t\t\t//\n\t\t\t// Note that glob patterns should use '/' on Windows:\n\t\t\t// https://code.visualstudio.com/docs/editor/glob-patterns\n\t\t\tpatterns[protocol.RelativePattern{BaseURI: modFile.Dir(), Pattern: watchGoFiles}] = unit{}\n\t\t}\n\t} else {\n\t\t// In non-module modes (GOPATH or AdHoc), we just watch the workspace root.\n\t\tdirs = []string{s.view.root.Path()}\n\t\tpatterns[protocol.RelativePattern{Pattern: watchGoFiles}] = unit{}\n\t}\n\n\tif s.watchSubdirs() {\n\t\t// Some clients (e.g. VS Code) do not send notifications for changes to\n\t\t// directories that contain Go code (golang/go#42348). To handle this,\n\t\t// explicitly watch all of the directories in the workspace. We find them\n\t\t// by adding the directories of every file in the snapshot's workspace\n\t\t// directories. There may be thousands of patterns, each a single\n\t\t// directory.\n\t\t//\n\t\t// We compute this set by looking at files that we've previously observed.\n\t\t// This may miss changed to directories that we haven't observed, but that\n\t\t// shouldn't matter as there is nothing to invalidate (if a directory falls\n\t\t// in forest, etc).\n\t\t//\n\t\t// (A previous iteration created a single glob pattern holding a union of\n\t\t// all the directories, but this was found to cause VS Code to get stuck\n\t\t// for several minutes after a buffer was saved twice in a workspace that\n\t\t// had >8000 watched directories.)\n\t\t//\n\t\t// Some clients (notably coc.nvim, which uses watchman for globs) perform\n\t\t// poorly with a large list of individual directories.\n\t\ts.addKnownSubdirs(patterns, dirs)\n\t}\n\n\treturn patterns\n}\n\nfunc (s *Snapshot) addKnownSubdirs(patterns map[protocol.RelativePattern]unit, wsDirs []string) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tfor dir := range s.files.getDirs().All() {\n\t\tfor _, wsDir := range wsDirs {\n\t\t\tif pathutil.InDir(wsDir, dir) {\n\t\t\t\tpatterns[protocol.RelativePattern{Pattern: filepath.ToSlash(dir)}] = unit{}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// watchSubdirs reports whether gopls should request separate file watchers for\n// each relevant subdirectory. This is necessary only for clients (namely VS\n// Code) that do not send notifications for individual files in a directory\n// when the entire directory is deleted.\nfunc (s *Snapshot) watchSubdirs() bool {\n\tswitch p := s.Options().SubdirWatchPatterns; p {\n\tcase settings.SubdirWatchPatternsOn:\n\t\treturn true\n\tcase settings.SubdirWatchPatternsOff:\n\t\treturn false\n\tcase settings.SubdirWatchPatternsAuto:\n\t\t// See the documentation of InternalOptions.SubdirWatchPatterns for an\n\t\t// explanation of why VS Code gets a different default value here.\n\t\t//\n\t\t// Unfortunately, there is no authoritative list of client names, nor any\n\t\t// requirements that client names do not change. We should update the VS\n\t\t// Code extension to set a default value of \"subdirWatchPatterns\" to \"on\",\n\t\t// so that this workaround is only temporary.\n\t\tswitch s.Options().ClientInfo.Name {\n\t\tcase \"Visual Studio Code\", \"Visual Studio Code - Insiders\":\n\t\t\treturn true\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\tdefault:\n\t\tbug.Reportf(\"invalid subdirWatchPatterns: %q\", p)\n\t\treturn false\n\t}\n}\n\n// filesInDir returns all files observed by the snapshot that are contained in\n// a directory with the provided URI.\nfunc (s *Snapshot) filesInDir(uri protocol.DocumentURI) []protocol.DocumentURI {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tdir := uri.Path()\n\tif !s.files.getDirs().Contains(dir) {\n\t\treturn nil\n\t}\n\tvar files []protocol.DocumentURI\n\tfor uri := range s.files.all() {\n\t\tif pathutil.InDir(dir, uri.Path()) {\n\t\t\tfiles = append(files, uri)\n\t\t}\n\t}\n\treturn files\n}\n\n// WorkspaceMetadata returns a new, unordered slice containing\n// metadata for all ordinary and test packages (but not\n// intermediate test variants) in the workspace.\n//\n// The workspace is the set of modules typically defined by a\n// go.work file. It is not transitively closed: for example,\n// the standard library is not usually part of the workspace\n// even though every module in the workspace depends on it.\n//\n// Operations that must inspect all the dependencies of the\n// workspace packages should instead use AllMetadata.\nfunc (s *Snapshot) WorkspaceMetadata(ctx context.Context) ([]*metadata.Package, error) {\n\tif err := s.awaitLoaded(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tmeta := make([]*metadata.Package, 0, s.workspacePackages.Len())\n\tfor id := range s.workspacePackages.All() {\n\t\tmeta = append(meta, s.meta.Packages[id])\n\t}\n\treturn meta, nil\n}\n\n// WorkspacePackages returns the map of workspace package to package path.\n//\n// The set of workspace packages is updated after every load. A package is a\n// workspace package if and only if it is present in this map.\nfunc (s *Snapshot) WorkspacePackages() immutable.Map[PackageID, PackagePath] {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.workspacePackages\n}\n\n// IsWorkspacePackage reports whether the given package ID refers to a\n// workspace package for the Snapshot. It is equivalent to looking up the\n// package in [Snapshot.WorkspacePackages].\nfunc (s *Snapshot) IsWorkspacePackage(id PackageID) bool {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\t_, ok := s.workspacePackages.Value(id)\n\treturn ok\n}\n\n// AllMetadata returns a new unordered array of metadata for\n// all packages known to this snapshot, which includes the\n// packages of all workspace modules plus their transitive\n// import dependencies.\n//\n// It may also contain ad-hoc packages for standalone files.\n// It includes all test variants.\n//\n// TODO(rfindley): Replace usage of function this with s.LoadMetadataGraph().\nfunc (s *Snapshot) AllMetadata(ctx context.Context) ([]*metadata.Package, error) {\n\tg, err := s.LoadMetadataGraph(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn moremaps.ValueSlice(g.Packages), nil\n}\n\n// GoModForFile returns the URI of the go.mod file for the given URI.\n//\n// TODO(rfindley): clarify that this is only active modules. Or update to just\n// use findRootPattern.\nfunc (s *Snapshot) GoModForFile(uri protocol.DocumentURI) protocol.DocumentURI {\n\treturn moduleForURI(s.view.workspaceModFiles, uri)\n}\n\nfunc moduleForURI(modFiles map[protocol.DocumentURI]struct{}, uri protocol.DocumentURI) protocol.DocumentURI {\n\tvar match protocol.DocumentURI\n\tfor modURI := range modFiles {\n\t\tif !modURI.Dir().Encloses(uri) {\n\t\t\tcontinue\n\t\t}\n\t\tif len(modURI) > len(match) {\n\t\t\tmatch = modURI\n\t\t}\n\t}\n\treturn match\n}\n\n// Metadata returns the metadata for the specified package,\n// or nil if it was not found.\nfunc (s *Snapshot) Metadata(id PackageID) *metadata.Package {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.meta.Packages[id]\n}\n\n// clearShouldLoad clears package IDs that no longer need to be reloaded after\n// scopes has been loaded.\nfunc (s *Snapshot) clearShouldLoad(scopes ...loadScope) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tfor _, scope := range scopes {\n\t\tswitch scope := scope.(type) {\n\t\tcase packageLoadScope:\n\t\t\tscopePath := PackagePath(scope)\n\t\t\tvar toDelete []PackageID\n\t\t\tfor id, pkgPaths := range s.shouldLoad.All() {\n\t\t\t\tif slices.Contains(pkgPaths, scopePath) {\n\t\t\t\t\ttoDelete = append(toDelete, id)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor _, id := range toDelete {\n\t\t\t\ts.shouldLoad.Delete(id)\n\t\t\t}\n\t\tcase fileLoadScope:\n\t\t\turi := protocol.DocumentURI(scope)\n\t\t\tfor _, pkg := range s.meta.ForFile[uri] {\n\t\t\t\ts.shouldLoad.Delete(pkg.ID)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ReadFile returns a File for the given URI. If the file is unknown it is added\n// to the managed set.\n//\n// ReadFile succeeds even if the file does not exist. A non-nil error return\n// indicates some type of internal error, for example if ctx is cancelled.\nfunc (s *Snapshot) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\treturn lockedSnapshot{s}.ReadFile(ctx, uri)\n}\n\n// lockedSnapshot implements the file.Source interface, while holding s.mu.\n//\n// TODO(rfindley): This unfortunate type had been eliminated, but it had to be\n// restored to fix golang/go#65801. We should endeavor to remove it again.\ntype lockedSnapshot struct {\n\ts *Snapshot\n}\n\nfunc (s lockedSnapshot) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) {\n\tfh, ok := s.s.files.get(uri)\n\tif !ok {\n\t\tvar err error\n\t\tfh, err = s.s.view.fs.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ts.s.files.set(uri, fh)\n\t}\n\treturn fh, nil\n}\n\n// preloadFiles delegates to the view FileSource to read the requested uris in\n// parallel, without holding the snapshot lock.\nfunc (s *Snapshot) preloadFiles(ctx context.Context, uris []protocol.DocumentURI) {\n\tfiles := make([]file.Handle, len(uris))\n\tvar wg sync.WaitGroup\n\tiolimit := make(chan struct{}, 20) // I/O concurrency limiting semaphore\n\tfor i, uri := range uris {\n\t\twg.Add(1)\n\t\tiolimit <- struct{}{}\n\t\tgo func(i int, uri protocol.DocumentURI) {\n\t\t\tdefer wg.Done()\n\t\t\tfh, err := s.view.fs.ReadFile(ctx, uri)\n\t\t\t<-iolimit\n\t\t\tif err != nil && ctx.Err() == nil {\n\t\t\t\tevent.Error(ctx, fmt.Sprintf(\"reading %s\", uri), err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfiles[i] = fh\n\t\t}(i, uri)\n\t}\n\twg.Wait()\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tfor i, fh := range files {\n\t\tif fh == nil {\n\t\t\tcontinue // error logged above\n\t\t}\n\t\turi := uris[i]\n\t\tif _, ok := s.files.get(uri); !ok {\n\t\t\ts.files.set(uri, fh)\n\t\t}\n\t}\n}\n\n// IsOpen returns whether the editor currently has a file open.\nfunc (s *Snapshot) IsOpen(uri protocol.DocumentURI) bool {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tfh, _ := s.files.get(uri)\n\t_, open := fh.(*overlay)\n\treturn open\n}\n\n// MetadataGraph returns the current metadata graph for the Snapshot.\nfunc (s *Snapshot) MetadataGraph() *metadata.Graph {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.meta\n}\n\n// LoadMetadataGraph is like [Snapshot.MetadataGraph], but awaits snapshot reloading.\nfunc (s *Snapshot) LoadMetadataGraph(ctx context.Context) (*metadata.Graph, error) {\n\tif err := s.awaitLoaded(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\treturn s.MetadataGraph(), nil\n}\n\n// InitializationError returns the last error from initialization.\nfunc (s *Snapshot) InitializationError() *InitializationError {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.initialErr\n}\n\n// awaitLoaded awaits initialization and package reloading, and returns\n// ctx.Err().\nfunc (s *Snapshot) awaitLoaded(ctx context.Context) error {\n\t// Do not return results until the snapshot's view has been initialized.\n\ts.AwaitInitialized(ctx)\n\ts.reloadWorkspace(ctx)\n\treturn ctx.Err()\n}\n\n// AwaitInitialized waits until the snapshot's view is initialized.\nfunc (s *Snapshot) AwaitInitialized(ctx context.Context) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn\n\tcase <-s.view.initialWorkspaceLoad:\n\t}\n\t// We typically prefer to run something as intensive as the IWL without\n\t// blocking. I'm not sure if there is a way to do that here.\n\ts.initialize(ctx, false)\n}\n\n// reloadWorkspace reloads the metadata for all invalidated workspace packages.\nfunc (s *Snapshot) reloadWorkspace(ctx context.Context) {\n\tif ctx.Err() != nil {\n\t\treturn\n\t}\n\n\tvar scopes []loadScope\n\tvar seen map[PackagePath]bool\n\ts.mu.Lock()\n\tfor _, pkgPaths := range s.shouldLoad.All() {\n\t\tfor _, pkgPath := range pkgPaths {\n\t\t\tif seen == nil {\n\t\t\t\tseen = make(map[PackagePath]bool)\n\t\t\t}\n\t\t\tif seen[pkgPath] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[pkgPath] = true\n\t\t\tscopes = append(scopes, packageLoadScope(pkgPath))\n\t\t}\n\t}\n\ts.mu.Unlock()\n\n\tif len(scopes) == 0 {\n\t\treturn\n\t}\n\n\t// For an ad-hoc view, we cannot reload by package path. Just reload the view.\n\tif s.view.typ == AdHocView {\n\t\tscopes = []loadScope{viewLoadScope{}}\n\t}\n\n\terr := s.load(ctx, NoNetwork, scopes...)\n\n\t// Unless the context was canceled, set \"shouldLoad\" to false for all\n\t// of the metadata we attempted to load.\n\tif !errors.Is(err, context.Canceled) {\n\t\ts.clearShouldLoad(scopes...)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"reloading workspace\", err, s.Labels()...)\n\t\t}\n\t}\n}\n\nfunc (s *Snapshot) orphanedFileDiagnostics(ctx context.Context, overlays []*overlay) ([]*Diagnostic, error) {\n\tif err := s.awaitLoaded(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar diagnostics []*Diagnostic\n\tvar orphaned []*overlay\nsearchOverlays:\n\tfor _, o := range overlays {\n\t\turi := o.URI()\n\t\tif s.IsBuiltin(uri) || s.FileKind(o) != file.Go {\n\t\t\tcontinue\n\t\t}\n\t\tmps, err := s.MetadataForFile(ctx, uri, true)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, mp := range mps {\n\t\t\tif !metadata.IsCommandLineArguments(mp.ID) || mp.Standalone {\n\t\t\t\tcontinue searchOverlays\n\t\t\t}\n\t\t}\n\n\t\t// With zero-config gopls (golang/go#57979), orphaned file diagnostics\n\t\t// include diagnostics for orphaned files -- not just diagnostics relating\n\t\t// to the reason the files are opened.\n\t\t//\n\t\t// This is because orphaned files are never considered part of a workspace\n\t\t// package: if they are loaded by a view, that view is arbitrary, and they\n\t\t// may be loaded by multiple views. If they were to be diagnosed by\n\t\t// multiple views, their diagnostics may become inconsistent.\n\t\tif len(mps) > 0 {\n\t\t\tdiags, err := s.PackageDiagnostics(ctx, mps[0].ID)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdiagnostics = append(diagnostics, diags[uri]...)\n\t\t}\n\t\torphaned = append(orphaned, o)\n\t}\n\n\tif len(orphaned) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tloadedModFiles := make(map[protocol.DocumentURI]struct{}) // all mod files, including dependencies\n\tignoredFiles := make(map[protocol.DocumentURI]bool)       // files reported in packages.Package.IgnoredFiles\n\n\tg := s.MetadataGraph()\n\tfor _, meta := range g.Packages {\n\t\tif meta.Module != nil && meta.Module.GoMod != \"\" {\n\t\t\tgomod := protocol.URIFromPath(meta.Module.GoMod)\n\t\t\tloadedModFiles[gomod] = struct{}{}\n\t\t}\n\t\tfor _, ignored := range meta.IgnoredFiles {\n\t\t\tignoredFiles[ignored] = true\n\t\t}\n\t}\n\n\tinitialErr := s.InitializationError()\n\n\tfor _, fh := range orphaned {\n\t\tpgf, rng, ok := orphanedFileDiagnosticRange(ctx, s.view.parseCache, fh)\n\t\tif !ok {\n\t\t\tcontinue // e.g. cancellation or parse error\n\t\t}\n\n\t\tvar (\n\t\t\tmsg            string         // if non-empty, report a diagnostic with this message\n\t\t\tsuggestedFixes []SuggestedFix // associated fixes, if any\n\t\t)\n\t\tif initialErr != nil {\n\t\t\tmsg = fmt.Sprintf(\"initialization failed: %v\", initialErr.MainError)\n\t\t} else if goMod, err := findRootPattern(ctx, fh.URI().Dir(), \"go.mod\", file.Source(s)); err == nil && goMod != \"\" {\n\t\t\t// Check if the file's module should be loadable by considering both\n\t\t\t// loaded modules and workspace modules. The former covers cases where\n\t\t\t// the file is outside of a workspace folder. The latter covers cases\n\t\t\t// where the file is inside a workspace module, but perhaps no packages\n\t\t\t// were loaded for that module.\n\t\t\t_, loadedMod := loadedModFiles[goMod]\n\t\t\t_, workspaceMod := s.view.workspaceModFiles[goMod]\n\t\t\t// If we have a relevant go.mod file, check whether the file is orphaned\n\t\t\t// due to its go.mod file being inactive. We could also offer a\n\t\t\t// prescriptive diagnostic in the case that there is no go.mod file, but\n\t\t\t// it is harder to be precise in that case, and less important.\n\t\t\tif !(loadedMod || workspaceMod) {\n\t\t\t\tmodDir := goMod.DirPath()\n\t\t\t\tviewDir := s.view.folder.Dir.Path()\n\n\t\t\t\t// When the module is underneath the view dir, we offer\n\t\t\t\t// \"use all modules\" quick-fixes.\n\t\t\t\tinDir := pathutil.InDir(viewDir, modDir)\n\n\t\t\t\tif rel, err := filepath.Rel(viewDir, modDir); err == nil {\n\t\t\t\t\tmodDir = rel\n\t\t\t\t}\n\n\t\t\t\tvar fix string\n\t\t\t\tif s.view.folder.Env.GoVersion >= 18 {\n\t\t\t\t\tif s.view.gowork != \"\" {\n\t\t\t\t\t\tfix = fmt.Sprintf(\"To fix this problem, you can add this module to your go.work file (%s)\", s.view.gowork)\n\n\t\t\t\t\t\tcmd := command.NewRunGoWorkCommandCommand(\"Run `go work use`\", command.RunGoWorkArgs{\n\t\t\t\t\t\t\tViewID: s.view.ID(),\n\t\t\t\t\t\t\tArgs:   []string{\"use\", modDir},\n\t\t\t\t\t\t})\n\t\t\t\t\t\tsuggestedFixes = append(suggestedFixes, SuggestedFix{\n\t\t\t\t\t\t\tTitle:      \"Use this module in your go.work file\",\n\t\t\t\t\t\t\tCommand:    cmd,\n\t\t\t\t\t\t\tActionKind: protocol.QuickFix,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif inDir {\n\t\t\t\t\t\t\tcmd := command.NewRunGoWorkCommandCommand(\"Run `go work use -r`\", command.RunGoWorkArgs{\n\t\t\t\t\t\t\t\tViewID: s.view.ID(),\n\t\t\t\t\t\t\t\tArgs:   []string{\"use\", \"-r\", \".\"},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tsuggestedFixes = append(suggestedFixes, SuggestedFix{\n\t\t\t\t\t\t\t\tTitle:      \"Use all modules in your workspace\",\n\t\t\t\t\t\t\t\tCommand:    cmd,\n\t\t\t\t\t\t\t\tActionKind: protocol.QuickFix,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfix = \"To fix this problem, you can add a go.work file that uses this directory.\"\n\n\t\t\t\t\t\tcmd := command.NewRunGoWorkCommandCommand(\"Run `go work init && go work use`\", command.RunGoWorkArgs{\n\t\t\t\t\t\t\tViewID:    s.view.ID(),\n\t\t\t\t\t\t\tInitFirst: true,\n\t\t\t\t\t\t\tArgs:      []string{\"use\", modDir},\n\t\t\t\t\t\t})\n\t\t\t\t\t\tsuggestedFixes = []SuggestedFix{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTitle:      \"Add a go.work file using this module\",\n\t\t\t\t\t\t\t\tCommand:    cmd,\n\t\t\t\t\t\t\t\tActionKind: protocol.QuickFix,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif inDir {\n\t\t\t\t\t\t\tcmd := command.NewRunGoWorkCommandCommand(\"Run `go work init && go work use -r`\", command.RunGoWorkArgs{\n\t\t\t\t\t\t\t\tViewID:    s.view.ID(),\n\t\t\t\t\t\t\t\tInitFirst: true,\n\t\t\t\t\t\t\t\tArgs:      []string{\"use\", \"-r\", \".\"},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tsuggestedFixes = append(suggestedFixes, SuggestedFix{\n\t\t\t\t\t\t\t\tTitle:      \"Add a go.work file using all modules in your workspace\",\n\t\t\t\t\t\t\t\tCommand:    cmd,\n\t\t\t\t\t\t\t\tActionKind: protocol.QuickFix,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfix = `To work with multiple modules simultaneously, please upgrade to Go 1.18 or\nlater, reinstall gopls, and use a go.work file.`\n\t\t\t\t}\n\n\t\t\t\tmsg = fmt.Sprintf(`This file is within module %q, which is not included in your workspace.\n%s\nSee the documentation for more information on setting up your workspace:\nhttps://github.com/golang/tools/blob/master/gopls/doc/workspace.md.`, modDir, fix)\n\t\t\t}\n\t\t}\n\n\t\tif msg == \"\" {\n\t\t\tif ignoredFiles[fh.URI()] {\n\t\t\t\t// TODO(rfindley): use the constraint package to check if the file\n\t\t\t\t// _actually_ satisfies the current build context.\n\t\t\t\thasConstraint := false\n\t\t\t\twalkConstraints(pgf.File, func(constraint.Expr) bool {\n\t\t\t\t\thasConstraint = true\n\t\t\t\t\treturn false\n\t\t\t\t})\n\t\t\t\tvar fix string\n\t\t\t\tif hasConstraint {\n\t\t\t\t\tfix = `This file may be excluded due to its build tags; try adding \"-tags=<build tag>\" to your gopls \"buildFlags\" configuration\nSee the documentation for more information on working with build tags:\nhttps://github.com/golang/tools/blob/master/gopls/doc/settings.md#buildflags.`\n\t\t\t\t} else if strings.Contains(fh.URI().Base(), \"_\") {\n\t\t\t\t\tfix = `This file may be excluded due to its GOOS/GOARCH, or other build constraints.`\n\t\t\t\t} else {\n\t\t\t\t\tfix = `This file is ignored by your gopls build.` // we don't know why\n\t\t\t\t}\n\t\t\t\tmsg = fmt.Sprintf(\"No packages found for open file %s.\\n%s\", fh.URI().Path(), fix)\n\t\t\t} else {\n\t\t\t\t// Fall back: we're not sure why the file is orphaned.\n\t\t\t\t// TODO(rfindley): we could do better here, diagnosing the lack of a\n\t\t\t\t// go.mod file and malformed file names (see the perc%ent marker test).\n\t\t\t\tmsg = fmt.Sprintf(\"No packages found for open file %s.\", fh.URI().Path())\n\t\t\t}\n\t\t}\n\n\t\tif msg != \"\" {\n\t\t\td := &Diagnostic{\n\t\t\t\tURI:            fh.URI(),\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityWarning,\n\t\t\t\tSource:         ListError,\n\t\t\t\tMessage:        msg,\n\t\t\t\tSuggestedFixes: suggestedFixes,\n\t\t\t}\n\t\t\tif ok := bundleLazyFixes(d); !ok {\n\t\t\t\tbug.Reportf(\"failed to bundle quick fixes for %v\", d)\n\t\t\t}\n\t\t\t// Only report diagnostics if we detect an actual exclusion.\n\t\t\tdiagnostics = append(diagnostics, d)\n\t\t}\n\t}\n\treturn diagnostics, nil\n}\n\n// orphanedFileDiagnosticRange returns the position to use for orphaned file diagnostics.\n// We only warn about an orphaned file if it is well-formed enough to actually\n// be part of a package. Otherwise, we need more information.\nfunc orphanedFileDiagnosticRange(ctx context.Context, cache *parseCache, fh file.Handle) (*parsego.File, protocol.Range, bool) {\n\tpgfs, err := cache.parseFiles(ctx, token.NewFileSet(), parsego.Header, false, fh)\n\tif err != nil {\n\t\treturn nil, protocol.Range{}, false\n\t}\n\tpgf := pgfs[0]\n\tname := pgf.File.Name\n\tif !name.Pos().IsValid() {\n\t\treturn nil, protocol.Range{}, false\n\t}\n\trng, err := pgf.PosRange(name.Pos(), name.End())\n\tif err != nil {\n\t\treturn nil, protocol.Range{}, false\n\t}\n\treturn pgf, rng, true\n}\n\n// TODO(golang/go#53756): this function needs to consider more than just the\n// absolute URI, for example:\n//   - the position of /vendor/ with respect to the relevant module root\n//   - whether or not go.work is in use (as vendoring isn't supported in workspace mode)\n//\n// Most likely, each call site of inVendor needs to be reconsidered to\n// understand and correctly implement the desired behavior.\nfunc inVendor(uri protocol.DocumentURI) bool {\n\t_, after, found := strings.Cut(string(uri), \"/vendor/\")\n\t// Only subdirectories of /vendor/ are considered vendored\n\t// (/vendor/a/foo.go is vendored, /vendor/foo.go is not).\n\treturn found && strings.Contains(after, \"/\")\n}\n\n// clone copies state from the receiver into a new Snapshot, applying the given\n// state changes.\n//\n// The caller of clone must call Snapshot.decref on the returned\n// snapshot when they are finished using it.\n//\n// The resulting bool reports whether the change invalidates any derived\n// diagnostics for the snapshot, for example because it invalidates Packages or\n// parsed go.mod files. This is used to mark a view as needing diagnosis in the\n// server.\n//\n// TODO(rfindley): long term, it may be better to move responsibility for\n// diagnostics into the Snapshot (e.g. a Snapshot.Diagnostics method), at which\n// point the Snapshot could be responsible for tracking and forwarding a\n// 'viewsToDiagnose' field. As is, this field is instead externalized in the\n// server.viewsToDiagnose map. Moving it to the snapshot would entirely\n// eliminate any 'relevance' heuristics from Session.DidModifyFiles, but would\n// also require more strictness about diagnostic dependencies. For example,\n// template.Diagnostics currently re-parses every time: there is no Snapshot\n// data responsible for providing these diagnostics.\nfunc (s *Snapshot) clone(ctx, bgCtx context.Context, changed StateChange, done func()) (*Snapshot, bool) {\n\tchangedFiles := changed.Files\n\tctx, stop := event.Start(ctx, \"cache.snapshot.clone\")\n\tdefer stop()\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\t// TODO(rfindley): reorganize this function to make the derivation of\n\t// needsDiagnosis clearer.\n\tneedsDiagnosis := len(changed.CompilerOptDetails) > 0 || len(changed.ModuleUpgrades) > 0 || len(changed.Vulns) > 0\n\n\tbgCtx, cancel := context.WithCancel(bgCtx)\n\tresult := &Snapshot{\n\t\tsequenceID:        s.sequenceID + 1,\n\t\tstore:             s.store,\n\t\trefcount:          1, // Snapshots are born referenced.\n\t\tdone:              done,\n\t\tview:              s.view,\n\t\tbackgroundCtx:     bgCtx,\n\t\tcancel:            cancel,\n\t\tbuiltin:           s.builtin,\n\t\tinitialized:       s.initialized,\n\t\tinitialErr:        s.initialErr,\n\t\tpackages:          s.packages.Clone(),\n\t\tfullAnalysisKeys:  s.fullAnalysisKeys.Clone(),\n\t\tfactyAnalysisKeys: s.factyAnalysisKeys.Clone(),\n\t\tfiles:             s.files.clone(changedFiles),\n\t\tworkspacePackages: s.workspacePackages,\n\t\tshouldLoad:        s.shouldLoad.Clone(),      // not cloneWithout: shouldLoad is cleared on loads\n\t\tunloadableFiles:   s.unloadableFiles.Clone(), // not cloneWithout: typing in a file doesn't necessarily make it loadable\n\t\tparseModHandles:   cloneWithout(s.parseModHandles, changedFiles, &needsDiagnosis),\n\t\tparseWorkHandles:  cloneWithout(s.parseWorkHandles, changedFiles, &needsDiagnosis),\n\t\tmodTidyHandles:    cloneWithout(s.modTidyHandles, changedFiles, &needsDiagnosis),\n\t\tmodWhyHandles:     cloneWithout(s.modWhyHandles, changedFiles, &needsDiagnosis),\n\t\tmodVulnHandles:    cloneWithout(s.modVulnHandles, changedFiles, &needsDiagnosis),\n\t\tmoduleUpgrades:    cloneWith(s.moduleUpgrades, changed.ModuleUpgrades),\n\t\tvulns:             cloneWith(s.vulns, changed.Vulns),\n\t}\n\n\t// Compute the new set of packages for which we want compiler\n\t// optimization details, after applying changed.CompilerOptDetails.\n\tif len(s.compilerOptDetails) > 0 || len(changed.CompilerOptDetails) > 0 {\n\t\tnewCompilerOptDetails := make(map[protocol.DocumentURI]unit)\n\t\tfor dir := range s.compilerOptDetails {\n\t\t\tif _, ok := changed.CompilerOptDetails[dir]; !ok {\n\t\t\t\tnewCompilerOptDetails[dir] = unit{} // no change\n\t\t\t}\n\t\t}\n\t\tfor dir, want := range changed.CompilerOptDetails {\n\t\t\tif want {\n\t\t\t\tnewCompilerOptDetails[dir] = unit{}\n\t\t\t}\n\t\t}\n\t\tif len(newCompilerOptDetails) > 0 {\n\t\t\tresult.compilerOptDetails = newCompilerOptDetails\n\t\t}\n\t}\n\n\treinit := false\n\tfor _, mod := range changed.Modifications {\n\t\t// Changes to vendor tree may require reinitialization,\n\t\t// either because of an initialization error\n\t\t// (e.g. \"inconsistent vendoring detected\"), or because\n\t\t// one or more modules may have moved into or out of the\n\t\t// vendor tree after 'go mod vendor' or 'rm -fr vendor/'.\n\t\t//\n\t\t// In this case, we consider the actual modification to see if was a creation\n\t\t// or deletion.\n\t\t//\n\t\t// TODO(rfindley): revisit the location of this check.\n\t\tif inVendor(mod.URI) && (mod.Action == file.Create || mod.Action == file.Delete) ||\n\t\t\tstrings.HasSuffix(string(mod.URI), \"/vendor/modules.txt\") {\n\n\t\t\treinit = true\n\t\t\tbreak\n\t\t}\n\n\t\t// Changes to workspace files, as a rule of thumb, should require reinitialization. Since their behavior\n\t\t// is generally user-defined, we want to do something sensible by re-triggering a query to the active GOPACKAGESDRIVER,\n\t\t// and reloading the state of the workspace.\n\t\tif isWorkspaceFile(mod.URI, s.view.folder.Options.WorkspaceFiles) && (mod.Action == file.Save || mod.OnDisk) {\n\t\t\treinit = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Collect observed file handles for changed URIs from the old snapshot, if\n\t// they exist. Importantly, we don't call ReadFile here: consider the case\n\t// where a file is added on disk; we don't want to read the newly added file\n\t// into the old snapshot, as that will break our change detection below.\n\t//\n\t// TODO(rfindley): it may be more accurate to rely on the modification type\n\t// here, similarly to what we do for vendored files above. If we happened not\n\t// to have read a file in the previous snapshot, that's not the same as it\n\t// actually being created.\n\toldFiles := make(map[protocol.DocumentURI]file.Handle)\n\tfor uri := range changedFiles {\n\t\tif fh, ok := s.files.get(uri); ok {\n\t\t\toldFiles[uri] = fh\n\t\t}\n\t}\n\t// changedOnDisk determines if the new file handle may have changed on disk.\n\t// It over-approximates, returning true if the new file is saved and either\n\t// the old file wasn't saved, or the on-disk contents changed.\n\t//\n\t// oldFH may be nil.\n\tchangedOnDisk := func(oldFH, newFH file.Handle) bool {\n\t\tif !newFH.SameContentsOnDisk() {\n\t\t\treturn false\n\t\t}\n\t\tif oe, ne := (oldFH != nil && fileExists(oldFH)), fileExists(newFH); !oe || !ne {\n\t\t\treturn oe != ne\n\t\t}\n\t\treturn !oldFH.SameContentsOnDisk() || oldFH.Identity() != newFH.Identity()\n\t}\n\n\t// Reinitialize if any workspace mod file has changed on disk.\n\tfor uri, newFH := range changedFiles {\n\t\tif _, ok := result.view.workspaceModFiles[uri]; ok && changedOnDisk(oldFiles[uri], newFH) {\n\t\t\treinit = true\n\t\t}\n\t}\n\n\t// Finally, process sumfile changes that may affect loading.\n\tfor uri, newFH := range changedFiles {\n\t\tif !changedOnDisk(oldFiles[uri], newFH) {\n\t\t\tcontinue // like with go.mod files, we only reinit when things change on disk\n\t\t}\n\t\tdir, base := filepath.Split(uri.Path())\n\t\tif base == \"go.work.sum\" && s.view.typ == GoWorkView && dir == s.view.gowork.DirPath() {\n\t\t\treinit = true\n\t\t}\n\t\tif base == \"go.sum\" {\n\t\t\tmodURI := protocol.URIFromPath(filepath.Join(dir, \"go.mod\"))\n\t\t\tif _, active := result.view.workspaceModFiles[modURI]; active {\n\t\t\t\treinit = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// The snapshot should be initialized if either s was uninitialized, or we've\n\t// detected a change that triggers reinitialization.\n\tif reinit {\n\t\tresult.initialized = false\n\t\tneedsDiagnosis = true\n\t}\n\n\t// directIDs keeps track of package IDs that have directly changed.\n\t// Note: this is not a set, it's a map from id to invalidateMetadata.\n\tdirectIDs := map[PackageID]bool{}\n\n\t// Invalidate all package metadata if the workspace module has changed.\n\tif reinit {\n\t\tfor k := range s.meta.Packages {\n\t\t\t// TODO(rfindley): this seems brittle; can we just start over?\n\t\t\tdirectIDs[k] = true\n\t\t}\n\t}\n\n\t// Compute invalidations based on file changes.\n\tanyImportDeleted := false      // import deletions can resolve cycles\n\tanyFileOpenedOrClosed := false // opened files affect workspace packages\n\tanyPkgFileChanged := false     // adding a file to a package can resolve missing dependencies\n\n\tfor uri, newFH := range changedFiles {\n\t\t// The original FileHandle for this URI is cached on the snapshot.\n\t\toldFH := oldFiles[uri] // may be nil\n\t\t_, oldOpen := oldFH.(*overlay)\n\t\t_, newOpen := newFH.(*overlay)\n\n\t\t// TODO(rfindley): consolidate with 'metadataChanges' logic below, which\n\t\t// also considers existential changes.\n\t\tanyFileOpenedOrClosed = anyFileOpenedOrClosed || (oldOpen != newOpen)\n\t\tanyPkgFileChanged = anyPkgFileChanged || (oldFH == nil || !fileExists(oldFH)) && fileExists(newFH)\n\n\t\t// If uri is a Go file, check if it has changed in a way that would\n\t\t// invalidate metadata. Note that we can't use s.view.FileKind here,\n\t\t// because the file type that matters is not what the *client* tells us,\n\t\t// but what the Go command sees.\n\t\tvar invalidateMetadata, pkgFileChanged, importDeleted bool\n\t\tif strings.HasSuffix(uri.Path(), \".go\") {\n\t\t\tinvalidateMetadata, pkgFileChanged, importDeleted = metadataChanges(ctx, s, oldFH, newFH)\n\t\t}\n\t\tif invalidateMetadata {\n\t\t\t// If this is a metadata-affecting change, perhaps a reload will succeed.\n\t\t\tresult.unloadableFiles.Remove(uri)\n\t\t\tneedsDiagnosis = true\n\t\t}\n\n\t\tinvalidateMetadata = invalidateMetadata || reinit\n\t\tanyImportDeleted = anyImportDeleted || importDeleted\n\t\tanyPkgFileChanged = anyPkgFileChanged || pkgFileChanged\n\n\t\t// Mark all of the package IDs containing the given file.\n\t\tfilePackageIDs := invalidatedPackageIDs(uri, s.meta.ForFile, pkgFileChanged)\n\t\tfor id := range filePackageIDs {\n\t\t\tdirectIDs[id] = directIDs[id] || invalidateMetadata // may insert 'false'\n\t\t}\n\n\t\t// Invalidate the previous modTidyHandle if any of the files have been\n\t\t// saved or if any of the metadata has been invalidated.\n\t\t//\n\t\t// TODO(rfindley): this seems like too-aggressive invalidation of mod\n\t\t// results. We should instead thread through overlays to the Go command\n\t\t// invocation and only run this if invalidateMetadata (and perhaps then\n\t\t// still do it less frequently).\n\t\tif invalidateMetadata || fileWasSaved(oldFH, newFH) {\n\t\t\t// Only invalidate mod tidy results for the most relevant modfile in the\n\t\t\t// workspace. This is a potentially lossy optimization for workspaces\n\t\t\t// with many modules (such as google-cloud-go, which has 145 modules as\n\t\t\t// of writing).\n\t\t\t//\n\t\t\t// While it is theoretically possible that a change in workspace module A\n\t\t\t// could affect the mod-tidiness of workspace module B (if B transitively\n\t\t\t// requires A), such changes are probably unlikely and not worth the\n\t\t\t// penalty of re-running go mod tidy for everything. Note that mod tidy\n\t\t\t// ignores GOWORK, so the two modules would have to be related by a chain\n\t\t\t// of replace directives.\n\t\t\t//\n\t\t\t// We could improve accuracy by inspecting replace directives, using\n\t\t\t// overlays in go mod tidy, and/or checking for metadata changes from the\n\t\t\t// on-disk content.\n\t\t\t//\n\t\t\t// Note that we iterate the modTidyHandles map here, rather than e.g.\n\t\t\t// using nearestModFile, because we don't have access to an accurate\n\t\t\t// FileSource at this point in the snapshot clone.\n\t\t\tconst onlyInvalidateMostRelevant = true\n\t\t\tif onlyInvalidateMostRelevant {\n\t\t\t\tdeleteMostRelevantModFile(result.modTidyHandles, uri)\n\t\t\t} else {\n\t\t\t\tresult.modTidyHandles.Clear()\n\t\t\t}\n\n\t\t\t// TODO(rfindley): should we apply the above heuristic to mod vuln or mod\n\t\t\t// why handles as well?\n\t\t\t//\n\t\t\t// TODO(rfindley): no tests fail if I delete the line below.\n\t\t\tresult.modWhyHandles.Clear()\n\t\t\tresult.modVulnHandles.Clear()\n\t\t}\n\t}\n\n\t// Deleting an import can cause list errors due to import cycles to be\n\t// resolved. The best we can do without parsing the list error message is to\n\t// hope that list errors may have been resolved by a deleted import.\n\t//\n\t// We could do better by parsing the list error message. We already do this\n\t// to assign a better range to the list error, but for such critical\n\t// functionality as metadata, it's better to be conservative until it proves\n\t// impractical.\n\t//\n\t// We could also do better by looking at which imports were deleted and\n\t// trying to find cycles they are involved in. This fails when the file goes\n\t// from an unparsable state to a parseable state, as we don't have a\n\t// starting point to compare with.\n\tif anyImportDeleted {\n\t\tfor id, mp := range s.meta.Packages {\n\t\t\tif len(mp.Errors) > 0 {\n\t\t\t\tdirectIDs[id] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Adding a file can resolve missing dependencies from existing packages.\n\t//\n\t// We could be smart here and try to guess which packages may have been\n\t// fixed, but until that proves necessary, just invalidate metadata for any\n\t// package with missing dependencies.\n\tif anyPkgFileChanged {\n\t\tfor id, mp := range s.meta.Packages {\n\t\t\tfor _, impID := range mp.DepsByImpPath {\n\t\t\t\tif impID == \"\" { // missing import\n\t\t\t\t\tdirectIDs[id] = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Invalidate reverse dependencies too.\n\t// idsToInvalidate keeps track of transitive reverse dependencies.\n\t// If an ID is present in the map, invalidate its types.\n\t// If an ID's value is true, invalidate its metadata too.\n\tidsToInvalidate := map[PackageID]bool{}\n\tvar addRevDeps func(PackageID, bool)\n\taddRevDeps = func(id PackageID, invalidateMetadata bool) {\n\t\tcurrent, seen := idsToInvalidate[id]\n\t\tnewInvalidateMetadata := current || invalidateMetadata\n\n\t\t// If we've already seen this ID, and the value of invalidate\n\t\t// metadata has not changed, we can return early.\n\t\tif seen && current == newInvalidateMetadata {\n\t\t\treturn\n\t\t}\n\t\tidsToInvalidate[id] = newInvalidateMetadata\n\t\tfor _, rdep := range s.meta.ImportedBy[id] {\n\t\t\taddRevDeps(rdep.ID, invalidateMetadata)\n\t\t}\n\t}\n\tfor id, invalidateMetadata := range directIDs {\n\t\taddRevDeps(id, invalidateMetadata)\n\t}\n\n\t// Invalidated package information.\n\tfor id, invalidateMetadata := range idsToInvalidate {\n\t\t// See the [packageHandle] documentation for more details about this\n\t\t// invalidation.\n\t\tif ph, ok := result.packages.Get(id); ok {\n\t\t\tneedsDiagnosis = true\n\n\t\t\t// Always invalidate analysis keys, as we do not implement fine-grained\n\t\t\t// invalidation for analysis.\n\t\t\tresult.fullAnalysisKeys.Delete(id)\n\t\t\tresult.factyAnalysisKeys.Delete(id)\n\n\t\t\tif invalidateMetadata {\n\t\t\t\tresult.packages.Delete(id)\n\t\t\t} else {\n\t\t\t\t// If the package was just invalidated by a dependency, its local\n\t\t\t\t// inputs are still valid.\n\t\t\t\tph = ph.clone()\n\t\t\t\tif _, ok := directIDs[id]; ok {\n\t\t\t\t\tph.state = validMetadata // local inputs changed\n\t\t\t\t} else {\n\t\t\t\t\tph.state = min(ph.state, validLocalData) // a dependency changed\n\t\t\t\t}\n\t\t\t\tresult.packages.Set(id, ph, nil)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compute which metadata updates are required. We only need to invalidate\n\t// packages directly containing the affected file, and only if it changed in\n\t// a relevant way.\n\tmetadataUpdates := make(map[PackageID]*metadata.Package)\n\tfor id, mp := range s.meta.Packages {\n\t\tinvalidateMetadata := idsToInvalidate[id]\n\n\t\t// For metadata that has been newly invalidated, capture package paths\n\t\t// requiring reloading in the shouldLoad map.\n\t\tif invalidateMetadata && !metadata.IsCommandLineArguments(mp.ID) {\n\t\t\tneedsReload := []PackagePath{mp.PkgPath}\n\t\t\tif mp.ForTest != \"\" && mp.ForTest != mp.PkgPath {\n\t\t\t\t// When reloading test variants, always reload their ForTest package as\n\t\t\t\t// well. Otherwise, we may miss test variants in the resulting load.\n\t\t\t\t//\n\t\t\t\t// TODO(rfindley): is this actually sufficient? Is it possible that\n\t\t\t\t// other test variants may be invalidated? Either way, we should\n\t\t\t\t// determine exactly what needs to be reloaded here.\n\t\t\t\tneedsReload = append(needsReload, mp.ForTest)\n\t\t\t}\n\t\t\tresult.shouldLoad.Set(id, needsReload, nil)\n\t\t}\n\n\t\t// Check whether the metadata should be deleted.\n\t\tif invalidateMetadata {\n\t\t\tneedsDiagnosis = true\n\t\t\tmetadataUpdates[id] = nil\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// Update metadata, if necessary.\n\tresult.meta = s.meta.Update(metadataUpdates)\n\n\t// Update workspace and active packages, if necessary.\n\tif result.meta != s.meta || anyFileOpenedOrClosed {\n\t\tneedsDiagnosis = true\n\t\tresult.workspacePackages = computeWorkspacePackagesLocked(ctx, result, result.meta)\n\t} else {\n\t\tresult.workspacePackages = s.workspacePackages\n\t}\n\n\treturn result, needsDiagnosis\n}\n\n// cloneWithout clones m then deletes from it the keys of changes.\n//\n// The optional didDelete variable is set to true if there were deletions.\nfunc cloneWithout[K constraints.Ordered, V1, V2 any](m *persistent.Map[K, V1], changes map[K]V2, didDelete *bool) *persistent.Map[K, V1] {\n\tm2 := m.Clone()\n\tfor k := range changes {\n\t\tif m2.Delete(k) && didDelete != nil {\n\t\t\t*didDelete = true\n\t\t}\n\t}\n\treturn m2\n}\n\n// cloneWith clones m then inserts the changes into it.\nfunc cloneWith[K constraints.Ordered, V any](m *persistent.Map[K, V], changes map[K]V) *persistent.Map[K, V] {\n\tm2 := m.Clone()\n\tfor k, v := range changes {\n\t\tm2.Set(k, v, nil)\n\t}\n\treturn m2\n}\n\n// deleteMostRelevantModFile deletes the mod file most likely to be the mod\n// file for the changed URI, if it exists.\n//\n// Specifically, this is the longest mod file path in a directory containing\n// changed. This might not be accurate if there is another mod file closer to\n// changed that happens not to be present in the map, but that's OK: the goal\n// of this function is to guarantee that IF the nearest mod file is present in\n// the map, it is invalidated.\nfunc deleteMostRelevantModFile(m *persistent.Map[protocol.DocumentURI, *memoize.Promise], changed protocol.DocumentURI) {\n\tvar mostRelevant protocol.DocumentURI\n\tchangedFile := changed.Path()\n\n\tfor modURI := range m.All() {\n\t\tif len(modURI) > len(mostRelevant) {\n\t\t\tif pathutil.InDir(modURI.DirPath(), changedFile) {\n\t\t\t\tmostRelevant = modURI\n\t\t\t}\n\t\t}\n\t}\n\tif mostRelevant != \"\" {\n\t\tm.Delete(mostRelevant)\n\t}\n}\n\n// invalidatedPackageIDs returns all packages invalidated by a change to uri.\n// If we haven't seen this URI before, we guess based on files in the same\n// directory. This is of course incorrect in build systems where packages are\n// not organized by directory.\n//\n// If packageFileChanged is set, the file is either a new file, or has a new\n// package name. In this case, all known packages in the directory will be\n// invalidated.\nfunc invalidatedPackageIDs(uri protocol.DocumentURI, known map[protocol.DocumentURI][]*metadata.Package, packageFileChanged bool) map[PackageID]struct{} {\n\tinvalidated := make(map[PackageID]struct{})\n\n\t// At a minimum, we invalidate packages known to contain uri.\n\tfor _, pkg := range known[uri] {\n\t\tinvalidated[pkg.ID] = struct{}{}\n\t}\n\n\t// If the file didn't move to a new package, we should only invalidate the\n\t// packages it is currently contained inside.\n\tif !packageFileChanged && len(invalidated) > 0 {\n\t\treturn invalidated\n\t}\n\n\t// This is a file we don't yet know about, or which has moved packages. Guess\n\t// relevant packages by considering files in the same directory.\n\n\t// Cache of FileInfo to avoid unnecessary stats for multiple files in the\n\t// same directory.\n\tstats := make(map[string]struct {\n\t\tos.FileInfo\n\t\terror\n\t})\n\tgetInfo := func(dir string) (os.FileInfo, error) {\n\t\tif res, ok := stats[dir]; ok {\n\t\t\treturn res.FileInfo, res.error\n\t\t}\n\t\tfi, err := os.Stat(dir)\n\t\tstats[dir] = struct {\n\t\t\tos.FileInfo\n\t\t\terror\n\t\t}{fi, err}\n\t\treturn fi, err\n\t}\n\tdir := uri.DirPath()\n\tfi, err := getInfo(dir)\n\tif err == nil {\n\t\t// Aggregate all possibly relevant package IDs.\n\t\tfor knownURI, pkgs := range known {\n\t\t\tknownDir := knownURI.DirPath()\n\t\t\tknownFI, err := getInfo(knownDir)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif os.SameFile(fi, knownFI) {\n\t\t\t\tfor _, pkg := range pkgs {\n\t\t\t\t\tinvalidated[pkg.ID] = struct{}{}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn invalidated\n}\n\n// fileWasSaved reports whether the FileHandle passed in has been saved. It\n// accomplishes this by checking to see if the original and current FileHandles\n// are both overlays, and if the current FileHandle is saved while the original\n// FileHandle was not saved.\nfunc fileWasSaved(originalFH, currentFH file.Handle) bool {\n\tif originalFH == nil || currentFH == nil {\n\t\treturn true // should not happen for valid file handles\n\t}\n\n\t// If the file identity has not changed, the content has not changed.\n\t// Therefore, the \"saved\" state (from the perspective of go mod tidy)\n\t// has not changed.\n\tif originalFH.Identity() == currentFH.Identity() {\n\t\treturn false\n\t}\n\tc, ok := currentFH.(*overlay)\n\tif !ok || c == nil {\n\t\treturn true\n\t}\n\to, ok := originalFH.(*overlay)\n\tif !ok || o == nil {\n\t\treturn c.saved\n\t}\n\treturn !o.saved && c.saved\n}\n\n// metadataChanges detects features of the change from oldFH->newFH that may\n// affect package metadata.\n//\n// It uses lockedSnapshot to access cached parse information. lockedSnapshot\n// must be locked.\n//\n// The result parameters have the following meaning:\n//   - invalidate means that package metadata for packages containing the file\n//     should be invalidated.\n//   - pkgFileChanged means that the file->package associates for the file have\n//     changed (possibly because the file is new, or because its package name has\n//     changed).\n//   - importDeleted means that an import has been deleted, or we can't\n//     determine if an import was deleted due to errors.\nfunc metadataChanges(ctx context.Context, lockedSnapshot *Snapshot, oldFH, newFH file.Handle) (invalidate, pkgFileChanged, importDeleted bool) {\n\tif oe, ne := oldFH != nil && fileExists(oldFH), fileExists(newFH); !oe || !ne { // existential changes\n\t\tchanged := oe != ne\n\t\treturn changed, changed, !ne // we don't know if an import was deleted\n\t}\n\n\t// If the file hasn't changed, there's no need to reload.\n\tif oldFH.Identity() == newFH.Identity() {\n\t\treturn false, false, false\n\t}\n\n\tfset := token.NewFileSet()\n\t// Parse headers to compare package names and imports.\n\toldHeads, oldErr := lockedSnapshot.view.parseCache.parseFiles(ctx, fset, parsego.Header, false, oldFH)\n\tnewHeads, newErr := lockedSnapshot.view.parseCache.parseFiles(ctx, fset, parsego.Header, false, newFH)\n\n\tif oldErr != nil || newErr != nil {\n\t\terrChanged := (oldErr == nil) != (newErr == nil)\n\t\treturn errChanged, errChanged, (newErr != nil) // we don't know if an import was deleted\n\t}\n\n\toldHead := oldHeads[0]\n\tnewHead := newHeads[0]\n\n\t// `go list` fails completely if the file header cannot be parsed. If we go\n\t// from a non-parsing state to a parsing state, we should reload.\n\tif oldHead.ParseErr != nil && newHead.ParseErr == nil {\n\t\treturn true, true, true // We don't know what changed, so fall back on full invalidation.\n\t}\n\n\t// If a package name has changed, the set of package imports may have changed\n\t// in ways we can't detect here. Assume an import has been deleted.\n\tif oldHead.File.Name.Name != newHead.File.Name.Name {\n\t\treturn true, true, true\n\t}\n\n\t// Check whether package imports have changed. Only consider potentially\n\t// valid imports paths.\n\toldImports := validImportPaths(oldHead.File.Imports)\n\tnewImports := validImportPaths(newHead.File.Imports)\n\n\tfor path := range newImports {\n\t\tif _, ok := oldImports[path]; ok {\n\t\t\tdelete(oldImports, path)\n\t\t} else {\n\t\t\tinvalidate = true // a new, potentially valid import was added\n\t\t}\n\t}\n\n\tif len(oldImports) > 0 {\n\t\tinvalidate = true\n\t\timportDeleted = true\n\t}\n\n\t// If the change does not otherwise invalidate metadata, get the full ASTs in\n\t// order to check magic comments.\n\t//\n\t// Note: if this affects performance we can probably avoid parsing in the\n\t// common case by first scanning the source for potential comments.\n\tif !invalidate {\n\t\torigFulls, oldErr := lockedSnapshot.view.parseCache.parseFiles(ctx, fset, parsego.Full, false, oldFH)\n\t\tnewFulls, newErr := lockedSnapshot.view.parseCache.parseFiles(ctx, fset, parsego.Full, false, newFH)\n\t\tif oldErr == nil && newErr == nil {\n\t\t\tinvalidate = magicCommentsChanged(origFulls[0].File, newFulls[0].File)\n\t\t} else {\n\t\t\t// At this point, we shouldn't ever fail to produce a parsego.File, as\n\t\t\t// we're already past header parsing.\n\t\t\tbug.Reportf(\"metadataChanges: unparsable file %v (old error: %v, new error: %v)\", oldFH.URI(), oldErr, newErr)\n\t\t}\n\t}\n\n\treturn invalidate, pkgFileChanged, importDeleted\n}\n\nfunc magicCommentsChanged(original *ast.File, current *ast.File) bool {\n\toldComments := extractMagicComments(original)\n\tnewComments := extractMagicComments(current)\n\tif len(oldComments) != len(newComments) {\n\t\treturn true\n\t}\n\tfor i := range oldComments {\n\t\tif oldComments[i] != newComments[i] {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// validImportPaths extracts the set of valid import paths from imports.\nfunc validImportPaths(imports []*ast.ImportSpec) map[string]struct{} {\n\tm := make(map[string]struct{})\n\tfor _, spec := range imports {\n\t\tif path := spec.Path.Value; validImportPath(path) {\n\t\t\tm[path] = struct{}{}\n\t\t}\n\t}\n\treturn m\n}\n\nfunc validImportPath(path string) bool {\n\tpath, err := strconv.Unquote(path)\n\tif err != nil {\n\t\treturn false\n\t}\n\tif path == \"\" {\n\t\treturn false\n\t}\n\tif path[len(path)-1] == '/' {\n\t\treturn false\n\t}\n\treturn true\n}\n\nvar buildConstraintOrEmbedRe = regexp.MustCompile(`^//(go:embed|go:build|\\s*\\+build).*`)\n\n// extractMagicComments finds magic comments that affect metadata in f.\nfunc extractMagicComments(f *ast.File) []string {\n\tvar results []string\n\tfor _, cg := range f.Comments {\n\t\tfor _, c := range cg.List {\n\t\t\tif buildConstraintOrEmbedRe.MatchString(c.Text) {\n\t\t\t\tresults = append(results, c.Text)\n\t\t\t}\n\t\t}\n\t}\n\treturn results\n}\n\n// BuiltinFile returns the pseudo-source file builtins.go,\n// parsed with legacy ast.Object resolution.\nfunc (s *Snapshot) BuiltinFile(ctx context.Context) (*parsego.File, error) {\n\ts.AwaitInitialized(ctx)\n\n\ts.mu.Lock()\n\tbuiltin := s.builtin\n\ts.mu.Unlock()\n\n\tif builtin == \"\" {\n\t\treturn nil, fmt.Errorf(\"no builtin package for view %s\", s.view.folder.Name)\n\t}\n\n\tfh, err := s.ReadFile(ctx, builtin)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// For the builtin file only, we need syntactic object resolution\n\t// (since we can't type check).\n\tmode := parsego.Full &^ parser.SkipObjectResolution\n\tpgfs, err := s.view.parseCache.parseFiles(ctx, token.NewFileSet(), mode, false, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pgfs[0], nil\n}\n\n// IsBuiltin reports whether uri is part of the builtin package.\nfunc (s *Snapshot) IsBuiltin(uri protocol.DocumentURI) bool {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\t// We should always get the builtin URI in a canonical form, so use simple\n\t// string comparison here. span.CompareURI is too expensive.\n\treturn uri == s.builtin\n}\n\nfunc (s *Snapshot) setBuiltin(path string) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\ts.builtin = protocol.URIFromPath(path)\n}\n\n// WantCompilerOptDetails reports whether to compute compiler\n// optimization details for packages and tests in the given directory.\nfunc (s *Snapshot) WantCompilerOptDetails(dir protocol.DocumentURI) bool {\n\t_, ok := s.compilerOptDetails[dir]\n\treturn ok\n}\n\n// A CodeLensSourceFunc is a function that reports CodeLenses (range-associated\n// commands) for a given file.\ntype CodeLensSourceFunc func(context.Context, *Snapshot, file.Handle) ([]protocol.CodeLens, error)\n"
  },
  {
    "path": "gopls/internal/cache/source.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"maps\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/symbols\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\n// goplsSource is an imports.Source that provides import information using\n// gopls and the module cache index.\ntype goplsSource struct {\n\tsnapshot  *Snapshot\n\tenvSource *imports.ProcessEnvSource\n\n\t// set by each invocation of ResolveReferences\n\tctx context.Context\n}\n\nfunc (s *Snapshot) NewGoplsSource(is *imports.ProcessEnvSource) *goplsSource {\n\treturn &goplsSource{\n\t\tsnapshot:  s,\n\t\tenvSource: is,\n\t}\n}\n\nfunc (s *goplsSource) LoadPackageNames(ctx context.Context, srcDir string, paths []imports.ImportPath) (map[imports.ImportPath]imports.PackageName, error) {\n\t// TODO: use metadata graph. Aside from debugging, this is the only used of envSource\n\treturn s.envSource.LoadPackageNames(ctx, srcDir, paths)\n}\n\ntype result struct {\n\tres        *imports.Result\n\tdeprecated bool\n}\n\n// ResolveReferences tries to find resolving imports in the workspace, and failing\n// that, in the module cache. It uses heuristics to decide among alternatives.\n// The heuristics will usually prefer a v2 version, if there is one.\n// TODO: It does not take advantage of hints provided by the user:\n// 1. syntactic context: pkg.Name().Foo\n// 3. already imported files in the same module\nfunc (s *goplsSource) ResolveReferences(ctx context.Context, filename string, missing imports.References) ([]*imports.Result, error) {\n\ts.ctx = ctx\n\t// get results from the workspace. There will at most one for each package name\n\tfromWS, err := s.resolveWorkspaceReferences(filename, missing)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// collect the ones that are still\n\tneeded := maps.Clone(missing)\n\tfor _, a := range fromWS {\n\t\tdelete(needed, a.Package.Name)\n\t}\n\t// when debug (below) is gone, change this to: if len(needed) == 0 {return fromWS, nil}\n\tvar fromCache []*result\n\tif len(needed) != 0 {\n\t\tvar err error\n\t\tfromCache, err = s.resolveCacheReferences(needed)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// trim candidates to one per missing package.\n\t\tbyPkgNm := make(map[string][]*result)\n\t\tfor _, c := range fromCache {\n\t\t\t// avoid internal and vendor\n\t\t\tif !imports.CanUse(filename, c.res.Import.ImportPath) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbyPkgNm[c.res.Package.Name] = append(byPkgNm[c.res.Package.Name], c)\n\t\t}\n\t\tfor k, v := range byPkgNm {\n\t\t\tfromWS = append(fromWS, s.bestCache(k, v))\n\t\t}\n\t}\n\tconst debug = false\n\tif debug { // debugging.\n\t\t// what does the old one find?\n\t\told, err := s.envSource.ResolveReferences(ctx, filename, missing)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tlog.Printf(\"fromCache:%d %s\", len(fromCache), filename)\n\t\tfor i, c := range fromCache {\n\t\t\tlog.Printf(\"cans%d %#v %#v %v\", i, c.res.Import, c.res.Package, c.deprecated)\n\t\t}\n\t\tfor k, v := range missing {\n\t\t\tfor x := range v {\n\t\t\t\tlog.Printf(\"missing %s.%s\", k, x)\n\t\t\t}\n\t\t}\n\t\tfor k, v := range needed {\n\t\t\tfor x := range v {\n\t\t\t\tlog.Printf(\"needed %s.%s\", k, x)\n\t\t\t}\n\t\t}\n\n\t\tdbgpr := func(hdr string, v []*imports.Result) {\n\t\t\tfor i := range v {\n\t\t\t\tlog.Printf(\"%s%d %+v %+v\", hdr, i, v[i].Import, v[i].Package)\n\t\t\t}\n\t\t}\n\n\t\tdbgpr(\"fromWS\", fromWS)\n\t\tdbgpr(\"old\", old)\n\t\tfor k, v := range s.snapshot.workspacePackages.All() {\n\t\t\tlog.Printf(\"workspacePackages[%s]=%s\", k, v)\n\t\t}\n\t\t// anything in ans with >1 matches?\n\t\tseen := make(map[string]int)\n\t\tfor _, a := range fromWS {\n\t\t\tseen[a.Package.Name]++\n\t\t}\n\t\tfor k, v := range seen {\n\t\t\tif v > 1 {\n\t\t\t\tlog.Printf(\"saw %d %s\", v, k)\n\t\t\t\tfor i, x := range fromWS {\n\t\t\t\t\tif x.Package.Name == k {\n\t\t\t\t\t\tlog.Printf(\"%d: %+v %+v\", i, x.Package, x.Import)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn fromWS, nil\n\n}\n\nfunc (s *goplsSource) resolveCacheReferences(missing imports.References) ([]*result, error) {\n\tix, err := s.snapshot.view.ModcacheIndex()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfound := make(map[string]*result)\n\tfor pkgName, nameSet := range missing {\n\t\tnames := moremaps.KeySlice(nameSet)\n\t\tfor importPath, cands := range ix.LookupAll(pkgName, names...) {\n\t\t\tres := found[importPath]\n\t\t\tif res == nil {\n\t\t\t\tres = &result{\n\t\t\t\t\tres: &imports.Result{\n\t\t\t\t\t\tImport: &imports.ImportInfo{\n\t\t\t\t\t\t\tImportPath: importPath,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tPackage: &imports.PackageInfo{\n\t\t\t\t\t\t\tName:    pkgName,\n\t\t\t\t\t\t\tExports: make(map[string]bool)},\n\t\t\t\t\t},\n\t\t\t\t\tdeprecated: false,\n\t\t\t\t}\n\t\t\t\tfound[importPath] = res\n\t\t\t}\n\t\t\tfor _, c := range cands {\n\t\t\t\tres.res.Package.Exports[c.Name] = true\n\t\t\t\t// The import path is deprecated if a symbol that would be used is deprecated\n\t\t\t\tres.deprecated = res.deprecated || c.Deprecated\n\t\t\t}\n\t\t}\n\n\t}\n\t// return results in some deterministic order\n\tgot := moremaps.ValueSlice(found)\n\tslices.SortFunc(got, func(a, b *result) int {\n\t\treturn strings.Compare(a.res.Import.ImportPath, b.res.Import.ImportPath)\n\t})\n\treturn got, nil\n}\n\ntype found struct {\n\tsym *symbols.Package\n\tres *imports.Result\n}\n\nfunc (s *goplsSource) resolveWorkspaceReferences(filename string, missing imports.References) ([]*imports.Result, error) {\n\turi := protocol.URIFromPath(filename)\n\tmypkgs, err := s.snapshot.MetadataForFile(s.ctx, uri, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(mypkgs) == 0 {\n\t\treturn nil, nil\n\t}\n\tmypkg := mypkgs[0] // narrowest package\n\t// search the metadata graph for package ids corresponding to missing\n\tg := s.snapshot.MetadataGraph()\n\tvar ids []metadata.PackageID\n\tvar pkgs []*metadata.Package\n\tfor pid, pkg := range g.Packages {\n\t\t// no test packages, except perhaps for ourselves\n\t\tif pkg.ForTest != \"\" && pkg != mypkg {\n\t\t\tcontinue\n\t\t}\n\t\tif missingWants(missing, pkg.Name) {\n\t\t\tids = append(ids, pid)\n\t\t\tpkgs = append(pkgs, pkg)\n\t\t}\n\t}\n\t// find the symbols in those packages\n\t// the syms occur in the same order as the ids and the pkgs\n\tsyms, err := s.snapshot.Symbols(s.ctx, ids...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// keep track of used syms and found results by package name\n\t// TODO: avoid import cycles (is current package in forward closure)\n\tfounds := make(map[string][]found)\n\tfor i := range len(ids) {\n\t\tnm := string(pkgs[i].Name)\n\t\tif satisfies(syms[i], missing[nm]) {\n\t\t\tgot := &imports.Result{\n\t\t\t\tImport: &imports.ImportInfo{\n\t\t\t\t\tName:       \"\",\n\t\t\t\t\tImportPath: string(pkgs[i].PkgPath),\n\t\t\t\t},\n\t\t\t\tPackage: &imports.PackageInfo{\n\t\t\t\t\tName:    string(pkgs[i].Name),\n\t\t\t\t\tExports: missing[imports.PackageName(pkgs[i].Name)],\n\t\t\t\t},\n\t\t\t}\n\t\t\tfounds[nm] = append(founds[nm], found{syms[i], got})\n\t\t}\n\t}\n\tvar ans []*imports.Result\n\tfor _, v := range founds {\n\t\t// make sure the elements of v are unique\n\t\t// (Import.ImportPath or Package.Name must differ)\n\t\tcmp := func(l, r found) int {\n\t\t\tswitch strings.Compare(l.res.Import.ImportPath, r.res.Import.ImportPath) {\n\t\t\tcase -1:\n\t\t\t\treturn -1\n\t\t\tcase 1:\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\treturn strings.Compare(l.res.Package.Name, r.res.Package.Name)\n\t\t}\n\t\tslices.SortFunc(v, cmp)\n\t\tnewv := make([]found, 0, len(v))\n\t\tnewv = append(newv, v[0])\n\t\tfor i := 1; i < len(v); i++ {\n\t\t\tif cmp(v[i], v[i-1]) != 0 {\n\t\t\t\tnewv = append(newv, v[i])\n\t\t\t}\n\t\t}\n\t\tans = append(ans, bestImport(filename, newv))\n\t}\n\treturn ans, nil\n}\n\n// for each package name, choose one using heuristics\nfunc bestImport(filename string, got []found) *imports.Result {\n\tif len(got) == 1 {\n\t\treturn got[0].res\n\t}\n\tisTestFile := strings.HasSuffix(filename, \"_test.go\")\n\tvar leftovers []found\n\tfor _, g := range got {\n\t\t// don't use _test packages unless isTestFile\n\t\ttestPkg := strings.HasSuffix(string(g.res.Package.Name), \"_test\") || strings.HasSuffix(string(g.res.Import.Name), \"_test\")\n\t\tif testPkg && !isTestFile {\n\t\t\tcontinue // no test covers this\n\t\t}\n\t\tif imports.CanUse(filename, g.sym.Files[0].DirPath()) {\n\t\t\tleftovers = append(leftovers, g)\n\t\t}\n\t}\n\tswitch len(leftovers) {\n\tcase 0:\n\t\tbreak // use got, they are all bad\n\tcase 1:\n\t\treturn leftovers[0].res // only one left\n\tdefault:\n\t\tgot = leftovers // filtered some out\n\t}\n\n\t// TODO: if there are versions (like /v2) prefer them\n\n\t// use distance to common ancestor with filename\n\t// (TestDirectoryFilters_MultiRootImportScanning)\n\t// filename is .../a/main.go, choices are\n\t// .../a/hi/hi.go and .../b/hi/hi.go\n\tlongest := -1\n\tix := -1\n\tfor i := 0; i < len(got); i++ {\n\t\td := commonpref(filename, got[i].sym.Files[0].Path())\n\t\tif d > longest {\n\t\t\tlongest = d\n\t\t\tix = i\n\t\t}\n\t}\n\t// it is possible that there were several tied, but we return the first\n\treturn got[ix].res\n}\n\n// choose the best result for the package named nm from the module cache\nfunc (s *goplsSource) bestCache(nm string, got []*result) *imports.Result {\n\tif len(got) == 1 {\n\t\treturn got[0].res\n\t}\n\t// does the go.mod file choose one?\n\tif ans := s.fromGoMod(got); ans != nil {\n\t\treturn ans\n\t}\n\tgot = preferUndeprecated(got)\n\t// want the best Import.ImportPath\n\t// these are all for the package named nm,\n\t// nm (probably) occurs in all the paths;\n\t// choose the longest (after nm), so as to get /v2\n\tmaxlen, which := -1, -1\n\tfor i := 0; i < len(got); i++ {\n\t\tix := strings.Index(got[i].res.Import.ImportPath, nm)\n\t\tif ix == -1 {\n\t\t\tcontinue // now what?\n\t\t}\n\t\tcnt := len(got[i].res.Import.ImportPath) - ix\n\t\tif cnt > maxlen {\n\t\t\tmaxlen = cnt\n\t\t\twhich = i\n\t\t}\n\t\t// what about ties? (e.g., /v2 and /v3)\n\t}\n\tif which >= 0 {\n\t\treturn got[which].res\n\t}\n\treturn got[0].res // arbitrary guess\n}\n\n// if go.mod requires one of the packages, return that\nfunc (s *goplsSource) fromGoMod(got []*result) *imports.Result {\n\t// should we use s.S.view.worsspaceModFiles, and the union of their requires?\n\t// (note that there are no tests where it contains more than one)\n\tmodURI := s.snapshot.view.gomod\n\tmodfh, ok := s.snapshot.files.get(modURI)\n\tif !ok {\n\t\treturn nil\n\t}\n\tparsed, err := s.snapshot.ParseMod(s.ctx, modfh)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treqs := parsed.File.Require\n\tfor _, g := range got {\n\t\tfor _, req := range reqs {\n\t\t\tif strings.HasPrefix(g.res.Import.ImportPath, req.Syntax.Token[1]) {\n\t\t\t\treturn g.res\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc commonpref(filename string, path string) int {\n\tk := 0\n\tfor ; k < len(filename) && k < len(path) && filename[k] == path[k]; k++ {\n\t}\n\treturn k\n}\n\nfunc satisfies(pkg *symbols.Package, missing map[string]bool) bool {\n\tsyms := make(map[string]bool)\n\tfor _, x := range pkg.Symbols {\n\t\tfor _, s := range x {\n\t\t\tsyms[s.Name] = true\n\t\t}\n\t}\n\tfor k := range missing {\n\t\tif !syms[k] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// does pkgPath potentially satisfy a missing reference?\nfunc missingWants(missing imports.References, pkgPath metadata.PackageName) bool {\n\tfor k := range missing {\n\t\tif string(k) == string(pkgPath) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// If there are both deprecated and undprecated ones\n// then return only the undeprecated one\nfunc preferUndeprecated(got []*result) []*result {\n\tvar ok []*result\n\tfor _, g := range got {\n\t\tif !g.deprecated {\n\t\t\tok = append(ok, g)\n\t\t}\n\t}\n\tif len(ok) > 0 {\n\t\treturn ok\n\t}\n\treturn got\n}\n"
  },
  {
    "path": "gopls/internal/cache/symbols/symbols.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package symbols defines the serializable index of package symbols extracted\n// from parsed package files.\npackage symbols\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\n// Symbol holds a precomputed symbol value. This is a subset of the information\n// in the full protocol.SymbolInformation struct to reduce the size of each\n// symbol.\ntype Symbol struct {\n\tName  string\n\tKind  protocol.SymbolKind\n\tRange protocol.Range\n}\n\n// A Package holds information about symbols declared by each file of a\n// package.\n//\n// The symbols included are: package-level declarations, and fields and methods\n// of type declarations.\ntype Package struct {\n\tFiles   []protocol.DocumentURI // package files\n\tSymbols [][]Symbol             // symbols in each file\n}\n\nvar codec = frob.CodecFor[Package]()\n\n// Decode decodes data from [Package.Encode].\nfunc Decode(data []byte) *Package {\n\tvar pkg Package\n\tcodec.Decode(data, &pkg)\n\treturn &pkg\n}\n\n// Encode encodes the package.\nfunc (pkg *Package) Encode() []byte {\n\treturn codec.Encode(*pkg)\n}\n\n// New returns a new [Package] summarizing symbols in the given files.\nfunc New(files []*parsego.File) *Package {\n\tvar (\n\t\turis    []protocol.DocumentURI\n\t\tsymbols [][]Symbol\n\t)\n\tfor _, pgf := range files {\n\t\turis = append(uris, pgf.URI)\n\t\tsyms := symbolizeFile(pgf)\n\t\tsymbols = append(symbols, syms)\n\t}\n\treturn &Package{\n\t\tFiles:   uris,\n\t\tSymbols: symbols,\n\t}\n}\n\n// symbolizeFile reads and parses a file and extracts symbols from it.\nfunc symbolizeFile(pgf *parsego.File) []Symbol {\n\tw := &symbolWalker{\n\t\tnodeRange: pgf.NodeRange,\n\t}\n\n\tfor _, decl := range pgf.File.Decls {\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tkind := protocol.Function\n\t\t\tvar recv *ast.Ident\n\t\t\tif decl.Recv.NumFields() > 0 {\n\t\t\t\tkind = protocol.Method\n\t\t\t\t_, recv, _ = astutil.UnpackRecv(decl.Recv.List[0].Type)\n\t\t\t}\n\t\t\tw.declare(decl.Name.Name, kind, decl.Name, recv)\n\n\t\tcase *ast.GenDecl:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tkind := protocol.Class\n\t\t\t\t\tswitch spec.Type.(type) {\n\t\t\t\t\tcase *ast.InterfaceType:\n\t\t\t\t\t\tkind = protocol.Interface\n\t\t\t\t\tcase *ast.StructType:\n\t\t\t\t\t\tkind = protocol.Struct\n\t\t\t\t\tcase *ast.FuncType:\n\t\t\t\t\t\tkind = protocol.Function\n\t\t\t\t\t}\n\t\t\t\t\tw.declare(spec.Name.Name, kind, spec.Name)\n\t\t\t\t\tw.walkType(spec.Type, spec.Name)\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\tkind := protocol.Variable\n\t\t\t\t\t\tif decl.Tok == token.CONST {\n\t\t\t\t\t\t\tkind = protocol.Constant\n\t\t\t\t\t\t}\n\t\t\t\t\t\tw.declare(name.Name, kind, name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn w.symbols\n}\n\ntype symbolWalker struct {\n\tnodeRange func(node ast.Node) (protocol.Range, error) // for computing positions\n\n\tsymbols []Symbol\n}\n\n// declare declares a symbol of the specified name, kind, node location, and enclosing dotted path of identifiers.\nfunc (w *symbolWalker) declare(name string, kind protocol.SymbolKind, node ast.Node, path ...*ast.Ident) {\n\tvar b strings.Builder\n\tfor _, ident := range path {\n\t\tif ident != nil {\n\t\t\tb.WriteString(ident.Name)\n\t\t\tb.WriteString(\".\")\n\t\t}\n\t}\n\tb.WriteString(name)\n\n\trng, err := w.nodeRange(node)\n\tif err != nil {\n\t\t// TODO(rfindley): establish an invariant that node positions cannot exceed\n\t\t// the file. This is not currently the case--for example see\n\t\t// golang/go#48300 (this can also happen due to phantom selectors).\n\t\t//\n\t\t// For now, we have nothing to do with this error.\n\t\treturn\n\t}\n\tsym := Symbol{\n\t\tName:  b.String(),\n\t\tKind:  kind,\n\t\tRange: rng,\n\t}\n\tw.symbols = append(w.symbols, sym)\n}\n\n// walkType processes symbols related to a type expression. path is path of\n// nested type identifiers to the type expression.\nfunc (w *symbolWalker) walkType(typ ast.Expr, path ...*ast.Ident) {\n\tswitch st := typ.(type) {\n\tcase *ast.StructType:\n\t\tfor _, field := range st.Fields.List {\n\t\t\tw.walkField(field, protocol.Field, protocol.Field, path...)\n\t\t}\n\tcase *ast.InterfaceType:\n\t\tfor _, field := range st.Methods.List {\n\t\t\tw.walkField(field, protocol.Interface, protocol.Method, path...)\n\t\t}\n\t}\n}\n\n// walkField processes symbols related to the struct field or interface method.\n//\n// unnamedKind and namedKind are the symbol kinds if the field is resp. unnamed\n// or named. path is the path of nested identifiers containing the field.\nfunc (w *symbolWalker) walkField(field *ast.Field, unnamedKind, namedKind protocol.SymbolKind, path ...*ast.Ident) {\n\tif len(field.Names) == 0 {\n\t\tswitch typ := field.Type.(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\t// embedded qualified type\n\t\t\tw.declare(typ.Sel.Name, unnamedKind, field, path...)\n\t\tdefault:\n\t\t\tw.declare(types.ExprString(field.Type), unnamedKind, field, path...)\n\t\t}\n\t}\n\tfor _, name := range field.Names {\n\t\tw.declare(name.Name, namedKind, name, path...)\n\t\tw.walkType(field.Type, append(path, name)...)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/symbols.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"runtime\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/symbols\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Symbols extracts and returns symbol information for every file contained in\n// a loaded package. It awaits snapshot loading.\n//\n// If workspaceOnly is set, this only includes symbols from files in a\n// workspace package. Otherwise, it returns symbols from all loaded packages.\nfunc (s *Snapshot) Symbols(ctx context.Context, ids ...PackageID) ([]*symbols.Package, error) {\n\tmeta := s.MetadataGraph()\n\n\tres := make([]*symbols.Package, len(ids))\n\tvar g errgroup.Group\n\tg.SetLimit(runtime.GOMAXPROCS(-1)) // symbolizing is cpu bound\n\tfor i, id := range ids {\n\t\tg.Go(func() error {\n\t\t\tmp := meta.Packages[id]\n\t\t\tif mp == nil {\n\t\t\t\treturn bug.Errorf(\"missing metadata for %q\", id)\n\t\t\t}\n\n\t\t\tkey, fhs, err := symbolKey(ctx, mp, s)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif data, err := filecache.Get(symbolsKind, key); err == nil {\n\t\t\t\tres[i] = symbols.Decode(data)\n\t\t\t\treturn nil\n\t\t\t} else if err != filecache.ErrNotFound {\n\t\t\t\tbug.Reportf(\"internal error reading symbol data: %v\", err)\n\t\t\t}\n\n\t\t\tpgfs, err := s.view.parseCache.parseFiles(ctx, token.NewFileSet(), parsego.Full&^parser.ParseComments, false, fhs...)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpkg := symbols.New(pgfs)\n\n\t\t\t// Store the resulting data in the cache.\n\t\t\tgo func() {\n\t\t\t\tdata := pkg.Encode()\n\t\t\t\tif err := filecache.Set(symbolsKind, key, data); err != nil {\n\t\t\t\t\tevent.Error(ctx, fmt.Sprintf(\"storing symbol data for %s\", id), err)\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tres[i] = pkg\n\t\t\treturn nil\n\t\t})\n\t}\n\n\treturn res, g.Wait()\n}\n\nfunc symbolKey(ctx context.Context, mp *metadata.Package, fs file.Source) (file.Hash, []file.Handle, error) {\n\tseen := make(map[protocol.DocumentURI]bool)\n\tvar fhs []file.Handle\n\tfor _, list := range [][]protocol.DocumentURI{mp.GoFiles, mp.CompiledGoFiles} {\n\t\tfor _, uri := range list {\n\t\t\tif !seen[uri] {\n\t\t\t\tseen[uri] = true\n\t\t\t\tfh, err := fs.ReadFile(ctx, uri)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn file.Hash{}, nil, err // context cancelled\n\t\t\t\t}\n\t\t\t\tfhs = append(fhs, fh)\n\t\t\t}\n\t\t}\n\t}\n\n\thasher := sha256.New()\n\tfmt.Fprintf(hasher, \"symbols: %s\\n\", mp.PkgPath)\n\tfmt.Fprintf(hasher, \"files: %d\\n\", len(fhs))\n\tfor _, fh := range fhs {\n\t\tfmt.Fprintln(hasher, fh.Identity())\n\t}\n\tvar hash file.Hash\n\thasher.Sum(hash[:0])\n\treturn hash, fhs, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/testfuncs/match.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testfuncs\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// The functions in this file are copies of those from the testing package.\n//\n// https://cs.opensource.google/go/go/+/refs/tags/go1.22.5:src/testing/match.go\n\n// uniqueName creates a unique name for the given parent and subname by affixing\n// it with one or more counts, if necessary.\nfunc (b *indexBuilder) uniqueName(parent, subname string) string {\n\tbase := parent + \"/\" + subname\n\n\tfor {\n\t\tn := b.subNames[base]\n\t\tif n < 0 {\n\t\t\tpanic(\"subtest count overflow\")\n\t\t}\n\t\tb.subNames[base] = n + 1\n\n\t\tif n == 0 && subname != \"\" {\n\t\t\tprefix, nn := parseSubtestNumber(base)\n\t\t\tif len(prefix) < len(base) && nn < b.subNames[prefix] {\n\t\t\t\t// This test is explicitly named like \"parent/subname#NN\",\n\t\t\t\t// and #NN was already used for the NNth occurrence of \"parent/subname\".\n\t\t\t\t// Loop to add a disambiguating suffix.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn base\n\t\t}\n\n\t\tname := fmt.Sprintf(\"%s#%02d\", base, n)\n\t\tif b.subNames[name] != 0 {\n\t\t\t// This is the nth occurrence of base, but the name \"parent/subname#NN\"\n\t\t\t// collides with the first occurrence of a subtest *explicitly* named\n\t\t\t// \"parent/subname#NN\". Try the next number.\n\t\t\tcontinue\n\t\t}\n\n\t\treturn name\n\t}\n}\n\n// parseSubtestNumber splits a subtest name into a \"#%02d\"-formatted int\n// suffix (if present), and a prefix preceding that suffix (always).\nfunc parseSubtestNumber(s string) (prefix string, nn int) {\n\ti := strings.LastIndex(s, \"#\")\n\tif i < 0 {\n\t\treturn s, 0\n\t}\n\n\tprefix, suffix := s[:i], s[i+1:]\n\tif len(suffix) < 2 || (len(suffix) > 2 && suffix[0] == '0') {\n\t\t// Even if suffix is numeric, it is not a possible output of a \"%02\" format\n\t\t// string: it has either too few digits or too many leading zeroes.\n\t\treturn s, 0\n\t}\n\tif suffix == \"00\" {\n\t\tif !strings.HasSuffix(prefix, \"/\") {\n\t\t\t// We only use \"#00\" as a suffix for subtests named with the empty\n\t\t\t// string — it isn't a valid suffix if the subtest name is non-empty.\n\t\t\treturn s, 0\n\t\t}\n\t}\n\n\tn, err := strconv.ParseInt(suffix, 10, 32)\n\tif err != nil || n < 0 {\n\t\treturn s, 0\n\t}\n\treturn prefix, int(n)\n}\n\n// rewrite rewrites a subname to having only printable characters and no white\n// space.\nfunc rewrite(s string) string {\n\tb := []byte{}\n\tfor _, r := range s {\n\t\tswitch {\n\t\tcase isSpace(r):\n\t\t\tb = append(b, '_')\n\t\tcase !strconv.IsPrint(r):\n\t\t\ts := strconv.QuoteRune(r)\n\t\t\tb = append(b, s[1:len(s)-1]...)\n\t\tdefault:\n\t\t\tb = append(b, string(r)...)\n\t\t}\n\t}\n\treturn string(b)\n}\n\nfunc isSpace(r rune) bool {\n\tif r < 0x2000 {\n\t\tswitch r {\n\t\t// Note: not the same as Unicode Z class.\n\t\tcase '\\t', '\\n', '\\v', '\\f', '\\r', ' ', 0x85, 0xA0, 0x1680:\n\t\t\treturn true\n\t\t}\n\t} else {\n\t\tif r <= 0x200a {\n\t\t\treturn true\n\t\t}\n\t\tswitch r {\n\t\tcase 0x2028, 0x2029, 0x202f, 0x205f, 0x3000:\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/cache/testfuncs/tests.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testfuncs\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// An Index records the test set of a package.\ntype Index struct {\n\tpkg gobPackage\n}\n\n// Decode decodes the given gob-encoded data as an Index.\nfunc Decode(data []byte) *Index {\n\tvar pkg gobPackage\n\tpackageCodec.Decode(data, &pkg)\n\treturn &Index{pkg}\n}\n\n// Encode encodes the receiver as gob-encoded data.\nfunc (index *Index) Encode() []byte {\n\treturn packageCodec.Encode(index.pkg)\n}\n\nfunc (index *Index) All() []Result {\n\tvar results []Result\n\tfor _, file := range index.pkg.Files {\n\t\tfor _, test := range file.Tests {\n\t\t\tresults = append(results, test.result())\n\t\t}\n\t}\n\treturn results\n}\n\n// A Result reports a test function\ntype Result struct {\n\tLocation protocol.Location // location of the test\n\tName     string            // name of the test\n}\n\n// NewIndex returns a new index of method-set information for all\n// package-level types in the specified package.\nfunc NewIndex(files []*parsego.File, info *types.Info) *Index {\n\tb := &indexBuilder{\n\t\tfileIndex: make(map[protocol.DocumentURI]int),\n\t\tsubNames:  make(map[string]int),\n\t\tvisited:   make(map[*types.Func]bool),\n\t}\n\treturn b.build(files, info)\n}\n\n// build adds to the index all tests of the specified package.\nfunc (b *indexBuilder) build(files []*parsego.File, info *types.Info) *Index {\n\tfor _, file := range files {\n\t\tif !strings.HasSuffix(file.Tok.Name(), \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, decl := range file.File.Decls {\n\t\t\tdecl, ok := decl.(*ast.FuncDecl)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobj, ok := info.ObjectOf(decl.Name).(*types.Func)\n\t\t\tif !ok || !obj.Exported() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// error.Error has empty Position, PkgPath, and ObjectPath.\n\t\t\tif obj.Pkg() == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tisTest, isExample := isTestOrExample(obj)\n\t\t\tif !isTest && !isExample {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar t gobTest\n\t\t\tt.Name = decl.Name.Name\n\t\t\tt.Location.URI = file.URI\n\t\t\tt.Location.Range, _ = file.NodeRange(decl)\n\n\t\t\ti, ok := b.fileIndex[t.Location.URI]\n\t\t\tif !ok {\n\t\t\t\ti = len(b.Files)\n\t\t\t\tb.Files = append(b.Files, gobFile{})\n\t\t\t\tb.fileIndex[t.Location.URI] = i\n\t\t\t}\n\n\t\t\tb.Files[i].Tests = append(b.Files[i].Tests, t)\n\t\t\tb.visited[obj] = true\n\n\t\t\t// Check for subtests\n\t\t\tif isTest {\n\t\t\t\tb.Files[i].Tests = append(b.Files[i].Tests, b.findSubtests(t, decl.Type, decl.Body, file, files, info)...)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn &Index{pkg: b.gobPackage}\n}\n\nfunc (b *indexBuilder) findSubtests(parent gobTest, typ *ast.FuncType, body *ast.BlockStmt, file *parsego.File, files []*parsego.File, info *types.Info) []gobTest {\n\tif body == nil {\n\t\treturn nil\n\t}\n\n\t// If the [testing.T] parameter is unnamed, the func cannot call\n\t// [testing.T.Run] and thus cannot create any subtests\n\tif len(typ.Params.List[0].Names) == 0 {\n\t\treturn nil\n\t}\n\n\t// This \"can't fail\" because testKind should guarantee that the function has\n\t// one parameter and the check above guarantees that parameter is named\n\tparam := info.ObjectOf(typ.Params.List[0].Names[0])\n\n\t// Find statements of form t.Run(name, func(...) {...}) where t is the\n\t// parameter of the enclosing test function.\n\tvar tests []gobTest\n\tfor _, stmt := range body.List {\n\t\texpr, ok := stmt.(*ast.ExprStmt)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tcall, ok := expr.X.(*ast.CallExpr)\n\t\tif !ok || len(call.Args) != 2 {\n\t\t\tcontinue\n\t\t}\n\t\tfun, ok := call.Fun.(*ast.SelectorExpr)\n\t\tif !ok || fun.Sel.Name != \"Run\" {\n\t\t\tcontinue\n\t\t}\n\t\trecv, ok := fun.X.(*ast.Ident)\n\t\tif !ok || info.ObjectOf(recv) != param {\n\t\t\tcontinue\n\t\t}\n\n\t\tsig, ok := info.TypeOf(call.Args[1]).(*types.Signature)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif _, ok := testKind(sig); !ok {\n\t\t\tcontinue // subtest has wrong signature\n\t\t}\n\n\t\tval := info.Types[call.Args[0]].Value // may be zero\n\t\tif val == nil || val.Kind() != constant.String {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar t gobTest\n\t\tt.Name = b.uniqueName(parent.Name, rewrite(constant.StringVal(val)))\n\t\tt.Location.URI = file.URI\n\t\tt.Location.Range, _ = file.NodeRange(call)\n\t\ttests = append(tests, t)\n\n\t\tfn, typ, body := findFunc(files, info, body, call.Args[1])\n\t\tif typ == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Function literals don't have an associated object\n\t\tif fn == nil {\n\t\t\ttests = append(tests, b.findSubtests(t, typ, body, file, files, info)...)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Never recurse if the second argument is a top-level test function\n\t\tif isTest, _ := isTestOrExample(fn); isTest {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Don't recurse into functions that have already been visited\n\t\tif b.visited[fn] {\n\t\t\tcontinue\n\t\t}\n\n\t\tb.visited[fn] = true\n\t\ttests = append(tests, b.findSubtests(t, typ, body, file, files, info)...)\n\t}\n\treturn tests\n}\n\n// findFunc finds the type and body of the given expr, which may be a function\n// literal or reference to a declared function. If the expression is a declared\n// function, findFunc returns its [types.Func]. If the expression is a function\n// literal, findFunc returns nil for the first return value. If no function is\n// found, findFunc returns (nil, nil, nil).\nfunc findFunc(files []*parsego.File, info *types.Info, body *ast.BlockStmt, expr ast.Expr) (*types.Func, *ast.FuncType, *ast.BlockStmt) {\n\tvar obj types.Object\n\tswitch arg := expr.(type) {\n\tcase *ast.FuncLit:\n\t\treturn nil, arg.Type, arg.Body\n\n\tcase *ast.Ident:\n\t\tobj = info.ObjectOf(arg)\n\t\tif obj == nil {\n\t\t\treturn nil, nil, nil\n\t\t}\n\n\tcase *ast.SelectorExpr:\n\t\t// Look for methods within the current package. We will not handle\n\t\t// imported functions and methods for now, as that would require access\n\t\t// to the source of other packages and would be substantially more\n\t\t// complex. However, those cases should be rare.\n\t\tsel, ok := info.Selections[arg]\n\t\tif !ok {\n\t\t\treturn nil, nil, nil\n\t\t}\n\t\tobj = sel.Obj()\n\n\tdefault:\n\t\treturn nil, nil, nil\n\t}\n\n\tif v, ok := obj.(*types.Var); ok {\n\t\t// TODO: Handle vars. This could handled by walking over the body (and\n\t\t// the file), but that doesn't account for assignment. If the variable\n\t\t// is assigned multiple times, we could easily get the wrong one.\n\t\t_, _ = v, body\n\t\treturn nil, nil, nil\n\t}\n\n\tfor _, file := range files {\n\t\t// Skip files that don't contain the object (there should only be a\n\t\t// single file that _does_ contain it)\n\t\tif _, err := safetoken.Offset(file.Tok, obj.Pos()); err != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, decl := range file.File.Decls {\n\t\t\tdecl, ok := decl.(*ast.FuncDecl)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif info.ObjectOf(decl.Name) == obj {\n\t\t\t\treturn obj.(*types.Func), decl.Type, decl.Body\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, nil, nil\n}\n\n// isTestOrExample reports whether the given func is a testing func or an\n// example func (or neither). isTestOrExample returns (true, false) for testing\n// funcs, (false, true) for example funcs, and (false, false) otherwise.\nfunc isTestOrExample(fn *types.Func) (isTest, isExample bool) {\n\tsig := fn.Type().(*types.Signature)\n\tif sig.Params().Len() == 0 &&\n\t\tsig.Results().Len() == 0 {\n\t\treturn false, isTestName(fn.Name(), \"Example\")\n\t}\n\n\tkind, ok := testKind(sig)\n\tif !ok {\n\t\treturn false, false\n\t}\n\tswitch kind.Name() {\n\tcase \"T\":\n\t\treturn isTestName(fn.Name(), \"Test\"), false\n\tcase \"B\":\n\t\treturn isTestName(fn.Name(), \"Benchmark\"), false\n\tcase \"F\":\n\t\treturn isTestName(fn.Name(), \"Fuzz\"), false\n\tdefault:\n\t\treturn false, false // \"can't happen\" (see testKind)\n\t}\n}\n\n// isTestName reports whether name is a valid test name for the test kind\n// indicated by the given prefix (\"Test\", \"Benchmark\", etc.).\n//\n// Adapted from go/analysis/passes/tests.\nfunc isTestName(name, prefix string) bool {\n\tsuffix, ok := strings.CutPrefix(name, prefix)\n\tif !ok {\n\t\treturn false\n\t}\n\tif len(suffix) == 0 {\n\t\t// \"Test\" is ok.\n\t\treturn true\n\t}\n\tr, _ := utf8.DecodeRuneInString(suffix)\n\treturn !unicode.IsLower(r)\n}\n\n// testKind returns the parameter type TypeName of a test, benchmark, or fuzz\n// function (one of testing.[TBF]).\nfunc testKind(sig *types.Signature) (*types.TypeName, bool) {\n\tif sig.Params().Len() != 1 ||\n\t\tsig.Results().Len() != 0 {\n\t\treturn nil, false\n\t}\n\n\tptr, ok := sig.Params().At(0).Type().(*types.Pointer)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\n\tnamed, ok := ptr.Elem().(*types.Named)\n\tif !ok || named.Obj().Pkg() == nil || named.Obj().Pkg().Path() != \"testing\" {\n\t\treturn nil, false\n\t}\n\n\tswitch named.Obj().Name() {\n\tcase \"T\", \"B\", \"F\":\n\t\treturn named.Obj(), true\n\t}\n\treturn nil, false\n}\n\n// An indexBuilder builds an index for a single package.\ntype indexBuilder struct {\n\tgobPackage\n\tfileIndex map[protocol.DocumentURI]int\n\tsubNames  map[string]int\n\tvisited   map[*types.Func]bool\n}\n\n// -- serial format of index --\n\n// (The name says gob but in fact we use frob.)\nvar packageCodec = frob.CodecFor[gobPackage]()\n\n// A gobPackage records the test set of each package-level type for a single package.\ntype gobPackage struct {\n\tFiles []gobFile\n}\n\ntype gobFile struct {\n\tTests []gobTest\n}\n\n// A gobTest records the name, type, and position of a single test.\ntype gobTest struct {\n\tLocation protocol.Location // location of the test\n\tName     string            // name of the test\n}\n\nfunc (t *gobTest) result() Result {\n\treturn Result(*t)\n}\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typerefs extracts symbol-level reachability information\n// from the syntax of a Go package.\n//\n// # Background\n//\n// The goal of this analysis is to determine, for each package P, a nearly\n// minimal set of packages that could affect the type checking of P. This set\n// may contain false positives, but the smaller this set the better we can\n// invalidate and prune packages in gopls.\n//\n// More precisely, for each package P we define the set of \"reachable\" packages\n// from P as the set of packages that may affect the (deep) export data of the\n// direct dependencies of P. By this definition, the complement of this set\n// cannot affect any information derived from type checking P, such as\n// diagnostics, cross references, or method sets. Therefore we need not\n// invalidate any results for P when a package in the complement of this set\n// changes.\n//\n// # Computing references\n//\n// For a given declaration D, references are computed based on identifiers or\n// dotted identifiers referenced in the declaration of D, that may affect\n// the type of D. However, these references reflect only local knowledge of the\n// package and its dependency metadata, and do not depend on any analysis of\n// the dependencies themselves. This allows the reference information for\n// a package to be cached independent of all others.\n//\n// Specifically, if a referring identifier I appears in the declaration, we\n// record an edge from D to each object possibly referenced by I. We search for\n// references within type syntax, but do not actually type-check, so we can't\n// reliably determine whether an expression is a type or a term, or whether a\n// function is a builtin or generic. For example, the type of x in var x =\n// p.F(W) only depends on W if p.F is a builtin or generic function, which we\n// cannot know without type-checking package p. So we may over-approximate in\n// this way.\n//\n//   - If I is declared in the current package, record a reference to its\n//     declaration.\n//   - Otherwise, if there are any dot imports in the current\n//     file and I is exported, record a (possibly dangling) edge to\n//     the corresponding declaration in each dot-imported package.\n//\n// If a dotted identifier q.I appears in the declaration, we\n// perform a similar operation:\n//\n//   - If q is declared in the current package, we record a reference to that\n//     object. It may be a var or const that has a field or method I.\n//   - Otherwise, if q is a valid import name based on imports in the current file\n//     and the provided metadata for dependency package names, record a\n//     reference to the object I in that package.\n//   - Additionally, handle the case where Q is exported, and Q.I may refer to\n//     a field or method in a dot-imported package.\n//\n// That is essentially the entire algorithm, though there is some subtlety to\n// visiting the set of identifiers or dotted identifiers that may affect the\n// declaration type. See the visitDeclOrSpec function for the details of this\n// analysis. Notably, we also skip identifiers that refer to type parameters in\n// generic declarations.\n//\n// # Graph optimizations\n//\n// The references extracted from the syntax are used to construct\n// edges between nodes representing declarations. Edges are of two\n// kinds: internal references, from one package-level declaration to\n// another; and external references, from a symbol in this package to\n// a symbol imported from a direct dependency.\n//\n// Once the symbol reference graph is constructed, we find its\n// strongly connected components (SCCs) using Tarjan's algorithm.\n// As we coalesce the nodes of each SCC we compute the union of\n// external references reached by each package-level declaration.\n// The final result is the mapping from each exported package-level\n// declaration to the set of external (imported) declarations that it\n// reaches.\n//\n// Because it is common for many package members to have the same\n// reachability, the result takes the form of a set of equivalence\n// classes, each mapping a set of package-level declarations to a set\n// of external symbols. We use a hash table to canonicalize sets so that\n// repeated occurrences of the same set (which are common) are only\n// represented once in memory or in the file system.\n// For example, all declarations that ultimately reference only\n// {fmt.Println,strings.Join} would be classed as equivalent.\n//\n// This approach was inspired by the Hash-Value Numbering (HVN)\n// optimization described by Hardekopf and Lin. See\n// golang.org/x/tools/go/pointer/hvn.go for an implementation. (Like\n// pointer analysis, this problem is fundamentally one of graph\n// reachability.) The HVN algorithm takes the compression a step\n// further by preserving the topology of the SCC DAG, in which edges\n// represent \"is a superset of\" constraints. Redundant edges that\n// don't increase the solution can be deleted. We could apply the same\n// technique here to further reduce the worst-case size of the result,\n// but the current implementation seems adequate.\n//\n// # API\n//\n// The main entry point for this analysis is the [Encode] function,\n// which implements the analysis described above for one package, and\n// encodes the result as a binary message.\n//\n// The [Decode] function decodes the message into a usable form: a set\n// of equivalence classes. The decoder uses a shared [PackageIndex] to\n// enable more compact representations of sets of packages\n// ([PackageSet]) during the global reacahability computation.\n//\n// The [BuildPackageGraph] constructor implements a whole-graph analysis similar\n// to that which will be implemented by gopls, but for various reasons the\n// logic for this analysis will eventually live in the\n// [golang.org/x/tools/gopls/internal/cache] package. Nevertheless,\n// BuildPackageGraph and its test serve to verify the syntactic analysis, and\n// may serve as a proving ground for new optimizations of the whole-graph analysis.\n//\n// # Export data is insufficient\n//\n// At first it may seem that the simplest way to implement this analysis would\n// be to consider the types.Packages of the dependencies of P, for example\n// during export. After all, it makes sense that the type checked packages\n// themselves could describe their dependencies. However, this does not work as\n// type information does not describe certain syntactic relationships.\n//\n// For example, the following scenarios cause type information to miss\n// syntactic relationships:\n//\n// Named type forwarding:\n//\n//\tpackage a; type A b.B\n//\tpackage b; type B int\n//\n// Aliases:\n//\n//\tpackage a; func A(f b.B)\n//\tpackage b; type B = func()\n//\n// Initializers:\n//\n//\tpackage a; var A = b.B()\n//\tpackage b; func B() string { return \"hi\" }\n//\n// Use of the unsafe package:\n//\n//\tpackage a; type A [unsafe.Sizeof(B{})]int\n//\tpackage b; type B struct { f1, f2, f3 int }\n//\n// In all of these examples, types do not contain information about the edge\n// between the a.A and b.B declarations.\npackage typerefs\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/packageset.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typerefs\n\nimport (\n\t\"fmt\"\n\t\"math/bits\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n)\n\n// PackageIndex stores common data to enable efficient representation of\n// references and package sets.\ntype PackageIndex struct {\n\t// For now, PackageIndex just indexes package ids, to save space and allow for\n\t// faster unions via sparse int vectors.\n\tmu  sync.Mutex\n\tids []metadata.PackageID\n\tm   map[metadata.PackageID]IndexID\n}\n\n// NewPackageIndex creates a new PackageIndex instance for use in building\n// reference and package sets.\nfunc NewPackageIndex() *PackageIndex {\n\treturn &PackageIndex{\n\t\tm: make(map[metadata.PackageID]IndexID),\n\t}\n}\n\n// IndexID returns the packageIdx referencing id, creating one if id is not yet\n// tracked by the receiver.\nfunc (index *PackageIndex) IndexID(id metadata.PackageID) IndexID {\n\tindex.mu.Lock()\n\tdefer index.mu.Unlock()\n\tif i, ok := index.m[id]; ok {\n\t\treturn i\n\t}\n\ti := IndexID(len(index.ids))\n\tindex.m[id] = i\n\tindex.ids = append(index.ids, id)\n\treturn i\n}\n\n// PackageID returns the PackageID for idx.\n//\n// idx must have been created by this PackageIndex instance.\nfunc (index *PackageIndex) PackageID(idx IndexID) metadata.PackageID {\n\tindex.mu.Lock()\n\tdefer index.mu.Unlock()\n\treturn index.ids[idx]\n}\n\n// A PackageSet is a set of metadata.PackageIDs, optimized for inuse memory\n// footprint and efficient union operations.\ntype PackageSet struct {\n\t// PackageSet is a sparse int vector of package indexes from parent.\n\tparent *PackageIndex\n\tsparse map[int]blockType // high bits in key, set of low bits in value\n}\n\ntype blockType = uint // type of each sparse vector element\nconst blockSize = bits.UintSize\n\n// NewSet creates a new PackageSet bound to this PackageIndex instance.\n//\n// PackageSets may only be combined with other PackageSets from the same\n// instance.\nfunc (index *PackageIndex) NewSet() *PackageSet {\n\treturn &PackageSet{\n\t\tparent: index,\n\t\tsparse: make(map[int]blockType),\n\t}\n}\n\n// DeclaringPackage returns the ID of the symbol's declaring package.\n// The package index must be the one used during decoding.\nfunc (index *PackageIndex) DeclaringPackage(sym Symbol) metadata.PackageID {\n\treturn index.PackageID(sym.Package)\n}\n\n// Add records a new element in the package set, for the provided package ID.\nfunc (s *PackageSet) AddPackage(id metadata.PackageID) {\n\ts.Add(s.parent.IndexID(id))\n}\n\n// Add records a new element in the package set.\n// It is the caller's responsibility to ensure that idx was created with the\n// same PackageIndex as the PackageSet.\nfunc (s *PackageSet) Add(idx IndexID) {\n\ti := int(idx)\n\ts.sparse[i/blockSize] |= 1 << (i % blockSize)\n}\n\n// Union records all elements from other into the receiver, mutating the\n// receiver set but not the argument set. The receiver must not be nil, but the\n// argument set may be nil.\n//\n// Precondition: both package sets were created with the same PackageIndex.\nfunc (s *PackageSet) Union(other *PackageSet) {\n\tif other == nil {\n\t\treturn // e.g. unsafe\n\t}\n\tif other.parent != s.parent {\n\t\tpanic(\"other set is from a different PackageIndex instance\")\n\t}\n\tfor k, v := range other.sparse {\n\t\tif v0 := s.sparse[k]; v0 != v {\n\t\t\ts.sparse[k] = v0 | v\n\t\t}\n\t}\n}\n\n// Contains reports whether id is contained in the receiver set.\nfunc (s *PackageSet) Contains(id metadata.PackageID) bool {\n\ti := int(s.parent.IndexID(id))\n\treturn s.sparse[i/blockSize]&(1<<(i%blockSize)) != 0\n}\n\n// Elems calls f for each element of the set in ascending order.\nfunc (s *PackageSet) Elems(f func(IndexID)) {\n\tfor i, v := range moremaps.Sorted(s.sparse) {\n\t\tfor b := range blockSize {\n\t\t\tif (v & (1 << b)) != 0 {\n\t\t\t\tf(IndexID(i*blockSize + b))\n\t\t\t}\n\t\t}\n\t}\n}\n\n// String returns a human-readable representation of the set: {A, B, ...}.\nfunc (s *PackageSet) String() string {\n\tvar ids []string\n\ts.Elems(func(id IndexID) {\n\t\tids = append(ids, string(s.parent.PackageID(id)))\n\t})\n\treturn fmt.Sprintf(\"{%s}\", strings.Join(ids, \", \"))\n}\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/pkggraph_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typerefs_test\n\n// This file is logically part of the test in pkgrefs_test.go: that\n// file defines the test assertion logic; this file provides a\n// reference implementation of a client of the typerefs package.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"runtime\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nconst (\n\t// trace enables additional trace output to stdout, for debugging.\n\t//\n\t// Warning: produces a lot of output! Best to run with small package queries.\n\ttrace = false\n)\n\n// A Package holds reference information for a single package.\ntype Package struct {\n\t// metapkg holds metapkg about this package and its dependencies.\n\tmetapkg *metadata.Package\n\n\t// transitiveRefs records, for each exported declaration in the package, the\n\t// transitive set of packages within the containing graph that are\n\t// transitively reachable through references, starting with the given decl.\n\ttransitiveRefs map[string]*typerefs.PackageSet\n\n\t// ReachesByDeps records the set of packages in the containing graph whose\n\t// syntax may affect the current package's types. See the package\n\t// documentation for more details of what this means.\n\tReachesByDeps *typerefs.PackageSet\n}\n\n// A PackageGraph represents a fully analyzed graph of packages and their\n// dependencies.\ntype PackageGraph struct {\n\tpkgIndex *typerefs.PackageIndex\n\tmeta     metadata.Source\n\tparse    func(context.Context, protocol.DocumentURI) (*parsego.File, error)\n\n\tmu       sync.Mutex\n\tpackages map[metadata.PackageID]*futurePackage\n}\n\n// BuildPackageGraph analyzes the package graph for the requested ids, whose\n// metadata is described by meta.\n//\n// The provided parse function is used to parse the CompiledGoFiles of each package.\n//\n// The resulting PackageGraph is fully evaluated, and may be investigated using\n// the Package method.\n//\n// See the package documentation for more information on the package reference\n// algorithm.\nfunc BuildPackageGraph(ctx context.Context, meta metadata.Source, ids []metadata.PackageID, parse func(context.Context, protocol.DocumentURI) (*parsego.File, error)) (*PackageGraph, error) {\n\tg := &PackageGraph{\n\t\tpkgIndex: typerefs.NewPackageIndex(),\n\t\tmeta:     meta,\n\t\tparse:    parse,\n\t\tpackages: make(map[metadata.PackageID]*futurePackage),\n\t}\n\tmetadata.SortPostOrder(meta, ids)\n\n\tworkers := runtime.GOMAXPROCS(0)\n\tif trace {\n\t\tworkers = 1\n\t}\n\n\tvar eg errgroup.Group\n\teg.SetLimit(workers)\n\tfor _, id := range ids {\n\t\teg.Go(func() error {\n\t\t\t_, err := g.Package(ctx, id)\n\t\t\treturn err\n\t\t})\n\t}\n\treturn g, eg.Wait()\n}\n\n// futurePackage is a future result of analyzing a package, for use from Package only.\ntype futurePackage struct {\n\tdone chan struct{}\n\tpkg  *Package\n\terr  error\n}\n\n// Package gets the result of analyzing references for a single package.\nfunc (g *PackageGraph) Package(ctx context.Context, id metadata.PackageID) (*Package, error) {\n\tg.mu.Lock()\n\tfut, ok := g.packages[id]\n\tif ok {\n\t\tg.mu.Unlock()\n\t\tselect {\n\t\tcase <-fut.done:\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t} else {\n\t\tfut = &futurePackage{done: make(chan struct{})}\n\t\tg.packages[id] = fut\n\t\tg.mu.Unlock()\n\t\tfut.pkg, fut.err = g.buildPackage(ctx, id)\n\t\tclose(fut.done)\n\t}\n\treturn fut.pkg, fut.err\n}\n\n// buildPackage parses a package and extracts its reference graph. It should\n// only be called from Package.\nfunc (g *PackageGraph) buildPackage(ctx context.Context, id metadata.PackageID) (*Package, error) {\n\tp := &Package{\n\t\tmetapkg:        g.meta.Metadata(id),\n\t\ttransitiveRefs: make(map[string]*typerefs.PackageSet),\n\t}\n\tvar files []*parsego.File\n\tfor _, filename := range p.metapkg.CompiledGoFiles {\n\t\tf, err := g.parse(ctx, filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfiles = append(files, f)\n\t}\n\timports := make(map[metadata.ImportPath]*metadata.Package)\n\tfor impPath, depID := range p.metapkg.DepsByImpPath {\n\t\tif depID != \"\" {\n\t\t\timports[impPath] = g.meta.Metadata(depID)\n\t\t}\n\t}\n\n\t// Compute the symbol-level dependencies through this package.\n\tdata := typerefs.Encode(files, imports)\n\n\t// data can be persisted in a filecache, keyed\n\t// by hash(id, CompiledGoFiles, imports).\n\n\t//      This point separates the local preprocessing\n\t//  --  of a single package (above) from the global   --\n\t//      transitive reachability query (below).\n\n\t// classes records syntactic edges between declarations in this\n\t// package and declarations in this package or another\n\t// package. See the package documentation for a detailed\n\t// description of what these edges do (and do not) represent.\n\tclasses := typerefs.Decode(g.pkgIndex, data)\n\n\t// Debug\n\tif trace && len(classes) > 0 {\n\t\tvar buf bytes.Buffer\n\t\tfmt.Fprintf(&buf, \"%s\\n\", id)\n\t\tfor _, class := range classes {\n\t\t\tfor i, name := range class.Decls {\n\t\t\t\tif i == 0 {\n\t\t\t\t\tfmt.Fprintf(&buf, \"\\t\")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&buf, \" .%s\", name)\n\t\t\t}\n\t\t\t// Group symbols by package.\n\t\t\tvar prevID PackageID\n\t\t\tfor _, sym := range class.Refs {\n\t\t\t\tid := g.pkgIndex.DeclaringPackage(sym)\n\t\t\t\tif id != prevID {\n\t\t\t\t\tprevID = id\n\t\t\t\t\tfmt.Fprintf(&buf, \"\\n\\t\\t-> %s:\", id)\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&buf, \" .%s\", sym.Name)\n\t\t\t}\n\t\t\tfmt.Fprintln(&buf)\n\t\t}\n\t\tos.Stderr.Write(buf.Bytes())\n\t}\n\n\t// Now compute the transitive closure of packages reachable\n\t// from any exported symbol of this package.\n\tfor _, class := range classes {\n\t\tset := g.pkgIndex.NewSet()\n\n\t\t// The Refs slice is sorted by (PackageID, name),\n\t\t// so we can economize by calling g.Package only\n\t\t// when the package id changes.\n\t\tdepP := p\n\t\tfor _, sym := range class.Refs {\n\t\t\tsymPkgID := g.pkgIndex.DeclaringPackage(sym)\n\t\t\tif symPkgID == id {\n\t\t\t\tpanic(\"intra-package edge\")\n\t\t\t}\n\t\t\tif depP.metapkg.ID != symPkgID {\n\t\t\t\t// package changed\n\t\t\t\tvar err error\n\t\t\t\tdepP, err = g.Package(ctx, symPkgID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t\tset.Add(sym.Package)\n\t\t\tset.Union(depP.transitiveRefs[sym.Name])\n\t\t}\n\t\tfor _, name := range class.Decls {\n\t\t\tp.transitiveRefs[name] = set\n\t\t}\n\t}\n\n\t// Finally compute the union of transitiveRefs\n\t// across the direct deps of this package.\n\tbyDeps, err := g.reachesByDeps(ctx, p.metapkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tp.ReachesByDeps = byDeps\n\n\treturn p, nil\n}\n\n// reachesByDeps computes the set of packages that are reachable through\n// dependencies of the package m.\nfunc (g *PackageGraph) reachesByDeps(ctx context.Context, mp *metadata.Package) (*typerefs.PackageSet, error) {\n\ttransitive := g.pkgIndex.NewSet()\n\tfor _, depID := range mp.DepsByPkgPath {\n\t\tdep, err := g.Package(ctx, depID)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttransitive.AddPackage(dep.metapkg.ID)\n\t\tfor _, set := range dep.transitiveRefs {\n\t\t\ttransitive.Union(set)\n\t\t}\n\t}\n\treturn transitive, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/pkgrefs_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typerefs_test\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar (\n\tdir    = flag.String(\"dir\", \"\", \"dir to run go/packages from\")\n\tquery  = flag.String(\"query\", \"std\", \"go/packages load query to use for walkdecl tests\")\n\tverify = flag.Bool(\"verify\", true, \"whether to verify reachable packages using export data (may be slow on large graphs)\")\n)\n\ntype (\n\tpackageName    = metadata.PackageName\n\tPackageID      = metadata.PackageID\n\tImportPath     = metadata.ImportPath\n\tPackagePath    = metadata.PackagePath\n\tMetadata       = metadata.Package\n\tMetadataSource = metadata.Source\n)\n\n// TestBuildPackageGraph tests the BuildPackageGraph constructor, which uses\n// the reference analysis of the Refs function to build a graph of\n// relationships between packages.\n//\n// It simulates the operation of gopls at startup: packages are loaded via\n// go/packages, and their syntax+metadata analyzed to determine which packages\n// are reachable from others.\n//\n// The test then verifies that the 'load' graph (the graph of relationships in\n// export data) is a subgraph of the 'reach' graph constructed by\n// BuildPackageGraph. While doing so, it constructs some statistics about the\n// relative sizes of these graphs, along with the 'transitive imports' graph,\n// to report the effectiveness of the reachability analysis.\n//\n// The following flags affect this test:\n//   - dir sets the dir from which to run go/packages\n//   - query sets the go/packages query to load\n//   - verify toggles the verification w.r.t. the load graph (which may be\n//     prohibitively expensive with large queries).\nfunc TestBuildPackageGraph(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping with -short: loading the packages can take a long time with a cold cache\")\n\t}\n\ttestenv.NeedsGoBuild(t) // for go/packages\n\n\tt0 := time.Now()\n\texports, meta, err := loadPackages(*query, *verify)\n\tif err != nil {\n\t\tt.Fatalf(\"loading failed: %v\", err)\n\t}\n\tt.Logf(\"loaded %d packages in %v\", len(exports), time.Since(t0))\n\n\tctx := context.Background()\n\tvar ids []PackageID\n\tfor id := range exports {\n\t\tids = append(ids, id)\n\t}\n\tslices.Sort(ids)\n\n\tt0 = time.Now()\n\tg, err := BuildPackageGraph(ctx, meta, ids, newParser().parse)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tt.Logf(\"building package graph took %v\", time.Since(t0))\n\n\t// Collect information about the edges between packages for later analysis.\n\t//\n\t// We compare the following package graphs:\n\t//  - the imports graph: edges are transitive imports\n\t//  - the reaches graph: edges are reachability relationships through syntax\n\t//    of imports (as defined in the package doc)\n\t//  - the loads graph: edges are packages loaded through the export data of\n\t//    imports\n\t//\n\t// By definition, loads < reaches < imports.\n\ttype edgeSet map[PackageID]map[PackageID]bool\n\tvar (\n\t\timports    = make(edgeSet) // A imports B transitively\n\t\timportedBy = make(edgeSet) // A is imported by B transitively\n\t\treaches    = make(edgeSet) // A reaches B through top-level declaration syntax\n\t\treachedBy  = make(edgeSet) // A is reached by B through top-level declaration syntax\n\t\tloads      = make(edgeSet) // A loads B through export data of its direct dependencies\n\t\tloadedBy   = make(edgeSet) // A is loaded by B through export data of B's direct dependencies\n\t)\n\trecordEdge := func(from, to PackageID, fwd, rev edgeSet) {\n\t\tif fwd[from] == nil {\n\t\t\tfwd[from] = make(map[PackageID]bool)\n\t\t}\n\t\tfwd[from][to] = true\n\t\tif rev[to] == nil {\n\t\t\trev[to] = make(map[PackageID]bool)\n\t\t}\n\t\trev[to][from] = true\n\t}\n\n\texportedPackages := make(map[PackageID]*types.Package)\n\timportPackage := func(id PackageID) *types.Package {\n\t\texportFile := exports[id]\n\t\tif exportFile == \"\" {\n\t\t\treturn nil // no exported symbols\n\t\t}\n\t\tmp := meta.Metadata(id)\n\t\ttpkg, ok := exportedPackages[id]\n\t\tif !ok {\n\t\t\tpkgPath := string(mp.PkgPath)\n\t\t\ttpkg, err = importFromExportData(pkgPath, exportFile)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"importFromExportData(%s, %s) failed: %v\", pkgPath, exportFile, err)\n\t\t\t}\n\t\t\texportedPackages[id] = tpkg\n\t\t}\n\t\treturn tpkg\n\t}\n\n\tfor _, id := range ids {\n\t\tpkg, err := g.Package(ctx, id)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tpkg.ReachesByDeps.Elems(func(id2 typerefs.IndexID) {\n\t\t\trecordEdge(id, g.pkgIndex.PackageID(id2), reaches, reachedBy)\n\t\t})\n\n\t\timportMap := importMap(id, meta)\n\t\tfor _, id2 := range importMap {\n\t\t\trecordEdge(id, id2, imports, importedBy)\n\t\t}\n\n\t\tif *verify {\n\t\t\tfor _, depID := range meta.Metadata(id).DepsByPkgPath {\n\t\t\t\ttpkg := importPackage(depID)\n\t\t\t\tif tpkg == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor _, imp := range tpkg.Imports() {\n\t\t\t\t\tdepID, ok := importMap[PackagePath(imp.Path())]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"import map (len: %d) for %s missing imported types.Package %s\", len(importMap), id, imp.Path())\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\trecordEdge(id, depID, loads, loadedBy)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor depID := range loads[id] {\n\t\t\t\tif !pkg.ReachesByDeps.Contains(depID) {\n\t\t\t\t\tt.Errorf(\"package %s was imported by %s, but not detected as reachable\", depID, id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif testing.Verbose() {\n\t\tfmt.Printf(\"%-52s%8s%8s%8s%8s%8s%8s\\n\", \"package ID\", \"imp\", \"impBy\", \"reach\", \"reachBy\", \"load\", \"loadBy\")\n\t\tfor _, id := range ids {\n\t\t\tfmt.Printf(\"%-52s%8d%8d%8d%8d%8d%8d\\n\", id, len(imports[id]), len(importedBy[id]), len(reaches[id]), len(reachedBy[id]), len(loads[id]), len(loadedBy[id]))\n\t\t}\n\t\tfmt.Println(strings.Repeat(\"-\", 100))\n\t\tfmt.Printf(\"%-52s%8s%8s%8s%8s%8s%8s\\n\", \"package ID\", \"imp\", \"impBy\", \"reach\", \"reachBy\", \"load\", \"loadBy\")\n\n\t\tavg := func(m edgeSet) float64 {\n\t\t\tvar avg float64\n\t\t\tfor _, id := range ids {\n\t\t\t\ts := m[id]\n\t\t\t\tavg += float64(len(s)) / float64(len(ids))\n\t\t\t}\n\t\t\treturn avg\n\t\t}\n\t\tfmt.Printf(\"%52s%8.1f%8.1f%8.1f%8.1f%8.1f%8.1f\\n\", \"averages:\", avg(imports), avg(importedBy), avg(reaches), avg(reachedBy), avg(loads), avg(loadedBy))\n\t}\n}\n\nfunc importMap(id PackageID, meta MetadataSource) map[PackagePath]PackageID {\n\timports := make(map[PackagePath]PackageID)\n\tvar recordIDs func(PackageID)\n\trecordIDs = func(id PackageID) {\n\t\tmp := meta.Metadata(id)\n\t\tif _, ok := imports[mp.PkgPath]; ok {\n\t\t\treturn\n\t\t}\n\t\timports[mp.PkgPath] = id\n\t\tfor _, id := range mp.DepsByPkgPath {\n\t\t\trecordIDs(id)\n\t\t}\n\t}\n\tfor _, id := range meta.Metadata(id).DepsByPkgPath {\n\t\trecordIDs(id)\n\t}\n\treturn imports\n}\n\nfunc importFromExportData(pkgPath, exportFile string) (*types.Package, error) {\n\tfile, err := os.Open(exportFile)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tr, err := gcexportdata.NewReader(file)\n\tif err != nil {\n\t\tfile.Close() // ignore error\n\t\treturn nil, err\n\t}\n\tfset := token.NewFileSet()\n\ttpkg, err := gcexportdata.Read(r, fset, make(map[string]*types.Package), pkgPath)\n\tfile.Close() // ignore error\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// The export file reported by go/packages is produced by the compiler, which\n\t// has additional package dependencies due to inlining.\n\t//\n\t// Export and re-import so that we only observe dependencies from the\n\t// exported API.\n\tvar out bytes.Buffer\n\terr = gcexportdata.Write(&out, fset, tpkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn gcexportdata.Read(&out, token.NewFileSet(), make(map[string]*types.Package), pkgPath)\n}\n\nfunc BenchmarkBuildPackageGraph(b *testing.B) {\n\tt0 := time.Now()\n\texports, meta, err := loadPackages(*query, *verify)\n\tif err != nil {\n\t\tb.Fatalf(\"loading failed: %v\", err)\n\t}\n\tb.Logf(\"loaded %d packages in %v\", len(exports), time.Since(t0))\n\tctx := context.Background()\n\tvar ids []PackageID\n\tfor id := range exports {\n\t\tids = append(ids, id)\n\t}\n\n\tfor b.Loop() {\n\t\t_, err := BuildPackageGraph(ctx, meta, ids, newParser().parse)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n}\n\ntype memoizedParser struct {\n\tmu    sync.Mutex\n\tfiles map[protocol.DocumentURI]*futureParse\n}\n\ntype futureParse struct {\n\tdone chan struct{}\n\tpgf  *parsego.File\n\terr  error\n}\n\nfunc newParser() *memoizedParser {\n\treturn &memoizedParser{\n\t\tfiles: make(map[protocol.DocumentURI]*futureParse),\n\t}\n}\n\nfunc (p *memoizedParser) parse(ctx context.Context, uri protocol.DocumentURI) (*parsego.File, error) {\n\tdoParse := func(ctx context.Context, uri protocol.DocumentURI) (*parsego.File, error) {\n\t\t// TODO(adonovan): hoist this operation outside the benchmark critsec.\n\t\tcontent, err := os.ReadFile(uri.Path())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcontent = astutil.PurgeFuncBodies(content)\n\t\tpgf, _ := parsego.Parse(ctx, token.NewFileSet(), uri, content, parsego.Full, false)\n\t\treturn pgf, nil\n\t}\n\n\tp.mu.Lock()\n\tfut, ok := p.files[uri]\n\tif ok {\n\t\tp.mu.Unlock()\n\t\tselect {\n\t\tcase <-fut.done:\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t} else {\n\t\tfut = &futureParse{done: make(chan struct{})}\n\t\tp.files[uri] = fut\n\t\tp.mu.Unlock()\n\t\tfut.pgf, fut.err = doParse(ctx, uri)\n\t\tclose(fut.done)\n\t}\n\treturn fut.pgf, fut.err\n}\n\ntype mapMetadataSource struct {\n\tm map[PackageID]*Metadata\n}\n\nfunc (s mapMetadataSource) Metadata(id PackageID) *Metadata {\n\treturn s.m[id]\n}\n\n// This function is a compressed version of snapshot.load from the\n// internal/cache package, for use in testing.\n//\n// TODO(rfindley): it may be valuable to extract this logic from the snapshot,\n// since it is otherwise standalone.\nfunc loadPackages(query string, needExport bool) (map[PackageID]string, MetadataSource, error) {\n\tcfg := &packages.Config{\n\t\tDir: *dir,\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedCompiledGoFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedTypesSizes |\n\t\t\tpackages.NeedModule |\n\t\t\tpackages.NeedEmbedFiles |\n\t\t\tpackages.LoadMode(packagesinternal.DepsErrors) |\n\t\t\tpackages.NeedForTest,\n\t\tTests: true,\n\t}\n\tif needExport {\n\t\tcfg.Mode |= packages.NeedExportFile // ExportFile is not requested by gopls: this is used to verify reachability\n\t}\n\tpkgs, err := packages.Load(cfg, query)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tmeta := make(map[PackageID]*Metadata)\n\tvar buildMetadata func(pkg *packages.Package)\n\tbuildMetadata = func(pkg *packages.Package) {\n\t\tid := PackageID(pkg.ID)\n\t\tif meta[id] != nil {\n\t\t\treturn\n\t\t}\n\t\tmp := &Metadata{\n\t\t\tID:         id,\n\t\t\tPkgPath:    PackagePath(pkg.PkgPath),\n\t\t\tName:       packageName(pkg.Name),\n\t\t\tForTest:    PackagePath(pkg.ForTest),\n\t\t\tTypesSizes: pkg.TypesSizes,\n\t\t\tLoadDir:    cfg.Dir,\n\t\t\tModule:     pkg.Module,\n\t\t\tErrors:     pkg.Errors,\n\t\t\tDepsErrors: packagesinternal.GetDepsErrors(pkg),\n\t\t}\n\t\tmeta[id] = mp\n\n\t\tfor _, filename := range pkg.CompiledGoFiles {\n\t\t\tmp.CompiledGoFiles = append(mp.CompiledGoFiles, protocol.URIFromPath(filename))\n\t\t}\n\t\tfor _, filename := range pkg.GoFiles {\n\t\t\tmp.GoFiles = append(mp.GoFiles, protocol.URIFromPath(filename))\n\t\t}\n\n\t\tmp.DepsByImpPath = make(map[ImportPath]PackageID)\n\t\tmp.DepsByPkgPath = make(map[PackagePath]PackageID)\n\t\tfor importPath, imported := range pkg.Imports {\n\t\t\timportPath := ImportPath(importPath)\n\n\t\t\t// see note in gopls/internal/cache/load.go for an explanation of this check.\n\t\t\tif importPath != \"unsafe\" && len(imported.CompiledGoFiles) == 0 {\n\t\t\t\tmp.DepsByImpPath[importPath] = \"\" // missing\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tmp.DepsByImpPath[importPath] = PackageID(imported.ID)\n\t\t\tmp.DepsByPkgPath[PackagePath(imported.PkgPath)] = PackageID(imported.ID)\n\t\t\tbuildMetadata(imported)\n\t\t}\n\t}\n\n\texportFiles := make(map[PackageID]string)\n\tfor _, pkg := range pkgs {\n\t\texportFiles[PackageID(pkg.ID)] = pkg.ExportFile\n\t\tbuildMetadata(pkg)\n\t}\n\treturn exportFiles, &mapMetadataSource{meta}, nil\n}\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/refs.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typerefs\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\n// Encode analyzes the Go syntax trees of a package, constructs a\n// reference graph, and uses it to compute, for each exported\n// declaration, the set of exported symbols of directly imported\n// packages that it references, perhaps indirectly.\n//\n// It returns a serializable index of this information.\n// Use Decode to expand the result.\nfunc Encode(files []*parsego.File, imports map[metadata.ImportPath]*metadata.Package) []byte {\n\treturn index(files, imports)\n}\n\n// Decode decodes a serializable index of symbol\n// reachability produced by Encode.\n//\n// Because many declarations reference the exact same set of symbols,\n// the results are grouped into equivalence classes.\n// Classes are sorted by Decls[0], ascending.\n// The class with empty reachability is omitted.\n//\n// See the package documentation for more details as to what a\n// reference does (and does not) represent.\nfunc Decode(pkgIndex *PackageIndex, data []byte) []Class {\n\treturn decode(pkgIndex, data)\n}\n\n// A Class is a reachability equivalence class.\n//\n// It attests that each exported package-level declaration in Decls\n// references (perhaps indirectly) one of the external (imported)\n// symbols in Refs.\n//\n// Because many Decls reach the same Refs,\n// it is more efficient to group them into classes.\ntype Class struct {\n\tDecls []string // sorted set of names of exported decls with same reachability\n\tRefs  []Symbol // set of external symbols, in ascending (PackageID, Name) order\n}\n\n// A Symbol represents an external (imported) symbol\n// referenced by the analyzed package.\ntype Symbol struct {\n\tPackage IndexID // w.r.t. PackageIndex passed to decoder\n\tName    string\n}\n\n// An IndexID is a small integer that uniquely identifies a package within a\n// given PackageIndex.\ntype IndexID int\n\n// -- internals --\n\n// A symbolSet is a set of symbols used internally during index construction.\n//\n// TODO(adonovan): opt: evaluate unifying Symbol and symbol.\n// (Encode would have to create a private PackageIndex.)\ntype symbolSet map[symbol]bool\n\n// A symbol is the internal representation of an external\n// (imported) symbol referenced by the analyzed package.\ntype symbol struct {\n\tpkg  metadata.PackageID\n\tname string\n}\n\n// declNode holds information about a package-level declaration\n// (or more than one with the same name, in ill-typed code).\n//\n// It is a node in the symbol reference graph, whose outgoing edges\n// are of two kinds: intRefs and extRefs.\ntype declNode struct {\n\tname string\n\trep  *declNode // canonical representative of this SCC (initially self)\n\n\t// outgoing graph edges\n\tintRefs      map[*declNode]bool // to symbols in this package\n\textRefs      symbolSet          // to imported symbols\n\textRefsClass int                // extRefs equivalence class number (-1 until set at end)\n\n\t// Tarjan's SCC algorithm\n\tindex, lowlink int32 // Tarjan numbering\n\tscc            int32 // -ve => on stack; 0 => unvisited; +ve => node is root of a found SCC\n}\n\n// state holds the working state of the Refs algorithm for a single package.\n//\n// The number of distinct symbols referenced by a single package\n// (measured across all of kubernetes), was found to be:\n//   - max = 1750.\n//   - Several packages reference > 100 symbols.\n//   - p95 = 32, p90 = 22, p50 = 8.\ntype state struct {\n\t// numbering of unique symbol sets\n\tclass      []symbolSet    // unique symbol sets\n\tclassIndex map[string]int // index of above (using SymbolSet.hash as key)\n\n\t// Tarjan's SCC algorithm\n\tindex int32\n\tstack []*declNode\n}\n\n// getClassIndex returns the small integer (an index into\n// state.class) that identifies the given set.\nfunc (st *state) getClassIndex(set symbolSet) int {\n\tkey := classKey(set)\n\ti, ok := st.classIndex[key]\n\tif !ok {\n\t\ti = len(st.class)\n\t\tst.classIndex[key] = i\n\t\tst.class = append(st.class, set)\n\t}\n\treturn i\n}\n\n// appendSorted appends the symbols to syms, sorts by ascending\n// (PackageID, name), and returns the result.\n// The argument must be an empty slice, ideally with capacity len(set).\nfunc (set symbolSet) appendSorted(syms []symbol) []symbol {\n\tfor sym := range set {\n\t\tsyms = append(syms, sym)\n\t}\n\tsort.Slice(syms, func(i, j int) bool {\n\t\tx, y := syms[i], syms[j]\n\t\tif x.pkg != y.pkg {\n\t\t\treturn x.pkg < y.pkg\n\t\t}\n\t\treturn x.name < y.name\n\t})\n\treturn syms\n}\n\n// classKey returns a key such that equal keys imply equal sets.\n// (e.g. a sorted string representation, or a cryptographic hash of same).\nfunc classKey(set symbolSet) string {\n\t// Sort symbols into a stable order.\n\t// TODO(adonovan): opt: a cheap crypto hash (e.g. BLAKE2b) might\n\t// make a cheaper map key than a large string.\n\t// Try using a hasher instead of a builder.\n\tvar s strings.Builder\n\tfor _, sym := range set.appendSorted(make([]symbol, 0, len(set))) {\n\t\tfmt.Fprintf(&s, \"%s:%s;\", sym.pkg, sym.name)\n\t}\n\treturn s.String()\n}\n\n// index builds the reference graph and encodes the index.\nfunc index(pgfs []*parsego.File, imports map[metadata.ImportPath]*metadata.Package) []byte {\n\t// First pass: gather package-level names and create a declNode for each.\n\t//\n\t// In ill-typed code, there may be multiple declarations of the\n\t// same name; a single declInfo node will represent them all.\n\tdecls := make(map[string]*declNode)\n\taddDecl := func(id *ast.Ident) {\n\t\tif name := id.Name; name != \"_\" && decls[name] == nil {\n\t\t\tnode := &declNode{name: name, extRefsClass: -1}\n\t\t\tnode.rep = node\n\t\t\tdecls[name] = node\n\t\t}\n\t}\n\tfor _, pgf := range pgfs {\n\t\tfor _, d := range pgf.File.Decls {\n\t\t\tswitch d := d.(type) {\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tswitch d.Tok {\n\t\t\t\tcase token.TYPE:\n\t\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\t\taddDecl(spec.(*ast.TypeSpec).Name)\n\t\t\t\t\t}\n\n\t\t\t\tcase token.VAR, token.CONST:\n\t\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\t\tfor _, ident := range spec.(*ast.ValueSpec).Names {\n\t\t\t\t\t\t\taddDecl(ident)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\t// non-method functions\n\t\t\t\tif d.Recv.NumFields() == 0 {\n\t\t\t\t\taddDecl(d.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass: process files to collect referring identifiers.\n\tst := &state{classIndex: make(map[string]int)}\n\tfor _, pgf := range pgfs {\n\t\tvisitFile(pgf.File, imports, decls)\n\t}\n\n\t// Find the strong components of the declNode graph\n\t// using Tarjan's algorithm, and coalesce each component.\n\tst.index = 1\n\tfor _, decl := range decls {\n\t\tif decl.index == 0 { // unvisited\n\t\t\tst.visit(decl)\n\t\t}\n\t}\n\n\t// TODO(adonovan): opt: consider compressing the serialized\n\t// representation by recording not the classes but the DAG of\n\t// non-trivial union operations (the \"pointer equivalence\"\n\t// optimization of Hardekopf & Lin). Unlike that algorithm,\n\t// which piggybacks on SCC coalescing, in our case it would\n\t// be better to make a forward traversal from the exported\n\t// decls, since it avoids visiting unreachable nodes, and\n\t// results in a dense (not sparse) numbering of the sets.\n\n\t// Tabulate the unique reachability sets of\n\t// each exported package member.\n\tclassNames := make(map[int][]string) // set of decls (names) for a given reachability set\n\tfor name, decl := range decls {\n\t\tif !ast.IsExported(name) {\n\t\t\tcontinue\n\t\t}\n\n\t\tdecl = decl.find()\n\n\t\t// Skip decls with empty reachability.\n\t\tif len(decl.extRefs) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Canonicalize the set (and memoize).\n\t\tclass := decl.extRefsClass\n\t\tif class < 0 {\n\t\t\tclass = st.getClassIndex(decl.extRefs)\n\t\t\tdecl.extRefsClass = class\n\t\t}\n\t\tclassNames[class] = append(classNames[class], name)\n\t}\n\n\treturn encode(classNames, st.class)\n}\n\n// visitFile inspects the file syntax for referring identifiers, and\n// populates the internal and external references of decls.\nfunc visitFile(file *ast.File, imports map[metadata.ImportPath]*metadata.Package, decls map[string]*declNode) {\n\t// Import information for this file. Multiple packages\n\t// may be referenced by a given name in the presence\n\t// of type errors (or multiple dot imports, which are\n\t// keyed by \".\").\n\tfileImports := make(map[string][]metadata.PackageID)\n\n\t// importEdge records a reference from decl to an imported symbol\n\t// (pkgname.name). The package name may be \".\".\n\timportEdge := func(decl *declNode, pkgname, name string) {\n\t\tif token.IsExported(name) {\n\t\t\tfor _, depID := range fileImports[pkgname] {\n\t\t\t\tif decl.extRefs == nil {\n\t\t\t\t\tdecl.extRefs = make(symbolSet)\n\t\t\t\t}\n\t\t\t\tdecl.extRefs[symbol{depID, name}] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// visit finds refs within node and builds edges from fromId's decl.\n\t// References to the type parameters are ignored.\n\tvisit := func(fromId *ast.Ident, node ast.Node, tparams map[string]bool) {\n\t\tif fromId.Name == \"_\" {\n\t\t\treturn\n\t\t}\n\t\tfrom := decls[fromId.Name]\n\t\t// When visiting a method, there may not be a valid type declaration for\n\t\t// the receiver. In this case there is no way to refer to the method, so\n\t\t// we need not record edges.\n\t\tif from == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// Visit each reference to name or name.sel.\n\t\tvisitDeclOrSpec(node, func(name, sel string) {\n\t\t\t// Ignore references to type parameters.\n\t\t\tif tparams[name] {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// If name is declared in the package scope,\n\t\t\t// record an edge whether or not sel is empty.\n\t\t\t// A field or method selector may affect the\n\t\t\t// type of the current decl via initializers:\n\t\t\t//\n\t\t\t//  package p\n\t\t\t//  var x = y.F\n\t\t\t//  var y = struct{ F int }{}\n\t\t\tif to, ok := decls[name]; ok {\n\t\t\t\tif from.intRefs == nil {\n\t\t\t\t\tfrom.intRefs = make(map[*declNode]bool)\n\t\t\t\t}\n\t\t\t\tfrom.intRefs[to] = true\n\n\t\t\t} else {\n\t\t\t\t// Only record an edge to dot-imported packages\n\t\t\t\t// if there was no edge to a local name.\n\t\t\t\t// This assumes that there are no duplicate declarations.\n\t\t\t\t// We conservatively, assume that this name comes from\n\t\t\t\t// every dot-imported package.\n\t\t\t\timportEdge(from, \".\", name)\n\t\t\t}\n\n\t\t\t// Record an edge to an import if it matches the name, even if that\n\t\t\t// name collides with a package level name. Unlike the case of dotted\n\t\t\t// imports, we know the package is invalid here, and choose to fail\n\t\t\t// conservatively.\n\t\t\tif sel != \"\" {\n\t\t\t\timportEdge(from, name, sel)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Visit the declarations and gather reference edges.\n\t// Import declarations appear before all others.\n\tfor _, d := range file.Decls {\n\t\tswitch d := d.(type) {\n\t\tcase *ast.GenDecl:\n\t\t\tswitch d.Tok {\n\t\t\tcase token.IMPORT:\n\t\t\t\t// Record local import names for this file.\n\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\tspec := spec.(*ast.ImportSpec)\n\t\t\t\t\tpath := metadata.UnquoteImportPath(spec)\n\t\t\t\t\tif path == \"\" {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tdep := imports[path]\n\t\t\t\t\tif dep == nil {\n\t\t\t\t\t\t// Note here that we don't try to \"guess\"\n\t\t\t\t\t\t// the name of an import based on e.g.\n\t\t\t\t\t\t// its importPath. Doing so would only\n\t\t\t\t\t\t// result in edges that don't go anywhere.\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tname := string(dep.Name)\n\t\t\t\t\tif spec.Name != nil {\n\t\t\t\t\t\tif spec.Name.Name == \"_\" {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tname = spec.Name.Name // possibly \".\"\n\t\t\t\t\t}\n\t\t\t\t\tfileImports[name] = append(fileImports[name], dep.ID)\n\t\t\t\t}\n\n\t\t\tcase token.TYPE:\n\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\tspec := spec.(*ast.TypeSpec)\n\t\t\t\t\ttparams := tparamsMap(spec.TypeParams)\n\t\t\t\t\tvisit(spec.Name, spec, tparams)\n\t\t\t\t}\n\n\t\t\tcase token.VAR, token.CONST:\n\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\tvisit(name, spec, nil)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.FuncDecl:\n\t\t\t// This check for NumFields() > 0 is consistent with go/types,\n\t\t\t// which reports an error but treats the declaration like a\n\t\t\t// normal function when Recv is non-nil but empty\n\t\t\t// (as in func () f()).\n\t\t\tif d.Recv.NumFields() > 0 {\n\t\t\t\t// Method. Associate it with the receiver.\n\t\t\t\t_, id, typeParams := astutil.UnpackRecv(d.Recv.List[0].Type)\n\t\t\t\tif id != nil {\n\t\t\t\t\tvar tparams map[string]bool\n\t\t\t\t\tif len(typeParams) > 0 {\n\t\t\t\t\t\ttparams = make(map[string]bool)\n\t\t\t\t\t\tfor _, tparam := range typeParams {\n\t\t\t\t\t\t\tif tparam.Name != \"_\" {\n\t\t\t\t\t\t\t\ttparams[tparam.Name] = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvisit(id, d, tparams)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Non-method.\n\t\t\t\ttparams := tparamsMap(d.Type.TypeParams)\n\t\t\t\tvisit(d.Name, d, tparams)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// tparamsMap returns a set recording each name declared by the provided field\n// list. It so happens that we only care about names declared by type parameter\n// lists.\nfunc tparamsMap(tparams *ast.FieldList) map[string]bool {\n\tif tparams == nil || len(tparams.List) == 0 {\n\t\treturn nil\n\t}\n\tm := make(map[string]bool)\n\tfor _, f := range tparams.List {\n\t\tfor _, name := range f.Names {\n\t\t\tif name.Name != \"_\" {\n\t\t\t\tm[name.Name] = true\n\t\t\t}\n\t\t}\n\t}\n\treturn m\n}\n\n// A refVisitor visits referring identifiers and dotted identifiers.\n//\n// For a referring identifier I, name=\"I\" and sel=\"\". For a dotted identifier\n// q.I, name=\"q\" and sel=\"I\".\ntype refVisitor = func(name, sel string)\n\n// visitDeclOrSpec visits referring idents or dotted idents that may affect\n// the type of the declaration at the given node, which must be an ast.Decl or\n// ast.Spec.\nfunc visitDeclOrSpec(node ast.Node, f refVisitor) {\n\t// Declarations\n\tswitch n := node.(type) {\n\t// ImportSpecs should not appear here, and will panic in the default case.\n\n\tcase *ast.ValueSpec:\n\t\t// Skip Doc, Names, Comments, which do not affect the decl type.\n\t\t// Initializers only affect the type of a value spec if the type is unset.\n\t\tif n.Type != nil {\n\t\t\tvisitExpr(n.Type, f)\n\t\t} else { // only need to walk expr list if type is nil\n\t\t\tvisitExprList(n.Values, f)\n\t\t}\n\n\tcase *ast.TypeSpec:\n\t\t// Skip Doc, Name, and Comment, which do not affect the decl type.\n\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\tvisitFieldList(tparams, f)\n\t\t}\n\t\tvisitExpr(n.Type, f)\n\n\tcase *ast.BadDecl:\n\t\t// nothing to do\n\n\t// We should not reach here with a GenDecl, so panic below in the default case.\n\n\tcase *ast.FuncDecl:\n\t\t// Skip Doc, Name, and Body, which do not affect the type.\n\t\t// Recv is handled by Refs: methods are associated with their type.\n\t\tvisitExpr(n.Type, f)\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected node type %T\", node))\n\t}\n}\n\n// visitExpr visits referring idents and dotted idents that may affect the\n// type of expr.\n//\n// visitExpr can't reliably distinguish a dotted ident pkg.X from a\n// selection expr.f or T.method.\nfunc visitExpr(expr ast.Expr, f refVisitor) {\n\tswitch n := expr.(type) {\n\t// These four cases account for about two thirds of all nodes,\n\t// so we place them first to shorten the common control paths.\n\t// (See go.dev/cl/480915.)\n\tcase *ast.Ident:\n\t\tf(n.Name, \"\")\n\n\tcase *ast.BasicLit:\n\t\t// nothing to do\n\n\tcase *ast.SelectorExpr:\n\t\tif ident, ok := n.X.(*ast.Ident); ok {\n\t\t\tf(ident.Name, n.Sel.Name)\n\t\t} else {\n\t\t\tvisitExpr(n.X, f)\n\t\t\t// Skip n.Sel as we don't care about which field or method is selected,\n\t\t\t// as we'll have recorded an edge to all declarations relevant to the\n\t\t\t// receiver type via visiting n.X above.\n\t\t}\n\n\tcase *ast.CallExpr:\n\t\tvisitExpr(n.Fun, f)\n\t\tvisitExprList(n.Args, f) // args affect types for unsafe.Sizeof or builtins or generics\n\n\t// Expressions\n\tcase *ast.Ellipsis:\n\t\tif n.Elt != nil {\n\t\t\tvisitExpr(n.Elt, f)\n\t\t}\n\n\tcase *ast.FuncLit:\n\t\tvisitExpr(n.Type, f)\n\t\t// Skip Body, which does not affect the type.\n\n\tcase *ast.CompositeLit:\n\t\tif n.Type != nil {\n\t\t\tvisitExpr(n.Type, f)\n\t\t}\n\t\t// Skip Elts, which do not affect the type.\n\n\tcase *ast.ParenExpr:\n\t\tvisitExpr(n.X, f)\n\n\tcase *ast.IndexExpr:\n\t\tvisitExpr(n.X, f)\n\t\tvisitExpr(n.Index, f) // may affect type for instantiations\n\n\tcase *ast.IndexListExpr:\n\t\tvisitExpr(n.X, f)\n\t\tfor _, index := range n.Indices {\n\t\t\tvisitExpr(index, f) // may affect the type for instantiations\n\t\t}\n\n\tcase *ast.SliceExpr:\n\t\tvisitExpr(n.X, f)\n\t\t// skip Low, High, and Max, which do not affect type.\n\n\tcase *ast.TypeAssertExpr:\n\t\t// Skip X, as it doesn't actually affect the resulting type of the type\n\t\t// assertion.\n\t\tif n.Type != nil {\n\t\t\tvisitExpr(n.Type, f)\n\t\t}\n\n\tcase *ast.StarExpr:\n\t\tvisitExpr(n.X, f)\n\n\tcase *ast.UnaryExpr:\n\t\tvisitExpr(n.X, f)\n\n\tcase *ast.BinaryExpr:\n\t\tvisitExpr(n.X, f)\n\t\tvisitExpr(n.Y, f)\n\n\tcase *ast.KeyValueExpr:\n\t\tpanic(\"unreachable\") // unreachable, as we don't descend into elts of composite lits.\n\n\tcase *ast.ArrayType:\n\t\tif n.Len != nil {\n\t\t\tvisitExpr(n.Len, f)\n\t\t}\n\t\tvisitExpr(n.Elt, f)\n\n\tcase *ast.StructType:\n\t\tvisitFieldList(n.Fields, f)\n\n\tcase *ast.FuncType:\n\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\tvisitFieldList(tparams, f)\n\t\t}\n\t\tif n.Params != nil {\n\t\t\tvisitFieldList(n.Params, f)\n\t\t}\n\t\tif n.Results != nil {\n\t\t\tvisitFieldList(n.Results, f)\n\t\t}\n\n\tcase *ast.InterfaceType:\n\t\tvisitFieldList(n.Methods, f)\n\n\tcase *ast.MapType:\n\t\tvisitExpr(n.Key, f)\n\t\tvisitExpr(n.Value, f)\n\n\tcase *ast.ChanType:\n\t\tvisitExpr(n.Value, f)\n\n\tcase *ast.BadExpr:\n\t\t// nothing to do\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"ast.Walk: unexpected node type %T\", n))\n\t}\n}\n\nfunc visitExprList(list []ast.Expr, f refVisitor) {\n\tfor _, x := range list {\n\t\tvisitExpr(x, f)\n\t}\n}\n\nfunc visitFieldList(n *ast.FieldList, f refVisitor) {\n\tfor _, field := range n.List {\n\t\tvisitExpr(field.Type, f)\n\t}\n}\n\n// -- strong component graph construction (plundered from go/pointer) --\n\n// visit implements the depth-first search of Tarjan's SCC algorithm\n// (see https://doi.org/10.1137/0201010).\n// Precondition: x is canonical.\nfunc (st *state) visit(x *declNode) {\n\tcheckCanonical(x)\n\tx.index = st.index\n\tx.lowlink = st.index\n\tst.index++\n\n\tst.stack = append(st.stack, x) // push\n\tassert(x.scc == 0, \"node revisited\")\n\tx.scc = -1\n\n\tfor y := range x.intRefs {\n\t\t// Loop invariant: x is canonical.\n\n\t\ty := y.find()\n\n\t\tif x == y {\n\t\t\tcontinue // nodes already coalesced\n\t\t}\n\n\t\tswitch {\n\t\tcase y.scc > 0:\n\t\t\t// y is already a collapsed SCC\n\n\t\tcase y.scc < 0:\n\t\t\t// y is on the stack, and thus in the current SCC.\n\t\t\tif y.index < x.lowlink {\n\t\t\t\tx.lowlink = y.index\n\t\t\t}\n\n\t\tdefault:\n\t\t\t// y is unvisited; visit it now.\n\t\t\tst.visit(y)\n\t\t\t// Note: x and y are now non-canonical.\n\n\t\t\tx = x.find()\n\n\t\t\tif y.lowlink < x.lowlink {\n\t\t\t\tx.lowlink = y.lowlink\n\t\t\t}\n\t\t}\n\t}\n\tcheckCanonical(x)\n\n\t// Is x the root of an SCC?\n\tif x.lowlink == x.index {\n\t\t// Coalesce all nodes in the SCC.\n\t\tfor {\n\t\t\t// Pop y from stack.\n\t\t\ti := len(st.stack) - 1\n\t\t\ty := st.stack[i]\n\t\t\tst.stack = st.stack[:i]\n\n\t\t\tcheckCanonical(x)\n\t\t\tcheckCanonical(y)\n\n\t\t\tif x == y {\n\t\t\t\tbreak // SCC is complete.\n\t\t\t}\n\t\t\tcoalesce(x, y)\n\t\t}\n\n\t\t// Accumulate union of extRefs over\n\t\t// internal edges (to other SCCs).\n\t\tfor y := range x.intRefs {\n\t\t\ty := y.find()\n\t\t\tif y == x {\n\t\t\t\tcontinue // already coalesced\n\t\t\t}\n\t\t\tassert(y.scc == 1, \"edge to non-scc node\")\n\t\t\tfor z := range y.extRefs {\n\t\t\t\tif x.extRefs == nil {\n\t\t\t\t\tx.extRefs = make(symbolSet)\n\t\t\t\t}\n\t\t\t\tx.extRefs[z] = true // extRefs: x U= y\n\t\t\t}\n\t\t}\n\n\t\tx.scc = 1\n\t}\n}\n\n// coalesce combines two nodes in the strong component graph.\n// Precondition: x and y are canonical.\nfunc coalesce(x, y *declNode) {\n\t// x becomes y's canonical representative.\n\ty.rep = x\n\n\t// x accumulates y's internal references.\n\tfor z := range y.intRefs {\n\t\tx.intRefs[z] = true\n\t}\n\ty.intRefs = nil\n\n\t// x accumulates y's external references.\n\tfor z := range y.extRefs {\n\t\tif x.extRefs == nil {\n\t\t\tx.extRefs = make(symbolSet)\n\t\t}\n\t\tx.extRefs[z] = true\n\t}\n\ty.extRefs = nil\n}\n\n// find returns the canonical node decl.\n// (The nodes form a disjoint set forest.)\nfunc (decl *declNode) find() *declNode {\n\trep := decl.rep\n\tif rep != decl {\n\t\trep = rep.find()\n\t\tdecl.rep = rep // simple path compression (no union-by-rank)\n\t}\n\treturn rep\n}\n\nconst debugSCC = false // enable assertions in strong-component algorithm\n\nfunc checkCanonical(x *declNode) {\n\tif debugSCC {\n\t\tassert(x == x.find(), \"not canonical\")\n\t}\n}\n\nfunc assert(cond bool, msg string) {\n\tif debugSCC && !cond {\n\t\tpanic(msg)\n\t}\n}\n\n// -- serialization --\n\n// (The name says gob but in fact we use frob.)\nvar classesCodec = frob.CodecFor[gobClasses]()\n\ntype gobClasses struct {\n\tStrings []string // table of strings (PackageIDs and names)\n\tClasses []gobClass\n}\n\ntype gobClass struct {\n\tDecls []int32 // indices into gobClasses.Strings\n\tRefs  []int32 // list of (package, name) pairs, each an index into gobClasses.Strings\n}\n\n// encode encodes the equivalence classes,\n// (classNames[i], classes[i]), for i in range classes.\n//\n// With the current encoding, across kubernetes,\n// the encoded size distribution has\n// p50 = 511B, p95 = 4.4KB, max = 108K.\nfunc encode(classNames map[int][]string, classes []symbolSet) []byte {\n\tpayload := gobClasses{\n\t\tClasses: make([]gobClass, 0, len(classNames)),\n\t}\n\n\t// index of unique strings\n\tstrings := make(map[string]int32)\n\tstringIndex := func(s string) int32 {\n\t\ti, ok := strings[s]\n\t\tif !ok {\n\t\t\ti = int32(len(payload.Strings))\n\t\t\tstrings[s] = i\n\t\t\tpayload.Strings = append(payload.Strings, s)\n\t\t}\n\t\treturn i\n\t}\n\n\tvar refs []symbol // recycled temporary\n\tfor class, names := range classNames {\n\t\tset := classes[class]\n\n\t\t// names, sorted\n\t\tsort.Strings(names)\n\t\tgobDecls := make([]int32, len(names))\n\t\tfor i, name := range names {\n\t\t\tgobDecls[i] = stringIndex(name)\n\t\t}\n\n\t\t// refs, sorted by ascending (PackageID, name)\n\t\tgobRefs := make([]int32, 0, 2*len(set))\n\t\tfor _, sym := range set.appendSorted(refs[:0]) {\n\t\t\tgobRefs = append(gobRefs,\n\t\t\t\tstringIndex(string(sym.pkg)),\n\t\t\t\tstringIndex(sym.name))\n\t\t}\n\t\tpayload.Classes = append(payload.Classes, gobClass{\n\t\t\tDecls: gobDecls,\n\t\t\tRefs:  gobRefs,\n\t\t})\n\t}\n\n\treturn classesCodec.Encode(payload)\n}\n\nfunc decode(pkgIndex *PackageIndex, data []byte) []Class {\n\tvar payload gobClasses\n\tclassesCodec.Decode(data, &payload)\n\n\tclasses := make([]Class, len(payload.Classes))\n\tfor i, gobClass := range payload.Classes {\n\t\tdecls := make([]string, len(gobClass.Decls))\n\t\tfor i, decl := range gobClass.Decls {\n\t\t\tdecls[i] = payload.Strings[decl]\n\t\t}\n\t\trefs := make([]Symbol, len(gobClass.Refs)/2)\n\t\tfor i := range refs {\n\t\t\tpkgID := pkgIndex.IndexID(metadata.PackageID(payload.Strings[gobClass.Refs[2*i]]))\n\t\t\tname := payload.Strings[gobClass.Refs[2*i+1]]\n\t\t\trefs[i] = Symbol{Package: pkgID, Name: name}\n\t\t}\n\t\tclasses[i] = Class{\n\t\t\tDecls: decls,\n\t\t\tRefs:  refs,\n\t\t}\n\t}\n\n\t// Sort by ascending Decls[0].\n\t// TODO(adonovan): move sort to encoder. Determinism is good.\n\tsort.Slice(classes, func(i, j int) bool {\n\t\treturn classes[i].Decls[0] < classes[j].Decls[0]\n\t})\n\n\treturn classes\n}\n"
  },
  {
    "path": "gopls/internal/cache/typerefs/refs_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typerefs_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// TestRefs checks that the analysis reports, for each exported member\n// of the test package (\"p\"), its correct dependencies on exported\n// members of its direct imports (e.g. \"ext\").\nfunc TestRefs(t *testing.T) {\n\tctx := context.Background()\n\n\ttests := []struct {\n\t\tlabel     string\n\t\tsrcs      []string            // source for the local package; package name must be p\n\t\timports   map[string]string   // for simplicity: importPath -> pkgID/pkgName (we set pkgName == pkgID); 'ext' is always available.\n\t\twant      map[string][]string // decl name -> id.<decl name>\n\t\tallowErrs bool                // whether we expect parsing errors\n\t}{\n\t\t{\n\t\t\tlabel: \"empty package\",\n\t\t\twant:  map[string][]string{},\n\t\t},\n\t\t{\n\t\t\tlabel: \"fields\",\n\t\t\tsrcs: []string{`\npackage p\n\nimport \"ext\"\n\ntype A struct{ b B }\ntype B func(c C) (d D)\ntype C ext.C\ntype D ext.D\n\n// Should not be referenced by field names.\ntype b ext.B_\ntype c int.C_\ntype d ext.D_\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.C\", \"ext.D\"},\n\t\t\t\t\"B\": {\"ext.C\", \"ext.D\"},\n\t\t\t\t\"C\": {\"ext.C\"},\n\t\t\t\t\"D\": {\"ext.D\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"embedding\",\n\t\t\tsrcs: []string{`\npackage p\n\nimport \"ext\"\n\ntype A struct{\n\tB\n\t_ struct {\n\t\tC\n\t}\n\tD\n}\ntype B ext.B\ntype C ext.C\ntype D interface{\n\tB\n}\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.B\", \"ext.C\"},\n\t\t\t\t\"B\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.C\"},\n\t\t\t\t\"D\": {\"ext.B\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"constraint embedding\",\n\t\t\tsrcs: []string{`\npackage p\n\nimport \"ext\"\n\ntype A interface{\n\tint | B | ~C\n\tstruct{D}\n}\n\ntype B ext.B\ntype C ext.C\ntype D ext.D\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.B\", \"ext.C\", \"ext.D\"},\n\t\t\t\t\"B\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.C\"},\n\t\t\t\t\"D\": {\"ext.D\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"funcs\",\n\t\t\tsrcs: []string{`\npackage p\n\nimport \"ext\"\n\ntype A ext.A\ntype B ext.B\nconst C B = 2\nfunc F(A) B {\n\treturn C\n}\nvar V = F(W)\nvar W A\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.A\"},\n\t\t\t\t\"B\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.B\"},\n\t\t\t\t\"F\": {\"ext.A\", \"ext.B\"},\n\t\t\t\t\"V\": {\n\t\t\t\t\t\"ext.A\", // via F\n\t\t\t\t\t\"ext.B\", // via W: can't be eliminated: F could be builtin or generic\n\t\t\t\t},\n\t\t\t\t\"W\": {\"ext.A\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"methods\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A ext.A\ntype B ext.B\n`, `package p\n\nfunc (A) M(B)\nfunc (*B) M(A)\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.A\", \"ext.B\"},\n\t\t\t\t\"B\": {\"ext.A\", \"ext.B\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"initializers\",\n\t\t\tsrcs: []string{`\npackage p\n\nimport \"ext\"\n\nvar A b = C // type does not depend on C\ntype b ext.B\nvar C = d // type does depend on D\nvar d b\n\nvar e = d + a\n\nvar F = func() B { return E }\n\nvar G = struct{\n\tA b\n\t_ [unsafe.Sizeof(ext.V)]int // array size + Sizeof creates edge to a var\n\t_ [unsafe.Sizeof(G)]int // creates a self edge; doesn't affect output though\n}{}\n\nvar H = (D + A + C*C)\n\nvar I = (A+C).F\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.B\"},          // via d\n\t\t\t\t\"G\": {\"ext.B\", \"ext.V\"}, // via b,C\n\t\t\t\t\"H\": {\"ext.B\"},          // via d,A,C\n\t\t\t\t\"I\": {\"ext.B\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"builtins\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\nvar A = new(b)\ntype b struct{ ext.B }\n\ntype C chan d\ntype d ext.D\n\ntype S []ext.S\ntype t ext.T\nvar U = append(([]*S)(nil), new(t))\n\ntype X map[k]v\ntype k ext.K\ntype v ext.V\n\nvar Z = make(map[k]A)\n\n// close, delete, and panic cannot occur outside of statements\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.D\"},\n\t\t\t\t\"S\": {\"ext.S\"},\n\t\t\t\t\"U\": {\"ext.S\", \"ext.T\"}, // ext.T edge could be eliminated\n\t\t\t\t\"X\": {\"ext.K\", \"ext.V\"},\n\t\t\t\t\"Z\": {\"ext.B\", \"ext.K\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"builtin shadowing\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\nvar A = new(ext.B)\nfunc new() c\ntype c ext.C\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.B\", \"ext.C\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"named forwarding\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A B\ntype B c\ntype c ext.C\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.C\"},\n\t\t\t\t\"B\": {\"ext.C\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"aliases\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A = B\ntype B = C\ntype C = ext.C\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.C\"},\n\t\t\t\t\"B\": {\"ext.C\"},\n\t\t\t\t\"C\": {\"ext.C\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"array length\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\nimport \"unsafe\"\n\ntype A [unsafe.Sizeof(ext.B{ext.C})]int\ntype A2 [unsafe.Sizeof(ext.B{f:ext.C})]int // use a KeyValueExpr\n\ntype D [unsafe.Sizeof(struct{ f E })]int\ntype E ext.E\n\ntype F [3]G\ntype G [ext.C]int\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\":  {\"ext.B\"}, // no ext.C: doesn't enter CompLit\n\t\t\t\t\"A2\": {\"ext.B\"}, // ditto\n\t\t\t\t\"D\":  {\"ext.E\"},\n\t\t\t\t\"E\":  {\"ext.E\"},\n\t\t\t\t\"F\":  {\"ext.C\"},\n\t\t\t\t\"G\":  {\"ext.C\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"imports\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\nimport (\n\t\"q\"\n\tr2 \"r\"\n\t\"s\" // note: package name is t\n\t\"z\"\n)\n\ntype A struct {\n\tq.Q\n\tr2.R\n\ts.S // invalid ref\n\tz.Z // references both external z.Z as well as package-level type z\n}\n\ntype B struct {\n\tr.R // invalid ref\n\tt.T\n}\n\nvar X int = q.V // X={}: no descent into RHS of 'var v T = rhs'\nvar Y = q.V.W\n\ntype z ext.Z\n`},\n\t\t\timports: map[string]string{\"q\": \"q\", \"r\": \"r\", \"s\": \"t\", \"z\": \"z\"},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.Z\", \"q.Q\", \"r.R\", \"z.Z\"},\n\t\t\t\t\"B\": {\"t.T\"},\n\t\t\t\t\"Y\": {\"q.V\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"import blank\",\n\t\t\tsrcs: []string{`package p\n\nimport _ \"q\"\n\ntype A q.Q\n`},\n\t\t\timports: map[string]string{\"q\": \"q\"},\n\t\t\twant:    map[string][]string{},\n\t\t},\n\t\t{\n\t\t\tlabel: \"import dot\",\n\t\t\tsrcs: []string{`package p\n\nimport . \"q\"\n\ntype A q.Q // not actually an edge, since q is imported .\ntype B struct {\n\tC // assumed to be an edge to q\n\tD // resolved to package decl\n}\n\n\ntype E error // unexported, therefore must be universe.error\ntype F Field\nvar G = Field.X\n`, `package p\n\nimport \"ext\"\nimport \"q\"\n\ntype D ext.D\n`},\n\t\t\timports: map[string]string{\"q\": \"q\"},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"B\": {\"ext.D\", \"q.C\"},\n\t\t\t\t\"D\": {\"ext.D\"},\n\t\t\t\t\"F\": {\"q.Field\"},\n\t\t\t\t\"G\": {\"q.Field\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"typeparams\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A[T any] struct {\n\tt T\n\tb B\n}\n\ntype B ext.B\n\nfunc F1[T any](T, B)\nfunc F2[T C]()(T, B)\n\ntype T ext.T\n\ntype C ext.C\n\nfunc F3[T1 ~[]T2, T2 ~[]T3](t1 T1, t2 T2)\ntype T3 ext.T3\n`, `package p\n\nfunc (A[B]) M(C) {}\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\":  {\"ext.B\", \"ext.C\"},\n\t\t\t\t\"B\":  {\"ext.B\"},\n\t\t\t\t\"C\":  {\"ext.C\"},\n\t\t\t\t\"F1\": {\"ext.B\"},\n\t\t\t\t\"F2\": {\"ext.B\", \"ext.C\"},\n\t\t\t\t\"F3\": {\"ext.T3\"},\n\t\t\t\t\"T\":  {\"ext.T\"},\n\t\t\t\t\"T3\": {\"ext.T3\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"instances\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A[T any] ext.A\ntype B[T1, T2 any] ext.B\n\ntype C A[int]\ntype D B[int, A[E]]\ntype E ext.E\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"ext.A\"},\n\t\t\t\t\"B\": {\"ext.B\"},\n\t\t\t\t\"C\": {\"ext.A\"},\n\t\t\t\t\"D\": {\"ext.A\", \"ext.B\", \"ext.E\"},\n\t\t\t\t\"E\": {\"ext.E\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"duplicate decls\",\n\t\t\tsrcs: []string{`package p\n\nimport \"a\"\nimport \"ext\"\n\ntype a a.A\ntype A a\ntype b ext.B\ntype C a.A\nfunc (C) Foo(x) {} // invalid parameter, but that does not matter\ntype C b\nfunc (C) Bar(y) {} // invalid parameter, but that does not matter\n\nvar x ext.X\nvar y ext.Y\n`},\n\t\t\timports: map[string]string{\"a\": \"a\", \"b\": \"b\"}, // \"b\" import should not matter, since it isn't in this file\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\": {\"a.A\"},\n\t\t\t\t\"C\": {\"a.A\", \"ext.B\", \"ext.X\", \"ext.Y\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tlabel: \"invalid decls\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype A B\n\nfunc () Foo(B){}\n\nvar B struct{ ext.B\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"A\":   {\"ext.B\"},\n\t\t\t\t\"B\":   {\"ext.B\"},\n\t\t\t\t\"Foo\": {\"ext.B\"},\n\t\t\t},\n\t\t\tallowErrs: true,\n\t\t},\n\t\t{\n\t\t\tlabel: \"unmapped receiver\",\n\t\t\tsrcs: []string{`package p\n\ntype P struct{}\n\nfunc (a) x(P)\n`},\n\t\t\twant:      map[string][]string{},\n\t\t\tallowErrs: true,\n\t\t},\n\t\t{\n\t\t\tlabel: \"SCC special case\",\n\t\t\tsrcs: []string{`package p\n\nimport \"ext\"\n\ntype X Y\ntype Y struct { Z; *X }\ntype Z map[ext.A]ext.B\n`},\n\t\t\twant: map[string][]string{\n\t\t\t\t\"X\": {\"ext.A\", \"ext.B\"},\n\t\t\t\t\"Y\": {\"ext.A\", \"ext.B\"},\n\t\t\t\t\"Z\": {\"ext.A\", \"ext.B\"},\n\t\t\t},\n\t\t\tallowErrs: true,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tvar pgfs []*parsego.File\n\t\t\tfor i, src := range test.srcs {\n\t\t\t\turi := protocol.DocumentURI(fmt.Sprintf(\"file:///%d.go\", i))\n\t\t\t\tpgf, _ := parsego.Parse(ctx, token.NewFileSet(), uri, []byte(src), parsego.Full, false)\n\t\t\t\tif !test.allowErrs && pgf.ParseErr != nil {\n\t\t\t\t\tt.Fatalf(\"ParseGoSrc(...) returned parse errors: %v\", pgf.ParseErr)\n\t\t\t\t}\n\t\t\t\tpgfs = append(pgfs, pgf)\n\t\t\t}\n\n\t\t\timports := map[metadata.ImportPath]*metadata.Package{\n\t\t\t\t\"ext\": {ID: \"ext\", Name: \"ext\"}, // this one comes for free\n\t\t\t}\n\t\t\tfor path, mp := range test.imports {\n\t\t\t\timports[metadata.ImportPath(path)] = &metadata.Package{\n\t\t\t\t\tID:   metadata.PackageID(mp),\n\t\t\t\t\tName: metadata.PackageName(mp),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdata := typerefs.Encode(pgfs, imports)\n\n\t\t\tgot := make(map[string][]string)\n\t\t\tindex := typerefs.NewPackageIndex()\n\t\t\tfor _, class := range typerefs.Decode(index, data) {\n\t\t\t\t// We redundantly expand out the name x refs cross product\n\t\t\t\t// here since that's what the existing tests expect.\n\t\t\t\tfor _, name := range class.Decls {\n\t\t\t\t\tvar syms []string\n\t\t\t\t\tfor _, sym := range class.Refs {\n\t\t\t\t\t\tsyms = append(syms, fmt.Sprintf(\"%s.%s\", index.DeclaringPackage(sym), sym.Name))\n\t\t\t\t\t}\n\t\t\t\t\tsort.Strings(syms)\n\t\t\t\t\tgot[name] = syms\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(test.want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"Refs(...) returned unexpected refs (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/view.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cache is the core of gopls: it is concerned with state\n// management, dependency analysis, and invalidation; and it holds the\n// machinery of type checking and modular static analysis. Its\n// principal types are [Session], [Folder], [View], [Snapshot],\n// [Cache], and [Package].\npackage cache\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/typerefs\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/modindex\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// A Folder represents an LSP workspace folder, together with its per-folder\n// options and environment variables that affect build configuration.\n//\n// Folders (Name and Dir) are specified by the 'initialize' and subsequent\n// 'didChangeWorkspaceFolders' requests; their options come from\n// didChangeConfiguration.\n//\n// Folders must not be mutated, as they may be shared across multiple views.\ntype Folder struct {\n\tDir     protocol.DocumentURI\n\tName    string // decorative name for UI; not necessarily unique\n\tOptions *settings.Options\n\tEnv     GoEnv\n}\n\n// GoEnv holds the environment variables and data from the Go command that is\n// required for operating on a workspace folder.\ntype GoEnv struct {\n\t// Go environment variables. These correspond directly with the Go env var of\n\t// the same name.\n\tGOOS        string\n\tGOARCH      string\n\tGOCACHE     string\n\tGOMODCACHE  string\n\tGOPATH      string\n\tGOPRIVATE   string\n\tGOFLAGS     string\n\tGO111MODULE string\n\tGOTOOLCHAIN string\n\tGOROOT      string\n\n\t// Go version output.\n\tGoVersion       int    // The X in Go 1.X\n\tGoVersionOutput string // complete go version output\n\n\t// OS environment variables (notably not go env).\n\n\t// ExplicitGOWORK is the GOWORK value set explicitly in the environment. This\n\t// may differ from `go env GOWORK` when the GOWORK value is implicit from the\n\t// working directory.\n\tExplicitGOWORK string\n\n\t// EffectiveGOPACKAGESDRIVER is the effective go/packages driver binary that\n\t// will be used. This may be set via GOPACKAGESDRIVER, or may be discovered\n\t// via os.LookPath(\"gopackagesdriver\"). The latter functionality is\n\t// undocumented and may be removed in the future.\n\t//\n\t// If GOPACKAGESDRIVER is set to \"off\", EffectiveGOPACKAGESDRIVER is \"\".\n\tEffectiveGOPACKAGESDRIVER string\n}\n\n// View represents a single build for a workspace.\n//\n// A View is a logical build (the viewDefinition) along with a state of that\n// build (the Snapshot).\ntype View struct {\n\tid string // a unique string to identify this View in (e.g.) serialized Commands\n\n\t*viewDefinition // build configuration\n\n\tgocmdRunner *gocommand.Runner // limits go command concurrency\n\n\t// baseCtx is the context handed to NewView. This is the parent of all\n\t// background contexts created for this view.\n\tbaseCtx context.Context\n\n\t// importsState is for the old imports code\n\timportsState *importsState\n\n\t// modcacheState is the replacement for importsState, to be used for\n\t// goimports operations when the imports source is \"gopls\".\n\t//\n\t// It may be nil, if the imports source is not \"gopls\".\n\tmodcacheState *modcacheState\n\n\t// pkgIndex is an index of package IDs, for efficient storage of typerefs.\n\tpkgIndex *typerefs.PackageIndex\n\n\t// parseCache holds an LRU cache of recently parsed files.\n\tparseCache *parseCache\n\n\t// fs is the file source used to populate this view.\n\tfs *overlayFS\n\n\t// ignoreFilter is used for fast checking of ignored files.\n\tignoreFilter *ignoreFilter\n\n\t// cancelInitialWorkspaceLoad can be used to terminate the view's first\n\t// attempt at initialization.\n\tcancelInitialWorkspaceLoad context.CancelFunc\n\n\tsnapshotMu sync.Mutex\n\tsnapshot   *Snapshot // latest snapshot; nil after shutdown has been called\n\n\t// initialWorkspaceLoad is closed when the first workspace initialization has\n\t// completed. If we failed to load, we only retry if the go.mod file changes,\n\t// to avoid too many go/packages calls.\n\tinitialWorkspaceLoad chan struct{}\n\n\t// initializationSema is used limit concurrent initialization of snapshots in\n\t// the view. We use a channel instead of a mutex to avoid blocking when a\n\t// context is canceled.\n\t//\n\t// This field (along with snapshot.initialized) guards against duplicate\n\t// initialization of snapshots. Do not change it without adjusting snapshot\n\t// accordingly.\n\tinitializationSema chan struct{}\n\n\t// Document filters are constructed once, in View.filterFunc.\n\tfilterFuncOnce sync.Once\n\t_filterFunc    func(protocol.DocumentURI) bool // only accessed by View.filterFunc\n}\n\n// definition implements the viewDefiner interface.\nfunc (v *View) definition() *viewDefinition { return v.viewDefinition }\n\n// A viewDefinition is a logical build, i.e. configuration (Folder) along with\n// a build directory and possibly an environment overlay (e.g. GOWORK=off or\n// GOOS, GOARCH=...) to affect the build.\n//\n// This type is immutable, and compared to see if the View needs to be\n// reconstructed.\n//\n// Note: whenever modifying this type, also modify the equivalence relation\n// implemented by viewDefinitionsEqual.\n//\n// TODO(golang/go#57979): viewDefinition should be sufficient for running\n// go/packages. Enforce this in the API.\ntype viewDefinition struct {\n\tfolder *Folder // pointer comparison is OK, as any new Folder creates a new def\n\n\ttyp    ViewType\n\troot   protocol.DocumentURI // root directory; where to run the Go command\n\tgomod  protocol.DocumentURI // the nearest go.mod file, or \"\"\n\tgowork protocol.DocumentURI // the nearest go.work file, or \"\"\n\n\t// workspaceModFiles holds the set of mod files active in this snapshot.\n\t//\n\t// For a go.work workspace, this is the set of workspace modfiles. For a\n\t// go.mod workspace, this contains the go.mod file defining the workspace\n\t// root, as well as any locally replaced modules (if\n\t// \"includeReplaceInWorkspace\" is set).\n\t//\n\t// TODO(rfindley): should we just run `go list -m` to compute this set?\n\tworkspaceModFiles    map[protocol.DocumentURI]struct{}\n\tworkspaceModFilesErr error // error encountered computing workspaceModFiles\n\n\t// envOverlay holds additional environment to apply to this viewDefinition.\n\tenvOverlay map[string]string\n}\n\n// definition implements the viewDefiner interface.\nfunc (d *viewDefinition) definition() *viewDefinition { return d }\n\n// Type returns the ViewType type, which determines how go/packages are loaded\n// for this View.\nfunc (d *viewDefinition) Type() ViewType { return d.typ }\n\n// Root returns the view root, which determines where packages are loaded from.\nfunc (d *viewDefinition) Root() protocol.DocumentURI { return d.root }\n\n// GoMod returns the nearest go.mod file for this view's root, or \"\".\nfunc (d *viewDefinition) GoMod() protocol.DocumentURI { return d.gomod }\n\n// GoWork returns the nearest go.work file for this view's root, or \"\".\nfunc (d *viewDefinition) GoWork() protocol.DocumentURI { return d.gowork }\n\n// EnvOverlay returns a new sorted slice of environment variables (in the form\n// \"k=v\") for this view definition's env overlay.\nfunc (d *viewDefinition) EnvOverlay() []string {\n\tvar env []string\n\tfor k, v := range d.envOverlay {\n\t\tenv = append(env, fmt.Sprintf(\"%s=%s\", k, v))\n\t}\n\tsort.Strings(env)\n\treturn env\n}\n\n// GOOS returns the effective GOOS value for this view definition, accounting\n// for its env overlay.\nfunc (d *viewDefinition) GOOS() string {\n\tif goos, ok := d.envOverlay[\"GOOS\"]; ok {\n\t\treturn goos\n\t}\n\treturn d.folder.Env.GOOS\n}\n\n// GOARCH returns the effective GOARCH value for this view definition, accounting\n// for its env overlay.\nfunc (d *viewDefinition) GOARCH() string {\n\tif goarch, ok := d.envOverlay[\"GOARCH\"]; ok {\n\t\treturn goarch\n\t}\n\treturn d.folder.Env.GOARCH\n}\n\n// adjustedGO111MODULE is the value of GO111MODULE to use for loading packages.\n// It is adjusted to default to \"auto\" rather than \"on\", since if we are in\n// GOPATH and have no module, we may as well allow a GOPATH view to work.\nfunc (d viewDefinition) adjustedGO111MODULE() string {\n\tif d.folder.Env.GO111MODULE != \"\" {\n\t\treturn d.folder.Env.GO111MODULE\n\t}\n\treturn \"auto\"\n}\n\n// ModFiles returns a new, sorted slice of go.mod files for main modules\n// enclosed in the snapshot's view and known to the snapshot.\nfunc (d viewDefinition) ModFiles() []protocol.DocumentURI {\n\treturn slices.Sorted(maps.Keys(d.workspaceModFiles))\n}\n\n// viewDefinitionsEqual reports whether x and y are equivalent.\nfunc viewDefinitionsEqual(x, y *viewDefinition) bool {\n\tif (x.workspaceModFilesErr == nil) != (y.workspaceModFilesErr == nil) {\n\t\treturn false\n\t}\n\tif x.workspaceModFilesErr != nil {\n\t\tif x.workspaceModFilesErr.Error() != y.workspaceModFilesErr.Error() {\n\t\t\treturn false\n\t\t}\n\t} else if !moremaps.SameKeys(x.workspaceModFiles, y.workspaceModFiles) {\n\t\treturn false\n\t}\n\tif len(x.envOverlay) != len(y.envOverlay) {\n\t\treturn false\n\t}\n\tfor i, xv := range x.envOverlay {\n\t\tif xv != y.envOverlay[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn x.folder == y.folder &&\n\t\tx.typ == y.typ &&\n\t\tx.root == y.root &&\n\t\tx.gomod == y.gomod &&\n\t\tx.gowork == y.gowork\n}\n\n// A ViewType describes how we load package information for a view.\n//\n// This is used for constructing the go/packages.Load query, and for\n// interpreting missing packages, imports, or errors.\n//\n// See the documentation for individual ViewType values for details.\ntype ViewType int\n\nconst (\n\t// GoPackagesDriverView is a view with a non-empty GOPACKAGESDRIVER\n\t// environment variable.\n\t//\n\t// Load: ./... from the workspace folder.\n\tGoPackagesDriverView ViewType = iota\n\n\t// GOPATHView is a view in GOPATH mode.\n\t//\n\t// I.e. in GOPATH, with GO111MODULE=off, or GO111MODULE=auto with no\n\t// go.mod file.\n\t//\n\t// Load: ./... from the workspace folder.\n\tGOPATHView\n\n\t// GoModView is a view in module mode with a single Go module.\n\t//\n\t// Load: <modulePath>/... from the module root.\n\tGoModView\n\n\t// GoWorkView is a view in module mode with a go.work file.\n\t//\n\t// Load: <modulePath>/... from the workspace folder, for each module.\n\tGoWorkView\n\n\t// An AdHocView is a collection of files in a given directory, not in GOPATH\n\t// or a module.\n\t//\n\t// Load: . from the workspace folder.\n\tAdHocView\n)\n\nfunc (t ViewType) String() string {\n\tswitch t {\n\tcase GoPackagesDriverView:\n\t\treturn \"GoPackagesDriver\"\n\tcase GOPATHView:\n\t\treturn \"GOPATH\"\n\tcase GoModView:\n\t\treturn \"GoMod\"\n\tcase GoWorkView:\n\t\treturn \"GoWork\"\n\tcase AdHocView:\n\t\treturn \"AdHoc\"\n\tdefault:\n\t\treturn \"Unknown\"\n\t}\n}\n\n// usesModules reports whether the view uses Go modules.\nfunc (typ ViewType) usesModules() bool {\n\tswitch typ {\n\tcase GoModView, GoWorkView:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// ID returns the unique ID of this View.\nfunc (v *View) ID() string { return v.id }\n\n// GoCommandRunner returns the shared gocommand.Runner for this view.\nfunc (v *View) GoCommandRunner() *gocommand.Runner {\n\treturn v.gocmdRunner\n}\n\n// Folder returns the folder at the base of this view.\nfunc (v *View) Folder() *Folder {\n\treturn v.folder\n}\n\n// Env returns the environment to use for running go commands in this view.\nfunc (v *View) Env() []string {\n\treturn slices.Concat(\n\t\tos.Environ(),\n\t\tv.folder.Options.EnvSlice(),\n\t\t[]string{\"GO111MODULE=\" + v.adjustedGO111MODULE()},\n\t\tv.EnvOverlay(),\n\t)\n}\n\n// ModcacheIndex returns the module cache index\nfunc (v *View) ModcacheIndex() (*modindex.Index, error) {\n\treturn v.modcacheState.getIndex()\n}\n\n// UpdateFolders updates the set of views for the new folders.\n//\n// Calling this causes each view to be reinitialized.\nfunc (s *Session) UpdateFolders(ctx context.Context, newFolders []*Folder) error {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\toverlays := s.Overlays()\n\tvar openFiles []protocol.DocumentURI\n\tfor _, o := range overlays {\n\t\topenFiles = append(openFiles, o.URI())\n\t}\n\n\tdefs, err := selectViewDefs(ctx, s, newFolders, openFiles)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar newViews []*View\n\tfor _, def := range defs {\n\t\tv, _, release := s.createView(ctx, def)\n\t\trelease()\n\t\tnewViews = append(newViews, v)\n\t}\n\tfor _, v := range s.views {\n\t\tv.shutdown()\n\t}\n\ts.views = newViews\n\treturn nil\n}\n\n// RunProcessEnvFunc runs fn with the process env for this snapshot's view.\n// Note: the process env contains cached module and filesystem state.\nfunc (s *Snapshot) RunProcessEnvFunc(ctx context.Context, fn func(context.Context, *imports.Options) error) error {\n\treturn s.view.importsState.runProcessEnvFunc(ctx, s, fn)\n}\n\n// separated out from its sole use in locateTemplateFiles for testability\nfunc fileHasExtension(path string, suffixes []string) bool {\n\text := filepath.Ext(path)\n\tif ext != \"\" && ext[0] == '.' {\n\t\text = ext[1:]\n\t}\n\tfor _, s := range suffixes {\n\t\tif s != \"\" && ext == s {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// locateTemplateFiles ensures that the snapshot has mapped template files\n// within the workspace folder.\nfunc (s *Snapshot) locateTemplateFiles(ctx context.Context) {\n\tsuffixes := s.Options().TemplateExtensions\n\tif len(suffixes) == 0 {\n\t\treturn\n\t}\n\n\tsearched := 0\n\tfilterFunc := s.view.filterFunc()\n\terr := filepath.WalkDir(s.view.folder.Dir.Path(), func(path string, entry os.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif entry.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\tif fileLimit > 0 && searched > fileLimit {\n\t\t\treturn errExhausted\n\t\t}\n\t\tsearched++\n\t\tif !fileHasExtension(path, suffixes) {\n\t\t\treturn nil\n\t\t}\n\t\turi := protocol.URIFromPath(path)\n\t\tif filterFunc(uri) {\n\t\t\treturn nil\n\t\t}\n\t\t// Get the file in order to include it in the snapshot.\n\t\t// TODO(golang/go#57558): it is fundamentally broken to track files in this\n\t\t// way; we may lose them if configuration or layout changes cause a view to\n\t\t// be recreated.\n\t\t//\n\t\t// Furthermore, this operation must ignore errors, including context\n\t\t// cancellation, or risk leaving the snapshot in an undefined state.\n\t\ts.ReadFile(ctx, uri)\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\tevent.Error(ctx, \"searching for template files failed\", err)\n\t}\n}\n\n// filterFunc returns a func that reports whether uri is filtered by the currently configured\n// directoryFilters.\nfunc (v *View) filterFunc() func(protocol.DocumentURI) bool {\n\tv.filterFuncOnce.Do(func() {\n\t\tfolderDir := v.folder.Dir.Path()\n\t\tgomodcache := v.folder.Env.GOMODCACHE\n\t\tvar filters []string\n\t\tfilters = append(filters, v.folder.Options.DirectoryFilters...)\n\t\tif pref, ok := strings.CutPrefix(gomodcache, folderDir); ok {\n\t\t\tmodcacheFilter := \"-\" + strings.TrimPrefix(filepath.ToSlash(pref), \"/\")\n\t\t\tfilters = append(filters, modcacheFilter)\n\t\t}\n\t\tpathIncluded := PathIncludeFunc(filters)\n\t\tv._filterFunc = func(uri protocol.DocumentURI) bool {\n\t\t\t// Only filter relative to the configured root directory.\n\t\t\tif pathutil.InDir(folderDir, uri.Path()) {\n\t\t\t\treturn relPathExcludedByFilter(strings.TrimPrefix(uri.Path(), folderDir), pathIncluded)\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t})\n\treturn v._filterFunc\n}\n\n// shutdown releases resources associated with the view.\nfunc (v *View) shutdown() {\n\t// Cancel the initial workspace load if it is still running.\n\tv.cancelInitialWorkspaceLoad()\n\tv.importsState.stopTimer()\n\tif v.modcacheState != nil {\n\t\tv.modcacheState.stopTimer()\n\t}\n\n\tv.snapshotMu.Lock()\n\tif v.snapshot != nil {\n\t\tv.snapshot.cancel()\n\t\tv.snapshot.decref()\n\t\tv.snapshot = nil\n\t}\n\tv.snapshotMu.Unlock()\n}\n\n// ScanImports scans the module cache synchronously.\n// For use in tests.\nfunc (v *View) ScanImports() {\n\tgomodcache := v.folder.Env.GOMODCACHE\n\tdirCache := v.importsState.modCache.dirCache(gomodcache)\n\timports.ScanModuleCache(gomodcache, dirCache, log.Printf)\n}\n\n// IgnoredFile reports if a file would be ignored by a `go list` of the whole\n// workspace.\n//\n// While go list ./... skips directories starting with '.', '_', or 'testdata',\n// gopls may still load them via file queries. Explicitly filter them out.\nfunc (s *Snapshot) IgnoredFile(uri protocol.DocumentURI) bool {\n\t// Fast path: if uri doesn't contain '.', '_', or 'testdata', it is not\n\t// possible that it is ignored.\n\t{\n\t\turiStr := string(uri)\n\t\tif !strings.Contains(uriStr, \".\") && !strings.Contains(uriStr, \"_\") && !strings.Contains(uriStr, \"testdata\") {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn s.view.ignoreFilter.ignored(uri.Path())\n}\n\n// An ignoreFilter implements go list's exclusion rules via its 'ignored' method.\ntype ignoreFilter struct {\n\tprefixes []string // root dirs, ending in filepath.Separator\n}\n\n// newIgnoreFilter returns a new ignoreFilter implementing exclusion rules\n// relative to the provided directories.\nfunc newIgnoreFilter(dirs []string) *ignoreFilter {\n\tf := new(ignoreFilter)\n\tfor _, d := range dirs {\n\t\tf.prefixes = append(f.prefixes, filepath.Clean(d)+string(filepath.Separator))\n\t}\n\treturn f\n}\n\nfunc (f *ignoreFilter) ignored(filename string) bool {\n\tfor _, prefix := range f.prefixes {\n\t\tif suffix, ok := strings.CutPrefix(filename, prefix); ok {\n\t\t\tif checkIgnored(suffix) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// checkIgnored implements go list's exclusion rules.\n// Quoting “go help list”:\n//\n//\tDirectory and file names that begin with \".\" or \"_\" are ignored\n//\tby the go tool, as are directories named \"testdata\".\nfunc checkIgnored(suffix string) bool {\n\t// Note: this could be further optimized by writing a HasSegment helper, a\n\t// segment-boundary respecting variant of strings.Contains.\n\tfor component := range strings.SplitSeq(suffix, string(filepath.Separator)) {\n\t\tif len(component) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif component[0] == '.' || component[0] == '_' || component == \"testdata\" {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Snapshot returns the current snapshot for the view, and a\n// release function that must be called when the Snapshot is\n// no longer needed.\n//\n// The resulting error is non-nil if and only if the view is shut down, in\n// which case the resulting release function will also be nil.\nfunc (v *View) Snapshot() (*Snapshot, func(), error) {\n\tv.snapshotMu.Lock()\n\tdefer v.snapshotMu.Unlock()\n\tif v.snapshot == nil {\n\t\treturn nil, nil, errors.New(\"view is shutdown\")\n\t}\n\treturn v.snapshot, v.snapshot.Acquire(), nil\n}\n\n// initialize loads the metadata (and currently, file contents, due to\n// golang/go#57558) for the main package query of the View, which depends on\n// the view type (see ViewType). If s.initialized is already true, initialize\n// is a no op.\n//\n// The first attempt--which populates the first snapshot for a new view--must\n// be allowed to run to completion without being cancelled.\n//\n// Subsequent attempts are triggered by conditions where gopls can't enumerate\n// specific packages that require reloading, such as a change to a go.mod file.\n// These attempts may be cancelled, and then retried by a later call.\n//\n// Postcondition: if ctx was not cancelled, s.initialized is true, s.initialErr\n// holds the error resulting from initialization, if any, and s.metadata holds\n// the resulting metadata graph.\nfunc (s *Snapshot) initialize(ctx context.Context, firstAttempt bool) {\n\t// Acquire initializationSema, which is\n\t// (in effect) a mutex with a timeout.\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn\n\tcase s.view.initializationSema <- struct{}{}:\n\t}\n\n\tdefer func() {\n\t\t<-s.view.initializationSema\n\t}()\n\n\ts.mu.Lock()\n\tinitialized := s.initialized\n\ts.mu.Unlock()\n\n\tif initialized {\n\t\treturn\n\t}\n\n\tdefer func() {\n\t\tif firstAttempt {\n\t\t\tclose(s.view.initialWorkspaceLoad)\n\t\t}\n\t}()\n\n\t// TODO(rFindley): we should only locate template files on the first attempt,\n\t// or guard it via a different mechanism.\n\ts.locateTemplateFiles(ctx)\n\n\t// Collect module paths to load by parsing go.mod files. If a module fails to\n\t// parse, capture the parsing failure as a critical diagnostic.\n\tvar scopes []loadScope           // scopes to load\n\tvar modDiagnostics []*Diagnostic // diagnostics for broken go.mod files\n\taddError := func(uri protocol.DocumentURI, err error) {\n\t\tmodDiagnostics = append(modDiagnostics, &Diagnostic{\n\t\t\tURI:      uri,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tSource:   ListError,\n\t\t\tMessage:  err.Error(),\n\t\t})\n\t}\n\n\tif len(s.view.workspaceModFiles) > 0 {\n\t\tfor modURI := range s.view.workspaceModFiles {\n\t\t\t// Verify that the modfile is valid before trying to load it.\n\t\t\t//\n\t\t\t// TODO(rfindley): now that we no longer need to parse the modfile in\n\t\t\t// order to load scope, we could move these diagnostics to a more general\n\t\t\t// location where we diagnose problems with modfiles or the workspace.\n\t\t\t//\n\t\t\t// Be careful not to add context cancellation errors as critical module\n\t\t\t// errors.\n\t\t\tfh, err := s.ReadFile(ctx, modURI)\n\t\t\tif err != nil {\n\t\t\t\tif ctx.Err() != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\taddError(modURI, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparsed, err := s.ParseMod(ctx, fh)\n\t\t\tif err != nil {\n\t\t\t\tif ctx.Err() != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\taddError(modURI, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif parsed.File == nil || parsed.File.Module == nil {\n\t\t\t\taddError(modURI, fmt.Errorf(\"no module path for %s\", modURI))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Previously, we loaded <modulepath>/... for each module path, but that\n\t\t\t// is actually incorrect when the pattern may match packages in more than\n\t\t\t// one module. See golang/go#59458 for more details.\n\t\t\tscopes = append(scopes, moduleLoadScope{dir: modURI.DirPath(), modulePath: parsed.File.Module.Mod.Path})\n\t\t}\n\t} else {\n\t\tscopes = append(scopes, viewLoadScope{})\n\t}\n\n\t// If we're loading anything, ensure we also load builtin,\n\t// since it provides fake definitions (and documentation)\n\t// for types like int that are used everywhere.\n\tif len(scopes) > 0 {\n\t\tscopes = append(scopes, packageLoadScope(\"builtin\"))\n\t}\n\tloadErr := s.load(ctx, NetworkOK, scopes...)\n\n\t// A failure is retryable if it may have been due to context cancellation,\n\t// and this is not the initial workspace load (firstAttempt==true).\n\t//\n\t// The IWL runs on a detached context with a long (~10m) timeout, so\n\t// if the context was canceled we consider loading to have failed\n\t// permanently.\n\tif loadErr != nil && ctx.Err() != nil && !firstAttempt {\n\t\treturn\n\t}\n\n\tvar initialErr *InitializationError\n\tswitch {\n\tcase loadErr != nil && ctx.Err() != nil:\n\t\tevent.Error(ctx, fmt.Sprintf(\"initial workspace load: %v\", loadErr), loadErr)\n\t\tinitialErr = &InitializationError{\n\t\t\tMainError: loadErr,\n\t\t}\n\tcase loadErr != nil:\n\t\tevent.Error(ctx, \"initial workspace load failed\", loadErr)\n\t\textractedDiags := s.extractGoCommandErrors(ctx, loadErr)\n\t\tinitialErr = &InitializationError{\n\t\t\tMainError:   loadErr,\n\t\t\tDiagnostics: moremaps.Group(extractedDiags, byURI),\n\t\t}\n\tcase s.view.workspaceModFilesErr != nil:\n\t\tinitialErr = &InitializationError{\n\t\t\tMainError: s.view.workspaceModFilesErr,\n\t\t}\n\tcase len(modDiagnostics) > 0:\n\t\tinitialErr = &InitializationError{\n\t\t\tMainError: errors.New(modDiagnostics[0].Message),\n\t\t}\n\t}\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\ts.initialized = true\n\ts.initialErr = initialErr\n}\n\n// A StateChange describes external state changes that may affect a snapshot.\n//\n// By far the most common of these is a change to file state, but a query of\n// module upgrade information or vulnerabilities also affects gopls' behavior.\ntype StateChange struct {\n\tModifications      []file.Modification // if set, the raw modifications originating this change\n\tFiles              map[protocol.DocumentURI]file.Handle\n\tModuleUpgrades     map[protocol.DocumentURI]map[string]string\n\tVulns              map[protocol.DocumentURI]*vulncheck.Result\n\tCompilerOptDetails map[protocol.DocumentURI]bool // package directory -> whether or not we want details\n}\n\n// InvalidateView processes the provided state change, invalidating any derived\n// results that depend on the changed state.\n//\n// The resulting snapshot is non-nil, representing the outcome of the state\n// change. The second result is a function that must be called to release the\n// snapshot when the snapshot is no longer needed.\n//\n// An error is returned if the given view is no longer active in the session.\nfunc (s *Session) InvalidateView(ctx context.Context, view *View, changed StateChange) (*Snapshot, func(), error) {\n\ts.viewMu.Lock()\n\tdefer s.viewMu.Unlock()\n\n\tif !slices.Contains(s.views, view) {\n\t\treturn nil, nil, fmt.Errorf(\"view is no longer active\")\n\t}\n\tsnapshot, release, _ := s.invalidateViewLocked(ctx, view, changed)\n\treturn snapshot, release, nil\n}\n\n// invalidateViewLocked invalidates the content of the given view.\n// (See [Session.InvalidateView]).\n//\n// The resulting bool reports whether the View needs to be re-diagnosed.\n// (See [Snapshot.clone]).\n//\n// s.viewMu must be held while calling this method.\nfunc (s *Session) invalidateViewLocked(ctx context.Context, v *View, changed StateChange) (*Snapshot, func(), bool) {\n\t// Detach the context so that content invalidation cannot be canceled.\n\tctx = xcontext.Detach(ctx)\n\n\t// This should be the only time we hold the view's snapshot lock for any period of time.\n\tv.snapshotMu.Lock()\n\tdefer v.snapshotMu.Unlock()\n\n\tprevSnapshot := v.snapshot\n\n\tif prevSnapshot == nil {\n\t\tpanic(\"invalidateContent called after shutdown\")\n\t}\n\n\t// Cancel all still-running previous requests, since they would be\n\t// operating on stale data.\n\tprevSnapshot.cancel()\n\n\t// Do not clone a snapshot until its view has finished initializing.\n\t//\n\t// TODO(rfindley): shouldn't we do this before canceling?\n\tprevSnapshot.AwaitInitialized(ctx)\n\n\tvar needsDiagnosis bool\n\ts.snapshotWG.Add(1)\n\tv.snapshot, needsDiagnosis = prevSnapshot.clone(ctx, v.baseCtx, changed, s.snapshotWG.Done)\n\n\t// Remove the initial reference created when prevSnapshot was created.\n\tprevSnapshot.decref()\n\n\t// Return a second lease to the caller.\n\treturn v.snapshot, v.snapshot.Acquire(), needsDiagnosis\n}\n\n// defineView computes the view definition for the provided workspace folder\n// and URI.\n//\n// If forURI is non-empty, this view should be the best view including forURI.\n// Otherwise, it is the default view for the folder.\n//\n// defineView may return an error if the context is cancelled, or the\n// workspace folder path is invalid.\n//\n// Note: keep this function in sync with [RelevantViews].\n//\n// TODO(rfindley): we should be able to remove the error return, as\n// findModules is going away, and all other I/O is memoized.\n//\n// TODO(rfindley): pass in a narrower interface for the file.Source\n// (e.g. fileExists func(DocumentURI) bool) to make clear that this\n// process depends only on directory information, not file contents.\nfunc defineView(ctx context.Context, fs file.Source, folder *Folder, forFile file.Handle) (*viewDefinition, error) {\n\tif err := checkPathValid(folder.Dir.Path()); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid workspace folder path: %w; check that the spelling of the configured workspace folder path agrees with the spelling reported by the operating system\", err)\n\t}\n\tdir := folder.Dir.Path()\n\tif forFile != nil {\n\t\tdir = forFile.URI().DirPath()\n\t}\n\n\tdef := new(viewDefinition)\n\tdef.folder = folder\n\n\tif forFile != nil && fileKind(forFile) == file.Go {\n\t\t// If the file has GOOS/GOARCH build constraints that\n\t\t// don't match the folder's environment (which comes from\n\t\t// 'go env' in the folder, plus user options),\n\t\t// add those constraints to the viewDefinition's environment.\n\n\t\t// Content trimming is nontrivial, so do this outside of the loop below.\n\t\t// Keep this in sync with [RelevantViews].\n\t\tpath := forFile.URI().Path()\n\t\tif content, err := forFile.Content(); err == nil {\n\t\t\t// Note the err == nil condition above: by convention a non-existent file\n\t\t\t// does not have any constraints. See the related note in [RelevantViews]: this\n\t\t\t// choice of behavior shouldn't actually matter. In this case, we should\n\t\t\t// only call defineView with Overlays, which always have content.\n\t\t\tcontent = trimContentForPortMatch(content)\n\t\t\tviewPort := port{def.folder.Env.GOOS, def.folder.Env.GOARCH}\n\t\t\tif !viewPort.matches(path, content) {\n\t\t\t\tfor _, p := range preferredPorts {\n\t\t\t\t\tif p.matches(path, content) {\n\t\t\t\t\t\tif def.envOverlay == nil {\n\t\t\t\t\t\t\tdef.envOverlay = make(map[string]string)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdef.envOverlay[\"GOOS\"] = p.GOOS\n\t\t\t\t\t\tdef.envOverlay[\"GOARCH\"] = p.GOARCH\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar err error\n\tdirURI := protocol.URIFromPath(dir)\n\tgoworkFromEnv := false\n\tif folder.Env.ExplicitGOWORK != \"off\" && folder.Env.ExplicitGOWORK != \"\" {\n\t\tgoworkFromEnv = true\n\t\tdef.gowork = protocol.URIFromPath(folder.Env.ExplicitGOWORK)\n\t} else {\n\t\tdef.gowork, err = findRootPattern(ctx, dirURI, \"go.work\", fs)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// When deriving the best view for a given file, we only want to search\n\t// up the directory hierarchy for modfiles.\n\tdef.gomod, err = findRootPattern(ctx, dirURI, \"go.mod\", fs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Determine how we load and where to load package information for this view\n\t//\n\t// Specifically, set\n\t//  - def.typ\n\t//  - def.root\n\t//  - def.workspaceModFiles, and\n\t//  - def.envOverlay.\n\n\t// If GOPACKAGESDRIVER is set it takes precedence.\n\tif def.folder.Env.EffectiveGOPACKAGESDRIVER != \"\" {\n\t\tdef.typ = GoPackagesDriverView\n\t\tdef.root = dirURI\n\t\treturn def, nil\n\t}\n\n\t// From go.dev/ref/mod, module mode is active if GO111MODULE=on, or\n\t// GO111MODULE=auto or \"\" and we are inside a module or have a GOWORK value.\n\t// But gopls is less strict, allowing GOPATH mode if GO111MODULE=\"\", and\n\t// AdHoc views if no module is found.\n\n\t// gomodWorkspace is a helper to compute the correct set of workspace\n\t// modfiles for a go.mod file, based on folder options.\n\tgomodWorkspace := func() map[protocol.DocumentURI]unit {\n\t\tmodFiles := map[protocol.DocumentURI]struct{}{def.gomod: {}}\n\t\tif folder.Options.IncludeReplaceInWorkspace {\n\t\t\tincludingReplace, err := goModModules(ctx, def.gomod, fs)\n\t\t\tif err == nil {\n\t\t\t\tmodFiles = includingReplace\n\t\t\t} else {\n\t\t\t\t// If the go.mod file fails to parse, we don't know anything about\n\t\t\t\t// replace directives, so fall back to a view of just the root module.\n\t\t\t}\n\t\t}\n\t\treturn modFiles\n\t}\n\n\t// Prefer a go.work file if it is available and contains the module relevant\n\t// to forURI.\n\tif def.adjustedGO111MODULE() != \"off\" && folder.Env.ExplicitGOWORK != \"off\" && def.gowork != \"\" {\n\t\tdef.typ = GoWorkView\n\t\tif goworkFromEnv {\n\t\t\t// The go.work file could be anywhere, which can lead to confusing error\n\t\t\t// messages.\n\t\t\tdef.root = dirURI\n\t\t} else {\n\t\t\t// The go.work file could be anywhere, which can lead to confusing error\n\t\t\tdef.root = def.gowork.Dir()\n\t\t}\n\t\tdef.workspaceModFiles, def.workspaceModFilesErr = goWorkModules(ctx, def.gowork, fs)\n\n\t\t// If forURI is in a module but that module is not\n\t\t// included in the go.work file, use a go.mod view with GOWORK=off.\n\t\tif forFile != nil && def.workspaceModFilesErr == nil && def.gomod != \"\" {\n\t\t\tif _, ok := def.workspaceModFiles[def.gomod]; !ok {\n\t\t\t\tdef.typ = GoModView\n\t\t\t\tdef.root = def.gomod.Dir()\n\t\t\t\tdef.workspaceModFiles = gomodWorkspace()\n\t\t\t\tif def.envOverlay == nil {\n\t\t\t\t\tdef.envOverlay = make(map[string]string)\n\t\t\t\t}\n\t\t\t\tdef.envOverlay[\"GOWORK\"] = \"off\"\n\t\t\t}\n\t\t}\n\t\treturn def, nil\n\t}\n\n\t// Otherwise, use the active module, if in module mode.\n\t//\n\t// Note, we could override GO111MODULE here via envOverlay if we wanted to\n\t// support the case where someone opens a module with GO111MODULE=off. But\n\t// that is probably not worth worrying about (at this point, folks probably\n\t// shouldn't be setting GO111MODULE).\n\tif def.adjustedGO111MODULE() != \"off\" && def.gomod != \"\" {\n\t\tdef.typ = GoModView\n\t\tdef.root = def.gomod.Dir()\n\t\tdef.workspaceModFiles = gomodWorkspace()\n\t\treturn def, nil\n\t}\n\n\t// Check if the workspace is within any GOPATH directory.\n\tinGOPATH := false\n\tfor _, gp := range filepath.SplitList(folder.Env.GOPATH) {\n\t\tif pathutil.InDir(filepath.Join(gp, \"src\"), dir) {\n\t\t\tinGOPATH = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif def.adjustedGO111MODULE() != \"on\" && inGOPATH {\n\t\tdef.typ = GOPATHView\n\t\tdef.root = dirURI\n\t\treturn def, nil\n\t}\n\n\t// We're not in a workspace, module, or GOPATH, so have no better choice than\n\t// an ad-hoc view.\n\tdef.typ = AdHocView\n\tdef.root = dirURI\n\treturn def, nil\n}\n\n// FetchGoEnv queries the environment and Go command to collect environment\n// variables necessary for the workspace folder.\nfunc FetchGoEnv(ctx context.Context, folder protocol.DocumentURI, opts *settings.Options) (*GoEnv, error) {\n\tdir := folder.Path()\n\t// All of the go commands invoked here should be fast. No need to share a\n\t// runner with other operations.\n\trunner := new(gocommand.Runner)\n\tinv := gocommand.Invocation{\n\t\tWorkingDir: dir,\n\t\tEnv:        opts.EnvSlice(),\n\t}\n\n\tvar (\n\t\tenv = new(GoEnv)\n\t\terr error\n\t)\n\tenvvars := map[string]*string{\n\t\t\"GOOS\":        &env.GOOS,\n\t\t\"GOARCH\":      &env.GOARCH,\n\t\t\"GOCACHE\":     &env.GOCACHE,\n\t\t\"GOPATH\":      &env.GOPATH,\n\t\t\"GOPRIVATE\":   &env.GOPRIVATE,\n\t\t\"GOMODCACHE\":  &env.GOMODCACHE,\n\t\t\"GOFLAGS\":     &env.GOFLAGS,\n\t\t\"GO111MODULE\": &env.GO111MODULE,\n\t\t\"GOTOOLCHAIN\": &env.GOTOOLCHAIN,\n\t\t\"GOROOT\":      &env.GOROOT,\n\t}\n\tif err := loadGoEnv(ctx, dir, opts.EnvSlice(), runner, envvars); err != nil {\n\t\treturn nil, err\n\t}\n\n\tenv.GoVersion, err = gocommand.GoVersion(ctx, inv, runner)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tenv.GoVersionOutput, err = gocommand.GoVersionOutput(ctx, inv, runner)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// The value of GOPACKAGESDRIVER is not returned through the go command.\n\tif driver, ok := opts.Env[\"GOPACKAGESDRIVER\"]; ok {\n\t\tif driver != \"off\" {\n\t\t\tenv.EffectiveGOPACKAGESDRIVER = driver\n\t\t}\n\t} else if driver := os.Getenv(\"GOPACKAGESDRIVER\"); driver != \"off\" {\n\t\tenv.EffectiveGOPACKAGESDRIVER = driver\n\t\t// A user may also have a gopackagesdriver binary on their machine, which\n\t\t// works the same way as setting GOPACKAGESDRIVER.\n\t\t//\n\t\t// TODO(rfindley): remove this call to LookPath. We should not support this\n\t\t// undocumented method of setting GOPACKAGESDRIVER.\n\t\tif env.EffectiveGOPACKAGESDRIVER == \"\" {\n\t\t\ttool, err := exec.LookPath(\"gopackagesdriver\")\n\t\t\tif err == nil && tool != \"\" {\n\t\t\t\tenv.EffectiveGOPACKAGESDRIVER = tool\n\t\t\t}\n\t\t}\n\t}\n\n\t// While GOWORK is available through the Go command, we want to differentiate\n\t// between an explicit GOWORK value and one which is implicit from the file\n\t// system. The former doesn't change unless the environment changes.\n\tif gowork, ok := opts.Env[\"GOWORK\"]; ok {\n\t\tenv.ExplicitGOWORK = gowork\n\t} else {\n\t\tenv.ExplicitGOWORK = os.Getenv(\"GOWORK\")\n\t}\n\treturn env, nil\n}\n\n// loadGoEnv loads `go env` values into the provided map, keyed by Go variable\n// name.\nfunc loadGoEnv(ctx context.Context, dir string, configEnv []string, runner *gocommand.Runner, vars map[string]*string) error {\n\t// We can save ~200 ms by requesting only the variables we care about.\n\targs := []string{\"-json\"}\n\tfor k := range vars {\n\t\targs = append(args, k)\n\t}\n\n\tinv := gocommand.Invocation{\n\t\tVerb:       \"env\",\n\t\tArgs:       args,\n\t\tEnv:        configEnv,\n\t\tWorkingDir: dir,\n\t}\n\tstdout, err := runner.Run(ctx, inv)\n\tif err != nil {\n\t\treturn err\n\t}\n\tenvMap := make(map[string]string)\n\tif err := json.Unmarshal(stdout.Bytes(), &envMap); err != nil {\n\t\treturn fmt.Errorf(\"internal error unmarshaling JSON from 'go env': %w\", err)\n\t}\n\tfor key, ptr := range vars {\n\t\t*ptr = envMap[key]\n\t}\n\n\treturn nil\n}\n\n// findRootPattern looks for files with the given basename in dir or any parent\n// directory of dir, using the provided FileSource. It returns the first match,\n// starting from dir and search parents.\n//\n// The resulting string is either the file path of a matching file with the\n// given basename, or \"\" if none was found.\n//\n// findRootPattern only returns an error in the case of context cancellation.\nfunc findRootPattern(ctx context.Context, dirURI protocol.DocumentURI, basename string, fs file.Source) (protocol.DocumentURI, error) {\n\tdir := dirURI.Path()\n\tfor dir != \"\" {\n\t\ttarget := filepath.Join(dir, basename)\n\t\turi := protocol.URIFromPath(target)\n\t\tfh, err := fs.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn \"\", err // context cancelled\n\t\t}\n\t\tif fileExists(fh) {\n\t\t\treturn uri, nil\n\t\t}\n\t\t// Trailing separators must be trimmed, otherwise filepath.Split is a noop.\n\t\tnext, _ := filepath.Split(strings.TrimRight(dir, string(filepath.Separator)))\n\t\tif next == dir {\n\t\t\tbreak\n\t\t}\n\t\tdir = next\n\t}\n\treturn \"\", nil\n}\n\n// checkPathValid performs an OS-specific path validity check. The\n// implementation varies for filesystems that are case-insensitive\n// (e.g. macOS, Windows), and for those that disallow certain file\n// names (e.g. path segments ending with a period on Windows, or\n// reserved names such as \"com\"; see\n// https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file).\nvar checkPathValid = defaultCheckPathValid\n\n// CheckPathValid checks whether a directory is suitable as a workspace folder.\nfunc CheckPathValid(dir string) error { return checkPathValid(dir) }\n\nfunc defaultCheckPathValid(path string) error {\n\treturn nil\n}\n\n// IsGoPrivatePath reports whether target is a private import path, as identified\n// by the GOPRIVATE environment variable.\nfunc (s *Snapshot) IsGoPrivatePath(target string) bool {\n\treturn globsMatchPath(s.view.folder.Env.GOPRIVATE, target)\n}\n\n// ModuleUpgrades returns known module upgrades for the dependencies of\n// modfile.\nfunc (s *Snapshot) ModuleUpgrades(modfile protocol.DocumentURI) map[string]string {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tupgrades := map[string]string{}\n\torig, _ := s.moduleUpgrades.Get(modfile)\n\tmaps.Copy(upgrades, orig)\n\treturn upgrades\n}\n\n// MaxGovulncheckResultsAge defines the maximum vulnerability age considered\n// valid by gopls.\n//\n// Mutable for testing.\nvar MaxGovulncheckResultAge = 1 * time.Hour\n\n// Vulnerabilities returns known vulnerabilities for the given modfile.\n//\n// Results more than an hour old are excluded.\n//\n// TODO(suzmue): replace command.Vuln with a different type, maybe\n// https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck/govulnchecklib#Summary?\n//\n// TODO(rfindley): move to snapshot.go\nfunc (s *Snapshot) Vulnerabilities(modfiles ...protocol.DocumentURI) map[protocol.DocumentURI]*vulncheck.Result {\n\tm := make(map[protocol.DocumentURI]*vulncheck.Result)\n\tnow := time.Now()\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif len(modfiles) == 0 { // empty means all modfiles\n\t\tmodfiles = slices.Collect(s.vulns.Keys())\n\t}\n\tfor _, modfile := range modfiles {\n\t\tvuln, _ := s.vulns.Get(modfile)\n\t\tif vuln != nil && now.Sub(vuln.AsOf) > MaxGovulncheckResultAge {\n\t\t\tvuln = nil\n\t\t}\n\t\tm[modfile] = vuln\n\t}\n\treturn m\n}\n\n// GoVersion returns the effective release Go version (the X in go1.X) for this\n// view.\nfunc (v *View) GoVersion() int {\n\treturn v.folder.Env.GoVersion\n}\n\n// GoVersionString returns the effective Go version string for this view.\n//\n// Unlike [GoVersion], this encodes the minor version and commit hash information.\nfunc (v *View) GoVersionString() string {\n\treturn gocommand.ParseGoVersionOutput(v.folder.Env.GoVersionOutput)\n}\n\n// GoVersionString is temporarily available from the snapshot.\n//\n// TODO(rfindley): refactor so that this method is not necessary.\nfunc (s *Snapshot) GoVersionString() string {\n\treturn s.view.GoVersionString()\n}\n\n// Copied from\n// https://cs.opensource.google/go/go/+/master:src/cmd/go/internal/str/path.go;l=58;drc=2910c5b4a01a573ebc97744890a07c1a3122c67a\nfunc globsMatchPath(globs, target string) bool {\n\tfor globs != \"\" {\n\t\t// Extract next non-empty glob in comma-separated list.\n\t\tvar glob string\n\t\tif i := strings.Index(globs, \",\"); i >= 0 {\n\t\t\tglob, globs = globs[:i], globs[i+1:]\n\t\t} else {\n\t\t\tglob, globs = globs, \"\"\n\t\t}\n\t\tif glob == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// A glob with N+1 path elements (N slashes) needs to be matched\n\t\t// against the first N+1 path elements of target,\n\t\t// which end just before the N+1'th slash.\n\t\tn := strings.Count(glob, \"/\")\n\t\tprefix := target\n\t\t// Walk target, counting slashes, truncating at the N+1'th slash.\n\t\tfor i := range len(target) {\n\t\t\tif target[i] == '/' {\n\t\t\t\tif n == 0 {\n\t\t\t\t\tprefix = target[:i]\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tn--\n\t\t\t}\n\t\t}\n\t\tif n > 0 {\n\t\t\t// Not enough prefix elements.\n\t\t\tcontinue\n\t\t}\n\t\tmatched, _ := path.Match(glob, prefix)\n\t\tif matched {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// TODO(rfindley): clean up the redundancy of allFilesExcluded,\n// pathExcludedByFilterFunc, pathExcludedByFilter, view.filterFunc...\nfunc allFilesExcluded(files []string, filterFunc func(protocol.DocumentURI) bool) bool {\n\tfor _, f := range files {\n\t\turi := protocol.URIFromPath(f)\n\t\tif !filterFunc(uri) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc relPathExcludedByFilter(path string, pathIncluded func(string) bool) bool {\n\tpath = strings.TrimPrefix(filepath.ToSlash(path), \"/\")\n\treturn !pathIncluded(path)\n}\n"
  },
  {
    "path": "gopls/internal/cache/view_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage cache\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestCaseInsensitiveFilesystem(t *testing.T) {\n\tbase := t.TempDir()\n\n\tinner := filepath.Join(base, \"a/B/c/DEFgh\")\n\tif err := os.MkdirAll(inner, 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfile := filepath.Join(inner, \"f.go\")\n\tif err := os.WriteFile(file, []byte(\"hi\"), 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := os.Stat(filepath.Join(inner, \"F.go\")); err != nil {\n\t\tt.Skip(\"filesystem is case-sensitive\")\n\t}\n\n\ttests := []struct {\n\t\tpath string\n\t\terr  bool\n\t}{\n\t\t{file, false},\n\t\t{filepath.Join(inner, \"F.go\"), true},\n\t\t{filepath.Join(base, \"a/b/c/defgh/f.go\"), true},\n\t}\n\tfor _, tt := range tests {\n\t\terr := checkPathValid(tt.path)\n\t\tif err != nil != tt.err {\n\t\t\tt.Errorf(\"checkPathValid(%q) = %v, wanted error: %v\", tt.path, err, tt.err)\n\t\t}\n\t}\n}\n\nfunc TestInVendor(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tpath     string\n\t\tinVendor bool\n\t}{\n\t\t{\"foo/vendor/x.go\", false},\n\t\t{\"foo/vendor/x/x.go\", true},\n\t\t{\"foo/x.go\", false},\n\t\t{\"foo/vendor/foo.txt\", false},\n\t\t{\"foo/vendor/modules.txt\", false},\n\t} {\n\t\tif got := inVendor(protocol.URIFromPath(tt.path)); got != tt.inVendor {\n\t\t\tt.Errorf(\"expected %s inVendor %v, got %v\", tt.path, tt.inVendor, got)\n\t\t}\n\t}\n}\n\nfunc TestFilters(t *testing.T) {\n\ttests := []struct {\n\t\tfilters  []string\n\t\tincluded []string\n\t\texcluded []string\n\t}{\n\t\t{\n\t\t\tincluded: []string{\"x\"},\n\t\t},\n\t\t{\n\t\t\tfilters:  []string{\"-\"},\n\t\t\texcluded: []string{\"x\", \"x/a\"},\n\t\t},\n\t\t{\n\t\t\tfilters:  []string{\"-x\", \"+y\"},\n\t\t\tincluded: []string{\"y\", \"y/a\", \"z\"},\n\t\t\texcluded: []string{\"x\", \"x/a\"},\n\t\t},\n\t\t{\n\t\t\tfilters:  []string{\"-x\", \"+x/y\", \"-x/y/z\"},\n\t\t\tincluded: []string{\"x/y\", \"x/y/a\", \"a\"},\n\t\t\texcluded: []string{\"x\", \"x/a\", \"x/y/z/a\"},\n\t\t},\n\t\t{\n\t\t\tfilters:  []string{\"+foobar\", \"-foo\"},\n\t\t\tincluded: []string{\"foobar\", \"foobar/a\"},\n\t\t\texcluded: []string{\"foo\", \"foo/a\"},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tpathIncluded := PathIncludeFunc(tt.filters)\n\t\tfor _, inc := range tt.included {\n\t\t\tif relPathExcludedByFilter(inc, pathIncluded) {\n\t\t\t\tt.Errorf(\"filters %q excluded %v, wanted included\", tt.filters, inc)\n\t\t\t}\n\t\t}\n\t\tfor _, exc := range tt.excluded {\n\t\t\tif !relPathExcludedByFilter(exc, pathIncluded) {\n\t\t\t\tt.Errorf(\"filters %q included %v, wanted excluded\", tt.filters, exc)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSuffixes(t *testing.T) {\n\ttype file struct {\n\t\tpath string\n\t\twant bool\n\t}\n\ttype cases struct {\n\t\toption []string\n\t\tfiles  []file\n\t}\n\ttests := []cases{\n\t\t{[]string{\"tmpl\", \"gotmpl\"}, []file{ // default\n\t\t\t{\"foo\", false},\n\t\t\t{\"foo.tmpl\", true},\n\t\t\t{\"foo.gotmpl\", true},\n\t\t\t{\"tmpl\", false},\n\t\t\t{\"tmpl.go\", false}},\n\t\t},\n\t\t{[]string{\"tmpl\", \"gotmpl\", \"html\", \"gohtml\"}, []file{\n\t\t\t{\"foo.gotmpl\", true},\n\t\t\t{\"foo.html\", true},\n\t\t\t{\"foo.gohtml\", true},\n\t\t\t{\"html\", false}},\n\t\t},\n\t\t{[]string{\"tmpl\", \"gotmpl\", \"\"}, []file{ // possible user mistake\n\t\t\t{\"foo.gotmpl\", true},\n\t\t\t{\"foo.go\", false},\n\t\t\t{\"foo\", false}},\n\t\t},\n\t}\n\tfor _, a := range tests {\n\t\tsuffixes := a.option\n\t\tfor _, b := range a.files {\n\t\t\tgot := fileHasExtension(b.path, suffixes)\n\t\t\tif got != b.want {\n\t\t\t\tt.Errorf(\"got %v, want %v, option %q, file %q (%+v)\",\n\t\t\t\t\tgot, b.want, a.option, b.path, b)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestIgnoreFilter(t *testing.T) {\n\ttests := []struct {\n\t\tdirs []string\n\t\tpath string\n\t\twant bool\n\t}{\n\t\t{[]string{\"a\"}, \"a/testdata/foo\", true},\n\t\t{[]string{\"a\"}, \"a/_ignore/foo\", true},\n\t\t{[]string{\"a\"}, \"a/.ignore/foo\", true},\n\t\t{[]string{\"a\"}, \"b/testdata/foo\", false},\n\t\t{[]string{\"a\"}, \"testdata/foo\", false},\n\t\t{[]string{\"a\", \"b\"}, \"b/testdata/foo\", true},\n\t\t{[]string{\"a\"}, \"atestdata/foo\", false},\n\t}\n\n\tfor _, test := range tests {\n\t\t// convert to filepaths, for convenience\n\t\tfor i, dir := range test.dirs {\n\t\t\ttest.dirs[i] = filepath.FromSlash(dir)\n\t\t}\n\t\ttest.path = filepath.FromSlash(test.path)\n\n\t\tf := newIgnoreFilter(test.dirs)\n\t\tif got := f.ignored(test.path); got != test.want {\n\t\t\tt.Errorf(\"newIgnoreFilter(%q).ignore(%q) = %t, want %t\", test.dirs, test.path, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cache/workspace.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake/glob\"\n)\n\n// isGoWork reports if uri is a go.work file.\nfunc isGoWork(uri protocol.DocumentURI) bool {\n\treturn uri.Base() == \"go.work\"\n}\n\n// goWorkModules returns the URIs of go.mod files named by the go.work file.\nfunc goWorkModules(ctx context.Context, gowork protocol.DocumentURI, fs file.Source) (map[protocol.DocumentURI]unit, error) {\n\tfh, err := fs.ReadFile(ctx, gowork)\n\tif err != nil {\n\t\treturn nil, err // canceled\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfilename := gowork.Path()\n\tdir := filepath.Dir(filename)\n\tworkFile, err := modfile.ParseWork(filename, content, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing go.work: %w\", err)\n\t}\n\tvar usedDirs []string\n\tfor _, use := range workFile.Use {\n\t\tusedDirs = append(usedDirs, use.Path)\n\t}\n\treturn localModFiles(dir, usedDirs), nil\n}\n\n// localModFiles builds a set of local go.mod files referenced by\n// goWorkOrModPaths, which is a slice of paths as contained in a go.work 'use'\n// directive or go.mod 'replace' directive (and which therefore may use either\n// '/' or '\\' as a path separator).\nfunc localModFiles(relativeTo string, goWorkOrModPaths []string) map[protocol.DocumentURI]unit {\n\tmodFiles := make(map[protocol.DocumentURI]unit)\n\tfor _, path := range goWorkOrModPaths {\n\t\tmodDir := filepath.FromSlash(path)\n\t\tif !filepath.IsAbs(modDir) {\n\t\t\tmodDir = filepath.Join(relativeTo, modDir)\n\t\t}\n\t\tmodURI := protocol.URIFromPath(filepath.Join(modDir, \"go.mod\"))\n\t\tmodFiles[modURI] = unit{}\n\t}\n\treturn modFiles\n}\n\n// isGoMod reports if uri is a go.mod file.\nfunc isGoMod(uri protocol.DocumentURI) bool {\n\treturn uri.Base() == \"go.mod\"\n}\n\n// isWorkspaceFile reports if uri matches a set of globs defined in workspaceFiles\nfunc isWorkspaceFile(uri protocol.DocumentURI, workspaceFiles []string) bool {\n\tfor _, workspaceFile := range workspaceFiles {\n\t\tg, err := glob.Parse(workspaceFile)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif g.Match(uri.Path()) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// goModModules returns the URIs of \"workspace\" go.mod files defined by a\n// go.mod file. This set is defined to be the given go.mod file itself, as well\n// as the modfiles of any locally replaced modules in the go.mod file.\nfunc goModModules(ctx context.Context, gomod protocol.DocumentURI, fs file.Source) (map[protocol.DocumentURI]unit, error) {\n\tfh, err := fs.ReadFile(ctx, gomod)\n\tif err != nil {\n\t\treturn nil, err // canceled\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfilename := gomod.Path()\n\tdir := filepath.Dir(filename)\n\tmodFile, err := modfile.Parse(filename, content, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar localReplaces []string\n\tfor _, replace := range modFile.Replace {\n\t\tif modfile.IsDirectoryPath(replace.New.Path) {\n\t\t\tlocalReplaces = append(localReplaces, replace.New.Path)\n\t\t}\n\t}\n\tmodFiles := localModFiles(dir, localReplaces)\n\tmodFiles[gomod] = unit{}\n\treturn modFiles, nil\n}\n\n// fileExists reports whether the file has a Content (which may be empty).\n// An overlay exists even if it is not reflected in the file system.\nfunc fileExists(fh file.Handle) bool {\n\t_, err := fh.Content()\n\treturn err == nil\n}\n\n// errExhausted is returned by findModules if the file scan limit is reached.\nvar errExhausted = errors.New(\"exhausted\")\n\n// Limit go.mod search to 1 million files. As a point of reference,\n// Kubernetes has 22K files (as of 2020-11-24).\n//\n// Note: per golang/go#56496, the previous limit of 1M files was too slow, at\n// which point this limit was decreased to 100K.\nconst fileLimit = 100_000\n"
  },
  {
    "path": "gopls/internal/cache/xrefs/xrefs.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package xrefs defines the serializable index of cross-package\n// references that is computed during type checking.\n//\n// See ../references.go for the 'references' query.\npackage xrefs\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n)\n\n// Index constructs a serializable index of outbound cross-references\n// for the specified type-checked package.\nfunc Index(files []*parsego.File, pkg *types.Package, info *types.Info) []byte {\n\t// pkgObjects maps each referenced package Q to a mapping:\n\t// from each referenced symbol in Q to the ordered list\n\t// of references to that symbol from this package.\n\t// A nil types.Object indicates a reference\n\t// to the package as a whole: an import.\n\tpkgObjects := make(map[*types.Package]map[types.Object]*gobObject)\n\n\t// getObjects returns the object-to-references mapping for a package.\n\tgetObjects := func(pkg *types.Package) map[types.Object]*gobObject {\n\t\tobjects, ok := pkgObjects[pkg]\n\t\tif !ok {\n\t\t\tobjects = make(map[types.Object]*gobObject)\n\t\t\tpkgObjects[pkg] = objects\n\t\t}\n\t\treturn objects\n\t}\n\n\tobjectpathFor := new(objectpath.Encoder).For\n\n\tfor fileIndex, pgf := range files {\n\t\tfor cur := range pgf.Cursor().Preorder((*ast.Ident)(nil), (*ast.ImportSpec)(nil)) {\n\t\t\tswitch n := cur.Node().(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\t// Report a reference for each identifier that\n\t\t\t\t// uses a symbol exported from another package.\n\t\t\t\t// (The built-in error.Error method has no package.)\n\t\t\t\tif n.IsExported() {\n\t\t\t\t\tif obj, ok := info.Uses[n]; ok &&\n\t\t\t\t\t\tobj.Pkg() != nil &&\n\t\t\t\t\t\tobj.Pkg() != pkg {\n\n\t\t\t\t\t\t// For instantiations of generic methods,\n\t\t\t\t\t\t// use the generic object (see issue #60622).\n\t\t\t\t\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\t\t\t\t\tobj = fn.Origin()\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tobjects := getObjects(obj.Pkg())\n\t\t\t\t\t\tgobObj, ok := objects[obj]\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tpath, err := objectpathFor(obj)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t// Capitalized but not exported\n\t\t\t\t\t\t\t\t// (e.g. local const/var/type).\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgobObj = &gobObject{Path: path}\n\t\t\t\t\t\t\tobjects[obj] = gobObj\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// golang/go#66683: nodes can under/overflow the file.\n\t\t\t\t\t\t// For example, \"var _ = x.\" creates a SelectorExpr(Sel=Ident(\"_\"))\n\t\t\t\t\t\t// that is beyond EOF. (Arguably Ident.Name should be \"\".)\n\t\t\t\t\t\tif rng, err := pgf.NodeRange(n); err == nil {\n\t\t\t\t\t\t\tgobObj.Refs = append(gobObj.Refs, gobRef{\n\t\t\t\t\t\t\t\tFileIndex: fileIndex,\n\t\t\t\t\t\t\t\tRange:     rng,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.ImportSpec:\n\t\t\t\t// Report a reference from each import path\n\t\t\t\t// string to the imported package.\n\t\t\t\tpkgname := info.PkgNameOf(n)\n\t\t\t\tif pkgname == nil {\n\t\t\t\t\tcontinue // missing import\n\t\t\t\t}\n\t\t\t\tobjects := getObjects(pkgname.Imported())\n\t\t\t\tgobObj, ok := objects[nil]\n\t\t\t\tif !ok {\n\t\t\t\t\tgobObj = &gobObject{Path: \"\"}\n\t\t\t\t\tobjects[nil] = gobObj\n\t\t\t\t}\n\t\t\t\t// golang/go#66683: nodes can under/overflow the file.\n\t\t\t\tif rng, err := pgf.NodeRange(n.Path); err == nil {\n\t\t\t\t\tgobObj.Refs = append(gobObj.Refs, gobRef{\n\t\t\t\t\t\tFileIndex: fileIndex,\n\t\t\t\t\t\tRange:     rng,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tbug.Reportf(\"out of bounds import spec %+v\", n.Path)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Flatten the maps into slices, and sort for determinism.\n\tvar packages []*gobPackage\n\tfor p := range pkgObjects {\n\t\tobjects := pkgObjects[p]\n\t\tgp := &gobPackage{\n\t\t\tPkgPath: metadata.PackagePath(p.Path()),\n\t\t\tObjects: make([]*gobObject, 0, len(objects)),\n\t\t}\n\t\tfor _, gobObj := range objects {\n\t\t\tgp.Objects = append(gp.Objects, gobObj)\n\t\t}\n\t\tsort.Slice(gp.Objects, func(i, j int) bool {\n\t\t\treturn gp.Objects[i].Path < gp.Objects[j].Path\n\t\t})\n\t\tpackages = append(packages, gp)\n\t}\n\tsort.Slice(packages, func(i, j int) bool {\n\t\treturn packages[i].PkgPath < packages[j].PkgPath\n\t})\n\n\treturn packageCodec.Encode(packages)\n}\n\n// Lookup searches a serialized index produced by an indexPackage\n// operation on m, and returns the locations of all references from m\n// to any object in the target set. Each object is denoted by a pair\n// of (package path, object path).\nfunc Lookup(mp *metadata.Package, data []byte, targets map[metadata.PackagePath]map[objectpath.Path]struct{}) (locs []protocol.Location) {\n\tvar packages []*gobPackage\n\tpackageCodec.Decode(data, &packages)\n\tfor _, gp := range packages {\n\t\tif objectSet, ok := targets[gp.PkgPath]; ok {\n\t\t\tfor _, gobObj := range gp.Objects {\n\t\t\t\tif _, ok := objectSet[gobObj.Path]; ok {\n\t\t\t\t\tfor _, ref := range gobObj.Refs {\n\t\t\t\t\t\turi := mp.CompiledGoFiles[ref.FileIndex]\n\t\t\t\t\t\tlocs = append(locs, protocol.Location{\n\t\t\t\t\t\t\tURI:   uri,\n\t\t\t\t\t\t\tRange: ref.Range,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn locs\n}\n\n// -- serialized representation --\n\n// The cross-reference index records the location of all references\n// from one package to symbols defined in other packages\n// (dependencies). It does not record within-package references.\n// The index for package P consists of a list of gopPackage records,\n// each enumerating references to symbols defined a single dependency, Q.\n\n// TODO(adonovan): opt: choose a more compact encoding.\n// The gobRef.Range field is the obvious place to begin.\n\n// (The name says gob but in fact we use frob.)\nvar packageCodec = frob.CodecFor[[]*gobPackage]()\n\n// A gobPackage records the set of outgoing references from the index\n// package to symbols defined in a dependency package.\ntype gobPackage struct {\n\tPkgPath metadata.PackagePath // defining package (Q)\n\tObjects []*gobObject         // set of Q objects referenced by P\n}\n\n// A gobObject records all references to a particular symbol.\ntype gobObject struct {\n\tPath objectpath.Path // symbol name within package; \"\" => import of package itself\n\tRefs []gobRef        // locations of references within P, in lexical order\n}\n\ntype gobRef struct {\n\tFileIndex int            // index of enclosing file within P's CompiledGoFiles\n\tRange     protocol.Range // source range of reference\n}\n"
  },
  {
    "path": "gopls/internal/clonetest/clonetest.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package clonetest provides utility functions for testing Clone operations.\n//\n// The [NonZero] helper may be used to construct a type in which fields are\n// recursively set to a non-zero value. This value can then be cloned, and the\n// [ZeroOut] helper can set values stored in the clone to zero, recursively.\n// Doing so should not mutate the original.\npackage clonetest\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"slices\"\n)\n\n// NonZero returns a T set to some appropriate nonzero value:\n//   - Values of basic type are set to an arbitrary non-zero value.\n//   - Struct fields are set to a non-zero value.\n//   - Array indices are set to a non-zero value.\n//   - Pointers point to a non-zero value.\n//   - Maps and slices are given a non-zero element.\n//   - Chan, Func, Interface, UnsafePointer are all unsupported.\n//\n// NonZero breaks cycles by returning a zero value for recursive types.\nfunc NonZero[T any]() T {\n\tvar x T\n\tt := reflect.TypeOf(x)\n\tif t == nil {\n\t\tpanic(\"untyped nil\")\n\t}\n\tv := nonZeroValue(t, nil)\n\treturn v.Interface().(T)\n}\n\n// nonZeroValue returns a non-zero, addressable value of the given type.\nfunc nonZeroValue(t reflect.Type, seen []reflect.Type) reflect.Value {\n\tif slices.Contains(seen, t) {\n\t\t// Cycle: return the zero value.\n\t\treturn reflect.Zero(t)\n\t}\n\tseen = append(seen, t)\n\tv := reflect.New(t).Elem()\n\tswitch t.Kind() {\n\tcase reflect.Bool:\n\t\tv.SetBool(true)\n\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tv.SetInt(1)\n\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:\n\t\tv.SetUint(1)\n\n\tcase reflect.Float32, reflect.Float64:\n\t\tv.SetFloat(1)\n\n\tcase reflect.Complex64, reflect.Complex128:\n\t\tv.SetComplex(1)\n\n\tcase reflect.Array:\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tv.Index(i).Set(nonZeroValue(t.Elem(), seen))\n\t\t}\n\n\tcase reflect.Map:\n\t\tv2 := reflect.MakeMap(t)\n\t\tv2.SetMapIndex(nonZeroValue(t.Key(), seen), nonZeroValue(t.Elem(), seen))\n\t\tv.Set(v2)\n\n\tcase reflect.Pointer:\n\t\tv2 := nonZeroValue(t.Elem(), seen)\n\t\tv.Set(v2.Addr())\n\n\tcase reflect.Slice:\n\t\tv2 := reflect.Append(v, nonZeroValue(t.Elem(), seen))\n\t\tv.Set(v2)\n\n\tcase reflect.String:\n\t\tv.SetString(\".\")\n\n\tcase reflect.Struct:\n\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\tv.Field(i).Set(nonZeroValue(t.Field(i).Type, seen))\n\t\t}\n\n\tdefault: // Chan, Func, Interface, UnsafePointer\n\t\tpanic(fmt.Sprintf(\"reflect kind %v not supported\", t.Kind()))\n\t}\n\treturn v\n}\n\n// ZeroOut recursively sets values contained in t to zero.\n// Values of king Chan, Func, Interface, UnsafePointer are all unsupported.\n//\n// No attempt is made to handle cyclic values.\nfunc ZeroOut[T any](t *T) {\n\tv := reflect.ValueOf(t).Elem()\n\tzeroOutValue(v)\n}\n\nfunc zeroOutValue(v reflect.Value) {\n\tif v.IsZero() {\n\t\treturn // nothing to do; this also handles untyped nil values\n\t}\n\n\tswitch v.Kind() {\n\tcase reflect.Bool,\n\t\treflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,\n\t\treflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,\n\t\treflect.Float32, reflect.Float64,\n\t\treflect.Complex64, reflect.Complex128,\n\t\treflect.String:\n\n\t\tv.Set(reflect.Zero(v.Type()))\n\n\tcase reflect.Array:\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tzeroOutValue(v.Index(i))\n\t\t}\n\n\tcase reflect.Map:\n\t\titer := v.MapRange()\n\t\tfor iter.Next() {\n\t\t\tmv := iter.Value()\n\t\t\tif mv.CanAddr() {\n\t\t\t\tzeroOutValue(mv)\n\t\t\t} else {\n\t\t\t\tmv = reflect.New(mv.Type()).Elem()\n\t\t\t}\n\t\t\tv.SetMapIndex(iter.Key(), mv)\n\t\t}\n\n\tcase reflect.Pointer:\n\t\tzeroOutValue(v.Elem())\n\n\tcase reflect.Slice:\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tzeroOutValue(v.Index(i))\n\t\t}\n\n\tcase reflect.Struct:\n\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\tzeroOutValue(v.Field(i))\n\t\t}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"reflect kind %v not supported\", v.Kind()))\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/clonetest/clonetest_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage clonetest_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/clonetest\"\n)\n\nfunc Test(t *testing.T) {\n\tdoTest(t, true, false)\n\ttype B bool\n\tdoTest(t, B(true), false)\n\tdoTest(t, 1, 0)\n\tdoTest(t, int(1), 0)\n\tdoTest(t, int8(1), 0)\n\tdoTest(t, int16(1), 0)\n\tdoTest(t, int32(1), 0)\n\tdoTest(t, int64(1), 0)\n\tdoTest(t, uint(1), 0)\n\tdoTest(t, uint8(1), 0)\n\tdoTest(t, uint16(1), 0)\n\tdoTest(t, uint32(1), 0)\n\tdoTest(t, uint64(1), 0)\n\tdoTest(t, uintptr(1), 0)\n\tdoTest(t, float32(1), 0)\n\tdoTest(t, float64(1), 0)\n\tdoTest(t, complex64(1), 0)\n\tdoTest(t, complex128(1), 0)\n\tdoTest(t, [3]int{1, 1, 1}, [3]int{0, 0, 0})\n\tdoTest(t, \".\", \"\")\n\tm1, m2 := map[string]int{\".\": 1}, map[string]int{\".\": 0}\n\tdoTest(t, m1, m2)\n\tdoTest(t, &m1, &m2)\n\tdoTest(t, []int{1}, []int{0})\n\ti, j := 1, 0\n\tdoTest(t, &i, &j)\n\tk, l := &i, &j\n\tdoTest(t, &k, &l)\n\n\ts1, s2 := []int{1}, []int{0}\n\tdoTest(t, &s1, &s2)\n\n\ttype S struct {\n\t\tField int\n\t}\n\tdoTest(t, S{1}, S{0})\n\n\tdoTest(t, []*S{{1}}, []*S{{0}})\n\n\t// An arbitrary recursive type.\n\ttype LinkedList[T any] struct {\n\t\tV    T\n\t\tNext *LinkedList[T]\n\t}\n\tdoTest(t, &LinkedList[int]{V: 1}, &LinkedList[int]{V: 0})\n}\n\n// doTest checks that the result of NonZero matches the nonzero argument, and\n// that zeroing out that result matches the zero argument.\nfunc doTest[T any](t *testing.T, nonzero, zero T) {\n\tgot := clonetest.NonZero[T]()\n\tif diff := cmp.Diff(nonzero, got); diff != \"\" {\n\t\tt.Fatalf(\"NonZero() returned unexpected diff (-want +got):\\n%s\", diff)\n\t}\n\tclonetest.ZeroOut(&got)\n\tif diff := cmp.Diff(zero, got); diff != \"\" {\n\t\tt.Errorf(\"ZeroOut() returned unexpected diff (-want +got):\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cmd/call_hierarchy.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// callHierarchy implements the callHierarchy verb for gopls.\ntype callHierarchy struct {\n\tapp *Application\n}\n\nfunc (c *callHierarchy) Name() string      { return \"call_hierarchy\" }\nfunc (c *callHierarchy) Parent() string    { return c.app.Name() }\nfunc (c *callHierarchy) Usage() string     { return \"<position>\" }\nfunc (c *callHierarchy) ShortHelp() string { return \"display selected identifier's call hierarchy\" }\nfunc (c *callHierarchy) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls call_hierarchy helper/helper.go:8:6\n\t$ gopls call_hierarchy helper/helper.go:#53\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (c *callHierarchy) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"call_hierarchy expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := c.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.CallHierarchyPrepareParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\n\tcallItems, err := cli.server.PrepareCallHierarchy(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(callItems) == 0 {\n\t\treturn fmt.Errorf(\"function declaration identifier not found at %v\", args[0])\n\t}\n\n\tfor _, item := range callItems {\n\t\tincomingCalls, err := cli.server.IncomingCalls(ctx, &protocol.CallHierarchyIncomingCallsParams{Item: item})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor i, call := range incomingCalls {\n\t\t\t// From the spec: CallHierarchyIncomingCall.FromRanges is relative to\n\t\t\t// the caller denoted by CallHierarchyIncomingCall.from.\n\t\t\tprintString, err := callItemPrintString(ctx, cli, call.From, call.From.URI, call.FromRanges)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfmt.Printf(\"caller[%d]: %s\\n\", i, printString)\n\t\t}\n\n\t\tprintString, err := callItemPrintString(ctx, cli, item, \"\", nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Printf(\"identifier: %s\\n\", printString)\n\n\t\toutgoingCalls, err := cli.server.OutgoingCalls(ctx, &protocol.CallHierarchyOutgoingCallsParams{Item: item})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor i, call := range outgoingCalls {\n\t\t\t// From the spec: CallHierarchyOutgoingCall.FromRanges is the range\n\t\t\t// relative to the caller, e.g the item passed to\n\t\t\tprintString, err := callItemPrintString(ctx, cli, call.To, item.URI, call.FromRanges)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfmt.Printf(\"callee[%d]: %s\\n\", i, printString)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// callItemPrintString returns a protocol.CallHierarchyItem object represented as a string.\n// item and call ranges (protocol.Range) are converted to user friendly spans (1-indexed).\nfunc callItemPrintString(ctx context.Context, cli *client, item protocol.CallHierarchyItem, callsURI protocol.DocumentURI, calls []protocol.Range) (string, error) {\n\titemFile, err := cli.openFile(ctx, item.URI)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\titemSpan, err := itemFile.rangeSpan(item.Range)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar callRanges []string\n\tif callsURI != \"\" {\n\t\tcallsFile, err := cli.openFile(ctx, callsURI)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tfor _, rng := range calls {\n\t\t\tcall, err := callsFile.rangeSpan(rng)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\tcallRange := fmt.Sprintf(\"%d:%d-%d\", call.Start().Line(), call.Start().Column(), call.End().Column())\n\t\t\tcallRanges = append(callRanges, callRange)\n\t\t}\n\t}\n\n\tprintString := fmt.Sprintf(\"function %s in %v\", item.Name, itemSpan)\n\tif len(calls) > 0 {\n\t\tprintString = fmt.Sprintf(\"ranges %s in %s from/to %s\", strings.Join(callRanges, \", \"), callsURI.Path(), printString)\n\t}\n\treturn printString, nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/capabilities_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestCapabilities does some minimal validation of the server's adherence to the LSP.\n// The checks in the test are added as changes are made and errors noticed.\nfunc TestCapabilities(t *testing.T) {\n\t// server.DidOpen fails to obtain metadata without go command (e.g. on wasm).\n\ttestenv.NeedsTool(t, \"go\")\n\n\ttmpDir, err := os.MkdirTemp(\"\", \"fake\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttmpFile := filepath.Join(tmpDir, \"fake.go\")\n\tif err := os.WriteFile(tmpFile, []byte(\"\"), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(tmpDir, \"go.mod\"), []byte(\"module fake\\n\\ngo 1.12\\n\"), 0775); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmpDir)\n\n\tapp := New()\n\tctx := context.Background()\n\n\t// Initialize the client.\n\t// (Unlike app.connect, we use minimal Initialize params.)\n\tclient := newClient(app)\n\toptions := settings.DefaultOptions(app.options)\n\tserver := server.New(cache.NewSession(ctx, cache.New(nil)), client, options)\n\tparams := &protocol.ParamInitialize{}\n\tparams.RootURI = protocol.URIFromPath(tmpDir)\n\tparams.Capabilities.Workspace.Configuration = true\n\tif err := client.initialize(ctx, server, params); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer client.terminate(ctx)\n\n\tif err := validateCapabilities(client.initializeResult); err != nil {\n\t\tt.Error(err)\n\t}\n\n\t// Open the file on the server side.\n\turi := protocol.URIFromPath(tmpFile)\n\tif err := server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{\n\t\tTextDocument: protocol.TextDocumentItem{\n\t\t\tURI:        uri,\n\t\t\tLanguageID: \"go\",\n\t\t\tVersion:    1,\n\t\t\tText:       `package main; func main() {};`,\n\t\t},\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// If we are sending a full text change, the change.Range must be nil.\n\t// It is not enough for the Change to be empty, as that is ambiguous.\n\tif err := server.DidChange(ctx, &protocol.DidChangeTextDocumentParams{\n\t\tTextDocument: protocol.VersionedTextDocumentIdentifier{\n\t\t\tTextDocumentIdentifier: protocol.TextDocumentIdentifier{\n\t\t\t\tURI: uri,\n\t\t\t},\n\t\t\tVersion: 2,\n\t\t},\n\t\tContentChanges: []protocol.TextDocumentContentChangeEvent{\n\t\t\t{\n\t\t\t\tRange: nil,\n\t\t\t\tText:  `package main; func main() { fmt.Println(\"\") }`,\n\t\t\t},\n\t\t},\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Send a code action request to validate expected types.\n\tactions, err := server.CodeAction(ctx, &protocol.CodeActionParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t\tContext: protocol.CodeActionContext{\n\t\t\tOnly: []protocol.CodeActionKind{protocol.SourceOrganizeImports},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, action := range actions {\n\t\t// Validate that an empty command is sent along with import organization responses.\n\t\tif action.Kind == protocol.SourceOrganizeImports && action.Command != nil {\n\t\t\tt.Errorf(\"unexpected command for import organization\")\n\t\t}\n\t}\n\n\tif err := server.DidSave(ctx, &protocol.DidSaveTextDocumentParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t\t// LSP specifies that a file can be saved with optional text, so this field must be nil.\n\t\tText: nil,\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Send a completion request to validate expected types.\n\tlist, err := server.Completion(ctx, &protocol.CompletionParams{\n\t\tTextDocumentPositionParams: protocol.TextDocumentPositionParams{\n\t\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\t\tURI: uri,\n\t\t\t},\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{\n\t\t\t\t\tLine:      0,\n\t\t\t\t\tCharacter: 28,\n\t\t\t\t},\n\t\t\t\tEnd: protocol.Position{\n\t\t\t\t\tLine:      0,\n\t\t\t\t\tCharacter: 28,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, item := range list.Items {\n\t\t// All other completion items should have nil commands.\n\t\t// An empty command will be treated as a command with the name '' by VS Code.\n\t\t// This causes VS Code to report errors to users about invalid commands.\n\t\tif item.Command != nil {\n\t\t\tt.Errorf(\"unexpected command for completion item\")\n\t\t}\n\t\t// The item's TextEdit must be a pointer, as VS Code considers TextEdits\n\t\t// that don't contain the cursor position to be invalid.\n\t\tvar textEdit = item.TextEdit.Value\n\t\tswitch textEdit.(type) {\n\t\tcase protocol.TextEdit, protocol.InsertReplaceEdit:\n\t\tdefault:\n\t\t\tt.Errorf(\"textEdit is not TextEdit nor InsertReplaceEdit, instead it is %T\", textEdit)\n\t\t}\n\t}\n\tif err := server.Shutdown(ctx); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := server.Exit(ctx); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc validateCapabilities(result *protocol.InitializeResult) error {\n\t// If the client sends \"false\" for RenameProvider.PrepareSupport,\n\t// the server must respond with a boolean.\n\tif v, ok := result.Capabilities.RenameProvider.(bool); !ok {\n\t\treturn fmt.Errorf(\"RenameProvider must be a boolean if PrepareSupport is false (got %T)\", v)\n\t}\n\t// The same goes for CodeActionKind.ValueSet.\n\tif v, ok := result.Capabilities.CodeActionProvider.(bool); !ok {\n\t\treturn fmt.Errorf(\"CodeActionSupport must be a boolean if CodeActionKind.ValueSet has length 0 (got %T)\", v)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/check.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n)\n\n// check implements the check verb for gopls.\ntype check struct {\n\tapp      *Application\n\tSeverity string `flag:\"severity\" help:\"minimum diagnostic severity (hint, info, warning, or error)\"`\n}\n\nfunc (c *check) Name() string      { return \"check\" }\nfunc (c *check) Parent() string    { return c.app.Name() }\nfunc (c *check) Usage() string     { return \"<filename>\" }\nfunc (c *check) ShortHelp() string { return \"show diagnostic results for the specified file\" }\nfunc (c *check) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample: show the diagnostic results of this file:\n\n\t$ gopls check internal/cmd/check.go\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run performs the check on the files specified by args and prints the\n// results to stdout.\nfunc (c *check) Run(ctx context.Context, args ...string) error {\n\tseverityCutoff := protocol.SeverityWarning\n\tswitch c.Severity {\n\tcase \"hint\":\n\t\tseverityCutoff = protocol.SeverityHint\n\tcase \"info\":\n\t\tseverityCutoff = protocol.SeverityInformation\n\tcase \"warning\":\n\t\t// default\n\tcase \"error\":\n\t\tseverityCutoff = protocol.SeverityError\n\tdefault:\n\t\treturn fmt.Errorf(\"unrecognized -severity value %q\", c.Severity)\n\t}\n\n\tif len(args) == 0 {\n\t\treturn nil\n\t}\n\n\t// TODO(adonovan): formally, we are required to set this\n\t// option if we want RelatedInformation, but it appears to\n\t// have no effect on the server, even though the default is\n\t// false. Investigate.\n\torigOptions := c.app.options\n\tc.app.options = func(opts *settings.Options) {\n\t\tif origOptions != nil {\n\t\t\torigOptions(opts)\n\t\t}\n\t\topts.RelatedInformationSupported = true\n\t}\n\n\tcli, _, err := c.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\t// Open and diagnose the requested files.\n\tvar (\n\t\turis     []protocol.DocumentURI\n\t\tchecking = make(map[protocol.DocumentURI]*cmdFile)\n\t)\n\tfor _, arg := range args {\n\t\turi := protocol.URIFromPath(arg)\n\t\turis = append(uris, uri)\n\t\tfile, err := cli.openFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tchecking[uri] = file\n\t}\n\tif err := diagnoseFiles(ctx, cli.server, uris); err != nil {\n\t\treturn err\n\t}\n\n\t// print prints a single element of a diagnostic.\n\tprint := func(uri protocol.DocumentURI, rng protocol.Range, message string) error {\n\t\tfile, err := cli.openFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tspn, err := file.rangeSpan(rng)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not convert position %v for %q\", rng, message)\n\t\t}\n\t\tfmt.Printf(\"%v: %v\\n\", spn, message)\n\t\treturn nil\n\t}\n\n\tfor _, file := range checking {\n\t\tfile.diagnosticsMu.Lock()\n\t\tdiags := slices.Clone(file.diagnostics)\n\t\tfile.diagnosticsMu.Unlock()\n\n\t\tfor _, diag := range diags {\n\t\t\tif diag.Severity > severityCutoff { // lower severity value => greater severity, counterintuitively\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := print(file.uri, diag.Range, diag.Message); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, rel := range diag.RelatedInformation {\n\t\t\t\tif err := print(rel.Location.URI, rel.Location.Range, \"- \"+rel.Message); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/cmd.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cmd handles the gopls command line.\n// It contains a handler for each of the modes, along with all the flag handling\n// and the command line output format.\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"text/tabwriter\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/browser\"\n\tbugpkg \"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/moreslices\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// Application is the main application as passed to tool.Main\n// It handles the main command line parsing and dispatch to the sub commands.\ntype Application struct {\n\t// Core application flags\n\n\t// Embed the basic profiling flags supported by the tool package\n\ttool.Profile\n\n\t// We include the server configuration directly for now, so the flags work\n\t// even without the verb.\n\t// TODO: Remove this when we stop allowing the serve verb by default.\n\tServe Serve\n\n\t// the options configuring function to invoke when building a server\n\toptions func(*settings.Options)\n\n\t// Support for remote LSP server.\n\tRemote string `flag:\"remote\" help:\"forward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment.\"`\n\n\t// Verbose enables verbose logging.\n\tVerbose bool `flag:\"v,verbose\" help:\"verbose output\"`\n\n\t// VeryVerbose enables a higher level of verbosity in logging output.\n\tVeryVerbose bool `flag:\"vv,veryverbose\" help:\"very verbose output\"`\n\n\t// OTel specifies the OpenTelemetry collector endpoint (e.g. http://localhost:4318).\n\tOTel string `flag:\"otel\" help:\"export telemetry to specified OpenTelemetry collector address (e.g. http://localhost:4318)\"`\n\n\t// PrepareOptions is called to update the options when a new view is built.\n\t// It is primarily to allow the behavior of gopls to be modified by hooks.\n\tPrepareOptions func(*settings.Options)\n\n\t// editFlags holds flags that control how file edit operations\n\t// are applied, in particular when the server makes an ApplyEdits\n\t// downcall to the client. Present only for commands that apply edits.\n\teditFlags *EditFlags\n}\n\n// EditFlags defines flags common to {code{action,lens},format,imports,rename}\n// that control how edits are applied to the client's files.\n//\n// The type is exported for flag reflection.\n//\n// The -write, -diff, and -list flags are orthogonal but any\n// of them suppresses the default behavior, which is to print\n// the edited file contents.\ntype EditFlags struct {\n\tWrite    bool `flag:\"w,write\" help:\"write edited content to source files\"`\n\tPreserve bool `flag:\"preserve\" help:\"with -write, make copies of original files\"`\n\tDiff     bool `flag:\"d,diff\" help:\"display diffs instead of edited file content\"`\n\tList     bool `flag:\"l,list\" help:\"display names of edited files\"`\n}\n\nfunc (app *Application) verbose() bool {\n\treturn app.Verbose || app.VeryVerbose\n}\n\n// New returns a new Application ready to run.\nfunc New() *Application {\n\tapp := &Application{\n\t\tServe: Serve{\n\t\t\tRemoteListenTimeout: 1 * time.Minute,\n\t\t},\n\t}\n\tapp.Serve.app = app\n\treturn app\n}\n\n// Name implements tool.Application returning the binary name.\nfunc (app *Application) Name() string { return \"gopls\" }\n\n// Usage implements tool.Application returning empty extra argument usage.\nfunc (app *Application) Usage() string { return \"\" }\n\n// ShortHelp implements tool.Application returning the main binary help.\nfunc (app *Application) ShortHelp() string {\n\treturn \"\"\n}\n\n// DetailedHelp implements tool.Application returning the main binary help.\n// This includes the short help for all the sub commands.\nfunc (app *Application) DetailedHelp(f *flag.FlagSet) {\n\tw := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0)\n\tdefer w.Flush()\n\n\tfmt.Fprint(w, `\ngopls is a Go language server.\n\nIt is typically used with an editor to provide language features. When no\ncommand is specified, gopls will default to the 'serve' command. The language\nfeatures can also be accessed via the gopls command-line interface.\n\nFor documentation of all its features, see:\n\n   https://github.com/golang/tools/blob/master/gopls/doc/features\n\nUsage:\n  gopls help [<subject>]\n\nCommand:\n`)\n\tfmt.Fprint(w, \"\\nMain\\t\\n\")\n\tfor _, c := range app.mainCommands() {\n\t\tfmt.Fprintf(w, \"  %s\\t%s\\n\", c.Name(), c.ShortHelp())\n\t}\n\tfmt.Fprint(w, \"\\t\\nFeatures\\t\\n\")\n\tfor _, c := range app.featureCommands() {\n\t\tfmt.Fprintf(w, \"  %s\\t%s\\n\", c.Name(), c.ShortHelp())\n\t}\n\tif app.verbose() {\n\t\tfmt.Fprint(w, \"\\t\\nInternal Use Only\\t\\n\")\n\t\tfor _, c := range app.internalCommands() {\n\t\t\tfmt.Fprintf(w, \"  %s\\t%s\\n\", c.Name(), c.ShortHelp())\n\t\t}\n\t}\n\tfmt.Fprint(w, \"\\nflags:\\n\")\n\tprintFlagDefaults(f)\n}\n\n// this is a slightly modified version of flag.PrintDefaults to give us control\nfunc printFlagDefaults(s *flag.FlagSet) {\n\tvar flags [][]*flag.Flag\n\tseen := map[flag.Value]int{}\n\ts.VisitAll(func(f *flag.Flag) {\n\t\tif i, ok := seen[f.Value]; !ok {\n\t\t\tseen[f.Value] = len(flags)\n\t\t\tflags = append(flags, []*flag.Flag{f})\n\t\t} else {\n\t\t\tflags[i] = append(flags[i], f)\n\t\t}\n\t})\n\tfor _, entry := range flags {\n\t\tsort.SliceStable(entry, func(i, j int) bool {\n\t\t\treturn len(entry[i].Name) < len(entry[j].Name)\n\t\t})\n\t\tvar b strings.Builder\n\t\tfor i, f := range entry {\n\t\t\tswitch i {\n\t\t\tcase 0:\n\t\t\t\tb.WriteString(\"  -\")\n\t\t\tdefault:\n\t\t\t\tb.WriteString(\",-\")\n\t\t\t}\n\t\t\tb.WriteString(f.Name)\n\t\t}\n\n\t\tf := entry[0]\n\t\tname, usage := flag.UnquoteUsage(f)\n\t\tif len(name) > 0 {\n\t\t\tb.WriteString(\"=\")\n\t\t\tb.WriteString(name)\n\t\t}\n\t\t// Boolean flags of one ASCII letter are so common we\n\t\t// treat them specially, putting their usage on the same line.\n\t\tif b.Len() <= 4 { // space, space, '-', 'x'.\n\t\t\tb.WriteString(\"\\t\")\n\t\t} else {\n\t\t\t// Four spaces before the tab triggers good alignment\n\t\t\t// for both 4- and 8-space tab stops.\n\t\t\tb.WriteString(\"\\n    \\t\")\n\t\t}\n\t\tb.WriteString(strings.ReplaceAll(usage, \"\\n\", \"\\n    \\t\"))\n\t\tif !isZeroValue(f, f.DefValue) {\n\t\t\tif reflect.TypeOf(f.Value).Elem().Name() == \"stringValue\" {\n\t\t\t\tfmt.Fprintf(&b, \" (default %q)\", f.DefValue)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(&b, \" (default %v)\", f.DefValue)\n\t\t\t}\n\t\t}\n\t\tfmt.Fprint(s.Output(), b.String(), \"\\n\")\n\t}\n}\n\n// isZeroValue is copied from the flags package\nfunc isZeroValue(f *flag.Flag, value string) bool {\n\t// Build a zero value of the flag's Value type, and see if the\n\t// result of calling its String method equals the value passed in.\n\t// This works unless the Value type is itself an interface type.\n\ttyp := reflect.TypeOf(f.Value)\n\tvar z reflect.Value\n\tif typ.Kind() == reflect.Pointer {\n\t\tz = reflect.New(typ.Elem())\n\t} else {\n\t\tz = reflect.Zero(typ)\n\t}\n\treturn value == z.Interface().(flag.Value).String()\n}\n\n// Run takes the args after top level flag processing, and invokes the correct\n// sub command as specified by the first argument.\n// If no arguments are passed it will invoke the server sub command, as a\n// temporary measure for compatibility.\nfunc (app *Application) Run(ctx context.Context, args ...string) error {\n\t// In the category of \"things we can do while waiting for the Go command\":\n\t// Pre-initialize the filecache, which takes ~50ms to hash the gopls\n\t// executable, and immediately runs a gc.\n\tfilecache.Start()\n\n\tctx = debug.WithInstance(ctx, app.OTel)\n\tif len(args) == 0 {\n\t\ts := flag.NewFlagSet(app.Name(), flag.ExitOnError)\n\t\treturn tool.Run(ctx, s, &app.Serve, args)\n\t}\n\tcommand, args := args[0], args[1:]\n\tfor _, c := range app.Commands() {\n\t\tif c.Name() == command {\n\t\t\ts := flag.NewFlagSet(app.Name(), flag.ExitOnError)\n\t\t\treturn tool.Run(ctx, s, c, args)\n\t\t}\n\t}\n\treturn tool.CommandLineErrorf(\"Unknown command %v\", command)\n}\n\n// Commands returns the set of commands supported by the gopls tool on the\n// command line.\n// The command is specified by the first non flag argument.\nfunc (app *Application) Commands() []tool.Application {\n\tvar commands []tool.Application\n\tcommands = append(commands, app.mainCommands()...)\n\tcommands = append(commands, app.featureCommands()...)\n\tcommands = append(commands, app.internalCommands()...)\n\treturn commands\n}\n\nfunc (app *Application) mainCommands() []tool.Application {\n\treturn []tool.Application{\n\t\t&app.Serve,\n\t\t&version{app: app},\n\t\t&bug{app: app},\n\t\t&help{app: app},\n\t\t&apiJSON{app: app},\n\t\t&licenses{app: app},\n\t}\n}\n\nfunc (app *Application) internalCommands() []tool.Application {\n\treturn []tool.Application{\n\t\t&vulncheck{app: app},\n\t}\n}\n\nfunc (app *Application) featureCommands() []tool.Application {\n\treturn []tool.Application{\n\t\t&callHierarchy{app: app},\n\t\t&check{app: app, Severity: \"warning\"},\n\t\t&codeaction{app: app},\n\t\t&codelens{app: app},\n\t\t&definition{app: app},\n\t\t&execute{app: app},\n\t\t&fix{app: app}, // (non-functional)\n\t\t&foldingRanges{app: app},\n\t\t&format{app: app},\n\t\t&headlessMCP{app: app},\n\t\t&highlight{app: app},\n\t\t&implementation{app: app},\n\t\t&imports{app: app},\n\t\tnewRemote(app, \"\"),\n\t\tnewRemote(app, \"inspect\"),\n\t\t&links{app: app},\n\t\t&prepareRename{app: app},\n\t\t&references{app: app},\n\t\t&rename{app: app},\n\t\t&semanticToken{app: app},\n\t\t&signature{app: app},\n\t\t&stats{app: app},\n\t\t&symbols{app: app},\n\n\t\t&workspaceSymbol{app: app},\n\t}\n}\n\n// connect creates and initializes a new in-process gopls LSP session.\nfunc (app *Application) connect(ctx context.Context) (*client, *cache.Session, error) {\n\troot, err := os.Getwd()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"finding workdir: %v\", err)\n\t}\n\toptions := settings.DefaultOptions(app.options)\n\tclient := newClient(app)\n\tvar (\n\t\tsvr  protocol.Server\n\t\tsess *cache.Session\n\t)\n\tif app.Remote == \"\" {\n\t\t// local\n\t\tsess = cache.NewSession(ctx, cache.New(nil))\n\t\tsvr = server.New(sess, client, options)\n\t\tctx = protocol.WithClient(ctx, client)\n\t} else {\n\t\t// remote\n\t\tnetConn, err := lsprpc.ConnectToRemote(ctx, app.Remote)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tstream := jsonrpc2.NewHeaderStream(netConn)\n\t\tjsonConn := jsonrpc2.NewConn(stream)\n\t\tsvr = protocol.ServerDispatcher(jsonConn)\n\t\tctx = protocol.WithClient(ctx, client)\n\t\tjsonConn.Go(ctx,\n\t\t\tprotocol.Handlers(\n\t\t\t\tprotocol.ClientHandler(client, jsonrpc2.MethodNotFound)))\n\t}\n\tif err := client.initialize(ctx, svr, initParams(root, options)); err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn client, sess, nil\n}\n\nfunc initParams(rootDir string, opts *settings.Options) *protocol.ParamInitialize {\n\tparams := &protocol.ParamInitialize{}\n\tparams.RootURI = protocol.URIFromPath(rootDir)\n\tparams.Capabilities.Workspace.Configuration = true\n\n\t// If you add an additional option here,\n\t// you must update the map key of settings.DefaultOptions called in (*Application).connect.\n\tparams.Capabilities.TextDocument.Hover = &protocol.HoverClientCapabilities{\n\t\tContentFormat: []protocol.MarkupKind{opts.PreferredContentFormat},\n\t}\n\tparams.Capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = opts.HierarchicalDocumentSymbolSupport\n\tparams.Capabilities.TextDocument.SemanticTokens = protocol.SemanticTokensClientCapabilities{}\n\tparams.Capabilities.TextDocument.SemanticTokens.Formats = []protocol.TokenFormat{\"relative\"}\n\tparams.Capabilities.TextDocument.SemanticTokens.Requests.Range = &protocol.Or_ClientSemanticTokensRequestOptions_range{Value: true}\n\t// params.Capabilities.TextDocument.SemanticTokens.Requests.Range.Value = true\n\tparams.Capabilities.TextDocument.SemanticTokens.Requests.Full = &protocol.Or_ClientSemanticTokensRequestOptions_full{Value: true}\n\tparams.Capabilities.TextDocument.SemanticTokens.TokenTypes = moreslices.ConvertStrings[string](semtok.Types)\n\tparams.Capabilities.TextDocument.SemanticTokens.TokenModifiers = moreslices.ConvertStrings[string](semtok.Modifiers)\n\tparams.Capabilities.TextDocument.CodeAction = protocol.CodeActionClientCapabilities{\n\t\tCodeActionLiteralSupport: protocol.ClientCodeActionLiteralOptions{\n\t\t\tCodeActionKind: protocol.ClientCodeActionKindOptions{\n\t\t\t\tValueSet: []protocol.CodeActionKind{protocol.Empty}, // => all\n\t\t\t},\n\t\t},\n\t}\n\tparams.Capabilities.Window.WorkDoneProgress = true\n\tparams.Capabilities.Workspace.FileOperations = &protocol.FileOperationClientCapabilities{\n\t\tDidCreate: true,\n\t}\n\tparams.InitializationOptions = map[string]any{\n\t\t\"symbolMatcher\": string(opts.SymbolMatcher),\n\t}\n\treturn params\n}\n\n// initialize performs LSP's two-call client/server handshake.\nfunc (cli *client) initialize(ctx context.Context, server protocol.Server, params *protocol.ParamInitialize) error {\n\tresult, err := server.Initialize(ctx, params)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {\n\t\treturn err\n\t}\n\tcli.server = server\n\tcli.initializeResult = result\n\treturn nil\n}\n\n// client implements [protocol.Client] and defines the LSP client\n// operations of the gopls command.\n//\n// It holds the client-side state of a single client/server\n// connection; it conceptually corresponds to a single call to\n// connect(2).\ntype client struct {\n\tapp *Application\n\n\tserver           protocol.Server\n\tinitializeResult *protocol.InitializeResult // includes server capabilities\n\n\tprogressMu sync.Mutex\n\tiwlToken   protocol.ProgressToken\n\tiwlDone    chan struct{}\n\n\tfilesMu sync.Mutex // guards files map\n\tfiles   map[protocol.DocumentURI]*cmdFile\n}\n\n// cmdFile represents an open file in the gopls command LSP client.\ntype cmdFile struct {\n\turi           protocol.DocumentURI\n\tmapper        *protocol.Mapper\n\terr           error\n\tdiagnosticsMu sync.Mutex\n\tdiagnostics   []protocol.Diagnostic\n}\n\nfunc newClient(app *Application) *client {\n\treturn &client{\n\t\tapp:     app,\n\t\tfiles:   make(map[protocol.DocumentURI]*cmdFile),\n\t\tiwlDone: make(chan struct{}),\n\t}\n}\n\nfunc (cli *client) TextDocumentContentRefresh(context.Context, *protocol.TextDocumentContentRefreshParams) error {\n\treturn nil\n}\n\nfunc (cli *client) CodeLensRefresh(context.Context) error { return nil }\n\nfunc (cli *client) FoldingRangeRefresh(context.Context) error { return nil }\n\nfunc (cli *client) LogTrace(context.Context, *protocol.LogTraceParams) error { return nil }\n\nfunc (cli *client) ShowMessage(ctx context.Context, p *protocol.ShowMessageParams) error {\n\tfmt.Fprintf(os.Stderr, \"%s: %s\\n\", p.Type, p.Message)\n\treturn nil\n}\n\nfunc (cli *client) ShowMessageRequest(ctx context.Context, p *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {\n\treturn nil, nil\n}\n\nfunc (cli *client) LogMessage(ctx context.Context, p *protocol.LogMessageParams) error {\n\t// This logic causes server logging to be double-prefixed with a timestamp.\n\t//     2023/11/08 10:50:21 Error:2023/11/08 10:50:21 <actual message>\n\t// TODO(adonovan): print just p.Message, plus a newline if needed?\n\tswitch p.Type {\n\tcase protocol.Error:\n\t\tlog.Print(\"Error:\", p.Message)\n\tcase protocol.Warning:\n\t\tlog.Print(\"Warning:\", p.Message)\n\tcase protocol.Info:\n\t\tif cli.app.verbose() {\n\t\t\tlog.Print(\"Info:\", p.Message)\n\t\t}\n\tcase protocol.Log:\n\t\tif cli.app.verbose() {\n\t\t\tlog.Print(\"Log:\", p.Message)\n\t\t}\n\tdefault:\n\t\tif cli.app.verbose() {\n\t\t\tlog.Print(p.Message)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (cli *client) Event(ctx context.Context, t *any) error { return nil }\n\nfunc (cli *client) RegisterCapability(ctx context.Context, p *protocol.RegistrationParams) error {\n\treturn nil\n}\n\nfunc (cli *client) UnregisterCapability(ctx context.Context, p *protocol.UnregistrationParams) error {\n\treturn nil\n}\n\nfunc (cli *client) WorkspaceFolders(ctx context.Context) ([]protocol.WorkspaceFolder, error) {\n\treturn nil, nil\n}\n\nfunc (cli *client) Configuration(ctx context.Context, p *protocol.ParamConfiguration) ([]any, error) {\n\tresults := make([]any, len(p.Items))\n\tfor i, item := range p.Items {\n\t\tif item.Section != \"gopls\" {\n\t\t\tcontinue\n\t\t}\n\t\tm := map[string]any{\n\t\t\t\"analyses\": map[string]any{\n\t\t\t\t\"fillreturns\":    true,\n\t\t\t\t\"nonewvars\":      true,\n\t\t\t\t\"noresultvalues\": true,\n\t\t\t\t\"undeclaredname\": true,\n\t\t\t},\n\t\t}\n\t\tif cli.app.VeryVerbose {\n\t\t\tm[\"verboseOutput\"] = true\n\t\t}\n\t\tresults[i] = m\n\t}\n\treturn results, nil\n}\n\nfunc (cli *client) ApplyEdit(ctx context.Context, p *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) {\n\tif err := cli.applyWorkspaceEdit(&p.Edit); err != nil {\n\t\treturn &protocol.ApplyWorkspaceEditResult{FailureReason: err.Error()}, nil\n\t}\n\treturn &protocol.ApplyWorkspaceEditResult{Applied: true}, nil\n}\n\n// applyWorkspaceEdit applies a complete WorkspaceEdit to the client's\n// files, honoring the preferred edit mode specified by cli.app.editMode.\n// (Used by rename and by ApplyEdit downcalls.)\n//\n// See also:\n//   - changedFiles in ../test/marker/marker_test.go for the golden-file capturing variant\n//   - applyWorkspaceEdit in ../test/integration/fake/editor.go for the Editor variant\nfunc (cli *client) applyWorkspaceEdit(wsedit *protocol.WorkspaceEdit) error {\n\n\tcreate := func(uri protocol.DocumentURI, content []byte) error {\n\t\tedits := []diff.Edit{{Start: 0, End: 0, New: string(content)}}\n\t\treturn updateFile(uri.Path(), nil, content, edits, cli.app.editFlags)\n\t}\n\n\tdelete := func(uri protocol.DocumentURI, content []byte) error {\n\t\tedits := []diff.Edit{{Start: 0, End: len(content), New: \"\"}}\n\t\treturn updateFile(uri.Path(), content, nil, edits, cli.app.editFlags)\n\t}\n\n\tfor _, c := range wsedit.DocumentChanges {\n\t\tswitch {\n\t\tcase c.TextDocumentEdit != nil:\n\t\t\tf := cli.getFile(c.TextDocumentEdit.TextDocument.URI)\n\t\t\tif f.err != nil {\n\t\t\t\treturn f.err\n\t\t\t}\n\t\t\t// TODO(adonovan): sanity-check c.TextDocumentEdit.TextDocument.Version\n\t\t\tedits := protocol.AsTextEdits(c.TextDocumentEdit.Edits)\n\t\t\tif err := applyTextEdits(f.mapper, edits, cli.app.editFlags); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase c.CreateFile != nil:\n\t\t\tif err := create(c.CreateFile.URI, []byte{}); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase c.RenameFile != nil:\n\t\t\t// Analyze as creation + deletion. (NB: loses file mode.)\n\t\t\tf := cli.getFile(c.RenameFile.OldURI)\n\t\t\tif f.err != nil {\n\t\t\t\treturn f.err\n\t\t\t}\n\t\t\tif err := create(c.RenameFile.NewURI, f.mapper.Content); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := delete(f.mapper.URI, f.mapper.Content); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase c.DeleteFile != nil:\n\t\t\tf := cli.getFile(c.DeleteFile.URI)\n\t\t\tif f.err != nil {\n\t\t\t\treturn f.err\n\t\t\t}\n\t\t\tif err := delete(f.mapper.URI, f.mapper.Content); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown DocumentChange: %#v\", c)\n\t\t}\n\t}\n\treturn nil\n}\n\n// applyTextEdits applies a list of edits to the mapper file content,\n// using the preferred edit mode. It is a no-op if there are no edits.\nfunc applyTextEdits(mapper *protocol.Mapper, edits []protocol.TextEdit, flags *EditFlags) error {\n\tif len(edits) == 0 {\n\t\treturn nil\n\t}\n\tnewContent, diffEdits, err := protocol.ApplyEdits(mapper, edits)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn updateFile(mapper.URI.Path(), mapper.Content, newContent, diffEdits, flags)\n}\n\n// updateFile performs a content update operation on the specified file.\n// If the old content is nil, the operation creates the file.\n// If the new content is nil, the operation deletes the file.\n// The flags control whether the operation is written, or merely listed, diffed, or printed.\nfunc updateFile(filename string, old, new []byte, edits []diff.Edit, flags *EditFlags) error {\n\tif flags.List {\n\t\tfmt.Println(filename)\n\t}\n\n\tif flags.Write {\n\t\tif flags.Preserve && old != nil { // edit or delete\n\t\t\tif err := os.WriteFile(filename+\".orig\", old, 0666); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif new != nil {\n\t\t\t// create or edit\n\t\t\tif err := os.WriteFile(filename, new, 0666); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\t// delete\n\t\t\tif err := os.Remove(filename); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tif flags.Diff {\n\t\t// For diffing, creations and deletions are equivalent\n\t\t// updating an empty file and making an existing file empty.\n\t\tunified, err := diff.ToUnified(filename+\".orig\", filename, string(old), edits, diff.DefaultContextLines)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Print(unified)\n\t}\n\n\t// No flags: just print edited file content.\n\t//\n\t// This makes no sense for multiple files.\n\t// (We should probably change the default to -diff.)\n\tif !(flags.List || flags.Write || flags.Diff) {\n\t\tos.Stdout.Write(new)\n\t}\n\n\treturn nil\n}\n\nfunc (cli *client) PublishDiagnostics(ctx context.Context, p *protocol.PublishDiagnosticsParams) error {\n\t// Don't worry about diagnostics without versions.\n\t//\n\t// (Note: the representation of PublishDiagnosticsParams\n\t// cannot distinguish a missing Version from v0, but the\n\t// server never sends back an explicit zero.)\n\tif p.Version == 0 {\n\t\treturn nil\n\t}\n\n\tfile := cli.getFile(p.URI)\n\n\tfile.diagnosticsMu.Lock()\n\tdefer file.diagnosticsMu.Unlock()\n\n\tfile.diagnostics = append(file.diagnostics, p.Diagnostics...)\n\n\t// Perform a crude in-place deduplication.\n\t// TODO(golang/go#60122): replace the gopls.diagnose_files\n\t// command with support for textDocument/diagnostic,\n\t// so that we don't need to do this de-duplication.\n\ttype key [6]any\n\tseen := make(map[key]bool)\n\tout := file.diagnostics[:0]\n\tfor _, d := range file.diagnostics {\n\t\tvar codeHref string\n\t\tif desc := d.CodeDescription; desc != nil {\n\t\t\tcodeHref = desc.Href\n\t\t}\n\t\tk := key{d.Range, d.Severity, d.Code, codeHref, d.Source, d.Message}\n\t\tif !seen[k] {\n\t\t\tseen[k] = true\n\t\t\tout = append(out, d)\n\t\t}\n\t}\n\tfile.diagnostics = out\n\n\treturn nil\n}\n\nfunc (cli *client) Progress(_ context.Context, params *protocol.ProgressParams) error {\n\tif _, ok := params.Token.(string); !ok {\n\t\treturn fmt.Errorf(\"unexpected progress token: %[1]T %[1]v\", params.Token)\n\t}\n\n\tswitch v := params.Value.(type) {\n\tcase *protocol.WorkDoneProgressBegin:\n\t\tif v.Title == server.DiagnosticWorkTitle(server.FromInitialWorkspaceLoad) {\n\t\t\tcli.progressMu.Lock()\n\t\t\tcli.iwlToken = params.Token\n\t\t\tcli.progressMu.Unlock()\n\t\t}\n\n\tcase *protocol.WorkDoneProgressReport:\n\t\tif cli.app.Verbose {\n\t\t\tfmt.Fprintln(os.Stderr, v.Message)\n\t\t}\n\n\tcase *protocol.WorkDoneProgressEnd:\n\t\tcli.progressMu.Lock()\n\t\tiwlToken := cli.iwlToken\n\t\tcli.progressMu.Unlock()\n\n\t\tif params.Token == iwlToken {\n\t\t\tclose(cli.iwlDone)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (cli *client) ShowDocument(ctx context.Context, params *protocol.ShowDocumentParams) (*protocol.ShowDocumentResult, error) {\n\tvar success bool\n\tif params.External {\n\t\t// Open URI in external browser.\n\t\tsuccess = browser.Open(params.URI)\n\t} else {\n\t\t// Open file in editor, optionally taking focus and selecting a range.\n\t\t// (client has no editor. Should it fork+exec $EDITOR?)\n\t\tlog.Printf(\"Server requested that client editor open %q (takeFocus=%t, selection=%+v)\",\n\t\t\tparams.URI, params.TakeFocus, params.Selection)\n\t\tsuccess = true\n\t}\n\treturn &protocol.ShowDocumentResult{Success: success}, nil\n}\n\nfunc (cli *client) WorkDoneProgressCreate(context.Context, *protocol.WorkDoneProgressCreateParams) error {\n\treturn nil\n}\n\nfunc (cli *client) DiagnosticRefresh(context.Context) error {\n\treturn nil\n}\n\nfunc (cli *client) InlayHintRefresh(context.Context) error {\n\treturn nil\n}\n\nfunc (cli *client) SemanticTokensRefresh(context.Context) error {\n\treturn nil\n}\n\nfunc (cli *client) InlineValueRefresh(context.Context) error {\n\treturn nil\n}\n\n// getFile returns the specified file, adding it to the client state if needed.\nfunc (cli *client) getFile(uri protocol.DocumentURI) *cmdFile {\n\tcli.filesMu.Lock()\n\tdefer cli.filesMu.Unlock()\n\n\tfile, found := cli.files[uri]\n\tif !found || file.err != nil {\n\t\tfile = &cmdFile{\n\t\t\turi: uri,\n\t\t}\n\t\tcli.files[uri] = file\n\t}\n\tif file.mapper == nil {\n\t\tcontent, err := os.ReadFile(uri.Path())\n\t\tif err != nil {\n\t\t\tfile.err = fmt.Errorf(\"getFile: %v: %v\", uri, err)\n\t\t\treturn file\n\t\t}\n\t\tfile.mapper = protocol.NewMapper(uri, content)\n\t}\n\treturn file\n}\n\n// openFile returns the specified file, adding it to the client state\n// if needed, and notifying the server that it was opened.\nfunc (cli *client) openFile(ctx context.Context, uri protocol.DocumentURI) (*cmdFile, error) {\n\tfile := cli.getFile(uri)\n\tif file.err != nil {\n\t\treturn nil, file.err\n\t}\n\n\t// Choose language ID from file extension.\n\tvar langID protocol.LanguageKind // \"\" eventually maps to file.UnknownKind\n\tswitch filepath.Ext(uri.Path()) {\n\tcase \".go\":\n\t\tlangID = \"go\"\n\tcase \".mod\":\n\t\tlangID = \"go.mod\"\n\tcase \".sum\":\n\t\tlangID = \"go.sum\"\n\tcase \".work\":\n\t\tlangID = \"go.work\"\n\tcase \".s\":\n\t\tlangID = \"go.s\"\n\t}\n\n\tp := &protocol.DidOpenTextDocumentParams{\n\t\tTextDocument: protocol.TextDocumentItem{\n\t\t\tURI:        uri,\n\t\t\tLanguageID: langID,\n\t\t\tVersion:    1,\n\t\t\tText:       string(file.mapper.Content),\n\t\t},\n\t}\n\tif err := cli.server.DidOpen(ctx, p); err != nil {\n\t\t// TODO(adonovan): is this assignment concurrency safe?\n\t\tfile.err = fmt.Errorf(\"%v: %v\", uri, err)\n\t\treturn nil, file.err\n\t}\n\treturn file, nil\n}\n\nfunc diagnoseFiles(ctx context.Context, server protocol.Server, files []protocol.DocumentURI) error {\n\tcmd := command.NewDiagnoseFilesCommand(\"Diagnose files\", command.DiagnoseFilesArgs{\n\t\tFiles: files,\n\t})\n\t_, err := executeCommand(ctx, server, cmd)\n\treturn err\n}\n\nfunc (cli *client) terminate(ctx context.Context) {\n\tif err := cli.server.Shutdown(ctx); err != nil {\n\t\tlog.Printf(\"server shutdown failed: %v\", err)\n\t}\n\n\t// Don't call Exit as it terminates the server process,\n\t// which is the same as this client process.\n\t// c.server.Exit(ctx)\n}\n\n// Implement io.Closer.\nfunc (cli *client) Close() error {\n\treturn nil\n}\n\n// -- conversions to span (UTF-8) domain --\n\n// locationSpan converts a protocol (UTF-16) Location to a (UTF-8) span.\n// Precondition: the URIs of Location and Mapper match.\nfunc (f *cmdFile) locationSpan(loc protocol.Location) (span, error) {\n\t// TODO(adonovan): check that l.URI matches m.URI.\n\treturn f.rangeSpan(loc.Range)\n}\n\n// rangeSpan converts a protocol (UTF-16) range to a (UTF-8) span.\n// The resulting span has valid Positions and Offsets.\nfunc (f *cmdFile) rangeSpan(r protocol.Range) (span, error) {\n\tstart, end, err := f.mapper.RangeOffsets(r)\n\tif err != nil {\n\t\treturn span{}, err\n\t}\n\treturn f.offsetSpan(start, end)\n}\n\n// offsetSpan converts a byte-offset interval to a (UTF-8) span.\n// The resulting span contains line, column, and offset information.\nfunc (f *cmdFile) offsetSpan(start, end int) (span, error) {\n\tif start > end {\n\t\treturn span{}, fmt.Errorf(\"start offset (%d) > end (%d)\", start, end)\n\t}\n\tstartPoint, err := offsetPoint(f.mapper, start)\n\tif err != nil {\n\t\treturn span{}, fmt.Errorf(\"start: %v\", err)\n\t}\n\tendPoint, err := offsetPoint(f.mapper, end)\n\tif err != nil {\n\t\treturn span{}, fmt.Errorf(\"end: %v\", err)\n\t}\n\treturn newSpan(f.mapper.URI, startPoint, endPoint), nil\n}\n\n// offsetPoint converts a byte offset to a span (UTF-8) point.\n// The resulting point contains line, column, and offset information.\nfunc offsetPoint(m *protocol.Mapper, offset int) (point, error) {\n\tif !(0 <= offset && offset <= len(m.Content)) {\n\t\treturn point{}, fmt.Errorf(\"invalid offset %d (want 0-%d)\", offset, len(m.Content))\n\t}\n\tline, col8 := m.OffsetLineCol8(offset)\n\treturn newPoint(line, col8, offset), nil\n}\n\n// -- conversions from span (UTF-8) domain --\n\n// spanLocation converts a (UTF-8) span to a protocol (UTF-16) range.\n// Precondition: the URIs of spanLocation and Mapper match.\nfunc (f *cmdFile) spanLocation(s span) (protocol.Location, error) {\n\trng, err := f.spanRange(s)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\treturn f.mapper.URI.Location(rng), nil\n}\n\n// spanRange converts a (UTF-8) span to a protocol (UTF-16) range.\n// Precondition: the URIs of span and Mapper match.\nfunc (f *cmdFile) spanRange(s span) (protocol.Range, error) {\n\t// Assert that we aren't using the wrong mapper.\n\t// We check only the base name, and case insensitively,\n\t// because we can't assume clean paths, no symbolic links,\n\t// case-sensitive directories. The authoritative answer\n\t// requires querying the file system, and we don't want\n\t// to do that.\n\tif !strings.EqualFold(f.mapper.URI.Base(), s.URI().Base()) {\n\t\treturn protocol.Range{}, bugpkg.Errorf(\"mapper is for file %q instead of %q\", f.mapper.URI, s.URI())\n\t}\n\tstart, err := pointPosition(f.mapper, s.Start())\n\tif err != nil {\n\t\treturn protocol.Range{}, fmt.Errorf(\"start: %w\", err)\n\t}\n\tend, err := pointPosition(f.mapper, s.End())\n\tif err != nil {\n\t\treturn protocol.Range{}, fmt.Errorf(\"end: %w\", err)\n\t}\n\treturn protocol.Range{Start: start, End: end}, nil\n}\n\n// pointPosition converts a valid span (UTF-8) point to a protocol (UTF-16) position.\nfunc pointPosition(m *protocol.Mapper, p point) (protocol.Position, error) {\n\tif p.HasPosition() {\n\t\treturn m.LineCol8Position(p.Line(), p.Column())\n\t}\n\tif p.HasOffset() {\n\t\treturn m.OffsetPosition(p.Offset())\n\t}\n\treturn protocol.Position{}, fmt.Errorf(\"point has neither offset nor line/column\")\n}\n\n// TODO(adonovan): delete in 2025.\ntype fix struct{ app *Application }\n\nfunc (*fix) Name() string       { return \"fix\" }\nfunc (cmd *fix) Parent() string { return cmd.app.Name() }\nfunc (*fix) Usage() string      { return \"\" }\nfunc (*fix) ShortHelp() string  { return \"apply suggested fixes (obsolete)\" }\nfunc (*fix) DetailedHelp(flags *flag.FlagSet) {\n\tfmt.Fprintf(flags.Output(), `No longer supported; use \"gopls codeaction\" instead.`)\n}\nfunc (*fix) Run(ctx context.Context, args ...string) error {\n\treturn tool.CommandLineErrorf(`no longer supported; use \"gopls codeaction\" instead`)\n}\n"
  },
  {
    "path": "gopls/internal/cmd/codeaction.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// codeaction implements the codeaction verb for gopls.\ntype codeaction struct {\n\tEditFlags\n\tKind  string `flag:\"kind\" help:\"comma-separated list of code action kinds to filter\"`\n\tTitle string `flag:\"title\" help:\"regular expression to match title\"`\n\tExec  bool   `flag:\"exec\" help:\"execute the first matching code action\"`\n\n\tapp *Application\n}\n\nfunc (cmd *codeaction) Name() string      { return \"codeaction\" }\nfunc (cmd *codeaction) Parent() string    { return cmd.app.Name() }\nfunc (cmd *codeaction) Usage() string     { return \"[codeaction-flags] filename[:line[:col]]\" }\nfunc (cmd *codeaction) ShortHelp() string { return \"list or execute code actions\" }\nfunc (cmd *codeaction) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprintf(f.Output(), `\n\nThe codeaction command lists or executes code actions for the\nspecified file or range of a file. Each code action contains\neither an edit to be directly applied to the file, or a command\nto be executed by the server, which may have an effect such as:\n- requesting that the client apply an edit;\n- changing the state of the server; or\n- requesting that the client open a document.\n\nThe -kind and and -title flags filter the list of actions.\n\nThe -kind flag specifies a comma-separated list of LSP CodeAction kinds.\nOnly actions of these kinds will be requested from the server.\nValid kinds include:\n\n\tgopls.doc.features\n\tquickfix\n\trefactor\n\trefactor.extract\n\trefactor.extract.constant\n\trefactor.extract.function\n\trefactor.extract.method\n\trefactor.extract.toNewFile\n\trefactor.extract.variable\n\trefactor.inline\n\trefactor.inline.call\n\trefactor.rewrite\n\trefactor.rewrite.changeQuote\n\trefactor.rewrite.fillStruct\n\trefactor.rewrite.fillSwitch\n\trefactor.rewrite.invertIf\n\trefactor.rewrite.joinLines\n\trefactor.rewrite.removeUnusedParam\n\trefactor.rewrite.splitLines\n\tsource\n\tsource.assembly\n\tsource.doc\n\tsource.fixAll\n\tsource.freesymbols\n\tsource.organizeImports\n\tsource.test\n\nKinds are hierarchical, so \"refactor\" includes \"refactor.inline\".\n(Note: actions of kind \"source.test\" are not returned unless explicitly\nrequested.)\n\nThe -title flag specifies a regular expression that must match the\naction's title. (Ideally kinds would be specific enough that this\nisn't necessary; we really need to subdivide refactor.rewrite; see\ngopls/internal/settings/codeactionkind.go.)\n\nThe -exec flag causes the first matching code action to be executed.\nWithout the flag, the matching actions are merely listed.\n\nIt is not currently possible to execute more than one action,\nas that requires a way to detect and resolve conflicts.\nTODO(adonovan): support it when golang/go#67049 is resolved.\n\nIf executing an action causes the server to send a patch to the\nclient, the usual -write, -preserve, -diff, and -list flags govern how\nthe client deals with the patch.\n\nExample: execute the first \"quick fix\" in the specified file and show the diff:\n\n\t$ gopls codeaction -kind=quickfix -exec -diff ./gopls/main.go\n\ncodeaction-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (cmd *codeaction) Run(ctx context.Context, args ...string) error {\n\tif len(args) < 1 {\n\t\treturn tool.CommandLineErrorf(\"codeaction expects at least 1 argument\")\n\t}\n\tcmd.app.editFlags = &cmd.EditFlags\n\tcli, _, err := cmd.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\turi := from.URI()\n\tfile, err := cli.openFile(ctx, uri)\n\tif err != nil {\n\t\treturn err\n\t}\n\trng, err := file.spanRange(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttitleRE, err := regexp.Compile(cmd.Title)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Get diagnostics, as they may encode various lazy code actions.\n\tif err := diagnoseFiles(ctx, cli.server, []protocol.DocumentURI{uri}); err != nil {\n\t\treturn err\n\t}\n\tfile.diagnosticsMu.Lock()\n\tdiagnostics := slices.Clone(file.diagnostics)\n\tfile.diagnosticsMu.Unlock()\n\n\t// Request code actions of the desired kinds.\n\tvar kinds []protocol.CodeActionKind\n\tif cmd.Kind != \"\" {\n\t\tfor kind := range strings.SplitSeq(cmd.Kind, \",\") {\n\t\t\tkinds = append(kinds, protocol.CodeActionKind(kind))\n\t\t}\n\t} else {\n\t\tkinds = append(kinds, protocol.Empty) // => all\n\t}\n\tactions, err := cli.server.CodeAction(ctx, &protocol.CodeActionParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{URI: uri},\n\t\tRange:        rng,\n\t\tContext: protocol.CodeActionContext{\n\t\t\tOnly:        kinds,\n\t\t\tDiagnostics: diagnostics,\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\n\t// Gather edits from matching code actions.\n\tvar edits []protocol.TextEdit\n\tfor _, act := range actions {\n\t\tif act.Disabled != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif !titleRE.MatchString(act.Title) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// If the provided span has a position (not just offsets),\n\t\t// and the action has diagnostics, the action must have a\n\t\t// diagnostic with the same range as it.\n\t\tif from.HasPosition() && len(act.Diagnostics) > 0 &&\n\t\t\t!slices.ContainsFunc(act.Diagnostics, func(diag protocol.Diagnostic) bool {\n\t\t\t\treturn diag.Range.Start == rng.Start\n\t\t\t}) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif cmd.Exec {\n\t\t\t// -exec: run the first matching code action.\n\t\t\tif act.Command != nil {\n\t\t\t\t// This may cause the server to make\n\t\t\t\t// an ApplyEdit downcall to the client.\n\t\t\t\tif _, err := executeCommand(ctx, cli.server, act.Command); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\t// The specification says that commands should\n\t\t\t\t// be executed _after_ edits are applied, not\n\t\t\t\t// instead of them, but we don't want to\n\t\t\t\t// duplicate edits.\n\t\t\t} else {\n\t\t\t\t// Partially apply CodeAction.Edit, a WorkspaceEdit.\n\t\t\t\t// (See also cli.applyWorkspaceEdit(a.Edit)).\n\t\t\t\tfor _, c := range act.Edit.DocumentChanges {\n\t\t\t\t\ttde := c.TextDocumentEdit\n\t\t\t\t\tif tde != nil && tde.TextDocument.URI == uri {\n\t\t\t\t\t\t// TODO(adonovan): this logic will butcher an edit that spans files.\n\t\t\t\t\t\t// It will also ignore create/delete/rename operations.\n\t\t\t\t\t\t// Fix or document. Need a three-way merge.\n\t\t\t\t\t\tedits = append(edits, protocol.AsTextEdits(tde.Edits)...)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn applyTextEdits(file.mapper, edits, cmd.app.editFlags)\n\t\t\t}\n\t\t\treturn nil\n\t\t} else {\n\t\t\t// No -exec: list matching code actions.\n\t\t\taction := \"edit\"\n\t\t\tif act.Command != nil {\n\t\t\t\taction = \"command\"\n\t\t\t}\n\t\t\tfmt.Printf(\"%s\\t%q [%s]\\n\",\n\t\t\t\taction,\n\t\t\t\tact.Title,\n\t\t\t\tact.Kind)\n\t\t}\n\t}\n\n\tif cmd.Exec {\n\t\treturn fmt.Errorf(\"no matching code action at %s\", from)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/codelens.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// codelens implements the codelens verb for gopls.\ntype codelens struct {\n\tEditFlags\n\tapp *Application\n\n\tExec bool `flag:\"exec\" help:\"execute the first matching code lens\"`\n}\n\nfunc (r *codelens) Name() string      { return \"codelens\" }\nfunc (r *codelens) Parent() string    { return r.app.Name() }\nfunc (r *codelens) Usage() string     { return \"[codelens-flags] file[:line[:col]] [title]\" }\nfunc (r *codelens) ShortHelp() string { return \"List or execute code lenses for a file\" }\nfunc (r *codelens) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nThe codelens command lists or executes code lenses for the specified\nfile, or line within a file. A code lens is a command associated with\na position in the code.\n\nWith an optional title argument, only code lenses matching that\ntitle are considered.\n\nBy default, the codelens command lists the available lenses for the\nspecified file or line within a file, including the title and\ntitle of the command. With the -exec flag, the first matching command\nis executed, and its output is printed to stdout.\n\nExample:\n\n\t$ gopls codelens a_test.go                     # list code lenses in a file\n\t$ gopls codelens a_test.go:10                  # list code lenses on line 10\n\t$ gopls codelens a_test.go \"run test\"          # list gopls.run_tests commands\n\t$ gopls codelens -exec a_test.go:10 \"run test\" # run a specific test\n\ncodelens-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *codelens) Run(ctx context.Context, args ...string) error {\n\tvar filename, title string\n\tswitch len(args) {\n\tcase 0:\n\t\treturn tool.CommandLineErrorf(\"codelens requires a file name\")\n\tcase 2:\n\t\ttitle = args[1]\n\t\tfallthrough\n\tcase 1:\n\t\tfilename = args[0]\n\tdefault:\n\t\treturn tool.CommandLineErrorf(\"codelens expects at most two arguments\")\n\t}\n\n\tr.app.editFlags = &r.EditFlags // in case a codelens perform an edit\n\n\t// Override the default setting for codelenses[\"test\"], which is\n\t// off by default because VS Code has a superior client-side\n\t// implementation. But this client is not VS Code.\n\t// See golang.LensFuncs().\n\torigOptions := r.app.options\n\tr.app.options = func(opts *settings.Options) {\n\t\tif origOptions != nil {\n\t\t\torigOptions(opts)\n\t\t}\n\t\tif opts.Codelenses == nil {\n\t\t\topts.Codelenses = make(map[settings.CodeLensSource]bool)\n\t\t}\n\t\topts.Codelenses[settings.CodeLensTest] = true\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfilespan := parseSpan(filename)\n\tfile, err := cli.openFile(ctx, filespan.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\tloc, err := file.spanLocation(filespan)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.CodeLensParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},\n\t}\n\tlenses, err := cli.server.CodeLens(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, lens := range lenses {\n\t\tsp, err := file.rangeSpan(lens.Range)\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\n\t\tif title != \"\" && lens.Command.Title != title {\n\t\t\tcontinue // title was specified but does not match\n\t\t}\n\t\tif filespan.HasPosition() && !protocol.Intersect(loc.Range, lens.Range) {\n\t\t\tcontinue // position was specified but does not match\n\t\t}\n\n\t\t// -exec: run the first matching code lens.\n\t\tif r.Exec {\n\t\t\t_, err := executeCommand(ctx, cli.server, lens.Command)\n\t\t\treturn err\n\t\t}\n\n\t\t// No -exec: list matching code lenses.\n\t\tfmt.Printf(\"%v: %q [%s]\\n\", sp, lens.Command.Title, lens.Command.Command)\n\t}\n\n\tif r.Exec {\n\t\treturn fmt.Errorf(\"no code lens at %s with title %q\", filespan, title)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/counters.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport \"golang.org/x/telemetry/counter\"\n\n// Proposed counters for evaluating usage of the Go MCP Server. These counters\n// increment when the user starts up the server in attached or headless mode.\nvar (\n\tcountHeadlessMCPStdIO = counter.New(\"gopls/mcp-headless:stdio\")\n\tcountHeadlessMCPSSE   = counter.New(\"gopls/mcp-headless:sse\")\n\tcountAttachedMCP      = counter.New(\"gopls/mcp\")\n)\n"
  },
  {
    "path": "gopls/internal/cmd/definition.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// A Definition is the result of a 'definition' query.\ntype Definition struct {\n\tSpan        span   `json:\"span\"`        // span of the definition\n\tDescription string `json:\"description\"` // description of the denoted object\n}\n\n// These constant is printed in the help, and then used in a test to verify the\n// help is still valid.\n// They refer to \"Set\" in \"flag.FlagSet\" from the DetailedHelp method below.\nconst (\n\texampleLine   = 44\n\texampleColumn = 47\n\texampleOffset = 1270\n)\n\n// definition implements the definition verb for gopls.\ntype definition struct {\n\tapp *Application\n\n\tJSON              bool `flag:\"json\" help:\"emit output in JSON format\"`\n\tMarkdownSupported bool `flag:\"markdown\" help:\"support markdown in responses\"`\n}\n\nfunc (d *definition) Name() string      { return \"definition\" }\nfunc (d *definition) Parent() string    { return d.app.Name() }\nfunc (d *definition) Usage() string     { return \"[definition-flags] <position>\" }\nfunc (d *definition) ShortHelp() string { return \"show declaration of selected identifier\" }\nfunc (d *definition) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprintf(f.Output(), `\nExample: show the definition of the identifier at syntax at offset %[1]v in this file (flag.FlagSet):\n\n\t$ gopls definition internal/cmd/definition.go:%[1]v:%[2]v\n\t$ gopls definition internal/cmd/definition.go:#%[3]v\n\ndefinition-flags:\n`, exampleLine, exampleColumn, exampleOffset)\n\tprintFlagDefaults(f)\n}\n\n// Run performs the definition query as specified by args and prints the\n// results to stdout.\nfunc (d *definition) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"definition expects 1 argument\")\n\t}\n\t// Plaintext makes more sense for the command line.\n\topts := d.app.options\n\td.app.options = func(o *settings.Options) {\n\t\tif opts != nil {\n\t\t\topts(o)\n\t\t}\n\t\to.PreferredContentFormat = protocol.PlainText\n\t\tif d.MarkdownSupported {\n\t\t\to.PreferredContentFormat = protocol.Markdown\n\t\t}\n\t}\n\tcli, _, err := d.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp := protocol.DefinitionParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\tlocs, err := cli.server.Definition(ctx, &p)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\n\tif len(locs) == 0 {\n\t\treturn fmt.Errorf(\"%v: no definition location (not an identifier?)\", from)\n\t}\n\tfile, err = cli.openFile(ctx, locs[0].URI)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\tdefinition, err := file.locationSpan(locs[0])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\n\tq := protocol.HoverParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\thover, err := cli.server.Hover(ctx, &q)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\tvar description string\n\tif hover != nil {\n\t\tdescription = strings.TrimSpace(hover.Contents.Value)\n\t}\n\n\tresult := &Definition{\n\t\tSpan:        definition,\n\t\tDescription: description,\n\t}\n\tif d.JSON {\n\t\tenc := json.NewEncoder(os.Stdout)\n\t\tenc.SetIndent(\"\", \"\\t\")\n\t\treturn enc.Encode(result)\n\t}\n\tfmt.Printf(\"%v\", result.Span)\n\tif len(result.Description) > 0 {\n\t\tfmt.Printf(\": defined here as %s\", result.Description)\n\t}\n\tfmt.Printf(\"\\n\")\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/execute.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// execute implements the LSP ExecuteCommand verb for gopls.\ntype execute struct {\n\tEditFlags\n\tapp *Application\n}\n\nfunc (e *execute) Name() string      { return \"execute\" }\nfunc (e *execute) Parent() string    { return e.app.Name() }\nfunc (e *execute) Usage() string     { return \"[flags] command argument...\" }\nfunc (e *execute) ShortHelp() string { return \"Execute a gopls custom LSP command\" }\nfunc (e *execute) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nThe execute command sends an LSP ExecuteCommand request to gopls,\nwith a set of optional JSON argument values.\nSome commands return a result, also JSON.\n\nGopls' command set is defined by the command.Interface type; see\nhttps://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol/command#Interface.\nIt is not a stable interface: commands may change or disappear without notice.\n\nExamples:\n\n\t$ gopls execute gopls.add_import '{\"ImportPath\": \"fmt\", \"URI\": \"file:///hello.go\"}'\n\t$ gopls execute gopls.run_tests '{\"URI\": \"file:///a_test.go\", \"Tests\": [\"Test\"]}'\n\t$ gopls execute gopls.list_known_packages '{\"URI\": \"file:///hello.go\"}'\n\nexecute-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (e *execute) Run(ctx context.Context, args ...string) error {\n\tif len(args) == 0 {\n\t\treturn tool.CommandLineErrorf(\"execute requires a command name\")\n\t}\n\tcmd := args[0]\n\tif !slices.Contains(command.Commands, command.Command(cmd)) {\n\t\treturn tool.CommandLineErrorf(\"unrecognized command: %s\", cmd)\n\t}\n\n\t// A command may have multiple arguments, though the only one\n\t// that currently does so is the \"legacy\" gopls.test,\n\t// so we don't show an example of it.\n\tvar jsonArgs []json.RawMessage\n\tfor i, arg := range args[1:] {\n\t\tvar dummy any\n\t\tif err := json.Unmarshal([]byte(arg), &dummy); err != nil {\n\t\t\treturn fmt.Errorf(\"argument %d is not valid JSON: %v\", i+1, err)\n\t\t}\n\t\tjsonArgs = append(jsonArgs, json.RawMessage(arg))\n\t}\n\n\te.app.editFlags = &e.EditFlags // in case command performs an edit\n\n\tcli, _, err := e.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tres, err := executeCommand(ctx, cli.server, &protocol.Command{\n\t\tCommand:   cmd,\n\t\tArguments: jsonArgs,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tif res != nil {\n\t\tdata, err := json.MarshalIndent(res, \"\", \"\\t\")\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s\\n\", data)\n\t}\n\treturn nil\n}\n\n// executeCommand executes a protocol.Command, displaying progress\n// messages and awaiting completion of asynchronous commands.\nfunc executeCommand(ctx context.Context, server protocol.Server, cmd *protocol.Command) (any, error) {\n\treturn server.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{\n\t\tCommand:   cmd.Command,\n\t\tArguments: cmd.Arguments,\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/cmd/folding_range.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// foldingRanges implements the folding_ranges verb for gopls\ntype foldingRanges struct {\n\tapp *Application\n}\n\nfunc (r *foldingRanges) Name() string      { return \"folding_ranges\" }\nfunc (r *foldingRanges) Parent() string    { return r.app.Name() }\nfunc (r *foldingRanges) Usage() string     { return \"<file>\" }\nfunc (r *foldingRanges) ShortHelp() string { return \"display selected file's folding ranges\" }\nfunc (r *foldingRanges) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ gopls folding_ranges helper/helper.go\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *foldingRanges) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"folding_ranges expects 1 argument (file)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tif _, err := cli.openFile(ctx, from.URI()); err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.FoldingRangeParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: from.URI(),\n\t\t},\n\t}\n\n\tranges, err := cli.server.FoldingRange(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, r := range ranges {\n\t\t// We assume our server always supplies these fields.\n\t\tfmt.Printf(\"%v:%v-%v:%v\\n\",\n\t\t\t*r.StartLine+1,\n\t\t\t*r.StartCharacter+1,\n\t\t\t*r.EndLine+1,\n\t\t\t*r.EndCharacter+1,\n\t\t)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/format.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// format implements the format verb for gopls.\ntype format struct {\n\tEditFlags\n\tapp *Application\n}\n\nfunc (c *format) Name() string      { return \"format\" }\nfunc (c *format) Parent() string    { return c.app.Name() }\nfunc (c *format) Usage() string     { return \"[format-flags] <filerange>\" }\nfunc (c *format) ShortHelp() string { return \"format the code according to the go standard\" }\nfunc (c *format) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nThe arguments supplied may be simple file names, or ranges within files.\n\nExample: reformat this file:\n\n\t$ gopls format -w internal/cmd/check.go\n\nformat-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run performs the check on the files specified by args and prints the\n// results to stdout.\nfunc (c *format) Run(ctx context.Context, args ...string) error {\n\tif len(args) == 0 {\n\t\treturn nil\n\t}\n\tc.app.editFlags = &c.EditFlags\n\tcli, _, err := c.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\tfor _, arg := range args {\n\t\tspn := parseSpan(arg)\n\t\tfile, err := cli.openFile(ctx, spn.URI())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tloc, err := file.spanLocation(spn)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif loc.Range.Start != loc.Range.End {\n\t\t\treturn fmt.Errorf(\"only full file formatting supported\")\n\t\t}\n\t\tp := protocol.DocumentFormattingParams{\n\t\t\tTextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},\n\t\t}\n\t\tedits, err := cli.server.Formatting(ctx, &p)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%v: %v\", spn, err)\n\t\t}\n\t\tif err := applyTextEdits(file.mapper, edits, c.app.editFlags); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/help_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd_test\n\n// This file defines tests to ensure the cmd/usage/*.hlp files match\n// the output of the tool. The .hlp files are not actually needed by\n// the executable (they are not //go:embed-ded, say), but they make it\n// easier to review changes to the gopls command's help logic since\n// any effects are manifest as changes to these files.\n\n//go:generate go test -run Help -update-help-files\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/cmd\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\nvar updateHelpFiles = flag.Bool(\"update-help-files\", false, \"Write out the help files instead of checking them\")\n\nconst appName = \"gopls\"\n\nfunc TestHelpFiles(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.\n\tapp := cmd.New()\n\tctx := context.Background()\n\tfor _, page := range append(app.Commands(), app) {\n\t\tt.Run(page.Name(), func(t *testing.T) {\n\t\t\tvar buf bytes.Buffer\n\t\t\ts := flag.NewFlagSet(page.Name(), flag.ContinueOnError)\n\t\t\ts.SetOutput(&buf)\n\t\t\ttool.Run(ctx, s, page, []string{\"-h\"}) // ignore error\n\t\t\tname := page.Name()\n\t\t\tif name == appName {\n\t\t\t\tname = \"usage\"\n\t\t\t}\n\t\t\thelpFile := filepath.Join(\"usage\", name+\".hlp\")\n\t\t\tgot := buf.Bytes()\n\t\t\tif *updateHelpFiles {\n\t\t\t\tif err := os.WriteFile(helpFile, got, 0666); err != nil {\n\t\t\t\t\tt.Errorf(\"Failed writing %v: %v\", helpFile, err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\twant, err := os.ReadFile(helpFile)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Missing help file %q\", helpFile)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(string(want), string(got)); diff != \"\" {\n\t\t\t\tt.Errorf(\"Help file %q did not match, run with -update-help-files to fix (-want +got)\\n%s\", helpFile, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestVerboseHelp(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // This is a lie. We actually need the source code.\n\tapp := cmd.New()\n\tctx := context.Background()\n\tvar buf bytes.Buffer\n\ts := flag.NewFlagSet(appName, flag.ContinueOnError)\n\ts.SetOutput(&buf)\n\ttool.Run(ctx, s, app, []string{\"-v\", \"-h\"}) // ignore error\n\tgot := buf.Bytes()\n\n\thelpFile := filepath.Join(\"usage\", \"usage-v.hlp\")\n\tif *updateHelpFiles {\n\t\tif err := os.WriteFile(helpFile, got, 0666); err != nil {\n\t\t\tt.Errorf(\"Failed writing %v: %v\", helpFile, err)\n\t\t}\n\t\treturn\n\t}\n\twant, err := os.ReadFile(helpFile)\n\tif err != nil {\n\t\tt.Fatalf(\"Missing help file %q\", helpFile)\n\t}\n\tif diff := cmp.Diff(string(want), string(got)); diff != \"\" {\n\t\tt.Errorf(\"Help file %q did not match, run with -update-help-files to fix (-want +got)\\n%s\", helpFile, diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cmd/highlight.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// highlight implements the highlight verb for gopls.\ntype highlight struct {\n\tapp *Application\n}\n\nfunc (r *highlight) Name() string      { return \"highlight\" }\nfunc (r *highlight) Parent() string    { return r.app.Name() }\nfunc (r *highlight) Usage() string     { return \"<position>\" }\nfunc (r *highlight) ShortHelp() string { return \"display selected identifier's highlights\" }\nfunc (r *highlight) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls highlight helper/helper.go:8:6\n\t$ gopls highlight helper/helper.go:#53\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *highlight) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"highlight expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.DocumentHighlightParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\thighlights, err := cli.server.DocumentHighlight(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar results []span\n\tfor _, h := range highlights {\n\t\ts, err := file.rangeSpan(h.Range)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresults = append(results, s)\n\t}\n\t// Sort results to make tests deterministic since DocumentHighlight uses a map.\n\tsortSpans(results)\n\n\tfor _, s := range results {\n\t\tfmt.Println(s)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/implementation.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// implementation implements the implementation verb for gopls\ntype implementation struct {\n\tapp *Application\n}\n\nfunc (i *implementation) Name() string      { return \"implementation\" }\nfunc (i *implementation) Parent() string    { return i.app.Name() }\nfunc (i *implementation) Usage() string     { return \"<position>\" }\nfunc (i *implementation) ShortHelp() string { return \"display selected identifier's implementation\" }\nfunc (i *implementation) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls implementation helper/helper.go:8:6\n\t$ gopls implementation helper/helper.go:#53\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (i *implementation) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"implementation expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := i.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.ImplementationParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\timplementations, err := cli.server.Implementation(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar spans []string\n\tfor _, impl := range implementations {\n\t\tf, err := cli.openFile(ctx, impl.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tspan, err := f.locationSpan(impl)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tspans = append(spans, fmt.Sprint(span))\n\t}\n\tsort.Strings(spans)\n\n\tfor _, s := range spans {\n\t\tfmt.Println(s)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/imports.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// imports implements the import verb for gopls.\ntype imports struct {\n\tEditFlags\n\tapp *Application\n}\n\nfunc (t *imports) Name() string      { return \"imports\" }\nfunc (t *imports) Parent() string    { return t.app.Name() }\nfunc (t *imports) Usage() string     { return \"[imports-flags] <filename>\" }\nfunc (t *imports) ShortHelp() string { return \"updates import statements\" }\nfunc (t *imports) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprintf(f.Output(), `\nExample: update imports statements in a file:\n\n\t$ gopls imports -w internal/cmd/check.go\n\nimports-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run performs diagnostic checks on the file specified and either;\n// - if -w is specified, updates the file in place;\n// - if -d is specified, prints out unified diffs of the changes; or\n// - otherwise, prints the new versions to stdout.\nfunc (t *imports) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"imports expects 1 argument\")\n\t}\n\tt.app.editFlags = &t.EditFlags\n\tcli, _, err := t.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\turi := from.URI()\n\tfile, err := cli.openFile(ctx, uri)\n\tif err != nil {\n\t\treturn err\n\t}\n\tactions, err := cli.server.CodeAction(ctx, &protocol.CodeActionParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t\tContext: protocol.CodeActionContext{\n\t\t\tOnly: []protocol.CodeActionKind{protocol.SourceOrganizeImports},\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\tvar edits []protocol.TextEdit\n\tfor _, a := range actions {\n\t\tfor _, c := range a.Edit.DocumentChanges {\n\t\t\t// This code action should affect only the specified file;\n\t\t\t// it is safe to ignore others.\n\t\t\tif c.TextDocumentEdit != nil && c.TextDocumentEdit.TextDocument.URI == uri {\n\t\t\t\tedits = append(edits, protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)\n\t\t\t}\n\t\t}\n\t}\n\treturn applyTextEdits(file.mapper, edits, t.app.editFlags)\n}\n"
  },
  {
    "path": "gopls/internal/cmd/info.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\n// This file defines the help, bug, version, api-json, licenses commands.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/url\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/doc\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\tlicensespkg \"golang.org/x/tools/gopls/internal/licenses\"\n\t\"golang.org/x/tools/gopls/internal/util/browser\"\n\tgoplsbug \"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// help implements the help command.\ntype help struct {\n\tapp *Application\n}\n\nfunc (h *help) Name() string      { return \"help\" }\nfunc (h *help) Parent() string    { return h.app.Name() }\nfunc (h *help) Usage() string     { return \"\" }\nfunc (h *help) ShortHelp() string { return \"print usage information for subcommands\" }\nfunc (h *help) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\n\nExamples:\n$ gopls help                         # main gopls help message\n$ gopls help remote                  # help on 'remote' command\n$ gopls help remote sessions         # help on 'remote sessions' subcommand\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run prints help information about a subcommand.\nfunc (h *help) Run(ctx context.Context, args ...string) error {\n\tfind := func(cmds []tool.Application, name string) tool.Application {\n\t\tfor _, cmd := range cmds {\n\t\t\tif cmd.Name() == name {\n\t\t\t\treturn cmd\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Find the subcommand denoted by args (empty => h.app).\n\tvar cmd tool.Application = h.app\n\tfor i, arg := range args {\n\t\tcmd = find(getSubcommands(cmd), arg)\n\t\tif cmd == nil {\n\t\t\treturn tool.CommandLineErrorf(\n\t\t\t\t\"no such subcommand: %s\", strings.Join(args[:i+1], \" \"))\n\t\t}\n\t}\n\n\t// 'gopls help cmd subcmd' is equivalent to 'gopls cmd subcmd -h'.\n\t// The flag package prints the usage information (defined by tool.Run)\n\t// when it sees the -h flag.\n\tfs := flag.NewFlagSet(cmd.Name(), flag.ExitOnError)\n\treturn tool.Run(ctx, fs, h.app, append(args[:len(args):len(args)], \"-h\"))\n}\n\n// version implements the version command.\ntype version struct {\n\tJSON bool `flag:\"json\" help:\"outputs in json format.\"`\n\n\tapp *Application\n}\n\nfunc (v *version) Name() string      { return \"version\" }\nfunc (v *version) Parent() string    { return v.app.Name() }\nfunc (v *version) Usage() string     { return \"\" }\nfunc (v *version) ShortHelp() string { return \"print the gopls version information\" }\nfunc (v *version) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), ``)\n\tprintFlagDefaults(f)\n}\n\n// Run prints version information to stdout.\nfunc (v *version) Run(ctx context.Context, args ...string) error {\n\tvar mode = debug.PlainText\n\tif v.JSON {\n\t\tmode = debug.JSON\n\t}\n\tvar buf bytes.Buffer\n\tdebug.WriteVersionInfo(&buf, v.app.verbose(), mode)\n\t_, err := io.Copy(os.Stdout, &buf)\n\treturn err\n}\n\n// bug implements the bug command.\ntype bug struct {\n\tapp *Application\n}\n\nfunc (b *bug) Name() string      { return \"bug\" }\nfunc (b *bug) Parent() string    { return b.app.Name() }\nfunc (b *bug) Usage() string     { return \"\" }\nfunc (b *bug) ShortHelp() string { return \"report a bug in gopls\" }\nfunc (b *bug) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), ``)\n\tprintFlagDefaults(f)\n}\n\nconst goplsBugPrefix = \"x/tools/gopls: <DESCRIBE THE PROBLEM>\"\nconst goplsBugHeader = `ATTENTION: Please answer these questions BEFORE submitting your issue. Thanks!\n\n#### What did you do?\nIf possible, provide a recipe for reproducing the error.\nA complete runnable program is good.\nA link on play.golang.org is better.\nA failing unit test is the best.\n\n#### What did you expect to see?\n\n\n#### What did you see instead?\n\n\n`\n\n// Run collects some basic information and then prepares an issue ready to\n// be reported.\nfunc (b *bug) Run(ctx context.Context, args ...string) error {\n\t// This undocumented environment variable allows\n\t// the cmd integration test (and maintainers) to\n\t// trigger a call to bug.Report.\n\tif msg := os.Getenv(\"TEST_GOPLS_BUG\"); msg != \"\" {\n\t\tfilecache.Start() // register bug handler\n\t\tgoplsbug.Report(msg)\n\t\treturn nil\n\t}\n\n\t// Enumerate bug reports, grouped and sorted.\n\t_, reports := filecache.BugReports()\n\tsort.Slice(reports, func(i, j int) bool {\n\t\tx, y := reports[i], reports[i]\n\t\tif x.Key != y.Key {\n\t\t\treturn x.Key < y.Key // ascending key order\n\t\t}\n\t\treturn y.AtTime.Before(x.AtTime) // most recent first\n\t})\n\tkeyDenom := make(map[string]int) // key is \"file:line\"\n\tfor _, report := range reports {\n\t\tkeyDenom[report.Key]++\n\t}\n\n\t// Privacy: the content of 'public' will be posted to GitHub\n\t// to populate an issue textarea. Even though the user must\n\t// submit the form to share the information with the world,\n\t// merely populating the form causes us to share the\n\t// information with GitHub itself.\n\t//\n\t// For that reason, we cannot write private information to\n\t// public, such as bug reports, which may quote source code.\n\tpublic := &bytes.Buffer{}\n\tfmt.Fprint(public, goplsBugHeader)\n\tif len(reports) > 0 {\n\t\tfmt.Fprintf(public, \"#### Internal errors\\n\\n\")\n\t\tfmt.Fprintf(public, \"Gopls detected %d internal errors, %d distinct:\\n\",\n\t\t\tlen(reports), len(keyDenom))\n\t\tfor key, denom := range keyDenom {\n\t\t\tfmt.Fprintf(public, \"- %s (%d)\\n\", key, denom)\n\t\t}\n\t\tfmt.Fprintf(public, \"\\nPlease copy the full information printed by `gopls bug` here, if you are comfortable sharing it.\\n\\n\")\n\t}\n\tdebug.WriteVersionInfo(public, true, debug.Markdown)\n\tbody := public.String()\n\ttitle := strings.Join(args, \" \")\n\tif !strings.HasPrefix(title, goplsBugPrefix) {\n\t\ttitle = goplsBugPrefix + title\n\t}\n\tif !browser.Open(\"https://github.com/golang/go/issues/new?title=\" + url.QueryEscape(title) + \"&body=\" + url.QueryEscape(body)) {\n\t\tfmt.Print(\"Please file a new issue at golang.org/issue/new using this template:\\n\\n\")\n\t\tfmt.Print(body)\n\t}\n\n\t// Print bug reports to stdout (not GitHub).\n\tkeyNum := make(map[string]int)\n\tfor _, report := range reports {\n\t\tfmt.Printf(\"-- %v -- \\n\", report.AtTime)\n\n\t\t// Append seq number (e.g. \" (1/2)\") for repeated keys.\n\t\tvar seq string\n\t\tif denom := keyDenom[report.Key]; denom > 1 {\n\t\t\tkeyNum[report.Key]++\n\t\t\tseq = fmt.Sprintf(\" (%d/%d)\", keyNum[report.Key], denom)\n\t\t}\n\n\t\t// Privacy:\n\t\t// - File and Stack may contain the name of the user that built gopls.\n\t\t// - Description may contain names of the user's packages/files/symbols.\n\t\tfmt.Printf(\"%s:%d: %s%s\\n\\n\", report.File, report.Line, report.Description, seq)\n\t\tfmt.Printf(\"%s\\n\\n\", report.Stack)\n\t}\n\tif len(reports) > 0 {\n\t\tfmt.Printf(\"Please copy the above information into the GitHub issue, if you are comfortable sharing it.\\n\")\n\t}\n\n\treturn nil\n}\n\ntype apiJSON struct {\n\tapp *Application\n}\n\nfunc (j *apiJSON) Name() string      { return \"api-json\" }\nfunc (j *apiJSON) Parent() string    { return j.app.Name() }\nfunc (j *apiJSON) Usage() string     { return \"\" }\nfunc (j *apiJSON) ShortHelp() string { return \"print JSON describing gopls API\" }\nfunc (j *apiJSON) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nThe api-json command prints a JSON value that describes\nand documents all gopls' public interfaces.\nIts schema is defined by golang.org/x/tools/gopls/internal/doc.API.\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (j *apiJSON) Run(ctx context.Context, args ...string) error {\n\tos.Stdout.WriteString(doc.JSON)\n\tfmt.Println()\n\treturn nil\n}\n\ntype licenses struct {\n\tapp *Application\n}\n\nfunc (l *licenses) Name() string      { return \"licenses\" }\nfunc (l *licenses) Parent() string    { return l.app.Name() }\nfunc (l *licenses) Usage() string     { return \"\" }\nfunc (l *licenses) ShortHelp() string { return \"print licenses of included software\" }\nfunc (l *licenses) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), ``)\n\tprintFlagDefaults(f)\n}\n\nconst licensePreamble = `\ngopls is made available under the following BSD-style license:\n\nCopyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ngopls implements the LSP specification, which is made available under the following license:\n\nCopyright (c) Microsoft Corporation\n\nAll rights reserved.\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy,\nmodify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\nBE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT\nOF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\ngopls also includes software made available under these licenses:\n`\n\nfunc (l *licenses) Run(ctx context.Context, args ...string) error {\n\ttxt := licensePreamble\n\tif licensespkg.Text == \"\" {\n\t\ttxt += \"(development gopls, license information not available)\"\n\t} else {\n\t\ttxt += licensespkg.Text\n\t}\n\tfmt.Fprint(os.Stdout, txt)\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/integration_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cmdtest contains the test suite for the command line behavior of gopls.\npackage cmd_test\n\n// This file defines integration tests of each gopls subcommand that\n// fork+exec the command in a separate process.\n//\n// (Rather than execute 'go build gopls' during the test, we reproduce\n// the main entrypoint in the test executable.)\n//\n// The purpose of this test is to exercise client-side logic such as\n// argument parsing and formatting of LSP RPC responses, not server\n// behavior; see lsp_test for that.\n//\n// All tests run in parallel.\n//\n// TODO(adonovan):\n// - Use markers to represent positions in the input and in assertions.\n// - Coverage of cross-cutting things like cwd, environ, span parsing, etc.\n// - Subcommands that accept -write and -diff flags implement them\n//   consistently; factor their tests.\n// - Add missing test for 'vulncheck' subcommand.\n// - Add tests for client-only commands: serve, bug, help, api-json, licenses.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cmd\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/version\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/tool\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TestVersion tests the 'version' subcommand (info.go).\nfunc TestVersion(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, \"\")\n\n\t// There's not much we can robustly assert about the actual version.\n\twant := version.Version() // e.g. \"master\"\n\n\t// basic\n\t{\n\t\tres := gopls(t, tree, \"version\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(want)\n\t}\n\n\t// basic, with version override\n\t{\n\t\tres := goplsWithEnv(t, tree, []string{\"TEST_GOPLS_VERSION=v1.2.3\"}, \"version\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`v1\\.2\\.3`)\n\t}\n\n\t// -json flag\n\t{\n\t\tres := gopls(t, tree, \"version\", \"-json\")\n\t\tres.checkExit(true)\n\t\tvar v debug.ServerVersion\n\t\tif res.toJSON(&v) {\n\t\t\tif v.Version != want {\n\t\t\t\tt.Errorf(\"expected Version %q, got %q (%v)\", want, v.Version, res)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestCheck tests the 'check' subcommand (check.go).\nfunc TestCheck(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nimport \"fmt\"\nvar _ = fmt.Sprintf(\"%s\", 123)\n\n-- b.go --\npackage a\nimport \"fmt\"\nvar _ = fmt.Sprintf(\"%d\", \"123\")\n-- c/c.go --\npackage c\nvar C int\n-- c/c2.go --\npackage c\nvar C int\n-- d/d.go --\npackage d\n\nimport \"io/ioutil\"\n\nvar _ = ioutil.ReadFile\n`)\n\n\t// no files\n\t{\n\t\tres := gopls(t, tree, \"check\")\n\t\tres.checkExit(true)\n\t\tif res.stdout != \"\" {\n\t\t\tt.Errorf(\"unexpected output: %v\", res)\n\t\t}\n\t}\n\n\t// one file\n\t{\n\t\tres := gopls(t, tree, \"check\", \"./a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"fmt.Sprintf format %s has arg 123 of wrong type int\")\n\t}\n\n\t// two files\n\t{\n\t\tres := gopls(t, tree, \"check\", \"./a.go\", \"./b.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`a.go:.* fmt.Sprintf format %s has arg 123 of wrong type int`)\n\t\tres.checkStdout(`b.go:.* fmt.Sprintf format %d has arg \"123\" of wrong type string`)\n\t}\n\n\t// diagnostic with related information spanning files\n\t{\n\t\tres := gopls(t, tree, \"check\", \"./c/c2.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`c2.go:2:5-6: C redeclared in this block`)\n\t\tres.checkStdout(`c.go:2:5-6: - other declaration of C`)\n\t}\n\n\t// No deprecated (hint) diagnostic without -severity.\n\t{\n\t\tres := gopls(t, tree, \"check\", \"./d/d.go\")\n\t\tres.checkExit(true)\n\t\tif len(res.stdout) > 0 {\n\t\t\tt.Errorf(\"check ./d/d.go returned unexpected output:\\n%s\", res.stdout)\n\t\t}\n\t}\n\n\t// Deprecated (hint) diagnostics with -severity=hint\n\t{\n\t\tres := gopls(t, tree, \"check\", \"-severity=hint\", \"./d/d.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`ioutil.ReadFile is deprecated`)\n\t}\n}\n\n// TestCallHierarchy tests the 'call_hierarchy' subcommand (call_hierarchy.go).\nfunc TestCallHierarchy(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc f() {}\nfunc g() {\n\tf()\n}\nfunc h() {\n\tf()\n\tf()\n}\n`)\n\t// missing position\n\t{\n\t\tres := gopls(t, tree, \"call_hierarchy\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// wrong place\n\t{\n\t\tres := gopls(t, tree, \"call_hierarchy\", \"a.go:1\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"identifier not found\")\n\t}\n\t// f is called once from g and twice from h.\n\t{\n\t\tres := gopls(t, tree, \"call_hierarchy\", \"a.go:2:6\")\n\t\tres.checkExit(true)\n\t\t// We use regexp '.' as an OS-agnostic path separator.\n\t\tres.checkStdout(\"ranges 7:2-3, 8:2-3 in ..a.go from/to function h in ..a.go:6:6-7\")\n\t\tres.checkStdout(\"ranges 4:2-3 in ..a.go from/to function g in ..a.go:3:6-7\")\n\t\tres.checkStdout(\"identifier: function f in ..a.go:2:6-7\")\n\t}\n}\n\n// TestCodeLens tests the 'codelens' subcommand (codelens.go).\nfunc TestCodeLens(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n-- a/a_test.go --\npackage a_test\nimport \"testing\"\nfunc TestPass(t *testing.T) {}\nfunc TestFail(t *testing.T) { t.Fatal(\"fail\") }\n`)\n\t// missing position\n\t{\n\t\tres := gopls(t, tree, \"codelens\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"requires a file name\")\n\t}\n\t// list code lenses\n\t{\n\t\tres := gopls(t, tree, \"codelens\", \"./a/a_test.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`a_test.go:3: \"run test\" \\[gopls.run_tests\\]`)\n\t\tres.checkStdout(`a_test.go:4: \"run test\" \\[gopls.run_tests\\]`)\n\t}\n\t// no codelens with title/position\n\t{\n\t\tres := gopls(t, tree, \"codelens\", \"-exec\", \"./a/a_test.go:1\", \"nope\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(`no code lens at .* with title \"nope\"`)\n\t}\n\t// run the passing test\n\t{\n\t\tres := gopls(t, tree, \"-v\", \"codelens\", \"-exec\", \"./a/a_test.go:3\", \"run test\")\n\t\tres.checkExit(true)\n\t\tres.checkStderr(`PASS: TestPass`)         // from go test\n\t\tres.checkStderr(\"Info: all tests passed\") // from gopls.test\n\t}\n\t// run the failing test\n\t{\n\t\tres := gopls(t, tree, \"codelens\", \"-exec\", \"./a/a_test.go:4\", \"run test\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(`FAIL\texample.com/a`)\n\t\tres.checkStderr(\"Info: 1 / 1 tests failed\")\n\t}\n}\n\n// TestDefinition tests the 'definition' subcommand (definition.go).\nfunc TestDefinition(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nimport \"fmt\"\nfunc f() {\n\tfmt.Println()\n}\nfunc g() {\n\tf()\n}\n`)\n\t// missing position\n\t{\n\t\tres := gopls(t, tree, \"definition\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// intra-package\n\t{\n\t\tres := gopls(t, tree, \"definition\", \"a.go:7:2\") // \"f()\"\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go:3:6-7: defined here as func f\")\n\t}\n\t// cross-package\n\t{\n\t\tres := gopls(t, tree, \"definition\", \"a.go:4:7\") // \"Println\"\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"print.go.* defined here as func fmt.Println\")\n\t\tres.checkStdout(\"Println formats using the default formats for its operands\")\n\t}\n\t// -json and -markdown\n\t{\n\t\tres := gopls(t, tree, \"definition\", \"-json\", \"-markdown\", \"a.go:4:7\")\n\t\tres.checkExit(true)\n\t\tvar defn cmd.Definition\n\t\tif res.toJSON(&defn) {\n\t\t\tif !strings.HasPrefix(defn.Description, \"```go\\nfunc fmt.Println\") {\n\t\t\t\tt.Errorf(\"Description does not start with markdown code block. Got: %s\", defn.Description)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestExecute tests the 'execute' subcommand (execute.go).\nfunc TestExecute(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- hello.go --\npackage a\nfunc main() {}\n\n-- hello_test.go --\npackage a\nimport \"testing\"\nfunc TestHello(t *testing.T) {\n\tt.Fatal(\"oops\")\n}\n`)\n\t// missing command name\n\t{\n\t\tres := gopls(t, tree, \"execute\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"requires a command\")\n\t}\n\t// bad command\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"gopls.foo\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"unrecognized command: gopls.foo\")\n\t}\n\t// too few arguments\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"gopls.run_tests\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expected 1 input arguments, got 0\")\n\t}\n\t// too many arguments\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"gopls.run_tests\", \"null\", \"null\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expected 1 input arguments, got 2\")\n\t}\n\t// argument is not JSON\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"gopls.run_tests\", \"hello\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"argument 1 is not valid JSON: invalid character 'h'\")\n\t}\n\t// add import, show diff\n\thello := \"file://\" + filepath.ToSlash(tree) + \"/hello.go\"\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"-d\", \"gopls.add_import\", `{\"ImportPath\": \"fmt\", \"URI\": \"`+hello+`\"}`)\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`[+]import \"fmt\"`)\n\t}\n\t// list known packages (has a result)\n\t{\n\t\tres := gopls(t, tree, \"execute\", \"gopls.list_known_packages\", `{\"URI\": \"`+hello+`\"}`)\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`\"fmt\"`)\n\t\tres.checkStdout(`\"encoding/json\"`)\n\t}\n\t// run tests\n\t{\n\t\thelloTest := \"file://\" + filepath.ToSlash(tree) + \"/hello_test.go\"\n\t\tres := gopls(t, tree, \"execute\", \"gopls.run_tests\", `{\"URI\": \"`+helloTest+`\", \"Tests\": [\"TestHello\"]}`)\n\t\tres.checkExit(false)\n\t\tres.checkStderr(`hello_test.go:4: oops`)\n\t\tres.checkStderr(`1 / 1 tests failed`)\n\t}\n}\n\n// TestFoldingRanges tests the 'folding_ranges' subcommand (folding_range.go).\nfunc TestFoldingRanges(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc f(x int) {\n\t// hello\n}\n`)\n\t// missing filename\n\t{\n\t\tres := gopls(t, tree, \"folding_ranges\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// success\n\t{\n\t\tres := gopls(t, tree, \"folding_ranges\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"2:8-2:13\") // params (x int)\n\t\tres.checkStdout(\"2:16-4:1\") //   body { ... }\n\t}\n}\n\n// TestFormat tests the 'format' subcommand (format.go).\nfunc TestFormat(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- a.go --\npackage a ;  func f ( ) { }\n`)\n\tconst want = `package a\n\nfunc f() {}\n`\n\n\t// no files => nop\n\t{\n\t\tres := gopls(t, tree, \"format\")\n\t\tres.checkExit(true)\n\t}\n\t// default => print formatted result\n\t{\n\t\tres := gopls(t, tree, \"format\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tif res.stdout != want {\n\t\t\tt.Errorf(\"format: got <<%s>>, want <<%s>>\", res.stdout, want)\n\t\t}\n\t}\n\t// start/end position not supported (unless equal to start/end of file)\n\t{\n\t\tres := gopls(t, tree, \"format\", \"a.go:1-2\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"only full file formatting supported\")\n\t}\n\t// -list: show only file names\n\t{\n\t\tres := gopls(t, tree, \"format\", \"-list\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go\")\n\t}\n\t// -diff prints a unified diff\n\t{\n\t\tres := gopls(t, tree, \"format\", \"-diff\", \"a.go\")\n\t\tres.checkExit(true)\n\t\t// We omit the filenames as they vary by OS.\n\t\twant := `\n-package a ;  func f ( ) { }\n+package a\n+\n+func f() {}\n`\n\t\tres.checkStdout(regexp.QuoteMeta(want))\n\t}\n\t// -write updates the file\n\t{\n\t\tres := gopls(t, tree, \"format\", \"-write\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"^$\") // empty\n\t\tcheckContent(t, filepath.Join(tree, \"a.go\"), want)\n\t}\n}\n\n// TestHighlight tests the 'highlight' subcommand (highlight.go).\nfunc TestHighlight(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- a.go --\npackage a\nimport \"fmt\"\nfunc f() {\n\tfmt.Println()\n\tfmt.Println()\n}\n`)\n\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"highlight\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// all occurrences of Println\n\t{\n\t\tres := gopls(t, tree, \"highlight\", \"a.go:4:7\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go:4:6-13\")\n\t\tres.checkStdout(\"a.go:5:6-13\")\n\t}\n}\n\n// TestImplementations tests the 'implementation' subcommand (implementation.go).\nfunc TestImplementations(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- a.go --\npackage a\nimport \"fmt\"\ntype T int\nfunc (T) String() string { return \"\" }\n`)\n\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"implementation\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// T.String\n\t{\n\t\tres := gopls(t, tree, \"implementation\", \"a.go:4:10\")\n\t\tres.checkExit(true)\n\t\t// TODO(adonovan): extract and check the content of the reported ranges?\n\t\t// We use regexp '.' as an OS-agnostic path separator.\n\t\tres.checkStdout(\"fmt.print.go:\")     // fmt.Stringer.String\n\t\tres.checkStdout(\"runtime.error.go:\") // runtime.stringer.String\n\t}\n}\n\n// TestImports tests the 'imports' subcommand (imports.go).\nfunc TestImports(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- a.go --\npackage a\nfunc _() {\n\tfmt.Println()\n}\n`)\n\n\twant := `\npackage a\n\nimport \"fmt\"\nfunc _() {\n\tfmt.Println()\n}\n`[1:]\n\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"imports\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// default: print with imports\n\t{\n\t\tres := gopls(t, tree, \"imports\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tif res.stdout != want {\n\t\t\tt.Errorf(\"imports: got <<%s>>, want <<%s>>\", res.stdout, want)\n\t\t}\n\t}\n\t// -diff: show a unified diff\n\t{\n\t\tres := gopls(t, tree, \"imports\", \"-diff\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(regexp.QuoteMeta(`+import \"fmt\"`))\n\t}\n\t// -write: update file\n\t{\n\t\tres := gopls(t, tree, \"imports\", \"-write\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tcheckContent(t, filepath.Join(tree, \"a.go\"), want)\n\t}\n}\n\n// TestLinks tests the 'links' subcommand (links.go).\nfunc TestLinks(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- a.go --\n// Link in package doc: https://pkg.go.dev/\npackage a\n\n// Link in internal comment: https://go.dev/cl\n\n// Doc comment link: https://blog.go.dev/\nfunc f() {}\n`)\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"links\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// success\n\t{\n\t\tres := gopls(t, tree, \"links\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"https://go.dev/cl\")\n\t\tres.checkStdout(\"https://pkg.go.dev\")\n\t\tres.checkStdout(\"https://blog.go.dev/\")\n\t}\n\t// -json\n\t{\n\t\tres := gopls(t, tree, \"links\", \"-json\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"https://pkg.go.dev\")\n\t\tres.checkStdout(\"https://go.dev/cl\")\n\t\tres.checkStdout(\"https://blog.go.dev/\") // at 5:21-5:41\n\t\tvar links []protocol.DocumentLink\n\t\tif res.toJSON(&links) {\n\t\t\t// Check just one of the three locations.\n\t\t\tif got, want := fmt.Sprint(links[2].Range), \"5:21-5:41\"; got != want {\n\t\t\t\tt.Errorf(\"wrong link location: got %v, want %v\", got, want)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestReferences tests the 'references' subcommand (references.go).\nfunc TestReferences(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nimport \"fmt\"\nfunc f() {\n\tfmt.Println()\n}\n\n-- b.go --\npackage a\nimport \"fmt\"\nfunc g() {\n\tfmt.Println()\n}\n`)\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"references\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// fmt.Println\n\t{\n\t\tres := gopls(t, tree, \"references\", \"a.go:4:10\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go:4:6-13\")\n\t\tres.checkStdout(\"b.go:4:6-13\")\n\t}\n}\n\n// TestSignature tests the 'signature' subcommand (signature.go).\nfunc TestSignature(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nimport \"fmt\"\nfunc f() {\n\tfmt.Println(123)\n}\n`)\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"signature\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// at 123 inside fmt.Println() call\n\t{\n\t\tres := gopls(t, tree, \"signature\", \"a.go:4:15\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"Println\\\\(a ...\")\n\t\tres.checkStdout(\"Println formats using the default formats...\")\n\t}\n}\n\n// TestPrepareRename tests the 'prepare_rename' subcommand (prepare_rename.go).\nfunc TestPrepareRename(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc oldname() {}\n`)\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"prepare_rename\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// in 'package' keyword\n\t{\n\t\tres := gopls(t, tree, \"prepare_rename\", \"a.go:1:3\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"request is not valid at the given position\")\n\t}\n\t// in 'package' identifier (not supported by client)\n\t{\n\t\tres := gopls(t, tree, \"prepare_rename\", \"a.go:1:9\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"can't rename package\")\n\t}\n\t// in func oldname\n\t{\n\t\tres := gopls(t, tree, \"prepare_rename\", \"a.go:2:9\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go:2:6-13\") // all of \"oldname\"\n\t}\n}\n\n// TestRename tests the 'rename' subcommand (rename.go).\nfunc TestRename(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc oldname() {}\n`)\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"rename\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 2 arguments\")\n\t}\n\t// missing newname\n\t{\n\t\tres := gopls(t, tree, \"rename\", \"a.go:1:3\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 2 arguments\")\n\t}\n\t// in 'package' keyword\n\t{\n\t\tres := gopls(t, tree, \"rename\", \"a.go:1:3\", \"newname\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"no identifier found\")\n\t}\n\t// in 'package' identifier\n\t{\n\t\tres := gopls(t, tree, \"rename\", \"a.go:1:9\", \"newname\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(`cannot rename package: module path .* same as the package path, so .* no effect`)\n\t}\n\t// success, func oldname (and -diff)\n\t{\n\t\tres := gopls(t, tree, \"rename\", \"-diff\", \"a.go:2:9\", \"newname\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(regexp.QuoteMeta(\"-func oldname() {}\"))\n\t\tres.checkStdout(regexp.QuoteMeta(\"+func newname() {}\"))\n\t}\n}\n\n// TestSymbols tests the 'symbols' subcommand (symbols.go).\nfunc TestSymbols(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc f()\nvar v int\nconst c = 0\n`)\n\t// no files\n\t{\n\t\tres := gopls(t, tree, \"symbols\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// success\n\t{\n\t\tres := gopls(t, tree, \"symbols\", \"a.go:123:456\") // (line/col ignored)\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"f Function 2:6-2:7\")\n\t\tres.checkStdout(\"v Variable 3:5-3:6\")\n\t\tres.checkStdout(\"c Constant 4:7-4:8\")\n\t}\n}\n\n// TestSemtok tests the 'semtok' subcommand (semantictokens.go).\nfunc TestSemtok(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc f()\nvar v int\nconst c = 0\n`)\n\t// no files\n\t{\n\t\tres := gopls(t, tree, \"semtok\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expected one file name\")\n\t}\n\t// success\n\t{\n\t\tres := gopls(t, tree, \"semtok\", \"a.go\")\n\t\tres.checkExit(true)\n\t\tgot := res.stdout\n\t\twant := `\n/*⇒7,keyword,[]*/package /*⇒1,namespace,[]*/a\n/*⇒4,keyword,[]*/func /*⇒1,function,[definition signature]*/f()\n/*⇒3,keyword,[]*/var /*⇒1,variable,[definition static number]*/v /*⇒3,type,[defaultLibrary number]*/int\n/*⇒5,keyword,[]*/const /*⇒1,variable,[definition readonly number]*/c = /*⇒1,number,[]*/0\n`[1:]\n\t\tif got != want {\n\t\t\tt.Errorf(\"semtok: got <<%s>>, want <<%s>>\", got, want)\n\t\t}\n\t}\n}\n\nfunc TestStats(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\n-- b/b.go --\npackage b\n-- testdata/foo.go --\npackage foo\n`)\n\n\t// Trigger a bug report with a distinctive string\n\t// and check that it was durably recorded.\n\toops := fmt.Sprintf(\"oops-%d\", rand.Int())\n\t{\n\t\tenv := []string{\"TEST_GOPLS_BUG=\" + oops}\n\t\tres := goplsWithEnv(t, tree, env, \"bug\")\n\t\tres.checkExit(true)\n\t}\n\n\tres := gopls(t, tree, \"stats\")\n\tres.checkExit(true)\n\n\tvar stats cmd.GoplsStats\n\tif err := json.Unmarshal([]byte(res.stdout), &stats); err != nil {\n\t\tt.Fatalf(\"failed to unmarshal JSON output of stats command: %v\", err)\n\t}\n\n\t// a few sanity checks\n\tchecks := []struct {\n\t\tfield string\n\t\tgot   int\n\t\twant  int\n\t}{\n\t\t{\n\t\t\t\"WorkspaceStats.Views[0].WorkspaceModules\",\n\t\t\tstats.WorkspaceStats.Views[0].WorkspacePackages.Modules,\n\t\t\t1,\n\t\t},\n\t\t{\n\t\t\t\"WorkspaceStats.Views[0].WorkspacePackages\",\n\t\t\tstats.WorkspaceStats.Views[0].WorkspacePackages.Packages,\n\t\t\t2,\n\t\t},\n\t\t{\"DirStats.Files\", stats.DirStats.Files, 4},\n\t\t{\"DirStats.GoFiles\", stats.DirStats.GoFiles, 2},\n\t\t{\"DirStats.ModFiles\", stats.DirStats.ModFiles, 1},\n\t\t{\"DirStats.TestdataFiles\", stats.DirStats.TestdataFiles, 1},\n\t}\n\tfor _, check := range checks {\n\t\tif check.got != check.want {\n\t\t\tt.Errorf(\"stats.%s = %d, want %d\", check.field, check.got, check.want)\n\t\t}\n\t}\n\n\t// Check that we got a BugReport with the expected message.\n\t{\n\t\tgot := fmt.Sprint(stats.BugReports)\n\t\twants := []string{\n\t\t\t\"cmd/info.go\", // File containing call to bug.Report\n\t\t\toops,          // Description\n\t\t}\n\t\tfor _, want := range wants {\n\t\t\tif !strings.Contains(got, want) {\n\t\t\t\tt.Errorf(\"BugReports does not contain %q. Got:<<%s>>\", want, got)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check that -anon suppresses fields containing user information.\n\t{\n\t\tres2 := gopls(t, tree, \"stats\", \"-anon\")\n\t\tres2.checkExit(true)\n\n\t\tvar stats2 cmd.GoplsStats\n\t\tif err := json.Unmarshal([]byte(res2.stdout), &stats2); err != nil {\n\t\t\tt.Fatalf(\"failed to unmarshal JSON output of stats command: %v\", err)\n\t\t}\n\t\tif got := len(stats2.BugReports); got > 0 {\n\t\t\tt.Errorf(\"Got %d bug reports with -anon, want 0. Reports:%+v\", got, stats2.BugReports)\n\t\t}\n\t\tvar stats2AsMap map[string]any\n\t\tif err := json.Unmarshal([]byte(res2.stdout), &stats2AsMap); err != nil {\n\t\t\tt.Fatalf(\"failed to unmarshal JSON output of stats command: %v\", err)\n\t\t}\n\t\t// GOPACKAGESDRIVER is user information, but is ok to print zero value.\n\t\tif v, ok := stats2AsMap[\"GOPACKAGESDRIVER\"]; ok && v != \"\" {\n\t\t\tt.Errorf(`Got GOPACKAGESDRIVER=(%v, %v); want (\"\", true(found))`, v, ok)\n\t\t}\n\t}\n\n\t// Check that -anon suppresses fields containing non-zero user information.\n\t{\n\t\tres3 := goplsWithEnv(t, tree, []string{\"GOPACKAGESDRIVER=off\"}, \"stats\", \"-anon\")\n\t\tres3.checkExit(true)\n\n\t\tvar statsAsMap3 map[string]any\n\t\tif err := json.Unmarshal([]byte(res3.stdout), &statsAsMap3); err != nil {\n\t\t\tt.Fatalf(\"failed to unmarshal JSON output of stats command: %v\", err)\n\t\t}\n\t\t// GOPACKAGESDRIVER is user information, want non-empty value to be omitted.\n\t\tif v, ok := statsAsMap3[\"GOPACKAGESDRIVER\"]; ok {\n\t\t\tt.Errorf(`Got GOPACKAGESDRIVER=(%q, %v); want (\"\", false(not found))`, v, ok)\n\t\t}\n\t}\n}\n\n// TestCodeAction tests the 'codeaction' subcommand (codeaction.go).\nfunc TestCodeAction(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\ntype T int\nfunc f() (int, string) { return }\n\n-- a/b.go --\npackage a\nimport \"io\"\nvar _ io.Reader = C{}\ntype C struct{}\n`)\n\n\t// no arguments\n\t{\n\t\tres := gopls(t, tree, \"codeaction\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects at least 1 argument\")\n\t}\n\t// list code actions in file\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"a/a.go\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`edit\t\"Fill in return values\" \\[quickfix\\]`)\n\t\tres.checkStdout(`command\t\"Browse documentation for package a\" \\[source.doc\\]`)\n\t}\n\t// list code actions in file, filtering by title\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"-title=Browse.*doc\", \"a/a.go\")\n\t\tres.checkExit(true)\n\t\tgot := res.stdout\n\t\twant := `command\t\"Browse documentation for package a\" [source.doc]` +\n\t\t\t\"\\n\" +\n\t\t\t`command\t\"Browse gopls feature documentation\" [gopls.doc.features]` +\n\t\t\t\"\\n\"\n\t\tif got != want {\n\t\t\tt.Errorf(\"codeaction: got <<%s>>, want <<%s>>\\nstderr:\\n%s\", got, want, res.stderr)\n\t\t}\n\t}\n\t// list code actions in file, filtering (hierarchically) by kind\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"-kind=source\", \"a/a.go\")\n\t\tres.checkExit(true)\n\t\tgot := res.stdout\n\t\twant := `command\t\"Browse documentation for package a\" [source.doc]` +\n\t\t\t\"\\n\" +\n\t\t\t`command\t\"Split package \\\"a\\\"\" [source.splitPackage]` +\n\t\t\t\"\\n\" +\n\t\t\t`command\t\"Show compiler optimization details for \\\"a\\\"\" [source.toggleCompilerOptDetails]` +\n\t\t\t\"\\n\"\n\t\tif got != want {\n\t\t\tt.Errorf(\"codeaction: got <<%s>>, want <<%s>>\\nstderr:\\n%s\", got, want, res.stderr)\n\t\t}\n\t}\n\t// list code actions at position (of io.Reader)\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"a/b.go:#31\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(`command\t\"Browse documentation for type io.Reader\" \\[source.doc]`)\n\t}\n\t// list quick fixes at position (of type T)\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"-kind=quickfix\", \"a/a.go:#15\")\n\t\tres.checkExit(true)\n\t\tgot := res.stdout\n\t\twant := `edit\t\"Fill in return values\" [quickfix]` + \"\\n\"\n\t\tif got != want {\n\t\t\tt.Errorf(\"codeaction: got <<%s>>, want <<%s>>\\nstderr:\\n%s\", got, want, res.stderr)\n\t\t}\n\t}\n\t// success, with explicit CodeAction kind and diagnostics span.\n\t{\n\t\tres := gopls(t, tree, \"codeaction\", \"-kind=quickfix\", \"-exec\", \"a/b.go:#40\")\n\t\tres.checkExit(true)\n\t\tgot := res.stdout\n\t\twant := `\npackage a\n\nimport \"io\"\n\nvar _ io.Reader = C{}\n\ntype C struct{}\n\n// Read implements [io.Reader].\nfunc (c C) Read(p []byte) (n int, err error) {\n\tpanic(\"unimplemented\")\n}\n`[1:]\n\t\tif got != want {\n\t\t\tt.Errorf(\"codeaction: got <<%s>>, want <<%s>>\\nstderr:\\n%s\", got, want, res.stderr)\n\t\t}\n\t}\n}\n\n// TestWorkspaceSymbol tests the 'workspace_symbol' subcommand (workspace_symbol.go).\nfunc TestWorkspaceSymbol(t *testing.T) {\n\tt.Parallel()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\nfunc someFunctionName()\n`)\n\t// no files\n\t{\n\t\tres := gopls(t, tree, \"workspace_symbol\")\n\t\tres.checkExit(false)\n\t\tres.checkStderr(\"expects 1 argument\")\n\t}\n\t// success\n\t{\n\t\tres := gopls(t, tree, \"workspace_symbol\", \"meFun\")\n\t\tres.checkExit(true)\n\t\tres.checkStdout(\"a.go:2:6-22 someFunctionName Function\")\n\t}\n}\n\n// -- test framework --\n\nfunc TestMain(m *testing.M) {\n\tswitch os.Getenv(\"ENTRYPOINT\") {\n\tcase \"goplsMain\":\n\t\tgoplsMain()\n\tdefault:\n\t\tos.Exit(m.Run())\n\t}\n}\n\n// This function is a stand-in for gopls.main in ../../../../main.go.\nfunc goplsMain() {\n\t// Panic on bugs (unlike the production gopls command),\n\t// except in tests that inject calls to bug.Report.\n\tif os.Getenv(\"TEST_GOPLS_BUG\") == \"\" {\n\t\tbug.PanicOnBugs = true\n\t}\n\n\tif v := os.Getenv(\"TEST_GOPLS_VERSION\"); v != \"\" {\n\t\tversion.VersionOverride = v\n\t}\n\n\ttool.Main(context.Background(), cmd.New(), os.Args[1:])\n}\n\n// writeTree extracts a txtar archive into a new directory and returns its path.\nfunc writeTree(t *testing.T, archive string) string {\n\troot := t.TempDir()\n\n\t// This unfortunate step is required because gopls output\n\t// expands symbolic links in its input file names (arguably it\n\t// should not), and on macOS the temp dir is in /var -> private/var.\n\troot, err := filepath.EvalSymlinks(root)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, f := range txtar.Parse([]byte(archive)).Files {\n\t\tfilename := filepath.Join(root, f.Name)\n\t\tif err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(filename, f.Data, 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\treturn root\n}\n\n// gopls executes gopls in a child process.\nfunc gopls(t *testing.T, dir string, args ...string) *result {\n\treturn goplsWithEnv(t, dir, nil, args...)\n}\n\nfunc goplsWithEnv(t *testing.T, dir string, env []string, args ...string) *result {\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Catch inadvertent use of dir=\".\", which would make\n\t// the ReplaceAll below unpredictable.\n\tif !filepath.IsAbs(dir) {\n\t\tt.Fatalf(\"dir is not absolute: %s\", dir)\n\t}\n\n\tgoplsCmd := exec.Command(os.Args[0], args...)\n\tgoplsCmd.Env = append(os.Environ(), \"ENTRYPOINT=goplsMain\")\n\tgoplsCmd.Env = append(goplsCmd.Env, \"GOPACKAGESDRIVER=off\")\n\tgoplsCmd.Env = append(goplsCmd.Env, env...)\n\tgoplsCmd.Dir = dir\n\tgoplsCmd.Stdout = new(bytes.Buffer)\n\tgoplsCmd.Stderr = new(bytes.Buffer)\n\n\tcmdErr := goplsCmd.Run()\n\n\tstdout := strings.ReplaceAll(fmt.Sprint(goplsCmd.Stdout), dir, \".\")\n\tstderr := strings.ReplaceAll(fmt.Sprint(goplsCmd.Stderr), dir, \".\")\n\texitcode := 0\n\tif cmdErr != nil {\n\t\tif exitErr, ok := cmdErr.(*exec.ExitError); ok {\n\t\t\texitcode = exitErr.ExitCode()\n\t\t} else {\n\t\t\tstderr = cmdErr.Error() // (execve failure)\n\t\t\texitcode = -1\n\t\t}\n\t}\n\tres := &result{\n\t\tt:        t,\n\t\tcommand:  \"gopls \" + strings.Join(args, \" \"),\n\t\texitcode: exitcode,\n\t\tstdout:   stdout,\n\t\tstderr:   stderr,\n\t}\n\tif false {\n\t\tt.Log(res)\n\t}\n\treturn res\n}\n\n// A result holds the result of a gopls invocation, and provides assertion helpers.\ntype result struct {\n\tt              *testing.T\n\tcommand        string\n\texitcode       int\n\tstdout, stderr string\n}\n\nfunc (res *result) String() string {\n\treturn fmt.Sprintf(\"%s: exit=%d stdout=<<%s>> stderr=<<%s>>\",\n\t\tres.command, res.exitcode, res.stdout, res.stderr)\n}\n\n// checkExit asserts that gopls returned the expected exit code.\nfunc (res *result) checkExit(success bool) {\n\tres.t.Helper()\n\tif (res.exitcode == 0) != success {\n\t\tres.t.Errorf(\"%s: exited with code %d, want success: %t (%s)\",\n\t\t\tres.command, res.exitcode, success, res)\n\t}\n}\n\n// checkStdout asserts that the gopls standard output matches the pattern.\nfunc (res *result) checkStdout(pattern string) {\n\tres.t.Helper()\n\tres.checkOutput(pattern, \"stdout\", res.stdout)\n}\n\n// checkStderr asserts that the gopls standard error matches the pattern.\nfunc (res *result) checkStderr(pattern string) {\n\tres.t.Helper()\n\tres.checkOutput(pattern, \"stderr\", res.stderr)\n}\n\nfunc (res *result) checkOutput(pattern, name, content string) {\n\tres.t.Helper()\n\tif match, err := regexp.MatchString(pattern, content); err != nil {\n\t\tres.t.Errorf(\"invalid regexp: %v\", err)\n\t} else if !match {\n\t\tres.t.Errorf(\"%s: %s does not match [%s]; got <<%s>>\",\n\t\t\tres.command, name, pattern, content)\n\t}\n}\n\n// toJSON decodes res.stdout as JSON into to *ptr and reports its success.\nfunc (res *result) toJSON(ptr any) bool {\n\tif err := json.Unmarshal([]byte(res.stdout), ptr); err != nil {\n\t\tres.t.Errorf(\"invalid JSON %v\", err)\n\t\treturn false\n\t}\n\treturn true\n}\n\n// checkContent checks that the contents of the file are as expected.\nfunc checkContent(t *testing.T, filename, want string) {\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\tif got := string(data); got != want {\n\t\tt.Errorf(\"content of %s is <<%s>>, want <<%s>>\", filename, got, want)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cmd/links.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// links implements the links verb for gopls.\ntype links struct {\n\tJSON bool `flag:\"json\" help:\"emit document links in JSON format\"`\n\n\tapp *Application\n}\n\nfunc (l *links) Name() string      { return \"links\" }\nfunc (l *links) Parent() string    { return l.app.Name() }\nfunc (l *links) Usage() string     { return \"[links-flags] <filename>\" }\nfunc (l *links) ShortHelp() string { return \"list links in a file\" }\nfunc (l *links) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprintf(f.Output(), `\nExample: list links contained within a file:\n\n\t$ gopls links internal/cmd/check.go\n\nlinks-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run finds all the links within a document\n// - if -json is specified, outputs location range and uri\n// - otherwise, prints the a list of unique links\nfunc (l *links) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"links expects 1 argument\")\n\t}\n\tcli, _, err := l.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\turi := from.URI()\n\n\tif _, err := cli.openFile(ctx, uri); err != nil {\n\t\treturn err\n\t}\n\tresults, err := cli.server.DocumentLink(ctx, &protocol.DocumentLinkParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%v: %v\", from, err)\n\t}\n\tif l.JSON {\n\t\tenc := json.NewEncoder(os.Stdout)\n\t\tenc.SetIndent(\"\", \"\\t\")\n\t\treturn enc.Encode(results)\n\t}\n\tfor _, v := range results {\n\t\tfmt.Println(*v.Target)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/mcp.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/filewatcher\"\n\tinternalmcp \"golang.org/x/tools/gopls/internal/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype headlessMCP struct {\n\tapp *Application\n\n\tAddress      string `flag:\"listen\" help:\"the address on which to run the mcp server\"`\n\tLogfile      string `flag:\"logfile\" help:\"filename to log to; if unset, logs to stderr\"`\n\tRPCTrace     bool   `flag:\"rpc.trace\" help:\"print MCP rpc traces; cannot be used with -listen\"`\n\tInstructions bool   `flag:\"instructions\" help:\"if set, print gopls' MCP instructions and exit\"`\n}\n\nfunc (m *headlessMCP) Name() string      { return \"mcp\" }\nfunc (m *headlessMCP) Parent() string    { return m.app.Name() }\nfunc (m *headlessMCP) Usage() string     { return \"[mcp-flags]\" }\nfunc (m *headlessMCP) ShortHelp() string { return \"start the gopls MCP server in headless mode\" }\n\nfunc (m *headlessMCP) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nStarts the gopls MCP server in headless mode, without needing an LSP client.\nStarts the server over stdio or sse with http, depending on whether the listen flag is provided.\n\nExamples:\n  $ gopls mcp -listen=localhost:3000\n  $ gopls mcp  //start over stdio\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (m *headlessMCP) Run(ctx context.Context, args ...string) error {\n\tif m.Instructions {\n\t\tfmt.Println(internalmcp.Instructions)\n\t\treturn nil\n\t}\n\tif m.Address != \"\" && m.RPCTrace {\n\t\t// There's currently no way to plumb logging instrumentation into the SSE\n\t\t// transport that is created on connections to the HTTP handler, so we must\n\t\t// disallow the -rpc.trace flag when using -listen.\n\t\treturn fmt.Errorf(\"-listen is incompatible with -rpc.trace\")\n\t}\n\tif m.Logfile != \"\" {\n\t\tf, err := os.Create(m.Logfile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"opening logfile: %v\", err)\n\t\t}\n\t\tlog.SetOutput(f)\n\t\tdefer f.Close()\n\t}\n\n\t// Start a new in-process gopls session and create a fake client\n\t// to connect to it.\n\tcli, sess, err := m.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tvar (\n\t\tqueueMu  sync.Mutex\n\t\tqueue    []protocol.FileEvent\n\t\tnonempty = make(chan struct{}) // receivable when len(queue) > 0\n\t\tstop     = make(chan struct{}) // closed when Run returns\n\t)\n\tdefer close(stop)\n\n\t// This goroutine forwards file change events to the LSP server.\n\tgo func() {\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-stop:\n\t\t\t\treturn\n\t\t\tcase <-nonempty:\n\t\t\t\tqueueMu.Lock()\n\t\t\t\tq := queue\n\t\t\t\tqueue = nil\n\t\t\t\tqueueMu.Unlock()\n\n\t\t\t\tif len(q) > 0 {\n\t\t\t\t\tif err := cli.server.DidChangeWatchedFiles(ctx, &protocol.DidChangeWatchedFilesParams{\n\t\t\t\t\t\tChanges: q,\n\t\t\t\t\t}); err != nil {\n\t\t\t\t\t\tlog.Printf(\"failed to notify changed files: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}()\n\n\terrHandler := func(err error) {\n\t\tlog.Printf(\"watch error: %v\", err)\n\t}\n\tw, err := filewatcher.New(\"fsnotify\", 500*time.Millisecond, nil, func(events []protocol.FileEvent) {\n\t\tif len(events) == 0 {\n\t\t\treturn\n\t\t}\n\n\t\t// Since there is no promise [protocol.Server.DidChangeWatchedFiles]\n\t\t// will return immediately, we should buffer the captured events and\n\t\t// sent them whenever available in a separate go routine.\n\t\tqueueMu.Lock()\n\t\tqueue = append(queue, events...)\n\t\tqueueMu.Unlock()\n\n\t\tselect {\n\t\tcase nonempty <- struct{}{}:\n\t\tdefault:\n\t\t}\n\t}, errHandler)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer w.Close()\n\n\t// TODO(hxjiang): in LSP's use case, the file watcher should watch for LSP\n\t// initial param workspace root.\n\n\t// TODO(hxjiang): refactor the queue pattern into a helper function to avoid\n\t// repetition.\n\tvar (\n\t\twatchStop          = make(chan struct{}) // closed to broadcast \"stop\" event\n\t\twatchQueueNonempty = make(chan struct{}) // each send indicates \"nonempty\"\n\t\twatchQueueMu       sync.Mutex\n\t\twatchQueue         []string\n\t)\n\t// The watchStop event occurs when this function returns,\n\t// for any reason (cancellation or completion).\n\tdefer close(watchStop)\n\n\t// TODO(hxjiang): memorize the roots and stop watching when the previously\n\t// watched roots are removed.\n\t// TODO(hxjiang): implement [filewatcher.Watcher]'s method StopWatchDir.\n\n\t// watchRoots is the callback triggered when the MCP client reports workspace\n\t// roots. We do not call w.WatchDir directly from this callback, but spawn a\n\t// goroutine for it because WatchDir performs OS-level filesystem operations\n\t// which can be slow. Blocking this callback would block the MCP server's\n\t// JSON-RPC message loop and stall the entireconnection.\n\twatchRoots := func(res *mcp.ListRootsResult, err error) {\n\t\tif err != nil {\n\t\t\terrHandler(err)\n\t\t\treturn\n\t\t}\n\t\twatchQueueMu.Lock()\n\t\tfor _, r := range res.Roots {\n\t\t\twatchQueue = append(watchQueue, protocol.DocumentURI(r.URI).Path())\n\t\t}\n\t\twatchQueueMu.Unlock()\n\n\t\tselect {\n\t\tcase watchQueueNonempty <- struct{}{}:\n\t\tdefault:\n\t\t}\n\t}\n\tgo func() {\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-watchStop:\n\t\t\t\treturn\n\t\t\tcase <-watchQueueNonempty:\n\t\t\t\twatchQueueMu.Lock()\n\t\t\t\tqueue := watchQueue\n\t\t\t\twatchQueue = nil\n\t\t\t\twatchQueueMu.Unlock()\n\n\t\t\t\tfor _, dir := range queue {\n\t\t\t\t\tif err := w.WatchDir(dir); err != nil {\n\t\t\t\t\t\terrHandler(err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n\n\tif m.Address != \"\" {\n\t\tcountHeadlessMCPSSE.Inc()\n\t\treturn internalmcp.Serve(ctx, m.Address, &staticSessions{sess, cli.server}, false, watchRoots)\n\t} else {\n\t\tcountHeadlessMCPStdIO.Inc()\n\t\tvar rpcLog io.Writer\n\t\tif m.RPCTrace {\n\t\t\trpcLog = log.Writer() // possibly redirected by -logfile above\n\t\t}\n\t\tlog.Printf(\"Listening for MCP messages on stdin...\")\n\t\treturn internalmcp.StartStdIO(ctx, sess, cli.server, rpcLog, watchRoots)\n\t}\n}\n\n// staticSessions implements the [internalmcp.Sessions] interface for a single gopls\n// session.\ntype staticSessions struct {\n\tsession *cache.Session\n\tserver  protocol.Server\n}\n\nfunc (s *staticSessions) SetSessionExitFunc(func(string)) {}\n\nfunc (s *staticSessions) FirstSession() (*cache.Session, protocol.Server) {\n\treturn s.session, s.server\n}\n\nfunc (s *staticSessions) Session(id string) (*cache.Session, protocol.Server) {\n\tif s.session.ID() == id {\n\t\treturn s.session, s.server\n\t}\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/mcp_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd_test\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\tgoplsmcp \"golang.org/x/tools/gopls/internal/mcp\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/vulntest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestMCPCommandStdio(t *testing.T) {\n\t// Test that the headless MCP subcommand works, and recognizes file changes.\n\tif !supportsFsnotify(runtime.GOOS) {\n\t\t// See golang/go#74580\n\t\tt.Skipf(\"skipping on %s; fsnotify is not supported\", runtime.GOOS)\n\t}\n\ttestenv.NeedsExec(t) // stdio transport uses execve(2)\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage p\n\nconst A = 1\n\n-- b.go --\npackage p\n\nconst B = 2\n`)\n\n\tgoplsCmd := exec.Command(os.Args[0], \"mcp\")\n\tgoplsCmd.Env = append(os.Environ(), \"ENTRYPOINT=goplsMain\")\n\tgoplsCmd.Dir = tree\n\tgoplsCmd.Stderr = t.Output() // to debug https://go.dev/issue/77334\n\n\tctx := t.Context()\n\tclient := mcp.NewClient(&mcp.Implementation{Name: \"client\", Version: \"v0.0.1\"}, nil)\n\tmcpSession, err := client.Connect(ctx, &mcp.CommandTransport{Command: goplsCmd}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := mcpSession.Close(); err != nil {\n\t\t\tt.Errorf(\"closing MCP connection: %v\", err)\n\t\t}\n\t}()\n\tvar (\n\t\ttool = \"go_diagnostics\"\n\t\targs = map[string]any{\"files\": []string{filepath.Join(tree, \"a.go\")}}\n\t)\n\t// On the first diagnostics call, there should be no diagnostics.\n\t{\n\t\t// Match on a substring of the expected output from the context tool.\n\t\tres, err := mcpSession.CallTool(ctx, &mcp.CallToolParams{Name: tool, Arguments: args})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgot := resultText(t, res)\n\t\twant := \"No diagnostics\"\n\t\tif !strings.Contains(got, want) {\n\t\t\tt.Errorf(\"CallTool(%s, %v) = %v, want containing %q\", tool, args, got, want)\n\t\t}\n\t}\n\t// Now, create a duplicate diagnostic in \"b.go\", and expect that the headless\n\t// MCP server detects the file change. In order to guarantee that the change\n\t// is detected, sleep long to ensure a different mtime.\n\ttime.Sleep(100 * time.Millisecond)\n\tnewContent := \"package p\\n\\nconst A = 2\\n\"\n\tif err := os.WriteFile(filepath.Join(tree, \"b.go\"), []byte(newContent), 0666); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t{\n\t\tres, err := mcpSession.CallTool(ctx, &mcp.CallToolParams{Name: tool, Arguments: args})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgot := resultText(t, res)\n\t\twant := \"redeclared\"\n\t\tif !strings.Contains(got, want) {\n\t\t\tt.Errorf(\"CallTool(%s, %v) = %v, want containing %q\", tool, args, got, want)\n\t\t}\n\t}\n}\n\nfunc TestMCPCommandLogging(t *testing.T) {\n\t// Test that logging flags for headless MCP subcommand work as intended.\n\tif !supportsFsnotify(runtime.GOOS) {\n\t\t// See golang/go#74580\n\t\tt.Skipf(\"skipping on %s; fsnotify is not supported\", runtime.GOOS)\n\t}\n\ttestenv.NeedsExec(t) // stdio transport uses execve(2)\n\n\ttests := []struct {\n\t\tlogFile  string // also the subtest name\n\t\ttrace    bool\n\t\twant     string\n\t\tdontWant string\n\t}{\n\t\t{\"notrace.log\", false, \"stdin\", \"initialized\"},\n\t\t{\"trace.log\", true, \"initialized\", \"\"},\n\t}\n\n\tdir := t.TempDir()\n\tfor _, test := range tests {\n\t\tt.Run(test.logFile, func(t *testing.T) {\n\t\t\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage p\n`)\n\n\t\t\tlogFile := filepath.Join(dir, test.logFile)\n\t\t\targs := []string{\"mcp\", \"-logfile\", logFile}\n\t\t\tif test.trace {\n\t\t\t\targs = append(args, \"-rpc.trace\")\n\t\t\t}\n\t\t\tgoplsCmd := exec.Command(os.Args[0], args...)\n\t\t\tgoplsCmd.Env = append(os.Environ(), \"ENTRYPOINT=goplsMain\")\n\t\t\tgoplsCmd.Dir = tree\n\t\t\tgoplsCmd.Stderr = t.Output() // to debug https://go.dev/issue/77334\n\n\t\t\tctx := t.Context()\n\t\t\tclient := mcp.NewClient(&mcp.Implementation{Name: \"client\", Version: \"v0.0.1\"}, nil)\n\t\t\tmcpSession, err := client.Connect(ctx, &mcp.CommandTransport{Command: goplsCmd}, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif err := mcpSession.Close(); err != nil {\n\t\t\t\tt.Errorf(\"closing MCP connection: %v\", err)\n\t\t\t}\n\t\t\tlogs, err := os.ReadFile(logFile)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif test.want != \"\" && !bytes.Contains(logs, []byte(test.want)) {\n\t\t\t\tt.Errorf(\"logs do not contain expected %q\", test.want)\n\t\t\t}\n\t\t\tif test.dontWant != \"\" && bytes.Contains(logs, []byte(test.dontWant)) {\n\t\t\t\tt.Errorf(\"logs contain unexpected %q\", test.dontWant)\n\t\t\t}\n\t\t\tif t.Failed() {\n\t\t\t\tt.Logf(\"Logs:\\n%s\", string(logs))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMCPCommandHTTP(t *testing.T) {\n\tif !supportsFsnotify(runtime.GOOS) {\n\t\t// See golang/go#74580\n\t\tt.Skipf(\"skipping on %s; fsnotify is not supported\", runtime.GOOS)\n\t}\n\ttestenv.NeedsExec(t)\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com\ngo 1.18\n-- a.go --\npackage a\n\nimport \"example.com/b\"\n\n-- b/b.go --\npackage b\n\nfunc MyFun() {}\n`)\n\tport := strconv.Itoa(getRandomPort())\n\taddr := \"localhost:\" + port\n\tgoplsCmd := exec.Command(os.Args[0], \"-v\", \"mcp\", \"-listen=\"+addr)\n\tgoplsCmd.Env = append(os.Environ(), \"ENTRYPOINT=goplsMain\")\n\tgoplsCmd.Dir = tree\n\tgoplsCmd.Stdout = os.Stderr\n\n\t// Pipe stderr to a scanner, so that we can wait for the log message that\n\t// tells us the server has started.\n\tstderr, err := goplsCmd.StderrPipe()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// forward stdout to test output\n\tif err := goplsCmd.Start(); err != nil {\n\t\tt.Fatalf(\"starting gopls: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := goplsCmd.Process.Kill(); err != nil {\n\t\t\tt.Fatalf(\"killing gopls: %v\", err)\n\t\t}\n\t\t// Wait for the gopls process to exit before we return and the test framework\n\t\t// attempts to clean up the temporary directory.\n\t\t// We expect an error because we killed the process.\n\t\tgoplsCmd.Wait()\n\t}()\n\n\t// Wait for the MCP server to start listening. The referenced log occurs\n\t// after the connection is opened via net.Listen and the HTTP handlers are\n\t// set up.\n\tready := make(chan bool)\n\tgo func() {\n\t\t// Copy from the pipe to stderr, keeping an eye out for the \"mcp http\n\t\t// server listening\" string.\n\t\tscan := bufio.NewScanner(stderr)\n\t\tfor scan.Scan() {\n\t\t\tline := scan.Text()\n\t\t\tif strings.Contains(line, \"mcp http server listening\") {\n\t\t\t\tready <- true\n\t\t\t}\n\t\t\tfmt.Fprintln(os.Stderr, line)\n\t\t}\n\t\tif err := scan.Err(); err != nil {\n\t\t\tt.Logf(\"reading from pipe: %v\", err)\n\t\t}\n\t}()\n\n\t<-ready\n\tclient := mcp.NewClient(&mcp.Implementation{Name: \"client\", Version: \"v0.0.1\"}, nil)\n\tctx := t.Context()\n\tmcpSession, err := client.Connect(ctx, &mcp.SSEClientTransport{Endpoint: \"http://\" + addr}, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"connecting to server: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := mcpSession.Close(); err != nil {\n\t\t\tt.Errorf(\"closing MCP connection: %v\", err)\n\t\t}\n\t}()\n\n\tvar (\n\t\ttool = \"go_file_context\"\n\t\targs = map[string]any{\"file\": filepath.Join(tree, \"a.go\")}\n\t)\n\tres, err := mcpSession.CallTool(ctx, &mcp.CallToolParams{Name: tool, Arguments: args})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := resultText(t, res)\n\twant := \"example.com\"\n\tif !strings.Contains(got, want) {\n\t\tt.Errorf(\"CallTool(%s, %v) = %+v, want containing %q\", tool, args, got, want)\n\t}\n}\n\nfunc TestMCPVulncheckCommand(t *testing.T) {\n\tif !supportsFsnotify(runtime.GOOS) {\n\t\t// See golang/go#74580\n\t\tt.Skipf(\"skipping on %s; fsnotify is not supported\", runtime.GOOS)\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\tconst proxyData = `\n-- example.com/vulnmod@v1.0.0/go.mod --\nmodule example.com/vulnmod\ngo 1.18\n-- example.com/vulnmod@v1.0.0/vuln.go --\npackage vulnmod\n\n// VulnFunc is a vulnerable function.\nfunc VulnFunc() {}\n`\n\tconst vulnData = `\n-- GO-TEST-0001.yaml --\nmodules:\n  - module: example.com/vulnmod\n    versions:\n      - introduced: \"1.0.0\"\n    packages:\n      - package: example.com/vulnmod\n        symbols:\n          - VulnFunc\n`\n\tproxyArchive := txtar.Parse([]byte(proxyData))\n\tproxyFiles := make(map[string][]byte)\n\tfor _, f := range proxyArchive.Files {\n\t\tproxyFiles[f.Name] = f.Data\n\t}\n\tgoproxy, err := fake.WriteProxy(t.TempDir(), proxyFiles)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdb, err := vulntest.NewDatabase(context.Background(), []byte(vulnData))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\n\ttree := writeTree(t, `\n-- go.mod --\nmodule example.com/user\ngo 1.18\nrequire example.com/vulnmod v1.0.0\n-- main.go --\npackage main\nimport \"example.com/vulnmod\"\nfunc main() {\n\tvulnmod.VulnFunc()\n}\n`)\n\n\t// Update go.sum before running gopls, to avoid load failures.\n\ttidyCmd := exec.CommandContext(t.Context(), \"go\", \"mod\", \"tidy\")\n\ttidyCmd.Dir = tree\n\ttidyCmd.Env = append(os.Environ(), \"GOPROXY=\"+goproxy, \"GOSUMDB=off\")\n\tif output, err := tidyCmd.CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"go mod tidy failed: %v\\n%s\", err, output)\n\t}\n\n\tgoplsCmd := exec.Command(os.Args[0], \"mcp\")\n\tgoplsCmd.Env = append(os.Environ(),\n\t\t\"ENTRYPOINT=goplsMain\",\n\t\t\"GOPROXY=\"+goproxy,\n\t\t\"GOSUMDB=off\",\n\t\t\"GOVULNDB=\"+db.URI(),\n\t)\n\tgoplsCmd.Dir = tree\n\tgoplsCmd.Stderr = t.Output() // to debug https://go.dev/issue/77334\n\n\tctx := t.Context()\n\tclient := mcp.NewClient(&mcp.Implementation{Name: \"client\", Version: \"v0.0.1\"}, nil)\n\tmcpSession, err := client.Connect(ctx, &mcp.CommandTransport{Command: goplsCmd}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := mcpSession.Close(); err != nil {\n\t\t\tt.Errorf(\"closing MCP connection: %v\", err)\n\t\t}\n\t}()\n\n\tres, err := mcpSession.CallTool(ctx, &mcp.CallToolParams{Name: \"go_vulncheck\", Arguments: map[string]any{}})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tjsonBytes, err := json.Marshal(res.StructuredContent)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar result goplsmcp.VulncheckResultOutput\n\tif err := json.Unmarshal(jsonBytes, &result); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(result.Findings) != 1 {\n\t\tt.Errorf(\"expected 1 finding, got %d\", len(result.Findings))\n\t} else {\n\t\tfinding := result.Findings[0]\n\t\tif finding.ID != \"GO-TEST-0001\" {\n\t\t\tt.Errorf(\"expected ID 'GO-TEST-0001', got %q\", finding.ID)\n\t\t}\n\t\texpectedPackages := []string{\"Go standard library\", \"example.com/vulnmod\"}\n\t\tif !slices.Equal(finding.AffectedPackages, expectedPackages) {\n\t\t\tt.Errorf(\"expected affected packages %v, got %v\", expectedPackages, finding.AffectedPackages)\n\t\t}\n\t}\n\n\tif result.Logs == \"\" {\n\t\tt.Errorf(\"expected logs to be non-empty\")\n\t} else {\n\t\tt.Logf(\"Logs:\\n%s\", result.Logs)\n\t}\n}\n\n// resultText concatenates the textual content of the given result, reporting\n// an error if any content values are non-textual.\nfunc resultText(t *testing.T, res *mcp.CallToolResult) string {\n\tt.Helper()\n\n\tvar buf bytes.Buffer\n\tfor _, content := range res.Content {\n\t\tif c, ok := content.(*mcp.TextContent); ok {\n\t\t\tfmt.Fprintf(&buf, \"%s\\n\", c.Text)\n\t\t} else {\n\t\t\tt.Errorf(\"Not text content: %T\", content)\n\t\t}\n\t}\n\treturn buf.String()\n}\n\n// getRandomPort returns the number of a random available port. Inherently racy:\n// nothing stops another process from listening on it - but this should be fine\n// for testing purposes.\nfunc getRandomPort() int {\n\tlistener, err := net.Listen(\"tcp\", \"localhost:0\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer listener.Close()\n\treturn listener.Addr().(*net.TCPAddr).Port\n}\n\n// supportsFsnotify returns true if fsnotify supports the os.\nfunc supportsFsnotify(os string) bool {\n\treturn os == \"darwin\" || os == \"linux\" || os == \"windows\"\n}\n"
  },
  {
    "path": "gopls/internal/cmd/parsespan.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// parseSpan returns the location represented by the input.\n// Only file paths are accepted, not URIs.\n// The returned span will be normalized, and thus if printed may produce a\n// different string.\nfunc parseSpan(input string) span {\n\turi := protocol.URIFromPath\n\n\t// :0:0#0-0:0#0\n\tvalid := input\n\tvar hold, offset int\n\thadCol := false\n\tsuf := rstripSuffix(input)\n\tif suf.sep == \"#\" {\n\t\toffset = suf.num\n\t\tsuf = rstripSuffix(suf.remains)\n\t}\n\tif suf.sep == \":\" {\n\t\tvalid = suf.remains\n\t\thold = suf.num\n\t\thadCol = true\n\t\tsuf = rstripSuffix(suf.remains)\n\t}\n\tswitch {\n\tcase suf.sep == \":\":\n\t\treturn newSpan(uri(suf.remains), newPoint(suf.num, hold, offset), point{})\n\tcase suf.sep == \"-\":\n\t\t// we have a span, fall out of the case to continue\n\tdefault:\n\t\t// separator not valid, rewind to either the : or the start\n\t\treturn newSpan(uri(valid), newPoint(hold, 0, offset), point{})\n\t}\n\t// only the span form can get here\n\t// at this point we still don't know what the numbers we have mean\n\t// if have not yet seen a : then we might have either a line or a column depending\n\t// on whether start has a column or not\n\t// we build an end point and will fix it later if needed\n\tend := newPoint(suf.num, hold, offset)\n\thold, offset = 0, 0\n\tsuf = rstripSuffix(suf.remains)\n\tif suf.sep == \"#\" {\n\t\toffset = suf.num\n\t\tsuf = rstripSuffix(suf.remains)\n\t}\n\tif suf.sep != \":\" {\n\t\t// turns out we don't have a span after all, rewind\n\t\treturn newSpan(uri(valid), end, point{})\n\t}\n\tvalid = suf.remains\n\thold = suf.num\n\tsuf = rstripSuffix(suf.remains)\n\tif suf.sep != \":\" {\n\t\t// line#offset only\n\t\treturn newSpan(uri(valid), newPoint(hold, 0, offset), end)\n\t}\n\t// we have a column, so if end only had one number, it is also the column\n\tif !hadCol {\n\t\tend = newPoint(suf.num, end.v.Line, end.v.Offset)\n\t}\n\treturn newSpan(uri(suf.remains), newPoint(suf.num, hold, offset), end)\n}\n\ntype suffix struct {\n\tremains string\n\tsep     string\n\tnum     int\n}\n\nfunc rstripSuffix(input string) suffix {\n\tif len(input) == 0 {\n\t\treturn suffix{\"\", \"\", -1}\n\t}\n\tremains := input\n\n\t// Remove optional trailing decimal number.\n\tnum := -1\n\tlast := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' })\n\tif last >= 0 && last < len(remains)-1 {\n\t\tnumber, err := strconv.ParseInt(remains[last+1:], 10, 64)\n\t\tif err == nil {\n\t\t\tnum = int(number)\n\t\t\tremains = remains[:last+1]\n\t\t}\n\t}\n\t// now see if we have a trailing separator\n\tr, w := utf8.DecodeLastRuneInString(remains)\n\t// TODO(adonovan): this condition is clearly wrong. Should the third byte be '-'?\n\tif r != ':' && r != '#' && r == '#' {\n\t\treturn suffix{input, \"\", -1}\n\t}\n\tremains = remains[:len(remains)-w]\n\treturn suffix{remains, string(r), num}\n}\n"
  },
  {
    "path": "gopls/internal/cmd/prepare_rename.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// prepareRename implements the prepare_rename verb for gopls.\ntype prepareRename struct {\n\tapp *Application\n}\n\nfunc (r *prepareRename) Name() string      { return \"prepare_rename\" }\nfunc (r *prepareRename) Parent() string    { return r.app.Name() }\nfunc (r *prepareRename) Usage() string     { return \"<position>\" }\nfunc (r *prepareRename) ShortHelp() string { return \"test validity of a rename operation at location\" }\nfunc (r *prepareRename) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls prepare_rename helper/helper.go:8:6\n\t$ gopls prepare_rename helper/helper.go:#53\n`)\n\tprintFlagDefaults(f)\n}\n\n// ErrInvalidRenamePosition is returned when prepareRename is run at a position that\n// is not a candidate for renaming.\nvar ErrInvalidRenamePosition = errors.New(\"request is not valid at the given position\")\n\nfunc (r *prepareRename) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"prepare_rename expects 1 argument (file)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp := protocol.PrepareRenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\tresult, err := cli.server.PrepareRename(ctx, &p)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"prepare_rename failed: %w\", err)\n\t}\n\tif result == nil {\n\t\treturn ErrInvalidRenamePosition\n\t}\n\n\ts, err := file.rangeSpan(result.Range)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Println(s)\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/references.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// references implements the references verb for gopls\ntype references struct {\n\tIncludeDeclaration bool `flag:\"d,declaration\" help:\"include the declaration of the specified identifier in the results\"`\n\n\tapp *Application\n}\n\nfunc (r *references) Name() string      { return \"references\" }\nfunc (r *references) Parent() string    { return r.app.Name() }\nfunc (r *references) Usage() string     { return \"[references-flags] <position>\" }\nfunc (r *references) ShortHelp() string { return \"display selected identifier's references\" }\nfunc (r *references) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls references helper/helper.go:8:6\n\t$ gopls references helper/helper.go:#53\n\nreferences-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *references) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"references expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp := protocol.ReferenceParams{\n\t\tContext: protocol.ReferenceContext{\n\t\t\tIncludeDeclaration: r.IncludeDeclaration,\n\t\t},\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\tlocations, err := cli.server.References(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar spans []string\n\tfor _, l := range locations {\n\t\tf, err := cli.openFile(ctx, l.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// convert location to span for user-friendly 1-indexed line\n\t\t// and column numbers\n\t\tspan, err := f.locationSpan(l)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tspans = append(spans, fmt.Sprint(span))\n\t}\n\n\tsort.Strings(spans)\n\tfor _, s := range spans {\n\t\tfmt.Println(s)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/remote.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n)\n\ntype remote struct {\n\tapp *Application\n\tsubcommands\n\n\t// For backward compatibility, allow aliasing this command (it was previously\n\t// called 'inspect').\n\t//\n\t// TODO(rFindley): delete this after allowing some transition time in case\n\t//                 there were any users of 'inspect' (I suspect not).\n\talias string\n}\n\nfunc newRemote(app *Application, alias string) *remote {\n\treturn &remote{\n\t\tapp: app,\n\t\tsubcommands: subcommands{\n\t\t\t&listSessions{app: app},\n\t\t\t&startDebugging{app: app},\n\t\t},\n\t\talias: alias,\n\t}\n}\n\nfunc (r *remote) Name() string {\n\tif r.alias != \"\" {\n\t\treturn r.alias\n\t}\n\treturn \"remote\"\n}\n\nfunc (r *remote) Parent() string { return r.app.Name() }\n\nfunc (r *remote) ShortHelp() string {\n\tshort := \"interact with the gopls daemon\"\n\tif r.alias != \"\" {\n\t\tshort += \" (deprecated: use 'remote')\"\n\t}\n\treturn short\n}\n\n// listSessions is an inspect subcommand to list current sessions.\ntype listSessions struct {\n\tapp *Application\n}\n\nfunc (c *listSessions) Name() string   { return \"sessions\" }\nfunc (c *listSessions) Parent() string { return c.app.Name() }\nfunc (c *listSessions) Usage() string  { return \"\" }\nfunc (c *listSessions) ShortHelp() string {\n\treturn \"print information about current gopls sessions\"\n}\n\nconst listSessionsExamples = `\nExamples:\n\n1) list sessions for the default daemon:\n\n$ gopls -remote=auto remote sessions\nor just\n$ gopls remote sessions\n\n2) list sessions for a specific daemon:\n\n$ gopls -remote=localhost:8082 remote sessions\n`\n\nfunc (c *listSessions) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), listSessionsExamples)\n\tprintFlagDefaults(f)\n}\n\nfunc (c *listSessions) Run(ctx context.Context, args ...string) error {\n\tremote := c.app.Remote\n\tif remote == \"\" {\n\t\tremote = \"auto\"\n\t}\n\tstate, err := lsprpc.QueryServerState(ctx, remote)\n\tif err != nil {\n\t\treturn err\n\t}\n\tv, err := json.MarshalIndent(state, \"\", \"\\t\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tos.Stdout.Write(v)\n\treturn nil\n}\n\ntype startDebugging struct {\n\tapp *Application\n}\n\nfunc (c *startDebugging) Name() string  { return \"debug\" }\nfunc (c *startDebugging) Usage() string { return \"[host:port]\" }\nfunc (c *startDebugging) ShortHelp() string {\n\treturn \"start the debug server\"\n}\n\nconst startDebuggingExamples = `\nExamples:\n\n1) start a debug server for the default daemon, on an arbitrary port:\n\n$ gopls -remote=auto remote debug\nor just\n$ gopls remote debug\n\n2) start for a specific daemon, on a specific port:\n\n$ gopls -remote=localhost:8082 remote debug localhost:8083\n`\n\nfunc (c *startDebugging) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), startDebuggingExamples)\n\tprintFlagDefaults(f)\n}\n\nfunc (c *startDebugging) Run(ctx context.Context, args ...string) error {\n\tif len(args) > 1 {\n\t\tfmt.Fprintln(os.Stderr, c.Usage())\n\t\treturn errors.New(\"invalid usage\")\n\t}\n\tremote := c.app.Remote\n\tif remote == \"\" {\n\t\tremote = \"auto\"\n\t}\n\tdebugAddr := \"\"\n\tif len(args) > 0 {\n\t\tdebugAddr = args[0]\n\t}\n\tdebugArgs := command.DebuggingArgs{\n\t\tAddr: debugAddr,\n\t}\n\tvar result command.DebuggingResult\n\tif err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.String(), debugArgs, &result); err != nil {\n\t\treturn err\n\t}\n\tif len(result.URLs) == 0 {\n\t\treturn errors.New(\"no debugging URLs\")\n\t}\n\tfor _, url := range result.URLs {\n\t\tfmt.Printf(\"debugging on %s\\n\", url)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/rename.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// rename implements the rename verb for gopls.\ntype rename struct {\n\tEditFlags\n\tapp *Application\n}\n\nfunc (r *rename) Name() string      { return \"rename\" }\nfunc (r *rename) Parent() string    { return r.app.Name() }\nfunc (r *rename) Usage() string     { return \"[rename-flags] <position> <name>\" }\nfunc (r *rename) ShortHelp() string { return \"rename selected identifier\" }\nfunc (r *rename) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-based location (:line:column or :#position) of the thing to change\n\t$ gopls rename helper/helper.go:8:6 Foo\n\t$ gopls rename helper/helper.go:#53 Foo\n\nrename-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run renames the specified identifier and either;\n// - if -w is specified, updates the file(s) in place;\n// - if -d is specified, prints out unified diffs of the changes; or\n// - otherwise, prints the new versions to stdout.\nfunc (r *rename) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 2 {\n\t\treturn tool.CommandLineErrorf(\"rename expects 2 arguments (position, new name)\")\n\t}\n\tr.app.editFlags = &r.EditFlags\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp := protocol.RenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\tNewName:                    args[1],\n\t}\n\tedit, err := cli.server.Rename(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn cli.applyWorkspaceEdit(edit)\n}\n"
  },
  {
    "path": "gopls/internal/cmd/semantictokens.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n)\n\n// generate semantic tokens and interpolate them in the file\n\n// The output is the input file decorated with comments showing the\n// syntactic tokens. The comments are stylized:\n//   /*<arrow><length>,<token type>,[<modifiers]*/\n// For most occurrences, the comment comes just before the token it\n// describes, and arrow is a right arrow. If the token is inside a string\n// the comment comes just after the string, and the arrow is a left arrow.\n// <length> is the length of the token in runes, <token type> is one\n// of the supported semantic token types, and <modifiers. is a\n// (possibly empty) list of token type modifiers.\n\n// There are 3 coordinate systems for lines and character offsets in lines\n// LSP (what's returned from semanticTokens()):\n//    0-based: the first line is line 0, the first character of a line\n//      is character 0, and characters are counted as UTF-16 code points\n// gopls (and Go error messages):\n//    1-based: the first line is line1, the first character of a line\n//      is character 0, and characters are counted as bytes\n// internal (as used in marks, and lines:=bytes.Split(buf, '\\n'))\n//    0-based: lines and character positions are 1 less than in\n//      the gopls coordinate system\n\ntype semanticToken struct {\n\tapp *Application\n}\n\nfunc (c *semanticToken) Name() string      { return \"semtok\" }\nfunc (c *semanticToken) Parent() string    { return c.app.Name() }\nfunc (c *semanticToken) Usage() string     { return \"<filename>\" }\nfunc (c *semanticToken) ShortHelp() string { return \"show semantic tokens for the specified file\" }\nfunc (c *semanticToken) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample: show the semantic tokens for this file:\n\n\t$ gopls semtok internal/cmd/semtok.go\n`)\n\tprintFlagDefaults(f)\n}\n\n// Run performs the semtok on the files specified by args and prints the\n// results to stdout in the format described above.\nfunc (c *semanticToken) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn fmt.Errorf(\"expected one file name, got %d\", len(args))\n\t}\n\t// perhaps simpler if app had just had a FlagSet member\n\torigOptions := c.app.options\n\tc.app.options = func(opts *settings.Options) {\n\t\tif origOptions != nil {\n\t\t\torigOptions(opts)\n\t\t}\n\t\topts.SemanticTokens = true\n\t}\n\tcli, _, err := c.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\turi := protocol.URIFromPath(args[0])\n\tfile, err := cli.openFile(ctx, uri)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlines := bytes.Split(file.mapper.Content, []byte{'\\n'})\n\tparams := &protocol.SemanticTokensRangeParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t\tRange: protocol.Range{Start: protocol.Position{Line: 0, Character: 0},\n\t\t\tEnd: protocol.Position{\n\t\t\t\tLine:      uint32(len(lines) - 1),\n\t\t\t\tCharacter: uint32(len(lines[len(lines)-1]))},\n\t\t},\n\t}\n\tresp, err := cli.server.SemanticTokensRange(ctx, params) // use Range to avoid limits on Full\n\tif err != nil {\n\t\treturn err\n\t}\n\tlegend := cli.initializeResult.Capabilities.SemanticTokensProvider.(protocol.SemanticTokensOptions).Legend\n\treturn decorate(legend, file, resp.Data)\n}\n\n// mark provides a human-readable representation of protocol.SemanticTokens.\n// It translates token types and modifiers to strings instead of uint32 values.\ntype mark struct {\n\tline, offset int // 1-based, from RangeSpan\n\tlen          int // bytes, not runes\n\ttyp          semtok.Type\n\tmods         []semtok.Modifier\n}\n\n// prefixes for semantic token comments\nconst (\n\tSemanticLeft  = \"/*⇐\"\n\tSemanticRight = \"/*⇒\"\n)\n\nfunc markLine(m mark, lines [][]byte) {\n\tl := lines[m.line-1] // mx is 1-based\n\tlength := utf8.RuneCount(l[m.offset-1 : m.offset-1+m.len])\n\tsplitAt := m.offset - 1\n\tinsert := \"\"\n\tif m.typ == \"namespace\" && m.offset-1+m.len < len(l) && l[m.offset-1+m.len] == '\"' {\n\t\t// it is the last component of an import spec\n\t\t// cannot put a comment inside a string\n\t\tinsert = fmt.Sprintf(\"%s%d,namespace,[]*/\", SemanticLeft, length)\n\t\tsplitAt = m.offset + m.len\n\t} else {\n\t\t// be careful not to generate //*\n\t\tspacer := \"\"\n\t\tif splitAt-1 >= 0 && l[splitAt-1] == '/' {\n\t\t\tspacer = \" \"\n\t\t}\n\t\tinsert = fmt.Sprintf(\"%s%s%d,%s,%v*/\", spacer, SemanticRight, length, m.typ, m.mods)\n\t}\n\tx := append([]byte(insert), l[splitAt:]...)\n\tl = append(l[:splitAt], x...)\n\tlines[m.line-1] = l\n}\n\n// decorate translates semantic token data (protocol.SemanticTokens) from its\n// raw []uint32 format into a human-readable representation and prints it to stdout.\nfunc decorate(legend protocol.SemanticTokensLegend, file *cmdFile, data []uint32) error {\n\tmarks := newMarks(legend, file, data)\n\tif len(marks) == 0 {\n\t\treturn nil\n\t}\n\tlines := bytes.Split(file.mapper.Content, []byte{'\\n'})\n\tfor i := len(marks) - 1; i >= 0; i-- {\n\t\tmx := marks[i]\n\t\tmarkLine(mx, lines)\n\t}\n\tos.Stdout.Write(bytes.Join(lines, []byte{'\\n'}))\n\treturn nil\n}\n\nfunc newMarks(legend protocol.SemanticTokensLegend, file *cmdFile, data []uint32) []mark {\n\tans := []mark{}\n\t// the following two loops could be merged, at the cost\n\t// of making the logic slightly more complicated to understand\n\t// first, convert from deltas to absolute, in LSP coordinates\n\tlspLine := make([]uint32, len(data)/5)\n\tlspChar := make([]uint32, len(data)/5)\n\tvar line, char uint32\n\tfor i := 0; 5*i < len(data); i++ {\n\t\tlspLine[i] = line + data[5*i+0]\n\t\tif data[5*i+0] > 0 {\n\t\t\tchar = 0\n\t\t}\n\t\tlspChar[i] = char + data[5*i+1]\n\t\tchar = lspChar[i]\n\t\tline = lspLine[i]\n\t}\n\t// second, convert to gopls coordinates\n\tfor i := 0; 5*i < len(data); i++ {\n\t\tpr := protocol.Range{\n\t\t\tStart: protocol.Position{\n\t\t\t\tLine:      lspLine[i],\n\t\t\t\tCharacter: lspChar[i],\n\t\t\t},\n\t\t\tEnd: protocol.Position{\n\t\t\t\tLine:      lspLine[i],\n\t\t\t\tCharacter: lspChar[i] + data[5*i+2],\n\t\t\t},\n\t\t}\n\t\tspn, err := file.rangeSpan(pr)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\n\t\tvar mods []semtok.Modifier\n\t\t{\n\t\t\tn := int(data[5*i+4])\n\t\t\tfor i, mod := range legend.TokenModifiers {\n\t\t\t\tif (n & (1 << i)) != 0 {\n\t\t\t\t\tmods = append(mods, semtok.Modifier(mod))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tm := mark{\n\t\t\tline:   spn.Start().Line(),\n\t\t\toffset: spn.Start().Column(),\n\t\t\tlen:    spn.End().Column() - spn.Start().Column(),\n\t\t\ttyp:    semtok.Type(legend.TokenTypes[data[5*i+3]]),\n\t\t\tmods:   mods,\n\t\t}\n\t\tans = append(ans, m)\n\t}\n\treturn ans\n}\n"
  },
  {
    "path": "gopls/internal/cmd/serve.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/gopls/internal/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/fakenet\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// Serve is a struct that exposes the configurable parts of the LSP and MCP\n// server as flags, in the right form for tool.Main to consume.\ntype Serve struct {\n\tLogfile     string        `flag:\"logfile\" help:\"filename to log to. if value is \\\"auto\\\", then logging to a default output file is enabled\"`\n\tMode        string        `flag:\"mode\" help:\"no effect\"`\n\tPort        int           `flag:\"port\" help:\"port on which to run gopls for debugging purposes\"`\n\tAddress     string        `flag:\"listen\" help:\"address on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.\"`\n\tIdleTimeout time.Duration `flag:\"listen.timeout\" help:\"when used with -listen, shut down the server when there are no connected clients for this duration\"`\n\tTrace       bool          `flag:\"rpc.trace\" help:\"print the full rpc trace in lsp inspector format\"`\n\tDebug       string        `flag:\"debug\" help:\"serve debug information on the supplied address\"`\n\n\tRemoteListenTimeout time.Duration `flag:\"remote.listen.timeout\" help:\"when used with -remote=auto, the -listen.timeout value used to start the daemon\"`\n\tRemoteDebug         string        `flag:\"remote.debug\" help:\"when used with -remote=auto, the -debug value used to start the daemon\"`\n\tRemoteLogfile       string        `flag:\"remote.logfile\" help:\"when used with -remote=auto, the -logfile value used to start the daemon\"`\n\n\t// MCP Server related configurations.\n\tMCPAddress string `flag:\"mcp.listen\" help:\"experimental: address on which to listen for model context protocol connections. If port is localhost:0, pick a random port in localhost instead.\"`\n\n\tapp *Application\n}\n\nfunc (s *Serve) Name() string   { return \"serve\" }\nfunc (s *Serve) Parent() string { return s.app.Name() }\nfunc (s *Serve) Usage() string  { return \"[server-flags]\" }\nfunc (s *Serve) ShortHelp() string {\n\treturn \"run a server for Go code using the Language Server Protocol\"\n}\nfunc (s *Serve) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `  gopls [flags] [server-flags]\n\nThe server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as\na child of an editor process.\n\nserver-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (s *Serve) remoteArgs(network, address string) []string {\n\targs := []string{\"serve\",\n\t\t\"-listen\", fmt.Sprintf(`%s;%s`, network, address),\n\t}\n\tif s.RemoteDebug != \"\" {\n\t\targs = append(args, \"-debug\", s.RemoteDebug)\n\t}\n\tif s.RemoteListenTimeout != 0 {\n\t\targs = append(args, \"-listen.timeout\", s.RemoteListenTimeout.String())\n\t}\n\tif s.RemoteLogfile != \"\" {\n\t\targs = append(args, \"-logfile\", s.RemoteLogfile)\n\t}\n\treturn args\n}\n\n// Run configures a server based on the flags, and then runs it.\n// It blocks until the server shuts down.\nfunc (s *Serve) Run(ctx context.Context, args ...string) error {\n\tif len(args) > 0 {\n\t\treturn tool.CommandLineErrorf(\"server does not take arguments, got %v\", args)\n\t}\n\n\tdi := debug.GetInstance(ctx)\n\tisDaemon := s.Address != \"\" || s.Port != 0\n\tif di != nil {\n\t\tcloseLog, err := di.SetLogFile(s.Logfile, isDaemon)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer closeLog()\n\t\tdi.ServerAddress = s.Address\n\t\tdi.Serve(ctx, s.Debug)\n\t}\n\n\tvar (\n\t\tss       jsonrpc2.StreamServer\n\t\tsessions mcp.Sessions // if non-nil, handle MCP sessions\n\t)\n\tif s.app.Remote != \"\" {\n\t\tvar err error\n\t\tss, err = lsprpc.NewForwarder(s.app.Remote, s.remoteArgs)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating forwarder: %w\", err)\n\t\t}\n\t} else {\n\t\tlsprpcServer := lsprpc.NewStreamServer(cache.New(nil), isDaemon, s.app.options)\n\t\tss = lsprpcServer\n\t\tif s.MCPAddress != \"\" {\n\t\t\tsessions = lsprpcServer\n\t\t}\n\t}\n\n\tgroup, ctx := errgroup.WithContext(ctx)\n\t// Indicate success by a special error so that successful termination\n\t// of one server causes cancellation of the other.\n\tsuccess := errors.New(\"success\")\n\n\t// Start MCP server.\n\tif sessions != nil {\n\t\tcountAttachedMCP.Inc()\n\t\tgroup.Go(func() (err error) {\n\t\t\tdefer func() {\n\t\t\t\tif err == nil {\n\t\t\t\t\terr = success\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\treturn mcp.Serve(ctx, s.MCPAddress, sessions, isDaemon, nil)\n\t\t})\n\t}\n\n\t// Start LSP server.\n\tgroup.Go(func() (err error) {\n\t\tdefer func() {\n\t\t\tif err == nil {\n\t\t\t\terr = success\n\t\t\t}\n\t\t}()\n\n\t\tvar network, addr string\n\t\tif s.Address != \"\" {\n\t\t\tnetwork, addr = lsprpc.ParseAddr(s.Address)\n\t\t}\n\t\tif s.Port != 0 {\n\t\t\tnetwork = \"tcp\"\n\t\t\t// TODO(adonovan): should gopls ever be listening on network\n\t\t\t// sockets, or only local ones?\n\t\t\t//\n\t\t\t// Ian says this was added in anticipation of\n\t\t\t// something related to \"VS Code remote\" that turned\n\t\t\t// out to be unnecessary. So I propose we limit it to\n\t\t\t// localhost, if only so that we avoid the macOS\n\t\t\t// firewall prompt.\n\t\t\t//\n\t\t\t// Hana says: \"s.Address is for the remote access (LSP)\n\t\t\t// and s.Port is for debugging purpose (according to\n\t\t\t// the Server type documentation). I am not sure why the\n\t\t\t// existing code here is mixing up and overwriting addr.\n\t\t\t// For debugging endpoint, I think localhost makes perfect sense.\"\n\t\t\t//\n\t\t\t// TODO(adonovan): disentangle Address and Port,\n\t\t\t// and use only localhost for the latter.\n\t\t\taddr = fmt.Sprintf(\":%v\", s.Port)\n\t\t}\n\n\t\tif addr != \"\" {\n\t\t\tlog.Printf(\"Gopls LSP daemon: listening on %s network, address %s...\", network, addr)\n\t\t\tdefer log.Printf(\"Gopls LSP daemon: exiting\")\n\t\t\treturn jsonrpc2.ListenAndServe(ctx, network, addr, ss, s.IdleTimeout)\n\t\t} else {\n\t\t\tstream := jsonrpc2.NewHeaderStream(fakenet.NewConn(\"stdio\", os.Stdin, os.Stdout))\n\t\t\tif s.Trace && di != nil {\n\t\t\t\tstream = protocol.LoggingStream(stream, di.LogWriter)\n\t\t\t}\n\t\t\tconn := jsonrpc2.NewConn(stream)\n\t\t\tif err := ss.ServeStream(ctx, conn); errors.Is(err, io.EOF) {\n\t\t\t\treturn nil\n\t\t\t} else {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t})\n\n\t// Wait for all servers to terminate, returning only the first error\n\t// encountered. Subsequent errors are typically due to context cancellation\n\t// and are disregarded.\n\tif err := group.Wait(); err != nil && !errors.Is(err, success) {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/signature.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// signature implements the signature verb for gopls\ntype signature struct {\n\tapp *Application\n}\n\nfunc (r *signature) Name() string      { return \"signature\" }\nfunc (r *signature) Parent() string    { return r.app.Name() }\nfunc (r *signature) Usage() string     { return \"<position>\" }\nfunc (r *signature) ShortHelp() string { return \"display selected identifier's signature\" }\nfunc (r *signature) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls signature helper/helper.go:8:6\n\t$ gopls signature helper/helper.go:#53\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *signature) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"signature expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tfile, err := cli.openFile(ctx, from.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tloc, err := file.spanLocation(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp := protocol.SignatureHelpParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\n\ts, err := cli.server.SignatureHelp(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif s == nil || len(s.Signatures) == 0 {\n\t\treturn tool.CommandLineErrorf(\"%v: not a function\", from)\n\t}\n\n\t// there is only ever one possible signature,\n\t// see toProtocolSignatureHelp in lsp/signature_help.go\n\tsignature := s.Signatures[0]\n\tfmt.Printf(\"%s\\n\", signature.Label)\n\tswitch x := signature.Documentation.Value.(type) {\n\tcase string:\n\t\tif x != \"\" {\n\t\t\tfmt.Printf(\"\\n%s\\n\", x)\n\t\t}\n\tcase protocol.MarkupContent:\n\t\tif x.Value != \"\" {\n\t\t\tfmt.Printf(\"\\n%s\\n\", x.Value)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/span.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\n// span and point represent positions and ranges in text files.\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"path\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// A span represents a range of text within a source file.  The start\n// and end points of a valid span may be hold either its byte offset,\n// or its (line, column) pair, or both.  Columns are measured in bytes.\n//\n// Spans are appropriate in user interfaces (e.g. command-line tools)\n// and tests where a position is notated without access to the content\n// of the file.\n//\n// Use protocol.Mapper to convert between span and other\n// representations, such as go/token (also UTF-8) or the LSP protocol\n// (UTF-16). The latter requires access to file contents.\n//\n// See overview comments at ../protocol/mapper.go.\ntype span struct {\n\tv _span\n}\n\n// point represents a single point within a file.\n// In general this should only be used as part of a span, as on its own it\n// does not carry enough information.\ntype point struct {\n\tv _point\n}\n\n// The span_/point_ types have public fields to support JSON encoding,\n// but the span/point types hide these fields by defining methods that\n// shadow them. (This is used by a few of the command-line tool\n// subcommands, which emit spans and have a -json flag.)\n//\n// TODO(adonovan): simplify now that it's all internal to cmd.\n\ntype _span struct {\n\tURI   protocol.DocumentURI `json:\"uri\"`\n\tStart _point               `json:\"start\"`\n\tEnd   _point               `json:\"end\"`\n}\n\ntype _point struct {\n\tLine   int `json:\"line\"`   // 1-based line number\n\tColumn int `json:\"column\"` // 1-based, UTF-8 codes (bytes)\n\tOffset int `json:\"offset\"` // 0-based byte offset\n}\n\nfunc newSpan(uri protocol.DocumentURI, start, end point) span {\n\ts := span{v: _span{URI: uri, Start: start.v, End: end.v}}\n\ts.v.clean()\n\treturn s\n}\n\nfunc newPoint(line, col, offset int) point {\n\tp := point{v: _point{Line: line, Column: col, Offset: offset}}\n\tp.v.clean()\n\treturn p\n}\n\n// sortSpans sorts spans into a stable but unspecified order.\nfunc sortSpans(spans []span) {\n\tsort.SliceStable(spans, func(i, j int) bool {\n\t\treturn compare(spans[i], spans[j]) < 0\n\t})\n}\n\n// compare implements a three-valued ordered comparison of Spans.\nfunc compare(a, b span) int {\n\t// This is a textual comparison. It does not perform path\n\t// cleaning, case folding, resolution of symbolic links,\n\t// testing for existence, or any I/O.\n\tif cmp := strings.Compare(string(a.URI()), string(b.URI())); cmp != 0 {\n\t\treturn cmp\n\t}\n\tif cmp := comparePoint(a.v.Start, b.v.Start); cmp != 0 {\n\t\treturn cmp\n\t}\n\treturn comparePoint(a.v.End, b.v.End)\n}\n\nfunc comparePoint(a, b _point) int {\n\tif !a.hasPosition() {\n\t\tif a.Offset < b.Offset {\n\t\t\treturn -1\n\t\t}\n\t\tif a.Offset > b.Offset {\n\t\t\treturn 1\n\t\t}\n\t\treturn 0\n\t}\n\tif a.Line < b.Line {\n\t\treturn -1\n\t}\n\tif a.Line > b.Line {\n\t\treturn 1\n\t}\n\tif a.Column < b.Column {\n\t\treturn -1\n\t}\n\tif a.Column > b.Column {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\nfunc (s span) HasPosition() bool             { return s.v.Start.hasPosition() }\nfunc (s span) HasOffset() bool               { return s.v.Start.hasOffset() }\nfunc (s span) IsValid() bool                 { return s.v.Start.isValid() }\nfunc (s span) IsPoint() bool                 { return s.v.Start == s.v.End }\nfunc (s span) URI() protocol.DocumentURI     { return s.v.URI }\nfunc (s span) Start() point                  { return point{s.v.Start} }\nfunc (s span) End() point                    { return point{s.v.End} }\nfunc (s *span) MarshalJSON() ([]byte, error) { return json.Marshal(&s.v) }\nfunc (s *span) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &s.v) }\n\nfunc (p point) HasPosition() bool             { return p.v.hasPosition() }\nfunc (p point) HasOffset() bool               { return p.v.hasOffset() }\nfunc (p point) IsValid() bool                 { return p.v.isValid() }\nfunc (p *point) MarshalJSON() ([]byte, error) { return json.Marshal(&p.v) }\nfunc (p *point) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &p.v) }\nfunc (p point) Line() int {\n\tif !p.v.hasPosition() {\n\t\tpanic(fmt.Errorf(\"position not set in %v\", p.v))\n\t}\n\treturn p.v.Line\n}\nfunc (p point) Column() int {\n\tif !p.v.hasPosition() {\n\t\tpanic(fmt.Errorf(\"position not set in %v\", p.v))\n\t}\n\treturn p.v.Column\n}\nfunc (p point) Offset() int {\n\tif !p.v.hasOffset() {\n\t\tpanic(fmt.Errorf(\"offset not set in %v\", p.v))\n\t}\n\treturn p.v.Offset\n}\n\nfunc (p _point) hasPosition() bool { return p.Line > 0 }\nfunc (p _point) hasOffset() bool   { return p.Offset >= 0 }\nfunc (p _point) isValid() bool     { return p.hasPosition() || p.hasOffset() }\nfunc (p _point) isZero() bool {\n\treturn (p.Line == 1 && p.Column == 1) || (!p.hasPosition() && p.Offset == 0)\n}\n\nfunc (s *_span) clean() {\n\t//this presumes the points are already clean\n\tif !s.End.isValid() || (s.End == _point{}) {\n\t\ts.End = s.Start\n\t}\n}\n\nfunc (p *_point) clean() {\n\tif p.Line < 0 {\n\t\tp.Line = 0\n\t}\n\tif p.Column <= 0 {\n\t\tif p.Line > 0 {\n\t\t\tp.Column = 1\n\t\t} else {\n\t\t\tp.Column = 0\n\t\t}\n\t}\n\tif p.Offset == 0 && (p.Line > 1 || p.Column > 1) {\n\t\tp.Offset = -1\n\t}\n}\n\n// Format implements fmt.Formatter to print the Location in a standard form.\n// The format produced is one that can be read back in using parseSpan.\n//\n// TODO(adonovan): this is esoteric, and the formatting options are\n// never used outside of TestFormat.\nfunc (s span) Format(f fmt.State, c rune) {\n\tfullForm := f.Flag('+')\n\tpreferOffset := f.Flag('#')\n\t// we should always have a uri, simplify if it is file format\n\t//TODO: make sure the end of the uri is unambiguous\n\turi := string(s.v.URI)\n\tif c == 'f' {\n\t\turi = path.Base(uri)\n\t} else if !fullForm {\n\t\turi = s.v.URI.Path()\n\t}\n\tfmt.Fprint(f, uri)\n\tif !s.IsValid() || (!fullForm && s.v.Start.isZero() && s.v.End.isZero()) {\n\t\treturn\n\t}\n\t// see which bits of start to write\n\tprintOffset := s.HasOffset() && (fullForm || preferOffset || !s.HasPosition())\n\tprintLine := s.HasPosition() && (fullForm || !printOffset)\n\tprintColumn := printLine && (fullForm || (s.v.Start.Column > 1 || s.v.End.Column > 1))\n\tfmt.Fprint(f, \":\")\n\tif printLine {\n\t\tfmt.Fprintf(f, \"%d\", s.v.Start.Line)\n\t}\n\tif printColumn {\n\t\tfmt.Fprintf(f, \":%d\", s.v.Start.Column)\n\t}\n\tif printOffset {\n\t\tfmt.Fprintf(f, \"#%d\", s.v.Start.Offset)\n\t}\n\t// start is written, do we need end?\n\tif s.IsPoint() {\n\t\treturn\n\t}\n\t// we don't print the line if it did not change\n\tprintLine = fullForm || (printLine && s.v.End.Line > s.v.Start.Line)\n\tfmt.Fprint(f, \"-\")\n\tif printLine {\n\t\tfmt.Fprintf(f, \"%d\", s.v.End.Line)\n\t}\n\tif printColumn {\n\t\tif printLine {\n\t\t\tfmt.Fprint(f, \":\")\n\t\t}\n\t\tfmt.Fprintf(f, \"%d\", s.v.End.Column)\n\t}\n\tif printOffset {\n\t\tfmt.Fprintf(f, \"#%d\", s.v.End.Offset)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/cmd/spanformat_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestSpanFormat(t *testing.T) {\n\tformats := []string{\"%v\", \"%#v\", \"%+v\"}\n\n\t// Element 0 is the input, and the elements 0-2 are the expected\n\t// output in [%v %#v %+v] formats. Thus the first must be in\n\t// canonical form (invariant under parseSpan + fmt.Sprint).\n\t// The '#' form displays offsets; the '+' form outputs a URI.\n\t// If len=4, element 0 is a noncanonical input and 1-3 are expected outputs.\n\tfor _, test := range [][]string{\n\t\t{\"C:/file_a\", \"C:/file_a\", \"file:///C:/file_a:#0\"},\n\t\t{\"C:/file_b:1:2\", \"C:/file_b:1:2\", \"file:///C:/file_b:1:2\"},\n\t\t{\"C:/file_c:1000\", \"C:/file_c:1000\", \"file:///C:/file_c:1000:1\"},\n\t\t{\"C:/file_d:14:9\", \"C:/file_d:14:9\", \"file:///C:/file_d:14:9\"},\n\t\t{\"C:/file_e:1:2-7\", \"C:/file_e:1:2-7\", \"file:///C:/file_e:1:2-1:7\"},\n\t\t{\"C:/file_f:500-502\", \"C:/file_f:500-502\", \"file:///C:/file_f:500:1-502:1\"},\n\t\t{\"C:/file_g:3:7-8\", \"C:/file_g:3:7-8\", \"file:///C:/file_g:3:7-3:8\"},\n\t\t{\"C:/file_h:3:7-4:8\", \"C:/file_h:3:7-4:8\", \"file:///C:/file_h:3:7-4:8\"},\n\t\t{\"C:/file_i:#100\", \"C:/file_i:#100\", \"file:///C:/file_i:#100\"},\n\t\t{\"C:/file_j:#26-#28\", \"C:/file_j:#26-#28\", \"file:///C:/file_j:#26-0#28\"}, // 0#28?\n\t\t{\"C:/file_h:3:7#26-4:8#37\", // not canonical\n\t\t\t\"C:/file_h:3:7-4:8\", \"C:/file_h:#26-#37\", \"file:///C:/file_h:3:7#26-4:8#37\"}} {\n\t\tinput := test[0]\n\t\tspn := parseSpan(input)\n\t\twants := test[0:3]\n\t\tif len(test) == 4 {\n\t\t\twants = test[1:4]\n\t\t}\n\t\tfor i, format := range formats {\n\t\t\twant := toPath(wants[i])\n\t\t\tif got := fmt.Sprintf(format, spn); got != want {\n\t\t\t\tt.Errorf(\"Sprintf(%q, %q) = %q, want %q\", format, input, got, want)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc toPath(value string) string {\n\tif strings.HasPrefix(value, \"file://\") {\n\t\treturn value\n\t}\n\treturn filepath.FromSlash(value)\n}\n"
  },
  {
    "path": "gopls/internal/cmd/stats.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\tbugpkg \"golang.org/x/tools/gopls/internal/util/bug\"\n\tversionpkg \"golang.org/x/tools/gopls/internal/version\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\ntype stats struct {\n\tapp *Application\n\n\tAnon bool `flag:\"anon\" help:\"hide any fields that may contain user names, file names, or source code\"`\n}\n\nfunc (s *stats) Name() string      { return \"stats\" }\nfunc (r *stats) Parent() string    { return r.app.Name() }\nfunc (s *stats) Usage() string     { return \"\" }\nfunc (s *stats) ShortHelp() string { return \"print workspace statistics\" }\n\nfunc (s *stats) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nLoad the workspace for the current directory, and output a JSON summary of\nworkspace information relevant to performance. As a side effect, this command\npopulates the gopls file cache for the current workspace.\n\nBy default, this command may include output that refers to the location or\ncontent of user code. When the -anon flag is set, fields that may refer to user\ncode are hidden.\n\nExample:\n  $ gopls stats -anon\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (s *stats) Run(ctx context.Context, args ...string) error {\n\tif s.app.Remote != \"\" {\n\t\t// stats does not work with -remote.\n\t\t// Other sessions on the daemon may interfere with results.\n\t\t// Additionally, the type assertions in below only work if progress\n\t\t// notifications bypass jsonrpc2 serialization.\n\t\treturn fmt.Errorf(\"the stats subcommand does not work with -remote\")\n\t}\n\n\tif !s.app.Verbose {\n\t\tevent.SetExporter(nil) // don't log errors to stderr\n\t}\n\n\tstats := GoplsStats{\n\t\tGOOS:             runtime.GOOS,\n\t\tGOARCH:           runtime.GOARCH,\n\t\tGOPLSCACHE:       os.Getenv(\"GOPLSCACHE\"),\n\t\tGoVersion:        runtime.Version(),\n\t\tGoplsVersion:     versionpkg.Version(),\n\t\tGOPACKAGESDRIVER: os.Getenv(\"GOPACKAGESDRIVER\"),\n\t}\n\n\topts := s.app.options\n\ts.app.options = func(o *settings.Options) {\n\t\tif opts != nil {\n\t\t\topts(o)\n\t\t}\n\t\to.VerboseWorkDoneProgress = true\n\t}\n\n\t// do executes a timed section of the stats command.\n\tdo := func(name string, f func() error) (time.Duration, error) {\n\t\tstart := time.Now()\n\t\tfmt.Fprintf(os.Stderr, \"%-30s\", name+\"...\")\n\t\tif err := f(); err != nil {\n\t\t\treturn time.Since(start), err\n\t\t}\n\t\td := time.Since(start)\n\t\tfmt.Fprintf(os.Stderr, \"done (%v)\\n\", d)\n\t\treturn d, nil\n\t}\n\n\tvar cli *client\n\tiwlDuration, err := do(\"Initializing workspace\", func() (err error) {\n\t\tcli, _, err = s.app.connect(ctx)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tselect {\n\t\tcase <-cli.iwlDone:\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tstats.InitialWorkspaceLoadDuration = fmt.Sprint(iwlDuration)\n\n\t// Gather bug reports produced by any process using\n\t// this executable and persisted in the cache.\n\tdo(\"Gathering bug reports\", func() error {\n\t\tstats.CacheDir, stats.BugReports = filecache.BugReports()\n\t\tif stats.BugReports == nil {\n\t\t\tstats.BugReports = []bugpkg.Bug{} // non-nil for JSON\n\t\t}\n\t\treturn nil\n\t})\n\n\tif _, err := do(\"Querying memstats\", func() error {\n\t\tmemStats, err := executeCommand(ctx, cli.server, &protocol.Command{\n\t\t\tCommand: command.MemStats.String(),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstats.MemStats = memStats.(command.MemStatsResult)\n\t\treturn nil\n\t}); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := do(\"Querying workspace stats\", func() error {\n\t\twsStats, err := executeCommand(ctx, cli.server, &protocol.Command{\n\t\t\tCommand: command.WorkspaceStats.String(),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstats.WorkspaceStats = wsStats.(command.WorkspaceStatsResult)\n\t\treturn nil\n\t}); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := do(\"Collecting directory info\", func() error {\n\t\tvar err error\n\t\tstats.DirStats, err = findDirStats()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn err\n\t}\n\n\t// Filter JSON output to fields that are consistent with s.Anon.\n\tokFields := make(map[string]any)\n\t{\n\t\tv := reflect.ValueOf(stats)\n\t\tt := v.Type()\n\t\tfor i := 0; i < t.NumField(); i++ {\n\t\t\tf := t.Field(i)\n\t\t\tif !token.IsExported(f.Name) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvf := v.FieldByName(f.Name)\n\t\t\tif s.Anon && f.Tag.Get(\"anon\") != \"ok\" && !vf.IsZero() {\n\t\t\t\t// Fields that can be served with -anon must be explicitly marked as OK.\n\t\t\t\t// But, if it's zero value, it's ok to print.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tokFields[f.Name] = vf.Interface()\n\t\t}\n\t}\n\tdata, err := json.MarshalIndent(okFields, \"\", \"  \")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tos.Stdout.Write(data)\n\tfmt.Println()\n\treturn nil\n}\n\n// GoplsStats holds information extracted from a gopls session in the current\n// workspace.\n//\n// Fields that should be printed with the -anon flag should be explicitly\n// marked as `anon:\"ok\"`. Only fields that cannot refer to user files or code\n// should be marked as such.\ntype GoplsStats struct {\n\tGOOS, GOARCH                 string `anon:\"ok\"`\n\tGOPLSCACHE                   string\n\tGoVersion                    string `anon:\"ok\"`\n\tGoplsVersion                 string `anon:\"ok\"`\n\tGOPACKAGESDRIVER             string\n\tInitialWorkspaceLoadDuration string `anon:\"ok\"` // in time.Duration string form\n\tCacheDir                     string\n\tBugReports                   []bugpkg.Bug\n\tMemStats                     command.MemStatsResult       `anon:\"ok\"`\n\tWorkspaceStats               command.WorkspaceStatsResult `anon:\"ok\"`\n\tDirStats                     dirStats                     `anon:\"ok\"`\n}\n\ntype dirStats struct {\n\tFiles         int\n\tTestdataFiles int\n\tGoFiles       int\n\tModFiles      int\n\tDirs          int\n}\n\n// findDirStats collects information about the current directory and its\n// subdirectories.\nfunc findDirStats() (dirStats, error) {\n\tvar ds dirStats\n\terr := filepath.WalkDir(\".\", func(path string, d fs.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif d.IsDir() {\n\t\t\tds.Dirs++\n\t\t} else {\n\t\t\tds.Files++\n\t\t\tslashed := filepath.ToSlash(path)\n\t\t\tswitch {\n\t\t\tcase strings.Contains(slashed, \"/testdata/\") || strings.HasPrefix(slashed, \"testdata/\"):\n\t\t\t\tds.TestdataFiles++\n\t\t\tcase strings.HasSuffix(path, \".go\"):\n\t\t\t\tds.GoFiles++\n\t\t\tcase strings.HasSuffix(path, \".mod\"):\n\t\t\t\tds.ModFiles++\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\treturn ds, err\n}\n"
  },
  {
    "path": "gopls/internal/cmd/subcommands.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"text/tabwriter\"\n\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// subcommands is a helper that may be embedded for commands that delegate to\n// subcommands.\ntype subcommands []tool.Application\n\nfunc (s subcommands) DetailedHelp(f *flag.FlagSet) {\n\tw := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0)\n\tdefer w.Flush()\n\tfmt.Fprint(w, \"\\nSubcommand:\\n\")\n\tfor _, c := range s {\n\t\tfmt.Fprintf(w, \"  %s\\t%s\\n\", c.Name(), c.ShortHelp())\n\t}\n\tprintFlagDefaults(f)\n}\n\nfunc (s subcommands) Usage() string { return \"<subcommand> [arg]...\" }\n\nfunc (s subcommands) Run(ctx context.Context, args ...string) error {\n\tif len(args) == 0 {\n\t\treturn tool.CommandLineErrorf(\"must provide subcommand\")\n\t}\n\tcommand, args := args[0], args[1:]\n\tfor _, c := range s {\n\t\tif c.Name() == command {\n\t\t\ts := flag.NewFlagSet(c.Name(), flag.ExitOnError)\n\t\t\treturn tool.Run(ctx, s, c, args)\n\t\t}\n\t}\n\treturn tool.CommandLineErrorf(\"unknown subcommand %v\", command)\n}\n\nfunc (s subcommands) Commands() []tool.Application { return s }\n\n// getSubcommands returns the subcommands of a given Application.\nfunc getSubcommands(a tool.Application) []tool.Application {\n\t// This interface is satisfied both by tool.Applications\n\t// that embed subcommands, and by *cmd.Application.\n\ttype hasCommands interface {\n\t\tCommands() []tool.Application\n\t}\n\tif sub, ok := a.(hasCommands); ok {\n\t\treturn sub.Commands()\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/symbols.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// symbols implements the symbols verb for gopls\ntype symbols struct {\n\tapp *Application\n}\n\nfunc (r *symbols) Name() string      { return \"symbols\" }\nfunc (r *symbols) Parent() string    { return r.app.Name() }\nfunc (r *symbols) Usage() string     { return \"<file>\" }\nfunc (r *symbols) ShortHelp() string { return \"display selected file's symbols\" }\nfunc (r *symbols) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\t$ gopls symbols helper/helper.go\n`)\n\tprintFlagDefaults(f)\n}\nfunc (r *symbols) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"symbols expects 1 argument (position)\")\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tfrom := parseSpan(args[0])\n\tp := protocol.DocumentSymbolParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: from.URI(),\n\t\t},\n\t}\n\tsymbols, err := cli.server.DocumentSymbol(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, s := range symbols {\n\t\tif m, ok := s.(map[string]any); ok {\n\t\t\ts, err = mapToSymbol(m)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tswitch t := s.(type) {\n\t\tcase protocol.DocumentSymbol:\n\t\t\tprintDocumentSymbol(t)\n\t\tcase protocol.SymbolInformation:\n\t\t\tprintSymbolInformation(t)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc mapToSymbol(m map[string]any) (any, error) {\n\tb, err := json.Marshal(m)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif _, ok := m[\"selectionRange\"]; ok {\n\t\tvar s protocol.DocumentSymbol\n\t\tif err := json.Unmarshal(b, &s); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s, nil\n\t}\n\n\tvar s protocol.SymbolInformation\n\tif err := json.Unmarshal(b, &s); err != nil {\n\t\treturn nil, err\n\t}\n\treturn s, nil\n}\n\nfunc printDocumentSymbol(s protocol.DocumentSymbol) {\n\tfmt.Printf(\"%s %s %s\\n\", s.Name, s.Kind, positionToString(s.SelectionRange))\n\t// Sort children for consistency\n\tsort.Slice(s.Children, func(i, j int) bool {\n\t\treturn s.Children[i].Name < s.Children[j].Name\n\t})\n\tfor _, c := range s.Children {\n\t\tfmt.Printf(\"\\t%s %s %s\\n\", c.Name, c.Kind, positionToString(c.SelectionRange))\n\t}\n}\n\nfunc printSymbolInformation(s protocol.SymbolInformation) {\n\tfmt.Printf(\"%s %s %s\\n\", s.Name, s.Kind, positionToString(s.Location.Range))\n}\n\nfunc positionToString(r protocol.Range) string {\n\treturn fmt.Sprintf(\"%v:%v-%v:%v\",\n\t\tr.Start.Line+1,\n\t\tr.Start.Character+1,\n\t\tr.End.Line+1,\n\t\tr.End.Character+1,\n\t)\n}\n"
  },
  {
    "path": "gopls/internal/cmd/usage/api-json.hlp",
    "content": "print JSON describing gopls API\n\nUsage:\n  gopls [flags] api-json\n\nThe api-json command prints a JSON value that describes\nand documents all gopls' public interfaces.\nIts schema is defined by golang.org/x/tools/gopls/internal/doc.API.\n"
  },
  {
    "path": "gopls/internal/cmd/usage/bug.hlp",
    "content": "report a bug in gopls\n\nUsage:\n  gopls [flags] bug\n"
  },
  {
    "path": "gopls/internal/cmd/usage/call_hierarchy.hlp",
    "content": "display selected identifier's call hierarchy\n\nUsage:\n  gopls [flags] call_hierarchy <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls call_hierarchy helper/helper.go:8:6\n\t$ gopls call_hierarchy helper/helper.go:#53\n"
  },
  {
    "path": "gopls/internal/cmd/usage/check.hlp",
    "content": "show diagnostic results for the specified file\n\nUsage:\n  gopls [flags] check <filename>\n\nExample: show the diagnostic results of this file:\n\n\t$ gopls check internal/cmd/check.go\n  -severity=string\n    \tminimum diagnostic severity (hint, info, warning, or error) (default \"warning\")\n"
  },
  {
    "path": "gopls/internal/cmd/usage/codeaction.hlp",
    "content": "list or execute code actions\n\nUsage:\n  gopls [flags] codeaction [codeaction-flags] filename[:line[:col]]\n\n\nThe codeaction command lists or executes code actions for the\nspecified file or range of a file. Each code action contains\neither an edit to be directly applied to the file, or a command\nto be executed by the server, which may have an effect such as:\n- requesting that the client apply an edit;\n- changing the state of the server; or\n- requesting that the client open a document.\n\nThe -kind and and -title flags filter the list of actions.\n\nThe -kind flag specifies a comma-separated list of LSP CodeAction kinds.\nOnly actions of these kinds will be requested from the server.\nValid kinds include:\n\n\tgopls.doc.features\n\tquickfix\n\trefactor\n\trefactor.extract\n\trefactor.extract.constant\n\trefactor.extract.function\n\trefactor.extract.method\n\trefactor.extract.toNewFile\n\trefactor.extract.variable\n\trefactor.inline\n\trefactor.inline.call\n\trefactor.rewrite\n\trefactor.rewrite.changeQuote\n\trefactor.rewrite.fillStruct\n\trefactor.rewrite.fillSwitch\n\trefactor.rewrite.invertIf\n\trefactor.rewrite.joinLines\n\trefactor.rewrite.removeUnusedParam\n\trefactor.rewrite.splitLines\n\tsource\n\tsource.assembly\n\tsource.doc\n\tsource.fixAll\n\tsource.freesymbols\n\tsource.organizeImports\n\tsource.test\n\nKinds are hierarchical, so \"refactor\" includes \"refactor.inline\".\n(Note: actions of kind \"source.test\" are not returned unless explicitly\nrequested.)\n\nThe -title flag specifies a regular expression that must match the\naction's title. (Ideally kinds would be specific enough that this\nisn't necessary; we really need to subdivide refactor.rewrite; see\ngopls/internal/settings/codeactionkind.go.)\n\nThe -exec flag causes the first matching code action to be executed.\nWithout the flag, the matching actions are merely listed.\n\nIt is not currently possible to execute more than one action,\nas that requires a way to detect and resolve conflicts.\nTODO(adonovan): support it when golang/go#67049 is resolved.\n\nIf executing an action causes the server to send a patch to the\nclient, the usual -write, -preserve, -diff, and -list flags govern how\nthe client deals with the patch.\n\nExample: execute the first \"quick fix\" in the specified file and show the diff:\n\n\t$ gopls codeaction -kind=quickfix -exec -diff ./gopls/main.go\n\ncodeaction-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -exec\n    \texecute the first matching code action\n  -kind=string\n    \tcomma-separated list of code action kinds to filter\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -title=string\n    \tregular expression to match title\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/codelens.hlp",
    "content": "List or execute code lenses for a file\n\nUsage:\n  gopls [flags] codelens [codelens-flags] file[:line[:col]] [title]\n\nThe codelens command lists or executes code lenses for the specified\nfile, or line within a file. A code lens is a command associated with\na position in the code.\n\nWith an optional title argument, only code lenses matching that\ntitle are considered.\n\nBy default, the codelens command lists the available lenses for the\nspecified file or line within a file, including the title and\ntitle of the command. With the -exec flag, the first matching command\nis executed, and its output is printed to stdout.\n\nExample:\n\n\t$ gopls codelens a_test.go                     # list code lenses in a file\n\t$ gopls codelens a_test.go:10                  # list code lenses on line 10\n\t$ gopls codelens a_test.go \"run test\"          # list gopls.run_tests commands\n\t$ gopls codelens -exec a_test.go:10 \"run test\" # run a specific test\n\ncodelens-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -exec\n    \texecute the first matching code lens\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/definition.hlp",
    "content": "show declaration of selected identifier\n\nUsage:\n  gopls [flags] definition [definition-flags] <position>\n\nExample: show the definition of the identifier at syntax at offset 44 in this file (flag.FlagSet):\n\n\t$ gopls definition internal/cmd/definition.go:44:47\n\t$ gopls definition internal/cmd/definition.go:#1270\n\ndefinition-flags:\n  -json\n    \temit output in JSON format\n  -markdown\n    \tsupport markdown in responses\n"
  },
  {
    "path": "gopls/internal/cmd/usage/execute.hlp",
    "content": "Execute a gopls custom LSP command\n\nUsage:\n  gopls [flags] execute [flags] command argument...\n\nThe execute command sends an LSP ExecuteCommand request to gopls,\nwith a set of optional JSON argument values.\nSome commands return a result, also JSON.\n\nGopls' command set is defined by the command.Interface type; see\nhttps://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol/command#Interface.\nIt is not a stable interface: commands may change or disappear without notice.\n\nExamples:\n\n\t$ gopls execute gopls.add_import '{\"ImportPath\": \"fmt\", \"URI\": \"file:///hello.go\"}'\n\t$ gopls execute gopls.run_tests '{\"URI\": \"file:///a_test.go\", \"Tests\": [\"Test\"]}'\n\t$ gopls execute gopls.list_known_packages '{\"URI\": \"file:///hello.go\"}'\n\nexecute-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/fix.hlp",
    "content": "apply suggested fixes (obsolete)\n\nUsage:\n  gopls [flags] fix\nNo longer supported; use \"gopls codeaction\" instead."
  },
  {
    "path": "gopls/internal/cmd/usage/folding_ranges.hlp",
    "content": "display selected file's folding ranges\n\nUsage:\n  gopls [flags] folding_ranges <file>\n\nExample:\n\n\t$ gopls folding_ranges helper/helper.go\n"
  },
  {
    "path": "gopls/internal/cmd/usage/format.hlp",
    "content": "format the code according to the go standard\n\nUsage:\n  gopls [flags] format [format-flags] <filerange>\n\nThe arguments supplied may be simple file names, or ranges within files.\n\nExample: reformat this file:\n\n\t$ gopls format -w internal/cmd/check.go\n\nformat-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/help.hlp",
    "content": "print usage information for subcommands\n\nUsage:\n  gopls [flags] help\n\n\nExamples:\n$ gopls help                         # main gopls help message\n$ gopls help remote                  # help on 'remote' command\n$ gopls help remote sessions         # help on 'remote sessions' subcommand\n"
  },
  {
    "path": "gopls/internal/cmd/usage/highlight.hlp",
    "content": "display selected identifier's highlights\n\nUsage:\n  gopls [flags] highlight <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls highlight helper/helper.go:8:6\n\t$ gopls highlight helper/helper.go:#53\n"
  },
  {
    "path": "gopls/internal/cmd/usage/implementation.hlp",
    "content": "display selected identifier's implementation\n\nUsage:\n  gopls [flags] implementation <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls implementation helper/helper.go:8:6\n\t$ gopls implementation helper/helper.go:#53\n"
  },
  {
    "path": "gopls/internal/cmd/usage/imports.hlp",
    "content": "updates import statements\n\nUsage:\n  gopls [flags] imports [imports-flags] <filename>\n\nExample: update imports statements in a file:\n\n\t$ gopls imports -w internal/cmd/check.go\n\nimports-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/inspect.hlp",
    "content": "interact with the gopls daemon (deprecated: use 'remote')\n\nUsage:\n  gopls [flags] inspect <subcommand> [arg]...\n\nSubcommand:\n  sessions  print information about current gopls sessions\n  debug     start the debug server\n"
  },
  {
    "path": "gopls/internal/cmd/usage/licenses.hlp",
    "content": "print licenses of included software\n\nUsage:\n  gopls [flags] licenses\n"
  },
  {
    "path": "gopls/internal/cmd/usage/links.hlp",
    "content": "list links in a file\n\nUsage:\n  gopls [flags] links [links-flags] <filename>\n\nExample: list links contained within a file:\n\n\t$ gopls links internal/cmd/check.go\n\nlinks-flags:\n  -json\n    \temit document links in JSON format\n"
  },
  {
    "path": "gopls/internal/cmd/usage/mcp.hlp",
    "content": "start the gopls MCP server in headless mode\n\nUsage:\n  gopls [flags] mcp [mcp-flags]\n\nStarts the gopls MCP server in headless mode, without needing an LSP client.\nStarts the server over stdio or sse with http, depending on whether the listen flag is provided.\n\nExamples:\n  $ gopls mcp -listen=localhost:3000\n  $ gopls mcp  //start over stdio\n  -instructions\n    \tif set, print gopls' MCP instructions and exit\n  -listen=string\n    \tthe address on which to run the mcp server\n  -logfile=string\n    \tfilename to log to; if unset, logs to stderr\n  -rpc.trace\n    \tprint MCP rpc traces; cannot be used with -listen\n"
  },
  {
    "path": "gopls/internal/cmd/usage/prepare_rename.hlp",
    "content": "test validity of a rename operation at location\n\nUsage:\n  gopls [flags] prepare_rename <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls prepare_rename helper/helper.go:8:6\n\t$ gopls prepare_rename helper/helper.go:#53\n"
  },
  {
    "path": "gopls/internal/cmd/usage/references.hlp",
    "content": "display selected identifier's references\n\nUsage:\n  gopls [flags] references [references-flags] <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls references helper/helper.go:8:6\n\t$ gopls references helper/helper.go:#53\n\nreferences-flags:\n  -d,-declaration\n    \tinclude the declaration of the specified identifier in the results\n"
  },
  {
    "path": "gopls/internal/cmd/usage/remote.hlp",
    "content": "interact with the gopls daemon\n\nUsage:\n  gopls [flags] remote <subcommand> [arg]...\n\nSubcommand:\n  sessions  print information about current gopls sessions\n  debug     start the debug server\n"
  },
  {
    "path": "gopls/internal/cmd/usage/rename.hlp",
    "content": "rename selected identifier\n\nUsage:\n  gopls [flags] rename [rename-flags] <position> <name>\n\nExample:\n\n\t$ # 1-based location (:line:column or :#position) of the thing to change\n\t$ gopls rename helper/helper.go:8:6 Foo\n\t$ gopls rename helper/helper.go:#53 Foo\n\nrename-flags:\n  -d,-diff\n    \tdisplay diffs instead of edited file content\n  -l,-list\n    \tdisplay names of edited files\n  -preserve\n    \twith -write, make copies of original files\n  -w,-write\n    \twrite edited content to source files\n"
  },
  {
    "path": "gopls/internal/cmd/usage/semtok.hlp",
    "content": "show semantic tokens for the specified file\n\nUsage:\n  gopls [flags] semtok <filename>\n\nExample: show the semantic tokens for this file:\n\n\t$ gopls semtok internal/cmd/semtok.go\n"
  },
  {
    "path": "gopls/internal/cmd/usage/serve.hlp",
    "content": "run a server for Go code using the Language Server Protocol\n\nUsage:\n  gopls [flags] serve [server-flags]\n  gopls [flags] [server-flags]\n\nThe server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as\na child of an editor process.\n\nserver-flags:\n  -debug=string\n    \tserve debug information on the supplied address\n  -listen=string\n    \taddress on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.\n  -listen.timeout=duration\n    \twhen used with -listen, shut down the server when there are no connected clients for this duration\n  -logfile=string\n    \tfilename to log to. if value is \"auto\", then logging to a default output file is enabled\n  -mcp.listen=string\n    \texperimental: address on which to listen for model context protocol connections. If port is localhost:0, pick a random port in localhost instead.\n  -mode=string\n    \tno effect\n  -port=int\n    \tport on which to run gopls for debugging purposes\n  -remote.debug=string\n    \twhen used with -remote=auto, the -debug value used to start the daemon\n  -remote.listen.timeout=duration\n    \twhen used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)\n  -remote.logfile=string\n    \twhen used with -remote=auto, the -logfile value used to start the daemon\n  -rpc.trace\n    \tprint the full rpc trace in lsp inspector format\n"
  },
  {
    "path": "gopls/internal/cmd/usage/signature.hlp",
    "content": "display selected identifier's signature\n\nUsage:\n  gopls [flags] signature <position>\n\nExample:\n\n\t$ # 1-indexed location (:line:column or :#offset) of the target identifier\n\t$ gopls signature helper/helper.go:8:6\n\t$ gopls signature helper/helper.go:#53\n"
  },
  {
    "path": "gopls/internal/cmd/usage/stats.hlp",
    "content": "print workspace statistics\n\nUsage:\n  gopls [flags] stats\n\nLoad the workspace for the current directory, and output a JSON summary of\nworkspace information relevant to performance. As a side effect, this command\npopulates the gopls file cache for the current workspace.\n\nBy default, this command may include output that refers to the location or\ncontent of user code. When the -anon flag is set, fields that may refer to user\ncode are hidden.\n\nExample:\n  $ gopls stats -anon\n  -anon\n    \thide any fields that may contain user names, file names, or source code\n"
  },
  {
    "path": "gopls/internal/cmd/usage/symbols.hlp",
    "content": "display selected file's symbols\n\nUsage:\n  gopls [flags] symbols <file>\n\nExample:\n\t$ gopls symbols helper/helper.go\n"
  },
  {
    "path": "gopls/internal/cmd/usage/usage-v.hlp",
    "content": "\ngopls is a Go language server.\n\nIt is typically used with an editor to provide language features. When no\ncommand is specified, gopls will default to the 'serve' command. The language\nfeatures can also be accessed via the gopls command-line interface.\n\nFor documentation of all its features, see:\n\n   https://github.com/golang/tools/blob/master/gopls/doc/features\n\nUsage:\n  gopls help [<subject>]\n\nCommand:\n\nMain                \n  serve             run a server for Go code using the Language Server Protocol\n  version           print the gopls version information\n  bug               report a bug in gopls\n  help              print usage information for subcommands\n  api-json          print JSON describing gopls API\n  licenses          print licenses of included software\n                    \nFeatures            \n  call_hierarchy    display selected identifier's call hierarchy\n  check             show diagnostic results for the specified file\n  codeaction        list or execute code actions\n  codelens          List or execute code lenses for a file\n  definition        show declaration of selected identifier\n  execute           Execute a gopls custom LSP command\n  fix               apply suggested fixes (obsolete)\n  folding_ranges    display selected file's folding ranges\n  format            format the code according to the go standard\n  mcp               start the gopls MCP server in headless mode\n  highlight         display selected identifier's highlights\n  implementation    display selected identifier's implementation\n  imports           updates import statements\n  remote            interact with the gopls daemon\n  inspect           interact with the gopls daemon (deprecated: use 'remote')\n  links             list links in a file\n  prepare_rename    test validity of a rename operation at location\n  references        display selected identifier's references\n  rename            rename selected identifier\n  semtok            show semantic tokens for the specified file\n  signature         display selected identifier's signature\n  stats             print workspace statistics\n  symbols           display selected file's symbols\n  workspace_symbol  search symbols in workspace\n                    \nInternal Use Only   \n  vulncheck         run vulncheck analysis (internal-use only)\n\nflags:\n  -debug=string\n    \tserve debug information on the supplied address\n  -listen=string\n    \taddress on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.\n  -listen.timeout=duration\n    \twhen used with -listen, shut down the server when there are no connected clients for this duration\n  -logfile=string\n    \tfilename to log to. if value is \"auto\", then logging to a default output file is enabled\n  -mcp.listen=string\n    \texperimental: address on which to listen for model context protocol connections. If port is localhost:0, pick a random port in localhost instead.\n  -mode=string\n    \tno effect\n  -otel=string\n    \texport telemetry to specified OpenTelemetry collector address (e.g. http://localhost:4318)\n  -port=int\n    \tport on which to run gopls for debugging purposes\n  -profile.alloc=string\n    \twrite alloc profile to this file\n  -profile.block=string\n    \twrite block profile to this file\n  -profile.cpu=string\n    \twrite CPU profile to this file\n  -profile.mem=string\n    \twrite memory profile to this file\n  -profile.trace=string\n    \twrite trace log to this file\n  -remote=string\n    \tforward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment.\n  -remote.debug=string\n    \twhen used with -remote=auto, the -debug value used to start the daemon\n  -remote.listen.timeout=duration\n    \twhen used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)\n  -remote.logfile=string\n    \twhen used with -remote=auto, the -logfile value used to start the daemon\n  -rpc.trace\n    \tprint the full rpc trace in lsp inspector format\n  -v,-verbose\n    \tverbose output\n  -vv,-veryverbose\n    \tvery verbose output\n"
  },
  {
    "path": "gopls/internal/cmd/usage/usage.hlp",
    "content": "\ngopls is a Go language server.\n\nIt is typically used with an editor to provide language features. When no\ncommand is specified, gopls will default to the 'serve' command. The language\nfeatures can also be accessed via the gopls command-line interface.\n\nFor documentation of all its features, see:\n\n   https://github.com/golang/tools/blob/master/gopls/doc/features\n\nUsage:\n  gopls help [<subject>]\n\nCommand:\n\nMain                \n  serve             run a server for Go code using the Language Server Protocol\n  version           print the gopls version information\n  bug               report a bug in gopls\n  help              print usage information for subcommands\n  api-json          print JSON describing gopls API\n  licenses          print licenses of included software\n                    \nFeatures            \n  call_hierarchy    display selected identifier's call hierarchy\n  check             show diagnostic results for the specified file\n  codeaction        list or execute code actions\n  codelens          List or execute code lenses for a file\n  definition        show declaration of selected identifier\n  execute           Execute a gopls custom LSP command\n  fix               apply suggested fixes (obsolete)\n  folding_ranges    display selected file's folding ranges\n  format            format the code according to the go standard\n  mcp               start the gopls MCP server in headless mode\n  highlight         display selected identifier's highlights\n  implementation    display selected identifier's implementation\n  imports           updates import statements\n  remote            interact with the gopls daemon\n  inspect           interact with the gopls daemon (deprecated: use 'remote')\n  links             list links in a file\n  prepare_rename    test validity of a rename operation at location\n  references        display selected identifier's references\n  rename            rename selected identifier\n  semtok            show semantic tokens for the specified file\n  signature         display selected identifier's signature\n  stats             print workspace statistics\n  symbols           display selected file's symbols\n  workspace_symbol  search symbols in workspace\n\nflags:\n  -debug=string\n    \tserve debug information on the supplied address\n  -listen=string\n    \taddress on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.\n  -listen.timeout=duration\n    \twhen used with -listen, shut down the server when there are no connected clients for this duration\n  -logfile=string\n    \tfilename to log to. if value is \"auto\", then logging to a default output file is enabled\n  -mcp.listen=string\n    \texperimental: address on which to listen for model context protocol connections. If port is localhost:0, pick a random port in localhost instead.\n  -mode=string\n    \tno effect\n  -otel=string\n    \texport telemetry to specified OpenTelemetry collector address (e.g. http://localhost:4318)\n  -port=int\n    \tport on which to run gopls for debugging purposes\n  -profile.alloc=string\n    \twrite alloc profile to this file\n  -profile.block=string\n    \twrite block profile to this file\n  -profile.cpu=string\n    \twrite CPU profile to this file\n  -profile.mem=string\n    \twrite memory profile to this file\n  -profile.trace=string\n    \twrite trace log to this file\n  -remote=string\n    \tforward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment.\n  -remote.debug=string\n    \twhen used with -remote=auto, the -debug value used to start the daemon\n  -remote.listen.timeout=duration\n    \twhen used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)\n  -remote.logfile=string\n    \twhen used with -remote=auto, the -logfile value used to start the daemon\n  -rpc.trace\n    \tprint the full rpc trace in lsp inspector format\n  -v,-verbose\n    \tverbose output\n  -vv,-veryverbose\n    \tvery verbose output\n"
  },
  {
    "path": "gopls/internal/cmd/usage/version.hlp",
    "content": "print the gopls version information\n\nUsage:\n  gopls [flags] version\n  -json\n    \toutputs in json format.\n"
  },
  {
    "path": "gopls/internal/cmd/usage/vulncheck.hlp",
    "content": "run vulncheck analysis (internal-use only)\n\nUsage:\n  gopls [flags] vulncheck\n\n\tWARNING: this command is for internal-use only.\n\n\tBy default, the command outputs a JSON-encoded\n\tgolang.org/x/tools/gopls/internal/protocol/command.VulncheckResult\n\tmessage.\n\tExample:\n\t$ gopls vulncheck <packages>\n\n"
  },
  {
    "path": "gopls/internal/cmd/usage/workspace_symbol.hlp",
    "content": "search symbols in workspace\n\nUsage:\n  gopls [flags] workspace_symbol [workspace_symbol-flags] <query>\n\nExample:\n\n\t$ gopls workspace_symbol -matcher fuzzy 'wsymbols'\n\nworkspace_symbol-flags:\n  -matcher=string\n    \tspecifies the type of matcher: fuzzy, fastfuzzy, casesensitive, or caseinsensitive.\n    \tThe default is caseinsensitive.\n"
  },
  {
    "path": "gopls/internal/cmd/vulncheck.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"golang.org/x/tools/gopls/internal/vulncheck/scan\"\n)\n\n// vulncheck implements the vulncheck command.\n// TODO(hakim): hide from the public.\ntype vulncheck struct {\n\tapp *Application\n}\n\nfunc (v *vulncheck) Name() string   { return \"vulncheck\" }\nfunc (v *vulncheck) Parent() string { return v.app.Name() }\nfunc (v *vulncheck) Usage() string  { return \"\" }\nfunc (v *vulncheck) ShortHelp() string {\n\treturn \"run vulncheck analysis (internal-use only)\"\n}\nfunc (v *vulncheck) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\n\tWARNING: this command is for internal-use only.\n\n\tBy default, the command outputs a JSON-encoded\n\tgolang.org/x/tools/gopls/internal/protocol/command.VulncheckResult\n\tmessage.\n\tExample:\n\t$ gopls vulncheck <packages>\n\n`)\n}\n\nfunc (v *vulncheck) Run(ctx context.Context, args ...string) error {\n\tif err := scan.Main(ctx, args...); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/cmd/workspace_symbol.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\n// workspaceSymbol implements the workspace_symbol verb for gopls.\ntype workspaceSymbol struct {\n\tMatcher string `flag:\"matcher\" help:\"specifies the type of matcher: fuzzy, fastfuzzy, casesensitive, or caseinsensitive.\\nThe default is caseinsensitive.\"`\n\n\tapp *Application\n}\n\nfunc (r *workspaceSymbol) Name() string      { return \"workspace_symbol\" }\nfunc (r *workspaceSymbol) Parent() string    { return r.app.Name() }\nfunc (r *workspaceSymbol) Usage() string     { return \"[workspace_symbol-flags] <query>\" }\nfunc (r *workspaceSymbol) ShortHelp() string { return \"search symbols in workspace\" }\nfunc (r *workspaceSymbol) DetailedHelp(f *flag.FlagSet) {\n\tfmt.Fprint(f.Output(), `\nExample:\n\n\t$ gopls workspace_symbol -matcher fuzzy 'wsymbols'\n\nworkspace_symbol-flags:\n`)\n\tprintFlagDefaults(f)\n}\n\nfunc (r *workspaceSymbol) Run(ctx context.Context, args ...string) error {\n\tif len(args) != 1 {\n\t\treturn tool.CommandLineErrorf(\"workspace_symbol expects 1 argument\")\n\t}\n\n\topts := r.app.options\n\tr.app.options = func(o *settings.Options) {\n\t\tif opts != nil {\n\t\t\topts(o)\n\t\t}\n\t\tswitch strings.ToLower(r.Matcher) {\n\t\tcase \"fuzzy\":\n\t\t\to.SymbolMatcher = settings.SymbolFuzzy\n\t\tcase \"casesensitive\":\n\t\t\to.SymbolMatcher = settings.SymbolCaseSensitive\n\t\tcase \"fastfuzzy\":\n\t\t\to.SymbolMatcher = settings.SymbolFastFuzzy\n\t\tdefault:\n\t\t\to.SymbolMatcher = settings.SymbolCaseInsensitive\n\t\t}\n\t}\n\n\tcli, _, err := r.app.connect(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cli.terminate(ctx)\n\n\tp := protocol.WorkspaceSymbolParams{\n\t\tQuery: args[0],\n\t}\n\n\tsymbols, err := cli.server.Symbol(ctx, &p)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, s := range symbols {\n\t\tf, err := cli.openFile(ctx, s.Location.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tspan, err := f.locationSpan(s.Location)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Printf(\"%s %s %s\\n\", span, s.Name, s.Kind)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/debug/flight.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.25\n\npackage debug\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime/trace\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n)\n\nvar (\n\ttraceviewersMu sync.Mutex\n\ttraceviewers   []*os.Process\n\n\tkill        = (*os.Process).Kill // windows, plan9; UNIX impl kills whole process group\n\tsysProcAttr syscall.SysProcAttr  // UNIX configuration to create process group\n)\n\n// KillTraceViewers kills all \"go tool trace\" processes started by\n// /flightrecorder requests, for use in tests (see #74668).\nfunc KillTraceViewers() {\n\ttraceviewersMu.Lock()\n\tfor _, p := range traceviewers {\n\t\tkill(p) // ignore error\n\t}\n\ttraceviewers = nil\n\ttraceviewersMu.Unlock()\n}\n\n// The FlightRecorder is a global resource, so create at most one per process.\nvar getRecorder = sync.OnceValues(func() (*trace.FlightRecorder, error) {\n\tfr := trace.NewFlightRecorder(trace.FlightRecorderConfig{\n\t\t// half a minute is usually enough to know \"what just happened?\"\n\t\tMinAge: 30 * time.Second,\n\t})\n\tif err := fr.Start(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn fr, nil\n})\n\nfunc startFlightRecorder() (http.HandlerFunc, error) {\n\tfr, err := getRecorder()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return a handler that writes the most recent flight record,\n\t// starts a trace viewer server, and redirects to it.\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\terrorf := func(format string, args ...any) {\n\t\t\tmsg := fmt.Sprintf(format, args...)\n\t\t\thttp.Error(w, msg, http.StatusInternalServerError)\n\t\t}\n\n\t\t// Write the most recent flight record into a temp file.\n\t\tf, err := os.CreateTemp(\"\", \"flightrecord\")\n\t\tif err != nil {\n\t\t\terrorf(\"can't create temp file for flight record: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tif _, err := fr.WriteTo(f); err != nil {\n\t\t\tf.Close() // ignore error\n\t\t\terrorf(\"failed to write flight record: %s\", err)\n\t\t\treturn\n\t\t}\n\t\tif err := f.Close(); err != nil {\n\t\t\terrorf(\"failed to close flight record: %s\", err)\n\t\t\treturn\n\t\t}\n\t\ttracefile, err := filepath.Abs(f.Name())\n\t\tif err != nil {\n\t\t\terrorf(\"can't absolutize name of trace file: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Run 'go tool trace' to start a new trace-viewer\n\t\t// web server process. It will run until gopls terminates.\n\t\t// (It would be nicer if we could just link it in; see #66843.)\n\t\tcmd := exec.Command(\"go\", \"tool\", \"trace\", tracefile)\n\t\tcmd.SysProcAttr = &sysProcAttr\n\n\t\t// Don't connect trace's std{out,err} to our os.Stderr directly,\n\t\t// otherwise the child may outlive the parent in tests,\n\t\t// and 'go test' will complain about unclosed pipes.\n\t\t// Instead, interpose a pipe that will close when gopls exits.\n\t\t// See CL 677262 for a better solution (a cmd/trace flag).\n\t\t// (#66843 is of course better still.)\n\t\t// Also, this notifies us of the server's readiness and URL.\n\t\turlC := make(chan string)\n\t\t{\n\t\t\tr, w, err := os.Pipe()\n\t\t\tif err != nil {\n\t\t\t\terrorf(\"can't create pipe: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tgo func() {\n\t\t\t\t// Copy from the pipe to stderr,\n\t\t\t\t// keeping an eye out for the \"listening on URL\" string.\n\t\t\t\tscan := bufio.NewScanner(r)\n\t\t\t\tfor scan.Scan() {\n\t\t\t\t\tline := scan.Text()\n\t\t\t\t\tif _, url, ok := strings.Cut(line, \"Trace viewer is listening on \"); ok {\n\t\t\t\t\t\turlC <- url\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintln(os.Stderr, line)\n\t\t\t\t}\n\t\t\t\tif err := scan.Err(); err != nil {\n\t\t\t\t\tlog.Printf(\"reading from pipe to cmd/trace: %v\", err)\n\t\t\t\t}\n\t\t\t}()\n\t\t\tcmd.Stderr = w\n\t\t\tcmd.Stdout = w\n\t\t}\n\n\t\t// Suppress the usual cmd/trace behavior of opening a new\n\t\t// browser tab by setting BROWSER to /usr/bin/true (a no-op).\n\t\tcmd.Env = append(os.Environ(), \"BROWSER=true\")\n\t\tif err := cmd.Start(); err != nil {\n\t\t\terrorf(\"failed to start trace server: %s\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Save the process so we can kill it when tests finish.\n\t\ttraceviewersMu.Lock()\n\t\ttraceviewers = append(traceviewers, cmd.Process)\n\t\ttraceviewersMu.Unlock()\n\n\t\t// Some of the CI builders can be quite heavily loaded.\n\t\t// Give them an extra grace period.\n\t\ttimeout := 10 * time.Second\n\t\tif os.Getenv(\"GO_BUILDER_NAME\") != \"\" {\n\t\t\ttimeout = 1 * time.Minute\n\t\t}\n\n\t\tselect {\n\t\tcase addr := <-urlC:\n\t\t\t// Success! Send a redirect to the new location.\n\t\t\t// (This URL bypasses the help screen at /.)\n\t\t\thttp.Redirect(w, r, addr+\"/trace?view=proc\", 302)\n\n\t\tcase <-r.Context().Done():\n\t\t\terrorf(\"canceled\")\n\n\t\tcase <-time.After(timeout):\n\t\t\terrorf(\"trace viewer failed to start within %v\", timeout)\n\t\t}\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/debug/flight_go124.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.25\n\npackage debug\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n)\n\nfunc startFlightRecorder() (http.HandlerFunc, error) {\n\treturn nil, errors.ErrUnsupported\n}\n\nfunc KillTraceViewers() {}\n"
  },
  {
    "path": "gopls/internal/debug/flight_unix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.25 && unix\n\npackage debug\n\nimport (\n\t\"os\"\n\t\"syscall\"\n)\n\nfunc init() {\n\t// UNIX: kill the whole process group, since\n\t// \"go tool trace\" starts a cmd/trace child.\n\tkill = killGroup\n\tsysProcAttr.Setpgid = true\n}\n\nfunc killGroup(p *os.Process) error {\n\treturn syscall.Kill(-p.Pid, syscall.SIGKILL)\n}\n"
  },
  {
    "path": "gopls/internal/debug/info.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package debug exports debug information for gopls.\npackage debug\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/version\"\n)\n\ntype PrintMode int\n\nconst (\n\tPlainText = PrintMode(iota)\n\tMarkdown\n\tHTML\n\tJSON\n)\n\n// ServerVersion is the format used by gopls to report its version to the\n// client. This format is structured so that the client can parse it easily.\ntype ServerVersion struct {\n\t*debug.BuildInfo\n\tVersion string\n}\n\n// VersionInfo returns the build info for the gopls process. If it was not\n// built in module mode, we return a GOPATH-specific message with the\n// hardcoded version.\nfunc VersionInfo() *ServerVersion {\n\tif info, ok := debug.ReadBuildInfo(); ok {\n\t\treturn &ServerVersion{\n\t\t\tVersion:   version.Version(),\n\t\t\tBuildInfo: info,\n\t\t}\n\t}\n\treturn &ServerVersion{\n\t\tVersion: version.Version(),\n\t\tBuildInfo: &debug.BuildInfo{\n\t\t\tPath:      \"gopls, built in GOPATH mode\",\n\t\t\tGoVersion: runtime.Version(),\n\t\t},\n\t}\n}\n\n// writeServerInfo writes HTML debug info to w for the instance.\nfunc (i *Instance) writeServerInfo(out *bytes.Buffer) {\n\tworkDir, _ := os.Getwd()\n\tsection(out, HTML, \"server instance\", func() {\n\t\tfmt.Fprintf(out, \"Start time: %v\\n\", i.StartTime)\n\t\tfmt.Fprintf(out, \"LogFile: %s\\n\", i.Logfile)\n\t\tfmt.Fprintf(out, \"pid: %d\\n\", os.Getpid())\n\t\tfmt.Fprintf(out, \"Working directory: %s\\n\", workDir)\n\t\tfmt.Fprintf(out, \"Address: %s\\n\", i.ServerAddress)\n\t\tfmt.Fprintf(out, \"Debug address: %s\\n\", i.DebugAddress())\n\t})\n\tWriteVersionInfo(out, true, HTML)\n\tsection(out, HTML, \"Command Line\", func() {\n\t\tfmt.Fprintf(out, \"<a href=/debug/pprof/cmdline>cmdline</a>\")\n\t})\n}\n\n// WriteVersionInfo writes version information to w, using the output format\n// specified by mode. verbose controls whether additional information is\n// written, including section headers.\nfunc WriteVersionInfo(out *bytes.Buffer, verbose bool, mode PrintMode) {\n\tinfo := VersionInfo()\n\tif mode == JSON {\n\t\twriteVersionInfoJSON(out, info)\n\t\treturn\n\t}\n\n\tif !verbose {\n\t\twriteBuildInfo(out, info, false, mode)\n\t\treturn\n\t}\n\tsection(out, mode, \"Build info\", func() {\n\t\twriteBuildInfo(out, info, true, mode)\n\t})\n}\n\nfunc writeVersionInfoJSON(out *bytes.Buffer, info *ServerVersion) {\n\tdata, err := json.MarshalIndent(info, \"\", \"\\t\")\n\tif err != nil {\n\t\tpanic(err) // can't happen\n\t}\n\tout.Write(data)\n}\n\nfunc section(w io.Writer, mode PrintMode, title string, body func()) {\n\tswitch mode {\n\tcase PlainText:\n\t\tfmt.Fprintln(w, title)\n\t\tfmt.Fprintln(w, strings.Repeat(\"-\", len(title)))\n\t\tbody()\n\tcase Markdown:\n\t\tfmt.Fprintf(w, \"#### %s\\n\\n```\\n\", title)\n\t\tbody()\n\t\tfmt.Fprintf(w, \"```\\n\")\n\tcase HTML:\n\t\tfmt.Fprintf(w, \"<h3>%s</h3>\\n<pre>\\n\", title)\n\t\tbody()\n\t\tfmt.Fprint(w, \"</pre>\\n\")\n\t}\n}\n\nfunc writeBuildInfo(w io.Writer, info *ServerVersion, verbose bool, mode PrintMode) {\n\tfmt.Fprintf(w, \"%v %v\\n\", info.Path, version.Version())\n\tif !verbose {\n\t\treturn\n\t}\n\tprintModuleInfo(w, info.Main, mode)\n\tfor _, dep := range info.Deps {\n\t\tprintModuleInfo(w, *dep, mode)\n\t}\n\tfmt.Fprintf(w, \"go: %v\\n\", info.GoVersion)\n}\n\nfunc printModuleInfo(w io.Writer, m debug.Module, _ PrintMode) {\n\tfmt.Fprintf(w, \"    %s@%s\", m.Path, m.Version)\n\tif m.Sum != \"\" {\n\t\tfmt.Fprintf(w, \" %s\", m.Sum)\n\t}\n\tif m.Replace != nil {\n\t\tfmt.Fprintf(w, \" => %v\", m.Replace.Path)\n\t}\n\tfmt.Fprintf(w, \"\\n\")\n}\n"
  },
  {
    "path": "gopls/internal/debug/info_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package debug exports debug information for gopls.\npackage debug\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/version\"\n)\n\nfunc TestPrintVersionInfoJSON(t *testing.T) {\n\tbuf := new(bytes.Buffer)\n\tWriteVersionInfo(buf, true, JSON)\n\tres := buf.Bytes()\n\n\tvar got ServerVersion\n\tif err := json.Unmarshal(res, &got); err != nil {\n\t\tt.Fatalf(\"unexpected output: %v\\n%s\", err, res)\n\t}\n\tif g, w := got.GoVersion, runtime.Version(); g != w {\n\t\tt.Errorf(\"go version = %v, want %v\", g, w)\n\t}\n\tif g, w := got.Version, version.Version(); g != w {\n\t\tt.Errorf(\"gopls version = %v, want %v\", g, w)\n\t}\n\t// Other fields of BuildInfo may not be available during test.\n}\n\nfunc TestPrintVersionInfoPlainText(t *testing.T) {\n\tbuf := new(bytes.Buffer)\n\tWriteVersionInfo(buf, true, PlainText)\n\tres := buf.Bytes()\n\n\t// Other fields of BuildInfo may not be available during test.\n\twantGoplsVersion, wantGoVersion := version.Version(), runtime.Version()\n\tif !bytes.Contains(res, []byte(wantGoplsVersion)) || !bytes.Contains(res, []byte(wantGoVersion)) {\n\t\tt.Errorf(\"plaintext output = %q,\\nwant (version: %v, go: %v)\", res, wantGoplsVersion, wantGoVersion)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/debug/log/log.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package log provides helper methods for exporting log events to the\n// internal/event package.\npackage log\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tlabel1 \"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Level parameterizes log severity.\ntype Level int\n\nconst (\n\t_ Level = iota\n\tError\n\tWarning\n\tInfo\n\tDebug\n\tTrace\n)\n\n// Log exports a log event labeled with level l.\nfunc (l Level) Log(ctx context.Context, msg string) {\n\tevent.Log(ctx, msg, label1.Level.Of(int(l)))\n}\n\n// Logf formats and exports a log event labeled with level l.\nfunc (l Level) Logf(ctx context.Context, format string, args ...any) {\n\tl.Log(ctx, fmt.Sprintf(format, args...))\n}\n\n// LabeledLevel extracts the labeled log l\nfunc LabeledLevel(lm label.Map) Level {\n\treturn Level(label1.Level.Get(lm))\n}\n"
  },
  {
    "path": "gopls/internal/debug/metrics.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug\n\nimport (\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/label\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\nvar (\n\t// the distributions we use for histograms\n\tbytesDistribution   = []int64{1 << 10, 1 << 11, 1 << 12, 1 << 14, 1 << 16, 1 << 20}\n\tsecondsDistribution = []float64{\n\t\t0.0001, // 0.1ms\n\t\t0.0005, // 0.5ms\n\t\t0.001,  // 1ms\n\t\t0.002,  // 2ms\n\t\t0.005,  // 5ms\n\t\t0.01,   // 10ms\n\t\t0.05,   // 50ms\n\t\t0.1,    // 100ms\n\t\t0.5,    // 500ms\n\t\t1,      // 1s\n\t\t5,      // 5s\n\t\t10,     // 10s\n\t\t50,     // 50s\n\t\t100,    // 1m40s\n\t\t500,    // 8m20s\n\t\t1000,   // 16m40s\n\t}\n\n\treceivedBytes = metric.HistogramInt64{\n\t\tName:        \"received_bytes\",\n\t\tDescription: \"Distribution of received bytes, by method.\",\n\t\tKeys:        []label.Key{jsonrpc2.RPCDirection, jsonrpc2.Method},\n\t\tBuckets:     bytesDistribution,\n\t}\n\n\tsentBytes = metric.HistogramInt64{\n\t\tName:        \"sent_bytes\",\n\t\tDescription: \"Distribution of sent bytes, by method.\",\n\t\tKeys:        []label.Key{jsonrpc2.RPCDirection, jsonrpc2.Method},\n\t\tBuckets:     bytesDistribution,\n\t}\n\n\tlatency = metric.HistogramFloat64{\n\t\tName:        \"latency\",\n\t\tDescription: \"Distribution of latency in seconds, by method.\",\n\t\tKeys:        []label.Key{jsonrpc2.RPCDirection, jsonrpc2.Method},\n\t\tBuckets:     secondsDistribution,\n\t}\n\n\tstarted = metric.Scalar{\n\t\tName:        \"started\",\n\t\tDescription: \"Count of RPCs started by method.\",\n\t\tKeys:        []label.Key{jsonrpc2.RPCDirection, jsonrpc2.Method},\n\t}\n\n\tcompleted = metric.Scalar{\n\t\tName:        \"completed\",\n\t\tDescription: \"Count of RPCs completed by method and status.\",\n\t\tKeys:        []label.Key{jsonrpc2.RPCDirection, jsonrpc2.Method, jsonrpc2.StatusCode},\n\t}\n)\n\nfunc registerMetrics(m *metric.Config) {\n\treceivedBytes.Record(m, jsonrpc2.ReceivedBytes)\n\tsentBytes.Record(m, jsonrpc2.SentBytes)\n\tlatency.Record(m, jsonrpc2.Latency)\n\tstarted.Count(m, jsonrpc2.Started)\n\tcompleted.Count(m, jsonrpc2.Latency)\n}\n"
  },
  {
    "path": "gopls/internal/debug/rpc.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/label\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\nvar RPCTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}RPC Information{{end}}\n{{define \"body\"}}\n\t<H2>Inbound</H2>\n\t{{template \"rpcSection\" .Inbound}}\n\t<H2>Outbound</H2>\n\t{{template \"rpcSection\" .Outbound}}\n{{end}}\n{{define \"rpcSection\"}}\n\t{{range .}}<P>\n\t\t<b>{{.Method}}</b> {{.Started}} <a href=\"/trace/{{.Method}}\">traces</a> ({{.InProgress}} in progress)\n\t\t<br>\n\t\t<i>Latency</i> {{with .Latency}}{{.Mean}} ({{.Min}}<{{.Max}}){{end}}\n\t\t<i>By bucket</i> 0s {{range .Latency.Values}}{{if gt .Count 0}}<b>{{.Count}}</b> {{.Limit}} {{end}}{{end}}\n\t\t<br>\n\t\t<i>Received</i> {{.Received}} (avg. {{.ReceivedMean}})\n\t\t<i>Sent</i> {{.Sent}} (avg. {{.SentMean}})\n\t\t<br>\n\t\t<i>Result codes</i> {{range .Codes}}{{.Key}}={{.Count}} {{end}}\n\t\t</P>\n\t{{end}}\n{{end}}\n`))\n\ntype Rpcs struct { // exported for testing\n\tmu       sync.Mutex\n\tInbound  []*rpcStats // stats for incoming lsp rpcs sorted by method name\n\tOutbound []*rpcStats // stats for outgoing lsp rpcs sorted by method name\n}\n\ntype rpcStats struct {\n\tMethod    string\n\tStarted   int64\n\tCompleted int64\n\n\tLatency  rpcTimeHistogram\n\tReceived byteUnits\n\tSent     byteUnits\n\tCodes    []*rpcCodeBucket\n}\n\ntype rpcTimeHistogram struct {\n\tSum    time.Duration\n\tCount  int64\n\tMin    time.Duration\n\tMax    time.Duration\n\tValues []rpcTimeBucket\n}\n\ntype rpcTimeBucket struct {\n\tLimit time.Duration\n\tCount int64\n}\n\ntype rpcCodeBucket struct {\n\tKey   string\n\tCount int64\n}\n\nfunc (r *Rpcs) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\tswitch {\n\tcase event.IsStart(ev):\n\t\tif _, stats := r.getRPCSpan(ctx); stats != nil {\n\t\t\tstats.Started++\n\t\t}\n\tcase event.IsEnd(ev):\n\t\tspan, stats := r.getRPCSpan(ctx)\n\t\tif stats != nil {\n\t\t\tendRPC(span, stats)\n\t\t}\n\tcase event.IsMetric(ev):\n\t\tsent := byteUnits(jsonrpc2.SentBytes.Get(lm))\n\t\trec := byteUnits(jsonrpc2.ReceivedBytes.Get(lm))\n\t\tif sent != 0 || rec != 0 {\n\t\t\tif _, stats := r.getRPCSpan(ctx); stats != nil {\n\t\t\t\tstats.Sent += sent\n\t\t\t\tstats.Received += rec\n\t\t\t}\n\t\t}\n\t}\n\treturn ctx\n}\n\nfunc endRPC(span *export.Span, stats *rpcStats) {\n\t// update the basic counts\n\tstats.Completed++\n\n\t// get and record the status code\n\tif status := getStatusCode(span); status != \"\" {\n\t\tvar b *rpcCodeBucket\n\t\tfor c, entry := range stats.Codes {\n\t\t\tif entry.Key == status {\n\t\t\t\tb = stats.Codes[c]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif b == nil {\n\t\t\tb = &rpcCodeBucket{Key: status}\n\t\t\tstats.Codes = append(stats.Codes, b)\n\t\t\tsort.Slice(stats.Codes, func(i int, j int) bool {\n\t\t\t\treturn stats.Codes[i].Key < stats.Codes[j].Key\n\t\t\t})\n\t\t}\n\t\tb.Count++\n\t}\n\n\t// calculate latency if this was an rpc span\n\telapsedTime := span.Finish().At().Sub(span.Start().At())\n\tif stats.Latency.Count == 0 {\n\t\tstats.Latency.Min = elapsedTime\n\t\tstats.Latency.Max = elapsedTime\n\t} else {\n\t\tstats.Latency.Min = min(stats.Latency.Min, elapsedTime)\n\t\tstats.Latency.Max = max(stats.Latency.Max, elapsedTime)\n\t}\n\tstats.Latency.Count++\n\tstats.Latency.Sum += elapsedTime\n\tfor i := range stats.Latency.Values {\n\t\tif stats.Latency.Values[i].Limit > elapsedTime {\n\t\t\tstats.Latency.Values[i].Count++\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (r *Rpcs) getRPCSpan(ctx context.Context) (*export.Span, *rpcStats) {\n\t// get the span\n\tspan := export.GetSpan(ctx)\n\tif span == nil {\n\t\treturn nil, nil\n\t}\n\t// use the span start event look up the correct stats block\n\t// we do this because it prevents us matching a sub span\n\treturn span, r.getRPCStats(span.Start())\n}\n\nfunc (r *Rpcs) getRPCStats(lm label.Map) *rpcStats {\n\tmethod := jsonrpc2.Method.Get(lm)\n\tif method == \"\" {\n\t\treturn nil\n\t}\n\tset := &r.Inbound\n\tif jsonrpc2.RPCDirection.Get(lm) != jsonrpc2.Inbound {\n\t\tset = &r.Outbound\n\t}\n\t// get the record for this method\n\tindex := sort.Search(len(*set), func(i int) bool {\n\t\treturn (*set)[i].Method >= method\n\t})\n\n\tif index < len(*set) && (*set)[index].Method == method {\n\t\treturn (*set)[index]\n\t}\n\n\told := *set\n\t*set = make([]*rpcStats, len(old)+1)\n\tcopy(*set, old[:index])\n\tcopy((*set)[index+1:], old[index:])\n\tstats := &rpcStats{Method: method}\n\tstats.Latency.Values = make([]rpcTimeBucket, len(secondsDistribution))\n\tfor i, m := range secondsDistribution {\n\t\tstats.Latency.Values[i].Limit = time.Duration(m * float64(time.Second))\n\t}\n\t(*set)[index] = stats\n\treturn stats\n}\n\nfunc (s *rpcStats) InProgress() int64       { return s.Started - s.Completed }\nfunc (s *rpcStats) SentMean() byteUnits     { return s.Sent / byteUnits(s.Started) }\nfunc (s *rpcStats) ReceivedMean() byteUnits { return s.Received / byteUnits(s.Started) }\n\nfunc (h *rpcTimeHistogram) Mean() time.Duration { return h.Sum / time.Duration(h.Count) }\n\nfunc getStatusCode(span *export.Span) string {\n\tfor _, ev := range span.Events() {\n\t\tif status := jsonrpc2.StatusCode.Get(ev); status != \"\" {\n\t\t\treturn status\n\t\t}\n\t}\n\treturn \"\"\n}\n\nfunc (r *Rpcs) getData(req *http.Request) any {\n\treturn r\n}\n\nfunc units(v float64, suffixes []string) string {\n\ts := \"\"\n\tfor _, s = range suffixes {\n\t\tn := v / 1000\n\t\tif n < 1 {\n\t\t\tbreak\n\t\t}\n\t\tv = n\n\t}\n\treturn fmt.Sprintf(\"%.2f%s\", v, s)\n}\n\ntype byteUnits float64\n\nfunc (v byteUnits) String() string {\n\treturn units(float64(v), []string{\"B\", \"KB\", \"MB\", \"GB\", \"TB\"})\n}\n"
  },
  {
    "path": "gopls/internal/debug/serve.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"io\"\n\tstdlog \"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/pprof\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/debug/log\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\tlabel1 \"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\tversionpkg \"golang.org/x/tools/gopls/internal/version\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/export/otel\"\n\t\"golang.org/x/tools/internal/event/export/prometheus\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\ntype contextKeyType int\n\nconst (\n\tinstanceKey contextKeyType = iota\n\ttraceKey\n)\n\n// An Instance holds all debug information associated with a gopls instance.\ntype Instance struct {\n\tLogfile       string\n\tStartTime     time.Time\n\tServerAddress string\n\n\tLogWriter io.Writer\n\n\texporter event.Exporter\n\n\tprometheus *prometheus.Exporter\n\trpcs       *Rpcs\n\ttraces     *traces\n\totel       *otel.Exporter\n\tState      *State\n\n\tserveMu              sync.Mutex\n\tdebugAddress         string\n\tlistenedDebugAddress string\n}\n\n// State holds debugging information related to the server state.\ntype State struct {\n\tmu      sync.Mutex\n\tclients []*Client\n\tservers []*Server\n}\n\nfunc (st *State) Bugs() []bug.Bug {\n\treturn bug.List()\n}\n\n// Caches returns the set of Cache objects currently being served.\nfunc (st *State) Caches() []*cache.Cache {\n\tvar caches []*cache.Cache\n\tseen := make(map[string]struct{})\n\tfor _, client := range st.Clients() {\n\t\tcache := client.Session.Cache()\n\t\tif _, found := seen[cache.ID()]; found {\n\t\t\tcontinue\n\t\t}\n\t\tseen[cache.ID()] = struct{}{}\n\t\tcaches = append(caches, cache)\n\t}\n\treturn caches\n}\n\n// Cache returns the Cache that matches the supplied id.\nfunc (st *State) Cache(id string) *cache.Cache {\n\tfor _, c := range st.Caches() {\n\t\tif c.ID() == id {\n\t\t\treturn c\n\t\t}\n\t}\n\treturn nil\n}\n\n// Analysis returns the global Analysis template value.\nfunc (st *State) Analysis() (_ analysisTmpl) { return }\n\ntype analysisTmpl struct{}\n\nfunc (analysisTmpl) AnalyzerRunTimes() []cache.LabelDuration { return cache.AnalyzerRunTimes() }\n\n// Sessions returns the set of Session objects currently being served.\nfunc (st *State) Sessions() []*cache.Session {\n\tvar sessions []*cache.Session\n\tfor _, client := range st.Clients() {\n\t\tsessions = append(sessions, client.Session)\n\t}\n\treturn sessions\n}\n\n// Session returns the Session that matches the supplied id.\nfunc (st *State) Session(id string) *cache.Session {\n\tfor _, s := range st.Sessions() {\n\t\tif s.ID() == id {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\n// Views returns the set of View objects currently being served.\nfunc (st *State) Views() []*cache.View {\n\tvar views []*cache.View\n\tfor _, s := range st.Sessions() {\n\t\tviews = append(views, s.Views()...)\n\t}\n\treturn views\n}\n\n// View returns the View that matches the supplied id.\nfunc (st *State) View(id string) *cache.View {\n\tfor _, s := range st.Sessions() {\n\t\tif v, err := s.View(id); err == nil {\n\t\t\treturn v\n\t\t}\n\t}\n\treturn nil // not found\n}\n\n// Clients returns the set of Clients currently being served.\nfunc (st *State) Clients() []*Client {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tclients := make([]*Client, len(st.clients))\n\tcopy(clients, st.clients)\n\treturn clients\n}\n\n// Client returns the Client matching the supplied id.\nfunc (st *State) Client(id string) *Client {\n\tfor _, c := range st.Clients() {\n\t\tif c.Session.ID() == id {\n\t\t\treturn c\n\t\t}\n\t}\n\treturn nil\n}\n\n// Servers returns the set of Servers the instance is currently connected to.\nfunc (st *State) Servers() []*Server {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tservers := make([]*Server, len(st.servers))\n\tcopy(servers, st.servers)\n\treturn servers\n}\n\n// A Client is an incoming connection from a remote client.\ntype Client struct {\n\tSession      *cache.Session\n\tDebugAddress string\n\tLogfile      string\n\tGoplsPath    string\n\tServerID     string\n\tService      protocol.Server\n}\n\n// A Server is an outgoing connection to a remote LSP server.\ntype Server struct {\n\tID           string\n\tDebugAddress string\n\tLogfile      string\n\tGoplsPath    string\n\tClientID     string\n}\n\n// addClient adds a client to the set being served.\nfunc (st *State) addClient(session *cache.Session) {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tst.clients = append(st.clients, &Client{Session: session})\n}\n\n// dropClient removes a client from the set being served.\nfunc (st *State) dropClient(session *cache.Session) {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tfor i, c := range st.clients {\n\t\tif c.Session == session {\n\t\t\tcopy(st.clients[i:], st.clients[i+1:])\n\t\t\tst.clients[len(st.clients)-1] = nil\n\t\t\tst.clients = st.clients[:len(st.clients)-1]\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// updateServer updates a server to the set being queried. In practice, there should\n// be at most one remote server.\nfunc (st *State) updateServer(server *Server) {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tfor i, existing := range st.servers {\n\t\tif existing.ID == server.ID {\n\t\t\t// Replace, rather than mutate, to avoid a race.\n\t\t\tnewServers := make([]*Server, len(st.servers))\n\t\t\tcopy(newServers, st.servers[:i])\n\t\t\tnewServers[i] = server\n\t\t\tcopy(newServers[i+1:], st.servers[i+1:])\n\t\t\tst.servers = newServers\n\t\t\treturn\n\t\t}\n\t}\n\tst.servers = append(st.servers, server)\n}\n\n// dropServer drops a server from the set being queried.\nfunc (st *State) dropServer(id string) {\n\tst.mu.Lock()\n\tdefer st.mu.Unlock()\n\tfor i, s := range st.servers {\n\t\tif s.ID == id {\n\t\t\tcopy(st.servers[i:], st.servers[i+1:])\n\t\t\tst.servers[len(st.servers)-1] = nil\n\t\t\tst.servers = st.servers[:len(st.servers)-1]\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// an http.ResponseWriter that filters writes\ntype filterResponse struct {\n\tw    http.ResponseWriter\n\tedit func([]byte) []byte\n}\n\nfunc (c filterResponse) Header() http.Header {\n\treturn c.w.Header()\n}\n\nfunc (c filterResponse) Write(buf []byte) (int, error) {\n\tans := c.edit(buf)\n\treturn c.w.Write(ans)\n}\n\nfunc (c filterResponse) WriteHeader(n int) {\n\tc.w.WriteHeader(n)\n}\n\n// replace annoying nuls by spaces\nfunc cmdline(w http.ResponseWriter, r *http.Request) {\n\tfake := filterResponse{\n\t\tw: w,\n\t\tedit: func(buf []byte) []byte {\n\t\t\treturn bytes.ReplaceAll(buf, []byte{0}, []byte{' '})\n\t\t},\n\t}\n\tpprof.Cmdline(fake, r)\n}\n\nfunc (i *Instance) getCache(r *http.Request) any {\n\treturn i.State.Cache(path.Base(r.URL.Path))\n}\n\nfunc (i *Instance) getAnalysis(r *http.Request) any {\n\treturn i.State.Analysis()\n}\n\nfunc (i *Instance) getSession(r *http.Request) any {\n\treturn i.State.Session(path.Base(r.URL.Path))\n}\n\nfunc (i *Instance) getClient(r *http.Request) any {\n\treturn i.State.Client(path.Base(r.URL.Path))\n}\n\nfunc (i *Instance) getServer(r *http.Request) any {\n\ti.State.mu.Lock()\n\tdefer i.State.mu.Unlock()\n\tid := path.Base(r.URL.Path)\n\tfor _, s := range i.State.servers {\n\t\tif s.ID == id {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\ntype FileWithKind interface {\n\tfile.Handle\n\tKind() file.Kind // (overlay files only)\n}\n\n// /file/{session}/{identifier}. Returns a [FileWithKind].\nfunc (i *Instance) getFile(r *http.Request) any {\n\ts := i.State.Session(r.PathValue(\"session\"))\n\tif s == nil {\n\t\treturn nil\n\t}\n\tidentifier := r.PathValue(\"identifier\")\n\tfor _, o := range s.Overlays() {\n\t\t// TODO(adonovan): understand and document this comparison.\n\t\tif o.Identity().Hash.String() == identifier {\n\t\t\treturn o\n\t\t}\n\t}\n\treturn nil\n}\n\ntype MetadataInfo struct {\n\tSessionID string\n\tViewID    string\n\tGraph     *metadata.Graph\n}\n\n// /metadata/{session}/{view}. Returns a [*MetadataInfo].\nfunc (i *Instance) getMetadata(r *http.Request) any {\n\tsession := i.State.Session(r.PathValue(\"session\"))\n\tif session == nil {\n\t\treturn nil\n\t}\n\n\tv, err := session.View(r.PathValue(\"view\"))\n\tif err != nil {\n\t\tstdlog.Printf(\"/metadata: %v\", err)\n\t\treturn nil // no found\n\t}\n\n\tsnapshot, release, err := v.Snapshot()\n\tif err != nil {\n\t\tstdlog.Printf(\"/metadata: failed to get latest snapshot: %v\", err)\n\t\treturn nil\n\t}\n\tdefer release()\n\treturn &MetadataInfo{\n\t\tSessionID: session.ID(),\n\t\tViewID:    v.ID(),\n\t\tGraph:     snapshot.MetadataGraph(),\n\t}\n}\n\ntype PackageInfo struct {\n\tSessionID   string\n\tViewID      string\n\tPackage     *cache.Package\n\tDiagnostics map[protocol.DocumentURI][]*cache.Diagnostic\n}\n\n// /package/{session}/{view}/{id...}. Returns a [*PackageInfo].\nfunc (i *Instance) getPackage(r *http.Request) any {\n\t// TODO(adonovan): shouldn't we report an HTTP error in all\n\t// these early returns? Same for getMetadata.\n\tsession := i.State.Session(r.PathValue(\"session\"))\n\tif session == nil {\n\t\treturn nil // not found\n\t}\n\n\tv, err := session.View(r.PathValue(\"view\"))\n\tif err != nil {\n\t\tstdlog.Printf(\"/package: %v\", err)\n\t\treturn nil // not found\n\t}\n\n\tid := r.PathValue(\"id\")\n\n\tsnapshot, release, err := v.Snapshot()\n\tif err != nil {\n\t\tstdlog.Printf(\"/package: failed to get latest snapshot: %v\", err)\n\t\treturn nil\n\t}\n\tdefer release()\n\n\tpkgs, err := snapshot.TypeCheck(r.Context(), cache.PackageID(id))\n\tif err != nil {\n\t\tstdlog.Printf(\"/package: failed to typecheck package %q: %v\", id, err)\n\t\treturn nil\n\t}\n\n\t// (PackageDiagnostics is redundant w.r.t. TypeCheck but it's\n\t// the only way to access type errors in cache.Diagnostic form.)\n\tdiags, err := snapshot.PackageDiagnostics(r.Context(), cache.PackageID(id))\n\tif err != nil {\n\t\tstdlog.Printf(\"/package: failed to typecheck package %q: %v\", id, err)\n\t\treturn nil\n\t}\n\n\treturn &PackageInfo{\n\t\tSessionID:   session.ID(),\n\t\tViewID:      v.ID(),\n\t\tPackage:     pkgs[0],\n\t\tDiagnostics: diags,\n\t}\n}\n\nfunc (i *Instance) getInfo(r *http.Request) any {\n\tbuf := &bytes.Buffer{}\n\ti.writeServerInfo(buf)\n\treturn template.HTML(buf.String())\n}\n\nfunc (i *Instance) AddService(s protocol.Server, session *cache.Session) {\n\tfor _, c := range i.State.clients {\n\t\tif c.Session == session {\n\t\t\tc.Service = s\n\t\t\treturn\n\t\t}\n\t}\n\tstdlog.Printf(\"unable to find a Client to add the protocol.Server to\")\n}\n\nfunc getMemory(_ *http.Request) any {\n\tvar m runtime.MemStats\n\truntime.ReadMemStats(&m)\n\treturn m\n}\n\nfunc init() {\n\tevent.SetExporter(makeGlobalExporter(os.Stderr))\n}\n\nfunc GetInstance(ctx context.Context) *Instance {\n\tif ctx == nil {\n\t\treturn nil\n\t}\n\tv := ctx.Value(instanceKey)\n\tif v == nil {\n\t\treturn nil\n\t}\n\treturn v.(*Instance)\n}\n\n// WithInstance creates debug instance ready for use using the supplied\n// configuration and stores it in the returned context.\nfunc WithInstance(ctx context.Context, otelEndpoint string) context.Context {\n\ti := &Instance{\n\t\tStartTime: time.Now(),\n\t}\n\ti.LogWriter = os.Stderr\n\ti.prometheus = prometheus.New()\n\ti.rpcs = &Rpcs{}\n\ti.traces = &traces{}\n\ti.State = &State{}\n\tif otelEndpoint != \"\" {\n\t\ti.otel = otel.NewExporter(ctx,\n\t\t\totel.WithEndpoint(otelEndpoint),\n\t\t\totel.WithServiceName(\"gopls\"),\n\t\t\totel.WithServiceVersion(versionpkg.Version()))\n\t}\n\ti.exporter = makeInstanceExporter(i)\n\treturn context.WithValue(ctx, instanceKey, i)\n}\n\n// SetLogFile sets the logfile for use with this instance.\nfunc (i *Instance) SetLogFile(logfile string, isDaemon bool) (func(), error) {\n\t// TODO: probably a better solution for deferring closure to the caller would\n\t// be for the debug instance to itself be closed, but this fixes the\n\t// immediate bug of logs not being captured.\n\tcloseLog := func() {}\n\tif logfile != \"\" {\n\t\tif logfile == \"auto\" {\n\t\t\tif isDaemon {\n\t\t\t\tlogfile = filepath.Join(os.TempDir(), fmt.Sprintf(\"gopls-daemon-%d.log\", os.Getpid()))\n\t\t\t} else {\n\t\t\t\tlogfile = filepath.Join(os.TempDir(), fmt.Sprintf(\"gopls-%d.log\", os.Getpid()))\n\t\t\t}\n\t\t}\n\t\tf, err := os.Create(logfile)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to create log file: %w\", err)\n\t\t}\n\t\tcloseLog = func() {\n\t\t\tdefer f.Close()\n\t\t}\n\t\tstdlog.SetOutput(io.MultiWriter(os.Stderr, f))\n\t\ti.LogWriter = f\n\t}\n\ti.Logfile = logfile\n\treturn closeLog, nil\n}\n\n// Serve starts and runs a debug server in the background on the given addr.\n// It also logs the port the server starts on, to allow for :0 auto assigned\n// ports.\nfunc (i *Instance) Serve(ctx context.Context, addr string) (string, error) {\n\tstdlog.SetFlags(stdlog.Lshortfile)\n\tif addr == \"\" {\n\t\treturn \"\", nil\n\t}\n\ti.serveMu.Lock()\n\tdefer i.serveMu.Unlock()\n\n\tif i.listenedDebugAddress != \"\" {\n\t\t// Already serving. Return the bound address.\n\t\treturn i.listenedDebugAddress, nil\n\t}\n\n\ti.debugAddress = addr\n\tlistener, err := net.Listen(\"tcp\", i.debugAddress)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\ti.listenedDebugAddress = listener.Addr().String()\n\n\tport := listener.Addr().(*net.TCPAddr).Port\n\tif strings.HasSuffix(i.debugAddress, \":0\") {\n\t\tstdlog.Printf(\"debug server listening at http://localhost:%d\", port)\n\t}\n\tevent.Log(ctx, \"Debug serving\", label1.Port.Of(port))\n\tgo func() {\n\t\tmux := http.NewServeMux()\n\t\tmux.HandleFunc(\"/\", render(MainTmpl, func(*http.Request) any { return i }))\n\t\tmux.HandleFunc(\"/debug/\", render(DebugTmpl, nil))\n\t\tmux.HandleFunc(\"/debug/pprof/\", pprof.Index)\n\t\tmux.HandleFunc(\"/debug/pprof/cmdline\", cmdline)\n\t\tmux.HandleFunc(\"/debug/pprof/profile\", pprof.Profile)\n\t\tmux.HandleFunc(\"/debug/pprof/symbol\", pprof.Symbol)\n\t\tmux.HandleFunc(\"/debug/pprof/trace\", pprof.Trace)\n\n\t\tif h, err := startFlightRecorder(); err != nil {\n\t\t\tstdlog.Printf(\"failed to start flight recorder: %v\", err) // e.g. go1.24\n\t\t} else {\n\t\t\tmux.HandleFunc(\"/flightrecorder\", h)\n\t\t}\n\n\t\tif i.prometheus != nil {\n\t\t\tmux.HandleFunc(\"/metrics/\", i.prometheus.Serve)\n\t\t}\n\t\tif i.rpcs != nil {\n\t\t\tmux.HandleFunc(\"/rpc/\", render(RPCTmpl, i.rpcs.getData))\n\t\t}\n\t\tif i.traces != nil {\n\t\t\tmux.HandleFunc(\"/trace/\", render(TraceTmpl, i.traces.getData))\n\t\t}\n\t\tmux.HandleFunc(\"/analysis/\", render(AnalysisTmpl, i.getAnalysis))\n\t\tmux.HandleFunc(\"/cache/\", render(CacheTmpl, i.getCache))\n\t\tmux.HandleFunc(\"/session/\", render(SessionTmpl, i.getSession))\n\t\tmux.HandleFunc(\"/client/\", render(ClientTmpl, i.getClient))\n\t\tmux.HandleFunc(\"/server/\", render(ServerTmpl, i.getServer))\n\t\tmux.HandleFunc(\"/file/{session}/{identifier}\", render(FileTmpl, i.getFile))\n\t\tmux.HandleFunc(\"/metadata/{session}/{view}/\", render(MetadataTmpl, i.getMetadata))\n\t\tmux.HandleFunc(\"/package/{session}/{view}/{id...}\", render(PackageTmpl, i.getPackage))\n\t\tmux.HandleFunc(\"/info\", render(InfoTmpl, i.getInfo))\n\t\tmux.HandleFunc(\"/memory\", render(MemoryTmpl, getMemory))\n\n\t\t// Internal debugging helpers.\n\t\tmux.HandleFunc(\"/gc\", func(w http.ResponseWriter, r *http.Request) {\n\t\t\truntime.GC()\n\t\t\truntime.GC()\n\t\t\truntime.GC()\n\t\t\thttp.Redirect(w, r, \"/memory\", http.StatusTemporaryRedirect)\n\t\t})\n\t\tmux.HandleFunc(\"/_makeabug\", func(w http.ResponseWriter, r *http.Request) {\n\t\t\tbug.Report(\"bug here\")\n\t\t\thttp.Error(w, \"made a bug\", http.StatusOK)\n\t\t})\n\n\t\terr := http.Serve(listener, mux) // always non-nil\n\t\tevent.Error(ctx, \"Debug server failed\", err)\n\t}()\n\treturn i.listenedDebugAddress, nil\n}\n\nfunc (i *Instance) DebugAddress() string {\n\ti.serveMu.Lock()\n\tdefer i.serveMu.Unlock()\n\treturn i.debugAddress\n}\n\nfunc (i *Instance) ListenedDebugAddress() string {\n\ti.serveMu.Lock()\n\tdefer i.serveMu.Unlock()\n\treturn i.listenedDebugAddress\n}\n\nfunc makeGlobalExporter(stderr io.Writer) event.Exporter {\n\tvar (\n\t\tpMu sync.Mutex\n\t\tp   export.Printer\n\t)\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\ti := GetInstance(ctx)\n\n\t\tif event.IsLog(ev) {\n\t\t\t// Don't log context cancellation errors.\n\t\t\tif err := keys.Err.Get(ev); errors.Is(err, context.Canceled) {\n\t\t\t\treturn ctx\n\t\t\t}\n\t\t\t// Make sure any log messages without an instance go to stderr.\n\t\t\tif i == nil {\n\t\t\t\tpMu.Lock()\n\t\t\t\tp.WriteEvent(stderr, ev, lm)\n\t\t\t\tpMu.Unlock()\n\t\t\t}\n\t\t\tlevel := log.LabeledLevel(lm)\n\t\t\t// Exclude trace logs from LSP logs.\n\t\t\tif level < log.Trace {\n\t\t\t\tctx = protocol.LogEvent(ctx, ev, lm, messageType(level))\n\t\t\t}\n\t\t}\n\t\tif i == nil {\n\t\t\treturn ctx\n\t\t}\n\t\treturn i.exporter(ctx, ev, lm)\n\t}\n}\n\nfunc messageType(l log.Level) protocol.MessageType {\n\tswitch l {\n\tcase log.Error:\n\t\treturn protocol.Error\n\tcase log.Warning:\n\t\treturn protocol.Warning\n\tcase log.Debug:\n\t\treturn protocol.Log\n\t}\n\treturn protocol.Info\n}\n\nfunc makeInstanceExporter(i *Instance) event.Exporter {\n\texporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tif i.prometheus != nil {\n\t\t\tctx = i.prometheus.ProcessEvent(ctx, ev, lm)\n\t\t}\n\t\tif i.rpcs != nil {\n\t\t\tctx = i.rpcs.ProcessEvent(ctx, ev, lm)\n\t\t}\n\t\tif i.traces != nil {\n\t\t\tctx = i.traces.ProcessEvent(ctx, ev, lm)\n\t\t}\n\t\tif i.otel != nil {\n\t\t\tctx = i.otel.ProcessEvent(ctx, ev, lm)\n\t\t}\n\t\tif event.IsLog(ev) {\n\t\t\tif s := cache.KeyCreateSession.Get(ev); s != nil {\n\t\t\t\ti.State.addClient(s)\n\t\t\t}\n\t\t\tif sid := label1.NewServer.Get(ev); sid != \"\" {\n\t\t\t\ti.State.updateServer(&Server{\n\t\t\t\t\tID:           sid,\n\t\t\t\t\tLogfile:      label1.Logfile.Get(ev),\n\t\t\t\t\tDebugAddress: label1.DebugAddress.Get(ev),\n\t\t\t\t\tGoplsPath:    label1.GoplsPath.Get(ev),\n\t\t\t\t\tClientID:     label1.ClientID.Get(ev),\n\t\t\t\t})\n\t\t\t}\n\t\t\tif s := cache.KeyShutdownSession.Get(ev); s != nil {\n\t\t\t\ti.State.dropClient(s)\n\t\t\t}\n\t\t\tif sid := label1.EndServer.Get(ev); sid != \"\" {\n\t\t\t\ti.State.dropServer(sid)\n\t\t\t}\n\t\t\tif s := cache.KeyUpdateSession.Get(ev); s != nil {\n\t\t\t\tif c := i.State.Client(s.ID()); c != nil {\n\t\t\t\t\tc.DebugAddress = label1.DebugAddress.Get(ev)\n\t\t\t\t\tc.Logfile = label1.Logfile.Get(ev)\n\t\t\t\t\tc.ServerID = label1.ServerID.Get(ev)\n\t\t\t\t\tc.GoplsPath = label1.GoplsPath.Get(ev)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ctx\n\t}\n\t// StdTrace must be above export.Spans below (by convention, export\n\t// middleware applies its wrapped exporter last).\n\texporter = StdTrace(exporter)\n\tmetrics := metric.Config{}\n\tregisterMetrics(&metrics)\n\texporter = metrics.Exporter(exporter)\n\texporter = export.Spans(exporter)\n\texporter = export.Labels(exporter)\n\treturn exporter\n}\n\ntype dataFunc func(*http.Request) any\n\nfunc render(tmpl *template.Template, fun dataFunc) func(http.ResponseWriter, *http.Request) {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tvar data any\n\t\tif fun != nil {\n\t\t\tdata = fun(r)\n\t\t}\n\t\tif err := tmpl.Execute(w, data); err != nil {\n\t\t\tevent.Error(context.Background(), \"\", err)\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t}\n\t}\n}\n\nfunc commas(s string) string {\n\tfor i := len(s); i > 3; {\n\t\ti -= 3\n\t\ts = s[:i] + \",\" + s[i:]\n\t}\n\treturn s\n}\n\nfunc fuint64(v uint64) string {\n\treturn commas(strconv.FormatUint(v, 10))\n}\n\nfunc fuint32(v uint32) string {\n\treturn commas(strconv.FormatUint(uint64(v), 10))\n}\n\nfunc fcontent(v []byte) string {\n\treturn string(v)\n}\n\nvar BaseTemplate = template.Must(template.New(\"\").Parse(`\n<html>\n<head>\n<title>{{template \"title\" .}}</title>\n<style>\n.profile-name{\n\tdisplay:inline-block;\n\twidth:6rem;\n}\ntd.value {\n\ttext-align: right;\n}\nul.spans {\n\tfont-family: monospace;\n\tfont-size:   85%;\n}\nbody {\n\tfont-family: sans-serif;\n\tfont-size: 1rem;\n\tline-height: normal;\n}\n</style>\n{{block \"head\" .}}{{end}}\n</head>\n<body>\n<a href=\"/\">Main</a>\n<a href=\"/info\">Info</a>\n<a href=\"/memory\">Memory</a>\n<a href=\"/debug/pprof\">Profiling</a>\n<a href=\"/metrics\">Metrics</a>\n<a href=\"/rpc\">RPC</a>\n<a href=\"/trace\">Trace</a>\n<a href=\"/flightrecorder\">Flight recorder</a>\n<a href=\"/analysis\">Analysis</a>\n<hr>\n<h1>{{template \"title\" .}}</h1>\n{{block \"body\" .}}\nUnknown page\n{{end}}\n</body>\n</html>\n\n{{define \"cachelink\"}}<a href=\"/cache/{{.}}\">Cache {{.}}</a>{{end}}\n{{define \"clientlink\"}}<a href=\"/client/{{.}}\">Client {{.}}</a>{{end}}\n{{define \"serverlink\"}}<a href=\"/server/{{.}}\">Server {{.}}</a>{{end}}\n{{define \"sessionlink\"}}<a href=\"/session/{{.}}\">Session {{.}}</a>{{end}}\n`)).Funcs(template.FuncMap{\n\t\"fuint64\":  fuint64,\n\t\"fuint32\":  fuint32,\n\t\"fcontent\": fcontent,\n\t\"localAddress\": func(s string) string {\n\t\t// Try to translate loopback addresses to localhost, both for cosmetics and\n\t\t// because unspecified ipv6 addresses can break links on Windows.\n\t\t//\n\t\t// TODO(rfindley): In the future, it would be better not to assume the\n\t\t// server is running on localhost, and instead construct this address using\n\t\t// the remote host.\n\t\thost, port, err := net.SplitHostPort(s)\n\t\tif err != nil {\n\t\t\treturn s\n\t\t}\n\t\tip := net.ParseIP(host)\n\t\tif ip == nil {\n\t\t\treturn s\n\t\t}\n\t\tif ip.IsLoopback() || ip.IsUnspecified() {\n\t\t\treturn \"localhost:\" + port\n\t\t}\n\t\treturn s\n\t},\n\t// TODO(rfindley): re-enable option inspection.\n\t// \"options\": func(s *cache.Session) []sessionOption {\n\t// \treturn showOptions(s.Options())\n\t// },\n})\n\nvar MainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Gopls server information{{end}}\n{{define \"body\"}}\n<h2>Caches</h2>\n<ul>{{range .State.Caches}}<li>{{template \"cachelink\" .ID}}</li>{{end}}</ul>\n<h2>Sessions</h2>\n<ul>{{range .State.Sessions}}<li>{{template \"sessionlink\" .ID}} from {{template \"cachelink\" .Cache.ID}}</li>{{end}}</ul>\n<h2>Clients</h2>\n<ul>{{range .State.Clients}}<li>{{template \"clientlink\" .Session.ID}}</li>{{end}}</ul>\n<h2>Servers</h2>\n<ul>{{range .State.Servers}}<li>{{template \"serverlink\" .ID}}</li>{{end}}</ul>\n<h2>Bug reports</h2>\n<dl>{{range .State.Bugs}}<dt>{{.Key}}</dt><dd>{{.Description}}</dd>{{end}}</dl>\n{{end}}\n`))\n\nvar InfoTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Gopls version information{{end}}\n{{define \"body\"}}\n{{.}}\n{{end}}\n`))\n\nvar MemoryTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Gopls memory usage{{end}}\n{{define \"head\"}}<meta http-equiv=\"refresh\" content=\"5\">{{end}}\n{{define \"body\"}}\n<form action=\"/gc\"><input type=\"submit\" value=\"Run garbage collector\"/></form>\n<h2>Stats</h2>\n<table>\n<tr><td class=\"label\">Allocated bytes</td><td class=\"value\">{{fuint64 .HeapAlloc}}</td></tr>\n<tr><td class=\"label\">Total allocated bytes</td><td class=\"value\">{{fuint64 .TotalAlloc}}</td></tr>\n<tr><td class=\"label\">System bytes</td><td class=\"value\">{{fuint64 .Sys}}</td></tr>\n<tr><td class=\"label\">Heap system bytes</td><td class=\"value\">{{fuint64 .HeapSys}}</td></tr>\n<tr><td class=\"label\">Malloc calls</td><td class=\"value\">{{fuint64 .Mallocs}}</td></tr>\n<tr><td class=\"label\">Frees</td><td class=\"value\">{{fuint64 .Frees}}</td></tr>\n<tr><td class=\"label\">Idle heap bytes</td><td class=\"value\">{{fuint64 .HeapIdle}}</td></tr>\n<tr><td class=\"label\">In use bytes</td><td class=\"value\">{{fuint64 .HeapInuse}}</td></tr>\n<tr><td class=\"label\">Released to system bytes</td><td class=\"value\">{{fuint64 .HeapReleased}}</td></tr>\n<tr><td class=\"label\">Heap object count</td><td class=\"value\">{{fuint64 .HeapObjects}}</td></tr>\n<tr><td class=\"label\">Stack in use bytes</td><td class=\"value\">{{fuint64 .StackInuse}}</td></tr>\n<tr><td class=\"label\">Stack from system bytes</td><td class=\"value\">{{fuint64 .StackSys}}</td></tr>\n<tr><td class=\"label\">Bucket hash bytes</td><td class=\"value\">{{fuint64 .BuckHashSys}}</td></tr>\n<tr><td class=\"label\">GC metadata bytes</td><td class=\"value\">{{fuint64 .GCSys}}</td></tr>\n<tr><td class=\"label\">Off heap bytes</td><td class=\"value\">{{fuint64 .OtherSys}}</td></tr>\n</table>\n<h2>By size</h2>\n<table>\n<tr><th>Size</th><th>Mallocs</th><th>Frees</th></tr>\n{{range .BySize}}<tr><td class=\"value\">{{fuint32 .Size}}</td><td class=\"value\">{{fuint64 .Mallocs}}</td><td class=\"value\">{{fuint64 .Frees}}</td></tr>{{end}}\n</table>\n{{end}}\n`))\n\nvar DebugTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}GoPls Debug pages{{end}}\n{{define \"body\"}}\n<a href=\"/debug/pprof\">Profiling</a>\n{{end}}\n`))\n\nvar CacheTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Cache {{.ID}}{{end}}\n{{define \"body\"}}\n<h2>memoize.Store entries</h2>\n<ul>{{range $k,$v := .MemStats}}<li>{{$k}} - {{$v}}</li>{{end}}</ul>\n<h2>File stats</h2>\n<p>\n{{- $stats := .FileStats -}}\nTotal: <b>{{$stats.Total}}</b><br>\nLargest: <b>{{$stats.Largest}}</b><br>\nErrors: <b>{{$stats.Errs}}</b><br>\n</p>\n{{end}}\n`))\n\nvar AnalysisTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Analysis{{end}}\n{{define \"body\"}}\n<h2>Analyzer.Run times</h2>\n<ul>{{range .AnalyzerRunTimes}}<li>{{.Duration}} {{.Label}}</li>{{end}}</ul>\n{{end}}\n`))\n\nvar ClientTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Client {{.Session.ID}}{{end}}\n{{define \"body\"}}\nUsing session: <b>{{template \"sessionlink\" .Session.ID}}</b><br>\n{{if .DebugAddress}}Debug this client at: <a href=\"http://{{localAddress .DebugAddress}}\">{{localAddress .DebugAddress}}</a><br>{{end}}\nLogfile: {{.Logfile}}<br>\nGopls Path: {{.GoplsPath}}<br>\n{{end}}\n`))\n\nvar ServerTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Server {{.ID}}{{end}}\n{{define \"body\"}}\n{{if .DebugAddress}}Debug this server at: <a href=\"http://{{localAddress .DebugAddress}}\">{{localAddress .DebugAddress}}</a><br>{{end}}\nLogfile: {{.Logfile}}<br>\nGopls Path: {{.GoplsPath}}<br>\n{{end}}\n`))\n\nvar SessionTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Session {{.ID}}{{end}}\n{{define \"body\"}}\nFrom: <b>{{template \"cachelink\" .Cache.ID}}</b><br>\n{{- $session := . -}}\n\n<h2>Views</h2>\n<ul>{{range .Views}}\n{{- $envOverlay := .EnvOverlay -}}\n<li>ID: <b>{{.ID}}</b><br>\nType: <b>{{.Type}}</b><br>\nRoot: <b>{{.Root}}</b><br>\n{{- if $envOverlay}}\nEnv overlay: <b>{{$envOverlay}})</b><br>\n{{end -}}\nFolder.Name: <b>{{.Folder.Name}}</b><br>\nFolder.Dir: <b>{{.Folder.Dir}}</b><br/>\n<a href=\"/metadata/{{$session.ID}}/{{.ID}}\">Latest metadata</a><br/>\n\nSettings:<br/>\n<ul>\n{{range .Folder.Options.Debug}}<li>{{.}}</li>\n{{end}}\n</ul>\n{{end}}</ul>\n\n<h2>Overlays</h2>\n{{$session := .}}\n<ul>{{range .Overlays}}\n<li>\n<a href=\"/file/{{$session.ID}}/{{.Identity.Hash}}\">{{.Identity.URI}}</a>\n</li>{{end}}</ul>\n{{end}}\n`))\n\n// For /file endpoint; operand is [FileWithKind].\nvar FileTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Overlay {{.Identity.Hash}}{{end}}\n{{define \"body\"}}\n{{with .}}\n\tURI: <b>{{.URI}}</b><br>\n\tIdentifier: <b>{{.Identity.Hash}}</b><br>\n\tVersion: <b>{{.Version}}</b><br>\n\tKind: <b>{{.Kind}}</b><br>\n{{end}}\n<h3>Contents</h3>\n<pre>{{fcontent .Content}}</pre>\n{{end}}\n`))\n\n// For /metadata endpoint; operand is [*MetadataInfo].\nvar MetadataTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Metadata graph{{end}}\n{{define \"body\"}}\n\n<p><a href='#hdr-Files'>↓ Index by file</a></p>\n\n<h3>Packages ({{len .Graph.Packages}})</h3>\n<ul>\n{{range $id, $pkg := .Graph.Packages}}\n<li id='{{$id}}'><b>{{$id}}</b>\n{{with $pkg}}\n<ul>\n <li>Name: {{.Name}}</li>\n <li>PkgPath: {{printf \"%q\" .PkgPath}}</li>\n {{if .Module}}<li>Module: {{printf \"%#v\" .Module}}</li>{{end}}\n <li><a href=\"/package/{{$.SessionID}}/{{$.ViewID}}/{{$id}}\">Type information</a></li>\n {{if .ForTest}}<li>ForTest: {{.ForTest}}</li>{{end}}\n {{if .Standalone}}<li>Standalone</li>{{end}}\n {{if .Errors}}<li>Errors: {{.Errors}}</li>{{end}}\n {{if .DepsErrors}}<li>DepsErrors: {{.DepsErrors}}</li>{{end}}\n <li>LoadDir: {{.LoadDir}}</li>\n <li>DepsByImpPath\n  <ul>\n   {{range $path, $id := .DepsByImpPath}}\n    <li>{{if $id}}<a href='#{{$id}}'>{{printf \"%q\" $path}}</a>{{else}}⚠️ {{printf \"%q\" $path}} missing{{end}}</li>\n   {{end}}\n  </ul>\n </li>\n {{if .GoFiles}}<li>GoFiles: <ul>{{range .GoFiles}}<li>{{.}}</li>{{end}}</ul></li>{{end}}\n {{if .CompiledGoFiles}}<li>CompiledGoFiles: <ul>{{range .CompiledGoFiles}}<li>{{.}}</li>{{end}}</ul></li>{{end}}\n {{if .IgnoredFiles}}<li>IgnoredFiles: <ul>{{range .IgnoredFiles}}<li>{{.}}</li>{{end}}</ul></li>{{end}}\n {{if .OtherFiles}}<li>OtherFiles: <ul>{{range .OtherFiles}}<li>{{.}}</li>{{end}}</ul></li>{{end}}\n <!-- skip DepsByPkgPath, ImportedBy (redundant indexes) -->\n</ul>\n{{end}}\n</li>\n{{end}}\n</ul>\n\n<h3 id='hdr-Files'>Files</h3>\n<ul>\n{{range $uri, $pkgs := .Graph.ForFile}}<li>{{$uri}} →{{range $pkgs}} <a href='#{{.ID}}'>{{.ID}}</a>{{end}}</li>{{end}}\n</ul>\n\n{{end}}\n`))\n\n// For /package endpoint; operand is [*PackageInfo].\nvar PackageTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Package {{.Package.Metadata.ID}}{{end}}\n{{define \"body\"}}\n\n<ul>\n<li><a href=\"/metadata/{{.SessionID}}/{{.ViewID}}#{{.Package.Metadata.ID}}\">Metadata</a></li>\n</ul>\n\n<h2>Diagnostics for syntax and type (but not analysis) errors</h2>\n<ul>\n {{range $url, $diags := .Diagnostics}}\n <li>{{$url}}\n  <ul>\n  {{range $diag := $diags}}\n  <li>{{$diag.Range}}: [{{$diag.Severity}}] {{$diag.Message}}<br/>\n  <ul>\n    <li>code {{$diag.Code}}</li>\n    <li>code href {{$diag.CodeHref}}</li>\n    <li>source {{$diag.Source}}</li>\n    <li>tags {{$diag.Tags}}</li>\n    <li>related {{$diag.Related}}</li> {{/*TODO: improve*/}}\n    <li>bundled fixes {{$diag.BundledFixes}}</li> {{/*TODO: improve*/}}\n    <li>fixes {{$diag.SuggestedFixes}}</li> {{/*TODO: improve*/}}\n  </ul>\n  {{end}}\n </ul>\n {{end}}\n</ul>\n\n{{end}}\n{{/*\nTODO:\n - link to godoc (tricky: in server package)\n - show Object inventory of types.Package.Scope\n - show index info (xrefs, methodsets, tests)\n - call DiagnoseFile on each file?\n*/}}\n`))\n"
  },
  {
    "path": "gopls/internal/debug/template_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug_test\n\n// Provide 'static type checking' of the templates. This guards against changes in various\n// gopls datastructures causing template execution to fail. The checking is done by\n// the github.com/jba/templatecheck package. Before that is run, the test checks that\n// its list of templates and their arguments corresponds to the arguments in\n// calls to render(). The test assumes that all uses of templates are done through render().\n\nimport (\n\t\"go/ast\"\n\t\"html/template\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/jba/templatecheck\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar templates = map[string]struct {\n\ttmpl *template.Template\n\tdata any // a value of the needed type\n}{\n\t\"MainTmpl\":     {debug.MainTmpl, &debug.Instance{}},\n\t\"DebugTmpl\":    {debug.DebugTmpl, nil},\n\t\"RPCTmpl\":      {debug.RPCTmpl, &debug.Rpcs{}},\n\t\"TraceTmpl\":    {debug.TraceTmpl, debug.TraceResults{}},\n\t\"CacheTmpl\":    {debug.CacheTmpl, &cache.Cache{}},\n\t\"SessionTmpl\":  {debug.SessionTmpl, &cache.Session{}},\n\t\"ClientTmpl\":   {debug.ClientTmpl, &debug.Client{}},\n\t\"ServerTmpl\":   {debug.ServerTmpl, &debug.Server{}},\n\t\"FileTmpl\":     {debug.FileTmpl, *new(debug.FileWithKind)},\n\t\"MetadataTmpl\": {debug.MetadataTmpl, new(debug.MetadataInfo)},\n\t\"PackageTmpl\":  {debug.PackageTmpl, new(debug.PackageInfo)},\n\t\"InfoTmpl\":     {debug.InfoTmpl, \"something\"},\n\t\"MemoryTmpl\":   {debug.MemoryTmpl, runtime.MemStats{}},\n\t\"AnalysisTmpl\": {debug.AnalysisTmpl, new(debug.State).Analysis()},\n}\n\nfunc TestTemplates(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.NeedsLocalXTools(t)\n\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo,\n\t}\n\tcfg.Env = os.Environ()\n\tcfg.Env = append(cfg.Env,\n\t\t\"GOPACKAGESDRIVER=off\",\n\t\t\"GOWORK=off\", // necessary for -mod=mod below\n\t\t\"GOFLAGS=-mod=mod\",\n\t)\n\n\tpkgs, err := packages.Load(cfg, \"golang.org/x/tools/gopls/internal/debug\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(pkgs) != 1 {\n\t\tt.Fatalf(\"expected a single package, but got %d\", len(pkgs))\n\t}\n\tp := pkgs[0]\n\tif len(p.Errors) != 0 {\n\t\tt.Fatalf(\"compiler error, e.g. %v\", p.Errors[0])\n\t}\n\t// find the calls to render in serve.go\n\ttree := treeOf(p, \"serve.go\")\n\tif tree == nil {\n\t\tt.Fatalf(\"found no syntax tree for %s\", \"serve.go\")\n\t}\n\trenders := callsOf(tree, \"render\")\n\tif len(renders) == 0 {\n\t\tt.Fatalf(\"found no calls to render\")\n\t}\n\tvar found = make(map[string]bool)\n\tfor _, r := range renders {\n\t\tif len(r.Args) != 2 {\n\t\t\t// template, func\n\t\t\tt.Fatalf(\"got %d args, expected 2\", len(r.Args))\n\t\t}\n\t\tt0, ok := p.TypesInfo.Types[r.Args[0]]\n\t\tif !ok || !t0.IsValue() || t0.Type.String() != \"*html/template.Template\" {\n\t\t\tt.Fatalf(\"no type info for template\")\n\t\t}\n\t\tif id, ok := r.Args[0].(*ast.Ident); !ok {\n\t\t\tt.Errorf(\"expected *ast.Ident, got %T\", r.Args[0])\n\t\t} else {\n\t\t\tfound[id.Name] = true\n\t\t}\n\t}\n\t// make sure found and templates have the same templates\n\tfor k := range found {\n\t\tif _, ok := templates[k]; !ok {\n\t\t\tt.Errorf(\"code has template %s, but test does not\", k)\n\t\t}\n\t}\n\tfor k := range templates {\n\t\tif _, ok := found[k]; !ok {\n\t\t\tt.Errorf(\"test has template %s, code does not\", k)\n\t\t}\n\t}\n\t// now check all the known templates, in alphabetic order, for determinacy\n\tfor k, v := range moremaps.Sorted(templates) {\n\t\t// the FuncMap is an annoyance; should not be necessary\n\t\tif err := templatecheck.CheckHTML(v.tmpl, v.data); err != nil {\n\t\t\tt.Errorf(\"%s: %v\", k, err)\n\t\t\tcontinue\n\t\t}\n\t\tt.Logf(\"%s ok\", k)\n\t}\n}\n\nfunc callsOf(tree *ast.File, name string) []*ast.CallExpr {\n\tvar ans []*ast.CallExpr\n\tf := func(n ast.Node) bool {\n\t\tx, ok := n.(*ast.CallExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif y, ok := x.Fun.(*ast.Ident); ok {\n\t\t\tif y.Name == name {\n\t\t\t\tans = append(ans, x)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\tast.Inspect(tree, f)\n\treturn ans\n}\n\nfunc treeOf(p *packages.Package, fname string) *ast.File {\n\tfor _, tree := range p.Syntax {\n\t\tloc := tree.Package\n\t\tpos := p.Fset.PositionFor(loc, false)\n\t\tif strings.HasSuffix(pos.Filename, fname) {\n\t\t\treturn tree\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/debug/trace.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"runtime/trace\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// TraceTmpl extends BaseTemplate and renders a TraceResults, e.g. from getData().\nvar TraceTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`\n{{define \"title\"}}Trace Information{{end}}\n{{define \"body\"}}\n\t{{range .Traces}}<a href=\"/trace/{{.Name}}\">{{.Name}}</a> last: {{.Last.Duration}}, longest: {{.Longest.Duration}}<br>{{end}}\n\t{{if .Selected}}\n\t\t<H2>{{.Selected.Name}}</H2>\n\t\t{{if .Selected.Last}}<H3>Last</H3><ul class='spans'>{{template \"completeSpan\" .Selected.Last}}</ul>{{end}}\n\t\t{{if .Selected.Longest}}<H3>Longest</H3><ul class='spans'>{{template \"completeSpan\" .Selected.Longest}}</ul>{{end}}\n\t{{end}}\n\n        <H2>Recent spans (oldest first)</H2>\n        <p>\n        A finite number of recent span start/end times are shown below.\n        The nesting represents the children of a parent span (and the log events within a span).\n        A span may appear twice: chronologically at toplevel, and nested within its parent.\n        </p>\n\t<ul class='spans'>{{range .Recent}}{{template \"spanStartEnd\" .}}{{end}}</ul>\n{{end}}\n{{define \"spanStartEnd\"}}\n\t{{if .Start}}\n\t\t<li>{{.Span.Header .Start}}</li>\n\t{{else}}\n\t\t{{template \"completeSpan\" .Span}}\n\t{{end}}\n{{end}}\n{{define \"completeSpan\"}}\n\t<li>{{.Header false}}</li>\n\t{{if .Events}}<ul>{{range .Events}}<li>{{.Header}}</li>{{end}}</ul>{{end}}\n\t{{if .ChildStartEnd}}<ul>{{range .ChildStartEnd}}{{template \"spanStartEnd\" .}}{{end}}</ul>{{end}}\n{{end}}\n`))\n\ntype traces struct {\n\tmu              sync.Mutex\n\tsets            map[string]*traceSet\n\tunfinished      map[export.SpanContext]*traceSpan\n\trecent          []spanStartEnd\n\trecentEvictions int\n}\n\n// A spanStartEnd records the start or end of a span.\n// If Start, the span may be unfinished, so some fields (e.g. Finish)\n// may be unset and others (e.g. Events) may be being actively populated.\ntype spanStartEnd struct {\n\tStart bool\n\tSpan  *traceSpan\n}\n\nfunc (ev spanStartEnd) Time() time.Time {\n\tif ev.Start {\n\t\treturn ev.Span.Start\n\t} else {\n\t\treturn ev.Span.Finish\n\t}\n}\n\n// A TraceResults is the subject for the /trace HTML template.\ntype TraceResults struct { // exported for testing\n\tTraces   []*traceSet\n\tSelected *traceSet\n\tRecent   []spanStartEnd\n}\n\n// A traceSet holds two representative spans of a given span name.\ntype traceSet struct {\n\tName    string\n\tLast    *traceSpan\n\tLongest *traceSpan\n}\n\n// A traceSpan holds information about a single span.\ntype traceSpan struct {\n\tTraceID       export.TraceID\n\tSpanID        export.SpanID\n\tParentID      export.SpanID\n\tName          string\n\tStart         time.Time\n\tFinish        time.Time     // set at end\n\tDuration      time.Duration // set at end\n\tTags          string\n\tEvents        []traceEvent   // set at end\n\tChildStartEnd []spanStartEnd // populated while active\n\n\tparent *traceSpan\n}\n\nconst timeFormat = \"15:04:05.000\"\n\n// Header renders the time, name, tags, and (if !start),\n// duration of a span start or end event.\nfunc (span *traceSpan) Header(start bool) string {\n\tif start {\n\t\treturn fmt.Sprintf(\"%s start %s %s\",\n\t\t\tspan.Start.Format(timeFormat), span.Name, span.Tags)\n\t} else {\n\t\treturn fmt.Sprintf(\"%s end %s (+%s) %s\",\n\t\t\tspan.Finish.Format(timeFormat), span.Name, span.Duration, span.Tags)\n\t}\n}\n\ntype traceEvent struct {\n\tTime   time.Time\n\tOffset time.Duration // relative to start of span\n\tTags   string\n}\n\nfunc (ev traceEvent) Header() string {\n\treturn fmt.Sprintf(\"%s event (+%s) %s\", ev.Time.Format(timeFormat), ev.Offset, ev.Tags)\n}\n\nfunc StdTrace(exporter event.Exporter) event.Exporter {\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tspan := export.GetSpan(ctx)\n\t\tif span == nil {\n\t\t\treturn exporter(ctx, ev, lm)\n\t\t}\n\t\tswitch {\n\t\tcase event.IsStart(ev):\n\t\t\tif span.ParentID.IsValid() {\n\t\t\t\tregion := trace.StartRegion(ctx, span.Name)\n\t\t\t\tctx = context.WithValue(ctx, traceKey, region)\n\t\t\t} else {\n\t\t\t\tvar task *trace.Task\n\t\t\t\tctx, task = trace.NewTask(ctx, span.Name)\n\t\t\t\tctx = context.WithValue(ctx, traceKey, task)\n\t\t\t}\n\t\t\t// Log the start event as it may contain useful labels.\n\t\t\tmsg := formatEvent(ev, lm)\n\t\t\ttrace.Log(ctx, \"start\", msg)\n\t\tcase event.IsLog(ev):\n\t\t\tcategory := \"\"\n\t\t\tif event.IsError(ev) {\n\t\t\t\tcategory = \"error\"\n\t\t\t}\n\t\t\tmsg := formatEvent(ev, lm)\n\t\t\ttrace.Log(ctx, category, msg)\n\t\tcase event.IsEnd(ev):\n\t\t\tif v := ctx.Value(traceKey); v != nil {\n\t\t\t\tv.(interface{ End() }).End()\n\t\t\t}\n\t\t}\n\t\treturn exporter(ctx, ev, lm)\n\t}\n}\n\nfunc formatEvent(ev core.Event, lm label.Map) string {\n\tbuf := &bytes.Buffer{}\n\tp := export.Printer{}\n\tp.WriteEvent(buf, ev, lm)\n\treturn buf.String()\n}\n\nfunc (t *traces) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\tspan := export.GetSpan(ctx)\n\tif span == nil {\n\t\treturn ctx\n\t}\n\n\tswitch {\n\tcase event.IsStart(ev):\n\t\t// Just starting: add it to the unfinished map.\n\t\t// Allocate before the critical section.\n\t\ttd := &traceSpan{\n\t\t\tTraceID:  span.ID.TraceID,\n\t\t\tSpanID:   span.ID.SpanID,\n\t\t\tParentID: span.ParentID,\n\t\t\tName:     span.Name,\n\t\t\tStart:    span.Start().At(),\n\t\t\tTags:     renderLabels(span.Start()),\n\t\t}\n\n\t\tt.mu.Lock()\n\t\tdefer t.mu.Unlock()\n\n\t\tt.addRecentLocked(td, true) // add start event\n\n\t\tif t.sets == nil {\n\t\t\tt.sets = make(map[string]*traceSet)\n\t\t\tt.unfinished = make(map[export.SpanContext]*traceSpan)\n\t\t}\n\t\tt.unfinished[span.ID] = td\n\n\t\t// Wire up parents if we have them.\n\t\tif span.ParentID.IsValid() {\n\t\t\tparentID := export.SpanContext{TraceID: span.ID.TraceID, SpanID: span.ParentID}\n\t\t\tif parent, ok := t.unfinished[parentID]; ok {\n\t\t\t\ttd.parent = parent\n\t\t\t\tparent.ChildStartEnd = append(parent.ChildStartEnd, spanStartEnd{true, td})\n\t\t\t}\n\t\t}\n\n\tcase event.IsEnd(ev):\n\t\t// Finishing: must be already in the map.\n\t\t// Allocate events before the critical section.\n\t\tevents := span.Events()\n\t\ttdEvents := make([]traceEvent, len(events))\n\t\tfor i, event := range events {\n\t\t\ttdEvents[i] = traceEvent{\n\t\t\t\tTime: event.At(),\n\t\t\t\tTags: renderLabels(event),\n\t\t\t}\n\t\t}\n\n\t\tt.mu.Lock()\n\t\tdefer t.mu.Unlock()\n\t\ttd, found := t.unfinished[span.ID]\n\t\tif !found {\n\t\t\treturn ctx // if this happens we are in a bad place\n\t\t}\n\t\tdelete(t.unfinished, span.ID)\n\t\ttd.Finish = span.Finish().At()\n\t\ttd.Duration = span.Finish().At().Sub(span.Start().At())\n\t\ttd.Events = tdEvents\n\t\tt.addRecentLocked(td, false) // add end event\n\n\t\tset, ok := t.sets[span.Name]\n\t\tif !ok {\n\t\t\tset = &traceSet{Name: span.Name}\n\t\t\tt.sets[span.Name] = set\n\t\t}\n\t\tset.Last = td\n\t\tif set.Longest == nil || set.Last.Duration > set.Longest.Duration {\n\t\t\tset.Longest = set.Last\n\t\t}\n\t\tif td.parent != nil {\n\t\t\ttd.parent.ChildStartEnd = append(td.parent.ChildStartEnd, spanStartEnd{false, td})\n\t\t} else {\n\t\t\tfillOffsets(td, td.Start)\n\t\t}\n\t}\n\treturn ctx\n}\n\n// addRecentLocked appends a start or end event to the \"recent\" log,\n// evicting an old entry if necessary.\nfunc (t *traces) addRecentLocked(span *traceSpan, start bool) {\n\tt.recent = append(t.recent, spanStartEnd{Start: start, Span: span})\n\n\tconst maxRecent = 100 // number of log entries before eviction\n\tfor len(t.recent) > maxRecent {\n\t\tt.recent[0] = spanStartEnd{} // aid GC\n\t\tt.recent = t.recent[1:]\n\t\tt.recentEvictions++\n\n\t\t// Using a slice as a FIFO queue leads to unbounded growth\n\t\t// as Go's GC cannot collect the ever-growing unused prefix.\n\t\t// So, compact it periodically.\n\t\tif t.recentEvictions%maxRecent == 0 {\n\t\t\tt.recent = slices.Clone(t.recent)\n\t\t}\n\t}\n}\n\n// getData returns the TraceResults rendered by TraceTmpl for the /trace[/name] endpoint.\nfunc (t *traces) getData(req *http.Request) any {\n\t// TODO(adonovan): the HTTP request doesn't acquire the mutex\n\t// for t or for each span! Audit and fix.\n\n\t// Sort last/longest sets by name.\n\ttraces := make([]*traceSet, 0, len(t.sets))\n\tfor _, set := range t.sets {\n\t\ttraces = append(traces, set)\n\t}\n\tsort.Slice(traces, func(i, j int) bool {\n\t\treturn traces[i].Name < traces[j].Name\n\t})\n\n\treturn TraceResults{\n\t\tTraces:   traces,\n\t\tSelected: t.sets[strings.TrimPrefix(req.URL.Path, \"/trace/\")], // may be nil\n\t\tRecent:   t.recent,\n\t}\n}\n\nfunc fillOffsets(td *traceSpan, start time.Time) {\n\tfor i := range td.Events {\n\t\ttd.Events[i].Offset = td.Events[i].Time.Sub(start)\n\t}\n\tfor _, child := range td.ChildStartEnd {\n\t\tif !child.Start {\n\t\t\tfillOffsets(child.Span, start)\n\t\t}\n\t}\n}\n\nfunc renderLabels(labels label.List) string {\n\tbuf := &bytes.Buffer{}\n\tfor index := 0; labels.Valid(index); index++ {\n\t\t// The 'start' label duplicates the span name, so discard it.\n\t\tif l := labels.Label(index); l.Valid() && l.Key().Name() != \"start\" {\n\t\t\tfmt.Fprintf(buf, \"%v \", l)\n\t\t}\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "gopls/internal/doc/api.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run ./generate\n\n// The doc package provides JSON metadata that documents gopls' public\n// interfaces.\npackage doc\n\nimport _ \"embed\"\n\n// JSON is a JSON encoding of value of type API.\n// The 'gopls api-json' command prints it.\n//\n//go:embed api.json\nvar JSON string\n\n// API is a JSON-encodable representation of gopls' public interfaces.\n//\n// TODO(adonovan): document these data types.\ntype API struct {\n\tOptions   map[string][]*Option\n\tLenses    []*Lens\n\tAnalyzers []*Analyzer\n\tHints     []*Hint\n}\n\ntype Option struct {\n\tName               string\n\tType               string // T = bool | string | int | enum | any | []T | map[T]T | time.Duration\n\tDoc                string\n\tEnumKeys           EnumKeys\n\tEnumValues         []EnumValue\n\tDefault            string\n\tStatus             string\n\tHierarchy          string\n\tDeprecationMessage string\n}\n\ntype EnumKeys struct {\n\tValueType string\n\tKeys      []EnumKey\n}\n\ntype EnumKey struct {\n\tName    string // in JSON syntax (quoted)\n\tDoc     string\n\tDefault string\n\tStatus  string // = \"\" | \"advanced\" | \"experimental\" | \"deprecated\"\n}\n\ntype EnumValue struct {\n\tValue  string // in JSON syntax (quoted)\n\tDoc    string // doc comment; always starts with `Value`\n\tStatus string // = \"\" | \"advanced\" | \"experimental\" | \"deprecated\"\n}\n\ntype Lens struct {\n\tFileType string // e.g. \"Go\", \"go.mod\"\n\tLens     string\n\tTitle    string\n\tDoc      string\n\tDefault  bool\n\tStatus   string // = \"\" | \"advanced\" | \"experimental\" | \"deprecated\"\n}\n\ntype Analyzer struct {\n\tName    string\n\tDoc     string // from analysis.Analyzer.Doc (\"title: summary\\ndescription\"; go/doc/comment, not Markdown)\n\tURL     string\n\tDefault bool\n}\n\ntype Hint struct {\n\tName    string\n\tDoc     string\n\tDefault bool\n\tStatus  string // = \"\" | \"advanced\" | \"experimental\" | \"deprecated\"\n}\n"
  },
  {
    "path": "gopls/internal/doc/api.json",
    "content": "{\n\t\"Options\": {\n\t\t\"User\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"buildFlags\",\n\t\t\t\t\"Type\": \"[]string\",\n\t\t\t\t\"Doc\": \"buildFlags is the set of flags passed on to the build system when invoked.\\nIt is applied to queries like `go list`, which is used when discovering files.\\nThe most common use is to set `-tags`.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"[]\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"env\",\n\t\t\t\t\"Type\": \"map[string]string\",\n\t\t\t\t\"Doc\": \"env adds environment variables to external commands run by `gopls`, most notably `go list`.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{}\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"directoryFilters\",\n\t\t\t\t\"Type\": \"[]string\",\n\t\t\t\t\"Doc\": \"directoryFilters can be used to exclude unwanted directories from the\\nworkspace. By default, all directories are included. Filters are an\\noperator, `+` to include and `-` to exclude, followed by a path prefix\\nrelative to the workspace folder. They are evaluated in order, and\\nthe last filter that applies to a path controls whether it is included.\\nThe path prefix can be empty, so an initial `-` excludes everything.\\n\\nDirectoryFilters also supports the `**` operator to match 0 or more directories.\\n\\nExamples:\\n\\nExclude node_modules at current depth: `-node_modules`\\n\\nExclude node_modules at any depth: `-**/node_modules`\\n\\nInclude only project_a: `-` (exclude everything), `+project_a`\\n\\nInclude only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"[\\\"-**/node_modules\\\"]\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"templateExtensions\",\n\t\t\t\t\"Type\": \"[]string\",\n\t\t\t\t\"Doc\": \"templateExtensions gives the extensions of file names that are treated\\nas template files. (The extension\\nis the part of the file name after the final dot.)\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"[]\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"memoryMode\",\n\t\t\t\t\"Type\": \"string\",\n\t\t\t\t\"Doc\": \"obsolete, no effect\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"\\\"\\\"\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"expandWorkspaceToModule\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"expandWorkspaceToModule determines which packages are considered\\n\\\"workspace packages\\\" when the workspace is using modules.\\n\\nWorkspace packages affect the scope of workspace-wide operations. Notably,\\ngopls diagnoses all packages considered to be part of the workspace after\\nevery keystroke, so by setting \\\"ExpandWorkspaceToModule\\\" to false, and\\nopening a nested workspace directory, you can reduce the amount of work\\ngopls has to do to keep your workspace up to date.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"standaloneTags\",\n\t\t\t\t\"Type\": \"[]string\",\n\t\t\t\t\"Doc\": \"standaloneTags specifies a set of build constraints that identify\\nindividual Go source files that make up the entire main package of an\\nexecutable.\\n\\nA common example of standalone main files is the convention of using the\\ndirective `//go:build ignore` to denote files that are not intended to be\\nincluded in any package, for example because they are invoked directly by\\nthe developer using `go run`.\\n\\nGopls considers a file to be a standalone main file if and only if it has\\npackage name \\\"main\\\" and has a build directive of the exact form\\n\\\"//go:build tag\\\" or \\\"// +build tag\\\", where tag is among the list of tags\\nconfigured by this setting. Notably, if the build constraint is more\\ncomplicated than a simple tag (such as the composite constraint\\n`//go:build tag \\u0026\\u0026 go1.18`), the file is not considered to be a standalone\\nmain file.\\n\\nThis setting is only supported when gopls is built with Go 1.16 or later.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"[\\\"ignore\\\"]\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"workspaceFiles\",\n\t\t\t\t\"Type\": \"[]string\",\n\t\t\t\t\"Doc\": \"workspaceFiles configures the set of globs that match files defining the\\nlogical build of the current workspace. Any on-disk changes to any files\\nmatching a glob specified here will trigger a reload of the workspace.\\n\\nThis setting need only be customized in environments with a custom\\nGOPACKAGESDRIVER.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"[]\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"build\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"hoverKind\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"hoverKind controls the information that appears in the hover text.\\nSingleLine is intended for use only by authors of editor plugins.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"FullDocumentation\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"NoDocumentation\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"SingleLine\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Structured\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Structured\\\"` is a misguided experimental setting that returns a JSON\\nhover format. This setting should not be used, as it will be removed in a\\nfuture release of gopls.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"SynopsisDocumentation\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"FullDocumentation\\\"\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.documentation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"linkTarget\",\n\t\t\t\t\"Type\": \"string\",\n\t\t\t\t\"Doc\": \"linkTarget is the base URL for links to Go package\\ndocumentation returned by LSP operations such as Hover and\\nDocumentLinks and in the CodeDescription field of each\\nDiagnostic.\\n\\nIt might be one of:\\n\\n* `\\\"godoc.org\\\"`\\n* `\\\"pkg.go.dev\\\"`\\n\\nIf company chooses to use its own `godoc.org`, its address can be used as well.\\n\\nModules matching the GOPRIVATE environment variable will not have\\ndocumentation links in hover.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"\\\"pkg.go.dev\\\"\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.documentation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"linksInHover\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"linksInHover controls the presence of documentation links in hover markdown.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"false\",\n\t\t\t\t\t\t\"Doc\": \"false: do not show links\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"true\",\n\t\t\t\t\t\t\"Doc\": \"true: show links to the `linkTarget` domain\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"gopls\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"gopls\\\"`: show links to gopls' internal documentation viewer\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.documentation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"usePlaceholders\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"placeholders enables placeholders for function parameters or struct\\nfields in completion responses.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.completion\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"completionBudget\",\n\t\t\t\t\"Type\": \"time.Duration\",\n\t\t\t\t\"Doc\": \"completionBudget is the soft latency goal for completion requests. Most\\nrequests finish in a couple milliseconds, but in some cases deep\\ncompletions can take much longer. As we use up our budget we\\ndynamically reduce the search scope to ensure we return timely\\nresults. Zero means unlimited.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"\\\"100ms\\\"\",\n\t\t\t\t\"Status\": \"debug\",\n\t\t\t\t\"Hierarchy\": \"ui.completion\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"matcher\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"matcher sets the algorithm that is used when calculating completion\\ncandidates.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"CaseInsensitive\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"CaseSensitive\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Fuzzy\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"Fuzzy\\\"\",\n\t\t\t\t\"Status\": \"advanced\",\n\t\t\t\t\"Hierarchy\": \"ui.completion\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"experimentalPostfixCompletions\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"experimentalPostfixCompletions enables artificial method snippets\\nsuch as \\\"someSlice.sort!\\\".\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.completion\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"completeFunctionCalls\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"completeFunctionCalls enables function call completion.\\n\\nWhen completing a statement, or when a function return type matches the\\nexpected of the expression being completed, completion may suggest call\\nexpressions (i.e. may include parentheses).\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.completion\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"importShortcut\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"importShortcut specifies whether import statements should link to\\ndocumentation or go to definitions.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Both\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Definition\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Link\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"Both\\\"\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.navigation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"symbolMatcher\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"symbolMatcher sets the algorithm that is used when finding workspace symbols.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"CaseInsensitive\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"CaseSensitive\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"FastFuzzy\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Fuzzy\\\"\",\n\t\t\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"FastFuzzy\\\"\",\n\t\t\t\t\"Status\": \"advanced\",\n\t\t\t\t\"Hierarchy\": \"ui.navigation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"symbolStyle\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"symbolStyle controls how symbols are qualified in symbol responses.\\n\\nExample Usage:\\n\\n```json5\\n\\\"gopls\\\": {\\n...\\n  \\\"symbolStyle\\\": \\\"Dynamic\\\",\\n...\\n}\\n```\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Dynamic\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Dynamic\\\"` uses whichever qualifier results in the highest scoring\\nmatch for the given symbol query. Here a \\\"qualifier\\\" is any \\\"/\\\" or \\\".\\\"\\ndelimited suffix of the fully qualified symbol. i.e. \\\"to/pkg.Foo.Field\\\" or\\njust \\\"Foo.Field\\\".\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Full\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Full\\\"` is fully qualified symbols, i.e.\\n\\\"path/to/pkg.Foo.Field\\\".\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Package\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Package\\\"` is package qualified symbols i.e.\\n\\\"pkg.Foo.Field\\\".\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"Dynamic\\\"\",\n\t\t\t\t\"Status\": \"advanced\",\n\t\t\t\t\"Hierarchy\": \"ui.navigation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"symbolScope\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"symbolScope controls which packages are searched for workspace/symbol\\nrequests. When the scope is \\\"workspace\\\", gopls searches only workspace\\npackages. When the scope is \\\"all\\\", gopls searches all loaded packages,\\nincluding dependencies and the standard library.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"all\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"all\\\"` matches symbols in any loaded package, including\\ndependencies.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"workspace\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"workspace\\\"` matches symbols in workspace packages only.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"all\\\"\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.navigation\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"analyses\",\n\t\t\t\t\"Type\": \"map[string]bool\",\n\t\t\t\t\"Doc\": \"analyses specify analyses that the user would like to enable or disable.\\nA map of the names of analysis passes that should be enabled/disabled.\\nA full list of analyzers that gopls uses can be found in\\n[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\\n\\nExample Usage:\\n\\n```json5\\n...\\n\\\"analyses\\\": {\\n  \\\"unreachable\\\": false, // Disable the unreachable analyzer.\\n  \\\"unusedvariable\\\": true  // Enable the unusedvariable analyzer.\\n}\\n...\\n```\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"bool\",\n\t\t\t\t\t\"Keys\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Apply De Morgan's law\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Convert untagged switch to tagged switch\\n\\nAn untagged switch that compares a single variable against a series of\\nvalues can be replaced with a tagged switch.\\n\\nBefore:\\n\\n    switch {\\n    case x == 1 || x == 2, x == 3:\\n        ...\\n    case x == 4:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAfter:\\n\\n    switch x {\\n    case 1, 2, 3:\\n        ...\\n    case 4:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Convert if/else-if chain to tagged switch\\n\\nA series of if/else-if checks comparing the same variable against\\nvalues can be replaced with a tagged switch.\\n\\nBefore:\\n\\n    if x == 1 || x == 2 {\\n        ...\\n    } else if x == 3 {\\n        ...\\n    } else {\\n        ...\\n    }\\n\\nAfter:\\n\\n    switch x {\\n    case 1, 2:\\n        ...\\n    case 3:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use strings.ReplaceAll instead of strings.Replace with n == -1\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Expand call to math.Pow\\n\\nSome uses of math.Pow can be simplified to basic multiplication.\\n\\nBefore:\\n\\n    math.Pow(x, 2)\\n\\nAfter:\\n\\n    x * x\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Lift if+break into loop condition\\n\\nBefore:\\n\\n    for {\\n        if done {\\n            break\\n        }\\n        ...\\n    }\\n\\nAfter:\\n\\n    for !done {\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1007\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Merge conditional assignment into variable declaration\\n\\nBefore:\\n\\n    x := false\\n    if someCondition {\\n        x = true\\n    }\\n\\nAfter:\\n\\n    x := someCondition\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit embedded fields from selector expression\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1009\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use time.Time.Equal instead of == operator\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1010\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Convert slice of bytes to string when printing it\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit redundant type from variable declaration\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"QF1012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use plain channel send or receive instead of single-case select\\n\\nSelect statements with a single case can be replaced with a simple\\nsend or receive.\\n\\nBefore:\\n\\n    select {\\n    case x := \\u003c-ch:\\n        fmt.Println(x)\\n    }\\n\\nAfter:\\n\\n    x := \\u003c-ch\\n    fmt.Println(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace for loop with call to copy\\n\\nUse copy() for copying elements from one slice to another. For\\narrays of identical size, you can use simple assignment.\\n\\nBefore:\\n\\n    for i, x := range src {\\n        dst[i] = x\\n    }\\n\\nAfter:\\n\\n    copy(dst, src)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit comparison with boolean constant\\n\\nBefore:\\n\\n    if x == true {}\\n\\nAfter:\\n\\n    if x {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace call to strings.Index with strings.Contains\\n\\nBefore:\\n\\n    if strings.Index(x, y) != -1 {}\\n\\nAfter:\\n\\n    if strings.Contains(x, y) {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace call to bytes.Compare with bytes.Equal\\n\\nBefore:\\n\\n    if bytes.Compare(x, y) == 0 {}\\n\\nAfter:\\n\\n    if bytes.Equal(x, y) {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Drop unnecessary use of the blank identifier\\n\\nIn many cases, assigning to the blank identifier is unnecessary.\\n\\nBefore:\\n\\n    for _ = range s {}\\n    x, _ = someMap[key]\\n    _ = \\u003c-ch\\n\\nAfter:\\n\\n    for range s{}\\n    x = someMap[key]\\n    \\u003c-ch\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use 'for { ... }' for infinite loops\\n\\nFor infinite loops, using for { ... } is the most idiomatic choice.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1007\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Simplify regular expression by using raw string literal\\n\\nRaw string literals use backticks instead of quotation marks and do not support\\nany escape sequences. This means that the backslash can be used\\nfreely, without the need of escaping.\\n\\nSince regular expressions have their own escape sequences, raw strings\\ncan improve their readability.\\n\\nBefore:\\n\\n    regexp.Compile(\\\"\\\\\\\\A(\\\\\\\\w+) profile: total \\\\\\\\d+\\\\\\\\n\\\\\\\\z\\\")\\n\\nAfter:\\n\\n    regexp.Compile(`\\\\A(\\\\w+) profile: total \\\\d+\\\\n\\\\z`)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Simplify returning boolean expression\\n\\nBefore:\\n\\n    if \\u003cexpr\\u003e {\\n        return true\\n    }\\n    return false\\n\\nAfter:\\n\\n    return \\u003cexpr\\u003e\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1009\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit redundant nil check on slices, maps, and channels\\n\\nThe len function is defined for all slices, maps, and\\nchannels, even nil ones, which have a length of zero. It is not necessary to\\ncheck for nil before checking that their length is not zero.\\n\\nBefore:\\n\\n    if x != nil \\u0026\\u0026 len(x) != 0 {}\\n\\nAfter:\\n\\n    if len(x) != 0 {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1010\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit default slice index\\n\\nWhen slicing, the second index defaults to the length of the value,\\nmaking s[n:len(s)] and s[n:] equivalent.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use a single append to concatenate two slices\\n\\nBefore:\\n\\n    for _, e := range y {\\n        x = append(x, e)\\n    }\\n    \\n    for i := range y {\\n        x = append(x, y[i])\\n    }\\n    \\n    for i := range y {\\n        v := y[i]\\n        x = append(x, v)\\n    }\\n\\nAfter:\\n\\n    x = append(x, y...)\\n    x = append(x, y...)\\n    x = append(x, y...)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace time.Now().Sub(x) with time.Since(x)\\n\\nThe time.Since helper has the same effect as using time.Now().Sub(x)\\nbut is easier to read.\\n\\nBefore:\\n\\n    time.Now().Sub(x)\\n\\nAfter:\\n\\n    time.Since(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1016\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use a type conversion instead of manually copying struct fields\\n\\nTwo struct types with identical fields can be converted between each\\nother. In older versions of Go, the fields had to have identical\\nstruct tags. Since Go 1.8, however, struct tags are ignored during\\nconversions. It is thus not necessary to manually copy every field\\nindividually.\\n\\nBefore:\\n\\n    var x T1\\n    y := T2{\\n        Field1: x.Field1,\\n        Field2: x.Field2,\\n    }\\n\\nAfter:\\n\\n    var x T1\\n    y := T2(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1017\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace manual trimming with strings.TrimPrefix\\n\\nInstead of using strings.HasPrefix and manual slicing, use the\\nstrings.TrimPrefix function. If the string doesn't start with the\\nprefix, the original string will be returned. Using strings.TrimPrefix\\nreduces complexity, and avoids common bugs, such as off-by-one\\nmistakes.\\n\\nBefore:\\n\\n    if strings.HasPrefix(str, prefix) {\\n        str = str[len(prefix):]\\n    }\\n\\nAfter:\\n\\n    str = strings.TrimPrefix(str, prefix)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1018\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use 'copy' for sliding elements\\n\\ncopy() permits using the same source and destination slice, even with\\noverlapping ranges. This makes it ideal for sliding elements in a\\nslice.\\n\\nBefore:\\n\\n    for i := 0; i \\u003c n; i++ {\\n        bs[i] = bs[offset+i]\\n    }\\n\\nAfter:\\n\\n    copy(bs[:n], bs[offset:])\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1019\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Simplify 'make' call by omitting redundant arguments\\n\\nThe 'make' function has default values for the length and capacity\\narguments. For channels, the length defaults to zero, and for slices,\\nthe capacity defaults to the length.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1020\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit redundant nil check in type assertion\\n\\nBefore:\\n\\n    if _, ok := i.(T); ok \\u0026\\u0026 i != nil {}\\n\\nAfter:\\n\\n    if _, ok := i.(T); ok {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1021\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Merge variable declaration and assignment\\n\\nBefore:\\n\\n    var x uint\\n    x = 1\\n\\nAfter:\\n\\n    var x uint = 1\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1023\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit redundant control flow\\n\\nFunctions that have no return value do not need a return statement as\\nthe final statement of the function.\\n\\nSwitches in Go do not have automatic fallthrough, unlike languages\\nlike C. It is not necessary to have a break statement as the final\\nstatement in a case block.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1024\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Replace x.Sub(time.Now()) with time.Until(x)\\n\\nThe time.Until helper has the same effect as using x.Sub(time.Now())\\nbut is easier to read.\\n\\nBefore:\\n\\n    x.Sub(time.Now())\\n\\nAfter:\\n\\n    time.Until(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1025\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Don't use fmt.Sprintf(\\\"%s\\\", x) unnecessarily\\n\\nIn many instances, there are easier and more efficient ways of getting\\na value's string representation. Whenever a value's underlying type is\\na string already, or the type has a String method, they should be used\\ndirectly.\\n\\nGiven the following shared definitions\\n\\n    type T1 string\\n    type T2 int\\n\\n    func (T2) String() string { return \\\"Hello, world\\\" }\\n\\n    var x string\\n    var y T1\\n    var z T2\\n\\nwe can simplify\\n\\n    fmt.Sprintf(\\\"%s\\\", x)\\n    fmt.Sprintf(\\\"%s\\\", y)\\n    fmt.Sprintf(\\\"%s\\\", z)\\n\\nto\\n\\n    x\\n    string(y)\\n    z.String()\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1028\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Simplify error construction with fmt.Errorf\\n\\nBefore:\\n\\n    errors.New(fmt.Sprintf(...))\\n\\nAfter:\\n\\n    fmt.Errorf(...)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1029\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Range over the string directly\\n\\nRanging over a string will yield byte offsets and runes. If the offset\\nisn't used, this is functionally equivalent to converting the string\\nto a slice of runes and ranging over that. Ranging directly over the\\nstring will be more performant, however, as it avoids allocating a new\\nslice, the size of which depends on the length of the string.\\n\\nBefore:\\n\\n    for _, r := range []rune(s) {}\\n\\nAfter:\\n\\n    for _, r := range s {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1030\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use bytes.Buffer.String or bytes.Buffer.Bytes\\n\\nbytes.Buffer has both a String and a Bytes method. It is almost never\\nnecessary to use string(buf.Bytes()) or []byte(buf.String()) – simply\\nuse the other method.\\n\\nThe only exception to this are map lookups. Due to a compiler optimization,\\nm[string(buf.Bytes())] is more efficient than m[buf.String()].\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1031\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Omit redundant nil check around loop\\n\\nYou can use range on nil slices and maps, the loop will simply never\\nexecute. This makes an additional nil check around the loop\\nunnecessary.\\n\\nBefore:\\n\\n    if s != nil {\\n        for _, x := range s {\\n            ...\\n        }\\n    }\\n\\nAfter:\\n\\n    for _, x := range s {\\n        ...\\n    }\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1032\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)\\n\\nThe sort.Ints, sort.Float64s and sort.Strings functions are easier to\\nread than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x))\\nand sort.Sort(sort.StringSlice(x)).\\n\\nBefore:\\n\\n    sort.Sort(sort.StringSlice(x))\\n\\nAfter:\\n\\n    sort.Strings(x)\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1033\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unnecessary guard around call to 'delete'\\n\\nCalling delete on a nil map is a no-op.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1034\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use result of type assertion to simplify cases\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1035\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header\\n\\nThe methods on net/http.Header, namely Add, Del, Get\\nand Set, already canonicalize the given header name.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1036\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unnecessary guard around map access\\n\\nWhen accessing a map key that doesn't exist yet, one receives a zero\\nvalue. Often, the zero value is a suitable value, for example when\\nusing append or doing integer math.\\n\\nThe following\\n\\n    if _, ok := m[\\\"foo\\\"]; ok {\\n        m[\\\"foo\\\"] = append(m[\\\"foo\\\"], \\\"bar\\\")\\n    } else {\\n        m[\\\"foo\\\"] = []string{\\\"bar\\\"}\\n    }\\n\\ncan be simplified to\\n\\n    m[\\\"foo\\\"] = append(m[\\\"foo\\\"], \\\"bar\\\")\\n\\nand\\n\\n    if _, ok := m2[\\\"k\\\"]; ok {\\n        m2[\\\"k\\\"] += 4\\n    } else {\\n        m2[\\\"k\\\"] = 4\\n    }\\n\\ncan be simplified to\\n\\n    m[\\\"k\\\"] += 4\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1037\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Elaborate way of sleeping\\n\\nUsing a select statement with a single case receiving\\nfrom the result of time.After is a very elaborate way of sleeping that\\ncan much simpler be expressed with a simple call to time.Sleep.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1038\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unnecessarily complex way of printing formatted string\\n\\nInstead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1039\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unnecessary use of fmt.Sprint\\n\\nCalling fmt.Sprint with a single string argument is unnecessary\\nand identical to using the string directly.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"S1040\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Type assertion to current type\\n\\nThe type assertion x.(SomeInterface), when x already has type\\nSomeInterface, can only fail if x is nil. Usually, this is\\nleft-over code from when x had a different type and you can safely\\ndelete the type assertion. If you want to check that x is not nil,\\nconsider being explicit and using an actual if x == nil comparison\\ninstead of relying on the type assertion panicking.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid regular expression\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid template\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid format in time.Parse\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unsupported argument to functions in encoding/binary\\n\\nThe encoding/binary package can only serialize types with known sizes.\\nThis precludes the use of the int and uint types, as their sizes\\ndiffer on different architectures. Furthermore, it doesn't support\\nserializing maps, channels, strings, or functions.\\n\\nBefore Go 1.8, bool wasn't supported, either.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Suspiciously small untyped constant in time.Sleep\\n\\nThe time.Sleep function takes a time.Duration as its only argument.\\nDurations are expressed in nanoseconds. Thus, calling time.Sleep(1)\\nwill sleep for 1 nanosecond. This is a common source of bugs, as sleep\\nfunctions in other languages often accept seconds or milliseconds.\\n\\nThe time package provides constants such as time.Second to express\\nlarge durations. These can be combined with arithmetic to express\\narbitrary durations, for example 5 * time.Second for 5 seconds.\\n\\nIf you truly meant to sleep for a tiny amount of time, use\\nn * time.Nanosecond to signal to Staticcheck that you did mean to sleep\\nfor some amount of nanoseconds.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid first argument to exec.Command\\n\\nos/exec runs programs directly (using variants of the fork and exec\\nsystem calls on Unix systems). This shouldn't be confused with running\\na command in a shell. The shell will allow for features such as input\\nredirection, pipes, and general scripting. The shell is also\\nresponsible for splitting the user's input into a program name and its\\narguments. For example, the equivalent to\\n\\n    ls / /tmp\\n\\nwould be\\n\\n    exec.Command(\\\"ls\\\", \\\"/\\\", \\\"/tmp\\\")\\n\\nIf you want to run a command in a shell, consider using something like\\nthe following – but be aware that not all systems, particularly\\nWindows, will have a /bin/sh program:\\n\\n    exec.Command(\\\"/bin/sh\\\", \\\"-c\\\", \\\"ls | grep Awesome\\\")\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1007\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid URL in net/url.Parse\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Non-canonical key in http.Header map\\n\\nKeys in http.Header maps are canonical, meaning they follow a specific\\ncombination of uppercase and lowercase letters. Methods such as\\nhttp.Header.Add and http.Header.Del convert inputs into this canonical\\nform before manipulating the map.\\n\\nWhen manipulating http.Header maps directly, as opposed to using the\\nprovided methods, care should be taken to stick to canonical form in\\norder to avoid inconsistencies. The following piece of code\\ndemonstrates one such inconsistency:\\n\\n    h := http.Header{}\\n    h[\\\"etag\\\"] = []string{\\\"1234\\\"}\\n    h.Add(\\\"etag\\\", \\\"5678\\\")\\n    fmt.Println(h)\\n\\n    // Output:\\n    // map[Etag:[5678] etag:[1234]]\\n\\nThe easiest way of obtaining the canonical form of a key is to use\\nhttp.CanonicalHeaderKey.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1010\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"(*regexp.Regexp).FindAll called with n == 0, which will always return zero results\\n\\nIf n \\u003e= 0, the function returns at most n matches/submatches. To\\nreturn all results, specify a negative number.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A nil context.Context is being passed to a function, consider using context.TODO instead\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1013\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1014\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Non-pointer value passed to Unmarshal or Decode\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1015\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions\\n\\nBefore Go 1.23, time.Tickers had to be closed to be able to be garbage\\ncollected. Since time.Tick doesn't make it possible to close the underlying\\nticker, using it repeatedly would leak memory.\\n\\nGo 1.23 fixes this by allowing tickers to be collected even if they weren't closed.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1016\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Trapping a signal that cannot be trapped\\n\\nNot all signals can be intercepted by a process. Specifically, on\\nUNIX-like systems, the syscall.SIGKILL and syscall.SIGSTOP signals are\\nnever passed to the process, but instead handled directly by the\\nkernel. It is therefore pointless to try and handle these signals.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1017\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Channels used with os/signal.Notify should be buffered\\n\\nThe os/signal package uses non-blocking channel sends when delivering\\nsignals. If the receiving end of the channel isn't ready and the\\nchannel is either unbuffered or full, the signal will be dropped. To\\navoid missing signals, the channel should be buffered and of the\\nappropriate size. For a channel used for notification of just one\\nsignal value, a buffer of size 1 is sufficient.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1018\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"strings.Replace called with n == 0, which does nothing\\n\\nWith n == 0, zero instances will be replaced. To replace all\\ninstances, use a negative number, or use strings.ReplaceAll.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1020\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using an invalid host:port pair with a net.Listen-related function\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1021\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using bytes.Equal to compare two net.IP\\n\\nA net.IP stores an IPv4 or IPv6 address as a slice of bytes. The\\nlength of the slice for an IPv4 address, however, can be either 4 or\\n16 bytes long, using different ways of representing IPv4 addresses. In\\norder to correctly compare two net.IPs, the net.IP.Equal method should\\nbe used, as it takes both representations into account.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1023\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Modifying the buffer in an io.Writer implementation\\n\\nWrite must not modify the slice data, even temporarily.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1024\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A string cutset contains duplicate characters\\n\\nThe strings.TrimLeft and strings.TrimRight functions take cutsets, not\\nprefixes. A cutset is treated as a set of characters to remove from a\\nstring. For example,\\n\\n    strings.TrimLeft(\\\"42133word\\\", \\\"1234\\\")\\n\\nwill result in the string \\\"word\\\" – any characters that are 1, 2, 3 or\\n4 are cut from the left of the string.\\n\\nIn order to remove one string from another, use strings.TrimPrefix instead.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1025\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"It is not possible to use (*time.Timer).Reset's return value correctly\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1026\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Cannot marshal channels or functions\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1027\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Atomic access to 64-bit variable must be 64-bit aligned\\n\\nOn ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to\\narrange for 64-bit alignment of 64-bit words accessed atomically. The\\nfirst word in a variable or in an allocated struct, array, or slice\\ncan be relied upon to be 64-bit aligned.\\n\\nYou can use the structlayout tool to inspect the alignment of fields\\nin a struct.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1028\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"sort.Slice can only be used on slices\\n\\nThe first argument of sort.Slice must be a slice.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1029\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Inappropriate key in call to context.WithValue\\n\\nThe provided key must be comparable and should not be\\nof type string or any other built-in type to avoid collisions between\\npackages using context. Users of WithValue should define their own\\ntypes for keys.\\n\\nTo avoid allocating when assigning to an interface{},\\ncontext keys often have concrete type struct{}. Alternatively,\\nexported context key variables' static type should be a pointer or\\ninterface.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1030\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid argument in call to a strconv function\\n\\nThis check validates the format, number base and bit size arguments of\\nthe various parsing and formatting functions in strconv.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1031\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Overlapping byte slices passed to an encoder\\n\\nIn an encoding function of the form Encode(dst, src), dst and\\nsrc were found to reference the same memory. This can result in\\nsrc bytes being overwritten before they are read, when the encoder\\nwrites more than one byte per src byte.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA1032\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Wrong order of arguments to errors.Is\\n\\nThe first argument of the function errors.Is is the error\\nthat we have and the second argument is the error we're trying to match against.\\nFor example:\\n\\n\\tif errors.Is(err, io.EOF) { ... }\\n\\nThis check detects some cases where the two arguments have been swapped. It\\nflags any calls where the first argument is referring to a package-level error\\nvariable, such as\\n\\n\\tif errors.Is(io.EOF, err) { /* this is wrong */ }\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA2001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Empty critical section, did you mean to defer the unlock?\\n\\nEmpty critical sections of the kind\\n\\n    mu.Lock()\\n    mu.Unlock()\\n\\nare very often a typo, and the following was intended instead:\\n\\n    mu.Lock()\\n    defer mu.Unlock()\\n\\nDo note that sometimes empty critical sections can be useful, as a\\nform of signaling to wait on another goroutine. Many times, there are\\nsimpler ways of achieving the same effect. When that isn't the case,\\nthe code should be amply commented to avoid confusion. Combining such\\ncomments with a //lint:ignore directive can be used to suppress this\\nrare false positive.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA2002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA2003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Deferred Lock right after locking, likely meant to defer Unlock instead\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA3000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"TestMain doesn't call os.Exit, hiding test failures\\n\\nTest executables (and in turn 'go test') exit with a non-zero status\\ncode if any tests failed. When specifying your own TestMain function,\\nit is your responsibility to arrange for this, by calling os.Exit with\\nthe correct code. The correct code is returned by (*testing.M).Run, so\\nthe usual way of implementing TestMain is to end it with\\nos.Exit(m.Run()).\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA3001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Assigning to b.N in benchmarks distorts the results\\n\\nThe testing package dynamically sets b.N to improve the reliability of\\nbenchmarks and uses it in computations to determine the duration of a\\nsingle operation. Benchmark code must not alter b.N as this would\\nfalsify results.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Binary operator has identical expressions on both sides\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"\\u0026*x gets simplified to x, it does not copy x\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Comparing unsigned values against negative values is pointless\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The loop exits unconditionally after one iteration\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Field assignment that will never be observed. Did you mean to use a pointer receiver?\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The variable in the loop condition never changes, are you incrementing the wrong variable?\\n\\nFor example:\\n\\n\\tfor i := 0; i \\u003c 10; j++ { ... }\\n\\nThis may also occur when a loop can only execute once because of unconditional\\ncontrol flow that terminates the loop. For example, when a loop body contains an\\nunconditional break, return, or panic:\\n\\n\\tfunc f() {\\n\\t\\tpanic(\\\"oops\\\")\\n\\t}\\n\\tfunc g() {\\n\\t\\tfor i := 0; i \\u003c 10; i++ {\\n\\t\\t\\t// f unconditionally calls panic, which means \\\"i\\\" is\\n\\t\\t\\t// never incremented.\\n\\t\\t\\tf()\\n\\t\\t}\\n\\t}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4009\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A function argument is overwritten before its first use\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4010\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The result of append will never be observed anywhere\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Break statement with no effect. Did you mean to break out of an outer loop?\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Comparing a value against NaN even though no value is equal to NaN\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4013\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4014\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4015\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Calling functions like math.Ceil on floats converted from integers doesn't do anything useful\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4016\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Certain bitwise operations, such as x ^ 0, do not do anything useful\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4017\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Discarding the return values of a function without side effects, making the call pointless\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4018\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Self-assignment of variables\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4019\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Multiple, identical build constraints in the same file\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4020\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Unreachable case clause in a type switch\\n\\nIn a type switch like the following\\n\\n    type T struct{}\\n    func (T) Read(b []byte) (int, error) { return 0, nil }\\n\\n    var v any = T{}\\n\\n    switch v.(type) {\\n    case io.Reader:\\n        // ...\\n    case T:\\n        // unreachable\\n    }\\n\\nthe second case clause can never be reached because T implements\\nio.Reader and case clauses are evaluated in source order.\\n\\nAnother example:\\n\\n    type T struct{}\\n    func (T) Read(b []byte) (int, error) { return 0, nil }\\n    func (T) Close() error { return nil }\\n\\n    var v any = T{}\\n\\n    switch v.(type) {\\n    case io.Reader:\\n        // ...\\n    case io.ReadCloser:\\n        // unreachable\\n    }\\n\\nEven though T has a Close method and thus implements io.ReadCloser,\\nio.Reader will always match first. The method set of io.Reader is a\\nsubset of io.ReadCloser. Thus it is impossible to match the second\\ncase without matching the first case.\\n\\n\\nStructurally equivalent interfaces\\n\\nA special case of the previous example are structurally identical\\ninterfaces. Given these declarations\\n\\n    type T error\\n    type V error\\n\\n    func doSomething() error {\\n        err, ok := doAnotherThing()\\n        if ok {\\n            return T(err)\\n        }\\n\\n        return U(err)\\n    }\\n\\nthe following type switch will have an unreachable case clause:\\n\\n    switch doSomething().(type) {\\n    case T:\\n        // ...\\n    case V:\\n        // unreachable\\n    }\\n\\nT will always match before V because they are structurally equivalent\\nand therefore doSomething()'s return value implements both.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4022\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Comparing the address of a variable against nil\\n\\nCode such as 'if \\u0026x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4023\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Impossible comparison of interface value with untyped nil\\n\\nUnder the covers, interfaces are implemented as two elements, a\\ntype T and a value V. V is a concrete value such as an int,\\nstruct or pointer, never an interface itself, and has type T. For\\ninstance, if we store the int value 3 in an interface, the\\nresulting interface value has, schematically, (T=int, V=3). The\\nvalue V is also known as the interface's dynamic value, since a\\ngiven interface variable might hold different values V (and\\ncorresponding types T) during the execution of the program.\\n\\nAn interface value is nil only if the V and T are both\\nunset, (T=nil, V is not set), In particular, a nil interface will\\nalways hold a nil type. If we store a nil pointer of type *int\\ninside an interface value, the inner type will be *int regardless\\nof the value of the pointer: (T=*int, V=nil). Such an interface\\nvalue will therefore be non-nil even when the pointer value V\\ninside is nil.\\n\\nThis situation can be confusing, and arises when a nil value is\\nstored inside an interface value such as an error return:\\n\\n    func returnsError() error {\\n        var p *MyError = nil\\n        if bad() {\\n            p = ErrBad\\n        }\\n        return p // Will always return a non-nil error.\\n    }\\n\\nIf all goes well, the function returns a nil p, so the return\\nvalue is an error interface value holding (T=*MyError, V=nil).\\nThis means that if the caller compares the returned error to nil,\\nit will always look as if there was an error even if nothing bad\\nhappened. To return a proper nil error to the caller, the\\nfunction must return an explicit nil:\\n\\n    func returnsError() error {\\n        if bad() {\\n            return ErrBad\\n        }\\n        return nil\\n    }\\n\\nIt's a good idea for functions that return errors always to use\\nthe error type in their signature (as we did above) rather than a\\nconcrete type such as *MyError, to help guarantee the error is\\ncreated correctly. As an example, os.Open returns an error even\\nthough, if not nil, it's always of concrete type *os.PathError.\\n\\nSimilar situations to those described here can arise whenever\\ninterfaces are used. Just keep in mind that if any concrete value\\nhas been stored in the interface, the interface will not be nil.\\nFor more information, see The Laws of\\nReflection at https://golang.org/doc/articles/laws_of_reflection.html.\\n\\nThis text has been copied from\\nhttps://golang.org/doc/faq#nil_error, licensed under the Creative\\nCommons Attribution 3.0 License.\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4024\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Checking for impossible return value from a builtin function\\n\\nReturn values of the len and cap builtins cannot be negative.\\n\\nSee https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap.\\n\\nExample:\\n\\n    if len(slice) \\u003c 0 {\\n        fmt.Println(\\\"unreachable code\\\")\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4025\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Integer division of literals that results in zero\\n\\nWhen dividing two integer constants, the result will\\nalso be an integer. Thus, a division such as 2 / 3 results in 0.\\nThis is true for all of the following examples:\\n\\n\\t_ = 2 / 3\\n\\tconst _ = 2 / 3\\n\\tconst _ float64 = 2 / 3\\n\\t_ = float64(2 / 3)\\n\\nStaticcheck will flag such divisions if both sides of the division are\\ninteger literals, as it is highly unlikely that the division was\\nintended to truncate to zero. Staticcheck will not flag integer\\ndivision involving named constants, to avoid noisy positives.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4026\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Go constants cannot express negative zero\\n\\nIn IEEE 754 floating point math, zero has a sign and can be positive\\nor negative. This can be useful in certain numerical code.\\n\\nGo constants, however, cannot express negative zero. This means that\\nthe literals -0.0 and 0.0 have the same ideal value (zero) and\\nwill both represent positive zero at runtime.\\n\\nTo explicitly and reliably create a negative zero, you can use the\\nmath.Copysign function: math.Copysign(0, -1).\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4027\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"(*net/url.URL).Query returns a copy, modifying it doesn't change the URL\\n\\n(*net/url.URL).Query parses the current value of net/url.URL.RawQuery\\nand returns it as a map of type net/url.Values. Subsequent changes to\\nthis map will not affect the URL unless the map gets encoded and\\nassigned to the URL's RawQuery.\\n\\nAs a consequence, the following code pattern is an expensive no-op:\\nu.Query().Add(key, value).\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4028\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"x % 1 is always zero\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4029\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Ineffective attempt at sorting slice\\n\\nsort.Float64Slice, sort.IntSlice, and sort.StringSlice are\\ntypes, not functions. Doing x = sort.StringSlice(x) does nothing,\\nespecially not sort any values. The correct usage is\\nsort.Sort(sort.StringSlice(x)) or sort.StringSlice(x).Sort(),\\nbut there are more convenient helpers, namely sort.Float64s,\\nsort.Ints, and sort.Strings.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4030\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Ineffective attempt at generating random number\\n\\nFunctions in the math/rand package that accept upper limits, such\\nas Intn, generate random numbers in the half-open interval [0,n). In\\nother words, the generated numbers will be \\u003e= 0 and \\u003c n – they\\ndon't include n. rand.Intn(1) therefore doesn't generate 0\\nor 1, it always generates 0.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4031\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Checking never-nil value against nil\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA4032\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Comparing runtime.GOOS or runtime.GOARCH against impossible value\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Assignment to nil map\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Deferring Close before checking for a possible error\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The empty for loop ('for {}') spins and can block the scheduler\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Defers in infinite loops will never execute\\n\\nDefers are scoped to the surrounding function, not the surrounding\\nblock. In a function that never returns, i.e. one containing an\\ninfinite loop, defers will never execute.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"'for { select { ...' with an empty default branch spins\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The finalizer references the finalized object, preventing garbage collection\\n\\nA finalizer is a function associated with an object that runs when the\\ngarbage collector is ready to collect said object, that is when the\\nobject is no longer referenced by anything.\\n\\nIf the finalizer references the object, however, it will always remain\\nas the final reference to that object, preventing the garbage\\ncollector from collecting the object. The finalizer will never run,\\nand the object will never be collected, leading to a memory leak. That\\nis why the finalizer should instead use its first argument to operate\\non the object. That way, the number of references can temporarily go\\nto zero before the object is being passed to the finalizer.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5007\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Infinite recursive call\\n\\nA function that calls itself recursively needs to have an exit\\ncondition. Otherwise it will recurse forever, until the system runs\\nout of memory.\\n\\nThis issue can be caused by simple bugs such as forgetting to add an\\nexit condition. It can also happen \\\"on purpose\\\". Some languages have\\ntail call optimization which makes certain infinite recursive calls\\nsafe to use. Go, however, does not implement TCO, and as such a loop\\nshould be used instead.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Invalid struct tag\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5010\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Impossible type assertion\\n\\nSome type assertions can be statically proven to be\\nimpossible. This is the case when the method sets of both\\narguments of the type assertion conflict with each other, for\\nexample by containing the same method with different\\nsignatures.\\n\\nThe Go compiler already applies this check when asserting from an\\ninterface value to a concrete type. If the concrete type misses\\nmethods from the interface, or if function signatures don't match,\\nthen the type assertion can never succeed.\\n\\nThis check applies the same logic when asserting from one interface to\\nanother. If both interface types contain the same method but with\\ndifferent signatures, then the type assertion can never succeed,\\neither.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Possible nil pointer dereference\\n\\nA pointer is being dereferenced unconditionally, while\\nalso being checked against nil in another place. This suggests that\\nthe pointer may be nil and dereferencing it may panic. This is\\ncommonly a result of improperly ordered code or missing return\\nstatements. Consider the following examples:\\n\\n    func fn(x *int) {\\n        fmt.Println(*x)\\n\\n        // This nil check is equally important for the previous dereference\\n        if x != nil {\\n            foo(*x)\\n        }\\n    }\\n\\n    func TestFoo(t *testing.T) {\\n        x := compute()\\n        if x == nil {\\n            t.Errorf(\\\"nil pointer received\\\")\\n        }\\n\\n        // t.Errorf does not abort the test, so if x is nil, the next line will panic.\\n        foo(*x)\\n    }\\n\\nStaticcheck tries to deduce which functions abort control flow.\\nFor example, it is aware that a function will not continue\\nexecution after a call to panic or log.Fatal. However, sometimes\\nthis detection fails, in particular in the presence of\\nconditionals. Consider the following example:\\n\\n    func Log(msg string, level int) {\\n        fmt.Println(msg)\\n        if level == levelFatal {\\n            os.Exit(1)\\n        }\\n    }\\n\\n    func Fatal(msg string) {\\n        Log(msg, levelFatal)\\n    }\\n\\n    func fn(x *int) {\\n        if x == nil {\\n            Fatal(\\\"unexpected nil pointer\\\")\\n        }\\n        fmt.Println(*x)\\n    }\\n\\nStaticcheck will flag the dereference of x, even though it is perfectly\\nsafe. Staticcheck is not able to deduce that a call to\\nFatal will exit the program. For the time being, the easiest\\nworkaround is to modify the definition of Fatal like so:\\n\\n    func Fatal(msg string) {\\n        Log(msg, levelFatal)\\n        panic(\\\"unreachable\\\")\\n    }\\n\\nWe also hard-code functions from common logging packages such as\\nlogrus. Please file an issue if we're missing support for a\\npopular package.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA5012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Passing odd-sized slice to function expecting even size\\n\\nSome functions that take slices as parameters expect the slices to have an even number of elements. \\nOften, these functions treat elements in a slice as pairs. \\nFor example, strings.NewReplacer takes pairs of old and new strings, \\nand calling it with an odd number of elements would be an error.\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using regexp.Match or related in a loop, should use regexp.Compile\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Missing an optimization opportunity when indexing maps by byte slices\\n\\nMap keys must be comparable, which precludes the use of byte slices.\\nThis usually leads to using string keys and converting byte slices to\\nstrings.\\n\\nNormally, a conversion of a byte slice to a string needs to copy the data and\\ncauses allocations. The compiler, however, recognizes m[string(b)] and\\nuses the data of b directly, without copying it, because it knows that\\nthe data can't change during the map lookup. This leads to the\\ncounter-intuitive situation that\\n\\n    k := string(b)\\n    println(m[k])\\n    println(m[k])\\n\\nwill be less efficient than\\n\\n    println(m[string(b)])\\n    println(m[string(b)])\\n\\nbecause the first version needs to copy and allocate, while the second\\none does not.\\n\\nFor some history on this optimization, check out commit\\nf5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Storing non-pointer values in sync.Pool allocates memory\\n\\nA sync.Pool is used to avoid unnecessary allocations and reduce the\\namount of work the garbage collector has to do.\\n\\nWhen passing a value that is not a pointer to a function that accepts\\nan interface, the value needs to be placed on the heap, which means an\\nadditional allocation. Slices are a common thing to put in sync.Pools,\\nand they're structs with 3 fields (length, capacity, and a pointer to\\nan array). In order to avoid the extra allocation, one should store a\\npointer to the slice instead.\\n\\nSee the comments on https://go-review.googlesource.com/c/go/+/24371\\nthat discuss this problem.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Converting a string to a slice of runes before ranging over it\\n\\nYou may want to loop over the runes in a string. Instead of converting\\nthe string to a slice of runes and looping over that, you can loop\\nover the string itself. That is,\\n\\n    for _, r := range s {}\\n\\nand\\n\\n    for _, r := range []rune(s) {}\\n\\nwill yield the same values. The first version, however, will be faster\\nand avoid unnecessary memory allocations.\\n\\nDo note that if you are interested in the indices, ranging over a\\nstring and over a slice of runes will yield different indices. The\\nfirst one yields byte offsets, while the second one yields indices in\\nthe slice of runes.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Inefficient string comparison with strings.ToLower or strings.ToUpper\\n\\nConverting two strings to the same case and comparing them like so\\n\\n    if strings.ToLower(s1) == strings.ToLower(s2) {\\n        ...\\n    }\\n\\nis significantly more expensive than comparing them with\\nstrings.EqualFold(s1, s2). This is due to memory usage as well as\\ncomputational complexity.\\n\\nstrings.ToLower will have to allocate memory for the new strings, as\\nwell as convert both strings fully, even if they differ on the very\\nfirst byte. strings.EqualFold, on the other hand, compares the strings\\none character at a time. It doesn't need to create two intermediate\\nstrings and can return as soon as the first non-matching character has\\nbeen found.\\n\\nFor a more in-depth explanation of this issue, see\\nhttps://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA6006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using io.WriteString to write []byte\\n\\nUsing io.WriteString to write a slice of bytes, as in\\n\\n    io.WriteString(w, string(b))\\n\\nis both unnecessary and inefficient. Converting from []byte to string\\nhas to allocate and copy the data, and we could simply use w.Write(b)\\ninstead.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Defers in range loops may not run when you expect them to\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9002\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Using a non-octal os.FileMode that looks like it was meant to be in octal.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Empty body in an if or else branch\\n\\nAvailable since\\n    2017.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9004\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Only the first constant has an explicit type\\n\\nIn a constant declaration such as the following:\\n\\n    const (\\n        First byte = 1\\n        Second     = 2\\n    )\\n\\nthe constant Second does not have the same type as the constant First.\\nThis construct shouldn't be confused with\\n\\n    const (\\n        First byte = iota\\n        Second\\n    )\\n\\nwhere First and Second do indeed have the same type. The type is only\\npassed on when no explicit value is assigned to the constant.\\n\\nWhen declaring enumerations with explicit values it is therefore\\nimportant not to write\\n\\n    const (\\n          EnumFirst EnumType = 1\\n          EnumSecond         = 2\\n          EnumThird          = 3\\n    )\\n\\nThis discrepancy in types can cause various confusing behaviors and\\nbugs.\\n\\n\\nWrong type in variable declarations\\n\\nThe most obvious issue with such incorrect enumerations expresses\\nitself as a compile error:\\n\\n    package pkg\\n\\n    const (\\n        EnumFirst  uint8 = 1\\n        EnumSecond       = 2\\n    )\\n\\n    func fn(useFirst bool) {\\n        x := EnumSecond\\n        if useFirst {\\n            x = EnumFirst\\n        }\\n    }\\n\\nfails to compile with\\n\\n    ./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment\\n\\n\\nLosing method sets\\n\\nA more subtle issue occurs with types that have methods and optional\\ninterfaces. Consider the following:\\n\\n    package main\\n\\n    import \\\"fmt\\\"\\n\\n    type Enum int\\n\\n    func (e Enum) String() string {\\n        return \\\"an enum\\\"\\n    }\\n\\n    const (\\n        EnumFirst  Enum = 1\\n        EnumSecond      = 2\\n    )\\n\\n    func main() {\\n        fmt.Println(EnumFirst)\\n        fmt.Println(EnumSecond)\\n    }\\n\\nThis code will output\\n\\n    an enum\\n    2\\n\\nas EnumSecond has no explicit type, and thus defaults to int.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Trying to marshal a struct with no public fields nor custom marshaling\\n\\nThe encoding/json and encoding/xml packages only operate on exported\\nfields in structs, not unexported ones. It is usually an error to try\\nto (un)marshal structs that only consist of unexported fields.\\n\\nThis check will not flag calls involving types that define custom\\nmarshaling behavior, e.g. via MarshalJSON methods. It will also not\\nflag empty structs.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Dubious bit shifting of a fixed size integer value\\n\\nBit shifting a value past its size will always clear the value.\\n\\nFor instance:\\n\\n    v := int8(42)\\n    v \\u003e\\u003e= 8\\n\\nwill always result in 0.\\n\\nThis check flags bit shifting operations on fixed size integer values only.\\nThat is, int, uint and uintptr are never flagged to avoid potential false\\npositives in somewhat exotic but valid bit twiddling tricks:\\n\\n    // Clear any value above 32 bits if integers are more than 32 bits.\\n    func f(i int) int {\\n        v := i \\u003e\\u003e 32\\n        v = v \\u003c\\u003c 32\\n        return i-v\\n    }\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9007\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Deleting a directory that shouldn't be deleted\\n\\nIt is virtually never correct to delete system directories such as\\n/tmp or the user's home directory. However, it can be fairly easy to\\ndo by mistake, for example by mistakenly using os.TempDir instead\\nof ioutil.TempDir, or by forgetting to add a suffix to the result\\nof os.UserHomeDir.\\n\\nWriting\\n\\n    d := os.TempDir()\\n    defer os.RemoveAll(d)\\n\\nin your unit tests will have a devastating effect on the stability of your system.\\n\\nThis check flags attempts at deleting the following directories:\\n\\n- os.TempDir\\n- os.UserCacheDir\\n- os.UserConfigDir\\n- os.UserHomeDir\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"else branch of a type assertion is probably not reading the right value\\n\\nWhen declaring variables as part of an if statement (like in 'if\\nfoo := ...; foo {'), the same variables will also be in the scope of\\nthe else branch. This means that in the following example\\n\\n    if x, ok := x.(int); ok {\\n        // ...\\n    } else {\\n        fmt.Printf(\\\"unexpected type %T\\\", x)\\n    }\\n\\nx in the else branch will refer to the x from x, ok\\n:=; it will not refer to the x that is being type-asserted. The\\nresult of a failed type assertion is the zero value of the type that\\nis being asserted to, so x in the else branch will always have the\\nvalue 0 and the type int.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"SA9009\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Ineffectual Go compiler directive\\n\\nA potential Go compiler directive was found, but is ineffectual as it begins\\nwith whitespace.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1000\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Incorrect or missing package comment\\n\\nPackages must have a package comment that is formatted according to\\nthe guidelines laid out in\\nhttps://go.dev/wiki/CodeReviewComments#package-comments.\\n\\nAvailable since\\n    2019.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1001\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Dot imports are discouraged\\n\\nDot imports that aren't in external test packages are discouraged.\\n\\nThe dot_import_whitelist option can be used to whitelist certain\\nimports.\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e The import . form can be useful in tests that, due to circular\\n\\u003e dependencies, cannot be made part of the package being tested:\\n\\u003e \\n\\u003e     package foo_test\\n\\u003e \\n\\u003e     import (\\n\\u003e         \\\"bar/testutil\\\" // also imports \\\"foo\\\"\\n\\u003e         . \\\"foo\\\"\\n\\u003e     )\\n\\u003e \\n\\u003e In this case, the test file cannot be in package foo because it\\n\\u003e uses bar/testutil, which imports foo. So we use the import .\\n\\u003e form to let the file pretend to be part of package foo even though\\n\\u003e it is not. Except for this one case, do not use import . in your\\n\\u003e programs. It makes the programs much harder to read because it is\\n\\u003e unclear whether a name like Quux is a top-level identifier in the\\n\\u003e current package or in an imported package.\\n\\nAvailable since\\n    2019.1\\n\\nOptions\\n    dot_import_whitelist\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1003\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Poorly chosen identifier\\n\\nIdentifiers, such as variable and package names, follow certain rules.\\n\\nSee the following links for details:\\n\\n- https://go.dev/doc/effective_go#package-names\\n- https://go.dev/doc/effective_go#mixed-caps\\n- https://go.dev/wiki/CodeReviewComments#initialisms\\n- https://go.dev/wiki/CodeReviewComments#variable-names\\n\\nAvailable since\\n    2019.1, non-default\\n\\nOptions\\n    initialisms\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1005\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Incorrectly formatted error string\\n\\nError strings follow a set of guidelines to ensure uniformity and good\\ncomposability.\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e Error strings should not be capitalized (unless beginning with\\n\\u003e proper nouns or acronyms) or end with punctuation, since they are\\n\\u003e usually printed following other context. That is, use\\n\\u003e fmt.Errorf(\\\"something bad\\\") not fmt.Errorf(\\\"Something bad\\\"), so\\n\\u003e that log.Printf(\\\"Reading %s: %v\\\", filename, err) formats without a\\n\\u003e spurious capital letter mid-message.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1006\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Poorly chosen receiver name\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e The name of a method's receiver should be a reflection of its\\n\\u003e identity; often a one or two letter abbreviation of its type\\n\\u003e suffices (such as \\\"c\\\" or \\\"cl\\\" for \\\"Client\\\"). Don't use generic\\n\\u003e names such as \\\"me\\\", \\\"this\\\" or \\\"self\\\", identifiers typical of\\n\\u003e object-oriented languages that place more emphasis on methods as\\n\\u003e opposed to functions. The name need not be as descriptive as that\\n\\u003e of a method argument, as its role is obvious and serves no\\n\\u003e documentary purpose. It can be very short as it will appear on\\n\\u003e almost every line of every method of the type; familiarity admits\\n\\u003e brevity. Be consistent, too: if you call the receiver \\\"c\\\" in one\\n\\u003e method, don't call it \\\"cl\\\" in another.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1008\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A function's error value should be its last return value\\n\\nA function's error value should be its last return value.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1011\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Poorly chosen name for variable of type time.Duration\\n\\ntime.Duration values represent an amount of time, which is represented\\nas a count of nanoseconds. An expression like 5 * time.Microsecond\\nyields the value 5000. It is therefore not appropriate to suffix a\\nvariable of type time.Duration with any time unit, such as Msec or\\nMilli.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1012\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Poorly chosen name for error variable\\n\\nError variables that are part of an API should be called errFoo or\\nErrFoo.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1013\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Should use constants for HTTP error codes, not magic numbers\\n\\nHTTP has a tremendous number of status codes. While some of those are\\nwell known (200, 400, 404, 500), most of them are not. The net/http\\npackage provides constants for all status codes that are part of the\\nvarious specifications. It is recommended to use these constants\\ninstead of hard-coding magic numbers, to vastly improve the\\nreadability of your code.\\n\\nAvailable since\\n    2019.1\\n\\nOptions\\n    http_status_code_whitelist\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1015\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"A switch's default case should be the first or last case\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1016\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Use consistent method receiver names\\n\\nAvailable since\\n    2019.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1017\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Don't use Yoda conditions\\n\\nYoda conditions are conditions of the kind 'if 42 == x', where the\\nliteral is on the left side of the comparison. These are a common\\nidiom in languages in which assignment is an expression, to avoid bugs\\nof the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of\\nbug, we prefer the more idiomatic 'if x == 42'.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1018\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Avoid zero-width and control characters in string literals\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1019\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Importing the same package multiple times\\n\\nGo allows importing the same package multiple times, as long as\\ndifferent import aliases are being used. That is, the following\\nbit of code is valid:\\n\\n    import (\\n        \\\"fmt\\\"\\n        fumpt \\\"fmt\\\"\\n        format \\\"fmt\\\"\\n    )\\n\\nHowever, this is very rarely done on purpose. Usually, it is a\\nsign of code that got refactored, accidentally adding duplicate\\nimport statements. It is also a rarely known feature, which may\\ncontribute to confusion.\\n\\nDo note that sometimes, this feature may be used\\nintentionally (see for example\\nhttps://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)\\n– if you want to allow this pattern in your code base, you're\\nadvised to disable this check.\\n\\nIt is acceptable to import the same package twice if one of the imports\\nuses the blank identifier. This is allowed in order to increase\\nresilience against erroneous changes when using the same package for its\\nside effects as well as its exported API.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1020\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The documentation of an exported function should start with the function's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1021\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The documentation of an exported type should start with type's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1022\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"The documentation of an exported variable or constant should start with variable's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ST1023\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"Redundant type in variable declaration\\n\\nAvailable since\\n    2021.1, non-default\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"any\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace interface{} with any\\n\\nThe any analyzer suggests replacing uses of the empty interface type,\\n`interface{}`, with the `any` alias, which was introduced in Go 1.18.\\nThis is a purely stylistic change that makes code more readable.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"appendclipped\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"simplify append chains using slices.Concat\\n\\nThe appendclipped analyzer suggests replacing chains of append calls with a\\nsingle call to slices.Concat, which was added in Go 1.21. For example,\\nappend(append(s, s1...), s2...) would be simplified to slices.Concat(s, s1, s2).\\n\\nIn the simple case of appending to a newly allocated slice, such as\\nappend([]T(nil), s...), the analyzer suggests the more concise slices.Clone(s).\\nFor byte slices, it will prefer bytes.Clone if the \\\"bytes\\\" package is\\nalready imported.\\n\\nThis fix is only applied when the base of the append tower is a\\n\\\"clipped\\\" slice, meaning its length and capacity are equal (e.g.\\nx[:0:0] or []T{}). This is to avoid changing program behavior by\\neliminating intended side effects on the base slice's underlying\\narray.\\n\\nThis analyzer is currently disabled by default as the\\ntransformation does not preserve the nilness of the base slice in\\nall cases; see https://go.dev/issue/73557.\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"appends\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for missing values after append\\n\\nThis checker reports calls to append that pass\\nno values to be appended to the slice.\\n\\n\\ts := []string{\\\"a\\\", \\\"b\\\", \\\"c\\\"}\\n\\t_ = append(s)\\n\\nSuch calls are always no-ops and often indicate an\\nunderlying mistake.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"asmdecl\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report mismatches between assembly files and Go declarations\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"assign\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for useless assignments\\n\\nThis checker reports assignments of the form x = x or a[i] = a[i].\\nThese are almost always useless, and even when they aren't they are\\nusually a mistake.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"atomic\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for common mistakes using the sync/atomic package\\n\\nThe atomic checker looks for assignment statements of the form:\\n\\n\\tx = atomic.AddUint64(\\u0026x, 1)\\n\\nwhich are not atomic.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"atomicalign\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for non-64-bits-aligned arguments to sync/atomic functions\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"atomictypes\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace basic types in sync/atomic calls with atomic types\\n\\nThe atomictypes analyzer suggests replacing the primitive sync/atomic functions with\\nthe strongly typed atomic wrapper types introduced in Go1.19 (e.g.\\natomic.Int32). For example,\\n\\n\\tvar x int32\\n\\tatomic.AddInt32(\\u0026x, 1)\\n\\nwould become\\n\\n\\tvar x atomic.Int32\\n\\tx.Add(1)\\n\\nThe atomic types are safer because they don't allow non-atomic access, which is\\na common source of bugs. These types also resolve memory alignment issues that\\nplagued the old atomic functions on 32-bit architectures.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"bloop\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace for-range over b.N with b.Loop\\n\\nThe bloop analyzer suggests replacing benchmark loops of the form\\n`for i := 0; i \\u003c b.N; i++` or `for range b.N` with the more modern\\n`for b.Loop()`, which was added in Go 1.24.\\n\\nThis change makes benchmark code more readable and also removes the need for\\nmanual timer control, so any preceding calls to b.StartTimer, b.StopTimer,\\nor b.ResetTimer within the same function will also be removed.\\n\\nCaveats: The b.Loop() method is designed to prevent the compiler from\\noptimizing away the benchmark loop, which can occasionally result in\\nslower execution due to increased allocations in some specific cases.\\nSince its fix may change the performance of nanosecond-scale benchmarks,\\nbloop is disabled by default in the `go fix` analyzer suite; see golang/go#74967.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"bools\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for common mistakes involving boolean operators\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"buildtag\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check //go:build and // +build directives\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"cgocall\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"detect some violations of the cgo pointer passing rules\\n\\nCheck for invalid cgo pointer passing.\\nThis looks for code that uses cgo to call C code passing values\\nwhose types are almost always invalid according to the cgo pointer\\nsharing rules.\\nSpecifically, it warns about attempts to pass a Go chan, map, func,\\nor slice to C, either directly, or via a pointer, array, or struct.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"composites\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unkeyed composite literals\\n\\nThis analyzer reports a diagnostic for composite literals of struct\\ntypes imported from another package that do not use the field-keyed\\nsyntax. Such literals are fragile because the addition of a new field\\n(even if unexported) to the struct will cause compilation to fail.\\n\\nAs an example,\\n\\n\\terr = \\u0026net.DNSConfigError{err}\\n\\nshould be replaced by:\\n\\n\\terr = \\u0026net.DNSConfigError{Err: err}\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"copylocks\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for locks erroneously passed by value\\n\\nInadvertently copying a value containing a lock, such as sync.Mutex or\\nsync.WaitGroup, may cause both copies to malfunction. Generally such\\nvalues should be referred to through a pointer.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"deepequalerrors\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for calls of reflect.DeepEqual on error values\\n\\nThe deepequalerrors checker looks for calls of the form:\\n\\n    reflect.DeepEqual(err1, err2)\\n\\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare\\nerrors is discouraged.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"defers\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report common mistakes in defer statements\\n\\nThe defers analyzer reports a diagnostic when a defer statement would\\nresult in a non-deferred call to time.Since, as experience has shown\\nthat this is nearly always a mistake.\\n\\nFor example:\\n\\n\\tstart := time.Now()\\n\\t...\\n\\tdefer recordLatency(time.Since(start)) // error: call to time.Since is not deferred\\n\\nThe correct code is:\\n\\n\\tdefer func() { recordLatency(time.Since(start)) }()\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"deprecated\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for use of deprecated identifiers\\n\\nThe deprecated analyzer looks for deprecated symbols and package\\nimports.\\n\\nSee https://go.dev/wiki/Deprecated to learn about Go's convention\\nfor documenting and signaling deprecated identifiers.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"directive\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check Go toolchain directives such as //go:debug\\n\\nThis analyzer checks for problems with known Go toolchain directives\\nin all Go source files in a package directory, even those excluded by\\n//go:build constraints, and all non-Go source files too.\\n\\nFor //go:debug (see https://go.dev/doc/godebug), the analyzer checks\\nthat the directives are placed only in Go source files, only above the\\npackage comment, and only in package main or *_test.go files.\\n\\nSupport for other known directives may be added in the future.\\n\\nThis analyzer does not check //go:build, which is handled by the\\nbuildtag analyzer.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"embed\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check //go:embed directive usage\\n\\nThis analyzer checks that the embed package is imported if //go:embed\\ndirectives are present, providing a suggested fix to add the import if\\nit is missing.\\n\\nThis analyzer also checks that //go:embed directives precede the\\ndeclaration of a single variable.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"errorsas\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report passing non-pointer or non-error values to errors.As\\n\\nThe errorsas analyzer reports calls to errors.As where the type\\nof the second argument is not a pointer to a type implementing error.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"errorsastype\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace errors.As with errors.AsType[T]\\n\\nThis analyzer suggests fixes to simplify uses of [errors.As] of\\nthis form:\\n\\n\\tvar myerr *MyErr\\n\\tif errors.As(err, \\u0026myerr) {\\n\\t\\thandle(myerr)\\n\\t}\\n\\nby using the less error-prone generic [errors.AsType] function,\\nintroduced in Go 1.26:\\n\\n\\tif myerr, ok := errors.AsType[*MyErr](err); ok {\\n\\t\\thandle(myerr)\\n\\t}\\n\\nThe fix is only offered if the var declaration has the form shown and\\nthere are no uses of myerr outside the if statement.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"fieldalignment\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"find structs that would use less memory if their fields were sorted\\n\\nThis analyzer finds structs that can be rearranged to use less memory, and provides\\na suggested edit with the most compact order.\\n\\nNote that there are two different diagnostics reported. One checks struct size,\\nand the other reports \\\"pointer bytes\\\" used. Pointer bytes is how many bytes of the\\nobject that the garbage collector has to potentially scan for pointers, for example:\\n\\n\\tstruct { uint32; string }\\n\\nhave 16 pointer bytes because the garbage collector has to scan up through the string's\\ninner pointer.\\n\\n\\tstruct { string; *uint32 }\\n\\nhas 24 pointer bytes because it has to scan further through the *uint32.\\n\\n\\tstruct { string; uint32 }\\n\\nhas 8 because it can stop immediately after the string pointer.\\n\\nBe aware that the most compact order is not always the most efficient.\\nIn rare cases it may cause two variables each updated by its own goroutine\\nto occupy the same CPU cache line, inducing a form of memory contention\\nknown as \\\"false sharing\\\" that slows down both goroutines.\\n\\nUnlike most analyzers, which report likely mistakes, the diagnostics\\nproduced by fieldanalyzer very rarely indicate a significant problem,\\nso the analyzer is not included in typical suites such as vet or\\ngopls. Use this standalone command to run it on your code:\\n\\n   $ go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest\\n   $ fieldalignment [packages]\\n\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"fillreturns\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"suggest fixes for errors due to an incorrect number of return values\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"wrong number of return values (want %d, got %d)\\\". For example:\\n\\n\\tfunc m() (int, string, *bool, error) {\\n\\t\\treturn\\n\\t}\\n\\nwill turn into\\n\\n\\tfunc m() (int, string, *bool, error) {\\n\\t\\treturn 0, \\\"\\\", nil, nil\\n\\t}\\n\\nThis functionality is similar to https://github.com/sqs/goreturns.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"fmtappendf\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace []byte(fmt.Sprintf) with fmt.Appendf\\n\\nThe fmtappendf analyzer suggests replacing `[]byte(fmt.Sprintf(...))` with\\n`fmt.Appendf(nil, ...)`. This avoids the intermediate allocation of a string\\nby Sprintf, making the code more efficient. The suggestion also applies to\\nfmt.Sprint and fmt.Sprintln.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"forvar\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"remove redundant re-declaration of loop variables\\n\\nThe forvar analyzer removes unnecessary shadowing of loop variables.\\nBefore Go 1.22, it was common to write `for _, x := range s { x := x ... }`\\nto create a fresh variable for each iteration. Go 1.22 changed the semantics\\nof `for` loops, making this pattern redundant. This analyzer removes the\\nunnecessary `x := x` statement.\\n\\nThis fix only applies to `range` loops.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"framepointer\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report assembly that clobbers the frame pointer before saving it\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"hostport\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check format of addresses passed to net.Dial\\n\\nThis analyzer flags code that produce network address strings using\\nfmt.Sprintf, as in this example:\\n\\n    addr := fmt.Sprintf(\\\"%s:%d\\\", host, 12345) // \\\"will not work with IPv6\\\"\\n    ...\\n    conn, err := net.Dial(\\\"tcp\\\", addr)       // \\\"when passed to dial here\\\"\\n\\nThe analyzer suggests a fix to use the correct approach, a call to\\nnet.JoinHostPort:\\n\\n    addr := net.JoinHostPort(host, \\\"12345\\\")\\n    ...\\n    conn, err := net.Dial(\\\"tcp\\\", addr)\\n\\nA similar diagnostic and fix are produced for a format string of \\\"%s:%s\\\".\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"httpresponse\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for mistakes using HTTP responses\\n\\nA common mistake when using the net/http package is to defer a function\\ncall to close the http.Response Body before checking the error that\\ndetermines whether the response is valid:\\n\\n\\tresp, err := http.Head(url)\\n\\tdefer resp.Body.Close()\\n\\tif err != nil {\\n\\t\\tlog.Fatal(err)\\n\\t}\\n\\t// (defer statement belongs here)\\n\\nThis checker helps uncover latent nil dereference bugs by reporting a\\ndiagnostic for such mistakes.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ifaceassert\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"detect impossible interface-to-interface type assertions\\n\\nThis checker flags type assertions v.(T) and corresponding type-switch cases\\nin which the static type V of v is an interface that cannot possibly implement\\nthe target interface T. This occurs when V and T contain methods with the same\\nname but different signatures. Example:\\n\\n\\tvar v interface {\\n\\t\\tRead()\\n\\t}\\n\\t_ = v.(io.Reader)\\n\\nThe Read method in v has a different signature than the Read method in\\nio.Reader, so this assertion cannot succeed.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"infertypeargs\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unnecessary type arguments in call expressions\\n\\nExplicit type arguments may be omitted from call expressions if they can be\\ninferred from function arguments, or from other type arguments:\\n\\n\\tfunc f[T any](T) {}\\n\\t\\n\\tfunc _() {\\n\\t\\tf[string](\\\"foo\\\") // string could be inferred\\n\\t}\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"inline\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"apply fixes based on 'go:fix inline' comment directives\\n\\nThe inline analyzer inlines functions and constants that are marked for inlining.\\n\\n## Functions\\n\\nGiven a function that is marked for inlining, like this one:\\n\\n\\t//go:fix inline\\n\\tfunc Square(x int) int { return Pow(x, 2) }\\n\\nthis analyzer will recommend that calls to the function elsewhere, in the same\\nor other packages, should be inlined.\\n\\nInlining can be used to move off of a deprecated function:\\n\\n\\t// Deprecated: prefer Pow(x, 2).\\n\\t//go:fix inline\\n\\tfunc Square(x int) int { return Pow(x, 2) }\\n\\nIt can also be used to move off of an obsolete package,\\nas when the import path has changed or a higher major version is available:\\n\\n\\tpackage pkg\\n\\n\\timport pkg2 \\\"pkg/v2\\\"\\n\\n\\t//go:fix inline\\n\\tfunc F() { pkg2.F(nil) }\\n\\nReplacing a call pkg.F() by pkg2.F(nil) can have no effect on the program,\\nso this mechanism provides a low-risk way to update large numbers of calls.\\nWe recommend, where possible, expressing the old API in terms of the new one\\nto enable automatic migration.\\n\\nThe inliner takes care to avoid behavior changes, even subtle ones,\\nsuch as changes to the order in which argument expressions are\\nevaluated. When it cannot safely eliminate all parameter variables,\\nit may introduce a \\\"binding declaration\\\" of the form\\n\\n\\tvar params = args\\n\\nto evaluate argument expressions in the correct order and bind them to\\nparameter variables. Since the resulting code transformation may be\\nstylistically suboptimal, such inlinings may be disabled by specifying\\nthe -inline.allow_binding_decl=false flag to the analyzer driver.\\n\\n(In cases where it is not safe to \\\"reduce\\\" a call—that is, to replace\\na call f(x) by the body of function f, suitably substituted—the\\ninliner machinery is capable of replacing f by a function literal,\\nfunc(){...}(). However, the inline analyzer discards all such\\n\\\"literalizations\\\" unconditionally, again on grounds of style.)\\n\\n## Constants\\n\\nGiven a constant that is marked for inlining, like this one:\\n\\n\\t//go:fix inline\\n\\tconst Ptr = Pointer\\n\\nthis analyzer will recommend that uses of Ptr should be replaced with Pointer.\\n\\nAs with functions, inlining can be used to replace deprecated constants and\\nconstants in obsolete packages.\\n\\nA constant definition can be marked for inlining only if it refers to another\\nnamed constant.\\n\\nThe \\\"//go:fix inline\\\" comment must appear before a single const declaration on its own,\\nas above; before a const declaration that is part of a group, as in this case:\\n\\n\\tconst (\\n\\t   C = 1\\n\\t   //go:fix inline\\n\\t   Ptr = Pointer\\n\\t)\\n\\nor before a group, applying to every constant in the group:\\n\\n\\t//go:fix inline\\n\\tconst (\\n\\t\\tPtr = Pointer\\n\\t    Val = Value\\n\\t)\\n\\nThe proposal https://go.dev/issue/32816 introduces the \\\"//go:fix inline\\\" directives.\\n\\nYou can use this command to apply inline fixes en masse:\\n\\n\\t$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"loopclosure\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check references to loop variables from within nested functions\\n\\nThis analyzer reports places where a function literal references the\\niteration variable of an enclosing loop, and the loop calls the function\\nin such a way (e.g. with go or defer) that it may outlive the loop\\niteration and possibly observe the wrong value of the variable.\\n\\nNote: An iteration variable can only outlive a loop iteration in Go versions \\u003c=1.21.\\nIn Go 1.22 and later, the loop variable lifetimes changed to create a new\\niteration variable per loop iteration. (See go.dev/issue/60078.)\\n\\nIn this example, all the deferred functions run after the loop has\\ncompleted, so all observe the final value of v [\\u003cgo1.22].\\n\\n\\tfor _, v := range list {\\n\\t    defer func() {\\n\\t        use(v) // incorrect\\n\\t    }()\\n\\t}\\n\\nOne fix is to create a new variable for each iteration of the loop:\\n\\n\\tfor _, v := range list {\\n\\t    v := v // new var per iteration\\n\\t    defer func() {\\n\\t        use(v) // ok\\n\\t    }()\\n\\t}\\n\\nAfter Go version 1.22, the previous two for loops are equivalent\\nand both are correct.\\n\\nThe next example uses a go statement and has a similar problem [\\u003cgo1.22].\\nIn addition, it has a data race because the loop updates v\\nconcurrent with the goroutines accessing it.\\n\\n\\tfor _, v := range elem {\\n\\t    go func() {\\n\\t        use(v)  // incorrect, and a data race\\n\\t    }()\\n\\t}\\n\\nA fix is the same as before. The checker also reports problems\\nin goroutines started by golang.org/x/sync/errgroup.Group.\\nA hard-to-spot variant of this form is common in parallel tests:\\n\\n\\tfunc Test(t *testing.T) {\\n\\t    for _, test := range tests {\\n\\t        t.Run(test.name, func(t *testing.T) {\\n\\t            t.Parallel()\\n\\t            use(test) // incorrect, and a data race\\n\\t        })\\n\\t    }\\n\\t}\\n\\nThe t.Parallel() call causes the rest of the function to execute\\nconcurrent with the loop [\\u003cgo1.22].\\n\\nThe analyzer reports references only in the last statement,\\nas it is not deep enough to understand the effects of subsequent\\nstatements that might render the reference benign.\\n(\\\"Last statement\\\" is defined recursively in compound\\nstatements such as if, switch, and select.)\\n\\nSee: https://golang.org/doc/go_faq.html#closures_and_goroutines\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"lostcancel\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check cancel func returned by context.WithCancel is called\\n\\nThe cancellation function returned by context.WithCancel, WithTimeout,\\nWithDeadline and variants such as WithCancelCause must be called,\\nor the new context will remain live until its parent context is cancelled.\\n(The background context is never cancelled.)\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"maprange\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"checks for unnecessary calls to maps.Keys and maps.Values in range statements\\n\\nConsider a loop written like this:\\n\\n\\tfor val := range maps.Values(m) {\\n\\t\\tfmt.Println(val)\\n\\t}\\n\\nThis should instead be written without the call to maps.Values:\\n\\n\\tfor _, val := range m {\\n\\t\\tfmt.Println(val)\\n\\t}\\n\\ngolang.org/x/exp/maps returns slices for Keys/Values instead of iterators,\\nbut unnecessary calls should similarly be removed:\\n\\n\\tfor _, key := range maps.Keys(m) {\\n\\t\\tfmt.Println(key)\\n\\t}\\n\\nshould be rewritten as:\\n\\n\\tfor key := range m {\\n\\t\\tfmt.Println(key)\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"mapsloop\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace explicit loops over maps with calls to maps package\\n\\nThe mapsloop analyzer replaces loops of the form\\n\\n\\tfor k, v := range x { m[k] = v }\\n\\nwith a single call to a function from the `maps` package, added in Go 1.23.\\nDepending on the context, this could be `maps.Copy`, `maps.Insert`,\\n`maps.Clone`, or `maps.Collect`.\\n\\nThe transformation to `maps.Clone` is applied conservatively, as it\\npreserves the nilness of the source map, which may be a subtle change in\\nbehavior if the original code did not handle a nil map in the same way.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"minmax\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace if/else statements with calls to min or max\\n\\nThe minmax analyzer simplifies conditional assignments by suggesting the use\\nof the built-in `min` and `max` functions, introduced in Go 1.21. For example,\\n\\n\\tif a \\u003c b { x = a } else { x = b }\\n\\nis replaced by\\n\\n\\tx = min(a, b).\\n\\nThis analyzer avoids making suggestions for floating-point types,\\nas the behavior of `min` and `max` with NaN values can differ from\\nthe original if/else statement.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"newexpr\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"simplify code by using go1.26's new(expr)\\n\\nThis analyzer finds declarations of functions of this form:\\n\\n\\tfunc varOf(x int) *int { return \\u0026x }\\n\\nand suggests a fix to turn them into inlinable wrappers around\\ngo1.26's built-in new(expr) function:\\n\\n\\t//go:fix inline\\n\\tfunc varOf(x int) *int { return new(x) }\\n\\n(The directive comment causes the 'inline' analyzer to suggest\\nthat calls to such functions are inlined.)\\n\\nIn addition, this analyzer suggests a fix for each call\\nto one of the functions before it is transformed, so that\\n\\n\\tuse(varOf(123))\\n\\nis replaced by:\\n\\n\\tuse(new(123))\\n\\nWrapper functions such as varOf are common when working with Go\\nserialization packages such as for JSON or protobuf, where pointers\\nare often used to express optionality.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"nilfunc\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for useless comparisons between functions and nil\\n\\nA useless comparison is one like f == nil as opposed to f() == nil.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"nilness\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for redundant or impossible nil comparisons\\n\\nThe nilness checker inspects the control-flow graph of each function in\\na package and reports nil pointer dereferences, degenerate nil\\npointers, and panics with nil values. A degenerate comparison is of the form\\nx==nil or x!=nil where x is statically known to be nil or non-nil. These are\\noften a mistake, especially in control flow related to errors. Panics with nil\\nvalues are checked because they are not detectable by\\n\\n\\tif r := recover(); r != nil {\\n\\nThis check reports conditions such as:\\n\\n\\tif f == nil { // impossible condition (f is a function)\\n\\t}\\n\\nand:\\n\\n\\tp := \\u0026v\\n\\t...\\n\\tif p != nil { // tautological condition\\n\\t}\\n\\nand:\\n\\n\\tif p == nil {\\n\\t\\tprint(*p) // nil dereference\\n\\t}\\n\\nand:\\n\\n\\tif p == nil {\\n\\t\\tpanic(p)\\n\\t}\\n\\nSometimes the control flow may be quite complex, making bugs hard\\nto spot. In the example below, the err.Error expression is\\nguaranteed to panic because, after the first return, err must be\\nnil. The intervening loop is just a distraction.\\n\\n\\t...\\n\\terr := g.Wait()\\n\\tif err != nil {\\n\\t\\treturn err\\n\\t}\\n\\tpartialSuccess := false\\n\\tfor _, err := range errs {\\n\\t\\tif err == nil {\\n\\t\\t\\tpartialSuccess = true\\n\\t\\t\\tbreak\\n\\t\\t}\\n\\t}\\n\\tif partialSuccess {\\n\\t\\treportStatus(StatusMessage{\\n\\t\\t\\tCode:   code.ERROR,\\n\\t\\t\\tDetail: err.Error(), // \\\"nil dereference in dynamic method call\\\"\\n\\t\\t})\\n\\t\\treturn nil\\n\\t}\\n\\n...\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"nonewvars\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"suggested fixes for \\\"no new vars on left side of :=\\\"\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"no new vars on left side of :=\\\". For example:\\n\\n\\tz := 1\\n\\tz := 2\\n\\nwill turn into\\n\\n\\tz := 1\\n\\tz = 2\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"noresultvalues\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"suggested fixes for unexpected return values\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"no result values expected\\\" or \\\"too many return values\\\".\\nFor example:\\n\\n\\tfunc z() { return nil }\\n\\nwill turn into\\n\\n\\tfunc z() { return }\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"omitzero\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"suggest replacing omitempty with omitzero for struct fields\\n\\nThe omitzero analyzer identifies uses of the `omitempty` JSON struct\\ntag on fields that are themselves structs. For struct-typed fields,\\nthe `omitempty` tag has no effect on the behavior of json.Marshal and\\njson.Unmarshal. The analyzer offers two suggestions: either remove the\\ntag, or replace it with `omitzero` (added in Go 1.24), which correctly\\nomits the field if the struct value is zero.\\n\\nHowever, some other serialization packages (notably kubebuilder, see\\nhttps://book.kubebuilder.io/reference/markers.html) may have their own\\ninterpretation of the `json:\\\",omitzero\\\"` tag, so removing it may affect\\nprogram behavior. For this reason, the omitzero modernizer will not\\nmake changes in any package that contains +kubebuilder annotations.\\n\\nReplacing `omitempty` with `omitzero` is a change in behavior. The\\noriginal code would always encode the struct field, whereas the\\nmodified code will omit it if it is a zero-value.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"plusbuild\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"remove obsolete //+build comments\\n\\nThe plusbuild analyzer suggests a fix to remove obsolete build tags\\nof the form:\\n\\n\\t//+build linux,amd64\\n\\nin files that also contain a Go 1.18-style tag such as:\\n\\n\\t//go:build linux \\u0026\\u0026 amd64\\n\\n(It does not check that the old and new tags are consistent;\\nthat is the job of the 'buildtag' analyzer in the vet suite.)\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"printf\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check consistency of Printf format strings and arguments\\n\\nThe check applies to calls of the formatting functions such as\\n[fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of\\nthose functions such as [log.Printf]. It reports a variety of\\nmistakes such as syntax errors in the format string and mismatches\\n(of number and type) between the verbs and their arguments.\\n\\nSee the documentation of the fmt package for the complete set of\\nformat operators and their operand types.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"rangeint\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace 3-clause for loops with for-range over integers\\n\\nThe rangeint analyzer suggests replacing traditional for loops such\\nas\\n\\n\\tfor i := 0; i \\u003c n; i++ { ... }\\n\\nwith the more idiomatic Go 1.22 style:\\n\\n\\tfor i := range n { ... }\\n\\nThis transformation is applied only if (a) the loop variable is not\\nmodified within the loop body and (b) the loop's limit expression\\nis not modified within the loop, as `for range` evaluates its\\noperand only once.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"recursiveiter\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for inefficient recursive iterators\\n\\nThis analyzer reports when a function that returns an iterator\\n(iter.Seq or iter.Seq2) calls itself as the operand of a range\\nstatement, as this is inefficient.\\n\\nWhen implementing an iterator (e.g. iter.Seq[T]) for a recursive\\ndata type such as a tree or linked list, it is tempting to\\nrecursively range over the iterator for each child element.\\n\\nHere's an example of a naive iterator over a binary tree:\\n\\n\\ttype tree struct {\\n\\t\\tvalue       int\\n\\t\\tleft, right *tree\\n\\t}\\n\\n\\tfunc (t *tree) All() iter.Seq[int] {\\n\\t\\treturn func(yield func(int) bool) {\\n\\t\\t\\tif t != nil {\\n\\t\\t\\t\\tfor elem := range t.left.All() { // \\\"inefficient recursive iterator\\\"\\n\\t\\t\\t\\t\\tif !yield(elem) {\\n\\t\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif !yield(t.value) {\\n\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor elem := range t.right.All() { // \\\"inefficient recursive iterator\\\"\\n\\t\\t\\t\\t\\tif !yield(elem) {\\n\\t\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\nThough it correctly enumerates the elements of the tree, it hides a\\nsignificant performance problem--two, in fact. Consider a balanced\\ntree of N nodes. Iterating the root node will cause All to be\\ncalled once on every node of the tree. This results in a chain of\\nnested active range-over-func statements when yield(t.value) is\\ncalled on a leaf node.\\n\\nThe first performance problem is that each range-over-func\\nstatement must typically heap-allocate a variable, so iteration of\\nthe tree allocates as many variables as there are elements in the\\ntree, for a total of O(N) allocations, all unnecessary.\\n\\nThe second problem is that each call to yield for a leaf of the\\ntree causes each of the enclosing range loops to receive a value,\\nwhich they then immediately pass on to their respective yield\\nfunction. This results in a chain of log(N) dynamic yield calls per\\nelement, a total of O(N*log N) dynamic calls overall, when only\\nO(N) are necessary.\\n\\nA better implementation strategy for recursive iterators is to\\nfirst define the \\\"every\\\" operator for your recursive data type,\\nwhere every(f) reports whether an arbitrary predicate f(x) is true\\nfor every element x in the data type. For our tree, the every\\nfunction would be:\\n\\n\\tfunc (t *tree) every(f func(int) bool) bool {\\n\\t\\treturn t == nil ||\\n\\t\\t\\tt.left.every(f) \\u0026\\u0026 f(t.value) \\u0026\\u0026 t.right.every(f)\\n\\t}\\n\\nFor example, this use of the every operator prints whether every\\nelement in the tree is an even number:\\n\\n\\teven := func(x int) bool { return x\\u00261 == 0 }\\n\\tprintln(t.every(even))\\n\\nThen the iterator can be simply expressed as a trivial wrapper\\naround the every operator:\\n\\n\\tfunc (t *tree) All() iter.Seq[int] {\\n\\t\\treturn func(yield func(int) bool) {\\n\\t\\t\\t_ = t.every(yield)\\n\\t\\t}\\n\\t}\\n\\nIn effect, tree.All computes whether yield returns true for each\\nelement, short-circuiting if it ever returns false, then discards\\nthe final boolean result.\\n\\nThis has much better performance characteristics: it makes one\\ndynamic call per element of the tree, and it doesn't heap-allocate\\nanything. It is also clearer.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"reflecttypefor\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace reflect.TypeOf(x) with TypeFor[T]()\\n\\nThis analyzer suggests fixes to replace uses of reflect.TypeOf(x) with\\nreflect.TypeFor, introduced in go1.22, when the desired runtime type\\nis known at compile time, for example:\\n\\n\\treflect.TypeOf(uint32(0))        -\\u003e reflect.TypeFor[uint32]()\\n\\treflect.TypeOf((*ast.File)(nil)) -\\u003e reflect.TypeFor[*ast.File]()\\n\\nIt also offers a fix to simplify the constructions below, which use\\nreflect.TypeOf to return the runtime type for an interface type,\\n\\n\\treflect.TypeOf((*io.Reader)(nil)).Elem()\\n\\nor:\\n\\n\\treflect.TypeOf([]io.Reader(nil)).Elem()\\n\\nto:\\n\\n\\treflect.TypeFor[io.Reader]()\\n\\nNo fix is offered in cases when the runtime type is dynamic, such as:\\n\\n\\tvar r io.Reader = ...\\n\\treflect.TypeOf(r)\\n\\nor when the operand has potential side effects.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"shadow\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for possible unintended shadowing of variables\\n\\nThis analyzer check for shadowed variables.\\nA shadowed variable is a variable declared in an inner scope\\nwith the same name and type as a variable in an outer scope,\\nand where the outer variable is mentioned after the inner one\\nis declared.\\n\\n(This definition can be refined; the module generates too many\\nfalse positives and is not yet enabled by default.)\\n\\nFor example:\\n\\n\\tfunc BadRead(f *os.File, buf []byte) error {\\n\\t\\tvar err error\\n\\t\\tfor {\\n\\t\\t\\tn, err := f.Read(buf) // shadows the function variable 'err'\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tbreak // causes return of wrong value\\n\\t\\t\\t}\\n\\t\\t\\tfoo(buf)\\n\\t\\t}\\n\\t\\treturn err\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"shift\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for shifts that equal or exceed the width of the integer\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"sigchanyzer\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unbuffered channel of os.Signal\\n\\nThis checker reports call expression of the form\\n\\n\\tsignal.Notify(c \\u003c-chan os.Signal, sig ...os.Signal),\\n\\nwhere c is an unbuffered channel, which can be at risk of missing the signal.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"simplifycompositelit\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for composite literal simplifications\\n\\nAn array, slice, or map composite literal of the form:\\n\\n\\t[]T{T{}, T{}}\\n\\nwill be simplified to:\\n\\n\\t[]T{{}, {}}\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"simplifyrange\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for range statement simplifications\\n\\nA range of the form:\\n\\n\\tfor x, _ = range v {...}\\n\\nwill be simplified to:\\n\\n\\tfor x = range v {...}\\n\\nA range of the form:\\n\\n\\tfor _ = range v {...}\\n\\nwill be simplified to:\\n\\n\\tfor range v {...}\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"simplifyslice\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for slice simplifications\\n\\nA slice expression of the form:\\n\\n\\ts[a:len(s)]\\n\\nwill be simplified to:\\n\\n\\ts[a:]\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"slicescontains\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace loops with slices.Contains or slices.ContainsFunc\\n\\nThe slicescontains analyzer simplifies loops that check for the existence of\\nan element in a slice. It replaces them with calls to `slices.Contains` or\\n`slices.ContainsFunc`, which were added in Go 1.21.\\n\\nIf the expression for the target element has side effects, this\\ntransformation will cause those effects to occur only once, not\\nonce per tested slice element.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"slicesdelete\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace append-based slice deletion with slices.Delete\\n\\nThe slicesdelete analyzer suggests replacing the idiom\\n\\n\\ts = append(s[:i], s[j:]...)\\n\\nwith the more explicit\\n\\n\\ts = slices.Delete(s, i, j)\\n\\nintroduced in Go 1.21.\\n\\nThis analyzer is disabled by default. The `slices.Delete` function\\nzeros the elements between the new length and the old length of the\\nslice to prevent memory leaks, which is a subtle difference in\\nbehavior compared to the append-based idiom; see https://go.dev/issue/73686.\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"slicessort\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace sort.Slice with slices.Sort for basic types\\n\\nThe slicessort analyzer simplifies sorting slices of basic ordered\\ntypes. It replaces\\n\\n\\tsort.Slice(s, func(i, j int) bool { return s[i] \\u003c s[j] })\\n\\nwith the simpler `slices.Sort(s)`, which was added in Go 1.21.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"slog\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for invalid structured logging calls\\n\\nThe slog checker looks for calls to functions from the log/slog\\npackage that take alternating key-value pairs. It reports calls\\nwhere an argument in a key position is neither a string nor a\\nslog.Attr, and where a final key is missing its value.\\nFor example,it would report\\n\\n\\tslog.Warn(\\\"message\\\", 11, \\\"k\\\") // slog.Warn arg \\\"11\\\" should be a string or a slog.Attr\\n\\nand\\n\\n\\tslog.Info(\\\"message\\\", \\\"k1\\\", v1, \\\"k2\\\") // call to slog.Info missing a final value\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"sortslice\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check the argument type of sort.Slice\\n\\nsort.Slice requires an argument of a slice type. Check that\\nthe interface{} value passed to sort.Slice is actually a slice.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stditerators\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"use iterators instead of Len/At-style APIs\\n\\nThis analyzer suggests a fix to replace each loop of the form:\\n\\n\\tfor i := 0; i \\u003c x.Len(); i++ {\\n\\t\\tuse(x.At(i))\\n\\t}\\n\\nor its \\\"for elem := range x.Len()\\\" equivalent by a range loop over an\\niterator offered by the same data type:\\n\\n\\tfor elem := range x.All() {\\n\\t\\tuse(x.At(i)\\n\\t}\\n\\nwhere x is one of various well-known types in the standard library.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stdmethods\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check signature of methods of well-known interfaces\\n\\nSometimes a type may be intended to satisfy an interface but may fail to\\ndo so because of a mistake in its method signature.\\nFor example, the result of this WriteTo method should be (int64, error),\\nnot error, to satisfy io.WriterTo:\\n\\n\\ttype myWriterTo struct{...}\\n\\tfunc (myWriterTo) WriteTo(w io.Writer) error { ... }\\n\\nThis check ensures that each method whose name matches one of several\\nwell-known interface methods from the standard library has the correct\\nsignature for that interface.\\n\\nChecked method names include:\\n\\n\\tFormat GobEncode GobDecode MarshalJSON MarshalXML\\n\\tPeek ReadByte ReadFrom ReadRune Scan Seek\\n\\tUnmarshalJSON UnreadByte UnreadRune WriteByte\\n\\tWriteTo\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stdversion\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report uses of too-new standard library symbols\\n\\nThe stdversion analyzer reports references to symbols in the standard\\nlibrary that were introduced by a Go release higher than the one in\\nforce in the referring file. (Recall that the file's Go version is\\ndefined by the 'go' directive its module's go.mod file, or by a\\n\\\"//go:build go1.X\\\" build tag at the top of the file.)\\n\\nThe analyzer does not report a diagnostic for a reference to a \\\"too\\nnew\\\" field or method of a type that is itself \\\"too new\\\", as this may\\nhave false positives, for example if fields or methods are accessed\\nthrough a type alias that is guarded by a Go version constraint.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stringintconv\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for string(int) conversions\\n\\nThis checker flags conversions of the form string(x) where x is an integer\\n(but not byte or rune) type. Such conversions are discouraged because they\\nreturn the UTF-8 representation of the Unicode code point x, and not a decimal\\nstring representation of x as one might expect. Furthermore, if x denotes an\\ninvalid code point, the conversion cannot be statically rejected.\\n\\nFor conversions that intend on using the code point, consider replacing them\\nwith string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the\\nstring representation of the value in the desired base.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stringsbuilder\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace += with strings.Builder\\n\\nThis analyzer replaces repeated string += string concatenation\\noperations with calls to Go 1.10's strings.Builder.\\n\\nFor example:\\n\\n\\tvar s = \\\"[\\\"\\n\\tfor x := range seq {\\n\\t\\ts += x\\n\\t\\ts += \\\".\\\"\\n\\t}\\n\\ts += \\\"]\\\"\\n\\tuse(s)\\n\\nis replaced by:\\n\\n\\tvar s strings.Builder\\n\\ts.WriteString(\\\"[\\\")\\n\\tfor x := range seq {\\n\\t\\ts.WriteString(x)\\n\\t\\ts.WriteString(\\\".\\\")\\n\\t}\\n\\ts.WriteString(\\\"]\\\")\\n\\tuse(s.String())\\n\\nThis avoids quadratic memory allocation and improves performance.\\n\\nThe analyzer requires that all references to s before the final uses\\nare += operations. To avoid warning about trivial cases, at least one\\nmust appear within a loop. The variable s must be a local\\nvariable, not a global or parameter.\\n\\nAll uses of the finished string must come after the last += operation.\\nEach such use will be replaced by a call to strings.Builder's String method.\\n(These may appear within an intervening loop or function literal, since even\\nif s.String() is called repeatedly, it does not allocate memory.)\\n\\nOften the addend is a call to fmt.Sprintf, as in this example:\\n\\n\\tvar s string\\n\\tfor x := range seq {\\n\\t\\ts += fmt.Sprintf(\\\"%v\\\", x)\\n\\t}\\n\\nwhich, once the suggested fix is applied, becomes:\\n\\n\\tvar s strings.Builder\\n\\tfor x := range seq {\\n\\t\\ts.WriteString(fmt.Sprintf(\\\"%v\\\", x))\\n\\t}\\n\\nThe WriteString call can be further simplified to the more efficient\\nfmt.Fprintf(\\u0026s, \\\"%v\\\", x), avoiding the allocation of an intermediary.\\nHowever, stringsbuilder does not perform this simplification;\\nit requires staticcheck analyzer QF1012. (See https://go.dev/issue/76918.)\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stringscut\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace strings.Index etc. with strings.Cut\\n\\nThis analyzer replaces certain patterns of use of [strings.Index] and string slicing by [strings.Cut], added in go1.18.\\n\\nFor example:\\n\\n\\tidx := strings.Index(s, substr)\\n\\tif idx \\u003e= 0 {\\n\\t    return s[:idx]\\n\\t}\\n\\nis replaced by:\\n\\n\\tbefore, _, ok := strings.Cut(s, substr)\\n\\tif ok {\\n\\t    return before\\n\\t}\\n\\nAnd:\\n\\n\\tidx := strings.Index(s, substr)\\n\\tif idx \\u003e= 0 {\\n\\t    return\\n\\t}\\n\\nis replaced by:\\n\\n\\tfound := strings.Contains(s, substr)\\n\\tif found {\\n\\t    return\\n\\t}\\n\\nIt also handles variants using [strings.IndexByte] instead of Index, or the bytes package instead of strings.\\n\\nFixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stringscutprefix\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace HasPrefix/TrimPrefix with CutPrefix\\n\\nThe stringscutprefix analyzer simplifies a common pattern where code first\\nchecks for a prefix with `strings.HasPrefix` and then removes it with\\n`strings.TrimPrefix`. It replaces this two-step process with a single call\\nto `strings.CutPrefix`, introduced in Go 1.20. The analyzer also handles\\nthe equivalent functions in the `bytes` package.\\n\\nFor example, this input:\\n\\n\\tif strings.HasPrefix(s, prefix) {\\n\\t    use(strings.TrimPrefix(s, prefix))\\n\\t}\\n\\nis fixed to:\\n\\n\\tif after, ok := strings.CutPrefix(s, prefix); ok {\\n\\t    use(after)\\n\\t}\\n\\nThe analyzer also offers fixes to use CutSuffix in a similar way.\\nThis input:\\n\\n\\tif strings.HasSuffix(s, suffix) {\\n\\t    use(strings.TrimSuffix(s, suffix))\\n\\t}\\n\\nis fixed to:\\n\\n\\tif before, ok := strings.CutSuffix(s, suffix); ok {\\n\\t    use(before)\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"stringsseq\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace ranging over Split/Fields with SplitSeq/FieldsSeq\\n\\nThe stringsseq analyzer improves the efficiency of iterating over substrings.\\nIt replaces\\n\\n\\tfor range strings.Split(...)\\n\\nwith the more efficient\\n\\n\\tfor range strings.SplitSeq(...)\\n\\nwhich was added in Go 1.24 and avoids allocating a slice for the\\nsubstrings. The analyzer also handles strings.Fields and the\\nequivalent functions in the bytes package.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"structtag\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check that struct field tags conform to reflect.StructTag.Get\\n\\nAlso report certain struct tags (json, xml) used with unexported fields.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"testingcontext\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace context.WithCancel with t.Context in tests\\n\\nThe testingcontext analyzer simplifies context management in tests. It\\nreplaces the manual creation of a cancellable context,\\n\\n\\tctx, cancel := context.WithCancel(context.Background())\\n\\tdefer cancel()\\n\\nwith a single call to t.Context(), which was added in Go 1.24.\\n\\nThis change is only suggested if the `cancel` function is not used\\nfor any other purpose.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"testinggoroutine\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report calls to (*testing.T).Fatal from goroutines started by a test\\n\\nFunctions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and\\nSkip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.\\nThis checker detects calls to these functions that occur within a goroutine\\nstarted by the test. For example:\\n\\n\\tfunc TestFoo(t *testing.T) {\\n\\t    go func() {\\n\\t        t.Fatal(\\\"oops\\\") // error: (*T).Fatal called from non-test goroutine\\n\\t    }()\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"tests\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for common mistaken usages of tests and examples\\n\\nThe tests checker walks Test, Benchmark, Fuzzing and Example functions checking\\nmalformed names, wrong signatures and examples documenting non-existent\\nidentifiers.\\n\\nPlease see the documentation for package testing in golang.org/pkg/testing\\nfor the conventions that are enforced for Tests, Benchmarks, and Examples.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"timeformat\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for calls of (time.Time).Format or time.Parse with 2006-02-01\\n\\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\\nformat. Internationally, \\\"yyyy-dd-mm\\\" does not occur in common calendar date\\nstandards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unmarshal\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report passing non-pointer or non-interface values to unmarshal\\n\\nThe unmarshal analysis reports calls to functions such as json.Unmarshal\\nin which the argument type is not a pointer or an interface.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unreachable\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unreachable code\\n\\nThe unreachable analyzer finds statements that execution can never reach\\nbecause they are preceded by a return statement, a call to panic, an\\ninfinite loop, or similar constructs.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unsafefuncs\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace unsafe pointer arithmetic with function calls\\n\\nThe unsafefuncs analyzer simplifies pointer arithmetic expressions by\\nreplacing them with calls to helper functions such as unsafe.Add,\\nadded in Go 1.17.\\n\\nExample:\\n\\n\\tunsafe.Pointer(uintptr(ptr) + uintptr(n))\\n\\nwhere ptr is an unsafe.Pointer, is replaced by:\\n\\n\\tunsafe.Add(ptr, n)\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unsafeptr\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for invalid conversions of uintptr to unsafe.Pointer\\n\\nThe unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer\\nto convert integers to pointers. A conversion from uintptr to\\nunsafe.Pointer is invalid if it implies that there is a uintptr-typed\\nword in memory that holds a pointer value, because that word will be\\ninvisible to stack copying and to the garbage collector.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unusedfunc\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unused functions, methods, etc\\n\\nThe unusedfunc analyzer reports functions and methods that are\\nnever referenced outside of their own declaration.\\n\\nA function is considered unused if it is unexported and not\\nreferenced (except within its own declaration).\\n\\nA method is considered unused if it is unexported, not referenced\\n(except within its own declaration), and its name does not match\\nthat of any method of an interface type declared within the same\\npackage.\\n\\nThe tool may report false positives in some situations, for\\nexample:\\n\\n  - for a declaration of an unexported function that is referenced\\n    from another package using the go:linkname mechanism, if the\\n    declaration's doc comment does not also have a go:linkname\\n    comment.\\n\\n    (Such code is in any case strongly discouraged: linkname\\n    annotations, if they must be used at all, should be used on both\\n    the declaration and the alias.)\\n\\n  - for compiler intrinsics in the \\\"runtime\\\" package that, though\\n    never referenced, are known to the compiler and are called\\n    indirectly by compiled object code.\\n\\n  - for functions called only from assembly.\\n\\n  - for functions called only from files whose build tags are not\\n    selected in the current build configuration.\\n\\nSince these situations are relatively common in the low-level parts\\nof the runtime, this analyzer ignores the standard library.\\nSee https://go.dev/issue/71686 and https://go.dev/issue/74130 for\\nfurther discussion of these limitations.\\n\\nThe unusedfunc algorithm is not as precise as the\\ngolang.org/x/tools/cmd/deadcode tool, but it has the advantage that\\nit runs within the modular analysis framework, enabling near\\nreal-time feedback within gopls.\\n\\nThe unusedfunc analyzer also reports unused types, vars, and\\nconstants. Enums--constants defined with iota--are ignored since\\neven the unused values must remain present to preserve the logical\\nordering.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unusedparams\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unused parameters of functions\\n\\nThe unusedparams analyzer checks functions to see if there are\\nany parameters that are not being used.\\n\\nTo ensure soundness, it ignores:\\n  - \\\"address-taken\\\" functions, that is, functions that are used as\\n    a value rather than being called directly; their signatures may\\n    be required to conform to a func type.\\n  - exported functions or methods, since they may be address-taken\\n    in another package.\\n  - unexported methods whose name matches an interface method\\n    declared in the same package, since the method's signature\\n    may be required to conform to the interface type.\\n  - functions with empty bodies, or containing just a call to panic.\\n  - parameters that are unnamed, or named \\\"_\\\", the blank identifier.\\n\\nThe analyzer suggests a fix of replacing the parameter name by \\\"_\\\",\\nbut in such cases a deeper fix can be obtained by invoking the\\n\\\"Refactor: remove unused parameter\\\" code action, which will\\neliminate the parameter entirely, along with all corresponding\\narguments at call sites, while taking care to preserve any side\\neffects in the argument expressions; see\\nhttps://github.com/golang/tools/releases/tag/gopls%2Fv0.14.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unusedresult\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unused results of calls to some functions\\n\\nSome functions like fmt.Errorf return a result and have no side\\neffects, so it is always a mistake to discard the result. Other\\nfunctions may return an error that must not be ignored, or a cleanup\\noperation that must be called. This analyzer reports calls to\\nfunctions like these when the result of the call is ignored.\\n\\nThe set of functions may be controlled using flags.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unusedvariable\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for unused variables and suggest fixes\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"unusedwrite\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"checks for unused writes\\n\\nThe analyzer reports instances of writes to struct fields and\\narrays that are never read. Specifically, when a struct object\\nor an array is copied, its elements are copied implicitly by\\nthe compiler, and any element write to this copy does nothing\\nwith the original object.\\n\\nFor example:\\n\\n\\ttype T struct { x int }\\n\\n\\tfunc f(input []T) {\\n\\t\\tfor i, v := range input {  // v is a copy\\n\\t\\t\\tv.x = i  // unused write to field x\\n\\t\\t}\\n\\t}\\n\\nAnother example is about non-pointer receiver:\\n\\n\\ttype T struct { x int }\\n\\n\\tfunc (t T) f() {  // t is a copy\\n\\t\\tt.x = i  // unused write to field x\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"waitgroup\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"check for misuses of sync.WaitGroup\\n\\nThis analyzer detects mistaken calls to the (*sync.WaitGroup).Add\\nmethod from inside a new goroutine, causing Add to race with Wait:\\n\\n\\t// WRONG\\n\\tvar wg sync.WaitGroup\\n\\tgo func() {\\n\\t        wg.Add(1) // \\\"WaitGroup.Add called from inside new goroutine\\\"\\n\\t        defer wg.Done()\\n\\t        ...\\n\\t}()\\n\\twg.Wait() // (may return prematurely before new goroutine starts)\\n\\nThe correct code calls Add before starting the goroutine:\\n\\n\\t// RIGHT\\n\\tvar wg sync.WaitGroup\\n\\twg.Add(1)\\n\\tgo func() {\\n\\t\\tdefer wg.Done()\\n\\t\\t...\\n\\t}()\\n\\twg.Wait()\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"waitgroupgo\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"replace wg.Add(1)/go/wg.Done() with wg.Go\\n\\nThe waitgroupgo analyzer simplifies goroutine management with `sync.WaitGroup`.\\nIt replaces the common pattern\\n\\n\\twg.Add(1)\\n\\tgo func() {\\n\\t\\tdefer wg.Done()\\n\\t\\t...\\n\\t}()\\n\\nwith a single call to\\n\\n\\twg.Go(func(){ ... })\\n\\nwhich was added in Go 1.25.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"writestring\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"detect inefficient string concatenation in uses of WriteString\\n\\nThe writestring analyzer offers to replace a call to WriteString(x + y) by\\ntwo calls WriteString(x); WriteString(y). This is more efficient because it\\navoids the additional memory allocation produced by string concatenation;\\ninstead we just write each string into the buffer directly.\\n\\nIt explicitly looks for calls to certain well-known writers such as\\nbytes.Buffer, strings.Builder and bufio.Writer. The analyzer will not suggest\\na fix for calls to, say, (*os.File).WriteString, because for certain kinds of\\nfile such as a UDP socket, it could split a single message into two.\\nSimilarly it does not offer fixes when the type of the writer is unknown (as\\nin calls to io.WriteString).\\n\\nFor example:\\n\\n\\tfunc f(a string, b string) string {\\n\\t\\t var s strings.Builder\\n\\t\\t s.WriteString(a+b)\\n\\t\\t return s.String()\\n\\t}\\n\\nwould become:\\n\\n\\tfunc f(a string, b string) string {\\n\\t\\tvar s strings.Builder\\n\\t\\ts.WriteString(a)\\n\\t\\ts.WriteString(b)\\n\\t\\treturn s.String()\\n\\t}\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"yield\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"report calls to yield where the result is ignored\\n\\nAfter a yield function returns false, the caller should not call\\nthe yield function again; generally the iterator should return\\npromptly.\\n\\nThis example fails to check the result of the call to yield,\\ncausing this analyzer to report a diagnostic:\\n\\n\\tyield(1) // yield may be called again (on L2) after returning false\\n\\tyield(2)\\n\\nThe corrected code is either this:\\n\\n\\tif yield(1) { yield(2) }\\n\\nor simply:\\n\\n\\t_ = yield(1) \\u0026\\u0026 yield(2)\\n\\nIt is not always a mistake to ignore the result of yield.\\nFor example, this is a valid single-element iterator:\\n\\n\\tyield(1) // ok to ignore result\\n\\treturn\\n\\nIt is only a mistake when the yield call that returned false may be\\nfollowed by another call.\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{}\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"staticcheck\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"staticcheck configures the default set of analyses staticcheck.io.\\nThese analyses are documented on\\n[Staticcheck's website](https://staticcheck.io/docs/checks/).\\n\\nThe \\\"staticcheck\\\" option has three values:\\n- false: disable all staticcheck analyzers\\n- true: enable all staticcheck analyzers\\n- unset: enable a subset of staticcheck analyzers\\n  selected by gopls maintainers for runtime efficiency\\n  and analytic precision.\\n\\nRegardless of this setting, individual analyzers can be\\nselectively enabled or disabled using the `analyses` setting.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"staticcheckProvided\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"annotations\",\n\t\t\t\t\"Type\": \"map[enum]bool\",\n\t\t\t\t\"Doc\": \"annotations specifies the various kinds of compiler\\noptimization details that should be reported as diagnostics\\nwhen enabled for a package by the \\\"Toggle compiler\\noptimization details\\\" (`gopls.gc_details`) command.\\n\\n(Some users care only about one kind of annotation in their\\nprofiling efforts. More importantly, in large packages, the\\nnumber of annotations can sometimes overwhelm the user\\ninterface and exceed the per-file diagnostic limit.)\\n\\nTODO(adonovan): rename this field to CompilerOptDetail.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"bool\",\n\t\t\t\t\t\"Keys\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"bounds\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"bounds\\\"` controls bounds checking diagnostics.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"escape\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"escape\\\"` controls diagnostics about escape choices.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"inline\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"inline\\\"` controls diagnostics about inlining choices.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"nil\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"nil\\\"` controls nil checks.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{\\\"bounds\\\":true,\\\"escape\\\":true,\\\"inline\\\":true,\\\"nil\\\":true}\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"vulncheck\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"vulncheck enables vulnerability scanning.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Imports\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Imports\\\"`: In Imports mode, `gopls` will report vulnerabilities that affect packages\\ndirectly and indirectly used by the analyzed main module.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Off\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Off\\\"`: Disable vulnerability analysis.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Prompt\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Prompt\\\"`: Vulncheck can be triggered via prompt.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"Prompt\\\"\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"diagnosticsDelay\",\n\t\t\t\t\"Type\": \"time.Duration\",\n\t\t\t\t\"Doc\": \"diagnosticsDelay controls the amount of time that gopls waits\\nafter the most recent file modification before computing deep diagnostics.\\nSimple diagnostics (parsing and type-checking) are always run immediately\\non recently modified packages.\\n\\nThis option must be set to a valid duration string, for example `\\\"250ms\\\"`.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"\\\"1s\\\"\",\n\t\t\t\t\"Status\": \"advanced\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"diagnosticsTrigger\",\n\t\t\t\t\"Type\": \"enum\",\n\t\t\t\t\"Doc\": \"diagnosticsTrigger controls when to run diagnostics.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Edit\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Edit\\\"`: Trigger diagnostics on file edit and save. (default)\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Value\": \"\\\"Save\\\"\",\n\t\t\t\t\t\t\"Doc\": \"`\\\"Save\\\"`: Trigger diagnostics only on file save. Events like initial workspace load\\nor configuration change will still trigger diagnostics.\\n\",\n\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"Default\": \"\\\"Edit\\\"\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"analysisProgressReporting\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"analysisProgressReporting controls whether gopls sends progress\\nnotifications when construction of its index of analysis facts is taking a\\nlong time. Cancelling these notifications will cancel the indexing task,\\nthough it will restart after the next change in the workspace.\\n\\nWhen a package is opened for the first time and heavyweight analyses such as\\nstaticcheck are enabled, it can take a while to construct the index of\\nanalysis facts for all its dependencies. The index is cached in the\\nfilesystem, so subsequent analysis should be faster.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui.diagnostic\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"hints\",\n\t\t\t\t\"Type\": \"map[enum]bool\",\n\t\t\t\t\"Doc\": \"hints specify inlay hints that users want to see. A full list of hints\\nthat gopls uses can be found in\\n[inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"bool\",\n\t\t\t\t\t\"Keys\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"assignVariableTypes\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"assignVariableTypes\\\"` controls inlay hints for variable types in assign statements:\\n```go\\n\\ti/* int*/, j/* int*/ := 0, len(r)-1\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"compositeLiteralFields\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"compositeLiteralFields\\\"` inlay hints for composite literal field names:\\n```go\\n\\t{/*in: */\\\"Hello, world\\\", /*want: */\\\"dlrow ,olleH\\\"}\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"compositeLiteralTypes\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"compositeLiteralTypes\\\"` controls inlay hints for composite literal types:\\n```go\\n\\tfor _, c := range []struct {\\n\\t\\tin, want string\\n\\t}{\\n\\t\\t/*struct{ in string; want string }*/{\\\"Hello, world\\\", \\\"dlrow ,olleH\\\"},\\n\\t}\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"constantValues\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"constantValues\\\"` controls inlay hints for constant values:\\n```go\\n\\tconst (\\n\\t\\tKindNone   Kind = iota/* = 0*/\\n\\t\\tKindPrint/*  = 1*/\\n\\t\\tKindPrintf/* = 2*/\\n\\t\\tKindErrorf/* = 3*/\\n\\t)\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"functionTypeParameters\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"functionTypeParameters\\\"` inlay hints for implicit type parameters on generic functions:\\n```go\\n\\tmyFoo/*[int, string]*/(1, \\\"hello\\\")\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"ignoredError\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"ignoredError\\\"` inlay hints for implicitly discarded errors:\\n```go\\n\\tf.Close() // ignore error\\n```\\nThis check inserts an `// ignore error` hint following any\\nstatement that is a function call whose error result is\\nimplicitly ignored.\\n\\nTo suppress the hint, write an actual comment containing\\n\\\"ignore error\\\" following the call statement, or explicitly\\nassign the result to a blank variable. A handful of common\\nfunctions such as `fmt.Println` are excluded from the\\ncheck.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"parameterNames\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"parameterNames\\\"` controls inlay hints for parameter names:\\n```go\\n\\tparseInt(/* str: */ \\\"123\\\", /* radix: */ 8)\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"rangeVariableTypes\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"rangeVariableTypes\\\"` controls inlay hints for variable types in range statements:\\n```go\\n\\tfor k/* int*/, v/* string*/ := range []string{} {\\n\\t\\tfmt.Println(k, v)\\n\\t}\\n```\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{}\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui.inlayhint\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"codelenses\",\n\t\t\t\t\"Type\": \"map[enum]bool\",\n\t\t\t\t\"Doc\": \"codelenses overrides the enabled/disabled state of each of gopls'\\nsources of [Code Lenses](codelenses.md).\\n\\nExample Usage:\\n\\n```json5\\n\\\"gopls\\\": {\\n...\\n  \\\"codelenses\\\": {\\n    \\\"generate\\\": false,  // Don't show the `go generate` lens.\\n  }\\n...\\n}\\n```\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"bool\",\n\t\t\t\t\t\"Keys\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"generate\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"generate\\\"`: Run `go generate`\\n\\nThis codelens source annotates any `//go:generate` comments\\nwith commands to run `go generate` in this directory, on\\nall directories recursively beneath this one.\\n\\nSee [Generating code](https://go.dev/blog/generate) for\\nmore details.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"regenerate_cgo\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"regenerate_cgo\\\"`: Re-generate cgo declarations\\n\\nThis codelens source annotates an `import \\\"C\\\"` declaration\\nwith a command to re-run the [cgo\\ncommand](https://pkg.go.dev/cmd/cgo) to regenerate the\\ncorresponding Go declarations.\\n\\nUse this after editing the C code in comments attached to\\nthe import, or in C header files included by it.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"run_govulncheck\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"run_govulncheck\\\"`: Run govulncheck (legacy)\\n\\nThis codelens source annotates the `module` directive in a go.mod file\\nwith a command to run Govulncheck asynchronously.\\n\\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\\ncomputes the set of functions reachable within your application, including\\ndependencies; queries a database of known security vulnerabilities; and\\nreports any potential problems it finds.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"test\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"test\\\"`: Run tests and benchmarks\\n\\nThis codelens source annotates each `Test` and `Benchmark`\\nfunction in a `*_test.go` file with a command to run it.\\n\\nThis source is off by default because VS Code has\\na client-side custom UI for testing, and because progress\\nnotifications are not a great UX for streamed test output.\\nSee:\\n- golang/go#67400 for a discussion of this feature.\\n- https://github.com/joaotavora/eglot/discussions/1402\\n  for an alternative approach.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"tidy\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"tidy\\\"`: Tidy go.mod file\\n\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with a command to run [`go mod\\ntidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures\\nthat the go.mod file matches the source code in the module.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"upgrade_dependency\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"upgrade_dependency\\\"`: Update dependencies\\n\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with commands to:\\n\\n- check for available upgrades,\\n- upgrade direct dependencies, and\\n- upgrade all dependencies transitively.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"vendor\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"vendor\\\"`: Update vendor directory\\n\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with a command to run [`go mod\\nvendor`](https://go.dev/ref/mod#go-mod-vendor), which\\ncreates or updates the directory named `vendor` in the\\nmodule root so that it contains an up-to-date copy of all\\nnecessary package dependencies.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\t\t\t\"Status\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"Name\": \"\\\"vulncheck\\\"\",\n\t\t\t\t\t\t\t\"Doc\": \"`\\\"vulncheck\\\"`: Run govulncheck\\n\\nThis codelens source annotates the `module` directive in a go.mod file\\nwith a command to run govulncheck synchronously.\\n\\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\\ncomputes the set of functions reachable within your application, including\\ndependencies; queries a database of known security vulnerabilities; and\\nreports any potential problems it finds.\\n\",\n\t\t\t\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\t\t\t\"Status\": \"experimental\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{\\\"generate\\\":true,\\\"regenerate_cgo\\\":true,\\\"run_govulncheck\\\":true,\\\"tidy\\\":true,\\\"upgrade_dependency\\\":true,\\\"vendor\\\":true}\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"semanticTokens\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"semanticTokens determines whether gopls will return a\\nSemanticTokensProvider at initialization, or respond\\nto request for semantic tokens.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"noSemanticString\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"noSemanticString turns off the sending of the semantic token 'string'\\n\\nDeprecated: Use SemanticTokenTypes[\\\"string\\\"] = false instead. See\\ngolang/vscode-go#3632\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"use SemanticTokenTypes[\\\"string\\\"] = false instead. See\\ngolang/vscode-go#3632\\n\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"noSemanticNumber\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"noSemanticNumber turns off the sending of the semantic token 'number'\\n\\nDeprecated: Use SemanticTokenTypes[\\\"number\\\"] = false instead. See\\ngolang/vscode-go#3632.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"use SemanticTokenTypes[\\\"number\\\"] = false instead. See\\ngolang/vscode-go#3632.\\n\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"semanticTokenTypes\",\n\t\t\t\t\"Type\": \"map[string]bool\",\n\t\t\t\t\"Doc\": \"semanticTokenTypes configures the semantic token types. It allows\\ndisabling types by setting each value to false.\\nBy default, all types are enabled.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{}\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"semanticTokenModifiers\",\n\t\t\t\t\"Type\": \"map[string]bool\",\n\t\t\t\t\"Doc\": \"semanticTokenModifiers configures the semantic token modifiers. It allows\\ndisabling modifiers by setting each value to false.\\nBy default, all modifiers are enabled.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"{}\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"newGoFileHeader\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"newGoFileHeader enables automatic insertion of the copyright comment\\nand package declaration in a newly created Go file.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"true\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"renameMovesSubpackages\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"renameMovesSubpackages enables Rename operations on packages to\\nmove subdirectories of the target package.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"ui\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"local\",\n\t\t\t\t\"Type\": \"string\",\n\t\t\t\t\"Doc\": \"local is the equivalent of the `goimports -local` flag, which puts\\nimports beginning with this string after third-party packages. It should\\nbe the prefix of the import path whose imports should be grouped\\nseparately.\\n\\nIt is used when tidying imports (during an LSP Organize\\nImports request) or when inserting new ones (for example,\\nduring completion); an LSP Formatting request merely sorts the\\nexisting imports.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"\\\"\\\"\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"formatting\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"gofumpt\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"gofumpt indicates if we should run gofumpt formatting.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"\",\n\t\t\t\t\"Hierarchy\": \"formatting\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"maxFileCacheBytes\",\n\t\t\t\t\"Type\": \"int64\",\n\t\t\t\t\"Doc\": \"maxFileCacheBytes sets a soft limit on the file cache size in bytes.\\nIf zero, the default budget is used.\\n\\nThe cache may temporarily use more than this amount.\\nAlso, this parameter limits file contents; disk block usage\\nas measured by du(1) may be significantly higher.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"0\",\n\t\t\t\t\"Status\": \"experimental\",\n\t\t\t\t\"Hierarchy\": \"\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Name\": \"verboseOutput\",\n\t\t\t\t\"Type\": \"bool\",\n\t\t\t\t\"Doc\": \"verboseOutput enables additional debug logging.\\n\",\n\t\t\t\t\"EnumKeys\": {\n\t\t\t\t\t\"ValueType\": \"\",\n\t\t\t\t\t\"Keys\": null\n\t\t\t\t},\n\t\t\t\t\"EnumValues\": null,\n\t\t\t\t\"Default\": \"false\",\n\t\t\t\t\"Status\": \"debug\",\n\t\t\t\t\"Hierarchy\": \"\",\n\t\t\t\t\"DeprecationMessage\": \"\"\n\t\t\t}\n\t\t]\n\t},\n\t\"Lenses\": [\n\t\t{\n\t\t\t\"FileType\": \"Go\",\n\t\t\t\"Lens\": \"generate\",\n\t\t\t\"Title\": \"Run `go generate`\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates any `//go:generate` comments\\nwith commands to run `go generate` in this directory, on\\nall directories recursively beneath this one.\\n\\nSee [Generating code](https://go.dev/blog/generate) for\\nmore details.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"Go\",\n\t\t\t\"Lens\": \"regenerate_cgo\",\n\t\t\t\"Title\": \"Re-generate cgo declarations\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates an `import \\\"C\\\"` declaration\\nwith a command to re-run the [cgo\\ncommand](https://pkg.go.dev/cmd/cgo) to regenerate the\\ncorresponding Go declarations.\\n\\nUse this after editing the C code in comments attached to\\nthe import, or in C header files included by it.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"Go\",\n\t\t\t\"Lens\": \"test\",\n\t\t\t\"Title\": \"Run tests and benchmarks\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates each `Test` and `Benchmark`\\nfunction in a `*_test.go` file with a command to run it.\\n\\nThis source is off by default because VS Code has\\na client-side custom UI for testing, and because progress\\nnotifications are not a great UX for streamed test output.\\nSee:\\n- golang/go#67400 for a discussion of this feature.\\n- https://github.com/joaotavora/eglot/discussions/1402\\n  for an alternative approach.\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"go.mod\",\n\t\t\t\"Lens\": \"run_govulncheck\",\n\t\t\t\"Title\": \"Run govulncheck (legacy)\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates the `module` directive in a go.mod file\\nwith a command to run Govulncheck asynchronously.\\n\\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\\ncomputes the set of functions reachable within your application, including\\ndependencies; queries a database of known security vulnerabilities; and\\nreports any potential problems it finds.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"go.mod\",\n\t\t\t\"Lens\": \"tidy\",\n\t\t\t\"Title\": \"Tidy go.mod file\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with a command to run [`go mod\\ntidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures\\nthat the go.mod file matches the source code in the module.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"go.mod\",\n\t\t\t\"Lens\": \"upgrade_dependency\",\n\t\t\t\"Title\": \"Update dependencies\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with commands to:\\n\\n- check for available upgrades,\\n- upgrade direct dependencies, and\\n- upgrade all dependencies transitively.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"go.mod\",\n\t\t\t\"Lens\": \"vendor\",\n\t\t\t\"Title\": \"Update vendor directory\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates the `module` directive in a\\ngo.mod file with a command to run [`go mod\\nvendor`](https://go.dev/ref/mod#go-mod-vendor), which\\ncreates or updates the directory named `vendor` in the\\nmodule root so that it contains an up-to-date copy of all\\nnecessary package dependencies.\\n\",\n\t\t\t\"Default\": true,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"FileType\": \"go.mod\",\n\t\t\t\"Lens\": \"vulncheck\",\n\t\t\t\"Title\": \"Run govulncheck\",\n\t\t\t\"Doc\": \"\\nThis codelens source annotates the `module` directive in a go.mod file\\nwith a command to run govulncheck synchronously.\\n\\n[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\\ncomputes the set of functions reachable within your application, including\\ndependencies; queries a database of known security vulnerabilities; and\\nreports any potential problems it finds.\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"experimental\"\n\t\t}\n\t],\n\t\"Analyzers\": [\n\t\t{\n\t\t\t\"Name\": \"QF1001\",\n\t\t\t\"Doc\": \"Apply De Morgan's law\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1001\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1002\",\n\t\t\t\"Doc\": \"Convert untagged switch to tagged switch\\n\\nAn untagged switch that compares a single variable against a series of\\nvalues can be replaced with a tagged switch.\\n\\nBefore:\\n\\n    switch {\\n    case x == 1 || x == 2, x == 3:\\n        ...\\n    case x == 4:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAfter:\\n\\n    switch x {\\n    case 1, 2, 3:\\n        ...\\n    case 4:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1002\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1003\",\n\t\t\t\"Doc\": \"Convert if/else-if chain to tagged switch\\n\\nA series of if/else-if checks comparing the same variable against\\nvalues can be replaced with a tagged switch.\\n\\nBefore:\\n\\n    if x == 1 || x == 2 {\\n        ...\\n    } else if x == 3 {\\n        ...\\n    } else {\\n        ...\\n    }\\n\\nAfter:\\n\\n    switch x {\\n    case 1, 2:\\n        ...\\n    case 3:\\n        ...\\n    default:\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1003\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1004\",\n\t\t\t\"Doc\": \"Use strings.ReplaceAll instead of strings.Replace with n == -1\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1005\",\n\t\t\t\"Doc\": \"Expand call to math.Pow\\n\\nSome uses of math.Pow can be simplified to basic multiplication.\\n\\nBefore:\\n\\n    math.Pow(x, 2)\\n\\nAfter:\\n\\n    x * x\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1006\",\n\t\t\t\"Doc\": \"Lift if+break into loop condition\\n\\nBefore:\\n\\n    for {\\n        if done {\\n            break\\n        }\\n        ...\\n    }\\n\\nAfter:\\n\\n    for !done {\\n        ...\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1006\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1007\",\n\t\t\t\"Doc\": \"Merge conditional assignment into variable declaration\\n\\nBefore:\\n\\n    x := false\\n    if someCondition {\\n        x = true\\n    }\\n\\nAfter:\\n\\n    x := someCondition\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1007\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1008\",\n\t\t\t\"Doc\": \"Omit embedded fields from selector expression\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1008\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1009\",\n\t\t\t\"Doc\": \"Use time.Time.Equal instead of == operator\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1009\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1010\",\n\t\t\t\"Doc\": \"Convert slice of bytes to string when printing it\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1010\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1011\",\n\t\t\t\"Doc\": \"Omit redundant type from variable declaration\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"QF1012\",\n\t\t\t\"Doc\": \"Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#QF1012\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1000\",\n\t\t\t\"Doc\": \"Use plain channel send or receive instead of single-case select\\n\\nSelect statements with a single case can be replaced with a simple\\nsend or receive.\\n\\nBefore:\\n\\n    select {\\n    case x := \\u003c-ch:\\n        fmt.Println(x)\\n    }\\n\\nAfter:\\n\\n    x := \\u003c-ch\\n    fmt.Println(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1000\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1001\",\n\t\t\t\"Doc\": \"Replace for loop with call to copy\\n\\nUse copy() for copying elements from one slice to another. For\\narrays of identical size, you can use simple assignment.\\n\\nBefore:\\n\\n    for i, x := range src {\\n        dst[i] = x\\n    }\\n\\nAfter:\\n\\n    copy(dst, src)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1002\",\n\t\t\t\"Doc\": \"Omit comparison with boolean constant\\n\\nBefore:\\n\\n    if x == true {}\\n\\nAfter:\\n\\n    if x {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1002\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1003\",\n\t\t\t\"Doc\": \"Replace call to strings.Index with strings.Contains\\n\\nBefore:\\n\\n    if strings.Index(x, y) != -1 {}\\n\\nAfter:\\n\\n    if strings.Contains(x, y) {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1003\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1004\",\n\t\t\t\"Doc\": \"Replace call to bytes.Compare with bytes.Equal\\n\\nBefore:\\n\\n    if bytes.Compare(x, y) == 0 {}\\n\\nAfter:\\n\\n    if bytes.Equal(x, y) {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1005\",\n\t\t\t\"Doc\": \"Drop unnecessary use of the blank identifier\\n\\nIn many cases, assigning to the blank identifier is unnecessary.\\n\\nBefore:\\n\\n    for _ = range s {}\\n    x, _ = someMap[key]\\n    _ = \\u003c-ch\\n\\nAfter:\\n\\n    for range s{}\\n    x = someMap[key]\\n    \\u003c-ch\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1006\",\n\t\t\t\"Doc\": \"Use 'for { ... }' for infinite loops\\n\\nFor infinite loops, using for { ... } is the most idiomatic choice.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1006\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1007\",\n\t\t\t\"Doc\": \"Simplify regular expression by using raw string literal\\n\\nRaw string literals use backticks instead of quotation marks and do not support\\nany escape sequences. This means that the backslash can be used\\nfreely, without the need of escaping.\\n\\nSince regular expressions have their own escape sequences, raw strings\\ncan improve their readability.\\n\\nBefore:\\n\\n    regexp.Compile(\\\"\\\\\\\\A(\\\\\\\\w+) profile: total \\\\\\\\d+\\\\\\\\n\\\\\\\\z\\\")\\n\\nAfter:\\n\\n    regexp.Compile(`\\\\A(\\\\w+) profile: total \\\\d+\\\\n\\\\z`)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1007\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1008\",\n\t\t\t\"Doc\": \"Simplify returning boolean expression\\n\\nBefore:\\n\\n    if \\u003cexpr\\u003e {\\n        return true\\n    }\\n    return false\\n\\nAfter:\\n\\n    return \\u003cexpr\\u003e\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1008\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1009\",\n\t\t\t\"Doc\": \"Omit redundant nil check on slices, maps, and channels\\n\\nThe len function is defined for all slices, maps, and\\nchannels, even nil ones, which have a length of zero. It is not necessary to\\ncheck for nil before checking that their length is not zero.\\n\\nBefore:\\n\\n    if x != nil \\u0026\\u0026 len(x) != 0 {}\\n\\nAfter:\\n\\n    if len(x) != 0 {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1009\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1010\",\n\t\t\t\"Doc\": \"Omit default slice index\\n\\nWhen slicing, the second index defaults to the length of the value,\\nmaking s[n:len(s)] and s[n:] equivalent.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1010\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1011\",\n\t\t\t\"Doc\": \"Use a single append to concatenate two slices\\n\\nBefore:\\n\\n    for _, e := range y {\\n        x = append(x, e)\\n    }\\n    \\n    for i := range y {\\n        x = append(x, y[i])\\n    }\\n    \\n    for i := range y {\\n        v := y[i]\\n        x = append(x, v)\\n    }\\n\\nAfter:\\n\\n    x = append(x, y...)\\n    x = append(x, y...)\\n    x = append(x, y...)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1011\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1012\",\n\t\t\t\"Doc\": \"Replace time.Now().Sub(x) with time.Since(x)\\n\\nThe time.Since helper has the same effect as using time.Now().Sub(x)\\nbut is easier to read.\\n\\nBefore:\\n\\n    time.Now().Sub(x)\\n\\nAfter:\\n\\n    time.Since(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1012\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1016\",\n\t\t\t\"Doc\": \"Use a type conversion instead of manually copying struct fields\\n\\nTwo struct types with identical fields can be converted between each\\nother. In older versions of Go, the fields had to have identical\\nstruct tags. Since Go 1.8, however, struct tags are ignored during\\nconversions. It is thus not necessary to manually copy every field\\nindividually.\\n\\nBefore:\\n\\n    var x T1\\n    y := T2{\\n        Field1: x.Field1,\\n        Field2: x.Field2,\\n    }\\n\\nAfter:\\n\\n    var x T1\\n    y := T2(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1016\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1017\",\n\t\t\t\"Doc\": \"Replace manual trimming with strings.TrimPrefix\\n\\nInstead of using strings.HasPrefix and manual slicing, use the\\nstrings.TrimPrefix function. If the string doesn't start with the\\nprefix, the original string will be returned. Using strings.TrimPrefix\\nreduces complexity, and avoids common bugs, such as off-by-one\\nmistakes.\\n\\nBefore:\\n\\n    if strings.HasPrefix(str, prefix) {\\n        str = str[len(prefix):]\\n    }\\n\\nAfter:\\n\\n    str = strings.TrimPrefix(str, prefix)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1017\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1018\",\n\t\t\t\"Doc\": \"Use 'copy' for sliding elements\\n\\ncopy() permits using the same source and destination slice, even with\\noverlapping ranges. This makes it ideal for sliding elements in a\\nslice.\\n\\nBefore:\\n\\n    for i := 0; i \\u003c n; i++ {\\n        bs[i] = bs[offset+i]\\n    }\\n\\nAfter:\\n\\n    copy(bs[:n], bs[offset:])\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1018\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1019\",\n\t\t\t\"Doc\": \"Simplify 'make' call by omitting redundant arguments\\n\\nThe 'make' function has default values for the length and capacity\\narguments. For channels, the length defaults to zero, and for slices,\\nthe capacity defaults to the length.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1019\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1020\",\n\t\t\t\"Doc\": \"Omit redundant nil check in type assertion\\n\\nBefore:\\n\\n    if _, ok := i.(T); ok \\u0026\\u0026 i != nil {}\\n\\nAfter:\\n\\n    if _, ok := i.(T); ok {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1020\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1021\",\n\t\t\t\"Doc\": \"Merge variable declaration and assignment\\n\\nBefore:\\n\\n    var x uint\\n    x = 1\\n\\nAfter:\\n\\n    var x uint = 1\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1021\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1023\",\n\t\t\t\"Doc\": \"Omit redundant control flow\\n\\nFunctions that have no return value do not need a return statement as\\nthe final statement of the function.\\n\\nSwitches in Go do not have automatic fallthrough, unlike languages\\nlike C. It is not necessary to have a break statement as the final\\nstatement in a case block.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1023\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1024\",\n\t\t\t\"Doc\": \"Replace x.Sub(time.Now()) with time.Until(x)\\n\\nThe time.Until helper has the same effect as using x.Sub(time.Now())\\nbut is easier to read.\\n\\nBefore:\\n\\n    x.Sub(time.Now())\\n\\nAfter:\\n\\n    time.Until(x)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1024\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1025\",\n\t\t\t\"Doc\": \"Don't use fmt.Sprintf(\\\"%s\\\", x) unnecessarily\\n\\nIn many instances, there are easier and more efficient ways of getting\\na value's string representation. Whenever a value's underlying type is\\na string already, or the type has a String method, they should be used\\ndirectly.\\n\\nGiven the following shared definitions\\n\\n    type T1 string\\n    type T2 int\\n\\n    func (T2) String() string { return \\\"Hello, world\\\" }\\n\\n    var x string\\n    var y T1\\n    var z T2\\n\\nwe can simplify\\n\\n    fmt.Sprintf(\\\"%s\\\", x)\\n    fmt.Sprintf(\\\"%s\\\", y)\\n    fmt.Sprintf(\\\"%s\\\", z)\\n\\nto\\n\\n    x\\n    string(y)\\n    z.String()\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1025\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1028\",\n\t\t\t\"Doc\": \"Simplify error construction with fmt.Errorf\\n\\nBefore:\\n\\n    errors.New(fmt.Sprintf(...))\\n\\nAfter:\\n\\n    fmt.Errorf(...)\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1028\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1029\",\n\t\t\t\"Doc\": \"Range over the string directly\\n\\nRanging over a string will yield byte offsets and runes. If the offset\\nisn't used, this is functionally equivalent to converting the string\\nto a slice of runes and ranging over that. Ranging directly over the\\nstring will be more performant, however, as it avoids allocating a new\\nslice, the size of which depends on the length of the string.\\n\\nBefore:\\n\\n    for _, r := range []rune(s) {}\\n\\nAfter:\\n\\n    for _, r := range s {}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1029\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1030\",\n\t\t\t\"Doc\": \"Use bytes.Buffer.String or bytes.Buffer.Bytes\\n\\nbytes.Buffer has both a String and a Bytes method. It is almost never\\nnecessary to use string(buf.Bytes()) or []byte(buf.String()) – simply\\nuse the other method.\\n\\nThe only exception to this are map lookups. Due to a compiler optimization,\\nm[string(buf.Bytes())] is more efficient than m[buf.String()].\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1030\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1031\",\n\t\t\t\"Doc\": \"Omit redundant nil check around loop\\n\\nYou can use range on nil slices and maps, the loop will simply never\\nexecute. This makes an additional nil check around the loop\\nunnecessary.\\n\\nBefore:\\n\\n    if s != nil {\\n        for _, x := range s {\\n            ...\\n        }\\n    }\\n\\nAfter:\\n\\n    for _, x := range s {\\n        ...\\n    }\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1031\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1032\",\n\t\t\t\"Doc\": \"Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)\\n\\nThe sort.Ints, sort.Float64s and sort.Strings functions are easier to\\nread than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x))\\nand sort.Sort(sort.StringSlice(x)).\\n\\nBefore:\\n\\n    sort.Sort(sort.StringSlice(x))\\n\\nAfter:\\n\\n    sort.Strings(x)\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1032\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1033\",\n\t\t\t\"Doc\": \"Unnecessary guard around call to 'delete'\\n\\nCalling delete on a nil map is a no-op.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1033\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1034\",\n\t\t\t\"Doc\": \"Use result of type assertion to simplify cases\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1034\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1035\",\n\t\t\t\"Doc\": \"Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header\\n\\nThe methods on net/http.Header, namely Add, Del, Get\\nand Set, already canonicalize the given header name.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1035\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1036\",\n\t\t\t\"Doc\": \"Unnecessary guard around map access\\n\\nWhen accessing a map key that doesn't exist yet, one receives a zero\\nvalue. Often, the zero value is a suitable value, for example when\\nusing append or doing integer math.\\n\\nThe following\\n\\n    if _, ok := m[\\\"foo\\\"]; ok {\\n        m[\\\"foo\\\"] = append(m[\\\"foo\\\"], \\\"bar\\\")\\n    } else {\\n        m[\\\"foo\\\"] = []string{\\\"bar\\\"}\\n    }\\n\\ncan be simplified to\\n\\n    m[\\\"foo\\\"] = append(m[\\\"foo\\\"], \\\"bar\\\")\\n\\nand\\n\\n    if _, ok := m2[\\\"k\\\"]; ok {\\n        m2[\\\"k\\\"] += 4\\n    } else {\\n        m2[\\\"k\\\"] = 4\\n    }\\n\\ncan be simplified to\\n\\n    m[\\\"k\\\"] += 4\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1036\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1037\",\n\t\t\t\"Doc\": \"Elaborate way of sleeping\\n\\nUsing a select statement with a single case receiving\\nfrom the result of time.After is a very elaborate way of sleeping that\\ncan much simpler be expressed with a simple call to time.Sleep.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1037\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1038\",\n\t\t\t\"Doc\": \"Unnecessarily complex way of printing formatted string\\n\\nInstead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1038\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1039\",\n\t\t\t\"Doc\": \"Unnecessary use of fmt.Sprint\\n\\nCalling fmt.Sprint with a single string argument is unnecessary\\nand identical to using the string directly.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1039\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"S1040\",\n\t\t\t\"Doc\": \"Type assertion to current type\\n\\nThe type assertion x.(SomeInterface), when x already has type\\nSomeInterface, can only fail if x is nil. Usually, this is\\nleft-over code from when x had a different type and you can safely\\ndelete the type assertion. If you want to check that x is not nil,\\nconsider being explicit and using an actual if x == nil comparison\\ninstead of relying on the type assertion panicking.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#S1040\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1000\",\n\t\t\t\"Doc\": \"Invalid regular expression\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1000\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1001\",\n\t\t\t\"Doc\": \"Invalid template\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1002\",\n\t\t\t\"Doc\": \"Invalid format in time.Parse\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1002\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1003\",\n\t\t\t\"Doc\": \"Unsupported argument to functions in encoding/binary\\n\\nThe encoding/binary package can only serialize types with known sizes.\\nThis precludes the use of the int and uint types, as their sizes\\ndiffer on different architectures. Furthermore, it doesn't support\\nserializing maps, channels, strings, or functions.\\n\\nBefore Go 1.8, bool wasn't supported, either.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1003\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1004\",\n\t\t\t\"Doc\": \"Suspiciously small untyped constant in time.Sleep\\n\\nThe time.Sleep function takes a time.Duration as its only argument.\\nDurations are expressed in nanoseconds. Thus, calling time.Sleep(1)\\nwill sleep for 1 nanosecond. This is a common source of bugs, as sleep\\nfunctions in other languages often accept seconds or milliseconds.\\n\\nThe time package provides constants such as time.Second to express\\nlarge durations. These can be combined with arithmetic to express\\narbitrary durations, for example 5 * time.Second for 5 seconds.\\n\\nIf you truly meant to sleep for a tiny amount of time, use\\nn * time.Nanosecond to signal to Staticcheck that you did mean to sleep\\nfor some amount of nanoseconds.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1005\",\n\t\t\t\"Doc\": \"Invalid first argument to exec.Command\\n\\nos/exec runs programs directly (using variants of the fork and exec\\nsystem calls on Unix systems). This shouldn't be confused with running\\na command in a shell. The shell will allow for features such as input\\nredirection, pipes, and general scripting. The shell is also\\nresponsible for splitting the user's input into a program name and its\\narguments. For example, the equivalent to\\n\\n    ls / /tmp\\n\\nwould be\\n\\n    exec.Command(\\\"ls\\\", \\\"/\\\", \\\"/tmp\\\")\\n\\nIf you want to run a command in a shell, consider using something like\\nthe following – but be aware that not all systems, particularly\\nWindows, will have a /bin/sh program:\\n\\n    exec.Command(\\\"/bin/sh\\\", \\\"-c\\\", \\\"ls | grep Awesome\\\")\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1005\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1007\",\n\t\t\t\"Doc\": \"Invalid URL in net/url.Parse\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1007\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1008\",\n\t\t\t\"Doc\": \"Non-canonical key in http.Header map\\n\\nKeys in http.Header maps are canonical, meaning they follow a specific\\ncombination of uppercase and lowercase letters. Methods such as\\nhttp.Header.Add and http.Header.Del convert inputs into this canonical\\nform before manipulating the map.\\n\\nWhen manipulating http.Header maps directly, as opposed to using the\\nprovided methods, care should be taken to stick to canonical form in\\norder to avoid inconsistencies. The following piece of code\\ndemonstrates one such inconsistency:\\n\\n    h := http.Header{}\\n    h[\\\"etag\\\"] = []string{\\\"1234\\\"}\\n    h.Add(\\\"etag\\\", \\\"5678\\\")\\n    fmt.Println(h)\\n\\n    // Output:\\n    // map[Etag:[5678] etag:[1234]]\\n\\nThe easiest way of obtaining the canonical form of a key is to use\\nhttp.CanonicalHeaderKey.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1008\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1010\",\n\t\t\t\"Doc\": \"(*regexp.Regexp).FindAll called with n == 0, which will always return zero results\\n\\nIf n \\u003e= 0, the function returns at most n matches/submatches. To\\nreturn all results, specify a negative number.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1010\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1011\",\n\t\t\t\"Doc\": \"Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1011\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1012\",\n\t\t\t\"Doc\": \"A nil context.Context is being passed to a function, consider using context.TODO instead\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1012\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1013\",\n\t\t\t\"Doc\": \"io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1013\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1014\",\n\t\t\t\"Doc\": \"Non-pointer value passed to Unmarshal or Decode\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1014\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1015\",\n\t\t\t\"Doc\": \"Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions\\n\\nBefore Go 1.23, time.Tickers had to be closed to be able to be garbage\\ncollected. Since time.Tick doesn't make it possible to close the underlying\\nticker, using it repeatedly would leak memory.\\n\\nGo 1.23 fixes this by allowing tickers to be collected even if they weren't closed.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1015\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1016\",\n\t\t\t\"Doc\": \"Trapping a signal that cannot be trapped\\n\\nNot all signals can be intercepted by a process. Specifically, on\\nUNIX-like systems, the syscall.SIGKILL and syscall.SIGSTOP signals are\\nnever passed to the process, but instead handled directly by the\\nkernel. It is therefore pointless to try and handle these signals.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1016\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1017\",\n\t\t\t\"Doc\": \"Channels used with os/signal.Notify should be buffered\\n\\nThe os/signal package uses non-blocking channel sends when delivering\\nsignals. If the receiving end of the channel isn't ready and the\\nchannel is either unbuffered or full, the signal will be dropped. To\\navoid missing signals, the channel should be buffered and of the\\nappropriate size. For a channel used for notification of just one\\nsignal value, a buffer of size 1 is sufficient.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1017\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1018\",\n\t\t\t\"Doc\": \"strings.Replace called with n == 0, which does nothing\\n\\nWith n == 0, zero instances will be replaced. To replace all\\ninstances, use a negative number, or use strings.ReplaceAll.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1018\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1020\",\n\t\t\t\"Doc\": \"Using an invalid host:port pair with a net.Listen-related function\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1020\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1021\",\n\t\t\t\"Doc\": \"Using bytes.Equal to compare two net.IP\\n\\nA net.IP stores an IPv4 or IPv6 address as a slice of bytes. The\\nlength of the slice for an IPv4 address, however, can be either 4 or\\n16 bytes long, using different ways of representing IPv4 addresses. In\\norder to correctly compare two net.IPs, the net.IP.Equal method should\\nbe used, as it takes both representations into account.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1021\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1023\",\n\t\t\t\"Doc\": \"Modifying the buffer in an io.Writer implementation\\n\\nWrite must not modify the slice data, even temporarily.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1023\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1024\",\n\t\t\t\"Doc\": \"A string cutset contains duplicate characters\\n\\nThe strings.TrimLeft and strings.TrimRight functions take cutsets, not\\nprefixes. A cutset is treated as a set of characters to remove from a\\nstring. For example,\\n\\n    strings.TrimLeft(\\\"42133word\\\", \\\"1234\\\")\\n\\nwill result in the string \\\"word\\\" – any characters that are 1, 2, 3 or\\n4 are cut from the left of the string.\\n\\nIn order to remove one string from another, use strings.TrimPrefix instead.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1024\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1025\",\n\t\t\t\"Doc\": \"It is not possible to use (*time.Timer).Reset's return value correctly\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1025\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1026\",\n\t\t\t\"Doc\": \"Cannot marshal channels or functions\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1026\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1027\",\n\t\t\t\"Doc\": \"Atomic access to 64-bit variable must be 64-bit aligned\\n\\nOn ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to\\narrange for 64-bit alignment of 64-bit words accessed atomically. The\\nfirst word in a variable or in an allocated struct, array, or slice\\ncan be relied upon to be 64-bit aligned.\\n\\nYou can use the structlayout tool to inspect the alignment of fields\\nin a struct.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1027\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1028\",\n\t\t\t\"Doc\": \"sort.Slice can only be used on slices\\n\\nThe first argument of sort.Slice must be a slice.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1028\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1029\",\n\t\t\t\"Doc\": \"Inappropriate key in call to context.WithValue\\n\\nThe provided key must be comparable and should not be\\nof type string or any other built-in type to avoid collisions between\\npackages using context. Users of WithValue should define their own\\ntypes for keys.\\n\\nTo avoid allocating when assigning to an interface{},\\ncontext keys often have concrete type struct{}. Alternatively,\\nexported context key variables' static type should be a pointer or\\ninterface.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1029\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1030\",\n\t\t\t\"Doc\": \"Invalid argument in call to a strconv function\\n\\nThis check validates the format, number base and bit size arguments of\\nthe various parsing and formatting functions in strconv.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1030\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1031\",\n\t\t\t\"Doc\": \"Overlapping byte slices passed to an encoder\\n\\nIn an encoding function of the form Encode(dst, src), dst and\\nsrc were found to reference the same memory. This can result in\\nsrc bytes being overwritten before they are read, when the encoder\\nwrites more than one byte per src byte.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1031\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA1032\",\n\t\t\t\"Doc\": \"Wrong order of arguments to errors.Is\\n\\nThe first argument of the function errors.Is is the error\\nthat we have and the second argument is the error we're trying to match against.\\nFor example:\\n\\n\\tif errors.Is(err, io.EOF) { ... }\\n\\nThis check detects some cases where the two arguments have been swapped. It\\nflags any calls where the first argument is referring to a package-level error\\nvariable, such as\\n\\n\\tif errors.Is(io.EOF, err) { /* this is wrong */ }\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA1032\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA2001\",\n\t\t\t\"Doc\": \"Empty critical section, did you mean to defer the unlock?\\n\\nEmpty critical sections of the kind\\n\\n    mu.Lock()\\n    mu.Unlock()\\n\\nare very often a typo, and the following was intended instead:\\n\\n    mu.Lock()\\n    defer mu.Unlock()\\n\\nDo note that sometimes empty critical sections can be useful, as a\\nform of signaling to wait on another goroutine. Many times, there are\\nsimpler ways of achieving the same effect. When that isn't the case,\\nthe code should be amply commented to avoid confusion. Combining such\\ncomments with a //lint:ignore directive can be used to suppress this\\nrare false positive.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA2001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA2002\",\n\t\t\t\"Doc\": \"Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA2002\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA2003\",\n\t\t\t\"Doc\": \"Deferred Lock right after locking, likely meant to defer Unlock instead\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA2003\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA3000\",\n\t\t\t\"Doc\": \"TestMain doesn't call os.Exit, hiding test failures\\n\\nTest executables (and in turn 'go test') exit with a non-zero status\\ncode if any tests failed. When specifying your own TestMain function,\\nit is your responsibility to arrange for this, by calling os.Exit with\\nthe correct code. The correct code is returned by (*testing.M).Run, so\\nthe usual way of implementing TestMain is to end it with\\nos.Exit(m.Run()).\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA3000\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA3001\",\n\t\t\t\"Doc\": \"Assigning to b.N in benchmarks distorts the results\\n\\nThe testing package dynamically sets b.N to improve the reliability of\\nbenchmarks and uses it in computations to determine the duration of a\\nsingle operation. Benchmark code must not alter b.N as this would\\nfalsify results.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA3001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4000\",\n\t\t\t\"Doc\": \"Binary operator has identical expressions on both sides\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4000\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4001\",\n\t\t\t\"Doc\": \"\\u0026*x gets simplified to x, it does not copy x\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4003\",\n\t\t\t\"Doc\": \"Comparing unsigned values against negative values is pointless\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4003\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4004\",\n\t\t\t\"Doc\": \"The loop exits unconditionally after one iteration\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4005\",\n\t\t\t\"Doc\": \"Field assignment that will never be observed. Did you mean to use a pointer receiver?\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4006\",\n\t\t\t\"Doc\": \"A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4006\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4008\",\n\t\t\t\"Doc\": \"The variable in the loop condition never changes, are you incrementing the wrong variable?\\n\\nFor example:\\n\\n\\tfor i := 0; i \\u003c 10; j++ { ... }\\n\\nThis may also occur when a loop can only execute once because of unconditional\\ncontrol flow that terminates the loop. For example, when a loop body contains an\\nunconditional break, return, or panic:\\n\\n\\tfunc f() {\\n\\t\\tpanic(\\\"oops\\\")\\n\\t}\\n\\tfunc g() {\\n\\t\\tfor i := 0; i \\u003c 10; i++ {\\n\\t\\t\\t// f unconditionally calls panic, which means \\\"i\\\" is\\n\\t\\t\\t// never incremented.\\n\\t\\t\\tf()\\n\\t\\t}\\n\\t}\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4008\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4009\",\n\t\t\t\"Doc\": \"A function argument is overwritten before its first use\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4009\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4010\",\n\t\t\t\"Doc\": \"The result of append will never be observed anywhere\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4010\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4011\",\n\t\t\t\"Doc\": \"Break statement with no effect. Did you mean to break out of an outer loop?\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4011\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4012\",\n\t\t\t\"Doc\": \"Comparing a value against NaN even though no value is equal to NaN\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4012\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4013\",\n\t\t\t\"Doc\": \"Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4013\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4014\",\n\t\t\t\"Doc\": \"An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4014\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4015\",\n\t\t\t\"Doc\": \"Calling functions like math.Ceil on floats converted from integers doesn't do anything useful\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4015\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4016\",\n\t\t\t\"Doc\": \"Certain bitwise operations, such as x ^ 0, do not do anything useful\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4016\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4017\",\n\t\t\t\"Doc\": \"Discarding the return values of a function without side effects, making the call pointless\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4017\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4018\",\n\t\t\t\"Doc\": \"Self-assignment of variables\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4018\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4019\",\n\t\t\t\"Doc\": \"Multiple, identical build constraints in the same file\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4019\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4020\",\n\t\t\t\"Doc\": \"Unreachable case clause in a type switch\\n\\nIn a type switch like the following\\n\\n    type T struct{}\\n    func (T) Read(b []byte) (int, error) { return 0, nil }\\n\\n    var v any = T{}\\n\\n    switch v.(type) {\\n    case io.Reader:\\n        // ...\\n    case T:\\n        // unreachable\\n    }\\n\\nthe second case clause can never be reached because T implements\\nio.Reader and case clauses are evaluated in source order.\\n\\nAnother example:\\n\\n    type T struct{}\\n    func (T) Read(b []byte) (int, error) { return 0, nil }\\n    func (T) Close() error { return nil }\\n\\n    var v any = T{}\\n\\n    switch v.(type) {\\n    case io.Reader:\\n        // ...\\n    case io.ReadCloser:\\n        // unreachable\\n    }\\n\\nEven though T has a Close method and thus implements io.ReadCloser,\\nio.Reader will always match first. The method set of io.Reader is a\\nsubset of io.ReadCloser. Thus it is impossible to match the second\\ncase without matching the first case.\\n\\n\\nStructurally equivalent interfaces\\n\\nA special case of the previous example are structurally identical\\ninterfaces. Given these declarations\\n\\n    type T error\\n    type V error\\n\\n    func doSomething() error {\\n        err, ok := doAnotherThing()\\n        if ok {\\n            return T(err)\\n        }\\n\\n        return U(err)\\n    }\\n\\nthe following type switch will have an unreachable case clause:\\n\\n    switch doSomething().(type) {\\n    case T:\\n        // ...\\n    case V:\\n        // unreachable\\n    }\\n\\nT will always match before V because they are structurally equivalent\\nand therefore doSomething()'s return value implements both.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4020\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4022\",\n\t\t\t\"Doc\": \"Comparing the address of a variable against nil\\n\\nCode such as 'if \\u0026x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4022\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4023\",\n\t\t\t\"Doc\": \"Impossible comparison of interface value with untyped nil\\n\\nUnder the covers, interfaces are implemented as two elements, a\\ntype T and a value V. V is a concrete value such as an int,\\nstruct or pointer, never an interface itself, and has type T. For\\ninstance, if we store the int value 3 in an interface, the\\nresulting interface value has, schematically, (T=int, V=3). The\\nvalue V is also known as the interface's dynamic value, since a\\ngiven interface variable might hold different values V (and\\ncorresponding types T) during the execution of the program.\\n\\nAn interface value is nil only if the V and T are both\\nunset, (T=nil, V is not set), In particular, a nil interface will\\nalways hold a nil type. If we store a nil pointer of type *int\\ninside an interface value, the inner type will be *int regardless\\nof the value of the pointer: (T=*int, V=nil). Such an interface\\nvalue will therefore be non-nil even when the pointer value V\\ninside is nil.\\n\\nThis situation can be confusing, and arises when a nil value is\\nstored inside an interface value such as an error return:\\n\\n    func returnsError() error {\\n        var p *MyError = nil\\n        if bad() {\\n            p = ErrBad\\n        }\\n        return p // Will always return a non-nil error.\\n    }\\n\\nIf all goes well, the function returns a nil p, so the return\\nvalue is an error interface value holding (T=*MyError, V=nil).\\nThis means that if the caller compares the returned error to nil,\\nit will always look as if there was an error even if nothing bad\\nhappened. To return a proper nil error to the caller, the\\nfunction must return an explicit nil:\\n\\n    func returnsError() error {\\n        if bad() {\\n            return ErrBad\\n        }\\n        return nil\\n    }\\n\\nIt's a good idea for functions that return errors always to use\\nthe error type in their signature (as we did above) rather than a\\nconcrete type such as *MyError, to help guarantee the error is\\ncreated correctly. As an example, os.Open returns an error even\\nthough, if not nil, it's always of concrete type *os.PathError.\\n\\nSimilar situations to those described here can arise whenever\\ninterfaces are used. Just keep in mind that if any concrete value\\nhas been stored in the interface, the interface will not be nil.\\nFor more information, see The Laws of\\nReflection at https://golang.org/doc/articles/laws_of_reflection.html.\\n\\nThis text has been copied from\\nhttps://golang.org/doc/faq#nil_error, licensed under the Creative\\nCommons Attribution 3.0 License.\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4023\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4024\",\n\t\t\t\"Doc\": \"Checking for impossible return value from a builtin function\\n\\nReturn values of the len and cap builtins cannot be negative.\\n\\nSee https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap.\\n\\nExample:\\n\\n    if len(slice) \\u003c 0 {\\n        fmt.Println(\\\"unreachable code\\\")\\n    }\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4024\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4025\",\n\t\t\t\"Doc\": \"Integer division of literals that results in zero\\n\\nWhen dividing two integer constants, the result will\\nalso be an integer. Thus, a division such as 2 / 3 results in 0.\\nThis is true for all of the following examples:\\n\\n\\t_ = 2 / 3\\n\\tconst _ = 2 / 3\\n\\tconst _ float64 = 2 / 3\\n\\t_ = float64(2 / 3)\\n\\nStaticcheck will flag such divisions if both sides of the division are\\ninteger literals, as it is highly unlikely that the division was\\nintended to truncate to zero. Staticcheck will not flag integer\\ndivision involving named constants, to avoid noisy positives.\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4025\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4026\",\n\t\t\t\"Doc\": \"Go constants cannot express negative zero\\n\\nIn IEEE 754 floating point math, zero has a sign and can be positive\\nor negative. This can be useful in certain numerical code.\\n\\nGo constants, however, cannot express negative zero. This means that\\nthe literals -0.0 and 0.0 have the same ideal value (zero) and\\nwill both represent positive zero at runtime.\\n\\nTo explicitly and reliably create a negative zero, you can use the\\nmath.Copysign function: math.Copysign(0, -1).\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4026\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4027\",\n\t\t\t\"Doc\": \"(*net/url.URL).Query returns a copy, modifying it doesn't change the URL\\n\\n(*net/url.URL).Query parses the current value of net/url.URL.RawQuery\\nand returns it as a map of type net/url.Values. Subsequent changes to\\nthis map will not affect the URL unless the map gets encoded and\\nassigned to the URL's RawQuery.\\n\\nAs a consequence, the following code pattern is an expensive no-op:\\nu.Query().Add(key, value).\\n\\nAvailable since\\n    2021.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4027\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4028\",\n\t\t\t\"Doc\": \"x % 1 is always zero\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4028\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4029\",\n\t\t\t\"Doc\": \"Ineffective attempt at sorting slice\\n\\nsort.Float64Slice, sort.IntSlice, and sort.StringSlice are\\ntypes, not functions. Doing x = sort.StringSlice(x) does nothing,\\nespecially not sort any values. The correct usage is\\nsort.Sort(sort.StringSlice(x)) or sort.StringSlice(x).Sort(),\\nbut there are more convenient helpers, namely sort.Float64s,\\nsort.Ints, and sort.Strings.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4029\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4030\",\n\t\t\t\"Doc\": \"Ineffective attempt at generating random number\\n\\nFunctions in the math/rand package that accept upper limits, such\\nas Intn, generate random numbers in the half-open interval [0,n). In\\nother words, the generated numbers will be \\u003e= 0 and \\u003c n – they\\ndon't include n. rand.Intn(1) therefore doesn't generate 0\\nor 1, it always generates 0.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4030\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4031\",\n\t\t\t\"Doc\": \"Checking never-nil value against nil\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4031\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA4032\",\n\t\t\t\"Doc\": \"Comparing runtime.GOOS or runtime.GOARCH against impossible value\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA4032\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5000\",\n\t\t\t\"Doc\": \"Assignment to nil map\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5000\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5001\",\n\t\t\t\"Doc\": \"Deferring Close before checking for a possible error\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5001\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5002\",\n\t\t\t\"Doc\": \"The empty for loop ('for {}') spins and can block the scheduler\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5002\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5003\",\n\t\t\t\"Doc\": \"Defers in infinite loops will never execute\\n\\nDefers are scoped to the surrounding function, not the surrounding\\nblock. In a function that never returns, i.e. one containing an\\ninfinite loop, defers will never execute.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5003\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5004\",\n\t\t\t\"Doc\": \"'for { select { ...' with an empty default branch spins\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5005\",\n\t\t\t\"Doc\": \"The finalizer references the finalized object, preventing garbage collection\\n\\nA finalizer is a function associated with an object that runs when the\\ngarbage collector is ready to collect said object, that is when the\\nobject is no longer referenced by anything.\\n\\nIf the finalizer references the object, however, it will always remain\\nas the final reference to that object, preventing the garbage\\ncollector from collecting the object. The finalizer will never run,\\nand the object will never be collected, leading to a memory leak. That\\nis why the finalizer should instead use its first argument to operate\\non the object. That way, the number of references can temporarily go\\nto zero before the object is being passed to the finalizer.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5007\",\n\t\t\t\"Doc\": \"Infinite recursive call\\n\\nA function that calls itself recursively needs to have an exit\\ncondition. Otherwise it will recurse forever, until the system runs\\nout of memory.\\n\\nThis issue can be caused by simple bugs such as forgetting to add an\\nexit condition. It can also happen \\\"on purpose\\\". Some languages have\\ntail call optimization which makes certain infinite recursive calls\\nsafe to use. Go, however, does not implement TCO, and as such a loop\\nshould be used instead.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5007\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5008\",\n\t\t\t\"Doc\": \"Invalid struct tag\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5008\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5010\",\n\t\t\t\"Doc\": \"Impossible type assertion\\n\\nSome type assertions can be statically proven to be\\nimpossible. This is the case when the method sets of both\\narguments of the type assertion conflict with each other, for\\nexample by containing the same method with different\\nsignatures.\\n\\nThe Go compiler already applies this check when asserting from an\\ninterface value to a concrete type. If the concrete type misses\\nmethods from the interface, or if function signatures don't match,\\nthen the type assertion can never succeed.\\n\\nThis check applies the same logic when asserting from one interface to\\nanother. If both interface types contain the same method but with\\ndifferent signatures, then the type assertion can never succeed,\\neither.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5010\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5011\",\n\t\t\t\"Doc\": \"Possible nil pointer dereference\\n\\nA pointer is being dereferenced unconditionally, while\\nalso being checked against nil in another place. This suggests that\\nthe pointer may be nil and dereferencing it may panic. This is\\ncommonly a result of improperly ordered code or missing return\\nstatements. Consider the following examples:\\n\\n    func fn(x *int) {\\n        fmt.Println(*x)\\n\\n        // This nil check is equally important for the previous dereference\\n        if x != nil {\\n            foo(*x)\\n        }\\n    }\\n\\n    func TestFoo(t *testing.T) {\\n        x := compute()\\n        if x == nil {\\n            t.Errorf(\\\"nil pointer received\\\")\\n        }\\n\\n        // t.Errorf does not abort the test, so if x is nil, the next line will panic.\\n        foo(*x)\\n    }\\n\\nStaticcheck tries to deduce which functions abort control flow.\\nFor example, it is aware that a function will not continue\\nexecution after a call to panic or log.Fatal. However, sometimes\\nthis detection fails, in particular in the presence of\\nconditionals. Consider the following example:\\n\\n    func Log(msg string, level int) {\\n        fmt.Println(msg)\\n        if level == levelFatal {\\n            os.Exit(1)\\n        }\\n    }\\n\\n    func Fatal(msg string) {\\n        Log(msg, levelFatal)\\n    }\\n\\n    func fn(x *int) {\\n        if x == nil {\\n            Fatal(\\\"unexpected nil pointer\\\")\\n        }\\n        fmt.Println(*x)\\n    }\\n\\nStaticcheck will flag the dereference of x, even though it is perfectly\\nsafe. Staticcheck is not able to deduce that a call to\\nFatal will exit the program. For the time being, the easiest\\nworkaround is to modify the definition of Fatal like so:\\n\\n    func Fatal(msg string) {\\n        Log(msg, levelFatal)\\n        panic(\\\"unreachable\\\")\\n    }\\n\\nWe also hard-code functions from common logging packages such as\\nlogrus. Please file an issue if we're missing support for a\\npopular package.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5011\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA5012\",\n\t\t\t\"Doc\": \"Passing odd-sized slice to function expecting even size\\n\\nSome functions that take slices as parameters expect the slices to have an even number of elements. \\nOften, these functions treat elements in a slice as pairs. \\nFor example, strings.NewReplacer takes pairs of old and new strings, \\nand calling it with an odd number of elements would be an error.\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA5012\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6000\",\n\t\t\t\"Doc\": \"Using regexp.Match or related in a loop, should use regexp.Compile\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6000\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6001\",\n\t\t\t\"Doc\": \"Missing an optimization opportunity when indexing maps by byte slices\\n\\nMap keys must be comparable, which precludes the use of byte slices.\\nThis usually leads to using string keys and converting byte slices to\\nstrings.\\n\\nNormally, a conversion of a byte slice to a string needs to copy the data and\\ncauses allocations. The compiler, however, recognizes m[string(b)] and\\nuses the data of b directly, without copying it, because it knows that\\nthe data can't change during the map lookup. This leads to the\\ncounter-intuitive situation that\\n\\n    k := string(b)\\n    println(m[k])\\n    println(m[k])\\n\\nwill be less efficient than\\n\\n    println(m[string(b)])\\n    println(m[string(b)])\\n\\nbecause the first version needs to copy and allocate, while the second\\none does not.\\n\\nFor some history on this optimization, check out commit\\nf5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6001\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6002\",\n\t\t\t\"Doc\": \"Storing non-pointer values in sync.Pool allocates memory\\n\\nA sync.Pool is used to avoid unnecessary allocations and reduce the\\namount of work the garbage collector has to do.\\n\\nWhen passing a value that is not a pointer to a function that accepts\\nan interface, the value needs to be placed on the heap, which means an\\nadditional allocation. Slices are a common thing to put in sync.Pools,\\nand they're structs with 3 fields (length, capacity, and a pointer to\\nan array). In order to avoid the extra allocation, one should store a\\npointer to the slice instead.\\n\\nSee the comments on https://go-review.googlesource.com/c/go/+/24371\\nthat discuss this problem.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6002\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6003\",\n\t\t\t\"Doc\": \"Converting a string to a slice of runes before ranging over it\\n\\nYou may want to loop over the runes in a string. Instead of converting\\nthe string to a slice of runes and looping over that, you can loop\\nover the string itself. That is,\\n\\n    for _, r := range s {}\\n\\nand\\n\\n    for _, r := range []rune(s) {}\\n\\nwill yield the same values. The first version, however, will be faster\\nand avoid unnecessary memory allocations.\\n\\nDo note that if you are interested in the indices, ranging over a\\nstring and over a slice of runes will yield different indices. The\\nfirst one yields byte offsets, while the second one yields indices in\\nthe slice of runes.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6003\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6005\",\n\t\t\t\"Doc\": \"Inefficient string comparison with strings.ToLower or strings.ToUpper\\n\\nConverting two strings to the same case and comparing them like so\\n\\n    if strings.ToLower(s1) == strings.ToLower(s2) {\\n        ...\\n    }\\n\\nis significantly more expensive than comparing them with\\nstrings.EqualFold(s1, s2). This is due to memory usage as well as\\ncomputational complexity.\\n\\nstrings.ToLower will have to allocate memory for the new strings, as\\nwell as convert both strings fully, even if they differ on the very\\nfirst byte. strings.EqualFold, on the other hand, compares the strings\\none character at a time. It doesn't need to create two intermediate\\nstrings and can return as soon as the first non-matching character has\\nbeen found.\\n\\nFor a more in-depth explanation of this issue, see\\nhttps://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6005\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA6006\",\n\t\t\t\"Doc\": \"Using io.WriteString to write []byte\\n\\nUsing io.WriteString to write a slice of bytes, as in\\n\\n    io.WriteString(w, string(b))\\n\\nis both unnecessary and inefficient. Converting from []byte to string\\nhas to allocate and copy the data, and we could simply use w.Write(b)\\ninstead.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA6006\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9001\",\n\t\t\t\"Doc\": \"Defers in range loops may not run when you expect them to\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9001\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9002\",\n\t\t\t\"Doc\": \"Using a non-octal os.FileMode that looks like it was meant to be in octal.\\n\\nAvailable since\\n    2017.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9002\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9003\",\n\t\t\t\"Doc\": \"Empty body in an if or else branch\\n\\nAvailable since\\n    2017.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9003\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9004\",\n\t\t\t\"Doc\": \"Only the first constant has an explicit type\\n\\nIn a constant declaration such as the following:\\n\\n    const (\\n        First byte = 1\\n        Second     = 2\\n    )\\n\\nthe constant Second does not have the same type as the constant First.\\nThis construct shouldn't be confused with\\n\\n    const (\\n        First byte = iota\\n        Second\\n    )\\n\\nwhere First and Second do indeed have the same type. The type is only\\npassed on when no explicit value is assigned to the constant.\\n\\nWhen declaring enumerations with explicit values it is therefore\\nimportant not to write\\n\\n    const (\\n          EnumFirst EnumType = 1\\n          EnumSecond         = 2\\n          EnumThird          = 3\\n    )\\n\\nThis discrepancy in types can cause various confusing behaviors and\\nbugs.\\n\\n\\nWrong type in variable declarations\\n\\nThe most obvious issue with such incorrect enumerations expresses\\nitself as a compile error:\\n\\n    package pkg\\n\\n    const (\\n        EnumFirst  uint8 = 1\\n        EnumSecond       = 2\\n    )\\n\\n    func fn(useFirst bool) {\\n        x := EnumSecond\\n        if useFirst {\\n            x = EnumFirst\\n        }\\n    }\\n\\nfails to compile with\\n\\n    ./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment\\n\\n\\nLosing method sets\\n\\nA more subtle issue occurs with types that have methods and optional\\ninterfaces. Consider the following:\\n\\n    package main\\n\\n    import \\\"fmt\\\"\\n\\n    type Enum int\\n\\n    func (e Enum) String() string {\\n        return \\\"an enum\\\"\\n    }\\n\\n    const (\\n        EnumFirst  Enum = 1\\n        EnumSecond      = 2\\n    )\\n\\n    func main() {\\n        fmt.Println(EnumFirst)\\n        fmt.Println(EnumSecond)\\n    }\\n\\nThis code will output\\n\\n    an enum\\n    2\\n\\nas EnumSecond has no explicit type, and thus defaults to int.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9004\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9005\",\n\t\t\t\"Doc\": \"Trying to marshal a struct with no public fields nor custom marshaling\\n\\nThe encoding/json and encoding/xml packages only operate on exported\\nfields in structs, not unexported ones. It is usually an error to try\\nto (un)marshal structs that only consist of unexported fields.\\n\\nThis check will not flag calls involving types that define custom\\nmarshaling behavior, e.g. via MarshalJSON methods. It will also not\\nflag empty structs.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9006\",\n\t\t\t\"Doc\": \"Dubious bit shifting of a fixed size integer value\\n\\nBit shifting a value past its size will always clear the value.\\n\\nFor instance:\\n\\n    v := int8(42)\\n    v \\u003e\\u003e= 8\\n\\nwill always result in 0.\\n\\nThis check flags bit shifting operations on fixed size integer values only.\\nThat is, int, uint and uintptr are never flagged to avoid potential false\\npositives in somewhat exotic but valid bit twiddling tricks:\\n\\n    // Clear any value above 32 bits if integers are more than 32 bits.\\n    func f(i int) int {\\n        v := i \\u003e\\u003e 32\\n        v = v \\u003c\\u003c 32\\n        return i-v\\n    }\\n\\nAvailable since\\n    2020.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9006\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9007\",\n\t\t\t\"Doc\": \"Deleting a directory that shouldn't be deleted\\n\\nIt is virtually never correct to delete system directories such as\\n/tmp or the user's home directory. However, it can be fairly easy to\\ndo by mistake, for example by mistakenly using os.TempDir instead\\nof ioutil.TempDir, or by forgetting to add a suffix to the result\\nof os.UserHomeDir.\\n\\nWriting\\n\\n    d := os.TempDir()\\n    defer os.RemoveAll(d)\\n\\nin your unit tests will have a devastating effect on the stability of your system.\\n\\nThis check flags attempts at deleting the following directories:\\n\\n- os.TempDir\\n- os.UserCacheDir\\n- os.UserConfigDir\\n- os.UserHomeDir\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9007\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9008\",\n\t\t\t\"Doc\": \"else branch of a type assertion is probably not reading the right value\\n\\nWhen declaring variables as part of an if statement (like in 'if\\nfoo := ...; foo {'), the same variables will also be in the scope of\\nthe else branch. This means that in the following example\\n\\n    if x, ok := x.(int); ok {\\n        // ...\\n    } else {\\n        fmt.Printf(\\\"unexpected type %T\\\", x)\\n    }\\n\\nx in the else branch will refer to the x from x, ok\\n:=; it will not refer to the x that is being type-asserted. The\\nresult of a failed type assertion is the zero value of the type that\\nis being asserted to, so x in the else branch will always have the\\nvalue 0 and the type int.\\n\\nAvailable since\\n    2022.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9008\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"SA9009\",\n\t\t\t\"Doc\": \"Ineffectual Go compiler directive\\n\\nA potential Go compiler directive was found, but is ineffectual as it begins\\nwith whitespace.\\n\\nAvailable since\\n    2024.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#SA9009\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1000\",\n\t\t\t\"Doc\": \"Incorrect or missing package comment\\n\\nPackages must have a package comment that is formatted according to\\nthe guidelines laid out in\\nhttps://go.dev/wiki/CodeReviewComments#package-comments.\\n\\nAvailable since\\n    2019.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1000\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1001\",\n\t\t\t\"Doc\": \"Dot imports are discouraged\\n\\nDot imports that aren't in external test packages are discouraged.\\n\\nThe dot_import_whitelist option can be used to whitelist certain\\nimports.\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e The import . form can be useful in tests that, due to circular\\n\\u003e dependencies, cannot be made part of the package being tested:\\n\\u003e \\n\\u003e     package foo_test\\n\\u003e \\n\\u003e     import (\\n\\u003e         \\\"bar/testutil\\\" // also imports \\\"foo\\\"\\n\\u003e         . \\\"foo\\\"\\n\\u003e     )\\n\\u003e \\n\\u003e In this case, the test file cannot be in package foo because it\\n\\u003e uses bar/testutil, which imports foo. So we use the import .\\n\\u003e form to let the file pretend to be part of package foo even though\\n\\u003e it is not. Except for this one case, do not use import . in your\\n\\u003e programs. It makes the programs much harder to read because it is\\n\\u003e unclear whether a name like Quux is a top-level identifier in the\\n\\u003e current package or in an imported package.\\n\\nAvailable since\\n    2019.1\\n\\nOptions\\n    dot_import_whitelist\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1001\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1003\",\n\t\t\t\"Doc\": \"Poorly chosen identifier\\n\\nIdentifiers, such as variable and package names, follow certain rules.\\n\\nSee the following links for details:\\n\\n- https://go.dev/doc/effective_go#package-names\\n- https://go.dev/doc/effective_go#mixed-caps\\n- https://go.dev/wiki/CodeReviewComments#initialisms\\n- https://go.dev/wiki/CodeReviewComments#variable-names\\n\\nAvailable since\\n    2019.1, non-default\\n\\nOptions\\n    initialisms\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1003\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1005\",\n\t\t\t\"Doc\": \"Incorrectly formatted error string\\n\\nError strings follow a set of guidelines to ensure uniformity and good\\ncomposability.\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e Error strings should not be capitalized (unless beginning with\\n\\u003e proper nouns or acronyms) or end with punctuation, since they are\\n\\u003e usually printed following other context. That is, use\\n\\u003e fmt.Errorf(\\\"something bad\\\") not fmt.Errorf(\\\"Something bad\\\"), so\\n\\u003e that log.Printf(\\\"Reading %s: %v\\\", filename, err) formats without a\\n\\u003e spurious capital letter mid-message.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1005\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1006\",\n\t\t\t\"Doc\": \"Poorly chosen receiver name\\n\\nQuoting Go Code Review Comments:\\n\\n\\u003e The name of a method's receiver should be a reflection of its\\n\\u003e identity; often a one or two letter abbreviation of its type\\n\\u003e suffices (such as \\\"c\\\" or \\\"cl\\\" for \\\"Client\\\"). Don't use generic\\n\\u003e names such as \\\"me\\\", \\\"this\\\" or \\\"self\\\", identifiers typical of\\n\\u003e object-oriented languages that place more emphasis on methods as\\n\\u003e opposed to functions. The name need not be as descriptive as that\\n\\u003e of a method argument, as its role is obvious and serves no\\n\\u003e documentary purpose. It can be very short as it will appear on\\n\\u003e almost every line of every method of the type; familiarity admits\\n\\u003e brevity. Be consistent, too: if you call the receiver \\\"c\\\" in one\\n\\u003e method, don't call it \\\"cl\\\" in another.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1006\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1008\",\n\t\t\t\"Doc\": \"A function's error value should be its last return value\\n\\nA function's error value should be its last return value.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1008\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1011\",\n\t\t\t\"Doc\": \"Poorly chosen name for variable of type time.Duration\\n\\ntime.Duration values represent an amount of time, which is represented\\nas a count of nanoseconds. An expression like 5 * time.Microsecond\\nyields the value 5000. It is therefore not appropriate to suffix a\\nvariable of type time.Duration with any time unit, such as Msec or\\nMilli.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1011\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1012\",\n\t\t\t\"Doc\": \"Poorly chosen name for error variable\\n\\nError variables that are part of an API should be called errFoo or\\nErrFoo.\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1012\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1013\",\n\t\t\t\"Doc\": \"Should use constants for HTTP error codes, not magic numbers\\n\\nHTTP has a tremendous number of status codes. While some of those are\\nwell known (200, 400, 404, 500), most of them are not. The net/http\\npackage provides constants for all status codes that are part of the\\nvarious specifications. It is recommended to use these constants\\ninstead of hard-coding magic numbers, to vastly improve the\\nreadability of your code.\\n\\nAvailable since\\n    2019.1\\n\\nOptions\\n    http_status_code_whitelist\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1013\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1015\",\n\t\t\t\"Doc\": \"A switch's default case should be the first or last case\\n\\nAvailable since\\n    2019.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1015\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1016\",\n\t\t\t\"Doc\": \"Use consistent method receiver names\\n\\nAvailable since\\n    2019.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1016\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1017\",\n\t\t\t\"Doc\": \"Don't use Yoda conditions\\n\\nYoda conditions are conditions of the kind 'if 42 == x', where the\\nliteral is on the left side of the comparison. These are a common\\nidiom in languages in which assignment is an expression, to avoid bugs\\nof the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of\\nbug, we prefer the more idiomatic 'if x == 42'.\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1017\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1018\",\n\t\t\t\"Doc\": \"Avoid zero-width and control characters in string literals\\n\\nAvailable since\\n    2019.2\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1018\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1019\",\n\t\t\t\"Doc\": \"Importing the same package multiple times\\n\\nGo allows importing the same package multiple times, as long as\\ndifferent import aliases are being used. That is, the following\\nbit of code is valid:\\n\\n    import (\\n        \\\"fmt\\\"\\n        fumpt \\\"fmt\\\"\\n        format \\\"fmt\\\"\\n    )\\n\\nHowever, this is very rarely done on purpose. Usually, it is a\\nsign of code that got refactored, accidentally adding duplicate\\nimport statements. It is also a rarely known feature, which may\\ncontribute to confusion.\\n\\nDo note that sometimes, this feature may be used\\nintentionally (see for example\\nhttps://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)\\n– if you want to allow this pattern in your code base, you're\\nadvised to disable this check.\\n\\nIt is acceptable to import the same package twice if one of the imports\\nuses the blank identifier. This is allowed in order to increase\\nresilience against erroneous changes when using the same package for its\\nside effects as well as its exported API.\\n\\nAvailable since\\n    2020.1\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1019\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1020\",\n\t\t\t\"Doc\": \"The documentation of an exported function should start with the function's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1020\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1021\",\n\t\t\t\"Doc\": \"The documentation of an exported type should start with type's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1021\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1022\",\n\t\t\t\"Doc\": \"The documentation of an exported variable or constant should start with variable's name\\n\\nDoc comments work best as complete sentences, which\\nallow a wide variety of automated presentations. The first sentence\\nshould be a one-sentence summary that starts with the name being\\ndeclared.\\n\\nIf every doc comment begins with the name of the item it describes,\\nyou can use the doc subcommand of the go tool and run the output\\nthrough grep.\\n\\nSee https://go.dev/doc/effective_go#commentary for more\\ninformation on how to write good documentation.\\n\\nAvailable since\\n    2020.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#ST1022\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ST1023\",\n\t\t\t\"Doc\": \"Redundant type in variable declaration\\n\\nAvailable since\\n    2021.1, non-default\\n\",\n\t\t\t\"URL\": \"https://staticcheck.dev/docs/checks/#\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"any\",\n\t\t\t\"Doc\": \"replace interface{} with any\\n\\nThe any analyzer suggests replacing uses of the empty interface type,\\n`interface{}`, with the `any` alias, which was introduced in Go 1.18.\\nThis is a purely stylistic change that makes code more readable.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"appendclipped\",\n\t\t\t\"Doc\": \"simplify append chains using slices.Concat\\n\\nThe appendclipped analyzer suggests replacing chains of append calls with a\\nsingle call to slices.Concat, which was added in Go 1.21. For example,\\nappend(append(s, s1...), s2...) would be simplified to slices.Concat(s, s1, s2).\\n\\nIn the simple case of appending to a newly allocated slice, such as\\nappend([]T(nil), s...), the analyzer suggests the more concise slices.Clone(s).\\nFor byte slices, it will prefer bytes.Clone if the \\\"bytes\\\" package is\\nalready imported.\\n\\nThis fix is only applied when the base of the append tower is a\\n\\\"clipped\\\" slice, meaning its length and capacity are equal (e.g.\\nx[:0:0] or []T{}). This is to avoid changing program behavior by\\neliminating intended side effects on the base slice's underlying\\narray.\\n\\nThis analyzer is currently disabled by default as the\\ntransformation does not preserve the nilness of the base slice in\\nall cases; see https://go.dev/issue/73557.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"appends\",\n\t\t\t\"Doc\": \"check for missing values after append\\n\\nThis checker reports calls to append that pass\\nno values to be appended to the slice.\\n\\n\\ts := []string{\\\"a\\\", \\\"b\\\", \\\"c\\\"}\\n\\t_ = append(s)\\n\\nSuch calls are always no-ops and often indicate an\\nunderlying mistake.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"asmdecl\",\n\t\t\t\"Doc\": \"report mismatches between assembly files and Go declarations\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/asmdecl\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"assign\",\n\t\t\t\"Doc\": \"check for useless assignments\\n\\nThis checker reports assignments of the form x = x or a[i] = a[i].\\nThese are almost always useless, and even when they aren't they are\\nusually a mistake.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"atomic\",\n\t\t\t\"Doc\": \"check for common mistakes using the sync/atomic package\\n\\nThe atomic checker looks for assignment statements of the form:\\n\\n\\tx = atomic.AddUint64(\\u0026x, 1)\\n\\nwhich are not atomic.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"atomicalign\",\n\t\t\t\"Doc\": \"check for non-64-bits-aligned arguments to sync/atomic functions\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomicalign\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"atomictypes\",\n\t\t\t\"Doc\": \"replace basic types in sync/atomic calls with atomic types\\n\\nThe atomictypes analyzer suggests replacing the primitive sync/atomic functions with\\nthe strongly typed atomic wrapper types introduced in Go1.19 (e.g.\\natomic.Int32). For example,\\n\\n\\tvar x int32\\n\\tatomic.AddInt32(\\u0026x, 1)\\n\\nwould become\\n\\n\\tvar x atomic.Int32\\n\\tx.Add(1)\\n\\nThe atomic types are safer because they don't allow non-atomic access, which is\\na common source of bugs. These types also resolve memory alignment issues that\\nplagued the old atomic functions on 32-bit architectures.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#atomictypes\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"bloop\",\n\t\t\t\"Doc\": \"replace for-range over b.N with b.Loop\\n\\nThe bloop analyzer suggests replacing benchmark loops of the form\\n`for i := 0; i \\u003c b.N; i++` or `for range b.N` with the more modern\\n`for b.Loop()`, which was added in Go 1.24.\\n\\nThis change makes benchmark code more readable and also removes the need for\\nmanual timer control, so any preceding calls to b.StartTimer, b.StopTimer,\\nor b.ResetTimer within the same function will also be removed.\\n\\nCaveats: The b.Loop() method is designed to prevent the compiler from\\noptimizing away the benchmark loop, which can occasionally result in\\nslower execution due to increased allocations in some specific cases.\\nSince its fix may change the performance of nanosecond-scale benchmarks,\\nbloop is disabled by default in the `go fix` analyzer suite; see golang/go#74967.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#bloop\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"bools\",\n\t\t\t\"Doc\": \"check for common mistakes involving boolean operators\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/bools\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"buildtag\",\n\t\t\t\"Doc\": \"check //go:build and // +build directives\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildtag\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"cgocall\",\n\t\t\t\"Doc\": \"detect some violations of the cgo pointer passing rules\\n\\nCheck for invalid cgo pointer passing.\\nThis looks for code that uses cgo to call C code passing values\\nwhose types are almost always invalid according to the cgo pointer\\nsharing rules.\\nSpecifically, it warns about attempts to pass a Go chan, map, func,\\nor slice to C, either directly, or via a pointer, array, or struct.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/cgocall\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"composites\",\n\t\t\t\"Doc\": \"check for unkeyed composite literals\\n\\nThis analyzer reports a diagnostic for composite literals of struct\\ntypes imported from another package that do not use the field-keyed\\nsyntax. Such literals are fragile because the addition of a new field\\n(even if unexported) to the struct will cause compilation to fail.\\n\\nAs an example,\\n\\n\\terr = \\u0026net.DNSConfigError{err}\\n\\nshould be replaced by:\\n\\n\\terr = \\u0026net.DNSConfigError{Err: err}\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/composite\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"copylocks\",\n\t\t\t\"Doc\": \"check for locks erroneously passed by value\\n\\nInadvertently copying a value containing a lock, such as sync.Mutex or\\nsync.WaitGroup, may cause both copies to malfunction. Generally such\\nvalues should be referred to through a pointer.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylock\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"deepequalerrors\",\n\t\t\t\"Doc\": \"check for calls of reflect.DeepEqual on error values\\n\\nThe deepequalerrors checker looks for calls of the form:\\n\\n    reflect.DeepEqual(err1, err2)\\n\\nwhere err1 and err2 are errors. Using reflect.DeepEqual to compare\\nerrors is discouraged.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/deepequalerrors\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"defers\",\n\t\t\t\"Doc\": \"report common mistakes in defer statements\\n\\nThe defers analyzer reports a diagnostic when a defer statement would\\nresult in a non-deferred call to time.Since, as experience has shown\\nthat this is nearly always a mistake.\\n\\nFor example:\\n\\n\\tstart := time.Now()\\n\\t...\\n\\tdefer recordLatency(time.Since(start)) // error: call to time.Since is not deferred\\n\\nThe correct code is:\\n\\n\\tdefer func() { recordLatency(time.Since(start)) }()\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"deprecated\",\n\t\t\t\"Doc\": \"check for use of deprecated identifiers\\n\\nThe deprecated analyzer looks for deprecated symbols and package\\nimports.\\n\\nSee https://go.dev/wiki/Deprecated to learn about Go's convention\\nfor documenting and signaling deprecated identifiers.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/deprecated\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"directive\",\n\t\t\t\"Doc\": \"check Go toolchain directives such as //go:debug\\n\\nThis analyzer checks for problems with known Go toolchain directives\\nin all Go source files in a package directory, even those excluded by\\n//go:build constraints, and all non-Go source files too.\\n\\nFor //go:debug (see https://go.dev/doc/godebug), the analyzer checks\\nthat the directives are placed only in Go source files, only above the\\npackage comment, and only in package main or *_test.go files.\\n\\nSupport for other known directives may be added in the future.\\n\\nThis analyzer does not check //go:build, which is handled by the\\nbuildtag analyzer.\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/directive\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"embed\",\n\t\t\t\"Doc\": \"check //go:embed directive usage\\n\\nThis analyzer checks that the embed package is imported if //go:embed\\ndirectives are present, providing a suggested fix to add the import if\\nit is missing.\\n\\nThis analyzer also checks that //go:embed directives precede the\\ndeclaration of a single variable.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/embeddirective\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"errorsas\",\n\t\t\t\"Doc\": \"report passing non-pointer or non-error values to errors.As\\n\\nThe errorsas analyzer reports calls to errors.As where the type\\nof the second argument is not a pointer to a type implementing error.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"errorsastype\",\n\t\t\t\"Doc\": \"replace errors.As with errors.AsType[T]\\n\\nThis analyzer suggests fixes to simplify uses of [errors.As] of\\nthis form:\\n\\n\\tvar myerr *MyErr\\n\\tif errors.As(err, \\u0026myerr) {\\n\\t\\thandle(myerr)\\n\\t}\\n\\nby using the less error-prone generic [errors.AsType] function,\\nintroduced in Go 1.26:\\n\\n\\tif myerr, ok := errors.AsType[*MyErr](err); ok {\\n\\t\\thandle(myerr)\\n\\t}\\n\\nThe fix is only offered if the var declaration has the form shown and\\nthere are no uses of myerr outside the if statement.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"fieldalignment\",\n\t\t\t\"Doc\": \"find structs that would use less memory if their fields were sorted\\n\\nThis analyzer finds structs that can be rearranged to use less memory, and provides\\na suggested edit with the most compact order.\\n\\nNote that there are two different diagnostics reported. One checks struct size,\\nand the other reports \\\"pointer bytes\\\" used. Pointer bytes is how many bytes of the\\nobject that the garbage collector has to potentially scan for pointers, for example:\\n\\n\\tstruct { uint32; string }\\n\\nhave 16 pointer bytes because the garbage collector has to scan up through the string's\\ninner pointer.\\n\\n\\tstruct { string; *uint32 }\\n\\nhas 24 pointer bytes because it has to scan further through the *uint32.\\n\\n\\tstruct { string; uint32 }\\n\\nhas 8 because it can stop immediately after the string pointer.\\n\\nBe aware that the most compact order is not always the most efficient.\\nIn rare cases it may cause two variables each updated by its own goroutine\\nto occupy the same CPU cache line, inducing a form of memory contention\\nknown as \\\"false sharing\\\" that slows down both goroutines.\\n\\nUnlike most analyzers, which report likely mistakes, the diagnostics\\nproduced by fieldanalyzer very rarely indicate a significant problem,\\nso the analyzer is not included in typical suites such as vet or\\ngopls. Use this standalone command to run it on your code:\\n\\n   $ go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest\\n   $ fieldalignment [packages]\\n\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/fieldalignment\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"fillreturns\",\n\t\t\t\"Doc\": \"suggest fixes for errors due to an incorrect number of return values\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"wrong number of return values (want %d, got %d)\\\". For example:\\n\\n\\tfunc m() (int, string, *bool, error) {\\n\\t\\treturn\\n\\t}\\n\\nwill turn into\\n\\n\\tfunc m() (int, string, *bool, error) {\\n\\t\\treturn 0, \\\"\\\", nil, nil\\n\\t}\\n\\nThis functionality is similar to https://github.com/sqs/goreturns.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"fmtappendf\",\n\t\t\t\"Doc\": \"replace []byte(fmt.Sprintf) with fmt.Appendf\\n\\nThe fmtappendf analyzer suggests replacing `[]byte(fmt.Sprintf(...))` with\\n`fmt.Appendf(nil, ...)`. This avoids the intermediate allocation of a string\\nby Sprintf, making the code more efficient. The suggestion also applies to\\nfmt.Sprint and fmt.Sprintln.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#fmtappendf\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"forvar\",\n\t\t\t\"Doc\": \"remove redundant re-declaration of loop variables\\n\\nThe forvar analyzer removes unnecessary shadowing of loop variables.\\nBefore Go 1.22, it was common to write `for _, x := range s { x := x ... }`\\nto create a fresh variable for each iteration. Go 1.22 changed the semantics\\nof `for` loops, making this pattern redundant. This analyzer removes the\\nunnecessary `x := x` statement.\\n\\nThis fix only applies to `range` loops.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"framepointer\",\n\t\t\t\"Doc\": \"report assembly that clobbers the frame pointer before saving it\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"hostport\",\n\t\t\t\"Doc\": \"check format of addresses passed to net.Dial\\n\\nThis analyzer flags code that produce network address strings using\\nfmt.Sprintf, as in this example:\\n\\n    addr := fmt.Sprintf(\\\"%s:%d\\\", host, 12345) // \\\"will not work with IPv6\\\"\\n    ...\\n    conn, err := net.Dial(\\\"tcp\\\", addr)       // \\\"when passed to dial here\\\"\\n\\nThe analyzer suggests a fix to use the correct approach, a call to\\nnet.JoinHostPort:\\n\\n    addr := net.JoinHostPort(host, \\\"12345\\\")\\n    ...\\n    conn, err := net.Dial(\\\"tcp\\\", addr)\\n\\nA similar diagnostic and fix are produced for a format string of \\\"%s:%s\\\".\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/hostport\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"httpresponse\",\n\t\t\t\"Doc\": \"check for mistakes using HTTP responses\\n\\nA common mistake when using the net/http package is to defer a function\\ncall to close the http.Response Body before checking the error that\\ndetermines whether the response is valid:\\n\\n\\tresp, err := http.Head(url)\\n\\tdefer resp.Body.Close()\\n\\tif err != nil {\\n\\t\\tlog.Fatal(err)\\n\\t}\\n\\t// (defer statement belongs here)\\n\\nThis checker helps uncover latent nil dereference bugs by reporting a\\ndiagnostic for such mistakes.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpresponse\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ifaceassert\",\n\t\t\t\"Doc\": \"detect impossible interface-to-interface type assertions\\n\\nThis checker flags type assertions v.(T) and corresponding type-switch cases\\nin which the static type V of v is an interface that cannot possibly implement\\nthe target interface T. This occurs when V and T contain methods with the same\\nname but different signatures. Example:\\n\\n\\tvar v interface {\\n\\t\\tRead()\\n\\t}\\n\\t_ = v.(io.Reader)\\n\\nThe Read method in v has a different signature than the Read method in\\nio.Reader, so this assertion cannot succeed.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"infertypeargs\",\n\t\t\t\"Doc\": \"check for unnecessary type arguments in call expressions\\n\\nExplicit type arguments may be omitted from call expressions if they can be\\ninferred from function arguments, or from other type arguments:\\n\\n\\tfunc f[T any](T) {}\\n\\t\\n\\tfunc _() {\\n\\t\\tf[string](\\\"foo\\\") // string could be inferred\\n\\t}\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"inline\",\n\t\t\t\"Doc\": \"apply fixes based on 'go:fix inline' comment directives\\n\\nThe inline analyzer inlines functions and constants that are marked for inlining.\\n\\n## Functions\\n\\nGiven a function that is marked for inlining, like this one:\\n\\n\\t//go:fix inline\\n\\tfunc Square(x int) int { return Pow(x, 2) }\\n\\nthis analyzer will recommend that calls to the function elsewhere, in the same\\nor other packages, should be inlined.\\n\\nInlining can be used to move off of a deprecated function:\\n\\n\\t// Deprecated: prefer Pow(x, 2).\\n\\t//go:fix inline\\n\\tfunc Square(x int) int { return Pow(x, 2) }\\n\\nIt can also be used to move off of an obsolete package,\\nas when the import path has changed or a higher major version is available:\\n\\n\\tpackage pkg\\n\\n\\timport pkg2 \\\"pkg/v2\\\"\\n\\n\\t//go:fix inline\\n\\tfunc F() { pkg2.F(nil) }\\n\\nReplacing a call pkg.F() by pkg2.F(nil) can have no effect on the program,\\nso this mechanism provides a low-risk way to update large numbers of calls.\\nWe recommend, where possible, expressing the old API in terms of the new one\\nto enable automatic migration.\\n\\nThe inliner takes care to avoid behavior changes, even subtle ones,\\nsuch as changes to the order in which argument expressions are\\nevaluated. When it cannot safely eliminate all parameter variables,\\nit may introduce a \\\"binding declaration\\\" of the form\\n\\n\\tvar params = args\\n\\nto evaluate argument expressions in the correct order and bind them to\\nparameter variables. Since the resulting code transformation may be\\nstylistically suboptimal, such inlinings may be disabled by specifying\\nthe -inline.allow_binding_decl=false flag to the analyzer driver.\\n\\n(In cases where it is not safe to \\\"reduce\\\" a call—that is, to replace\\na call f(x) by the body of function f, suitably substituted—the\\ninliner machinery is capable of replacing f by a function literal,\\nfunc(){...}(). However, the inline analyzer discards all such\\n\\\"literalizations\\\" unconditionally, again on grounds of style.)\\n\\n## Constants\\n\\nGiven a constant that is marked for inlining, like this one:\\n\\n\\t//go:fix inline\\n\\tconst Ptr = Pointer\\n\\nthis analyzer will recommend that uses of Ptr should be replaced with Pointer.\\n\\nAs with functions, inlining can be used to replace deprecated constants and\\nconstants in obsolete packages.\\n\\nA constant definition can be marked for inlining only if it refers to another\\nnamed constant.\\n\\nThe \\\"//go:fix inline\\\" comment must appear before a single const declaration on its own,\\nas above; before a const declaration that is part of a group, as in this case:\\n\\n\\tconst (\\n\\t   C = 1\\n\\t   //go:fix inline\\n\\t   Ptr = Pointer\\n\\t)\\n\\nor before a group, applying to every constant in the group:\\n\\n\\t//go:fix inline\\n\\tconst (\\n\\t\\tPtr = Pointer\\n\\t    Val = Value\\n\\t)\\n\\nThe proposal https://go.dev/issue/32816 introduces the \\\"//go:fix inline\\\" directives.\\n\\nYou can use this command to apply inline fixes en masse:\\n\\n\\t$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"loopclosure\",\n\t\t\t\"Doc\": \"check references to loop variables from within nested functions\\n\\nThis analyzer reports places where a function literal references the\\niteration variable of an enclosing loop, and the loop calls the function\\nin such a way (e.g. with go or defer) that it may outlive the loop\\niteration and possibly observe the wrong value of the variable.\\n\\nNote: An iteration variable can only outlive a loop iteration in Go versions \\u003c=1.21.\\nIn Go 1.22 and later, the loop variable lifetimes changed to create a new\\niteration variable per loop iteration. (See go.dev/issue/60078.)\\n\\nIn this example, all the deferred functions run after the loop has\\ncompleted, so all observe the final value of v [\\u003cgo1.22].\\n\\n\\tfor _, v := range list {\\n\\t    defer func() {\\n\\t        use(v) // incorrect\\n\\t    }()\\n\\t}\\n\\nOne fix is to create a new variable for each iteration of the loop:\\n\\n\\tfor _, v := range list {\\n\\t    v := v // new var per iteration\\n\\t    defer func() {\\n\\t        use(v) // ok\\n\\t    }()\\n\\t}\\n\\nAfter Go version 1.22, the previous two for loops are equivalent\\nand both are correct.\\n\\nThe next example uses a go statement and has a similar problem [\\u003cgo1.22].\\nIn addition, it has a data race because the loop updates v\\nconcurrent with the goroutines accessing it.\\n\\n\\tfor _, v := range elem {\\n\\t    go func() {\\n\\t        use(v)  // incorrect, and a data race\\n\\t    }()\\n\\t}\\n\\nA fix is the same as before. The checker also reports problems\\nin goroutines started by golang.org/x/sync/errgroup.Group.\\nA hard-to-spot variant of this form is common in parallel tests:\\n\\n\\tfunc Test(t *testing.T) {\\n\\t    for _, test := range tests {\\n\\t        t.Run(test.name, func(t *testing.T) {\\n\\t            t.Parallel()\\n\\t            use(test) // incorrect, and a data race\\n\\t        })\\n\\t    }\\n\\t}\\n\\nThe t.Parallel() call causes the rest of the function to execute\\nconcurrent with the loop [\\u003cgo1.22].\\n\\nThe analyzer reports references only in the last statement,\\nas it is not deep enough to understand the effects of subsequent\\nstatements that might render the reference benign.\\n(\\\"Last statement\\\" is defined recursively in compound\\nstatements such as if, switch, and select.)\\n\\nSee: https://golang.org/doc/go_faq.html#closures_and_goroutines\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"lostcancel\",\n\t\t\t\"Doc\": \"check cancel func returned by context.WithCancel is called\\n\\nThe cancellation function returned by context.WithCancel, WithTimeout,\\nWithDeadline and variants such as WithCancelCause must be called,\\nor the new context will remain live until its parent context is cancelled.\\n(The background context is never cancelled.)\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"maprange\",\n\t\t\t\"Doc\": \"checks for unnecessary calls to maps.Keys and maps.Values in range statements\\n\\nConsider a loop written like this:\\n\\n\\tfor val := range maps.Values(m) {\\n\\t\\tfmt.Println(val)\\n\\t}\\n\\nThis should instead be written without the call to maps.Values:\\n\\n\\tfor _, val := range m {\\n\\t\\tfmt.Println(val)\\n\\t}\\n\\ngolang.org/x/exp/maps returns slices for Keys/Values instead of iterators,\\nbut unnecessary calls should similarly be removed:\\n\\n\\tfor _, key := range maps.Keys(m) {\\n\\t\\tfmt.Println(key)\\n\\t}\\n\\nshould be rewritten as:\\n\\n\\tfor key := range m {\\n\\t\\tfmt.Println(key)\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"mapsloop\",\n\t\t\t\"Doc\": \"replace explicit loops over maps with calls to maps package\\n\\nThe mapsloop analyzer replaces loops of the form\\n\\n\\tfor k, v := range x { m[k] = v }\\n\\nwith a single call to a function from the `maps` package, added in Go 1.23.\\nDepending on the context, this could be `maps.Copy`, `maps.Insert`,\\n`maps.Clone`, or `maps.Collect`.\\n\\nThe transformation to `maps.Clone` is applied conservatively, as it\\npreserves the nilness of the source map, which may be a subtle change in\\nbehavior if the original code did not handle a nil map in the same way.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"minmax\",\n\t\t\t\"Doc\": \"replace if/else statements with calls to min or max\\n\\nThe minmax analyzer simplifies conditional assignments by suggesting the use\\nof the built-in `min` and `max` functions, introduced in Go 1.21. For example,\\n\\n\\tif a \\u003c b { x = a } else { x = b }\\n\\nis replaced by\\n\\n\\tx = min(a, b).\\n\\nThis analyzer avoids making suggestions for floating-point types,\\nas the behavior of `min` and `max` with NaN values can differ from\\nthe original if/else statement.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#minmax\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"newexpr\",\n\t\t\t\"Doc\": \"simplify code by using go1.26's new(expr)\\n\\nThis analyzer finds declarations of functions of this form:\\n\\n\\tfunc varOf(x int) *int { return \\u0026x }\\n\\nand suggests a fix to turn them into inlinable wrappers around\\ngo1.26's built-in new(expr) function:\\n\\n\\t//go:fix inline\\n\\tfunc varOf(x int) *int { return new(x) }\\n\\n(The directive comment causes the 'inline' analyzer to suggest\\nthat calls to such functions are inlined.)\\n\\nIn addition, this analyzer suggests a fix for each call\\nto one of the functions before it is transformed, so that\\n\\n\\tuse(varOf(123))\\n\\nis replaced by:\\n\\n\\tuse(new(123))\\n\\nWrapper functions such as varOf are common when working with Go\\nserialization packages such as for JSON or protobuf, where pointers\\nare often used to express optionality.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#newexpr\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"nilfunc\",\n\t\t\t\"Doc\": \"check for useless comparisons between functions and nil\\n\\nA useless comparison is one like f == nil as opposed to f() == nil.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"nilness\",\n\t\t\t\"Doc\": \"check for redundant or impossible nil comparisons\\n\\nThe nilness checker inspects the control-flow graph of each function in\\na package and reports nil pointer dereferences, degenerate nil\\npointers, and panics with nil values. A degenerate comparison is of the form\\nx==nil or x!=nil where x is statically known to be nil or non-nil. These are\\noften a mistake, especially in control flow related to errors. Panics with nil\\nvalues are checked because they are not detectable by\\n\\n\\tif r := recover(); r != nil {\\n\\nThis check reports conditions such as:\\n\\n\\tif f == nil { // impossible condition (f is a function)\\n\\t}\\n\\nand:\\n\\n\\tp := \\u0026v\\n\\t...\\n\\tif p != nil { // tautological condition\\n\\t}\\n\\nand:\\n\\n\\tif p == nil {\\n\\t\\tprint(*p) // nil dereference\\n\\t}\\n\\nand:\\n\\n\\tif p == nil {\\n\\t\\tpanic(p)\\n\\t}\\n\\nSometimes the control flow may be quite complex, making bugs hard\\nto spot. In the example below, the err.Error expression is\\nguaranteed to panic because, after the first return, err must be\\nnil. The intervening loop is just a distraction.\\n\\n\\t...\\n\\terr := g.Wait()\\n\\tif err != nil {\\n\\t\\treturn err\\n\\t}\\n\\tpartialSuccess := false\\n\\tfor _, err := range errs {\\n\\t\\tif err == nil {\\n\\t\\t\\tpartialSuccess = true\\n\\t\\t\\tbreak\\n\\t\\t}\\n\\t}\\n\\tif partialSuccess {\\n\\t\\treportStatus(StatusMessage{\\n\\t\\t\\tCode:   code.ERROR,\\n\\t\\t\\tDetail: err.Error(), // \\\"nil dereference in dynamic method call\\\"\\n\\t\\t})\\n\\t\\treturn nil\\n\\t}\\n\\n...\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilness\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"nonewvars\",\n\t\t\t\"Doc\": \"suggested fixes for \\\"no new vars on left side of :=\\\"\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"no new vars on left side of :=\\\". For example:\\n\\n\\tz := 1\\n\\tz := 2\\n\\nwill turn into\\n\\n\\tz := 1\\n\\tz = 2\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"noresultvalues\",\n\t\t\t\"Doc\": \"suggested fixes for unexpected return values\\n\\nThis checker provides suggested fixes for type errors of the\\ntype \\\"no result values expected\\\" or \\\"too many return values\\\".\\nFor example:\\n\\n\\tfunc z() { return nil }\\n\\nwill turn into\\n\\n\\tfunc z() { return }\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvalues\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"omitzero\",\n\t\t\t\"Doc\": \"suggest replacing omitempty with omitzero for struct fields\\n\\nThe omitzero analyzer identifies uses of the `omitempty` JSON struct\\ntag on fields that are themselves structs. For struct-typed fields,\\nthe `omitempty` tag has no effect on the behavior of json.Marshal and\\njson.Unmarshal. The analyzer offers two suggestions: either remove the\\ntag, or replace it with `omitzero` (added in Go 1.24), which correctly\\nomits the field if the struct value is zero.\\n\\nHowever, some other serialization packages (notably kubebuilder, see\\nhttps://book.kubebuilder.io/reference/markers.html) may have their own\\ninterpretation of the `json:\\\",omitzero\\\"` tag, so removing it may affect\\nprogram behavior. For this reason, the omitzero modernizer will not\\nmake changes in any package that contains +kubebuilder annotations.\\n\\nReplacing `omitempty` with `omitzero` is a change in behavior. The\\noriginal code would always encode the struct field, whereas the\\nmodified code will omit it if it is a zero-value.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"plusbuild\",\n\t\t\t\"Doc\": \"remove obsolete //+build comments\\n\\nThe plusbuild analyzer suggests a fix to remove obsolete build tags\\nof the form:\\n\\n\\t//+build linux,amd64\\n\\nin files that also contain a Go 1.18-style tag such as:\\n\\n\\t//go:build linux \\u0026\\u0026 amd64\\n\\n(It does not check that the old and new tags are consistent;\\nthat is the job of the 'buildtag' analyzer in the vet suite.)\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"printf\",\n\t\t\t\"Doc\": \"check consistency of Printf format strings and arguments\\n\\nThe check applies to calls of the formatting functions such as\\n[fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of\\nthose functions such as [log.Printf]. It reports a variety of\\nmistakes such as syntax errors in the format string and mismatches\\n(of number and type) between the verbs and their arguments.\\n\\nSee the documentation of the fmt package for the complete set of\\nformat operators and their operand types.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"rangeint\",\n\t\t\t\"Doc\": \"replace 3-clause for loops with for-range over integers\\n\\nThe rangeint analyzer suggests replacing traditional for loops such\\nas\\n\\n\\tfor i := 0; i \\u003c n; i++ { ... }\\n\\nwith the more idiomatic Go 1.22 style:\\n\\n\\tfor i := range n { ... }\\n\\nThis transformation is applied only if (a) the loop variable is not\\nmodified within the loop body and (b) the loop's limit expression\\nis not modified within the loop, as `for range` evaluates its\\noperand only once.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#rangeint\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"recursiveiter\",\n\t\t\t\"Doc\": \"check for inefficient recursive iterators\\n\\nThis analyzer reports when a function that returns an iterator\\n(iter.Seq or iter.Seq2) calls itself as the operand of a range\\nstatement, as this is inefficient.\\n\\nWhen implementing an iterator (e.g. iter.Seq[T]) for a recursive\\ndata type such as a tree or linked list, it is tempting to\\nrecursively range over the iterator for each child element.\\n\\nHere's an example of a naive iterator over a binary tree:\\n\\n\\ttype tree struct {\\n\\t\\tvalue       int\\n\\t\\tleft, right *tree\\n\\t}\\n\\n\\tfunc (t *tree) All() iter.Seq[int] {\\n\\t\\treturn func(yield func(int) bool) {\\n\\t\\t\\tif t != nil {\\n\\t\\t\\t\\tfor elem := range t.left.All() { // \\\"inefficient recursive iterator\\\"\\n\\t\\t\\t\\t\\tif !yield(elem) {\\n\\t\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif !yield(t.value) {\\n\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor elem := range t.right.All() { // \\\"inefficient recursive iterator\\\"\\n\\t\\t\\t\\t\\tif !yield(elem) {\\n\\t\\t\\t\\t\\t\\treturn\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\nThough it correctly enumerates the elements of the tree, it hides a\\nsignificant performance problem--two, in fact. Consider a balanced\\ntree of N nodes. Iterating the root node will cause All to be\\ncalled once on every node of the tree. This results in a chain of\\nnested active range-over-func statements when yield(t.value) is\\ncalled on a leaf node.\\n\\nThe first performance problem is that each range-over-func\\nstatement must typically heap-allocate a variable, so iteration of\\nthe tree allocates as many variables as there are elements in the\\ntree, for a total of O(N) allocations, all unnecessary.\\n\\nThe second problem is that each call to yield for a leaf of the\\ntree causes each of the enclosing range loops to receive a value,\\nwhich they then immediately pass on to their respective yield\\nfunction. This results in a chain of log(N) dynamic yield calls per\\nelement, a total of O(N*log N) dynamic calls overall, when only\\nO(N) are necessary.\\n\\nA better implementation strategy for recursive iterators is to\\nfirst define the \\\"every\\\" operator for your recursive data type,\\nwhere every(f) reports whether an arbitrary predicate f(x) is true\\nfor every element x in the data type. For our tree, the every\\nfunction would be:\\n\\n\\tfunc (t *tree) every(f func(int) bool) bool {\\n\\t\\treturn t == nil ||\\n\\t\\t\\tt.left.every(f) \\u0026\\u0026 f(t.value) \\u0026\\u0026 t.right.every(f)\\n\\t}\\n\\nFor example, this use of the every operator prints whether every\\nelement in the tree is an even number:\\n\\n\\teven := func(x int) bool { return x\\u00261 == 0 }\\n\\tprintln(t.every(even))\\n\\nThen the iterator can be simply expressed as a trivial wrapper\\naround the every operator:\\n\\n\\tfunc (t *tree) All() iter.Seq[int] {\\n\\t\\treturn func(yield func(int) bool) {\\n\\t\\t\\t_ = t.every(yield)\\n\\t\\t}\\n\\t}\\n\\nIn effect, tree.All computes whether yield returns true for each\\nelement, short-circuiting if it ever returns false, then discards\\nthe final boolean result.\\n\\nThis has much better performance characteristics: it makes one\\ndynamic call per element of the tree, and it doesn't heap-allocate\\nanything. It is also clearer.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/recursiveiter\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"reflecttypefor\",\n\t\t\t\"Doc\": \"replace reflect.TypeOf(x) with TypeFor[T]()\\n\\nThis analyzer suggests fixes to replace uses of reflect.TypeOf(x) with\\nreflect.TypeFor, introduced in go1.22, when the desired runtime type\\nis known at compile time, for example:\\n\\n\\treflect.TypeOf(uint32(0))        -\\u003e reflect.TypeFor[uint32]()\\n\\treflect.TypeOf((*ast.File)(nil)) -\\u003e reflect.TypeFor[*ast.File]()\\n\\nIt also offers a fix to simplify the constructions below, which use\\nreflect.TypeOf to return the runtime type for an interface type,\\n\\n\\treflect.TypeOf((*io.Reader)(nil)).Elem()\\n\\nor:\\n\\n\\treflect.TypeOf([]io.Reader(nil)).Elem()\\n\\nto:\\n\\n\\treflect.TypeFor[io.Reader]()\\n\\nNo fix is offered in cases when the runtime type is dynamic, such as:\\n\\n\\tvar r io.Reader = ...\\n\\treflect.TypeOf(r)\\n\\nor when the operand has potential side effects.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#reflecttypefor\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"shadow\",\n\t\t\t\"Doc\": \"check for possible unintended shadowing of variables\\n\\nThis analyzer check for shadowed variables.\\nA shadowed variable is a variable declared in an inner scope\\nwith the same name and type as a variable in an outer scope,\\nand where the outer variable is mentioned after the inner one\\nis declared.\\n\\n(This definition can be refined; the module generates too many\\nfalse positives and is not yet enabled by default.)\\n\\nFor example:\\n\\n\\tfunc BadRead(f *os.File, buf []byte) error {\\n\\t\\tvar err error\\n\\t\\tfor {\\n\\t\\t\\tn, err := f.Read(buf) // shadows the function variable 'err'\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tbreak // causes return of wrong value\\n\\t\\t\\t}\\n\\t\\t\\tfoo(buf)\\n\\t\\t}\\n\\t\\treturn err\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shadow\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"shift\",\n\t\t\t\"Doc\": \"check for shifts that equal or exceed the width of the integer\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shift\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"sigchanyzer\",\n\t\t\t\"Doc\": \"check for unbuffered channel of os.Signal\\n\\nThis checker reports call expression of the form\\n\\n\\tsignal.Notify(c \\u003c-chan os.Signal, sig ...os.Signal),\\n\\nwhere c is an unbuffered channel, which can be at risk of missing the signal.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"simplifycompositelit\",\n\t\t\t\"Doc\": \"check for composite literal simplifications\\n\\nAn array, slice, or map composite literal of the form:\\n\\n\\t[]T{T{}, T{}}\\n\\nwill be simplified to:\\n\\n\\t[]T{{}, {}}\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"simplifyrange\",\n\t\t\t\"Doc\": \"check for range statement simplifications\\n\\nA range of the form:\\n\\n\\tfor x, _ = range v {...}\\n\\nwill be simplified to:\\n\\n\\tfor x = range v {...}\\n\\nA range of the form:\\n\\n\\tfor _ = range v {...}\\n\\nwill be simplified to:\\n\\n\\tfor range v {...}\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"simplifyslice\",\n\t\t\t\"Doc\": \"check for slice simplifications\\n\\nA slice expression of the form:\\n\\n\\ts[a:len(s)]\\n\\nwill be simplified to:\\n\\n\\ts[a:]\\n\\nThis is one of the simplifications that \\\"gofmt -s\\\" applies.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"slicescontains\",\n\t\t\t\"Doc\": \"replace loops with slices.Contains or slices.ContainsFunc\\n\\nThe slicescontains analyzer simplifies loops that check for the existence of\\nan element in a slice. It replaces them with calls to `slices.Contains` or\\n`slices.ContainsFunc`, which were added in Go 1.21.\\n\\nIf the expression for the target element has side effects, this\\ntransformation will cause those effects to occur only once, not\\nonce per tested slice element.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"slicesdelete\",\n\t\t\t\"Doc\": \"replace append-based slice deletion with slices.Delete\\n\\nThe slicesdelete analyzer suggests replacing the idiom\\n\\n\\ts = append(s[:i], s[j:]...)\\n\\nwith the more explicit\\n\\n\\ts = slices.Delete(s, i, j)\\n\\nintroduced in Go 1.21.\\n\\nThis analyzer is disabled by default. The `slices.Delete` function\\nzeros the elements between the new length and the old length of the\\nslice to prevent memory leaks, which is a subtle difference in\\nbehavior compared to the append-based idiom; see https://go.dev/issue/73686.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete\",\n\t\t\t\"Default\": false\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"slicessort\",\n\t\t\t\"Doc\": \"replace sort.Slice with slices.Sort for basic types\\n\\nThe slicessort analyzer simplifies sorting slices of basic ordered\\ntypes. It replaces\\n\\n\\tsort.Slice(s, func(i, j int) bool { return s[i] \\u003c s[j] })\\n\\nwith the simpler `slices.Sort(s)`, which was added in Go 1.21.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicessort\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"slog\",\n\t\t\t\"Doc\": \"check for invalid structured logging calls\\n\\nThe slog checker looks for calls to functions from the log/slog\\npackage that take alternating key-value pairs. It reports calls\\nwhere an argument in a key position is neither a string nor a\\nslog.Attr, and where a final key is missing its value.\\nFor example,it would report\\n\\n\\tslog.Warn(\\\"message\\\", 11, \\\"k\\\") // slog.Warn arg \\\"11\\\" should be a string or a slog.Attr\\n\\nand\\n\\n\\tslog.Info(\\\"message\\\", \\\"k1\\\", v1, \\\"k2\\\") // call to slog.Info missing a final value\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"sortslice\",\n\t\t\t\"Doc\": \"check the argument type of sort.Slice\\n\\nsort.Slice requires an argument of a slice type. Check that\\nthe interface{} value passed to sort.Slice is actually a slice.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sortslice\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stditerators\",\n\t\t\t\"Doc\": \"use iterators instead of Len/At-style APIs\\n\\nThis analyzer suggests a fix to replace each loop of the form:\\n\\n\\tfor i := 0; i \\u003c x.Len(); i++ {\\n\\t\\tuse(x.At(i))\\n\\t}\\n\\nor its \\\"for elem := range x.Len()\\\" equivalent by a range loop over an\\niterator offered by the same data type:\\n\\n\\tfor elem := range x.All() {\\n\\t\\tuse(x.At(i)\\n\\t}\\n\\nwhere x is one of various well-known types in the standard library.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stditerators\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stdmethods\",\n\t\t\t\"Doc\": \"check signature of methods of well-known interfaces\\n\\nSometimes a type may be intended to satisfy an interface but may fail to\\ndo so because of a mistake in its method signature.\\nFor example, the result of this WriteTo method should be (int64, error),\\nnot error, to satisfy io.WriterTo:\\n\\n\\ttype myWriterTo struct{...}\\n\\tfunc (myWriterTo) WriteTo(w io.Writer) error { ... }\\n\\nThis check ensures that each method whose name matches one of several\\nwell-known interface methods from the standard library has the correct\\nsignature for that interface.\\n\\nChecked method names include:\\n\\n\\tFormat GobEncode GobDecode MarshalJSON MarshalXML\\n\\tPeek ReadByte ReadFrom ReadRune Scan Seek\\n\\tUnmarshalJSON UnreadByte UnreadRune WriteByte\\n\\tWriteTo\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stdversion\",\n\t\t\t\"Doc\": \"report uses of too-new standard library symbols\\n\\nThe stdversion analyzer reports references to symbols in the standard\\nlibrary that were introduced by a Go release higher than the one in\\nforce in the referring file. (Recall that the file's Go version is\\ndefined by the 'go' directive its module's go.mod file, or by a\\n\\\"//go:build go1.X\\\" build tag at the top of the file.)\\n\\nThe analyzer does not report a diagnostic for a reference to a \\\"too\\nnew\\\" field or method of a type that is itself \\\"too new\\\", as this may\\nhave false positives, for example if fields or methods are accessed\\nthrough a type alias that is guarded by a Go version constraint.\\n\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stringintconv\",\n\t\t\t\"Doc\": \"check for string(int) conversions\\n\\nThis checker flags conversions of the form string(x) where x is an integer\\n(but not byte or rune) type. Such conversions are discouraged because they\\nreturn the UTF-8 representation of the Unicode code point x, and not a decimal\\nstring representation of x as one might expect. Furthermore, if x denotes an\\ninvalid code point, the conversion cannot be statically rejected.\\n\\nFor conversions that intend on using the code point, consider replacing them\\nwith string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the\\nstring representation of the value in the desired base.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stringsbuilder\",\n\t\t\t\"Doc\": \"replace += with strings.Builder\\n\\nThis analyzer replaces repeated string += string concatenation\\noperations with calls to Go 1.10's strings.Builder.\\n\\nFor example:\\n\\n\\tvar s = \\\"[\\\"\\n\\tfor x := range seq {\\n\\t\\ts += x\\n\\t\\ts += \\\".\\\"\\n\\t}\\n\\ts += \\\"]\\\"\\n\\tuse(s)\\n\\nis replaced by:\\n\\n\\tvar s strings.Builder\\n\\ts.WriteString(\\\"[\\\")\\n\\tfor x := range seq {\\n\\t\\ts.WriteString(x)\\n\\t\\ts.WriteString(\\\".\\\")\\n\\t}\\n\\ts.WriteString(\\\"]\\\")\\n\\tuse(s.String())\\n\\nThis avoids quadratic memory allocation and improves performance.\\n\\nThe analyzer requires that all references to s before the final uses\\nare += operations. To avoid warning about trivial cases, at least one\\nmust appear within a loop. The variable s must be a local\\nvariable, not a global or parameter.\\n\\nAll uses of the finished string must come after the last += operation.\\nEach such use will be replaced by a call to strings.Builder's String method.\\n(These may appear within an intervening loop or function literal, since even\\nif s.String() is called repeatedly, it does not allocate memory.)\\n\\nOften the addend is a call to fmt.Sprintf, as in this example:\\n\\n\\tvar s string\\n\\tfor x := range seq {\\n\\t\\ts += fmt.Sprintf(\\\"%v\\\", x)\\n\\t}\\n\\nwhich, once the suggested fix is applied, becomes:\\n\\n\\tvar s strings.Builder\\n\\tfor x := range seq {\\n\\t\\ts.WriteString(fmt.Sprintf(\\\"%v\\\", x))\\n\\t}\\n\\nThe WriteString call can be further simplified to the more efficient\\nfmt.Fprintf(\\u0026s, \\\"%v\\\", x), avoiding the allocation of an intermediary.\\nHowever, stringsbuilder does not perform this simplification;\\nit requires staticcheck analyzer QF1012. (See https://go.dev/issue/76918.)\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringbuilder\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stringscut\",\n\t\t\t\"Doc\": \"replace strings.Index etc. with strings.Cut\\n\\nThis analyzer replaces certain patterns of use of [strings.Index] and string slicing by [strings.Cut], added in go1.18.\\n\\nFor example:\\n\\n\\tidx := strings.Index(s, substr)\\n\\tif idx \\u003e= 0 {\\n\\t    return s[:idx]\\n\\t}\\n\\nis replaced by:\\n\\n\\tbefore, _, ok := strings.Cut(s, substr)\\n\\tif ok {\\n\\t    return before\\n\\t}\\n\\nAnd:\\n\\n\\tidx := strings.Index(s, substr)\\n\\tif idx \\u003e= 0 {\\n\\t    return\\n\\t}\\n\\nis replaced by:\\n\\n\\tfound := strings.Contains(s, substr)\\n\\tif found {\\n\\t    return\\n\\t}\\n\\nIt also handles variants using [strings.IndexByte] instead of Index, or the bytes package instead of strings.\\n\\nFixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscut\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stringscutprefix\",\n\t\t\t\"Doc\": \"replace HasPrefix/TrimPrefix with CutPrefix\\n\\nThe stringscutprefix analyzer simplifies a common pattern where code first\\nchecks for a prefix with `strings.HasPrefix` and then removes it with\\n`strings.TrimPrefix`. It replaces this two-step process with a single call\\nto `strings.CutPrefix`, introduced in Go 1.20. The analyzer also handles\\nthe equivalent functions in the `bytes` package.\\n\\nFor example, this input:\\n\\n\\tif strings.HasPrefix(s, prefix) {\\n\\t    use(strings.TrimPrefix(s, prefix))\\n\\t}\\n\\nis fixed to:\\n\\n\\tif after, ok := strings.CutPrefix(s, prefix); ok {\\n\\t    use(after)\\n\\t}\\n\\nThe analyzer also offers fixes to use CutSuffix in a similar way.\\nThis input:\\n\\n\\tif strings.HasSuffix(s, suffix) {\\n\\t    use(strings.TrimSuffix(s, suffix))\\n\\t}\\n\\nis fixed to:\\n\\n\\tif before, ok := strings.CutSuffix(s, suffix); ok {\\n\\t    use(before)\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscutprefix\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"stringsseq\",\n\t\t\t\"Doc\": \"replace ranging over Split/Fields with SplitSeq/FieldsSeq\\n\\nThe stringsseq analyzer improves the efficiency of iterating over substrings.\\nIt replaces\\n\\n\\tfor range strings.Split(...)\\n\\nwith the more efficient\\n\\n\\tfor range strings.SplitSeq(...)\\n\\nwhich was added in Go 1.24 and avoids allocating a slice for the\\nsubstrings. The analyzer also handles strings.Fields and the\\nequivalent functions in the bytes package.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringsseq\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"structtag\",\n\t\t\t\"Doc\": \"check that struct field tags conform to reflect.StructTag.Get\\n\\nAlso report certain struct tags (json, xml) used with unexported fields.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/structtag\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"testingcontext\",\n\t\t\t\"Doc\": \"replace context.WithCancel with t.Context in tests\\n\\nThe testingcontext analyzer simplifies context management in tests. It\\nreplaces the manual creation of a cancellable context,\\n\\n\\tctx, cancel := context.WithCancel(context.Background())\\n\\tdefer cancel()\\n\\nwith a single call to t.Context(), which was added in Go 1.24.\\n\\nThis change is only suggested if the `cancel` function is not used\\nfor any other purpose.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#testingcontext\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"testinggoroutine\",\n\t\t\t\"Doc\": \"report calls to (*testing.T).Fatal from goroutines started by a test\\n\\nFunctions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and\\nSkip{,f,Now} methods of *testing.T, must be called from the test goroutine itself.\\nThis checker detects calls to these functions that occur within a goroutine\\nstarted by the test. For example:\\n\\n\\tfunc TestFoo(t *testing.T) {\\n\\t    go func() {\\n\\t        t.Fatal(\\\"oops\\\") // error: (*T).Fatal called from non-test goroutine\\n\\t    }()\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"tests\",\n\t\t\t\"Doc\": \"check for common mistaken usages of tests and examples\\n\\nThe tests checker walks Test, Benchmark, Fuzzing and Example functions checking\\nmalformed names, wrong signatures and examples documenting non-existent\\nidentifiers.\\n\\nPlease see the documentation for package testing in golang.org/pkg/testing\\nfor the conventions that are enforced for Tests, Benchmarks, and Examples.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"timeformat\",\n\t\t\t\"Doc\": \"check for calls of (time.Time).Format or time.Parse with 2006-02-01\\n\\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\\nformat. Internationally, \\\"yyyy-dd-mm\\\" does not occur in common calendar date\\nstandards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unmarshal\",\n\t\t\t\"Doc\": \"report passing non-pointer or non-interface values to unmarshal\\n\\nThe unmarshal analysis reports calls to functions such as json.Unmarshal\\nin which the argument type is not a pointer or an interface.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unreachable\",\n\t\t\t\"Doc\": \"check for unreachable code\\n\\nThe unreachable analyzer finds statements that execution can never reach\\nbecause they are preceded by a return statement, a call to panic, an\\ninfinite loop, or similar constructs.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unsafefuncs\",\n\t\t\t\"Doc\": \"replace unsafe pointer arithmetic with function calls\\n\\nThe unsafefuncs analyzer simplifies pointer arithmetic expressions by\\nreplacing them with calls to helper functions such as unsafe.Add,\\nadded in Go 1.17.\\n\\nExample:\\n\\n\\tunsafe.Pointer(uintptr(ptr) + uintptr(n))\\n\\nwhere ptr is an unsafe.Pointer, is replaced by:\\n\\n\\tunsafe.Add(ptr, n)\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unsafeptr\",\n\t\t\t\"Doc\": \"check for invalid conversions of uintptr to unsafe.Pointer\\n\\nThe unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer\\nto convert integers to pointers. A conversion from uintptr to\\nunsafe.Pointer is invalid if it implies that there is a uintptr-typed\\nword in memory that holds a pointer value, because that word will be\\ninvisible to stack copying and to the garbage collector.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unusedfunc\",\n\t\t\t\"Doc\": \"check for unused functions, methods, etc\\n\\nThe unusedfunc analyzer reports functions and methods that are\\nnever referenced outside of their own declaration.\\n\\nA function is considered unused if it is unexported and not\\nreferenced (except within its own declaration).\\n\\nA method is considered unused if it is unexported, not referenced\\n(except within its own declaration), and its name does not match\\nthat of any method of an interface type declared within the same\\npackage.\\n\\nThe tool may report false positives in some situations, for\\nexample:\\n\\n  - for a declaration of an unexported function that is referenced\\n    from another package using the go:linkname mechanism, if the\\n    declaration's doc comment does not also have a go:linkname\\n    comment.\\n\\n    (Such code is in any case strongly discouraged: linkname\\n    annotations, if they must be used at all, should be used on both\\n    the declaration and the alias.)\\n\\n  - for compiler intrinsics in the \\\"runtime\\\" package that, though\\n    never referenced, are known to the compiler and are called\\n    indirectly by compiled object code.\\n\\n  - for functions called only from assembly.\\n\\n  - for functions called only from files whose build tags are not\\n    selected in the current build configuration.\\n\\nSince these situations are relatively common in the low-level parts\\nof the runtime, this analyzer ignores the standard library.\\nSee https://go.dev/issue/71686 and https://go.dev/issue/74130 for\\nfurther discussion of these limitations.\\n\\nThe unusedfunc algorithm is not as precise as the\\ngolang.org/x/tools/cmd/deadcode tool, but it has the advantage that\\nit runs within the modular analysis framework, enabling near\\nreal-time feedback within gopls.\\n\\nThe unusedfunc analyzer also reports unused types, vars, and\\nconstants. Enums--constants defined with iota--are ignored since\\neven the unused values must remain present to preserve the logical\\nordering.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unusedparams\",\n\t\t\t\"Doc\": \"check for unused parameters of functions\\n\\nThe unusedparams analyzer checks functions to see if there are\\nany parameters that are not being used.\\n\\nTo ensure soundness, it ignores:\\n  - \\\"address-taken\\\" functions, that is, functions that are used as\\n    a value rather than being called directly; their signatures may\\n    be required to conform to a func type.\\n  - exported functions or methods, since they may be address-taken\\n    in another package.\\n  - unexported methods whose name matches an interface method\\n    declared in the same package, since the method's signature\\n    may be required to conform to the interface type.\\n  - functions with empty bodies, or containing just a call to panic.\\n  - parameters that are unnamed, or named \\\"_\\\", the blank identifier.\\n\\nThe analyzer suggests a fix of replacing the parameter name by \\\"_\\\",\\nbut in such cases a deeper fix can be obtained by invoking the\\n\\\"Refactor: remove unused parameter\\\" code action, which will\\neliminate the parameter entirely, along with all corresponding\\narguments at call sites, while taking care to preserve any side\\neffects in the argument expressions; see\\nhttps://github.com/golang/tools/releases/tag/gopls%2Fv0.14.\\n\\nThis analyzer ignores generated code.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unusedresult\",\n\t\t\t\"Doc\": \"check for unused results of calls to some functions\\n\\nSome functions like fmt.Errorf return a result and have no side\\neffects, so it is always a mistake to discard the result. Other\\nfunctions may return an error that must not be ignored, or a cleanup\\noperation that must be called. This analyzer reports calls to\\nfunctions like these when the result of the call is ignored.\\n\\nThe set of functions may be controlled using flags.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unusedvariable\",\n\t\t\t\"Doc\": \"check for unused variables and suggest fixes\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"unusedwrite\",\n\t\t\t\"Doc\": \"checks for unused writes\\n\\nThe analyzer reports instances of writes to struct fields and\\narrays that are never read. Specifically, when a struct object\\nor an array is copied, its elements are copied implicitly by\\nthe compiler, and any element write to this copy does nothing\\nwith the original object.\\n\\nFor example:\\n\\n\\ttype T struct { x int }\\n\\n\\tfunc f(input []T) {\\n\\t\\tfor i, v := range input {  // v is a copy\\n\\t\\t\\tv.x = i  // unused write to field x\\n\\t\\t}\\n\\t}\\n\\nAnother example is about non-pointer receiver:\\n\\n\\ttype T struct { x int }\\n\\n\\tfunc (t T) f() {  // t is a copy\\n\\t\\tt.x = i  // unused write to field x\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"waitgroup\",\n\t\t\t\"Doc\": \"check for misuses of sync.WaitGroup\\n\\nThis analyzer detects mistaken calls to the (*sync.WaitGroup).Add\\nmethod from inside a new goroutine, causing Add to race with Wait:\\n\\n\\t// WRONG\\n\\tvar wg sync.WaitGroup\\n\\tgo func() {\\n\\t        wg.Add(1) // \\\"WaitGroup.Add called from inside new goroutine\\\"\\n\\t        defer wg.Done()\\n\\t        ...\\n\\t}()\\n\\twg.Wait() // (may return prematurely before new goroutine starts)\\n\\nThe correct code calls Add before starting the goroutine:\\n\\n\\t// RIGHT\\n\\tvar wg sync.WaitGroup\\n\\twg.Add(1)\\n\\tgo func() {\\n\\t\\tdefer wg.Done()\\n\\t\\t...\\n\\t}()\\n\\twg.Wait()\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"waitgroupgo\",\n\t\t\t\"Doc\": \"replace wg.Add(1)/go/wg.Done() with wg.Go\\n\\nThe waitgroupgo analyzer simplifies goroutine management with `sync.WaitGroup`.\\nIt replaces the common pattern\\n\\n\\twg.Add(1)\\n\\tgo func() {\\n\\t\\tdefer wg.Done()\\n\\t\\t...\\n\\t}()\\n\\nwith a single call to\\n\\n\\twg.Go(func(){ ... })\\n\\nwhich was added in Go 1.25.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#waitgroupgo\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"writestring\",\n\t\t\t\"Doc\": \"detect inefficient string concatenation in uses of WriteString\\n\\nThe writestring analyzer offers to replace a call to WriteString(x + y) by\\ntwo calls WriteString(x); WriteString(y). This is more efficient because it\\navoids the additional memory allocation produced by string concatenation;\\ninstead we just write each string into the buffer directly.\\n\\nIt explicitly looks for calls to certain well-known writers such as\\nbytes.Buffer, strings.Builder and bufio.Writer. The analyzer will not suggest\\na fix for calls to, say, (*os.File).WriteString, because for certain kinds of\\nfile such as a UDP socket, it could split a single message into two.\\nSimilarly it does not offer fixes when the type of the writer is unknown (as\\nin calls to io.WriteString).\\n\\nFor example:\\n\\n\\tfunc f(a string, b string) string {\\n\\t\\t var s strings.Builder\\n\\t\\t s.WriteString(a+b)\\n\\t\\t return s.String()\\n\\t}\\n\\nwould become:\\n\\n\\tfunc f(a string, b string) string {\\n\\t\\tvar s strings.Builder\\n\\t\\ts.WriteString(a)\\n\\t\\ts.WriteString(b)\\n\\t\\treturn s.String()\\n\\t}\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/writestring\",\n\t\t\t\"Default\": true\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"yield\",\n\t\t\t\"Doc\": \"report calls to yield where the result is ignored\\n\\nAfter a yield function returns false, the caller should not call\\nthe yield function again; generally the iterator should return\\npromptly.\\n\\nThis example fails to check the result of the call to yield,\\ncausing this analyzer to report a diagnostic:\\n\\n\\tyield(1) // yield may be called again (on L2) after returning false\\n\\tyield(2)\\n\\nThe corrected code is either this:\\n\\n\\tif yield(1) { yield(2) }\\n\\nor simply:\\n\\n\\t_ = yield(1) \\u0026\\u0026 yield(2)\\n\\nIt is not always a mistake to ignore the result of yield.\\nFor example, this is a valid single-element iterator:\\n\\n\\tyield(1) // ok to ignore result\\n\\treturn\\n\\nIt is only a mistake when the yield call that returned false may be\\nfollowed by another call.\",\n\t\t\t\"URL\": \"https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/yield\",\n\t\t\t\"Default\": true\n\t\t}\n\t],\n\t\"Hints\": [\n\t\t{\n\t\t\t\"Name\": \"assignVariableTypes\",\n\t\t\t\"Doc\": \"`\\\"assignVariableTypes\\\"` controls inlay hints for variable types in assign statements:\\n```go\\n\\ti/* int*/, j/* int*/ := 0, len(r)-1\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"compositeLiteralFields\",\n\t\t\t\"Doc\": \"`\\\"compositeLiteralFields\\\"` inlay hints for composite literal field names:\\n```go\\n\\t{/*in: */\\\"Hello, world\\\", /*want: */\\\"dlrow ,olleH\\\"}\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"compositeLiteralTypes\",\n\t\t\t\"Doc\": \"`\\\"compositeLiteralTypes\\\"` controls inlay hints for composite literal types:\\n```go\\n\\tfor _, c := range []struct {\\n\\t\\tin, want string\\n\\t}{\\n\\t\\t/*struct{ in string; want string }*/{\\\"Hello, world\\\", \\\"dlrow ,olleH\\\"},\\n\\t}\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"constantValues\",\n\t\t\t\"Doc\": \"`\\\"constantValues\\\"` controls inlay hints for constant values:\\n```go\\n\\tconst (\\n\\t\\tKindNone   Kind = iota/* = 0*/\\n\\t\\tKindPrint/*  = 1*/\\n\\t\\tKindPrintf/* = 2*/\\n\\t\\tKindErrorf/* = 3*/\\n\\t)\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"functionTypeParameters\",\n\t\t\t\"Doc\": \"`\\\"functionTypeParameters\\\"` inlay hints for implicit type parameters on generic functions:\\n```go\\n\\tmyFoo/*[int, string]*/(1, \\\"hello\\\")\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"ignoredError\",\n\t\t\t\"Doc\": \"`\\\"ignoredError\\\"` inlay hints for implicitly discarded errors:\\n```go\\n\\tf.Close() // ignore error\\n```\\nThis check inserts an `// ignore error` hint following any\\nstatement that is a function call whose error result is\\nimplicitly ignored.\\n\\nTo suppress the hint, write an actual comment containing\\n\\\"ignore error\\\" following the call statement, or explicitly\\nassign the result to a blank variable. A handful of common\\nfunctions such as `fmt.Println` are excluded from the\\ncheck.\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"parameterNames\",\n\t\t\t\"Doc\": \"`\\\"parameterNames\\\"` controls inlay hints for parameter names:\\n```go\\n\\tparseInt(/* str: */ \\\"123\\\", /* radix: */ 8)\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"rangeVariableTypes\",\n\t\t\t\"Doc\": \"`\\\"rangeVariableTypes\\\"` controls inlay hints for variable types in range statements:\\n```go\\n\\tfor k/* int*/, v/* string*/ := range []string{} {\\n\\t\\tfmt.Println(k, v)\\n\\t}\\n```\\n\",\n\t\t\t\"Default\": false,\n\t\t\t\"Status\": \"\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "gopls/internal/doc/generate/generate.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The generate command updates the following files of documentation:\n//\n//\tgopls/doc/settings.md   -- from linking gopls/internal/settings.DefaultOptions\n//\tgopls/doc/analyzers.md  -- from linking gopls/internal/settings.DefaultAnalyzers\n//\tgopls/doc/inlayHints.md -- from loading gopls/internal/settings.InlayHint\n//\tgopls/internal/doc/api.json -- all of the above in a single value, for 'gopls api-json'\n//\n// Run it with this command:\n//\n//\t$ cd gopls/internal/doc/generate && go generate\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/doc/comment\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/doc\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nfunc main() {\n\tif _, err := doMain(true); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"Generation failed: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\n// doMain regenerates the output files. On success:\n// - if write, it updates them;\n// - if !write, it reports whether they would change.\nfunc doMain(write bool) (bool, error) {\n\tapi, err := loadAPI()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tgoplsDir, err := pkgDir(\"golang.org/x/tools/gopls\")\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// TODO(adonovan): consider using HTML, not Markdown, for the\n\t// generated reference documents. It's not more difficult, the\n\t// layout is easier to read, and we can use go/doc-comment\n\t// rendering logic.\n\n\tfor _, f := range []struct {\n\t\tname    string // relative to gopls\n\t\trewrite rewriter\n\t}{\n\t\t{\"internal/doc/api.json\", rewriteAPI},\n\t\t{\"doc/settings.md\", rewriteSettings},\n\t\t{\"doc/codelenses.md\", rewriteCodeLenses},\n\t\t{\"doc/analyzers.md\", rewriteAnalyzers},\n\t\t{\"doc/inlayHints.md\", rewriteInlayHints},\n\t} {\n\t\tfile := filepath.Join(goplsDir, f.name)\n\t\told, err := os.ReadFile(file)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tnew, err := f.rewrite(old, api)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"rewriting %q: %v\", file, err)\n\t\t}\n\n\t\tif write {\n\t\t\tif err := os.WriteFile(file, new, 0); err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t} else if !bytes.Equal(old, new) {\n\t\t\treturn false, nil // files would change\n\t\t}\n\t}\n\treturn true, nil\n}\n\n// A rewriter is a function that transforms the content of a file.\ntype rewriter = func([]byte, *doc.API) ([]byte, error)\n\n// pkgDir returns the directory corresponding to the import path pkgPath.\nfunc pkgDir(pkgPath string) (string, error) {\n\tcmd := exec.Command(\"go\", \"list\", \"-f\", \"{{.Dir}}\", pkgPath)\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\tif ee, _ := err.(*exec.ExitError); ee != nil && len(ee.Stderr) > 0 {\n\t\t\treturn \"\", fmt.Errorf(\"%v: %w\\n%s\", cmd, err, ee.Stderr)\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"%v: %w\", cmd, err)\n\t}\n\treturn strings.TrimSpace(string(out)), nil\n}\n\n// loadAPI computes the JSON-encodable value that describes gopls'\n// interfaces, by a combination of static and dynamic analysis.\nfunc loadAPI() (*doc.API, error) {\n\tpkgs, err := packages.Load(\n\t\t&packages.Config{\n\t\t\tMode: packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedDeps,\n\t\t},\n\t\t\"golang.org/x/tools/gopls/internal/settings\",\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsettingsPkg := pkgs[0]\n\n\tdefaults := settings.DefaultOptions()\n\tapi := &doc.API{\n\t\tOptions:   map[string][]*doc.Option{},\n\t\tAnalyzers: loadAnalyzers(settings.AllAnalyzers, defaults),\n\t}\n\n\tapi.Lenses, err = loadLenses(settingsPkg, defaults.Codelenses)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tapi.Hints, err = loadHints(settingsPkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, category := range []reflect.Value{\n\t\treflect.ValueOf(defaults.UserOptions),\n\t} {\n\t\t// Find the type information and ast.File corresponding to the category.\n\t\toptsType := settingsPkg.Types.Scope().Lookup(category.Type().Name())\n\t\tif optsType == nil {\n\t\t\treturn nil, fmt.Errorf(\"could not find %v in scope %v\", category.Type().Name(), settingsPkg.Types.Scope())\n\t\t}\n\t\topts, err := loadOptions(category, optsType, settingsPkg, \"\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Edge case for \"analyses\": populate its enum keys from\n\t\t// the analyzer list, since its map keys are strings, not enums.\n\t\t// Also, set its EnumKeys.ValueType for historical reasons.\n\t\tfor _, opt := range opts {\n\t\t\tif opt.Name == \"analyses\" {\n\t\t\t\topt.EnumKeys.ValueType = \"bool\"\n\t\t\t\tfor _, a := range api.Analyzers {\n\t\t\t\t\topt.EnumKeys.Keys = append(opt.EnumKeys.Keys, doc.EnumKey{\n\t\t\t\t\t\tName:    fmt.Sprintf(\"%q\", a.Name),\n\t\t\t\t\t\tDoc:     a.Doc,\n\t\t\t\t\t\tDefault: strconv.FormatBool(a.Default),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tcatName := strings.TrimSuffix(category.Type().Name(), \"Options\")\n\t\tapi.Options[catName] = opts\n\t}\n\treturn api, nil\n}\n\n// loadOptions computes a single category of settings by a combination\n// of static analysis and reflection over gopls internal types.\nfunc loadOptions(category reflect.Value, optsType types.Object, pkg *packages.Package, hierarchy string) ([]*doc.Option, error) {\n\tfile, err := fileForPos(pkg, optsType.Pos())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tenums, err := loadEnums(pkg) // TODO(adonovan): do this only once at toplevel.\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar opts []*doc.Option\n\toptsStruct := optsType.Type().Underlying().(*types.Struct)\n\tfor typesField := range optsStruct.Fields() {\n\t\t// The types field gives us the type.\n\n\t\t// If the field name ends with \"Options\", assume it is a struct with\n\t\t// additional options and process it recursively.\n\t\tif h, ok := strings.CutSuffix(typesField.Name(), \"Options\"); ok {\n\t\t\t// Keep track of the parent structs.\n\t\t\tif hierarchy != \"\" {\n\t\t\t\th = hierarchy + \".\" + h\n\t\t\t}\n\t\t\toptions, err := loadOptions(category, typesField, pkg, strings.ToLower(h))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\topts = append(opts, options...)\n\t\t\tcontinue\n\t\t}\n\t\tpath, _ := goastutil.PathEnclosingInterval(file, typesField.Pos(), typesField.Pos())\n\t\tif len(path) < 2 {\n\t\t\treturn nil, fmt.Errorf(\"could not find AST node for field %v\", typesField)\n\t\t}\n\n\t\t// The AST field gives us the doc.\n\t\tastField, ok := path[1].(*ast.Field)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unexpected AST path %v\", path)\n\t\t}\n\t\tdescription, deprecation := astField.Doc.Text(), astutil.Deprecation(astField.Doc)\n\n\t\t// The reflect field gives us the default value.\n\t\treflectField := category.FieldByName(typesField.Name())\n\t\tif !reflectField.IsValid() {\n\t\t\treturn nil, fmt.Errorf(\"could not find reflect field for %v\", typesField.Name())\n\t\t}\n\n\t\tdef, err := formatDefault(reflectField)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Derive the doc-and-api.json type from the Go field type.\n\t\t//\n\t\t// In principle, we should use JSON nomenclature here\n\t\t// (number, array, object, etc; see #68057), but in\n\t\t// practice we use the Go type string ([]T, map[K]V,\n\t\t// etc) with only one tweak: enumeration types are\n\t\t// replaced by \"enum\", including when they appear as\n\t\t// map keys.\n\t\t//\n\t\t// Notable edge cases:\n\t\t// - any (e.g. in linksInHover) is really a sum of false | true | \"internal\".\n\t\t// - time.Duration is really a string with a particular syntax.\n\t\ttyp := typesField.Type().String()\n\t\tif _, ok := enums[typesField.Type()]; ok {\n\t\t\ttyp = \"enum\"\n\t\t}\n\t\tname := lowerFirst(typesField.Name())\n\n\t\t// enum-keyed maps\n\t\tvar enumKeys doc.EnumKeys\n\t\tif m, ok := typesField.Type().Underlying().(*types.Map); ok {\n\t\t\tif values, ok := enums[m.Key()]; ok {\n\t\t\t\t// Update type name: \"map[CodeLensSource]T\" -> \"map[enum]T\"\n\t\t\t\t// hack: assumes key substring is unique!\n\t\t\t\ttyp = strings.Replace(typ, m.Key().String(), \"enum\", 1)\n\n\t\t\t\tenumKeys.ValueType = m.Elem().String() // e.g. bool\n\n\t\t\t\t// For map[enum]T fields, gather the set of valid\n\t\t\t\t// EnumKeys (from type information). If T=bool, also\n\t\t\t\t// record the default value (from reflection).\n\t\t\t\tkeys, err := collectEnumKeys(m, reflectField, values)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tenumKeys.Keys = keys\n\t\t\t}\n\t\t}\n\n\t\t// Get the status of the field by checking its struct tags.\n\t\treflectStructField, ok := category.Type().FieldByName(typesField.Name())\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"no struct field for %s\", typesField.Name())\n\t\t}\n\t\tstatus := reflectStructField.Tag.Get(\"status\")\n\n\t\topts = append(opts, &doc.Option{\n\t\t\tName:               name,\n\t\t\tType:               typ,\n\t\t\tDoc:                lowerFirst(description),\n\t\t\tDefault:            def,\n\t\t\tEnumKeys:           enumKeys,\n\t\t\tEnumValues:         enums[typesField.Type()],\n\t\t\tStatus:             status,\n\t\t\tHierarchy:          hierarchy,\n\t\t\tDeprecationMessage: lowerFirst(strings.TrimPrefix(deprecation, \"Deprecated: \")),\n\t\t})\n\t}\n\treturn opts, nil\n}\n\n// loadEnums returns a description of gopls' settings enum types based on static analysis.\nfunc loadEnums(pkg *packages.Package) (map[types.Type][]doc.EnumValue, error) {\n\tenums := make(map[types.Type][]doc.EnumValue)\n\tfor _, name := range pkg.Types.Scope().Names() {\n\t\tobj := pkg.Types.Scope().Lookup(name)\n\t\tcnst, ok := obj.(*types.Const)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tf, err := fileForPos(pkg, cnst.Pos())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"finding file for %q: %v\", cnst.Name(), err)\n\t\t}\n\t\tpath, _ := goastutil.PathEnclosingInterval(f, cnst.Pos(), cnst.Pos())\n\t\tspec := path[1].(*ast.ValueSpec)\n\t\tvalue := cnst.Val().ExactString()\n\t\tdocstring := valueDoc(cnst.Name(), value, spec.Doc.Text())\n\t\tvar status string\n\t\tfor _, d := range astutil.Directives(spec.Doc) {\n\t\t\tif d.Tool == \"gopls\" && d.Name == \"status\" {\n\t\t\t\tstatus = d.Args\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tv := doc.EnumValue{\n\t\t\tValue:  value,\n\t\t\tDoc:    docstring,\n\t\t\tStatus: status,\n\t\t}\n\t\tenums[obj.Type()] = append(enums[obj.Type()], v)\n\t}\n\n\t// linksInHover is a one-off edge case (true | false | \"gopls\")\n\t// that doesn't warrant a general solution (e.g. struct tag).\n\tenums[pkg.Types.Scope().Lookup(\"LinksInHoverEnum\").Type()] = []doc.EnumValue{\n\t\t{Value: \"false\", Doc: \"false: do not show links\"},\n\t\t{Value: \"true\", Doc: \"true: show links to the `linkTarget` domain\"},\n\t\t{Value: `\"gopls\"`, Doc: \"`\\\"gopls\\\"`: show links to gopls' internal documentation viewer\"},\n\t}\n\n\treturn enums, nil\n}\n\nfunc collectEnumKeys(m *types.Map, reflectField reflect.Value, enumValues []doc.EnumValue) ([]doc.EnumKey, error) {\n\t// We can get default values for enum -> bool maps.\n\tvar isEnumBoolMap bool\n\tif basic, ok := m.Elem().Underlying().(*types.Basic); ok && basic.Kind() == types.Bool {\n\t\tisEnumBoolMap = true\n\t}\n\tvar keys []doc.EnumKey\n\tfor _, v := range enumValues {\n\t\tvar def string\n\t\tif isEnumBoolMap {\n\t\t\tvar err error\n\t\t\tdef, err = formatDefaultFromEnumBoolMap(reflectField, v.Value)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tkeys = append(keys, doc.EnumKey{\n\t\t\tName:    v.Value,\n\t\t\tDoc:     v.Doc,\n\t\t\tStatus:  v.Status,\n\t\t\tDefault: def,\n\t\t})\n\t}\n\treturn keys, nil\n}\n\nfunc formatDefaultFromEnumBoolMap(reflectMap reflect.Value, enumKey string) (string, error) {\n\tif reflectMap.Kind() != reflect.Map {\n\t\treturn \"\", nil\n\t}\n\tname := enumKey\n\tif unquoted, err := strconv.Unquote(name); err == nil {\n\t\tname = unquoted\n\t}\n\tfor _, e := range reflectMap.MapKeys() {\n\t\tif e.String() == name {\n\t\t\tvalue := reflectMap.MapIndex(e)\n\t\t\tif value.Type().Kind() == reflect.Bool {\n\t\t\t\treturn formatDefault(value)\n\t\t\t}\n\t\t}\n\t}\n\t// Assume that if the value isn't mentioned in the map, it defaults to\n\t// the default value, false.\n\treturn formatDefault(reflect.ValueOf(false))\n}\n\n// formatDefault formats the default value into a JSON-like string.\n// VS Code exposes settings as JSON, so showing them as JSON is reasonable.\n// TODO(rstambler): Reconsider this approach, as the VS Code Go generator now\n// marshals to JSON.\nfunc formatDefault(reflectField reflect.Value) (string, error) {\n\tdef := reflectField.Interface()\n\n\t// Durations marshal as nanoseconds, but we want the stringy versions,\n\t// e.g. \"100ms\".\n\tif t, ok := def.(time.Duration); ok {\n\t\tdef = t.String()\n\t}\n\tdefBytes, err := json.Marshal(def)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Nil values format as \"null\" so print them as hardcoded empty values.\n\tswitch reflectField.Type().Kind() {\n\tcase reflect.Map:\n\t\tif reflectField.IsNil() {\n\t\t\tdefBytes = []byte(\"{}\")\n\t\t}\n\tcase reflect.Slice:\n\t\tif reflectField.IsNil() {\n\t\t\tdefBytes = []byte(\"[]\")\n\t\t}\n\t}\n\treturn string(defBytes), err\n}\n\n// valueDoc transforms a docstring documenting a constant identifier to a\n// docstring documenting its value.\n//\n// If doc is of the form \"Foo is a bar\", it returns '`\"fooValue\"` is a bar'. If\n// doc is non-standard (\"this value is a bar\"), it returns '`\"fooValue\"`: this\n// value is a bar'.\nfunc valueDoc(name, value, doc string) string {\n\tif doc == \"\" {\n\t\treturn \"\"\n\t}\n\tif strings.HasPrefix(doc, name) {\n\t\t// docstring in standard form. Replace the subject with value.\n\t\treturn fmt.Sprintf(\"`%s`%s\", value, doc[len(name):])\n\t}\n\treturn fmt.Sprintf(\"`%s`: %s\", value, doc)\n}\n\n// loadLenses combines the syntactic comments from the settings\n// package with the default values from settings.DefaultOptions(), and\n// returns a list of Code Lens descriptors.\nfunc loadLenses(settingsPkg *packages.Package, defaults map[settings.CodeLensSource]bool) ([]*doc.Lens, error) {\n\t// Find the CodeLensSource enums among the files of the protocol package.\n\t// Map each enum value to its doc comment.\n\tenumDoc := make(map[string]string)\n\tenumStatus := make(map[string]string)\n\tfor _, f := range settingsPkg.Syntax {\n\t\tfor _, decl := range f.Decls {\n\t\t\tif decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.CONST {\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\tposn := safetoken.StartPosition(settingsPkg.Fset, spec.Pos())\n\t\t\t\t\tif id, ok := spec.Type.(*ast.Ident); ok && id.Name == \"CodeLensSource\" {\n\t\t\t\t\t\tif len(spec.Names) != 1 || len(spec.Values) != 1 {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"%s: declare one CodeLensSource per line\", posn)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlit, ok := spec.Values[0].(*ast.BasicLit)\n\t\t\t\t\t\tif !ok || lit.Kind != token.STRING {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"%s: CodeLensSource value is not a string literal\", posn)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalue, _ := strconv.Unquote(lit.Value) // ignore error: AST is well-formed\n\t\t\t\t\t\tif spec.Doc == nil {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"%s: %s lacks doc comment\", posn, spec.Names[0].Name)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenumDoc[value] = spec.Doc.Text()\n\t\t\t\t\t\tfor _, d := range astutil.Directives(spec.Doc) {\n\t\t\t\t\t\t\tif d.Tool == \"gopls\" && d.Name == \"status\" {\n\t\t\t\t\t\t\t\tenumStatus[value] = d.Args\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif len(enumDoc) == 0 {\n\t\treturn nil, fmt.Errorf(\"failed to extract any CodeLensSource declarations\")\n\t}\n\n\t// Build list of Lens descriptors.\n\tvar lenses []*doc.Lens\n\taddAll := func(sources map[settings.CodeLensSource]cache.CodeLensSourceFunc, fileType string) error {\n\t\tfor _, source := range slices.Sorted(maps.Keys(sources)) {\n\t\t\tdocText, ok := enumDoc[string(source)]\n\t\t\tif !ok {\n\t\t\t\treturn fmt.Errorf(\"missing CodeLensSource declaration for %s\", source)\n\t\t\t}\n\t\t\ttitle, docText, _ := strings.Cut(docText, \"\\n\") // first line is title\n\t\t\tlenses = append(lenses, &doc.Lens{\n\t\t\t\tFileType: fileType,\n\t\t\t\tLens:     string(source),\n\t\t\t\tTitle:    title,\n\t\t\t\tDoc:      docText,\n\t\t\t\tDefault:  defaults[source],\n\t\t\t\tStatus:   enumStatus[string(source)],\n\t\t\t})\n\t\t}\n\t\treturn nil\n\t}\n\terr := errors.Join(\n\t\taddAll(golang.CodeLensSources(), \"Go\"),\n\t\taddAll(mod.CodeLensSources(), \"go.mod\"))\n\treturn lenses, err\n}\n\nfunc loadAnalyzers(analyzers []*settings.Analyzer, defaults *settings.Options) []*doc.Analyzer {\n\tslices.SortFunc(analyzers, func(x, y *settings.Analyzer) int {\n\t\treturn strings.Compare(x.Analyzer().Name, y.Analyzer().Name)\n\t})\n\tvar json []*doc.Analyzer\n\tfor _, a := range analyzers {\n\t\tjson = append(json, &doc.Analyzer{\n\t\t\tName:    a.Analyzer().Name,\n\t\t\tDoc:     a.Analyzer().Doc,\n\t\t\tURL:     a.Analyzer().URL,\n\t\t\tDefault: a.Enabled(defaults),\n\t\t})\n\t}\n\treturn json\n}\n\n// loadHints derives and returns the inlay hints metadata from the settings.InlayHint type.\nfunc loadHints(settingsPkg *packages.Package) ([]*doc.Hint, error) {\n\tenums, err := loadEnums(settingsPkg) // TODO(adonovan): call loadEnums exactly once\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tinlayHint := settingsPkg.Types.Scope().Lookup(\"InlayHint\").Type()\n\tvar hints []*doc.Hint\n\tfor _, enumVal := range enums[inlayHint] {\n\t\tname, _ := strconv.Unquote(enumVal.Value)\n\t\thints = append(hints, &doc.Hint{\n\t\t\tName:   name,\n\t\t\tDoc:    enumVal.Doc,\n\t\t\tStatus: enumVal.Status,\n\t\t})\n\t}\n\treturn hints, nil\n}\n\nfunc lowerFirst(x string) string {\n\tif x == \"\" {\n\t\treturn x\n\t}\n\treturn strings.ToLower(x[:1]) + x[1:]\n}\n\nfunc fileForPos(pkg *packages.Package, pos token.Pos) (*ast.File, error) {\n\tfset := pkg.Fset\n\tfor _, f := range pkg.Syntax {\n\t\tif safetoken.StartPosition(fset, f.FileStart).Filename == safetoken.StartPosition(fset, pos).Filename {\n\t\t\treturn f, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"no file for pos %v\", pos)\n}\n\nfunc rewriteAPI(_ []byte, api *doc.API) ([]byte, error) {\n\treturn json.MarshalIndent(api, \"\", \"\\t\")\n}\n\ntype optionsGroup struct {\n\ttitle   string // dotted path (e.g. \"ui.documentation\")\n\tfinal   string // final segment of title (e.g. \"documentation\")\n\tlevel   int\n\toptions []*doc.Option\n}\n\nfunc rewriteSettings(prevContent []byte, api *doc.API) ([]byte, error) {\n\tcontent := prevContent\n\tfor category, opts := range api.Options {\n\t\tgroups := collectGroups(opts)\n\n\t\tvar buf bytes.Buffer\n\n\t\t// First, print a table of contents (ToC).\n\t\tfmt.Fprintln(&buf)\n\t\tfor _, h := range groups {\n\t\t\ttitle := h.final\n\t\t\tif title != \"\" {\n\t\t\t\tfmt.Fprintf(&buf, \"%s* [%s](#%s)\\n\",\n\t\t\t\t\tstrings.Repeat(\"  \", h.level),\n\t\t\t\t\tcapitalize(title),\n\t\t\t\t\tstrings.ToLower(title))\n\t\t\t}\n\t\t}\n\n\t\t// Section titles are h2, options are h3.\n\t\t// This is independent of the option hierarchy.\n\t\t// (Nested options should not be smaller!)\n\t\tfmt.Fprintln(&buf)\n\t\tfor _, h := range groups {\n\t\t\ttitle := h.final\n\t\t\tif title != \"\" {\n\t\t\t\t// Emit HTML anchor as GitHub markdown doesn't support\n\t\t\t\t// \"# Heading {#anchor}\" syntax.\n\t\t\t\tfmt.Fprintf(&buf, \"<a id='%s'></a>\\n\", strings.ToLower(title))\n\n\t\t\t\tfmt.Fprintf(&buf, \"## %s\\n\\n\", capitalize(title))\n\t\t\t}\n\t\t\tfor _, opt := range h.options {\n\t\t\t\t// Emit HTML anchor as GitHub markdown doesn't support\n\t\t\t\t// \"# Heading {#anchor}\" syntax.\n\t\t\t\t//\n\t\t\t\t// (Each option name is the camelCased name of a field of\n\t\t\t\t// settings.UserOptions or one of its FooOptions subfields.)\n\t\t\t\tfmt.Fprintf(&buf, \"<a id='%s'></a>\\n\", opt.Name)\n\n\t\t\t\t// heading\n\t\t\t\t//\n\t\t\t\t// We do not display the undocumented dotted-path alias\n\t\t\t\t// (h.title + \".\" + opt.Name) used by VS Code only.\n\t\t\t\tfmt.Fprintf(&buf, \"### `%s %s`\\n\\n\", opt.Name, opt.Type)\n\n\t\t\t\t// status\n\t\t\t\twriteStatus(&buf, opt.Status)\n\n\t\t\t\t// doc comment\n\t\t\t\tbuf.WriteString(opt.Doc)\n\n\t\t\t\t// enums\n\t\t\t\twrite := func(name, doc string) {\n\t\t\t\t\tif doc != \"\" {\n\t\t\t\t\t\tunbroken := parBreakRE.ReplaceAllString(doc, \"\\\\\\n\")\n\t\t\t\t\t\tfmt.Fprintf(&buf, \"* %s\\n\", strings.TrimSpace(unbroken))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfmt.Fprintf(&buf, \"* `%s`\\n\", name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(opt.EnumValues) > 0 && opt.Type == \"enum\" {\n\t\t\t\t\t// enum as top-level type constructor\n\t\t\t\t\tbuf.WriteString(\"\\nMust be one of:\\n\\n\")\n\t\t\t\t\tfor _, val := range opt.EnumValues {\n\t\t\t\t\t\twrite(val.Value, val.Doc)\n\t\t\t\t\t}\n\t\t\t\t} else if len(opt.EnumKeys.Keys) > 0 && shouldShowEnumKeysInSettings(opt.Name) {\n\t\t\t\t\t// enum as map key (currently just \"annotations\")\n\t\t\t\t\tbuf.WriteString(\"\\nEach enum must be one of:\\n\\n\")\n\t\t\t\t\tfor _, val := range opt.EnumKeys.Keys {\n\t\t\t\t\t\twrite(val.Name, val.Doc)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// default value\n\t\t\t\tfmt.Fprintf(&buf, \"\\nDefault: `%v`.\\n\\n\", opt.Default)\n\t\t\t}\n\t\t}\n\t\tnewContent, err := replaceSection(content, category, buf.Bytes())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcontent = newContent\n\t}\n\treturn content, nil\n}\n\n// writeStatus emits a Markdown paragraph to buf about the status of a feature,\n// if nonempty.\nfunc writeStatus(buf *bytes.Buffer, status string) {\n\tswitch status {\n\tcase \"\":\n\tcase \"advanced\":\n\t\tfmt.Fprint(buf, \"**This is an advanced setting and should not be configured by most `gopls` users.**\\n\\n\")\n\tcase \"debug\":\n\t\tfmt.Fprint(buf, \"**This setting is for debugging purposes only.**\\n\\n\")\n\tcase \"experimental\":\n\t\tfmt.Fprint(buf, \"**This setting is experimental and may be deleted.**\\n\\n\")\n\tdefault:\n\t\tfmt.Fprintf(buf, \"**Status: %s.**\\n\\n\", status)\n\t}\n}\n\nvar parBreakRE = regexp.MustCompile(\"\\n{2,}\")\n\nfunc shouldShowEnumKeysInSettings(name string) bool {\n\t// These fields have too many possible options,\n\t// or too voluminous documentation, to render as enums.\n\t// Instead they each get their own page in the manual.\n\treturn !(name == \"analyses\" || name == \"codelenses\" || name == \"hints\")\n}\n\nfunc collectGroups(opts []*doc.Option) []optionsGroup {\n\toptsByHierarchy := map[string][]*doc.Option{}\n\tfor _, opt := range opts {\n\t\toptsByHierarchy[opt.Hierarchy] = append(optsByHierarchy[opt.Hierarchy], opt)\n\t}\n\n\t// As a hack, assume that uncategorized items are less important to\n\t// users and force the empty string to the end of the list.\n\tvar containsEmpty bool\n\tvar sorted []string\n\tfor h := range optsByHierarchy {\n\t\tif h == \"\" {\n\t\t\tcontainsEmpty = true\n\t\t\tcontinue\n\t\t}\n\t\tsorted = append(sorted, h)\n\t}\n\tsort.Strings(sorted)\n\tif containsEmpty {\n\t\tsorted = append(sorted, \"\")\n\t}\n\tvar groups []optionsGroup\n\tbaseLevel := 0\n\tfor _, h := range sorted {\n\t\tsplit := strings.SplitAfter(h, \".\")\n\t\tlast := split[len(split)-1]\n\t\t// Hack to capitalize all of UI.\n\t\tif last == \"ui\" {\n\t\t\tlast = \"UI\"\n\t\t}\n\t\t// A hierarchy may look like \"ui.formatting\". If \"ui\" has no\n\t\t// options of its own, it may not be added to the map, but it\n\t\t// still needs a heading.\n\t\tcomponents := strings.Split(h, \".\")\n\t\tfor i := 1; i < len(components); i++ {\n\t\t\tparent := strings.Join(components[0:i], \".\")\n\t\t\tif _, ok := optsByHierarchy[parent]; !ok {\n\t\t\t\tgroups = append(groups, optionsGroup{\n\t\t\t\t\ttitle: parent,\n\t\t\t\t\tfinal: last,\n\t\t\t\t\tlevel: baseLevel + i,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tgroups = append(groups, optionsGroup{\n\t\t\ttitle:   h,\n\t\t\tfinal:   last,\n\t\t\tlevel:   baseLevel + strings.Count(h, \".\"),\n\t\t\toptions: optsByHierarchy[h],\n\t\t})\n\t}\n\treturn groups\n}\n\nfunc capitalize(s string) string {\n\treturn string(unicode.ToUpper(rune(s[0]))) + s[1:]\n}\n\nfunc rewriteCodeLenses(prevContent []byte, api *doc.API) ([]byte, error) {\n\tvar buf bytes.Buffer\n\tfor _, lens := range api.Lenses {\n\t\tfmt.Fprintf(&buf, \"## `%s`: %s\\n\\n\", lens.Lens, lens.Title)\n\t\twriteStatus(&buf, lens.Status)\n\t\tfmt.Fprintf(&buf, \"%s\\n\\n\", lens.Doc)\n\t\tfmt.Fprintf(&buf, \"Default: %v\\n\\n\", onOff(lens.Default))\n\t\tfmt.Fprintf(&buf, \"File type: %s\\n\\n\", lens.FileType)\n\t}\n\treturn replaceSection(prevContent, \"Lenses\", buf.Bytes())\n}\n\nfunc rewriteAnalyzers(prevContent []byte, api *doc.API) ([]byte, error) {\n\tvar buf bytes.Buffer\n\tfor _, analyzer := range api.Analyzers {\n\t\tfmt.Fprintf(&buf, \"<a id='%s'></a>\\n\", analyzer.Name)\n\t\ttitle, doc, _ := strings.Cut(analyzer.Doc, \"\\n\")\n\t\ttitle = strings.TrimPrefix(title, analyzer.Name+\": \")\n\t\tfmt.Fprintf(&buf, \"## `%s`: %s\\n\\n\", analyzer.Name, title)\n\n\t\t// Convert Analyzer.Doc from go/doc/comment form to Markdown.\n\t\t// Headings in doc comments are converted to ### (HeadingLevel=3).\n\t\t//\n\t\t// Some Analyzers (e.g. go/analysis/passes/inline) use ## to indicate subheadings\n\t\t// Although this is valid Markdown, it is not valid go/doc/comment,\n\t\t// nor is it rendered as a subheading by pkg.go.dev or gopls's doc viewer.\n\t\t// Perhaps it will be supported in future; see\n\t\t// https://github.com/golang/go/issues/51082#issuecomment-1033116430 et seq.\n\t\t//\n\t\t// In the meantime, the go/doc/comment processing will escape them so\n\t\t// that the ## appears literally in analyzers.md just as it does in\n\t\t// the two viewers mentioned above. The meaning is clear enough.\n\t\tdoctree := new(comment.Parser).Parse(doc)\n\t\tbuf.Write((&comment.Printer{HeadingLevel: 3}).Markdown(doctree))\n\t\tbuf.WriteString(\"\\n\\n\")\n\n\t\tfmt.Fprintf(&buf, \"Default: %s.\", onOff(analyzer.Default))\n\t\tif !analyzer.Default {\n\t\t\tfmt.Fprintf(&buf, \" Enable by setting `\\\"analyses\\\": {\\\"%s\\\": true}`.\", analyzer.Name)\n\t\t}\n\t\tfmt.Fprintf(&buf, \"\\n\\n\")\n\t\tif analyzer.URL != \"\" {\n\t\t\t// TODO(adonovan): currently the URL provides the same information\n\t\t\t// as 'doc' above, though that may change due to\n\t\t\t// https://github.com/golang/go/issues/61315#issuecomment-1841350181.\n\t\t\t// In that case, update this to something like \"Complete documentation\".\n\t\t\tfmt.Fprintf(&buf, \"Package documentation: [%s](%s)\\n\\n\",\n\t\t\t\tanalyzer.Name, analyzer.URL)\n\t\t}\n\n\t}\n\treturn replaceSection(prevContent, \"Analyzers\", buf.Bytes())\n}\n\nfunc rewriteInlayHints(prevContent []byte, api *doc.API) ([]byte, error) {\n\tvar buf bytes.Buffer\n\tfor _, hint := range api.Hints {\n\t\tfmt.Fprintf(&buf, \"## **%v**\\n\\n\", hint.Name)\n\t\tfmt.Fprintf(&buf, \"%s\\n\\n\", hint.Doc)\n\t\tswitch hint.Default {\n\t\tcase true:\n\t\t\tfmt.Fprintf(&buf, \"**Enabled by default.**\\n\\n\")\n\t\tcase false:\n\t\t\tfmt.Fprintf(&buf, \"**Disabled by default. Enable it by setting `\\\"hints\\\": {\\\"%s\\\": true}`.**\\n\\n\", hint.Name)\n\t\t}\n\t}\n\treturn replaceSection(prevContent, \"Hints\", buf.Bytes())\n}\n\n// replaceSection replaces the portion of a file delimited by comments of the form:\n//\n//\t<!-- BEGIN sectionName -->\n//\t<!-- END section Name -->\nfunc replaceSection(content []byte, sectionName string, replacement []byte) ([]byte, error) {\n\tre := regexp.MustCompile(fmt.Sprintf(`(?s)<!-- BEGIN %v.* -->\\n(.*?)<!-- END %v.* -->`, sectionName, sectionName))\n\tidx := re.FindSubmatchIndex(content)\n\tif idx == nil {\n\t\treturn nil, fmt.Errorf(\"could not find section %q\", sectionName)\n\t}\n\tresult := slices.Clone(content[:idx[2]])\n\tresult = append(result, replacement...)\n\tresult = append(result, content[idx[3]:]...)\n\treturn result, nil\n}\n\ntype onOff bool\n\nfunc (o onOff) String() string {\n\tif o {\n\t\treturn \"on\"\n\t} else {\n\t\treturn \"off\"\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/doc/generate/generate_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestGenerated(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.NeedsLocalXTools(t)\n\n\tok, err := doMain(false)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !ok {\n\t\tt.Error(\"documentation needs updating. Run: cd gopls && go generate ./...\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/file/file.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The file package defines types used for working with LSP files.\npackage file\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// An Identity identifies the name and contents of a file.\n//\n// TODO(rfindley): Identity may not carry its weight. Consider instead just\n// exposing Handle.Hash, and using an ad-hoc key type where necessary.\n// Or perhaps if mod/work parsing is moved outside of the memoize cache,\n// a notion of Identity simply isn't needed.\ntype Identity struct {\n\tURI  protocol.DocumentURI\n\tHash Hash // digest of file contents\n}\n\nfunc (id Identity) String() string {\n\treturn fmt.Sprintf(\"%s%s\", id.URI, id.Hash)\n}\n\n// A FileHandle represents the URI, content, hash, and optional\n// version of a file tracked by the LSP session.\n//\n// File content may be provided by the file system (for Saved files)\n// or from an overlay, for open files with unsaved edits.\n// A FileHandle may record an attempt to read a non-existent file,\n// in which case Content returns an error.\ntype Handle interface {\n\t// URI is the URI for this file handle.\n\tURI() protocol.DocumentURI\n\t// Identity returns an Identity for the file, even if there was an error\n\t// reading it.\n\tIdentity() Identity\n\t// SameContentsOnDisk reports whether the file has the same content on disk:\n\t// it is false for files open on an editor with unsaved edits.\n\tSameContentsOnDisk() bool\n\t// Version returns the file version, as defined by the LSP client.\n\t// For on-disk file handles, Version returns 0.\n\tVersion() int32\n\t// Content returns the contents of a file.\n\t// If the file is not available, returns a nil slice and an error.\n\tContent() ([]byte, error)\n\t// ModTime reports the modification time of a file.\n\t// If the file is not available, returns the zero time and an error.\n\tModTime() (time.Time, error)\n\t// String returns the file's path.\n\tString() string\n}\n\n// A Source maps URIs to Handles.\ntype Source interface {\n\t// ReadFile returns the Handle for a given URI, either by reading the content\n\t// of the file or by obtaining it from a cache.\n\t//\n\t// Invariant: ReadFile must only return an error in the case of context\n\t// cancellation. If ctx.Err() is nil, the resulting error must also be nil.\n\tReadFile(ctx context.Context, uri protocol.DocumentURI) (Handle, error)\n}\n"
  },
  {
    "path": "gopls/internal/file/hash.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage file\n\nimport (\n\t\"crypto/sha256\"\n\t\"fmt\"\n)\n\n// A Hash is a cryptographic digest of the contents of a file.\n// (Although at 32B it is larger than a 16B string header, it is smaller\n// and has better locality than the string header + 64B of hex digits.)\ntype Hash [sha256.Size]byte\n\n// HashOf returns the hash of some data.\nfunc HashOf(data []byte) Hash {\n\treturn Hash(sha256.Sum256(data))\n}\n\n// String returns the digest as a string of hex digits.\nfunc (h Hash) String() string {\n\treturn fmt.Sprintf(\"%64x\", [sha256.Size]byte(h))\n}\n\n// XORWith updates *h to *h XOR h2.\nfunc (h *Hash) XORWith(h2 Hash) {\n\t// Small enough that we don't need crypto/subtle.XORBytes.\n\tfor i := range h {\n\t\th[i] ^= h2[i]\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/file/kind.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage file\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// Kind describes the kind of the file in question.\n// It can be one of Go,mod, Sum, or Tmpl.\ntype Kind int\n\nconst (\n\t// UnknownKind is a file type we don't know about.\n\tUnknownKind = Kind(iota)\n\n\t// Go is a Go source file.\n\tGo\n\t// Mod is a go.mod file.\n\tMod\n\t// Sum is a go.sum file.\n\tSum\n\t// Tmpl is a template file.\n\tTmpl\n\t// Work is a go.work file.\n\tWork\n\t// Asm is a Go assembly (.s) file.\n\tAsm\n)\n\nfunc (k Kind) String() string {\n\tswitch k {\n\tcase Go:\n\t\treturn \"go\"\n\tcase Mod:\n\t\treturn \"go.mod\"\n\tcase Sum:\n\t\treturn \"go.sum\"\n\tcase Tmpl:\n\t\treturn \"tmpl\"\n\tcase Work:\n\t\treturn \"go.work\"\n\tcase Asm:\n\t\treturn \"Go assembly\"\n\tdefault:\n\t\treturn fmt.Sprintf(\"internal error: unknown file kind %d\", k)\n\t}\n}\n\n// KindForLang returns the gopls file [Kind] associated with the given LSP\n// LanguageKind string from the LanguageID field of [protocol.TextDocumentItem],\n// or UnknownKind if the language is not one recognized by gopls.\nfunc KindForLang(langID protocol.LanguageKind) Kind {\n\tswitch langID {\n\tcase \"go\":\n\t\treturn Go\n\tcase \"go.mod\":\n\t\treturn Mod\n\tcase \"go.sum\":\n\t\treturn Sum\n\tcase \"tmpl\", \"gotmpl\":\n\t\treturn Tmpl\n\tcase \"go.work\":\n\t\treturn Work\n\tcase \"go.s\":\n\t\treturn Asm\n\tdefault:\n\t\treturn UnknownKind\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/file/modification.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage file\n\nimport \"golang.org/x/tools/gopls/internal/protocol\"\n\n// Modification represents a modification to a file.\ntype Modification struct {\n\tURI    protocol.DocumentURI\n\tAction Action\n\n\t// OnDisk is true if a watched file is changed on disk.\n\t// If true, Version will be -1 and Text will be nil.\n\tOnDisk bool\n\n\t// Version will be -1 and Text will be nil when they are not supplied,\n\t// specifically on textDocument/didClose and for on-disk changes.\n\tVersion int32\n\tText    []byte\n\n\t// LanguageID is only sent from the language client on textDocument/didOpen.\n\tLanguageID protocol.LanguageKind\n}\n\n// An Action is a type of file state change.\ntype Action int\n\nconst (\n\tUnknownAction = Action(iota)\n\tOpen\n\tChange\n\tClose\n\tSave\n\tCreate\n\tDelete\n)\n\nfunc (a Action) String() string {\n\tswitch a {\n\tcase Open:\n\t\treturn \"Open\"\n\tcase Change:\n\t\treturn \"Change\"\n\tcase Close:\n\t\treturn \"Close\"\n\tcase Save:\n\t\treturn \"Save\"\n\tcase Create:\n\t\treturn \"Create\"\n\tcase Delete:\n\t\treturn \"Delete\"\n\tdefault:\n\t\treturn \"Unknown\"\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/filecache/filecache.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The filecache package provides a file-based shared durable blob cache.\n//\n// The cache is a machine-global mapping from (kind string, key\n// [32]byte) to []byte, where kind is an identifier describing the\n// namespace or purpose (e.g. \"analysis\"), and key is a SHA-256 digest\n// of the recipe of the value. (It need not be the digest of the value\n// itself, so you can query the cache without knowing what value the\n// recipe would produce.)\n//\n// The space budget of the cache can be controlled by [SetBudget].\n// Cache entries may be evicted at any time or in any order.\n// Note that \"du -sh $GOPLSCACHE\" may report a disk usage\n// figure that is rather larger (e.g. 50%) than the budget because\n// it rounds up partial disk blocks.\n//\n// The Get and Set operations are concurrency-safe.\npackage filecache\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/lru\"\n)\n\n// Start causes the filecache to initialize and start garbage gollection.\n//\n// Start is automatically called by the first call to Get, but may be called\n// explicitly to pre-initialize the cache.\nfunc Start() {\n\tgo getCacheDir()\n}\n\n// As an optimization, use a 100MB in-memory LRU cache in front of filecache\n// operations. This reduces I/O for operations such as diagnostics or\n// implementations that repeatedly access the same cache entries.\nvar memCache = lru.New[memKey, []byte](100 * 1e6)\n\ntype memKey struct {\n\tkind string\n\tkey  [32]byte\n}\n\n// Get retrieves from the cache and returns the value most recently\n// supplied to Set(kind, key), possibly by another process.\n//\n// Get returns ErrNotFound if the value was not found. The first call\n// to Get may fail due to ENOSPC or deletion of the process's\n// executable. Other causes of failure include deletion or corruption\n// of the cache (by external meddling) while gopls is running, or\n// faulty hardware; see issue #67433.\n//\n// Callers should not modify the returned array.\nfunc Get(kind string, key [32]byte) ([]byte, error) {\n\t// First consult the read-through memory cache.\n\t// Note that memory cache hits do not update the times\n\t// used for LRU eviction of the file-based cache.\n\tif value, ok := memCache.Get(memKey{kind, key}); ok {\n\t\treturn value, nil\n\t}\n\n\tiolimit <- struct{}{}        // acquire a token\n\tdefer func() { <-iolimit }() // release a token\n\n\t// Read the index file, which provides the name of the CAS file.\n\tindexName, err := filename(kind, key)\n\tif err != nil {\n\t\t// e.g. ENOSPC, deletion of executable (first time only);\n\t\t// deletion of cache (at any time).\n\t\treturn nil, err\n\t}\n\tindexData, err := os.ReadFile(indexName)\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\treturn nil, ErrNotFound\n\t\t}\n\t\treturn nil, err\n\t}\n\tvar valueHash [32]byte\n\tif copy(valueHash[:], indexData) != len(valueHash) {\n\t\treturn nil, ErrNotFound // index entry has wrong length\n\t}\n\n\t// Read the CAS file and check its contents match.\n\t//\n\t// This ensures integrity in all cases (corrupt or truncated\n\t// file, short read, I/O error, wrong length, etc) except an\n\t// engineered hash collision, which is infeasible.\n\tcasName, err := filename(casKind, valueHash)\n\tif err != nil {\n\t\treturn nil, err // see above for possible causes\n\t}\n\tvalue, _ := os.ReadFile(casName) // ignore error\n\tif sha256.Sum256(value) != valueHash {\n\t\treturn nil, ErrNotFound // CAS file is missing or has wrong contents\n\t}\n\n\t// Update file times used by LRU eviction.\n\t//\n\t// Because this turns a read into a write operation,\n\t// we follow the approach used in the go command's\n\t// cache and update the access time only if the\n\t// existing timestamp is older than one hour.\n\t//\n\t// (Traditionally the access time would be updated\n\t// automatically, but for efficiency most POSIX systems have\n\t// for many years set the noatime mount option to avoid every\n\t// open or read operation entailing a metadata write.)\n\ttouch(indexName, casName)\n\n\tmemCache.Set(memKey{kind, key}, value, len(value))\n\n\treturn value, nil\n}\n\n// ErrNotFound is the distinguished error\n// returned by Get when the key is not found.\nvar ErrNotFound = fmt.Errorf(\"not found\")\n\n// Set updates the value in the cache.\n//\n// Set may fail due to:\n// - failure to access/create the cache (first call only);\n// - out of space (ENOSPC);\n// - deletion of the cache concurrent with a call to Set;\n// - faulty hardware.\n// See issue #67433.\nfunc Set(kind string, key [32]byte, value []byte) error {\n\tmemCache.Set(memKey{kind, key}, value, len(value))\n\n\t// Set the active event to wake up the GC.\n\tselect {\n\tcase active <- struct{}{}:\n\tdefault:\n\t}\n\n\tiolimit <- struct{}{}        // acquire a token\n\tdefer func() { <-iolimit }() // release a token\n\n\t// First, add the value to the content-\n\t// addressable store (CAS), if not present.\n\thash := sha256.Sum256(value)\n\tcasName, err := filename(casKind, hash)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Does CAS file exist and have correct (complete) content?\n\t// TODO(adonovan): opt: use mmap for this check.\n\tif prev, _ := os.ReadFile(casName); !bytes.Equal(prev, value) {\n\t\tif err := os.MkdirAll(filepath.Dir(casName), 0700); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// Avoiding O_TRUNC here is merely an optimization to avoid\n\t\t// cache misses when two threads race to write the same file.\n\t\tif err := writeFileNoTrunc(casName, value, 0600); err != nil {\n\t\t\tos.Remove(casName) // ignore error\n\t\t\treturn err         // e.g. disk full\n\t\t}\n\t}\n\n\t// Now write an index entry that refers to the CAS file.\n\tindexName, err := filename(kind, key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := os.MkdirAll(filepath.Dir(indexName), 0700); err != nil {\n\t\treturn err\n\t}\n\tif err := writeFileNoTrunc(indexName, hash[:], 0600); err != nil {\n\t\tos.Remove(indexName) // ignore error\n\t\treturn err           // e.g. disk full\n\t}\n\n\t// Update the CAS file's timestamp to prevent premature LRU eviction.\n\ttouch(casName)\n\n\treturn nil\n}\n\nfunc touch(filenames ...string) {\n\tnow := time.Now()\n\tfor _, filename := range filenames {\n\t\tst, err := os.Stat(filename)\n\t\tif err == nil && now.Sub(st.ModTime()) > time.Hour {\n\t\t\tos.Chtimes(filename, now, now) // ignore error\n\t\t}\n\t}\n}\n\n// The active 1-channel is a selectable resettable event\n// indicating recent cache activity.\nvar active = make(chan struct{}, 1)\n\n// writeFileNoTrunc is like os.WriteFile but doesn't truncate until\n// after the write, so that racing writes of the same data are idempotent.\nfunc writeFileNoTrunc(filename string, data []byte, perm os.FileMode) error {\n\tf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, perm)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = f.Write(data)\n\tif err == nil {\n\t\terr = f.Truncate(int64(len(data)))\n\t}\n\tif closeErr := f.Close(); err == nil {\n\t\terr = closeErr\n\t}\n\treturn err\n}\n\n// reserved kind strings\nconst (\n\tcasKind = \"cas\" // content-addressable store files\n\tbugKind = \"bug\" // gopls bug reports\n)\n\nvar iolimit = make(chan struct{}, 128) // counting semaphore to limit I/O concurrency in Set.\n\nvar budget int64 = 1e9 // 1GB\n\n// SetBudget sets a soft limit on disk usage of regular files in the\n// cache (in bytes) and returns the previous value. Supplying a\n// negative value queries the current value without changing it.\n//\n// If two gopls processes have different budgets, the one with the\n// lower budget will collect garbage more actively, but both will\n// observe the effect.\n//\n// Even in the steady state, the storage usage reported by the 'du'\n// command may exceed the budget by as much as a factor of 3 due to\n// the overheads of directories and the effects of block quantization,\n// which are especially pronounced for the small index files.\nfunc SetBudget(new int64) (old int64) {\n\tif new < 0 {\n\t\treturn atomic.LoadInt64(&budget)\n\t}\n\treturn atomic.SwapInt64(&budget, new)\n}\n\n// --- implementation ----\n\n// filename returns the name of the cache file of the specified kind and key.\n//\n// A typical cache file has a name such as:\n//\n//\t$HOME/Library/Caches / gopls / VVVVVVVV / KK / KKKK...KKKK - kind\n//\n// The portions separated by spaces are as follows:\n// - The user's preferred cache directory; the default value varies by OS.\n// - The constant \"gopls\".\n// - The \"version\", 32 bits of the digest of the gopls executable.\n// - The first 8 bits of the key, to avoid huge directories.\n// - The full 256 bits of the key.\n// - The kind or purpose of this cache file (e.g. \"analysis\").\n//\n// The kind establishes a namespace for the keys. It is represented as\n// a suffix, not a segment, as this significantly reduces the number\n// of directories created, and thus the storage overhead.\n//\n// Previous iterations of the design aimed for the invariant that once\n// a file is written, its contents are never modified, though it may\n// be atomically replaced or removed. However, not all platforms have\n// an atomic rename operation (our first approach), and file locking\n// (our second) is a notoriously fickle mechanism.\n//\n// The current design instead exploits a trick from the cache\n// implementation used by the go command: writes of small files are in\n// practice atomic (all or nothing) on all platforms.\n// (See GOROOT/src/cmd/go/internal/cache/cache.go.)\n//\n// Russ Cox notes: \"all file systems use an rwlock around every file\n// system block, including data blocks, so any writes or reads within\n// the same block are going to be handled atomically by the FS\n// implementation without any need to request file locking explicitly.\n// And since the files are so small, there's only one block. (A block\n// is at minimum 512 bytes, usually much more.)\" And: \"all modern file\n// systems protect against [partial writes due to power loss] with\n// journals.\"\n//\n// We use a two-level scheme consisting of an index and a\n// content-addressable store (CAS). A single cache entry consists of\n// two files. The value of a cache entry is written into the file at\n// filename(\"cas\", sha256(value)). Since the value may be arbitrarily\n// large, this write is not atomic. That means we must check the\n// integrity of the contents read back from the CAS to make sure they\n// hash to the expected key. If the CAS file is incomplete or\n// inconsistent, we proceed as if it were missing.\n//\n// Once the CAS file has been written, we write a small fixed-size\n// index file at filename(kind, key), using the values supplied by the\n// caller. The index file contains the hash that identifies the value\n// file in the CAS. (We could add extra metadata to this file, up to\n// 512B, the minimum size of a disk block, if later desired, so long\n// as the total size remains fixed.) Because the index file is small,\n// concurrent writes to it are atomic in practice, even though this is\n// not guaranteed by any OS. The fixed size ensures that readers can't\n// see a palimpsest when a short new file overwrites a longer old one.\n//\n// New versions of gopls are free to reorganize the contents of the\n// version directory as needs evolve.  But all versions of gopls must\n// in perpetuity treat the \"gopls\" directory in a common fashion.\n//\n// In particular, each gopls process attempts to garbage collect\n// the entire gopls directory so that newer binaries can clean up\n// after older ones: in the development cycle especially, new\n// versions may be created frequently.\nfunc filename(kind string, key [32]byte) (string, error) {\n\tbase := fmt.Sprintf(\"%x-%s\", key, kind)\n\tdir, err := getCacheDir()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t// Keep the BugReports function consistent with this one.\n\treturn filepath.Join(dir, base[:2], base), nil\n}\n\n// getCacheDir returns the persistent cache directory of all processes\n// running this version of the gopls executable.\n//\n// It must incorporate the hash of the executable so that we needn't\n// worry about incompatible changes to the file format or changes to\n// the algorithm that produced the index.\nfunc getCacheDir() (string, error) {\n\tcacheDirOnce.Do(func() {\n\t\t// Use user's preferred cache directory.\n\t\tuserDir := os.Getenv(\"GOPLSCACHE\")\n\t\tif userDir == \"\" {\n\t\t\tvar err error\n\t\t\tuserDir, err = os.UserCacheDir()\n\t\t\tif err != nil {\n\t\t\t\tuserDir = os.TempDir()\n\t\t\t}\n\t\t}\n\t\tgoplsDir := filepath.Join(userDir, \"gopls\")\n\n\t\t// UserCacheDir may return a nonexistent directory\n\t\t// (in which case we must create it, which may fail),\n\t\t// or it may return a non-writable directory, in\n\t\t// which case we should ideally respect the user's express\n\t\t// wishes (e.g. XDG_CACHE_HOME) and not write somewhere else.\n\t\t// Sadly UserCacheDir doesn't currently let us distinguish\n\t\t// such intent from accidental misconfiguraton such as HOME=/\n\t\t// in a CI builder. So, we check whether the gopls subdirectory\n\t\t// can be created (or already exists) and not fall back to /tmp.\n\t\t// See also https://github.com/golang/go/issues/57638.\n\t\tif os.MkdirAll(goplsDir, 0700) != nil {\n\t\t\tgoplsDir = filepath.Join(os.TempDir(), \"gopls\")\n\t\t}\n\n\t\t// Start the garbage collector.\n\t\tgo gc(goplsDir)\n\n\t\t// Compute the hash of this executable (~20ms) and create a subdirectory.\n\t\thash, err := hashExecutable()\n\t\tif err != nil {\n\t\t\tcacheDirErr = fmt.Errorf(\"can't hash gopls executable: %w\", err)\n\t\t}\n\t\t// Use only 32 bits of the digest to avoid unwieldy filenames.\n\t\t// It's not an adversarial situation.\n\t\tcacheDir = filepath.Join(goplsDir, fmt.Sprintf(\"%x\", hash[:4]))\n\t\tif err := os.MkdirAll(cacheDir, 0700); err != nil {\n\t\t\tcacheDirErr = fmt.Errorf(\"can't create cache: %w\", err)\n\t\t}\n\t})\n\treturn cacheDir, cacheDirErr\n}\n\nvar (\n\tcacheDirOnce sync.Once\n\tcacheDir     string\n\tcacheDirErr  error\n)\n\nfunc hashExecutable() (hash [32]byte, err error) {\n\texe, err := os.Executable()\n\tif err != nil {\n\t\treturn hash, err\n\t}\n\tf, err := os.Open(exe)\n\tif err != nil {\n\t\treturn hash, err\n\t}\n\tdefer f.Close()\n\th := sha256.New()\n\tif _, err := io.Copy(h, f); err != nil {\n\t\treturn hash, fmt.Errorf(\"can't read executable: %w\", err)\n\t}\n\th.Sum(hash[:0])\n\treturn hash, nil\n}\n\n// gc runs forever, periodically deleting files from the gopls\n// directory until the space budget is no longer exceeded, and also\n// deleting files older than the maximum age, regardless of budget.\n//\n// One gopls process may delete garbage created by a different gopls\n// process, possibly running a different version of gopls, possibly\n// running concurrently.\nfunc gc(goplsDir string) {\n\t// period between collections\n\t//\n\t// Originally the period was always 1 minute, but this\n\t// consumed 15% of a CPU core when idle (#61049).\n\t//\n\t// The reason for running collections even when idle is so\n\t// that long lived gopls sessions eventually clean up the\n\t// caches created by defunct executables.\n\tconst (\n\t\tminPeriod = 5 * time.Minute // when active\n\t\tmaxPeriod = 6 * time.Hour   // when idle\n\t)\n\n\t// Sleep statDelay*batchSize between stats to smooth out I/O.\n\t//\n\t// The constants below were chosen using the following heuristics:\n\t//  - 1GB of filecache is on the order of ~100-200k files, in which case\n\t//    100μs delay per file introduces 10-20s of additional walk time,\n\t//    less than the minPeriod.\n\t//  - Processing batches of stats at once is much more efficient than\n\t//    sleeping after every stat (due to OS optimizations).\n\tconst statDelay = 100 * time.Microsecond // average delay between stats, to smooth out I/O\n\tconst batchSize = 1000                   // # of stats to process before sleeping\n\tconst maxAge = 5 * 24 * time.Hour        // max time since last access before file is deleted\n\n\t// The macOS filesystem is strikingly slow, at least on some machines.\n\t// /usr/bin/find achieves only about 25,000 stats per second\n\t// at full speed (no pause between items), meaning a large\n\t// cache may take several minutes to scan.\n\t//\n\t// (gopls' caches should never actually get this big in\n\t// practice: the example mentioned above resulted from a bug\n\t// that caused filecache to fail to delete any files.)\n\n\tconst debug = false\n\n\t// Names of all directories found in first pass; nil thereafter.\n\tdirs := make(map[string]bool)\n\n\tfor {\n\t\t// Wait unconditionally for the minimum period.\n\t\t// We do this even on the first run so that tests\n\t\t// don't (all) run the GC.\n\t\ttime.Sleep(minPeriod)\n\n\t\t// Enumerate all files in the cache.\n\t\ttype item struct {\n\t\t\tpath  string\n\t\t\tmtime time.Time\n\t\t\tsize  int64\n\t\t}\n\t\tvar files []item\n\t\tstart := time.Now()\n\t\tvar total int64 // bytes\n\t\t_ = filepath.Walk(goplsDir, func(path string, stat os.FileInfo, err error) error {\n\t\t\tif err != nil {\n\t\t\t\treturn nil // ignore errors\n\t\t\t}\n\t\t\tif stat.IsDir() {\n\t\t\t\t// Collect (potentially empty) directories.\n\t\t\t\tif dirs != nil {\n\t\t\t\t\tdirs[path] = true\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Unconditionally delete files we haven't used in ages.\n\t\t\t\tage := time.Since(stat.ModTime())\n\t\t\t\tif age > maxAge {\n\t\t\t\t\tif debug {\n\t\t\t\t\t\tlog.Printf(\"age: deleting stale file %s (%dB, age %v)\",\n\t\t\t\t\t\t\tpath, stat.Size(), age)\n\t\t\t\t\t}\n\t\t\t\t\tos.Remove(path) // ignore error\n\t\t\t\t} else {\n\t\t\t\t\tfiles = append(files, item{path, stat.ModTime(), stat.Size()})\n\t\t\t\t\ttotal += stat.Size()\n\t\t\t\t\tif debug && len(files)%1000 == 0 {\n\t\t\t\t\t\tlog.Printf(\"filecache: checked %d files in %v\", len(files), time.Since(start))\n\t\t\t\t\t}\n\t\t\t\t\tif len(files)%batchSize == 0 {\n\t\t\t\t\t\ttime.Sleep(batchSize * statDelay)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\n\t\t// Sort oldest files first.\n\t\tsort.Slice(files, func(i, j int) bool {\n\t\t\treturn files[i].mtime.Before(files[j].mtime)\n\t\t})\n\n\t\t// Delete oldest files until we're under budget.\n\t\tbudget := atomic.LoadInt64(&budget)\n\t\tfor _, file := range files {\n\t\t\tif total < budget {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif debug {\n\t\t\t\tage := time.Since(file.mtime)\n\t\t\t\tlog.Printf(\"budget: deleting stale file %s (%dB, age %v)\",\n\t\t\t\t\tfile.path, file.size, age)\n\t\t\t}\n\t\t\tos.Remove(file.path) // ignore error\n\t\t\ttotal -= file.size\n\t\t}\n\t\tfiles = nil // release memory before sleep\n\n\t\t// Once only, delete all directories.\n\t\t// This will succeed only for the empty ones,\n\t\t// and ensures that stale directories (whose\n\t\t// files have been deleted) are removed eventually.\n\t\t// They don't take up much space but they do slow\n\t\t// down the traversal.\n\t\t//\n\t\t// We do this after the sleep to minimize the\n\t\t// race against Set, which may create a directory\n\t\t// that is momentarily empty.\n\t\t//\n\t\t// (Test processes don't live that long, so\n\t\t// this may not be reached on the CI builders.)\n\t\tif dirs != nil {\n\t\t\tdirnames := make([]string, 0, len(dirs))\n\t\t\tfor dir := range dirs {\n\t\t\t\tdirnames = append(dirnames, dir)\n\t\t\t}\n\t\t\tdirs = nil\n\n\t\t\t// Descending length order => children before parents.\n\t\t\tsort.Slice(dirnames, func(i, j int) bool {\n\t\t\t\treturn len(dirnames[i]) > len(dirnames[j])\n\t\t\t})\n\t\t\tvar deleted int\n\t\t\tfor _, dir := range dirnames {\n\t\t\t\tif os.Remove(dir) == nil { // ignore error\n\t\t\t\t\tdeleted++\n\t\t\t\t}\n\t\t\t}\n\t\t\tif debug {\n\t\t\t\tlog.Printf(\"deleted %d empty directories\", deleted)\n\t\t\t}\n\t\t}\n\n\t\t// Wait up to the max period,\n\t\t// or for Set activity in this process.\n\t\tselect {\n\t\tcase <-active:\n\t\tcase <-time.After(maxPeriod):\n\t\t}\n\t}\n}\n\nfunc init() {\n\t// Register a handler to durably record this process's first\n\t// assertion failure in the cache so that we can ask users to\n\t// share this information via the stats command.\n\tbug.Handle(func(bug bug.Bug) {\n\t\t// Wait for cache init (bugs in tests happen early).\n\t\t_, _ = getCacheDir()\n\n\t\tdata, err := json.Marshal(bug)\n\t\tif err != nil {\n\t\t\tpanic(fmt.Sprintf(\"error marshalling bug %+v: %v\", bug, err))\n\t\t}\n\n\t\tkey := sha256.Sum256(data)\n\t\t_ = Set(bugKind, key, data)\n\t})\n}\n\n// BugReports returns a new unordered array of the contents\n// of all cached bug reports produced by this executable.\n// It also returns the location of the cache directory\n// used by this process (or \"\" on initialization error).\nfunc BugReports() (string, []bug.Bug) {\n\t// To test this logic, run:\n\t// $ TEST_GOPLS_BUG=oops gopls bug     # trigger a bug\n\t// $ gopls stats                       # list the bugs\n\n\tdir, err := getCacheDir()\n\tif err != nil {\n\t\treturn \"\", nil // ignore initialization errors\n\t}\n\tvar result []bug.Bug\n\t_ = filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn nil // ignore readdir/stat errors\n\t\t}\n\t\t// Parse the key from each \"XXXX-bug\" cache file name.\n\t\tif !info.IsDir() && strings.HasSuffix(path, bugKind) {\n\t\t\tvar key [32]byte\n\t\t\tn, err := hex.Decode(key[:], []byte(filepath.Base(path)[:len(key)*2]))\n\t\t\tif err != nil || n != len(key) {\n\t\t\t\treturn nil // ignore malformed file names\n\t\t\t}\n\t\t\tcontent, err := Get(bugKind, key)\n\t\t\tif err == nil { // ignore read errors\n\t\t\t\tvar b bug.Bug\n\t\t\t\tif err := json.Unmarshal(content, &b); err != nil {\n\t\t\t\t\tlog.Printf(\"error marshalling bug %q: %v\", string(content), err)\n\t\t\t\t}\n\t\t\t\tresult = append(result, b)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\treturn dir, result\n}\n"
  },
  {
    "path": "gopls/internal/filecache/filecache_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage filecache_test\n\n// This file defines tests of the API of the filecache package.\n//\n// Some properties (e.g. garbage collection) cannot be exercised\n// through the API, so this test does not attempt to do so.\n\nimport (\n\t\"bytes\"\n\tcryptorand \"crypto/rand\"\n\t\"fmt\"\n\t\"log\"\n\tmathrand \"math/rand\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestBasics(t *testing.T) {\n\tconst kind = \"TestBasics\"\n\tkey := uniqueKey() // never used before\n\tvalue := []byte(\"hello\")\n\n\t// Get of a never-seen key returns not found.\n\tif _, err := filecache.Get(kind, key); err != filecache.ErrNotFound {\n\t\tif strings.Contains(err.Error(), \"operation not supported\") ||\n\t\t\tstrings.Contains(err.Error(), \"not implemented\") {\n\t\t\tt.Skipf(\"skipping: %v\", err)\n\t\t}\n\t\tt.Errorf(\"Get of random key returned err=%q, want not found\", err)\n\t}\n\n\t// Set of a never-seen key and a small value succeeds.\n\tif err := filecache.Set(kind, key, value); err != nil {\n\t\tt.Errorf(\"Set failed: %v\", err)\n\t}\n\n\t// Get of the key returns a copy of the value.\n\tif got, err := filecache.Get(kind, key); err != nil {\n\t\tt.Errorf(\"Get after Set failed: %v\", err)\n\t} else if string(got) != string(value) {\n\t\tt.Errorf(\"Get after Set returned different value: got %q, want %q\", got, value)\n\t}\n\n\t// The kind is effectively part of the key.\n\tif _, err := filecache.Get(\"different-kind\", key); err != filecache.ErrNotFound {\n\t\tt.Errorf(\"Get with wrong kind returned err=%q, want not found\", err)\n\t}\n}\n\n// TestConcurrency exercises concurrent access to the same entry.\nfunc TestConcurrency(t *testing.T) {\n\tif os.Getenv(\"GO_BUILDER_NAME\") == \"plan9-arm\" {\n\t\tt.Skip(`skipping on plan9-arm builder due to golang/go#58748: failing with 'mount rpc error'`)\n\t}\n\tconst kind = \"TestConcurrency\"\n\tkey := uniqueKey()\n\tconst N = 100 // concurrency level\n\n\t// Construct N distinct values, each larger\n\t// than a typical 4KB OS file buffer page.\n\tvar values [N][8192]byte\n\tfor i := range values {\n\t\tif _, err := mathrand.Read(values[i][:]); err != nil {\n\t\t\tt.Fatalf(\"rand: %v\", err)\n\t\t}\n\t}\n\n\t// get calls Get and verifies that the cache entry\n\t// matches one of the values passed to Set.\n\tget := func(mustBeFound bool) error {\n\t\tgot, err := filecache.Get(kind, key)\n\t\tif err != nil {\n\t\t\tif err == filecache.ErrNotFound && !mustBeFound {\n\t\t\t\treturn nil // not found\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\tfor _, want := range values {\n\t\t\tif bytes.Equal(want[:], got) {\n\t\t\t\treturn nil // a match\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"Get returned a value that was never Set\")\n\t}\n\n\t// Perform N concurrent calls to Set and Get.\n\t// All sets must succeed.\n\t// All gets must return nothing, or one of the Set values;\n\t// there is no third possibility.\n\tvar group errgroup.Group\n\tfor i := range values {\n\t\tgroup.Go(func() error { return filecache.Set(kind, key, values[i][:]) })\n\t\tgroup.Go(func() error { return get(false) })\n\t}\n\tif err := group.Wait(); err != nil {\n\t\tif strings.Contains(err.Error(), \"operation not supported\") ||\n\t\t\tstrings.Contains(err.Error(), \"not implemented\") {\n\t\t\tt.Skipf(\"skipping: %v\", err)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\t// A final Get must report one of the values that was Set.\n\tif err := get(true); err != nil {\n\t\tt.Fatalf(\"final Get failed: %v\", err)\n\t}\n}\n\nconst (\n\ttestIPCKind   = \"TestIPC\"\n\ttestIPCValueA = \"hello\"\n\ttestIPCValueB = \"world\"\n)\n\n// TestIPC exercises interprocess communication through the cache.\n// It calls Set(A) in the parent, { Get(A); Set(B) } in the child\n// process, then Get(B) in the parent.\nfunc TestIPC(t *testing.T) {\n\ttestenv.NeedsExec(t)\n\n\tkeyA := uniqueKey()\n\tkeyB := uniqueKey()\n\tvalue := []byte(testIPCValueA)\n\n\t// Set keyA.\n\tif err := filecache.Set(testIPCKind, keyA, value); err != nil {\n\t\tif strings.Contains(err.Error(), \"operation not supported\") {\n\t\t\tt.Skipf(\"skipping: %v\", err)\n\t\t}\n\t\tt.Fatalf(\"Set: %v\", err)\n\t}\n\n\t// Call ipcChild in a child process,\n\t// passing it the keys in the environment\n\t// (quoted, to avoid NUL termination of C strings).\n\t// It will Get(A) then Set(B).\n\tcmd := exec.Command(os.Args[0], os.Args[1:]...)\n\tcmd.Env = append(os.Environ(),\n\t\t\"ENTRYPOINT=ipcChild\",\n\t\tfmt.Sprintf(\"KEYA=%q\", keyA),\n\t\tfmt.Sprintf(\"KEYB=%q\", keyB))\n\tcmd.Stdout = os.Stderr\n\tcmd.Stderr = os.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Verify keyB.\n\tgot, err := filecache.Get(testIPCKind, keyB)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif string(got) != \"world\" {\n\t\tt.Fatalf(\"Get(keyB) = %q, want %q\", got, \"world\")\n\t}\n}\n\n// We define our own main function so that portions of\n// some tests can run in a separate (child) process.\nfunc TestMain(m *testing.M) {\n\tswitch os.Getenv(\"ENTRYPOINT\") {\n\tcase \"ipcChild\":\n\t\tipcChild()\n\tdefault:\n\t\tos.Exit(m.Run())\n\t}\n}\n\n// ipcChild is the portion of TestIPC that runs in a child process.\nfunc ipcChild() {\n\tgetenv := func(name string) (key [32]byte) {\n\t\ts, _ := strconv.Unquote(os.Getenv(name))\n\t\tcopy(key[:], []byte(s))\n\t\treturn\n\t}\n\n\t// Verify key A.\n\tgot, err := filecache.Get(testIPCKind, getenv(\"KEYA\"))\n\tif err != nil || string(got) != testIPCValueA {\n\t\tlog.Fatalf(\"child: Get(key) = %q, %v; want %q\", got, err, testIPCValueA)\n\t}\n\n\t// Set key B.\n\tif err := filecache.Set(testIPCKind, getenv(\"KEYB\"), []byte(testIPCValueB)); err != nil {\n\t\tlog.Fatalf(\"child: Set(keyB) failed: %v\", err)\n\t}\n}\n\n// uniqueKey returns a key that has never been used before.\nfunc uniqueKey() (key [32]byte) {\n\tif _, err := cryptorand.Read(key[:]); err != nil {\n\t\tlog.Fatalf(\"rand: %v\", err)\n\t}\n\treturn\n}\n\nfunc BenchmarkUncontendedGet(b *testing.B) {\n\tconst kind = \"BenchmarkUncontendedGet\"\n\tkey := uniqueKey()\n\n\tvar value [8192]byte\n\tif _, err := mathrand.Read(value[:]); err != nil {\n\t\tb.Fatalf(\"rand: %v\", err)\n\t}\n\tif err := filecache.Set(kind, key, value[:]); err != nil {\n\t\tb.Fatal(err)\n\t}\n\n\tb.SetBytes(int64(len(value)))\n\n\tvar group errgroup.Group\n\tgroup.SetLimit(50)\n\tfor b.Loop() {\n\t\tgroup.Go(func() error {\n\t\t\t_, err := filecache.Get(kind, key)\n\t\t\treturn err\n\t\t})\n\t}\n\tif err := group.Wait(); err != nil {\n\t\tb.Fatal(err)\n\t}\n}\n\n// These two benchmarks are asymmetric: the one for Get imposes a\n// modest bound on concurrency (50) whereas the one for Set imposes a\n// much higher concurrency (1000) to test the implementation's\n// self-imposed bound.\n\nfunc BenchmarkUncontendedSet(b *testing.B) {\n\tconst kind = \"BenchmarkUncontendedSet\"\n\tkey := uniqueKey()\n\tvar value [8192]byte\n\n\tconst P = 1000 // parallelism\n\tb.SetBytes(P * int64(len(value)))\n\n\tfor b.Loop() {\n\t\t// Perform P concurrent calls to Set. All must succeed.\n\t\tvar group errgroup.Group\n\t\tfor range [P]bool{} {\n\t\t\tgroup.Go(func() error {\n\t\t\t\treturn filecache.Set(kind, key, value[:])\n\t\t\t})\n\t\t}\n\t\tif err := group.Wait(); err != nil {\n\t\t\tif strings.Contains(err.Error(), \"operation not supported\") ||\n\t\t\t\tstrings.Contains(err.Error(), \"not implemented\") {\n\t\t\t\tb.Skipf(\"skipping: %v\", err)\n\t\t\t}\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/filewatcher/export_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage filewatcher\n\n// This file defines things (and opens backdoors) needed only by tests.\n\n// SetAfterAddHook sets a hook to be called after a path is added to the watcher.\n// This is used in tests to inspect the error returned by the underlying watcher.\nfunc SetAfterAddHook(f func(string, error)) {\n\tafterAddHook = f\n}\n"
  },
  {
    "path": "gopls/internal/filewatcher/filewatcher.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage filewatcher\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// Watcher monitors file system events.\ntype Watcher interface {\n\t// WatchDir adds a directory to the set of watched directories.\n\tWatchDir(path string) error\n\n\t// Close stops the watcher and releases any associated resources.\n\tClose() error\n\n\t// Poke signals the watcher to prioritize a scan, if applicable.\n\t// This is used to implement adaptive polling.\n\tPoke()\n}\n\n// New creates a new file watcher and starts its event-handling loop. The\n// [Watcher.Close] method must be called to clean up resources.\n//\n// The provided event handler is called sequentially with a batch of file events,\n// but the error handler is called concurrently. The watcher blocks until the\n// handler returns, so the handlers should be fast and non-blocking.\n//\n// TODO(hxjiang): replace mode string to enum.\nfunc New(mode string, interval time.Duration, logger *slog.Logger, onEvents func([]protocol.FileEvent), onError func(error)) (Watcher, error) {\n\tswitch mode {\n\t// TODO (hxjiang): support poll watcher.\n\tcase \"fsnotify\":\n\t\treturn NewFSNotifyWatcher(interval, logger, onEvents, onError)\n\t}\n\t// TODO(hxjiang): support \"auto\" mode.\n\treturn nil, fmt.Errorf(\"unknown FileWatcher mode: %q\", mode)\n}\n"
  },
  {
    "path": "gopls/internal/filewatcher/filewatcher_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage filewatcher_test\n\nimport (\n\t\"cmp\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/filewatcher\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestFileWatcher(t *testing.T) {\n\tswitch runtime.GOOS {\n\tcase \"darwin\", \"linux\", \"windows\":\n\tdefault:\n\t\tt.Skip(\"unsupported OS\")\n\t}\n\n\ttestCases := []struct {\n\t\tname           string\n\t\tgoos           []string // if not empty, only run in these OS.\n\t\tinitWorkspace  string\n\t\tchanges        func(root string) error\n\t\texpectedEvents []protocol.FileEvent\n\t}{\n\t\t{\n\t\t\tname: \"create file in darwin\",\n\t\t\tgoos: []string{\"darwin\"},\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.WriteFile(filepath.Join(root, \"bar.go\"), []byte(\"package main\"), 0644)\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"bar.go\", Type: protocol.Created},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"create file in linux & windows\",\n\t\t\tgoos: []string{\"linux\", \"windows\"},\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.WriteFile(filepath.Join(root, \"bar.go\"), []byte(\"package main\"), 0644)\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"bar.go\", Type: protocol.Created},\n\t\t\t\t{URI: \"bar.go\", Type: protocol.Changed},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"modify file\",\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.WriteFile(filepath.Join(root, \"foo.go\"), []byte(\"package main // modified\"), 0644)\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"foo.go\", Type: protocol.Changed},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"delete file\",\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n-- bar.go --\npackage bar\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Remove(filepath.Join(root, \"foo.go\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"foo.go\", Type: protocol.Deleted},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"rename file in linux & windows\",\n\t\t\tgoos: []string{\"linux\", \"windows\"},\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Rename(filepath.Join(root, \"foo.go\"), filepath.Join(root, \"bar.go\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"foo.go\", Type: protocol.Deleted},\n\t\t\t\t{URI: \"bar.go\", Type: protocol.Created},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"rename file in darwin\",\n\t\t\tgoos: []string{\"darwin\"},\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Rename(filepath.Join(root, \"foo.go\"), filepath.Join(root, \"bar.go\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"bar.go\", Type: protocol.Created},\n\t\t\t\t{URI: \"foo.go\", Type: protocol.Deleted},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"create directory\",\n\t\t\tinitWorkspace: `\n-- foo.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Mkdir(filepath.Join(root, \"bar\"), 0755)\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"bar\", Type: protocol.Created},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"delete directory\",\n\t\t\tinitWorkspace: `\n-- foo/bar.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.RemoveAll(filepath.Join(root, \"foo\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t// We only assert that the directory deletion event exists,\n\t\t\t\t// because file system event behavior is inconsistent across\n\t\t\t\t// platforms when deleting a non-empty directory.\n\t\t\t\t// e.g. windows-amd64 may only emit a single dir removal event,\n\t\t\t\t// freebsd-amd64 report dir removal before file removal,\n\t\t\t\t// linux-amd64 report the reverse order.\n\t\t\t\t// Therefore, the most reliable and cross-platform compatible\n\t\t\t\t// signal is the deletion event for the directory itself.\n\t\t\t\t{URI: \"foo\", Type: protocol.Deleted},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"rename directory in linux & windows\",\n\t\t\tgoos: []string{\"linux\", \"windows\"},\n\t\t\tinitWorkspace: `\n-- foo/bar.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Rename(filepath.Join(root, \"foo\"), filepath.Join(root, \"baz\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"foo\", Type: protocol.Deleted},\n\t\t\t\t{URI: \"baz\", Type: protocol.Created},\n\t\t\t\t{URI: \"baz/bar.go\", Type: protocol.Created},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"rename directory in darwin\",\n\t\t\tgoos: []string{\"darwin\"},\n\t\t\tinitWorkspace: `\n-- foo/bar.go --\npackage foo\n`,\n\t\t\tchanges: func(root string) error {\n\t\t\t\treturn os.Rename(filepath.Join(root, \"foo\"), filepath.Join(root, \"baz\"))\n\t\t\t},\n\t\t\texpectedEvents: []protocol.FileEvent{\n\t\t\t\t{URI: \"baz\", Type: protocol.Created},\n\t\t\t\t{URI: \"baz/bar.go\", Type: protocol.Created},\n\t\t\t\t{URI: \"foo\", Type: protocol.Deleted},\n\t\t\t},\n\t\t},\n\t\t// TODO(hxjiang): test for symlink to a dir.\n\t}\n\n\tfor _, tt := range testCases {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif len(tt.goos) > 0 && !slices.Contains(tt.goos, runtime.GOOS) {\n\t\t\t\tt.Skipf(\"skipping on %s\", runtime.GOOS)\n\t\t\t}\n\n\t\t\troot := t.TempDir()\n\n\t\t\tarchive := txtar.Parse([]byte(tt.initWorkspace))\n\t\t\tfor _, f := range archive.Files {\n\t\t\t\tpath := filepath.Join(root, f.Name)\n\t\t\t\tif err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif err := os.WriteFile(path, f.Data, 0644); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfoundAll := make(chan struct{})\n\t\t\tvar gots []protocol.FileEvent\n\n\t\t\tmatched := 0\n\t\t\teventsHandler := func(events []protocol.FileEvent) {\n\t\t\t\tgots = append(gots, events...)\n\n\t\t\t\tif matched == len(tt.expectedEvents) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// This verifies that the list of wanted events is a subsequence of\n\t\t\t\t// the received events. It confirms not only that all wanted events\n\t\t\t\t// are present, but also that their relative order is preserved.\n\t\t\t\tfor _, got := range events {\n\t\t\t\t\twant := protocol.FileEvent{\n\t\t\t\t\t\tURI:  protocol.URIFromPath(filepath.Join(root, string(tt.expectedEvents[matched].URI))),\n\t\t\t\t\t\tType: tt.expectedEvents[matched].Type,\n\t\t\t\t\t}\n\t\t\t\t\tif want == got {\n\t\t\t\t\t\tmatched++\n\t\t\t\t\t}\n\t\t\t\t\tif matched == len(tt.expectedEvents) {\n\t\t\t\t\t\tclose(foundAll)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t\terrHandler := func(err error) {\n\t\t\t\tt.Errorf(\"error from watcher: %v\", err)\n\t\t\t}\n\t\t\tw, err := filewatcher.New(\"fsnotify\", 50*time.Millisecond, nil, eventsHandler, errHandler)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer func() {\n\t\t\t\tif err := w.Close(); err != nil {\n\t\t\t\t\tt.Errorf(\"failed to close the file watcher: %v\", err)\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tif err := w.WatchDir(root); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif tt.changes != nil {\n\t\t\t\tif err := tt.changes(root); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tselect {\n\t\t\tcase <-foundAll:\n\t\t\tcase <-time.After(30 * time.Second):\n\t\t\t\tif matched != len(tt.expectedEvents) {\n\t\t\t\t\tvar want strings.Builder\n\t\t\t\t\tfor _, e := range tt.expectedEvents {\n\t\t\t\t\t\twant.WriteString(fmt.Sprintf(\"URI: %s type: %v\\n\", e.URI, e.Type))\n\t\t\t\t\t}\n\t\t\t\t\tvar got strings.Builder\n\t\t\t\t\tfor _, e := range gots {\n\t\t\t\t\t\tgot.WriteString(fmt.Sprintf(\"URI: %s type: %v\\n\", strings.TrimPrefix(e.URI.Path(), root+\"/\"), e.Type))\n\t\t\t\t\t}\n\t\t\t\t\tt.Errorf(\"found %v matching events slice\\nwant sequences:\\n%s\\nall got:\\n%s\", matched, want.String(), got.String())\n\t\t\t\t}\n\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestBrokenSymlink(t *testing.T) {\n\tif runtime.GOOS != \"darwin\" {\n\t\tt.Skip(\"unsupported OS\")\n\t}\n\n\troot := t.TempDir()\n\n\t// watchErrs is used to capture watch errors during directory monitoring.\n\t// This mechanism allows the test to assert that specific directory watches\n\t// initially fail and subsequently recover upon fixing the broken symlink.\n\twatchErrs := make(chan error, 10)\n\tfilewatcher.SetAfterAddHook(func(path string, watchErr error) {\n\t\trel, err := filepath.Rel(root, path)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif rel == \"foo\" {\n\t\t\tif watchErr == nil {\n\t\t\t\tclose(watchErrs)\n\t\t\t} else {\n\t\t\t\twatchErrs <- watchErr\n\t\t\t}\n\t\t}\n\t})\n\tdefer filewatcher.SetAfterAddHook(nil)\n\n\tvar (\n\t\tgots     []protocol.FileEvent\n\t\tmatched  int\n\t\tfoundAll = make(chan struct{})\n\t)\n\twants := []protocol.FileEvent{\n\t\t// \"foo\" create event from fsnotify and synthesized create event\n\t\t// for all entries under foo.\n\t\t{URI: \"foo\", Type: protocol.Created},\n\t\t{URI: \"foo/a.go\", Type: protocol.Created},\n\t\t{URI: \"foo/b.go\", Type: protocol.Created},\n\t\t{URI: \"foo/from.go\", Type: protocol.Created},\n\t\t// \"to.go\" creation from fsnotify.\n\t\t{URI: \"to.go\", Type: protocol.Created},\n\t\t// file creation event after watch retry succeeded.\n\t\t{URI: \"foo/new.go\", Type: protocol.Created},\n\t}\n\teventsHandler := func(events []protocol.FileEvent) {\n\t\tgots = append(gots, events...)\n\n\t\tif matched == len(wants) {\n\t\t\treturn\n\t\t}\n\n\t\tfor _, got := range events {\n\t\t\twant := protocol.FileEvent{\n\t\t\t\tURI:  protocol.URIFromPath(filepath.Join(root, string(wants[matched].URI))),\n\t\t\t\tType: wants[matched].Type,\n\t\t\t}\n\t\t\tif want == got {\n\t\t\t\tmatched++\n\t\t\t}\n\t\t\tif matched == len(wants) {\n\t\t\t\tclose(foundAll)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t}\n\terrHandler := func(err error) {\n\t\tt.Errorf(\"error from watcher: %v\", err)\n\t}\n\tw, err := filewatcher.New(\"fsnotify\", 50*time.Millisecond, nil, eventsHandler, errHandler)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := w.Close(); err != nil {\n\t\t\tt.Errorf(\"failed to close the file watcher: %v\", err)\n\t\t}\n\t}()\n\n\tif err := w.WatchDir(root); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t{\n\t\t// Prepare a dir with with broken symbolic link.\n\t\t// foo                       <- 1st\n\t\t// ├── from.go -> root/to.go <- 1st\n\t\t// ├── a.go                  <- 1st\n\t\t// └── b.go                  <- 1st\n\n\t\tto := filepath.Join(root, \"to.go\")\n\n\t\tarchive := txtar.Parse([]byte(`\n-- a.go --\npackage a\n-- b.go --\npackage b\n`))\n\t\ttmp := filepath.Join(t.TempDir(), \"foo\")\n\t\tfor _, f := range archive.Files {\n\t\t\tpath := filepath.Join(tmp, f.Name)\n\t\t\tif err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {\n\t\t\t\tt.Fatalf(\"fail to create dir %v\", err)\n\t\t\t}\n\t\t\tif err := os.WriteFile(path, f.Data, 0644); err != nil {\n\t\t\t\tt.Fatalf(\"fail to write file %v\", err)\n\t\t\t}\n\t\t}\n\n\t\t// Create the symbolic link to a non-existing file. This would\n\t\t// cause the watch registration for dir \"foo\" to fail.\n\t\tif err := os.Symlink(to, filepath.Join(tmp, \"from.go\")); err != nil {\n\t\t\tt.Fatalf(\"fail to create symlink file %v\", err)\n\t\t}\n\n\t\t// Move the directory containing the broken symlink into place\n\t\t// to avoids a flaky test where the directory could be watched\n\t\t// before the symlink is created. See golang/go#74782.\n\t\tif err := os.Rename(tmp, filepath.Join(root, \"foo\")); err != nil {\n\t\t\tt.Fatalf(\"fail to rename file %v\", err)\n\t\t}\n\n\t\t// root\n\t\t// ├── foo                          <- 2nd (Move)\n\t\t// │   ├── a.go                     <- 2nd (Move)\n\t\t// │   ├── b.go                     <- 2nd (Move)\n\t\t// │   ├── from.go -> ../../to.go   <- 2nd (Move)\n\t\t// │   └── new.go                   <- 4th (Create)\n\t\t// └── to.go                        <- 3rd (Create)\n\n\t\t// Should be able to capture watch error while trying to watch dir \"foo\".\n\t\tif err := <-watchErrs; err == nil {\n\t\t\tt.Errorf(\"did not capture watch registration failure for dir foo\")\n\t\t}\n\n\t\t// The file watcher should retry watch registration and eventually succeed\n\t\t// watching for all dir under 'foo' after the file got created.\n\t\t{\n\t\t\tif err := os.WriteFile(to, []byte(\"package main\"), 0644); err != nil {\n\t\t\t\tt.Errorf(\"fail to write file %v\", err)\n\t\t\t}\n\n\t\t\ttimer := time.NewTimer(30 * time.Second)\n\t\t\tdefer timer.Stop()\n\n\t\touter:\n\t\t\tfor {\n\t\t\t\tselect {\n\t\t\t\tcase _, ok := <-watchErrs:\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tbreak outer\n\t\t\t\t\t}\n\t\t\t\tcase <-timer.C:\n\t\t\t\t\tt.Errorf(\"timed out after 30s waiting for watches on foo to be established\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Once the watch registration is done, file events under the\n\t\t// dir \"foo\" should be captured\n\t\tif err := os.WriteFile(filepath.Join(root, \"foo\", \"new.go\"), []byte(\"package main\"), 0644); err != nil {\n\t\t\tt.Fatalf(\"fail to write file %v\", err)\n\t\t}\n\t}\n\n\tselect {\n\tcase <-foundAll:\n\tcase <-time.After(30 * time.Second):\n\t\tif matched != len(wants) {\n\t\t\tvar want strings.Builder\n\t\t\tfor _, e := range wants {\n\t\t\t\twant.WriteString(fmt.Sprintf(\"URI: %s type: %v\\n\", e.URI, e.Type))\n\t\t\t}\n\t\t\tvar got strings.Builder\n\t\t\tfor _, e := range gots {\n\t\t\t\tgot.WriteString(fmt.Sprintf(\"URI: %s type: %v\\n\", strings.TrimPrefix(e.URI.Path(), root+\"/\"), e.Type))\n\t\t\t}\n\t\t\tt.Errorf(\"found %v matching events slice\\nwant sequences:\\n%s\\nall got:\\n%s\", matched, want.String(), got.String())\n\t\t}\n\n\t}\n}\n\nfunc TestStress(t *testing.T) {\n\tswitch runtime.GOOS {\n\tcase \"darwin\", \"linux\", \"windows\":\n\tdefault:\n\t\tt.Skip(\"unsupported OS\")\n\t}\n\n\tconst (\n\t\tdelay       = 50 * time.Millisecond\n\t\tparallelism = 100 // number of parallel instances of each kind of operation\n\t)\n\n\troot := t.TempDir()\n\n\tmkdir := func(base string) func() error {\n\t\treturn func() error {\n\t\t\treturn os.Mkdir(filepath.Join(root, base), 0755)\n\t\t}\n\t}\n\twrite := func(base string) func() error {\n\t\treturn func() error {\n\t\t\treturn os.WriteFile(filepath.Join(root, base), []byte(\"package main\"), 0644)\n\t\t}\n\t}\n\tremove := func(base string) func() error {\n\t\treturn func() error {\n\t\t\treturn os.Remove(filepath.Join(root, base))\n\t\t}\n\t}\n\trename := func(old, new string) func() error {\n\t\treturn func() error {\n\t\t\treturn os.Rename(filepath.Join(root, old), filepath.Join(root, new))\n\t\t}\n\t}\n\n\twants := make(map[protocol.FileEvent]bool)\n\twant := func(base string, t protocol.FileChangeType) {\n\t\twants[protocol.FileEvent{URI: protocol.URIFromPath(filepath.Join(root, base)), Type: t}] = true\n\t}\n\n\tfor i := range parallelism {\n\t\t// Create files and dirs that will be deleted or renamed later.\n\t\tif err := cmp.Or(\n\t\t\tmkdir(fmt.Sprintf(\"delete-dir-%d\", i))(),\n\t\t\tmkdir(fmt.Sprintf(\"old-dir-%d\", i))(),\n\t\t\twrite(fmt.Sprintf(\"delete-file-%d.go\", i))(),\n\t\t\twrite(fmt.Sprintf(\"old-file-%d.go\", i))(),\n\t\t); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Add expected notification events to the \"wants\" set.\n\t\twant(fmt.Sprintf(\"file-%d.go\", i), protocol.Created)\n\t\twant(fmt.Sprintf(\"delete-file-%d.go\", i), protocol.Deleted)\n\t\twant(fmt.Sprintf(\"old-file-%d.go\", i), protocol.Deleted)\n\t\twant(fmt.Sprintf(\"new-file-%d.go\", i), protocol.Created)\n\t\twant(fmt.Sprintf(\"dir-%d\", i), protocol.Created)\n\t\twant(fmt.Sprintf(\"delete-dir-%d\", i), protocol.Deleted)\n\t\twant(fmt.Sprintf(\"old-dir-%d\", i), protocol.Deleted)\n\t\twant(fmt.Sprintf(\"new-dir-%d\", i), protocol.Created)\n\t}\n\n\tfoundAll := make(chan struct{})\n\n\teventsHandler := func(events []protocol.FileEvent) {\n\t\tif len(wants) == 0 { // avoid closing twice\n\t\t\treturn\n\t\t}\n\t\tfor _, e := range events {\n\t\t\tdelete(wants, e)\n\t\t}\n\t\tif len(wants) == 0 {\n\t\t\tclose(foundAll)\n\t\t}\n\t}\n\terrHandler := func(err error) {\n\t\tt.Errorf(\"error from watcher: %v\", err)\n\t}\n\tw, err := filewatcher.New(\"fsnotify\", delay, nil, eventsHandler, errHandler)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := w.Close(); err != nil {\n\t\t\tt.Errorf(\"failed to close the file watcher: %v\", err)\n\t\t}\n\t}()\n\n\tif err := w.WatchDir(root); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Spin up multiple goroutines, to perform 6 file system operations i.e.\n\t// create, delete, rename of file or directory. For deletion and rename,\n\t// the goroutine deletes / renames files or directories created before the\n\t// watcher starts.\n\tvar g errgroup.Group\n\tfor id := range parallelism {\n\t\tops := []func() error{\n\t\t\twrite(fmt.Sprintf(\"file-%d.go\", id)),\n\t\t\tremove(fmt.Sprintf(\"delete-file-%d.go\", id)),\n\t\t\trename(fmt.Sprintf(\"old-file-%d.go\", id), fmt.Sprintf(\"new-file-%d.go\", id)),\n\t\t\tmkdir(fmt.Sprintf(\"dir-%d\", id)),\n\t\t\tremove(fmt.Sprintf(\"delete-dir-%d\", id)),\n\t\t\trename(fmt.Sprintf(\"old-dir-%d\", id), fmt.Sprintf(\"new-dir-%d\", id)),\n\t\t}\n\t\tfor _, f := range ops {\n\t\t\tg.Go(f)\n\t\t}\n\t}\n\tif err := g.Wait(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tselect {\n\tcase <-foundAll:\n\tcase <-time.After(30 * time.Second):\n\t\tif len(wants) > 0 {\n\t\t\tt.Errorf(\"missing expected events: %#v\", moremaps.KeySlice(wants))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/filewatcher/fsnotify_watcher.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage filewatcher\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t\"log\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/robustio\"\n)\n\n// ErrClosed is used when trying to operate on a closed Watcher.\nvar ErrClosed = errors.New(\"file watcher: watcher already closed\")\n\n// fsnotifyWatcher collects events from a [fsnotify.Watcher] and converts them\n// into batched LSP [protocol.FileEvent]s.\ntype fsnotifyWatcher struct {\n\tlogger *slog.Logger\n\n\tstop chan struct{}  // closed by Close to terminate run and process loop\n\twg   sync.WaitGroup // counts the number of active run and process goroutines (max 2)\n\n\tready chan struct{} // signals work to process\n\n\twatcher *fsnotify.Watcher\n\n\tmu sync.Mutex // guards all fields below\n\n\t// in is the queue of fsnotify events waiting to be processed.\n\tin []fsnotify.Event\n\n\t// out is the current batch of unsent file events, which will be sent when\n\t// the timer expires.\n\tout []protocol.FileEvent\n\n\t// knownDirs tracks all known directories to help distinguish between file\n\t// and directory deletion events.\n\tknownDirs map[string]struct{}\n}\n\n// New creates a new file watcher and starts its event-handling loop. The\n// [Watcher.Close] method must be called to clean up resources.\n//\n// The provided event handler is called sequentially with a batch of file events,\n// but the error handler is called concurrently. The watcher blocks until the\n// handler returns, so the handlers should be fast and non-blocking.\nfunc NewFSNotifyWatcher(delay time.Duration, logger *slog.Logger, eventsHandler func([]protocol.FileEvent), errHandler func(error)) (Watcher, error) {\n\twatcher, err := fsnotify.NewWatcher()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tw := &fsnotifyWatcher{\n\t\tlogger:    logger,\n\t\twatcher:   watcher,\n\t\tknownDirs: make(map[string]struct{}),\n\t\tstop:      make(chan struct{}),\n\t\tready:     make(chan struct{}, 1),\n\t}\n\n\tw.wg.Add(1)\n\tgo w.run(eventsHandler, errHandler, delay)\n\n\tw.wg.Add(1)\n\tgo w.process(errHandler)\n\n\treturn w, nil\n}\n\n// run is the receiver and sender loop.\n//\n// As receiver, its primary responsibility is to drain events and errors from\n// the fsnotify watcher as quickly as possible and enqueue events for processing\n// by the process goroutine. This is critical to work around a potential\n// fsnotify deadlock (see fsnotify/fsnotify#502).\n//\n// As sender, it manages a timer and flush events to the handler if there is\n// no events captured for a period of time.\nfunc (w *fsnotifyWatcher) run(eventsHandler func([]protocol.FileEvent), errHandler func(error), delay time.Duration) {\n\tdefer w.wg.Done()\n\n\ttimer := time.NewTimer(delay)\n\tdefer timer.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-w.stop:\n\t\t\treturn\n\n\t\tcase <-timer.C:\n\t\t\t// TODO(hxjiang): flush is triggered when there is no events captured\n\t\t\t// in a certain period of time, it may be better to flush it when the\n\t\t\t// w.in is completely empty.\n\t\t\t//\n\t\t\t// Currently, partial events may be emitted if a directory watch gets\n\t\t\t// stuck. While this does not affect correctness, it means events\n\t\t\t// might be sent to the client in multiple portions rather than a\n\t\t\t// single batch.\n\t\t\tw.mu.Lock()\n\t\t\tevents := w.out\n\t\t\tw.out = nil\n\t\t\tw.mu.Unlock()\n\n\t\t\tif len(events) > 0 {\n\t\t\t\teventsHandler(events)\n\t\t\t}\n\n\t\t\ttimer.Reset(delay)\n\n\t\tcase event, ok := <-w.watcher.Events:\n\t\t\t// The watcher closed. Continue the loop and let the <-w.stop case\n\t\t\t// handle the actual shutdown.\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// TODO(hxjiang): perform some filtering before we reset the timer\n\t\t\t// to avoid consistently resetting the timer in a noisy file system,\n\t\t\t// or simply convert the event here.\n\t\t\ttimer.Reset(delay)\n\n\t\t\tw.mu.Lock()\n\t\t\tw.in = append(w.in, event)\n\t\t\tw.mu.Unlock()\n\n\t\t\tw.signal()\n\n\t\tcase err, ok := <-w.watcher.Errors:\n\t\t\t// The watcher closed. Continue the loop and let the <-w.stop case\n\t\t\t// handle the actual shutdown.\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\terrHandler(err)\n\t\t}\n\t}\n}\n\n// process is a worker goroutine that converts raw fsnotify events from queue\n// and handles the potentially blocking work of watching new directories. It is\n// the counterpart to the run goroutine.\nfunc (w *fsnotifyWatcher) process(errHandler func(error)) {\n\tdefer w.wg.Done()\n\n\tfor {\n\t\tselect {\n\t\tcase <-w.stop:\n\t\t\treturn\n\n\t\tcase <-w.ready:\n\t\t\tw.mu.Lock()\n\t\t\tevents := w.in\n\t\t\tw.in = nil\n\t\t\tw.mu.Unlock()\n\n\t\t\tfor _, event := range events {\n\t\t\t\t// File watcher is closing, drop any remaining work.\n\t\t\t\tselect {\n\t\t\t\tcase <-w.stop:\n\t\t\t\t\treturn\n\t\t\t\tdefault:\n\t\t\t\t}\n\n\t\t\t\t// fsnotify does not guarantee clean filepaths.\n\t\t\t\tevent.Name = filepath.Clean(event.Name)\n\n\t\t\t\t// fsnotify.Event should not be handled concurrently, to preserve their\n\t\t\t\t// original order. For example, if a file is deleted and recreated,\n\t\t\t\t// concurrent handling could process the events in reverse order.\n\t\t\t\te, isDir := w.convertEvent(event)\n\t\t\t\tif e == (protocol.FileEvent{}) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tvar synthesized []protocol.FileEvent // synthesized create events\n\n\t\t\t\tif isDir {\n\t\t\t\t\tswitch e.Type {\n\t\t\t\t\tcase protocol.Created:\n\t\t\t\t\t\t// Walks the entire directory tree, synthesizes create\n\t\t\t\t\t\t// events for its contents, and establishes watches for\n\t\t\t\t\t\t// subdirectories. This recursive, pre-order traversal\n\t\t\t\t\t\t// guarantees a logical event sequence: parent directory\n\t\t\t\t\t\t// creation events always precede those of their children.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// For example, consider a creation event for directory\n\t\t\t\t\t\t// a, and suppose a has contents [a/b, a/b/c, a/c, a/c/d].\n\t\t\t\t\t\t// The effective events will be:\n\t\t\t\t\t\t//\n\t\t\t\t\t\t//     CREATE a\n\t\t\t\t\t\t//     CREATE a/b\n\t\t\t\t\t\t//     CREATE a/b/c\n\t\t\t\t\t\t//     CREATE a/c\n\t\t\t\t\t\t//     CREATE a/c/d\n\t\t\t\t\t\tw.walkDirWithRetry(event.Name, errHandler, func(path string, isDir bool) error {\n\t\t\t\t\t\t\tif path != event.Name {\n\t\t\t\t\t\t\t\tsynthesized = append(synthesized, protocol.FileEvent{\n\t\t\t\t\t\t\t\t\tURI:  protocol.URIFromPath(path),\n\t\t\t\t\t\t\t\t\tType: protocol.Created,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif isDir {\n\t\t\t\t\t\t\t\treturn w.watchDir(path)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn nil\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\tcase protocol.Deleted:\n\t\t\t\t\t\t// Upon removal, we only need to remove the entries from\n\t\t\t\t\t\t// the map. The [fsnotify.Watcher] removes the watch for\n\t\t\t\t\t\t// us. fsnotify/fsnotify#268\n\t\t\t\t\t\tw.mu.Lock()\n\t\t\t\t\t\tdelete(w.knownDirs, event.Name)\n\t\t\t\t\t\tw.mu.Unlock()\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// convertEvent enforces that dirs are only Created or Deleted.\n\t\t\t\t\t\tpanic(\"impossible\")\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Discovered events must be appended to the 'out' slice atomically.\n\t\t\t\t// This ensures that at any point, the slice contains a logically\n\t\t\t\t// correct (maybe slightly outdated) batch of file events that is\n\t\t\t\t// ready to be flushed.\n\t\t\t\tw.mu.Lock()\n\t\t\t\t// Some systems emit duplicate change events in close\n\t\t\t\t// succession upon file modification. While the current\n\t\t\t\t// deduplication is naive and only handles immediate duplicates,\n\t\t\t\t// a more robust solution is needed.\n\t\t\t\t// https://github.com/fsnotify/fsnotify?tab=readme-ov-file#why-do-i-get-many-chmod-events\n\t\t\t\t//\n\t\t\t\t// TODO(hxjiang): Enhance deduplication. The current batching of\n\t\t\t\t// events means all duplicates, regardless of proximity, should\n\t\t\t\t// be removed. Consider checking the entire buffered slice or\n\t\t\t\t// using a map for this.\n\t\t\t\tif len(w.out) == 0 || w.out[len(w.out)-1] != e {\n\t\t\t\t\tw.out = append(w.out, e)\n\t\t\t\t}\n\t\t\t\tw.out = append(w.out, synthesized...) // synthesized events are guaranteed to be unique\n\t\t\t\tw.mu.Unlock()\n\t\t\t}\n\t\t}\n\t}\n}\n\n// signal notifies the process goroutine that events are added to the queue and\n// ready for handling.\nfunc (w *fsnotifyWatcher) signal() {\n\tselect {\n\tcase w.ready <- struct{}{}:\n\tdefault:\n\t}\n}\n\n// skipDir reports whether the input dir should be skipped.\n// Directories that are unlikely to contain Go source files relevant for\n// analysis, such as .git directories or testdata, should be skipped to\n// avoid unnecessary file system notifications. This reduces noise and\n// improves efficiency. Conversely, any directory that might contain Go\n// source code should be watched to ensure that gopls can respond to\n// file changes.\nfunc skipDir(dirName string) bool {\n\t// TODO(hxjiang): the file watcher should honor gopls directory\n\t// filter or the new go.mod ignore directive, or actively listening\n\t// to gopls register capability request with method\n\t// \"workspace/didChangeWatchedFiles\" like a real LSP client.\n\treturn strings.HasPrefix(dirName, \".\") || strings.HasPrefix(dirName, \"_\") || dirName == \"testdata\"\n}\n\n// skipFile reports whether the file should be skipped.\nfunc skipFile(fileName string) bool {\n\tswitch strings.TrimPrefix(filepath.Ext(fileName), \".\") {\n\tcase \"go\", \"mod\", \"sum\", \"work\", \"s\":\n\t\treturn false\n\tdefault:\n\t\treturn true\n\t}\n}\n\n// WatchDir walks through the directory and all its subdirectories, adding\n// them to the watcher.\nfunc (w *fsnotifyWatcher) WatchDir(path string) error {\n\tlog.Printf(\"Watching %s\", path)\n\treturn filepath.WalkDir(filepath.Clean(path), func(path string, d fs.DirEntry, err error) error {\n\t\tif d.IsDir() {\n\t\t\tif skipDir(d.Name()) {\n\t\t\t\treturn filepath.SkipDir\n\t\t\t}\n\n\t\t\treturn w.watchDir(path)\n\t\t}\n\t\treturn nil\n\t})\n}\n\n// convertEvent translates an [fsnotify.Event] into a [protocol.FileEvent].\n// It returns the translated event and a boolean indicating if the path was a\n// directory. For directories, the event Type is either Created or Deleted.\n// It returns empty event for events that should be ignored.\nfunc (w *fsnotifyWatcher) convertEvent(event fsnotify.Event) (_ protocol.FileEvent, isDir bool) {\n\t// Determine if the event is for a directory.\n\tif info, err := os.Stat(event.Name); err == nil {\n\t\tisDir = info.IsDir()\n\t} else if os.IsNotExist(err) {\n\t\t// Upon deletion, the file/dir has been removed. fsnotify does not\n\t\t// provide information regarding the deleted item.\n\t\t// Use the set of known directories to determine if the deleted item was a directory.\n\t\tisDir = w.isWatchedDir(event.Name)\n\t} else {\n\t\t// If statting failed, something is wrong with the file system.\n\t\t// Log and move on.\n\t\tif w.logger != nil {\n\t\t\tw.logger.Error(\"failed to stat path, skipping event as its type (file/dir) is unknown\", \"path\", event.Name, \"err\", err)\n\t\t}\n\t\treturn protocol.FileEvent{}, false\n\t}\n\n\t// Filter out events for directories and files that are not of interest.\n\tif isDir && skipDir(filepath.Base(event.Name)) {\n\t\treturn protocol.FileEvent{}, true\n\t}\n\tif !isDir && skipFile(filepath.Base(event.Name)) {\n\t\treturn protocol.FileEvent{}, false\n\t}\n\n\tvar t protocol.FileChangeType\n\tswitch {\n\tcase event.Op.Has(fsnotify.Rename):\n\t\t// A rename is treated as a deletion of the old path because the\n\t\t// fsnotify RENAME event doesn't include the new path. A separate\n\t\t// CREATE event will be sent for the new path if the destination\n\t\t// directory is watched.\n\t\tfallthrough\n\tcase event.Op.Has(fsnotify.Remove):\n\t\t// TODO(hxjiang): Directory removal events from some LSP clients may\n\t\t// not include corresponding removal events for child files and\n\t\t// subdirectories. Should we do some filtering when adding the dir\n\t\t// deletion event to the events slice.\n\t\tt = protocol.Deleted\n\tcase event.Op.Has(fsnotify.Create):\n\t\tt = protocol.Created\n\tcase event.Op.Has(fsnotify.Write):\n\t\tif isDir {\n\t\t\treturn protocol.FileEvent{}, isDir // ignore dir write events\n\t\t}\n\t\tt = protocol.Changed\n\tdefault:\n\t\treturn protocol.FileEvent{}, isDir // ignore the rest of the events\n\t}\n\n\treturn protocol.FileEvent{\n\t\tURI:  protocol.URIFromPath(event.Name),\n\t\tType: t,\n\t}, isDir\n}\n\n// watchDir registers a watch for a directory, retrying with backoff if it fails.\n//\n// Returns nil on success or watcher closing; otherwise, the last error after\n// all retries.\nfunc (w *fsnotifyWatcher) watchDir(path string) error {\n\tw.mu.Lock()\n\tw.knownDirs[path] = struct{}{}\n\tw.mu.Unlock()\n\n\t// On darwin, watching a directory will fail if it contains broken symbolic\n\t// links. This state can occur temporarily during operations like a git\n\t// branch switch. To handle this, we retry multiple times with exponential\n\t// backoff, allowing time for the symbolic link's target to be created.\n\tvar (\n\t\tdelay = 500 * time.Millisecond\n\t\terr   error\n\t)\n\n\tfor i := range 5 {\n\t\tif i > 0 {\n\t\t\tselect {\n\t\t\tcase <-time.After(delay):\n\t\t\t\tdelay *= 2\n\t\t\tcase <-w.stop:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\t// This function may block due to fsnotify/fsnotify#502.\n\t\terr = w.watcher.Add(path)\n\t\tif afterAddHook != nil {\n\t\t\tafterAddHook(path, err)\n\t\t}\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn err\n}\n\nvar afterAddHook func(path string, err error)\n\n// isWatchedDir reports whether the given path is a known directory that\n// the watcher is managing.\nfunc (w *fsnotifyWatcher) isWatchedDir(path string) bool {\n\tw.mu.Lock()\n\tdefer w.mu.Unlock()\n\n\t_, isDir := w.knownDirs[path]\n\treturn isDir\n}\n\n// Poke is a no-op for fsnotify watcher, as it relies on OS events.\nfunc (w *fsnotifyWatcher) Poke() {}\n\n// Close shuts down the watcher, waits for the internal goroutine to terminate,\n// and returns any final error.\nfunc (w *fsnotifyWatcher) Close() error {\n\t// Wait for fsnotify' watcher to terminate.\n\terr := w.watcher.Close()\n\n\t// Wait for run and process loop to terminate. It's important to stop the\n\t// run and process loop the last place because we don't know whether\n\t// fsnotify's watcher expect us to keep consuming events or errors from\n\t// [fsnotify.Watcher.Events] and [fsnotify.Watcher.Errors] while it's being\n\t// closed.\n\t// To avoid any potential deadlock, have the channel receiver running until\n\t// the last minute.\n\tclose(w.stop)\n\tw.wg.Wait()\n\n\treturn err\n}\n\n// walkDir calls fn against current path and recursively descends path for each\n// file or directory of our interest.\nfunc (w *fsnotifyWatcher) walkDir(path string, isDir bool, errHandler func(error), fn func(path string, isDir bool) error) {\n\tif err := fn(path, isDir); err != nil {\n\t\terrHandler(err)\n\t\treturn\n\t}\n\n\tif !isDir {\n\t\treturn\n\t}\n\n\tentries, err := tryFSOperation(w.stop, func() ([]fs.DirEntry, error) {\n\t\t// ReadDir may fail due because other processes may be actively\n\t\t// modifying the watched dir see golang/go#74820.\n\t\t// TODO(hxjiang): consider adding robustio.ReadDir.\n\t\treturn os.ReadDir(path)\n\t})\n\tif err != nil {\n\t\tif err != ErrClosed {\n\t\t\terrHandler(err)\n\t\t}\n\t\treturn\n\t}\n\n\tfor _, e := range entries {\n\t\tif e.IsDir() && skipDir(e.Name()) {\n\t\t\tcontinue\n\t\t}\n\t\tif !e.IsDir() && skipFile(e.Name()) {\n\t\t\tcontinue\n\t\t}\n\n\t\tw.walkDir(filepath.Join(path, e.Name()), e.IsDir(), errHandler, fn)\n\t}\n}\n\n// walkDirWithRetry walks the file tree rooted at root, calling fn for each\n// file or directory of our interest in the tree, including root.\n//\n// All errors that arise visiting directories or files will be reported to the\n// provided error handler function. If an error is encountered visiting a\n// directory, that entire subtree will be skipped.\n//\n// walkDirWithRetry does not follow symbolic links.\n//\n// It is used instead of [filepath.WalkDir] because it provides control over\n// retry behavior when reading a directory fails. If [os.ReadDir] fails with an\n// ephemeral error, it is retried multiple times with exponential backoff.\n//\n// TODO(hxjiang): call walkDirWithRetry in WalkDir.\nfunc (w *fsnotifyWatcher) walkDirWithRetry(root string, errHandler func(error), fn func(path string, isDir bool) error) {\n\tinfo, err := tryFSOperation(w.stop, func() (os.FileInfo, error) {\n\t\treturn os.Lstat(root) // [os.Lstat] does not follow symlink.\n\t})\n\tif err != nil {\n\t\tif err != ErrClosed {\n\t\t\terrHandler(err)\n\t\t}\n\t\treturn\n\t}\n\n\tw.walkDir(root, info.IsDir(), errHandler, fn)\n}\n\n// tryFSOperation executes a function `op` with retry logic, making it resilient\n// to transient errors. It attempts the operation up to 5 times with exponential\n// backoff. Retries occur only if the error is ephemeral.\n//\n// The operation can be interrupted by closing the `stop` channel, in which case\n// it returns [ErrClosed].\nfunc tryFSOperation[Result any](stop <-chan struct{}, op func() (Result, error)) (Result, error) {\n\tvar (\n\t\tdelay = 50 * time.Millisecond\n\t\terr   error\n\t)\n\n\tfor i := range 5 {\n\t\tif i > 0 {\n\t\t\tselect {\n\t\t\tcase <-time.After(delay):\n\t\t\t\tdelay *= 2\n\t\t\tcase <-stop:\n\t\t\t\tvar zero Result\n\t\t\t\treturn zero, ErrClosed\n\t\t\t}\n\t\t}\n\n\t\tvar res Result\n\t\tres, err = op()\n\n\t\tif robustio.IsEphemeralError(err) {\n\t\t\tcontinue\n\t\t} else {\n\t\t\treturn res, err\n\t\t}\n\t}\n\n\tvar zero Result\n\treturn zero, err // return last error encountered\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/input.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fuzzy\n\nimport (\n\t\"unicode\"\n)\n\n// RuneRole specifies the role of a rune in the context of an input.\ntype RuneRole byte\n\nconst (\n\t// RNone specifies a rune without any role in the input (i.e., whitespace/non-ASCII).\n\tRNone RuneRole = iota\n\t// RSep specifies a rune with the role of segment separator.\n\tRSep\n\t// RTail specifies a rune which is a lower-case tail in a word in the input.\n\tRTail\n\t// RUCTail specifies a rune which is an upper-case tail in a word in the input.\n\tRUCTail\n\t// RHead specifies a rune which is the first character in a word in the input.\n\tRHead\n)\n\n// RuneRoles detects the roles of each byte rune in an input string and stores it in the output\n// slice. The rune role depends on the input type. Stops when it parsed all the runes in the string\n// or when it filled the output. If output is nil, then it gets created.\nfunc RuneRoles(candidate []byte, reuse []RuneRole) []RuneRole {\n\tvar output []RuneRole\n\tif cap(reuse) < len(candidate) {\n\t\toutput = make([]RuneRole, 0, len(candidate))\n\t} else {\n\t\toutput = reuse[:0]\n\t}\n\n\tprev, prev2 := rtNone, rtNone\n\tfor i := range candidate {\n\t\tr := rune(candidate[i])\n\n\t\trole := RNone\n\n\t\tcurr := rtLower\n\t\tif candidate[i] <= unicode.MaxASCII {\n\t\t\tcurr = runeType(rt[candidate[i]] - '0')\n\t\t}\n\n\t\tif curr == rtLower {\n\t\t\tif prev == rtNone || prev == rtPunct {\n\t\t\t\trole = RHead\n\t\t\t} else {\n\t\t\t\trole = RTail\n\t\t\t}\n\t\t} else if curr == rtUpper {\n\t\t\trole = RHead\n\n\t\t\tif prev == rtUpper {\n\t\t\t\t// This and previous characters are both upper case.\n\n\t\t\t\tif i+1 == len(candidate) {\n\t\t\t\t\t// This is last character, previous was also uppercase -> this is UCTail\n\t\t\t\t\t// i.e., (current char is C): aBC / BC / ABC\n\t\t\t\t\trole = RUCTail\n\t\t\t\t}\n\t\t\t}\n\t\t} else if curr == rtPunct {\n\t\t\tswitch r {\n\t\t\tcase '.', ':':\n\t\t\t\trole = RSep\n\t\t\t}\n\t\t}\n\t\tif curr != rtLower {\n\t\t\tif i > 1 && output[i-1] == RHead && prev2 == rtUpper && (output[i-2] == RHead || output[i-2] == RUCTail) {\n\t\t\t\t// The previous two characters were uppercase. The current one is not a lower case, so the\n\t\t\t\t// previous one can't be a HEAD. Make it a UCTail.\n\t\t\t\t// i.e., (last char is current char - B must be a UCTail): ABC / ZABC / AB.\n\t\t\t\toutput[i-1] = RUCTail\n\t\t\t}\n\t\t}\n\n\t\toutput = append(output, role)\n\t\tprev2 = prev\n\t\tprev = curr\n\t}\n\treturn output\n}\n\ntype runeType byte\n\nconst (\n\trtNone runeType = iota\n\trtPunct\n\trtLower\n\trtUpper\n)\n\nconst rt = \"00000000000000000000000000000000000000000000001122222222221000000333333333333333333333333330000002222222222222222222222222200000\"\n\n// LastSegment returns the substring representing the last segment from the input, where each\n// byte has an associated RuneRole in the roles slice. This makes sense only for inputs of Symbol\n// or Filename type.\nfunc LastSegment(input string, roles []RuneRole) string {\n\t// Exclude ending separators.\n\tend := len(input) - 1\n\tfor end >= 0 && roles[end] == RSep {\n\t\tend--\n\t}\n\tif end < 0 {\n\t\treturn \"\"\n\t}\n\n\tstart := end - 1\n\tfor start >= 0 && roles[start] != RSep {\n\t\tstart--\n\t}\n\n\treturn input[start+1 : end+1]\n}\n\n// fromChunks copies string chunks into the given buffer.\nfunc fromChunks(chunks []string, buffer []byte) []byte {\n\tii := 0\n\tfor _, chunk := range chunks {\n\t\tfor i := range len(chunk) {\n\t\t\tif ii >= cap(buffer) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tbuffer[ii] = chunk[i]\n\t\t\tii++\n\t\t}\n\t}\n\treturn buffer[:ii]\n}\n\n// toLower transforms the input string to lower case, which is stored in the output byte slice.\n// The lower casing considers only ASCII values - non ASCII values are left unmodified.\n// Stops when parsed all input or when it filled the output slice. If output is nil, then it gets\n// created.\nfunc toLower(input []byte, reuse []byte) []byte {\n\toutput := reuse\n\tif cap(reuse) < len(input) {\n\t\toutput = make([]byte, len(input))\n\t}\n\n\tfor i := range input {\n\t\tr := rune(input[i])\n\t\tif input[i] <= unicode.MaxASCII {\n\t\t\tif 'A' <= r && r <= 'Z' {\n\t\t\t\tr += 'a' - 'A'\n\t\t\t}\n\t\t}\n\t\toutput[i] = byte(r)\n\t}\n\treturn output[:len(input)]\n}\n\n// WordConsumer defines a consumer for a word delimited by the [start,end) byte offsets in an input\n// (start is inclusive, end is exclusive).\ntype WordConsumer func(start, end int)\n\n// Words find word delimiters in an input based on its bytes' mappings to rune roles. The offset\n// delimiters for each word are fed to the provided consumer function.\nfunc Words(roles []RuneRole, consume WordConsumer) {\n\tvar wordStart int\n\tfor i, r := range roles {\n\t\tswitch r {\n\t\tcase RUCTail, RTail:\n\t\tcase RHead, RNone, RSep:\n\t\t\tif i != wordStart {\n\t\t\t\tconsume(wordStart, i)\n\t\t\t}\n\t\t\twordStart = i\n\t\t\tif r != RHead {\n\t\t\t\t// Skip this character.\n\t\t\t\twordStart = i + 1\n\t\t\t}\n\t\t}\n\t}\n\tif wordStart != len(roles) {\n\t\tconsume(wordStart, len(roles))\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/input_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fuzzy_test\n\nimport (\n\t\"bytes\"\n\t\"slices\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n)\n\nvar rolesTests = []struct {\n\tstr  string\n\twant string\n}{\n\t{str: \"abc::def::goo\", want: \"Ccc//Ccc//Ccc\"},\n\t{str: \"proto::Message\", want: \"Ccccc//Ccccccc\"},\n\t{str: \"AbstractSWTFactory\", want: \"CcccccccCuuCcccccc\"},\n\t{str: \"Abs012\", want: \"Cccccc\"},\n\t{str: \"/\", want: \" \"},\n\t{str: \"fOO\", want: \"CCu\"},\n\t{str: \"fo_oo.o_oo\", want: \"Cc Cc/C Cc\"},\n}\n\nfunc rolesString(roles []fuzzy.RuneRole) string {\n\tvar buf bytes.Buffer\n\tfor _, r := range roles {\n\t\tbuf.WriteByte(\" /cuC\"[int(r)])\n\t}\n\treturn buf.String()\n}\n\nfunc TestRoles(t *testing.T) {\n\tfor _, tc := range rolesTests {\n\t\tgotRoles := make([]fuzzy.RuneRole, len(tc.str))\n\t\tfuzzy.RuneRoles([]byte(tc.str), gotRoles)\n\t\tgot := rolesString(gotRoles)\n\t\tif got != tc.want {\n\t\t\tt.Errorf(\"roles(%s) = %v; want %v\", tc.str, got, tc.want)\n\t\t}\n\t}\n}\n\nvar wordSplitTests = []struct {\n\tinput string\n\twant  []string\n}{\n\t{\n\t\tinput: \"foo bar baz\",\n\t\twant:  []string{\"foo\", \"bar\", \"baz\"},\n\t},\n\t{\n\t\tinput: \"fooBarBaz\",\n\t\twant:  []string{\"foo\", \"Bar\", \"Baz\"},\n\t},\n\t{\n\t\tinput: \"FOOBarBAZ\",\n\t\twant:  []string{\"FOO\", \"Bar\", \"BAZ\"},\n\t},\n\t{\n\t\tinput: \"foo123_bar2Baz3\",\n\t\twant:  []string{\"foo123\", \"bar2\", \"Baz3\"},\n\t},\n}\n\nfunc TestWordSplit(t *testing.T) {\n\tfor _, tc := range wordSplitTests {\n\t\troles := fuzzy.RuneRoles([]byte(tc.input), nil)\n\n\t\tvar got []string\n\t\tconsumer := func(i, j int) {\n\t\t\tgot = append(got, tc.input[i:j])\n\t\t}\n\t\tfuzzy.Words(roles, consumer)\n\n\t\tif eq := diffStringLists(tc.want, got); !eq {\n\t\t\tt.Errorf(\"input %v: (want %v -> got %v)\", tc.input, tc.want, got)\n\t\t}\n\t}\n}\n\nfunc diffStringLists(a, b []string) bool {\n\tsort.Strings(a)\n\tsort.Strings(b)\n\treturn slices.Equal(a, b)\n}\n\nvar lastSegmentSplitTests = []struct {\n\tstr  string\n\twant string\n}{\n\t{\n\t\tstr:  \"identifier\",\n\t\twant: \"identifier\",\n\t},\n\t{\n\t\tstr:  \"two_words\",\n\t\twant: \"two_words\",\n\t},\n\t{\n\t\tstr:  \"first::second\",\n\t\twant: \"second\",\n\t},\n\t{\n\t\tstr:  \"foo.bar.FOOBar_buz123_test\",\n\t\twant: \"FOOBar_buz123_test\",\n\t},\n}\n\nfunc TestLastSegment(t *testing.T) {\n\tfor _, tc := range lastSegmentSplitTests {\n\t\troles := fuzzy.RuneRoles([]byte(tc.str), nil)\n\n\t\tgot := fuzzy.LastSegment(tc.str, roles)\n\n\t\tif got != tc.want {\n\t\t\tt.Errorf(\"str %v: want %v; got %v\", tc.str, tc.want, got)\n\t\t}\n\t}\n}\n\nfunc BenchmarkRoles(b *testing.B) {\n\tstr := \"AbstractSWTFactory\"\n\tout := make([]fuzzy.RuneRole, len(str))\n\n\tfor b.Loop() {\n\t\tfuzzy.RuneRoles([]byte(str), out)\n\t}\n\tb.SetBytes(int64(len(str)))\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/matcher.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fuzzy implements a fuzzy matching algorithm.\npackage fuzzy\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nconst (\n\t// MaxInputSize is the maximum size of the input scored against the fuzzy matcher. Longer inputs\n\t// will be truncated to this size.\n\tMaxInputSize = 127\n\t// MaxPatternSize is the maximum size of the pattern used to construct the fuzzy matcher. Longer\n\t// inputs are truncated to this size.\n\tMaxPatternSize = 63\n)\n\ntype scoreVal int\n\nfunc (s scoreVal) val() int {\n\treturn int(s) >> 1\n}\n\nfunc (s scoreVal) prevK() int {\n\treturn int(s) & 1\n}\n\nfunc score(val int, prevK int /*0 or 1*/) scoreVal {\n\treturn scoreVal(val<<1 + prevK)\n}\n\n// Matcher implements a fuzzy matching algorithm for scoring candidates against a pattern.\n// The matcher does not support parallel usage.\ntype Matcher struct {\n\tpattern       string\n\tpatternLower  []byte // lower-case version of the pattern\n\tpatternShort  []byte // first characters of the pattern\n\tcaseSensitive bool   // set if the pattern is mix-cased\n\n\tpatternRoles []RuneRole // the role of each character in the pattern\n\troles        []RuneRole // the role of each character in the tested string\n\n\tscores [MaxInputSize + 1][MaxPatternSize + 1][2]scoreVal\n\n\tscoreScale float32\n\n\tlastCandidateLen     int // in bytes\n\tlastCandidateMatched bool\n\n\t// Reusable buffers to avoid allocating for every candidate.\n\t//  - inputBuf stores the concatenated input chunks\n\t//  - lowerBuf stores the last candidate in lower-case\n\t//  - rolesBuf stores the calculated roles for each rune in the last\n\t//    candidate.\n\tinputBuf [MaxInputSize]byte\n\tlowerBuf [MaxInputSize]byte\n\trolesBuf [MaxInputSize]RuneRole\n}\n\nfunc (m *Matcher) String() string { return m.pattern }\n\nfunc (m *Matcher) bestK(i, j int) int {\n\tif m.scores[i][j][0].val() < m.scores[i][j][1].val() {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n// NewMatcher returns a new fuzzy matcher for scoring candidates against the provided pattern.\nfunc NewMatcher(pattern string) *Matcher {\n\tif len(pattern) > MaxPatternSize {\n\t\tpattern = pattern[:MaxPatternSize]\n\t}\n\n\tm := &Matcher{\n\t\tpattern:      pattern,\n\t\tpatternLower: toLower([]byte(pattern), nil),\n\t}\n\n\tfor i, c := range m.patternLower {\n\t\tif pattern[i] != c {\n\t\t\tm.caseSensitive = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif len(pattern) > 3 {\n\t\tm.patternShort = m.patternLower[:3]\n\t} else {\n\t\tm.patternShort = m.patternLower\n\t}\n\n\tm.patternRoles = RuneRoles([]byte(pattern), nil)\n\n\tif len(pattern) > 0 {\n\t\tmaxCharScore := 4\n\t\tm.scoreScale = 1 / float32(maxCharScore*len(pattern))\n\t}\n\n\treturn m\n}\n\n// Score returns the score returned by matching the candidate to the pattern.\n// This is not designed for parallel use. Multiple candidates must be scored sequentially.\n// Returns a score between 0 and 1 (0 - no match, 1 - perfect match).\nfunc (m *Matcher) Score(candidate string) float32 {\n\treturn m.ScoreChunks([]string{candidate})\n}\n\nfunc (m *Matcher) ScoreChunks(chunks []string) float32 {\n\tcandidate := fromChunks(chunks, m.inputBuf[:])\n\tif len(candidate) > MaxInputSize {\n\t\tcandidate = candidate[:MaxInputSize]\n\t}\n\tlower := toLower(candidate, m.lowerBuf[:])\n\tm.lastCandidateLen = len(candidate)\n\n\tif len(m.pattern) == 0 {\n\t\t// Empty patterns perfectly match candidates.\n\t\treturn 1\n\t}\n\n\tif m.match(candidate, lower) {\n\t\tsc := m.computeScore(candidate, lower)\n\t\tif sc > minScore/2 && !m.poorMatch() {\n\t\t\tm.lastCandidateMatched = true\n\t\t\tif len(m.pattern) == len(candidate) {\n\t\t\t\t// Perfect match.\n\t\t\t\treturn 1\n\t\t\t}\n\n\t\t\tif sc < 0 {\n\t\t\t\tsc = 0\n\t\t\t}\n\t\t\tnormalizedScore := min(float32(sc)*m.scoreScale, 1)\n\n\t\t\treturn normalizedScore\n\t\t}\n\t}\n\n\tm.lastCandidateMatched = false\n\treturn 0\n}\n\nconst minScore = -10000\n\n// MatchedRanges returns matches ranges for the last scored string as a flattened array of\n// [begin, end) byte offset pairs.\nfunc (m *Matcher) MatchedRanges() []int {\n\tif len(m.pattern) == 0 || !m.lastCandidateMatched {\n\t\treturn nil\n\t}\n\ti, j := m.lastCandidateLen, len(m.pattern)\n\tif m.scores[i][j][0].val() < minScore/2 && m.scores[i][j][1].val() < minScore/2 {\n\t\treturn nil\n\t}\n\n\tvar ret []int\n\tk := m.bestK(i, j)\n\tfor i > 0 {\n\t\ttake := (k == 1)\n\t\tk = m.scores[i][j][k].prevK()\n\t\tif take {\n\t\t\tif len(ret) == 0 || ret[len(ret)-1] != i {\n\t\t\t\tret = append(ret, i)\n\t\t\t\tret = append(ret, i-1)\n\t\t\t} else {\n\t\t\t\tret[len(ret)-1] = i - 1\n\t\t\t}\n\t\t\tj--\n\t\t}\n\t\ti--\n\t}\n\t// Reverse slice.\n\tfor i := range len(ret) / 2 {\n\t\tret[i], ret[len(ret)-1-i] = ret[len(ret)-1-i], ret[i]\n\t}\n\treturn ret\n}\n\nfunc (m *Matcher) match(candidate []byte, candidateLower []byte) bool {\n\ti, j := 0, 0\n\tfor ; i < len(candidateLower) && j < len(m.patternLower); i++ {\n\t\tif candidateLower[i] == m.patternLower[j] {\n\t\t\tj++\n\t\t}\n\t}\n\tif j != len(m.patternLower) {\n\t\treturn false\n\t}\n\n\t// The input passes the simple test against pattern, so it is time to classify its characters.\n\t// Character roles are used below to find the last segment.\n\tm.roles = RuneRoles(candidate, m.rolesBuf[:])\n\n\treturn true\n}\n\nfunc (m *Matcher) computeScore(candidate []byte, candidateLower []byte) int {\n\tpattLen, candLen := len(m.pattern), len(candidate)\n\n\tfor j := 0; j <= len(m.pattern); j++ {\n\t\tm.scores[0][j][0] = minScore << 1\n\t\tm.scores[0][j][1] = minScore << 1\n\t}\n\tm.scores[0][0][0] = score(0, 0) // Start with 0.\n\n\tsegmentsLeft, lastSegStart := 1, 0\n\tfor i := range candLen {\n\t\tif m.roles[i] == RSep {\n\t\t\tsegmentsLeft++\n\t\t\tlastSegStart = i + 1\n\t\t}\n\t}\n\n\t// A per-character bonus for a consecutive match.\n\tconsecutiveBonus := 2\n\twordIdx := 0 // Word count within segment.\n\tfor i := 1; i <= candLen; i++ {\n\n\t\trole := m.roles[i-1]\n\t\tisHead := role == RHead\n\n\t\tif isHead {\n\t\t\twordIdx++\n\t\t} else if role == RSep && segmentsLeft > 1 {\n\t\t\twordIdx = 0\n\t\t\tsegmentsLeft--\n\t\t}\n\n\t\tvar skipPenalty int\n\t\tif i == 1 || (i-1) == lastSegStart {\n\t\t\t// Skipping the start of first or last segment.\n\t\t\tskipPenalty++\n\t\t}\n\n\t\tfor j := 0; j <= pattLen; j++ {\n\t\t\t// By default, we don't have a match. Fill in the skip data.\n\t\t\tm.scores[i][j][1] = minScore << 1\n\n\t\t\t// Compute the skip score.\n\t\t\tk := 0\n\t\t\tif m.scores[i-1][j][0].val() < m.scores[i-1][j][1].val() {\n\t\t\t\tk = 1\n\t\t\t}\n\n\t\t\tskipScore := m.scores[i-1][j][k].val()\n\t\t\t// Do not penalize missing characters after the last matched segment.\n\t\t\tif j != pattLen {\n\t\t\t\tskipScore -= skipPenalty\n\t\t\t}\n\t\t\tm.scores[i][j][0] = score(skipScore, k)\n\n\t\t\tif j == 0 || candidateLower[i-1] != m.patternLower[j-1] {\n\t\t\t\t// Not a match.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpRole := m.patternRoles[j-1]\n\n\t\t\tif role == RTail && pRole == RHead {\n\t\t\t\tif j > 1 {\n\t\t\t\t\t// Not a match: a head in the pattern matches a tail character in the candidate.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Special treatment for the first character of the pattern. We allow\n\t\t\t\t// matches in the middle of a word if they are long enough, at least\n\t\t\t\t// min(3, pattern.length) characters.\n\t\t\t\tif !bytes.HasPrefix(candidateLower[i-1:], m.patternShort) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compute the char score.\n\t\t\tvar charScore int\n\t\t\t// Bonus: the char is in the candidate's last segment.\n\t\t\tif segmentsLeft <= 1 {\n\t\t\t\tcharScore++\n\t\t\t}\n\n\t\t\t// Bonus: exact case match between pattern and candidate.\n\t\t\tif candidate[i-1] == m.pattern[j-1] ||\n\t\t\t\t// Bonus: candidate char is a head and pattern is all\n\t\t\t\t// lowercase. There is no segmentation in an all lowercase\n\t\t\t\t// pattern, so assume any char in pattern can be a head. Note\n\t\t\t\t// that we are intentionally _not_ giving a bonus to a case\n\t\t\t\t// insensitive match when the pattern is case sensitive.\n\t\t\t\trole == RHead && !m.caseSensitive {\n\t\t\t\tcharScore++\n\t\t\t}\n\n\t\t\t// Penalty: pattern char is Head, candidate char is Tail.\n\t\t\tif role == RTail && pRole == RHead {\n\t\t\t\tcharScore--\n\t\t\t}\n\t\t\t// Penalty: first pattern character matched in the middle of a word.\n\t\t\tif j == 1 && role == RTail {\n\t\t\t\tcharScore -= 4\n\t\t\t}\n\n\t\t\t// Third dimension encodes whether there is a gap between the previous match and the current\n\t\t\t// one.\n\t\t\tfor k := range 2 {\n\t\t\t\tsc := m.scores[i-1][j-1][k].val() + charScore\n\n\t\t\t\tisConsecutive := k == 1 || i-1 == 0 || i-1 == lastSegStart\n\t\t\t\tif isConsecutive {\n\t\t\t\t\t// Bonus: a consecutive match. First character match also gets a bonus to\n\t\t\t\t\t// ensure prefix final match score normalizes to 1.0.\n\t\t\t\t\t// Logically, this is a part of charScore, but we have to compute it here because it\n\t\t\t\t\t// only applies for consecutive matches (k == 1).\n\t\t\t\t\tsc += consecutiveBonus\n\t\t\t\t}\n\t\t\t\tif k == 0 {\n\t\t\t\t\t// Penalty: Matching inside a segment (and previous char wasn't matched). Penalize for the lack\n\t\t\t\t\t// of alignment.\n\t\t\t\t\tif role == RTail || role == RUCTail {\n\t\t\t\t\t\tsc -= 3\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif sc > m.scores[i][j][1].val() {\n\t\t\t\t\tm.scores[i][j][1] = score(sc, k)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := m.scores[len(candidate)][len(m.pattern)][m.bestK(len(candidate), len(m.pattern))].val()\n\n\treturn result\n}\n\n// ScoreTable returns the score table computed for the provided candidate. Used only for debugging.\nfunc (m *Matcher) ScoreTable(candidate string) string {\n\tvar buf bytes.Buffer\n\n\tvar line1, line2, separator bytes.Buffer\n\tline1.WriteString(\"\\t\")\n\tline2.WriteString(\"\\t\")\n\tfor j := range len(m.pattern) {\n\t\tline1.WriteString(fmt.Sprintf(\"%c\\t\\t\", m.pattern[j]))\n\t\tseparator.WriteString(\"----------------\")\n\t}\n\n\tbuf.WriteString(line1.String())\n\tbuf.WriteString(\"\\n\")\n\tbuf.WriteString(separator.String())\n\tbuf.WriteString(\"\\n\")\n\n\tfor i := 1; i <= len(candidate); i++ {\n\t\tline1.Reset()\n\t\tline2.Reset()\n\n\t\tline1.WriteString(fmt.Sprintf(\"%c\\t\", candidate[i-1]))\n\t\tline2.WriteString(\"\\t\")\n\n\t\tfor j := 1; j <= len(m.pattern); j++ {\n\t\t\tline1.WriteString(fmt.Sprintf(\"M%6d(%c)\\t\", m.scores[i][j][0].val(), dir(m.scores[i][j][0].prevK())))\n\t\t\tline2.WriteString(fmt.Sprintf(\"H%6d(%c)\\t\", m.scores[i][j][1].val(), dir(m.scores[i][j][1].prevK())))\n\t\t}\n\t\tbuf.WriteString(line1.String())\n\t\tbuf.WriteString(\"\\n\")\n\t\tbuf.WriteString(line2.String())\n\t\tbuf.WriteString(\"\\n\")\n\t\tbuf.WriteString(separator.String())\n\t\tbuf.WriteString(\"\\n\")\n\t}\n\n\treturn buf.String()\n}\n\nfunc dir(prevK int) rune {\n\tif prevK == 0 {\n\t\treturn 'M'\n\t}\n\treturn 'H'\n}\n\nfunc (m *Matcher) poorMatch() bool {\n\tif len(m.pattern) < 2 {\n\t\treturn false\n\t}\n\n\ti, j := m.lastCandidateLen, len(m.pattern)\n\tk := m.bestK(i, j)\n\n\tvar counter, len int\n\tfor i > 0 {\n\t\ttake := (k == 1)\n\t\tk = m.scores[i][j][k].prevK()\n\t\tif take {\n\t\t\tlen++\n\t\t\tif k == 0 && len < 3 && m.roles[i-1] == RTail {\n\t\t\t\t// Short match in the middle of a word\n\t\t\t\tcounter++\n\t\t\t\tif counter > 1 {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\tj--\n\t\t} else {\n\t\t\tlen = 0\n\t\t}\n\t\ti--\n\t}\n\treturn false\n}\n\n// BestMatch returns the name most similar to the\n// pattern, using fuzzy matching, or the empty string.\nfunc BestMatch(pattern string, names []string) string {\n\tfuzz := NewMatcher(pattern)\n\tbest := \"\"\n\thighScore := float32(0) // minimum score is 0 (no match)\n\tfor _, name := range names {\n\t\t// TODO: Improve scoring algorithm.\n\t\tscore := fuzz.Score(name)\n\t\tif score > highScore {\n\t\t\thighScore = score\n\t\t\tbest = name\n\t\t} else if score == 0 {\n\t\t\t// Order matters in the fuzzy matching algorithm. If we find no match\n\t\t\t// when matching the target to the identifier, try matching the identifier\n\t\t\t// to the target.\n\t\t\trevFuzz := NewMatcher(name)\n\t\t\trevScore := revFuzz.Score(pattern)\n\t\t\tif revScore > highScore {\n\t\t\t\thighScore = revScore\n\t\t\t\tbest = name\n\t\t\t}\n\t\t}\n\t}\n\treturn best\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/matcher_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Benchmark results:\n//\n// BenchmarkMatcher-12    \t 1000000\t      1615 ns/op\t  30.95 MB/s\t       0 B/op\t       0 allocs/op\npackage fuzzy_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"math\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n)\n\ntype comparator struct {\n\tf     func(val, ref float32) bool\n\tdescr string\n}\n\nvar (\n\teq = comparator{\n\t\tf: func(val, ref float32) bool {\n\t\t\treturn val == ref\n\t\t},\n\t\tdescr: \"==\",\n\t}\n\tge = comparator{\n\t\tf: func(val, ref float32) bool {\n\t\t\treturn val >= ref\n\t\t},\n\t\tdescr: \">=\",\n\t}\n\tgt = comparator{\n\t\tf: func(val, ref float32) bool {\n\t\t\treturn val > ref\n\t\t},\n\t\tdescr: \">\",\n\t}\n)\n\nfunc (c comparator) eval(val, ref float32) bool {\n\treturn c.f(val, ref)\n}\n\nfunc (c comparator) String() string {\n\treturn c.descr\n}\n\ntype scoreTest struct {\n\tcandidate string\n\tcomparator\n\tref float32\n}\n\nvar matcherTests = []struct {\n\tpattern string\n\ttests   []scoreTest\n}{\n\t{\n\t\tpattern: \"\",\n\t\ttests: []scoreTest{\n\t\t\t{\"def\", eq, 1},\n\t\t\t{\"Ab stuff c\", eq, 1},\n\t\t},\n\t},\n\t{\n\t\tpattern: \"abc\",\n\t\ttests: []scoreTest{\n\t\t\t{\"def\", eq, 0},\n\t\t\t{\"abd\", eq, 0},\n\t\t\t{\"abc\", ge, 0},\n\t\t\t{\"Abc\", ge, 0},\n\t\t\t{\"Ab stuff c\", ge, 0},\n\t\t},\n\t},\n\t{\n\t\tpattern: \"Abc\",\n\t\ttests: []scoreTest{\n\t\t\t{\"def\", eq, 0},\n\t\t\t{\"abd\", eq, 0},\n\t\t\t{\"abc\", ge, 0},\n\t\t\t{\"Abc\", ge, 0},\n\t\t\t{\"Ab stuff c\", ge, 0},\n\t\t},\n\t},\n\t{\n\t\tpattern: \"U\",\n\t\ttests: []scoreTest{\n\t\t\t{\"ErrUnexpectedEOF\", gt, 0},\n\t\t\t{\"ErrUnexpectedEOF.Error\", eq, 0},\n\t\t},\n\t},\n}\n\nfunc TestScore(t *testing.T) {\n\tfor _, tc := range matcherTests {\n\t\tm := fuzzy.NewMatcher(tc.pattern)\n\t\tfor _, sct := range tc.tests {\n\t\t\tscore := m.Score(sct.candidate)\n\t\t\tif !sct.comparator.eval(score, sct.ref) {\n\t\t\t\tt.Errorf(\"m.Score(%q) = %.2g, want %s %v\", sct.candidate, score, sct.comparator, sct.ref)\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar compareCandidatesTestCases = []struct {\n\tpattern string\n\t// In `[][]string{{\"foo\", \"bar\"}, {\"baz\"}}`,\n\t// \"foo\" and \"bar\" must have same score, \"baz\" must be strictly higher scoring.\n\torderedCandidates [][]string\n}{\n\t{\n\t\tpattern: \"Foo\",\n\t\torderedCandidates: [][]string{\n\t\t\t{\"Barfoo\"},\n\t\t\t{\"Faoo\"},\n\t\t\t{\"F_o_o\"},\n\t\t\t{\"FaoFooa\", \"BarFoo\"},\n\t\t\t{\"F__oo\", \"F_oo\"},\n\t\t\t{\"FooA\", \"FooBar\", \"Foo\"},\n\t\t},\n\t},\n\t{\n\t\tpattern: \"U\",\n\t\torderedCandidates: [][]string{\n\t\t\t{\"ErrUnexpectedEOF.Error\"},\n\t\t\t{\"ErrUnexpectedEOF\"},\n\t\t},\n\t},\n\t{\n\t\tpattern: \"N\",\n\t\torderedCandidates: [][]string{\n\t\t\t{\"name\"},\n\t\t\t{\"Name\"},\n\t\t},\n\t},\n}\n\nfunc TestCompareCandidateScores(t *testing.T) {\n\tfor _, tc := range compareCandidatesTestCases {\n\t\tm := fuzzy.NewMatcher(tc.pattern)\n\n\t\tvar prevScore float32\n\t\tvar prevCandGroup []string\n\t\tfor i, candGroup := range tc.orderedCandidates {\n\t\t\tvar groupScore float32\n\t\t\tfor j, cand := range candGroup {\n\t\t\t\tscore := m.Score(cand)\n\t\t\t\tif j > 0 && score != groupScore {\n\t\t\t\t\tt.Fatalf(\"score %f of %q different than group\", score, cand)\n\t\t\t\t}\n\t\t\t\tgroupScore = score\n\t\t\t}\n\n\t\t\tif i > 0 && prevScore >= groupScore {\n\t\t\t\tt.Errorf(\"%s[=%v] is not scored higher than %s[=%v]\", candGroup, groupScore, prevCandGroup, prevScore)\n\t\t\t}\n\t\t\tif groupScore < 0 || groupScore > 1 {\n\t\t\t\tt.Errorf(\"%s score is %v; want value between [0, 1]\", candGroup, groupScore)\n\t\t\t}\n\t\t\tprevScore = groupScore\n\t\t\tprevCandGroup = candGroup\n\t\t}\n\t}\n}\n\nvar fuzzyMatcherTestCases = []struct {\n\tp    string\n\tstr  string\n\twant string\n}{\n\t{p: \"foo\", str: \"abc::foo\", want: \"abc::[foo]\"},\n\t{p: \"foo\", str: \"foo.foo\", want: \"foo.[foo]\"},\n\t{p: \"foo\", str: \"fo_oo.o_oo\", want: \"[fo]_oo.[o]_oo\"},\n\t{p: \"foo\", str: \"fo_oo.fo_oo\", want: \"fo_oo.[fo]_[o]o\"},\n\t{p: \"fo_o\", str: \"fo_oo.o_oo\", want: \"[f]o_oo.[o_o]o\"},\n\t{p: \"fOO\", str: \"fo_oo.o_oo\", want: \"[f]o_oo.[o]_[o]o\"},\n\t{p: \"tedit\", str: \"foo.TextEdit\", want: \"foo.[T]ext[Edit]\"},\n\t{p: \"TEdit\", str: \"foo.TextEdit\", want: \"foo.[T]ext[Edit]\"},\n\t{p: \"Tedit\", str: \"foo.TextEdit\", want: \"foo.[T]ext[Edit]\"},\n\t{p: \"Tedit\", str: \"foo.Textedit\", want: \"foo.[Te]xte[dit]\"},\n\t{p: \"TEdit\", str: \"foo.Textedit\", want: \"\"},\n\t{p: \"te\", str: \"foo.Textedit\", want: \"foo.[Te]xtedit\"},\n\t{p: \"ee\", str: \"foo.Textedit\", want: \"\"}, // short middle of the word match\n\t{p: \"ex\", str: \"foo.Textedit\", want: \"foo.T[ex]tedit\"},\n\t{p: \"exdi\", str: \"foo.Textedit\", want: \"\"},  // short middle of the word match\n\t{p: \"exdit\", str: \"foo.Textedit\", want: \"\"}, // short middle of the word match\n\t{p: \"extdit\", str: \"foo.Textedit\", want: \"foo.T[ext]e[dit]\"},\n\t{p: \"e\", str: \"foo.Textedit\", want: \"foo.T[e]xtedit\"},\n\t{p: \"E\", str: \"foo.Textedit\", want: \"foo.T[e]xtedit\"},\n\t{p: \"ed\", str: \"foo.Textedit\", want: \"foo.Text[ed]it\"},\n\t{p: \"edt\", str: \"foo.Textedit\", want: \"\"}, // short middle of the word match\n\t{p: \"edit\", str: \"foo.Textedit\", want: \"foo.Text[edit]\"},\n\t{p: \"edin\", str: \"foo.TexteditNum\", want: \"foo.Text[edi]t[N]um\"},\n\t{p: \"n\", str: \"node.GoNodeMax\", want: \"[n]ode.GoNodeMax\"},\n\t{p: \"N\", str: \"node.GoNodeMax\", want: \"[n]ode.GoNodeMax\"},\n\t{p: \"completio\", str: \"completion\", want: \"[completio]n\"},\n\t{p: \"completio\", str: \"completion.None\", want: \"[completio]n.None\"},\n}\n\nfunc TestFuzzyMatcherRanges(t *testing.T) {\n\tfor _, tc := range fuzzyMatcherTestCases {\n\t\tmatcher := fuzzy.NewMatcher(tc.p)\n\t\tscore := matcher.Score(tc.str)\n\t\tif tc.want == \"\" {\n\t\t\tif score > 0 {\n\t\t\t\tt.Errorf(\"Score(%s, %s) = %v; want: <= 0\", tc.p, tc.str, score)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif score < 0 {\n\t\t\tt.Errorf(\"Score(%s, %s) = %v, want: > 0\", tc.p, tc.str, score)\n\t\t\tcontinue\n\t\t}\n\t\tgot := highlightMatches(tc.str, matcher)\n\t\tif tc.want != got {\n\t\t\tt.Errorf(\"highlightMatches(%s, %s) = %v, want: %v\", tc.p, tc.str, got, tc.want)\n\t\t}\n\t}\n}\n\nvar scoreTestCases = []struct {\n\tp    string\n\tstr  string\n\twant float64\n}{\n\t// Score precision up to five digits. Modify if changing the score, but make sure the new values\n\t// are reasonable.\n\t{p: \"abc\", str: \"abc\", want: 1},\n\t{p: \"abc\", str: \"Abc\", want: 1},\n\t{p: \"abc\", str: \"Abcdef\", want: 1},\n\t{p: \"strc\", str: \"StrCat\", want: 1},\n\t{p: \"abc_def\", str: \"abc_def_xyz\", want: 1},\n\t{p: \"abcdef\", str: \"abc_def_xyz\", want: 0.91667},\n\t{p: \"abcxyz\", str: \"abc_def_xyz\", want: 0.91667},\n\t{p: \"sc\", str: \"StrCat\", want: 0.75},\n\t{p: \"abc\", str: \"AbstrBasicCtor\", want: 0.83333},\n\t{p: \"foo\", str: \"abc::foo\", want: 0.91667},\n\t{p: \"afoo\", str: \"abc::foo\", want: 0.9375},\n\t{p: \"abr\", str: \"abc::bar\", want: 0.5},\n\t{p: \"br\", str: \"abc::bar\", want: 0.25},\n\t{p: \"aar\", str: \"abc::bar\", want: 0.41667},\n\t{p: \"edin\", str: \"foo.TexteditNum\", want: 0.125},\n\t{p: \"ediu\", str: \"foo.TexteditNum\", want: 0},\n\t// We want the next two items to have roughly similar scores.\n\t{p: \"up\", str: \"unique_ptr\", want: 0.75},\n\t{p: \"up\", str: \"upper_bound\", want: 1},\n}\n\nfunc TestScores(t *testing.T) {\n\tfor _, tc := range scoreTestCases {\n\t\tmatcher := fuzzy.NewMatcher(tc.p)\n\t\tgot := math.Round(float64(matcher.Score(tc.str))*1e5) / 1e5\n\t\tif got != tc.want {\n\t\t\tt.Errorf(\"Score(%s, %s) = %v, want: %v\", tc.p, tc.str, got, tc.want)\n\t\t}\n\t}\n}\n\nfunc highlightMatches(str string, matcher *fuzzy.Matcher) string {\n\tmatches := matcher.MatchedRanges()\n\n\tvar buf bytes.Buffer\n\tindex := 0\n\tfor i := 0; i < len(matches)-1; i += 2 {\n\t\ts, e := matches[i], matches[i+1]\n\t\tfmt.Fprintf(&buf, \"%s[%s]\", str[index:s], str[s:e])\n\t\tindex = e\n\t}\n\tbuf.WriteString(str[index:])\n\treturn buf.String()\n}\n\nfunc BenchmarkMatcher(b *testing.B) {\n\tpattern := \"Foo\"\n\tcandidates := []string{\n\t\t\"F_o_o\",\n\t\t\"Barfoo\",\n\t\t\"Faoo\",\n\t\t\"F__oo\",\n\t\t\"F_oo\",\n\t\t\"FaoFooa\",\n\t\t\"BarFoo\",\n\t\t\"FooA\",\n\t\t\"FooBar\",\n\t\t\"Foo\",\n\t}\n\n\tmatcher := fuzzy.NewMatcher(pattern)\n\n\tfor b.Loop() {\n\t\tfor _, c := range candidates {\n\t\t\tmatcher.Score(c)\n\t\t}\n\t}\n\tvar numBytes int\n\tfor _, c := range candidates {\n\t\tnumBytes += len(c)\n\t}\n\tb.SetBytes(int64(numBytes))\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/self_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fuzzy_test\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/fuzzy\"\n)\n\nfunc BenchmarkSelf_Matcher(b *testing.B) {\n\tidents := collectIdentifiers(b)\n\tpatterns := generatePatterns()\n\n\tfor b.Loop() {\n\t\tfor _, pattern := range patterns {\n\t\t\tsm := NewMatcher(pattern)\n\t\t\tfor _, ident := range idents {\n\t\t\t\t_ = sm.Score(ident)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc BenchmarkSelf_SymbolMatcher(b *testing.B) {\n\tidents := collectIdentifiers(b)\n\tpatterns := generatePatterns()\n\n\tfor b.Loop() {\n\t\tfor _, pattern := range patterns {\n\t\t\tsm := NewSymbolMatcher(pattern)\n\t\t\tfor _, ident := range idents {\n\t\t\t\t_, _ = sm.Match([]string{ident})\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/symbol.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fuzzy\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"unicode\"\n)\n\n// SymbolMatcher implements a fuzzy matching algorithm optimized for Go symbols\n// of the form:\n//\n//\texample.com/path/to/package.object.field\n//\n// Knowing that we are matching symbols like this allows us to make the\n// following optimizations:\n//   - We can incorporate right-to-left relevance directly into the score\n//     calculation.\n//   - We can match from right to left, discarding leading bytes if the input is\n//     too long.\n//   - We just take the right-most match without losing too much precision. This\n//     allows us to use an O(n) algorithm.\n//   - We can operate directly on chunked strings; in many cases we will\n//     be storing the package path and/or package name separately from the\n//     symbol or identifiers, so doing this avoids allocating strings.\n//   - We can return the index of the right-most match, allowing us to trim\n//     irrelevant qualification.\ntype SymbolMatcher struct {\n\t// Using buffers of length 256 is both a reasonable size for most qualified\n\t// symbols, and makes it easy to avoid bounds checks by using uint8 indexes.\n\tpattern     [256]rune\n\tpatternLen  uint8\n\tinputBuffer [256]rune   // avoid allocating when considering chunks\n\troles       [256]uint32 // which roles does a rune play (word start, etc.)\n\tsegments    [256]uint8  // how many segments from the right is each rune\n}\n\n// Rune roles.\nconst (\n\tsegmentStart uint32 = 1 << iota // input rune starts a segment (i.e. follows '/' or '.')\n\twordStart                       // input rune starts a word, per camel-case naming rules\n\tseparator                       // input rune is a separator ('/' or '.')\n\tupper                           // input rune is an upper case letter\n)\n\n// NewSymbolMatcher creates a SymbolMatcher that may be used to match the given\n// search pattern.\n//\n// Currently this matcher only accepts case-insensitive fuzzy patterns.\n//\n// An empty pattern matches no input.\nfunc NewSymbolMatcher(pattern string) *SymbolMatcher {\n\tm := &SymbolMatcher{}\n\tfor _, p := range pattern {\n\t\tm.pattern[m.patternLen] = unicode.ToLower(p)\n\t\tm.patternLen++\n\t\tif m.patternLen == 255 || int(m.patternLen) == len(pattern) {\n\t\t\t// break at 255 so that we can represent patternLen with a uint8.\n\t\t\tbreak\n\t\t}\n\t}\n\treturn m\n}\n\n// Match searches for the right-most match of the search pattern within the\n// symbol represented by concatenating the given chunks.\n//\n// If a match is found, the first result holds the absolute byte offset within\n// all chunks for the start of the symbol. In other words, the index of the\n// match within strings.Join(chunks, \"\").\n//\n// The second return value will be the score of the match, which is always\n// between 0 and 1, inclusive. A score of 0 indicates no match.\n//\n// If no match is found, Match returns (-1, 0).\nfunc (m *SymbolMatcher) Match(chunks []string) (int, float64) {\n\t// Explicit behavior for an empty pattern.\n\t//\n\t// As a minor optimization, this also avoids nilness checks later on, since\n\t// the compiler can prove that m != nil.\n\tif m.patternLen == 0 {\n\t\treturn -1, 0\n\t}\n\n\t// Matching implements a heavily optimized linear scoring algorithm on the\n\t// input. This is not guaranteed to produce the highest score, but works well\n\t// enough, particularly due to the right-to-left significance of qualified\n\t// symbols.\n\t//\n\t// Matching proceeds in three passes through the input:\n\t//  - The first pass populates the input buffer and collects rune roles.\n\t//  - The second pass proceeds right-to-left to find the right-most match.\n\t//  - The third pass proceeds left-to-right from the start of the right-most\n\t//    match, to find the most *compact* match, and computes the score of this\n\t//    match.\n\t//\n\t// See below for more details of each pass, as well as the scoring algorithm.\n\n\t// First pass: populate the input buffer out of the provided chunks\n\t// (lower-casing in the process), and collect rune roles.\n\t//\n\t// We could also check for a forward match here, but since we'd have to write\n\t// the entire input anyway this has negligible impact on performance.\n\tvar (\n\t\tinputLen  = uint8(0)\n\t\tmodifiers = wordStart | segmentStart\n\t)\n\ninput:\n\tfor _, chunk := range chunks {\n\t\tfor _, r := range chunk {\n\t\t\tif r == '.' || r == '/' {\n\t\t\t\tmodifiers |= separator\n\t\t\t}\n\t\t\t// optimization: avoid calls to unicode.ToLower, which can't be inlined.\n\t\t\tl := r\n\t\t\tif r <= unicode.MaxASCII {\n\t\t\t\tif 'A' <= r && r <= 'Z' {\n\t\t\t\t\tl = r + 'a' - 'A'\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tl = unicode.ToLower(r)\n\t\t\t}\n\t\t\tif l != r {\n\t\t\t\tmodifiers |= upper\n\n\t\t\t\t// If the current rune is capitalized *and the preceding rune was not*,\n\t\t\t\t// mark this as a word start. This avoids spuriously high ranking of\n\t\t\t\t// non-camelcase naming schemas, such as the\n\t\t\t\t// yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE example of\n\t\t\t\t// golang/go#60201.\n\t\t\t\tif inputLen == 0 || m.roles[inputLen-1]&upper == 0 {\n\t\t\t\t\tmodifiers |= wordStart\n\t\t\t\t}\n\t\t\t}\n\t\t\tm.inputBuffer[inputLen] = l\n\t\t\tm.roles[inputLen] = modifiers\n\t\t\tinputLen++\n\t\t\tif m.roles[inputLen-1]&separator != 0 {\n\t\t\t\tmodifiers = wordStart | segmentStart\n\t\t\t} else {\n\t\t\t\tmodifiers = 0\n\t\t\t}\n\t\t\t// TODO: we should prefer the right-most input if it overflows, rather\n\t\t\t//       than the left-most as we're doing here.\n\t\t\tif inputLen == 255 {\n\t\t\t\tbreak input\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass: find the right-most match, and count segments from the\n\t// right.\n\tvar (\n\t\tpi    = uint8(m.patternLen - 1) // pattern index\n\t\tp     = m.pattern[pi]           // pattern rune\n\t\tstart = -1                      // start offset of match\n\t\trseg  = uint8(0)                // effective \"depth\" from the right of the current rune in consideration\n\t)\n\tconst maxSeg = 3 // maximum number of segments from the right to count, for scoring purposes.\n\n\tfor ii := inputLen - 1; ; ii-- {\n\t\tr := m.inputBuffer[ii]\n\t\tif rseg < maxSeg && m.roles[ii]&separator != 0 {\n\t\t\trseg++\n\t\t}\n\t\tm.segments[ii] = rseg\n\t\tif p == r {\n\t\t\tif pi == 0 {\n\t\t\t\t// TODO(rfindley): BUG: the docstring for Match says that it returns an\n\t\t\t\t// absolute byte offset, but clearly it is returning a rune offset here.\n\t\t\t\tstart = int(ii)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpi--\n\t\t\tp = m.pattern[pi]\n\t\t}\n\t\t// Don't check ii >= 0 in the loop condition: ii is a uint8.\n\t\tif ii == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif start < 0 {\n\t\t// no match: skip scoring\n\t\treturn -1, 0\n\t}\n\n\t// Third pass: find the shortest match and compute the score.\n\n\t// Score is the average score for each rune.\n\t//\n\t// A rune score is the multiple of:\n\t//   1. The base score, which is 1.0 if the rune starts a segment, 0.9 if the\n\t//      rune starts a mid-segment word, else 0.6.\n\t//\n\t//      Runes preceded by a matching rune are treated the same as the start\n\t//      of a mid-segment word (with a 0.9 score), so that sequential or exact\n\t//      matches are preferred. We call this a sequential bonus.\n\t//\n\t//      For the final rune match, this sequential bonus is reduced to 0.8 if\n\t//      the next rune in the input is a mid-segment word, or 0.7 if the next\n\t//      rune in the input is not a word or segment start. This ensures that\n\t//      we favor whole-word or whole-segment matches over prefix matches.\n\t//\n\t//   2. 1.0 if the rune is part of the last segment, otherwise\n\t//      1.0-0.1*<segments from the right>, with a max segment count of 3.\n\t//      Notably 1.0-0.1*3 = 0.7 > 0.6, so that foo/_/_/_/_ (a match very\n\t//      early in a qualified symbol name) still scores higher than _f_o_o_ (a\n\t//      completely split match).\n\t//\n\t// This is a naive algorithm, but it is fast. There's lots of prior art here\n\t// that could be leveraged. For example, we could explicitly consider\n\t// rune distance, and exact matches of words or segments.\n\t//\n\t// Also note that this might not actually find the highest scoring match, as\n\t// doing so could require a non-linear algorithm, depending on how the score\n\t// is calculated.\n\n\t// debugging support\n\tconst debug = false // enable to log debugging information\n\tvar (\n\t\truneScores []float64\n\t\truneIdxs   []int\n\t)\n\n\tpi = 0\n\tp = m.pattern[pi]\n\n\tconst (\n\t\tsegStartScore = 1.0 // base score of runes starting a segment\n\t\twordScore     = 0.9 // base score of runes starting or continuing a word\n\t\tnoStreak      = 0.6\n\t\tperSegment    = 0.1 // we count at most 3 segments above\n\t)\n\n\ttotScore := 0.0\n\tlastMatch := uint8(255)\n\tfor ii := uint8(start); ii < inputLen; ii++ {\n\t\tr := m.inputBuffer[ii]\n\t\tif r == p {\n\t\t\tpi++\n\t\t\tfinalRune := pi >= m.patternLen\n\t\t\tp = m.pattern[pi]\n\n\t\t\tbaseScore := noStreak\n\n\t\t\t// Calculate the sequence bonus based on preceding matches.\n\t\t\t//\n\t\t\t// We do this first as it is overridden by role scoring below.\n\t\t\tif lastMatch == ii-1 {\n\t\t\t\tbaseScore = wordScore\n\t\t\t\t// Reduce the sequence bonus for the final rune of the pattern based on\n\t\t\t\t// whether it borders a new segment or word.\n\t\t\t\tif finalRune {\n\t\t\t\t\tswitch {\n\t\t\t\t\tcase ii == inputLen-1 || m.roles[ii+1]&separator != 0:\n\t\t\t\t\t\t// Full segment: no reduction\n\t\t\t\t\tcase m.roles[ii+1]&wordStart != 0:\n\t\t\t\t\t\tbaseScore = wordScore - 0.1\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbaseScore = wordScore - 0.2\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlastMatch = ii\n\n\t\t\t// Calculate the rune's role score. If the rune starts a segment or word,\n\t\t\t// this overrides the sequence score, as the rune starts a new sequence.\n\t\t\tswitch {\n\t\t\tcase m.roles[ii]&segmentStart != 0:\n\t\t\t\tbaseScore = segStartScore\n\t\t\tcase m.roles[ii]&wordStart != 0:\n\t\t\t\tbaseScore = wordScore\n\t\t\t}\n\n\t\t\t// Apply the segment-depth penalty (segments from the right).\n\t\t\truneScore := baseScore * (1.0 - float64(m.segments[ii])*perSegment)\n\t\t\tif debug {\n\t\t\t\truneScores = append(runeScores, runeScore)\n\t\t\t\truneIdxs = append(runeIdxs, int(ii))\n\t\t\t}\n\t\t\ttotScore += runeScore\n\t\t\tif finalRune {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tif debug {\n\t\t// Format rune roles and scores in line:\n\t\t// fo[o:.52].[b:1]a[r:.6]\n\t\tvar summary bytes.Buffer\n\t\tlast := 0\n\t\tfor i, idx := range runeIdxs {\n\t\t\tsummary.WriteString(string(m.inputBuffer[last:idx])) // encode runes\n\t\t\tfmt.Fprintf(&summary, \"[%s:%.2g]\", string(m.inputBuffer[idx]), runeScores[i])\n\t\t\tlast = idx + 1\n\t\t}\n\t\tsummary.WriteString(string(m.inputBuffer[last:inputLen])) // encode runes\n\t\tlog.Println(summary.String())\n\t}\n\n\treturn start, totScore / float64(m.patternLen)\n}\n"
  },
  {
    "path": "gopls/internal/fuzzy/symbol_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fuzzy_test\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t. \"golang.org/x/tools/gopls/internal/fuzzy\"\n)\n\nfunc TestSymbolMatchIndex(t *testing.T) {\n\ttests := []struct {\n\t\tpattern, input string\n\t\twant           int\n\t}{\n\t\t{\"test\", \"foo.TestFoo\", 4},\n\t\t{\"test\", \"test\", 0},\n\t\t{\"test\", \"Test\", 0},\n\t\t{\"test\", \"est\", -1},\n\t\t{\"t\", \"shortest\", 7},\n\t\t{\"\", \"foo\", -1},\n\t\t{\"\", string([]rune{0}), -1}, // verify that we don't default to an empty pattern.\n\t\t{\"anything\", \"\", -1},\n\t}\n\n\tfor _, test := range tests {\n\t\tmatcher := NewSymbolMatcher(test.pattern)\n\t\tif got, _ := matcher.Match([]string{test.input}); got != test.want {\n\t\t\tt.Errorf(\"NewSymbolMatcher(%q).Match(%q) = %v, _, want %v, _\", test.pattern, test.input, got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestSymbolRanking(t *testing.T) {\n\n\t// query -> symbols to match, in ascending order of score\n\tqueryRanks := map[string][]string{\n\t\t\"test\": {\n\t\t\t\"this.is.better.than.most\",\n\t\t\t\"test.foo.bar\",\n\t\t\t\"thebest\",\n\t\t\t\"atest\",\n\t\t\t\"test.foo\",\n\t\t\t\"testage\",\n\t\t\t\"tTest\",\n\t\t\t\"foo.test\",\n\t\t},\n\t\t\"parseside\": { // golang/go#60201\n\t\t\t\"yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE\",\n\t\t\t\"parseContext.parse_sidebyside\",\n\t\t},\n\t\t\"cvb\": {\n\t\t\t\"filecache_test.testIPCValueB\",\n\t\t\t\"cover.Boundary\",\n\t\t},\n\t\t\"dho\": {\n\t\t\t\"gocommand.DebugHangingGoCommands\",\n\t\t\t\"protocol.DocumentHighlightOptions\",\n\t\t},\n\t\t\"flg\": {\n\t\t\t\"completion.FALLTHROUGH\",\n\t\t\t\"main.flagGoCmd\",\n\t\t},\n\t\t\"fvi\": {\n\t\t\t\"godoc.fileIndexVersion\",\n\t\t\t\"macho.FlagSubsectionsViaSymbols\",\n\t\t},\n\t}\n\n\tfor query, symbols := range queryRanks {\n\t\tt.Run(query, func(t *testing.T) {\n\t\t\tmatcher := NewSymbolMatcher(query)\n\t\t\tprev := 0.0\n\t\t\tfor _, sym := range symbols {\n\t\t\t\t_, score := matcher.Match([]string{sym})\n\t\t\t\tt.Logf(\"Match(%q) = %v\", sym, score)\n\t\t\t\tif score <= prev {\n\t\t\t\t\tt.Errorf(\"Match(%q) = _, %v, want > %v\", sym, score, prev)\n\t\t\t\t}\n\t\t\t\tprev = score\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMatcherSimilarities(t *testing.T) {\n\t// This test compares the fuzzy matcher with the symbol matcher on a corpus\n\t// of qualified identifiers extracted from x/tools.\n\t//\n\t// These two matchers are not expected to agree, but inspecting differences\n\t// can be useful for finding interesting ranking edge cases.\n\tt.Skip(\"unskip this test to compare matchers\")\n\n\tidents := collectIdentifiers(t)\n\tt.Logf(\"collected %d unique identifiers\", len(idents))\n\n\t// We can't use slices.MaxFunc because we want a custom\n\t// scoring (not equivalence) function.\n\ttopMatch := func(score func(string) float64) string {\n\t\ttop := \"\"\n\t\ttopScore := 0.0\n\t\tfor _, cand := range idents {\n\t\t\tif s := score(cand); s > topScore {\n\t\t\t\ttop = cand\n\t\t\t\ttopScore = s\n\t\t\t}\n\t\t}\n\t\treturn top\n\t}\n\n\tagreed := 0\n\ttotal := 0\n\tbad := 0\n\tpatterns := generatePatterns()\n\tfor _, pattern := range patterns {\n\t\ttotal++\n\n\t\tfm := NewMatcher(pattern)\n\t\ttopFuzzy := topMatch(func(input string) float64 {\n\t\t\treturn float64(fm.Score(input))\n\t\t})\n\t\tsm := NewSymbolMatcher(pattern)\n\t\ttopSymbol := topMatch(func(input string) float64 {\n\t\t\t_, score := sm.Match([]string{input})\n\t\t\treturn score\n\t\t})\n\t\tswitch {\n\t\tcase topFuzzy == \"\" && topSymbol != \"\":\n\t\t\tif false {\n\t\t\t\t// The fuzzy matcher has a bug where it misses some matches; for this\n\t\t\t\t// test we only care about the symbol matcher.\n\t\t\t\tt.Logf(\"%q matched %q but no fuzzy match\", pattern, topSymbol)\n\t\t\t}\n\t\t\ttotal--\n\t\t\tbad++\n\t\tcase topFuzzy != \"\" && topSymbol == \"\":\n\t\t\tt.Fatalf(\"%q matched %q but no symbol match\", pattern, topFuzzy)\n\t\tcase topFuzzy == topSymbol:\n\t\t\tagreed++\n\t\tdefault:\n\t\t\t// Enable this log to see mismatches.\n\t\t\tif false {\n\t\t\t\tt.Logf(\"mismatch for %q: fuzzy: %q, symbol: %q\", pattern, topFuzzy, topSymbol)\n\t\t\t}\n\t\t}\n\t}\n\tt.Logf(\"fuzzy matchers agreed on %d out of %d queries (%d bad)\", agreed, total, bad)\n}\n\nfunc collectIdentifiers(tb testing.TB) []string {\n\tcfg := &packages.Config{\n\t\tMode:  packages.NeedName | packages.NeedSyntax | packages.NeedFiles,\n\t\tTests: true,\n\t}\n\tpkgs, err := packages.Load(cfg, \"golang.org/x/tools/...\")\n\tif err != nil {\n\t\ttb.Fatal(err)\n\t}\n\tuniqueIdents := make(map[string]bool)\n\tdecls := 0\n\tfor _, pkg := range pkgs {\n\t\tfor _, f := range pkg.Syntax {\n\t\t\tfor _, decl := range f.Decls {\n\t\t\t\tdecls++\n\t\t\t\tswitch decl := decl.(type) {\n\t\t\t\tcase *ast.GenDecl:\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tswitch decl.Tok {\n\t\t\t\t\t\tcase token.IMPORT:\n\t\t\t\t\t\tcase token.TYPE:\n\t\t\t\t\t\t\tname := spec.(*ast.TypeSpec).Name.Name\n\t\t\t\t\t\t\tqualified := pkg.Name + \".\" + name\n\t\t\t\t\t\t\tuniqueIdents[qualified] = true\n\t\t\t\t\t\tcase token.CONST, token.VAR:\n\t\t\t\t\t\t\tfor _, n := range spec.(*ast.ValueSpec).Names {\n\t\t\t\t\t\t\t\tqualified := pkg.Name + \".\" + n.Name\n\t\t\t\t\t\t\t\tuniqueIdents[qualified] = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvar idents []string\n\tfor k := range uniqueIdents {\n\t\tidents = append(idents, k)\n\t}\n\tsort.Strings(idents)\n\treturn idents\n}\n\nfunc generatePatterns() []string {\n\tvar patterns []string\n\tfor x := 'a'; x <= 'z'; x++ {\n\t\tfor y := 'a'; y <= 'z'; y++ {\n\t\t\tfor z := 'a'; z <= 'z'; z++ {\n\t\t\t\tpatterns = append(patterns, string(x)+string(y)+string(z))\n\t\t\t}\n\t\t}\n\t}\n\treturn patterns\n}\n\n// Test that we strongly prefer exact matches.\n//\n// In golang/go#60027, we preferred \"Runner\" for the query \"rune\" over several\n// results containing the word \"rune\" exactly. Following this observation,\n// scoring was tweaked to more strongly emphasize sequential characters and\n// exact matches.\nfunc TestSymbolRanking_Issue60027(t *testing.T) {\n\tmatcher := NewSymbolMatcher(\"rune\")\n\n\t// symbols to match, in ascending order of ranking.\n\tsymbols := []string{\n\t\t\"Runner\",\n\t\t\"singleRuneParam\",\n\t\t\"Config.ifsRune\",\n\t\t\"Parser.rune\",\n\t}\n\tprev := 0.0\n\tfor _, sym := range symbols {\n\t\t_, score := matcher.Match([]string{sym})\n\t\tt.Logf(\"Match(%q) = %v\", sym, score)\n\t\tif score < prev {\n\t\t\tt.Errorf(\"Match(%q) = _, %v, want > %v\", sym, score, prev)\n\t\t}\n\t\tprev = score\n\t}\n}\n\nfunc TestChunkedMatch(t *testing.T) {\n\tmatcher := NewSymbolMatcher(\"test\")\n\t_, want := matcher.Match([]string{\"test\"})\n\tchunked := [][]string{\n\t\t{\"\", \"test\"},\n\t\t{\"test\", \"\"},\n\t\t{\"te\", \"st\"},\n\t}\n\n\tfor _, chunks := range chunked {\n\t\toffset, score := matcher.Match(chunks)\n\t\tif offset != 0 || score != want {\n\t\t\tt.Errorf(\"Match(%v) = %v, %v, want 0, 1.0\", chunks, offset, score)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/goasm/definition.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package goasm provides language-server features for files in Go\n// assembly language (https://go.dev/doc/asm).\npackage goasm\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/asm\"\n\t\"golang.org/x/tools/gopls/internal/util/morestrings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Definition handles the textDocument/definition request for Go assembly files.\nfunc Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\tctx, done := event.Start(ctx, \"goasm.Definition\")\n\tdefer done()\n\n\tmp, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Read the file.\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tmapper := protocol.NewMapper(fh.URI(), content)\n\tstart, end, err := mapper.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Parse the assembly.\n\t//\n\t// TODO(adonovan): make this just another\n\t// attribute of the type-checked cache.Package.\n\tfile := asm.Parse(content)\n\n\t// Figure out the selected symbol.\n\t// For now, just find the identifier around the cursor.\n\tvar found *asm.Ident\n\tfor _, id := range file.Idents {\n\t\tif id.Offset <= start && end <= id.End() {\n\t\t\tfound = &id\n\t\t\tbreak\n\t\t}\n\t}\n\tif found == nil {\n\t\treturn nil, fmt.Errorf(\"not an identifier\")\n\t}\n\n\t// Resolve a symbol with a \".\" prefix to the current package.\n\tsym := found.Name\n\tif sym != \"\" && sym[0] == '.' {\n\t\tsym = string(mp.PkgPath) + sym\n\t}\n\n\t// package-qualified symbol?\n\tif pkgpath, name, ok := morestrings.CutLast(sym, \".\"); ok {\n\t\t// Find declaring package among dependencies.\n\t\t//\n\t\t// TODO(adonovan): assembly may legally reference\n\t\t// non-dependencies. For example, sync/atomic calls\n\t\t// internal/runtime/atomic. Perhaps we should search\n\t\t// the entire metadata graph, but that's path-dependent.\n\t\tvar declaring *metadata.Package\n\t\tfor pkg := range snapshot.MetadataGraph().ForwardReflexiveTransitiveClosure(mp.ID) {\n\t\t\tif pkg.PkgPath == metadata.PackagePath(pkgpath) {\n\t\t\t\tdeclaring = pkg\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif declaring == nil {\n\t\t\treturn nil, fmt.Errorf(\"package %q is not a dependency\", pkgpath)\n\t\t}\n\n\t\t// Find declared symbol in syntax package.\n\t\tpkgs, err := snapshot.TypeCheck(ctx, declaring.ID)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpkg := pkgs[0]\n\t\tdef := pkg.Types().Scope().Lookup(name)\n\t\tif def == nil {\n\t\t\treturn nil, fmt.Errorf(\"no symbol %q in package %q\", name, pkgpath)\n\t\t}\n\n\t\t// Map position.\n\t\tpos := def.Pos()\n\t\tpgf, err := pkg.FileEnclosing(pos)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tloc, err := pgf.PosLocation(pos, pos+token.Pos(len(name)))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn []protocol.Location{loc}, nil\n\n\t} else {\n\t\t// local symbols (funcs, vars, labels)\n\t\tfor _, id := range file.Idents {\n\t\t\tif id.Name == found.Name &&\n\t\t\t\t(id.Kind == asm.Text || id.Kind == asm.Global || id.Kind == asm.Label) {\n\n\t\t\t\tloc, err := mapper.OffsetLocation(id.Offset, id.End())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\treturn []protocol.Location{loc}, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/add_import.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\n// AddImport adds a single import statement to the given file\nfunc AddImport(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, importPath string) ([]protocol.TextEdit, error) {\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn ComputeImportFixEdits(snapshot.Options().Local, pgf.Src, &imports.ImportFix{\n\t\tStmtInfo: imports.ImportInfo{\n\t\t\tImportPath: importPath,\n\t\t},\n\t\tFixType: imports.AddImport,\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/golang/addtest.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines the behavior of the \"Add test for FUNC\" command.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/template\"\n\t\"unicode\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst testTmplString = `\nfunc {{.TestFuncName}}(t *{{.TestingPackageName}}.T) {\n\t{{- /* Test cases struct declaration and empty initialization. */}}\n\ttests := []struct {\n\t\tname string // description of this test case\n\n\t\t{{- $commentPrinted := false }}\n\t\t{{- if and .Receiver .Receiver.Constructor}}\n\t\t{{- range .Receiver.Constructor.Args}}\n\t\t{{- if .Name}}\n\t\t{{- if not $commentPrinted}}\n\t\t// Named input parameters for receiver constructor.\n\t\t{{- $commentPrinted = true }}\n\t\t{{- end}}\n\t\t{{.Name}} {{.Type}}\n\t\t{{- end}}\n\t\t{{- end}}\n\t\t{{- end}}\n\n\t\t{{- $commentPrinted := false }}\n\t\t{{- range .Func.Args}}\n\t\t{{- if .Name}}\n\t\t{{- if not $commentPrinted}}\n\t\t// Named input parameters for target function.\n\t\t{{- $commentPrinted = true }}\n\t\t{{- end}}\n\t\t{{.Name}} {{.Type}}\n\t\t{{- end}}\n\t\t{{- end}}\n\n\t\t{{- range $index, $res := .Func.Results}}\n\t\t{{- if eq $res.Name \"gotErr\"}}\n\t\twantErr bool\n\t\t{{- else if eq $index 0}}\n\t\twant {{$res.Type}}\n\t\t{{- else}}\n\t\twant{{add $index 1}} {{$res.Type}}\n\t\t{{- end}}\n\t\t{{- end}}\n\t}{\n\t\t// TODO: Add test cases.\n\t}\n\n\t{{- /* Loop over all the test cases. */}}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *{{.TestingPackageName}}.T) {\n\t\t\t{{- /* Constructor or empty initialization. */}}\n\t\t\t{{- if .Receiver}}\n\t\t\t{{- if .Receiver.Constructor}}\n\t\t\t{{- /* Receiver variable by calling constructor. */}}\n\t\t\t{{fieldNames .Receiver.Constructor.Results \"\"}} := {{if .PackageName}}{{.PackageName}}.{{end}}\n\t\t\t{{- .Receiver.Constructor.Name}}\n\n\t\t\t{{- /* Constructor input parameters. */ -}}\n\t\t\t(\n\t\t\t\t{{- range $index, $arg := .Receiver.Constructor.Args}}\n\t\t\t\t{{- if ne $index 0}}, {{end}}\n\t\t\t\t{{- if .Name}}tt.{{.Name}}{{else}}{{.Value}}{{end}}\n\t\t\t\t{{- end -}}\n\t\t\t\t{{- if and .Receiver.Constructor.IsVariadic (not .Receiver.Constructor.IsUnusedVariadic) }}...{{- end -}}\n\t\t\t)\n\n\t\t\t{{- /* Handles the error return from constructor. */}}\n\t\t\t{{- $last := last .Receiver.Constructor.Results}}\n\t\t\t{{- if eq $last.Type \"error\"}}\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n\t\t\t}\n\t\t\t{{- end}}\n\t\t\t{{- else}}\n\t\t\t{{- /* Receiver variable declaration. */}}\n\t\t\t// TODO: construct the receiver type.\n\t\t\tvar {{.Receiver.Var.Name}} {{.Receiver.Var.Type}}\n\t\t\t{{- end}}\n\t\t\t{{- end}}\n\n\t\t\t{{- /* Got variables. */}}\n\t\t\t{{if .Func.Results}}{{fieldNames .Func.Results \"\"}} := {{end}}\n\n\t\t\t{{- /* Call expression. */}}\n\t\t\t{{- if .Receiver}}{{/* Call method by VAR.METHOD. */}}\n\t\t\t{{- .Receiver.Var.Name}}.\n\t\t\t{{- else if .PackageName}}{{/* Call function by PACKAGE.FUNC. */}}\n\t\t\t{{- .PackageName}}.\n\t\t\t{{- end}}{{.Func.Name}}\n\n\t\t\t{{- /* Input parameters. */ -}}\n\t\t\t(\n\t\t\t\t{{- range $index, $arg := .Func.Args}}\n\t\t\t\t{{- if ne $index 0}}, {{end}}\n\t\t\t\t{{- if .Name}}tt.{{.Name}}{{else}}{{.Value}}{{end}}\n\t\t\t\t{{- end -}}\n\t\t\t\t{{- if and .Func.IsVariadic (not .Func.IsUnusedVariadic) }}...{{- end -}}\n\t\t\t)\n\n\t\t\t{{- /* Handles the returned error before the rest of return value. */}}\n\t\t\t{{- $last := last .Func.Results}}\n\t\t\t{{- if eq $last.Type \"error\"}}\n\t\t\tif gotErr != nil {\n\t\t\t\tif !tt.wantErr {\n\t\t\t\t\tt.Errorf(\"{{$.Func.Name}}() failed: %v\", gotErr)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif tt.wantErr {\n\t\t\t\tt.Fatal(\"{{$.Func.Name}}() succeeded unexpectedly\")\n\t\t\t}\n\t\t\t{{- end}}\n\n\t\t\t{{- /* Compare the returned values except for the last returned error. */}}\n\t\t\t{{- if or (and .Func.Results (ne $last.Type \"error\")) (and (gt (len .Func.Results) 1) (eq $last.Type \"error\"))}}\n\t\t\t// TODO: update the condition below to compare got with tt.want.\n\t\t\t{{- range $index, $res := .Func.Results}}\n\t\t\t{{- if ne $res.Name \"gotErr\"}}\n\t\t\tif true {\n\t\t\t\tt.Errorf(\"{{$.Func.Name}}() = %v, want %v\", {{.Name}}, tt.{{if eq $index 0}}want{{else}}want{{add $index 1}}{{end}})\n\t\t\t}\n\t\t\t{{- end}}\n\t\t\t{{- end}}\n\t\t\t{{- end}}\n\t\t})\n\t}\n}\n`\n\n// Name is the name of the field this input parameter should reference.\n// Value is the expression this input parameter should accept.\n//\n// Exactly one of Name or Value must be set.\ntype field struct {\n\tName, Type, Value string\n}\n\ntype function struct {\n\tName    string\n\tArgs    []field\n\tResults []field\n\t// IsVariadic holds information if the function is variadic.\n\t// In case of the IsVariadic=true must expand it in the function-under-test call.\n\tIsVariadic bool\n\t// IsUnusedVariadic holds information if the function's variadic args is not used.\n\t// In this case ... must be skipped.\n\tIsUnusedVariadic bool\n}\n\ntype receiver struct {\n\t// Var is the name and type of the receiver variable.\n\tVar field\n\t// Constructor holds information about the constructor for the receiver type.\n\t// If no qualified constructor is found, this field will be nil.\n\tConstructor *function\n}\n\ntype testInfo struct {\n\t// TestingPackageName is the package name should be used when referencing\n\t// package \"testing\"\n\tTestingPackageName string\n\t// PackageName is the package name the target function/method is declared from.\n\tPackageName  string\n\tTestFuncName string\n\t// Func holds information about the function or method being tested.\n\tFunc function\n\t// Receiver holds information about the receiver of the function or method\n\t// being tested.\n\t// This field is nil for functions and non-nil for methods.\n\tReceiver *receiver\n}\n\nvar testTmpl = template.Must(template.New(\"test\").Funcs(template.FuncMap{\n\t\"add\": func(a, b int) int { return a + b },\n\t\"last\": func(slice []field) field {\n\t\tif len(slice) == 0 {\n\t\t\treturn field{}\n\t\t}\n\t\treturn slice[len(slice)-1]\n\t},\n\t\"fieldNames\": func(fields []field, qualifier string) (res string) {\n\t\tvar names []string\n\t\tfor _, f := range fields {\n\t\t\tnames = append(names, qualifier+f.Name)\n\t\t}\n\t\treturn strings.Join(names, \", \")\n\t},\n}).Parse(testTmplString))\n\n// AddTestForFunc adds a test for the function enclosing the given input range.\n// It creates a _test.go file if one does not already exist.\n// It returns the required text edits and the predicted location of the new test\n// function, which is only valid after the edits have been successfully applied.\nfunc AddTestForFunc(ctx context.Context, snapshot *cache.Snapshot, loc protocol.Location) (changes []protocol.DocumentChange, show *protocol.Location, _ error) {\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, loc.URI)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif metadata.IsCommandLineArguments(pkg.Metadata().ID) {\n\t\treturn nil, nil, fmt.Errorf(\"current file in command-line-arguments package\")\n\t}\n\n\tif errors := pkg.ParseErrors(); len(errors) > 0 {\n\t\treturn nil, nil, fmt.Errorf(\"package has parse errors: %v\", errors[0])\n\t}\n\tif errors := pkg.TypeErrors(); len(errors) > 0 {\n\t\treturn nil, nil, fmt.Errorf(\"package has type errors: %v\", errors[0])\n\t}\n\n\t// All three maps map the path of an imported package to\n\t// the local name if explicit or \"\" otherwise.\n\tvar (\n\t\tfileImports  map[string]string         // imports in foo.go file\n\t\ttestImports  map[string]string         // imports in foo_test.go file\n\t\textraImports = make(map[string]string) // imports to add to test file\n\t)\n\n\tcollectImports := func(file *ast.File) (map[string]string, error) {\n\t\timps := make(map[string]string)\n\t\tfor _, spec := range file.Imports {\n\t\t\t// TODO(hxjiang): support dot imports.\n\t\t\tif spec.Name != nil && spec.Name.Name == \".\" {\n\t\t\t\treturn nil, fmt.Errorf(\"\\\"add test for func\\\" does not support files containing dot imports\")\n\t\t\t}\n\t\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif spec.Name != nil {\n\t\t\t\tif spec.Name.Name == \"_\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\timps[path] = spec.Name.Name\n\t\t\t} else {\n\t\t\t\timps[path] = \"\"\n\t\t\t}\n\t\t}\n\t\treturn imps, nil\n\t}\n\n\t// Collect all the imports from the x.go, keep track of the local package name.\n\tif fileImports, err = collectImports(pgf.File); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\ttestBase := strings.TrimSuffix(loc.URI.Base(), \".go\") + \"_test.go\"\n\tgoTestFileURI := protocol.URIFromPath(filepath.Join(loc.URI.DirPath(), testBase))\n\n\ttestFH, err := snapshot.ReadFile(ctx, goTestFileURI)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// TODO(hxjiang): use a fresh name if the same test function name already\n\t// exist.\n\n\tvar (\n\t\teofRange protocol.Range // empty selection at end of new file\n\t\t// edits contains all the text edits to be applied to the test file.\n\t\tedits []protocol.TextEdit\n\t\t// xtest indicates whether the test file use package x or x_test.\n\t\t// TODO(hxjiang): We can discuss the option to interpret the user's\n\t\t// intention by which function they are selecting. Have one file for\n\t\t// x_test package testing, one file for x package testing.\n\t\txtest = true\n\t)\n\n\tstart, end, err := pgf.RangePos(loc.Range)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, start, end)\n\tif len(path) < 2 {\n\t\treturn nil, nil, fmt.Errorf(\"no enclosing function\")\n\t}\n\n\tdecl, ok := path[len(path)-2].(*ast.FuncDecl)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"no enclosing function\")\n\t}\n\n\tfn := pkg.TypesInfo().Defs[decl.Name].(*types.Func)\n\tsig := fn.Signature()\n\n\ttestPGF, err := snapshot.ParseGo(ctx, testFH, parsego.Header)\n\tif err != nil {\n\t\tif !errors.Is(err, os.ErrNotExist) {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tchanges = append(changes, protocol.DocumentChangeCreate(goTestFileURI))\n\n\t\t// header is the buffer containing the text to add to the beginning of the file.\n\t\tvar header bytes.Buffer\n\n\t\t// If this test file was created by the gopls, add a copyright header and\n\t\t// package decl based on the originating file.\n\t\t// Search for something that looks like a copyright header, to replicate\n\t\t// in the new file.\n\t\tif c := CopyrightComment(pgf.File); c != nil {\n\t\t\ttext, err := pgf.NodeText(c)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\theader.Write(text)\n\t\t\t// One empty line between copyright header and following.\n\t\t\theader.WriteString(\"\\n\\n\")\n\t\t}\n\n\t\t// If this test file was created by gopls, add build constraints\n\t\t// matching the non-test file.\n\t\tif c := buildConstraintComment(pgf.File); c != nil {\n\t\t\ttext, err := pgf.NodeText(c)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\theader.Write(text)\n\t\t\t// One empty line between build constraint and following.\n\t\t\theader.WriteString(\"\\n\\n\")\n\t\t}\n\n\t\t// Determine if a new test file should use in-package test (package x)\n\t\t// or external test (package x_test). If any of the function parameters\n\t\t// reference an unexported object, we cannot write out test cases from\n\t\t// an x_test package.\n\t\texternalTestOK := func() bool {\n\t\t\tif !fn.Exported() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif fn.Signature().Recv() != nil {\n\t\t\t\tif _, ident, _ := astutil.UnpackRecv(decl.Recv.List[0].Type); ident == nil || !ident.IsExported() {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\trefsUnexported := false\n\t\t\tast.Inspect(decl, func(n ast.Node) bool {\n\t\t\t\t// The original function refs to an unexported object from the\n\t\t\t\t// same package, so further inspection is unnecessary.\n\t\t\t\tif refsUnexported {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tswitch t := n.(type) {\n\t\t\t\tcase *ast.BlockStmt:\n\t\t\t\t\t// Avoid inspect the function body.\n\t\t\t\t\treturn false\n\t\t\t\tcase *ast.Ident:\n\t\t\t\t\t// Use test variant (package foo) if the function signature\n\t\t\t\t\t// references any unexported objects (like types or\n\t\t\t\t\t// constants) from the same package.\n\t\t\t\t\t// Note: types.PkgName is excluded from this check as it's\n\t\t\t\t\t// always defined in the same package.\n\t\t\t\t\tif obj, ok := pkg.TypesInfo().Uses[t]; ok && !obj.Exported() && obj.Pkg() == pkg.Types() && !is[*types.PkgName](obj) {\n\t\t\t\t\t\trefsUnexported = true\n\t\t\t\t\t}\n\t\t\t\t\treturn false\n\t\t\t\tdefault:\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t})\n\t\t\treturn !refsUnexported\n\t\t}\n\n\t\txtest = externalTestOK()\n\t\tif xtest {\n\t\t\tfmt.Fprintf(&header, \"package %s_test\\n\", pkg.Types().Name())\n\t\t} else {\n\t\t\tfmt.Fprintf(&header, \"package %s\\n\", pkg.Types().Name())\n\t\t}\n\n\t\t// Write the copyright and package decl to the beginning of the file.\n\t\tedits = append(edits, protocol.TextEdit{\n\t\t\tRange:   protocol.Range{},\n\t\t\tNewText: header.String(),\n\t\t})\n\t} else { // existing _test.go file.\n\t\tfile := testPGF.File\n\t\tif !file.Name.NamePos.IsValid() {\n\t\t\treturn nil, nil, fmt.Errorf(\"missing package declaration\")\n\t\t}\n\t\tswitch file.Name.Name {\n\t\tcase pgf.File.Name.Name:\n\t\t\txtest = false\n\t\tcase pgf.File.Name.Name + \"_test\":\n\t\t\txtest = true\n\t\tdefault:\n\t\t\treturn nil, nil, fmt.Errorf(\"invalid package declaration %q in test file %q\", file.Name, testPGF)\n\t\t}\n\n\t\teofRange, err = testPGF.PosRange(file.FileEnd, file.FileEnd)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\t// Collect all the imports from the foo_test.go.\n\t\tif testImports, err = collectImports(file); err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t}\n\n\t// qual qualifier determines the correct package name to use for a type in\n\t// foo_test.go. It does this by:\n\t// - Consult imports map from test file foo_test.go.\n\t// - If not found, consult imports map from original file foo.go.\n\t// If the package is not imported in test file foo_test.go, it is added to\n\t// extraImports map.\n\tqual := func(p *types.Package) string {\n\t\t// References from an in-package test should not be qualified.\n\t\tif !xtest && p == pkg.Types() {\n\t\t\treturn \"\"\n\t\t}\n\t\t// Prefer using the package name if already defined in foo_test.go\n\t\tif local, ok := testImports[p.Path()]; ok {\n\t\t\tif local != \"\" {\n\t\t\t\treturn local\n\t\t\t} else {\n\t\t\t\treturn p.Name()\n\t\t\t}\n\t\t}\n\t\t// TODO(hxjiang): we should consult the scope of the test package to\n\t\t// ensure these new imports do not shadow any package-level names.\n\t\t// Prefer the local import name (if any) used in the package under test.\n\t\tif local, ok := fileImports[p.Path()]; ok && local != \"\" {\n\t\t\textraImports[p.Path()] = local\n\t\t\treturn local\n\t\t}\n\t\t// Fall back to the package name since there is no renaming.\n\t\textraImports[p.Path()] = \"\"\n\t\treturn p.Name()\n\t}\n\n\tif xtest {\n\t\t// Reject if function/method is unexported.\n\t\tif !fn.Exported() {\n\t\t\treturn nil, nil, fmt.Errorf(\"cannot add test of unexported function %s to external test package %s_test\", decl.Name, pgf.File.Name)\n\t\t}\n\n\t\t// Reject if receiver is unexported.\n\t\tif sig.Recv() != nil {\n\t\t\tif _, ident, _ := astutil.UnpackRecv(decl.Recv.List[0].Type); ident == nil || !ident.IsExported() {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"cannot add external test for method %s.%s as receiver type is not exported\", ident.Name, decl.Name)\n\t\t\t}\n\t\t}\n\t\t// TODO(hxjiang): reject if the any input parameter type is unexported.\n\t\t// TODO(hxjiang): reject if any return value type is unexported. Explore\n\t\t// the option to drop the return value if the type is unexported.\n\t}\n\n\ttestName, err := testName(fn)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tdata := testInfo{\n\t\tTestingPackageName: qual(types.NewPackage(\"testing\", \"testing\")),\n\t\tPackageName:        qual(pkg.Types()),\n\t\tTestFuncName:       testName,\n\t\tFunc: function{\n\t\t\tName:       fn.Name(),\n\t\t\tIsVariadic: sig.Variadic(),\n\t\t},\n\t}\n\n\tisContextType := func(t types.Type) bool {\n\t\treturn typesinternal.IsTypeNamed(t, \"context\", \"Context\")\n\t}\n\n\tisUnusedParameter := func(name string) bool {\n\t\treturn name == \"\" || name == \"_\"\n\t}\n\n\tfor i := range sig.Params().Len() {\n\t\tparam := sig.Params().At(i)\n\t\tname, typ := param.Name(), param.Type()\n\t\tf := field{Type: types.TypeString(typ, qual)}\n\t\tif i == 0 && isContextType(typ) {\n\t\t\tf.Value = qual(types.NewPackage(\"context\", \"context\")) + \".Background()\"\n\t\t} else if isUnusedParameter(name) && data.Func.IsVariadic && sig.Params().Len()-1 == i {\n\t\t\t// The last argument is the variadic argument, and it's not used in the function body,\n\t\t\t// so we don't need to render it in the test case struct.\n\t\t\tdata.Func.IsUnusedVariadic = true\n\t\t\tcontinue\n\t\t} else if isUnusedParameter(name) {\n\t\t\tf.Value, _ = typesinternal.ZeroString(typ, qual)\n\t\t} else {\n\t\t\tf.Name = name\n\t\t}\n\t\tdata.Func.Args = append(data.Func.Args, f)\n\t}\n\n\tfor i := range sig.Results().Len() {\n\t\ttyp := sig.Results().At(i).Type()\n\t\tvar name string\n\t\tif i == sig.Results().Len()-1 && types.Identical(typ, errorType) {\n\t\t\tname = \"gotErr\"\n\t\t} else if i == 0 {\n\t\t\tname = \"got\"\n\t\t} else {\n\t\t\tname = fmt.Sprintf(\"got%d\", i+1)\n\t\t}\n\t\tdata.Func.Results = append(data.Func.Results, field{\n\t\t\tName: name,\n\t\t\tType: types.TypeString(typ, qual),\n\t\t})\n\t}\n\n\tif sig.Recv() != nil {\n\t\t// Find the preferred type for the receiver. We don't use\n\t\t// typesinternal.ReceiverNamed here as we want to preserve aliases.\n\t\trecvType := sig.Recv().Type()\n\t\tif ptr, ok := recvType.(*types.Pointer); ok {\n\t\t\trecvType = ptr.Elem()\n\t\t}\n\n\t\tt, ok := recvType.(typesinternal.NamedOrAlias)\n\t\tif !ok {\n\t\t\treturn nil, nil, fmt.Errorf(\"the receiver type is neither named type nor alias type\")\n\t\t}\n\n\t\tvar varName string\n\t\t{\n\t\t\tvar possibleNames []string // list of candidates, preferring earlier entries.\n\t\t\tif len(sig.Recv().Name()) > 0 {\n\t\t\t\tpossibleNames = append(possibleNames,\n\t\t\t\t\tsig.Recv().Name(),            // receiver name.\n\t\t\t\t\tstring(sig.Recv().Name()[0]), // first character of receiver name.\n\t\t\t\t)\n\t\t\t}\n\t\t\tpossibleNames = append(possibleNames,\n\t\t\t\tstring(t.Obj().Name()[0]), // first character of receiver type name.\n\t\t\t)\n\t\t\tif len(t.Obj().Name()) >= 2 {\n\t\t\t\tpossibleNames = append(possibleNames,\n\t\t\t\t\tstring(t.Obj().Name()[:2]), // first two character of receiver type name.\n\t\t\t\t)\n\t\t\t}\n\t\t\tvar camelCase []rune\n\t\t\tfor i, s := range t.Obj().Name() {\n\t\t\t\tif i == 0 || unicode.IsUpper(s) {\n\t\t\t\t\tcamelCase = append(camelCase, s)\n\t\t\t\t}\n\t\t\t}\n\t\t\tpossibleNames = append(possibleNames,\n\t\t\t\tstring(camelCase), // captalized initials.\n\t\t\t)\n\t\t\tfor _, name := range possibleNames {\n\t\t\t\tname = strings.ToLower(name)\n\t\t\t\tif name == \"\" || name == \"t\" || name == \"tt\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvarName = name\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif varName == \"\" {\n\t\t\t\tvarName = \"r\" // default as \"r\" for \"receiver\".\n\t\t\t}\n\t\t}\n\n\t\tdata.Receiver = &receiver{\n\t\t\tVar: field{\n\t\t\t\tName: varName,\n\t\t\t\tType: types.TypeString(recvType, qual),\n\t\t\t},\n\t\t}\n\n\t\t// constructor is the selected constructor for type T.\n\t\tvar constructor *types.Func\n\n\t\t// When finding the qualified constructor, the function should return the\n\t\t// any type whose named type is the same type as T's named type.\n\t\t_, wantType := typesinternal.ReceiverNamed(sig.Recv())\n\t\tfor _, name := range pkg.Types().Scope().Names() {\n\t\t\tf, ok := pkg.Types().Scope().Lookup(name).(*types.Func)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif f.Signature().Recv() != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Unexported constructor is not visible in x_test package.\n\t\t\tif xtest && !f.Exported() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Only allow constructors returning T, T, (T, error), or (T, error).\n\t\t\tif f.Signature().Results().Len() > 2 || f.Signature().Results().Len() == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t_, gotType := typesinternal.ReceiverNamed(f.Signature().Results().At(0))\n\t\t\tif gotType == nil || !types.Identical(gotType, wantType) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif f.Signature().Results().Len() == 2 && !types.Identical(f.Signature().Results().At(1).Type(), errorType) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif constructor == nil {\n\t\t\t\tconstructor = f\n\t\t\t}\n\n\t\t\t// Functions named NewType are prioritized as constructors over other\n\t\t\t// functions that match only the signature criteria.\n\t\t\tif strings.EqualFold(strings.ToLower(f.Name()), strings.ToLower(\"new\"+t.Obj().Name())) {\n\t\t\t\tconstructor = f\n\t\t\t}\n\t\t}\n\n\t\tif constructor != nil {\n\t\t\tdata.Receiver.Constructor = &function{\n\t\t\t\tName:       constructor.Name(),\n\t\t\t\tIsVariadic: constructor.Signature().Variadic(),\n\t\t\t}\n\t\t\tfor i := range constructor.Signature().Params().Len() {\n\t\t\t\tparam := constructor.Signature().Params().At(i)\n\t\t\t\tname, typ := param.Name(), param.Type()\n\t\t\t\tf := field{Type: types.TypeString(typ, qual)}\n\t\t\t\tif i == 0 && isContextType(typ) {\n\t\t\t\t\tf.Value = qual(types.NewPackage(\"context\", \"context\")) + \".Background()\"\n\t\t\t\t} else if isUnusedParameter(name) && data.Receiver.Constructor.IsVariadic && constructor.Signature().Params().Len()-1 == i {\n\t\t\t\t\t// The last argument is the variadic argument, and it's not used in the function body,\n\t\t\t\t\t// so we don't need to render it in the test case struct.\n\t\t\t\t\tdata.Receiver.Constructor.IsUnusedVariadic = true\n\t\t\t\t\tcontinue\n\t\t\t\t} else if isUnusedParameter(name) {\n\t\t\t\t\tf.Value, _ = typesinternal.ZeroString(typ, qual)\n\t\t\t\t} else {\n\t\t\t\t\tf.Name = name\n\t\t\t\t}\n\t\t\t\tdata.Receiver.Constructor.Args = append(data.Receiver.Constructor.Args, f)\n\t\t\t}\n\t\t\tfor i := range constructor.Signature().Results().Len() {\n\t\t\t\ttyp := constructor.Signature().Results().At(i).Type()\n\t\t\t\tvar name string\n\t\t\t\tif i == 0 {\n\t\t\t\t\t// The first return value must be of type T, *T, or a type whose named\n\t\t\t\t\t// type is the same as named type of T.\n\t\t\t\t\tname = varName\n\t\t\t\t} else if i == constructor.Signature().Results().Len()-1 && types.Identical(typ, errorType) {\n\t\t\t\t\tname = \"err\"\n\t\t\t\t} else {\n\t\t\t\t\t// Drop any return values beyond the first and the last.\n\t\t\t\t\t// e.g., \"f, _, _, err := NewFoo()\".\n\t\t\t\t\tname = \"_\"\n\t\t\t\t}\n\t\t\t\tdata.Receiver.Constructor.Results = append(data.Receiver.Constructor.Results, field{\n\t\t\t\t\tName: name,\n\t\t\t\t\tType: types.TypeString(typ, qual),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Resolves duplicate parameter names between the function and its\n\t// receiver's constructor. It adds prefix to the constructor's parameters\n\t// until no conflicts remain.\n\tif data.Receiver != nil && data.Receiver.Constructor != nil {\n\t\tseen := map[string]bool{}\n\t\tfor _, f := range data.Func.Args {\n\t\t\tif f.Name == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[f.Name] = true\n\t\t}\n\n\t\t// \"\" for no change, \"c\" for constructor, \"i\" for input.\n\t\tfor _, prefix := range []string{\"\", \"c\", \"c_\", \"i\", \"i_\"} {\n\t\t\tconflict := false\n\t\t\tfor _, f := range data.Receiver.Constructor.Args {\n\t\t\t\tif f.Name == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif seen[prefix+f.Name] {\n\t\t\t\t\tconflict = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !conflict {\n\t\t\t\tfor i, f := range data.Receiver.Constructor.Args {\n\t\t\t\t\tif f.Name == \"\" {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tdata.Receiver.Constructor.Args[i].Name = prefix + data.Receiver.Constructor.Args[i].Name\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compute edits to update imports.\n\t//\n\t// If we're adding to an existing test file, we need to adjust existing\n\t// imports. Otherwise, we can simply write out the imports to the new file.\n\tif testPGF != nil {\n\t\tvar importFixes []*imports.ImportFix\n\t\tfor path, name := range extraImports {\n\t\t\timportFixes = append(importFixes, &imports.ImportFix{\n\t\t\t\tStmtInfo: imports.ImportInfo{\n\t\t\t\t\tImportPath: path,\n\t\t\t\t\tName:       name,\n\t\t\t\t},\n\t\t\t\tFixType: imports.AddImport,\n\t\t\t})\n\t\t}\n\t\timportEdits, err := ComputeImportFixEdits(snapshot.Options().Local, testPGF.Src, importFixes...)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"could not compute the import fix edits: %w\", err)\n\t\t}\n\t\tedits = append(edits, importEdits...)\n\t} else {\n\t\tvar importsBuffer bytes.Buffer\n\t\tif len(extraImports) == 1 {\n\t\t\timportsBuffer.WriteString(\"\\nimport \")\n\t\t\tfor path, name := range extraImports {\n\t\t\t\tif name != \"\" {\n\t\t\t\t\timportsBuffer.WriteString(name + \" \")\n\t\t\t\t}\n\t\t\t\timportsBuffer.WriteString(fmt.Sprintf(\"\\\"%s\\\"\\n\", path))\n\t\t\t}\n\t\t} else {\n\t\t\timportsBuffer.WriteString(\"\\nimport(\")\n\t\t\t// Sort for determinism.\n\t\t\tfor path, name := range moremaps.Sorted(extraImports) {\n\t\t\t\timportsBuffer.WriteString(\"\\n\\t\")\n\t\t\t\tif name != \"\" {\n\t\t\t\t\timportsBuffer.WriteString(name + \" \")\n\t\t\t\t}\n\t\t\t\timportsBuffer.WriteString(fmt.Sprintf(\"\\\"%s\\\"\", path))\n\t\t\t}\n\t\t\timportsBuffer.WriteString(\"\\n)\\n\")\n\t\t}\n\t\tedits = append(edits, protocol.TextEdit{\n\t\t\tRange:   protocol.Range{},\n\t\t\tNewText: importsBuffer.String(),\n\t\t})\n\t}\n\n\tvar test bytes.Buffer\n\tif err := testTmpl.Execute(&test, data); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tformatted, err := format.Source(test.Bytes())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tedits = append(edits,\n\t\tprotocol.TextEdit{\n\t\t\tRange:   eofRange,\n\t\t\tNewText: string(formatted),\n\t\t},\n\t)\n\n\t// Show the line of generated test function.\n\t{\n\t\tline := eofRange.Start.Line\n\t\tfor i := range len(edits) - 1 { // last edits is the func decl\n\t\t\te := edits[i]\n\t\t\toldLines := e.Range.End.Line - e.Range.Start.Line\n\t\t\tnewLines := uint32(strings.Count(e.NewText, \"\\n\"))\n\t\t\tline += (newLines - oldLines)\n\t\t}\n\t\tshow = &protocol.Location{\n\t\t\tURI: testFH.URI(),\n\t\t\tRange: protocol.Range{\n\t\t\t\t// Test function template have a new line at beginning.\n\t\t\t\tStart: protocol.Position{Line: line + 1},\n\t\t\t\tEnd:   protocol.Position{Line: line + 1},\n\t\t\t},\n\t\t}\n\t}\n\n\treturn append(changes, protocol.DocumentChangeEdit(testFH, edits)), show, nil\n}\n\n// testName returns the name of the function to use for the new function that\n// tests fn.\n// Returns empty string if the fn is ill typed or nil.\nfunc testName(fn *types.Func) (string, error) {\n\tif fn == nil {\n\t\treturn \"\", fmt.Errorf(\"input nil function\")\n\t}\n\ttestName := \"Test\"\n\tif recv := fn.Signature().Recv(); recv != nil { // method declaration.\n\t\t// Retrieve the unpointered receiver type to ensure the test name is based\n\t\t// on the topmost alias or named type, not the alias' RHS type (potentially\n\t\t// unexported) type.\n\t\t// For example:\n\t\t// type Foo = foo // Foo is an exported alias for the unexported type foo\n\t\trecvType := recv.Type()\n\t\tif ptr, ok := recv.Type().(*types.Pointer); ok {\n\t\t\trecvType = ptr.Elem()\n\t\t}\n\n\t\tt, ok := recvType.(typesinternal.NamedOrAlias)\n\t\tif !ok {\n\t\t\treturn \"\", fmt.Errorf(\"receiver type is not named type or alias type\")\n\t\t}\n\n\t\tif !t.Obj().Exported() {\n\t\t\ttestName += \"_\"\n\t\t}\n\n\t\ttestName += t.Obj().Name() + \"_\"\n\t} else if !fn.Exported() { // unexported function declaration.\n\t\ttestName += \"_\"\n\t}\n\treturn testName + fn.Name(), nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/assembly.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file produces the \"Browse GOARCH assembly of f\" HTML report.\n//\n// See also:\n// - ./codeaction.go - computes the symbol and offers the CodeAction command.\n// - ../server/command.go - handles the command by opening a web page.\n// - ../server/server.go - handles the HTTP request and calls this function.\n//\n// For language-server behavior in Go assembly language files,\n// see [golang.org/x/tools/gopls/internal/goasm].\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"html\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/util/morestrings\"\n)\n\n// AssemblyHTML returns an HTML document containing an assembly listing of the selected function.\n//\n// TODO(adonovan): cross-link jumps and block labels, like github.com/aclements/objbrowse.\n//\n// See gopls/internal/test/integration/misc/webserver_test.go for tests.\nfunc AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, w http.ResponseWriter, pkg *cache.Package, symbol string, web Web) {\n\t// Prepare to compile the package with -S, and capture its stderr stream.\n\t// We use \"go test -c\" not \"go build\" as it covers all three packages\n\t// (p, \"p [p.test]\", \"p_test [p.test]\") in the directory, if they exist.\n\t// (See also compileropt.go.)\n\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, pkg.Metadata().CompiledGoFiles[0].DirPath(),\n\t\t\"test\", []string{\n\t\t\t\"-c\",\n\t\t\t\"-o\", os.DevNull,\n\t\t\t\"-gcflags=-S\",\n\t\t\t\".\",\n\t\t})\n\tif err != nil {\n\t\t// e.g. failed to write overlays (rare)\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer cleanupInvocation()\n\n\tescape := html.EscapeString\n\n\t// Emit the start of the report.\n\ttitleHTML := fmt.Sprintf(\"%s assembly for %s\",\n\t\tescape(snapshot.View().GOARCH()),\n\t\tescape(symbol))\n\tio.WriteString(w, `<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>`+titleHTML+`</title>\n  <link rel=\"stylesheet\" href=\"/assets/common.css\">\n  <script src=\"/assets/common.js\"></script>\n</head>\n<body>\n<h1>`+titleHTML+`</h1>\n<p>\n  <a href='https://go.dev/doc/asm'>A Quick Guide to Go's Assembler</a>\n</p>\n<p>\n  Experimental. <a href='https://github.com/golang/go/issues/67478'>Contributions welcome!</a>\n</p>\n<p>\n  Click on a source line marker <code>L1234</code> to navigate your editor there.\n  (VS Code users: please upvote <a href='https://github.com/microsoft/vscode/issues/208093'>#208093</a>)\n</p>\n<p id='compiling'>Compiling...</p>\n<pre>\n`)\n\tif flusher, ok := w.(http.Flusher); ok {\n\t\tflusher.Flush()\n\t}\n\n\t// At this point errors must be reported by writing HTML.\n\t// To do this, set \"status\" return early.\n\n\tvar buf bytes.Buffer\n\tstatus := \"Reload the page to recompile.\"\n\tdefer func() {\n\t\t// Update the \"Compiling...\" message.\n\t\tfmt.Fprintf(&buf, `\n</pre>\n<script>\ndocument.getElementById('compiling').innerText = %q;\n</script>\n</body>`, status)\n\t\tw.Write(buf.Bytes())\n\t}()\n\n\t// Compile the package.\n\t_, stderr, err, _ := snapshot.View().GoCommandRunner().RunRaw(ctx, *inv)\n\tif err != nil {\n\t\tstatus = fmt.Sprintf(\"compilation failed: %v\", err)\n\t\treturn\n\t}\n\n\t// Write the rest of the report.\n\tcontent := stderr.String()\n\n\t// insnRx matches an assembly instruction line.\n\t// Submatch groups are: (offset-hex-dec, file-line-column, instruction).\n\tinsnRx := regexp.MustCompile(`^(\\s+0x[0-9a-f ]+)\\(([^)]*)\\)\\s+(.*)$`)\n\n\t// Parse the functions of interest out of the listing.\n\t// Each function is of the form:\n\t//\n\t//     symbol STEXT k=v...\n\t//         0x0000 00000 (/file.go:123) NOP...\n\t//         ...\n\t//\n\t// Allow matches of symbol, symbol.func1, symbol.deferwrap, etc.\n\ton := false\n\tfor line := range strings.SplitSeq(content, \"\\n\") {\n\t\t// start of function symbol?\n\t\tif strings.Contains(line, \" STEXT \") {\n\t\t\ton = strings.HasPrefix(line, symbol) &&\n\t\t\t\t(line[len(symbol)] == ' ' || line[len(symbol)] == '.')\n\t\t}\n\t\tif !on {\n\t\t\tcontinue // within uninteresting symbol\n\t\t}\n\n\t\t// In lines of the form\n\t\t//   \"\\t0x0000 00000 (/file.go:123) NOP...\"\n\t\t// replace the \"(/file.go:123)\" portion with an \"L0123\" source link.\n\t\t// Skip filenames of the form \"<foo>\".\n\t\tif parts := insnRx.FindStringSubmatch(line); parts != nil {\n\t\t\tlink := \"     \" // if unknown\n\t\t\tif file, linenum, ok := morestrings.CutLast(parts[2], \":\"); ok && !strings.HasPrefix(file, \"<\") {\n\t\t\t\tif linenum, err := strconv.Atoi(linenum); err == nil {\n\t\t\t\t\ttext := fmt.Sprintf(\"L%04d\", linenum)\n\t\t\t\t\tlink = sourceLink(text, web.SrcURL(file, linenum, 1))\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"%s\\t%s\\t%s\", escape(parts[1]), link, escape(parts[3]))\n\t\t} else {\n\t\t\tbuf.WriteString(escape(line))\n\t\t}\n\t\tbuf.WriteByte('\\n')\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/call_hierarchy.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// PrepareCallHierarchy returns an array of CallHierarchyItem for a file and the position within the file.\nfunc PrepareCallHierarchy(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.CallHierarchyItem, error) {\n\tctx, done := event.Start(ctx, \"golang.PrepareCallHierarchy\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobj, err := callHierarchyFuncAtRange(pkg.TypesInfo(), pgf, astutil.RangeOf(start, end))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdeclLoc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn []protocol.CallHierarchyItem{{\n\t\tName:           obj.Name(),\n\t\tKind:           protocol.Function,\n\t\tTags:           []protocol.SymbolTag{},\n\t\tDetail:         callHierarchyItemDetail(obj, declLoc),\n\t\tURI:            declLoc.URI,\n\t\tRange:          declLoc.Range,\n\t\tSelectionRange: declLoc.Range,\n\t}}, nil\n}\n\n// IncomingCalls returns an array of CallHierarchyIncomingCall for a file and the position within the file.\nfunc IncomingCalls(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.CallHierarchyIncomingCall, error) {\n\tctx, done := event.Start(ctx, \"golang.IncomingCalls\")\n\tdefer done()\n\n\trefs, err := references(ctx, snapshot, fh, rng, false)\n\tif err != nil {\n\t\tif errors.Is(err, ErrNoIdentFound) || errors.Is(err, errNoObjectFound) {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\n\t// Group references by their enclosing function declaration.\n\tincomingCalls := make(map[protocol.Location]*protocol.CallHierarchyIncomingCall)\n\tfor _, ref := range refs {\n\t\tcallItem, err := enclosingNodeCallItem(ctx, snapshot, ref.pkgPath, ref.location)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"error getting enclosing node for %q\", ref.pkgPath), err)\n\t\t\tcontinue\n\t\t}\n\t\tloc := callItem.URI.Location(callItem.Range)\n\t\tcall, ok := incomingCalls[loc]\n\t\tif !ok {\n\t\t\tcall = &protocol.CallHierarchyIncomingCall{From: callItem}\n\t\t\tincomingCalls[loc] = call\n\t\t}\n\t\tcall.FromRanges = append(call.FromRanges, ref.location.Range)\n\t}\n\n\t// Flatten the map of pointers into a slice of values.\n\tincomingCallItems := make([]protocol.CallHierarchyIncomingCall, 0, len(incomingCalls))\n\tfor _, callItem := range moremaps.SortedFunc(incomingCalls, protocol.CompareLocation) {\n\t\tincomingCallItems = append(incomingCallItems, *callItem)\n\t}\n\treturn incomingCallItems, nil\n}\n\n// enclosingNodeCallItem creates a CallHierarchyItem representing the function call at loc.\nfunc enclosingNodeCallItem(ctx context.Context, snapshot *cache.Snapshot, pkgPath PackagePath, loc protocol.Location) (protocol.CallHierarchyItem, error) {\n\t// Parse the file containing the reference.\n\tfh, err := snapshot.ReadFile(ctx, loc.URI)\n\tif err != nil {\n\t\treturn protocol.CallHierarchyItem{}, err\n\t}\n\t// TODO(adonovan): opt: before parsing, trim the bodies of functions\n\t// that don't contain the reference, using either a scanner-based\n\t// implementation such as https://go.dev/play/p/KUrObH1YkX8\n\t// (~31% speedup), or a byte-oriented implementation (2x speedup).\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn protocol.CallHierarchyItem{}, err\n\t}\n\tstart, end, err := pgf.RangePos(loc.Range)\n\tif err != nil {\n\t\treturn protocol.CallHierarchyItem{}, err\n\t}\n\n\t// Find the enclosing named function, if any.\n\t//\n\t// It is tempting to treat anonymous functions as nodes in the\n\t// call hierarchy, and historically we used to do that,\n\t// poorly; see #64451. However, it is impossible to track\n\t// references to anonymous functions without much deeper\n\t// analysis. Local analysis is tractable, but ultimately it\n\t// can only detect calls from the outer function to the inner\n\t// function.\n\t//\n\t// It is simpler and clearer to treat the top-level named\n\t// function and all its nested functions as one entity, and it\n\t// allows users to recursively expand the tree where, before,\n\t// the chain would be broken by each lambda.\n\t//\n\t// If the selection is in a global var initializer,\n\t// default to the file's package declaration.\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, start, end)\n\tvar (\n\t\tname = pgf.File.Name.Name\n\t\tkind = protocol.Package\n\t)\n\tstart, end = pgf.File.Name.Pos(), pgf.File.Name.End()\n\tfor _, node := range path {\n\t\tswitch node := node.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tname = node.Name.Name\n\t\t\tstart, end = node.Name.Pos(), node.Name.End()\n\t\t\tkind = protocol.Function\n\n\t\tcase *ast.FuncLit:\n\t\t\t// If the call comes from a FuncLit with\n\t\t\t// no enclosing FuncDecl, then use the\n\t\t\t// FuncLit's extent.\n\t\t\tname = \"func\"\n\t\t\tstart, end = node.Pos(), node.Type.End() // signature, sans body\n\t\t\tkind = protocol.Function\n\n\t\tcase *ast.ValueSpec:\n\t\t\t// If the call comes from a var (or,\n\t\t\t// theoretically, const) initializer outside\n\t\t\t// any function, then use the ValueSpec.Names span.\n\t\t\tname = \"init\"\n\t\t\tstart, end = node.Names[0].Pos(), node.Names[len(node.Names)-1].End()\n\t\t\tkind = protocol.Variable\n\t\t}\n\t}\n\n\trng, err := pgf.PosRange(start, end)\n\tif err != nil {\n\t\treturn protocol.CallHierarchyItem{}, err\n\t}\n\n\treturn protocol.CallHierarchyItem{\n\t\tName:           name,\n\t\tKind:           kind,\n\t\tTags:           []protocol.SymbolTag{},\n\t\tDetail:         fmt.Sprintf(\"%s • %s\", pkgPath, fh.URI().Base()),\n\t\tURI:            loc.URI,\n\t\tRange:          rng,\n\t\tSelectionRange: rng,\n\t}, nil\n}\n\n// OutgoingCalls returns an array of CallHierarchyOutgoingCall for a file and the position within the file.\nfunc OutgoingCalls(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp protocol.Position) ([]protocol.CallHierarchyOutgoingCall, error) {\n\tctx, done := event.Start(ctx, \"golang.OutgoingCalls\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpos, err := pgf.PositionPos(pp)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobj, err := callHierarchyFuncAtRange(pkg.TypesInfo(), pgf, astutil.RangeOf(pos, pos))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif isBuiltin(obj) {\n\t\treturn nil, nil // built-in functions have no outgoing calls\n\t}\n\n\tdeclPkg, declPGF, declPos, err := NarrowestDeclaringPackage(ctx, snapshot, pkg, obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdeclNode, _, _ := findDeclInfo([]*ast.File{declPGF.File}, declPos)\n\tif declNode == nil {\n\t\t// TODO(rfindley): why don't we return an error here, or even bug.Errorf?\n\t\treturn nil, nil\n\t\t// return nil, bug.Errorf(\"failed to find declaration for %v\", obj)\n\t}\n\n\t// Find calls to known functions/methods,\n\t// including interface methods, and built-ins.\n\tvar callRanges []astutil.Range\n\tfor n := range ast.Preorder(declNode) {\n\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\tcallee := typeutil.Callee(pkg.TypesInfo(), call)\n\t\t\tswitch callee.(type) {\n\t\t\tcase *types.Func, *types.Builtin:\n\t\t\t\t// Skip trivial builtins (e.g. len)\n\t\t\t\t// but allow unsafe.Slice, etc.\n\t\t\t\tif callee.Pkg() == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tid := typesinternal.UsedIdent(pkg.TypesInfo(), call.Fun)\n\t\t\t\tcallRanges = append(callRanges, astutil.RangeOf(id.Pos(), id.End()))\n\t\t\t}\n\t\t}\n\t}\n\n\toutgoingCalls := make(map[protocol.Location]*protocol.CallHierarchyOutgoingCall)\n\tfor _, callRange := range callRanges {\n\t\tobj, err := callHierarchyFuncAtRange(declPkg.TypesInfo(), declPGF, callRange)\n\t\tif err != nil {\n\t\t\tcontinue // ignore\n\t\t}\n\n\t\tloc, err := ObjectLocation(ctx, declPkg.FileSet(), snapshot, obj)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\toutgoingCall, ok := outgoingCalls[loc]\n\t\tif !ok {\n\t\t\toutgoingCall = &protocol.CallHierarchyOutgoingCall{\n\t\t\t\tTo: protocol.CallHierarchyItem{\n\t\t\t\t\tName:           obj.Name(),\n\t\t\t\t\tKind:           protocol.Function,\n\t\t\t\t\tTags:           []protocol.SymbolTag{},\n\t\t\t\t\tDetail:         callHierarchyItemDetail(obj, loc),\n\t\t\t\t\tURI:            loc.URI,\n\t\t\t\t\tRange:          loc.Range,\n\t\t\t\t\tSelectionRange: loc.Range,\n\t\t\t\t},\n\t\t\t}\n\t\t\toutgoingCalls[loc] = outgoingCall\n\t\t}\n\n\t\trng, err := declPGF.PosRange(callRange.Pos(), callRange.End())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\toutgoingCall.FromRanges = append(outgoingCall.FromRanges, rng)\n\t}\n\n\toutgoingCallItems := make([]protocol.CallHierarchyOutgoingCall, 0, len(outgoingCalls))\n\tfor _, callItem := range moremaps.SortedFunc(outgoingCalls, protocol.CompareLocation) {\n\t\toutgoingCallItems = append(outgoingCallItems, *callItem)\n\t}\n\treturn outgoingCallItems, nil\n}\n\nfunc callHierarchyItemDetail(obj types.Object, loc protocol.Location) string {\n\tdetail := loc.URI.Base()\n\tif obj.Pkg() != nil {\n\t\tdetail = fmt.Sprintf(\"%s • %s\", obj.Pkg().Path(), detail)\n\t}\n\treturn detail\n}\n\n// callHierarchyFuncAtRange returns the function symbol (Func or Builtin) referred\n// to by the identifier at the specified range.\nfunc callHierarchyFuncAtRange(info *types.Info, pgf *parsego.File, rng astutil.Range) (types.Object, error) {\n\tcur, ok := pgf.Cursor().FindByPos(rng.Pos(), rng.End())\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no enclosing syntax\") // can't happen\n\t}\n\tid, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"identifier not found\")\n\t}\n\tswitch obj := info.ObjectOf(id).(type) {\n\tcase *types.Func, *types.Builtin:\n\t\treturn obj, nil\n\tcase nil:\n\t\treturn nil, fmt.Errorf(\"no symbol here\")\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"%s is not a function\", obj.Name())\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/change_quote.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// convertStringLiteral reports whether we can convert between raw and interpreted\n// string literals in the [start, end) range, along with a CodeAction containing the edits.\n//\n// Only the following conditions are true, the action in result is valid\n//   - [start, end) is enclosed by a string literal\n//   - if the string is interpreted string, need check whether the convert is allowed\nfunc convertStringLiteral(req *codeActionsRequest) {\n\tpath, _ := astutil.PathEnclosingInterval(req.pgf.File, req.start, req.end)\n\tlit, ok := path[0].(*ast.BasicLit)\n\tif !ok || lit.Kind != token.STRING {\n\t\treturn\n\t}\n\n\tstr, err := strconv.Unquote(lit.Value)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tinterpreted := lit.Value[0] == '\"'\n\t// Not all \"...\" strings can be represented as `...` strings.\n\tif interpreted && !strconv.CanBackquote(strings.ReplaceAll(str, \"\\n\", \"\")) {\n\t\treturn\n\t}\n\n\tvar (\n\t\ttitle   string\n\t\tnewText string\n\t)\n\tif interpreted {\n\t\ttitle = \"Convert to raw string literal\"\n\t\tnewText = \"`\" + str + \"`\"\n\t} else {\n\t\ttitle = \"Convert to interpreted string literal\"\n\t\tnewText = strconv.Quote(str)\n\t}\n\n\tstart, end, err := safetoken.Offsets(req.pgf.Tok, lit.Pos(), lit.End())\n\tif err != nil {\n\t\tbug.Reportf(\"failed to get string literal offset by token.Pos:%v\", err)\n\t\treturn\n\t}\n\tedits := []diff.Edit{{\n\t\tStart: start,\n\t\tEnd:   end,\n\t\tNew:   newText,\n\t}}\n\ttextedits, err := protocol.EditsFromDiffEdits(req.pgf.Mapper, edits)\n\tif err != nil {\n\t\tbug.Reportf(\"failed to convert diff.Edit to protocol.TextEdit:%v\", err)\n\t\treturn\n\t}\n\treq.addEditAction(title, nil, protocol.DocumentChangeEdit(req.fh, textedits))\n}\n"
  },
  {
    "path": "gopls/internal/golang/change_signature.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/imports\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// Changing a signature works as follows, supposing we have the following\n// original function declaration:\n//\n//  func Foo(a, b, c int)\n//\n// Step 1: Write the declaration according to the given signature change. For\n// example, given the parameter transformation [2, 0, 1], we construct a new\n// ast.FuncDecl for the signature:\n//\n//   func Foo0(c, a, b int)\n//\n// Step 2: Build a wrapper function that delegates to the new function.\n// With this example, the wrapper would look like this:\n//\n//   func Foo1(a, b, c int) {\n//     Foo0(c, a, b int)\n//   }\n//\n// Step 3: Swap in the wrapper for the original, and inline all calls. The\n// trick here is to rename Foo1 to Foo, inline all calls (replacing them with\n// a call to Foo0), and then rename Foo0 back to Foo, using a simple string\n// replacement.\n//\n// For example, given a call\n//\n// \tfunc _() {\n// \t\tFoo(1, 2, 3)\n// \t}\n//\n// The inlining results in\n//\n// \tfunc _() {\n// \t\tFoo0(3, 1, 2)\n// \t}\n//\n// And then renaming results in\n//\n// \tfunc _() {\n//  \tFoo(3, 1, 2)\n// \t}\n//\n// And the desired signature rewriting has occurred! Note: in practice, we\n// don't use the names Foo0 and Foo1, as they are too likely to conflict with\n// an existing declaration name. (Instead, we use the prefix G_o_ + p_l_s)\n//\n// The advantage of going through the inliner is that we get all of the\n// semantic considerations for free: the inliner will check for side effects\n// of arguments, check if the last use of a variable is being removed, check\n// for unnecessary imports, etc.\n//\n// Furthermore, by running the change signature rewriting through the inliner,\n// we ensure that the inliner gets better to the point that it can handle a\n// change signature rewrite just as well as if we had implemented change\n// signature as its own operation. For example, suppose we support reordering\n// the results of a function. In that case, the wrapper would be:\n//\n// \tfunc Foo1() (int, int) {\n// \t\ty, x := Foo0()\n// \t\treturn x, y\n// \t}\n//\n// And a call would be rewritten from\n//\n// \tx, y := Foo()\n//\n// To\n//\n//  r1, r2 := Foo()\n//  x, y := r2, r1\n//\n// In order to make this idiomatic, we'd have to teach the inliner to rewrite\n// this as y, x := Foo(). The simplest and most general way to achieve this is\n// to teach the inliner to recognize when a variable is redundant (r1 and r2,\n// in this case), lifting declarations. That's probably a very useful skill for\n// the inliner to have.\n\n// removeParam computes a refactoring to remove the parameter indicated by the\n// given range.\nfunc removeParam(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.DocumentChange, error) {\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Find the unused parameter to remove.\n\tinfo := findParam(pgf, rng)\n\tif info == nil || info.paramIndex == -1 {\n\t\treturn nil, fmt.Errorf(\"no param found\")\n\t}\n\t// Write a transformation to remove the param.\n\tvar newParams []int\n\tfor i := 0; i < info.decl.Type.Params.NumFields(); i++ {\n\t\tif i != info.paramIndex {\n\t\t\tnewParams = append(newParams, i)\n\t\t}\n\t}\n\treturn ChangeSignature(ctx, snapshot, pkg, pgf, rng, newParams)\n}\n\n// ChangeSignature computes a refactoring to update the signature according to\n// the provided parameter transformation, for the signature definition\n// surrounding rng.\n//\n// newParams expresses the new parameters for the signature in terms of the old\n// parameters. Each entry in newParams is the index of the new parameter in the\n// original parameter list. For example, given func Foo(a, b, c int) and newParams\n// [2, 0, 1], the resulting changed signature is Foo(c, a, b int). If newParams\n// omits an index of the original signature, that parameter is removed.\n//\n// This operation is a work in progress. Remaining TODO:\n//   - Handle adding parameters.\n//   - Handle adding/removing/reordering results.\n//   - Improve the extra newlines in output.\n//   - Stream type checking via ForEachPackage.\n//   - Avoid unnecessary additional type checking.\nfunc ChangeSignature(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, rng protocol.Range, newParams []int) ([]protocol.DocumentChange, error) {\n\t// Changes to our heuristics for whether we can remove a parameter must also\n\t// be reflected in the canRemoveParameter helper.\n\tif perrors, terrors := pkg.ParseErrors(), pkg.TypeErrors(); len(perrors) > 0 || len(terrors) > 0 {\n\t\tvar sample string\n\t\tif len(perrors) > 0 {\n\t\t\tsample = perrors[0].Error()\n\t\t} else {\n\t\t\tsample = terrors[0].Error()\n\t\t}\n\t\treturn nil, fmt.Errorf(\"can't change signatures for packages with parse or type errors: (e.g. %s)\", sample)\n\t}\n\n\tinfo := findParam(pgf, rng)\n\tif info == nil || info.decl == nil {\n\t\treturn nil, fmt.Errorf(\"failed to find declaration\")\n\t}\n\n\t// Step 1: create the new declaration, which is a copy of the original decl\n\t// with the rewritten signature.\n\n\t// Flatten, transform and regroup fields, using the flatField intermediate\n\t// representation. A flatField is the result of flattening an *ast.FieldList\n\t// along with type information.\n\ttype flatField struct {\n\t\tname     string // empty if the field is unnamed\n\t\ttypeExpr ast.Expr\n\t\ttyp      types.Type\n\t}\n\n\tvar newParamFields []flatField\n\tfor id, field := range astutil.FlatFields(info.decl.Type.Params) {\n\t\ttyp := pkg.TypesInfo().TypeOf(field.Type)\n\t\tif typ == nil {\n\t\t\treturn nil, fmt.Errorf(\"missing field type for field #%d\", len(newParamFields))\n\t\t}\n\t\tfield := flatField{\n\t\t\ttypeExpr: field.Type,\n\t\t\ttyp:      typ,\n\t\t}\n\t\tif id != nil {\n\t\t\tfield.name = id.Name\n\t\t}\n\t\tnewParamFields = append(newParamFields, field)\n\t}\n\n\t// Select the new parameter fields.\n\tnewParamFields, ok := selectElements(newParamFields, newParams)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"failed to apply parameter transformation %v\", newParams)\n\t}\n\n\t// writeFields performs the regrouping of named fields.\n\twriteFields := func(flatFields []flatField) *ast.FieldList {\n\t\tlist := new(ast.FieldList)\n\t\tfor i, f := range flatFields {\n\t\t\tvar field *ast.Field\n\t\t\tif i > 0 && f.name != \"\" && flatFields[i-1].name != \"\" && types.Identical(f.typ, flatFields[i-1].typ) {\n\t\t\t\t// Group named fields if they have the same type.\n\t\t\t\tfield = list.List[len(list.List)-1]\n\t\t\t} else {\n\t\t\t\t// Otherwise, create a new field.\n\t\t\t\tfield = &ast.Field{\n\t\t\t\t\tType: astutil.CloneNode(f.typeExpr),\n\t\t\t\t}\n\t\t\t\tlist.List = append(list.List, field)\n\t\t\t}\n\t\t\tif f.name != \"\" {\n\t\t\t\tfield.Names = append(field.Names, ast.NewIdent(f.name))\n\t\t\t}\n\t\t}\n\t\treturn list\n\t}\n\n\tnewDecl := astutil.CloneNode(info.decl)\n\tnewDecl.Type.Params = writeFields(newParamFields)\n\n\t// Step 2: build a wrapper function calling the new declaration.\n\n\tvar (\n\t\tparams   = astutil.CloneNode(info.decl.Type.Params) // parameters of wrapper func: \"_\" names must be modified\n\t\targs     = make([]ast.Expr, len(newParams))         // arguments to the delegated call\n\t\tvariadic = false                                    // whether the signature is variadic\n\t)\n\t{\n\t\t// Record names used by non-blank parameters, just in case the user had a\n\t\t// parameter named 'blank0', which would conflict with the synthetic names\n\t\t// we construct below.\n\t\t// TODO(rfindley): add an integration test for this behavior.\n\t\tnonBlankNames := make(map[string]bool) // for detecting conflicts with renamed blanks\n\t\tfor _, fld := range params.List {\n\t\t\tfor _, n := range fld.Names {\n\t\t\t\tif n.Name != \"_\" {\n\t\t\t\t\tnonBlankNames[n.Name] = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(fld.Names) == 0 {\n\t\t\t\t// All parameters must have a non-blank name. For convenience, give\n\t\t\t\t// this field a blank name.\n\t\t\t\tfld.Names = append(fld.Names, ast.NewIdent(\"_\")) // will be named below\n\t\t\t}\n\t\t}\n\t\t// oldParams maps parameters to their argument in the delegated call.\n\t\t// In other words, it is the inverse of newParams, but it is represented as\n\t\t// a map rather than a slice, as not every old param need exist in\n\t\t// newParams.\n\t\toldParams := make(map[int]int)\n\t\tfor new, old := range newParams {\n\t\t\toldParams[old] = new\n\t\t}\n\t\tblanks := 0\n\t\tparamIndex := 0 // global param index.\n\t\tfor id, field := range astutil.FlatFields(params) {\n\t\t\targIndex, ok := oldParams[paramIndex]\n\t\t\tparamIndex++\n\t\t\tif !ok {\n\t\t\t\tcontinue // parameter is removed\n\t\t\t}\n\t\t\tif id.Name == \"_\" { // from above: every field has names\n\t\t\t\t// Create names for blank (_) parameters so the delegating wrapper\n\t\t\t\t// can refer to them.\n\t\t\t\tfor {\n\t\t\t\t\t// These names will not be seen by the user, so give them an\n\t\t\t\t\t// arbitrary name.\n\t\t\t\t\tnewName := fmt.Sprintf(\"blank%d\", blanks)\n\t\t\t\t\tblanks++\n\t\t\t\t\tif !nonBlankNames[newName] {\n\t\t\t\t\t\tid.Name = newName\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\targs[argIndex] = ast.NewIdent(id.Name)\n\t\t\t// Record whether the call has an ellipsis.\n\t\t\t// (Only the last loop iteration matters.)\n\t\t\t_, variadic = field.Type.(*ast.Ellipsis)\n\t\t}\n\t}\n\n\t// Step 3: Rewrite all referring calls, by swapping in the wrapper and\n\t// inlining all.\n\n\tnewContent, err := rewriteCalls(ctx, signatureRewrite{\n\t\tsnapshot: snapshot,\n\t\tpkg:      pkg,\n\t\tpgf:      pgf,\n\t\torigDecl: info.decl,\n\t\tnewDecl:  newDecl,\n\t\tparams:   params,\n\t\tcallArgs: args,\n\t\tvariadic: variadic,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Finally, rewrite the original declaration. We do this after inlining all\n\t// calls, as there may be calls in the same file as the declaration. But none\n\t// of the inlining should have changed the location of the original\n\t// declaration.\n\t{\n\t\tidx := findDecl(pgf.File, info.decl)\n\t\tif idx < 0 {\n\t\t\treturn nil, bug.Errorf(\"didn't find original decl\")\n\t\t}\n\n\t\tsrc, ok := newContent[pgf.URI]\n\t\tif !ok {\n\t\t\tsrc = pgf.Src\n\t\t}\n\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\tsrc, err := rewriteSignature(fset, idx, src, newDecl)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tnewContent[pgf.URI] = src\n\t}\n\n\t// Translate the resulting state into document changes.\n\tvar changes []protocol.DocumentChange\n\tfor uri, after := range newContent {\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbefore, err := fh.Content()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tedits := diff.Bytes(before, after)\n\t\tmapper := protocol.NewMapper(uri, before)\n\t\ttextedits, err := protocol.EditsFromDiffEdits(mapper, edits)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"computing edits for %s: %v\", uri, err)\n\t\t}\n\t\tchange := protocol.DocumentChangeEdit(fh, textedits)\n\t\tchanges = append(changes, change)\n\t}\n\treturn changes, nil\n}\n\n// rewriteSignature rewrites the signature of the declIdx'th declaration in src\n// to use the signature of newDecl (described by fset).\n//\n// TODO(rfindley): I think this operation could be generalized, for example by\n// using a concept of a 'nodepath' to correlate nodes between two related\n// files.\n//\n// Note that with its current application, rewriteSignature is expected to\n// succeed. Separate bug.Errorf calls are used below (rather than one call at\n// the callsite) in order to have greater precision.\nfunc rewriteSignature(fset *token.FileSet, declIdx int, src0 []byte, newDecl *ast.FuncDecl) ([]byte, error) {\n\t// Parse the new file0 content, to locate the original params.\n\tfile0, err := parser.ParseFile(fset, \"\", src0, parser.ParseComments|parser.SkipObjectResolution)\n\tif err != nil {\n\t\treturn nil, bug.Errorf(\"re-parsing declaring file failed: %v\", err)\n\t}\n\tdecl0, _ := file0.Decls[declIdx].(*ast.FuncDecl)\n\t// Inlining shouldn't have changed the location of any declarations, but do\n\t// a sanity check.\n\tif decl0 == nil || decl0.Name.Name != newDecl.Name.Name {\n\t\treturn nil, bug.Errorf(\"inlining affected declaration order: found %v, not func %s\", decl0, newDecl.Name.Name)\n\t}\n\topening0, closing0, err := safetoken.Offsets(fset.File(decl0.Pos()), decl0.Type.Params.Opening, decl0.Type.Params.Closing)\n\tif err != nil {\n\t\treturn nil, bug.Errorf(\"can't find params: %v\", err)\n\t}\n\n\t// Format the modified signature and apply a textual replacement. This\n\t// minimizes comment disruption.\n\tformattedType := FormatNode(fset, newDecl.Type)\n\texpr, err := parser.ParseExprFrom(fset, \"\", []byte(formattedType), 0)\n\tif err != nil {\n\t\treturn nil, bug.Errorf(\"parsing modified signature: %v\", err)\n\t}\n\tnewType := expr.(*ast.FuncType)\n\topening1, closing1, err := safetoken.Offsets(fset.File(newType.Pos()), newType.Params.Opening, newType.Params.Closing)\n\tif err != nil {\n\t\treturn nil, bug.Errorf(\"param offsets: %v\", err)\n\t}\n\tnewParams := formattedType[opening1 : closing1+1]\n\n\t// Splice.\n\tvar buf bytes.Buffer\n\tbuf.Write(src0[:opening0])\n\tbuf.WriteString(newParams)\n\tbuf.Write(src0[closing0+1:])\n\tnewSrc := buf.Bytes()\n\tif len(file0.Imports) > 0 {\n\t\tformatted, err := imports.Process(\"output\", newSrc, nil)\n\t\tif err != nil {\n\t\t\treturn nil, bug.Errorf(\"imports.Process failed: %v\", err)\n\t\t}\n\t\tnewSrc = formatted\n\t}\n\treturn newSrc, nil\n}\n\n// paramInfo records information about a param identified by a position.\ntype paramInfo struct {\n\tdecl       *ast.FuncDecl // enclosing func decl (non-nil)\n\tparamIndex int           // index of param among all params, or -1\n\tfield      *ast.Field    // enclosing field of Decl, or nil if range not among parameters\n\tname       *ast.Ident    // indicated name (either enclosing, or Field.Names[0] if len(Field.Names) == 1)\n}\n\n// findParam finds the parameter information spanned by the given range.\nfunc findParam(pgf *parsego.File, rng protocol.Range) *paramInfo {\n\tinfo := paramInfo{paramIndex: -1}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, start, end)\n\tvar (\n\t\tid    *ast.Ident\n\t\tfield *ast.Field\n\t)\n\t// Find the outermost enclosing node of each kind, whether or not they match\n\t// the semantics described in the docstring.\n\tfor _, n := range path {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Ident:\n\t\t\tid = n\n\t\tcase *ast.Field:\n\t\t\tfield = n\n\t\tcase *ast.FuncDecl:\n\t\t\tinfo.decl = n\n\t\t}\n\t}\n\tif info.decl == nil {\n\t\treturn nil\n\t}\n\tif field == nil {\n\t\treturn &info\n\t}\n\tpi := 0\n\t// Search for field and id among parameters of decl.\n\t// This search may fail, even if one or both of id and field are non nil:\n\t// field could be from a result or local declaration, and id could be part of\n\t// the field type rather than names.\n\tfor _, f := range info.decl.Type.Params.List {\n\t\tif f == field {\n\t\t\tinfo.paramIndex = pi // may be modified later\n\t\t\tinfo.field = f\n\t\t\tfor _, n := range f.Names {\n\t\t\t\tif n == id {\n\t\t\t\t\tinfo.paramIndex = pi\n\t\t\t\t\tinfo.name = n\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tpi++\n\t\t\t}\n\t\t\tif info.name == nil && len(info.field.Names) == 1 {\n\t\t\t\tinfo.name = info.field.Names[0]\n\t\t\t}\n\t\t\tbreak\n\t\t} else {\n\t\t\tm := len(f.Names)\n\t\t\tif m == 0 {\n\t\t\t\tm = 1\n\t\t\t}\n\t\t\tpi += m\n\t\t}\n\t}\n\treturn &info\n}\n\n// signatureRewrite defines a rewritten function signature.\n//\n// See rewriteCalls for more details.\ntype signatureRewrite struct {\n\tsnapshot          *cache.Snapshot\n\tpkg               *cache.Package\n\tpgf               *parsego.File\n\torigDecl, newDecl *ast.FuncDecl\n\tparams            *ast.FieldList\n\tcallArgs          []ast.Expr\n\tvariadic          bool\n}\n\n// rewriteCalls returns the document changes required to rewrite the\n// signature of origDecl to that of newDecl.\n//\n// This is a rather complicated factoring of the rewrite operation, but is able\n// to describe arbitrary rewrites. Specifically, rewriteCalls creates a\n// synthetic copy of pkg, where the original function declaration is changed to\n// be a trivial wrapper around the new declaration. params and callArgs are\n// used to perform this delegation: params must have the same type as origDecl,\n// but may have renamed parameters (such as is required for delegating blank\n// parameters). callArgs are the arguments of the delegated call (i.e. using\n// params).\n//\n// For example, consider removing the unused 'b' parameter below, rewriting\n//\n//\tfunc Foo(a, b, c, _ int) int {\n//\t  return a+c\n//\t}\n//\n// To\n//\n//\tfunc Foo(a, c, _ int) int {\n//\t  return a+c\n//\t}\n//\n// In this case, rewriteCalls is parameterized as follows:\n//   - origDecl is the original declaration\n//   - newDecl is the new declaration, which is a copy of origDecl less the 'b'\n//     parameter.\n//   - params is a new parameter list (a, b, c, blank0 int) to be used for the\n//     new wrapper.\n//   - callArgs is the argument list (a, c, blank0), to be used to call the new\n//     delegate.\n//\n// rewriting is expressed this way so that rewriteCalls can own the details\n// of *how* this rewriting is performed. For example, as of writing it names\n// the synthetic delegate G_o_p_l_s_foo, but the caller need not know this.\n//\n// By passing an entirely new declaration, rewriteCalls may be used for\n// signature refactorings that may affect the function body, such as removing\n// or adding return values.\nfunc rewriteCalls(ctx context.Context, rw signatureRewrite) (map[protocol.DocumentURI][]byte, error) {\n\t// tag is a unique prefix that is added to the delegated declaration.\n\t//\n\t// It must have a ~0% probability of causing collisions with existing names.\n\tconst tag = \"G_o_p_l_s_\"\n\n\tvar (\n\t\tmodifiedSrc  []byte\n\t\tmodifiedFile *ast.File\n\t\tmodifiedDecl *ast.FuncDecl\n\t)\n\t{\n\t\tdelegate := astutil.CloneNode(rw.newDecl) // clone before modifying\n\t\tdelegate.Name.Name = tag + delegate.Name.Name\n\t\tif obj := rw.pkg.Types().Scope().Lookup(delegate.Name.Name); obj != nil {\n\t\t\treturn nil, fmt.Errorf(\"synthetic name %q conflicts with an existing declaration\", delegate.Name.Name)\n\t\t}\n\n\t\twrapper := astutil.CloneNode(rw.origDecl)\n\t\twrapper.Type.Params = rw.params\n\n\t\t// Get the receiver name, creating it if necessary.\n\t\tvar recv string // nonempty => call is a method call with receiver recv\n\t\tif wrapper.Recv.NumFields() > 0 {\n\t\t\tif len(wrapper.Recv.List[0].Names) > 0 {\n\t\t\t\trecv = wrapper.Recv.List[0].Names[0].Name\n\t\t\t} else {\n\t\t\t\t// Create unique name for the temporary receiver, which will be inlined away.\n\t\t\t\t//\n\t\t\t\t// We use the lexical scope of the original function to avoid conflicts\n\t\t\t\t// with (e.g.) named result variables. However, since the parameter syntax\n\t\t\t\t// may have been modified/renamed from the original function, we must\n\t\t\t\t// reject those names too.\n\t\t\t\tusedParams := make(map[string]bool)\n\t\t\t\tfor _, fld := range wrapper.Type.Params.List {\n\t\t\t\t\tfor _, name := range fld.Names {\n\t\t\t\t\t\tusedParams[name.Name] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tscope := rw.pkg.TypesInfo().Scopes[rw.origDecl.Type]\n\t\t\t\tif scope == nil {\n\t\t\t\t\treturn nil, bug.Errorf(\"missing function scope for %v\", rw.origDecl.Name.Name)\n\t\t\t\t}\n\t\t\t\tfor i := 0; ; i++ {\n\t\t\t\t\trecv = fmt.Sprintf(\"r%d\", i)\n\t\t\t\t\t_, obj := scope.LookupParent(recv, token.NoPos)\n\t\t\t\t\tif obj == nil && !usedParams[recv] {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twrapper.Recv.List[0].Names = []*ast.Ident{{Name: recv}}\n\t\t\t}\n\t\t}\n\n\t\tname := &ast.Ident{Name: delegate.Name.Name}\n\t\tvar fun ast.Expr = name\n\t\tif recv != \"\" {\n\t\t\tfun = &ast.SelectorExpr{\n\t\t\t\tX:   &ast.Ident{Name: recv},\n\t\t\t\tSel: name,\n\t\t\t}\n\t\t}\n\t\tcall := &ast.CallExpr{\n\t\t\tFun:  fun,\n\t\t\tArgs: rw.callArgs,\n\t\t}\n\t\tif rw.variadic {\n\t\t\tcall.Ellipsis = 1 // must not be token.NoPos\n\t\t}\n\n\t\tvar stmt ast.Stmt\n\t\tif delegate.Type.Results.NumFields() > 0 {\n\t\t\tstmt = &ast.ReturnStmt{\n\t\t\t\tResults: []ast.Expr{call},\n\t\t\t}\n\t\t} else {\n\t\t\tstmt = &ast.ExprStmt{\n\t\t\t\tX: call,\n\t\t\t}\n\t\t}\n\t\twrapper.Body = &ast.BlockStmt{\n\t\t\tList: []ast.Stmt{stmt},\n\t\t}\n\n\t\tfset := tokeninternal.FileSetFor(rw.pgf.Tok)\n\t\tvar err error\n\t\tmodifiedSrc, err = replaceFileDecl(rw.pgf, rw.origDecl, delegate)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// TODO(rfindley): we can probably get away with one fewer parse operations\n\t\t// by returning the modified AST from replaceDecl. Investigate if that is\n\t\t// accurate.\n\t\tmodifiedSrc = append(modifiedSrc, []byte(\"\\n\\n\"+FormatNode(fset, wrapper))...)\n\t\tmodifiedFile, err = parser.ParseFile(rw.pkg.FileSet(), rw.pgf.URI.Path(), modifiedSrc, parser.ParseComments|parser.SkipObjectResolution)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmodifiedDecl = modifiedFile.Decls[len(modifiedFile.Decls)-1].(*ast.FuncDecl)\n\t}\n\n\t// Type check pkg again with the modified file, to compute the synthetic\n\t// callee.\n\tlogf := logger(ctx, \"change signature\", rw.snapshot.Options().VerboseOutput)\n\tpkg2, info, err := reTypeCheck(logf, rw.pkg, map[protocol.DocumentURI]*ast.File{rw.pgf.URI: modifiedFile}, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcalleeInfo, err := inline.AnalyzeCallee(logf, rw.pkg.FileSet(), pkg2, info, modifiedDecl, modifiedSrc)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"analyzing callee: %v\", err)\n\t}\n\n\tpost := func(got []byte) []byte { return bytes.ReplaceAll(got, []byte(tag), nil) }\n\topts := &inline.Options{\n\t\tLogf:          logf,\n\t\tIgnoreEffects: true,\n\t}\n\treturn inlineAllCalls(ctx, rw.snapshot, rw.pkg, rw.pgf, rw.origDecl, calleeInfo, post, opts)\n}\n\n// reTypeCheck re-type checks orig with new file contents defined by fileMask.\n//\n// It expects that any newly added imports are already present in the\n// transitive imports of orig.\n//\n// If expectErrors is true, reTypeCheck allows errors in the new package.\n// TODO(rfindley): perhaps this should be a filter to specify which errors are\n// acceptable.\nfunc reTypeCheck(logf func(string, ...any), orig *cache.Package, fileMask map[protocol.DocumentURI]*ast.File, expectErrors bool) (*types.Package, *types.Info, error) {\n\tpkg := types.NewPackage(string(orig.Metadata().PkgPath), string(orig.Metadata().Name))\n\tinfo := &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\t{\n\t\tvar files []*ast.File\n\t\tfor _, pgf := range orig.CompiledGoFiles() {\n\t\t\tif mask, ok := fileMask[pgf.URI]; ok {\n\t\t\t\tfiles = append(files, mask)\n\t\t\t} else {\n\t\t\t\tfiles = append(files, pgf.File)\n\t\t\t}\n\t\t}\n\n\t\t// Implement a BFS for imports in the transitive package graph.\n\t\t//\n\t\t// Note that this only works if any newly added imports are expected to be\n\t\t// present among transitive imports. In general we cannot assume this to\n\t\t// be the case, but in the special case of removing a parameter it works\n\t\t// because any parameter types must be present in export data.\n\t\tvar importer func(importPath string) (*types.Package, error)\n\t\t{\n\t\t\tvar (\n\t\t\t\timportsByPath = make(map[string]*types.Package) // cached imports\n\t\t\t\ttoSearch      = []*types.Package{orig.Types()}  // packages to search\n\t\t\t\tsearched      = make(map[string]bool)           // path -> (false, if present in toSearch; true, if already searched)\n\t\t\t)\n\t\t\timporter = func(path string) (*types.Package, error) {\n\t\t\t\tif p, ok := importsByPath[path]; ok {\n\t\t\t\t\treturn p, nil\n\t\t\t\t}\n\t\t\t\tfor len(toSearch) > 0 {\n\t\t\t\t\tpkg := toSearch[0]\n\t\t\t\t\ttoSearch = toSearch[1:]\n\t\t\t\t\tsearched[pkg.Path()] = true\n\t\t\t\t\tfor _, p := range pkg.Imports() {\n\t\t\t\t\t\t// TODO(rfindley): this is incorrect: p.Path() is a package path,\n\t\t\t\t\t\t// whereas path is an import path. We can fix this by reporting any\n\t\t\t\t\t\t// newly added imports from inlining, or by using the ImporterFrom\n\t\t\t\t\t\t// interface and package metadata.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// TODO(rfindley): can't the inliner also be wrong here? It's\n\t\t\t\t\t\t// possible that an import path means different things depending on\n\t\t\t\t\t\t// the location.\n\t\t\t\t\t\timportsByPath[p.Path()] = p\n\t\t\t\t\t\tif _, ok := searched[p.Path()]; !ok {\n\t\t\t\t\t\t\tsearched[p.Path()] = false\n\t\t\t\t\t\t\ttoSearch = append(toSearch, p)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif p, ok := importsByPath[path]; ok {\n\t\t\t\t\t\treturn p, nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"missing import\")\n\t\t\t}\n\t\t}\n\t\tcfg := &types.Config{\n\t\t\tSizes:    orig.Metadata().TypesSizes,\n\t\t\tImporter: ImporterFunc(importer),\n\t\t}\n\n\t\t// Copied from cache/check.go.\n\t\t// TODO(rfindley): factor this out and fix goVersionRx.\n\t\t// Set Go dialect.\n\t\tif module := orig.Metadata().Module; module != nil && module.GoVersion != \"\" {\n\t\t\tgoVersion := \"go\" + module.GoVersion\n\t\t\t// types.NewChecker panics if GoVersion is invalid.\n\t\t\t// An unparsable mod file should probably stop us\n\t\t\t// before we get here, but double check just in case.\n\t\t\tif goVersionRx.MatchString(goVersion) {\n\t\t\t\tcfg.GoVersion = goVersion\n\t\t\t}\n\t\t}\n\t\tif expectErrors {\n\t\t\tcfg.Error = func(err error) {\n\t\t\t\tlogf(\"re-type checking: expected error: %v\", err)\n\t\t\t}\n\t\t}\n\t\ttypesinternal.SetUsesCgo(cfg)\n\t\tchecker := types.NewChecker(cfg, orig.FileSet(), pkg, info)\n\t\tif err := checker.Files(files); err != nil && !expectErrors {\n\t\t\treturn nil, nil, fmt.Errorf(\"type checking rewritten package: %v\", err)\n\t\t}\n\t}\n\treturn pkg, info, nil\n}\n\n// TODO(golang/go#63472): this looks wrong with the new Go version syntax.\nvar goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\\.(0|[1-9][0-9]*)$`)\n\n// selectElements returns a new array of elements of s indicated by the\n// provided list of indices. It returns false if any index was out of bounds.\n//\n// For example, given the slice []string{\"a\", \"b\", \"c\", \"d\"}, the\n// indices []int{3, 0, 1} results in the slice []string{\"d\", \"a\", \"b\"}.\nfunc selectElements[T any](s []T, indices []int) ([]T, bool) {\n\tres := make([]T, len(indices))\n\tfor i, index := range indices {\n\t\tif index < 0 || index >= len(s) {\n\t\t\treturn nil, false\n\t\t}\n\t\tres[i] = s[index]\n\t}\n\treturn res, true\n}\n\n// replaceFileDecl replaces old with new in the file described by pgf.\n//\n// TODO(rfindley): generalize, and combine with rewriteSignature.\nfunc replaceFileDecl(pgf *parsego.File, old, new ast.Decl) ([]byte, error) {\n\ti := findDecl(pgf.File, old)\n\tif i == -1 {\n\t\treturn nil, bug.Errorf(\"didn't find old declaration\")\n\t}\n\tstart, end, err := safetoken.Offsets(pgf.Tok, old.Pos(), old.End())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar out bytes.Buffer\n\tout.Write(pgf.Src[:start])\n\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\tif err := format.Node(&out, fset, new); err != nil {\n\t\treturn nil, bug.Errorf(\"formatting new node: %v\", err)\n\t}\n\tout.Write(pgf.Src[end:])\n\treturn out.Bytes(), nil\n}\n\n// findDecl finds the index of decl in file.Decls.\n//\n// TODO: use slices.Index when it is available.\nfunc findDecl(file *ast.File, decl ast.Decl) int {\n\tfor i, d := range file.Decls {\n\t\tif d == decl {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "gopls/internal/golang/code_lens.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n)\n\n// CodeLensSources returns the supported sources of code lenses for Go files.\nfunc CodeLensSources() map[settings.CodeLensSource]cache.CodeLensSourceFunc {\n\treturn map[settings.CodeLensSource]cache.CodeLensSourceFunc{\n\t\tsettings.CodeLensGenerate:      goGenerateCodeLens, // commands: Generate\n\t\tsettings.CodeLensTest:          runTestCodeLens,    // commands: Test\n\t\tsettings.CodeLensRegenerateCgo: regenerateCgoLens,  // commands: RegenerateCgo\n\t}\n}\n\nvar (\n\ttestRe      = regexp.MustCompile(`^Test([^a-z]|$)`) // TestFoo or Test but not Testable\n\tbenchmarkRe = regexp.MustCompile(`^Benchmark([^a-z]|$)`)\n)\n\nfunc runTestCodeLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tvar codeLens []protocol.CodeLens\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttestFuncs, benchFuncs, err := testsAndBenchmarks(pkg.TypesInfo(), pgf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpuri := fh.URI()\n\tfor _, fn := range testFuncs {\n\t\tcmd := command.NewRunTestsCommand(\"run test\", command.RunTestsArgs{\n\t\t\tURI:   puri,\n\t\t\tTests: []string{fn.name},\n\t\t})\n\t\trng := protocol.Range{Start: fn.rng.Start, End: fn.rng.Start}\n\t\tcodeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: cmd})\n\t}\n\n\tfor _, fn := range benchFuncs {\n\t\tcmd := command.NewRunTestsCommand(\"run benchmark\", command.RunTestsArgs{\n\t\t\tURI:        puri,\n\t\t\tBenchmarks: []string{fn.name},\n\t\t})\n\t\trng := protocol.Range{Start: fn.rng.Start, End: fn.rng.Start}\n\t\tcodeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: cmd})\n\t}\n\n\tif len(benchFuncs) > 0 {\n\t\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// add a code lens to the top of the file which runs all benchmarks in the file\n\t\trng, err := pgf.PosRange(pgf.File.Package, pgf.File.Package)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar benches []string\n\t\tfor _, fn := range benchFuncs {\n\t\t\tbenches = append(benches, fn.name)\n\t\t}\n\t\tcmd := command.NewRunTestsCommand(\"run file benchmarks\", command.RunTestsArgs{\n\t\t\tURI:        puri,\n\t\t\tBenchmarks: benches,\n\t\t})\n\t\tcodeLens = append(codeLens, protocol.CodeLens{Range: rng, Command: cmd})\n\t}\n\treturn codeLens, nil\n}\n\ntype testFunc struct {\n\tname string\n\trng  protocol.Range // of *ast.FuncDecl\n}\n\n// testsAndBenchmarks returns all Test and Benchmark functions in the\n// specified file.\nfunc testsAndBenchmarks(info *types.Info, pgf *parsego.File) (tests, benchmarks []testFunc, _ error) {\n\tif !strings.HasSuffix(pgf.URI.Path(), \"_test.go\") {\n\t\treturn nil, nil, nil // empty\n\t}\n\n\tfor _, d := range pgf.File.Decls {\n\t\tfn, ok := d.(*ast.FuncDecl)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\trng, err := pgf.NodeRange(fn)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tif matchTestFunc(fn, info, testRe, \"T\") {\n\t\t\ttests = append(tests, testFunc{fn.Name.Name, rng})\n\t\t} else if matchTestFunc(fn, info, benchmarkRe, \"B\") {\n\t\t\tbenchmarks = append(benchmarks, testFunc{fn.Name.Name, rng})\n\t\t}\n\t}\n\treturn\n}\n\nfunc matchTestFunc(fn *ast.FuncDecl, info *types.Info, nameRe *regexp.Regexp, paramID string) bool {\n\t// Make sure that the function name matches a test function.\n\tif !nameRe.MatchString(fn.Name.Name) {\n\t\treturn false\n\t}\n\tobj, ok := info.ObjectOf(fn.Name).(*types.Func)\n\tif !ok {\n\t\treturn false\n\t}\n\tsig := obj.Signature()\n\t// Test functions should have only one parameter.\n\tif sig.Params().Len() != 1 {\n\t\treturn false\n\t}\n\n\t// Check the type of the only parameter\n\t// (We don't Unalias or use typesinternal.ReceiverNamed\n\t// in the two checks below because \"go test\" can't see\n\t// through aliases when enumerating Test* functions;\n\t// it's syntactic.)\n\tparamTyp, ok := sig.Params().At(0).Type().(*types.Pointer)\n\tif !ok {\n\t\treturn false\n\t}\n\tnamed, ok := paramTyp.Elem().(*types.Named)\n\tif !ok {\n\t\treturn false\n\t}\n\tnamedObj := named.Obj()\n\tif namedObj.Pkg().Path() != \"testing\" {\n\t\treturn false\n\t}\n\treturn namedObj.Id() == paramID\n}\n\nfunc goGenerateCodeLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tconst ggDirective = \"//go:generate\"\n\tfor _, c := range pgf.File.Comments {\n\t\tfor _, l := range c.List {\n\t\t\tif !strings.HasPrefix(l.Text, ggDirective) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trng, err := pgf.PosRange(l.Pos(), l.Pos()+token.Pos(len(ggDirective)))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdir := fh.URI().Dir()\n\t\t\tnonRecursiveCmd := command.NewGenerateCommand(\"run go generate\", command.GenerateArgs{Dir: dir, Recursive: false})\n\t\t\trecursiveCmd := command.NewGenerateCommand(\"run go generate ./...\", command.GenerateArgs{Dir: dir, Recursive: true})\n\t\t\treturn []protocol.CodeLens{\n\t\t\t\t{Range: rng, Command: recursiveCmd},\n\t\t\t\t{Range: rng, Command: nonRecursiveCmd},\n\t\t\t}, nil\n\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc regenerateCgoLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar c *ast.ImportSpec\n\tfor _, imp := range pgf.File.Imports {\n\t\tif imp.Path.Value == `\"C\"` {\n\t\t\tc = imp\n\t\t}\n\t}\n\tif c == nil {\n\t\treturn nil, nil\n\t}\n\trng, err := pgf.NodeRange(c)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpuri := fh.URI()\n\tcmd := command.NewRegenerateCgoCommand(\"regenerate cgo definitions\", command.URIArg{URI: puri})\n\treturn []protocol.CodeLens{{Range: rng, Command: cmd}}, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/codeaction.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillstruct\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillswitch\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang/stubmethods\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// CodeActions returns all enabled code actions (edits and other\n// commands) available for the selected range.\n//\n// Depending on how the request was triggered, fewer actions may be\n// offered, e.g. to avoid UI distractions after mere cursor motion.\n//\n// See ../protocol/codeactionkind.go for some code action theory.\nfunc CodeActions(ctx context.Context, snapshot *cache.Snapshot, opts *settings.Options, fh file.Handle, rng protocol.Range, diagnostics []protocol.Diagnostic, enabled func(protocol.CodeActionKind) bool, trigger protocol.CodeActionTriggerKind) (actions []protocol.CodeAction, _ error) {\n\tloc := fh.URI().Location(rng)\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Scan to see if any enabled producer needs type information.\n\tvar enabledMemo [len(codeActionProducers)]bool\n\tneedTypes := false\n\tfor i, p := range codeActionProducers {\n\t\tif enabled(p.kind) {\n\t\t\tenabledMemo[i] = true\n\t\t\tif p.needPkg {\n\t\t\t\tneedTypes = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compute type information if needed.\n\t// Also update pgf, start, end to be consistent with pkg.\n\t// They may differ in case of parse cache miss.\n\tvar pkg *cache.Package\n\tif needTypes {\n\t\tvar err error\n\t\tpkg, pgf, err = NarrowestPackageForFile(ctx, snapshot, loc.URI)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tstart, end, err = pgf.RangePos(loc.Range)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Execute each enabled producer function.\n\treq := &codeActionsRequest{\n\t\tactions:     &actions,\n\t\tlazy:        make(map[reflect.Type]any),\n\t\tsnapshot:    snapshot,\n\t\toptions:     *opts,\n\t\tfh:          fh,\n\t\tpgf:         pgf,\n\t\tloc:         loc,\n\t\tstart:       start,\n\t\tend:         end,\n\t\tdiagnostics: diagnostics,\n\t\ttrigger:     trigger,\n\t\tpkg:         pkg,\n\t}\n\tfor i, p := range codeActionProducers {\n\t\tif !enabledMemo[i] {\n\t\t\tcontinue\n\t\t}\n\t\treq.kind = p.kind\n\t\tif p.needPkg {\n\t\t\treq.pkg = pkg\n\t\t} else {\n\t\t\treq.pkg = nil\n\t\t}\n\t\tif err := p.fn(ctx, req); err != nil {\n\t\t\t// An error in one code action producer\n\t\t\t// should not affect the others.\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"CodeAction producer %s failed\", p.kind), err)\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// Return code actions in the order their providers are listed.\n\treturn actions, nil\n}\n\n// A codeActionsRequest is passed to each function\n// that produces code actions.\ntype codeActionsRequest struct {\n\t// internal fields for use only by [CodeActions].\n\tactions *[]protocol.CodeAction // pointer to output slice; call addAction to populate\n\tlazy    map[reflect.Type]any   // lazy construction\n\n\t// inputs to the producer function:\n\tkind        protocol.CodeActionKind\n\tsnapshot    *cache.Snapshot\n\toptions     settings.Options\n\tfh          file.Handle\n\tpgf         *parsego.File\n\tloc         protocol.Location\n\tstart, end  token.Pos\n\tdiagnostics []protocol.Diagnostic\n\ttrigger     protocol.CodeActionTriggerKind\n\tpkg         *cache.Package // set only if producer.needPkg\n}\n\n// addApplyFixAction adds an ApplyFix command-based CodeAction to the result.\nfunc (req *codeActionsRequest) addApplyFixAction(title, fix string, loc protocol.Location) {\n\tcmd := command.NewApplyFixCommand(title, command.ApplyFixArgs{\n\t\tFix:          fix,\n\t\tLocation:     loc,\n\t\tResolveEdits: req.resolveEdits(),\n\t})\n\treq.addCommandAction(cmd, true)\n}\n\n// addCommandAction adds a CodeAction to the result based on the provided command.\n//\n// If allowResolveEdits (and the client supports codeAction/resolve)\n// then the command is embedded into the code action data field so\n// that the client can later ask the server to \"resolve\" a command\n// into an edit that they can preview and apply selectively.\n// IMPORTANT: set allowResolveEdits only for actions that are 'edit aware',\n// meaning they can detect when they are being executed in the context of a\n// codeAction/resolve request, and return edits rather than applying them using\n// workspace/applyEdit. In golang/go#71405, edits were being apply during the\n// codeAction/resolve request handler.\n// TODO(rfindley): refactor the command and code lens registration APIs so that\n// resolve edit support is inferred from the command signature, not dependent\n// on coordination between codeAction and command logic.\n//\n// Otherwise, the command is set as the code action operation.\nfunc (req *codeActionsRequest) addCommandAction(cmd *protocol.Command, allowResolveEdits bool) {\n\tact := protocol.CodeAction{\n\t\tTitle: cmd.Title,\n\t\tKind:  req.kind,\n\t}\n\tif allowResolveEdits && req.resolveEdits() {\n\t\tdata, err := json.Marshal(cmd)\n\t\tif err != nil {\n\t\t\tpanic(\"unable to marshal\")\n\t\t}\n\t\tmsg := json.RawMessage(data)\n\t\tact.Data = &msg\n\t} else {\n\t\tact.Command = cmd\n\t}\n\treq.addAction(act)\n}\n\n// addEditAction adds an edit-based CodeAction to the result.\nfunc (req *codeActionsRequest) addEditAction(title string, fixedDiagnostics []protocol.Diagnostic, changes ...protocol.DocumentChange) {\n\treq.addAction(protocol.CodeAction{\n\t\tTitle:       title,\n\t\tKind:        req.kind,\n\t\tDiagnostics: fixedDiagnostics,\n\t\tEdit:        protocol.NewWorkspaceEdit(changes...),\n\t})\n}\n\n// addAction adds a code action to the response.\nfunc (req *codeActionsRequest) addAction(act protocol.CodeAction) {\n\t*req.actions = append(*req.actions, act)\n}\n\n// resolveEdits reports whether the client can resolve edits lazily.\nfunc (req *codeActionsRequest) resolveEdits() bool {\n\topts := req.snapshot.Options()\n\treturn opts.CodeActionResolveOptions != nil &&\n\t\tslices.Contains(opts.CodeActionResolveOptions, \"edit\")\n}\n\n// lazyInit[*T](ctx, req) returns a pointer to an instance of T,\n// calling new(T).init(ctx.req) on the first request.\n//\n// It is conceptually a (generic) method of req.\nfunc lazyInit[P interface {\n\tinit(ctx context.Context, req *codeActionsRequest)\n\t*T\n}, T any](ctx context.Context, req *codeActionsRequest) P {\n\tt := reflect.TypeFor[T]()\n\tv, ok := req.lazy[t].(P)\n\tif !ok {\n\t\tv = new(T)\n\t\tv.init(ctx, req)\n\t\treq.lazy[t] = v\n\t}\n\treturn v\n}\n\n// -- producers --\n\n// A codeActionProducer describes a function that produces CodeActions\n// of a particular kind.\n// The function is only called if that kind is enabled.\ntype codeActionProducer struct {\n\tkind    protocol.CodeActionKind\n\tfn      func(ctx context.Context, req *codeActionsRequest) error\n\tneedPkg bool // fn needs type information (req.pkg)\n}\n\n// Code Actions are returned in the order their producers are listed below.\n// Depending on the client, this may influence the order they appear in the UI.\nvar codeActionProducers = [...]codeActionProducer{\n\t{kind: protocol.QuickFix, fn: quickFix, needPkg: true},\n\t{kind: protocol.SourceOrganizeImports, fn: sourceOrganizeImports},\n\t{kind: settings.AddTest, fn: addTest, needPkg: true},\n\t{kind: settings.GoAssembly, fn: goAssembly, needPkg: true},\n\t{kind: settings.GoDoc, fn: goDoc, needPkg: true},\n\t{kind: settings.GoFreeSymbols, fn: goFreeSymbols},\n\t{kind: settings.GoSplitPackage, fn: goSplitPackage, needPkg: true},\n\t{kind: settings.GoTest, fn: goTest, needPkg: true},\n\t{kind: settings.GoToggleCompilerOptDetails, fn: toggleCompilerOptDetails},\n\t{kind: settings.RefactorExtractFunction, fn: refactorExtractFunction},\n\t{kind: settings.RefactorExtractMethod, fn: refactorExtractMethod},\n\t{kind: settings.RefactorExtractToNewFile, fn: refactorExtractToNewFile},\n\t{kind: settings.RefactorExtractConstant, fn: refactorExtractVariable, needPkg: true},\n\t{kind: settings.RefactorExtractVariable, fn: refactorExtractVariable, needPkg: true},\n\t{kind: settings.RefactorExtractConstantAll, fn: refactorExtractVariableAll, needPkg: true},\n\t{kind: settings.RefactorExtractVariableAll, fn: refactorExtractVariableAll, needPkg: true},\n\t{kind: settings.RefactorInlineCall, fn: refactorInlineCall, needPkg: true},\n\t{kind: settings.RefactorInlineVariable, fn: refactorInlineVariable, needPkg: true},\n\t// {kind: settings.RefactorMoveType, fn: refactorMoveType, needPkg: true},\n\t{kind: settings.RefactorRewriteChangeQuote, fn: refactorRewriteChangeQuote},\n\t{kind: settings.RefactorRewriteFillStruct, fn: refactorRewriteFillStruct, needPkg: true},\n\t{kind: settings.RefactorRewriteFillSwitch, fn: refactorRewriteFillSwitch, needPkg: true},\n\t{kind: settings.RefactorRewriteInvertIf, fn: refactorRewriteInvertIf},\n\t{kind: settings.RefactorRewriteJoinLines, fn: refactorRewriteJoinLines, needPkg: true},\n\t{kind: settings.RefactorRewriteRemoveUnusedParam, fn: refactorRewriteRemoveUnusedParam, needPkg: true},\n\t{kind: settings.RefactorRewriteMoveParamLeft, fn: refactorRewriteMoveParamLeft, needPkg: true},\n\t{kind: settings.RefactorRewriteMoveParamRight, fn: refactorRewriteMoveParamRight, needPkg: true},\n\t{kind: settings.RefactorRewriteSplitLines, fn: refactorRewriteSplitLines, needPkg: true},\n\t{kind: settings.RefactorRewriteEliminateDotImport, fn: refactorRewriteEliminateDotImport, needPkg: true},\n\t{kind: settings.RefactorRewriteAddTags, fn: refactorRewriteAddStructTags, needPkg: true},\n\t{kind: settings.RefactorRewriteRemoveTags, fn: refactorRewriteRemoveStructTags, needPkg: true},\n\t{kind: settings.GoplsDocFeatures, fn: goplsDocFeatures}, // offer this one last (#72742)\n\n\t// Note: don't forget to update the allow-list in Server.CodeAction\n\t// when adding new query operations like GoTest and GoDoc that\n\t// are permitted even in generated source files.\n}\n\n// sourceOrganizeImports produces \"Organize Imports\" code actions.\nfunc sourceOrganizeImports(ctx context.Context, req *codeActionsRequest) error {\n\tres := lazyInit[*allImportsFixesResult](ctx, req)\n\n\t// Send all of the import edits as one code action\n\t// if the file is being organized.\n\tif len(res.allFixEdits) > 0 {\n\t\treq.addEditAction(\"Organize Imports\", nil, protocol.DocumentChangeEdit(req.fh, res.allFixEdits))\n\t}\n\n\treturn nil\n}\n\n// quickFix produces code actions that fix errors,\n// for example by adding/deleting/renaming imports,\n// or declaring the missing methods of a type.\nfunc quickFix(ctx context.Context, req *codeActionsRequest) error {\n\t// Only compute quick fixes if there are any diagnostics to fix.\n\tif len(req.diagnostics) == 0 {\n\t\treturn nil\n\t}\n\n\t// Process any missing imports and pair them with the diagnostics they fix.\n\tres := lazyInit[*allImportsFixesResult](ctx, req)\n\tif res.err != nil {\n\t\treturn nil\n\t}\n\n\t// Separate this into a set of codeActions per diagnostic, where\n\t// each action is the addition, removal, or renaming of one import.\n\tfor _, importFix := range res.editsPerFix {\n\t\tfixedDiags := fixedByImportFix(importFix.fix, req.diagnostics)\n\t\tif len(fixedDiags) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\treq.addEditAction(importFixTitle(importFix.fix), fixedDiags, protocol.DocumentChangeEdit(req.fh, importFix.edits))\n\t}\n\n\t// Quick fixes for type errors.\n\tinfo := req.pkg.TypesInfo()\n\tfor _, typeError := range req.pkg.TypeErrors() {\n\t\t// Does type error overlap with CodeAction range?\n\t\tstart, end := typeError.Pos, typeError.Pos\n\t\tif _, _, endPos, ok := typesinternal.ErrorCodeStartEnd(typeError); ok {\n\t\t\tend = endPos\n\t\t}\n\t\ttypeErrorRange, err := req.pgf.PosRange(start, end)\n\t\tif err != nil || !protocol.Intersect(typeErrorRange, req.loc.Range) {\n\t\t\tcontinue\n\t\t}\n\n\t\tmsg := typeError.Msg\n\t\tswitch {\n\t\t// \"Missing method\" error? (stubmethods)\n\t\t// Offer a \"Declare missing methods of INTERFACE\" code action.\n\t\t// See [stubMissingInterfaceMethodsFixer] for command implementation.\n\t\tcase strings.Contains(msg, \"missing method\"),\n\t\t\tstrings.HasPrefix(msg, \"cannot convert\"),\n\t\t\tstrings.Contains(msg, \"not implement\"):\n\t\t\tsi := stubmethods.GetIfaceStubInfo(req.pkg.FileSet(), info, req.pgf, start, end)\n\t\t\tif si != nil {\n\t\t\t\tqual := typesinternal.FileQualifier(req.pgf.File, si.Concrete.Obj().Pkg())\n\t\t\t\tiface := types.TypeString(si.Interface.Type(), qual)\n\t\t\t\tmsg := fmt.Sprintf(\"Declare missing methods of %s\", iface)\n\t\t\t\treq.addApplyFixAction(msg, fixMissingInterfaceMethods, req.loc)\n\t\t\t}\n\n\t\t// \"type X has no field or method Y\" compiler error.\n\t\t// Offer a \"Declare missing method T.f\" code action.\n\t\t// See [stubMissingCalledFunctionFixer] for command implementation.\n\t\tcase strings.Contains(msg, \"has no field or method\"):\n\t\t\tsi := stubmethods.GetCallStubInfo(req.pkg.FileSet(), info, req.pgf, start, end)\n\t\t\tif si != nil {\n\t\t\t\tmsg := fmt.Sprintf(\"Declare missing method %s.%s\", si.Receiver.Obj().Name(), si.MethodName)\n\t\t\t\treq.addApplyFixAction(msg, fixMissingCalledFunction, req.loc)\n\t\t\t}\n\n\t\t// \"undeclared name: X\" or \"undefined: X\" compiler error.\n\t\t// Offer a \"Create variable/function X\" code action.\n\t\t// See [createUndeclared] for command implementation.\n\t\tcase strings.HasPrefix(msg, \"undeclared name: \"),\n\t\t\tstrings.HasPrefix(msg, \"undefined: \"):\n\t\t\tcur, _ := req.pgf.Cursor().FindByPos(start, end)\n\t\t\ttitle := undeclaredFixTitle(cur, msg)\n\t\t\tif title != \"\" {\n\t\t\t\treq.addApplyFixAction(title, fixCreateUndeclared, req.loc)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// allImportsFixesResult is the result of a lazy call to allImportsFixes.\n// It implements the codeActionsRequest lazyInit interface.\ntype allImportsFixesResult struct {\n\tallFixEdits []protocol.TextEdit\n\teditsPerFix []*importFix\n\terr         error\n}\n\nfunc (res *allImportsFixesResult) init(ctx context.Context, req *codeActionsRequest) {\n\tres.allFixEdits, res.editsPerFix, res.err = allImportsFixes(ctx, req.snapshot, req.pgf)\n\tif res.err != nil {\n\t\tevent.Error(ctx, \"imports fixes\", res.err, label.File.Of(req.loc.URI.Path()))\n\t}\n}\n\nfunc importFixTitle(fix *imports.ImportFix) string {\n\tvar str string\n\tswitch fix.FixType {\n\tcase imports.AddImport:\n\t\tstr = fmt.Sprintf(\"Add import: %s %q\", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)\n\tcase imports.DeleteImport:\n\t\tstr = fmt.Sprintf(\"Delete import: %s %q\", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)\n\tcase imports.SetImportName:\n\t\tstr = fmt.Sprintf(\"Rename import: %s %q\", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)\n\t}\n\treturn str\n}\n\n// fixedByImportFix filters the provided slice of diagnostics to those that\n// would be fixed by the provided imports fix.\nfunc fixedByImportFix(fix *imports.ImportFix, diagnostics []protocol.Diagnostic) []protocol.Diagnostic {\n\tvar results []protocol.Diagnostic\n\tfor _, diagnostic := range diagnostics {\n\t\tswitch {\n\t\t// \"undeclared name: X\" may be an unresolved import.\n\t\tcase strings.HasPrefix(diagnostic.Message, \"undeclared name: \"):\n\t\t\tident := strings.TrimPrefix(diagnostic.Message, \"undeclared name: \")\n\t\t\tif ident == fix.IdentName {\n\t\t\t\tresults = append(results, diagnostic)\n\t\t\t}\n\t\t// \"undefined: X\" may be an unresolved import at Go 1.20+.\n\t\tcase strings.HasPrefix(diagnostic.Message, \"undefined: \"):\n\t\t\tident := strings.TrimPrefix(diagnostic.Message, \"undefined: \")\n\t\t\tif ident == fix.IdentName {\n\t\t\t\tresults = append(results, diagnostic)\n\t\t\t}\n\t\t// \"could not import: X\" may be an invalid import.\n\t\tcase strings.HasPrefix(diagnostic.Message, \"could not import: \"):\n\t\t\tident := strings.TrimPrefix(diagnostic.Message, \"could not import: \")\n\t\t\tif ident == fix.IdentName {\n\t\t\t\tresults = append(results, diagnostic)\n\t\t\t}\n\t\t// \"X imported but not used\" is an unused import.\n\t\t// \"X imported but not used as Y\" is an unused import.\n\t\tcase strings.Contains(diagnostic.Message, \" imported but not used\"):\n\t\t\tidx := strings.Index(diagnostic.Message, \" imported but not used\")\n\t\t\timportPath := diagnostic.Message[:idx]\n\t\t\tif importPath == fmt.Sprintf(\"%q\", fix.StmtInfo.ImportPath) {\n\t\t\t\tresults = append(results, diagnostic)\n\t\t\t}\n\t\t}\n\t}\n\treturn results\n}\n\n// goFreeSymbols produces \"Browse free symbols\" code actions.\n// See [server.commandHandler.FreeSymbols] for command implementation.\nfunc goFreeSymbols(ctx context.Context, req *codeActionsRequest) error {\n\tif !req.loc.Empty() {\n\t\tcmd := command.NewFreeSymbolsCommand(\"Browse free symbols\", req.snapshot.View().ID(), req.loc)\n\t\treq.addCommandAction(cmd, false)\n\t}\n\treturn nil\n}\n\n// goSplitPackage produces \"Split package p\" code actions.\n// See [server.commandHandler.SplitPackage] for command implementation.\nfunc goSplitPackage(ctx context.Context, req *codeActionsRequest) error {\n\t// TODO(adonovan): ideally we would key by the package path,\n\t// or the ID of the widest package for the current file,\n\t// so that we don't see different results when toggling\n\t// between p.go and p_test.go.\n\t//\n\t// TODO(adonovan): opt: req should always provide metadata so\n\t// that we don't have to request type checking (needPkg=true).\n\tmeta := req.pkg.Metadata()\n\ttitle := fmt.Sprintf(\"Split package %q\", meta.Name)\n\tcmd := command.NewSplitPackageCommand(title, req.snapshot.View().ID(), string(meta.ID))\n\treq.addCommandAction(cmd, false)\n\treturn nil\n}\n\n// goplsDocFeatures produces \"Browse gopls feature documentation\" code actions.\n// See [server.commandHandler.ClientOpenURL] for command implementation.\nfunc goplsDocFeatures(ctx context.Context, req *codeActionsRequest) error {\n\tcmd := command.NewClientOpenURLCommand(\n\t\t\"Browse gopls feature documentation\",\n\t\t\"https://go.dev/gopls/features\")\n\treq.addCommandAction(cmd, false)\n\treturn nil\n}\n\n// goDoc produces \"Browse documentation for X\" code actions.\n// See [server.commandHandler.Doc] for command implementation.\nfunc goDoc(ctx context.Context, req *codeActionsRequest) error {\n\t_, _, title := DocFragment(req.pkg, req.pgf, req.start, req.end)\n\tif title != \"\" {\n\t\tcmd := command.NewDocCommand(title, command.DocArgs{Location: req.loc, ShowDocument: true})\n\t\treq.addCommandAction(cmd, false)\n\t}\n\treturn nil\n}\n\n// refactorExtractFunction produces \"Extract function\" code actions.\n// See [extractFunction] for command implementation.\nfunc refactorExtractFunction(ctx context.Context, req *codeActionsRequest) error {\n\tif _, ok, _, _ := canExtractFunction(req.pgf.Cursor(), req.start, req.end); ok {\n\t\treq.addApplyFixAction(\"Extract function\", fixExtractFunction, req.loc)\n\t}\n\treturn nil\n}\n\n// refactorExtractMethod produces \"Extract method\" code actions.\n// See [extractMethod] for command implementation.\nfunc refactorExtractMethod(ctx context.Context, req *codeActionsRequest) error {\n\tif _, ok, methodOK, _ := canExtractFunction(req.pgf.Cursor(), req.start, req.end); ok && methodOK {\n\t\treq.addApplyFixAction(\"Extract method\", fixExtractMethod, req.loc)\n\t}\n\treturn nil\n}\n\n// refactorExtractVariable produces \"Extract variable|constant\" code actions.\n// See [extractVariable] for command implementation.\nfunc refactorExtractVariable(ctx context.Context, req *codeActionsRequest) error {\n\tinfo := req.pkg.TypesInfo()\n\tif curExprs, err := canExtractVariable(info, req.pgf.Cursor(), req.start, req.end, false); err == nil && len(curExprs) > 0 {\n\t\t// Offer one of refactor.extract.{constant,variable}\n\t\t// based on the constness of the expression; this is a\n\t\t// limitation of the codeActionProducers mechanism.\n\t\t// Beware that future evolutions of the refactorings\n\t\t// may make them diverge to become non-complementary,\n\t\t// for example because \"if const x = ...; y {\" is illegal.\n\t\t// Same as [refactorExtractVariableAll].\n\t\texpr0 := curExprs[0].Node().(ast.Expr)\n\t\tconstant := info.Types[expr0].Value != nil\n\t\tif (req.kind == settings.RefactorExtractConstant) == constant {\n\t\t\ttitle := \"Extract variable\"\n\t\t\tif constant {\n\t\t\t\ttitle = \"Extract constant\"\n\t\t\t}\n\t\t\treq.addApplyFixAction(title, fixExtractVariable, req.loc)\n\t\t}\n\t}\n\treturn nil\n}\n\n// refactorExtractVariableAll produces \"Extract N occurrences of EXPR\" code action.\n// See [extractVariable] for implementation.\nfunc refactorExtractVariableAll(ctx context.Context, req *codeActionsRequest) error {\n\tinfo := req.pkg.TypesInfo()\n\t// Don't suggest if only one expr is found,\n\t// otherwise it will duplicate with [refactorExtractVariable]\n\tif curExprs, err := canExtractVariable(info, req.pgf.Cursor(), req.start, req.end, true); err == nil && len(curExprs) > 1 {\n\t\texpr0 := curExprs[0].Node().(ast.Expr)\n\t\ttext, err := req.pgf.NodeText(expr0)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdesc := string(text)\n\t\tif len(desc) >= 40 || strings.Contains(desc, \"\\n\") {\n\t\t\tdesc = goastutil.NodeDescription(expr0)\n\t\t}\n\t\tconstant := info.Types[expr0].Value != nil\n\t\tif (req.kind == settings.RefactorExtractConstantAll) == constant {\n\t\t\tvar title string\n\t\t\tif constant {\n\t\t\t\ttitle = fmt.Sprintf(\"Extract %d occurrences of const expression: %s\", len(curExprs), desc)\n\t\t\t} else {\n\t\t\t\ttitle = fmt.Sprintf(\"Extract %d occurrences of %s\", len(curExprs), desc)\n\t\t\t}\n\t\t\treq.addApplyFixAction(title, fixExtractVariableAll, req.loc)\n\t\t}\n\t}\n\treturn nil\n}\n\n// refactorExtractToNewFile produces \"Extract declarations to new file\" code actions.\n// See [server.commandHandler.ExtractToNewFile] for command implementation.\nfunc refactorExtractToNewFile(ctx context.Context, req *codeActionsRequest) error {\n\tif canExtractToNewFile(req.pgf, req.start, req.end) {\n\t\tcmd := command.NewExtractToNewFileCommand(\"Extract declarations to new file\", req.loc)\n\t\treq.addCommandAction(cmd, false)\n\t}\n\treturn nil\n}\n\n// addTest produces \"Add test for FUNC\" code actions.\n// See [server.commandHandler.AddTest] for command implementation.\nfunc addTest(ctx context.Context, req *codeActionsRequest) error {\n\t// Reject test package.\n\tif req.pkg.Metadata().ForTest != \"\" {\n\t\treturn nil\n\t}\n\n\tpath, _ := goastutil.PathEnclosingInterval(req.pgf.File, req.start, req.end)\n\tif len(path) < 2 {\n\t\treturn nil\n\t}\n\n\tdecl, ok := path[len(path)-2].(*ast.FuncDecl)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// Don't offer to create tests of \"init\" or \"_\".\n\tif decl.Name.Name == \"_\" || decl.Name.Name == \"init\" {\n\t\treturn nil\n\t}\n\n\t// TODO(hxjiang): support functions with type parameter.\n\tif decl.Type.TypeParams != nil {\n\t\treturn nil\n\t}\n\n\tcmd := command.NewAddTestCommand(\"Add test for \"+decl.Name.String(), req.loc)\n\treq.addCommandAction(cmd, false)\n\n\t// TODO(hxjiang): add code action for generate test for package/file.\n\treturn nil\n}\n\n// identityTransform returns a change signature transformation that leaves the\n// given fieldlist unmodified.\nfunc identityTransform(fields *ast.FieldList) []command.ChangeSignatureParam {\n\tvar id []command.ChangeSignatureParam\n\tfor i := 0; i < fields.NumFields(); i++ {\n\t\tid = append(id, command.ChangeSignatureParam{OldIndex: i})\n\t}\n\treturn id\n}\n\n// refactorRewriteRemoveUnusedParam produces \"Remove unused parameter\" code actions.\n// See [server.commandHandler.ChangeSignature] for command implementation.\nfunc refactorRewriteRemoveUnusedParam(ctx context.Context, req *codeActionsRequest) error {\n\tif info := removableParameter(req.pkg, req.pgf, req.loc.Range); info != nil {\n\t\tvar transform []command.ChangeSignatureParam\n\t\tfor i := 0; i < info.decl.Type.Params.NumFields(); i++ {\n\t\t\tif i != info.paramIndex {\n\t\t\t\ttransform = append(transform, command.ChangeSignatureParam{OldIndex: i})\n\t\t\t}\n\t\t}\n\t\tcmd := command.NewChangeSignatureCommand(\"Remove unused parameter\", command.ChangeSignatureArgs{\n\t\t\tLocation:     req.loc,\n\t\t\tNewParams:    transform,\n\t\t\tNewResults:   identityTransform(info.decl.Type.Results),\n\t\t\tResolveEdits: req.resolveEdits(),\n\t\t})\n\t\treq.addCommandAction(cmd, true)\n\t}\n\treturn nil\n}\n\nfunc refactorRewriteMoveParamLeft(ctx context.Context, req *codeActionsRequest) error {\n\tif info := findParam(req.pgf, req.loc.Range); info != nil &&\n\t\tinfo.paramIndex > 0 &&\n\t\t!is[*ast.Ellipsis](info.field.Type) {\n\n\t\t// ^^ we can't currently handle moving a variadic param.\n\t\t// TODO(rfindley): implement.\n\n\t\ttransform := identityTransform(info.decl.Type.Params)\n\t\ttransform[info.paramIndex] = command.ChangeSignatureParam{OldIndex: info.paramIndex - 1}\n\t\ttransform[info.paramIndex-1] = command.ChangeSignatureParam{OldIndex: info.paramIndex}\n\t\tcmd := command.NewChangeSignatureCommand(\"Move parameter left\", command.ChangeSignatureArgs{\n\t\t\tLocation:     req.loc,\n\t\t\tNewParams:    transform,\n\t\t\tNewResults:   identityTransform(info.decl.Type.Results),\n\t\t\tResolveEdits: req.resolveEdits(),\n\t\t})\n\n\t\treq.addCommandAction(cmd, true)\n\t}\n\treturn nil\n}\n\nfunc refactorRewriteMoveParamRight(ctx context.Context, req *codeActionsRequest) error {\n\tif info := findParam(req.pgf, req.loc.Range); info != nil && info.paramIndex >= 0 {\n\t\tparams := info.decl.Type.Params\n\t\tnparams := params.NumFields()\n\t\tif info.paramIndex < nparams-1 { // not the last param\n\t\t\tif info.paramIndex == nparams-2 && is[*ast.Ellipsis](params.List[len(params.List)-1].Type) {\n\t\t\t\t// We can't currently handle moving a variadic param.\n\t\t\t\t// TODO(rfindley): implement.\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\ttransform := identityTransform(info.decl.Type.Params)\n\t\t\ttransform[info.paramIndex] = command.ChangeSignatureParam{OldIndex: info.paramIndex + 1}\n\t\t\ttransform[info.paramIndex+1] = command.ChangeSignatureParam{OldIndex: info.paramIndex}\n\t\t\tcmd := command.NewChangeSignatureCommand(\"Move parameter right\", command.ChangeSignatureArgs{\n\t\t\t\tLocation:     req.loc,\n\t\t\t\tNewParams:    transform,\n\t\t\t\tNewResults:   identityTransform(info.decl.Type.Results),\n\t\t\t\tResolveEdits: req.resolveEdits(),\n\t\t\t})\n\t\t\treq.addCommandAction(cmd, true)\n\t\t}\n\t}\n\treturn nil\n}\n\n// refactorRewriteChangeQuote produces \"Convert to {raw,interpreted} string literal\" code actions.\nfunc refactorRewriteChangeQuote(ctx context.Context, req *codeActionsRequest) error {\n\tconvertStringLiteral(req)\n\treturn nil\n}\n\n// refactorRewriteInvertIf produces \"Invert 'if' condition\" code actions.\n// See [invertIfCondition] for command implementation.\nfunc refactorRewriteInvertIf(ctx context.Context, req *codeActionsRequest) error {\n\tif _, ok, _ := canInvertIfCondition(req.pgf.Cursor(), req.start, req.end); ok {\n\t\treq.addApplyFixAction(\"Invert 'if' condition\", fixInvertIfCondition, req.loc)\n\t}\n\treturn nil\n}\n\n// refactorRewriteSplitLines produces \"Split ITEMS into separate lines\" code actions.\n// See [splitLines] for command implementation.\nfunc refactorRewriteSplitLines(ctx context.Context, req *codeActionsRequest) error {\n\t// TODO(adonovan): opt: don't set needPkg just for FileSet.\n\tif msg, ok, _ := canSplitLines(req.pgf.Cursor(), req.pkg.FileSet(), req.start, req.end); ok {\n\t\treq.addApplyFixAction(msg, fixSplitLines, req.loc)\n\t}\n\treturn nil\n}\n\nfunc refactorRewriteEliminateDotImport(ctx context.Context, req *codeActionsRequest) error {\n\t// Figure out if the request is placed over a dot import.\n\tvar importSpec *ast.ImportSpec\n\tfor _, imp := range req.pgf.File.Imports {\n\t\tif posRangeContains(imp.Pos(), imp.End(), req.start, req.end) {\n\t\t\timportSpec = imp\n\t\t\tbreak\n\t\t}\n\t}\n\tif importSpec == nil {\n\t\treturn nil\n\t}\n\tif importSpec.Name == nil || importSpec.Name.Name != \".\" {\n\t\treturn nil\n\t}\n\n\t// dotImported package path and its imported name after removing the dot.\n\tpkgname := req.pkg.TypesInfo().PkgNameOf(importSpec)\n\tif pkgname == nil {\n\t\treturn nil // e.g. import . \"C\"\n\t}\n\timported := pkgname.Imported()\n\tnewName := imported.Name()\n\n\trng, err := req.pgf.PosRange(importSpec.Name.Pos(), importSpec.Path.Pos())\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Delete the '.' part of the import.\n\tedits := []protocol.TextEdit{{\n\t\tRange: rng,\n\t}}\n\n\tfileScope, ok := req.pkg.TypesInfo().Scopes[req.pgf.File]\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// Go through each use of the dot imported package, checking its scope for\n\t// shadowing and calculating an edit to qualify the identifier.\n\tfor curId := range req.pgf.Cursor().Preorder((*ast.Ident)(nil)) {\n\t\tident := curId.Node().(*ast.Ident)\n\n\t\t// Only keep identifiers that use a symbol from the\n\t\t// dot imported package.\n\t\tuse := req.pkg.TypesInfo().Uses[ident]\n\t\tif use == nil || use.Pkg() == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif use.Pkg() != imported {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Only qualify unqualified identifiers (due to dot imports)\n\t\t// that reference package-level symbols.\n\t\t// All other references to a symbol imported from another package\n\t\t// are nested within a select expression (pkg.Foo, v.Method, v.Field).\n\t\tif curId.ParentEdgeKind() == edge.SelectorExpr_Sel {\n\t\t\tcontinue // qualified identifier (pkg.X) or selector (T.X or e.X)\n\t\t}\n\t\tif !typesinternal.IsPackageLevel(use) {\n\t\t\tcontinue // unqualified field reference T{X: ...}\n\t\t}\n\n\t\t// Make sure that the package name will not be shadowed by something else in scope.\n\t\t// If it is then we cannot offer this particular code action.\n\t\t//\n\t\t// TODO: If the object found in scope is the package imported without a\n\t\t// dot, or some builtin not used in the file, the code action could be\n\t\t// allowed to go through.\n\t\tsc := fileScope.Innermost(ident.Pos())\n\t\tif sc == nil {\n\t\t\tcontinue\n\t\t}\n\t\t_, obj := sc.LookupParent(newName, ident.Pos())\n\t\tif obj != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\trng, err := req.pgf.PosRange(ident.Pos(), ident.Pos()) // sic, zero-width range before ident\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tedits = append(edits, protocol.TextEdit{\n\t\t\tRange:   rng,\n\t\t\tNewText: newName + \".\",\n\t\t})\n\t}\n\n\treq.addEditAction(\"Eliminate dot import\", nil, protocol.DocumentChangeEdit(\n\t\treq.fh,\n\t\tedits,\n\t))\n\treturn nil\n}\n\n// refactorRewriteJoinLines produces \"Join ITEMS into one line\" code actions.\n// See [joinLines] for command implementation.\nfunc refactorRewriteJoinLines(ctx context.Context, req *codeActionsRequest) error {\n\t// TODO(adonovan): opt: don't set needPkg just for FileSet.\n\tif msg, ok, _ := canJoinLines(req.pgf.Cursor(), req.pkg.FileSet(), req.start, req.end); ok {\n\t\treq.addApplyFixAction(msg, fixJoinLines, req.loc)\n\t}\n\treturn nil\n}\n\n// refactorRewriteFillStruct produces \"Fill STRUCT\" code actions.\n// See [fillstruct.SuggestedFix] for command implementation.\nfunc refactorRewriteFillStruct(ctx context.Context, req *codeActionsRequest) error {\n\t// fillstruct.Diagnose is a lazy analyzer: all it gives us is\n\t// the (start, end, message) of each SuggestedFix; the actual\n\t// edit is computed only later by ApplyFix, which calls fillstruct.SuggestedFix.\n\tfor _, diag := range fillstruct.Diagnose(req.pgf.File, req.start, req.end, req.pkg.Types(), req.pkg.TypesInfo()) {\n\t\tloc, err := req.pgf.Mapper.PosLocation(req.pgf.Tok, diag.Pos, diag.End)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, fix := range diag.SuggestedFixes {\n\t\t\treq.addApplyFixAction(fix.Message, diag.Category, loc)\n\t\t}\n\t}\n\treturn nil\n}\n\n// refactorRewriteFillSwitch produces \"Add cases for TYPE/ENUM\" code actions.\nfunc refactorRewriteFillSwitch(ctx context.Context, req *codeActionsRequest) error {\n\tfor _, diag := range fillswitch.Diagnose(req.pgf.File, req.start, req.end, req.pkg.Types(), req.pkg.TypesInfo()) {\n\t\tchanges, err := suggestedFixToDocumentChange(ctx, req.snapshot, req.pkg.FileSet(), &diag.SuggestedFixes[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treq.addEditAction(diag.Message, nil, changes...)\n\t}\n\n\treturn nil\n}\n\n// selectionContainsStructField returns true if the given struct contains a\n// field between start and end pos. If needsTag is true, it only returns true if\n// the struct field found contains a struct tag.\nfunc selectionContainsStructField(node *ast.StructType, start, end token.Pos, needsTag bool) bool {\n\tfor _, field := range node.Fields.List {\n\t\tif start <= field.End() && end >= field.Pos() {\n\t\t\tif !needsTag || field.Tag != nil {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// selectionContainsStruct returns true if there exists a struct containing\n// fields within start and end positions. If removeTags is true, it means the\n// current command is for remove tags rather than add tags, so we only return\n// true if the struct field found contains a struct tag to remove.\nfunc selectionContainsStruct(cursor inspector.Cursor, start, end token.Pos, removeTags bool) bool {\n\tcur, ok := cursor.FindByPos(start, end)\n\tif !ok {\n\t\treturn false\n\t}\n\tif _, ok := cur.Node().(*ast.StructType); ok {\n\t\treturn true\n\t}\n\n\t// Handles case where selection is within struct.\n\tfor c := range cur.Enclosing((*ast.StructType)(nil)) {\n\t\tif selectionContainsStructField(c.Node().(*ast.StructType), start, end, removeTags) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Handles case where selection contains struct but may contain other nodes, including other structs.\n\tfor c := range cur.Preorder((*ast.StructType)(nil)) {\n\t\tnode := c.Node().(*ast.StructType)\n\t\t// Check that at least one field is located within the selection. If we are removing tags, that field\n\t\t// must also have a struct tag, otherwise we do not provide the code action.\n\t\tif selectionContainsStructField(node, start, end, removeTags) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// supportsDialog reports whether the client supports interactive UI dialogs.\n// If specific [settings.InteractiveInputType]s are provided, it also verifies that\n// the client explicitly supports every requested input type.\nfunc supportsDialog(req *codeActionsRequest, need ...settings.InteractiveInputType) bool {\n\t// TODO(pjw): this would be better if it checked the actual form, e.g., server.AddTagsForm\n\t// rather than the types, but that would cause an imports loop.\n\to := req.options.ClientOptions.SupportedInteractiveInputTypes\n\tif o == nil {\n\t\treturn false\n\t}\n\tfor _, n := range need {\n\t\tif !o[n] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// refactorRewriteAddStructTags produces \"Add struct tags\" code actions.\n// See [server.commandHandler.ModifyTags] for command implementation.\nfunc refactorRewriteAddStructTags(ctx context.Context, req *codeActionsRequest) error {\n\tif selectionContainsStruct(req.pgf.Cursor(), req.start, req.end, false) {\n\t\tadd := \"\"\n\t\tif !supportsDialog(req) {\n\t\t\tadd = \"json\" // default choice\n\t\t}\n\t\tcmdAdd := command.NewModifyTagsCommand(\"Add struct tags\", command.ModifyTagsArgs{\n\t\t\tModification: \"add\",\n\t\t\tURI:          req.loc.URI,\n\t\t\tRange:        req.loc.Range,\n\t\t\tAdd:          add,\n\t\t})\n\t\treq.addCommandAction(cmdAdd, false)\n\t}\n\treturn nil\n}\n\n// refactorRewriteRemoveStructTags produces \"Remove struct tags\" code actions.\n// See [server.commandHandler.ModifyTags] for command implementation.\nfunc refactorRewriteRemoveStructTags(ctx context.Context, req *codeActionsRequest) error {\n\tif selectionContainsStruct(req.pgf.Cursor(), req.start, req.end, true) {\n\t\tclear := !supportsDialog(req) // clear the entry if there is no dialog\n\t\tcmdRemove := command.NewModifyTagsCommand(\"Remove struct tags\", command.ModifyTagsArgs{\n\t\t\tModification: \"remove\",\n\t\t\tURI:          req.loc.URI,\n\t\t\tRange:        req.loc.Range,\n\t\t\tClear:        clear,\n\t\t})\n\t\treq.addCommandAction(cmdRemove, false)\n\t}\n\treturn nil\n}\n\n// removableParameter returns paramInfo about a removable parameter indicated\n// by the given [start, end) range, or nil if no such removal is available.\n//\n// Removing a parameter is possible if\n//   - there are no parse or type errors, and\n//   - [start, end) is contained within an unused field or parameter name\n//   - ... of a non-method function declaration.\n//\n// (Note that the unusedparam analyzer also computes this property, but\n// much more precisely, allowing it to report its findings as diagnostics.)\n//\n// TODO(adonovan): inline into refactorRewriteRemoveUnusedParam.\nfunc removableParameter(pkg *cache.Package, pgf *parsego.File, rng protocol.Range) *paramInfo {\n\tif perrors, terrors := pkg.ParseErrors(), pkg.TypeErrors(); len(perrors) > 0 || len(terrors) > 0 {\n\t\treturn nil // can't remove parameters from packages with errors\n\t}\n\tinfo := findParam(pgf, rng)\n\tif info == nil || info.field == nil {\n\t\treturn nil // range does not span a parameter\n\t}\n\tif info.decl.Body == nil {\n\t\treturn nil // external function\n\t}\n\tif len(info.field.Names) == 0 {\n\t\treturn info // no names => field is unused\n\t}\n\tif info.name == nil {\n\t\treturn nil // no name is indicated\n\t}\n\tif info.name.Name == \"_\" {\n\t\treturn info // trivially unused\n\t}\n\n\tobj := pkg.TypesInfo().Defs[info.name]\n\tif obj == nil {\n\t\treturn nil // something went wrong\n\t}\n\n\tused := false\n\tast.Inspect(info.decl.Body, func(node ast.Node) bool {\n\t\tif n, ok := node.(*ast.Ident); ok && pkg.TypesInfo().Uses[n] == obj {\n\t\t\tused = true\n\t\t}\n\t\treturn !used // keep going until we find a use\n\t})\n\tif used {\n\t\treturn nil\n\t}\n\treturn info\n}\n\n// refactorInlineCall produces \"Inline call to FUNC\" code actions.\n// See [inlineCall] for command implementation.\nfunc refactorInlineCall(ctx context.Context, req *codeActionsRequest) error {\n\t// To avoid distraction (e.g. VS Code lightbulb), offer \"inline\"\n\t// only after a selection or explicit menu operation.\n\t// TODO(adonovan): remove this (and req.trigger); see comment at TestVSCodeIssue65167.\n\tif req.trigger == protocol.CodeActionAutomatic && req.loc.Empty() {\n\t\treturn nil\n\t}\n\n\t// If range is within call expression, offer to inline the call.\n\tif _, fn, err := enclosingStaticCall(req.pkg, req.pgf, req.start, req.end); err == nil {\n\t\treq.addApplyFixAction(\"Inline call to \"+fn.Name(), fixInlineCall, req.loc)\n\t}\n\treturn nil\n}\n\n// refactorInlineVariable produces the \"Inline variable 'v'\" code action.\n// See [inlineVariableOne] for command implementation.\nfunc refactorInlineVariable(ctx context.Context, req *codeActionsRequest) error {\n\t// TODO(adonovan): offer \"inline all\" variant that eliminates the var (see #70085).\n\tif curUse, _, ok := canInlineVariable(req.pkg.TypesInfo(), req.pgf.Cursor(), req.start, req.end); ok {\n\t\ttitle := fmt.Sprintf(\"Inline variable %q\", curUse.Node().(*ast.Ident).Name)\n\t\treq.addApplyFixAction(title, fixInlineVariable, req.loc)\n\t}\n\treturn nil\n}\n\n// goTest produces \"Run tests and benchmarks\" code actions.\n// See [server.commandHandler.runTests] for command implementation.\nfunc goTest(ctx context.Context, req *codeActionsRequest) error {\n\ttestFuncs, benchFuncs, err := testsAndBenchmarks(req.pkg.TypesInfo(), req.pgf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar tests, benchmarks []string\n\tfor _, fn := range testFuncs {\n\t\tif protocol.Intersect(fn.rng, req.loc.Range) {\n\t\t\ttests = append(tests, fn.name)\n\t\t}\n\t}\n\tfor _, fn := range benchFuncs {\n\t\tif protocol.Intersect(fn.rng, req.loc.Range) {\n\t\t\tbenchmarks = append(benchmarks, fn.name)\n\t\t}\n\t}\n\n\tif len(tests) == 0 && len(benchmarks) == 0 {\n\t\treturn nil\n\t}\n\n\tcmd := command.NewRunTestsCommand(\"Run tests and benchmarks\", command.RunTestsArgs{\n\t\tURI:        req.loc.URI,\n\t\tTests:      tests,\n\t\tBenchmarks: benchmarks,\n\t})\n\treq.addCommandAction(cmd, false)\n\treturn nil\n}\n\n// goAssembly produces \"Browse ARCH assembly for FUNC\" code actions.\n// See [server.commandHandler.Assembly] for command implementation.\nfunc goAssembly(ctx context.Context, req *codeActionsRequest) error {\n\tview := req.snapshot.View()\n\n\t// Find the enclosing toplevel function or method,\n\t// and compute its symbol name (e.g. \"pkgpath.(T).method\").\n\t// The report will show this method and all its nested\n\t// functions (FuncLit, defers, etc).\n\t//\n\t// TODO(adonovan): this is no good for generics, since they\n\t// will always be uninstantiated when they enclose the cursor.\n\t// Instead, we need to query the func symbol under the cursor,\n\t// rather than the enclosing function. It may be an explicitly\n\t// or implicitly instantiated generic, and it may be defined\n\t// in another package, though we would still need to compile\n\t// the current package to see its assembly. The challenge,\n\t// however, is that computing the linker name for a generic\n\t// symbol is quite tricky. Talk with the compiler team for\n\t// ideas.\n\t//\n\t// TODO(adonovan): think about a smoother UX for jumping\n\t// directly to (say) a lambda of interest.\n\t// Perhaps we could scroll to STEXT for the innermost\n\t// enclosing nested function?\n\n\t// Compute the linker symbol of the enclosing function or var initializer.\n\tvar sym strings.Builder\n\tif pkg := req.pkg.Types(); pkg.Name() == \"main\" {\n\t\tsym.WriteString(\"main\")\n\t} else {\n\t\tsym.WriteString(pkg.Path())\n\t}\n\tsym.WriteString(\".\")\n\n\tcurSel, _ := req.pgf.Cursor().FindByPos(req.start, req.end)\n\tfor cur := range curSel.Enclosing((*ast.FuncDecl)(nil), (*ast.ValueSpec)(nil)) {\n\t\tvar name string // in command title\n\t\tswitch node := cur.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\t// package-level func or method\n\t\t\tif fn, ok := req.pkg.TypesInfo().Defs[node.Name].(*types.Func); ok &&\n\t\t\t\tfn.Name() != \"_\" { // blank functions are not compiled\n\n\t\t\t\t// Source-level init functions are compiled (along with\n\t\t\t\t// package-level var initializers) in into a single pkg.init\n\t\t\t\t// function, so this falls out of the logic below.\n\n\t\t\t\tif sig := fn.Signature(); sig.TypeParams() == nil && sig.RecvTypeParams() == nil { // generic => no assembly\n\t\t\t\t\tif sig.Recv() != nil {\n\t\t\t\t\t\tif isPtr, named := typesinternal.ReceiverNamed(sig.Recv()); named != nil {\n\t\t\t\t\t\t\tif isPtr {\n\t\t\t\t\t\t\t\tfmt.Fprintf(&sym, \"(*%s)\", named.Obj().Name())\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsym.WriteString(named.Obj().Name())\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsym.WriteByte('.')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsym.WriteString(fn.Name())\n\n\t\t\t\t\tname = node.Name.Name // success\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.ValueSpec:\n\t\t\t// package-level var initializer?\n\t\t\tif len(node.Names) > 0 && len(node.Values) > 0 {\n\t\t\t\tv := req.pkg.TypesInfo().Defs[node.Names[0]]\n\t\t\t\tif v != nil && typesinternal.IsPackageLevel(v) {\n\t\t\t\t\tsym.WriteString(\"init\")\n\t\t\t\t\tname = \"package initializer\" // success\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif name != \"\" {\n\t\t\tcmd := command.NewAssemblyCommand(\n\t\t\t\tfmt.Sprintf(\"Browse %s assembly for %s\", view.GOARCH(), name),\n\t\t\t\tview.ID(),\n\t\t\t\tstring(req.pkg.Metadata().ID),\n\t\t\t\tsym.String())\n\t\t\treq.addCommandAction(cmd, false)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn nil\n}\n\n// toggleCompilerOptDetails produces \"{Show,Hide} compiler optimization details\" code action.\n// See [server.commandHandler.GCDetails] for command implementation.\nfunc toggleCompilerOptDetails(ctx context.Context, req *codeActionsRequest) error {\n\t// TODO(adonovan): errors from code action providers should probably be\n\t// logged, even if they aren't visible to the client; see https://go.dev/issue/71275.\n\tif meta, err := req.snapshot.NarrowestMetadataForFile(ctx, req.fh.URI()); err == nil {\n\t\tif len(meta.CompiledGoFiles) == 0 {\n\t\t\treturn fmt.Errorf(\"package %q does not compile file %q\", meta.ID, req.fh.URI())\n\t\t}\n\t\tdir := meta.CompiledGoFiles[0].Dir()\n\n\t\ttitle := fmt.Sprintf(\"%s compiler optimization details for %q\",\n\t\t\tcond(req.snapshot.WantCompilerOptDetails(dir), \"Hide\", \"Show\"),\n\t\t\tdir.Base())\n\t\tcmd := command.NewGCDetailsCommand(title, req.fh.URI())\n\t\treq.addCommandAction(cmd, false)\n\t}\n\treturn nil\n}\n\n// (this function is unused)\nfunc refactorMoveType(_ context.Context, req *codeActionsRequest) error {\n\tcurSel, _ := req.pgf.Cursor().FindByPos(req.start, req.end)\n\tif _, _, _, typeName, ok := selectionContainsType(curSel); ok {\n\t\tcmd := command.NewMoveTypeCommand(fmt.Sprintf(\"Move type %s\", typeName), command.MoveTypeArgs{Location: req.loc})\n\t\treq.addCommandAction(cmd, false)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/comment.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/doc/comment\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\tpathpkg \"path\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nvar errNoCommentReference = errors.New(\"no comment reference found\")\n\n// DocCommentToMarkdown converts the text of a [doc comment] to Markdown.\n//\n// TODO(adonovan): provide a package (or file imports) as context for\n// proper rendering of doc links; see [newDocCommentParser] and golang/go#61677.\n//\n// [doc comment]: https://go.dev/doc/comment\nfunc DocCommentToMarkdown(text string, options *settings.Options) string {\n\tvar parser comment.Parser\n\tdoc := parser.Parse(text)\n\n\tvar printer comment.Printer\n\t// The default produces {#Hdr-...} tags for headings.\n\t// vscode displays thems, which is undesirable.\n\t// The godoc for comment.Printer says the tags\n\t// avoid a security problem.\n\tprinter.HeadingID = func(*comment.Heading) string { return \"\" }\n\tprinter.DocLinkURL = func(link *comment.DocLink) string {\n\t\tmsg := fmt.Sprintf(\"https://%s/%s\", options.LinkTarget, link.ImportPath)\n\t\tif link.Name != \"\" {\n\t\t\tmsg += \"#\"\n\t\t\tif link.Recv != \"\" {\n\t\t\t\tmsg += link.Recv + \".\"\n\t\t\t}\n\t\t\tmsg += link.Name\n\t\t}\n\t\treturn msg\n\t}\n\n\treturn string(printer.Markdown(doc))\n}\n\n// docLinkDefinition finds the definition of the doc link in comments at pos.\n// If there is no reference at pos, returns errNoCommentReference.\n//\n// TODO(hxjiang): simplify the error handling.\nfunc docLinkDefinition(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) ([]protocol.Location, error) {\n\tobj, _, err := resolveDocLink(pkg, pgf, astutil.RangeOf(start, end))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tloc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn []protocol.Location{loc}, nil\n}\n\n// resolveDocLink parses a doc link in a comment such as [fmt.Println]\n// and returns the symbol at pos, along with the link's range.\nfunc resolveDocLink(pkg *cache.Package, pgf *parsego.File, rng astutil.Range) (types.Object, protocol.Range, error) {\n\tvar comment *ast.CommentGroup\n\tfor _, c := range pgf.File.Comments {\n\t\tif astutil.NodeContains(c, rng) {\n\t\t\tcomment = c\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif comment == nil {\n\t\treturn nil, protocol.Range{}, errNoCommentReference\n\t}\n\n\tfor docLink := range commentDocLinks(comment) {\n\t\tif astutil.NodeContains(docLink.partRange, rng) {\n\t\t\tif obj := lookupDocLinkSymbol(pkg, pgf, docLink.nameText); obj != nil {\n\t\t\t\trng, err := pgf.NodeRange(docLink.partRange)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, protocol.Range{}, err\n\t\t\t\t}\n\t\t\t\treturn obj, rng, nil\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil, protocol.Range{}, errNoCommentReference\n}\n\n// A docLink holds the parsed information for a single resolution step of a\n// documentation link. For a link like \"[fmt.Scanner.Scan]\", the parser will\n// yield three docLink values, one for each progressively resolved part:\n// \"fmt\", \"fmt.Scanner\", and \"fmt.Scanner.Scan\".\ntype docLink struct {\n\t// The text of the right-most component of the name for this step.\n\t// For the name \"fmt.Scanner\", this is \"Scanner\".\n\tpartText  string\n\tpartRange astutil.Range\n\n\t// The text of the fully-qualified symbol path resolved in this step.\n\t// For example, \"fmt.Scanner\". Used for symbol lookups.\n\tnameText string\n\n\t// The text of the entire, original doc link expression, including brackets.\n\t// For example, \"[fmt.Scanner.Scan]\".\n\tbracketText string\n}\n\n// commentDocLinks returns the sequence of Go doc links in the comment group.\n// TODO(hxjiang): move to [parsego] package.\nfunc commentDocLinks(cg *ast.CommentGroup) iter.Seq[docLink] {\n\treturn func(yield func(docLink) bool) {\n\t\tfor _, comment := range cg.List {\n\t\t\t// The canonical parsing algorithm is defined by go/doc/comment, but\n\t\t\t// unfortunately its API provides no way to reliably reconstruct the\n\t\t\t// position of each doc link from the parsed result.\n\n\t\t\tfor _, idx := range docLinkRegex.FindAllStringSubmatchIndex(comment.Text, -1) {\n\t\t\t\t// [mstart, mend) identifies the first submatch, which is the\n\t\t\t\t// reference name in the doc link (sans '*').\n\t\t\t\t// e.g. The \"[fmt.Println]\" reference name is \"fmt.Println\".\n\t\t\t\tmstart, mend := idx[2], idx[3]\n\n\t\t\t\t// idx[0], idx[1] matches the full pattern. idx[0] corresponds\n\t\t\t\t// to the opening bracket. idx[1] may include trailing\n\t\t\t\t// whitespace or punctuation, so we need to use \"mend\" to\n\t\t\t\t// capture the exact location of the closing bracket, which must\n\t\t\t\t// be one space after the end of the reference name.\n\t\t\t\tbracketText := comment.Text[idx[0] : mend+1]\n\n\t\t\t\tmatch := comment.Text[mstart:mend]\n\n\t\t\t\tif strings.Contains(match, \"\\n\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// [namePos.Start, namePos.End) identifies the start and end\n\t\t\t\t// position of a name. e.g. \"fmt\", \"fmt.Scanner\", \"fmt.Scanner.Scan\".\n\t\t\t\tvar name string\n\n\t\t\t\tnamePos := astutil.RangeOf(comment.Pos()+token.Pos(mstart), comment.Pos()+token.Pos(mstart-1))\n\t\t\t\t// [partPos.Start, partPos.End) identifies the start and end\n\t\t\t\t// position of a part. e.g. \"fmt\", \"Scanner\", \"Scan\".\n\t\t\t\tpartPos := namePos\n\t\t\t\tfor part := range strings.SplitSeq(match, \".\") {\n\t\t\t\t\tif name != \"\" {\n\t\t\t\t\t\tname += \".\"\n\t\t\t\t\t}\n\t\t\t\t\tname += part\n\n\t\t\t\t\tpartPos.Start = partPos.EndPos + token.Pos(len(\".\"))  // Move start to the first char of next part\n\t\t\t\t\tpartPos.EndPos = partPos.Start + token.Pos(len(part)) // Move end to next char of current part\n\n\t\t\t\t\tnamePos.EndPos = partPos.EndPos\n\n\t\t\t\t\tif !yield(docLink{\n\t\t\t\t\t\tpartRange:   partPos,\n\t\t\t\t\t\tpartText:    part,\n\t\t\t\t\t\tnameText:    name,\n\t\t\t\t\t\tbracketText: bracketText,\n\t\t\t\t\t}) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// lookupDocLinkSymbol returns the symbol denoted by a doc link such\n// as \"fmt.Println\" or \"bytes.Buffer.Write\" in the specified file.\nfunc lookupDocLinkSymbol(pkg *cache.Package, pgf *parsego.File, name string) types.Object {\n\tscope := pkg.Types().Scope()\n\n\tprefix, suffix, _ := strings.Cut(name, \".\")\n\n\t// Try treating the prefix as a package name,\n\t// allowing for non-renaming and renaming imports.\n\tfileScope := pkg.TypesInfo().Scopes[pgf.File]\n\tif fileScope == nil {\n\t\t// As we learned in golang/go#69616, any file may not be Scopes!\n\t\t//  - A non-compiled Go file (such as unsafe.go) won't be in Scopes.\n\t\t//  - A (technically) compiled go file with the wrong package name won't be\n\t\t//    in Scopes, as it will be skipped by go/types.\n\t\treturn nil\n\t}\n\tpkgname, ok := fileScope.Lookup(prefix).(*types.PkgName) // ok => prefix is imported name\n\tif !ok {\n\t\t// Handle renaming import, e.g.\n\t\t// [path.Join] after import pathpkg \"path\".\n\t\t// (Should we look at all files of the package?)\n\t\tfor _, imp := range pgf.File.Imports {\n\t\t\tpkgname2 := pkg.TypesInfo().PkgNameOf(imp)\n\t\t\tif pkgname2 != nil && pkgname2.Imported().Name() == prefix {\n\t\t\t\tpkgname = pkgname2\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tif pkgname != nil {\n\t\tscope = pkgname.Imported().Scope()\n\t\tif suffix == \"\" {\n\t\t\treturn pkgname // not really a valid doc link\n\t\t}\n\t\tname = suffix\n\t}\n\n\t// TODO(adonovan): try searching the forward closure for packages\n\t// that define the symbol but are not directly imported;\n\t// see https://github.com/golang/go/issues/61677\n\n\t// Field or sel?\n\trecv, sel, ok := strings.Cut(name, \".\")\n\tif ok {\n\t\tobj := scope.Lookup(recv) // package scope\n\t\tif obj == nil {\n\t\t\tobj = types.Universe.Lookup(recv)\n\t\t}\n\t\tobj, ok := obj.(*types.TypeName)\n\t\tif !ok {\n\t\t\treturn nil\n\t\t}\n\t\tm, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), sel)\n\t\treturn m\n\t}\n\n\tif obj := scope.Lookup(name); obj != nil {\n\t\treturn obj // package-level symbol\n\t}\n\treturn types.Universe.Lookup(name) // built-in symbol\n}\n\n// newDocCommentParser returns a function that parses [doc comments],\n// with context for Doc Links supplied by the specified package.\n//\n// Imported symbols are rendered using the import mapping for the file\n// that encloses fileNode.\n//\n// The resulting function is not concurrency safe.\n//\n// See issue #61677 for how this might be generalized to support\n// correct contextual parsing of doc comments in Hover too.\n//\n// [doc comment]: https://go.dev/doc/comment\nfunc newDocCommentParser(pkg *cache.Package) func(fileNode ast.Node, text string) *comment.Doc {\n\tvar currentFilePos token.Pos // pos whose enclosing file's import mapping should be used\n\tparser := &comment.Parser{\n\t\tLookupPackage: func(name string) (importPath string, ok bool) {\n\t\t\tfor _, f := range pkg.Syntax() {\n\t\t\t\t// Different files in the same package have\n\t\t\t\t// different import mappings. Use the provided\n\t\t\t\t// syntax node to find the correct file.\n\t\t\t\tif astutil.NodeContainsPos(f, currentFilePos) {\n\t\t\t\t\t// First try each actual imported package name.\n\t\t\t\t\tfor _, imp := range f.Imports {\n\t\t\t\t\t\tpkgName := pkg.TypesInfo().PkgNameOf(imp)\n\t\t\t\t\t\tif pkgName != nil && pkgName.Name() == name {\n\t\t\t\t\t\t\treturn pkgName.Imported().Path(), true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Then try each imported package's declared name,\n\t\t\t\t\t// as some packages are typically imported under a\n\t\t\t\t\t// non-default name (e.g. pathpkg \"path\") but\n\t\t\t\t\t// may be referred to in doc links using their\n\t\t\t\t\t// canonical name.\n\t\t\t\t\tfor _, imp := range f.Imports {\n\t\t\t\t\t\tpkgName := pkg.TypesInfo().PkgNameOf(imp)\n\t\t\t\t\t\tif pkgName != nil && pkgName.Imported().Name() == name {\n\t\t\t\t\t\t\treturn pkgName.Imported().Path(), true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Finally try matching the last segment of each import\n\t\t\t\t\t// path imported by any file in the package, as the\n\t\t\t\t\t// doc comment may appear in a different file from the\n\t\t\t\t\t// import.\n\t\t\t\t\t//\n\t\t\t\t\t// Ideally we would look up the DepsByPkgPath value\n\t\t\t\t\t// (a PackageID) in the metadata graph and use the\n\t\t\t\t\t// package's declared name instead of this heuristic,\n\t\t\t\t\t// but we don't have access to the graph here.\n\t\t\t\t\tfor path := range pkg.Metadata().DepsByPkgPath {\n\t\t\t\t\t\tif pathpkg.Base(trimVersionSuffix(string(path))) == name {\n\t\t\t\t\t\t\treturn string(path), true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"\", false\n\t\t},\n\t\tLookupSym: func(recv, name string) (ok bool) {\n\t\t\t// package-level decl?\n\t\t\tif recv == \"\" {\n\t\t\t\treturn pkg.Types().Scope().Lookup(name) != nil\n\t\t\t}\n\n\t\t\t// method?\n\t\t\ttname, ok := pkg.Types().Scope().Lookup(recv).(*types.TypeName)\n\t\t\tif !ok {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tm, _, _ := types.LookupFieldOrMethod(tname.Type(), true, pkg.Types(), name)\n\t\t\treturn is[*types.Func](m)\n\t\t},\n\t}\n\treturn func(fileNode ast.Node, text string) *comment.Doc {\n\t\tcurrentFilePos = fileNode.Pos()\n\t\treturn parser.Parse(text)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/compileropt.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// CompilerOptDetails invokes the Go compiler with the \"-json=0,dir\"\n// flag on the packages and tests in the specified directory, parses\n// its log of optimization decisions, and returns them as a set of\n// diagnostics.\nfunc CompilerOptDetails(ctx context.Context, snapshot *cache.Snapshot, pkgDir protocol.DocumentURI) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\toutDir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"gopls-%d.details\", os.Getpid()))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\tif err := os.RemoveAll(outDir); err != nil {\n\t\t\tevent.Error(ctx, \"cleaning details dir\", err)\n\t\t}\n\t}()\n\n\toutDirURI := protocol.URIFromPath(outDir)\n\t// details doesn't handle Windows URIs in the form of \"file:///C:/...\",\n\t// so rewrite them to \"file://C:/...\". See golang/go#41614.\n\tif !strings.HasPrefix(outDir, \"/\") {\n\t\toutDirURI = protocol.DocumentURI(strings.Replace(string(outDirURI), \"file:///\", \"file://\", 1))\n\t}\n\n\t// We use \"go test -c\" not \"go build\" as it covers all three packages\n\t// (p, \"p [p.test]\", \"p_test [p.test]\") in the directory, if they exist.\n\t// (See also assembly.go.)\n\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, pkgDir.Path(), \"test\", []string{\n\t\t\"-c\",\n\t\t\"-vet=off\", // weirdly -c doesn't disable vet\n\t\tfmt.Sprintf(\"-gcflags=-json=0,%s\", outDirURI), // JSON schema version 0\n\t\tfmt.Sprintf(\"-o=%s\", os.DevNull),\n\t\t\".\",\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cleanupInvocation()\n\t_, err = snapshot.View().GoCommandRunner().Run(ctx, *inv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfiles, err := findJSONFiles(outDir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treports := make(map[protocol.DocumentURI][]*cache.Diagnostic)\n\tvar parseError error\n\tfor _, fn := range files {\n\t\turi, diagnostics, err := parseDetailsFile(fn, snapshot.Options())\n\t\tif err != nil {\n\t\t\t// expect errors for all the files, save 1\n\t\t\tparseError = err\n\t\t}\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil || fh == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif pkgDir != fh.URI().Dir() {\n\t\t\t// Filter compiler diagnostics to the requested directory.\n\t\t\t// https://github.com/golang/go/issues/42198\n\t\t\t// sometimes the detail diagnostics generated for files\n\t\t\t// outside the package can never be taken back.\n\t\t\tcontinue\n\t\t}\n\t\treports[fh.URI()] = diagnostics\n\t}\n\treturn reports, parseError\n}\n\n// parseDetailsFile parses the file written by the Go compiler which contains a JSON-encoded protocol.Diagnostic.\nfunc parseDetailsFile(filename string, options *settings.Options) (protocol.DocumentURI, []*cache.Diagnostic, error) {\n\tbuf, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tvar (\n\t\turi         protocol.DocumentURI\n\t\ti           int\n\t\tdiagnostics []*cache.Diagnostic\n\t)\n\ttype metadata struct {\n\t\tFile string `json:\"file,omitempty\"`\n\t}\n\tfor dec := json.NewDecoder(bytes.NewReader(buf)); dec.More(); {\n\t\t// The first element always contains metadata.\n\t\tif i == 0 {\n\t\t\ti++\n\t\t\tm := new(metadata)\n\t\t\tif err := dec.Decode(m); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t\tif !strings.HasSuffix(m.File, \".go\") {\n\t\t\t\tcontinue // <autogenerated>\n\t\t\t}\n\t\t\turi = protocol.URIFromPath(m.File)\n\t\t\tcontinue\n\t\t}\n\t\td := new(protocol.Diagnostic)\n\t\tif err := dec.Decode(d); err != nil {\n\t\t\treturn \"\", nil, err\n\t\t}\n\t\td.Tags = []protocol.DiagnosticTag{} // must be an actual slice\n\t\tmsg := d.Code.(string)\n\t\tif msg != \"\" {\n\t\t\tmsg = fmt.Sprintf(\"%s(%s)\", msg, d.Message)\n\t\t}\n\t\tif !showDiagnostic(msg, d.Source, options) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// zeroIndexedRange subtracts 1 from the line and\n\t\t// range, because the compiler output neglects to\n\t\t// convert from 1-based UTF-8 coordinates to 0-based UTF-16.\n\t\t// (See GOROOT/src/cmd/compile/internal/logopt/log_opts.go.)\n\t\t// TODO(rfindley): also translate UTF-8 to UTF-16.\n\t\tzeroIndexedRange := func(rng protocol.Range) protocol.Range {\n\t\t\treturn protocol.Range{\n\t\t\t\tStart: protocol.Position{\n\t\t\t\t\tLine:      rng.Start.Line - 1,\n\t\t\t\t\tCharacter: rng.Start.Character - 1,\n\t\t\t\t},\n\t\t\t\tEnd: protocol.Position{\n\t\t\t\t\tLine:      rng.End.Line - 1,\n\t\t\t\t\tCharacter: rng.End.Character - 1,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\tvar related []protocol.DiagnosticRelatedInformation\n\t\tfor _, ri := range d.RelatedInformation {\n\t\t\trelated = append(related, protocol.DiagnosticRelatedInformation{\n\t\t\t\tLocation: ri.Location.URI.Location(zeroIndexedRange(ri.Location.Range)),\n\t\t\t\tMessage:  ri.Message,\n\t\t\t})\n\t\t}\n\t\tdiagnostic := &cache.Diagnostic{\n\t\t\tURI:      uri,\n\t\t\tRange:    zeroIndexedRange(d.Range),\n\t\t\tMessage:  msg,\n\t\t\tSeverity: d.Severity,\n\t\t\tSource:   cache.CompilerOptDetailsInfo, // d.Source is always \"go compiler\" as of 1.16, use our own\n\t\t\tTags:     d.Tags,\n\t\t\tRelated:  related,\n\t\t}\n\t\tdiagnostics = append(diagnostics, diagnostic)\n\t\ti++\n\t}\n\treturn uri, diagnostics, nil\n}\n\n// showDiagnostic reports whether a given diagnostic should be shown to the end\n// user, given the current options.\nfunc showDiagnostic(msg, source string, o *settings.Options) bool {\n\tif source != \"go compiler\" {\n\t\treturn false\n\t}\n\tif o.Annotations == nil {\n\t\treturn true\n\t}\n\n\t// The strings below were gathered by grepping the source of\n\t// cmd/compile for literal arguments in calls to logopt.LogOpt.\n\t// (It is not a well defined set.)\n\t//\n\t// - canInlineFunction\n\t// - cannotInlineCall\n\t// - cannotInlineFunction\n\t// - escape\n\t// - escapes\n\t// - isInBounds\n\t// - isSliceInBounds\n\t// - leak\n\t// - nilcheck\n\t//\n\t// Additional ones not handled by logic below:\n\t// - copy\n\t// - iteration-variable-to-{heap,stack}\n\t// - loop-modified-{range,for}\n\n\tswitch {\n\tcase strings.HasPrefix(msg, \"canInline\") ||\n\t\tstrings.HasPrefix(msg, \"cannotInline\") ||\n\t\tstrings.HasPrefix(msg, \"inlineCall\"):\n\t\treturn o.Annotations[settings.Inline]\n\tcase strings.HasPrefix(msg, \"escape\") || msg == \"leak\":\n\t\treturn o.Annotations[settings.Escape]\n\tcase strings.HasPrefix(msg, \"nilcheck\"):\n\t\treturn o.Annotations[settings.Nil]\n\tcase strings.HasPrefix(msg, \"isInBounds\") ||\n\t\tstrings.HasPrefix(msg, \"isSliceInBounds\"):\n\t\treturn o.Annotations[settings.Bounds]\n\t}\n\treturn false\n}\n\nfunc findJSONFiles(dir string) ([]string, error) {\n\tans := []string{}\n\tf := func(path string, fi os.FileInfo, _ error) error {\n\t\tif fi.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\tif strings.HasSuffix(path, \".json\") {\n\t\t\tans = append(ans, path)\n\t\t}\n\t\treturn nil\n\t}\n\terr := filepath.Walk(dir, f)\n\treturn ans, err\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/builtin.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"context\"\n\t\"go/ast\"\n\t\"go/types\"\n)\n\n// builtinArgKind determines the expected object kind for a builtin\n// argument. It attempts to use the AST hints from builtin.go where\n// possible.\nfunc (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {\n\tbuiltin, err := c.snapshot.BuiltinFile(ctx)\n\tif err != nil {\n\t\treturn 0\n\t}\n\texprIdx := exprAtPos(c.pos, call.Args)\n\n\tbuiltinObj := builtin.File.Scope.Lookup(obj.Name())\n\tif builtinObj == nil {\n\t\treturn 0\n\t}\n\tdecl, ok := builtinObj.Decl.(*ast.FuncDecl)\n\tif !ok || exprIdx >= len(decl.Type.Params.List) {\n\t\treturn 0\n\t}\n\n\tswitch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {\n\tcase *ast.ChanType:\n\t\treturn kindChan\n\tcase *ast.ArrayType:\n\t\treturn kindSlice\n\tcase *ast.MapType:\n\t\treturn kindMap\n\tcase *ast.Ident:\n\t\tswitch ptyp.Name {\n\t\tcase \"Type\":\n\t\t\tswitch obj.Name() {\n\t\t\tcase \"make\":\n\t\t\t\treturn kindChan | kindSlice | kindMap\n\t\t\tcase \"len\":\n\t\t\t\treturn kindSlice | kindMap | kindArray | kindString | kindChan\n\t\t\tcase \"cap\":\n\t\t\t\treturn kindSlice | kindArray | kindChan\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0\n}\n\n// builtinArgType infers the type of an argument to a builtin\n// function. parentInf is the inferred type info for the builtin\n// call's parent node.\nfunc (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentInf candidateInference) candidateInference {\n\tvar (\n\t\texprIdx = exprAtPos(c.pos, call.Args)\n\n\t\t// Propagate certain properties from our parent's inference.\n\t\tinf = candidateInference{\n\t\t\ttypeName:  parentInf.typeName,\n\t\t\tmodifiers: parentInf.modifiers,\n\t\t}\n\t)\n\n\tswitch obj.Name() {\n\tcase \"append\":\n\t\tif exprIdx <= 0 {\n\t\t\t// Infer first append() arg type as apparent return type of\n\t\t\t// append().\n\t\t\tinf.objType = parentInf.objType\n\t\t\tif parentInf.variadic {\n\t\t\t\tinf.objType = types.NewSlice(inf.objType)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\t// For non-initial append() args, infer slice type from the first\n\t\t// append() arg, or from parent context.\n\t\tif len(call.Args) > 0 {\n\t\t\tinf.objType = c.pkg.TypesInfo().TypeOf(call.Args[0])\n\t\t}\n\t\tif inf.objType == nil {\n\t\t\tinf.objType = parentInf.objType\n\t\t}\n\t\tif inf.objType == nil {\n\t\t\tbreak\n\t\t}\n\n\t\tinf.objType = deslice(inf.objType)\n\n\t\t// Check if we are completing the variadic append() param.\n\t\tinf.variadic = exprIdx == 1 && len(call.Args) <= 2\n\n\t\t// Penalize the first append() argument as a candidate. You\n\t\t// don't normally append a slice to itself.\n\t\tif sliceChain := objChain(c.pkg.TypesInfo(), call.Args[0]); len(sliceChain) > 0 {\n\t\t\tinf.penalized = append(inf.penalized, penalizedObj{objChain: sliceChain, penalty: 0.9})\n\t\t}\n\tcase \"delete\":\n\t\tif exprIdx > 0 && len(call.Args) > 0 {\n\t\t\t// Try to fill in expected type of map key.\n\t\t\tfirstArgType := c.pkg.TypesInfo().TypeOf(call.Args[0])\n\t\t\tif firstArgType != nil {\n\t\t\t\tif mt, ok := firstArgType.Underlying().(*types.Map); ok {\n\t\t\t\t\tinf.objType = mt.Key()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase \"copy\":\n\t\tvar t1, t2 types.Type\n\t\tif len(call.Args) > 0 {\n\t\t\tt1 = c.pkg.TypesInfo().TypeOf(call.Args[0])\n\t\t\tif len(call.Args) > 1 {\n\t\t\t\tt2 = c.pkg.TypesInfo().TypeOf(call.Args[1])\n\t\t\t}\n\t\t}\n\n\t\t// Fill in expected type of either arg if the other is already present.\n\t\tif exprIdx == 1 && t1 != nil {\n\t\t\tinf.objType = t1\n\t\t} else if exprIdx == 0 && t2 != nil {\n\t\t\tinf.objType = t2\n\t\t}\n\tcase \"new\":\n\t\tinf.typeName.wantTypeName = true\n\t\tif parentInf.objType != nil {\n\t\t\t// Expected type for \"new\" is the de-pointered parent type.\n\t\t\tif ptr, ok := parentInf.objType.Underlying().(*types.Pointer); ok {\n\t\t\t\tinf.objType = ptr.Elem()\n\t\t\t}\n\t\t}\n\tcase \"make\":\n\t\tif exprIdx == 0 {\n\t\t\tinf.typeName.wantTypeName = true\n\t\t\tinf.objType = parentInf.objType\n\t\t} else {\n\t\t\tinf.objType = types.Typ[types.UntypedInt]\n\t\t}\n\t}\n\n\treturn inf\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/completion.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package completion provides core functionality for code completion in Go\n// editors and tools.\npackage completion\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\t\"unicode\"\n\n\t\"golang.org/x/sync/errgroup\"\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// A CompletionItem represents a possible completion suggested by the algorithm.\ntype CompletionItem struct {\n\n\t// Invariant: CompletionItem does not refer to syntax or types.\n\n\t// Label is the primary text the user sees for this completion item.\n\tLabel string\n\n\t// Detail is supplemental information to present to the user.\n\t// This often contains the type or return type of the completion item.\n\tDetail string\n\n\t// InsertText is the text to insert if this item is selected.\n\t// Any of the prefix that has already been typed is not trimmed.\n\t// The insert text does not contain snippets.\n\tInsertText string\n\n\tKind       protocol.CompletionItemKind\n\tTags       []protocol.CompletionItemTag\n\tDeprecated bool // Deprecated, prefer Tags if available\n\n\t// An optional array of additional TextEdits that are applied when\n\t// selecting this completion.\n\t//\n\t// Additional text edits should be used to change text unrelated to the current cursor position\n\t// (for example adding an import statement at the top of the file if the completion item will\n\t// insert an unqualified type).\n\tAdditionalTextEdits []protocol.TextEdit\n\n\t// Depth is how many levels were searched to find this completion.\n\t// For example when completing \"foo<>\", \"fooBar\" is depth 0, and\n\t// \"fooBar.Baz\" is depth 1.\n\tDepth int\n\n\t// Score is the internal relevance score.\n\t// A higher score indicates that this completion item is more relevant.\n\tScore float64\n\n\t// snippet is the LSP snippet for the completion item. The LSP\n\t// specification contains details about LSP snippets. For example, a\n\t// snippet for a function with the following signature:\n\t//\n\t//     func foo(a, b, c int)\n\t//\n\t// would be:\n\t//\n\t//     foo(${1:a int}, ${2: b int}, ${3: c int})\n\t//\n\t// If Placeholders is false in the CompletionOptions, the above\n\t// snippet would instead be:\n\t//\n\t//     foo(${1:})\n\tsnippet *snippet.Builder\n\n\t// Documentation is the documentation for the completion item.\n\tDocumentation string\n\n\t// isSlice reports whether the underlying type of the object\n\t// from which this candidate was derived is a slice.\n\t// (Used to complete append() calls.)\n\tisSlice bool\n}\n\n// completionOptions holds completion specific configuration.\ntype completionOptions struct {\n\tunimported            bool\n\tdocumentation         bool\n\tfullDocumentation     bool\n\tplaceholders          bool\n\tsnippets              bool\n\tpostfix               bool\n\tmatcher               settings.Matcher\n\tbudget                time.Duration\n\tcompleteFunctionCalls bool\n}\n\n// Snippet is a convenience returns the snippet if available, otherwise\n// the InsertText.\n// used for an item, depending on if the callee wants placeholders or not.\nfunc (i *CompletionItem) Snippet() string {\n\tif i.snippet != nil {\n\t\treturn i.snippet.String()\n\t}\n\treturn i.InsertText\n}\n\n// addConversion wraps the existing completionItem in a conversion expression.\n// Only affects the receiver's InsertText and snippet fields, not the Label.\n// An empty conv argument has no effect.\nfunc (i *CompletionItem) addConversion(c *completer, conv conversionEdits) {\n\tif conv.prefix != \"\" {\n\t\t// If we are in a selector, add an edit to place prefix before selector.\n\t\tif sel := enclosingSelector(c.path, c.pos); sel != nil {\n\t\t\tedits, err := c.editText(sel.Pos(), sel.Pos(), conv.prefix)\n\t\t\tif err != nil {\n\t\t\t\t// safetoken failed: invalid token.Pos information in AST.\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti.AdditionalTextEdits = append(i.AdditionalTextEdits, edits...)\n\t\t} else {\n\t\t\t// If there is no selector, just stick the prefix at the start.\n\t\t\ti.InsertText = conv.prefix + i.InsertText\n\t\t\ti.snippet.PrependText(conv.prefix)\n\t\t}\n\t}\n\n\tif conv.suffix != \"\" {\n\t\ti.InsertText += conv.suffix\n\t\ti.snippet.WriteText(conv.suffix)\n\t}\n}\n\n// Scoring constants are used for weighting the relevance of different candidates.\nconst (\n\t// lowScore indicates an irrelevant or not useful completion item.\n\tlowScore float64 = 0.01\n\n\t// stdScore is the base score for all completion items.\n\tstdScore float64 = 1.0\n\n\t// highScore indicates a very relevant completion item.\n\thighScore float64 = 10.0\n)\n\n// matcher matches a candidate's label against the user input. The\n// returned score reflects the quality of the match. A score of zero\n// indicates no match, and a score of one means a perfect match.\ntype matcher interface {\n\tScore(candidateLabel string) (score float32)\n}\n\n// prefixMatcher implements case sensitive prefix matching.\ntype prefixMatcher string\n\nfunc (pm prefixMatcher) Score(candidateLabel string) float32 {\n\tif strings.HasPrefix(candidateLabel, string(pm)) {\n\t\treturn 1\n\t}\n\treturn -1\n}\n\n// insensitivePrefixMatcher implements case insensitive prefix matching.\ntype insensitivePrefixMatcher string\n\nfunc (ipm insensitivePrefixMatcher) Score(candidateLabel string) float32 {\n\tif strings.HasPrefix(strings.ToLower(candidateLabel), string(ipm)) {\n\t\treturn 1\n\t}\n\treturn -1\n}\n\n// completer contains the necessary information for a single completion request.\ntype completer struct {\n\tsnapshot *cache.Snapshot\n\tpkg      *cache.Package\n\tqual     types.Qualifier          // for qualifying typed expressions\n\tmq       golang.MetadataQualifier // for syntactic qualifying\n\topts     *completionOptions\n\n\t// completionContext contains information about the trigger for this\n\t// completion request.\n\tcompletionContext completionContext\n\n\t// fh is a handle to the file associated with this completion request.\n\tfh file.Handle\n\n\t// filename is the name of the file associated with this completion request.\n\tfilename string\n\n\t// pgf is the AST of the file associated with this completion request.\n\tpgf *parsego.File // debugging\n\n\t// goversion is the version of Go in force in the file, as\n\t// defined by x/tools/internal/versions. Empty if unknown.\n\t// Since go1.22 it should always be known.\n\tgoversion string\n\n\t// pos is the position at which the request was triggered.\n\tpos token.Pos\n\n\t// path is the path of AST nodes enclosing the position.\n\tpath []ast.Node\n\n\t// seen is the map that ensures we do not return duplicate results.\n\tseen map[types.Object]bool\n\n\t// items is the list of completion items returned.\n\titems []CompletionItem\n\n\t// completionCallbacks is a list of callbacks to collect completions that\n\t// require expensive operations. This includes operations where we search\n\t// through the entire module cache.\n\tcompletionCallbacks []func(context.Context, *imports.Options) error\n\n\t// surrounding describes the identifier surrounding the position.\n\tsurrounding *Selection\n\n\t// inference contains information we've inferred about ideal\n\t// candidates such as the candidate's type.\n\tinference candidateInference\n\n\t// enclosingFunc contains information about the function enclosing\n\t// the position.\n\tenclosingFunc *funcInfo\n\n\t// enclosingCompositeLiteral contains information about the composite literal\n\t// enclosing the position.\n\tenclosingCompositeLiteral *compLitInfo\n\n\t// deepState contains the current state of our deep completion search.\n\tdeepState deepCompletionState\n\n\t// matcher matches the candidates against the surrounding prefix.\n\tmatcher matcher\n\n\t// methodSetCache caches the [types.NewMethodSet] call, which is relatively\n\t// expensive and can be called many times for the same type while searching\n\t// for deep completions.\n\t// TODO(adonovan): use [typeutil.MethodSetCache], which exists for this purpose.\n\tmethodSetCache map[methodSetKey]*types.MethodSet\n\n\t// tooNewSymbolsCache is a cache of\n\t// [typesinternal.TooNewStdSymbols], recording for each std\n\t// package which of its exported symbols are too new for\n\t// the version of Go in force in the completion file.\n\t// (The value is the minimum version in the form \"go1.%d\".)\n\ttooNewSymbolsCache map[*types.Package]map[types.Object]string\n\n\t// mapper converts the positions in the file from which the completion originated.\n\tmapper *protocol.Mapper\n\n\t// startTime is when we started processing this completion request. It does\n\t// not include any time the request spent in the queue.\n\t//\n\t// Note: in CL 503016, startTime move to *after* type checking, but it was\n\t// subsequently determined that it was better to keep setting it *before*\n\t// type checking, so that the completion budget best approximates the user\n\t// experience. See golang/go#62665 for more details.\n\tstartTime time.Time\n\n\t// scopes contains all scopes defined by nodes in our path,\n\t// including nil values for nodes that don't defined a scope. It\n\t// also includes our package scope and the universal scope at the\n\t// end.\n\t//\n\t// (It is tempting to replace this with fileScope.Innermost(pos)\n\t// and simply follow the Scope.Parent chain, but we need to\n\t// preserve the pairwise association of scopes[i] and path[i]\n\t// because there is no way to get from the Scope to the Node.)\n\tscopes []*types.Scope\n}\n\n// tooNew reports whether obj is a standard library symbol that is too\n// new for the specified Go version.\nfunc (c *completer) tooNew(obj types.Object) bool {\n\tpkg := obj.Pkg()\n\tif pkg == nil {\n\t\treturn false // unsafe.Pointer or error.Error\n\t}\n\tdisallowed, ok := c.tooNewSymbolsCache[pkg]\n\tif !ok {\n\t\tdisallowed = typesinternal.TooNewStdSymbols(pkg, c.goversion)\n\t\tc.tooNewSymbolsCache[pkg] = disallowed\n\t}\n\treturn disallowed[obj] != \"\"\n}\n\n// funcInfo holds info about a function object.\ntype funcInfo struct {\n\t// sig is the function declaration enclosing the position.\n\tsig *types.Signature\n\n\t// body is the function's body.\n\tbody *ast.BlockStmt\n}\n\ntype compLitInfo struct {\n\t// cl is the *ast.CompositeLit enclosing the position.\n\tcl *ast.CompositeLit\n\n\t// clType is the type of cl.\n\tclType types.Type\n\n\t// kv is the *ast.KeyValueExpr enclosing the position, if any.\n\tkv *ast.KeyValueExpr\n\n\t// inKey is true if we are certain the position is in the key side\n\t// of a key-value pair.\n\tinKey bool\n\n\t// maybeInFieldName is true if inKey is false and it is possible\n\t// we are completing a struct field name. For example,\n\t// \"SomeStruct{<>}\" will be inKey=false, but maybeInFieldName=true\n\t// because we _could_ be completing a field name.\n\tmaybeInFieldName bool\n}\n\ntype importInfo struct {\n\timportPath string\n\tname       string\n}\n\ntype methodSetKey struct {\n\ttyp         types.Type\n\taddressable bool\n}\n\ntype completionContext struct {\n\t// triggerCharacter is the character used to trigger completion at current\n\t// position, if any.\n\ttriggerCharacter string\n\n\t// triggerKind is information about how a completion was triggered.\n\ttriggerKind protocol.CompletionTriggerKind\n\n\t// commentCompletion is true if we are completing a comment.\n\tcommentCompletion bool\n\n\t// packageCompletion is true if we are completing a package name.\n\tpackageCompletion bool\n}\n\n// A Selection represents the cursor position and surrounding identifier.\ntype Selection struct {\n\tcontent            string // invariant: 0<=cursor-start<=len(content)\n\ttokFile            *token.File\n\tstart, end, cursor token.Pos // relative to rng.TokFile\n\tmapper             *protocol.Mapper\n}\n\n// Range returns the surrounding identifier's protocol.Range.\nfunc (p Selection) Range() (protocol.Range, error) {\n\treturn p.mapper.PosRange(p.tokFile, p.start, p.end)\n}\n\n// PrefixRange returns the protocol.Range of the prefix of the selection.\nfunc (p Selection) PrefixRange() (protocol.Range, error) {\n\treturn p.mapper.PosRange(p.tokFile, p.start, p.cursor)\n}\n\nfunc (p Selection) Prefix() string {\n\treturn p.content[:p.cursor-p.start]\n}\n\nfunc (p Selection) Suffix() string {\n\treturn p.content[p.cursor-p.start:]\n}\n\n// check that Prefix and Suffix will succeed (golang/go#77050)\n// at the time a Selection is constructed.\nfunc (p Selection) check() {\n\toffset := int(p.cursor - p.start)\n\t// separate the cases so that they are distinguished in the stack trace\n\tif offset < 0 {\n\t\tbug.Reportf(\"Selection invariant, len(content)=%d cursor=%d start=%d\", len(p.content), p.cursor, p.start)\n\t}\n\tif offset > len(p.content) {\n\t\tbug.Reportf(\"Selection invariant, len(content)=%d cursor=%d start=%d\", len(p.content), p.cursor, p.start)\n\t}\n}\n\nfunc (c *completer) setSurrounding(ident *ast.Ident) {\n\tif c.surrounding != nil {\n\t\treturn\n\t}\n\tif !(ident.Pos() <= c.pos && c.pos <= ident.End()) {\n\t\treturn\n\t}\n\n\tc.surrounding = &Selection{\n\t\tcontent: ident.Name,\n\t\tcursor:  c.pos,\n\t\t// Overwrite the prefix only.\n\t\ttokFile: c.pgf.Tok,\n\t\tstart:   ident.Pos(),\n\t\tend:     ident.End(),\n\t\tmapper:  c.mapper,\n\t}\n\tc.surrounding.check()\n\n\tc.setMatcherFromPrefix(c.surrounding.Prefix())\n}\n\nfunc (c *completer) setMatcherFromPrefix(prefix string) {\n\tswitch c.opts.matcher {\n\tcase settings.Fuzzy:\n\t\tc.matcher = fuzzy.NewMatcher(prefix)\n\tcase settings.CaseSensitive:\n\t\tc.matcher = prefixMatcher(prefix)\n\tdefault:\n\t\tc.matcher = insensitivePrefixMatcher(strings.ToLower(prefix))\n\t}\n}\n\nfunc (c *completer) getSurrounding() *Selection {\n\tif c.surrounding == nil {\n\t\tc.surrounding = &Selection{\n\t\t\tcontent: \"\",\n\t\t\tcursor:  c.pos,\n\t\t\ttokFile: c.pgf.Tok,\n\t\t\tstart:   c.pos,\n\t\t\tend:     c.pos,\n\t\t\tmapper:  c.mapper,\n\t\t}\n\t\tc.surrounding.check()\n\t}\n\treturn c.surrounding\n}\n\n// candidate represents a completion candidate.\ntype candidate struct {\n\t// obj is the types.Object to complete to.\n\t// TODO(adonovan): eliminate dependence on go/types throughout this struct.\n\t// See comment in (*completer).selector for explanation.\n\tobj types.Object\n\n\t// score is used to rank candidates.\n\tscore float64\n\n\t// name is the deep object name path, e.g. \"foo.bar\"\n\tname string\n\n\t// detail is additional information about this item. If not specified,\n\t// defaults to type string for the object.\n\tdetail string\n\n\t// path holds the path from the search root (excluding the candidate\n\t// itself) for a deep candidate.\n\tpath []types.Object\n\n\t// pathInvokeMask is a bit mask tracking whether each entry in path\n\t// should be formatted with \"()\" (i.e. whether it is a function\n\t// invocation).\n\tpathInvokeMask uint16\n\n\t// mods contains modifications that should be applied to the\n\t// candidate when inserted. For example, \"foo\" may be inserted as\n\t// \"*foo\" or \"foo()\".\n\tmods []typeModKind\n\n\t// addressable is true if a pointer can be taken to the candidate.\n\taddressable bool\n\n\t// convertTo is a type that this candidate should be cast to. For\n\t// example, if convertTo is float64, \"foo\" should be formatted as\n\t// \"float64(foo)\".\n\tconvertTo types.Type\n\n\t// imp is the import that needs to be added to this package in order\n\t// for this candidate to be valid. nil if no import needed.\n\timp *importInfo\n}\n\nfunc (c candidate) hasMod(mod typeModKind) bool {\n\treturn slices.Contains(c.mods, mod)\n}\n\n// Completion returns a list of possible candidates for completion, given a\n// a file and a position.\n//\n// The selection is computed based on the preceding identifier and can be used by\n// the client to score the quality of the completion. For instance, some clients\n// may tolerate imperfect matches as valid completion results, since users may make typos.\nfunc Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, protoPos protocol.Position, protoContext protocol.CompletionContext) ([]CompletionItem, *Selection, error) {\n\tctx, done := event.Start(ctx, \"completion.Completion\")\n\tdefer done()\n\n\tstartTime := time.Now()\n\n\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil || !pgf.File.Package.IsValid() {\n\t\t// Invalid package declaration\n\t\t//\n\t\t// If we can't parse this file or find position for the package\n\t\t// keyword, it may be missing a package declaration. Try offering\n\t\t// suggestions for the package declaration.\n\t\t// Note that this would be the case even if the keyword 'package' is\n\t\t// present but no package name exists.\n\t\titems, surrounding, innerErr := packageClauseCompletions(ctx, snapshot, fh, protoPos)\n\t\tif innerErr != nil {\n\t\t\t// return the error for GetParsedFile since it's more relevant in this situation.\n\t\t\treturn nil, nil, fmt.Errorf(\"getting file %s for Completion: %v (package completions: %v)\", fh.URI(), err, innerErr)\n\t\t}\n\t\treturn items, surrounding, nil\n\t}\n\n\tpos, err := pgf.PositionPos(protoPos)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\t// Completion is based on what precedes the cursor.\n\t// Find the path to the position before pos.\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, pos-1, pos-1)\n\tif path == nil {\n\t\treturn nil, nil, fmt.Errorf(\"cannot find node enclosing position\")\n\t}\n\n\tinfo := pkg.TypesInfo()\n\n\t// Check if completion at this position is valid. If not, return early.\n\tswitch n := path[0].(type) {\n\tcase *ast.BasicLit:\n\t\t// Skip completion inside literals except for ImportSpec\n\t\tif len(path) > 1 {\n\t\t\tif _, ok := path[1].(*ast.ImportSpec); ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\treturn nil, nil, nil\n\tcase *ast.CallExpr:\n\t\tif n.Ellipsis.IsValid() && pos > n.Ellipsis && pos <= n.Ellipsis+token.Pos(len(\"...\")) {\n\t\t\t// Don't offer completions inside or directly after \"...\". For\n\t\t\t// example, don't offer completions at \"<>\" in \"foo(bar...<>\").\n\t\t\treturn nil, nil, nil\n\t\t}\n\tcase *ast.Ident:\n\t\t// Don't offer completions for (most) defining identifiers.\n\t\tif obj, ok := info.Defs[n]; ok {\n\t\t\tif v, ok := obj.(*types.Var); ok && v.IsField() && v.Embedded() {\n\t\t\t\t// Allow completion of anonymous fields, since they may reference type\n\t\t\t\t// names.\n\t\t\t} else if pgf.File.Name == n {\n\t\t\t\t// Allow package name completion.\n\t\t\t} else {\n\t\t\t\t// Check if we have special completion for this definition, such as\n\t\t\t\t// test function name completion.\n\t\t\t\tans, sel := definition(path, obj, pgf)\n\t\t\t\tif ans != nil {\n\t\t\t\t\tsort.Slice(ans, func(i, j int) bool {\n\t\t\t\t\t\treturn ans[i].Score > ans[j].Score\n\t\t\t\t\t})\n\t\t\t\t\treturn ans, sel, nil\n\t\t\t\t}\n\n\t\t\t\treturn nil, nil, nil // No completions.\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect all surrounding scopes, innermost first, inserting\n\t// nils as needed to preserve the correspondence with path[i].\n\tvar scopes []*types.Scope\n\tfor _, n := range path {\n\t\tswitch node := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tn = node.Type\n\t\tcase *ast.FuncLit:\n\t\t\tn = node.Type\n\t\t}\n\t\tscopes = append(scopes, info.Scopes[n])\n\t}\n\tscopes = append(scopes, pkg.Types().Scope(), types.Universe)\n\n\topts := snapshot.Options()\n\tc := &completer{\n\t\tpkg:      pkg,\n\t\tsnapshot: snapshot,\n\t\tqual:     typesinternal.FileQualifier(pgf.File, pkg.Types()),\n\t\tmq:       golang.MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata()),\n\t\tcompletionContext: completionContext{\n\t\t\ttriggerCharacter: protoContext.TriggerCharacter,\n\t\t\ttriggerKind:      protoContext.TriggerKind,\n\t\t},\n\t\tfh:                        fh,\n\t\tfilename:                  fh.URI().Path(),\n\t\tpgf:                       pgf,\n\t\tgoversion:                 versions.FileVersion(info, pgf.File), // may be \"\" => no version check\n\t\tpath:                      path,\n\t\tpos:                       pos,\n\t\tseen:                      make(map[types.Object]bool),\n\t\tenclosingFunc:             enclosingFunction(path, info),\n\t\tenclosingCompositeLiteral: enclosingCompositeLiteral(path, pos, info),\n\t\tdeepState: deepCompletionState{\n\t\t\tenabled: opts.DeepCompletion,\n\t\t},\n\t\topts: &completionOptions{\n\t\t\tmatcher:               opts.Matcher,\n\t\t\tunimported:            opts.CompleteUnimported,\n\t\t\tdocumentation:         opts.CompletionDocumentation && opts.HoverKind != settings.NoDocumentation,\n\t\t\tfullDocumentation:     opts.HoverKind == settings.FullDocumentation,\n\t\t\tplaceholders:          opts.UsePlaceholders,\n\t\t\tbudget:                opts.CompletionBudget,\n\t\t\tsnippets:              opts.InsertTextFormat == protocol.SnippetTextFormat,\n\t\t\tpostfix:               opts.ExperimentalPostfixCompletions,\n\t\t\tcompleteFunctionCalls: opts.CompleteFunctionCalls,\n\t\t},\n\t\t// default to a matcher that always matches\n\t\tmatcher:            prefixMatcher(\"\"),\n\t\tmethodSetCache:     make(map[methodSetKey]*types.MethodSet),\n\t\ttooNewSymbolsCache: make(map[*types.Package]map[types.Object]string),\n\t\tmapper:             pgf.Mapper,\n\t\tstartTime:          startTime,\n\t\tscopes:             scopes,\n\t}\n\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\n\t// Compute the deadline for this operation. Deadline is relative to the\n\t// search operation, not the entire completion RPC, as the work up until this\n\t// point depends significantly on how long it took to type-check, which in\n\t// turn depends on the timing of the request relative to other operations on\n\t// the snapshot. Including that work in the budget leads to inconsistent\n\t// results (and realistically, if type-checking took 200ms already, the user\n\t// is unlikely to be significantly more bothered by e.g. another 100ms of\n\t// search).\n\t//\n\t// Don't overload the context with this deadline, as we don't want to\n\t// conflate user cancellation (=fail the operation) with our time limit\n\t// (=stop searching and succeed with partial results).\n\tvar deadline *time.Time\n\tif c.opts.budget > 0 {\n\t\td := startTime.Add(c.opts.budget)\n\t\tdeadline = &d\n\t}\n\n\tif surrounding := c.containingIdent(pgf.Src); surrounding != nil {\n\t\tc.setSurrounding(surrounding)\n\t}\n\n\tc.inference = expectedCandidate(ctx, c)\n\n\terr = c.collectCompletions(ctx)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to collect completions: %v\", err)\n\t}\n\n\t// Deep search collected candidates and their members for more candidates.\n\tc.deepSearch(ctx, 1, deadline)\n\n\t// At this point we have a sufficiently complete set of results, and want to\n\t// return as close to the completion budget as possible. Previously, we\n\t// avoided cancelling the context because it could result in partial results\n\t// for e.g. struct fields. At this point, we have a minimal valid set of\n\t// candidates, and so truncating due to context cancellation is acceptable.\n\tif c.opts.budget > 0 {\n\t\ttimeoutDuration := time.Until(c.startTime.Add(c.opts.budget))\n\t\tctx, cancel = context.WithTimeout(ctx, timeoutDuration)\n\t\tdefer cancel()\n\t}\n\n\tfor _, callback := range c.completionCallbacks {\n\t\tif deadline == nil || time.Now().Before(*deadline) {\n\t\t\tif err := c.snapshot.RunProcessEnvFunc(ctx, callback); err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to run goimports callback: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Search candidates populated by expensive operations like\n\t// unimportedMembers etc. for more completion items.\n\tc.deepSearch(ctx, 0, deadline)\n\n\t// Statement candidates offer an entire statement in certain contexts, as\n\t// opposed to a single object. Add statement candidates last because they\n\t// depend on other candidates having already been collected.\n\tc.addStatementCandidates()\n\n\tsortItems(c.items)\n\treturn c.items, c.getSurrounding(), nil\n}\n\n// collectCompletions adds possible completion candidates to either the deep\n// search queue or completion items directly for different completion contexts.\nfunc (c *completer) collectCompletions(ctx context.Context) error {\n\t// Inside import blocks, return completions for unimported packages.\n\tfor _, importSpec := range c.pgf.File.Imports {\n\t\tif !(importSpec.Path.Pos() <= c.pos && c.pos <= importSpec.Path.End()) {\n\t\t\tcontinue\n\t\t}\n\t\treturn c.populateImportCompletions(importSpec)\n\t}\n\n\t// Inside comments, offer completions for the name of the relevant symbol.\n\tfor _, comment := range c.pgf.File.Comments {\n\t\tif comment.Pos() < c.pos && c.pos <= comment.End() {\n\t\t\tc.populateCommentCompletions(comment)\n\t\t\treturn nil\n\t\t}\n\t}\n\n\t// Struct literals are handled entirely separately.\n\tif wantStructFieldCompletions(c.enclosingCompositeLiteral) {\n\t\t// If we are definitely completing a struct field name, deep completions\n\t\t// don't make sense.\n\t\tif c.enclosingCompositeLiteral.inKey {\n\t\t\tc.deepState.enabled = false\n\t\t}\n\t\treturn c.structLiteralFieldName(ctx)\n\t}\n\n\tif lt := c.wantLabelCompletion(); lt != labelNone {\n\t\tc.labels(lt)\n\t\treturn nil\n\t}\n\n\tif c.emptySwitchStmt() {\n\t\t// Empty switch statements only admit \"default\" and \"case\" keywords.\n\t\tc.addKeywordItems(map[string]bool{}, highScore, CASE, DEFAULT)\n\t\treturn nil\n\t}\n\n\tswitch n := c.path[0].(type) {\n\tcase *ast.Ident:\n\t\tif c.pgf.File.Name == n {\n\t\t\treturn c.packageNameCompletions(ctx, c.fh.URI(), n)\n\t\t} else if sel, ok := c.path[1].(*ast.SelectorExpr); ok && sel.Sel == n {\n\t\t\t// We are in the Sel part of a selector (e.g. x.‸sel or x.sel‸).\n\t\t\treturn c.selector(ctx, sel)\n\t\t}\n\t\treturn c.lexical(ctx)\n\n\tcase *ast.TypeAssertExpr:\n\t\t// The function name hasn't been typed yet, but the parens are there:\n\t\t//   recv.‸(arg)\n\t\t// Create a fake selector expression.\n\n\t\t// The name \"_\" is the convention used by go/parser to represent phantom\n\t\t// selectors.\n\t\tsel := &ast.Ident{NamePos: n.X.End() + token.Pos(len(\".\")), Name: \"_\"}\n\t\treturn c.selector(ctx, &ast.SelectorExpr{X: n.X, Sel: sel})\n\n\tcase *ast.SelectorExpr:\n\t\t// We are in the X part of a selector (x‸.sel),\n\t\t// or after the dot with a fixed/phantom Sel (x.‸_).\n\t\treturn c.selector(ctx, n)\n\n\tcase *ast.BadDecl, *ast.File:\n\t\t// At the file scope, only keywords are allowed.\n\t\tc.addKeywordCompletions()\n\n\tdefault:\n\t\t// fallback to lexical completions\n\t\treturn c.lexical(ctx)\n\t}\n\n\treturn nil\n}\n\n// containingIdent returns the *ast.Ident containing pos, if any. It\n// synthesizes an *ast.Ident to allow completion in the face of\n// certain syntax errors.\nfunc (c *completer) containingIdent(src []byte) *ast.Ident {\n\t// In the normal case, our leaf AST node is the identifier being completed.\n\tif ident, ok := c.path[0].(*ast.Ident); ok {\n\t\treturn ident\n\t}\n\n\tpos, tkn, lit := c.scanToken(src)\n\tif !pos.IsValid() {\n\t\treturn nil\n\t}\n\n\tfakeIdent := &ast.Ident{Name: lit, NamePos: pos}\n\tif _, isBadDecl := c.path[0].(*ast.BadDecl); isBadDecl {\n\t\t// You don't get *ast.Idents at the file level, so look for bad\n\t\t// decls and use the manually extracted token.\n\t\treturn fakeIdent\n\t} else if c.emptySwitchStmt() {\n\t\t// Only keywords are allowed in empty switch statements.\n\t\t// *ast.Idents are not parsed, so we must use the manually\n\t\t// extracted token.\n\t\treturn fakeIdent\n\t} else if tkn.IsKeyword() {\n\t\t// Otherwise, manually extract the prefix if our containing token\n\t\t// is a keyword. This improves completion after an \"accidental\n\t\t// keyword\", e.g. completing to \"variance\" in \"someFunc(var<>)\".\n\t\treturn fakeIdent\n\t} else if block, ok := c.path[0].(*ast.BlockStmt); ok && len(block.List) != 0 {\n\t\tlast := block.List[len(block.List)-1]\n\t\t// Handle incomplete AssignStmt with multiple left-hand vars:\n\t\t//     var left, right int\n\t\t//     left, ri‸                    -> \"right\"\n\t\tif expr, ok := last.(*ast.ExprStmt); ok &&\n\t\t\t(is[*ast.Ident](expr.X) ||\n\t\t\t\tis[*ast.SelectorExpr](expr.X) ||\n\t\t\t\tis[*ast.IndexExpr](expr.X) ||\n\t\t\t\tis[*ast.StarExpr](expr.X)) {\n\t\t\treturn fakeIdent\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// scanToken scans pgh's contents for the token containing pos.\nfunc (c *completer) scanToken(contents []byte) (token.Pos, token.Token, string) {\n\ttok := c.pkg.FileSet().File(c.pos)\n\n\tvar s scanner.Scanner\n\t// TODO(adonovan): fix! this mutates the token.File borrowed from c.pkg,\n\t// calling AddLine and AddLineColumnInfo. Not sound!\n\ts.Init(tok, contents, nil, 0)\n\tfor {\n\t\ttknPos, tkn, lit := s.Scan()\n\t\tif tkn == token.EOF || tknPos >= c.pos {\n\t\t\treturn token.NoPos, token.ILLEGAL, \"\"\n\t\t}\n\n\t\tif len(lit) > 0 && tknPos <= c.pos && c.pos <= tknPos+token.Pos(len(lit)) {\n\t\t\treturn tknPos, tkn, lit\n\t\t}\n\t}\n}\n\nfunc sortItems(items []CompletionItem) {\n\tsort.SliceStable(items, func(i, j int) bool {\n\t\t// Sort by score first.\n\t\tif items[i].Score != items[j].Score {\n\t\t\treturn items[i].Score > items[j].Score\n\t\t}\n\n\t\t// Then sort by label so order stays consistent. This also has the\n\t\t// effect of preferring shorter candidates.\n\t\treturn items[i].Label < items[j].Label\n\t})\n}\n\n// emptySwitchStmt reports whether pos is in an empty switch or select\n// statement.\nfunc (c *completer) emptySwitchStmt() bool {\n\tblock, ok := c.path[0].(*ast.BlockStmt)\n\tif !ok || len(block.List) > 0 || len(c.path) == 1 {\n\t\treturn false\n\t}\n\n\tswitch c.path[1].(type) {\n\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// populateImportCompletions yields completions for an import path around the cursor.\n//\n// Completions are suggested at the directory depth of the given import path so\n// that we don't overwhelm the user with a large list of possibilities. As an\n// example, a completion for the prefix \"golang\" results in \"golang.org/\".\n// Completions for \"golang.org/\" yield its subdirectories\n// (i.e. \"golang.org/x/\"). The user is meant to accept completion suggestions\n// until they reach a complete import path.\nfunc (c *completer) populateImportCompletions(searchImport *ast.ImportSpec) error {\n\tif !strings.HasPrefix(searchImport.Path.Value, `\"`) {\n\t\treturn nil\n\t}\n\n\t// deepSearch is not valuable for import completions.\n\tc.deepState.enabled = false\n\n\timportPath := searchImport.Path.Value\n\n\t// Extract the text between the quotes (if any) in an import spec.\n\t// prefix is the part of import path before the cursor.\n\tprefixEnd := c.pos - searchImport.Path.Pos()\n\tprefix := strings.Trim(importPath[:prefixEnd], `\"`)\n\n\t// The number of directories in the import path gives us the depth at\n\t// which to search.\n\tdepth := len(strings.Split(prefix, \"/\")) - 1\n\n\tcontent := importPath\n\tstart, end := searchImport.Path.Pos(), searchImport.Path.End()\n\tnamePrefix, nameSuffix := `\"`, `\"`\n\t// If a starting quote is present, adjust surrounding to either after the\n\t// cursor or after the first slash (/), except if cursor is at the starting\n\t// quote. Otherwise we provide a completion including the starting quote.\n\tif strings.HasPrefix(importPath, `\"`) && c.pos > searchImport.Path.Pos() {\n\t\tcontent = content[1:]\n\t\tstart++\n\t\tif depth > 0 {\n\t\t\t// Adjust textEdit start to replacement range. For ex: if current\n\t\t\t// path was \"golang.or/x/to<>ols/internal/\", where <> is the cursor\n\t\t\t// position, start of the replacement range would be after\n\t\t\t// \"golang.org/x/\".\n\t\t\tpath := strings.SplitAfter(prefix, \"/\")\n\t\t\tnumChars := len(strings.Join(path[:len(path)-1], \"\"))\n\t\t\tcontent = content[numChars:]\n\t\t\tstart += token.Pos(numChars)\n\t\t}\n\t\tnamePrefix = \"\"\n\t}\n\n\t// We won't provide an ending quote if one is already present, except if\n\t// cursor is after the ending quote but still in import spec. This is\n\t// because cursor has to be in our textEdit range.\n\tif strings.HasSuffix(importPath, `\"`) && c.pos < searchImport.Path.End() {\n\t\tend--\n\t\tcontent = content[:len(content)-1]\n\t\tnameSuffix = \"\"\n\t}\n\n\tc.surrounding = &Selection{\n\t\tcontent: content,\n\t\tcursor:  c.pos,\n\t\ttokFile: c.pgf.Tok,\n\t\tstart:   start,\n\t\tend:     end,\n\t\tmapper:  c.mapper,\n\t}\n\tc.surrounding.check()\n\n\tseenImports := make(map[string]struct{})\n\tfor _, importSpec := range c.pgf.File.Imports {\n\t\tif importSpec.Path.Value == importPath {\n\t\t\tcontinue\n\t\t}\n\t\tseenImportPath, err := strconv.Unquote(importSpec.Path.Value)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tseenImports[seenImportPath] = struct{}{}\n\t}\n\n\tvar mu sync.Mutex // guard c.items locally, since searchImports is called in parallel\n\tseen := make(map[string]struct{})\n\tsearchImports := func(pkg imports.ImportFix) {\n\t\tpath := pkg.StmtInfo.ImportPath\n\t\tif _, ok := seenImports[path]; ok {\n\t\t\treturn\n\t\t}\n\n\t\t// Any package path containing fewer directories than the search\n\t\t// prefix is not a match.\n\t\tpkgDirList := strings.Split(path, \"/\")\n\t\tif len(pkgDirList) < depth+1 {\n\t\t\treturn\n\t\t}\n\t\tpkgToConsider := strings.Join(pkgDirList[:depth+1], \"/\")\n\n\t\tname := pkgDirList[depth]\n\t\t// if we're adding an opening quote to completion too, set name to full\n\t\t// package path since we'll need to overwrite that range.\n\t\tif namePrefix == `\"` {\n\t\t\tname = pkgToConsider\n\t\t}\n\n\t\tscore := pkg.Relevance\n\t\tif len(pkgDirList)-1 == depth {\n\t\t\tscore *= highScore\n\t\t} else {\n\t\t\t// For incomplete package paths, add a terminal slash to indicate that the\n\t\t\t// user should keep triggering completions.\n\t\t\tname += \"/\"\n\t\t\tpkgToConsider += \"/\"\n\t\t}\n\n\t\tif _, ok := seen[pkgToConsider]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[pkgToConsider] = struct{}{}\n\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\n\t\tname = namePrefix + name + nameSuffix\n\t\tobj := types.NewPkgName(0, nil, name, types.NewPackage(pkgToConsider, name))\n\t\tc.deepState.enqueue(candidate{\n\t\t\tobj:    obj,\n\t\t\tdetail: strconv.Quote(pkgToConsider),\n\t\t\tscore:  score,\n\t\t})\n\t}\n\n\tc.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {\n\t\tif err := imports.GetImportPaths(ctx, searchImports, prefix, c.filename, c.pkg.Types().Name(), opts.Env); err != nil {\n\t\t\treturn fmt.Errorf(\"getting import paths: %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\treturn nil\n}\n\n// populateCommentCompletions yields completions for comments preceding or in declarations.\nfunc (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {\n\t// If the completion was triggered by a period, ignore it. These types of\n\t// completions will not be useful in comments.\n\tif c.completionContext.triggerCharacter == \".\" {\n\t\treturn\n\t}\n\n\t// Using the comment position find the line after\n\tfile := c.pkg.FileSet().File(comment.End())\n\tif file == nil {\n\t\treturn\n\t}\n\n\t// Deep completion doesn't work properly in comments since we don't\n\t// have a type object to complete further.\n\tc.deepState.enabled = false\n\tc.completionContext.commentCompletion = true\n\n\t// Documentation isn't useful in comments, since it might end up being the\n\t// comment itself.\n\tc.opts.documentation = false\n\n\tcommentLine := safetoken.Line(file, comment.End())\n\n\t// comment is valid, set surrounding as word boundaries around cursor\n\tc.setSurroundingForComment(comment)\n\n\t// Using the next line pos, grab and parse the exported symbol on that line\n\tfor _, n := range c.pgf.File.Decls {\n\t\tdeclLine := safetoken.Line(file, n.Pos())\n\t\t// if the comment is not in, directly above or on the same line as a declaration\n\t\tif declLine != commentLine && declLine != commentLine+1 &&\n\t\t\t!(n.Pos() <= comment.Pos() && comment.End() <= n.End()) {\n\t\t\tcontinue\n\t\t}\n\t\tswitch node := n.(type) {\n\t\t// handle const, vars, and types\n\t\tcase *ast.GenDecl:\n\t\t\tfor _, spec := range node.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\tif name.String() == \"_\" {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobj := c.pkg.TypesInfo().ObjectOf(name)\n\t\t\t\t\t\tc.deepState.enqueue(candidate{obj: obj, score: stdScore})\n\t\t\t\t\t}\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t// add TypeSpec fields to completion\n\t\t\t\t\tswitch typeNode := spec.Type.(type) {\n\t\t\t\t\tcase *ast.StructType:\n\t\t\t\t\t\tc.addFieldItems(typeNode.Fields)\n\t\t\t\t\tcase *ast.FuncType:\n\t\t\t\t\t\tc.addFieldItems(typeNode.Params)\n\t\t\t\t\t\tc.addFieldItems(typeNode.Results)\n\t\t\t\t\tcase *ast.InterfaceType:\n\t\t\t\t\t\tc.addFieldItems(typeNode.Methods)\n\t\t\t\t\t}\n\n\t\t\t\t\tif spec.Name.String() == \"_\" {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tobj := c.pkg.TypesInfo().ObjectOf(spec.Name)\n\t\t\t\t\t// Type name should get a higher score than fields but not highScore by default\n\t\t\t\t\t// since field near a comment cursor gets a highScore\n\t\t\t\t\tscore := stdScore * 1.1\n\t\t\t\t\t// If type declaration is on the line after comment, give it a highScore.\n\t\t\t\t\tif declLine == commentLine+1 {\n\t\t\t\t\t\tscore = highScore\n\t\t\t\t\t}\n\n\t\t\t\t\tc.deepState.enqueue(candidate{obj: obj, score: score})\n\t\t\t\t}\n\t\t\t}\n\t\t// handle functions\n\t\tcase *ast.FuncDecl:\n\t\t\tc.addFieldItems(node.Recv)\n\t\t\tc.addFieldItems(node.Type.Params)\n\t\t\tc.addFieldItems(node.Type.Results)\n\n\t\t\t// collect receiver struct fields\n\t\t\tif node.Recv != nil {\n\t\t\t\tfn, ok := c.pkg.TypesInfo().Defs[node.Name].(*types.Func)\n\t\t\t\tif !ok {\n\t\t\t\t\t// A duplicate FuncDecl may lack a Defs entry.\n\t\t\t\t\t// Avoid panicking in this case; see go.dev/issue/71273.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsig := fn.Signature()\n\t\t\t\trecv := sig.Recv()\n\t\t\t\tif recv == nil {\n\t\t\t\t\tcontinue // may be nil if ill-typed\n\t\t\t\t}\n\t\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\t\tif named != nil {\n\t\t\t\t\tif recvStruct, ok := named.Underlying().(*types.Struct); ok {\n\t\t\t\t\t\tfor field := range recvStruct.Fields() {\n\t\t\t\t\t\t\tc.deepState.enqueue(candidate{obj: field, score: lowScore})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif node.Name.String() == \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tobj := c.pkg.TypesInfo().ObjectOf(node.Name)\n\t\t\tif obj == nil || obj.Pkg() != nil && obj.Pkg() != c.pkg.Types() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tc.deepState.enqueue(candidate{obj: obj, score: highScore})\n\t\t}\n\t}\n}\n\n// sets word boundaries surrounding a cursor for a comment\nfunc (c *completer) setSurroundingForComment(comments *ast.CommentGroup) {\n\tvar cursorComment *ast.Comment\n\tfor _, comment := range comments.List {\n\t\tif c.pos >= comment.Pos() && c.pos <= comment.End() {\n\t\t\tcursorComment = comment\n\t\t\tbreak\n\t\t}\n\t}\n\t// if cursor isn't in the comment\n\tif cursorComment == nil {\n\t\treturn\n\t}\n\n\t// index of cursor in comment text\n\tcursorOffset := int(c.pos - cursorComment.Pos())\n\tstart, end := cursorOffset, cursorOffset\n\tfor start > 0 && isValidIdentifierChar(cursorComment.Text[start-1]) {\n\t\tstart--\n\t}\n\tfor end < len(cursorComment.Text) && isValidIdentifierChar(cursorComment.Text[end]) {\n\t\tend++\n\t}\n\n\tc.surrounding = &Selection{\n\t\tcontent: cursorComment.Text[start:end],\n\t\tcursor:  c.pos,\n\t\ttokFile: c.pgf.Tok,\n\t\tstart:   token.Pos(int(cursorComment.Slash) + start),\n\t\tend:     token.Pos(int(cursorComment.Slash) + end),\n\t\tmapper:  c.mapper,\n\t}\n\tc.surrounding.check()\n\tc.setMatcherFromPrefix(c.surrounding.Prefix())\n}\n\n// isValidIdentifierChar returns true if a byte is a valid go identifier\n// character, i.e. unicode letter or digit or underscore.\nfunc isValidIdentifierChar(char byte) bool {\n\tcharRune := rune(char)\n\treturn unicode.In(charRune, unicode.Letter, unicode.Digit) || char == '_'\n}\n\n// adds struct fields, interface methods, function declaration fields to completion\nfunc (c *completer) addFieldItems(fields *ast.FieldList) {\n\t// TODO: in golang/go#72828, we get here with a nil surrounding.\n\t// This indicates a logic bug elsewhere: we should only be interrogating the\n\t// surrounding if it is set.\n\tif fields == nil || c.surrounding == nil {\n\t\treturn\n\t}\n\n\tcursor := c.surrounding.cursor\n\tfor _, field := range fields.List {\n\t\tfor _, name := range field.Names {\n\t\t\tif name.String() == \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobj := c.pkg.TypesInfo().ObjectOf(name)\n\t\t\tif obj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// if we're in a field comment/doc, score that field as more relevant\n\t\t\tscore := stdScore\n\t\t\tif field.Comment != nil && field.Comment.Pos() <= cursor && cursor <= field.Comment.End() {\n\t\t\t\tscore = highScore\n\t\t\t} else if field.Doc != nil && field.Doc.Pos() <= cursor && cursor <= field.Doc.End() {\n\t\t\t\tscore = highScore\n\t\t\t}\n\n\t\t\tc.deepState.enqueue(candidate{obj: obj, score: score})\n\t\t}\n\t}\n}\n\nfunc wantStructFieldCompletions(enclosingCl *compLitInfo) bool {\n\tif enclosingCl == nil {\n\t\treturn false\n\t}\n\treturn is[*types.Struct](enclosingCl.clType) && (enclosingCl.inKey || enclosingCl.maybeInFieldName)\n}\n\nfunc (c *completer) wantTypeName() bool {\n\treturn !c.completionContext.commentCompletion && c.inference.typeName.wantTypeName\n}\n\n// See https://golang.org/issue/36001. Unimported completions are expensive.\nconst (\n\tmaxUnimportedPackageNames = 5\n\tunimportedMemberTarget    = 100\n)\n\n// selector finds completions for the specified selector expression.\n//\n// The caller should ensure that sel.X has type information,\n// even if sel is synthetic.\nfunc (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {\n\tc.inference.objChain = objChain(c.pkg.TypesInfo(), sel.X)\n\n\t// True selector?\n\tif tv, ok := c.pkg.TypesInfo().Types[sel.X]; ok {\n\t\tc.methodsAndFields(tv.Type, tv.Addressable(), nil, c.deepState.enqueue)\n\t\tc.addPostfixSnippetCandidates(ctx, sel)\n\t\treturn nil\n\t}\n\n\tid, ok := sel.X.(*ast.Ident)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// Treat sel as a qualified identifier.\n\tvar filter func(*metadata.Package) bool\n\tneedImport := false\n\tif pkgName, ok := c.pkg.TypesInfo().Uses[id].(*types.PkgName); ok {\n\t\t// Qualified identifier with import declaration.\n\t\timp := pkgName.Imported()\n\n\t\t// Known direct dependency? Expand using type information.\n\t\tif _, ok := c.pkg.Metadata().DepsByPkgPath[golang.PackagePath(imp.Path())]; ok {\n\t\t\tc.packageMembers(imp, stdScore, nil, c.deepState.enqueue)\n\t\t\treturn nil\n\t\t}\n\n\t\t// Imported declaration with missing type information.\n\t\t// Fall through to shallow completion of unimported package members.\n\t\t// Match candidate packages by path.\n\t\tfilter = func(mp *metadata.Package) bool {\n\t\t\treturn strings.TrimPrefix(string(mp.PkgPath), \"vendor/\") == imp.Path()\n\t\t}\n\t} else {\n\t\t// Qualified identifier without import declaration.\n\t\t// Match candidate packages by name.\n\t\tfilter = func(mp *metadata.Package) bool {\n\t\t\treturn string(mp.Name) == id.Name\n\t\t}\n\t\tneedImport = true\n\t}\n\n\t// Search unimported packages.\n\tif !c.opts.unimported {\n\t\treturn nil // feature disabled\n\t}\n\n\t// -- completion of symbols in unimported packages --\n\n\t// use new code for unimported completions, if flag allows it\n\tif c.snapshot.Options().ImportsSource == settings.ImportsSourceGopls {\n\t\t// The user might have typed strings.TLower, so id.Name==strings, sel.Sel.Name == TLower,\n\t\t// but the cursor might be inside TLower, so adjust the prefix\n\t\tprefix := sel.Sel.Name\n\t\tif c.surrounding != nil {\n\t\t\tif c.surrounding.content != sel.Sel.Name {\n\t\t\t\tbug.Reportf(\"unexpected surrounding: %q != %q\", c.surrounding.content, sel.Sel.Name)\n\t\t\t} else {\n\t\t\t\tprefix = sel.Sel.Name[:c.surrounding.cursor-c.surrounding.start]\n\t\t\t}\n\t\t}\n\t\tc.unimported(ctx, metadata.PackageName(id.Name), prefix)\n\t\treturn nil\n\n\t}\n\n\t// The deep completion algorithm is exceedingly complex and\n\t// deeply coupled to the now obsolete notions that all\n\t// token.Pos values can be interpreted by as a single FileSet\n\t// belonging to the Snapshot and that all types.Object values\n\t// are canonicalized by a single types.Importer mapping.\n\t// These invariants are no longer true now that gopls uses\n\t// an incremental approach, parsing and type-checking each\n\t// package separately.\n\t//\n\t// Consequently, completion of symbols defined in packages that\n\t// are not currently imported by the query file cannot use the\n\t// deep completion machinery which is based on type information.\n\t// Instead it must use only syntax information from a quick\n\t// parse of top-level declarations (but not function bodies).\n\t//\n\t// TODO(adonovan): rewrite the deep completion machinery to\n\t// not assume global Pos/Object realms and then use export\n\t// data instead of the quick parse approach taken here.\n\n\t// First, we search among packages in the forward transitive\n\t// closure of the workspace.\n\t// We'll use a fast parse to extract package members\n\t// from those that match the name/path criterion.\n\tall, err := c.snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tknown := make(map[golang.PackagePath]*metadata.Package)\n\tfor _, mp := range all {\n\t\tif mp.Name == \"main\" {\n\t\t\tcontinue // not importable\n\t\t}\n\t\tif mp.IsIntermediateTestVariant() {\n\t\t\tcontinue\n\t\t}\n\t\t// The only test variant we admit is \"p [p.test]\"\n\t\t// when we are completing within \"p_test [p.test]\",\n\t\t// as in that case we would like to offer completions\n\t\t// of the test variants' additional symbols.\n\t\tif mp.ForTest != \"\" && c.pkg.Metadata().PkgPath != mp.ForTest+\"_test\" {\n\t\t\tcontinue\n\t\t}\n\t\tif !filter(mp) {\n\t\t\tcontinue\n\t\t}\n\t\t// Prefer previous entry unless this one is its test variant.\n\t\tif mp.ForTest != \"\" || known[mp.PkgPath] == nil {\n\t\t\tknown[mp.PkgPath] = mp\n\t\t}\n\t}\n\n\tpaths := make([]string, 0, len(known))\n\tfor path := range known {\n\t\tpaths = append(paths, string(path))\n\t}\n\n\t// Rank import paths as goimports would.\n\tvar relevances map[string]float64\n\tif len(paths) > 0 {\n\t\tif err := c.snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {\n\t\t\tvar err error\n\t\t\trelevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)\n\t\t\treturn err\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsort.Slice(paths, func(i, j int) bool {\n\t\t\treturn relevances[paths[i]] > relevances[paths[j]]\n\t\t})\n\t}\n\n\t// quickParse does a quick parse of a single file of package m,\n\t// extracts exported package members and adds candidates to c.items.\n\t// TODO(rfindley): synchronizing access to c here does not feel right.\n\t// Consider adding a concurrency-safe API for completer.\n\tvar cMu sync.Mutex // guards c.items and c.matcher\n\tvar enough int32   // atomic bool\n\tquickParse := func(uri protocol.DocumentURI, mp *metadata.Package, tooNew map[string]bool) error {\n\t\tif atomic.LoadInt32(&enough) != 0 {\n\t\t\treturn nil\n\t\t}\n\n\t\tfh, err := c.snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcontent, err := fh.Content()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpath := string(mp.PkgPath)\n\t\tforEachPackageMember(content, func(tok token.Token, id *ast.Ident, fn *ast.FuncDecl) {\n\t\t\tif atomic.LoadInt32(&enough) != 0 {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif !id.IsExported() {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif tooNew[id.Name] {\n\t\t\t\treturn // symbol too new for requesting file's Go's version\n\t\t\t}\n\n\t\t\tcMu.Lock()\n\t\t\tscore := c.matcher.Score(id.Name)\n\t\t\tcMu.Unlock()\n\n\t\t\tif sel.Sel.Name != \"_\" && score == 0 {\n\t\t\t\treturn // not a match; avoid constructing the completion item below\n\t\t\t}\n\n\t\t\t// The only detail is the kind and package: `var (from \"example.com/foo\")`\n\t\t\t// TODO(adonovan): pretty-print FuncDecl.FuncType or TypeSpec.Type?\n\t\t\t// TODO(adonovan): should this score consider the actual c.matcher.Score\n\t\t\t// of the item? How does this compare with the deepState.enqueue path?\n\t\t\titem := CompletionItem{\n\t\t\t\tLabel:      id.Name,\n\t\t\t\tDetail:     fmt.Sprintf(\"%s (from %q)\", strings.ToLower(tok.String()), mp.PkgPath),\n\t\t\t\tInsertText: id.Name,\n\t\t\t\tScore:      float64(score) * unimportedScore(relevances[path]),\n\t\t\t}\n\t\t\tswitch tok {\n\t\t\tcase token.FUNC:\n\t\t\t\titem.Kind = protocol.FunctionCompletion\n\t\t\tcase token.VAR:\n\t\t\t\titem.Kind = protocol.VariableCompletion\n\t\t\tcase token.CONST:\n\t\t\t\titem.Kind = protocol.ConstantCompletion\n\t\t\tcase token.TYPE:\n\t\t\t\t// Without types, we can't distinguish Class from Interface.\n\t\t\t\titem.Kind = protocol.ClassCompletion\n\t\t\t}\n\n\t\t\tif needImport {\n\t\t\t\timp := &importInfo{importPath: path}\n\t\t\t\tif imports.ImportPathToAssumedName(path) != string(mp.Name) {\n\t\t\t\t\timp.name = string(mp.Name)\n\t\t\t\t}\n\t\t\t\titem.AdditionalTextEdits, _ = c.importEdits(imp)\n\t\t\t}\n\n\t\t\t// For functions, add a parameter snippet.\n\t\t\tif fn != nil {\n\t\t\t\tparamList := func(list *ast.FieldList) []string {\n\t\t\t\t\tvar params []string\n\t\t\t\t\tif list != nil {\n\t\t\t\t\t\tvar cfg printer.Config // slight overkill\n\t\t\t\t\t\tparam := func(name string, typ ast.Expr) {\n\t\t\t\t\t\t\tvar buf strings.Builder\n\t\t\t\t\t\t\tbuf.WriteString(name)\n\t\t\t\t\t\t\tbuf.WriteByte(' ')\n\t\t\t\t\t\t\tcfg.Fprint(&buf, token.NewFileSet(), typ) // ignore error\n\t\t\t\t\t\t\tparams = append(params, buf.String())\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor _, field := range list.List {\n\t\t\t\t\t\t\tif field.Names != nil {\n\t\t\t\t\t\t\t\tfor _, name := range field.Names {\n\t\t\t\t\t\t\t\t\tparam(name.Name, field.Type)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tparam(\"_\", field.Type)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn params\n\t\t\t\t}\n\n\t\t\t\t// Ideally we would eliminate the suffix of type\n\t\t\t\t// parameters that are redundant with inference\n\t\t\t\t// from the argument types (#51783), but it's\n\t\t\t\t// quite fiddly to do using syntax alone.\n\t\t\t\t// (See inferableTypeParams in format.go.)\n\t\t\t\ttparams := paramList(fn.Type.TypeParams)\n\t\t\t\tparams := paramList(fn.Type.Params)\n\t\t\t\tvar sn snippet.Builder\n\t\t\t\tc.functionCallSnippet(id.Name, tparams, params, &sn)\n\t\t\t\titem.snippet = &sn\n\t\t\t}\n\n\t\t\tcMu.Lock()\n\t\t\tc.items = append(c.items, item)\n\t\t\tif len(c.items) >= unimportedMemberTarget {\n\t\t\t\tatomic.StoreInt32(&enough, 1)\n\t\t\t}\n\t\t\tcMu.Unlock()\n\t\t})\n\t\treturn nil\n\t}\n\n\tgoversion := c.pkg.TypesInfo().FileVersions[c.pgf.File]\n\n\t// Extract the package-level candidates using a quick parse.\n\tvar g errgroup.Group\n\tfor _, path := range paths {\n\t\tmp := known[golang.PackagePath(path)]\n\n\t\t// For standard packages, build a filter of symbols that\n\t\t// are too new for the requesting file's Go version.\n\t\tvar tooNew map[string]bool\n\t\tif syms, ok := stdlib.PackageSymbols[path]; ok && goversion != \"\" {\n\t\t\ttooNew = make(map[string]bool)\n\t\t\tfor _, sym := range syms {\n\t\t\t\tif versions.Before(goversion, sym.Version.String()) {\n\t\t\t\t\ttooNew[sym.Name] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\tg.Go(func() error {\n\t\t\t\treturn quickParse(uri, mp, tooNew)\n\t\t\t})\n\t\t}\n\t}\n\tif err := g.Wait(); err != nil {\n\t\treturn err\n\t}\n\n\t// In addition, we search in the module cache using goimports.\n\tctx, cancel := context.WithCancel(ctx)\n\tvar mu sync.Mutex\n\tadd := func(pkgExport imports.PackageExport) {\n\t\tif ignoreUnimportedCompletion(pkgExport.Fix) {\n\t\t\treturn\n\t\t}\n\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\t// TODO(adonovan): what if the actual package has a vendor/ prefix?\n\t\tif _, ok := known[golang.PackagePath(pkgExport.Fix.StmtInfo.ImportPath)]; ok {\n\t\t\treturn // We got this one above.\n\t\t}\n\n\t\t// Continue with untyped proposals.\n\t\tpkg := types.NewPackage(pkgExport.Fix.StmtInfo.ImportPath, pkgExport.Fix.IdentName)\n\t\tfor _, symbol := range pkgExport.Exports {\n\t\t\tif goversion != \"\" && versions.Before(goversion, symbol.Version.String()) {\n\t\t\t\tcontinue // symbol too new for this file\n\t\t\t}\n\t\t\tscore := unimportedScore(pkgExport.Fix.Relevance)\n\t\t\tc.deepState.enqueue(candidate{\n\t\t\t\tobj:   types.NewVar(0, pkg, symbol.Name, nil),\n\t\t\t\tscore: score,\n\t\t\t\timp: &importInfo{\n\t\t\t\t\timportPath: pkgExport.Fix.StmtInfo.ImportPath,\n\t\t\t\t\tname:       pkgExport.Fix.StmtInfo.Name,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\tif len(c.items) >= unimportedMemberTarget {\n\t\t\tcancel()\n\t\t}\n\t}\n\n\tc.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {\n\t\tdefer cancel()\n\t\tif err := imports.GetPackageExports(ctx, add, id.Name, c.filename, c.pkg.Types().Name(), opts.Env); err != nil {\n\t\t\treturn fmt.Errorf(\"getting package exports: %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\treturn nil\n}\n\n// unimportedScore returns a score for an unimported package that is generally\n// lower than other candidates.\nfunc unimportedScore(relevance float64) float64 {\n\treturn (stdScore + .1*relevance) / 2\n}\n\nfunc (c *completer) packageMembers(pkg *types.Package, score float64, imp *importInfo, cb func(candidate)) {\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif c.tooNew(obj) {\n\t\t\tcontinue // std symbol too new for file's Go version\n\t\t}\n\t\tcb(candidate{\n\t\t\tobj:         obj,\n\t\t\tscore:       score,\n\t\t\timp:         imp,\n\t\t\taddressable: isVar(obj),\n\t\t})\n\t}\n}\n\n// ignoreUnimportedCompletion reports whether an unimported completion\n// resulting in the given import should be ignored.\nfunc ignoreUnimportedCompletion(fix *imports.ImportFix) bool {\n\t// golang/go#60062: don't add unimported completion to golang.org/toolchain.\n\treturn fix != nil && strings.HasPrefix(fix.StmtInfo.ImportPath, \"golang.org/toolchain\")\n}\n\nfunc (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *importInfo, cb func(candidate)) {\n\tif isStarTestingDotF(typ) {\n\t\t// is that a sufficient test? (or is more care needed?)\n\t\tif c.fuzz(typ, imp, cb) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tmset := c.methodSetCache[methodSetKey{typ, addressable}]\n\tif mset == nil {\n\t\tif addressable && !types.IsInterface(typ) && !isPointer(typ) {\n\t\t\t// Add methods of *T, which includes methods with receiver T.\n\t\t\tmset = types.NewMethodSet(types.NewPointer(typ))\n\t\t} else {\n\t\t\t// Add methods of T.\n\t\t\tmset = types.NewMethodSet(typ)\n\t\t}\n\t\tc.methodSetCache[methodSetKey{typ, addressable}] = mset\n\t}\n\n\tfor method := range mset.Methods() {\n\t\tobj := method.Obj()\n\t\t// to the other side of the cb() queue?\n\t\tif c.tooNew(obj) {\n\t\t\tcontinue // std method too new for file's Go version\n\t\t}\n\t\tcb(candidate{\n\t\t\tobj:         method.Obj(),\n\t\t\tscore:       stdScore,\n\t\t\timp:         imp,\n\t\t\taddressable: addressable || isPointer(typ),\n\t\t})\n\t}\n\n\t// Add fields of T.\n\teachField(typ, func(v *types.Var) {\n\t\tif c.tooNew(v) {\n\t\t\treturn // std field too new for file's Go version\n\t\t}\n\t\tcb(candidate{\n\t\t\tobj:         v,\n\t\t\tscore:       stdScore - 0.01,\n\t\t\timp:         imp,\n\t\t\taddressable: addressable || isPointer(typ),\n\t\t})\n\t})\n}\n\n// isStarTestingDotF reports whether typ is *testing.F.\nfunc isStarTestingDotF(typ types.Type) bool {\n\t// No Unalias, since go test doesn't consider\n\t// types when enumeratinf test funcs, only syntax.\n\tptr, _ := typ.(*types.Pointer)\n\tif ptr == nil {\n\t\treturn false\n\t}\n\tnamed, _ := ptr.Elem().(*types.Named)\n\tif named == nil {\n\t\treturn false\n\t}\n\tobj := named.Obj()\n\t// obj.Pkg is nil for the error type.\n\treturn obj != nil && obj.Pkg() != nil && obj.Pkg().Path() == \"testing\" && obj.Name() == \"F\"\n}\n\n// lexical finds completions in the lexical environment.\nfunc (c *completer) lexical(ctx context.Context) error {\n\tvar (\n\t\tbuiltinIota = types.Universe.Lookup(\"iota\")\n\t\tbuiltinNil  = types.Universe.Lookup(\"nil\")\n\n\t\t// TODO(rfindley): only allow \"comparable\" where it is valid (in constraint\n\t\t// position or embedded in interface declarations).\n\t\t// builtinComparable = types.Universe.Lookup(\"comparable\")\n\t)\n\n\t// Track seen variables to avoid showing completions for shadowed variables.\n\t// This works since we look at scopes from innermost to outermost.\n\tseen := make(map[string]struct{})\n\n\t// Process scopes innermost first.\n\tfor i, scope := range c.scopes {\n\t\tif scope == nil {\n\t\t\tcontinue\n\t\t}\n\n\tNames:\n\t\tfor _, name := range scope.Names() {\n\t\t\tdeclScope, obj := scope.LookupParent(name, c.pos)\n\t\t\tif declScope != scope {\n\t\t\t\tcontinue // scope of name starts after c.pos\n\t\t\t}\n\n\t\t\t// If obj's type is invalid, find the AST node that defines the lexical block\n\t\t\t// containing the declaration of obj. Don't resolve types for packages.\n\t\t\tif !isPkgName(obj) && !typeIsValid(obj.Type()) {\n\t\t\t\t// Match the scope to its ast.Node. If the scope is the package scope,\n\t\t\t\t// use the *ast.File as the starting node.\n\t\t\t\tvar node ast.Node\n\t\t\t\tif i < len(c.path) {\n\t\t\t\t\tnode = c.path[i]\n\t\t\t\t} else if i == len(c.path) { // use the *ast.File for package scope\n\t\t\t\t\tnode = c.path[i-1]\n\t\t\t\t}\n\t\t\t\tif node != nil {\n\t\t\t\t\tif resolved := resolveInvalid(c.pkg.FileSet(), obj, node, c.pkg.TypesInfo()); resolved != nil {\n\t\t\t\t\t\tobj = resolved\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Don't use LHS of decl in RHS.\n\t\t\tfor _, ident := range enclosingDeclLHS(c.path) {\n\t\t\t\tif obj.Pos() == ident.Pos() {\n\t\t\t\t\tcontinue Names\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Don't suggest \"iota\" outside of const decls.\n\t\t\tif obj == builtinIota && !c.inConstDecl() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Rank outer scopes lower than inner.\n\t\t\tscore := stdScore * math.Pow(.99, float64(i))\n\n\t\t\t// Dowrank \"nil\" a bit so it is ranked below more interesting candidates.\n\t\t\tif obj == builtinNil {\n\t\t\t\tscore /= 2\n\t\t\t}\n\n\t\t\t// If we haven't already added a candidate for an object with this name.\n\t\t\tif _, ok := seen[obj.Name()]; !ok {\n\t\t\t\tseen[obj.Name()] = struct{}{}\n\t\t\t\tc.deepState.enqueue(candidate{\n\t\t\t\t\tobj:         obj,\n\t\t\t\t\tscore:       score,\n\t\t\t\t\taddressable: isVar(obj),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tif c.inference.objType != nil {\n\t\tif named, ok := types.Unalias(typesinternal.Unpointer(c.inference.objType)).(*types.Named); ok {\n\t\t\t// If we expected a named type, check the type's package for\n\t\t\t// completion items. This is useful when the current file hasn't\n\t\t\t// imported the type's package yet.\n\n\t\t\tif named.Obj() != nil && named.Obj().Pkg() != nil {\n\t\t\t\tpkg := named.Obj().Pkg()\n\n\t\t\t\t// Make sure the package name isn't already in use by another\n\t\t\t\t// object, and that this file doesn't import the package yet.\n\t\t\t\t// TODO(adonovan): what if pkg.Path has vendor/ prefix?\n\t\t\t\tif _, ok := seen[pkg.Name()]; !ok && pkg != c.pkg.Types() && !alreadyImports(c.pgf.File, golang.ImportPath(pkg.Path())) {\n\t\t\t\t\tseen[pkg.Name()] = struct{}{}\n\t\t\t\t\tobj := types.NewPkgName(0, nil, pkg.Name(), pkg)\n\t\t\t\t\timp := &importInfo{\n\t\t\t\t\t\timportPath: pkg.Path(),\n\t\t\t\t\t}\n\t\t\t\t\tif imports.ImportPathToAssumedName(pkg.Path()) != pkg.Name() {\n\t\t\t\t\t\timp.name = pkg.Name()\n\t\t\t\t\t}\n\t\t\t\t\tc.deepState.enqueue(candidate{\n\t\t\t\t\t\tobj:   obj,\n\t\t\t\t\t\tscore: stdScore,\n\t\t\t\t\t\timp:   imp,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif c.opts.unimported {\n\t\tif err := c.unimportedPackages(ctx, seen); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.inference.typeName.isTypeParam {\n\t\t// If we are completing a type param, offer each structural type.\n\t\t// This ensures we suggest \"[]int\" and \"[]float64\" for a constraint\n\t\t// with type union \"[]int | []float64\".\n\t\tif t, ok := c.inference.objType.(*types.Interface); ok {\n\t\t\tif terms, err := typeparams.InterfaceTermSet(t); err == nil {\n\t\t\t\tfor _, term := range terms {\n\t\t\t\t\tc.injectType(ctx, term.Type())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tc.injectType(ctx, c.inference.objType)\n\t}\n\n\t// Add keyword completion items appropriate in the current context.\n\tc.addKeywordCompletions()\n\n\treturn nil\n}\n\n// injectType manufactures candidates based on the given type. This is\n// intended for types not discoverable via lexical search, such as\n// composite and/or generic types. For example, if the type is \"[]int\",\n// this method makes sure you get candidates \"[]int{}\" and \"[]int\"\n// (the latter applies when completing a type name).\nfunc (c *completer) injectType(ctx context.Context, t types.Type) {\n\tif t == nil {\n\t\treturn\n\t}\n\n\tt = typesinternal.Unpointer(t)\n\n\t// If we have an expected type and it is _not_ a named type, handle\n\t// it specially. Non-named types like \"[]int\" will never be\n\t// considered via a lexical search, so we need to directly inject\n\t// them. Also allow generic types since lexical search does not\n\t// infer instantiated versions of them.\n\tif pnt, ok := t.(typesinternal.NamedOrAlias); !ok || pnt.TypeParams().Len() > 0 {\n\t\t// If our expected type is \"[]int\", this will add a literal\n\t\t// candidate of \"[]int{}\".\n\t\tc.literal(ctx, t, nil)\n\n\t\tif _, isBasic := t.(*types.Basic); !isBasic {\n\t\t\t// If we expect a non-basic type name (e.g. \"[]int\"), hack up\n\t\t\t// a named type whose name is literally \"[]int\". This allows\n\t\t\t// us to reuse our object based completion machinery.\n\t\t\tfakeNamedType := candidate{\n\t\t\t\tobj:   types.NewTypeName(token.NoPos, nil, types.TypeString(t, c.qual), t),\n\t\t\t\tscore: stdScore,\n\t\t\t}\n\t\t\t// Make sure the type name matches before considering\n\t\t\t// candidate. This cuts down on useless candidates.\n\t\t\tif c.matchingTypeName(&fakeNamedType) {\n\t\t\t\tc.deepState.enqueue(fakeNamedType)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (c *completer) unimportedPackages(ctx context.Context, seen map[string]struct{}) error {\n\tvar prefix string\n\tif c.surrounding != nil {\n\t\tprefix = c.surrounding.Prefix()\n\t}\n\n\t// Don't suggest unimported packages if we have absolutely nothing\n\t// to go on.\n\tif prefix == \"\" {\n\t\treturn nil\n\t}\n\n\tcount := 0\n\n\t// Search the forward transitive closure of the workspace.\n\tall, err := c.snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpkgNameByPath := make(map[golang.PackagePath]string)\n\tvar paths []string // actually PackagePaths\n\tfor _, mp := range all {\n\t\tif mp.ForTest != \"\" {\n\t\t\tcontinue // skip all test variants\n\t\t}\n\t\tif mp.Name == \"main\" {\n\t\t\tcontinue // main is non-importable\n\t\t}\n\t\tif !strings.HasPrefix(string(mp.Name), prefix) {\n\t\t\tcontinue // not a match\n\t\t}\n\t\tpaths = append(paths, string(mp.PkgPath))\n\t\tpkgNameByPath[mp.PkgPath] = string(mp.Name)\n\t}\n\n\t// Rank candidates using goimports' algorithm.\n\tvar relevances map[string]float64\n\tif len(paths) != 0 {\n\t\tif err := c.snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {\n\t\t\tvar err error\n\t\t\trelevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)\n\t\t\treturn err\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tsort.Slice(paths, func(i, j int) bool {\n\t\tif relevances[paths[i]] != relevances[paths[j]] {\n\t\t\treturn relevances[paths[i]] > relevances[paths[j]]\n\t\t}\n\n\t\t// Fall back to lexical sort to keep truncated set of candidates\n\t\t// in a consistent order.\n\t\treturn paths[i] < paths[j]\n\t})\n\n\tfor _, path := range paths {\n\t\tname := pkgNameByPath[golang.PackagePath(path)]\n\t\tif _, ok := seen[name]; ok {\n\t\t\tcontinue\n\t\t}\n\t\timp := &importInfo{\n\t\t\timportPath: path,\n\t\t}\n\t\tif imports.ImportPathToAssumedName(path) != name {\n\t\t\timp.name = name\n\t\t}\n\t\tif count >= maxUnimportedPackageNames {\n\t\t\treturn nil\n\t\t}\n\t\tc.deepState.enqueue(candidate{\n\t\t\t// Pass an empty *types.Package to disable deep completions.\n\t\t\tobj:   types.NewPkgName(0, nil, name, types.NewPackage(path, name)),\n\t\t\tscore: unimportedScore(relevances[path]),\n\t\t\timp:   imp,\n\t\t})\n\t\tcount++\n\t}\n\n\tvar mu sync.Mutex\n\tadd := func(pkg imports.ImportFix) {\n\t\tif ignoreUnimportedCompletion(&pkg) {\n\t\t\treturn\n\t\t}\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\tif _, ok := seen[pkg.IdentName]; ok {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := relevances[pkg.StmtInfo.ImportPath]; ok {\n\t\t\treturn\n\t\t}\n\n\t\tif count >= maxUnimportedPackageNames {\n\t\t\treturn\n\t\t}\n\n\t\t// Do not add the unimported packages to seen, since we can have\n\t\t// multiple packages of the same name as completion suggestions, since\n\t\t// only one will be chosen.\n\t\tobj := types.NewPkgName(0, nil, pkg.IdentName, types.NewPackage(pkg.StmtInfo.ImportPath, pkg.IdentName))\n\t\tc.deepState.enqueue(candidate{\n\t\t\tobj:   obj,\n\t\t\tscore: unimportedScore(pkg.Relevance),\n\t\t\timp: &importInfo{\n\t\t\t\timportPath: pkg.StmtInfo.ImportPath,\n\t\t\t\tname:       pkg.StmtInfo.Name,\n\t\t\t},\n\t\t})\n\t\tcount++\n\t}\n\n\tc.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {\n\t\tif err := imports.GetAllCandidates(ctx, add, prefix, c.filename, c.pkg.Types().Name(), opts.Env); err != nil {\n\t\t\treturn fmt.Errorf(\"getting completion candidates: %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\n\treturn nil\n}\n\n// alreadyImports reports whether f has an import with the specified path.\nfunc alreadyImports(f *ast.File, path golang.ImportPath) bool {\n\tfor _, s := range f.Imports {\n\t\tif metadata.UnquoteImportPath(s) == path {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (c *completer) inConstDecl() bool {\n\tfor _, n := range c.path {\n\t\tif decl, ok := n.(*ast.GenDecl); ok && decl.Tok == token.CONST {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// structLiteralFieldName finds completions for struct field names inside a struct literal.\nfunc (c *completer) structLiteralFieldName(ctx context.Context) error {\n\tclInfo := c.enclosingCompositeLiteral\n\n\t// Mark fields of the composite literal that have already been set,\n\t// except for the current field.\n\taddedFields := make(map[*types.Var]bool)\n\tfor _, el := range clInfo.cl.Elts {\n\t\tif kvExpr, ok := el.(*ast.KeyValueExpr); ok {\n\t\t\tif clInfo.kv == kvExpr {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif key, ok := kvExpr.Key.(*ast.Ident); ok {\n\t\t\t\tif used, ok := c.pkg.TypesInfo().Uses[key]; ok {\n\t\t\t\t\tif usedVar, ok := used.(*types.Var); ok {\n\t\t\t\t\t\taddedFields[usedVar] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add struct fields.\n\tif t, ok := types.Unalias(clInfo.clType).(*types.Struct); ok {\n\t\tconst deltaScore = 0.0001\n\t\tfor i := range t.NumFields() {\n\t\t\tfield := t.Field(i)\n\t\t\tif !addedFields[field] {\n\t\t\t\tc.deepState.enqueue(candidate{\n\t\t\t\t\tobj:   field,\n\t\t\t\t\tscore: highScore - float64(i)*deltaScore,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Fall through and add lexical completions if we aren't\n\t\t// certain we are in the key part of a key-value pair.\n\t\tif !clInfo.maybeInFieldName {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn c.lexical(ctx)\n}\n\n// enclosingCompositeLiteral returns information about the composite literal enclosing the\n// position.\n// It returns nil on failure; for example, if there is no type information for a\n// node on path.\nfunc enclosingCompositeLiteral(path []ast.Node, pos token.Pos, info *types.Info) *compLitInfo {\n\tfor _, n := range path {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.CompositeLit:\n\t\t\t// The enclosing node will be a composite literal if the user has just\n\t\t\t// opened the curly brace (e.g. &x{<>) or the completion request is triggered\n\t\t\t// from an already completed composite literal expression (e.g. &x{foo: 1, <>})\n\t\t\t//\n\t\t\t// The position is not part of the composite literal unless it falls within the\n\t\t\t// curly braces (e.g. \"foo.Foo<>Struct{}\").\n\t\t\tif !(n.Lbrace < pos && pos <= n.Rbrace) {\n\t\t\t\t// Keep searching since we may yet be inside a composite literal.\n\t\t\t\t// For example \"Foo{B: Ba<>{}}\".\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\ttv, ok := info.Types[n]\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tclInfo := compLitInfo{\n\t\t\t\tcl:     n,\n\t\t\t\tclType: typesinternal.Unpointer(tv.Type).Underlying(),\n\t\t\t}\n\n\t\t\tvar (\n\t\t\t\texpr    ast.Expr\n\t\t\t\thasKeys bool\n\t\t\t)\n\t\t\tfor _, el := range n.Elts {\n\t\t\t\t// Remember the expression that the position falls in, if any.\n\t\t\t\tif el.Pos() <= pos && pos <= el.End() {\n\t\t\t\t\texpr = el\n\t\t\t\t}\n\n\t\t\t\tif kv, ok := el.(*ast.KeyValueExpr); ok {\n\t\t\t\t\thasKeys = true\n\t\t\t\t\t// If expr == el then we know the position falls in this expression,\n\t\t\t\t\t// so also record kv as the enclosing *ast.KeyValueExpr.\n\t\t\t\t\tif expr == el {\n\t\t\t\t\t\tclInfo.kv = kv\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif clInfo.kv != nil {\n\t\t\t\t// If in a *ast.KeyValueExpr, we know we are in the key if the position\n\t\t\t\t// is to the left of the colon (e.g. \"Foo{F<>: V}\".\n\t\t\t\tclInfo.inKey = pos <= clInfo.kv.Colon\n\t\t\t} else if hasKeys {\n\t\t\t\t// If we aren't in a *ast.KeyValueExpr but the composite literal has\n\t\t\t\t// other *ast.KeyValueExprs, we must be on the key side of a new\n\t\t\t\t// *ast.KeyValueExpr (e.g. \"Foo{F: V, <>}\").\n\t\t\t\tclInfo.inKey = true\n\t\t\t} else {\n\t\t\t\tswitch clInfo.clType.(type) {\n\t\t\t\tcase *types.Struct:\n\t\t\t\t\tif len(n.Elts) == 0 {\n\t\t\t\t\t\t// If the struct literal is empty, next could be a struct field\n\t\t\t\t\t\t// name or an expression (e.g. \"Foo{<>}\" could become \"Foo{F:}\"\n\t\t\t\t\t\t// or \"Foo{someVar}\").\n\t\t\t\t\t\tclInfo.maybeInFieldName = true\n\t\t\t\t\t} else if len(n.Elts) == 1 {\n\t\t\t\t\t\t// If there is one expression and the position is in that expression\n\t\t\t\t\t\t// and the expression is an identifier, we may be writing a field\n\t\t\t\t\t\t// name or an expression (e.g. \"Foo{F<>}\").\n\t\t\t\t\t\t_, clInfo.maybeInFieldName = expr.(*ast.Ident)\n\t\t\t\t\t}\n\t\t\t\tcase *types.Map:\n\t\t\t\t\t// If we aren't in a *ast.KeyValueExpr we must be adding a new key\n\t\t\t\t\t// to the map.\n\t\t\t\t\tclInfo.inKey = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn &clInfo\n\t\tdefault:\n\t\t\tif breaksExpectedTypeInference(n, pos) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// enclosingFunction returns the signature and body of the function\n// enclosing the given position.\nfunc enclosingFunction(path []ast.Node, info *types.Info) *funcInfo {\n\tfor _, node := range path {\n\t\tswitch t := node.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif obj, ok := info.Defs[t.Name]; ok {\n\t\t\t\treturn &funcInfo{\n\t\t\t\t\tsig:  obj.Type().(*types.Signature),\n\t\t\t\t\tbody: t.Body,\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.FuncLit:\n\t\t\tif typ, ok := info.Types[t]; ok {\n\t\t\t\tif sig, _ := typ.Type.(*types.Signature); sig == nil {\n\t\t\t\t\t// golang/go#49397: it should not be possible, but we somehow arrived\n\t\t\t\t\t// here with a non-signature type, most likely due to AST mangling\n\t\t\t\t\t// such that node.Type is not a FuncType.\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\treturn &funcInfo{\n\t\t\t\t\tsig:  typ.Type.(*types.Signature),\n\t\t\t\t\tbody: t.Body,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc expectedCompositeLiteralType(clInfo *compLitInfo, pos token.Pos) types.Type {\n\tswitch t := clInfo.clType.(type) {\n\tcase *types.Slice:\n\t\tif clInfo.inKey {\n\t\t\treturn types.Typ[types.UntypedInt]\n\t\t}\n\t\treturn t.Elem()\n\tcase *types.Array:\n\t\tif clInfo.inKey {\n\t\t\treturn types.Typ[types.UntypedInt]\n\t\t}\n\t\treturn t.Elem()\n\tcase *types.Map:\n\t\tif clInfo.inKey {\n\t\t\treturn t.Key()\n\t\t}\n\t\treturn t.Elem()\n\tcase *types.Struct:\n\t\t// If we are completing a key (i.e. field name), there is no expected type.\n\t\tif clInfo.inKey {\n\t\t\treturn nil\n\t\t}\n\n\t\t// If we are in a key-value pair, but not in the key, then we must be on the\n\t\t// value side. The expected type of the value will be determined from the key.\n\t\tif clInfo.kv != nil {\n\t\t\tif key, ok := clInfo.kv.Key.(*ast.Ident); ok {\n\t\t\t\tfor field := range t.Fields() {\n\t\t\t\t\tif field.Name() == key.Name {\n\t\t\t\t\t\treturn field.Type()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// If we aren't in a key-value pair and aren't in the key, we must be using\n\t\t\t// implicit field names.\n\n\t\t\t// The order of the literal fields must match the order in the struct definition.\n\t\t\t// Find the element that the position belongs to and suggest that field's type.\n\t\t\tif i := exprAtPos(pos, clInfo.cl.Elts); i < t.NumFields() {\n\t\t\t\treturn t.Field(i).Type()\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// typeMod represents an operator that changes the expected type.\ntype typeMod struct {\n\tmod      typeModKind\n\tarrayLen int64\n}\n\ntype typeModKind int\n\nconst (\n\tdereference   typeModKind = iota // pointer indirection: \"*\"\n\treference                        // adds level of pointer: \"&\" for values, \"*\" for type names\n\tchanRead                         // channel read operator: \"<-\"\n\tsliceType                        // make a slice type: \"[]\" in \"[]int\"\n\tarrayType                        // make an array type: \"[2]\" in \"[2]int\"\n\tinvoke                           // make a function call: \"()\" in \"foo()\"\n\ttakeSlice                        // take slice of array: \"[:]\" in \"foo[:]\"\n\ttakeDotDotDot                    // turn slice into variadic args: \"...\" in \"foo...\"\n\tindex                            // index into slice/array: \"[0]\" in \"foo[0]\"\n)\n\ntype objKind int\n\nconst (\n\tkindAny   objKind = 0\n\tkindArray objKind = 1 << iota\n\tkindSlice\n\tkindChan\n\tkindMap\n\tkindStruct\n\tkindString\n\tkindInt\n\tkindBool\n\tkindBytes\n\tkindPtr\n\tkindInterface\n\tkindFloat\n\tkindComplex\n\tkindError\n\tkindStringer\n\tkindFunc\n\tkindRange0Func\n\tkindRange1Func\n\tkindRange2Func\n)\n\n// penalizedObj represents an object that should be disfavored as a\n// completion candidate.\ntype penalizedObj struct {\n\t// objChain is the full \"chain\", e.g. \"foo.bar().baz\" becomes\n\t// []types.Object{foo, bar, baz}.\n\tobjChain []types.Object\n\t// penalty is score penalty in the range (0, 1).\n\tpenalty float64\n}\n\n// candidateInference holds information we have inferred about a type that can be\n// used at the current position.\ntype candidateInference struct {\n\t// objType is the desired type of an object used at the query position.\n\tobjType types.Type\n\n\t// objKind is a mask of expected kinds of types such as \"map\", \"slice\", etc.\n\tobjKind objKind\n\n\t// variadic is true if we are completing the initial variadic\n\t// parameter. For example:\n\t//   append([]T{}, <>)      // objType=T variadic=true\n\t//   append([]T{}, T{}, <>) // objType=T variadic=false\n\tvariadic bool\n\n\t// modifiers are prefixes such as \"*\", \"&\" or \"<-\" that influence how\n\t// a candidate type relates to the expected type.\n\tmodifiers []typeMod\n\n\t// convertibleTo is a type our candidate type must be convertible to.\n\tconvertibleTo types.Type\n\n\t// needsExactType is true if the candidate type must be exactly the type of\n\t// the objType, e.g. an interface rather than it's implementors.\n\t//\n\t// This is necessary when objType is derived using reverse type inference:\n\t// any different (but assignable) type may lead to different type inference,\n\t// which may no longer be valid.\n\t//\n\t// For example, consider the following scenario:\n\t//\n\t//   func f[T any](x T) []T { return []T{x} }\n\t//\n\t//   var s []any = f(_)\n\t//\n\t// Reverse type inference would infer that the type at _ must be 'any', but\n\t// that does not mean that any object in the lexical scope is valid: the type of\n\t// the object must be *exactly* any, otherwise type inference will cause the\n\t// slice assignment to fail.\n\tneedsExactType bool\n\n\t// typeName holds information about the expected type name at\n\t// position, if any.\n\ttypeName typeNameInference\n\n\t// assignees are the types that would receive a function call's\n\t// results at the position. For example:\n\t//\n\t// foo := 123\n\t// foo, bar := <>\n\t//\n\t// at \"<>\", the assignees are [int, <invalid>].\n\tassignees []types.Type\n\n\t// variadicAssignees is true if we could be completing an inner\n\t// function call that fills out an outer function call's variadic\n\t// params. For example:\n\t//\n\t// func foo(int, ...string) {}\n\t//\n\t// foo(<>)         // variadicAssignees=true\n\t// foo(bar<>)      // variadicAssignees=true\n\t// foo(bar, baz<>) // variadicAssignees=false\n\tvariadicAssignees bool\n\n\t// penalized holds expressions that should be disfavored as\n\t// candidates. For example, it tracks expressions already used in a\n\t// switch statement's other cases. Each expression is tracked using\n\t// its entire object \"chain\" allowing differentiation between\n\t// \"a.foo\" and \"b.foo\" when \"a\" and \"b\" are the same type.\n\tpenalized []penalizedObj\n\n\t// objChain contains the chain of objects representing the\n\t// surrounding *ast.SelectorExpr. For example, if we are completing\n\t// \"foo.bar.ba<>\", objChain will contain []types.Object{foo, bar}.\n\tobjChain []types.Object\n}\n\n// typeNameInference holds information about the expected type name at\n// position.\ntype typeNameInference struct {\n\t// wantTypeName is true if we expect the name of a type.\n\twantTypeName bool\n\n\t// modifiers are prefixes such as \"*\", \"&\" or \"<-\" that influence how\n\t// a candidate type relates to the expected type.\n\tmodifiers []typeMod\n\n\t// assertableFrom is a type that must be assertable to our candidate type.\n\tassertableFrom types.Type\n\n\t// wantComparable is true if we want a comparable type.\n\twantComparable bool\n\n\t// seenTypeSwitchCases tracks types that have already been used by\n\t// the containing type switch.\n\tseenTypeSwitchCases []types.Type\n\n\t// compLitType is true if we are completing a composite literal type\n\t// name, e.g \"foo<>{}\".\n\tcompLitType bool\n\n\t// isTypeParam is true if we are completing a type instantiation parameter\n\tisTypeParam bool\n}\n\n// expectedCandidate returns information about the expected candidate\n// for an expression at the query position.\nfunc expectedCandidate(ctx context.Context, c *completer) (inf candidateInference) {\n\tinf.typeName = expectTypeName(c)\n\n\tif c.enclosingCompositeLiteral != nil {\n\t\tinf.objType = expectedCompositeLiteralType(c.enclosingCompositeLiteral, c.pos)\n\t}\n\nNodes:\n\tfor i, node := range c.path {\n\t\tswitch node := node.(type) {\n\t\tcase *ast.BinaryExpr:\n\t\t\t// Determine if query position comes from left or right of op.\n\t\t\te := node.X\n\t\t\tif c.pos < node.OpPos {\n\t\t\t\te = node.Y\n\t\t\t}\n\t\t\tif tv, ok := c.pkg.TypesInfo().Types[e]; ok {\n\t\t\t\tswitch node.Op {\n\t\t\t\tcase token.LAND, token.LOR:\n\t\t\t\t\t// Don't infer \"bool\" type for \"&&\" or \"||\". Often you want\n\t\t\t\t\t// to compose a boolean expression from non-boolean\n\t\t\t\t\t// candidates.\n\t\t\t\tdefault:\n\t\t\t\t\tinf.objType = tv.Type\n\t\t\t\t}\n\t\t\t\tbreak Nodes\n\t\t\t}\n\t\tcase *ast.AssignStmt:\n\t\t\tobjType, assignees := expectedAssignStmtTypes(c.pkg, node, c.pos)\n\t\t\tinf.objType = objType\n\t\t\tinf.assignees = assignees\n\t\t\treturn inf\n\t\tcase *ast.ValueSpec:\n\t\t\tinf.objType = expectedValueSpecType(c.pkg, node, c.pos)\n\t\t\treturn\n\t\tcase *ast.ReturnStmt:\n\t\t\tif c.enclosingFunc != nil {\n\t\t\t\tinf.objType = expectedReturnStmtType(c.enclosingFunc.sig, node, c.pos)\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.SendStmt:\n\t\t\tif typ := expectedSendStmtType(c.pkg, node, c.pos); typ != nil {\n\t\t\t\tinf.objType = typ\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.CallExpr:\n\t\t\t// Only consider CallExpr args if position falls between parens.\n\t\t\tif node.Lparen < c.pos && c.pos <= node.Rparen {\n\t\t\t\t// For type conversions like \"int64(foo)\" we can only infer our\n\t\t\t\t// desired type is convertible to int64.\n\t\t\t\tif typ := typeConversion(node, c.pkg.TypesInfo()); typ != nil {\n\t\t\t\t\tinf.convertibleTo = typ\n\t\t\t\t\tbreak Nodes\n\t\t\t\t}\n\n\t\t\t\tif sig, ok := c.pkg.TypesInfo().Types[node.Fun].Type.(*types.Signature); ok {\n\t\t\t\t\t// Out of bounds arguments get no inference completion.\n\t\t\t\t\tif !sig.Variadic() && exprAtPos(c.pos, node.Args) >= sig.Params().Len() {\n\t\t\t\t\t\treturn inf\n\t\t\t\t\t}\n\n\t\t\t\t\t// Inference is necessary only when function results are generic.\n\t\t\t\t\tvar free typeparams.Free\n\t\t\t\t\tif free.Has(sig.Results()) {\n\t\t\t\t\t\ttargs := c.getTypeArgs(node)\n\t\t\t\t\t\tres := inferExpectedResultTypes(c, i)\n\t\t\t\t\t\tsubsts := reverseInferTypeArgs(sig, targs, res)\n\t\t\t\t\t\tinst := instantiate(sig, substs)\n\t\t\t\t\t\tif inst != nil {\n\t\t\t\t\t\t\t// TODO(jacobz): If partial signature instantiation becomes possible,\n\t\t\t\t\t\t\t// make needsExactType only true if necessary.\n\t\t\t\t\t\t\t// Currently, ambiguous cases always resolve to a conversion expression\n\t\t\t\t\t\t\t// wrapping the completion, which is occasionally superfluous.\n\t\t\t\t\t\t\tinf.needsExactType = true\n\t\t\t\t\t\t\tsig = inst\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tinf = c.expectedCallParamType(inf, node, sig)\n\t\t\t\t}\n\n\t\t\t\tif funIdent, ok := node.Fun.(*ast.Ident); ok {\n\t\t\t\t\tobj := c.pkg.TypesInfo().ObjectOf(funIdent)\n\n\t\t\t\t\tif obj != nil && obj.Parent() == types.Universe {\n\t\t\t\t\t\t// Defer call to builtinArgType so we can provide it the\n\t\t\t\t\t\t// inferred type from its parent node.\n\t\t\t\t\t\tdefer func() {\n\t\t\t\t\t\t\tinf = c.builtinArgType(obj, node, inf)\n\t\t\t\t\t\t\tinf.objKind = c.builtinArgKind(ctx, obj, node)\n\t\t\t\t\t\t}()\n\n\t\t\t\t\t\t// The expected type of builtin arguments like append() is\n\t\t\t\t\t\t// the expected type of the builtin call itself. For\n\t\t\t\t\t\t// example:\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// var foo []int = append(<>)\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To find the expected type at <> we \"skip\" the append()\n\t\t\t\t\t\t// node and get the expected type one level up, which is\n\t\t\t\t\t\t// []int.\n\t\t\t\t\t\tcontinue Nodes\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn inf\n\t\t\t}\n\t\tcase *ast.CaseClause:\n\t\t\tif swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, node).(*ast.SwitchStmt); ok {\n\t\t\t\tif tv, ok := c.pkg.TypesInfo().Types[swtch.Tag]; ok {\n\t\t\t\t\tinf.objType = tv.Type\n\n\t\t\t\t\t// Record which objects have already been used in the case\n\t\t\t\t\t// statements so we don't suggest them again.\n\t\t\t\t\tfor _, cc := range swtch.Body.List {\n\t\t\t\t\t\tfor _, caseExpr := range cc.(*ast.CaseClause).List {\n\t\t\t\t\t\t\t// Don't record the expression we are currently completing.\n\t\t\t\t\t\t\tif caseExpr.Pos() < c.pos && c.pos <= caseExpr.End() {\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif objs := objChain(c.pkg.TypesInfo(), caseExpr); len(objs) > 0 {\n\t\t\t\t\t\t\t\tinf.penalized = append(inf.penalized, penalizedObj{objChain: objs, penalty: 0.1})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.SliceExpr:\n\t\t\t// Make sure position falls within the brackets (e.g. \"foo[a:<>]\").\n\t\t\tif node.Lbrack < c.pos && c.pos <= node.Rbrack {\n\t\t\t\tinf.objType = types.Typ[types.UntypedInt]\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.IndexExpr:\n\t\t\t// Make sure position falls within the brackets (e.g. \"foo[<>]\").\n\t\t\tif node.Lbrack < c.pos && c.pos <= node.Rbrack {\n\t\t\t\tif tv, ok := c.pkg.TypesInfo().Types[node.X]; ok {\n\t\t\t\t\tswitch t := tv.Type.Underlying().(type) {\n\t\t\t\t\tcase *types.Map:\n\t\t\t\t\t\tinf.objType = t.Key()\n\t\t\t\t\tcase *types.Slice, *types.Array:\n\t\t\t\t\t\tinf.objType = types.Typ[types.UntypedInt]\n\t\t\t\t\t}\n\n\t\t\t\t\tif ct := expectedConstraint(tv.Type, 0); ct != nil {\n\t\t\t\t\t\tinf.objType = ct\n\t\t\t\t\t\tinf.typeName.wantTypeName = true\n\t\t\t\t\t\tinf.typeName.isTypeParam = true\n\t\t\t\t\t\tif typ := c.inferExpectedTypeArg(i+1, 0); typ != nil {\n\t\t\t\t\t\t\tinf.objType = typ\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.IndexListExpr:\n\t\t\tif node.Lbrack < c.pos && c.pos <= node.Rbrack {\n\t\t\t\tif tv, ok := c.pkg.TypesInfo().Types[node.X]; ok {\n\t\t\t\t\ttypeParamIdx := exprAtPos(c.pos, node.Indices)\n\t\t\t\t\tif ct := expectedConstraint(tv.Type, typeParamIdx); ct != nil {\n\t\t\t\t\t\tinf.objType = ct\n\t\t\t\t\t\tinf.typeName.wantTypeName = true\n\t\t\t\t\t\tinf.typeName.isTypeParam = true\n\t\t\t\t\t\tif typ := c.inferExpectedTypeArg(i+1, typeParamIdx); typ != nil {\n\t\t\t\t\t\t\tinf.objType = typ\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.RangeStmt:\n\t\t\tif astutil.NodeContainsPos(node.X, c.pos) {\n\t\t\t\tinf.objKind |= kindSlice | kindArray | kindMap | kindString\n\t\t\t\tif node.Key == nil && node.Value == nil {\n\t\t\t\t\tinf.objKind |= kindRange0Func | kindRange1Func | kindRange2Func\n\t\t\t\t} else if node.Value == nil {\n\t\t\t\t\tinf.objKind |= kindChan | kindRange1Func | kindRange2Func\n\t\t\t\t} else {\n\t\t\t\t\tinf.objKind |= kindRange2Func\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn inf\n\t\tcase *ast.StarExpr:\n\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: dereference})\n\t\tcase *ast.UnaryExpr:\n\t\t\tswitch node.Op {\n\t\t\tcase token.AND:\n\t\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: reference})\n\t\t\tcase token.ARROW:\n\t\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: chanRead})\n\t\t\t}\n\t\tcase *ast.DeferStmt, *ast.GoStmt:\n\t\t\tinf.objKind |= kindFunc\n\t\t\treturn inf\n\t\tdefault:\n\t\t\tif breaksExpectedTypeInference(node, c.pos) {\n\t\t\t\treturn inf\n\t\t\t}\n\t\t}\n\t}\n\n\treturn inf\n}\n\n// inferExpectedResultTypes takes the index of a call expression within the completion\n// path and uses its surroundings to infer the expected result tuple of the call's signature.\n// Returns the signature result tuple as a slice, or nil if reverse type inference fails.\n//\n// # For example\n//\n// func generic[T any, U any](a T, b U) (T, U) { ... }\n//\n// var x TypeA\n// var y TypeB\n// x, y := generic(<cursor>, <cursor>)\n//\n// inferExpectedResultTypes can determine that the expected result type of the function is (TypeA, TypeB)\nfunc inferExpectedResultTypes(c *completer, callNodeIdx int) []types.Type {\n\tcallNode, ok := c.path[callNodeIdx].(*ast.CallExpr)\n\tif !ok {\n\t\tbug.Reportf(\"inferExpectedResultTypes given callNodeIndex: %v which is not a ast.CallExpr\\n\", callNodeIdx)\n\t\treturn nil\n\t}\n\n\tif len(c.path) <= callNodeIdx+1 {\n\t\treturn nil\n\t}\n\n\tvar expectedResults []types.Type\n\n\t// Check the parents of the call node to extract the expected result types of the call signature.\n\t// Currently reverse inferences are only supported with the following parent expressions,\n\t// however this list isn't exhaustive.\n\tswitch node := c.path[callNodeIdx+1].(type) {\n\tcase *ast.KeyValueExpr:\n\t\tenclosingCompositeLiteral := enclosingCompositeLiteral(c.path[callNodeIdx:], callNode.Pos(), c.pkg.TypesInfo())\n\t\tif enclosingCompositeLiteral != nil && !wantStructFieldCompletions(enclosingCompositeLiteral) {\n\t\t\texpectedResults = append(expectedResults, expectedCompositeLiteralType(enclosingCompositeLiteral, callNode.Pos()))\n\t\t}\n\tcase *ast.AssignStmt:\n\t\tobjType, assignees := expectedAssignStmtTypes(c.pkg, node, c.pos)\n\t\tif len(assignees) > 0 {\n\t\t\treturn assignees\n\t\t} else if objType != nil {\n\t\t\texpectedResults = append(expectedResults, objType)\n\t\t}\n\tcase *ast.ValueSpec:\n\t\tif resultType := expectedValueSpecType(c.pkg, node, c.pos); resultType != nil {\n\t\t\texpectedResults = append(expectedResults, resultType)\n\t\t}\n\tcase *ast.SendStmt:\n\t\tif resultType := expectedSendStmtType(c.pkg, node, c.pos); resultType != nil {\n\t\t\texpectedResults = append(expectedResults, resultType)\n\t\t}\n\tcase *ast.ReturnStmt:\n\t\tif c.enclosingFunc == nil {\n\t\t\treturn nil\n\t\t}\n\n\t\t// As a special case for reverse call inference in\n\t\t//\n\t\t// return foo(<cursor>)\n\t\t//\n\t\t// Pull the result type from the enclosing function\n\t\tif exprAtPos(c.pos, node.Results) == 0 {\n\t\t\tif callSig := c.pkg.TypesInfo().Types[callNode.Fun].Type.(*types.Signature); callSig != nil {\n\t\t\t\tenclosingResults := c.enclosingFunc.sig.Results()\n\t\t\t\tif callSig.Results().Len() == enclosingResults.Len() {\n\t\t\t\t\texpectedResults = make([]types.Type, enclosingResults.Len())\n\t\t\t\t\tfor i := range enclosingResults.Len() {\n\t\t\t\t\t\texpectedResults[i] = enclosingResults.At(i).Type()\n\t\t\t\t\t}\n\t\t\t\t\treturn expectedResults\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif resultType := expectedReturnStmtType(c.enclosingFunc.sig, node, c.pos); resultType != nil {\n\t\t\texpectedResults = append(expectedResults, resultType)\n\t\t}\n\tcase *ast.CallExpr:\n\t\t// TODO(jacobz): This is a difficult case because the normal CallExpr candidateInference\n\t\t// leans on control flow which is inaccessible in this helper function.\n\t\t// It would probably take a significant refactor to a recursive solution to make this case\n\t\t// work cleanly. For now it's unimplemented.\n\t}\n\treturn expectedResults\n}\n\n// expectedSendStmtType return the expected type at the position.\n// Returns nil if unknown.\nfunc expectedSendStmtType(pkg *cache.Package, node *ast.SendStmt, pos token.Pos) types.Type {\n\t// Make sure we are on right side of arrow (e.g. \"foo <- <>\").\n\tif pos > node.Arrow+1 {\n\t\tif tv, ok := pkg.TypesInfo().Types[node.Chan]; ok {\n\t\t\tif ch, ok := tv.Type.Underlying().(*types.Chan); ok {\n\t\t\t\treturn ch.Elem()\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// expectedValueSpecType returns the expected type of a ValueSpec at the query\n// position.\nfunc expectedValueSpecType(pkg *cache.Package, node *ast.ValueSpec, pos token.Pos) types.Type {\n\tif node.Type != nil && pos > node.Type.End() {\n\t\treturn pkg.TypesInfo().TypeOf(node.Type)\n\t}\n\treturn nil\n}\n\n// expectedAssignStmtTypes analyzes the provided assignStmt, and checks\n// to see if the provided pos is within a RHS expression. If so, it report\n// the expected type of that expression, and the LHS type(s) to which it\n// is being assigned.\nfunc expectedAssignStmtTypes(pkg *cache.Package, node *ast.AssignStmt, pos token.Pos) (objType types.Type, assignees []types.Type) {\n\t// Only rank completions if you are on the right side of the token.\n\tif pos > node.TokPos {\n\t\ti := exprAtPos(pos, node.Rhs)\n\t\tif i >= len(node.Lhs) {\n\t\t\ti = len(node.Lhs) - 1\n\t\t}\n\t\tif tv, ok := pkg.TypesInfo().Types[node.Lhs[i]]; ok {\n\t\t\tobjType = tv.Type\n\t\t}\n\n\t\t// If we have a single expression on the RHS, record the LHS\n\t\t// assignees so we can favor multi-return function calls with\n\t\t// matching result values.\n\t\tif len(node.Rhs) <= 1 {\n\t\t\tfor _, lhs := range node.Lhs {\n\t\t\t\tassignees = append(assignees, pkg.TypesInfo().TypeOf(lhs))\n\t\t\t}\n\t\t} else {\n\t\t\t// Otherwise, record our single assignee, even if its type is\n\t\t\t// not available. We use this info to downrank functions\n\t\t\t// with the wrong number of result values.\n\t\t\tassignees = append(assignees, pkg.TypesInfo().TypeOf(node.Lhs[i]))\n\t\t}\n\t}\n\treturn objType, assignees\n}\n\n// expectedReturnStmtType returns the expected type of a return statement.\n// Returns nil if enclosingSig is nil.\nfunc expectedReturnStmtType(enclosingSig *types.Signature, node *ast.ReturnStmt, pos token.Pos) types.Type {\n\tif enclosingSig != nil {\n\t\tif resultIdx := exprAtPos(pos, node.Results); resultIdx < enclosingSig.Results().Len() {\n\t\t\treturn enclosingSig.Results().At(resultIdx).Type()\n\t\t}\n\t}\n\treturn nil\n}\n\n// Returns the number of type arguments in a callExpr\nfunc (c *completer) getTypeArgs(callExpr *ast.CallExpr) []types.Type {\n\tvar targs []types.Type\n\tswitch fun := callExpr.Fun.(type) {\n\tcase *ast.IndexListExpr:\n\t\tfor i := range fun.Indices {\n\t\t\tif typ, ok := c.pkg.TypesInfo().Types[fun.Indices[i]]; ok && typeIsValid(typ.Type) {\n\t\t\t\ttargs = append(targs, typ.Type)\n\t\t\t}\n\t\t}\n\tcase *ast.IndexExpr:\n\t\tif typ, ok := c.pkg.TypesInfo().Types[fun.Index]; ok && typeIsValid(typ.Type) {\n\t\t\ttargs = []types.Type{typ.Type}\n\t\t}\n\t}\n\treturn targs\n}\n\n// reverseInferTypeArgs takes a generic signature, a list of passed type arguments, and the expected concrete return types\n// inferred from the signature's call site. If possible, it returns a list of types that could be used as the type arguments\n// to the signature. If not possible, it returns nil.\n//\n// Does not panic if any of the arguments are nil.\nfunc reverseInferTypeArgs(sig *types.Signature, typeArgs []types.Type, expectedResults []types.Type) []types.Type {\n\tif len(expectedResults) == 0 || sig == nil || sig.TypeParams().Len() == 0 || sig.Results().Len() != len(expectedResults) {\n\t\treturn nil\n\t}\n\n\ttparams := make([]*types.TypeParam, sig.TypeParams().Len())\n\tfor i := range sig.TypeParams().Len() {\n\t\ttparams[i] = sig.TypeParams().At(i)\n\t}\n\n\tfor i := len(typeArgs); i < sig.TypeParams().Len(); i++ {\n\t\ttypeArgs = append(typeArgs, nil)\n\t}\n\n\tu := newUnifier(tparams, typeArgs)\n\tfor i, assignee := range expectedResults {\n\t\t// Unify does not check the constraints of the type parameters.\n\t\t// Checks must be applied after.\n\t\tif !u.unify(sig.Results().At(i).Type(), assignee, unifyModeExact) {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tsubsts := make([]types.Type, sig.TypeParams().Len())\n\tfor i := range sig.TypeParams().Len() {\n\t\tif sub := u.handles[sig.TypeParams().At(i)]; sub != nil && *sub != nil {\n\t\t\t// Ensure the inferred subst is assignable to the type parameter's constraint.\n\t\t\tif !assignableTo(*sub, sig.TypeParams().At(i).Constraint()) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tsubsts[i] = *sub\n\t\t}\n\t}\n\treturn substs\n}\n\n// inferExpectedTypeArg gives a type param candidateInference based on the surroundings of its call site.\n// If successful, the inf parameter is returned with only it's objType field updated.\n//\n// callNodeIdx is the index within the completion path of the type parameter's parent call expression.\n// typeParamIdx is the index of the type parameter at the completion pos.\nfunc (c *completer) inferExpectedTypeArg(callNodeIdx int, typeParamIdx int) types.Type {\n\tif len(c.path) <= callNodeIdx {\n\t\treturn nil\n\t}\n\n\tcallNode, ok := c.path[callNodeIdx].(*ast.CallExpr)\n\tif !ok {\n\t\treturn nil\n\t}\n\tsig, ok := c.pkg.TypesInfo().Types[callNode.Fun].Type.(*types.Signature)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// Infer the type parameters in a function call based on context\n\texpectedResults := inferExpectedResultTypes(c, callNodeIdx)\n\tif typeParamIdx < 0 || typeParamIdx >= sig.TypeParams().Len() {\n\t\treturn nil\n\t}\n\tsubsts := reverseInferTypeArgs(sig, nil, expectedResults)\n\tif substs == nil || substs[typeParamIdx] == nil {\n\t\treturn nil\n\t}\n\n\treturn substs[typeParamIdx]\n}\n\n// Instantiates a signature with a set of type parameters.\n// Wrapper around types.Instantiate but bad arguments won't cause a panic.\nfunc instantiate(sig *types.Signature, substs []types.Type) *types.Signature {\n\tif substs == nil || sig == nil || len(substs) != sig.TypeParams().Len() {\n\t\treturn nil\n\t}\n\n\tfor i := range substs {\n\t\tif substs[i] == nil {\n\t\t\tsubsts[i] = sig.TypeParams().At(i)\n\t\t}\n\t}\n\n\tif inst, err := types.Instantiate(nil, sig, substs, true); err == nil {\n\t\tif inst, ok := inst.(*types.Signature); ok {\n\t\t\treturn inst\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (c *completer) expectedCallParamType(inf candidateInference, node *ast.CallExpr, sig *types.Signature) candidateInference {\n\tnumParams := sig.Params().Len()\n\tif numParams == 0 {\n\t\treturn inf\n\t}\n\n\texprIdx := exprAtPos(c.pos, node.Args)\n\n\t// If we have one or zero arg expressions, we may be\n\t// completing to a function call that returns multiple\n\t// values, in turn getting passed in to the surrounding\n\t// call. Record the assignees so we can favor function\n\t// calls that return matching values.\n\tif len(node.Args) <= 1 && exprIdx == 0 {\n\t\tfor v := range sig.Params().Variables() {\n\t\t\tinf.assignees = append(inf.assignees, v.Type())\n\t\t}\n\n\t\t// Record that we may be completing into variadic parameters.\n\t\tinf.variadicAssignees = sig.Variadic()\n\t}\n\n\t// Make sure not to run past the end of expected parameters.\n\tif exprIdx >= numParams {\n\t\tinf.objType = sig.Params().At(numParams - 1).Type()\n\t} else {\n\t\tinf.objType = sig.Params().At(exprIdx).Type()\n\t}\n\n\tif sig.Variadic() && exprIdx >= (numParams-1) {\n\t\t// If we are completing a variadic param, deslice the variadic type.\n\t\tinf.objType = deslice(inf.objType)\n\t\t// Record whether we are completing the initial variadic param.\n\t\tinf.variadic = exprIdx == numParams-1 && len(node.Args) <= numParams\n\n\t\t// Check if we can infer object kind from printf verb.\n\t\tinf.objKind |= printfArgKind(c.pkg.TypesInfo(), node, exprIdx)\n\t}\n\n\t// If our expected type is an uninstantiated generic type param,\n\t// swap to the constraint which will do a decent job filtering\n\t// candidates.\n\tif tp, _ := inf.objType.(*types.TypeParam); tp != nil {\n\t\tinf.objType = tp.Constraint()\n\t}\n\n\treturn inf\n}\n\nfunc expectedConstraint(t types.Type, idx int) types.Type {\n\tvar tp *types.TypeParamList\n\tif pnt, ok := t.(typesinternal.NamedOrAlias); ok {\n\t\ttp = pnt.TypeParams()\n\t} else if sig, _ := t.Underlying().(*types.Signature); sig != nil {\n\t\ttp = sig.TypeParams()\n\t}\n\tif tp == nil || idx >= tp.Len() {\n\t\treturn nil\n\t}\n\treturn tp.At(idx).Constraint()\n}\n\n// objChain decomposes e into a chain of objects if possible. For\n// example, \"foo.bar().baz\" will yield []types.Object{foo, bar, baz}.\n// If any part can't be turned into an object, return nil.\nfunc objChain(info *types.Info, e ast.Expr) []types.Object {\n\tvar objs []types.Object\n\n\tfor e != nil {\n\t\tswitch n := e.(type) {\n\t\tcase *ast.Ident:\n\t\t\tobj := info.ObjectOf(n)\n\t\t\tif obj == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobjs = append(objs, obj)\n\t\t\te = nil\n\t\tcase *ast.SelectorExpr:\n\t\t\tobj := info.ObjectOf(n.Sel)\n\t\t\tif obj == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobjs = append(objs, obj)\n\t\t\te = n.X\n\t\tcase *ast.CallExpr:\n\t\t\tif len(n.Args) > 0 {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\te = n.Fun\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n\n\t// Reverse order so the layout matches the syntactic order.\n\tslices.Reverse(objs)\n\n\treturn objs\n}\n\n// applyTypeModifiers applies the list of type modifiers to a type.\n// It returns nil if the modifiers could not be applied.\nfunc (ci candidateInference) applyTypeModifiers(typ types.Type, addressable bool) types.Type {\n\tfor _, mod := range ci.modifiers {\n\t\tswitch mod.mod {\n\t\tcase dereference:\n\t\t\t// For every \"*\" indirection operator, remove a pointer layer\n\t\t\t// from candidate type.\n\t\t\tif ptr, ok := typ.Underlying().(*types.Pointer); ok {\n\t\t\t\ttyp = ptr.Elem()\n\t\t\t} else {\n\t\t\t\treturn nil\n\t\t\t}\n\t\tcase reference:\n\t\t\t// For every \"&\" address operator, add another pointer layer to\n\t\t\t// candidate type, if the candidate is addressable.\n\t\t\tif addressable {\n\t\t\t\ttyp = types.NewPointer(typ)\n\t\t\t} else {\n\t\t\t\treturn nil\n\t\t\t}\n\t\tcase chanRead:\n\t\t\t// For every \"<-\" operator, remove a layer of channelness.\n\t\t\tif ch, ok := typ.(*types.Chan); ok {\n\t\t\t\ttyp = ch.Elem()\n\t\t\t} else {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn typ\n}\n\n// applyTypeNameModifiers applies the list of type modifiers to a type name.\nfunc (ci candidateInference) applyTypeNameModifiers(typ types.Type) types.Type {\n\tfor _, mod := range ci.typeName.modifiers {\n\t\tswitch mod.mod {\n\t\tcase reference:\n\t\t\ttyp = types.NewPointer(typ)\n\t\tcase arrayType:\n\t\t\ttyp = types.NewArray(typ, mod.arrayLen)\n\t\tcase sliceType:\n\t\t\ttyp = types.NewSlice(typ)\n\t\t}\n\t}\n\treturn typ\n}\n\n// matchesVariadic returns true if we are completing a variadic\n// parameter and candType is a compatible slice type.\nfunc (ci candidateInference) matchesVariadic(candType types.Type) bool {\n\treturn ci.variadic && ci.objType != nil && assignableTo(candType, types.NewSlice(ci.objType))\n}\n\n// findSwitchStmt returns an *ast.CaseClause's corresponding *ast.SwitchStmt or\n// *ast.TypeSwitchStmt. path should start from the case clause's first ancestor.\nfunc findSwitchStmt(path []ast.Node, pos token.Pos, c *ast.CaseClause) ast.Stmt {\n\t// Make sure position falls within a \"case <>:\" clause.\n\tif exprAtPos(pos, c.List) >= len(c.List) {\n\t\treturn nil\n\t}\n\t// A case clause is always nested within a block statement in a switch statement.\n\tif len(path) < 2 {\n\t\treturn nil\n\t}\n\tif _, ok := path[0].(*ast.BlockStmt); !ok {\n\t\treturn nil\n\t}\n\tswitch s := path[1].(type) {\n\tcase *ast.SwitchStmt:\n\t\treturn s\n\tcase *ast.TypeSwitchStmt:\n\t\treturn s\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// breaksExpectedTypeInference reports if an expression node's type is unrelated\n// to its child expression node types. For example, \"Foo{Bar: x.Baz(<>)}\" should\n// expect a function argument, not a composite literal value.\nfunc breaksExpectedTypeInference(n ast.Node, pos token.Pos) bool {\n\tswitch n := n.(type) {\n\tcase *ast.CompositeLit:\n\t\t// Doesn't break inference if pos is in type name.\n\t\t// For example: \"Foo<>{Bar: 123}\"\n\t\treturn n.Type == nil || !astutil.NodeContainsPos(n.Type, pos)\n\tcase *ast.CallExpr:\n\t\t// Doesn't break inference if pos is in func name.\n\t\t// For example: \"Foo<>(123)\"\n\t\treturn !astutil.NodeContainsPos(n.Fun, pos)\n\tcase *ast.FuncLit, *ast.IndexExpr, *ast.SliceExpr:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// expectTypeName returns information about the expected type name at position.\nfunc expectTypeName(c *completer) typeNameInference {\n\tvar inf typeNameInference\n\nNodes:\n\tfor i, p := range c.path {\n\t\tswitch n := p.(type) {\n\t\tcase *ast.FieldList:\n\t\t\t// Expect a type name if pos is in a FieldList. This applies to\n\t\t\t// FuncType params/results, FuncDecl receiver, StructType, and\n\t\t\t// InterfaceType. We don't need to worry about the field name\n\t\t\t// because completion bails out early if pos is in an *ast.Ident\n\t\t\t// that defines an object.\n\t\t\tinf.wantTypeName = true\n\t\t\tbreak Nodes\n\t\tcase *ast.CaseClause:\n\t\t\t// Expect type names in type switch case clauses.\n\t\t\tif swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, n).(*ast.TypeSwitchStmt); ok {\n\t\t\t\t// The case clause types must be assertable from the type switch parameter.\n\t\t\t\tast.Inspect(swtch.Assign, func(n ast.Node) bool {\n\t\t\t\t\tif ta, ok := n.(*ast.TypeAssertExpr); ok {\n\t\t\t\t\t\tinf.assertableFrom = c.pkg.TypesInfo().TypeOf(ta.X)\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\tinf.wantTypeName = true\n\n\t\t\t\t// Track the types that have already been used in this\n\t\t\t\t// switch's case statements so we don't recommend them.\n\t\t\t\tfor _, e := range swtch.Body.List {\n\t\t\t\t\tfor _, typeExpr := range e.(*ast.CaseClause).List {\n\t\t\t\t\t\t// Skip if type expression contains pos. We don't want to\n\t\t\t\t\t\t// count it as already used if the user is completing it.\n\t\t\t\t\t\tif typeExpr.Pos() < c.pos && c.pos <= typeExpr.End() {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif t := c.pkg.TypesInfo().TypeOf(typeExpr); t != nil {\n\t\t\t\t\t\t\tinf.seenTypeSwitchCases = append(inf.seenTypeSwitchCases, t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak Nodes\n\t\t\t}\n\t\t\treturn typeNameInference{}\n\t\tcase *ast.TypeAssertExpr:\n\t\t\t// Expect type names in type assert expressions.\n\t\t\tif n.Lparen < c.pos && c.pos <= n.Rparen {\n\t\t\t\t// The type in parens must be assertable from the expression type.\n\t\t\t\tinf.assertableFrom = c.pkg.TypesInfo().TypeOf(n.X)\n\t\t\t\tinf.wantTypeName = true\n\t\t\t\tbreak Nodes\n\t\t\t}\n\t\t\treturn typeNameInference{}\n\t\tcase *ast.StarExpr:\n\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: reference})\n\t\tcase *ast.CompositeLit:\n\t\t\t// We want a type name if position is in the \"Type\" part of a\n\t\t\t// composite literal (e.g. \"Foo<>{}\").\n\t\t\tif n.Type != nil && n.Type.Pos() <= c.pos && c.pos <= n.Type.End() {\n\t\t\t\tinf.wantTypeName = true\n\t\t\t\tinf.compLitType = true\n\n\t\t\t\tif i < len(c.path)-1 {\n\t\t\t\t\t// Track preceding \"&\" operator. Technically it applies to\n\t\t\t\t\t// the composite literal and not the type name, but if\n\t\t\t\t\t// affects our type completion nonetheless.\n\t\t\t\t\tif u, ok := c.path[i+1].(*ast.UnaryExpr); ok && u.Op == token.AND {\n\t\t\t\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: reference})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak Nodes\n\t\tcase *ast.ArrayType:\n\t\t\t// If we are inside the \"Elt\" part of an array type, we want a type name.\n\t\t\tif n.Elt.Pos() <= c.pos && c.pos <= n.Elt.End() {\n\t\t\t\tinf.wantTypeName = true\n\t\t\t\tif n.Len == nil {\n\t\t\t\t\t// No \"Len\" expression means a slice type.\n\t\t\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: sliceType})\n\t\t\t\t} else {\n\t\t\t\t\t// Try to get the array type using the constant value of \"Len\".\n\t\t\t\t\ttv, ok := c.pkg.TypesInfo().Types[n.Len]\n\t\t\t\t\tif ok && tv.Value != nil && tv.Value.Kind() == constant.Int {\n\t\t\t\t\t\tif arrayLen, ok := constant.Int64Val(tv.Value); ok {\n\t\t\t\t\t\t\tinf.modifiers = append(inf.modifiers, typeMod{mod: arrayType, arrayLen: arrayLen})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// ArrayTypes can be nested, so keep going if our parent is an\n\t\t\t\t// ArrayType.\n\t\t\t\tif i < len(c.path)-1 {\n\t\t\t\t\tif _, ok := c.path[i+1].(*ast.ArrayType); ok {\n\t\t\t\t\t\tcontinue Nodes\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak Nodes\n\t\t\t}\n\t\tcase *ast.MapType:\n\t\t\tinf.wantTypeName = true\n\t\t\tif n.Key != nil {\n\t\t\t\tinf.wantComparable = astutil.NodeContainsPos(n.Key, c.pos)\n\t\t\t} else {\n\t\t\t\t// If the key is empty, assume we are completing the key if\n\t\t\t\t// pos is directly after the \"map[\".\n\t\t\t\tinf.wantComparable = c.pos == n.Pos()+token.Pos(len(\"map[\"))\n\t\t\t}\n\t\t\tbreak Nodes\n\t\tcase *ast.ValueSpec:\n\t\t\tinf.wantTypeName = n.Type != nil && astutil.NodeContainsPos(n.Type, c.pos)\n\t\t\tbreak Nodes\n\t\tcase *ast.TypeSpec:\n\t\t\tinf.wantTypeName = astutil.NodeContainsPos(n.Type, c.pos)\n\t\tdefault:\n\t\t\tif breaksExpectedTypeInference(p, c.pos) {\n\t\t\t\treturn typeNameInference{}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn inf\n}\n\nfunc (c *completer) fakeObj(T types.Type) *types.Var {\n\treturn types.NewVar(token.NoPos, c.pkg.Types(), \"\", T)\n}\n\n// derivableTypes iterates types you can derive from t. For example,\n// from \"foo\" we might derive \"&foo\", and \"foo()\".\nfunc derivableTypes(t types.Type, addressable bool, f func(t types.Type, addressable bool, mod typeModKind) bool) bool {\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Signature:\n\t\t// If t is a func type with a single result, offer the result type.\n\t\tif t.Results().Len() == 1 && f(t.Results().At(0).Type(), false, invoke) {\n\t\t\treturn true\n\t\t}\n\tcase *types.Array:\n\t\tif f(t.Elem(), true, index) {\n\t\t\treturn true\n\t\t}\n\t\t// Try converting array to slice.\n\t\tif f(types.NewSlice(t.Elem()), false, takeSlice) {\n\t\t\treturn true\n\t\t}\n\tcase *types.Pointer:\n\t\tif f(t.Elem(), false, dereference) {\n\t\t\treturn true\n\t\t}\n\tcase *types.Slice:\n\t\tif f(t.Elem(), true, index) {\n\t\t\treturn true\n\t\t}\n\tcase *types.Map:\n\t\tif f(t.Elem(), false, index) {\n\t\t\treturn true\n\t\t}\n\tcase *types.Chan:\n\t\tif f(t.Elem(), false, chanRead) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Check if c is addressable and a pointer to c matches our type inference.\n\tif addressable && f(types.NewPointer(t), false, reference) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// anyCandType reports whether f returns true for any candidate type\n// derivable from c. It searches up to three levels of type\n// modification. For example, given \"foo\" we could discover \"***foo\"\n// or \"*foo()\".\nfunc (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) bool {\n\tif c.obj == nil || c.obj.Type() == nil {\n\t\treturn false\n\t}\n\n\tconst maxDepth = 3\n\n\tvar searchTypes func(t types.Type, addressable bool, mods []typeModKind) bool\n\tsearchTypes = func(t types.Type, addressable bool, mods []typeModKind) bool {\n\t\tif f(t, addressable) {\n\t\t\tif len(mods) > 0 {\n\t\t\t\tnewMods := make([]typeModKind, len(mods)+len(c.mods))\n\t\t\t\tcopy(newMods, mods)\n\t\t\t\tcopy(newMods[len(mods):], c.mods)\n\t\t\t\tc.mods = newMods\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\n\t\tif len(mods) == maxDepth {\n\t\t\treturn false\n\t\t}\n\n\t\treturn derivableTypes(t, addressable, func(t types.Type, addressable bool, mod typeModKind) bool {\n\t\t\treturn searchTypes(t, addressable, append(mods, mod))\n\t\t})\n\t}\n\n\treturn searchTypes(c.obj.Type(), c.addressable, make([]typeModKind, 0, maxDepth))\n}\n\n// matchingCandidate reports whether cand matches our type inferences.\n// It mutates cand's score in certain cases.\nfunc (c *completer) matchingCandidate(cand *candidate) bool {\n\tif c.completionContext.commentCompletion {\n\t\treturn false\n\t}\n\n\t// Bail out early if we are completing a field name in a composite literal.\n\tif v, ok := cand.obj.(*types.Var); ok && v.IsField() && wantStructFieldCompletions(c.enclosingCompositeLiteral) {\n\t\treturn true\n\t}\n\n\tif isTypeName(cand.obj) {\n\t\treturn c.matchingTypeName(cand)\n\t} else if c.wantTypeName() {\n\t\t// If we want a type, a non-type object never matches.\n\t\treturn false\n\t}\n\n\tif c.inference.candTypeMatches(cand) {\n\t\treturn true\n\t}\n\n\tcandType := cand.obj.Type()\n\tif candType == nil {\n\t\treturn false\n\t}\n\n\tif sig, ok := candType.Underlying().(*types.Signature); ok {\n\t\tif c.inference.assigneesMatch(cand, sig) {\n\t\t\t// Invoke the candidate if its results are multi-assignable.\n\t\t\tcand.mods = append(cand.mods, invoke)\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Default to invoking *types.Func candidates. This is so function\n\t// completions in an empty statement (or other cases with no expected type)\n\t// are invoked by default.\n\tif isFunc(cand.obj) {\n\t\tcand.mods = append(cand.mods, invoke)\n\t}\n\n\treturn false\n}\n\n// candTypeMatches reports whether cand makes a good completion\n// candidate given the candidate inference. cand's score may be\n// mutated to downrank the candidate in certain situations.\nfunc (ci *candidateInference) candTypeMatches(cand *candidate) bool {\n\tvar (\n\t\texpTypes     = make([]types.Type, 0, 2)\n\t\tvariadicType types.Type\n\t)\n\tif ci.objType != nil {\n\t\texpTypes = append(expTypes, ci.objType)\n\n\t\tif ci.variadic {\n\t\t\tvariadicType = types.NewSlice(ci.objType)\n\t\t\texpTypes = append(expTypes, variadicType)\n\t\t}\n\t}\n\n\treturn cand.anyCandType(func(candType types.Type, addressable bool) bool {\n\t\t// Take into account any type modifiers on the expected type.\n\t\tcandType = ci.applyTypeModifiers(candType, addressable)\n\t\tif candType == nil {\n\t\t\treturn false\n\t\t}\n\n\t\tif ci.convertibleTo != nil && convertibleTo(candType, ci.convertibleTo) {\n\t\t\treturn true\n\t\t}\n\n\t\tfor _, expType := range expTypes {\n\t\t\tif isEmptyInterface(expType) {\n\t\t\t\t// If any type matches the expected type, fall back to other\n\t\t\t\t// considerations below.\n\t\t\t\t//\n\t\t\t\t// TODO(rfindley): can this be expressed via scoring, rather than a boolean?\n\t\t\t\t// Why is it the case that we break ties for the empty interface, but\n\t\t\t\t// not for other expected types that may be satisfied by a lot of\n\t\t\t\t// types, such as fmt.Stringer?\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tmatches := ci.typeMatches(expType, candType)\n\t\t\tif !matches {\n\t\t\t\t// If candType doesn't otherwise match, consider if we can\n\t\t\t\t// convert candType directly to expType.\n\t\t\t\tif considerTypeConversion(candType, expType, cand.path) {\n\t\t\t\t\tcand.convertTo = expType\n\t\t\t\t\t// Give a major score penalty so we always prefer directly\n\t\t\t\t\t// assignable candidates, all else equal.\n\t\t\t\t\tcand.score *= 0.5\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif expType == variadicType {\n\t\t\t\tcand.mods = append(cand.mods, takeDotDotDot)\n\t\t\t}\n\n\t\t\t// Candidate matches, but isn't exactly identical to the expected type.\n\t\t\t// Apply a conversion to allow it to match.\n\t\t\tif ci.needsExactType && !types.Identical(candType, expType) {\n\t\t\t\tcand.convertTo = expType\n\t\t\t\t// Ranks barely lower if it needs a conversion, even though it's perfectly valid.\n\t\t\t\tcand.score *= 0.95\n\t\t\t}\n\n\t\t\t// Lower candidate score for untyped conversions. This avoids\n\t\t\t// ranking untyped constants above candidates with an exact type\n\t\t\t// match. Don't lower score of builtin constants, e.g. \"true\".\n\t\t\tif isUntyped(candType) && !types.Identical(candType, expType) && cand.obj.Parent() != types.Universe {\n\t\t\t\t// Bigger penalty for deep completions into other packages to\n\t\t\t\t// avoid random constants from other packages popping up all\n\t\t\t\t// the time.\n\t\t\t\tif len(cand.path) > 0 && isPkgName(cand.path[0]) {\n\t\t\t\t\tcand.score *= 0.5\n\t\t\t\t} else {\n\t\t\t\t\tcand.score *= 0.75\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\n\t\t// If we don't have a specific expected type, fall back to coarser\n\t\t// object kind checks.\n\t\tif ci.objType == nil || isEmptyInterface(ci.objType) {\n\t\t\t// If we were able to apply type modifiers to our candidate type,\n\t\t\t// count that as a match. For example:\n\t\t\t//\n\t\t\t//   var foo chan int\n\t\t\t//   <-fo<>\n\t\t\t//\n\t\t\t// We were able to apply the \"<-\" type modifier to \"foo\", so \"foo\"\n\t\t\t// matches.\n\t\t\tif len(ci.modifiers) > 0 {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If we didn't have an exact type match, check if our object kind\n\t\t\t// matches.\n\t\t\tif ci.kindMatches(candType) {\n\t\t\t\tif ci.objKind == kindFunc {\n\t\t\t\t\tcand.mods = append(cand.mods, invoke)\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t})\n}\n\n// considerTypeConversion returns true if we should offer a completion\n// automatically converting \"from\" to \"to\".\nfunc considerTypeConversion(from, to types.Type, path []types.Object) bool {\n\t// Don't offer to convert deep completions from other packages.\n\t// Otherwise there are many random package level consts/vars that\n\t// pop up as candidates all the time.\n\tif len(path) > 0 && isPkgName(path[0]) {\n\t\treturn false\n\t}\n\n\tif _, ok := from.(*types.TypeParam); ok {\n\t\treturn false\n\t}\n\n\tif !convertibleTo(from, to) {\n\t\treturn false\n\t}\n\n\t// Don't offer to convert ints to strings since that probably\n\t// doesn't do what the user wants.\n\tif isBasicKind(from, types.IsInteger) && isBasicKind(to, types.IsString) {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\n// typeMatches reports whether an object of candType makes a good\n// completion candidate given the expected type expType.\nfunc (ci *candidateInference) typeMatches(expType, candType types.Type) bool {\n\t// Handle untyped values specially since AssignableTo gives false negatives\n\t// for them (see https://golang.org/issue/32146).\n\tif candBasic, ok := candType.Underlying().(*types.Basic); ok {\n\t\tif expBasic, ok := expType.Underlying().(*types.Basic); ok {\n\t\t\t// Note that the candidate and/or the expected can be untyped.\n\t\t\t// In \"fo<> == 100\" the expected type is untyped, and the\n\t\t\t// candidate could also be an untyped constant.\n\n\t\t\t// Sort by is_untyped and then by is_int to simplify below logic.\n\t\t\ta, b := candBasic.Info(), expBasic.Info()\n\t\t\tif a&types.IsUntyped == 0 || (b&types.IsInteger > 0 && b&types.IsUntyped > 0) {\n\t\t\t\ta, b = b, a\n\t\t\t}\n\n\t\t\t// If at least one is untyped...\n\t\t\tif a&types.IsUntyped > 0 {\n\t\t\t\tswitch {\n\t\t\t\t// Untyped integers are compatible with floats.\n\t\t\t\tcase a&types.IsInteger > 0 && b&types.IsFloat > 0:\n\t\t\t\t\treturn true\n\n\t\t\t\t// Check if their constant kind (bool|int|float|complex|string) matches.\n\t\t\t\t// This doesn't take into account the constant value, so there will be some\n\t\t\t\t// false positives due to integer sign and overflow.\n\t\t\t\tcase a&types.IsConstType == b&types.IsConstType:\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// AssignableTo covers the case where the types are equal, but also handles\n\t// cases like assigning a concrete type to an interface type.\n\treturn assignableTo(candType, expType)\n}\n\n// kindMatches reports whether candType's kind matches our expected\n// kind (e.g. slice, map, etc.).\nfunc (ci *candidateInference) kindMatches(candType types.Type) bool {\n\treturn ci.objKind > 0 && ci.objKind&candKind(candType) > 0\n}\n\n// assigneesMatch reports whether an invocation of sig matches the\n// number and type of any assignees.\nfunc (ci *candidateInference) assigneesMatch(cand *candidate, sig *types.Signature) bool {\n\tif len(ci.assignees) == 0 {\n\t\treturn false\n\t}\n\n\t// Uniresult functions are always usable and are handled by the\n\t// normal, non-assignees type matching logic.\n\tif sig.Results().Len() == 1 {\n\t\treturn false\n\t}\n\n\t// Don't prefer completing into func(...interface{}) calls since all\n\t// functions would match.\n\tif ci.variadicAssignees && len(ci.assignees) == 1 && isEmptyInterface(deslice(ci.assignees[0])) {\n\t\treturn false\n\t}\n\n\tvar numberOfResultsCouldMatch bool\n\tif ci.variadicAssignees {\n\t\tnumberOfResultsCouldMatch = sig.Results().Len() >= len(ci.assignees)-1\n\t} else {\n\t\tnumberOfResultsCouldMatch = sig.Results().Len() == len(ci.assignees)\n\t}\n\n\t// If our signature doesn't return the right number of values, it's\n\t// not a match, so downrank it. For example:\n\t//\n\t//  var foo func() (int, int)\n\t//  a, b, c := <> // downrank \"foo()\" since it only returns two values\n\tif !numberOfResultsCouldMatch {\n\t\tcand.score /= 2\n\t\treturn false\n\t}\n\n\t// If at least one assignee has a valid type, and all valid\n\t// assignees match the corresponding sig result value, the signature\n\t// is a match.\n\tallMatch := false\n\tfor i := range sig.Results().Len() {\n\t\tvar assignee types.Type\n\n\t\t// If we are completing into variadic parameters, deslice the\n\t\t// expected variadic type.\n\t\tif ci.variadicAssignees && i >= len(ci.assignees)-1 {\n\t\t\tassignee = ci.assignees[len(ci.assignees)-1]\n\t\t\tif elem := deslice(assignee); elem != nil {\n\t\t\t\tassignee = elem\n\t\t\t}\n\t\t} else {\n\t\t\tassignee = ci.assignees[i]\n\t\t}\n\n\t\tif assignee == nil || assignee == types.Typ[types.Invalid] {\n\t\t\tcontinue\n\t\t}\n\n\t\tallMatch = ci.typeMatches(assignee, sig.Results().At(i).Type())\n\t\tif !allMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn allMatch\n}\n\nfunc (c *completer) matchingTypeName(cand *candidate) bool {\n\tif !c.wantTypeName() {\n\t\treturn false\n\t}\n\n\twantExactTypeParam := c.inference.typeName.isTypeParam &&\n\t\tc.inference.typeName.wantTypeName && c.inference.needsExactType\n\n\ttypeMatches := func(candType types.Type) bool {\n\t\t// Take into account any type name modifier prefixes.\n\t\tcandType = c.inference.applyTypeNameModifiers(candType)\n\n\t\tif from := c.inference.typeName.assertableFrom; from != nil {\n\t\t\t// Don't suggest the starting type in type assertions. For example,\n\t\t\t// if \"foo\" is an io.Writer, don't suggest \"foo.(io.Writer)\".\n\t\t\tif types.Identical(from, candType) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif intf, ok := from.Underlying().(*types.Interface); ok {\n\t\t\t\tif !types.AssertableTo(intf, candType) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Suggest the exact type when performing reverse type inference.\n\t\t// x = Foo[<>]()\n\t\t// Where x is an interface kind, only suggest the interface type rather than its implementors\n\t\tif wantExactTypeParam && types.Identical(candType, c.inference.objType) {\n\t\t\treturn true\n\t\t}\n\n\t\tif c.inference.typeName.wantComparable && !types.Comparable(candType) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Skip this type if it has already been used in another type\n\t\t// switch case.\n\t\tfor _, seen := range c.inference.typeName.seenTypeSwitchCases {\n\t\t\tif types.Identical(candType, seen) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t\t// We can expect a type name and have an expected type in cases like:\n\t\t//\n\t\t//   var foo []int\n\t\t//   foo = []i<>\n\t\t//\n\t\t// Where our expected type is \"[]int\", and we expect a type name.\n\t\tif c.inference.objType != nil {\n\t\t\treturn assignableTo(candType, c.inference.objType)\n\t\t}\n\n\t\t// Default to saying any type name is a match.\n\t\treturn true\n\t}\n\n\tt := cand.obj.Type()\n\n\tif typeMatches(t) {\n\t\treturn true\n\t}\n\n\tif !types.IsInterface(t) && typeMatches(types.NewPointer(t)) {\n\t\tif c.inference.typeName.compLitType {\n\t\t\t// If we are completing a composite literal type as in\n\t\t\t// \"foo<>{}\", to make a pointer we must prepend \"&\".\n\t\t\tcand.mods = append(cand.mods, reference)\n\t\t} else {\n\t\t\t// If we are completing a normal type name such as \"foo<>\", to\n\t\t\t// make a pointer we must prepend \"*\".\n\t\t\tcand.mods = append(cand.mods, dereference)\n\t\t}\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nvar (\n\t// \"interface { Error() string }\" (i.e. error)\n\terrorIntf = types.Universe.Lookup(\"error\").Type().Underlying().(*types.Interface)\n\n\t// \"interface { String() string }\" (i.e. fmt.Stringer)\n\tstringerIntf = types.NewInterfaceType([]*types.Func{\n\t\ttypes.NewFunc(token.NoPos, nil, \"String\", types.NewSignatureType(\n\t\t\tnil, nil,\n\t\t\tnil, nil,\n\t\t\ttypes.NewTuple(types.NewParam(token.NoPos, nil, \"\", types.Typ[types.String])),\n\t\t\tfalse,\n\t\t)),\n\t}, nil).Complete()\n\n\tbyteType = types.Universe.Lookup(\"byte\").Type()\n\n\tboolType = types.Universe.Lookup(\"bool\").Type()\n)\n\n// candKind returns the objKind of candType, if any.\nfunc candKind(candType types.Type) objKind {\n\tvar kind objKind\n\n\tswitch t := candType.Underlying().(type) {\n\tcase *types.Array:\n\t\tkind |= kindArray\n\t\tif t.Elem() == byteType {\n\t\t\tkind |= kindBytes\n\t\t}\n\tcase *types.Slice:\n\t\tkind |= kindSlice\n\t\tif t.Elem() == byteType {\n\t\t\tkind |= kindBytes\n\t\t}\n\tcase *types.Chan:\n\t\tkind |= kindChan\n\tcase *types.Map:\n\t\tkind |= kindMap\n\tcase *types.Pointer:\n\t\tkind |= kindPtr\n\n\t\t// Some builtins handle array pointers as arrays, so just report a pointer\n\t\t// to an array as an array.\n\t\tif _, isArray := t.Elem().Underlying().(*types.Array); isArray {\n\t\t\tkind |= kindArray\n\t\t}\n\tcase *types.Interface:\n\t\tkind |= kindInterface\n\tcase *types.Basic:\n\t\tswitch info := t.Info(); {\n\t\tcase info&types.IsString > 0:\n\t\t\tkind |= kindString\n\t\tcase info&types.IsInteger > 0:\n\t\t\tkind |= kindInt\n\t\tcase info&types.IsFloat > 0:\n\t\t\tkind |= kindFloat\n\t\tcase info&types.IsComplex > 0:\n\t\t\tkind |= kindComplex\n\t\tcase info&types.IsBoolean > 0:\n\t\t\tkind |= kindBool\n\t\t}\n\tcase *types.Signature:\n\t\tkind |= kindFunc\n\n\t\tswitch rangeFuncParamCount(t) {\n\t\tcase 0:\n\t\t\tkind |= kindRange0Func\n\t\tcase 1:\n\t\t\tkind |= kindRange1Func\n\t\tcase 2:\n\t\t\tkind |= kindRange2Func\n\t\t}\n\t}\n\n\tif types.Implements(candType, errorIntf) {\n\t\tkind |= kindError\n\t}\n\n\tif types.Implements(candType, stringerIntf) {\n\t\tkind |= kindStringer\n\t}\n\n\treturn kind\n}\n\n// If sig looks like a range func, return param count, else return -1.\nfunc rangeFuncParamCount(sig *types.Signature) int {\n\tif sig.Results().Len() != 0 || sig.Params().Len() != 1 {\n\t\treturn -1\n\t}\n\n\tyieldSig, _ := sig.Params().At(0).Type().Underlying().(*types.Signature)\n\tif yieldSig == nil {\n\t\treturn -1\n\t}\n\n\tif yieldSig.Results().Len() != 1 || yieldSig.Results().At(0).Type() != boolType {\n\t\treturn -1\n\t}\n\n\treturn yieldSig.Params().Len()\n}\n\n// innermostScope returns the innermost scope for c.pos.\nfunc (c *completer) innermostScope() *types.Scope {\n\tfor _, s := range c.scopes {\n\t\tif s != nil {\n\t\t\treturn s\n\t\t}\n\t}\n\treturn nil\n}\n\n// isSlice reports whether the object's underlying type is a slice.\nfunc isSlice(obj types.Object) bool {\n\tif obj != nil && obj.Type() != nil {\n\t\tif _, ok := obj.Type().Underlying().(*types.Slice); ok {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// forEachPackageMember calls f(tok, id, fn) for each package-level\n// TYPE/VAR/CONST/FUNC declaration in the Go source file, based on a\n// quick partial parse. fn is non-nil only for function declarations.\n// The AST position information is garbage.\nfunc forEachPackageMember(content []byte, f func(tok token.Token, id *ast.Ident, fn *ast.FuncDecl)) {\n\tpurged := astutil.PurgeFuncBodies(content)\n\tfile, _ := parser.ParseFile(token.NewFileSet(), \"\", purged, parser.SkipObjectResolution)\n\tfor _, decl := range file.Decls {\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.GenDecl:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.ValueSpec: // var/const\n\t\t\t\t\tfor _, id := range spec.Names {\n\t\t\t\t\t\tf(decl.Tok, id, nil)\n\t\t\t\t\t}\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tf(decl.Tok, spec.Name, nil)\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.FuncDecl:\n\t\t\tif decl.Recv == nil {\n\t\t\t\tf(token.FUNC, decl.Name, decl)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/deep_completion.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"context\"\n\t\"go/types\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/util/typesutil\"\n\t\"golang.org/x/tools/internal/packagepath\"\n)\n\n// MaxDeepCompletions limits deep completion results because in most cases\n// there are too many to be useful.\nconst MaxDeepCompletions = 3\n\n// deepCompletionState stores our state as we search for deep completions.\n// \"deep completion\" refers to searching into objects' fields and methods to\n// find more completion candidates.\ntype deepCompletionState struct {\n\t// enabled indicates whether deep completion is permitted.\n\tenabled bool\n\n\t// queueClosed is used to disable adding new sub-fields to search queue\n\t// once we're running out of our time budget.\n\tqueueClosed bool\n\n\t// thisQueue holds the current breadth first search queue.\n\tthisQueue []candidate\n\n\t// nextQueue holds the next breadth first search iteration's queue.\n\tnextQueue []candidate\n\n\t// highScores tracks the highest deep candidate scores we have found\n\t// so far. This is used to avoid work for low scoring deep candidates.\n\thighScores [MaxDeepCompletions]float64\n\n\t// candidateCount is the count of unique deep candidates encountered\n\t// so far.\n\tcandidateCount int\n}\n\n// enqueue adds a candidate to the search queue.\nfunc (s *deepCompletionState) enqueue(cand candidate) {\n\ts.nextQueue = append(s.nextQueue, cand)\n}\n\n// scorePenalty computes a deep candidate score penalty. A candidate is\n// penalized based on depth to favor shallower candidates. We also give a\n// slight bonus to unexported objects and a slight additional penalty to\n// function objects.\nfunc (s *deepCompletionState) scorePenalty(cand *candidate) float64 {\n\tvar deepPenalty float64\n\tfor _, dc := range cand.path {\n\t\tdeepPenalty++\n\n\t\tif !dc.Exported() {\n\t\t\tdeepPenalty -= 0.1\n\t\t}\n\n\t\tif _, isSig := dc.Type().Underlying().(*types.Signature); isSig {\n\t\t\tdeepPenalty += 0.1\n\t\t}\n\t}\n\n\t// Normalize penalty to a max depth of 10.\n\treturn deepPenalty / 10\n}\n\n// isHighScore returns whether score is among the top MaxDeepCompletions deep\n// candidate scores encountered so far. If so, it adds score to highScores,\n// possibly displacing an existing high score.\nfunc (s *deepCompletionState) isHighScore(score float64) bool {\n\t// Invariant: s.highScores is sorted with highest score first. Unclaimed\n\t// positions are trailing zeros.\n\n\t// If we beat an existing score then take its spot.\n\tfor i, deepScore := range s.highScores {\n\t\tif score <= deepScore {\n\t\t\tcontinue\n\t\t}\n\n\t\tif deepScore != 0 && i != len(s.highScores)-1 {\n\t\t\t// If this wasn't an empty slot then we need to scooch everyone\n\t\t\t// down one spot.\n\t\t\tcopy(s.highScores[i+1:], s.highScores[i:])\n\t\t}\n\t\ts.highScores[i] = score\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// newPath returns path from search root for an object following a given\n// candidate.\nfunc (s *deepCompletionState) newPath(cand candidate, obj types.Object) []types.Object {\n\tpath := make([]types.Object, len(cand.path)+1)\n\tcopy(path, cand.path)\n\tpath[len(path)-1] = obj\n\n\treturn path\n}\n\n// deepSearch searches a candidate and its subordinate objects for completion\n// items if deep completion is enabled and adds the valid candidates to\n// completion items.\nfunc (c *completer) deepSearch(ctx context.Context, minDepth int, deadline *time.Time) {\n\tdefer func() {\n\t\t// We can return early before completing the search, so be sure to\n\t\t// clear out our queues to not impact any further invocations.\n\t\tc.deepState.thisQueue = c.deepState.thisQueue[:0]\n\t\tc.deepState.nextQueue = c.deepState.nextQueue[:0]\n\t}()\n\n\tdepth := 0 // current depth being processed\n\t// Stop reports whether we should stop the search immediately.\n\tstop := func() bool {\n\t\t// Context cancellation indicates that the actual completion operation was\n\t\t// cancelled, so ignore minDepth and deadline.\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn true\n\t\tdefault:\n\t\t}\n\t\t// Otherwise, only stop if we've searched at least minDepth and reached the deadline.\n\t\treturn depth > minDepth && deadline != nil && time.Now().After(*deadline)\n\t}\n\n\tfor len(c.deepState.nextQueue) > 0 {\n\t\tdepth++\n\t\tif stop() {\n\t\t\treturn\n\t\t}\n\t\tc.deepState.thisQueue, c.deepState.nextQueue = c.deepState.nextQueue, c.deepState.thisQueue[:0]\n\n\touter:\n\t\tfor _, cand := range c.deepState.thisQueue {\n\t\t\tobj := cand.obj\n\n\t\t\tif obj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// At the top level, dedupe by object.\n\t\t\tif len(cand.path) == 0 {\n\t\t\t\tif c.seen[obj] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tc.seen[obj] = true\n\t\t\t}\n\n\t\t\t// If obj is not accessible because it lives in another package and is\n\t\t\t// not exported, don't treat it as a completion candidate unless it's\n\t\t\t// a package completion candidate.\n\t\t\tif !c.completionContext.packageCompletion &&\n\t\t\t\tobj.Pkg() != nil && obj.Pkg() != c.pkg.Types() && !obj.Exported() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif cand.imp != nil && !packagepath.CanImport(string(c.pkg.Metadata().PkgPath), cand.imp.importPath) {\n\t\t\t\tcontinue // inaccessible internal package\n\t\t\t}\n\n\t\t\t// If we want a type name, don't offer non-type name candidates.\n\t\t\t// However, do offer package names since they can contain type names,\n\t\t\t// and do offer any candidate without a type since we aren't sure if it\n\t\t\t// is a type name or not (i.e. unimported candidate).\n\t\t\tif c.wantTypeName() && obj.Type() != nil && !isTypeName(obj) && !isPkgName(obj) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// When searching deep, make sure we don't have a cycle in our chain.\n\t\t\t// We don't dedupe by object because we want to allow both \"foo.Baz\"\n\t\t\t// and \"bar.Baz\" even though \"Baz\" is represented the same types.Object\n\t\t\t// in both.\n\t\t\tfor _, seenObj := range cand.path {\n\t\t\t\tif seenObj == obj {\n\t\t\t\t\tcontinue outer\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.addCandidate(ctx, &cand)\n\n\t\t\tc.deepState.candidateCount++\n\t\t\tif c.opts.budget > 0 && c.deepState.candidateCount%100 == 0 {\n\t\t\t\tif stop() {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tspent := float64(time.Since(c.startTime)) / float64(c.opts.budget)\n\t\t\t\t// If we are almost out of budgeted time, no further elements\n\t\t\t\t// should be added to the queue. This ensures remaining time is\n\t\t\t\t// used for processing current queue.\n\t\t\t\tif !c.deepState.queueClosed && spent >= 0.85 {\n\t\t\t\t\tc.deepState.queueClosed = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if deep search is disabled, don't add any more candidates.\n\t\t\tif !c.deepState.enabled || c.deepState.queueClosed {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Searching members for a type name doesn't make sense.\n\t\t\tif isTypeName(obj) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif obj.Type() == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Don't search embedded fields because they were already included in their\n\t\t\t// parent's fields.\n\t\t\tif v, ok := obj.(*types.Var); ok && v.Embedded() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif sig, ok := obj.Type().Underlying().(*types.Signature); ok {\n\t\t\t\t// If obj is a function that takes no arguments and returns one\n\t\t\t\t// value, keep searching across the function call.\n\t\t\t\tif sig.Params().Len() == 0 && sig.Results().Len() == 1 {\n\t\t\t\t\tpath := c.deepState.newPath(cand, obj)\n\t\t\t\t\t// The result of a function call is not addressable.\n\t\t\t\t\tc.methodsAndFields(sig.Results().At(0).Type(), false, cand.imp, func(newCand candidate) {\n\t\t\t\t\t\tnewCand.pathInvokeMask = cand.pathInvokeMask | (1 << uint64(len(cand.path)))\n\t\t\t\t\t\tnewCand.path = path\n\t\t\t\t\t\tc.deepState.enqueue(newCand)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpath := c.deepState.newPath(cand, obj)\n\t\t\tswitch obj := obj.(type) {\n\t\t\tcase *types.PkgName:\n\t\t\t\tc.packageMembers(obj.Imported(), stdScore, cand.imp, func(newCand candidate) {\n\t\t\t\t\tnewCand.pathInvokeMask = cand.pathInvokeMask\n\t\t\t\t\tnewCand.path = path\n\t\t\t\t\tc.deepState.enqueue(newCand)\n\t\t\t\t})\n\t\t\tdefault:\n\t\t\t\tc.methodsAndFields(obj.Type(), cand.addressable, cand.imp, func(newCand candidate) {\n\t\t\t\t\tnewCand.pathInvokeMask = cand.pathInvokeMask\n\t\t\t\t\tnewCand.path = path\n\t\t\t\t\tc.deepState.enqueue(newCand)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\n// addCandidate adds a completion candidate to suggestions, without searching\n// its members for more candidates.\nfunc (c *completer) addCandidate(ctx context.Context, cand *candidate) {\n\tobj := cand.obj\n\tif c.matchingCandidate(cand) {\n\t\tcand.score *= highScore\n\n\t\tif p := c.penalty(cand); p > 0 {\n\t\t\tcand.score *= (1 - p)\n\t\t}\n\t} else if isTypeName(obj) {\n\t\t// If obj is a *types.TypeName that didn't otherwise match, check\n\t\t// if a literal object of this type makes a good candidate.\n\n\t\t// We only care about named types (i.e. don't want builtin types).\n\t\tif _, isNamed := obj.Type().(*types.Named); isNamed {\n\t\t\tc.literal(ctx, obj.Type(), cand.imp)\n\t\t}\n\t}\n\n\t// Lower score of method calls so we prefer fields and vars over calls.\n\tif cand.hasMod(invoke) {\n\t\tif sig, ok := obj.Type().Underlying().(*types.Signature); ok && sig.Recv() != nil {\n\t\t\tcand.score *= 0.9\n\t\t}\n\t}\n\n\t// Prefer private objects over public ones.\n\tif !obj.Exported() && obj.Parent() != types.Universe {\n\t\tcand.score *= 1.1\n\t}\n\n\t// Slight penalty for index modifier (e.g. changing \"foo\" to\n\t// \"foo[]\") to curb false positives.\n\tif cand.hasMod(index) {\n\t\tcand.score *= 0.9\n\t}\n\n\t// Favor shallow matches by lowering score according to depth.\n\tcand.score -= cand.score * c.deepState.scorePenalty(cand)\n\n\tif cand.score < 0 {\n\t\tcand.score = 0\n\t}\n\n\tcand.name = deepCandName(cand)\n\tif item, err := c.item(ctx, *cand); err == nil {\n\t\tc.items = append(c.items, item)\n\t}\n}\n\n// deepCandName produces the full candidate name including any\n// ancestor objects. For example, \"foo.bar().baz\" for candidate \"baz\".\nfunc deepCandName(cand *candidate) string {\n\ttotalLen := len(cand.obj.Name())\n\tfor i, obj := range cand.path {\n\t\ttotalLen += len(obj.Name()) + 1\n\t\tif cand.pathInvokeMask&(1<<uint16(i)) > 0 {\n\t\t\ttotalLen += 2\n\t\t}\n\t}\n\n\tvar buf strings.Builder\n\tbuf.Grow(totalLen)\n\n\tfor i, obj := range cand.path {\n\t\tbuf.WriteString(obj.Name())\n\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\tbuf.WriteString(typesutil.FormatTypeParams(fn.Signature().TypeParams()))\n\t\t}\n\t\tif cand.pathInvokeMask&(1<<uint16(i)) > 0 {\n\t\t\tbuf.WriteByte('(')\n\t\t\tbuf.WriteByte(')')\n\t\t}\n\t\tbuf.WriteByte('.')\n\t}\n\n\tbuf.WriteString(cand.obj.Name())\n\n\treturn buf.String()\n}\n\n// penalty reports a score penalty for cand in the range (0, 1).\n// For example, a candidate is penalized if it has already been used\n// in another switch case statement.\nfunc (c *completer) penalty(cand *candidate) float64 {\n\tfor _, p := range c.inference.penalized {\n\t\tif c.objChainMatches(cand, p.objChain) {\n\t\t\treturn p.penalty\n\t\t}\n\t}\n\n\treturn 0\n}\n\n// objChainMatches reports whether cand combined with the surrounding\n// object prefix matches chain.\nfunc (c *completer) objChainMatches(cand *candidate, chain []types.Object) bool {\n\t// For example, when completing:\n\t//\n\t//   foo.ba<>\n\t//\n\t// If we are considering the deep candidate \"bar.baz\", cand is baz,\n\t// objChain is [foo] and deepChain is [bar]. We would match the\n\t// chain [foo, bar, baz].\n\tif len(chain) != len(c.inference.objChain)+len(cand.path)+1 {\n\t\treturn false\n\t}\n\n\tif chain[len(chain)-1] != cand.obj {\n\t\treturn false\n\t}\n\n\tfor i, o := range c.inference.objChain {\n\t\tif chain[i] != o {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tfor i, o := range cand.path {\n\t\tif chain[i+len(c.inference.objChain)] != o {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/deep_completion_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"testing\"\n)\n\nfunc TestDeepCompletionIsHighScore(t *testing.T) {\n\t// Test that deepCompletionState.isHighScore properly tracks the top\n\t// N=MaxDeepCompletions scores.\n\n\tvar s deepCompletionState\n\n\tif !s.isHighScore(1) {\n\t\t// No other scores yet, anything is a winner.\n\t\tt.Error(\"1 should be high score\")\n\t}\n\n\t// Fill up with higher scores.\n\tfor range MaxDeepCompletions {\n\t\tif !s.isHighScore(10) {\n\t\t\tt.Error(\"10 should be high score\")\n\t\t}\n\t}\n\n\t// High scores should be filled with 10s so 2 is not a high score.\n\tif s.isHighScore(2) {\n\t\tt.Error(\"2 shouldn't be high score\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/definition.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// some function definitions in test files can be completed\n// So far, TestFoo(t *testing.T), TestMain(m *testing.M)\n// BenchmarkFoo(b *testing.B), FuzzFoo(f *testing.F)\n\n// path[0] is known to be *ast.Ident\nfunc definition(path []ast.Node, obj types.Object, pgf *parsego.File) ([]CompletionItem, *Selection) {\n\tif _, ok := obj.(*types.Func); !ok {\n\t\treturn nil, nil // not a function at all\n\t}\n\tif !strings.HasSuffix(pgf.URI.Path(), \"_test.go\") {\n\t\treturn nil, nil // not a test file\n\t}\n\n\tname := path[0].(*ast.Ident).Name\n\tif len(name) == 0 {\n\t\t// can't happen\n\t\treturn nil, nil\n\t}\n\tstart := path[0].Pos()\n\tend := path[0].End()\n\tsel := &Selection{\n\t\tcontent: \"\", // why isn't this name?\n\t\tcursor:  start,\n\t\ttokFile: pgf.Tok,\n\t\tstart:   start,\n\t\tend:     end,\n\t\tmapper:  pgf.Mapper,\n\t}\n\tsel.check()\n\tvar ans []CompletionItem\n\tvar hasParens bool\n\tn, ok := path[1].(*ast.FuncDecl)\n\tif !ok {\n\t\treturn nil, nil // can't happen\n\t}\n\tif n.Recv != nil {\n\t\treturn nil, nil // a method, not a function\n\t}\n\tt := n.Type.Params\n\tif t.Closing != t.Opening {\n\t\thasParens = true\n\t}\n\n\t// Always suggest TestMain, if possible\n\tif strings.HasPrefix(\"TestMain\", name) {\n\t\tif hasParens {\n\t\t\tans = append(ans, defItem(\"TestMain\", obj))\n\t\t} else {\n\t\t\tans = append(ans, defItem(\"TestMain(m *testing.M)\", obj))\n\t\t}\n\t}\n\n\t// If a snippet is possible, suggest it\n\tif strings.HasPrefix(\"Test\", name) {\n\t\tif hasParens {\n\t\t\tans = append(ans, defItem(\"Test\", obj))\n\t\t} else {\n\t\t\tans = append(ans, defSnippet(\"Test\", \"(t *testing.T)\", obj))\n\t\t}\n\t\treturn ans, sel\n\t} else if strings.HasPrefix(\"Benchmark\", name) {\n\t\tif hasParens {\n\t\t\tans = append(ans, defItem(\"Benchmark\", obj))\n\t\t} else {\n\t\t\tans = append(ans, defSnippet(\"Benchmark\", \"(b *testing.B)\", obj))\n\t\t}\n\t\treturn ans, sel\n\t} else if strings.HasPrefix(\"Fuzz\", name) {\n\t\tif hasParens {\n\t\t\tans = append(ans, defItem(\"Fuzz\", obj))\n\t\t} else {\n\t\t\tans = append(ans, defSnippet(\"Fuzz\", \"(f *testing.F)\", obj))\n\t\t}\n\t\treturn ans, sel\n\t}\n\n\t// Fill in the argument for what the user has already typed\n\tif got := defMatches(name, \"Test\", path, \"(t *testing.T)\"); got != \"\" {\n\t\tans = append(ans, defItem(got, obj))\n\t} else if got := defMatches(name, \"Benchmark\", path, \"(b *testing.B)\"); got != \"\" {\n\t\tans = append(ans, defItem(got, obj))\n\t} else if got := defMatches(name, \"Fuzz\", path, \"(f *testing.F)\"); got != \"\" {\n\t\tans = append(ans, defItem(got, obj))\n\t}\n\treturn ans, sel\n}\n\n// defMatches returns text for defItem, never for defSnippet\nfunc defMatches(name, pat string, path []ast.Node, arg string) string {\n\tif !strings.HasPrefix(name, pat) {\n\t\treturn \"\"\n\t}\n\tc, _ := utf8.DecodeRuneInString(name[len(pat):])\n\tif unicode.IsLower(c) {\n\t\treturn \"\"\n\t}\n\tfd, ok := path[1].(*ast.FuncDecl)\n\tif !ok {\n\t\t// we don't know what's going on\n\t\treturn \"\"\n\t}\n\tfp := fd.Type.Params\n\tif len(fp.List) > 0 {\n\t\t// signature already there, nothing to suggest\n\t\treturn \"\"\n\t}\n\tif fp.Opening != fp.Closing {\n\t\t// nothing: completion works on words, not easy to insert arg\n\t\treturn \"\"\n\t}\n\t// suggesting signature too\n\treturn name + arg\n}\n\nfunc defSnippet(prefix, suffix string, obj types.Object) CompletionItem {\n\tvar sn snippet.Builder\n\tsn.WriteText(prefix)\n\tsn.WritePlaceholder(func(b *snippet.Builder) { b.WriteText(\"Xxx\") })\n\tsn.WriteText(suffix + \" {\\n\\t\")\n\tsn.WriteFinalTabstop()\n\tsn.WriteText(\"\\n}\")\n\treturn CompletionItem{\n\t\tLabel:         prefix + \"Xxx\" + suffix,\n\t\tDetail:        \"tab, type the rest of the name, then tab\",\n\t\tKind:          protocol.FunctionCompletion,\n\t\tDepth:         0,\n\t\tScore:         10,\n\t\tsnippet:       &sn,\n\t\tDocumentation: prefix + \" test function\",\n\t\tisSlice:       isSlice(obj),\n\t}\n}\nfunc defItem(val string, obj types.Object) CompletionItem {\n\treturn CompletionItem{\n\t\tLabel:         val,\n\t\tInsertText:    val,\n\t\tKind:          protocol.FunctionCompletion,\n\t\tDepth:         0,\n\t\tScore:         9, // prefer the snippets when available\n\t\tDocumentation: \"complete the function name\",\n\t\tisSlice:       isSlice(obj),\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/format.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/doc\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/typesutil\"\n\tinternalastutil \"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\nvar (\n\terrNoMatch  = errors.New(\"not a surrounding match\")\n\terrLowScore = errors.New(\"not a high scoring candidate\")\n)\n\n// item formats a candidate to a CompletionItem.\nfunc (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, error) {\n\tobj := cand.obj\n\n\t// if the object isn't a valid match against the surrounding, return early.\n\tmatchScore := c.matcher.Score(cand.name)\n\tif matchScore <= 0 {\n\t\treturn CompletionItem{}, errNoMatch\n\t}\n\tcand.score *= float64(matchScore)\n\n\t// Ignore deep candidates that won't be in the MaxDeepCompletions anyway.\n\tif len(cand.path) != 0 && !c.deepState.isHighScore(cand.score) {\n\t\treturn CompletionItem{}, errLowScore\n\t}\n\n\t// Handle builtin types separately.\n\tif obj.Parent() == types.Universe {\n\t\treturn c.formatBuiltin(ctx, cand)\n\t}\n\n\tvar (\n\t\tlabel         = cand.name\n\t\tdetail        = types.TypeString(obj.Type(), c.qual)\n\t\tinsert        = label\n\t\tkind          = protocol.TextCompletion\n\t\tsnip          snippet.Builder\n\t\tprotocolEdits []protocol.TextEdit\n\t)\n\tif obj.Type() == nil {\n\t\tdetail = \"\"\n\t}\n\n\ttype hasTypeParams interface{ TypeParams() *types.TypeParamList }\n\tif genericType, _ := obj.Type().(hasTypeParams); genericType != nil && isTypeName(obj) && c.wantTypeParams() {\n\t\t// golang/go#71044: note that type names can be basic types, even in\n\t\t// receiver position, for invalid code.\n\t\ttparams := genericType.TypeParams()\n\t\tlabel += typesutil.FormatTypeParams(tparams)\n\t\tinsert = label // maintain invariant above (label == insert)\n\t}\n\n\tsnip.WriteText(insert)\n\n\tswitch obj := obj.(type) {\n\tcase *types.TypeName:\n\t\tdetail, kind = golang.FormatType(obj.Type(), c.qual)\n\tcase *types.Const:\n\t\tkind = protocol.ConstantCompletion\n\tcase *types.Var:\n\t\tif _, ok := obj.Type().(*types.Struct); ok {\n\t\t\tdetail = \"struct{...}\" // for anonymous unaliased struct types\n\t\t} else if obj.IsField() {\n\t\t\tvar err error\n\t\t\tdetail, err = golang.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qual, c.mq)\n\t\t\tif err != nil {\n\t\t\t\treturn CompletionItem{}, err\n\t\t\t}\n\t\t}\n\t\tif obj.IsField() {\n\t\t\tkind = protocol.FieldCompletion\n\t\t\tc.structFieldSnippet(cand, detail, &snip)\n\t\t} else {\n\t\t\tkind = protocol.VariableCompletion\n\t\t}\n\t\tif obj.Type() == nil {\n\t\t\tbreak\n\t\t}\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() == nil {\n\t\t\tkind = protocol.FunctionCompletion\n\t\t} else {\n\t\t\tkind = protocol.MethodCompletion\n\t\t}\n\tcase *types.PkgName:\n\t\tkind = protocol.ModuleCompletion\n\t\tdetail = fmt.Sprintf(\"%q\", obj.Imported().Path())\n\tcase *types.Label:\n\t\tkind = protocol.ConstantCompletion\n\t\tdetail = \"label\"\n\t}\n\n\tvar prefix string\n\tfor _, mod := range cand.mods {\n\t\tswitch mod {\n\t\tcase reference:\n\t\t\tprefix = \"&\" + prefix\n\t\tcase dereference:\n\t\t\tprefix = \"*\" + prefix\n\t\tcase chanRead:\n\t\t\tprefix = \"<-\" + prefix\n\t\t}\n\t}\n\n\tvar (\n\t\tsuffix   string\n\t\tfuncType = obj.Type()\n\t)\nSuffixes:\n\tfor _, mod := range cand.mods {\n\t\tswitch mod {\n\t\tcase invoke:\n\t\t\tif sig, ok := funcType.Underlying().(*types.Signature); ok {\n\t\t\t\ts, err := golang.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qual, c.mq)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn CompletionItem{}, err\n\t\t\t\t}\n\n\t\t\t\ttparams := s.TypeParams()\n\t\t\t\tif len(tparams) > 0 {\n\t\t\t\t\t// Eliminate the suffix of type parameters that are\n\t\t\t\t\t// likely redundant because they can probably be\n\t\t\t\t\t// inferred from the argument types (#51783).\n\t\t\t\t\t//\n\t\t\t\t\t// We don't bother doing the reverse inference from\n\t\t\t\t\t// result types as result-only type parameters are\n\t\t\t\t\t// quite unusual.\n\t\t\t\t\tfree := inferableTypeParams(sig)\n\t\t\t\t\tfor i := sig.TypeParams().Len() - 1; i >= 0; i-- {\n\t\t\t\t\t\ttparam := sig.TypeParams().At(i)\n\t\t\t\t\t\tif !free[tparam] {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttparams = tparams[:i] // eliminate\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tc.functionCallSnippet(\"\", tparams, s.Params(), &snip)\n\t\t\t\tif sig.Results().Len() == 1 {\n\t\t\t\t\tfuncType = sig.Results().At(0).Type()\n\t\t\t\t}\n\t\t\t\tdetail = \"func\" + s.Format()\n\t\t\t}\n\n\t\t\tif !c.opts.snippets {\n\t\t\t\t// Without snippets the candidate will not include \"()\". Don't\n\t\t\t\t// add further suffixes since they will be invalid. For\n\t\t\t\t// example, with snippets \"foo()...\" would become \"foo...\"\n\t\t\t\t// without snippets if we added the dotDotDot.\n\t\t\t\tbreak Suffixes\n\t\t\t}\n\t\tcase takeSlice:\n\t\t\tsuffix += \"[:]\"\n\t\tcase takeDotDotDot:\n\t\t\tsuffix += \"...\"\n\t\tcase index:\n\t\t\tsnip.WriteText(\"[\")\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t\tsnip.WriteText(\"]\")\n\t\t}\n\t}\n\n\t// If this candidate needs an additional import statement,\n\t// add the additional text edits needed.\n\tif cand.imp != nil {\n\t\taddlEdits, err := c.importEdits(cand.imp)\n\n\t\tif err != nil {\n\t\t\treturn CompletionItem{}, err\n\t\t}\n\n\t\tprotocolEdits = append(protocolEdits, addlEdits...)\n\t\tif kind != protocol.ModuleCompletion {\n\t\t\tif detail != \"\" {\n\t\t\t\tdetail += \" \"\n\t\t\t}\n\t\t\tdetail += fmt.Sprintf(\"(from %q)\", cand.imp.importPath)\n\t\t}\n\t}\n\n\tif cand.convertTo != nil {\n\t\tconv := c.formatConversion(cand.convertTo)\n\t\tprefix = conv.prefix + prefix\n\t\tsuffix = conv.suffix\n\t}\n\n\tif prefix != \"\" {\n\t\t// If we are in a selector, add an edit to place prefix before selector.\n\t\tif sel := enclosingSelector(c.path, c.pos); sel != nil {\n\t\t\tedits, err := c.editText(sel.Pos(), sel.Pos(), prefix)\n\t\t\tif err != nil {\n\t\t\t\treturn CompletionItem{}, err\n\t\t\t}\n\t\t\tprotocolEdits = append(protocolEdits, edits...)\n\t\t} else {\n\t\t\t// If there is no selector, just stick the prefix at the start.\n\t\t\tinsert = prefix + insert\n\t\t\tsnip.PrependText(prefix)\n\t\t}\n\t}\n\n\tif suffix != \"\" {\n\t\tinsert += suffix\n\t\tsnip.WriteText(suffix)\n\t}\n\n\tdetail = strings.TrimPrefix(detail, \"untyped \")\n\t// override computed detail with provided detail, if something is provided.\n\tif cand.detail != \"\" {\n\t\tdetail = cand.detail\n\t}\n\titem := CompletionItem{\n\t\tLabel:               label,\n\t\tInsertText:          insert,\n\t\tAdditionalTextEdits: protocolEdits,\n\t\tDetail:              detail,\n\t\tKind:                kind,\n\t\tScore:               cand.score,\n\t\tDepth:               len(cand.path),\n\t\tsnippet:             &snip,\n\t\tisSlice:             isSlice(obj),\n\t}\n\t// If the user doesn't want documentation for completion items.\n\tif !c.opts.documentation {\n\t\treturn item, nil\n\t}\n\tpos := safetoken.StartPosition(c.pkg.FileSet(), obj.Pos())\n\n\t// We ignore errors here, because some types, like \"unsafe\" or \"error\",\n\t// may not have valid positions that we can use to get documentation.\n\tif !pos.IsValid() {\n\t\treturn item, nil\n\t}\n\n\tcomment, err := golang.HoverDocForObject(ctx, c.snapshot, c.pkg.FileSet(), obj)\n\tif err != nil {\n\t\tevent.Error(ctx, fmt.Sprintf(\"failed to find Hover for %q\", obj.Name()), err)\n\t\treturn item, nil\n\t}\n\tif c.opts.fullDocumentation {\n\t\titem.Documentation = comment.Text()\n\t} else {\n\t\titem.Documentation = doc.Synopsis(comment.Text())\n\t}\n\tif internalastutil.Deprecation(comment) != \"\" {\n\t\tif c.snapshot.Options().CompletionTags {\n\t\t\titem.Tags = []protocol.CompletionItemTag{protocol.ComplDeprecated}\n\t\t} else if c.snapshot.Options().CompletionDeprecated {\n\t\t\titem.Deprecated = true\n\t\t}\n\t}\n\n\treturn item, nil\n}\n\n// conversionEdits represents the string edits needed to make a type conversion\n// of an expression.\ntype conversionEdits struct {\n\tprefix, suffix string\n}\n\n// formatConversion returns the edits needed to make a type conversion\n// expression, including parentheses if necessary.\n//\n// Returns empty conversionEdits if convertTo is nil.\nfunc (c *completer) formatConversion(convertTo types.Type) conversionEdits {\n\tif convertTo == nil {\n\t\treturn conversionEdits{}\n\t}\n\n\ttypeName := types.TypeString(convertTo, c.qual)\n\tswitch t := convertTo.(type) {\n\t// We need extra parens when casting to these types. For example,\n\t// we need \"(*int)(foo)\", not \"*int(foo)\".\n\tcase *types.Pointer, *types.Signature:\n\t\ttypeName = \"(\" + typeName + \")\"\n\tcase *types.Basic:\n\t\t// If the types are incompatible (as determined by typeMatches), then we\n\t\t// must need a conversion here. However, if the target type is untyped,\n\t\t// don't suggest converting to e.g. \"untyped float\" (golang/go#62141).\n\t\tif t.Info()&types.IsUntyped != 0 {\n\t\t\ttypeName = types.TypeString(types.Default(convertTo), c.qual)\n\t\t}\n\t}\n\treturn conversionEdits{prefix: typeName + \"(\", suffix: \")\"}\n}\n\n// importEdits produces the text edits necessary to add the given import to the current file.\nfunc (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {\n\tif imp == nil {\n\t\treturn nil, nil\n\t}\n\n\tpgf, err := c.pkg.File(protocol.URIFromPath(c.filename))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn golang.ComputeImportFixEdits(c.snapshot.Options().Local, pgf.Src, &imports.ImportFix{\n\t\tStmtInfo: imports.ImportInfo{\n\t\t\tImportPath: imp.importPath,\n\t\t\tName:       imp.name,\n\t\t},\n\t\t// IdentName is unused on this path and is difficult to get.\n\t\tFixType: imports.AddImport,\n\t})\n}\n\nfunc (c *completer) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) {\n\tobj := cand.obj\n\titem := CompletionItem{\n\t\tLabel:      obj.Name(),\n\t\tInsertText: obj.Name(),\n\t\tScore:      cand.score,\n\t}\n\tswitch obj.(type) {\n\tcase *types.Const:\n\t\titem.Kind = protocol.ConstantCompletion\n\tcase *types.Builtin:\n\t\titem.Kind = protocol.FunctionCompletion\n\t\tsig, err := golang.NewBuiltinSignature(ctx, c.snapshot, obj.Name())\n\t\tif err != nil {\n\t\t\treturn CompletionItem{}, err\n\t\t}\n\t\titem.Detail = \"func\" + sig.Format()\n\t\titem.snippet = &snippet.Builder{}\n\t\t// The signature inferred for a built-in is instantiated, so TypeParams=∅.\n\t\tc.functionCallSnippet(obj.Name(), sig.TypeParams(), sig.Params(), item.snippet)\n\tcase *types.TypeName:\n\t\tif types.IsInterface(obj.Type()) {\n\t\t\titem.Kind = protocol.InterfaceCompletion\n\t\t} else {\n\t\t\titem.Kind = protocol.ClassCompletion\n\t\t}\n\tcase *types.Nil:\n\t\titem.Kind = protocol.VariableCompletion\n\t}\n\treturn item, nil\n}\n\n// decide if the type params (if any) should be part of the completion\n// which only possible for types.Named and types.Signature\n// (so far, only in receivers, e.g.; func (s *GENERIC[K, V])..., which is a types.Named)\nfunc (c *completer) wantTypeParams() bool {\n\t// Need to be lexically in a receiver, and a child of an IndexListExpr\n\t// (but IndexListExpr only exists with go1.18)\n\tstart := c.path[0].Pos()\n\tfor i, nd := range c.path {\n\t\tif fd, ok := nd.(*ast.FuncDecl); ok {\n\t\t\tif i > 0 && fd.Recv != nil && start < fd.Recv.End() {\n\t\t\t\treturn true\n\t\t\t} else {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// inferableTypeParams returns the set of type parameters\n// of sig that are constrained by (inferred from) the argument types.\nfunc inferableTypeParams(sig *types.Signature) map[*types.TypeParam]bool {\n\tfree := make(map[*types.TypeParam]bool)\n\n\t// visit adds to free all the free type parameters of t.\n\tvar visit func(t types.Type)\n\tvisit = func(t types.Type) {\n\t\tswitch t := t.(type) {\n\t\tcase *types.Array:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Chan:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Map:\n\t\t\tvisit(t.Key())\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Pointer:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Slice:\n\t\t\tvisit(t.Elem())\n\t\tcase *types.Interface:\n\t\t\tfor method := range t.ExplicitMethods() {\n\t\t\t\tvisit(method.Type())\n\t\t\t}\n\t\t\tfor etyp := range t.EmbeddedTypes() {\n\t\t\t\tvisit(etyp)\n\t\t\t}\n\t\tcase *types.Union:\n\t\t\tfor term := range t.Terms() {\n\t\t\t\tvisit(term.Type())\n\t\t\t}\n\t\tcase *types.Signature:\n\t\t\tif tp := t.TypeParams(); tp != nil {\n\t\t\t\t// Generic signatures only appear as the type of generic\n\t\t\t\t// function declarations, so this isn't really reachable.\n\t\t\t\tfor tparam := range tp.TypeParams() {\n\t\t\t\t\tvisit(tparam.Constraint())\n\t\t\t\t}\n\t\t\t}\n\t\t\tvisit(t.Params())\n\t\t\tvisit(t.Results())\n\t\tcase *types.Tuple:\n\t\t\tfor v := range t.Variables() {\n\t\t\t\tvisit(v.Type())\n\t\t\t}\n\t\tcase *types.Struct:\n\t\t\tfor field := range t.Fields() {\n\t\t\t\tvisit(field.Type())\n\t\t\t}\n\t\tcase *types.TypeParam:\n\t\t\tfree[t] = true\n\t\tcase *types.Alias:\n\t\t\tvisit(types.Unalias(t))\n\t\tcase *types.Named:\n\t\t\ttargs := t.TypeArgs()\n\t\t\tfor t0 := range targs.Types() {\n\t\t\t\tvisit(t0)\n\t\t\t}\n\t\tcase *types.Basic:\n\t\t\t// nop\n\t\tdefault:\n\t\t\tpanic(t)\n\t\t}\n\t}\n\n\tvisit(sig.Params())\n\n\t// Perform induction through constraints.\nrestart:\n\tfor tp := range sig.TypeParams().TypeParams() {\n\t\tif free[tp] {\n\t\t\tn := len(free)\n\t\t\tvisit(tp.Constraint())\n\t\t\tif len(free) > n {\n\t\t\t\tgoto restart // iterate until fixed point\n\t\t\t}\n\t\t}\n\t}\n\treturn free\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/fuzz.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// golang/go#51089\n// *testing.F deserves special treatment as member use is constrained:\n// The arguments to f.Fuzz are determined by the arguments to a previous f.Add\n// Inside f.Fuzz only f.Failed and f.Name are allowed.\n// PJW: are there other packages where we can deduce usage constraints?\n\n// if we find fuzz completions, then return true, as those are the only completions to offer\nfunc (c *completer) fuzz(testingF types.Type, imp *importInfo, cb func(candidate)) bool {\n\t// 1. inside f.Fuzz? (only f.Failed and f.Name)\n\t// 2. possible completing f.Fuzz?\n\t//    [Ident,SelectorExpr,Callexpr,ExprStmt,BlockiStmt,FuncDecl(Fuzz...)]\n\t// 3. before f.Fuzz, same (for 2., offer choice when looking at an F)\n\n\tmset := types.NewMethodSet(testingF)\n\n\t// does the path contain FuncLit as arg to f.Fuzz CallExpr?\n\tinside := false\nLoop:\n\tfor i, n := range c.path {\n\t\tswitch v := n.(type) {\n\t\tcase *ast.CallExpr:\n\t\t\tif len(v.Args) != 1 {\n\t\t\t\tcontinue Loop\n\t\t\t}\n\t\t\tif _, ok := v.Args[0].(*ast.FuncLit); !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif s, ok := v.Fun.(*ast.SelectorExpr); !ok || s.Sel.Name != \"Fuzz\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif i > 2 { // avoid t.Fuzz itself in tests\n\t\t\t\tinside = true\n\t\t\t\tbreak Loop\n\t\t\t}\n\t\t}\n\t}\n\tif inside {\n\t\tfor method := range mset.Methods() {\n\t\t\to := method.Obj()\n\t\t\tif o.Name() == \"Failed\" || o.Name() == \"Name\" {\n\t\t\t\tcb(candidate{\n\t\t\t\t\tobj:         o,\n\t\t\t\t\tscore:       stdScore,\n\t\t\t\t\timp:         imp,\n\t\t\t\t\taddressable: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\t// if it could be t.Fuzz, look for the preceding t.Add\n\tid, ok := c.path[0].(*ast.Ident)\n\tif ok && strings.HasPrefix(\"Fuzz\", id.Name) {\n\t\tvar add *ast.CallExpr\n\t\tf := func(n ast.Node) bool {\n\t\t\tif n == nil {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcall, ok := n.(*ast.CallExpr)\n\t\t\tif !ok {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\ts, ok := call.Fun.(*ast.SelectorExpr)\n\t\t\tif !ok {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif s.Sel.Name != \"Add\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Sel.X should be of type *testing.F\n\t\t\tgot := c.pkg.TypesInfo().Types[s.X]\n\t\t\tif got.Type.String() == \"*testing.F\" {\n\t\t\t\tadd = call\n\t\t\t}\n\t\t\treturn false // because we're done...\n\t\t}\n\t\t// look at the enclosing FuzzFoo functions\n\t\tif len(c.path) < 2 {\n\t\t\treturn false\n\t\t}\n\t\tn := c.path[len(c.path)-2]\n\t\tif _, ok := n.(*ast.FuncDecl); !ok {\n\t\t\t// the path should start with ast.File, ast.FuncDecl, ...\n\t\t\t// but it didn't, so give up\n\t\t\treturn false\n\t\t}\n\t\tast.Inspect(n, f)\n\t\tif add == nil {\n\t\t\t// looks like f.Fuzz without a preceding f.Add.\n\t\t\t// let the regular completion handle it.\n\t\t\treturn false\n\t\t}\n\n\t\tlbl := \"Fuzz(func(t *testing.T\"\n\t\tfor i, a := range add.Args {\n\t\t\tinfo := c.pkg.TypesInfo().TypeOf(a)\n\t\t\tif info == nil {\n\t\t\t\treturn false // How could this happen, but better safe than panic.\n\t\t\t}\n\t\t\tlbl += fmt.Sprintf(\", %c %s\", 'a'+i, info)\n\t\t}\n\t\tlbl += \")\"\n\t\txx := CompletionItem{\n\t\t\tLabel:         lbl,\n\t\t\tInsertText:    lbl,\n\t\t\tKind:          protocol.FunctionCompletion,\n\t\t\tDepth:         0,\n\t\t\tScore:         10, // pretty confident the user should see this\n\t\t\tDocumentation: \"argument types from f.Add\",\n\t\t\tisSlice:       false,\n\t\t}\n\t\tc.items = append(c.items, xx)\n\t\tfor method := range mset.Methods() {\n\t\t\to := method.Obj()\n\t\t\tif o.Name() != \"Fuzz\" {\n\t\t\t\tcb(candidate{\n\t\t\t\t\tobj:         o,\n\t\t\t\t\tscore:       stdScore,\n\t\t\t\t\timp:         imp,\n\t\t\t\t\taddressable: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn true // done\n\t}\n\t// let the standard processing take care of it instead\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/keywords.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nconst (\n\tBREAK       = \"break\"\n\tCASE        = \"case\"\n\tCHAN        = \"chan\"\n\tCONST       = \"const\"\n\tCONTINUE    = \"continue\"\n\tDEFAULT     = \"default\"\n\tDEFER       = \"defer\"\n\tELSE        = \"else\"\n\tFALLTHROUGH = \"fallthrough\"\n\tFOR         = \"for\"\n\tFUNC        = \"func\"\n\tGO          = \"go\"\n\tGOTO        = \"goto\"\n\tIF          = \"if\"\n\tIMPORT      = \"import\"\n\tINTERFACE   = \"interface\"\n\tMAP         = \"map\"\n\tPACKAGE     = \"package\"\n\tRANGE       = \"range\"\n\tRETURN      = \"return\"\n\tSELECT      = \"select\"\n\tSTRUCT      = \"struct\"\n\tSWITCH      = \"switch\"\n\tTYPE        = \"type\"\n\tVAR         = \"var\"\n)\n\n// addKeywordCompletions offers keyword candidates appropriate at the position.\nfunc (c *completer) addKeywordCompletions() {\n\tseen := make(map[string]bool)\n\n\tif c.wantTypeName() && c.inference.objType == nil {\n\t\t// If we want a type name but don't have an expected obj type,\n\t\t// include \"interface\", \"struct\", \"func\", \"chan\", and \"map\".\n\n\t\t// \"interface\" and \"struct\" are more common declaring named types.\n\t\t// Give them a higher score if we are in a type declaration.\n\t\tstructIntf, funcChanMap := stdScore, highScore\n\t\tif len(c.path) > 1 {\n\t\t\tif _, namedDecl := c.path[1].(*ast.TypeSpec); namedDecl {\n\t\t\t\tstructIntf, funcChanMap = highScore, stdScore\n\t\t\t}\n\t\t}\n\n\t\tc.addKeywordItems(seen, structIntf, STRUCT, INTERFACE)\n\t\tc.addKeywordItems(seen, funcChanMap, FUNC, CHAN, MAP)\n\t}\n\n\t// If we are at the file scope, only offer decl keywords. We don't\n\t// get *ast.Idents at the file scope because non-keyword identifiers\n\t// turn into *ast.BadDecl, not *ast.Ident.\n\tif len(c.path) == 1 || is[*ast.File](c.path[1]) {\n\t\tc.addKeywordItems(seen, stdScore, TYPE, CONST, VAR, FUNC, IMPORT)\n\t\treturn\n\t} else if _, ok := c.path[0].(*ast.Ident); !ok {\n\t\t// Otherwise only offer keywords if the client is completing an identifier.\n\t\treturn\n\t}\n\n\tif len(c.path) > 2 {\n\t\t// Offer \"range\" if we are in ast.ForStmt.Init. This is what the\n\t\t// AST looks like before \"range\" is typed, e.g. \"for i := r<>\".\n\t\tif loop, ok := c.path[2].(*ast.ForStmt); ok && loop.Init != nil && astutil.NodeContainsPos(loop.Init, c.pos) {\n\t\t\tc.addKeywordItems(seen, stdScore, RANGE)\n\t\t}\n\t}\n\n\t// Only suggest keywords if we are beginning a statement.\n\tswitch n := c.path[1].(type) {\n\tcase *ast.BlockStmt, *ast.ExprStmt:\n\t\t// OK - our ident must be at beginning of statement.\n\tcase *ast.CommClause:\n\t\t// Make sure we aren't in the Comm statement.\n\t\tif !n.Colon.IsValid() || c.pos <= n.Colon {\n\t\t\treturn\n\t\t}\n\tcase *ast.CaseClause:\n\t\t// Make sure we aren't in the case List.\n\t\tif !n.Colon.IsValid() || c.pos <= n.Colon {\n\t\t\treturn\n\t\t}\n\tdefault:\n\t\treturn\n\t}\n\n\t// Filter out keywords depending on scope\n\t// Skip the first one because we want to look at the enclosing scopes\n\tpath := c.path[1:]\n\tfor i, n := range path {\n\t\tswitch node := n.(type) {\n\t\tcase *ast.CaseClause:\n\t\t\t// only recommend \"fallthrough\" and \"break\" within the bodies of a case clause\n\t\t\tif c.pos > node.Colon {\n\t\t\t\tc.addKeywordItems(seen, stdScore, BREAK)\n\t\t\t\t// \"fallthrough\" is only valid in switch statements.\n\t\t\t\t// A case clause is always nested within a block statement in a switch statement,\n\t\t\t\t// that block statement is nested within either a TypeSwitchStmt or a SwitchStmt.\n\t\t\t\tif i+2 >= len(path) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif _, ok := path[i+2].(*ast.SwitchStmt); ok {\n\t\t\t\t\tc.addKeywordItems(seen, stdScore, FALLTHROUGH)\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.CommClause:\n\t\t\tif c.pos > node.Colon {\n\t\t\t\tc.addKeywordItems(seen, stdScore, BREAK)\n\t\t\t}\n\t\tcase *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.SwitchStmt:\n\t\t\t// if there is no default case yet, it's highly likely to add a default in switch.\n\t\t\t// we don't offer 'default' anymore if user has used it already in current switch.\n\t\t\tif !hasDefaultClause(node) {\n\t\t\t\tc.addKeywordItems(seen, highScore, CASE, DEFAULT)\n\t\t\t}\n\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\tc.addKeywordItems(seen, stdScore, BREAK, CONTINUE)\n\t\t// This is a bit weak, functions allow for many keywords\n\t\tcase *ast.FuncDecl:\n\t\t\tif node.Body != nil && c.pos > node.Body.Lbrace {\n\t\t\t\t// requireReturnObj checks whether user must provide some objects after return.\n\t\t\t\trequireReturnObj := func(sig *ast.FuncType) bool {\n\t\t\t\t\tresults := sig.Results\n\t\t\t\t\tif results == nil || results.List == nil {\n\t\t\t\t\t\treturn false // nothing to return\n\t\t\t\t\t}\n\t\t\t\t\t// If any result is named, allow a bare return.\n\t\t\t\t\tfor _, r := range results.List {\n\t\t\t\t\t\tfor _, name := range r.Names {\n\t\t\t\t\t\t\tif name.Name != \"_\" {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tret := RETURN\n\t\t\t\tif requireReturnObj(node.Type) {\n\t\t\t\t\t// as user must return something, we offer a space after return.\n\t\t\t\t\t// function literal inside a function will be affected by outer function,\n\t\t\t\t\t// but 'go fmt' will help to remove the ending space.\n\t\t\t\t\t// the benefit is greater than introducing an unnecessary space.\n\t\t\t\t\tret += \" \"\n\t\t\t\t}\n\n\t\t\t\tc.addKeywordItems(seen, stdScore, DEFER, ret, FOR, GO, SWITCH, SELECT, IF, ELSE, VAR, CONST, GOTO, TYPE)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// hasDefaultClause reports whether the given node contains a direct default case.\n// It does not traverse child nodes to look for nested default clauses,\n// and returns false if the node is not a switch statement.\nfunc hasDefaultClause(node ast.Node) bool {\n\tvar cases []ast.Stmt\n\tswitch node := node.(type) {\n\tcase *ast.TypeSwitchStmt:\n\t\tcases = node.Body.List\n\tcase *ast.SelectStmt:\n\t\tcases = node.Body.List\n\tcase *ast.SwitchStmt:\n\t\tcases = node.Body.List\n\t}\n\tfor _, c := range cases {\n\t\tif clause, ok := c.(*ast.CaseClause); ok &&\n\t\t\tclause.List == nil { // default case\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// addKeywordItems dedupes and adds completion items for the specified\n// keywords with the specified score.\nfunc (c *completer) addKeywordItems(seen map[string]bool, score float64, kws ...string) {\n\tfor _, kw := range kws {\n\t\tif seen[kw] {\n\t\t\tcontinue\n\t\t}\n\t\tseen[kw] = true\n\n\t\tif matchScore := c.matcher.Score(kw); matchScore > 0 {\n\t\t\tc.items = append(c.items, CompletionItem{\n\t\t\t\tLabel:      kw,\n\t\t\t\tKind:       protocol.KeywordCompletion,\n\t\t\t\tInsertText: kw,\n\t\t\t\tScore:      score * float64(matchScore),\n\t\t\t})\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/labels.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"math\"\n\t\"slices\"\n)\n\ntype labelType int\n\nconst (\n\tlabelNone labelType = iota\n\tlabelBreak\n\tlabelContinue\n\tlabelGoto\n)\n\n// wantLabelCompletion returns true if we want (only) label\n// completions at the position.\nfunc (c *completer) wantLabelCompletion() labelType {\n\tif _, ok := c.path[0].(*ast.Ident); ok && len(c.path) > 1 {\n\t\t// We want a label if we are an *ast.Ident child of a statement\n\t\t// that accepts a label, e.g. \"break Lo<>\".\n\t\treturn takesLabel(c.path[1])\n\t}\n\n\treturn labelNone\n}\n\n// takesLabel returns the corresponding labelType if n is a statement\n// that accepts a label, otherwise labelNone.\nfunc takesLabel(n ast.Node) labelType {\n\tif bs, ok := n.(*ast.BranchStmt); ok {\n\t\tswitch bs.Tok {\n\t\tcase token.BREAK:\n\t\t\treturn labelBreak\n\t\tcase token.CONTINUE:\n\t\t\treturn labelContinue\n\t\tcase token.GOTO:\n\t\t\treturn labelGoto\n\t\t}\n\t}\n\treturn labelNone\n}\n\n// labels adds completion items for labels defined in the enclosing\n// function.\nfunc (c *completer) labels(lt labelType) {\n\tif c.enclosingFunc == nil {\n\t\treturn\n\t}\n\n\taddLabel := func(score float64, l *ast.LabeledStmt) {\n\t\tlabelObj := c.pkg.TypesInfo().ObjectOf(l.Label)\n\t\tif labelObj != nil {\n\t\t\tc.deepState.enqueue(candidate{obj: labelObj, score: score})\n\t\t}\n\t}\n\n\tswitch lt {\n\tcase labelBreak, labelContinue:\n\t\t// \"break\" and \"continue\" only accept labels from enclosing statements.\n\n\t\tfor i, p := range c.path {\n\t\t\tswitch p := p.(type) {\n\t\t\tcase *ast.FuncLit:\n\t\t\t\t// Labels are function scoped, so don't continue out of functions.\n\t\t\t\treturn\n\t\t\tcase *ast.LabeledStmt:\n\t\t\t\tswitch p.Stmt.(type) {\n\t\t\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\t\t\t// Loop labels can be used for \"break\" or \"continue\".\n\t\t\t\t\taddLabel(highScore*math.Pow(.99, float64(i)), p)\n\t\t\t\tcase *ast.SwitchStmt, *ast.SelectStmt, *ast.TypeSwitchStmt:\n\t\t\t\t\t// Switch and select labels can be used only for \"break\".\n\t\t\t\t\tif lt == labelBreak {\n\t\t\t\t\t\taddLabel(highScore*math.Pow(.99, float64(i)), p)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase labelGoto:\n\t\t// Goto accepts any label in the same function not in a nested\n\t\t// block. It also doesn't take labels that would jump across\n\t\t// variable definitions, but ignore that case for now.\n\t\tast.Inspect(c.enclosingFunc.body, func(n ast.Node) bool {\n\t\t\tif n == nil {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tswitch n := n.(type) {\n\t\t\t// Only search into block-like nodes enclosing our \"goto\".\n\t\t\t// This prevents us from finding labels in nested blocks.\n\t\t\tcase *ast.BlockStmt, *ast.CommClause, *ast.CaseClause:\n\t\t\t\treturn slices.Contains(c.path, n)\n\t\t\tcase *ast.LabeledStmt:\n\t\t\t\taddLabel(highScore, n)\n\t\t\t}\n\n\t\t\treturn true\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/literal.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// literal generates composite literal, function literal, and make()\n// completion items.\nfunc (c *completer) literal(ctx context.Context, literalType types.Type, imp *importInfo) {\n\tif !c.opts.snippets {\n\t\treturn\n\t}\n\n\texpType := c.inference.objType\n\n\tif c.inference.matchesVariadic(literalType) {\n\t\t// Don't offer literal slice candidates for variadic arguments.\n\t\t// For example, don't offer \"[]interface{}{}\" in \"fmt.Print(<>)\".\n\t\treturn\n\t}\n\n\t// Avoid literal candidates if the expected type is an empty\n\t// interface. It isn't very useful to suggest a literal candidate of\n\t// every possible type.\n\tif expType != nil && isEmptyInterface(expType) {\n\t\treturn\n\t}\n\n\t// We handle unnamed literal completions explicitly before searching\n\t// for candidates. Avoid named-type literal completions for\n\t// unnamed-type expected type since that results in duplicate\n\t// candidates. For example, in\n\t//\n\t// type mySlice []int\n\t// var []int = <>\n\t//\n\t// don't offer \"mySlice{}\" since we have already added a candidate\n\t// of \"[]int{}\".\n\n\t// TODO(adonovan): think about aliases:\n\t// they should probably be treated more like Named.\n\t// Should this use Deref not Unpointer?\n\tif is[*types.Named](types.Unalias(literalType)) &&\n\t\texpType != nil &&\n\t\t!is[*types.Named](types.Unalias(typesinternal.Unpointer(expType))) {\n\n\t\treturn\n\t}\n\n\t// Check if an object of type literalType would match our expected type.\n\tcand := candidate{\n\t\tobj: c.fakeObj(literalType),\n\t}\n\n\tswitch literalType.Underlying().(type) {\n\t// These literal types are addressable (e.g. \"&[]int{}\"), others are\n\t// not (e.g. can't do \"&(func(){})\").\n\tcase *types.Struct, *types.Array, *types.Slice, *types.Map:\n\t\tcand.addressable = true\n\t}\n\n\t// Only suggest a literal conversion if the exact type is known.\n\tif !c.matchingCandidate(&cand) || (cand.convertTo != nil && !c.inference.needsExactType) {\n\t\treturn\n\t}\n\n\tvar (\n\t\tqual       = c.qual\n\t\tsel        = enclosingSelector(c.path, c.pos)\n\t\tconversion conversionEdits\n\t)\n\n\tif cand.convertTo != nil {\n\t\tconversion = c.formatConversion(cand.convertTo)\n\t}\n\n\t// Don't qualify the type name if we are in a selector expression\n\t// since the package name is already present.\n\tif sel != nil {\n\t\tqual = func(_ *types.Package) string { return \"\" }\n\t}\n\n\tsnip, typeName := c.typeNameSnippet(literalType, qual)\n\n\t// A type name of \"[]int\" doesn't work very will with the matcher\n\t// since \"[\" isn't a valid identifier prefix. Here we strip off the\n\t// slice (and array) prefix yielding just \"int\".\n\tmatchName := typeName\n\tswitch t := literalType.(type) {\n\tcase *types.Slice:\n\t\tmatchName = types.TypeString(t.Elem(), qual)\n\tcase *types.Array:\n\t\tmatchName = types.TypeString(t.Elem(), qual)\n\t}\n\n\taddlEdits, err := c.importEdits(imp)\n\tif err != nil {\n\t\tevent.Error(ctx, \"error adding import for literal candidate\", err)\n\t\treturn\n\t}\n\n\t// If prefix matches the type name, client may want a composite literal.\n\tif score := c.matcher.Score(matchName); score > 0 {\n\t\tif cand.hasMod(reference) {\n\t\t\tif sel != nil {\n\t\t\t\t// If we are in a selector we must place the \"&\" before the selector.\n\t\t\t\t// For example, \"foo.B<>\" must complete to \"&foo.Bar{}\", not\n\t\t\t\t// \"foo.&Bar{}\".\n\t\t\t\tedits, err := c.editText(sel.Pos(), sel.Pos(), \"&\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tevent.Error(ctx, \"error making edit for literal pointer completion\", err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\taddlEdits = append(addlEdits, edits...)\n\t\t\t} else {\n\t\t\t\t// Otherwise we can stick the \"&\" directly before the type name.\n\t\t\t\ttypeName = \"&\" + typeName\n\t\t\t\tsnip.PrependText(\"&\")\n\t\t\t}\n\t\t}\n\n\t\tswitch t := literalType.Underlying().(type) {\n\t\tcase *types.Struct, *types.Array, *types.Slice, *types.Map:\n\t\t\titem := c.compositeLiteral(t, snip.Clone(), typeName, float64(score), addlEdits)\n\t\t\titem.addConversion(c, conversion)\n\t\t\tc.items = append(c.items, item)\n\t\tcase *types.Signature:\n\t\t\t// Add a literal completion for a signature type that implements\n\t\t\t// an interface. For example, offer \"http.HandlerFunc()\" when\n\t\t\t// expected type is \"http.Handler\".\n\t\t\tif expType != nil && types.IsInterface(expType) {\n\t\t\t\tif item, ok := c.basicLiteral(t, snip.Clone(), typeName, float64(score), addlEdits); ok {\n\t\t\t\t\titem.addConversion(c, conversion)\n\t\t\t\t\tc.items = append(c.items, item)\n\t\t\t\t}\n\t\t\t}\n\t\tcase *types.Basic:\n\t\t\t// Add a literal completion for basic types that implement our\n\t\t\t// expected interface (e.g. named string type http.Dir\n\t\t\t// implements http.FileSystem), or are identical to our expected\n\t\t\t// type (i.e. yielding a type conversion such as \"float64()\").\n\t\t\tif expType != nil && (types.IsInterface(expType) || types.Identical(expType, literalType)) {\n\t\t\t\tif item, ok := c.basicLiteral(t, snip.Clone(), typeName, float64(score), addlEdits); ok {\n\t\t\t\t\titem.addConversion(c, conversion)\n\t\t\t\t\tc.items = append(c.items, item)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If prefix matches \"make\", client may want a \"make()\"\n\t// invocation. We also include the type name to allow for more\n\t// flexible fuzzy matching.\n\tif score := c.matcher.Score(\"make.\" + matchName); !cand.hasMod(reference) && score > 0 {\n\t\tswitch literalType.Underlying().(type) {\n\t\tcase *types.Slice:\n\t\t\t// The second argument to \"make()\" for slices is required, so default to \"0\".\n\t\t\titem := c.makeCall(snip.Clone(), typeName, \"0\", float64(score), addlEdits)\n\t\t\titem.addConversion(c, conversion)\n\t\t\tc.items = append(c.items, item)\n\t\tcase *types.Map, *types.Chan:\n\t\t\t// Maps and channels don't require the second argument, so omit\n\t\t\t// to keep things simple for now.\n\t\t\titem := c.makeCall(snip.Clone(), typeName, \"\", float64(score), addlEdits)\n\t\t\titem.addConversion(c, conversion)\n\t\t\tc.items = append(c.items, item)\n\t\t}\n\t}\n\n\t// If prefix matches \"func\", client may want a function literal.\n\tif score := c.matcher.Score(\"func\"); !cand.hasMod(reference) && score > 0 && (expType == nil || !types.IsInterface(expType)) {\n\t\tswitch t := literalType.Underlying().(type) {\n\t\tcase *types.Signature:\n\t\t\tif item, ok := c.functionLiteral(ctx, t, float64(score)); ok {\n\t\t\t\titem.addConversion(c, conversion)\n\t\t\t\tc.items = append(c.items, item)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// literalCandidateScore is the base score for literal candidates.\n// Literal candidates match the expected type so they should be high\n// scoring, but we want them ranked below lexical objects of the\n// correct type, so scale down highScore.\nconst literalCandidateScore = highScore / 2\n\n// functionLiteral returns a function literal completion item for the\n// given signature, if applicable.\nfunc (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, matchScore float64) (CompletionItem, bool) {\n\tsnip := &snippet.Builder{}\n\tsnip.WriteText(\"func(\")\n\n\t// First we generate names for each param and keep a seen count so\n\t// we know if we need to uniquify param names. For example,\n\t// \"func(int)\" will become \"func(i int)\", but \"func(int, int64)\"\n\t// will become \"func(i1 int, i2 int64)\".\n\tvar (\n\t\tparamNames     = make([]string, sig.Params().Len())\n\t\tparamNameCount = make(map[string]int)\n\t\thasTypeParams  bool\n\t)\n\tfor i := range sig.Params().Len() {\n\t\tvar (\n\t\t\tp    = sig.Params().At(i)\n\t\t\tname = p.Name()\n\t\t)\n\n\t\tif tp, _ := types.Unalias(p.Type()).(*types.TypeParam); tp != nil && !c.typeParamInScope(tp) {\n\t\t\thasTypeParams = true\n\t\t}\n\n\t\tif name == \"\" {\n\t\t\t// If the param has no name in the signature, guess a name based\n\t\t\t// on the type. Use an empty qualifier to ignore the package.\n\t\t\t// For example, we want to name \"http.Request\" \"r\", not \"hr\".\n\t\t\ttypeName, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, p,\n\t\t\t\tfunc(p *types.Package) string { return \"\" },\n\t\t\t\tfunc(golang.PackageName, golang.ImportPath, golang.PackagePath) string { return \"\" })\n\t\t\tif err != nil {\n\t\t\t\t// In general, the only error we should encounter while formatting is\n\t\t\t\t// context cancellation.\n\t\t\t\tif ctx.Err() == nil {\n\t\t\t\t\tevent.Error(ctx, \"formatting var type\", err)\n\t\t\t\t}\n\t\t\t\treturn CompletionItem{}, false\n\t\t\t}\n\t\t\tname = abbreviateTypeName(typeName)\n\t\t}\n\t\tparamNames[i] = name\n\t\tif name != \"_\" {\n\t\t\tparamNameCount[name]++\n\t\t}\n\t}\n\n\tfor n, c := range paramNameCount {\n\t\t// Any names we saw more than once will need a unique suffix added\n\t\t// on. Reset the count to 1 to act as the suffix for the first\n\t\t// name.\n\t\tif c >= 2 {\n\t\t\tparamNameCount[n] = 1\n\t\t} else {\n\t\t\tdelete(paramNameCount, n)\n\t\t}\n\t}\n\n\tfor i := range sig.Params().Len() {\n\t\tif hasTypeParams && !c.opts.placeholders {\n\t\t\t// If there are type params in the args then the user must\n\t\t\t// choose the concrete types. If placeholders are disabled just\n\t\t\t// drop them between the parens and let them fill things in.\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t\tbreak\n\t\t}\n\n\t\tif i > 0 {\n\t\t\tsnip.WriteText(\", \")\n\t\t}\n\n\t\tvar (\n\t\t\tp    = sig.Params().At(i)\n\t\t\tname = paramNames[i]\n\t\t)\n\n\t\t// Uniquify names by adding on an incrementing numeric suffix.\n\t\tif idx, found := paramNameCount[name]; found {\n\t\t\tparamNameCount[name]++\n\t\t\tname = fmt.Sprintf(\"%s%d\", name, idx)\n\t\t}\n\n\t\tif name != p.Name() && c.opts.placeholders {\n\t\t\t// If we didn't use the signature's param name verbatim then we\n\t\t\t// may have chosen a poor name. Give the user a placeholder so\n\t\t\t// they can easily fix the name.\n\t\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\t\tb.WriteText(name)\n\t\t\t})\n\t\t} else {\n\t\t\tsnip.WriteText(name)\n\t\t}\n\n\t\t// If the following param's type is identical to this one, omit\n\t\t// this param's type string. For example, emit \"i, j int\" instead\n\t\t// of \"i int, j int\".\n\t\tif i == sig.Params().Len()-1 || !types.Identical(p.Type(), sig.Params().At(i+1).Type()) {\n\t\t\tsnip.WriteText(\" \")\n\t\t\ttypeStr, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, p, c.qual, c.mq)\n\t\t\tif err != nil {\n\t\t\t\t// In general, the only error we should encounter while formatting is\n\t\t\t\t// context cancellation.\n\t\t\t\tif ctx.Err() == nil {\n\t\t\t\t\tevent.Error(ctx, \"formatting var type\", err)\n\t\t\t\t}\n\t\t\t\treturn CompletionItem{}, false\n\t\t\t}\n\t\t\tif sig.Variadic() && i == sig.Params().Len()-1 {\n\t\t\t\ttypeStr = strings.Replace(typeStr, \"[]\", \"...\", 1)\n\t\t\t}\n\n\t\t\tif tp, ok := types.Unalias(p.Type()).(*types.TypeParam); ok && !c.typeParamInScope(tp) {\n\t\t\t\tsnip.WritePlaceholder(func(snip *snippet.Builder) {\n\t\t\t\t\tsnip.WriteText(typeStr)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsnip.WriteText(typeStr)\n\t\t\t}\n\t\t}\n\t}\n\tsnip.WriteText(\")\")\n\n\tresults := sig.Results()\n\tif results.Len() > 0 {\n\t\tsnip.WriteText(\" \")\n\t}\n\n\tresultsNeedParens := results.Len() > 1 ||\n\t\tresults.Len() == 1 && results.At(0).Name() != \"\"\n\n\tvar resultHasTypeParams bool\n\tfor v := range results.Variables() {\n\t\tif tp, ok := types.Unalias(v.Type()).(*types.TypeParam); ok && !c.typeParamInScope(tp) {\n\t\t\tresultHasTypeParams = true\n\t\t}\n\t}\n\n\tif resultsNeedParens {\n\t\tsnip.WriteText(\"(\")\n\t}\n\tfor i := range results.Len() {\n\t\tif resultHasTypeParams && !c.opts.placeholders {\n\t\t\t// Leave an empty tabstop if placeholders are disabled and there\n\t\t\t// are type args that need specifying.\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t\tbreak\n\t\t}\n\n\t\tif i > 0 {\n\t\t\tsnip.WriteText(\", \")\n\t\t}\n\t\tr := results.At(i)\n\t\tif name := r.Name(); name != \"\" {\n\t\t\tsnip.WriteText(name + \" \")\n\t\t}\n\n\t\ttext, err := golang.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qual, c.mq)\n\t\tif err != nil {\n\t\t\t// In general, the only error we should encounter while formatting is\n\t\t\t// context cancellation.\n\t\t\tif ctx.Err() == nil {\n\t\t\t\tevent.Error(ctx, \"formatting var type\", err)\n\t\t\t}\n\t\t\treturn CompletionItem{}, false\n\t\t}\n\t\tif tp, ok := types.Unalias(r.Type()).(*types.TypeParam); ok && !c.typeParamInScope(tp) {\n\t\t\tsnip.WritePlaceholder(func(snip *snippet.Builder) {\n\t\t\t\tsnip.WriteText(text)\n\t\t\t})\n\t\t} else {\n\t\t\tsnip.WriteText(text)\n\t\t}\n\t}\n\tif resultsNeedParens {\n\t\tsnip.WriteText(\")\")\n\t}\n\n\tsnip.WriteText(\" {\")\n\tsnip.WriteFinalTabstop()\n\tsnip.WriteText(\"}\")\n\n\treturn CompletionItem{\n\t\tLabel:   \"func(...) {}\",\n\t\tScore:   matchScore * literalCandidateScore,\n\t\tKind:    protocol.VariableCompletion,\n\t\tsnippet: snip,\n\t}, true\n}\n\n// conventionalAcronyms contains conventional acronyms for type names\n// in lower case. For example, \"ctx\" for \"context\" and \"err\" for \"error\".\n//\n// Keep this up to date with golang.conventionalVarNames.\nvar conventionalAcronyms = map[string]string{\n\t\"context\":        \"ctx\",\n\t\"error\":          \"err\",\n\t\"tx\":             \"tx\",\n\t\"responsewriter\": \"w\",\n}\n\n// abbreviateTypeName abbreviates type names into acronyms. For\n// example, \"fooBar\" is abbreviated \"fb\". Care is taken to ignore\n// non-identifier runes. For example, \"[]int\" becomes \"i\", and\n// \"struct { i int }\" becomes \"s\".\nfunc abbreviateTypeName(s string) string {\n\t// Trim off leading non-letters. We trim everything between \"[\" and\n\t// \"]\" to handle array types like \"[someConst]int\".\n\tvar inBracket bool\n\ts = strings.TrimFunc(s, func(r rune) bool {\n\t\tif inBracket {\n\t\t\tinBracket = r != ']'\n\t\t\treturn true\n\t\t}\n\n\t\tif r == '[' {\n\t\t\tinBracket = true\n\t\t}\n\n\t\treturn !unicode.IsLetter(r)\n\t})\n\n\tif acr, ok := conventionalAcronyms[strings.ToLower(s)]; ok {\n\t\treturn acr\n\t}\n\n\treturn golang.AbbreviateVarName(s)\n}\n\n// compositeLiteral returns a composite literal completion item for the given typeName.\n// T is an (unnamed, unaliased) struct, array, slice, or map type.\nfunc (c *completer) compositeLiteral(T types.Type, snip *snippet.Builder, typeName string, matchScore float64, edits []protocol.TextEdit) CompletionItem {\n\tsnip.WriteText(\"{\")\n\t// Don't put the tab stop inside the composite literal curlies \"{}\"\n\t// for structs that have no accessible fields.\n\tif strct, ok := T.(*types.Struct); !ok || fieldsAccessible(strct, c.pkg.Types()) {\n\t\tsnip.WriteFinalTabstop()\n\t}\n\tsnip.WriteText(\"}\")\n\n\tnonSnippet := typeName + \"{}\"\n\n\treturn CompletionItem{\n\t\tLabel:               nonSnippet,\n\t\tInsertText:          nonSnippet,\n\t\tScore:               matchScore * literalCandidateScore,\n\t\tKind:                protocol.VariableCompletion,\n\t\tAdditionalTextEdits: edits,\n\t\tsnippet:             snip,\n\t}\n}\n\n// basicLiteral returns a literal completion item for the given basic\n// type name typeName.\n//\n// If T is untyped, this function returns false.\nfunc (c *completer) basicLiteral(T types.Type, snip *snippet.Builder, typeName string, matchScore float64, edits []protocol.TextEdit) (CompletionItem, bool) {\n\t// Never give type conversions like \"untyped int()\".\n\tif isUntyped(T) {\n\t\treturn CompletionItem{}, false\n\t}\n\n\tsnip.WriteText(\"(\")\n\tsnip.WriteFinalTabstop()\n\tsnip.WriteText(\")\")\n\n\tnonSnippet := typeName + \"()\"\n\n\treturn CompletionItem{\n\t\tLabel:               nonSnippet,\n\t\tInsertText:          nonSnippet,\n\t\tDetail:              T.String(),\n\t\tScore:               matchScore * literalCandidateScore,\n\t\tKind:                protocol.VariableCompletion,\n\t\tAdditionalTextEdits: edits,\n\t\tsnippet:             snip,\n\t}, true\n}\n\n// makeCall returns a completion item for a \"make()\" call given a specific type.\nfunc (c *completer) makeCall(snip *snippet.Builder, typeName string, secondArg string, matchScore float64, edits []protocol.TextEdit) CompletionItem {\n\t// Keep it simple and don't add any placeholders for optional \"make()\" arguments.\n\n\tsnip.PrependText(\"make(\")\n\tif secondArg != \"\" {\n\t\tsnip.WriteText(\", \")\n\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\tif c.opts.placeholders {\n\t\t\t\tb.WriteText(secondArg)\n\t\t\t}\n\t\t})\n\t}\n\tsnip.WriteText(\")\")\n\n\tvar nonSnippet strings.Builder\n\tnonSnippet.WriteString(\"make(\" + typeName)\n\tif secondArg != \"\" {\n\t\tnonSnippet.WriteString(\", \")\n\t\tnonSnippet.WriteString(secondArg)\n\t}\n\tnonSnippet.WriteByte(')')\n\n\treturn CompletionItem{\n\t\tLabel:      nonSnippet.String(),\n\t\tInsertText: nonSnippet.String(),\n\t\t// make() should be just below other literal completions\n\t\tScore:               matchScore * literalCandidateScore * 0.99,\n\t\tKind:                protocol.FunctionCompletion,\n\t\tAdditionalTextEdits: edits,\n\t\tsnippet:             snip,\n\t}\n}\n\n// Create a snippet for a type name where type params become placeholders.\nfunc (c *completer) typeNameSnippet(literalType types.Type, qual types.Qualifier) (*snippet.Builder, string) {\n\tvar (\n\t\tsnip     snippet.Builder\n\t\ttypeName string\n\t\ttparams  *types.TypeParamList\n\t)\n\n\tt, ok := literalType.(typesinternal.NamedOrAlias) // = *Named | *Alias\n\tif ok {\n\t\ttparams = t.TypeParams()\n\t}\n\tif tparams.Len() > 0 && !c.fullyInstantiated(t) {\n\t\t// tparams.Len() > 0 implies t != nil.\n\t\t// Inv: t is not \"error\" or \"unsafe.Pointer\", so t.Obj() != nil and has a Pkg().\n\n\t\t// We are not \"fully instantiated\" meaning we have type params that must be specified.\n\t\tif pkg := qual(t.Obj().Pkg()); pkg != \"\" {\n\t\t\ttypeName = pkg + \".\"\n\t\t}\n\n\t\t// We do this to get \"someType\" instead of \"someType[T]\".\n\t\ttypeName += t.Obj().Name()\n\t\tsnip.WriteText(typeName + \"[\")\n\n\t\tif c.opts.placeholders {\n\t\t\tfor i := range tparams.Len() {\n\t\t\t\tif i > 0 {\n\t\t\t\t\tsnip.WriteText(\", \")\n\t\t\t\t}\n\t\t\t\tsnip.WritePlaceholder(func(snip *snippet.Builder) {\n\t\t\t\t\tsnip.WriteText(types.TypeString(tparams.At(i), qual))\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t}\n\t\tsnip.WriteText(\"]\")\n\t\ttypeName += \"[...]\"\n\t} else {\n\t\t// We don't have unspecified type params so use default type formatting.\n\t\ttypeName = types.TypeString(literalType, qual)\n\t\tsnip.WriteText(typeName)\n\t}\n\n\treturn &snip, typeName\n}\n\n// fullyInstantiated reports whether all of t's type params have\n// specified type args.\nfunc (c *completer) fullyInstantiated(t typesinternal.NamedOrAlias) bool {\n\ttargs := t.TypeArgs()\n\ttparams := t.TypeParams()\n\n\tif tparams.Len() != targs.Len() {\n\t\treturn false\n\t}\n\n\tfor targ := range targs.Types() {\n\n\t\t// The expansion of an alias can have free type parameters,\n\t\t// whether or not the alias itself has type parameters:\n\t\t//\n\t\t//   func _[K comparable]() {\n\t\t//     type Set      = map[K]bool // free(Set)      = {K}\n\t\t//     type MapTo[V] = map[K]V    // free(Map[foo]) = {V}\n\t\t//   }\n\t\t//\n\t\t// So, we must Unalias.\n\t\tswitch targ := types.Unalias(targ).(type) {\n\t\tcase *types.TypeParam:\n\t\t\t// A *TypeParam only counts as specified if it is currently in\n\t\t\t// scope (i.e. we are in a generic definition).\n\t\t\tif !c.typeParamInScope(targ) {\n\t\t\t\treturn false\n\t\t\t}\n\t\tcase *types.Named:\n\t\t\tif !c.fullyInstantiated(targ) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n// typeParamInScope returns whether tp's object is in scope at c.pos.\n// This tells you whether you are in a generic definition and can\n// assume tp has been specified.\nfunc (c *completer) typeParamInScope(tp *types.TypeParam) bool {\n\tobj := tp.Obj()\n\tif obj == nil {\n\t\treturn false\n\t}\n\n\tscope := c.innermostScope()\n\tif scope == nil {\n\t\treturn false\n\t}\n\n\t_, foundObj := scope.LookupParent(obj.Name(), c.pos)\n\treturn obj == foundObj\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/newfile.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// NewFile returns a document change to complete an empty Go source file. Document change may be nil.\nfunc NewFile(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) (*protocol.DocumentChange, error) {\n\tif !snapshot.Options().NewGoFileHeader {\n\t\treturn nil, nil\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(content) != 0 {\n\t\treturn nil, fmt.Errorf(\"file is not empty\")\n\t}\n\tmeta, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar buf bytes.Buffer\n\t// Copy the copyright header from the first existing file that has one.\n\tfor _, fileURI := range meta.GoFiles {\n\t\tif fileURI == fh.URI() {\n\t\t\tcontinue\n\t\t}\n\t\tfh, err := snapshot.ReadFile(ctx, fileURI)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif group := golang.CopyrightComment(pgf.File); group != nil {\n\t\t\ttext, err := pgf.NodeText(group)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbuf.Write(text)\n\t\t\tbuf.WriteString(\"\\n\\n\")\n\t\t\tbreak\n\t\t}\n\t}\n\n\tpkgName, err := bestPackage(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfmt.Fprintf(&buf, \"package %s\\n\", pkgName)\n\tchange := protocol.DocumentChangeEdit(fh, []protocol.TextEdit{{\n\t\tRange:   protocol.Range{}, // insert at start of file\n\t\tNewText: buf.String(),\n\t}})\n\n\treturn &change, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/package.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// bestPackage offers the best package name for a package declaration when\n// one is not present in the given file.\nfunc bestPackage(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (string, error) {\n\tsuggestions, err := packageSuggestions(ctx, snapshot, uri, \"\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t// sort with the same way of sortItems.\n\tsort.SliceStable(suggestions, func(i, j int) bool {\n\t\tif suggestions[i].score != suggestions[j].score {\n\t\t\treturn suggestions[i].score > suggestions[j].score\n\t\t}\n\t\treturn suggestions[i].name < suggestions[j].name\n\t})\n\n\treturn suggestions[0].name, nil\n}\n\n// packageClauseCompletions offers completions for a package declaration when\n// one is not present in the given file.\nfunc packageClauseCompletions(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) ([]CompletionItem, *Selection, error) {\n\t// We know that the AST for this file will be empty due to the missing\n\t// package declaration, but parse it anyway to get a mapper.\n\t// TODO(adonovan): opt: there's no need to parse just to get a mapper.\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\toffset, err := pgf.Mapper.PositionOffset(position)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tsurrounding, err := packageCompletionSurrounding(pgf, offset)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"invalid position for package completion: %w\", err)\n\t}\n\n\tpackageSuggestions, err := packageSuggestions(ctx, snapshot, fh.URI(), \"\")\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar items []CompletionItem\n\tfor _, pkg := range packageSuggestions {\n\t\tinsertText := fmt.Sprintf(\"package %s\", pkg.name)\n\t\titems = append(items, CompletionItem{\n\t\t\tLabel:      insertText,\n\t\t\tKind:       protocol.ModuleCompletion,\n\t\t\tInsertText: insertText,\n\t\t\tScore:      pkg.score,\n\t\t})\n\t}\n\tsortItems(items)\n\treturn items, surrounding, nil\n}\n\n// packageCompletionSurrounding returns surrounding for package completion if a\n// package completions can be suggested at a given cursor offset. A valid location\n// for package completion is above any declarations or import statements.\nfunc packageCompletionSurrounding(pgf *parsego.File, offset int) (*Selection, error) {\n\tm := pgf.Mapper\n\t// If the file lacks a package declaration, the parser will return an empty\n\t// AST. As a work-around, try to parse an expression from the file contents.\n\tfset := token.NewFileSet()\n\texpr, _ := parser.ParseExprFrom(fset, m.URI.Path(), pgf.Src, parser.Mode(0))\n\tif expr == nil {\n\t\treturn nil, fmt.Errorf(\"unparsable file (%s)\", m.URI)\n\t}\n\ttok := fset.File(expr.Pos())\n\tcursor := tok.Pos(offset)\n\n\t// If we were able to parse out an identifier as the first expression from\n\t// the file, it may be the beginning of a package declaration (\"pack \").\n\t// We can offer package completions if the cursor is in the identifier.\n\tif name, ok := expr.(*ast.Ident); ok {\n\t\tif cursor >= name.Pos() && cursor <= name.End() {\n\t\t\tif !strings.HasPrefix(PACKAGE, name.Name) {\n\t\t\t\treturn nil, fmt.Errorf(\"cursor in non-matching ident\")\n\t\t\t}\n\t\t\tsel := &Selection{\n\t\t\t\tcontent: name.Name,\n\t\t\t\tcursor:  cursor,\n\t\t\t\ttokFile: tok,\n\t\t\t\tstart:   name.Pos(),\n\t\t\t\tend:     name.End(),\n\t\t\t\tmapper:  m,\n\t\t\t}\n\t\t\tsel.check()\n\t\t\treturn sel, nil\n\t\t}\n\t}\n\n\t// The file is invalid, but it contains an expression that we were able to\n\t// parse. We will use this expression to construct the cursor's\n\t// \"surrounding\".\n\n\t// First, consider the possibility that we have a valid \"package\" keyword\n\t// with an empty package name (\"package \"). \"package\" is parsed as an\n\t// *ast.BadDecl since it is a keyword.\n\tstart, err := safetoken.Offset(tok, expr.Pos())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif offset > start && string(bytes.TrimRight(pgf.Src[start:offset], \" \")) == PACKAGE {\n\t\tsel := &Selection{\n\t\t\tcontent: string(pgf.Src[start:offset]),\n\t\t\tcursor:  cursor,\n\t\t\ttokFile: tok,\n\t\t\tstart:   expr.Pos(),\n\t\t\tend:     cursor,\n\t\t\tmapper:  m,\n\t\t}\n\t\tsel.check()\n\t\treturn sel, nil\n\t}\n\n\t// If the cursor is after the start of the expression, no package\n\t// declaration will be valid.\n\tif cursor > expr.Pos() {\n\t\treturn nil, fmt.Errorf(\"cursor after expression\")\n\t}\n\n\t// If the cursor is in a comment, don't offer any completions.\n\tif cursorInComment(tok, cursor, m.Content) {\n\t\treturn nil, fmt.Errorf(\"cursor in comment\")\n\t}\n\n\t// The surrounding range in this case is the cursor.\n\tsel := &Selection{\n\t\tcontent: \"\",\n\t\ttokFile: tok,\n\t\tstart:   cursor,\n\t\tend:     cursor,\n\t\tcursor:  cursor,\n\t\tmapper:  m,\n\t}\n\tsel.check()\n\treturn sel, nil\n}\n\nfunc cursorInComment(file *token.File, cursor token.Pos, src []byte) bool {\n\tvar s scanner.Scanner\n\ts.Init(file, src, func(_ token.Position, _ string) {}, scanner.ScanComments)\n\tfor {\n\t\tpos, tok, lit := s.Scan()\n\t\tif pos <= cursor && cursor <= token.Pos(int(pos)+len(lit)) {\n\t\t\treturn tok == token.COMMENT\n\t\t}\n\t\tif tok == token.EOF {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn false\n}\n\n// packageNameCompletions returns name completions for a package clause using\n// the current name as prefix.\nfunc (c *completer) packageNameCompletions(ctx context.Context, fileURI protocol.DocumentURI, name *ast.Ident) error {\n\tcursor := int(c.pos - name.NamePos)\n\tif cursor < 0 || cursor > len(name.Name) {\n\t\treturn errors.New(\"cursor is not in package name identifier\")\n\t}\n\n\tc.completionContext.packageCompletion = true\n\n\tprefix := name.Name[:cursor]\n\tpackageSuggestions, err := packageSuggestions(ctx, c.snapshot, fileURI, prefix)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, pkg := range packageSuggestions {\n\t\tc.deepState.enqueue(pkg)\n\t}\n\treturn nil\n}\n\n// packageSuggestions returns a list of packages from workspace packages that\n// have the given prefix and are used in the same directory as the given\n// file. This also includes test packages for these packages (<pkg>_test) and\n// the directory name itself.\nfunc packageSuggestions(ctx context.Context, snapshot *cache.Snapshot, fileURI protocol.DocumentURI, prefix string) (packages []candidate, err error) {\n\tactive, err := snapshot.WorkspaceMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttoCandidate := func(name string, score float64) candidate {\n\t\tobj := types.NewPkgName(0, nil, name, types.NewPackage(\"\", name))\n\t\treturn candidate{obj: obj, name: name, detail: name, score: score}\n\t}\n\n\tvar currentPackageName string\n\t// TODO: consider propagating error.\n\tif md, err := snapshot.NarrowestMetadataForFile(ctx, fileURI); err == nil {\n\t\tcurrentPackageName = string(md.Name)\n\t}\n\n\tmatcher := fuzzy.NewMatcher(prefix)\n\n\t// Always try to suggest a main package\n\tdefer func() {\n\t\tmainScore := lowScore\n\t\tif currentPackageName == \"main\" {\n\t\t\tmainScore = highScore\n\t\t}\n\t\tif score := float64(matcher.Score(\"main\")); score > 0 {\n\t\t\tpackages = append(packages, toCandidate(\"main\", score*mainScore))\n\t\t}\n\t}()\n\n\tdirPath := fileURI.DirPath()\n\tdirName := filepath.Base(dirPath)\n\tif !isValidDirName(dirName) {\n\t\treturn packages, nil\n\t}\n\tpkgName := convertDirNameToPkgName(dirName)\n\n\tseenPkgs := make(map[golang.PackageName]struct{})\n\n\t// The `go` command by default only allows one package per directory but we\n\t// support multiple package suggestions since gopls is build system agnostic.\n\tfor _, mp := range active {\n\t\tif mp.Name == \"main\" || mp.Name == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif _, ok := seenPkgs[mp.Name]; ok {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Only add packages that are previously used in the current directory.\n\t\tvar relevantPkg bool\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\tif uri.DirPath() == dirPath {\n\t\t\t\trelevantPkg = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !relevantPkg {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Add a found package used in current directory as a high relevance\n\t\t// suggestion and the test package for it as a medium relevance\n\t\t// suggestion.\n\t\tif score := float64(matcher.Score(string(mp.Name))); score > 0 {\n\t\t\tpackages = append(packages, toCandidate(string(mp.Name), score*highScore))\n\t\t}\n\t\tseenPkgs[mp.Name] = struct{}{}\n\n\t\ttestPkgName := mp.Name + \"_test\"\n\t\tif _, ok := seenPkgs[testPkgName]; ok || strings.HasSuffix(string(mp.Name), \"_test\") {\n\t\t\tcontinue\n\t\t}\n\t\tif score := float64(matcher.Score(string(testPkgName))); score > 0 {\n\t\t\tpackages = append(packages, toCandidate(string(testPkgName), score*stdScore))\n\t\t}\n\t\tseenPkgs[testPkgName] = struct{}{}\n\t}\n\n\tif _, ok := seenPkgs[pkgName]; !ok {\n\t\t// Add current directory name as a low relevance suggestion.\n\t\tdirNameScore := lowScore\n\t\t// if current package name is empty, the dir name is the best choice.\n\t\tif currentPackageName == \"\" {\n\t\t\tdirNameScore = highScore\n\t\t}\n\t\tif score := float64(matcher.Score(string(pkgName))); score > 0 {\n\t\t\tpackages = append(packages, toCandidate(string(pkgName), score*dirNameScore))\n\t\t}\n\n\t\ttestPkgName := pkgName + \"_test\"\n\t\tif score := float64(matcher.Score(string(testPkgName))); score > 0 {\n\t\t\tpackages = append(packages, toCandidate(string(testPkgName), score*dirNameScore))\n\t\t}\n\t}\n\n\treturn packages, nil\n}\n\n// isValidDirName checks whether the passed directory name can be used in\n// a package path. Requirements for a package path can be found here:\n// https://golang.org/ref/mod#go-mod-file-ident.\nfunc isValidDirName(dirName string) bool {\n\tif dirName == \"\" {\n\t\treturn false\n\t}\n\n\tfor i, ch := range dirName {\n\t\tif isLetter(ch) || isDigit(ch) {\n\t\t\tcontinue\n\t\t}\n\t\tif i == 0 {\n\t\t\t// Directory name can start only with '_'. '.' is not allowed in module paths.\n\t\t\t// '-' and '~' are not allowed because elements of package paths must be\n\t\t\t// safe command-line arguments.\n\t\t\tif ch == '_' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// Modules path elements can't end with '.'\n\t\t\tif isAllowedPunctuation(ch) && (i != len(dirName)-1 || ch != '.') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}\n\treturn true\n}\n\n// convertDirNameToPkgName converts a valid directory name to a valid package name.\n// It leaves only letters and digits. All letters are mapped to lower case.\nfunc convertDirNameToPkgName(dirName string) golang.PackageName {\n\tvar buf bytes.Buffer\n\tfor _, ch := range dirName {\n\t\tswitch {\n\t\tcase isLetter(ch):\n\t\t\tbuf.WriteRune(unicode.ToLower(ch))\n\n\t\tcase buf.Len() != 0 && isDigit(ch):\n\t\t\tbuf.WriteRune(ch)\n\t\t}\n\t}\n\treturn golang.PackageName(buf.String())\n}\n\n// isLetter and isDigit allow only ASCII characters because\n// \"Each path element is a non-empty string made of up ASCII letters,\n// ASCII digits, and limited ASCII punctuation\"\n// (see https://golang.org/ref/mod#go-mod-file-ident).\n\nfunc isLetter(ch rune) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z'\n}\n\nfunc isDigit(ch rune) bool {\n\treturn '0' <= ch && ch <= '9'\n}\n\nfunc isAllowedPunctuation(ch rune) bool {\n\treturn ch == '_' || ch == '-' || ch == '~' || ch == '.'\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/package_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/golang\"\n)\n\nfunc TestIsValidDirName(t *testing.T) {\n\ttests := []struct {\n\t\tdirName string\n\t\tvalid   bool\n\t}{\n\t\t{dirName: \"\", valid: false},\n\t\t//\n\t\t{dirName: \"a\", valid: true},\n\t\t{dirName: \"abcdef\", valid: true},\n\t\t{dirName: \"AbCdEf\", valid: true},\n\t\t//\n\t\t{dirName: \"1a35\", valid: true},\n\t\t{dirName: \"a16\", valid: true},\n\t\t//\n\t\t{dirName: \"_a\", valid: true},\n\t\t{dirName: \"a_\", valid: true},\n\t\t//\n\t\t{dirName: \"~a\", valid: false},\n\t\t{dirName: \"a~\", valid: true},\n\t\t//\n\t\t{dirName: \"-a\", valid: false},\n\t\t{dirName: \"a-\", valid: true},\n\t\t//\n\t\t{dirName: \".a\", valid: false},\n\t\t{dirName: \"a.\", valid: false},\n\t\t//\n\t\t{dirName: \"a~_b--c.-e\", valid: true},\n\t\t{dirName: \"~a~_b--c.-e\", valid: false},\n\t\t{dirName: \"a~_b--c.-e--~\", valid: true},\n\t\t{dirName: \"a~_b--2134dc42.-e6--~\", valid: true},\n\t\t{dirName: \"abc`def\", valid: false},\n\t\t{dirName: \"тест\", valid: false},\n\t\t{dirName: \"你好\", valid: false},\n\t}\n\tfor _, tt := range tests {\n\t\tvalid := isValidDirName(tt.dirName)\n\t\tif tt.valid != valid {\n\t\t\tt.Errorf(\"%s: expected %v, got %v\", tt.dirName, tt.valid, valid)\n\t\t}\n\t}\n}\n\nfunc TestConvertDirNameToPkgName(t *testing.T) {\n\ttests := []struct {\n\t\tdirName string\n\t\tpkgName golang.PackageName\n\t}{\n\t\t{dirName: \"a\", pkgName: \"a\"},\n\t\t{dirName: \"abcdef\", pkgName: \"abcdef\"},\n\t\t{dirName: \"AbCdEf\", pkgName: \"abcdef\"},\n\t\t{dirName: \"1a35\", pkgName: \"a35\"},\n\t\t{dirName: \"14a35\", pkgName: \"a35\"},\n\t\t{dirName: \"a16\", pkgName: \"a16\"},\n\t\t{dirName: \"_a\", pkgName: \"a\"},\n\t\t{dirName: \"a_\", pkgName: \"a\"},\n\t\t{dirName: \"a~\", pkgName: \"a\"},\n\t\t{dirName: \"a-\", pkgName: \"a\"},\n\t\t{dirName: \"a~_b--c.-e\", pkgName: \"abce\"},\n\t\t{dirName: \"a~_b--c.-e--~\", pkgName: \"abce\"},\n\t\t{dirName: \"a~_b--2134dc42.-e6--~\", pkgName: \"ab2134dc42e6\"},\n\t}\n\tfor _, tt := range tests {\n\t\tpkgName := convertDirNameToPkgName(tt.dirName)\n\t\tif tt.pkgName != pkgName {\n\t\t\tt.Errorf(\"%s: expected %v, got %v\", tt.dirName, tt.pkgName, pkgName)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/postfix_snippets.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\t\"text/template\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// Postfix snippets are artificial methods that allow the user to\n// compose common operations in an \"argument oriented\" fashion. For\n// example, instead of \"sort.Slice(someSlice, ...)\" a user can expand\n// \"someSlice.sort!\".\n\n// postfixTmpl represents a postfix snippet completion candidate.\ntype postfixTmpl struct {\n\t// label is the completion candidate's label presented to the user.\n\tlabel string\n\n\t// details is passed along to the client as the candidate's details.\n\tdetails string\n\n\t// body is the template text. See postfixTmplArgs for details on the\n\t// facilities available to the template.\n\tbody string\n\n\ttmpl *template.Template\n}\n\n// postfixTmplArgs are the template execution arguments available to\n// the postfix snippet templates.\ntype postfixTmplArgs struct {\n\t// StmtOK is true if it is valid to replace the selector with a\n\t// statement. For example:\n\t//\n\t//    func foo() {\n\t//      bar.sort! // statement okay\n\t//\n\t//      someMethod(bar.sort!) // statement not okay\n\t//    }\n\tStmtOK bool\n\n\t// X is the textual SelectorExpr.X. For example, when completing\n\t// \"foo.bar.print!\", \"X\" is \"foo.bar\".\n\tX string\n\n\t// Obj is the types.Object of SelectorExpr.X, if any.\n\tObj types.Object\n\n\t// Type is the type of \"foo.bar\" in \"foo.bar.print!\".\n\tType types.Type\n\n\t// FuncResults are results of the enclosed function\n\tFuncResults []*types.Var\n\n\tsel            *ast.SelectorExpr\n\tscope          *types.Scope\n\tsnip           snippet.Builder\n\timportIfNeeded func(pkgPath string, scope *types.Scope) (name string, edits []protocol.TextEdit, err error)\n\tedits          []protocol.TextEdit\n\tqual           types.Qualifier\n\tvarNames       map[string]bool\n\tplaceholders   bool\n\tcurrentTabStop int\n}\n\nvar postfixTmpls = []postfixTmpl{{\n\tlabel:   \"sort\",\n\tdetails: \"sort.Slice()\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK -}}\n{{.Import \"sort\"}}.Slice({{.X}}, func({{.VarName nil \"i\"}}, {{.VarName nil \"j\"}} int) bool {\n\t{{.Cursor}}\n})\n{{- end}}`,\n}, {\n\tlabel:   \"last\",\n\tdetails: \"s[len(s)-1]\",\n\tbody: `{{if and (eq .Kind \"slice\") .Obj -}}\n{{.X}}[len({{.X}})-1]\n{{- end}}`,\n}, {\n\tlabel:   \"reverse\",\n\tdetails: \"reverse slice\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK -}}\n{{.Import \"slices\"}}.Reverse({{.X}})\n{{- end}}`,\n}, {\n\tlabel:   \"range\",\n\tdetails: \"range over slice\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK -}}\nfor {{.VarName nil \"i\" | .Placeholder }}, {{.VarName .ElemType \"v\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"for\",\n\tdetails: \"range over slice by index\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK -}}\nfor {{ .VarName nil \"i\" | .Placeholder }} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"forr\",\n\tdetails: \"range over slice by index and value\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK -}}\nfor {{.VarName nil \"i\" | .Placeholder }}, {{.VarName .ElemType \"v\" | .Placeholder }} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"append\",\n\tdetails: \"append and re-assign slice\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK .Obj -}}\n{{.X}} = append({{.X}}, {{.Cursor}})\n{{- end}}`,\n}, {\n\tlabel:   \"append\",\n\tdetails: \"append to slice\",\n\tbody: `{{if and (eq .Kind \"slice\") (not .StmtOK) -}}\nappend({{.X}}, {{.Cursor}})\n{{- end}}`,\n}, {\n\tlabel:   \"copy\",\n\tdetails: \"duplicate slice\",\n\tbody: `{{if and (eq .Kind \"slice\") .StmtOK .Obj -}}\n{{$v := (.VarName nil (printf \"%sCopy\" .X))}}{{$v}} := make([]{{.TypeName .ElemType}}, len({{.X}}))\ncopy({{$v}}, {{.X}})\n{{end}}`,\n}, {\n\tlabel:   \"range\",\n\tdetails: \"range over map\",\n\tbody: `{{if and (eq .Kind \"map\") .StmtOK -}}\nfor {{.VarName .KeyType \"k\" | .Placeholder}}, {{.VarName .ElemType \"v\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"for\",\n\tdetails: \"range over map by key\",\n\tbody: `{{if and (eq .Kind \"map\") .StmtOK -}}\nfor {{.VarName .KeyType \"k\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"forr\",\n\tdetails: \"range over map by key and value\",\n\tbody: `{{if and (eq .Kind \"map\") .StmtOK -}}\nfor {{.VarName .KeyType \"k\" | .Placeholder}}, {{.VarName .ElemType \"v\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"clear\",\n\tdetails: \"clear map contents\",\n\tbody: `{{if and (eq .Kind \"map\") .StmtOK -}}\n{{$k := (.VarName .KeyType \"k\")}}for {{$k}} := range {{.X}} {\n\tdelete({{.X}}, {{$k}})\n}\n{{end}}`,\n}, {\n\tlabel:   \"keys\",\n\tdetails: \"create slice of keys\",\n\tbody: `{{if and (eq .Kind \"map\") .StmtOK -}}\n{{$keysVar := (.VarName nil \"keys\")}}{{$keysVar}} := make([]{{.TypeName .KeyType}}, 0, len({{.X}}))\n{{$k := (.VarName .KeyType \"k\")}}for {{$k}} := range {{.X}} {\n\t{{$keysVar}} = append({{$keysVar}}, {{$k}})\n}\n{{end}}`,\n}, {\n\tlabel:   \"range\",\n\tdetails: \"range over channel\",\n\tbody: `{{if and (eq .Kind \"chan\") .StmtOK -}}\nfor {{.VarName .ElemType \"e\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"for\",\n\tdetails: \"range over channel\",\n\tbody: `{{if and (eq .Kind \"chan\") .StmtOK -}}\nfor {{.VarName .ElemType \"e\" | .Placeholder}} := range {{.X}} {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"var\",\n\tdetails: \"assign to variables\",\n\tbody: `{{if and (eq .Kind \"tuple\") .StmtOK -}}\n{{$a := .}}{{range $i, $v := .Tuple}}{{if $i}}, {{end}}{{$a.VarName $v.Type $v.Name | $a.Placeholder }}{{end}} := {{.X}}\n{{- end}}`,\n}, {\n\tlabel:   \"var\",\n\tdetails: \"assign to variable\",\n\tbody: `{{if and (ne .Kind \"tuple\") .StmtOK -}}\n{{.VarName .Type \"\" | .Placeholder }} := {{.X}}\n{{- end}}`,\n}, {\n\tlabel:   \"print\",\n\tdetails: \"print to stdout\",\n\tbody: `{{if and (ne .Kind \"tuple\") .StmtOK -}}\n{{.Import \"fmt\"}}.Printf(\"{{.EscapeQuotes .X}}: %v\\n\", {{.X}})\n{{- end}}`,\n}, {\n\tlabel:   \"print\",\n\tdetails: \"print to stdout\",\n\tbody: `{{if and (eq .Kind \"tuple\") .StmtOK -}}\n{{.Import \"fmt\"}}.Println({{.X}})\n{{- end}}`,\n}, {\n\tlabel:   \"split\",\n\tdetails: \"split string\",\n\tbody: `{{if (eq (.TypeName .Type) \"string\") -}}\n{{.Import \"strings\"}}.Split({{.X}}, \"{{.Cursor}}\")\n{{- end}}`,\n}, {\n\tlabel:   \"join\",\n\tdetails: \"join string slice\",\n\tbody: `{{if and (eq .Kind \"slice\") (eq (.TypeName .ElemType) \"string\") -}}\n{{.Import \"strings\"}}.Join({{.X}}, \"{{.Cursor}}\")\n{{- end}}`,\n}, {\n\tlabel:   \"ifnotnil\",\n\tdetails: \"if expr != nil\",\n\tbody: `{{if and (or (eq .Kind \"pointer\") (eq .Kind \"chan\") (eq .Kind \"signature\") (eq .Kind \"interface\") (eq .Kind \"map\") (eq .Kind \"slice\")) .StmtOK -}}\nif {{.X}} != nil {\n\t{{.Cursor}}\n}\n{{- end}}`,\n}, {\n\tlabel:   \"len\",\n\tdetails: \"len(s)\",\n\tbody: `{{if (eq .Kind \"slice\" \"map\" \"array\" \"chan\") -}}\nlen({{.X}})\n{{- end}}`,\n}, {\n\tlabel:   \"iferr\",\n\tdetails: \"check error and return\",\n\tbody: `{{if and .StmtOK (eq (.TypeName .Type) \"error\") -}}\n{{- $errName := (or (and .IsIdent .X) \"err\") -}}\nif {{if not .IsIdent}}err := {{.X}}; {{end}}{{$errName}} != nil {\n\treturn {{$a := .}}{{range $i, $v := .FuncResults}}\n\t\t{{- if $i}}, {{end -}}\n\t\t{{- if eq ($a.TypeName $v.Type) \"error\" -}}\n\t\t\t{{$a.Placeholder $errName}}\n\t\t{{- else -}}\n\t\t\t{{$a.Zero $v.Type}}\n\t\t{{- end -}}\n\t{{end}}\n}\n{{end}}`,\n}, {\n\tlabel:   \"iferr\",\n\tdetails: \"check error and return\",\n\tbody: `{{if and .StmtOK (eq .Kind \"tuple\") (len .Tuple) (eq (.TypeName .TupleLast.Type) \"error\") -}}\n{{- $a := . -}}\nif {{range $i, $v := .Tuple}}{{if $i}}, {{end}}{{if and (eq ($a.TypeName $v.Type) \"error\") (eq (inc $i) (len $a.Tuple))}}err{{else}}_{{end}}{{end}} := {{.X -}}\n; err != nil {\n\treturn {{range $i, $v := .FuncResults}}\n\t\t{{- if $i}}, {{end -}}\n\t\t{{- if eq ($a.TypeName $v.Type) \"error\" -}}\n\t\t\t{{$a.Placeholder \"err\"}}\n\t\t{{- else -}}\n\t\t\t{{$a.Zero $v.Type}}\n\t\t{{- end -}}\n\t{{end}}\n}\n{{end}}`,\n}, {\n\t// variferr snippets use nested placeholders, as described in\n\t// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#snippet_syntax,\n\t// so that users can wrap the returned error without modifying the error\n\t// variable name.\n\tlabel:   \"variferr\",\n\tdetails: \"assign variables and check error\",\n\tbody: `{{if and .StmtOK (eq .Kind \"tuple\") (len .Tuple) (eq (.TypeName .TupleLast.Type) \"error\") -}}\n{{- $a := . -}}\n{{- $errName := \"err\" -}}\n{{- range $i, $v := .Tuple -}}\n\t{{- if $i}}, {{end -}}\n\t{{- if and (eq ($a.TypeName $v.Type) \"error\") (eq (inc $i) (len $a.Tuple)) -}}\n\t\t{{$errName | $a.SpecifiedPlaceholder (len $a.Tuple)}}\n\t{{- else -}}\n\t\t{{$a.VarName $v.Type $v.Name | $a.Placeholder}}\n\t{{- end -}}\n{{- end}} := {{.X}}\nif {{$errName | $a.SpecifiedPlaceholder (len $a.Tuple)}} != nil {\n\treturn {{range $i, $v := .FuncResults}}\n\t\t{{- if $i}}, {{end -}}\n\t\t{{- if eq ($a.TypeName $v.Type) \"error\" -}}\n\t\t\t{{$errName | $a.SpecifiedPlaceholder (len $a.Tuple) |\n\t\t\t\t$a.SpecifiedPlaceholder (inc (len $a.Tuple))}}\n\t\t{{- else -}}\n\t\t\t{{$a.Zero $v.Type}}\n\t\t{{- end -}}\n\t{{end}}\n}\n{{end}}`,\n}, {\n\tlabel:   \"variferr\",\n\tdetails: \"assign variables and check error\",\n\tbody: `{{if and .StmtOK (eq (.TypeName .Type) \"error\") -}}\n{{- $a := . -}}\n{{- $errName := .VarName nil \"err\" -}}\n{{$errName | $a.SpecifiedPlaceholder 1}} := {{.X}}\nif {{$errName | $a.SpecifiedPlaceholder 1}} != nil {\n\treturn {{range $i, $v := .FuncResults}}\n\t\t{{- if $i}}, {{end -}}\n\t\t{{- if eq ($a.TypeName $v.Type) \"error\" -}}\n\t\t\t{{$errName | $a.SpecifiedPlaceholder 1 | $a.SpecifiedPlaceholder 2}}\n\t\t{{- else -}}\n\t\t\t{{$a.Zero $v.Type}}\n\t\t{{- end -}}\n\t{{end}}\n}\n{{end}}`,\n},\n\t{\n\t\tlabel:   \"tostring\",\n\t\tdetails: \"[]byte to string\",\n\t\tbody: `{{if (eq (.TypeName .Type) \"[]byte\") -}}\n\tstring({{.X}})\n\t{{- end}}`,\n\t},\n\t{\n\t\tlabel:   \"tostring\",\n\t\tdetails: \"int to string\",\n\t\tbody: `{{if (eq (.TypeName .Type) \"int\") -}}\n\t\t{{.Import \"strconv\"}}.Itoa({{.X}})\n\t\t{{- end}}`,\n\t},\n\t{\n\t\tlabel:   \"tobytes\",\n\t\tdetails: \"string to []byte\",\n\t\tbody: `{{if (eq (.TypeName .Type) \"string\") -}}\n\t[]byte({{.X}})\n\t{{- end}}`,\n\t},\n}\n\n// Cursor indicates where the client's cursor should end up after the\n// snippet is done.\nfunc (a *postfixTmplArgs) Cursor() string {\n\treturn \"$0\"\n}\n\n// Placeholder indicate a tab stop with the placeholder string, the order\n// of tab stops is the same as the order of invocation\nfunc (a *postfixTmplArgs) Placeholder(placeholder string) string {\n\tif !a.placeholders {\n\t\tplaceholder = \"\"\n\t}\n\treturn fmt.Sprintf(\"${%d:%s}\", a.nextTabStop(), placeholder)\n}\n\n// nextTabStop returns the next tab stop index for a new placeholder.\nfunc (a *postfixTmplArgs) nextTabStop() int {\n\t// Tab stops start from 1, so increment before returning.\n\ta.currentTabStop++\n\treturn a.currentTabStop\n}\n\n// SpecifiedPlaceholder indicate a specified tab stop with the placeholder string.\n// Sometimes the same tab stop appears in multiple places and their numbers\n// need to be specified. e.g. variferr\nfunc (a *postfixTmplArgs) SpecifiedPlaceholder(tabStop int, placeholder string) string {\n\tif !a.placeholders {\n\t\tplaceholder = \"\"\n\t}\n\treturn fmt.Sprintf(\"${%d:%s}\", tabStop, placeholder)\n}\n\n// Import makes sure the package corresponding to path is imported,\n// returning the identifier to use to refer to the package.\nfunc (a *postfixTmplArgs) Import(path string) (string, error) {\n\tname, edits, err := a.importIfNeeded(path, a.scope)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"couldn't import %q: %w\", path, err)\n\t}\n\ta.edits = append(a.edits, edits...)\n\n\treturn name, nil\n}\n\nfunc (a *postfixTmplArgs) EscapeQuotes(v string) string {\n\treturn strings.ReplaceAll(v, `\"`, `\\\\\"`)\n}\n\n// ElemType returns the Elem() type of xType, if applicable.\nfunc (a *postfixTmplArgs) ElemType() types.Type {\n\ttype hasElem interface{ Elem() types.Type } // Array, Chan, Map, Pointer, Slice\n\tif e, ok := a.Type.Underlying().(hasElem); ok {\n\t\treturn e.Elem()\n\t}\n\treturn nil\n}\n\n// Kind returns the underlying kind of type, e.g. \"slice\", \"struct\",\n// etc.\nfunc (a *postfixTmplArgs) Kind() string {\n\tt := reflect.TypeOf(a.Type.Underlying())\n\treturn strings.ToLower(strings.TrimPrefix(t.String(), \"*types.\"))\n}\n\n// KeyType returns the type of X's key. KeyType panics if X is not a\n// map.\nfunc (a *postfixTmplArgs) KeyType() types.Type {\n\treturn a.Type.Underlying().(*types.Map).Key()\n}\n\n// Tuple returns the tuple result vars if the type of X is tuple.\nfunc (a *postfixTmplArgs) Tuple() []*types.Var {\n\ttuple, _ := a.Type.(*types.Tuple)\n\ttyps := make([]*types.Var, tuple.Len())\n\tfor i := range typs {\n\t\ttyps[i] = tuple.At(i)\n\t}\n\treturn typs\n}\n\n// TupleLast returns the last tuple result vars if the type of X is tuple.\nfunc (a *postfixTmplArgs) TupleLast() *types.Var {\n\ttuple, _ := a.Type.(*types.Tuple)\n\tif tuple.Len() == 0 {\n\t\treturn nil\n\t}\n\treturn tuple.At(tuple.Len() - 1)\n}\n\n// TypeName returns the textual representation of type t.\nfunc (a *postfixTmplArgs) TypeName(t types.Type) (string, error) {\n\tif t == nil || t == types.Typ[types.Invalid] {\n\t\treturn \"\", fmt.Errorf(\"invalid type: %v\", t)\n\t}\n\treturn types.TypeString(t, a.qual), nil\n}\n\n// Zero return the zero value representation of type t\nfunc (a *postfixTmplArgs) Zero(t types.Type) string {\n\tzero, _ := typesinternal.ZeroString(t, a.qual)\n\treturn zero\n}\n\nfunc (a *postfixTmplArgs) IsIdent() bool {\n\t_, ok := a.sel.X.(*ast.Ident)\n\treturn ok\n}\n\n// VarName returns a suitable variable name for the type t. If t\n// implements the error interface, \"err\" is used. If t is not a named\n// type then nonNamedDefault is used. Otherwise a name is made by\n// abbreviating the type name. If the resultant name is already in\n// scope, an integer is appended to make a unique name.\nfunc (a *postfixTmplArgs) VarName(t types.Type, nonNamedDefault string) string {\n\tif t == nil {\n\t\tt = types.Typ[types.Invalid]\n\t}\n\n\tvar name string\n\t// go/types predicates are undefined on types.Typ[types.Invalid].\n\tif !types.Identical(t, types.Typ[types.Invalid]) && types.Implements(t, errorIntf) {\n\t\tname = \"err\"\n\t} else if !is[*types.Named](types.Unalias(typesinternal.Unpointer(t))) {\n\t\tname = nonNamedDefault\n\t}\n\n\tif name == \"\" {\n\t\tname = types.TypeString(t, func(p *types.Package) string {\n\t\t\treturn \"\"\n\t\t})\n\t\tname = abbreviateTypeName(name)\n\t}\n\n\tif dot := strings.LastIndex(name, \".\"); dot > -1 {\n\t\tname = name[dot+1:]\n\t}\n\n\tuniqueName := name\n\tfor i := 2; ; i++ {\n\t\tif s, _ := a.scope.LookupParent(uniqueName, token.NoPos); s == nil && !a.varNames[uniqueName] {\n\t\t\tbreak\n\t\t}\n\t\tuniqueName = fmt.Sprintf(\"%s%d\", name, i)\n\t}\n\n\ta.varNames[uniqueName] = true\n\n\treturn uniqueName\n}\n\nfunc (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.SelectorExpr) {\n\tif !c.opts.postfix {\n\t\treturn\n\t}\n\n\tinitPostfixRules()\n\n\tif sel == nil || sel.Sel == nil {\n\t\treturn\n\t}\n\n\tselType := c.pkg.TypesInfo().TypeOf(sel.X)\n\tif selType == nil {\n\t\treturn\n\t}\n\n\t// Skip empty tuples since there is no value to operate on.\n\tif tuple, ok := selType.(*types.Tuple); ok && tuple == nil {\n\t\treturn\n\t}\n\n\ttokFile := c.pkg.FileSet().File(c.pos)\n\n\t// Only replace sel with a statement if sel is already a statement.\n\tvar stmtOK bool\n\tfor i, n := range c.path {\n\t\tif n == sel && i < len(c.path)-1 {\n\t\t\tswitch p := c.path[i+1].(type) {\n\t\t\tcase *ast.ExprStmt:\n\t\t\t\tstmtOK = true\n\t\t\tcase *ast.AssignStmt:\n\t\t\t\t// In cases like:\n\t\t\t\t//\n\t\t\t\t//   foo.<>\n\t\t\t\t//   bar = 123\n\t\t\t\t//\n\t\t\t\t// detect that \"foo.\" makes up the entire statement since the\n\t\t\t\t// apparent selector spans lines.\n\t\t\t\tstmtOK = safetoken.Line(tokFile, c.pos) < safetoken.Line(tokFile, p.TokPos)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\tvar funcResults []*types.Var\n\tif c.enclosingFunc != nil {\n\t\tresults := c.enclosingFunc.sig.Results()\n\t\tif results != nil {\n\t\t\tfuncResults = make([]*types.Var, results.Len())\n\t\t\tfor i := range results.Len() {\n\t\t\t\tfuncResults[i] = results.At(i)\n\t\t\t}\n\t\t}\n\t}\n\n\tscope := c.pkg.Types().Scope().Innermost(c.pos)\n\tif scope == nil {\n\t\treturn\n\t}\n\n\t// afterDot is the position after selector dot, e.g. \"|\" in\n\t// \"foo.|print\".\n\tafterDot := sel.Sel.Pos()\n\n\t// We must detect dangling selectors such as:\n\t//\n\t//    foo.<>\n\t//    bar\n\t//\n\t// and adjust afterDot so that we don't mistakenly delete the\n\t// newline thinking \"bar\" is part of our selector.\n\tif startLine := safetoken.Line(tokFile, sel.Pos()); startLine != safetoken.Line(tokFile, afterDot) {\n\t\tif safetoken.Line(tokFile, c.pos) != startLine {\n\t\t\treturn\n\t\t}\n\t\tafterDot = c.pos\n\t}\n\n\tfor _, rule := range postfixTmpls {\n\t\t// When completing foo.print<>, \"print\" is naturally overwritten,\n\t\t// but we need to also remove \"foo.\" so the snippet has a clean\n\t\t// slate.\n\t\tedits, err := c.editText(sel.Pos(), afterDot, \"\")\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"error calculating postfix edits\", err)\n\t\t\treturn\n\t\t}\n\n\t\ttmplArgs := postfixTmplArgs{\n\t\t\tX:              golang.FormatNode(c.pkg.FileSet(), sel.X),\n\t\t\tStmtOK:         stmtOK,\n\t\t\tObj:            exprObj(c.pkg.TypesInfo(), sel.X),\n\t\t\tType:           selType,\n\t\t\tFuncResults:    funcResults,\n\t\t\tsel:            sel,\n\t\t\tqual:           c.qual,\n\t\t\timportIfNeeded: c.importIfNeeded,\n\t\t\tscope:          scope,\n\t\t\tvarNames:       make(map[string]bool),\n\t\t\tplaceholders:   c.opts.placeholders,\n\t\t}\n\n\t\t// Feed the template straight into the snippet builder. This\n\t\t// allows templates to build snippets as they are executed.\n\t\terr = rule.tmpl.Execute(&tmplArgs.snip, &tmplArgs)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"error executing postfix template\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif strings.TrimSpace(tmplArgs.snip.String()) == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tscore := c.matcher.Score(rule.label)\n\t\tif score <= 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tc.items = append(c.items, CompletionItem{\n\t\t\tLabel:               rule.label + \"!\",\n\t\t\tDetail:              rule.details,\n\t\t\tScore:               float64(score) * 0.01,\n\t\t\tKind:                protocol.SnippetCompletion,\n\t\t\tsnippet:             &tmplArgs.snip,\n\t\t\tAdditionalTextEdits: append(edits, tmplArgs.edits...),\n\t\t})\n\t}\n}\n\nvar postfixRulesOnce sync.Once\n\nfunc initPostfixRules() {\n\tpostfixRulesOnce.Do(func() {\n\t\tvar idx int\n\t\tfor _, rule := range postfixTmpls {\n\t\t\tvar err error\n\t\t\trule.tmpl, err = template.New(\"postfix_snippet\").Funcs(template.FuncMap{\n\t\t\t\t\"inc\": inc,\n\t\t\t}).Parse(rule.body)\n\t\t\tif err != nil {\n\t\t\t\tlog.Panicf(\"error parsing postfix snippet template: %v\", err)\n\t\t\t}\n\t\t\tpostfixTmpls[idx] = rule\n\t\t\tidx++\n\t\t}\n\t\tpostfixTmpls = postfixTmpls[:idx]\n\t})\n}\n\nfunc inc(i int) int {\n\treturn i + 1\n}\n\n// importIfNeeded returns the package identifier and any necessary\n// edits to import package pkgPath.\nfunc (c *completer) importIfNeeded(pkgPath string, scope *types.Scope) (string, []protocol.TextEdit, error) {\n\tdefaultName := imports.ImportPathToAssumedName(pkgPath)\n\n\t// Check if file already imports pkgPath.\n\tfor _, s := range c.pgf.File.Imports {\n\t\t// TODO(adonovan): what if pkgPath has a vendor/ suffix?\n\t\t// This may be the cause of go.dev/issue/56291.\n\t\tif string(metadata.UnquoteImportPath(s)) == pkgPath {\n\t\t\tif s.Name == nil {\n\t\t\t\treturn defaultName, nil, nil\n\t\t\t}\n\t\t\tif s.Name.Name != \"_\" {\n\t\t\t\treturn s.Name.Name, nil, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Give up if the package's name is already in use by another object.\n\tif _, obj := scope.LookupParent(defaultName, token.NoPos); obj != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"import name %q of %q already in use\", defaultName, pkgPath)\n\t}\n\n\tedits, err := c.importEdits(&importInfo{\n\t\timportPath: pkgPath,\n\t})\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\n\treturn defaultName, edits, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/printf.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// printfArgKind returns the expected objKind when completing a\n// printf-like operand. call is the printf-like function call, and\n// argIdx is the index of call.Args being completed.\nfunc printfArgKind(info *types.Info, call *ast.CallExpr, argIdx int) objKind {\n\t// Printf-like function name must end in \"f\".\n\tfn := exprObj(info, call.Fun)\n\tif fn == nil || !strings.HasSuffix(fn.Name(), \"f\") {\n\t\treturn kindAny\n\t}\n\n\tsig, _ := fn.Type().Underlying().(*types.Signature)\n\tif sig == nil {\n\t\treturn kindAny\n\t}\n\n\t// Must be variadic and take at least two params.\n\tnumParams := sig.Params().Len()\n\tif !sig.Variadic() || numParams < 2 || argIdx < numParams-1 {\n\t\treturn kindAny\n\t}\n\n\t// Param preceding variadic args must be a (format) string.\n\tif !types.Identical(sig.Params().At(numParams-2).Type(), types.Typ[types.String]) {\n\t\treturn kindAny\n\t}\n\n\t// Format string must be a constant.\n\tstrArg := info.Types[call.Args[numParams-2]].Value // may be zero\n\tif strArg == nil || strArg.Kind() != constant.String {\n\t\treturn kindAny\n\t}\n\n\treturn formatOperandKind(constant.StringVal(strArg), argIdx-(numParams-1)+1)\n}\n\n// formatOperandKind returns the objKind corresponding to format's\n// operandIdx'th operand.\nfunc formatOperandKind(format string, operandIdx int) objKind {\n\tvar (\n\t\tprevOperandIdx int\n\t\tkind           = kindAny\n\t)\n\tfor {\n\t\ti := strings.Index(format, \"%\")\n\t\tif i == -1 {\n\t\t\tbreak\n\t\t}\n\n\t\tvar operands []formatOperand\n\t\tformat, operands = parsePrintfVerb(format[i+1:], prevOperandIdx)\n\n\t\t// Check if any this verb's operands correspond to our target\n\t\t// operandIdx.\n\t\tfor _, v := range operands {\n\t\t\tif v.idx == operandIdx {\n\t\t\t\tif kind == kindAny {\n\t\t\t\t\tkind = v.kind\n\t\t\t\t} else if v.kind != kindAny {\n\t\t\t\t\t// If multiple verbs refer to the same operand, take the\n\t\t\t\t\t// intersection of their kinds.\n\t\t\t\t\tkind &= v.kind\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprevOperandIdx = v.idx\n\t\t}\n\t}\n\treturn kind\n}\n\ntype formatOperand struct {\n\t// idx is the one-based printf operand index.\n\tidx int\n\t// kind is a mask of expected kinds of objects for this operand.\n\tkind objKind\n}\n\n// parsePrintfVerb parses the leading printf verb in f. The opening\n// \"%\" must already be trimmed from f. prevIdx is the previous\n// operand's index, or zero if this is the first verb. The format\n// string is returned with the leading verb removed. Multiple operands\n// can be returned in the case of dynamic widths such as \"%*.*f\".\nfunc parsePrintfVerb(f string, prevIdx int) (string, []formatOperand) {\n\tvar verbs []formatOperand\n\n\taddVerb := func(k objKind) {\n\t\tverbs = append(verbs, formatOperand{\n\t\t\tidx:  prevIdx + 1,\n\t\t\tkind: k,\n\t\t})\n\t\tprevIdx++\n\t}\n\n\tfor len(f) > 0 {\n\t\t// Trim first rune off of f so we are guaranteed to make progress.\n\t\tr, l := utf8.DecodeRuneInString(f)\n\t\tf = f[l:]\n\n\t\t// We care about three things:\n\t\t// 1. The verb, which maps directly to object kind.\n\t\t// 2. Explicit operand indices like \"%[2]s\".\n\t\t// 3. Dynamic widths using \"*\".\n\t\tswitch r {\n\t\tcase '%':\n\t\t\treturn f, nil\n\t\tcase '*':\n\t\t\taddVerb(kindInt)\n\t\t\tcontinue\n\t\tcase '[':\n\t\t\t// Parse operand index as in \"%[2]s\".\n\t\t\ti := strings.Index(f, \"]\")\n\t\t\tif i == -1 {\n\t\t\t\treturn f, nil\n\t\t\t}\n\n\t\t\tidx, err := strconv.Atoi(f[:i])\n\t\t\tf = f[i+1:]\n\t\t\tif err != nil {\n\t\t\t\treturn f, nil\n\t\t\t}\n\n\t\t\tprevIdx = idx - 1\n\t\t\tcontinue\n\t\tcase 'v', 'T':\n\t\t\taddVerb(kindAny)\n\t\tcase 't':\n\t\t\taddVerb(kindBool)\n\t\tcase 'c', 'd', 'o', 'O', 'U':\n\t\t\taddVerb(kindInt)\n\t\tcase 'e', 'E', 'f', 'F', 'g', 'G':\n\t\t\taddVerb(kindFloat | kindComplex)\n\t\tcase 'b':\n\t\t\taddVerb(kindInt | kindFloat | kindComplex | kindBytes)\n\t\tcase 'q', 's':\n\t\t\taddVerb(kindString | kindBytes | kindStringer | kindError)\n\t\tcase 'x', 'X':\n\t\t\t// Omit kindStringer and kindError though technically allowed.\n\t\t\taddVerb(kindString | kindBytes | kindInt | kindFloat | kindComplex)\n\t\tcase 'p':\n\t\t\t// Accept kindInterface even though it doesn't necessarily contain a pointer.\n\t\t\t// This avoids us offering \"&foo\" when \"foo\" is an interface type.\n\t\t\taddVerb(kindPtr | kindSlice | kindMap | kindFunc | kindInterface)\n\t\tcase 'w':\n\t\t\taddVerb(kindError)\n\t\tcase '+', '-', '#', ' ', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\t\t// Flag or numeric width/precision value.\n\t\t\tcontinue\n\t\tdefault:\n\t\t\t// Assume unrecognized rune is a custom fmt.Formatter verb.\n\t\t\taddVerb(kindAny)\n\t\t}\n\n\t\tif len(verbs) > 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn f, verbs\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/printf_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestFormatOperandKind(t *testing.T) {\n\tcases := []struct {\n\t\tf    string\n\t\tidx  int\n\t\tkind objKind\n\t}{\n\t\t{\"\", 1, kindAny},\n\t\t{\"%\", 1, kindAny},\n\t\t{\"%%%\", 1, kindAny},\n\t\t{\"%[1\", 1, kindAny},\n\t\t{\"%[?%s\", 2, kindAny},\n\t\t{\"%[abc]v\", 1, kindAny},\n\n\t\t{\"%v\", 1, kindAny},\n\t\t{\"%T\", 1, kindAny},\n\t\t{\"%t\", 1, kindBool},\n\t\t{\"%d\", 1, kindInt},\n\t\t{\"%c\", 1, kindInt},\n\t\t{\"%o\", 1, kindInt},\n\t\t{\"%O\", 1, kindInt},\n\t\t{\"%U\", 1, kindInt},\n\t\t{\"%e\", 1, kindFloat | kindComplex},\n\t\t{\"%E\", 1, kindFloat | kindComplex},\n\t\t{\"%f\", 1, kindFloat | kindComplex},\n\t\t{\"%F\", 1, kindFloat | kindComplex},\n\t\t{\"%g\", 1, kindFloat | kindComplex},\n\t\t{\"%G\", 1, kindFloat | kindComplex},\n\t\t{\"%b\", 1, kindInt | kindFloat | kindComplex | kindBytes},\n\t\t{\"%q\", 1, kindString | kindBytes | kindStringer | kindError},\n\t\t{\"%s\", 1, kindString | kindBytes | kindStringer | kindError},\n\t\t{\"%x\", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},\n\t\t{\"%X\", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},\n\t\t{\"%p\", 1, kindPtr | kindSlice | kindMap | kindFunc | kindInterface},\n\t\t{\"%w\", 1, kindError},\n\n\t\t{\"%1.2f\", 1, kindFloat | kindComplex},\n\t\t{\"%*f\", 1, kindInt},\n\t\t{\"%*f\", 2, kindFloat | kindComplex},\n\t\t{\"%*.*f\", 1, kindInt},\n\t\t{\"%*.*f\", 2, kindInt},\n\t\t{\"%*.*f\", 3, kindFloat | kindComplex},\n\t\t{\"%[3]*.[2]*[1]f\", 1, kindFloat | kindComplex},\n\t\t{\"%[3]*.[2]*[1]f\", 2, kindInt},\n\t\t{\"%[3]*.[2]*[1]f\", 3, kindInt},\n\n\t\t{\"foo %% %d\", 1, kindInt},\n\t\t{\"%#-12.34f\", 1, kindFloat | kindComplex},\n\t\t{\"% d\", 1, kindInt},\n\n\t\t{\"%s %[1]X %d\", 1, kindString | kindBytes},\n\t\t{\"%s %[1]X %d\", 2, kindInt},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(fmt.Sprintf(\"%q#%d\", c.f, c.idx), func(t *testing.T) {\n\t\t\tif got := formatOperandKind(c.f, c.idx); got != c.kind {\n\t\t\t\tt.Errorf(\"expected %d (%[1]b), got %d (%[2]b)\", c.kind, got)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/snippet/snippet_builder.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package snippet implements the specification for the LSP snippet format.\n//\n// Snippets are \"tab stop\" templates returned as an optional attribute of LSP\n// completion candidates. As the user presses tab, they cycle through a series of\n// tab stops defined in the snippet. Each tab stop can optionally have placeholder\n// text, which can be pre-selected by editors. For a full description of syntax\n// and features, see \"Snippet Syntax\" at\n// https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#textDocument_completion.\n//\n// A typical snippet looks like \"foo(${1:i int}, ${2:s string})\".\npackage snippet\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// A Builder is used to build an LSP snippet piecemeal.\n// The zero value is ready to use. Do not copy a non-zero Builder.\ntype Builder struct {\n\t// currentTabStop is the index of the previous tab stop. The\n\t// next tab stop will be currentTabStop+1.\n\tcurrentTabStop int\n\tsb             strings.Builder\n}\n\n// Escape characters defined in https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#textDocument_completion under \"Grammar\".\nvar replacer = strings.NewReplacer(\n\t`\\`, `\\\\`,\n\t`}`, `\\}`,\n\t`$`, `\\$`,\n)\n\nfunc (b *Builder) WriteText(s string) {\n\treplacer.WriteString(&b.sb, s)\n}\n\nfunc (b *Builder) PrependText(s string) {\n\trawSnip := b.String()\n\tb.sb.Reset()\n\tb.WriteText(s)\n\tb.sb.WriteString(rawSnip)\n}\n\nfunc (b *Builder) Write(data []byte) (int, error) {\n\treturn b.sb.Write(data)\n}\n\n// WritePlaceholder writes a tab stop and placeholder value to the Builder.\n// The callback style allows for creating nested placeholders. To write an\n// empty tab stop, provide a nil callback.\nfunc (b *Builder) WritePlaceholder(fn func(*Builder)) {\n\tfmt.Fprintf(&b.sb, \"${%d:\", b.nextTabStop())\n\tif fn != nil {\n\t\tfn(b)\n\t}\n\tb.sb.WriteByte('}')\n}\n\n// WriteFinalTabstop marks where cursor ends up after the user has\n// cycled through all the normal tab stops. It defaults to the\n// character after the snippet.\nfunc (b *Builder) WriteFinalTabstop() {\n\tfmt.Fprint(&b.sb, \"$0\")\n}\n\n// In addition to '\\', '}', and '$', snippet choices also use '|' and ',' as\n// meta characters, so they must be escaped within the choices.\nvar choiceReplacer = strings.NewReplacer(\n\t`\\`, `\\\\`,\n\t`}`, `\\}`,\n\t`$`, `\\$`,\n\t`|`, `\\|`,\n\t`,`, `\\,`,\n)\n\n// WriteChoice writes a tab stop and list of text choices to the Builder.\n// The user's editor will prompt the user to choose one of the choices.\nfunc (b *Builder) WriteChoice(choices []string) {\n\tfmt.Fprintf(&b.sb, \"${%d|\", b.nextTabStop())\n\tfor i, c := range choices {\n\t\tif i != 0 {\n\t\t\tb.sb.WriteByte(',')\n\t\t}\n\t\tchoiceReplacer.WriteString(&b.sb, c)\n\t}\n\tb.sb.WriteString(\"|}\")\n}\n\n// String returns the built snippet string.\nfunc (b *Builder) String() string {\n\treturn b.sb.String()\n}\n\n// Clone returns a copy of b.\nfunc (b *Builder) Clone() *Builder {\n\tvar clone Builder\n\tclone.sb.WriteString(b.String())\n\treturn &clone\n}\n\n// nextTabStop returns the next tab stop index for a new placeholder.\nfunc (b *Builder) nextTabStop() int {\n\t// Tab stops start from 1, so increment before returning.\n\tb.currentTabStop++\n\treturn b.currentTabStop\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/snippet/snippet_builder_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage snippet\n\nimport (\n\t\"testing\"\n)\n\nfunc TestSnippetBuilder(t *testing.T) {\n\texpect := func(expected string, fn func(*Builder)) {\n\t\tt.Helper()\n\n\t\tvar b Builder\n\t\tfn(&b)\n\t\tif got := b.String(); got != expected {\n\t\t\tt.Errorf(\"got %q, expected %q\", got, expected)\n\t\t}\n\t}\n\n\texpect(\"\", func(b *Builder) {})\n\n\texpect(`hi { \\} \\$ | \" , / \\\\`, func(b *Builder) {\n\t\tb.WriteText(`hi { } $ | \" , / \\`)\n\t})\n\n\texpect(\"${1:}\", func(b *Builder) {\n\t\tb.WritePlaceholder(nil)\n\t})\n\n\texpect(\"hi ${1:there}\", func(b *Builder) {\n\t\tb.WriteText(\"hi \")\n\t\tb.WritePlaceholder(func(b *Builder) {\n\t\t\tb.WriteText(\"there\")\n\t\t})\n\t})\n\n\texpect(`${1:id=${2:{your id\\}}}`, func(b *Builder) {\n\t\tb.WritePlaceholder(func(b *Builder) {\n\t\t\tb.WriteText(\"id=\")\n\t\t\tb.WritePlaceholder(func(b *Builder) {\n\t\t\t\tb.WriteText(\"{your id}\")\n\t\t\t})\n\t\t})\n\t})\n\n\texpect(`${1|one,{ \\} \\$ \\| \" \\, / \\\\,three|}`, func(b *Builder) {\n\t\tb.WriteChoice([]string{\"one\", `{ } $ | \" , / \\`, \"three\"})\n\t})\n\n\texpect(\"$0 hello\", func(b *Builder) {\n\t\tb.WriteFinalTabstop()\n\t\tb.WriteText(\" hello\")\n\t})\n\n\texpect(`prepended \\$5 ${1:} hello`, func(b *Builder) {\n\t\tb.WritePlaceholder(nil)\n\t\tb.WriteText(\" hello\")\n\t\tb.PrependText(\"prepended $5 \")\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/snippet.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// structFieldSnippet calculates the snippet for struct literal field names.\nfunc (c *completer) structFieldSnippet(cand candidate, detail string, snip *snippet.Builder) {\n\tif !wantStructFieldCompletions(c.enclosingCompositeLiteral) {\n\t\treturn\n\t}\n\n\t// If we are in a deep completion then we can't be completing a field\n\t// name (e.g. \"Foo{f<>}\" completing to \"Foo{f.Bar}\" should not generate\n\t// a snippet).\n\tif len(cand.path) > 0 {\n\t\treturn\n\t}\n\n\tclInfo := c.enclosingCompositeLiteral\n\n\t// If we are already in a key-value expression, we don't want a snippet.\n\tif clInfo.kv != nil {\n\t\treturn\n\t}\n\n\t// A plain snippet turns \"Foo{Ba<>\" into \"Foo{Bar: <>\".\n\tsnip.WriteText(\": \")\n\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t// A placeholder snippet turns \"Foo{Ba<>\" into \"Foo{Bar: <*int*>\".\n\t\tif c.opts.placeholders {\n\t\t\tb.WriteText(detail)\n\t\t}\n\t})\n\n\tfset := c.pkg.FileSet()\n\n\t// If the cursor position is on a different line from the literal's opening brace,\n\t// we are in a multiline literal. Ignore line directives.\n\tif safetoken.StartPosition(fset, c.pos).Line != safetoken.StartPosition(fset, clInfo.cl.Lbrace).Line {\n\t\tsnip.WriteText(\",\")\n\t}\n}\n\n// functionCallSnippet calculates the snippet for function calls.\n//\n// Callers should omit the suffix of type parameters that are\n// constrained by the argument types, to avoid offering completions\n// that contain instantiations that are redundant because of type\n// inference, such as f[int](1) for func f[T any](x T).\nfunc (c *completer) functionCallSnippet(name string, tparams, params []string, snip *snippet.Builder) {\n\tif !c.opts.completeFunctionCalls {\n\t\tsnip.WriteText(name)\n\t\treturn\n\t}\n\n\t// If there is no suffix then we need to reuse existing call parens\n\t// \"()\" if present. If there is an identifier suffix then we always\n\t// need to include \"()\" since we don't overwrite the suffix.\n\tif c.surrounding != nil && c.surrounding.Suffix() == \"\" && len(c.path) > 1 {\n\t\t// If we are the left side (i.e. \"Fun\") part of a call expression,\n\t\t// we don't want a snippet since there are already parens present.\n\t\tswitch n := c.path[1].(type) {\n\t\tcase *ast.CallExpr:\n\t\t\t// The Lparen != Rparen check detects fudged CallExprs we\n\t\t\t// inserted when fixing the AST. In this case, we do still need\n\t\t\t// to insert the calling \"()\" parens.\n\t\t\tif n.Fun == c.path[0] && n.Lparen != n.Rparen {\n\t\t\t\treturn\n\t\t\t}\n\t\tcase *ast.SelectorExpr:\n\t\t\tif len(c.path) > 2 {\n\t\t\t\tif call, ok := c.path[2].(*ast.CallExpr); ok && call.Fun == c.path[1] && call.Lparen != call.Rparen {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsnip.WriteText(name)\n\n\tif len(tparams) > 0 {\n\t\tsnip.WriteText(\"[\")\n\t\tif c.opts.placeholders {\n\t\t\tfor i, tp := range tparams {\n\t\t\t\tif i > 0 {\n\t\t\t\t\tsnip.WriteText(\", \")\n\t\t\t\t}\n\t\t\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\t\t\tb.WriteText(tp)\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t}\n\t\tsnip.WriteText(\"]\")\n\t}\n\n\tsnip.WriteText(\"(\")\n\n\tif c.opts.placeholders {\n\t\t// A placeholder snippet turns \"someFun<>\" into \"someFunc(<*i int*>, *s string*)\".\n\t\tfor i, p := range params {\n\t\t\tif i > 0 {\n\t\t\t\tsnip.WriteText(\", \")\n\t\t\t}\n\t\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\t\tb.WriteText(p)\n\t\t\t})\n\t\t}\n\t} else {\n\t\t// A plain snippet turns \"someFun<>\" into \"someFunc(<>)\".\n\t\tif len(params) > 0 {\n\t\t\tsnip.WritePlaceholder(nil)\n\t\t}\n\t}\n\n\tsnip.WriteText(\")\")\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/statements.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// addStatementCandidates adds full statement completion candidates\n// appropriate for the current context.\nfunc (c *completer) addStatementCandidates() {\n\tc.addErrCheck()\n\tc.addAssignAppend()\n\tc.addReturnZeroValues()\n}\n\n// addAssignAppend offers a completion candidate of the form:\n//\n//\tsomeSlice = append(someSlice, )\n//\n// It will offer the \"append\" completion in either of two situations:\n//\n//  1. Position is in RHS of assign, prefix matches \"append\", and\n//     corresponding LHS object is a slice. For example,\n//     \"foo = ap<>\" completes to \"foo = append(foo, )\".\n//\n//  2. Prefix is an ident or selector in an *ast.ExprStmt (i.e.\n//     beginning of statement), and our best matching candidate is a\n//     slice. For example: \"foo.ba\" completes to \"foo.bar = append(foo.bar, )\".\nfunc (c *completer) addAssignAppend() {\n\tif len(c.path) < 3 {\n\t\treturn\n\t}\n\n\tident, _ := c.path[0].(*ast.Ident)\n\tif ident == nil {\n\t\treturn\n\t}\n\n\tvar (\n\t\t// sliceText is the full name of our slice object, e.g. \"s.abc\" in\n\t\t// \"s.abc = app<>\".\n\t\tsliceText string\n\t\t// needsLHS is true if we need to prepend the LHS slice name and\n\t\t// \"=\" to our candidate.\n\t\tneedsLHS = false\n\t\tfset     = c.pkg.FileSet()\n\t)\n\n\tswitch n := c.path[1].(type) {\n\tcase *ast.AssignStmt:\n\t\t// We are already in an assignment. Make sure our prefix matches \"append\".\n\t\tif c.matcher.Score(\"append\") <= 0 {\n\t\t\treturn\n\t\t}\n\n\t\texprIdx := exprAtPos(c.pos, n.Rhs)\n\t\tif exprIdx == len(n.Rhs) || exprIdx > len(n.Lhs)-1 {\n\t\t\treturn\n\t\t}\n\n\t\tlhsType := c.pkg.TypesInfo().TypeOf(n.Lhs[exprIdx])\n\t\tif lhsType == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// Make sure our corresponding LHS object is a slice.\n\t\tif _, isSlice := lhsType.Underlying().(*types.Slice); !isSlice {\n\t\t\treturn\n\t\t}\n\n\t\t// The name or our slice is whatever's in the LHS expression.\n\t\tsliceText = golang.FormatNode(fset, n.Lhs[exprIdx])\n\tcase *ast.SelectorExpr:\n\t\t// Make sure we are a selector at the beginning of a statement.\n\t\tif _, parentIsExprtStmt := c.path[2].(*ast.ExprStmt); !parentIsExprtStmt {\n\t\t\treturn\n\t\t}\n\n\t\t// So far we only know the first part of our slice name. For\n\t\t// example in \"s.a<>\" we only know our slice begins with \"s.\"\n\t\t// since the user could still be typing.\n\t\tsliceText = golang.FormatNode(fset, n.X) + \".\"\n\t\tneedsLHS = true\n\tcase *ast.ExprStmt:\n\t\tneedsLHS = true\n\tdefault:\n\t\treturn\n\t}\n\n\tvar (\n\t\tlabel string\n\t\tsnip  snippet.Builder\n\t\tscore = highScore\n\t)\n\n\tif needsLHS {\n\t\t// Offer the long form assign + append candidate if our best\n\t\t// candidate is a slice.\n\t\tbestItem := c.topCandidate()\n\t\tif bestItem == nil || !bestItem.isSlice {\n\t\t\treturn\n\t\t}\n\n\t\t// Don't rank the full form assign + append candidate above the\n\t\t// slice itself.\n\t\tscore = bestItem.Score - 0.01\n\n\t\t// Fill in rest of sliceText now that we have the object name.\n\t\tsliceText += bestItem.Label\n\n\t\t// Fill in the candidate's LHS bits.\n\t\tlabel = fmt.Sprintf(\"%s = \", bestItem.Label)\n\t\tsnip.WriteText(label)\n\t}\n\n\tsnip.WriteText(fmt.Sprintf(\"append(%s, \", sliceText))\n\tsnip.WritePlaceholder(nil)\n\tsnip.WriteText(\")\")\n\n\tc.items = append(c.items, CompletionItem{\n\t\tLabel:   label + fmt.Sprintf(\"append(%s, )\", sliceText),\n\t\tKind:    protocol.FunctionCompletion,\n\t\tScore:   score,\n\t\tsnippet: &snip,\n\t})\n}\n\n// topCandidate returns the strictly highest scoring candidate\n// collected so far. If the top two candidates have the same score,\n// nil is returned.\nfunc (c *completer) topCandidate() *CompletionItem {\n\tvar bestItem, secondBestItem *CompletionItem\n\tfor i := range c.items {\n\t\tif bestItem == nil || c.items[i].Score > bestItem.Score {\n\t\t\tbestItem = &c.items[i]\n\t\t} else if secondBestItem == nil || c.items[i].Score > secondBestItem.Score {\n\t\t\tsecondBestItem = &c.items[i]\n\t\t}\n\t}\n\n\t// If secondBestItem has the same score, bestItem isn't\n\t// the strict best.\n\tif secondBestItem != nil && secondBestItem.Score == bestItem.Score {\n\t\treturn nil\n\t}\n\n\treturn bestItem\n}\n\n// addErrCheck offers a completion candidate of the form:\n//\n//\tif err != nil {\n//\t  return nil, err\n//\t}\n//\n// In the case of test functions, it offers a completion candidate of the form:\n//\n//\tif err != nil {\n//\t  t.Fatal(err)\n//\t}\n//\n// The position must be in a function that returns an error, and the\n// statement preceding the position must be an assignment where the\n// final LHS object is an error. addErrCheck will synthesize\n// zero values as necessary to make the return statement valid.\nfunc (c *completer) addErrCheck() {\n\tif len(c.path) < 2 || c.enclosingFunc == nil || !c.opts.placeholders {\n\t\treturn\n\t}\n\n\tvar (\n\t\terrorType        = types.Universe.Lookup(\"error\").Type()\n\t\tresult           = c.enclosingFunc.sig.Results()\n\t\ttestVar          = getTestVar(c.enclosingFunc, c.pkg)\n\t\tisTest           = testVar != \"\"\n\t\tdoesNotReturnErr = result.Len() == 0 || !types.Identical(result.At(result.Len()-1).Type(), errorType)\n\t)\n\t// Make sure our enclosing function is a Test func or returns an error.\n\tif !isTest && doesNotReturnErr {\n\t\treturn\n\t}\n\n\tprevLine := prevStmt(c.pos, c.path)\n\tif prevLine == nil {\n\t\treturn\n\t}\n\n\t// Make sure our preceding statement was as assignment.\n\tassign, _ := prevLine.(*ast.AssignStmt)\n\tif assign == nil || len(assign.Lhs) == 0 {\n\t\treturn\n\t}\n\n\tlastAssignee := assign.Lhs[len(assign.Lhs)-1]\n\n\t// Make sure the final assignee is an error.\n\tif !types.Identical(c.pkg.TypesInfo().TypeOf(lastAssignee), errorType) {\n\t\treturn\n\t}\n\n\tvar (\n\t\t// errVar is e.g. \"err\" in \"foo, err := bar()\".\n\t\terrVar = golang.FormatNode(c.pkg.FileSet(), lastAssignee)\n\n\t\t// Whether we need to include the \"if\" keyword in our candidate.\n\t\tneedsIf = true\n\t)\n\n\t// If the returned error from the previous statement is \"_\", it is not a real object.\n\t// If we don't have an error, and the function signature takes a testing.TB that is either ignored\n\t// or an \"_\", then we also can't call t.Fatal(err).\n\tif errVar == \"_\" {\n\t\treturn\n\t}\n\n\t// Below we try to detect if the user has already started typing \"if\n\t// err\" so we can replace what they've typed with our complete\n\t// statement.\n\tswitch n := c.path[0].(type) {\n\tcase *ast.Ident:\n\t\tswitch c.path[1].(type) {\n\t\tcase *ast.ExprStmt:\n\t\t\t// This handles:\n\t\t\t//\n\t\t\t//     f, err := os.Open(\"foo\")\n\t\t\t//     i<>\n\n\t\t\t// Make sure they are typing \"if\".\n\t\t\tif c.matcher.Score(\"if\") <= 0 {\n\t\t\t\treturn\n\t\t\t}\n\t\tcase *ast.IfStmt:\n\t\t\t// This handles:\n\t\t\t//\n\t\t\t//     f, err := os.Open(\"foo\")\n\t\t\t//     if er<>\n\n\t\t\t// Make sure they are typing the error's name.\n\t\t\tif c.matcher.Score(errVar) <= 0 {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tneedsIf = false\n\t\tdefault:\n\t\t\treturn\n\t\t}\n\tcase *ast.IfStmt:\n\t\t// This handles:\n\t\t//\n\t\t//     f, err := os.Open(\"foo\")\n\t\t//     if <>\n\n\t\t// Avoid false positives by ensuring the if's cond is a bad\n\t\t// expression. For example, don't offer the completion in cases\n\t\t// like \"if <> somethingElse\".\n\t\tif _, bad := n.Cond.(*ast.BadExpr); !bad {\n\t\t\treturn\n\t\t}\n\n\t\t// If \"if\" is our direct prefix, we need to include it in our\n\t\t// candidate since the existing \"if\" will be overwritten.\n\t\tneedsIf = c.pos == n.Pos()+token.Pos(len(\"if\"))\n\t}\n\n\t// Build up a snippet that looks like:\n\t//\n\t//     if err != nil {\n\t//       return <zero value>, ..., ${1:err}\n\t//     }\n\t//\n\t// We make the error a placeholder so it is easy to alter the error.\n\tvar snip snippet.Builder\n\tif needsIf {\n\t\tsnip.WriteText(\"if \")\n\t}\n\tsnip.WriteText(fmt.Sprintf(\"%s != nil {\\n\\t\", errVar))\n\n\tvar label string\n\tif isTest {\n\t\tsnip.WriteText(fmt.Sprintf(\"%s.Fatal(%s)\", testVar, errVar))\n\t\tlabel = fmt.Sprintf(\"%[1]s != nil { %[2]s.Fatal(%[1]s) }\", errVar, testVar)\n\t} else {\n\t\tsnip.WriteText(\"return \")\n\t\tfor i := range result.Len() - 1 {\n\t\t\tif zero, isValid := typesinternal.ZeroString(result.At(i).Type(), c.qual); isValid {\n\t\t\t\tsnip.WriteText(zero)\n\t\t\t}\n\t\t\tsnip.WriteText(\", \")\n\t\t}\n\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\tb.WriteText(errVar)\n\t\t})\n\t\tlabel = fmt.Sprintf(\"%[1]s != nil { return %[1]s }\", errVar)\n\t}\n\n\tsnip.WriteText(\"\\n}\")\n\n\tif needsIf {\n\t\tlabel = \"if \" + label\n\t}\n\n\tc.items = append(c.items, CompletionItem{\n\t\tLabel:   label,\n\t\tKind:    protocol.SnippetCompletion,\n\t\tScore:   highScore,\n\t\tsnippet: &snip,\n\t})\n}\n\n// getTestVar checks the function signature's input parameters and returns\n// the name of the first parameter that implements \"testing.TB\". For example,\n// func someFunc(t *testing.T) returns the string \"t\", func someFunc(b *testing.B)\n// returns \"b\" etc. An empty string indicates that the function signature\n// does not take a testing.TB parameter or does so but is ignored such\n// as func someFunc(*testing.T).\nfunc getTestVar(enclosingFunc *funcInfo, pkg *cache.Package) string {\n\tif enclosingFunc == nil || enclosingFunc.sig == nil {\n\t\treturn \"\"\n\t}\n\n\tvar testingPkg *types.Package\n\tfor _, p := range pkg.Types().Imports() {\n\t\tif p.Path() == \"testing\" {\n\t\t\ttestingPkg = p\n\t\t\tbreak\n\t\t}\n\t}\n\tif testingPkg == nil {\n\t\treturn \"\"\n\t}\n\ttbObj := testingPkg.Scope().Lookup(\"TB\")\n\tif tbObj == nil {\n\t\treturn \"\"\n\t}\n\tiface, ok := tbObj.Type().Underlying().(*types.Interface)\n\tif !ok {\n\t\treturn \"\"\n\t}\n\n\tsig := enclosingFunc.sig\n\tfor param := range sig.Params().Variables() {\n\t\tif param.Name() == \"_\" {\n\t\t\tcontinue\n\t\t}\n\t\tif !types.Implements(param.Type(), iface) {\n\t\t\tcontinue\n\t\t}\n\t\treturn param.Name()\n\t}\n\n\treturn \"\"\n}\n\n// addReturnZeroValues offers a snippet candidate on the form:\n//\n//\treturn 0, \"\", nil\n//\n// Requires a partially or fully written return keyword at position.\n// Requires current position to be in a function with more than\n// zero return parameters.\nfunc (c *completer) addReturnZeroValues() {\n\tif len(c.path) < 2 || c.enclosingFunc == nil || !c.opts.placeholders {\n\t\treturn\n\t}\n\tresult := c.enclosingFunc.sig.Results()\n\tif result.Len() == 0 {\n\t\treturn\n\t}\n\n\t// Offer just less than we expect from return as a keyword.\n\tvar score = stdScore - 0.01\n\tswitch c.path[0].(type) {\n\tcase *ast.ReturnStmt, *ast.Ident:\n\t\tf := c.matcher.Score(\"return\")\n\t\tif f <= 0 {\n\t\t\treturn\n\t\t}\n\t\tscore *= float64(f)\n\tdefault:\n\t\treturn\n\t}\n\n\t// The snippet will have a placeholder over each return value.\n\t// The label will not.\n\tvar snip snippet.Builder\n\tvar label strings.Builder\n\tsnip.WriteText(\"return \")\n\tfmt.Fprintf(&label, \"return \")\n\n\tfor i := range result.Len() {\n\t\tif i > 0 {\n\t\t\tsnip.WriteText(\", \")\n\t\t\tfmt.Fprintf(&label, \", \")\n\t\t}\n\n\t\tzero, isValid := typesinternal.ZeroString(result.At(i).Type(), c.qual)\n\t\tif !isValid {\n\t\t\tzero = \"\"\n\t\t}\n\t\tsnip.WritePlaceholder(func(b *snippet.Builder) {\n\t\t\tb.WriteText(zero)\n\t\t})\n\t\tfmt.Fprint(&label, zero)\n\t}\n\n\tc.items = append(c.items, CompletionItem{\n\t\tLabel:   label.String(),\n\t\tKind:    protocol.SnippetCompletion,\n\t\tScore:   score,\n\t\tsnippet: &snip,\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/unify.go",
    "content": "// Below was copied from go/types/unify.go on September 24, 2024,\n// and combined with snippets from other files as well.\n// It is copied to implement unification for code completion inferences,\n// in lieu of an official type unification API.\n//\n// TODO: When such an API is available, the code below should deleted.\n//\n// Due to complexity of extracting private types from the go/types package,\n// the unifier does not fully implement interface unification.\n//\n// The code has been modified to compile without introducing any key functionality changes.\n//\n\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements type unification.\n//\n// Type unification attempts to make two types x and y structurally\n// equivalent by determining the types for a given list of (bound)\n// type parameters which may occur within x and y. If x and y are\n// structurally different (say []T vs chan T), or conflicting\n// types are determined for type parameters, unification fails.\n// If unification succeeds, as a side-effect, the types of the\n// bound type parameters may be determined.\n//\n// Unification typically requires multiple calls u.unify(x, y) to\n// a given unifier u, with various combinations of types x and y.\n// In each call, additional type parameter types may be determined\n// as a side effect and recorded in u.\n// If a call fails (returns false), unification fails.\n//\n// In the unification context, structural equivalence of two types\n// ignores the difference between a defined type and its underlying\n// type if one type is a defined type and the other one is not.\n// It also ignores the difference between an (external, unbound)\n// type parameter and its core type.\n// If two types are not structurally equivalent, they cannot be Go\n// identical types. On the other hand, if they are structurally\n// equivalent, they may be Go identical or at least assignable, or\n// they may be in the type set of a constraint.\n// Whether they indeed are identical or assignable is determined\n// upon instantiation and function argument passing.\n\npackage completion\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"strings\"\n)\n\nconst (\n\t// Upper limit for recursion depth. Used to catch infinite recursions\n\t// due to implementation issues (e.g., see issues go.dev/issue/48619, go.dev/issue/48656).\n\tunificationDepthLimit = 50\n\n\t// Whether to panic when unificationDepthLimit is reached.\n\t// If disabled, a recursion depth overflow results in a (quiet)\n\t// unification failure.\n\tpanicAtUnificationDepthLimit = true\n\n\t// If enableCoreTypeUnification is set, unification will consider\n\t// the core types, if any, of non-local (unbound) type parameters.\n\tenableCoreTypeUnification = true\n)\n\n// A unifier maintains a list of type parameters and\n// corresponding types inferred for each type parameter.\n// A unifier is created by calling newUnifier.\ntype unifier struct {\n\t// handles maps each type parameter to its inferred type through\n\t// an indirection *Type called (inferred type) \"handle\".\n\t// Initially, each type parameter has its own, separate handle,\n\t// with a nil (i.e., not yet inferred) type.\n\t// After a type parameter P is unified with a type parameter Q,\n\t// P and Q share the same handle (and thus type). This ensures\n\t// that inferring the type for a given type parameter P will\n\t// automatically infer the same type for all other parameters\n\t// unified (joined) with P.\n\thandles map[*types.TypeParam]*types.Type\n\tdepth   int // recursion depth during unification\n}\n\n// newUnifier returns a new unifier initialized with the given type parameter\n// and corresponding type argument lists. The type argument list may be shorter\n// than the type parameter list, and it may contain nil types. Matching type\n// parameters and arguments must have the same index.\nfunc newUnifier(tparams []*types.TypeParam, targs []types.Type) *unifier {\n\thandles := make(map[*types.TypeParam]*types.Type, len(tparams))\n\t// Allocate all handles up-front: in a correct program, all type parameters\n\t// must be resolved and thus eventually will get a handle.\n\t// Also, sharing of handles caused by unified type parameters is rare and\n\t// so it's ok to not optimize for that case (and delay handle allocation).\n\tfor i, x := range tparams {\n\t\tvar t types.Type\n\t\tif i < len(targs) {\n\t\t\tt = targs[i]\n\t\t}\n\t\thandles[x] = &t\n\t}\n\treturn &unifier{handles, 0}\n}\n\n// unifyMode controls the behavior of the unifier.\ntype unifyMode uint\n\nconst (\n\t// If unifyModeAssign is set, we are unifying types involved in an assignment:\n\t// they may match inexactly at the top, but element types must match\n\t// exactly.\n\tunifyModeAssign unifyMode = 1 << iota\n\n\t// If unifyModeExact is set, types unify if they are identical (or can be\n\t// made identical with suitable arguments for type parameters).\n\t// Otherwise, a named type and a type literal unify if their\n\t// underlying types unify, channel directions are ignored, and\n\t// if there is an interface, the other type must implement the\n\t// interface.\n\tunifyModeExact\n)\n\n// This function was copied from go/types/unify.go\n//\n// unify attempts to unify x and y and reports whether it succeeded.\n// As a side-effect, types may be inferred for type parameters.\n// The mode parameter controls how types are compared.\nfunc (u *unifier) unify(x, y types.Type, mode unifyMode) bool {\n\treturn u.nify(x, y, mode)\n}\n\n// join unifies the given type parameters x and y.\n// If both type parameters already have a type associated with them\n// and they are not joined, join fails and returns false.\nfunc (u *unifier) join(x, y *types.TypeParam) bool {\n\tswitch hx, hy := u.handles[x], u.handles[y]; {\n\tcase hx == hy:\n\t\t// Both type parameters already share the same handle. Nothing to do.\n\tcase *hx != nil && *hy != nil:\n\t\t// Both type parameters have (possibly different) inferred types. Cannot join.\n\t\treturn false\n\tcase *hx != nil:\n\t\t// Only type parameter x has an inferred type. Use handle of x.\n\t\tu.setHandle(y, hx)\n\t// This case is treated like the default case.\n\t// case *hy != nil:\n\t// \t// Only type parameter y has an inferred type. Use handle of y.\n\t//\tu.setHandle(x, hy)\n\tdefault:\n\t\t// Neither type parameter has an inferred type. Use handle of y.\n\t\tu.setHandle(x, hy)\n\t}\n\treturn true\n}\n\n// asBoundTypeParam returns x.(*types.TypeParam) if x is a type parameter recorded with u.\n// Otherwise, the result is nil.\nfunc (u *unifier) asBoundTypeParam(x types.Type) *types.TypeParam {\n\tif x, _ := types.Unalias(x).(*types.TypeParam); x != nil {\n\t\tif _, found := u.handles[x]; found {\n\t\t\treturn x\n\t\t}\n\t}\n\treturn nil\n}\n\n// setHandle sets the handle for type parameter x\n// (and all its joined type parameters) to h.\nfunc (u *unifier) setHandle(x *types.TypeParam, h *types.Type) {\n\thx := u.handles[x]\n\tfor y, hy := range u.handles {\n\t\tif hy == hx {\n\t\t\tu.handles[y] = h\n\t\t}\n\t}\n}\n\n// at returns the (possibly nil) type for type parameter x.\nfunc (u *unifier) at(x *types.TypeParam) types.Type {\n\treturn *u.handles[x]\n}\n\n// set sets the type t for type parameter x;\n// t must not be nil.\nfunc (u *unifier) set(x *types.TypeParam, t types.Type) {\n\t*u.handles[x] = t\n}\n\n// asInterface returns the underlying type of x as an interface if\n// it is a non-type parameter interface. Otherwise it returns nil.\nfunc asInterface(x types.Type) (i *types.Interface) {\n\tif _, ok := types.Unalias(x).(*types.TypeParam); !ok {\n\t\ti, _ = x.Underlying().(*types.Interface)\n\t}\n\treturn i\n}\n\nfunc isTypeParam(t types.Type) bool {\n\t_, ok := types.Unalias(t).(*types.TypeParam)\n\treturn ok\n}\n\nfunc asNamed(t types.Type) *types.Named {\n\tn, _ := types.Unalias(t).(*types.Named)\n\treturn n\n}\n\nfunc isTypeLit(t types.Type) bool {\n\tswitch types.Unalias(t).(type) {\n\tcase *types.Named, *types.TypeParam:\n\t\treturn false\n\t}\n\treturn true\n}\n\n// identicalOrigin reports whether x and y originated in the same declaration.\nfunc identicalOrigin(x, y *types.Named) bool {\n\t// TODO(gri) is this correct?\n\treturn x.Origin().Obj() == y.Origin().Obj()\n}\n\nfunc coreType(t types.Type) types.Type {\n\tt = types.Unalias(t)\n\ttpar, _ := t.(*types.TypeParam)\n\tif tpar == nil {\n\t\treturn t.Underlying()\n\t}\n\n\treturn nil\n}\n\nfunc sameId(obj *types.Var, pkg *types.Package, name string, foldCase bool) bool {\n\t// If we don't care about capitalization, we also ignore packages.\n\tif foldCase && strings.EqualFold(obj.Name(), name) {\n\t\treturn true\n\t}\n\t// spec:\n\t// \"Two identifiers are different if they are spelled differently,\n\t// or if they appear in different packages and are not exported.\n\t// Otherwise, they are the same.\"\n\tif obj.Name() != name {\n\t\treturn false\n\t}\n\t// obj.Name == name\n\tif obj.Exported() {\n\t\treturn true\n\t}\n\t// not exported, so packages must be the same\n\tif obj.Pkg() != nil && pkg != nil {\n\t\treturn obj.Pkg() == pkg\n\t}\n\treturn obj.Pkg().Path() == pkg.Path()\n}\n\n// nify implements the core unification algorithm which is an\n// adapted version of Checker.identical. For changes to that\n// code the corresponding changes should be made here.\n// Must not be called directly from outside the unifier.\nfunc (u *unifier) nify(x, y types.Type, mode unifyMode) (result bool) {\n\tu.depth++\n\tdefer func() {\n\t\tu.depth--\n\t}()\n\n\t// nothing to do if x == y\n\tif x == y || types.Unalias(x) == types.Unalias(y) {\n\t\treturn true\n\t}\n\n\t// Stop gap for cases where unification fails.\n\tif u.depth > unificationDepthLimit {\n\t\tif panicAtUnificationDepthLimit {\n\t\t\tpanic(\"unification reached recursion depth limit\")\n\t\t}\n\t\treturn false\n\t}\n\n\t// Unification is symmetric, so we can swap the operands.\n\t// Ensure that if we have at least one\n\t// - defined type, make sure one is in y\n\t// - type parameter recorded with u, make sure one is in x\n\tif asNamed(x) != nil || u.asBoundTypeParam(y) != nil {\n\t\tx, y = y, x\n\t}\n\n\t// Unification will fail if we match a defined type against a type literal.\n\t// If we are matching types in an assignment, at the top-level, types with\n\t// the same type structure are permitted as long as at least one of them\n\t// is not a defined type. To accommodate for that possibility, we continue\n\t// unification with the underlying type of a defined type if the other type\n\t// is a type literal. This is controlled by the exact unification mode.\n\t// We also continue if the other type is a basic type because basic types\n\t// are valid underlying types and may appear as core types of type constraints.\n\t// If we exclude them, inferred defined types for type parameters may not\n\t// match against the core types of their constraints (even though they might\n\t// correctly match against some of the types in the constraint's type set).\n\t// Finally, if unification (incorrectly) succeeds by matching the underlying\n\t// type of a defined type against a basic type (because we include basic types\n\t// as type literals here), and if that leads to an incorrectly inferred type,\n\t// we will fail at function instantiation or argument assignment time.\n\t//\n\t// If we have at least one defined type, there is one in y.\n\tif ny := asNamed(y); mode&unifyModeExact == 0 && ny != nil && isTypeLit(x) {\n\t\ty = ny.Underlying()\n\t\t// Per the spec, a defined type cannot have an underlying type\n\t\t// that is a type parameter.\n\t\t// x and y may be identical now\n\t\tif x == y || types.Unalias(x) == types.Unalias(y) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Cases where at least one of x or y is a type parameter recorded with u.\n\t// If we have at least one type parameter, there is one in x.\n\t// If we have exactly one type parameter, because it is in x,\n\t// isTypeLit(x) is false and y was not changed above. In other\n\t// words, if y was a defined type, it is still a defined type\n\t// (relevant for the logic below).\n\tswitch px, py := u.asBoundTypeParam(x), u.asBoundTypeParam(y); {\n\tcase px != nil && py != nil:\n\t\t// both x and y are type parameters\n\t\tif u.join(px, py) {\n\t\t\treturn true\n\t\t}\n\t\t// both x and y have an inferred type - they must match\n\t\treturn u.nify(u.at(px), u.at(py), mode)\n\n\tcase px != nil:\n\t\t// x is a type parameter, y is not\n\t\tif x := u.at(px); x != nil {\n\t\t\t// x has an inferred type which must match y\n\t\t\tif u.nify(x, y, mode) {\n\t\t\t\t// We have a match, possibly through underlying types.\n\t\t\t\txi := asInterface(x)\n\t\t\t\tyi := asInterface(y)\n\t\t\t\txn := asNamed(x) != nil\n\t\t\t\tyn := asNamed(y) != nil\n\t\t\t\t// If we have two interfaces, what to do depends on\n\t\t\t\t// whether they are named and their method sets.\n\t\t\t\tif xi != nil && yi != nil {\n\t\t\t\t\t// Both types are interfaces.\n\t\t\t\t\t// If both types are defined types, they must be identical\n\t\t\t\t\t// because unification doesn't know which type has the \"right\" name.\n\t\t\t\t\tif xn && yn {\n\t\t\t\t\t\treturn types.Identical(x, y)\n\t\t\t\t\t}\n\t\t\t\t\treturn false\n\t\t\t\t\t// Below is the original code for reference\n\n\t\t\t\t\t// In all other cases, the method sets must match.\n\t\t\t\t\t// The types unified so we know that corresponding methods\n\t\t\t\t\t// match and we can simply compare the number of methods.\n\t\t\t\t\t// TODO(gri) We may be able to relax this rule and select\n\t\t\t\t\t// the more general interface. But if one of them is a defined\n\t\t\t\t\t// type, it's not clear how to choose and whether we introduce\n\t\t\t\t\t// an order dependency or not. Requiring the same method set\n\t\t\t\t\t// is conservative.\n\t\t\t\t\t// if len(xi.typeSet().methods) != len(yi.typeSet().methods) {\n\t\t\t\t\t// \treturn false\n\t\t\t\t\t// }\n\t\t\t\t} else if xi != nil || yi != nil {\n\t\t\t\t\t// One but not both of them are interfaces.\n\t\t\t\t\t// In this case, either x or y could be viable matches for the corresponding\n\t\t\t\t\t// type parameter, which means choosing either introduces an order dependence.\n\t\t\t\t\t// Therefore, we must fail unification (go.dev/issue/60933).\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// If we have inexact unification and one of x or y is a defined type, select the\n\t\t\t\t// defined type. This ensures that in a series of types, all matching against the\n\t\t\t\t// same type parameter, we infer a defined type if there is one, independent of\n\t\t\t\t// order. Type inference or assignment may fail, which is ok.\n\t\t\t\t// Selecting a defined type, if any, ensures that we don't lose the type name;\n\t\t\t\t// and since we have inexact unification, a value of equally named or matching\n\t\t\t\t// undefined type remains assignable (go.dev/issue/43056).\n\t\t\t\t//\n\t\t\t\t// Similarly, if we have inexact unification and there are no defined types but\n\t\t\t\t// channel types, select a directed channel, if any. This ensures that in a series\n\t\t\t\t// of unnamed types, all matching against the same type parameter, we infer the\n\t\t\t\t// directed channel if there is one, independent of order.\n\t\t\t\t// Selecting a directional channel, if any, ensures that a value of another\n\t\t\t\t// inexactly unifying channel type remains assignable (go.dev/issue/62157).\n\t\t\t\t//\n\t\t\t\t// If we have multiple defined channel types, they are either identical or we\n\t\t\t\t// have assignment conflicts, so we can ignore directionality in this case.\n\t\t\t\t//\n\t\t\t\t// If we have defined and literal channel types, a defined type wins to avoid\n\t\t\t\t// order dependencies.\n\t\t\t\tif mode&unifyModeExact == 0 {\n\t\t\t\t\tswitch {\n\t\t\t\t\tcase xn:\n\t\t\t\t\t\t// x is a defined type: nothing to do.\n\t\t\t\t\tcase yn:\n\t\t\t\t\t\t// x is not a defined type and y is a defined type: select y.\n\t\t\t\t\t\tu.set(px, y)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// Neither x nor y are defined types.\n\t\t\t\t\t\tif yc, _ := y.Underlying().(*types.Chan); yc != nil && yc.Dir() != types.SendRecv {\n\t\t\t\t\t\t\t// y is a directed channel type: select y.\n\t\t\t\t\t\t\tu.set(px, y)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\t// otherwise, infer type from y\n\t\tu.set(px, y)\n\t\treturn true\n\t}\n\n\t// If u.EnableInterfaceInference is set and we don't require exact unification,\n\t// if both types are interfaces, one interface must have a subset of the\n\t// methods of the other and corresponding method signatures must unify.\n\t// If only one type is an interface, all its methods must be present in the\n\t// other type and corresponding method signatures must unify.\n\n\t// Unless we have exact unification, neither x nor y are interfaces now.\n\t// Except for unbound type parameters (see below), x and y must be structurally\n\t// equivalent to unify.\n\n\t// If we get here and x or y is a type parameter, they are unbound\n\t// (not recorded with the unifier).\n\t// Ensure that if we have at least one type parameter, it is in x\n\t// (the earlier swap checks for _recorded_ type parameters only).\n\t// This ensures that the switch switches on the type parameter.\n\t//\n\t// TODO(gri) Factor out type parameter handling from the switch.\n\tif isTypeParam(y) {\n\t\tx, y = y, x\n\t}\n\n\t// Type elements (array, slice, etc. elements) use emode for unification.\n\t// Element types must match exactly if the types are used in an assignment.\n\temode := mode\n\tif mode&unifyModeAssign != 0 {\n\t\temode |= unifyModeExact\n\t}\n\n\t// Continue with unaliased types but don't lose original alias names, if any (go.dev/issue/67628).\n\txorig, x := x, types.Unalias(x)\n\tyorig, y := y, types.Unalias(y)\n\n\tswitch x := x.(type) {\n\tcase *types.Basic:\n\t\t// Basic types are singletons except for the rune and byte\n\t\t// aliases, thus we cannot solely rely on the x == y check\n\t\t// above. See also comment in TypeName.IsAlias.\n\t\tif y, ok := y.(*types.Basic); ok {\n\t\t\treturn x.Kind() == y.Kind()\n\t\t}\n\n\tcase *types.Array:\n\t\t// Two array types unify if they have the same array length\n\t\t// and their element types unify.\n\t\tif y, ok := y.(*types.Array); ok {\n\t\t\t// If one or both array lengths are unknown (< 0) due to some error,\n\t\t\t// assume they are the same to avoid spurious follow-on errors.\n\t\t\treturn (x.Len() < 0 || y.Len() < 0 || x.Len() == y.Len()) && u.nify(x.Elem(), y.Elem(), emode)\n\t\t}\n\n\tcase *types.Slice:\n\t\t// Two slice types unify if their element types unify.\n\t\tif y, ok := y.(*types.Slice); ok {\n\t\t\treturn u.nify(x.Elem(), y.Elem(), emode)\n\t\t}\n\n\tcase *types.Struct:\n\t\t// Two struct types unify if they have the same sequence of fields,\n\t\t// and if corresponding fields have the same names, their (field) types unify,\n\t\t// and they have identical tags. Two embedded fields are considered to have the same\n\t\t// name. Lower-case field names from different packages are always different.\n\t\tif y, ok := y.(*types.Struct); ok {\n\t\t\tif x.NumFields() == y.NumFields() {\n\t\t\t\tfor i := range x.NumFields() {\n\t\t\t\t\tf := x.Field(i)\n\t\t\t\t\tg := y.Field(i)\n\t\t\t\t\tif f.Embedded() != g.Embedded() ||\n\t\t\t\t\t\tx.Tag(i) != y.Tag(i) ||\n\t\t\t\t\t\t!sameId(f, g.Pkg(), g.Name(), false) ||\n\t\t\t\t\t\t!u.nify(f.Type(), g.Type(), emode) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\tcase *types.Pointer:\n\t\t// Two pointer types unify if their base types unify.\n\t\tif y, ok := y.(*types.Pointer); ok {\n\t\t\treturn u.nify(x.Elem(), y.Elem(), emode)\n\t\t}\n\n\tcase *types.Tuple:\n\t\t// Two tuples types unify if they have the same number of elements\n\t\t// and the types of corresponding elements unify.\n\t\tif y, ok := y.(*types.Tuple); ok {\n\t\t\tif x.Len() == y.Len() {\n\t\t\t\tif x != nil {\n\t\t\t\t\tfor i := range x.Len() {\n\t\t\t\t\t\tv := x.At(i)\n\t\t\t\t\t\tw := y.At(i)\n\t\t\t\t\t\tif !u.nify(v.Type(), w.Type(), mode) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\tcase *types.Signature:\n\t\t// Two function types unify if they have the same number of parameters\n\t\t// and result values, corresponding parameter and result types unify,\n\t\t// and either both functions are variadic or neither is.\n\t\t// Parameter and result names are not required to match.\n\t\t// TODO(gri) handle type parameters or document why we can ignore them.\n\t\tif y, ok := y.(*types.Signature); ok {\n\t\t\treturn x.Variadic() == y.Variadic() &&\n\t\t\t\tu.nify(x.Params(), y.Params(), emode) &&\n\t\t\t\tu.nify(x.Results(), y.Results(), emode)\n\t\t}\n\n\tcase *types.Interface:\n\t\treturn false\n\t\t// Below is the original code\n\n\t\t// Two interface types unify if they have the same set of methods with\n\t\t// the same names, and corresponding function types unify.\n\t\t// Lower-case method names from different packages are always different.\n\t\t// The order of the methods is irrelevant.\n\t\t// xset := x.typeSet()\n\t\t// yset := y.typeSet()\n\t\t// if xset.comparable != yset.comparable {\n\t\t// \treturn false\n\t\t// }\n\t\t// if !xset.terms.equal(yset.terms) {\n\t\t// \treturn false\n\t\t// }\n\t\t// a := xset.methods\n\t\t// b := yset.methods\n\t\t// if len(a) == len(b) {\n\t\t// \t// Interface types are the only types where cycles can occur\n\t\t// \t// that are not \"terminated\" via named types; and such cycles\n\t\t// \t// can only be created via method parameter types that are\n\t\t// \t// anonymous interfaces (directly or indirectly) embedding\n\t\t// \t// the current interface. Example:\n\t\t// \t//\n\t\t// \t//    type T interface {\n\t\t// \t//        m() interface{T}\n\t\t// \t//    }\n\t\t// \t//\n\t\t// \t// If two such (differently named) interfaces are compared,\n\t\t// \t// endless recursion occurs if the cycle is not detected.\n\t\t// \t//\n\t\t// \t// If x and y were compared before, they must be equal\n\t\t// \t// (if they were not, the recursion would have stopped);\n\t\t// \t// search the ifacePair stack for the same pair.\n\t\t// \t//\n\t\t// \t// This is a quadratic algorithm, but in practice these stacks\n\t\t// \t// are extremely short (bounded by the nesting depth of interface\n\t\t// \t// type declarations that recur via parameter types, an extremely\n\t\t// \t// rare occurrence). An alternative implementation might use a\n\t\t// \t// \"visited\" map, but that is probably less efficient overall.\n\t\t// \tq := &ifacePair{x, y, p}\n\t\t// \tfor p != nil {\n\t\t// \t\tif p.identical(q) {\n\t\t// \t\t\treturn true // same pair was compared before\n\t\t// \t\t}\n\t\t// \t\tp = p.prev\n\t\t// \t}\n\t\t// \tif debug {\n\t\t// \t\tassertSortedMethods(a)\n\t\t// \t\tassertSortedMethods(b)\n\t\t// \t}\n\t\t// \tfor i, f := range a {\n\t\t// \t\tg := b[i]\n\t\t// \t\tif f.Id() != g.Id() || !u.nify(f.typ, g.typ, exact, q) {\n\t\t// \t\t\treturn false\n\t\t// \t\t}\n\t\t// \t}\n\t\t// \treturn true\n\t\t// }\n\n\tcase *types.Map:\n\t\t// Two map types unify if their key and value types unify.\n\t\tif y, ok := y.(*types.Map); ok {\n\t\t\treturn u.nify(x.Key(), y.Key(), emode) && u.nify(x.Elem(), y.Elem(), emode)\n\t\t}\n\n\tcase *types.Chan:\n\t\t// Two channel types unify if their value types unify\n\t\t// and if they have the same direction.\n\t\t// The channel direction is ignored for inexact unification.\n\t\tif y, ok := y.(*types.Chan); ok {\n\t\t\treturn (mode&unifyModeExact == 0 || x.Dir() == y.Dir()) && u.nify(x.Elem(), y.Elem(), emode)\n\t\t}\n\n\tcase *types.Named:\n\t\t// Two named types unify if their type names originate in the same type declaration.\n\t\t// If they are instantiated, their type argument lists must unify.\n\t\tif y := asNamed(y); y != nil {\n\t\t\t// Check type arguments before origins so they unify\n\t\t\t// even if the origins don't match; for better error\n\t\t\t// messages (see go.dev/issue/53692).\n\t\t\txargs := x.TypeArgs()\n\t\t\tyargs := y.TypeArgs()\n\t\t\tif xargs.Len() != yargs.Len() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor i := range xargs.Len() {\n\t\t\t\txarg := xargs.At(i)\n\t\t\t\tyarg := yargs.At(i)\n\t\t\t\tif !u.nify(xarg, yarg, mode) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn identicalOrigin(x, y)\n\t\t}\n\n\tcase *types.TypeParam:\n\t\t// By definition, a valid type argument must be in the type set of\n\t\t// the respective type constraint. Therefore, the type argument's\n\t\t// underlying type must be in the set of underlying types of that\n\t\t// constraint. If there is a single such underlying type, it's the\n\t\t// constraint's core type. It must match the type argument's under-\n\t\t// lying type, irrespective of whether the actual type argument,\n\t\t// which may be a defined type, is actually in the type set (that\n\t\t// will be determined at instantiation time).\n\t\t// Thus, if we have the core type of an unbound type parameter,\n\t\t// we know the structure of the possible types satisfying such\n\t\t// parameters. Use that core type for further unification\n\t\t// (see go.dev/issue/50755 for a test case).\n\t\tif enableCoreTypeUnification {\n\t\t\t// Because the core type is always an underlying type,\n\t\t\t// unification will take care of matching against a\n\t\t\t// defined or literal type automatically.\n\t\t\t// If y is also an unbound type parameter, we will end\n\t\t\t// up here again with x and y swapped, so we don't\n\t\t\t// need to take care of that case separately.\n\t\t\tif cx := coreType(x); cx != nil {\n\t\t\t\t// If y is a defined type, it may not match against cx which\n\t\t\t\t// is an underlying type (incl. int, string, etc.). Use assign\n\t\t\t\t// mode here so that the unifier automatically takes under(y)\n\t\t\t\t// if necessary.\n\t\t\t\treturn u.nify(cx, yorig, unifyModeAssign)\n\t\t\t}\n\t\t}\n\t\t// x != y and there's nothing to do\n\n\tcase nil:\n\t\t// avoid a crash in case of nil type\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"u.nify(%s, %s, %d)\", xorig, yorig, mode))\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/unimported.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\n// unimported completion is invoked when the user types something like 'foo.xx',\n// foo is known to be a package name not yet imported in the current file, and\n// xx (or whatever the user has typed) is interpreted as a hint (pattern) for the\n// member of foo that the user is looking for.\n//\n// This code looks for a suitable completion in a number of places. A 'suitable\n// completion' is an exported symbol (so a type, const, var, or func) from package\n// foo, which, after converting everything to lower case, has the pattern as a\n// subsequence.\n//\n// The code looks for a suitable completion in\n// 1. the imports of some other file of the current package,\n// 2. the standard library,\n// 3. the imports of some other file in the current workspace,\n// 4. imports in the current module with 'foo' as the explicit package name,\n// 5. the module cache,\n// It stops at the first success.\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"path\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion/snippet\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/modindex\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nfunc (c *completer) unimported(ctx context.Context, pkgname metadata.PackageName, prefix string) {\n\twsIDs, ourIDs := c.findPackageIDs(pkgname)\n\tstdpkgs := c.stdlibPkgs(pkgname)\n\tif len(ourIDs) > 0 {\n\t\t// use the one in the current package, if possible\n\t\titems := c.pkgIDmatches(ctx, ourIDs, pkgname, prefix)\n\t\tif c.scoreList(items) {\n\t\t\treturn\n\t\t}\n\t}\n\t// do the stdlib next.\n\titems := c.stdlibMatches(stdpkgs, pkgname, prefix)\n\tif c.scoreList(items) {\n\t\treturn\n\t}\n\n\t// look in the rest of the workspace\n\titems = c.pkgIDmatches(ctx, wsIDs, pkgname, prefix)\n\tif c.scoreList(items) {\n\t\treturn\n\t}\n\n\t// before looking in the module cache, maybe it is an explicit\n\t// package name used in this module\n\tif c.explicitPkgName(ctx, pkgname, prefix) {\n\t\treturn\n\t}\n\n\t// look in the module cache\n\titems, err := c.modcacheMatches(pkgname, prefix)\n\titems = c.filterGoMod(ctx, items)\n\tif err == nil && c.scoreList(items) {\n\t\treturn\n\t}\n\n\t// out of things to do\n}\n\n// prefer completion items that are referenced in the go.mod file\nfunc (c *completer) filterGoMod(ctx context.Context, items []CompletionItem) []CompletionItem {\n\tif c.pkg.Metadata().Module == nil {\n\t\t// for std or GOROOT mode\n\t\treturn items\n\t}\n\tgomod := c.pkg.Metadata().Module.GoMod\n\turi := protocol.URIFromPath(gomod)\n\tfh, err := c.snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn items\n\t}\n\tpm, err := c.snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm == nil {\n\t\treturn items\n\t}\n\t// if any of the items match any of the req, just return those\n\treqnames := []string{}\n\tfor _, req := range pm.File.Require {\n\t\treqnames = append(reqnames, req.Mod.Path)\n\t}\n\tbetter := []CompletionItem{}\n\tfor _, compl := range items {\n\t\tif len(compl.AdditionalTextEdits) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// import \"foof/pkg\"\n\t\tflds := strings.FieldsFunc(compl.AdditionalTextEdits[0].NewText, func(r rune) bool {\n\t\t\treturn r == '\"' || r == '/'\n\t\t})\n\t\tif len(flds) < 3 {\n\t\t\tcontinue\n\t\t}\n\t\tif slices.Contains(reqnames, flds[1]) {\n\t\t\tbetter = append(better, compl)\n\t\t}\n\t}\n\tif len(better) > 0 {\n\t\treturn better\n\t}\n\treturn items\n}\n\n// see if some file in the current package satisfied a foo. import\n// because foo is an explicit package name (import foo \"a.b.c\")\nfunc (c *completer) explicitPkgName(ctx context.Context, pkgname metadata.PackageName, prefix string) bool {\n\tfor _, pgf := range c.pkg.CompiledGoFiles() {\n\t\timports := pgf.File.Imports\n\t\tfor _, imp := range imports {\n\t\t\tif imp.Name != nil && imp.Name.Name == string(pkgname) {\n\t\t\t\tpath := strings.Trim(imp.Path.Value, `\"`)\n\t\t\t\tif c.tryPath(ctx, metadata.PackagePath(path), string(pkgname), prefix) {\n\t\t\t\t\treturn true // one is enough\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// see if this path contains a usable import with explicit package name\nfunc (c *completer) tryPath(ctx context.Context, path metadata.PackagePath, pkgname, prefix string) bool {\n\tpackages := c.snapshot.MetadataGraph().ForPackagePath\n\tids := []metadata.PackageID{}\n\tfor _, pkg := range packages[path] { // could there ever be more than one?\n\t\tids = append(ids, pkg.ID) // pkg.ID. ID: \"math/rand\" but Name: \"rand\"\n\t}\n\titems := c.pkgIDmatches(ctx, ids, metadata.PackageName(pkgname), prefix)\n\treturn c.scoreList(items)\n}\n\n// find all the packageIDs for packages in the workspace that have the desired name\n// thisPkgIDs contains the ones known to the current package, wsIDs contains the others\nfunc (c *completer) findPackageIDs(pkgname metadata.PackageName) (wsIDs, thisPkgIDs []metadata.PackageID) {\n\tg := c.snapshot.MetadataGraph()\n\tfor pid, pkg := range c.snapshot.MetadataGraph().Packages {\n\t\tif pkg.Name != pkgname {\n\t\t\tcontinue\n\t\t}\n\t\timports := g.ImportedBy[pid]\n\t\t// Metadata is not canonical: it may be held onto by a package. Therefore,\n\t\t// we must compare by ID.\n\t\tthisPkg := func(mp *metadata.Package) bool { return mp.ID == c.pkg.Metadata().ID }\n\t\tif slices.ContainsFunc(imports, thisPkg) {\n\t\t\tthisPkgIDs = append(thisPkgIDs, pid)\n\t\t} else {\n\t\t\twsIDs = append(wsIDs, pid)\n\t\t}\n\t}\n\treturn\n}\n\n// find all the stdlib packages that have the desired name\nfunc (c *completer) stdlibPkgs(pkgname metadata.PackageName) []metadata.PackagePath {\n\tvar pkgs []metadata.PackagePath // stlib packages that match pkg\n\tfor pkgpath := range stdlib.PackageSymbols {\n\t\tv := metadata.PackageName(path.Base(pkgpath))\n\t\tif v == pkgname {\n\t\t\tpkgs = append(pkgs, metadata.PackagePath(pkgpath))\n\t\t} else if imports.WithoutVersion(string(pkgpath)) == string(pkgname) {\n\t\t\tpkgs = append(pkgs, metadata.PackagePath(pkgpath))\n\t\t}\n\t}\n\treturn pkgs\n}\n\n// return CompletionItems for all matching symbols in the packages in ids.\nfunc (c *completer) pkgIDmatches(ctx context.Context, ids []metadata.PackageID, pkgname metadata.PackageName, prefix string) []CompletionItem {\n\tpattern := strings.ToLower(prefix)\n\tallpkgsyms, err := c.snapshot.Symbols(ctx, ids...)\n\tif err != nil {\n\t\treturn nil // would if be worth retrying the ids one by one?\n\t}\n\tif len(allpkgsyms) != len(ids) {\n\t\tbug.Reportf(\"Symbols returned %d values for %d pkgIDs\", len(allpkgsyms), len(ids))\n\t\treturn nil\n\t}\n\tvar got []CompletionItem\n\tfor i, pkgID := range ids {\n\t\tpkg := c.snapshot.MetadataGraph().Packages[pkgID]\n\t\tif pkg == nil {\n\t\t\tbug.Reportf(\"no metadata for %s\", pkgID)\n\t\t\tcontinue // something changed underfoot, otherwise can't happen\n\t\t}\n\t\tpkgsyms := allpkgsyms[i]\n\t\tpkgfname := pkgsyms.Files[0].Path()\n\t\tif !imports.CanUse(c.filename, pkgfname) {\n\t\t\t// avoid unusable internal, etc\n\t\t\tcontinue\n\t\t}\n\t\t// are any of these any good?\n\t\tfor np, asym := range pkgsyms.Symbols {\n\t\t\tfor _, sym := range asym {\n\t\t\t\tif !token.IsExported(sym.Name) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif !usefulCompletion(sym.Name, pattern) {\n\t\t\t\t\t// for json.U, the existing code finds InvalidUTF8Error\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvar params []string\n\t\t\t\tvar kind protocol.CompletionItemKind\n\t\t\t\tvar detail string\n\t\t\t\tswitch sym.Kind {\n\t\t\t\tcase protocol.Function:\n\t\t\t\t\tfoundURI := pkgsyms.Files[np]\n\t\t\t\t\tfh, _ := c.snapshot.ReadFile(ctx, foundURI)\n\t\t\t\t\tpgf, err := c.snapshot.ParseGo(ctx, fh, 0)\n\t\t\t\t\tif err == nil {\n\t\t\t\t\t\tparams = funcParams(pgf.File, sym.Name)\n\t\t\t\t\t}\n\t\t\t\t\tkind = protocol.FunctionCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"func (from %q)\", pkg.PkgPath)\n\t\t\t\tcase protocol.Variable, protocol.Struct:\n\t\t\t\t\tkind = protocol.VariableCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"var (from %q)\", pkg.PkgPath)\n\t\t\t\tcase protocol.Constant:\n\t\t\t\t\tkind = protocol.ConstantCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"const (from %q)\", pkg.PkgPath)\n\t\t\t\tdefault:\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tgot = c.appendNewItem(got, sym.Name,\n\t\t\t\t\tdetail,\n\t\t\t\t\tpkg.PkgPath,\n\t\t\t\t\tkind,\n\t\t\t\t\tpkgname, params)\n\t\t\t}\n\t\t}\n\t}\n\treturn got\n}\n\n// return CompletionItems for all the matches in packages in pkgs.\nfunc (c *completer) stdlibMatches(pkgs []metadata.PackagePath, pkg metadata.PackageName, prefix string) []CompletionItem {\n\t// check for deprecated symbols someday\n\tgot := make([]CompletionItem, 0)\n\tpattern := strings.ToLower(prefix)\n\t// avoid non-determinacy, especially for marker tests\n\tslices.Sort(pkgs)\n\tfor _, candpkg := range pkgs {\n\t\tif std, ok := stdlib.PackageSymbols[string(candpkg)]; ok {\n\t\t\tfor _, sym := range std {\n\t\t\t\tif !usefulCompletion(sym.Name, pattern) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif !versions.AtLeast(c.goversion, sym.Version.String()) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvar kind protocol.CompletionItemKind\n\t\t\t\tvar detail string\n\t\t\t\tvar params []string\n\t\t\t\tswitch sym.Kind {\n\t\t\t\tcase stdlib.Func:\n\t\t\t\t\tparams = parseSignature(sym.Signature)\n\t\t\t\t\tkind = protocol.FunctionCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"func (from %q)\", candpkg)\n\t\t\t\tcase stdlib.Const:\n\t\t\t\t\tkind = protocol.ConstantCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"const (from %q)\", candpkg)\n\t\t\t\tcase stdlib.Var:\n\t\t\t\t\tkind = protocol.VariableCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"var (from %q)\", candpkg)\n\t\t\t\tcase stdlib.Type:\n\t\t\t\t\tkind = protocol.VariableCompletion\n\t\t\t\t\tdetail = fmt.Sprintf(\"type (from %q)\", candpkg)\n\t\t\t\tdefault:\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tgot = c.appendNewItem(got, sym.Name,\n\t\t\t\t\tdetail,\n\t\t\t\t\tcandpkg,\n\t\t\t\t\tkind,\n\t\t\t\t\tpkg, params)\n\t\t\t}\n\t\t}\n\t}\n\treturn got\n}\n\nfunc (c *completer) modcacheMatches(pkg metadata.PackageName, prefix string) ([]CompletionItem, error) {\n\tix, err := c.snapshot.View().ModcacheIndex()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// retrieve everything and let usefulCompletion() and the matcher sort them out\n\tcands := ix.Lookup(string(pkg), \"\", true)\n\tlx := len(cands)\n\tgot := make([]CompletionItem, 0, lx)\n\tpattern := strings.ToLower(prefix)\n\tfor _, cand := range cands {\n\t\tif !usefulCompletion(cand.Name, pattern) {\n\t\t\tcontinue\n\t\t}\n\t\tvar params []string\n\t\tvar kind protocol.CompletionItemKind\n\t\tvar detail string\n\t\tswitch cand.Type {\n\t\tcase modindex.Func:\n\t\t\tfor _, f := range cand.Sig {\n\t\t\t\tparams = append(params, fmt.Sprintf(\"%s %s\", f.Arg, f.Type))\n\t\t\t}\n\t\t\tkind = protocol.FunctionCompletion\n\t\t\tdetail = fmt.Sprintf(\"func (from %s)\", cand.ImportPath)\n\t\tcase modindex.Var:\n\t\t\tkind = protocol.VariableCompletion\n\t\t\tdetail = fmt.Sprintf(\"var (from %s)\", cand.ImportPath)\n\t\tcase modindex.Const:\n\t\t\tkind = protocol.ConstantCompletion\n\t\t\tdetail = fmt.Sprintf(\"const (from %s)\", cand.ImportPath)\n\t\tcase modindex.Type: // might be a type alias\n\t\t\tkind = protocol.VariableCompletion\n\t\t\tdetail = fmt.Sprintf(\"type (from %s)\", cand.ImportPath)\n\t\tdefault:\n\t\t\tcontinue\n\t\t}\n\t\tgot = c.appendNewItem(got, cand.Name,\n\t\t\tdetail,\n\t\t\tmetadata.PackagePath(cand.ImportPath),\n\t\t\tkind,\n\t\t\tpkg, params)\n\t}\n\treturn got, nil\n}\n\nfunc (c *completer) appendNewItem(got []CompletionItem, name, detail string, path metadata.PackagePath, kind protocol.CompletionItemKind, pkg metadata.PackageName, params []string) []CompletionItem {\n\titem := CompletionItem{\n\t\tLabel:      name,\n\t\tDetail:     detail,\n\t\tInsertText: name,\n\t\tKind:       kind,\n\t}\n\timp := importInfo{\n\t\timportPath: string(path),\n\t\tname:       string(pkg),\n\t}\n\tif imports.ImportPathToAssumedName(string(path)) == string(pkg) {\n\t\timp.name = \"\"\n\t}\n\titem.AdditionalTextEdits, _ = c.importEdits(&imp)\n\tif params != nil {\n\t\tvar sn snippet.Builder\n\t\tc.functionCallSnippet(name, nil, params, &sn)\n\t\titem.snippet = &sn\n\t}\n\tgot = append(got, item)\n\treturn got\n}\n\n// score the list. Return true if any item is added to c.items\nfunc (c *completer) scoreList(items []CompletionItem) bool {\n\tret := false\n\tfor _, item := range items {\n\t\titem.Score = float64(c.matcher.Score(item.Label))\n\t\tif item.Score > 0 {\n\t\t\tc.items = append(c.items, item)\n\t\t\tret = true\n\t\t}\n\t}\n\treturn ret\n}\n\n// pattern is always the result of strings.ToLower\nfunc usefulCompletion(name, pattern string) bool {\n\t// this travesty comes from foo.(type) somehow. see issue59096.txt\n\tif pattern == \"_\" {\n\t\treturn true\n\t}\n\t// convert both to lower case, and then the runes in the pattern have to occur, in order,\n\t// in the name\n\tcand := strings.ToLower(name)\n\tfor _, r := range pattern {\n\t\tix := strings.IndexRune(cand, r)\n\t\tif ix < 0 {\n\t\t\treturn false\n\t\t}\n\t\tcand = cand[ix+1:]\n\t}\n\treturn true\n}\n\n// return a printed version of the function arguments for snippets\nfunc funcParams(f *ast.File, fname string) []string {\n\tvar params []string\n\tsetParams := func(list *ast.FieldList) {\n\t\tif list == nil {\n\t\t\treturn\n\t\t}\n\t\tvar cfg printer.Config // slight overkill\n\t\tparam := func(name string, typ ast.Expr) {\n\t\t\tvar buf strings.Builder\n\t\t\tbuf.WriteString(name)\n\t\t\tbuf.WriteByte(' ')\n\t\t\tcfg.Fprint(&buf, token.NewFileSet(), typ) // ignore error\n\t\t\tparams = append(params, buf.String())\n\t\t}\n\n\t\tfor _, field := range list.List {\n\t\t\tif field.Names != nil {\n\t\t\t\tfor _, name := range field.Names {\n\t\t\t\t\tparam(name.Name, field.Type)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparam(\"_\", field.Type)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, n := range f.Decls {\n\t\tswitch x := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif x.Recv == nil && x.Name.Name == fname {\n\t\t\t\tsetParams(x.Type.Params)\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n// extract the formal parameters from the signature.\n// func[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) -> []{\"dst M1\", \"src M2\"}\n// func[K comparable, V any](seq iter.Seq2[K, V]) map[K]V -> []{\"seq iter.Seq2[K, V]\"}\n// func(args ...any) *Logger -> []{\"args ...any\"}\n// func[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) -> []{\"m M\", \"del func(K, V) bool\"}\nfunc parseSignature(sig string) []string {\n\tvar level int       // nesting level of delimiters\n\tvar processing bool // are we doing the params\n\tvar last int        // start of current parameter\n\tvar params []string\n\tfor i := range len(sig) {\n\t\tswitch sig[i] {\n\t\tcase '[', '{':\n\t\t\tlevel++\n\t\tcase ']', '}':\n\t\t\tlevel--\n\t\tcase '(':\n\t\t\tlevel++\n\t\t\tif level == 1 {\n\t\t\t\tprocessing = true\n\t\t\t\tlast = i + 1\n\t\t\t}\n\t\tcase ')':\n\t\t\tlevel--\n\t\t\tif level == 0 && processing { // done\n\t\t\t\tif i > last {\n\t\t\t\t\tparams = append(params, strings.TrimSpace(sig[last:i]))\n\t\t\t\t}\n\t\t\t\treturn params\n\t\t\t}\n\t\tcase ',':\n\t\t\tif level == 1 && processing {\n\t\t\t\tparams = append(params, strings.TrimSpace(sig[last:i]))\n\t\t\t\tlast = i + 1\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/completion/util.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// exprAtPos returns the index of the expression containing pos.\nfunc exprAtPos(pos token.Pos, args []ast.Expr) int {\n\tfor i, expr := range args {\n\t\tif expr.Pos() <= pos && pos <= expr.End() {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn len(args)\n}\n\n// eachField invokes fn for each field that can be selected from a\n// value of type T.\nfunc eachField(T types.Type, fn func(*types.Var)) {\n\t// TODO(adonovan): this algorithm doesn't exclude ambiguous\n\t// selections that match more than one field/method.\n\t// types.NewSelectionSet should do that for us.\n\n\t// for termination on recursive types\n\tvar seen typeutil.Map\n\n\tvar visit func(T types.Type)\n\tvisit = func(T types.Type) {\n\t\t// T may be a Struct, optionally Named, with an optional\n\t\t// Pointer (with optional Aliases at every step!):\n\t\t// Consider: type T *struct{ f int }; _ = T(nil).f\n\t\tif T, ok := typeparams.Deref(T).Underlying().(*types.Struct); ok {\n\t\t\tif seen.At(T) != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor f := range T.Fields() {\n\t\t\t\tfn(f)\n\t\t\t\tif f.Anonymous() {\n\t\t\t\t\tseen.Set(T, true)\n\t\t\t\t\tvisit(f.Type())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvisit(T)\n}\n\n// typeIsValid reports whether typ doesn't contain any Invalid types.\nfunc typeIsValid(typ types.Type) bool {\n\t// Check named types separately, because we don't want\n\t// to call Underlying() on them to avoid problems with recursive types.\n\tif _, ok := types.Unalias(typ).(*types.Named); ok {\n\t\treturn true\n\t}\n\n\tswitch typ := typ.Underlying().(type) {\n\tcase *types.Basic:\n\t\treturn typ.Kind() != types.Invalid\n\tcase *types.Array:\n\t\treturn typeIsValid(typ.Elem())\n\tcase *types.Slice:\n\t\treturn typeIsValid(typ.Elem())\n\tcase *types.Pointer:\n\t\treturn typeIsValid(typ.Elem())\n\tcase *types.Map:\n\t\treturn typeIsValid(typ.Key()) && typeIsValid(typ.Elem())\n\tcase *types.Chan:\n\t\treturn typeIsValid(typ.Elem())\n\tcase *types.Signature:\n\t\treturn typeIsValid(typ.Params()) && typeIsValid(typ.Results())\n\tcase *types.Tuple:\n\t\tfor v := range typ.Variables() {\n\t\t\tif !typeIsValid(v.Type()) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *types.Struct, *types.Interface:\n\t\t// Don't bother checking structs, interfaces for validity.\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// resolveInvalid traverses the node of the AST that defines the scope\n// containing the declaration of obj, and attempts to find a user-friendly\n// name for its invalid type. The resulting Object and its Type are fake.\nfunc resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info *types.Info) types.Object {\n\tvar resultExpr ast.Expr\n\tast.Inspect(node, func(node ast.Node) bool {\n\t\tswitch n := node.(type) {\n\t\tcase *ast.ValueSpec:\n\t\t\tfor _, name := range n.Names {\n\t\t\t\tif info.Defs[name] == obj {\n\t\t\t\t\tresultExpr = n.Type\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\tcase *ast.Field: // This case handles parameters and results of a FuncDecl or FuncLit.\n\t\t\tfor _, name := range n.Names {\n\t\t\t\tif info.Defs[name] == obj {\n\t\t\t\t\tresultExpr = n.Type\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\tdefault:\n\t\t\treturn true\n\t\t}\n\t})\n\t// Construct a fake type for the object and return a fake object with this type.\n\ttypename := golang.FormatNode(fset, resultExpr)\n\ttyp := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)\n\tv := types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)\n\tv.SetKind(types.PackageVar)\n\treturn v\n}\n\n// TODO(adonovan): inline these.\nfunc isVar(obj types.Object) bool      { return is[*types.Var](obj) }\nfunc isTypeName(obj types.Object) bool { return is[*types.TypeName](obj) }\nfunc isFunc(obj types.Object) bool     { return is[*types.Func](obj) }\nfunc isPkgName(obj types.Object) bool  { return is[*types.PkgName](obj) }\n\n// isPointer reports whether T is a Pointer, or an alias of one.\n// It returns false for a Named type whose Underlying is a Pointer.\n//\n// TODO(adonovan): shouldn't this use CoreType(T)?\nfunc isPointer(T types.Type) bool { return is[*types.Pointer](types.Unalias(T)) }\n\n// isEmptyInterface whether T is a (possibly Named or Alias) empty interface\n// type, such that every type is assignable to T.\n//\n// isEmptyInterface returns false for type parameters, since they have\n// different assignability rules.\nfunc isEmptyInterface(T types.Type) bool {\n\tif _, ok := T.(*types.TypeParam); ok {\n\t\treturn false\n\t}\n\tintf, _ := T.Underlying().(*types.Interface)\n\treturn intf != nil && intf.Empty()\n}\n\nfunc isUntyped(T types.Type) bool {\n\tif basic, ok := types.Unalias(T).(*types.Basic); ok {\n\t\treturn basic.Info()&types.IsUntyped > 0\n\t}\n\treturn false\n}\n\nfunc deslice(T types.Type) types.Type {\n\tif slice, ok := T.Underlying().(*types.Slice); ok {\n\t\treturn slice.Elem()\n\t}\n\treturn nil\n}\n\n// enclosingSelector returns the enclosing *ast.SelectorExpr when pos is in the\n// selector.\nfunc enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {\n\tif len(path) == 0 {\n\t\treturn nil\n\t}\n\n\tif sel, ok := path[0].(*ast.SelectorExpr); ok {\n\t\treturn sel\n\t}\n\n\t// TODO(adonovan): consider ast.ParenExpr (e.g. (x).name)\n\tif _, ok := path[0].(*ast.Ident); ok && len(path) > 1 {\n\t\tif sel, ok := path[1].(*ast.SelectorExpr); ok && pos >= sel.Sel.Pos() {\n\t\t\treturn sel\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// enclosingDeclLHS returns LHS idents from containing value spec or\n// assign statement.\nfunc enclosingDeclLHS(path []ast.Node) []*ast.Ident {\n\tfor _, n := range path {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.ValueSpec:\n\t\t\treturn n.Names\n\t\tcase *ast.AssignStmt:\n\t\t\tids := make([]*ast.Ident, 0, len(n.Lhs))\n\t\t\tfor _, e := range n.Lhs {\n\t\t\t\tif id, ok := e.(*ast.Ident); ok {\n\t\t\t\t\tids = append(ids, id)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ids\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// exprObj returns the types.Object associated with the *ast.Ident or\n// *ast.SelectorExpr e.\nfunc exprObj(info *types.Info, e ast.Expr) types.Object {\n\tvar ident *ast.Ident\n\tswitch expr := e.(type) {\n\tcase *ast.Ident:\n\t\tident = expr\n\tcase *ast.SelectorExpr:\n\t\tident = expr.Sel\n\tdefault:\n\t\treturn nil\n\t}\n\n\treturn info.ObjectOf(ident)\n}\n\n// typeConversion returns the type being converted to if call is a type\n// conversion expression.\nfunc typeConversion(call *ast.CallExpr, info *types.Info) types.Type {\n\t// Type conversion (e.g. \"float64(foo)\").\n\tif fun, _ := exprObj(info, call.Fun).(*types.TypeName); fun != nil {\n\t\treturn fun.Type()\n\t}\n\n\treturn nil\n}\n\n// fieldsAccessible returns whether s has at least one field accessible by p.\nfunc fieldsAccessible(s *types.Struct, p *types.Package) bool {\n\tfor f := range s.Fields() {\n\t\tif f.Exported() || f.Pkg() == p {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// prevStmt returns the statement that precedes the statement containing pos.\n// For example:\n//\n//\tfoo := 1\n//\tbar(1 + 2<>)\n//\n// If \"<>\" is pos, prevStmt returns \"foo := 1\"\nfunc prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {\n\tvar blockLines []ast.Stmt\n\tfor i := 0; i < len(path) && blockLines == nil; i++ {\n\t\tswitch n := path[i].(type) {\n\t\tcase *ast.BlockStmt:\n\t\t\tblockLines = n.List\n\t\tcase *ast.CommClause:\n\t\t\tblockLines = n.Body\n\t\tcase *ast.CaseClause:\n\t\t\tblockLines = n.Body\n\t\t}\n\t}\n\n\tfor i := len(blockLines) - 1; i >= 0; i-- {\n\t\tif blockLines[i].End() < pos {\n\t\t\treturn blockLines[i]\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// isBasicKind returns whether t is a basic type of kind k.\nfunc isBasicKind(t types.Type, k types.BasicInfo) bool {\n\tb, _ := t.Underlying().(*types.Basic)\n\treturn b != nil && b.Info()&k > 0\n}\n\nfunc (c *completer) editText(from, to token.Pos, newText string) ([]protocol.TextEdit, error) {\n\tstart, end, err := safetoken.Offsets(c.pgf.Tok, from, to)\n\tif err != nil {\n\t\treturn nil, err // can't happen: from/to came from c\n\t}\n\treturn protocol.EditsFromDiffEdits(c.mapper, []diff.Edit{{\n\t\tStart: start,\n\t\tEnd:   end,\n\t\tNew:   newText,\n\t}})\n}\n\n// assignableTo is like types.AssignableTo, but returns false if\n// either type is invalid.\nfunc assignableTo(x, to types.Type) bool {\n\tif types.Unalias(x) == types.Typ[types.Invalid] ||\n\t\ttypes.Unalias(to) == types.Typ[types.Invalid] {\n\t\treturn false\n\t}\n\n\treturn types.AssignableTo(x, to)\n}\n\n// convertibleTo is like types.ConvertibleTo, but returns false if\n// either type is invalid.\nfunc convertibleTo(x, to types.Type) bool {\n\tif types.Unalias(x) == types.Typ[types.Invalid] ||\n\t\ttypes.Unalias(to) == types.Typ[types.Invalid] {\n\t\treturn false\n\t}\n\n\treturn types.ConvertibleTo(x, to)\n}\n"
  },
  {
    "path": "gopls/internal/golang/counters.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport \"golang.org/x/telemetry/counter\"\n\n// Proposed counters for evaluating gopls extract, inline, and package rename. These counters\n// increment when the user attempts to perform one of these operations,\n// regardless of whether it succeeds.\nvar (\n\tcountExtractFunction    = counter.New(\"gopls/extract:func\")\n\tcountExtractMethod      = counter.New(\"gopls/extract:method\")\n\tcountExtractVariable    = counter.New(\"gopls/extract:variable\")\n\tcountExtractVariableAll = counter.New(\"gopls/extract:variable-all\")\n\n\tcountInlineCall     = counter.New(\"gopls/inline:call\")\n\tcountInlineVariable = counter.New(\"gopls/inline:variable\")\n\n\tcountRenamePackage = counter.New(\"gopls/renamekind:package\")\n)\n"
  },
  {
    "path": "gopls/internal/golang/definition.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Definition handles the textDocument/definition request for Go files.\nfunc Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\tctx, done := event.Start(ctx, \"golang.Definition\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(start, end) // can't fail\n\n\t// Handle the case where the range is in an import.\n\timportLocations, err := importDefinition(ctx, snapshot, pkg, pgf, start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(importLocations) > 0 {\n\t\treturn importLocations, nil\n\t}\n\n\t// Handle the case where the cursor is in the package name.\n\t// We use \"<= End\" to accept a query immediately after the package name.\n\tif pgf.File != nil && astutil.NodeContains(pgf.File.Name, astutil.RangeOf(start, end)) {\n\t\t// If there's no package documentation, just use current file.\n\t\tdeclFile := pgf\n\t\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\t\tif pgf.File.Name != nil && pgf.File.Doc != nil {\n\t\t\t\tdeclFile = pgf\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tloc, err := declFile.NodeLocation(declFile.File.Name)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn []protocol.Location{loc}, nil\n\t}\n\n\t// Handle the case where the cursor is in a linkname directive.\n\tlocations, err := linknameDefinition(ctx, snapshot, pgf.Mapper, rng)\n\tif !errors.Is(err, ErrNoLinkname) {\n\t\treturn locations, err // may be success or failure\n\t}\n\n\t// Handle the case where the cursor is in an embed directive.\n\tlocations, err = embedDefinition(pgf.Mapper, rng)\n\tif !errors.Is(err, ErrNoEmbed) {\n\t\treturn locations, err // may be success or failure\n\t}\n\n\t// Handle the case where the cursor is in a doc link.\n\tlocations, err = docLinkDefinition(ctx, snapshot, pkg, pgf, start, end)\n\tif !errors.Is(err, errNoCommentReference) {\n\t\treturn locations, err // may be success or failure\n\t}\n\n\t// Handle definition requests for various special kinds of syntax node.\n\tswitch node := cur.Node().(type) {\n\t// Handle the case where the cursor is on a return statement by jumping to the result variables.\n\tcase *ast.ReturnStmt:\n\t\tvar funcType *ast.FuncType\n\t\tfor c := range cur.Enclosing() {\n\t\t\tswitch n := c.Node().(type) {\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tfuncType = n.Type\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tfuncType = n.Type\n\t\t\t}\n\t\t\tif funcType != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t// Inv: funcType != nil, as a return stmt cannot appear outside a function.\n\t\tif funcType.Results == nil {\n\t\t\treturn nil, nil // no result variables\n\t\t}\n\t\tloc, err := pgf.NodeLocation(funcType.Results)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn []protocol.Location{loc}, nil\n\n\tcase *ast.BranchStmt:\n\t\t// Handle the case where the cursor is on a goto, break or continue statement by returning the\n\t\t// location of the label, the closing brace of the relevant block statement, or the\n\t\t// start of the relevant loop, respectively.\n\t\tlabel, isLabeled := pkg.TypesInfo().Uses[node.Label].(*types.Label)\n\t\tswitch node.Tok {\n\t\tcase token.GOTO:\n\t\t\tif !isLabeled {\n\t\t\t\treturn nil, fmt.Errorf(\"undefined label\")\n\t\t\t}\n\t\t\tloc, err := pgf.PosLocation(label.Pos(), label.Pos()+token.Pos(len(label.Name())))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn []protocol.Location{loc}, nil\n\n\t\tcase token.BREAK, token.CONTINUE:\n\t\t\t// Find innermost relevant ancestor for break/continue.\n\t\t\tfor c := range cur.Enclosing() {\n\t\t\t\tif isLabeled {\n\t\t\t\t\tl, ok := c.Parent().Node().(*ast.LabeledStmt)\n\t\t\t\t\tif !(ok && l.Label.Name == label.Name()) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch n := c.Node().(type) {\n\t\t\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\t\t\tvar start, end token.Pos\n\t\t\t\t\tif node.Tok == token.BREAK {\n\t\t\t\t\t\tstart, end = n.End()-token.Pos(len(\"}\")), n.End()\n\t\t\t\t\t} else { // CONTINUE\n\t\t\t\t\t\tstart, end = n.Pos(), n.Pos()+token.Pos(len(\"for\"))\n\t\t\t\t\t}\n\t\t\t\t\tloc, err := pgf.PosLocation(start, end)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t\treturn []protocol.Location{loc}, nil\n\t\t\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\t\t\t\tif node.Tok == token.BREAK {\n\t\t\t\t\t\tloc, err := pgf.PosLocation(n.End()-1, n.End())\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn []protocol.Location{loc}, nil\n\t\t\t\t\t}\n\t\t\t\tcase *ast.FuncDecl, *ast.FuncLit:\n\t\t\t\t\t// bad syntax; avoid jumping outside the current function\n\t\t\t\t\treturn nil, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// The general case: the cursor is on (or near) an identifier.\n\tobjects, err := objectsAt(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\treturn nil, nil\n\t}\n\tobj := objects[0].obj\n\tcur = objects[0].cur // nearby\n\tid, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\t// objectsAt can return a non-Ident (e.g. ImportSpec),\n\t\t// but we dealt with them earlier. Can't happen?\n\t\treturn nil, nil\n\t}\n\n\t// If the query position was an embedded field, we want to jump\n\t// to the field's type definition, not the field's definition (#42254).\n\tif v, ok := obj.(*types.Var); ok && v.Embedded() {\n\t\t// types.Info.Uses contains the embedded field's *types.TypeName.\n\t\tif typeName := pkg.TypesInfo().Uses[id]; typeName != nil {\n\t\t\tobj = typeName\n\t\t}\n\t}\n\n\t// Non-go (e.g. assembly) symbols\n\t//\n\t// When already at the definition of a Go function without\n\t// a body, we jump to its non-Go (C or assembly) definition.\n\tfor _, decl := range pgf.File.Decls {\n\t\tif decl, ok := decl.(*ast.FuncDecl); ok &&\n\t\t\tdecl.Body == nil &&\n\t\t\tastutil.NodeContains(decl.Name, astutil.RangeOf(start, end)) {\n\t\t\treturn nonGoDefinition(ctx, snapshot, pkg, decl.Name.Name)\n\t\t}\n\t}\n\n\t// Finally, map the object position.\n\tloc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn []protocol.Location{loc}, nil\n}\n\n// builtinDecl returns the parsed Go file and node corresponding to a builtin\n// object, which may be a universe object or part of types.Unsafe, as well as\n// its declaring identifier.\nfunc builtinDecl(ctx context.Context, snapshot *cache.Snapshot, obj types.Object) (*parsego.File, *ast.Ident, error) {\n\t// declaringIdent returns the file-level declaration node (as reported by\n\t// ast.Object) and declaring identifier of name using legacy (go/ast) object\n\t// resolution.\n\tdeclaringIdent := func(file *ast.File, name string) (ast.Node, *ast.Ident, error) {\n\t\tastObj := file.Scope.Lookup(name)\n\t\tif astObj == nil {\n\t\t\t// Every built-in should have documentation syntax.\n\t\t\t// However, it is possible to reach this statement by\n\t\t\t// commenting out declarations in {builtin,unsafe}.go.\n\t\t\treturn nil, nil, fmt.Errorf(\"internal error: no object for %s\", name)\n\t\t}\n\t\tdecl, ok := astObj.Decl.(ast.Node)\n\t\tif !ok {\n\t\t\treturn nil, nil, bug.Errorf(\"internal error: no declaration for %s\", obj.Name())\n\t\t}\n\t\tvar ident *ast.Ident\n\t\tswitch node := decl.(type) {\n\t\tcase *ast.Field:\n\t\t\tfor _, id := range node.Names {\n\t\t\t\tif id.Name == name {\n\t\t\t\t\tident = id\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.ValueSpec:\n\t\t\tfor _, id := range node.Names {\n\t\t\t\tif id.Name == name {\n\t\t\t\t\tident = id\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.TypeSpec:\n\t\t\tident = node.Name\n\t\tcase *ast.Ident:\n\t\t\tident = node\n\t\tcase *ast.FuncDecl:\n\t\t\tident = node.Name\n\t\tcase *ast.ImportSpec, *ast.LabeledStmt, *ast.AssignStmt:\n\t\t\t// Not reachable for imported objects.\n\t\tdefault:\n\t\t\treturn nil, nil, bug.Errorf(\"internal error: unexpected decl type %T\", decl)\n\t\t}\n\t\tif ident == nil {\n\t\t\treturn nil, nil, bug.Errorf(\"internal error: no declaring identifier for %s\", obj.Name())\n\t\t}\n\t\treturn decl, ident, nil\n\t}\n\n\tvar (\n\t\tpgf   *parsego.File\n\t\tident *ast.Ident\n\t\terr   error\n\t)\n\tif obj.Pkg() == types.Unsafe {\n\t\t// package \"unsafe\":\n\t\t// parse $GOROOT/src/unsafe/unsafe.go\n\t\t//\n\t\t// (Strictly, we shouldn't assume that the ID of a std\n\t\t// package is its PkgPath, but no Bazel+gopackagesdriver\n\t\t// users have complained about this yet.)\n\t\tunsafe := snapshot.Metadata(\"unsafe\")\n\t\tif unsafe == nil {\n\t\t\t// If the type checker somehow resolved 'unsafe', we must have metadata\n\t\t\t// for it.\n\t\t\treturn nil, nil, bug.Errorf(\"no metadata for package 'unsafe'\")\n\t\t}\n\t\turi := unsafe.GoFiles[0]\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\t// TODO(rfindley): treat unsafe symmetrically with the builtin file. Either\n\t\t// pre-parse them both, or look up metadata for both.\n\t\tpgf, err = snapshot.ParseGo(ctx, fh, parsego.Full&^parser.SkipObjectResolution)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\t_, ident, err = declaringIdent(pgf.File, obj.Name())\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t} else {\n\t\t// pseudo-package \"builtin\":\n\t\t// use parsed $GOROOT/src/builtin/builtin.go\n\t\tpgf, err = snapshot.BuiltinFile(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tif obj.Parent() == types.Universe {\n\t\t\t// built-in function or type\n\t\t\t_, ident, err = declaringIdent(pgf.File, obj.Name())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t} else if obj.Name() == \"Error\" {\n\t\t\t// error.Error method\n\t\t\tdecl, _, err := declaringIdent(pgf.File, \"error\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tfield := decl.(*ast.TypeSpec).Type.(*ast.InterfaceType).Methods.List[0]\n\t\t\tident = field.Names[0]\n\t\t} else {\n\t\t\treturn nil, nil, bug.Errorf(\"unknown built-in %v\", obj)\n\t\t}\n\t}\n\t_ = ident.Name // ident != nil\n\n\treturn pgf, ident, nil\n}\n\n// importDefinition returns locations defining a package referenced by the\n// import spec containing pos.\n//\n// If pos is not inside an import spec, it returns nil, nil.\nfunc importDefinition(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) ([]protocol.Location, error) {\n\tvar imp *ast.ImportSpec\n\tfor _, spec := range pgf.File.Imports {\n\t\t// We use \"<= End\" to accept a query immediately after an ImportSpec.\n\t\tif astutil.NodeContains(spec.Path, astutil.RangeOf(start, end)) {\n\t\t\timp = spec\n\t\t}\n\t}\n\tif imp == nil {\n\t\treturn nil, nil\n\t}\n\n\timportPath := metadata.UnquoteImportPath(imp)\n\timpID := pkg.Metadata().DepsByImpPath[importPath]\n\tif impID == \"\" {\n\t\treturn nil, fmt.Errorf(\"failed to resolve import %q\", importPath)\n\t}\n\timpMetadata := s.Metadata(impID)\n\tif impMetadata == nil {\n\t\treturn nil, fmt.Errorf(\"missing information for package %q\", impID)\n\t}\n\n\tvar locs []protocol.Location\n\tfor _, f := range impMetadata.CompiledGoFiles {\n\t\tfh, err := s.ReadFile(ctx, f)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tpgf, err := s.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tloc, err := pgf.NodeLocation(pgf.File)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlocs = append(locs, loc)\n\t}\n\n\tif len(locs) == 0 {\n\t\treturn nil, fmt.Errorf(\"package %q has no readable files\", impID) // incl. unsafe\n\t}\n\n\treturn locs, nil\n}\n\n// ObjectLocation returns the location of the declaring identifier of obj.\n// If valid, obj.Pos() must be mapped by fset.\n// It may need to read the declaring file content, hence (ctx, s).\n// It supports the builtin and unsafe pseudo-packages.\nfunc ObjectLocation(ctx context.Context, fset *token.FileSet, snapshot *cache.Snapshot, obj types.Object) (protocol.Location, error) {\n\tif isBuiltin(obj) {\n\t\t// Returns fake source declaration in {builtin,unsafe}.go.\n\t\tpgf, ident, err := builtinDecl(ctx, snapshot, obj)\n\t\tif err != nil {\n\t\t\treturn protocol.Location{}, err\n\t\t}\n\t\treturn pgf.NodeLocation(ident)\n\t}\n\n\t// An imported Go package has a package-local, unqualified name.\n\t// When the name matches the imported package name, there is usually\n\t// no identifier in the import spec with the local package name.\n\t//\n\t// For example:\n\t// \timport \"go/‸ast\" \t// name \"ast\" matches package name\n\t// \timport ‸a \"go/ast\"  \t// name \"a\" does not match package name\n\t//\n\t// When the identifier does not appear in the source, have the range\n\t// of the object be the import path, including quotes.\n\t//\n\t// But this is just a heuristic, and it's wrong in this case:\n\t// \timport ‸ast \"go/ast\"  \t// name matches (spurious result is `ast \"go/`)\n\tnameLen := len(obj.Name())\n\tif pkgName, ok := obj.(*types.PkgName); ok && pkgName.Imported().Name() == pkgName.Name() {\n\t\tnameLen = len(pkgName.Imported().Path()) + len(`\"\"`)\n\t}\n\n\tvar (\n\t\tstart = obj.Pos()\n\t\tend   = start + token.Pos(nameLen)\n\t)\n\tfile := fset.File(start)\n\tif file == nil {\n\t\treturn protocol.Location{}, bug.Errorf(\"FileSet does not map Pos %d\", start)\n\t}\n\turi := protocol.URIFromPath(file.Name())\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\t// TODO(rfindley): avoid the duplicate column mapping here, by associating a\n\t// column mapper with each file handle.\n\tm := protocol.NewMapper(fh.URI(), content)\n\treturn m.PosLocation(file, start, end)\n}\n\n// nonGoDefinition returns the location of the definition of a non-Go symbol.\n// Only assembly is supported for now.\nfunc nonGoDefinition(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, symbol string) ([]protocol.Location, error) {\n\t// Examples:\n\t//   TEXT runtime·foo(SB)\n\t//   TEXT ·foo<ABIInternal>(SB)\n\t// TODO(adonovan): why does ^TEXT cause it not to match?\n\tpattern := regexp.MustCompile(\"TEXT\\\\b.*·(\" + regexp.QuoteMeta(symbol) + \")[\\\\(<]\")\n\n\tfor _, uri := range pkg.Metadata().OtherFiles {\n\t\tif strings.HasSuffix(uri.Path(), \".s\") {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err // context cancelled\n\t\t\t}\n\t\t\tcontent, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\tcontinue // can't read file\n\t\t\t}\n\t\t\tif match := pattern.FindSubmatchIndex(content); match != nil {\n\t\t\t\tmapper := protocol.NewMapper(uri, content)\n\t\t\t\tloc, err := mapper.OffsetLocation(match[2], match[3])\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\treturn []protocol.Location{loc}, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(adonovan): try C files\n\n\t// This may be reached for functions that aren't implemented\n\t// in assembly (e.g. compiler intrinsics like getg).\n\treturn nil, fmt.Errorf(\"can't find non-Go definition of %s\", symbol)\n}\n"
  },
  {
    "path": "gopls/internal/golang/diagnostics.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n)\n\n// DiagnoseFile returns pull-based diagnostics for the given file.\nfunc DiagnoseFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) ([]*cache.Diagnostic, error) {\n\tmp, err := snapshot.NarrowestMetadataForFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// TODO(rfindley): consider analysing the package concurrently to package\n\t// diagnostics.\n\n\t// Get package (list/parse/type check) diagnostics.\n\tpkgDiags, err := snapshot.PackageDiagnostics(ctx, mp.ID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdiags := pkgDiags[uri]\n\n\t// Get analysis diagnostics.\n\tpkgAnalysisDiags, err := snapshot.Analyze(ctx, map[PackageID]*metadata.Package{mp.ID: mp}, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tanalysisDiags := moremaps.Group(pkgAnalysisDiags, byURI)[uri]\n\n\t// Return the merged set of file diagnostics, combining type error analyses\n\t// with type error diagnostics.\n\treturn CombineDiagnostics(diags, analysisDiags), nil\n}\n\n// Analyze reports go/analysis-framework diagnostics in the specified package.\n//\n// If the provided tracker is non-nil, it may be used to provide notifications\n// of the ongoing analysis pass.\n//\n// TODO(rfindley): merge this with snapshot.Analyze.\nfunc Analyze(ctx context.Context, snapshot *cache.Snapshot, pkgIDs map[PackageID]*metadata.Package, tracker *progress.Tracker) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\t// Exit early if the context has been canceled. This also protects us\n\t// from a race on Options, see golang/go#36699.\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\tanalysisDiagnostics, err := snapshot.Analyze(ctx, pkgIDs, tracker)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn moremaps.Group(analysisDiagnostics, byURI), nil\n}\n\n// byURI is used for grouping diagnostics.\nfunc byURI(d *cache.Diagnostic) protocol.DocumentURI { return d.URI }\n\n// CombineDiagnostics combines and filters list/parse/type diagnostics from\n// tdiags with the analysis adiags, returning the resulting combined set.\n//\n// Type-error analyzers produce diagnostics that are redundant with type\n// checker diagnostics, but more detailed (e.g. fixes). Rather than report two\n// diagnostics for the same problem, we combine them by augmenting the\n// type-checker diagnostic and discarding the analyzer diagnostic.\n//\n// If an analysis diagnostic has the same range and message as a\n// list/parse/type diagnostic, the suggested fix information (et al) of the\n// latter is merged into a copy of the former. This handles the case where a\n// type-error analyzer suggests a fix to a type error, and avoids duplication.\n//\n// The arguments are not modified.\nfunc CombineDiagnostics(tdiags []*cache.Diagnostic, adiags []*cache.Diagnostic) []*cache.Diagnostic {\n\t// Build index of (list+parse+)type errors.\n\ttype key struct {\n\t\tRange   protocol.Range\n\t\tmessage string\n\t}\n\tcombined := make([]*cache.Diagnostic, len(tdiags))\n\tindex := make(map[key]int) // maps (Range,Message) to index in tdiags slice\n\tfor i, diag := range tdiags {\n\t\tindex[key{diag.Range, diag.Message}] = i\n\t\tcombined[i] = diag\n\t}\n\n\t// Filter out analysis diagnostics that match type errors,\n\t// retaining their suggested fix (etc) fields.\n\tfor _, diag := range adiags {\n\t\tif i, ok := index[key{diag.Range, diag.Message}]; ok {\n\t\t\tcopy := *tdiags[i]\n\t\t\tcopy.SuggestedFixes = diag.SuggestedFixes\n\t\t\tcopy.Tags = diag.Tags\n\t\t\tcombined[i] = &copy\n\t\t\tcontinue\n\t\t}\n\t\tcombined = append(combined, diag)\n\t}\n\treturn combined\n}\n"
  },
  {
    "path": "gopls/internal/golang/embeddirective.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// ErrNoEmbed is returned by EmbedDefinition when no embed\n// directive is found at a particular position.\n// As such it indicates that other definitions could be worth checking.\nvar ErrNoEmbed = errors.New(\"no embed directive found\")\n\n// embedDefinition finds a file matching the embed directive at pos in the mapped file.\n// If there is no embed directive at pos, returns [ErrNoEmbed].\n// If multiple files match the embed pattern, one is picked at random.\nfunc embedDefinition(m *protocol.Mapper, rng protocol.Range) ([]protocol.Location, error) {\n\tpattern, _ := parseEmbedDirective(m, rng)\n\tif pattern == \"\" {\n\t\treturn nil, ErrNoEmbed\n\t}\n\tpattern = filepath.FromSlash(pattern) // Match requires OS separators\n\n\terrFound := errors.New(\"found\")\n\n\t// Find the first matching file.\n\tvar match string\n\tdir := m.URI.DirPath()\n\terr := filepath.WalkDir(dir, func(abs string, d fs.DirEntry, e error) error {\n\t\tif e != nil {\n\t\t\treturn e\n\t\t}\n\t\trel, err := filepath.Rel(dir, abs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tok, err := filepath.Match(pattern, rel)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif ok && !d.IsDir() {\n\t\t\tmatch = abs\n\t\t\treturn errFound\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil && !errors.Is(err, errFound) {\n\t\treturn nil, err // bad pattern or I/O error\n\t}\n\tif match == \"\" {\n\t\treturn nil, fmt.Errorf(\"%q does not match any files in %q\", pattern, dir)\n\t}\n\treturn []protocol.Location{{URI: protocol.URIFromPath(match)}}, nil\n}\n\n// parseEmbedDirective attempts to parse a go:embed directive argument that\n// contains the given range.\n// If successful it returns the directive argument (a UNIX-style glob\n// pattern) and its range, else zero values are returned.\nfunc parseEmbedDirective(m *protocol.Mapper, rng protocol.Range) (string, protocol.Range) {\n\tif rng.Start.Line != rng.End.Line {\n\t\treturn \"\", protocol.Range{}\n\t}\n\n\tlineStart, err := m.PositionOffset(protocol.Position{Line: rng.Start.Line, Character: 0})\n\tif err != nil {\n\t\treturn \"\", protocol.Range{}\n\t}\n\tlineEnd, err := m.PositionOffset(protocol.Position{Line: rng.Start.Line + 1, Character: 0})\n\tif err != nil {\n\t\treturn \"\", protocol.Range{}\n\t}\n\n\ttext := string(m.Content[lineStart:lineEnd])\n\tif !strings.HasPrefix(text, \"//go:embed\") {\n\t\treturn \"\", protocol.Range{}\n\t}\n\ttext = text[len(\"//go:embed\"):]\n\toffset := lineStart + len(\"//go:embed\")\n\n\t// Find the first pattern in text that covers the offset of the pos we are looking for.\n\tstartOffset, endOffset, err := m.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn \"\", protocol.Range{}\n\t}\n\n\tpatterns, err := parseGoEmbed(text, offset)\n\tif err != nil {\n\t\treturn \"\", protocol.Range{}\n\t}\n\n\tfor _, p := range patterns {\n\t\tif p.startOffset <= startOffset && endOffset <= p.endOffset {\n\t\t\t// Found our match.\n\t\t\trng, err := m.OffsetRange(p.startOffset, p.endOffset)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", protocol.Range{}\n\t\t\t}\n\t\t\treturn p.pattern, rng\n\t\t}\n\t}\n\n\treturn \"\", protocol.Range{}\n}\n\ntype fileEmbed struct {\n\tpattern     string\n\tstartOffset int\n\tendOffset   int\n}\n\n// parseGoEmbed patterns that come after the directive.\n//\n// Copied and adapted from go/build/read.go.\n// Replaced token.Position with start/end offset (including quotes if present).\nfunc parseGoEmbed(args string, offset int) ([]fileEmbed, error) {\n\ttrimBytes := func(n int) {\n\t\toffset += n\n\t\targs = args[n:]\n\t}\n\ttrimSpace := func() {\n\t\ttrim := strings.TrimLeftFunc(args, unicode.IsSpace)\n\t\ttrimBytes(len(args) - len(trim))\n\t}\n\n\tvar list []fileEmbed\n\tfor trimSpace(); args != \"\"; trimSpace() {\n\t\tvar path string\n\t\tpathOffset := offset\n\tSwitch:\n\t\tswitch args[0] {\n\t\tdefault:\n\t\t\ti := len(args)\n\t\t\tfor j, c := range args {\n\t\t\t\tif unicode.IsSpace(c) {\n\t\t\t\t\ti = j\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tpath = args[:i]\n\t\t\ttrimBytes(i)\n\n\t\tcase '`':\n\t\t\tvar ok bool\n\t\t\tpath, _, ok = strings.Cut(args[1:], \"`\")\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid quoted string in //go:embed: %s\", args)\n\t\t\t}\n\t\t\ttrimBytes(1 + len(path) + 1)\n\n\t\tcase '\"':\n\t\t\ti := 1\n\t\t\tfor ; i < len(args); i++ {\n\t\t\t\tif args[i] == '\\\\' {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif args[i] == '\"' {\n\t\t\t\t\tq, err := strconv.Unquote(args[:i+1])\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"invalid quoted string in //go:embed: %s\", args[:i+1])\n\t\t\t\t\t}\n\t\t\t\t\tpath = q\n\t\t\t\t\ttrimBytes(i + 1)\n\t\t\t\t\tbreak Switch\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i >= len(args) {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid quoted string in //go:embed: %s\", args)\n\t\t\t}\n\t\t}\n\n\t\tif args != \"\" {\n\t\t\tr, _ := utf8.DecodeRuneInString(args)\n\t\t\tif !unicode.IsSpace(r) {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid quoted string in //go:embed: %s\", args)\n\t\t\t}\n\t\t}\n\t\tlist = append(list, fileEmbed{\n\t\t\tpattern:     path,\n\t\t\tstartOffset: pathOffset,\n\t\t\tendOffset:   offset,\n\t\t})\n\t}\n\treturn list, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/extract.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// extractVariableOne implements the refactor.extract.{variable,constant} CodeAction command.\nfunc extractVariableOne(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tcountExtractVariable.Inc()\n\treturn extractVariable(pkg, pgf, start, end, false)\n}\n\n// extractVariableAll implements the refactor.extract.{variable,constant}-all CodeAction command.\nfunc extractVariableAll(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tcountExtractVariableAll.Inc()\n\treturn extractVariable(pkg, pgf, start, end, true)\n}\n\n// extractVariable replaces one or all occurrences of a specified\n// expression within the same function with newVar. If 'all' is true,\n// it replaces all occurrences of the same expression; otherwise, it\n// only replaces the selected expression.\n//\n// The new variable/constant is declared as close as possible to the first found expression\n// within the deepest common scope accessible to all candidate occurrences.\nfunc extractVariable(pkg *cache.Package, pgf *parsego.File, start, end token.Pos, all bool) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tvar (\n\t\tfset = pkg.FileSet()\n\t\tinfo = pkg.TypesInfo()\n\t\tfile = pgf.File\n\t)\n\tcurExprs, err := canExtractVariable(info, pgf.Cursor(), start, end, all)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"cannot extract: %v\", err)\n\t}\n\texpr0 := curExprs[0].Node().(ast.Expr)\n\n\t// innermost scope enclosing ith expression\n\texprScopes := make([]*types.Scope, len(curExprs))\n\tfor i, curExpr := range curExprs {\n\t\texprScopes[i] = info.Scopes[file].Innermost(curExpr.Node().Pos())\n\t}\n\n\thasCollision := func(name string) bool {\n\t\tfor _, scope := range exprScopes {\n\t\t\tif s, _ := scope.LookupParent(name, token.NoPos); s != nil {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\tconstant := info.Types[expr0].Value != nil\n\n\t// Generate name(s) for new declaration.\n\tbaseName := cond(constant, \"newConst\", \"newVar\")\n\tvar lhsNames []string\n\tswitch expr := expr0.(type) {\n\tcase *ast.CallExpr:\n\t\ttup, ok := info.TypeOf(expr).(*types.Tuple)\n\t\tif !ok {\n\t\t\t// conversion or single-valued call:\n\t\t\t// treat it the same as our standard extract variable case.\n\t\t\tname, _ := generateName(0, baseName, hasCollision)\n\t\t\tlhsNames = append(lhsNames, name)\n\n\t\t} else {\n\t\t\t// call with multiple results\n\t\t\tidx := 0\n\t\t\tfor range tup.Len() {\n\t\t\t\t// Generate a unique variable for each result.\n\t\t\t\tvar name string\n\t\t\t\tname, idx = generateName(idx, baseName, hasCollision)\n\t\t\t\tlhsNames = append(lhsNames, name)\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\t// TODO: stricter rules for selectorExpr.\n\t\tname, _ := generateName(0, baseName, hasCollision)\n\t\tlhsNames = append(lhsNames, name)\n\t}\n\n\t// Where all the extractable positions can see variable being declared.\n\tvar commonScope *types.Scope\n\tcounter := make(map[*types.Scope]int)\nOuter:\n\tfor _, scope := range exprScopes {\n\t\tfor s := scope; s != nil; s = s.Parent() {\n\t\t\tcounter[s]++\n\t\t\tif counter[s] == len(exprScopes) {\n\t\t\t\t// A scope whose count is len(scopes) is common to all ancestor paths.\n\t\t\t\t// Stop at the first (innermost) one.\n\t\t\t\tcommonScope = s\n\t\t\t\tbreak Outer\n\t\t\t}\n\t\t}\n\t}\n\n\tvisible := curExprs[0] // Insert newVar inside commonScope before the first occurrence of the expression.\n\tif commonScope != exprScopes[0] {\n\t\t// This means the first expr within function body is not the largest scope,\n\t\t// we need to find the scope immediately follow the common\n\t\t// scope where we will insert the statement before.\n\t\tchild := exprScopes[0]\n\t\tfor p := child; p != nil; p = p.Parent() {\n\t\t\tif p == commonScope {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tchild = p\n\t\t}\n\t\tvisible, _ = pgf.Cursor().FindByPos(child.Pos(), child.End())\n\t}\n\tvariables, err := collectFreeVars(info, file, expr0.Pos(), expr0.End(), expr0)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// TODO: There is a bug here: for a variable declared in a labeled\n\t// switch/for statement it returns the for/switch statement itself\n\t// which produces the below code which is a compiler error. e.g.\n\t//     label:\n\t//         switch r1 := r() { ... break label ... }\n\t// On extracting \"r()\" to a variable\n\t//     label:\n\t//         x := r()\n\t//         switch r1 := x { ... break label ... } // compiler error\n\t//\n\tvar (\n\t\tinsertPos   token.Pos\n\t\tindentation string\n\t\tstmtOK      bool // ok to use \":=\" instead of var/const decl?\n\t)\n\tif funcDecl, _ := cursorutil.FirstEnclosing[*ast.FuncDecl](visible); funcDecl != nil &&\n\t\tastutil.NodeContainsPos(funcDecl.Body, start) {\n\n\t\tbeforePos, err := stmtToInsertVarBefore(visible, variables)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"cannot find location to insert extraction: %v\", err)\n\t\t}\n\t\t// Within function: compute appropriate statement indentation.\n\t\tindent, err := pgf.Indentation(beforePos)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tinsertPos = beforePos\n\t\tindentation = \"\\n\" + indent\n\n\t\t// Currently, we always extract a constant expression\n\t\t// to a const declaration (and logic in CodeAction\n\t\t// assumes that we do so); this is conservative because\n\t\t// it preserves its constant-ness.\n\t\t//\n\t\t// In future, constant expressions used only in\n\t\t// contexts where constant-ness isn't important could\n\t\t// be profitably extracted to a var declaration or :=\n\t\t// statement, especially if the latter is the Init of\n\t\t// an {If,For,Switch}Stmt.\n\t\tstmtOK = !constant\n\t} else {\n\t\t// Outside any statement: insert before the current\n\t\t// top-level declaration, without indentation.\n\t\tfor curDecl := range visible.Enclosing((*ast.FuncDecl)(nil), (*ast.GenDecl)(nil)) {\n\t\t\tinsertPos = curDecl.Node().Pos()\n\t\t}\n\t\tindentation = \"\\n\"\n\t}\n\n\t// Create statement to declare extracted var/const.\n\t//\n\t// TODO(adonovan): beware the const decls are not valid short\n\t// statements, so if fixing #70563 causes\n\t// StmtToInsertVarBefore to evolve to permit declarations in\n\t// the \"pre\" part of an IfStmt, like so:\n\t//   Before:\n\t//\tif cond {\n\t//      } else if «1 + 2» > 0 {\n\t//      }\n\t//   After:\n\t//\tif x := 1 + 2; cond {\n\t//      } else if x > 0 {\n\t//      }\n\t// then it will need to become aware that this is invalid\n\t// for constants.\n\t//\n\t// Conversely, a short var decl stmt is not valid at top level,\n\t// so when we fix #70665, we'll need to use a var decl.\n\tvar newNode ast.Node\n\tif !stmtOK {\n\t\t// var/const x1, ..., xn = expr\n\t\tvar names []*ast.Ident\n\t\tfor _, name := range lhsNames {\n\t\t\tnames = append(names, ast.NewIdent(name))\n\t\t}\n\t\tnewNode = &ast.GenDecl{\n\t\t\tTok: cond(constant, token.CONST, token.VAR),\n\t\t\tSpecs: []ast.Spec{\n\t\t\t\t&ast.ValueSpec{\n\t\t\t\t\tNames:  names,\n\t\t\t\t\tValues: []ast.Expr{expr0},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t} else {\n\t\t// var: x1, ... xn := expr\n\t\tvar lhs []ast.Expr\n\t\tfor _, name := range lhsNames {\n\t\t\tlhs = append(lhs, ast.NewIdent(name))\n\t\t}\n\t\tnewNode = &ast.AssignStmt{\n\t\t\tTok: token.DEFINE,\n\t\t\tLhs: lhs,\n\t\t\tRhs: []ast.Expr{expr0},\n\t\t}\n\t}\n\n\t// Format and indent the declaration.\n\tvar buf bytes.Buffer\n\tif err := format.Node(&buf, fset, newNode); err != nil {\n\t\treturn nil, nil, err\n\t}\n\t// TODO(adonovan): not sound for `...` string literals containing newlines.\n\tassignment := strings.ReplaceAll(buf.String(), \"\\n\", indentation) + indentation\n\ttextEdits := []analysis.TextEdit{{\n\t\tPos:     insertPos,\n\t\tEnd:     insertPos,\n\t\tNewText: []byte(assignment),\n\t}}\n\tfor _, curExpr := range curExprs {\n\t\te := curExpr.Node()\n\t\ttextEdits = append(textEdits, analysis.TextEdit{\n\t\t\tPos:     e.Pos(),\n\t\t\tEnd:     e.End(),\n\t\t\tNewText: []byte(strings.Join(lhsNames, \", \")),\n\t\t})\n\t}\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: textEdits,\n\t}, nil\n}\n\n// stmtToInsertVarBefore returns the ast.Stmt before which we can safely insert a new variable,\n// and ensures that the new declaration is inserted at a point where all free variables are declared before.\n// Some examples:\n//\n// Basic Example:\n//\n//\tz := 1\n//\ty := z + x\n//\n// If x is undeclared, then this function would return `y := z + x`, so that we\n// can insert `x := ` on the line before `y := z + x`.\n//\n// valid IfStmt example:\n//\n//\tif z == 1 {\n//\t} else if z == y {}\n//\n// If y is undeclared, then this function would return `if z == 1 {`, because we cannot\n// insert a statement between an if and an else if statement. As a result, we need to find\n// the top of the if chain to insert `y := ` before.\n//\n// invalid IfStmt example:\n//\n//\tif x := 1; true {\n//\t} else if y := x + 1; true { //apply refactor.extract.variable to x\n//\t}\n//\n// `x` is a free variable defined in the IfStmt, we should not insert\n// the extracted expression outside the IfStmt scope, instead, return an error.\nfunc stmtToInsertVarBefore(cur inspector.Cursor, variables []*variable) (token.Pos, error) {\n\t// Walk up to enclosing statement.\n\t{\n\t\tvar curStmt inspector.Cursor\n\t\tfor cur := range cur.Enclosing() {\n\t\t\tif is[ast.Stmt](cur.Node()) {\n\t\t\t\tcurStmt = cur\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !curStmt.Valid() {\n\t\t\treturn 0, fmt.Errorf(\"no enclosing statement\")\n\t\t}\n\t\tcur = curStmt\n\t}\n\n\t// hasFreeVar reports if any free variables is defined inside stmt (which may be nil).\n\t// If true, indicates that the insertion point will sit before the variable declaration.\n\thasFreeVar := func(stmt ast.Stmt) bool {\n\t\tif stmt == nil {\n\t\t\treturn false\n\t\t}\n\t\tfor _, v := range variables {\n\t\t\tif astutil.NodeContainsPos(stmt, v.obj.Pos()) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// baseIfStmt walks up the if/else-if chain until we get to\n\t// the top of the current if chain.\n\tbaseIfStmt := func(curIf inspector.Cursor) (token.Pos, error) {\n\t\tfor curIf.ParentEdgeKind() == edge.IfStmt_Else {\n\t\t\tcurIf = curIf.Parent()\n\t\t\tif hasFreeVar(curIf.Node().(*ast.IfStmt).Init) {\n\t\t\t\treturn 0, fmt.Errorf(\"else-if's init has free variable\")\n\t\t\t}\n\t\t}\n\t\treturn curIf.Node().Pos(), nil\n\t}\n\n\tstmt := cur.Node()\n\tswitch stmt := stmt.(type) {\n\tcase *ast.IfStmt:\n\t\tif hasFreeVar(stmt.Init) {\n\t\t\treturn 0, fmt.Errorf(\"if statement's init has free variable\")\n\t\t}\n\t\t// stmt is inside of the if declaration.\n\t\t// We need to check if we are in an else-if stmt and\n\t\t// get the base if statement.\n\t\treturn baseIfStmt(cur)\n\n\tcase *ast.CaseClause:\n\t\tfor curSwitch := range cur.Enclosing((*ast.SwitchStmt)(nil), (*ast.TypeSwitchStmt)(nil)) {\n\t\t\tswtch := curSwitch.Node()\n\t\t\tvar init ast.Stmt\n\t\t\tswitch swtch := swtch.(type) {\n\t\t\tcase *ast.SwitchStmt:\n\t\t\t\tinit = swtch.Init\n\t\t\tcase *ast.TypeSwitchStmt:\n\t\t\t\tinit = swtch.Init\n\t\t\t}\n\t\t\tif hasFreeVar(init) {\n\t\t\t\treturn 0, fmt.Errorf(\"switch's init has free variable\")\n\t\t\t}\n\t\t\treturn swtch.Pos(), nil\n\t\t}\n\t}\n\n\t// Check if the enclosing statement is inside another node.\n\tswitch parent := cur.Parent().Node().(type) {\n\tcase *ast.IfStmt:\n\t\tif hasFreeVar(parent.Init) {\n\t\t\treturn 0, fmt.Errorf(\"if-statement's init has free variable\")\n\t\t}\n\t\treturn baseIfStmt(cur.Parent())\n\n\tcase *ast.ForStmt:\n\t\tswitch cur.Node() {\n\t\tcase parent.Init, parent.Post:\n\t\t\treturn parent.Pos(), nil\n\t\t}\n\n\tcase *ast.SwitchStmt:\n\t\tif hasFreeVar(parent.Init) {\n\t\t\treturn 0, fmt.Errorf(\"switch's init has free variable\")\n\t\t}\n\t\treturn parent.Pos(), nil\n\n\tcase *ast.TypeSwitchStmt:\n\t\tif hasFreeVar(parent.Init) {\n\t\t\treturn 0, fmt.Errorf(\"switch's init has free variable\")\n\t\t}\n\t\treturn parent.Pos(), nil\n\t}\n\treturn stmt.Pos(), nil\n}\n\n// canExtractVariable reports whether the code in the given range can\n// be extracted to a variable (or constant). It returns (cursors for)\n// the selected expression or, if 'all', all structurally equivalent\n// expressions within the same function body, in lexical order.\nfunc canExtractVariable(info *types.Info, curFile inspector.Cursor, start, end token.Pos, all bool) ([]inspector.Cursor, error) {\n\tif start == end {\n\t\treturn nil, fmt.Errorf(\"empty selection\")\n\t}\n\n\t_, curStart, curEnd, err := astutil.Select(curFile, start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\texpr, ok := curStart.Node().(ast.Expr)\n\tif !ok || curEnd != curStart {\n\t\treturn nil, fmt.Errorf(\"selection is not an expression\")\n\t}\n\tif imp, _ := cursorutil.FirstEnclosing[*ast.ImportSpec](curStart); imp != nil {\n\t\treturn nil, fmt.Errorf(\"cannot extract variable or constant in an import block\")\n\t}\n\tif tv, ok := info.Types[expr]; !ok || !tv.IsValue() || tv.Type == nil || tv.HasOk() {\n\t\t// e.g. type, builtin, x.(type), 2-valued m[k], or ill-typed\n\t\treturn nil, fmt.Errorf(\"selection is not a single-valued expression\")\n\t}\n\n\tvar curExprs []inspector.Cursor\n\tif !all {\n\t\tcurExprs = append(curExprs, curStart)\n\t} else if funcDecl, curFuncDecl := cursorutil.FirstEnclosing[*ast.FuncDecl](curStart); funcDecl != nil && funcDecl.Body != nil {\n\t\t// Find all expressions in the same function body that\n\t\t// are equal to the selected expression.\n\t\tfor cur := range curFuncDecl.ChildAt(edge.FuncDecl_Body, -1).Preorder() {\n\t\t\tif e, ok := cur.Node().(ast.Expr); ok {\n\t\t\t\tif astutil.Equal(e, expr, func(x, y *ast.Ident) bool {\n\t\t\t\t\txobj, yobj := info.ObjectOf(x), info.ObjectOf(y)\n\t\t\t\t\t// The two identifiers must resolve to the same object,\n\t\t\t\t\t// or to a declaration within the candidate expression.\n\t\t\t\t\t// (This allows two copies of \"func (x int) { print(x) }\"\n\t\t\t\t\t// to match.)\n\t\t\t\t\tif xobj != nil && astutil.NodeContainsPos(e, xobj.Pos()) &&\n\t\t\t\t\t\tyobj != nil && astutil.NodeContainsPos(expr, yobj.Pos()) {\n\t\t\t\t\t\treturn x.Name == y.Name\n\t\t\t\t\t}\n\t\t\t\t\t// Use info.Uses to avoid including declaration, for example,\n\t\t\t\t\t// when extractnig x:\n\t\t\t\t\t//\n\t\t\t\t\t//   x := 1 // should not include x\n\t\t\t\t\t//   y := x // include x\n\t\t\t\t\t//   z := x // include x\n\t\t\t\t\txuse := info.Uses[x]\n\t\t\t\t\treturn xuse != nil && xuse == info.Uses[y]\n\t\t\t\t}) {\n\t\t\t\t\tcurExprs = append(curExprs, cur)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn nil, fmt.Errorf(\"node %T is not inside a function\", expr)\n\t}\n\n\t// Disallow any expr that sits in lhs of an AssignStmt or ValueSpec for now.\n\t//\n\t// TODO(golang/go#70784): In such cases, exprs are operated in \"variable\" mode (L-value mode in C).\n\t// In contrast, exprs in the RHS operate in \"value\" mode (R-value mode in C).\n\t// L-value mode refers to exprs that represent storage locations,\n\t// while R-value mode refers to exprs that represent values.\n\t// There are a number of expressions that may have L-value mode, given by:\n\t//\n\t//   lvalue = ident                -- Ident such that info.Uses[id] is a *Var\n\t//          | '(' lvalue ') '      -- ParenExpr\n\t//          | lvalue '[' expr ']'  -- IndexExpr\n\t//          | lvalue '.' ident     -- SelectorExpr.\n\t//\n\t// For example:\n\t//\n\t//   type foo struct {\n\t//       bar int\n\t//   }\n\t//   f := foo{bar: 1}\n\t//   x := f.bar + 1 // f.bar operates in \"value\" mode.\n\t//   f.bar = 2      // f.bar operates in \"variable\" mode.\n\t//\n\t// When extracting exprs in variable mode, we must be cautious. Any such extraction\n\t// may require capturing the address of the expression and replacing its uses with dereferenced access.\n\t// The type checker records this information in info.Types[id].{IsValue,Addressable}().\n\t// The correct result should be:\n\t//\n\t//   newVar := &f.bar\n\t//   x := *newVar + 1\n\t//   *newVar = 2\n\tfor _, curExpr := range curExprs {\n\t\tswitch curExpr.ParentEdgeKind() {\n\t\tcase edge.AssignStmt_Lhs:\n\t\t\treturn nil, fmt.Errorf(\"node %T is in LHS of an AssignStmt\", expr)\n\t\tcase edge.ValueSpec_Names:\n\t\t\treturn nil, fmt.Errorf(\"node %T is in LHS of a ValueSpec\", expr)\n\t\t}\n\t}\n\n\treturn curExprs, nil\n}\n\n// freshName returns an identifier based on prefix (perhaps with a\n// numeric suffix) that is not in scope at the specified position\n// within the file. It returns the next numeric suffix to use.\nfunc freshName(info *types.Info, file *ast.File, pos token.Pos, prefix string, idx int) (string, int) {\n\tscope := info.Scopes[file].Innermost(pos)\n\treturn generateName(idx, prefix, func(name string) bool {\n\t\tobj, _ := scope.LookupParent(name, pos)\n\t\treturn obj != nil\n\t})\n}\n\n// freshNameOutsideRange is like [freshName], but ignores names\n// declared between start and end for the purposes of detecting conflicts.\n//\n// This is used for function extraction, where [start, end) will be extracted\n// to a new scope.\nfunc freshNameOutsideRange(info *types.Info, file *ast.File, pos, start, end token.Pos, prefix string, idx int) (string, int) {\n\tscope := info.Scopes[file].Innermost(pos)\n\treturn generateName(idx, prefix, func(name string) bool {\n\t\t// Only report a collision if the object declaration\n\t\t// was outside the extracted range.\n\t\tfor scope != nil {\n\t\t\tobj, declScope := scope.LookupParent(name, pos)\n\t\t\tif obj == nil {\n\t\t\t\treturn false // undeclared\n\t\t\t}\n\t\t\tif !(start <= obj.Pos() && obj.Pos() < end) {\n\t\t\t\treturn true // declared outside ignored range\n\t\t\t}\n\t\t\tscope = declScope.Parent()\n\t\t}\n\t\treturn false\n\t})\n}\n\nfunc generateName(idx int, prefix string, hasCollision func(string) bool) (string, int) {\n\tname := prefix\n\tif idx != 0 {\n\t\tname += fmt.Sprintf(\"%d\", idx)\n\t}\n\tfor hasCollision(name) {\n\t\tidx++\n\t\tname = fmt.Sprintf(\"%v%d\", prefix, idx)\n\t}\n\treturn name, idx + 1\n}\n\n// returnVariable keeps track of the information we need to properly introduce a new variable\n// that we will return in the extracted function.\ntype returnVariable struct {\n\t// name is the identifier that is used on the left-hand side of the call to\n\t// the extracted function.\n\tname *ast.Ident\n\t// decl is the declaration of the variable. It is used in the type signature of the\n\t// extracted function and for variable declarations.\n\tdecl *ast.Field\n\t// zeroVal is the \"zero value\" of the type of the variable. It is used in a return\n\t// statement in the extracted function.\n\tzeroVal ast.Expr\n}\n\n// extractMethod refactors the selected block of code into a new method.\nfunc extractMethod(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tcountExtractMethod.Inc()\n\treturn extractFunctionMethod(pkg, pgf, start, end, true)\n}\n\n// extractFunction refactors the selected block of code into a new function.\nfunc extractFunction(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tcountExtractFunction.Inc()\n\treturn extractFunctionMethod(pkg, pgf, start, end, false)\n}\n\n// extractFunctionMethod refactors the selected block of code into a new function/method.\n// It also replaces the selected block of code with a call to the extracted\n// function. First, we manually adjust the selection range. We remove trailing\n// and leading whitespace characters to ensure the range is precisely bounded\n// by AST nodes. Next, we determine the variables that will be the parameters\n// and return values of the extracted function/method. Lastly, we construct the call\n// of the function/method and insert this call as well as the extracted function/method into\n// their proper locations.\nfunc extractFunctionMethod(cpkg *cache.Package, pgf *parsego.File, start, end token.Pos, isMethod bool) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tvar (\n\t\tfset = cpkg.FileSet()\n\t\tpkg  = cpkg.Types()\n\t\tinfo = cpkg.TypesInfo()\n\t\tsrc  = pgf.Src\n\t\tfile = pgf.File\n\t)\n\n\terrorPrefix := \"extractFunction\"\n\tif isMethod {\n\t\terrorPrefix = \"extractMethod\"\n\t}\n\n\tp, ok, methodOk, err := canExtractFunction(pgf.Cursor(), start, end)\n\tif (!ok && !isMethod) || (!methodOk && isMethod) {\n\t\treturn nil, nil, fmt.Errorf(\"%s: cannot extract %s: %v\", errorPrefix,\n\t\t\tsafetoken.StartPosition(fset, start), err)\n\t}\n\tcurEnclosing, curStart, curEnd, curFuncDecl := p.curEnclosing, p.curStart, p.curEnd, p.curFuncDecl\n\n\t// Narrow (start, end) to the located nodes.\n\tstart, end = curStart.Node().Pos(), curEnd.Node().End()\n\touter := curFuncDecl.Node().(*ast.FuncDecl)\n\n\t// Labeled statements have un-intuitive ranges.\n\t// Technically they end at the end of the statement\n\t// that they label, but user expectation is that the label\n\t// is a pseudo-statement by itself. This is especially confusing when\n\t// the statement that's labeled is a multi-line block statement.\n\t//\n\t// If the end cursor is the identifier in a labeled statement,\n\t// we expand the range to include the colon.\n\t// That way, we include the label, but not the statement being labeled\n\tif curEnd.ParentEdgeKind() == edge.LabeledStmt_Label {\n\t\tend = curEnd.Parent().Node().(*ast.LabeledStmt).Colon + 1\n\t}\n\n\t// A return statement is non-nested if its parent node is equal to the parent node\n\t// of the first node in the selection. These cases must be handled separately because\n\t// non-nested return statements are guaranteed to execute.\n\tvar hasNonNestedReturn bool\n\n\t// Determine whether all return statements in the selection are\n\t// error-handling return statements. They must be of the form:\n\t// if err != nil {\n\t// \treturn ..., err\n\t// }\n\t// If all return statements in the extracted block have a non-nil error, we\n\t// can replace the \"shouldReturn\" check with an error check to produce a\n\t// more concise output.\n\tvar (\n\t\tallReturnsFinalErr = true  // all ReturnStmts have final 'err' expression\n\t\thasReturn          = false // selection contains a ReturnStmt\n\t\tfilter             = []ast.Node{(*ast.ReturnStmt)(nil), (*ast.FuncLit)(nil)}\n\t)\n\tcurEnclosing.Inspect(filter, func(cur inspector.Cursor) (descend bool) {\n\t\tif funcLit, ok := cur.Node().(*ast.FuncLit); ok {\n\t\t\t// Exclude return statements in function literals because they don't affect the refactor.\n\t\t\t// Keep descending into func lits whose declaration is not included in the extracted block.\n\t\t\treturn !(start < funcLit.Pos() && funcLit.End() < end)\n\t\t}\n\t\tret := cur.Node().(*ast.ReturnStmt)\n\t\tif ret.Pos() < start || ret.End() > end {\n\t\t\treturn false // not part of the extracted block\n\t\t}\n\t\thasReturn = true\n\n\t\tif cur.Parent() == curStart.Parent() {\n\t\t\thasNonNestedReturn = true\n\t\t}\n\n\t\tif !allReturnsFinalErr {\n\t\t\t// Stop the traversal if we have already found a non error-handling return statement.\n\t\t\treturn false\n\t\t}\n\t\t// Check if the return statement returns a non-nil error as the last value.\n\t\tif len(ret.Results) > 0 {\n\t\t\ttyp := info.TypeOf(ret.Results[len(ret.Results)-1])\n\t\t\tif typ != nil && types.Identical(typ, errorType) {\n\t\t\t\t// Have: return ..., err\n\t\t\t\t// Check for enclosing \"if err != nil { return ..., err }\".\n\t\t\t\t// In that case, we can lift the error return to the caller.\n\t\t\t\tif ifstmt, ok := cur.Parent().Parent().Node().(*ast.IfStmt); ok {\n\t\t\t\t\t// Only handle the case where the if statement body contains a single statement.\n\t\t\t\t\tif body, ok := cur.Parent().Node().(*ast.BlockStmt); ok && len(body.List) <= 1 {\n\t\t\t\t\t\tif cond, ok := ifstmt.Cond.(*ast.BinaryExpr); ok {\n\t\t\t\t\t\t\ttx := info.TypeOf(cond.X)\n\t\t\t\t\t\t\tty := info.TypeOf(cond.Y)\n\t\t\t\t\t\t\tisErr := tx != nil && types.Identical(tx, errorType)\n\t\t\t\t\t\t\tisNil := ty != nil && types.Identical(ty, types.Typ[types.UntypedNil])\n\t\t\t\t\t\t\tif cond.Op == token.NEQ && isErr && isNil {\n\t\t\t\t\t\t\t\t// allReturnsErrHandling remains true\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tallReturnsFinalErr = false\n\t\treturn false\n\t})\n\n\tallReturnsFinalErr = hasReturn && allReturnsFinalErr\n\n\t// Now that we have determined the correct range for the selection block,\n\t// we must determine the signature of the extracted function. We will then replace\n\t// the block with an assignment statement that calls the extracted function with\n\t// the appropriate parameters and return values.\n\tvariables, err := collectFreeVars(info, file, start, end, curEnclosing.Node())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar (\n\t\treceiverUsed bool\n\t\treceiver     *ast.Field\n\t\treceiverName string\n\t\treceiverObj  types.Object\n\t)\n\tif isMethod {\n\t\tif outer.Recv == nil || len(outer.Recv.List) == 0 {\n\t\t\treturn nil, nil, fmt.Errorf(\"%s: cannot extract need method receiver\", errorPrefix)\n\t\t}\n\t\treceiver = outer.Recv.List[0]\n\t\tif len(receiver.Names) == 0 || receiver.Names[0] == nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"%s: cannot extract need method receiver name\", errorPrefix)\n\t\t}\n\t\trecvName := receiver.Names[0]\n\t\treceiverName = recvName.Name\n\t\treceiverObj = info.ObjectOf(recvName)\n\t}\n\n\tvar (\n\t\tparams, returns         []ast.Expr     // used when calling the extracted function\n\t\tparamTypes, returnTypes []*ast.Field   // used in the signature of the extracted function\n\t\tuninitialized           []types.Object // vars we will need to initialize before the call\n\t)\n\n\t// Avoid duplicates while traversing vars and uninitialized.\n\tseenVars := make(map[types.Object]ast.Expr)\n\tseenUninitialized := make(map[types.Object]struct{})\n\n\t// Some variables on the left-hand side of our assignment statement may be free. If our\n\t// selection begins in the same scope in which the free variable is defined, we can\n\t// redefine it in our assignment statement. See the following example, where 'b' and\n\t// 'err' (both free variables) can be redefined in the second funcCall() while maintaining\n\t// correctness.\n\t//\n\t//\n\t// Not Redefined:\n\t//\n\t// a, err := funcCall()\n\t// var b int\n\t// b, err = funcCall()\n\t//\n\t// Redefined:\n\t//\n\t// a, err := funcCall()\n\t// b, err := funcCall()\n\t//\n\t// We track the number of free variables that can be redefined to maintain our preference\n\t// of using \"x, y, z := fn()\" style assignment statements.\n\tvar canRedefineCount int\n\n\tqual := typesinternal.FileQualifier(file, pkg)\n\n\t// Each identifier in the selected block must become (1) a parameter to the\n\t// extracted function, (2) a return value of the extracted function, or (3) a local\n\t// variable in the extracted function. Determine the outcome(s) for each variable\n\t// based on whether it is free, altered within the selected block, and used outside\n\t// of the selected block.\n\tfor _, v := range variables {\n\t\tif _, ok := seenVars[v.obj]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tif v.obj.Name() == \"_\" {\n\t\t\t// The blank identifier is always a local variable\n\t\t\tcontinue\n\t\t}\n\t\ttyp := typesinternal.TypeExpr(v.obj.Type(), qual)\n\t\tseenVars[v.obj] = typ\n\t\tidentifier := ast.NewIdent(v.obj.Name())\n\t\t// An identifier must meet three conditions to become a return value of the\n\t\t// extracted function. (1) its value must be defined or reassigned within\n\t\t// the selection (isAssigned), (2) it must be used at least once after the\n\t\t// selection (isUsed), and (3) its first use after the selection\n\t\t// cannot be its own reassignment or redefinition (objOverriden).\n\t\tvscope := v.obj.Parent()\n\t\tif vscope == nil {\n\t\t\t// v.obj could be a field on an anonymous struct. We'll examine the\n\t\t\t// struct in a different iteration so don't return an error here.\n\t\t\tcontinue\n\t\t}\n\t\tisUsed, firstUseAfter := objUsed(info, end, vscope.End(), v.obj)\n\t\tif v.assigned && isUsed && !varOverridden(info, firstUseAfter, v.obj, v.free, outer) {\n\t\t\treturnTypes = append(returnTypes, &ast.Field{Type: typ})\n\t\t\treturns = append(returns, identifier)\n\t\t\tif !v.free {\n\t\t\t\tuninitialized = append(uninitialized, v.obj)\n\n\t\t\t} else {\n\t\t\t\t// In go1.22, Scope.Pos for function scopes changed (#60752):\n\t\t\t\t// it used to start at the body ('{'), now it starts at \"func\".\n\t\t\t\t//\n\t\t\t\t// The second condition below handles the case when\n\t\t\t\t// v's block is the FuncDecl.Body itself.\n\t\t\t\tstartParent := curStart.Parent().Node()\n\t\t\t\tif vscope.Pos() == startParent.Pos() ||\n\t\t\t\t\tstartParent == outer.Body && vscope == info.Scopes[outer.Type] {\n\t\t\t\t\tcanRedefineCount++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// An identifier must meet two conditions to become a parameter of the\n\t\t// extracted function. (1) it must be free (isFree), and (2) its first\n\t\t// use within the selection cannot be its own definition (isDefined).\n\t\tif v.free && !v.defined {\n\t\t\t// Skip the selector for a method.\n\t\t\tif isMethod && v.obj == receiverObj {\n\t\t\t\treceiverUsed = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparams = append(params, identifier)\n\t\t\tparamTypes = append(paramTypes, &ast.Field{\n\t\t\t\tNames: []*ast.Ident{identifier},\n\t\t\t\tType:  typ,\n\t\t\t})\n\t\t}\n\t}\n\n\treorderParams(params, paramTypes)\n\n\t// Find the function literal that encloses the selection. The enclosing function literal\n\t// may not be the enclosing function declaration (i.e. 'outer'). For example, in the\n\t// following block:\n\t//\n\t// func main() {\n\t//     ast.Inspect(node, func(n ast.Node) bool {\n\t//         v := 1 // this line extracted\n\t//         return true\n\t//     })\n\t// }\n\t//\n\t// 'outer' is main(). However, the extracted selection most directly belongs to\n\t// the anonymous function literal, the second argument of ast.Inspect(). We use the\n\t// enclosing function literal to determine the proper return types for return statements\n\t// within the selection. We still need the enclosing function declaration because this is\n\t// the top-level declaration. We inspect the top-level declaration to look for variables\n\t// as well as for code replacement.\n\tenclosing := outer.Type\n\tif funcLit, _ := cursorutil.FirstEnclosing[*ast.FuncLit](curEnclosing); funcLit != nil {\n\t\tenclosing = funcLit.Type\n\t}\n\n\t// We put the selection in a constructed file. We can then traverse and edit\n\t// the extracted selection without modifying the original AST.\n\tstartOffset, endOffset, err := safetoken.Offsets(pgf.Tok, start, end)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tselection := src[startOffset:endOffset]\n\n\textractedBlock, extractedComments, err := parseStmts(fset, selection)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// We need to account for return statements in the selected block, as they will complicate\n\t// the logical flow of the extracted function. See the following example, where ** denotes\n\t// the range to be extracted.\n\t//\n\t// Before:\n\t//\n\t// func _() int {\n\t//     a := 1\n\t//     b := 2\n\t//     **if a == b {\n\t//         return a\n\t//     }**\n\t//     ...\n\t// }\n\t//\n\t// After:\n\t//\n\t// func _() int {\n\t//     a := 1\n\t//     b := 2\n\t//     cond0, ret0 := x0(a, b)\n\t//     if cond0 {\n\t//         return ret0\n\t//     }\n\t//     ...\n\t// }\n\t//\n\t// func x0(a int, b int) (bool, int) {\n\t//     if a == b {\n\t//         return true, a\n\t//     }\n\t//     return false, 0\n\t// }\n\t//\n\t// We handle returns by adding an additional boolean return value to the extracted function.\n\t// This bool reports whether the original function would have returned. Because the\n\t// extracted selection contains a return statement, we must also add the types in the\n\t// return signature of the enclosing function to the return signature of the\n\t// extracted function. We then add an extra if statement checking this boolean value\n\t// in the original function. If the condition is met, the original function should\n\t// return a value, mimicking the functionality of the original return statement(s)\n\t// in the selection.\n\t//\n\t// If there is a return that is guaranteed to execute (hasNonNestedReturns=true), then\n\t// we don't need to include this additional condition check and can simply return.\n\t//\n\t// Before:\n\t//\n\t// func _() int {\n\t//     a := 1\n\t//     b := 2\n\t//     **if a == b {\n\t//         return a\n\t//     }\n\t//\t   return b**\n\t// }\n\t//\n\t// After:\n\t//\n\t// func _() int {\n\t//     a := 1\n\t//     b := 2\n\t//     return x0(a, b)\n\t// }\n\t//\n\t// func x0(a int, b int) int {\n\t//     if a == b {\n\t//         return a\n\t//     }\n\t//     return b\n\t// }\n\n\tvar retVars []*returnVariable\n\tvar ifReturn *ast.IfStmt\n\n\t// Determine if the extracted block contains any free branch statements, for\n\t// example: \"continue label\" where \"label\" is declared outside of the\n\t// extracted block, or continue inside a \"for\" statement where the for\n\t// statement is declared outside of the extracted block. These will be\n\t// handled below, after adjusting return statements and generating return\n\t// info.\n\tcurSel, _ := pgf.Cursor().FindByPos(start, end) // since canExtractFunction succeeded, this will always return a valid cursor\n\tfreeBranches := freeBranches(info, curSel, start, end)\n\n\t// All return statements in the extracted block are error handling returns, and there are no free control statements.\n\tisErrHandlingReturnsCase := allReturnsFinalErr && len(freeBranches) == 0\n\n\tif hasReturn {\n\t\tif !hasNonNestedReturn {\n\t\t\t// The selected block contained return statements, so we have to modify the\n\t\t\t// signature of the extracted function as described above. Adjust all of\n\t\t\t// the return statements in the extracted function to reflect this change in\n\t\t\t// signature.\n\t\t\tif err := adjustReturnStatements(returnTypes, seenVars, extractedBlock, qual, isErrHandlingReturnsCase); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t}\n\t\t// Collect the additional return values and types needed to accommodate return\n\t\t// statements in the selection. Update the type signature of the extracted\n\t\t// function and construct the if statement that will be inserted in the enclosing\n\t\t// function.\n\t\tretVars, ifReturn, err = generateReturnInfo(enclosing, pkg, curEnclosing.Node().Pos(), file, info, start, end, hasNonNestedReturn, isErrHandlingReturnsCase)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t}\n\n\t// If the extracted block contains free branch statements, we add another\n\t// return value \"ctrl\" to the extracted function that will be used to\n\t// determine the control flow. See the following example, where === denotes\n\t// the range to be extracted.\n\t//\n\t// Before:\n\t// func f(cond bool) {\n\t//      for range \"abc\" {\n\t//      ==============\n\t//      if cond {\n\t//          continue\n\t//      }\n\t//      ==============\n\t//      println(0)\n\t//      }\n\t// }\n\n\t// After:\n\t// func f(cond bool) {\n\t//      for range \"abc\" {\n\t//      ctrl := newFunction(cond)\n\t//      switch ctrl {\n\t//      case 1:\n\t//          continue\n\t//      }\n\t//      println(0)\n\t//      }\n\t// }\n\t//\n\t// func newFunction(cond bool) int {\n\t//      if cond {\n\t//          return 1\n\t//      }\n\t//      return 0\n\t// }\n\t//\n\n\t// Generate an unused identifier for the control value.\n\tctrlVar, _ := freshName(info, file, start, \"ctrl\", 0)\n\tif len(freeBranches) > 0 {\n\n\t\tzeroValExpr := &ast.BasicLit{\n\t\t\tKind:  token.INT,\n\t\t\tValue: \"0\",\n\t\t}\n\t\tvar branchStmts []*ast.BranchStmt\n\t\t// Add the zero \"ctrl\" value to each return statement in the extracted block.\n\t\tast.PreorderStack(extractedBlock, nil, func(n ast.Node, stack []ast.Node) bool {\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.ReturnStmt:\n\t\t\t\tn.Results = append(n.Results, zeroValExpr)\n\t\t\tcase *ast.BranchStmt:\n\t\t\t\t// Collect a list of branch statements in the extracted block to examine later.\n\t\t\t\tif isFreeBranchStmt(append(stack, n), extractedBlock) {\n\t\t\t\t\tbranchStmts = append(branchStmts, n)\n\t\t\t\t}\n\t\t\tcase *ast.FuncLit:\n\t\t\t\t// Don't descend into nested functions.\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\n\t\t// Construct a return statement to replace each free branch statement in the extracted block. It should have\n\t\t// zero values for all return parameters except one, \"ctrl\", which dictates which continuation to follow.\n\t\tvar freeCtrlStmtReturns []ast.Expr\n\t\t// Create \"zero values\" for each type.\n\t\tfor _, returnType := range returnTypes {\n\t\t\tvar val ast.Expr\n\t\t\tvar isValid bool\n\t\t\tfor obj, typ := range seenVars {\n\t\t\t\tif typ == returnType.Type {\n\t\t\t\t\tval, isValid = typesinternal.ZeroExpr(obj.Type(), qual)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !isValid {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"could not find matching AST expression for %T\", returnType.Type)\n\t\t\t}\n\t\t\tfreeCtrlStmtReturns = append(freeCtrlStmtReturns, val)\n\t\t}\n\t\tfreeCtrlStmtReturns = append(freeCtrlStmtReturns, getZeroVals(retVars)...)\n\n\t\tfor i, branchStmt := range branchStmts {\n\t\t\treplaceBranchStmtWithReturnStmt(extractedBlock, branchStmt, &ast.ReturnStmt{\n\t\t\t\tReturn: branchStmt.Pos(),\n\t\t\t\tResults: append(slices.Clip(freeCtrlStmtReturns), &ast.BasicLit{\n\t\t\t\t\tKind:  token.INT,\n\t\t\t\t\tValue: strconv.Itoa(i + 1), // start with 1 because 0 is reserved for base case\n\t\t\t\t}),\n\t\t\t})\n\n\t\t}\n\t\tretVars = append(retVars, &returnVariable{\n\t\t\tname:    ast.NewIdent(ctrlVar),\n\t\t\tdecl:    &ast.Field{Type: ast.NewIdent(\"int\")},\n\t\t\tzeroVal: zeroValExpr,\n\t\t})\n\t}\n\n\t// Add a return statement to the end of the new function. This return statement must include\n\t// the values for the types of the original extracted function signature and (if a return\n\t// statement is present in the selection) enclosing function signature.\n\t// This only needs to be done if the selections does not have a non-nested return, otherwise\n\t// it already terminates with a return statement.\n\thasReturnValues := len(returns)+len(retVars) > 0\n\tif hasReturnValues && !hasNonNestedReturn {\n\t\textractedBlock.List = append(extractedBlock.List, &ast.ReturnStmt{\n\t\t\tResults: append(returns, getZeroVals(retVars)...),\n\t\t})\n\t}\n\n\t// Construct the appropriate call to the extracted function.\n\t// We must meet two conditions to use \":=\" instead of '='. (1) there must be at least\n\t// one variable on the lhs that is uninitialized (non-free) prior to the assignment.\n\t// (2) all of the initialized (free) variables on the lhs must be able to be redefined.\n\tsym := token.ASSIGN\n\tcanDefineCount := len(uninitialized) + canRedefineCount\n\tcanDefine := len(uninitialized)+len(retVars) > 0 && canDefineCount == len(returns)\n\tif canDefine {\n\t\tsym = token.DEFINE\n\t}\n\tvar funName string\n\tif isMethod {\n\t\t// TODO(suzmue): generate a name that does not conflict for \"newMethod\".\n\t\tfunName = \"newMethod\"\n\t} else {\n\t\tfunName, _ = freshName(info, file, start, \"newFunction\", 0)\n\t}\n\textractedFunCall := generateFuncCall(hasNonNestedReturn, hasReturnValues, params,\n\t\tappend(returns, getNames(retVars)...), funName, sym, receiverName)\n\n\t// Create variable declarations for any identifiers that need to be initialized prior to\n\t// calling the extracted function. We do not manually initialize variables if every return\n\t// value is uninitialized. We can use := to initialize the variables in this situation.\n\tvar declarations []ast.Stmt\n\tif canDefineCount != len(returns) {\n\t\tdeclarations = initializeVars(uninitialized, retVars, seenUninitialized, seenVars)\n\t}\n\n\tvar declBuf, replaceBuf, newFuncBuf, ifBuf, commentBuf bytes.Buffer\n\tif err := format.Node(&declBuf, fset, declarations); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif err := format.Node(&replaceBuf, fset, extractedFunCall); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif ifReturn != nil {\n\t\tif isErrHandlingReturnsCase {\n\t\t\terrName := retVars[len(retVars)-1]\n\t\t\tfmt.Fprintf(&ifBuf, \"if %s != nil \", errName.name.String())\n\t\t\tif err := format.Node(&ifBuf, fset, ifReturn.Body); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t} else {\n\t\t\tif err := format.Node(&ifBuf, fset, ifReturn); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build the extracted function. We format the function declaration and body\n\t// separately, so that comments are printed relative to the extracted\n\t// BlockStmt.\n\t//\n\t// In other words, extractedBlock and extractedComments were parsed from a\n\t// synthetic function declaration of the form func _() { ... }. If we now\n\t// print the real function declaration, the length of the signature will have\n\t// grown, causing some comment positions to be computed as inside the\n\t// signature itself.\n\tnewFunc := &ast.FuncDecl{\n\t\tName: ast.NewIdent(funName),\n\t\tType: &ast.FuncType{\n\t\t\tParams:  &ast.FieldList{List: paramTypes},\n\t\t\tResults: &ast.FieldList{List: append(returnTypes, getDecls(retVars)...)},\n\t\t},\n\t\t// Body handled separately -- see above.\n\t}\n\tif isMethod {\n\t\tvar names []*ast.Ident\n\t\tif receiverUsed {\n\t\t\tnames = append(names, ast.NewIdent(receiverName))\n\t\t}\n\t\tnewFunc.Recv = &ast.FieldList{\n\t\t\tList: []*ast.Field{{\n\t\t\t\tNames: names,\n\t\t\t\tType:  receiver.Type,\n\t\t\t}},\n\t\t}\n\t}\n\tif err := format.Node(&newFuncBuf, fset, newFunc); err != nil {\n\t\treturn nil, nil, err\n\t}\n\t// Write a space between the end of the function signature and opening '{'.\n\tif err := newFuncBuf.WriteByte(' '); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tcommentedNode := &printer.CommentedNode{\n\t\tNode:     extractedBlock,\n\t\tComments: extractedComments,\n\t}\n\tif err := format.Node(&newFuncBuf, fset, commentedNode); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// We're going to replace the whole enclosing function,\n\t// so preserve the text before and after the selected block.\n\touterStart, outerEnd, err := pgf.NodeOffsets(outer)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tbefore := src[outerStart:startOffset]\n\tafter := src[endOffset:outerEnd]\n\tindent, err := pgf.Indentation(start)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tnewLineIndent := \"\\n\" + indent\n\n\tvar fullReplacement strings.Builder\n\tfullReplacement.Write(before)\n\tif commentBuf.Len() > 0 {\n\t\tcomments := strings.ReplaceAll(commentBuf.String(), \"\\n\", newLineIndent)\n\t\tfullReplacement.WriteString(comments)\n\t}\n\tif declBuf.Len() > 0 { // add any initializations, if needed\n\t\tinitializations := strings.ReplaceAll(declBuf.String(), \"\\n\", newLineIndent) +\n\t\t\tnewLineIndent\n\t\tfullReplacement.WriteString(initializations)\n\t}\n\tfullReplacement.Write(replaceBuf.Bytes()) // call the extracted function\n\tif ifBuf.Len() > 0 {                      // add the if statement below the function call, if needed\n\t\tifstatement := newLineIndent +\n\t\t\tstrings.ReplaceAll(ifBuf.String(), \"\\n\", newLineIndent)\n\t\tfullReplacement.WriteString(ifstatement)\n\t}\n\n\t// Add the switch statement for free branch statements after the new function call.\n\tif len(freeBranches) > 0 {\n\t\tfmt.Fprintf(&fullReplacement, \"%[1]sswitch %[2]s {%[1]s\", newLineIndent, ctrlVar)\n\t\tfor i, br := range freeBranches {\n\t\t\t// Preserve spacing at the beginning of the line containing the branch statement.\n\t\t\tstartPos := pgf.Tok.LineStart(safetoken.Line(pgf.Tok, br.Pos()))\n\t\t\ttext, err := pgf.PosText(startPos, br.End())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tfmt.Fprintf(&fullReplacement, \"case %d:\\n%s%s\", i+1, text, newLineIndent)\n\t\t}\n\t\tfullReplacement.WriteString(\"}\")\n\t}\n\n\tfullReplacement.Write(after)\n\tfullReplacement.WriteString(\"\\n\\n\")       // add newlines after the enclosing function\n\tfullReplacement.Write(newFuncBuf.Bytes()) // insert the extracted function\n\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: []analysis.TextEdit{{\n\t\t\tPos:     outer.Pos(),\n\t\t\tEnd:     outer.End(),\n\t\t\tNewText: []byte(fullReplacement.String()),\n\t\t}},\n\t}, nil\n}\n\n// isSelector reports if e is the selector expr <x>, <sel>. It works for pointer and non-pointer selector expressions.\nfunc isSelector(e ast.Expr, x, sel string) bool {\n\tunary, ok := e.(*ast.UnaryExpr)\n\tif ok && unary.Op == token.MUL {\n\t\te = unary.X\n\t}\n\tselectorExpr, ok := e.(*ast.SelectorExpr)\n\tif !ok {\n\t\treturn false\n\t}\n\tident, ok := selectorExpr.X.(*ast.Ident)\n\tif !ok {\n\t\treturn false\n\t}\n\treturn ident.Name == x && selectorExpr.Sel.Name == sel\n}\n\n// reorderParams reorders the given parameters in-place to follow common Go conventions.\nfunc reorderParams(params []ast.Expr, paramTypes []*ast.Field) {\n\tmoveParamToFrontIfFound(params, paramTypes, \"testing\", \"T\")\n\tmoveParamToFrontIfFound(params, paramTypes, \"testing\", \"B\")\n\tmoveParamToFrontIfFound(params, paramTypes, \"context\", \"Context\")\n}\n\nfunc moveParamToFrontIfFound(params []ast.Expr, paramTypes []*ast.Field, x, sel string) {\n\t// Move Context parameter (if any) to front.\n\tfor i, t := range paramTypes {\n\t\tif isSelector(t.Type, x, sel) {\n\t\t\tp, t := params[i], paramTypes[i]\n\t\t\tcopy(params[1:], params[:i])\n\t\t\tcopy(paramTypes[1:], paramTypes[:i])\n\t\t\tparams[0], paramTypes[0] = p, t\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// variable describes the status of a variable within a selection.\ntype variable struct {\n\tobj types.Object\n\n\t// free reports whether the variable is a free variable, meaning it should\n\t// be a parameter to the extracted function.\n\tfree bool\n\n\t// assigned reports whether the variable is assigned to in the selection.\n\tassigned bool\n\n\t// defined reports whether the variable is defined in the selection.\n\tdefined bool\n}\n\n// collectFreeVars maps each identifier in the given range to whether it is \"free.\"\n// Given a range, a variable in that range is defined as \"free\" if it is declared\n// outside of the range and neither at the file scope nor package scope. These free\n// variables will be used as arguments in the extracted function. It also returns a\n// list of identifiers that may need to be returned by the extracted function.\n// Some of the code in this function has been adapted from tools/cmd/guru/freevars.go.\nfunc collectFreeVars(info *types.Info, file *ast.File, start, end token.Pos, node ast.Node) ([]*variable, error) {\n\tfileScope := info.Scopes[file]\n\tif fileScope == nil {\n\t\treturn nil, bug.Errorf(\"file scope is empty\")\n\t}\n\tpkgScope := fileScope.Parent()\n\tif pkgScope == nil {\n\t\treturn nil, bug.Errorf(\"package scope is empty\")\n\t}\n\t// id returns non-nil if n denotes an object that is referenced by the span\n\t// and defined either within the span or in the lexical environment. The bool\n\t// return value acts as an indicator for where it was defined.\n\tid := func(n *ast.Ident) (types.Object, bool) {\n\t\tobj := info.Uses[n]\n\t\tif obj == nil {\n\t\t\treturn info.Defs[n], false\n\t\t}\n\t\tif obj.Name() == \"_\" {\n\t\t\treturn nil, false // exclude objects denoting '_'\n\t\t}\n\t\tif _, ok := obj.(*types.PkgName); ok {\n\t\t\treturn nil, false // imported package\n\t\t}\n\t\tif !(file.FileStart <= obj.Pos() && obj.Pos() <= file.FileEnd) {\n\t\t\treturn nil, false // not defined in this file\n\t\t}\n\t\tscope := obj.Parent()\n\t\tif scope == nil {\n\t\t\treturn nil, false // e.g. interface method, struct field\n\t\t}\n\t\tif scope == fileScope || scope == pkgScope {\n\t\t\treturn nil, false // defined at file or package scope\n\t\t}\n\t\tif start <= obj.Pos() && obj.Pos() <= end {\n\t\t\treturn obj, false // defined within selection => not free\n\t\t}\n\t\treturn obj, true\n\t}\n\t// sel returns non-nil if n denotes a selection o.x.y that is referenced by the\n\t// span and defined either within the span or in the lexical environment. The bool\n\t// return value acts as an indicator for where it was defined.\n\tvar sel func(n *ast.SelectorExpr) (types.Object, bool)\n\tsel = func(n *ast.SelectorExpr) (types.Object, bool) {\n\t\tswitch x := ast.Unparen(n.X).(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\treturn sel(x)\n\t\tcase *ast.Ident:\n\t\t\treturn id(x)\n\t\t}\n\t\treturn nil, false\n\t}\n\tseen := make(map[types.Object]*variable)\n\tfirstUseIn := make(map[types.Object]token.Pos)\n\tvar vars []types.Object\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\tif start <= n.Pos() && n.End() <= end {\n\t\t\tvar obj types.Object\n\t\t\tvar isFree, prune bool\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.BranchStmt:\n\t\t\t\t// Avoid including labels attached to branch statements.\n\t\t\t\treturn false\n\t\t\tcase *ast.Ident:\n\t\t\t\tobj, isFree = id(n)\n\t\t\tcase *ast.SelectorExpr:\n\t\t\t\tobj, isFree = sel(n)\n\t\t\t\tprune = true\n\t\t\t}\n\t\t\tif obj != nil {\n\t\t\t\tseen[obj] = &variable{\n\t\t\t\t\tobj:  obj,\n\t\t\t\t\tfree: isFree,\n\t\t\t\t}\n\t\t\t\tvars = append(vars, obj)\n\t\t\t\t// Find the first time that the object is used in the selection.\n\t\t\t\tfirst, ok := firstUseIn[obj]\n\t\t\t\tif !ok || n.Pos() < first {\n\t\t\t\t\tfirstUseIn[obj] = n.Pos()\n\t\t\t\t}\n\t\t\t\tif prune {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn n.Pos() <= end\n\t})\n\n\t// Find identifiers that are initialized or whose values are altered at some\n\t// point in the selected block. For example, in a selected block from lines 2-4,\n\t// variables x, y, and z are included in assigned. However, in a selected block\n\t// from lines 3-4, only variables y and z are included in assigned.\n\t//\n\t// 1: var a int\n\t// 2: var x int\n\t// 3: y := 3\n\t// 4: z := x + a\n\t//\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\tif n.Pos() < start || n.End() > end {\n\t\t\treturn n.Pos() <= end\n\t\t}\n\t\tswitch n := n.(type) {\n\t\tcase *ast.AssignStmt:\n\t\t\tfor _, assignment := range n.Lhs {\n\t\t\t\tlhs, ok := assignment.(*ast.Ident)\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tobj, _ := id(lhs)\n\t\t\t\tif obj == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif _, ok := seen[obj]; !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tseen[obj].assigned = true\n\t\t\t\tif n.Tok != token.DEFINE {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Find identifiers that are defined prior to being used\n\t\t\t\t// elsewhere in the selection.\n\t\t\t\t// TODO: Include identifiers that are assigned prior to being\n\t\t\t\t// used elsewhere in the selection. Then, change the assignment\n\t\t\t\t// to a definition in the extracted function.\n\t\t\t\tif firstUseIn[obj] != lhs.Pos() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Ensure that the object is not used in its own re-definition.\n\t\t\t\t// For example:\n\t\t\t\t// var f float64\n\t\t\t\t// f, e := math.Frexp(f)\n\t\t\t\tfor _, expr := range n.Rhs {\n\t\t\t\t\tif referencesObj(info, expr, obj) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tif _, ok := seen[obj]; !ok {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tseen[obj].defined = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\tcase *ast.DeclStmt:\n\t\t\tgen, ok := n.Decl.(*ast.GenDecl)\n\t\t\tif !ok {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor _, spec := range gen.Specs {\n\t\t\t\tvSpecs, ok := spec.(*ast.ValueSpec)\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor _, vSpec := range vSpecs.Names {\n\t\t\t\t\tobj, _ := id(vSpec)\n\t\t\t\t\tif obj == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tif _, ok := seen[obj]; !ok {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tseen[obj].assigned = true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\tcase *ast.IncDecStmt:\n\t\t\tif ident, ok := n.X.(*ast.Ident); !ok {\n\t\t\t\treturn false\n\t\t\t} else if obj, _ := id(ident); obj == nil {\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\tif _, ok := seen[obj]; !ok {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tseen[obj].assigned = true\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\tvar variables []*variable\n\tfor _, obj := range vars {\n\t\tv, ok := seen[obj]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"no seen types.Object for %v\", obj)\n\t\t}\n\t\tif named, ok := v.obj.Type().(typesinternal.NamedOrAlias); ok {\n\t\t\tnamedPos := named.Obj().Pos()\n\t\t\tif isLocal(named.Obj()) && !(start <= namedPos && namedPos <= end) {\n\t\t\t\treturn nil, fmt.Errorf(\"Cannot extract selection: the code refers to a local type whose definition lies outside the extracted block\")\n\t\t\t}\n\t\t}\n\t\tvariables = append(variables, v)\n\t}\n\treturn variables, nil\n}\n\n// referencesObj checks whether the given object appears in the given expression.\nfunc referencesObj(info *types.Info, expr ast.Expr, obj types.Object) bool {\n\tvar hasObj bool\n\tast.Inspect(expr, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\tident, ok := n.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tobjUse := info.Uses[ident]\n\t\tif obj == objUse {\n\t\t\thasObj = true\n\t\t\treturn false\n\t\t}\n\t\treturn false\n\t})\n\treturn hasObj\n}\n\ntype fnExtractParams struct {\n\tcurStart, curEnd inspector.Cursor // first and last nodes wholly enclosed by selection\n\tcurEnclosing     inspector.Cursor // node that encloses selection (e.g. a BlockStmt)\n\tcurFuncDecl      inspector.Cursor // enclosing *ast.FuncDecl\n}\n\n// canExtractFunction reports whether the code in the given range can be\n// extracted to a function.\nfunc canExtractFunction(curFile inspector.Cursor, start, end token.Pos) (*fnExtractParams, bool, bool, error) {\n\tif start == end {\n\t\treturn nil, false, false, fmt.Errorf(\"start and end are equal\")\n\t}\n\n\tcurEnclosing, curStart, curEnd, err := astutil.Select(curFile, start, end)\n\tif err != nil {\n\t\treturn nil, false, false, err\n\t}\n\n\t// Node that encloses the selection must be a statement.\n\t// TODO: Support function extraction for an expression.\n\tif !is[ast.Stmt](curEnclosing.Node()) {\n\t\treturn nil, false, false, fmt.Errorf(\"node is not a statement\")\n\t}\n\n\t// Find the function declaration that encloses the selection.\n\tfuncDecl, curFuncDecl := cursorutil.FirstEnclosing[*ast.FuncDecl](curEnclosing)\n\tif funcDecl == nil {\n\t\treturn nil, false, false, fmt.Errorf(\"no enclosing function\")\n\t}\n\n\t// If the selection is a block statement, use its first and last statements.\n\t// «{ ... }»  =>  { «...» }\n\tif is[*ast.BlockStmt](curStart.Node()) && curStart == curEnd {\n\t\tvar (\n\t\t\tfirst, ok1 = curStart.FirstChild()\n\t\t\tlast, ok2  = curStart.LastChild()\n\t\t)\n\t\tif !(ok1 && ok2) {\n\t\t\treturn nil, false, false, fmt.Errorf(\"range maps to empty block statement\")\n\t\t}\n\t\tcurStart = first\n\t\tcurEnd = last\n\t}\n\n\treturn &fnExtractParams{\n\t\tcurStart:     curStart,\n\t\tcurEnd:       curEnd,\n\t\tcurEnclosing: curEnclosing,\n\t\tcurFuncDecl:  curFuncDecl,\n\t}, true, funcDecl.Recv != nil, nil\n}\n\n// objUsed checks if the object is used within the range. It returns the first\n// occurrence of the object in the range, if it exists.\nfunc objUsed(info *types.Info, start, end token.Pos, obj types.Object) (bool, *ast.Ident) {\n\tvar firstUse *ast.Ident\n\tfor id, objUse := range info.Uses {\n\t\tif obj != objUse {\n\t\t\tcontinue\n\t\t}\n\t\tif id.Pos() < start || id.End() > end {\n\t\t\tcontinue\n\t\t}\n\t\tif firstUse == nil || id.Pos() < firstUse.Pos() {\n\t\t\tfirstUse = id\n\t\t}\n\t}\n\treturn firstUse != nil, firstUse\n}\n\n// varOverridden traverses the given AST node until we find the given identifier. Then, we\n// examine the occurrence of the given identifier and check for (1) whether the identifier\n// is being redefined. If the identifier is free, we also check for (2) whether the identifier\n// is being reassigned. We will not include an identifier in the return statement of the\n// extracted function if it meets one of the above conditions.\nfunc varOverridden(info *types.Info, firstUse *ast.Ident, obj types.Object, isFree bool, node ast.Node) bool {\n\tvar isOverriden bool\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\tassignment, ok := n.(*ast.AssignStmt)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\t// A free variable is initialized prior to the selection. We can always reassign\n\t\t// this variable after the selection because it has already been defined.\n\t\t// Conversely, a non-free variable is initialized within the selection. Thus, we\n\t\t// cannot reassign this variable after the selection unless it is initialized and\n\t\t// returned by the extracted function.\n\t\tif !isFree && assignment.Tok == token.ASSIGN {\n\t\t\treturn false\n\t\t}\n\t\tfor _, assigned := range assignment.Lhs {\n\t\t\tident, ok := assigned.(*ast.Ident)\n\t\t\t// Check if we found the first use of the identifier.\n\t\t\tif !ok || ident != firstUse {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobjUse := info.Uses[ident]\n\t\t\tif objUse == nil || objUse != obj {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Ensure that the object is not used in its own definition.\n\t\t\t// For example:\n\t\t\t// var f float64\n\t\t\t// f, e := math.Frexp(f)\n\t\t\tfor _, expr := range assignment.Rhs {\n\t\t\t\tif referencesObj(info, expr, obj) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\tisOverriden = true\n\t\t\treturn false\n\t\t}\n\t\treturn false\n\t})\n\treturn isOverriden\n}\n\n// parseStmts parses the specified source (a list of statements) and\n// returns them as a BlockStmt along with any associated comments.\nfunc parseStmts(fset *token.FileSet, src []byte) (*ast.BlockStmt, []*ast.CommentGroup, error) {\n\ttext := \"package main\\nfunc _() { \" + string(src) + \" }\"\n\tfile, err := parser.ParseFile(fset, \"\", text, parser.ParseComments|parser.SkipObjectResolution)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif len(file.Decls) != 1 {\n\t\treturn nil, nil, fmt.Errorf(\"got %d declarations, want 1\", len(file.Decls))\n\t}\n\tdecl, ok := file.Decls[0].(*ast.FuncDecl)\n\tif !ok {\n\t\treturn nil, nil, bug.Errorf(\"parsed file does not contain expected function declaration\")\n\t}\n\tif decl.Body == nil {\n\t\treturn nil, nil, bug.Errorf(\"extracted function has no body\")\n\t}\n\treturn decl.Body, file.Comments, nil\n}\n\n// generateReturnInfo generates the information we need to adjust the return statements and\n// signature of the extracted function. We prepare names, signatures, and \"zero values\" that\n// represent the new variables. We also use this information to construct the if statement that\n// is inserted below the call to the extracted function.\nfunc generateReturnInfo(enclosing *ast.FuncType, pkg *types.Package, at token.Pos, file *ast.File, info *types.Info, start, end token.Pos, hasNonNestedReturns bool, isErrHandlingReturnsCase bool) ([]*returnVariable, *ast.IfStmt, error) {\n\tvar retVars []*returnVariable\n\tvar cond *ast.Ident\n\t// Generate information for the values in the return signature of the enclosing function.\n\tif enclosing.Results != nil {\n\t\tnameIdx := make(map[string]int) // last integral suffixes of generated names\n\t\tqual := typesinternal.FileQualifier(file, pkg)\n\t\tfor _, field := range enclosing.Results.List {\n\t\t\ttyp := info.TypeOf(field.Type)\n\t\t\tif typ == nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\n\t\t\t\t\t\"failed type conversion, AST expression: %T\", field.Type)\n\t\t\t}\n\t\t\tnames := []string{\"\"}\n\t\t\tif len(field.Names) > 0 {\n\t\t\t\tnames = nil\n\t\t\t\tfor _, n := range field.Names {\n\t\t\t\t\tnames = append(names, n.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor _, name := range names {\n\t\t\t\tbestName := \"result\"\n\t\t\t\tif name != \"\" && name != \"_\" {\n\t\t\t\t\tbestName = name\n\t\t\t\t} else if n, ok := varNameForType(typ); ok {\n\t\t\t\t\tbestName = n\n\t\t\t\t}\n\t\t\t\tretName, idx := freshNameOutsideRange(info, file, at, start, end, bestName, nameIdx[bestName])\n\t\t\t\tnameIdx[bestName] = idx\n\t\t\t\tz, isValid := typesinternal.ZeroExpr(typ, qual)\n\t\t\t\tif !isValid {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"can't generate zero value for %T\", typ)\n\t\t\t\t}\n\t\t\t\tretVars = append(retVars, &returnVariable{\n\t\t\t\t\tname:    ast.NewIdent(retName),\n\t\t\t\t\tdecl:    &ast.Field{Type: typesinternal.TypeExpr(typ, qual)},\n\t\t\t\t\tzeroVal: z,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\tvar ifReturn *ast.IfStmt\n\tif !hasNonNestedReturns {\n\t\tresults := getNames(retVars)\n\t\tif !isErrHandlingReturnsCase {\n\t\t\t// Generate information for the added bool value.\n\t\t\tname, _ := freshNameOutsideRange(info, file, at, start, end, \"shouldReturn\", 0)\n\t\t\tcond = &ast.Ident{Name: name}\n\t\t\tretVars = append(retVars, &returnVariable{\n\t\t\t\tname:    cond,\n\t\t\t\tdecl:    &ast.Field{Type: ast.NewIdent(\"bool\")},\n\t\t\t\tzeroVal: ast.NewIdent(\"false\"),\n\t\t\t})\n\t\t}\n\t\tifReturn = &ast.IfStmt{\n\t\t\tCond: cond,\n\t\t\tBody: &ast.BlockStmt{\n\t\t\t\tList: []ast.Stmt{&ast.ReturnStmt{Results: results}},\n\t\t\t},\n\t\t}\n\t}\n\treturn retVars, ifReturn, nil\n}\n\ntype objKey struct{ pkg, name string }\n\n// conventionalVarNames specifies conventional names for variables with various\n// standard library types.\n//\n// Keep this up to date with completion.conventionalAcronyms.\n//\n// TODO(rfindley): consider factoring out a \"conventions\" library.\nvar conventionalVarNames = map[objKey]string{\n\t{\"\", \"error\"}:              \"err\",\n\t{\"context\", \"Context\"}:     \"ctx\",\n\t{\"sql\", \"Tx\"}:              \"tx\",\n\t{\"http\", \"ResponseWriter\"}: \"rw\", // Note: same as [AbbreviateVarName].\n}\n\n// varNameForType chooses a \"good\" name for a variable with the given type,\n// if possible. Otherwise, it returns \"\", false.\n//\n// For special types, it uses known conventional names.\nfunc varNameForType(t types.Type) (string, bool) {\n\ttname := typesinternal.TypeNameFor(t)\n\tif tname == nil {\n\t\treturn \"\", false\n\t}\n\n\t// Have Alias, Basic, Named, or TypeParam.\n\tk := objKey{name: tname.Name()}\n\tif tname.Pkg() != nil {\n\t\tk.pkg = tname.Pkg().Name()\n\t}\n\tif name, ok := conventionalVarNames[k]; ok {\n\t\treturn name, true\n\t}\n\n\treturn AbbreviateVarName(tname.Name()), true\n}\n\n// adjustReturnStatements adds \"zero values\" of the given types to each return\n// statement in the given AST node.\nfunc adjustReturnStatements(returnTypes []*ast.Field, seenVars map[types.Object]ast.Expr, extractedBlock *ast.BlockStmt, qual types.Qualifier, isErrHandlingReturnsCase bool) error {\n\tvar zeroVals []ast.Expr\n\t// Create \"zero values\" for each type.\n\tfor _, returnType := range returnTypes {\n\t\tvar val ast.Expr\n\t\tvar isValid bool\n\t\tfor obj, typ := range seenVars {\n\t\t\tif typ == returnType.Type {\n\t\t\t\tval, isValid = typesinternal.ZeroExpr(obj.Type(), qual)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !isValid {\n\t\t\treturn fmt.Errorf(\"could not find matching AST expression for %T\", returnType.Type)\n\t\t}\n\t\tzeroVals = append(zeroVals, val)\n\t}\n\t// Add \"zero values\" to each return statement.\n\t// The bool reports whether the enclosing function should return after calling the\n\t// extracted function. We set the bool to 'true' because, if these return statements\n\t// execute, the extracted function terminates early, and the enclosing function must\n\t// return as well.\n\tvar shouldReturnCond []ast.Expr\n\tif !isErrHandlingReturnsCase {\n\t\tshouldReturnCond = append(shouldReturnCond, ast.NewIdent(\"true\"))\n\t}\n\n\tast.Inspect(extractedBlock, func(n ast.Node) bool {\n\t\tif n == nil {\n\t\t\treturn false\n\t\t}\n\t\t// Don't modify return statements inside anonymous functions.\n\t\tif _, ok := n.(*ast.FuncLit); ok {\n\t\t\treturn false\n\t\t}\n\t\tif n, ok := n.(*ast.ReturnStmt); ok {\n\t\t\tn.Results = slices.Concat(zeroVals, n.Results, shouldReturnCond)\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\treturn nil\n}\n\n// generateFuncCall constructs a call expression for the extracted function, described by the\n// given parameters and return variables.\nfunc generateFuncCall(hasNonNestedReturn, hasReturnVals bool, params, returns []ast.Expr, name string, token token.Token, selector string) ast.Node {\n\tvar replace ast.Node\n\tcallExpr := &ast.CallExpr{\n\t\tFun:  ast.NewIdent(name),\n\t\tArgs: params,\n\t}\n\tif selector != \"\" {\n\t\tcallExpr = &ast.CallExpr{\n\t\t\tFun: &ast.SelectorExpr{\n\t\t\t\tX:   ast.NewIdent(selector),\n\t\t\t\tSel: ast.NewIdent(name),\n\t\t\t},\n\t\t\tArgs: params,\n\t\t}\n\t}\n\tif hasReturnVals {\n\t\tif hasNonNestedReturn {\n\t\t\t// Create a return statement that returns the result of the function call.\n\t\t\treplace = &ast.ReturnStmt{\n\t\t\t\tReturn:  0,\n\t\t\t\tResults: []ast.Expr{callExpr},\n\t\t\t}\n\t\t} else {\n\t\t\t// Assign the result of the function call.\n\t\t\treplace = &ast.AssignStmt{\n\t\t\t\tLhs: returns,\n\t\t\t\tTok: token,\n\t\t\t\tRhs: []ast.Expr{callExpr},\n\t\t\t}\n\t\t}\n\t} else {\n\t\treplace = callExpr\n\t}\n\treturn replace\n}\n\n// initializeVars creates variable declarations, if needed.\n// Our preference is to replace the selected block with an \"x, y, z := fn()\" style\n// assignment statement. We can use this style when all of the variables in the\n// extracted function's return statement are either not defined prior to the extracted block\n// or can be safely redefined. However, for example, if z is already defined\n// in a different scope, we replace the selected block with:\n//\n// var x int\n// var y string\n// x, y, z = fn()\nfunc initializeVars(uninitialized []types.Object, retVars []*returnVariable, seenUninitialized map[types.Object]struct{}, seenVars map[types.Object]ast.Expr) []ast.Stmt {\n\tvar declarations []ast.Stmt\n\tfor _, obj := range uninitialized {\n\t\tif _, ok := seenUninitialized[obj]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseenUninitialized[obj] = struct{}{}\n\t\tvalSpec := &ast.ValueSpec{\n\t\t\tNames: []*ast.Ident{ast.NewIdent(obj.Name())},\n\t\t\tType:  seenVars[obj],\n\t\t}\n\t\tgenDecl := &ast.GenDecl{\n\t\t\tTok:   token.VAR,\n\t\t\tSpecs: []ast.Spec{valSpec},\n\t\t}\n\t\tdeclarations = append(declarations, &ast.DeclStmt{Decl: genDecl})\n\t}\n\t// Each variable added from a return statement in the selection\n\t// must be initialized.\n\tfor i, retVar := range retVars {\n\t\tvalSpec := &ast.ValueSpec{\n\t\t\tNames: []*ast.Ident{retVar.name},\n\t\t\tType:  retVars[i].decl.Type,\n\t\t}\n\t\tgenDecl := &ast.GenDecl{\n\t\t\tTok:   token.VAR,\n\t\t\tSpecs: []ast.Spec{valSpec},\n\t\t}\n\t\tdeclarations = append(declarations, &ast.DeclStmt{Decl: genDecl})\n\t}\n\treturn declarations\n}\n\n// getNames returns the names from the given list of returnVariable.\nfunc getNames(retVars []*returnVariable) []ast.Expr {\n\tvar names []ast.Expr\n\tfor _, retVar := range retVars {\n\t\tnames = append(names, retVar.name)\n\t}\n\treturn names\n}\n\n// getZeroVals returns the \"zero values\" from the given list of returnVariable.\nfunc getZeroVals(retVars []*returnVariable) []ast.Expr {\n\tvar zvs []ast.Expr\n\tfor _, retVar := range retVars {\n\t\tzvs = append(zvs, retVar.zeroVal)\n\t}\n\treturn zvs\n}\n\n// getDecls returns the declarations from the given list of returnVariable.\nfunc getDecls(retVars []*returnVariable) []*ast.Field {\n\tvar decls []*ast.Field\n\tfor _, retVar := range retVars {\n\t\tdecls = append(decls, retVar.decl)\n\t}\n\treturn decls\n}\n\nfunc cond[T any](cond bool, t, f T) T {\n\tif cond {\n\t\treturn t\n\t} else {\n\t\treturn f\n\t}\n}\n\n// replaceBranchStmtWithReturnStmt modifies the ast node to replace the given\n// branch statement with the given return statement.\nfunc replaceBranchStmtWithReturnStmt(block ast.Node, br *ast.BranchStmt, ret *ast.ReturnStmt) {\n\tast.Inspect(block, func(n ast.Node) bool {\n\t\t// Look for the branch statement within a BlockStmt or CaseClause.\n\t\tswitch n := n.(type) {\n\t\tcase *ast.BlockStmt:\n\t\t\tfor i, stmt := range n.List {\n\t\t\t\tif stmt == br {\n\t\t\t\t\tn.List[i] = ret\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.CaseClause:\n\t\t\tfor i, stmt := range n.Body {\n\t\t\t\tif stmt.Pos() == br.Pos() {\n\t\t\t\t\tn.Body[i] = ret\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// freeBranches returns all branch statements beneath cur whose continuation\n// lies outside the (start, end) range.\nfunc freeBranches(info *types.Info, cur inspector.Cursor, start, end token.Pos) (free []*ast.BranchStmt) {\nnextBranch:\n\tfor curBr := range cur.Preorder((*ast.BranchStmt)(nil)) {\n\t\tbr := curBr.Node().(*ast.BranchStmt)\n\t\tif br.End() < start || br.Pos() > end {\n\t\t\tcontinue\n\t\t}\n\t\tlabel, _ := info.Uses[br.Label].(*types.Label)\n\t\tif label != nil && !(start <= label.Pos() && label.Pos() <= end) {\n\t\t\tfree = append(free, br)\n\t\t\tcontinue\n\t\t}\n\t\tif br.Tok == token.BREAK || br.Tok == token.CONTINUE {\n\t\t\tfilter := []ast.Node{\n\t\t\t\t(*ast.ForStmt)(nil),\n\t\t\t\t(*ast.RangeStmt)(nil),\n\t\t\t\t(*ast.SwitchStmt)(nil),\n\t\t\t\t(*ast.TypeSwitchStmt)(nil),\n\t\t\t\t(*ast.SelectStmt)(nil),\n\t\t\t}\n\t\t\t// Find innermost relevant ancestor for break/continue.\n\t\t\tfor curAncestor := range curBr.Parent().Enclosing(filter...) {\n\t\t\t\tif l, ok := curAncestor.Parent().Node().(*ast.LabeledStmt); ok &&\n\t\t\t\t\tlabel != nil &&\n\t\t\t\t\tl.Label.Name == label.Name() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tswitch n := curAncestor.Node().(type) {\n\t\t\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\t\t\tif n.Pos() < start {\n\t\t\t\t\t\tfree = append(free, br)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue nextBranch\n\t\t\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\t\t\t\tif br.Tok == token.BREAK {\n\t\t\t\t\t\tif n.Pos() < start {\n\t\t\t\t\t\t\tfree = append(free, br)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue nextBranch\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// isFreeBranchStmt returns true if the relevant ancestor for the branch\n// statement at stack[len(stack)-1] cannot be found in the stack (for\n// break/continue) or the extracted block (for goto). This is used when we are\n// examining the extracted block, since type information isn't available. We\n// need to find the location of the label without using types.Info.\n// We treat goto and break/continue separately because while break/continue\n// must be used within a for, range, switch, or select, goto's use is\n// less restrictive within a function body.\nfunc isFreeBranchStmt(stack []ast.Node, extractedBlock *ast.BlockStmt) bool {\n\tswitch node := stack[len(stack)-1].(type) {\n\tcase *ast.BranchStmt:\n\t\tisLabeled := node.Label != nil\n\t\tswitch node.Tok {\n\t\tcase token.GOTO:\n\t\t\tif isLabeled {\n\t\t\t\tfor _, stmt := range extractedBlock.List {\n\t\t\t\t\tif l, ok := stmt.(*ast.LabeledStmt); ok && l.Label != nil && l.Label.Name == node.Label.Name {\n\t\t\t\t\t\t// We found the label in the extracted block, so it's not a free branch stmt.\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\t\tcase token.BREAK, token.CONTINUE:\n\t\t\t// Find innermost relevant ancestor for break/continue.\n\t\t\tfor i := len(stack) - 2; i >= 0; i-- {\n\t\t\t\tn := stack[i]\n\t\t\t\tif isLabeled {\n\t\t\t\t\tl, ok := n.(*ast.LabeledStmt)\n\t\t\t\t\tif !(ok && l.Label.Name == node.Label.Name) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch n.(type) {\n\t\t\t\tcase *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// We didn't find the relevant ancestor on the path, so this must be a free branch statement.\n\treturn true\n}\n"
  },
  {
    "path": "gopls/internal/golang/extracttofile.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines the code action \"Extract declarations to new file\".\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// canExtractToNewFile reports whether the code in the given range can be extracted to a new file.\nfunc canExtractToNewFile(pgf *parsego.File, start, end token.Pos) bool {\n\t_, _, _, ok := selectedToplevelDecls(pgf, start, end)\n\treturn ok\n}\n\n// findImportEdits finds imports specs that needs to be added to the new file\n// or deleted from the old file if the range is extracted to a new file.\n//\n// TODO: handle dot imports.\nfunc findImportEdits(file *ast.File, info *types.Info, start, end token.Pos) (adds, deletes []*ast.ImportSpec, _ error) {\n\t// make a map from a pkgName to its references\n\tpkgNameReferences := make(map[*types.PkgName][]*ast.Ident)\n\tfor ident, use := range info.Uses {\n\t\tif pkgName, ok := use.(*types.PkgName); ok {\n\t\t\tpkgNameReferences[pkgName] = append(pkgNameReferences[pkgName], ident)\n\t\t}\n\t}\n\n\t// PkgName referenced in the extracted selection must be\n\t// imported in the new file.\n\t// PkgName only referenced in the extracted selection must be\n\t// deleted from the original file.\n\tfor _, spec := range file.Imports {\n\t\tif spec.Name != nil && spec.Name.Name == \".\" {\n\t\t\t// TODO: support dot imports.\n\t\t\treturn nil, nil, errors.New(\"\\\"extract to new file\\\" does not support files containing dot imports\")\n\t\t}\n\t\tpkgName := info.PkgNameOf(spec)\n\t\tif pkgName == nil {\n\t\t\tcontinue\n\t\t}\n\t\tusedInSelection := false\n\t\tusedInNonSelection := false\n\t\tfor _, ident := range pkgNameReferences[pkgName] {\n\t\t\tif posRangeContains(start, end, ident.Pos(), ident.End()) {\n\t\t\t\tusedInSelection = true\n\t\t\t} else {\n\t\t\t\tusedInNonSelection = true\n\t\t\t}\n\t\t}\n\t\tif usedInSelection {\n\t\t\tadds = append(adds, spec)\n\t\t}\n\t\tif usedInSelection && !usedInNonSelection {\n\t\t\tdeletes = append(deletes, spec)\n\t\t}\n\t}\n\n\treturn adds, deletes, nil\n}\n\n// ExtractToNewFile moves selected declarations into a new file.\nfunc ExtractToNewFile(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.DocumentChange, error) {\n\terrorPrefix := \"ExtractToNewFile\"\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", errorPrefix, err)\n\t}\n\n\t// Expand the selection, and compute the portion to extract.\n\tstart, end, firstSymbol, ok := selectedToplevelDecls(pgf, start, end)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid selection\")\n\t}\n\tpgf.CheckPos(start) // #70553\n\t// Inv: start is valid wrt pgf.Tok.\n\n\t// select trailing empty lines\n\toffset, err := safetoken.Offset(pgf.Tok, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\trest := pgf.Src[offset:]\n\tspaces := len(rest) - len(bytes.TrimLeft(rest, \" \\t\\n\"))\n\tend += token.Pos(spaces)\n\tpgf.CheckPos(end) // #70553\n\tif !(start <= end) {\n\t\tbug.Reportf(\"start: not before end\")\n\t}\n\t// Inv: end is valid wrt pgf.Tok; env >= start.\n\tfileStart := pgf.File.FileStart\n\tpgf.CheckPos(fileStart) // #70553\n\tif !(0 <= start-fileStart) {\n\t\tbug.Reportf(\"start: out of bounds\")\n\t}\n\tif !(int(end-fileStart) <= len(pgf.Src)) {\n\t\tbug.Reportf(\"end: out of bounds\")\n\t}\n\t// Inv: 0 <= start-fileStart <= end-fileStart <= len(Src).\n\tsrc := pgf.Src[start-fileStart : end-fileStart]\n\n\treplaceRange, err := pgf.PosRange(start, end)\n\tif err != nil {\n\t\treturn nil, bug.Errorf(\"invalid range: %v\", err)\n\t}\n\n\tadds, deletes, err := findImportEdits(pgf.File, pkg.TypesInfo(), start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar importDeletes []protocol.TextEdit\n\t// For unparenthesised declarations like `import \"fmt\"` we remove\n\t// the whole declaration because simply removing importSpec leaves\n\t// `import \\n`, which does not compile.\n\t// For parenthesised declarations like `import (\"fmt\"\\n \"log\")`\n\t// we only remove the ImportSpec, because removing the whole declaration\n\t// might remove other ImportsSpecs we don't want to touch.\n\tunparenthesizedImports := unparenthesizedImports(pgf)\n\tfor _, importSpec := range deletes {\n\t\tif decl := unparenthesizedImports[importSpec]; decl != nil {\n\t\t\timportDeletes = append(importDeletes, removeNode(pgf, decl))\n\t\t} else {\n\t\t\timportDeletes = append(importDeletes, removeNode(pgf, importSpec))\n\t\t}\n\t}\n\n\tvar buf bytes.Buffer\n\tif c := CopyrightComment(pgf.File); c != nil {\n\t\ttext, err := pgf.NodeText(c)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbuf.Write(text)\n\t\t// One empty line between copyright header and following.\n\t\tbuf.WriteString(\"\\n\\n\")\n\t}\n\n\tif c := buildConstraintComment(pgf.File); c != nil {\n\t\ttext, err := pgf.NodeText(c)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbuf.Write(text)\n\t\t// One empty line between build constraint and following.\n\t\tbuf.WriteString(\"\\n\\n\")\n\t}\n\n\tfmt.Fprintf(&buf, \"package %s\\n\", pgf.File.Name.Name)\n\tif len(adds) > 0 {\n\t\tbuf.WriteString(\"import (\")\n\t\tfor _, importSpec := range adds {\n\t\t\tif importSpec.Name != nil {\n\t\t\t\tfmt.Fprintf(&buf, \"%s %s\\n\", importSpec.Name.Name, importSpec.Path.Value)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(&buf, \"%s\\n\", importSpec.Path.Value)\n\t\t\t}\n\t\t}\n\t\tbuf.WriteString(\")\\n\")\n\t}\n\n\tnewFile, err := chooseNewFile(ctx, snapshot, pgf.URI.DirPath(), firstSymbol)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", errorPrefix, err)\n\t}\n\n\tbuf.Write(src)\n\n\tnewFileContent, err := format.Source(buf.Bytes())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn []protocol.DocumentChange{\n\t\t// edit the original file\n\t\tprotocol.DocumentChangeEdit(fh, append(importDeletes, protocol.TextEdit{Range: replaceRange, NewText: \"\"})),\n\t\t// create a new file\n\t\tprotocol.DocumentChangeCreate(newFile.URI()),\n\t\t// edit the created file\n\t\tprotocol.DocumentChangeEdit(newFile, []protocol.TextEdit{\n\t\t\t{Range: protocol.Range{}, NewText: string(newFileContent)},\n\t\t})}, nil\n}\n\n// chooseNewFile chooses a new filename in dir, based on the name of the\n// first extracted symbol, and if necessary to disambiguate, a numeric suffix.\nfunc chooseNewFile(ctx context.Context, snapshot *cache.Snapshot, dir string, firstSymbol string) (file.Handle, error) {\n\tbasename := strings.ToLower(firstSymbol)\n\tnewPath := protocol.URIFromPath(filepath.Join(dir, basename+\".go\"))\n\tfor count := 1; count < 5; count++ {\n\t\tfh, err := snapshot.ReadFile(ctx, newPath)\n\t\tif err != nil {\n\t\t\treturn nil, err // canceled\n\t\t}\n\t\tif _, err := fh.Content(); errors.Is(err, os.ErrNotExist) {\n\t\t\treturn fh, nil\n\t\t}\n\t\tfilename := fmt.Sprintf(\"%s.%d.go\", basename, count)\n\t\tnewPath = protocol.URIFromPath(filepath.Join(dir, filename))\n\t}\n\treturn nil, fmt.Errorf(\"chooseNewFileURI: exceeded retry limit\")\n}\n\n// selectedToplevelDecls returns the lexical extent of the top-level\n// declarations enclosed by [start, end), along with the name of the\n// first declaration. The returned boolean reports whether the selection\n// should be offered a code action to extract the declarations.\nfunc selectedToplevelDecls(pgf *parsego.File, start, end token.Pos) (token.Pos, token.Pos, string, bool) {\n\t// selection cannot intersect a package declaration\n\tif posRangeIntersects(start, end, pgf.File.Package, pgf.File.Name.End()) {\n\t\treturn 0, 0, \"\", false\n\t}\n\tfirstName := \"\"\n\tfor _, decl := range pgf.File.Decls {\n\t\tif posRangeIntersects(start, end, decl.Pos(), decl.End()) {\n\t\t\tvar (\n\t\t\t\tcomment *ast.CommentGroup // (include comment preceding decl)\n\t\t\t\tid      *ast.Ident\n\t\t\t)\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.BadDecl:\n\t\t\t\treturn 0, 0, \"\", false\n\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\t// if only selecting keyword \"func\" or function name, extend selection to the\n\t\t\t\t// whole function\n\t\t\t\tif posRangeContains(decl.Pos(), decl.Name.End(), start, end) {\n\t\t\t\t\tpgf.CheckNode(decl) // #70553\n\t\t\t\t\tstart, end = decl.Pos(), decl.End()\n\t\t\t\t\t// Inv: start, end are valid wrt pgf.Tok.\n\t\t\t\t}\n\t\t\t\tcomment = decl.Doc\n\t\t\t\tid = decl.Name\n\n\t\t\tcase *ast.GenDecl:\n\t\t\t\t// selection cannot intersect an import declaration\n\t\t\t\tif decl.Tok == token.IMPORT {\n\t\t\t\t\treturn 0, 0, \"\", false\n\t\t\t\t}\n\t\t\t\t// if only selecting keyword \"type\", \"const\", or \"var\", extend selection to the\n\t\t\t\t// whole declaration\n\t\t\t\tif decl.Tok == token.TYPE && posRangeContains(decl.Pos(), decl.Pos()+token.Pos(len(\"type\")), start, end) ||\n\t\t\t\t\tdecl.Tok == token.CONST && posRangeContains(decl.Pos(), decl.Pos()+token.Pos(len(\"const\")), start, end) ||\n\t\t\t\t\tdecl.Tok == token.VAR && posRangeContains(decl.Pos(), decl.Pos()+token.Pos(len(\"var\")), start, end) {\n\t\t\t\t\tpgf.CheckNode(decl) // #70553\n\t\t\t\t\tstart, end = decl.Pos(), decl.End()\n\t\t\t\t\t// Inv: start, end are valid wrt pgf.Tok.\n\t\t\t\t}\n\t\t\t\tcomment = decl.Doc\n\t\t\t\tif len(decl.Specs) > 0 {\n\t\t\t\t\tswitch spec := decl.Specs[0].(type) {\n\t\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t\tid = spec.Name\n\t\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t\tid = spec.Names[0]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// selection cannot partially intersect a node\n\t\t\tif !posRangeContains(start, end, decl.Pos(), decl.End()) {\n\t\t\t\treturn 0, 0, \"\", false\n\t\t\t}\n\t\t\tif id != nil && firstName == \"\" {\n\t\t\t\t// may be \"_\"\n\t\t\t\tfirstName = id.Name\n\t\t\t}\n\t\t\tif comment != nil && comment.Pos() < start {\n\t\t\t\tpgf.CheckNode(comment) // #70553\n\t\t\t\tstart = comment.Pos()\n\t\t\t\t// Inv: start is valid wrt pgf.Tok.\n\t\t\t}\n\t\t}\n\t}\n\tfor _, comment := range pgf.File.Comments {\n\t\tif posRangeIntersects(start, end, comment.Pos(), comment.End()) {\n\t\t\tif !posRangeContains(start, end, comment.Pos(), comment.End()) {\n\t\t\t\t// selection cannot partially intersect a comment\n\t\t\t\treturn 0, 0, \"\", false\n\t\t\t}\n\t\t}\n\t}\n\tif firstName == \"\" {\n\t\treturn 0, 0, \"\", false\n\t}\n\treturn start, end, firstName, true\n}\n\n// unparenthesizedImports returns a map from each unparenthesized ImportSpec\n// to its enclosing declaration (which may need to be deleted too).\nfunc unparenthesizedImports(pgf *parsego.File) map[*ast.ImportSpec]*ast.GenDecl {\n\tdecls := make(map[*ast.ImportSpec]*ast.GenDecl)\n\tfor _, decl := range pgf.File.Decls {\n\t\tif decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT && !decl.Lparen.IsValid() {\n\t\t\tdecls[decl.Specs[0].(*ast.ImportSpec)] = decl\n\t\t}\n\t}\n\treturn decls\n}\n\n// removeNode returns a TextEdit that removes the node.\nfunc removeNode(pgf *parsego.File, node ast.Node) protocol.TextEdit {\n\trng, err := pgf.NodeRange(node)\n\tif err != nil {\n\t\tbug.Reportf(\"removeNode: %v\", err)\n\t}\n\treturn protocol.TextEdit{Range: rng, NewText: \"\"}\n}\n\n// posRangeIntersects checks if [a, b) and [c, d) intersects, assuming a <= b and c <= d.\nfunc posRangeIntersects(a, b, c, d token.Pos) bool {\n\treturn !(b <= c || d <= a)\n}\n\n// posRangeContains checks if [a, b) contains [c, d), assuming a <= b and c <= d.\nfunc posRangeContains(a, b, c, d token.Pos) bool {\n\treturn a <= c && d <= b\n}\n"
  },
  {
    "path": "gopls/internal/golang/fix.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillstruct\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedparams\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\n// A fixer is a function that suggests a fix for a diagnostic produced\n// by the analysis framework. This is done outside of the analyzer Run\n// function so that the construction of expensive fixes can be\n// deferred until they are requested by the user.\n//\n// The actual diagnostic is not provided; only its position, as the\n// triple (pgf, start, end); the resulting SuggestedFix implicitly\n// relates to that file.\n//\n// The supplied token positions (start, end) must belong to\n// pkg.FileSet(), and the returned positions\n// (SuggestedFix.TextEdits[*].{Pos,End}) must belong to the returned\n// FileSet, which is not necessarily the same.\n// (See [insertDeclsAfter] for explanation.)\n//\n// A fixer may return (nil, nil) if no fix is available.\ntype fixer func(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error)\n\n// A singleFileFixer is a [fixer] that inspects only a single file.\ntype singleFileFixer func(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error)\n\n// singleFile adapts a [singleFileFixer] to a [fixer]\n// by discarding the snapshot and the context it needs.\nfunc singleFile(fixer1 singleFileFixer) fixer {\n\treturn func(_ context.Context, _ *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\t\treturn fixer1(pkg, pgf, start, end)\n\t}\n}\n\n// Names of ApplyFix.Fix created directly by the CodeAction handler.\nconst (\n\tfixExtractVariable         = \"extract_variable\" // (or constant)\n\tfixExtractVariableAll      = \"extract_variable_all\"\n\tfixExtractFunction         = \"extract_function\"\n\tfixExtractMethod           = \"extract_method\"\n\tfixInlineCall              = \"inline_call\" // keep consistent with go/analysis/passes/inline Diagnostic.Category\n\tfixInlineVariable          = \"inline_variable\"\n\tfixInvertIfCondition       = \"invert_if_condition\"\n\tfixSplitLines              = \"split_lines\"\n\tfixJoinLines               = \"join_lines\"\n\tfixCreateUndeclared        = \"create_undeclared\"\n\tfixMissingInterfaceMethods = \"stub_missing_interface_method\"\n\tfixMissingCalledFunction   = \"stub_missing_called_function\"\n)\n\n// ApplyFix applies the specified kind of suggested fix to the given\n// file and range, returning the resulting changes.\n//\n// A fix kind is either the Category of an analysis.Diagnostic that\n// had a SuggestedFix with no edits; or the name of a fix agreed upon\n// by [CodeActions] and this function.\n// Fix kinds identify fixes in the command protocol.\n//\n// TODO(adonovan): come up with a better mechanism for registering the\n// connection between analyzers, code actions, and fixers. A flaw of\n// the current approach is that the same Category could in theory\n// apply to a Diagnostic with several lazy fixes, making them\n// impossible to distinguish. It would more precise if there was a\n// SuggestedFix.Category field, or some other way to squirrel metadata\n// in the fix.\nfunc ApplyFix(ctx context.Context, fix string, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.DocumentChange, error) {\n\t// This can't be expressed as an entry in the fixer table below\n\t// because it operates in the protocol (not go/{token,ast}) domain.\n\t// (Sigh; perhaps it was a mistake to factor out the\n\t// NarrowestPackageForFile/RangePos/suggestedFixToEdits\n\t// steps.)\n\tif fix == unusedparams.FixCategory {\n\t\treturn removeParam(ctx, snapshot, fh, rng)\n\t}\n\n\tfixers := map[string]fixer{\n\t\t// Fixes for analyzer-provided diagnostics.\n\t\t// These match the Diagnostic.Category.\n\t\tfillstruct.FixCategory: singleFile(fillstruct.SuggestedFix),\n\n\t\t// Ad-hoc fixers: these are used when the command is\n\t\t// constructed directly by logic in server/code_action.\n\t\tfixExtractFunction:         singleFile(extractFunction),\n\t\tfixExtractMethod:           singleFile(extractMethod),\n\t\tfixExtractVariable:         singleFile(extractVariableOne),\n\t\tfixExtractVariableAll:      singleFile(extractVariableAll),\n\t\tfixInlineCall:              inlineCall,\n\t\tfixInlineVariable:          singleFile(inlineVariableOne),\n\t\tfixInvertIfCondition:       singleFile(invertIfCondition),\n\t\tfixSplitLines:              singleFile(splitLines),\n\t\tfixJoinLines:               singleFile(joinLines),\n\t\tfixCreateUndeclared:        singleFile(createUndeclared),\n\t\tfixMissingInterfaceMethods: stubMissingInterfaceMethodsFixer,\n\t\tfixMissingCalledFunction:   stubMissingCalledFunctionFixer,\n\t}\n\tfixer, ok := fixers[fix]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no suggested fix function for %s\", fix)\n\t}\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfixFset, suggestion, err := fixer(ctx, snapshot, pkg, pgf, start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif suggestion == nil {\n\t\treturn nil, nil\n\t}\n\treturn suggestedFixToDocumentChange(ctx, snapshot, fixFset, suggestion)\n}\n\n// suggestedFixToDocumentChange converts the suggestion's edits from analysis form into protocol form.\nfunc suggestedFixToDocumentChange(ctx context.Context, snapshot *cache.Snapshot, fset *token.FileSet, suggestion *analysis.SuggestedFix) ([]protocol.DocumentChange, error) {\n\ttype fileInfo struct {\n\t\tfh     file.Handle\n\t\tmapper *protocol.Mapper\n\t\tedits  []protocol.TextEdit\n\t}\n\tfiles := make(map[protocol.DocumentURI]*fileInfo)\n\tfor _, edit := range suggestion.TextEdits {\n\t\ttokFile := fset.File(edit.Pos)\n\t\tif tokFile == nil {\n\t\t\treturn nil, bug.Errorf(\"no file for edit position\")\n\t\t}\n\t\tend := edit.End\n\t\tif !end.IsValid() {\n\t\t\tend = edit.Pos\n\t\t}\n\t\turi := protocol.URIFromPath(tokFile.Name())\n\t\tinfo, ok := files[uri]\n\t\tif !ok {\n\t\t\t// First edit: create a mapper.\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcontent, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tmapper := protocol.NewMapper(uri, content)\n\t\t\tinfo = &fileInfo{fh, mapper, nil}\n\t\t\tfiles[uri] = info\n\t\t}\n\t\trng, err := info.mapper.PosRange(tokFile, edit.Pos, end)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tinfo.edits = append(info.edits, protocol.TextEdit{\n\t\t\tRange:   rng,\n\t\t\tNewText: string(edit.NewText),\n\t\t})\n\t}\n\tvar changes []protocol.DocumentChange\n\tfor _, info := range files {\n\t\tchange := protocol.DocumentChangeEdit(info.fh, info.edits)\n\t\tchanges = append(changes, change)\n\t}\n\treturn changes, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/folding_range.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// FoldingRange gets all of the folding range for f.\nfunc FoldingRange(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, lineFoldingOnly bool) ([]protocol.FoldingRange, error) {\n\t// TODO(suzmue): consider limiting the number of folding ranges returned, and\n\t// implement a way to prioritize folding ranges in that case.\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// With parse errors, we wouldn't be able to produce accurate folding info.\n\t// LSP protocol (3.16) currently does not have a way to handle this case\n\t// (https://github.com/microsoft/language-server-protocol/issues/1200).\n\t// We cannot return an error either because we are afraid some editors\n\t// may not handle errors nicely. As a workaround, we now return an empty\n\t// result and let the client handle this case by double check the file\n\t// contents (i.e. if the file is not empty and the folding range result\n\t// is empty, raise an internal error).\n\tif pgf.ParseErr != nil {\n\t\treturn nil, nil\n\t}\n\n\t// Get folding ranges for comments separately as they are not walked by ast.Inspect.\n\tranges := commentsFoldingRange(pgf)\n\n\t// Walk the ast and collect folding ranges.\n\tfilter := []ast.Node{\n\t\t(*ast.BasicLit)(nil),\n\t\t(*ast.BlockStmt)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t\t(*ast.CaseClause)(nil),\n\t\t(*ast.CommClause)(nil),\n\t\t(*ast.CompositeLit)(nil),\n\t\t(*ast.FieldList)(nil),\n\t\t(*ast.GenDecl)(nil),\n\t}\n\tfor cur := range pgf.Cursor().Preorder(filter...) {\n\t\tvar kind protocol.FoldingRangeKind\n\t\t// start and end define the range of content to fold away.\n\t\tvar start, end token.Pos\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.BlockStmt:\n\t\t\t// Fold between positions of or lines between \"{\" and \"}\".\n\t\t\tstart, end = bracketedFoldingRange(pgf, n.Lbrace, n.Rbrace, lineFoldingOnly)\n\n\t\tcase *ast.CaseClause:\n\t\t\t// Fold from position of \":\" to end.\n\t\t\tstart, end = n.Colon+1, n.End()\n\n\t\tcase *ast.CommClause:\n\t\t\t// Fold from position of \":\" to end.\n\t\t\tstart, end = n.Colon+1, n.End()\n\n\t\tcase *ast.CallExpr:\n\t\t\t// Fold between positions of or lines between \"(\" and \")\".\n\t\t\tstart, end = bracketedFoldingRange(pgf, n.Lparen, n.Rparen, lineFoldingOnly)\n\n\t\tcase *ast.FieldList:\n\t\t\t// Fold between positions of or lines between opening parenthesis/brace and closing parenthesis/brace.\n\t\t\tstart, end = bracketedFoldingRange(pgf, n.Opening, n.Closing, lineFoldingOnly)\n\n\t\tcase *ast.GenDecl:\n\t\t\t// If this is an import declaration, set the kind to be protocol.Imports.\n\t\t\tif n.Tok == token.IMPORT {\n\t\t\t\tkind = protocol.Imports\n\t\t\t}\n\t\t\t// Fold between positions of or lines between \"(\" and \")\".\n\t\t\tstart, end = bracketedFoldingRange(pgf, n.Lparen, n.Rparen, lineFoldingOnly)\n\n\t\tcase *ast.BasicLit:\n\t\t\t// Fold raw string literals from position of \"`\" to position of \"`\".\n\t\t\tif n.Kind == token.STRING && len(n.Value) >= 2 && n.Value[0] == '`' && n.Value[len(n.Value)-1] == '`' {\n\t\t\t\tstart, end = n.Pos(), n.End()\n\t\t\t}\n\n\t\tcase *ast.CompositeLit:\n\t\t\t// Fold between positions of or lines between \"{\" and \"}\".\n\t\t\tstart, end = bracketedFoldingRange(pgf, n.Lbrace, n.Rbrace, lineFoldingOnly)\n\n\t\tdefault:\n\t\t\tpanic(n)\n\t\t}\n\n\t\t// Check that folding positions are valid.\n\t\tif !start.IsValid() || !end.IsValid() {\n\t\t\tcontinue\n\t\t}\n\t\tif start == end {\n\t\t\t// Nothing to fold.\n\t\t\tcontinue\n\t\t}\n\t\t// in line folding mode, do not fold if the start and end lines are the same.\n\t\tif lineFoldingOnly && safetoken.Line(pgf.Tok, start) == safetoken.Line(pgf.Tok, end) {\n\t\t\tcontinue\n\t\t}\n\t\trng, err := pgf.PosRange(start, end)\n\t\tif err != nil {\n\t\t\tbug.Reportf(\"failed to create range: %s\", err) // can't happen\n\t\t\tcontinue\n\t\t}\n\t\tranges = append(ranges, foldingRange(kind, rng))\n\t}\n\n\t// Sort by start position.\n\tslices.SortFunc(ranges, func(x, y protocol.FoldingRange) int {\n\t\tif d := cmp.Compare(*x.StartLine, *y.StartLine); d != 0 {\n\t\t\treturn d\n\t\t}\n\t\treturn cmp.Compare(*x.StartCharacter, *y.StartCharacter)\n\t})\n\n\treturn ranges, nil\n}\n\n// bracketedFoldingRange returns the folding range for nodes with parentheses/braces/brackets\n// that potentially can take up multiple lines.\nfunc bracketedFoldingRange(pgf *parsego.File, open, close token.Pos, lineFoldingOnly bool) (token.Pos, token.Pos) {\n\tif !open.IsValid() || !close.IsValid() {\n\t\treturn token.NoPos, token.NoPos\n\t}\n\tif open+1 == close {\n\t\t// Nothing to fold: (), {} or [].\n\t\treturn token.NoPos, token.NoPos\n\t}\n\n\tif !lineFoldingOnly {\n\t\treturn open + 1, close\n\t}\n\n\t// Clients with \"LineFoldingOnly\" set to true can fold only full lines.\n\t// This is also checked in the caller.\n\t//\n\t// Clients that support folding ranges can display them in various ways\n\t// (e.g., how are folding ranges marked? is the final line displayed?).\n\t// The most common client\n\t// is vscode, which displays the first line followed by ..., and then does not\n\t// display any other lines in the range, but other clients might also display\n\t// final line of the range. For example, the following code\n\t//\n\t//\tvar x = []string{\"a\",\n\t//\t\"b\",\n\t//\t\"c\" }\n\t//\n\t// can be folded (in vscode) to\n\t//\n\t// var x = []string{\"a\", ...\n\t//\n\t// or in some other client\n\t//\n\t//\tvar x = []string{\"a\", ...\n\t//\t\"c\" }\n\t//\n\t// This code displays the final line containing ),},], but not the closing quote\n\t// of a multi-line string\n\n\tprevLineEnd := pgf.Tok.LineStart(safetoken.Line(pgf.Tok, close)) - 1 // there was a previous line\n\tif prevLineEnd <= open {                                             // all the same line\n\t\treturn token.NoPos, token.NoPos\n\t}\n\treturn open + 1, prevLineEnd\n}\n\n// commentsFoldingRange returns the folding ranges for all comment blocks in file.\n// The folding range starts at the end of the first line of the comment block, and ends at the end of the\n// comment block and has kind protocol.Comment.\nfunc commentsFoldingRange(pgf *parsego.File) (comments []protocol.FoldingRange) {\n\ttokFile := pgf.Tok\n\tfor _, commentGrp := range pgf.File.Comments {\n\t\tstartGrpLine, endGrpLine := safetoken.Line(tokFile, commentGrp.Pos()), safetoken.Line(tokFile, commentGrp.End())\n\t\tif startGrpLine == endGrpLine {\n\t\t\t// Don't fold single line comments.\n\t\t\tcontinue\n\t\t}\n\n\t\tfirstComment := commentGrp.List[0]\n\t\tstartPos, endLinePos := firstComment.Pos(), firstComment.End()\n\t\tstartCmmntLine, endCmmntLine := safetoken.Line(tokFile, startPos), safetoken.Line(tokFile, endLinePos)\n\t\tif startCmmntLine != endCmmntLine {\n\t\t\t// If the first comment spans multiple lines, then we want to have the\n\t\t\t// folding range start at the end of the first line.\n\t\t\tendLinePos = token.Pos(int(startPos) + len(strings.Split(firstComment.Text, \"\\n\")[0]))\n\t\t}\n\t\trng, err := pgf.PosRange(endLinePos, commentGrp.End())\n\t\tif err != nil {\n\t\t\tbug.Reportf(\"failed to create mapped range: %s\", err) // can't happen\n\t\t\tcontinue\n\t\t}\n\t\t// Fold from the end of the first line comment to the end of the comment block.\n\t\tcomments = append(comments, foldingRange(protocol.Comment, rng))\n\t}\n\treturn comments\n}\n\nfunc foldingRange(kind protocol.FoldingRangeKind, rng protocol.Range) protocol.FoldingRange {\n\treturn protocol.FoldingRange{\n\t\t// (I guess LSP doesn't use a protocol.Range here\n\t\t// because missing means something different from zero.)\n\t\tStartLine:      varOf(rng.Start.Line),\n\t\tStartCharacter: varOf(rng.Start.Character),\n\t\tEndLine:        varOf(rng.End.Line),\n\t\tEndCharacter:   varOf(rng.End.Character),\n\t\tKind:           string(kind),\n\t}\n}\n\n// varOf returns a new variable whose value is x.\nfunc varOf[T any](x T) *T { return &x }\n"
  },
  {
    "path": "gopls/internal/golang/format.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package golang defines the LSP features for navigation, analysis,\n// and refactoring of Go source code.\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strings\"\n\t\"text/scanner\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n\tgofumptFormat \"mvdan.cc/gofumpt/format\"\n)\n\n// Format formats a file with a given range.\nfunc Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.TextEdit, error) {\n\tctx, done := event.Start(ctx, \"golang.Format\")\n\tdefer done()\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Even if this file has parse errors, it might still be possible to format it.\n\t// Using format.Node on an AST with errors may result in code being modified.\n\t// Attempt to format the source of this file instead.\n\tif pgf.ParseErr != nil {\n\t\tformatted, err := formatSource(ctx, fh)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn computeTextEdits(ctx, pgf, string(formatted))\n\t}\n\n\t// format.Node changes slightly from one release to another, so the version\n\t// of Go used to build the LSP server will determine how it formats code.\n\t// This should be acceptable for all users, who likely be prompted to rebuild\n\t// the LSP server on each Go release.\n\tbuf := &bytes.Buffer{}\n\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\tif err := format.Node(buf, fset, pgf.File); err != nil {\n\t\treturn nil, err\n\t}\n\tformatted := buf.String()\n\n\t// Apply additional formatting, if any is supported. Currently, the only\n\t// supported additional formatter is gofumpt.\n\tif snapshot.Options().Gofumpt {\n\t\t// gofumpt can customize formatting based on language version and module\n\t\t// path, if available.\n\t\t//\n\t\t// Try to derive this information, but fall-back on the default behavior.\n\t\t//\n\t\t// TODO: under which circumstances can we fail to find module information?\n\t\t// Can this, for example, result in inconsistent formatting across saves,\n\t\t// due to pending calls to packages.Load?\n\t\tvar opts gofumptFormat.Options\n\t\tmeta, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI())\n\t\tif err == nil {\n\t\t\tif mi := meta.Module; mi != nil {\n\t\t\t\tif v := mi.GoVersion; v != \"\" {\n\t\t\t\t\topts.LangVersion = \"go\" + v\n\t\t\t\t}\n\t\t\t\topts.ModulePath = mi.Path\n\t\t\t}\n\t\t}\n\t\tb, err := gofumptFormat.Source(buf.Bytes(), opts)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tformatted = string(b)\n\t}\n\treturn computeTextEdits(ctx, pgf, formatted)\n}\n\nfunc formatSource(ctx context.Context, fh file.Handle) ([]byte, error) {\n\t_, done := event.Start(ctx, \"golang.formatSource\")\n\tdefer done()\n\n\tdata, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn format.Source(data)\n}\n\ntype importFix struct {\n\tfix   *imports.ImportFix\n\tedits []protocol.TextEdit\n}\n\n// allImportsFixes formats f for each possible fix to the imports.\n// In addition to returning the result of applying all edits,\n// it returns a list of fixes that could be applied to the file, with the\n// corresponding TextEdits that would be needed to apply that fix.\nfunc allImportsFixes(ctx context.Context, snapshot *cache.Snapshot, pgf *parsego.File) (allFixEdits []protocol.TextEdit, editsPerFix []*importFix, err error) {\n\tctx, done := event.Start(ctx, \"golang.allImportsFixes\")\n\tdefer done()\n\n\tif err := snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {\n\t\tallFixEdits, editsPerFix, err = computeImportEdits(ctx, pgf, snapshot, opts)\n\t\treturn err\n\t}); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"allImportsFixes: %v\", err)\n\t}\n\treturn allFixEdits, editsPerFix, nil\n}\n\n// computeImportEdits computes a set of edits that perform one or all of the\n// necessary import fixes.\nfunc computeImportEdits(ctx context.Context, pgf *parsego.File, snapshot *cache.Snapshot, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*importFix, err error) {\n\tgoroot := snapshot.View().Folder().Env.GOROOT\n\tfilename := pgf.URI.Path()\n\n\t// Build up basic information about the original file.\n\tisource, err := imports.NewProcessEnvSource(options.Env, filename, pgf.File.Name.Name)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tvar source imports.Source\n\n\t// Keep this in sync with [cache.Session.createView] (see the TODO there: we\n\t// should factor out the handling of the ImportsSource setting).\n\tswitch snapshot.Options().ImportsSource {\n\tcase settings.ImportsSourceGopls:\n\t\tsource = snapshot.NewGoplsSource(isource)\n\tcase settings.ImportsSourceOff: // for cider, which has no file system\n\t\tsource = nil\n\tcase settings.ImportsSourceGoimports:\n\t\tsource = isource\n\t}\n\t// imports require a current metadata graph\n\t// TODO(rfindley): improve the API\n\tsnapshot.WorkspaceMetadata(ctx) // ignore error\n\tallFixes, err := imports.FixImports(ctx, filename, pgf.Src, goroot, options.Env.Logf, source)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tallFixEdits, err = computeFixEdits(pgf.Src, options, allFixes)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Apply all of the import fixes to the file.\n\t// Add the edits for each fix to the result.\n\tfor _, fix := range allFixes {\n\t\tedits, err := computeFixEdits(pgf.Src, options, []*imports.ImportFix{fix})\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\teditsPerFix = append(editsPerFix, &importFix{\n\t\t\tfix:   fix,\n\t\t\tedits: edits,\n\t\t})\n\t}\n\treturn allFixEdits, editsPerFix, nil\n}\n\n// ComputeImportFixEdits returns text edits for a single import fix.\nfunc ComputeImportFixEdits(localPrefix string, src []byte, fixes ...*imports.ImportFix) ([]protocol.TextEdit, error) {\n\toptions := &imports.Options{\n\t\tLocalPrefix: localPrefix,\n\t\t// Defaults.\n\t\tAllErrors:  true,\n\t\tComments:   true,\n\t\tFragment:   true,\n\t\tFormatOnly: false,\n\t\tTabIndent:  true,\n\t\tTabWidth:   8,\n\t}\n\treturn computeFixEdits(src, options, fixes)\n}\n\nfunc computeFixEdits(src []byte, options *imports.Options, fixes []*imports.ImportFix) ([]protocol.TextEdit, error) {\n\t// trim the original data to match fixedData\n\tleft, err := importPrefix(src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\textra := !strings.Contains(left, \"\\n\") // one line may have more than imports\n\tif extra {\n\t\tleft = string(src)\n\t}\n\tif len(left) > 0 && left[len(left)-1] != '\\n' {\n\t\tleft += \"\\n\"\n\t}\n\t// Apply the fixes and re-parse the file so that we can locate the\n\t// new imports.\n\tflags := parser.ImportsOnly\n\tif extra {\n\t\t// used all of origData above, use all of it here too\n\t\tflags = 0\n\t}\n\tfixedData, err := imports.ApplyFixes(fixes, \"\", src, options, flags)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif fixedData == nil || fixedData[len(fixedData)-1] != '\\n' {\n\t\tfixedData = append(fixedData, '\\n') // ApplyFixes may miss the newline, go figure.\n\t}\n\tedits := diff.Strings(left, string(fixedData))\n\treturn protocolEditsFromSource([]byte(left), edits)\n}\n\n// importPrefix returns the prefix of the given file content through the final\n// import statement. If there are no imports, the prefix is the package\n// statement and any comment groups below it.\nfunc importPrefix(src []byte) (string, error) {\n\tfset := token.NewFileSet()\n\t// do as little parsing as possible\n\tf, err := parser.ParseFile(fset, \"\", src, parser.ImportsOnly|parser.ParseComments)\n\tif err != nil { // This can happen if 'package' is misspelled\n\t\treturn \"\", fmt.Errorf(\"importPrefix: failed to parse: %s\", err)\n\t}\n\ttok := fset.File(f.FileStart)\n\tvar importEnd int\n\tfor _, d := range f.Decls {\n\t\tif x, ok := d.(*ast.GenDecl); ok && x.Tok == token.IMPORT {\n\t\t\tif e, err := safetoken.Offset(tok, d.End()); err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"importPrefix: %s\", err)\n\t\t\t} else if e > importEnd {\n\t\t\t\timportEnd = e\n\t\t\t}\n\t\t}\n\t}\n\n\tmaybeAdjustToLineEnd := func(pos token.Pos, isCommentNode bool) int {\n\t\toffset, err := safetoken.Offset(tok, pos)\n\t\tif err != nil {\n\t\t\treturn -1\n\t\t}\n\n\t\t// Don't go past the end of the file.\n\t\tif offset > len(src) {\n\t\t\toffset = len(src)\n\t\t}\n\t\t// The go/ast package does not account for different line endings, and\n\t\t// specifically, in the text of a comment, it will strip out \\r\\n line\n\t\t// endings in favor of \\n. To account for these differences, we try to\n\t\t// return a position on the next line whenever possible.\n\t\tswitch line := safetoken.Line(tok, tok.Pos(offset)); {\n\t\tcase line < tok.LineCount():\n\t\t\tnextLineOffset, err := safetoken.Offset(tok, tok.LineStart(line+1))\n\t\t\tif err != nil {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\t// If we found a position that is at the end of a line, move the\n\t\t\t// offset to the start of the next line.\n\t\t\tif offset+1 == nextLineOffset {\n\t\t\t\toffset = nextLineOffset\n\t\t\t}\n\t\tcase isCommentNode, offset+1 == tok.Size():\n\t\t\t// If the last line of the file is a comment, or we are at the end\n\t\t\t// of the file, the prefix is the entire file.\n\t\t\toffset = len(src)\n\t\t}\n\t\treturn offset\n\t}\n\tif importEnd == 0 {\n\t\tpkgEnd := f.Name.End()\n\t\timportEnd = maybeAdjustToLineEnd(pkgEnd, false)\n\t}\n\tfor _, cgroup := range f.Comments {\n\t\tfor _, c := range cgroup.List {\n\t\t\tif end, err := safetoken.Offset(tok, c.End()); err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t} else if end > importEnd {\n\t\t\t\tstartLine := safetoken.Position(tok, c.Pos()).Line\n\t\t\t\tendLine := safetoken.Position(tok, c.End()).Line\n\n\t\t\t\t// Work around golang/go#41197 by checking if the comment might\n\t\t\t\t// contain \"\\r\", and if so, find the actual end position of the\n\t\t\t\t// comment by scanning the content of the file.\n\t\t\t\tstartOffset, err := safetoken.Offset(tok, c.Pos())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn \"\", err\n\t\t\t\t}\n\t\t\t\tif startLine != endLine && bytes.Contains(src[startOffset:], []byte(\"\\r\")) {\n\t\t\t\t\tif commentEnd := scanForCommentEnd(src[startOffset:]); commentEnd > 0 {\n\t\t\t\t\t\tend = startOffset + commentEnd\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\timportEnd = maybeAdjustToLineEnd(tok.Pos(end), true)\n\t\t\t}\n\t\t}\n\t}\n\tif importEnd > len(src) {\n\t\timportEnd = len(src)\n\t}\n\treturn string(src[:importEnd]), nil\n}\n\n// scanForCommentEnd returns the offset of the end of the multi-line comment\n// at the start of the given byte slice.\nfunc scanForCommentEnd(src []byte) int {\n\tvar s scanner.Scanner\n\ts.Init(bytes.NewReader(src))\n\ts.Mode ^= scanner.SkipComments\n\n\tt := s.Scan()\n\tif t == scanner.Comment {\n\t\treturn s.Pos().Offset\n\t}\n\treturn 0\n}\n\nfunc computeTextEdits(ctx context.Context, pgf *parsego.File, formatted string) ([]protocol.TextEdit, error) {\n\t_, done := event.Start(ctx, \"golang.computeTextEdits\")\n\tdefer done()\n\n\tedits := diff.Strings(string(pgf.Src), formatted)\n\treturn protocol.EditsFromDiffEdits(pgf.Mapper, edits)\n}\n\n// protocolEditsFromSource converts text edits to LSP edits using the original\n// source.\nfunc protocolEditsFromSource(src []byte, edits []diff.Edit) ([]protocol.TextEdit, error) {\n\tm := protocol.NewMapper(\"\", src)\n\tvar result []protocol.TextEdit\n\tfor _, edit := range edits {\n\t\trng, err := m.OffsetRange(edit.Start, edit.End)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif rng.Start == rng.End && edit.New == \"\" {\n\t\t\t// Degenerate case, which may result from a diff tool wanting to delete\n\t\t\t// '\\r' in line endings. Filter it out.\n\t\t\tcontinue\n\t\t}\n\t\tresult = append(result, protocol.TextEdit{\n\t\t\tRange:   rng,\n\t\t\tNewText: edit.New,\n\t\t})\n\t}\n\treturn result, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/format_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n)\n\nfunc TestImportPrefix(t *testing.T) {\n\tfor i, tt := range []struct {\n\t\tinput, want string\n\t}{\n\t\t{\"package foo\", \"package foo\"},\n\t\t{\"package foo\\n\", \"package foo\\n\"},\n\t\t{\"package foo\\n\\nfunc f(){}\\n\", \"package foo\\n\"},\n\t\t{\"package foo\\n\\nimport \\\"fmt\\\"\\n\", \"package foo\\n\\nimport \\\"fmt\\\"\"},\n\t\t{\"package foo\\nimport (\\n\\\"fmt\\\"\\n)\\n\", \"package foo\\nimport (\\n\\\"fmt\\\"\\n)\"},\n\t\t{\"\\n\\n\\npackage foo\\n\", \"\\n\\n\\npackage foo\\n\"},\n\t\t{\"// hi \\n\\npackage foo //xx\\nfunc _(){}\\n\", \"// hi \\n\\npackage foo //xx\\n\"},\n\t\t{\"package foo //hi\\n\", \"package foo //hi\\n\"},\n\t\t{\"//hi\\npackage foo\\n//a\\n\\n//b\\n\", \"//hi\\npackage foo\\n//a\\n\\n//b\\n\"},\n\t\t{\n\t\t\t\"package a\\n\\nimport (\\n  \\\"fmt\\\"\\n)\\n//hi\\n\",\n\t\t\t\"package a\\n\\nimport (\\n  \\\"fmt\\\"\\n)\\n//hi\\n\",\n\t\t},\n\t\t{`package a /*hi*/`, `package a /*hi*/`},\n\t\t{\"package main\\r\\n\\r\\nimport \\\"go/types\\\"\\r\\n\\r\\n/*\\r\\n\\r\\n */\\r\\n\", \"package main\\r\\n\\r\\nimport \\\"go/types\\\"\\r\\n\\r\\n/*\\r\\n\\r\\n */\\r\\n\"},\n\t\t{\"package x; import \\\"os\\\"; func f() {}\\n\\n\", \"package x; import \\\"os\\\"\"},\n\t\t{\"package x; func f() {fmt.Println()}\\n\\n\", \"package x\"},\n\t} {\n\t\tgot, err := importPrefix([]byte(tt.input))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif d := compare.Text(tt.want, got); d != \"\" {\n\t\t\tt.Errorf(\"%d: failed for %q:\\n%s\", i, tt.input, d)\n\t\t}\n\t}\n}\n\nfunc TestCRLFFile(t *testing.T) {\n\tfor i, tt := range []struct {\n\t\tinput, want string\n\t}{\n\t\t{\n\t\t\tinput: `package main\n\n/*\nHi description\n*/\nfunc Hi() {\n}\n`,\n\t\t\twant: `package main\n\n/*\nHi description\n*/`,\n\t\t},\n\t} {\n\t\tgot, err := importPrefix([]byte(strings.ReplaceAll(tt.input, \"\\n\", \"\\r\\n\")))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twant := strings.ReplaceAll(tt.want, \"\\n\", \"\\r\\n\")\n\t\tif d := compare.Text(want, got); d != \"\" {\n\t\t\tt.Errorf(\"%d: failed for %q:\\n%s\", i, tt.input, d)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/freesymbols.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file implements the \"Browse free symbols\" code action.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"html\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// FreeSymbolsHTML returns an HTML document containing the report of\n// free symbols referenced by the selection.\nfunc FreeSymbolsHTML(viewID string, pkg *cache.Package, pgf *parsego.File, start, end token.Pos, web Web) []byte {\n\n\t// Compute free references.\n\trefs := freeRefs(pkg.Types(), pkg.TypesInfo(), pgf.File, start, end)\n\n\t// -- model --\n\n\ttype Import struct {\n\t\tPath    metadata.PackagePath\n\t\tSymbols []string\n\t}\n\ttype Symbol struct {\n\t\tKind string\n\t\tType string\n\t\tRefs []types.Object\n\t}\n\tvar model struct {\n\t\tImported []Import\n\t\tPkgLevel []Symbol\n\t\tLocal    []Symbol\n\t}\n\n\tqualifier := typesinternal.NameRelativeTo(pkg.Types())\n\n\t// Populate model.\n\t{\n\t\t// List the refs in order of dotted paths.\n\t\tsort.Slice(refs, func(i, j int) bool {\n\t\t\treturn refs[i].dotted < refs[j].dotted\n\t\t})\n\n\t\t// Inspect the references.\n\t\timported := make(map[string][]*freeRef) // refs to imported symbols, by package path\n\t\tseen := make(map[string]bool)           // to de-dup dotted paths\n\t\tfor _, ref := range refs {\n\t\t\tif seen[ref.dotted] {\n\t\t\t\tcontinue // de-dup\n\t\t\t}\n\t\t\tseen[ref.dotted] = true\n\n\t\t\tvar symbols *[]Symbol\n\t\t\tswitch ref.scope {\n\t\t\tcase \"file\":\n\t\t\t\t// imported symbol: group by package\n\t\t\t\tif pkgname, ok := ref.objects[0].(*types.PkgName); ok {\n\t\t\t\t\tpath := pkgname.Imported().Path()\n\t\t\t\t\timported[path] = append(imported[path], ref)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\tcase \"pkg\":\n\t\t\t\tsymbols = &model.PkgLevel\n\t\t\tcase \"local\":\n\t\t\t\tsymbols = &model.Local\n\t\t\tdefault:\n\t\t\t\tpanic(ref.scope)\n\t\t\t}\n\n\t\t\t// Package and local symbols are presented the same way.\n\t\t\t// We treat each dotted path x.y.z as a separate entity.\n\n\t\t\t// Compute kind and type of last object (y in obj.x.y).\n\t\t\ttypestr := \" \" + types.TypeString(ref.typ, qualifier)\n\t\t\tvar kind string\n\t\t\tswitch obj := ref.objects[len(ref.objects)-1].(type) {\n\t\t\tcase *types.Var:\n\t\t\t\tkind = \"var\"\n\t\t\tcase *types.Func:\n\t\t\t\tkind = \"func\"\n\t\t\tcase *types.TypeName:\n\t\t\t\tif is[*types.TypeParam](obj.Type()) {\n\t\t\t\t\tkind = \"type parameter\"\n\t\t\t\t} else {\n\t\t\t\t\tkind = \"type\"\n\t\t\t\t}\n\t\t\t\ttypestr = \"\" // avoid \"type T T\"\n\t\t\tcase *types.Const:\n\t\t\t\tkind = \"const\"\n\t\t\tcase *types.Label:\n\t\t\t\tkind = \"label\"\n\t\t\t\ttypestr = \"\" // avoid \"label L L\"\n\t\t\t}\n\n\t\t\t*symbols = append(*symbols, Symbol{\n\t\t\t\tKind: kind,\n\t\t\t\tType: typestr,\n\t\t\t\tRefs: ref.objects,\n\t\t\t})\n\t\t}\n\n\t\t// Imported symbols.\n\t\t// Produce one record per package, with a list of symbols.\n\t\tfor pkgPath, refs := range moremaps.Sorted(imported) {\n\t\t\tvar syms []string\n\t\t\tfor _, ref := range refs {\n\t\t\t\t// strip package name (bytes.Buffer.Len -> Buffer.Len)\n\t\t\t\tsyms = append(syms, ref.dotted[len(ref.objects[0].Name())+len(\".\"):])\n\t\t\t}\n\t\t\tsort.Strings(syms)\n\t\t\tconst max = 4\n\t\t\tif len(syms) > max {\n\t\t\t\tsyms[max-1] = fmt.Sprintf(\"... (%d)\", len(syms))\n\t\t\t\tsyms = syms[:max]\n\t\t\t}\n\n\t\t\tmodel.Imported = append(model.Imported, Import{\n\t\t\t\tPath:    PackagePath(pkgPath),\n\t\t\t\tSymbols: syms,\n\t\t\t})\n\t\t}\n\t}\n\n\t// -- presentation --\n\n\tvar buf bytes.Buffer\n\tbuf.WriteString(`<!DOCTYPE html>\n<html>\n<head>\n<style>\n.col-pkg { color: #2eb007 }\n.col-file { color: #a10b15 }\n.col-local { color: #0cb7c9 }\nli { font-family: monospace; }\np { max-width: 6in; }\n</style>\n  <script src=\"/assets/common.js\"></script>\n  <link rel=\"stylesheet\" href=\"/assets/common.css\">\n</head>\n<body>\n<h1>Free symbols</h1>\n<p>\n  The selected code contains references to these free* symbols:\n</p>\n`)\n\n\t// Present the refs in three sections: imported, same package, local.\n\n\t// -- imported symbols --\n\n\t// Show one item per package, with a list of symbols.\n\tfmt.Fprintf(&buf, \"<h2><span class='col-file'>⬤</span> Imported symbols</h2>\\n\")\n\tfmt.Fprintf(&buf, \"<ul>\\n\")\n\tfor _, imp := range model.Imported {\n\t\tfmt.Fprintf(&buf, \"<li>import \\\"<a href='%s'>%s</a>\\\" // for %s</li>\\n\",\n\t\t\tweb.PkgURL(viewID, imp.Path, \"\"),\n\t\t\thtml.EscapeString(string(imp.Path)),\n\t\t\tstrings.Join(imp.Symbols, \", \"))\n\t}\n\tif len(model.Imported) == 0 {\n\t\tfmt.Fprintf(&buf, \"<li>(none)</li>\\n\")\n\t}\n\tbuf.WriteString(\"</ul>\\n\")\n\n\t// -- package and local symbols --\n\n\tshowSymbols := func(scope, title string, symbols []Symbol) {\n\t\tfmt.Fprintf(&buf, \"<h2><span class='col-%s'>⬤</span> %s</h2>\\n\", scope, title)\n\t\tfmt.Fprintf(&buf, \"<ul>\\n\")\n\t\tpre := buf.Len()\n\t\tfor _, sym := range symbols {\n\t\t\tfmt.Fprintf(&buf, \"<li>%s \", sym.Kind) // of rightmost symbol in dotted path\n\t\t\tfor i, obj := range sym.Refs {\n\t\t\t\tif i > 0 {\n\t\t\t\t\tbuf.WriteByte('.')\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(objHTML(pkg.FileSet(), web, obj))\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \" %s</li>\\n\", html.EscapeString(sym.Type))\n\t\t}\n\t\tif buf.Len() == pre {\n\t\t\tfmt.Fprintf(&buf, \"<li>(none)</li>\\n\")\n\t\t}\n\t\tbuf.WriteString(\"</ul>\\n\")\n\t}\n\tshowSymbols(\"pkg\", \"Package-level symbols\", model.PkgLevel)\n\tshowSymbols(\"local\", \"Local symbols\", model.Local)\n\n\t// -- code selection --\n\n\t// Print the selection, highlighting references to free symbols.\n\tbuf.WriteString(\"<hr/>\\n\")\n\tsort.Slice(refs, func(i, j int) bool {\n\t\treturn refs[i].expr.Pos() < refs[j].expr.Pos()\n\t})\n\tpos := start\n\temitTo := func(end token.Pos) {\n\t\tif pos < end {\n\t\t\tfileStart := pgf.File.FileStart\n\t\t\ttext := pgf.Mapper.Content[pos-fileStart : end-fileStart]\n\t\t\tbuf.WriteString(html.EscapeString(string(text)))\n\t\t\tpos = end\n\t\t}\n\t}\n\tbuf.WriteString(`<pre>`)\n\tfor _, ref := range refs {\n\t\temitTo(ref.expr.Pos())\n\t\tfmt.Fprintf(&buf, `<b class='col-%s'>`, ref.scope)\n\t\temitTo(ref.expr.End())\n\t\tbuf.WriteString(`</b>`)\n\t}\n\temitTo(end)\n\tbuf.WriteString(`</pre>\n<hr>\n<p>\n  *A symbol is \"free\" if it is referenced within the selection but declared\n  outside of it.\n\n  The free variables are approximately the set of parameters that\n  would be needed if the block were extracted into its own function in\n  the same package.\n\n  Free identifiers may include local types and control labels as well.\n\n  Even when you don't intend to extract a block into a new function,\n  this information can help you to tell at a glance what names a block\n  of code depends on.\n</p>\n<p>\n  Each dotted path of identifiers (such as file.Name.Pos) is reported\n  as a separate item, so that you can see which parts of a complex\n  type are actually needed.\n\n  The free symbols referenced by the body of a function may\n  reveal that only a small part (a single field of a struct, say) of\n  one of the function's parameters is used, allowing you to simplify\n  and generalize the function by choosing a different type for that\n  parameter.\n</p>\n`)\n\treturn buf.Bytes()\n}\n\n// A freeRef records a reference to a dotted path obj.x.y,\n// where obj (=objects[0]) is a free symbol.\ntype freeRef struct {\n\tobjects []types.Object // [obj x y]\n\tdotted  string         // \"obj.x.y\"  (used as sort key)\n\tscope   string         // scope of obj: pkg|file|local\n\texpr    ast.Expr       // =*Ident|*SelectorExpr\n\ttyp     types.Type     // type of obj.x.y\n}\n\n// freeRefs returns the list of references to free symbols (from\n// within the selection to a symbol declared outside of it).\n// It uses only info.{Scopes,Types,Uses}.\nfunc freeRefs(pkg *types.Package, info *types.Info, file *ast.File, start, end token.Pos) []*freeRef {\n\t// Keep us honest about which fields we access.\n\tinfo = &types.Info{\n\t\tScopes: info.Scopes,\n\t\tTypes:  info.Types,\n\t\tUses:   info.Uses,\n\t}\n\n\tfileScope := info.Scopes[file]\n\tpkgScope := fileScope.Parent()\n\n\t// id is called for the leftmost id x in each dotted chain such as (x.y).z.\n\t// suffix is the reversed suffix of selections (e.g. [z y]).\n\tid := func(n *ast.Ident, suffix []types.Object) *freeRef {\n\t\tobj := info.Uses[n]\n\t\tif obj == nil {\n\t\t\treturn nil // not a reference\n\t\t}\n\t\tif start <= obj.Pos() && obj.Pos() < end {\n\t\t\treturn nil // defined within selection => not free\n\t\t}\n\t\tparent := obj.Parent()\n\n\t\t// Compute dotted path.\n\t\tobjects := append(suffix, obj)\n\t\tif obj.Pkg() != nil && obj.Pkg() != pkg && typesinternal.IsPackageLevel(obj) { // dot import\n\t\t\t// Synthesize the implicit PkgName.\n\t\t\tpkgName := types.NewPkgName(token.NoPos, pkg, obj.Pkg().Name(), obj.Pkg())\n\t\t\tparent = fileScope\n\t\t\tobjects = append(objects, pkgName)\n\t\t}\n\t\tslices.Reverse(objects)\n\t\tvar dotted strings.Builder\n\t\tfor i, obj := range objects {\n\t\t\tif obj == nil {\n\t\t\t\treturn nil // type error\n\t\t\t}\n\t\t\tif i > 0 {\n\t\t\t\tdotted.WriteByte('.')\n\t\t\t}\n\t\t\tdotted.WriteString(obj.Name())\n\t\t}\n\n\t\t// Compute scope of base object.\n\t\tvar scope string\n\t\tswitch parent {\n\t\tcase nil:\n\t\t\treturn nil // interface method or struct field\n\t\tcase types.Universe:\n\t\t\treturn nil // built-in (not interesting)\n\t\tcase fileScope:\n\t\t\tscope = \"file\" // defined at file scope (imported package)\n\t\tcase pkgScope:\n\t\t\tscope = \"pkg\" // defined at package level\n\t\tdefault:\n\t\t\tscope = \"local\" // defined within current function\n\t\t}\n\n\t\treturn &freeRef{\n\t\t\tobjects: objects,\n\t\t\tdotted:  dotted.String(),\n\t\t\tscope:   scope,\n\t\t}\n\t}\n\n\t// sel(x.y.z, []) calls sel(x.y, [z]) calls id(x, [z, y]).\n\tsel := func(sel *ast.SelectorExpr, suffix []types.Object) *freeRef {\n\t\tfor {\n\t\t\tsuffix = append(suffix, info.Uses[sel.Sel])\n\n\t\t\tswitch x := ast.Unparen(sel.X).(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\treturn id(x, suffix)\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\tcase *ast.SelectorExpr:\n\t\t\t\tsel = x\n\t\t\t}\n\t\t}\n\t}\n\n\t// Visit all the identifiers in the selected ASTs.\n\tvar free []*freeRef\n\tpath, _ := astutil.PathEnclosingInterval(file, start, end)\n\tvar visit func(n ast.Node) bool\n\tvisit = func(n ast.Node) bool {\n\t\t// Is this node contained within the selection?\n\t\t// (freesymbols permits inexact selections,\n\t\t// like two stmts in a block.)\n\t\tif n != nil && start <= n.Pos() && n.End() <= end {\n\t\t\tvar ref *freeRef\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\tref = id(n, nil)\n\t\t\tcase *ast.SelectorExpr:\n\t\t\t\tref = sel(n, nil)\n\t\t\t}\n\n\t\t\tif ref != nil {\n\t\t\t\tref.expr = n.(ast.Expr)\n\t\t\t\tif tv, ok := info.Types[ref.expr]; ok {\n\t\t\t\t\tref.typ = tv.Type\n\t\t\t\t} else {\n\t\t\t\t\tref.typ = types.Typ[types.Invalid]\n\t\t\t\t}\n\t\t\t\tfree = append(free, ref)\n\t\t\t}\n\n\t\t\t// After visiting x.sel, don't descend into sel.\n\t\t\t// Descend into x only if we didn't get a ref for x.sel.\n\t\t\tif sel, ok := n.(*ast.SelectorExpr); ok {\n\t\t\t\tif ref == nil {\n\t\t\t\t\tast.Inspect(sel.X, visit)\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t\treturn true // descend\n\t}\n\tast.Inspect(path[0], visit)\n\treturn free\n}\n\n// objHTML returns HTML for obj.Name(), possibly marked up as a link\n// to the web server that, when visited, opens the declaration in the\n// client editor.\nfunc objHTML(fset *token.FileSet, web Web, obj types.Object) string {\n\ttext := obj.Name()\n\tif posn := safetoken.StartPosition(fset, obj.Pos()); posn.IsValid() {\n\t\turl := web.SrcURL(posn.Filename, posn.Line, posn.Column)\n\t\treturn sourceLink(text, url)\n\t}\n\treturn text\n}\n\n// sourceLink returns HTML for a link to open a file in the client editor.\nfunc sourceLink(text, url string) string {\n\t// The /src URL returns nothing but has the side effect\n\t// of causing the LSP client to open the requested file.\n\t// So we use onclick to prevent the browser from navigating.\n\t// We keep the href attribute as it causes the <a> to render\n\t// as a link: blue, underlined, with URL hover information.\n\treturn fmt.Sprintf(`<a href=\"%[1]s\" onclick='return httpGET(\"%[1]s\")'>%[2]s</a>`,\n\t\thtml.EscapeString(url), text)\n}\n"
  },
  {
    "path": "gopls/internal/golang/freesymbols_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\n// TestFreeRefs is a unit test of the free-references algorithm.\nfunc TestFreeRefs(t *testing.T) {\n\tif runtime.GOOS == \"js\" || runtime.GOARCH == \"wasm\" {\n\t\tt.Skip(\"some test imports are unsupported on js or wasm\")\n\t}\n\n\tfor i, test := range []struct {\n\t\tsrc  string\n\t\twant []string // expected list of \"scope kind dotted-path\" triples\n\t}{\n\t\t{\n\t\t\t// basic example (has a \"cannot infer\" type error)\n\t\t\t`package p; func f[T ~int](x any) { var y T; « f(x.(T) + y) » }`,\n\t\t\t[]string{\"pkg func f\", \"local var x\", \"local typename T\", \"local var y\"},\n\t\t},\n\t\t{\n\t\t\t// selection need not be tree-aligned\n\t\t\t`package p; type T int; type U « T; func _(x U) »`,\n\t\t\t[]string{\"pkg typename T\", \"pkg typename U\"},\n\t\t},\n\t\t{\n\t\t\t// imported symbols\n\t\t\t`package p; import \"fmt\"; func f() { « var x fmt.Stringer » }`,\n\t\t\t[]string{\"file pkgname fmt.Stringer\"},\n\t\t},\n\t\t{\n\t\t\t// unsafe and error, our old nemeses\n\t\t\t`package p; import \"unsafe\"; var ( « _  unsafe.Pointer; _ = error(nil).Error »; )`,\n\t\t\t[]string{\"file pkgname unsafe.Pointer\"},\n\t\t},\n\t\t{\n\t\t\t// two attributes of a var, but not the var itself\n\t\t\t`package p; import \"bytes\"; func _(buf bytes.Buffer) { « buf.WriteByte(0); buf.WriteString(\"\"); » }`,\n\t\t\t[]string{\"local var buf.WriteByte\", \"local var buf.WriteString\"},\n\t\t},\n\t\t{\n\t\t\t// dot imports (an edge case)\n\t\t\t`package p; import . \"errors\"; var _ = « New»`,\n\t\t\t[]string{\"file pkgname errors.New\"},\n\t\t},\n\t\t{\n\t\t\t// struct field (regression test for overzealous dot import logic)\n\t\t\t`package p; import \"net/url\"; var _ = «url.URL{Host: \"\"}»`,\n\t\t\t[]string{\"file pkgname url.URL\"},\n\t\t},\n\t\t{\n\t\t\t// dot imports (another regression test of same)\n\t\t\t`package p; import . \"net/url\"; var _ = «URL{Host: \"\"}»`,\n\t\t\t[]string{\"file pkgname url.URL\"},\n\t\t},\n\t\t{\n\t\t\t// dot import of unsafe (a corner case)\n\t\t\t`package p; import . \"unsafe\"; var _ « Pointer»`,\n\t\t\t[]string{\"file pkgname unsafe.Pointer\"},\n\t\t},\n\t\t{\n\t\t\t// dotted path\n\t\t\t`package p; import \"go/build\"; var _ = « build.Default.GOOS »`,\n\t\t\t[]string{\"file pkgname build.Default.GOOS\"},\n\t\t},\n\t\t{\n\t\t\t// type error\n\t\t\t`package p; import \"nope\"; var _ = « nope.nope.nope »`,\n\t\t\t[]string{\"file pkgname nope\"},\n\t\t},\n\t} {\n\t\tname := fmt.Sprintf(\"file%d.go\", i)\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tstartOffset := strings.Index(test.src, \"«\")\n\t\t\tendOffset := strings.Index(test.src, \"»\")\n\t\t\tif startOffset < 0 || endOffset < startOffset {\n\t\t\t\tt.Fatalf(\"invalid «...» selection (%d:%d)\", startOffset, endOffset)\n\t\t\t}\n\t\t\tsrc := test.src[:startOffset] +\n\t\t\t\t\" \" +\n\t\t\t\ttest.src[startOffset+len(\"«\"):endOffset] +\n\t\t\t\t\" \" +\n\t\t\t\ttest.src[endOffset+len(\"»\"):]\n\t\t\tf, err := parser.ParseFile(fset, name, src, parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tconf := &types.Config{\n\t\t\t\tImporter: importer.Default(),\n\t\t\t\tError:    func(err error) { t.Log(err) }, // not fatal\n\t\t\t}\n\t\t\tinfo := &types.Info{\n\t\t\t\tUses:   make(map[*ast.Ident]types.Object),\n\t\t\t\tScopes: make(map[ast.Node]*types.Scope),\n\t\t\t\tTypes:  make(map[ast.Expr]types.TypeAndValue),\n\t\t\t}\n\t\t\tpkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, info) // ignore errors\n\t\t\ttf := fset.File(f.Package)\n\t\t\trefs := freeRefs(pkg, info, f, tf.Pos(startOffset), tf.Pos(endOffset))\n\n\t\t\tkind := func(obj types.Object) string { // e.g. \"var\", \"const\"\n\t\t\t\treturn strings.ToLower(reflect.TypeOf(obj).Elem().Name())\n\t\t\t}\n\n\t\t\tvar got []string\n\t\t\tfor _, ref := range refs {\n\t\t\t\tmsg := ref.scope + \" \" + kind(ref.objects[0]) + \" \" + ref.dotted\n\t\t\t\tgot = append(got, msg)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(test.want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"(-want +got)\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/highlight.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/fmtstr\"\n\t\"golang.org/x/tools/internal/moreiters\"\n)\n\nfunc Highlight(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.DocumentHighlight, error) {\n\tctx, done := event.Start(ctx, \"golang.Highlight\")\n\tdefer done()\n\n\t// We always want fully parsed files for highlight, regardless\n\t// of whether the file belongs to a workspace package.\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting package for Highlight: %w\", err)\n\t}\n\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcur, _, _, _ := astutil.Select(pgf.Cursor(), start, end) // can't fail: pgf contains pos\n\n\tresult, err := highlightPath(pkg.TypesInfo(), cur, start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar ranges []protocol.DocumentHighlight\n\tfor rng, kind := range result {\n\t\trng, err := pgf.NodeRange(rng)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tranges = append(ranges, protocol.DocumentHighlight{\n\t\t\tRange: rng,\n\t\t\tKind:  kind,\n\t\t})\n\t}\n\treturn ranges, nil\n}\n\n// highlightPath returns ranges to highlight for the given the cursor.\nfunc highlightPath(info *types.Info, cur inspector.Cursor, start, end token.Pos) (map[astutil.Range]protocol.DocumentHighlightKind, error) {\n\tresult := make(map[astutil.Range]protocol.DocumentHighlightKind)\n\n\t// Inside a call to a printf-like function (as identified\n\t// by a simple heuristic).\n\t// Treat each corresponding (\"%v\", arg) pair as a highlight class.\n\tfor node := range cur.Enclosing((*ast.CallExpr)(nil)) {\n\t\tcall := node.Node().(*ast.CallExpr)\n\t\tlit, idx := formatStringAndIndex(info, call)\n\t\tif idx != -1 {\n\t\t\thighlightPrintf(call, idx, start, end, lit, result)\n\t\t}\n\t}\n\n\tswitch node := cur.Node().(type) {\n\tcase *ast.BasicLit:\n\t\t// Import path string literal?\n\t\tif imp, ok := cur.Parent().Node().(*ast.ImportSpec); ok {\n\t\t\thighlight := func(n ast.Node) {\n\t\t\t\thighlightNode(result, n, protocol.Text)\n\t\t\t}\n\n\t\t\t// Highlight the import itself...\n\t\t\thighlight(imp)\n\n\t\t\t// ...and all references to it in the file.\n\t\t\tif pkgname := info.PkgNameOf(imp); pkgname != nil {\n\t\t\t\t_, curFile := cursorutil.FirstEnclosing[*ast.File](cur)\n\t\t\t\tfor c := range curFile.Preorder((*ast.Ident)(nil)) {\n\t\t\t\t\tif id := c.Node().(*ast.Ident); info.Uses[id] == pkgname {\n\t\t\t\t\t\thighlight(id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result, nil\n\t\t}\n\t\thighlightFuncControlFlow(cur, result)\n\tcase *ast.ReturnStmt, *ast.FuncDecl, *ast.FuncType:\n\t\thighlightFuncControlFlow(cur, result)\n\tcase *ast.Ident:\n\t\t// Check if ident is inside return or func decl.\n\t\thighlightFuncControlFlow(cur, result)\n\t\thighlightIdentifier(cur, info, result)\n\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\tvar label *ast.Ident\n\t\tif l, ok := cur.Parent().Node().(*ast.LabeledStmt); ok {\n\t\t\tlabel = l.Label\n\t\t}\n\t\thighlightLoopControlFlow(node, label, info, result)\n\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt:\n\t\tvar label *ast.Ident\n\t\tif l, ok := cur.Parent().Node().(*ast.LabeledStmt); ok {\n\t\t\tlabel = l.Label\n\t\t}\n\t\thighlightSwitchFlow(node, label, info, result)\n\tcase *ast.BranchStmt:\n\t\t// BREAK can exit a loop, switch or select, while CONTINUE exit a loop so\n\t\t// these need to be handled separately. They can also be embedded in any\n\t\t// other loop/switch/select if they have a label. TODO: add support for\n\t\t// GOTO and FALLTHROUGH as well.\n\t\tswitch node.Tok {\n\t\tcase token.BREAK:\n\t\t\tif node.Label != nil {\n\t\t\t\thighlightLabeledFlow(cur, info, result)\n\t\t\t} else {\n\t\t\t\thighlightUnlabeledBreakFlow(cur, info, result)\n\t\t\t}\n\t\tcase token.CONTINUE:\n\t\t\tif node.Label != nil {\n\t\t\t\thighlightLabeledFlow(cur, info, result)\n\t\t\t} else {\n\t\t\t\tvar (\n\t\t\t\t\tstmt  ast.Node\n\t\t\t\t\tlabel *ast.Ident\n\t\t\t\t)\n\t\t\t\tif curLoop, ok := moreiters.First(cur.Enclosing((*ast.ForStmt)(nil), (*ast.RangeStmt)(nil))); ok {\n\t\t\t\t\tstmt = curLoop.Node()\n\t\t\t\t\tif l, ok := curLoop.Parent().Node().(*ast.LabeledStmt); ok {\n\t\t\t\t\t\tlabel = l.Label\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\thighlightLoopControlFlow(stmt, label, info, result)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// formatStringAndIndex returns the BasicLit and index of the BasicLit (the last\n// non-variadic parameter) within the given printf-like call\n// expression, returns -1 as index if unknown.\nfunc formatStringAndIndex(info *types.Info, call *ast.CallExpr) (*ast.BasicLit, int) {\n\ttyp := info.Types[call.Fun].Type\n\tif typ == nil {\n\t\treturn nil, -1 // missing type\n\t}\n\tsig, ok := typ.(*types.Signature)\n\tif !ok {\n\t\treturn nil, -1 // ill-typed\n\t}\n\tif !sig.Variadic() {\n\t\t// Skip checking non-variadic functions.\n\t\treturn nil, -1\n\t}\n\tidx := sig.Params().Len() - 2\n\tif !(0 <= idx && idx < len(call.Args)) {\n\t\t// Skip checking functions without a format string parameter, or\n\t\t// missing the corresponding format argument.\n\t\treturn nil, -1\n\t}\n\t// We only care about literal format strings, so fmt.Sprint(\"a\"+\"b%s\", \"bar\") won't be highlighted.\n\tif lit, ok := call.Args[idx].(*ast.BasicLit); ok && lit.Kind == token.STRING {\n\t\treturn lit, idx\n\t}\n\treturn nil, -1\n}\n\n// highlightPrintf highlights operations in a format string and their\n// corresponding variadic arguments in a (possible) printf-style function call.\n// For example:\n//\n// fmt.Printf(\"Hello %s, you scored %d\", name, score)\n//\n// If the cursor is on %s or name, it will highlight %s as a write operation,\n// and name as a read operation.\nfunc highlightPrintf(call *ast.CallExpr, idx int, start, end token.Pos, lit *ast.BasicLit, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\tformat, err := strconv.Unquote(lit.Value)\n\tif err != nil {\n\t\treturn\n\t}\n\tif !strings.Contains(format, \"%\") {\n\t\treturn\n\t}\n\toperations, err := fmtstr.Parse(format, idx)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// fmt.Printf(\"%[1]d %[1].2d\", 3)\n\t//\n\t// When cursor is in `%[1]d`, we record `3` being successfully highlighted.\n\t// And because we will also record `%[1].2d`'s corresponding arguments index is `3`\n\t// in `visited`, even though it will not highlight any item in the first pass,\n\t// in the second pass we can correctly highlight it. So the three are the same class.\n\tsucceededArg := 0\n\tvisited := make(map[astutil.Range]int, 0)\n\n\t// highlightPair highlights the operation and its potential argument pair if the cursor is within either range.\n\thighlightPair := func(rang fmtstr.Range, argIndex int) {\n\t\tvar (\n\t\t\trng       astutil.Range\n\t\t\twithinRng bool\n\t\t)\n\t\trng, err = astutil.RangeInStringLiteral(lit, rang.Start, rang.End)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tvisited[rng] = argIndex\n\n\t\tif start == end {\n\t\t\t// End pos can't equal to range's end, otherwise the two neighborhood\n\t\t\t// such as (%[2]*d) are both highlighted if cursor in \"d\" (ending of [2]*).\n\t\t\twithinRng = rng.Start <= start && end < rng.End()\n\t\t} else {\n\t\t\t// With a non-empty selection, there is no ambiguity.\n\t\t\twithinRng = rng.Contains(astutil.RangeOf(start, end))\n\t\t}\n\n\t\tvar (\n\t\t\targ       ast.Expr\n\t\t\twithinArg bool\n\t\t)\n\t\tif argIndex < len(call.Args) {\n\t\t\targ = call.Args[argIndex]\n\t\t\twithinArg = astutil.NodeContains(arg, astutil.RangeOf(start, end))\n\t\t}\n\n\t\tif withinRng || withinArg {\n\t\t\thighlightRange(result, rng, protocol.Write)\n\t\t\tif arg != nil {\n\t\t\t\tsucceededArg = argIndex\n\t\t\t\thighlightNode(result, arg, protocol.Read)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, op := range operations {\n\t\t// If width or prec has any *, we can not highlight the full range from % to verb,\n\t\t// because it will overlap with the sub-range of *, for example:\n\t\t//\n\t\t// fmt.Printf(\"%*[3]d\", 4, 5, 6)\n\t\t//               ^  ^ we can only highlight this range when cursor in 6. '*' as a one-rune range will\n\t\t//               highlight for 4.\n\t\thasAsterisk := false\n\n\t\t// Try highlight Width if there is a *.\n\t\tif op.Width.Dynamic != -1 {\n\t\t\thasAsterisk = true\n\t\t\thighlightPair(op.Width.Range, op.Width.Dynamic)\n\t\t}\n\n\t\t// Try highlight Precision if there is a *.\n\t\tif op.Prec.Dynamic != -1 {\n\t\t\thasAsterisk = true\n\t\t\thighlightPair(op.Prec.Range, op.Prec.Dynamic)\n\t\t}\n\n\t\t// Try highlight Verb.\n\t\tif op.Verb.Verb != '%' {\n\t\t\t// If any * is found inside operation, narrow the highlight range.\n\t\t\tif hasAsterisk {\n\t\t\t\thighlightPair(op.Verb.Range, op.Verb.ArgIndex)\n\t\t\t} else {\n\t\t\t\thighlightPair(op.Range, op.Verb.ArgIndex)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass, try to highlight those missed operations.\n\tfor rng, argIndex := range visited {\n\t\tif succeededArg == argIndex {\n\t\t\thighlightRange(result, rng, protocol.Write)\n\t\t}\n\t}\n}\n\n// highlightFuncControlFlow adds highlight ranges to the result map to\n// associate results and result parameters.\n//\n// Specifically, if the cursor is in a result or result parameter, all\n// results and result parameters with the same index are highlighted. If the\n// cursor is in a 'func' or 'return' keyword, the func keyword as well as all\n// returns from that func are highlighted.\n//\n// As a special case, if the cursor is within a complicated expression, control\n// flow highlighting is disabled, as it would highlight too much.\nfunc highlightFuncControlFlow(cur inspector.Cursor, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\n\tvar (\n\t\tfuncType   *ast.FuncType   // type of enclosing func, or nil\n\t\tfuncBody   *ast.BlockStmt  // body of enclosing func, or nil\n\t\treturnStmt *ast.ReturnStmt // enclosing ReturnStmt within the func, or nil\n\t)\n\nloop:\n\tfor cur := range cur.Enclosing() {\n\t\tswitch n := cur.Node().(type) {\n\t\t// TODO(rfindley, low priority): these pre-existing cases for KeyValueExpr\n\t\t// and CallExpr appear to avoid highlighting when the cursor is in a\n\t\t// complicated expression. However, the basis for this heuristic is\n\t\t// unclear. Can we formalize a rationale?\n\t\tcase *ast.KeyValueExpr:\n\t\t\t// If cursor is in a key: value expr, we don't want control flow highlighting.\n\t\t\treturn\n\n\t\tcase *ast.FuncLit:\n\t\t\tfuncType = n.Type\n\t\t\tfuncBody = n.Body\n\t\t\tbreak loop\n\n\t\tcase *ast.FuncDecl:\n\t\t\tfuncType = n.Type\n\t\t\tfuncBody = n.Body\n\t\t\tbreak loop\n\n\t\tcase *ast.ReturnStmt:\n\t\t\treturnStmt = n\n\t\t}\n\n\t\t// If cursor is an arg in a callExpr, we don't want control flow highlighting.\n\t\tif cur.ParentEdgeKind() == edge.CallExpr_Args {\n\t\t\treturn\n\t\t}\n\t}\n\n\tif funcType == nil {\n\t\treturn // cursor is not in a function\n\t}\n\n\t// Helper functions for inspecting the current location.\n\tvar (\n\t\tpos    = cur.Node().Pos()\n\t\tinSpan = func(start, end token.Pos) bool { return start <= pos && pos < end }\n\t\tinNode = func(n ast.Node) bool { return inSpan(n.Pos(), n.End()) }\n\t)\n\n\tinResults := funcType.Results != nil && inNode(funcType.Results)\n\n\t// If the cursor is on a \"return\" or \"func\" keyword, but not highlighting any\n\t// specific field or expression, we should highlight all of the exit points\n\t// of the function, including the \"return\" and \"func\" keywords.\n\tfuncEnd := funcType.Func + token.Pos(len(\"func\"))\n\thighlightAll := cur.Node() == returnStmt || inSpan(funcType.Func, funcEnd)\n\tvar highlightIndexes map[int]bool\n\n\tif highlightAll {\n\t\t// Add the \"func\" part of the func declaration.\n\t\thighlightRange(result, astutil.RangeOf(funcType.Func, funcEnd), protocol.Text)\n\t} else if returnStmt == nil && !inResults {\n\t\treturn // nothing to highlight\n\t} else {\n\t\t// If we're not highlighting the entire return statement, we need to collect\n\t\t// specific result indexes to highlight. This may be more than one index if\n\t\t// the cursor is on a multi-name result field, but not in any specific name.\n\t\tif !highlightAll {\n\t\t\thighlightIndexes = make(map[int]bool)\n\t\t\tif returnStmt != nil {\n\t\t\t\tfor i, n := range returnStmt.Results {\n\t\t\t\t\tif inNode(n) {\n\t\t\t\t\t\thighlightIndexes[i] = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif funcType.Results != nil {\n\t\t\t\t// Scan fields, either adding highlights according to the highlightIndexes\n\t\t\t\t// computed above, or accounting for the cursor position within the result\n\t\t\t\t// list.\n\t\t\t\t// (We do both at once to avoid repeating the cumbersome field traversal.)\n\t\t\t\ti := 0\n\t\t\tfindField:\n\t\t\t\tfor _, field := range funcType.Results.List {\n\t\t\t\t\tfor j, name := range field.Names {\n\t\t\t\t\t\tif inNode(name) || highlightIndexes[i+j] {\n\t\t\t\t\t\t\thighlightNode(result, name, protocol.Text)\n\t\t\t\t\t\t\thighlightIndexes[i+j] = true\n\t\t\t\t\t\t\tbreak findField // found/highlighted the specific name\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If the cursor is in a field but not in a name (e.g. in the space, or\n\t\t\t\t\t// the type), highlight the whole field.\n\t\t\t\t\t//\n\t\t\t\t\t// Note that this may not be ideal if we're at e.g.\n\t\t\t\t\t//\n\t\t\t\t\t//  (x,‸y int, z int8)\n\t\t\t\t\t//\n\t\t\t\t\t// ...where it would make more sense to highlight only y. But we don't\n\t\t\t\t\t// reach this function if not in a func, return, ident, or basiclit.\n\t\t\t\t\tif inNode(field) || highlightIndexes[i] {\n\t\t\t\t\t\thighlightNode(result, field, protocol.Text)\n\t\t\t\t\t\thighlightIndexes[i] = true\n\t\t\t\t\t\tif inNode(field) {\n\t\t\t\t\t\t\tfor j := range field.Names {\n\t\t\t\t\t\t\t\thighlightIndexes[i+j] = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak findField // found/highlighted the field\n\t\t\t\t\t}\n\n\t\t\t\t\tn := len(field.Names)\n\t\t\t\t\tif n == 0 {\n\t\t\t\t\t\tn = 1\n\t\t\t\t\t}\n\t\t\t\t\ti += n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif funcBody != nil {\n\t\tast.Inspect(funcBody, func(n ast.Node) bool {\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.FuncDecl, *ast.FuncLit:\n\t\t\t\t// Don't traverse into any functions other than enclosingFunc.\n\t\t\t\treturn false\n\t\t\tcase *ast.ReturnStmt:\n\t\t\t\tif highlightAll {\n\t\t\t\t\t// Add the entire return statement.\n\t\t\t\t\thighlightNode(result, n, protocol.Text)\n\t\t\t\t} else {\n\t\t\t\t\t// Add the highlighted indexes.\n\t\t\t\t\tfor i, expr := range n.Results {\n\t\t\t\t\t\tif highlightIndexes[i] {\n\t\t\t\t\t\t\thighlightNode(result, expr, protocol.Text)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false\n\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n}\n\n// highlightUnlabeledBreakFlow highlights the innermost enclosing\n// for/range/switch or select\nfunc highlightUnlabeledBreakFlow(cur inspector.Cursor, info *types.Info, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\t// Reverse walk the path until we find closest loop, select, or switch.\n\tfor cur := range cur.Enclosing() {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\tvar label *ast.Ident\n\t\t\tif l, ok := cur.Parent().Node().(*ast.LabeledStmt); ok {\n\t\t\t\tlabel = l.Label\n\t\t\t}\n\t\t\thighlightLoopControlFlow(n, label, info, result)\n\t\t\treturn // only highlight the innermost statement\n\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt:\n\t\t\tvar label *ast.Ident\n\t\t\tif l, ok := cur.Parent().Node().(*ast.LabeledStmt); ok {\n\t\t\t\tlabel = l.Label\n\t\t\t}\n\t\t\thighlightSwitchFlow(n, label, info, result)\n\t\t\treturn\n\t\tcase *ast.SelectStmt:\n\t\t\t// TODO: add highlight when breaking a select.\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// highlightLabeledFlow highlights the enclosing labeled for, range,\n// or switch statement denoted by a labeled break or continue stmt.\n//\n// The input cursor must point to a [ast.BranchStmt]\nfunc highlightLabeledFlow(curBranch inspector.Cursor, info *types.Info, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\tuse := info.Uses[curBranch.Node().(*ast.BranchStmt).Label]\n\tif use == nil {\n\t\treturn\n\t}\n\tfor cur := range curBranch.Enclosing((*ast.LabeledStmt)(nil)) {\n\t\tif label := cur.Node().(*ast.LabeledStmt); info.Defs[label.Label] == use {\n\t\t\tswitch label.Stmt.(type) {\n\t\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\t\thighlightLoopControlFlow(label.Stmt, label.Label, info, result)\n\t\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt:\n\t\t\t\thighlightSwitchFlow(label.Stmt, label.Label, info, result)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc highlightLoopControlFlow(loop ast.Node, label *ast.Ident, info *types.Info, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\t// Add the for statement.\n\trngStart := loop.Pos()\n\trngEnd := loop.Pos() + token.Pos(len(\"for\"))\n\thighlightRange(result, astutil.RangeOf(rngStart, rngEnd), protocol.Text)\n\n\t// Traverse AST to find branch statements within the same for-loop.\n\tast.Inspect(loop, func(n ast.Node) bool {\n\t\tswitch n.(type) {\n\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\treturn loop == n\n\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:\n\t\t\treturn false\n\t\t}\n\t\tb, ok := n.(*ast.BranchStmt)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif b.Label == nil || info.Uses[b.Label] == info.Defs[label] {\n\t\t\thighlightNode(result, b, protocol.Text)\n\t\t}\n\t\treturn true\n\t})\n\n\t// Find continue statements in the same loop or switches/selects.\n\tast.Inspect(loop, func(n ast.Node) bool {\n\t\tswitch n.(type) {\n\t\tcase *ast.ForStmt, *ast.RangeStmt:\n\t\t\treturn loop == n\n\t\t}\n\n\t\tif n, ok := n.(*ast.BranchStmt); ok && n.Tok == token.CONTINUE {\n\t\t\thighlightNode(result, n, protocol.Text)\n\t\t}\n\t\treturn true\n\t})\n\n\t// We don't need to check other for loops if we aren't looking for labeled statements.\n\tif label == nil {\n\t\treturn\n\t}\n\n\t// Find labeled branch statements in any loop.\n\tast.Inspect(loop, func(n ast.Node) bool {\n\t\tb, ok := n.(*ast.BranchStmt)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\t// statement with labels that matches the loop\n\t\tif b.Label != nil && info.Uses[b.Label] == info.Defs[label] {\n\t\t\thighlightNode(result, b, protocol.Text)\n\t\t}\n\t\treturn true\n\t})\n}\n\nfunc highlightSwitchFlow(node ast.Node, label *ast.Ident, info *types.Info, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\t// Add the switch statement.\n\trngStart := node.Pos()\n\trngEnd := node.Pos() + token.Pos(len(\"switch\"))\n\thighlightRange(result, astutil.RangeOf(rngStart, rngEnd), protocol.Text)\n\n\t// Traverse AST to find break statements within the same switch.\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tswitch n.(type) {\n\t\tcase *ast.SwitchStmt, *ast.TypeSwitchStmt:\n\t\t\treturn node == n\n\t\tcase *ast.ForStmt, *ast.RangeStmt, *ast.SelectStmt:\n\t\t\treturn false\n\t\t}\n\n\t\tb, ok := n.(*ast.BranchStmt)\n\t\tif !ok || b.Tok != token.BREAK {\n\t\t\treturn true\n\t\t}\n\n\t\tif b.Label == nil || info.Uses[b.Label] == info.Defs[label] {\n\t\t\thighlightNode(result, b, protocol.Text)\n\t\t}\n\t\treturn true\n\t})\n\n\t// We don't need to check other switches if we aren't looking for labeled statements.\n\tif label == nil {\n\t\treturn\n\t}\n\n\t// Find labeled break statements in any switch\n\tast.Inspect(node, func(n ast.Node) bool {\n\t\tb, ok := n.(*ast.BranchStmt)\n\t\tif !ok || b.Tok != token.BREAK {\n\t\t\treturn true\n\t\t}\n\n\t\tif b.Label != nil && info.Uses[b.Label] == info.Defs[label] {\n\t\t\thighlightNode(result, b, protocol.Text)\n\t\t}\n\n\t\treturn true\n\t})\n}\n\nfunc highlightNode(result map[astutil.Range]protocol.DocumentHighlightKind, n ast.Node, kind protocol.DocumentHighlightKind) {\n\thighlightRange(result, astutil.NodeRange(n), kind)\n}\n\nfunc highlightRange(result map[astutil.Range]protocol.DocumentHighlightKind, rng astutil.Range, kind protocol.DocumentHighlightKind) {\n\t// Order of traversal is important: some nodes (e.g. identifiers) are\n\t// visited more than once, but the kind set during the first visitation \"wins\".\n\tif _, exists := result[rng]; !exists {\n\t\tresult[rng] = kind\n\t}\n}\n\nfunc highlightIdentifier(cur inspector.Cursor, info *types.Info, result map[astutil.Range]protocol.DocumentHighlightKind) {\n\tident := cur.Node().(*ast.Ident)\n\n\t// obj may be nil if the Ident is undefined.\n\t// In this case, the behavior expected by tests is\n\t// to match other undefined Idents of the same name.\n\tobj := info.ObjectOf(ident)\n\n\thighlightIdent := func(n *ast.Ident, kind protocol.DocumentHighlightKind) {\n\t\tif n.Name == ident.Name && info.ObjectOf(n) == obj {\n\t\t\thighlightNode(result, n, kind)\n\t\t}\n\t}\n\t// highlightWriteInExpr is called for expressions that are\n\t// logically on the left side of an assignment.\n\t// We follow the behavior of VSCode+Rust and GoLand, which differs\n\t// slightly from types.TypeAndValue.Assignable:\n\t//     *ptr = 1       // ptr write\n\t//     *ptr.field = 1 // ptr read, field write\n\t//     s.field = 1    // s read, field write\n\t//     array[i] = 1   // array read\n\tvar highlightWriteInExpr func(expr ast.Expr)\n\thighlightWriteInExpr = func(expr ast.Expr) {\n\t\tswitch expr := expr.(type) {\n\t\tcase *ast.Ident:\n\t\t\thighlightIdent(expr, protocol.Write)\n\t\tcase *ast.SelectorExpr:\n\t\t\thighlightIdent(expr.Sel, protocol.Write)\n\t\tcase *ast.StarExpr:\n\t\t\thighlightWriteInExpr(expr.X)\n\t\tcase *ast.ParenExpr:\n\t\t\thighlightWriteInExpr(expr.X)\n\t\t}\n\t}\n\n\t_, curFile := cursorutil.FirstEnclosing[*ast.File](cur)\n\tcurFile.Inspect(nil, func(c inspector.Cursor) bool {\n\t\tswitch n := c.Node().(type) {\n\t\tcase *ast.AssignStmt:\n\t\t\tfor _, s := range n.Lhs {\n\t\t\t\thighlightWriteInExpr(s)\n\t\t\t}\n\t\tcase *ast.GenDecl:\n\t\t\tif n.Tok == token.CONST || n.Tok == token.VAR {\n\t\t\t\tfor _, spec := range n.Specs {\n\t\t\t\t\tif spec, ok := spec.(*ast.ValueSpec); ok {\n\t\t\t\t\t\tfor _, ele := range spec.Names {\n\t\t\t\t\t\t\thighlightWriteInExpr(ele)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.IncDecStmt:\n\t\t\thighlightWriteInExpr(n.X)\n\t\tcase *ast.SendStmt:\n\t\t\thighlightWriteInExpr(n.Chan)\n\t\tcase *ast.CompositeLit:\n\t\t\tt := info.TypeOf(n)\n\t\t\tif t == nil {\n\t\t\t\tt = types.Typ[types.Invalid]\n\t\t\t}\n\t\t\tif ptr, ok := t.Underlying().(*types.Pointer); ok {\n\t\t\t\tt = ptr.Elem()\n\t\t\t}\n\t\t\tif _, ok := t.Underlying().(*types.Struct); ok {\n\t\t\t\tfor _, expr := range n.Elts {\n\t\t\t\t\tif expr, ok := (expr).(*ast.KeyValueExpr); ok {\n\t\t\t\t\t\thighlightWriteInExpr(expr.Key)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.RangeStmt:\n\t\t\thighlightWriteInExpr(n.Key)\n\t\t\thighlightWriteInExpr(n.Value)\n\t\tcase *ast.Field:\n\t\t\tfor _, name := range n.Names {\n\t\t\t\thighlightIdent(name, protocol.Text)\n\t\t\t}\n\t\tcase *ast.Ident:\n\t\t\t// This case is reached for all Idents,\n\t\t\t// including those also visited by highlightWriteInExpr.\n\t\t\tif is[*types.Var](info.ObjectOf(n)) {\n\t\t\t\thighlightIdent(n, protocol.Read)\n\t\t\t} else {\n\t\t\t\t// kind of idents in PkgName, etc. is Text\n\t\t\t\thighlightIdent(n, protocol.Text)\n\t\t\t}\n\t\tcase *ast.ImportSpec:\n\t\t\tpkgname := info.PkgNameOf(n)\n\t\t\tif obj != nil && pkgname == obj {\n\t\t\t\tif n.Name != nil {\n\t\t\t\t\thighlightNode(result, n.Name, protocol.Text)\n\t\t\t\t} else {\n\t\t\t\t\thighlightNode(result, n, protocol.Text)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/golang/hover.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/doc\"\n\t\"go/format\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"go/version\"\n\t\"io/fs\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/tabwriter\"\n\t\"time\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/text/unicode/runenames\"\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// hoverResult contains the (internal) result of a hover query.\n// It is formatted in one of several formats as determined by the\n// HoverKind setting.\ntype hoverResult struct {\n\t// The fields below are exported to define the JSON hover format.\n\t// TODO(golang/go#70233): (re)remove support for JSON hover.\n\n\t// Synopsis is a single sentence Synopsis of the symbol's documentation.\n\t//\n\t// TODO(adonovan): in what syntax? It (usually) comes from doc.Synopsis,\n\t// which produces \"Text\" form, but it may be fed to\n\t// DocCommentToMarkdown, which expects doc comment syntax.\n\tSynopsis string `json:\"synopsis\"`\n\n\t// FullDocumentation is the symbol's full documentation.\n\tFullDocumentation string `json:\"fullDocumentation\"`\n\n\t// Signature is the symbol's Signature.\n\tSignature string `json:\"signature\"`\n\n\t// SingleLine is a single line describing the symbol.\n\t// This is recommended only for use in clients that show a single line for hover.\n\tSingleLine string `json:\"singleLine\"`\n\n\t// SymbolName is the human-readable name to use for the symbol in links.\n\tSymbolName string `json:\"symbolName\"`\n\n\t// LinkPath is the path of the package enclosing the given symbol,\n\t// with the module portion (if any) replaced by \"module@version\".\n\t//\n\t// For example: \"github.com/google/go-github/v48@v48.1.0/github\".\n\t//\n\t// Use LinkTarget + \"/\" + LinkPath + \"#\" + LinkAnchor to form a pkgsite URL.\n\tLinkPath string `json:\"linkPath\"`\n\n\t// LinkAnchor is the pkg.go.dev link anchor for the given symbol.\n\t// For example, the \"Node\" part of \"pkg.go.dev/go/ast#Node\".\n\tLinkAnchor string `json:\"linkAnchor\"`\n\n\t// New fields go below, and are unexported. The existing\n\t// exported fields are underspecified and have already\n\t// constrained our movements too much. A detailed JSON\n\t// interface might be nice, but it needs a design and a\n\t// precise specification.\n\t// TODO(golang/go#70233): (re)deprecate the JSON hover output.\n\n\t// typeDecl is the declaration syntax for a type,\n\t// or \"\" for a non-type.\n\ttypeDecl string\n\n\t// methods is the list of descriptions of methods of a type,\n\t// omitting any that are obvious from typeDecl.\n\t// It is \"\" for a non-type.\n\tmethods string\n\n\t// promotedFields is the list of descriptions of accessible\n\t// fields of a (struct) type that were promoted through an\n\t// embedded field.\n\tpromotedFields string\n\n\t// footer is additional content to insert at the bottom of the hover\n\t// documentation, before the pkgdoc link.\n\tfooter string\n}\n\n// Hover implements the \"textDocument/hover\" RPC for Go files.\n// It may return nil even on success.\n//\n// If pkgURL is non-nil, it should be used to generate doc links.\nfunc Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range, pkgURL func(path PackagePath, fragment string) protocol.URI) (*protocol.Hover, error) {\n\tctx, done := event.Start(ctx, \"golang.Hover\")\n\tdefer done()\n\n\trng, h, err := hover(ctx, snapshot, fh, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif h == nil {\n\t\treturn nil, nil\n\t}\n\thover, err := formatHover(h, snapshot.Options(), pkgURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &protocol.Hover{\n\t\tContents: protocol.MarkupContent{\n\t\t\tKind:  snapshot.Options().PreferredContentFormat,\n\t\t\tValue: hover,\n\t\t},\n\t\tRange: rng,\n\t}, nil\n}\n\n// findRhsTypeDecl finds an alias's rhs type and returns its declaration.\n// The rhs of an alias might be an alias as well, but we feel this is a rare case.\n// It returns an empty string if the given obj is not an alias.\nfunc findRhsTypeDecl(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, obj types.Object) (string, error) {\n\tif alias, ok := obj.Type().(*types.Alias); ok {\n\t\t// we choose Rhs instead of types.Unalias to make the connection between original alias\n\t\t// and the corresponding aliased type clearer.\n\t\t// types.Unalias brings confusion because it breaks the connection from A to C given\n\t\t// the alias chain like 'type ( A = B; B = C; )' except we show all transitive alias\n\t\t// from start to the end. As it's rare, we don't do so.\n\t\tif named, ok := alias.Rhs().(*types.Named); ok {\n\t\t\tobj = named.Obj()\n\t\t\tdeclPGF1, declPos1, err := parseFull(ctx, snapshot, pkg.FileSet(), obj)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\trealTypeDecl, _, err := typeDeclContent(declPGF1, declPos1, obj.Name())\n\t\t\treturn realTypeDecl, err\n\t\t}\n\t}\n\n\treturn \"\", nil\n}\n\n// hover computes hover information at the given range. When hover over a single\n// point, the input range's start and end are the same.\n//\n// If we do not support hovering at the position, it returns _, nil, nil:\n// an error is only returned if the position is valid but we fail to compute\n// hover information.\n//\n// TODO(adonovan): strength-reduce file.Handle to protocol.DocumentURI.\nfunc hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (protocol.Range, *hoverResult, error) {\n\t// Check for hover inside the builtin file before attempting type checking\n\t// below. NarrowestPackageForFile may or may not succeed, depending on\n\t// whether this is a GOROOT view, but even if it does succeed the resulting\n\t// package will be command-line-arguments package. The user should get a\n\t// hover for the builtin object, not the object type checked from the\n\t// builtin.go.\n\tif snapshot.IsBuiltin(fh.URI()) {\n\t\tpgf, err := snapshot.BuiltinFile(ctx)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\tstart, end, err := pgf.RangePos(rng)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\tcur, _ := pgf.Cursor().FindByPos(start, end) // can't fail\n\t\tif id, ok := cur.Node().(*ast.Ident); ok {\n\t\t\trng, err := pgf.NodeRange(id)\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\t\t\tvar obj types.Object\n\t\t\tif id.Name == \"Error\" {\n\t\t\t\tobj = types.Universe.Lookup(\"error\").Type().Underlying().(*types.Interface).Method(0)\n\t\t\t} else {\n\t\t\t\tobj = types.Universe.Lookup(id.Name)\n\t\t\t}\n\t\t\tif obj != nil {\n\t\t\t\th, err := hoverBuiltin(ctx, snapshot, obj)\n\t\t\t\treturn rng, h, err\n\t\t\t}\n\t\t}\n\t\treturn protocol.Range{}, nil, nil // no object to hover\n\t}\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\tvar posRange astutil.Range\n\t{\n\t\tstart, end, err := pgf.RangePos(rng)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\tposRange = astutil.RangeOf(start, end)\n\t}\n\n\t// Handle hovering over the package name, which does not have an associated\n\t// object.\n\t// As with import paths, we allow hovering just after the package name.\n\tif pgf.File.Name != nil && astutil.NodeContains(pgf.File.Name, posRange) {\n\t\treturn hoverPackageName(pkg, pgf)\n\t}\n\n\t// Handle hovering over embed directive argument.\n\tpattern, embedRng := parseEmbedDirective(pgf.Mapper, rng)\n\tif pattern != \"\" {\n\t\treturn hoverEmbed(fh, embedRng, pattern)\n\t}\n\n\t// hoverRange is the range reported to the client (e.g. for highlighting).\n\t// It may be an expansion around the selected identifier,\n\t// for instance when hovering over a linkname directive or doc link.\n\tvar hoverRange *protocol.Range\n\t// Handle linkname directive by overriding what to look for.\n\tif pkgPath, name, offset := parseLinkname(pgf.Mapper, rng); pkgPath != \"\" && name != \"\" {\n\t\t// rng covering 2nd linkname argument: pkgPath.name.\n\t\trng, err := pgf.PosRange(pgf.Tok.Pos(offset), pgf.Tok.Pos(offset+len(pkgPath)+len(\".\")+len(name)))\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, fmt.Errorf(\"range over linkname arg: %w\", err)\n\t\t}\n\t\thoverRange = &rng\n\n\t\tvar pos token.Pos\n\t\t// Subtle: updates pkg, which defines the FileSet used to resolve (start, end),\n\t\t// which were obtained from pkg.\n\t\tpkg, pgf, pos, err = findLinkname(ctx, snapshot, PackagePath(pkgPath), name)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, fmt.Errorf(\"find linkname: %w\", err)\n\t\t}\n\t\tposRange = astutil.RangeOf(pos, pos) // move the range\n\t}\n\n\t// TODO(hxjiang): Hovering over a doc link like \"[foo.Foo]\" and a direct\n\t// call to \"foo.Foo\" can produce different signatures. The doc link hover is\n\t// qualified relative to the function's definition file, whereas the direct\n\t// call hover is qualified relative to the current file where the call occurs.\n\n\t// Handle hovering over a doc link\n\tif obj, rng, err := resolveDocLink(pkg, pgf, posRange); obj != nil {\n\t\t// Built-ins have no position.\n\t\tif isBuiltin(obj) {\n\t\t\th, err := hoverBuiltin(ctx, snapshot, obj)\n\t\t\treturn rng, h, err\n\t\t}\n\n\t\t// Find position in declaring file.\n\t\thoverRange = &rng\n\n\t\tvar pos token.Pos\n\t\t// Subtle: updates pkg, which defines the FileSet used to resolve (start, end),\n\t\t// which were obtained from pkg.\n\t\tpkg, pgf, pos, err = NarrowestDeclaringPackage(ctx, snapshot, pkg, obj)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\tposRange = astutil.RangeOf(pos, pos)\n\t}\n\n\t// Find cursor for selection.\n\tcur, ok := pgf.Cursor().FindByPos(posRange.Pos(), posRange.End())\n\tif !ok {\n\t\treturn protocol.Range{}, nil, fmt.Errorf(\"hover position not within file\")\n\t}\n\n\t// Handle hovering over import specs,\n\t// which may not have an associated identifier.\n\tfor _, spec := range pgf.File.Imports {\n\t\tif astutil.NodeContains(spec, posRange) {\n\t\t\tpath := metadata.UnquoteImportPath(spec)\n\t\t\thoverRes, err := hoverPackageRef(ctx, snapshot, pkg, path)\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\t\t\trng, err := pgf.NodeRange(spec.Path)\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\t\t\tif hoverRange == nil { // (may have already been set by a doc link)\n\t\t\t\thoverRange = &rng\n\t\t\t}\n\t\t\treturn *hoverRange, hoverRes, nil // (hoverRes may be nil)\n\t\t}\n\t}\n\n\t// By convention, we qualify hover information relative to the package\n\t// from which the request originated.\n\tqual := typesinternal.FileQualifier(pgf.File, pkg.Types())\n\n\t// Handle hovering over various special kinds of syntax node.\n\tswitch node := cur.Node().(type) {\n\t// (import paths were handled above)\n\tcase *ast.ReturnStmt:\n\t\treturn hoverReturnStatement(pgf, cur)\n\tcase *ast.Ident:\n\t\t// fall through to rest of function\n\tcase ast.Expr:\n\t\ttv, ok := pkg.TypesInfo().Types[node]\n\t\tif !ok {\n\t\t\treturn protocol.Range{}, nil, nil\n\t\t}\n\t\tif tv.Value != nil {\n\t\t\t// non-identifier constant expression\n\t\t\treturn hoverConstantExpr(pgf, node, tv, posRange)\n\t\t}\n\t\t// non-constant, non-identifier expression\n\t\t// TODO(hxjiang): what info should we provide other than type of\n\t\t// the selected expression.\n\t\t// TODO(hxjiang): show method set of the given expression' type.\n\t\tr := &hoverResult{\n\t\t\tSynopsis:          goastutil.NodeDescription(node),\n\t\t\tFullDocumentation: types.TypeString(pkg.TypesInfo().TypeOf(node), qual),\n\t\t}\n\n\t\thighlight, err := pgf.NodeRange(node)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\treturn highlight, r, nil\n\t}\n\n\t// Handle hover over identifier.\n\n\t// The general case: compute hover information for the object referenced by\n\t// the identifier at (or near) pos.\n\tobjects, err := objectsAt(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, nil // no object to hover\n\t}\n\t// Pick first object arbitrarily.\n\t// Update cursor to its identifier (perhaps nearby).\n\tobj, cur := objects[0].obj, objects[0].cur\n\tident, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn protocol.Range{}, nil, nil // e.g. ImportSpec?\n\t}\n\n\t// Unless otherwise specified, rng covers the ident being hovered.\n\tif hoverRange == nil {\n\t\trng, err := pgf.NodeRange(ident)\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\thoverRange = &rng\n\t}\n\n\t// Handle type switch identifiers as a special case,\n\t// since they don't have a regular object.\n\t// There's not much useful information to provide.\n\tif _, selectedType := typeSwitchVars(pkg.TypesInfo(), cur); selectedType != nil {\n\t\tv := types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), selectedType)\n\t\ttypesinternal.SetVarKind(v, typesinternal.LocalVar)\n\t\tsignature := types.ObjectString(v, qual)\n\t\treturn *hoverRange, &hoverResult{\n\t\t\tSignature:  signature,\n\t\t\tSingleLine: signature,\n\t\t\tSymbolName: v.Name(),\n\t\t}, nil\n\t}\n\n\tif isBuiltin(obj) {\n\t\t// Built-ins have no position.\n\t\th, err := hoverBuiltin(ctx, snapshot, obj)\n\t\treturn *hoverRange, h, err\n\t}\n\n\t// For all other objects, load type information for their declaring package\n\t// in order to correctly compute their documentation, signature, and link.\n\t//\n\t// Beware: positions derived from decl{Obj,Pkg,PGF,Pos} should be resolve\n\t// using declPkg.FileSet; other positions should use pkg.FileSet().\n\tdeclPkg, declPGF, declPos, err := NarrowestDeclaringPackage(ctx, snapshot, pkg, obj)\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\n\tdecl, spec, field := findDeclInfo([]*ast.File{declPGF.File}, declPos) // may be nil^3\n\n\tvar docText string\n\tif docComment := chooseDocComment(decl, spec, field); docComment != nil {\n\t\tdocBuf := new(strings.Builder)\n\t\tdocBuf.WriteString(docComment.Text())\n\n\t\t// docLinks maps the literal text of a doc link to its definition URI.\n\t\t// Since the link parser yields progressively for each part of a symbol\n\t\t// path (e.g., \"fmt\", then \"fmt.Scanner\"), we intentionally overwrite the\n\t\t// map entry to ensure the final value is the URI for the complete symbol.\n\t\tdocLinks := make(map[string]string)\n\t\tfor docLink := range commentDocLinks(docComment) {\n\t\t\tobj := lookupDocLinkSymbol(declPkg, declPGF, docLink.nameText)\n\t\t\tif obj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// The URI is set to the location of the right-most element in a doc link\n\t\t\t// (e.g., 'Scan' in [fmt.Scanner.Scan]). The sequential yielding of path\n\t\t\t// segments intentionally overwrites the location for previous segments,\n\t\t\t// ensuring only the most specific definition's location is retained.\n\t\t\tloc, err := ObjectLocation(ctx, declPkg.FileSet(), snapshot, obj)\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\n\t\t\t// The #line,col URL fragment is a non-standard format for file\n\t\t\t// URIs that is supported by VS Code for navigating from hover\n\t\t\t// text. The line and column are 1-based, and the column is a\n\t\t\t// UTF-16 code unit offset, matching the LSP's definition of\n\t\t\t// character position.\n\t\t\tdocLinks[docLink.bracketText] = fmt.Sprintf(\"%s#%d,%d\", loc.URI, loc.Range.Start.Line+1, loc.Range.Start.Character+1)\n\t\t}\n\n\t\t// Attaching doc links to the bottom of the comment. The non-deterministic\n\t\t// order is acceptable as these will be removed later by the [formatHover].\n\t\tif len(docLinks) > 0 {\n\t\t\tdocBuf.WriteString(\"\\n\")\n\t\t\tfor doc, link := range docLinks {\n\t\t\t\tfmt.Fprintf(docBuf, \"%s: %s\\n\", doc, link)\n\t\t\t}\n\t\t}\n\n\t\tdocText = docBuf.String()\n\t}\n\n\t// By default, types.ObjectString provides a reasonable signature.\n\tsignature := objectString(obj, qual, declPos, declPGF.Tok, spec)\n\n\t// When hovering over a reference to a promoted struct field,\n\t// show the implicitly selected intervening fields.\n\tif obj, ok := obj.(*types.Var); ok && obj.IsField() {\n\t\tif selExpr, ok := cur.Parent().Node().(*ast.SelectorExpr); ok {\n\t\t\tsel, ok := pkg.TypesInfo().Selections[selExpr]\n\t\t\tif ok && len(sel.Index()) > 1 {\n\t\t\t\tvar buf bytes.Buffer\n\t\t\t\tbuf.WriteString(\" // through \")\n\t\t\t\tt := typesinternal.Unpointer(sel.Recv())\n\t\t\t\tfor i, index := range sel.Index()[:len(sel.Index())-1] {\n\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\tbuf.WriteString(\", \")\n\t\t\t\t\t}\n\t\t\t\t\tfield := typesinternal.Unpointer(t.Underlying()).(*types.Struct).Field(index)\n\t\t\t\t\tt = field.Type()\n\t\t\t\t\t// Inv: fieldType is N or *N for some NamedOrAlias type N.\n\t\t\t\t\tif ptr, ok := t.(*types.Pointer); ok {\n\t\t\t\t\t\tbuf.WriteString(\"*\")\n\t\t\t\t\t\tt = ptr.Elem()\n\t\t\t\t\t}\n\t\t\t\t\t// Be defensive in case of ill-typed code:\n\t\t\t\t\tif named, ok := t.(typesinternal.NamedOrAlias); ok {\n\t\t\t\t\t\tbuf.WriteString(named.Obj().Name())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Update signature to include embedded struct info.\n\t\t\t\tsignature += buf.String()\n\t\t\t}\n\t\t}\n\t}\n\n\tsingleLineSignature := signature\n\n\t// Display struct tag for struct fields at the end of the signature.\n\tif field != nil && field.Tag != nil {\n\t\tsignature += \" \" + field.Tag.Value\n\t}\n\n\t// TODO(rfindley): we could do much better for inferred signatures.\n\t// TODO(adonovan): fuse the two calls below.\n\tif inferred := inferredSignature(pkg.TypesInfo(), ident); inferred != nil {\n\t\tif s := inferredSignatureString(obj, qual, inferred); s != \"\" {\n\t\t\tsignature = s\n\t\t}\n\t}\n\n\t// Compute size information for types,\n\t// including allocator size class,\n\t// and (size, offset) for struct fields.\n\t//\n\t// Also, if a struct type's field ordering is significantly\n\t// wasteful of space, report its optimal size.\n\t//\n\t// This information is useful when debugging crashes or\n\t// optimizing layout. To reduce distraction, we show it only\n\t// when hovering over the declaring identifier,\n\t// but not referring identifiers.\n\t//\n\t// Size and alignment vary across OS/ARCH.\n\t// Gopls will select the appropriate build configuration when\n\t// viewing a type declaration in a build-tagged file, but will\n\t// use the default build config for all other types, even\n\t// if they embed platform-variant types.\n\t//\n\tvar sizeOffset string\n\n\tif ident.Pos() == obj.Pos() {\n\t\t// This is the declaring identifier.\n\n\t\t// format returns the decimal and hex representation of x.\n\t\tformat := func(x int64) string {\n\t\t\tif x < 10 {\n\t\t\t\treturn fmt.Sprintf(\"%d\", x)\n\t\t\t}\n\t\t\treturn fmt.Sprintf(\"%[1]d (%#[1]x)\", x)\n\t\t}\n\n\t\t// Build string of form \"size=... (X% wasted), class=..., offset=...\".\n\t\tsize, wasted, offset := computeSizeOffsetInfo(pkg, cur, obj)\n\t\tvar buf strings.Builder\n\t\tif size >= 0 {\n\t\t\tfmt.Fprintf(&buf, \"size=%s\", format(size))\n\t\t\tif wasted >= 20 { // >=20% wasted\n\t\t\t\tfmt.Fprintf(&buf, \" (%d%% wasted)\", wasted)\n\t\t\t}\n\n\t\t\t// Include allocator size class, if larger.\n\t\t\tif class := sizeClass(size); class > size {\n\t\t\t\tfmt.Fprintf(&buf, \", class=%s\", format(class))\n\t\t\t}\n\t\t}\n\t\tif offset >= 0 {\n\t\t\tif buf.Len() > 0 {\n\t\t\t\tbuf.WriteString(\", \")\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"offset=%s\", format(offset))\n\t\t}\n\t\tsizeOffset = buf.String()\n\t}\n\n\tvar typeDecl, methods, fields string\n\n\t// For \"objects defined by a type spec\", the signature produced by\n\t// objectString is insufficient:\n\t//  (1) large structs are formatted poorly, with no newlines\n\t//  (2) we lose inline comments\n\t// Furthermore, we include a summary of their method set.\n\t_, isTypeName := obj.(*types.TypeName)\n\t_, isTypeParam := types.Unalias(obj.Type()).(*types.TypeParam)\n\tif isTypeName && !isTypeParam {\n\t\tvar spec1 *ast.TypeSpec\n\t\ttypeDecl, spec1, err = typeDeclContent(declPGF, declPos, obj.Name())\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\n\t\t// Splice in size/offset at end of first line.\n\t\t//   \"type T struct { // size=...\"\n\t\tif sizeOffset != \"\" {\n\t\t\tnl := strings.IndexByte(typeDecl, '\\n')\n\t\t\tif nl < 0 {\n\t\t\t\tnl = len(typeDecl)\n\t\t\t}\n\t\t\ttypeDecl = typeDecl[:nl] + \" // \" + sizeOffset + typeDecl[nl:]\n\t\t}\n\n\t\t// Promoted fields\n\t\t//\n\t\t// Show a table of accessible fields of the (struct)\n\t\t// type that may not be visible in the syntax (above)\n\t\t// due to promotion through embedded fields.\n\t\t//\n\t\t// Example:\n\t\t//\n\t\t//\t// Embedded fields:\n\t\t//\tfoo int\t   // through x.y\n\t\t//\tz   string // through x.y\n\t\tif prom := promotedFields(obj.Type(), pkg.Types()); len(prom) > 0 {\n\t\t\tvar b strings.Builder\n\t\t\tb.WriteString(\"// Embedded fields:\\n\")\n\t\t\tw := tabwriter.NewWriter(&b, 0, 8, 1, ' ', 0)\n\t\t\tfor _, f := range prom {\n\t\t\t\tfmt.Fprintf(w, \"%s\\t%s\\t// through %s\\t\\n\",\n\t\t\t\t\tf.field.Name(),\n\t\t\t\t\ttypes.TypeString(f.field.Type(), qual),\n\t\t\t\t\tf.path)\n\t\t\t}\n\t\t\tw.Flush() // ignore error\n\t\t\tb.WriteByte('\\n')\n\t\t\tfields = b.String()\n\t\t}\n\n\t\t// -- methods --\n\n\t\t// For an interface type, explicit methods will have\n\t\t// already been displayed when the node was formatted\n\t\t// above. Don't list these again.\n\t\tvar skip map[string]bool\n\t\tif iface, ok := spec1.Type.(*ast.InterfaceType); ok {\n\t\t\tif iface.Methods.List != nil {\n\t\t\t\tfor _, m := range iface.Methods.List {\n\t\t\t\t\tif len(m.Names) == 1 {\n\t\t\t\t\t\tif skip == nil {\n\t\t\t\t\t\t\tskip = make(map[string]bool)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskip[m.Names[0].Name] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Display all the type's accessible methods,\n\t\t// including those that require a pointer receiver,\n\t\t// and those promoted from embedded struct fields or\n\t\t// embedded interfaces.\n\t\tvar b strings.Builder\n\t\tfor _, m := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {\n\t\t\tif !accessibleTo(m.Obj(), pkg.Types()) {\n\t\t\t\tcontinue // inaccessible\n\t\t\t}\n\t\t\tif skip[m.Obj().Name()] {\n\t\t\t\tcontinue // redundant with format.Node above\n\t\t\t}\n\t\t\tif b.Len() > 0 {\n\t\t\t\tb.WriteByte('\\n')\n\t\t\t}\n\n\t\t\t// Use objectString for its prettier rendering of method receivers.\n\t\t\tb.WriteString(objectString(m.Obj(), qual, token.NoPos, nil, nil))\n\t\t}\n\t\tmethods = b.String()\n\n\t\tsignature = typeDecl + \"\\n\" + methods\n\t} else {\n\t\t// Non-types\n\t\tif sizeOffset != \"\" {\n\t\t\tsignature += \" // \" + sizeOffset\n\t\t}\n\t}\n\n\tif isTypeName {\n\t\t// get the real type decl only if current object is a type,\n\t\t// for non-types, we'd better hide the real type decl to avoid possible confusion.\n\t\t//\n\t\t// realTypeDecl is defined to store the underlying definition of an alias.\n\t\trealTypeDecl, _ := findRhsTypeDecl(ctx, snapshot, pkg, obj) // tolerate the error\n\t\tif realTypeDecl != \"\" {\n\t\t\ttypeDecl += fmt.Sprintf(\"\\n\\n%s\", realTypeDecl)\n\t\t}\n\t}\n\n\t// Compute link data (on pkg.go.dev or other documentation host).\n\t//\n\t// If linkPath is empty, the symbol is not linkable.\n\tvar (\n\t\tlinkName string            // => link title, always non-empty\n\t\tlinkPath string            // => link path\n\t\tanchor   string            // link anchor\n\t\tlinkMeta *metadata.Package // metadata for the linked package\n\t)\n\t{\n\t\tlinkMeta = findFileInDeps(snapshot, pkg.Metadata(), declPGF.URI)\n\t\tif linkMeta == nil {\n\t\t\treturn protocol.Range{}, nil, bug.Errorf(\"no package data for %s\", declPGF.URI)\n\t\t}\n\n\t\t// For package names, we simply link to their imported package.\n\t\tif pkgName, ok := obj.(*types.PkgName); ok {\n\t\t\tlinkName = pkgName.Name()\n\t\t\tlinkPath = pkgName.Imported().Path()\n\t\t\timpID := linkMeta.DepsByPkgPath[PackagePath(pkgName.Imported().Path())]\n\t\t\tlinkMeta = snapshot.Metadata(impID)\n\t\t\tif linkMeta == nil {\n\t\t\t\t// Broken imports have fake package paths, so it is not a bug if we\n\t\t\t\t// don't have metadata. As of writing, there is no way to distinguish\n\t\t\t\t// broken imports from a true bug where expected metadata is missing.\n\t\t\t\treturn protocol.Range{}, nil, fmt.Errorf(\"no package data for %s\", declPGF.URI)\n\t\t\t}\n\t\t} else {\n\t\t\t// For all others, check whether the object is in the package scope, or\n\t\t\t// an exported field or method of an object in the package scope.\n\t\t\t//\n\t\t\t// We try to match pkgsite's heuristics for what is linkable, and what is\n\t\t\t// not.\n\t\t\tvar recv types.Object\n\t\t\tswitch obj := obj.(type) {\n\t\t\tcase *types.Func:\n\t\t\t\tsig := obj.Signature()\n\t\t\t\tif sig.Recv() != nil {\n\t\t\t\t\ttnames := typeToObjects(sig.Recv().Type())\n\t\t\t\t\tif len(tnames) == 1 { // beware empty slice\n\t\t\t\t\t\trecv = tnames[0]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *types.Var:\n\t\t\t\tif obj.IsField() {\n\t\t\t\t\tif spec, ok := spec.(*ast.TypeSpec); ok {\n\t\t\t\t\t\ttypeName := spec.Name\n\t\t\t\t\t\tscopeObj, _ := obj.Pkg().Scope().Lookup(typeName.Name).(*types.TypeName)\n\t\t\t\t\t\tif scopeObj != nil {\n\t\t\t\t\t\t\tif st, _ := scopeObj.Type().Underlying().(*types.Struct); st != nil {\n\t\t\t\t\t\t\t\tfor field := range st.Fields() {\n\t\t\t\t\t\t\t\t\tif obj == field {\n\t\t\t\t\t\t\t\t\t\trecv = scopeObj\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Even if the object is not available in package documentation, it may\n\t\t\t// be embedded in a documented receiver. Detect this by searching\n\t\t\t// enclosing selector expressions.\n\t\t\t//\n\t\t\t// TODO(rfindley): pkgsite doesn't document fields from embedding, just\n\t\t\t// methods.\n\t\t\tif recv == nil || !recv.Exported() {\n\t\t\t\tif enclosing := searchForEnclosing(pkg.TypesInfo(), cur); enclosing != nil {\n\t\t\t\t\trecv = enclosing\n\t\t\t\t} else {\n\t\t\t\t\trecv = nil // note: just recv = ... could result in a typed nil.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpkg := obj.Pkg()\n\t\t\tif recv != nil {\n\t\t\t\tlinkName = fmt.Sprintf(\"(%s.%s).%s\", pkg.Name(), recv.Name(), obj.Name())\n\t\t\t\tif obj.Exported() && recv.Exported() && typesinternal.IsPackageLevel(recv) {\n\t\t\t\t\tlinkPath = pkg.Path()\n\t\t\t\t\tanchor = fmt.Sprintf(\"%s.%s\", recv.Name(), obj.Name())\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlinkName = fmt.Sprintf(\"%s.%s\", pkg.Name(), obj.Name())\n\t\t\t\tif obj.Exported() && typesinternal.IsPackageLevel(obj) {\n\t\t\t\t\tlinkPath = pkg.Path()\n\t\t\t\t\tanchor = obj.Name()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif snapshot.IsGoPrivatePath(linkPath) || linkMeta.ForTest != \"\" {\n\t\tlinkPath = \"\"\n\t} else if linkMeta.Module != nil && linkMeta.Module.Version != \"\" {\n\t\tmod := linkMeta.Module\n\t\tlinkPath = strings.Replace(linkPath, mod.Path, cache.ResolvedString(mod), 1)\n\t}\n\n\t// Handle hover over an imported package name identifier.\n\tif pkgName, ok := obj.(*types.PkgName); ok {\n\t\thoverRes, err := hoverPackageRef(ctx, snapshot, pkg, metadata.ImportPath(pkgName.Imported().Path()))\n\t\tif err != nil {\n\t\t\treturn protocol.Range{}, nil, err\n\t\t}\n\t\thoverRes.LinkAnchor = anchor\n\t\thoverRes.LinkPath = linkPath\n\t\thoverRes.SymbolName = linkName\n\t\treturn *hoverRange, hoverRes, nil // (hoverRes may be nil)\n\t}\n\n\tvar footer string\n\tif sym := StdSymbolOf(obj); sym != nil && sym.Version > 0 {\n\t\tfooter = fmt.Sprintf(\"Added in %v\", sym.Version)\n\t}\n\n\treturn *hoverRange, &hoverResult{\n\t\tSynopsis:          doc.Synopsis(docText),\n\t\tFullDocumentation: docText,\n\t\tSingleLine:        singleLineSignature,\n\t\tSymbolName:        linkName,\n\t\tSignature:         signature,\n\t\tLinkPath:          linkPath,\n\t\tLinkAnchor:        anchor,\n\t\ttypeDecl:          typeDecl,\n\t\tmethods:           methods,\n\t\tpromotedFields:    fields,\n\t\tfooter:            footer,\n\t}, nil\n}\n\n// typeDeclContent returns a well formatted type definition.\nfunc typeDeclContent(declPGF *parsego.File, declPos token.Pos, name string) (string, *ast.TypeSpec, error) {\n\t_, spec, _ := findDeclInfo([]*ast.File{declPGF.File}, declPos) // may be nil^3\n\t// Don't duplicate comments.\n\tspec1, ok := spec.(*ast.TypeSpec)\n\tif !ok {\n\t\t// We cannot find a TypeSpec for this type or alias declaration\n\t\t// (that is not a type parameter or a built-in).\n\t\t// This should be impossible even for ill-formed trees;\n\t\t// we suspect that AST repair may be creating inconsistent\n\t\t// positions. Don't report a bug in that case. (#64241)\n\t\terrorf := fmt.Errorf\n\t\tif !declPGF.Fixed() {\n\t\t\terrorf = bug.Errorf\n\t\t}\n\t\treturn \"\", nil, errorf(\"type name %q without type spec\", name)\n\t}\n\tspec2 := *spec1\n\tspec2.Doc = nil\n\tspec2.Comment = nil\n\n\tvar b strings.Builder\n\tb.WriteString(\"type \")\n\tfset := tokeninternal.FileSetFor(declPGF.Tok)\n\t// TODO(adonovan): use a smarter formatter that omits\n\t// inaccessible fields (non-exported ones from other packages).\n\tif err := format.Node(&b, fset, &spec2); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\ttypeDecl := b.String()\n\treturn typeDecl, spec1, nil\n}\n\n// hoverBuiltin computes hover information when hovering over a builtin\n// identifier.\nfunc hoverBuiltin(ctx context.Context, snapshot *cache.Snapshot, obj types.Object) (*hoverResult, error) {\n\t// Special handling for error.Error, which is the only builtin method.\n\t//\n\t// TODO(rfindley): can this be unified with the handling below?\n\tif obj.Name() == \"Error\" {\n\t\tsignature := obj.String()\n\t\treturn &hoverResult{\n\t\t\tSignature:  signature,\n\t\t\tSingleLine: signature,\n\t\t\t// TODO(rfindley): these are better than the current behavior.\n\t\t\t// SymbolName: \"(error).Error\",\n\t\t\t// LinkPath:   \"builtin\",\n\t\t\t// LinkAnchor: \"error.Error\",\n\t\t}, nil\n\t}\n\n\tpgf, ident, err := builtinDecl(ctx, snapshot, obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar (\n\t\tcomment *ast.CommentGroup\n\t\tdecl    ast.Decl\n\t)\n\tcurIdent, _ := pgf.Cursor().FindNode(ident) // can't fail\n\tfor cur := range curIdent.Enclosing() {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.GenDecl:\n\t\t\t// Separate documentation and signature.\n\t\t\tcomment = n.Doc\n\t\t\tnode2 := *n\n\t\t\tnode2.Doc = nil\n\t\t\tdecl = &node2\n\t\tcase *ast.FuncDecl:\n\t\t\t// Ditto.\n\t\t\tcomment = n.Doc\n\t\t\tnode2 := *n\n\t\t\tnode2.Doc = nil\n\t\t\tdecl = &node2\n\t\t}\n\t}\n\n\tsignature := formatNodeFile(pgf.Tok, decl)\n\t// Replace fake types with their common equivalent.\n\t// TODO(rfindley): we should instead use obj.Type(), which would have the\n\t// *actual* types of the builtin call.\n\tsignature = replacer.Replace(signature)\n\n\tdocText := comment.Text()\n\treturn &hoverResult{\n\t\tSynopsis:          doc.Synopsis(docText),\n\t\tFullDocumentation: docText,\n\t\tSignature:         signature,\n\t\tSingleLine:        obj.String(),\n\t\tSymbolName:        obj.Name(),\n\t\tLinkPath:          \"builtin\",\n\t\tLinkAnchor:        obj.Name(),\n\t}, nil\n}\n\n// hoverPackageRef computes hover information for the package of the specified\n// path imported by pkg. If we do not have metadata for the hovered import, it\n// returns _\nfunc hoverPackageRef(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, importPath metadata.ImportPath) (*hoverResult, error) {\n\timpID := pkg.Metadata().DepsByImpPath[importPath]\n\tif impID == \"\" {\n\t\treturn nil, fmt.Errorf(\"no package data for import %q\", importPath)\n\t}\n\timpMetadata := snapshot.Metadata(impID)\n\tif impMetadata == nil {\n\t\treturn nil, bug.Errorf(\"failed to resolve import ID %q\", impID)\n\t}\n\n\t// Find the first file with a package doc comment.\n\tvar comment *ast.CommentGroup\n\tfor _, f := range impMetadata.CompiledGoFiles {\n\t\tfh, err := snapshot.ReadFile(ctx, f)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif pgf.File.Doc != nil {\n\t\t\tcomment = pgf.File.Doc\n\t\t\tbreak\n\t\t}\n\t}\n\n\tdocText := comment.Text()\n\treturn &hoverResult{\n\t\tSignature:         \"package \" + string(impMetadata.Name),\n\t\tSynopsis:          doc.Synopsis(docText),\n\t\tFullDocumentation: docText,\n\t}, nil\n}\n\n// hoverPackageName computes hover information for the package name of the file\n// pgf in pkg.\nfunc hoverPackageName(pkg *cache.Package, pgf *parsego.File) (protocol.Range, *hoverResult, error) {\n\tvar comment *ast.CommentGroup\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tif pgf.File.Doc != nil {\n\t\t\tcomment = pgf.File.Doc\n\t\t\tbreak\n\t\t}\n\t}\n\trng, err := pgf.NodeRange(pgf.File.Name)\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\tdocText := comment.Text()\n\n\t// List some package attributes at the bottom of the documentation, if\n\t// applicable.\n\ttype attr struct{ title, value string }\n\tvar attrs []attr\n\n\tif !metadata.IsCommandLineArguments(pkg.Metadata().ID) {\n\t\tattrs = append(attrs, attr{\"Package path\", string(pkg.Metadata().PkgPath)})\n\t}\n\n\tif pkg.Metadata().Module != nil {\n\t\tattrs = append(attrs, attr{\"Module\", pkg.Metadata().Module.Path})\n\t}\n\n\t// Show the effective language version for this package.\n\tif v := pkg.TypesInfo().FileVersions[pgf.File]; v != \"\" {\n\t\tattr := attr{value: version.Lang(v)}\n\t\tif v == pkg.Types().GoVersion() {\n\t\t\tattr.title = \"Language version\"\n\t\t} else {\n\t\t\tattr.title = \"Language version (current file)\"\n\t\t}\n\t\tattrs = append(attrs, attr)\n\t}\n\n\t// TODO(rfindley): consider exec'ing go here to compute DefaultGODEBUG, or\n\t// propose adding GODEBUG info to go/packages.\n\n\tvar footer strings.Builder\n\tfor i, attr := range attrs {\n\t\tif i > 0 {\n\t\t\tfooter.WriteString(\"\\n\")\n\t\t}\n\t\tfmt.Fprintf(&footer, \" - %s: %s\", attr.title, attr.value)\n\t}\n\n\treturn rng, &hoverResult{\n\t\tSignature:         \"package \" + string(pkg.Metadata().Name),\n\t\tSynopsis:          doc.Synopsis(docText),\n\t\tFullDocumentation: docText,\n\t\tfooter:            footer.String(),\n\t}, nil\n}\n\n// hoverConstantExpr computes information about the value of a constant expression.\n//\n// The provided start and end positions must be precise. For example, when hovering\n// over a string literal, the exact cursor position is used to identify and display\n// the value of the rune under the cursor.\nfunc hoverConstantExpr(pgf *parsego.File, expr ast.Expr, tv types.TypeAndValue, posRange astutil.Range) (protocol.Range, *hoverResult, error) {\n\tvar (\n\t\tvalue      string    // if non-empty, a constant value to format in hover\n\t\tr          rune      // if non-zero, format a description of this rune in hover\n\t\tstart, end token.Pos // hover span\n\t)\n\tif lit, ok := expr.(*ast.BasicLit); ok {\n\t\tswitch tv.Value.Kind() {\n\t\tcase constant.Bool:\n\t\t\tfallthrough\n\t\tcase constant.Float:\n\t\t\tfallthrough\n\t\tcase constant.Complex:\n\t\t\tfallthrough\n\t\tcase constant.Unknown:\n\t\t\t// In most cases, basic literals are uninteresting.\n\t\t\tbreak\n\t\tcase constant.Int:\n\t\t\tswitch lit.Kind {\n\t\t\tcase token.CHAR:\n\t\t\t\ts, err := strconv.Unquote(lit.Value)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// If the conversion fails, it's because of an invalid syntax, therefore\n\t\t\t\t\t// there is no rune to be found.\n\t\t\t\t\treturn protocol.Range{}, nil, nil\n\t\t\t\t}\n\t\t\t\tr, _ = utf8.DecodeRuneInString(s)\n\t\t\t\tif r == utf8.RuneError {\n\t\t\t\t\treturn protocol.Range{}, nil, fmt.Errorf(\"rune error\")\n\t\t\t\t}\n\t\t\t\tstart, end = lit.Pos(), lit.End()\n\t\t\tcase token.INT:\n\t\t\t\t// Short literals (e.g. 99 decimal, 07 octal) are uninteresting.\n\t\t\t\tif len(lit.Value) < 3 {\n\t\t\t\t\treturn protocol.Range{}, nil, nil\n\t\t\t\t}\n\n\t\t\t\tv := constant.MakeFromLiteral(lit.Value, lit.Kind, 0)\n\t\t\t\tif v.Kind() != constant.Int {\n\t\t\t\t\treturn protocol.Range{}, nil, nil\n\t\t\t\t}\n\n\t\t\t\tswitch lit.Value[:2] {\n\t\t\t\tcase \"0x\", \"0X\":\n\t\t\t\t\t// As a special case, try to recognize hexadecimal literals as runes if\n\t\t\t\t\t// they are within the range of valid unicode values.\n\t\t\t\t\tif v, ok := constant.Int64Val(v); ok && v > 0 && v <= utf8.MaxRune && utf8.ValidRune(rune(v)) {\n\t\t\t\t\t\tr = rune(v)\n\t\t\t\t\t}\n\t\t\t\t\tfallthrough\n\t\t\t\tcase \"0o\", \"0O\", \"0b\", \"0B\":\n\t\t\t\t\t// Format the decimal value of non-decimal literals.\n\t\t\t\t\tvalue = v.ExactString()\n\t\t\t\t\tstart, end = lit.Pos(), lit.End()\n\t\t\t\tdefault:\n\t\t\t\t\treturn protocol.Range{}, nil, nil\n\t\t\t\t}\n\t\t\t}\n\t\tcase constant.String:\n\t\t\tindex, err := astutil.OffsetInStringLiteral(lit, posRange.Pos())\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\t\t\t// pos is the point in the literal where the current rune starts.\n\t\t\tpos, err := astutil.PosInStringLiteral(lit, index)\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\n\t\t\trest, err := pgf.PosText(pos, lit.End())\n\t\t\tif err != nil {\n\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t}\n\n\t\t\t// Is the selected character denoted by an escape sequence?\n\t\t\tif bytes.HasPrefix(rest, []byte(`\\`)) {\n\t\t\t\trr, _, tail, err := strconv.UnquoteChar(string(rest), lit.Value[0])\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn protocol.Range{}, nil, err\n\t\t\t\t}\n\n\t\t\t\trawSize := len(rest) - len(tail)\n\n\t\t\t\tstart, end = pos, pos+token.Pos(rawSize)\n\t\t\t\tr = rr\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unexpected constant.Kind\")\n\t\t}\n\t} else {\n\t\t// By default, provide value information and the expression's range.\n\t\t// It is possible evaluated value will give us the wrong number because\n\t\t// type checker will perform error recovery.\n\t\t// E.g. expression like '\\u22111' + 1 is invalid but type checker\n\t\t// will yield the value of `\\u2211` + 1.\n\n\t\t// We could be more smart about whether we want to evaluate an\n\t\t// [ast.Expr] as a number or as a rune by evaluating the syntax of\n\t\t// the expression. e.g. rune + int => rune, rune - int => rune.\n\t\tvalue = tv.Value.String()\n\t\tstart, end = expr.Pos(), expr.End()\n\t}\n\n\tif value == \"\" && r == 0 { // nothing to format\n\t\treturn protocol.Range{}, nil, nil\n\t}\n\n\trng, err := pgf.PosRange(start, end)\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\n\tvar b strings.Builder\n\tif value != \"\" {\n\t\tb.WriteString(value)\n\t}\n\tif r != 0 {\n\t\truneName := runenames.Name(r)\n\t\tif len(runeName) > 0 && runeName[0] == '<' {\n\t\t\t// Check if the rune looks like an HTML tag. If so, trim the surrounding <>\n\t\t\t// characters to work around https://github.com/microsoft/vscode/issues/124042.\n\t\t\truneName = strings.TrimRight(runeName[1:], \">\")\n\t\t}\n\t\tif b.Len() > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tif strconv.IsPrint(r) {\n\t\t\tfmt.Fprintf(&b, \"'%c', \", r)\n\t\t}\n\t\tfmt.Fprintf(&b, \"U+%04X, %s\", r, runeName)\n\t}\n\thover := b.String()\n\treturn rng, &hoverResult{\n\t\tSynopsis:          hover,\n\t\tFullDocumentation: hover,\n\t}, nil\n}\n\nfunc hoverReturnStatement(pgf *parsego.File, curReturn inspector.Cursor) (protocol.Range, *hoverResult, error) {\n\tvar funcType *ast.FuncType\n\t// Find innermost enclosing function.\n\tfor c := range curReturn.Enclosing((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {\n\t\tswitch n := c.Node().(type) {\n\t\tcase *ast.FuncLit:\n\t\t\tfuncType = n.Type\n\t\tcase *ast.FuncDecl:\n\t\t\tfuncType = n.Type\n\t\t}\n\t\tif funcType != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\t// Inv: funcType != nil because a ReturnStmt is always enclosed by a function.\n\tif funcType.Results == nil {\n\t\treturn protocol.Range{}, nil, nil // no result variables\n\t}\n\trng, err := pgf.NodeRange(curReturn.Node())\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\t// Format the function's result type.\n\tvar buf strings.Builder\n\tvar cfg printer.Config\n\tfset := token.NewFileSet()\n\tbuf.WriteString(\"returns (\")\n\tfor i, field := range funcType.Results.List {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tcfg.Fprint(&buf, fset, field.Type) // ignore error\n\t}\n\tbuf.WriteByte(')')\n\treturn rng, &hoverResult{\n\t\tSignature: buf.String(),\n\t}, nil\n}\n\n// hoverEmbed computes hover information for a filepath.Match pattern.\n// Assumes that the pattern is relative to the location of fh.\nfunc hoverEmbed(fh file.Handle, rng protocol.Range, pattern string) (protocol.Range, *hoverResult, error) {\n\ts := &strings.Builder{}\n\n\tdir := fh.URI().DirPath()\n\tvar matches []string\n\terr := filepath.WalkDir(dir, func(abs string, d fs.DirEntry, e error) error {\n\t\tif e != nil {\n\t\t\treturn e\n\t\t}\n\t\trel, err := filepath.Rel(dir, abs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tok, err := filepath.Match(pattern, rel)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif ok && !d.IsDir() {\n\t\t\tmatches = append(matches, rel)\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn protocol.Range{}, nil, err\n\t}\n\n\tfor _, m := range matches {\n\t\t// TODO: Renders each file as separate markdown paragraphs.\n\t\t// If forcing (a single) newline is possible it might be more clear.\n\t\tfmt.Fprintf(s, \"%s\\n\\n\", m)\n\t}\n\n\tres := &hoverResult{\n\t\tSignature:         fmt.Sprintf(\"Embedding %q\", pattern),\n\t\tSynopsis:          s.String(),\n\t\tFullDocumentation: s.String(),\n\t}\n\treturn rng, res, nil\n}\n\n// inferredSignatureString is a wrapper around the types.ObjectString function\n// that adds more information to inferred signatures. It will return an empty string\n// if the passed types.Object is not a signature.\nfunc inferredSignatureString(obj types.Object, qual types.Qualifier, inferred *types.Signature) string {\n\t// If the signature type was inferred, prefer the inferred signature with a\n\t// comment showing the generic signature.\n\tif sig, _ := obj.Type().Underlying().(*types.Signature); sig != nil && sig.TypeParams().Len() > 0 && inferred != nil {\n\t\tobj2 := types.NewFunc(obj.Pos(), obj.Pkg(), obj.Name(), inferred)\n\t\tstr := types.ObjectString(obj2, qual)\n\t\t// Try to avoid overly long lines.\n\t\tif len(str) > 60 {\n\t\t\tstr += \"\\n\"\n\t\t} else {\n\t\t\tstr += \" \"\n\t\t}\n\t\tstr += \"// \" + types.TypeString(sig, qual)\n\t\treturn str\n\t}\n\treturn \"\"\n}\n\n// objectString is a wrapper around the types.ObjectString function.\n// It handles adding more information to the object string.\n// If spec is non-nil, it may be used to format additional declaration\n// syntax, and file must be the token.File describing its positions.\n//\n// Precondition: obj is not a built-in function or method.\nfunc objectString(obj types.Object, qual types.Qualifier, declPos token.Pos, file *token.File, spec ast.Spec) string {\n\tstr := types.ObjectString(obj, qual)\n\n\tswitch obj := obj.(type) {\n\tcase *types.Func:\n\t\t// We fork ObjectString to improve its rendering of methods:\n\t\t// specifically, we show the receiver name,\n\t\t// and replace the period in (T).f by a space (#62190).\n\n\t\tsig := obj.Signature()\n\n\t\tvar buf bytes.Buffer\n\t\tbuf.WriteString(\"func \")\n\t\tif recv := sig.Recv(); recv != nil {\n\t\t\tbuf.WriteByte('(')\n\t\t\tif _, ok := recv.Type().(*types.Interface); ok {\n\t\t\t\t// gcimporter creates abstract methods of\n\t\t\t\t// named interfaces using the interface type\n\t\t\t\t// (not the named type) as the receiver.\n\t\t\t\t// Don't print it in full.\n\t\t\t\tbuf.WriteString(\"interface\")\n\t\t\t} else {\n\t\t\t\t// Show receiver name (go/types does not).\n\t\t\t\tname := recv.Name()\n\t\t\t\tif name != \"\" && name != \"_\" {\n\t\t\t\t\tbuf.WriteString(name)\n\t\t\t\t\tbuf.WriteString(\" \")\n\t\t\t\t}\n\t\t\t\ttypes.WriteType(&buf, recv.Type(), qual)\n\t\t\t}\n\t\t\tbuf.WriteByte(')')\n\t\t\tbuf.WriteByte(' ') // space (go/types uses a period)\n\t\t} else if s := qual(obj.Pkg()); s != \"\" {\n\t\t\tbuf.WriteString(s)\n\t\t\tbuf.WriteString(\".\")\n\t\t}\n\t\tbuf.WriteString(obj.Name())\n\t\ttypes.WriteSignature(&buf, sig, qual)\n\t\tstr = buf.String()\n\n\tcase *types.Const:\n\t\t// Show value of a constant.\n\t\tvar (\n\t\t\tdeclaration = obj.Val().String() // default formatted declaration\n\t\t\tcomment     = \"\"                 // if non-empty, a clarifying comment\n\t\t)\n\n\t\t// Try to use the original declaration.\n\t\tswitch obj.Val().Kind() {\n\t\tcase constant.String:\n\t\t\t// Usually the original declaration of a string doesn't carry much information.\n\t\t\t// Also strings can be very long. So, just use the constant's value.\n\n\t\tdefault:\n\t\t\tif spec, _ := spec.(*ast.ValueSpec); spec != nil {\n\t\t\t\tfor i, name := range spec.Names {\n\t\t\t\t\tif declPos == name.Pos() {\n\t\t\t\t\t\tif i < len(spec.Values) {\n\t\t\t\t\t\t\toriginalDeclaration := formatNodeFile(file, spec.Values[i])\n\t\t\t\t\t\t\tif originalDeclaration != declaration {\n\t\t\t\t\t\t\t\tcomment = declaration\n\t\t\t\t\t\t\t\tdeclaration = originalDeclaration\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Special formatting cases.\n\t\tswitch typ := types.Unalias(obj.Type()).(type) {\n\t\tcase *types.Named:\n\t\t\t// Try to add a formatted duration as an inline comment.\n\t\t\tpkg := typ.Obj().Pkg()\n\t\t\tif pkg.Path() == \"time\" && typ.Obj().Name() == \"Duration\" && obj.Val().Kind() == constant.Int {\n\t\t\t\tif d, ok := constant.Int64Val(obj.Val()); ok {\n\t\t\t\t\tcomment = time.Duration(d).String()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif comment == declaration {\n\t\t\tcomment = \"\"\n\t\t}\n\n\t\tstr += \" = \" + declaration\n\t\tif comment != \"\" {\n\t\t\tstr += \" // \" + comment\n\t\t}\n\t}\n\treturn str\n}\n\n// HoverDocForObject returns the best doc comment for obj (for which\n// fset provides file/line information).\n//\n// TODO(rfindley): there appears to be zero(!) tests for this functionality.\nfunc HoverDocForObject(ctx context.Context, snapshot *cache.Snapshot, fset *token.FileSet, obj types.Object) (*ast.CommentGroup, error) {\n\tif is[*types.TypeName](obj) && is[*types.TypeParam](obj.Type()) {\n\t\treturn nil, nil\n\t}\n\n\tpgf, pos, err := parseFull(ctx, snapshot, fset, obj)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"re-parsing: %v\", err)\n\t}\n\n\tdecl, spec, field := findDeclInfo([]*ast.File{pgf.File}, pos)\n\treturn chooseDocComment(decl, spec, field), nil\n}\n\nfunc chooseDocComment(decl ast.Decl, spec ast.Spec, field *ast.Field) *ast.CommentGroup {\n\tif field != nil {\n\t\tif field.Doc != nil {\n\t\t\treturn field.Doc\n\t\t}\n\t\tif field.Comment != nil {\n\t\t\treturn field.Comment\n\t\t}\n\t\treturn nil\n\t}\n\tswitch decl := decl.(type) {\n\tcase *ast.FuncDecl:\n\t\treturn decl.Doc\n\tcase *ast.GenDecl:\n\t\tswitch spec := spec.(type) {\n\t\tcase *ast.ValueSpec:\n\t\t\tif spec.Doc != nil {\n\t\t\t\treturn spec.Doc\n\t\t\t}\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\t\treturn spec.Comment\n\t\tcase *ast.TypeSpec:\n\t\t\tif spec.Doc != nil {\n\t\t\t\treturn spec.Doc\n\t\t\t}\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\t\treturn spec.Comment\n\t\t}\n\t}\n\treturn nil\n}\n\n// parseFull fully parses the file containing the declaration of obj\n// (for which fset provides file/line information). It returns the\n// parsego.File and the position of the declaration within it.\n//\n// BEWARE: the provided FileSet is used only to interpret the provided\n// pos; the resulting File and Pos may belong to the same or a\n// different FileSet, such as one synthesized by the parser cache, if\n// parse-caching is enabled.\nfunc parseFull(ctx context.Context, snapshot *cache.Snapshot, fset *token.FileSet, obj types.Object) (*parsego.File, token.Pos, error) {\n\tif isBuiltin(obj) {\n\t\tpgf, id, err := builtinDecl(ctx, snapshot, obj)\n\t\tif err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\treturn pgf, id.Pos(), err\n\t}\n\tpos := obj.Pos()\n\tf := fset.File(pos)\n\tif f == nil {\n\t\treturn nil, 0, bug.Errorf(\"internal error: no file for position %d\", pos)\n\t}\n\n\turi := protocol.URIFromPath(f.Name())\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\n\t// Translate pos from original file to new file.\n\toffset, err := safetoken.Offset(f, pos)\n\tif err != nil {\n\t\treturn nil, 0, bug.Errorf(\"offset out of bounds in %q\", uri)\n\t}\n\tfullPos, err := safetoken.Pos(pgf.Tok, offset)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\n\treturn pgf, fullPos, nil\n}\n\n// If pkgURL is non-nil, it should be used to generate doc links.\nfunc formatHover(h *hoverResult, options *settings.Options, pkgURL func(path PackagePath, fragment string) protocol.URI) (string, error) {\n\tmarkdown := options.PreferredContentFormat == protocol.Markdown\n\tmaybeFenced := func(s string) string {\n\t\tif s != \"\" && markdown {\n\t\t\ts = fmt.Sprintf(\"```go\\n%s\\n```\", strings.Trim(s, \"\\n\"))\n\t\t}\n\t\treturn s\n\t}\n\n\tswitch options.HoverKind {\n\tcase settings.SingleLine:\n\t\treturn h.SingleLine, nil\n\n\tcase settings.NoDocumentation:\n\t\treturn maybeFenced(h.Signature), nil\n\n\tcase settings.Structured:\n\t\tb, err := json.Marshal(h)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn string(b), nil\n\n\tcase settings.SynopsisDocumentation, settings.FullDocumentation:\n\t\tvar sections [][]string // assembled below\n\n\t\t// Signature section.\n\t\t//\n\t\t// For types, we display TypeDecl and Methods,\n\t\t// but not Signature, which is redundant (= TypeDecl + \"\\n\" + Methods).\n\t\t// For all other symbols, we display Signature;\n\t\t// TypeDecl and Methods are empty.\n\t\t// TODO(golang/go#70233): When JSON is no more, we could rationalize this.\n\t\tif h.typeDecl != \"\" {\n\t\t\tsections = append(sections, []string{maybeFenced(h.typeDecl)})\n\t\t} else {\n\t\t\tsections = append(sections, []string{maybeFenced(h.Signature)})\n\t\t}\n\n\t\t// Doc section.\n\t\tvar doc string\n\t\tswitch options.HoverKind {\n\t\tcase settings.SynopsisDocumentation:\n\t\t\tdoc = h.Synopsis\n\t\tcase settings.FullDocumentation:\n\t\t\tdoc = h.FullDocumentation\n\t\t}\n\t\tif options.PreferredContentFormat == protocol.Markdown {\n\t\t\tdoc = DocCommentToMarkdown(doc, options)\n\t\t}\n\t\tsections = append(sections, []string{\n\t\t\tdoc,\n\t\t\tmaybeFenced(h.promotedFields),\n\t\t\tmaybeFenced(h.methods),\n\t\t})\n\n\t\t// Footer section.\n\t\tsections = append(sections, []string{\n\t\t\th.footer,\n\t\t\tformatLink(h, options, pkgURL),\n\t\t})\n\n\t\tvar b strings.Builder\n\t\tnewline := func() {\n\t\t\tif options.PreferredContentFormat == protocol.Markdown {\n\t\t\t\tb.WriteString(\"\\n\\n\")\n\t\t\t} else {\n\t\t\t\tb.WriteByte('\\n')\n\t\t\t}\n\t\t}\n\t\tfor _, section := range sections {\n\t\t\tstart := b.Len()\n\t\t\tfor _, part := range section {\n\t\t\t\tif part == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// When markdown is available, insert an hline before the start of\n\t\t\t\t// the section, if there is content above.\n\t\t\t\tif markdown && b.Len() == start && start > 0 {\n\t\t\t\t\tnewline()\n\t\t\t\t\tb.WriteString(\"---\")\n\t\t\t\t}\n\t\t\t\tif b.Len() > 0 {\n\t\t\t\t\tnewline()\n\t\t\t\t}\n\t\t\t\tb.WriteString(part)\n\t\t\t}\n\t\t}\n\t\treturn b.String(), nil\n\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"invalid HoverKind: %v\", options.HoverKind)\n\t}\n}\n\n// StdSymbolOf returns the std lib symbol information of the given obj.\n// It returns nil if the input obj is not an exported standard library symbol.\nfunc StdSymbolOf(obj types.Object) *stdlib.Symbol {\n\tif !obj.Exported() || obj.Pkg() == nil {\n\t\treturn nil\n\t}\n\n\t// Symbols that not defined in standard library should return early.\n\t// TODO(hxjiang): The returned slices is binary searchable.\n\tsymbols := stdlib.PackageSymbols[obj.Pkg().Path()]\n\tif symbols == nil {\n\t\treturn nil\n\t}\n\n\t// Handle Function, Type, Const & Var.\n\tif obj != nil && typesinternal.IsPackageLevel(obj) {\n\t\tfor _, s := range symbols {\n\t\t\tif s.Kind == stdlib.Method || s.Kind == stdlib.Field {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif s.Name == obj.Name() {\n\t\t\t\treturn &s\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Handle Method.\n\tif fn, _ := obj.(*types.Func); fn != nil {\n\t\tisPtr, named := typesinternal.ReceiverNamed(fn.Signature().Recv())\n\t\tif named != nil && typesinternal.IsPackageLevel(named.Obj()) {\n\t\t\tfor _, s := range symbols {\n\t\t\t\tif s.Kind != stdlib.Method {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tptr, recv, name := s.SplitMethod()\n\t\t\t\tif ptr == isPtr && recv == named.Obj().Name() && name == fn.Name() {\n\t\t\t\t\treturn &s\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\n\t// Handle Field.\n\tif v, _ := obj.(*types.Var); v != nil && v.IsField() {\n\t\tfor _, s := range symbols {\n\t\t\tif s.Kind != stdlib.Field {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttypeName, fieldName := s.SplitField()\n\t\t\tif fieldName != v.Name() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttypeObj := obj.Pkg().Scope().Lookup(typeName)\n\t\t\tif typeObj == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif fieldObj, _, _ := types.LookupFieldOrMethod(typeObj.Type(), true, obj.Pkg(), fieldName); obj == fieldObj {\n\t\t\t\treturn &s\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn nil\n}\n\n// If pkgURL is non-nil, it should be used to generate doc links.\nfunc formatLink(h *hoverResult, options *settings.Options, pkgURL func(path PackagePath, fragment string) protocol.URI) string {\n\tif options.LinksInHover == settings.LinksInHover_None || h.LinkPath == \"\" {\n\t\treturn \"\"\n\t}\n\tvar url protocol.URI\n\tvar caption string\n\tif pkgURL != nil { // LinksInHover == \"gopls\"\n\t\t// Discard optional module version portion.\n\t\t// (Ideally the hoverResult would retain the structure...)\n\t\tpath := h.LinkPath\n\t\tif module, versionDir, ok := strings.Cut(h.LinkPath, \"@\"); ok {\n\t\t\t// \"module@version/dir\"\n\t\t\tpath = module\n\t\t\tif _, dir, ok := strings.Cut(versionDir, \"/\"); ok {\n\t\t\t\tpath += \"/\" + dir\n\t\t\t}\n\t\t}\n\t\turl = pkgURL(PackagePath(path), h.LinkAnchor)\n\t\tcaption = \"in gopls doc viewer\"\n\t} else {\n\t\tif options.LinkTarget == \"\" {\n\t\t\treturn \"\"\n\t\t}\n\t\turl = cache.BuildLink(options.LinkTarget, h.LinkPath, h.LinkAnchor)\n\t\tcaption = \"on \" + options.LinkTarget\n\t}\n\tswitch options.PreferredContentFormat {\n\tcase protocol.Markdown:\n\t\treturn fmt.Sprintf(\"[`%s` %s](%s)\", h.SymbolName, caption, url)\n\tcase protocol.PlainText:\n\t\treturn \"\"\n\tdefault:\n\t\treturn url\n\t}\n}\n\n// findDeclInfo returns the syntax nodes involved in the declaration of the\n// types.Object with position pos, searching the given list of file syntax\n// trees.\n//\n// Pos may be the position of the name-defining identifier in a FuncDecl,\n// ValueSpec, TypeSpec, Field, or as a special case the position of\n// Ellipsis.Elt in an ellipsis field.\n//\n// If found, the resulting decl, spec, and field will be the inner-most\n// instance of each node type surrounding pos.\n//\n// If field is non-nil, pos is the position of a field Var. If field is nil and\n// spec is non-nil, pos is the position of a Var, Const, or TypeName object. If\n// both field and spec are nil and decl is non-nil, pos is the position of a\n// Func object.\n//\n// It returns a nil decl if no object-defining node is found at pos.\n//\n// TODO(rfindley): this function has tricky semantics, and may be worth unit\n// testing and/or refactoring.\nfunc findDeclInfo(files []*ast.File, pos token.Pos) (decl ast.Decl, spec ast.Spec, field *ast.Field) {\n\tfound := false\n\n\t// Visit the files in search of the node at pos.\n\tstack := make([]ast.Node, 0, 20)\n\n\t// Allocate the closure once, outside the loop.\n\tf := func(n ast.Node, stack []ast.Node) bool {\n\t\tif found {\n\t\t\treturn false\n\t\t}\n\n\t\t// Skip subtrees (incl. files) that don't contain the search point.\n\t\tif !(n.Pos() <= pos && pos < n.End()) {\n\t\t\treturn false\n\t\t}\n\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Field:\n\t\t\tfindEnclosingDeclAndSpec := func() {\n\t\t\t\tfor i := len(stack) - 1; i >= 0; i-- {\n\t\t\t\t\tswitch n := stack[i].(type) {\n\t\t\t\t\tcase ast.Spec:\n\t\t\t\t\t\tspec = n\n\t\t\t\t\tcase ast.Decl:\n\t\t\t\t\t\tdecl = n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check each field name since you can have\n\t\t\t// multiple names for the same type expression.\n\t\t\tfor _, id := range n.Names {\n\t\t\t\tif id.Pos() == pos {\n\t\t\t\t\tfield = n\n\t\t\t\t\tfindEnclosingDeclAndSpec()\n\t\t\t\t\tfound = true\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check *ast.Field itself. This handles embedded\n\t\t\t// fields which have no associated *ast.Ident name.\n\t\t\tif n.Pos() == pos {\n\t\t\t\tfield = n\n\t\t\t\tfindEnclosingDeclAndSpec()\n\t\t\t\tfound = true\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Also check \"X\" in \"...X\". This makes it easy to format variadic\n\t\t\t// signature params properly.\n\t\t\t//\n\t\t\t// TODO(rfindley): I don't understand this comment. How does finding the\n\t\t\t// field in this case make it easier to format variadic signature params?\n\t\t\tif ell, ok := n.Type.(*ast.Ellipsis); ok && ell.Elt != nil && ell.Elt.Pos() == pos {\n\t\t\t\tfield = n\n\t\t\t\tfindEnclosingDeclAndSpec()\n\t\t\t\tfound = true\n\t\t\t\treturn false\n\t\t\t}\n\n\t\tcase *ast.FuncDecl:\n\t\t\tif n.Name.Pos() == pos {\n\t\t\t\tdecl = n\n\t\t\t\tfound = true\n\t\t\t\treturn false\n\t\t\t}\n\n\t\tcase *ast.GenDecl:\n\t\t\tfor _, s := range n.Specs {\n\t\t\t\tswitch s := s.(type) {\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tif s.Name.Pos() == pos {\n\t\t\t\t\t\tdecl = n\n\t\t\t\t\t\tspec = s\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, id := range s.Names {\n\t\t\t\t\t\tif id.Pos() == pos {\n\t\t\t\t\t\t\tdecl = n\n\t\t\t\t\t\t\tspec = s\n\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\tfor _, file := range files {\n\t\tast.PreorderStack(file, stack, f)\n\t\tif found {\n\t\t\treturn decl, spec, field\n\t\t}\n\t}\n\n\treturn nil, nil, nil\n}\n\ntype promotedField struct {\n\tpath  string // path (e.g. \"x.y\" through embedded fields)\n\tfield *types.Var\n}\n\n// promotedFields returns the list of accessible promoted fields of a struct type t.\n// (Logic plundered from x/tools/cmd/guru/describe.go.)\nfunc promotedFields(t types.Type, from *types.Package) []promotedField {\n\twantField := func(f *types.Var) bool {\n\t\tif !accessibleTo(f, from) {\n\t\t\treturn false\n\t\t}\n\t\t// Check that the field is not shadowed.\n\t\tobj, _, _ := types.LookupFieldOrMethod(t, true, f.Pkg(), f.Name())\n\t\treturn obj == f\n\t}\n\n\tvar fields []promotedField\n\tvar visit func(t types.Type, stack []*types.Named)\n\tvisit = func(t types.Type, stack []*types.Named) {\n\t\ttStruct, ok := typesinternal.Unpointer(t).Underlying().(*types.Struct)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\tfieldloop:\n\t\tfor f := range tStruct.Fields() {\n\n\t\t\t// Handle recursion through anonymous fields.\n\t\t\tif f.Anonymous() {\n\t\t\t\tif _, named := typesinternal.ReceiverNamed(f); named != nil {\n\t\t\t\t\t// If we've already visited this named type\n\t\t\t\t\t// on this path, break the cycle.\n\t\t\t\t\tfor _, x := range stack {\n\t\t\t\t\t\tif x.Origin() == named.Origin() {\n\t\t\t\t\t\t\tcontinue fieldloop\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvisit(f.Type(), append(stack, named))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Save accessible promoted fields.\n\t\t\tif len(stack) > 0 && wantField(f) {\n\t\t\t\tvar path strings.Builder\n\t\t\t\tfor i, t := range stack {\n\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\tpath.WriteByte('.')\n\t\t\t\t\t}\n\t\t\t\t\tpath.WriteString(t.Obj().Name())\n\t\t\t\t}\n\t\t\t\tfields = append(fields, promotedField{\n\t\t\t\t\tpath:  path.String(),\n\t\t\t\t\tfield: f,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\tvisit(t, nil)\n\n\treturn fields\n}\n\nfunc accessibleTo(obj types.Object, pkg *types.Package) bool {\n\treturn obj.Exported() || obj.Pkg() == pkg\n}\n\n// computeSizeOffsetInfo reports the size of obj (if a type or struct\n// field), its wasted space percentage (if a struct type), and its\n// offset (if a struct field). curIdent is obj's declaring identifier.\n// It returns -1 for undefined components.\nfunc computeSizeOffsetInfo(pkg *cache.Package, curIdent inspector.Cursor, obj types.Object) (size, wasted, offset int64) {\n\tsize, wasted, offset = -1, -1, -1\n\n\tvar free typeparams.Free\n\tsizes := pkg.TypesSizes()\n\n\t// size (types and fields)\n\tif v, ok := obj.(*types.Var); ok && v.IsField() || is[*types.TypeName](obj) {\n\t\t// If the field's type has free type parameters,\n\t\t// its size cannot be computed.\n\t\tif !free.Has(obj.Type()) {\n\t\t\tsize = sizes.Sizeof(obj.Type())\n\t\t}\n\n\t\t// wasted space (struct types)\n\t\tif tStruct, ok := obj.Type().Underlying().(*types.Struct); ok && is[*types.TypeName](obj) && size > 0 {\n\t\t\tfields := slices.Collect(tStruct.Fields())\n\t\t\tif len(fields) > 0 {\n\t\t\t\t// Sort into descending (most compact) order\n\t\t\t\t// and recompute size of entire struct.\n\t\t\t\tsort.Slice(fields, func(i, j int) bool {\n\t\t\t\t\treturn sizes.Sizeof(fields[i].Type()) >\n\t\t\t\t\t\tsizes.Sizeof(fields[j].Type())\n\t\t\t\t})\n\t\t\t\toffsets := sizes.Offsetsof(fields)\n\t\t\t\tcompactSize := offsets[len(offsets)-1] + sizes.Sizeof(fields[len(fields)-1].Type())\n\t\t\t\twasted = 100 * (size - compactSize) / size\n\t\t\t}\n\t\t}\n\t}\n\n\t// offset (fields)\n\tif v, ok := obj.(*types.Var); ok && v.IsField() {\n\t\t// Find enclosing struct type.\n\t\tvar tStruct *types.Struct\n\t\tif n, _ := cursorutil.FirstEnclosing[*ast.StructType](curIdent); n != nil {\n\t\t\tt, ok := pkg.TypesInfo().TypeOf(n).(*types.Struct)\n\t\t\tif ok {\n\t\t\t\t// golang/go#69150: TypeOf(n) was observed not to be a Struct (likely\n\t\t\t\t// nil) in some cases.\n\t\t\t\ttStruct = t\n\t\t\t}\n\t\t}\n\t\tif tStruct != nil {\n\t\t\tvar fields []*types.Var\n\t\t\tfor f := range tStruct.Fields() {\n\t\t\t\t// If any preceding field's type has free type parameters,\n\t\t\t\t// its offset cannot be computed.\n\t\t\t\tif free.Has(f.Type()) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tfields = append(fields, f)\n\t\t\t\tif f == v {\n\t\t\t\t\toffsets := sizes.Offsetsof(fields)\n\t\t\t\t\toffset = offsets[len(offsets)-1]\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n\n// sizeClass reports the size class for a struct of the specified size, or -1 if unknown.f\n// See GOROOT/src/runtime/msize.go for details.\nfunc sizeClass(size int64) int64 {\n\tif size > 1<<16 {\n\t\treturn -1 // avoid allocation\n\t}\n\t// We assume that bytes.Clone doesn't trim,\n\t// and reports the underlying size class; see TestSizeClass.\n\treturn int64(cap(bytes.Clone(make([]byte, size))))\n}\n"
  },
  {
    "path": "gopls/internal/golang/hover_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport \"testing\"\n\nfunc TestSizeClass(t *testing.T) {\n\t// See GOROOT/src/runtime/msize.go for details.\n\tfor _, test := range [...]struct{ size, class int64 }{\n\t\t{8, 8},\n\t\t{9, 16},\n\t\t{16, 16},\n\t\t{17, 24},\n\t} {\n\t\tgot := sizeClass(test.size)\n\t\tif got != test.class {\n\t\t\tt.Errorf(\"sizeClass(%d) = %d, want %d\", test.size, got, test.class)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/identifier.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"errors\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// ErrNoIdentFound is error returned when no identifier is found at a particular position\nvar ErrNoIdentFound = errors.New(\"no identifier found\")\n\n// inferredSignature determines the resolved non-generic signature for an\n// identifier in an instantiation expression.\n//\n// If no such signature exists, it returns nil.\nfunc inferredSignature(info *types.Info, id *ast.Ident) *types.Signature {\n\tinst := info.Instances[id]\n\tsig, _ := types.Unalias(inst.Type).(*types.Signature)\n\treturn sig\n}\n\n// searchForEnclosing returns, given the AST path to a SelectorExpr,\n// the exported named type of the innermost implicit field selection.\n//\n// For example, given \"new(A).d\" where this is (due to embedding) a\n// shorthand for \"new(A).b.c.d\", it returns the named type of c,\n// if it is exported, otherwise the type of b, or A.\nfunc searchForEnclosing(info *types.Info, curIdent inspector.Cursor) *types.TypeName {\n\tselector, _ := cursorutil.FirstEnclosing[*ast.SelectorExpr](curIdent)\n\tif selector == nil {\n\t\treturn nil\n\t}\n\tsel, ok := info.Selections[selector]\n\tif !ok {\n\t\treturn nil\n\t}\n\trecv := typesinternal.Unpointer(sel.Recv())\n\n\t// Keep track of the last exported type seen.\n\tvar exported *types.TypeName\n\tif named, ok := types.Unalias(recv).(*types.Named); ok && named.Obj().Exported() {\n\t\texported = named.Obj()\n\t}\n\t// We don't want the last element, as that's the field or\n\t// method itself.\n\tfor _, index := range sel.Index()[:len(sel.Index())-1] {\n\t\tif r, ok := recv.Underlying().(*types.Struct); ok {\n\t\t\trecv = typesinternal.Unpointer(r.Field(index).Type())\n\t\t\tif named, ok := types.Unalias(recv).(*types.Named); ok && named.Obj().Exported() {\n\t\t\t\texported = named.Obj()\n\t\t\t}\n\t\t}\n\t}\n\treturn exported\n}\n\n// typeToObjects returns the underlying type name objects for the given type.\n// It unwraps composite types (pointers, slices, etc), and accumulates names\n// from each parameter of a function type\nfunc typeToObjects(typ types.Type) []*types.TypeName {\n\tswitch typ := typ.(type) {\n\tcase *types.Alias:\n\t\treturn []*types.TypeName{typ.Origin().Obj()}\n\tcase *types.Named:\n\t\treturn []*types.TypeName{typ.Origin().Obj()}\n\tcase *types.Pointer:\n\t\treturn typeToObjects(typ.Elem())\n\tcase *types.Array:\n\t\treturn typeToObjects(typ.Elem())\n\tcase *types.Slice:\n\t\treturn typeToObjects(typ.Elem())\n\tcase *types.Chan:\n\t\treturn typeToObjects(typ.Elem())\n\tcase *types.Tuple:\n\t\tvar res []*types.TypeName\n\t\tfor v := range typ.Variables() {\n\t\t\tres = append(res, typeToObjects(v.Type())...)\n\t\t}\n\t\treturn res\n\tcase *types.Signature:\n\t\treturn typeToObjects(typ.Results())\n\tcase *types.Basic:\n\t\ttname, ok := types.Universe.Lookup(typ.Name()).(*types.TypeName)\n\t\tif !ok {\n\t\t\treturn nil\n\t\t}\n\t\treturn []*types.TypeName{tname}\n\tdefault:\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/identifier_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\nfunc TestSearchForEnclosing(t *testing.T) {\n\ttests := []struct {\n\t\tdesc string\n\t\t// For convenience, consider the first occurrence of the identifier \"X\" in\n\t\t// src.\n\t\tsrc string\n\t\t// By convention, \"\" means no type found.\n\t\twantTypeName string\n\t}{\n\t\t{\n\t\t\t// TODO(rFindley): is this correct, or do we want to resolve I2 here?\n\t\t\tdesc:         \"embedded interface in interface\",\n\t\t\tsrc:          `package a; var y = i1.X; type i1 interface {I2}; type I2 interface{X()}`,\n\t\t\twantTypeName: \"\",\n\t\t},\n\t\t{\n\t\t\tdesc:         \"embedded interface in struct\",\n\t\t\tsrc:          `package a; var y = t.X; type t struct {I}; type I interface{X()}`,\n\t\t\twantTypeName: \"I\",\n\t\t},\n\t\t{\n\t\t\tdesc:         \"double embedding\",\n\t\t\tsrc:          `package a; var y = t1.X; type t1 struct {t2}; type t2 struct {I}; type I interface{X()}`,\n\t\t\twantTypeName: \"I\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tfile, err := parser.ParseFile(fset, \"a.go\", test.src, parser.AllErrors|parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar (\n\t\t\t\tfiles  = []*ast.File{file}\n\t\t\t\tcolumn = 1 + bytes.IndexRune([]byte(test.src), 'X')\n\t\t\t\tpos    = posAt(1, column, fset, \"a.go\")\n\t\t\t)\n\t\t\tcur, ok := inspector.New(files).Root().FindByPos(pos, pos)\n\t\t\tif !ok {\n\t\t\t\tt.Fatalf(\"no ident found at (1, %d)\", column)\n\t\t\t}\n\t\t\tinfo := newInfo()\n\t\t\tif _, err = (*types.Config)(nil).Check(\"p\", fset, files, info); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tobj := searchForEnclosing(info, cur)\n\t\t\tif obj == nil {\n\t\t\t\tif test.wantTypeName != \"\" {\n\t\t\t\t\tt.Errorf(\"searchForEnclosing(...) = <nil>, want %q\", test.wantTypeName)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got := obj.Name(); got != test.wantTypeName {\n\t\t\t\tt.Errorf(\"searchForEnclosing(...) = %q, want %q\", got, test.wantTypeName)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// posAt returns the token.Pos corresponding to the 1-based (line, column)\n// coordinates in the file fname of fset.\nfunc posAt(line, column int, fset *token.FileSet, fname string) token.Pos {\n\tvar tok *token.File\n\tfset.Iterate(func(tf *token.File) bool {\n\t\tif tf.Name() == fname {\n\t\t\ttok = tf\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\tif tok == nil {\n\t\treturn token.NoPos\n\t}\n\tstart := tok.LineStart(line)\n\treturn start + token.Pos(column-1)\n}\n\n// newInfo returns a types.Info with all maps populated.\nfunc newInfo() *types.Info {\n\tinfo := &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\treturn info\n}\n"
  },
  {
    "path": "gopls/internal/golang/implementation.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/methodsets\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/moreiters\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// This file defines the new implementation of the 'implementation'\n// operator that does not require type-checker data structures for an\n// unbounded number of packages.\n//\n// TODO(adonovan):\n// - Audit to ensure robustness in face of type errors.\n// - Eliminate false positives due to 'tricky' cases of the global algorithm.\n// - Ensure we have test coverage of:\n//      type aliases\n//      nil, PkgName, Builtin (all errors)\n//      any (empty result)\n//      method of unnamed interface type (e.g. var x interface { f() })\n//        (the global algorithm may find implementations of this type\n//         but will not include it in the index.)\n\n// Implementation returns a new sorted array of locations of\n// declarations of types that implement (or are implemented by) the\n// type referred to at the given position.\n//\n// If the position denotes a method, the computation is applied to its\n// receiver type and then its corresponding methods are returned.\nfunc Implementation(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\tctx, done := event.Start(ctx, \"golang.Implementation\")\n\tdefer done()\n\n\tlocs, err := implementations(ctx, snapshot, f, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tslices.SortFunc(locs, protocol.CompareLocation)\n\tlocs = slices.Compact(locs) // de-duplicate\n\treturn locs, nil\n}\n\nfunc implementations(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\t// Type check the current package.\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(start, end) // can't fail\n\n\t// Find implementations based on func signatures.\n\tif locs, err := implFuncs(pkg, cur, start, end); err != errNotHandled {\n\t\treturn locs, err\n\t}\n\n\t// Find implementations based on method sets.\n\tvar (\n\t\tlocsMu sync.Mutex\n\t\tlocs   []protocol.Location\n\t)\n\t// relation=0 here means infer direction of the relation\n\t// (Supertypes/Subtypes) from concreteness of query type/method.\n\t// (Ideally the implementations request would provide directionality\n\t// so that one could ask for, say, the superinterfaces of io.ReadCloser;\n\t// see https://github.com/golang/go/issues/68641#issuecomment-2269293762.)\n\tconst relation = methodsets.TypeRelation(0)\n\terr = implementationsMsets(ctx, snapshot, pkg, cur, relation, func(_ metadata.PackagePath, _ string, _ bool, loc protocol.Location) {\n\t\tlocsMu.Lock()\n\t\tlocs = append(locs, loc)\n\t\tlocsMu.Unlock()\n\t})\n\treturn locs, err\n}\n\n// An implYieldFunc is a callback called for each match produced by the implementation machinery.\n// - name describes the type or method.\n// - abstract indicates that the result is an interface type or interface method.\n//\n// implYieldFunc implementations must be concurrency-safe.\ntype implYieldFunc func(pkgpath metadata.PackagePath, name string, abstract bool, loc protocol.Location)\n\n// implementationsMsets computes implementations of the type at the\n// position specified by cur, by method sets.\n//\n// rel specifies the desired direction of the relation: Subtype,\n// Supertype, or both. As a special case, zero means infer the\n// direction from the concreteness of the query object: Supertype for\n// a concrete type, Subtype for an interface.\n//\n// It is shared by Implementations and TypeHierarchy.\nfunc implementationsMsets(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, cur inspector.Cursor, rel methodsets.TypeRelation, yield implYieldFunc) error {\n\t// First, find the object referenced at the cursor.\n\t// The object may be declared in a different package.\n\tobj, err := implementsObj(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If the resulting object has a position, we can expand the search to types\n\t// in the declaring package(s). In this case, we must re-type check these\n\t// packages in the same realm.\n\tvar (\n\t\tdeclOffset int\n\t\tdeclURI    protocol.DocumentURI\n\t\tlocalPkgs  []*cache.Package\n\t)\n\tif obj.Pos().IsValid() { // no local package for error or error.Error\n\t\tdeclPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())\n\t\tdeclOffset = declPosn.Offset\n\t\t// Type-check the declaring package (incl. variants) for use\n\t\t// by the \"local\" search, which uses type information to\n\t\t// enumerate all types within the package that satisfy the\n\t\t// query type, even those defined local to a function.\n\t\tdeclURI = protocol.URIFromPath(declPosn.Filename)\n\t\tdeclMPs, err := snapshot.MetadataForFile(ctx, declURI, true)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(declMPs) == 0 {\n\t\t\treturn fmt.Errorf(\"no packages for file %s\", declURI)\n\t\t}\n\t\tids := make([]PackageID, len(declMPs))\n\t\tfor i, mp := range declMPs {\n\t\t\tids[i] = mp.ID\n\t\t}\n\t\tlocalPkgs, err = snapshot.TypeCheck(ctx, ids...)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tpkg = nil // no longer used\n\n\t// Is the selected identifier a type name or method?\n\t// (For methods, report the corresponding method names.)\n\tqueryType, queryMethod := typeOrMethod(obj)\n\tif queryType == nil {\n\t\treturn bug.Errorf(\"%s is not a type or method\", obj.Name()) // should have been handled by implementsObj\n\t}\n\n\t// Compute the method-set fingerprint used as a key to the global search.\n\tkey, hasMethods := methodsets.KeyOf(queryType)\n\tif !hasMethods {\n\t\t// A type with no methods yields an empty result.\n\t\t// (No point reporting that every type satisfies 'any'.)\n\t\treturn nil\n\t}\n\n\t// If the client specified no relation, infer it\n\t// from the concreteness of the query type.\n\tif rel == 0 {\n\t\trel = cond(types.IsInterface(queryType),\n\t\t\tmethodsets.Subtype,\n\t\t\tmethodsets.Supertype)\n\t}\n\n\t// The global search needs to look at every package in the\n\t// forward transitive closure of the workspace; see package\n\t// ./methodsets.\n\t//\n\t// For now we do all the type checking before beginning the search.\n\t// TODO(adonovan): opt: search in parallel topological order\n\t// so that we can overlap index lookup with typechecking.\n\t// I suspect a number of algorithms on the result of TypeCheck could\n\t// be optimized by being applied as soon as each package is available.\n\tglobalMetas, err := snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tmetadata.RemoveIntermediateTestVariants(&globalMetas)\n\tglobalIDs := make([]PackageID, 0, len(globalMetas))\n\n\tvar pkgPath PackagePath\n\tif obj.Pkg() != nil { // nil for error\n\t\tpkgPath = PackagePath(obj.Pkg().Path())\n\t}\n\tfor _, mp := range globalMetas {\n\t\tif mp.PkgPath == pkgPath {\n\t\t\tcontinue // declaring package is handled by local implementation\n\t\t}\n\t\tglobalIDs = append(globalIDs, mp.ID)\n\t}\n\tindexes, err := snapshot.MethodSets(ctx, globalIDs...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"querying method sets: %v\", err)\n\t}\n\n\t// Search local and global packages in parallel.\n\tvar group errgroup.Group\n\n\t// local search\n\tfor _, pkg := range localPkgs {\n\t\t// The localImplementations algorithm assumes needle and haystack\n\t\t// belong to a single package (=\"realm\" of types symbol identities),\n\t\t// so we need to recompute obj for each local package.\n\t\t// (By contrast the global algorithm is name-based.)\n\t\tgroup.Go(func() error {\n\t\t\tpkgID := pkg.Metadata().ID\n\n\t\t\t// Find declaring identifier based on (URI, offset)\n\t\t\t// so that localImplementations can locate the\n\t\t\t// corresponding obj/queryType/queryMethod in pkg.\n\t\t\tdeclFile, err := pkg.File(declURI)\n\t\t\tif err != nil {\n\t\t\t\treturn err // \"can't happen\"\n\t\t\t}\n\t\t\tpos, err := safetoken.Pos(declFile.Tok, declOffset)\n\t\t\tif err != nil {\n\t\t\t\treturn err // also \"can't happen\"\n\t\t\t}\n\t\t\tcurIdent, ok := declFile.Cursor().FindByPos(pos, pos)\n\t\t\tif !ok {\n\t\t\t\treturn bug.Errorf(\"position not within file\") // can't happen\n\t\t\t}\n\t\t\tid, ok := curIdent.Node().(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\treturn ErrNoIdentFound // checked earlier\n\t\t\t}\n\t\t\tif err := localImplementations(ctx, snapshot, pkg, id, rel, yield); err != nil {\n\t\t\t\treturn fmt.Errorf(\"querying local implementations %q: %v\", pkgID, err)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\t// global search\n\tfor _, index := range indexes {\n\t\tgroup.Go(func() error {\n\t\t\tfor _, res := range index.Search(key, rel, queryMethod) {\n\t\t\t\tloc := res.Location\n\t\t\t\t// Map offsets to protocol.Locations in parallel (may involve I/O).\n\t\t\t\tgroup.Go(func() error {\n\t\t\t\t\tploc, err := offsetToLocation(ctx, snapshot, loc.Filename, loc.Start, loc.End)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tyield(index.PkgPath, res.TypeName, res.IsInterface, ploc)\n\t\t\t\t\treturn nil\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\treturn group.Wait()\n}\n\n// typeOrMethod returns the type and optional method to use in an\n// Implementations operation on the specified symbol.\n// It returns a nil type to indicate that the query should not proceed.\n//\n// (It is factored out to allow it to be used both in the query package\n// then (in [localImplementations]) again in the declaring package.)\nfunc typeOrMethod(obj types.Object) (types.Type, *types.Func) {\n\tswitch obj := obj.(type) {\n\tcase *types.TypeName:\n\t\treturn obj.Type(), nil\n\tcase *types.Func:\n\t\t// For methods, use the receiver type, which may be anonymous.\n\t\tif recv := obj.Signature().Recv(); recv != nil {\n\t\t\treturn recv.Type(), obj\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// offsetToLocation converts an offset-based position to a protocol.Location,\n// which requires reading the file.\nfunc offsetToLocation(ctx context.Context, snapshot *cache.Snapshot, filename string, start, end int) (protocol.Location, error) {\n\turi := protocol.URIFromPath(filename)\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn protocol.Location{}, err // cancelled, perhaps\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn protocol.Location{}, err // nonexistent or deleted (\"can't happen\")\n\t}\n\tm := protocol.NewMapper(uri, content)\n\treturn m.OffsetLocation(start, end)\n}\n\n// implementsObj returns the object to query for implementations,\n// which is a type name or method.\nfunc implementsObj(info *types.Info, cur inspector.Cursor) (types.Object, error) {\n\t// This function inherits the limitation of its predecessor in\n\t// requiring the selection to be an identifier (of a type or\n\t// method). But there's no fundamental reason why one could\n\t// not pose this query about any selected piece of syntax that\n\t// has a type and thus a method set.\n\t// (If LSP was more thorough about passing text selections as\n\t// intervals to queries, you could ask about the method set of a\n\t// subexpression such as x.f().)\n\t// [Note that this process has begun; see #69058.]\n\tid, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn nil, ErrNoIdentFound\n\t}\n\n\t// Is the object a type or method? Reject other kinds.\n\tobj := info.Uses[id]\n\tif obj == nil {\n\t\t// Check uses first (unlike ObjectOf) so that T in\n\t\t// struct{T} is treated as a reference to a type,\n\t\t// not a declaration of a field.\n\t\tobj = info.Defs[id]\n\t}\n\tswitch obj := obj.(type) {\n\tcase *types.TypeName:\n\t\t// ok\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() == nil {\n\t\t\treturn nil, fmt.Errorf(\"%s is a function, not a method (query at 'func' token to find matching signatures)\", id.Name)\n\t\t}\n\tcase nil:\n\t\treturn nil, fmt.Errorf(\"%s denotes unknown object\", id.Name)\n\tdefault:\n\t\t// e.g. *types.Var -> \"var\".\n\t\tkind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), \"*types.\"))\n\t\t// TODO(adonovan): improve upon \"nil is a nil, not a type\".\n\t\treturn nil, fmt.Errorf(\"%s is a %s, not a type\", id.Name, kind)\n\t}\n\n\treturn obj, nil\n}\n\n// localImplementations searches within pkg for declarations of all\n// supertypes (if rel contains Supertype) or subtypes (if rel contains\n// Subtype) of the type or method declared by id within the same\n// package, and returns a new unordered array of their locations.\n//\n// If method is non-nil, the function instead returns the location\n// of each type's method (if any) of that ID.\n//\n// (\"Local\" refers to the search within the same package, but this\n// function's results may include type declarations that are local to\n// a function body. The global search index excludes such types\n// because reliably naming such types is hard.)\n//\n// Results are reported via the yield function.\nfunc localImplementations(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, id *ast.Ident, rel methodsets.TypeRelation, yield implYieldFunc) error {\n\tqueryType, queryMethod := typeOrMethod(pkg.TypesInfo().Defs[id])\n\tif queryType == nil {\n\t\treturn bug.Errorf(\"can't find corresponding symbol for %q in package %q\", id.Name, pkg)\n\t}\n\tqueryType = methodsets.EnsurePointer(queryType)\n\n\tvar msets typeutil.MethodSetCache\n\n\tmatches := func(candidateType types.Type) bool {\n\t\t// Test the direction of the relation.\n\t\t// The client may request either direction or both\n\t\t// (e.g. when the client is References),\n\t\t// and the Result reports each test independently;\n\t\t// both tests succeed when comparing identical\n\t\t// interface types.\n\t\tvar got methodsets.TypeRelation\n\t\tif rel&methodsets.Supertype != 0 && implements(&msets, queryType, candidateType) {\n\t\t\tgot |= methodsets.Supertype\n\t\t}\n\t\tif rel&methodsets.Subtype != 0 && implements(&msets, candidateType, queryType) {\n\t\t\tgot |= methodsets.Subtype\n\t\t}\n\t\treturn got != 0\n\t}\n\n\t// Scan through all type declarations in the syntax.\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tfor cur := range pgf.Cursor().Preorder((*ast.TypeSpec)(nil)) {\n\t\t\tspec := cur.Node().(*ast.TypeSpec)\n\t\t\tif spec.Name == id {\n\t\t\t\tcontinue // avoid self-comparison of query type\n\t\t\t}\n\t\t\tdef := pkg.TypesInfo().Defs[spec.Name]\n\t\t\tif def == nil {\n\t\t\t\tcontinue // \"can't happen\" for types\n\t\t\t}\n\t\t\tif def.(*types.TypeName).IsAlias() {\n\t\t\t\tcontinue // skip type aliases to avoid duplicate reporting\n\t\t\t}\n\t\t\tcandidateType := methodsets.EnsurePointer(def.Type())\n\t\t\tif !matches(candidateType) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Ignore types with empty method sets.\n\t\t\t// (No point reporting that every type satisfies 'any'.)\n\t\t\tmset := msets.MethodSet(candidateType)\n\t\t\tif mset.Len() == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tisInterface := types.IsInterface(def.Type())\n\n\t\t\tif queryMethod == nil {\n\t\t\t\t// Found matching type.\n\t\t\t\tloc := mustLocation(pgf, spec.Name)\n\t\t\t\tyield(pkg.Metadata().PkgPath, spec.Name.Name, isInterface, loc)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Find corresponding method.\n\t\t\t//\n\t\t\t// We can't use LookupFieldOrMethod because it requires\n\t\t\t// the methodID's types.Package, which we don't know.\n\t\t\t// We could recursively search pkg.Imports for it,\n\t\t\t// but it's easier to walk the method set.\n\t\t\tfor method := range mset.Methods() {\n\t\t\t\tm := method.Obj()\n\t\t\t\tif m.Pos() == id.Pos() {\n\t\t\t\t\tcontinue // avoid self-comparison of query method\n\t\t\t\t}\n\t\t\t\tif m.Id() == queryMethod.Id() {\n\t\t\t\t\tposn := safetoken.StartPosition(pkg.FileSet(), m.Pos())\n\t\t\t\t\tloc, err := offsetToLocation(ctx, snapshot, posn.Filename, posn.Offset, posn.Offset+len(m.Name()))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tyield(pkg.Metadata().PkgPath, m.Name(), isInterface, loc)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Special case: for types that satisfy error,\n\t// report error in builtin.go (see #59527).\n\t//\n\t// (An inconsistency: we always report the type error\n\t// even when the query was for the method error.Error.)\n\tif matches(errorType) {\n\t\tloc, err := errorLocation(ctx, snapshot)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tyield(\"\", \"error\", true, loc)\n\t}\n\n\treturn nil\n}\n\nvar errorType = types.Universe.Lookup(\"error\").Type()\n\n// errorLocation returns the location of the 'error' type in builtin.go.\nfunc errorLocation(ctx context.Context, snapshot *cache.Snapshot) (protocol.Location, error) {\n\tpgf, err := snapshot.BuiltinFile(ctx)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tfor _, decl := range pgf.File.Decls {\n\t\tif decl, ok := decl.(*ast.GenDecl); ok {\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tif spec, ok := spec.(*ast.TypeSpec); ok && spec.Name.Name == \"error\" {\n\t\t\t\t\treturn pgf.NodeLocation(spec.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn protocol.Location{}, fmt.Errorf(\"built-in error type not found\")\n}\n\n// implements reports whether x implements y.\n// If one or both types are generic, the result indicates whether the\n// interface may be implemented under some instantiation.\nfunc implements(msets *typeutil.MethodSetCache, x, y types.Type) bool {\n\tif !types.IsInterface(y) {\n\t\treturn false\n\t}\n\n\t// For each interface method of y, check that x has it too.\n\t// It is not necessary to compute x's complete method set.\n\t//\n\t// If y is a constraint interface (!y.IsMethodSet()), we\n\t// ignore non-interface terms, leading to occasional spurious\n\t// matches. We could in future filter based on them, but it\n\t// would lead to divergence with the global (fingerprint-based)\n\t// algorithm, which operates only on methodsets.\n\tymset := msets.MethodSet(y)\n\tfor method := range ymset.Methods() {\n\t\tym := method.Obj().(*types.Func)\n\n\t\txobj, _, _ := types.LookupFieldOrMethod(x, false, ym.Pkg(), ym.Name())\n\t\txm, ok := xobj.(*types.Func)\n\t\tif !ok {\n\t\t\treturn false // x lacks a method of y\n\t\t}\n\t\tif !unify(xm.Signature(), ym.Signature(), nil) {\n\t\t\treturn false // signatures do not match\n\t\t}\n\t}\n\treturn true // all methods found\n}\n\n// unify reports whether the types of x and y match.\n//\n// If unifier is nil, unify reports only whether it succeeded.\n// If unifier is non-nil, it is populated with the values\n// of type parameters determined during a successful unification.\n// If unification succeeds without binding a type parameter, that parameter\n// will not be present in the map.\n//\n// On entry, the unifier's contents are treated as the values of already-bound type\n// parameters, constraining the unification.\n//\n// For example, if unifier is an empty (not nil) map on entry, then the types\n//\n//\tfunc[T any](T, int)\n//\n// and\n//\n//\tfunc[U any](bool, U)\n//\n// will unify, with T=bool and U=int.\n// That is, the contents of unifier after unify returns will be\n//\n//\t{T: bool, U: int}\n//\n// where \"T\" is the type parameter T and \"bool\" is the basic type for bool.\n//\n// But if unifier is {T: int} is int on entry, then unification will fail, because T\n// does not unify with bool.\n//\n// Unify does not preserve aliases. For example, given the following:\n//\n//\ttype String = string\n//\ttype A[T] = T\n//\n// unification succeeds with T bound to string, not String.\n//\n// See also: unify in cache/methodsets/fingerprint, which implements\n// unification for type fingerprints, for the global index.\n//\n// BUG: literal interfaces are not handled properly. But this function is currently\n// used only for signatures, where such types are very rare.\nfunc unify(x, y types.Type, unifier map[*types.TypeParam]types.Type) bool {\n\t// bindings[tp] is the binding for type parameter tp.\n\t// Although type parameters are nominally bound to types, each bindings[tp]\n\t// is a pointer to a type, so unbound variables that unify can share a binding.\n\tbindings := map[*types.TypeParam]*types.Type{}\n\n\t// Bindings is initialized with pointers to the provided types.\n\tfor tp, t := range unifier {\n\t\tbindings[tp] = &t\n\t}\n\n\t// bindingFor returns the *types.Type in bindings for tp if tp is not nil,\n\t// creating one if needed.\n\tbindingFor := func(tp *types.TypeParam) *types.Type {\n\t\tif tp == nil {\n\t\t\treturn nil\n\t\t}\n\t\tb := bindings[tp]\n\t\tif b == nil {\n\t\t\tb = new(types.Type)\n\t\t\tbindings[tp] = b\n\t\t}\n\t\treturn b\n\t}\n\n\t// bind sets b to t if b does not occur in t.\n\tbind := func(b *types.Type, t types.Type) bool {\n\t\tfor tp := range typeParams(t) {\n\t\t\tif b == bindings[tp] {\n\t\t\t\treturn false // failed \"occurs\" check\n\t\t\t}\n\t\t}\n\t\t*b = t\n\t\treturn true\n\t}\n\n\t// uni performs the actual unification.\n\tdepth := 0\n\tvar uni func(x, y types.Type) bool\n\tuni = func(x, y types.Type) bool {\n\t\t// Panic if recursion gets too deep, to detect bugs before\n\t\t// overflowing the stack.\n\t\tdepth++\n\t\tdefer func() { depth-- }()\n\t\tif depth > 100 {\n\t\t\tpanic(\"unify: max depth exceeded\")\n\t\t}\n\n\t\tx = types.Unalias(x)\n\t\ty = types.Unalias(y)\n\n\t\ttpx, _ := x.(*types.TypeParam)\n\t\ttpy, _ := y.(*types.TypeParam)\n\t\tif tpx != nil || tpy != nil {\n\t\t\t// Identical type params unify.\n\t\t\tif tpx == tpy {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tbx := bindingFor(tpx)\n\t\t\tby := bindingFor(tpy)\n\n\t\t\t// If both args are type params and neither is bound, have them share a binding.\n\t\t\tif bx != nil && by != nil && *bx == nil && *by == nil {\n\t\t\t\t// Arbitrarily give y's binding to x.\n\t\t\t\tbindings[tpx] = by\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Treat param bindings like original args in what follows.\n\t\t\tif bx != nil && *bx != nil {\n\t\t\t\tx = *bx\n\t\t\t}\n\t\t\tif by != nil && *by != nil {\n\t\t\t\ty = *by\n\t\t\t}\n\t\t\t// If the x param is unbound, bind it to y.\n\t\t\tif bx != nil && *bx == nil {\n\t\t\t\treturn bind(bx, y)\n\t\t\t}\n\t\t\t// If the y param is unbound, bind it to x.\n\t\t\tif by != nil && *by == nil {\n\t\t\t\treturn bind(by, x)\n\t\t\t}\n\t\t\t// Unify the binding of a bound parameter.\n\t\t\treturn uni(x, y)\n\t\t}\n\n\t\t// Neither arg is a type param.\n\n\t\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\t\treturn false // mismatched types\n\t\t}\n\n\t\tswitch x := x.(type) {\n\t\tcase *types.Array:\n\t\t\ty := y.(*types.Array)\n\t\t\treturn x.Len() == y.Len() &&\n\t\t\t\tuni(x.Elem(), y.Elem())\n\n\t\tcase *types.Basic:\n\t\t\ty := y.(*types.Basic)\n\t\t\treturn x.Kind() == y.Kind()\n\n\t\tcase *types.Chan:\n\t\t\ty := y.(*types.Chan)\n\t\t\treturn x.Dir() == y.Dir() &&\n\t\t\t\tuni(x.Elem(), y.Elem())\n\n\t\tcase *types.Interface:\n\t\t\ty := y.(*types.Interface)\n\t\t\t// TODO(adonovan,jba): fix: for correctness, we must check\n\t\t\t// that both interfaces have the same set of methods\n\t\t\t// modulo type parameters, while avoiding the risk of\n\t\t\t// unbounded interface recursion.\n\t\t\t//\n\t\t\t// Since non-empty interface literals are vanishingly\n\t\t\t// rare in methods signatures, we ignore this for now.\n\t\t\t// If more precision is needed we could compare method\n\t\t\t// names and arities, still without full recursion.\n\t\t\treturn x.NumMethods() == y.NumMethods()\n\n\t\tcase *types.Map:\n\t\t\ty := y.(*types.Map)\n\t\t\treturn uni(x.Key(), y.Key()) &&\n\t\t\t\tuni(x.Elem(), y.Elem())\n\n\t\tcase *types.Named:\n\t\t\ty := y.(*types.Named)\n\t\t\tif x.Origin() != y.Origin() {\n\t\t\t\treturn false // different named types\n\t\t\t}\n\t\t\txtargs := x.TypeArgs()\n\t\t\tytargs := y.TypeArgs()\n\t\t\tif xtargs.Len() != ytargs.Len() {\n\t\t\t\treturn false // arity error (ill-typed)\n\t\t\t}\n\t\t\tfor i := range xtargs.Len() {\n\t\t\t\tif !uni(xtargs.At(i), ytargs.At(i)) {\n\t\t\t\t\treturn false // mismatched type args\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\n\t\tcase *types.Pointer:\n\t\t\ty := y.(*types.Pointer)\n\t\t\treturn uni(x.Elem(), y.Elem())\n\n\t\tcase *types.Signature:\n\t\t\ty := y.(*types.Signature)\n\t\t\treturn x.Variadic() == y.Variadic() &&\n\t\t\t\tuni(x.Params(), y.Params()) &&\n\t\t\t\tuni(x.Results(), y.Results())\n\n\t\tcase *types.Slice:\n\t\t\ty := y.(*types.Slice)\n\t\t\treturn uni(x.Elem(), y.Elem())\n\n\t\tcase *types.Struct:\n\t\t\ty := y.(*types.Struct)\n\t\t\tif x.NumFields() != y.NumFields() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor i := range x.NumFields() {\n\t\t\t\txf := x.Field(i)\n\t\t\t\tyf := y.Field(i)\n\t\t\t\tif xf.Embedded() != yf.Embedded() ||\n\t\t\t\t\txf.Name() != yf.Name() ||\n\t\t\t\t\tx.Tag(i) != y.Tag(i) ||\n\t\t\t\t\t!xf.Exported() && xf.Pkg() != yf.Pkg() ||\n\t\t\t\t\t!uni(xf.Type(), yf.Type()) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\n\t\tcase *types.Tuple:\n\t\t\ty := y.(*types.Tuple)\n\t\t\tif x.Len() != y.Len() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor i := range x.Len() {\n\t\t\t\tif !uni(x.At(i).Type(), y.At(i).Type()) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\n\t\tdefault: // incl. *Union, *TypeParam\n\t\t\tpanic(fmt.Sprintf(\"unexpected Type %#v\", x))\n\t\t}\n\t}\n\n\tif !uni(x, y) {\n\t\tclear(unifier)\n\t\treturn false\n\t}\n\n\t// Populate the input map with the resulting types.\n\tif unifier != nil {\n\t\tfor tparam, tptr := range bindings {\n\t\t\tunifier[tparam] = *tptr\n\t\t}\n\t}\n\treturn true\n}\n\n// typeParams yields all the free type parameters within t that are relevant for\n// unification.\n//\n// Note: this function is tailored for the specific needs of the unification algorithm.\n// Don't try to use it for other purposes, see [typeparams.Free] instead.\nfunc typeParams(t types.Type) iter.Seq[*types.TypeParam] {\n\n\treturn func(yield func(*types.TypeParam) bool) {\n\t\tseen := map[*types.TypeParam]bool{} // yield each type param only once\n\n\t\t// tps(t) yields each TypeParam in t and returns false to stop.\n\t\tvar tps func(types.Type) bool\n\t\ttps = func(t types.Type) bool {\n\t\t\tt = types.Unalias(t)\n\n\t\t\tswitch t := t.(type) {\n\t\t\tcase *types.TypeParam:\n\t\t\t\tif seen[t] {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tseen[t] = true\n\t\t\t\treturn yield(t)\n\n\t\t\tcase *types.Basic:\n\t\t\t\treturn true\n\n\t\t\tcase *types.Array:\n\t\t\t\treturn tps(t.Elem())\n\n\t\t\tcase *types.Chan:\n\t\t\t\treturn tps(t.Elem())\n\n\t\t\tcase *types.Interface:\n\t\t\t\t// TODO(jba): implement.\n\t\t\t\treturn true\n\n\t\t\tcase *types.Map:\n\t\t\t\treturn tps(t.Key()) && tps(t.Elem())\n\n\t\t\tcase *types.Named:\n\t\t\t\tif t.Origin() == t {\n\t\t\t\t\t// generic type: look at type params\n\t\t\t\t\treturn moreiters.Every(t.TypeParams().TypeParams(),\n\t\t\t\t\t\tfunc(tp *types.TypeParam) bool { return tps(tp) })\n\t\t\t\t}\n\t\t\t\t// instantiated type: look at type args\n\t\t\t\treturn moreiters.Every(t.TypeArgs().Types(), tps)\n\n\t\t\tcase *types.Pointer:\n\t\t\t\treturn tps(t.Elem())\n\n\t\t\tcase *types.Signature:\n\t\t\t\treturn tps(t.Params()) && tps(t.Results())\n\n\t\t\tcase *types.Slice:\n\t\t\t\treturn tps(t.Elem())\n\n\t\t\tcase *types.Struct:\n\t\t\t\treturn moreiters.Every(t.Fields(),\n\t\t\t\t\tfunc(v *types.Var) bool { return tps(v.Type()) })\n\n\t\t\tcase *types.Tuple:\n\t\t\t\treturn moreiters.Every(t.Variables(),\n\t\t\t\t\tfunc(v *types.Var) bool { return tps(v.Type()) })\n\n\t\t\tdefault: // incl. *Union\n\t\t\t\tpanic(fmt.Sprintf(\"unexpected Type %#v\", t))\n\t\t\t}\n\t\t}\n\n\t\ttps(t)\n\t}\n}\n\nvar (\n\t// TODO(adonovan): why do various RPC handlers related to\n\t// IncomingCalls return (nil, nil) on the protocol in response\n\t// to this error? That seems like a violation of the protocol.\n\t// Is it perhaps a workaround for VSCode behavior?\n\terrNoObjectFound = errors.New(\"no object found\")\n)\n\n// --- Implementations based on signature types --\n\n// implFuncs finds Implementations based on func types.\n//\n// Just as an interface type abstracts a set of concrete methods, a\n// function type abstracts a set of concrete functions. Gopls provides\n// analogous operations for navigating from abstract to concrete and\n// back in the domain of function types.\n//\n// A single type (for example http.HandlerFunc) can have both an\n// underlying type of function (types.Signature) and have methods that\n// cause it to implement an interface. To avoid a confusing user\n// interface we want to separate the two operations so that the user\n// can unambiguously specify the query they want.\n//\n// So, whereas Implementations queries on interface types are usually\n// keyed by an identifier of a named type, Implementations queries on\n// function types are keyed by the \"func\" keyword, or by the \"(\" of a\n// call expression. The query relates two sets of locations:\n//\n//  1. the \"func\" token of each function declaration (FuncDecl or\n//     FuncLit). These are analogous to declarations of concrete\n//     methods.\n//\n//  2. uses of abstract functions:\n//\n//     (a) the \"func\" token of each FuncType that is not part of\n//     Func{Decl,Lit}. These are analogous to interface{...} types.\n//\n//     (b) the \"(\" paren of each dynamic call on a value of an\n//     abstract function type. These are analogous to references to\n//     interface method names, but no names are involved, which has\n//     historically made them hard to search for.\n//\n// An Implementations query on a location in set 1 returns set 2,\n// and vice versa.\n//\n// curSel denotes the selected syntax node whose type drives the\n// pos indicates the exact cursor position.\n//\n// implFuncs returns errNotHandled to indicate that we should try the\n// regular method-sets algorithm.\nfunc implFuncs(pkg *cache.Package, curSel inspector.Cursor, start, end token.Pos) ([]protocol.Location, error) {\n\tinfo := pkg.TypesInfo()\n\tif info.Types == nil || info.Defs == nil || info.Uses == nil {\n\t\tpanic(\"one of info.Types, .Defs or .Uses is nil\")\n\t}\n\n\t// Find innermost enclosing FuncType or CallExpr.\n\t//\n\t// We are looking for specific tokens (FuncType.Func and\n\t// CallExpr.Lparen), but FindPos prefers an adjoining\n\t// subexpression: given f(x) without additional spaces between\n\t// tokens, FindPos always returns either f or x, never the\n\t// CallExpr itself. Thus we must ascend the tree.\n\t//\n\t// Another subtlety: due to an edge case in go/ast, FindPos at\n\t// FuncDecl.Type.Func does not return FuncDecl.Type, only the\n\t// FuncDecl, because the orders of tree positions and tokens\n\t// are inconsistent. Consequently, the ancestors for a \"func\"\n\t// token of Func{Lit,Decl} do not include FuncType, hence the\n\t// explicit cases below.\n\tfor cur := range curSel.Enclosing(\n\t\t(*ast.FuncDecl)(nil),\n\t\t(*ast.FuncLit)(nil),\n\t\t(*ast.FuncType)(nil),\n\t\t(*ast.CallExpr)(nil),\n\t) {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.FuncDecl, *ast.FuncLit:\n\t\t\tif inToken(n.Pos(), \"func\", start, end) {\n\t\t\t\t// Case 1: concrete function declaration.\n\t\t\t\t// Report uses of corresponding function types.\n\t\t\t\tswitch n := n.(type) {\n\t\t\t\tcase *ast.FuncDecl:\n\t\t\t\t\treturn funcUses(pkg, info.Defs[n.Name].Type())\n\t\t\t\tcase *ast.FuncLit:\n\t\t\t\t\treturn funcUses(pkg, info.TypeOf(n.Type))\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.FuncType:\n\t\t\tif n.Func.IsValid() && inToken(n.Func, \"func\", start, end) && !beneathFuncDef(cur) {\n\t\t\t\t// Case 2a: function type.\n\t\t\t\t// Report declarations of corresponding concrete functions.\n\t\t\t\treturn funcDefs(pkg, info.TypeOf(n))\n\t\t\t}\n\n\t\tcase *ast.CallExpr:\n\t\t\tif inToken(n.Lparen, \"(\", start, end) {\n\t\t\t\tt := dynamicFuncCallType(info, n)\n\t\t\t\tif t == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"not a dynamic function call\")\n\t\t\t\t}\n\t\t\t\t// Case 2b: dynamic call of function value.\n\t\t\t\t// Report declarations of corresponding concrete functions.\n\t\t\t\treturn funcDefs(pkg, t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// It's probably a query of a named type or method.\n\t// Fall back to the method-sets computation.\n\treturn nil, errNotHandled\n}\n\nvar errNotHandled = errors.New(\"not handled\")\n\n// funcUses returns all locations in the workspace that are dynamic\n// uses of the specified function type.\nfunc funcUses(pkg *cache.Package, t types.Type) ([]protocol.Location, error) {\n\tvar locs []protocol.Location\n\n\t// local search\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tfor cur := range pgf.Cursor().Preorder((*ast.CallExpr)(nil), (*ast.FuncType)(nil)) {\n\t\t\tvar pos, end token.Pos\n\t\t\tvar ftyp types.Type\n\t\t\tswitch n := cur.Node().(type) {\n\t\t\tcase *ast.CallExpr:\n\t\t\t\tftyp = dynamicFuncCallType(pkg.TypesInfo(), n)\n\t\t\t\tpos, end = n.Lparen, n.Lparen+token.Pos(len(\"(\"))\n\n\t\t\tcase *ast.FuncType:\n\t\t\t\tif !beneathFuncDef(cur) {\n\t\t\t\t\t// func type (not def)\n\t\t\t\t\tftyp = pkg.TypesInfo().TypeOf(n)\n\t\t\t\t\tpos, end = n.Func, n.Func+token.Pos(len(\"func\"))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ftyp == nil {\n\t\t\t\tcontinue // missing type information\n\t\t\t}\n\t\t\tif unify(t, ftyp, nil) {\n\t\t\t\tloc, err := pgf.PosLocation(pos, end)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tlocs = append(locs, loc)\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(adonovan): implement global search\n\n\treturn locs, nil\n}\n\n// funcDefs returns all locations in the workspace that define\n// functions of the specified type.\nfunc funcDefs(pkg *cache.Package, t types.Type) ([]protocol.Location, error) {\n\tvar locs []protocol.Location\n\n\t// local search\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tfor curFn := range pgf.Cursor().Preorder((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {\n\t\t\tfn := curFn.Node()\n\t\t\tvar ftyp types.Type\n\t\t\tswitch fn := fn.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tftyp = pkg.TypesInfo().Defs[fn.Name].Type()\n\t\t\tcase *ast.FuncLit:\n\t\t\t\tftyp = pkg.TypesInfo().TypeOf(fn)\n\t\t\t}\n\t\t\tif ftyp == nil {\n\t\t\t\tcontinue // missing type information\n\t\t\t}\n\t\t\tif unify(t, ftyp, nil) {\n\t\t\t\tpos := fn.Pos()\n\t\t\t\tloc, err := pgf.PosLocation(pos, pos+token.Pos(len(\"func\")))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tlocs = append(locs, loc)\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(adonovan): implement global search, by analogy with\n\t// methodsets algorithm.\n\t//\n\t// One optimization: if any signature type has free package\n\t// names, look for matches only in packages among the rdeps of\n\t// those packages.\n\n\treturn locs, nil\n}\n\n// beneathFuncDef reports whether the specified FuncType cursor is a\n// child of Func{Decl,Lit}.\nfunc beneathFuncDef(cur inspector.Cursor) bool {\n\tswitch cur.ParentEdgeKind() {\n\tcase edge.FuncDecl_Type, edge.FuncLit_Type:\n\t\treturn true\n\t}\n\treturn false\n}\n\n// dynamicFuncCallType reports whether call is a dynamic (non-method) function call.\n// If so, it returns the function type, otherwise nil.\n//\n// Tested via ../test/marker/testdata/implementation/signature.txt.\nfunc dynamicFuncCallType(info *types.Info, call *ast.CallExpr) types.Type {\n\tif typesinternal.ClassifyCall(info, call) == typesinternal.CallDynamic {\n\t\tif tv, ok := info.Types[call.Fun]; ok {\n\t\t\treturn tv.Type.Underlying()\n\t\t}\n\t}\n\treturn nil\n}\n\n// inToken reports whether (start, end) is within the token of\n// the specified position and string.\nfunc inToken(tokPos token.Pos, tokStr string, start, end token.Pos) bool {\n\treturn tokPos <= start && end <= tokPos+token.Pos(len(tokStr))\n}\n"
  },
  {
    "path": "gopls/internal/golang/implementation_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"go/types\"\n\t\"maps\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestUnify(t *testing.T) {\n\t// Most cases from TestMatches in gopls/internal/util/fingerprint/fingerprint_test.go.\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.24\n\n-- a/a.go --\npackage a\n\ntype Int = int\ntype String = string\n\n// Eq.Equal matches casefold.Equal.\ntype Eq[T any] interface { Equal(T, T) bool }\ntype casefold struct{}\nfunc (casefold) Equal(x, y string) bool\n\n// A matches AString.\ntype A[T any] = struct { x T }\ntype AString = struct { x string }\n\nfunc C1[T any](int, T, ...string) T { panic(0) }\nfunc C2[U any](int, int, ...U) bool { panic(0) }\nfunc C3(int, bool, ...string) rune\nfunc C4(int, bool, ...string)\nfunc C5(int, float64, bool, string) bool\nfunc C6(int, bool, ...string) bool\n\nfunc DAny[T any](Named[T]) { panic(0) }\nfunc DString(Named[string])\nfunc DInt(Named[int])\n\ntype Named[T any] struct { x T }\n\nfunc E1(byte) rune\nfunc E2(uint8) int32\nfunc E3(int8) uint32\n\n// generic vs. generic\nfunc F1[T any](T) { panic(0) }\nfunc F2[T any](*T) { panic(0) }\nfunc F3[T any](T, T) { panic(0) }\nfunc F4[U any](U, *U) {panic(0) }\nfunc F4a[U any](U, Named[U]) {panic(0) }\nfunc F5[T, U any](T, U, U) { panic(0) }\nfunc F6[T any](T, int, T) { panic(0) }\nfunc F7[T any](bool, T, T) { panic(0) }\nfunc F8[V any](*V, int, int) { panic(0) }\nfunc F9[V any](V, *V, V) { panic(0) }\n`\n\ttype tmap = map[*types.TypeParam]types.Type\n\n\tvar (\n\t\tboolType   = types.Typ[types.Bool]\n\t\tintType    = types.Typ[types.Int]\n\t\tstringType = types.Typ[types.String]\n\t)\n\n\tpkg := testfiles.LoadPackages(t, txtar.Parse([]byte(src)), \"./a\")[0]\n\tscope := pkg.Types.Scope()\n\n\ttparam := func(name string, index int) *types.TypeParam {\n\t\tobj := scope.Lookup(name)\n\t\tvar tps *types.TypeParamList\n\t\tswitch obj := obj.(type) {\n\t\tcase *types.Func:\n\t\t\ttps = obj.Signature().TypeParams()\n\t\tcase *types.TypeName:\n\t\t\tif n, ok := obj.Type().(*types.Named); ok {\n\t\t\t\ttps = n.TypeParams()\n\t\t\t} else {\n\t\t\t\ttps = obj.Type().(*types.Alias).TypeParams()\n\t\t\t}\n\t\tdefault:\n\t\t\tt.Fatalf(\"unsupported object of type %T\", obj)\n\t\t}\n\t\treturn tps.At(index)\n\t}\n\n\tfor _, test := range []struct {\n\t\tx, y       string // the symbols in the above source code whose types to unify\n\t\tmethod     string // optional field or method\n\t\tparams     tmap   // initial values of type params\n\t\twant       bool   // success or failure\n\t\twantParams tmap   // expected output\n\t}{\n\t\t{\n\t\t\t// In Eq[T], T is bound to string.\n\t\t\tx:          \"Eq\",\n\t\t\ty:          \"casefold\",\n\t\t\tmethod:     \"Equal\",\n\t\t\twant:       true,\n\t\t\twantParams: tmap{tparam(\"Eq\", 0): stringType},\n\t\t},\n\t\t{\n\t\t\t// If we unify A[T] and A[string], T should be bound to string.\n\t\t\tx:          \"A\",\n\t\t\ty:          \"AString\",\n\t\t\twant:       true,\n\t\t\twantParams: tmap{tparam(\"A\", 0): stringType},\n\t\t},\n\t\t{x: \"A\", y: \"Eq\", want: false}, // completely unrelated\n\t\t{\n\t\t\t// C1's U unifies with C6's bool.\n\t\t\tx:          \"C1\",\n\t\t\ty:          \"C6\",\n\t\t\twantParams: tmap{tparam(\"C1\", 0): boolType},\n\t\t\twant:       true,\n\t\t},\n\t\t// C1 fails to unify with C2 because C1's T must be bound to both int and bool.\n\t\t{x: \"C1\", y: \"C2\", want: false},\n\t\t// The remaining \"C\" cases fail for less interesting reasons, usually different numbers\n\t\t// or types of parameters or results.\n\t\t{x: \"C1\", y: \"C3\", want: false},\n\t\t{x: \"C1\", y: \"C4\", want: false},\n\t\t{x: \"C1\", y: \"C5\", want: false},\n\t\t{x: \"C2\", y: \"C3\", want: false},\n\t\t{x: \"C2\", y: \"C4\", want: false},\n\t\t{x: \"C3\", y: \"C4\", want: false},\n\t\t{\n\t\t\tx:          \"DAny\",\n\t\t\ty:          \"DString\",\n\t\t\twant:       true,\n\t\t\twantParams: tmap{tparam(\"DAny\", 0): stringType},\n\t\t},\n\t\t{x: \"DString\", y: \"DInt\", want: false}, // different instantiations of Named\n\t\t{x: \"E1\", y: \"E2\", want: true},         // byte and rune are just aliases\n\t\t{x: \"E2\", y: \"E3\", want: false},\n\n\t\t// The following tests cover all of the type param cases of unify.\n\t\t{\n\t\t\t// F1[*int] = F2[int], for example\n\t\t\t// F1's T is bound to a pointer to F2's T.\n\t\t\tx: \"F1\",\n\t\t\t// F2's T is unbound: any instantiation works.\n\t\t\ty:          \"F2\",\n\t\t\twant:       true,\n\t\t\twantParams: tmap{tparam(\"F1\", 0): types.NewPointer(tparam(\"F2\", 0))},\n\t\t},\n\t\t{x: \"F3\", y: \"F4\", want: false},  // would require U identical to *U, prevented by occur check\n\t\t{x: \"F3\", y: \"F4a\", want: false}, // occur check through Named[T]\n\t\t{\n\t\t\tx:    \"F5\",\n\t\t\ty:    \"F6\",\n\t\t\twant: true,\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F5\", 0): intType,\n\t\t\t\ttparam(\"F5\", 1): intType,\n\t\t\t\ttparam(\"F6\", 0): intType,\n\t\t\t},\n\t\t},\n\t\t{x: \"F6\", y: \"F7\", want: false}, // both are bound\n\t\t{\n\t\t\tx:      \"F5\",\n\t\t\ty:      \"F6\",\n\t\t\tparams: tmap{tparam(\"F6\", 0): intType}, // consistent with the result\n\t\t\twant:   true,\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F5\", 0): intType,\n\t\t\t\ttparam(\"F5\", 1): intType,\n\t\t\t\ttparam(\"F6\", 0): intType,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tx:      \"F5\",\n\t\t\ty:      \"F6\",\n\t\t\tparams: tmap{tparam(\"F6\", 0): boolType}, // not consistent\n\t\t\twant:   false,\n\t\t},\n\t\t{x: \"F6\", y: \"F7\", want: false}, // both are bound\n\t\t{\n\t\t\t// T=*V, U=int, V=int\n\t\t\tx:    \"F5\",\n\t\t\ty:    \"F8\",\n\t\t\twant: true,\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F5\", 0): types.NewPointer(tparam(\"F8\", 0)),\n\t\t\t\ttparam(\"F5\", 1): intType,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// T=*V, U=int, V=int\n\t\t\t// Partial initial information is fine, as long as it's consistent.\n\t\t\tx:      \"F5\",\n\t\t\ty:      \"F8\",\n\t\t\twant:   true,\n\t\t\tparams: tmap{tparam(\"F5\", 1): intType},\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F5\", 0): types.NewPointer(tparam(\"F8\", 0)),\n\t\t\t\ttparam(\"F5\", 1): intType,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// T=*V, U=int, V=int\n\t\t\t// Partial initial information is fine, as long as it's consistent.\n\t\t\tx:      \"F5\",\n\t\t\ty:      \"F8\",\n\t\t\twant:   true,\n\t\t\tparams: tmap{tparam(\"F5\", 0): types.NewPointer(tparam(\"F8\", 0))},\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F5\", 0): types.NewPointer(tparam(\"F8\", 0)),\n\t\t\t\ttparam(\"F5\", 1): intType,\n\t\t\t},\n\t\t},\n\t\t{x: \"F5\", y: \"F9\", want: false}, // T is unbound, V is bound, and T occurs in V\n\t\t{\n\t\t\t// T bound to Named[T']\n\t\t\tx:    \"F1\",\n\t\t\ty:    \"DAny\",\n\t\t\twant: true,\n\t\t\twantParams: tmap{\n\t\t\t\ttparam(\"F1\", 0): scope.Lookup(\"DAny\").(*types.Func).Signature().Params().At(0).Type()},\n\t\t},\n\t} {\n\n\t\tlookup := func(name string) types.Type {\n\t\t\tobj := scope.Lookup(name)\n\t\t\tif obj == nil {\n\t\t\t\tt.Fatalf(\"Lookup %s failed\", name)\n\t\t\t}\n\t\t\tif test.method != \"\" {\n\t\t\t\tobj, _, _ = types.LookupFieldOrMethod(obj.Type(), true, pkg.Types, test.method)\n\t\t\t\tif obj == nil {\n\t\t\t\t\tt.Fatalf(\"Lookup %s.%s failed\", name, test.method)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn obj.Type()\n\t\t}\n\n\t\tcheck := func(a, b string, want, compareParams bool) {\n\t\t\tt.Helper()\n\n\t\t\tta := lookup(a)\n\t\t\ttb := lookup(b)\n\n\t\t\tvar gotParams tmap\n\t\t\tif test.params == nil {\n\t\t\t\t// Get the unifier even if there are no input params.\n\t\t\t\tgotParams = tmap{}\n\t\t\t} else {\n\t\t\t\tgotParams = maps.Clone(test.params)\n\t\t\t}\n\t\t\tgot := unify(ta, tb, gotParams)\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"a=%s b=%s method=%s: unify returned %t for these inputs:\\n- %s\\n- %s\",\n\t\t\t\t\ta, b, test.method, got, ta, tb)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !compareParams {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !maps.EqualFunc(gotParams, test.wantParams, types.Identical) {\n\t\t\t\tt.Errorf(\"x=%s y=%s method=%s: params: got %v, want %v\",\n\t\t\t\t\ta, b, test.method, gotParams, test.wantParams)\n\t\t\t}\n\t\t}\n\n\t\tcheck(test.x, test.y, test.want, true)\n\t\t// unify is symmetric\n\t\tcheck(test.y, test.x, test.want, true)\n\t\t// unify is reflexive\n\t\tcheck(test.x, test.x, true, false)\n\t\tcheck(test.y, test.y, true, false)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/inlay_hint.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nfunc InlayHint(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pRng protocol.Range) ([]protocol.InlayHint, error) {\n\tctx, done := event.Start(ctx, \"golang.InlayHint\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting file for InlayHint: %w\", err)\n\t}\n\n\t// Collect a list of the inlay hints that are enabled.\n\tinlayHintOptions := snapshot.Options().InlayHintOptions\n\tvar enabledHints []inlayHintFunc\n\tfor hint, enabled := range inlayHintOptions.Hints {\n\t\tif !enabled {\n\t\t\tcontinue\n\t\t}\n\t\tif fn, ok := allInlayHints[hint]; ok {\n\t\t\tenabledHints = append(enabledHints, fn)\n\t\t}\n\t}\n\tif len(enabledHints) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tinfo := pkg.TypesInfo()\n\tqual := typesinternal.FileQualifier(pgf.File, pkg.Types())\n\n\t// Set the range to the full file if the range is not valid.\n\tstart, end := pgf.File.FileStart, pgf.File.FileEnd\n\n\t// TODO(adonovan): this condition looks completely wrong!\n\tif pRng.Start.Line < pRng.End.Line || pRng.Start.Character < pRng.End.Character {\n\t\t// Adjust start and end for the specified range.\n\t\tvar err error\n\t\tstart, end, err = pgf.RangePos(pRng)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tvar hints []protocol.InlayHint\n\tif curSubrange, ok := pgf.Cursor().FindByPos(start, end); ok {\n\t\tadd := func(hint protocol.InlayHint) { hints = append(hints, hint) }\n\t\tfor _, fn := range enabledHints {\n\t\t\tfn(info, pgf, qual, curSubrange, add)\n\t\t}\n\t}\n\treturn hints, nil\n}\n\ntype inlayHintFunc func(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint))\n\nvar allInlayHints = map[settings.InlayHint]inlayHintFunc{\n\tsettings.AssignVariableTypes:        assignVariableTypes,\n\tsettings.ConstantValues:             constantValues,\n\tsettings.ParameterNames:             parameterNames,\n\tsettings.RangeVariableTypes:         rangeVariableTypes,\n\tsettings.CompositeLiteralTypes:      compositeLiteralTypes,\n\tsettings.CompositeLiteralFieldNames: compositeLiteralFields,\n\tsettings.FunctionTypeParameters:     funcTypeParams,\n\tsettings.IgnoredError:               ignoredError,\n}\n\nfunc parameterNames(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curCall := range cur.Preorder((*ast.CallExpr)(nil)) {\n\t\tcallExpr := curCall.Node().(*ast.CallExpr)\n\t\tt := info.TypeOf(callExpr.Fun)\n\t\tif t == nil {\n\t\t\tcontinue\n\t\t}\n\t\tsignature, ok := typeparams.CoreType(t).(*types.Signature)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor i, v := range callExpr.Args {\n\t\t\tstart, err := pgf.PosPosition(v.Pos())\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparams := signature.Params()\n\t\t\t// When a function has variadic params, we skip args after\n\t\t\t// params.Len().\n\t\t\tif i > params.Len()-1 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tparam := params.At(i)\n\t\t\t// param.Name is empty for built-ins like append\n\t\t\tif param.Name() == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Skip the parameter name hint if the arg matches\n\t\t\t// the parameter name.\n\t\t\tif i, ok := v.(*ast.Ident); ok && i.Name == param.Name() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlabel := param.Name()\n\t\t\tif signature.Variadic() && i == params.Len()-1 {\n\t\t\t\tlabel = label + \"...\"\n\t\t\t}\n\t\t\tadd(protocol.InlayHint{\n\t\t\t\tPosition:     start,\n\t\t\t\tLabel:        labelPart(label + \":\"),\n\t\t\t\tKind:         protocol.Parameter,\n\t\t\t\tPaddingRight: true,\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc ignoredError(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\nouter:\n\tfor curCall := range cur.Preorder((*ast.ExprStmt)(nil)) {\n\t\tstmt := curCall.Node().(*ast.ExprStmt)\n\t\tcall, ok := stmt.X.(*ast.CallExpr)\n\t\tif !ok {\n\t\t\tcontinue // not a call stmt\n\t\t}\n\n\t\t// Check that type of result (or last component) is error.\n\t\ttv, ok := info.Types[call]\n\t\tif !ok {\n\t\t\tcontinue // no type info\n\t\t}\n\t\tt := tv.Type\n\t\tif res, ok := t.(*types.Tuple); ok && res.Len() > 1 {\n\t\t\tt = res.At(res.Len() - 1).Type()\n\t\t}\n\t\tif !types.Identical(t, errorType) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Suppress some common false positives.\n\t\tobj := typeutil.Callee(info, call)\n\t\tif typesinternal.IsFunctionNamed(obj, \"fmt\", \"Print\", \"Printf\", \"Println\", \"Fprint\", \"Fprintf\", \"Fprintln\") ||\n\t\t\ttypesinternal.IsMethodNamed(obj, \"bytes\", \"Buffer\", \"Write\", \"WriteByte\", \"WriteRune\", \"WriteString\") ||\n\t\t\ttypesinternal.IsMethodNamed(obj, \"strings\", \"Builder\", \"Write\", \"WriteByte\", \"WriteRune\", \"WriteString\") ||\n\t\t\ttypesinternal.IsFunctionNamed(obj, \"io\", \"WriteString\") {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Suppress if comment on same line contains \"// ignore error\".\n\t\tline := func(pos token.Pos) int { return safetoken.Line(pgf.Tok, pos) }\n\t\tcomments := pgf.File.Comments\n\t\tcompare := func(cg *ast.CommentGroup, pos token.Pos) int {\n\t\t\treturn cmp.Compare(cg.Pos(), pos)\n\t\t}\n\t\ti, _ := slices.BinarySearchFunc(comments, stmt.End(), compare)\n\t\tif i >= 0 && i < len(comments) {\n\t\t\tcg := comments[i]\n\t\t\tif line(cg.Pos()) == line(stmt.End()) && strings.Contains(cg.Text(), \"ignore error\") {\n\t\t\t\tcontinue outer // suppress\n\t\t\t}\n\t\t}\n\n\t\t// Provide a hint.\n\t\tpos, err := pgf.PosPosition(stmt.End())\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tadd(protocol.InlayHint{\n\t\t\tPosition: pos,\n\t\t\tLabel:    labelPart(\" // ignore error\"),\n\t\t})\n\t}\n}\n\nfunc funcTypeParams(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curCall := range cur.Preorder((*ast.CallExpr)(nil)) {\n\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\tid, ok := call.Fun.(*ast.Ident)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tinst := info.Instances[id]\n\t\tif inst.TypeArgs == nil {\n\t\t\tcontinue\n\t\t}\n\t\tstart, err := pgf.PosPosition(id.End())\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tvar args []string\n\t\tfor t := range inst.TypeArgs.Types() {\n\t\t\targs = append(args, t.String())\n\t\t}\n\t\tif len(args) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tadd(protocol.InlayHint{\n\t\t\tPosition: start,\n\t\t\tLabel:    labelPart(\"[\" + strings.Join(args, \", \") + \"]\"),\n\t\t\tKind:     protocol.Type,\n\t\t})\n\t}\n}\n\nfunc assignVariableTypes(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor node := range cur.Preorder((*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil)) {\n\t\tswitch n := node.Node().(type) {\n\t\tcase *ast.AssignStmt:\n\t\t\tif n.Tok != token.DEFINE {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, v := range n.Lhs {\n\t\t\t\tvariableType(info, pgf, qual, v, add)\n\t\t\t}\n\t\tcase *ast.GenDecl:\n\t\t\tif n.Tok != token.VAR {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, v := range n.Specs {\n\t\t\t\tspec := v.(*ast.ValueSpec)\n\t\t\t\t// The type of the variable is written, skip showing type of this var.\n\t\t\t\t// ```go\n\t\t\t\t// var foo string\n\t\t\t\t// ```\n\t\t\t\tif spec.Type != nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfor _, v := range spec.Names {\n\t\t\t\t\tvariableType(info, pgf, qual, v, add)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc rangeVariableTypes(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curRange := range cur.Preorder((*ast.RangeStmt)(nil)) {\n\t\trStmt := curRange.Node().(*ast.RangeStmt)\n\t\tvariableType(info, pgf, qual, rStmt.Key, add)\n\t\tvariableType(info, pgf, qual, rStmt.Value, add)\n\t}\n}\n\nfunc variableType(info *types.Info, pgf *parsego.File, qual types.Qualifier, e ast.Expr, add func(protocol.InlayHint)) {\n\ttyp := info.TypeOf(e)\n\tif typ == nil {\n\t\treturn\n\t}\n\tend, err := pgf.PosPosition(e.End())\n\tif err != nil {\n\t\treturn\n\t}\n\tadd(protocol.InlayHint{\n\t\tPosition:    end,\n\t\tLabel:       labelPart(types.TypeString(typ, qual)),\n\t\tKind:        protocol.Type,\n\t\tPaddingLeft: true,\n\t})\n}\n\nfunc constantValues(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curDecl := range cur.Preorder((*ast.GenDecl)(nil)) {\n\t\tgenDecl := curDecl.Node().(*ast.GenDecl)\n\t\tif genDecl.Tok != token.CONST {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, v := range genDecl.Specs {\n\t\t\tspec, ok := v.(*ast.ValueSpec)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tend, err := pgf.PosPosition(v.End())\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Show hints when values are missing or at least one value is not\n\t\t\t// a basic literal.\n\t\t\tshowHints := len(spec.Values) == 0\n\t\t\tcheckValues := len(spec.Names) == len(spec.Values)\n\t\t\tvar values []string\n\t\t\tfor i, w := range spec.Names {\n\t\t\t\tobj, ok := info.ObjectOf(w).(*types.Const)\n\t\t\t\tif !ok || obj.Val().Kind() == constant.Unknown {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif checkValues {\n\t\t\t\t\tswitch spec.Values[i].(type) {\n\t\t\t\t\tcase *ast.BadExpr:\n\t\t\t\t\t\tcontinue\n\t\t\t\t\tcase *ast.BasicLit:\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif obj.Val().Kind() != constant.Bool {\n\t\t\t\t\t\t\tshowHints = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalues = append(values, fmt.Sprintf(\"%v\", obj.Val()))\n\t\t\t}\n\t\t\tif !showHints || len(values) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tadd(protocol.InlayHint{\n\t\t\t\tPosition:    end,\n\t\t\t\tLabel:       labelPart(\"= \" + strings.Join(values, \", \")),\n\t\t\t\tPaddingLeft: true,\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc compositeLiteralFields(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curCompLit := range cur.Preorder((*ast.CompositeLit)(nil)) {\n\t\tcompLit, ok := curCompLit.Node().(*ast.CompositeLit)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\ttyp := info.TypeOf(compLit)\n\t\tif typ == nil {\n\t\t\tcontinue\n\t\t}\n\t\ttyp = typesinternal.Unpointer(typ)\n\t\tstrct, ok := typeparams.CoreType(typ).(*types.Struct)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar hints []protocol.InlayHint\n\t\tvar allEdits []protocol.TextEdit\n\t\tfor i, v := range compLit.Elts {\n\t\t\tif _, ok := v.(*ast.KeyValueExpr); !ok {\n\t\t\t\tstart, err := pgf.PosPosition(v.Pos())\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif i > strct.NumFields()-1 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\thints = append(hints, protocol.InlayHint{\n\t\t\t\t\tPosition:     start,\n\t\t\t\t\tLabel:        labelPart(strct.Field(i).Name() + \":\"),\n\t\t\t\t\tKind:         protocol.Parameter,\n\t\t\t\t\tPaddingRight: true,\n\t\t\t\t})\n\t\t\t\tallEdits = append(allEdits, protocol.TextEdit{\n\t\t\t\t\tRange:   protocol.Range{Start: start, End: start},\n\t\t\t\t\tNewText: strct.Field(i).Name() + \": \",\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\t// It is not allowed to have a mix of keyed and unkeyed fields, so\n\t\t// have the text edits add keys to all fields.\n\t\tfor i := range hints {\n\t\t\thints[i].TextEdits = allEdits\n\t\t\tadd(hints[i])\n\t\t}\n\t}\n}\n\nfunc compositeLiteralTypes(info *types.Info, pgf *parsego.File, qual types.Qualifier, cur inspector.Cursor, add func(protocol.InlayHint)) {\n\tfor curCompLit := range cur.Preorder((*ast.CompositeLit)(nil)) {\n\t\tcompLit := curCompLit.Node().(*ast.CompositeLit)\n\t\ttyp := info.TypeOf(compLit)\n\t\tif typ == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif compLit.Type != nil {\n\t\t\tcontinue\n\t\t}\n\t\tprefix := \"\"\n\t\tif t, ok := typeparams.CoreType(typ).(*types.Pointer); ok {\n\t\t\ttyp = t.Elem()\n\t\t\tprefix = \"&\"\n\t\t}\n\t\t// The type for this composite literal is implicit, add an inlay hint.\n\t\tstart, err := pgf.PosPosition(compLit.Lbrace)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tadd(protocol.InlayHint{\n\t\t\tPosition: start,\n\t\t\tLabel:    labelPart(fmt.Sprintf(\"%s%s\", prefix, types.TypeString(typ, qual))),\n\t\t\tKind:     protocol.Type,\n\t\t})\n\t}\n}\n\nfunc labelPart(s string) []protocol.InlayHintLabelPart {\n\tconst maxLabelLength = 28\n\tif len(s) > maxLabelLength+len(\"...\") {\n\t\ts = s[:maxLabelLength] + \"...\"\n\t}\n\treturn []protocol.InlayHintLabelPart{{Value: s}}\n}\n"
  },
  {
    "path": "gopls/internal/golang/inline.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines the refactor.inline code action.\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n)\n\n// enclosingStaticCall returns the innermost function call enclosing\n// the selected range, along with the callee.\nfunc enclosingStaticCall(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*ast.CallExpr, *types.Func, error) {\n\t// TODO(adonovan): simplify using pgf.Cursor\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, start, end)\n\n\tvar call *ast.CallExpr\nloop:\n\tfor _, n := range path {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncLit:\n\t\t\tbreak loop\n\t\tcase *ast.CallExpr:\n\t\t\tcall = n\n\t\t\tbreak loop\n\t\t}\n\t}\n\tif call == nil {\n\t\treturn nil, nil, fmt.Errorf(\"no enclosing call\")\n\t}\n\tif safetoken.Line(pgf.Tok, call.Lparen) != safetoken.Line(pgf.Tok, start) {\n\t\treturn nil, nil, fmt.Errorf(\"enclosing call is not on this line\")\n\t}\n\tfn := typeutil.StaticCallee(pkg.TypesInfo(), call)\n\tif fn == nil {\n\t\treturn nil, nil, fmt.Errorf(\"not a static call to a Go function\")\n\t}\n\treturn call, fn, nil\n}\n\nfunc inlineCall(ctx context.Context, snapshot *cache.Snapshot, callerPkg *cache.Package, callerPGF *parsego.File, start, end token.Pos) (_ *token.FileSet, _ *analysis.SuggestedFix, err error) {\n\tcountInlineCall.Inc()\n\t// Find enclosing static call.\n\tcall, fn, err := enclosingStaticCall(callerPkg, callerPGF, start, end)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tcalleePkg, calleePGF, calleePos, err := NarrowestDeclaringPackage(ctx, snapshot, callerPkg, fn)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar calleeDecl *ast.FuncDecl\n\tfor _, decl := range calleePGF.File.Decls {\n\t\tfuncDecl, ok := decl.(*ast.FuncDecl)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif funcDecl.Name.Pos() == calleePos {\n\t\t\tcalleeDecl = funcDecl\n\t\t\tbreak\n\t\t}\n\t}\n\tif calleeDecl == nil {\n\t\treturn nil, nil, fmt.Errorf(\"can't find callee\")\n\t}\n\n\t// The inliner assumes that input is well-typed,\n\t// but that is frequently not the case within gopls.\n\t// Until we are able to harden the inliner,\n\t// report panics as errors to avoid crashing the server.\n\tbad := func(p *cache.Package) bool { return len(p.ParseErrors())+len(p.TypeErrors()) > 0 }\n\tif bad(calleePkg) || bad(callerPkg) {\n\t\tdefer func() {\n\t\t\tif x := recover(); x != nil {\n\t\t\t\terr = fmt.Errorf(\"inlining failed (%q), likely because inputs were ill-typed\", x)\n\t\t\t}\n\t\t}()\n\t}\n\n\t// Users can consult the gopls event log to see\n\t// why a particular inlining strategy was chosen.\n\tlogf := logger(ctx, \"inliner\", snapshot.Options().VerboseOutput)\n\n\tcallee, err := inline.AnalyzeCallee(logf, calleePkg.FileSet(), calleePkg.Types(), calleePkg.TypesInfo(), calleeDecl, calleePGF.Src)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Inline the call.\n\tcaller := &inline.Caller{\n\t\tFset:      callerPkg.FileSet(),\n\t\tTypes:     callerPkg.Types(),\n\t\tInfo:      callerPkg.TypesInfo(),\n\t\tFile:      callerPGF.File,\n\t\tCall:      call,\n\t\tCountUses: nil, // (use inefficient default implementation)\n\t}\n\n\tres, err := inline.Inline(caller, callee, &inline.Options{Logf: logf})\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn callerPkg.FileSet(), &analysis.SuggestedFix{\n\t\tMessage:   fmt.Sprintf(\"inline call of %v\", callee),\n\t\tTextEdits: res.Edits,\n\t}, nil\n}\n\n// TODO(adonovan): change the inliner to instead accept an io.Writer.\nfunc logger(ctx context.Context, name string, verbose bool) func(format string, args ...any) {\n\tif verbose {\n\t\treturn func(format string, args ...any) {\n\t\t\tevent.Log(ctx, name+\": \"+fmt.Sprintf(format, args...))\n\t\t}\n\t} else {\n\t\treturn func(string, ...any) {}\n\t}\n}\n\n// canInlineVariable reports whether the selection is within an\n// identifier that is a use of a variable that has an initializer\n// expression. If so, it returns cursors for the identifier and the\n// initializer expression.\nfunc canInlineVariable(info *types.Info, curFile inspector.Cursor, start, end token.Pos) (_, _ inspector.Cursor, ok bool) {\n\tif curUse, ok := curFile.FindByPos(start, end); ok {\n\t\tif id, ok := curUse.Node().(*ast.Ident); ok && !isLvalueUse(curUse, info) {\n\t\t\tif v, ok := info.Uses[id].(*types.Var); ok && v.Kind() == types.LocalVar {\n\t\t\t\tif curIdent, ok := curFile.FindByPos(v.Pos(), v.Pos()); ok {\n\t\t\t\t\tcurParent := curIdent.Parent()\n\t\t\t\t\tkind, index := curIdent.ParentEdge()\n\t\t\t\t\tswitch kind {\n\t\t\t\t\tcase edge.ValueSpec_Names:\n\t\t\t\t\t\t// var v = expr\n\t\t\t\t\t\tspec := curParent.Node().(*ast.ValueSpec)\n\t\t\t\t\t\tif len(spec.Names) == len(spec.Values) {\n\t\t\t\t\t\t\treturn curUse, curParent.ChildAt(edge.ValueSpec_Values, index), true\n\t\t\t\t\t\t}\n\t\t\t\t\tcase edge.AssignStmt_Lhs:\n\t\t\t\t\t\t// v := expr\n\t\t\t\t\t\tstmt := curParent.Node().(*ast.AssignStmt)\n\t\t\t\t\t\tif len(stmt.Lhs) == len(stmt.Rhs) {\n\t\t\t\t\t\t\treturn curUse, curParent.ChildAt(edge.AssignStmt_Rhs, index), true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// isLvalueUse reports whether the \"use\" identifier represented by cur\n// appears in an l-value context such as:\n//\n//   - v=...\n//   - v++\n//   - &v\n//   - v.f(), when this implicitly takes the address of v.\nfunc isLvalueUse(cur inspector.Cursor, info *types.Info) bool {\n\tcur = unparenEnclosing(cur)\n\n\tswitch cur.ParentEdgeKind() {\n\tcase edge.AssignStmt_Lhs, edge.IncDecStmt_X:\n\t\treturn true // v=..., v++\n\n\tcase edge.UnaryExpr_X:\n\t\treturn cur.Parent().Node().(*ast.UnaryExpr).Op == token.AND // &v\n\n\tcase edge.SelectorExpr_X:\n\t\tsel := cur.Parent().Node().(*ast.SelectorExpr)\n\t\tisPointer := func(t types.Type) bool {\n\t\t\treturn is[*types.Pointer](t)\n\t\t}\n\t\tif seln, ok := info.Selections[sel]; ok && seln.Kind() == types.MethodVal {\n\t\t\t// Have: recv.f() method call\n\t\t\tmethodRecv := seln.Obj().(*types.Func).Signature().Recv().Type()\n\t\t\treturn !seln.Indirect() && isPointer(methodRecv) && !isPointer(info.TypeOf(sel.X))\n\t\t}\n\t}\n\n\treturn false\n}\n\n// unparenEnclosing removes enclosing parens from cur in\n// preparation for a call to [Cursor.ParentEdge].\nfunc unparenEnclosing(cur inspector.Cursor) inspector.Cursor {\n\tfor cur.ParentEdgeKind() == edge.ParenExpr_X {\n\t\tcur = cur.Parent()\n\t}\n\treturn cur\n}\n\n// inlineVariableOne computes a fix to replace the selected variable by\n// its initialization expression.\nfunc inlineVariableOne(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tcountInlineVariable.Inc()\n\tinfo := pkg.TypesInfo()\n\tcurUse, curRHS, ok := canInlineVariable(info, pgf.Cursor(), start, end)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"cannot inline variable here\")\n\t}\n\n\t// Check that free symbols of rhs are unshadowed at curUse.\n\tvar (\n\t\tuse   = curUse.Node().(*ast.Ident)\n\t\trhs   = curRHS.Node().(ast.Expr)\n\t\tpos   = use.Pos()\n\t\tscope = info.Scopes[pgf.File].Innermost(pos)\n\t)\n\tfor curIdent := range curRHS.Preorder((*ast.Ident)(nil)) {\n\t\tif curIdent.ParentEdgeKind() == edge.SelectorExpr_Sel {\n\t\t\tcontinue // ignore f in x.f\n\t\t}\n\t\tid := curIdent.Node().(*ast.Ident)\n\t\tobj1 := info.Uses[id]\n\t\tif obj1 == nil {\n\t\t\tcontinue // undefined; or a def, not a use\n\t\t}\n\t\tif v, ok := obj1.(*types.Var); ok && v.IsField() {\n\t\t\tcontinue // a field reference T{F: 0} is non-lexical\n\t\t}\n\t\tif astutil.NodeContainsPos(rhs, obj1.Pos()) {\n\t\t\tcontinue // not free (id is defined within RHS)\n\t\t}\n\t\t_, obj2 := scope.LookupParent(id.Name, pos)\n\t\t// Inv: obj2 is non-nil.\n\t\tif obj1 != obj2 {\n\t\t\treturn nil, nil, fmt.Errorf(\"cannot inline variable: its initializer expression refers to %q, which is shadowed by the declaration at line %d\", id.Name, safetoken.Position(pgf.Tok, obj2.Pos()).Line)\n\t\t}\n\t}\n\n\t// TODO(adonovan): also reject variables that are updated by assignments?\n\n\t// Add parens to 'new' as needed by the 'use' context.\n\trhs = astutil.MaybeParenthesize(curUse.Parent().Node(), use, rhs)\n\n\treturn pkg.FileSet(), &analysis.SuggestedFix{\n\t\tMessage: fmt.Sprintf(\"Replace variable %q by its initializer expression\", use.Name),\n\t\tTextEdits: []analysis.TextEdit{\n\t\t\t{\n\t\t\t\tPos:     use.Pos(),\n\t\t\t\tEnd:     use.End(),\n\t\t\t\tNewText: []byte(FormatNode(pkg.FileSet(), rhs)),\n\t\t\t},\n\t\t},\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/inline_all.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n)\n\n// inlineAllCalls inlines all calls to the original function declaration\n// described by callee, returning the resulting modified file content.\n//\n// inlining everything is currently an expensive operation: it involves re-type\n// checking every package that contains a potential call, as reported by\n// References. In cases where there are multiple calls per file, inlineAllCalls\n// must type check repeatedly for each additional call.\n//\n// The provided post processing function is applied to the resulting source\n// after each transformation. This is necessary because we are using this\n// function to inline synthetic wrappers for the purpose of signature\n// rewriting. The delegated function has a fake name that doesn't exist in the\n// snapshot, and so we can't re-type check until we replace this fake name.\n//\n// TODO(rfindley): this only works because removing a parameter is a very\n// narrow operation. A better solution would be to allow for ad-hoc snapshots\n// that expose the full machinery of real snapshots: minimal invalidation,\n// batched type checking, etc. Then we could actually rewrite the declaring\n// package in this snapshot (and so 'post' would not be necessary), and could\n// robustly re-type check for the purpose of iterative inlining, even if the\n// inlined code pulls in new imports that weren't present in export data.\n//\n// The code below notes where are assumptions are made that only hold true in\n// the case of parameter removal (annotated with 'Assumption:')\nfunc inlineAllCalls(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, origDecl *ast.FuncDecl, callee *inline.Callee, post func([]byte) []byte, opts *inline.Options) (_ map[protocol.DocumentURI][]byte, inlineErr error) {\n\t// Collect references.\n\tvar refs []protocol.Location\n\t{\n\t\tfuncRng, err := pgf.Mapper.PosRange(pgf.Tok, origDecl.Name.NamePos, origDecl.Name.NamePos)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfh, err := snapshot.ReadFile(ctx, pgf.URI)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trefs, err = References(ctx, snapshot, fh, funcRng, false)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"finding references to rewrite: %v\", err)\n\t\t}\n\t}\n\n\t// Type-check the narrowest package containing each reference.\n\t// TODO(rfindley): we should expose forEachPackage in order to operate in\n\t// parallel and to reduce peak memory for this operation.\n\tvar (\n\t\tpkgForRef = make(map[protocol.Location]PackageID)\n\t\tpkgs      = make(map[PackageID]*cache.Package)\n\t\t// The inliner assumes that input is well-typed, but that is frequently not\n\t\t// the case within gopls.\n\t\t// Until we're able to harden the inliner, report panics as errors to avoid\n\t\t// crashing the server.\n\t\tbadPkg = false\n\t)\n\t{\n\t\tneedPkgs := make(map[PackageID]struct{})\n\t\tfor _, ref := range refs {\n\t\t\tmd, err := snapshot.NarrowestMetadataForFile(ctx, ref.URI)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"finding ref metadata: %v\", err)\n\t\t\t}\n\t\t\tpkgForRef[ref] = md.ID\n\t\t\tneedPkgs[md.ID] = struct{}{}\n\t\t}\n\t\tvar pkgIDs []PackageID\n\t\tfor id := range needPkgs { // TODO: use maps.Keys once it is available to us\n\t\t\tpkgIDs = append(pkgIDs, id)\n\t\t}\n\n\t\trefPkgs, err := snapshot.TypeCheck(ctx, pkgIDs...)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"type checking reference packages: %v\", err)\n\t\t}\n\n\t\tfor _, p := range refPkgs {\n\t\t\tpkgs[p.Metadata().ID] = p\n\t\t\tif len(p.ParseErrors())+len(p.TypeErrors()) > 0 {\n\t\t\t\tbadPkg = true\n\t\t\t}\n\t\t}\n\t}\n\n\tif badPkg {\n\t\tdefer func() {\n\t\t\tif x := recover(); x != nil {\n\t\t\t\tinlineErr = fmt.Errorf(\"inlining failed (%q), likely because inputs were ill-typed\", x)\n\t\t\t}\n\t\t}()\n\t}\n\n\t// Organize calls by top file declaration. Calls within a single file may\n\t// affect each other, as the inlining edit may affect the surrounding scope\n\t// or imports Therefore, when inlining subsequent calls in the same\n\t// declaration, we must re-type check.\n\n\ttype fileCalls struct {\n\t\tpkg   *cache.Package\n\t\tpgf   *parsego.File\n\t\tcalls []*ast.CallExpr\n\t}\n\n\trefsByFile := make(map[protocol.DocumentURI]*fileCalls)\n\tfor _, ref := range refs {\n\t\trefpkg := pkgs[pkgForRef[ref]]\n\t\tpgf, err := refpkg.File(ref.URI)\n\t\tif err != nil {\n\t\t\treturn nil, bug.Errorf(\"finding %s in %s: %v\", ref.URI, refpkg.Metadata().ID, err)\n\t\t}\n\n\t\tstart, end, err := pgf.RangePos(ref.Range)\n\t\tif err != nil {\n\t\t\treturn nil, err // e.g. invalid range\n\t\t}\n\n\t\t// Look for the surrounding call expression.\n\t\tvar (\n\t\t\tname *ast.Ident\n\t\t\tcall *ast.CallExpr\n\t\t)\n\t\tpath, _ := astutil.PathEnclosingInterval(pgf.File, start, end)\n\t\tname, _ = path[0].(*ast.Ident)\n\n\t\t// TODO(rfindley): handle method expressions correctly.\n\t\tif _, ok := path[1].(*ast.SelectorExpr); ok {\n\t\t\tcall, _ = path[2].(*ast.CallExpr)\n\t\t} else {\n\t\t\tcall, _ = path[1].(*ast.CallExpr)\n\t\t}\n\t\tif name == nil || call == nil {\n\t\t\t// TODO(rfindley): handle this case with eta-abstraction:\n\t\t\t// a reference to the target function f in a non-call position\n\t\t\t//    use(f)\n\t\t\t// is replaced by\n\t\t\t//    use(func(...) { f(...) })\n\t\t\treturn nil, fmt.Errorf(\"cannot inline: found non-call function reference %v\", ref)\n\t\t}\n\n\t\t// Heuristic: ignore references that overlap with type checker errors, as they may\n\t\t// lead to invalid results (see golang/go#70268).\n\t\thasTypeErrors := false\n\t\tfor _, typeErr := range refpkg.TypeErrors() {\n\t\t\tif call.Lparen <= typeErr.Pos && typeErr.Pos <= call.Rparen {\n\t\t\t\thasTypeErrors = true\n\t\t\t}\n\t\t}\n\n\t\tif hasTypeErrors {\n\t\t\tcontinue\n\t\t}\n\n\t\tif typeutil.StaticCallee(refpkg.TypesInfo(), call) == nil {\n\t\t\tcontinue // dynamic call\n\t\t}\n\n\t\t// Sanity check.\n\t\tif obj := refpkg.TypesInfo().ObjectOf(name); obj == nil ||\n\t\t\tobj.Name() != origDecl.Name.Name ||\n\t\t\tobj.Pkg() == nil ||\n\t\t\tobj.Pkg().Path() != string(pkg.Metadata().PkgPath) {\n\n\t\t\treturn nil, bug.Errorf(\"cannot inline: corrupted reference %v\", ref)\n\t\t}\n\n\t\tcallInfo, ok := refsByFile[ref.URI]\n\t\tif !ok {\n\t\t\tcallInfo = &fileCalls{\n\t\t\t\tpkg: refpkg,\n\t\t\t\tpgf: pgf,\n\t\t\t}\n\t\t\trefsByFile[ref.URI] = callInfo\n\t\t}\n\t\tcallInfo.calls = append(callInfo.calls, call)\n\t}\n\n\t// Inline each call within the same decl in sequence, re-typechecking after\n\t// each one. If there is only a single call within the decl, we can avoid\n\t// additional type checking.\n\t//\n\t// Assumption: inlining does not affect the package scope, so we can operate\n\t// on separate files independently.\n\tresult := make(map[protocol.DocumentURI][]byte)\n\tfor uri, callInfo := range refsByFile {\n\t\tvar (\n\t\t\tcalls   = callInfo.calls\n\t\t\tfset    = callInfo.pkg.FileSet()\n\t\t\ttpkg    = callInfo.pkg.Types()\n\t\t\ttinfo   = callInfo.pkg.TypesInfo()\n\t\t\tfile    = callInfo.pgf.File\n\t\t\tcontent = callInfo.pgf.Src\n\t\t)\n\n\t\t// Check for overlapping calls (such as Foo(Foo())). We can't handle these\n\t\t// because inlining may change the source order of the inner call with\n\t\t// respect to the inlined outer call, and so the heuristic we use to find\n\t\t// the next call (counting from top-to-bottom) does not work.\n\t\tfor i := range calls {\n\t\t\tif i > 0 && calls[i-1].End() > calls[i].Pos() {\n\t\t\t\treturn nil, fmt.Errorf(\"%s: can't inline overlapping call %s\", uri, types.ExprString(calls[i-1]))\n\t\t\t}\n\t\t}\n\n\t\tcurrentCall := 0\n\t\tfor currentCall < len(calls) {\n\t\t\tcaller := &inline.Caller{\n\t\t\t\tFset:      fset,\n\t\t\t\tTypes:     tpkg,\n\t\t\t\tInfo:      tinfo,\n\t\t\t\tFile:      file,\n\t\t\t\tCall:      calls[currentCall],\n\t\t\t\tCountUses: nil, // TODO(adonovan): opt: amortize across callInfo.pkg\n\t\t\t}\n\t\t\tres, err := inline.Inline(caller, callee, opts)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"inlining failed: %v\", err)\n\t\t\t}\n\n\t\t\t// applyEdits transforms content by applying the specified edits\n\t\t\t// (whose positions are defined by fset), reformatting the file, and\n\t\t\t// removing unused imports (using pkg for names of imported packages).\n\t\t\t// (Adapted from inline_test.applyEdits.)\n\t\t\tapplyEdits := func(content []byte, edits []refactor.Edit) ([]byte, error) {\n\t\t\t\tdedits := make([]diff.Edit, len(edits))\n\t\t\t\tfor i, edit := range edits {\n\t\t\t\t\tdedits[i] = diff.Edit{\n\t\t\t\t\t\tStart: int(edit.Pos - file.FileStart),\n\t\t\t\t\t\tEnd:   int(edit.End - file.FileStart),\n\t\t\t\t\t\tNew:   string(edit.NewText),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tgot, err := diff.ApplyBytes(content, dedits)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err // inliner produced invalid edits\n\t\t\t\t}\n\t\t\t\tgot, err = driverutil.FormatSourceRemoveImports(tpkg, got)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err // failed to parse+print\n\t\t\t\t}\n\t\t\t\treturn []byte(got), nil\n\t\t\t}\n\n\t\t\tcontent, err = applyEdits(content, res.Edits)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"applying inliner edits failed: %v\", err)\n\t\t\t}\n\n\t\t\tif post != nil {\n\t\t\t\tcontent = post(content)\n\t\t\t}\n\t\t\tif len(calls) <= 1 {\n\t\t\t\t// No need to re-type check, as we've inlined all calls.\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// TODO(rfindley): develop a theory of \"trivial\" inlining, which are\n\t\t\t// inlinings that don't require re-type checking.\n\t\t\t//\n\t\t\t// In principle, if the inlining only involves replacing one call with\n\t\t\t// another, the scope of the caller is unchanged and there is no need to\n\t\t\t// type check again before inlining subsequent calls (edits should not\n\t\t\t// overlap, and should not affect each other semantically). However, it\n\t\t\t// feels sufficiently complicated that, to be safe, this optimization is\n\t\t\t// deferred until later.\n\n\t\t\tfile, err = parser.ParseFile(fset, uri.Path(), content, parser.ParseComments|parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, bug.Errorf(\"inlined file failed to parse: %v\", err)\n\t\t\t}\n\n\t\t\t// After inlining one call with a removed parameter, the package will\n\t\t\t// fail to type check due to \"not enough arguments\". Therefore, we must\n\t\t\t// allow type errors here.\n\t\t\t//\n\t\t\t// Assumption: the resulting type errors do not affect the correctness of\n\t\t\t// subsequent inlining, because invalid arguments to a call do not affect\n\t\t\t// anything in the surrounding scope.\n\t\t\t//\n\t\t\t// TODO(rfindley): improve this.\n\t\t\tlogf := func(string, ...any) {}\n\t\t\tif opts != nil {\n\t\t\t\tlogf = opts.Logf\n\t\t\t}\n\t\t\ttpkg, tinfo, err = reTypeCheck(logf, callInfo.pkg, map[protocol.DocumentURI]*ast.File{uri: file}, true)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, bug.Errorf(\"type checking after inlining failed: %v\", err)\n\t\t\t}\n\n\t\t\t// Collect calls to the target function in the modified declaration.\n\t\t\tvar calls2 []*ast.CallExpr\n\t\t\tast.Inspect(file, func(n ast.Node) bool {\n\t\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\tfn := typeutil.StaticCallee(tinfo, call)\n\t\t\t\t\tif fn != nil && fn.Pkg().Path() == string(pkg.Metadata().PkgPath) && fn.Name() == origDecl.Name.Name {\n\t\t\t\t\t\tcalls2 = append(calls2, call)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\n\t\t\t// If the number of calls has increased, this process will never cease.\n\t\t\t// If the number of calls has decreased, assume that inlining removed a\n\t\t\t// call.\n\t\t\t// If the number of calls didn't change, assume that inlining replaced\n\t\t\t// a call, and move on to the next.\n\t\t\t//\n\t\t\t// Assumption: we're inlining a call that has at most one recursive\n\t\t\t// reference (which holds for signature rewrites).\n\t\t\t//\n\t\t\t// TODO(rfindley): this isn't good enough. We should be able to support\n\t\t\t// inlining all existing calls even if they increase calls. How do we\n\t\t\t// correlate the before and after syntax?\n\t\t\tswitch {\n\t\t\tcase len(calls2) > len(calls):\n\t\t\t\treturn nil, fmt.Errorf(\"inlining increased calls %d->%d, possible recursive call? content:\\n%s\", len(calls), len(calls2), content)\n\t\t\tcase len(calls2) < len(calls):\n\t\t\t\tcalls = calls2\n\t\t\tcase len(calls2) == len(calls):\n\t\t\t\tcalls = calls2\n\t\t\t\tcurrentCall++\n\t\t\t}\n\t\t}\n\n\t\tresult[callInfo.pgf.URI] = content\n\t}\n\treturn result, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/invertifcondition.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// invertIfCondition is a singleFileFixFunc that inverts an if/else statement\nfunc invertIfCondition(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tvar (\n\t\tfset = pkg.FileSet()\n\t\tsrc  = pgf.Src\n\t)\n\n\tifStatement, _, err := canInvertIfCondition(pgf.Cursor(), start, end)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar replaceElse analysis.TextEdit\n\n\tendsWithReturn, err := endsWithReturn(ifStatement.Else)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif endsWithReturn {\n\t\t// Replace the whole else part with an empty line and an unindented\n\t\t// version of the original if body\n\t\tsourcePos := safetoken.StartPosition(fset, ifStatement.Pos())\n\n\t\tindent := max(sourcePos.Column-1, 0)\n\n\t\tstandaloneBodyText := ifBodyToStandaloneCode(fset, ifStatement.Body, src)\n\t\treplaceElse = analysis.TextEdit{\n\t\t\tPos:     ifStatement.Body.Rbrace + 1, // 1 == len(\"}\")\n\t\t\tEnd:     ifStatement.End(),\n\t\t\tNewText: []byte(\"\\n\\n\" + strings.Repeat(\"\\t\", indent) + standaloneBodyText),\n\t\t}\n\t} else {\n\t\t// Replace the else body text with the if body text\n\t\tbodyStart := safetoken.StartPosition(fset, ifStatement.Body.Lbrace)\n\t\tbodyEnd := safetoken.EndPosition(fset, ifStatement.Body.Rbrace+1) // 1 == len(\"}\")\n\t\tbodyText := src[bodyStart.Offset:bodyEnd.Offset]\n\t\treplaceElse = analysis.TextEdit{\n\t\t\tPos:     ifStatement.Else.Pos(),\n\t\t\tEnd:     ifStatement.Else.End(),\n\t\t\tNewText: bodyText,\n\t\t}\n\t}\n\n\t// Replace the if text with the else text\n\telsePosInSource := safetoken.StartPosition(fset, ifStatement.Else.Pos())\n\telseEndInSource := safetoken.EndPosition(fset, ifStatement.Else.End())\n\telseText := src[elsePosInSource.Offset:elseEndInSource.Offset]\n\treplaceBodyWithElse := analysis.TextEdit{\n\t\tPos:     ifStatement.Body.Pos(),\n\t\tEnd:     ifStatement.Body.End(),\n\t\tNewText: elseText,\n\t}\n\n\t// Replace the if condition with its inverse\n\tinverseCondition, err := invertCondition(fset, ifStatement.Cond, src)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treplaceConditionWithInverse := analysis.TextEdit{\n\t\tPos:     ifStatement.Cond.Pos(),\n\t\tEnd:     ifStatement.Cond.End(),\n\t\tNewText: inverseCondition,\n\t}\n\n\t// Return a SuggestedFix with just that TextEdit in there\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: []analysis.TextEdit{\n\t\t\treplaceConditionWithInverse,\n\t\t\treplaceBodyWithElse,\n\t\t\treplaceElse,\n\t\t},\n\t}, nil\n}\n\nfunc endsWithReturn(elseBranch ast.Stmt) (bool, error) {\n\telseBlock, isBlockStatement := elseBranch.(*ast.BlockStmt)\n\tif !isBlockStatement {\n\t\treturn false, fmt.Errorf(\"unable to figure out whether this ends with return: %T\", elseBranch)\n\t}\n\n\tif len(elseBlock.List) == 0 {\n\t\t// Empty blocks don't end in returns\n\t\treturn false, nil\n\t}\n\n\tlastStatement := elseBlock.List[len(elseBlock.List)-1]\n\n\t_, lastStatementIsReturn := lastStatement.(*ast.ReturnStmt)\n\treturn lastStatementIsReturn, nil\n}\n\n// Turn { fmt.Println(\"Hello\") } into just fmt.Println(\"Hello\"), with one less\n// level of indentation.\n//\n// The first line of the result will not be indented, but all of the following\n// lines will.\nfunc ifBodyToStandaloneCode(fset *token.FileSet, ifBody *ast.BlockStmt, src []byte) string {\n\t// Get the whole body (without the surrounding braces) as a string\n\tbodyStart := safetoken.StartPosition(fset, ifBody.Lbrace+1) // 1 == len(\"}\")\n\tbodyEnd := safetoken.EndPosition(fset, ifBody.Rbrace)\n\tbodyWithoutBraces := string(src[bodyStart.Offset:bodyEnd.Offset])\n\tbodyWithoutBraces = strings.TrimSpace(bodyWithoutBraces)\n\n\t// Unindent\n\tbodyWithoutBraces = strings.ReplaceAll(bodyWithoutBraces, \"\\n\\t\", \"\\n\")\n\n\treturn bodyWithoutBraces\n}\n\nfunc invertCondition(fset *token.FileSet, cond ast.Expr, src []byte) ([]byte, error) {\n\tcondStart := safetoken.StartPosition(fset, cond.Pos())\n\tcondEnd := safetoken.EndPosition(fset, cond.End())\n\toldText := string(src[condStart.Offset:condEnd.Offset])\n\n\tswitch expr := cond.(type) {\n\tcase *ast.Ident, *ast.ParenExpr, *ast.CallExpr, *ast.StarExpr, *ast.IndexExpr, *ast.IndexListExpr, *ast.SelectorExpr:\n\t\tnewText := \"!\" + oldText\n\t\tif oldText == \"true\" {\n\t\t\tnewText = \"false\"\n\t\t} else if oldText == \"false\" {\n\t\t\tnewText = \"true\"\n\t\t}\n\n\t\treturn []byte(newText), nil\n\n\tcase *ast.UnaryExpr:\n\t\tif expr.Op != token.NOT {\n\t\t\t// This should never happen\n\t\t\treturn dumbInvert(fset, cond, src), nil\n\t\t}\n\n\t\tinverse := expr.X\n\t\tif p, isParen := inverse.(*ast.ParenExpr); isParen {\n\t\t\t// We got !(x), remove the parentheses with the ! so we get just \"x\"\n\t\t\tinverse = p.X\n\n\t\t\tstart := safetoken.StartPosition(fset, inverse.Pos())\n\t\t\tend := safetoken.EndPosition(fset, inverse.End())\n\t\t\tif start.Line != end.Line {\n\t\t\t\t// The expression is multi-line, so we can't remove the parentheses\n\t\t\t\tinverse = expr.X\n\t\t\t}\n\t\t}\n\n\t\tstart := safetoken.StartPosition(fset, inverse.Pos())\n\t\tend := safetoken.EndPosition(fset, inverse.End())\n\t\ttextWithoutNot := src[start.Offset:end.Offset]\n\n\t\treturn textWithoutNot, nil\n\n\tcase *ast.BinaryExpr:\n\t\t// These inversions are unsound for floating point NaN, but that's ok.\n\t\tnegations := map[token.Token]string{\n\t\t\ttoken.EQL: \"!=\",\n\t\t\ttoken.LSS: \">=\",\n\t\t\ttoken.GTR: \"<=\",\n\t\t\ttoken.NEQ: \"==\",\n\t\t\ttoken.LEQ: \">\",\n\t\t\ttoken.GEQ: \"<\",\n\t\t}\n\n\t\tnegation, negationFound := negations[expr.Op]\n\t\tif !negationFound {\n\t\t\treturn invertAndOr(fset, expr, src)\n\t\t}\n\n\t\txPosInSource := safetoken.StartPosition(fset, expr.X.Pos())\n\t\topPosInSource := safetoken.StartPosition(fset, expr.OpPos)\n\t\tyPosInSource := safetoken.StartPosition(fset, expr.Y.Pos())\n\n\t\ttextBeforeOp := string(src[xPosInSource.Offset:opPosInSource.Offset])\n\n\t\toldOpWithTrailingWhitespace := string(src[opPosInSource.Offset:yPosInSource.Offset])\n\t\tnewOpWithTrailingWhitespace := negation + oldOpWithTrailingWhitespace[len(expr.Op.String()):]\n\n\t\ttextAfterOp := string(src[yPosInSource.Offset:condEnd.Offset])\n\n\t\treturn []byte(textBeforeOp + newOpWithTrailingWhitespace + textAfterOp), nil\n\t}\n\n\treturn dumbInvert(fset, cond, src), nil\n}\n\n// dumbInvert is a fallback, inverting cond into !(cond).\nfunc dumbInvert(fset *token.FileSet, expr ast.Expr, src []byte) []byte {\n\tstart := safetoken.StartPosition(fset, expr.Pos())\n\tend := safetoken.EndPosition(fset, expr.End())\n\ttext := string(src[start.Offset:end.Offset])\n\treturn []byte(\"!(\" + text + \")\")\n}\n\nfunc invertAndOr(fset *token.FileSet, expr *ast.BinaryExpr, src []byte) ([]byte, error) {\n\tif expr.Op != token.LAND && expr.Op != token.LOR {\n\t\t// Neither AND nor OR, don't know how to invert this\n\t\treturn dumbInvert(fset, expr, src), nil\n\t}\n\n\toppositeOp := \"&&\"\n\tif expr.Op == token.LAND {\n\t\toppositeOp = \"||\"\n\t}\n\n\txEndInSource := safetoken.EndPosition(fset, expr.X.End())\n\topPosInSource := safetoken.StartPosition(fset, expr.OpPos)\n\twhitespaceAfterBefore := src[xEndInSource.Offset:opPosInSource.Offset]\n\n\tinvertedBefore, err := invertCondition(fset, expr.X, src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinvertedAfter, err := invertCondition(fset, expr.Y, src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tyPosInSource := safetoken.StartPosition(fset, expr.Y.Pos())\n\n\toldOpWithTrailingWhitespace := string(src[opPosInSource.Offset:yPosInSource.Offset])\n\tnewOpWithTrailingWhitespace := oppositeOp + oldOpWithTrailingWhitespace[len(expr.Op.String()):]\n\n\treturn []byte(string(invertedBefore) + string(whitespaceAfterBefore) + newOpWithTrailingWhitespace + string(invertedAfter)), nil\n}\n\n// canInvertIfCondition reports whether we can do invert-if-condition on the\n// code in the given range.\nfunc canInvertIfCondition(curFile inspector.Cursor, start, end token.Pos) (*ast.IfStmt, bool, error) {\n\tcurIf, _ := curFile.FindByPos(start, end)\n\tstmt, _ := cursorutil.FirstEnclosing[*ast.IfStmt](curIf)\n\tif stmt == nil {\n\t\treturn nil, false, fmt.Errorf(\"not an if statement\")\n\t}\n\tif stmt.Else == nil {\n\t\t// Can't invert conditions without else clauses\n\t\treturn nil, false, fmt.Errorf(\"else clause required\")\n\t}\n\n\tif _, hasElseIf := stmt.Else.(*ast.IfStmt); hasElseIf {\n\t\t// Can't invert conditions with else-if clauses, unclear what that\n\t\t// would look like\n\t\treturn nil, false, fmt.Errorf(\"else-if not supported\")\n\t}\n\n\treturn stmt, true, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/known_packages.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/imports\"\n)\n\n// KnownPackagePaths returns a new list of package paths of all known\n// packages in the package graph that could potentially be imported by\n// the given file. The list is ordered lexicographically, except that\n// all dot-free paths (standard packages) appear before dotful ones.\n//\n// It is part of the gopls.list_known_packages command.\nfunc KnownPackagePaths(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]PackagePath, error) {\n\t// This algorithm is expressed in terms of Metadata, not Packages,\n\t// so it doesn't cause or wait for type checking.\n\n\tcurrent, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI())\n\tif err != nil {\n\t\treturn nil, err // e.g. context cancelled\n\t}\n\n\t// Parse the file's imports so we can compute which\n\t// PackagePaths are imported by this specific file.\n\tsrc, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfile, err := parser.ParseFile(token.NewFileSet(), fh.URI().Path(), src, parser.ImportsOnly)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\timported := make(map[PackagePath]bool)\n\tfor _, imp := range file.Imports {\n\t\tif id := current.DepsByImpPath[metadata.UnquoteImportPath(imp)]; id != \"\" {\n\t\t\tif mp := snapshot.Metadata(id); mp != nil {\n\t\t\t\timported[mp.PkgPath] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Now find candidates among all known packages.\n\tknownPkgs, err := snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tseen := make(map[PackagePath]bool)\n\tfor _, knownPkg := range knownPkgs {\n\t\t// package main cannot be imported\n\t\tif knownPkg.Name == \"main\" {\n\t\t\tcontinue\n\t\t}\n\t\t// test packages cannot be imported\n\t\tif knownPkg.ForTest != \"\" {\n\t\t\tcontinue\n\t\t}\n\t\t// No need to import what the file already imports.\n\t\t// This check is based on PackagePath, not PackageID,\n\t\t// so that all test variants are filtered out too.\n\t\tif imported[knownPkg.PkgPath] {\n\t\t\tcontinue\n\t\t}\n\t\t// make sure internal packages are importable by the file\n\t\tif !metadata.IsValidImport(current.PkgPath, knownPkg.PkgPath, snapshot.View().Type() != cache.GoPackagesDriverView) {\n\t\t\tcontinue\n\t\t}\n\t\t// naive check on cyclical imports\n\t\tif isDirectlyCyclical(current, knownPkg) {\n\t\t\tcontinue\n\t\t}\n\t\t// AllMetadata may have multiple variants of a pkg.\n\t\tseen[knownPkg.PkgPath] = true\n\t}\n\n\t// Augment the set by invoking the goimports algorithm.\n\tif err := snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, o *imports.Options) error {\n\t\tctx, cancel := context.WithTimeout(ctx, time.Millisecond*80)\n\t\tdefer cancel()\n\t\tvar seenMu sync.Mutex\n\t\twrapped := func(ifix imports.ImportFix) {\n\t\t\tseenMu.Lock()\n\t\t\tdefer seenMu.Unlock()\n\t\t\t// TODO(adonovan): what if the actual package path has a vendor/ prefix?\n\t\t\tseen[PackagePath(ifix.StmtInfo.ImportPath)] = true\n\t\t}\n\t\treturn imports.GetAllCandidates(ctx, wrapped, \"\", fh.URI().Path(), string(current.Name), o.Env)\n\t}); err != nil {\n\t\t// If goimports failed, proceed with just the candidates from the metadata.\n\t\tevent.Error(ctx, \"imports.GetAllCandidates\", err)\n\t}\n\n\t// Sort lexicographically, but with std before non-std packages.\n\tpaths := make([]PackagePath, 0, len(seen))\n\tfor path := range seen {\n\t\tpaths = append(paths, path)\n\t}\n\tsort.Slice(paths, func(i, j int) bool {\n\t\timportI, importJ := paths[i], paths[j]\n\t\tiHasDot := strings.Contains(string(importI), \".\")\n\t\tjHasDot := strings.Contains(string(importJ), \".\")\n\t\tif iHasDot != jHasDot {\n\t\t\treturn jHasDot // dot-free paths (standard packages) compare less\n\t\t}\n\t\treturn importI < importJ\n\t})\n\n\treturn paths, nil\n}\n\n// isDirectlyCyclical checks if imported directly imports pkg.\n// It does not (yet) offer a full cyclical check because showing a user\n// a list of importable packages already generates a very large list\n// and having a few false positives in there could be worth the\n// performance snappiness.\n//\n// TODO(adonovan): ensure that metadata graph is always cyclic!\n// Many algorithms will get confused or even stuck in the\n// presence of cycles. Then replace this function by 'false'.\nfunc isDirectlyCyclical(pkg, imported *metadata.Package) bool {\n\t_, ok := imported.DepsByPkgPath[pkg.PkgPath]\n\treturn ok\n}\n"
  },
  {
    "path": "gopls/internal/golang/lines.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines refactorings for splitting lists of elements\n// (arguments, literals, etc) across multiple lines, and joining\n// them into a single line.\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// canSplitLines checks whether we can split lists of elements inside\n// an enclosing curly bracket/parens into separate lines.\nfunc canSplitLines(curFile inspector.Cursor, fset *token.FileSet, start, end token.Pos) (string, bool, error) {\n\titemType, items, comments, _, _, _ := findSplitJoinTarget(fset, curFile, nil, start, end)\n\tif itemType == \"\" {\n\t\treturn \"\", false, nil\n\t}\n\n\tif !canSplitJoinLines(items, comments) {\n\t\treturn \"\", false, nil\n\t}\n\n\tfor i := 1; i < len(items); i++ {\n\t\tprevLine := safetoken.EndPosition(fset, items[i-1].End()).Line\n\t\tcurLine := safetoken.StartPosition(fset, items[i].Pos()).Line\n\t\tif prevLine == curLine {\n\t\t\treturn \"Split \" + itemType + \" into separate lines\", true, nil\n\t\t}\n\t}\n\n\treturn \"\", false, nil\n}\n\n// canJoinLines checks whether we can join lists of elements inside an\n// enclosing curly bracket/parens into a single line.\nfunc canJoinLines(curFile inspector.Cursor, fset *token.FileSet, start, end token.Pos) (string, bool, error) {\n\titemType, items, comments, _, _, _ := findSplitJoinTarget(fset, curFile, nil, start, end)\n\tif itemType == \"\" {\n\t\treturn \"\", false, nil\n\t}\n\n\tif !canSplitJoinLines(items, comments) {\n\t\treturn \"\", false, nil\n\t}\n\n\tfor i := 1; i < len(items); i++ {\n\t\tprevLine := safetoken.EndPosition(fset, items[i-1].End()).Line\n\t\tcurLine := safetoken.StartPosition(fset, items[i].Pos()).Line\n\t\tif prevLine != curLine {\n\t\t\treturn \"Join \" + itemType + \" into one line\", true, nil\n\t\t}\n\t}\n\n\treturn \"\", false, nil\n}\n\n// canSplitJoinLines determines whether we should split/join the lines or not.\nfunc canSplitJoinLines(items []ast.Node, comments []*ast.CommentGroup) bool {\n\tif len(items) <= 1 {\n\t\treturn false\n\t}\n\n\tfor _, cg := range comments {\n\t\tif !strings.HasPrefix(cg.List[0].Text, \"/*\") {\n\t\t\treturn false // can't split/join lists containing \"//\" comments\n\t\t}\n\t}\n\n\treturn true\n}\n\n// splitLines is a singleFile fixer.\nfunc splitLines(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tfset := pkg.FileSet()\n\titemType, items, comments, indent, braceOpen, braceClose := findSplitJoinTarget(fset, pgf.Cursor(), pgf.Src, start, end)\n\tif itemType == \"\" {\n\t\treturn nil, nil, nil // no fix available\n\t}\n\n\treturn fset, processLines(fset, items, comments, pgf.Src, braceOpen, braceClose, \",\\n\", \"\\n\", \",\\n\"+indent, indent+\"\\t\"), nil\n}\n\n// joinLines is a singleFile fixer.\nfunc joinLines(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tfset := pkg.FileSet()\n\titemType, items, comments, _, braceOpen, braceClose := findSplitJoinTarget(fset, pgf.Cursor(), pgf.Src, start, end)\n\tif itemType == \"\" {\n\t\treturn nil, nil, nil // no fix available\n\t}\n\n\treturn fset, processLines(fset, items, comments, pgf.Src, braceOpen, braceClose, \", \", \"\", \"\", \"\"), nil\n}\n\n// processLines is the common operation for both split and join lines because this split/join operation is\n// essentially a transformation of the separating whitespace.\nfunc processLines(fset *token.FileSet, items []ast.Node, comments []*ast.CommentGroup, src []byte, braceOpen, braceClose token.Pos, sep, prefix, suffix, indent string) *analysis.SuggestedFix {\n\tnodes := slices.Clone(items)\n\n\t// box *ast.CommentGroup to ast.Node for easier processing later.\n\tfor _, cg := range comments {\n\t\tnodes = append(nodes, cg)\n\t}\n\n\t// Sort to interleave comments and nodes.\n\tsort.Slice(nodes, func(i, j int) bool {\n\t\treturn nodes[i].Pos() < nodes[j].Pos()\n\t})\n\n\tedits := []analysis.TextEdit{\n\t\t{\n\t\t\tPos:     token.Pos(int(braceOpen) + len(\"{\")),\n\t\t\tEnd:     nodes[0].Pos(),\n\t\t\tNewText: []byte(prefix + indent),\n\t\t},\n\t\t{\n\t\t\tPos:     nodes[len(nodes)-1].End(),\n\t\t\tEnd:     braceClose,\n\t\t\tNewText: []byte(suffix),\n\t\t},\n\t}\n\n\tfor i := 1; i < len(nodes); i++ {\n\t\tpos, end := nodes[i-1].End(), nodes[i].Pos()\n\t\tif pos > end {\n\t\t\t// this will happen if we have a /*-style comment inside of a Field\n\t\t\t// e.g. `a /*comment here */ int`\n\t\t\t//\n\t\t\t// we will ignore as we only care about finding the field delimiter.\n\t\t\tcontinue\n\t\t}\n\n\t\t// at this point, the `,` token in between 2 nodes here must be the field delimiter.\n\t\tposOffset := safetoken.EndPosition(fset, pos).Offset\n\t\tendOffset := safetoken.StartPosition(fset, end).Offset\n\t\tif bytes.IndexByte(src[posOffset:endOffset], ',') == -1 {\n\t\t\t// nodes[i] or nodes[i-1] is a comment hence no delimiter in between\n\t\t\t// in such case, do nothing.\n\t\t\tcontinue\n\t\t}\n\n\t\tedits = append(edits, analysis.TextEdit{Pos: pos, End: end, NewText: []byte(sep + indent)})\n\n\t\t// Print the Ellipsis if we synthesized one earlier.\n\t\tif is[*ast.Ellipsis](nodes[i]) {\n\t\t\tedits = append(edits, analysis.TextEdit{\n\t\t\t\tPos:     nodes[i].End(),\n\t\t\t\tEnd:     nodes[i].End(),\n\t\t\t\tNewText: []byte(\"...\"),\n\t\t\t})\n\t\t}\n\t}\n\n\treturn &analysis.SuggestedFix{TextEdits: edits}\n}\n\n// findSplitJoinTarget returns the first curly bracket/parens that encloses the current cursor.\nfunc findSplitJoinTarget(fset *token.FileSet, curFile inspector.Cursor, src []byte, start, end token.Pos) (itemType string, items []ast.Node, comments []*ast.CommentGroup, indent string, open, close token.Pos) {\n\n\tfindTarget := func() (targetType string, target ast.Node, open, close token.Pos) {\n\t\tcur, _ := curFile.FindByPos(start, end)\n\t\tfor cur := range cur.Enclosing() {\n\t\t\t// TODO: do cur = enclosingUnparen(cur) first, once CL 701035 lands.\n\t\t\tswitch cur.ParentEdgeKind() {\n\t\t\t// params or results of func signature\n\t\t\t// Note:\n\t\t\t// - each ast.Field (e.g. \"x, y, z int\") is considered a single item.\n\t\t\t// - splitting Params and Results lists is not usually good style.\n\t\t\tcase edge.FuncType_Params:\n\t\t\t\tp := cur.Node().(*ast.FieldList)\n\t\t\t\treturn \"parameters\", p, p.Opening, p.Closing\n\t\t\tcase edge.FuncType_Results:\n\t\t\t\tr := cur.Node().(*ast.FieldList)\n\t\t\t\tif !r.Opening.IsValid() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn \"results\", r, r.Opening, r.Closing\n\t\t\tcase edge.CallExpr_Args: // f(a, b, c)\n\t\t\t\tnode := cur.Parent().Node().(*ast.CallExpr)\n\t\t\t\treturn \"arguments\", node, node.Lparen, node.Rparen\n\t\t\tcase edge.CompositeLit_Elts: // T{a, b, c}\n\t\t\t\tnode := cur.Parent().Node().(*ast.CompositeLit)\n\t\t\t\treturn \"elements\", node, node.Lbrace, node.Rbrace\n\t\t\t}\n\t\t}\n\t\treturn \"\", nil, 0, 0\n\t}\n\n\ttargetType, targetNode, open, close := findTarget()\n\tif targetType == \"\" {\n\t\treturn \"\", nil, nil, \"\", 0, 0\n\t}\n\n\tswitch node := targetNode.(type) {\n\tcase *ast.FieldList:\n\t\tfor _, field := range node.List {\n\t\t\titems = append(items, field)\n\t\t}\n\tcase *ast.CallExpr:\n\t\tfor _, arg := range node.Args {\n\t\t\titems = append(items, arg)\n\t\t}\n\n\t\t// Preserve \"...\" by wrapping the last\n\t\t// argument in an Ellipsis node\n\t\t// with the same Pos/End as the argument.\n\t\t// See corresponding logic in processLines.\n\t\tif node.Ellipsis.IsValid() {\n\t\t\tlast := &items[len(items)-1]\n\t\t\t*last = &ast.Ellipsis{\n\t\t\t\tEllipsis: (*last).Pos(),      // determines Ellipsis.Pos()\n\t\t\t\tElt:      (*last).(ast.Expr), // determines Ellipsis.End()\n\t\t\t}\n\t\t}\n\tcase *ast.CompositeLit:\n\t\tfor _, arg := range node.Elts {\n\t\t\titems = append(items, arg)\n\t\t}\n\t}\n\n\t// preserve comments separately as it's not part of the targetNode AST.\n\tfile := curFile.Node().(*ast.File)\n\tfor _, cg := range file.Comments {\n\t\tif open <= cg.Pos() && cg.Pos() < close {\n\t\t\tcomments = append(comments, cg)\n\t\t}\n\t}\n\n\t// indent is the leading whitespace before the opening curly bracket/paren.\n\t//\n\t// in case where we don't have access to src yet i.e. src == nil\n\t// it's fine to return incorrect indent because we don't need it yet.\n\tindent = \"\"\n\tif len(src) > 0 {\n\t\tvar pos token.Pos\n\t\tswitch node := targetNode.(type) {\n\t\tcase *ast.FieldList:\n\t\t\tpos = node.Opening\n\t\tcase *ast.CallExpr:\n\t\t\tpos = node.Lparen\n\t\tcase *ast.CompositeLit:\n\t\t\tpos = node.Lbrace\n\t\t}\n\n\t\tsplit := bytes.Split(src, []byte(\"\\n\"))\n\t\ttargetLineNumber := safetoken.StartPosition(fset, pos).Line\n\t\tfirstLine := string(split[targetLineNumber-1])\n\t\ttrimmed := strings.TrimSpace(string(firstLine))\n\t\tindent = firstLine[:strings.Index(firstLine, trimmed)]\n\t}\n\n\treturn targetType, items, comments, indent, open, close\n}\n"
  },
  {
    "path": "gopls/internal/golang/linkname.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// ErrNoLinkname is returned by LinknameDefinition when no linkname\n// directive is found at a particular position.\n// As such it indicates that other definitions could be worth checking.\nvar ErrNoLinkname = errors.New(\"no linkname directive found\")\n\n// linknameDefinition finds the definition of the linkname directive in m at pos.\n// If there is no linkname directive at pos, returns ErrNoLinkname.\nfunc linknameDefinition(ctx context.Context, snapshot *cache.Snapshot, m *protocol.Mapper, from protocol.Range) ([]protocol.Location, error) {\n\tpkgPath, name, _ := parseLinkname(m, from)\n\tif pkgPath == \"\" {\n\t\treturn nil, ErrNoLinkname\n\t}\n\n\t_, pgf, pos, err := findLinkname(ctx, snapshot, PackagePath(pkgPath), name)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"find linkname: %w\", err)\n\t}\n\tloc, err := pgf.PosLocation(pos, pos+token.Pos(len(name)))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"location of linkname: %w\", err)\n\t}\n\treturn []protocol.Location{loc}, nil\n}\n\n// parseLinkname attempts to parse a go:linkname declaration at the given range.\n// If successful, it returns\n// - package path referenced\n// - object name referenced\n// - byte offset in mapped file of the start of the link target\n// of the linkname directives 2nd argument.\n//\n// If the range is not in the second argument of a go:linkname directive, or\n// parsing fails, it returns \"\", \"\", 0.\nfunc parseLinkname(m *protocol.Mapper, rng protocol.Range) (pkgPath, name string, targetOffset int) {\n\tif rng.Start.Line != rng.End.Line {\n\t\treturn \"\", \"\", 0\n\t}\n\n\tlineStart, err := m.PositionOffset(protocol.Position{Line: rng.Start.Line, Character: 0})\n\tif err != nil {\n\t\treturn \"\", \"\", 0\n\t}\n\tlineEnd, err := m.PositionOffset(protocol.Position{Line: rng.Start.Line + 1, Character: 0})\n\tif err != nil {\n\t\treturn \"\", \"\", 0\n\t}\n\n\tdirective := string(m.Content[lineStart:lineEnd])\n\t// (Assumes no leading spaces.)\n\tif !strings.HasPrefix(directive, \"//go:linkname\") {\n\t\treturn \"\", \"\", 0\n\t}\n\t// Sometimes source code (typically tests) has another\n\t// comment after the directive, trim that away.\n\tif i := strings.LastIndex(directive, \"//\"); i != 0 {\n\t\tdirective = strings.TrimSpace(directive[:i])\n\t}\n\n\t// Looking for pkgpath in '//go:linkname f pkgpath.g'.\n\t// (We ignore 1-arg linkname directives.)\n\tparts := strings.Fields(directive)\n\tif len(parts) != 3 {\n\t\treturn \"\", \"\", 0\n\t}\n\n\t// Inside 2nd arg [start, end]?\n\t// (Assumes no trailing spaces.)\n\tstartOffset, endOffset, err := m.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn \"\", \"\", 0\n\t}\n\tend := lineStart + len(directive)\n\tstart := end - len(parts[2])\n\tif !(start <= startOffset && endOffset <= end) {\n\t\treturn \"\", \"\", 0\n\t}\n\tlinkname := parts[2]\n\n\t// Split the pkg path from the name.\n\tdot := strings.LastIndexByte(linkname, '.')\n\tif dot < 0 {\n\t\treturn \"\", \"\", 0\n\t}\n\n\treturn linkname[:dot], linkname[dot+1:], start\n}\n\n// findLinkname searches dependencies of packages containing fh for an object\n// with linker name matching the given package path and name.\nfunc findLinkname(ctx context.Context, snapshot *cache.Snapshot, pkgPath PackagePath, name string) (*cache.Package, *parsego.File, token.Pos, error) {\n\t// Typically the linkname refers to a forward dependency\n\t// or a reverse dependency, but in general it may refer\n\t// to any package that is linked with this one.\n\tvar pkgMeta *metadata.Package\n\tmetas, err := snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, nil, token.NoPos, err\n\t}\n\tmetadata.RemoveIntermediateTestVariants(&metas)\n\tfor _, meta := range metas {\n\t\tif meta.PkgPath == pkgPath {\n\t\t\tpkgMeta = meta\n\t\t\tbreak\n\t\t}\n\t}\n\tif pkgMeta == nil {\n\t\treturn nil, nil, token.NoPos, fmt.Errorf(\"cannot find package %q\", pkgPath)\n\t}\n\n\t// When found, type check the desired package (snapshot.TypeCheck in TypecheckFull mode),\n\tpkgs, err := snapshot.TypeCheck(ctx, pkgMeta.ID)\n\tif err != nil {\n\t\treturn nil, nil, token.NoPos, err\n\t}\n\tpkg := pkgs[0]\n\n\tobj := pkg.Types().Scope().Lookup(name)\n\tif obj == nil {\n\t\treturn nil, nil, token.NoPos, fmt.Errorf(\"package %q does not define %s\", pkgPath, name)\n\t}\n\n\tpos := obj.Pos()\n\tpgf, err := pkg.FileEnclosing(pos)\n\treturn pkg, pgf, pos, err\n}\n"
  },
  {
    "path": "gopls/internal/golang/modify_tags.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\n\t\"github.com/fatih/gomodifytags/modifytags\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\tinternalastutil \"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// ModifyTags applies the given struct tag modifications to the specified struct.\nfunc ModifyTags(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, args command.ModifyTagsArgs, m *modifytags.Modification) ([]protocol.DocumentChange, error) {\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error fetching package file: %v\", err)\n\t}\n\tstart, end, err := pgf.RangePos(args.Range)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting position information: %v\", err)\n\t}\n\t// If the cursor is at a point and not a selection, we should use the entire enclosing struct.\n\tif start == end {\n\t\tcur, ok := pgf.Cursor().FindByPos(start, end)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"error finding start and end positions: %v\", err)\n\t\t}\n\t\tstructnode, _ := cursorutil.FirstEnclosing[*ast.StructType](cur)\n\t\tif structnode == nil {\n\t\t\treturn nil, fmt.Errorf(\"no enclosing struct type\")\n\t\t}\n\t\tstart, end = structnode.Pos(), structnode.End()\n\t}\n\n\t// Create a copy of the file node in order to avoid race conditions when we modify the node in Apply.\n\tcloned := internalastutil.CloneNode(pgf.File)\n\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\n\tif err = m.Apply(fset, cloned, start, end); err != nil {\n\t\treturn nil, fmt.Errorf(\"could not modify tags: %v\", err)\n\t}\n\n\t// Construct a list of DocumentChanges based on the diff between the formatted node and the\n\t// original file content.\n\tvar after bytes.Buffer\n\tif err := format.Node(&after, fset, cloned); err != nil {\n\t\treturn nil, err\n\t}\n\tedits := diff.Bytes(pgf.Src, after.Bytes())\n\tif len(edits) == 0 {\n\t\treturn nil, nil\n\t}\n\ttextedits, err := protocol.EditsFromDiffEdits(pgf.Mapper, edits)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error computing edits for %s: %v\", args.URI, err)\n\t}\n\treturn []protocol.DocumentChange{\n\t\tprotocol.DocumentChangeEdit(fh, textedits),\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/movetype.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/moreiters\"\n)\n\n// MoveType moves the selected type declaration into a new package and updates all references.\nfunc MoveType(ctx context.Context, fh file.Handle, snapshot *cache.Snapshot, loc protocol.Location, newPkgDir string) ([]protocol.DocumentChange, error) {\n\treturn nil, fmt.Errorf(\"MoveType: not yet supported\")\n}\n\n// selectionContainsType returns the Cursor, GenDecl and TypeSpec of the type\n// declaration that encloses cursor if one exists. Otherwise it returns false.\nfunc selectionContainsType(cursor inspector.Cursor) (inspector.Cursor, *ast.GenDecl, *ast.TypeSpec, string, bool) {\n\tdeclCur, ok := moreiters.First(cursor.Enclosing((*ast.GenDecl)(nil)))\n\tif !ok {\n\t\treturn inspector.Cursor{}, &ast.GenDecl{}, &ast.TypeSpec{}, \"\", false\n\t}\n\n\t// Verify that we have a type declaration (e.g. not an import declaration).\n\tdeclNode := declCur.Node().(*ast.GenDecl)\n\tif declNode.Tok != token.TYPE {\n\t\treturn inspector.Cursor{}, &ast.GenDecl{}, &ast.TypeSpec{}, \"\", false\n\t}\n\n\ttypSpec, ok := declNode.Specs[0].(*ast.TypeSpec)\n\tif !ok {\n\t\treturn inspector.Cursor{}, &ast.GenDecl{}, &ast.TypeSpec{}, \"\", false\n\t}\n\n\treturn declCur, declNode, declNode.Specs[0].(*ast.TypeSpec), typSpec.Name.Name, true\n}\n"
  },
  {
    "path": "gopls/internal/golang/origin.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport \"go/types\"\n\n// containsOrigin reports whether the provided object set contains an object\n// with the same origin as the provided obj (which may be a synthetic object\n// created during instantiation).\nfunc containsOrigin(objSet map[types.Object]bool, obj types.Object) bool {\n\tobjOrigin := origin(obj)\n\tfor target := range objSet {\n\t\tif origin(target) == objOrigin {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc origin(obj types.Object) types.Object {\n\tswitch obj := obj.(type) {\n\tcase *types.Var:\n\t\treturn obj.Origin()\n\tcase *types.Func:\n\t\treturn obj.Origin()\n\t}\n\treturn obj\n}\n"
  },
  {
    "path": "gopls/internal/golang/pkgdoc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines a simple HTML rendering of package documentation\n// in imitation of the style of pkg.go.dev.\n//\n// The current implementation is just a starting point and a\n// placeholder for a more sophisticated one.\n//\n// TODO(adonovan):\n// - rewrite using html/template.\n//   Or factor with golang.org/x/pkgsite/internal/godoc/dochtml.\n// - emit breadcrumbs for parent + sibling packages.\n// - list promoted methods---we have type information! (golang/go#67158)\n// - gather Example tests, following go/doc and pkgsite.\n// - add option for doc.AllDecls: show non-exported symbols too.\n// - style the <li> bullets in the index as invisible.\n// - add push notifications such as didChange -> reload.\n// - there appears to be a maximum file size beyond which the\n//   \"source.doc\" code action is not offered. Remove that.\n// - modify JS httpGET function to give a transient visual indication\n//   when clicking a source link that the editor is being navigated\n//   (in case it doesn't raise itself, like VS Code).\n// - move this into a new package, golang/web, and then\n//   split out the various helpers without fear of polluting\n//   the golang package namespace?\n// - show \"Deprecated\" chip when appropriate.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/doc\"\n\t\"go/doc/comment\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"html\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// DocFragment finds the package and (optionally) symbol identified by\n// the current selection, and returns the package path and the\n// optional symbol URL fragment (e.g. \"#Buffer.Len\") for a symbol,\n// along with a title for the code action.\n//\n// It is called once to offer the code action, and again when the\n// command is executed. This is slightly inefficient but ensures that\n// the title and package/symbol logic are consistent in all cases.\n//\n// It returns zeroes if there is nothing to see here (e.g. reference to a builtin).\nfunc DocFragment(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (pkgpath PackagePath, fragment, title string) {\n\tthing := thingAtPoint(pkg, pgf, start, end)\n\n\tmakeTitle := func(kind string, imp *types.Package, name string) string {\n\t\ttitle := \"Browse documentation for \" + kind + \" \"\n\t\tif imp != nil && imp != pkg.Types() {\n\t\t\ttitle += imp.Name() + \".\"\n\t\t}\n\t\treturn title + name\n\t}\n\n\twholePackage := func(pkg *types.Package) (PackagePath, string, string) {\n\t\t// External test packages don't have /pkg doc pages,\n\t\t// so instead show the doc for the package under test.\n\t\t// (This named-based heuristic is imperfect.)\n\t\tif forTest, ok := strings.CutSuffix(pkg.Path(), \"_test\"); ok {\n\t\t\treturn PackagePath(forTest), \"\", makeTitle(\"package\", nil, filepath.Base(forTest))\n\t\t}\n\n\t\treturn PackagePath(pkg.Path()), \"\", makeTitle(\"package\", nil, pkg.Name())\n\t}\n\n\t// Conceptually, we check cases in the order:\n\t// 1. symbol\n\t// 2. package\n\t// 3. enclosing\n\t// but the logic of cases 1 and 3 are identical, hence the odd factoring.\n\n\t// Imported package?\n\tif thing.pkg != nil && thing.symbol == nil {\n\t\treturn wholePackage(thing.pkg)\n\t}\n\n\t// Symbol?\n\tvar sym types.Object\n\tif thing.symbol != nil {\n\t\tsym = thing.symbol // reference to a symbol\n\t} else if thing.enclosing != nil {\n\t\tsym = thing.enclosing // selection is within a declaration of a symbol\n\t}\n\tif sym == nil {\n\t\treturn wholePackage(pkg.Types()) // no symbol\n\t}\n\n\t// Built-in (error.Error, append or unsafe).\n\t// TODO(adonovan): handle builtins in /pkg viewer.\n\tif sym.Pkg() == nil {\n\t\treturn \"\", \"\", \"\" // nothing to see here\n\t}\n\tpkgpath = PackagePath(sym.Pkg().Path())\n\n\t// Unexported? Show enclosing type or package.\n\tif !sym.Exported() {\n\t\t// Unexported method of exported type?\n\t\tif fn, ok := sym.(*types.Func); ok {\n\t\t\tif recv := fn.Signature().Recv(); recv != nil {\n\t\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\t\tif named != nil && named.Obj().Exported() {\n\t\t\t\t\tsym = named.Obj()\n\t\t\t\t\tgoto below\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn wholePackage(sym.Pkg())\n\tbelow:\n\t}\n\n\t// Reference to symbol in external test package?\n\t// Short-circuit: see comment in wholePackage.\n\tif strings.HasSuffix(string(pkgpath), \"_test\") {\n\t\treturn wholePackage(pkg.Types())\n\t}\n\n\t// package-level symbol?\n\tif typesinternal.IsPackageLevel(sym) {\n\t\treturn pkgpath, sym.Name(), makeTitle(objectKind(sym), sym.Pkg(), sym.Name())\n\t}\n\n\t// Inv: sym is field or method, or local.\n\tswitch sym := sym.(type) {\n\tcase *types.Func: // => method\n\t\tsig := sym.Signature()\n\t\tisPtr, named := typesinternal.ReceiverNamed(sig.Recv())\n\t\tif named != nil {\n\t\t\tif !named.Obj().Exported() {\n\t\t\t\treturn wholePackage(sym.Pkg()) // exported method of unexported type\n\t\t\t}\n\t\t\tname := fmt.Sprintf(\"(%s%s).%s\",\n\t\t\t\tstrings.Repeat(\"*\", btoi(isPtr)), // for *T\n\t\t\t\tnamed.Obj().Name(),\n\t\t\t\tsym.Name())\n\t\t\tfragment := named.Obj().Name() + \".\" + sym.Name()\n\t\t\treturn pkgpath, fragment, makeTitle(\"method\", sym.Pkg(), name)\n\t\t}\n\n\tcase *types.Var:\n\t\tif sym.IsField() {\n\t\t\t// TODO(adonovan): support fields.\n\t\t\t// The Var symbol doesn't include the struct\n\t\t\t// type, so we need to use the logic from\n\t\t\t// Hover. (This isn't important for\n\t\t\t// DocFragment as fields don't have fragments,\n\t\t\t// but it matters to the grand unification of\n\t\t\t// Hover/Definition/DocFragment.\n\t\t}\n\t}\n\n\t// Field, non-exported method, or local declaration:\n\t// just show current package.\n\treturn wholePackage(pkg.Types())\n}\n\n// thing describes the package or symbol denoted by a selection.\n//\n// TODO(adonovan): Hover, Definition, and References all start by\n// identifying the selected object. Let's achieve a better factoring\n// of the common parts using this structure, including uniform\n// treatment of doc links, linkname, and suchlike.\ntype thing struct {\n\t// At most one of these fields is set.\n\t// (The 'enclosing' field is a fallback for when neither\n\t// of the first two is set.)\n\tsymbol    types.Object   // referenced symbol\n\tpkg       *types.Package // referenced package\n\tenclosing types.Object   // package-level symbol or method decl enclosing selection\n}\n\nfunc thingAtPoint(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) thing {\n\tcur, _, _, _ := astutil.Select(pgf.Cursor(), start, end)\n\n\t// In an import spec?\n\tif spec, _ := cursorutil.FirstEnclosing[*ast.ImportSpec](cur); spec != nil {\n\t\tif pkgname := pkg.TypesInfo().PkgNameOf(spec); pkgname != nil {\n\t\t\treturn thing{pkg: pkgname.Imported()}\n\t\t}\n\t}\n\n\t// Definition or reference to symbol?\n\tvar obj types.Object\n\tif id, ok := cur.Node().(*ast.Ident); ok {\n\t\tobj = pkg.TypesInfo().ObjectOf(id)\n\n\t\t// Treat use to PkgName like ImportSpec.\n\t\tif pkgname, ok := obj.(*types.PkgName); ok {\n\t\t\treturn thing{pkg: pkgname.Imported()}\n\t\t}\n\n\t} else if sel, ok := cur.Node().(*ast.SelectorExpr); ok {\n\t\t// e.g. selection is \"fmt.Println\" or just a portion (\"mt.Prin\")\n\t\tobj = pkg.TypesInfo().Uses[sel.Sel]\n\t}\n\tif obj != nil {\n\t\treturn thing{symbol: obj}\n\t}\n\n\t// Find outermost enclosing declaration.\n\tvar id *ast.Ident\n\tfor cur := range cur.Enclosing((*ast.FuncDecl)(nil), (*ast.ValueSpec)(nil), (*ast.TypeSpec)(nil)) {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.FuncDecl: // function or method\n\t\t\tid = n.Name\n\t\tcase *ast.ValueSpec:\n\t\t\tid = n.Names[0] // var, const: use first name\n\t\tcase *ast.TypeSpec:\n\t\t\tid = n.Name\n\t\t}\n\t}\n\tif obj := pkg.TypesInfo().Defs[id]; obj != nil {\n\t\treturn thing{enclosing: obj}\n\t}\n\n\treturn thing{} // nothing to see here\n}\n\n// Web is an abstraction of gopls' web server.\ntype Web interface {\n\t// PkgURL forms URLs of package or symbol documentation.\n\tPkgURL(viewID string, path PackagePath, fragment string) protocol.URI\n\n\t// SrcURL forms URLs that cause the editor to open a file at a specific position.\n\tSrcURL(filename string, line, col8 int) protocol.URI\n}\n\n// PackageDocHTML formats the package documentation page.\n//\n// The posURL function returns a URL that when visited, has the side\n// effect of causing gopls to direct the client editor to navigate to\n// the specified file/line/column position, in UTF-8 coordinates.\n//\n// TODO(adonovan): this function could use some unit tests; we\n// shouldn't have to use integration tests to cover microdetails of\n// HTML rendering. (It is tempting to abstract this function so that\n// it depends only on FileSet/File/Types/TypeInfo/etc, but we should\n// bend the tests to the production interfaces, not the other way\n// around.)\nfunc PackageDocHTML(viewID string, pkg *cache.Package, web Web) ([]byte, error) {\n\t// We can't use doc.NewFromFiles (even with doc.PreserveAST\n\t// mode) as it calls ast.NewPackage which assumes that each\n\t// ast.File has an ast.Scope and resolves identifiers to\n\t// (deprecated) ast.Objects. (This is golang/go#66290.)\n\t// But doc.New only requires pkg.{Name,Files},\n\t// so we just boil it down.\n\t//\n\t// The only loss is doc.classifyExamples.\n\t// TODO(adonovan): simulate that too.\n\tfileMap := make(map[string]*ast.File)\n\tfor _, f := range pkg.Syntax() {\n\t\tfileMap[pkg.FileSet().File(f.FileStart).Name()] = f\n\t}\n\tastpkg := &ast.Package{\n\t\tName:  pkg.Types().Name(),\n\t\tFiles: fileMap,\n\t}\n\t// PreserveAST mode only half works (golang/go#66449): it still\n\t// mutates ASTs when filtering out non-exported symbols.\n\t// As a workaround, enable AllDecls to suppress filtering,\n\t// and do it ourselves.\n\tmode := doc.PreserveAST | doc.AllDecls\n\tdocpkg := doc.New(astpkg, pkg.Types().Path(), mode)\n\n\t// Discard non-exported symbols.\n\t// TODO(adonovan): do this conditionally, and expose option in UI.\n\tconst showUnexported = false\n\tif !showUnexported {\n\t\tvar (\n\t\t\tunexported   = func(name string) bool { return !token.IsExported(name) }\n\t\t\tfilterValues = func(slice *[]*doc.Value) {\n\t\t\t\tdelValue := func(v *doc.Value) bool {\n\t\t\t\t\tv.Names = slices.DeleteFunc(v.Names, unexported)\n\t\t\t\t\treturn len(v.Names) == 0\n\t\t\t\t}\n\t\t\t\t*slice = slices.DeleteFunc(*slice, delValue)\n\t\t\t}\n\t\t\tfilterFuncs = func(funcs *[]*doc.Func) {\n\t\t\t\t*funcs = slices.DeleteFunc(*funcs, func(v *doc.Func) bool {\n\t\t\t\t\treturn unexported(v.Name)\n\t\t\t\t})\n\t\t\t}\n\t\t)\n\t\tfilterValues(&docpkg.Consts)\n\t\tfilterValues(&docpkg.Vars)\n\t\tfilterFuncs(&docpkg.Funcs)\n\t\tdocpkg.Types = slices.DeleteFunc(docpkg.Types, func(t *doc.Type) bool {\n\t\t\tfilterValues(&t.Consts)\n\t\t\tfilterValues(&t.Vars)\n\t\t\tfilterFuncs(&t.Funcs)\n\t\t\tfilterFuncs(&t.Methods)\n\t\t\tif unexported(t.Name) {\n\t\t\t\t// If an unexported type has an exported constructor function,\n\t\t\t\t// treat the constructor as an ordinary standalone function.\n\t\t\t\t// We will sort Funcs again below.\n\t\t\t\tdocpkg.Funcs = append(docpkg.Funcs, t.Funcs...)\n\t\t\t\treturn true // delete this type\n\t\t\t}\n\t\t\treturn false // keep this type\n\t\t})\n\t\tslices.SortFunc(docpkg.Funcs, func(x, y *doc.Func) int {\n\t\t\treturn strings.Compare(x.Name, y.Name)\n\t\t})\n\t}\n\n\t// docHTML renders the doc comment as Markdown.\n\t// The fileNode is used to deduce the enclosing file\n\t// for the correct import mapping.\n\t//\n\t// It is not concurrency-safe.\n\tvar docHTML func(fileNode ast.Node, comment string) []byte\n\t{\n\t\t// Adapt doc comment parser and printer\n\t\t// to our representation of Go packages\n\t\t// so that doc links (e.g. \"[fmt.Println]\")\n\t\t// become valid links.\n\t\tprinter := &comment.Printer{\n\t\t\tDocLinkURL: func(link *comment.DocLink) string {\n\t\t\t\tpath := pkg.Metadata().PkgPath\n\t\t\t\tif link.ImportPath != \"\" {\n\t\t\t\t\tpath = PackagePath(link.ImportPath)\n\t\t\t\t}\n\t\t\t\tfragment := link.Name\n\t\t\t\tif link.Recv != \"\" {\n\t\t\t\t\tfragment = link.Recv + \".\" + link.Name\n\t\t\t\t}\n\t\t\t\treturn web.PkgURL(viewID, path, fragment)\n\t\t\t},\n\t\t}\n\t\tparse := newDocCommentParser(pkg)\n\t\tdocHTML = func(fileNode ast.Node, comment string) []byte {\n\t\t\tdoc := parse(fileNode, comment)\n\t\t\treturn printer.HTML(doc)\n\t\t}\n\t}\n\n\tscope := pkg.Types().Scope()\n\tescape := html.EscapeString\n\n\ttitle := fmt.Sprintf(\"%s package - %s - Gopls packages\",\n\t\tpkg.Types().Name(), escape(pkg.Types().Path()))\n\n\tvar buf bytes.Buffer\n\tbuf.WriteString(`<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>` + title + `</title>\n  <link rel=\"stylesheet\" href=\"/assets/common.css\">\n  <script src=\"/assets/common.js\"></script>\n  <style>\n.lit { color: darkgreen; }\n\nheader {\n  position: sticky;\n  top: 0;\n  left: 0;\n  width: 100%;\n  padding: 0.3em;\n}\n\n.Documentation-sinceVersion {\n  font-weight: normal;\n  color: #808080;\n  float: right;\n}\n\n#pkgsite { height: 1.5em; }\n\n#hdr-Selector {\n  margin-right: 0.3em;\n  float: right;\n  min-width: 25em;\n  padding: 0.3em;\n}\n  </style>\n  <script type='text/javascript'>\nwindow.addEventListener('load', function() {\n\t// Hook up the navigation selector.\n\tdocument.getElementById('hdr-Selector').onchange = (e) => {\n\t\twindow.location.href = e.target.value;\n\t};\n});\n  </script>\n</head>\n<body>\n<header>\n<select id='hdr-Selector'>\n<optgroup label=\"Documentation\">\n  <option label=\"Overview\" value=\"#hdr-Overview\"/>\n  <option label=\"Index\" value=\"#hdr-Index\"/>\n  <option label=\"Constants\" value=\"#hdr-Constants\"/>\n  <option label=\"Variables\" value=\"#hdr-Variables\"/>\n  <option label=\"Functions\" value=\"#hdr-Functions\"/>\n  <option label=\"Types\" value=\"#hdr-Types\"/>\n  <option label=\"Source Files\" value=\"#hdr-SourceFiles\"/>\n</optgroup>\n`)\n\n\t// -- header select element --\n\n\t// option emits an <option> for the specified symbol.\n\t//\n\t// recvType is the apparent receiver type, which may\n\t// differ from ReceiverNamed(obj.Signature.Recv).Name\n\t// for promoted methods.\n\toption := func(obj types.Object, recvType string) {\n\t\t// Render functions/methods as \"(recv) Method(p1, ..., pN)\".\n\t\tfragment := obj.Name()\n\n\t\t// format parameter names (p1, ..., pN)\n\t\tlabel := obj.Name() // for a type\n\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\tvar buf strings.Builder\n\t\t\tsig := fn.Signature()\n\t\t\tif sig.Recv() != nil {\n\t\t\t\tfmt.Fprintf(&buf, \"(%s) \", sig.Recv().Name())\n\t\t\t\tfragment = recvType + \".\" + fn.Name()\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"%s(\", fn.Name())\n\t\t\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\t\t\tif i > 0 {\n\t\t\t\t\tbuf.WriteString(\", \")\n\t\t\t\t}\n\t\t\t\tname := sig.Params().At(i).Name()\n\t\t\t\tif name == \"\" {\n\t\t\t\t\tname = \"_\"\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(name)\n\t\t\t}\n\t\t\tbuf.WriteByte(')')\n\t\t\tlabel = buf.String()\n\t\t}\n\n\t\tfmt.Fprintf(&buf, \"  <option label='%s' value='#%s'/>\\n\", label, fragment)\n\t}\n\n\t// index of functions\n\tfmt.Fprintf(&buf, \"<optgroup label='Functions'>\\n\")\n\tfor _, fn := range docpkg.Funcs {\n\t\toption(scope.Lookup(fn.Name), \"\")\n\t}\n\tfmt.Fprintf(&buf, \"</optgroup>\\n\")\n\n\t// index of types\n\tfmt.Fprintf(&buf, \"<optgroup label='Types'>\\n\")\n\tfor _, doctype := range docpkg.Types {\n\t\toption(scope.Lookup(doctype.Name), \"\")\n\t}\n\tfmt.Fprintf(&buf, \"</optgroup>\\n\")\n\n\t// index of constructors and methods of each type\n\tfor _, doctype := range docpkg.Types {\n\t\ttname := scope.Lookup(doctype.Name).(*types.TypeName)\n\t\tif len(doctype.Funcs)+len(doctype.Methods) > 0 {\n\t\t\tfmt.Fprintf(&buf, \"<optgroup label='type %s'>\\n\", doctype.Name)\n\t\t\tfor _, docfn := range doctype.Funcs {\n\t\t\t\toption(scope.Lookup(docfn.Name), \"\")\n\t\t\t}\n\t\t\tfor _, docmethod := range doctype.Methods {\n\t\t\t\tmethod, _, _ := types.LookupFieldOrMethod(tname.Type(), true, tname.Pkg(), docmethod.Name)\n\t\t\t\toption(method, doctype.Name)\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"</optgroup>\\n\")\n\t\t}\n\t}\n\tfmt.Fprintf(&buf, \"</select>\\n\")\n\tfmt.Fprintf(&buf, \"</header>\\n\")\n\n\t// -- main element --\n\n\t// nodeHTML returns HTML markup for a syntax tree.\n\t// It replaces referring identifiers with links,\n\t// and adds style spans for strings and comments.\n\tnodeHTML := func(n ast.Node) string {\n\n\t\t// linkify returns the appropriate URL (if any) for an identifier.\n\t\tlinkify := func(id *ast.Ident) protocol.URI {\n\t\t\tif obj, ok := pkg.TypesInfo().Uses[id]; ok && obj.Pkg() != nil {\n\t\t\t\t// imported package name?\n\t\t\t\tif pkgname, ok := obj.(*types.PkgName); ok {\n\t\t\t\t\t// TODO(adonovan): do this for Defs of PkgName too.\n\t\t\t\t\treturn web.PkgURL(viewID, PackagePath(pkgname.Imported().Path()), \"\")\n\t\t\t\t}\n\n\t\t\t\t// package-level symbol?\n\t\t\t\tif obj.Parent() == obj.Pkg().Scope() {\n\t\t\t\t\tif obj.Pkg() == pkg.Types() {\n\t\t\t\t\t\treturn \"#\" + obj.Name() // intra-package ref\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn web.PkgURL(viewID, PackagePath(obj.Pkg().Path()), obj.Name())\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// method of package-level named type?\n\t\t\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\t\t\tsig := fn.Signature()\n\t\t\t\t\tif sig.Recv() != nil {\n\t\t\t\t\t\t_, named := typesinternal.ReceiverNamed(sig.Recv())\n\t\t\t\t\t\tif named != nil {\n\t\t\t\t\t\t\tfragment := named.Obj().Name() + \".\" + fn.Name()\n\t\t\t\t\t\t\treturn web.PkgURL(viewID, PackagePath(fn.Pkg().Path()), fragment)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn \"\"\n\t\t\t\t}\n\n\t\t\t\t// TODO(adonovan): field of package-level named struct type.\n\t\t\t\t// (Requires an index, since there's no way to\n\t\t\t\t// get from Var to Named.)\n\t\t\t}\n\t\t\treturn \"\"\n\t\t}\n\n\t\t// Splice spans into HTML-escaped segments of the\n\t\t// original source buffer (which is usually but not\n\t\t// necessarily formatted).\n\t\t//\n\t\t// (For expedience we don't use the more sophisticated\n\t\t// approach taken by cmd/godoc and pkgsite's render\n\t\t// package, which emit the text, spans, and comments\n\t\t// in one traversal of the syntax tree.)\n\t\t//\n\t\t// TODO(adonovan): splice styled spans around comments too.\n\t\t//\n\t\t// TODO(adonovan): pkgsite prints specs from grouped\n\t\t// type decls like \"type ( T1; T2 )\" to make them\n\t\t// appear as separate decls. We should too.\n\t\tvar buf bytes.Buffer\n\t\tfor _, file := range pkg.CompiledGoFiles() {\n\t\t\tif astutil.NodeContainsPos(file.File, n.Pos()) {\n\t\t\t\tpos := n.Pos()\n\n\t\t\t\t// emit emits source in the interval [pos:to] and updates pos.\n\t\t\t\temit := func(to token.Pos) {\n\t\t\t\t\t// Ident and BasicLit always have a valid pos.\n\t\t\t\t\t// (Failure means the AST has been corrupted.)\n\t\t\t\t\tif !to.IsValid() {\n\t\t\t\t\t\tbug.Reportf(\"invalid Pos\")\n\t\t\t\t\t}\n\t\t\t\t\ttext, err := file.PosText(pos, to)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tbug.Reportf(\"invalid pos range: %v\", err)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tbuf.WriteString(escape(string(text)))\n\t\t\t\t\tpos = to\n\t\t\t\t}\n\t\t\t\tast.Inspect(n, func(n ast.Node) bool {\n\t\t\t\t\tswitch n := n.(type) {\n\t\t\t\t\tcase *ast.Ident:\n\t\t\t\t\t\temit(n.Pos())\n\t\t\t\t\t\tpos = n.End()\n\t\t\t\t\t\tif url := linkify(n); url != \"\" {\n\t\t\t\t\t\t\tfmt.Fprintf(&buf, \"<a class='id' href='%s'>%s</a>\", url, escape(n.Name))\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbuf.WriteString(escape(n.Name)) // plain\n\t\t\t\t\t\t}\n\n\t\t\t\t\tcase *ast.BasicLit:\n\t\t\t\t\t\temit(n.Pos())\n\t\t\t\t\t\tpos = n.End()\n\t\t\t\t\t\tfmt.Fprintf(&buf, \"<span class='lit'>%s</span>\", escape(n.Value))\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\temit(n.End())\n\t\t\t\treturn buf.String()\n\t\t\t}\n\t\t}\n\n\t\t// Original source not found.\n\t\t// Format the node without adornments.\n\t\tif err := format.Node(&buf, pkg.FileSet(), n); err != nil {\n\t\t\t// e.g. BadDecl?\n\t\t\tbuf.Reset()\n\t\t\tfmt.Fprintf(&buf, \"formatting error: %v\", err)\n\t\t}\n\t\treturn escape(buf.String())\n\t}\n\n\t// fnString is like fn.String() except that it:\n\t// - shows the receiver name;\n\t// - uses space \"(T) M()\" not dot \"(T).M()\" after receiver;\n\t// - doesn't bother with the special case for interface receivers\n\t//   since it is unreachable for the methods in go/doc.\n\t// - elides parameters after the first three: f(a, b, c, ...).\n\tfnString := func(fn *types.Func) string {\n\t\tpkgRelative := typesinternal.NameRelativeTo(pkg.Types())\n\n\t\tsig := fn.Signature()\n\n\t\t// Emit \"func (recv T) F\".\n\t\tvar buf bytes.Buffer\n\t\tbuf.WriteString(\"func \")\n\t\tif recv := sig.Recv(); recv != nil {\n\t\t\tbuf.WriteByte('(')\n\t\t\tif recv.Name() != \"\" {\n\t\t\t\tbuf.WriteString(recv.Name())\n\t\t\t\tbuf.WriteByte(' ')\n\t\t\t}\n\t\t\ttypes.WriteType(&buf, recv.Type(), pkgRelative)\n\t\t\tbuf.WriteByte(')')\n\t\t\tbuf.WriteByte(' ') // (ObjectString uses a '.' here)\n\t\t} else if pkg := fn.Pkg(); pkg != nil {\n\t\t\tif s := pkgRelative(pkg); s != \"\" {\n\t\t\t\tbuf.WriteString(s)\n\t\t\t\tbuf.WriteByte('.')\n\t\t\t}\n\t\t}\n\t\tbuf.WriteString(fn.Name())\n\n\t\t// Emit signature.\n\t\t//\n\t\t// Elide parameters after the third one.\n\t\t// WriteSignature is too complex to fork, so we replace\n\t\t// parameters 4+ with \"invalid type\", format,\n\t\t// then post-process the string.\n\t\tif sig.Params().Len() > 3 {\n\n\t\t\t// Clone each TypeParam as NewSignatureType modifies them (#67294).\n\t\t\tcloneTparams := func(seq *types.TypeParamList) []*types.TypeParam {\n\t\t\t\tslice := make([]*types.TypeParam, seq.Len())\n\t\t\t\tfor i := range slice {\n\t\t\t\t\ttparam := seq.At(i)\n\t\t\t\t\tslice[i] = types.NewTypeParam(tparam.Obj(), tparam.Constraint())\n\t\t\t\t}\n\t\t\t\treturn slice\n\t\t\t}\n\n\t\t\tsig = types.NewSignatureType(\n\t\t\t\tsig.Recv(),\n\t\t\t\tcloneTparams(sig.RecvTypeParams()),\n\t\t\t\tcloneTparams(sig.TypeParams()),\n\t\t\t\ttypes.NewTuple(append(\n\t\t\t\t\tslices.Collect(sig.Params().Variables())[:3],\n\t\t\t\t\ttypes.NewParam(0, nil, \"\", types.Typ[types.Invalid]))...),\n\t\t\t\tsig.Results(),\n\t\t\t\tfalse) // any final ...T parameter is truncated\n\t\t}\n\t\ttypes.WriteSignature(&buf, sig, pkgRelative)\n\t\treturn strings.ReplaceAll(buf.String(), \", invalid type)\", \", ...)\")\n\t}\n\n\tfmt.Fprintf(&buf, \"<main>\\n\")\n\n\t// package name\n\tfmt.Fprintf(&buf, \"<h1 id='hdr-Overview'>Package %s</h1>\\n\", pkg.Types().Name())\n\n\t// import path\n\tfmt.Fprintf(&buf, \"<pre class='code'>import %q</pre>\\n\", pkg.Types().Path())\n\n\t// link to same package in pkg.go.dev\n\tfmt.Fprintf(&buf, \"<div><a href=%q title='View in pkg.go.dev'><img id='pkgsite' src='/assets/go-logo-blue.svg'/></a>\\n\",\n\t\t\"https://pkg.go.dev/\"+string(pkg.Types().Path()))\n\n\t// package doc\n\tfor _, f := range pkg.Syntax() {\n\t\tif f.Doc != nil {\n\t\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\", docHTML(f.Doc, docpkg.Doc))\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// symbol index\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-Index'>Index</h2>\\n\")\n\tfmt.Fprintf(&buf, \"<ul>\\n\")\n\tif len(docpkg.Consts) > 0 {\n\t\tfmt.Fprintf(&buf, \"<li><a href='#hdr-Constants'>Constants</a></li>\\n\")\n\t}\n\tif len(docpkg.Vars) > 0 {\n\t\tfmt.Fprintf(&buf, \"<li><a href='#hdr-Variables'>Variables</a></li>\\n\")\n\t}\n\tfor _, fn := range docpkg.Funcs {\n\t\tobj := scope.Lookup(fn.Name).(*types.Func)\n\t\tfmt.Fprintf(&buf, \"<li><a href='#%s'>%s</a></li>\\n\",\n\t\t\tobj.Name(), escape(fnString(obj)))\n\t}\n\tfor _, doctype := range docpkg.Types {\n\t\ttname := scope.Lookup(doctype.Name).(*types.TypeName)\n\t\tfmt.Fprintf(&buf, \"<li><a href='#%[1]s'>type %[1]s</a></li>\\n\",\n\t\t\ttname.Name())\n\n\t\tif len(doctype.Funcs)+len(doctype.Methods) > 0 {\n\t\t\tfmt.Fprintf(&buf, \"<ul>\\n\")\n\n\t\t\t// constructors\n\t\t\tfor _, docfn := range doctype.Funcs {\n\t\t\t\tobj := scope.Lookup(docfn.Name).(*types.Func)\n\t\t\t\tfmt.Fprintf(&buf, \"<li><a href='#%s'>%s</a></li>\\n\",\n\t\t\t\t\tdocfn.Name, escape(fnString(obj)))\n\t\t\t}\n\t\t\t// methods\n\t\t\tfor _, docmethod := range doctype.Methods {\n\t\t\t\tmethod, _, _ := types.LookupFieldOrMethod(tname.Type(), true, tname.Pkg(), docmethod.Name)\n\t\t\t\tfmt.Fprintf(&buf, \"<li><a href='#%s.%s'>%s</a></li>\\n\",\n\t\t\t\t\tdoctype.Name,\n\t\t\t\t\tdocmethod.Name,\n\t\t\t\t\tescape(fnString(method.(*types.Func))))\n\t\t\t}\n\t\t\tfmt.Fprintf(&buf, \"</ul>\\n\")\n\t\t}\n\t}\n\t// TODO(adonovan): add index of Examples here.\n\tfmt.Fprintf(&buf, \"</ul>\\n\")\n\n\t// constants and variables\n\tvalues := func(vals []*doc.Value) {\n\t\tfor _, v := range vals {\n\t\t\t// anchors\n\t\t\tfor _, name := range v.Names {\n\t\t\t\tfmt.Fprintf(&buf, \"<a id='%s'></a>\\n\", escape(name))\n\t\t\t}\n\n\t\t\t// declaration\n\t\t\tdecl2 := *v.Decl // shallow copy\n\t\t\tdecl2.Doc = nil\n\t\t\tfmt.Fprintf(&buf, \"<pre class='code'>%s</pre>\\n\", nodeHTML(&decl2))\n\n\t\t\t// comment (if any)\n\t\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\", docHTML(v.Decl, v.Doc))\n\t\t}\n\t}\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-Constants'>Constants</h2>\\n\")\n\tif len(docpkg.Consts) == 0 {\n\t\tfmt.Fprintf(&buf, \"<div>(no constants)</div>\\n\")\n\t} else {\n\t\tvalues(docpkg.Consts)\n\t}\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-Variables'>Variables</h2>\\n\")\n\tif len(docpkg.Vars) == 0 {\n\t\tfmt.Fprintf(&buf, \"<div>(no variables)</div>\\n\")\n\t} else {\n\t\tvalues(docpkg.Vars)\n\t}\n\n\t// addedInHTML returns an HTML division containing the Go release version at\n\t// which this obj became available.\n\taddedInHTML := func(obj types.Object) string {\n\t\tif sym := StdSymbolOf(obj); sym != nil && sym.Version != stdlib.Version(0) {\n\t\t\treturn fmt.Sprintf(\"<span class='Documentation-sinceVersion'>added in %v</span>\", sym.Version)\n\t\t}\n\t\treturn \"\"\n\t}\n\n\t// package-level functions\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-Functions'>Functions</h2>\\n\")\n\t// funcs emits a list of package-level functions,\n\t// possibly organized beneath the type they construct.\n\tfuncs := func(funcs []*doc.Func) {\n\t\tfor _, docfn := range funcs {\n\t\t\tobj := scope.Lookup(docfn.Name).(*types.Func)\n\n\t\t\tfmt.Fprintf(&buf, \"<h3 id='%s'>func %s %s</h3>\\n\",\n\t\t\t\tdocfn.Name, objHTML(pkg.FileSet(), web, obj), addedInHTML(obj))\n\n\t\t\t// decl: func F(params) results\n\t\t\tfmt.Fprintf(&buf, \"<pre class='code'>%s</pre>\\n\",\n\t\t\t\tnodeHTML(docfn.Decl.Type))\n\n\t\t\t// comment (if any)\n\t\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\", docHTML(docfn.Decl, docfn.Doc))\n\t\t}\n\t}\n\tfuncs(docpkg.Funcs)\n\n\t// types and their subelements\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-Types'>Types</h2>\\n\")\n\tfor _, doctype := range docpkg.Types {\n\t\ttname := scope.Lookup(doctype.Name).(*types.TypeName)\n\n\t\t// title and source link\n\t\tfmt.Fprintf(&buf, \"<h3 id='%s'>type %s %s</h3>\\n\",\n\t\t\tdoctype.Name, objHTML(pkg.FileSet(), web, tname), addedInHTML(tname))\n\n\t\t// declaration\n\t\t// TODO(adonovan): excise non-exported struct fields somehow.\n\t\tdecl2 := *doctype.Decl // shallow copy\n\t\tdecl2.Doc = nil\n\t\tfmt.Fprintf(&buf, \"<pre class='code'>%s</pre>\\n\", nodeHTML(&decl2))\n\n\t\t// comment (if any)\n\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\", docHTML(doctype.Decl, doctype.Doc))\n\n\t\t// subelements\n\t\tvalues(doctype.Consts) // constants of type T\n\t\tvalues(doctype.Vars)   // vars of type T\n\t\tfuncs(doctype.Funcs)   // constructors of T\n\n\t\t// methods on T\n\t\tfor _, docmethod := range doctype.Methods {\n\t\t\tmethod, _, _ := types.LookupFieldOrMethod(tname.Type(), true, tname.Pkg(), docmethod.Name)\n\t\t\tfmt.Fprintf(&buf, \"<h4 id='%s.%s'>func (%s) %s %s</h4>\\n\",\n\t\t\t\tdoctype.Name, docmethod.Name,\n\t\t\t\tdocmethod.Orig, // T or *T\n\t\t\t\tobjHTML(pkg.FileSet(), web, method), addedInHTML(method))\n\n\t\t\t// decl: func (x T) M(params) results\n\t\t\tfmt.Fprintf(&buf, \"<pre class='code'>%s</pre>\\n\",\n\t\t\t\tnodeHTML(docmethod.Decl.Type))\n\n\t\t\t// comment (if any)\n\t\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\",\n\t\t\t\tdocHTML(docmethod.Decl, docmethod.Doc))\n\t\t}\n\t}\n\n\t// source files\n\tfmt.Fprintf(&buf, \"<h2 id='hdr-SourceFiles'>Source files</h2>\\n\")\n\tfor _, filename := range docpkg.Filenames {\n\t\tfmt.Fprintf(&buf, \"<div class='comment'>%s</div>\\n\",\n\t\t\tsourceLink(filepath.Base(filename), web.SrcURL(filename, 1, 1)))\n\t}\n\n\tfmt.Fprintf(&buf, \"</main>\\n\")\n\tfmt.Fprintf(&buf, \"</body>\\n\")\n\tfmt.Fprintf(&buf, \"</html>\\n\")\n\n\treturn buf.Bytes(), nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/references.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines the 'references' query based on a serializable\n// index constructed during type checking, thus avoiding the need to\n// type-check packages at search time.\n//\n// See the ./xrefs/ subpackage for the index construction and lookup.\n//\n// This implementation does not intermingle objects from distinct\n// calls to TypeCheck.\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/methodsets\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// References returns a list of all references (sorted with\n// definitions before uses) to the object denoted by the identifier at\n// the given file/position, searching the entire workspace.\nfunc References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range, includeDeclaration bool) ([]protocol.Location, error) {\n\treferences, err := references(ctx, snapshot, fh, rng, includeDeclaration)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlocations := make([]protocol.Location, len(references))\n\tfor i, ref := range references {\n\t\tlocations[i] = ref.location\n\t}\n\treturn locations, nil\n}\n\n// A reference describes an identifier that refers to the same\n// object as the subject of a References query.\ntype reference struct {\n\tisDeclaration bool\n\tlocation      protocol.Location\n\tpkgPath       PackagePath // of declaring package (same for all elements of the slice)\n}\n\n// references returns a list of all references (sorted with\n// definitions before uses) to the object denoted by the identifier at\n// the given file/position, searching the entire workspace.\nfunc references(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, rng protocol.Range, includeDeclaration bool) ([]reference, error) {\n\tctx, done := event.Start(ctx, \"golang.references\")\n\tdefer done()\n\n\t// Is the cursor within the package name declaration?\n\t_, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar refs []reference\n\tif inPackageName {\n\t\trefs, err = packageReferences(ctx, snapshot, f.URI())\n\t} else {\n\t\trefs, err = ordinaryReferences(ctx, snapshot, f.URI(), rng)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsort.Slice(refs, func(i, j int) bool {\n\t\tx, y := refs[i], refs[j]\n\t\tif x.isDeclaration != y.isDeclaration {\n\t\t\treturn x.isDeclaration // decls < refs\n\t\t}\n\t\treturn protocol.CompareLocation(x.location, y.location) < 0\n\t})\n\n\t// De-duplicate by location, and optionally remove declarations.\n\tout := refs[:0]\n\tfor _, ref := range refs {\n\t\tif !includeDeclaration && ref.isDeclaration {\n\t\t\tcontinue\n\t\t}\n\t\tif len(out) == 0 || out[len(out)-1].location != ref.location {\n\t\t\tout = append(out, ref)\n\t\t}\n\t}\n\trefs = out\n\n\treturn refs, nil\n}\n\n// packageReferences returns a list of references to the package\n// declaration of the specified name and uri by searching among the\n// import declarations of all packages that directly import the target\n// package.\nfunc packageReferences(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) ([]reference, error) {\n\tmetas, err := snapshot.MetadataForFile(ctx, uri, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(metas) == 0 {\n\t\treturn nil, fmt.Errorf(\"found no package containing %s\", uri)\n\t}\n\n\tvar refs []reference\n\n\t// Find external references to the package declaration\n\t// from each direct import of the package.\n\t//\n\t// The narrowest package is the most broadly imported,\n\t// so we choose it for the external references.\n\t//\n\t// But if the file ends with _test.go then we need to\n\t// find the package it is testing; there's no direct way\n\t// to do that, so pick a file from the same package that\n\t// doesn't end in _test.go and start over.\n\tnarrowest := metas[0]\n\tif narrowest.ForTest != \"\" && strings.HasSuffix(string(uri), \"_test.go\") {\n\t\tfor _, f := range narrowest.CompiledGoFiles {\n\t\t\tif !strings.HasSuffix(string(f), \"_test.go\") {\n\t\t\t\treturn packageReferences(ctx, snapshot, f)\n\t\t\t}\n\t\t}\n\t\t// This package has no non-test files.\n\t\t// Skip the search for external references.\n\t\t// (Conceivably one could blank-import an empty package, but why?)\n\t} else {\n\t\trdeps, err := snapshot.ReverseDependencies(ctx, narrowest.ID, false) // direct\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Restrict search to workspace packages.\n\t\tworkspace, err := snapshot.WorkspaceMetadata(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tworkspaceMap := make(map[PackageID]*metadata.Package, len(workspace))\n\t\tfor _, mp := range workspace {\n\t\t\tworkspaceMap[mp.ID] = mp\n\t\t}\n\n\t\tfor _, rdep := range rdeps {\n\t\t\tif _, ok := workspaceMap[rdep.ID]; !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, uri := range rdep.CompiledGoFiles {\n\t\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfor _, imp := range f.File.Imports {\n\t\t\t\t\tif rdep.DepsByImpPath[metadata.UnquoteImportPath(imp)] == narrowest.ID {\n\t\t\t\t\t\trefs = append(refs, reference{\n\t\t\t\t\t\t\tisDeclaration: false,\n\t\t\t\t\t\t\tlocation:      mustLocation(f, imp),\n\t\t\t\t\t\t\tpkgPath:       narrowest.PkgPath,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find internal \"references\" to the package from\n\t// of each package declaration in the target package itself.\n\t//\n\t// The widest package (possibly a test variant) has the\n\t// greatest number of files and thus we choose it for the\n\t// \"internal\" references.\n\twidest := metas[len(metas)-1] // may include _test.go files\n\tfor _, uri := range widest.CompiledGoFiles {\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// golang/go#66250: don't crash if the package file lacks a name.\n\t\tif f.File.Name.Pos().IsValid() {\n\t\t\trefs = append(refs, reference{\n\t\t\t\tisDeclaration: true, // (one of many)\n\t\t\t\tlocation:      mustLocation(f, f.File.Name),\n\t\t\t\tpkgPath:       widest.PkgPath,\n\t\t\t})\n\t\t}\n\t}\n\n\treturn refs, nil\n}\n\n// ordinaryReferences computes references for all ordinary objects (not package declarations).\nfunc ordinaryReferences(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, rng protocol.Range) ([]reference, error) {\n\t// Strategy: use the reference information computed by the\n\t// type checker to find the declaration. First type-check this\n\t// package to find the declaration, then type check the\n\t// declaring package (which may be different), plus variants,\n\t// to find local (in-package) references.\n\t// Global references are satisfied by the index.\n\n\t// Strictly speaking, a wider package could provide a different\n\t// declaration (e.g. because the _test.go files can change the\n\t// meaning of a field or method selection), but the narrower\n\t// package reports the more broadly referenced object.\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Find the selected object (declaration or reference).\n\t// For struct{T}, we choose the field (Def) over the type (Use).\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(start, end) // can't fail\n\n\tcandidates, err := objectsAt(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Pick first object arbitrarily.\n\t// The case variables of a type switch have different\n\t// types but that difference is immaterial here.\n\tobj := candidates[0].obj\n\n\t// nil, error, error.Error, iota, or other built-in?\n\tif isBuiltin(obj) {\n\t\treturn nil, fmt.Errorf(\"references to builtin %q are not supported\", obj.Name())\n\t}\n\n\t// Find metadata of all packages containing the object's defining file.\n\t// This may include the query pkg, and possibly other variants.\n\tdeclPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())\n\tdeclURI := protocol.URIFromPath(declPosn.Filename)\n\tvariants, err := snapshot.MetadataForFile(ctx, declURI, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(variants) == 0 {\n\t\treturn nil, fmt.Errorf(\"no packages for file %q\", declURI) // can't happen\n\t}\n\t// (variants must include ITVs for reverse dependency computation below.)\n\n\t// Is object exported?\n\t// If so, compute scope and targets of the global search.\n\tvar (\n\t\tglobalScope   = make(map[PackageID]*metadata.Package) // (excludes ITVs)\n\t\tglobalTargets map[PackagePath]map[objectpath.Path]unit\n\t\texpansions    = make(map[PackageID]unit) // packages that caused search expansion\n\t)\n\t// TODO(adonovan): what about generic functions? Need to consider both\n\t// uninstantiated and instantiated. The latter have no objectpath. Use Origin?\n\tif path, err := objectpath.For(obj); err == nil && obj.Exported() {\n\t\tpkgPath := variants[0].PkgPath // (all variants have same package path)\n\t\tglobalTargets = map[PackagePath]map[objectpath.Path]unit{\n\t\t\tpkgPath: {path: {}}, // primary target\n\t\t}\n\n\t\t// Compute set of (non-ITV) workspace packages.\n\t\t// We restrict references to this subset.\n\t\tworkspace, err := snapshot.WorkspaceMetadata(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tworkspaceMap := make(map[PackageID]*metadata.Package, len(workspace))\n\t\tworkspaceIDs := make([]PackageID, 0, len(workspace))\n\t\tfor _, mp := range workspace {\n\t\t\tworkspaceMap[mp.ID] = mp\n\t\t\tworkspaceIDs = append(workspaceIDs, mp.ID)\n\t\t}\n\n\t\t// addRdeps expands the global scope to include the\n\t\t// reverse dependencies of the specified package.\n\t\taddRdeps := func(id PackageID, transitive bool) error {\n\t\t\trdeps, err := snapshot.ReverseDependencies(ctx, id, transitive)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor rdepID, rdep := range rdeps {\n\t\t\t\t// Skip non-workspace packages.\n\t\t\t\t//\n\t\t\t\t// This means we also skip any expansion of the\n\t\t\t\t// search that might be caused by a non-workspace\n\t\t\t\t// package, possibly causing us to miss references\n\t\t\t\t// to the expanded target set from workspace packages.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): don't skip those expansions.\n\t\t\t\t// The challenge is how to so without type-checking\n\t\t\t\t// a lot of non-workspace packages not covered by\n\t\t\t\t// the initial workspace load.\n\t\t\t\tif _, ok := workspaceMap[rdepID]; !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tglobalScope[rdepID] = rdep\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\t// How far need we search?\n\t\t// For package-level objects, we need only search the direct importers.\n\t\t// For fields and methods, we must search transitively.\n\t\ttransitive := obj.Pkg().Scope().Lookup(obj.Name()) != obj\n\n\t\t// The scope is the union of rdeps of each variant.\n\t\t// (Each set is disjoint so there's no benefit to\n\t\t// combining the metadata graph traversals.)\n\t\tfor _, mp := range variants {\n\t\t\tif err := addRdeps(mp.ID, transitive); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\t// Is object a method?\n\t\t//\n\t\t// If so, expand the search so that the targets include\n\t\t// all methods that correspond to it through interface\n\t\t// satisfaction, and the scope includes the rdeps of\n\t\t// the package that declares each corresponding type.\n\t\t//\n\t\t// 'expansions' records the packages that declared\n\t\t// such types.\n\t\tif recv := effectiveReceiver(obj); recv != nil {\n\t\t\tif err := expandMethodSearch(ctx, snapshot, workspaceIDs, obj.(*types.Func), recv, addRdeps, globalTargets, expansions); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// The search functions will call report(loc) for each hit.\n\tvar (\n\t\trefsMu sync.Mutex\n\t\trefs   []reference\n\t)\n\treport := func(loc protocol.Location, isDecl bool) {\n\t\tref := reference{\n\t\t\tisDeclaration: isDecl,\n\t\t\tlocation:      loc,\n\t\t\tpkgPath:       pkg.Metadata().PkgPath,\n\t\t}\n\t\trefsMu.Lock()\n\t\trefs = append(refs, ref)\n\t\trefsMu.Unlock()\n\t}\n\n\t// Loop over the variants of the declaring package,\n\t// and perform both the local (in-package) and global\n\t// (cross-package) searches, in parallel.\n\t//\n\t// TODO(adonovan): opt: support LSP reference streaming. See:\n\t// - https://github.com/microsoft/vscode-languageserver-node/pull/164\n\t// - https://github.com/microsoft/language-server-protocol/pull/182\n\t//\n\t// Careful: this goroutine must not return before group.Wait.\n\tvar group errgroup.Group\n\n\t// Compute local references for each variant.\n\t// The target objects are identified by (URI, offset).\n\tfor _, mp := range variants {\n\t\t// We want the ordinary importable package,\n\t\t// plus any test-augmented variants, since\n\t\t// declarations in _test.go files may change\n\t\t// the reference of a selection, or even a\n\t\t// field into a method or vice versa.\n\t\t//\n\t\t// But we don't need intermediate test variants,\n\t\t// as their local references will be covered\n\t\t// already by other variants.\n\t\tif mp.IsIntermediateTestVariant() {\n\t\t\tcontinue\n\t\t}\n\t\tmp := mp\n\t\tgroup.Go(func() error {\n\t\t\t// TODO(adonovan): opt: batch these TypeChecks.\n\t\t\tpkgs, err := snapshot.TypeCheck(ctx, mp.ID)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpkg := pkgs[0]\n\n\t\t\t// Find the declaration of the corresponding\n\t\t\t// object in this package based on (URI, offset).\n\t\t\tpgf, err := pkg.File(declURI)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpos, err := safetoken.Pos(pgf.Tok, declPosn.Offset)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcur, _ := pgf.Cursor().FindByPos(pos, pos) // can't fail\n\n\t\t\tobjects, err := objectsAt(pkg.TypesInfo(), cur)\n\t\t\tif err != nil {\n\t\t\t\treturn err // unreachable? (probably caught earlier)\n\t\t\t}\n\n\t\t\t// Report the locations of the declaration(s).\n\t\t\t// TODO(adonovan): what about for corresponding methods? Add tests.\n\t\t\tfor _, o := range objects {\n\t\t\t\treport(mustLocation(pgf, o.cur.Node()), true)\n\t\t\t}\n\n\t\t\t// Convert objects list to targets set.\n\t\t\ttargets := make(map[types.Object]bool)\n\t\t\tfor _, o := range objects {\n\t\t\t\ttargets[o.obj] = true\n\t\t\t}\n\n\t\t\treturn localReferences(pkg, targets, true, report)\n\t\t})\n\t}\n\n\t// Also compute local references within packages that declare\n\t// corresponding methods (see above), which expand the global search.\n\t// The target objects are identified by (PkgPath, objectpath).\n\tfor id := range expansions {\n\t\tgroup.Go(func() error {\n\t\t\t// TODO(adonovan): opt: batch these TypeChecks.\n\t\t\tpkgs, err := snapshot.TypeCheck(ctx, id)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpkg := pkgs[0]\n\n\t\t\ttargets := make(map[types.Object]bool)\n\t\t\tfor objpath := range globalTargets[pkg.Metadata().PkgPath] {\n\t\t\t\tobj, err := objectpath.Object(pkg.Types(), objpath)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// No such object, because it was\n\t\t\t\t\t// declared only in the test variant.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\ttargets[obj] = true\n\t\t\t}\n\n\t\t\t// Don't include corresponding types or methods\n\t\t\t// since expansions did that already, and we don't\n\t\t\t// want (e.g.) concrete -> interface -> concrete.\n\t\t\tconst correspond = false\n\t\t\treturn localReferences(pkg, targets, correspond, report)\n\t\t})\n\t}\n\n\t// Compute global references for selected reverse dependencies.\n\tgroup.Go(func() error {\n\t\tvar globalIDs []PackageID\n\t\tfor id := range globalScope {\n\t\t\tglobalIDs = append(globalIDs, id)\n\t\t}\n\t\tindexes, err := snapshot.References(ctx, globalIDs...)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, index := range indexes {\n\t\t\tfor _, loc := range index.Lookup(globalTargets) {\n\t\t\t\treport(loc, false)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\tif err := group.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn refs, nil\n}\n\n// expandMethodSearch expands the scope and targets of a global search\n// for an exported method to include all methods in the workspace\n// that correspond to it through interface satisfaction.\n//\n// Each package that declares a corresponding type is added to\n// expansions so that we can also find local references to the type\n// within the package, which of course requires type checking.\n//\n// The scope is expanded by a sequence of calls (not concurrent) to addRdeps.\n//\n// recv is the method's effective receiver type, for method-set computations.\nfunc expandMethodSearch(ctx context.Context, snapshot *cache.Snapshot, workspaceIDs []PackageID, method *types.Func, recv types.Type, addRdeps func(id PackageID, transitive bool) error, targets map[PackagePath]map[objectpath.Path]unit, expansions map[PackageID]unit) error {\n\t// Compute the method-set fingerprint used as a key to the global search.\n\tkey, hasMethods := methodsets.KeyOf(recv)\n\tif !hasMethods {\n\t\t// The query object was method T.m, but methodset(T)={}:\n\t\t// this indicates that ill-typed T has conflicting fields and methods.\n\t\t// Rather than bug-report (#67978), treat the empty method set at face value.\n\t\treturn nil\n\t}\n\t// Search the methodset index of each package in the workspace.\n\tindexes, err := snapshot.MethodSets(ctx, workspaceIDs...)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar mu sync.Mutex // guards addRdeps, targets, expansions\n\tvar group errgroup.Group\n\tfor i, index := range indexes {\n\t\tgroup.Go(func() error {\n\t\t\t// Consult index for matching (super/sub) methods.\n\t\t\tconst want = methodsets.Supertype | methodsets.Subtype\n\t\t\tresults := index.Search(key, want, method)\n\t\t\tif len(results) == 0 {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// We have discovered one or more corresponding types.\n\t\t\tid := workspaceIDs[i]\n\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\n\t\t\t// Expand global search scope to include rdeps of this pkg.\n\t\t\tif err := addRdeps(id, true); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Mark this package so that we search within it for\n\t\t\t// local references to the additional types/methods.\n\t\t\texpansions[id] = unit{}\n\n\t\t\t// Add each corresponding method the to set of global search targets.\n\t\t\tfor _, res := range results {\n\t\t\t\tmethodPkg := PackagePath(res.PkgPath)\n\t\t\t\topaths, ok := targets[methodPkg]\n\t\t\t\tif !ok {\n\t\t\t\t\topaths = make(map[objectpath.Path]unit)\n\t\t\t\t\ttargets[methodPkg] = opaths\n\t\t\t\t}\n\t\t\t\topaths[res.ObjectPath] = unit{}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\treturn group.Wait()\n}\n\n// localReferences traverses syntax and reports each reference to one\n// of the target objects, or (if correspond is set) an object that\n// corresponds to one of them via interface satisfaction.\nfunc localReferences(pkg *cache.Package, targets map[types.Object]bool, correspond bool, report func(loc protocol.Location, isDecl bool)) error {\n\t// If we're searching for references to a method optionally\n\t// broaden the search to include references to corresponding\n\t// methods of mutually assignable receiver types.\n\t// (We use a slice, but objectsAt never returns >1 methods.)\n\tvar methodRecvs []types.Type\n\tvar methodName string // name of an arbitrary target, iff a method\n\tif correspond {\n\t\tfor obj := range targets {\n\t\t\tif t := effectiveReceiver(obj); t != nil {\n\t\t\t\tmethodRecvs = append(methodRecvs, t)\n\t\t\t\tmethodName = obj.Name()\n\t\t\t}\n\t\t}\n\t}\n\n\tvar msets typeutil.MethodSetCache\n\n\t// matches reports whether obj either is or corresponds to a target.\n\t// (Correspondence is defined as usual for interface methods: super/subtype.)\n\tmatches := func(obj types.Object) bool {\n\t\tif containsOrigin(targets, obj) {\n\t\t\treturn true\n\t\t}\n\t\tif methodRecvs != nil && obj.Name() == methodName {\n\t\t\tif orecv := effectiveReceiver(obj); orecv != nil {\n\t\t\t\tfor _, mrecv := range methodRecvs {\n\t\t\t\t\tif implements(&msets, orecv, mrecv) ||\n\t\t\t\t\t\timplements(&msets, mrecv, orecv) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// Scan through syntax looking for uses of one of the target objects.\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tfor curId := range pgf.Cursor().Preorder((*ast.Ident)(nil)) {\n\t\t\tid := curId.Node().(*ast.Ident)\n\t\t\tif obj, ok := pkg.TypesInfo().Uses[id]; ok && matches(obj) {\n\t\t\t\treport(mustLocation(pgf, id), false)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// effectiveReceiver returns the effective receiver type for method-set\n// comparisons for obj, if it is a method, or nil otherwise.\nfunc effectiveReceiver(obj types.Object) types.Type {\n\tif fn, ok := obj.(*types.Func); ok {\n\t\tif recv := fn.Signature().Recv(); recv != nil {\n\t\t\treturn methodsets.EnsurePointer(recv.Type())\n\t\t}\n\t}\n\treturn nil\n}\n\ntype objectAt struct {\n\tobj types.Object     // symbol\n\tcur inspector.Cursor // associated syntax (Ident | ImportSpec)\n}\n\n// objectsAt returns the non-empty list of objects referenced (defined\n// or used) at or near the position specified by cur. It returns an\n// error if none were found.\n//\n// The implementation may look \"nearby\", for example at x when given\n// a cursor to an expression \"*x\", i.e. the cursor was at the star.\n//\n// The result may contain more than one element because all case\n// variables of a type switch appear to be declared at the same\n// identifier.\n//\n// Each object is paired with a cursor for the syntax node that was\n// treated as an identifier, which is not always an ast.Ident.\nfunc objectsAt(info *types.Info, cur inspector.Cursor) ([]objectAt, error) {\n\n\t// Within an ImportSpec, return the PkgName\n\t// and its .Name (if explicit) or the spec if not.\n\tif cur.ParentEdgeKind() == edge.ImportSpec_Path {\n\t\tcur = cur.Parent() // ImportSpec\n\t\tspec := cur.Node().(*ast.ImportSpec)\n\t\tpkgname := info.PkgNameOf(spec)\n\t\tif pkgname == nil {\n\t\t\treturn nil, fmt.Errorf(\"%w for import %s\", errNoObjectFound, metadata.UnquoteImportPath(spec))\n\t\t}\n\t\tif spec.Name != nil { // explicit?\n\t\t\tcur = cur.ChildAt(edge.ImportSpec_Name, -1) // Ident\n\t\t}\n\t\treturn []objectAt{{pkgname, cur}}, nil\n\t}\n\n\t// If the selection is the * of *T or *ptr,\n\t// nudge it to the T or ptr operand in the hope\n\t// that it is an Ident. This makes (e.g.) Hover and\n\t// Definition more flexible w.r.t selections:\n\tif is[*ast.StarExpr](cur.Node()) {\n\t\tcur, _ = cur.FirstChild() // can't fail\n\t}\n\n\tid, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn nil, ErrNoIdentFound\n\t}\n\n\t// If id is a reference to a special var v in\n\t//  switch v := expr.(type) { case T: use(v); ... }\n\t// then return all the implicit case vars.\n\tobjects, _ := typeSwitchVars(info, cur)\n\tif len(objects) > 0 {\n\t\treturn objects, nil\n\t}\n\n\t// All other identifiers.\n\t// For struct{T}, we prefer the defined field Var over the used TypeName.\n\tobj := info.ObjectOf(id)\n\tif obj == nil {\n\t\treturn nil, fmt.Errorf(\"%w for %q\", errNoObjectFound, id.Name)\n\t}\n\treturn []objectAt{{obj, cur}}, nil\n}\n\n// typeSwitchVars returns information about type switch local variables.\n//\n// Given the cursor for an identifier that refers to a variable v\n// declared by a type switch of this form:\n//\n//\tswitch v := expr.(type) {\n//\tcase T: use(v)\n//\t...\n//\t}\n//\n// it returns:\n//\n//   - the (possibly empty) list of variables implicitly declared for\n//     each case type; and\n//\n//   - the identifier's effective type, which is either the case type\n//     (for an occurrence in a case), or the type of 'expr' for the\n//     occurrence in \"switch v\".\n//\n// The identifier may be v in \"switch v\", or a use of it in one of the\n// cases. typeSwitchVars returns zero for all other identifiers.\nfunc typeSwitchVars(info *types.Info, curIdent inspector.Cursor) ([]objectAt, types.Type) {\n\tsw, curSwitch := cursorutil.FirstEnclosing[*ast.TypeSwitchStmt](curIdent)\n\tif sw == nil {\n\t\treturn nil, nil\n\t}\n\tassign, ok := sw.Assign.(*ast.AssignStmt)\n\tif !(ok &&\n\t\tlen(assign.Lhs) == 1 &&\n\t\tis[*ast.Ident](assign.Lhs[0]) &&\n\t\tlen(assign.Rhs) == 1 &&\n\t\tis[*ast.TypeAssertExpr](assign.Rhs[0])) {\n\t\treturn nil, nil\n\t}\n\t// Have: switch v := expr.(type)\n\n\tid := curIdent.Node().(*ast.Ident)\n\n\tmatch := false\n\n\t// Is selected ident \"switch v\" var?\n\t// Since it has no object, use the type of 'expr'.\n\tvar t types.Type\n\tif id == assign.Lhs[0] {\n\t\tmatch = true\n\t\tt = info.TypeOf(assign.Rhs[0].(*ast.TypeAssertExpr).X) // may be nil\n\t}\n\n\t// Gather the switch's implicit variables.\n\tvar objects []objectAt\n\tfor curCase := range curSwitch.ChildAt(edge.TypeSwitchStmt_Body, -1).Children() {\n\t\tclause := curCase.Node().(*ast.CaseClause)\n\t\tv, ok := info.Implicits[clause]\n\t\tif ok {\n\t\t\tif v == info.Uses[id] {\n\t\t\t\t// Selected ident is one of the case vars.\n\t\t\t\tt = v.Type()\n\t\t\t\tmatch = true\n\t\t\t}\n\t\t\tobjects = append(objects, objectAt{v, curIdent})\n\t\t}\n\t}\n\n\tif !match {\n\t\t// Type switch is unrelated to ident.\n\t\treturn nil, nil\n\t}\n\n\t// Note: match does not imply t != nil,\n\t// as type information may be incomplete.\n\n\treturn objects, t\n}\n\n// mustLocation reports the location interval a syntax node,\n// which must belong to m.File.\n//\n// Safe for use only by references and implementations.\nfunc mustLocation(pgf *parsego.File, n ast.Node) protocol.Location {\n\tloc, err := pgf.NodeLocation(n)\n\tif err != nil {\n\t\tpanic(err) // can't happen in references or implementations\n\t}\n\treturn loc\n}\n"
  },
  {
    "path": "gopls/internal/golang/rename.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// TODO(adonovan):\n//\n// - method of generic concrete type -> arbitrary instances of same\n//\n// - make satisfy work across packages.\n//\n// - tests, tests, tests:\n//   - play with renamings in the k8s tree.\n//   - generics\n//   - error cases (e.g. conflicts)\n//   - renaming a symbol declared in the module cache\n//     (currently proceeds with half of the renaming!)\n//   - make sure all tests have both a local and a cross-package analogue.\n//   - look at coverage\n//   - special cases: embedded fields, interfaces, test variants,\n//     function-local things with uppercase names;\n//     packages with type errors (currently 'satisfy' rejects them),\n//     package with missing imports;\n//\n// - measure performance in k8s.\n//\n// - The original gorename tool assumed well-typedness, but the gopls feature\n//   does no such check (which actually makes it much more useful).\n//   Audit to ensure it is safe on ill-typed code.\n//\n// - Generics support was no doubt buggy before but incrementalization\n//   may have exacerbated it. If the problem were just about objects,\n//   defs and uses it would be fairly simple, but type assignability\n//   comes into play in the 'satisfy' check for method renamings.\n//   De-instantiating Vector[int] to Vector[T] changes its type.\n//   We need to come up with a theory for the satisfy check that\n//   works with generics, and across packages. We currently have no\n//   simple way to pass types between packages (think: objectpath for\n//   types), though presumably exportdata could be pressed into service.\n//\n// - FileID-based de-duplication of edits to different URIs for the same file.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\tgoastutil \"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\n// A renamer holds state of a single call to renameObj, which renames\n// an object (or several coupled objects) within a single type-checked\n// syntax package.\ntype renamer struct {\n\tpkg                *cache.Package        // the syntax package in which the renaming is applied\n\tobjsToUpdate       map[types.Object]bool // records progress of calls to check\n\tconflicts          []string\n\tfrom, to           string\n\tsatisfyConstraints map[satisfy.Constraint]bool\n\tmsets              typeutil.MethodSetCache\n\tchangeMethods      bool\n}\n\n// A PrepareItem holds the result of a \"prepare rename\" operation:\n// the source range and value of a selected identifier.\ntype PrepareItem struct {\n\tRange protocol.Range\n\tText  string\n}\n\n// PrepareRename searches for a valid renaming at position pp.\n//\n// The returned usererr is intended to be displayed to the user to explain why\n// the prepare fails. Probably we could eliminate the redundancy in returning\n// two errors, but for now this is done defensively.\nfunc PrepareRename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, rng protocol.Range) (_ *PrepareItem, usererr, err error) {\n\tctx, done := event.Start(ctx, \"golang.PrepareRename\")\n\tdefer done()\n\n\t// Is the cursor within the package name declaration?\n\tif pgf, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, rng); err != nil {\n\t\treturn nil, err, err\n\t} else if inPackageName {\n\t\titem, err := prepareRenamePackageName(ctx, snapshot, pgf)\n\t\treturn item, err, err\n\t}\n\n\t// Ordinary (non-package) renaming.\n\t//\n\t// Type-check the current package, locate the reference at the position,\n\t// validate the object, and report its name and range.\n\t//\n\t// TODO(adonovan): in all cases below, we return usererr=nil,\n\t// which means we return (nil, nil) at the protocol\n\t// layer. This seems like a bug, or at best an exploitation of\n\t// knowledge of VSCode-specific behavior. Can we avoid that?\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, f.URI())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(start, end) // can't fail\n\n\t// Check if we're in a 'func' keyword. If so, we hijack the renaming to\n\t// change the function signature.\n\tif item, err := prepareRenameFuncSignature(pgf, start, end, cur); err != nil {\n\t\treturn nil, nil, err\n\t} else if item != nil {\n\t\treturn item, nil, nil\n\t}\n\n\ttargets, err := objectsAt(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\t// Check if we are renaming an ident inside its doc comment. The call to\n\t\t// objectsAt will have returned an error in this case.\n\t\t// TODO(adonovan): move this logic into objectsAt.\n\t\tvar ok bool\n\t\tcur, ok = docCommentPosToIdent(pgf, start, end, cur)\n\t\tif !ok {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tid := cur.Node().(*ast.Ident)\n\t\tobj := pkg.TypesInfo().Defs[id]\n\t\tif obj == nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"error fetching Object for ident %q\", id.Name)\n\t\t}\n\t\t// Change rename target to the ident.\n\t\ttargets = []objectAt{{obj, cur}}\n\t}\n\n\t// Pick a representative object arbitrarily.\n\t// (All share the same name, pos, and kind.)\n\tobj, node := targets[0].obj, targets[0].cur.Node()\n\tif err := checkRenamable(obj, node); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tnodeRng, err := pgf.NodeRange(node)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif _, isImport := node.(*ast.ImportSpec); isImport {\n\t\t// We're not really renaming the import path.\n\t\tnodeRng.End = nodeRng.Start\n\t}\n\treturn &PrepareItem{\n\t\tRange: nodeRng,\n\t\tText:  obj.Name(),\n\t}, nil, nil\n}\n\nfunc prepareRenamePackageName(ctx context.Context, snapshot *cache.Snapshot, pgf *parsego.File) (*PrepareItem, error) {\n\t// Does the client support file renaming?\n\tif !slices.Contains(snapshot.Options().SupportedResourceOperations, protocol.Rename) {\n\t\treturn nil, errors.New(\"can't rename package: LSP client does not support file renaming\")\n\t}\n\n\t// Check validity of the metadata for the file's containing package.\n\tmeta, err := snapshot.NarrowestMetadataForFile(ctx, pgf.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif meta.Name == \"main\" {\n\t\treturn nil, fmt.Errorf(\"can't rename package \\\"main\\\"\")\n\t}\n\t// TODO(mkalil): support renaming x_test packages.\n\tif strings.HasSuffix(string(meta.Name), \"_test\") {\n\t\treturn nil, fmt.Errorf(\"can't rename x_test packages\")\n\t}\n\tif meta.Module == nil {\n\t\treturn nil, fmt.Errorf(\"can't rename package: missing module information for package %q\", meta.PkgPath)\n\t}\n\t// TODO(mkalil): why is renaming the root package of a module unsupported?\n\tif meta.Module.Path == string(meta.PkgPath) {\n\t\treturn nil, fmt.Errorf(\"can't rename package: package path %q is the same as module path %q\", meta.PkgPath, meta.Module.Path)\n\t}\n\n\t// Return the location of the package declaration.\n\trng, err := pgf.NodeRange(pgf.File.Name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &PrepareItem{\n\t\tRange: rng,\n\t\tText:  string(meta.PkgPath),\n\t}, nil\n}\n\n// prepareRenameFuncSignature prepares a change signature refactoring initiated\n// through invoking a rename request at the 'func' keyword of a function\n// declaration.\n//\n// The resulting text is the signature of the function, which may be edited to\n// the new signature.\nfunc prepareRenameFuncSignature(pgf *parsego.File, start, end token.Pos, cursor inspector.Cursor) (*PrepareItem, error) {\n\tfdecl := funcKeywordDecl(start, end, cursor)\n\tif fdecl == nil {\n\t\treturn nil, nil\n\t}\n\tftyp := nameBlankParams(fdecl.Type)\n\tvar buf bytes.Buffer\n\tif err := printer.Fprint(&buf, token.NewFileSet(), ftyp); err != nil { // use a new fileset so that the signature is formatted on a single line\n\t\treturn nil, err\n\t}\n\trng, err := pgf.PosRange(ftyp.Func, ftyp.Func+token.Pos(len(\"func\")))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttext := buf.String()\n\treturn &PrepareItem{\n\t\tRange: rng,\n\t\tText:  text,\n\t}, nil\n}\n\n// nameBlankParams returns a copy of ftype with blank or unnamed params\n// assigned a unique name.\nfunc nameBlankParams(ftype *ast.FuncType) *ast.FuncType {\n\tftype = astutil.CloneNode(ftype)\n\n\t// First, collect existing names.\n\tscope := make(map[string]bool)\n\tfor name := range astutil.FlatFields(ftype.Params) {\n\t\tif name != nil {\n\t\t\tscope[name.Name] = true\n\t\t}\n\t}\n\tblanks := 0\n\tfor name, field := range astutil.FlatFields(ftype.Params) {\n\t\tif name == nil {\n\t\t\tname = ast.NewIdent(\"_\")\n\t\t\tfield.Names = append(field.Names, name) // ok to append\n\t\t}\n\t\tif name.Name == \"\" || name.Name == \"_\" {\n\t\t\tfor {\n\t\t\t\tnewName := fmt.Sprintf(\"_%d\", blanks)\n\t\t\t\tblanks++\n\t\t\t\tif !scope[newName] {\n\t\t\t\t\tname.Name = newName\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn ftype\n}\n\n// renameFuncSignature computes and applies the effective change signature\n// operation resulting from a 'renamed' (=rewritten) signature.\nfunc renameFuncSignature(ctx context.Context, pkg *cache.Package, pgf *parsego.File, start, end token.Pos, snapshot *cache.Snapshot, cursor inspector.Cursor, f file.Handle, rng protocol.Range, newName string) (map[protocol.DocumentURI][]protocol.TextEdit, error) {\n\tfdecl := funcKeywordDecl(start, end, cursor)\n\tif fdecl == nil {\n\t\treturn nil, nil\n\t}\n\tftyp := nameBlankParams(fdecl.Type)\n\n\t// Parse the user's requested new signature.\n\tparsed, err := parser.ParseExpr(newName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnewType, _ := parsed.(*ast.FuncType)\n\tif newType == nil {\n\t\treturn nil, fmt.Errorf(\"parsed signature is %T, not a function type\", parsed)\n\t}\n\n\t// Check results, before we get into handling permutations of parameters.\n\tif got, want := newType.Results.NumFields(), ftyp.Results.NumFields(); got != want {\n\t\treturn nil, fmt.Errorf(\"changing results not yet supported (got %d results, want %d)\", got, want)\n\t}\n\tvar resultTypes []string\n\tfor _, field := range astutil.FlatFields(ftyp.Results) {\n\t\tresultTypes = append(resultTypes, FormatNode(token.NewFileSet(), field.Type))\n\t}\n\tresultIndex := 0\n\tfor _, field := range astutil.FlatFields(newType.Results) {\n\t\tif FormatNode(token.NewFileSet(), field.Type) != resultTypes[resultIndex] {\n\t\t\treturn nil, fmt.Errorf(\"changing results not yet supported\")\n\t\t}\n\t\tresultIndex++\n\t}\n\n\ttype paramInfo struct {\n\t\tidx int\n\t\ttyp string\n\t}\n\toldParams := make(map[string]paramInfo)\n\tfor name, field := range astutil.FlatFields(ftyp.Params) {\n\t\toldParams[name.Name] = paramInfo{\n\t\t\tidx: len(oldParams),\n\t\t\ttyp: types.ExprString(field.Type),\n\t\t}\n\t}\n\n\tvar newParams []int\n\tfor name, field := range astutil.FlatFields(newType.Params) {\n\t\tif name == nil {\n\t\t\treturn nil, fmt.Errorf(\"need named fields\")\n\t\t}\n\t\tinfo, ok := oldParams[name.Name]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"couldn't find name %s: adding parameters not yet supported\", name)\n\t\t}\n\t\tif newType := types.ExprString(field.Type); newType != info.typ {\n\t\t\treturn nil, fmt.Errorf(\"changing types (%s to %s) not yet supported\", info.typ, newType)\n\t\t}\n\t\tnewParams = append(newParams, info.idx)\n\t}\n\n\tfuncRng, err := pgf.PosRange(ftyp.Func, ftyp.Func)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tchanges, err := ChangeSignature(ctx, snapshot, pkg, pgf, funcRng, newParams)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttransposed := make(map[protocol.DocumentURI][]protocol.TextEdit)\n\tfor _, change := range changes {\n\t\ttransposed[change.TextDocumentEdit.TextDocument.URI] = protocol.AsTextEdits(change.TextDocumentEdit.Edits)\n\t}\n\treturn transposed, nil\n}\n\n// funcKeywordDecl returns the FuncDecl for which pos is in the 'func' keyword,\n// if any.\nfunc funcKeywordDecl(start, end token.Pos, cursor inspector.Cursor) *ast.FuncDecl {\n\tfdecl, _ := cursorutil.FirstEnclosing[*ast.FuncDecl](cursor)\n\tif fdecl == nil {\n\t\treturn nil\n\t}\n\tftyp := fdecl.Type\n\tif start < ftyp.Func || end > ftyp.Func+token.Pos(len(\"func\")) { // tolerate renaming immediately after 'func'\n\t\treturn nil\n\t}\n\treturn fdecl\n}\n\n// checkRenamable returns an error if the object cannot be renamed.\n// node is the name-like syntax node from which the renaming originated.\nfunc checkRenamable(obj types.Object, node ast.Node) error {\n\tswitch obj := obj.(type) {\n\tcase *types.Var:\n\t\t// Allow renaming an embedded field only at its declaration.\n\t\tif obj.Embedded() && node.Pos() != obj.Pos() {\n\t\t\treturn errors.New(\"an embedded field must be renamed at its declaration (since it renames the type too)\")\n\n\t\t}\n\tcase *types.Builtin, *types.Nil:\n\t\treturn fmt.Errorf(\"%s is built in and cannot be renamed\", obj.Name())\n\t}\n\tif obj.Pkg() == nil || obj.Pkg().Path() == \"unsafe\" {\n\t\t// e.g. error.Error, unsafe.Pointer\n\t\treturn fmt.Errorf(\"%s is built in and cannot be renamed\", obj.Name())\n\t}\n\tif obj.Name() == \"_\" {\n\t\treturn errors.New(\"can't rename \\\"_\\\"\")\n\t}\n\treturn nil\n}\n\n// editsToDocChanges converts a map of uris to arrays of text edits to a list of document changes.\nfunc editsToDocChanges(ctx context.Context, snapshot *cache.Snapshot, edits map[protocol.DocumentURI][]protocol.TextEdit) ([]protocol.DocumentChange, error) {\n\tvar changes []protocol.DocumentChange\n\tfor uri, e := range edits {\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tchanges = append(changes, protocol.DocumentChangeEdit(fh, e))\n\t}\n\treturn changes, nil\n}\n\n// Rename returns a map of TextEdits for each file modified when renaming a\n// given identifier within a package.\nfunc Rename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, rng protocol.Range, newName string) ([]protocol.DocumentChange, error) {\n\tctx, done := event.Start(ctx, \"golang.Rename\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, f.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcur, ok := pgf.Cursor().FindByPos(start, end)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"can't find cursor for selection\")\n\t}\n\n\tif edits, err := renameFuncSignature(ctx, pkg, pgf, start, end, snapshot, cur, f, rng, newName); err != nil {\n\t\treturn nil, err\n\t} else if edits != nil {\n\t\treturn editsToDocChanges(ctx, snapshot, edits)\n\t}\n\n\t// Cursor within package name declaration?\n\t_, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar (\n\t\teditMap   map[protocol.DocumentURI][]diff.Edit\n\t\tnewPkgDir string // declared here so it can be used later to move the package's contents to the new directory\n\t)\n\tif inPackageName {\n\t\tcountRenamePackage.Inc()\n\t\tvar (\n\t\t\tnewPkgName PackageName\n\t\t\tnewPkgPath PackagePath\n\t\t\terr        error\n\t\t)\n\t\tmoveSubpackages := snapshot.Options().RenameMovesSubpackages\n\t\tif newPkgDir, newPkgName, newPkgPath, err = checkPackageRename(pkg, f, newName, moveSubpackages); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\teditMap, err = renamePackage(ctx, snapshot, f, newPkgName, newPkgPath, newPkgDir, moveSubpackages)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\tif !isValidIdentifier(newName) {\n\t\t\treturn nil, fmt.Errorf(\"invalid identifier to rename: %q\", newName)\n\t\t}\n\t\teditMap, err = renameOrdinary(ctx, snapshot, f.URI(), rng, newName)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Convert edits to protocol form.\n\tresult := make(map[protocol.DocumentURI][]protocol.TextEdit)\n\tfor uri, edits := range editMap {\n\t\t// Sort and de-duplicate edits.\n\t\t//\n\t\t// Overlapping edits may arise in local renamings (due\n\t\t// to type switch implicits) and globals ones (due to\n\t\t// processing multiple package variants).\n\t\t//\n\t\t// We assume renaming produces diffs that are all\n\t\t// replacements (no adjacent insertions that might\n\t\t// become reordered) and that are either identical or\n\t\t// non-overlapping.\n\t\tdiff.SortEdits(edits)\n\t\tedits = slices.Compact(edits)\n\n\t\t// TODO(adonovan): the logic above handles repeat edits to the\n\t\t// same file URI (e.g. as a member of package p and p_test) but\n\t\t// is not sufficient to handle file-system level aliasing arising\n\t\t// from symbolic or hard links. For that, we should use a\n\t\t// robustio-FileID-keyed map.\n\t\t// See https://go.dev/cl/457615 for example.\n\t\t// This really occurs in practice, e.g. kubernetes has\n\t\t// vendor/k8s.io/kubectl -> ../../staging/src/k8s.io/kubectl.\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdata, err := fh.Content()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tm := protocol.NewMapper(uri, data)\n\t\ttextedits, err := protocol.EditsFromDiffEdits(m, edits)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[uri] = textedits\n\t}\n\n\tchanges, err := editsToDocChanges(ctx, snapshot, result)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif inPackageName {\n\t\toldDir := f.URI().DirPath()\n\t\tif snapshot.Options().RenameMovesSubpackages {\n\t\t\t// Update the last component of the file's enclosing directory.\n\t\t\tchanges = append(changes, protocol.DocumentChangeRename(\n\t\t\t\tprotocol.URIFromPath(oldDir),\n\t\t\t\tprotocol.URIFromPath(newPkgDir)))\n\t\t} else {\n\t\t\t// Not moving subpackages, so we need to move the files individually\n\t\t\t// Move each file from oldDir to newPkgDir\n\t\t\tfiles, err := os.ReadDir(oldDir)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thasNestedDir := false\n\t\t\tfor _, f := range files {\n\t\t\t\tif !f.IsDir() {\n\t\t\t\t\tchanges = append(changes,\n\t\t\t\t\t\tprotocol.DocumentChangeRename(\n\t\t\t\t\t\t\tprotocol.URIFromPath(filepath.Join(oldDir, f.Name())),\n\t\t\t\t\t\t\tprotocol.URIFromPath(filepath.Join(newPkgDir, f.Name()))),\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\thasNestedDir = true\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Delete oldPkgDir if it is now empty and newPkgDir is not a subdirectory of oldPkgDir.\n\t\t\t// protocol.DeleteFile, when used with a directory, will only delete the directory\n\t\t\t// if it is empty as long as the \"recursive\" option is set to its default value, false.\n\t\t\t// TODO(mkalil): The above should be true according to the LSP spec but in VSCode\n\t\t\t// we could get \"Renamed failed to apply edits\" errors when we include the edit\n\t\t\t// to delete a directory that can't be deleted. For now, check if the oldDir has\n\t\t\t// any nested directories before trying to delete it.\n\t\t\t// TODO(mkalil): We could be deleting more directories. For example, if\n\t\t\t// we have a package at a/b/c/d and we move it to a/z, it only deletes\n\t\t\t// directory d and would leave directories b and c even if they are now\n\t\t\t// empty.\n\t\t\toldPkgDir := f.URI().DirPath()\n\t\t\tif !pathutil.InDir(oldPkgDir, newPkgDir) && !hasNestedDir {\n\t\t\t\tchanges = append(changes,\n\t\t\t\t\tprotocol.DocumentChangeDelete(protocol.URIFromPath(oldPkgDir)))\n\t\t\t}\n\t\t}\n\t}\n\treturn changes, nil\n}\n\n// renameOrdinary renames an ordinary (non-package) name throughout the workspace.\nfunc renameOrdinary(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, rng protocol.Range, newName string) (map[protocol.DocumentURI][]diff.Edit, error) {\n\t// Type-check the referring package and locate the object(s).\n\t//\n\t// Unlike NarrowestPackageForFile, this operation prefers the\n\t// widest variant as, for non-exported identifiers, it is the\n\t// only package we need. (In case you're wondering why\n\t// 'references' doesn't also want the widest variant: it\n\t// computes the union across all variants.)\n\tmps, err := snapshot.MetadataForFile(ctx, uri, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(mps) == 0 {\n\t\treturn nil, fmt.Errorf(\"no package metadata for file %s\", uri)\n\t}\n\twidest := mps[len(mps)-1] // widest variant may include _test.go files\n\tpkgs, err := snapshot.TypeCheck(ctx, widest.ID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpkg := pkgs[0]\n\tpgf, err := pkg.File(uri)\n\tif err != nil {\n\t\treturn nil, err // \"can't happen\"\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(start, end) // cannot fail\n\n\ttargets, err := objectsAt(pkg.TypesInfo(), cur)\n\tif err != nil {\n\t\t// Check if we are renaming an ident inside its doc comment. The call to\n\t\t// objectsAt will have returned an error in this case.\n\t\t// TODO(adonovan): move this logic into objectsAt.\n\t\tvar ok bool\n\t\tcur, ok = docCommentPosToIdent(pgf, start, end, cur)\n\t\tif !ok {\n\t\t\treturn nil, err\n\t\t}\n\t\tid := cur.Node().(*ast.Ident)\n\t\tobj := pkg.TypesInfo().Defs[id]\n\t\tif obj == nil {\n\t\t\treturn nil, fmt.Errorf(\"error fetching types.Object for ident %q\", id.Name)\n\t\t}\n\t\t// Change rename target to the ident.\n\t\ttargets = []objectAt{{obj, cur}}\n\t}\n\n\t// Pick a representative object arbitrarily.\n\t// (All share the same name, pos, and kind.)\n\tobj, node := targets[0].obj, targets[0].cur.Node()\n\tif obj.Name() == newName {\n\t\treturn nil, fmt.Errorf(\"old and new names are the same: %s\", newName)\n\t}\n\tif err := checkRenamable(obj, node); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// This covers the case where we are renaming an embedded field at its\n\t// declaration (see golang/go#45199). Perform the rename on the field's type declaration.\n\tif is[*types.Var](obj) && obj.(*types.Var).Embedded() {\n\t\tif id, ok := node.(*ast.Ident); ok {\n\t\t\t// TypesInfo.Uses contains the embedded field's *types.TypeName.\n\t\t\tif typeName := pkg.TypesInfo().Uses[id]; typeName != nil {\n\t\t\t\tloc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, typeName)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\treturn renameOrdinary(ctx, snapshot, loc.URI, loc.Range, newName)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find objectpath, if object is exported (\"\" otherwise).\n\tvar declObjPath objectpath.Path\n\tif obj.Exported() {\n\t\t// objectpath.For requires the origin of a generic function or type, not an\n\t\t// instantiation (a bug?).\n\t\t//\n\t\t// Note that unlike Funcs, TypeNames are always canonical (they are \"left\"\n\t\t// of the type parameters, unlike methods).\n\t\tswitch obj0 := obj.(type) { // avoid \"obj :=\" since cases reassign the var\n\t\tcase *types.TypeName:\n\t\t\tif _, ok := types.Unalias(obj.Type()).(*types.TypeParam); ok {\n\t\t\t\t// As with capitalized function parameters below, type parameters are\n\t\t\t\t// local.\n\t\t\t\tgoto skipObjectPath\n\t\t\t}\n\t\tcase *types.Func:\n\t\t\tobj = obj0.Origin()\n\t\tcase *types.Var:\n\t\t\t// TODO(adonovan): do vars need the origin treatment too? (issue #58462)\n\n\t\t\t// Function parameter and result vars that are (unusually)\n\t\t\t// capitalized are technically exported, even though they\n\t\t\t// cannot be referenced, because they may affect downstream\n\t\t\t// error messages. But we can safely treat them as local.\n\t\t\t//\n\t\t\t// This is not merely an optimization: the renameExported\n\t\t\t// operation gets confused by such vars. It finds them from\n\t\t\t// objectpath, the classifies them as local vars, but as\n\t\t\t// they came from export data they lack syntax and the\n\t\t\t// correct scope tree (issue #61294).\n\t\t\tif !obj0.IsField() && !typesinternal.IsPackageLevel(obj) {\n\t\t\t\tgoto skipObjectPath\n\t\t\t}\n\t\t}\n\t\tif path, err := objectpath.For(obj); err == nil {\n\t\t\tdeclObjPath = path\n\t\t}\n\tskipObjectPath:\n\t}\n\n\t// Nonexported? Search locally.\n\tif declObjPath == \"\" {\n\t\tvar objects []types.Object\n\t\tfor _, o := range targets {\n\t\t\tobjects = append(objects, o.obj)\n\t\t}\n\n\t\teditMap, _, err := renameObjects(newName, pkg, objects...)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// If the selected identifier is a receiver declaration,\n\t\t// also rename receivers of other methods of the same type\n\t\t// that don't already have the desired name.\n\t\t// Quietly discard edits from any that can't be renamed.\n\t\t//\n\t\t// We interpret renaming the receiver declaration as\n\t\t// intent for the broader renaming; renaming a use of\n\t\t// the receiver effects only the local renaming.\n\t\tif id, ok := cur.Node().(*ast.Ident); ok && id.Pos() == obj.Pos() {\n\t\t\t// enclosing func\n\t\t\tif decl, _ := cursorutil.FirstEnclosing[*ast.FuncDecl](cur); decl != nil {\n\t\t\t\tif decl.Recv != nil &&\n\t\t\t\t\tlen(decl.Recv.List) > 0 &&\n\t\t\t\t\tlen(decl.Recv.List[0].Names) > 0 {\n\t\t\t\t\trecv := pkg.TypesInfo().Defs[decl.Recv.List[0].Names[0]]\n\t\t\t\t\tif recv == obj {\n\t\t\t\t\t\t// TODO(adonovan): simplify the above 7 lines to\n\t\t\t\t\t\t// to \"if obj.(*Var).Kind==Recv\" in go1.25.\n\t\t\t\t\t\trenameReceivers(pkg, recv.(*types.Var), newName, editMap)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn editMap, nil\n\t}\n\n\t// Exported: search globally.\n\t//\n\t// For exported package-level var/const/func/type objects, the\n\t// search scope is just the direct importers.\n\t//\n\t// For exported fields and methods, the scope is the\n\t// transitive rdeps. (The exportedness of the field's struct\n\t// or method's receiver is irrelevant.)\n\ttransitive := false\n\tswitch obj := obj.(type) {\n\tcase *types.TypeName:\n\t\t// Renaming an exported package-level type\n\t\t// requires us to inspect all transitive rdeps\n\t\t// in the event that the type is embedded.\n\t\t//\n\t\t// TODO(adonovan): opt: this is conservative\n\t\t// but inefficient. Instead, expand the scope\n\t\t// of the search only if we actually encounter\n\t\t// an embedding of the type, and only then to\n\t\t// the rdeps of the embedding package.\n\t\tif obj.Parent() == obj.Pkg().Scope() {\n\t\t\ttransitive = true\n\t\t}\n\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\ttransitive = true // field\n\t\t}\n\n\t\t// TODO(adonovan): opt: process only packages that\n\t\t// contain a reference (xrefs) to the target field.\n\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() != nil {\n\t\t\ttransitive = true // method\n\t\t}\n\n\t\t// It's tempting to optimize by skipping\n\t\t// packages that don't contain a reference to\n\t\t// the method in the xrefs index, but we still\n\t\t// need to apply the satisfy check to those\n\t\t// packages to find assignment statements that\n\t\t// might expands the scope of the renaming.\n\t}\n\n\t// Type-check all the packages to inspect.\n\tdeclURI := protocol.URIFromPath(pkg.FileSet().File(obj.Pos()).Name())\n\tpkgs, err = typeCheckReverseDependencies(ctx, snapshot, declURI, transitive)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Apply the renaming to the (initial) object.\n\tdeclPkgPath := PackagePath(obj.Pkg().Path())\n\treturn renameExported(pkgs, declPkgPath, declObjPath, newName)\n}\n\n// renameReceivers renames all receivers of methods of the same named\n// type as recv. The edits of each successful renaming are added to\n// editMap; the failed ones are quietly discarded.\nfunc renameReceivers(pkg *cache.Package, recv *types.Var, newName string, editMap map[protocol.DocumentURI][]diff.Edit) {\n\t_, named := typesinternal.ReceiverNamed(recv)\n\tif named == nil {\n\t\treturn\n\t}\n\n\t// Find receivers of other methods of the same named type.\n\tfor m := range named.Origin().Methods() {\n\t\trecv2 := m.Signature().Recv()\n\t\tif recv2 == recv {\n\t\t\tcontinue // don't re-rename original receiver\n\t\t}\n\t\tif recv2.Name() == newName {\n\t\t\tcontinue // no renaming needed\n\t\t}\n\t\teditMap2, _, err := renameObjects(newName, pkg, recv2)\n\t\tif err != nil {\n\t\t\tcontinue // ignore secondary failures\n\t\t}\n\n\t\t// Since all methods (and their comments)\n\t\t// are disjoint, and don't affect imports,\n\t\t// we can safely assume that all edits are\n\t\t// nonconflicting and disjoint.\n\t\tfor uri, edits := range editMap2 {\n\t\t\teditMap[uri] = append(editMap[uri], edits...)\n\t\t}\n\t}\n}\n\n// typeCheckReverseDependencies returns the type-checked packages for\n// the reverse dependencies of all packages variants containing\n// file declURI. The packages are in some topological order.\n//\n// It includes all variants (even intermediate test variants) for the\n// purposes of computing reverse dependencies, but discards ITVs for\n// the actual renaming work.\n//\n// (This neglects obscure edge cases where a _test.go file changes the\n// selectors used only in an ITV, but life is short. Also sin must be\n// punished.)\nfunc typeCheckReverseDependencies(ctx context.Context, snapshot *cache.Snapshot, declURI protocol.DocumentURI, transitive bool) ([]*cache.Package, error) {\n\tvariants, err := snapshot.MetadataForFile(ctx, declURI, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// variants must include ITVs for the reverse dependency\n\t// computation, but they are filtered out before we typecheck.\n\tallRdeps := make(map[PackageID]*metadata.Package)\n\tfor _, variant := range variants {\n\t\trdeps, err := snapshot.ReverseDependencies(ctx, variant.ID, transitive)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tallRdeps[variant.ID] = variant // include self\n\t\tmaps.Copy(allRdeps, rdeps)\n\t}\n\tvar ids []PackageID\n\tfor id, meta := range allRdeps {\n\t\tif meta.IsIntermediateTestVariant() {\n\t\t\tcontinue\n\t\t}\n\t\tids = append(ids, id)\n\t}\n\n\t// Sort the packages into some topological order of the\n\t// (unfiltered) metadata graph.\n\tmetadata.SortPostOrder(snapshot, ids)\n\n\t// Dependencies must be visited first since they can expand\n\t// the search set. Ideally we would process the (filtered) set\n\t// of packages in the parallel postorder of the snapshot's\n\t// (unfiltered) metadata graph, but this is quite tricky\n\t// without a good graph abstraction.\n\t//\n\t// For now, we visit packages sequentially in order of\n\t// ascending height, like an inverted breadth-first search.\n\t//\n\t// Type checking is by far the dominant cost, so\n\t// overlapping it with renaming may not be worthwhile.\n\treturn snapshot.TypeCheck(ctx, ids...)\n}\n\n// renameExported renames the object denoted by (pkgPath, objPath)\n// within the specified packages, along with any other objects that\n// must be renamed as a consequence. The slice of packages must be\n// topologically ordered.\nfunc renameExported(pkgs []*cache.Package, declPkgPath PackagePath, declObjPath objectpath.Path, newName string) (map[protocol.DocumentURI][]diff.Edit, error) {\n\n\t// A target is a name for an object that is stable across types.Packages.\n\ttype target struct {\n\t\tpkg PackagePath\n\t\tobj objectpath.Path\n\t}\n\n\t// Populate the initial set of target objects.\n\t// This set may grow as we discover the consequences of each renaming.\n\t//\n\t// TODO(adonovan): strictly, each cone of reverse dependencies\n\t// of a single variant should have its own target map that\n\t// monotonically expands as we go up the import graph, because\n\t// declarations in test files can alter the set of\n\t// package-level names and change the meaning of field and\n\t// method selectors. So if we parallelize the graph\n\t// visitation (see above), we should also compute the targets\n\t// as a union of dependencies.\n\t//\n\t// Or we could decide that the logic below is fast enough not\n\t// to need parallelism. In small measurements so far the\n\t// type-checking step is about 95% and the renaming only 5%.\n\ttargets := map[target]bool{{declPkgPath, declObjPath}: true}\n\n\t// Apply the renaming operation to each package.\n\tallEdits := make(map[protocol.DocumentURI][]diff.Edit)\n\tfor _, pkg := range pkgs {\n\n\t\t// Resolved target objects within package pkg.\n\t\tvar objects []types.Object\n\t\tfor t := range targets {\n\t\t\tp := pkg.DependencyTypes(t.pkg)\n\t\t\tif p == nil {\n\t\t\t\tcontinue // indirect dependency of no consequence\n\t\t\t}\n\t\t\tobj, err := objectpath.Object(p, t.obj)\n\t\t\tif err != nil {\n\t\t\t\t// Possibly a method or an unexported type\n\t\t\t\t// that is not reachable through export data?\n\t\t\t\t// See https://github.com/golang/go/issues/60789.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): it seems unsatisfactory that Object\n\t\t\t\t// should return an error for a \"valid\" path. Perhaps\n\t\t\t\t// we should define such paths as invalid and make\n\t\t\t\t// objectpath.For compute reachability?\n\t\t\t\t// Would that be a compatible change?\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tobjects = append(objects, obj)\n\t\t}\n\t\tif len(objects) == 0 {\n\t\t\tcontinue // no targets of consequence to this package\n\t\t}\n\n\t\t// Apply the renaming.\n\t\teditMap, moreObjects, err := renameObjects(newName, pkg, objects...)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// It is safe to concatenate the edits as they are non-overlapping\n\t\t// (or identical, in which case they will be de-duped by Rename).\n\t\tfor uri, edits := range editMap {\n\t\t\tallEdits[uri] = append(allEdits[uri], edits...)\n\t\t}\n\n\t\t// Expand the search set?\n\t\tfor obj := range moreObjects {\n\t\t\tobjpath, err := objectpath.For(obj)\n\t\t\tif err != nil {\n\t\t\t\tcontinue // not exported\n\t\t\t}\n\t\t\ttarget := target{PackagePath(obj.Pkg().Path()), objpath}\n\t\t\ttargets[target] = true\n\n\t\t\t// TODO(adonovan): methods requires dynamic\n\t\t\t// programming of the product targets x\n\t\t\t// packages as any package might add a new\n\t\t\t// target (from a forward dep) as a\n\t\t\t// consequence, and any target might imply a\n\t\t\t// new set of rdeps. See golang/go#58461.\n\t\t}\n\t}\n\n\treturn allEdits, nil\n}\n\n// renamePackage renames package declarations, imports, and go.mod files.\n//\n// f is the file originating the rename, and therefore f.URI().Dir() is the\n// current package directory. newName, newPath, and newDir describe the renaming.\nfunc renamePackage(ctx context.Context, s *cache.Snapshot, f file.Handle, newName PackageName, newPath PackagePath, newDir string, moveSubpackages bool) (map[protocol.DocumentURI][]diff.Edit, error) {\n\t// Rename the package decl and all imports.\n\trenamingEdits := make(map[protocol.DocumentURI][]diff.Edit)\n\terr := updatePackageDeclsAndImports(ctx, s, f, newName, newPath, renamingEdits, moveSubpackages)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = updateModFiles(ctx, s, f.URI().DirPath(), newDir, renamingEdits, moveSubpackages)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn renamingEdits, nil\n}\n\n// Update any affected replace directives in go.mod files.\n// TODO(adonovan): should this operate on all go.mod files,\n// irrespective of whether they are included in the workspace?\nfunc updateModFiles(ctx context.Context, s *cache.Snapshot, oldDir string, newPkgDir string, renamingEdits map[protocol.DocumentURI][]diff.Edit, moveSubpackages bool) error {\n\tmodFiles := s.View().ModFiles()\n\tfor _, m := range modFiles {\n\t\tfh, err := s.ReadFile(ctx, m)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpm, err := s.ParseMod(ctx, fh)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tmodFileDir := pm.URI.DirPath()\n\t\taffectedReplaces := []*modfile.Replace{}\n\n\t\t// Check if any replace directives need to be fixed\n\t\tfor _, r := range pm.File.Replace {\n\t\t\tif !strings.HasPrefix(r.New.Path, \"/\") && !strings.HasPrefix(r.New.Path, \"./\") && !strings.HasPrefix(r.New.Path, \"../\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treplacedDir := r.New.Path\n\t\t\tif strings.HasPrefix(r.New.Path, \"./\") || strings.HasPrefix(r.New.Path, \"../\") {\n\t\t\t\treplacedDir = filepath.Join(modFileDir, r.New.Path)\n\t\t\t}\n\n\t\t\t// TODO: Is there a risk of converting a '\\' delimited replacement to a '/' delimited replacement?\n\n\t\t\tif moveSubpackages && !strings.HasPrefix(filepath.ToSlash(replacedDir)+\"/\", filepath.ToSlash(oldDir)+\"/\") ||\n\t\t\t\t!moveSubpackages && !(filepath.ToSlash(replacedDir) == filepath.ToSlash(oldDir)) {\n\t\t\t\tcontinue //not affected by the package renanming\n\t\t\t}\n\n\t\t\taffectedReplaces = append(affectedReplaces, r)\n\t\t}\n\n\t\tif len(affectedReplaces) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tcopied, err := modfile.Parse(\"\", pm.Mapper.Content, nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfor _, r := range affectedReplaces {\n\t\t\treplacedDir := r.New.Path\n\t\t\tif strings.HasPrefix(r.New.Path, \"./\") || strings.HasPrefix(r.New.Path, \"../\") {\n\t\t\t\treplacedDir = filepath.Join(modFileDir, r.New.Path)\n\t\t\t}\n\n\t\t\tsuffix := strings.TrimPrefix(replacedDir, oldDir)\n\n\t\t\tnewReplacedPath, err := filepath.Rel(modFileDir, newPkgDir+suffix)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tnewReplacedPath = filepath.ToSlash(newReplacedPath)\n\n\t\t\tif !strings.HasPrefix(newReplacedPath, \"/\") && !strings.HasPrefix(newReplacedPath, \"../\") {\n\t\t\t\tnewReplacedPath = \"./\" + newReplacedPath\n\t\t\t}\n\n\t\t\tif err := copied.AddReplace(r.Old.Path, \"\", newReplacedPath, \"\"); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tcopied.Cleanup()\n\t\tnewContent, err := copied.Format()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Calculate the edits to be made due to the change.\n\t\tedits := diff.Bytes(pm.Mapper.Content, newContent)\n\t\trenamingEdits[pm.URI] = append(renamingEdits[pm.URI], edits...)\n\t}\n\treturn nil\n}\n\n// updatePackageDeclsAndImports computes all workspace edits required to rename the package\n// described by the given metadata, to newName, by renaming its package\n// directory.\n//\n// It updates package clauses and import paths for the renamed package as well\n// as any other packages affected by the directory renaming among all packages\n// known to the snapshot.\nfunc updatePackageDeclsAndImports(ctx context.Context, s *cache.Snapshot, f file.Handle, newName PackageName, newPkgPath PackagePath, renamingEdits map[protocol.DocumentURI][]diff.Edit, moveSubpackages bool) error {\n\tif strings.HasSuffix(string(newName), \"_test\") {\n\t\treturn fmt.Errorf(\"cannot rename to _test package\")\n\t}\n\n\t// We need metadata for the relevant package and module paths.\n\t// These should be the same for all packages containing the file.\n\tmeta, err := s.NarrowestMetadataForFile(ctx, f.URI())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\toldPkgPath := meta.PkgPath\n\tif meta.Module == nil {\n\t\treturn fmt.Errorf(\"cannot rename package: missing module information for package %q\", meta.PkgPath)\n\t}\n\tmodulePath := PackagePath(meta.Module.Path)\n\tif modulePath == oldPkgPath {\n\t\treturn fmt.Errorf(\"cannot rename package: module path %q is the same as the package path, so renaming the package directory would have no effect\", modulePath)\n\t}\n\n\t// We must inspect all packages, not just direct importers,\n\t// because we might also rename subpackages, which may be unrelated.\n\t// (If the renamed package imports a subpackage it may require\n\t// edits to both its package and import decls.)\n\tallMetadata, err := s.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Rename package and import declarations in all relevant packages.\n\tfor _, mp := range allMetadata {\n\t\t// Special case: x_test packages for the renamed package will not have the\n\t\t// package path as a dir prefix, but still need their package clauses\n\t\t// renamed.\n\t\tif mp.PkgPath == oldPkgPath+\"_test\" {\n\t\t\tif err := renamePackageClause(ctx, mp, s, newName+\"_test\", renamingEdits); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Subtle: check this condition before checking for valid module info\n\t\t// below, because we should not fail this operation if unrelated packages\n\t\t// lack module info.\n\t\tif moveSubpackages && !pathutil.InDir(filepath.FromSlash(string(oldPkgPath)), filepath.FromSlash(string(mp.PkgPath))) ||\n\t\t\t!moveSubpackages && mp.PkgPath != oldPkgPath {\n\t\t\tcontinue // not affected by the package renaming\n\t\t}\n\n\t\tif mp.Module == nil {\n\t\t\t// This check will always fail under Bazel.\n\t\t\treturn fmt.Errorf(\"cannot rename package: missing module information for package %q\", mp.PkgPath)\n\t\t}\n\n\t\tif modulePath != PackagePath(mp.Module.Path) {\n\t\t\tcontinue // don't edit imports if nested package and renaming package have different module paths\n\t\t}\n\n\t\t// Renaming a package consists of changing its import path and package name.\n\t\tsuffix := strings.TrimPrefix(string(mp.PkgPath), string(oldPkgPath))\n\t\tnewImportPath := string(newPkgPath) + suffix\n\n\t\tpkgName := mp.Name\n\t\tif mp.PkgPath == oldPkgPath {\n\t\t\tpkgName = newName\n\n\t\t\tif err := renamePackageClause(ctx, mp, s, newName, renamingEdits); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\timp := ImportPath(newImportPath) // TODO(adonovan): what if newImportPath has vendor/ prefix?\n\t\tif err := renameImports(ctx, s, mp, imp, pkgName, renamingEdits); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// renamePackageClause computes edits renaming the package clause of files in\n// the package described by the given metadata, to newName.\n//\n// Edits are written into the edits map.\nfunc renamePackageClause(ctx context.Context, mp *metadata.Package, snapshot *cache.Snapshot, newName PackageName, edits map[protocol.DocumentURI][]diff.Edit) error {\n\t// Rename internal references to the package in the renaming package.\n\tfor _, uri := range mp.CompiledGoFiles {\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif f.File.Name == nil {\n\t\t\tcontinue // no package declaration\n\t\t}\n\n\t\tedit, err := posEdit(f.Tok, f.File.Name.Pos(), f.File.Name.End(), string(newName))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tedits[f.URI] = append(edits[f.URI], edit)\n\t}\n\n\treturn nil\n}\n\n// renameImports computes the set of edits to imports resulting from renaming\n// the package described by the given metadata, to a package with import path\n// newPath and name newName.\n//\n// Edits are written into the edits map.\nfunc renameImports(ctx context.Context, snapshot *cache.Snapshot, mp *metadata.Package, newPath ImportPath, newName PackageName, allEdits map[protocol.DocumentURI][]diff.Edit) error {\n\trdeps, err := snapshot.ReverseDependencies(ctx, mp.ID, false) // find direct importers\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Pass 1: rename import paths in import declarations.\n\tneedsTypeCheck := make(map[PackageID][]protocol.DocumentURI)\n\tfor _, rdep := range rdeps {\n\t\tif rdep.IsIntermediateTestVariant() {\n\t\t\tcontinue // for renaming, these variants are redundant\n\t\t}\n\n\t\tfor _, uri := range rdep.CompiledGoFiles {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif f.File.Name == nil {\n\t\t\t\tcontinue // no package declaration\n\t\t\t}\n\t\t\tfor _, imp := range f.File.Imports {\n\t\t\t\tif rdep.DepsByImpPath[metadata.UnquoteImportPath(imp)] != mp.ID {\n\t\t\t\t\tcontinue // not the import we're looking for\n\t\t\t\t}\n\n\t\t\t\t// If we are moving a package from a non-internal directory to\n\t\t\t\t// an internal directory, and there is an importer located in a\n\t\t\t\t// different module, then it is an invalid import.\n\t\t\t\t//\n\t\t\t\t// We do not prevent moves from an internal directory to a\n\t\t\t\t// non-internal directory.\n\t\t\t\tif !metadata.IsValidImport(rdep.PkgPath, metadata.PackagePath(newPath), snapshot.View().Type() != cache.GoPackagesDriverView) {\n\t\t\t\t\treturn fmt.Errorf(\"invalid: package move would result in illegal internal import\")\n\t\t\t\t}\n\n\t\t\t\t// If the import does not explicitly specify\n\t\t\t\t// a local name, then we need to invoke the\n\t\t\t\t// type checker to locate references to update.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): is this actually true?\n\t\t\t\t// Renaming an import with a local name can still\n\t\t\t\t// cause conflicts: shadowing of built-ins, or of\n\t\t\t\t// package-level decls in the same or another file.\n\t\t\t\tif imp.Name == nil {\n\t\t\t\t\tneedsTypeCheck[rdep.ID] = append(needsTypeCheck[rdep.ID], uri)\n\t\t\t\t}\n\n\t\t\t\t// Create text edit for the import path (string literal).\n\t\t\t\tedit, err := posEdit(f.Tok, imp.Path.Pos(), imp.Path.End(), strconv.Quote(string(newPath)))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tallEdits[uri] = append(allEdits[uri], edit)\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the imported package's name hasn't changed,\n\t// we don't need to rename references within each file.\n\tif newName == mp.Name {\n\t\treturn nil\n\t}\n\n\t// Pass 2: rename local name (types.PkgName) of imported\n\t// package throughout one or more files of the package.\n\tids := make([]PackageID, 0, len(needsTypeCheck))\n\tfor id := range needsTypeCheck {\n\t\tids = append(ids, id)\n\t}\n\tpkgs, err := snapshot.TypeCheck(ctx, ids...)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor i, id := range ids {\n\t\tpkg := pkgs[i]\n\t\tfor _, uri := range needsTypeCheck[id] {\n\t\t\tf, err := pkg.File(uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, imp := range f.File.Imports {\n\t\t\t\tif imp.Name != nil {\n\t\t\t\t\tcontinue // has explicit local name\n\t\t\t\t}\n\t\t\t\tif rdeps[id].DepsByImpPath[metadata.UnquoteImportPath(imp)] != mp.ID {\n\t\t\t\t\tcontinue // not the import we're looking for\n\t\t\t\t}\n\n\t\t\t\tpkgname, ok := pkg.TypesInfo().Implicits[imp].(*types.PkgName)\n\t\t\t\tif !ok {\n\t\t\t\t\t// \"can't happen\", but be defensive (#71656)\n\t\t\t\t\treturn fmt.Errorf(\"internal error: missing type information for %s import at %s\",\n\t\t\t\t\t\timp.Path.Value, safetoken.StartPosition(pkg.FileSet(), imp.Pos()))\n\t\t\t\t}\n\n\t\t\t\tpkgScope := pkg.Types().Scope()\n\t\t\t\tfileScope := pkg.TypesInfo().Scopes[f.File]\n\n\t\t\t\tlocalName := string(newName)\n\t\t\t\ttry := 0\n\n\t\t\t\t// Keep trying with fresh names until one succeeds.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): fix: this loop is not sufficient to choose a name\n\t\t\t\t// that is guaranteed to be conflict-free; renameObj may still fail.\n\t\t\t\t// So the retry loop should be around renameObj, and we shouldn't\n\t\t\t\t// bother with scopes here.\n\t\t\t\tfor fileScope.Lookup(localName) != nil || pkgScope.Lookup(localName) != nil {\n\t\t\t\t\ttry++\n\t\t\t\t\tlocalName = fmt.Sprintf(\"%s%d\", newName, try)\n\t\t\t\t}\n\n\t\t\t\t// renameObj detects various conflicts, including:\n\t\t\t\t// - new name conflicts with a package-level decl in this file;\n\t\t\t\t// - new name hides a package-level decl in another file that\n\t\t\t\t//   is actually referenced in this file;\n\t\t\t\t// - new name hides a built-in that is actually referenced\n\t\t\t\t//   in this file;\n\t\t\t\t// - a reference in this file to the old package name would\n\t\t\t\t//   become shadowed by an intervening declaration that\n\t\t\t\t//   uses the new name.\n\t\t\t\t// It returns the edits if no conflict was detected.\n\t\t\t\teditMap, _, err := renameObjects(localName, pkg, pkgname)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\t// If the chosen local package name matches the package's\n\t\t\t\t// new name, delete the change that would have inserted\n\t\t\t\t// an explicit local name, which is always the lexically\n\t\t\t\t// first change.\n\t\t\t\tif localName == string(newName) {\n\t\t\t\t\tedits, ok := editMap[uri]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn fmt.Errorf(\"internal error: no changes for %s\", uri)\n\t\t\t\t\t}\n\t\t\t\t\tdiff.SortEdits(edits)\n\t\t\t\t\teditMap[uri] = edits[1:]\n\t\t\t\t}\n\t\t\t\tfor uri, edits := range editMap {\n\t\t\t\t\tallEdits[uri] = append(allEdits[uri], edits...)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// renameObjects computes the edits to the type-checked syntax package pkg\n// required to rename a set of target objects to newName.\n//\n// It also returns the set of objects that were found (due to\n// corresponding methods and embedded fields) to require renaming as a\n// consequence of the requested renamings.\n//\n// It returns an error if the renaming would cause a conflict.\nfunc renameObjects(newName string, pkg *cache.Package, targets ...types.Object) (map[protocol.DocumentURI][]diff.Edit, map[types.Object]bool, error) {\n\tr := renamer{\n\t\tpkg:          pkg,\n\t\tobjsToUpdate: make(map[types.Object]bool),\n\t\tfrom:         targets[0].Name(),\n\t\tto:           newName,\n\t}\n\n\t// A renaming initiated at an interface method indicates the\n\t// intention to rename abstract and concrete methods as needed\n\t// to preserve assignability.\n\t// TODO(adonovan): pull this into the caller.\n\tfor _, obj := range targets {\n\t\tif obj, ok := obj.(*types.Func); ok {\n\t\t\trecv := obj.Signature().Recv()\n\t\t\tif recv != nil && types.IsInterface(recv.Type().Underlying()) {\n\t\t\t\tr.changeMethods = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check that the renaming of the identifier is ok.\n\tfor _, obj := range targets {\n\t\tr.check(obj)\n\t\tif len(r.conflicts) > 0 {\n\t\t\t// Stop at first error.\n\t\t\treturn nil, nil, fmt.Errorf(\"%s\", strings.Join(r.conflicts, \"\\n\"))\n\t\t}\n\t}\n\n\teditMap, err := r.update()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Remove initial targets so that only 'consequences' remain.\n\tfor _, obj := range targets {\n\t\tdelete(r.objsToUpdate, obj)\n\t}\n\treturn editMap, r.objsToUpdate, nil\n}\n\n// Rename all references to the target objects.\nfunc (r *renamer) update() (map[protocol.DocumentURI][]diff.Edit, error) {\n\tresult := make(map[protocol.DocumentURI][]diff.Edit)\n\n\t// shouldUpdate reports whether obj is one of (or an\n\t// instantiation of one of) the target objects.\n\tshouldUpdate := func(obj types.Object) bool {\n\t\treturn containsOrigin(r.objsToUpdate, obj)\n\t}\n\n\t// Find all identifiers in the package that define or use a\n\t// renamed object. We iterate over info as it is more efficient\n\t// than calling ast.Inspect for each of r.pkg.CompiledGoFiles().\n\ttype item struct {\n\t\tnode  ast.Node // Ident, ImportSpec (obj=PkgName), or CaseClause (obj=Var)\n\t\tobj   types.Object\n\t\tisDef bool\n\t}\n\tvar items []item\n\tinfo := r.pkg.TypesInfo()\n\tfor id, obj := range info.Uses {\n\t\tif shouldUpdate(obj) {\n\t\t\titems = append(items, item{id, obj, false})\n\t\t}\n\t}\n\tfor id, obj := range info.Defs {\n\t\tif shouldUpdate(obj) {\n\t\t\titems = append(items, item{id, obj, true})\n\t\t}\n\t}\n\tfor node, obj := range info.Implicits {\n\t\tif shouldUpdate(obj) {\n\t\t\tswitch node.(type) {\n\t\t\tcase *ast.ImportSpec, *ast.CaseClause:\n\t\t\t\titems = append(items, item{node, obj, true})\n\t\t\t}\n\t\t}\n\t}\n\tsort.Slice(items, func(i, j int) bool {\n\t\treturn items[i].node.Pos() < items[j].node.Pos()\n\t})\n\n\t// Update each identifier, and its doc comment if it is a declaration.\n\tfor _, item := range items {\n\t\tpgf, err := r.pkg.FileEnclosing(item.node.Pos())\n\t\tif err != nil {\n\t\t\tbug.Reportf(\"edit does not belong to syntax of package %q: %v\", r.pkg, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Renaming a types.PkgName may result in the addition or removal of an identifier,\n\t\t// so we deal with this separately.\n\t\tif pkgName, ok := item.obj.(*types.PkgName); ok && item.isDef {\n\t\t\tedit, err := r.updatePkgName(pgf, pkgName)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tresult[pgf.URI] = append(result[pgf.URI], edit)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Workaround the unfortunate lack of a Var object\n\t\t// for x in \"switch x := expr.(type) {}\" by adjusting\n\t\t// the case clause to the switch ident.\n\t\t// This may result in duplicate edits, but we de-dup later.\n\t\tif _, ok := item.node.(*ast.CaseClause); ok {\n\t\t\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, item.obj.Pos(), item.obj.Pos())\n\t\t\titem.node = path[0].(*ast.Ident)\n\t\t}\n\n\t\t// Replace the identifier with r.to.\n\t\tedit, err := posEdit(pgf.Tok, item.node.Pos(), item.node.End(), r.to)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresult[pgf.URI] = append(result[pgf.URI], edit)\n\n\t\tif !item.isDef { // uses do not have doc comments to update.\n\t\t\tcontinue\n\t\t}\n\n\t\tcur, _ := pgf.Cursor().FindNode(item.node) // can't fail\n\t\tdoc := docComment(pgf, cur)\n\t\tif doc == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Perform the rename in doc comments declared in the original package.\n\t\t// go/parser strips out \\r\\n returns from the comment text, so go\n\t\t// line-by-line through the comment text to get the correct positions.\n\t\tdocRegexp := regexp.MustCompile(`\\b` + r.from + `\\b`) // valid identifier => valid regexp\n\t\tfor _, comment := range doc.List {\n\t\t\tif isDirective(comment.Text) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// TODO(adonovan): why are we looping over lines?\n\t\t\t// Just run the loop body once over the entire multiline comment.\n\t\t\tlines := strings.Split(comment.Text, \"\\n\")\n\t\t\ttokFile := pgf.Tok\n\t\t\tcommentLine := safetoken.Line(tokFile, comment.Pos())\n\t\t\turi := protocol.URIFromPath(tokFile.Name())\n\t\t\tfor i, line := range lines {\n\t\t\t\tlineStart := comment.Pos()\n\t\t\t\tif i > 0 {\n\t\t\t\t\tlineStart = tokFile.LineStart(commentLine + i)\n\t\t\t\t}\n\t\t\t\tfor _, locs := range docRegexp.FindAllIndex([]byte(line), -1) {\n\t\t\t\t\tedit, err := posEdit(tokFile, lineStart+token.Pos(locs[0]), lineStart+token.Pos(locs[1]), r.to)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err // can't happen\n\t\t\t\t\t}\n\t\t\t\t\tresult[uri] = append(result[uri], edit)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdocLinkEdits, err := r.updateCommentDocLinks()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor uri, edits := range docLinkEdits {\n\t\tresult[uri] = append(result[uri], edits...)\n\t}\n\n\treturn result, nil\n}\n\n// updateCommentDocLinks updates each doc comment in the package\n// that refers to one of the renamed objects using a doc link\n// (https://golang.org/doc/comment#doclinks) such as \"[pkg.Type.Method]\".\nfunc (r *renamer) updateCommentDocLinks() (map[protocol.DocumentURI][]diff.Edit, error) {\n\tresult := make(map[protocol.DocumentURI][]diff.Edit)\n\tvar docRenamers []*docLinkRenamer\n\tfor obj := range r.objsToUpdate {\n\t\tif _, ok := obj.(*types.PkgName); ok {\n\t\t\t// The dot package name will not be referenced\n\t\t\tif obj.Name() == \".\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tdocRenamers = append(docRenamers, &docLinkRenamer{\n\t\t\t\tisDep:       false,\n\t\t\t\tisPkgOrType: true,\n\t\t\t\tfile:        r.pkg.FileSet().File(obj.Pos()),\n\t\t\t\tregexp:      docLinkPattern(\"\", \"\", obj.Name(), true),\n\t\t\t\tto:          r.to,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif !obj.Exported() {\n\t\t\tcontinue\n\t\t}\n\t\trecvName := \"\"\n\t\t// Doc links can reference only exported package-level objects\n\t\t// and methods of exported package-level named types.\n\t\tif !typesinternal.IsPackageLevel(obj) {\n\t\t\tobj, isFunc := obj.(*types.Func)\n\t\t\tif !isFunc {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trecv := obj.Signature().Recv()\n\t\t\tif recv == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\tif named == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Doc links can't reference interface methods.\n\t\t\tif types.IsInterface(named.Underlying()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tname := named.Origin().Obj()\n\t\t\tif !name.Exported() || !typesinternal.IsPackageLevel(name) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trecvName = name.Name()\n\t\t}\n\n\t\t// Qualify objects from other packages.\n\t\tpkgName := \"\"\n\t\tif r.pkg.Types() != obj.Pkg() {\n\t\t\tpkgName = obj.Pkg().Name()\n\t\t}\n\t\t_, isTypeName := obj.(*types.TypeName)\n\t\tdocRenamers = append(docRenamers, &docLinkRenamer{\n\t\t\tisDep:       r.pkg.Types() != obj.Pkg(),\n\t\t\tisPkgOrType: isTypeName,\n\t\t\tpackagePath: obj.Pkg().Path(),\n\t\t\tpackageName: pkgName,\n\t\t\trecvName:    recvName,\n\t\t\tobjName:     obj.Name(),\n\t\t\tregexp:      docLinkPattern(pkgName, recvName, obj.Name(), isTypeName),\n\t\t\tto:          r.to,\n\t\t})\n\t}\n\tfor _, pgf := range r.pkg.CompiledGoFiles() {\n\t\tfor _, d := range docRenamers {\n\t\t\tedits, err := d.update(pgf)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif len(edits) > 0 {\n\t\t\t\tresult[pgf.URI] = append(result[pgf.URI], edits...)\n\t\t\t}\n\t\t}\n\t}\n\treturn result, nil\n}\n\n// docLinkPattern returns a regular expression that matches doclinks in comments.\n// It has one submatch that indicates the symbol to be updated.\nfunc docLinkPattern(pkgName, recvName, objName string, isPkgOrType bool) *regexp.Regexp {\n\t// The doc link may contain a leading star, e.g. [*bytes.Buffer].\n\tpattern := `\\[\\*?`\n\tif pkgName != \"\" {\n\t\tpattern += pkgName + `\\.`\n\t}\n\tif recvName != \"\" {\n\t\tpattern += recvName + `\\.`\n\t}\n\t// The first submatch is object name.\n\tpattern += `(` + objName + `)`\n\t// If the object is a *types.TypeName or *types.PkgName, also need\n\t// match the objects referenced by them, so add `(\\.\\w+)*`.\n\tif isPkgOrType {\n\t\tpattern += `(?:\\.\\w+)*`\n\t}\n\t// There are two type of link in comments:\n\t//   1. url link. e.g. [text]: url\n\t//   2. doc link. e.g. [pkg.Name]\n\t// in order to only match the doc link, add `([^:]|$)` in the end.\n\tpattern += `\\](?:[^:]|$)`\n\n\treturn regexp.MustCompile(pattern)\n}\n\n// A docLinkRenamer renames doc links of forms such as these:\n//\n//\t[Func]\n//\t[pkg.Func]\n//\t[RecvType.Method]\n//\t[*Type]\n//\t[*pkg.Type]\n//\t[*pkg.RecvType.Method]\ntype docLinkRenamer struct {\n\tisDep       bool // object is from a dependency package\n\tisPkgOrType bool // object is *types.PkgName or *types.TypeName\n\tpackagePath string\n\tpackageName string // e.g. \"pkg\"\n\trecvName    string // e.g. \"RecvType\"\n\tobjName     string // e.g. \"Func\", \"Type\", \"Method\"\n\tto          string // new name\n\tregexp      *regexp.Regexp\n\n\tfile *token.File // enclosing file, if renaming *types.PkgName\n}\n\n// update updates doc links in the package level comments.\nfunc (r *docLinkRenamer) update(pgf *parsego.File) (result []diff.Edit, err error) {\n\tif r.file != nil && r.file != pgf.Tok {\n\t\treturn nil, nil\n\t}\n\tpattern := r.regexp\n\t// If the object is in dependency package,\n\t// the imported name in the file may be different from the original package name\n\tif r.isDep {\n\t\tfor _, spec := range pgf.File.Imports {\n\t\t\timportPath, _ := strconv.Unquote(spec.Path.Value)\n\t\t\tif importPath == r.packagePath {\n\t\t\t\t// Ignore blank imports\n\t\t\t\tif spec.Name == nil || spec.Name.Name == \"_\" || spec.Name.Name == \".\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif spec.Name.Name != r.packageName {\n\t\t\t\t\tpattern = docLinkPattern(spec.Name.Name, r.recvName, r.objName, r.isPkgOrType)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tvar edits []diff.Edit\n\tupdateDocLinks := func(doc *ast.CommentGroup) error {\n\t\tif doc != nil {\n\t\t\tfor _, c := range doc.List {\n\t\t\t\tfor _, locs := range pattern.FindAllStringSubmatchIndex(c.Text, -1) {\n\t\t\t\t\t// The first submatch is the object name, so the locs[2:4] is the index of object name.\n\t\t\t\t\tedit, err := posEdit(pgf.Tok, c.Pos()+token.Pos(locs[2]), c.Pos()+token.Pos(locs[3]), r.to)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tedits = append(edits, edit)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Update package doc comments.\n\terr = updateDocLinks(pgf.File.Doc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, decl := range pgf.File.Decls {\n\t\tvar doc *ast.CommentGroup\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.GenDecl:\n\t\t\tdoc = decl.Doc\n\t\tcase *ast.FuncDecl:\n\t\t\tdoc = decl.Doc\n\t\t}\n\t\terr = updateDocLinks(doc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn edits, nil\n}\n\n// docComment returns the doc for an identifier within the specified file.\nfunc docComment(pgf *parsego.File, curId inspector.Cursor) *ast.CommentGroup {\n\t// (Strictly it needn't be an identifier; only its Pos is used.)\n\tid := curId.Node().(*ast.Ident)\n\tfor cur := range curId.Enclosing() {\n\t\tswitch decl := cur.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\treturn decl.Doc\n\t\tcase *ast.Field:\n\t\t\treturn decl.Doc\n\t\tcase *ast.GenDecl:\n\t\t\treturn decl.Doc\n\t\t// For {Type,Value}Spec, if the doc on the spec is absent,\n\t\t// search for the enclosing GenDecl\n\t\tcase *ast.TypeSpec:\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\tcase *ast.ValueSpec:\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\tcase *ast.Ident:\n\t\tcase *ast.AssignStmt:\n\t\t\t// *ast.AssignStmt doesn't have an associated comment group.\n\t\t\t// So, we try to find a comment just before the identifier.\n\n\t\t\t// Try to find a comment group only for short variable declarations (:=).\n\t\t\tif decl.Tok != token.DEFINE {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tidentLine := safetoken.Line(pgf.Tok, id.Pos())\n\t\t\tfor _, comment := range pgf.File.Comments {\n\t\t\t\tif comment.Pos() > id.Pos() {\n\t\t\t\t\t// Comment is after the identifier.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tlastCommentLine := safetoken.Line(pgf.Tok, comment.End())\n\t\t\t\tif lastCommentLine+1 == identLine {\n\t\t\t\t\treturn comment\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn nil\n}\n\n// docCommentPosToIdent returns a cursor for the identifier whose doc\n// comment contains pos, if any. The pos must be within an occurrence\n// of the identifier's name, otherwise it returns zero.\nfunc docCommentPosToIdent(pgf *parsego.File, start, end token.Pos, cur inspector.Cursor) (inspector.Cursor, bool) {\n\tfor curId := range cur.Preorder((*ast.Ident)(nil)) {\n\t\tid := curId.Node().(*ast.Ident)\n\t\tif start > id.Pos() {\n\t\t\tcontinue // Doc comments are not located after an ident.\n\t\t}\n\t\tdoc := docComment(pgf, curId)\n\t\tif doc == nil || !(doc.Pos() <= start && end < doc.End()) {\n\t\t\tcontinue\n\t\t}\n\n\t\tdocRegexp := regexp.MustCompile(`\\b` + id.Name + `\\b`)\n\t\tfor _, comment := range doc.List {\n\t\t\tif isDirective(comment.Text) || !(comment.Pos() <= start && end < comment.End()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcommentStart := comment.Pos()\n\t\t\ttext, err := pgf.NodeText(comment)\n\t\t\tif err != nil {\n\t\t\t\treturn inspector.Cursor{}, false\n\t\t\t}\n\t\t\tfor _, locs := range docRegexp.FindAllIndex(text, -1) {\n\t\t\t\tmatchStart := commentStart + token.Pos(locs[0])\n\t\t\t\tmatchEnd := commentStart + token.Pos(locs[1])\n\t\t\t\tif matchStart <= start && end <= matchEnd {\n\t\t\t\t\treturn curId, true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn inspector.Cursor{}, false\n}\n\n// updatePkgName returns the updates to rename a pkgName in the import spec by\n// only modifying the package name portion of the import declaration.\nfunc (r *renamer) updatePkgName(pgf *parsego.File, pkgName *types.PkgName) (diff.Edit, error) {\n\t// Modify ImportSpec syntax to add or remove the Name as needed.\n\tpath, _ := goastutil.PathEnclosingInterval(pgf.File, pkgName.Pos(), pkgName.Pos())\n\tif len(path) < 2 {\n\t\treturn diff.Edit{}, fmt.Errorf(\"no path enclosing interval for %s\", pkgName.Name())\n\t}\n\tspec, ok := path[1].(*ast.ImportSpec)\n\tif !ok {\n\t\treturn diff.Edit{}, fmt.Errorf(\"failed to update PkgName for %s\", pkgName.Name())\n\t}\n\n\tnewText := \"\"\n\tif pkgName.Imported().Name() != r.to {\n\t\tnewText = r.to + \" \"\n\t}\n\n\t// Replace the portion (possibly empty) of the spec before the path:\n\t//     local \"path\"      or      \"path\"\n\t//   ->      <-                -><-\n\treturn posEdit(pgf.Tok, spec.Pos(), spec.Path.Pos(), newText)\n}\n\n// parsePackageNameDecl is a convenience function that parses and\n// returns the package name declaration of file fh, and reports\n// whether the position ppos lies within it.\n//\n// Note: also used by references.\nfunc parsePackageNameDecl(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (*parsego.File, bool, error) {\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\t// Careful: because we used parsego.Header,\n\t// pgf.Pos(ppos) may be beyond EOF => (0, err).\n\tstart, end, _ := pgf.RangePos(rng)\n\treturn pgf, astutil.NodeContains(pgf.File.Name, astutil.RangeOf(start, end)), nil\n}\n\n// posEdit returns an edit to replace the (start, end) range of tf with 'new'.\nfunc posEdit(tf *token.File, start, end token.Pos, new string) (diff.Edit, error) {\n\tstartOffset, endOffset, err := safetoken.Offsets(tf, start, end)\n\tif err != nil {\n\t\treturn diff.Edit{}, err\n\t}\n\treturn diff.Edit{Start: startOffset, End: endOffset, New: new}, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/rename_check.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n// Taken from golang.org/x/tools/refactor/rename.\n\npackage golang\n\n// This file defines the conflict-checking portion of the rename operation.\n//\n// The renamer works on a single package of type-checked syntax, and\n// is called in parallel for all necessary packages in the workspace,\n// possibly up to the transitive reverse dependencies of the\n// declaration. Finally the union of all edits and errors is computed.\n//\n// Renaming one object may entail renaming of others. For example:\n//\n// - An embedded field couples a Var (field) and a TypeName.\n//   So, renaming either one requires renaming the other.\n//   If the initial object is an embedded field, we must add its\n//   TypeName (and its enclosing package) to the renaming set;\n//   this is easily discovered at the outset.\n//\n//   Conversely, if the initial object is a TypeName, we must observe\n//   whether any of its references (from directly importing packages)\n//   is coincident with an embedded field Var and, if so, initiate a\n//   renaming of it.\n//\n// - A method of an interface type is coupled to all corresponding\n//   methods of types that are assigned to the interface (as\n//   discovered by the 'satisfy' pass). As a matter of usability, we\n//   require that such renamings be initiated from the interface\n//   method, not the concrete method.\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\n// errorf reports an error (e.g. conflict) and prevents file modification.\nfunc (r *renamer) errorf(pos token.Pos, format string, args ...any) {\n\t// Conflict error messages in the old gorename tool (whence this\n\t// logic originated) contain rich information associated with\n\t// multiple source lines, such as:\n\t//\n\t//   p/a.go:1:2: renaming \"x\" to \"y\" here\n\t//   p/b.go:3:4: \\t would cause this reference to \"y\"\n\t//   p/c.go:5:5: \\t to become shadowed by this intervening declaration.\n\t//\n\t// Unfortunately LSP provides no means to transmit the\n\t// structure of this error, so we format the positions briefly\n\t// using dir/file.go where dir is the base name of the parent\n\t// directory.\n\n\tvar conflict strings.Builder\n\n\t// Add prefix of (truncated) position.\n\tif pos != token.NoPos {\n\t\t// TODO(adonovan): skip position of first error if it is\n\t\t// on the same line as the renaming itself.\n\t\tposn := safetoken.StartPosition(r.pkg.FileSet(), pos).String()\n\t\tsegments := strings.Split(filepath.ToSlash(posn), \"/\")\n\t\tif n := len(segments); n > 2 {\n\t\t\tsegments = segments[n-2:]\n\t\t}\n\t\tposn = strings.Join(segments, \"/\")\n\t\tfmt.Fprintf(&conflict, \"%s:\", posn)\n\n\t\tif !strings.HasPrefix(format, \"\\t\") {\n\t\t\tconflict.WriteByte(' ')\n\t\t}\n\t}\n\n\tfmt.Fprintf(&conflict, format, args...)\n\tr.conflicts = append(r.conflicts, conflict.String())\n}\n\n// check performs safety checks of the renaming of the 'from' object to r.to.\nfunc (r *renamer) check(from types.Object) {\n\tif r.objsToUpdate[from] {\n\t\treturn\n\t}\n\tr.objsToUpdate[from] = true\n\n\t// NB: order of conditions is important.\n\tif from_, ok := from.(*types.PkgName); ok {\n\t\tr.checkInFileBlock(from_)\n\t} else if from_, ok := from.(*types.Label); ok {\n\t\tr.checkLabel(from_)\n\t} else if typesinternal.IsPackageLevel(from) {\n\t\tr.checkInPackageBlock(from)\n\t} else if v, ok := from.(*types.Var); ok && v.IsField() {\n\t\tr.checkStructField(v)\n\t} else if f, ok := from.(*types.Func); ok && recv(f) != nil {\n\t\tr.checkMethod(f)\n\t} else if isLocal(from) {\n\t\tr.checkInLexicalScope(from)\n\t} else {\n\t\tr.errorf(from.Pos(), \"unexpected %s object %q (please report a bug)\\n\",\n\t\t\tobjectKind(from), from)\n\t}\n}\n\n// checkInFileBlock performs safety checks for renames of objects in the file block,\n// i.e. imported package names.\nfunc (r *renamer) checkInFileBlock(from *types.PkgName) {\n\t// Check import name is not \"init\".\n\tif r.to == \"init\" {\n\t\tr.errorf(from.Pos(), \"%q is not a valid imported package name\", r.to)\n\t}\n\n\t// Check for conflicts between file and package block.\n\tif prev := from.Pkg().Scope().Lookup(r.to); prev != nil {\n\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q would conflict\",\n\t\t\tobjectKind(from), from.Name(), r.to)\n\t\tr.errorf(prev.Pos(), \"\\twith this package member %s\",\n\t\t\tobjectKind(prev))\n\t\treturn // since checkInPackageBlock would report redundant errors\n\t}\n\n\t// Check for conflicts in lexical scope.\n\tr.checkInLexicalScope(from)\n}\n\n// checkInPackageBlock performs safety checks for renames of\n// func/var/const/type objects in the package block.\nfunc (r *renamer) checkInPackageBlock(from types.Object) {\n\t// Check that there are no references to the name from another\n\t// package if the renaming would make it unexported.\n\tif typ := r.pkg.Types(); typ != from.Pkg() && ast.IsExported(r.from) && !ast.IsExported(r.to) {\n\t\tif id := someUse(r.pkg.TypesInfo(), from); id != nil {\n\t\t\tr.checkExport(id, typ, from)\n\t\t}\n\t}\n\n\t// Check that in the package block, \"init\" is a function, and never referenced.\n\tif r.to == \"init\" {\n\t\tkind := objectKind(from)\n\t\tif kind == \"func\" {\n\t\t\t// Reject if intra-package references to it exist.\n\t\t\tfor id, obj := range r.pkg.TypesInfo().Uses {\n\t\t\t\tif obj == from {\n\t\t\t\t\tr.errorf(from.Pos(),\n\t\t\t\t\t\t\"renaming this func %q to %q would make it a package initializer\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(id.Pos(), \"\\tbut references to it exist\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tr.errorf(from.Pos(), \"you cannot have a %s at package level named %q\",\n\t\t\t\tkind, r.to)\n\t\t}\n\t}\n\n\t// In the declaring package, check for conflicts between the\n\t// package block and all file blocks.\n\tif from.Pkg() == r.pkg.Types() {\n\t\tfor _, f := range r.pkg.Syntax() {\n\t\t\tfileScope := r.pkg.TypesInfo().Scopes[f]\n\t\t\tif fileScope == nil {\n\t\t\t\tcontinue // type error? (golang/go#40835)\n\t\t\t}\n\t\t\tb, prev := fileScope.LookupParent(r.to, token.NoPos)\n\t\t\tif b == fileScope {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q would conflict\", objectKind(from), from.Name(), r.to)\n\t\t\t\tr.errorf(prev.Pos(), \"\\twith this %s\", objectKind(prev))\n\t\t\t\treturn // since checkInPackageBlock would report redundant errors\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check for conflicts in lexical scope.\n\tr.checkInLexicalScope(from)\n}\n\n// checkInLexicalScope performs safety checks that a renaming does not\n// change the lexical reference structure of the specified package.\n//\n// For objects in lexical scope, there are three kinds of conflicts:\n// same-, sub-, and super-block conflicts.  We will illustrate all three\n// using this example:\n//\n//\tvar x int\n//\tvar z int\n//\n//\tfunc f(y int) {\n//\t\tprint(x)\n//\t\tprint(y)\n//\t}\n//\n// Renaming x to z encounters a \"same-block conflict\", because an object\n// with the new name already exists, defined in the same lexical block\n// as the old object.\n//\n// Renaming x to y encounters a \"sub-block conflict\", because there exists\n// a reference to x from within (what would become) a hole in its scope.\n// The definition of y in an (inner) sub-block would cast a shadow in\n// the scope of the renamed variable.\n//\n// Renaming y to x encounters a \"super-block conflict\".  This is the\n// converse situation: there is an existing definition of the new name\n// (x) in an (enclosing) super-block, and the renaming would create a\n// hole in its scope, within which there exist references to it.  The\n// new name shadows the existing definition of x in the super-block.\n//\n// Removing the old name (and all references to it) is always safe, and\n// requires no checks.\nfunc (r *renamer) checkInLexicalScope(from types.Object) {\n\tb := from.Parent() // the block defining the 'from' object\n\tif b != nil {\n\t\ttoBlock, to := b.LookupParent(r.to, from.Parent().End())\n\t\tif toBlock == b {\n\t\t\t// same-block conflict\n\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\tr.errorf(to.Pos(), \"\\tconflicts with %s in same block\",\n\t\t\t\tobjectKind(to))\n\t\t\treturn\n\t\t} else if toBlock != nil {\n\t\t\t// Check for super-block conflict.\n\t\t\t// The name r.to is defined in a superblock.\n\t\t\t// Is that name referenced from within this block?\n\t\t\tforEachLexicalRef(r.pkg, to, func(id *ast.Ident, block *types.Scope) bool {\n\t\t\t\t_, obj := block.LookupParent(from.Name(), id.Pos())\n\t\t\t\tif obj == from {\n\t\t\t\t\t// super-block conflict\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\t\t\tr.errorf(id.Pos(), \"\\twould shadow this reference\")\n\t\t\t\t\tr.errorf(to.Pos(), \"\\tto the %s declared here\",\n\t\t\t\t\t\tobjectKind(to))\n\t\t\t\t\treturn false // stop\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t}\n\t// Check for sub-block conflict.\n\t// Is there an intervening definition of r.to between\n\t// the block defining 'from' and some reference to it?\n\tforEachLexicalRef(r.pkg, from, func(id *ast.Ident, block *types.Scope) bool {\n\t\t// Find the block that defines the found reference.\n\t\t// It may be an ancestor.\n\t\tfromBlock, _ := block.LookupParent(from.Name(), id.Pos())\n\t\t// See what r.to would resolve to in the same scope.\n\t\ttoBlock, to := block.LookupParent(r.to, id.Pos())\n\t\tif to != nil {\n\t\t\t// sub-block conflict\n\t\t\tif deeper(toBlock, fromBlock) {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\t\tr.errorf(id.Pos(), \"\\twould cause this reference to become shadowed\")\n\t\t\t\tr.errorf(to.Pos(), \"\\tby this intervening %s definition\",\n\t\t\t\t\tobjectKind(to))\n\t\t\t\treturn false // stop\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\t// Renaming a type that is used as an embedded field\n\t// requires renaming the field too. e.g.\n\t// \ttype T int // if we rename this to U..\n\t// \tvar s struct {T}\n\t// \tprint(s.T) // ...this must change too\n\tif _, ok := from.(*types.TypeName); ok {\n\t\tfor id, obj := range r.pkg.TypesInfo().Uses {\n\t\t\tif obj == from {\n\t\t\t\tif field := r.pkg.TypesInfo().Defs[id]; field != nil {\n\t\t\t\t\tr.check(field)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// deeper reports whether block x is lexically deeper than y.\nfunc deeper(x, y *types.Scope) bool {\n\tif x == y || x == nil {\n\t\treturn false\n\t} else if y == nil {\n\t\treturn true\n\t} else {\n\t\treturn deeper(x.Parent(), y.Parent())\n\t}\n}\n\n// Scope and Position\n//\n// Consider a function f declared as:\n//\n//\tfunc f[T *U, U *T](p, q T) (r, s U) { var ( v T; w = v ); type (t *t; u t) }\n//\t^                                  ^           ^      ^         ^     ^\n///   {T,U}                           {p,q,r,s}        v      w         t     u\n//\n// All objects {T, U, p, q, r, s, local} belong to the same lexical\n// block, the function scope, which is found in types.Info.Scopes\n// for f's FuncType. (A function body's BlockStmt does not have\n// an associated scope; only nested BlockStmts do.)\n//\n// The effective scope of each object is different:\n//\n//   - The type parameters T and U, whose constraints may refer to each\n//     other, all have a scope that starts at the beginning of the\n//     FuncDecl.Type.Func token.\n//\n//   - The parameter and result variables {p,q,r,s} can reference the\n//     type parameters but not each other, so their scopes all start at\n//     the end of the FuncType.\n//     (Prior to go1.22 it was--incorrectly--unset; see #64295).\n//     Beware also that Scope.Innermost does not currently work correctly for\n//     type parameters: it returns the scope of the package, not the function.\n//\n//   - Each const or var {v,w} declared within the function body has a\n//     scope that begins at the end of its ValueSpec, or after the\n//     AssignStmt for a var declared by \":=\".\n//\n//   - Each type {t,u} in the body has a scope that begins at\n//     the start of the TypeSpec, so they can be self-recursive\n//     but--unlike package-level types--not mutually recursive.\n\n// forEachLexicalRef calls fn(id, block) for each identifier id in package\n// pkg that is a reference to obj in lexical scope.  block is the\n// lexical block enclosing the reference.  If fn returns false the\n// iteration is terminated and findLexicalRefs returns false.\nfunc forEachLexicalRef(pkg *cache.Package, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {\n\tfilter := []ast.Node{\n\t\t(*ast.Ident)(nil),\n\t\t(*ast.SelectorExpr)(nil),\n\t\t(*ast.CompositeLit)(nil),\n\t}\n\tok := true\n\tvar visit func(cur inspector.Cursor) (descend bool)\n\tvisit = func(cur inspector.Cursor) (descend bool) {\n\t\tif !ok {\n\t\t\treturn false // bail out\n\t\t}\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.Ident:\n\t\t\tif pkg.TypesInfo().Uses[n] == obj {\n\t\t\t\tblock := typesinternal.EnclosingScope(pkg.TypesInfo(), cur)\n\t\t\t\tif !fn(n, block) {\n\t\t\t\t\tok = false\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.SelectorExpr:\n\t\t\t// don't visit n.Sel\n\t\t\tcur.ChildAt(edge.SelectorExpr_X, -1).Inspect(filter, visit)\n\t\t\treturn false // don't descend\n\n\t\tcase *ast.CompositeLit:\n\t\t\t// Handle recursion ourselves for struct literals\n\t\t\t// so we don't visit field identifiers.\n\t\t\ttv, ok := pkg.TypesInfo().Types[n]\n\t\t\tif !ok {\n\t\t\t\treturn false // don't descend\n\t\t\t}\n\t\t\tif is[*types.Struct](typeparams.CoreType(typeparams.Deref(tv.Type))) {\n\t\t\t\tif n.Type != nil {\n\t\t\t\t\tcur.ChildAt(edge.CompositeLit_Type, -1).Inspect(filter, visit)\n\t\t\t\t}\n\t\t\t\tfor i, elt := range n.Elts {\n\t\t\t\t\tcurElt := cur.ChildAt(edge.CompositeLit_Elts, i)\n\t\t\t\t\tif _, ok := elt.(*ast.KeyValueExpr); ok {\n\t\t\t\t\t\t// skip kv.Key\n\t\t\t\t\t\tcurElt = curElt.ChildAt(edge.KeyValueExpr_Value, -1)\n\t\t\t\t\t}\n\t\t\t\t\tcurElt.Inspect(filter, visit)\n\t\t\t\t}\n\t\t\t\treturn false // don't descend\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tpgf.Cursor().Inspect(filter, visit)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn ok\n}\n\nfunc (r *renamer) checkLabel(label *types.Label) {\n\t// Check there are no identical labels in the function's label block.\n\t// (Label blocks don't nest, so this is easy.)\n\tif prev := label.Parent().Lookup(r.to); prev != nil {\n\t\tr.errorf(label.Pos(), \"renaming this label %q to %q\", label.Name(), prev.Name())\n\t\tr.errorf(prev.Pos(), \"\\twould conflict with this one\")\n\t}\n}\n\n// checkStructField checks that the field renaming will not cause\n// conflicts at its declaration, or ambiguity or changes to any selection.\nfunc (r *renamer) checkStructField(from *types.Var) {\n\t// If this is the declaring package, check that the struct\n\t// declaration is free of field conflicts, and field/method\n\t// conflicts.\n\t//\n\t// go/types offers no easy way to get from a field (or interface\n\t// method) to its declaring struct (or interface), so we must\n\t// ascend the AST.\n\tif pgf, err := r.pkg.FileEnclosing(from.Pos()); err == nil {\n\t\tpath, _ := astutil.PathEnclosingInterval(pgf.File, from.Pos(), from.Pos())\n\t\t// path matches this pattern:\n\t\t// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]\n\n\t\t// Ascend to FieldList.\n\t\tvar i int\n\t\tfor {\n\t\t\tif _, ok := path[i].(*ast.FieldList); ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\ti++\n\t\ttStruct := path[i].(*ast.StructType)\n\t\ti++\n\t\t// Ascend past parens (unlikely).\n\t\tfor {\n\t\t\t_, ok := path[i].(*ast.ParenExpr)\n\t\t\tif !ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tif spec, ok := path[i].(*ast.TypeSpec); ok {\n\t\t\t// This struct is also a named type.\n\t\t\t// We must check for direct (non-promoted) field/field\n\t\t\t// and method/field conflicts.\n\t\t\tif tname := r.pkg.TypesInfo().Defs[spec.Name]; tname != nil {\n\t\t\t\tprev, indices, _ := types.LookupFieldOrMethod(tname.Type(), true, r.pkg.Types(), r.to)\n\t\t\t\tif len(indices) == 1 {\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this field %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this %s\",\n\t\t\t\t\t\tobjectKind(prev))\n\t\t\t\t\treturn // skip checkSelections to avoid redundant errors\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// This struct is not a named type.\n\t\t\t// We need only check for direct (non-promoted) field/field conflicts.\n\t\t\tT := r.pkg.TypesInfo().Types[tStruct].Type.Underlying().(*types.Struct)\n\t\t\tfor prev := range T.Fields() {\n\t\t\t\tif prev.Name() == r.to {\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this field %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this field\")\n\t\t\t\t\treturn // skip checkSelections to avoid redundant errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Renaming an anonymous field requires renaming the type too. e.g.\n\t// \tprint(s.T)       // if we rename T to U,\n\t// \ttype T int       // this and\n\t// \tvar s struct {T} // this must change too.\n\tif from.Anonymous() {\n\t\tif named, ok := from.Type().(*types.Named); ok {\n\t\t\tr.check(named.Obj())\n\t\t} else if named, ok := types.Unalias(typesinternal.Unpointer(from.Type())).(*types.Named); ok {\n\t\t\tr.check(named.Obj())\n\t\t}\n\t}\n\n\t// Check integrity of existing (field and method) selections.\n\tr.checkSelections(from)\n}\n\n// checkSelections checks that all uses and selections that resolve to\n// the specified object would continue to do so after the renaming.\nfunc (r *renamer) checkSelections(from types.Object) {\n\tpkg := r.pkg\n\ttyp := pkg.Types()\n\t{\n\t\tif id := someUse(pkg.TypesInfo(), from); id != nil {\n\t\t\tif !r.checkExport(id, typ, from) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tfor syntax, sel := range pkg.TypesInfo().Selections {\n\t\t\t// There may be extant selections of only the old\n\t\t\t// name or only the new name, so we must check both.\n\t\t\t// (If neither, the renaming is sound.)\n\t\t\t//\n\t\t\t// In both cases, we wish to compare the lengths\n\t\t\t// of the implicit field path (Selection.Index)\n\t\t\t// to see if the renaming would change it.\n\t\t\t//\n\t\t\t// If a selection that resolves to 'from', when renamed,\n\t\t\t// would yield a path of the same or shorter length,\n\t\t\t// this indicates ambiguity or a changed referent,\n\t\t\t// analogous to same- or sub-block lexical conflict.\n\t\t\t//\n\t\t\t// If a selection using the name 'to' would\n\t\t\t// yield a path of the same or shorter length,\n\t\t\t// this indicates ambiguity or shadowing,\n\t\t\t// analogous to same- or super-block lexical conflict.\n\n\t\t\t// TODO(adonovan): fix: derive from Types[syntax.X].Mode\n\t\t\t// TODO(adonovan): test with pointer, value, addressable value.\n\t\t\tisAddressable := true\n\n\t\t\tif sel.Obj() == from {\n\t\t\t\tif obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {\n\t\t\t\t\t// Renaming this existing selection of\n\t\t\t\t\t// 'from' may block access to an existing\n\t\t\t\t\t// type member named 'to'.\n\t\t\t\t\tdelta := len(indices) - len(sel.Index())\n\t\t\t\t\tif delta > 0 {\n\t\t\t\t\t\tcontinue // no ambiguity\n\t\t\t\t\t}\n\t\t\t\t\tr.selectionConflict(from, delta, syntax, obj)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else if sel.Obj().Name() == r.to {\n\t\t\t\tif obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {\n\t\t\t\t\t// Renaming 'from' may cause this existing\n\t\t\t\t\t// selection of the name 'to' to change\n\t\t\t\t\t// its meaning.\n\t\t\t\t\tdelta := len(indices) - len(sel.Index())\n\t\t\t\t\tif delta > 0 {\n\t\t\t\t\t\tcontinue //  no ambiguity\n\t\t\t\t\t}\n\t\t\t\t\tr.selectionConflict(from, -delta, syntax, sel.Obj())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {\n\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\tobjectKind(from), from.Name(), r.to)\n\n\tswitch {\n\tcase delta < 0:\n\t\t// analogous to sub-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould change the referent of this selection\")\n\t\tr.errorf(obj.Pos(), \"\\tof this %s\", objectKind(obj))\n\tcase delta == 0:\n\t\t// analogous to same-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould make this reference ambiguous\")\n\t\tr.errorf(obj.Pos(), \"\\twith this %s\", objectKind(obj))\n\tcase delta > 0:\n\t\t// analogous to super-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould shadow this selection\")\n\t\tr.errorf(obj.Pos(), \"\\tof the %s declared here\",\n\t\t\tobjectKind(obj))\n\t}\n}\n\n// checkMethod performs safety checks for renaming a method.\n// There are three hazards:\n// - declaration conflicts\n// - selection ambiguity/changes\n// - entailed renamings of assignable concrete/interface types.\n//\n// We reject renamings initiated at concrete methods if it would\n// change the assignability relation.  For renamings of abstract\n// methods, we rename all methods transitively coupled to it via\n// assignability.\nfunc (r *renamer) checkMethod(from *types.Func) {\n\t// e.g. error.Error\n\tif from.Pkg() == nil {\n\t\tr.errorf(from.Pos(), \"you cannot rename built-in method %s\", from)\n\t\treturn\n\t}\n\n\t// ASSIGNABILITY: We reject renamings of concrete methods that\n\t// would break a 'satisfy' constraint; but renamings of abstract\n\t// methods are allowed to proceed, and we rename affected\n\t// concrete and abstract methods as necessary.  It is the\n\t// initial method that determines the policy.\n\n\t// Check for conflict at point of declaration.\n\t// Check to ensure preservation of assignability requirements.\n\tR := recv(from).Type()\n\tif types.IsInterface(R) {\n\t\t// Abstract method\n\n\t\t// declaration\n\t\tprev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)\n\t\tif prev != nil {\n\t\t\tr.errorf(from.Pos(), \"renaming this interface method %q to %q\",\n\t\t\t\tfrom.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this method\")\n\t\t\treturn\n\t\t}\n\n\t\t// Check all interfaces that embed this one for\n\t\t// declaration conflicts too.\n\t\t{\n\t\t\t// Start with named interface types (better errors)\n\t\t\tfor _, obj := range r.pkg.TypesInfo().Defs {\n\t\t\t\tif obj, ok := obj.(*types.TypeName); ok && types.IsInterface(obj.Type()) {\n\t\t\t\t\tf, _, _ := types.LookupFieldOrMethod(\n\t\t\t\t\t\tobj.Type(), false, from.Pkg(), from.Name())\n\t\t\t\t\tif f == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tt, _, _ := types.LookupFieldOrMethod(\n\t\t\t\t\t\tobj.Type(), false, from.Pkg(), r.to)\n\t\t\t\t\tif t == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this interface method %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(t.Pos(), \"\\twould conflict with this method\")\n\t\t\t\t\tr.errorf(obj.Pos(), \"\\tin named interface type %q\", obj.Name())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now look at all literal interface types (includes named ones again).\n\t\t\tfor e, tv := range r.pkg.TypesInfo().Types {\n\t\t\t\tif e, ok := e.(*ast.InterfaceType); ok {\n\t\t\t\t\t_ = e\n\t\t\t\t\t_ = tv.Type.(*types.Interface)\n\t\t\t\t\t// TODO(adonovan): implement same check as above.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// assignability\n\t\t//\n\t\t// Find the set of concrete or abstract methods directly\n\t\t// coupled to abstract method 'from' by some\n\t\t// satisfy.Constraint, and rename them too.\n\t\tfor key := range r.satisfy() {\n\t\t\t// key = (lhs, rhs) where lhs is always an interface.\n\n\t\t\tlsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif lsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trmethods := r.msets.MethodSet(key.RHS)\n\t\t\trsel := rmethods.Lookup(from.Pkg(), from.Name())\n\t\t\tif rsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If both sides have a method of this name,\n\t\t\t// and one of them is m, the other must be coupled.\n\t\t\tvar coupled *types.Func\n\t\t\tswitch from {\n\t\t\tcase lsel.Obj():\n\t\t\t\tcoupled = rsel.Obj().(*types.Func)\n\t\t\tcase rsel.Obj():\n\t\t\t\tcoupled = lsel.Obj().(*types.Func)\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// We must treat concrete-to-interface\n\t\t\t// constraints like an implicit selection C.f of\n\t\t\t// each interface method I.f, and check that the\n\t\t\t// renaming leaves the selection unchanged and\n\t\t\t// unambiguous.\n\t\t\t//\n\t\t\t// Fun fact: the implicit selection of C.f\n\t\t\t// \ttype I interface{f()}\n\t\t\t// \ttype C struct{I}\n\t\t\t// \tfunc (C) g()\n\t\t\t//      var _ I = C{} // here\n\t\t\t// yields abstract method I.f.  This can make error\n\t\t\t// messages less than obvious.\n\t\t\t//\n\t\t\tif !types.IsInterface(key.RHS) {\n\t\t\t\t// The logic below was derived from checkSelections.\n\n\t\t\t\trtosel := rmethods.Lookup(from.Pkg(), r.to)\n\t\t\t\tif rtosel != nil {\n\t\t\t\t\trto := rtosel.Obj().(*types.Func)\n\t\t\t\t\tdelta := len(rsel.Index()) - len(rtosel.Index())\n\t\t\t\t\tif delta < 0 {\n\t\t\t\t\t\tcontinue // no ambiguity\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO(adonovan): record the constraint's position.\n\t\t\t\t\tkeyPos := token.NoPos\n\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tif delta == 0 {\n\t\t\t\t\t\t// analogous to same-block conflict\n\t\t\t\t\t\tr.errorf(keyPos, \"\\twould make the %s method of %s invoked via interface %s ambiguous\",\n\t\t\t\t\t\t\tr.to, key.RHS, key.LHS)\n\t\t\t\t\t\tr.errorf(rto.Pos(), \"\\twith (%s).%s\",\n\t\t\t\t\t\t\trecv(rto).Type(), r.to)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// analogous to super-block conflict\n\t\t\t\t\t\tr.errorf(keyPos, \"\\twould change the %s method of %s invoked via interface %s\",\n\t\t\t\t\t\t\tr.to, key.RHS, key.LHS)\n\t\t\t\t\t\tr.errorf(coupled.Pos(), \"\\tfrom (%s).%s\",\n\t\t\t\t\t\t\trecv(coupled).Type(), r.to)\n\t\t\t\t\t\tr.errorf(rto.Pos(), \"\\tto (%s).%s\",\n\t\t\t\t\t\t\trecv(rto).Type(), r.to)\n\t\t\t\t\t}\n\t\t\t\t\treturn // one error is enough\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !r.changeMethods {\n\t\t\t\t// This should be unreachable.\n\t\t\t\tr.errorf(from.Pos(), \"internal error: during renaming of abstract method %s\", from)\n\t\t\t\tr.errorf(coupled.Pos(), \"\\tchangedMethods=false, coupled method=%s\", coupled)\n\t\t\t\tr.errorf(from.Pos(), \"\\tPlease file a bug report\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Rename the coupled method to preserve assignability.\n\t\t\tr.check(coupled)\n\t\t}\n\t} else {\n\t\t// Concrete method\n\n\t\t// declaration\n\t\tprev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)\n\t\tif prev != nil && len(indices) == 1 {\n\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\tfrom.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this %s\",\n\t\t\t\tobjectKind(prev))\n\t\t\treturn\n\t\t}\n\n\t\t// assignability\n\t\t//\n\t\t// Find the set of abstract methods coupled to concrete\n\t\t// method 'from' by some satisfy.Constraint, and rename\n\t\t// them too.\n\t\t//\n\t\t// Coupling may be indirect, e.g. I.f <-> C.f via type D.\n\t\t//\n\t\t// \ttype I interface {f()}\n\t\t//\ttype C int\n\t\t//\ttype (C) f()\n\t\t//\ttype D struct{C}\n\t\t//\tvar _ I = D{}\n\t\t//\n\t\tfor key := range r.satisfy() {\n\t\t\t// key = (lhs, rhs) where lhs is always an interface.\n\t\t\tif types.IsInterface(key.RHS) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif rsel == nil || rsel.Obj() != from {\n\t\t\t\tcontinue // rhs does not have the method\n\t\t\t}\n\t\t\tlsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif lsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timeth := lsel.Obj().(*types.Func)\n\n\t\t\t// imeth is the abstract method (e.g. I.f)\n\t\t\t// and key.RHS is the concrete coupling type (e.g. D).\n\t\t\tif !r.changeMethods {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\tvar pos token.Pos\n\t\t\t\tvar iface string\n\n\t\t\t\tI := recv(imeth).Type()\n\t\t\t\tif named, ok := types.Unalias(I).(*types.Named); ok {\n\t\t\t\t\tpos = named.Obj().Pos()\n\t\t\t\t\tiface = \"interface \" + named.Obj().Name()\n\t\t\t\t} else {\n\t\t\t\t\tpos = from.Pos()\n\t\t\t\t\tiface = I.String()\n\t\t\t\t}\n\t\t\t\tr.errorf(pos, \"\\twould make %s no longer assignable to %s\",\n\t\t\t\t\tkey.RHS, iface)\n\t\t\t\tr.errorf(imeth.Pos(), \"\\t(rename %s.%s if you intend to change both types)\",\n\t\t\t\t\tI, from.Name())\n\t\t\t\treturn // one error is enough\n\t\t\t}\n\n\t\t\t// Rename the coupled interface method to preserve assignability.\n\t\t\tr.check(imeth)\n\t\t}\n\t}\n\n\t// Check integrity of existing (field and method) selections.\n\t// We skip this if there were errors above, to avoid redundant errors.\n\tr.checkSelections(from)\n}\n\nfunc (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {\n\t// Reject cross-package references if r.to is unexported.\n\t// (Such references may be qualified identifiers or field/method\n\t// selections.)\n\tif !ast.IsExported(r.to) && pkg != from.Pkg() {\n\t\tr.errorf(from.Pos(),\n\t\t\t\"renaming %q to %q would make it unexported\",\n\t\t\tfrom.Name(), r.to)\n\t\tr.errorf(id.Pos(), \"\\tbreaking references from packages such as %q\",\n\t\t\tpkg.Path())\n\t\treturn false\n\t}\n\treturn true\n}\n\n// satisfy returns the set of interface satisfaction constraints.\nfunc (r *renamer) satisfy() map[satisfy.Constraint]bool {\n\tif r.satisfyConstraints == nil {\n\t\t// Compute on demand: it's expensive.\n\t\tvar f satisfy.Finder\n\t\tpkg := r.pkg\n\t\t{\n\t\t\t// From satisfy.Finder documentation:\n\t\t\t//\n\t\t\t// The package must be free of type errors, and\n\t\t\t// info.{Defs,Uses,Selections,Types} must have been populated by the\n\t\t\t// type-checker.\n\t\t\t//\n\t\t\t// Only proceed if all packages have no errors.\n\t\t\tif len(pkg.ParseErrors()) > 0 || len(pkg.TypeErrors()) > 0 {\n\t\t\t\tvar filename string\n\t\t\t\tif len(pkg.ParseErrors()) > 0 {\n\t\t\t\t\terr := pkg.ParseErrors()[0][0]\n\t\t\t\t\tfilename = filepath.Base(err.Pos.Filename)\n\t\t\t\t} else if len(pkg.TypeErrors()) > 0 {\n\t\t\t\t\terr := pkg.TypeErrors()[0]\n\t\t\t\t\tfilename = filepath.Base(err.Fset.File(err.Pos).Name())\n\t\t\t\t}\n\t\t\t\tr.errorf(token.NoPos, // we don't have a position for this error.\n\t\t\t\t\t\"renaming %q to %q not possible because %q in %q has errors\",\n\t\t\t\t\tr.from, r.to, filename, pkg.Metadata().PkgPath)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tf.Find(pkg.TypesInfo(), pkg.Syntax())\n\t\t}\n\t\tr.satisfyConstraints = f.Result\n\t}\n\treturn r.satisfyConstraints\n}\n\n// -- helpers ----------------------------------------------------------\n\n// recv returns the method's receiver.\nfunc recv(meth *types.Func) *types.Var {\n\treturn meth.Signature().Recv()\n}\n\n// someUse returns an arbitrary use of obj within info.\nfunc someUse(info *types.Info, obj types.Object) *ast.Ident {\n\tfor id, o := range info.Uses {\n\t\tif o == obj {\n\t\t\treturn id\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc objectKind(obj types.Object) string {\n\tif obj == nil {\n\t\treturn \"nil object\"\n\t}\n\tswitch obj := obj.(type) {\n\tcase *types.PkgName:\n\t\treturn \"imported package name\"\n\tcase *types.TypeName:\n\t\treturn \"type\"\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\treturn \"field\"\n\t\t}\n\tcase *types.Func:\n\t\tif recv(obj) != nil {\n\t\t\treturn \"method\"\n\t\t}\n\t}\n\t// label, func, var, const\n\treturn strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), \"*types.\"))\n}\n\n// NB: for renamings, blank is not considered valid.\nfunc isValidIdentifier(id string) bool {\n\tif id == \"\" || id == \"_\" {\n\t\treturn false\n\t}\n\tfor i, r := range id {\n\t\tif !isLetter(r) && (i == 0 || !isDigit(r)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn token.Lookup(id) == token.IDENT\n}\n\n// checkPackageRename returns the effective new package directory, path and name\n// resulting from renaming the current package to newName, which may be an\n// identifier or a package path. An error is returned if the renaming is\n// invalid.\nfunc checkPackageRename(curPkg *cache.Package, f file.Handle, newName string, moveSubpackages bool) (newPkgDir string, newPkgName PackageName, newPkgPath PackagePath, err error) {\n\t// Path unchanged\n\tif newName == curPkg.String() || newName == string(curPkg.Metadata().Name) {\n\t\treturn f.URI().DirPath(), curPkg.Metadata().Name, curPkg.Metadata().PkgPath, nil\n\t}\n\n\t// If there are any Go files in the package that are not in the compiled package\n\t// with the current build config, we should not allow a package move.\n\tignored := hasIgnoredGoFiles(curPkg)\n\tif ignored {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"moving a package with ignored files is not supported\")\n\t}\n\n\t// TODO(mkalil): support relative paths\n\tif build.IsLocalImport(newName) {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"specifying relative paths in package rename not yet supported\")\n\t}\n\t// When package move is enabled, we prompt with the full package path. Users\n\t// can either submit a full package path or just provide the package\n\t// identifier.\n\tvalidIdent := isValidIdentifier(newName)\n\tif validIdent {\n\t\t// Not an attempted move. Check if a directory already exists at that\n\t\t// path, in which case we should not allow renaming.\n\t\troot := filepath.Dir(f.URI().DirPath())\n\t\tnewPkgDir = filepath.Join(root, newName)\n\t\texists, empty, err := dirIsEmpty(newPkgDir)\n\t\tif err != nil {\n\t\t\treturn \"\", \"\", \"\", err\n\t\t}\n\t\t// When rename moves subpackages, we merely change the directory name, which cannot\n\t\t// happen if the target directory already exists.\n\t\tif moveSubpackages && exists || !empty {\n\t\t\treturn \"\", \"\", \"\", fmt.Errorf(\"invalid package identifier: %q is not empty\", newPkgDir)\n\t\t}\n\t\tparentPkgPath := strings.TrimSuffix(string(curPkg.Metadata().PkgPath), string(curPkg.Metadata().Name)) // leaves a trailing slash\n\t\tnewPkgPath = PackagePath(parentPkgPath + newName)\n\t\tnewPkgName = PackageName(newName)\n\t\treturn newPkgDir, newPkgName, newPkgPath, nil\n\t}\n\t// Don't allow moving packages across module boundaries.\n\tcurModPath := curPkg.Metadata().Module.Path\n\tif !strings.HasPrefix(newName+\"/\", curModPath+\"/\") {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"invalid package path %q; cannot move package across module boundary\", newName)\n\t}\n\t// Don't support package merging. If a directory already exists\n\t// at that path, we should not allow renaming.\n\tnewPathAfterMod := strings.TrimPrefix(newName, curModPath) //newName is a package path here.\n\tmodDir := curPkg.Metadata().Module.Dir\n\tnewPkgDir = filepath.Join(modDir, filepath.FromSlash(newPathAfterMod))\n\t// Trim the starting slash, which is not considered valid in fs.ValidPath.\n\tisValidDir := fs.ValidPath(strings.TrimPrefix(newPkgDir, string(filepath.Separator)))\n\tif !isValidDir {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"invalid package path %q\", newName)\n\t}\n\tnewPkgName = PackageName(filepath.Base(newPkgDir))\n\texists, empty, err := dirIsEmpty(newPkgDir)\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", err\n\t}\n\t// When rename moves subpackages, we merely change the directory name, which cannot\n\t// happen if the target directory already exists.\n\tif moveSubpackages && exists || !empty {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"invalid package path: %q is not empty\", newPkgDir)\n\t}\n\t// Verify that the new package name is a valid identifier.\n\tif !isValidIdentifier(string(newPkgName)) {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"invalid package name %q\", newPkgName)\n\t}\n\tif f.URI().Dir().Base() != string(curPkg.Metadata().Name) {\n\t\treturn \"\", \"\", \"\", fmt.Errorf(\"can't move package: package name %q does not match directory base name %q\", string(curPkg.Metadata().Name), f.URI().Dir().Base())\n\t}\n\treturn newPkgDir, newPkgName, PackagePath(newName), nil\n}\n\n// hasIgnoredGoFiles returns true if the input pkg contains any Go files that\n// are not part of package pkg with the current build configuration.\nfunc hasIgnoredGoFiles(pkg *cache.Package) bool {\n\t// If any ignored files are Go files, don't allow a package move.\n\tfor _, f := range pkg.Metadata().IgnoredFiles {\n\t\tif strings.HasSuffix(f.Path(), \".go\") {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// dirIsEmpty returns two values: whether the directory exists and whether it is\n// empty (contains only directory entries). If it does not exist, empty is\n// always true.\nfunc dirIsEmpty(dir string) (exists bool, empty bool, err error) {\n\tfiles, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn false, true, nil\n\t\t} else {\n\t\t\treturn false, false, err\n\t\t}\n\t}\n\tfor _, f := range files {\n\t\tif !f.IsDir() {\n\t\t\treturn true, false, nil\n\t\t}\n\t}\n\treturn true, true, nil\n}\n\n// isLocal reports whether obj is local to some function.\n// Precondition: not a struct field or interface method.\nfunc isLocal(obj types.Object) bool {\n\t// [... 5=stmt 4=func 3=file 2=pkg 1=universe]\n\tvar depth int\n\tfor scope := obj.Parent(); scope != nil; scope = scope.Parent() {\n\t\tdepth++\n\t}\n\treturn depth >= 4\n}\n\n// -- Plundered from go/scanner: ---------------------------------------\n\nfunc isLetter(ch rune) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)\n}\n\nfunc isDigit(ch rune) bool {\n\treturn '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)\n}\n"
  },
  {
    "path": "gopls/internal/golang/semtok.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\n// This file defines the Semantic Tokens operation for Go source.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/fmtstr\"\n)\n\n// semDebug enables comprehensive logging of decisions\n// (gopls semtok foo.go > /dev/null shows log output).\n// It should never be true in checked-in code.\nconst semDebug = false\n\nfunc SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng *protocol.Range) (*protocol.SemanticTokens, error) {\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Select range.\n\tvar start, end token.Pos\n\tif rng != nil {\n\t\tvar err error\n\t\tstart, end, err = pgf.RangePos(*rng)\n\t\tif err != nil {\n\t\t\treturn nil, err // e.g. invalid range\n\t\t}\n\t} else {\n\t\ttok := pgf.Tok\n\t\tstart, end = tok.Pos(0), tok.Pos(tok.Size()) // entire file\n\t}\n\n\t// Reject full semantic token requests for large files.\n\t//\n\t// The LSP says that errors for the semantic token requests\n\t// should only be returned for exceptions (a word not\n\t// otherwise defined). This code treats a too-large file as an\n\t// exception. On parse errors, the code does what it can.\n\tconst maxFullFileSize = 100000\n\tif int(end-start) > maxFullFileSize {\n\t\treturn nil, fmt.Errorf(\"semantic tokens: range %s too large (%d > %d)\",\n\t\t\tfh.URI().Path(), end-start, maxFullFileSize)\n\t}\n\n\ttv := tokenVisitor{\n\t\tctx:            ctx,\n\t\tmetadataSource: snapshot,\n\t\tmetadata:       pkg.Metadata(),\n\t\tinfo:           pkg.TypesInfo(),\n\t\tfset:           pkg.FileSet(),\n\t\tpkg:            pkg,\n\t\tpgf:            pgf,\n\t\tstart:          start,\n\t\tend:            end,\n\t}\n\ttv.visit()\n\treturn &protocol.SemanticTokens{\n\t\tData: semtok.Encode(\n\t\t\ttv.tokens,\n\t\t\tsnapshot.Options().EnabledSemanticTokenTypes(),\n\t\t\tsnapshot.Options().EnabledSemanticTokenModifiers()),\n\t\tResultID: time.Now().String(), // for delta requests, but we've never seen any\n\t}, nil\n}\n\ntype tokenVisitor struct {\n\t// inputs\n\tctx            context.Context // for event logging\n\tmetadataSource metadata.Source // used to resolve imports\n\tmetadata       *metadata.Package\n\tinfo           *types.Info\n\tfset           *token.FileSet\n\tpkg            *cache.Package\n\tpgf            *parsego.File\n\tstart, end     token.Pos // range of interest\n\n\t// working state\n\tstack  []ast.Node     // path from root of the syntax tree\n\ttokens []semtok.Token // computed sequence of semantic tokens\n}\n\nfunc (tv *tokenVisitor) visit() {\n\tf := tv.pgf.File\n\t// may not be in range, but harmless\n\ttv.token(f.Package, len(\"package\"), semtok.TokKeyword)\n\tif f.Name != nil {\n\t\ttv.token(f.Name.NamePos, len(f.Name.Name), semtok.TokNamespace)\n\t}\n\tfor _, decl := range f.Decls {\n\t\t// Only look at the decls that overlap the range.\n\t\tif decl.End() <= tv.start || decl.Pos() >= tv.end {\n\t\t\tcontinue\n\t\t}\n\t\tast.Inspect(decl, tv.inspect)\n\t}\n\n\t// Scan all files for imported pkgs, ignore the ambiguous pkg.\n\t// This is to be consistent with the behavior in [go/doc]: https://pkg.go.dev/pkg/go/doc.\n\timportByName := make(map[string]*types.PkgName)\n\tfor _, pgf := range tv.pkg.CompiledGoFiles() {\n\t\tfor _, imp := range pgf.File.Imports {\n\t\t\tif obj := tv.pkg.TypesInfo().PkgNameOf(imp); obj != nil {\n\t\t\t\tif old, ok := importByName[obj.Name()]; ok {\n\t\t\t\t\tif old != nil && old.Imported() != obj.Imported() {\n\t\t\t\t\t\timportByName[obj.Name()] = nil // nil => ambiguous across files\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\timportByName[obj.Name()] = obj\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, cg := range f.Comments {\n\t\tfor _, c := range cg.List {\n\t\t\t// Only look at the comment that overlap the range.\n\t\t\tif c.End() <= tv.start || c.Pos() >= tv.end {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttv.comment(c, importByName)\n\t\t}\n\t}\n}\n\n// Matches (for example) \"[F]\", \"[*p.T]\", \"[p.T.M]\"\n// unless followed by a colon (exclude url link, e.g. \"[go]: https://go.dev\").\n// The first group is reference name. e.g. The first group of \"[*p.T.M]\" is \"p.T.M\".\nvar docLinkRegex = regexp.MustCompile(`\\[\\*?([\\pL_][\\pL_0-9]*(\\.[\\pL_][\\pL_0-9]*){0,2})](?:[^:]|$)`)\n\n// comment emits semantic tokens for a comment.\n// If the comment contains doc links or \"go:\" directives,\n// it emits a separate token for each link or directive and\n// each comment portion between them.\nfunc (tv *tokenVisitor) comment(c *ast.Comment, importByName map[string]*types.PkgName) {\n\tif strings.HasPrefix(c.Text, \"//go:\") {\n\t\ttv.godirective(c)\n\t\treturn\n\t}\n\n\tpkgScope := tv.pkg.Types().Scope()\n\t// lookupObjects interprets the name in various forms\n\t// (X, p.T, p.T.M, etc) and return the list of symbols\n\t// denoted by each identifier in the dotted list.\n\tlookupObjects := func(name string) (objs []types.Object) {\n\t\tscope := pkgScope\n\t\tif pkg, suffix, ok := strings.Cut(name, \".\"); ok {\n\t\t\tif obj, _ := importByName[pkg]; obj != nil {\n\t\t\t\tobjs = append(objs, obj)\n\t\t\t\tscope = obj.Imported().Scope()\n\t\t\t\tname = suffix\n\t\t\t}\n\t\t}\n\n\t\tif recv, method, ok := strings.Cut(name, \".\"); ok {\n\t\t\tobj, ok := scope.Lookup(recv).(*types.TypeName)\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobjs = append(objs, obj)\n\t\t\tt, ok := obj.Type().(*types.Named)\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tm, _, _ := types.LookupFieldOrMethod(t, true, tv.pkg.Types(), method)\n\t\t\tif m == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobjs = append(objs, m)\n\t\t\treturn objs\n\t\t} else {\n\t\t\tobj := scope.Lookup(name)\n\t\t\tif obj == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif _, ok := obj.(*types.PkgName); !ok && !obj.Exported() {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobjs = append(objs, obj)\n\t\t\treturn objs\n\n\t\t}\n\t}\n\n\tpos := c.Pos()\n\tfor line := range strings.SplitSeq(c.Text, \"\\n\") {\n\t\tlast := 0\n\n\t\tfor _, idx := range docLinkRegex.FindAllStringSubmatchIndex(line, -1) {\n\t\t\t// The first group is the reference name. e.g. \"X\", \"p.T\", \"p.T.M\".\n\t\t\tname := line[idx[2]:idx[3]]\n\t\t\tif objs := lookupObjects(name); len(objs) > 0 {\n\t\t\t\tif last < idx[2] {\n\t\t\t\t\ttv.token(pos+token.Pos(last), idx[2]-last, semtok.TokComment)\n\t\t\t\t}\n\t\t\t\toffset := pos + token.Pos(idx[2])\n\t\t\t\tfor i, obj := range objs {\n\t\t\t\t\tif i > 0 {\n\t\t\t\t\t\ttv.token(offset, len(\".\"), semtok.TokComment)\n\t\t\t\t\t\toffset += token.Pos(len(\".\"))\n\t\t\t\t\t}\n\t\t\t\t\tid, rest, _ := strings.Cut(name, \".\")\n\t\t\t\t\tname = rest\n\t\t\t\t\ttok, mods := tv.appendObjectModifiers(nil, obj)\n\t\t\t\t\ttv.token(offset, len(id), tok, mods...)\n\t\t\t\t\toffset += token.Pos(len(id))\n\t\t\t\t}\n\t\t\t\tlast = idx[3]\n\t\t\t}\n\t\t}\n\t\tif last != len(c.Text) {\n\t\t\ttv.token(pos+token.Pos(last), len(line)-last, semtok.TokComment)\n\t\t}\n\t\tpos += token.Pos(len(line) + 1)\n\t}\n}\n\n// token emits a token of the specified extent and semantics.\nfunc (tv *tokenVisitor) token(start token.Pos, length int, typ semtok.Type, modifiers ...semtok.Modifier) {\n\tif !start.IsValid() {\n\t\treturn\n\t}\n\tif length <= 0 {\n\t\treturn // vscode doesn't like 0-length Tokens\n\t}\n\tend := start + token.Pos(length)\n\tif start >= tv.end || end <= tv.start {\n\t\treturn\n\t}\n\t// want a line and column from start (in LSP coordinates). Ignore line directives.\n\trng, err := tv.pgf.PosRange(start, end)\n\tif err != nil {\n\t\tevent.Error(tv.ctx, \"failed to convert to range\", err)\n\t\treturn\n\t}\n\tif rng.End.Line != rng.Start.Line {\n\t\t// this happens if users are typing at the end of the file, but report nothing\n\t\treturn\n\t}\n\ttv.tokens = append(tv.tokens, semtok.Token{\n\t\tLine:      rng.Start.Line,\n\t\tStart:     rng.Start.Character,\n\t\tLen:       rng.End.Character - rng.Start.Character, // (on same line)\n\t\tType:      typ,\n\t\tModifiers: modifiers,\n\t})\n}\n\n// strStack converts the stack to a string, for debugging and error messages.\nfunc (tv *tokenVisitor) strStack() string {\n\tmsg := []string{\"[\"}\n\tfor i := len(tv.stack) - 1; i >= 0; i-- {\n\t\tn := tv.stack[i]\n\t\tmsg = append(msg, strings.TrimPrefix(fmt.Sprintf(\"%T\", n), \"*ast.\"))\n\t}\n\tif len(tv.stack) > 0 {\n\t\tpos := tv.stack[len(tv.stack)-1].Pos()\n\t\tif _, err := safetoken.Offset(tv.pgf.Tok, pos); err != nil {\n\t\t\tmsg = append(msg, fmt.Sprintf(\"invalid position %v for %s\", pos, tv.pgf.URI))\n\t\t} else {\n\t\t\tposn := safetoken.Position(tv.pgf.Tok, pos)\n\t\t\tmsg = append(msg, fmt.Sprintf(\"(%s:%d,col:%d)\",\n\t\t\t\tfilepath.Base(posn.Filename), posn.Line, posn.Column))\n\t\t}\n\t}\n\tmsg = append(msg, \"]\")\n\treturn strings.Join(msg, \" \")\n}\n\n// srcLine returns the source text for n (truncated at first newline).\nfunc (tv *tokenVisitor) srcLine(n ast.Node) string {\n\tfile := tv.pgf.Tok\n\tline := safetoken.Line(file, n.Pos())\n\tstart, err := safetoken.Offset(file, file.LineStart(line))\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\tend := start\n\tfor ; end < len(tv.pgf.Src) && tv.pgf.Src[end] != '\\n'; end++ {\n\n\t}\n\treturn string(tv.pgf.Src[start:end])\n}\n\nfunc (tv *tokenVisitor) inspect(n ast.Node) (descend bool) {\n\tif n == nil {\n\t\ttv.stack = tv.stack[:len(tv.stack)-1] // pop\n\t\treturn true\n\t}\n\ttv.stack = append(tv.stack, n) // push\n\tdefer func() {\n\t\tif !descend {\n\t\t\ttv.stack = tv.stack[:len(tv.stack)-1] // pop\n\t\t}\n\t}()\n\n\tswitch n := n.(type) {\n\tcase *ast.ArrayType:\n\tcase *ast.AssignStmt:\n\t\ttv.token(n.TokPos, len(n.Tok.String()), semtok.TokOperator)\n\tcase *ast.BasicLit:\n\t\tif n.Kind == token.STRING {\n\t\t\tif strings.Contains(n.Value, \"\\n\") {\n\t\t\t\t// has to be a string.\n\t\t\t\ttv.multiline(n.Pos(), n.End(), semtok.TokString)\n\t\t\t} else if !tv.formatString(n) {\n\t\t\t\t// not a format string, color the whole as a TokString.\n\t\t\t\ttv.token(n.Pos(), len(n.Value), semtok.TokString)\n\t\t\t}\n\t\t} else {\n\t\t\ttv.token(n.Pos(), len(n.Value), semtok.TokNumber)\n\t\t}\n\tcase *ast.BinaryExpr:\n\t\ttv.token(n.OpPos, len(n.Op.String()), semtok.TokOperator)\n\tcase *ast.BlockStmt:\n\tcase *ast.BranchStmt:\n\t\ttv.token(n.TokPos, len(n.Tok.String()), semtok.TokKeyword)\n\tcase *ast.CallExpr:\n\t\tif n.Ellipsis.IsValid() {\n\t\t\ttv.token(n.Ellipsis, len(\"...\"), semtok.TokOperator)\n\t\t}\n\tcase *ast.CaseClause:\n\t\tiam := \"case\"\n\t\tif n.List == nil {\n\t\t\tiam = \"default\"\n\t\t}\n\t\ttv.token(n.Case, len(iam), semtok.TokKeyword)\n\tcase *ast.ChanType:\n\t\t// chan | chan <- | <- chan\n\t\tswitch {\n\t\tcase n.Arrow == token.NoPos:\n\t\t\ttv.token(n.Begin, len(\"chan\"), semtok.TokKeyword)\n\t\tcase n.Arrow == n.Begin:\n\t\t\ttv.token(n.Arrow, 2, semtok.TokOperator)\n\t\t\tpos := tv.findKeyword(\"chan\", n.Begin+2, n.Value.Pos())\n\t\t\ttv.token(pos, len(\"chan\"), semtok.TokKeyword)\n\t\tcase n.Arrow != n.Begin:\n\t\t\ttv.token(n.Begin, len(\"chan\"), semtok.TokKeyword)\n\t\t\ttv.token(n.Arrow, 2, semtok.TokOperator)\n\t\t}\n\tcase *ast.CommClause:\n\t\tlength := len(\"case\")\n\t\tif n.Comm == nil {\n\t\t\tlength = len(\"default\")\n\t\t}\n\t\ttv.token(n.Case, length, semtok.TokKeyword)\n\tcase *ast.CompositeLit:\n\tcase *ast.DeclStmt:\n\tcase *ast.DeferStmt:\n\t\ttv.token(n.Defer, len(\"defer\"), semtok.TokKeyword)\n\tcase *ast.Ellipsis:\n\t\ttv.token(n.Ellipsis, len(\"...\"), semtok.TokOperator)\n\tcase *ast.EmptyStmt:\n\tcase *ast.ExprStmt:\n\tcase *ast.Field:\n\tcase *ast.FieldList:\n\tcase *ast.ForStmt:\n\t\ttv.token(n.For, len(\"for\"), semtok.TokKeyword)\n\tcase *ast.FuncDecl:\n\tcase *ast.FuncLit:\n\tcase *ast.FuncType:\n\t\tif n.Func != token.NoPos {\n\t\t\ttv.token(n.Func, len(\"func\"), semtok.TokKeyword)\n\t\t}\n\tcase *ast.GenDecl:\n\t\ttv.token(n.TokPos, len(n.Tok.String()), semtok.TokKeyword)\n\tcase *ast.GoStmt:\n\t\ttv.token(n.Go, len(\"go\"), semtok.TokKeyword)\n\tcase *ast.Ident:\n\t\ttv.ident(n)\n\tcase *ast.IfStmt:\n\t\ttv.token(n.If, len(\"if\"), semtok.TokKeyword)\n\t\tif n.Else != nil {\n\t\t\t// x.Body.End() or x.Body.End()+1, not that it matters\n\t\t\tpos := tv.findKeyword(\"else\", n.Body.End(), n.Else.Pos())\n\t\t\ttv.token(pos, len(\"else\"), semtok.TokKeyword)\n\t\t}\n\tcase *ast.ImportSpec:\n\t\ttv.importSpec(n)\n\t\treturn false\n\tcase *ast.IncDecStmt:\n\t\ttv.token(n.TokPos, len(n.Tok.String()), semtok.TokOperator)\n\tcase *ast.IndexExpr:\n\tcase *ast.IndexListExpr:\n\tcase *ast.InterfaceType:\n\t\ttv.token(n.Interface, len(\"interface\"), semtok.TokKeyword)\n\tcase *ast.KeyValueExpr:\n\tcase *ast.LabeledStmt:\n\tcase *ast.MapType:\n\t\ttv.token(n.Map, len(\"map\"), semtok.TokKeyword)\n\tcase *ast.ParenExpr:\n\tcase *ast.RangeStmt:\n\t\ttv.token(n.For, len(\"for\"), semtok.TokKeyword)\n\t\t// x.TokPos == token.NoPos is legal (for range foo {})\n\t\toffset := n.TokPos\n\t\tif offset == token.NoPos {\n\t\t\toffset = n.For\n\t\t}\n\t\tpos := tv.findKeyword(\"range\", offset, n.X.Pos())\n\t\ttv.token(pos, len(\"range\"), semtok.TokKeyword)\n\tcase *ast.ReturnStmt:\n\t\ttv.token(n.Return, len(\"return\"), semtok.TokKeyword)\n\tcase *ast.SelectStmt:\n\t\ttv.token(n.Select, len(\"select\"), semtok.TokKeyword)\n\tcase *ast.SelectorExpr:\n\tcase *ast.SendStmt:\n\t\ttv.token(n.Arrow, len(\"<-\"), semtok.TokOperator)\n\tcase *ast.SliceExpr:\n\tcase *ast.StarExpr:\n\t\ttv.token(n.Star, len(\"*\"), semtok.TokOperator)\n\tcase *ast.StructType:\n\t\ttv.token(n.Struct, len(\"struct\"), semtok.TokKeyword)\n\tcase *ast.SwitchStmt:\n\t\ttv.token(n.Switch, len(\"switch\"), semtok.TokKeyword)\n\tcase *ast.TypeAssertExpr:\n\t\tif n.Type == nil {\n\t\t\tpos := tv.findKeyword(\"type\", n.Lparen, n.Rparen)\n\t\t\ttv.token(pos, len(\"type\"), semtok.TokKeyword)\n\t\t}\n\tcase *ast.TypeSpec:\n\tcase *ast.TypeSwitchStmt:\n\t\ttv.token(n.Switch, len(\"switch\"), semtok.TokKeyword)\n\tcase *ast.UnaryExpr:\n\t\ttv.token(n.OpPos, len(n.Op.String()), semtok.TokOperator)\n\tcase *ast.ValueSpec:\n\t// things only seen with parsing or type errors, so ignore them\n\tcase *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:\n\t\treturn false\n\t// not going to see these\n\tcase *ast.File, *ast.Package:\n\t\ttv.errorf(\"implement %T %s\", n, safetoken.Position(tv.pgf.Tok, n.Pos()))\n\t// other things we knowingly ignore\n\tcase *ast.Comment, *ast.CommentGroup:\n\t\treturn false\n\tdefault:\n\t\ttv.errorf(\"failed to implement %T\", n)\n\t}\n\treturn true\n}\n\n// formatString tries to report directives and string literals\n// inside a (possible) printf-like call, it returns false and does nothing\n// if the string is not a format string.\nfunc (tv *tokenVisitor) formatString(lit *ast.BasicLit) bool {\n\tif len(tv.stack) <= 1 {\n\t\treturn false\n\t}\n\tcall, ok := tv.stack[len(tv.stack)-2].(*ast.CallExpr)\n\tif !ok {\n\t\treturn false\n\t}\n\tlastNonVariadic, idx := formatStringAndIndex(tv.info, call)\n\tif idx == -1 || lit != lastNonVariadic {\n\t\treturn false\n\t}\n\tformat, err := strconv.Unquote(lit.Value)\n\tif err != nil {\n\t\treturn false\n\t}\n\tif !strings.Contains(format, \"%\") {\n\t\treturn false\n\t}\n\toperations, err := fmtstr.Parse(format, idx)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// It's a format string, compute interleaved sub range of directives and literals.\n\t// pos tracks literal substring position within the overall BasicLit.\n\tpos := lit.ValuePos\n\tfor _, op := range operations {\n\t\t// Skip \"%%\".\n\t\tif op.Verb.Verb == '%' {\n\t\t\tcontinue\n\t\t}\n\t\trng, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End)\n\t\tif err != nil {\n\t\t\treturn false\n\t\t}\n\t\t// Report literal substring.\n\t\ttv.token(pos, int(rng.Start-pos), semtok.TokString)\n\t\t// Report formatting directive.\n\t\ttv.token(rng.Start, int(rng.EndPos-rng.Start), semtok.TokString, semtok.ModFormat)\n\t\tpos = rng.EndPos\n\t}\n\t// Report remaining literal substring.\n\ttv.token(pos, int(lit.End()-pos), semtok.TokString)\n\treturn true\n}\n\nfunc (tv *tokenVisitor) appendObjectModifiers(mods []semtok.Modifier, obj types.Object) (semtok.Type, []semtok.Modifier) {\n\tif obj.Pkg() == nil {\n\t\tmods = append(mods, semtok.ModDefaultLibrary)\n\t}\n\n\t// Note: PkgName, Builtin, Label have type Invalid, which adds no modifiers.\n\tmods = appendTypeModifiers(mods, obj.Type())\n\n\tswitch obj := obj.(type) {\n\tcase *types.PkgName:\n\t\treturn semtok.TokNamespace, mods\n\n\tcase *types.Builtin:\n\t\treturn semtok.TokFunction, mods\n\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() != nil {\n\t\t\treturn semtok.TokMethod, mods\n\t\t} else {\n\t\t\treturn semtok.TokFunction, mods\n\t\t}\n\n\tcase *types.TypeName:\n\t\tif is[*types.TypeParam](types.Unalias(obj.Type())) {\n\t\t\treturn semtok.TokTypeParam, mods\n\t\t}\n\t\treturn semtok.TokType, mods\n\n\tcase *types.Const:\n\t\tmods = append(mods, semtok.ModReadonly)\n\t\treturn semtok.TokVariable, mods\n\n\tcase *types.Var:\n\t\tswitch obj.Kind() {\n\t\tcase types.PackageVar:\n\t\t\tmods = append(mods, semtok.ModStatic)\n\t\tcase types.RecvVar, types.ParamVar:\n\t\t\treturn semtok.TokParameter, mods\n\t\tcase types.FieldVar:\n\t\t\treturn semtok.TokProperty, mods\n\t\t}\n\t\treturn semtok.TokVariable, mods\n\n\tcase *types.Label:\n\t\treturn semtok.TokLabel, mods\n\n\tcase *types.Nil:\n\t\tmods = append(mods, semtok.ModReadonly)\n\t\treturn semtok.TokVariable, mods\n\t}\n\n\tpanic(obj)\n}\n\n// appendTypeModifiers appends optional modifiers that describe the top-level\n// type constructor of t: \"pointer\", \"map\", etc.\nfunc appendTypeModifiers(mods []semtok.Modifier, t types.Type) []semtok.Modifier {\n\t// For a type parameter, don't report \"interface\".\n\tif is[*types.TypeParam](types.Unalias(t)) {\n\t\treturn mods\n\t}\n\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Interface:\n\t\tmods = append(mods, semtok.ModInterface)\n\tcase *types.Struct:\n\t\tmods = append(mods, semtok.ModStruct)\n\tcase *types.Signature:\n\t\tmods = append(mods, semtok.ModSignature)\n\tcase *types.Pointer:\n\t\tmods = append(mods, semtok.ModPointer)\n\tcase *types.Array:\n\t\tmods = append(mods, semtok.ModArray)\n\tcase *types.Map:\n\t\tmods = append(mods, semtok.ModMap)\n\tcase *types.Slice:\n\t\tmods = append(mods, semtok.ModSlice)\n\tcase *types.Chan:\n\t\tmods = append(mods, semtok.ModChan)\n\tcase *types.Basic:\n\t\tswitch t.Kind() {\n\t\tcase types.Invalid:\n\t\t\t// ignore (e.g. Builtin, PkgName, Label)\n\t\tcase types.String:\n\t\t\tmods = append(mods, semtok.ModString)\n\t\tcase types.Bool:\n\t\t\tmods = append(mods, semtok.ModBool)\n\t\tcase types.UnsafePointer:\n\t\t\tmods = append(mods, semtok.ModPointer)\n\t\tdefault:\n\t\t\tif t.Info()&types.IsNumeric != 0 {\n\t\t\t\tmods = append(mods, semtok.ModNumber)\n\t\t\t}\n\t\t}\n\t}\n\treturn mods\n}\n\nfunc (tv *tokenVisitor) ident(id *ast.Ident) {\n\tvar (\n\t\ttok  semtok.Type\n\t\tmods []semtok.Modifier\n\t\tobj  types.Object\n\t\tok   bool\n\t)\n\tif obj, _ = tv.info.Defs[id]; obj != nil {\n\t\t// definition\n\t\tmods = append(mods, semtok.ModDefinition)\n\t\ttok, mods = tv.appendObjectModifiers(mods, obj)\n\n\t} else if obj, ok = tv.info.Uses[id]; ok {\n\t\t// use\n\t\ttok, mods = tv.appendObjectModifiers(mods, obj)\n\n\t} else if tok, mods = tv.unkIdent(id); tok != \"\" {\n\t\t// ok\n\n\t} else {\n\t\treturn\n\t}\n\n\t// Emit a token for the identifier's extent.\n\ttv.token(id.Pos(), len(id.Name), tok, mods...)\n\n\tif semDebug {\n\t\tq := \"nil\"\n\t\tif obj != nil {\n\t\t\tq = fmt.Sprintf(\"%T\", obj.Type()) // e.g. \"*types.Map\"\n\t\t}\n\t\tlog.Printf(\" use %s/%T/%s got %s %v (%s)\",\n\t\t\tid.Name, obj, q, tok, mods, tv.strStack())\n\t}\n}\n\n// unkIdent handles identifiers with no types.Object (neither use nor\n// def), use the parse stack.\n// A lot of these only happen when the package doesn't compile,\n// but in that case it is all best-effort from the parse tree.\nfunc (tv *tokenVisitor) unkIdent(id *ast.Ident) (semtok.Type, []semtok.Modifier) {\n\tdef := []semtok.Modifier{semtok.ModDefinition}\n\tn := len(tv.stack) - 2 // parent of Ident; stack is [File ... Ident]\n\tif n < 0 {\n\t\ttv.errorf(\"no stack\") // can't happen\n\t\treturn \"\", nil\n\t}\n\tswitch parent := tv.stack[n].(type) {\n\tcase *ast.BinaryExpr, *ast.UnaryExpr, *ast.ParenExpr, *ast.StarExpr,\n\t\t*ast.IncDecStmt, *ast.SliceExpr, *ast.ExprStmt, *ast.IndexExpr,\n\t\t*ast.ReturnStmt, *ast.ChanType, *ast.SendStmt,\n\t\t*ast.ForStmt,      // possibly incomplete\n\t\t*ast.IfStmt,       /* condition */\n\t\t*ast.KeyValueExpr, // either key or value\n\t\t*ast.IndexListExpr:\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.Ellipsis:\n\t\treturn semtok.TokType, nil\n\tcase *ast.CaseClause:\n\t\tif n-2 >= 0 && is[ast.TypeSwitchStmt](tv.stack[n-2]) {\n\t\t\treturn semtok.TokType, nil\n\t\t}\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.ArrayType:\n\t\tif id == parent.Len {\n\t\t\t// or maybe a Type Param, but we can't just from the parse tree\n\t\t\treturn semtok.TokVariable, nil\n\t\t} else {\n\t\t\treturn semtok.TokType, nil\n\t\t}\n\tcase *ast.MapType:\n\t\treturn semtok.TokType, nil\n\tcase *ast.CallExpr:\n\t\tif id == parent.Fun {\n\t\t\treturn semtok.TokFunction, nil\n\t\t}\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.SwitchStmt:\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.TypeAssertExpr:\n\t\tif id == parent.X {\n\t\t\treturn semtok.TokVariable, nil\n\t\t} else if id == parent.Type {\n\t\t\treturn semtok.TokType, nil\n\t\t}\n\tcase *ast.ValueSpec:\n\t\tif slices.Contains(parent.Names, id) {\n\t\t\treturn semtok.TokVariable, def\n\t\t}\n\t\tfor _, p := range parent.Values {\n\t\t\tif p == id {\n\t\t\t\treturn semtok.TokVariable, nil\n\t\t\t}\n\t\t}\n\t\treturn semtok.TokType, nil\n\tcase *ast.SelectorExpr: // e.ti.Selections[nd] is nil, so no help\n\t\tif n-1 >= 0 {\n\t\t\tif ce, ok := tv.stack[n-1].(*ast.CallExpr); ok {\n\t\t\t\t// ... CallExpr SelectorExpr Ident (_.x())\n\t\t\t\tif ce.Fun == parent && parent.Sel == id {\n\t\t\t\t\treturn semtok.TokFunction, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.AssignStmt:\n\t\tfor _, p := range parent.Lhs {\n\t\t\t// x := ..., or x = ...\n\t\t\tif p == id {\n\t\t\t\tif parent.Tok != token.DEFINE {\n\t\t\t\t\tdef = nil\n\t\t\t\t}\n\t\t\t\treturn semtok.TokVariable, def // '_' in _ = ...\n\t\t\t}\n\t\t}\n\t\t// RHS, = x\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.TypeSpec: // it's a type if it is either the Name or the Type\n\t\tif id == parent.Type {\n\t\t\tdef = nil\n\t\t}\n\t\treturn semtok.TokType, def\n\tcase *ast.Field:\n\t\t// ident could be type in a field, or a method in an interface type, or a variable\n\t\tif id == parent.Type {\n\t\t\treturn semtok.TokType, nil\n\t\t}\n\t\tif n > 2 &&\n\t\t\tis[*ast.InterfaceType](tv.stack[n-2]) &&\n\t\t\tis[*ast.FieldList](tv.stack[n-1]) {\n\n\t\t\treturn semtok.TokMethod, def\n\t\t}\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.LabeledStmt:\n\t\tif id == parent.Label {\n\t\t\treturn semtok.TokLabel, def\n\t\t}\n\tcase *ast.BranchStmt:\n\t\tif id == parent.Label {\n\t\t\treturn semtok.TokLabel, nil\n\t\t}\n\tcase *ast.CompositeLit:\n\t\tif parent.Type == id {\n\t\t\treturn semtok.TokType, nil\n\t\t}\n\t\treturn semtok.TokVariable, nil\n\tcase *ast.RangeStmt:\n\t\tif parent.Tok != token.DEFINE {\n\t\t\tdef = nil\n\t\t}\n\t\treturn semtok.TokVariable, def\n\tcase *ast.FuncDecl:\n\t\treturn semtok.TokFunction, def\n\tdefault:\n\t\ttv.errorf(\"%T unexpected: %s %s%q\", parent, id.Name, tv.strStack(), tv.srcLine(id))\n\t}\n\treturn \"\", nil\n}\n\n// multiline emits a multiline token (`string` or /*comment*/).\nfunc (tv *tokenVisitor) multiline(start, end token.Pos, tok semtok.Type) {\n\t// TODO(adonovan): test with non-ASCII.\n\n\tf := tv.fset.File(start)\n\t// the hard part is finding the lengths of lines. include the \\n\n\tlength := func(line int) int {\n\t\tn := f.LineStart(line)\n\t\tif line >= f.LineCount() {\n\t\t\treturn f.Size() - int(n)\n\t\t}\n\t\treturn int(f.LineStart(line+1) - n)\n\t}\n\tspos := safetoken.StartPosition(tv.fset, start)\n\tepos := safetoken.EndPosition(tv.fset, end)\n\tsline := spos.Line\n\teline := epos.Line\n\t// first line is from spos.Column to end\n\ttv.token(start, length(sline)-spos.Column, tok) // leng(sline)-1 - (spos.Column-1)\n\tfor i := sline + 1; i < eline; i++ {\n\t\t// intermediate lines are from 1 to end\n\t\ttv.token(f.LineStart(i), length(i)-1, tok) // avoid the newline\n\t}\n\t// last line is from 1 to epos.Column\n\ttv.token(f.LineStart(eline), epos.Column-1, tok) // columns are 1-based\n}\n\n// findKeyword returns the position of a keyword by searching within\n// the specified range, for when it cannot be exactly known from the AST.\n// It returns NoPos if the keyword was not present in the source due to parse error.\nfunc (tv *tokenVisitor) findKeyword(keyword string, start, end token.Pos) token.Pos {\n\t// TODO(adonovan): use safetoken.Offset.\n\toffset := int(start) - tv.pgf.Tok.Base()\n\tlast := int(end) - tv.pgf.Tok.Base()\n\tbuf := tv.pgf.Src\n\tidx := bytes.Index(buf[offset:last], []byte(keyword))\n\tif idx < 0 {\n\t\t// Ill-formed code may form syntax trees without their usual tokens.\n\t\t// For example, \"type _ <-<-chan int\" parses as <-chan (chan int),\n\t\t// with two nested ChanTypes but only one chan keyword.\n\t\treturn token.NoPos\n\t}\n\treturn start + token.Pos(idx)\n}\n\nfunc (tv *tokenVisitor) importSpec(spec *ast.ImportSpec) {\n\t// a local package name or the last component of the Path\n\tif spec.Name != nil {\n\t\tname := spec.Name.String()\n\t\tif name != \"_\" && name != \".\" {\n\t\t\ttv.token(spec.Name.Pos(), len(name), semtok.TokNamespace)\n\t\t}\n\t\treturn // don't mark anything for . or _\n\t}\n\timportPath := metadata.UnquoteImportPath(spec)\n\tif importPath == \"\" {\n\t\treturn\n\t}\n\t// Import strings are implementation defined. Try to match with parse information.\n\tdepID := tv.metadata.DepsByImpPath[importPath]\n\tif depID == \"\" {\n\t\treturn\n\t}\n\tdepMD := tv.metadataSource.Metadata(depID)\n\tif depMD == nil {\n\t\t// unexpected, but impact is that maybe some import is not colored\n\t\treturn\n\t}\n\t// Check whether the original literal contains the package's declared name.\n\tj := strings.LastIndex(spec.Path.Value, string(depMD.Name))\n\tif j < 0 {\n\t\t// Package name does not match import path, so there is nothing to report.\n\t\treturn\n\t}\n\t// Report virtual declaration at the position of the substring.\n\tstart := spec.Path.Pos() + token.Pos(j)\n\ttv.token(start, len(depMD.Name), semtok.TokNamespace)\n}\n\n// errorf logs an error and reports a bug.\nfunc (tv *tokenVisitor) errorf(format string, args ...any) {\n\tmsg := fmt.Sprintf(format, args...)\n\tbug.Report(msg)\n\tevent.Error(tv.ctx, tv.strStack(), errors.New(msg))\n}\n\nvar godirectives = map[string]struct{}{\n\t// https://pkg.go.dev/cmd/compile\n\t\"noescape\":       {},\n\t\"uintptrescapes\": {},\n\t\"noinline\":       {},\n\t\"norace\":         {},\n\t\"nosplit\":        {},\n\t\"linkname\":       {},\n\n\t// https://pkg.go.dev/go/build\n\t\"build\":               {},\n\t\"binary-only-package\": {},\n\t\"embed\":               {},\n}\n\n// Tokenize godirective at the start of the comment c, if any, and the surrounding comment.\n// If there is any failure, emits the entire comment as a TokComment token.\n// Directives are highlighted as-is, even if used incorrectly. Typically there are\n// dedicated analyzers that will warn about misuse.\nfunc (tv *tokenVisitor) godirective(c *ast.Comment) {\n\t// First check if '//go:directive args...' is a valid directive.\n\tdirective, args, _ := strings.Cut(c.Text, \" \")\n\tkind, _ := stringsCutPrefix(directive, \"//go:\")\n\tif _, ok := godirectives[kind]; !ok {\n\t\t// Unknown 'go:' directive.\n\t\ttv.token(c.Pos(), len(c.Text), semtok.TokComment)\n\t\treturn\n\t}\n\n\t// Make the 'go:directive' part stand out, the rest is comments.\n\ttv.token(c.Pos(), len(\"//\"), semtok.TokComment)\n\n\tdirectiveStart := c.Pos() + token.Pos(len(\"//\"))\n\ttv.token(directiveStart, len(directive[len(\"//\"):]), semtok.TokNamespace)\n\n\tif len(args) > 0 {\n\t\ttailStart := c.Pos() + token.Pos(len(directive)+len(\" \"))\n\t\ttv.token(tailStart, len(args), semtok.TokComment)\n\t}\n}\n\n// Go 1.20 strings.CutPrefix.\nfunc stringsCutPrefix(s, prefix string) (after string, found bool) {\n\tif !strings.HasPrefix(s, prefix) {\n\t\treturn s, false\n\t}\n\treturn s[len(prefix):], true\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n"
  },
  {
    "path": "gopls/internal/golang/signature_help.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// SignatureHelp returns information about the signature of the innermost\n// function call enclosing the position, or nil if there is none.\nfunc SignatureHelp(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range, context *protocol.SignatureHelpContext) (*protocol.SignatureInformation, error) {\n\tctx, done := event.Start(ctx, \"golang.SignatureHelp\")\n\tdefer done()\n\n\t// We need full type-checking here, as we must type-check function bodies in\n\t// order to provide signature help at the requested position.\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting file for SignatureHelp: %w\", err)\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Find a call expression surrounding the query position.\n\tvar callExpr *ast.CallExpr\n\tpath, _ := astutil.PathEnclosingInterval(pgf.File, start, end)\n\tif path == nil {\n\t\treturn nil, fmt.Errorf(\"cannot find node enclosing position\")\n\t}\n\tinfo := pkg.TypesInfo()\n\tvar fnval ast.Expr\nloop:\n\tfor i, node := range path {\n\t\tswitch node := node.(type) {\n\t\tcase *ast.Ident:\n\t\t\t// If the selected text is a function/method Ident or SelectorExpr,\n\t\t\t// even one not in function call position,\n\t\t\t// show help for its signature. Example:\n\t\t\t//    once.Do(initialize⁁)\n\t\t\t// should show help for initialize, not once.Do.\n\t\t\tif t := info.TypeOf(node); t != nil &&\n\t\t\t\tinfo.Defs[node] == nil &&\n\t\t\t\tis[*types.Signature](t.Underlying()) {\n\t\t\t\tif sel, ok := path[i+1].(*ast.SelectorExpr); ok && sel.Sel == node {\n\t\t\t\t\tfnval = sel // e.g. fmt.Println⁁\n\t\t\t\t} else {\n\t\t\t\t\tfnval = node\n\t\t\t\t}\n\t\t\t\tbreak loop\n\t\t\t}\n\t\tcase *ast.CallExpr:\n\t\t\t// Beware: the ')' may be missing.\n\t\t\tif node.Lparen <= start && end <= node.Rparen {\n\t\t\t\tcallExpr = node\n\t\t\t\tfnval = callExpr.Fun\n\t\t\t\tbreak loop\n\t\t\t}\n\t\tcase *ast.FuncLit, *ast.FuncType, *ast.CompositeLit:\n\t\t\t// The user is within an anonymous function or\n\t\t\t// a composite literal, which may be the argument\n\t\t\t// to the *ast.CallExpr.\n\t\t\t// Don't show signature help in this case.\n\t\t\treturn nil, nil\n\t\tcase *ast.BasicLit:\n\t\t\t// golang/go#43397: don't offer signature help when the user is typing\n\t\t\t// in a string literal unless it was manually invoked or help is already active.\n\t\t\tif node.Kind == token.STRING &&\n\t\t\t\t(context == nil || (context.TriggerKind != protocol.SigInvoked && !context.IsRetrigger)) {\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t}\n\t}\n\n\tif fnval == nil {\n\t\treturn nil, nil\n\t}\n\n\t// Get the type information for the function being called.\n\tvar sig *types.Signature\n\tif tv, ok := info.Types[fnval]; !ok {\n\t\treturn nil, fmt.Errorf(\"cannot get type for Fun %[1]T (%[1]v)\", fnval)\n\t} else if tv.IsType() {\n\t\treturn nil, nil // a conversion, not a call\n\t} else if sig, ok = tv.Type.Underlying().(*types.Signature); !ok {\n\t\treturn nil, fmt.Errorf(\"call operand is not a func or type: %[1]T (%[1]v)\", fnval)\n\t}\n\t// Inv: sig != nil\n\n\t// Get the object representing the function, if available.\n\t// There is no object in certain cases such as calling a function returned by\n\t// a function (e.g. \"foo()()\").\n\tvar obj types.Object\n\tswitch t := fnval.(type) {\n\tcase *ast.Ident:\n\t\tobj = info.ObjectOf(t)\n\tcase *ast.SelectorExpr:\n\t\tobj = info.ObjectOf(t.Sel)\n\t}\n\n\tif obj != nil && isBuiltin(obj) {\n\t\t// Special handling for error.Error, which is the only builtin method.\n\t\tif obj.Name() == \"Error\" {\n\t\t\treturn &protocol.SignatureInformation{\n\t\t\t\tLabel: \"Error() string\",\n\t\t\t\t// TODO(skewb1k): move the docstring for error.Error to builtin.go and reuse it across all relevant LSP methods.\n\t\t\t\tDocumentation:   stringToSigInfoDocumentation(\"Error returns the error message.\", snapshot.Options()),\n\t\t\t\tParameters:      nil,\n\t\t\t\tActiveParameter: nil,\n\t\t\t}, nil\n\t\t}\n\t\ts, err := NewBuiltinSignature(ctx, snapshot, obj.Name())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn signatureInformation(s, snapshot.Options(), start, end, callExpr)\n\t}\n\n\tmq := MetadataQualifierForFile(snapshot, pgf.File, pkg.Metadata())\n\tqual := typesinternal.FileQualifier(pgf.File, pkg.Types())\n\tvar (\n\t\tcomment *ast.CommentGroup\n\t\tname    string\n\t)\n\n\tif obj != nil {\n\t\tcomment, err = HoverDocForObject(ctx, snapshot, pkg.FileSet(), obj)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tname = obj.Name()\n\t} else {\n\t\tname = \"func\"\n\t}\n\n\ts, err := NewSignature(ctx, snapshot, pkg, sig, comment, qual, mq)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.name = name\n\treturn signatureInformation(s, snapshot.Options(), start, end, callExpr)\n}\n\nfunc signatureInformation(sig *signature, options *settings.Options, start, end token.Pos, call *ast.CallExpr) (*protocol.SignatureInformation, error) {\n\tparamInfo := make([]protocol.ParameterInformation, 0, len(sig.params))\n\tfor _, p := range sig.params {\n\t\tparamInfo = append(paramInfo, protocol.ParameterInformation{Label: p})\n\t}\n\treturn &protocol.SignatureInformation{\n\t\tLabel:           sig.name + sig.Format(),\n\t\tDocumentation:   stringToSigInfoDocumentation(sig.doc, options),\n\t\tParameters:      paramInfo,\n\t\tActiveParameter: activeParameter(sig, start, end, call),\n\t}, nil\n}\n\n// activeParameter returns a pointer to a variable containing\n// the index of the active parameter (if known), or nil otherwise.\nfunc activeParameter(sig *signature, start, end token.Pos, call *ast.CallExpr) *uint32 {\n\tif call == nil {\n\t\treturn nil\n\t}\n\tnumParams := uint32(len(sig.params))\n\tif numParams == 0 {\n\t\treturn nil\n\t}\n\t// Check if the position is even in the range of the arguments.\n\tif !(call.Lparen < start && end <= call.Rparen) {\n\t\treturn nil\n\t}\n\n\tvar activeParam uint32\n\tfor _, arg := range call.Args {\n\t\tif end <= arg.End() {\n\t\t\tbreak\n\t\t}\n\t\t// Don't advance the active parameter for the last parameter of a variadic function.\n\t\tif !sig.variadic || activeParam < numParams-1 {\n\t\t\tactiveParam++\n\t\t}\n\t}\n\treturn &activeParam\n}\n\nfunc stringToSigInfoDocumentation(s string, options *settings.Options) *protocol.Or_SignatureInformation_documentation {\n\tv := s\n\tk := protocol.PlainText\n\tif options.PreferredContentFormat == protocol.Markdown {\n\t\tv = DocCommentToMarkdown(s, options)\n\t\t// whether or not content is newline terminated may not matter for LSP clients,\n\t\t// but our tests expect trailing newlines to be stripped.\n\t\tv = strings.TrimSuffix(v, \"\\n\") // TODO(pjw): change the golden files\n\t\tk = protocol.Markdown\n\t}\n\treturn &protocol.Or_SignatureInformation_documentation{\n\t\tValue: protocol.MarkupContent{\n\t\t\tKind:  k,\n\t\t\tValue: v,\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/snapshot.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// NarrowestPackageForFile is a convenience function that selects the narrowest\n// non-ITV package to which this file belongs, type-checks it in the requested\n// mode (full or workspace), and returns it, along with the parse tree of that\n// file.\n//\n// The \"narrowest\" package is the one with the fewest number of files that\n// includes the given file. This solves the problem of test variants, as the\n// test will have more files than the non-test package.\n//\n// An intermediate test variant (ITV) package has identical source to a regular\n// package but resolves imports differently. gopls should never need to\n// type-check them.\n//\n// Type-checking is expensive. Call snapshot.ParseGo if all you need is a parse\n// tree, or snapshot.MetadataForFile if you only need metadata.\nfunc NarrowestPackageForFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (*cache.Package, *parsego.File, error) {\n\treturn selectPackageForFile(ctx, snapshot, uri, func(metas []*metadata.Package) *metadata.Package { return metas[0] })\n}\n\n// WidestPackageForFile is a convenience function that selects the widest\n// non-ITV package to which this file belongs, type-checks it in the requested\n// mode (full or workspace), and returns it, along with the parse tree of that\n// file.\n//\n// The \"widest\" package is the one with the most number of files that includes\n// the given file. Which is the test variant if one exists.\n//\n// An intermediate test variant (ITV) package has identical source to a regular\n// package but resolves imports differently. gopls should never need to\n// type-check them.\n//\n// Type-checking is expensive. Call snapshot.ParseGo if all you need is a parse\n// tree, or snapshot.MetadataForFile if you only need metadata.\nfunc WidestPackageForFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (*cache.Package, *parsego.File, error) {\n\treturn selectPackageForFile(ctx, snapshot, uri, func(metas []*metadata.Package) *metadata.Package { return metas[len(metas)-1] })\n}\n\n// NarrowestDeclaringPackage facilitates cross-package analysis by \"jumping\"\n// from the current package context to the package that declares the given object.\n//\n// This is essential when the object of interest is defined in a different\n// package than the one currently being type-checked.\n//\n// This function performs the context switch: it locates the file declaring\n// the object, loads its narrowest package (see [NarrowestPackageForFile]),\n// and returns the type-checked result.\n//\n// It returns the new package, the file, and the object's position translated\n// to be valid within the new package's file set.\nfunc NarrowestDeclaringPackage(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, obj types.Object) (*cache.Package, *parsego.File, token.Pos, error) {\n\tposn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, protocol.URIFromPath(posn.Filename))\n\tif err != nil {\n\t\treturn nil, nil, token.NoPos, err\n\t}\n\treturn pkg, pgf, pgf.Tok.Pos(posn.Offset), nil\n}\n\nfunc selectPackageForFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, selector func([]*metadata.Package) *metadata.Package) (*cache.Package, *parsego.File, error) {\n\tmps, err := snapshot.MetadataForFile(ctx, uri, true)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif len(mps) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"no package metadata for file %s\", uri)\n\t}\n\tmp := selector(mps)\n\tpkgs, err := snapshot.TypeCheck(ctx, mp.ID)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tpkg := pkgs[0]\n\tpgf, err := pkg.File(uri)\n\tif err != nil {\n\t\treturn nil, nil, err // \"can't happen\"\n\t}\n\treturn pkg, pgf, err\n}\n\ntype (\n\tPackageID   = metadata.PackageID\n\tPackagePath = metadata.PackagePath\n\tPackageName = metadata.PackageName\n\tImportPath  = metadata.ImportPath\n)\n\ntype unit = struct{}\n"
  },
  {
    "path": "gopls/internal/golang/splitpkg/graph.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage splitpkg\n\n// SCC algorithm stolen from cmd/digraph.\n\ntype (\n\tgraph    = map[int]map[int]bool\n\tnodeList = []int\n\tnodeSet  = map[int]bool\n)\n\n// addNode ensures a node exists in the graph with an initialized edge set.\nfunc addNode(g graph, node int) map[int]bool {\n\tedges := g[node]\n\tif edges == nil {\n\t\tedges = make(map[int]bool)\n\t\tg[node] = edges\n\t}\n\treturn edges\n}\n\n// addEdges adds one or more edges from a 'from' node.\nfunc addEdges(g graph, from int, to ...int) {\n\tedges := addNode(g, from)\n\tfor _, toNode := range to {\n\t\taddNode(g, toNode)\n\t\tedges[toNode] = true\n\t}\n}\n\n// transpose creates the transpose (reverse) of the graph.\nfunc transpose(g graph) graph {\n\trev := make(graph)\n\tfor node, edges := range g {\n\t\taddNode(rev, node) // Ensure all nodes exist in the transposed graph\n\t\tfor succ := range edges {\n\t\t\taddEdges(rev, succ, node)\n\t\t}\n\t}\n\treturn rev\n}\n\n// sccs returns the non-trivial strongly connected components of the graph.\nfunc sccs(g graph) []nodeSet {\n\t// Kosaraju's algorithm---Tarjan is overkill here.\n\t//\n\t// TODO(adonovan): factor with Tarjan's algorithms from\n\t// go/ssa/dom.go,\n\t// go/callgraph/vta/propagation.go,\n\t// ../../cache/typerefs/refs.go,\n\t// ../../cache/metadata/graph.go.\n\n\t// Forward pass.\n\tS := make(nodeList, 0, len(g)) // postorder stack\n\tseen := make(nodeSet)\n\tvar visit func(node int)\n\tvisit = func(node int) {\n\t\tif !seen[node] {\n\t\t\tseen[node] = true\n\t\t\tfor e := range g[node] {\n\t\t\t\tvisit(e)\n\t\t\t}\n\t\t\tS = append(S, node)\n\t\t}\n\t}\n\tfor node := range g {\n\t\tvisit(node)\n\t}\n\n\t// Reverse pass.\n\trev := transpose(g)\n\tvar scc nodeSet\n\tseen = make(nodeSet)\n\tvar rvisit func(node int)\n\trvisit = func(node int) {\n\t\tif !seen[node] {\n\t\t\tseen[node] = true\n\t\t\tscc[node] = true\n\t\t\tfor e := range rev[node] {\n\t\t\t\trvisit(e)\n\t\t\t}\n\t\t}\n\t}\n\tvar sccs []nodeSet\n\tfor len(S) > 0 {\n\t\ttop := S[len(S)-1]\n\t\tS = S[:len(S)-1] // pop\n\t\tif !seen[top] {\n\t\t\tscc = make(nodeSet)\n\t\t\trvisit(top)\n\t\t\tif len(scc) == 1 && !g[top][top] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsccs = append(sccs, scc)\n\t\t}\n\t}\n\treturn sccs\n}\n"
  },
  {
    "path": "gopls/internal/golang/splitpkg/splitpkg.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage splitpkg\n\n// This file produces the \"Split package\" HTML report.\n//\n// The server persistently holds, for each PackageID, the current set\n// of components and the mapping from declared names to components. On\n// each page reload or JS reload() call, the server type-checks the\n// package, computes its symbol reference graph, projects it onto\n// components, then returns the component reference graph, and if it\n// is cyclic, which edges form cycles. Thus changes to the package\n// source are reflected in the client UI at the next page reload or JS\n// reload() event.\n//\n// See also:\n// - ../codeaction.go - offers the CodeAction command\n// - ../../server/command.go - handles the command by opening a web page\n// - ../../server/server.go - handles the HTTP request and calls this function\n// - ../../server/assets/splitpkg.js - client-side logic\n// - ../../test/integration/web/splitpkg_test.go - integration test of server\n//\n// TODO(adonovan): future work\n//\n// Refine symbol reference graph:\n// - deal with enums (values must stay together; implicit dependency on iota expression)\n// - deal with coupled vars \"var x, y = f()\"\n// - deal with declared methods (coupled to receiver named type)\n// - deal with fields/interface methods (loosely coupled to struct/interface type)\n//   In both cases the field/method name must be either exported or in the same component.\n//\n// UI:\n// - make shift click extend selection of a range of checkboxes.\n// - display two-level grouping of decls and specs: var ( x int; y int )\n// - indicate when package has type errors (data may be incomplete).\n//\n// Code transformation:\n// - add \"Split\" button that is green when acyclic. It should:\n//   1) move each component into a new package, or separate file of\n//      the same package. (The UI will need to hold this user\n//      intent in the list of components.)\n//   2) ensure that each declaration referenced from another package\n//      is public, renaming as needed.\n//   3) update package decls, imports, package docs, file docs,\n//      doc comments, etc.\n// Should we call this feature \"Reorganize package\" or \"Decompose package\"\n// until the \"Split\" button actually exists?\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"html/template\"\n\t\"log\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n//go:embed splitpkg.html.tmpl\nvar htmlTmpl string\n\n// HTML returns the HTML for the main \"Split package\" page, for the\n// /splitpkg endpoint. The real magic happens in JavaScript; see\n// ../../server/assets/splitpkg.js.\nfunc HTML(pkgpath metadata.PackagePath) []byte {\n\tt, err := template.New(\"splitpkg.html\").Parse(htmlTmpl)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdata := struct {\n\t\tTitle string\n\t}{\n\t\tTitle: fmt.Sprintf(\"Split package %s\", pkgpath),\n\t}\n\tvar buf bytes.Buffer\n\tif err := t.Execute(&buf, data); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn buf.Bytes()\n}\n\nconst cacheKind = \"splitpkg\" // filecache kind\n\nfunc cacheKey(pkgID metadata.PackageID) [32]byte {\n\treturn sha256.Sum256([]byte(pkgID))\n}\n\n// UpdateComponentsJSON parses the JSON description of components and\n// their assigned declarations and updates the component state for the\n// specified package.\nfunc UpdateComponentsJSON(pkgID metadata.PackageID, data []byte) error {\n\treturn filecache.Set(cacheKind, cacheKey(pkgID), data)\n}\n\n// Web is an abstraction of gopls' web server.\ntype Web interface {\n\t// SrcURL forms URLs that cause the editor to open a file at a specific position.\n\tSrcURL(filename string, line, col8 int) protocol.URI\n}\n\n// JSON returns the JSON encoding of the data needed by\n// the /splitpkg-json endpoint for the specified package. It includes:\n//   - the set of names declared by the package, grouped by file;\n//   - the set of components and their assigned declarations from\n//     the most recent call to [UpdateComponentsJSON]; and\n//   - the component graph derived from them, along with the\n//     sets of reference that give rise to each edge.\nfunc JSON(pkg *cache.Package, web Web) ([]byte, error) {\n\t// Retrieve package's most recent state from the file cache.\n\tvar comp ComponentsJSON\n\tdata, err := filecache.Get(cacheKind, cacheKey(pkg.Metadata().ID))\n\tif err != nil {\n\t\tif err != filecache.ErrNotFound {\n\t\t\treturn nil, err\n\t\t}\n\t\t// cache miss: use zero value\n\t} else if err := json.Unmarshal(data, &comp); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Prepare to construct symbol reference graph.\n\tvar (\n\t\tinfo    = pkg.TypesInfo()\n\t\tsymbols = make(map[types.Object]*symbol)\n\t)\n\n\t// setName records the UI name for an object.\n\t// (The UI name disambiguates \"init\", \"_\", etc.)\n\tsetName := func(obj types.Object, name string) {\n\t\tsymbols[obj] = &symbol{\n\t\t\tname:      name,\n\t\t\tcomponent: comp.Assignments[name], // missing => \"default\"\n\t\t}\n\t}\n\n\t// Pass 1: name everything, since naming is order-dependent.\n\tvar initCounter, blankCounter int\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tfor _, decl := range pgf.File.Decls {\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tif fn, ok := info.Defs[decl.Name].(*types.Func); ok {\n\t\t\t\t\t// For now we treat methods as first class decls,\n\t\t\t\t\t// but since they are coupled to the named type\n\t\t\t\t\t// they should be omitted in the UI for brevity.\n\t\t\t\t\tname := fn.Name()\n\t\t\t\t\tif recv := fn.Signature().Recv(); recv != nil {\n\t\t\t\t\t\tfn = fn.Origin()\n\t\t\t\t\t\t_, named := typesinternal.ReceiverNamed(recv)\n\t\t\t\t\t\tname = named.Obj().Name() + \".\" + name\n\t\t\t\t\t} else if name == \"init\" {\n\t\t\t\t\t\t// Disambiguate top-level init functions.\n\t\t\t\t\t\tname += suffix(&initCounter)\n\t\t\t\t\t}\n\t\t\t\t\tif name == \"_\" { // (function or method)\n\t\t\t\t\t\tname += suffix(&blankCounter)\n\t\t\t\t\t}\n\t\t\t\t\tsetName(fn, name)\n\t\t\t\t}\n\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tswitch decl.Tok {\n\t\t\t\tcase token.CONST, token.VAR:\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\t\tfor _, id := range spec.Names {\n\t\t\t\t\t\t\tif obj := info.Defs[id]; obj != nil {\n\t\t\t\t\t\t\t\tname := obj.Name()\n\t\t\t\t\t\t\t\tif name == \"_\" {\n\t\t\t\t\t\t\t\t\tname += suffix(&blankCounter)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tsetName(obj, name)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\tcase token.TYPE:\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tspec := spec.(*ast.TypeSpec)\n\t\t\t\t\t\tif obj := info.Defs[spec.Name]; obj != nil {\n\t\t\t\t\t\t\tname := obj.Name()\n\t\t\t\t\t\t\tif name == \"_\" {\n\t\t\t\t\t\t\t\tname += suffix(&blankCounter)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsetName(obj, name)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Pass 2: compute symbol reference graph, project onto\n\t// component dependency graph, and build JSON response.\n\tvar (\n\t\tfiles []*fileJSON\n\t\trefs  []*refJSON\n\t)\n\tfor _, pgf := range pkg.CompiledGoFiles() {\n\t\tidentURL := func(id *ast.Ident) string {\n\t\t\tposn := safetoken.Position(pgf.Tok, id.Pos())\n\t\t\treturn web.SrcURL(posn.Filename, posn.Line, posn.Column)\n\t\t}\n\t\tnewCollector := func(from *symbol) *refCollector {\n\t\t\treturn &refCollector{\n\t\t\t\tfrom:     from,\n\t\t\t\tidentURL: identURL,\n\t\t\t\tpkg:      pkg.Types(),\n\t\t\t\tinfo:     info,\n\t\t\t\tsymbols:  symbols,\n\t\t\t}\n\t\t}\n\t\tvar decls []*declJSON\n\t\tfor _, decl := range pgf.File.Decls {\n\t\t\tvar (\n\t\t\t\tkind  string\n\t\t\t\tspecs []*specJSON\n\t\t\t)\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tkind = \"func\"\n\t\t\t\tif fn, ok := info.Defs[decl.Name].(*types.Func); ok {\n\t\t\t\t\tsymbol := symbols[fn]\n\t\t\t\t\trc := newCollector(symbol).collect(decl)\n\t\t\t\t\trefs = append(refs, rc.refs...)\n\t\t\t\t\tspecs = append(specs, &specJSON{\n\t\t\t\t\t\tName: symbol.name,\n\t\t\t\t\t\tURL:  identURL(decl.Name),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tkind = decl.Tok.String()\n\n\t\t\t\tswitch decl.Tok {\n\t\t\t\tcase token.CONST, token.VAR:\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\t\tfor i, id := range spec.Names {\n\t\t\t\t\t\t\tif obj := info.Defs[id]; obj != nil {\n\t\t\t\t\t\t\t\tsymbol := symbols[obj]\n\t\t\t\t\t\t\t\trc := newCollector(symbol)\n\t\t\t\t\t\t\t\t// If there's a type,\n\t\t\t\t\t\t\t\t// all RHSs depend on it.\n\t\t\t\t\t\t\t\tif spec.Type != nil {\n\t\t\t\t\t\t\t\t\trc.collect(spec.Type)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tswitch len(spec.Values) {\n\t\t\t\t\t\t\t\tcase len(spec.Names):\n\t\t\t\t\t\t\t\t\t// var x, y = a, b\n\t\t\t\t\t\t\t\t\trc.collect(spec.Values[i])\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t// var x, y = f()\n\t\t\t\t\t\t\t\t\trc.collect(spec.Values[0])\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t// var x T\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trefs = append(refs, rc.refs...)\n\t\t\t\t\t\t\t\tspecs = append(specs, &specJSON{\n\t\t\t\t\t\t\t\t\tName: symbol.name,\n\t\t\t\t\t\t\t\t\tURL:  identURL(id),\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\tcase token.TYPE:\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tspec := spec.(*ast.TypeSpec)\n\t\t\t\t\t\tif obj := info.Defs[spec.Name]; obj != nil {\n\t\t\t\t\t\t\tsymbol := symbols[obj]\n\t\t\t\t\t\t\trc := newCollector(symbol).collect(spec.Type)\n\t\t\t\t\t\t\trefs = append(refs, rc.refs...)\n\t\t\t\t\t\t\tspecs = append(specs, &specJSON{\n\t\t\t\t\t\t\t\tName: symbol.name,\n\t\t\t\t\t\t\t\tURL:  identURL(spec.Name),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(specs) > 0 {\n\t\t\t\tdecls = append(decls, &declJSON{Kind: kind, Specs: specs})\n\t\t\t}\n\t\t}\n\t\tfiles = append(files, &fileJSON{\n\t\t\tBase:  pgf.URI.Base(),\n\t\t\tURL:   web.SrcURL(pgf.URI.Path(), 1, 1),\n\t\t\tDecls: decls,\n\t\t})\n\t}\n\n\t// Compute the graph of dependencies between components, by\n\t// projecting the symbol dependency graph through component\n\t// assignments.\n\tvar (\n\t\tg        = make(graph)\n\t\tedgeRefs = make(map[[2]int][]*refJSON) // refs that induce each intercomponent edge\n\t)\n\tfor _, ref := range refs {\n\t\tfrom, to := ref.from, ref.to\n\t\tif from.component != to.component {\n\t\t\t// inter-component reference\n\t\t\tm, ok := g[from.component]\n\t\t\tif !ok {\n\t\t\t\tm = make(map[int]bool)\n\t\t\t\tg[from.component] = m\n\t\t\t}\n\t\t\tm[to.component] = true\n\n\t\t\tkey := [2]int{from.component, to.component}\n\t\t\tedgeRefs[key] = append(edgeRefs[key], ref)\n\t\t}\n\t}\n\n\t// Detect cycles in the component graph\n\t// and record cyclic (⚠) components.\n\tcycles := [][]int{}        // non-nil for JSON\n\tscmap := make(map[int]int) // maps component index to 1 + SCC index (0 => acyclic)\n\tfor i, scc := range sccs(g) {\n\t\tfor c := range scc {\n\t\t\tscmap[c] = i + 1\n\t\t}\n\t\tcycles = append(cycles, moremaps.KeySlice(scc))\n\t}\n\n\t// Record intercomponent edges and their references.\n\tedges := []*edgeJSON{} // non-nil for JSON\n\tfor edge, refs := range edgeRefs {\n\t\tfrom, to := edge[0], edge[1]\n\t\tedges = append(edges, &edgeJSON{\n\t\t\tFrom:   from,\n\t\t\tTo:     to,\n\t\t\tRefs:   refs,\n\t\t\tCyclic: scmap[from] > 0 && scmap[from] == scmap[to],\n\t\t})\n\t}\n\n\treturn json.Marshal(ResultJSON{\n\t\tFiles:      files,\n\t\tComponents: comp,\n\t\tEdges:      edges,\n\t\tCycles:     cycles,\n\t})\n}\n\n// A refCollector gathers intra-package references to top-level\n// symbols from within one syntax tree, in lexical order.\ntype refCollector struct {\n\tfrom     *symbol\n\tidentURL func(*ast.Ident) string\n\tpkg      *types.Package\n\tinfo     *types.Info\n\tindex    map[types.Object]*refJSON\n\tsymbols  map[types.Object]*symbol\n\n\trefs []*refJSON // output\n}\n\n// A symbol describes a declared name and its assigned component.\ntype symbol struct {\n\tname      string // unique name in the UI and JSON/HTTP protocol\n\tcomponent int    // index of assigned component\n}\n\n// collect adds the free references of n to the collection.\nfunc (rc *refCollector) collect(n ast.Node) *refCollector {\n\tvar f func(n ast.Node) bool\n\tf = func(n ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\tif sel, ok := rc.info.Selections[n]; ok {\n\t\t\t\trc.addRef(n.Sel, sel.Obj())\n\t\t\t\tast.Inspect(n.X, f)\n\t\t\t\treturn false // don't visit n.Sel\n\t\t\t}\n\n\t\tcase *ast.Ident:\n\t\t\tif obj := rc.info.Uses[n]; obj != nil {\n\t\t\t\trc.addRef(n, obj)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\tast.Inspect(n, f)\n\n\treturn rc\n}\n\n// addRef records a reference from id to obj.\nfunc (rc *refCollector) addRef(id *ast.Ident, obj types.Object) {\n\tif obj.Pkg() != rc.pkg {\n\t\treturn // cross-package reference\n\t}\n\n\t// Un-instantiate methods.\n\tif fn, ok := obj.(*types.Func); ok && fn.Signature().Recv() != nil {\n\t\tobj = fn.Origin() // G[int].method -> G[T].method\n\t}\n\n\t// We only care about refs to package-level symbols.\n\t// And methods, for now.\n\tdecl := rc.symbols[obj]\n\tif decl == nil {\n\t\treturn // not a package-level symbol or top-level method\n\t}\n\n\tif ref, ok := rc.index[obj]; !ok {\n\t\tref = &refJSON{\n\t\t\tFrom: rc.from.name,\n\t\t\tTo:   decl.name,\n\t\t\tURL:  rc.identURL(id),\n\t\t\tfrom: rc.from,\n\t\t\tto:   decl,\n\t\t}\n\t\tif rc.index == nil {\n\t\t\trc.index = make(map[types.Object]*refJSON)\n\t\t}\n\t\trc.index[obj] = ref\n\t\trc.refs = append(rc.refs, ref)\n\t}\n}\n\n// suffix returns a subscripted decimal suffix,\n// preincrementing the specified counter.\nfunc suffix(counter *int) string {\n\t*counter++\n\tn := *counter\n\treturn subscripter.Replace(strconv.Itoa(n))\n}\n\nvar subscripter = strings.NewReplacer(\n\t\"0\", \"₀\",\n\t\"1\", \"₁\",\n\t\"2\", \"₂\",\n\t\"3\", \"₃\",\n\t\"4\", \"₄\",\n\t\"5\", \"₅\",\n\t\"6\", \"₆\",\n\t\"7\", \"₇\",\n\t\"8\", \"₈\",\n\t\"9\", \"₉\",\n)\n\n// -- JSON types --\n\n// ResultJSON describes the result of a /splitpkg-json query.\n// It is public for testing.\ntype ResultJSON struct {\n\tComponents ComponentsJSON // component names and their assigned declarations\n\tFiles      []*fileJSON    // files of the packages and their declarations and references\n\tEdges      []*edgeJSON    // inter-component edges and their references\n\tCycles     [][]int        // sets of strongly-connected components\n}\n\n// request body of a /splitpkg-components update;\n// also part of /splitpkg-json response.\ntype ComponentsJSON struct {\n\tNames       []string       `json:\",omitempty\"` // if empty, implied Names[0]==\"default\".\n\tAssignments map[string]int `json:\",omitempty\"` // maps specJSON.Name to component index; missing => 0\n}\n\n// edgeJSON describes an inter-component dependency.\ntype edgeJSON struct {\n\tFrom, To int        // component IDs\n\tRefs     []*refJSON // references that give rise to this edge\n\tCyclic   bool       // edge is part of nontrivial strongly connected component\n}\n\n// fileJSON records groups decl/spec information about a single file.\ntype fileJSON struct {\n\tBase  string      // file base name\n\tURL   string      // showDocument link for file\n\tDecls []*declJSON `json:\",omitempty\"`\n}\n\n// declJSON groups specs (e.g. \"var ( x int; y int )\").\ntype declJSON struct {\n\tKind  string      // const, var, type, func\n\tSpecs []*specJSON `json:\",omitempty\"`\n}\n\n// specJSON describes a single declared name.\n// (A coupled declaration \"var x, y = f()\" results in two specJSONs.)\ntype specJSON struct {\n\tName string // x or T.x\n\tURL  string // showDocument link for declaring identifier\n}\n\n// refJSON records the first reference from a given declaration to a symbol.\n// (Repeat uses of the same identifier are omitted.)\ntype refJSON struct {\n\tFrom, To string // x or T.x of referenced spec\n\tURL      string // showDocument link for referring identifier\n\n\tfrom, to *symbol // transient\n}\n"
  },
  {
    "path": "gopls/internal/golang/splitpkg/splitpkg.html.tmpl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>{{.Title}}</title>\n  <link rel=\"stylesheet\" href=\"/assets/common.css\">\n  <link rel=\"stylesheet\" href=\"/assets/splitpkg.css\">\n  <script src=\"/assets/common.js\"></script>\n  <script src=\"/assets/splitpkg.js\"></script>\n</head>\n<body>\n<h1>{{.Title}}</h1>\n\n<p class='help'>\nⓘ Use this tool to decompose a package into a set of components\nwhose dependencies are acyclic.\n\nFirst, name a set of <a href='#components'>components</a>.\n\nSecond, assign each <a href='#assign'>declaration</a> to an\nappropriate component: check their checkboxes, choose a component, and\nclick Apply. Use the checkbox for a file to select all declarations in\nthat file.\n\nThird, examine the set of <a href='#deps'>dependencies</a> between\ncomponents. Each inter-component dependency lists the symbol\nreferences that cross the boundary. Click on one to navigate your\neditor there.\n\nIf two or more components form a dependency cycle (⚠),\nyou will need to either change your code,\nor change the component assignments.\n\nIterate this process.\nReload the page to refresh after each code change.\n</p>\n<p class='help'>\nOnce you are happy with the result, you can split the package,\nrenaming declarations as needed to export them.\nIn a future release, the code transformation will be automated.\n</p>\n\n<h2>Components</h2>\n<div id=\"components\"><!--programmatic--></div>\n\n<p>\n<input size=\"20\" id=\"new-component\" type='text'/>\n<button id=\"add-component\">Add component</button>\n[<a href='#deps'>▼ see dependencies</a>]\n</p>\n\n<hr>\n\n<h2>Declarations</h2>\n\n<div id=\"assign\">\n  <label for=\"assign-select\">Assign selected declarations to component:</label>\n  <select id=\"assign-select\"><!--programmatic--></select>\n  <button id=\"assign-apply\">Apply</button>\n</div>\n\n<div id=\"files\"><!--programmatic--></div>\n\n<hr>\n\n<h2>Component dependencies</h2>\n\n<div id=\"deps\"><!--programmatic--></div>\n`\n"
  },
  {
    "path": "gopls/internal/golang/stub.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\tpathpkg \"path\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/golang/stubmethods\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// stubMissingInterfaceMethodsFixer returns a suggested fix to declare the missing\n// methods of the concrete type that is assigned to an interface type\n// at the cursor position.\nfunc stubMissingInterfaceMethodsFixer(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tsi := stubmethods.GetIfaceStubInfo(pkg.FileSet(), pkg.TypesInfo(), pgf, start, end)\n\tif si == nil {\n\t\treturn nil, nil, fmt.Errorf(\"nil interface request\")\n\t}\n\treturn insertDeclsAfter(ctx, snapshot, pkg.Metadata(), si.Fset, si.Concrete.Obj(), si.Emit)\n}\n\n// stubMissingCalledFunctionFixer returns a suggested fix to declare the missing\n// method that the user may want to generate based on CallExpr\n// at the cursor position.\nfunc stubMissingCalledFunctionFixer(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tsi := stubmethods.GetCallStubInfo(pkg.FileSet(), pkg.TypesInfo(), pgf, start, end)\n\tif si == nil {\n\t\treturn nil, nil, fmt.Errorf(\"invalid type request\")\n\t}\n\treturn insertDeclsAfter(ctx, snapshot, pkg.Metadata(), si.Fset, si.After, si.Emit)\n}\n\n// An emitter writes new top-level declarations into an existing\n// file. References to symbols should be qualified using qual, which\n// respects the local import environment.\ntype emitter = func(out *bytes.Buffer, qual types.Qualifier) error\n\n// insertDeclsAfter locates the file that declares symbol sym,\n// (which must be among the dependencies of mp),\n// calls the emit function to generate new declarations,\n// respecting the local import environment,\n// and splices those declarations into the file after the declaration of sym,\n// updating imports as needed.\n//\n// fset must provide the position of sym.\nfunc insertDeclsAfter(ctx context.Context, snapshot *cache.Snapshot, mp *metadata.Package, fset *token.FileSet, sym types.Object, emit emitter) (*token.FileSet, *analysis.SuggestedFix, error) {\n\t// Parse the file declaring the sym.\n\t//\n\t// Beware: declPGF is not necessarily covered by pkg.FileSet() or si.Fset.\n\tdeclPGF, _, err := parseFull(ctx, snapshot, fset, sym)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to parse file %q declaring implementation symbol: %w\", declPGF.URI, err)\n\t}\n\tif declPGF.Fixed() {\n\t\treturn nil, nil, fmt.Errorf(\"file contains parse errors: %s\", declPGF.URI)\n\t}\n\n\t// Find metadata for the symbol's declaring package\n\t// as we'll need its import mapping.\n\tdeclMeta := findFileInDeps(snapshot, mp, declPGF.URI)\n\tif declMeta == nil {\n\t\treturn nil, nil, bug.Errorf(\"can't find metadata for file %s among dependencies of %s\", declPGF.URI, mp)\n\t}\n\n\t// Build import environment for the declaring file.\n\t// (typesinternal.FileQualifier works only for complete\n\t// import mappings, and requires types.)\n\timportEnv := make(map[ImportPath]string) // value is local name\n\tfor _, imp := range declPGF.File.Imports {\n\t\timportPath := metadata.UnquoteImportPath(imp)\n\t\tvar name string\n\t\tif imp.Name != nil {\n\t\t\tname = imp.Name.Name\n\t\t\tif name == \"_\" {\n\t\t\t\tcontinue\n\t\t\t} else if name == \".\" {\n\t\t\t\tname = \"\" // see types.Qualifier\n\t\t\t}\n\t\t} else {\n\t\t\t// Use the correct name from the metadata of the imported\n\t\t\t// package---not a guess based on the import path.\n\t\t\tmp := snapshot.Metadata(declMeta.DepsByImpPath[importPath])\n\t\t\tif mp == nil {\n\t\t\t\tcontinue // can't happen?\n\t\t\t}\n\t\t\tname = string(mp.Name)\n\t\t}\n\t\timportEnv[importPath] = name // latest alias wins\n\t}\n\n\t// Create a package name qualifier that uses the\n\t// locally appropriate imported package name.\n\t// It records any needed new imports.\n\t// TODO(adonovan): factor with golang.FormatVarType?\n\t//\n\t// Prior to CL 469155 this logic preserved any renaming\n\t// imports from the file that declares the interface\n\t// method--ostensibly the preferred name for imports of\n\t// frequently renamed packages such as protobufs.\n\t// Now we use the package's declared name. If this turns out\n\t// to be a mistake, then use parseHeader(si.iface.Pos()).\n\t//\n\ttype newImport struct{ name, importPath string }\n\tvar newImports []newImport // for AddNamedImport\n\tqual := func(pkg *types.Package) string {\n\t\t// TODO(adonovan): don't ignore vendor prefix.\n\t\t//\n\t\t// Ignore the current package import.\n\t\tif pkg.Path() == sym.Pkg().Path() {\n\t\t\treturn \"\"\n\t\t}\n\n\t\timportPath := ImportPath(pkg.Path())\n\t\tname, ok := importEnv[importPath]\n\t\tif !ok {\n\t\t\t// Insert new import using package's declared name.\n\t\t\t//\n\t\t\t// TODO(adonovan): resolve conflict between declared\n\t\t\t// name and existing file-level (declPGF.File.Imports)\n\t\t\t// or package-level (sym.Pkg.Scope) decls by\n\t\t\t// generating a fresh name.\n\t\t\tname = pkg.Name()\n\t\t\timportEnv[importPath] = name\n\t\t\tnew := newImport{importPath: string(importPath)}\n\t\t\t// For clarity, use a renaming import whenever the\n\t\t\t// local name does not match the path's last segment.\n\t\t\tif name != pathpkg.Base(trimVersionSuffix(new.importPath)) {\n\t\t\t\tnew.name = name\n\t\t\t}\n\t\t\tnewImports = append(newImports, new)\n\t\t}\n\t\treturn name\n\t}\n\n\t// Compute insertion point for new declarations:\n\t// after the top-level declaration enclosing the (package-level) type.\n\tinsertOffset, err := safetoken.Offset(declPGF.Tok, declPGF.File.End())\n\tif err != nil {\n\t\treturn nil, nil, bug.Errorf(\"internal error: end position outside file bounds: %v\", err)\n\t}\n\tsymOffset, err := safetoken.Offset(fset.File(sym.Pos()), sym.Pos())\n\tif err != nil {\n\t\treturn nil, nil, bug.Errorf(\"internal error: finding type decl offset: %v\", err)\n\t}\n\tfor _, decl := range declPGF.File.Decls {\n\t\tdeclEndOffset, err := safetoken.Offset(declPGF.Tok, decl.End())\n\t\tif err != nil {\n\t\t\treturn nil, nil, bug.Errorf(\"internal error: finding decl offset: %v\", err)\n\t\t}\n\t\tif declEndOffset > symOffset {\n\t\t\tinsertOffset = declEndOffset\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Splice the new declarations into the file content.\n\tvar buf bytes.Buffer\n\tinput := declPGF.Mapper.Content // unfixed content of file\n\tbuf.Write(input[:insertOffset])\n\tbuf.WriteByte('\\n')\n\terr = emit(&buf, qual)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tbuf.Write(input[insertOffset:])\n\n\t// Re-parse the file.\n\tfset = token.NewFileSet()\n\tnewF, err := parser.ParseFile(fset, declPGF.URI.Path(), buf.Bytes(), parser.ParseComments|parser.SkipObjectResolution)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"could not reparse file: %w\", err)\n\t}\n\n\t// Splice the new imports into the syntax tree.\n\tfor _, imp := range newImports {\n\t\tastutil.AddNamedImport(fset, newF, imp.name, imp.importPath)\n\t}\n\n\t// Pretty-print.\n\tvar output bytes.Buffer\n\tif err := format.Node(&output, fset, newF); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"format.Node: %w\", err)\n\t}\n\n\t// Report the diff.\n\tdiffs := diff.Bytes(input, output.Bytes())\n\treturn tokeninternal.FileSetFor(declPGF.Tok), // edits use declPGF.Tok\n\t\t&analysis.SuggestedFix{TextEdits: diffToTextEdits(declPGF.Tok, diffs)},\n\t\tnil\n}\n\n// diffToTextEdits converts diff (offset-based) edits to analysis (token.Pos) form.\nfunc diffToTextEdits(tok *token.File, diffs []diff.Edit) []analysis.TextEdit {\n\tedits := make([]analysis.TextEdit, 0, len(diffs))\n\tfor _, edit := range diffs {\n\t\tedits = append(edits, analysis.TextEdit{\n\t\t\tPos:     tok.Pos(edit.Start),\n\t\t\tEnd:     tok.Pos(edit.End),\n\t\t\tNewText: []byte(edit.New),\n\t\t})\n\t}\n\treturn edits\n}\n\n// trimVersionSuffix removes a trailing \"/v2\" (etc) suffix from a module path.\n//\n// This is only a heuristic as to the package's declared name, and\n// should only be used for stylistic decisions, such as whether it\n// would be clearer to use an explicit local name in the import\n// because the declared name differs from the result of this function.\n// When the name matters for correctness, look up the imported\n// package's Metadata.Name.\nfunc trimVersionSuffix(path string) string {\n\tdir, base := pathpkg.Split(path)\n\tif len(base) > 1 && base[0] == 'v' && strings.Trim(base[1:], \"0123456789\") == \"\" {\n\t\treturn dir // sans \"/v2\"\n\t}\n\treturn path\n}\n"
  },
  {
    "path": "gopls/internal/golang/stubmethods/stubcalledfunc.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stubmethods\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/typesutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nvar anyType = types.Universe.Lookup(\"any\").Type()\n\n// CallStubInfo represents a missing method\n// that a receiver type is about to generate\n// which has \"type X has no field or method Y\" error\ntype CallStubInfo struct {\n\tFset       *token.FileSet             // the FileSet used to type-check the types below\n\tReceiver   typesinternal.NamedOrAlias // the method's receiver type\n\tMethodName string\n\tAfter      types.Object // decl after which to insert the new decl\n\tpointer    bool\n\tinfo       *types.Info\n\tcurCall    inspector.Cursor // cursor to the CallExpr\n}\n\n// GetCallStubInfo extracts necessary information to generate a method definition from\n// a CallExpr.\nfunc GetCallStubInfo(fset *token.FileSet, info *types.Info, pgf *parsego.File, start, end token.Pos) *CallStubInfo {\n\tcallCur, _ := pgf.Cursor().FindByPos(start, end)\n\tcall, callCur := cursorutil.FirstEnclosing[*ast.CallExpr](callCur)\n\tif call == nil {\n\t\treturn nil\n\t}\n\ts, ok := call.Fun.(*ast.SelectorExpr)\n\t// TODO: support generating stub functions in the same way.\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// If recvExpr is a package name, compiler error would be\n\t// e.g., \"undefined: http.bar\", thus will not hit this code path.\n\trecvExpr := s.X\n\trecvType, pointer := concreteType(recvExpr, info)\n\n\tif recvType == nil || recvType.Obj().Pkg() == nil {\n\t\treturn nil\n\t}\n\n\t// A method of a function-local type cannot be stubbed\n\t// since there's nowhere to put the methods.\n\trecv := recvType.Obj()\n\tif recv.Parent() != recv.Pkg().Scope() {\n\t\treturn nil\n\t}\n\n\tafter := types.Object(recv)\n\t// If the enclosing function declaration is a method declaration,\n\t// and matches the receiver type of the diagnostic,\n\t// insert after the enclosing method.\n\tdecl, _ := cursorutil.FirstEnclosing[*ast.FuncDecl](callCur)\n\tif decl != nil && decl.Recv != nil {\n\t\tif len(decl.Recv.List) != 1 {\n\t\t\treturn nil\n\t\t}\n\t\tmrt := info.TypeOf(decl.Recv.List[0].Type)\n\t\tif mrt != nil && types.Identical(types.Unalias(typesinternal.Unpointer(mrt)), recv.Type()) {\n\t\t\tafter = info.ObjectOf(decl.Name)\n\t\t}\n\t}\n\treturn &CallStubInfo{\n\t\tFset:       fset,\n\t\tReceiver:   recvType,\n\t\tMethodName: s.Sel.Name,\n\t\tAfter:      after,\n\t\tpointer:    pointer,\n\t\tcurCall:    callCur,\n\t\tinfo:       info,\n\t}\n}\n\n// Emit writes to out the missing method based on type info of si.Receiver and CallExpr.\nfunc (si *CallStubInfo) Emit(out *bytes.Buffer, qual types.Qualifier) error {\n\tparams := si.collectParams()\n\trets := typesutil.TypesFromContext(si.info, si.curCall)\n\trecv := si.Receiver.Obj()\n\t// Pointer receiver?\n\tvar star string\n\tif si.pointer {\n\t\tstar = \"*\"\n\t}\n\n\t// Choose receiver name.\n\t// If any method has a named receiver, choose the first one.\n\t// Otherwise, use lowercase for the first letter of the object.\n\trecvName := strings.ToLower(fmt.Sprintf(\"%.1s\", recv.Name()))\n\tif named, ok := types.Unalias(si.Receiver).(*types.Named); ok {\n\t\tfor method := range named.Methods() {\n\t\t\tif recv := method.Signature().Recv(); recv.Name() != \"\" {\n\t\t\t\trecvName = recv.Name()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Emit method declaration.\n\tfmt.Fprintf(out, \"\\nfunc (%s %s%s%s) %s\",\n\t\trecvName,\n\t\tstar,\n\t\trecv.Name(),\n\t\ttypesutil.FormatTypeParams(si.Receiver.TypeParams()),\n\t\tsi.MethodName)\n\n\t// Emit parameters, avoiding name conflicts.\n\tseen := map[string]bool{recvName: true}\n\tout.WriteString(\"(\")\n\tfor i, param := range params {\n\t\tname := param.name\n\t\tif seen[name] {\n\t\t\tname = fmt.Sprintf(\"param%d\", i+1)\n\t\t}\n\t\tseen[name] = true\n\n\t\tif i > 0 {\n\t\t\tout.WriteString(\", \")\n\t\t}\n\t\tfmt.Fprintf(out, \"%s %s\", name, types.TypeString(param.typ, qual))\n\t}\n\tout.WriteString(\") \")\n\n\t// Emit result types.\n\tif len(rets) > 1 {\n\t\tout.WriteString(\"(\")\n\t}\n\tfor i, r := range rets {\n\t\tif i > 0 {\n\t\t\tout.WriteString(\", \")\n\t\t}\n\t\tout.WriteString(types.TypeString(r, qual))\n\t}\n\tif len(rets) > 1 {\n\t\tout.WriteString(\")\")\n\t}\n\n\t// Emit body.\n\tout.WriteString(` {\n\t\tpanic(\"unimplemented\")\n}`)\n\treturn nil\n}\n\ntype param struct {\n\tname string\n\ttyp  types.Type // the type of param, inferred from CallExpr\n}\n\n// collectParams gathers the parameter information needed to generate a method stub.\n// The param's type default to any if there is a type error in the argument.\nfunc (si *CallStubInfo) collectParams() []param {\n\tvar params []param\n\tappendParam := func(e ast.Expr, t types.Type) {\n\t\tp := param{\"param\", anyType}\n\t\tif t != nil && !containsInvalid(t) {\n\t\t\tt = types.Default(t)\n\t\t\tp = param{paramName(e, t), t}\n\t\t}\n\t\tparams = append(params, p)\n\t}\n\n\targs := si.curCall.Node().(*ast.CallExpr).Args\n\tfor _, arg := range args {\n\t\tt := si.info.TypeOf(arg)\n\t\tswitch t := t.(type) {\n\t\t// This is the case where another function call returning multiple\n\t\t// results is used as an argument.\n\t\tcase *types.Tuple:\n\t\t\tfor v := range t.Variables() {\n\t\t\t\tappendParam(arg, v.Type())\n\t\t\t}\n\t\tdefault:\n\t\t\tappendParam(arg, t)\n\t\t}\n\t}\n\treturn params\n}\n\n// containsInvalid checks if the type name contains \"invalid type\",\n// which is not a valid syntax to generate.\nfunc containsInvalid(t types.Type) bool {\n\ttypeString := types.TypeString(t, nil)\n\treturn strings.Contains(typeString, types.Typ[types.Invalid].String())\n}\n\n// paramName heuristically chooses a parameter name from\n// its argument expression and type. Caller should ensure\n// typ is non-nil.\nfunc paramName(e ast.Expr, typ types.Type) string {\n\tif typ == types.Universe.Lookup(\"error\").Type() {\n\t\treturn \"err\"\n\t}\n\tswitch t := e.(type) {\n\t// Use the identifier's name as the argument name.\n\tcase *ast.Ident:\n\t\treturn t.Name\n\t// Use the Sel.Name's last section as the argument name.\n\tcase *ast.SelectorExpr:\n\t\treturn lastSection(t.Sel.Name)\n\t}\n\n\ttyp = typesinternal.Unpointer(typ)\n\tswitch t := typ.(type) {\n\t// Use the first character of the type name as the argument name for builtin types\n\tcase *types.Basic:\n\t\treturn t.Name()[:1]\n\tcase *types.Slice:\n\t\treturn paramName(e, t.Elem())\n\tcase *types.Array:\n\t\treturn paramName(e, t.Elem())\n\tcase *types.Signature:\n\t\treturn \"f\"\n\tcase *types.Map:\n\t\treturn \"m\"\n\tcase *types.Chan:\n\t\treturn \"ch\"\n\tcase *types.Named:\n\t\treturn lastSection(t.Obj().Name())\n\tdefault:\n\t\treturn lastSection(t.String())\n\t}\n}\n\n// lastSection find the position of the last uppercase letter,\n// extract the substring from that point onward,\n// and convert it to lowercase.\n//\n// Example: lastSection(\"registryManagerFactory\") = \"factory\"\nfunc lastSection(identName string) string {\n\tlastUpperIndex := -1\n\tfor i, r := range identName {\n\t\tif unicode.IsUpper(r) {\n\t\t\tlastUpperIndex = i\n\t\t}\n\t}\n\tif lastUpperIndex != -1 {\n\t\tlast := identName[lastUpperIndex:]\n\t\treturn strings.ToLower(last)\n\t} else {\n\t\treturn identName\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/stubmethods/stubmethods.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package stubmethods provides the analysis logic for the quick fix\n// to \"Declare missing methods of TYPE\" errors. (The fix logic lives\n// in golang.stubMethodsFixer.)\npackage stubmethods\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/typesutil\"\n)\n\n// TODO(adonovan): eliminate the confusing Fset parameter; only the\n// file name and byte offset of Concrete are needed.\n\n// IfaceStubInfo represents a concrete type\n// that wants to stub out an interface type\ntype IfaceStubInfo struct {\n\t// Interface is the interface that the client wants to implement.\n\t// When the interface is defined, the underlying object will be a TypeName.\n\t// Note that we keep track of types.Object instead of types.Type in order\n\t// to keep a reference to the declaring object's package and the ast file\n\t// in the case where the concrete type file requires a new import that happens to be renamed\n\t// in the interface file.\n\t// TODO(marwan-at-work): implement interface literals.\n\tFset      *token.FileSet // the FileSet used to type-check the types below\n\tInterface *types.TypeName\n\tConcrete  typesinternal.NamedOrAlias\n\tpointer   bool\n}\n\n// GetIfaceStubInfo determines whether the \"missing method error\"\n// can be used to deduced what the concrete and interface types are.\n//\n// TODO(adonovan): this function (and its following 5 helpers) tries\n// to deduce a pair of (concrete, interface) types that are related by\n// an assignment, either explicitly or through a return statement or\n// function call. This is essentially what the refactor/satisfy does,\n// more generally. Refactor to share logic, after auditing 'satisfy'\n// for safety on ill-typed code.\nfunc GetIfaceStubInfo(fset *token.FileSet, info *types.Info, pgf *parsego.File, pos, end token.Pos) *IfaceStubInfo {\n\tcur, _ := pgf.Cursor().FindByPos(pos, end)\n\tfor cur := range cur.Enclosing() {\n\t\t// TODO: do cur = unparenEnclosing(cur) first, once CL 701035 lands.\n\t\tswitch cur.ParentEdgeKind() {\n\t\tcase edge.ValueSpec_Values:\n\t\t\treturn fromValueSpec(fset, info, cur)\n\t\tcase edge.ReturnStmt_Results:\n\t\t\t// An error here may not indicate a real error the user should know about, but it may.\n\t\t\t// Therefore, it would be best to log it out for debugging/reporting purposes instead of ignoring\n\t\t\t// it. However, event.Log takes a context which is not passed via the analysis package.\n\t\t\t// TODO(marwan-at-work): properly log this error.\n\t\t\tsi, _ := fromReturnStmt(fset, info, cur)\n\t\t\treturn si\n\t\tcase edge.AssignStmt_Rhs:\n\t\t\treturn fromAssignStmt(fset, info, cur)\n\t\tcase edge.CallExpr_Args:\n\t\t\t// Note that some call expressions don't carry the interface type\n\t\t\t// because they don't point to a function or method declaration elsewhere.\n\t\t\t// For eaxmple, \"var Interface = (*Concrete)(nil)\". In that case, continue\n\t\t\t// this loop to encounter other possibilities such as *ast.ValueSpec or others.\n\t\t\tsi := fromCallExpr(fset, info, cur)\n\t\t\tif si != nil {\n\t\t\t\treturn si\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// Emit writes to out the missing methods of si.Concrete required for it to implement si.Interface\nfunc (si *IfaceStubInfo) Emit(out *bytes.Buffer, qual types.Qualifier) error {\n\tconc := si.Concrete.Obj()\n\t// Record all direct methods of the current object\n\tconcreteFuncs := make(map[string]struct{})\n\tif named, ok := types.Unalias(si.Concrete).(*types.Named); ok {\n\t\tfor method := range named.Methods() {\n\t\t\tconcreteFuncs[method.Name()] = struct{}{}\n\t\t}\n\t}\n\n\tvar (\n\t\tmissing []*types.Func\n\t\t// Find subset of interface methods that the concrete type lacks.\n\t\tifaceType = si.Interface.Type().Underlying().(*types.Interface)\n\t)\n\n\tfor imethod := range ifaceType.Methods() {\n\t\tcmethod, index, _ := types.LookupFieldOrMethod(si.Concrete, si.pointer, imethod.Pkg(), imethod.Name())\n\t\tif cmethod == nil {\n\t\t\tmissing = append(missing, imethod)\n\t\t\tcontinue\n\t\t}\n\n\t\tif _, ok := cmethod.(*types.Var); ok {\n\t\t\t// len(LookupFieldOrMethod.index) = 1 => conflict, >1 => shadow.\n\t\t\treturn fmt.Errorf(\"adding method %s.%s would conflict with (or shadow) existing field\",\n\t\t\t\tconc.Name(), imethod.Name())\n\t\t}\n\n\t\tif _, exist := concreteFuncs[imethod.Name()]; exist {\n\t\t\tif !types.Identical(cmethod.Type(), imethod.Type()) {\n\t\t\t\treturn fmt.Errorf(\"method %s.%s already exists but has the wrong type: got %s, want %s\",\n\t\t\t\t\tconc.Name(), imethod.Name(), cmethod.Type(), imethod.Type())\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(index) > 0 {\n\t\t\t// len(index) > 0 implies that the current method is already\n\t\t\t// implemented on some embedded object.\n\t\t\t// Do not generate a method if it would result in shadowing, but\n\t\t\t// continue generating other parts of the stub.\n\t\t\t// For example, if some struct A partially implements an interface I\n\t\t\t// and another struct B embeds A, we should not implement methods on\n\t\t\t// B that are already implemented on A, as these would be shadowed\n\t\t\t// methods.\n\t\t\tcontinue\n\t\t}\n\n\t\tmissing = append(missing, imethod)\n\t}\n\tif len(missing) == 0 {\n\t\treturn fmt.Errorf(\"no missing methods found\")\n\t}\n\n\t// Format interface name (used only in a comment).\n\tiface := si.Interface.Name()\n\tif ipkg := si.Interface.Pkg(); ipkg != nil && ipkg != conc.Pkg() {\n\t\tiface = ipkg.Name() + \".\" + iface\n\t}\n\n\t// Pointer receiver?\n\tvar star string\n\tif si.pointer {\n\t\tstar = \"*\"\n\t}\n\n\t// If there are any that have named receiver, choose the first one.\n\t// Otherwise, use lowercase for the first letter of the object.\n\trn := strings.ToLower(si.Concrete.Obj().Name()[0:1])\n\tif named, ok := types.Unalias(si.Concrete).(*types.Named); ok {\n\t\tfor method := range named.Methods() {\n\t\t\tif recv := method.Signature().Recv(); recv.Name() != \"\" {\n\t\t\t\trn = recv.Name()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check for receiver name conflicts\n\tcheckRecvName := func(tuple *types.Tuple) bool {\n\t\tfor v := range tuple.Variables() {\n\t\t\tif rn == v.Name() {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfor index := range missing {\n\t\tmrn := rn + \" \"\n\t\tsig := missing[index].Signature()\n\t\tif checkRecvName(sig.Params()) || checkRecvName(sig.Results()) {\n\t\t\tmrn = \"\"\n\t\t}\n\n\t\tfmt.Fprintf(out, `// %s implements [%s].\nfunc (%s%s%s%s) %s%s {\n\tpanic(\"unimplemented\")\n}\n`,\n\t\t\tmissing[index].Name(),\n\t\t\tiface,\n\t\t\tmrn,\n\t\t\tstar,\n\t\t\tsi.Concrete.Obj().Name(),\n\t\t\ttypesutil.FormatTypeParams(si.Concrete.TypeParams()),\n\t\t\tmissing[index].Name(),\n\t\t\tstrings.TrimPrefix(types.TypeString(missing[index].Type(), qual), \"func\"))\n\t}\n\treturn nil\n}\n\n// fromCallExpr tries to find an *ast.CallExpr's function declaration and\n// analyzes a function call's signature against the passed in call argument to deduce\n// the concrete and interface types.\nfunc fromCallExpr(fset *token.FileSet, info *types.Info, curCallArg inspector.Cursor) *IfaceStubInfo {\n\n\tcall := curCallArg.Parent().Node().(*ast.CallExpr)\n\targ := curCallArg.Node().(ast.Expr)\n\n\tconcType, pointer := concreteType(arg, info)\n\tif concType == nil || concType.Obj().Pkg() == nil {\n\t\treturn nil\n\t}\n\ttv, ok := info.Types[call.Fun]\n\tif !ok {\n\t\treturn nil\n\t}\n\tsig, ok := types.Unalias(tv.Type).(*types.Signature)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\targIdx := curCallArg.ParentEdgeIndex()\n\tvar paramType types.Type\n\tif sig.Variadic() && argIdx >= sig.Params().Len()-1 {\n\t\tv := sig.Params().At(sig.Params().Len() - 1)\n\t\tif s, _ := v.Type().(*types.Slice); s != nil {\n\t\t\tparamType = s.Elem()\n\t\t}\n\t} else if argIdx < sig.Params().Len() {\n\t\tparamType = sig.Params().At(argIdx).Type()\n\t}\n\tif paramType == nil {\n\t\treturn nil // A type error prevents us from determining the param type.\n\t}\n\tiface := ifaceObjFromType(paramType)\n\tif iface == nil {\n\t\treturn nil\n\t}\n\treturn &IfaceStubInfo{\n\t\tFset:      fset,\n\t\tConcrete:  concType,\n\t\tpointer:   pointer,\n\t\tInterface: iface,\n\t}\n}\n\n// fromReturnStmt analyzes a \"return\" statement to extract\n// a concrete type that is trying to be returned as an interface type.\n//\n// For example, func() io.Writer { return myType{} }\n// would return StubIfaceInfo with the interface being io.Writer and the concrete type being myType{}.\nfunc fromReturnStmt(fset *token.FileSet, info *types.Info, curResult inspector.Cursor) (*IfaceStubInfo, error) {\n\tconcType, pointer := concreteType(curResult.Node().(ast.Expr), info)\n\tif concType == nil || concType.Obj().Pkg() == nil {\n\t\treturn nil, nil // result is not a named or *named or alias thereof\n\t}\n\t// Inv: the return is not a spread return,\n\t// such as \"return f()\" where f() has tuple type.\n\tconc := concType.Obj()\n\tif conc.Parent() != conc.Pkg().Scope() {\n\t\treturn nil, fmt.Errorf(\"local type %q cannot be stubbed\", conc.Name())\n\t}\n\n\tsig := typesutil.EnclosingSignature(curResult, info)\n\tif sig == nil {\n\t\t// Either curResult is not within a function (incontheivable?),\n\t\t// or the function's type information is missing (in which case\n\t\t// EnclosingSignature will have called bug.Report).\n\t\t// Don't report a second bug here.\n\t\t// See https://go.dev/issue/70666.\n\t\treturn nil, fmt.Errorf(\"internal error: return statement lacks type information or enclosing function (issue 70666)\")\n\t}\n\trets := sig.Results()\n\t// The return operands and function results must match.\n\t// (Spread returns were rejected earlier.)\n\tret := curResult.Parent().Node().(*ast.ReturnStmt)\n\tif rets.Len() != len(ret.Results) {\n\t\treturn nil, fmt.Errorf(\"%d-operand return statement in %d-result function\",\n\t\t\tlen(ret.Results),\n\t\t\trets.Len())\n\t}\n\tiface := ifaceObjFromType(rets.At(curResult.ParentEdgeIndex()).Type())\n\tif iface == nil {\n\t\treturn nil, nil\n\t}\n\treturn &IfaceStubInfo{\n\t\tFset:      fset,\n\t\tConcrete:  concType,\n\t\tpointer:   pointer,\n\t\tInterface: iface,\n\t}, nil\n}\n\n// fromValueSpec returns *StubIfaceInfo from a variable declaration such as\n// var x io.Writer = &T{}\nfunc fromValueSpec(fset *token.FileSet, info *types.Info, curValue inspector.Cursor) *IfaceStubInfo {\n\n\trhs := curValue.Node().(ast.Expr)\n\tspec := curValue.Parent().Node().(*ast.ValueSpec)\n\n\t// Possible implicit/explicit conversion to interface type?\n\tifaceNode := spec.Type // var _ myInterface = ...\n\tif call, ok := rhs.(*ast.CallExpr); ok && ifaceNode == nil && len(call.Args) == 1 {\n\t\t// var _ = myInterface(v)\n\t\tifaceNode = call.Fun\n\t\trhs = call.Args[0]\n\t}\n\tconcType, pointer := concreteType(rhs, info)\n\tif concType == nil || concType.Obj().Pkg() == nil {\n\t\treturn nil\n\t}\n\tconc := concType.Obj()\n\tif conc.Parent() != conc.Pkg().Scope() {\n\t\treturn nil\n\t}\n\n\tifaceObj := ifaceType(ifaceNode, info)\n\tif ifaceObj == nil {\n\t\treturn nil\n\t}\n\treturn &IfaceStubInfo{\n\t\tFset:      fset,\n\t\tConcrete:  concType,\n\t\tInterface: ifaceObj,\n\t\tpointer:   pointer,\n\t}\n}\n\n// fromAssignStmt returns *StubIfaceInfo from a variable assignment such as\n// var x io.Writer\n// x = &T{}\nfunc fromAssignStmt(fset *token.FileSet, info *types.Info, curRhs inspector.Cursor) *IfaceStubInfo {\n\t// The interface conversion error in an assignment is against the RHS:\n\t//\n\t//      var x io.Writer\n\t//      x = &T{} // error: missing method\n\t//          ^^^^\n\n\tassign := curRhs.Parent().Node().(*ast.AssignStmt)\n\tlhs, rhs := assign.Lhs[curRhs.ParentEdgeIndex()], curRhs.Node().(ast.Expr)\n\n\tifaceObj := ifaceType(lhs, info)\n\tif ifaceObj == nil {\n\t\treturn nil\n\t}\n\tconcType, pointer := concreteType(rhs, info)\n\tif concType == nil || concType.Obj().Pkg() == nil {\n\t\treturn nil\n\t}\n\tconc := concType.Obj()\n\tif conc.Parent() != conc.Pkg().Scope() {\n\t\treturn nil\n\t}\n\treturn &IfaceStubInfo{\n\t\tFset:      fset,\n\t\tConcrete:  concType,\n\t\tInterface: ifaceObj,\n\t\tpointer:   pointer,\n\t}\n}\n\n// ifaceType returns the named interface type to which e refers, if any.\nfunc ifaceType(e ast.Expr, info *types.Info) *types.TypeName {\n\ttv, ok := info.Types[e]\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn ifaceObjFromType(tv.Type)\n}\n\nfunc ifaceObjFromType(t types.Type) *types.TypeName {\n\tnamed, ok := types.Unalias(t).(*types.Named)\n\tif !ok {\n\t\treturn nil\n\t}\n\tif !types.IsInterface(named) {\n\t\treturn nil\n\t}\n\t// Interfaces defined in the \"builtin\" package return nil a Pkg().\n\t// But they are still real interfaces that we need to make a special case for.\n\t// Therefore, protect gopls from panicking if a new interface type was added in the future.\n\tif named.Obj().Pkg() == nil && named.Obj().Name() != \"error\" {\n\t\treturn nil\n\t}\n\treturn named.Obj()\n}\n\n// concreteType tries to extract the *types.Named that defines\n// the concrete type given the ast.Expr where the \"missing method\"\n// or \"conversion\" errors happened. If the concrete type is something\n// that cannot have methods defined on it (such as basic types), this\n// method will return a nil *types.Named. The second return parameter\n// is a boolean that indicates whether the concreteType was defined as a\n// pointer or value.\nfunc concreteType(e ast.Expr, info *types.Info) (*types.Named, bool) {\n\ttv, ok := info.Types[e]\n\tif !ok {\n\t\treturn nil, false\n\t}\n\ttyp := tv.Type\n\tptr, isPtr := types.Unalias(typ).(*types.Pointer)\n\tif isPtr {\n\t\ttyp = ptr.Elem()\n\t}\n\tnamed, ok := types.Unalias(typ).(*types.Named)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\treturn named, isPtr\n}\n"
  },
  {
    "path": "gopls/internal/golang/symbols.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc DocumentSymbols(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentSymbol, error) {\n\tctx, done := event.Start(ctx, \"golang.DocumentSymbols\")\n\tdefer done()\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting file for DocumentSymbols: %w\", err)\n\t}\n\n\t// Build symbols for file declarations. When encountering a declaration with\n\t// errors (typically because positions are invalid), we skip the declaration\n\t// entirely. VS Code fails to show any symbols if one of the top-level\n\t// symbols is missing position information.\n\tvar symbols []protocol.DocumentSymbol\n\tfor _, decl := range pgf.File.Decls {\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif decl.Name.Name == \"_\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfs, err := funcSymbol(pgf.Mapper, pgf.Tok, decl)\n\t\t\tif err == nil {\n\t\t\t\t// If function is a method, prepend the type of the method.\n\t\t\t\tif decl.Recv != nil && len(decl.Recv.List) > 0 {\n\t\t\t\t\tfs.Name = fmt.Sprintf(\"(%s).%s\", types.ExprString(decl.Recv.List[0].Type), fs.Name)\n\t\t\t\t}\n\t\t\t\tsymbols = append(symbols, fs)\n\t\t\t}\n\t\tcase *ast.GenDecl:\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tif spec.Name.Name == \"_\" {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tts, err := typeSymbol(pgf.Mapper, pgf.Tok, spec)\n\t\t\t\t\tif err == nil {\n\t\t\t\t\t\tsymbols = append(symbols, ts)\n\t\t\t\t\t}\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\tif name.Name == \"_\" {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvs, err := varSymbol(pgf.Mapper, pgf.Tok, spec, name, decl.Tok == token.CONST)\n\t\t\t\t\t\tif err == nil {\n\t\t\t\t\t\t\tsymbols = append(symbols, vs)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn symbols, nil\n}\n\n// PackageSymbols returns a list of symbols in the narrowest package for the given file (specified\n// by its URI).\n// Methods with receivers are stored as children under the symbol for their receiver type.\n// The PackageSymbol data type contains the same fields as protocol.DocumentSymbol, with\n// an additional int field \"File\" that stores the index of that symbol's file in the\n// PackageSymbolsResult.Files.\n// Symbols are gathered using syntax rather than type information because type checking is\n// significantly slower. Syntax information provides enough value to the user without\n// causing a lag when loading symbol information across different files.\nfunc PackageSymbols(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (command.PackageSymbolsResult, error) {\n\tctx, done := event.Start(ctx, \"source.PackageSymbols\")\n\tdefer done()\n\n\tpkgFiles := []protocol.DocumentURI{uri}\n\n\t// golang/vscode-go#3681: do our best if the file is not in a package.\n\t// TODO(rfindley): revisit this in the future once there is more graceful\n\t// handling in VS Code.\n\tif mp, err := snapshot.NarrowestMetadataForFile(ctx, uri); err == nil {\n\t\tpkgFiles = mp.CompiledGoFiles\n\t}\n\n\tvar (\n\t\tpkgName           string\n\t\tsymbols           []command.PackageSymbol\n\t\treceiverToMethods = make(map[string][]command.PackageSymbol) // receiver name -> methods\n\t\ttypeSymbolToIdx   = make(map[string]int)                     // type name -> index in symbols\n\t)\n\tfor fidx, f := range pkgFiles {\n\t\tfh, err := snapshot.ReadFile(ctx, f)\n\t\tif err != nil {\n\t\t\treturn command.PackageSymbolsResult{}, err\n\t\t}\n\t\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\t\tif err != nil {\n\t\t\treturn command.PackageSymbolsResult{}, err\n\t\t}\n\t\tif pkgName == \"\" && pgf.File != nil && pgf.File.Name != nil {\n\t\t\tpkgName = pgf.File.Name.Name\n\t\t}\n\t\tfor _, decl := range pgf.File.Decls {\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tif decl.Name.Name == \"_\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif fs, err := funcSymbol(pgf.Mapper, pgf.Tok, decl); err == nil {\n\t\t\t\t\t// If function is a method, prepend the type of the method.\n\t\t\t\t\t// Don't add the method as its own symbol; store it so we can\n\t\t\t\t\t// add it as a child of the receiver type later\n\t\t\t\t\tif decl.Recv != nil && len(decl.Recv.List) > 0 {\n\t\t\t\t\t\t_, rname, _ := astutil.UnpackRecv(decl.Recv.List[0].Type)\n\t\t\t\t\t\treceiverToMethods[rname.String()] = append(receiverToMethods[rname.String()], toPackageSymbol(fidx, fs))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsymbols = append(symbols, toPackageSymbol(fidx, fs))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t\tif spec.Name.Name == \"_\" {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ts, err := typeSymbol(pgf.Mapper, pgf.Tok, spec); err == nil {\n\t\t\t\t\t\t\ttypeSymbolToIdx[ts.Name] = len(symbols)\n\t\t\t\t\t\t\tsymbols = append(symbols, toPackageSymbol(fidx, ts))\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\t\tif name.Name == \"_\" {\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif vs, err := varSymbol(pgf.Mapper, pgf.Tok, spec, name, decl.Tok == token.CONST); err == nil {\n\t\t\t\t\t\t\t\tsymbols = append(symbols, toPackageSymbol(fidx, vs))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Add methods as the child of their receiver type symbol\n\tfor recv, methods := range receiverToMethods {\n\t\tif i, ok := typeSymbolToIdx[recv]; ok {\n\t\t\tsymbols[i].Children = append(symbols[i].Children, methods...)\n\t\t}\n\t}\n\treturn command.PackageSymbolsResult{\n\t\tPackageName: pkgName,\n\t\tFiles:       pkgFiles,\n\t\tSymbols:     symbols,\n\t}, nil\n}\n\nfunc toPackageSymbol(fileIndex int, s protocol.DocumentSymbol) command.PackageSymbol {\n\tvar res command.PackageSymbol\n\tres.Name = s.Name\n\tres.Detail = s.Detail\n\tres.Kind = s.Kind\n\tres.Tags = s.Tags\n\tres.Range = s.Range\n\tres.SelectionRange = s.SelectionRange\n\n\tchildren := make([]command.PackageSymbol, len(s.Children))\n\tfor i, c := range s.Children {\n\t\tchildren[i] = toPackageSymbol(fileIndex, c)\n\t}\n\tres.Children = children\n\n\tres.File = fileIndex\n\treturn res\n}\n\nfunc funcSymbol(m *protocol.Mapper, tf *token.File, decl *ast.FuncDecl) (protocol.DocumentSymbol, error) {\n\ts := protocol.DocumentSymbol{\n\t\tName: decl.Name.Name,\n\t\tKind: protocol.Function,\n\t}\n\tif decl.Recv != nil {\n\t\ts.Kind = protocol.Method\n\t}\n\tvar err error\n\ts.Range, err = m.NodeRange(tf, decl)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\ts.SelectionRange, err = m.NodeRange(tf, decl.Name)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\ts.Detail = types.ExprString(decl.Type)\n\treturn s, nil\n}\n\nfunc typeSymbol(m *protocol.Mapper, tf *token.File, spec *ast.TypeSpec) (protocol.DocumentSymbol, error) {\n\ts := protocol.DocumentSymbol{\n\t\tName: spec.Name.Name,\n\t}\n\tvar err error\n\ts.Range, err = m.NodeRange(tf, spec)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\ts.SelectionRange, err = m.NodeRange(tf, spec.Name)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\ts.Kind, s.Detail, s.Children = typeDetails(m, tf, spec.Type)\n\treturn s, nil\n}\n\nfunc typeDetails(m *protocol.Mapper, tf *token.File, typExpr ast.Expr) (kind protocol.SymbolKind, detail string, children []protocol.DocumentSymbol) {\n\tswitch typExpr := typExpr.(type) {\n\tcase *ast.StructType:\n\t\tkind = protocol.Struct\n\t\tchildren = fieldListSymbols(m, tf, typExpr.Fields, protocol.Field)\n\t\tif len(children) > 0 {\n\t\t\tdetail = \"struct{...}\"\n\t\t} else {\n\t\t\tdetail = \"struct{}\"\n\t\t}\n\n\t\t// Find interface methods and embedded types.\n\tcase *ast.InterfaceType:\n\t\tkind = protocol.Interface\n\t\tchildren = fieldListSymbols(m, tf, typExpr.Methods, protocol.Method)\n\t\tif len(children) > 0 {\n\t\t\tdetail = \"interface{...}\"\n\t\t} else {\n\t\t\tdetail = \"interface{}\"\n\t\t}\n\n\tcase *ast.FuncType:\n\t\tkind = protocol.Function\n\t\tdetail = types.ExprString(typExpr)\n\n\tdefault:\n\t\tkind = protocol.Class // catch-all, for cases where we don't know the kind syntactically\n\t\tdetail = types.ExprString(typExpr)\n\t}\n\treturn\n}\n\nfunc fieldListSymbols(m *protocol.Mapper, tf *token.File, fields *ast.FieldList, fieldKind protocol.SymbolKind) []protocol.DocumentSymbol {\n\tif fields == nil {\n\t\treturn nil\n\t}\n\n\tvar symbols []protocol.DocumentSymbol\n\tfor _, field := range fields.List {\n\t\tdetail, children := \"\", []protocol.DocumentSymbol(nil)\n\t\tif field.Type != nil {\n\t\t\t_, detail, children = typeDetails(m, tf, field.Type)\n\t\t}\n\t\tif len(field.Names) == 0 { // embedded interface or struct field\n\t\t\t// By default, use the formatted type details as the name of this field.\n\t\t\t// This handles potentially invalid syntax, as well as type embeddings in\n\t\t\t// interfaces.\n\t\t\tchild := protocol.DocumentSymbol{\n\t\t\t\tName:     detail,\n\t\t\t\tKind:     protocol.Field, // consider all embeddings to be fields\n\t\t\t\tChildren: children,\n\t\t\t}\n\n\t\t\t// If the field is a valid embedding, promote the type name to field\n\t\t\t// name.\n\t\t\tselection := field.Type\n\t\t\tif id := embeddedIdent(field.Type); id != nil {\n\t\t\t\tchild.Name = id.Name\n\t\t\t\tchild.Detail = detail\n\t\t\t\tselection = id\n\t\t\t}\n\n\t\t\tif rng, err := m.NodeRange(tf, field.Type); err == nil {\n\t\t\t\tchild.Range = rng\n\t\t\t}\n\t\t\tif rng, err := m.NodeRange(tf, selection); err == nil {\n\t\t\t\tchild.SelectionRange = rng\n\t\t\t}\n\n\t\t\tsymbols = append(symbols, child)\n\t\t} else {\n\t\t\tfor _, name := range field.Names {\n\t\t\t\tchild := protocol.DocumentSymbol{\n\t\t\t\t\tName:     name.Name,\n\t\t\t\t\tKind:     fieldKind,\n\t\t\t\t\tDetail:   detail,\n\t\t\t\t\tChildren: children,\n\t\t\t\t}\n\n\t\t\t\tif rng, err := m.NodeRange(tf, field); err == nil {\n\t\t\t\t\tchild.Range = rng\n\t\t\t\t}\n\t\t\t\tif rng, err := m.NodeRange(tf, name); err == nil {\n\t\t\t\t\tchild.SelectionRange = rng\n\t\t\t\t}\n\n\t\t\t\tsymbols = append(symbols, child)\n\t\t\t}\n\t\t}\n\n\t}\n\treturn symbols\n}\n\nfunc varSymbol(m *protocol.Mapper, tf *token.File, spec *ast.ValueSpec, name *ast.Ident, isConst bool) (protocol.DocumentSymbol, error) {\n\ts := protocol.DocumentSymbol{\n\t\tName: name.Name,\n\t\tKind: protocol.Variable,\n\t}\n\tif isConst {\n\t\ts.Kind = protocol.Constant\n\t}\n\tvar err error\n\ts.Range, err = m.NodeRange(tf, spec)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\ts.SelectionRange, err = m.NodeRange(tf, name)\n\tif err != nil {\n\t\treturn protocol.DocumentSymbol{}, err\n\t}\n\tif spec.Type != nil { // type may be missing from the syntax\n\t\t_, s.Detail, s.Children = typeDetails(m, tf, spec.Type)\n\t}\n\treturn s, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/type_definition.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// TypeDefinition handles the textDocument/typeDefinition request for Go files.\nfunc TypeDefinition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\tctx, done := event.Start(ctx, \"golang.TypeDefinition\")\n\tdefer done()\n\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _, _, _ := astutil.Select(pgf.Cursor(), start, end) // can't fail (start, end are within File)\n\n\t// Find innermost enclosing expression that has a type.\n\t// It needn't be an identifier.\n\tvar (\n\t\tinfo = pkg.TypesInfo()\n\t\tt    types.Type\n\t)\n\tfor cur := range cur.Enclosing() {\n\t\texpr, ok := cur.Node().(ast.Expr)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\t// edge case: switch id := expr.(type) {}\n\t\t// id has no type; use expr instead.\n\t\tif cur.ParentEdgeKind() == edge.AssignStmt_Lhs &&\n\t\t\tcur.Parent().ParentEdgeKind() == edge.TypeSwitchStmt_Assign {\n\t\t\texpr = cur.Parent().Node().(*ast.AssignStmt).Rhs[0].(*ast.TypeAssertExpr).X\n\t\t}\n\n\t\tif id, ok := expr.(*ast.Ident); ok {\n\t\t\tif obj := info.ObjectOf(id); obj != nil {\n\t\t\t\tt = obj.Type()\n\t\t\t}\n\t\t} else {\n\t\t\tt = info.TypeOf(expr)\n\t\t}\n\t\tif t != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\tif t == nil {\n\t\treturn nil, fmt.Errorf(\"no enclosing expression has a type\")\n\t}\n\ttnames := typeToObjects(t)\n\tif len(tnames) == 0 {\n\t\treturn nil, fmt.Errorf(\"cannot find type name(s) from type %s\", t)\n\t}\n\n\tvar locs []protocol.Location\n\tfor _, t := range tnames {\n\t\tloc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlocs = append(locs, loc)\n\t}\n\n\treturn locs, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/type_hierarchy.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/methodsets\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// Type hierarchy support (using method sets)\n//\n// TODO(adonovan):\n// - Support type hierarchy by signatures (using Kind=Function).\n//   As with Implementations by signature matching, needs more UX thought.\n//\n// - Allow methods too (using Kind=Method)? It's not exactly in the\n//   spirit of TypeHierarchy but it would be useful and it's easy\n//   enough to support.\n//\n// - fix pkg=command-line-arguments problem with query initiated at \"error\" in builtins.go\n\n// PrepareTypeHierarchy returns the TypeHierarchyItems for the types at the selected position.\nfunc PrepareTypeHierarchy(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.TypeHierarchyItem, error) {\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstart, end, err := pgf.RangePos(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// For now, we require that the selection be a type name.\n\tcur, ok := pgf.Cursor().FindByPos(start, end)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no enclosing syntax\") // can't happen\n\t}\n\tid, ok := cur.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"not a type name\")\n\t}\n\ttname, ok := pkg.TypesInfo().ObjectOf(id).(*types.TypeName)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"not a type name\")\n\t}\n\n\t// Find declaration.\n\tdeclLoc, err := ObjectLocation(ctx, pkg.FileSet(), snapshot, tname)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpkgpath := \"builtin\"\n\tif tname.Pkg() != nil {\n\t\tpkgpath = tname.Pkg().Path()\n\t}\n\n\treturn []protocol.TypeHierarchyItem{{\n\t\tName:           tname.Name(),\n\t\tKind:           cond(types.IsInterface(tname.Type()), protocol.Interface, protocol.Class),\n\t\tDetail:         pkgpath,\n\t\tURI:            declLoc.URI,\n\t\tRange:          declLoc.Range, // (in theory this should be the entire declaration)\n\t\tSelectionRange: declLoc.Range,\n\t}}, nil\n}\n\n// Subtypes reports information about subtypes of the selected type.\nfunc Subtypes(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, item protocol.TypeHierarchyItem) ([]protocol.TypeHierarchyItem, error) {\n\treturn relatedTypes(ctx, snapshot, fh, item, methodsets.Subtype)\n}\n\n// Supertypes reports information about supertypes of the selected type.\nfunc Supertypes(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, item protocol.TypeHierarchyItem) ([]protocol.TypeHierarchyItem, error) {\n\treturn relatedTypes(ctx, snapshot, fh, item, methodsets.Supertype)\n}\n\n// relatedTypes is the common implementation of {Super,Sub}types.\nfunc relatedTypes(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, item protocol.TypeHierarchyItem, rel methodsets.TypeRelation) ([]protocol.TypeHierarchyItem, error) {\n\tpkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpos, err := pgf.PositionPos(item.Range.Start)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcur, _ := pgf.Cursor().FindByPos(pos, pos) // can't fail\n\n\tvar (\n\t\titemsMu sync.Mutex\n\t\titems   []protocol.TypeHierarchyItem\n\t)\n\terr = implementationsMsets(ctx, snapshot, pkg, cur, rel, func(pkgpath metadata.PackagePath, name string, abstract bool, loc protocol.Location) {\n\t\tif pkgpath == \"\" {\n\t\t\tpkgpath = \"builtin\"\n\t\t}\n\n\t\titemsMu.Lock()\n\t\tdefer itemsMu.Unlock()\n\t\titems = append(items, protocol.TypeHierarchyItem{\n\t\t\tName:           name,\n\t\t\tKind:           cond(abstract, protocol.Interface, protocol.Class),\n\t\t\tDetail:         string(pkgpath),\n\t\t\tURI:            loc.URI,\n\t\t\tRange:          loc.Range, // (in theory this should be the entire declaration)\n\t\t\tSelectionRange: loc.Range,\n\t\t})\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Sort by (package, name, URI, range) then\n\t// de-duplicate based on the same 4-tuple\n\tcmp := func(x, y protocol.TypeHierarchyItem) int {\n\t\tif d := strings.Compare(x.Detail, y.Detail); d != 0 {\n\t\t\t// Rank the original item's package first.\n\t\t\tif d := boolCompare(x.Detail == item.Detail, y.Detail == item.Detail); d != 0 {\n\t\t\t\treturn -d\n\t\t\t}\n\t\t\treturn d\n\t\t}\n\t\tif d := strings.Compare(x.Name, y.Name); d != 0 {\n\t\t\treturn d\n\t\t}\n\t\tif d := strings.Compare(string(x.URI), string(y.URI)); d != 0 {\n\t\t\treturn d\n\t\t}\n\t\treturn protocol.CompareRange(x.SelectionRange, y.Range)\n\t}\n\tslices.SortFunc(items, cmp)\n\teq := func(x, y protocol.TypeHierarchyItem) bool { return cmp(x, y) == 0 }\n\titems = slices.CompactFunc(items, eq)\n\n\treturn items, nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/types_format.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/doc\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// FormatType returns the detail and kind for a types.Type.\nfunc FormatType(typ types.Type, qual types.Qualifier) (detail string, kind protocol.CompletionItemKind) {\n\ttyp = typ.Underlying()\n\tif types.IsInterface(typ) {\n\t\tdetail = \"interface{...}\"\n\t\tkind = protocol.InterfaceCompletion\n\t} else if _, ok := typ.(*types.Struct); ok {\n\t\tdetail = \"struct{...}\"\n\t\tkind = protocol.StructCompletion\n\t} else {\n\t\tdetail = types.TypeString(typ, qual)\n\t\tkind = protocol.ClassCompletion\n\t}\n\treturn detail, kind\n}\n\ntype signature struct {\n\tname, doc                   string\n\ttypeParams, params, results []string\n\tvariadic                    bool\n\tneedResultParens            bool\n}\n\nfunc (s *signature) Format() string {\n\tvar b strings.Builder\n\tb.WriteByte('(')\n\tfor i, p := range s.params {\n\t\tif i > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tb.WriteString(p)\n\t}\n\tb.WriteByte(')')\n\n\t// Add space between parameters and results.\n\tif len(s.results) > 0 {\n\t\tb.WriteByte(' ')\n\t}\n\tif s.needResultParens {\n\t\tb.WriteByte('(')\n\t}\n\tfor i, r := range s.results {\n\t\tif i > 0 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t\tb.WriteString(r)\n\t}\n\tif s.needResultParens {\n\t\tb.WriteByte(')')\n\t}\n\treturn b.String()\n}\n\nfunc (s *signature) TypeParams() []string {\n\treturn s.typeParams\n}\n\nfunc (s *signature) Params() []string {\n\treturn s.params\n}\n\n// NewBuiltinSignature returns signature for the builtin object with a given\n// name, if a builtin object with the name exists.\nfunc NewBuiltinSignature(ctx context.Context, s *cache.Snapshot, name string) (*signature, error) {\n\tbuiltin, err := s.BuiltinFile(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobj := builtin.File.Scope.Lookup(name)\n\tif obj == nil {\n\t\treturn nil, fmt.Errorf(\"no builtin object for %s\", name)\n\t}\n\tdecl, ok := obj.Decl.(*ast.FuncDecl)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no function declaration for builtin: %s\", name)\n\t}\n\tif decl.Type == nil {\n\t\treturn nil, fmt.Errorf(\"no type for builtin decl %s\", decl.Name)\n\t}\n\tvar variadic bool\n\tif decl.Type.Params.List != nil {\n\t\tnumParams := len(decl.Type.Params.List)\n\t\tlastParam := decl.Type.Params.List[numParams-1]\n\t\tif _, ok := lastParam.Type.(*ast.Ellipsis); ok {\n\t\t\tvariadic = true\n\t\t}\n\t}\n\tfset := tokeninternal.FileSetFor(builtin.Tok)\n\tparams, _ := formatFieldList(ctx, fset, decl.Type.Params, variadic)\n\tresults, needResultParens := formatFieldList(ctx, fset, decl.Type.Results, false)\n\td := decl.Doc.Text()\n\tswitch s.Options().HoverKind {\n\tcase settings.SynopsisDocumentation:\n\t\td = doc.Synopsis(d)\n\tcase settings.NoDocumentation:\n\t\td = \"\"\n\t}\n\treturn &signature{\n\t\tdoc:              d,\n\t\tname:             name,\n\t\tneedResultParens: needResultParens,\n\t\tparams:           params,\n\t\tresults:          results,\n\t\tvariadic:         variadic,\n\t}, nil\n}\n\n// replacer replaces some synthetic \"type classes\" used in the builtin file\n// with their most common constituent type.\nvar replacer = strings.NewReplacer(\n\t`ComplexType`, `complex128`,\n\t`FloatType`, `float64`,\n\t`IntegerType`, `int`,\n)\n\nfunc formatFieldList(ctx context.Context, fset *token.FileSet, list *ast.FieldList, variadic bool) ([]string, bool) {\n\tif list == nil {\n\t\treturn nil, false\n\t}\n\tvar writeResultParens bool\n\tvar result []string\n\tfor i := 0; i < len(list.List); i++ {\n\t\tif i >= 1 {\n\t\t\twriteResultParens = true\n\t\t}\n\t\tp := list.List[i]\n\t\tcfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4}\n\t\tb := &bytes.Buffer{}\n\t\tif err := cfg.Fprint(b, fset, p.Type); err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"error printing type %s\", types.ExprString(p.Type)), err)\n\t\t\tcontinue\n\t\t}\n\t\ttyp := replacer.Replace(b.String())\n\t\tif len(p.Names) == 0 {\n\t\t\tresult = append(result, typ)\n\t\t}\n\t\tfor _, name := range p.Names {\n\t\t\tif name.Name != \"\" {\n\t\t\t\tif i == 0 {\n\t\t\t\t\twriteResultParens = true\n\t\t\t\t}\n\t\t\t\tresult = append(result, fmt.Sprintf(\"%s %s\", name.Name, typ))\n\t\t\t} else {\n\t\t\t\tresult = append(result, typ)\n\t\t\t}\n\t\t}\n\t}\n\tif variadic {\n\t\tresult[len(result)-1] = strings.Replace(result[len(result)-1], \"[]\", \"...\", 1)\n\t}\n\treturn result, writeResultParens\n}\n\n// NewSignature returns formatted signature for a types.Signature struct.\nfunc NewSignature(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, sig *types.Signature, comment *ast.CommentGroup, qual types.Qualifier, mq MetadataQualifier) (*signature, error) {\n\tvar tparams []string\n\ttpList := sig.TypeParams()\n\tfor tparam := range tpList.TypeParams() {\n\t\t// TODO: is it possible to reuse the logic from FormatVarType here?\n\t\ts := tparam.Obj().Name() + \" \" + tparam.Constraint().String()\n\t\ttparams = append(tparams, s)\n\t}\n\n\tparams := make([]string, 0, sig.Params().Len())\n\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\tel := sig.Params().At(i)\n\t\ttyp, err := FormatVarType(ctx, s, pkg, el, qual, mq)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif sig.Variadic() && i == sig.Params().Len()-1 {\n\t\t\ttyp = strings.Replace(typ, \"[]\", \"...\", 1)\n\t\t}\n\t\tp := typ\n\t\tif el.Name() != \"\" {\n\t\t\tp = el.Name() + \" \" + typ\n\t\t}\n\t\tparams = append(params, p)\n\t}\n\n\tvar needResultParens bool\n\tresults := make([]string, 0, sig.Results().Len())\n\tfor i := 0; i < sig.Results().Len(); i++ {\n\t\tif i >= 1 {\n\t\t\tneedResultParens = true\n\t\t}\n\t\tel := sig.Results().At(i)\n\t\ttyp, err := FormatVarType(ctx, s, pkg, el, qual, mq)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif el.Name() == \"\" {\n\t\t\tresults = append(results, typ)\n\t\t} else {\n\t\t\tif i == 0 {\n\t\t\t\tneedResultParens = true\n\t\t\t}\n\t\t\tresults = append(results, el.Name()+\" \"+typ)\n\t\t}\n\t}\n\tvar d string\n\tif comment != nil {\n\t\td = comment.Text()\n\t}\n\tswitch s.Options().HoverKind {\n\tcase settings.SynopsisDocumentation:\n\t\td = doc.Synopsis(d)\n\tcase settings.NoDocumentation:\n\t\td = \"\"\n\t}\n\treturn &signature{\n\t\tdoc:              d,\n\t\ttypeParams:       tparams,\n\t\tparams:           params,\n\t\tresults:          results,\n\t\tvariadic:         sig.Variadic(),\n\t\tneedResultParens: needResultParens,\n\t}, nil\n}\n\n// We look for 'invalidTypeString' to determine if we can use the fast path for\n// FormatVarType.\nvar invalidTypeString = types.Typ[types.Invalid].String()\n\n// FormatVarType formats a *types.Var, accounting for type aliases.\n// To do this, it looks in the AST of the file in which the object is declared.\n// On any errors, it always falls back to types.TypeString.\n//\n// TODO(rfindley): this function could return the actual name used in syntax,\n// for better parameter names.\nfunc FormatVarType(ctx context.Context, snapshot *cache.Snapshot, srcpkg *cache.Package, obj *types.Var, qual types.Qualifier, mq MetadataQualifier) (string, error) {\n\ttypeString := types.TypeString(obj.Type(), qual)\n\t// Fast path: if the type string does not contain 'invalid type', we no\n\t// longer need to do any special handling, thanks to materialized aliases in\n\t// Go 1.23+.\n\t//\n\t// Unfortunately, due to the handling of invalid types, we can't quite delete\n\t// the rather complicated preexisting logic of FormatVarType--it isn't an\n\t// acceptable regression to start printing \"invalid type\" in completion or\n\t// signature help. strings.Contains is conservative: the type string of a\n\t// valid type may actually contain \"invalid type\" (due to struct tags or\n\t// field formatting), but such cases should be exceedingly rare.\n\tif !strings.Contains(typeString, invalidTypeString) {\n\t\treturn typeString, nil\n\t}\n\n\t// TODO(rfindley): This looks wrong. The previous comment said:\n\t// \"If the given expr refers to a type parameter, then use the\n\t// object's Type instead of the type parameter declaration. This helps\n\t// format the instantiated type as opposed to the original undeclared\n\t// generic type\".\n\t//\n\t// But of course, if obj is a type param, we are formatting a generic type\n\t// and not an instantiated type. Handling for instantiated types must be done\n\t// at a higher level.\n\t//\n\t// Left this during refactoring in order to preserve pre-existing logic.\n\tif typeparams.IsTypeParam(obj.Type()) {\n\t\treturn typeString, nil\n\t}\n\n\tif isBuiltin(obj) {\n\t\t// This is defensive, though it is extremely unlikely we'll ever have a\n\t\t// builtin var.\n\t\treturn typeString, nil\n\t}\n\n\t// TODO(rfindley): parsing to produce candidates can be costly; consider\n\t// using faster methods.\n\ttargetpgf, pos, err := parseFull(ctx, snapshot, srcpkg.FileSet(), obj)\n\tif err != nil {\n\t\treturn \"\", err // e.g. ctx cancelled\n\t}\n\n\ttargetMeta := findFileInDeps(snapshot, srcpkg.Metadata(), targetpgf.URI)\n\tif targetMeta == nil {\n\t\t// If we have an object from type-checking, it should exist in a file in\n\t\t// the forward transitive closure.\n\t\treturn \"\", bug.Errorf(\"failed to find file %q in deps of %q\", targetpgf.URI, srcpkg.Metadata().ID)\n\t}\n\n\tdecl, spec, field := findDeclInfo([]*ast.File{targetpgf.File}, pos)\n\n\t// We can't handle type parameters correctly, so we fall back on TypeString\n\t// for parameterized decls.\n\tif decl, _ := decl.(*ast.FuncDecl); decl != nil {\n\t\tif decl.Type.TypeParams.NumFields() > 0 {\n\t\t\treturn typeString, nil // in generic function\n\t\t}\n\t\tif decl.Recv != nil && len(decl.Recv.List) > 0 {\n\t\t\trtype := decl.Recv.List[0].Type\n\t\t\tif e, ok := rtype.(*ast.StarExpr); ok {\n\t\t\t\trtype = e.X\n\t\t\t}\n\t\t\tif x, _, _, _ := typeparams.UnpackIndexExpr(rtype); x != nil {\n\t\t\t\treturn typeString, nil // in method of generic type\n\t\t\t}\n\t\t}\n\t}\n\tif spec, _ := spec.(*ast.TypeSpec); spec != nil && spec.TypeParams.NumFields() > 0 {\n\t\treturn typeString, nil // in generic type decl\n\t}\n\n\tif field == nil {\n\t\t// TODO(rfindley): we should never reach here from an ordinary var, so\n\t\t// should probably return an error here.\n\t\treturn typeString, nil\n\t}\n\texpr := field.Type\n\n\trq := requalifier(snapshot, targetpgf.File, targetMeta, mq)\n\n\t// The type names in the AST may not be correctly qualified.\n\t// Determine the package name to use based on the package that originated\n\t// the query and the package in which the type is declared.\n\t// We then qualify the value by cloning the AST node and editing it.\n\texpr = qualifyTypeExpr(expr, rq)\n\n\t// If the request came from a different package than the one in which the\n\t// types are defined, we may need to modify the qualifiers.\n\treturn formatNodeFile(targetpgf.Tok, expr), nil\n}\n\n// qualifyTypeExpr clones the type expression expr after re-qualifying type\n// names using the given function, which accepts the current syntactic\n// qualifier (possibly \"\" for unqualified idents), and returns a new qualifier\n// (again, possibly \"\" if the identifier should be unqualified).\n//\n// The resulting expression may be inaccurate: without type-checking we don't\n// properly account for \".\" imported identifiers or builtins.\n//\n// TODO(rfindley): add many more tests for this function.\nfunc qualifyTypeExpr(expr ast.Expr, qf func(string) string) ast.Expr {\n\tswitch expr := expr.(type) {\n\tcase *ast.ArrayType:\n\t\treturn &ast.ArrayType{\n\t\t\tLbrack: expr.Lbrack,\n\t\t\tElt:    qualifyTypeExpr(expr.Elt, qf),\n\t\t\tLen:    expr.Len,\n\t\t}\n\n\tcase *ast.BinaryExpr:\n\t\tif expr.Op != token.OR {\n\t\t\treturn expr\n\t\t}\n\t\treturn &ast.BinaryExpr{\n\t\t\tX:     qualifyTypeExpr(expr.X, qf),\n\t\t\tOpPos: expr.OpPos,\n\t\t\tOp:    expr.Op,\n\t\t\tY:     qualifyTypeExpr(expr.Y, qf),\n\t\t}\n\n\tcase *ast.ChanType:\n\t\treturn &ast.ChanType{\n\t\t\tArrow: expr.Arrow,\n\t\t\tBegin: expr.Begin,\n\t\t\tDir:   expr.Dir,\n\t\t\tValue: qualifyTypeExpr(expr.Value, qf),\n\t\t}\n\n\tcase *ast.Ellipsis:\n\t\treturn &ast.Ellipsis{\n\t\t\tEllipsis: expr.Ellipsis,\n\t\t\tElt:      qualifyTypeExpr(expr.Elt, qf),\n\t\t}\n\n\tcase *ast.FuncType:\n\t\treturn &ast.FuncType{\n\t\t\tFunc:    expr.Func,\n\t\t\tParams:  qualifyFieldList(expr.Params, qf),\n\t\t\tResults: qualifyFieldList(expr.Results, qf),\n\t\t}\n\n\tcase *ast.Ident:\n\t\t// Unqualified type (builtin, package local, or dot-imported).\n\n\t\t// Don't qualify names that look like builtins.\n\t\t//\n\t\t// Without type-checking this may be inaccurate. It could be made accurate\n\t\t// by doing syntactic object resolution for the entire package, but that\n\t\t// does not seem worthwhile and we generally want to avoid using\n\t\t// ast.Object, which may be inaccurate.\n\t\tif obj := types.Universe.Lookup(expr.Name); obj != nil {\n\t\t\treturn expr\n\t\t}\n\n\t\tnewName := qf(\"\")\n\t\tif newName != \"\" {\n\t\t\treturn &ast.SelectorExpr{\n\t\t\t\tX: &ast.Ident{\n\t\t\t\t\tNamePos: expr.Pos(),\n\t\t\t\t\tName:    newName,\n\t\t\t\t},\n\t\t\t\tSel: expr,\n\t\t\t}\n\t\t}\n\t\treturn expr\n\n\tcase *ast.IndexExpr:\n\t\treturn &ast.IndexExpr{\n\t\t\tX:      qualifyTypeExpr(expr.X, qf),\n\t\t\tLbrack: expr.Lbrack,\n\t\t\tIndex:  qualifyTypeExpr(expr.Index, qf),\n\t\t\tRbrack: expr.Rbrack,\n\t\t}\n\n\tcase *ast.IndexListExpr:\n\t\tindices := make([]ast.Expr, len(expr.Indices))\n\t\tfor i, idx := range expr.Indices {\n\t\t\tindices[i] = qualifyTypeExpr(idx, qf)\n\t\t}\n\t\treturn &ast.IndexListExpr{\n\t\t\tX:       qualifyTypeExpr(expr.X, qf),\n\t\t\tLbrack:  expr.Lbrack,\n\t\t\tIndices: indices,\n\t\t\tRbrack:  expr.Rbrack,\n\t\t}\n\n\tcase *ast.InterfaceType:\n\t\treturn &ast.InterfaceType{\n\t\t\tInterface:  expr.Interface,\n\t\t\tMethods:    qualifyFieldList(expr.Methods, qf),\n\t\t\tIncomplete: expr.Incomplete,\n\t\t}\n\n\tcase *ast.MapType:\n\t\treturn &ast.MapType{\n\t\t\tMap:   expr.Map,\n\t\t\tKey:   qualifyTypeExpr(expr.Key, qf),\n\t\t\tValue: qualifyTypeExpr(expr.Value, qf),\n\t\t}\n\n\tcase *ast.ParenExpr:\n\t\treturn &ast.ParenExpr{\n\t\t\tLparen: expr.Lparen,\n\t\t\tRparen: expr.Rparen,\n\t\t\tX:      qualifyTypeExpr(expr.X, qf),\n\t\t}\n\n\tcase *ast.SelectorExpr:\n\t\tif id, ok := expr.X.(*ast.Ident); ok {\n\t\t\t// qualified type\n\t\t\tnewName := qf(id.Name)\n\t\t\tif newName == \"\" {\n\t\t\t\treturn expr.Sel\n\t\t\t}\n\t\t\treturn &ast.SelectorExpr{\n\t\t\t\tX: &ast.Ident{\n\t\t\t\t\tNamePos: id.NamePos,\n\t\t\t\t\tName:    newName,\n\t\t\t\t},\n\t\t\t\tSel: expr.Sel,\n\t\t\t}\n\t\t}\n\t\treturn expr\n\n\tcase *ast.StarExpr:\n\t\treturn &ast.StarExpr{\n\t\t\tStar: expr.Star,\n\t\t\tX:    qualifyTypeExpr(expr.X, qf),\n\t\t}\n\n\tcase *ast.StructType:\n\t\treturn &ast.StructType{\n\t\t\tStruct:     expr.Struct,\n\t\t\tFields:     qualifyFieldList(expr.Fields, qf),\n\t\t\tIncomplete: expr.Incomplete,\n\t\t}\n\n\tdefault:\n\t\treturn expr\n\t}\n}\n\nfunc qualifyFieldList(fl *ast.FieldList, qf func(string) string) *ast.FieldList {\n\tif fl == nil {\n\t\treturn nil\n\t}\n\tif fl.List == nil {\n\t\treturn &ast.FieldList{\n\t\t\tClosing: fl.Closing,\n\t\t\tOpening: fl.Opening,\n\t\t}\n\t}\n\tlist := make([]*ast.Field, 0, len(fl.List))\n\tfor _, f := range fl.List {\n\t\tlist = append(list, &ast.Field{\n\t\t\tComment: f.Comment,\n\t\t\tDoc:     f.Doc,\n\t\t\tNames:   f.Names,\n\t\t\tTag:     f.Tag,\n\t\t\tType:    qualifyTypeExpr(f.Type, qf),\n\t\t})\n\t}\n\treturn &ast.FieldList{\n\t\tClosing: fl.Closing,\n\t\tOpening: fl.Opening,\n\t\tList:    list,\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/golang/undeclared.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/util/cursorutil\"\n\t\"golang.org/x/tools/gopls/internal/util/typesutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// The prefix for this error message changed in Go 1.20.\nvar undeclaredNamePrefixes = []string{\"undeclared name: \", \"undefined: \"}\n\n// undeclaredFixTitle generates a code action title for \"undeclared name\" errors,\n// suggesting the creation of the missing variable or function if applicable.\nfunc undeclaredFixTitle(curId inspector.Cursor, errMsg string) string {\n\t// Extract symbol name from error.\n\tvar name string\n\tfor _, prefix := range undeclaredNamePrefixes {\n\t\tif !strings.HasPrefix(errMsg, prefix) {\n\t\t\tcontinue\n\t\t}\n\t\tname = strings.TrimPrefix(errMsg, prefix)\n\t}\n\tident, ok := curId.Node().(*ast.Ident)\n\tif !ok || ident.Name != name {\n\t\treturn \"\"\n\t}\n\t// TODO: support create undeclared field\n\tif _, ok := curId.Parent().Node().(*ast.SelectorExpr); ok {\n\t\treturn \"\"\n\t}\n\n\t// Undeclared quick fixes only work in function bodies.\n\tblock, _ := cursorutil.FirstEnclosing[*ast.BlockStmt](curId)\n\tif block == nil {\n\t\treturn \"\"\n\t}\n\n\t// Offer a fix.\n\tnoun := cond(curId.ParentEdgeKind() == edge.CallExpr_Fun, \"function\", \"variable\")\n\treturn fmt.Sprintf(\"Create %s %s\", noun, name)\n}\n\n// createUndeclared generates a suggested declaration for an undeclared variable or function.\nfunc createUndeclared(pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error) {\n\tvar (\n\t\tfset = pkg.FileSet()\n\t\tinfo = pkg.TypesInfo()\n\t\tfile = pgf.File\n\t\tpos  = start // don't use end\n\t)\n\tcurId, _ := pgf.Cursor().FindByPos(pos, pos)\n\tident, ok := curId.Node().(*ast.Ident)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"no identifier found\")\n\t}\n\n\t// Check for a possible call expression, in which case we should add a\n\t// new function declaration.\n\tif curId.ParentEdgeKind() == edge.CallExpr_Fun {\n\t\treturn newFunctionDeclaration(curId, file, pkg.Types(), info, fset)\n\t}\n\t// We should insert the new declaration before the\n\t// first occurrence of the undefined ident.\n\tvar curFirstRef inspector.Cursor // *ast.Ident\n\n\t// Search from enclosing FuncDecl to first use, since we can not use := syntax outside function.\n\t// Adds the missing colon under the following conditions:\n\t// 1) parent node must be an *ast.AssignStmt with Tok set to token.ASSIGN.\n\t// 2) ident must not be self assignment.\n\t//\n\t// For example, we should not add a colon when\n\t// a = a + 1\n\t// ^   ^ cursor here\n\t_, curFuncDecl := cursorutil.FirstEnclosing[*ast.FuncDecl](curId)\n\tfor curRef := range curFuncDecl.Preorder((*ast.Ident)(nil)) {\n\t\tn := curRef.Node().(*ast.Ident)\n\t\tif n.Name == ident.Name && info.ObjectOf(n) == nil {\n\t\t\tif curRef.ParentEdgeKind() == edge.AssignStmt_Lhs {\n\t\t\t\tassign := curRef.Parent().Node().(*ast.AssignStmt)\n\t\t\t\tif assign.Tok == token.ASSIGN && !referencesIdent(info, assign, ident) {\n\t\t\t\t\t// replace = with :=\n\t\t\t\t\treturn fset, &analysis.SuggestedFix{\n\t\t\t\t\t\tTextEdits: []analysis.TextEdit{{\n\t\t\t\t\t\t\tPos:     assign.TokPos,\n\t\t\t\t\t\t\tEnd:     assign.TokPos,\n\t\t\t\t\t\t\tNewText: []byte(\":\"),\n\t\t\t\t\t\t}},\n\t\t\t\t\t}, nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurFirstRef = curRef\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// firstRef should never be nil; at least one ident at cursor\n\t// position should be found. But be defensive.\n\tif !curFirstRef.Valid() {\n\t\treturn nil, nil, fmt.Errorf(\"no identifier found\")\n\t}\n\tinsertPos, err := stmtToInsertVarBefore(curFirstRef, nil)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"could not locate insertion point: %v\", err)\n\t}\n\tindent, err := pgf.Indentation(insertPos)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\ttyps := typesutil.TypesFromContext(info, curId)\n\tif typs == nil {\n\t\t// Default to 0.\n\t\ttyps = []types.Type{types.Typ[types.Int]}\n\t}\n\texpr, _ := typesinternal.ZeroExpr(typs[0], typesinternal.FileQualifier(file, pkg.Types()))\n\tassignStmt := &ast.AssignStmt{\n\t\tLhs: []ast.Expr{ast.NewIdent(ident.Name)},\n\t\tTok: token.DEFINE,\n\t\tRhs: []ast.Expr{expr},\n\t}\n\tvar buf bytes.Buffer\n\tif err := format.Node(&buf, fset, assignStmt); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tnewLineIndent := \"\\n\" + indent\n\tassignment := strings.ReplaceAll(buf.String(), \"\\n\", newLineIndent) + newLineIndent\n\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: []analysis.TextEdit{\n\t\t\t{\n\t\t\t\tPos:     insertPos,\n\t\t\t\tEnd:     insertPos,\n\t\t\t\tNewText: []byte(assignment),\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\n// referencesIdent checks whether the given undefined ident appears in the right-hand side\n// of an assign statement\nfunc referencesIdent(info *types.Info, assign *ast.AssignStmt, ident *ast.Ident) bool {\n\tfor _, rhs := range assign.Rhs {\n\t\tfor n := range ast.Preorder(rhs) {\n\t\t\tif id, ok := n.(*ast.Ident); ok &&\n\t\t\t\tid.Name == ident.Name && info.Uses[id] == nil {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// newFunctionDeclaration returns a suggested declaration for the ident identified by curId\n// curId always points at an ast.Ident at the CallExpr_Fun edge.\nfunc newFunctionDeclaration(curId inspector.Cursor, file *ast.File, pkg *types.Package, info *types.Info, fset *token.FileSet) (*token.FileSet, *analysis.SuggestedFix, error) {\n\n\tid := curId.Node().(*ast.Ident)\n\tcall := curId.Parent().Node().(*ast.CallExpr)\n\n\t// Find the enclosing function, so that we can add the new declaration\n\t// below.\n\tfuncdecl, _ := cursorutil.FirstEnclosing[*ast.FuncDecl](curId)\n\tif funcdecl == nil {\n\t\t// TODO(rstambler): Support the situation when there is no enclosing\n\t\t// function.\n\t\treturn nil, nil, fmt.Errorf(\"no enclosing function found: %v\", curId)\n\t}\n\n\tpos := funcdecl.End()\n\n\tvar paramNames []string\n\tvar paramTypes []types.Type\n\t// keep track of all param names to later ensure uniqueness\n\tnameCounts := map[string]int{}\n\tfor _, arg := range call.Args {\n\t\ttyp := info.TypeOf(arg)\n\t\tif typ == nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"unable to determine type for %s\", arg)\n\t\t}\n\n\t\tswitch t := typ.(type) {\n\t\t// this is the case where another function call returning multiple\n\t\t// results is used as an argument\n\t\tcase *types.Tuple:\n\t\t\tn := t.Len()\n\t\t\tfor i := range n {\n\t\t\t\tname := typeToArgName(t.At(i).Type())\n\t\t\t\tnameCounts[name]++\n\n\t\t\t\tparamNames = append(paramNames, name)\n\t\t\t\tparamTypes = append(paramTypes, types.Default(t.At(i).Type()))\n\t\t\t}\n\n\t\tdefault:\n\t\t\t// does the argument have a name we can reuse?\n\t\t\t// only happens in case of a *ast.Ident\n\t\t\tvar name string\n\t\t\tif ident, ok := arg.(*ast.Ident); ok {\n\t\t\t\tname = ident.Name\n\t\t\t}\n\n\t\t\tif name == \"\" {\n\t\t\t\tname = typeToArgName(typ)\n\t\t\t}\n\n\t\t\tnameCounts[name]++\n\n\t\t\tparamNames = append(paramNames, name)\n\t\t\tparamTypes = append(paramTypes, types.Default(typ))\n\t\t}\n\t}\n\n\tfor n, c := range nameCounts {\n\t\t// Any names we saw more than once will need a unique suffix added\n\t\t// on. Reset the count to 1 to act as the suffix for the first\n\t\t// occurrence of that name.\n\t\tif c >= 2 {\n\t\t\tnameCounts[n] = 1\n\t\t} else {\n\t\t\tdelete(nameCounts, n)\n\t\t}\n\t}\n\n\tparams := &ast.FieldList{}\n\tqual := typesinternal.FileQualifier(file, pkg)\n\tfor i, name := range paramNames {\n\t\tif suffix, repeats := nameCounts[name]; repeats {\n\t\t\tnameCounts[name]++\n\t\t\tname = fmt.Sprintf(\"%s%d\", name, suffix)\n\t\t}\n\n\t\t// only worth checking after previous param in the list\n\t\tif i > 0 {\n\t\t\t// if type of parameter at hand is the same as the previous one,\n\t\t\t// add it to the previous param list of identifiers so to have:\n\t\t\t//  (s1, s2 string)\n\t\t\t// and not\n\t\t\t//  (s1 string, s2 string)\n\t\t\tif paramTypes[i] == paramTypes[i-1] {\n\t\t\t\tparams.List[len(params.List)-1].Names = append(params.List[len(params.List)-1].Names, ast.NewIdent(name))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tparams.List = append(params.List, &ast.Field{\n\t\t\tNames: []*ast.Ident{\n\t\t\t\tast.NewIdent(name),\n\t\t\t},\n\t\t\tType: typesinternal.TypeExpr(paramTypes[i], qual),\n\t\t})\n\t}\n\n\trets := &ast.FieldList{}\n\tretTypes := typesutil.TypesFromContext(info, curId.Parent())\n\tfor _, rt := range retTypes {\n\t\trets.List = append(rets.List, &ast.Field{\n\t\t\tType: typesinternal.TypeExpr(rt, qual),\n\t\t})\n\t}\n\n\tdecl := &ast.FuncDecl{\n\t\tName: ast.NewIdent(id.Name),\n\t\tType: &ast.FuncType{\n\t\t\tParams:  params,\n\t\t\tResults: rets,\n\t\t},\n\t\tBody: &ast.BlockStmt{\n\t\t\tList: []ast.Stmt{\n\t\t\t\t&ast.ExprStmt{\n\t\t\t\t\tX: &ast.CallExpr{\n\t\t\t\t\t\tFun: ast.NewIdent(\"panic\"),\n\t\t\t\t\t\tArgs: []ast.Expr{\n\t\t\t\t\t\t\t&ast.BasicLit{\n\t\t\t\t\t\t\t\tValue: `\"unimplemented\"`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tb := bytes.NewBufferString(\"\\n\\n\")\n\tif err := format.Node(b, fset, decl); err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn fset, &analysis.SuggestedFix{\n\t\tTextEdits: []analysis.TextEdit{{\n\t\t\tPos:     pos,\n\t\t\tEnd:     pos,\n\t\t\tNewText: b.Bytes(),\n\t\t}},\n\t}, nil\n}\n\nfunc typeToArgName(ty types.Type) string {\n\ts := types.Default(ty).String()\n\n\tswitch t := types.Unalias(ty).(type) {\n\tcase *types.Basic:\n\t\t// use first letter in type name for basic types\n\t\treturn s[0:1]\n\tcase *types.Slice:\n\t\t// use element type to decide var name for slices\n\t\treturn typeToArgName(t.Elem())\n\tcase *types.Array:\n\t\t// use element type to decide var name for arrays\n\t\treturn typeToArgName(t.Elem())\n\tcase *types.Chan:\n\t\treturn \"ch\"\n\t}\n\n\ts = strings.TrimFunc(s, func(r rune) bool {\n\t\treturn !unicode.IsLetter(r)\n\t})\n\n\tif s == \"error\" {\n\t\treturn \"err\"\n\t}\n\n\t// remove package (if present)\n\t// and make first letter lowercase\n\ta := []rune(s[strings.LastIndexByte(s, '.')+1:])\n\ta[0] = unicode.ToLower(a[0])\n\treturn string(a)\n}\n"
  },
  {
    "path": "gopls/internal/golang/util.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"context\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n)\n\n// IsGenerated reads and parses the header of the file denoted by uri\n// and reports whether it [ast.IsGenerated].\nfunc IsGenerated(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) bool {\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn false\n\t}\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Header)\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn ast.IsGenerated(pgf.File)\n}\n\n// FormatNode returns the \"pretty-print\" output for an ast node.\nfunc FormatNode(fset *token.FileSet, n ast.Node) string {\n\tvar buf strings.Builder\n\tif err := printer.Fprint(&buf, fset, n); err != nil {\n\t\t// TODO(rfindley): we should use bug.Reportf here.\n\t\t// We encounter this during completion.resolveInvalid.\n\t\treturn \"\"\n\t}\n\treturn buf.String()\n}\n\n// formatNodeFile is like FormatNode, but requires only the token.File for the\n// syntax containing the given ast node.\nfunc formatNodeFile(file *token.File, n ast.Node) string {\n\tfset := tokeninternal.FileSetFor(file)\n\treturn FormatNode(fset, n)\n}\n\n// findFileInDeps finds package metadata containing URI in the transitive\n// dependencies of m. When using the Go command, the answer is unique.\nfunc findFileInDeps(s metadata.Source, mp *metadata.Package, uri protocol.DocumentURI) *metadata.Package {\n\tseen := make(map[PackageID]bool)\n\tvar search func(*metadata.Package) *metadata.Package\n\tsearch = func(mp *metadata.Package) *metadata.Package {\n\t\tif seen[mp.ID] {\n\t\t\treturn nil\n\t\t}\n\t\tseen[mp.ID] = true\n\t\tif slices.Contains(mp.CompiledGoFiles, uri) {\n\t\t\treturn mp\n\t\t}\n\t\tfor _, dep := range mp.DepsByPkgPath {\n\t\t\tmp := s.Metadata(dep)\n\t\t\tif mp == nil {\n\t\t\t\tbug.Reportf(\"nil metadata for %q\", dep)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif found := search(mp); found != nil {\n\t\t\t\treturn found\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn search(mp)\n}\n\n// requalifier returns a function that re-qualifies identifiers and qualified\n// identifiers contained in targetFile using the given metadata qualifier.\nfunc requalifier(s metadata.Source, targetFile *ast.File, targetMeta *metadata.Package, mq MetadataQualifier) func(string) string {\n\tqm := map[string]string{\n\t\t\"\": mq(targetMeta.Name, \"\", targetMeta.PkgPath),\n\t}\n\n\t// Construct mapping of import paths to their defined or implicit names.\n\tfor _, imp := range targetFile.Imports {\n\t\tname, pkgName, impPath, pkgPath := importInfo(s, imp, targetMeta)\n\n\t\t// Re-map the target name for the source file.\n\t\tqm[name] = mq(pkgName, impPath, pkgPath)\n\t}\n\n\treturn func(name string) string {\n\t\tif newName, ok := qm[name]; ok {\n\t\t\treturn newName\n\t\t}\n\t\treturn name\n\t}\n}\n\n// A MetadataQualifier is a function that qualifies an identifier declared in a\n// package with the given package name, import path, and package path.\n//\n// In scenarios where metadata is missing the provided PackageName and\n// PackagePath may be empty, but ImportPath must always be non-empty.\ntype MetadataQualifier func(PackageName, ImportPath, PackagePath) string\n\n// MetadataQualifierForFile returns a metadata qualifier that chooses the best\n// qualification of an imported package relative to the file f in package with\n// metadata m.\nfunc MetadataQualifierForFile(s metadata.Source, f *ast.File, mp *metadata.Package) MetadataQualifier {\n\t// Record local names for import paths.\n\tlocalNames := make(map[ImportPath]string) // local names for imports in f\n\tfor _, imp := range f.Imports {\n\t\tname, _, impPath, _ := importInfo(s, imp, mp)\n\t\tlocalNames[impPath] = name\n\t}\n\n\t// Record a package path -> import path mapping.\n\tinverseDeps := make(map[PackageID]PackagePath)\n\tfor path, id := range mp.DepsByPkgPath {\n\t\tinverseDeps[id] = path\n\t}\n\timportsByPkgPath := make(map[PackagePath]ImportPath) // best import paths by pkgPath\n\tfor impPath, id := range mp.DepsByImpPath {\n\t\tif id == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tpkgPath := inverseDeps[id]\n\t\t_, hasPath := importsByPkgPath[pkgPath]\n\t\t_, hasImp := localNames[impPath]\n\t\t// In rare cases, there may be multiple import paths with the same package\n\t\t// path. In such scenarios, prefer an import path that already exists in\n\t\t// the file.\n\t\tif !hasPath || hasImp {\n\t\t\timportsByPkgPath[pkgPath] = impPath\n\t\t}\n\t}\n\n\treturn func(pkgName PackageName, impPath ImportPath, pkgPath PackagePath) string {\n\t\t// If supplied, translate the package path to an import path in the source\n\t\t// package.\n\t\tif pkgPath != \"\" {\n\t\t\tif srcImp := importsByPkgPath[pkgPath]; srcImp != \"\" {\n\t\t\t\timpPath = srcImp\n\t\t\t}\n\t\t\tif pkgPath == mp.PkgPath {\n\t\t\t\treturn \"\"\n\t\t\t}\n\t\t}\n\t\tif localName, ok := localNames[impPath]; ok && impPath != \"\" {\n\t\t\treturn localName\n\t\t}\n\t\tif pkgName != \"\" {\n\t\t\treturn string(pkgName)\n\t\t}\n\t\tidx := strings.LastIndexByte(string(impPath), '/')\n\t\treturn string(impPath[idx+1:])\n\t}\n}\n\n// importInfo collects information about the import specified by imp,\n// extracting its file-local name, package name, import path, and package path.\n//\n// If metadata is missing for the import, the resulting package name and\n// package path may be empty, and the file local name may be guessed based on\n// the import path.\n//\n// Note: previous versions of this helper used a PackageID->PackagePath map\n// extracted from m, for extracting package path even in the case where\n// metadata for a dep was missing. This should not be necessary, as we should\n// always have metadata for IDs contained in DepsByPkgPath.\nfunc importInfo(s metadata.Source, imp *ast.ImportSpec, mp *metadata.Package) (string, PackageName, ImportPath, PackagePath) {\n\tvar (\n\t\tname    string // local name\n\t\tpkgName PackageName\n\t\timpPath = metadata.UnquoteImportPath(imp)\n\t\tpkgPath PackagePath\n\t)\n\n\t// If the import has a local name, use it.\n\tif imp.Name != nil {\n\t\tname = imp.Name.Name\n\t}\n\n\t// Try to find metadata for the import. If successful and there is no local\n\t// name, the package name is the local name.\n\tif depID := mp.DepsByImpPath[impPath]; depID != \"\" {\n\t\tif depMP := s.Metadata(depID); depMP != nil {\n\t\t\tif name == \"\" {\n\t\t\t\tname = string(depMP.Name)\n\t\t\t}\n\t\t\tpkgName = depMP.Name\n\t\t\tpkgPath = depMP.PkgPath\n\t\t}\n\t}\n\n\t// If the local name is still unknown, guess it based on the import path.\n\tif name == \"\" {\n\t\tidx := strings.LastIndexByte(string(impPath), '/')\n\t\tname = string(impPath[idx+1:])\n\t}\n\treturn name, pkgName, impPath, pkgPath\n}\n\n// isDirective reports whether c is a comment directive.\n//\n// Copied and adapted from go/src/go/ast/ast.go.\nfunc isDirective(c string) bool {\n\tif len(c) < 3 {\n\t\treturn false\n\t}\n\tif c[1] != '/' {\n\t\treturn false\n\t}\n\t//-style comment (no newline at the end)\n\tc = c[2:]\n\tif len(c) == 0 {\n\t\t// empty line\n\t\treturn false\n\t}\n\t// \"//line \" is a line directive.\n\t// (The // has been removed.)\n\tif strings.HasPrefix(c, \"line \") {\n\t\treturn true\n\t}\n\n\t// \"//[a-z0-9]+:[a-z0-9]\"\n\t// (The // has been removed.)\n\tcolon := strings.Index(c, \":\")\n\tif colon <= 0 || colon+1 >= len(c) {\n\t\treturn false\n\t}\n\tfor i := 0; i <= colon+1; i++ {\n\t\tif i == colon {\n\t\t\tcontinue\n\t\t}\n\t\tb := c[i]\n\t\tif !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// embeddedIdent returns the type name identifier for an embedding x, if x in a\n// valid embedding. Otherwise, it returns nil.\n//\n// Spec: An embedded field must be specified as a type name T or as a pointer\n// to a non-interface type name *T\nfunc embeddedIdent(x ast.Expr) *ast.Ident {\n\tif star, ok := x.(*ast.StarExpr); ok {\n\t\tx = star.X\n\t}\n\tswitch ix := x.(type) { // check for instantiated receivers\n\tcase *ast.IndexExpr:\n\t\tx = ix.X\n\tcase *ast.IndexListExpr:\n\t\tx = ix.X\n\t}\n\tswitch x := x.(type) {\n\tcase *ast.Ident:\n\t\treturn x\n\tcase *ast.SelectorExpr:\n\t\tif _, ok := x.X.(*ast.Ident); ok {\n\t\t\treturn x.Sel\n\t\t}\n\t}\n\treturn nil\n}\n\n// An importFunc is an implementation of the single-method\n// types.Importer interface based on a function value.\ntype ImporterFunc func(path string) (*types.Package, error)\n\nfunc (f ImporterFunc) Import(path string) (*types.Package, error) { return f(path) }\n\n// isBuiltin reports whether obj is a built-in symbol (e.g. append, iota, error.Error, unsafe.Slice).\n// All other symbols have a valid position and a valid package.\nfunc isBuiltin(obj types.Object) bool { return !obj.Pos().IsValid() }\n\n// btoi returns int(b) as proposed in #64825.\nfunc btoi(b bool) int {\n\tif b {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\n// boolCompare is a comparison function for booleans, returning -1 if x < y, 0\n// if x == y, and 1 if x > y, where false < true.\nfunc boolCompare(x, y bool) int {\n\treturn btoi(x) - btoi(y)\n}\n\n// AbbreviateVarName returns an abbreviated var name based on the given full\n// name (which may be a type name, for example).\n//\n// See the simple heuristics documented in line.\nfunc AbbreviateVarName(s string) string {\n\tvar (\n\t\tb            strings.Builder\n\t\tuseNextUpper bool\n\t)\n\tfor i, r := range s {\n\t\t// Stop if we encounter a non-identifier rune.\n\t\tif !unicode.IsLetter(r) && !unicode.IsNumber(r) {\n\t\t\tbreak\n\t\t}\n\n\t\t// Otherwise, take the first letter from word boundaries, assuming\n\t\t// camelCase.\n\t\tif i == 0 {\n\t\t\tb.WriteRune(unicode.ToLower(r))\n\t\t}\n\n\t\tif unicode.IsUpper(r) {\n\t\t\tif useNextUpper {\n\t\t\t\tb.WriteRune(unicode.ToLower(r))\n\t\t\t\tuseNextUpper = false\n\t\t\t}\n\t\t} else {\n\t\t\tuseNextUpper = true\n\t\t}\n\t}\n\treturn b.String()\n}\n\n// CopyrightComment returns the copyright comment group from the input file, or\n// nil if not found.\nfunc CopyrightComment(file *ast.File) *ast.CommentGroup {\n\tif len(file.Comments) == 0 {\n\t\treturn nil\n\t}\n\n\t// Copyright should appear before package decl and must be the first\n\t// comment group.\n\tif c := file.Comments[0]; c.Pos() < file.Package && c != file.Doc &&\n\t\t!isDirective(c.List[0].Text) &&\n\t\tstrings.Contains(strings.ToLower(c.List[0].Text), \"copyright\") {\n\t\treturn c\n\t}\n\n\treturn nil\n}\n\nvar buildConstraintRe = regexp.MustCompile(`^//(go:build|\\s*\\+build).*`)\n\n// buildConstraintComment returns the build constraint comment from the input\n// file.\n// Returns nil if not found.\nfunc buildConstraintComment(file *ast.File) *ast.Comment {\n\tfor _, cg := range file.Comments {\n\t\t// In Go files a build constraint must appear before the package clause.\n\t\t// See https://pkg.go.dev/cmd/go#hdr-Build_constraints\n\t\tif cg.Pos() > file.Package {\n\t\t\treturn nil\n\t\t}\n\n\t\tfor _, c := range cg.List {\n\t\t\t// TODO: use ast.ParseDirective when available (#68021).\n\t\t\tif buildConstraintRe.MatchString(c.Text) {\n\t\t\t\treturn c\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/golang/workspace_symbol.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/symbols\"\n\t\"golang.org/x/tools/gopls/internal/fuzzy\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// maxSymbols defines the maximum number of symbol results that should ever be\n// sent in response to a client.\nconst maxSymbols = 100\n\n// WorkspaceSymbols matches symbols across all views using the given query,\n// according to the match semantics parameterized by matcherType and style.\n//\n// The workspace symbol method is defined in the spec as follows:\n//\n//\tThe workspace symbol request is sent from the client to the server to\n//\tlist project-wide symbols matching the query string.\n//\n// It is unclear what \"project-wide\" means here, but given the parameters of\n// workspace/symbol do not include any workspace identifier, then it has to be\n// assumed that \"project-wide\" means \"across all workspaces\".  Hence why\n// WorkspaceSymbols receives the views []View.\n//\n// However, it then becomes unclear what it would mean to call WorkspaceSymbols\n// with a different configured SymbolMatcher per View. Therefore we assume that\n// Session level configuration will define the SymbolMatcher to be used for the\n// WorkspaceSymbols method.\nfunc WorkspaceSymbols(ctx context.Context, matcher settings.SymbolMatcher, style settings.SymbolStyle, snapshots []*cache.Snapshot, query string) ([]protocol.SymbolInformation, error) {\n\tctx, done := event.Start(ctx, \"golang.WorkspaceSymbols\")\n\tdefer done()\n\tif query == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tvar s symbolizer\n\tswitch style {\n\tcase settings.DynamicSymbols:\n\t\ts = dynamicSymbolMatch\n\tcase settings.FullyQualifiedSymbols:\n\t\ts = fullyQualifiedSymbolMatch\n\tcase settings.PackageQualifiedSymbols:\n\t\ts = packageSymbolMatch\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unknown symbol style: %v\", style))\n\t}\n\n\treturn collectSymbols(ctx, snapshots, matcher, s, query)\n}\n\n// A matcherFunc returns the index and score of a symbol match.\n//\n// See the comment for symbolCollector for more information.\ntype matcherFunc func(chunks []string) (int, float64)\n\n// A symbolizer returns the best symbol match for a name with pkg, according to\n// some heuristic. The symbol name is passed as the slice nameParts of logical\n// name pieces. For example, for myType.field the caller can pass either\n// []string{\"myType.field\"} or []string{\"myType.\", \"field\"}.\n//\n// See the comment for symbolCollector for more information.\n//\n// The space argument is an empty slice with spare capacity that may be used\n// to allocate the result.\ntype symbolizer func(space []string, name string, pkg *metadata.Package, m matcherFunc) ([]string, float64)\n\nfunc fullyQualifiedSymbolMatch(space []string, name string, pkg *metadata.Package, matcher matcherFunc) ([]string, float64) {\n\tif _, score := dynamicSymbolMatch(space, name, pkg, matcher); score > 0 {\n\t\treturn append(space, string(pkg.PkgPath), \".\", name), score\n\t}\n\treturn nil, 0\n}\n\nfunc dynamicSymbolMatch(space []string, name string, pkg *metadata.Package, matcher matcherFunc) ([]string, float64) {\n\tif metadata.IsCommandLineArguments(pkg.ID) {\n\t\t// command-line-arguments packages have a non-sensical package path, so\n\t\t// just use their package name.\n\t\treturn packageSymbolMatch(space, name, pkg, matcher)\n\t}\n\n\tvar score float64\n\n\tendsInPkgName := strings.HasSuffix(string(pkg.PkgPath), string(pkg.Name))\n\n\t// If the package path does not end in the package name, we need to check the\n\t// package-qualified symbol as an extra pass first.\n\tif !endsInPkgName {\n\t\tpkgQualified := append(space, string(pkg.Name), \".\", name)\n\t\tidx, score := matcher(pkgQualified)\n\t\tnameStart := len(pkg.Name) + 1\n\t\tif score > 0 {\n\t\t\t// If our match is contained entirely within the unqualified portion,\n\t\t\t// just return that.\n\t\t\tif idx >= nameStart {\n\t\t\t\treturn append(space, name), score\n\t\t\t}\n\t\t\t// Lower the score for matches that include the package name.\n\t\t\treturn pkgQualified, score * 0.8\n\t\t}\n\t}\n\n\t// Now try matching the fully qualified symbol.\n\tfullyQualified := append(space, string(pkg.PkgPath), \".\", name)\n\tidx, score := matcher(fullyQualified)\n\n\t// As above, check if we matched just the unqualified symbol name.\n\tnameStart := len(pkg.PkgPath) + 1\n\tif idx >= nameStart {\n\t\treturn append(space, name), score\n\t}\n\n\t// If our package path ends in the package name, we'll have skipped the\n\t// initial pass above, so check if we matched just the package-qualified\n\t// name.\n\tif endsInPkgName && idx >= 0 {\n\t\tpkgStart := len(pkg.PkgPath) - len(pkg.Name)\n\t\tif idx >= pkgStart {\n\t\t\treturn append(space, string(pkg.Name), \".\", name), score\n\t\t}\n\t}\n\n\t// Our match was not contained within the unqualified or package qualified\n\t// symbol. Return the fully qualified symbol but discount the score.\n\treturn fullyQualified, score * 0.6\n}\n\nfunc packageSymbolMatch(space []string, name string, pkg *metadata.Package, matcher matcherFunc) ([]string, float64) {\n\tqualified := append(space, string(pkg.Name), \".\", name)\n\tif _, s := matcher(qualified); s > 0 {\n\t\treturn qualified, s\n\t}\n\treturn nil, 0\n}\n\nfunc buildMatcher(matcher settings.SymbolMatcher, query string) matcherFunc {\n\tswitch matcher {\n\tcase settings.SymbolFuzzy:\n\t\treturn parseQuery(query, newFuzzyMatcher)\n\tcase settings.SymbolFastFuzzy:\n\t\treturn parseQuery(query, func(query string) matcherFunc {\n\t\t\treturn fuzzy.NewSymbolMatcher(query).Match\n\t\t})\n\tcase settings.SymbolCaseSensitive:\n\t\treturn matchExact(query)\n\tcase settings.SymbolCaseInsensitive:\n\t\tq := strings.ToLower(query)\n\t\texact := matchExact(q)\n\t\twrapper := []string{\"\"}\n\t\treturn func(chunks []string) (int, float64) {\n\t\t\ts := strings.Join(chunks, \"\")\n\t\t\twrapper[0] = strings.ToLower(s)\n\t\t\treturn exact(wrapper)\n\t\t}\n\t}\n\tpanic(fmt.Errorf(\"unknown symbol matcher: %v\", matcher))\n}\n\nfunc newFuzzyMatcher(query string) matcherFunc {\n\tfm := fuzzy.NewMatcher(query)\n\treturn func(chunks []string) (int, float64) {\n\t\tscore := float64(fm.ScoreChunks(chunks))\n\t\tranges := fm.MatchedRanges()\n\t\tif len(ranges) > 0 {\n\t\t\treturn ranges[0], score\n\t\t}\n\t\treturn -1, score\n\t}\n}\n\n// parseQuery parses a field-separated symbol query, extracting the special\n// characters listed below, and returns a matcherFunc corresponding to the AND\n// of all field queries.\n//\n// Special characters:\n//\n//\t^  match exact prefix\n//\t$  match exact suffix\n//\t'  match exact\n//\n// In all three of these special queries, matches are 'smart-cased', meaning\n// they are case sensitive if the symbol query contains any upper-case\n// characters, and case insensitive otherwise.\nfunc parseQuery(q string, newMatcher func(string) matcherFunc) matcherFunc {\n\tfields := strings.Fields(q)\n\tif len(fields) == 0 {\n\t\treturn func([]string) (int, float64) { return -1, 0 }\n\t}\n\tvar funcs []matcherFunc\n\tfor _, field := range fields {\n\t\tvar f matcherFunc\n\t\tswitch {\n\t\tcase strings.HasPrefix(field, \"^\"):\n\t\t\tprefix := field[1:]\n\t\t\tf = smartCase(prefix, func(chunks []string) (int, float64) {\n\t\t\t\ts := strings.Join(chunks, \"\")\n\t\t\t\tif strings.HasPrefix(s, prefix) {\n\t\t\t\t\treturn 0, 1\n\t\t\t\t}\n\t\t\t\treturn -1, 0\n\t\t\t})\n\t\tcase strings.HasPrefix(field, \"'\"):\n\t\t\texact := field[1:]\n\t\t\tf = smartCase(exact, matchExact(exact))\n\t\tcase strings.HasSuffix(field, \"$\"):\n\t\t\tsuffix := field[0 : len(field)-1]\n\t\t\tf = smartCase(suffix, func(chunks []string) (int, float64) {\n\t\t\t\ts := strings.Join(chunks, \"\")\n\t\t\t\tif strings.HasSuffix(s, suffix) {\n\t\t\t\t\treturn len(s) - len(suffix), 1\n\t\t\t\t}\n\t\t\t\treturn -1, 0\n\t\t\t})\n\t\tdefault:\n\t\t\tf = newMatcher(field)\n\t\t}\n\t\tfuncs = append(funcs, f)\n\t}\n\tif len(funcs) == 1 {\n\t\treturn funcs[0]\n\t}\n\treturn comboMatcher(funcs).match\n}\n\nfunc matchExact(exact string) matcherFunc {\n\treturn func(chunks []string) (int, float64) {\n\t\ts := strings.Join(chunks, \"\")\n\t\tif idx := strings.LastIndex(s, exact); idx >= 0 {\n\t\t\treturn idx, 1\n\t\t}\n\t\treturn -1, 0\n\t}\n}\n\n// smartCase returns a matcherFunc that is case-sensitive if q contains any\n// upper-case characters, and case-insensitive otherwise.\nfunc smartCase(q string, m matcherFunc) matcherFunc {\n\tinsensitive := strings.ToLower(q) == q\n\twrapper := []string{\"\"}\n\treturn func(chunks []string) (int, float64) {\n\t\ts := strings.Join(chunks, \"\")\n\t\tif insensitive {\n\t\t\ts = strings.ToLower(s)\n\t\t}\n\t\twrapper[0] = s\n\t\treturn m(wrapper)\n\t}\n}\n\ntype comboMatcher []matcherFunc\n\nfunc (c comboMatcher) match(chunks []string) (int, float64) {\n\tscore := 1.0\n\tfirst := 0\n\tfor _, f := range c {\n\t\tidx, s := f(chunks)\n\t\tif idx < first {\n\t\t\tfirst = idx\n\t\t}\n\t\tscore *= s\n\t}\n\treturn first, score\n}\n\n// collectSymbols calls snapshot.Symbols to walk the syntax trees of\n// all files in the views' current snapshots, and returns a sorted,\n// scored list of symbols that best match the parameters.\n//\n// How it matches symbols is parameterized by two interfaces:\n//   - A matcherFunc determines how well a string symbol matches a query. It\n//     returns a non-negative score indicating the quality of the match. A score\n//     of zero indicates no match.\n//   - A symbolizer determines how we extract the symbol for an object. This\n//     enables the 'symbolStyle' configuration option.\nfunc collectSymbols(ctx context.Context, snapshots []*cache.Snapshot, matcherType settings.SymbolMatcher, symbolizer symbolizer, query string) ([]protocol.SymbolInformation, error) {\n\t// Extract symbols from all files.\n\tvar work []symbolFile\n\tseen := make(map[protocol.DocumentURI]*metadata.Package) // only scan each file once\n\n\tfor _, snapshot := range snapshots {\n\t\t// Use the root view URIs for determining (lexically)\n\t\t// whether a URI is in any open workspace.\n\t\tfolderURI := snapshot.Folder()\n\n\t\tpathIncluded := cache.PathIncludeFunc(snapshot.Options().DirectoryFilters)\n\t\tfolder := filepath.ToSlash(folderURI.Path())\n\n\t\tvar (\n\t\t\tmps []*metadata.Package\n\t\t\terr error\n\t\t)\n\t\tif snapshot.Options().SymbolScope == settings.AllSymbolScope {\n\t\t\tmps, err = snapshot.AllMetadata(ctx)\n\t\t} else {\n\t\t\tmps, err = snapshot.WorkspaceMetadata(ctx)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmetadata.RemoveIntermediateTestVariants(&mps)\n\n\t\t// We'll process packages in order to consider candidate symbols.\n\t\t//\n\t\t// The order here doesn't matter for correctness, but can affect\n\t\t// performance:\n\t\t//  - As workspace packages score higher than non-workspace packages,\n\t\t//    sort them first to increase the likelihood that non-workspace\n\t\t//    symbols are skipped.\n\t\t//  - As files can be contained in multiple packages, sort by wider\n\t\t//    packages first, to cover all files with fewer packages.\n\t\tworkspacePackages := snapshot.WorkspacePackages()\n\t\tslices.SortFunc(mps, func(a, b *metadata.Package) int {\n\t\t\t_, aworkspace := workspacePackages.Value(a.ID)\n\t\t\t_, bworkspace := workspacePackages.Value(b.ID)\n\t\t\tif cmp := boolCompare(aworkspace, bworkspace); cmp != 0 {\n\t\t\t\treturn -cmp // workspace packages first\n\t\t\t}\n\t\t\treturn -cmp.Compare(len(a.CompiledGoFiles), len(b.CompiledGoFiles)) // widest first\n\t\t})\n\n\t\t// Filter out unneeded mps in place, and collect file<->package\n\t\t// associations.\n\t\tvar ids []metadata.PackageID\n\t\tfor _, mp := range mps {\n\t\t\tused := false\n\t\t\tfor _, list := range [][]protocol.DocumentURI{mp.GoFiles, mp.CompiledGoFiles} {\n\t\t\t\tfor _, uri := range list {\n\t\t\t\t\tif _, ok := seen[uri]; !ok {\n\t\t\t\t\t\tseen[uri] = mp\n\t\t\t\t\t\tused = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif used {\n\t\t\t\tmps[len(ids)] = mp\n\t\t\t\tids = append(ids, mp.ID)\n\t\t\t}\n\t\t}\n\t\tmps = mps[:len(ids)]\n\n\t\tsymbolPkgs, err := snapshot.Symbols(ctx, ids...)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tfor i, sp := range symbolPkgs {\n\t\t\tif sp == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmp := mps[i]\n\t\t\tfor i, syms := range sp.Symbols {\n\t\t\t\turi := sp.Files[i]\n\t\t\t\tnorm := filepath.ToSlash(uri.Path())\n\t\t\t\tnm := strings.TrimPrefix(norm, folder)\n\t\t\t\tif !pathIncluded(nm) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Only scan each file once.\n\t\t\t\tif seen[uri] != mp {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// seen[uri] = true\n\t\t\t\t_, workspace := workspacePackages.Value(mp.ID)\n\t\t\t\twork = append(work, symbolFile{mp, uri, syms, workspace})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Match symbols in parallel.\n\t// Each worker has its own symbolStore,\n\t// which we merge at the end.\n\tnmatchers := runtime.GOMAXPROCS(-1) // matching is CPU bound\n\tresults := make(chan *symbolStore)\n\tfor i := range nmatchers {\n\t\tgo func(i int) {\n\t\t\tmatcher := buildMatcher(matcherType, query)\n\t\t\tstore := new(symbolStore)\n\t\t\t// Assign files to workers in round-robin fashion.\n\t\t\tfor j := i; j < len(work); j += nmatchers {\n\t\t\t\tmatchFile(store, symbolizer, matcher, work[j])\n\t\t\t}\n\t\t\tresults <- store\n\t\t}(i)\n\t}\n\n\t// Gather and merge results as they arrive.\n\tvar unified symbolStore\n\tfor range nmatchers {\n\t\tstore := <-results\n\t\tfor _, syms := range store.res {\n\t\t\tif syms != nil {\n\t\t\t\tunified.store(syms)\n\t\t\t}\n\t\t}\n\t}\n\treturn unified.results(), nil\n}\n\n// symbolFile holds symbol information for a single file.\ntype symbolFile struct {\n\tmp        *metadata.Package\n\turi       protocol.DocumentURI\n\tsyms      []symbols.Symbol\n\tworkspace bool\n}\n\n// matchFile scans a symbol file and adds matching symbols to the store.\nfunc matchFile(store *symbolStore, symbolizer symbolizer, matcher matcherFunc, f symbolFile) {\n\tspace := make([]string, 0, 3)\n\tfor _, sym := range f.syms {\n\t\tsymbolParts, score := symbolizer(space, sym.Name, f.mp, matcher)\n\n\t\t// Check if the score is too low before applying any downranking.\n\t\tif store.tooLow(score) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Factors to apply to the match score for the purpose of downranking\n\t\t// results.\n\t\t//\n\t\t// These numbers were crudely calibrated based on trial-and-error using a\n\t\t// small number of sample queries. Adjust as necessary.\n\t\t//\n\t\t// All factors are multiplicative, meaning if more than one applies they are\n\t\t// multiplied together.\n\t\tconst (\n\t\t\t// nonWorkspaceFactor is applied to symbols outside the workspace.\n\t\t\t// Developers are less likely to want to jump to code that they\n\t\t\t// are not actively working on.\n\t\t\tnonWorkspaceFactor = 0.5\n\t\t\t// nonWorkspaceUnexportedFactor is applied to unexported symbols outside\n\t\t\t// the workspace. Since one wouldn't usually jump to unexported\n\t\t\t// symbols to understand a package API, they are particularly irrelevant.\n\t\t\tnonWorkspaceUnexportedFactor = 0.5\n\t\t\t// every field or method nesting level to access the field decreases\n\t\t\t// the score by a factor of 1.0 - depth*depthFactor, up to a depth of\n\t\t\t// 3.\n\t\t\t//\n\t\t\t// Use a small constant here, as this exists mostly to break ties\n\t\t\t// (e.g. given a type Foo and a field x.Foo, prefer Foo).\n\t\t\tdepthFactor = 0.01\n\t\t)\n\n\t\t// TODO(rfindley): compute this downranking *before* calling the symbolizer\n\t\t// (which is expensive), so that we can pre-filter candidates whose score\n\t\t// will always be too low, even with a perfect match.\n\n\t\tstartWord := true\n\t\texported := true\n\t\tdepth := 0.0\n\t\tfor _, r := range sym.Name {\n\t\t\tif startWord && !unicode.IsUpper(r) {\n\t\t\t\texported = false\n\t\t\t}\n\t\t\tif r == '.' {\n\t\t\t\tstartWord = true\n\t\t\t\tdepth++\n\t\t\t} else {\n\t\t\t\tstartWord = false\n\t\t\t}\n\t\t}\n\n\t\t// Apply downranking based on workspace position.\n\t\tif !f.workspace {\n\t\t\tscore *= nonWorkspaceFactor\n\t\t\tif !exported {\n\t\t\t\tscore *= nonWorkspaceUnexportedFactor\n\t\t\t}\n\t\t}\n\n\t\t// Apply downranking based on symbol depth.\n\t\tif depth > 3 {\n\t\t\tdepth = 3\n\t\t}\n\t\tscore *= 1.0 - depth*depthFactor\n\n\t\tif store.tooLow(score) {\n\t\t\tcontinue\n\t\t}\n\n\t\tsi := &scoredSymbol{\n\t\t\tscore: score,\n\t\t\tinfo: protocol.SymbolInformation{\n\t\t\t\tName:          strings.Join(symbolParts, \"\"),\n\t\t\t\tKind:          sym.Kind,\n\t\t\t\tLocation:      f.uri.Location(sym.Range),\n\t\t\t\tContainerName: string(f.mp.PkgPath),\n\t\t\t},\n\t\t}\n\t\tstore.store(si)\n\t}\n}\n\ntype symbolStore struct {\n\tres [maxSymbols]*scoredSymbol\n}\n\n// store inserts si into the sorted results, if si has a high enough score.\nfunc (sc *symbolStore) store(ss *scoredSymbol) {\n\tif sc.tooLow(ss.score) {\n\t\treturn\n\t}\n\tinsertAt := sort.Search(len(sc.res), func(i int) bool {\n\t\tif sc.res[i] == nil {\n\t\t\treturn true\n\t\t}\n\t\t// Sort by score, then symbol length, and finally lexically.\n\t\tif ss.score != sc.res[i].score {\n\t\t\treturn ss.score > sc.res[i].score\n\t\t}\n\t\tif cmp := cmp.Compare(len(ss.info.Name), len(sc.res[i].info.Name)); cmp != 0 {\n\t\t\treturn cmp < 0 // shortest first\n\t\t}\n\t\treturn ss.info.Name < sc.res[i].info.Name\n\t})\n\tif insertAt < len(sc.res)-1 {\n\t\tcopy(sc.res[insertAt+1:], sc.res[insertAt:len(sc.res)-1])\n\t}\n\tsc.res[insertAt] = ss\n}\n\nfunc (sc *symbolStore) tooLow(score float64) bool {\n\tlast := sc.res[len(sc.res)-1]\n\tif last == nil {\n\t\treturn false\n\t}\n\treturn score <= last.score\n}\n\nfunc (sc *symbolStore) results() []protocol.SymbolInformation {\n\tvar res []protocol.SymbolInformation\n\tfor _, si := range sc.res {\n\t\tif si == nil || si.score <= 0 {\n\t\t\treturn res\n\t\t}\n\t\tres = append(res, si.info)\n\t}\n\treturn res\n}\n\ntype scoredSymbol struct {\n\tscore float64\n\tinfo  protocol.SymbolInformation\n}\n"
  },
  {
    "path": "gopls/internal/golang/workspace_symbol_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage golang\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n)\n\nfunc TestParseQuery(t *testing.T) {\n\ttests := []struct {\n\t\tquery, s  string\n\t\twantMatch bool\n\t}{\n\t\t{\"\", \"anything\", false},\n\t\t{\"any\", \"anything\", true},\n\t\t{\"any$\", \"anything\", false},\n\t\t{\"ing$\", \"anything\", true},\n\t\t{\"ing$\", \"anythinG\", true},\n\t\t{\"inG$\", \"anything\", false},\n\t\t{\"^any\", \"anything\", true},\n\t\t{\"^any\", \"Anything\", true},\n\t\t{\"^Any\", \"anything\", false},\n\t\t{\"at\", \"anything\", true},\n\t\t// TODO: this appears to be a bug in the fuzzy matching algorithm. 'At'\n\t\t// should cause a case-sensitive match.\n\t\t// {\"At\", \"anything\", false},\n\t\t{\"At\", \"Anything\", true},\n\t\t{\"'yth\", \"Anything\", true},\n\t\t{\"'yti\", \"Anything\", false},\n\t\t{\"'any 'thing\", \"Anything\", true},\n\t\t{\"anythn nythg\", \"Anything\", true},\n\t\t{\"ntx\", \"Anything\", false},\n\t\t{\"anythn\", \"anything\", true},\n\t\t{\"ing\", \"anything\", true},\n\t\t{\"anythn nythgx\", \"anything\", false},\n\t}\n\n\tfor _, test := range tests {\n\t\tmatcher := parseQuery(test.query, newFuzzyMatcher)\n\t\tif _, score := matcher([]string{test.s}); score > 0 != test.wantMatch {\n\t\t\tt.Errorf(\"parseQuery(%q) match for %q: %.2g, want match: %t\", test.query, test.s, score, test.wantMatch)\n\t\t}\n\t}\n}\n\nfunc TestPathIncludeFunc(t *testing.T) {\n\ttests := []struct {\n\t\tfilters  []string\n\t\tincluded []string\n\t\texcluded []string\n\t}{\n\t\t{\n\t\t\t[]string{\"+**/c.go\"},\n\t\t\t[]string{\"a/c.go\", \"a/b/c.go\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+a/**/c.go\"},\n\t\t\t[]string{\"a/b/c.go\", \"a/b/d/c.go\", \"a/c.go\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"-a/c.go\", \"+a/**\"},\n\t\t\t[]string{\"a/c.go\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+a/**/c.go\", \"-**/c.go\"},\n\t\t\t[]string{},\n\t\t\t[]string{\"a/b/c.go\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+a/**/c.go\", \"-a/**\"},\n\t\t\t[]string{},\n\t\t\t[]string{\"a/b/c.go\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+**/c.go\", \"-a/**/c.go\"},\n\t\t\t[]string{},\n\t\t\t[]string{\"a/b/c.go\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+foobar\", \"-foo\"},\n\t\t\t[]string{\"foobar\", \"foobar/a\"},\n\t\t\t[]string{\"foo\", \"foo/a\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+\", \"-\"},\n\t\t\t[]string{},\n\t\t\t[]string{\"foobar\", \"foobar/a\", \"foo\", \"foo/a\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"-\", \"+\"},\n\t\t\t[]string{\"foobar\", \"foobar/a\", \"foo\", \"foo/a\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"-a/**/b/**/c.go\"},\n\t\t\t[]string{},\n\t\t\t[]string{\"a/x/y/z/b/f/g/h/c.go\"},\n\t\t},\n\t\t// tests for unsupported glob operators\n\t\t{\n\t\t\t[]string{\"+**/c.go\", \"-a/*/c.go\"},\n\t\t\t[]string{\"a/b/c.go\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"+**/c.go\", \"-a/?/c.go\"},\n\t\t\t[]string{\"a/b/c.go\"},\n\t\t\t[]string{},\n\t\t},\n\t\t{\n\t\t\t[]string{\"-b\"}, // should only filter paths prefixed with the \"b\" directory\n\t\t\t[]string{\"a/b/c.go\", \"bb\"},\n\t\t\t[]string{\"b/c/d.go\", \"b\"},\n\t\t},\n\t\t// golang/vscode-go#3692\n\t\t{\n\t\t\t[]string{\"-**/foo\", \"+**/bar\"},\n\t\t\t[]string{\"bar/a.go\", \"a/bar/b.go\"},\n\t\t\t[]string{\"foo/a.go\", \"a/foo/b.go\"},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpathIncluded := cache.PathIncludeFunc(test.filters)\n\t\tfor _, inc := range test.included {\n\t\t\tif !pathIncluded(inc) {\n\t\t\t\tt.Errorf(\"Filters %v excluded %v, wanted included\", test.filters, inc)\n\t\t\t}\n\t\t}\n\n\t\tfor _, exc := range test.excluded {\n\t\t\tif pathIncluded(exc) {\n\t\t\t\tt.Errorf(\"Filters %v included %v, wanted excluded\", test.filters, exc)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/label/keys.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package label provides common labels used to annotate gopls log messages\n// and events.\npackage label\n\nimport \"golang.org/x/tools/internal/event/keys\"\n\nvar (\n\tFile      = keys.NewString(\"file\", \"\")\n\tDirectory = keys.New(\"directory\", \"\")\n\tURI       = keys.New(\"URI\", \"\")\n\tPackage   = keys.NewString(\"package\", \"\") // sorted comma-separated list of Package IDs\n\tQuery     = keys.New(\"query\", \"\")\n\tViewID    = keys.NewString(\"view_id\", \"\")\n\tSnapshot  = keys.NewUint(\"snapshot\", \"\")\n\tOperation = keys.NewString(\"operation\", \"\")\n\tDuration  = keys.New(\"duration\", \"Elapsed time\")\n\n\tPosition     = keys.New(\"position\", \"\")\n\tPackageCount = keys.NewInt(\"packages\", \"\")\n\tFiles        = keys.New(\"files\", \"\")\n\tPort         = keys.NewInt(\"port\", \"\")\n\n\tNewServer = keys.NewString(\"new_server\", \"A new server was added\")\n\tEndServer = keys.NewString(\"end_server\", \"A server was shut down\")\n\n\tServerID     = keys.NewString(\"server\", \"The server ID an event is related to\")\n\tLogfile      = keys.NewString(\"logfile\", \"\")\n\tDebugAddress = keys.NewString(\"debug_address\", \"\")\n\tGoplsPath    = keys.NewString(\"gopls_path\", \"\")\n\tClientID     = keys.NewString(\"client_id\", \"\")\n\n\tLevel = keys.NewInt(\"level\", \"The logging level\")\n)\n"
  },
  {
    "path": "gopls/internal/licenses/gen-licenses.sh",
    "content": "#!/bin/bash -eu\n\n# Copyright 2020 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n\nset -o pipefail\n\noutput=$1\ntempfile=$(mktemp)\ncd $(dirname $0)\n\ncat > $tempfile <<END\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate ./gen-licenses.sh licenses.go\npackage licenses\n\nconst Text = \\`\nEND\n\n# List all the modules gopls depends on, except other golang.org modules, which\n# are known to have the same license.\nmods=$(go list -deps -f '{{with .Module}}{{.Path}}{{end}}' golang.org/x/tools/gopls | sort -u | grep -v golang.org)\nfor mod in $mods; do\n  # Find the license file, either LICENSE, COPYING, or LICENSE.md and add it to the result.\n  dir=$(go list -m -f {{.Dir}} $mod)\n  license=$(ls -1 $dir | grep -E -i '^(LICENSE|LICENSE.md|COPYING)?$')\n  echo \"-- $mod $license --\" >> $tempfile\n  echo >> $tempfile\n  sed 's/^-- / &/' $dir/$license >> $tempfile\n  echo >> $tempfile\ndone\n\necho \"\\`\" >> $tempfile\nmv $tempfile $output\n"
  },
  {
    "path": "gopls/internal/licenses/licenses.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate ./gen-licenses.sh licenses.go\npackage licenses\n\nconst Text = `\n-- github.com/BurntSushi/toml COPYING --\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 TOML authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-- github.com/fatih/camelcase LICENSE.md --\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 Fatih Arslan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-- github.com/fatih/gomodifytags LICENSE --\n\nCopyright (c) 2017, Fatih Arslan\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of gomodifytags nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-- github.com/fatih/structtag LICENSE --\n\nCopyright (c) 2017, Fatih Arslan\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of structtag nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThis software includes some portions from Go. Go is used under the terms of the\nBSD like license.\n\nCopyright (c) 2012 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher\n\n-- github.com/fsnotify/fsnotify LICENSE --\n\nCopyright © 2012 The Go Authors. All rights reserved.\nCopyright © fsnotify Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used\n  to endorse or promote products derived from this software without specific\n  prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-- github.com/google/go-cmp LICENSE --\n\nCopyright (c) 2017 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-- github.com/google/jsonschema-go LICENSE --\n\nMIT License\n\nCopyright (c) 2025 JSON Schema Go Project Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-- github.com/modelcontextprotocol/go-sdk LICENSE --\n\nThe MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 (\"Apache-2.0\"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.\n\nContributions for which relicensing consent has been obtained are licensed under Apache-2.0. Contributions made by authors who originally licensed their work under the MIT License and who have not yet granted explicit permission to relicense remain licensed under the MIT License.\n\nNo rights beyond those granted by the applicable original license are conveyed for such contributions.\n\n---\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright\n      owner or by an individual or Legal Entity authorized to submit on behalf\n      of the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n---\n\nMIT License\n\nCopyright (c) 2024-2025 Model Context Protocol a Series of LF Projects, LLC.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---\n\nCreative Commons Attribution 4.0 International (CC-BY-4.0)\n\nDocumentation in this project (excluding specifications) is licensed under\nCC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for\nthe full license text.\n\n-- github.com/segmentio/asm LICENSE --\n\nMIT No Attribution\n\nCopyright 2023 Segment\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this\nsoftware and associated documentation files (the \"Software\"), to deal in the Software\nwithout restriction, including without limitation the rights to use, copy, modify,\nmerge, publish, distribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-- github.com/segmentio/encoding LICENSE --\n\nMIT License\n\nCopyright (c) 2019 Segment.io, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-- github.com/yosida95/uritemplate/v3 LICENSE --\n\nCopyright (C) 2016, Kohei YOSHIDA <https://yosida95.com/>. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the names of its\n      contributors may be used to endorse or promote products derived from\n      this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-- honnef.co/go/tools LICENSE --\n\nCopyright (c) 2016 Dominik Honnef\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-- mvdan.cc/gofumpt LICENSE --\n\nCopyright (c) 2019, Daniel Martí. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of the copyright holder nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-- mvdan.cc/xurls/v2 LICENSE --\n\nCopyright (c) 2015, Daniel Martí. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of the copyright holder nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n`\n"
  },
  {
    "path": "gopls/internal/licenses/licenses_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage licenses_test\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestLicenses(t *testing.T) {\n\tif runtime.GOOS != \"linux\" && runtime.GOOS != \"darwin\" {\n\t\tt.Skip(\"generating licenses only works on Unixes\")\n\t}\n\ttmp, err := os.CreateTemp(\"\", \"\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttmp.Close() // ignore error\n\n\tif out, err := exec.Command(\"./gen-licenses.sh\", tmp.Name()).CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"generating licenses failed: %q, %v\", out, err)\n\t}\n\n\tgot, err := os.ReadFile(tmp.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant, err := os.ReadFile(\"licenses.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !bytes.Equal(got, want) {\n\t\tt.Error(\"combined license text needs updating. Run: `go generate ./internal/licenses` from the gopls module.\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/autostart_default.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n)\n\nvar (\n\tdaemonize             = func(*exec.Cmd) {}\n\tautoNetworkAddress    = autoNetworkAddressDefault\n\tverifyRemoteOwnership = verifyRemoteOwnershipDefault\n)\n\nfunc runRemote(cmd *exec.Cmd) error {\n\tdaemonize(cmd)\n\tif err := cmd.Start(); err != nil {\n\t\treturn fmt.Errorf(\"starting remote gopls: %w\", err)\n\t}\n\treturn nil\n}\n\n// autoNetworkAddressDefault returns the default network and address for the\n// automatically-started gopls remote. See autostart_posix.go for more\n// information.\nfunc autoNetworkAddressDefault(goplsPath, id string) (network string, address string) {\n\tif id != \"\" {\n\t\tpanic(\"identified remotes are not supported on windows\")\n\t}\n\treturn \"tcp\", \"localhost:37374\"\n}\n\nfunc verifyRemoteOwnershipDefault(network, address string) (bool, error) {\n\treturn true, nil\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/autostart_posix.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris\n\npackage lsprpc\n\nimport (\n\t\"crypto/sha256\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/user\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"syscall\"\n)\n\nfunc init() {\n\tdaemonize = daemonizePosix\n\tautoNetworkAddress = autoNetworkAddressPosix\n\tverifyRemoteOwnership = verifyRemoteOwnershipPosix\n}\n\nfunc daemonizePosix(cmd *exec.Cmd) {\n\tcmd.SysProcAttr = &syscall.SysProcAttr{\n\t\tSetsid: true,\n\t}\n}\n\n// autoNetworkAddressPosix resolves an id on the 'auto' pseudo-network to a\n// real network and address. On unix, this uses unix domain sockets.\nfunc autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {\n\t// Especially when doing local development or testing, it's important that\n\t// the remote gopls instance we connect to is running the same binary as our\n\t// forwarder. So we encode a short hash of the binary path into the daemon\n\t// socket name. If possible, we also include the buildid in this hash, to\n\t// account for long-running processes where the binary has been subsequently\n\t// rebuilt.\n\th := sha256.New()\n\tcmd := exec.Command(\"go\", \"tool\", \"buildid\", goplsPath)\n\tcmd.Stdout = h\n\tvar pathHash []byte\n\tif err := cmd.Run(); err == nil {\n\t\tpathHash = h.Sum(nil)\n\t} else {\n\t\tlog.Printf(\"error getting current buildid: %v\", err)\n\t\tsum := sha256.Sum256([]byte(goplsPath))\n\t\tpathHash = sum[:]\n\t}\n\tshortHash := fmt.Sprintf(\"%x\", pathHash)[:6]\n\tuser := os.Getenv(\"USER\")\n\tif user == \"\" {\n\t\tuser = \"shared\"\n\t}\n\tbasename := filepath.Base(goplsPath)\n\tidComponent := \"\"\n\tif id != \"\" {\n\t\tidComponent = \"-\" + id\n\t}\n\truntimeDir := os.TempDir()\n\tif xdg := os.Getenv(\"XDG_RUNTIME_DIR\"); xdg != \"\" {\n\t\truntimeDir = xdg\n\t}\n\treturn \"unix\", filepath.Join(runtimeDir, fmt.Sprintf(\"%s-%s-daemon.%s%s\", basename, shortHash, user, idComponent))\n}\n\nfunc verifyRemoteOwnershipPosix(network, address string) (bool, error) {\n\tif network != \"unix\" {\n\t\treturn true, nil\n\t}\n\tfi, err := os.Stat(address)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, fmt.Errorf(\"checking socket owner: %w\", err)\n\t}\n\tstat, ok := fi.Sys().(*syscall.Stat_t)\n\tif !ok {\n\t\treturn false, errors.New(\"fi.Sys() is not a Stat_t\")\n\t}\n\tuser, err := user.Current()\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"checking current user: %w\", err)\n\t}\n\tuid, err := strconv.ParseUint(user.Uid, 10, 32)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"parsing current UID: %w\", err)\n\t}\n\treturn stat.Uid == uint32(uid), nil\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/binder.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n"
  },
  {
    "path": "gopls/internal/lsprpc/binder_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc_test\n\nimport (\n\t\"context\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\n\t. \"golang.org/x/tools/gopls/internal/lsprpc\"\n)\n\n// ServerBinder binds incoming connections to a new server.\ntype ServerBinder struct {\n\tnewServer ServerFunc\n}\n\nfunc NewServerBinder(newServer ServerFunc) *ServerBinder {\n\treturn &ServerBinder{newServer: newServer}\n}\n\n// streamServer used to have this method, but it was never used.\n// TODO(adonovan): figure out whether we need any of this machinery\n// and, if not, delete it. In the meantime, it's better that it sit\n// in the test package with all the other mothballed machinery\n// than in the production code where it would couple streamServer\n// and ServerBinder.\n/*\nfunc (s *streamServer) Binder() *ServerBinder {\n\tnewServer := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {\n\t\tsession := cache.NewSession(ctx, s.cache)\n\t\tsvr := s.serverForTest\n\t\tif svr == nil {\n\t\t\toptions := settings.DefaultOptions(s.optionsOverrides)\n\t\t\tsvr = server.New(session, client, options)\n\t\t\tif instance := debug.GetInstance(ctx); instance != nil {\n\t\t\t\tinstance.AddService(svr, session)\n\t\t\t}\n\t\t}\n\t\treturn svr\n\t}\n\treturn NewServerBinder(newServer)\n}\n*/\n\nfunc (b *ServerBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\tclient := protocol.ClientDispatcherV2(conn)\n\tserver := b.newServer(ctx, client)\n\tserverHandler := protocol.ServerHandlerV2(server)\n\t// Wrap the server handler to inject the client into each request context, so\n\t// that log events are reflected back to the client.\n\twrapped := jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\tctx = protocol.WithClient(ctx, client)\n\t\treturn serverHandler.Handle(ctx, req)\n\t})\n\tpreempter := &Canceler{\n\t\tConn: conn,\n\t}\n\treturn jsonrpc2_v2.ConnectionOptions{\n\t\tHandler:   wrapped,\n\t\tPreempter: preempter,\n\t}\n}\n\ntype TestEnv struct {\n\tConns   []*jsonrpc2_v2.Connection\n\tServers []*jsonrpc2_v2.Server\n}\n\nfunc (e *TestEnv) Shutdown(t *testing.T) {\n\tfor _, s := range e.Servers {\n\t\ts.Shutdown()\n\t}\n\tfor _, c := range e.Conns {\n\t\tif err := c.Close(); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\tfor _, s := range e.Servers {\n\t\tif err := s.Wait(); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n}\n\nfunc (e *TestEnv) serve(ctx context.Context, t *testing.T, server jsonrpc2_v2.Binder) (jsonrpc2_v2.Listener, *jsonrpc2_v2.Server) {\n\tl, err := jsonrpc2_v2.NetPipeListener(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ts := jsonrpc2_v2.NewServer(ctx, l, server)\n\te.Servers = append(e.Servers, s)\n\treturn l, s\n}\n\nfunc (e *TestEnv) dial(ctx context.Context, t *testing.T, dialer jsonrpc2_v2.Dialer, client jsonrpc2_v2.Binder, forwarded bool) *jsonrpc2_v2.Connection {\n\tif forwarded {\n\t\tl, _ := e.serve(ctx, t, NewForwardBinder(dialer))\n\t\tdialer = l.Dialer()\n\t}\n\tconn, err := jsonrpc2_v2.Dial(ctx, dialer, client, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\te.Conns = append(e.Conns, conn)\n\treturn conn\n}\n\nfunc staticClientBinder(client protocol.Client) jsonrpc2_v2.Binder {\n\tf := func(context.Context, protocol.Server) protocol.Client { return client }\n\treturn NewClientBinder(f)\n}\n\nfunc staticServerBinder(server protocol.Server) jsonrpc2_v2.Binder {\n\tf := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {\n\t\treturn server\n\t}\n\treturn NewServerBinder(f)\n}\n\nfunc TestClientLoggingV2(t *testing.T) {\n\tctx := context.Background()\n\n\tfor name, forwarded := range map[string]bool{\n\t\t\"forwarded\":  true,\n\t\t\"standalone\": false,\n\t} {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tclient := FakeClient{Logs: make(chan string, 10)}\n\t\t\tenv := new(TestEnv)\n\t\t\tdefer env.Shutdown(t)\n\t\t\tl, _ := env.serve(ctx, t, staticServerBinder(PingServer{}))\n\t\t\tconn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)\n\n\t\t\tif err := protocol.ServerDispatcherV2(conn).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil {\n\t\t\t\tt.Errorf(\"DidOpen: %v\", err)\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase got := <-client.Logs:\n\t\t\t\twant := \"ping\"\n\t\t\t\tmatched, err := regexp.MatchString(want, got)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif !matched {\n\t\t\t\t\tt.Errorf(\"got log %q, want a log containing %q\", got, want)\n\t\t\t\t}\n\t\t\tcase <-time.After(1 * time.Second):\n\t\t\t\tt.Error(\"timeout waiting for client log\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestRequestCancellationV2(t *testing.T) {\n\tctx := context.Background()\n\n\tfor name, forwarded := range map[string]bool{\n\t\t\"forwarded\":  true,\n\t\t\"standalone\": false,\n\t} {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tserver := WaitableServer{\n\t\t\t\tStarted:   make(chan struct{}),\n\t\t\t\tCompleted: make(chan error),\n\t\t\t}\n\t\t\tenv := new(TestEnv)\n\t\t\tdefer env.Shutdown(t)\n\t\t\tl, _ := env.serve(ctx, t, staticServerBinder(server))\n\t\t\tclient := FakeClient{Logs: make(chan string, 10)}\n\t\t\tconn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)\n\n\t\t\tsd := protocol.ServerDispatcherV2(conn)\n\t\t\tctx, cancel := context.WithCancel(ctx)\n\n\t\t\tresult := make(chan error)\n\t\t\tgo func() {\n\t\t\t\t_, err := sd.Hover(ctx, &protocol.HoverParams{})\n\t\t\t\tresult <- err\n\t\t\t}()\n\t\t\t// Wait for the Hover request to start.\n\t\t\t<-server.Started\n\t\t\tcancel()\n\t\t\tif err := <-result; err == nil {\n\t\t\t\tt.Error(\"nil error for cancelled Hover(), want non-nil\")\n\t\t\t}\n\t\t\tif err := <-server.Completed; err == nil || !strings.Contains(err.Error(), \"cancelled hover\") {\n\t\t\t\tt.Errorf(\"Hover(): unexpected server-side error %v\", err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/commandinterceptor_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\n\t. \"golang.org/x/tools/gopls/internal/lsprpc\"\n)\n\nfunc CommandInterceptor(command string, run func(*protocol.ExecuteCommandParams) (any, error)) Middleware {\n\treturn BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {\n\t\treturn jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\t\tif req.Method == \"workspace/executeCommand\" {\n\t\t\t\tvar params protocol.ExecuteCommandParams\n\t\t\t\tif err := json.Unmarshal(req.Params, &params); err == nil {\n\t\t\t\t\tif params.Command == command {\n\t\t\t\t\t\treturn run(&params)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn delegate.Handle(ctx, req)\n\t\t})\n\t})\n}\n\nfunc TestCommandInterceptor(t *testing.T) {\n\tconst command = \"foo\"\n\tcaught := false\n\tintercept := func(_ *protocol.ExecuteCommandParams) (any, error) {\n\t\tcaught = true\n\t\treturn map[string]any{}, nil\n\t}\n\n\tctx := context.Background()\n\tenv := new(TestEnv)\n\tdefer env.Shutdown(t)\n\tmw := CommandInterceptor(command, intercept)\n\tl, _ := env.serve(ctx, t, mw(noopBinder))\n\tconn := env.dial(ctx, t, l.Dialer(), noopBinder, false)\n\n\tparams := &protocol.ExecuteCommandParams{\n\t\tCommand: command,\n\t}\n\tvar res any\n\terr := conn.Call(ctx, \"workspace/executeCommand\", params).Await(ctx, &res)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !caught {\n\t\tt.Errorf(\"workspace/executeCommand was not intercepted\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/dialer.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// autoNetwork is the pseudo network type used to signal that gopls should use\n// automatic discovery to resolve a remote address.\nconst autoNetwork = \"auto\"\n\n// An autoDialer is a jsonrpc2 dialer that understands the 'auto' network.\ntype autoDialer struct {\n\tnetwork, addr string // the 'real' network and address\n\tisAuto        bool   // whether the server is on the 'auto' network\n\n\texecutable string\n\targFunc    func(network, addr string) []string\n}\n\nfunc newAutoDialer(rawAddr string, argFunc func(network, addr string) []string) (*autoDialer, error) {\n\td := autoDialer{\n\t\targFunc: argFunc,\n\t}\n\td.network, d.addr = ParseAddr(rawAddr)\n\tif d.network == autoNetwork {\n\t\td.isAuto = true\n\t\tbin, err := os.Executable()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"getting executable: %w\", err)\n\t\t}\n\t\td.executable = bin\n\t\td.network, d.addr = autoNetworkAddress(bin, d.addr)\n\t}\n\treturn &d, nil\n}\n\n// Dial implements the jsonrpc2.Dialer interface.\nfunc (d *autoDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) {\n\tconn, err := d.dialNet(ctx)\n\treturn conn, err\n}\n\n// TODO(rFindley): remove this once we no longer need to integrate with v1 of\n// the jsonrpc2 package.\nfunc (d *autoDialer) dialNet(ctx context.Context) (net.Conn, error) {\n\t// Attempt to verify that we own the remote. This is imperfect, but if we can\n\t// determine that the remote is owned by a different user, we should fail.\n\tok, err := verifyRemoteOwnership(d.network, d.addr)\n\tif err != nil {\n\t\t// If the ownership check itself failed, we fail open but log an error to\n\t\t// the user.\n\t\tevent.Error(ctx, \"unable to check daemon socket owner, failing open\", err)\n\t} else if !ok {\n\t\t// We successfully checked that the socket is not owned by us, we fail\n\t\t// closed.\n\t\treturn nil, fmt.Errorf(\"socket %q is owned by a different user\", d.addr)\n\t}\n\tconst dialTimeout = 1 * time.Second\n\t// Try dialing our remote once, in case it is already running.\n\tnetConn, err := net.DialTimeout(d.network, d.addr, dialTimeout)\n\tif err == nil {\n\t\treturn netConn, nil\n\t}\n\tif d.isAuto && d.argFunc != nil {\n\t\tif d.network == \"unix\" {\n\t\t\t// Sometimes the socketfile isn't properly cleaned up when the server\n\t\t\t// shuts down. Since we have already tried and failed to dial this\n\t\t\t// address, it should *usually* be safe to remove the socket before\n\t\t\t// binding to the address.\n\t\t\t// TODO(rfindley): there is probably a race here if multiple server\n\t\t\t// instances are simultaneously starting up.\n\t\t\tif _, err := os.Stat(d.addr); err == nil {\n\t\t\t\tif err := os.Remove(d.addr); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"removing remote socket file: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\targs := d.argFunc(d.network, d.addr)\n\t\tcmd := exec.Command(d.executable, args...)\n\t\tif err := runRemote(cmd); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tconst retries = 5\n\t// It can take some time for the newly started server to bind to our address,\n\t// so we retry for a bit.\n\tfor retry := range retries {\n\t\tstartDial := time.Now()\n\t\tnetConn, err = net.DialTimeout(d.network, d.addr, dialTimeout)\n\t\tif err == nil {\n\t\t\treturn netConn, nil\n\t\t}\n\t\tevent.Log(ctx, fmt.Sprintf(\"failed attempt #%d to connect to remote: %v\\n\", retry+2, err))\n\t\t// In case our failure was a fast-failure, ensure we wait at least\n\t\t// f.dialTimeout before trying again.\n\t\tif retry != retries-1 {\n\t\t\ttime.Sleep(dialTimeout - time.Since(startDial))\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"dialing remote: %w\", err)\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/export_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n\n// This file defines things (and opens backdoors) needed only by tests.\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\nconst HandshakeMethod = handshakeMethod\n\n// A ServerFunc is used to construct an LSP server for a given client.\ntype ServerFunc func(context.Context, protocol.ClientCloser) protocol.Server\n\ntype Canceler struct {\n\tConn *jsonrpc2_v2.Connection\n}\n\nfunc (c *Canceler) Preempt(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\tif req.Method != \"$/cancelRequest\" {\n\t\treturn nil, jsonrpc2_v2.ErrNotHandled\n\t}\n\tvar params protocol.CancelParams\n\tif err := json.Unmarshal(req.Params, &params); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %v\", jsonrpc2_v2.ErrParse, err)\n\t}\n\tid, err := jsonrpc2_v2.MakeID(params.ID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: invalid ID type %T\", jsonrpc2_v2.ErrParse, params.ID)\n\t}\n\tc.Conn.Cancel(id)\n\treturn nil, nil\n}\n\ntype ForwardBinder struct {\n\tdialer jsonrpc2_v2.Dialer\n\tonBind func(*jsonrpc2_v2.Connection)\n}\n\nfunc NewForwardBinder(dialer jsonrpc2_v2.Dialer) *ForwardBinder {\n\treturn &ForwardBinder{\n\t\tdialer: dialer,\n\t}\n}\n\nfunc (b *ForwardBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) (opts jsonrpc2_v2.ConnectionOptions) {\n\tclient := protocol.ClientDispatcherV2(conn)\n\tclientBinder := NewClientBinder(func(context.Context, protocol.Server) protocol.Client { return client })\n\n\tserverConn, err := jsonrpc2_v2.Dial(context.Background(), b.dialer, clientBinder, nil)\n\tif err != nil {\n\t\treturn jsonrpc2_v2.ConnectionOptions{\n\t\t\tHandler: jsonrpc2_v2.HandlerFunc(func(context.Context, *jsonrpc2_v2.Request) (any, error) {\n\t\t\t\treturn nil, fmt.Errorf(\"%w: %v\", jsonrpc2_v2.ErrInternal, err)\n\t\t\t}),\n\t\t}\n\t}\n\n\tif b.onBind != nil {\n\t\tb.onBind(serverConn)\n\t}\n\tserver := protocol.ServerDispatcherV2(serverConn)\n\tpreempter := &Canceler{\n\t\tConn: conn,\n\t}\n\tdetached := xcontext.Detach(ctx)\n\tgo func() {\n\t\tconn.Wait() // ignore error\n\t\tif err := serverConn.Close(); err != nil {\n\t\t\tevent.Log(detached, fmt.Sprintf(\"closing remote connection: %v\", err))\n\t\t}\n\t}()\n\treturn jsonrpc2_v2.ConnectionOptions{\n\t\tHandler:   protocol.ServerHandlerV2(server),\n\t\tPreempter: preempter,\n\t}\n}\n\nfunc NewClientBinder(newClient ClientFunc) *clientBinder {\n\treturn &clientBinder{newClient}\n}\n\n// A ClientFunc is used to construct an LSP client for a given server.\ntype ClientFunc func(context.Context, protocol.Server) protocol.Client\n\n// clientBinder binds an LSP client to an incoming connection.\ntype clientBinder struct {\n\tnewClient ClientFunc\n}\n\nfunc (b *clientBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\tserver := protocol.ServerDispatcherV2(conn)\n\tclient := b.newClient(ctx, server)\n\treturn jsonrpc2_v2.ConnectionOptions{\n\t\tHandler: protocol.ClientHandlerV2(client),\n\t}\n}\n\n// HandlerMiddleware is a middleware that only modifies the jsonrpc2 handler.\ntype HandlerMiddleware func(jsonrpc2_v2.Handler) jsonrpc2_v2.Handler\n\n// BindHandler transforms a HandlerMiddleware into a Middleware.\nfunc BindHandler(hmw HandlerMiddleware) Middleware {\n\treturn Middleware(func(binder jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {\n\t\treturn BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\t\t\topts := binder.Bind(ctx, conn)\n\t\t\topts.Handler = hmw(opts.Handler)\n\t\t\treturn opts\n\t\t})\n\t})\n}\n\n// The BinderFunc type adapts a bind function to implement the jsonrpc2.Binder\n// interface.\ntype BinderFunc func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions\n\nfunc (f BinderFunc) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\treturn f(ctx, conn)\n}\n\n// Middleware defines a transformation of jsonrpc2 Binders, that may be\n// composed to build jsonrpc2 servers.\ntype Middleware func(jsonrpc2_v2.Binder) jsonrpc2_v2.Binder\n\nvar GetGoEnv = getGoEnv\n"
  },
  {
    "path": "gopls/internal/lsprpc/goenv.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n)\n\nfunc getGoEnv(ctx context.Context, env map[string]any) (map[string]string, error) {\n\tvar runEnv []string\n\tfor k, v := range env {\n\t\trunEnv = append(runEnv, fmt.Sprintf(\"%s=%s\", k, v))\n\t}\n\trunner := gocommand.Runner{}\n\toutput, err := runner.Run(ctx, gocommand.Invocation{\n\t\tVerb: \"env\",\n\t\tArgs: []string{\"-json\"},\n\t\tEnv:  runEnv,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tenvmap := make(map[string]string)\n\tif err := json.Unmarshal(output.Bytes(), &envmap); err != nil {\n\t\treturn nil, err\n\t}\n\treturn envmap, nil\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/goenv_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/testenv\"\n\n\t. \"golang.org/x/tools/gopls/internal/lsprpc\"\n)\n\nfunc GoEnvMiddleware() (Middleware, error) {\n\treturn BindHandler(func(delegate jsonrpc2_v2.Handler) jsonrpc2_v2.Handler {\n\t\treturn jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\t\tif req.Method == \"initialize\" {\n\t\t\t\tif err := addGoEnvToInitializeRequestV2(ctx, req); err != nil {\n\t\t\t\t\tevent.Error(ctx, \"adding go env to initialize\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn delegate.Handle(ctx, req)\n\t\t})\n\t}), nil\n}\n\n// This function is almost identical to addGoEnvToInitializeRequest in lsprpc.go.\n// Make changes in parallel.\nfunc addGoEnvToInitializeRequestV2(ctx context.Context, req *jsonrpc2_v2.Request) error {\n\tvar params protocol.ParamInitialize\n\tif err := json.Unmarshal(req.Params, &params); err != nil {\n\t\treturn err\n\t}\n\tvar opts map[string]any\n\tswitch v := params.InitializationOptions.(type) {\n\tcase nil:\n\t\topts = make(map[string]any)\n\tcase map[string]any:\n\t\topts = v\n\tdefault:\n\t\treturn fmt.Errorf(\"unexpected type for InitializationOptions: %T\", v)\n\t}\n\tenvOpt, ok := opts[\"env\"]\n\tif !ok {\n\t\tenvOpt = make(map[string]any)\n\t}\n\tenv, ok := envOpt.(map[string]any)\n\tif !ok {\n\t\treturn fmt.Errorf(\"env option is %T, expected a map\", envOpt)\n\t}\n\tgoenv, err := GetGoEnv(ctx, env)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// We don't want to propagate GOWORK unless explicitly set since that could mess with\n\t// path inference during cmd/go invocations, see golang/go#51825.\n\t_, goworkSet := os.LookupEnv(\"GOWORK\")\n\tfor govar, value := range goenv {\n\t\tif govar == \"GOWORK\" && !goworkSet {\n\t\t\tcontinue\n\t\t}\n\t\tenv[govar] = value\n\t}\n\topts[\"env\"] = env\n\tparams.InitializationOptions = opts\n\traw, err := json.Marshal(params)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling updated options: %v\", err)\n\t}\n\treq.Params = json.RawMessage(raw)\n\treturn nil\n}\n\ntype initServer struct {\n\tprotocol.Server\n\n\tparams *protocol.ParamInitialize\n}\n\nfunc (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {\n\ts.params = params\n\treturn &protocol.InitializeResult{}, nil\n}\n\nfunc TestGoEnvMiddleware(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tctx := context.Background()\n\n\tserver := &initServer{}\n\tenv := new(TestEnv)\n\tdefer env.Shutdown(t)\n\tl, _ := env.serve(ctx, t, staticServerBinder(server))\n\tmw, err := GoEnvMiddleware()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tbinder := mw(NewForwardBinder(l.Dialer()))\n\tl, _ = env.serve(ctx, t, binder)\n\tconn := env.dial(ctx, t, l.Dialer(), noopBinder, true)\n\tdispatch := protocol.ServerDispatcherV2(conn)\n\tinitParams := &protocol.ParamInitialize{}\n\tinitParams.InitializationOptions = map[string]any{\n\t\t\"env\": map[string]any{\n\t\t\t\"GONOPROXY\": \"example.com\",\n\t\t},\n\t}\n\tif _, err := dispatch.Initialize(ctx, initParams); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif server.params == nil {\n\t\tt.Fatalf(\"initialize params are unset\")\n\t}\n\tenvOpts := server.params.InitializationOptions.(map[string]any)[\"env\"].(map[string]any)\n\n\t// Check for an arbitrary Go variable. It should be set.\n\tif _, ok := envOpts[\"GOPRIVATE\"]; !ok {\n\t\tt.Errorf(\"Go environment variable GOPRIVATE unset in initialization options\")\n\t}\n\t// Check that the variable present in our user config was not overwritten.\n\tif got, want := envOpts[\"GONOPROXY\"], \"example.com\"; got != want {\n\t\tt.Errorf(\"GONOPROXY=%q, want %q\", got, want)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/lsprpc.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package lsprpc implements a jsonrpc2.StreamServer that may be used to\n// serve the LSP on a jsonrpc2 channel.\npackage lsprpc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"maps\"\n\t\"net\"\n\t\"os\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\n// Unique identifiers for client/server.\nvar serverIndex int64\n\n// The streamServer type is a jsonrpc2.streamServer that handles incoming\n// streams as a new LSP session, using a shared cache.\ntype StreamServer struct {\n\tcache *cache.Cache\n\t// daemon controls whether or not to log new connections.\n\tdaemon bool\n\n\t// optionsOverrides is passed to newly created sessions.\n\toptionsOverrides func(*settings.Options)\n\n\t// onSessionExit is called whenever a session exits, with the session ID.\n\tonSessionExit func(id string)\n\n\t// serverForTest may be set to a test fake for testing.\n\tserverForTest protocol.Server\n\n\t// Keep track of active sessions, for interrogation.\n\tsessionMu sync.Mutex\n\tsessions  map[string]sessionServer\n}\n\ntype sessionServer struct {\n\tsession *cache.Session\n\tserver  protocol.Server\n}\n\n// NewStreamServer creates a StreamServer using the shared cache. If\n// withTelemetry is true, each session is instrumented with telemetry that\n// records RPC statistics.\nfunc NewStreamServer(cache *cache.Cache, daemon bool, optionsFunc func(*settings.Options)) *StreamServer {\n\treturn &StreamServer{\n\t\tcache:            cache,\n\t\tdaemon:           daemon,\n\t\toptionsOverrides: optionsFunc,\n\t\tsessions:         make(map[string]sessionServer),\n\t}\n}\n\n// SetSessionExitFunc sets the function to call when sessions exit.\n// It is not concurrency safe, and must only be called at most once, before the\n// receiver is passed to jsonrpc2.Serve.\nfunc (s *StreamServer) SetSessionExitFunc(f func(id string)) {\n\tif s.onSessionExit != nil {\n\t\tpanic(\"duplicate call to SetSessionExitFunc\")\n\t}\n\ts.onSessionExit = f\n}\n\n// ServeStream implements the jsonrpc2.StreamServer interface, by handling\n// incoming streams using a new lsp server.\nfunc (s *StreamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) error {\n\tclient := protocol.ClientDispatcher(conn)\n\tsession := cache.NewSession(ctx, s.cache)\n\tsvr := s.serverForTest\n\tif svr == nil {\n\t\toptions := settings.DefaultOptions(s.optionsOverrides)\n\t\tsvr = server.New(session, client, options)\n\t\tif instance := debug.GetInstance(ctx); instance != nil {\n\t\t\tinstance.AddService(svr, session)\n\t\t}\n\t}\n\ts.sessionMu.Lock()\n\ts.sessions[session.ID()] = sessionServer{session, svr}\n\ts.sessionMu.Unlock()\n\tdefer func() {\n\t\ts.sessionMu.Lock()\n\t\tdelete(s.sessions, session.ID())\n\t\ts.sessionMu.Unlock()\n\t\tif s.onSessionExit != nil {\n\t\t\ts.onSessionExit(session.ID())\n\t\t}\n\t}()\n\n\t// Clients may or may not send a shutdown message. Make sure the server is\n\t// shut down.\n\t// TODO(rFindley): this shutdown should perhaps be on a disconnected context.\n\tdefer func() {\n\t\tif err := svr.Shutdown(ctx); err != nil {\n\t\t\tevent.Error(ctx, \"error shutting down\", err)\n\t\t}\n\t}()\n\texecutable, err := os.Executable()\n\tif err != nil {\n\t\tlog.Printf(\"error getting gopls path: %v\", err)\n\t\texecutable = \"\"\n\t}\n\tctx = protocol.WithClient(ctx, client)\n\tconn.Go(ctx,\n\t\tprotocol.Handlers(\n\t\t\thandshaker(session, executable, s.daemon,\n\t\t\t\tprotocol.ServerHandler(svr,\n\t\t\t\t\tjsonrpc2.MethodNotFound))))\n\n\tif s.daemon {\n\t\tlog.Printf(\"Session %s: connected\", session.ID())\n\t\tdefer log.Printf(\"Session %s: exited\", session.ID())\n\t}\n\n\t<-conn.Done()\n\treturn conn.Err()\n}\n\n// Session returns the current active session for the given id, or (nil, nil)\n// if none exists.\nfunc (s *StreamServer) Session(id string) (*cache.Session, protocol.Server) {\n\ts.sessionMu.Lock()\n\tdefer s.sessionMu.Unlock()\n\tss := s.sessions[id]\n\treturn ss.session, ss.server // possibly nil for zero value\n}\n\n// FirstSession returns the first session by lexically sorted session ID, or\n// (nil, nil).\nfunc (s *StreamServer) FirstSession() (*cache.Session, protocol.Server) {\n\ts.sessionMu.Lock()\n\tdefer s.sessionMu.Unlock()\n\tkeys := slices.Collect(maps.Keys(s.sessions))\n\tif len(keys) == 0 {\n\t\treturn nil, nil\n\t}\n\tid := slices.Min(keys)\n\tss := s.sessions[id]\n\treturn ss.session, ss.server\n}\n\n// A forwarder is a jsonrpc2.StreamServer that handles an LSP stream by\n// forwarding it to a remote. This is used when the gopls process started by\n// the editor is in the `-remote` mode, which means it finds and connects to a\n// separate gopls daemon. In these cases, we still want the forwarder gopls to\n// be instrumented with telemetry, and want to be able to in some cases hijack\n// the jsonrpc2 connection with the daemon.\ntype forwarder struct {\n\tdialer *autoDialer\n\n\tmu sync.Mutex\n\t// Hold on to the server connection so that we can redo the handshake if any\n\t// information changes.\n\tserverConn jsonrpc2.Conn\n\tserverID   string\n}\n\n// NewForwarder creates a new forwarder (a [jsonrpc2.StreamServer]),\n// ready to forward connections to the\n// remote server specified by rawAddr. If provided and rawAddr indicates an\n// 'automatic' address (starting with 'auto;'), argFunc may be used to start a\n// remote server for the auto-discovered address.\nfunc NewForwarder(rawAddr string, argFunc func(network, address string) []string) (jsonrpc2.StreamServer, error) {\n\tdialer, err := newAutoDialer(rawAddr, argFunc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfwd := &forwarder{\n\t\tdialer: dialer,\n\t}\n\treturn fwd, nil\n}\n\n// QueryServerState returns a JSON-encodable struct describing the state of the named server.\nfunc QueryServerState(ctx context.Context, addr string) (any, error) {\n\tserverConn, err := dialRemote(ctx, addr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar state serverState\n\tif err := protocol.Call(ctx, serverConn, sessionsMethod, nil, &state); err != nil {\n\t\treturn nil, fmt.Errorf(\"querying server state: %w\", err)\n\t}\n\treturn &state, nil\n}\n\n// dialRemote is used for making calls into the gopls daemon. addr should be a\n// URL, possibly on the synthetic 'auto' network (e.g. tcp://..., unix://...,\n// or auto://...).\nfunc dialRemote(ctx context.Context, addr string) (jsonrpc2.Conn, error) {\n\tnetwork, address := ParseAddr(addr)\n\tif network == autoNetwork {\n\t\tgp, err := os.Executable()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"getting gopls path: %w\", err)\n\t\t}\n\t\tnetwork, address = autoNetworkAddress(gp, address)\n\t}\n\tnetConn, err := net.DialTimeout(network, address, 5*time.Second)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"dialing remote: %w\", err)\n\t}\n\tserverConn := jsonrpc2.NewConn(jsonrpc2.NewHeaderStream(netConn))\n\tserverConn.Go(ctx, jsonrpc2.MethodNotFound)\n\treturn serverConn, nil\n}\n\n// ExecuteCommand connects to the named server, sends it a\n// workspace/executeCommand request (with command 'id' and arguments\n// JSON encoded in 'request'), and populates the result variable.\nfunc ExecuteCommand(ctx context.Context, addr string, id string, request, result any) error {\n\tserverConn, err := dialRemote(ctx, addr)\n\tif err != nil {\n\t\treturn err\n\t}\n\targs, err := command.MarshalArgs(request)\n\tif err != nil {\n\t\treturn err\n\t}\n\tparams := protocol.ExecuteCommandParams{\n\t\tCommand:   id,\n\t\tArguments: args,\n\t}\n\treturn protocol.Call(ctx, serverConn, \"workspace/executeCommand\", params, result)\n}\n\n// ServeStream dials the forwarder remote and binds the remote to serve the LSP\n// on the incoming stream.\nfunc (f *forwarder) ServeStream(ctx context.Context, clientConn jsonrpc2.Conn) error {\n\tclient := protocol.ClientDispatcher(clientConn)\n\n\tnetConn, err := f.dialer.dialNet(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"forwarder: connecting to remote: %w\", err)\n\t}\n\tserverConn := jsonrpc2.NewConn(jsonrpc2.NewHeaderStream(netConn))\n\tserver := protocol.ServerDispatcher(serverConn)\n\n\t// Forward between connections.\n\tserverConn.Go(ctx,\n\t\tprotocol.Handlers(\n\t\t\tprotocol.ClientHandler(client,\n\t\t\t\tjsonrpc2.MethodNotFound)))\n\n\t// Don't run the clientConn yet, so that we can complete the handshake before\n\t// processing any client messages.\n\n\t// Do a handshake with the server instance to exchange debug information.\n\tindex := atomic.AddInt64(&serverIndex, 1)\n\tf.mu.Lock()\n\tf.serverConn = serverConn\n\tf.serverID = strconv.FormatInt(index, 10)\n\tf.mu.Unlock()\n\tf.handshake(ctx)\n\tclientConn.Go(ctx,\n\t\tprotocol.Handlers(\n\t\t\tf.handler(\n\t\t\t\tprotocol.ServerHandler(server,\n\t\t\t\t\tjsonrpc2.MethodNotFound))))\n\n\tselect {\n\tcase <-serverConn.Done():\n\t\tclientConn.Close() // ignore error\n\tcase <-clientConn.Done():\n\t\tserverConn.Close() // ignore error\n\t}\n\n\terr = nil\n\tif serverConn.Err() != nil {\n\t\terr = fmt.Errorf(\"remote disconnected: %v\", serverConn.Err())\n\t} else if clientConn.Err() != nil {\n\t\terr = fmt.Errorf(\"client disconnected: %v\", clientConn.Err())\n\t}\n\tevent.Log(ctx, fmt.Sprintf(\"forwarder: exited with error: %v\", err))\n\treturn err\n}\n\n// TODO(rfindley): remove this handshaking in favor of middleware.\nfunc (f *forwarder) handshake(ctx context.Context) {\n\t// This call to os.Executable is redundant, and will be eliminated by the\n\t// transition to the V2 API.\n\tgoplsPath, err := os.Executable()\n\tif err != nil {\n\t\tevent.Error(ctx, \"getting executable for handshake\", err)\n\t\tgoplsPath = \"\"\n\t}\n\tvar (\n\t\threq = handshakeRequest{\n\t\t\tServerID:  f.serverID,\n\t\t\tGoplsPath: goplsPath,\n\t\t}\n\t\thresp handshakeResponse\n\t)\n\tif di := debug.GetInstance(ctx); di != nil {\n\t\threq.Logfile = di.Logfile\n\t\threq.DebugAddr = di.ListenedDebugAddress()\n\t}\n\tif err := protocol.Call(ctx, f.serverConn, handshakeMethod, hreq, &hresp); err != nil {\n\t\t// TODO(rfindley): at some point in the future we should return an error\n\t\t// here.  Handshakes have become functional in nature.\n\t\tevent.Error(ctx, \"forwarder: gopls handshake failed\", err)\n\t}\n\tif hresp.GoplsPath != goplsPath {\n\t\tevent.Error(ctx, \"\", fmt.Errorf(\"forwarder: gopls path mismatch: forwarder is %q, remote is %q\", goplsPath, hresp.GoplsPath))\n\t}\n\tevent.Log(ctx, \"New server\",\n\t\tlabel.NewServer.Of(f.serverID),\n\t\tlabel.Logfile.Of(hresp.Logfile),\n\t\tlabel.DebugAddress.Of(hresp.DebugAddr),\n\t\tlabel.GoplsPath.Of(hresp.GoplsPath),\n\t\tlabel.ClientID.Of(hresp.SessionID),\n\t)\n}\n\nfunc ConnectToRemote(ctx context.Context, addr string) (net.Conn, error) {\n\tdialer, err := newAutoDialer(addr, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn dialer.dialNet(ctx)\n}\n\n// handler intercepts messages to the daemon to enrich them with local\n// information.\nfunc (f *forwarder) handler(handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {\n\t\t// Intercept certain messages to add special handling.\n\t\tswitch r.Method() {\n\t\tcase \"initialize\":\n\t\t\tif newr, err := addGoEnvToInitializeRequest(ctx, r); err == nil {\n\t\t\t\tr = newr\n\t\t\t} else {\n\t\t\t\tlog.Printf(\"unable to add local env to initialize request: %v\", err)\n\t\t\t}\n\t\tcase \"workspace/executeCommand\":\n\t\t\tvar params protocol.ExecuteCommandParams\n\t\t\tif err := json.Unmarshal(r.Params(), &params); err == nil {\n\t\t\t\tif params.Command == command.StartDebugging.String() {\n\t\t\t\t\tvar args command.DebuggingArgs\n\t\t\t\t\tif err := command.UnmarshalArgs(params.Arguments, &args); err == nil {\n\t\t\t\t\t\treply = f.replyWithDebugAddress(ctx, reply, args)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tevent.Error(ctx, \"unmarshaling debugging args\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tevent.Error(ctx, \"intercepting executeCommand request\", err)\n\t\t\t}\n\t\t}\n\t\t// The gopls workspace environment defaults to the process environment in\n\t\t// which gopls daemon was started. To avoid discrepancies in Go environment\n\t\t// between the editor and daemon, inject any unset variables in `go env`\n\t\t// into the options sent by initialize.\n\t\t//\n\t\t// See also golang.org/issue/37830.\n\t\treturn handler(ctx, reply, r)\n\t}\n}\n\n// addGoEnvToInitializeRequest builds a new initialize request in which we set\n// any environment variables output by `go env` and not already present in the\n// request.\n//\n// It returns an error if r is not an initialize request, or is otherwise\n// malformed.\nfunc addGoEnvToInitializeRequest(ctx context.Context, r jsonrpc2.Request) (jsonrpc2.Request, error) {\n\tvar params protocol.ParamInitialize\n\tif err := json.Unmarshal(r.Params(), &params); err != nil {\n\t\treturn nil, err\n\t}\n\tvar opts map[string]any\n\tswitch v := params.InitializationOptions.(type) {\n\tcase nil:\n\t\topts = make(map[string]any)\n\tcase map[string]any:\n\t\topts = v\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unexpected type for InitializationOptions: %T\", v)\n\t}\n\tenvOpt, ok := opts[\"env\"]\n\tif !ok {\n\t\tenvOpt = make(map[string]any)\n\t}\n\tenv, ok := envOpt.(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(`env option is %T, expected a map`, envOpt)\n\t}\n\tgoenv, err := getGoEnv(ctx, env)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// We don't want to propagate GOWORK unless explicitly set since that could mess with\n\t// path inference during cmd/go invocations, see golang/go#51825.\n\t_, goworkSet := os.LookupEnv(\"GOWORK\")\n\tfor govar, value := range goenv {\n\t\tif govar == \"GOWORK\" && !goworkSet {\n\t\t\tcontinue\n\t\t}\n\t\tenv[govar] = value\n\t}\n\topts[\"env\"] = env\n\tparams.InitializationOptions = opts\n\tcall, ok := r.(*jsonrpc2.Call)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%T is not a *jsonrpc2.Call\", r)\n\t}\n\treturn jsonrpc2.NewCall(call.ID(), \"initialize\", params)\n}\n\nfunc (f *forwarder) replyWithDebugAddress(outerCtx context.Context, r jsonrpc2.Replier, args command.DebuggingArgs) jsonrpc2.Replier {\n\tdi := debug.GetInstance(outerCtx)\n\tif di == nil {\n\t\tevent.Log(outerCtx, \"no debug instance to start\")\n\t\treturn r\n\t}\n\treturn func(ctx context.Context, result any, outerErr error) error {\n\t\tif outerErr != nil {\n\t\t\treturn r(ctx, result, outerErr)\n\t\t}\n\t\t// Enrich the result with our own debugging information. Since we're an\n\t\t// intermediary, the jsonrpc2 package has deserialized the result into\n\t\t// maps, by default. Re-do the unmarshalling.\n\t\traw, err := json.Marshal(result)\n\t\tif err != nil {\n\t\t\tevent.Error(outerCtx, \"marshaling intermediate command result\", err)\n\t\t\treturn r(ctx, result, err)\n\t\t}\n\t\tvar modified command.DebuggingResult\n\t\tif err := json.Unmarshal(raw, &modified); err != nil {\n\t\t\tevent.Error(outerCtx, \"unmarshaling intermediate command result\", err)\n\t\t\treturn r(ctx, result, err)\n\t\t}\n\t\taddr := args.Addr\n\t\tif addr == \"\" {\n\t\t\taddr = \"localhost:0\"\n\t\t}\n\t\taddr, err = di.Serve(outerCtx, addr)\n\t\tif err != nil {\n\t\t\tevent.Error(outerCtx, \"starting debug server\", err)\n\t\t\treturn r(ctx, result, err)\n\t\t}\n\t\turls := []string{\"http://\" + addr}\n\t\tmodified.URLs = append(urls, modified.URLs...)\n\t\tgo f.handshake(ctx)\n\t\treturn r(ctx, modified, nil)\n\t}\n}\n\n// A handshakeRequest identifies a client to the LSP server.\ntype handshakeRequest struct {\n\t// ServerID is the ID of the server on the client. This should usually be 0.\n\tServerID string `json:\"serverID\"`\n\t// Logfile is the location of the clients log file.\n\tLogfile string `json:\"logfile\"`\n\t// DebugAddr is the client debug address.\n\tDebugAddr string `json:\"debugAddr\"`\n\t// GoplsPath is the path to the Gopls binary running the current client\n\t// process.\n\tGoplsPath string `json:\"goplsPath\"`\n}\n\n// A handshakeResponse is returned by the LSP server to tell the LSP client\n// information about its session.\ntype handshakeResponse struct {\n\t// SessionID is the server session associated with the client.\n\tSessionID string `json:\"sessionID\"`\n\t// Logfile is the location of the server logs.\n\tLogfile string `json:\"logfile\"`\n\t// DebugAddr is the server debug address.\n\tDebugAddr string `json:\"debugAddr\"`\n\t// GoplsPath is the path to the Gopls binary running the current server\n\t// process.\n\tGoplsPath string `json:\"goplsPath\"`\n}\n\n// clientSession identifies a current client LSP session on the server. Note\n// that it looks similar to handshakeResponse, but in fact 'Logfile' and\n// 'DebugAddr' now refer to the client.\ntype clientSession struct {\n\tSessionID string `json:\"sessionID\"`\n\tLogfile   string `json:\"logfile\"`\n\tDebugAddr string `json:\"debugAddr\"`\n}\n\n// serverState holds information about the gopls daemon process, including its\n// debug information and debug information of all of its current connected\n// clients.\ntype serverState struct {\n\tLogfile         string          `json:\"logfile\"`\n\tDebugAddr       string          `json:\"debugAddr\"`\n\tGoplsPath       string          `json:\"goplsPath\"`\n\tCurrentClientID string          `json:\"currentClientID\"`\n\tClients         []clientSession `json:\"clients\"`\n}\n\nconst (\n\thandshakeMethod = \"gopls/handshake\"\n\tsessionsMethod  = \"gopls/sessions\"\n)\n\nfunc handshaker(session *cache.Session, goplsPath string, logHandshakes bool, handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {\n\t\tswitch r.Method() {\n\t\tcase handshakeMethod:\n\t\t\t// We log.Printf in this handler, rather than event.Log when we want logs\n\t\t\t// to go to the daemon log rather than being reflected back to the\n\t\t\t// client.\n\t\t\tvar req handshakeRequest\n\t\t\tif err := json.Unmarshal(r.Params(), &req); err != nil {\n\t\t\t\tif logHandshakes {\n\t\t\t\t\tlog.Printf(\"Error processing handshake for session %s: %v\", session.ID(), err)\n\t\t\t\t}\n\t\t\t\tsendError(ctx, reply, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif logHandshakes {\n\t\t\t\tlog.Printf(\"Session %s: got handshake. Logfile: %q, Debug addr: %q\", session.ID(), req.Logfile, req.DebugAddr)\n\t\t\t}\n\t\t\tevent.Log(ctx, \"Handshake session update\",\n\t\t\t\tcache.KeyUpdateSession.Of(session),\n\t\t\t\tlabel.DebugAddress.Of(req.DebugAddr),\n\t\t\t\tlabel.Logfile.Of(req.Logfile),\n\t\t\t\tlabel.ServerID.Of(req.ServerID),\n\t\t\t\tlabel.GoplsPath.Of(req.GoplsPath),\n\t\t\t)\n\t\t\tresp := handshakeResponse{\n\t\t\t\tSessionID: session.ID(),\n\t\t\t\tGoplsPath: goplsPath,\n\t\t\t}\n\t\t\tif di := debug.GetInstance(ctx); di != nil {\n\t\t\t\tresp.Logfile = di.Logfile\n\t\t\t\tresp.DebugAddr = di.ListenedDebugAddress()\n\t\t\t}\n\t\t\treturn reply(ctx, resp, nil)\n\n\t\tcase sessionsMethod:\n\t\t\tresp := serverState{\n\t\t\t\tGoplsPath:       goplsPath,\n\t\t\t\tCurrentClientID: session.ID(),\n\t\t\t}\n\t\t\tif di := debug.GetInstance(ctx); di != nil {\n\t\t\t\tresp.Logfile = di.Logfile\n\t\t\t\tresp.DebugAddr = di.ListenedDebugAddress()\n\t\t\t\tfor _, c := range di.State.Clients() {\n\t\t\t\t\tresp.Clients = append(resp.Clients, clientSession{\n\t\t\t\t\t\tSessionID: c.Session.ID(),\n\t\t\t\t\t\tLogfile:   c.Logfile,\n\t\t\t\t\t\tDebugAddr: c.DebugAddress,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn reply(ctx, resp, nil)\n\t\t}\n\t\treturn handler(ctx, reply, r)\n\t}\n}\n\nfunc sendError(ctx context.Context, reply jsonrpc2.Replier, err error) {\n\terr = fmt.Errorf(\"%v: %w\", err, jsonrpc2.ErrParse)\n\tif err := reply(ctx, nil, err); err != nil {\n\t\tevent.Error(ctx, \"\", err)\n\t}\n}\n\n// ParseAddr parses the address of a gopls remote.\n// TODO(rFindley): further document this syntax, and allow URI-style remote\n// addresses such as \"auto://...\".\nfunc ParseAddr(listen string) (network string, address string) {\n\t// Allow passing just -remote=auto, as a shorthand for using automatic remote\n\t// resolution.\n\tif listen == autoNetwork {\n\t\treturn autoNetwork, \"\"\n\t}\n\tif parts := strings.SplitN(listen, \";\", 2); len(parts) == 2 {\n\t\treturn parts[0], parts[1]\n\t}\n\treturn \"tcp\", listen\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/lsprpc_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\ntype FakeClient struct {\n\tprotocol.Client\n\n\tLogs chan string\n}\n\nfunc (c FakeClient) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {\n\tc.Logs <- params.Message\n\treturn nil\n}\n\n// fakeServer is intended to be embedded in the test fakes below, to trivially\n// implement Shutdown.\ntype fakeServer struct {\n\tprotocol.Server\n}\n\nfunc (fakeServer) Shutdown(ctx context.Context) error {\n\treturn nil\n}\n\ntype PingServer struct{ fakeServer }\n\nfunc (s PingServer) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {\n\tevent.Log(ctx, \"ping\")\n\treturn nil\n}\n\nfunc TestClientLogging(t *testing.T) {\n\tctx := t.Context()\n\n\tserver := PingServer{}\n\tclient := FakeClient{Logs: make(chan string, 10)}\n\n\tctx = debug.WithInstance(ctx, \"\")\n\tss := NewStreamServer(cache.New(nil), false, nil)\n\tss.serverForTest = server\n\tts := servertest.NewPipeServer(ss, nil)\n\tdefer checkClose(t, ts.Close)\n\tcc := ts.Connect(ctx)\n\tcc.Go(ctx, protocol.ClientHandler(client, jsonrpc2.MethodNotFound))\n\n\tif err := protocol.ServerDispatcher(cc).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil {\n\t\tt.Errorf(\"DidOpen: %v\", err)\n\t}\n\n\tselect {\n\tcase got := <-client.Logs:\n\t\twant := \"ping\"\n\t\tmatched, err := regexp.MatchString(want, got)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !matched {\n\t\t\tt.Errorf(\"got log %q, want a log containing %q\", got, want)\n\t\t}\n\n\tcase <-time.After(10 * time.Second):\n\t\t// Any timeout we enforce here is at the mercy\n\t\t// of the underlying operating system.\n\t\t// 1s was occasionally flaky; 10s should be better.\n\t\tt.Error(\"timeout waiting for client log\")\n\t}\n}\n\n// WaitableServer instruments LSP request so that we can control their timing.\n// The requests chosen are arbitrary: we simply needed one that blocks, and\n// another that doesn't.\ntype WaitableServer struct {\n\tfakeServer\n\n\tStarted   chan struct{}\n\tCompleted chan error\n}\n\nfunc (s WaitableServer) Hover(ctx context.Context, _ *protocol.HoverParams) (_ *protocol.Hover, err error) {\n\ts.Started <- struct{}{}\n\tdefer func() {\n\t\ts.Completed <- err\n\t}()\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, errors.New(\"cancelled hover\")\n\tcase <-time.After(10 * time.Second):\n\t}\n\treturn &protocol.Hover{}, nil\n}\n\nfunc (s WaitableServer) ResolveCompletionItem(_ context.Context, item *protocol.CompletionItem) (*protocol.CompletionItem, error) {\n\treturn item, nil\n}\n\nfunc checkClose(t *testing.T, closer func() error) {\n\tt.Helper()\n\tif err := closer(); err != nil {\n\t\tt.Errorf(\"closing: %v\", err)\n\t}\n}\n\nfunc setupForwarding(ctx context.Context, t *testing.T, s protocol.Server) (direct, forwarded servertest.Connector, cleanup func()) {\n\tt.Helper()\n\tserveCtx := debug.WithInstance(ctx, \"\")\n\tss := NewStreamServer(cache.New(nil), false, nil)\n\tss.serverForTest = s\n\ttsDirect := servertest.NewTCPServer(serveCtx, ss, nil)\n\n\tforwarder, err := NewForwarder(\"tcp;\"+tsDirect.Addr, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttsForwarded := servertest.NewPipeServer(forwarder, nil)\n\treturn tsDirect, tsForwarded, func() {\n\t\tcheckClose(t, tsDirect.Close)\n\t\tcheckClose(t, tsForwarded.Close)\n\t}\n}\n\nfunc TestRequestCancellation(t *testing.T) {\n\tctx := context.Background()\n\tserver := WaitableServer{\n\t\tStarted:   make(chan struct{}),\n\t\tCompleted: make(chan error),\n\t}\n\ttsDirect, tsForwarded, cleanup := setupForwarding(ctx, t, server)\n\tdefer cleanup()\n\ttests := []struct {\n\t\tserverType string\n\t\tts         servertest.Connector\n\t}{\n\t\t{\"direct\", tsDirect},\n\t\t{\"forwarder\", tsForwarded},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.serverType, func(t *testing.T) {\n\t\t\tcc := test.ts.Connect(ctx)\n\t\t\tsd := protocol.ServerDispatcher(cc)\n\t\t\tcc.Go(ctx,\n\t\t\t\tprotocol.Handlers(\n\t\t\t\t\tjsonrpc2.MethodNotFound))\n\n\t\t\tctx := context.Background()\n\t\t\tctx, cancel := context.WithCancel(ctx)\n\n\t\t\tresult := make(chan error)\n\t\t\tgo func() {\n\t\t\t\t_, err := sd.Hover(ctx, &protocol.HoverParams{})\n\t\t\t\tresult <- err\n\t\t\t}()\n\t\t\t// Wait for the Hover request to start.\n\t\t\t<-server.Started\n\t\t\tcancel()\n\t\t\tif err := <-result; err == nil {\n\t\t\t\tt.Error(\"nil error for cancelled Hover(), want non-nil\")\n\t\t\t}\n\t\t\tif err := <-server.Completed; err == nil || !strings.Contains(err.Error(), \"cancelled hover\") {\n\t\t\t\tt.Errorf(\"Hover(): unexpected server-side error %v\", err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nconst exampleProgram = `\n-- go.mod --\nmodule mod\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello World.\")\n}`\n\nfunc TestDebugInfoLifecycle(t *testing.T) {\n\tsb, err := fake.NewSandbox(&fake.SandboxConfig{Files: fake.UnpackTxt(exampleProgram)})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := sb.Close(); err != nil {\n\t\t\t// TODO(golang/go#38490): we can't currently make this an error because\n\t\t\t// it fails on Windows: the workspace directory is still locked by a\n\t\t\t// separate Go process.\n\t\t\t// Once we have a reliable way to wait for proper shutdown, make this an\n\t\t\t// error.\n\t\t\tt.Logf(\"closing workspace failed: %v\", err)\n\t\t}\n\t}()\n\n\tbaseCtx := t.Context()\n\tclientCtx := debug.WithInstance(baseCtx, \"\")\n\tserverCtx := debug.WithInstance(baseCtx, \"\")\n\n\tss := NewStreamServer(cache.New(nil), false, nil)\n\ttsBackend := servertest.NewTCPServer(serverCtx, ss, nil)\n\n\tforwarder, err := NewForwarder(\"tcp;\"+tsBackend.Addr, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttsForwarder := servertest.NewPipeServer(forwarder, nil)\n\n\ted1, err := fake.NewEditor(sb, fake.EditorConfig{}).Connect(clientCtx, tsForwarder, fake.ClientHooks{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer ed1.Close(clientCtx)\n\ted2, err := fake.NewEditor(sb, fake.EditorConfig{}).Connect(baseCtx, tsBackend, fake.ClientHooks{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer ed2.Close(baseCtx)\n\n\tserverDebug := debug.GetInstance(serverCtx)\n\tif got, want := len(serverDebug.State.Clients()), 2; got != want {\n\t\tt.Errorf(\"len(server:Clients) = %d, want %d\", got, want)\n\t}\n\tif got, want := len(serverDebug.State.Sessions()), 2; got != want {\n\t\tt.Errorf(\"len(server:Sessions) = %d, want %d\", got, want)\n\t}\n\tclientDebug := debug.GetInstance(clientCtx)\n\tif got, want := len(clientDebug.State.Servers()), 1; got != want {\n\t\tt.Errorf(\"len(client:Servers) = %d, want %d\", got, want)\n\t}\n\t// Close one of the connections to verify that the client and session were\n\t// dropped.\n\tif err := ed1.Close(clientCtx); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t/*TODO: at this point we have verified the editor is closed\n\tHowever there is no way currently to wait for all associated go routines to\n\tgo away, and we need to wait for those to trigger the client drop\n\tfor now we just give it a little bit of time, but we need to fix this\n\tin a principled way\n\t*/\n\tstart := time.Now()\n\tdelay := time.Millisecond\n\tconst maxWait = time.Second\n\tfor len(serverDebug.State.Clients()) > 1 {\n\t\tif time.Since(start) > maxWait {\n\t\t\tbreak\n\t\t}\n\t\ttime.Sleep(delay)\n\t\tdelay *= 2\n\t}\n\tif got, want := len(serverDebug.State.Clients()), 1; got != want {\n\t\tt.Errorf(\"len(server:Clients) = %d, want %d\", got, want)\n\t}\n\tif got, want := len(serverDebug.State.Sessions()), 1; got != want {\n\t\tt.Errorf(\"len(server:Sessions()) = %d, want %d\", got, want)\n\t}\n}\n\ntype initServer struct {\n\tfakeServer\n\n\tparams *protocol.ParamInitialize\n}\n\nfunc (s *initServer) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {\n\ts.params = params\n\treturn &protocol.InitializeResult{}, nil\n}\n\nfunc TestEnvForwarding(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tctx := context.Background()\n\n\tserver := &initServer{}\n\t_, tsForwarded, cleanup := setupForwarding(ctx, t, server)\n\tdefer cleanup()\n\n\tconn := tsForwarded.Connect(ctx)\n\tconn.Go(ctx, jsonrpc2.MethodNotFound)\n\tdispatch := protocol.ServerDispatcher(conn)\n\tinitParams := &protocol.ParamInitialize{}\n\tinitParams.InitializationOptions = map[string]any{\n\t\t\"env\": map[string]any{\n\t\t\t\"GONOPROXY\": \"example.com\",\n\t\t},\n\t}\n\t_, err := dispatch.Initialize(ctx, initParams)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif server.params == nil {\n\t\tt.Fatalf(\"initialize params are unset\")\n\t}\n\tenv := server.params.InitializationOptions.(map[string]any)[\"env\"].(map[string]any)\n\n\t// Check for an arbitrary Go variable. It should be set.\n\tif _, ok := env[\"GOPRIVATE\"]; !ok {\n\t\tt.Errorf(\"Go environment variable GOPRIVATE unset in initialization options\")\n\t}\n\t// Check that the variable present in our user config was not overwritten.\n\tif v := env[\"GONOPROXY\"]; v != \"example.com\" {\n\t\tt.Errorf(\"GONOPROXY environment variable was overwritten\")\n\t}\n}\n\nfunc TestListenParsing(t *testing.T) {\n\ttests := []struct {\n\t\tinput, wantNetwork, wantAddr string\n\t}{\n\t\t{\"127.0.0.1:0\", \"tcp\", \"127.0.0.1:0\"},\n\t\t{\"unix;/tmp/sock\", \"unix\", \"/tmp/sock\"},\n\t\t{\"auto\", \"auto\", \"\"},\n\t\t{\"auto;foo\", \"auto\", \"foo\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotNetwork, gotAddr := ParseAddr(test.input)\n\t\tif gotNetwork != test.wantNetwork {\n\t\t\tt.Errorf(\"network = %q, want %q\", gotNetwork, test.wantNetwork)\n\t\t}\n\t\tif gotAddr != test.wantAddr {\n\t\t\tt.Errorf(\"addr = %q, want %q\", gotAddr, test.wantAddr)\n\t\t}\n\t}\n}\n\n// For #59479, verify that empty slices are serialized as [].\nfunc TestEmptySlices(t *testing.T) {\n\t// The LSP would prefer that empty slices be sent as [] rather than null.\n\tconst bad = `{\"a\":null}`\n\tconst good = `{\"a\":[]}`\n\tvar x struct {\n\t\tA []string `json:\"a\"`\n\t}\n\tbuf, _ := json.Marshal(x)\n\tif string(buf) != bad {\n\t\t// uninitialized is ezpected to give null\n\t\tt.Errorf(\"unexpectedly got %s, want %s\", buf, bad)\n\t}\n\tx.A = make([]string, 0)\n\tbuf, _ = json.Marshal(x)\n\tif string(buf) != good {\n\t\t// expect []\n\t\tt.Errorf(\"unexpectedly got %s, want %s\", buf, good)\n\t}\n\tx.A = []string{}\n\tbuf, _ = json.Marshal(x)\n\tif string(buf) != good {\n\t\t// expect []\n\t\tt.Errorf(\"unexpectedly got %s, want %s\", buf, good)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/lsprpc/middleware_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lsprpc_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/internal/event\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\nvar noopBinder = BinderFunc(func(context.Context, *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\treturn jsonrpc2_v2.ConnectionOptions{}\n})\n\nfunc TestHandshakeMiddleware(t *testing.T) {\n\tsh := &Handshaker{\n\t\tmetadata: metadata{\n\t\t\t\"answer\": 42,\n\t\t},\n\t}\n\tctx := context.Background()\n\tenv := new(TestEnv)\n\tdefer env.Shutdown(t)\n\tl, _ := env.serve(ctx, t, sh.Middleware(noopBinder))\n\tconn := env.dial(ctx, t, l.Dialer(), noopBinder, false)\n\tch := &Handshaker{\n\t\tmetadata: metadata{\n\t\t\t\"question\": 6 * 9,\n\t\t},\n\t}\n\n\tcheck := func(connected bool) error {\n\t\tclients := sh.Peers()\n\t\tservers := ch.Peers()\n\t\twant := 0\n\t\tif connected {\n\t\t\twant = 1\n\t\t}\n\t\tif got := len(clients); got != want {\n\t\t\treturn fmt.Errorf(\"got %d clients on the server, want %d\", got, want)\n\t\t}\n\t\tif got := len(servers); got != want {\n\t\t\treturn fmt.Errorf(\"got %d servers on the client, want %d\", got, want)\n\t\t}\n\t\tif !connected {\n\t\t\treturn nil\n\t\t}\n\t\tclient := clients[0]\n\t\tserver := servers[0]\n\t\tif _, ok := client.Metadata[\"question\"]; !ok {\n\t\t\treturn errors.New(\"no client metadata\")\n\t\t}\n\t\tif _, ok := server.Metadata[\"answer\"]; !ok {\n\t\t\treturn errors.New(\"no server metadata\")\n\t\t}\n\t\tif client.LocalID != server.RemoteID {\n\t\t\treturn fmt.Errorf(\"client.LocalID == %d, server.PeerID == %d\", client.LocalID, server.RemoteID)\n\t\t}\n\t\tif client.RemoteID != server.LocalID {\n\t\t\treturn fmt.Errorf(\"client.PeerID == %d, server.LocalID == %d\", client.RemoteID, server.LocalID)\n\t\t}\n\t\treturn nil\n\t}\n\n\tif err := check(false); err != nil {\n\t\tt.Fatalf(\"before handshake: %v\", err)\n\t}\n\tch.ClientHandshake(ctx, conn)\n\tif err := check(true); err != nil {\n\t\tt.Fatalf(\"after handshake: %v\", err)\n\t}\n\tconn.Close() // ignore error\n\t// Wait for up to ~2s for connections to get cleaned up.\n\tdelay := 25 * time.Millisecond\n\tfor retries := 3; retries >= 0; retries-- {\n\t\ttime.Sleep(delay)\n\t\terr := check(false)\n\t\tif err == nil {\n\t\t\treturn\n\t\t}\n\t\tif retries == 0 {\n\t\t\tt.Fatalf(\"after closing connection: %v\", err)\n\t\t}\n\t\tdelay *= 4\n\t}\n}\n\n// Handshaker handles both server and client handshaking over jsonrpc2 v2.\n// To instrument server-side handshaking, use Handshaker.Middleware.\n// To instrument client-side handshaking, call\n// Handshaker.ClientHandshake for any new client-side connections.\ntype Handshaker struct {\n\t// metadata will be shared with peers via handshaking.\n\tmetadata metadata\n\n\tmu     sync.Mutex\n\tprevID int64\n\tpeers  map[int64]PeerInfo\n}\n\n// metadata holds arbitrary data transferred between jsonrpc2 peers.\ntype metadata map[string]any\n\n// PeerInfo holds information about a peering between jsonrpc2 servers.\ntype PeerInfo struct {\n\t// RemoteID is the identity of the current server on its peer.\n\tRemoteID int64\n\n\t// LocalID is the identity of the peer on the server.\n\tLocalID int64\n\n\t// IsClient reports whether the peer is a client. If false, the peer is a\n\t// server.\n\tIsClient bool\n\n\t// Metadata holds arbitrary information provided by the peer.\n\tMetadata metadata\n}\n\n// Peers returns the peer info this handshaker knows about by way of either the\n// server-side handshake middleware, or client-side handshakes.\nfunc (h *Handshaker) Peers() []PeerInfo {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\n\tvar c []PeerInfo\n\tfor _, v := range h.peers {\n\t\tc = append(c, v)\n\t}\n\treturn c\n}\n\n// Middleware is a jsonrpc2 middleware function to augment connection binding\n// to handle the handshake method, and record disconnections.\nfunc (h *Handshaker) Middleware(inner jsonrpc2_v2.Binder) jsonrpc2_v2.Binder {\n\treturn BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions {\n\t\topts := inner.Bind(ctx, conn)\n\n\t\tlocalID := h.nextID()\n\t\tinfo := &PeerInfo{\n\t\t\tRemoteID: localID,\n\t\t\tMetadata: h.metadata,\n\t\t}\n\n\t\t// Wrap the delegated handler to accept the handshake.\n\t\tdelegate := opts.Handler\n\t\topts.Handler = jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\t\tif req.Method == HandshakeMethod {\n\t\t\t\tvar peerInfo PeerInfo\n\t\t\t\tif err := json.Unmarshal(req.Params, &peerInfo); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"%w: unmarshaling client info: %v\", jsonrpc2_v2.ErrInvalidParams, err)\n\t\t\t\t}\n\t\t\t\tpeerInfo.LocalID = localID\n\t\t\t\tpeerInfo.IsClient = true\n\t\t\t\th.recordPeer(peerInfo)\n\t\t\t\treturn info, nil\n\t\t\t}\n\t\t\treturn delegate.Handle(ctx, req)\n\t\t})\n\n\t\t// Record the dropped client.\n\t\tgo h.cleanupAtDisconnect(conn, localID)\n\n\t\treturn opts\n\t})\n}\n\n// ClientHandshake performs a client-side handshake with the server at the\n// other end of conn, recording the server's peer info and watching for conn's\n// disconnection.\nfunc (h *Handshaker) ClientHandshake(ctx context.Context, conn *jsonrpc2_v2.Connection) {\n\tlocalID := h.nextID()\n\tinfo := &PeerInfo{\n\t\tRemoteID: localID,\n\t\tMetadata: h.metadata,\n\t}\n\n\tcall := conn.Call(ctx, HandshakeMethod, info)\n\tvar serverInfo PeerInfo\n\tif err := call.Await(ctx, &serverInfo); err != nil {\n\t\tevent.Error(ctx, \"performing handshake\", err)\n\t\treturn\n\t}\n\tserverInfo.LocalID = localID\n\th.recordPeer(serverInfo)\n\n\tgo h.cleanupAtDisconnect(conn, localID)\n}\n\nfunc (h *Handshaker) nextID() int64 {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\n\th.prevID++\n\treturn h.prevID\n}\n\nfunc (h *Handshaker) cleanupAtDisconnect(conn *jsonrpc2_v2.Connection, peerID int64) {\n\tconn.Wait() // ignore error\n\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\tdelete(h.peers, peerID)\n}\n\nfunc (h *Handshaker) recordPeer(info PeerInfo) {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\tif h.peers == nil {\n\t\th.peers = make(map[int64]PeerInfo)\n\t}\n\th.peers[info.LocalID] = info\n}\n"
  },
  {
    "path": "gopls/internal/mcp/context.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\n// This file defines the \"context\" operation, which returns a summary of the\n// specified package.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/packagepath\"\n)\n\ntype ContextParams struct {\n\tFile string `json:\"file\" jsonschema:\"the absolute path to the file\"`\n}\n\nfunc (h *handler) contextHandler(ctx context.Context, req *mcp.CallToolRequest, params ContextParams) (*mcp.CallToolResult, any, error) {\n\tcountGoContextMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\t// TODO(hxjiang): support context for GoMod.\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil, fmt.Errorf(\"can't provide context for non-Go file\")\n\t}\n\n\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar result strings.Builder\n\n\tfmt.Fprintf(&result, \"Current package %q (package %s):\\n\\n\", pkg.Metadata().PkgPath, pkg.Metadata().Name)\n\t// Write context of the current file.\n\t{\n\t\tfmt.Fprintf(&result, \"%s (current file):\\n\", pgf.URI.Base())\n\t\tresult.WriteString(\"```go\\n\")\n\t\tif err := writeFileSummary(ctx, snapshot, pgf.URI, &result, false, nil); err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tresult.WriteString(\"```\\n\\n\")\n\t}\n\n\t// Write context of the rest of the files in the current package.\n\t{\n\t\tfor _, file := range pkg.CompiledGoFiles() {\n\t\t\tif file.URI == pgf.URI {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfmt.Fprintf(&result, \"%s:\\n\", file.URI.Base())\n\t\t\tresult.WriteString(\"```go\\n\")\n\t\t\tif err := writeFileSummary(ctx, snapshot, file.URI, &result, false, nil); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tresult.WriteString(\"```\\n\\n\")\n\t\t}\n\t}\n\n\t// Write dependencies context of current file.\n\tif len(pgf.File.Imports) > 0 {\n\t\t// Write import decls of the current file.\n\t\t{\n\t\t\tfmt.Fprintf(&result, \"Current file %q contains this import declaration:\\n\", pgf.URI.Base())\n\t\t\tresult.WriteString(\"```go\\n\")\n\t\t\t// Add all import decl to output including all floating comment by\n\t\t\t// using GenDecl's start and end position.\n\t\t\tfor _, decl := range pgf.File.Decls {\n\t\t\t\tgenDecl, ok := decl.(*ast.GenDecl)\n\t\t\t\tif !ok || genDecl.Tok != token.IMPORT {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\ttext, err := pgf.NodeText(genDecl)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, err\n\t\t\t\t}\n\n\t\t\t\tresult.Write(text)\n\t\t\t\tresult.WriteString(\"\\n\")\n\t\t\t}\n\t\t\tresult.WriteString(\"```\\n\\n\")\n\t\t}\n\n\t\tvar toSummarize []*ast.ImportSpec\n\t\tfor _, spec := range pgf.File.Imports {\n\t\t\t// Skip the standard library to reduce token usage, operating on\n\t\t\t// the assumption that the LLM is already familiar with its\n\t\t\t// symbols and documentation.\n\t\t\tif packagepath.IsStdPackage(spec.Path.Value) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttoSummarize = append(toSummarize, spec)\n\t\t}\n\n\t\t// Write summaries from imported packages.\n\t\tif len(toSummarize) > 0 {\n\t\t\tresult.WriteString(\"The imported packages declare the following symbols:\\n\\n\")\n\t\t\tfor _, spec := range toSummarize {\n\t\t\t\tpath := metadata.UnquoteImportPath(spec)\n\t\t\t\tid := pkg.Metadata().DepsByImpPath[path]\n\t\t\t\tif id == \"\" {\n\t\t\t\t\tcontinue // ignore error\n\t\t\t\t}\n\t\t\t\tmd := snapshot.Metadata(id)\n\t\t\t\tif md == nil {\n\t\t\t\t\tcontinue // ignore error\n\t\t\t\t}\n\t\t\t\tif summary := summarizePackage(ctx, snapshot, md); summary != \"\" {\n\t\t\t\t\tresult.WriteString(summary)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn textResult(result.String()), nil, nil\n}\n\nfunc summarizePackage(ctx context.Context, snapshot *cache.Snapshot, md *metadata.Package) string {\n\tvar buf strings.Builder\n\tfmt.Fprintf(&buf, \"%q (package %s)\\n\", md.PkgPath, md.Name)\n\tfor _, f := range md.CompiledGoFiles {\n\t\tfmt.Fprintf(&buf, \"%s:\\n\", f.Base())\n\t\tbuf.WriteString(\"```go\\n\")\n\t\tif err := writeFileSummary(ctx, snapshot, f, &buf, true, nil); err != nil {\n\t\t\treturn \"\" // ignore error\n\t\t}\n\t\tbuf.WriteString(\"```\\n\\n\")\n\t}\n\treturn buf.String()\n}\n\n// writeFileSummary writes the file summary to the string builder based on\n// the input file URI.\nfunc writeFileSummary(ctx context.Context, snapshot *cache.Snapshot, f protocol.DocumentURI, out *strings.Builder, onlyExported bool, declsToSummarize map[string]bool) error {\n\tfh, err := snapshot.ReadFile(ctx, f)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If we're summarizing specific declarations, we don't need to copy the header.\n\tif declsToSummarize == nil {\n\t\t// Copy everything before the first non-import declaration:\n\t\t// package decl, imports decl(s), and all comments (excluding copyright).\n\t\t{\n\t\t\tendPos := pgf.File.FileEnd\n\n\t\touterloop:\n\t\t\tfor _, decl := range pgf.File.Decls {\n\t\t\t\tswitch decl := decl.(type) {\n\t\t\t\tcase *ast.FuncDecl:\n\t\t\t\t\tif decl.Doc != nil {\n\t\t\t\t\t\tendPos = decl.Doc.Pos()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendPos = decl.Pos()\n\t\t\t\t\t}\n\t\t\t\t\tbreak outerloop\n\t\t\t\tcase *ast.GenDecl:\n\t\t\t\t\tif decl.Tok == token.IMPORT {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tif decl.Doc != nil {\n\t\t\t\t\t\tendPos = decl.Doc.Pos()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendPos = decl.Pos()\n\t\t\t\t\t}\n\t\t\t\t\tbreak outerloop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstartPos := pgf.File.FileStart\n\t\t\tif copyright := golang.CopyrightComment(pgf.File); copyright != nil {\n\t\t\t\tstartPos = copyright.End()\n\t\t\t}\n\n\t\t\ttext, err := pgf.PosText(startPos, endPos)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tout.Write(bytes.TrimSpace(text))\n\t\t\tout.WriteString(\"\\n\\n\")\n\t\t}\n\t}\n\n\t// Write func decl and gen decl.\n\tfor _, decl := range pgf.File.Decls {\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif declsToSummarize != nil {\n\t\t\t\tif _, ok := declsToSummarize[decl.Name.Name]; !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif onlyExported {\n\t\t\t\tif !decl.Name.IsExported() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif decl.Recv != nil && len(decl.Recv.List) > 0 {\n\t\t\t\t\t_, rname, _ := astutil.UnpackRecv(decl.Recv.List[0].Type)\n\t\t\t\t\tif !rname.IsExported() {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Write doc comment and func signature.\n\t\t\tstartPos := decl.Pos()\n\t\t\tif decl.Doc != nil {\n\t\t\t\tstartPos = decl.Doc.Pos()\n\t\t\t}\n\n\t\t\ttext, err := pgf.PosText(startPos, decl.Type.End())\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tout.Write(text)\n\t\t\tout.WriteString(\"\\n\\n\")\n\n\t\tcase *ast.GenDecl:\n\t\t\tif decl.Tok == token.IMPORT {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If we are summarizing specific decls, check if any of them are in this GenDecl.\n\t\t\tif declsToSummarize != nil {\n\t\t\t\tfound := false\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t\tif _, ok := declsToSummarize[spec.Name.Name]; ok {\n\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\t\tif _, ok := declsToSummarize[name.Name]; ok {\n\t\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !found {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Dump the entire GenDecl (exported or unexported)\n\t\t\t// including doc comment without any filtering to the output.\n\t\t\tif !onlyExported {\n\t\t\t\tstartPos := decl.Pos()\n\t\t\t\tif decl.Doc != nil {\n\t\t\t\t\tstartPos = decl.Doc.Pos()\n\t\t\t\t}\n\t\t\t\ttext, err := pgf.PosText(startPos, decl.End())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tout.Write(text)\n\t\t\t\tout.WriteString(\"\\n\")\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Write only the GenDecl with exported identifier to the output.\n\t\t\tvar buf bytes.Buffer\n\t\t\tif decl.Doc != nil {\n\t\t\t\ttext, err := pgf.NodeText(decl.Doc)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tbuf.Write(text)\n\t\t\t\tbuf.WriteString(\"\\n\")\n\t\t\t}\n\n\t\t\tbuf.WriteString(decl.Tok.String() + \" \")\n\t\t\tif decl.Lparen.IsValid() {\n\t\t\t\tbuf.WriteString(\"(\\n\")\n\t\t\t}\n\n\t\t\tvar anyExported bool\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t// Captures the full byte range of the spec, including\n\t\t\t\t// its associated doc comments and line comments.\n\t\t\t\t// This range also covers any floating comments as these\n\t\t\t\t// can be valuable for context. Like\n\t\t\t\t// ```\n\t\t\t\t// type foo struct { // floating comment.\n\t\t\t\t// \t\t// floating comment.\n\t\t\t\t//\n\t\t\t\t// \t\tx int\n\t\t\t\t// }\n\t\t\t\t// ```\n\t\t\t\tvar startPos, endPos token.Pos\n\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tif declsToSummarize != nil {\n\t\t\t\t\t\tif _, ok := declsToSummarize[spec.Name.Name]; !ok {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// TODO(hxjiang): only keep the exported field of\n\t\t\t\t\t// struct spec and exported method of interface spec.\n\t\t\t\t\tif !spec.Name.IsExported() {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tanyExported = true\n\n\t\t\t\t\t// Include preceding doc comment, if any.\n\t\t\t\t\tif spec.Doc == nil {\n\t\t\t\t\t\tstartPos = spec.Pos()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstartPos = spec.Doc.Pos()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Include trailing line comment, if any.\n\t\t\t\t\tif spec.Comment == nil {\n\t\t\t\t\t\tendPos = spec.End()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendPos = spec.Comment.End()\n\t\t\t\t\t}\n\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tif declsToSummarize != nil {\n\t\t\t\t\t\tfound := false\n\t\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\t\tif _, ok := declsToSummarize[name.Name]; ok {\n\t\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// TODO(hxjiang): only keep the exported identifier.\n\t\t\t\t\tif !slices.ContainsFunc(spec.Names, (*ast.Ident).IsExported) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tanyExported = true\n\n\t\t\t\t\tif spec.Doc == nil {\n\t\t\t\t\t\tstartPos = spec.Pos()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstartPos = spec.Doc.Pos()\n\t\t\t\t\t}\n\n\t\t\t\t\tif spec.Comment == nil {\n\t\t\t\t\t\tendPos = spec.End()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendPos = spec.Comment.End()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tindent, err := pgf.Indentation(startPos)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tbuf.WriteString(indent)\n\n\t\t\t\ttext, err := pgf.PosText(startPos, endPos)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tbuf.Write(text)\n\t\t\t\tbuf.WriteString(\"\\n\")\n\t\t\t}\n\n\t\t\tif decl.Lparen.IsValid() {\n\t\t\t\tbuf.WriteString(\")\\n\")\n\t\t\t}\n\n\t\t\t// Only write the summary of the genDecl if there is\n\t\t\t// any exported spec.\n\t\t\tif anyExported {\n\t\t\t\tout.Write(buf.Bytes())\n\t\t\t\tout.WriteString(\"\\n\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/counters.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport \"golang.org/x/telemetry/counter\"\n\n// Proposed counters for evaluating usage of Go MCP Server tools. These counters\n// increment when a user utilizes a specific Go MCP tool.\nvar (\n\tcountGoContextMCP          = counter.New(\"gopls/mcp-tool:go_context\")\n\tcountGoDiagnosticsMCP      = counter.New(\"gopls/mcp-tool:go_diagnostics\")\n\tcountGoFileContextMCP      = counter.New(\"gopls/mcp-tool:go_file_context\")\n\tcountGoFileDiagnosticsMCP  = counter.New(\"gopls/mcp-tool:go_file_diagnostics\")\n\tcountGoFileMetadataMCP     = counter.New(\"gopls/mcp-tool:go_file_metadata\")\n\tcountGoPackageAPIMCP       = counter.New(\"gopls/mcp-tool:go_package_api\")\n\tcountGoReferencesMCP       = counter.New(\"gopls/mcp-tool:go_references\")\n\tcountGoRenameSymbolMCP     = counter.New(\"gopls/mcp-tool:go_rename_symbol\")\n\tcountGoSearchMCP           = counter.New(\"gopls/mcp-tool:go_search\")\n\tcountGoSymbolReferencesMCP = counter.New(\"gopls/mcp-tool:go_symbol_references\")\n\tcountGoWorkspaceMCP        = counter.New(\"gopls/mcp-tool:go_workspace\")\n\tcountGoVulncheckMCP        = counter.New(\"gopls/mcp-tool:go_vulncheck\")\n)\n"
  },
  {
    "path": "gopls/internal/mcp/file_context.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype fileContextParams struct {\n\tFile string `json:\"file\" jsonschema:\"the absolute path to the file\"`\n}\n\nfunc (h *handler) fileContextHandler(ctx context.Context, req *mcp.CallToolRequest, params fileContextParams) (*mcp.CallToolResult, any, error) {\n\tcountGoFileContextMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tinfo := pkg.TypesInfo()\n\tif info == nil {\n\t\treturn nil, nil, fmt.Errorf(\"no types info for package %q\", pkg.Metadata().PkgPath)\n\t}\n\n\t// Group objects defined in other files by file URI.\n\totherFiles := make(map[protocol.DocumentURI]map[string]bool)\n\taddObj := func(obj types.Object) {\n\t\tif obj == nil {\n\t\t\treturn\n\t\t}\n\t\tpos := obj.Pos()\n\t\tif !pos.IsValid() {\n\t\t\treturn\n\t\t}\n\t\tobjFile := pkg.FileSet().File(pos)\n\t\tif objFile == nil {\n\t\t\treturn\n\t\t}\n\t\turi := protocol.URIFromPath(objFile.Name())\n\t\tif uri == fh.URI() {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := otherFiles[uri]; !ok {\n\t\t\totherFiles[uri] = make(map[string]bool)\n\t\t}\n\t\totherFiles[uri][obj.Name()] = true\n\t}\n\n\tfor cur := range pgf.Cursor().Preorder((*ast.Ident)(nil)) {\n\t\tid := cur.Node().(*ast.Ident)\n\t\taddObj(info.Uses[id])\n\t\taddObj(info.Defs[id])\n\t}\n\n\tvar result strings.Builder\n\tfmt.Fprintf(&result, \"File `%s` is in package %q.\\n\", params.File, pkg.Metadata().PkgPath)\n\tfmt.Fprintf(&result, \"Below is a summary of the APIs it uses from other files.\\n\")\n\tfmt.Fprintf(&result, \"To read the full API of any package, use go_package_api.\\n\")\n\tfor uri, decls := range otherFiles {\n\t\tpkgPath := \"UNKNOWN\"\n\t\tmd, err := snapshot.NarrowestMetadataForFile(ctx, uri)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, nil, ctx.Err()\n\t\t\t}\n\t\t} else {\n\t\t\tpkgPath = string(md.PkgPath)\n\t\t}\n\t\tfmt.Fprintf(&result, \"Referenced declarations from %s (package %q):\\n\", uri.Path(), pkgPath)\n\t\tresult.WriteString(\"```go\\n\")\n\t\tif err := writeFileSummary(ctx, snapshot, uri, &result, false, decls); err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tresult.WriteString(\"```\\n\\n\")\n\t}\n\n\treturn textResult(result.String()), nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/file_diagnostics.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\n// This file defines the \"diagnostics\" operation, which is responsible for\n// returning diagnostics for the input file.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/diff\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n)\n\ntype diagnosticsParams struct {\n\tFile string `json:\"file\" jsonschema:\"the absolute path to the file to diagnose\"`\n}\n\nfunc (h *handler) fileDiagnosticsHandler(ctx context.Context, req *mcp.CallToolRequest, params diagnosticsParams) (*mcp.CallToolResult, any, error) {\n\tcountGoFileDiagnosticsMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tdiagnostics, fixes, err := h.diagnoseFile(ctx, snapshot, fh.URI())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar builder strings.Builder\n\tif len(diagnostics) == 0 {\n\t\treturn textResult(\"No diagnostics\"), nil, nil\n\t}\n\n\tif err := summarizeDiagnostics(ctx, snapshot, &builder, diagnostics, fixes); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn textResult(builder.String()), nil, nil\n}\n\n// diagnoseFile diagnoses a single file, including go/analysis and quick fixes.\nfunc (h *handler) diagnoseFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) ([]*cache.Diagnostic, map[*cache.Diagnostic]*protocol.CodeAction, error) {\n\tdiagnostics, err := golang.DiagnoseFile(ctx, snapshot, uri)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif len(diagnostics) == 0 {\n\t\treturn nil, nil, nil\n\t}\n\n\t// LSP [protocol.Diagnostic]s do not carry code edits directly.\n\t// Instead, gopls provides associated [protocol.CodeAction]s with their\n\t// diagnostics field populated.\n\t// Ignore errors. It is still valuable to provide only the diagnostic\n\t// without any text edits.\n\t// TODO(hxjiang): support code actions that returns call back command.\n\tactions, _ := h.lspServer.CodeAction(ctx, &protocol.CodeActionParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: uri,\n\t\t},\n\t\tContext: protocol.CodeActionContext{\n\t\t\tOnly:        []protocol.CodeActionKind{protocol.QuickFix},\n\t\t\tDiagnostics: cache.ToProtocolDiagnostics(diagnostics...),\n\t\t},\n\t})\n\n\ttype key struct {\n\t\tMessage string\n\t\tRange   protocol.Range\n\t}\n\n\tactionMap := make(map[key]*protocol.CodeAction)\n\tfor _, action := range actions {\n\t\tfor _, d := range action.Diagnostics {\n\t\t\tk := key{d.Message, d.Range}\n\t\t\tif alt, ok := actionMap[k]; !ok || !alt.IsPreferred && action.IsPreferred {\n\t\t\t\tactionMap[k] = &action\n\t\t\t}\n\t\t}\n\t}\n\n\tfixes := make(map[*cache.Diagnostic]*protocol.CodeAction)\n\tfor _, d := range diagnostics {\n\t\tif fix, ok := actionMap[key{d.Message, d.Range}]; ok {\n\t\t\tfixes[d] = fix\n\t\t}\n\t}\n\treturn diagnostics, fixes, nil\n}\n\nfunc summarizeDiagnostics(ctx context.Context, snapshot *cache.Snapshot, w *strings.Builder, diagnostics []*cache.Diagnostic, fixes map[*cache.Diagnostic]*protocol.CodeAction) error {\n\tfor _, d := range diagnostics {\n\t\tfmt.Fprintf(w, \"%d:%d-%d:%d: [%s] %s\\n\", d.Range.Start.Line, d.Range.Start.Character, d.Range.End.Line, d.Range.End.Character, d.Severity, d.Message)\n\n\t\tfix, ok := fixes[d]\n\t\tif ok && fix.Edit != nil {\n\t\t\tw.WriteString(\"Fix:\\n\")\n\t\t\tif err := writeUnifiedDiff(ctx, snapshot, w, fix.Edit.DocumentChanges); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tw.WriteString(\"\\n\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// writeUnifiedDiff converts each [protocol.DocumentChange] into a separate\n// unified diff and write to the input writer.\n//\n// All returned diffs use forward slash ('/') as the file path separator for\n// consistency, regardless of the original system's separator.\n// Multiple changes targeting the same file are not consolidated.\n//\n// TODO(hxjiang): consolidate diffs to the same file.\nfunc writeUnifiedDiff(ctx context.Context, snapshot *cache.Snapshot, w *strings.Builder, changes []protocol.DocumentChange) error {\n\tfor _, change := range changes {\n\t\t// The before-and-after states for the file change.\n\t\tvar (\n\t\t\toldFile, newFile       string\n\t\t\toldContent, newContent string\n\t\t)\n\t\tswitch {\n\t\tcase change.CreateFile != nil:\n\t\t\toldFile, newFile = \"/dev/null\", filepath.ToSlash(change.CreateFile.URI.Path())\n\t\t\toldContent, newContent = \"\", \"\"\n\t\tcase change.DeleteFile != nil:\n\t\t\tfh, err := snapshot.ReadFile(ctx, change.DeleteFile.URI)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontent, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\toldFile, newFile = filepath.ToSlash(change.DeleteFile.URI.Path()), \"/dev/null\"\n\t\t\toldContent, newContent = string(content), \"\"\n\t\tcase change.RenameFile != nil:\n\t\t\tfh, err := snapshot.ReadFile(ctx, change.RenameFile.OldURI)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontent, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\toldFile = filepath.ToSlash(change.RenameFile.OldURI.Path())\n\t\t\tnewFile = filepath.ToSlash(change.RenameFile.NewURI.Path())\n\t\t\toldContent, newContent = string(content), string(content)\n\t\tcase change.TextDocumentEdit != nil:\n\t\t\tfh, err := snapshot.ReadFile(ctx, change.TextDocumentEdit.TextDocument.URI)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Assumes gopls never return AnnotatedTextEdit.\n\t\t\tsorted := protocol.AsTextEdits(change.TextDocumentEdit.Edits)\n\n\t\t\t// As stated by the LSP, text edits ranges must never overlap.\n\t\t\t// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray\n\t\t\tslices.SortStableFunc(sorted, func(a, b protocol.TextEdit) int {\n\t\t\t\treturn protocol.CompareRange(a.Range, b.Range)\n\t\t\t})\n\n\t\t\tcontent, err := fh.Content()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tvar newSrc bytes.Buffer\n\t\t\t{\n\t\t\t\tmapper := protocol.NewMapper(fh.URI(), content)\n\n\t\t\t\tstart := 0\n\t\t\t\tfor _, edit := range sorted {\n\t\t\t\t\tl, r, err := mapper.RangeOffsets(edit.Range)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\n\t\t\t\t\tnewSrc.Write(content[start:l])\n\t\t\t\t\tnewSrc.WriteString(edit.NewText)\n\n\t\t\t\t\tstart = r\n\t\t\t\t}\n\t\t\t\tnewSrc.Write(content[start:])\n\t\t\t}\n\n\t\t\toldFile, newFile = filepath.ToSlash(fh.URI().Path()), filepath.ToSlash(fh.URI().Path())\n\t\t\toldContent, newContent = string(content), newSrc.String()\n\t\tdefault:\n\t\t\tcontinue // this shouldn't happen\n\t\t}\n\t\tw.WriteString(diff.Unified(oldFile, newFile, oldContent, newContent))\n\t\tw.WriteString(\"\\n\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/file_metadata.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n)\n\ntype fileMetadataParams struct {\n\tFile string `json:\"file\" jsonschema:\"the absolute path to the file to describe\"`\n}\n\nfunc (h *handler) fileMetadataHandler(ctx context.Context, req *mcp.CallToolRequest, params fileMetadataParams) (*mcp.CallToolResult, any, error) {\n\tcountGoFileMetadataMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tmd, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar b strings.Builder\n\taddf := func(format string, args ...any) {\n\t\tfmt.Fprintf(&b, format, args...)\n\t}\n\taddf(\"File `%s` is in package %q, which has the following files:\\n\", params.File, md.PkgPath)\n\tfor _, f := range md.CompiledGoFiles {\n\t\taddf(\"\\t%s\\n\", f.Path())\n\t}\n\treturn textResult(b.String()), nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/instructions.md",
    "content": "# The gopls MCP server\n\nThese instructions describe how to efficiently work in the Go programming language using the gopls MCP server. You can load this file directly into a session where the gopls MCP server is connected.\n\n## Detecting a Go workspace\n\nAt the start of every session, you MUST use the `go_workspace` tool to learn about the Go workspace. ONLY if you are in a Go workspace, you MUST run `go_vulncheck` immediately afterwards to identify any existing security risks. The rest of these instructions apply whenever that tool indicates that the user is in a Go workspace.\n\n## Go programming workflows\n\nThese guidelines MUST be followed whenever working in a Go workspace. There are two workflows described below: the 'Read Workflow' must be followed when the user asks a question about a Go workspace. The 'Edit Workflow' must be followed when the user edits a Go workspace.\n\nYou may re-do parts of each workflow as necessary to recover from errors. However, you must not skip any steps.\n\n### Read workflow\n\nThe goal of the read workflow is to understand the codebase.\n\n1. **Understand the workspace layout**: Start by using `go_workspace` to understand the overall structure of the workspace, such as whether it's a module, a workspace, or a GOPATH project.\n\n2. **Find relevant symbols**: If you're looking for a specific type, function, or variable, use `go_search`. This is a fuzzy search that will help you locate symbols even if you don't know the exact name or location.\n   EXAMPLE: search for the 'Server' type: `go_search({\"query\":\"server\"})`\n\n3. **Understand a file and its intra-package dependencies**: When you have a file path and want to understand its contents and how it connects to other files *in the same package*, use `go_file_context`. This tool will show you a summary of the declarations from other files in the same package that are used by the current file. `go_file_context` MUST be used immediately after reading any Go file for the first time, and MAY be re-used if dependencies have changed.\n   EXAMPLE: to understand `server.go`'s dependencies on other files in its package: `go_file_context({\"file\":\"/path/to/server.go\"})`\n\n4. **Understand a package's public API**: When you need to understand what a package provides to external code (i.e., its public API), use `go_package_api`. This is especially useful for understanding third-party dependencies or other packages in the same monorepo.\n   EXAMPLE: to see the API of the `storage` package: `go_package_api({\"packagePaths\":[\"example.com/internal/storage\"]})`\n\n### Editing workflow\n\nThe editing workflow is iterative. You should cycle through these steps until the task is complete.\n\n1. **Read first**: Before making any edits, follow the Read Workflow to understand the user's request and the relevant code.\n\n2. **Find references**: Before modifying the definition of any symbol, use the `go_symbol_references` tool to find all references to that identifier. This is critical for understanding the impact of your change. Read the files containing references to evaluate if any further edits are required.\n   EXAMPLE: `go_symbol_references({\"file\":\"/path/to/server.go\",\"symbol\":\"Server.Run\"})`\n\n3. **Make edits**: Make the required edits, including edits to references you identified in the previous step. Don't proceed to the next step until all planned edits are complete.\n\n4. **Check for errors**: After every code modification, you MUST call the `go_diagnostics` tool. Pass the paths of the files you have edited. This tool will report any build or analysis errors.\n   EXAMPLE: `go_diagnostics({\"files\":[\"/path/to/server.go\"]})`\n\n5. **Fix errors**: If `go_diagnostics` reports any errors, fix them. The tool may provide suggested quick fixes in the form of diffs. You should review these diffs and apply them if they are correct. Once you've applied a fix, re-run `go_diagnostics` to confirm that the issue is resolved. It is OK to ignore 'hint' or 'info' diagnostics if they are not relevant to the current task. Note that Go diagnostic messages may contain a summary of the source code, which may not match its exact text.\n\n6. **Check for vulnerabilities**: If your edits involved adding or updating dependencies in the go.mod file, you MUST run a vulnerability check on the entire workspace. This ensures that the new dependencies do not introduce any security risks. This step should be performed after all build errors are resolved. EXAMPLE: `go_vulncheck({\"pattern\":\"./...\"})`\n\n7. **Run tests**: Once `go_diagnostics` reports no errors (and ONLY once there are no errors), run the tests for the packages you have changed. You can do this with `go test [packagePath...]`. Don't run `go test ./...` unless the user explicitly requests it, as doing so may slow down the iteration loop.\n\n"
  },
  {
    "path": "gopls/internal/mcp/mcp.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"sync\"\n\n\t\"github.com/google/jsonschema-go/jsonschema\"\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n)\n\n//go:embed instructions.md\nvar Instructions string\n\n// A handler implements various MCP tools for an LSP session.\ntype handler struct {\n\tsession   *cache.Session\n\tlspServer protocol.Server\n}\n\n// Sessions is the interface used to access gopls sessions.\ntype Sessions interface {\n\tSession(id string) (*cache.Session, protocol.Server)\n\tFirstSession() (*cache.Session, protocol.Server)\n\tSetSessionExitFunc(func(string))\n}\n\n// Serve starts an MCP server serving at the input address.\n//\n// The server receives LSP session events on the specified channel, which the\n// caller is responsible for closing. The server runs until the context is\n// canceled.\n//\n// The rootsHandler callback is invoked immediately after initialization and\n// subsequently whenever the MCP client signals a change to the workspace roots.\n// It is passed the list roots result returned by the MCP client, or an error\n// if the roots could not be retrieved. rootsHandler may be called concurrently.\nfunc Serve(ctx context.Context, address string, sessions Sessions, isDaemon bool, rootsHandler func(*mcp.ListRootsResult, error)) error {\n\tlog.Printf(\"Gopls MCP server: starting up on http\")\n\tlistener, err := net.Listen(\"tcp\", address)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer listener.Close()\n\n\t// TODO(hxjiang): expose the MCP server address to the LSP client.\n\tif isDaemon {\n\t\tlog.Printf(\"Gopls MCP daemon: listening on address %s...\", listener.Addr())\n\t}\n\tdefer log.Printf(\"Gopls MCP server: exiting\")\n\n\tsvr := http.Server{\n\t\tHandler: HTTPHandler(sessions, isDaemon, rootsHandler),\n\t\tBaseContext: func(net.Listener) context.Context {\n\t\t\treturn ctx\n\t\t},\n\t}\n\n\t// Run the server until cancellation.\n\tgo func() {\n\t\t<-ctx.Done()\n\t\tsvr.Close() // ignore error\n\t}()\n\tlog.Printf(\"mcp http server listening\")\n\treturn svr.Serve(listener)\n}\n\n// StartStdIO starts an MCP server over stdio.\nfunc StartStdIO(ctx context.Context, session *cache.Session, server protocol.Server, rpcLog io.Writer, rootsHandler func(*mcp.ListRootsResult, error)) error {\n\ts := NewServer(session, server, rootsHandler)\n\tif rpcLog != nil {\n\t\treturn s.Run(ctx, &mcp.LoggingTransport{\n\t\t\tTransport: &mcp.StdioTransport{},\n\t\t\tWriter:    rpcLog,\n\t\t})\n\t} else {\n\t\treturn s.Run(ctx, &mcp.StdioTransport{})\n\t}\n\n}\n\nfunc HTTPHandler(sessions Sessions, isDaemon bool, rootsHandler func(*mcp.ListRootsResult, error)) http.Handler {\n\tvar (\n\t\tmu          sync.Mutex                         // lock for mcpHandlers.\n\t\tmcpHandlers = make(map[string]*mcp.SSEHandler) // map from lsp session ids to MCP sse handlers.\n\t)\n\tmux := http.NewServeMux()\n\n\t// In daemon mode, gopls serves mcp server at ADDRESS/sessions/$SESSIONID.\n\t// Otherwise, gopls serves mcp server at ADDRESS.\n\tif isDaemon {\n\t\tmux.HandleFunc(\"/sessions/{id}\", func(w http.ResponseWriter, r *http.Request) {\n\t\t\tsessionID := r.PathValue(\"id\")\n\n\t\t\tmu.Lock()\n\t\t\thandler, ok := mcpHandlers[sessionID]\n\t\t\tif !ok {\n\t\t\t\tif s, svr := sessions.Session(sessionID); s != nil {\n\t\t\t\t\thandler = mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {\n\t\t\t\t\t\treturn NewServer(s, svr, rootsHandler)\n\t\t\t\t\t}, nil)\n\t\t\t\t\tmcpHandlers[sessionID] = handler\n\t\t\t\t}\n\t\t\t}\n\t\t\tmu.Unlock()\n\n\t\t\tif handler == nil {\n\t\t\t\thttp.Error(w, fmt.Sprintf(\"session %s not established\", sessionID), http.StatusNotFound)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\thandler.ServeHTTP(w, r)\n\t\t})\n\t} else {\n\t\t// TODO(hxjiang): should gopls serve only at a specific path?\n\t\tmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\t\tmu.Lock()\n\t\t\t// When not in daemon mode, gopls has at most one LSP session.\n\t\t\t_, handler, ok := moremaps.Arbitrary(mcpHandlers)\n\t\t\tif !ok {\n\t\t\t\ts, svr := sessions.FirstSession()\n\t\t\t\thandler = mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {\n\t\t\t\t\treturn NewServer(s, svr, rootsHandler)\n\t\t\t\t}, nil)\n\t\t\t\tmcpHandlers[s.ID()] = handler\n\t\t\t}\n\t\t\tmu.Unlock()\n\n\t\t\tif handler == nil {\n\t\t\t\thttp.Error(w, \"session not established\", http.StatusNotFound)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\thandler.ServeHTTP(w, r)\n\t\t})\n\t}\n\tsessions.SetSessionExitFunc(func(sessionID string) {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\t// TODO(rfindley): add a way to close SSE handlers (and therefore\n\t\t// close their transports). Otherwise, we leak JSON-RPC goroutines.\n\t\tdelete(mcpHandlers, sessionID)\n\t})\n\treturn mux\n}\n\nfunc NewServer(session *cache.Session, lspServer protocol.Server, rootsHandler func(*mcp.ListRootsResult, error)) *mcp.Server {\n\th := handler{\n\t\tsession:   session,\n\t\tlspServer: lspServer,\n\t}\n\topts := &mcp.ServerOptions{\n\t\tInstructions: Instructions,\n\t}\n\tmcpServer := mcp.NewServer(&mcp.Implementation{Name: \"gopls\", Version: \"v1.0.0\"}, opts)\n\n\tdefaultTools := []string{\n\t\t\"go_workspace\",\n\t\t\"go_package_api\",\n\t\t\"go_diagnostics\",\n\t\t\"go_rename_symbol\",\n\t\t\"go_symbol_references\",\n\t\t\"go_search\",\n\t\t\"go_file_context\",\n\t\t\"go_vulncheck\"}\n\tdisabledTools := append(defaultTools,\n\t\t// The fileMetadata tool is redundant with fileContext.\n\t\t[]string{\"go_file_metadata\",\n\t\t\t// The context tool returns context for all imports, which can consume a\n\t\t\t// lot of tokens. Conservatively, rely on the model selecting the imports\n\t\t\t// to summarize using the outline tool.\n\t\t\t\"go_context\",\n\t\t\t// The fileDiagnosticsTool only returns diagnostics for the current file,\n\t\t\t// but often changes will cause breakages in other tools. The\n\t\t\t// workspaceDiagnosticsTool always returns breakages, and supports running\n\t\t\t// deeper diagnostics in selected files.\n\t\t\t\"go_file_diagnostics\",\n\t\t\t// The references tool requires a location, which models tend to get wrong.\n\t\t\t// The symbolic variant seems to be easier to get right, albeit less\n\t\t\t// powerful.\n\t\t\t\"go_references\",\n\t\t}...)\n\tvar toolConfig map[string]bool // non-default settings\n\t// For testing, poke through to the gopls server to access its options,\n\t// and enable some of the disabled tools.\n\tif hasOpts, ok := lspServer.(interface{ Options() *settings.Options }); ok {\n\t\ttoolConfig = hasOpts.Options().MCPTools\n\t}\n\tvar tools []string\n\tfor _, tool := range defaultTools {\n\t\tif enabled, ok := toolConfig[tool]; !ok || enabled {\n\t\t\ttools = append(tools, tool)\n\t\t}\n\t}\n\t// Disabled tools must be explicitly enabled.\n\tfor _, tool := range disabledTools {\n\t\tif toolConfig[tool] {\n\t\t\ttools = append(tools, tool)\n\t\t}\n\t}\n\tfor _, tool := range tools {\n\t\taddToolByName(mcpServer, h, tool)\n\t}\n\n\t// Subscribe to the roots change.\n\tif rootsHandler != nil {\n\t\tmcpServer.AddReceivingMiddleware(func(next mcp.MethodHandler) mcp.MethodHandler {\n\t\t\treturn func(ctx context.Context, method string, req mcp.Request) (mcp.Result, error) {\n\t\t\t\tresult, err := next(ctx, method, req)\n\n\t\t\t\t// Read roots list after initialized once and every time roots\n\t\t\t\t// list changes and pass them to handler.\n\t\t\t\t//\n\t\t\t\t// See MCP spec:\n\t\t\t\t//\n\t\t\t\t//  The server SHOULD NOT send requests other than pings\n\t\t\t\t//  and logging before receiving the initialized notification.\n\t\t\t\t//\n\t\t\t\t// https://modelcontextprotocol.info/specification/2024-11-05/basic/lifecycle/#initialization\n\t\t\t\tif method == \"notifications/initialized\" || method == \"notifications/roots/list_changed\" {\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tvar session *mcp.ServerSession\n\t\t\t\t\t\tfor s := range mcpServer.Sessions() {\n\t\t\t\t\t\t\tif s.ID() == req.GetSession().ID() {\n\t\t\t\t\t\t\t\tsession = s\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif session == nil { // session terminated.\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif session.InitializeParams().Capabilities.RootsV2 == nil {\n\t\t\t\t\t\t\treturn // client does not support roots\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\troots, err := session.ListRoots(context.Background(), &mcp.ListRootsParams{})\n\t\t\t\t\t\trootsHandler(roots, err)\n\t\t\t\t\t}()\n\t\t\t\t}\n\n\t\t\t\treturn result, err\n\t\t\t}\n\t\t})\n\t}\n\n\treturn mcpServer\n}\n\nfunc addToolByName(mcpServer *mcp.Server, h handler, name string) {\n\tswitch name {\n\tcase \"go_context\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_context\",\n\t\t\tDescription: \"Provide context for a region within a Go file\",\n\t\t}, h.contextHandler)\n\tcase \"go_diagnostics\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName: \"go_diagnostics\",\n\t\t\tDescription: `Provides Go workspace diagnostics.\n\nChecks for parse and build errors across the entire Go workspace. If provided,\n\"files\" holds absolute paths for active files, on which additional linting is\nperformed.\n`,\n\t\t}, h.workspaceDiagnosticsHandler)\n\tcase \"go_file_context\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_file_context\",\n\t\t\tDescription: \"Summarizes a file's cross-file dependencies\",\n\t\t}, h.fileContextHandler)\n\tcase \"go_file_diagnostics\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_file_diagnostics\",\n\t\t\tDescription: \"Provides diagnostics for a Go file\",\n\t\t}, h.fileDiagnosticsHandler)\n\tcase \"go_file_metadata\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_file_metadata\",\n\t\t\tDescription: \"Provides metadata about the Go package containing the file\",\n\t\t}, h.fileMetadataHandler)\n\tcase \"go_package_api\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_package_api\",\n\t\t\tDescription: \"Provides a summary of a Go package API\",\n\t\t}, h.outlineHandler)\n\tcase \"go_references\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_references\",\n\t\t\tDescription: \"Provide the locations of references to a given object\",\n\t\t}, h.referencesHandler)\n\tcase \"go_rename_symbol\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName: \"go_rename_symbol\",\n\t\t\tDescription: `Renames a symbol in the Go workspace\n\nFor example, given arguments {\"file\": \"/path/to/foo.go\", \"symbol\": \"Foo\", \"new_name\": \"Bar\"},\ngo_rename_symbol returns the edits necessary to rename the symbol \"Foo\" (located in the file foo.go) to\n\"Bar\" across the Go workspace.`,\n\t\t}, h.renameSymbolHandler)\n\tcase \"go_search\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName: \"go_search\",\n\t\t\tDescription: `Search for symbols in the Go workspace.\n\nSearch for symbols using case-insensitive fuzzy search, which may match all or\npart of the fully qualified symbol name. For example, the query 'foo' matches\nGo symbols 'Foo', 'fooBar', 'futils.Oboe', 'github.com/foo/bar.Baz'.\n\nResults are limited to 100 symbols.\n`,\n\t\t}, h.searchHandler)\n\tcase \"go_symbol_references\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName: \"go_symbol_references\",\n\t\t\tDescription: `Provides the locations of references to a (possibly qualified)\npackage-level Go symbol referenced from the current file.\n\nFor example, given arguments {\"file\": \"/path/to/foo.go\", \"name\": \"Foo\"},\ngo_symbol_references returns references to the symbol \"Foo\" declared\nin the current package.\n\nSimilarly, given arguments {\"file\": \"/path/to/foo.go\", \"name\": \"lib.Bar\"},\ngo_symbol_references returns references to the symbol \"Bar\" in the imported lib\npackage.\n\nFinally, symbol references supporting querying fields and methods: symbol\n\"T.M\" selects the \"M\" field or method of the \"T\" type (or value), and \"lib.T.M\"\ndoes the same for a symbol in the imported package \"lib\".\n`,\n\t\t}, h.symbolReferencesHandler)\n\tcase \"go_workspace\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName:        \"go_workspace\",\n\t\t\tDescription: \"Summarize the Go programming language workspace\",\n\t\t\tInputSchema: &jsonschema.Schema{\n\t\t\t\tType:       \"object\",\n\t\t\t\tProperties: map[string]*jsonschema.Schema{},\n\t\t\t},\n\t\t}, h.workspaceHandler)\n\tcase \"go_vulncheck\":\n\t\tmcp.AddTool(mcpServer, &mcp.Tool{\n\t\t\tName: \"go_vulncheck\",\n\t\t\tDescription: `Runs a vulnerability check on the Go workspace.\n\n\tThe check is performed on a given package pattern within a specified directory.\n\tIf no directory is provided, it defaults to the workspace root.\n\tIf no pattern is provided, it defaults to \"./...\".`,\n\t\t}, h.vulncheckHandler)\n\t}\n}\n\n// snapshot returns the best default snapshot to use for workspace queries.\nfunc (h *handler) snapshot() (*cache.Snapshot, func(), error) {\n\tviews := h.session.Views()\n\tif len(views) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"No active builds.\")\n\t}\n\treturn views[0].Snapshot()\n}\n\n// fileOf is like [cache.Session.FileOf], but does a sanity check for file\n// changes. Currently, it checks for modified files in the transitive closure\n// of the file's narrowest package.\n//\n// This helps avoid stale packages, but is not a substitute for real file\n// watching, as it misses things like files being added to a package.\nfunc (h *handler) fileOf(ctx context.Context, file string) (file.Handle, *cache.Snapshot, func(), error) {\n\turi := protocol.URIFromPath(file)\n\tfh, snapshot, release, err := h.session.FileOf(ctx, uri)\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\tmd, err := snapshot.NarrowestMetadataForFile(ctx, uri)\n\tif err != nil {\n\t\trelease()\n\t\treturn nil, nil, nil, err\n\t}\n\tfileEvents, err := checkForFileChanges(ctx, snapshot, md.ID)\n\tif err != nil {\n\t\trelease()\n\t\treturn nil, nil, nil, err\n\t}\n\tif len(fileEvents) == 0 {\n\t\treturn fh, snapshot, release, nil\n\t}\n\trelease() // snapshot is not latest\n\n\t// We detect changed files: process them before getting the snapshot.\n\tif err := h.lspServer.DidChangeWatchedFiles(ctx, &protocol.DidChangeWatchedFilesParams{\n\t\tChanges: fileEvents,\n\t}); err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\treturn h.session.FileOf(ctx, uri)\n}\n\n// checkForFileChanges checks for file changes in the transitive closure of\n// the given package, by checking file modification time. Since it does not\n// actually read file contents, it may miss changes that occur within the mtime\n// resolution of the current file system (on some operating systems, this may\n// be as much as a second).\n//\n// It also doesn't catch package changes that occur due to added files or\n// changes to the go.mod file.\nfunc checkForFileChanges(ctx context.Context, snapshot *cache.Snapshot, id metadata.PackageID) ([]protocol.FileEvent, error) {\n\tvar events []protocol.FileEvent\n\n\tseen := make(map[metadata.PackageID]struct{})\n\tvar checkPkg func(id metadata.PackageID) error\n\tcheckPkg = func(id metadata.PackageID) error {\n\t\tif _, ok := seen[id]; ok {\n\t\t\treturn nil\n\t\t}\n\t\tseen[id] = struct{}{}\n\n\t\tmp := snapshot.Metadata(id)\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err // context cancelled\n\t\t\t}\n\n\t\t\tmtime, mtimeErr := fh.ModTime()\n\t\t\tfi, err := os.Stat(uri.Path())\n\t\t\tswitch {\n\t\t\tcase err != nil:\n\t\t\t\tif mtimeErr == nil {\n\t\t\t\t\t// file existed, and doesn't anymore, so the file was deleted\n\t\t\t\t\tevents = append(events, protocol.FileEvent{URI: uri, Type: protocol.Deleted})\n\t\t\t\t}\n\t\t\tcase mtimeErr != nil:\n\t\t\t\t// err == nil (from above), so the file was created\n\t\t\t\tevents = append(events, protocol.FileEvent{URI: uri, Type: protocol.Created})\n\t\t\tcase !mtime.IsZero() && fi.ModTime().After(mtime):\n\t\t\t\tevents = append(events, protocol.FileEvent{URI: uri, Type: protocol.Changed})\n\t\t\t}\n\t\t}\n\t\tfor _, depID := range mp.DepsByPkgPath {\n\t\t\tif err := checkPkg(depID); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn events, checkPkg(id)\n}\n\nfunc textResult(text string) *mcp.CallToolResult {\n\treturn &mcp.CallToolResult{\n\t\tContent: []mcp.Content{&mcp.TextContent{Text: text}},\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/mcp/mcp_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\tinternalmcp \"golang.org/x/tools/gopls/internal/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype emptySessions struct {\n}\n\n// FirstSession implements mcp.Sessions.\nfunc (e emptySessions) FirstSession() (*cache.Session, protocol.Server) {\n\treturn nil, nil\n}\n\n// Session implements mcp.Sessions.\nfunc (e emptySessions) Session(string) (*cache.Session, protocol.Server) {\n\treturn nil, nil\n}\n\n// SetSessionExitFunc implements mcp.Sessions.\nfunc (e emptySessions) SetSessionExitFunc(func(string)) {\n}\n\nfunc TestContextCancellation(t *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background())\n\n\tres := make(chan error)\n\tgo func() {\n\t\tres <- internalmcp.Serve(ctx, \"localhost:0\", emptySessions{}, true, nil)\n\t}()\n\n\ttime.Sleep(1 * time.Second)\n\tcancel()\n\n\tselect {\n\tcase err := <-res:\n\t\tif !errors.Is(err, http.ErrServerClosed) {\n\t\t\tt.Errorf(\"mcp server unexpected return got %v, want: %v\", err, http.ErrServerClosed)\n\t\t}\n\tcase <-time.After(5 * time.Second):\n\t\tt.Errorf(\"mcp server did not terminate after 5 seconds of context cancellation\")\n\t}\n}\n\nfunc TestClientRootChange(t *testing.T) {\n\tfoundError := make(chan error, 1)\n\tfoundAll := []chan struct{}{\n\t\tmake(chan struct{}), // after initialized\n\t\tmake(chan struct{}), // after roots/list_changed\n\t}\n\n\twantRoots := []map[string]struct{}{\n\t\t{ // after initialized\n\t\t\t\"file:///path/to/one\": struct{}{},\n\t\t\t\"file:///path/to/two\": struct{}{},\n\t\t},\n\t\t{ // after roots/list_changed\n\t\t\t\"file:///path/to/one\":   struct{}{},\n\t\t\t\"file:///path/to/two\":   struct{}{},\n\t\t\t\"file:///path/to/three\": struct{}{},\n\t\t\t\"file:///path/to/four\":  struct{}{},\n\t\t},\n\t}\n\n\tvar callCount int\n\n\tserver := internalmcp.NewServer(nil, nil, func(res *mcp.ListRootsResult, err error) {\n\t\tif err != nil {\n\t\t\tfoundError <- err\n\t\t\treturn\n\t\t}\n\n\t\tif callCount >= len(wantRoots) {\n\t\t\tt.Errorf(\"Handler called more times than expected: %d\", callCount)\n\t\t\treturn\n\t\t}\n\n\t\texpected := wantRoots[callCount]\n\n\t\tif len(res.Roots) != len(expected) {\n\t\t\tt.Errorf(\"Phase %d: expected %d roots, got %d\", callCount+1, len(expected), len(res.Roots))\n\t\t\treturn\n\t\t}\n\n\t\tfor _, r := range res.Roots {\n\t\t\tif _, ok := expected[r.URI]; !ok {\n\t\t\t\tt.Errorf(\"Phase %d: unexpected root %s\", callCount+1, r)\n\t\t\t}\n\t\t}\n\n\t\tcallCount++\n\t\tclose(foundAll[callCount-1]) // Signal that this phase is complete\n\t})\n\n\tclient := mcp.NewClient(&mcp.Implementation{Name: \"test-client\"}, nil)\n\tclient.AddRoots(&mcp.Root{\n\t\tName: \"one\",\n\t\tURI:  \"file:///path/to/one\",\n\t}, &mcp.Root{\n\t\tName: \"two\",\n\t\tURI:  \"file:///path/to/two\",\n\t})\n\n\tclientTransport, serverTransport := mcp.NewInMemoryTransports()\n\n\tctx := t.Context()\n\n\t// Connect server and client\n\tserverSession, _ := server.Connect(ctx, serverTransport, nil)\n\tdefer serverSession.Close()\n\n\tclientSession, _ := client.Connect(ctx, clientTransport, nil)\n\tdefer clientSession.Close()\n\n\t// Phase 1: Wait for the initial handshake and first root fetch\n\tselect {\n\tcase <-foundAll[0]:\n\t\tt.Log(\"Phase 1: Initial roots received successfully.\")\n\tcase err := <-foundError:\n\t\tt.Fatalf(\"Server handler error during initialization: %v\", err)\n\tcase <-time.After(20 * time.Second):\n\t\tt.Fatal(\"Timeout waiting for initial roots.\")\n\t}\n\n\t// Trigger the root change\n\tclient.AddRoots(&mcp.Root{\n\t\tName: \"three\",\n\t\tURI:  \"file:///path/to/three\",\n\t}, &mcp.Root{\n\t\tName: \"four\",\n\t\tURI:  \"file:///path/to/four\",\n\t})\n\n\t// Phase 2: Wait for the server to catch the notification and fetch the updated roots\n\tselect {\n\tcase <-foundAll[1]:\n\t\tt.Log(\"Phase 2: Updated roots received successfully.\")\n\tcase err := <-foundError:\n\t\tt.Fatalf(\"Server handler error after root change: %v\", err)\n\tcase <-time.After(20 * time.Second):\n\t\tt.Fatal(\"Timeout waiting for updated roots.\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/mcp/outline.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n)\n\ntype outlineParams struct {\n\tPackagePaths []string `json:\"packagePaths\" jsonschema:\"the go package paths to describe\"`\n}\n\nfunc (h *handler) outlineHandler(ctx context.Context, req *mcp.CallToolRequest, params outlineParams) (*mcp.CallToolResult, any, error) {\n\tcountGoPackageAPIMCP.Inc()\n\tsnapshot, release, err := h.snapshot()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\t// Await initialization to ensure we've at least got an initial package graph\n\tmd, err := snapshot.LoadMetadataGraph(ctx)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tvar toSummarize []*metadata.Package\n\tfor _, imp := range params.PackagePaths {\n\t\tpkgPath := metadata.PackagePath(imp)\n\t\tif len(imp) > 0 && imp[0] == '\"' {\n\t\t\tunquoted, err := strconv.Unquote(imp)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to unquote %s: %v\", imp, err)\n\t\t\t}\n\t\t\tpkgPath = metadata.PackagePath(unquoted)\n\t\t}\n\t\tif mps := md.ForPackagePath[pkgPath]; len(mps) > 0 {\n\t\t\ttoSummarize = append(toSummarize, mps[0]) // first is best\n\t\t}\n\t}\n\n\tvar content []mcp.Content\n\tfor _, mp := range toSummarize {\n\t\tif md == nil {\n\t\t\tcontinue // ignore error\n\t\t}\n\t\tif summary := summarizePackage(ctx, snapshot, mp); summary != \"\" {\n\t\t\tcontent = append(content, &mcp.TextContent{Text: summary})\n\t\t}\n\t}\n\treturn &mcp.CallToolResult{\n\t\tContent: content,\n\t}, nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/references.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype findReferencesParams struct {\n\tLocation protocol.Location `json:\"location\"`\n}\n\nfunc (h *handler) referencesHandler(ctx context.Context, req *mcp.CallToolRequest, params findReferencesParams) (*mcp.CallToolResult, any, error) {\n\tcountGoReferencesMCP.Inc()\n\tfh, snapshot, release, err := h.session.FileOf(ctx, params.Location.URI)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\tpos := params.Location.Range.Start\n\trefs, err := golang.References(ctx, snapshot, fh, protocol.Range{Start: pos, End: pos}, true)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tformatted, err := formatReferences(ctx, snapshot, refs)\n\treturn formatted, nil, err\n}\n\nfunc formatReferences(ctx context.Context, snapshot *cache.Snapshot, refs []protocol.Location) (*mcp.CallToolResult, error) {\n\tif len(refs) == 0 {\n\t\treturn nil, fmt.Errorf(\"no references found\")\n\t}\n\tvar builder strings.Builder\n\tfmt.Fprintf(&builder, \"The object has %v references. Their locations are listed below\\n\", len(refs))\n\tfor i, r := range refs {\n\t\tfmt.Fprintf(&builder, \"Reference %d\\n\", i+1)\n\t\tfmt.Fprintf(&builder, \"Located in the file: %s\\n\", filepath.ToSlash(r.URI.Path()))\n\t\trefFh, err := snapshot.ReadFile(ctx, r.URI)\n\t\t// If for some reason there is an error reading the file content, we should still\n\t\t// return the references URIs.\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tcontent, err := refFh.Content()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tlines := strings.Split(string(content), \"\\n\")\n\t\tvar lineContent string\n\t\tif int(r.Range.Start.Line) < len(lines) {\n\t\t\tlineContent = strings.TrimLeftFunc(lines[r.Range.Start.Line], unicode.IsSpace)\n\t\t} else {\n\t\t\tcontinue\n\t\t}\n\t\tfmt.Fprintf(&builder, \"The reference is located on line %v, which has content `%s`\\n\", r.Range.Start.Line, lineContent)\n\t\tbuilder.WriteString(\"\\n\")\n\t}\n\treturn textResult(builder.String()), nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/rename_symbol.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype renameSymbolParams struct {\n\tFile    string `json:\"file\" jsonschema:\"the absolute path to the file containing the symbol\"`\n\tSymbol  string `json:\"symbol\" jsonschema:\"the symbol or qualified symbol\"`\n\tNewName string `json:\"new_name\" jsonschema:\"the new name for the symbol\"`\n}\n\nfunc (h *handler) renameSymbolHandler(ctx context.Context, req *mcp.CallToolRequest, params renameSymbolParams) (*mcp.CallToolResult, any, error) {\n\tcountGoRenameSymbolMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil, fmt.Errorf(\"can't rename symbols in non-Go files\")\n\t}\n\tloc, err := symbolLocation(ctx, snapshot, fh.URI(), params.Symbol)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tchanges, err := golang.Rename(ctx, snapshot, fh, loc.Range, params.NewName)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tvar builder strings.Builder\n\tif err := formatRenameChanges(ctx, snapshot, &builder, changes); err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn textResult(builder.String()), nil, nil\n}\n\n// formatRenameChanges converts the list of DocumentChange to a unified diff and writes them to the specified buffer.\nfunc formatRenameChanges(ctx context.Context, snapshot *cache.Snapshot, w *strings.Builder, changes []protocol.DocumentChange) error {\n\tw.WriteString(\"The following changes are necessary to rename the symbol:\\n\")\n\tif err := writeUnifiedDiff(ctx, snapshot, w, changes); err != nil {\n\t\treturn err\n\t}\n\tw.WriteString(\"\\n\")\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/search.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype searchParams struct {\n\tQuery string `json:\"query\" jsonschema:\"the fuzzy search query to use for matching symbols\"`\n}\n\nfunc (h *handler) searchHandler(ctx context.Context, req *mcp.CallToolRequest, params searchParams) (*mcp.CallToolResult, any, error) {\n\tcountGoSearchMCP.Inc()\n\tquery := params.Query\n\tif len(query) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"empty query\")\n\t}\n\tsyms, err := h.lspServer.Symbol(ctx, &protocol.WorkspaceSymbolParams{\n\t\tQuery: params.Query,\n\t})\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to execute symbol query: %v\", err)\n\t}\n\tif len(syms) == 0 {\n\t\treturn textResult(\"No symbols found.\"), nil, nil\n\t}\n\tvar b strings.Builder\n\tfmt.Fprintf(&b, \"Top symbol matches:\\n\")\n\tfor _, sym := range syms {\n\t\tfmt.Fprintf(&b, \"\\t%s (%s in `%s`)\\n\", sym.Name, kindName(sym.Kind), sym.Location.URI.Path())\n\t}\n\treturn textResult(b.String()), nil, nil\n}\n\n// kindName returns the adjusted name for the given symbol kind,\n// fixing LSP conventions that don't work for go, like 'Class'.\nfunc kindName(k protocol.SymbolKind) string {\n\tif k == protocol.Class {\n\t\treturn \"Type\"\n\t}\n\treturn fmt.Sprint(k)\n}\n"
  },
  {
    "path": "gopls/internal/mcp/symbol_references.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// symbolReferencesParams defines the parameters for the \"go_symbol_references\"\n// tool.\ntype symbolReferencesParams struct {\n\tFile   string `json:\"file\" jsonschema:\"the absolute path to the file containing the symbol\"`\n\tSymbol string `json:\"symbol\" jsonschema:\"the symbol or qualified symbol\"`\n}\n\n// symbolReferencesHandler is the handler for the \"go_symbol_references\" tool.\n// It finds all references to the requested symbol and describes their\n// locations.\nfunc (h *handler) symbolReferencesHandler(ctx context.Context, req *mcp.CallToolRequest, params symbolReferencesParams) (*mcp.CallToolResult, any, error) {\n\tcountGoSymbolReferencesMCP.Inc()\n\tfh, snapshot, release, err := h.fileOf(ctx, params.File)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil, fmt.Errorf(\"can't provide references for non-Go files\")\n\t}\n\n\tloc, err := symbolLocation(ctx, snapshot, fh.URI(), params.Symbol)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdeclFH, err := snapshot.ReadFile(ctx, loc.URI)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\trefs, err := golang.References(ctx, snapshot, declFH, loc.Range, true)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tformatted, err := formatReferences(ctx, snapshot, refs)\n\treturn formatted, nil, err\n}\n\n// symbolLocation returns the protocol.Location of the given symbol within the file uri, or an error if it cannot be located.\nfunc symbolLocation(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, symbol string) (protocol.Location, error) {\n\t// Parse and extract names before type checking, to fail fast in the case of\n\t// invalid inputs.\n\te, err := parser.ParseExpr(symbol)\n\tif err != nil {\n\t\treturn protocol.Location{}, fmt.Errorf(\"\\\"symbol\\\" failed to parse: %v\", err)\n\t}\n\tpath, err := extractPath(e)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\n\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, uri)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\n\ttarget, err := resolveSymbol(path, pkg, pgf)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\n\tloc, err := golang.ObjectLocation(ctx, pkg.FileSet(), snapshot, target)\n\tif err != nil {\n\t\treturn protocol.Location{}, fmt.Errorf(\"finding symbol location: %v\", err)\n\t}\n\treturn loc, nil\n}\n\n// extractPath extracts the 'path' of names from e, which must be of the form\n// a, a.b, or a.b.c.\n//\n// If a nil error is returned, the resulting path is either length 1, 2, or 3.\nfunc extractPath(e ast.Expr) ([]string, error) {\n\tswitch e := e.(type) {\n\tcase *ast.Ident:\n\t\treturn []string{e.Name}, nil\n\tcase *ast.SelectorExpr:\n\t\tswitch x := e.X.(type) {\n\t\tcase *ast.Ident:\n\t\t\t// Qualified identifier 'a.b', where a is a package or receiver.\n\t\t\treturn []string{x.Name, e.Sel.Name}, nil\n\t\tcase *ast.SelectorExpr:\n\t\t\t// Imported field or method a.b.c: a must be a package name.\n\t\t\tif x2, ok := x.X.(*ast.Ident); ok {\n\t\t\t\treturn []string{x2.Name, x.Sel.Name, e.Sel.Name}, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"invalid qualified symbol: expected a.b or a.b.c\")\n}\n\n// resolveSymbol resolves the types.Object for the given qualified path, which\n// must be of length 1, 2, or 3:\n//   - For length 1 paths, the symbol is a name in the file scope.\n//   - For length 2 paths, the symbol is either field, method, or imported symbol.\n//   - For length 3 paths, the symbol is a field or method on an important object.\nfunc resolveSymbol(path []string, pkg *cache.Package, pgf *parsego.File) (types.Object, error) {\n\tfileScope, ok := pkg.TypesInfo().Scopes[pgf.File]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"internal error: no scope for file\")\n\t}\n\n\tswitch len(path) {\n\tcase 1:\n\t\t_, target := fileScope.LookupParent(path[0], token.NoPos)\n\t\tif target == nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to resolve name %q\", path[0])\n\t\t}\n\t\treturn target, nil\n\tcase 2:\n\t\tswitch _, obj := fileScope.LookupParent(path[0], token.NoPos); obj := obj.(type) {\n\t\tcase *types.PkgName:\n\t\t\ttarget := obj.Imported().Scope().Lookup(path[1])\n\t\t\tif target == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to resolve member %q of %q\", path[1], path[0])\n\t\t\t}\n\t\t\treturn target, nil\n\t\tcase nil:\n\t\t\treturn nil, fmt.Errorf(\"failed to resolve name %q\", path[0])\n\t\tdefault:\n\t\t\ttarget, _, _ := types.LookupFieldOrMethod(obj.Type(), true, pkg.Types(), path[1])\n\t\t\tif target == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to resolve member %q of %q\", path[1], path[0])\n\t\t\t}\n\t\t\treturn target, nil\n\t\t}\n\tcase 3:\n\t\t// Imported field or method a.b.c: a must be a package name.\n\t\tobj := fileScope.Lookup(path[0])\n\t\tp, ok := obj.(*types.PkgName)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid qualified symbol: %q must be a package (got %T)\", path[0], obj)\n\t\t}\n\t\trecv := p.Imported().Scope().Lookup(path[1])\n\t\tif recv == nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid qualified symbol: could not find %q in package %q\", path[1], path[0])\n\t\t}\n\t\ttarget, _, _ := types.LookupFieldOrMethod(recv.Type(), true, pkg.Types(), path[2])\n\t\tif target == nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to resolve member %q of %q\", path[2], path[1])\n\t\t}\n\t\treturn target, nil\n\t}\n\tpanic(\"unreachable\")\n}\n"
  },
  {
    "path": "gopls/internal/mcp/vulncheck.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"maps\"\n\t\"slices\"\n\t\"sort\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/scan\"\n)\n\ntype vulncheckParams struct {\n\tDir     string `json:\"dir,omitempty\" jsonschema:\"directory to run the vulnerability check within\"`\n\tPattern string `json:\"pattern,omitempty\" jsonschema:\"package pattern to check\"`\n}\n\ntype GroupedVulnFinding struct {\n\tID               string   `json:\"id\"`\n\tDetails          string   `json:\"details\"`\n\tAffectedPackages []string `json:\"affectedPackages\"`\n}\n\ntype VulncheckResultOutput struct {\n\tFindings []GroupedVulnFinding `json:\"findings,omitempty\"`\n\tLogs     string               `json:\"logs,omitempty\"`\n}\n\nfunc (h *handler) vulncheckHandler(ctx context.Context, req *mcp.CallToolRequest, params *vulncheckParams) (*mcp.CallToolResult, *VulncheckResultOutput, error) {\n\tcountGoVulncheckMCP.Inc()\n\tsnapshot, release, err := h.snapshot()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer release()\n\n\tdir := params.Dir\n\tif dir == \"\" && len(h.session.Views()) > 0 {\n\t\tdir = h.session.Views()[0].Root().Path()\n\t}\n\n\tpattern := params.Pattern\n\tif pattern == \"\" {\n\t\tpattern = \"./...\"\n\t}\n\n\tvar logBuf bytes.Buffer\n\tresult, err := scan.RunGovulncheck(ctx, pattern, snapshot, dir, &logBuf)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"running govulncheck failed: %v\\nLogs:\\n%s\", err, logBuf.String())\n\t}\n\n\tgroupedPkgs := make(map[string]map[string]struct{})\n\tfor _, finding := range result.Findings {\n\t\tif osv := result.Entries[finding.OSV]; osv != nil {\n\t\t\tif _, ok := groupedPkgs[osv.ID]; !ok {\n\t\t\t\tgroupedPkgs[osv.ID] = make(map[string]struct{})\n\t\t\t}\n\t\t\tpkg := finding.Trace[0].Package\n\t\t\tif pkg == \"\" {\n\t\t\t\tpkg = \"Go standard library\"\n\t\t\t}\n\t\t\tgroupedPkgs[osv.ID][pkg] = struct{}{}\n\t\t}\n\t}\n\n\tvar output VulncheckResultOutput\n\tif len(groupedPkgs) > 0 {\n\t\toutput.Findings = make([]GroupedVulnFinding, 0, len(groupedPkgs))\n\t\tfor id, pkgsSet := range groupedPkgs {\n\t\t\tpkgs := slices.Sorted(maps.Keys(pkgsSet))\n\n\t\t\toutput.Findings = append(output.Findings, GroupedVulnFinding{\n\t\t\t\tID:               id,\n\t\t\t\tDetails:          result.Entries[id].Details,\n\t\t\t\tAffectedPackages: pkgs,\n\t\t\t})\n\t\t}\n\t\tsort.Slice(output.Findings, func(i, j int) bool {\n\t\t\treturn output.Findings[i].ID < output.Findings[j].ID\n\t\t})\n\t}\n\n\tif logBuf.Len() > 0 {\n\t\toutput.Logs = logBuf.String()\n\t}\n\n\tvar summary bytes.Buffer\n\tfmt.Fprintf(&summary, \"Vulnerability check for pattern %q complete. Found %d vulnerabilities.\", pattern, len(output.Findings))\n\tif output.Logs != \"\" {\n\t\tfmt.Fprintf(&summary, \"\\nLogs are available in the structured output.\")\n\t}\n\n\treturn nil, &output, nil\n}\n"
  },
  {
    "path": "gopls/internal/mcp/workspace.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\n\t\"slices\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/immutable\"\n)\n\nfunc (h *handler) workspaceHandler(ctx context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) {\n\tcountGoWorkspaceMCP.Inc()\n\tvar summary bytes.Buffer\n\tviews := h.session.Views()\n\tfor _, v := range views {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // view is shut down\n\t\t}\n\t\tdefer release()\n\n\t\tpkgs := snapshot.WorkspacePackages()\n\n\t\t// Special case: check if it's likely that this isn't actually a Go workspace.\n\t\tif len(views) == 1 && // only view\n\t\t\t(v.Type() == cache.AdHocView || v.Type() == cache.GoPackagesDriverView) && // not necessarily Go code\n\t\t\tpkgs.Len() == 0 { // no packages\n\n\t\t\treturn &mcp.CallToolResult{\n\t\t\t\tContent: []mcp.Content{&mcp.TextContent{Text: \"This is not a Go workspace. To work on Go code, open a directory inside a Go module.\"}},\n\t\t\t}, nil, nil\n\t\t}\n\n\t\tdir := v.Root().Path()\n\t\tswitch v.Type() {\n\t\tcase cache.GoPackagesDriverView:\n\t\t\tfmt.Fprintf(&summary, \"The `%s` directory is loaded using a custom golang.org/x/tools/go/packages driver.\\n\", dir)\n\t\t\tfmt.Fprintf(&summary, \"This indicates a non-standard build system.\\n\")\n\n\t\tcase cache.GOPATHView:\n\t\t\tfmt.Fprintf(&summary, \"The `%s` directory is loaded using a the legacy GOPATH build system.\\n\", dir)\n\n\t\tcase cache.GoModView:\n\t\t\tfmt.Fprintf(&summary, \"The `%s` directory uses Go modules, with the following main modules:\\n\", dir)\n\t\t\tsummarizeModFiles(ctx, &summary, snapshot)\n\n\t\tcase cache.GoWorkView:\n\t\t\tfmt.Fprintf(&summary, \"The `%s` directory is in the go workspace defined by `%s`, with the following main modules:\\n\", dir, v.GoWork().Path())\n\t\t\tsummarizeModFiles(ctx, &summary, snapshot)\n\n\t\tcase cache.AdHocView:\n\t\t\tfmt.Fprintf(&summary, \"The `%s` directory is an ad-hoc Go package, not in a Go module.\\n\", dir)\n\t\t}\n\t\tfmt.Fprintln(&summary)\n\t\tconst summarizePackages = false\n\t\tif summarizePackages {\n\t\t\tsummaries := packageSummaries(snapshot, pkgs)\n\t\t\tfmt.Fprintf(&summary, \"It contains the following Go packages:\\n\")\n\t\t\tfmt.Fprintf(&summary, \"\\t%s\\n\", strings.Join(summaries, \"\\n\\t\"))\n\t\t\tfmt.Fprintln(&summary)\n\t\t}\n\t}\n\treturn textResult(summary.String()), nil, nil\n}\n\nfunc summarizeModFiles(ctx context.Context, w io.Writer, snapshot *cache.Snapshot) {\n\tv := snapshot.View()\n\tfor _, m := range v.ModFiles() {\n\t\tif modPath, err := modulePath(ctx, snapshot, m); err != nil {\n\t\t\t// Fall back on just the go.mod file.\n\t\t\tfmt.Fprintf(w, \"\\t%s\\n\", m.Path())\n\t\t} else {\n\t\t\tfmt.Fprintf(w, \"\\t%s (module %s)\\n\", m.Path(), modPath)\n\t\t}\n\t}\n}\n\nfunc modulePath(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (string, error) {\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"Reading %s: %v\", uri, err)\n\t}\n\tpmf, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"parsing modfile: %v\", err)\n\t}\n\tif pmf.File == nil || pmf.File.Module == nil {\n\t\treturn \"\", fmt.Errorf(\"malformed modfile\")\n\t}\n\treturn pmf.File.Module.Mod.Path, nil\n}\n\nfunc packageSummaries(snapshot *cache.Snapshot, pkgs immutable.Map[cache.PackageID, cache.PackagePath]) []string {\n\tvar summaries []string\n\tfor id := range pkgs.All() {\n\t\tmp := snapshot.Metadata(id)\n\t\tif len(mp.CompiledGoFiles) == 0 {\n\t\t\tcontinue // For convenience, just skip uncompiled packages; we could do more if it matters.\n\t\t}\n\t\tdir := mp.CompiledGoFiles[0].DirPath()\n\t\tsummaries = append(summaries, fmt.Sprintf(\"The `%s` directory contains the %q package with path %q\", dir, mp.Name, mp.PkgPath))\n\t}\n\tslices.Sort(summaries) // for stability\n\treturn summaries\n}\n"
  },
  {
    "path": "gopls/internal/mcp/workspace_diagnostics.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"maps\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype workspaceDiagnosticsParams struct {\n\tFiles []string `json:\"files,omitempty\" jsonschema:\"absolute paths to active files, if any\"`\n}\n\nfunc (h *handler) workspaceDiagnosticsHandler(ctx context.Context, req *mcp.CallToolRequest, params workspaceDiagnosticsParams) (*mcp.CallToolResult, any, error) {\n\tcountGoDiagnosticsMCP.Inc()\n\tvar (\n\t\tfh       file.Handle\n\t\tsnapshot *cache.Snapshot\n\t\trelease  func()\n\t\terr      error\n\t)\n\tif len(params.Files) > 0 {\n\t\tfh, snapshot, release, err = h.fileOf(ctx, params.Files[0])\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t} else {\n\t\tviews := h.session.Views()\n\t\tif len(views) == 0 {\n\t\t\treturn nil, nil, fmt.Errorf(\"No active builds.\")\n\t\t}\n\t\tsnapshot, release, err = views[0].Snapshot()\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t}\n\tdefer release()\n\n\tpkgMap := snapshot.WorkspacePackages()\n\tvar ids []metadata.PackageID\n\tfor id := range pkgMap.All() {\n\t\tids = append(ids, id)\n\t}\n\tslices.Sort(ids)\n\n\tdiagnostics, err := snapshot.PackageDiagnostics(ctx, ids...)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"diagnostics failed: %v\", err)\n\t}\n\n\tfixes := make(map[*cache.Diagnostic]*protocol.CodeAction)\n\tfor _, file := range params.Files {\n\t\turi := protocol.URIFromPath(file)\n\t\t// Get more specific diagnostics for the file in question.\n\t\tfileDiagnostics, fileFixes, err := h.diagnoseFile(ctx, snapshot, uri)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"diagnostics failed: %v\", err)\n\t\t}\n\t\tdiagnostics[fh.URI()] = fileDiagnostics\n\t\tmaps.Insert(fixes, maps.All(fileFixes))\n\t}\n\n\tkeys := slices.Sorted(maps.Keys(diagnostics))\n\tvar b strings.Builder\n\tfor _, uri := range keys {\n\t\tdiags := diagnostics[uri]\n\t\tif len(diags) > 0 {\n\t\t\tfmt.Fprintf(&b, \"File `%s` has the following diagnostics:\\n\", uri.Path())\n\t\t\tif err := summarizeDiagnostics(ctx, snapshot, &b, diags, fixes); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tfmt.Fprintln(&b)\n\t\t}\n\t}\n\n\tif b.Len() == 0 {\n\t\treturn textResult(\"No diagnostics.\"), nil, nil\n\t}\n\n\treturn textResult(b.String()), nil, nil\n}\n"
  },
  {
    "path": "gopls/internal/mod/code_lens.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mod\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n)\n\n// CodeLensSources returns the sources of code lenses for go.mod files.\nfunc CodeLensSources() map[settings.CodeLensSource]cache.CodeLensSourceFunc {\n\treturn map[settings.CodeLensSource]cache.CodeLensSourceFunc{\n\t\tsettings.CodeLensUpgradeDependency: upgradeLenses,        // commands: CheckUpgrades, UpgradeDependency\n\t\tsettings.CodeLensTidy:              tidyLens,             // commands: Tidy\n\t\tsettings.CodeLensVendor:            vendorLens,           // commands: Vendor\n\t\tsettings.CodeLensVulncheck:         vulncheckLenses,      // commands: Vulncheck\n\t\tsettings.CodeLensRunGovulncheck:    runGovulncheckLenses, // commands: RunGovulncheck\n\t}\n}\n\nfunc upgradeLenses(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm.File == nil {\n\t\treturn nil, err\n\t}\n\turi := fh.URI()\n\treset := command.NewResetGoModDiagnosticsCommand(\"Reset go.mod diagnostics\", command.ResetGoModDiagnosticsArgs{URIArg: command.URIArg{URI: uri}})\n\t// Put the `Reset go.mod diagnostics` codelens on the module statement.\n\tmodrng, err := moduleStmtRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlenses := []protocol.CodeLens{{Range: modrng, Command: reset}}\n\tif len(pm.File.Require) == 0 {\n\t\t// Nothing to upgrade.\n\t\treturn lenses, nil\n\t}\n\tvar requires []string\n\tfor _, req := range pm.File.Require {\n\t\trequires = append(requires, req.Mod.Path)\n\t}\n\tcheckUpgrade := command.NewCheckUpgradesCommand(\"Check for upgrades\", command.CheckUpgradesArgs{\n\t\tURI:     uri,\n\t\tModules: requires,\n\t})\n\tupgradeTransitive := command.NewUpgradeDependencyCommand(\"Upgrade transitive dependencies\", command.DependencyArgs{\n\t\tURI:        uri,\n\t\tAddRequire: false,\n\t\tGoCmdArgs:  []string{\"-d\", \"-u\", \"-t\", \"./...\"},\n\t})\n\tupgradeDirect := command.NewUpgradeDependencyCommand(\"Upgrade direct dependencies\", command.DependencyArgs{\n\t\tURI:        uri,\n\t\tAddRequire: false,\n\t\tGoCmdArgs:  append([]string{\"-d\"}, requires...),\n\t})\n\n\t// Put the upgrade code lenses above the first require block or statement.\n\trng, err := firstRequireRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn append(lenses, []protocol.CodeLens{\n\t\t{Range: rng, Command: checkUpgrade},\n\t\t{Range: rng, Command: upgradeTransitive},\n\t\t{Range: rng, Command: upgradeDirect},\n\t}...), nil\n}\n\nfunc tidyLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm.File == nil {\n\t\treturn nil, err\n\t}\n\turi := fh.URI()\n\tcmd := command.NewTidyCommand(\"Run go mod tidy\", command.URIArgs{URIs: []protocol.DocumentURI{uri}})\n\trng, err := moduleStmtRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn []protocol.CodeLens{{\n\t\tRange:   rng,\n\t\tCommand: cmd,\n\t}}, nil\n}\n\nfunc vendorLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm.File == nil {\n\t\treturn nil, err\n\t}\n\tif len(pm.File.Require) == 0 {\n\t\t// Nothing to vendor.\n\t\treturn nil, nil\n\t}\n\trng, err := moduleStmtRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttitle := \"Create vendor directory\"\n\turi := fh.URI()\n\tcmd := command.NewVendorCommand(title, command.URIArg{URI: uri})\n\t// Change the message depending on whether or not the module already has a\n\t// vendor directory.\n\tvendorDir := filepath.Join(fh.URI().DirPath(), \"vendor\")\n\tif info, _ := os.Stat(vendorDir); info != nil && info.IsDir() {\n\t\ttitle = \"Sync vendor directory\"\n\t}\n\treturn []protocol.CodeLens{{Range: rng, Command: cmd}}, nil\n}\n\nfunc moduleStmtRange(fh file.Handle, pm *cache.ParsedModule) (protocol.Range, error) {\n\tif pm.File == nil || pm.File.Module == nil || pm.File.Module.Syntax == nil {\n\t\treturn protocol.Range{}, fmt.Errorf(\"no module statement in %s\", fh.URI())\n\t}\n\tsyntax := pm.File.Module.Syntax\n\treturn pm.Mapper.OffsetRange(syntax.Start.Byte, syntax.End.Byte)\n}\n\n// firstRequireRange returns the range for the first \"require\" in the given\n// go.mod file. This is either a require block or an individual require line.\nfunc firstRequireRange(fh file.Handle, pm *cache.ParsedModule) (protocol.Range, error) {\n\tif len(pm.File.Require) == 0 {\n\t\treturn protocol.Range{}, fmt.Errorf(\"no requires in the file %s\", fh.URI())\n\t}\n\tvar start, end modfile.Position\n\tfor _, stmt := range pm.File.Syntax.Stmt {\n\t\tif b, ok := stmt.(*modfile.LineBlock); ok && len(b.Token) == 1 && b.Token[0] == \"require\" {\n\t\t\tstart, end = b.Span()\n\t\t\tbreak\n\t\t}\n\t}\n\n\tfirstRequire := pm.File.Require[0].Syntax\n\tif start.Byte == 0 || firstRequire.Start.Byte < start.Byte {\n\t\tstart, end = firstRequire.Start, firstRequire.End\n\t}\n\treturn pm.Mapper.OffsetRange(start.Byte, end.Byte)\n}\n\nfunc vulncheckLenses(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm.File == nil {\n\t\treturn nil, err\n\t}\n\t// Place the codelenses near the module statement.\n\t// A module may not have the require block,\n\t// but vulnerabilities can exist in standard libraries.\n\turi := fh.URI()\n\trng, err := moduleStmtRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvulncheck := command.NewVulncheckCommand(\"Run govulncheck\", command.VulncheckArgs{\n\t\tURI:     uri,\n\t\tPattern: \"./...\",\n\t})\n\treturn []protocol.CodeLens{\n\t\t{Range: rng, Command: vulncheck},\n\t}, nil\n}\n\nfunc runGovulncheckLenses(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.CodeLens, error) {\n\t// If CodeLensVulncheck is enabled, do not use the legacy CodeLensRunGovulncheck.\n\tif snapshot.Options().UserOptions.UIOptions.Codelenses[settings.CodeLensVulncheck] {\n\t\treturn nil, nil\n\t}\n\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil || pm.File == nil {\n\t\treturn nil, err\n\t}\n\t// Place the codelenses near the module statement.\n\t// A module may not have the require block,\n\t// but vulnerabilities can exist in standard libraries.\n\turi := fh.URI()\n\trng, err := moduleStmtRange(fh, pm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvulncheck := command.NewRunGovulncheckCommand(\"Run govulncheck\", command.VulncheckArgs{\n\t\tURI:     uri,\n\t\tPattern: \"./...\",\n\t})\n\treturn []protocol.CodeLens{\n\t\t{Range: rng, Command: vulncheck},\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/mod/diagnostics.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package mod provides core features related to go.mod file\n// handling for use by Go editors and tools.\npackage mod\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// ParseDiagnostics returns diagnostics from parsing the go.mod files in the workspace.\nfunc ParseDiagnostics(ctx context.Context, snapshot *cache.Snapshot) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"mod.Diagnostics\", snapshot.Labels()...)\n\tdefer done()\n\n\treturn collectDiagnostics(ctx, snapshot, parseDiagnostics)\n}\n\n// TidyDiagnostics returns diagnostics from running go mod tidy.\nfunc TidyDiagnostics(ctx context.Context, snapshot *cache.Snapshot) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"mod.Diagnostics\", snapshot.Labels()...)\n\tdefer done()\n\n\treturn collectDiagnostics(ctx, snapshot, tidyDiagnostics)\n}\n\n// UpgradeDiagnostics returns upgrade diagnostics for the modules in the\n// workspace with known upgrades.\nfunc UpgradeDiagnostics(ctx context.Context, snapshot *cache.Snapshot) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"mod.UpgradeDiagnostics\", snapshot.Labels()...)\n\tdefer done()\n\n\treturn collectDiagnostics(ctx, snapshot, upgradeDiagnostics)\n}\n\n// VulnerabilityDiagnostics returns vulnerability diagnostics for the active modules in the\n// workspace with known vulnerabilities.\nfunc VulnerabilityDiagnostics(ctx context.Context, snapshot *cache.Snapshot) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"mod.VulnerabilityDiagnostics\", snapshot.Labels()...)\n\tdefer done()\n\n\treturn collectDiagnostics(ctx, snapshot, vulnerabilityDiagnostics)\n}\n\nfunc collectDiagnostics(ctx context.Context, snapshot *cache.Snapshot, diagFn func(context.Context, *cache.Snapshot, file.Handle) ([]*cache.Diagnostic, error)) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tg, ctx := errgroup.WithContext(ctx)\n\tcpulimit := runtime.GOMAXPROCS(0)\n\tg.SetLimit(cpulimit)\n\n\tvar mu sync.Mutex\n\treports := make(map[protocol.DocumentURI][]*cache.Diagnostic)\n\n\tfor _, uri := range snapshot.View().ModFiles() {\n\t\tg.Go(func() error {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdiagnostics, err := diagFn(ctx, snapshot, fh)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, d := range diagnostics {\n\t\t\t\tmu.Lock()\n\t\t\t\treports[d.URI] = append(reports[fh.URI()], d)\n\t\t\t\tmu.Unlock()\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\n\tif err := g.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn reports, nil\n}\n\n// parseDiagnostics reports diagnostics from parsing the mod file.\nfunc parseDiagnostics(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) (diagnostics []*cache.Diagnostic, err error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\tif pm == nil || len(pm.ParseErrors) == 0 {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn pm.ParseErrors, nil\n\t}\n\treturn nil, nil\n}\n\n// tidyDiagnostics reports diagnostics from running go mod tidy.\nfunc tidyDiagnostics(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]*cache.Diagnostic, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh) // memoized\n\tif err != nil {\n\t\treturn nil, nil // errors reported by ModDiagnostics above\n\t}\n\n\ttidied, err := snapshot.ModTidy(ctx, pm)\n\tif err != nil {\n\t\tif err != cache.ErrNoModOnDisk && !strings.Contains(err.Error(), \"GOPROXY=off\") {\n\t\t\t// TODO(rfindley): the check for ErrNoModOnDisk was historically determined\n\t\t\t// to be benign, but may date back to the time when the Go command did not\n\t\t\t// have overlay support.\n\t\t\t//\n\t\t\t// See if we can pass the overlay to the Go command, and eliminate this guard..\n\n\t\t\t// TODO(golang/go#56395): remove the arbitrary suppression of the mod\n\t\t\t// tidy error when GOPROXY=off. The true fix for this noisy log message\n\t\t\t// is to fix the mod tidy diagnostics.\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"tidy: diagnosing %s\", pm.URI), err)\n\t\t}\n\t\treturn nil, nil\n\t}\n\treturn tidied.Diagnostics, nil\n}\n\n// upgradeDiagnostics adds upgrade quick fixes for individual modules if the upgrades\n// are recorded in the view.\nfunc upgradeDiagnostics(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) (upgradeDiagnostics []*cache.Diagnostic, err error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\t// Don't return an error if there are parse error diagnostics to be shown, but also do not\n\t\t// continue since we won't be able to show the upgrade diagnostics.\n\t\tif pm != nil && len(pm.ParseErrors) != 0 {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\n\tupgrades := snapshot.ModuleUpgrades(fh.URI())\n\tfor _, req := range pm.File.Require {\n\t\tver, ok := upgrades[req.Mod.Path]\n\t\tif !ok || req.Mod.Version == ver {\n\t\t\tcontinue\n\t\t}\n\t\trng, err := pm.Mapper.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Upgrade to the exact version we offer the user, not the most recent.\n\t\ttitle := fmt.Sprintf(\"%s%v\", upgradeCodeActionPrefix, ver)\n\t\tcmd := command.NewUpgradeDependencyCommand(title, command.DependencyArgs{\n\t\t\tURI:        fh.URI(),\n\t\t\tAddRequire: false,\n\t\t\tGoCmdArgs:  []string{req.Mod.Path + \"@\" + ver},\n\t\t})\n\t\tupgradeDiagnostics = append(upgradeDiagnostics, &cache.Diagnostic{\n\t\t\tURI:            fh.URI(),\n\t\t\tRange:          rng,\n\t\t\tSeverity:       protocol.SeverityInformation,\n\t\t\tSource:         cache.UpgradeNotification,\n\t\t\tMessage:        fmt.Sprintf(\"%v can be upgraded\", req.Mod.Path),\n\t\t\tSuggestedFixes: []cache.SuggestedFix{cache.SuggestedFixFromCommand(cmd, protocol.QuickFix)},\n\t\t})\n\t}\n\n\treturn upgradeDiagnostics, nil\n}\n\nconst upgradeCodeActionPrefix = \"Upgrade to \"\n\n// vulnerabilityDiagnostics adds diagnostics for vulnerabilities in individual modules\n// if the vulnerability is recorded in the view.\nfunc vulnerabilityDiagnostics(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) (vulnDiagnostics []*cache.Diagnostic, err error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\t// Don't return an error if there are parse error diagnostics to be shown, but also do not\n\t\t// continue since we won't be able to show the vulnerability diagnostics.\n\t\tif pm != nil && len(pm.ParseErrors) != 0 {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\n\tdiagSource := cache.Govulncheck\n\tvs := snapshot.Vulnerabilities(fh.URI())[fh.URI()]\n\tif vs == nil && snapshot.Options().Vulncheck == settings.ModeVulncheckImports {\n\t\tvs, err = snapshot.ModVuln(ctx, fh.URI())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdiagSource = cache.Vulncheck\n\t}\n\tif vs == nil || len(vs.Findings) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tsuggestRunOrResetGovulncheck, err := suggestGovulncheckAction(diagSource == cache.Govulncheck, fh.URI())\n\tif err != nil {\n\t\t// must not happen\n\t\treturn nil, err // TODO: bug report\n\t}\n\tvulnsByModule := make(map[string][]*govulncheck.Finding)\n\n\tfor _, finding := range vs.Findings {\n\t\tif vuln, typ := foundVuln(finding); typ == vulnCalled || typ == vulnImported {\n\t\t\tvulnsByModule[vuln.Module] = append(vulnsByModule[vuln.Module], finding)\n\t\t}\n\t}\n\tfor _, req := range pm.File.Require {\n\t\tmod := req.Mod.Path\n\t\tfindings := vulnsByModule[mod]\n\t\tif len(findings) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// note: req.Syntax is the line corresponding to 'require', which means\n\t\t// req.Syntax.Start can point to the beginning of the \"require\" keyword\n\t\t// for a single line require (e.g. \"require golang.org/x/mod v0.0.0\").\n\t\tstart := req.Syntax.Start.Byte\n\t\tif len(req.Syntax.Token) == 3 {\n\t\t\tstart += len(\"require \")\n\t\t}\n\t\trng, err := pm.Mapper.OffsetRange(start, req.Syntax.End.Byte)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Map affecting vulns to 'warning' level diagnostics,\n\t\t// others to 'info' level diagnostics.\n\t\t// Fixes will include only the upgrades for warning level diagnostics.\n\t\tvar warningFixes, infoFixes []cache.SuggestedFix\n\t\tvar warningSet, infoSet = map[string]bool{}, map[string]bool{}\n\t\tfor _, finding := range findings {\n\t\t\t// It is possible that the source code was changed since the last\n\t\t\t// govulncheck run and information in the `vulns` info is stale.\n\t\t\t// For example, imagine that a user is in the middle of updating\n\t\t\t// problematic modules detected by the govulncheck run by applying\n\t\t\t// quick fixes. Stale diagnostics can be confusing and prevent the\n\t\t\t// user from quickly locating the next module to fix.\n\t\t\t// Ideally we should rerun the analysis with the updated module\n\t\t\t// dependencies or any other code changes, but we are not yet\n\t\t\t// in the position of automatically triggering the analysis\n\t\t\t// (govulncheck can take a while). We also don't know exactly what\n\t\t\t// part of source code was changed since `vulns` was computed.\n\t\t\t// As a heuristic, we assume that a user upgrades the affecting\n\t\t\t// module to the version with the fix or the latest one, and if the\n\t\t\t// version in the require statement is equal to or higher than the\n\t\t\t// fixed version, skip generating a diagnostic about the vulnerability.\n\t\t\t// Eventually, the user has to rerun govulncheck.\n\t\t\tif finding.FixedVersion != \"\" && semver.IsValid(req.Mod.Version) && semver.Compare(finding.FixedVersion, req.Mod.Version) <= 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch _, typ := foundVuln(finding); typ {\n\t\t\tcase vulnImported:\n\t\t\t\tinfoSet[finding.OSV] = true\n\t\t\tcase vulnCalled:\n\t\t\t\twarningSet[finding.OSV] = true\n\t\t\t}\n\t\t\t// Upgrade to the exact version we offer the user, not the most recent.\n\t\t\tif fixedVersion := finding.FixedVersion; semver.IsValid(fixedVersion) && semver.Compare(req.Mod.Version, fixedVersion) < 0 {\n\t\t\t\tcmd := getUpgradeCodeAction(fh, req, fixedVersion)\n\t\t\t\tsf := cache.SuggestedFixFromCommand(cmd, protocol.QuickFix)\n\t\t\t\tswitch _, typ := foundVuln(finding); typ {\n\t\t\t\tcase vulnImported:\n\t\t\t\t\tinfoFixes = append(infoFixes, sf)\n\t\t\t\tcase vulnCalled:\n\t\t\t\t\twarningFixes = append(warningFixes, sf)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif len(warningSet) == 0 && len(infoSet) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// Remove affecting osvs from the non-affecting osv list if any.\n\t\tif len(warningSet) > 0 {\n\t\t\tfor k := range infoSet {\n\t\t\t\tif warningSet[k] {\n\t\t\t\t\tdelete(infoSet, k)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Add an upgrade for module@latest.\n\t\t// TODO(suzmue): verify if latest is the same as fixedVersion.\n\t\tlatest := getUpgradeCodeAction(fh, req, \"latest\")\n\t\tsf := cache.SuggestedFixFromCommand(latest, protocol.QuickFix)\n\t\tif len(warningFixes) > 0 {\n\t\t\twarningFixes = append(warningFixes, sf)\n\t\t}\n\t\tif len(infoFixes) > 0 {\n\t\t\tinfoFixes = append(infoFixes, sf)\n\t\t}\n\t\tif len(warningSet) > 0 {\n\t\t\twarning := sortedKeys(warningSet)\n\t\t\twarningFixes = append(warningFixes, suggestRunOrResetGovulncheck)\n\t\t\tvulnDiagnostics = append(vulnDiagnostics, &cache.Diagnostic{\n\t\t\t\tURI:            fh.URI(),\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityWarning,\n\t\t\t\tSource:         diagSource,\n\t\t\t\tMessage:        getVulnMessage(req.Mod.Path, warning, true, diagSource == cache.Govulncheck),\n\t\t\t\tSuggestedFixes: warningFixes,\n\t\t\t})\n\t\t}\n\t\tif len(infoSet) > 0 {\n\t\t\tinfo := sortedKeys(infoSet)\n\t\t\tinfoFixes = append(infoFixes, suggestRunOrResetGovulncheck)\n\t\t\tvulnDiagnostics = append(vulnDiagnostics, &cache.Diagnostic{\n\t\t\t\tURI:            fh.URI(),\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityInformation,\n\t\t\t\tSource:         diagSource,\n\t\t\t\tMessage:        getVulnMessage(req.Mod.Path, info, false, diagSource == cache.Govulncheck),\n\t\t\t\tSuggestedFixes: infoFixes,\n\t\t\t})\n\t\t}\n\t}\n\n\t// TODO(hyangah): place this diagnostic on the `go` directive or `toolchain` directive\n\t// after https://go.dev/issue/57001.\n\tconst diagnoseStdLib = false\n\n\t// If diagnosing the stdlib, add standard library vulnerability diagnostics\n\t// on the module declaration.\n\t//\n\t// Only proceed if we have a valid module declaration on which to position\n\t// the diagnostics.\n\tif diagnoseStdLib && pm.File.Module != nil && pm.File.Module.Syntax != nil {\n\t\t// Add standard library vulnerabilities.\n\t\tstdlibVulns := vulnsByModule[\"stdlib\"]\n\t\tif len(stdlibVulns) == 0 {\n\t\t\treturn vulnDiagnostics, nil\n\t\t}\n\n\t\t// Put the standard library diagnostic on the module declaration.\n\t\trng, err := pm.Mapper.OffsetRange(pm.File.Module.Syntax.Start.Byte, pm.File.Module.Syntax.End.Byte)\n\t\tif err != nil {\n\t\t\treturn vulnDiagnostics, nil // TODO: bug report\n\t\t}\n\n\t\tvar warningSet, infoSet = map[string]bool{}, map[string]bool{}\n\t\tfor _, finding := range stdlibVulns {\n\t\t\tswitch _, typ := foundVuln(finding); typ {\n\t\t\tcase vulnImported:\n\t\t\t\tinfoSet[finding.OSV] = true\n\t\t\tcase vulnCalled:\n\t\t\t\twarningSet[finding.OSV] = true\n\t\t\t}\n\t\t}\n\t\tif len(warningSet) > 0 {\n\t\t\twarning := sortedKeys(warningSet)\n\t\t\tfixes := []cache.SuggestedFix{suggestRunOrResetGovulncheck}\n\t\t\tvulnDiagnostics = append(vulnDiagnostics, &cache.Diagnostic{\n\t\t\t\tURI:            fh.URI(),\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityWarning,\n\t\t\t\tSource:         diagSource,\n\t\t\t\tMessage:        getVulnMessage(\"go\", warning, true, diagSource == cache.Govulncheck),\n\t\t\t\tSuggestedFixes: fixes,\n\t\t\t})\n\n\t\t\t// remove affecting osvs from the non-affecting osv list if any.\n\t\t\tfor k := range infoSet {\n\t\t\t\tif warningSet[k] {\n\t\t\t\t\tdelete(infoSet, k)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif len(infoSet) > 0 {\n\t\t\tinfo := sortedKeys(infoSet)\n\t\t\tfixes := []cache.SuggestedFix{suggestRunOrResetGovulncheck}\n\t\t\tvulnDiagnostics = append(vulnDiagnostics, &cache.Diagnostic{\n\t\t\t\tURI:            fh.URI(),\n\t\t\t\tRange:          rng,\n\t\t\t\tSeverity:       protocol.SeverityInformation,\n\t\t\t\tSource:         diagSource,\n\t\t\t\tMessage:        getVulnMessage(\"go\", info, false, diagSource == cache.Govulncheck),\n\t\t\t\tSuggestedFixes: fixes,\n\t\t\t})\n\t\t}\n\t}\n\n\treturn vulnDiagnostics, nil\n}\n\ntype vulnFindingType int\n\nconst (\n\tvulnUnknown vulnFindingType = iota\n\tvulnCalled\n\tvulnImported\n\tvulnRequired\n)\n\n// foundVuln returns the frame info describing discovered vulnerable symbol/package/module\n// and how this vulnerability affects the analyzed package or module.\nfunc foundVuln(finding *govulncheck.Finding) (*govulncheck.Frame, vulnFindingType) {\n\t// finding.Trace is sorted from the imported vulnerable symbol to\n\t// the entry point in the callstack.\n\t// If Function is set, then Package must be set. Module will always be set.\n\t// If Function is set it was found in the call graph, otherwise if Package is set\n\t// it was found in the import graph, otherwise it was found in the require graph.\n\t// See the documentation of govulncheck.Finding.\n\tif len(finding.Trace) == 0 { // this shouldn't happen, but just in case...\n\t\treturn nil, vulnUnknown\n\t}\n\tvuln := finding.Trace[0]\n\tif vuln.Package == \"\" {\n\t\treturn vuln, vulnRequired\n\t}\n\tif vuln.Function == \"\" {\n\t\treturn vuln, vulnImported\n\t}\n\treturn vuln, vulnCalled\n}\n\nfunc sortedKeys(m map[string]bool) []string {\n\tret := make([]string, 0, len(m))\n\tfor k := range m {\n\t\tret = append(ret, k)\n\t}\n\tsort.Strings(ret)\n\treturn ret\n}\n\n// suggestGovulncheckAction returns a code action that suggests either run govulncheck\n// for more accurate investigation (if the present vulncheck diagnostics are based on\n// analysis less accurate than govulncheck) or reset the existing govulncheck result\n// (if the present vulncheck diagnostics are already based on govulncheck run).\nfunc suggestGovulncheckAction(fromGovulncheck bool, uri protocol.DocumentURI) (cache.SuggestedFix, error) {\n\tif fromGovulncheck {\n\t\tresetVulncheck := command.NewResetGoModDiagnosticsCommand(\"Reset govulncheck result\", command.ResetGoModDiagnosticsArgs{\n\t\t\tURIArg:           command.URIArg{URI: uri},\n\t\t\tDiagnosticSource: string(cache.Govulncheck),\n\t\t})\n\t\treturn cache.SuggestedFixFromCommand(resetVulncheck, protocol.QuickFix), nil\n\t}\n\tvulncheck := command.NewRunGovulncheckCommand(\"Run govulncheck to verify\", command.VulncheckArgs{\n\t\tURI:     uri,\n\t\tPattern: \"./...\",\n\t})\n\treturn cache.SuggestedFixFromCommand(vulncheck, protocol.QuickFix), nil\n}\n\nfunc getVulnMessage(mod string, vulns []string, used, fromGovulncheck bool) string {\n\tvar b strings.Builder\n\tif used {\n\t\tswitch len(vulns) {\n\t\tcase 1:\n\t\t\tfmt.Fprintf(&b, \"%v has a vulnerability used in the code: %v.\", mod, vulns[0])\n\t\tdefault:\n\t\t\tfmt.Fprintf(&b, \"%v has vulnerabilities used in the code: %v.\", mod, strings.Join(vulns, \", \"))\n\t\t}\n\t} else {\n\t\tif fromGovulncheck {\n\t\t\tswitch len(vulns) {\n\t\t\tcase 1:\n\t\t\t\tfmt.Fprintf(&b, \"%v has a vulnerability %v that is not used in the code.\", mod, vulns[0])\n\t\t\tdefault:\n\t\t\t\tfmt.Fprintf(&b, \"%v has known vulnerabilities %v that are not used in the code.\", mod, strings.Join(vulns, \", \"))\n\t\t\t}\n\t\t} else {\n\t\t\tswitch len(vulns) {\n\t\t\tcase 1:\n\t\t\t\tfmt.Fprintf(&b, \"%v has a vulnerability %v.\", mod, vulns[0])\n\t\t\tdefault:\n\t\t\t\tfmt.Fprintf(&b, \"%v has known vulnerabilities %v.\", mod, strings.Join(vulns, \", \"))\n\t\t\t}\n\t\t}\n\t}\n\treturn b.String()\n}\n\n// href returns the url for the vulnerability information.\n// Eventually we should retrieve the url embedded in the osv.Entry.\n// While vuln.go.dev is under development, this always returns\n// the page in pkg.go.dev.\nfunc href(vulnID string) string {\n\treturn fmt.Sprintf(\"https://pkg.go.dev/vuln/%s\", vulnID)\n}\n\nfunc getUpgradeCodeAction(fh file.Handle, req *modfile.Require, version string) *protocol.Command {\n\treturn command.NewUpgradeDependencyCommand(upgradeTitle(version), command.DependencyArgs{\n\t\tURI:        fh.URI(),\n\t\tAddRequire: false,\n\t\tGoCmdArgs:  []string{req.Mod.Path + \"@\" + version},\n\t})\n}\n\nfunc upgradeTitle(fixedVersion string) string {\n\ttitle := fmt.Sprintf(\"%s%v\", upgradeCodeActionPrefix, fixedVersion)\n\treturn title\n}\n\n// SelectUpgradeCodeActions takes a list of code actions for a required module\n// and returns a more selective list of upgrade code actions,\n// where the code actions have been deduped. Code actions unrelated to upgrade\n// are deduplicated by the name.\nfunc SelectUpgradeCodeActions(actions []protocol.CodeAction) []protocol.CodeAction {\n\tif len(actions) <= 1 {\n\t\treturn actions // return early if no sorting necessary\n\t}\n\tvar versionedUpgrade, latestUpgrade, resetAction protocol.CodeAction\n\tvar chosenVersionedUpgrade string\n\tvar selected []protocol.CodeAction\n\n\tseenTitles := make(map[string]bool)\n\n\tfor _, action := range actions {\n\t\tif strings.HasPrefix(action.Title, upgradeCodeActionPrefix) {\n\t\t\tif v := getUpgradeVersion(action); v == \"latest\" && latestUpgrade.Title == \"\" {\n\t\t\t\tlatestUpgrade = action\n\t\t\t} else if versionedUpgrade.Title == \"\" || semver.Compare(v, chosenVersionedUpgrade) > 0 {\n\t\t\t\tchosenVersionedUpgrade = v\n\t\t\t\tversionedUpgrade = action\n\t\t\t}\n\t\t} else if strings.HasPrefix(action.Title, \"Reset govulncheck\") {\n\t\t\tresetAction = action\n\t\t} else if !seenTitles[action.Command.Title] {\n\t\t\tseenTitles[action.Command.Title] = true\n\t\t\tselected = append(selected, action)\n\t\t}\n\t}\n\tif versionedUpgrade.Title != \"\" {\n\t\tselected = append(selected, versionedUpgrade)\n\t}\n\tif latestUpgrade.Title != \"\" {\n\t\tselected = append(selected, latestUpgrade)\n\t}\n\tif resetAction.Title != \"\" {\n\t\tselected = append(selected, resetAction)\n\t}\n\treturn selected\n}\n\nfunc getUpgradeVersion(p protocol.CodeAction) string {\n\treturn strings.TrimPrefix(p.Title, upgradeCodeActionPrefix)\n}\n"
  },
  {
    "path": "gopls/internal/mod/format.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mod\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.TextEdit, error) {\n\tctx, done := event.Start(ctx, \"mod.Format\")\n\tdefer done()\n\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tformatted, err := pm.File.Format()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Calculate the edits to be made due to the change.\n\tdiffs := diff.Bytes(pm.Mapper.Content, formatted)\n\treturn protocol.EditsFromDiffEdits(pm.Mapper, diffs)\n}\n"
  },
  {
    "path": "gopls/internal/mod/hover.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mod\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (*protocol.Hover, error) {\n\t// We only provide hover information for the view's go.mod files.\n\tif !slices.Contains(snapshot.View().ModFiles(), fh.URI()) {\n\t\treturn nil, nil\n\t}\n\n\tctx, done := event.Start(ctx, \"mod.Hover\")\n\tdefer done()\n\n\t// Get the position of the cursor.\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting modfile handle: %w\", err)\n\t}\n\tstartOffset, endOffset, err := pm.Mapper.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"computing cursor position: %w\", err)\n\t}\n\n\t// If the cursor position is on a module statement\n\tif hover, ok := hoverOnModuleStatement(ctx, pm, startOffset, endOffset, snapshot, fh); ok {\n\t\treturn hover, nil\n\t}\n\treturn hoverOnRequireStatement(ctx, pm, startOffset, endOffset, snapshot, fh)\n}\n\nfunc hoverOnRequireStatement(ctx context.Context, pm *cache.ParsedModule, startOffset, endOffset int, snapshot *cache.Snapshot, fh file.Handle) (*protocol.Hover, error) {\n\t// Confirm that the cursor is at the position of a require statement.\n\tvar req *modfile.Require\n\tvar depStartOffset, depEndOffset int\n\tfor _, r := range pm.File.Require {\n\t\tdep := []byte(r.Mod.Path)\n\t\ts, e := r.Syntax.Start.Byte, r.Syntax.End.Byte\n\t\ti := bytes.Index(pm.Mapper.Content[s:e], dep)\n\t\tif i == -1 {\n\t\t\tcontinue\n\t\t}\n\t\t// Shift the start position to the location of the\n\t\t// dependency within the require statement.\n\t\tdepStartOffset, depEndOffset = s+i, e\n\t\tif depStartOffset <= startOffset && endOffset <= depEndOffset {\n\t\t\treq = r\n\t\t\tbreak\n\t\t}\n\t}\n\t// TODO(hyangah): find position for info about vulnerabilities in Go\n\n\t// The cursor position is not on a require statement.\n\tif req == nil {\n\t\treturn nil, nil\n\t}\n\n\t// Get the vulnerability info.\n\tfromGovulncheck := true\n\tvs := snapshot.Vulnerabilities(fh.URI())[fh.URI()]\n\tif vs == nil && snapshot.Options().Vulncheck == settings.ModeVulncheckImports {\n\t\tvar err error\n\t\tvs, err = snapshot.ModVuln(ctx, fh.URI())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfromGovulncheck = false\n\t}\n\taffecting, nonaffecting, osvs := lookupVulns(vs, req.Mod.Path, req.Mod.Version)\n\n\t// Get the `go mod why` results for the given file.\n\twhy, err := snapshot.ModWhy(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\texplanation, ok := why[req.Mod.Path]\n\tif !ok {\n\t\treturn nil, nil\n\t}\n\n\t// Get the range to highlight for the hover.\n\t// TODO(hyangah): adjust the hover range to include the version number\n\t// to match the diagnostics' range.\n\trng, err := pm.Mapper.OffsetRange(startOffset, endOffset)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\toptions := snapshot.Options()\n\tisPrivate := snapshot.IsGoPrivatePath(req.Mod.Path)\n\theader := formatHeader(req.Mod.Path, options)\n\texplanation = formatExplanation(explanation, pm.ReplaceMap, req, options, isPrivate)\n\tvulns := formatVulnerabilities(affecting, nonaffecting, osvs, options, fromGovulncheck)\n\n\treturn &protocol.Hover{\n\t\tContents: protocol.MarkupContent{\n\t\t\tKind:  options.PreferredContentFormat,\n\t\t\tValue: header + vulns + explanation,\n\t\t},\n\t\tRange: rng,\n\t}, nil\n}\n\nfunc hoverOnModuleStatement(ctx context.Context, pm *cache.ParsedModule, startOffset, endOffset int, snapshot *cache.Snapshot, fh file.Handle) (*protocol.Hover, bool) {\n\tmodule := pm.File.Module\n\tif module == nil {\n\t\treturn nil, false // no module stmt\n\t}\n\tif endOffset < module.Syntax.Start.Byte || startOffset > module.Syntax.End.Byte {\n\t\treturn nil, false // cursor not in module stmt\n\t}\n\n\trng, err := pm.Mapper.OffsetRange(module.Syntax.Start.Byte, module.Syntax.End.Byte)\n\tif err != nil {\n\t\treturn nil, false\n\t}\n\tfromGovulncheck := true\n\tvs := snapshot.Vulnerabilities(fh.URI())[fh.URI()]\n\n\tif vs == nil && snapshot.Options().Vulncheck == settings.ModeVulncheckImports {\n\t\tvs, err = snapshot.ModVuln(ctx, fh.URI())\n\t\tif err != nil {\n\t\t\treturn nil, false\n\t\t}\n\t\tfromGovulncheck = false\n\t}\n\tmodpath := \"stdlib\"\n\tgoVersion := snapshot.View().GoVersionString()\n\taffecting, nonaffecting, osvs := lookupVulns(vs, modpath, goVersion)\n\toptions := snapshot.Options()\n\tvulns := formatVulnerabilities(affecting, nonaffecting, osvs, options, fromGovulncheck)\n\n\treturn &protocol.Hover{\n\t\tContents: protocol.MarkupContent{\n\t\t\tKind:  options.PreferredContentFormat,\n\t\t\tValue: vulns,\n\t\t},\n\t\tRange: rng,\n\t}, true\n}\n\nfunc formatHeader(modpath string, options *settings.Options) string {\n\tvar b strings.Builder\n\t// Write the heading as an H3.\n\tb.WriteString(\"#### \" + modpath)\n\tif options.PreferredContentFormat == protocol.Markdown {\n\t\tb.WriteString(\"\\n\\n\")\n\t} else {\n\t\tb.WriteRune('\\n')\n\t}\n\treturn b.String()\n}\n\nfunc lookupVulns(vulns *vulncheck.Result, modpath, version string) (affecting, nonaffecting []*govulncheck.Finding, osvs map[string]*osv.Entry) {\n\tif vulns == nil || len(vulns.Entries) == 0 {\n\t\treturn nil, nil, nil\n\t}\n\tfor _, finding := range vulns.Findings {\n\t\tvuln, typ := foundVuln(finding)\n\t\tif vuln.Module != modpath {\n\t\t\tcontinue\n\t\t}\n\t\t// It is possible that the source code was changed since the last\n\t\t// govulncheck run and information in the `vulns` info is stale.\n\t\t// For example, imagine that a user is in the middle of updating\n\t\t// problematic modules detected by the govulncheck run by applying\n\t\t// quick fixes. Stale diagnostics can be confusing and prevent the\n\t\t// user from quickly locating the next module to fix.\n\t\t// Ideally we should rerun the analysis with the updated module\n\t\t// dependencies or any other code changes, but we are not yet\n\t\t// in the position of automatically triggering the analysis\n\t\t// (govulncheck can take a while). We also don't know exactly what\n\t\t// part of source code was changed since `vulns` was computed.\n\t\t// As a heuristic, we assume that a user upgrades the affecting\n\t\t// module to the version with the fix or the latest one, and if the\n\t\t// version in the require statement is equal to or higher than the\n\t\t// fixed version, skip the vulnerability information in the hover.\n\t\t// Eventually, the user has to rerun govulncheck.\n\t\tif finding.FixedVersion != \"\" && semver.IsValid(version) && semver.Compare(finding.FixedVersion, version) <= 0 {\n\t\t\tcontinue\n\t\t}\n\t\tswitch typ {\n\t\tcase vulnCalled:\n\t\t\taffecting = append(affecting, finding)\n\t\tcase vulnImported:\n\t\t\tnonaffecting = append(nonaffecting, finding)\n\t\t}\n\t}\n\n\t// Remove affecting elements from nonaffecting.\n\t// An OSV entry can appear in both lists if an OSV entry covers\n\t// multiple packages imported but not all vulnerable symbols are used.\n\t// The current wording of hover message doesn't clearly\n\t// present this case well IMO, so let's skip reporting nonaffecting.\n\tif len(affecting) > 0 && len(nonaffecting) > 0 {\n\t\taffectingSet := map[string]bool{}\n\t\tfor _, f := range affecting {\n\t\t\taffectingSet[f.OSV] = true\n\t\t}\n\t\tn := 0\n\t\tfor _, v := range nonaffecting {\n\t\t\tif !affectingSet[v.OSV] {\n\t\t\t\tnonaffecting[n] = v\n\t\t\t\tn++\n\t\t\t}\n\t\t}\n\t\tnonaffecting = nonaffecting[:n]\n\t}\n\tsort.Slice(nonaffecting, func(i, j int) bool { return nonaffecting[i].OSV < nonaffecting[j].OSV })\n\tsort.Slice(affecting, func(i, j int) bool { return affecting[i].OSV < affecting[j].OSV })\n\treturn affecting, nonaffecting, vulns.Entries\n}\n\nfunc fixedVersion(fixed string) string {\n\tif fixed == \"\" {\n\t\treturn \"No fix is available.\"\n\t}\n\treturn \"Fixed in \" + fixed + \".\"\n}\n\nfunc formatVulnerabilities(affecting, nonaffecting []*govulncheck.Finding, osvs map[string]*osv.Entry, options *settings.Options, fromGovulncheck bool) string {\n\tif len(osvs) == 0 || (len(affecting) == 0 && len(nonaffecting) == 0) {\n\t\treturn \"\"\n\t}\n\tbyOSV := func(findings []*govulncheck.Finding) map[string][]*govulncheck.Finding {\n\t\tm := make(map[string][]*govulncheck.Finding)\n\t\tfor _, f := range findings {\n\t\t\tm[f.OSV] = append(m[f.OSV], f)\n\t\t}\n\t\treturn m\n\t}\n\taffectingByOSV := byOSV(affecting)\n\tnonaffectingByOSV := byOSV(nonaffecting)\n\n\t// TODO(hyangah): can we use go templates to generate hover messages?\n\t// Then, we can use a different template for markdown case.\n\tuseMarkdown := options.PreferredContentFormat == protocol.Markdown\n\n\tvar b strings.Builder\n\n\tif len(affectingByOSV) > 0 {\n\t\t// TODO(hyangah): make the message more eyecatching (icon/codicon/color)\n\t\tif len(affectingByOSV) == 1 {\n\t\t\tfmt.Fprintf(&b, \"\\n**WARNING:** Found %d reachable vulnerability.\\n\", len(affectingByOSV))\n\t\t} else {\n\t\t\tfmt.Fprintf(&b, \"\\n**WARNING:** Found %d reachable vulnerabilities.\\n\", len(affectingByOSV))\n\t\t}\n\t}\n\tfor id, findings := range affectingByOSV {\n\t\tfix := fixedVersion(findings[0].FixedVersion)\n\t\tpkgs := vulnerablePkgsInfo(findings, useMarkdown)\n\t\tosvEntry := osvs[id]\n\n\t\tif useMarkdown {\n\t\t\tfmt.Fprintf(&b, \"- [**%v**](%v) %v%v\\n%v\\n\", id, href(id), osvEntry.Summary, pkgs, fix)\n\t\t} else {\n\t\t\tfmt.Fprintf(&b, \"  - [%v] %v (%v) %v%v\\n\", id, osvEntry.Summary, href(id), pkgs, fix)\n\t\t}\n\t}\n\tif len(nonaffecting) > 0 {\n\t\tif fromGovulncheck {\n\t\t\tfmt.Fprintf(&b, \"\\n**Note:** The project imports packages with known vulnerabilities, but does not call the vulnerable code.\\n\")\n\t\t} else {\n\t\t\tfmt.Fprintf(&b, \"\\n**Note:** The project imports packages with known vulnerabilities. Use `govulncheck` to check if the project uses vulnerable symbols.\\n\")\n\t\t}\n\t}\n\tfor k, findings := range nonaffectingByOSV {\n\t\tfix := fixedVersion(findings[0].FixedVersion)\n\t\tpkgs := vulnerablePkgsInfo(findings, useMarkdown)\n\t\tosvEntry := osvs[k]\n\n\t\tif useMarkdown {\n\t\t\tfmt.Fprintf(&b, \"- [%v](%v) %v%v\\n%v\\n\", k, href(k), osvEntry.Summary, pkgs, fix)\n\t\t} else {\n\t\t\tfmt.Fprintf(&b, \"  - [%v] %v (%v) %v\\n%v\\n\", k, osvEntry.Summary, href(k), pkgs, fix)\n\t\t}\n\t}\n\tb.WriteString(\"\\n\")\n\treturn b.String()\n}\n\nfunc vulnerablePkgsInfo(findings []*govulncheck.Finding, useMarkdown bool) string {\n\tvar b strings.Builder\n\tseen := map[string]bool{}\n\tfor _, f := range findings {\n\t\tp := f.Trace[0].Package\n\t\tif !seen[p] {\n\t\t\tseen[p] = true\n\t\t\tif useMarkdown {\n\t\t\t\tb.WriteString(\"\\n  * `\")\n\t\t\t} else {\n\t\t\t\tb.WriteString(\"\\n    \")\n\t\t\t}\n\t\t\tb.WriteString(p)\n\t\t\tif useMarkdown {\n\t\t\t\tb.WriteString(\"`\")\n\t\t\t}\n\t\t}\n\t}\n\treturn b.String()\n}\n\nfunc formatExplanation(text string, replaceMap map[module.Version]module.Version, req *modfile.Require, options *settings.Options, isPrivate bool) string {\n\ttext = strings.TrimSuffix(text, \"\\n\")\n\tsplt := strings.Split(text, \"\\n\")\n\tlength := len(splt)\n\n\tvar b strings.Builder\n\n\t// If the explanation is 2 lines, then it is of the form:\n\t// # golang.org/x/text/encoding\n\t// (main module does not need package golang.org/x/text/encoding)\n\tif length == 2 {\n\t\tb.WriteString(splt[1])\n\t\treturn b.String()\n\t}\n\n\timp := splt[length-1] // import path\n\treference := imp\n\t// See golang/go#36998: don't link to modules matching GOPRIVATE.\n\tif !isPrivate && options.PreferredContentFormat == protocol.Markdown {\n\t\ttarget := imp\n\t\tif strings.ToLower(options.LinkTarget) == \"pkg.go.dev\" {\n\t\t\tmod := req.Mod\n\t\t\t// respect the replacement when constructing a module link.\n\t\t\tif m, ok := replaceMap[req.Mod]; ok {\n\t\t\t\t// Have: 'replace A v1.2.3 => A vx.x.x' or 'replace A v1.2.3 => B vx.x.x'.\n\t\t\t\tmod = m\n\t\t\t} else if m, ok := replaceMap[module.Version{Path: req.Mod.Path}]; ok &&\n\t\t\t\t!modfile.IsDirectoryPath(m.Path) { // exclude local replacement.\n\t\t\t\t// Have: 'replace A => A vx.x.x' or 'replace A => B vx.x.x'.\n\t\t\t\tmod = m\n\t\t\t}\n\t\t\ttarget = strings.Replace(target, req.Mod.Path, mod.String(), 1)\n\t\t}\n\t\treference = fmt.Sprintf(\"[%s](%s)\", imp, cache.BuildLink(options.LinkTarget, target, \"\"))\n\t}\n\tb.WriteString(\"This module is necessary because \" + reference + \" is imported in\")\n\n\t// If the explanation is 3 lines, then it is of the form:\n\t// # golang.org/x/tools\n\t// modtest\n\t// golang.org/x/tools/go/packages\n\tif length == 3 {\n\t\tmsg := fmt.Sprintf(\" `%s`.\", splt[1])\n\t\tb.WriteString(msg)\n\t\treturn b.String()\n\t}\n\n\t// If the explanation is more than 3 lines, then it is of the form:\n\t// # golang.org/x/text/language\n\t// rsc.io/quote\n\t// rsc.io/sampler\n\t// golang.org/x/text/language\n\tb.WriteString(\":\\n```text\")\n\tvar dash strings.Builder\n\tfor _, imp := range splt[1 : length-1] {\n\t\tdash.WriteString(\"-\")\n\t\tb.WriteString(\"\\n\" + dash.String() + \" \" + imp)\n\t}\n\tb.WriteString(\"\\n```\")\n\treturn b.String()\n}\n"
  },
  {
    "path": "gopls/internal/mod/inlay_hint.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage mod\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc InlayHint(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, _ protocol.Range) ([]protocol.InlayHint, error) {\n\t// Inlay hints are enabled if the client supports them.\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Compare the version of the module used in the snapshot's\n\t// metadata (i.e. the solution to the MVS constraints computed\n\t// by go list) with the version requested by the module, in\n\t// both cases, taking replaces into account. Produce an\n\t// InlayHint when the version of the module is not the one\n\t// used.\n\n\treplaces := make(map[string]*modfile.Replace)\n\tfor _, x := range pm.File.Replace {\n\t\treplaces[x.Old.Path] = x\n\t}\n\n\trequires := make(map[string]*modfile.Require)\n\tfor _, x := range pm.File.Require {\n\t\trequires[x.Mod.Path] = x\n\t}\n\n\tam, err := snapshot.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar ans []protocol.InlayHint\n\tseen := make(map[string]bool)\n\tfor _, meta := range am {\n\t\tif meta.Module == nil || seen[meta.Module.Path] {\n\t\t\tcontinue\n\t\t}\n\t\tseen[meta.Module.Path] = true\n\t\tmetaVersion := meta.Module.Version\n\t\tif meta.Module.Replace != nil {\n\t\t\tmetaVersion = meta.Module.Replace.Version\n\t\t}\n\t\t// These versions can be blank, as in gopls/go.mod's local replace\n\t\tif oldrepl, ok := replaces[meta.Module.Path]; ok && oldrepl.New.Version != metaVersion {\n\t\t\tih := genHint(oldrepl.Syntax, oldrepl.New.Version, metaVersion, pm.Mapper)\n\t\t\tif ih != nil {\n\t\t\t\tans = append(ans, *ih)\n\t\t\t}\n\t\t} else if oldreq, ok := requires[meta.Module.Path]; ok && oldreq.Mod.Version != metaVersion {\n\t\t\t// maybe it was replaced:\n\t\t\tif _, ok := replaces[meta.Module.Path]; ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tih := genHint(oldreq.Syntax, oldreq.Mod.Version, metaVersion, pm.Mapper)\n\t\t\tif ih != nil {\n\t\t\t\tans = append(ans, *ih)\n\t\t\t}\n\t\t}\n\t}\n\treturn ans, nil\n}\n\nfunc genHint(mline *modfile.Line, oldVersion, newVersion string, m *protocol.Mapper) *protocol.InlayHint {\n\tx := mline.End.Byte // the parser has removed trailing whitespace and comments (see modfile_test.go)\n\tx -= len(mline.Token[len(mline.Token)-1])\n\tline, err := m.OffsetPosition(x)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tpart := protocol.InlayHintLabelPart{\n\t\tValue: newVersion,\n\t\tTooltip: &protocol.OrPTooltipPLabel{\n\t\t\tValue: fmt.Sprintf(\"The build selects version %s rather than go.mod's version %s.\", newVersion, oldVersion),\n\t\t},\n\t}\n\trng, err := m.OffsetRange(x, mline.End.Byte)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tte := protocol.TextEdit{\n\t\tRange:   rng,\n\t\tNewText: newVersion,\n\t}\n\treturn &protocol.InlayHint{\n\t\tPosition:     line,\n\t\tLabel:        []protocol.InlayHintLabelPart{part},\n\t\tKind:         protocol.Parameter,\n\t\tPaddingRight: true,\n\t\tTextEdits:    []protocol.TextEdit{te},\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/mod/references.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mod\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"maps\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// References returns the locations of imports referenced by a required module\nfunc References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, params *protocol.ReferenceParams) ([]protocol.Location, error) {\n\t// Th go.mod file will contain a module name (e.g., golang.org/x/tools)\n\t// but the import statements contain package names\n\t// (e.g., golang.org/x/tools/internal/astutil).\n\t// The code has to avoid imports from submodules, like golang.org/x/tools/gopls/internal/file\n\t// so simple string matching would not work.\n\n\t// find modpath, the module path the user wants the references for\n\tgomod, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif gomod.File == nil {\n\t\treturn nil, fmt.Errorf(\"mysterious parse failure %s\", fh.URI().Path())\n\t}\n\t// protocol.ReferenceParams contains both a Position and a Range.\n\t// The Range would contain the Position, so use Position.\n\toffset, err := gomod.Mapper.PositionOffset(params.Position)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar modpath string\n\tfor _, req := range gomod.File.Require {\n\t\tif req.Syntax.Start.Byte <= offset && offset <= req.Syntax.End.Byte {\n\t\t\tmodpath = req.Mod.Path\n\t\t\tbreak\n\t\t}\n\t}\n\tif modpath == \"\" {\n\t\t// nothing to report\n\t\treturn nil, nil\n\t}\n\n\tlocs := make(map[protocol.Location]bool)\n\n\tincludeDecl := params.Context.IncludeDeclaration\n\t// A. find the IDs of all packages in the module that was required\n\tids := make(map[metadata.PackageID]bool)\n\tg := snapshot.MetadataGraph()\n\tfor _, pkg := range g.Packages {\n\t\tif pkg.Module != nil && pkg.Module.Path == modpath {\n\t\t\tids[pkg.ID] = true\n\t\t\t// once, if the definition is needed\n\t\t\tif includeDecl {\n\t\t\t\tfh, err := snapshot.ReadFile(ctx, protocol.URIFromPath(pkg.Module.GoMod))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tparsed, err := snapshot.ParseMod(ctx, fh)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tif parsed.File != nil && parsed.File.Module != nil {\n\t\t\t\t\tstart, end := parsed.File.Module.Syntax.Span()\n\t\t\t\t\tloc, err := parsed.Mapper.OffsetLocation(start.Byte, end.Byte)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t\tlocs[loc] = true\n\t\t\t\t\tincludeDecl = false // no need to do this again\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// B. find all the importers of these packages that are in the go.mod's module\n\turis := make(map[protocol.DocumentURI]*metadata.Package)\n\tfor id := range ids {\n\t\tfor _, importer := range g.ImportedBy[id] {\n\t\t\tif importer.Module.GoMod != gomod.URI.Path() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// files to be read.\n\t\t\t// at least one of them has an import to be reported.\n\t\t\tfor _, uri := range importer.CompiledGoFiles {\n\t\t\t\tupkgs := g.ForFile[uri]\n\t\t\t\tfor _, upkg := range upkgs {\n\t\t\t\t\tif upkg.ID == importer.ID {\n\t\t\t\t\t\turis[uri] = importer // may overwrite, but it doesn't matter\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// C. for each of the uris, pick out the locs of imports from the requested module\n\tfor uri := range uris {\n\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Header) // Header promotes cache hits\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\txpkg := uris[uri]\n\t\tfor _, spec := range pgf.File.Imports {\n\t\t\timportPath := metadata.UnquoteImportPath(spec)\n\t\t\tif ids[xpkg.DepsByImpPath[importPath]] {\n\t\t\t\tloc, err := pgf.NodeLocation(spec.Path)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tlocs[loc] = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\n\tans := slices.SortedFunc(maps.Keys(locs), protocol.CompareLocation)\n\treturn ans, nil\n}\n"
  },
  {
    "path": "gopls/internal/progress/progress.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The progress package defines utilities for reporting the progress\n// of long-running operations using features of the LSP client\n// interface such as Progress and ShowMessage.\npackage progress\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// NewTracker returns a new Tracker that reports progress to the\n// specified client.\nfunc NewTracker(client protocol.Client) *Tracker {\n\treturn &Tracker{\n\t\tclient:     client,\n\t\tinProgress: make(map[protocol.ProgressToken]*WorkDone),\n\t}\n}\n\n// A Tracker reports the progress of a long-running operation to an LSP client.\ntype Tracker struct {\n\tclient                   protocol.Client\n\tsupportsWorkDoneProgress bool\n\n\tmu         sync.Mutex\n\tinProgress map[protocol.ProgressToken]*WorkDone\n}\n\n// SetSupportsWorkDoneProgress sets whether the client supports \"work done\"\n// progress reporting. It must be set before using the tracker.\n//\n// TODO(rfindley): fix this broken initialization pattern.\n// Also: do we actually need the fall-back progress behavior using ShowMessage?\n// Surely ShowMessage notifications are too noisy to be worthwhile.\nfunc (t *Tracker) SetSupportsWorkDoneProgress(b bool) {\n\tt.supportsWorkDoneProgress = b\n}\n\n// SupportsWorkDoneProgress reports whether the tracker supports work done\n// progress reporting.\nfunc (t *Tracker) SupportsWorkDoneProgress() bool {\n\treturn t.supportsWorkDoneProgress\n}\n\n// Start notifies the client of work being done on the server. It uses either\n// ShowMessage RPCs or $/progress messages, depending on the capabilities of\n// the client.  The returned WorkDone handle may be used to report incremental\n// progress, and to report work completion. In particular, it is an error to\n// call start and not call end(...) on the returned WorkDone handle.\n//\n// If token is empty, a token will be randomly generated.\n//\n// The progress item is considered cancellable if the given cancel func is\n// non-nil. In this case, cancel is called when the work done\n//\n// Example:\n//\n//\tfunc Generate(ctx) (err error) {\n//\t  ctx, cancel := context.WithCancel(ctx)\n//\t  defer cancel()\n//\t  work := s.progress.start(ctx, \"generate\", \"running go generate\", cancel)\n//\t  defer func() {\n//\t    if err != nil {\n//\t      work.end(ctx, fmt.Sprintf(\"generate failed: %v\", err))\n//\t    } else {\n//\t      work.end(ctx, \"done\")\n//\t    }\n//\t  }()\n//\t  // Do the work...\n//\t}\nfunc (t *Tracker) Start(ctx context.Context, title, message string, token protocol.ProgressToken, cancel func()) *WorkDone {\n\tctx = xcontext.Detach(ctx) // progress messages should not be cancelled\n\twd := &WorkDone{\n\t\tclient: t.client,\n\t\ttoken:  token,\n\t\tcancel: cancel,\n\t}\n\tif !t.supportsWorkDoneProgress {\n\t\t// Previous iterations of this fallback attempted to retain cancellation\n\t\t// support by using ShowMessageCommand with a 'Cancel' button, but this is\n\t\t// not ideal as the 'Cancel' dialog stays open even after the command\n\t\t// completes.\n\t\t//\n\t\t// Just show a simple message. Clients can implement workDone progress\n\t\t// reporting to get cancellation support.\n\t\tif err := wd.client.ShowMessage(ctx, &protocol.ShowMessageParams{\n\t\t\tType:    protocol.Log,\n\t\t\tMessage: message,\n\t\t}); err != nil {\n\t\t\tevent.Error(ctx, \"showing start message for \"+title, err)\n\t\t}\n\t\treturn wd\n\t}\n\tif wd.token == nil {\n\t\ttoken = strconv.FormatInt(rand.Int63(), 10)\n\t\terr := wd.client.WorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{\n\t\t\tToken: token,\n\t\t})\n\t\tif err != nil {\n\t\t\twd.err = err\n\t\t\tevent.Error(ctx, \"starting work for \"+title, err)\n\t\t\treturn wd\n\t\t}\n\t\twd.token = token\n\t}\n\t// At this point we have a token that the client knows about. Store the token\n\t// before starting work.\n\tt.mu.Lock()\n\tt.inProgress[wd.token] = wd\n\tt.mu.Unlock()\n\twd.cleanup = func() {\n\t\tt.mu.Lock()\n\t\tdelete(t.inProgress, token)\n\t\tt.mu.Unlock()\n\t}\n\terr := wd.client.Progress(ctx, &protocol.ProgressParams{\n\t\tToken: wd.token,\n\t\tValue: &protocol.WorkDoneProgressBegin{\n\t\t\tKind:        \"begin\",\n\t\t\tCancellable: wd.cancel != nil,\n\t\t\tMessage:     message,\n\t\t\tTitle:       title,\n\t\t},\n\t})\n\tif err != nil {\n\t\tevent.Error(ctx, \"progress begin\", err)\n\t}\n\treturn wd\n}\n\nfunc (t *Tracker) Cancel(token protocol.ProgressToken) error {\n\tt.mu.Lock()\n\tdefer t.mu.Unlock()\n\twd, ok := t.inProgress[token]\n\tif !ok {\n\t\treturn fmt.Errorf(\"token %q not found in progress\", token)\n\t}\n\tif wd.cancel == nil {\n\t\treturn fmt.Errorf(\"work %q is not cancellable\", token)\n\t}\n\twd.doCancel()\n\treturn nil\n}\n\n// WorkDone represents a unit of work that is reported to the client via the\n// progress API.\ntype WorkDone struct {\n\tclient protocol.Client\n\t// If token is nil, this workDone object uses the ShowMessage API, rather\n\t// than $/progress.\n\ttoken protocol.ProgressToken\n\t// err is set if progress reporting is broken for some reason (for example,\n\t// if there was an initial error creating a token).\n\terr error\n\n\tcancelMu  sync.Mutex\n\tcancelled bool\n\tcancel    func()\n\n\tcleanup func()\n}\n\nfunc (wd *WorkDone) Token() protocol.ProgressToken {\n\treturn wd.token\n}\n\nfunc (wd *WorkDone) doCancel() {\n\twd.cancelMu.Lock()\n\tdefer wd.cancelMu.Unlock()\n\tif !wd.cancelled {\n\t\twd.cancel()\n\t}\n}\n\n// Report reports an update on WorkDone report back to the client.\nfunc (wd *WorkDone) Report(ctx context.Context, message string, fraction float64) {\n\tctx = xcontext.Detach(ctx) // progress messages should not be cancelled\n\tif wd == nil {\n\t\treturn\n\t}\n\twd.cancelMu.Lock()\n\tcancelled := wd.cancelled\n\twd.cancelMu.Unlock()\n\tif cancelled {\n\t\treturn\n\t}\n\tif wd.err != nil || wd.token == nil {\n\t\t// Not using the workDone API, so we do nothing. It would be far too spammy\n\t\t// to send incremental messages.\n\t\treturn\n\t}\n\tmessage = strings.TrimSuffix(message, \"\\n\")\n\tpercentage := uint32(100 * fraction)\n\terr := wd.client.Progress(ctx, &protocol.ProgressParams{\n\t\tToken: wd.token,\n\t\tValue: &protocol.WorkDoneProgressReport{\n\t\t\tKind: \"report\",\n\t\t\t// Note that in the LSP spec, the value of Cancellable may be changed to\n\t\t\t// control whether the cancel button in the UI is enabled. Since we don't\n\t\t\t// yet use this feature, the value is kept constant here.\n\t\t\tCancellable: wd.cancel != nil,\n\t\t\tMessage:     message,\n\t\t\tPercentage:  &percentage,\n\t\t},\n\t})\n\tif err != nil {\n\t\tevent.Error(ctx, \"reporting progress\", err)\n\t}\n}\n\n// End reports a workdone completion back to the client.\nfunc (wd *WorkDone) End(ctx context.Context, message string) {\n\tctx = xcontext.Detach(ctx) // progress messages should not be cancelled\n\tif wd == nil {\n\t\treturn\n\t}\n\tvar err error\n\tswitch {\n\tcase wd.err != nil:\n\t\t// There is a prior error.\n\tcase wd.token == nil:\n\t\t// We're falling back to message-based reporting.\n\t\terr = wd.client.ShowMessage(ctx, &protocol.ShowMessageParams{\n\t\t\tType:    protocol.Info,\n\t\t\tMessage: message,\n\t\t})\n\tdefault:\n\t\terr = wd.client.Progress(ctx, &protocol.ProgressParams{\n\t\t\tToken: wd.token,\n\t\t\tValue: &protocol.WorkDoneProgressEnd{\n\t\t\t\tKind:    \"end\",\n\t\t\t\tMessage: message,\n\t\t\t},\n\t\t})\n\t}\n\tif err != nil {\n\t\tevent.Error(ctx, \"ending work\", err)\n\t}\n\tif wd.cleanup != nil {\n\t\twd.cleanup()\n\t}\n}\n\n// NewEventWriter returns an [io.Writer] that calls the context's\n// event printer for each data payload, wrapping it with the\n// operation=generate tag to distinguish its logs from others.\nfunc NewEventWriter(ctx context.Context, operation string) io.Writer {\n\treturn &eventWriter{ctx: ctx, operation: operation}\n}\n\ntype eventWriter struct {\n\tctx       context.Context\n\toperation string\n}\n\nfunc (ew *eventWriter) Write(p []byte) (n int, err error) {\n\tevent.Log(ew.ctx, string(p), label.Operation.Of(ew.operation))\n\treturn len(p), nil\n}\n\n// NewWorkDoneWriter wraps a WorkDone handle to provide a Writer interface,\n// so that workDone reporting can more easily be hooked into commands.\nfunc NewWorkDoneWriter(ctx context.Context, wd *WorkDone) io.Writer {\n\treturn &workDoneWriter{ctx: ctx, wd: wd}\n}\n\n// workDoneWriter wraps a workDone handle to provide a Writer interface,\n// so that workDone reporting can more easily be hooked into commands.\ntype workDoneWriter struct {\n\t// In order to implement the io.Writer interface, we must close over ctx.\n\tctx context.Context\n\twd  *WorkDone\n}\n\nfunc (wdw *workDoneWriter) Write(p []byte) (n int, err error) {\n\twdw.wd.Report(wdw.ctx, string(p), 0)\n\t// Don't fail just because of a failure to report progress.\n\treturn len(p), nil\n}\n"
  },
  {
    "path": "gopls/internal/progress/progress_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage progress\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\ntype fakeClient struct {\n\tprotocol.Client\n\n\ttoken protocol.ProgressToken\n\n\tmu                                        sync.Mutex\n\tcreated, begun, reported, messages, ended int\n}\n\nfunc (c *fakeClient) checkToken(token protocol.ProgressToken) {\n\tif token == nil {\n\t\tpanic(\"nil token in progress message\")\n\t}\n\tif c.token != nil && c.token != token {\n\t\tpanic(fmt.Errorf(\"invalid token in progress message: got %v, want %v\", token, c.token))\n\t}\n}\n\nfunc (c *fakeClient) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.checkToken(params.Token)\n\tc.created++\n\treturn nil\n}\n\nfunc (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.checkToken(params.Token)\n\tswitch params.Value.(type) {\n\tcase *protocol.WorkDoneProgressBegin:\n\t\tc.begun++\n\tcase *protocol.WorkDoneProgressReport:\n\t\tc.reported++\n\tcase *protocol.WorkDoneProgressEnd:\n\t\tc.ended++\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unknown progress value %T\", params.Value))\n\t}\n\treturn nil\n}\n\nfunc (c *fakeClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.messages++\n\treturn nil\n}\n\nfunc setup() (*Tracker, *fakeClient) {\n\tc := &fakeClient{}\n\ttracker := NewTracker(c)\n\ttracker.SetSupportsWorkDoneProgress(true)\n\treturn tracker, c\n}\n\nfunc TestProgressTracker_Reporting(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname                                            string\n\t\tsupported                                       bool\n\t\ttoken                                           protocol.ProgressToken\n\t\twantReported, wantCreated, wantBegun, wantEnded int\n\t\twantMessages                                    int\n\t}{\n\t\t{\n\t\t\tname:         \"unsupported\",\n\t\t\twantMessages: 2,\n\t\t},\n\t\t{\n\t\t\tname:         \"random token\",\n\t\t\tsupported:    true,\n\t\t\twantCreated:  1,\n\t\t\twantBegun:    1,\n\t\t\twantReported: 1,\n\t\t\twantEnded:    1,\n\t\t},\n\t\t{\n\t\t\tname:         \"string token\",\n\t\t\tsupported:    true,\n\t\t\ttoken:        \"token\",\n\t\t\twantBegun:    1,\n\t\t\twantReported: 1,\n\t\t\twantEnded:    1,\n\t\t},\n\t\t{\n\t\t\tname:         \"numeric token\",\n\t\t\tsupported:    true,\n\t\t\ttoken:        1,\n\t\t\twantReported: 1,\n\t\t\twantBegun:    1,\n\t\t\twantEnded:    1,\n\t\t},\n\t} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\ttracker, client := setup()\n\t\t\tctx := t.Context()\n\t\t\ttracker.supportsWorkDoneProgress = test.supported\n\t\t\twork := tracker.Start(ctx, \"work\", \"message\", test.token, nil)\n\t\t\tclient.mu.Lock()\n\t\t\tgotCreated, gotBegun := client.created, client.begun\n\t\t\tclient.mu.Unlock()\n\t\t\tif gotCreated != test.wantCreated {\n\t\t\t\tt.Errorf(\"got %d created tokens, want %d\", gotCreated, test.wantCreated)\n\t\t\t}\n\t\t\tif gotBegun != test.wantBegun {\n\t\t\t\tt.Errorf(\"got %d work begun, want %d\", gotBegun, test.wantBegun)\n\t\t\t}\n\t\t\t// Ignore errors: this is just testing the reporting behavior.\n\t\t\twork.Report(ctx, \"report\", 0.5)\n\t\t\tclient.mu.Lock()\n\t\t\tgotReported := client.reported\n\t\t\tclient.mu.Unlock()\n\t\t\tif gotReported != test.wantReported {\n\t\t\t\tt.Errorf(\"got %d progress reports, want %d\", gotReported, test.wantCreated)\n\t\t\t}\n\t\t\twork.End(ctx, \"done\")\n\t\t\tclient.mu.Lock()\n\t\t\tgotEnded, gotMessages := client.ended, client.messages\n\t\t\tclient.mu.Unlock()\n\t\t\tif gotEnded != test.wantEnded {\n\t\t\t\tt.Errorf(\"got %d ended reports, want %d\", gotEnded, test.wantEnded)\n\t\t\t}\n\t\t\tif gotMessages != test.wantMessages {\n\t\t\t\tt.Errorf(\"got %d messages, want %d\", gotMessages, test.wantMessages)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestProgressTracker_Cancellation(t *testing.T) {\n\tfor _, token := range []protocol.ProgressToken{nil, 1, \"a\"} {\n\t\ttracker, _ := setup()\n\t\tvar canceled bool\n\t\tcancel := func() { canceled = true }\n\t\twork := tracker.Start(t.Context(), \"work\", \"message\", token, cancel)\n\t\tif err := tracker.Cancel(work.Token()); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !canceled {\n\t\t\tt.Errorf(\"tracker.cancel(...): cancel not called\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/command_gen.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Don't include this file during code generation, or it will break the build\n// if existing interface methods have been modified.\n//go:build !generate\n// +build !generate\n\n// Code generated by gen.go from gopls/internal/protocol/command. DO NOT EDIT.\n\npackage command\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// Symbolic names for gopls commands, corresponding to methods of [Interface].\n//\n// The string value is used in the Command field of protocol.Command.\n// These commands may be obtained from a CodeLens or CodeAction request\n// and executed by an ExecuteCommand request.\nconst (\n\tAddDependency           Command = \"gopls.add_dependency\"\n\tAddImport               Command = \"gopls.add_import\"\n\tAddTelemetryCounters    Command = \"gopls.add_telemetry_counters\"\n\tAddTest                 Command = \"gopls.add_test\"\n\tApplyFix                Command = \"gopls.apply_fix\"\n\tAssembly                Command = \"gopls.assembly\"\n\tChangeSignature         Command = \"gopls.change_signature\"\n\tCheckUpgrades           Command = \"gopls.check_upgrades\"\n\tClientOpenURL           Command = \"gopls.client_open_url\"\n\tDiagnoseFiles           Command = \"gopls.diagnose_files\"\n\tDoc                     Command = \"gopls.doc\"\n\tEditGoDirective         Command = \"gopls.edit_go_directive\"\n\tExtractToNewFile        Command = \"gopls.extract_to_new_file\"\n\tFetchVulncheckResult    Command = \"gopls.fetch_vulncheck_result\"\n\tFreeSymbols             Command = \"gopls.free_symbols\"\n\tGCDetails               Command = \"gopls.gc_details\"\n\tGenerate                Command = \"gopls.generate\"\n\tGoGetPackage            Command = \"gopls.go_get_package\"\n\tListImports             Command = \"gopls.list_imports\"\n\tListKnownPackages       Command = \"gopls.list_known_packages\"\n\tLSP                     Command = \"gopls.lsp\"\n\tMaybePromptForTelemetry Command = \"gopls.maybe_prompt_for_telemetry\"\n\tMemStats                Command = \"gopls.mem_stats\"\n\tModifyTags              Command = \"gopls.modify_tags\"\n\tModules                 Command = \"gopls.modules\"\n\tMoveType                Command = \"gopls.move_type\"\n\tPackageSymbols          Command = \"gopls.package_symbols\"\n\tPackages                Command = \"gopls.packages\"\n\tRegenerateCgo           Command = \"gopls.regenerate_cgo\"\n\tRemoveDependency        Command = \"gopls.remove_dependency\"\n\tResetGoModDiagnostics   Command = \"gopls.reset_go_mod_diagnostics\"\n\tRunGoWorkCommand        Command = \"gopls.run_go_work_command\"\n\tRunGovulncheck          Command = \"gopls.run_govulncheck\"\n\tRunTests                Command = \"gopls.run_tests\"\n\tScanImports             Command = \"gopls.scan_imports\"\n\tSplitPackage            Command = \"gopls.split_package\"\n\tStartDebugging          Command = \"gopls.start_debugging\"\n\tStartProfile            Command = \"gopls.start_profile\"\n\tStopProfile             Command = \"gopls.stop_profile\"\n\tTidy                    Command = \"gopls.tidy\"\n\tUpdateGoSum             Command = \"gopls.update_go_sum\"\n\tUpgradeDependency       Command = \"gopls.upgrade_dependency\"\n\tVendor                  Command = \"gopls.vendor\"\n\tViews                   Command = \"gopls.views\"\n\tVulncheck               Command = \"gopls.vulncheck\"\n\tWorkspaceStats          Command = \"gopls.workspace_stats\"\n)\n\nvar Commands = []Command{\n\tAddDependency,\n\tAddImport,\n\tAddTelemetryCounters,\n\tAddTest,\n\tApplyFix,\n\tAssembly,\n\tChangeSignature,\n\tCheckUpgrades,\n\tClientOpenURL,\n\tDiagnoseFiles,\n\tDoc,\n\tEditGoDirective,\n\tExtractToNewFile,\n\tFetchVulncheckResult,\n\tFreeSymbols,\n\tGCDetails,\n\tGenerate,\n\tGoGetPackage,\n\tListImports,\n\tListKnownPackages,\n\tLSP,\n\tMaybePromptForTelemetry,\n\tMemStats,\n\tModifyTags,\n\tModules,\n\tMoveType,\n\tPackageSymbols,\n\tPackages,\n\tRegenerateCgo,\n\tRemoveDependency,\n\tResetGoModDiagnostics,\n\tRunGoWorkCommand,\n\tRunGovulncheck,\n\tRunTests,\n\tScanImports,\n\tSplitPackage,\n\tStartDebugging,\n\tStartProfile,\n\tStopProfile,\n\tTidy,\n\tUpdateGoSum,\n\tUpgradeDependency,\n\tVendor,\n\tViews,\n\tVulncheck,\n\tWorkspaceStats,\n}\n\nfunc Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (any, error) {\n\tswitch Command(params.Command) {\n\tcase AddDependency:\n\t\tvar a0 DependencyArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.AddDependency(ctx, a0)\n\tcase AddImport:\n\t\tvar a0 AddImportArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.AddImport(ctx, a0)\n\tcase AddTelemetryCounters:\n\t\tvar a0 AddTelemetryCountersArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.AddTelemetryCounters(ctx, a0)\n\tcase AddTest:\n\t\tvar a0 protocol.Location\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.AddTest(ctx, a0)\n\tcase ApplyFix:\n\t\tvar a0 ApplyFixArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.ApplyFix(ctx, a0)\n\tcase Assembly:\n\t\tvar a0 string\n\t\tvar a1 string\n\t\tvar a2 string\n\t\tif err := UnmarshalArgs(params.Arguments, &a0, &a1, &a2); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.Assembly(ctx, a0, a1, a2)\n\tcase ChangeSignature:\n\t\tvar a0 ChangeSignatureArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.ChangeSignature(ctx, a0)\n\tcase CheckUpgrades:\n\t\tvar a0 CheckUpgradesArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.CheckUpgrades(ctx, a0)\n\tcase ClientOpenURL:\n\t\tvar a0 string\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.ClientOpenURL(ctx, a0)\n\tcase DiagnoseFiles:\n\t\tvar a0 DiagnoseFilesArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.DiagnoseFiles(ctx, a0)\n\tcase Doc:\n\t\tvar a0 DocArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.Doc(ctx, a0)\n\tcase EditGoDirective:\n\t\tvar a0 EditGoDirectiveArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.EditGoDirective(ctx, a0)\n\tcase ExtractToNewFile:\n\t\tvar a0 protocol.Location\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.ExtractToNewFile(ctx, a0)\n\tcase FetchVulncheckResult:\n\t\tvar a0 URIArg\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.FetchVulncheckResult(ctx, a0)\n\tcase FreeSymbols:\n\t\tvar a0 string\n\t\tvar a1 protocol.Location\n\t\tif err := UnmarshalArgs(params.Arguments, &a0, &a1); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.FreeSymbols(ctx, a0, a1)\n\tcase GCDetails:\n\t\tvar a0 protocol.DocumentURI\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.GCDetails(ctx, a0)\n\tcase Generate:\n\t\tvar a0 GenerateArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.Generate(ctx, a0)\n\tcase GoGetPackage:\n\t\tvar a0 GoGetPackageArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.GoGetPackage(ctx, a0)\n\tcase ListImports:\n\t\tvar a0 URIArg\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.ListImports(ctx, a0)\n\tcase ListKnownPackages:\n\t\tvar a0 URIArg\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.ListKnownPackages(ctx, a0)\n\tcase LSP:\n\t\tvar a0 LSPArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.LSP(ctx, a0)\n\tcase MaybePromptForTelemetry:\n\t\treturn nil, s.MaybePromptForTelemetry(ctx)\n\tcase MemStats:\n\t\treturn s.MemStats(ctx)\n\tcase ModifyTags:\n\t\tvar a0 ModifyTagsArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.ModifyTags(ctx, a0)\n\tcase Modules:\n\t\tvar a0 ModulesArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.Modules(ctx, a0)\n\tcase MoveType:\n\t\tvar a0 MoveTypeArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.MoveType(ctx, a0)\n\tcase PackageSymbols:\n\t\tvar a0 PackageSymbolsArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.PackageSymbols(ctx, a0)\n\tcase Packages:\n\t\tvar a0 PackagesArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.Packages(ctx, a0)\n\tcase RegenerateCgo:\n\t\tvar a0 URIArg\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.RegenerateCgo(ctx, a0)\n\tcase RemoveDependency:\n\t\tvar a0 RemoveDependencyArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.RemoveDependency(ctx, a0)\n\tcase ResetGoModDiagnostics:\n\t\tvar a0 ResetGoModDiagnosticsArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.ResetGoModDiagnostics(ctx, a0)\n\tcase RunGoWorkCommand:\n\t\tvar a0 RunGoWorkArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.RunGoWorkCommand(ctx, a0)\n\tcase RunGovulncheck:\n\t\tvar a0 VulncheckArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.RunGovulncheck(ctx, a0)\n\tcase RunTests:\n\t\tvar a0 RunTestsArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.RunTests(ctx, a0)\n\tcase ScanImports:\n\t\treturn nil, s.ScanImports(ctx)\n\tcase SplitPackage:\n\t\tvar a0 string\n\t\tvar a1 string\n\t\tif err := UnmarshalArgs(params.Arguments, &a0, &a1); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.SplitPackage(ctx, a0, a1)\n\tcase StartDebugging:\n\t\tvar a0 DebuggingArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.StartDebugging(ctx, a0)\n\tcase StartProfile:\n\t\tvar a0 StartProfileArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.StartProfile(ctx, a0)\n\tcase StopProfile:\n\t\tvar a0 StopProfileArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.StopProfile(ctx, a0)\n\tcase Tidy:\n\t\tvar a0 URIArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.Tidy(ctx, a0)\n\tcase UpdateGoSum:\n\t\tvar a0 URIArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.UpdateGoSum(ctx, a0)\n\tcase UpgradeDependency:\n\t\tvar a0 DependencyArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.UpgradeDependency(ctx, a0)\n\tcase Vendor:\n\t\tvar a0 URIArg\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, s.Vendor(ctx, a0)\n\tcase Views:\n\t\treturn s.Views(ctx)\n\tcase Vulncheck:\n\t\tvar a0 VulncheckArgs\n\t\tif err := UnmarshalArgs(params.Arguments, &a0); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s.Vulncheck(ctx, a0)\n\tcase WorkspaceStats:\n\t\treturn s.WorkspaceStats(ctx)\n\t}\n\treturn nil, fmt.Errorf(\"unsupported command %q\", params.Command)\n}\n\nfunc NewAddDependencyCommand(title string, a0 DependencyArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   AddDependency.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewAddImportCommand(title string, a0 AddImportArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   AddImport.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewAddTelemetryCountersCommand(title string, a0 AddTelemetryCountersArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   AddTelemetryCounters.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewAddTestCommand(title string, a0 protocol.Location) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   AddTest.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewApplyFixCommand(title string, a0 ApplyFixArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ApplyFix.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewAssemblyCommand(title string, a0 string, a1 string, a2 string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Assembly.String(),\n\t\tArguments: MustMarshalArgs(a0, a1, a2),\n\t}\n}\n\nfunc NewChangeSignatureCommand(title string, a0 ChangeSignatureArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ChangeSignature.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewCheckUpgradesCommand(title string, a0 CheckUpgradesArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   CheckUpgrades.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewClientOpenURLCommand(title string, a0 string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ClientOpenURL.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewDiagnoseFilesCommand(title string, a0 DiagnoseFilesArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   DiagnoseFiles.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewDocCommand(title string, a0 DocArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Doc.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewEditGoDirectiveCommand(title string, a0 EditGoDirectiveArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   EditGoDirective.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewExtractToNewFileCommand(title string, a0 protocol.Location) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ExtractToNewFile.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewFetchVulncheckResultCommand(title string, a0 URIArg) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   FetchVulncheckResult.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewFreeSymbolsCommand(title string, a0 string, a1 protocol.Location) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   FreeSymbols.String(),\n\t\tArguments: MustMarshalArgs(a0, a1),\n\t}\n}\n\nfunc NewGCDetailsCommand(title string, a0 protocol.DocumentURI) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   GCDetails.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewGenerateCommand(title string, a0 GenerateArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Generate.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewGoGetPackageCommand(title string, a0 GoGetPackageArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   GoGetPackage.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewListImportsCommand(title string, a0 URIArg) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ListImports.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewListKnownPackagesCommand(title string, a0 URIArg) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ListKnownPackages.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewLSPCommand(title string, a0 LSPArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   LSP.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewMaybePromptForTelemetryCommand(title string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   MaybePromptForTelemetry.String(),\n\t\tArguments: MustMarshalArgs(),\n\t}\n}\n\nfunc NewMemStatsCommand(title string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   MemStats.String(),\n\t\tArguments: MustMarshalArgs(),\n\t}\n}\n\nfunc NewModifyTagsCommand(title string, a0 ModifyTagsArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ModifyTags.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewModulesCommand(title string, a0 ModulesArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Modules.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewMoveTypeCommand(title string, a0 MoveTypeArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   MoveType.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewPackageSymbolsCommand(title string, a0 PackageSymbolsArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   PackageSymbols.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewPackagesCommand(title string, a0 PackagesArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Packages.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewRegenerateCgoCommand(title string, a0 URIArg) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   RegenerateCgo.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewRemoveDependencyCommand(title string, a0 RemoveDependencyArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   RemoveDependency.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewResetGoModDiagnosticsCommand(title string, a0 ResetGoModDiagnosticsArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ResetGoModDiagnostics.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewRunGoWorkCommandCommand(title string, a0 RunGoWorkArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   RunGoWorkCommand.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewRunGovulncheckCommand(title string, a0 VulncheckArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   RunGovulncheck.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewRunTestsCommand(title string, a0 RunTestsArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   RunTests.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewScanImportsCommand(title string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   ScanImports.String(),\n\t\tArguments: MustMarshalArgs(),\n\t}\n}\n\nfunc NewSplitPackageCommand(title string, a0 string, a1 string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   SplitPackage.String(),\n\t\tArguments: MustMarshalArgs(a0, a1),\n\t}\n}\n\nfunc NewStartDebuggingCommand(title string, a0 DebuggingArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   StartDebugging.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewStartProfileCommand(title string, a0 StartProfileArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   StartProfile.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewStopProfileCommand(title string, a0 StopProfileArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   StopProfile.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewTidyCommand(title string, a0 URIArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Tidy.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewUpdateGoSumCommand(title string, a0 URIArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   UpdateGoSum.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewUpgradeDependencyCommand(title string, a0 DependencyArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   UpgradeDependency.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewVendorCommand(title string, a0 URIArg) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Vendor.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewViewsCommand(title string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Views.String(),\n\t\tArguments: MustMarshalArgs(),\n\t}\n}\n\nfunc NewVulncheckCommand(title string, a0 VulncheckArgs) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   Vulncheck.String(),\n\t\tArguments: MustMarshalArgs(a0),\n\t}\n}\n\nfunc NewWorkspaceStatsCommand(title string) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle:     title,\n\t\tCommand:   WorkspaceStats.String(),\n\t\tArguments: MustMarshalArgs(),\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/commandmeta/meta.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package commandmeta provides metadata about LSP commands, by\n// statically analyzing the command.Interface type.\n//\n// It is used to generate JSONRPC dispatch and marshaling.\n// TODO(adonovan): combine with gopls/internal/protocol/command/gen.\npackage commandmeta\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/packages\"\n\t// (does not depend on gopls itself)\n)\n\n// A Command describes a workspace/executeCommand extension command.\ntype Command struct {\n\tMethodName string // e.g. \"RunTests\"\n\tName       string // e.g. \"gopls.run_tests\"\n\tTitle      string\n\tDoc        string\n\tArgs       []*Field\n\tResult     *Field\n}\n\ntype Field struct {\n\tName     string\n\tDoc      string\n\tJSONTag  string\n\tType     types.Type\n\tFieldMod string\n\t// In some circumstances, we may want to recursively load additional field\n\t// descriptors for fields of struct types, documenting their internals.\n\tFields []*Field\n}\n\n// Load returns a description of the workspace/executeCommand commands\n// supported by gopls based on static analysis of the command.Interface type.\nfunc Load() ([]*Command, error) {\n\tpkgs, err := packages.Load(\n\t\t&packages.Config{\n\t\t\tMode:       packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,\n\t\t\tBuildFlags: []string{\"-tags=generate\"},\n\t\t},\n\t\t\"golang.org/x/tools/gopls/internal/protocol/command\",\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"packages.Load: %v\", err)\n\t}\n\tpkg := pkgs[0]\n\tif len(pkg.Errors) > 0 {\n\t\treturn nil, pkg.Errors[0]\n\t}\n\n\t// command.Interface\n\tobj := pkg.Types.Scope().Lookup(\"Interface\").Type().Underlying().(*types.Interface)\n\n\t// Load command metadata corresponding to each interface method.\n\tvar commands []*Command\n\tloader := fieldLoader{make(map[types.Object]*Field)}\n\tfor m := range obj.Methods() {\n\t\tc, err := loader.loadMethod(pkg, m)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"loading %s: %v\", m.Name(), err)\n\t\t}\n\t\tcommands = append(commands, c)\n\t}\n\n\t// Sort commands for deterministic results.\n\tslices.SortFunc(commands, func(a, b *Command) int {\n\t\treturn strings.Compare(a.Name, b.Name)\n\t})\n\treturn commands, nil\n}\n\n// fieldLoader loads field information, memoizing results to prevent infinite\n// recursion.\ntype fieldLoader struct {\n\tloaded map[types.Object]*Field\n}\n\nvar universeError = types.Universe.Lookup(\"error\").Type()\n\nfunc (l *fieldLoader) loadMethod(pkg *packages.Package, m *types.Func) (*Command, error) {\n\tnode, err := findField(pkg, m.Pos())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttitle, doc := splitDoc(node.Doc.Text())\n\tc := &Command{\n\t\tMethodName: m.Name(),\n\t\tName:       lspName(m.Name()),\n\t\tDoc:        doc,\n\t\tTitle:      title,\n\t}\n\tsig := m.Type().Underlying().(*types.Signature)\n\trlen := sig.Results().Len()\n\tif rlen > 2 || rlen == 0 {\n\t\treturn nil, fmt.Errorf(\"must have 1 or 2 returns, got %d\", rlen)\n\t}\n\tfinalResult := sig.Results().At(rlen - 1)\n\tif !types.Identical(finalResult.Type(), universeError) {\n\t\treturn nil, fmt.Errorf(\"final return must be error\")\n\t}\n\tif rlen == 2 {\n\t\tobj := sig.Results().At(0)\n\t\tc.Result, err = l.loadField(pkg, obj, \"\", \"\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\tobj := sig.Params().At(i)\n\t\tfld, err := l.loadField(pkg, obj, \"\", \"\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif i == 0 {\n\t\t\t// Lazy check that the first argument is a context. We could relax this,\n\t\t\t// but then the generated code gets more complicated.\n\t\t\tif named, ok := types.Unalias(fld.Type).(*types.Named); !ok || named.Obj().Name() != \"Context\" || named.Obj().Pkg().Path() != \"context\" {\n\t\t\t\treturn nil, fmt.Errorf(\"first method parameter must be context.Context\")\n\t\t\t}\n\t\t\t// Skip the context argument, as it is implied.\n\t\t\tcontinue\n\t\t}\n\t\tc.Args = append(c.Args, fld)\n\t}\n\treturn c, nil\n}\n\nfunc (l *fieldLoader) loadField(pkg *packages.Package, obj *types.Var, doc, tag string) (*Field, error) {\n\tif existing, ok := l.loaded[obj]; ok {\n\t\treturn existing, nil\n\t}\n\tfld := &Field{\n\t\tName:    obj.Name(),\n\t\tDoc:     strings.TrimSpace(doc),\n\t\tType:    obj.Type(),\n\t\tJSONTag: reflect.StructTag(tag).Get(\"json\"),\n\t}\n\n\t// This must be done here to handle nested types, such as:\n\t//\n\t//    type Test struct { Subtests []Test }\n\tl.loaded[obj] = fld\n\n\tunder := fld.Type.Underlying()\n\t// Quick-and-dirty handling for various underlying types.\n\tswitch p := under.(type) {\n\tcase *types.Pointer:\n\t\tunder = p.Elem().Underlying()\n\tcase *types.Array:\n\t\tunder = p.Elem().Underlying()\n\t\tfld.FieldMod = fmt.Sprintf(\"[%d]\", p.Len())\n\tcase *types.Slice:\n\t\tunder = p.Elem().Underlying()\n\t\tfld.FieldMod = \"[]\"\n\t}\n\n\tif s, ok := under.(*types.Struct); ok {\n\t\tfor i := 0; i < s.NumFields(); i++ {\n\t\t\tobj2 := s.Field(i)\n\t\t\tpkg2 := pkg\n\t\t\tif obj2.Pkg() != pkg2.Types {\n\t\t\t\tpkg2, ok = pkg.Imports[obj2.Pkg().Path()]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"missing import for %q: %q\", pkg.ID, obj2.Pkg().Path())\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode, err := findField(pkg2, obj2.Pos())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ttag := s.Tag(i)\n\t\t\tstructField, err := l.loadField(pkg2, obj2, node.Doc.Text(), tag)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tfld.Fields = append(fld.Fields, structField)\n\t\t}\n\t}\n\treturn fld, nil\n}\n\n// splitDoc parses a command doc string to separate the title from normal\n// documentation.\n//\n// The doc comment should be of the form: \"MethodName: Title\\nDocumentation\"\nfunc splitDoc(text string) (title, doc string) {\n\tdocParts := strings.SplitN(text, \"\\n\", 2)\n\ttitleParts := strings.SplitN(docParts[0], \":\", 2)\n\tif len(titleParts) > 1 {\n\t\ttitle = strings.TrimSpace(titleParts[1])\n\t}\n\tif len(docParts) > 1 {\n\t\tdoc = strings.TrimSpace(docParts[1])\n\t}\n\treturn title, doc\n}\n\n// lspName returns the normalized command name to use in the LSP.\nfunc lspName(methodName string) string {\n\twords := splitCamel(methodName)\n\tfor i := range words {\n\t\twords[i] = strings.ToLower(words[i])\n\t}\n\treturn \"gopls.\" + strings.Join(words, \"_\")\n}\n\n// splitCamel splits s into words, according to camel-case word boundaries.\n// Initialisms are grouped as a single word.\n//\n// For example:\n//\n//\t\"RunTests\"      -> []string{\"Run\", \"Tests\"}\n//\t\"ClientOpenURL\" -> []string{\"Client\", \"Open\", \"URL\"}\nfunc splitCamel(s string) []string {\n\tvar words []string\n\tfor len(s) > 0 {\n\t\tlast := max(strings.LastIndexFunc(s, unicode.IsUpper), 0)\n\t\tif last == len(s)-1 {\n\t\t\t// Group initialisms as a single word.\n\t\t\tlast = 1 + strings.LastIndexFunc(s[:last], func(r rune) bool { return !unicode.IsUpper(r) })\n\t\t}\n\t\twords = append(words, s[last:])\n\t\ts = s[:last]\n\t}\n\tfor i := 0; i < len(words)/2; i++ {\n\t\tj := len(words) - i - 1\n\t\twords[i], words[j] = words[j], words[i]\n\t}\n\treturn words\n}\n\n// findField finds the struct field or interface method positioned at pos,\n// within the AST.\nfunc findField(pkg *packages.Package, pos token.Pos) (*ast.Field, error) {\n\tfset := pkg.Fset\n\tvar file *ast.File\n\tfor _, f := range pkg.Syntax {\n\t\tif fset.File(f.FileStart).Name() == fset.File(pos).Name() {\n\t\t\tfile = f\n\t\t\tbreak\n\t\t}\n\t}\n\tif file == nil {\n\t\treturn nil, fmt.Errorf(\"no file for pos %v\", pos)\n\t}\n\tpath, _ := astutil.PathEnclosingInterval(file, pos, pos)\n\t// This is fragile, but in the cases we care about, the field will be in\n\t// path[1].\n\treturn path[1].(*ast.Field), nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/gen/gen.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gen is used to generate command bindings from the gopls command\n// interface.\npackage gen\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"log\"\n\t\"text/template\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol/command/commandmeta\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst src = `// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Don't include this file during code generation, or it will break the build\n// if existing interface methods have been modified.\n//go:build !generate\n// +build !generate\n\n// Code generated by gen.go from gopls/internal/protocol/command. DO NOT EDIT.\n\npackage command\n\nimport (\n\t{{range $k, $v := .Imports -}}\n\t\"{{$k}}\"\n\t{{end}}\n)\n\n// Symbolic names for gopls commands, corresponding to methods of [Interface].\n//\n// The string value is used in the Command field of protocol.Command.\n// These commands may be obtained from a CodeLens or CodeAction request\n// and executed by an ExecuteCommand request.\nconst (\n{{- range .Commands}}\n\t{{.MethodName}} Command = \"{{.Name}}\"\n{{- end}}\n)\n\nvar Commands = []Command {\n{{- range .Commands}}\n\t{{.MethodName}},\n{{- end}}\n}\n\nfunc Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (any, error) {\n\tswitch Command(params.Command) {\n\t{{- range .Commands}}\n\tcase {{.MethodName}}:\n\t\t{{- if .Args -}}\n\t\t\t{{- range $i, $v := .Args}}\n\t\tvar a{{$i}} {{typeString $v.Type}}\n\t\t\t{{- end}}\n\t\tif err := UnmarshalArgs(params.Arguments{{range $i, $v := .Args}}, &a{{$i}}{{end}}); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t{{end -}}\n\t\treturn {{if not .Result}}nil, {{end}}s.{{.MethodName}}(ctx{{range $i, $v := .Args}}, a{{$i}}{{end}})\n\t{{- end}}\n\t}\n\treturn nil, fmt.Errorf(\"unsupported command %q\", params.Command)\n}\n{{- range .Commands}}\n\n{{if fallible .Args}}\nfunc New{{.MethodName}}Command(title string, {{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}} {{typeString $v.Type}}{{end}}) (*protocol.Command, error) {\n\targs, err := MarshalArgs({{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}}{{end}})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &protocol.Command{\n\t\tTitle: title,\n\t\tCommand: {{.MethodName}}.String(),\n\t\tArguments: args,\n\t}, nil\n}\n{{else}}\nfunc New{{.MethodName}}Command(title string, {{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}} {{typeString $v.Type}}{{end}}) *protocol.Command {\n\treturn &protocol.Command{\n\t\tTitle: title,\n\t\tCommand: {{.MethodName}}.String(),\n\t\tArguments: MustMarshalArgs({{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}}{{end}}),\n\t}\n}\n{{end}}\n\n{{end}}\n`\n\ntype data struct {\n\tImports  map[string]bool\n\tCommands []*commandmeta.Command\n}\n\n// Generate computes the new contents of ../command_gen.go from a\n// static analysis of the command.Interface type.\nfunc Generate() ([]byte, error) {\n\tcmds, err := commandmeta.Load()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"loading command data: %v\", err)\n\t}\n\tconst thispkg = \"golang.org/x/tools/gopls/internal/protocol/command\"\n\tqual := func(p *types.Package) string {\n\t\tif p.Path() == thispkg {\n\t\t\treturn \"\"\n\t\t}\n\t\treturn p.Name()\n\t}\n\ttmpl, err := template.New(\"\").Funcs(template.FuncMap{\n\t\t\"typeString\": func(t types.Type) string {\n\t\t\treturn types.TypeString(t, qual)\n\t\t},\n\t\t\"fallible\": func(args []*commandmeta.Field) bool {\n\t\t\tvar fallible func(types.Type) bool\n\t\t\tfallible = func(t types.Type) bool {\n\t\t\t\tswitch t := t.Underlying().(type) {\n\t\t\t\tcase *types.Basic:\n\t\t\t\t\treturn false\n\t\t\t\tcase *types.Slice:\n\t\t\t\t\treturn fallible(t.Elem())\n\t\t\t\tcase *types.Struct:\n\t\t\t\t\tfor field := range t.Fields() {\n\t\t\t\t\t\tif fallible(field.Type()) {\n\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// Assume all other types are fallible for now:\n\t\t\t\tlog.Println(\"Command.Args has fallible type\", t)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tfor _, arg := range args {\n\t\t\t\tif fallible(arg.Type) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\t\t},\n\t}).Parse(src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\td := data{\n\t\tCommands: cmds,\n\t\tImports: map[string]bool{\n\t\t\t\"context\": true,\n\t\t\t\"fmt\":     true,\n\t\t\t\"golang.org/x/tools/gopls/internal/protocol\": true,\n\t\t},\n\t}\n\tfor _, c := range d.Commands {\n\t\tfor _, arg := range c.Args {\n\t\t\tpth := pkgPath(arg.Type)\n\t\t\tif pth != \"\" && pth != thispkg {\n\t\t\t\td.Imports[pth] = true\n\t\t\t}\n\t\t}\n\t\tif c.Result != nil {\n\t\t\tpth := pkgPath(c.Result.Type)\n\t\t\tif pth != \"\" && pth != thispkg {\n\t\t\t\td.Imports[pth] = true\n\t\t\t}\n\t\t}\n\t}\n\n\tvar buf bytes.Buffer\n\tif err := tmpl.Execute(&buf, d); err != nil {\n\t\treturn nil, fmt.Errorf(\"executing: %v\", err)\n\t}\n\n\topts := &imports.Options{\n\t\tAllErrors:  true,\n\t\tFormatOnly: true,\n\t\tComments:   true,\n\t}\n\tcontent, err := imports.Process(\"\", buf.Bytes(), opts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"goimports: %v\", err)\n\t}\n\treturn content, nil\n}\n\nfunc pkgPath(t types.Type) string {\n\tif tname := typesinternal.TypeNameFor(t); tname != nil {\n\t\tif pkg := tname.Pkg(); pkg != nil {\n\t\t\treturn pkg.Path()\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/generate.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The generate command generates command_gen.go from a combination of\n// static and dynamic analysis of the command package.\npackage main\n\nimport (\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol/command/gen\"\n)\n\nfunc main() {\n\tcontent, err := gen.Generate()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.WriteFile(\"command_gen.go\", content, 0644); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/interface.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run -tags=generate generate.go\n\n// Package command defines the interface provided by gopls for the\n// workspace/executeCommand LSP request.\n//\n// This interface is fully specified by the Interface type, provided it\n// conforms to the restrictions outlined in its doc string.\n//\n// Bindings for server-side command dispatch and client-side serialization are\n// also provided by this package, via code generation.\npackage command\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n)\n\n// Interface defines the interface gopls exposes for the\n// workspace/executeCommand request.\n//\n// This interface is used to generate logic for marshaling,\n// unmarshaling, and dispatch, so it has some additional restrictions:\n//\n//  1. All method arguments must be JSON serializable.\n//\n//  2. Methods must return either error or (T, error), where T is a\n//     JSON serializable type.\n//\n//  3. The first line of the doc string is special.\n//     Everything after the colon is considered the command 'Title'.\n//     For example:\n//\n//     Command: Capitalized verb phrase with no period\n//\n//     Longer description here...\ntype Interface interface {\n\t// ApplyFix: Apply a fix\n\t//\n\t// Applies a fix to a region of source code.\n\tApplyFix(context.Context, ApplyFixArgs) (*protocol.WorkspaceEdit, error)\n\n\t// RunTests: Run tests\n\t//\n\t// Runs `go test` for a specific set of test or benchmark functions.\n\t//\n\t// This command is asynchronous; clients must wait for the 'end' progress notification.\n\tRunTests(context.Context, RunTestsArgs) error\n\n\t// Generate: Run go generate\n\t//\n\t// Runs `go generate` for a given directory.\n\tGenerate(context.Context, GenerateArgs) error\n\n\t// Doc: Browse package documentation.\n\t//\n\t// Opens the Go package documentation page for the current\n\t// package in a browser.\n\tDoc(context.Context, DocArgs) (protocol.URI, error)\n\n\t// SplitPackage: organize a package into two or more components\n\t//\n\t// Opens the \"split package\" tool in a web browser.\n\tSplitPackage(ctx context.Context, viewID, packageID string) error\n\n\t// RegenerateCgo: Regenerate cgo\n\t//\n\t// Regenerates cgo definitions.\n\tRegenerateCgo(context.Context, URIArg) error\n\n\t// Tidy: Run go mod tidy\n\t//\n\t// Runs `go mod tidy` for a module.\n\tTidy(context.Context, URIArgs) error\n\n\t// Vendor: Run go mod vendor\n\t//\n\t// Runs `go mod vendor` for a module.\n\tVendor(context.Context, URIArg) error\n\n\t// EditGoDirective: Run go mod edit -go=version\n\t//\n\t// Runs `go mod edit -go=version` for a module.\n\tEditGoDirective(context.Context, EditGoDirectiveArgs) error\n\n\t// UpdateGoSum: Update go.sum\n\t//\n\t// Updates the go.sum file for a module.\n\tUpdateGoSum(context.Context, URIArgs) error\n\n\t// CheckUpgrades: Check for upgrades\n\t//\n\t// Checks for module upgrades.\n\tCheckUpgrades(context.Context, CheckUpgradesArgs) error\n\n\t// AddDependency: Add a dependency\n\t//\n\t// Adds a dependency to the go.mod file for a module.\n\tAddDependency(context.Context, DependencyArgs) error\n\n\t// UpgradeDependency: Upgrade a dependency\n\t//\n\t// Upgrades a dependency in the go.mod file for a module.\n\tUpgradeDependency(context.Context, DependencyArgs) error\n\n\t// RemoveDependency: Remove a dependency\n\t//\n\t// Removes a dependency from the go.mod file of a module.\n\tRemoveDependency(context.Context, RemoveDependencyArgs) error\n\n\t// ResetGoModDiagnostics: Reset go.mod diagnostics\n\t//\n\t// Reset diagnostics in the go.mod file of a module.\n\tResetGoModDiagnostics(context.Context, ResetGoModDiagnosticsArgs) error\n\n\t// GoGetPackage: 'go get' a package\n\t//\n\t// Runs `go get` to fetch a package.\n\tGoGetPackage(context.Context, GoGetPackageArgs) error\n\n\t// GCDetails: Toggle display of compiler optimization details\n\t//\n\t// Toggle the per-package flag that causes Go compiler\n\t// optimization decisions to be reported as diagnostics.\n\t//\n\t// (The name is a legacy of a time when the Go compiler was\n\t// known as \"gc\". Renaming the command would break custom\n\t// client-side logic in VS Code.)\n\tGCDetails(context.Context, protocol.DocumentURI) error\n\n\t// LSP is a command that functions as a generic dispatcher, allowing clients\n\t// to execute any LSP RPC through the \"workspace/executeCommand\" request.\n\t//\n\t// This serves two primary purposes:\n\t//\n\t// 1. It provides a unified endpoint for clients that are restricted from\n\t//    making arbitrary LSP calls directly, giving them full access to the\n\t//    server's capabilities.\n\t//\n\t// 2. It allows the client and server to extend the standard protocol. A\n\t//    client can send custom parameters that are not part of the official\n\t//    LSP, enabling richer functionality.\n\t//\n\t// The command takes the target LSP method name and its parameters as a\n\t// [json.RawMessage], routing the call to the appropriate internal handler.\n\tLSP(context.Context, LSPArgs) (any, error)\n\n\t// ListKnownPackages: List known packages\n\t//\n\t// Retrieve a list of packages that are importable from the given URI.\n\tListKnownPackages(context.Context, URIArg) (ListKnownPackagesResult, error)\n\n\t// ListImports: List imports of a file and its package\n\t//\n\t// Retrieve a list of imports in the given Go file, and the package it\n\t// belongs to.\n\tListImports(context.Context, URIArg) (ListImportsResult, error)\n\n\t// AddImport: Add an import\n\t//\n\t// Ask the server to add an import path to a given Go file.  The method will\n\t// call applyEdit on the client so that clients don't have to apply the edit\n\t// themselves.\n\tAddImport(context.Context, AddImportArgs) error\n\n\t// ExtractToNewFile: Move selected declarations to a new file\n\t//\n\t// Used by the code action of the same name.\n\tExtractToNewFile(context.Context, protocol.Location) error\n\n\t// StartDebugging: Start the gopls debug server\n\t//\n\t// Start the gopls debug server if it isn't running, and return the debug\n\t// address.\n\tStartDebugging(context.Context, DebuggingArgs) (DebuggingResult, error)\n\n\t// StartProfile: Start capturing a profile of gopls' execution\n\t//\n\t// Start a new pprof profile. Before using the resulting file, profiling must\n\t// be stopped with a corresponding call to StopProfile.\n\t//\n\t// This command is intended for internal use only, by the gopls benchmark\n\t// runner.\n\tStartProfile(context.Context, StartProfileArgs) (StartProfileResult, error)\n\n\t// StopProfile: Stop an ongoing profile\n\t//\n\t// This command is intended for internal use only, by the gopls benchmark\n\t// runner.\n\tStopProfile(context.Context, StopProfileArgs) (StopProfileResult, error)\n\n\t// GoVulncheck: run vulncheck synchronously.\n\t//\n\t// Run vulnerability check (`govulncheck`).\n\t//\n\t// This command is synchronous, and returns the govulncheck result.\n\tVulncheck(context.Context, VulncheckArgs) (VulncheckResult, error)\n\n\t// RunGovulncheck: Run vulncheck asynchronously.\n\t//\n\t// Run vulnerability check (`govulncheck`).\n\t//\n\t// This command is asynchronous; clients must wait for the 'end' progress\n\t// notification and then retrieve results using gopls.fetch_vulncheck_result.\n\t//\n\t// Deprecated: clients should call gopls.vulncheck instead, which returns the\n\t// actual vulncheck result.\n\tRunGovulncheck(context.Context, VulncheckArgs) (RunVulncheckResult, error)\n\n\t// FetchVulncheckResult: Get known vulncheck result\n\t//\n\t// Fetch the result of latest vulnerability check (`govulncheck`).\n\t//\n\t// Deprecated: clients should call gopls.vulncheck instead, which returns the\n\t// actual vulncheck result.\n\tFetchVulncheckResult(context.Context, URIArg) (map[protocol.DocumentURI]*vulncheck.Result, error)\n\n\t// MemStats: Fetch memory statistics\n\t//\n\t// Call runtime.GC multiple times and return memory statistics as reported by\n\t// runtime.MemStats.\n\t//\n\t// This command is used for benchmarking, and may change in the future.\n\tMemStats(context.Context) (MemStatsResult, error)\n\n\t// WorkspaceStats: Fetch workspace statistics\n\t//\n\t// Query statistics about workspace builds, modules, packages, and files.\n\t//\n\t// This command is intended for internal use only, by the gopls stats\n\t// command.\n\tWorkspaceStats(context.Context) (WorkspaceStatsResult, error)\n\n\t// RunGoWorkCommand: Run `go work [args...]`, and apply the resulting go.work\n\t// edits to the current go.work file\n\tRunGoWorkCommand(context.Context, RunGoWorkArgs) error\n\n\t// AddTelemetryCounters: Update the given telemetry counters\n\t//\n\t// Gopls will prepend \"fwd/\" to all the counters updated using this command\n\t// to avoid conflicts with other counters gopls collects.\n\tAddTelemetryCounters(context.Context, AddTelemetryCountersArgs) error\n\n\t// AddTest: add test for the selected function\n\tAddTest(context.Context, protocol.Location) (*protocol.WorkspaceEdit, error)\n\n\t// MaybePromptForTelemetry: Prompt user to enable telemetry\n\t//\n\t// Checks for the right conditions, and then prompts the user\n\t// to ask if they want to enable Go telemetry uploading. If\n\t// the user responds 'Yes', the telemetry mode is set to \"on\".\n\tMaybePromptForTelemetry(context.Context) error\n\n\t// ChangeSignature: Perform a \"change signature\" refactoring\n\t//\n\t// This command is experimental, currently only supporting parameter removal.\n\t// Its signature will certainly change in the future (pun intended).\n\tChangeSignature(context.Context, ChangeSignatureArgs) (*protocol.WorkspaceEdit, error)\n\n\t// DiagnoseFiles: Cause server to publish diagnostics for the specified files.\n\t//\n\t// This command is needed by the 'gopls {check,fix}' CLI subcommands.\n\tDiagnoseFiles(context.Context, DiagnoseFilesArgs) error\n\n\t// Views: List current Views on the server.\n\t//\n\t// This command is intended for use by gopls tests only.\n\tViews(context.Context) ([]View, error)\n\n\t// FreeSymbols: Browse free symbols referenced by the selection in a browser.\n\t//\n\t// This command is a query over a selected range of Go source\n\t// code. It reports the set of \"free\" symbols of the\n\t// selection: the set of symbols that are referenced within\n\t// the selection but are declared outside of it. This\n\t// information is useful for understanding at a glance what a\n\t// block of code depends on, perhaps as a precursor to\n\t// extracting it into a separate function.\n\tFreeSymbols(ctx context.Context, viewID string, loc protocol.Location) error\n\n\t// Assembly: Browse assembly listing of current function in a browser.\n\t//\n\t// This command opens a web-based disassembly listing of the\n\t// specified function symbol (plus any nested lambdas and defers).\n\t// The machine architecture is determined by the view.\n\tAssembly(_ context.Context, viewID, packageID, symbol string) error\n\n\t// ClientOpenURL: Request that the client open a URL in a browser.\n\tClientOpenURL(_ context.Context, url string) error\n\n\t// ScanImports: force a synchronous scan of the imports cache.\n\t//\n\t// This command is intended for use by gopls tests only.\n\tScanImports(context.Context) error\n\n\t// Packages: Return information about packages\n\t//\n\t// This command returns an empty result if the specified files\n\t// or directories are not associated with any Views on the\n\t// server yet.\n\tPackages(context.Context, PackagesArgs) (PackagesResult, error)\n\n\t// Modules: Return information about modules within a directory\n\t//\n\t// This command returns an empty result if there is no module, or if module\n\t// mode is disabled. Modules will not cause any new views to be loaded and\n\t// will only return modules associated with views that have already been\n\t// loaded, regardless of how it is called. Given current usage (by the\n\t// language server client), there should never be a case where Modules is\n\t// called on a path that has not already been loaded.\n\tModules(context.Context, ModulesArgs) (ModulesResult, error)\n\n\t// PackageSymbols: Return information about symbols in the given file's package.\n\tPackageSymbols(context.Context, PackageSymbolsArgs) (PackageSymbolsResult, error)\n\n\t// ModifyTags: Add or remove struct tags on a given node.\n\tModifyTags(context.Context, ModifyTagsArgs) error\n\n\t// MoveType: Move a type declaration to a different package.\n\tMoveType(context.Context, MoveTypeArgs) error\n}\n\ntype RunTestsArgs struct {\n\t// The test file containing the tests to run.\n\tURI protocol.DocumentURI\n\n\t// Specific test names to run, e.g. TestFoo.\n\tTests []string\n\n\t// Specific benchmarks to run, e.g. BenchmarkFoo.\n\tBenchmarks []string\n}\n\ntype GenerateArgs struct {\n\t// URI for the directory to generate.\n\tDir protocol.DocumentURI\n\n\t// Whether to generate recursively (go generate ./...)\n\tRecursive bool\n}\n\ntype DocArgs struct {\n\tLocation     protocol.Location\n\tShowDocument bool // in addition to returning the URL, send showDocument\n}\n\n// TODO(rFindley): document the rest of these once the docgen is fleshed out.\n\ntype ApplyFixArgs struct {\n\t// The name of the fix to apply.\n\t//\n\t// For fixes suggested by analyzers, this is a string constant\n\t// advertised by the analyzer that matches the Category of\n\t// the analysis.Diagnostic with a SuggestedFix containing no edits.\n\t//\n\t// For fixes suggested by code actions, this is a string agreed\n\t// upon by the code action and golang.ApplyFix.\n\tFix string\n\n\t// The portion of the document to fix.\n\tLocation protocol.Location\n\n\t// Whether to resolve and return the edits.\n\tResolveEdits bool\n}\n\ntype URIArg struct {\n\t// The file URI.\n\tURI protocol.DocumentURI\n}\n\ntype URIArgs struct {\n\t// The file URIs.\n\tURIs []protocol.DocumentURI\n}\n\ntype CheckUpgradesArgs struct {\n\t// The go.mod file URI.\n\tURI protocol.DocumentURI\n\t// The modules to check.\n\tModules []string\n}\n\ntype DependencyArgs struct {\n\t// The go.mod file URI.\n\tURI protocol.DocumentURI\n\t// Additional args to pass to the go command.\n\tGoCmdArgs []string\n\t// Whether to add a require directive.\n\tAddRequire bool\n}\n\ntype RemoveDependencyArgs struct {\n\t// The go.mod file URI.\n\tURI protocol.DocumentURI\n\t// The module path to remove.\n\tModulePath string\n\t// If the module is tidied apart from the one unused diagnostic, we can\n\t// run `go get module@none`, and then run `go mod tidy`. Otherwise, we\n\t// must make textual edits.\n\tOnlyDiagnostic bool\n}\n\ntype EditGoDirectiveArgs struct {\n\t// Any document URI within the relevant module.\n\tURI protocol.DocumentURI\n\t// The version to pass to `go mod edit -go`.\n\tVersion string\n}\n\ntype GoGetPackageArgs struct {\n\t// Any document URI within the relevant module.\n\tURI protocol.DocumentURI\n\t// The package to go get.\n\tPkg        string\n\tAddRequire bool\n}\n\ntype AddImportArgs struct {\n\t// ImportPath is the target import path that should\n\t// be added to the URI file\n\tImportPath string\n\t// URI is the file that the ImportPath should be\n\t// added to\n\tURI protocol.DocumentURI\n}\n\ntype ListKnownPackagesResult struct {\n\t// Packages is a list of packages relative\n\t// to the URIArg passed by the command request.\n\t// In other words, it omits paths that are already\n\t// imported or cannot be imported due to compiler\n\t// restrictions.\n\tPackages []string\n}\n\ntype ListImportsResult struct {\n\t// Imports is a list of imports in the requested file.\n\tImports []FileImport\n\n\t// PackageImports is a list of all imports in the requested file's package.\n\tPackageImports []PackageImport\n}\n\ntype FileImport struct {\n\t// Path is the import path of the import.\n\tPath string\n\t// Name is the name of the import, e.g. `foo` in `import foo \"strings\"`.\n\tName string\n}\n\ntype PackageImport struct {\n\t// Path is the import path of the import.\n\tPath string\n}\n\ntype DebuggingArgs struct {\n\t// Optional: the address (including port) for the debug server to listen on.\n\t// If not provided, the debug server will bind to \"localhost:0\", and the\n\t// full debug URL will be contained in the result.\n\t//\n\t// If there is more than one gopls instance along the serving path (i.e. you\n\t// are using a daemon), each gopls instance will attempt to start debugging.\n\t// If Addr specifies a port, only the daemon will be able to bind to that\n\t// port, and each intermediate gopls instance will fail to start debugging.\n\t// For this reason it is recommended not to specify a port (or equivalently,\n\t// to specify \":0\").\n\t//\n\t// If the server was already debugging this field has no effect, and the\n\t// result will contain the previously configured debug URL(s).\n\tAddr string\n}\n\ntype DebuggingResult struct {\n\t// The URLs to use to access the debug servers, for all gopls instances in\n\t// the serving path. For the common case of a single gopls instance (i.e. no\n\t// daemon), this will be exactly one address.\n\t//\n\t// In the case of one or more gopls instances forwarding the LSP to a daemon,\n\t// URLs will contain debug addresses for each server in the serving path, in\n\t// serving order. The daemon debug address will be the last entry in the\n\t// slice. If any intermediate gopls instance fails to start debugging, no\n\t// error will be returned but the debug URL for that server in the URLs slice\n\t// will be empty.\n\tURLs []string\n}\n\n// StartProfileArgs holds the arguments to the StartProfile command.\n//\n// It is a placeholder for future compatibility.\ntype StartProfileArgs struct {\n}\n\n// StartProfileResult holds the result of the StartProfile command.\n//\n// It is a placeholder for future compatibility.\ntype StartProfileResult struct {\n}\n\n// StopProfileArgs holds the arguments to the StopProfile command.\n//\n// It is a placeholder for future compatibility.\ntype StopProfileArgs struct {\n}\n\n// StopProfileResult holds the result to the StopProfile command.\ntype StopProfileResult struct {\n\t// File is the profile file name.\n\tFile string\n}\n\ntype ResetGoModDiagnosticsArgs struct {\n\tURIArg\n\n\t// Optional: source of the diagnostics to reset.\n\t// If not set, all resettable go.mod diagnostics will be cleared.\n\tDiagnosticSource string\n}\n\ntype VulncheckArgs struct {\n\t// Any document in the directory from which govulncheck will run.\n\tURI protocol.DocumentURI\n\n\t// Package pattern. E.g. \"\", \".\", \"./...\".\n\tPattern string\n\n\t// TODO: -tests\n}\n\n// RunVulncheckResult holds the result of asynchronously starting the vulncheck\n// command.\ntype RunVulncheckResult struct {\n\t// Token holds the progress token for LSP workDone reporting of the vulncheck\n\t// invocation.\n\tToken protocol.ProgressToken\n}\n\n// VulncheckResult holds the result of synchronously running the vulncheck\n// command.\ntype VulncheckResult struct {\n\t// Result holds the result of running vulncheck.\n\tResult *vulncheck.Result\n\t// Token holds the progress token used to report progress during back to the\n\t// LSP client during vulncheck execution.\n\tToken protocol.ProgressToken\n}\n\n// MemStatsResult holds selected fields from runtime.MemStats.\ntype MemStatsResult struct {\n\tHeapAlloc  uint64\n\tHeapInUse  uint64\n\tTotalAlloc uint64\n}\n\n// WorkspaceStatsResult returns information about the size and shape of the\n// workspace.\ntype WorkspaceStatsResult struct {\n\tFiles FileStats   // file stats for the cache\n\tViews []ViewStats // stats for each view in the session\n}\n\n// FileStats holds information about a set of files.\ntype FileStats struct {\n\tTotal   int // total number of files\n\tLargest int // number of bytes in the largest file\n\tErrs    int // number of files that could not be read\n}\n\n// ViewStats holds information about a single View in the session.\ntype ViewStats struct {\n\tGoCommandVersion  string       // version of the Go command resolved for this view\n\tAllPackages       PackageStats // package info for all packages (incl. dependencies)\n\tWorkspacePackages PackageStats // package info for workspace packages\n\tDiagnostics       int          // total number of diagnostics in the workspace\n}\n\n// PackageStats holds information about a collection of packages.\ntype PackageStats struct {\n\tPackages        int // total number of packages\n\tLargestPackage  int // number of files in the largest package\n\tCompiledGoFiles int // total number of compiled Go files across all packages\n\tModules         int // total number of unique modules\n}\n\ntype RunGoWorkArgs struct {\n\tViewID    string   // ID of the view to run the command from\n\tInitFirst bool     // Whether to run `go work init` first\n\tArgs      []string // Args to pass to `go work`\n}\n\n// AddTelemetryCountersArgs holds the arguments to the AddCounters command\n// that updates the telemetry counters.\ntype AddTelemetryCountersArgs struct {\n\t// Names and Values must have the same length.\n\tNames  []string // Name of counters.\n\tValues []int64  // Values added to the corresponding counters. Must be non-negative.\n}\n\n// ChangeSignatureArgs specifies a \"change signature\" refactoring to perform.\n//\n// The new signature is expressed via the NewParams and NewResults fields. The\n// elements of these lists each describe a new field of the signature, by\n// either referencing a field in the old signature or by defining a new field:\n//   - If the element is an integer, it references a positional parameter in the\n//     old signature.\n//   - If the element is a string, it is parsed as a new field to add.\n//\n// Suppose we have a function `F(a, b int) (string, error)`. Here are some\n// examples of refactoring this signature in practice, eliding the 'Location'\n// and 'ResolveEdits' fields.\n//   - `{ \"NewParams\": [0], \"NewResults\": [0, 1] }` removes the second parameter\n//   - `{ \"NewParams\": [1, 0], \"NewResults\": [0, 1] }` flips the parameter order\n//   - `{ \"NewParams\": [0, 1, \"a int\"], \"NewResults\": [0, 1] }` adds a new field\n//   - `{ \"NewParams\": [1, 2], \"NewResults\": [1] }` drops the `error` result\ntype ChangeSignatureArgs struct {\n\t// Location is any range inside the function signature. By convention, this\n\t// is the same location provided in the codeAction request.\n\tLocation protocol.Location // a range inside of the function signature, as passed to CodeAction\n\n\t// NewParams describes parameters of the new signature.\n\t// An int value references a parameter in the old signature by index.\n\t// A string value describes a new parameter field (e.g. \"x int\").\n\tNewParams []ChangeSignatureParam\n\n\t// NewResults describes results of the new signature (see above).\n\t// An int value references a result in the old signature by index.\n\t// A string value describes a new result field (e.g. \"err error\").\n\tNewResults []ChangeSignatureParam\n\n\t// Whether to resolve and return the edits.\n\tResolveEdits bool\n}\n\n// ChangeSignatureParam implements the API described in the doc string of\n// [ChangeSignatureArgs]: a union of JSON int | string.\ntype ChangeSignatureParam struct {\n\tOldIndex int\n\tNewField string\n}\n\nfunc (a *ChangeSignatureParam) UnmarshalJSON(b []byte) error {\n\tvar s string\n\tif err := json.Unmarshal(b, &s); err == nil {\n\t\ta.NewField = s\n\t\treturn nil\n\t}\n\tvar i int\n\tif err := json.Unmarshal(b, &i); err == nil {\n\t\ta.OldIndex = i\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"must be int or string\")\n}\n\nfunc (a ChangeSignatureParam) MarshalJSON() ([]byte, error) {\n\tif a.NewField != \"\" {\n\t\treturn json.Marshal(a.NewField)\n\t}\n\treturn json.Marshal(a.OldIndex)\n}\n\n// DiagnoseFilesArgs specifies a set of files for which diagnostics are wanted.\ntype DiagnoseFilesArgs struct {\n\tFiles []protocol.DocumentURI\n}\n\n// A View holds summary information about a cache.View.\ntype View struct {\n\tID         string               // view ID (the index of this view among all views created)\n\tType       string               // view type (via cache.ViewType.String)\n\tRoot       protocol.DocumentURI // root dir of the view (e.g. containing go.mod or go.work)\n\tFolder     protocol.DocumentURI // workspace folder associated with the view\n\tEnvOverlay []string             // environment variable overrides\n}\n\n// PackagesArgs holds arguments for the Packages command.\ntype PackagesArgs struct {\n\t// Files is a list of files and directories whose associated\n\t// packages should be described by the result.\n\t//\n\t// In some cases, a file may belong to more than one package;\n\t// the result may describe any of them.\n\tFiles []protocol.DocumentURI\n\n\t// Enumerate all packages under the directory loadable with\n\t// the ... pattern.\n\t// The search does not cross the module boundaries and\n\t// does not return packages that are not yet loaded.\n\t// (e.g. those excluded by the gopls directory filter setting,\n\t// or the go.work configuration)\n\tRecursive bool `json:\"Recursive,omitempty\"`\n\n\t// Mode controls the types of information returned for each package.\n\tMode PackagesMode\n}\n\n// PackagesMode controls the details to include in PackagesResult.\ntype PackagesMode uint64\n\nconst (\n\t// Populate the [TestFile.Tests] field in [Package] returned by the\n\t// Packages command.\n\tNeedTests PackagesMode = 1 << iota\n)\n\n// PackagesResult is the result of the Packages command.\ntype PackagesResult struct {\n\t// Packages is an unordered list of package metadata.\n\tPackages []Package\n\n\t// Module maps module path to module metadata for\n\t// all the modules of the returned Packages.\n\tModule map[string]Module\n}\n\n// Package describes a Go package (not an empty parent).\ntype Package struct {\n\t// Package path.\n\tPath string\n\t// Module path. Empty if the package doesn't\n\t// belong to any module.\n\tModulePath string\n\t// q in a \"p [q.test]\" package.\n\tForTest string\n\n\t// Note: the result does not include the directory name\n\t// of the package because mapping between a package and\n\t// a folder is not possible in certain build systems.\n\t// If directory info is needed, one can guess it\n\t// from the TestFile's file name.\n\n\t// TestFiles contains the subset of the files of the package\n\t// whose name ends with \"_test.go\".\n\t// They are ordered deterministically as determined\n\t// by the underlying build system.\n\tTestFiles []TestFile\n}\n\ntype Module struct {\n\tPath    string               // module path\n\tVersion string               // module version if any.\n\tGoMod   protocol.DocumentURI // path to the go.mod file.\n}\n\ntype TestFile struct {\n\tURI protocol.DocumentURI // a *_test.go file\n\n\t// Tests is the list of tests in File, including subtests.\n\t//\n\t// The set of subtests is not exhaustive as in general they may be\n\t// dynamically generated, so it is impossible for static heuristics\n\t// to enumerate them.\n\t//\n\t// Tests are lexically ordered.\n\t// Since subtest names are prefixed by their top-level test names\n\t// each top-level test precedes its subtests.\n\tTests []TestCase\n}\n\n// TestCase represents a test case.\n// A test case can be a top-level Test/Fuzz/Benchmark/Example function,\n// as recognized by 'go list' or 'go test -list', or\n// a subtest within a top-level function.\ntype TestCase struct {\n\t// Name is the complete name of the test (Test, Benchmark, Example, or Fuzz)\n\t// or the subtest as it appears in the output of go test -json.\n\t// The server may attempt to infer names of subtests by static\n\t// analysis; if so, it should aim to simulate the actual computed\n\t// name of the test, including any disambiguating suffix such as \"#01\".\n\t// To run only this test, clients need to compute the -run, -bench, -fuzz\n\t// flag values by first splitting the Name with \"/\" and\n\t// quoting each element with \"^\" + regexp.QuoteMeta(Name) + \"$\".\n\t// e.g. TestToplevel/Inner.Subtest → -run=^TestToplevel$/^Inner\\.Subtest$\n\tName string\n\n\t// Loc is the filename and range enclosing this test function\n\t// or the subtest. This is used to place the gutter marker\n\t// and group tests based on location.\n\t// For subtests whose test names can be determined statically,\n\t// this can be either t.Run or the test data table\n\t// for table-driven setup.\n\t// Some testing frameworks allow to declare the actual test\n\t// logic in a different file. For example, one can define\n\t// a testify test suite in suite_test.go and use it from\n\t// main_test.go.\n\t/*\n\t   -- main_test.go --\n\t   ...\n\t   func TestFoo(t *testing.T) {\n\t       suite.Run(t, new(MyTestSuite))\n\t   }\n\t   -- suite_test.go --\n\t   type MyTestSuite struct {\n\t   \tsuite.Suite\n\t   }\n\t   func (suite *MyTestSuite) TestBar() { ... }\n\t*/\n\t// In this case, the testing framework creates \"TestFoo/TestBar\"\n\t// and the corresponding test case belongs to \"main_test.go\"\n\t// TestFile. However, the test case has \"suite_test.go\" as its\n\t// file location.\n\tLoc protocol.Location\n}\n\ntype ModulesArgs struct {\n\t// Dir is the directory in which to search for go.mod files.\n\tDir protocol.DocumentURI\n\n\t// MaxDepth is the directory walk limit.\n\t// A value of 0 means inspect only Dir.\n\t// 1 means inspect its child directories too, and so on.\n\t// A negative value removes the limit.\n\tMaxDepth int\n}\n\ntype ModulesResult struct {\n\tModules []Module\n}\n\ntype PackageSymbolsArgs struct {\n\tURI protocol.DocumentURI\n}\n\ntype PackageSymbolsResult struct {\n\tPackageName string\n\t// Files is a list of files in the given URI's package.\n\tFiles   []protocol.DocumentURI\n\tSymbols []PackageSymbol\n}\n\n// PackageSymbol has the same fields as DocumentSymbol, with an additional int field \"File\"\n// which stores the index of the symbol's file in the PackageSymbolsResult.Files array\ntype PackageSymbol struct {\n\tName string `json:\"name\"`\n\n\tDetail string `json:\"detail,omitempty\"`\n\n\t// protocol.SymbolKind maps an integer to an enum:\n\t// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#symbolKind\n\t// i.e. File = 1\n\tKind protocol.SymbolKind `json:\"kind\"`\n\n\tTags []protocol.SymbolTag `json:\"tags,omitempty\"`\n\n\tRange protocol.Range `json:\"range\"`\n\n\tSelectionRange protocol.Range `json:\"selectionRange\"`\n\n\tChildren []PackageSymbol `json:\"children,omitempty\"`\n\n\t// Index of this symbol's file in PackageSymbolsResult.Files\n\tFile int `json:\"file,omitempty\"`\n}\n\n// ModifyTagsArgs holds variables that determine how struct tags are modified.\ntype ModifyTagsArgs struct {\n\t// NOTE(hxjiang): the mofidication field is important, when resolving a\n\t// command, the title of the code action or code lenses is no longer available.\n\t// The language server is not aware of the original user intention, whether\n\t// the command is meant for tag addition or tag removal.\n\tModification         string\n\tURI                  protocol.DocumentURI // uri of the file to be modified\n\tRange                protocol.Range       // range in the file for where to modify struct tags\n\tAdd                  string               // comma-separated list of tags to add; i.e. \"json,xml\"\n\tAddOptions           string               // comma-separated list of options to add, per tag; i.e. \"json=omitempty\"\n\tRemove               string               // comma-separated list of tags to remove\n\tRemoveOptions        string               // comma-separated list of options to remove\n\tClear                bool                 // if set, clear all tags. tags are cleared before any new tags are added\n\tClearOptions         bool                 // if set, clear all tag options; options are cleared before any new options are added\n\tOverwrite            bool                 // if set, replace existing tags when adding\n\tSkipUnexportedFields bool                 // if set, do not modify tags on unexported struct fields\n\tTransform            string               // transform rule for adding tags; i.e. \"snakecase\"\n\tValueFormat          string               // format for the tag's value, after transformation; for example \"column:{field}\"\n}\n\ntype LSPArgs struct {\n\tMethod string          `json:\"method\"`\n\tParam  json.RawMessage `json:\"param\"`\n}\n\n// MoveTypeArgs specifies a \"move type\" refactoring to perform.\ntype MoveTypeArgs struct {\n\t// The location of the type to move.\n\tLocation protocol.Location\n\t// TODO(mkalil): Determine format of the parameter that specifies where to\n\t// move the type to.\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/interface_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage command_test\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command/gen\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestGenerated ensures that we haven't forgotten to update command_gen.go.\nfunc TestGenerated(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.NeedsLocalXTools(t)\n\n\tonDisk, err := os.ReadFile(\"command_gen.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgenerated, err := gen.Generate()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif diff := cmp.Diff(string(generated), string(onDisk)); diff != \"\" {\n\t\tt.Errorf(\"command_gen.go is stale -- regenerate (-generated +on disk)\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/command/util.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage command\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// A Command identifies one of gopls' ad-hoc extension commands\n// that may be invoked through LSP's executeCommand.\ntype Command string\n\nfunc (c Command) String() string { return string(c) }\n\n// MarshalArgs encodes the given arguments to json.RawMessages. This function\n// is used to construct arguments to a protocol.Command.\n//\n// Example usage:\n//\n//\tjsonArgs, err := MarshalArgs(1, \"hello\", true, StructuredArg{42, 12.6})\nfunc MarshalArgs(args ...any) ([]json.RawMessage, error) {\n\tvar out []json.RawMessage\n\tfor _, arg := range args {\n\t\targJSON, err := json.Marshal(arg)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tout = append(out, argJSON)\n\t}\n\treturn out, nil\n}\n\n// MustMarshalArgs is like MarshalArgs, but panics on error.\nfunc MustMarshalArgs(args ...any) []json.RawMessage {\n\tmsg, err := MarshalArgs(args...)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn msg\n}\n\n// UnmarshalArgs decodes the given json.RawMessages to the variables provided\n// by args. Each element of args should be a pointer.\n//\n// Example usage:\n//\n//\tvar (\n//\t    num int\n//\t    str string\n//\t    bul bool\n//\t    structured StructuredArg\n//\t)\n//\terr := UnmarshalArgs(args, &num, &str, &bul, &structured)\nfunc UnmarshalArgs(jsonArgs []json.RawMessage, args ...any) error {\n\tif len(args) != len(jsonArgs) {\n\t\treturn fmt.Errorf(\"DecodeArgs: expected %d input arguments, got %d JSON arguments\", len(args), len(jsonArgs))\n\t}\n\tfor i, arg := range args {\n\t\tif err := json.Unmarshal(jsonArgs[i], arg); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/context.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/label\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\ntype contextKey int\n\nconst (\n\tclientKey = contextKey(iota)\n)\n\nfunc WithClient(ctx context.Context, client Client) context.Context {\n\treturn context.WithValue(ctx, clientKey, client)\n}\n\nfunc LogEvent(ctx context.Context, ev core.Event, lm label.Map, mt MessageType) context.Context {\n\tclient, ok := ctx.Value(clientKey).(Client)\n\tif !ok {\n\t\treturn ctx\n\t}\n\tbuf := &bytes.Buffer{}\n\tp := export.Printer{}\n\tp.WriteEvent(buf, ev, lm)\n\tmsg := &LogMessageParams{Type: mt, Message: buf.String()}\n\t// Handle messages generated via event.Error, which won't have a level Label.\n\tif event.IsError(ev) {\n\t\tmsg.Type = Error\n\t}\n\n\t// The background goroutine lives forever once started,\n\t// and ensures log messages are sent in order (#61216).\n\tstartLogSenderOnce.Do(func() {\n\t\tgo func() {\n\t\t\tfor f := range logQueue {\n\t\t\t\tf()\n\t\t\t}\n\t\t}()\n\t})\n\n\t// Add the log item to a queue, rather than sending a\n\t// window/logMessage request to the client synchronously,\n\t// which would slow down this thread.\n\tctx2 := xcontext.Detach(ctx)\n\tlogQueue <- func() { client.LogMessage(ctx2, msg) }\n\n\treturn ctx\n}\n\nvar (\n\tstartLogSenderOnce sync.Once\n\tlogQueue           = make(chan func(), 100) // big enough for a large transient burst\n)\n"
  },
  {
    "path": "gopls/internal/protocol/doc.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run ./generate\n\n// Package protocol contains the structs that map directly to the\n// request and response messages of the Language Server Protocol.\n//\n// It is a literal transcription, with unmodified comments, and only the changes\n// required to make it go code.\n// Names are uppercased to export them.\n// All fields have JSON tags added to correct the names.\n// Fields marked with a ? are also marked as \"omitempty\"\n// Fields that are \"|| null\" are made pointers\n// Fields that are string or number are left as string\n// Fields that are type \"number\" are made float64\npackage protocol\n"
  },
  {
    "path": "gopls/internal/protocol/edits.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// EditsFromDiffEdits converts diff.Edits to a non-nil slice of LSP TextEdits.\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray\nfunc EditsFromDiffEdits(m *Mapper, edits []diff.Edit) ([]TextEdit, error) {\n\t// LSP doesn't require TextEditArray to be sorted:\n\t// this is the receiver's concern. But govim, and perhaps\n\t// other clients have historically relied on the order.\n\tedits = slices.Clone(edits)\n\tdiff.SortEdits(edits)\n\n\tresult := make([]TextEdit, len(edits))\n\tfor i, edit := range edits {\n\t\trng, err := m.OffsetRange(edit.Start, edit.End)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[i] = TextEdit{\n\t\t\tRange:   rng,\n\t\t\tNewText: edit.New,\n\t\t}\n\t}\n\treturn result, nil\n}\n\n// EditsToDiffEdits converts LSP TextEdits to diff.Edits.\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray\nfunc EditsToDiffEdits(m *Mapper, edits []TextEdit) ([]diff.Edit, error) {\n\tif edits == nil {\n\t\treturn nil, nil\n\t}\n\tresult := make([]diff.Edit, len(edits))\n\tfor i, edit := range edits {\n\t\tstart, end, err := m.RangeOffsets(edit.Range)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[i] = diff.Edit{\n\t\t\tStart: start,\n\t\t\tEnd:   end,\n\t\t\tNew:   edit.NewText,\n\t\t}\n\t}\n\treturn result, nil\n}\n\n// ApplyEdits applies the patch (edits) to m.Content and returns the result.\n// It also returns the edits converted to diff-package form.\nfunc ApplyEdits(m *Mapper, edits []TextEdit) ([]byte, []diff.Edit, error) {\n\tdiffEdits, err := EditsToDiffEdits(m, edits)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tout, err := diff.ApplyBytes(m.Content, diffEdits)\n\treturn out, diffEdits, err\n}\n\n// AsTextEdits converts a slice possibly containing AnnotatedTextEdits\n// to a slice of TextEdits.\nfunc AsTextEdits(edits []Or_TextDocumentEdit_edits_Elem) []TextEdit {\n\tvar result []TextEdit\n\tfor _, e := range edits {\n\t\tvar te TextEdit\n\t\tif x, ok := e.Value.(AnnotatedTextEdit); ok {\n\t\t\tte = x.TextEdit\n\t\t} else if x, ok := e.Value.(TextEdit); ok {\n\t\t\tte = x\n\t\t} else {\n\t\t\tpanic(fmt.Sprintf(\"unexpected type %T, expected AnnotatedTextEdit or TextEdit\", e.Value))\n\t\t}\n\t\tresult = append(result, te)\n\t}\n\treturn result\n}\n\n// AsAnnotatedTextEdits converts a slice of TextEdits\n// to a slice of Or_TextDocumentEdit_edits_Elem.\n// (returning a typed nil is required in server: in code_action.go and command.go))\nfunc AsAnnotatedTextEdits(edits []TextEdit) []Or_TextDocumentEdit_edits_Elem {\n\tif edits == nil {\n\t\treturn []Or_TextDocumentEdit_edits_Elem{}\n\t}\n\tvar result []Or_TextDocumentEdit_edits_Elem\n\tfor _, e := range edits {\n\t\tresult = append(result, Or_TextDocumentEdit_edits_Elem{\n\t\t\tValue: TextEdit{\n\t\t\t\tRange:   e.Range,\n\t\t\t\tNewText: e.NewText,\n\t\t\t},\n\t\t})\n\t}\n\treturn result\n}\n\n// fileHandle abstracts file.Handle to avoid a cycle.\ntype fileHandle interface {\n\tURI() DocumentURI\n\tVersion() int32\n}\n\n// NewWorkspaceEdit constructs a WorkspaceEdit from a list of document changes.\n//\n// Any ChangeAnnotations must be added after.\nfunc NewWorkspaceEdit(changes ...DocumentChange) *WorkspaceEdit {\n\treturn &WorkspaceEdit{DocumentChanges: changes}\n}\n\n// DocumentChangeEdit constructs a DocumentChange containing a\n// TextDocumentEdit from a file.Handle and a list of TextEdits.\nfunc DocumentChangeEdit(fh fileHandle, textedits []TextEdit) DocumentChange {\n\treturn DocumentChange{\n\t\tTextDocumentEdit: &TextDocumentEdit{\n\t\t\tTextDocument: OptionalVersionedTextDocumentIdentifier{\n\t\t\t\tVersion:                fh.Version(),\n\t\t\t\tTextDocumentIdentifier: TextDocumentIdentifier{URI: fh.URI()},\n\t\t\t},\n\t\t\tEdits: AsAnnotatedTextEdits(textedits),\n\t\t},\n\t}\n}\n\n// DocumentChangeCreate constructs a DocumentChange that creates a file.\nfunc DocumentChangeCreate(uri DocumentURI) DocumentChange {\n\treturn DocumentChange{\n\t\tCreateFile: &CreateFile{\n\t\t\tKind: \"create\",\n\t\t\tURI:  uri,\n\t\t},\n\t}\n}\n\n// DocumentChangeDelete constructs a DocumentChange that deletes a file.\nfunc DocumentChangeDelete(uri DocumentURI) DocumentChange {\n\treturn DocumentChange{\n\t\tDeleteFile: &DeleteFile{\n\t\t\tKind: \"delete\",\n\t\t\tURI:  uri,\n\t\t},\n\t}\n}\n\n// DocumentChangeRename constructs a DocumentChange that renames a file.\nfunc DocumentChangeRename(src, dst DocumentURI) DocumentChange {\n\treturn DocumentChange{\n\t\tRenameFile: &RenameFile{\n\t\t\tKind:   \"rename\",\n\t\t\tOldURI: src,\n\t\t\tNewURI: dst,\n\t\t},\n\t}\n}\n\n// SelectCompletionTextEdit returns insert or replace mode TextEdit\n// included in the completion item.\nfunc SelectCompletionTextEdit(item CompletionItem, useReplaceMode bool) (TextEdit, error) {\n\tvar edit TextEdit\n\tswitch typ := item.TextEdit.Value.(type) {\n\tcase TextEdit: // old style completion item.\n\t\treturn typ, nil\n\tcase InsertReplaceEdit:\n\t\tif useReplaceMode {\n\t\t\treturn TextEdit{\n\t\t\t\tNewText: typ.NewText,\n\t\t\t\tRange:   typ.Replace,\n\t\t\t}, nil\n\t\t} else {\n\t\t\treturn TextEdit{\n\t\t\t\tNewText: typ.NewText,\n\t\t\t\tRange:   typ.Insert,\n\t\t\t}, nil\n\t\t}\n\tdefault:\n\t\treturn edit, fmt.Errorf(\"unsupported edit type %T\", typ)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/enums.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"fmt\"\n)\n\n// CodeActionUnknownTrigger indicates that the trigger for a\n// CodeAction request is unknown. A missing\n// CodeActionContext.TriggerKind should be treated as equivalent.\nconst CodeActionUnknownTrigger CodeActionTriggerKind = 0\n\nvar (\n\tnamesTextDocumentSyncKind   [int(Incremental) + 1]string\n\tnamesMessageType            [int(Log) + 1]string\n\tnamesFileChangeType         [int(Deleted) + 1]string\n\tnamesWatchKind              [int(WatchDelete) + 1]string\n\tnamesCompletionTriggerKind  [int(TriggerForIncompleteCompletions) + 1]string\n\tnamesDiagnosticSeverity     [int(SeverityHint) + 1]string\n\tnamesDiagnosticTag          [int(Unnecessary) + 1]string\n\tnamesCompletionItemKind     [int(TypeParameterCompletion) + 1]string\n\tnamesInsertTextFormat       [int(SnippetTextFormat) + 1]string\n\tnamesDocumentHighlightKind  [int(Write) + 1]string\n\tnamesSymbolKind             [int(TypeParameter) + 1]string\n\tnamesTextDocumentSaveReason [int(FocusOut) + 1]string\n)\n\nfunc init() {\n\tnamesTextDocumentSyncKind[int(None)] = \"None\"\n\tnamesTextDocumentSyncKind[int(Full)] = \"Full\"\n\tnamesTextDocumentSyncKind[int(Incremental)] = \"Incremental\"\n\n\tnamesMessageType[int(Error)] = \"Error\"\n\tnamesMessageType[int(Warning)] = \"Warning\"\n\tnamesMessageType[int(Info)] = \"Info\"\n\tnamesMessageType[int(Log)] = \"Log\"\n\n\tnamesFileChangeType[int(Created)] = \"Created\"\n\tnamesFileChangeType[int(Changed)] = \"Changed\"\n\tnamesFileChangeType[int(Deleted)] = \"Deleted\"\n\n\tnamesWatchKind[int(WatchCreate)] = \"WatchCreate\"\n\tnamesWatchKind[int(WatchChange)] = \"WatchChange\"\n\tnamesWatchKind[int(WatchDelete)] = \"WatchDelete\"\n\n\tnamesCompletionTriggerKind[int(Invoked)] = \"Invoked\"\n\tnamesCompletionTriggerKind[int(TriggerCharacter)] = \"TriggerCharacter\"\n\tnamesCompletionTriggerKind[int(TriggerForIncompleteCompletions)] = \"TriggerForIncompleteCompletions\"\n\n\tnamesDiagnosticSeverity[int(SeverityError)] = \"Error\"\n\tnamesDiagnosticSeverity[int(SeverityWarning)] = \"Warning\"\n\tnamesDiagnosticSeverity[int(SeverityInformation)] = \"Information\"\n\tnamesDiagnosticSeverity[int(SeverityHint)] = \"Hint\"\n\n\tnamesDiagnosticTag[int(Unnecessary)] = \"Unnecessary\"\n\n\tnamesCompletionItemKind[int(TextCompletion)] = \"text\"\n\tnamesCompletionItemKind[int(MethodCompletion)] = \"method\"\n\tnamesCompletionItemKind[int(FunctionCompletion)] = \"func\"\n\tnamesCompletionItemKind[int(ConstructorCompletion)] = \"constructor\"\n\tnamesCompletionItemKind[int(FieldCompletion)] = \"field\"\n\tnamesCompletionItemKind[int(VariableCompletion)] = \"var\"\n\tnamesCompletionItemKind[int(ClassCompletion)] = \"type\"\n\tnamesCompletionItemKind[int(InterfaceCompletion)] = \"interface\"\n\tnamesCompletionItemKind[int(ModuleCompletion)] = \"package\"\n\tnamesCompletionItemKind[int(PropertyCompletion)] = \"property\"\n\tnamesCompletionItemKind[int(UnitCompletion)] = \"unit\"\n\tnamesCompletionItemKind[int(ValueCompletion)] = \"value\"\n\tnamesCompletionItemKind[int(EnumCompletion)] = \"enum\"\n\tnamesCompletionItemKind[int(KeywordCompletion)] = \"keyword\"\n\tnamesCompletionItemKind[int(SnippetCompletion)] = \"snippet\"\n\tnamesCompletionItemKind[int(ColorCompletion)] = \"color\"\n\tnamesCompletionItemKind[int(FileCompletion)] = \"file\"\n\tnamesCompletionItemKind[int(ReferenceCompletion)] = \"reference\"\n\tnamesCompletionItemKind[int(FolderCompletion)] = \"folder\"\n\tnamesCompletionItemKind[int(EnumMemberCompletion)] = \"enumMember\"\n\tnamesCompletionItemKind[int(ConstantCompletion)] = \"const\"\n\tnamesCompletionItemKind[int(StructCompletion)] = \"struct\"\n\tnamesCompletionItemKind[int(EventCompletion)] = \"event\"\n\tnamesCompletionItemKind[int(OperatorCompletion)] = \"operator\"\n\tnamesCompletionItemKind[int(TypeParameterCompletion)] = \"typeParam\"\n\n\tnamesInsertTextFormat[int(PlainTextTextFormat)] = \"PlainText\"\n\tnamesInsertTextFormat[int(SnippetTextFormat)] = \"Snippet\"\n\n\tnamesDocumentHighlightKind[int(Text)] = \"Text\"\n\tnamesDocumentHighlightKind[int(Read)] = \"Read\"\n\tnamesDocumentHighlightKind[int(Write)] = \"Write\"\n\n\tnamesSymbolKind[int(File)] = \"File\"\n\tnamesSymbolKind[int(Module)] = \"Module\"\n\tnamesSymbolKind[int(Namespace)] = \"Namespace\"\n\tnamesSymbolKind[int(Package)] = \"Package\"\n\tnamesSymbolKind[int(Class)] = \"Class\"\n\tnamesSymbolKind[int(Method)] = \"Method\"\n\tnamesSymbolKind[int(Property)] = \"Property\"\n\tnamesSymbolKind[int(Field)] = \"Field\"\n\tnamesSymbolKind[int(Constructor)] = \"Constructor\"\n\tnamesSymbolKind[int(Enum)] = \"Enum\"\n\tnamesSymbolKind[int(Interface)] = \"Interface\"\n\tnamesSymbolKind[int(Function)] = \"Function\"\n\tnamesSymbolKind[int(Variable)] = \"Variable\"\n\tnamesSymbolKind[int(Constant)] = \"Constant\"\n\tnamesSymbolKind[int(String)] = \"String\"\n\tnamesSymbolKind[int(Number)] = \"Number\"\n\tnamesSymbolKind[int(Boolean)] = \"Boolean\"\n\tnamesSymbolKind[int(Array)] = \"Array\"\n\tnamesSymbolKind[int(Object)] = \"Object\"\n\tnamesSymbolKind[int(Key)] = \"Key\"\n\tnamesSymbolKind[int(Null)] = \"Null\"\n\tnamesSymbolKind[int(EnumMember)] = \"EnumMember\"\n\tnamesSymbolKind[int(Struct)] = \"Struct\"\n\tnamesSymbolKind[int(Event)] = \"Event\"\n\tnamesSymbolKind[int(Operator)] = \"Operator\"\n\tnamesSymbolKind[int(TypeParameter)] = \"TypeParameter\"\n\n\tnamesTextDocumentSaveReason[int(Manual)] = \"Manual\"\n\tnamesTextDocumentSaveReason[int(AfterDelay)] = \"AfterDelay\"\n\tnamesTextDocumentSaveReason[int(FocusOut)] = \"FocusOut\"\n}\n\nfunc formatEnum(f fmt.State, i int, names []string, unknown string) {\n\ts := \"\"\n\tif i >= 0 && i < len(names) {\n\t\ts = names[i]\n\t}\n\tif s != \"\" {\n\t\tfmt.Fprint(f, s)\n\t} else {\n\t\tfmt.Fprintf(f, \"%s(%d)\", unknown, i)\n\t}\n}\n\nfunc (e TextDocumentSyncKind) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesTextDocumentSyncKind[:], \"TextDocumentSyncKind\")\n}\n\nfunc (e MessageType) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesMessageType[:], \"MessageType\")\n}\n\nfunc (e FileChangeType) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesFileChangeType[:], \"FileChangeType\")\n}\n\nfunc (e CompletionTriggerKind) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesCompletionTriggerKind[:], \"CompletionTriggerKind\")\n}\n\nfunc (e DiagnosticSeverity) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesDiagnosticSeverity[:], \"DiagnosticSeverity\")\n}\n\nfunc (e DiagnosticTag) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesDiagnosticTag[:], \"DiagnosticTag\")\n}\n\nfunc (e CompletionItemKind) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesCompletionItemKind[:], \"CompletionItemKind\")\n}\n\nfunc (e InsertTextFormat) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesInsertTextFormat[:], \"InsertTextFormat\")\n}\n\nfunc (e DocumentHighlightKind) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesDocumentHighlightKind[:], \"DocumentHighlightKind\")\n}\n\nfunc (e SymbolKind) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesSymbolKind[:], \"SymbolKind\")\n}\n\nfunc (e TextDocumentSaveReason) Format(f fmt.State, c rune) {\n\tformatEnum(f, int(e), namesTextDocumentSaveReason[:], \"TextDocumentSaveReason\")\n}\n"
  },
  {
    "path": "gopls/internal/protocol/form.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file defines types for an experimental feature (golang/go#76331,\n// microsoft/language-server-protocol#1164). As an experimental feature,\n// these types are not yet included in tsprotocol.go.\n\npackage protocol\n\nimport \"encoding/json\"\n\n// FormFieldTypeString defines a text input.\n//\n// It is defined as a struct to allow for future extensibility, such as\n// adding regex validation or file URI constraints.\ntype FormFieldTypeString struct {\n\t// Kind must be \"string\".\n\tKind string `json:\"kind\"`\n}\n\n// FormFieldTypeDocumentURI defines an input for a file or directory URI.\n//\n// The client determines the best mechanism to collect this information from\n// the user (e.g., a graphical file picker, a text input with autocomplete, etc).\n//\n// The value returned by the client must be a valid \"DocumentUri\" as defined\n// in the LSP specification:\n// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#documentUri\ntype FormFieldTypeDocumentURI struct {\n\t// Kind must be \"documentURI\".\n\tKind string `json:\"kind\"`\n}\n\n// FormFieldTypeBool defines a boolean input.\ntype FormFieldTypeBool struct {\n\t// Kind must be \"bool\".\n\tKind string `json:\"kind\"`\n}\n\n// FormFieldTypeNumber defines a numeric input.\n//\n// It is defined as a struct to allow for future extensibility, such as\n// adding range constraints (min/max) or precision requirements.\ntype FormFieldTypeNumber struct {\n\t// Kind must be \"number\".\n\tKind string `json:\"kind\"`\n}\n\n// FormEnumEntry represents a single option in an enumeration.\ntype FormEnumEntry struct {\n\t// Value is the unique string identifier for this option.\n\t//\n\t// This is the value that will be sent back to the server in\n\t// 'FormAnswers' if the user selects this option.\n\tValue string `json:\"value\"`\n\n\t// Description is the human-readable label presented to the user.\n\tDescription string `json:\"description\"`\n}\n\n// FormFieldTypeEnum defines a selection from a set of values.\n//\n// Use this type when:\n// - The number of options is small (e.g., < 20).\n// - All options are known at the time the form is created.\ntype FormFieldTypeEnum struct {\n\t// Kind must be \"enum\".\n\tKind string `json:\"kind\"`\n\n\t// Entries is the list of allowable options.\n\tEntries []FormEnumEntry `json:\"entries\"`\n}\n\n// FormFieldTypeLazyEnum defines a selection from a large or dynamic enum entry set.\n//\n// Use this type when:\n//  1. The dataset is too large to send efficiently in a single payload\n//     (e.g., thousands of workspace symbols, file uri or cloud resources).\n//  2. The available options depend on the user's input (e.g., semantic search).\n//  3. Generating the list is expensive and should only be done if requested.\n//\n// The client is expected to render a search interface (e.g., a combo box with\n// a text input) and query the server via 'interactive/listEnum' as the user types.\ntype FormFieldTypeLazyEnum struct {\n\t// Kind must be \"lazyEnum\".\n\tKind string `json:\"kind\"`\n\n\t// TODO(hxjiang): consider make debounce configurable since fetching\n\t// cloud resources could be expensive and slow.\n\n\t// Source identifies the data source on the server.\n\t//\n\t// Examples: \"workspace/symbol\", \"database/schema\", \"git/tags\".\n\tSource string `json:\"source\"`\n\n\t// Config contains the static settings for the source.\n\t// The client treats this as opaque data and echoes it back in the\n\t// 'interactive/listEnum' request.\n\tConfig *json.RawMessage `json:\"config,omitempty\"`\n}\n\n// FormFieldTypeList defines a homogenous list of items.\ntype FormFieldTypeList struct {\n\t// Kind must be \"list\".\n\tKind string `json:\"kind\"`\n\n\t// ElementType specifies the type of the items in the list.\n\t// It must be one of the FormFieldType* structs (e.g., FormFieldTypeString).\n\tElementType any `json:\"elementType\"`\n}\n\n// FormField describes a single question in a form and its validation state.\ntype FormField struct {\n\t// Description is the text content of the question (the prompt) presented\n\t// to the user.\n\tDescription string `json:\"description\"`\n\n\t// Type specifies the data type and validation constraints for the answer.\n\t//\n\t// It must be one of the FormFieldType* structs. The Kind field within the\n\t// struct determines the expected data type.\n\t//\n\t// The language client is expected to render an input appropriate for this\n\t// type. If the client does not support the specified type, it should\n\t// fall back to a string input.\n\tType any `json:\"type\"`\n\n\t// Default specifies an optional initial value for the answer.\n\t//\n\t// If Type is FormFieldTypeEnum, this value must be present in the enum's\n\t// Values slice.\n\tDefault any `json:\"default,omitempty\"`\n\n\t// Error provides a validation message from the language server.\n\t// If empty, the current answer is considered valid.\n\tError string `json:\"error,omitempty\"`\n}\n\n// InteractiveParams allow the server and client to exchange interactive\n// questions and answers during an LSP request.\n//\n// The server populates FormFields to define the schema. The server may\n// optionally populate FormAnswers to preserve previous user input; if\n// provided, the client may present these as default values.\n//\n// When the client responds, it must provide FormAnswers. The client is not\n// required to send FormFields back to the server.\ntype InteractiveParams struct {\n\t// FormFields defines the questions and validation errors in previous\n\t// answers to the same questions.\n\t//\n\t// This is a server-to-client field. The language server defines these, and\n\t// the client uses them to render the form.\n\t//\n\t// Note: This is a non-standard protocol extension. See microsoft/language-server-protocol#1164.\n\tFormFields []FormField `json:\"formFields,omitempty\"`\n\n\t// FormAnswers contains the values for the form questions.\n\t//\n\t// When sent by the language server, this field is optional but recommended\n\t// to support editing previous values.\n\t//\n\t// When sent by the language client, this field is required. The slice must\n\t// have the same length as FormFields (one answer per question), where the\n\t// answer at index i corresponds to the field at index i.\n\t//\n\t// Note: This is a non-standard protocol extension. See microsoft/language-server-protocol#1164.\n\tFormAnswers []any `json:\"formAnswers,omitempty\"`\n}\n\n// InteractiveListEnumParams defines the parameters for the\n// 'interactive/listEnum' request.\ntype InteractiveListEnumParams struct {\n\t// Source identifies the data source on the server.\n\t//\n\t// The client treats this as opaque data and echoes it back in the\n\t// 'interactive/listEnum' request.\n\t//\n\t// Examples: \"workspace/symbol\", \"database/schema\", \"git/tags\".\n\tSource string `json:\"source\"`\n\n\t// Config contains the static settings for the specified source.\n\t//\n\t// The client treats this as opaque data and echoes it back in the\n\t// 'interactive/listEnum' request.\n\tConfig *json.RawMessage `json:\"config,omitempty\"`\n\n\t// A query string to filter enum entries by.\n\t//\n\t// The exact interpretation of this string (e.g., fuzzy matching, exact\n\t// match, prefix search, or regular expression) is entirely up to the\n\t// server and may vary depending on the source. This follows the similar\n\t// semantics as the standard 'workspace/symbol' request. Clients may\n\t// send an empty string here to request a default set of enum entries.\n\tQuery string `json:\"query\"`\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/README.md",
    "content": "# LSP Support for gopls\n\n## The protocol\n\nThe LSP protocol exchanges json-encoded messages between the client and the server.\n(gopls is the server.) The messages are either Requests, which require Responses, or\nNotifications, which generate no response. Each Request or Notification has a method name\nsuch as \"textDocument/hover\" that indicates its meaning and determines which function in the server will handle it.\nThe protocol is described in a\n[web page](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/),\nin words, and in a json file (metaModel.json) available either linked towards the bottom of the\nweb page, or in the vscode-languageserver-node repository. This code uses the latter so the\nexact version can be tied to a githash. By default, the command will download the `github.com/microsoft/vscode-languageserver-node` repository to a temporary directory.\n\nThe specification has five sections\n\n1. Requests, which describe the Request and Response types for request methods (e.g., *textDocument/didChange*),\n2. Notifications, which describe the Request types for notification methods,\n3. Structures, which describe named struct-like types,\n4. TypeAliases, which describe type aliases,\n5. Enumerations, which describe named constants.\n\nRequests and Notifications are tagged with a Method (e.g., `\"textDocument/hover\"`).\nThe specification does not specify the names of the functions that handle the messages. These\nnames are specified by the `methodNames` map. Enumerations generate Go `const`s, but\nin Typescript they are scoped to namespaces, while in Go they are scoped to a package, so the Go names\nmay need to be modified to avoid name collisions. (See the `disambiguate` map, and its use.)\n\nFinally, the specified types are Typescript types, which are quite different from Go types.\n\n### Optionality\n\nThe specification can mark fields in structs as Optional. The client distinguishes between missing\nfields and `null` fields in some cases. The Go translation for an optional type\nshould be making sure the field's value\ncan be `nil`, and adding the json tag `,omitempty`. The former condition would be satisfied by\nadding `*` to the field's type if the type is not a reference type.\n\n### Types\n\nThe specification uses a number of different types, only a few of which correspond directly to Go types.\nThe specification's types are \"base\", \"reference\", \"map\", \"literal\", \"stringLiteral\", \"tuple\", \"and\", \"or\".\nThe \"base\" types correspond directly to Go types, although some Go types needs to be chosen for `URI` and `DocumentUri`. (The \"base\" types`RegExp`, `BooleanLiteral`, `NumericLiteral` never occur.)\n\n\"reference\" types are the struct-like types in the Structures section of the specification. The given\nnames are suitable for Go to use, except the code needs to change names like `_Initialize` to `XInitialize` so\nthey are exported for json marshaling and unmarshaling.\n\n\"map\" types are just like Go. (The key type in all of them is `DocumentUri`.)\n\n\"stringLiteral\" types are types whose type name and value are a single string. The chosen Go equivalent\nis to make the type `string` and the value a constant. (The alternative would be to generate a new\nnamed type, which seemed redundant.)\n\n\"literal\" types are like Go anonymous structs, so they have to be given a name. (All instances\nof the remaining types have to be given names. One approach is to construct the name from the components\nof the type, but this leads to misleading punning, and is unstable if components are added. The other approach\nis to construct the name from the context of the definition, that is, from the types it is defined within.\nFor instance `Lit__InitializeParams_clientInfo` is the \"literal\" type at the\n`clientInfo` field in the `_InitializeParams`\nstruct. Although this choice is sensitive to the ordering of the components, the code uses this approach,\npresuming that reordering components is an unlikely protocol change.)\n\n\"tuple\" types are generated as Go structs. (There is only one, with two `uint32` fields.)\n\n\"and\" types are Go structs with embedded type names. (There is only one, `And_Param_workspace_configuration`.)\n\n\"or\" types are the most complicated. There are a lot of them and there is no simple Go equivalent.\nThey are defined as structs with a single `Value interface{}` field and custom json marshaling\nand unmarshaling code. Users can assign anything to `Value` but the type will be checked, and\ncorrectly marshaled, by the custom marshaling code. The unmarshaling code checks types, so `Value`\nwill have one of the permitted types. (`nil` is always allowed.) There are about 40 \"or\" types that\nhave a single non-null component, and these are converted to the component type.\n\n## Processing\n\nThe code parses the json specification file, and scans all the types. It assigns names, as described\nabove, to the types that are unnamed in the specification, and constructs Go equivalents as required.\n(Most of this code is in typenames.go.)\n\nThere are four output files. tsclient.go and tsserver.go contain the definition and implementation\nof the `protocol.Client` and `protocol.Server` types and the code that dispatches on the Method\nof the Request or Notification. tsjson.go contains the custom marshaling and unmarshaling code.\nAnd tsprotocol.go contains the type and const definitions.\n\n### Accommodating gopls\n\nAs the code generates output, mostly in generateoutput.go and main.go,\nit makes adjustments so that no changes are required to the existing Go code.\n(Organizing the computation this way makes the code's structure simpler, but results in\na lot of unused types.)\nThere are three major classes of these adjustments, and leftover special cases.\n\nThe first major\nadjustment is to change generated type names to the ones gopls expects. Some of these don't change the\nsemantics of the type, just the name.\nBut for historical reasons a lot of them replace \"or\" types by a single\ncomponent of the type. (Until fairly recently Go only saw or used only one of components.)\nThe `goplsType` map in tables.go controls this process.\n\nThe second major adjustment is to the types of fields of structs, which is done using the\n`renameProp` map in tables.go.\n\nThe third major adjustment handles optionality, controlling `*` and `,omitempty` placement when\nthe default rules don't match what gopls is expecting. (The map is `goplsStar`, also in tables.go)\n(If the intermediate components in expressions of the form `A.B.C.S` were optional, the code would need\na lot of useless checking for nils. Typescript has a language construct to avoid most checks.)\n\nThen there are some additional special cases. There are a few places with adjustments to avoid\nrecursive types. For instance `LSPArray` is `[]LSPAny`, but `LSPAny` is an \"or\" type including `LSPArray`.\nThe solution is to make `LSPAny` an `interface{}`. Another instance is `_InitializeParams.trace`\nwhose type is an \"or\" of 3 stringLiterals, which just becomes a `string`.\n\n### Checking\n\n`TestAll(t *testing.T)` checks that there are no unexpected fields in the json specification.\n\nWhile the code is executing, it checks that all the entries in the maps in tables.go are used.\nIt also checks that the entries in `renameProp` and `goplsStar` are not redundant.\n\nAs a one-time check on the first release of this code, diff-ing the existing and generated tsclient.go\nand tsserver.go code results in only whitespace and comment diffs. The existing and generated\ntsprotocol.go differ in whitespace and comments, and in a substantial number of new type definitions\nthat the older, more heuristic, code did not generate. (And the unused type `_InitializeParams` differs\nslightly between the new and the old, and is not worth fixing.)\n\n### Some history\n\nThe original stub code was written by hand, but with the protocol under active development, that\ncouldn't last. The web page existed before the json specification, but it lagged the implementation\nand was hard to process by machine. So the earlier version of the generating code was written in Typescript, and\nused the Typescript compiler's API to parse the protocol code in the repository.\nIt then used a set of heuristics\nto pick out the elements of the protocol, and another set of overlapping heuristics to create the Go code.\nThe output was functional, but idiosyncratic, and the code was fragile and barely maintainable.\n\n### The future\n\nMost of the adjustments using the maps in tables.go could be removed by making changes, mostly to names,\nin the gopls code. Using more \"or\" types in gopls requires more elaborate, but stereotyped, changes.\nBut even without all the adjustments, making this its own module would face problems; a number of\ndependencies would have to be factored out. And, it is fragile. The custom unmarshaling code knows what\ntypes it expects. A design that return an 'any' on unexpected types would match the json\n'ignore unexpected values' philosophy better, but the Go code would need extra checking.\n"
  },
  {
    "path": "gopls/internal/protocol/generate/generate.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n)\n\n// a newType is a type that needs a name and a definition\n// These are the various types that the json specification doesn't name\ntype newType struct {\n\tname       string\n\tproperties Properties // for struct/literal types\n\titems      []*Type    // for other types (\"and\", \"tuple\")\n\tline       int\n\tkind       string // Or, And, Tuple, Lit, Map\n\ttyp        *Type\n}\n\nfunc generateDoc(out *bytes.Buffer, doc string) {\n\tif doc == \"\" {\n\t\treturn\n\t}\n\n\tif !strings.Contains(doc, \"\\n\") {\n\t\tfmt.Fprintf(out, \"// %s\\n\", doc)\n\t\treturn\n\t}\n\tvar list bool\n\tfor line := range strings.SplitSeq(doc, \"\\n\") {\n\t\t// Lists in metaModel.json start with a dash.\n\t\t// To make a go doc list they have to be preceded\n\t\t// by a blank line, and indented.\n\t\t// (see type TextDccumentFilter in protocol.go)\n\t\tif len(line) > 0 && line[0] == '-' {\n\t\t\tif !list {\n\t\t\t\tlist = true\n\t\t\t\tfmt.Fprintf(out, \"//\\n\")\n\t\t\t}\n\t\t\tfmt.Fprintf(out, \"//  %s\\n\", line)\n\t\t} else {\n\t\t\tif len(line) == 0 {\n\t\t\t\tlist = false\n\t\t\t}\n\t\t\tfmt.Fprintf(out, \"// %s\\n\", line)\n\t\t}\n\t}\n}\n\n// decide if a property is optional, and if it needs a *\n// return \",omitempty\" if it is optional, and \"*\" if it needs a pointer\nfunc propStar(name string, t NameType, gotype string) (omitempty, indirect bool) {\n\tif t.Optional {\n\t\tswitch gotype {\n\t\tcase \"uint32\", \"int32\":\n\t\t\t// in FoldingRange.endLine, 0 and empty have different semantics\n\t\t\t// There seem to be no other cases.\n\t\tdefault:\n\t\t\tindirect = true\n\t\t\tomitempty = true\n\t\t}\n\t}\n\tif strings.HasPrefix(gotype, \"[]\") || strings.HasPrefix(gotype, \"map[\") {\n\t\tindirect = false // passed by reference, so no need for *\n\t} else {\n\t\tswitch gotype {\n\t\tcase \"bool\", \"string\", \"interface{}\", \"any\":\n\t\t\tindirect = false // gopls compatibility if t.Optional\n\t\t}\n\t}\n\toind, oomit := indirect, omitempty\n\tif newStar, ok := goplsStar[prop{name, t.Name}]; ok {\n\t\tswitch newStar {\n\t\tcase nothing:\n\t\t\tindirect, omitempty = false, false\n\t\tcase wantOpt:\n\t\t\tindirect, omitempty = false, true\n\t\tcase wantOptStar:\n\t\t\tindirect, omitempty = true, true\n\t\t}\n\t\tif indirect == oind && omitempty == oomit { // no change\n\t\t\tlog.Printf(\"goplsStar[ {%q, %q} ](%d) useless %v/%v %v/%v\", name, t.Name, t.Line, oind, indirect, oomit, omitempty)\n\t\t}\n\t\tusedGoplsStar[prop{name, t.Name}] = true\n\t}\n\n\treturn\n}\n\nfunc goName(s string) string {\n\t// Go naming conventions\n\tif strings.HasSuffix(s, \"Id\") {\n\t\ts = s[:len(s)-len(\"Id\")] + \"ID\"\n\t} else if strings.HasSuffix(s, \"Uri\") {\n\t\ts = s[:len(s)-3] + \"URI\"\n\t} else if s == \"uri\" {\n\t\ts = \"URI\"\n\t} else if s == \"id\" {\n\t\ts = \"ID\"\n\t}\n\n\t// renames for temporary GOPLS compatibility\n\tif news := goplsType[s]; news != \"\" {\n\t\tusedGoplsType[s] = true\n\t\ts = news\n\t}\n\t// Names beginning _ are not exported\n\tif strings.HasPrefix(s, \"_\") {\n\t\ts = strings.Replace(s, \"_\", \"X\", 1)\n\t}\n\tif s != \"string\" { // base types are unchanged (textDocuemnt/diagnostic)\n\t\t// Title is deprecated, but a) s is only one word, b) replacement is too heavy-weight\n\t\ts = strings.Title(s)\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/main.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The generate command generates Go declarations from VSCode's\n// description of the Language Server Protocol.\n//\n// To run it, type 'go generate' in the parent (protocol) directory.\npackage main\n\n// see https://github.com/golang/go/issues/61217 for discussion of an issue\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/format\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n)\n\nconst vscodeRepo = \"https://github.com/microsoft/vscode-languageserver-node\"\n\n// lspGitRef names a branch or tag in vscodeRepo.\n// It implicitly determines the protocol version of the LSP used by gopls.\n// For example, tag release/protocol/3.17.3 of the repo defines\n// protocol version 3.17.0 (as declared by the metaData.version field).\n// (Point releases are reflected in the git tag version even when they are cosmetic\n// and don't change the protocol.)\nvar lspGitRef = \"release/protocol/3.17.6-next.14\"\n\nvar (\n\trepodir   = flag.String(\"d\", \"\", \"directory containing clone of \"+vscodeRepo)\n\toutputdir = flag.String(\"o\", \".\", \"output directory\")\n\t// PJW: not for real code\n\tlineNumbers = flag.Bool(\"l\", false, \"add line numbers to generated output\")\n)\n\nfunc main() {\n\tlog.SetFlags(log.Lshortfile) // log file name and line number, not time\n\tflag.Parse()\n\n\tprocessinline()\n}\n\nfunc processinline() {\n\t// A local repository may be specified during debugging.\n\t// The default behavior is to download the canonical version.\n\tif *repodir == \"\" {\n\t\ttmpdir, err := os.MkdirTemp(\"\", \"\")\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tdefer os.RemoveAll(tmpdir) // ignore error\n\n\t\t// Clone the repository.\n\t\tcmd := exec.Command(\"git\", \"clone\", \"--quiet\", \"--depth=1\", \"-c\", \"advice.detachedHead=false\", vscodeRepo, \"--branch=\"+lspGitRef, \"--single-branch\", tmpdir)\n\t\tcmd.Stdout = os.Stderr\n\t\tcmd.Stderr = os.Stderr\n\t\tif err := cmd.Run(); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\n\t\t*repodir = tmpdir\n\t} else {\n\t\tlspGitRef = fmt.Sprintf(\"(not git, local dir %s)\", *repodir)\n\t}\n\n\tmodel := parse(filepath.Join(*repodir, \"protocol/metaModel.json\"))\n\n\t// Although the LSP specification defines RenameParams as extending\n\t// TextDocumentPositionParams, the metaModel.json definition flattens\n\t// these properties (likely due to specific comments in the TS definition).\n\t// See microsoft/vscode-languageserver-node#1698.\n\t//\n\t// TODO(hxjiang): delete the patch logic after releasing lsp 3.18.\n\tfor _, s := range model.Structures {\n\t\tif s.Name == \"RenameParams\" {\n\t\t\ts.Properties = slices.DeleteFunc(s.Properties, func(t NameType) bool {\n\t\t\t\treturn t.Name == \"position\" || t.Name == \"textDocument\"\n\t\t\t})\n\t\t\tif !slices.ContainsFunc(s.Extends, func(t *Type) bool {\n\t\t\t\treturn t.Kind == \"reference\" && t.Name == \"TextDocumentPositionParams\"\n\t\t\t}) {\n\t\t\t\ts.Extends = append(s.Extends, &Type{\n\t\t\t\t\tKind: \"reference\",\n\t\t\t\t\tName: \"TextDocumentPositionParams\",\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add a client to server LSP method \"command/resolve\" for interactive\n\t// refactoring. The method's param and result are both \"ExecuteCommandParams\".\n\t// The types are only accessible from the \"workspace/executeCommand\" request.\n\t//\n\t// See microsoft/language-server-protocol#1164.\n\tfor _, req := range model.Requests {\n\t\tif req.Method == \"workspace/executeCommand\" {\n\t\t\tmodel.Requests = append(model.Requests, &Request{\n\t\t\t\tMethod:    \"command/resolve\",\n\t\t\t\tErrorData: req.ErrorData,\n\t\t\t\tDirection: \"clientToServer\",\n\t\t\t\tParams:    req.Params,\n\t\t\t\tResult:    req.Params,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t}\n\n\tmodel.Requests = append(model.Requests, &Request{\n\t\tMethod:    \"interactive/listEnum\",\n\t\tDirection: \"clientToServer\",\n\t\tParams: &Type{\n\t\t\tKind: \"reference\",\n\t\t\tName: \"InteractiveListEnumParams\",\n\t\t},\n\t\tResult: &Type{\n\t\t\tKind: \"array\",\n\t\t\tElement: &Type{\n\t\t\t\tKind: \"reference\",\n\t\t\t\tName: \"FormEnumEntry\",\n\t\t\t},\n\t\t},\n\t})\n\n\tfindTypeNames(model)\n\tgenerateOutput(model)\n\n\tfileHdr = fileHeader(model)\n\n\t// write the files\n\twriteclient()\n\twriteserver()\n\twriteprotocol()\n\twritejsons()\n\n\tcheckTables()\n}\n\n// common file header for output files\nvar fileHdr string\n\nfunc writeclient() {\n\tout := new(bytes.Buffer)\n\tfmt.Fprintln(out, fileHdr)\n\tout.WriteString(\n\t\t`import (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n`)\n\tout.WriteString(\"type Client interface {\\n\")\n\tfor _, k := range cdecls.keys() {\n\t\tout.WriteString(cdecls[k])\n\t}\n\tout.WriteString(\"}\\n\\n\")\n\tout.WriteString(`\nfunc clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {\n\tresp, valid, err := ClientDispatchCall(ctx, client, r.Method(), r.Params())\n\tif !valid {\n\t\treturn false, nil\n\t}\n\n\tif err != nil {\n\t\treturn valid, reply(ctx, nil, err)\n\t} else {\n\t \treturn valid, reply(ctx, resp, nil)\n\t}\n}\n\nfunc ClientDispatchCall(ctx context.Context, client Client, method string, raw json.RawMessage) (resp any, _ bool, err error) {\n\tswitch method {\n`)\n\tfor _, k := range ccases.keys() {\n\t\tout.WriteString(ccases[k])\n\t}\n\tout.WriteString((\"\\tdefault:\\n\\t\\treturn nil, false, nil\\n\\t}\\n}\\n\\n\"))\n\tfor _, k := range cfuncs.keys() {\n\t\tout.WriteString(cfuncs[k])\n\t}\n\tformatTo(\"tsclient.go\", out.Bytes())\n}\n\nfunc writeserver() {\n\tout := new(bytes.Buffer)\n\tfmt.Fprintln(out, fileHdr)\n\tout.WriteString(\n\t\t`import (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n`)\n\tout.WriteString(\"type Server interface {\\n\")\n\tfor _, k := range sdecls.keys() {\n\t\tout.WriteString(sdecls[k])\n\t}\n\tout.WriteString(`\n}\nfunc serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {\n\tresp, valid, err := ServerDispatchCall(ctx, server, r.Method(), r.Params())\n\tif !valid {\n\t\treturn false, nil\n\t}\n\n\tif err != nil {\n\t\treturn valid, reply(ctx, nil, err)\n\t} else {\n\t \treturn valid, reply(ctx, resp, nil)\n\t}\n}\n\nfunc ServerDispatchCall(ctx context.Context, server Server, method string, raw json.RawMessage) (resp any, _ bool, err error) {\n\tswitch method {\n`)\n\tfor _, k := range scases.keys() {\n\t\tout.WriteString(scases[k])\n\t}\n\tout.WriteString((\"\\tdefault:\\n\\t\\treturn nil, false, nil\\n\\t}\\n}\\n\\n\"))\n\tfor _, k := range sfuncs.keys() {\n\t\tout.WriteString(sfuncs[k])\n\t}\n\tformatTo(\"tsserver.go\", out.Bytes())\n}\n\nfunc writeprotocol() {\n\tout := new(bytes.Buffer)\n\tfmt.Fprintln(out, fileHdr)\n\tout.WriteString(\"import \\\"encoding/json\\\"\\n\\n\")\n\n\t// The following are unneeded, but make the new code a superset of the old\n\thack := func(newer, existing string) {\n\t\tif _, ok := types[existing]; !ok {\n\t\t\tlog.Fatalf(\"types[%q] not found\", existing)\n\t\t}\n\t\ttypes[newer] = strings.Replace(types[existing], existing, newer, 1)\n\t}\n\thack(\"ConfigurationParams\", \"ParamConfiguration\")\n\thack(\"InitializeParams\", \"ParamInitialize\")\n\thack(\"PreviousResultId\", \"PreviousResultID\")\n\thack(\"WorkspaceFoldersServerCapabilities\", \"WorkspaceFolders5Gn\")\n\thack(\"_InitializeParams\", \"XInitializeParams\")\n\n\tfor _, k := range types.keys() {\n\t\tif k == \"WatchKind\" {\n\t\t\ttypes[k] = \"type WatchKind = uint32\" // strict gopls compatibility needs the '='\n\t\t}\n\t\tout.WriteString(types[k])\n\t}\n\n\tout.WriteString(\"\\nconst (\\n\")\n\tfor _, k := range consts.keys() {\n\t\tout.WriteString(consts[k])\n\t}\n\tout.WriteString(\")\\n\\n\")\n\tformatTo(\"tsprotocol.go\", out.Bytes())\n}\n\nfunc writejsons() {\n\tout := new(bytes.Buffer)\n\tfmt.Fprintln(out, fileHdr)\n\tout.WriteString(\"import \\\"encoding/json\\\"\\n\\n\")\n\tout.WriteString(\"import \\\"fmt\\\"\\n\")\n\n\tout.WriteString(`\n// UnmarshalError indicates that a JSON value did not conform to\n// one of the expected cases of an LSP union type.\ntype UnmarshalError struct {\n\tmsg string\n}\n\nfunc (e UnmarshalError) Error() string {\n\treturn e.msg\n}\n`)\n\n\tfor _, k := range jsons.keys() {\n\t\tout.WriteString(jsons[k])\n\t}\n\tformatTo(\"tsjson.go\", out.Bytes())\n}\n\n// formatTo formats the Go source and writes it to *outputdir/basename.\nfunc formatTo(basename string, src []byte) {\n\tformatted, err := format.Source(src)\n\tif err != nil {\n\t\tfailed := filepath.Join(\"/tmp\", basename+\".fail\")\n\t\tif err := os.WriteFile(failed, src, 0644); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tlog.Fatalf(\"formatting %s: %v (see %s)\", basename, err, failed)\n\t}\n\tif err := os.WriteFile(filepath.Join(*outputdir, basename), formatted, 0644); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\n// create the common file header for the output files\nfunc fileHeader(model *Model) string {\n\tfname := filepath.Join(*repodir, \".git\", \"HEAD\")\n\tbuf, err := os.ReadFile(fname)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tbuf = bytes.TrimSpace(buf)\n\tvar githash string\n\tif len(buf) == 40 {\n\t\tgithash = string(buf[:40])\n\t} else if bytes.HasPrefix(buf, []byte(\"ref: \")) {\n\t\tfname = filepath.Join(*repodir, \".git\", string(buf[5:]))\n\t\tbuf, err = os.ReadFile(fname)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tgithash = string(buf[:40])\n\t} else {\n\t\tlog.Fatalf(\"githash cannot be recovered from %s\", fname)\n\t}\n\n\tformat := `// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated for LSP. DO NOT EDIT.\n\npackage protocol\n\n// Code generated from %[1]s at ref %[2]s (hash %[3]s).\n// %[4]s/blob/%[2]s/%[1]s\n// LSP metaData.version = %[5]s.\n\n`\n\treturn fmt.Sprintf(format,\n\t\t\"protocol/metaModel.json\", // 1\n\t\tlspGitRef,                 // 2\n\t\tgithash,                   // 3\n\t\tvscodeRepo,                // 4\n\t\tmodel.Version.Version)     // 5\n}\n\nfunc parse(fname string) *Model {\n\tbuf, err := os.ReadFile(fname)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tbuf = addLineNumbers(buf)\n\tmodel := new(Model)\n\tif err := json.Unmarshal(buf, model); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn model\n}\n\n// Type.Value has to be treated specially for literals and maps\nfunc (t *Type) UnmarshalJSON(data []byte) error {\n\t// First unmarshal only the unambiguous fields.\n\tvar x struct {\n\t\tKind    string  `json:\"kind\"`\n\t\tItems   []*Type `json:\"items\"`\n\t\tElement *Type   `json:\"element\"`\n\t\tName    string  `json:\"name\"`\n\t\tKey     *Type   `json:\"key\"`\n\t\tValue   any     `json:\"value\"`\n\t\tLine    int     `json:\"line\"`\n\t}\n\tif err := json.Unmarshal(data, &x); err != nil {\n\t\treturn err\n\t}\n\t*t = Type{\n\t\tKind:    x.Kind,\n\t\tItems:   x.Items,\n\t\tElement: x.Element,\n\t\tName:    x.Name,\n\t\tValue:   x.Value,\n\t\tLine:    x.Line,\n\t}\n\n\t// Then unmarshal the 'value' field based on the kind.\n\t// This depends on Unmarshal ignoring fields it doesn't know about.\n\tswitch x.Kind {\n\tcase \"map\":\n\t\tvar x struct {\n\t\t\tKey   *Type `json:\"key\"`\n\t\t\tValue *Type `json:\"value\"`\n\t\t}\n\t\tif err := json.Unmarshal(data, &x); err != nil {\n\t\t\treturn fmt.Errorf(\"Type.kind=map: %v\", err)\n\t\t}\n\t\tt.Key = x.Key\n\t\tt.Value = x.Value\n\n\tcase \"literal\":\n\t\tvar z struct {\n\t\t\tValue ParseLiteral `json:\"value\"`\n\t\t}\n\n\t\tif err := json.Unmarshal(data, &z); err != nil {\n\t\t\treturn fmt.Errorf(\"Type.kind=literal: %v\", err)\n\t\t}\n\t\tt.Value = z.Value\n\n\tcase \"base\", \"reference\", \"array\", \"and\", \"or\", \"tuple\",\n\t\t\"stringLiteral\":\n\t\t// no-op. never seen integerLiteral or booleanLiteral.\n\n\tdefault:\n\t\treturn fmt.Errorf(\"cannot decode Type.kind %q: %s\", x.Kind, data)\n\t}\n\treturn nil\n}\n\n// which table entries were not used\nfunc checkTables() {\n\tfor k := range disambiguate {\n\t\tif !usedDisambiguate[k] {\n\t\t\tlog.Printf(\"disambiguate[%v] unused\", k)\n\t\t}\n\t}\n\tfor k := range renameProp {\n\t\tif !usedRenameProp[k] {\n\t\t\tlog.Printf(\"renameProp {%q, %q} unused\", k[0], k[1])\n\t\t}\n\t}\n\tfor k := range goplsStar {\n\t\tif !usedGoplsStar[k] {\n\t\t\tlog.Printf(\"goplsStar {%q, %q} unused\", k[0], k[1])\n\t\t}\n\t}\n\tfor k := range goplsType {\n\t\tif !usedGoplsType[k] {\n\t\t\tlog.Printf(\"unused goplsType[%q]->%s\", k, goplsType[k])\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/main_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"testing\"\n)\n\n// These tests require the result of\n//\"git clone https://github.com/microsoft/vscode-languageserver-node\" in the HOME directory\n\n// this is not a test, but a way to get code coverage,\n// (in vscode, just run the test with  \"go.coverOnSingleTest\": true)\nfunc TestAll(t *testing.T) {\n\tt.Skip(\"needs vscode-languageserver-node repository\")\n\t*lineNumbers = true\n\tlog.SetFlags(log.Lshortfile)\n\tmain()\n}\n\n// check that the parsed file includes all the information\n// from the json file. This test will fail if the spec\n// introduces new fields. (one can test this test by\n// commenting out the version field in Model.)\nfunc TestParseContents(t *testing.T) {\n\tt.Skip(\"needs vscode-languageserver-node repository\")\n\tlog.SetFlags(log.Lshortfile)\n\n\t// compute our parse of the specification\n\tdir := os.Getenv(\"HOME\") + \"/vscode-languageserver-node\"\n\tfname := dir + \"/protocol/metaModel.json\"\n\tv := parse(fname)\n\tout, err := json.Marshal(v)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar our any\n\tif err := json.Unmarshal(out, &our); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// process the json file\n\tbuf, err := os.ReadFile(fname)\n\tif err != nil {\n\t\tt.Fatalf(\"could not read metaModel.json: %v\", err)\n\t}\n\tvar raw any\n\tif err := json.Unmarshal(buf, &raw); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// convert to strings showing the fields\n\tthem := flatten(raw)\n\tus := flatten(our)\n\n\t// everything in them should be in us\n\tlesser := make(sortedMap[bool])\n\tfor _, s := range them {\n\t\tlesser[s] = true\n\t}\n\tgreater := make(sortedMap[bool]) // set of fields we have\n\tfor _, s := range us {\n\t\tgreater[s] = true\n\t}\n\tfor _, k := range lesser.keys() { // set if fields they have\n\t\tif !greater[k] {\n\t\t\tt.Errorf(\"missing %s\", k)\n\t\t}\n\t}\n}\n\n// flatten(nil) = \"nil\"\n// flatten(v string) = fmt.Sprintf(\"%q\", v)\n// flatten(v float64)= fmt.Sprintf(\"%g\", v)\n// flatten(v bool) = fmt.Sprintf(\"%v\", v)\n// flatten(v []any) = []string{\"[0]\"flatten(v[0]), \"[1]\"flatten(v[1]), ...}\n// flatten(v map[string]any) = {\"key1\": flatten(v[\"key1\"]), \"key2\": flatten(v[\"key2\"]), ...}\nfunc flatten(x any) []string {\n\tswitch v := x.(type) {\n\tcase nil:\n\t\treturn []string{\"nil\"}\n\tcase string:\n\t\treturn []string{fmt.Sprintf(\"%q\", v)}\n\tcase float64:\n\t\treturn []string{fmt.Sprintf(\"%g\", v)}\n\tcase bool:\n\t\treturn []string{fmt.Sprintf(\"%v\", v)}\n\tcase []any:\n\t\tvar ans []string\n\t\tfor i, x := range v {\n\t\t\tidx := fmt.Sprintf(\"[%.3d]\", i)\n\t\t\tfor _, s := range flatten(x) {\n\t\t\t\tans = append(ans, idx+s)\n\t\t\t}\n\t\t}\n\t\treturn ans\n\tcase map[string]any:\n\t\tvar ans []string\n\t\tfor k, x := range v {\n\t\t\tidx := fmt.Sprintf(\"%q:\", k)\n\t\t\tfor _, s := range flatten(x) {\n\t\t\t\tans = append(ans, idx+s)\n\t\t\t}\n\t\t}\n\t\treturn ans\n\tdefault:\n\t\tlog.Fatalf(\"unexpected type %T\", x)\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/output.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n)\n\nvar (\n\t// tsclient.go has 3 sections\n\tcdecls = make(sortedMap[string])\n\tccases = make(sortedMap[string])\n\tcfuncs = make(sortedMap[string])\n\t// tsserver.go has 3 sections\n\tsdecls = make(sortedMap[string])\n\tscases = make(sortedMap[string])\n\tsfuncs = make(sortedMap[string])\n\t// tsprotocol.go has 2 sections\n\ttypes  = make(sortedMap[string])\n\tconsts = make(sortedMap[string])\n\t// tsjson has 1 section\n\tjsons = make(sortedMap[string])\n)\n\nfunc generateOutput(model *Model) {\n\tfor _, r := range model.Requests {\n\t\tgenDecl(model, r.Method, r.Params, r.Result, r.Direction, r.Line == 0)\n\t\tgenCase(model, r.Method, r.Params, r.Result, r.Direction)\n\t\tgenFunc(model, r.Method, r.Params, r.Result, r.Direction, false)\n\t}\n\tfor _, n := range model.Notifications {\n\t\tif n.Method == \"$/cancelRequest\" {\n\t\t\tcontinue // handled internally by jsonrpc2\n\t\t}\n\t\tgenDecl(model, n.Method, n.Params, nil, n.Direction, n.Line == 0)\n\t\tgenCase(model, n.Method, n.Params, nil, n.Direction)\n\t\tgenFunc(model, n.Method, n.Params, nil, n.Direction, true)\n\t}\n\tgenStructs(model)\n\tgenAliases(model)\n\tgenGenTypes() // generate the unnamed types\n\tgenConsts(model)\n\tgenMarshal()\n}\n\nfunc genDecl(model *Model, method string, param, result *Type, dir string, experiment bool) {\n\tfname := methodName(method)\n\tp := \"\"\n\tif notNil(param) {\n\t\tp = \", *\" + goplsName(param)\n\t}\n\tret := \"error\"\n\tif notNil(result) {\n\t\ttp := goplsName(result)\n\t\tif !hasNilValue(tp) {\n\t\t\ttp = \"*\" + tp\n\t\t}\n\t\tret = fmt.Sprintf(\"(%s, error)\", tp)\n\t}\n\t// special gopls compatibility case (PJW: still needed?)\n\tswitch method {\n\tcase \"workspace/configuration\":\n\t\t// was And_Param_workspace_configuration, but the type substitution doesn't work,\n\t\t// as ParamConfiguration is embedded in And_Param_workspace_configuration\n\t\tp = \", *ParamConfiguration\"\n\t\tret = \"([]LSPAny, error)\"\n\t}\n\n\tvar msg string\n\t{\n\t\tvar sb strings.Builder\n\n\t\tif doc, ok := prependMethodDocComments[fname]; ok {\n\t\t\tsb.WriteString(doc)\n\t\t\tsb.WriteString(\"\\n\\t//\\n\")\n\t\t}\n\n\t\tif experiment {\n\t\t\tsb.WriteString(\"\\t// Note: This is a non-standard protocol extension.\\n\")\n\t\t} else {\n\t\t\tfragment := strings.ReplaceAll(strings.TrimPrefix(method, \"$/\"), \"/\", \"_\")\n\t\t\tfmt.Fprintf(&sb, \"\\t%s\", lspLink(model, fragment))\n\t\t}\n\n\t\tfmt.Fprintf(&sb, \"\\t%s(context.Context%s) %s\\n\", fname, p, ret)\n\n\t\tmsg = sb.String()\n\t}\n\n\tswitch dir {\n\tcase \"clientToServer\":\n\t\tsdecls[method] = msg\n\tcase \"serverToClient\":\n\t\tcdecls[method] = msg\n\tcase \"both\":\n\t\tsdecls[method] = msg\n\t\tcdecls[method] = msg\n\tdefault:\n\t\tlog.Fatalf(\"impossible direction %q\", dir)\n\t}\n}\n\nfunc genCase(model *Model, method string, param, result *Type, dir string) {\n\textends := func(x, y string) bool {\n\t\tfor _, struc := range model.Structures {\n\t\t\tif struc.Name == x {\n\t\t\t\tif contains := slices.ContainsFunc(struc.Extends, func(t *Type) bool {\n\t\t\t\t\treturn t.Name == y\n\t\t\t\t}); contains {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\tout := new(bytes.Buffer)\n\tfmt.Fprintf(out, \"\\tcase %q:\\n\", method)\n\tvar p string\n\tfname := methodName(method)\n\tif notNil(param) {\n\t\tnm := goplsName(param)\n\t\tif method == \"workspace/configuration\" { // gopls compatibility\n\t\t\t// was And_Param_workspace_configuration, which contains ParamConfiguration\n\t\t\t// so renaming the type leads to circular definitions\n\t\t\tnm = \"ParamConfiguration\" // gopls compatibility\n\t\t}\n\t\tfmt.Fprintf(out, \"\\t\\tvar params %s\\n\", nm)\n\t\tout.WriteString(\"\\t\\tif err := UnmarshalJSON(raw, &params); err != nil {\\n\")\n\t\tout.WriteString(\"\\t\\t\\treturn nil, true, fmt.Errorf(\\\"%%w: %%s\\\", jsonrpc2.ErrParse, err)\\n\\t\\t}\\n\")\n\t\tp = \", &params\"\n\n\t\t// Ensure consistency between Range and Position. If the client provides\n\t\t// only a Position, synthesize a zero-width Range at that location.\n\t\t//\n\t\t// Crucially, we do not clear the Position field. Since this request may\n\t\t// be forwarded, the downstream receiver (gopls) will re-validate that\n\t\t// the Position lies within the Range.\n\t\t//\n\t\t// TODO(hxjiang): define util function\n\t\t// func (*protocol.Position) EmptyRange() protocol.Range.\n\t\tif extends(nm, \"TextDocumentPositionParams\") {\n\t\t\tout.WriteString(`\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %%v is outside the provided range %%v.\", params.Position, params.Range)\n\t\t}\n`)\n\t\t}\n\n\t}\n\tif notNil(result) {\n\t\tfmt.Fprintf(out, \"\\t\\tresp, err := %%s.%s(ctx%s)\\n\", fname, p)\n\t\tout.WriteString(\"\\t\\tif err != nil {\\n\")\n\t\tout.WriteString(\"\\t\\t\\treturn nil, true, err\\n\")\n\t\tout.WriteString(\"\\t\\t}\\n\")\n\t\tout.WriteString(\"\\t\\treturn resp, true, nil\\n\")\n\t} else {\n\t\tfmt.Fprintf(out, \"\\t\\terr := %%s.%s(ctx%s)\\n\", fname, p)\n\t\tout.WriteString(\"\\t\\treturn nil, true, err\\n\")\n\t}\n\tout.WriteString(\"\\n\")\n\tmsg := out.String()\n\tswitch dir {\n\tcase \"clientToServer\":\n\t\tscases[method] = fmt.Sprintf(msg, \"server\")\n\tcase \"serverToClient\":\n\t\tccases[method] = fmt.Sprintf(msg, \"client\")\n\tcase \"both\":\n\t\tscases[method] = fmt.Sprintf(msg, \"server\")\n\t\tccases[method] = fmt.Sprintf(msg, \"client\")\n\tdefault:\n\t\tlog.Fatalf(\"impossible direction %q\", dir)\n\t}\n}\n\nfunc genFunc(_ *Model, method string, param, result *Type, dir string, isnotify bool) {\n\tout := new(bytes.Buffer)\n\tvar p, r string\n\tvar goResult string\n\tif notNil(param) {\n\t\tp = \", params *\" + goplsName(param)\n\t}\n\tif notNil(result) {\n\t\tgoResult = goplsName(result)\n\t\tif !hasNilValue(goResult) {\n\t\t\tgoResult = \"*\" + goResult\n\t\t}\n\t\tr = fmt.Sprintf(\"(%s, error)\", goResult)\n\t} else {\n\t\tr = \"error\"\n\t}\n\t// special gopls compatibility case\n\tswitch method {\n\tcase \"workspace/configuration\":\n\t\t// was And_Param_workspace_configuration, but the type substitution doesn't work,\n\t\t// as ParamConfiguration is embedded in And_Param_workspace_configuration\n\t\tp = \", params *ParamConfiguration\"\n\t\tr = \"([]LSPAny, error)\"\n\t\tgoResult = \"[]LSPAny\"\n\t}\n\tfname := methodName(method)\n\tfmt.Fprintf(out, \"func (s *%%sDispatcher) %s(ctx context.Context%s) %s {\\n\",\n\t\tfname, p, r)\n\n\tif !notNil(result) {\n\t\tif isnotify {\n\t\t\tif notNil(param) {\n\t\t\t\tfmt.Fprintf(out, \"\\treturn s.sender.Notify(ctx, %q, params)\\n\", method)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(out, \"\\treturn s.sender.Notify(ctx, %q, nil)\\n\", method)\n\t\t\t}\n\t\t} else {\n\t\t\tif notNil(param) {\n\t\t\t\tfmt.Fprintf(out, \"\\treturn s.sender.Call(ctx, %q, params, nil)\\n\", method)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(out, \"\\treturn s.sender.Call(ctx, %q, nil, nil)\\n\", method)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfmt.Fprintf(out, \"\\tvar result %s\\n\", goResult)\n\t\tif isnotify {\n\t\t\tif notNil(param) {\n\t\t\t\tfmt.Fprintf(out, \"\\ts.sender.Notify(ctx, %q, params)\\n\", method)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(out, \"\\t\\tif err := s.sender.Notify(ctx, %q, nil); err != nil {\\n\", method)\n\t\t\t}\n\t\t} else {\n\t\t\tif notNil(param) {\n\t\t\t\tfmt.Fprintf(out, \"\\t\\tif err := s.sender.Call(ctx, %q, params, &result); err != nil {\\n\", method)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(out, \"\\t\\tif err := s.sender.Call(ctx, %q, nil, &result); err != nil {\\n\", method)\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(out, \"\\t\\treturn nil, err\\n\\t}\\n\\treturn result, nil\\n\")\n\t}\n\tout.WriteString(\"}\\n\")\n\tmsg := out.String()\n\tswitch dir {\n\tcase \"clientToServer\":\n\t\tsfuncs[method] = fmt.Sprintf(msg, \"server\")\n\tcase \"serverToClient\":\n\t\tcfuncs[method] = fmt.Sprintf(msg, \"client\")\n\tcase \"both\":\n\t\tsfuncs[method] = fmt.Sprintf(msg, \"server\")\n\t\tcfuncs[method] = fmt.Sprintf(msg, \"client\")\n\tdefault:\n\t\tlog.Fatalf(\"impossible direction %q\", dir)\n\t}\n}\n\nfunc genStructs(model *Model) {\n\tstructures := make(map[string]*Structure) // for expanding Extends\n\tfor _, s := range model.Structures {\n\t\tstructures[s.Name] = s\n\t}\n\tfor _, s := range model.Structures {\n\t\tout := new(bytes.Buffer)\n\t\tgenerateDoc(out, s.Documentation)\n\t\tnm := goName(s.Name)\n\t\tif nm == \"string\" { // an unacceptable strut name\n\t\t\t// a weird case, and needed only so the generated code contains the old gopls code\n\t\t\tnm = \"DocumentDiagnosticParams\"\n\t\t}\n\t\tfmt.Fprintf(out, \"//\\n\")\n\t\tout.WriteString(lspLink(model, camelCase(s.Name)))\n\t\tfmt.Fprintf(out, \"type %s struct {%s\\n\", nm, linex(s.Line))\n\t\t// for gopls compatibility, embed most extensions, but expand the rest some day\n\t\tprops := slices.Clone(s.Properties)\n\t\tif s.Name == \"SymbolInformation\" { // but expand this one\n\t\t\tfor _, ex := range s.Extends {\n\t\t\t\tfmt.Fprintf(out, \"\\t// extends %s\\n\", ex.Name)\n\t\t\t\tprops = append(props, structures[ex.Name].Properties...)\n\t\t\t}\n\t\t\tgenProps(out, props, nm)\n\t\t} else {\n\t\t\tgenProps(out, props, nm)\n\t\t\tfor _, ex := range s.Extends {\n\t\t\t\tfmt.Fprintf(out, \"\\t%s\\n\", goName(ex.Name))\n\t\t\t}\n\t\t}\n\t\tfor _, ex := range s.Mixins {\n\t\t\tfmt.Fprintf(out, \"\\t%s\\n\", goName(ex.Name))\n\t\t}\n\t\t// TODO(hxjiang): clean this up after microsoft/language-server-protocol#377\n\t\t// is fixed and released.\n\t\tif nm == \"TextDocumentPositionParams\" {\n\t\t\tout.WriteString(\"\\t// Range is an optional field representing the user's text selection in the document.\\n\")\n\t\t\tout.WriteString(\"\\t// If provided, the Position must be contained within this range.\\n\")\n\t\t\tout.WriteString(\"\\t//\\n\")\n\t\t\tout.WriteString(\"\\t// Note: This is a non-standard protocol extension. See microsoft/language-server-protocol#377.\\n\")\n\t\t\tout.WriteString(\"\\tRange Range `json:\\\"range\\\"`\")\n\t\t}\n\t\tout.WriteString(\"}\\n\")\n\t\ttypes[nm] = out.String()\n\t}\n\n\t// base types\n\t// (For URI and DocumentURI, see ../uri.go.)\n\ttypes[\"LSPAny\"] = \"type LSPAny = any\\n\"\n\t// A special case, the only previously existing Or type\n\ttypes[\"DocumentDiagnosticReport\"] = \"type DocumentDiagnosticReport = Or_DocumentDiagnosticReport // (alias) \\n\"\n\n}\n\n// \"FooBar\" -> \"fooBar\"\nfunc camelCase(TitleCased string) string {\n\treturn strings.ToLower(TitleCased[:1]) + TitleCased[1:]\n}\n\nfunc lspLink(model *Model, fragment string) string {\n\t// Derive URL version from metaData.version in JSON file.\n\tparts := strings.Split(model.Version.Version, \".\") // e.g. \"3.17.0\"\n\treturn fmt.Sprintf(\"// See https://microsoft.github.io/language-server-protocol/specifications/lsp/%s.%s/specification#%s\\n\",\n\t\tparts[0], parts[1], // major.minor\n\t\tfragment)\n}\n\nfunc genProps(out *bytes.Buffer, props []NameType, name string) {\n\tfor _, p := range props {\n\t\ttp := goplsName(p.Type)\n\t\tif newNm, ok := renameProp[prop{name, p.Name}]; ok {\n\t\t\tusedRenameProp[prop{name, p.Name}] = true\n\t\t\tif tp == newNm {\n\t\t\t\tlog.Printf(\"renameProp useless {%q, %q} for %s\", name, p.Name, tp)\n\t\t\t}\n\t\t\ttp = newNm\n\t\t}\n\t\t// it's a pointer if it is optional, or for gopls compatibility\n\t\tomit, star := propStar(name, p, tp)\n\t\tjson := fmt.Sprintf(\" `json:\\\"%s\\\"`\", p.Name)\n\t\tif omit {\n\t\t\tjson = fmt.Sprintf(\" `json:\\\"%s,omitempty\\\"`\", p.Name)\n\t\t}\n\t\tgenerateDoc(out, p.Documentation)\n\t\tif docs := appendTypePropDocComments[name]; docs != nil {\n\t\t\tif doc, ok := docs[p.Name]; ok {\n\t\t\t\tout.WriteString(doc)\n\t\t\t}\n\t\t}\n\t\tif star {\n\t\t\tfmt.Fprintf(out, \"\\t%s *%s %s\\n\", goName(p.Name), tp, json)\n\t\t} else {\n\t\t\tfmt.Fprintf(out, \"\\t%s %s %s\\n\", goName(p.Name), tp, json)\n\t\t}\n\t}\n\n\tif block, ok := appendTypeProp[name]; ok {\n\t\tout.WriteString(block)\n\t}\n}\n\nfunc genAliases(model *Model) {\n\tfor _, ta := range model.TypeAliases {\n\t\tout := new(bytes.Buffer)\n\t\tgenerateDoc(out, ta.Documentation)\n\t\tnm := goName(ta.Name)\n\t\tif nm != ta.Name {\n\t\t\tcontinue // renamed the type, e.g., \"DocumentDiagnosticReport\", an or-type to \"string\"\n\t\t}\n\t\ttp := goplsName(ta.Type)\n\t\tfmt.Fprintf(out, \"//\\n\")\n\t\tout.WriteString(lspLink(model, camelCase(ta.Name)))\n\t\tfmt.Fprintf(out, \"type %s = %s // (alias)\\n\", nm, tp)\n\t\ttypes[nm] = out.String()\n\t}\n}\n\nfunc genGenTypes() {\n\tfor _, nt := range genTypes {\n\t\tout := new(bytes.Buffer)\n\t\tnm := goplsName(nt.typ)\n\t\tswitch nt.kind {\n\t\tcase \"literal\":\n\t\t\tfmt.Fprintf(out, \"// created for Literal (%s)\\n\", nt.name)\n\t\t\tfmt.Fprintf(out, \"type %s struct {%s\\n\", nm, linex(nt.line+1))\n\t\t\tgenProps(out, nt.properties, nt.name) // systematic name, not gopls name; is this a good choice?\n\t\tcase \"or\":\n\t\t\tif !strings.HasPrefix(nm, \"Or\") {\n\t\t\t\t// It was replaced by a narrower type defined elsewhere\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnames := []string{}\n\t\t\tfor _, t := range nt.items {\n\t\t\t\tif notNil(t) {\n\t\t\t\t\tnames = append(names, goplsName(t))\n\t\t\t\t}\n\t\t\t}\n\t\t\tsort.Strings(names)\n\t\t\tfmt.Fprintf(out, \"// created for Or %v\\n\", names)\n\t\t\tfmt.Fprintf(out, \"type %s struct {%s\\n\", nm, linex(nt.line+1))\n\t\t\tfmt.Fprintf(out, \"\\tValue any `json:\\\"value\\\"`\\n\")\n\t\tcase \"and\":\n\t\t\tfmt.Fprintf(out, \"// created for And\\n\")\n\t\t\tfmt.Fprintf(out, \"type %s struct {%s\\n\", nm, linex(nt.line+1))\n\t\t\tfor _, x := range nt.items {\n\t\t\t\tnm := goplsName(x)\n\t\t\t\tfmt.Fprintf(out, \"\\t%s\\n\", nm)\n\t\t\t}\n\t\tcase \"tuple\": // there's only this one\n\t\t\tnt.name = \"UIntCommaUInt\"\n\t\t\tfmt.Fprintf(out, \"//created for Tuple\\ntype %s struct {%s\\n\", nm, linex(nt.line+1))\n\t\t\tfmt.Fprintf(out, \"\\tFld0 uint32 `json:\\\"fld0\\\"`\\n\")\n\t\t\tfmt.Fprintf(out, \"\\tFld1 uint32 `json:\\\"fld1\\\"`\\n\")\n\t\tdefault:\n\t\t\tlog.Fatalf(\"%s not handled\", nt.kind)\n\t\t}\n\t\tout.WriteString(\"}\\n\")\n\t\ttypes[nm] = out.String()\n\t}\n}\nfunc genConsts(model *Model) {\n\tfor _, e := range model.Enumerations {\n\t\tout := new(bytes.Buffer)\n\t\tgenerateDoc(out, e.Documentation)\n\t\ttp := goplsName(e.Type)\n\t\tnm := goName(e.Name)\n\t\tfmt.Fprintf(out, \"type %s %s%s\\n\", nm, tp, linex(e.Line))\n\t\ttypes[nm] = out.String()\n\t\tvals := new(bytes.Buffer)\n\t\tgenerateDoc(vals, e.Documentation)\n\t\tfor _, v := range e.Values {\n\t\t\tgenerateDoc(vals, v.Documentation)\n\t\t\tnm := goName(v.Name)\n\t\t\tmore, ok := disambiguate[e.Name]\n\t\t\tif ok {\n\t\t\t\tusedDisambiguate[e.Name] = true\n\t\t\t\tnm = more.prefix + nm + more.suffix\n\t\t\t\tnm = goName(nm) // stringType\n\t\t\t}\n\t\t\tvar val string\n\t\t\tswitch v := v.Value.(type) {\n\t\t\tcase string:\n\t\t\t\tval = fmt.Sprintf(\"%q\", v)\n\t\t\tcase float64:\n\t\t\t\tval = fmt.Sprintf(\"%d\", int(v))\n\t\t\tdefault:\n\t\t\t\tlog.Fatalf(\"impossible type %T\", v)\n\t\t\t}\n\t\t\tfmt.Fprintf(vals, \"\\t%s %s = %s%s\\n\", nm, e.Name, val, linex(v.Line))\n\t\t}\n\t\tconsts[nm] = vals.String()\n\t}\n}\nfunc genMarshal() {\n\tfor _, nt := range genTypes {\n\t\tnm := goplsName(nt.typ)\n\t\tif !strings.HasPrefix(nm, \"Or\") {\n\t\t\tcontinue\n\t\t}\n\t\tnames := []string{}\n\t\tfor _, t := range nt.items {\n\t\t\tif notNil(t) {\n\t\t\t\tnames = append(names, goplsName(t))\n\t\t\t}\n\t\t}\n\t\tsort.Strings(names)\n\t\tvar buf bytes.Buffer\n\t\tfmt.Fprintf(&buf, \"func (t %s) MarshalJSON() ([]byte, error) {\\n\", nm)\n\t\tbuf.WriteString(\"\\tswitch x := t.Value.(type){\\n\")\n\t\tfor _, nmx := range names {\n\t\t\tfmt.Fprintf(&buf, \"\\tcase %s:\\n\", nmx)\n\t\t\tfmt.Fprintf(&buf, \"\\t\\treturn json.Marshal(x)\\n\")\n\t\t}\n\t\tbuf.WriteString(\"\\tcase nil:\\n\\t\\treturn []byte(\\\"null\\\"), nil\\n\\t}\\n\")\n\t\tfmt.Fprintf(&buf, \"\\treturn nil, fmt.Errorf(\\\"type %%T not one of %v\\\", t)\\n\", names)\n\t\tbuf.WriteString(\"}\\n\\n\")\n\n\t\tfmt.Fprintf(&buf, \"func (t *%s) UnmarshalJSON(x []byte) error {\\n\", nm)\n\t\tbuf.WriteString(\"\\tif string(x) == \\\"null\\\" {\\n\\t\\tt.Value = nil\\n\\t\\t\\treturn nil\\n\\t}\\n\")\n\t\tfor i, nmx := range names {\n\t\t\tfmt.Fprintf(&buf, \"\\tvar h%d %s\\n\", i, nmx)\n\t\t\tfmt.Fprintf(&buf, \"\\tif err := json.Unmarshal(x, &h%d); err == nil {\\n\\t\\tt.Value = h%d\\n\\t\\t\\treturn nil\\n\\t\\t}\\n\", i, i)\n\t\t}\n\t\tfmt.Fprintf(&buf, \"return &UnmarshalError{\\\"unmarshal failed to match one of %v\\\"}\", names)\n\t\tbuf.WriteString(\"}\\n\\n\")\n\t\tjsons[nm] = buf.String()\n\t}\n}\n\nfunc linex(n int) string {\n\tif *lineNumbers {\n\t\treturn fmt.Sprintf(\" // line %d\", n)\n\t}\n\treturn \"\"\n}\n\nfunc goplsName(t *Type) string {\n\tnm := typeNames[t]\n\t// translate systematic name to gopls name\n\tif newNm, ok := goplsType[nm]; ok {\n\t\tusedGoplsType[nm] = true\n\t\tnm = newNm\n\t}\n\treturn nm\n}\n\nfunc notNil(t *Type) bool { // shutdwon is the special case that needs this\n\treturn t != nil && (t.Kind != \"base\" || t.Name != \"null\")\n}\n\nfunc hasNilValue(t string) bool {\n\t// this may be unreliable, and need a supplementary table\n\tif strings.HasPrefix(t, \"[]\") || strings.HasPrefix(t, \"*\") {\n\t\treturn true\n\t}\n\tif t == \"interface{}\" || t == \"any\" {\n\t\treturn true\n\t}\n\t// that's all the cases that occur currently\n\treturn false\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/tables.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport \"log\"\n\n// prop combines the name of a property (class.field) with the name of\n// the structure it is in, using LSP field capitalization.\ntype prop [2]string\n\nconst (\n\tnothing     = iota\n\twantOpt     // omitempty\n\twantOptStar // omitempty, indirect\n)\n\n// goplsStar records the optionality of each field in the protocol.\n// The comments are vague hints as to why removing the line is not trivial.\n// A.B.C.D means that one of B or C would change to a pointer\n// so a test or initialization would be needed\nvar goplsStar = map[prop]int{\n\t{\"AnnotatedTextEdit\", \"annotationId\"}:  wantOptStar,\n\t{\"ClientCapabilities\", \"textDocument\"}: wantOpt, // A.B.C.D at fake/editor.go:255\n\t{\"ClientCapabilities\", \"window\"}:       wantOpt, // test failures\n\t{\"ClientCapabilities\", \"workspace\"}:    wantOpt, // test failures\n\t{\"CodeAction\", \"kind\"}:                 wantOpt, // A.B.C.D\n\n\t{\"CodeActionClientCapabilities\", \"codeActionLiteralSupport\"}: wantOpt, // test failures\n\n\t{\"CompletionClientCapabilities\", \"completionItem\"}: wantOpt, // A.B.C.D\n\t{\"CompletionClientCapabilities\", \"insertTextMode\"}: wantOpt, // A.B.C.D\n\t{\"CompletionItem\", \"kind\"}:                         wantOpt, // need temporary variables\n\t{\"CompletionParams\", \"context\"}:                    wantOpt, // needs nil checks\n\n\t{\"Diagnostic\", \"severity\"}:            wantOpt,     // needs nil checks or more careful thought\n\t{\"DidSaveTextDocumentParams\", \"text\"}: wantOptStar, // capabilities_test.go:112 logic\n\t{\"DocumentHighlight\", \"kind\"}:         wantOpt,     // need temporary variables\n\n\t{\"FoldingRange\", \"startLine\"}:      wantOptStar, // unset != zero (#71489)\n\t{\"FoldingRange\", \"startCharacter\"}: wantOptStar, // unset != zero (#71489)\n\t{\"FoldingRange\", \"endLine\"}:        wantOptStar, // unset != zero (#71489)\n\t{\"FoldingRange\", \"endCharacter\"}:   wantOptStar, // unset != zero (#71489)\n\n\t{\"Hover\", \"range\"}:    wantOpt, // complex expressions\n\t{\"InlayHint\", \"kind\"}: wantOpt, // temporary variables\n\n\t{\"PublishDiagnosticsParams\", \"version\"}:                   wantOpt,     // zero => missing (#73501)\n\t{\"SignatureHelp\", \"activeParameter\"}:                      wantOptStar, // unset != zero\n\t{\"SignatureInformation\", \"activeParameter\"}:               wantOptStar, // unset != zero\n\t{\"TextDocumentClientCapabilities\", \"codeAction\"}:          wantOpt,     // A.B.C.D\n\t{\"TextDocumentClientCapabilities\", \"completion\"}:          wantOpt,     // A.B.C.D\n\t{\"TextDocumentClientCapabilities\", \"documentSymbol\"}:      wantOpt,     // A.B.C.D\n\t{\"TextDocumentClientCapabilities\", \"publishDiagnostics\"}:  wantOpt,     // A.B.C.D\n\t{\"TextDocumentClientCapabilities\", \"semanticTokens\"}:      wantOpt,     // A.B.C.D\n\t{\"TextDocumentContentChangePartial\", \"range\"}:             wantOptStar, // == nil test\n\t{\"TextDocumentContentChangePartial\", \"rangeLength\"}:       wantOptStar, // unset != zero\n\t{\"TextDocumentSyncOptions\", \"change\"}:                     wantOpt,     // &constant\n\t{\"WorkDoneProgressBegin\", \"percentage\"}:                   wantOptStar, // unset != zero\n\t{\"WorkDoneProgressParams\", \"workDoneToken\"}:               wantOpt,     // test failures\n\t{\"WorkDoneProgressReport\", \"percentage\"}:                  wantOptStar, // unset != zero\n\t{\"WorkspaceClientCapabilities\", \"didChangeConfiguration\"}: wantOpt,     // A.B.C.D\n\t{\"WorkspaceClientCapabilities\", \"didChangeWatchedFiles\"}:  wantOpt,     // A.B.C.D\n}\n\n// keep track of which entries in goplsStar are used\nvar usedGoplsStar = make(map[prop]bool)\n\n// For gopls compatibility, use a different, typically more restrictive, type for some fields.\nvar renameProp = map[prop]string{\n\t{\"CancelParams\", \"id\"}:   \"any\",\n\t{\"Command\", \"arguments\"}: \"[]json.RawMessage\",\n\t{\"CodeAction\", \"data\"}:   \"json.RawMessage\", // delay unmarshalling commands\n\t{\"Diagnostic\", \"code\"}:   \"any\",\n\t{\"Diagnostic\", \"data\"}:   \"json.RawMessage\", // delay unmarshalling quickfixes\n\n\t{\"DocumentDiagnosticReportPartialResult\", \"relatedDocuments\"}: \"map[DocumentURI]any\",\n\n\t{\"ExecuteCommandParams\", \"arguments\"}: \"[]json.RawMessage\",\n\t{\"FoldingRange\", \"kind\"}:              \"string\",\n\t{\"Hover\", \"contents\"}:                 \"MarkupContent\",\n\t{\"InlayHint\", \"label\"}:                \"[]InlayHintLabelPart\",\n\n\t{\"RelatedFullDocumentDiagnosticReport\", \"relatedDocuments\"}:      \"map[DocumentURI]any\",\n\t{\"RelatedUnchangedDocumentDiagnosticReport\", \"relatedDocuments\"}: \"map[DocumentURI]any\",\n\n\t// PJW: this one is tricky.\n\t{\"ServerCapabilities\", \"codeActionProvider\"}: \"any\",\n\n\t{\"ServerCapabilities\", \"inlayHintProvider\"}: \"any\",\n\t// slightly tricky\n\t{\"ServerCapabilities\", \"renameProvider\"}: \"any\",\n\t// slightly tricky\n\t{\"ServerCapabilities\", \"semanticTokensProvider\"}: \"any\",\n\t// slightly tricky\n\t{\"ServerCapabilities\", \"textDocumentSync\"}: \"any\",\n\t{\"TextDocumentSyncOptions\", \"save\"}:        \"SaveOptions\",\n\t{\"WorkspaceEdit\", \"documentChanges\"}:       \"[]DocumentChange\",\n}\n\n// which entries of renameProp were used\nvar usedRenameProp = make(map[prop]bool)\n\ntype adjust struct {\n\tprefix, suffix string\n}\n\n// disambiguate specifies prefixes or suffixes to add to all values of\n// some enum types to avoid name conflicts\nvar disambiguate = map[string]adjust{\n\t\"CodeActionTriggerKind\":        {\"CodeAction\", \"\"},\n\t\"CompletionItemKind\":           {\"\", \"Completion\"},\n\t\"CompletionItemTag\":            {\"Compl\", \"\"},\n\t\"DiagnosticSeverity\":           {\"Severity\", \"\"},\n\t\"DocumentDiagnosticReportKind\": {\"Diagnostic\", \"\"},\n\t\"FileOperationPatternKind\":     {\"\", \"Pattern\"},\n\t\"InlineCompletionTriggerKind\":  {\"Inline\", \"\"},\n\t\"InsertTextFormat\":             {\"\", \"TextFormat\"},\n\t\"LanguageKind\":                 {\"Lang\", \"\"},\n\t\"SemanticTokenModifiers\":       {\"Mod\", \"\"},\n\t\"SemanticTokenTypes\":           {\"\", \"Type\"},\n\t\"SignatureHelpTriggerKind\":     {\"Sig\", \"\"},\n\t\"SymbolTag\":                    {\"\", \"Symbol\"},\n\t\"WatchKind\":                    {\"Watch\", \"\"},\n}\n\n// which entries of disambiguate got used\nvar usedDisambiguate = make(map[string]bool)\n\n// for gopls compatibility, replace generated type names with existing ones\nvar goplsType = map[string]string{\n\t\"And_RegOpt_textDocument_colorPresentation\": \"WorkDoneProgressOptionsAndTextDocumentRegistrationOptions\",\n\t\"ConfigurationParams\":                       \"ParamConfiguration\",\n\t\"DocumentUri\":                               \"DocumentURI\",\n\t\"InitializeParams\":                          \"ParamInitialize\",\n\t\"LSPAny\":                                    \"any\",\n\n\t\"Lit_SemanticTokensOptions_range_Item1\": \"PRangeESemanticTokensOptions\",\n\n\t\"Or_Declaration\": \"[]Location\",\n\t\"Or_DidChangeConfigurationRegistrationOptions_section\": \"OrPSection_workspace_didChangeConfiguration\",\n\t\"Or_InlayHintLabelPart_tooltip\":                        \"OrPTooltipPLabel\",\n\t\"Or_InlayHint_tooltip\":                                 \"OrPTooltip_textDocument_inlayHint\",\n\t\"Or_LSPAny\":                                            \"any\",\n\n\t\"Or_ParameterInformation_documentation\":            \"string\",\n\t\"Or_ParameterInformation_label\":                    \"string\",\n\t\"Or_PrepareRenameResult\":                           \"PrepareRenamePlaceholder\",\n\t\"Or_ProgressToken\":                                 \"any\",\n\t\"Or_Result_textDocument_completion\":                \"CompletionList\",\n\t\"Or_Result_textDocument_declaration\":               \"Or_textDocument_declaration\",\n\t\"Or_Result_textDocument_definition\":                \"[]Location\",\n\t\"Or_Result_textDocument_documentSymbol\":            \"[]any\",\n\t\"Or_Result_textDocument_implementation\":            \"[]Location\",\n\t\"Or_Result_textDocument_semanticTokens_full_delta\": \"any\",\n\t\"Or_Result_textDocument_typeDefinition\":            \"[]Location\",\n\t\"Or_Result_workspace_symbol\":                       \"[]SymbolInformation\",\n\t\"Or_TextDocumentContentChangeEvent\":                \"TextDocumentContentChangePartial\",\n\t\"Or_RelativePattern_baseUri\":                       \"DocumentURI\",\n\n\t\"Or_WorkspaceFoldersServerCapabilities_changeNotifications\": \"string\",\n\t\"Or_WorkspaceSymbol_location\":                               \"OrPLocation_workspace_symbol\",\n\n\t\"Tuple_ParameterInformation_label_Item1\": \"UIntCommaUInt\",\n\t\"WorkspaceFoldersServerCapabilities\":     \"WorkspaceFolders5Gn\",\n\t\"[]LSPAny\":                               \"[]any\",\n\n\t\"[]Or_Result_textDocument_codeAction_Item0_Elem\": \"[]CodeAction\",\n\t\"[]PreviousResultId\":                             \"[]PreviousResultID\",\n\t\"[]uinteger\":                                     \"[]uint32\",\n\t\"boolean\":                                        \"bool\",\n\t\"decimal\":                                        \"float64\",\n\t\"integer\":                                        \"int32\",\n\t\"map[DocumentUri][]TextEdit\":                     \"map[DocumentURI][]TextEdit\",\n\t\"uinteger\":                                       \"uint32\",\n}\n\nvar usedGoplsType = make(map[string]bool)\n\n// methodNames is a map from the method to the name of the function that handles it\nvar methodNames = map[string]string{\n\t\"$/cancelRequest\":                        \"CancelRequest\",\n\t\"$/logTrace\":                             \"LogTrace\",\n\t\"$/progress\":                             \"Progress\",\n\t\"$/setTrace\":                             \"SetTrace\",\n\t\"callHierarchy/incomingCalls\":            \"IncomingCalls\",\n\t\"callHierarchy/outgoingCalls\":            \"OutgoingCalls\",\n\t\"client/registerCapability\":              \"RegisterCapability\",\n\t\"client/unregisterCapability\":            \"UnregisterCapability\",\n\t\"codeAction/resolve\":                     \"ResolveCodeAction\",\n\t\"codeLens/resolve\":                       \"ResolveCodeLens\",\n\t\"completionItem/resolve\":                 \"ResolveCompletionItem\",\n\t\"command/resolve\":                        \"ResolveCommand\",\n\t\"documentLink/resolve\":                   \"ResolveDocumentLink\",\n\t\"exit\":                                   \"Exit\",\n\t\"initialize\":                             \"Initialize\",\n\t\"initialized\":                            \"Initialized\",\n\t\"inlayHint/resolve\":                      \"Resolve\",\n\t\"interactive/listEnum\":                   \"InteractiveListEnum\",\n\t\"notebookDocument/didChange\":             \"DidChangeNotebookDocument\",\n\t\"notebookDocument/didClose\":              \"DidCloseNotebookDocument\",\n\t\"notebookDocument/didOpen\":               \"DidOpenNotebookDocument\",\n\t\"notebookDocument/didSave\":               \"DidSaveNotebookDocument\",\n\t\"shutdown\":                               \"Shutdown\",\n\t\"telemetry/event\":                        \"Event\",\n\t\"textDocument/codeAction\":                \"CodeAction\",\n\t\"textDocument/codeLens\":                  \"CodeLens\",\n\t\"textDocument/colorPresentation\":         \"ColorPresentation\",\n\t\"textDocument/completion\":                \"Completion\",\n\t\"textDocument/declaration\":               \"Declaration\",\n\t\"textDocument/definition\":                \"Definition\",\n\t\"textDocument/diagnostic\":                \"Diagnostic\",\n\t\"textDocument/didChange\":                 \"DidChange\",\n\t\"textDocument/didClose\":                  \"DidClose\",\n\t\"textDocument/didOpen\":                   \"DidOpen\",\n\t\"textDocument/didSave\":                   \"DidSave\",\n\t\"textDocument/documentColor\":             \"DocumentColor\",\n\t\"textDocument/documentHighlight\":         \"DocumentHighlight\",\n\t\"textDocument/documentLink\":              \"DocumentLink\",\n\t\"textDocument/documentSymbol\":            \"DocumentSymbol\",\n\t\"textDocument/foldingRange\":              \"FoldingRange\",\n\t\"textDocument/formatting\":                \"Formatting\",\n\t\"textDocument/hover\":                     \"Hover\",\n\t\"textDocument/implementation\":            \"Implementation\",\n\t\"textDocument/inlayHint\":                 \"InlayHint\",\n\t\"textDocument/inlineCompletion\":          \"InlineCompletion\",\n\t\"textDocument/inlineValue\":               \"InlineValue\",\n\t\"textDocument/linkedEditingRange\":        \"LinkedEditingRange\",\n\t\"textDocument/moniker\":                   \"Moniker\",\n\t\"textDocument/onTypeFormatting\":          \"OnTypeFormatting\",\n\t\"textDocument/prepareCallHierarchy\":      \"PrepareCallHierarchy\",\n\t\"textDocument/prepareRename\":             \"PrepareRename\",\n\t\"textDocument/prepareTypeHierarchy\":      \"PrepareTypeHierarchy\",\n\t\"textDocument/publishDiagnostics\":        \"PublishDiagnostics\",\n\t\"textDocument/rangeFormatting\":           \"RangeFormatting\",\n\t\"textDocument/rangesFormatting\":          \"RangesFormatting\",\n\t\"textDocument/references\":                \"References\",\n\t\"textDocument/rename\":                    \"Rename\",\n\t\"textDocument/selectionRange\":            \"SelectionRange\",\n\t\"textDocument/semanticTokens/full\":       \"SemanticTokensFull\",\n\t\"textDocument/semanticTokens/full/delta\": \"SemanticTokensFullDelta\",\n\t\"textDocument/semanticTokens/range\":      \"SemanticTokensRange\",\n\t\"textDocument/signatureHelp\":             \"SignatureHelp\",\n\t\"textDocument/typeDefinition\":            \"TypeDefinition\",\n\t\"textDocument/willSave\":                  \"WillSave\",\n\t\"textDocument/willSaveWaitUntil\":         \"WillSaveWaitUntil\",\n\t\"typeHierarchy/subtypes\":                 \"Subtypes\",\n\t\"typeHierarchy/supertypes\":               \"Supertypes\",\n\t\"window/logMessage\":                      \"LogMessage\",\n\t\"window/showDocument\":                    \"ShowDocument\",\n\t\"window/showMessage\":                     \"ShowMessage\",\n\t\"window/showMessageRequest\":              \"ShowMessageRequest\",\n\t\"window/workDoneProgress/cancel\":         \"WorkDoneProgressCancel\",\n\t\"window/workDoneProgress/create\":         \"WorkDoneProgressCreate\",\n\t\"workspace/applyEdit\":                    \"ApplyEdit\",\n\t\"workspace/codeLens/refresh\":             \"CodeLensRefresh\",\n\t\"workspace/configuration\":                \"Configuration\",\n\t\"workspace/diagnostic\":                   \"DiagnosticWorkspace\",\n\t\"workspace/diagnostic/refresh\":           \"DiagnosticRefresh\",\n\t\"workspace/didChangeConfiguration\":       \"DidChangeConfiguration\",\n\t\"workspace/didChangeWatchedFiles\":        \"DidChangeWatchedFiles\",\n\t\"workspace/didChangeWorkspaceFolders\":    \"DidChangeWorkspaceFolders\",\n\t\"workspace/didCreateFiles\":               \"DidCreateFiles\",\n\t\"workspace/didDeleteFiles\":               \"DidDeleteFiles\",\n\t\"workspace/didRenameFiles\":               \"DidRenameFiles\",\n\t\"workspace/executeCommand\":               \"ExecuteCommand\",\n\t\"workspace/foldingRange/refresh\":         \"FoldingRangeRefresh\",\n\t\"workspace/inlayHint/refresh\":            \"InlayHintRefresh\",\n\t\"workspace/inlineValue/refresh\":          \"InlineValueRefresh\",\n\t\"workspace/semanticTokens/refresh\":       \"SemanticTokensRefresh\",\n\t\"workspace/symbol\":                       \"Symbol\",\n\t\"workspace/textDocumentContent\":          \"TextDocumentContent\",\n\t\"workspace/textDocumentContent/refresh\":  \"TextDocumentContentRefresh\",\n\t\"workspace/willCreateFiles\":              \"WillCreateFiles\",\n\t\"workspace/willDeleteFiles\":              \"WillDeleteFiles\",\n\t\"workspace/willRenameFiles\":              \"WillRenameFiles\",\n\t\"workspace/workspaceFolders\":             \"WorkspaceFolders\",\n\t\"workspaceSymbol/resolve\":                \"ResolveWorkspaceSymbol\",\n}\n\nfunc methodName(method string) string {\n\tans := methodNames[method]\n\tif ans == \"\" {\n\t\tlog.Fatalf(\"unknown method %q\", method)\n\t}\n\treturn ans\n}\n\n// prependMethodDocComments specifies doc comments that will be prepend to\n// an LSP method name defined in both Server and Client interface.\nvar prependMethodDocComments = map[string]string{\n\t\"ResolveCommand\": `// To support microsoft/language-server-protocol#1164, the language server\n\t// need to read the form with client-supplied answers and either returns an\n\t// ExecuteCommandParams with errors in the form surfacing the error to the\n\t// client, or an ExecuteCommandParams with interactive properties empty (e.g\n\t// formFields, formAnswers) and user information integrated in original\n\t// properties.\n\t//\n\t// The language client may call \"command/resolve\" if the language server\n\t// returns an ExecuteCommandParams with errors or try asking the user for\n\t// completing the form again.\n\t// The language client may call \"command/resolve\" multiple times with user\n\t// filled (re-filled) answers in the form until it obtains an\n\t// ExecuteCommandParams with interactive properties empty (e.g. formFields,\n\t// formAnswers). by then the original properties contains all information,\n\t// the client can call \"workspace/executeCommand\" with the same param.\n\t//\n\t// Standard resolution (e.g., \"codeAction/resolve\") cannot be used here because\n\t// it is often triggered eagerly (e.g., for previews), prohibiting interactive\n\t// forms. \"command/resolve\" is introduced to handle the interactive flow\n\t// strictly *after* the user has explicitly indicated intention (e.g., by\n\t// clicking), making it safe for Code Actions and other refactorings.`,\n\t\"InteractiveListEnum\": `// InteractiveListEnum is the request handler for fetching dynamic enum options.\n\t//\n\t// This method is called by the client when the user interacts with a\n\t// FormFieldTypeLazyEnum field (e.g., typing in a combo box). The server\n\t// uses the provided Action and Params to determine the context (e.g.,\n\t// \"search workspace symbols for interfaces\") and returns a filtered list\n\t// of matching entries.`,\n}\n\n// prependMethodDocComments specifies doc comments that will be prepend to\n// an LSP type's properties existing doc comments.\nvar appendTypePropDocComments = map[string]map[string]string{\n\t\"TextDocumentPositionParams\": {\"position\": `\t//\n\t// Deprecated: gopls should use [TextDocumentPositionParams.Range] instead.\n`},\n}\n\n// appendTypeProp specifies block of code (typically properties with doc comment)\n// that will be append to a struct.\nvar appendTypeProp = map[string]string{\n\t\"ExecuteCommandParams\": `\n\t// Support interactive command execution.\n\t//\n\t// Note: This is a non-standard protocol extension. See golang/go#76331.\n\tInteractiveParams\n`,\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/typenames.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n)\n\nvar typeNames = make(map[*Type]string)\nvar genTypes []*newType\n\nfunc findTypeNames(model *Model) {\n\tfor _, s := range model.Structures {\n\t\tfor _, e := range s.Extends {\n\t\t\tnameType(e, nil) // all references\n\t\t}\n\t\tfor _, m := range s.Mixins {\n\t\t\tnameType(m, nil) // all references\n\t\t}\n\t\tfor _, p := range s.Properties {\n\t\t\tnameType(p.Type, []string{s.Name, p.Name})\n\t\t}\n\t}\n\tfor _, t := range model.Enumerations {\n\t\tnameType(t.Type, []string{t.Name})\n\t}\n\tfor _, t := range model.TypeAliases {\n\t\tnameType(t.Type, []string{t.Name})\n\t}\n\tfor _, r := range model.Requests {\n\t\tnameType(r.Params, []string{\"Param\", r.Method})\n\t\tnameType(r.Result, []string{\"Result\", r.Method})\n\t\tnameType(r.RegistrationOptions, []string{\"RegOpt\", r.Method})\n\t}\n\tfor _, n := range model.Notifications {\n\t\tnameType(n.Params, []string{\"Param\", n.Method})\n\t\tnameType(n.RegistrationOptions, []string{\"RegOpt\", n.Method})\n\t}\n}\n\n// nameType populates typeNames[t] with the computed name of the type.\n// path is the list of enclosing constructs in the JSON model.\nfunc nameType(t *Type, path []string) string {\n\tif t == nil || typeNames[t] != \"\" {\n\t\treturn \"\"\n\t}\n\tswitch t.Kind {\n\tcase \"base\":\n\t\ttypeNames[t] = t.Name\n\t\treturn t.Name\n\tcase \"reference\":\n\t\ttypeNames[t] = t.Name\n\t\treturn t.Name\n\tcase \"array\":\n\t\tnm := \"[]\" + nameType(t.Element, append(path, \"Elem\"))\n\t\ttypeNames[t] = nm\n\t\treturn nm\n\tcase \"map\":\n\t\tkey := nameType(t.Key, nil) // never a generated type\n\t\tvalue := nameType(t.Value.(*Type), append(path, \"Value\"))\n\t\tnm := \"map[\" + key + \"]\" + value\n\t\ttypeNames[t] = nm\n\t\treturn nm\n\t// generated types\n\tcase \"and\":\n\t\tnm := nameFromPath(\"And\", path)\n\t\ttypeNames[t] = nm\n\t\tfor _, it := range t.Items {\n\t\t\tnameType(it, append(path, \"Item\"))\n\t\t}\n\t\tgenTypes = append(genTypes, &newType{\n\t\t\tname:  nm,\n\t\t\ttyp:   t,\n\t\t\tkind:  \"and\",\n\t\t\titems: t.Items,\n\t\t\tline:  t.Line,\n\t\t})\n\t\treturn nm\n\tcase \"literal\":\n\t\tnm := nameFromPath(\"Lit\", path)\n\t\ttypeNames[t] = nm\n\t\tfor _, p := range t.Value.(ParseLiteral).Properties {\n\t\t\tnameType(p.Type, append(path, p.Name))\n\t\t}\n\t\tgenTypes = append(genTypes, &newType{\n\t\t\tname:       nm,\n\t\t\ttyp:        t,\n\t\t\tkind:       \"literal\",\n\t\t\tproperties: t.Value.(ParseLiteral).Properties,\n\t\t\tline:       t.Line,\n\t\t})\n\t\treturn nm\n\tcase \"tuple\":\n\t\tnm := nameFromPath(\"Tuple\", path)\n\t\ttypeNames[t] = nm\n\t\tfor _, it := range t.Items {\n\t\t\tnameType(it, append(path, \"Item\"))\n\t\t}\n\t\tgenTypes = append(genTypes, &newType{\n\t\t\tname:  nm,\n\t\t\ttyp:   t,\n\t\t\tkind:  \"tuple\",\n\t\t\titems: t.Items,\n\t\t\tline:  t.Line,\n\t\t})\n\t\treturn nm\n\tcase \"or\":\n\t\tnm := nameFromPath(\"Or\", path)\n\t\ttypeNames[t] = nm\n\t\tfor i, it := range t.Items {\n\t\t\t// these names depend on the ordering within the \"or\" type\n\t\t\tnameType(it, append(path, fmt.Sprintf(\"Item%d\", i)))\n\t\t}\n\t\t// this code handles an \"or\" of stringLiterals (_InitializeParams.trace)\n\t\tnames := make(map[string]int)\n\t\tvar msg strings.Builder\n\t\tfor _, it := range t.Items {\n\t\t\tif line, ok := names[typeNames[it]]; ok {\n\t\t\t\t// duplicate component names are bad\n\t\t\t\tfmt.Fprintf(&msg, \"lines %d %d dup, %s for %s\\n\", line, it.Line, typeNames[it], nm)\n\t\t\t}\n\t\t\tnames[typeNames[it]] = t.Line\n\t\t}\n\t\t// this code handles an \"or\" of stringLiterals (_InitializeParams.trace)\n\t\tif len(names) == 1 {\n\t\t\tvar solekey string\n\t\t\tfor k := range names {\n\t\t\t\tsolekey = k // the sole name\n\t\t\t}\n\t\t\tif solekey == \"string\" { // _InitializeParams.trace\n\t\t\t\ttypeNames[t] = \"string\"\n\t\t\t\treturn \"string\"\n\t\t\t}\n\t\t\t// otherwise unexpected\n\t\t\tlog.Printf(\"unexpected: single-case 'or' type has non-string key %s: %s\", nm, solekey)\n\t\t\tlog.Fatal(msg.String())\n\t\t} else if len(names) == 2 {\n\t\t\t// if one of the names is null, just use the other, rather than generating an \"or\".\n\t\t\t// This removes about 40 types from the generated code. An entry in goplsStar\n\t\t\t// could be added to handle the null case, if necessary.\n\t\t\tnewNm := \"\"\n\t\t\tsawNull := false\n\t\t\tfor k := range names {\n\t\t\t\tif k == \"null\" {\n\t\t\t\t\tsawNull = true\n\t\t\t\t} else {\n\t\t\t\t\tnewNm = k\n\t\t\t\t}\n\t\t\t}\n\t\t\tif sawNull {\n\t\t\t\ttypeNames[t] = newNm\n\t\t\t\treturn newNm\n\t\t\t}\n\t\t}\n\t\tgenTypes = append(genTypes, &newType{\n\t\t\tname:  nm,\n\t\t\ttyp:   t,\n\t\t\tkind:  \"or\",\n\t\t\titems: t.Items,\n\t\t\tline:  t.Line,\n\t\t})\n\t\treturn nm\n\tcase \"stringLiteral\": // a single type, like 'kind' or 'rename'\n\t\ttypeNames[t] = \"string\"\n\t\treturn \"string\"\n\tdefault:\n\t\tlog.Fatalf(\"nameType: %T unexpected, line:%d path:%v\", t, t.Line, path)\n\t\tpanic(\"unreachable in nameType\")\n\t}\n}\n\nfunc nameFromPath(prefix string, path []string) string {\n\tnm := prefix + \"_\" + strings.Join(path, \"_\")\n\t// methods have slashes\n\tnm = strings.ReplaceAll(nm, \"/\", \"_\")\n\treturn nm\n}\n"
  },
  {
    "path": "gopls/internal/protocol/generate/types.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\n// Model contains the parsed version of the spec\ntype Model struct {\n\tVersion       Metadata        `json:\"metaData\"`\n\tRequests      []*Request      `json:\"requests\"`\n\tNotifications []*Notification `json:\"notifications\"`\n\tStructures    []*Structure    `json:\"structures\"`\n\tEnumerations  []*Enumeration  `json:\"enumerations\"`\n\tTypeAliases   []*TypeAlias    `json:\"typeAliases\"`\n\tLine          int             `json:\"line\"`\n}\n\n// Metadata is information about the version of the spec\ntype Metadata struct {\n\tVersion string `json:\"version\"`\n\tLine    int    `json:\"line\"`\n}\n\n// A Request is the parsed version of an LSP request\ntype Request struct {\n\tDocumentation       string `json:\"documentation\"`\n\tErrorData           *Type  `json:\"errorData\"`\n\tDirection           string `json:\"messageDirection\"`\n\tMethod              string `json:\"method\"`\n\tParams              *Type  `json:\"params\"`\n\tPartialResult       *Type  `json:\"partialResult\"`\n\tProposed            bool   `json:\"proposed\"`\n\tRegistrationMethod  string `json:\"registrationMethod\"`\n\tRegistrationOptions *Type  `json:\"registrationOptions\"`\n\tResult              *Type  `json:\"result\"`\n\tSince               string `json:\"since\"`\n\tLine                int    `json:\"line\"`\n}\n\n// A Notification is the parsed version of an LSP notification\ntype Notification struct {\n\tDocumentation       string `json:\"documentation\"`\n\tDirection           string `json:\"messageDirection\"`\n\tMethod              string `json:\"method\"`\n\tParams              *Type  `json:\"params\"`\n\tProposed            bool   `json:\"proposed\"`\n\tRegistrationMethod  string `json:\"registrationMethod\"`\n\tRegistrationOptions *Type  `json:\"registrationOptions\"`\n\tSince               string `json:\"since\"`\n\tLine                int    `json:\"line\"`\n}\n\n// A Structure is the parsed version of an LSP structure from the spec\ntype Structure struct {\n\tDocumentation string     `json:\"documentation\"`\n\tExtends       []*Type    `json:\"extends\"`\n\tMixins        []*Type    `json:\"mixins\"`\n\tName          string     `json:\"name\"`\n\tProperties    []NameType `json:\"properties\"`\n\tProposed      bool       `json:\"proposed\"`\n\tSince         string     `json:\"since\"`\n\tLine          int        `json:\"line\"`\n}\n\n// An enumeration is the parsed version of an LSP enumeration from the spec\ntype Enumeration struct {\n\tDocumentation        string      `json:\"documentation\"`\n\tName                 string      `json:\"name\"`\n\tProposed             bool        `json:\"proposed\"`\n\tSince                string      `json:\"since\"`\n\tSupportsCustomValues bool        `json:\"supportsCustomValues\"`\n\tType                 *Type       `json:\"type\"`\n\tValues               []NameValue `json:\"values\"`\n\tLine                 int         `json:\"line\"`\n}\n\n// A TypeAlias is the parsed version of an LSP type alias from the spec\ntype TypeAlias struct {\n\tDocumentation string `json:\"documentation\"`\n\tDeprecated    string `json:\"deprecated\"`\n\tName          string `json:\"name\"`\n\tProposed      bool   `json:\"proposed\"`\n\tSince         string `json:\"since\"`\n\tType          *Type  `json:\"type\"`\n\tLine          int    `json:\"line\"`\n}\n\n// A NameValue describes an enumeration constant\ntype NameValue struct {\n\tDocumentation string `json:\"documentation\"`\n\tName          string `json:\"name\"`\n\tProposed      bool   `json:\"proposed\"`\n\tSince         string `json:\"since\"`\n\tValue         any    `json:\"value\"` // number or string\n\tLine          int    `json:\"line\"`\n}\n\n// A Type is the parsed version of an LSP type from the spec,\n// or a Type the code constructs\ntype Type struct {\n\tKind    string  `json:\"kind\"`    // -- which kind goes with which field --\n\tItems   []*Type `json:\"items\"`   // \"and\", \"or\", \"tuple\"\n\tElement *Type   `json:\"element\"` // \"array\"\n\tName    string  `json:\"name\"`    // \"base\", \"reference\"\n\tKey     *Type   `json:\"key\"`     // \"map\"\n\tValue   any     `json:\"value\"`   // \"map\", \"stringLiteral\", \"literal\"\n\tLine    int     `json:\"line\"`    // JSON source line\n}\n\n// ParseLiteral is Type.Value when Type.Kind is \"literal\"\ntype ParseLiteral struct {\n\tProperties `json:\"properties\"`\n}\n\n// A NameType represents the name and type of a structure element\ntype NameType struct {\n\tName          string `json:\"name\"`\n\tType          *Type  `json:\"type\"`\n\tOptional      bool   `json:\"optional\"`\n\tDocumentation string `json:\"documentation\"`\n\tDeprecated    string `json:\"deprecated\"`\n\tSince         string `json:\"since\"`\n\tProposed      bool   `json:\"proposed\"`\n\tLine          int    `json:\"line\"`\n}\n\n// Properties are the collection of structure fields\ntype Properties []NameType\n\n// addLineNumbers adds a \"line\" field to each object in the JSON.\nfunc addLineNumbers(buf []byte) []byte {\n\tvar ans []byte\n\t// In the specification .json file, the delimiter '{' is\n\t// always followed by a newline. There are other {s embedded in strings.\n\t// json.Token does not return \\n, or :, or , so using it would\n\t// require parsing the json to reconstruct the missing information.\n\tfor linecnt, i := 1, 0; i < len(buf); i++ {\n\t\tans = append(ans, buf[i])\n\t\tswitch buf[i] {\n\t\tcase '{':\n\t\t\tif buf[i+1] == '\\n' {\n\t\t\t\tans = append(ans, fmt.Sprintf(`\"line\": %d, `, linecnt)...)\n\t\t\t\t// warning: this would fail if the spec file had\n\t\t\t\t// `\"value\": {\\n}`, but it does not, as comma is a separator.\n\t\t\t}\n\t\tcase '\\n':\n\t\t\tlinecnt++\n\t\t}\n\t}\n\treturn ans\n}\n\ntype sortedMap[T any] map[string]T\n\nfunc (s sortedMap[T]) keys() []string {\n\tvar keys []string\n\tfor k := range s {\n\t\tkeys = append(keys, k)\n\t}\n\tsort.Strings(keys)\n\treturn keys\n}\n"
  },
  {
    "path": "gopls/internal/protocol/json_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol_test\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// verify that type errors in Initialize lsp messages don't cause\n// any other unmarshalling errors. The code looks at single values and the\n// first component of array values. Each occurrence is replaced by something\n// of a different type,  the resulting string unmarshalled, and compared to\n// the unmarshalling of the unchanged strings. The test passes if there is no\n// more than a single difference reported. That is, if changing a single value\n// in the message changes no more than a single value in the unmarshalled struct,\n// it is safe to ignore *json.UnmarshalTypeError.\n\n// strings are changed to numbers or bools (true)\n// bools are changed to numbers or strings\n// numbers are changed to strings or bools\n\n// a recent Initialize message taken from a log (at some point\n// some field incompatibly changed from bool to int32)\nconst input = `{\"processId\":46408,\"clientInfo\":{\"name\":\"Visual Studio Code - Insiders\",\"version\":\"1.76.0-insider\"},\"locale\":\"en-us\",\"rootPath\":\"/Users/pjw/hakim\",\"rootUri\":\"file:///Users/pjw/hakim\",\"capabilities\":{\"workspace\":{\"applyEdit\":true,\"workspaceEdit\":{\"documentChanges\":true,\"resourceOperations\":[\"create\",\"rename\",\"delete\"],\"failureHandling\":\"textOnlyTransactional\",\"normalizesLineEndings\":true,\"changeAnnotationSupport\":{\"groupsOnLabel\":true}},\"configuration\":true,\"didChangeWatchedFiles\":{\"dynamicRegistration\":true,\"relativePatternSupport\":true},\"symbol\":{\"dynamicRegistration\":true,\"symbolKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},\"tagSupport\":{\"valueSet\":[1]},\"resolveSupport\":{\"properties\":[\"location.range\"]}},\"codeLens\":{\"refreshSupport\":true},\"executeCommand\":{\"dynamicRegistration\":true},\"didChangeConfiguration\":{\"dynamicRegistration\":true},\"workspaceFolders\":true,\"semanticTokens\":{\"refreshSupport\":true},\"fileOperations\":{\"dynamicRegistration\":true,\"didCreate\":true,\"didRename\":true,\"didDelete\":true,\"willCreate\":true,\"willRename\":true,\"willDelete\":true},\"inlineValue\":{\"refreshSupport\":true},\"inlayHint\":{\"refreshSupport\":true},\"diagnostics\":{\"refreshSupport\":true}},\"textDocument\":{\"publishDiagnostics\":{\"relatedInformation\":true,\"versionSupport\":false,\"tagSupport\":{\"valueSet\":[1,2]},\"codeDescriptionSupport\":true,\"dataSupport\":true},\"synchronization\":{\"dynamicRegistration\":true,\"willSave\":true,\"willSaveWaitUntil\":true,\"didSave\":true},\"completion\":{\"dynamicRegistration\":true,\"contextSupport\":true,\"completionItem\":{\"snippetSupport\":true,\"commitCharactersSupport\":true,\"documentationFormat\":[\"markdown\",\"plaintext\"],\"deprecatedSupport\":true,\"preselectSupport\":true,\"tagSupport\":{\"valueSet\":[1]},\"insertReplaceSupport\":true,\"resolveSupport\":{\"properties\":[\"documentation\",\"detail\",\"additionalTextEdits\"]},\"insertTextModeSupport\":{\"valueSet\":[1,2]},\"labelDetailsSupport\":true},\"insertTextMode\":2,\"completionItemKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},\"completionList\":{\"itemDefaults\":[\"commitCharacters\",\"editRange\",\"insertTextFormat\",\"insertTextMode\"]}},\"hover\":{\"dynamicRegistration\":true,\"contentFormat\":[\"markdown\",\"plaintext\"]},\"signatureHelp\":{\"dynamicRegistration\":true,\"signatureInformation\":{\"documentationFormat\":[\"markdown\",\"plaintext\"],\"parameterInformation\":{\"labelOffsetSupport\":true},\"activeParameterSupport\":true},\"contextSupport\":true},\"definition\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"references\":{\"dynamicRegistration\":true},\"documentHighlight\":{\"dynamicRegistration\":true},\"documentSymbol\":{\"dynamicRegistration\":true,\"symbolKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},\"hierarchicalDocumentSymbolSupport\":true,\"tagSupport\":{\"valueSet\":[1]},\"labelSupport\":true},\"codeAction\":{\"dynamicRegistration\":true,\"isPreferredSupport\":true,\"disabledSupport\":true,\"dataSupport\":true,\"resolveSupport\":{\"properties\":[\"edit\"]},\"codeActionLiteralSupport\":{\"codeActionKind\":{\"valueSet\":[\"\",\"quickfix\",\"refactor\",\"refactor.extract\",\"refactor.inline\",\"refactor.rewrite\",\"source\",\"source.organizeImports\"]}},\"honorsChangeAnnotations\":false},\"codeLens\":{\"dynamicRegistration\":true},\"formatting\":{\"dynamicRegistration\":true},\"rangeFormatting\":{\"dynamicRegistration\":true},\"onTypeFormatting\":{\"dynamicRegistration\":true},\"rename\":{\"dynamicRegistration\":true,\"prepareSupport\":true,\"prepareSupportDefaultBehavior\":1,\"honorsChangeAnnotations\":true},\"documentLink\":{\"dynamicRegistration\":true,\"tooltipSupport\":true},\"typeDefinition\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"implementation\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"colorProvider\":{\"dynamicRegistration\":true},\"foldingRange\":{\"dynamicRegistration\":true,\"rangeLimit\":5000,\"lineFoldingOnly\":true,\"foldingRangeKind\":{\"valueSet\":[\"comment\",\"imports\",\"region\"]},\"foldingRange\":{\"collapsedText\":false}},\"declaration\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"selectionRange\":{\"dynamicRegistration\":true},\"callHierarchy\":{\"dynamicRegistration\":true},\"semanticTokens\":{\"dynamicRegistration\":true,\"tokenTypes\":[\"namespace\",\"type\",\"class\",\"enum\",\"interface\",\"struct\",\"typeParameter\",\"parameter\",\"variable\",\"property\",\"enumMember\",\"event\",\"function\",\"method\",\"macro\",\"keyword\",\"modifier\",\"comment\",\"string\",\"number\",\"regexp\",\"operator\",\"decorator\"],\"tokenModifiers\":[\"declaration\",\"definition\",\"readonly\",\"static\",\"deprecated\",\"abstract\",\"async\",\"modification\",\"documentation\",\"defaultLibrary\"],\"formats\":[\"relative\"],\"requests\":{\"range\":true,\"full\":{\"delta\":true}},\"multilineTokenSupport\":false,\"overlappingTokenSupport\":false,\"serverCancelSupport\":true,\"augmentsSyntaxTokens\":true},\"linkedEditingRange\":{\"dynamicRegistration\":true},\"typeHierarchy\":{\"dynamicRegistration\":true},\"inlineValue\":{\"dynamicRegistration\":true},\"inlayHint\":{\"dynamicRegistration\":true,\"resolveSupport\":{\"properties\":[\"tooltip\",\"textEdits\",\"label.tooltip\",\"label.location\",\"label.command\"]}},\"diagnostic\":{\"dynamicRegistration\":true,\"relatedDocumentSupport\":false}},\"window\":{\"showMessage\":{\"messageActionItem\":{\"additionalPropertiesSupport\":true}},\"showDocument\":{\"support\":true},\"workDoneProgress\":true},\"general\":{\"staleRequestSupport\":{\"cancel\":true,\"retryOnContentModified\":[\"textDocument/semanticTokens/full\",\"textDocument/semanticTokens/range\",\"textDocument/semanticTokens/full/delta\"]},\"regularExpressions\":{\"engine\":\"ECMAScript\",\"version\":\"ES2020\"},\"markdown\":{\"parser\":\"marked\",\"version\":\"1.1.0\"},\"positionEncodings\":[\"utf-16\"]},\"notebookDocument\":{\"synchronization\":{\"dynamicRegistration\":true,\"executionSummarySupport\":true}}},\"initializationOptions\":{\"usePlaceholders\":true,\"completionDocumentation\":true,\"verboseOutput\":false,\"build.directoryFilters\":[\"-foof\",\"-internal/protocol/typescript\"],\"codelenses\":{\"reference\":true,\"gc_details\":true},\"analyses\":{\"fillstruct\":true,\"staticcheck\":true,\"unusedparams\":false,\"composites\":false},\"semanticTokens\":true,\"noSemanticString\":true,\"noSemanticNumber\":true,\"templateExtensions\":[\"tmpl\",\"gotmpl\"],\"ui.completion.matcher\":\"Fuzzy\",\"ui.inlayhint.hints\":{\"assignVariableTypes\":false,\"compositeLiteralFields\":false,\"compositeLiteralTypes\":false,\"constantValues\":false,\"functionTypeParameters\":false,\"parameterNames\":false,\"rangeVariableTypes\":false},\"ui.vulncheck\":\"Off\",\"allExperiments\":true},\"trace\":\"off\",\"workspaceFolders\":[{\"uri\":\"file:///Users/pjw/hakim\",\"name\":\"hakim\"}]}`\n\ntype DiffReporter struct {\n\tpath  cmp.Path\n\tdiffs []string\n}\n\nfunc (r *DiffReporter) PushStep(ps cmp.PathStep) {\n\tr.path = append(r.path, ps)\n}\n\nfunc (r *DiffReporter) Report(rs cmp.Result) {\n\tif !rs.Equal() {\n\t\tvx, vy := r.path.Last().Values()\n\t\tr.diffs = append(r.diffs, fmt.Sprintf(\"%#v:\\n\\t-: %+v\\n\\t+: %+v\\n\", r.path, vx, vy))\n\t}\n}\n\nfunc (r *DiffReporter) PopStep() {\n\tr.path = r.path[:len(r.path)-1]\n}\n\nfunc (r *DiffReporter) String() string {\n\treturn strings.Join(r.diffs, \"\\n\")\n}\n\nfunc TestStringChanges(t *testing.T) {\n\t// string as value\n\tstringLeaf := regexp.MustCompile(`:(\"[^\"]*\")`)\n\tleafs := stringLeaf.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, leafs, \"23\", \"true\")\n\t// string as first element of array\n\tstringArray := regexp.MustCompile(`[[](\"[^\"]*\")`)\n\tarrays := stringArray.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, arrays, \"23\", \"true\")\n}\n\nfunc TestBoolChanges(t *testing.T) {\n\tboolLeaf := regexp.MustCompile(`:(true|false)(,|})`)\n\tleafs := boolLeaf.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, leafs, \"23\", `\"xx\"`)\n\tboolArray := regexp.MustCompile(`:[[](true|false)(,|])`)\n\tarrays := boolArray.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, arrays, \"23\", `\"xx\"`)\n}\n\nfunc TestNumberChanges(t *testing.T) {\n\tnumLeaf := regexp.MustCompile(`:(\\d+)(,|})`)\n\tleafs := numLeaf.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, leafs, \"true\", `\"xx\"`)\n\tnumArray := regexp.MustCompile(`:[[](\\d+)(,|])`)\n\tarrays := numArray.FindAllStringSubmatchIndex(input, -1)\n\tallDeltas(t, arrays, \"true\", `\"xx\"`)\n}\n\n// v is a set of matches. check that substituting any repl never\n// creates more than 1 unmarshaling error\nfunc allDeltas(t *testing.T, v [][]int, repls ...string) {\n\tt.Helper()\n\tfor _, repl := range repls {\n\t\tfor i, x := range v {\n\t\t\terr := tryChange(x[2], x[3], repl)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"%d:%q %v\", i, input[x[2]:x[3]], err)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc tryChange(start, end int, repl string) error {\n\tvar p, q protocol.ParamInitialize\n\tmod := input[:start] + repl + input[end:]\n\texcerpt := func() (string, string) {\n\t\ta := max(start-5, 0)\n\t\t// trusting repl to be no longer than what it replaces\n\t\tb := min(end+5, len(input))\n\t\tma := input[a:b]\n\t\tmb := mod[a:b]\n\t\treturn ma, mb\n\t}\n\n\tif err := json.Unmarshal([]byte(input), &p); err != nil {\n\t\treturn fmt.Errorf(\"%s %v\", repl, err)\n\t}\n\tswitch err := json.Unmarshal([]byte(mod), &q).(type) {\n\tcase nil: //ok\n\tcase *json.UnmarshalTypeError:\n\t\tbreak\n\tcase *protocol.UnmarshalError:\n\t\treturn nil // cmp.Diff produces several diffs for custom unmrshalers\n\tdefault:\n\t\treturn fmt.Errorf(\"%T unexpected unmarshal error\", err)\n\t}\n\n\tvar r DiffReporter\n\tcmp.Diff(p, q, cmp.Reporter(&r))\n\tif len(r.diffs) > 1 { // 0 is possible, e.g., for interface{}\n\t\tma, mb := excerpt()\n\t\treturn fmt.Errorf(\"got %d diffs for %q\\n%s\\n%s\", len(r.diffs), repl, ma, mb)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/log.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\ntype loggingStream struct {\n\tstream jsonrpc2.Stream\n\tlogMu  sync.Mutex\n\tlog    io.Writer\n}\n\n// LoggingStream returns a stream that does LSP protocol logging too\nfunc LoggingStream(str jsonrpc2.Stream, w io.Writer) jsonrpc2.Stream {\n\treturn &loggingStream{stream: str, log: w}\n}\n\nfunc (s *loggingStream) Read(ctx context.Context) (jsonrpc2.Message, int64, error) {\n\tmsg, count, err := s.stream.Read(ctx)\n\tif err == nil {\n\t\ts.logCommon(msg, true)\n\t}\n\treturn msg, count, err\n}\n\nfunc (s *loggingStream) Write(ctx context.Context, msg jsonrpc2.Message) (int64, error) {\n\ts.logCommon(msg, false)\n\tcount, err := s.stream.Write(ctx, msg)\n\treturn count, err\n}\n\nfunc (s *loggingStream) Close() error {\n\treturn s.stream.Close()\n}\n\ntype req struct {\n\tmethod string\n\tstart  time.Time\n}\n\ntype mapped struct {\n\tmu          sync.Mutex\n\tclientCalls map[string]req\n\tserverCalls map[string]req\n}\n\nvar maps = &mapped{\n\tsync.Mutex{},\n\tmake(map[string]req),\n\tmake(map[string]req),\n}\n\n// these 4 methods are each used exactly once, but it seemed\n// better to have the encapsulation rather than ad hoc mutex\n// code in 4 places\nfunc (m *mapped) client(id string) req {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\tv := m.clientCalls[id]\n\tdelete(m.clientCalls, id)\n\treturn v\n}\n\nfunc (m *mapped) server(id string) req {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\tv := m.serverCalls[id]\n\tdelete(m.serverCalls, id)\n\treturn v\n}\n\nfunc (m *mapped) setClient(id string, r req) {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\tm.clientCalls[id] = r\n}\n\nfunc (m *mapped) setServer(id string, r req) {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\tm.serverCalls[id] = r\n}\n\nconst eor = \"\\r\\n\\r\\n\\r\\n\"\n\nfunc (s *loggingStream) logCommon(msg jsonrpc2.Message, isRead bool) {\n\ts.logMu.Lock()\n\tdefer s.logMu.Unlock()\n\tdirection, pastTense := \"Received\", \"Received\"\n\tget, set := maps.client, maps.setServer\n\tif isRead {\n\t\tdirection, pastTense = \"Sending\", \"Sent\"\n\t\tget, set = maps.server, maps.setClient\n\t}\n\tif msg == nil || s.log == nil {\n\t\treturn\n\t}\n\ttm := time.Now()\n\ttmfmt := tm.Format(\"15:04:05.000 PM\")\n\n\tbuf := strings.Builder{}\n\tfmt.Fprintf(&buf, \"[Trace - %s] \", tmfmt) // common beginning\n\tswitch msg := msg.(type) {\n\tcase *jsonrpc2.Call:\n\t\tid := fmt.Sprint(msg.ID())\n\t\tfmt.Fprintf(&buf, \"%s request '%s - (%s)'.\\n\", direction, msg.Method(), id)\n\t\tfmt.Fprintf(&buf, \"Params: %s%s\", msg.Params(), eor)\n\t\tset(id, req{method: msg.Method(), start: tm})\n\tcase *jsonrpc2.Notification:\n\t\tfmt.Fprintf(&buf, \"%s notification '%s'.\\n\", direction, msg.Method())\n\t\tfmt.Fprintf(&buf, \"Params: %s%s\", msg.Params(), eor)\n\tcase *jsonrpc2.Response:\n\t\tid := fmt.Sprint(msg.ID())\n\t\tif err := msg.Err(); err != nil {\n\t\t\tfmt.Fprintf(s.log, \"[Error - %s] %s #%s %s%s\", pastTense, tmfmt, id, err, eor)\n\t\t\treturn\n\t\t}\n\t\tcc := get(id)\n\t\telapsed := tm.Sub(cc.start)\n\t\tfmt.Fprintf(&buf, \"%s response '%s - (%s)' in %dms.\\n\",\n\t\t\tdirection, cc.method, id, elapsed/time.Millisecond)\n\t\tfmt.Fprintf(&buf, \"Result: %s%s\", msg.Result(), eor)\n\t}\n\ts.log.Write([]byte(buf.String()))\n}\n"
  },
  {
    "path": "gopls/internal/protocol/mapper.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\n// This file defines Mapper, which wraps a file content buffer\n// ([]byte) and provides efficient conversion between every kind of\n// position representation.\n//\n// gopls uses four main representations of position:\n//\n// 1. byte offsets, e.g. (start, end int), starting from zero.\n//\n// 2. go/token notation. Use these types when interacting directly\n//    with the go/* syntax packages:\n//\n// \ttoken.Pos\n// \ttoken.FileSet\n// \ttoken.File\n//\n//    Because File.Offset and File.Pos panic on invalid inputs,\n//    we do not call them directly and instead use the safetoken package\n//    for these conversions. This is enforced by a static check.\n//\n//    Beware also that the methods of token.File have two bugs for which\n//    safetoken contains workarounds:\n//    - #57490, whereby the parser may create ast.Nodes during error\n//      recovery whose computed positions are out of bounds (EOF+1).\n//    - #41029, whereby the wrong line number is returned for the EOF position.\n//\n// 3. the cmd package.\n//\n//    cmd.point = (line, col8, offset).\n//    cmd.Span = (uri URI, start, end cmd.point)\n//\n//          Line and column are 1-based.\n//          Columns are measured in bytes (UTF-8 codes).\n//          All fields are optional.\n//\n//    These types are useful as intermediate conversions of validated\n//    ranges. Since their fields are optional they are also useful for\n//    parsing user-provided positions (e.g. in the CLI) before we have\n//    access to file contents.\n//\n// 4. protocol, the LSP RPC message format.\n//\n//    protocol.Position = (Line, Character uint32)\n//    protocol.Range = (start, end Position)\n//    protocol.Location = (URI, protocol.Range)\n//\n//          Line and Character are 0-based.\n//          Characters (columns) are measured in UTF-16 codes.\n//\n//    protocol.Mapper holds the (URI, Content) of a file, enabling\n//    efficient mapping between byte offsets, cmd ranges, and\n//    protocol ranges.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"sort\"\n\t\"sync\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n)\n\n// A Mapper wraps the content of a file and provides mapping\n// between byte offsets and notations of position such as:\n//\n//   - (line, col8) pairs, where col8 is a 1-based UTF-8 column number\n//     (bytes), as used by the go/token and cmd packages.\n//\n//   - (line, col16) pairs, where col16 is a 1-based UTF-16 column\n//     number, as used by the LSP protocol.\n//\n// All conversion methods are named \"FromTo\", where From and To are the two types.\n// For example, the PointPosition method converts from a Point to a Position.\n//\n// Mapper does not intrinsically depend on go/token-based\n// representations.  Use safetoken to map between token.Pos <=> byte\n// offsets, or the convenience methods such as PosPosition,\n// NodePosition, or NodeRange.\n//\n// See overview comments at top of this file.\ntype Mapper struct {\n\tURI     DocumentURI\n\tContent []byte\n\n\t// Line-number information is requested only for a tiny\n\t// fraction of Mappers, so we compute it lazily.\n\t// Call initLines() before accessing fields below.\n\tlinesOnce sync.Once\n\tlineStart []int // byte offset of start of ith line (0-based); last=EOF iff \\n-terminated\n\tnonASCII  bool\n\n\t// TODO(adonovan): adding an extra lineStart entry for EOF\n\t// might simplify every method that accesses it. Try it out.\n}\n\n// NewMapper creates a new mapper for the given URI and content.\nfunc NewMapper(uri DocumentURI, content []byte) *Mapper {\n\treturn &Mapper{URI: uri, Content: content}\n}\n\n// initLines populates the lineStart table.\nfunc (m *Mapper) initLines() {\n\tm.linesOnce.Do(func() {\n\t\tnlines := bytes.Count(m.Content, []byte(\"\\n\"))\n\t\tm.lineStart = make([]int, 1, nlines+1) // initially []int{0}\n\t\tfor offset, b := range m.Content {\n\t\t\tif b == '\\n' {\n\t\t\t\tm.lineStart = append(m.lineStart, offset+1)\n\t\t\t}\n\t\t\tif b >= utf8.RuneSelf {\n\t\t\t\tm.nonASCII = true\n\t\t\t}\n\t\t}\n\t})\n}\n\n// LineCol8Position converts a valid line and UTF-8 column number,\n// both 1-based, to a protocol (UTF-16) position.\nfunc (m *Mapper) LineCol8Position(line, col8 int) (Position, error) {\n\t// Report a bug for inputs that are invalid for any file content.\n\tif line < 1 {\n\t\treturn Position{}, bug.Errorf(\"invalid 1-based line number: %d\", line)\n\t}\n\tif col8 < 1 {\n\t\treturn Position{}, bug.Errorf(\"invalid 1-based column number: %d\", col8)\n\t}\n\n\tm.initLines()\n\tline0 := line - 1 // 0-based\n\tif !(0 <= line0 && line0 < len(m.lineStart)) {\n\t\treturn Position{}, fmt.Errorf(\"line number %d out of range (max %d)\", line, len(m.lineStart))\n\t}\n\n\t// content[start:end] is the preceding partial line.\n\tstart := m.lineStart[line0]\n\tend := start + col8 - 1\n\n\t// Validate column.\n\tif end > len(m.Content) {\n\t\treturn Position{}, fmt.Errorf(\"column is beyond end of file\")\n\t} else if line0+1 < len(m.lineStart) && end >= m.lineStart[line0+1] {\n\t\treturn Position{}, fmt.Errorf(\"column is beyond end of line\")\n\t}\n\n\tchar := UTF16Len(m.Content[start:end])\n\treturn Position{Line: uint32(line0), Character: uint32(char)}, nil\n}\n\n// -- conversions from byte offsets --\n\n// OffsetLocation converts a byte-offset interval to a protocol (UTF-16) location.\nfunc (m *Mapper) OffsetLocation(start, end int) (Location, error) {\n\trng, err := m.OffsetRange(start, end)\n\tif err != nil {\n\t\treturn Location{}, err\n\t}\n\treturn m.URI.Location(rng), nil\n}\n\n// OffsetRange converts a byte-offset interval to a protocol (UTF-16) range.\nfunc (m *Mapper) OffsetRange(start, end int) (Range, error) {\n\tif start > end {\n\t\treturn Range{}, fmt.Errorf(\"start offset (%d) > end (%d)\", start, end)\n\t}\n\tstartPosition, err := m.OffsetPosition(start)\n\tif err != nil {\n\t\treturn Range{}, fmt.Errorf(\"start: %v\", err)\n\t}\n\tendPosition, err := m.OffsetPosition(end)\n\tif err != nil {\n\t\treturn Range{}, fmt.Errorf(\"end: %v\", err)\n\t}\n\treturn Range{Start: startPosition, End: endPosition}, nil\n}\n\n// OffsetPosition converts a byte offset to a protocol (UTF-16) position.\nfunc (m *Mapper) OffsetPosition(offset int) (Position, error) {\n\tif !(0 <= offset && offset <= len(m.Content)) {\n\t\treturn Position{}, fmt.Errorf(\"invalid offset %d (want 0-%d)\", offset, len(m.Content))\n\t}\n\t// No error may be returned after this point,\n\t// even if the offset does not fall at a rune boundary.\n\n\tline, col16 := m.lineCol16(offset)\n\treturn Position{Line: uint32(line), Character: uint32(col16)}, nil\n}\n\n// lineCol16 converts a valid byte offset to line and UTF-16 column numbers, both 0-based.\nfunc (m *Mapper) lineCol16(offset int) (int, int) {\n\tline, start, cr := m.line(offset)\n\tvar col16 int\n\tif m.nonASCII {\n\t\tcol16 = UTF16Len(m.Content[start:offset])\n\t} else {\n\t\tcol16 = offset - start\n\t}\n\tif cr {\n\t\tcol16-- // retreat from \\r at line end\n\t}\n\treturn line, col16\n}\n\n// OffsetLineCol8 converts a valid byte offset to line and UTF-8 column numbers, both 1-based.\nfunc (m *Mapper) OffsetLineCol8(offset int) (int, int) {\n\tline, start, cr := m.line(offset)\n\tcol8 := offset - start\n\tif cr {\n\t\tcol8-- // retreat from \\r at line end\n\t}\n\treturn line + 1, col8 + 1\n}\n\n// line returns:\n// - the 0-based index of the line that encloses the (valid) byte offset;\n// - the start offset of that line; and\n// - whether the offset denotes a carriage return (\\r) at line end.\nfunc (m *Mapper) line(offset int) (int, int, bool) {\n\tm.initLines()\n\t// In effect, binary search returns a 1-based result.\n\tline := sort.Search(len(m.lineStart), func(i int) bool {\n\t\treturn offset < m.lineStart[i]\n\t})\n\n\t// Adjustment for line-endings: \\r|\\n is the same as |\\r\\n.\n\tvar eol int\n\tif line == len(m.lineStart) {\n\t\teol = len(m.Content) // EOF\n\t} else {\n\t\teol = m.lineStart[line] - 1\n\t}\n\tcr := offset == eol && offset > 0 && m.Content[offset-1] == '\\r'\n\n\tline-- // 0-based\n\n\treturn line, m.lineStart[line], cr\n}\n\n// -- conversions from protocol (UTF-16) domain --\n\n// RangeOffsets converts a protocol (UTF-16) range to start/end byte offsets.\nfunc (m *Mapper) RangeOffsets(r Range) (int, int, error) {\n\tstart, err := m.PositionOffset(r.Start)\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\tend, err := m.PositionOffset(r.End)\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\tif start > end {\n\t\treturn 0, 0, fmt.Errorf(\"start (offset %d) > end (offset %d)\", start, end)\n\t}\n\treturn start, end, nil\n}\n\n// PositionOffset converts a protocol (UTF-16) position to a byte offset.\nfunc (m *Mapper) PositionOffset(p Position) (int, error) {\n\tm.initLines()\n\n\t// Validate line number.\n\tif p.Line > uint32(len(m.lineStart)) {\n\t\treturn 0, fmt.Errorf(\"line number %d out of range 0-%d\", p.Line, len(m.lineStart))\n\t} else if p.Line == uint32(len(m.lineStart)) {\n\t\tif p.Character == 0 {\n\t\t\treturn len(m.Content), nil // EOF\n\t\t}\n\t\treturn 0, fmt.Errorf(\"column is beyond end of file\")\n\t}\n\n\toffset := m.lineStart[p.Line]\n\tcontent := m.Content[offset:] // rest of file from start of enclosing line\n\n\t// Advance bytes up to the required number of UTF-16 codes.\n\tcol8 := 0\n\tfor col16 := 0; col16 < int(p.Character); col16++ {\n\t\tr, sz := utf8.DecodeRune(content)\n\t\tif sz == 0 {\n\t\t\treturn 0, fmt.Errorf(\"column is beyond end of file\")\n\t\t}\n\t\tif r == '\\n' {\n\t\t\treturn 0, fmt.Errorf(\"column is beyond end of line\")\n\t\t}\n\t\tif sz == 1 && r == utf8.RuneError {\n\t\t\treturn 0, fmt.Errorf(\"buffer contains invalid UTF-8 text\")\n\t\t}\n\t\tcontent = content[sz:]\n\n\t\tif r >= 0x10000 {\n\t\t\tcol16++ // rune was encoded by a pair of surrogate UTF-16 codes\n\n\t\t\tif col16 == int(p.Character) {\n\t\t\t\tbreak // requested position is in the middle of a rune\n\t\t\t}\n\t\t}\n\t\tcol8 += sz\n\t}\n\treturn offset + col8, nil\n}\n\n// -- go/token domain convenience methods --\n\n// PosPosition converts a token pos to a protocol (UTF-16) position.\nfunc (m *Mapper) PosPosition(tf *token.File, pos token.Pos) (Position, error) {\n\toffset, err := safetoken.Offset(tf, pos)\n\tif err != nil {\n\t\treturn Position{}, err\n\t}\n\treturn m.OffsetPosition(offset)\n}\n\n// PosLocation converts a token range to a protocol (UTF-16) location.\nfunc (m *Mapper) PosLocation(tf *token.File, start, end token.Pos) (Location, error) {\n\tstartOffset, endOffset, err := safetoken.Offsets(tf, start, end)\n\tif err != nil {\n\t\treturn Location{}, err\n\t}\n\trng, err := m.OffsetRange(startOffset, endOffset)\n\tif err != nil {\n\t\treturn Location{}, err\n\t}\n\treturn m.URI.Location(rng), nil\n}\n\n// PosRange converts a token range to a protocol (UTF-16) range.\nfunc (m *Mapper) PosRange(tf *token.File, start, end token.Pos) (Range, error) {\n\tstartOffset, endOffset, err := safetoken.Offsets(tf, start, end)\n\tif err != nil {\n\t\treturn Range{}, err\n\t}\n\treturn m.OffsetRange(startOffset, endOffset)\n}\n\n// PosText returns the source text for the token range.\nfunc (m *Mapper) PosText(tf *token.File, start, end token.Pos) ([]byte, error) {\n\tstartOffset, endOffset, err := safetoken.Offsets(tf, start, end)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn m.Content[startOffset:endOffset], nil\n}\n\n// NodeRange converts a syntax node range to a protocol (UTF-16) range.\nfunc (m *Mapper) NodeRange(tf *token.File, node ast.Node) (Range, error) {\n\treturn m.PosRange(tf, node.Pos(), node.End())\n}\n\n// NodeText returns the source text for syntax node range.\nfunc (m *Mapper) NodeText(tf *token.File, node ast.Node) ([]byte, error) {\n\treturn m.PosText(tf, node.Pos(), node.End())\n}\n\n// LocationTextDocumentPositionParams converts its argument to its result.\nfunc LocationTextDocumentPositionParams(loc Location) TextDocumentPositionParams {\n\treturn TextDocumentPositionParams{\n\t\tTextDocument: TextDocumentIdentifier{URI: loc.URI},\n\t\tRange:        loc.Range,\n\t\tPosition:     loc.Range.Start, // not used\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/mapper_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol_test\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// This file tests Mapper's logic for converting between offsets,\n// UTF-8 columns, and UTF-16 columns. (The strange form attests to\n// earlier abstractions.)\n\n// 𐐀 is U+10400 = [F0 90 90 80] in UTF-8, [D801 DC00] in UTF-16.\nvar funnyString = []byte(\"𐐀23\\n𐐀45\")\n\nvar toUTF16Tests = []struct {\n\tscenario    string\n\tinput       []byte\n\tline        int    // 1-indexed count\n\tcol         int    // 1-indexed byte position in line\n\toffset      int    // 0-indexed byte offset into input\n\tresUTF16col int    // 1-indexed UTF-16 col number\n\tpre         string // everything before the cursor on the line\n\tpost        string // everything from the cursor onwards\n\terr         string // expected error string in call to ToUTF16Column\n\tissue       *bool\n}{\n\t{\n\t\tscenario: \"cursor missing content\",\n\t\tinput:    nil,\n\t\toffset:   -1,\n\t\terr:      \"point has neither offset nor line/column\",\n\t},\n\t{\n\t\tscenario: \"cursor missing position\",\n\t\tinput:    funnyString,\n\t\tline:     -1,\n\t\tcol:      -1,\n\t\toffset:   -1,\n\t\terr:      \"point has neither offset nor line/column\",\n\t},\n\t{\n\t\tscenario:    \"zero length input; cursor at first col, first line\",\n\t\tinput:       []byte(\"\"),\n\t\tline:        1,\n\t\tcol:         1,\n\t\toffset:      0,\n\t\tresUTF16col: 1,\n\t},\n\t{\n\t\tscenario:    \"cursor before funny character; first line\",\n\t\tinput:       funnyString,\n\t\tline:        1,\n\t\tcol:         1,\n\t\toffset:      0,\n\t\tresUTF16col: 1,\n\t\tpre:         \"\",\n\t\tpost:        \"𐐀23\",\n\t},\n\t{\n\t\tscenario:    \"cursor after funny character; first line\",\n\t\tinput:       funnyString,\n\t\tline:        1,\n\t\tcol:         5, // 4 + 1 (1-indexed)\n\t\toffset:      4, // (unused since we have line+col)\n\t\tresUTF16col: 3, // 2 + 1 (1-indexed)\n\t\tpre:         \"𐐀\",\n\t\tpost:        \"23\",\n\t},\n\t{\n\t\tscenario:    \"cursor after last character on first line\",\n\t\tinput:       funnyString,\n\t\tline:        1,\n\t\tcol:         7, // 4 + 1 + 1 + 1 (1-indexed)\n\t\toffset:      6, // 4 + 1 + 1 (unused since we have line+col)\n\t\tresUTF16col: 5, // 2 + 1 + 1 + 1 (1-indexed)\n\t\tpre:         \"𐐀23\",\n\t\tpost:        \"\",\n\t},\n\t{\n\t\tscenario:    \"cursor before funny character; second line\",\n\t\tinput:       funnyString,\n\t\tline:        2,\n\t\tcol:         1,\n\t\toffset:      7, // length of first line (unused since we have line+col)\n\t\tresUTF16col: 1,\n\t\tpre:         \"\",\n\t\tpost:        \"𐐀45\",\n\t},\n\t{\n\t\tscenario:    \"cursor after funny character; second line\",\n\t\tinput:       funnyString,\n\t\tline:        1,\n\t\tcol:         5,  // 4 + 1 (1-indexed)\n\t\toffset:      11, // 7 (length of first line) + 4 (unused since we have line+col)\n\t\tresUTF16col: 3,  // 2 + 1 (1-indexed)\n\t\tpre:         \"𐐀\",\n\t\tpost:        \"45\",\n\t},\n\t{\n\t\tscenario:    \"cursor after last character on second line\",\n\t\tinput:       funnyString,\n\t\tline:        2,\n\t\tcol:         7,  // 4 + 1 + 1 + 1 (1-indexed)\n\t\toffset:      13, // 7 (length of first line) + 4 + 1 + 1 (unused since we have line+col)\n\t\tresUTF16col: 5,  // 2 + 1 + 1 + 1 (1-indexed)\n\t\tpre:         \"𐐀45\",\n\t\tpost:        \"\",\n\t},\n\t{\n\t\tscenario: \"cursor beyond end of file\",\n\t\tinput:    funnyString,\n\t\tline:     2,\n\t\tcol:      8,  // 4 + 1 + 1 + 1 + 1 (1-indexed)\n\t\toffset:   14, // 4 + 1 + 1 + 1 (unused since we have line+col)\n\t\terr:      \"column is beyond end of file\",\n\t},\n}\n\nvar fromUTF16Tests = []struct {\n\tscenario  string\n\tinput     []byte\n\tline      int    // 1-indexed line number (isn't actually used)\n\tutf16col  int    // 1-indexed UTF-16 col number\n\tresCol    int    // 1-indexed byte position in line\n\tresOffset int    // 0-indexed byte offset into input\n\tpre       string // everything before the cursor on the line\n\tpost      string // everything from the cursor onwards\n\terr       string // expected error string in call to ToUTF16Column\n}{\n\t{\n\t\tscenario:  \"zero length input; cursor at first col, first line\",\n\t\tinput:     []byte(\"\"),\n\t\tline:      1,\n\t\tutf16col:  1,\n\t\tresCol:    1,\n\t\tresOffset: 0,\n\t\tpre:       \"\",\n\t\tpost:      \"\",\n\t},\n\t{\n\t\tscenario:  \"cursor before funny character\",\n\t\tinput:     funnyString,\n\t\tline:      1,\n\t\tutf16col:  1,\n\t\tresCol:    1,\n\t\tresOffset: 0,\n\t\tpre:       \"\",\n\t\tpost:      \"𐐀23\",\n\t},\n\t{\n\t\tscenario:  \"cursor after funny character\",\n\t\tinput:     funnyString,\n\t\tline:      1,\n\t\tutf16col:  3,\n\t\tresCol:    5,\n\t\tresOffset: 4,\n\t\tpre:       \"𐐀\",\n\t\tpost:      \"23\",\n\t},\n\t{\n\t\tscenario:  \"cursor after last character on line\",\n\t\tinput:     funnyString,\n\t\tline:      1,\n\t\tutf16col:  5,\n\t\tresCol:    7,\n\t\tresOffset: 6,\n\t\tpre:       \"𐐀23\",\n\t\tpost:      \"\",\n\t},\n\t{\n\t\tscenario:  \"cursor beyond last character on line\",\n\t\tinput:     funnyString,\n\t\tline:      1,\n\t\tutf16col:  6,\n\t\tresCol:    7,\n\t\tresOffset: 6,\n\t\tpre:       \"𐐀23\",\n\t\tpost:      \"\",\n\t\terr:       \"column is beyond end of line\",\n\t},\n\t{\n\t\tscenario:  \"cursor before funny character; second line\",\n\t\tinput:     funnyString,\n\t\tline:      2,\n\t\tutf16col:  1,\n\t\tresCol:    1,\n\t\tresOffset: 7,\n\t\tpre:       \"\",\n\t\tpost:      \"𐐀45\",\n\t},\n\t{\n\t\tscenario:  \"cursor after funny character; second line\",\n\t\tinput:     funnyString,\n\t\tline:      2,\n\t\tutf16col:  3,  // 2 + 1 (1-indexed)\n\t\tresCol:    5,  // 4 + 1 (1-indexed)\n\t\tresOffset: 11, // 7 (length of first line) + 4\n\t\tpre:       \"𐐀\",\n\t\tpost:      \"45\",\n\t},\n\t{\n\t\tscenario:  \"cursor after last character on second line\",\n\t\tinput:     funnyString,\n\t\tline:      2,\n\t\tutf16col:  5,  // 2 + 1 + 1 + 1 (1-indexed)\n\t\tresCol:    7,  // 4 + 1 + 1 + 1 (1-indexed)\n\t\tresOffset: 13, // 7 (length of first line) + 4 + 1 + 1\n\t\tpre:       \"𐐀45\",\n\t\tpost:      \"\",\n\t},\n\t{\n\t\tscenario:  \"cursor beyond end of file\",\n\t\tinput:     funnyString,\n\t\tline:      2,\n\t\tutf16col:  6,  // 2 + 1 + 1 + 1 + 1(1-indexed)\n\t\tresCol:    8,  // 4 + 1 + 1 + 1 + 1 (1-indexed)\n\t\tresOffset: 14, // 7 (length of first line) + 4 + 1 + 1 + 1\n\t\terr:       \"column is beyond end of file\",\n\t},\n}\n\nfunc TestToUTF16(t *testing.T) {\n\tfor _, e := range toUTF16Tests {\n\t\tt.Run(e.scenario, func(t *testing.T) {\n\t\t\tif e.issue != nil && !*e.issue {\n\t\t\t\tt.Skip(\"expected to fail\")\n\t\t\t}\n\t\t\tm := protocol.NewMapper(\"\", e.input)\n\t\t\tvar pos protocol.Position\n\t\t\tvar err error\n\t\t\tif e.line > 0 {\n\t\t\t\tpos, err = m.LineCol8Position(e.line, e.col)\n\t\t\t} else if e.offset >= 0 {\n\t\t\t\tpos, err = m.OffsetPosition(e.offset)\n\t\t\t} else {\n\t\t\t\terr = fmt.Errorf(\"point has neither offset nor line/column\")\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tif err.Error() != e.err {\n\t\t\t\t\tt.Fatalf(\"expected error %v; got %v\", e.err, err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif e.err != \"\" {\n\t\t\t\tt.Fatalf(\"unexpected success; wanted %v\", e.err)\n\t\t\t}\n\t\t\tgot := int(pos.Character) + 1\n\t\t\tif got != e.resUTF16col {\n\t\t\t\tt.Fatalf(\"expected result %v; got %v\", e.resUTF16col, got)\n\t\t\t}\n\t\t\tpre, post := getPrePost(e.input, e.offset)\n\t\t\tif pre != e.pre {\n\t\t\t\tt.Fatalf(\"expected #%d pre %q; got %q\", e.offset, e.pre, pre)\n\t\t\t}\n\t\t\tif post != e.post {\n\t\t\t\tt.Fatalf(\"expected #%d, post %q; got %q\", e.offset, e.post, post)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFromUTF16(t *testing.T) {\n\tfor _, e := range fromUTF16Tests {\n\t\tt.Run(e.scenario, func(t *testing.T) {\n\t\t\tm := protocol.NewMapper(\"\", e.input)\n\t\t\toffset, err := m.PositionOffset(protocol.Position{\n\t\t\t\tLine:      uint32(e.line - 1),\n\t\t\t\tCharacter: uint32(e.utf16col - 1),\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tif err.Error() != e.err {\n\t\t\t\t\tt.Fatalf(\"expected error %v; got %v\", e.err, err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif e.err != \"\" {\n\t\t\t\tt.Fatalf(\"unexpected success; wanted %v\", e.err)\n\t\t\t}\n\t\t\tif offset != e.resOffset {\n\t\t\t\tt.Fatalf(\"expected offset %v; got %v\", e.resOffset, offset)\n\t\t\t}\n\t\t\tline, col8 := m.OffsetLineCol8(offset)\n\t\t\tif line != e.line {\n\t\t\t\tt.Fatalf(\"expected resulting line %v; got %v\", e.line, line)\n\t\t\t}\n\t\t\tif col8 != e.resCol {\n\t\t\t\tt.Fatalf(\"expected resulting col %v; got %v\", e.resCol, col8)\n\t\t\t}\n\t\t\tpre, post := getPrePost(e.input, offset)\n\t\t\tif pre != e.pre {\n\t\t\t\tt.Fatalf(\"expected #%d pre %q; got %q\", offset, e.pre, pre)\n\t\t\t}\n\t\t\tif post != e.post {\n\t\t\t\tt.Fatalf(\"expected #%d post %q; got %q\", offset, e.post, post)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc getPrePost(content []byte, offset int) (string, string) {\n\tpre, post := string(content)[:offset], string(content)[offset:]\n\tif i := strings.LastIndex(pre, \"\\n\"); i >= 0 {\n\t\tpre = pre[i+1:]\n\t}\n\tif i := strings.IndexRune(post, '\\n'); i >= 0 {\n\t\tpost = post[:i]\n\t}\n\treturn pre, post\n}\n\n// -- these are the historical lsppos tests --\n\ntype testCase struct {\n\tcontent            string // input text\n\tsubstrOrOffset     any    // explicit integer offset, or a substring\n\twantLine, wantChar int    // expected LSP position information\n}\n\n// offset returns the test case byte offset\nfunc (c testCase) offset() int {\n\tswitch x := c.substrOrOffset.(type) {\n\tcase int:\n\t\treturn x\n\tcase string:\n\t\ti := strings.Index(c.content, x)\n\t\tif i < 0 {\n\t\t\tpanic(fmt.Sprintf(\"%q does not contain substring %q\", c.content, x))\n\t\t}\n\t\treturn i\n\t}\n\tpanic(\"substrOrIndex must be an integer or string\")\n}\n\nvar tests = []testCase{\n\t{\"a𐐀b\", \"a\", 0, 0},\n\t{\"a𐐀b\", \"𐐀\", 0, 1},\n\t{\"a𐐀b\", \"b\", 0, 3},\n\t{\"a𐐀b\\n\", \"\\n\", 0, 4},\n\t{\"a𐐀b\\r\\n\", \"\\n\", 0, 4}, // \\r|\\n is not a valid position, so we move back to the end of the first line.\n\t{\"a𐐀b\\r\\nx\", \"x\", 1, 0},\n\t{\"a𐐀b\\r\\nx\\ny\", \"y\", 2, 0},\n\n\t// Testing EOL and EOF positions\n\t{\"\", 0, 0, 0}, // 0th position of an empty buffer is (0, 0)\n\t{\"abc\", \"c\", 0, 2},\n\t{\"abc\", 3, 0, 3},\n\t{\"abc\\n\", \"\\n\", 0, 3},\n\t{\"abc\\n\", 4, 1, 0}, // position after a newline is on the next line\n}\n\nfunc TestLineChar(t *testing.T) {\n\tfor _, test := range tests {\n\t\tm := protocol.NewMapper(\"\", []byte(test.content))\n\t\toffset := test.offset()\n\t\tposn, _ := m.OffsetPosition(offset)\n\t\tgotLine, gotChar := int(posn.Line), int(posn.Character)\n\t\tif gotLine != test.wantLine || gotChar != test.wantChar {\n\t\t\tt.Errorf(\"LineChar(%d) = (%d,%d), want (%d,%d)\", offset, gotLine, gotChar, test.wantLine, test.wantChar)\n\t\t}\n\t}\n}\n\nfunc TestInvalidOffset(t *testing.T) {\n\tcontent := []byte(\"a𐐀b\\r\\nx\\ny\")\n\tm := protocol.NewMapper(\"\", content)\n\tfor _, offset := range []int{-1, 100} {\n\t\tposn, err := m.OffsetPosition(offset)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"OffsetPosition(%d) = %s, want error\", offset, posn)\n\t\t}\n\t}\n}\n\nfunc TestPosition(t *testing.T) {\n\tfor _, test := range tests {\n\t\tm := protocol.NewMapper(\"\", []byte(test.content))\n\t\toffset := test.offset()\n\t\tgot, err := m.OffsetPosition(offset)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"OffsetPosition(%d) failed: %v\", offset, err)\n\t\t\tcontinue\n\t\t}\n\t\twant := protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)}\n\t\tif got != want {\n\t\t\tt.Errorf(\"Position(%d) = %v, want %v\", offset, got, want)\n\t\t}\n\t}\n}\n\nfunc TestRange(t *testing.T) {\n\tfor _, test := range tests {\n\t\tm := protocol.NewMapper(\"\", []byte(test.content))\n\t\toffset := test.offset()\n\t\tgot, err := m.OffsetRange(0, offset)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twant := protocol.Range{\n\t\t\tEnd: protocol.Position{Line: uint32(test.wantLine), Character: uint32(test.wantChar)},\n\t\t}\n\t\tif got != want {\n\t\t\tt.Errorf(\"Range(%d) = %v, want %v\", offset, got, want)\n\t\t}\n\t}\n}\n\nfunc TestBytesOffset(t *testing.T) {\n\ttests := []struct {\n\t\ttext string\n\t\tpos  protocol.Position\n\t\twant int\n\t}{\n\t\t// U+10400 encodes as [F0 90 90 80] in UTF-8 and [D801 DC00] in UTF-16.\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 0}, want: 0},\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 1}, want: 1},\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 2}, want: 1},\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 3}, want: 5},\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 4}, want: 6},\n\t\t{text: `a𐐀b`, pos: protocol.Position{Line: 0, Character: 5}, want: -1},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 0, Character: 3}, want: 3},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 0, Character: 4}, want: -1},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 1, Character: 0}, want: 4},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 1, Character: 3}, want: 7},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 1, Character: 4}, want: -1},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 2, Character: 0}, want: 8},\n\t\t{text: \"aaa\\nbbb\\n\", pos: protocol.Position{Line: 2, Character: 1}, want: -1},\n\t\t{text: \"aaa\\nbbb\\n\\n\", pos: protocol.Position{Line: 2, Character: 0}, want: 8},\n\t}\n\n\tfor i, test := range tests {\n\t\tfname := fmt.Sprintf(\"test %d\", i)\n\t\turi := protocol.URIFromPath(fname)\n\t\tmapper := protocol.NewMapper(uri, []byte(test.text))\n\t\tgot, err := mapper.PositionOffset(test.pos)\n\t\tif err != nil && test.want != -1 {\n\t\t\tt.Errorf(\"%d: unexpected error: %v\", i, err)\n\t\t}\n\t\tif err == nil && got != test.want {\n\t\t\tt.Errorf(\"want %d for %q(Line:%d,Character:%d), but got %d\", test.want, test.text, int(test.pos.Line), int(test.pos.Character), got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/protocol.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\tjsonrpc2_v2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\nvar (\n\t// RequestCancelledError should be used when a request is cancelled early.\n\tRequestCancelledError   = jsonrpc2.NewError(-32800, \"JSON RPC cancelled\")\n\tRequestCancelledErrorV2 = jsonrpc2_v2.NewError(-32800, \"JSON RPC cancelled\")\n)\n\ntype ClientCloser interface {\n\tClient\n\tio.Closer\n}\n\ntype connSender interface {\n\tio.Closer\n\n\tNotify(ctx context.Context, method string, params any) error\n\tCall(ctx context.Context, method string, params, result any) error\n}\n\ntype clientDispatcher struct {\n\tsender connSender\n}\n\nfunc (c *clientDispatcher) Close() error {\n\treturn c.sender.Close()\n}\n\n// ClientDispatcher returns a Client that dispatches LSP requests across the\n// given jsonrpc2 connection.\nfunc ClientDispatcher(conn jsonrpc2.Conn) ClientCloser {\n\treturn &clientDispatcher{sender: clientConn{conn}}\n}\n\ntype clientConn struct {\n\tconn jsonrpc2.Conn\n}\n\nfunc (c clientConn) Close() error {\n\treturn c.conn.Close()\n}\n\nfunc (c clientConn) Notify(ctx context.Context, method string, params any) error {\n\treturn c.conn.Notify(ctx, method, params)\n}\n\nfunc (c clientConn) Call(ctx context.Context, method string, params any, result any) error {\n\tid, err := c.conn.Call(ctx, method, params, result)\n\tif ctx.Err() != nil {\n\t\tcancelCall(ctx, c, id)\n\t}\n\treturn err\n}\n\nfunc ClientDispatcherV2(conn *jsonrpc2_v2.Connection) ClientCloser {\n\treturn &clientDispatcher{clientConnV2{conn}}\n}\n\ntype clientConnV2 struct {\n\tconn *jsonrpc2_v2.Connection\n}\n\nfunc (c clientConnV2) Close() error {\n\treturn c.conn.Close()\n}\n\nfunc (c clientConnV2) Notify(ctx context.Context, method string, params any) error {\n\treturn c.conn.Notify(ctx, method, params)\n}\n\nfunc (c clientConnV2) Call(ctx context.Context, method string, params any, result any) error {\n\tcall := c.conn.Call(ctx, method, params)\n\terr := call.Await(ctx, result)\n\tif ctx.Err() != nil {\n\t\tdetached := xcontext.Detach(ctx)\n\t\tc.conn.Notify(detached, \"$/cancelRequest\", &CancelParams{ID: call.ID().Raw()})\n\t}\n\treturn err\n}\n\n// ServerDispatcher returns a Server that dispatches LSP requests across the\n// given jsonrpc2 connection.\nfunc ServerDispatcher(conn jsonrpc2.Conn) Server {\n\treturn &serverDispatcher{sender: clientConn{conn}}\n}\n\nfunc ServerDispatcherV2(conn *jsonrpc2_v2.Connection) Server {\n\treturn &serverDispatcher{sender: clientConnV2{conn}}\n}\n\ntype serverDispatcher struct {\n\tsender connSender\n}\n\nfunc ClientHandler(client Client, handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\t\tif ctx.Err() != nil {\n\t\t\tctx := xcontext.Detach(ctx)\n\t\t\treturn reply(ctx, nil, RequestCancelledError)\n\t\t}\n\t\thandled, err := clientDispatch(ctx, client, reply, req)\n\t\tif handled || err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn handler(ctx, reply, req)\n\t}\n}\n\nfunc ClientHandlerV2(client Client) jsonrpc2_v2.Handler {\n\treturn jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, RequestCancelledErrorV2\n\t\t}\n\t\treq1 := req2to1(req)\n\t\tvar (\n\t\t\tresult any\n\t\t\tresErr error\n\t\t)\n\t\treplier := func(_ context.Context, res any, err error) error {\n\t\t\tif err != nil {\n\t\t\t\tresErr = err\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tresult = res\n\t\t\treturn nil\n\t\t}\n\t\t_, err := clientDispatch(ctx, client, replier, req1)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn result, resErr\n\t})\n}\n\nfunc ServerHandler(server Server, handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\t\tif ctx.Err() != nil {\n\t\t\tctx := xcontext.Detach(ctx)\n\t\t\treturn reply(ctx, nil, RequestCancelledError)\n\t\t}\n\t\thandled, err := serverDispatch(ctx, server, reply, req)\n\t\tif handled || err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn handler(ctx, reply, req)\n\t}\n}\n\nfunc ServerHandlerV2(server Server) jsonrpc2_v2.Handler {\n\treturn jsonrpc2_v2.HandlerFunc(func(ctx context.Context, req *jsonrpc2_v2.Request) (any, error) {\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, RequestCancelledErrorV2\n\t\t}\n\t\treq1 := req2to1(req)\n\t\tvar (\n\t\t\tresult any\n\t\t\tresErr error\n\t\t)\n\t\treplier := func(_ context.Context, res any, err error) error {\n\t\t\tif err != nil {\n\t\t\t\tresErr = err\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tresult = res\n\t\t\treturn nil\n\t\t}\n\t\t_, err := serverDispatch(ctx, server, replier, req1)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn result, resErr\n\t})\n}\n\nfunc req2to1(req2 *jsonrpc2_v2.Request) jsonrpc2.Request {\n\tif req2.ID.IsValid() {\n\t\traw := req2.ID.Raw()\n\t\tvar idv1 jsonrpc2.ID\n\t\tswitch v := raw.(type) {\n\t\tcase int64:\n\t\t\tidv1 = jsonrpc2.NewIntID(v)\n\t\tcase string:\n\t\t\tidv1 = jsonrpc2.NewStringID(v)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unsupported ID type %T\", raw))\n\t\t}\n\t\treq1, err := jsonrpc2.NewCall(idv1, req2.Method, req2.Params)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn req1\n\t}\n\treq1, err := jsonrpc2.NewNotification(req2.Method, req2.Params)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn req1\n}\n\nfunc Handlers(handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn CancelHandler(\n\t\tjsonrpc2.AsyncHandler(\n\t\t\tjsonrpc2.MustReplyHandler(handler)))\n}\n\nfunc CancelHandler(handler jsonrpc2.Handler) jsonrpc2.Handler {\n\thandler, canceller := jsonrpc2.CancelHandler(handler)\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\t\tif req.Method() != \"$/cancelRequest\" {\n\t\t\t// TODO(iancottrell): See if we can generate a reply for the request to be cancelled\n\t\t\t// at the point of cancellation rather than waiting for gopls to naturally reply.\n\t\t\t// To do that, we need to keep track of whether a reply has been sent already and\n\t\t\t// be careful about racing between the two paths.\n\t\t\t// TODO(iancottrell): Add a test that watches the stream and verifies the response\n\t\t\t// for the cancelled request flows.\n\t\t\treplyWithDetachedContext := func(ctx context.Context, resp any, err error) error {\n\t\t\t\t// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest\n\t\t\t\tif ctx.Err() != nil && err == nil {\n\t\t\t\t\terr = RequestCancelledError\n\t\t\t\t}\n\t\t\t\tctx = xcontext.Detach(ctx)\n\t\t\t\treturn reply(ctx, resp, err)\n\t\t\t}\n\t\t\treturn handler(ctx, replyWithDetachedContext, req)\n\t\t}\n\t\tvar params CancelParams\n\t\tif err := UnmarshalJSON(req.Params(), &params); err != nil {\n\t\t\treturn sendParseError(ctx, reply, err)\n\t\t}\n\t\tif n, ok := params.ID.(float64); ok {\n\t\t\tcanceller(jsonrpc2.NewIntID(int64(n)))\n\t\t} else if s, ok := params.ID.(string); ok {\n\t\t\tcanceller(jsonrpc2.NewStringID(s))\n\t\t} else {\n\t\t\treturn sendParseError(ctx, reply, fmt.Errorf(\"request ID %v malformed\", params.ID))\n\t\t}\n\t\treturn reply(ctx, nil, nil)\n\t}\n}\n\nfunc Call(ctx context.Context, conn jsonrpc2.Conn, method string, params any, result any) error {\n\tid, err := conn.Call(ctx, method, params, result)\n\tif ctx.Err() != nil {\n\t\tcancelCall(ctx, clientConn{conn}, id)\n\t}\n\treturn err\n}\n\nfunc cancelCall(ctx context.Context, sender connSender, id jsonrpc2.ID) {\n\tctx = xcontext.Detach(ctx)\n\tctx, done := event.Start(ctx, \"protocol.canceller\")\n\tdefer done()\n\t// Note that only *jsonrpc2.ID implements json.Marshaler.\n\tsender.Notify(ctx, \"$/cancelRequest\", &CancelParams{ID: &id})\n}\n\n// UnmarshalJSON unmarshals msg into the variable pointed to by\n// params. In JSONRPC, optional messages may be\n// \"null\", in which case it is a no-op.\nfunc UnmarshalJSON(msg json.RawMessage, v any) error {\n\tif len(msg) == 0 || bytes.Equal(msg, []byte(\"null\")) {\n\t\treturn nil\n\t}\n\treturn json.Unmarshal(msg, v)\n}\n\nfunc sendParseError(ctx context.Context, reply jsonrpc2.Replier, err error) error {\n\treturn reply(ctx, nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err))\n}\n\n// NonNilSlice returns x, or an empty slice if x was nil.\n//\n// (Many slice fields of protocol structs must be non-nil\n// to avoid being encoded as JSON \"null\".)\nfunc NonNilSlice[T comparable](x []T) []T {\n\tif x == nil {\n\t\treturn []T{}\n\t}\n\treturn x\n}\n"
  },
  {
    "path": "gopls/internal/protocol/semtok/README.txt",
    "content": "\nThe [LSP](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocument_semanticTokens)\nspecifies semantic tokens as a way of telling clients about language-specific\nproperties of pieces of code in a file being edited.\n\nThe client asks for a set of semantic tokens and modifiers. This note describe which ones\ngopls will return, and under what circumstances. Gopls has no control over how the client\nconverts semantic tokens into colors (or some other visible indication). In vscode it\nis possible to modify the color a theme uses by setting the `editor.semanticTokenColorCustomizations`\nobject. We provide a little [guidance](#Colors) later.\n\nThere are 22 semantic tokens, with 10 possible modifiers. The protocol allows each semantic\ntoken to be used with any of the 1024 subsets of possible modifiers, but most combinations\ndon't make intuitive sense (although `async documentation` has a certain appeal).\n\nThe 22 semantic tokens are `namespace`, `type`, `class`, `enum`, `interface`,\n\t\t`struct`, `typeParameter`, `parameter`, `variable`, `property`, `enumMember`,\n\t\t`event`, `function`, `method`, `macro`, `keyword`, `modifier`, `comment`,\n\t\t`string`, `number`, `regexp`, `operator`.\n\nThe 10 modifiers are `declaration`, `definition`, `readonly`, `static`,\n\t\t`deprecated`, `abstract`, `async`, `modification`, `documentation`, `defaultLibrary`.\n\nThe authoritative lists are in the [specification](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#semanticTokenTypes)\n\nFor the implementation to work correctly the client and server have to agree on the ordering\nof the tokens and of the modifiers. Gopls, therefore, will only send tokens and modifiers\nthat the client has asked for. This document says what gopls would send if the client\nasked for everything. By default, vscode asks for everything.\n\nGopls sends 11 token types for `.go` files and 1 for `.*tmpl` files.\nNothing is sent for any other kind of file.\nThis all could change. (When Go has generics, gopls will return `typeParameter`.)\n\nFor `.*tmpl` files gopls sends `macro`, and no modifiers, for each `{{`...`}}` scope.\n\n## Semantic tokens for Go files\n\nThere are two contrasting guiding principles that might be used to decide what to mark\nwith semantic tokens. All clients already do some kind of syntax marking. E.g., vscode\nuses a TextMate grammar. The minimal principle would send semantic tokens only for those\nlanguage features that cannot be reliably found without parsing Go and looking at types.\nThe maximal principle would attempt to convey as much as possible about the Go code,\nusing all available parsing and type information.\n\nThere is much to be said for returning minimal information, but the minimal principle is\nnot well-specified. Gopls has no way of knowing what the clients know about the Go program\nbeing edited. Even in vscode the TextMate grammars can be more or less elaborate\nand change over time. (Nonetheless, a minimal implementation would not return `keyword`,\n`number`, `comment`, or `string`.)\n\nThe maximal position isn't particularly well-specified either. To chose one example, a\nformat string might have formatting codes (`%-[4].6f`), escape sequences (`\\U00010604`), and regular\ncharacters. Should these all be distinguished? One could even imagine distinguishing\ndifferent runes by their Unicode language assignment, or some other Unicode property, such as\nbeing [confusable](http://www.unicode.org/Public/security/10.0.0/confusables.txt). While gopls does not fully adhere to such distinctions,\nit does recognizes formatting directives within strings, decorating them with \"format\" modifiers,\nproviding more precise semantic highlighting in format strings.\n\nSemantic tokens are returned for identifiers, keywords, operators, comments, and literals.\n(Semantic tokens do not cover the file. They are not returned for\nwhite space or punctuation, and there is no semantic token for labels.)\nThe following describes more precisely what gopls\ndoes, with a few notes on possible alternative choices.\nThe references to *object* refer to the\n```types.Object``` returned by the type checker. The references to *nodes* refer to the\n```ast.Node``` from the parser.\n\n1. __`keyword`__ All Go [keywords](https://golang.org/ref/spec#Keywords) are marked `keyword`.\n1. __`namespace`__ All package names are marked `namespace`. In an import, if there is an\nalias, it would be marked. Otherwise the last component of the import path is marked.\n1. __`type`__ Objects of type ```types.TypeName``` are marked `type`. It also reports\na modifier for the top-level constructor of the object's type, one of:\n`interface`, `struct`, `signature`, `pointer`, `array`, `map`, `slice`, `chan`, `string`, `number`, `bool`, `invalid`.\n1. __`parameter`__ The formal arguments in ```ast.FuncDecl``` and ```ast.FuncType``` nodes are marked `parameter`.\n1. __`variable`__  Identifiers in the\nscope of ```const``` are modified with `readonly`. ```nil``` is usually a `variable` modified with both\n`readonly` and `defaultLibrary`. (```nil``` is a predefined identifier; the user can redefine it,\nin which case it would just be a variable, or whatever.) Identifiers of type ```types.Variable``` are,\nnot surprisingly, marked `variable`. Identifiers being defined (node ```ast.GenDecl```) are modified\nby `definition` and, if appropriate, `readonly`. Receivers (in method declarations) are\n`variable`.\n1. __`method`__ Methods are marked at their definition (```func (x foo) bar() {}```) or declaration\nin an ```interface```. Methods are not marked where they are used.\nIn ```x.bar()```, ```x``` will be marked\neither as a `namespace` if it is a package name, or as a `variable` if it is an interface value,\nso distinguishing ```bar``` seemed superfluous.\n1. __`function`__ Bultins (```types.Builtin```) are modified with `defaultLibrary`\n(e.g., ```make```, ```len```, ```copy```). Identifiers whose\nobject is ```types.Func``` or whose node is ```ast.FuncDecl``` are `function`.\n1. __`comment`__ Comments and struct tags. (Perhaps struct tags should be `property`?)\n1. __`string`__ Strings. Could add modifiers for e.g., escapes or format codes.\n1. __`number`__ Numbers. Should the ```i``` in ```23i``` be handled specially?\n1. __`operator`__ Assignment operators, binary operators, ellipses (```...```), increment/decrement\noperators, sends (```<-```), and unary operators.\n\nGopls will send the modifier `deprecated` if it finds a comment\n```// deprecated``` in the godoc.\n\nThe unused tokens for Go code are `class`, `enum`, `interface`,\n\t\t`struct`, `typeParameter`, `property`, `enumMember`,\n\t\t`event`, `macro`, `modifier`,\n\t\t`regexp`\n\n## Colors\n\nThese comments are about vscode.\n\nThe documentation has a [helpful](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide#custom-textmate-scope-mappings)\ndescription of which semantic tokens correspond to scopes in TextMate grammars. Themes seem\nto use the TextMate scopes to decide on colors.\n\nSome examples of color customizations are [here](https://medium.com/@danromans/how-to-customize-semantic-token-colorization-with-visual-studio-code-ac3eab96141b).\n\n## Note\n\nWhile a file is being edited it may temporarily contain either\nparsing errors or type errors. In this case gopls cannot determine some (or maybe any)\nof the semantic tokens. To avoid weird flickering it is the responsibility\nof clients to maintain the semantic token information\nin the unedited part of the file, and they do.\n"
  },
  {
    "path": "gopls/internal/protocol/semtok/semtok.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The semtok package provides an encoder for LSP's semantic tokens.\npackage semtok\n\nimport \"sort\"\n\n// A Token provides the extent and semantics of a token.\ntype Token struct {\n\tLine, Start uint32 // 0-based UTF-16 index\n\tLen         uint32 // in UTF-16 codes\n\tType        Type\n\tModifiers   []Modifier\n}\n\ntype Type string\n\nconst (\n\t// These are the tokens defined by LSP 3.18, but a client is\n\t// free to send its own set; any tokens that the server emits\n\t// that are not in this set are simply not encoded in the bitfield.\n\tTokComment   Type = \"comment\"       // for a comment\n\tTokFunction  Type = \"function\"      // for a function\n\tTokKeyword   Type = \"keyword\"       // for a keyword\n\tTokLabel     Type = \"label\"         // for a control label (LSP 3.18)\n\tTokMacro     Type = \"macro\"         // for text/template tokens\n\tTokMethod    Type = \"method\"        // for a method\n\tTokNamespace Type = \"namespace\"     // for an imported package name\n\tTokNumber    Type = \"number\"        // for a numeric literal\n\tTokOperator  Type = \"operator\"      // for an operator\n\tTokParameter Type = \"parameter\"     // for a parameter variable\n\tTokProperty  Type = \"property\"      // for a struct field\n\tTokString    Type = \"string\"        // for a string literal\n\tTokType      Type = \"type\"          // for a type name (plus other uses)\n\tTokTypeParam Type = \"typeParameter\" // for a type parameter\n\tTokVariable  Type = \"variable\"      // for a var or const\n\t// The section below defines a subset of token types in standard token types\n\t// that gopls does not use.\n\t//\n\t// If you move types to above, document it in\n\t// gopls/doc/features/passive.md#semantic-tokens.\n\t// TokClass      Type = \"class\"\n\t// TokDecorator  Type = \"decorator\"\n\t// TokEnum       Type = \"enum\"\n\t// TokEnumMember Type = \"enumMember\"\n\t// TokEvent      Type = \"event\"\n\t// TokInterface  Type = \"interface\"\n\t// TokModifier   Type = \"modifier\"\n\t// TokRegexp     Type = \"regexp\"\n\t// TokStruct     Type = \"struct\"\n)\n\n// Types is a slice of types gopls will return as its server capabilities.\nvar Types = []Type{\n\tTokNamespace,\n\tTokType,\n\tTokTypeParam,\n\tTokParameter,\n\tTokProperty,\n\tTokVariable,\n\tTokFunction,\n\tTokMethod,\n\tTokMacro,\n\tTokKeyword,\n\tTokComment,\n\tTokString,\n\tTokNumber,\n\tTokOperator,\n\tTokLabel,\n}\n\ntype Modifier string\n\nconst (\n\t// LSP 3.18 standard modifiers\n\t// As with Types, clients get only the modifiers they request.\n\t//\n\t// The section below defines a subset of modifiers in standard modifiers\n\t// that gopls understand.\n\tModDefaultLibrary Modifier = \"defaultLibrary\" // for predeclared symbols\n\tModDefinition     Modifier = \"definition\"     // for the declaring identifier of a symbol\n\tModReadonly       Modifier = \"readonly\"       // for constants (TokVariable)\n\tModStatic         Modifier = \"static\"         // for package-level variables\n\t// The section below defines the rest of the modifiers in standard modifiers\n\t// that gopls does not use.\n\t//\n\t// If you move modifiers to above, document it in\n\t// gopls/doc/features/passive.md#semantic-tokens.\n\t// ModAbstract      Modifier = \"abstract\"\n\t// ModAsync         Modifier = \"async\"\n\t// ModDeclaration   Modifier = \"declaration\"\n\t// ModDeprecated    Modifier = \"deprecated\"\n\t// ModDocumentation Modifier = \"documentation\"\n\t// ModModification  Modifier = \"modification\"\n\n\t// non-standard modifiers\n\t//\n\t// Since the type of a symbol is orthogonal to its kind,\n\t// (e.g. a variable can have function type),\n\t// we use modifiers for the top-level type constructor.\n\tModArray     Modifier = \"array\"\n\tModBool      Modifier = \"bool\"\n\tModChan      Modifier = \"chan\"\n\tModFormat    Modifier = \"format\" // for format string directives such as \"%s\"\n\tModInterface Modifier = \"interface\"\n\tModMap       Modifier = \"map\"\n\tModNumber    Modifier = \"number\"\n\tModPointer   Modifier = \"pointer\"\n\tModSignature Modifier = \"signature\" // for function types\n\tModSlice     Modifier = \"slice\"\n\tModString    Modifier = \"string\"\n\tModStruct    Modifier = \"struct\"\n)\n\n// Modifiers is a slice of modifiers gopls will return as its server capabilities.\nvar Modifiers = []Modifier{\n\t// LSP 3.18 standard modifiers.\n\tModDefinition,\n\tModReadonly,\n\tModDefaultLibrary,\n\tModStatic,\n\t// Additional custom modifiers.\n\tModArray,\n\tModBool,\n\tModChan,\n\tModFormat,\n\tModInterface,\n\tModMap,\n\tModNumber,\n\tModPointer,\n\tModSignature,\n\tModSlice,\n\tModString,\n\tModStruct,\n}\n\n// Encode returns the LSP encoding of a sequence of tokens.\n// encodeType and encodeModifier maps control which types and modifiers are\n// excluded in the response. If a type or modifier maps to false, it will be\n// omitted from the output.\nfunc Encode(\n\ttokens []Token,\n\tencodeType map[Type]bool,\n\tencodeModifier map[Modifier]bool) []uint32 {\n\n\t// binary operators, at least, will be out of order\n\tsort.Slice(tokens, func(i, j int) bool {\n\t\tif tokens[i].Line != tokens[j].Line {\n\t\t\treturn tokens[i].Line < tokens[j].Line\n\t\t}\n\t\treturn tokens[i].Start < tokens[j].Start\n\t})\n\n\ttypeMap := make(map[Type]int)\n\tfor i, t := range Types {\n\t\tif enable, ok := encodeType[t]; ok && !enable {\n\t\t\tcontinue\n\t\t}\n\t\ttypeMap[Type(t)] = i\n\t}\n\n\tmodMap := make(map[Modifier]int)\n\tfor i, m := range Modifiers {\n\t\tif enable, ok := encodeModifier[m]; ok && !enable {\n\t\t\tcontinue\n\t\t}\n\t\tmodMap[Modifier(m)] = 1 << i\n\t}\n\n\t// each semantic token needs five values but some tokens might be skipped.\n\t// (see Integer Encoding for Tokens in the LSP spec)\n\tx := make([]uint32, 5*len(tokens))\n\tvar j int\n\tvar last Token\n\tfor i := range tokens {\n\t\titem := tokens[i]\n\t\ttyp, ok := typeMap[item.Type]\n\t\tif !ok {\n\t\t\tcontinue // client doesn't want semantic token info.\n\t\t}\n\t\tif j == 0 {\n\t\t\tx[0] = tokens[0].Line\n\t\t} else {\n\t\t\tx[j] = item.Line - last.Line\n\t\t}\n\t\tx[j+1] = item.Start\n\t\tif j > 0 && x[j] == 0 {\n\t\t\tx[j+1] = item.Start - last.Start\n\t\t}\n\t\tx[j+2] = item.Len\n\t\tx[j+3] = uint32(typ)\n\t\tmask := 0\n\t\tfor _, s := range item.Modifiers {\n\t\t\t// modMap[s] is 0 if the client doesn't want this modifier\n\t\t\tmask |= modMap[s]\n\t\t}\n\t\tx[j+4] = uint32(mask)\n\t\tj += 5\n\t\tlast = item\n\t}\n\treturn x[:j]\n}\n"
  },
  {
    "path": "gopls/internal/protocol/span.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"fmt\"\n\t\"unicode/utf8\"\n)\n\n// Empty reports whether the Range is an empty selection.\nfunc (rng Range) Empty() bool { return rng.Start == rng.End }\n\n// Contains reports whether the position is within the range, inclusive of the\n// start and end positions.\nfunc (rng Range) Contains(pos Position) bool {\n\treturn ComparePosition(rng.Start, pos) <= 0 &&\n\t\tComparePosition(pos, rng.End) <= 0\n}\n\n// Empty reports whether the Location is an empty selection.\nfunc (loc Location) Empty() bool { return loc.Range.Empty() }\n\n// CompareLocation defines a three-valued comparison over locations,\n// lexicographically ordered by (URI, Range).\nfunc CompareLocation(x, y Location) int {\n\tif x.URI != y.URI {\n\t\tif x.URI < y.URI {\n\t\t\treturn -1\n\t\t} else {\n\t\t\treturn +1\n\t\t}\n\t}\n\treturn CompareRange(x.Range, y.Range)\n}\n\n// CompareRange returns -1 if a is before b, 0 if a == b, and 1 if a is after b.\n//\n// A range a is defined to be 'before' b if a.Start is before b.Start, or\n// a.Start == b.Start and a.End is before b.End.\nfunc CompareRange(a, b Range) int {\n\tif r := ComparePosition(a.Start, b.Start); r != 0 {\n\t\treturn r\n\t}\n\treturn ComparePosition(a.End, b.End)\n}\n\n// ComparePosition returns -1 if a is before b, 0 if a == b, and 1 if a is after b.\nfunc ComparePosition(a, b Position) int {\n\tif a.Line != b.Line {\n\t\tif a.Line < b.Line {\n\t\t\treturn -1\n\t\t} else {\n\t\t\treturn +1\n\t\t}\n\t}\n\tif a.Character != b.Character {\n\t\tif a.Character < b.Character {\n\t\t\treturn -1\n\t\t} else {\n\t\t\treturn +1\n\t\t}\n\t}\n\treturn 0\n}\n\n// Intersect reports whether x and y intersect.\n//\n// Two non-empty half-open integer intervals intersect iff:\n//\n//\ty.start < x.end && x.start < y.end\n//\n// Mathematical conventional views an interval as a set of integers.\n// An empty interval is the empty set, so its intersection with any\n// other interval is empty, and thus an empty interval does not\n// intersect any other interval.\n//\n// However, this function uses a looser definition appropriate for\n// text selections: if either x or y is empty, it uses <= operators\n// instead, so an empty range within or abutting a non-empty range is\n// considered to overlap it, and an empty range overlaps itself.\n//\n// This handles the common case in which there is no selection, but\n// the cursor is at the start or end of an expression and the caller\n// wants to know whether the cursor intersects the range of the\n// expression. The answer in this case should be yes, even though the\n// selection is empty. Similarly the answer should also be yes if the\n// cursor is properly within the range of the expression. But a\n// non-empty selection abutting the expression should not be\n// considered to intersect it.\nfunc Intersect(x, y Range) bool {\n\tr1 := ComparePosition(x.Start, y.End)\n\tr2 := ComparePosition(y.Start, x.End)\n\tif r1 < 0 && r2 < 0 {\n\t\treturn true // mathematical intersection\n\t}\n\treturn (x.Empty() || y.Empty()) && r1 <= 0 && r2 <= 0\n}\n\n// Format implements fmt.Formatter.\n//\n// Note: Formatter is implemented instead of Stringer (presumably) for\n// performance reasons, though it is not clear that it matters in practice.\nfunc (r Range) Format(f fmt.State, _ rune) {\n\tfmt.Fprintf(f, \"%v-%v\", r.Start, r.End)\n}\n\n// Format implements fmt.Formatter.\n//\n// See Range.Format for discussion of why the Formatter interface is\n// implemented rather than Stringer.\nfunc (p Position) Format(f fmt.State, _ rune) {\n\tfmt.Fprintf(f, \"%v:%v\", p.Line, p.Character)\n}\n\n// -- implementation helpers --\n\n// UTF16Len returns the number of codes in the UTF-16 transcoding of s.\nfunc UTF16Len(s []byte) int {\n\tvar n int\n\tfor len(s) > 0 {\n\t\tn++\n\n\t\t// Fast path for ASCII.\n\t\tif s[0] < 0x80 {\n\t\t\ts = s[1:]\n\t\t\tcontinue\n\t\t}\n\n\t\tr, size := utf8.DecodeRune(s)\n\t\tif r >= 0x10000 {\n\t\t\tn++ // surrogate pair\n\t\t}\n\t\ts = s[size:]\n\t}\n\treturn n\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsclient.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated for LSP. DO NOT EDIT.\n\npackage protocol\n\n// Code generated from protocol/metaModel.json at ref release/protocol/3.17.6-next.14 (hash 66a087310eea0d60495ba3578d78f70409c403d9).\n// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.6-next.14/protocol/metaModel.json\n// LSP metaData.version = 3.17.0.\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\ntype Client interface {\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#logTrace\n\tLogTrace(context.Context, *LogTraceParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#progress\n\tProgress(context.Context, *ProgressParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#client_registerCapability\n\tRegisterCapability(context.Context, *RegistrationParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#client_unregisterCapability\n\tUnregisterCapability(context.Context, *UnregistrationParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#telemetry_event\n\tEvent(context.Context, *any) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_publishDiagnostics\n\tPublishDiagnostics(context.Context, *PublishDiagnosticsParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_logMessage\n\tLogMessage(context.Context, *LogMessageParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_showDocument\n\tShowDocument(context.Context, *ShowDocumentParams) (*ShowDocumentResult, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_showMessage\n\tShowMessage(context.Context, *ShowMessageParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_showMessageRequest\n\tShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_workDoneProgress_create\n\tWorkDoneProgressCreate(context.Context, *WorkDoneProgressCreateParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_applyEdit\n\tApplyEdit(context.Context, *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResult, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_codeLens_refresh\n\tCodeLensRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_configuration\n\tConfiguration(context.Context, *ParamConfiguration) ([]LSPAny, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_diagnostic_refresh\n\tDiagnosticRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_foldingRange_refresh\n\tFoldingRangeRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_inlayHint_refresh\n\tInlayHintRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_inlineValue_refresh\n\tInlineValueRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_semanticTokens_refresh\n\tSemanticTokensRefresh(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_textDocumentContent_refresh\n\tTextDocumentContentRefresh(context.Context, *TextDocumentContentRefreshParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_workspaceFolders\n\tWorkspaceFolders(context.Context) ([]WorkspaceFolder, error)\n}\n\nfunc clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {\n\tresp, valid, err := ClientDispatchCall(ctx, client, r.Method(), r.Params())\n\tif !valid {\n\t\treturn false, nil\n\t}\n\n\tif err != nil {\n\t\treturn valid, reply(ctx, nil, err)\n\t} else {\n\t\treturn valid, reply(ctx, resp, nil)\n\t}\n}\n\nfunc ClientDispatchCall(ctx context.Context, client Client, method string, raw json.RawMessage) (resp any, _ bool, err error) {\n\tswitch method {\n\tcase \"$/logTrace\":\n\t\tvar params LogTraceParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.LogTrace(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"$/progress\":\n\t\tvar params ProgressParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.Progress(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"client/registerCapability\":\n\t\tvar params RegistrationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.RegisterCapability(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"client/unregisterCapability\":\n\t\tvar params UnregistrationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.UnregisterCapability(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"telemetry/event\":\n\t\tvar params any\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.Event(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/publishDiagnostics\":\n\t\tvar params PublishDiagnosticsParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.PublishDiagnostics(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"window/logMessage\":\n\t\tvar params LogMessageParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.LogMessage(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"window/showDocument\":\n\t\tvar params ShowDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := client.ShowDocument(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"window/showMessage\":\n\t\tvar params ShowMessageParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.ShowMessage(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"window/showMessageRequest\":\n\t\tvar params ShowMessageRequestParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := client.ShowMessageRequest(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"window/workDoneProgress/create\":\n\t\tvar params WorkDoneProgressCreateParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.WorkDoneProgressCreate(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/applyEdit\":\n\t\tvar params ApplyWorkspaceEditParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := client.ApplyEdit(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/codeLens/refresh\":\n\t\terr := client.CodeLensRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/configuration\":\n\t\tvar params ParamConfiguration\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := client.Configuration(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/diagnostic/refresh\":\n\t\terr := client.DiagnosticRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/foldingRange/refresh\":\n\t\terr := client.FoldingRangeRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/inlayHint/refresh\":\n\t\terr := client.InlayHintRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/inlineValue/refresh\":\n\t\terr := client.InlineValueRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/semanticTokens/refresh\":\n\t\terr := client.SemanticTokensRefresh(ctx)\n\t\treturn nil, true, err\n\n\tcase \"workspace/textDocumentContent/refresh\":\n\t\tvar params TextDocumentContentRefreshParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := client.TextDocumentContentRefresh(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/workspaceFolders\":\n\t\tresp, err := client.WorkspaceFolders(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tdefault:\n\t\treturn nil, false, nil\n\t}\n}\n\nfunc (s *clientDispatcher) LogTrace(ctx context.Context, params *LogTraceParams) error {\n\treturn s.sender.Notify(ctx, \"$/logTrace\", params)\n}\nfunc (s *clientDispatcher) Progress(ctx context.Context, params *ProgressParams) error {\n\treturn s.sender.Notify(ctx, \"$/progress\", params)\n}\nfunc (s *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error {\n\treturn s.sender.Call(ctx, \"client/registerCapability\", params, nil)\n}\nfunc (s *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error {\n\treturn s.sender.Call(ctx, \"client/unregisterCapability\", params, nil)\n}\nfunc (s *clientDispatcher) Event(ctx context.Context, params *any) error {\n\treturn s.sender.Notify(ctx, \"telemetry/event\", params)\n}\nfunc (s *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/publishDiagnostics\", params)\n}\nfunc (s *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error {\n\treturn s.sender.Notify(ctx, \"window/logMessage\", params)\n}\nfunc (s *clientDispatcher) ShowDocument(ctx context.Context, params *ShowDocumentParams) (*ShowDocumentResult, error) {\n\tvar result *ShowDocumentResult\n\tif err := s.sender.Call(ctx, \"window/showDocument\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error {\n\treturn s.sender.Notify(ctx, \"window/showMessage\", params)\n}\nfunc (s *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) {\n\tvar result *MessageActionItem\n\tif err := s.sender.Call(ctx, \"window/showMessageRequest\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *clientDispatcher) WorkDoneProgressCreate(ctx context.Context, params *WorkDoneProgressCreateParams) error {\n\treturn s.sender.Call(ctx, \"window/workDoneProgress/create\", params, nil)\n}\nfunc (s *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResult, error) {\n\tvar result *ApplyWorkspaceEditResult\n\tif err := s.sender.Call(ctx, \"workspace/applyEdit\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *clientDispatcher) CodeLensRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/codeLens/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) Configuration(ctx context.Context, params *ParamConfiguration) ([]LSPAny, error) {\n\tvar result []LSPAny\n\tif err := s.sender.Call(ctx, \"workspace/configuration\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *clientDispatcher) DiagnosticRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/diagnostic/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) FoldingRangeRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/foldingRange/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) InlayHintRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/inlayHint/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) InlineValueRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/inlineValue/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) SemanticTokensRefresh(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"workspace/semanticTokens/refresh\", nil, nil)\n}\nfunc (s *clientDispatcher) TextDocumentContentRefresh(ctx context.Context, params *TextDocumentContentRefreshParams) error {\n\treturn s.sender.Call(ctx, \"workspace/textDocumentContent/refresh\", params, nil)\n}\nfunc (s *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) {\n\tvar result []WorkspaceFolder\n\tif err := s.sender.Call(ctx, \"workspace/workspaceFolders\", nil, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsdocument_changes.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// DocumentChange is a union of various file edit operations.\n//\n// Exactly one field of this struct is non-nil; see [DocumentChange.Valid].\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#resourceChanges\ntype DocumentChange struct {\n\tTextDocumentEdit *TextDocumentEdit\n\tCreateFile       *CreateFile\n\tRenameFile       *RenameFile\n\tDeleteFile       *DeleteFile\n}\n\n// Valid reports whether the DocumentChange sum-type value is valid,\n// that is, exactly one of create, delete, edit, or rename.\nfunc (ch DocumentChange) Valid() bool {\n\tn := 0\n\tif ch.TextDocumentEdit != nil {\n\t\tn++\n\t}\n\tif ch.CreateFile != nil {\n\t\tn++\n\t}\n\tif ch.RenameFile != nil {\n\t\tn++\n\t}\n\tif ch.DeleteFile != nil {\n\t\tn++\n\t}\n\treturn n == 1\n}\n\nfunc (d *DocumentChange) UnmarshalJSON(data []byte) error {\n\tvar m map[string]any\n\tif err := json.Unmarshal(data, &m); err != nil {\n\t\treturn err\n\t}\n\n\tif _, ok := m[\"textDocument\"]; ok {\n\t\td.TextDocumentEdit = new(TextDocumentEdit)\n\t\treturn json.Unmarshal(data, d.TextDocumentEdit)\n\t}\n\n\t// The {Create,Rename,Delete}File types all share a 'kind' field.\n\tkind := m[\"kind\"]\n\tswitch kind {\n\tcase \"create\":\n\t\td.CreateFile = new(CreateFile)\n\t\treturn json.Unmarshal(data, d.CreateFile)\n\tcase \"rename\":\n\t\td.RenameFile = new(RenameFile)\n\t\treturn json.Unmarshal(data, d.RenameFile)\n\tcase \"delete\":\n\t\td.DeleteFile = new(DeleteFile)\n\t\treturn json.Unmarshal(data, d.DeleteFile)\n\t}\n\treturn fmt.Errorf(\"DocumentChanges: unexpected kind: %q\", kind)\n}\n\nfunc (d *DocumentChange) MarshalJSON() ([]byte, error) {\n\tif d.TextDocumentEdit != nil {\n\t\treturn json.Marshal(d.TextDocumentEdit)\n\t} else if d.CreateFile != nil {\n\t\treturn json.Marshal(d.CreateFile)\n\t} else if d.RenameFile != nil {\n\t\treturn json.Marshal(d.RenameFile)\n\t} else if d.DeleteFile != nil {\n\t\treturn json.Marshal(d.DeleteFile)\n\t}\n\treturn nil, fmt.Errorf(\"empty DocumentChanges union value\")\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsinsertreplaceedit.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// InsertReplaceEdit is used instead of TextEdit in CompletionItem\n// in editors that support it. These two types are alike in appearance\n// but can be differentiated by the presence or absence of\n// certain properties. UnmarshalJSON of the sum type tries to\n// unmarshal as TextEdit only if unmarshal as InsertReplaceEdit fails.\n// However, due to this similarity, unmarshal with the other type\n// never fails. This file has a custom JSON unmarshaller for\n// InsertReplaceEdit, that fails if the required fields are missing.\n\n// UnmarshalJSON unmarshals InsertReplaceEdit with extra\n// checks on the presence of \"insert\" and \"replace\" properties.\nfunc (e *InsertReplaceEdit) UnmarshalJSON(data []byte) error {\n\tvar required struct {\n\t\tNewText string\n\t\tInsert  *Range `json:\"insert,omitempty\"`\n\t\tReplace *Range `json:\"replace,omitempty\"`\n\t}\n\n\tif err := json.Unmarshal(data, &required); err != nil {\n\t\treturn err\n\t}\n\tif required.Insert == nil && required.Replace == nil {\n\t\treturn fmt.Errorf(\"not InsertReplaceEdit\")\n\t}\n\te.NewText = required.NewText\n\te.Insert = *required.Insert\n\te.Replace = *required.Replace\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsinsertreplaceedit_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestInsertReplaceEdit_UnmarshalJSON(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tin      any\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"TextEdit\",\n\t\t\tin:   TextEdit{NewText: \"new text\", Range: Range{Start: Position{Line: 1}}},\n\t\t},\n\t\t{\n\t\t\tname: \"InsertReplaceEdit\",\n\t\t\tin:   InsertReplaceEdit{NewText: \"new text\", Insert: Range{Start: Position{Line: 100}}, Replace: Range{End: Position{Line: 200}}},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tdata, err := json.MarshalIndent(Or_CompletionItem_textEdit{Value: tt.in}, \"\", \" \")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"failed to marshal: %v\", err)\n\t\t\t}\n\t\t\tvar decoded Or_CompletionItem_textEdit\n\t\t\tif err := json.Unmarshal(data, &decoded); err != nil {\n\t\t\t\tt.Fatalf(\"failed to unmarshal: %v\", err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(tt.in, decoded.Value); diff != \"\" {\n\t\t\t\tt.Errorf(\"unmarshal returns unexpected result: (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsjson.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated for LSP. DO NOT EDIT.\n\npackage protocol\n\n// Code generated from protocol/metaModel.json at ref release/protocol/3.17.6-next.14 (hash 66a087310eea0d60495ba3578d78f70409c403d9).\n// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.6-next.14/protocol/metaModel.json\n// LSP metaData.version = 3.17.0.\n\nimport \"encoding/json\"\n\nimport \"fmt\"\n\n// UnmarshalError indicates that a JSON value did not conform to\n// one of the expected cases of an LSP union type.\ntype UnmarshalError struct {\n\tmsg string\n}\n\nfunc (e UnmarshalError) Error() string {\n\treturn e.msg\n}\nfunc (t OrPLocation_workspace_symbol) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase Location:\n\t\treturn json.Marshal(x)\n\tcase LocationUriOnly:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [Location LocationUriOnly]\", t)\n}\n\nfunc (t *OrPLocation_workspace_symbol) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 Location\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 LocationUriOnly\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [Location LocationUriOnly]\"}\n}\n\nfunc (t OrPSection_workspace_didChangeConfiguration) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase []string:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [[]string string]\", t)\n}\n\nfunc (t *OrPSection_workspace_didChangeConfiguration) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 []string\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [[]string string]\"}\n}\n\nfunc (t OrPTooltipPLabel) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkupContent:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkupContent string]\", t)\n}\n\nfunc (t *OrPTooltipPLabel) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkupContent\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkupContent string]\"}\n}\n\nfunc (t OrPTooltip_textDocument_inlayHint) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkupContent:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkupContent string]\", t)\n}\n\nfunc (t *OrPTooltip_textDocument_inlayHint) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkupContent\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkupContent string]\"}\n}\n\nfunc (t Or_CancelParams_id) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase int32:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [int32 string]\", t)\n}\n\nfunc (t *Or_CancelParams_id) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 int32\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [int32 string]\"}\n}\n\nfunc (t Or_ClientSemanticTokensRequestOptions_full) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase ClientSemanticTokensRequestFullDelta:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [ClientSemanticTokensRequestFullDelta bool]\", t)\n}\n\nfunc (t *Or_ClientSemanticTokensRequestOptions_full) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 ClientSemanticTokensRequestFullDelta\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [ClientSemanticTokensRequestFullDelta bool]\"}\n}\n\nfunc (t Or_ClientSemanticTokensRequestOptions_range) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase Lit_ClientSemanticTokensRequestOptions_range_Item1:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [Lit_ClientSemanticTokensRequestOptions_range_Item1 bool]\", t)\n}\n\nfunc (t *Or_ClientSemanticTokensRequestOptions_range) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 Lit_ClientSemanticTokensRequestOptions_range_Item1\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [Lit_ClientSemanticTokensRequestOptions_range_Item1 bool]\"}\n}\n\nfunc (t Or_CompletionItemDefaults_editRange) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase EditRangeWithInsertReplace:\n\t\treturn json.Marshal(x)\n\tcase Range:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [EditRangeWithInsertReplace Range]\", t)\n}\n\nfunc (t *Or_CompletionItemDefaults_editRange) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 EditRangeWithInsertReplace\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 Range\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [EditRangeWithInsertReplace Range]\"}\n}\n\nfunc (t Or_CompletionItem_documentation) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkupContent:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkupContent string]\", t)\n}\n\nfunc (t *Or_CompletionItem_documentation) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkupContent\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkupContent string]\"}\n}\n\nfunc (t Or_CompletionItem_textEdit) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InsertReplaceEdit:\n\t\treturn json.Marshal(x)\n\tcase TextEdit:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InsertReplaceEdit TextEdit]\", t)\n}\n\nfunc (t *Or_CompletionItem_textEdit) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InsertReplaceEdit\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TextEdit\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InsertReplaceEdit TextEdit]\"}\n}\n\nfunc (t Or_Definition) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase Location:\n\t\treturn json.Marshal(x)\n\tcase []Location:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [Location []Location]\", t)\n}\n\nfunc (t *Or_Definition) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 Location\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 []Location\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [Location []Location]\"}\n}\n\nfunc (t Or_Diagnostic_code) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase int32:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [int32 string]\", t)\n}\n\nfunc (t *Or_Diagnostic_code) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 int32\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [int32 string]\"}\n}\n\nfunc (t Or_DocumentDiagnosticReport) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase RelatedFullDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase RelatedUnchangedDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]\", t)\n}\n\nfunc (t *Or_DocumentDiagnosticReport) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 RelatedFullDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 RelatedUnchangedDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]\"}\n}\n\nfunc (t Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase FullDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase UnchangedDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\", t)\n}\n\nfunc (t *Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 FullDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 UnchangedDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\"}\n}\n\nfunc (t Or_DocumentFilter) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookCellTextDocumentFilter:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentFilter:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookCellTextDocumentFilter TextDocumentFilter]\", t)\n}\n\nfunc (t *Or_DocumentFilter) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookCellTextDocumentFilter\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TextDocumentFilter\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookCellTextDocumentFilter TextDocumentFilter]\"}\n}\n\nfunc (t Or_GlobPattern) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase Pattern:\n\t\treturn json.Marshal(x)\n\tcase RelativePattern:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [Pattern RelativePattern]\", t)\n}\n\nfunc (t *Or_GlobPattern) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 Pattern\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 RelativePattern\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [Pattern RelativePattern]\"}\n}\n\nfunc (t Or_Hover_contents) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkedString:\n\t\treturn json.Marshal(x)\n\tcase MarkupContent:\n\t\treturn json.Marshal(x)\n\tcase []MarkedString:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkedString MarkupContent []MarkedString]\", t)\n}\n\nfunc (t *Or_Hover_contents) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkedString\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 MarkupContent\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 []MarkedString\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkedString MarkupContent []MarkedString]\"}\n}\n\nfunc (t Or_InlayHint_label) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase []InlayHintLabelPart:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [[]InlayHintLabelPart string]\", t)\n}\n\nfunc (t *Or_InlayHint_label) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 []InlayHintLabelPart\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [[]InlayHintLabelPart string]\"}\n}\n\nfunc (t Or_InlineCompletionItem_insertText) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase StringValue:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [StringValue string]\", t)\n}\n\nfunc (t *Or_InlineCompletionItem_insertText) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 StringValue\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [StringValue string]\"}\n}\n\nfunc (t Or_InlineValue) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InlineValueEvaluatableExpression:\n\t\treturn json.Marshal(x)\n\tcase InlineValueText:\n\t\treturn json.Marshal(x)\n\tcase InlineValueVariableLookup:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]\", t)\n}\n\nfunc (t *Or_InlineValue) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InlineValueEvaluatableExpression\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 InlineValueText\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 InlineValueVariableLookup\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]\"}\n}\n\nfunc (t Or_MarkedString) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkedStringWithLanguage:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkedStringWithLanguage string]\", t)\n}\n\nfunc (t *Or_MarkedString) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkedStringWithLanguage\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkedStringWithLanguage string]\"}\n}\n\nfunc (t Or_NotebookCellTextDocumentFilter_notebook) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentFilter:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentFilter string]\", t)\n}\n\nfunc (t *Or_NotebookCellTextDocumentFilter_notebook) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentFilter\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentFilter string]\"}\n}\n\nfunc (t Or_NotebookDocumentFilter) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentFilterNotebookType:\n\t\treturn json.Marshal(x)\n\tcase NotebookDocumentFilterPattern:\n\t\treturn json.Marshal(x)\n\tcase NotebookDocumentFilterScheme:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentFilterNotebookType NotebookDocumentFilterPattern NotebookDocumentFilterScheme]\", t)\n}\n\nfunc (t *Or_NotebookDocumentFilter) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentFilterNotebookType\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 NotebookDocumentFilterPattern\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 NotebookDocumentFilterScheme\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentFilterNotebookType NotebookDocumentFilterPattern NotebookDocumentFilterScheme]\"}\n}\n\nfunc (t Or_NotebookDocumentFilterWithCells_notebook) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentFilter:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentFilter string]\", t)\n}\n\nfunc (t *Or_NotebookDocumentFilterWithCells_notebook) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentFilter\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentFilter string]\"}\n}\n\nfunc (t Or_NotebookDocumentFilterWithNotebook_notebook) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentFilter:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentFilter string]\", t)\n}\n\nfunc (t *Or_NotebookDocumentFilterWithNotebook_notebook) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentFilter\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentFilter string]\"}\n}\n\nfunc (t Or_NotebookDocumentSyncOptions_notebookSelector_Elem) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentFilterWithCells:\n\t\treturn json.Marshal(x)\n\tcase NotebookDocumentFilterWithNotebook:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentFilterWithCells NotebookDocumentFilterWithNotebook]\", t)\n}\n\nfunc (t *Or_NotebookDocumentSyncOptions_notebookSelector_Elem) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentFilterWithCells\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 NotebookDocumentFilterWithNotebook\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentFilterWithCells NotebookDocumentFilterWithNotebook]\"}\n}\n\nfunc (t Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase FullDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase UnchangedDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\", t)\n}\n\nfunc (t *Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 FullDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 UnchangedDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\"}\n}\n\nfunc (t Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase FullDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase UnchangedDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\", t)\n}\n\nfunc (t *Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 FullDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 UnchangedDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\"}\n}\n\nfunc (t Or_Result_textDocument_codeAction_Item0_Elem) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase CodeAction:\n\t\treturn json.Marshal(x)\n\tcase Command:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [CodeAction Command]\", t)\n}\n\nfunc (t *Or_Result_textDocument_codeAction_Item0_Elem) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 CodeAction\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 Command\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [CodeAction Command]\"}\n}\n\nfunc (t Or_Result_textDocument_inlineCompletion) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InlineCompletionList:\n\t\treturn json.Marshal(x)\n\tcase []InlineCompletionItem:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InlineCompletionList []InlineCompletionItem]\", t)\n}\n\nfunc (t *Or_Result_textDocument_inlineCompletion) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InlineCompletionList\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 []InlineCompletionItem\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InlineCompletionList []InlineCompletionItem]\"}\n}\n\nfunc (t Or_SemanticTokensOptions_full) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase SemanticTokensFullDelta:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [SemanticTokensFullDelta bool]\", t)\n}\n\nfunc (t *Or_SemanticTokensOptions_full) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 SemanticTokensFullDelta\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [SemanticTokensFullDelta bool]\"}\n}\n\nfunc (t Or_SemanticTokensOptions_range) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase PRangeESemanticTokensOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [PRangeESemanticTokensOptions bool]\", t)\n}\n\nfunc (t *Or_SemanticTokensOptions_range) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 PRangeESemanticTokensOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [PRangeESemanticTokensOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_callHierarchyProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase CallHierarchyOptions:\n\t\treturn json.Marshal(x)\n\tcase CallHierarchyRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [CallHierarchyOptions CallHierarchyRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_callHierarchyProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 CallHierarchyOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 CallHierarchyRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [CallHierarchyOptions CallHierarchyRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_codeActionProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase CodeActionOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [CodeActionOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_codeActionProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 CodeActionOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [CodeActionOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_colorProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DocumentColorOptions:\n\t\treturn json.Marshal(x)\n\tcase DocumentColorRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DocumentColorOptions DocumentColorRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_colorProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DocumentColorOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 DocumentColorRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DocumentColorOptions DocumentColorRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_declarationProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DeclarationOptions:\n\t\treturn json.Marshal(x)\n\tcase DeclarationRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DeclarationOptions DeclarationRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_declarationProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DeclarationOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 DeclarationRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DeclarationOptions DeclarationRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_definitionProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DefinitionOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DefinitionOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_definitionProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DefinitionOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DefinitionOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_diagnosticProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DiagnosticOptions:\n\t\treturn json.Marshal(x)\n\tcase DiagnosticRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DiagnosticOptions DiagnosticRegistrationOptions]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_diagnosticProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DiagnosticOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 DiagnosticRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DiagnosticOptions DiagnosticRegistrationOptions]\"}\n}\n\nfunc (t Or_ServerCapabilities_documentFormattingProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DocumentFormattingOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DocumentFormattingOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_documentFormattingProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DocumentFormattingOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DocumentFormattingOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_documentHighlightProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DocumentHighlightOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DocumentHighlightOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_documentHighlightProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DocumentHighlightOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DocumentHighlightOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_documentRangeFormattingProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DocumentRangeFormattingOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DocumentRangeFormattingOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_documentRangeFormattingProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DocumentRangeFormattingOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DocumentRangeFormattingOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_documentSymbolProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase DocumentSymbolOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [DocumentSymbolOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_documentSymbolProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 DocumentSymbolOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [DocumentSymbolOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_foldingRangeProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase FoldingRangeOptions:\n\t\treturn json.Marshal(x)\n\tcase FoldingRangeRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [FoldingRangeOptions FoldingRangeRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_foldingRangeProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 FoldingRangeOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 FoldingRangeRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [FoldingRangeOptions FoldingRangeRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_hoverProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase HoverOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [HoverOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_hoverProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 HoverOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [HoverOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_implementationProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase ImplementationOptions:\n\t\treturn json.Marshal(x)\n\tcase ImplementationRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [ImplementationOptions ImplementationRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_implementationProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 ImplementationOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 ImplementationRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [ImplementationOptions ImplementationRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_inlayHintProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InlayHintOptions:\n\t\treturn json.Marshal(x)\n\tcase InlayHintRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InlayHintOptions InlayHintRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_inlayHintProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InlayHintOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 InlayHintRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InlayHintOptions InlayHintRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_inlineCompletionProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InlineCompletionOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InlineCompletionOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_inlineCompletionProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InlineCompletionOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InlineCompletionOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_inlineValueProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase InlineValueOptions:\n\t\treturn json.Marshal(x)\n\tcase InlineValueRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [InlineValueOptions InlineValueRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_inlineValueProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 InlineValueOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 InlineValueRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [InlineValueOptions InlineValueRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_linkedEditingRangeProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase LinkedEditingRangeOptions:\n\t\treturn json.Marshal(x)\n\tcase LinkedEditingRangeRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_linkedEditingRangeProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 LinkedEditingRangeOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 LinkedEditingRangeRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_monikerProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MonikerOptions:\n\t\treturn json.Marshal(x)\n\tcase MonikerRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MonikerOptions MonikerRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_monikerProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MonikerOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 MonikerRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MonikerOptions MonikerRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_notebookDocumentSync) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase NotebookDocumentSyncOptions:\n\t\treturn json.Marshal(x)\n\tcase NotebookDocumentSyncRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_notebookDocumentSync) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 NotebookDocumentSyncOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 NotebookDocumentSyncRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]\"}\n}\n\nfunc (t Or_ServerCapabilities_referencesProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase ReferenceOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [ReferenceOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_referencesProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 ReferenceOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [ReferenceOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_renameProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase RenameOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [RenameOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_renameProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 RenameOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [RenameOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_selectionRangeProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase SelectionRangeOptions:\n\t\treturn json.Marshal(x)\n\tcase SelectionRangeRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [SelectionRangeOptions SelectionRangeRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_selectionRangeProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 SelectionRangeOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 SelectionRangeRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [SelectionRangeOptions SelectionRangeRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_semanticTokensProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase SemanticTokensOptions:\n\t\treturn json.Marshal(x)\n\tcase SemanticTokensRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [SemanticTokensOptions SemanticTokensRegistrationOptions]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_semanticTokensProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 SemanticTokensOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 SemanticTokensRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [SemanticTokensOptions SemanticTokensRegistrationOptions]\"}\n}\n\nfunc (t Or_ServerCapabilities_textDocumentSync) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase TextDocumentSyncKind:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentSyncOptions:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [TextDocumentSyncKind TextDocumentSyncOptions]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_textDocumentSync) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 TextDocumentSyncKind\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TextDocumentSyncOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [TextDocumentSyncKind TextDocumentSyncOptions]\"}\n}\n\nfunc (t Or_ServerCapabilities_typeDefinitionProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase TypeDefinitionOptions:\n\t\treturn json.Marshal(x)\n\tcase TypeDefinitionRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_typeDefinitionProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 TypeDefinitionOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TypeDefinitionRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_typeHierarchyProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase TypeHierarchyOptions:\n\t\treturn json.Marshal(x)\n\tcase TypeHierarchyRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_typeHierarchyProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 TypeHierarchyOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TypeHierarchyRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 bool\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]\"}\n}\n\nfunc (t Or_ServerCapabilities_workspaceSymbolProvider) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase WorkspaceSymbolOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [WorkspaceSymbolOptions bool]\", t)\n}\n\nfunc (t *Or_ServerCapabilities_workspaceSymbolProvider) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 WorkspaceSymbolOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [WorkspaceSymbolOptions bool]\"}\n}\n\nfunc (t Or_SignatureInformation_documentation) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase MarkupContent:\n\t\treturn json.Marshal(x)\n\tcase string:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [MarkupContent string]\", t)\n}\n\nfunc (t *Or_SignatureInformation_documentation) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 MarkupContent\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 string\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [MarkupContent string]\"}\n}\n\nfunc (t Or_TextDocumentEdit_edits_Elem) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase AnnotatedTextEdit:\n\t\treturn json.Marshal(x)\n\tcase SnippetTextEdit:\n\t\treturn json.Marshal(x)\n\tcase TextEdit:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [AnnotatedTextEdit SnippetTextEdit TextEdit]\", t)\n}\n\nfunc (t *Or_TextDocumentEdit_edits_Elem) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 AnnotatedTextEdit\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 SnippetTextEdit\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 TextEdit\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [AnnotatedTextEdit SnippetTextEdit TextEdit]\"}\n}\n\nfunc (t Or_TextDocumentFilter) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase TextDocumentFilterLanguage:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentFilterPattern:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentFilterScheme:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [TextDocumentFilterLanguage TextDocumentFilterPattern TextDocumentFilterScheme]\", t)\n}\n\nfunc (t *Or_TextDocumentFilter) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 TextDocumentFilterLanguage\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TextDocumentFilterPattern\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 TextDocumentFilterScheme\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [TextDocumentFilterLanguage TextDocumentFilterPattern TextDocumentFilterScheme]\"}\n}\n\nfunc (t Or_TextDocumentSyncOptions_save) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase SaveOptions:\n\t\treturn json.Marshal(x)\n\tcase bool:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [SaveOptions bool]\", t)\n}\n\nfunc (t *Or_TextDocumentSyncOptions_save) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 SaveOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 bool\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [SaveOptions bool]\"}\n}\n\nfunc (t Or_WorkspaceDocumentDiagnosticReport) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase WorkspaceFullDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase WorkspaceUnchangedDocumentDiagnosticReport:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]\", t)\n}\n\nfunc (t *Or_WorkspaceDocumentDiagnosticReport) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 WorkspaceFullDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 WorkspaceUnchangedDocumentDiagnosticReport\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]\"}\n}\n\nfunc (t Or_WorkspaceEdit_documentChanges_Elem) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase CreateFile:\n\t\treturn json.Marshal(x)\n\tcase DeleteFile:\n\t\treturn json.Marshal(x)\n\tcase RenameFile:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentEdit:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [CreateFile DeleteFile RenameFile TextDocumentEdit]\", t)\n}\n\nfunc (t *Or_WorkspaceEdit_documentChanges_Elem) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 CreateFile\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 DeleteFile\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\tvar h2 RenameFile\n\tif err := json.Unmarshal(x, &h2); err == nil {\n\t\tt.Value = h2\n\t\treturn nil\n\t}\n\tvar h3 TextDocumentEdit\n\tif err := json.Unmarshal(x, &h3); err == nil {\n\t\tt.Value = h3\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [CreateFile DeleteFile RenameFile TextDocumentEdit]\"}\n}\n\nfunc (t Or_WorkspaceOptions_textDocumentContent) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase TextDocumentContentOptions:\n\t\treturn json.Marshal(x)\n\tcase TextDocumentContentRegistrationOptions:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [TextDocumentContentOptions TextDocumentContentRegistrationOptions]\", t)\n}\n\nfunc (t *Or_WorkspaceOptions_textDocumentContent) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 TextDocumentContentOptions\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 TextDocumentContentRegistrationOptions\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [TextDocumentContentOptions TextDocumentContentRegistrationOptions]\"}\n}\n\nfunc (t Or_textDocument_declaration) MarshalJSON() ([]byte, error) {\n\tswitch x := t.Value.(type) {\n\tcase Declaration:\n\t\treturn json.Marshal(x)\n\tcase []DeclarationLink:\n\t\treturn json.Marshal(x)\n\tcase nil:\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn nil, fmt.Errorf(\"type %T not one of [Declaration []DeclarationLink]\", t)\n}\n\nfunc (t *Or_textDocument_declaration) UnmarshalJSON(x []byte) error {\n\tif string(x) == \"null\" {\n\t\tt.Value = nil\n\t\treturn nil\n\t}\n\tvar h0 Declaration\n\tif err := json.Unmarshal(x, &h0); err == nil {\n\t\tt.Value = h0\n\t\treturn nil\n\t}\n\tvar h1 []DeclarationLink\n\tif err := json.Unmarshal(x, &h1); err == nil {\n\t\tt.Value = h1\n\t\treturn nil\n\t}\n\treturn &UnmarshalError{\"unmarshal failed to match one of [Declaration []DeclarationLink]\"}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/tsprotocol.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated for LSP. DO NOT EDIT.\n\npackage protocol\n\n// Code generated from protocol/metaModel.json at ref release/protocol/3.17.6-next.14 (hash 66a087310eea0d60495ba3578d78f70409c403d9).\n// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.6-next.14/protocol/metaModel.json\n// LSP metaData.version = 3.17.0.\n\nimport \"encoding/json\"\n\n// A special text edit with an additional change annotation.\n//\n// @since 3.16.0.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#annotatedTextEdit\ntype AnnotatedTextEdit struct {\n\t// The actual identifier of the change annotation\n\tAnnotationID *ChangeAnnotationIdentifier `json:\"annotationId,omitempty\"`\n\tTextEdit\n}\n\n// Defines how values from a set of defaults and an individual item will be\n// merged.\n//\n// @since 3.18.0\ntype ApplyKind uint32\n\n// The parameters passed via an apply workspace edit request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#applyWorkspaceEditParams\ntype ApplyWorkspaceEditParams struct {\n\t// An optional label of the workspace edit. This label is\n\t// presented in the user interface for example on an undo\n\t// stack to undo the workspace edit.\n\tLabel string `json:\"label,omitempty\"`\n\t// The edits to apply.\n\tEdit WorkspaceEdit `json:\"edit\"`\n\t// Additional data about the edit.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tMetadata *WorkspaceEditMetadata `json:\"metadata,omitempty\"`\n}\n\n// The result returned from the apply workspace edit request.\n//\n// @since 3.17 renamed from ApplyWorkspaceEditResponse\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#applyWorkspaceEditResult\ntype ApplyWorkspaceEditResult struct {\n\t// Indicates whether the edit was applied or not.\n\tApplied bool `json:\"applied\"`\n\t// An optional textual description for why the edit was not applied.\n\t// This may be used by the server for diagnostic logging or to provide\n\t// a suitable error for a request that triggered the edit.\n\tFailureReason string `json:\"failureReason,omitempty\"`\n\t// Depending on the client's failure handling strategy `failedChange` might\n\t// contain the index of the change that failed. This property is only available\n\t// if the client signals a `failureHandlingStrategy` in its client capabilities.\n\tFailedChange uint32 `json:\"failedChange\"`\n}\n\n// A base for all symbol information.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#baseSymbolInformation\ntype BaseSymbolInformation struct {\n\t// The name of this symbol.\n\tName string `json:\"name\"`\n\t// The kind of this symbol.\n\tKind SymbolKind `json:\"kind\"`\n\t// Tags for this symbol.\n\t//\n\t// @since 3.16.0\n\tTags []SymbolTag `json:\"tags,omitempty\"`\n\t// The name of the symbol containing this symbol. This information is for\n\t// user interface purposes (e.g. to render a qualifier in the user interface\n\t// if necessary). It can't be used to re-infer a hierarchy for the document\n\t// symbols.\n\tContainerName string `json:\"containerName,omitempty\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyClientCapabilities\ntype CallHierarchyClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Represents an incoming call, e.g. a caller of a method or constructor.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyIncomingCall\ntype CallHierarchyIncomingCall struct {\n\t// The item that makes the call.\n\tFrom CallHierarchyItem `json:\"from\"`\n\t// The ranges at which the calls appear. This is relative to the caller\n\t// denoted by {@link CallHierarchyIncomingCall.from `this.from`}.\n\tFromRanges []Range `json:\"fromRanges\"`\n}\n\n// The parameter of a `callHierarchy/incomingCalls` request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyIncomingCallsParams\ntype CallHierarchyIncomingCallsParams struct {\n\tItem CallHierarchyItem `json:\"item\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Represents programming constructs like functions or constructors in the context\n// of call hierarchy.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyItem\ntype CallHierarchyItem struct {\n\t// The name of this item.\n\tName string `json:\"name\"`\n\t// The kind of this item.\n\tKind SymbolKind `json:\"kind\"`\n\t// Tags for this item.\n\tTags []SymbolTag `json:\"tags,omitempty\"`\n\t// More detail for this item, e.g. the signature of a function.\n\tDetail string `json:\"detail,omitempty\"`\n\t// The resource identifier of this item.\n\tURI DocumentURI `json:\"uri\"`\n\t// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.\n\tRange Range `json:\"range\"`\n\t// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.\n\t// Must be contained by the {@link CallHierarchyItem.range `range`}.\n\tSelectionRange Range `json:\"selectionRange\"`\n\t// A data entry field that is preserved between a call hierarchy prepare and\n\t// incoming calls or outgoing calls requests.\n\tData any `json:\"data,omitempty\"`\n}\n\n// Call hierarchy options used during static registration.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyOptions\ntype CallHierarchyOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyOutgoingCall\ntype CallHierarchyOutgoingCall struct {\n\t// The item that is called.\n\tTo CallHierarchyItem `json:\"to\"`\n\t// The range at which this item is called. This is the range relative to the caller, e.g the item\n\t// passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`}\n\t// and not {@link CallHierarchyOutgoingCall.to `this.to`}.\n\tFromRanges []Range `json:\"fromRanges\"`\n}\n\n// The parameter of a `callHierarchy/outgoingCalls` request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyOutgoingCallsParams\ntype CallHierarchyOutgoingCallsParams struct {\n\tItem CallHierarchyItem `json:\"item\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// The parameter of a `textDocument/prepareCallHierarchy` request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyPrepareParams\ntype CallHierarchyPrepareParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Call hierarchy options used during static or dynamic registration.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyRegistrationOptions\ntype CallHierarchyRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tCallHierarchyOptions\n\tStaticRegistrationOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#cancelParams\ntype CancelParams struct {\n\t// The request id to cancel.\n\tID any `json:\"id\"`\n}\n\n// Additional information that describes document changes.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#changeAnnotation\ntype ChangeAnnotation struct {\n\t// A human-readable string describing the actual change. The string\n\t// is rendered prominent in the user interface.\n\tLabel string `json:\"label\"`\n\t// A flag which indicates that user confirmation is needed\n\t// before applying the change.\n\tNeedsConfirmation bool `json:\"needsConfirmation,omitempty\"`\n\t// A human-readable string which is rendered less prominent in\n\t// the user interface.\n\tDescription string `json:\"description,omitempty\"`\n}\n\n// An identifier to refer to a change annotation stored with a workspace edit.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#changeAnnotationIdentifier\ntype ChangeAnnotationIdentifier = string // (alias)\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#changeAnnotationsSupportOptions\ntype ChangeAnnotationsSupportOptions struct {\n\t// Whether the client groups edits with equal labels into tree nodes,\n\t// for instance all edits labelled with \"Changes in Strings\" would\n\t// be a tree node.\n\tGroupsOnLabel bool `json:\"groupsOnLabel,omitempty\"`\n}\n\n// Defines the capabilities provided by the client.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCapabilities\ntype ClientCapabilities struct {\n\t// Workspace specific client capabilities.\n\tWorkspace WorkspaceClientCapabilities `json:\"workspace,omitempty\"`\n\t// Text document specific client capabilities.\n\tTextDocument TextDocumentClientCapabilities `json:\"textDocument,omitempty\"`\n\t// Capabilities specific to the notebook document support.\n\t//\n\t// @since 3.17.0\n\tNotebookDocument *NotebookDocumentClientCapabilities `json:\"notebookDocument,omitempty\"`\n\t// Window specific client capabilities.\n\tWindow WindowClientCapabilities `json:\"window,omitempty\"`\n\t// General client capabilities.\n\t//\n\t// @since 3.16.0\n\tGeneral *GeneralClientCapabilities `json:\"general,omitempty\"`\n\t// Experimental client capabilities.\n\tExperimental any `json:\"experimental,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCodeActionKindOptions\ntype ClientCodeActionKindOptions struct {\n\t// The code action kind values the client supports. When this\n\t// property exists the client also guarantees that it will\n\t// handle values outside its set gracefully and falls back\n\t// to a default value when unknown.\n\tValueSet []CodeActionKind `json:\"valueSet\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCodeActionLiteralOptions\ntype ClientCodeActionLiteralOptions struct {\n\t// The code action kind is support with the following value\n\t// set.\n\tCodeActionKind ClientCodeActionKindOptions `json:\"codeActionKind\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCodeActionResolveOptions\ntype ClientCodeActionResolveOptions struct {\n\t// The properties that a client can resolve lazily.\n\tProperties []string `json:\"properties\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCodeLensResolveOptions\ntype ClientCodeLensResolveOptions struct {\n\t// The properties that a client can resolve lazily.\n\tProperties []string `json:\"properties\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCompletionItemInsertTextModeOptions\ntype ClientCompletionItemInsertTextModeOptions struct {\n\tValueSet []InsertTextMode `json:\"valueSet\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCompletionItemOptions\ntype ClientCompletionItemOptions struct {\n\t// Client supports snippets as insert text.\n\t//\n\t// A snippet can define tab stops and placeholders with `$1`, `$2`\n\t// and `${3:foo}`. `$0` defines the final tab stop, it defaults to\n\t// the end of the snippet. Placeholders with equal identifiers are linked,\n\t// that is typing in one will update others too.\n\tSnippetSupport bool `json:\"snippetSupport,omitempty\"`\n\t// Client supports commit characters on a completion item.\n\tCommitCharactersSupport bool `json:\"commitCharactersSupport,omitempty\"`\n\t// Client supports the following content formats for the documentation\n\t// property. The order describes the preferred format of the client.\n\tDocumentationFormat []MarkupKind `json:\"documentationFormat,omitempty\"`\n\t// Client supports the deprecated property on a completion item.\n\tDeprecatedSupport bool `json:\"deprecatedSupport,omitempty\"`\n\t// Client supports the preselect property on a completion item.\n\tPreselectSupport bool `json:\"preselectSupport,omitempty\"`\n\t// Client supports the tag property on a completion item. Clients supporting\n\t// tags have to handle unknown tags gracefully. Clients especially need to\n\t// preserve unknown tags when sending a completion item back to the server in\n\t// a resolve call.\n\t//\n\t// @since 3.15.0\n\tTagSupport *CompletionItemTagOptions `json:\"tagSupport,omitempty\"`\n\t// Client support insert replace edit to control different behavior if a\n\t// completion item is inserted in the text or should replace text.\n\t//\n\t// @since 3.16.0\n\tInsertReplaceSupport bool `json:\"insertReplaceSupport,omitempty\"`\n\t// Indicates which properties a client can resolve lazily on a completion\n\t// item. Before version 3.16.0 only the predefined properties `documentation`\n\t// and `details` could be resolved lazily.\n\t//\n\t// @since 3.16.0\n\tResolveSupport *ClientCompletionItemResolveOptions `json:\"resolveSupport,omitempty\"`\n\t// The client supports the `insertTextMode` property on\n\t// a completion item to override the whitespace handling mode\n\t// as defined by the client (see `insertTextMode`).\n\t//\n\t// @since 3.16.0\n\tInsertTextModeSupport *ClientCompletionItemInsertTextModeOptions `json:\"insertTextModeSupport,omitempty\"`\n\t// The client has support for completion item label\n\t// details (see also `CompletionItemLabelDetails`).\n\t//\n\t// @since 3.17.0\n\tLabelDetailsSupport bool `json:\"labelDetailsSupport,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCompletionItemOptionsKind\ntype ClientCompletionItemOptionsKind struct {\n\t// The completion item kind values the client supports. When this\n\t// property exists the client also guarantees that it will\n\t// handle values outside its set gracefully and falls back\n\t// to a default value when unknown.\n\t//\n\t// If this property is not present the client only supports\n\t// the completion items kinds from `Text` to `Reference` as defined in\n\t// the initial version of the protocol.\n\tValueSet []CompletionItemKind `json:\"valueSet,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientCompletionItemResolveOptions\ntype ClientCompletionItemResolveOptions struct {\n\t// The properties that a client can resolve lazily.\n\tProperties []string `json:\"properties\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientDiagnosticsTagOptions\ntype ClientDiagnosticsTagOptions struct {\n\t// The tags supported by the client.\n\tValueSet []DiagnosticTag `json:\"valueSet\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientFoldingRangeKindOptions\ntype ClientFoldingRangeKindOptions struct {\n\t// The folding range kind values the client supports. When this\n\t// property exists the client also guarantees that it will\n\t// handle values outside its set gracefully and falls back\n\t// to a default value when unknown.\n\tValueSet []FoldingRangeKind `json:\"valueSet,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientFoldingRangeOptions\ntype ClientFoldingRangeOptions struct {\n\t// If set, the client signals that it supports setting collapsedText on\n\t// folding ranges to display custom labels instead of the default text.\n\t//\n\t// @since 3.17.0\n\tCollapsedText bool `json:\"collapsedText,omitempty\"`\n}\n\n// Information about the client\n//\n// @since 3.15.0\n// @since 3.18.0 ClientInfo type name added.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientInfo\ntype ClientInfo struct {\n\t// The name of the client as defined by the client.\n\tName string `json:\"name\"`\n\t// The client's version as defined by the client.\n\tVersion string `json:\"version,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientInlayHintResolveOptions\ntype ClientInlayHintResolveOptions struct {\n\t// The properties that a client can resolve lazily.\n\tProperties []string `json:\"properties\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSemanticTokensRequestFullDelta\ntype ClientSemanticTokensRequestFullDelta struct {\n\t// The client will send the `textDocument/semanticTokens/full/delta` request if\n\t// the server provides a corresponding handler.\n\tDelta bool `json:\"delta,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSemanticTokensRequestOptions\ntype ClientSemanticTokensRequestOptions struct {\n\t// The client will send the `textDocument/semanticTokens/range` request if\n\t// the server provides a corresponding handler.\n\tRange *Or_ClientSemanticTokensRequestOptions_range `json:\"range,omitempty\"`\n\t// The client will send the `textDocument/semanticTokens/full` request if\n\t// the server provides a corresponding handler.\n\tFull *Or_ClientSemanticTokensRequestOptions_full `json:\"full,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientShowMessageActionItemOptions\ntype ClientShowMessageActionItemOptions struct {\n\t// Whether the client supports additional attributes which\n\t// are preserved and send back to the server in the\n\t// request's response.\n\tAdditionalPropertiesSupport bool `json:\"additionalPropertiesSupport,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSignatureInformationOptions\ntype ClientSignatureInformationOptions struct {\n\t// Client supports the following content formats for the documentation\n\t// property. The order describes the preferred format of the client.\n\tDocumentationFormat []MarkupKind `json:\"documentationFormat,omitempty\"`\n\t// Client capabilities specific to parameter information.\n\tParameterInformation *ClientSignatureParameterInformationOptions `json:\"parameterInformation,omitempty\"`\n\t// The client supports the `activeParameter` property on `SignatureInformation`\n\t// literal.\n\t//\n\t// @since 3.16.0\n\tActiveParameterSupport bool `json:\"activeParameterSupport,omitempty\"`\n\t// The client supports the `activeParameter` property on\n\t// `SignatureHelp`/`SignatureInformation` being set to `null` to\n\t// indicate that no parameter should be active.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tNoActiveParameterSupport bool `json:\"noActiveParameterSupport,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSignatureParameterInformationOptions\ntype ClientSignatureParameterInformationOptions struct {\n\t// The client supports processing label offsets instead of a\n\t// simple label string.\n\t//\n\t// @since 3.14.0\n\tLabelOffsetSupport bool `json:\"labelOffsetSupport,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSymbolKindOptions\ntype ClientSymbolKindOptions struct {\n\t// The symbol kind values the client supports. When this\n\t// property exists the client also guarantees that it will\n\t// handle values outside its set gracefully and falls back\n\t// to a default value when unknown.\n\t//\n\t// If this property is not present the client only supports\n\t// the symbol kinds from `File` to `Array` as defined in\n\t// the initial version of the protocol.\n\tValueSet []SymbolKind `json:\"valueSet,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSymbolResolveOptions\ntype ClientSymbolResolveOptions struct {\n\t// The properties that a client can resolve lazily. Usually\n\t// `location.range`\n\tProperties []string `json:\"properties\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#clientSymbolTagOptions\ntype ClientSymbolTagOptions struct {\n\t// The tags supported by the client.\n\tValueSet []SymbolTag `json:\"valueSet\"`\n}\n\n// A code action represents a change that can be performed in code, e.g. to fix a problem or\n// to refactor code.\n//\n// A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeAction\ntype CodeAction struct {\n\t// A short, human-readable, title for this code action.\n\tTitle string `json:\"title\"`\n\t// The kind of the code action.\n\t//\n\t// Used to filter code actions.\n\tKind CodeActionKind `json:\"kind,omitempty\"`\n\t// The diagnostics that this code action resolves.\n\tDiagnostics []Diagnostic `json:\"diagnostics,omitempty\"`\n\t// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted\n\t// by keybindings.\n\t//\n\t// A quick fix should be marked preferred if it properly addresses the underlying error.\n\t// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.\n\t//\n\t// @since 3.15.0\n\tIsPreferred bool `json:\"isPreferred,omitempty\"`\n\t// Marks that the code action cannot currently be applied.\n\t//\n\t// Clients should follow the following guidelines regarding disabled code actions:\n\t//\n\t//   - Disabled code actions are not shown in automatic [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)\n\t//     code action menus.\n\t//\n\t//   - Disabled actions are shown as faded out in the code action menu when the user requests a more specific type\n\t//     of code action, such as refactorings.\n\t//\n\t//   - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)\n\t//     that auto applies a code action and only disabled code actions are returned, the client should show the user an\n\t//     error message with `reason` in the editor.\n\t//\n\t// @since 3.16.0\n\tDisabled *CodeActionDisabled `json:\"disabled,omitempty\"`\n\t// The workspace edit this code action performs.\n\tEdit *WorkspaceEdit `json:\"edit,omitempty\"`\n\t// A command this code action executes. If a code action\n\t// provides an edit and a command, first the edit is\n\t// executed and then the command.\n\tCommand *Command `json:\"command,omitempty\"`\n\t// A data entry field that is preserved on a code action between\n\t// a `textDocument/codeAction` and a `codeAction/resolve` request.\n\t//\n\t// @since 3.16.0\n\tData *json.RawMessage `json:\"data,omitempty\"`\n\t// Tags for this code action.\n\t//\n\t// @since 3.18.0 - proposed\n\tTags []CodeActionTag `json:\"tags,omitempty\"`\n}\n\n// The Client Capabilities of a {@link CodeActionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionClientCapabilities\ntype CodeActionClientCapabilities struct {\n\t// Whether code action supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client support code action literals of type `CodeAction` as a valid\n\t// response of the `textDocument/codeAction` request. If the property is not\n\t// set the request can only return `Command` literals.\n\t//\n\t// @since 3.8.0\n\tCodeActionLiteralSupport ClientCodeActionLiteralOptions `json:\"codeActionLiteralSupport,omitempty\"`\n\t// Whether code action supports the `isPreferred` property.\n\t//\n\t// @since 3.15.0\n\tIsPreferredSupport bool `json:\"isPreferredSupport,omitempty\"`\n\t// Whether code action supports the `disabled` property.\n\t//\n\t// @since 3.16.0\n\tDisabledSupport bool `json:\"disabledSupport,omitempty\"`\n\t// Whether code action supports the `data` property which is\n\t// preserved between a `textDocument/codeAction` and a\n\t// `codeAction/resolve` request.\n\t//\n\t// @since 3.16.0\n\tDataSupport bool `json:\"dataSupport,omitempty\"`\n\t// Whether the client supports resolving additional code action\n\t// properties via a separate `codeAction/resolve` request.\n\t//\n\t// @since 3.16.0\n\tResolveSupport *ClientCodeActionResolveOptions `json:\"resolveSupport,omitempty\"`\n\t// Whether the client honors the change annotations in\n\t// text edits and resource operations returned via the\n\t// `CodeAction#edit` property by for example presenting\n\t// the workspace edit in the user interface and asking\n\t// for confirmation.\n\t//\n\t// @since 3.16.0\n\tHonorsChangeAnnotations bool `json:\"honorsChangeAnnotations,omitempty\"`\n\t// Whether the client supports documentation for a class of\n\t// code actions.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tDocumentationSupport bool `json:\"documentationSupport,omitempty\"`\n\t// Client supports the tag property on a code action. Clients\n\t// supporting tags have to handle unknown tags gracefully.\n\t//\n\t// @since 3.18.0 - proposed\n\tTagSupport *CodeActionTagOptions `json:\"tagSupport,omitempty\"`\n}\n\n// Contains additional diagnostic information about the context in which\n// a {@link CodeActionProvider.provideCodeActions code action} is run.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionContext\ntype CodeActionContext struct {\n\t// An array of diagnostics known on the client side overlapping the range provided to the\n\t// `textDocument/codeAction` request. They are provided so that the server knows which\n\t// errors are currently presented to the user for the given range. There is no guarantee\n\t// that these accurately reflect the error state of the resource. The primary parameter\n\t// to compute code actions is the provided range.\n\tDiagnostics []Diagnostic `json:\"diagnostics\"`\n\t// Requested kind of actions to return.\n\t//\n\t// Actions not of this kind are filtered out by the client before being shown. So servers\n\t// can omit computing them.\n\tOnly []CodeActionKind `json:\"only,omitempty\"`\n\t// The reason why code actions were requested.\n\t//\n\t// @since 3.17.0\n\tTriggerKind *CodeActionTriggerKind `json:\"triggerKind,omitempty\"`\n}\n\n// Captures why the code action is currently disabled.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionDisabled\ntype CodeActionDisabled struct {\n\t// Human readable description of why the code action is currently disabled.\n\t//\n\t// This is displayed in the code actions UI.\n\tReason string `json:\"reason\"`\n}\n\n// A set of predefined code action kinds\ntype CodeActionKind string\n\n// Documentation for a class of code actions.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionKindDocumentation\ntype CodeActionKindDocumentation struct {\n\t// The kind of the code action being documented.\n\t//\n\t// If the kind is generic, such as `CodeActionKind.Refactor`, the documentation will be shown whenever any\n\t// refactorings are returned. If the kind if more specific, such as `CodeActionKind.RefactorExtract`, the\n\t// documentation will only be shown when extract refactoring code actions are returned.\n\tKind CodeActionKind `json:\"kind\"`\n\t// Command that is ued to display the documentation to the user.\n\t//\n\t// The title of this documentation code action is taken from {@linkcode Command.title}\n\tCommand Command `json:\"command\"`\n}\n\n// Provider options for a {@link CodeActionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionOptions\ntype CodeActionOptions struct {\n\t// CodeActionKinds that this server may return.\n\t//\n\t// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server\n\t// may list out every specific kind they provide.\n\tCodeActionKinds []CodeActionKind `json:\"codeActionKinds,omitempty\"`\n\t// Static documentation for a class of code actions.\n\t//\n\t// Documentation from the provider should be shown in the code actions menu if either:\n\t//\n\t//\n\t//  - Code actions of `kind` are requested by the editor. In this case, the editor will show the documentation that\n\t//   most closely matches the requested code action kind. For example, if a provider has documentation for\n\t//   both `Refactor` and `RefactorExtract`, when the user requests code actions for `RefactorExtract`,\n\t//   the editor will use the documentation for `RefactorExtract` instead of the documentation for `Refactor`.\n\t//\n\t//\n\t//  - Any code actions of `kind` are returned by the provider.\n\t//\n\t// At most one documentation entry should be shown per provider.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tDocumentation []CodeActionKindDocumentation `json:\"documentation,omitempty\"`\n\t// The server provides support to resolve additional\n\t// information for a code action.\n\t//\n\t// @since 3.16.0\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link CodeActionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionParams\ntype CodeActionParams struct {\n\t// The document in which the command was invoked.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The range for which the command was invoked.\n\tRange Range `json:\"range\"`\n\t// Context carrying additional information.\n\tContext CodeActionContext `json:\"context\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link CodeActionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionRegistrationOptions\ntype CodeActionRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tCodeActionOptions\n}\n\n// Code action tags are extra annotations that tweak the behavior of a code action.\n//\n// @since 3.18.0 - proposed\ntype CodeActionTag uint32\n\n// @since 3.18.0 - proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeActionTagOptions\ntype CodeActionTagOptions struct {\n\t// The tags supported by the client.\n\tValueSet []CodeActionTag `json:\"valueSet\"`\n}\n\n// The reason why code actions were requested.\n//\n// @since 3.17.0\ntype CodeActionTriggerKind uint32\n\n// Structure to capture a description for an error code.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeDescription\ntype CodeDescription struct {\n\t// An URI to open with more information about the diagnostic error.\n\tHref URI `json:\"href\"`\n}\n\n// A code lens represents a {@link Command command} that should be shown along with\n// source text, like the number of references, a way to run tests, etc.\n//\n// A code lens is _unresolved_ when no command is associated to it. For performance\n// reasons the creation of a code lens and resolving should be done in two stages.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLens\ntype CodeLens struct {\n\t// The range in which this code lens is valid. Should only span a single line.\n\tRange Range `json:\"range\"`\n\t// The command this code lens represents.\n\tCommand *Command `json:\"command,omitempty\"`\n\t// A data entry field that is preserved on a code lens item between\n\t// a {@link CodeLensRequest} and a {@link CodeLensResolveRequest}\n\tData any `json:\"data,omitempty\"`\n}\n\n// The client capabilities  of a {@link CodeLensRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLensClientCapabilities\ntype CodeLensClientCapabilities struct {\n\t// Whether code lens supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Whether the client supports resolving additional code lens\n\t// properties via a separate `codeLens/resolve` request.\n\t//\n\t// @since 3.18.0\n\tResolveSupport *ClientCodeLensResolveOptions `json:\"resolveSupport,omitempty\"`\n}\n\n// Code Lens provider options of a {@link CodeLensRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLensOptions\ntype CodeLensOptions struct {\n\t// Code lens has a resolve provider as well.\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link CodeLensRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLensParams\ntype CodeLensParams struct {\n\t// The document to request code lens for.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link CodeLensRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLensRegistrationOptions\ntype CodeLensRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tCodeLensOptions\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLensWorkspaceClientCapabilities\ntype CodeLensWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from the\n\t// server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// code lenses currently shown. It should be used with absolute care and is\n\t// useful for situation where a server for example detect a project wide\n\t// change that requires such a calculation.\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// Represents a color in RGBA space.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#color\ntype Color struct {\n\t// The red component of this color in the range [0-1].\n\tRed float64 `json:\"red\"`\n\t// The green component of this color in the range [0-1].\n\tGreen float64 `json:\"green\"`\n\t// The blue component of this color in the range [0-1].\n\tBlue float64 `json:\"blue\"`\n\t// The alpha component of this color in the range [0-1].\n\tAlpha float64 `json:\"alpha\"`\n}\n\n// Represents a color range from a document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#colorInformation\ntype ColorInformation struct {\n\t// The range in the document where this color appears.\n\tRange Range `json:\"range\"`\n\t// The actual color value for this color range.\n\tColor Color `json:\"color\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#colorPresentation\ntype ColorPresentation struct {\n\t// The label of this color presentation. It will be shown on the color\n\t// picker header. By default this is also the text that is inserted when selecting\n\t// this color presentation.\n\tLabel string `json:\"label\"`\n\t// An {@link TextEdit edit} which is applied to a document when selecting\n\t// this presentation for the color.  When `falsy` the {@link ColorPresentation.label label}\n\t// is used.\n\tTextEdit *TextEdit `json:\"textEdit,omitempty\"`\n\t// An optional array of additional {@link TextEdit text edits} that are applied when\n\t// selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves.\n\tAdditionalTextEdits []TextEdit `json:\"additionalTextEdits,omitempty\"`\n}\n\n// Parameters for a {@link ColorPresentationRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#colorPresentationParams\ntype ColorPresentationParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The color to request presentations for.\n\tColor Color `json:\"color\"`\n\t// The range where the color would be inserted. Serves as a context.\n\tRange Range `json:\"range\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Represents a reference to a command. Provides a title which\n// will be used to represent a command in the UI and, optionally,\n// an array of arguments which will be passed to the command handler\n// function when invoked.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#command\ntype Command struct {\n\t// Title of the command, like `save`.\n\tTitle string `json:\"title\"`\n\t// An optional tooltip.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tTooltip string `json:\"tooltip,omitempty\"`\n\t// The identifier of the actual command handler.\n\tCommand string `json:\"command\"`\n\t// Arguments that the command handler should be\n\t// invoked with.\n\tArguments []json.RawMessage `json:\"arguments,omitempty\"`\n}\n\n// Completion client capabilities\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionClientCapabilities\ntype CompletionClientCapabilities struct {\n\t// Whether completion supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports the following `CompletionItem` specific\n\t// capabilities.\n\tCompletionItem     ClientCompletionItemOptions      `json:\"completionItem,omitempty\"`\n\tCompletionItemKind *ClientCompletionItemOptionsKind `json:\"completionItemKind,omitempty\"`\n\t// Defines how the client handles whitespace and indentation\n\t// when accepting a completion item that uses multi line\n\t// text in either `insertText` or `textEdit`.\n\t//\n\t// @since 3.17.0\n\tInsertTextMode InsertTextMode `json:\"insertTextMode,omitempty\"`\n\t// The client supports to send additional context information for a\n\t// `textDocument/completion` request.\n\tContextSupport bool `json:\"contextSupport,omitempty\"`\n\t// The client supports the following `CompletionList` specific\n\t// capabilities.\n\t//\n\t// @since 3.17.0\n\tCompletionList *CompletionListCapabilities `json:\"completionList,omitempty\"`\n}\n\n// Contains additional information about the context in which a completion request is triggered.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionContext\ntype CompletionContext struct {\n\t// How the completion was triggered.\n\tTriggerKind CompletionTriggerKind `json:\"triggerKind\"`\n\t// The trigger character (a single character) that has trigger code complete.\n\t// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`\n\tTriggerCharacter string `json:\"triggerCharacter,omitempty\"`\n}\n\n// A completion item represents a text snippet that is\n// proposed to complete text that is being typed.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItem\ntype CompletionItem struct {\n\t// The label of this completion item.\n\t//\n\t// The label property is also by default the text that\n\t// is inserted when selecting this completion.\n\t//\n\t// If label details are provided the label itself should\n\t// be an unqualified name of the completion item.\n\tLabel string `json:\"label\"`\n\t// Additional details for the label\n\t//\n\t// @since 3.17.0\n\tLabelDetails *CompletionItemLabelDetails `json:\"labelDetails,omitempty\"`\n\t// The kind of this completion item. Based of the kind\n\t// an icon is chosen by the editor.\n\tKind CompletionItemKind `json:\"kind,omitempty\"`\n\t// Tags for this completion item.\n\t//\n\t// @since 3.15.0\n\tTags []CompletionItemTag `json:\"tags,omitempty\"`\n\t// A human-readable string with additional information\n\t// about this item, like type or symbol information.\n\tDetail string `json:\"detail,omitempty\"`\n\t// A human-readable string that represents a doc-comment.\n\tDocumentation *Or_CompletionItem_documentation `json:\"documentation,omitempty\"`\n\t// Indicates if this item is deprecated.\n\t// @deprecated Use `tags` instead.\n\tDeprecated bool `json:\"deprecated,omitempty\"`\n\t// Select this item when showing.\n\t//\n\t// *Note* that only one completion item can be selected and that the\n\t// tool / client decides which item that is. The rule is that the *first*\n\t// item of those that match best is selected.\n\tPreselect bool `json:\"preselect,omitempty\"`\n\t// A string that should be used when comparing this item\n\t// with other items. When `falsy` the {@link CompletionItem.label label}\n\t// is used.\n\tSortText string `json:\"sortText,omitempty\"`\n\t// A string that should be used when filtering a set of\n\t// completion items. When `falsy` the {@link CompletionItem.label label}\n\t// is used.\n\tFilterText string `json:\"filterText,omitempty\"`\n\t// A string that should be inserted into a document when selecting\n\t// this completion. When `falsy` the {@link CompletionItem.label label}\n\t// is used.\n\t//\n\t// The `insertText` is subject to interpretation by the client side.\n\t// Some tools might not take the string literally. For example\n\t// VS Code when code complete is requested in this example\n\t// `con<cursor position>` and a completion item with an `insertText` of\n\t// `console` is provided it will only insert `sole`. Therefore it is\n\t// recommended to use `textEdit` instead since it avoids additional client\n\t// side interpretation.\n\tInsertText string `json:\"insertText,omitempty\"`\n\t// The format of the insert text. The format applies to both the\n\t// `insertText` property and the `newText` property of a provided\n\t// `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.\n\t//\n\t// Please note that the insertTextFormat doesn't apply to\n\t// `additionalTextEdits`.\n\tInsertTextFormat *InsertTextFormat `json:\"insertTextFormat,omitempty\"`\n\t// How whitespace and indentation is handled during completion\n\t// item insertion. If not provided the clients default value depends on\n\t// the `textDocument.completion.insertTextMode` client capability.\n\t//\n\t// @since 3.16.0\n\tInsertTextMode *InsertTextMode `json:\"insertTextMode,omitempty\"`\n\t// An {@link TextEdit edit} which is applied to a document when selecting\n\t// this completion. When an edit is provided the value of\n\t// {@link CompletionItem.insertText insertText} is ignored.\n\t//\n\t// Most editors support two different operations when accepting a completion\n\t// item. One is to insert a completion text and the other is to replace an\n\t// existing text with a completion text. Since this can usually not be\n\t// predetermined by a server it can report both ranges. Clients need to\n\t// signal support for `InsertReplaceEdits` via the\n\t// `textDocument.completion.insertReplaceSupport` client capability\n\t// property.\n\t//\n\t// *Note 1:* The text edit's range as well as both ranges from an insert\n\t// replace edit must be a [single line] and they must contain the position\n\t// at which completion has been requested.\n\t// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range\n\t// must be a prefix of the edit's replace range, that means it must be\n\t// contained and starting at the same position.\n\t//\n\t// @since 3.16.0 additional type `InsertReplaceEdit`\n\tTextEdit *Or_CompletionItem_textEdit `json:\"textEdit,omitempty\"`\n\t// The edit text used if the completion item is part of a CompletionList and\n\t// CompletionList defines an item default for the text edit range.\n\t//\n\t// Clients will only honor this property if they opt into completion list\n\t// item defaults using the capability `completionList.itemDefaults`.\n\t//\n\t// If not provided and a list's default range is provided the label\n\t// property is used as a text.\n\t//\n\t// @since 3.17.0\n\tTextEditText string `json:\"textEditText,omitempty\"`\n\t// An optional array of additional {@link TextEdit text edits} that are applied when\n\t// selecting this completion. Edits must not overlap (including the same insert position)\n\t// with the main {@link CompletionItem.textEdit edit} nor with themselves.\n\t//\n\t// Additional text edits should be used to change text unrelated to the current cursor position\n\t// (for example adding an import statement at the top of the file if the completion item will\n\t// insert an unqualified type).\n\tAdditionalTextEdits []TextEdit `json:\"additionalTextEdits,omitempty\"`\n\t// An optional set of characters that when pressed while this completion is active will accept it first and\n\t// then type that character. *Note* that all commit characters should have `length=1` and that superfluous\n\t// characters will be ignored.\n\tCommitCharacters []string `json:\"commitCharacters,omitempty\"`\n\t// An optional {@link Command command} that is executed *after* inserting this completion. *Note* that\n\t// additional modifications to the current document should be described with the\n\t// {@link CompletionItem.additionalTextEdits additionalTextEdits}-property.\n\tCommand *Command `json:\"command,omitempty\"`\n\t// A data entry field that is preserved on a completion item between a\n\t// {@link CompletionRequest} and a {@link CompletionResolveRequest}.\n\tData any `json:\"data,omitempty\"`\n}\n\n// Specifies how fields from a completion item should be combined with those\n// from `completionList.itemDefaults`.\n//\n// If unspecified, all fields will be treated as ApplyKind.Replace.\n//\n// If a field's value is ApplyKind.Replace, the value from a completion item (if\n// provided and not `null`) will always be used instead of the value from\n// `completionItem.itemDefaults`.\n//\n// If a field's value is ApplyKind.Merge, the values will be merged using the rules\n// defined against each field below.\n//\n// Servers are only allowed to return `applyKind` if the client\n// signals support for this via the `completionList.applyKindSupport`\n// capability.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItemApplyKinds\ntype CompletionItemApplyKinds struct {\n\t// Specifies whether commitCharacters on a completion will replace or be\n\t// merged with those in `completionList.itemDefaults.commitCharacters`.\n\t//\n\t// If ApplyKind.Replace, the commit characters from the completion item will\n\t// always be used unless not provided, in which case those from\n\t// `completionList.itemDefaults.commitCharacters` will be used. An\n\t// empty list can be used if a completion item does not have any commit\n\t// characters and also should not use those from\n\t// `completionList.itemDefaults.commitCharacters`.\n\t//\n\t// If ApplyKind.Merge the commitCharacters for the completion will be the\n\t// union of all values in both `completionList.itemDefaults.commitCharacters`\n\t// and the completion's own `commitCharacters`.\n\t//\n\t// @since 3.18.0\n\tCommitCharacters *ApplyKind `json:\"commitCharacters,omitempty\"`\n\t// Specifies whether the `data` field on a completion will replace or\n\t// be merged with data from `completionList.itemDefaults.data`.\n\t//\n\t// If ApplyKind.Replace, the data from the completion item will be used if\n\t// provided (and not `null`), otherwise\n\t// `completionList.itemDefaults.data` will be used. An empty object can\n\t// be used if a completion item does not have any data but also should\n\t// not use the value from `completionList.itemDefaults.data`.\n\t//\n\t// If ApplyKind.Merge, a shallow merge will be performed between\n\t// `completionList.itemDefaults.data` and the completion's own data\n\t// using the following rules:\n\t//\n\t//\n\t//  - If a completion's `data` field is not provided (or `null`), the\n\t//   entire `data` field from `completionList.itemDefaults.data` will be\n\t//   used as-is.\n\t//  - If a completion's `data` field is provided, each field will\n\t//   overwrite the field of the same name in\n\t//   `completionList.itemDefaults.data` but no merging of nested fields\n\t//   within that value will occur.\n\t//\n\t// @since 3.18.0\n\tData *ApplyKind `json:\"data,omitempty\"`\n}\n\n// In many cases the items of an actual completion result share the same\n// value for properties like `commitCharacters` or the range of a text\n// edit. A completion list can therefore define item defaults which will\n// be used if a completion item itself doesn't specify the value.\n//\n// If a completion list specifies a default value and a completion item\n// also specifies a corresponding value, the rules for combining these are\n// defined by `applyKinds` (if the client supports it), defaulting to\n// ApplyKind.Replace.\n//\n// Servers are only allowed to return default values if the client\n// signals support for this via the `completionList.itemDefaults`\n// capability.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItemDefaults\ntype CompletionItemDefaults struct {\n\t// A default commit character set.\n\t//\n\t// @since 3.17.0\n\tCommitCharacters []string `json:\"commitCharacters,omitempty\"`\n\t// A default edit range.\n\t//\n\t// @since 3.17.0\n\tEditRange *Or_CompletionItemDefaults_editRange `json:\"editRange,omitempty\"`\n\t// A default insert text format.\n\t//\n\t// @since 3.17.0\n\tInsertTextFormat *InsertTextFormat `json:\"insertTextFormat,omitempty\"`\n\t// A default insert text mode.\n\t//\n\t// @since 3.17.0\n\tInsertTextMode *InsertTextMode `json:\"insertTextMode,omitempty\"`\n\t// A default data value.\n\t//\n\t// @since 3.17.0\n\tData any `json:\"data,omitempty\"`\n}\n\n// The kind of a completion entry.\ntype CompletionItemKind uint32\n\n// Additional details for a completion item label.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItemLabelDetails\ntype CompletionItemLabelDetails struct {\n\t// An optional string which is rendered less prominently directly after {@link CompletionItem.label label},\n\t// without any spacing. Should be used for function signatures and type annotations.\n\tDetail string `json:\"detail,omitempty\"`\n\t// An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used\n\t// for fully qualified names and file paths.\n\tDescription string `json:\"description,omitempty\"`\n}\n\n// Completion item tags are extra annotations that tweak the rendering of a completion\n// item.\n//\n// @since 3.15.0\ntype CompletionItemTag uint32\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItemTagOptions\ntype CompletionItemTagOptions struct {\n\t// The tags supported by the client.\n\tValueSet []CompletionItemTag `json:\"valueSet\"`\n}\n\n// Represents a collection of {@link CompletionItem completion items} to be presented\n// in the editor.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionList\ntype CompletionList struct {\n\t// This list it not complete. Further typing results in recomputing this list.\n\t//\n\t// Recomputed lists have all their items replaced (not appended) in the\n\t// incomplete completion sessions.\n\tIsIncomplete bool `json:\"isIncomplete\"`\n\t// In many cases the items of an actual completion result share the same\n\t// value for properties like `commitCharacters` or the range of a text\n\t// edit. A completion list can therefore define item defaults which will\n\t// be used if a completion item itself doesn't specify the value.\n\t//\n\t// If a completion list specifies a default value and a completion item\n\t// also specifies a corresponding value, the rules for combining these are\n\t// defined by `applyKinds` (if the client supports it), defaulting to\n\t// ApplyKind.Replace.\n\t//\n\t// Servers are only allowed to return default values if the client\n\t// signals support for this via the `completionList.itemDefaults`\n\t// capability.\n\t//\n\t// @since 3.17.0\n\tItemDefaults *CompletionItemDefaults `json:\"itemDefaults,omitempty\"`\n\t// Specifies how fields from a completion item should be combined with those\n\t// from `completionList.itemDefaults`.\n\t//\n\t// If unspecified, all fields will be treated as ApplyKind.Replace.\n\t//\n\t// If a field's value is ApplyKind.Replace, the value from a completion item\n\t// (if provided and not `null`) will always be used instead of the value\n\t// from `completionItem.itemDefaults`.\n\t//\n\t// If a field's value is ApplyKind.Merge, the values will be merged using\n\t// the rules defined against each field below.\n\t//\n\t// Servers are only allowed to return `applyKind` if the client\n\t// signals support for this via the `completionList.applyKindSupport`\n\t// capability.\n\t//\n\t// @since 3.18.0\n\tApplyKind *CompletionItemApplyKinds `json:\"applyKind,omitempty\"`\n\t// The completion items.\n\tItems []CompletionItem `json:\"items\"`\n}\n\n// The client supports the following `CompletionList` specific\n// capabilities.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionListCapabilities\ntype CompletionListCapabilities struct {\n\t// The client supports the following itemDefaults on\n\t// a completion list.\n\t//\n\t// The value lists the supported property names of the\n\t// `CompletionList.itemDefaults` object. If omitted\n\t// no properties are supported.\n\t//\n\t// @since 3.17.0\n\tItemDefaults []string `json:\"itemDefaults,omitempty\"`\n\t// Specifies whether the client supports `CompletionList.applyKind` to\n\t// indicate how supported values from `completionList.itemDefaults`\n\t// and `completion` will be combined.\n\t//\n\t// If a client supports `applyKind` it must support it for all fields\n\t// that it supports that are listed in `CompletionList.applyKind`. This\n\t// means when clients add support for new/future fields in completion\n\t// items the MUST also support merge for them if those fields are\n\t// defined in `CompletionList.applyKind`.\n\t//\n\t// @since 3.18.0\n\tApplyKindSupport bool `json:\"applyKindSupport,omitempty\"`\n}\n\n// Completion options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionOptions\ntype CompletionOptions struct {\n\t// Most tools trigger completion request automatically without explicitly requesting\n\t// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user\n\t// starts to type an identifier. For example if the user types `c` in a JavaScript file\n\t// code complete will automatically pop up present `console` besides others as a\n\t// completion item. Characters that make up identifiers don't need to be listed here.\n\t//\n\t// If code complete should automatically be trigger on characters not being valid inside\n\t// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.\n\tTriggerCharacters []string `json:\"triggerCharacters,omitempty\"`\n\t// The list of all possible characters that commit a completion. This field can be used\n\t// if clients don't support individual commit characters per completion item. See\n\t// `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`\n\t//\n\t// If a server provides both `allCommitCharacters` and commit characters on an individual\n\t// completion item the ones on the completion item win.\n\t//\n\t// @since 3.2.0\n\tAllCommitCharacters []string `json:\"allCommitCharacters,omitempty\"`\n\t// The server provides support to resolve additional\n\t// information for a completion item.\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\t// The server supports the following `CompletionItem` specific\n\t// capabilities.\n\t//\n\t// @since 3.17.0\n\tCompletionItem *ServerCompletionItemOptions `json:\"completionItem,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// Completion parameters\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionParams\ntype CompletionParams struct {\n\t// The completion context. This is only available it the client specifies\n\t// to send this using the client capability `textDocument.completion.contextSupport === true`\n\tContext CompletionContext `json:\"context,omitempty\"`\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link CompletionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionRegistrationOptions\ntype CompletionRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tCompletionOptions\n}\n\n// How a completion was triggered\ntype CompletionTriggerKind uint32\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#configurationItem\ntype ConfigurationItem struct {\n\t// The scope to get the configuration section for.\n\tScopeURI *URI `json:\"scopeUri,omitempty\"`\n\t// The configuration section asked for.\n\tSection string `json:\"section,omitempty\"`\n}\n\n// The parameters of a configuration request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#configurationParams\ntype ConfigurationParams struct {\n\tItems []ConfigurationItem `json:\"items\"`\n}\n\n// Create file operation.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#createFile\ntype CreateFile struct {\n\t// A create\n\tKind string `json:\"kind\"`\n\t// The resource to create.\n\tURI DocumentURI `json:\"uri\"`\n\t// Additional options\n\tOptions *CreateFileOptions `json:\"options,omitempty\"`\n\tResourceOperation\n}\n\n// Options to create a file.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#createFileOptions\ntype CreateFileOptions struct {\n\t// Overwrite existing file. Overwrite wins over `ignoreIfExists`\n\tOverwrite bool `json:\"overwrite,omitempty\"`\n\t// Ignore if exists.\n\tIgnoreIfExists bool `json:\"ignoreIfExists,omitempty\"`\n}\n\n// The parameters sent in notifications/requests for user-initiated creation of\n// files.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#createFilesParams\ntype CreateFilesParams struct {\n\t// An array of all files/folders created in this operation.\n\tFiles []FileCreate `json:\"files\"`\n}\n\n// The declaration of a symbol representation as one or many {@link Location locations}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declaration\ntype Declaration = []Location // (alias)\n// @since 3.14.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declarationClientCapabilities\ntype DeclarationClientCapabilities struct {\n\t// Whether declaration supports dynamic registration. If this is set to `true`\n\t// the client supports the new `DeclarationRegistrationOptions` return value\n\t// for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports additional metadata in the form of declaration links.\n\tLinkSupport bool `json:\"linkSupport,omitempty\"`\n}\n\n// Information about where a symbol is declared.\n//\n// Provides additional metadata over normal {@link Location location} declarations, including the range of\n// the declaring symbol.\n//\n// Servers should prefer returning `DeclarationLink` over `Declaration` if supported\n// by the client.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declarationLink\ntype DeclarationLink = LocationLink // (alias)\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declarationOptions\ntype DeclarationOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declarationParams\ntype DeclarationParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#declarationRegistrationOptions\ntype DeclarationRegistrationOptions struct {\n\tDeclarationOptions\n\tTextDocumentRegistrationOptions\n\tStaticRegistrationOptions\n}\n\n// The definition of a symbol represented as one or many {@link Location locations}.\n// For most programming languages there is only one location at which a symbol is\n// defined.\n//\n// Servers should prefer returning `DefinitionLink` over `Definition` if supported\n// by the client.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definition\ntype Definition = Or_Definition // (alias)\n// Client Capabilities for a {@link DefinitionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definitionClientCapabilities\ntype DefinitionClientCapabilities struct {\n\t// Whether definition supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports additional metadata in the form of definition links.\n\t//\n\t// @since 3.14.0\n\tLinkSupport bool `json:\"linkSupport,omitempty\"`\n}\n\n// Information about where a symbol is defined.\n//\n// Provides additional metadata over normal {@link Location location} definitions, including the range of\n// the defining symbol\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definitionLink\ntype DefinitionLink = LocationLink // (alias)\n// Server Capabilities for a {@link DefinitionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definitionOptions\ntype DefinitionOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link DefinitionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definitionParams\ntype DefinitionParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link DefinitionRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#definitionRegistrationOptions\ntype DefinitionRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDefinitionOptions\n}\n\n// Delete file operation\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#deleteFile\ntype DeleteFile struct {\n\t// A delete\n\tKind string `json:\"kind\"`\n\t// The file to delete.\n\tURI DocumentURI `json:\"uri\"`\n\t// Delete options.\n\tOptions *DeleteFileOptions `json:\"options,omitempty\"`\n\tResourceOperation\n}\n\n// Delete file options\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#deleteFileOptions\ntype DeleteFileOptions struct {\n\t// Delete the content recursively if a folder is denoted.\n\tRecursive bool `json:\"recursive,omitempty\"`\n\t// Ignore the operation if the file doesn't exist.\n\tIgnoreIfNotExists bool `json:\"ignoreIfNotExists,omitempty\"`\n}\n\n// The parameters sent in notifications/requests for user-initiated deletes of\n// files.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#deleteFilesParams\ntype DeleteFilesParams struct {\n\t// An array of all files/folders deleted in this operation.\n\tFiles []FileDelete `json:\"files\"`\n}\n\n// Represents a diagnostic, such as a compiler error or warning. Diagnostic objects\n// are only valid in the scope of a resource.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnostic\ntype Diagnostic struct {\n\t// The range at which the message applies\n\tRange Range `json:\"range\"`\n\t// The diagnostic's severity. To avoid interpretation mismatches when a\n\t// server is used with different clients it is highly recommended that servers\n\t// always provide a severity value.\n\tSeverity DiagnosticSeverity `json:\"severity,omitempty\"`\n\t// The diagnostic's code, which usually appear in the user interface.\n\tCode any `json:\"code,omitempty\"`\n\t// An optional property to describe the error code.\n\t// Requires the code field (above) to be present/not null.\n\t//\n\t// @since 3.16.0\n\tCodeDescription *CodeDescription `json:\"codeDescription,omitempty\"`\n\t// A human-readable string describing the source of this\n\t// diagnostic, e.g. 'typescript' or 'super lint'. It usually\n\t// appears in the user interface.\n\tSource string `json:\"source,omitempty\"`\n\t// The diagnostic's message. It usually appears in the user interface\n\tMessage string `json:\"message\"`\n\t// Additional metadata about the diagnostic.\n\t//\n\t// @since 3.15.0\n\tTags []DiagnosticTag `json:\"tags,omitempty\"`\n\t// An array of related diagnostic information, e.g. when symbol-names within\n\t// a scope collide all definitions can be marked via this property.\n\tRelatedInformation []DiagnosticRelatedInformation `json:\"relatedInformation,omitempty\"`\n\t// A data entry field that is preserved between a `textDocument/publishDiagnostics`\n\t// notification and `textDocument/codeAction` request.\n\t//\n\t// @since 3.16.0\n\tData *json.RawMessage `json:\"data,omitempty\"`\n}\n\n// Client capabilities specific to diagnostic pull requests.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticClientCapabilities\ntype DiagnosticClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Whether the clients supports related documents for document diagnostic pulls.\n\tRelatedDocumentSupport bool `json:\"relatedDocumentSupport,omitempty\"`\n\tDiagnosticsCapabilities\n}\n\n// Diagnostic options.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticOptions\ntype DiagnosticOptions struct {\n\t// An optional identifier under which the diagnostics are\n\t// managed by the client.\n\tIdentifier string `json:\"identifier,omitempty\"`\n\t// Whether the language has inter file dependencies meaning that\n\t// editing code in one file can result in a different diagnostic\n\t// set in another file. Inter file dependencies are common for\n\t// most programming languages and typically uncommon for linters.\n\tInterFileDependencies bool `json:\"interFileDependencies\"`\n\t// The server provides support for workspace diagnostics as well.\n\tWorkspaceDiagnostics bool `json:\"workspaceDiagnostics\"`\n\tWorkDoneProgressOptions\n}\n\n// Diagnostic registration options.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticRegistrationOptions\ntype DiagnosticRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDiagnosticOptions\n\tStaticRegistrationOptions\n}\n\n// Represents a related message and source code location for a diagnostic. This should be\n// used to point to code locations that cause or related to a diagnostics, e.g when duplicating\n// a symbol in a scope.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticRelatedInformation\ntype DiagnosticRelatedInformation struct {\n\t// The location of this related diagnostic information.\n\tLocation Location `json:\"location\"`\n\t// The message of this related diagnostic information.\n\tMessage string `json:\"message\"`\n}\n\n// Cancellation data returned from a diagnostic request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticServerCancellationData\ntype DiagnosticServerCancellationData struct {\n\tRetriggerRequest bool `json:\"retriggerRequest\"`\n}\n\n// The diagnostic's severity.\ntype DiagnosticSeverity uint32\n\n// The diagnostic tags.\n//\n// @since 3.15.0\ntype DiagnosticTag uint32\n\n// Workspace client capabilities specific to diagnostic pull requests.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticWorkspaceClientCapabilities\ntype DiagnosticWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from\n\t// the server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// pulled diagnostics currently shown. It should be used with absolute care and\n\t// is useful for situation where a server for example detects a project wide\n\t// change that requires such a calculation.\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// General diagnostics capabilities for pull and push model.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#diagnosticsCapabilities\ntype DiagnosticsCapabilities struct {\n\t// Whether the clients accepts diagnostics with related information.\n\tRelatedInformation bool `json:\"relatedInformation,omitempty\"`\n\t// Client supports the tag property to provide meta data about a diagnostic.\n\t// Clients supporting tags have to handle unknown tags gracefully.\n\t//\n\t// @since 3.15.0\n\tTagSupport *ClientDiagnosticsTagOptions `json:\"tagSupport,omitempty\"`\n\t// Client supports a codeDescription property\n\t//\n\t// @since 3.16.0\n\tCodeDescriptionSupport bool `json:\"codeDescriptionSupport,omitempty\"`\n\t// Whether code action supports the `data` property which is\n\t// preserved between a `textDocument/publishDiagnostics` and\n\t// `textDocument/codeAction` request.\n\t//\n\t// @since 3.16.0\n\tDataSupport bool `json:\"dataSupport,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeConfigurationClientCapabilities\ntype DidChangeConfigurationClientCapabilities struct {\n\t// Did change configuration notification supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// The parameters of a change configuration notification.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeConfigurationParams\ntype DidChangeConfigurationParams struct {\n\t// The actual changed settings\n\tSettings any `json:\"settings\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeConfigurationRegistrationOptions\ntype DidChangeConfigurationRegistrationOptions struct {\n\tSection *OrPSection_workspace_didChangeConfiguration `json:\"section,omitempty\"`\n}\n\n// The params sent in a change notebook document notification.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeNotebookDocumentParams\ntype DidChangeNotebookDocumentParams struct {\n\t// The notebook document that did change. The version number points\n\t// to the version after all provided changes have been applied. If\n\t// only the text document content of a cell changes the notebook version\n\t// doesn't necessarily have to change.\n\tNotebookDocument VersionedNotebookDocumentIdentifier `json:\"notebookDocument\"`\n\t// The actual changes to the notebook document.\n\t//\n\t// The changes describe single state changes to the notebook document.\n\t// So if there are two changes c1 (at array index 0) and c2 (at array\n\t// index 1) for a notebook in state S then c1 moves the notebook from\n\t// S to S' and c2 from S' to S''. So c1 is computed on the state S and\n\t// c2 is computed on the state S'.\n\t//\n\t// To mirror the content of a notebook using change events use the following approach:\n\t//\n\t//  - start with the same initial content\n\t//  - apply the 'notebookDocument/didChange' notifications in the order you receive them.\n\t//  - apply the `NotebookChangeEvent`s in a single notification in the order\n\t//   you receive them.\n\tChange NotebookDocumentChangeEvent `json:\"change\"`\n}\n\n// The change text document notification's parameters.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeTextDocumentParams\ntype DidChangeTextDocumentParams struct {\n\t// The document that did change. The version number points\n\t// to the version after all provided content changes have\n\t// been applied.\n\tTextDocument VersionedTextDocumentIdentifier `json:\"textDocument\"`\n\t// The actual content changes. The content changes describe single state changes\n\t// to the document. So if there are two content changes c1 (at array index 0) and\n\t// c2 (at array index 1) for a document in state S then c1 moves the document from\n\t// S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed\n\t// on the state S'.\n\t//\n\t// To mirror the content of a document using change events use the following approach:\n\t//\n\t//  - start with the same initial content\n\t//  - apply the 'textDocument/didChange' notifications in the order you receive them.\n\t//  - apply the `TextDocumentContentChangeEvent`s in a single notification in the order\n\t//   you receive them.\n\tContentChanges []TextDocumentContentChangeEvent `json:\"contentChanges\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeWatchedFilesClientCapabilities\ntype DidChangeWatchedFilesClientCapabilities struct {\n\t// Did change watched files notification supports dynamic registration. Please note\n\t// that the current protocol doesn't support static configuration for file changes\n\t// from the server side.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Whether the client has support for {@link  RelativePattern relative pattern}\n\t// or not.\n\t//\n\t// @since 3.17.0\n\tRelativePatternSupport bool `json:\"relativePatternSupport,omitempty\"`\n}\n\n// The watched files change notification's parameters.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeWatchedFilesParams\ntype DidChangeWatchedFilesParams struct {\n\t// The actual file events.\n\tChanges []FileEvent `json:\"changes\"`\n}\n\n// Describe options to be used when registered for text document change events.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeWatchedFilesRegistrationOptions\ntype DidChangeWatchedFilesRegistrationOptions struct {\n\t// The watchers to register.\n\tWatchers []FileSystemWatcher `json:\"watchers\"`\n}\n\n// The parameters of a `workspace/didChangeWorkspaceFolders` notification.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didChangeWorkspaceFoldersParams\ntype DidChangeWorkspaceFoldersParams struct {\n\t// The actual workspace folder change event.\n\tEvent WorkspaceFoldersChangeEvent `json:\"event\"`\n}\n\n// The params sent in a close notebook document notification.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didCloseNotebookDocumentParams\ntype DidCloseNotebookDocumentParams struct {\n\t// The notebook document that got closed.\n\tNotebookDocument NotebookDocumentIdentifier `json:\"notebookDocument\"`\n\t// The text documents that represent the content\n\t// of a notebook cell that got closed.\n\tCellTextDocuments []TextDocumentIdentifier `json:\"cellTextDocuments\"`\n}\n\n// The parameters sent in a close text document notification\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didCloseTextDocumentParams\ntype DidCloseTextDocumentParams struct {\n\t// The document that was closed.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n}\n\n// The params sent in an open notebook document notification.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didOpenNotebookDocumentParams\ntype DidOpenNotebookDocumentParams struct {\n\t// The notebook document that got opened.\n\tNotebookDocument NotebookDocument `json:\"notebookDocument\"`\n\t// The text documents that represent the content\n\t// of a notebook cell.\n\tCellTextDocuments []TextDocumentItem `json:\"cellTextDocuments\"`\n}\n\n// The parameters sent in an open text document notification\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didOpenTextDocumentParams\ntype DidOpenTextDocumentParams struct {\n\t// The document that was opened.\n\tTextDocument TextDocumentItem `json:\"textDocument\"`\n}\n\n// The params sent in a save notebook document notification.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didSaveNotebookDocumentParams\ntype DidSaveNotebookDocumentParams struct {\n\t// The notebook document that got saved.\n\tNotebookDocument NotebookDocumentIdentifier `json:\"notebookDocument\"`\n}\n\n// The parameters sent in a save text document notification\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#didSaveTextDocumentParams\ntype DidSaveTextDocumentParams struct {\n\t// The document that was saved.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// Optional the content when saved. Depends on the includeText value\n\t// when the save notification was requested.\n\tText *string `json:\"text,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentColorClientCapabilities\ntype DocumentColorClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `DocumentColorRegistrationOptions` return value\n\t// for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentColorOptions\ntype DocumentColorOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link DocumentColorRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentColorParams\ntype DocumentColorParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentColorRegistrationOptions\ntype DocumentColorRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentColorOptions\n\tStaticRegistrationOptions\n}\n\n// Parameters of the document diagnostic request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentDiagnosticParams\ntype DocumentDiagnosticParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The additional identifier  provided during registration.\n\tIdentifier string `json:\"identifier,omitempty\"`\n\t// The result id of a previous response if provided.\n\tPreviousResultID string `json:\"previousResultId,omitempty\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// The result of a document diagnostic pull request. A report can\n// either be a full report containing all diagnostics for the\n// requested document or an unchanged report indicating that nothing\n// has changed in terms of diagnostics in comparison to the last\n// pull request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentDiagnosticReport\ntype DocumentDiagnosticReport = Or_DocumentDiagnosticReport // (alias)\n// The document diagnostic report kinds.\n//\n// @since 3.17.0\ntype DocumentDiagnosticReportKind string\n\n// A partial result for a document diagnostic report.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentDiagnosticReportPartialResult\ntype DocumentDiagnosticReportPartialResult struct {\n\tRelatedDocuments map[DocumentURI]any `json:\"relatedDocuments\"`\n}\n\n// A document filter describes a top level text document or\n// a notebook cell document.\n//\n// @since 3.17.0 - support for NotebookCellTextDocumentFilter.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentFilter\ntype DocumentFilter = Or_DocumentFilter // (alias)\n// Client capabilities of a {@link DocumentFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentFormattingClientCapabilities\ntype DocumentFormattingClientCapabilities struct {\n\t// Whether formatting supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Provider options for a {@link DocumentFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentFormattingOptions\ntype DocumentFormattingOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link DocumentFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentFormattingParams\ntype DocumentFormattingParams struct {\n\t// The document to format.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The format options.\n\tOptions FormattingOptions `json:\"options\"`\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link DocumentFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentFormattingRegistrationOptions\ntype DocumentFormattingRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentFormattingOptions\n}\n\n// A document highlight is a range inside a text document which deserves\n// special attention. Usually a document highlight is visualized by changing\n// the background color of its range.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentHighlight\ntype DocumentHighlight struct {\n\t// The range this highlight applies to.\n\tRange Range `json:\"range\"`\n\t// The highlight kind, default is {@link DocumentHighlightKind.Text text}.\n\tKind DocumentHighlightKind `json:\"kind,omitempty\"`\n}\n\n// Client Capabilities for a {@link DocumentHighlightRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentHighlightClientCapabilities\ntype DocumentHighlightClientCapabilities struct {\n\t// Whether document highlight supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// A document highlight kind.\ntype DocumentHighlightKind uint32\n\n// Provider options for a {@link DocumentHighlightRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentHighlightOptions\ntype DocumentHighlightOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link DocumentHighlightRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentHighlightParams\ntype DocumentHighlightParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link DocumentHighlightRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentHighlightRegistrationOptions\ntype DocumentHighlightRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentHighlightOptions\n}\n\n// A document link is a range in a text document that links to an internal or external resource, like another\n// text document or a web site.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLink\ntype DocumentLink struct {\n\t// The range this link applies to.\n\tRange Range `json:\"range\"`\n\t// The uri this link points to. If missing a resolve request is sent later.\n\tTarget *URI `json:\"target,omitempty\"`\n\t// The tooltip text when you hover over this link.\n\t//\n\t// If a tooltip is provided, is will be displayed in a string that includes instructions on how to\n\t// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS,\n\t// user settings, and localization.\n\t//\n\t// @since 3.15.0\n\tTooltip string `json:\"tooltip,omitempty\"`\n\t// A data entry field that is preserved on a document link between a\n\t// DocumentLinkRequest and a DocumentLinkResolveRequest.\n\tData any `json:\"data,omitempty\"`\n}\n\n// The client capabilities of a {@link DocumentLinkRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLinkClientCapabilities\ntype DocumentLinkClientCapabilities struct {\n\t// Whether document link supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Whether the client supports the `tooltip` property on `DocumentLink`.\n\t//\n\t// @since 3.15.0\n\tTooltipSupport bool `json:\"tooltipSupport,omitempty\"`\n}\n\n// Provider options for a {@link DocumentLinkRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLinkOptions\ntype DocumentLinkOptions struct {\n\t// Document links have a resolve provider as well.\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link DocumentLinkRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLinkParams\ntype DocumentLinkParams struct {\n\t// The document to provide document links for.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link DocumentLinkRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLinkRegistrationOptions\ntype DocumentLinkRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentLinkOptions\n}\n\n// Client capabilities of a {@link DocumentOnTypeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentOnTypeFormattingClientCapabilities\ntype DocumentOnTypeFormattingClientCapabilities struct {\n\t// Whether on type formatting supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Provider options for a {@link DocumentOnTypeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentOnTypeFormattingOptions\ntype DocumentOnTypeFormattingOptions struct {\n\t// A character on which formatting should be triggered, like `{`.\n\tFirstTriggerCharacter string `json:\"firstTriggerCharacter\"`\n\t// More trigger characters.\n\tMoreTriggerCharacter []string `json:\"moreTriggerCharacter,omitempty\"`\n}\n\n// The parameters of a {@link DocumentOnTypeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentOnTypeFormattingParams\ntype DocumentOnTypeFormattingParams struct {\n\t// The document to format.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The position around which the on type formatting should happen.\n\t// This is not necessarily the exact position where the character denoted\n\t// by the property `ch` got typed.\n\tPosition Position `json:\"position\"`\n\t// The character that has been typed that triggered the formatting\n\t// on type request. That is not necessarily the last character that\n\t// got inserted into the document since the client could auto insert\n\t// characters as well (e.g. like automatic brace completion).\n\tCh string `json:\"ch\"`\n\t// The formatting options.\n\tOptions FormattingOptions `json:\"options\"`\n}\n\n// Registration options for a {@link DocumentOnTypeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentOnTypeFormattingRegistrationOptions\ntype DocumentOnTypeFormattingRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentOnTypeFormattingOptions\n}\n\n// Client capabilities of a {@link DocumentRangeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentRangeFormattingClientCapabilities\ntype DocumentRangeFormattingClientCapabilities struct {\n\t// Whether range formatting supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Whether the client supports formatting multiple ranges at once.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tRangesSupport bool `json:\"rangesSupport,omitempty\"`\n}\n\n// Provider options for a {@link DocumentRangeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentRangeFormattingOptions\ntype DocumentRangeFormattingOptions struct {\n\t// Whether the server supports formatting multiple ranges at once.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tRangesSupport bool `json:\"rangesSupport,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link DocumentRangeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentRangeFormattingParams\ntype DocumentRangeFormattingParams struct {\n\t// The document to format.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The range to format\n\tRange Range `json:\"range\"`\n\t// The format options\n\tOptions FormattingOptions `json:\"options\"`\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link DocumentRangeFormattingRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentRangeFormattingRegistrationOptions\ntype DocumentRangeFormattingRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentRangeFormattingOptions\n}\n\n// The parameters of a {@link DocumentRangesFormattingRequest}.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentRangesFormattingParams\ntype DocumentRangesFormattingParams struct {\n\t// The document to format.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The ranges to format\n\tRanges []Range `json:\"ranges\"`\n\t// The format options\n\tOptions FormattingOptions `json:\"options\"`\n\tWorkDoneProgressParams\n}\n\n// A document selector is the combination of one or many document filters.\n//\n// @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`;\n//\n// The use of a string as a document filter is deprecated @since 3.16.0.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSelector\ntype DocumentSelector = []DocumentFilter // (alias)\n// Represents programming constructs like variables, classes, interfaces etc.\n// that appear in a document. Document symbols can be hierarchical and they\n// have two ranges: one that encloses its definition and one that points to\n// its most interesting range, e.g. the range of an identifier.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbol\ntype DocumentSymbol struct {\n\t// The name of this symbol. Will be displayed in the user interface and therefore must not be\n\t// an empty string or a string only consisting of white spaces.\n\tName string `json:\"name\"`\n\t// More detail for this symbol, e.g the signature of a function.\n\tDetail string `json:\"detail,omitempty\"`\n\t// The kind of this symbol.\n\tKind SymbolKind `json:\"kind\"`\n\t// Tags for this document symbol.\n\t//\n\t// @since 3.16.0\n\tTags []SymbolTag `json:\"tags,omitempty\"`\n\t// Indicates if this symbol is deprecated.\n\t//\n\t// @deprecated Use tags instead\n\tDeprecated bool `json:\"deprecated,omitempty\"`\n\t// The range enclosing this symbol not including leading/trailing whitespace but everything else\n\t// like comments. This information is typically used to determine if the clients cursor is\n\t// inside the symbol to reveal in the symbol in the UI.\n\tRange Range `json:\"range\"`\n\t// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.\n\t// Must be contained by the `range`.\n\tSelectionRange Range `json:\"selectionRange\"`\n\t// Children of this symbol, e.g. properties of a class.\n\tChildren []DocumentSymbol `json:\"children,omitempty\"`\n}\n\n// Client Capabilities for a {@link DocumentSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolClientCapabilities\ntype DocumentSymbolClientCapabilities struct {\n\t// Whether document symbol supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Specific capabilities for the `SymbolKind` in the\n\t// `textDocument/documentSymbol` request.\n\tSymbolKind *ClientSymbolKindOptions `json:\"symbolKind,omitempty\"`\n\t// The client supports hierarchical document symbols.\n\tHierarchicalDocumentSymbolSupport bool `json:\"hierarchicalDocumentSymbolSupport,omitempty\"`\n\t// The client supports tags on `SymbolInformation`. Tags are supported on\n\t// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.\n\t// Clients supporting tags have to handle unknown tags gracefully.\n\t//\n\t// @since 3.16.0\n\tTagSupport *ClientSymbolTagOptions `json:\"tagSupport,omitempty\"`\n\t// The client supports an additional label presented in the UI when\n\t// registering a document symbol provider.\n\t//\n\t// @since 3.16.0\n\tLabelSupport bool `json:\"labelSupport,omitempty\"`\n}\n\n// Provider options for a {@link DocumentSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolOptions\ntype DocumentSymbolOptions struct {\n\t// A human-readable string that is shown when multiple outlines trees\n\t// are shown for the same document.\n\t//\n\t// @since 3.16.0\n\tLabel string `json:\"label,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link DocumentSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolParams\ntype DocumentSymbolParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link DocumentSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolRegistrationOptions\ntype DocumentSymbolRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tDocumentSymbolOptions\n}\n\n// Edit range variant that includes ranges for insert and replace operations.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#editRangeWithInsertReplace\ntype EditRangeWithInsertReplace struct {\n\tInsert  Range `json:\"insert\"`\n\tReplace Range `json:\"replace\"`\n}\n\n// Predefined error codes.\ntype ErrorCodes int32\n\n// The client capabilities of a {@link ExecuteCommandRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#executeCommandClientCapabilities\ntype ExecuteCommandClientCapabilities struct {\n\t// Execute command supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// The server capabilities of a {@link ExecuteCommandRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#executeCommandOptions\ntype ExecuteCommandOptions struct {\n\t// The commands to be executed on the server\n\tCommands []string `json:\"commands\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link ExecuteCommandRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#executeCommandParams\ntype ExecuteCommandParams struct {\n\t// The identifier of the actual command handler.\n\tCommand string `json:\"command\"`\n\t// Arguments that the command should be invoked with.\n\tArguments []json.RawMessage `json:\"arguments,omitempty\"`\n\n\t// Support interactive command execution.\n\t//\n\t// Note: This is a non-standard protocol extension. See golang/go#76331.\n\tInteractiveParams\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link ExecuteCommandRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#executeCommandRegistrationOptions\ntype ExecuteCommandRegistrationOptions struct {\n\tExecuteCommandOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#executionSummary\ntype ExecutionSummary struct {\n\t// A strict monotonically increasing value\n\t// indicating the execution order of a cell\n\t// inside a notebook.\n\tExecutionOrder uint32 `json:\"executionOrder\"`\n\t// Whether the execution was successful or\n\t// not if known by the client.\n\tSuccess bool `json:\"success,omitempty\"`\n}\ntype FailureHandlingKind string\n\n// The file event type\ntype FileChangeType uint32\n\n// Represents information on a file/folder create.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileCreate\ntype FileCreate struct {\n\t// A file:// URI for the location of the file/folder being created.\n\tURI string `json:\"uri\"`\n}\n\n// Represents information on a file/folder delete.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileDelete\ntype FileDelete struct {\n\t// A file:// URI for the location of the file/folder being deleted.\n\tURI string `json:\"uri\"`\n}\n\n// An event describing a file change.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileEvent\ntype FileEvent struct {\n\t// The file's uri.\n\tURI DocumentURI `json:\"uri\"`\n\t// The change type.\n\tType FileChangeType `json:\"type\"`\n}\n\n// Capabilities relating to events from file operations by the user in the client.\n//\n// These events do not come from the file system, they come from user operations\n// like renaming a file in the UI.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationClientCapabilities\ntype FileOperationClientCapabilities struct {\n\t// Whether the client supports dynamic registration for file requests/notifications.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client has support for sending didCreateFiles notifications.\n\tDidCreate bool `json:\"didCreate,omitempty\"`\n\t// The client has support for sending willCreateFiles requests.\n\tWillCreate bool `json:\"willCreate,omitempty\"`\n\t// The client has support for sending didRenameFiles notifications.\n\tDidRename bool `json:\"didRename,omitempty\"`\n\t// The client has support for sending willRenameFiles requests.\n\tWillRename bool `json:\"willRename,omitempty\"`\n\t// The client has support for sending didDeleteFiles notifications.\n\tDidDelete bool `json:\"didDelete,omitempty\"`\n\t// The client has support for sending willDeleteFiles requests.\n\tWillDelete bool `json:\"willDelete,omitempty\"`\n}\n\n// A filter to describe in which file operation requests or notifications\n// the server is interested in receiving.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationFilter\ntype FileOperationFilter struct {\n\t// A Uri scheme like `file` or `untitled`.\n\tScheme string `json:\"scheme,omitempty\"`\n\t// The actual file operation pattern.\n\tPattern FileOperationPattern `json:\"pattern\"`\n}\n\n// Options for notifications/requests for user operations on files.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationOptions\ntype FileOperationOptions struct {\n\t// The server is interested in receiving didCreateFiles notifications.\n\tDidCreate *FileOperationRegistrationOptions `json:\"didCreate,omitempty\"`\n\t// The server is interested in receiving willCreateFiles requests.\n\tWillCreate *FileOperationRegistrationOptions `json:\"willCreate,omitempty\"`\n\t// The server is interested in receiving didRenameFiles notifications.\n\tDidRename *FileOperationRegistrationOptions `json:\"didRename,omitempty\"`\n\t// The server is interested in receiving willRenameFiles requests.\n\tWillRename *FileOperationRegistrationOptions `json:\"willRename,omitempty\"`\n\t// The server is interested in receiving didDeleteFiles file notifications.\n\tDidDelete *FileOperationRegistrationOptions `json:\"didDelete,omitempty\"`\n\t// The server is interested in receiving willDeleteFiles file requests.\n\tWillDelete *FileOperationRegistrationOptions `json:\"willDelete,omitempty\"`\n}\n\n// A pattern to describe in which file operation requests or notifications\n// the server is interested in receiving.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationPattern\ntype FileOperationPattern struct {\n\t// The glob pattern to match. Glob patterns can have the following syntax:\n\t//\n\t//  - `*` to match one or more characters in a path segment\n\t//  - `?` to match on one character in a path segment\n\t//  - `**` to match any number of path segments, including none\n\t//  - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)\n\t//  - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n\t//  - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)\n\tGlob string `json:\"glob\"`\n\t// Whether to match files or folders with this pattern.\n\t//\n\t// Matches both if undefined.\n\tMatches *FileOperationPatternKind `json:\"matches,omitempty\"`\n\t// Additional options used during matching.\n\tOptions *FileOperationPatternOptions `json:\"options,omitempty\"`\n}\n\n// A pattern kind describing if a glob pattern matches a file a folder or\n// both.\n//\n// @since 3.16.0\ntype FileOperationPatternKind string\n\n// Matching options for the file operation pattern.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationPatternOptions\ntype FileOperationPatternOptions struct {\n\t// The pattern should be matched ignoring casing.\n\tIgnoreCase bool `json:\"ignoreCase,omitempty\"`\n}\n\n// The options to register for file operations.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileOperationRegistrationOptions\ntype FileOperationRegistrationOptions struct {\n\t// The actual filters.\n\tFilters []FileOperationFilter `json:\"filters\"`\n}\n\n// Represents information on a file/folder rename.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileRename\ntype FileRename struct {\n\t// A file:// URI for the original location of the file/folder being renamed.\n\tOldURI string `json:\"oldUri\"`\n\t// A file:// URI for the new location of the file/folder being renamed.\n\tNewURI string `json:\"newUri\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fileSystemWatcher\ntype FileSystemWatcher struct {\n\t// The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail.\n\t//\n\t// @since 3.17.0 support for relative patterns.\n\tGlobPattern GlobPattern `json:\"globPattern\"`\n\t// The kind of events of interest. If omitted it defaults\n\t// to WatchKind.Create | WatchKind.Change | WatchKind.Delete\n\t// which is 7.\n\tKind *WatchKind `json:\"kind,omitempty\"`\n}\n\n// Represents a folding range. To be valid, start and end line must be bigger than zero and smaller\n// than the number of lines in the document. Clients are free to ignore invalid ranges.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRange\ntype FoldingRange struct {\n\t// The zero-based start line of the range to fold. The folded area starts after the line's last character.\n\t// To be valid, the end must be zero or larger and smaller than the number of lines in the document.\n\tStartLine *uint32 `json:\"startLine,omitempty\"`\n\t// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.\n\tStartCharacter *uint32 `json:\"startCharacter,omitempty\"`\n\t// The zero-based end line of the range to fold. The folded area ends with the line's last character.\n\t// To be valid, the end must be zero or larger and smaller than the number of lines in the document.\n\tEndLine *uint32 `json:\"endLine,omitempty\"`\n\t// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.\n\tEndCharacter *uint32 `json:\"endCharacter,omitempty\"`\n\t// Describes the kind of the folding range such as 'comment' or 'region'. The kind\n\t// is used to categorize folding ranges and used by commands like 'Fold all comments'.\n\t// See {@link FoldingRangeKind} for an enumeration of standardized kinds.\n\tKind string `json:\"kind,omitempty\"`\n\t// The text that the client should show when the specified range is\n\t// collapsed. If not defined or not supported by the client, a default\n\t// will be chosen by the client.\n\t//\n\t// @since 3.17.0\n\tCollapsedText string `json:\"collapsedText,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRangeClientCapabilities\ntype FoldingRangeClientCapabilities struct {\n\t// Whether implementation supports dynamic registration for folding range\n\t// providers. If this is set to `true` the client supports the new\n\t// `FoldingRangeRegistrationOptions` return value for the corresponding\n\t// server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The maximum number of folding ranges that the client prefers to receive\n\t// per document. The value serves as a hint, servers are free to follow the\n\t// limit.\n\tRangeLimit uint32 `json:\"rangeLimit\"`\n\t// If set, the client signals that it only supports folding complete lines.\n\t// If set, client will ignore specified `startCharacter` and `endCharacter`\n\t// properties in a FoldingRange.\n\tLineFoldingOnly bool `json:\"lineFoldingOnly,omitempty\"`\n\t// Specific options for the folding range kind.\n\t//\n\t// @since 3.17.0\n\tFoldingRangeKind *ClientFoldingRangeKindOptions `json:\"foldingRangeKind,omitempty\"`\n\t// Specific options for the folding range.\n\t//\n\t// @since 3.17.0\n\tFoldingRange *ClientFoldingRangeOptions `json:\"foldingRange,omitempty\"`\n}\n\n// A set of predefined range kinds.\ntype FoldingRangeKind string\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRangeOptions\ntype FoldingRangeOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link FoldingRangeRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRangeParams\ntype FoldingRangeParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRangeRegistrationOptions\ntype FoldingRangeRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tFoldingRangeOptions\n\tStaticRegistrationOptions\n}\n\n// Client workspace capabilities specific to folding ranges\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#foldingRangeWorkspaceClientCapabilities\ntype FoldingRangeWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from the\n\t// server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// folding ranges currently shown. It should be used with absolute care and is\n\t// useful for situation where a server for example detects a project wide\n\t// change that requires such a calculation.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// Value-object describing what options formatting should use.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#formattingOptions\ntype FormattingOptions struct {\n\t// Size of a tab in spaces.\n\tTabSize uint32 `json:\"tabSize\"`\n\t// Prefer spaces over tabs.\n\tInsertSpaces bool `json:\"insertSpaces\"`\n\t// Trim trailing whitespace on a line.\n\t//\n\t// @since 3.15.0\n\tTrimTrailingWhitespace bool `json:\"trimTrailingWhitespace,omitempty\"`\n\t// Insert a newline character at the end of the file if one does not exist.\n\t//\n\t// @since 3.15.0\n\tInsertFinalNewline bool `json:\"insertFinalNewline,omitempty\"`\n\t// Trim all newlines after the final newline at the end of the file.\n\t//\n\t// @since 3.15.0\n\tTrimFinalNewlines bool `json:\"trimFinalNewlines,omitempty\"`\n}\n\n// A diagnostic report with a full set of problems.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#fullDocumentDiagnosticReport\ntype FullDocumentDiagnosticReport struct {\n\t// A full document diagnostic report.\n\tKind string `json:\"kind\"`\n\t// An optional result id. If provided it will\n\t// be sent on the next diagnostic request for the\n\t// same document.\n\tResultID string `json:\"resultId,omitempty\"`\n\t// The actual items.\n\tItems []Diagnostic `json:\"items\"`\n}\n\n// General client capabilities.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#generalClientCapabilities\ntype GeneralClientCapabilities struct {\n\t// Client capability that signals how the client\n\t// handles stale requests (e.g. a request\n\t// for which the client will not process the response\n\t// anymore since the information is outdated).\n\t//\n\t// @since 3.17.0\n\tStaleRequestSupport *StaleRequestSupportOptions `json:\"staleRequestSupport,omitempty\"`\n\t// Client capabilities specific to regular expressions.\n\t//\n\t// @since 3.16.0\n\tRegularExpressions *RegularExpressionsClientCapabilities `json:\"regularExpressions,omitempty\"`\n\t// Client capabilities specific to the client's markdown parser.\n\t//\n\t// @since 3.16.0\n\tMarkdown *MarkdownClientCapabilities `json:\"markdown,omitempty\"`\n\t// The position encodings supported by the client. Client and server\n\t// have to agree on the same position encoding to ensure that offsets\n\t// (e.g. character position in a line) are interpreted the same on both\n\t// sides.\n\t//\n\t// To keep the protocol backwards compatible the following applies: if\n\t// the value 'utf-16' is missing from the array of position encodings\n\t// servers can assume that the client supports UTF-16. UTF-16 is\n\t// therefore a mandatory encoding.\n\t//\n\t// If omitted it defaults to ['utf-16'].\n\t//\n\t// Implementation considerations: since the conversion from one encoding\n\t// into another requires the content of the file / line the conversion\n\t// is best done where the file is read which is usually on the server\n\t// side.\n\t//\n\t// @since 3.17.0\n\tPositionEncodings []PositionEncodingKind `json:\"positionEncodings,omitempty\"`\n}\n\n// The glob pattern. Either a string pattern or a relative pattern.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#globPattern\ntype GlobPattern = Or_GlobPattern // (alias)\n// The result of a hover request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#hover\ntype Hover struct {\n\t// The hover's content\n\tContents MarkupContent `json:\"contents\"`\n\t// An optional range inside the text document that is used to\n\t// visualize the hover, e.g. by changing the background color.\n\tRange Range `json:\"range,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#hoverClientCapabilities\ntype HoverClientCapabilities struct {\n\t// Whether hover supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Client supports the following content formats for the content\n\t// property. The order describes the preferred format of the client.\n\tContentFormat []MarkupKind `json:\"contentFormat,omitempty\"`\n}\n\n// Hover options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#hoverOptions\ntype HoverOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link HoverRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#hoverParams\ntype HoverParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link HoverRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#hoverRegistrationOptions\ntype HoverRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tHoverOptions\n}\n\n// @since 3.6.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#implementationClientCapabilities\ntype ImplementationClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `ImplementationRegistrationOptions` return value\n\t// for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports additional metadata in the form of definition links.\n\t//\n\t// @since 3.14.0\n\tLinkSupport bool `json:\"linkSupport,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#implementationOptions\ntype ImplementationOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#implementationParams\ntype ImplementationParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#implementationRegistrationOptions\ntype ImplementationRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tImplementationOptions\n\tStaticRegistrationOptions\n}\n\n// The data type of the ResponseError if the\n// initialize request fails.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initializeError\ntype InitializeError struct {\n\t// Indicates whether the client execute the following retry logic:\n\t// (1) show the message provided by the ResponseError to the user\n\t// (2) user selects retry or cancel\n\t// (3) if user selected retry the initialize method is sent again.\n\tRetry bool `json:\"retry\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initializeParams\ntype InitializeParams struct {\n\tXInitializeParams\n\tWorkspaceFoldersInitializeParams\n}\n\n// The result returned from an initialize request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initializeResult\ntype InitializeResult struct {\n\t// The capabilities the language server provides.\n\tCapabilities ServerCapabilities `json:\"capabilities\"`\n\t// Information about the server.\n\t//\n\t// @since 3.15.0\n\tServerInfo *ServerInfo `json:\"serverInfo,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initializedParams\ntype InitializedParams struct {\n}\n\n// Inlay hint information.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHint\ntype InlayHint struct {\n\t// The position of this hint.\n\t//\n\t// If multiple hints have the same position, they will be shown in the order\n\t// they appear in the response.\n\tPosition Position `json:\"position\"`\n\t// The label of this hint. A human readable string or an array of\n\t// InlayHintLabelPart label parts.\n\t//\n\t// *Note* that neither the string nor the label part can be empty.\n\tLabel []InlayHintLabelPart `json:\"label\"`\n\t// The kind of this hint. Can be omitted in which case the client\n\t// should fall back to a reasonable default.\n\tKind InlayHintKind `json:\"kind,omitempty\"`\n\t// Optional text edits that are performed when accepting this inlay hint.\n\t//\n\t// *Note* that edits are expected to change the document so that the inlay\n\t// hint (or its nearest variant) is now part of the document and the inlay\n\t// hint itself is now obsolete.\n\tTextEdits []TextEdit `json:\"textEdits,omitempty\"`\n\t// The tooltip text when you hover over this item.\n\tTooltip *OrPTooltip_textDocument_inlayHint `json:\"tooltip,omitempty\"`\n\t// Render padding before the hint.\n\t//\n\t// Note: Padding should use the editor's background color, not the\n\t// background color of the hint itself. That means padding can be used\n\t// to visually align/separate an inlay hint.\n\tPaddingLeft bool `json:\"paddingLeft,omitempty\"`\n\t// Render padding after the hint.\n\t//\n\t// Note: Padding should use the editor's background color, not the\n\t// background color of the hint itself. That means padding can be used\n\t// to visually align/separate an inlay hint.\n\tPaddingRight bool `json:\"paddingRight,omitempty\"`\n\t// A data entry field that is preserved on an inlay hint between\n\t// a `textDocument/inlayHint` and a `inlayHint/resolve` request.\n\tData any `json:\"data,omitempty\"`\n}\n\n// Inlay hint client capabilities.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintClientCapabilities\ntype InlayHintClientCapabilities struct {\n\t// Whether inlay hints support dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Indicates which properties a client can resolve lazily on an inlay\n\t// hint.\n\tResolveSupport *ClientInlayHintResolveOptions `json:\"resolveSupport,omitempty\"`\n}\n\n// Inlay hint kinds.\n//\n// @since 3.17.0\ntype InlayHintKind uint32\n\n// An inlay hint label part allows for interactive and composite labels\n// of inlay hints.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintLabelPart\ntype InlayHintLabelPart struct {\n\t// The value of this label part.\n\tValue string `json:\"value\"`\n\t// The tooltip text when you hover over this label part. Depending on\n\t// the client capability `inlayHint.resolveSupport` clients might resolve\n\t// this property late using the resolve request.\n\tTooltip *OrPTooltipPLabel `json:\"tooltip,omitempty\"`\n\t// An optional source code location that represents this\n\t// label part.\n\t//\n\t// The editor will use this location for the hover and for code navigation\n\t// features: This part will become a clickable link that resolves to the\n\t// definition of the symbol at the given location (not necessarily the\n\t// location itself), it shows the hover that shows at the given location,\n\t// and it shows a context menu with further code navigation commands.\n\t//\n\t// Depending on the client capability `inlayHint.resolveSupport` clients\n\t// might resolve this property late using the resolve request.\n\tLocation *Location `json:\"location,omitempty\"`\n\t// An optional command for this label part.\n\t//\n\t// Depending on the client capability `inlayHint.resolveSupport` clients\n\t// might resolve this property late using the resolve request.\n\tCommand *Command `json:\"command,omitempty\"`\n}\n\n// Inlay hint options used during static registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintOptions\ntype InlayHintOptions struct {\n\t// The server provides support to resolve additional\n\t// information for an inlay hint item.\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// A parameter literal used in inlay hint requests.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintParams\ntype InlayHintParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The document range for which inlay hints should be computed.\n\tRange Range `json:\"range\"`\n\tWorkDoneProgressParams\n}\n\n// Inlay hint options used during static or dynamic registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintRegistrationOptions\ntype InlayHintRegistrationOptions struct {\n\tInlayHintOptions\n\tTextDocumentRegistrationOptions\n\tStaticRegistrationOptions\n}\n\n// Client workspace capabilities specific to inlay hints.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHintWorkspaceClientCapabilities\ntype InlayHintWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from\n\t// the server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// inlay hints currently shown. It should be used with absolute care and\n\t// is useful for situation where a server for example detects a project wide\n\t// change that requires such a calculation.\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// Client capabilities specific to inline completions.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionClientCapabilities\ntype InlineCompletionClientCapabilities struct {\n\t// Whether implementation supports dynamic registration for inline completion providers.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Provides information about the context in which an inline completion was requested.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionContext\ntype InlineCompletionContext struct {\n\t// Describes how the inline completion was triggered.\n\tTriggerKind InlineCompletionTriggerKind `json:\"triggerKind\"`\n\t// Provides information about the currently selected item in the autocomplete widget if it is visible.\n\tSelectedCompletionInfo *SelectedCompletionInfo `json:\"selectedCompletionInfo,omitempty\"`\n}\n\n// An inline completion item represents a text snippet that is proposed inline to complete text that is being typed.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionItem\ntype InlineCompletionItem struct {\n\t// The text to replace the range with. Must be set.\n\tInsertText Or_InlineCompletionItem_insertText `json:\"insertText\"`\n\t// A text that is used to decide if this inline completion should be shown. When `falsy` the {@link InlineCompletionItem.insertText} is used.\n\tFilterText string `json:\"filterText,omitempty\"`\n\t// The range to replace. Must begin and end on the same line.\n\tRange *Range `json:\"range,omitempty\"`\n\t// An optional {@link Command} that is executed *after* inserting this completion.\n\tCommand *Command `json:\"command,omitempty\"`\n}\n\n// Represents a collection of {@link InlineCompletionItem inline completion items} to be presented in the editor.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionList\ntype InlineCompletionList struct {\n\t// The inline completion items\n\tItems []InlineCompletionItem `json:\"items\"`\n}\n\n// Inline completion options used during static registration.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionOptions\ntype InlineCompletionOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// A parameter literal used in inline completion requests.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionParams\ntype InlineCompletionParams struct {\n\t// Additional information about the context in which inline completions were\n\t// requested.\n\tContext InlineCompletionContext `json:\"context\"`\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Inline completion options used during static or dynamic registration.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineCompletionRegistrationOptions\ntype InlineCompletionRegistrationOptions struct {\n\tInlineCompletionOptions\n\tTextDocumentRegistrationOptions\n\tStaticRegistrationOptions\n}\n\n// Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered.\n//\n// @since 3.18.0\n// @proposed\ntype InlineCompletionTriggerKind uint32\n\n// Inline value information can be provided by different means:\n//\n//   - directly as a text value (class InlineValueText).\n//   - as a name to use for a variable lookup (class InlineValueVariableLookup)\n//   - as an evaluatable expression (class InlineValueEvaluatableExpression)\n//\n// The InlineValue types combines all inline value types into one type.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValue\ntype InlineValue = Or_InlineValue // (alias)\n// Client capabilities specific to inline values.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueClientCapabilities\ntype InlineValueClientCapabilities struct {\n\t// Whether implementation supports dynamic registration for inline value providers.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueContext\ntype InlineValueContext struct {\n\t// The stack frame (as a DAP Id) where the execution has stopped.\n\tFrameID int32 `json:\"frameId\"`\n\t// The document range where execution has stopped.\n\t// Typically the end position of the range denotes the line where the inline values are shown.\n\tStoppedLocation Range `json:\"stoppedLocation\"`\n}\n\n// Provide an inline value through an expression evaluation.\n// If only a range is specified, the expression will be extracted from the underlying document.\n// An optional expression can be used to override the extracted expression.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueEvaluatableExpression\ntype InlineValueEvaluatableExpression struct {\n\t// The document range for which the inline value applies.\n\t// The range is used to extract the evaluatable expression from the underlying document.\n\tRange Range `json:\"range\"`\n\t// If specified the expression overrides the extracted expression.\n\tExpression string `json:\"expression,omitempty\"`\n}\n\n// Inline value options used during static registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueOptions\ntype InlineValueOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// A parameter literal used in inline value requests.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueParams\ntype InlineValueParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The document range for which inline values should be computed.\n\tRange Range `json:\"range\"`\n\t// Additional information about the context in which inline values were\n\t// requested.\n\tContext InlineValueContext `json:\"context\"`\n\tWorkDoneProgressParams\n}\n\n// Inline value options used during static or dynamic registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueRegistrationOptions\ntype InlineValueRegistrationOptions struct {\n\tInlineValueOptions\n\tTextDocumentRegistrationOptions\n\tStaticRegistrationOptions\n}\n\n// Provide inline value as text.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueText\ntype InlineValueText struct {\n\t// The document range for which the inline value applies.\n\tRange Range `json:\"range\"`\n\t// The text of the inline value.\n\tText string `json:\"text\"`\n}\n\n// Provide inline value through a variable lookup.\n// If only a range is specified, the variable name will be extracted from the underlying document.\n// An optional variable name can be used to override the extracted name.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueVariableLookup\ntype InlineValueVariableLookup struct {\n\t// The document range for which the inline value applies.\n\t// The range is used to extract the variable name from the underlying document.\n\tRange Range `json:\"range\"`\n\t// If specified the name of the variable to look up.\n\tVariableName string `json:\"variableName,omitempty\"`\n\t// How to perform the lookup.\n\tCaseSensitiveLookup bool `json:\"caseSensitiveLookup\"`\n}\n\n// Client workspace capabilities specific to inline values.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlineValueWorkspaceClientCapabilities\ntype InlineValueWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from the\n\t// server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// inline values currently shown. It should be used with absolute care and is\n\t// useful for situation where a server for example detects a project wide\n\t// change that requires such a calculation.\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// A special text edit to provide an insert and a replace operation.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#insertReplaceEdit\ntype InsertReplaceEdit struct {\n\t// The string to be inserted.\n\tNewText string `json:\"newText\"`\n\t// The range if the insert is requested\n\tInsert Range `json:\"insert\"`\n\t// The range if the replace is requested.\n\tReplace Range `json:\"replace\"`\n}\n\n// Defines whether the insert text in a completion item should be interpreted as\n// plain text or a snippet.\ntype InsertTextFormat uint32\n\n// How whitespace and indentation is handled during completion\n// item insertion.\n//\n// @since 3.16.0\ntype InsertTextMode uint32\ntype LSPAny = any\n\n// LSP arrays.\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#lSPArray\ntype LSPArray = []any // (alias)\ntype LSPErrorCodes int32\n\n// LSP object definition.\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#lSPObject\ntype LSPObject = map[string]LSPAny // (alias)\n// Predefined Language kinds\n// @since 3.18.0\ntype LanguageKind string\n\n// Client capabilities for the linked editing range request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#linkedEditingRangeClientCapabilities\ntype LinkedEditingRangeClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#linkedEditingRangeOptions\ntype LinkedEditingRangeOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#linkedEditingRangeParams\ntype LinkedEditingRangeParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#linkedEditingRangeRegistrationOptions\ntype LinkedEditingRangeRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tLinkedEditingRangeOptions\n\tStaticRegistrationOptions\n}\n\n// The result of a linked editing range request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#linkedEditingRanges\ntype LinkedEditingRanges struct {\n\t// A list of ranges that can be edited together. The ranges must have\n\t// identical length and contain identical text content. The ranges cannot overlap.\n\tRanges []Range `json:\"ranges\"`\n\t// An optional word pattern (regular expression) that describes valid contents for\n\t// the given ranges. If no pattern is provided, the client configuration's word\n\t// pattern will be used.\n\tWordPattern string `json:\"wordPattern,omitempty\"`\n}\n\n// created for Literal (Lit_ClientSemanticTokensRequestOptions_range_Item1)\ntype Lit_ClientSemanticTokensRequestOptions_range_Item1 struct {\n}\n\n// Represents a location inside a resource, such as a line\n// inside a text file.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#location\ntype Location struct {\n\tURI   DocumentURI `json:\"uri\"`\n\tRange Range       `json:\"range\"`\n}\n\n// Represents the connection of two locations. Provides additional metadata over normal {@link Location locations},\n// including an origin range.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#locationLink\ntype LocationLink struct {\n\t// Span of the origin of this link.\n\t//\n\t// Used as the underlined span for mouse interaction. Defaults to the word range at\n\t// the definition position.\n\tOriginSelectionRange *Range `json:\"originSelectionRange,omitempty\"`\n\t// The target resource identifier of this link.\n\tTargetURI DocumentURI `json:\"targetUri\"`\n\t// The full target range of this link. If the target for example is a symbol then target range is the\n\t// range enclosing this symbol not including leading/trailing whitespace but everything else\n\t// like comments. This information is typically used to highlight the range in the editor.\n\tTargetRange Range `json:\"targetRange\"`\n\t// The range that should be selected and revealed when this link is being followed, e.g the name of a function.\n\t// Must be contained by the `targetRange`. See also `DocumentSymbol#range`\n\tTargetSelectionRange Range `json:\"targetSelectionRange\"`\n}\n\n// Location with only uri and does not include range.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#locationUriOnly\ntype LocationUriOnly struct {\n\tURI DocumentURI `json:\"uri\"`\n}\n\n// The log message parameters.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#logMessageParams\ntype LogMessageParams struct {\n\t// The message type. See {@link MessageType}\n\tType MessageType `json:\"type\"`\n\t// The actual message.\n\tMessage string `json:\"message\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#logTraceParams\ntype LogTraceParams struct {\n\tMessage string `json:\"message\"`\n\tVerbose string `json:\"verbose,omitempty\"`\n}\n\n// Client capabilities specific to the used markdown parser.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#markdownClientCapabilities\ntype MarkdownClientCapabilities struct {\n\t// The name of the parser.\n\tParser string `json:\"parser\"`\n\t// The version of the parser.\n\tVersion string `json:\"version,omitempty\"`\n\t// A list of HTML tags that the client allows / supports in\n\t// Markdown.\n\t//\n\t// @since 3.17.0\n\tAllowedTags []string `json:\"allowedTags,omitempty\"`\n}\n\n// MarkedString can be used to render human readable text. It is either a markdown string\n// or a code-block that provides a language and a code snippet. The language identifier\n// is semantically equal to the optional language identifier in fenced code blocks in GitHub\n// issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting\n//\n// The pair of a language and a value is an equivalent to markdown:\n// ```${language}\n// ${value}\n// ```\n//\n// Note that markdown strings will be sanitized - that means html will be escaped.\n// @deprecated use MarkupContent instead.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#markedString\ntype MarkedString = Or_MarkedString // (alias)\n// @since 3.18.0\n// @deprecated use MarkupContent instead.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#markedStringWithLanguage\ntype MarkedStringWithLanguage struct {\n\tLanguage string `json:\"language\"`\n\tValue    string `json:\"value\"`\n}\n\n// A `MarkupContent` literal represents a string value which content is interpreted base on its\n// kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.\n//\n// If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.\n// See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting\n//\n// Here is an example how such a string can be constructed using JavaScript / TypeScript:\n// ```ts\n//\n//\tlet markdown: MarkdownContent = {\n//\t kind: MarkupKind.Markdown,\n//\t value: [\n//\t   '# Header',\n//\t   'Some text',\n//\t   '```typescript',\n//\t   'someCode();',\n//\t   '```'\n//\t ].join('\\n')\n//\t};\n//\n// ```\n//\n// *Please Note* that clients might sanitize the return markdown. A client could decide to\n// remove HTML from the markdown to avoid script execution.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#markupContent\ntype MarkupContent struct {\n\t// The type of the Markup\n\tKind MarkupKind `json:\"kind\"`\n\t// The content itself\n\tValue string `json:\"value\"`\n}\n\n// Describes the content type that a client supports in various\n// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.\n//\n// Please note that `MarkupKinds` must not start with a `$`. This kinds\n// are reserved for internal usage.\ntype MarkupKind string\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#messageActionItem\ntype MessageActionItem struct {\n\t// A short title like 'Retry', 'Open Log' etc.\n\tTitle string `json:\"title\"`\n}\n\n// The message type\ntype MessageType uint32\n\n// Moniker definition to match LSIF 0.5 moniker definition.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#moniker\ntype Moniker struct {\n\t// The scheme of the moniker. For example tsc or .Net\n\tScheme string `json:\"scheme\"`\n\t// The identifier of the moniker. The value is opaque in LSIF however\n\t// schema owners are allowed to define the structure if they want.\n\tIdentifier string `json:\"identifier\"`\n\t// The scope in which the moniker is unique\n\tUnique UniquenessLevel `json:\"unique\"`\n\t// The moniker kind if known.\n\tKind *MonikerKind `json:\"kind,omitempty\"`\n}\n\n// Client capabilities specific to the moniker request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#monikerClientCapabilities\ntype MonikerClientCapabilities struct {\n\t// Whether moniker supports dynamic registration. If this is set to `true`\n\t// the client supports the new `MonikerRegistrationOptions` return value\n\t// for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// The moniker kind.\n//\n// @since 3.16.0\ntype MonikerKind string\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#monikerOptions\ntype MonikerOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#monikerParams\ntype MonikerParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#monikerRegistrationOptions\ntype MonikerRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tMonikerOptions\n}\n\n// A notebook cell.\n//\n// A cell's document URI must be unique across ALL notebook\n// cells and can therefore be used to uniquely identify a\n// notebook cell or the cell's text document.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookCell\ntype NotebookCell struct {\n\t// The cell's kind\n\tKind NotebookCellKind `json:\"kind\"`\n\t// The URI of the cell's text document\n\t// content.\n\tDocument DocumentURI `json:\"document\"`\n\t// Additional metadata stored with the cell.\n\t//\n\t// Note: should always be an object literal (e.g. LSPObject)\n\tMetadata *LSPObject `json:\"metadata,omitempty\"`\n\t// Additional execution summary information\n\t// if supported by the client.\n\tExecutionSummary *ExecutionSummary `json:\"executionSummary,omitempty\"`\n}\n\n// A change describing how to move a `NotebookCell`\n// array from state S to S'.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookCellArrayChange\ntype NotebookCellArrayChange struct {\n\t// The start oftest of the cell that changed.\n\tStart uint32 `json:\"start\"`\n\t// The deleted cells\n\tDeleteCount uint32 `json:\"deleteCount\"`\n\t// The new cells, if any\n\tCells []NotebookCell `json:\"cells,omitempty\"`\n}\n\n// A notebook cell kind.\n//\n// @since 3.17.0\ntype NotebookCellKind uint32\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookCellLanguage\ntype NotebookCellLanguage struct {\n\tLanguage string `json:\"language\"`\n}\n\n// A notebook cell text document filter denotes a cell text\n// document by different properties.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookCellTextDocumentFilter\ntype NotebookCellTextDocumentFilter struct {\n\t// A filter that matches against the notebook\n\t// containing the notebook cell. If a string\n\t// value is provided it matches against the\n\t// notebook type. '*' matches every notebook.\n\tNotebook Or_NotebookCellTextDocumentFilter_notebook `json:\"notebook\"`\n\t// A language id like `python`.\n\t//\n\t// Will be matched against the language id of the\n\t// notebook cell document. '*' matches every language.\n\tLanguage string `json:\"language,omitempty\"`\n}\n\n// A notebook document.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocument\ntype NotebookDocument struct {\n\t// The notebook document's uri.\n\tURI URI `json:\"uri\"`\n\t// The type of the notebook.\n\tNotebookType string `json:\"notebookType\"`\n\t// The version number of this document (it will increase after each\n\t// change, including undo/redo).\n\tVersion int32 `json:\"version\"`\n\t// Additional metadata stored with the notebook\n\t// document.\n\t//\n\t// Note: should always be an object literal (e.g. LSPObject)\n\tMetadata *LSPObject `json:\"metadata,omitempty\"`\n\t// The cells of a notebook.\n\tCells []NotebookCell `json:\"cells\"`\n}\n\n// Structural changes to cells in a notebook document.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentCellChangeStructure\ntype NotebookDocumentCellChangeStructure struct {\n\t// The change to the cell array.\n\tArray NotebookCellArrayChange `json:\"array\"`\n\t// Additional opened cell text documents.\n\tDidOpen []TextDocumentItem `json:\"didOpen,omitempty\"`\n\t// Additional closed cell text documents.\n\tDidClose []TextDocumentIdentifier `json:\"didClose,omitempty\"`\n}\n\n// Cell changes to a notebook document.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentCellChanges\ntype NotebookDocumentCellChanges struct {\n\t// Changes to the cell structure to add or\n\t// remove cells.\n\tStructure *NotebookDocumentCellChangeStructure `json:\"structure,omitempty\"`\n\t// Changes to notebook cells properties like its\n\t// kind, execution summary or metadata.\n\tData []NotebookCell `json:\"data,omitempty\"`\n\t// Changes to the text content of notebook cells.\n\tTextContent []NotebookDocumentCellContentChanges `json:\"textContent,omitempty\"`\n}\n\n// Content changes to a cell in a notebook document.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentCellContentChanges\ntype NotebookDocumentCellContentChanges struct {\n\tDocument VersionedTextDocumentIdentifier  `json:\"document\"`\n\tChanges  []TextDocumentContentChangeEvent `json:\"changes\"`\n}\n\n// A change event for a notebook document.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentChangeEvent\ntype NotebookDocumentChangeEvent struct {\n\t// The changed meta data if any.\n\t//\n\t// Note: should always be an object literal (e.g. LSPObject)\n\tMetadata *LSPObject `json:\"metadata,omitempty\"`\n\t// Changes to cells\n\tCells *NotebookDocumentCellChanges `json:\"cells,omitempty\"`\n}\n\n// Capabilities specific to the notebook document support.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentClientCapabilities\ntype NotebookDocumentClientCapabilities struct {\n\t// Capabilities specific to notebook document synchronization\n\t//\n\t// @since 3.17.0\n\tSynchronization NotebookDocumentSyncClientCapabilities `json:\"synchronization\"`\n}\n\n// A notebook document filter denotes a notebook document by\n// different properties. The properties will be match\n// against the notebook's URI (same as with documents)\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilter\ntype NotebookDocumentFilter = Or_NotebookDocumentFilter // (alias)\n// A notebook document filter where `notebookType` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilterNotebookType\ntype NotebookDocumentFilterNotebookType struct {\n\t// The type of the enclosing notebook.\n\tNotebookType string `json:\"notebookType\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme,omitempty\"`\n\t// A glob pattern.\n\tPattern *GlobPattern `json:\"pattern,omitempty\"`\n}\n\n// A notebook document filter where `pattern` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilterPattern\ntype NotebookDocumentFilterPattern struct {\n\t// The type of the enclosing notebook.\n\tNotebookType string `json:\"notebookType,omitempty\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme,omitempty\"`\n\t// A glob pattern.\n\tPattern GlobPattern `json:\"pattern\"`\n}\n\n// A notebook document filter where `scheme` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilterScheme\ntype NotebookDocumentFilterScheme struct {\n\t// The type of the enclosing notebook.\n\tNotebookType string `json:\"notebookType,omitempty\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme\"`\n\t// A glob pattern.\n\tPattern *GlobPattern `json:\"pattern,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilterWithCells\ntype NotebookDocumentFilterWithCells struct {\n\t// The notebook to be synced If a string\n\t// value is provided it matches against the\n\t// notebook type. '*' matches every notebook.\n\tNotebook *Or_NotebookDocumentFilterWithCells_notebook `json:\"notebook,omitempty\"`\n\t// The cells of the matching notebook to be synced.\n\tCells []NotebookCellLanguage `json:\"cells\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentFilterWithNotebook\ntype NotebookDocumentFilterWithNotebook struct {\n\t// The notebook to be synced If a string\n\t// value is provided it matches against the\n\t// notebook type. '*' matches every notebook.\n\tNotebook Or_NotebookDocumentFilterWithNotebook_notebook `json:\"notebook\"`\n\t// The cells of the matching notebook to be synced.\n\tCells []NotebookCellLanguage `json:\"cells,omitempty\"`\n}\n\n// A literal to identify a notebook document in the client.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentIdentifier\ntype NotebookDocumentIdentifier struct {\n\t// The notebook document's uri.\n\tURI URI `json:\"uri\"`\n}\n\n// Notebook specific client capabilities.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentSyncClientCapabilities\ntype NotebookDocumentSyncClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is\n\t// set to `true` the client supports the new\n\t// `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports sending execution summary data per cell.\n\tExecutionSummarySupport bool `json:\"executionSummarySupport,omitempty\"`\n}\n\n// Options specific to a notebook plus its cells\n// to be synced to the server.\n//\n// If a selector provides a notebook document\n// filter but no cell selector all cells of a\n// matching notebook document will be synced.\n//\n// If a selector provides no notebook document\n// filter but only a cell selector all notebook\n// document that contain at least one matching\n// cell will be synced.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentSyncOptions\ntype NotebookDocumentSyncOptions struct {\n\t// The notebooks to be synced\n\tNotebookSelector []Or_NotebookDocumentSyncOptions_notebookSelector_Elem `json:\"notebookSelector\"`\n\t// Whether save notification should be forwarded to\n\t// the server. Will only be honored if mode === `notebook`.\n\tSave bool `json:\"save,omitempty\"`\n}\n\n// Registration options specific to a notebook.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocumentSyncRegistrationOptions\ntype NotebookDocumentSyncRegistrationOptions struct {\n\tNotebookDocumentSyncOptions\n\tStaticRegistrationOptions\n}\n\n// A text document identifier to optionally denote a specific version of a text document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#optionalVersionedTextDocumentIdentifier\ntype OptionalVersionedTextDocumentIdentifier struct {\n\t// The version number of this document. If a versioned text document identifier\n\t// is sent from the server to the client and the file is not open in the editor\n\t// (the server has not received an open notification before) the server can send\n\t// `null` to indicate that the version is unknown and the content on disk is the\n\t// truth (as specified with document content ownership).\n\tVersion int32 `json:\"version\"`\n\tTextDocumentIdentifier\n}\n\n// created for Or [Location LocationUriOnly]\ntype OrPLocation_workspace_symbol struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [[]string string]\ntype OrPSection_workspace_didChangeConfiguration struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkupContent string]\ntype OrPTooltipPLabel struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkupContent string]\ntype OrPTooltip_textDocument_inlayHint struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [int32 string]\ntype Or_CancelParams_id struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [ClientSemanticTokensRequestFullDelta bool]\ntype Or_ClientSemanticTokensRequestOptions_full struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [Lit_ClientSemanticTokensRequestOptions_range_Item1 bool]\ntype Or_ClientSemanticTokensRequestOptions_range struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [EditRangeWithInsertReplace Range]\ntype Or_CompletionItemDefaults_editRange struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkupContent string]\ntype Or_CompletionItem_documentation struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InsertReplaceEdit TextEdit]\ntype Or_CompletionItem_textEdit struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [Location []Location]\ntype Or_Definition struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [int32 string]\ntype Or_Diagnostic_code struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [RelatedFullDocumentDiagnosticReport RelatedUnchangedDocumentDiagnosticReport]\ntype Or_DocumentDiagnosticReport struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\ntype Or_DocumentDiagnosticReportPartialResult_relatedDocuments_Value struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookCellTextDocumentFilter TextDocumentFilter]\ntype Or_DocumentFilter struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [Pattern RelativePattern]\ntype Or_GlobPattern struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkedString MarkupContent []MarkedString]\ntype Or_Hover_contents struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [[]InlayHintLabelPart string]\ntype Or_InlayHint_label struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [StringValue string]\ntype Or_InlineCompletionItem_insertText struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InlineValueEvaluatableExpression InlineValueText InlineValueVariableLookup]\ntype Or_InlineValue struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkedStringWithLanguage string]\ntype Or_MarkedString struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentFilter string]\ntype Or_NotebookCellTextDocumentFilter_notebook struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentFilterNotebookType NotebookDocumentFilterPattern NotebookDocumentFilterScheme]\ntype Or_NotebookDocumentFilter struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentFilter string]\ntype Or_NotebookDocumentFilterWithCells_notebook struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentFilter string]\ntype Or_NotebookDocumentFilterWithNotebook_notebook struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentFilterWithCells NotebookDocumentFilterWithNotebook]\ntype Or_NotebookDocumentSyncOptions_notebookSelector_Elem struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\ntype Or_RelatedFullDocumentDiagnosticReport_relatedDocuments_Value struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [FullDocumentDiagnosticReport UnchangedDocumentDiagnosticReport]\ntype Or_RelatedUnchangedDocumentDiagnosticReport_relatedDocuments_Value struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [CodeAction Command]\ntype Or_Result_textDocument_codeAction_Item0_Elem struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InlineCompletionList []InlineCompletionItem]\ntype Or_Result_textDocument_inlineCompletion struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [SemanticTokensFullDelta bool]\ntype Or_SemanticTokensOptions_full struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [PRangeESemanticTokensOptions bool]\ntype Or_SemanticTokensOptions_range struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [CallHierarchyOptions CallHierarchyRegistrationOptions bool]\ntype Or_ServerCapabilities_callHierarchyProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [CodeActionOptions bool]\ntype Or_ServerCapabilities_codeActionProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DocumentColorOptions DocumentColorRegistrationOptions bool]\ntype Or_ServerCapabilities_colorProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DeclarationOptions DeclarationRegistrationOptions bool]\ntype Or_ServerCapabilities_declarationProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DefinitionOptions bool]\ntype Or_ServerCapabilities_definitionProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DiagnosticOptions DiagnosticRegistrationOptions]\ntype Or_ServerCapabilities_diagnosticProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DocumentFormattingOptions bool]\ntype Or_ServerCapabilities_documentFormattingProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DocumentHighlightOptions bool]\ntype Or_ServerCapabilities_documentHighlightProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DocumentRangeFormattingOptions bool]\ntype Or_ServerCapabilities_documentRangeFormattingProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [DocumentSymbolOptions bool]\ntype Or_ServerCapabilities_documentSymbolProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [FoldingRangeOptions FoldingRangeRegistrationOptions bool]\ntype Or_ServerCapabilities_foldingRangeProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [HoverOptions bool]\ntype Or_ServerCapabilities_hoverProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [ImplementationOptions ImplementationRegistrationOptions bool]\ntype Or_ServerCapabilities_implementationProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InlayHintOptions InlayHintRegistrationOptions bool]\ntype Or_ServerCapabilities_inlayHintProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InlineCompletionOptions bool]\ntype Or_ServerCapabilities_inlineCompletionProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [InlineValueOptions InlineValueRegistrationOptions bool]\ntype Or_ServerCapabilities_inlineValueProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [LinkedEditingRangeOptions LinkedEditingRangeRegistrationOptions bool]\ntype Or_ServerCapabilities_linkedEditingRangeProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MonikerOptions MonikerRegistrationOptions bool]\ntype Or_ServerCapabilities_monikerProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [NotebookDocumentSyncOptions NotebookDocumentSyncRegistrationOptions]\ntype Or_ServerCapabilities_notebookDocumentSync struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [ReferenceOptions bool]\ntype Or_ServerCapabilities_referencesProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [RenameOptions bool]\ntype Or_ServerCapabilities_renameProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [SelectionRangeOptions SelectionRangeRegistrationOptions bool]\ntype Or_ServerCapabilities_selectionRangeProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [SemanticTokensOptions SemanticTokensRegistrationOptions]\ntype Or_ServerCapabilities_semanticTokensProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [TextDocumentSyncKind TextDocumentSyncOptions]\ntype Or_ServerCapabilities_textDocumentSync struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [TypeDefinitionOptions TypeDefinitionRegistrationOptions bool]\ntype Or_ServerCapabilities_typeDefinitionProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [TypeHierarchyOptions TypeHierarchyRegistrationOptions bool]\ntype Or_ServerCapabilities_typeHierarchyProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [WorkspaceSymbolOptions bool]\ntype Or_ServerCapabilities_workspaceSymbolProvider struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [MarkupContent string]\ntype Or_SignatureInformation_documentation struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [AnnotatedTextEdit SnippetTextEdit TextEdit]\ntype Or_TextDocumentEdit_edits_Elem struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [TextDocumentFilterLanguage TextDocumentFilterPattern TextDocumentFilterScheme]\ntype Or_TextDocumentFilter struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [SaveOptions bool]\ntype Or_TextDocumentSyncOptions_save struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [WorkspaceFullDocumentDiagnosticReport WorkspaceUnchangedDocumentDiagnosticReport]\ntype Or_WorkspaceDocumentDiagnosticReport struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [CreateFile DeleteFile RenameFile TextDocumentEdit]\ntype Or_WorkspaceEdit_documentChanges_Elem struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [TextDocumentContentOptions TextDocumentContentRegistrationOptions]\ntype Or_WorkspaceOptions_textDocumentContent struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Or [Declaration []DeclarationLink]\ntype Or_textDocument_declaration struct {\n\tValue any `json:\"value\"`\n}\n\n// created for Literal (Lit_SemanticTokensOptions_range_Item1)\ntype PRangeESemanticTokensOptions struct {\n}\n\n// The parameters of a configuration request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#configurationParams\ntype ParamConfiguration struct {\n\tItems []ConfigurationItem `json:\"items\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initializeParams\ntype ParamInitialize struct {\n\tXInitializeParams\n\tWorkspaceFoldersInitializeParams\n}\n\n// Represents a parameter of a callable-signature. A parameter can\n// have a label and a doc-comment.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#parameterInformation\ntype ParameterInformation struct {\n\t// The label of this parameter information.\n\t//\n\t// Either a string or an inclusive start and exclusive end offsets within its containing\n\t// signature label. (see SignatureInformation.label). The offsets are based on a UTF-16\n\t// string representation as `Position` and `Range` does.\n\t//\n\t// To avoid ambiguities a server should use the [start, end] offset value instead of using\n\t// a substring. Whether a client support this is controlled via `labelOffsetSupport` client\n\t// capability.\n\t//\n\t// *Note*: a label of type string should be a substring of its containing signature label.\n\t// Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.\n\tLabel string `json:\"label\"`\n\t// The human-readable doc-comment of this parameter. Will be shown\n\t// in the UI but can be omitted.\n\tDocumentation string `json:\"documentation,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#partialResultParams\ntype PartialResultParams struct {\n\t// An optional token that a server can use to report partial results (e.g. streaming) to\n\t// the client.\n\tPartialResultToken *ProgressToken `json:\"partialResultToken,omitempty\"`\n}\n\n// The glob pattern to watch relative to the base path. Glob patterns can have the following syntax:\n//\n//   - `*` to match one or more characters in a path segment\n//   - `?` to match on one character in a path segment\n//   - `**` to match any number of path segments, including none\n//   - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)\n//   - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n//   - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#pattern\ntype Pattern = string // (alias)\n// Position in a text document expressed as zero-based line and character\n// offset. Prior to 3.17 the offsets were always based on a UTF-16 string\n// representation. So a string of the form `a𐐀b` the character offset of the\n// character `a` is 0, the character offset of `𐐀` is 1 and the character\n// offset of b is 3 since `𐐀` is represented using two code units in UTF-16.\n// Since 3.17 clients and servers can agree on a different string encoding\n// representation (e.g. UTF-8). The client announces it's supported encoding\n// via the client capability [`general.positionEncodings`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#clientCapabilities).\n// The value is an array of position encodings the client supports, with\n// decreasing preference (e.g. the encoding at index `0` is the most preferred\n// one). To stay backwards compatible the only mandatory encoding is UTF-16\n// represented via the string `utf-16`. The server can pick one of the\n// encodings offered by the client and signals that encoding back to the\n// client via the initialize result's property\n// [`capabilities.positionEncoding`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#serverCapabilities). If the string value\n// `utf-16` is missing from the client's capability `general.positionEncodings`\n// servers can safely assume that the client supports UTF-16. If the server\n// omits the position encoding in its initialize result the encoding defaults\n// to the string value `utf-16`. Implementation considerations: since the\n// conversion from one encoding into another requires the content of the\n// file / line the conversion is best done where the file is read which is\n// usually on the server side.\n//\n// Positions are line end character agnostic. So you can not specify a position\n// that denotes `\\r|\\n` or `\\n|` where `|` represents the character offset.\n//\n// @since 3.17.0 - support for negotiated position encoding.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#position\ntype Position struct {\n\t// Line position in a document (zero-based).\n\tLine uint32 `json:\"line\"`\n\t// Character offset on a line in a document (zero-based).\n\t//\n\t// The meaning of this offset is determined by the negotiated\n\t// `PositionEncodingKind`.\n\tCharacter uint32 `json:\"character\"`\n}\n\n// A set of predefined position encoding kinds.\n//\n// @since 3.17.0\ntype PositionEncodingKind string\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#prepareRenameDefaultBehavior\ntype PrepareRenameDefaultBehavior struct {\n\tDefaultBehavior bool `json:\"defaultBehavior\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#prepareRenameParams\ntype PrepareRenameParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#prepareRenamePlaceholder\ntype PrepareRenamePlaceholder struct {\n\tRange       Range  `json:\"range\"`\n\tPlaceholder string `json:\"placeholder\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#prepareRenameResult\ntype PrepareRenameResult = PrepareRenamePlaceholder // (alias)\ntype PrepareSupportDefaultBehavior uint32\n\n// A previous result id in a workspace pull request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#previousResultId\ntype PreviousResultID struct {\n\t// The URI for which the client knowns a\n\t// result id.\n\tURI DocumentURI `json:\"uri\"`\n\t// The value of the previous result id.\n\tValue string `json:\"value\"`\n}\n\n// A previous result id in a workspace pull request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#previousResultId\ntype PreviousResultId struct {\n\t// The URI for which the client knowns a\n\t// result id.\n\tURI DocumentURI `json:\"uri\"`\n\t// The value of the previous result id.\n\tValue string `json:\"value\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#progressParams\ntype ProgressParams struct {\n\t// The progress token provided by the client or server.\n\tToken ProgressToken `json:\"token\"`\n\t// The progress data.\n\tValue any `json:\"value\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#progressToken\ntype ProgressToken = any // (alias)\n// The publish diagnostic client capabilities.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#publishDiagnosticsClientCapabilities\ntype PublishDiagnosticsClientCapabilities struct {\n\t// Whether the client interprets the version property of the\n\t// `textDocument/publishDiagnostics` notification's parameter.\n\t//\n\t// @since 3.15.0\n\tVersionSupport bool `json:\"versionSupport,omitempty\"`\n\tDiagnosticsCapabilities\n}\n\n// The publish diagnostic notification's parameters.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#publishDiagnosticsParams\ntype PublishDiagnosticsParams struct {\n\t// The URI for which diagnostic information is reported.\n\tURI DocumentURI `json:\"uri\"`\n\t// Optional the version number of the document the diagnostics are published for.\n\t//\n\t// @since 3.15.0\n\tVersion int32 `json:\"version,omitempty\"`\n\t// An array of diagnostic information items.\n\tDiagnostics []Diagnostic `json:\"diagnostics\"`\n}\n\n// A range in a text document expressed as (zero-based) start and end positions.\n//\n// If you want to specify a range that contains a line including the line ending\n// character(s) then use an end position denoting the start of the next line.\n// For example:\n// ```ts\n//\n//\t{\n//\t    start: { line: 5, character: 23 }\n//\t    end : { line 6, character : 0 }\n//\t}\n//\n// ```\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#range\ntype Range struct {\n\t// The range's start position.\n\tStart Position `json:\"start\"`\n\t// The range's end position.\n\tEnd Position `json:\"end\"`\n}\n\n// Client Capabilities for a {@link ReferencesRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#referenceClientCapabilities\ntype ReferenceClientCapabilities struct {\n\t// Whether references supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Value-object that contains additional information when\n// requesting references.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#referenceContext\ntype ReferenceContext struct {\n\t// Include the declaration of the current symbol.\n\tIncludeDeclaration bool `json:\"includeDeclaration\"`\n}\n\n// Reference options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#referenceOptions\ntype ReferenceOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link ReferencesRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#referenceParams\ntype ReferenceParams struct {\n\tContext ReferenceContext `json:\"context\"`\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link ReferencesRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#referenceRegistrationOptions\ntype ReferenceRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tReferenceOptions\n}\n\n// General parameters to register for a notification or to register a provider.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#registration\ntype Registration struct {\n\t// The id used to register the request. The id can be used to deregister\n\t// the request again.\n\tID string `json:\"id\"`\n\t// The method / capability to register for.\n\tMethod string `json:\"method\"`\n\t// Options necessary for the registration.\n\tRegisterOptions any `json:\"registerOptions,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#registrationParams\ntype RegistrationParams struct {\n\tRegistrations []Registration `json:\"registrations\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#regularExpressionEngineKind\ntype RegularExpressionEngineKind = string // (alias)\n// Client capabilities specific to regular expressions.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#regularExpressionsClientCapabilities\ntype RegularExpressionsClientCapabilities struct {\n\t// The engine's name.\n\tEngine RegularExpressionEngineKind `json:\"engine\"`\n\t// The engine's version.\n\tVersion string `json:\"version,omitempty\"`\n}\n\n// A full diagnostic report with a set of related documents.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#relatedFullDocumentDiagnosticReport\ntype RelatedFullDocumentDiagnosticReport struct {\n\t// Diagnostics of related documents. This information is useful\n\t// in programming languages where code in a file A can generate\n\t// diagnostics in a file B which A depends on. An example of\n\t// such a language is C/C++ where marco definitions in a file\n\t// a.cpp and result in errors in a header file b.hpp.\n\t//\n\t// @since 3.17.0\n\tRelatedDocuments map[DocumentURI]any `json:\"relatedDocuments,omitempty\"`\n\tFullDocumentDiagnosticReport\n}\n\n// An unchanged diagnostic report with a set of related documents.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#relatedUnchangedDocumentDiagnosticReport\ntype RelatedUnchangedDocumentDiagnosticReport struct {\n\t// Diagnostics of related documents. This information is useful\n\t// in programming languages where code in a file A can generate\n\t// diagnostics in a file B which A depends on. An example of\n\t// such a language is C/C++ where marco definitions in a file\n\t// a.cpp and result in errors in a header file b.hpp.\n\t//\n\t// @since 3.17.0\n\tRelatedDocuments map[DocumentURI]any `json:\"relatedDocuments,omitempty\"`\n\tUnchangedDocumentDiagnosticReport\n}\n\n// A relative pattern is a helper to construct glob patterns that are matched\n// relatively to a base URI. The common value for a `baseUri` is a workspace\n// folder root, but it can be another absolute URI as well.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#relativePattern\ntype RelativePattern struct {\n\t// A workspace folder or a base URI to which this pattern will be matched\n\t// against relatively.\n\tBaseURI DocumentURI `json:\"baseUri\"`\n\t// The actual glob pattern;\n\tPattern Pattern `json:\"pattern\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameClientCapabilities\ntype RenameClientCapabilities struct {\n\t// Whether rename supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Client supports testing for validity of rename operations\n\t// before execution.\n\t//\n\t// @since 3.12.0\n\tPrepareSupport bool `json:\"prepareSupport,omitempty\"`\n\t// Client supports the default behavior result.\n\t//\n\t// The value indicates the default behavior used by the\n\t// client.\n\t//\n\t// @since 3.16.0\n\tPrepareSupportDefaultBehavior *PrepareSupportDefaultBehavior `json:\"prepareSupportDefaultBehavior,omitempty\"`\n\t// Whether the client honors the change annotations in\n\t// text edits and resource operations returned via the\n\t// rename request's workspace edit by for example presenting\n\t// the workspace edit in the user interface and asking\n\t// for confirmation.\n\t//\n\t// @since 3.16.0\n\tHonorsChangeAnnotations bool `json:\"honorsChangeAnnotations,omitempty\"`\n}\n\n// Rename file operation\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameFile\ntype RenameFile struct {\n\t// A rename\n\tKind string `json:\"kind\"`\n\t// The old (existing) location.\n\tOldURI DocumentURI `json:\"oldUri\"`\n\t// The new location.\n\tNewURI DocumentURI `json:\"newUri\"`\n\t// Rename options.\n\tOptions *RenameFileOptions `json:\"options,omitempty\"`\n\tResourceOperation\n}\n\n// Rename file options\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameFileOptions\ntype RenameFileOptions struct {\n\t// Overwrite target if existing. Overwrite wins over `ignoreIfExists`\n\tOverwrite bool `json:\"overwrite,omitempty\"`\n\t// Ignores if target exists.\n\tIgnoreIfExists bool `json:\"ignoreIfExists,omitempty\"`\n}\n\n// The parameters sent in notifications/requests for user-initiated renames of\n// files.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameFilesParams\ntype RenameFilesParams struct {\n\t// An array of all files/folders renamed in this operation. When a folder is renamed, only\n\t// the folder will be included, and not its children.\n\tFiles []FileRename `json:\"files\"`\n}\n\n// Provider options for a {@link RenameRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameOptions\ntype RenameOptions struct {\n\t// Renames should be checked and tested before being executed.\n\t//\n\t// @since version 3.12.0\n\tPrepareProvider bool `json:\"prepareProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link RenameRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameParams\ntype RenameParams struct {\n\t// The new name of the symbol. If the given name is not valid the\n\t// request must return a {@link ResponseError} with an\n\t// appropriate message set.\n\tNewName string `json:\"newName\"`\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link RenameRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#renameRegistrationOptions\ntype RenameRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tRenameOptions\n}\n\n// A generic resource operation.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#resourceOperation\ntype ResourceOperation struct {\n\t// The resource operation kind.\n\tKind string `json:\"kind\"`\n\t// An optional annotation identifier describing the operation.\n\t//\n\t// @since 3.16.0\n\tAnnotationID *ChangeAnnotationIdentifier `json:\"annotationId,omitempty\"`\n}\ntype ResourceOperationKind string\n\n// Save options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#saveOptions\ntype SaveOptions struct {\n\t// The client is supposed to include the content on save.\n\tIncludeText bool `json:\"includeText,omitempty\"`\n}\n\n// Describes the currently selected completion item.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectedCompletionInfo\ntype SelectedCompletionInfo struct {\n\t// The range that will be replaced if this completion item is accepted.\n\tRange Range `json:\"range\"`\n\t// The text the range will be replaced with if this completion is accepted.\n\tText string `json:\"text\"`\n}\n\n// A selection range represents a part of a selection hierarchy. A selection range\n// may have a parent selection range that contains it.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectionRange\ntype SelectionRange struct {\n\t// The {@link Range range} of this selection range.\n\tRange Range `json:\"range\"`\n\t// The parent selection range containing this range. Therefore `parent.range` must contain `this.range`.\n\tParent *SelectionRange `json:\"parent,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectionRangeClientCapabilities\ntype SelectionRangeClientCapabilities struct {\n\t// Whether implementation supports dynamic registration for selection range providers. If this is set to `true`\n\t// the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server\n\t// capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectionRangeOptions\ntype SelectionRangeOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// A parameter literal used in selection range requests.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectionRangeParams\ntype SelectionRangeParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The positions inside the text document.\n\tPositions []Position `json:\"positions\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#selectionRangeRegistrationOptions\ntype SelectionRangeRegistrationOptions struct {\n\tSelectionRangeOptions\n\tTextDocumentRegistrationOptions\n\tStaticRegistrationOptions\n}\n\n// A set of predefined token modifiers. This set is not fixed\n// an clients can specify additional token types via the\n// corresponding client capabilities.\n//\n// @since 3.16.0\ntype SemanticTokenModifiers string\n\n// A set of predefined token types. This set is not fixed\n// an clients can specify additional token types via the\n// corresponding client capabilities.\n//\n// @since 3.16.0\ntype SemanticTokenTypes string\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokens\ntype SemanticTokens struct {\n\t// An optional result id. If provided and clients support delta updating\n\t// the client will include the result id in the next semantic token request.\n\t// A server can then instead of computing all semantic tokens again simply\n\t// send a delta.\n\tResultID string `json:\"resultId,omitempty\"`\n\t// The actual tokens.\n\tData []uint32 `json:\"data\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensClientCapabilities\ntype SemanticTokensClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Which requests the client supports and might send to the server\n\t// depending on the server's capability. Please note that clients might not\n\t// show semantic tokens or degrade some of the user experience if a range\n\t// or full request is advertised by the client but not provided by the\n\t// server. If for example the client capability `requests.full` and\n\t// `request.range` are both set to true but the server only provides a\n\t// range provider the client might not render a minimap correctly or might\n\t// even decide to not show any semantic tokens at all.\n\tRequests ClientSemanticTokensRequestOptions `json:\"requests\"`\n\t// The token types that the client supports.\n\tTokenTypes []string `json:\"tokenTypes\"`\n\t// The token modifiers that the client supports.\n\tTokenModifiers []string `json:\"tokenModifiers\"`\n\t// The token formats the clients supports.\n\tFormats []TokenFormat `json:\"formats\"`\n\t// Whether the client supports tokens that can overlap each other.\n\tOverlappingTokenSupport bool `json:\"overlappingTokenSupport,omitempty\"`\n\t// Whether the client supports tokens that can span multiple lines.\n\tMultilineTokenSupport bool `json:\"multilineTokenSupport,omitempty\"`\n\t// Whether the client allows the server to actively cancel a\n\t// semantic token request, e.g. supports returning\n\t// LSPErrorCodes.ServerCancelled. If a server does the client\n\t// needs to retrigger the request.\n\t//\n\t// @since 3.17.0\n\tServerCancelSupport bool `json:\"serverCancelSupport,omitempty\"`\n\t// Whether the client uses semantic tokens to augment existing\n\t// syntax tokens. If set to `true` client side created syntax\n\t// tokens and semantic tokens are both used for colorization. If\n\t// set to `false` the client only uses the returned semantic tokens\n\t// for colorization.\n\t//\n\t// If the value is `undefined` then the client behavior is not\n\t// specified.\n\t//\n\t// @since 3.17.0\n\tAugmentsSyntaxTokens bool `json:\"augmentsSyntaxTokens,omitempty\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensDelta\ntype SemanticTokensDelta struct {\n\tResultID string `json:\"resultId,omitempty\"`\n\t// The semantic token edits to transform a previous result into a new result.\n\tEdits []SemanticTokensEdit `json:\"edits\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensDeltaParams\ntype SemanticTokensDeltaParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The result id of a previous response. The result Id can either point to a full response\n\t// or a delta response depending on what was received last.\n\tPreviousResultID string `json:\"previousResultId\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensDeltaPartialResult\ntype SemanticTokensDeltaPartialResult struct {\n\tEdits []SemanticTokensEdit `json:\"edits\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensEdit\ntype SemanticTokensEdit struct {\n\t// The start offset of the edit.\n\tStart uint32 `json:\"start\"`\n\t// The count of elements to remove.\n\tDeleteCount uint32 `json:\"deleteCount\"`\n\t// The elements to insert.\n\tData []uint32 `json:\"data,omitempty\"`\n}\n\n// Semantic tokens options to support deltas for full documents\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensFullDelta\ntype SemanticTokensFullDelta struct {\n\t// The server supports deltas for full documents.\n\tDelta bool `json:\"delta,omitempty\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensLegend\ntype SemanticTokensLegend struct {\n\t// The token types a server uses.\n\tTokenTypes []string `json:\"tokenTypes\"`\n\t// The token modifiers a server uses.\n\tTokenModifiers []string `json:\"tokenModifiers\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensOptions\ntype SemanticTokensOptions struct {\n\t// The legend used by the server\n\tLegend SemanticTokensLegend `json:\"legend\"`\n\t// Server supports providing semantic tokens for a specific range\n\t// of a document.\n\tRange *Or_SemanticTokensOptions_range `json:\"range,omitempty\"`\n\t// Server supports providing semantic tokens for a full document.\n\tFull *Or_SemanticTokensOptions_full `json:\"full,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensParams\ntype SemanticTokensParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensPartialResult\ntype SemanticTokensPartialResult struct {\n\tData []uint32 `json:\"data\"`\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensRangeParams\ntype SemanticTokensRangeParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The range the semantic tokens are requested for.\n\tRange Range `json:\"range\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensRegistrationOptions\ntype SemanticTokensRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tSemanticTokensOptions\n\tStaticRegistrationOptions\n}\n\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#semanticTokensWorkspaceClientCapabilities\ntype SemanticTokensWorkspaceClientCapabilities struct {\n\t// Whether the client implementation supports a refresh request sent from\n\t// the server to the client.\n\t//\n\t// Note that this event is global and will force the client to refresh all\n\t// semantic tokens currently shown. It should be used with absolute care\n\t// and is useful for situation where a server for example detects a project\n\t// wide change that requires such a calculation.\n\tRefreshSupport bool `json:\"refreshSupport,omitempty\"`\n}\n\n// Defines the capabilities provided by a language\n// server.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#serverCapabilities\ntype ServerCapabilities struct {\n\t// The position encoding the server picked from the encodings offered\n\t// by the client via the client capability `general.positionEncodings`.\n\t//\n\t// If the client didn't provide any position encodings the only valid\n\t// value that a server can return is 'utf-16'.\n\t//\n\t// If omitted it defaults to 'utf-16'.\n\t//\n\t// @since 3.17.0\n\tPositionEncoding *PositionEncodingKind `json:\"positionEncoding,omitempty\"`\n\t// Defines how text documents are synced. Is either a detailed structure\n\t// defining each notification or for backwards compatibility the\n\t// TextDocumentSyncKind number.\n\tTextDocumentSync any `json:\"textDocumentSync,omitempty\"`\n\t// Defines how notebook documents are synced.\n\t//\n\t// @since 3.17.0\n\tNotebookDocumentSync *Or_ServerCapabilities_notebookDocumentSync `json:\"notebookDocumentSync,omitempty\"`\n\t// The server provides completion support.\n\tCompletionProvider *CompletionOptions `json:\"completionProvider,omitempty\"`\n\t// The server provides hover support.\n\tHoverProvider *Or_ServerCapabilities_hoverProvider `json:\"hoverProvider,omitempty\"`\n\t// The server provides signature help support.\n\tSignatureHelpProvider *SignatureHelpOptions `json:\"signatureHelpProvider,omitempty\"`\n\t// The server provides Goto Declaration support.\n\tDeclarationProvider *Or_ServerCapabilities_declarationProvider `json:\"declarationProvider,omitempty\"`\n\t// The server provides goto definition support.\n\tDefinitionProvider *Or_ServerCapabilities_definitionProvider `json:\"definitionProvider,omitempty\"`\n\t// The server provides Goto Type Definition support.\n\tTypeDefinitionProvider *Or_ServerCapabilities_typeDefinitionProvider `json:\"typeDefinitionProvider,omitempty\"`\n\t// The server provides Goto Implementation support.\n\tImplementationProvider *Or_ServerCapabilities_implementationProvider `json:\"implementationProvider,omitempty\"`\n\t// The server provides find references support.\n\tReferencesProvider *Or_ServerCapabilities_referencesProvider `json:\"referencesProvider,omitempty\"`\n\t// The server provides document highlight support.\n\tDocumentHighlightProvider *Or_ServerCapabilities_documentHighlightProvider `json:\"documentHighlightProvider,omitempty\"`\n\t// The server provides document symbol support.\n\tDocumentSymbolProvider *Or_ServerCapabilities_documentSymbolProvider `json:\"documentSymbolProvider,omitempty\"`\n\t// The server provides code actions. CodeActionOptions may only be\n\t// specified if the client states that it supports\n\t// `codeActionLiteralSupport` in its initial `initialize` request.\n\tCodeActionProvider any `json:\"codeActionProvider,omitempty\"`\n\t// The server provides code lens.\n\tCodeLensProvider *CodeLensOptions `json:\"codeLensProvider,omitempty\"`\n\t// The server provides document link support.\n\tDocumentLinkProvider *DocumentLinkOptions `json:\"documentLinkProvider,omitempty\"`\n\t// The server provides color provider support.\n\tColorProvider *Or_ServerCapabilities_colorProvider `json:\"colorProvider,omitempty\"`\n\t// The server provides workspace symbol support.\n\tWorkspaceSymbolProvider *Or_ServerCapabilities_workspaceSymbolProvider `json:\"workspaceSymbolProvider,omitempty\"`\n\t// The server provides document formatting.\n\tDocumentFormattingProvider *Or_ServerCapabilities_documentFormattingProvider `json:\"documentFormattingProvider,omitempty\"`\n\t// The server provides document range formatting.\n\tDocumentRangeFormattingProvider *Or_ServerCapabilities_documentRangeFormattingProvider `json:\"documentRangeFormattingProvider,omitempty\"`\n\t// The server provides document formatting on typing.\n\tDocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:\"documentOnTypeFormattingProvider,omitempty\"`\n\t// The server provides rename support. RenameOptions may only be\n\t// specified if the client states that it supports\n\t// `prepareSupport` in its initial `initialize` request.\n\tRenameProvider any `json:\"renameProvider,omitempty\"`\n\t// The server provides folding provider support.\n\tFoldingRangeProvider *Or_ServerCapabilities_foldingRangeProvider `json:\"foldingRangeProvider,omitempty\"`\n\t// The server provides selection range support.\n\tSelectionRangeProvider *Or_ServerCapabilities_selectionRangeProvider `json:\"selectionRangeProvider,omitempty\"`\n\t// The server provides execute command support.\n\tExecuteCommandProvider *ExecuteCommandOptions `json:\"executeCommandProvider,omitempty\"`\n\t// The server provides call hierarchy support.\n\t//\n\t// @since 3.16.0\n\tCallHierarchyProvider *Or_ServerCapabilities_callHierarchyProvider `json:\"callHierarchyProvider,omitempty\"`\n\t// The server provides linked editing range support.\n\t//\n\t// @since 3.16.0\n\tLinkedEditingRangeProvider *Or_ServerCapabilities_linkedEditingRangeProvider `json:\"linkedEditingRangeProvider,omitempty\"`\n\t// The server provides semantic tokens support.\n\t//\n\t// @since 3.16.0\n\tSemanticTokensProvider any `json:\"semanticTokensProvider,omitempty\"`\n\t// The server provides moniker support.\n\t//\n\t// @since 3.16.0\n\tMonikerProvider *Or_ServerCapabilities_monikerProvider `json:\"monikerProvider,omitempty\"`\n\t// The server provides type hierarchy support.\n\t//\n\t// @since 3.17.0\n\tTypeHierarchyProvider *Or_ServerCapabilities_typeHierarchyProvider `json:\"typeHierarchyProvider,omitempty\"`\n\t// The server provides inline values.\n\t//\n\t// @since 3.17.0\n\tInlineValueProvider *Or_ServerCapabilities_inlineValueProvider `json:\"inlineValueProvider,omitempty\"`\n\t// The server provides inlay hints.\n\t//\n\t// @since 3.17.0\n\tInlayHintProvider any `json:\"inlayHintProvider,omitempty\"`\n\t// The server has support for pull model diagnostics.\n\t//\n\t// @since 3.17.0\n\tDiagnosticProvider *Or_ServerCapabilities_diagnosticProvider `json:\"diagnosticProvider,omitempty\"`\n\t// Inline completion options used during static registration.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tInlineCompletionProvider *Or_ServerCapabilities_inlineCompletionProvider `json:\"inlineCompletionProvider,omitempty\"`\n\t// Workspace specific server capabilities.\n\tWorkspace *WorkspaceOptions `json:\"workspace,omitempty\"`\n\t// Experimental server capabilities.\n\tExperimental any `json:\"experimental,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#serverCompletionItemOptions\ntype ServerCompletionItemOptions struct {\n\t// The server has support for completion item label\n\t// details (see also `CompletionItemLabelDetails`) when\n\t// receiving a completion item in a resolve call.\n\t//\n\t// @since 3.17.0\n\tLabelDetailsSupport bool `json:\"labelDetailsSupport,omitempty\"`\n}\n\n// Information about the server\n//\n// @since 3.15.0\n// @since 3.18.0 ServerInfo type name added.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#serverInfo\ntype ServerInfo struct {\n\t// The name of the server as defined by the server.\n\tName string `json:\"name\"`\n\t// The server's version as defined by the server.\n\tVersion string `json:\"version,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#setTraceParams\ntype SetTraceParams struct {\n\tValue TraceValue `json:\"value\"`\n}\n\n// Client capabilities for the showDocument request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showDocumentClientCapabilities\ntype ShowDocumentClientCapabilities struct {\n\t// The client has support for the showDocument\n\t// request.\n\tSupport bool `json:\"support\"`\n}\n\n// Params to show a resource in the UI.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showDocumentParams\ntype ShowDocumentParams struct {\n\t// The uri to show.\n\tURI URI `json:\"uri\"`\n\t// Indicates to show the resource in an external program.\n\t// To show, for example, `https://code.visualstudio.com/`\n\t// in the default WEB browser set `external` to `true`.\n\tExternal bool `json:\"external,omitempty\"`\n\t// An optional property to indicate whether the editor\n\t// showing the document should take focus or not.\n\t// Clients might ignore this property if an external\n\t// program is started.\n\tTakeFocus bool `json:\"takeFocus,omitempty\"`\n\t// An optional selection range if the document is a text\n\t// document. Clients might ignore the property if an\n\t// external program is started or the file is not a text\n\t// file.\n\tSelection *Range `json:\"selection,omitempty\"`\n}\n\n// The result of a showDocument request.\n//\n// @since 3.16.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showDocumentResult\ntype ShowDocumentResult struct {\n\t// A boolean indicating if the show was successful.\n\tSuccess bool `json:\"success\"`\n}\n\n// The parameters of a notification message.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showMessageParams\ntype ShowMessageParams struct {\n\t// The message type. See {@link MessageType}\n\tType MessageType `json:\"type\"`\n\t// The actual message.\n\tMessage string `json:\"message\"`\n}\n\n// Show message request client capabilities\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showMessageRequestClientCapabilities\ntype ShowMessageRequestClientCapabilities struct {\n\t// Capabilities specific to the `MessageActionItem` type.\n\tMessageActionItem *ClientShowMessageActionItemOptions `json:\"messageActionItem,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#showMessageRequestParams\ntype ShowMessageRequestParams struct {\n\t// The message type. See {@link MessageType}\n\tType MessageType `json:\"type\"`\n\t// The actual message.\n\tMessage string `json:\"message\"`\n\t// The message action items to present.\n\tActions []MessageActionItem `json:\"actions,omitempty\"`\n}\n\n// Signature help represents the signature of something\n// callable. There can be multiple signature but only one\n// active and only one active parameter.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelp\ntype SignatureHelp struct {\n\t// One or more signatures.\n\tSignatures []SignatureInformation `json:\"signatures\"`\n\t// The active signature. If omitted or the value lies outside the\n\t// range of `signatures` the value defaults to zero or is ignored if\n\t// the `SignatureHelp` has no signatures.\n\t//\n\t// Whenever possible implementors should make an active decision about\n\t// the active signature and shouldn't rely on a default value.\n\t//\n\t// In future version of the protocol this property might become\n\t// mandatory to better express this.\n\tActiveSignature uint32 `json:\"activeSignature\"`\n\t// The active parameter of the active signature.\n\t//\n\t// If `null`, no parameter of the signature is active (for example a named\n\t// argument that does not match any declared parameters). This is only valid\n\t// if the client specifies the client capability\n\t// `textDocument.signatureHelp.noActiveParameterSupport === true`\n\t//\n\t// If omitted or the value lies outside the range of\n\t// `signatures[activeSignature].parameters` defaults to 0 if the active\n\t// signature has parameters.\n\t//\n\t// If the active signature has no parameters it is ignored.\n\t//\n\t// In future version of the protocol this property might become\n\t// mandatory (but still nullable) to better express the active parameter if\n\t// the active signature does have any.\n\tActiveParameter *uint32 `json:\"activeParameter,omitempty\"`\n}\n\n// Client Capabilities for a {@link SignatureHelpRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelpClientCapabilities\ntype SignatureHelpClientCapabilities struct {\n\t// Whether signature help supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports the following `SignatureInformation`\n\t// specific properties.\n\tSignatureInformation *ClientSignatureInformationOptions `json:\"signatureInformation,omitempty\"`\n\t// The client supports to send additional context information for a\n\t// `textDocument/signatureHelp` request. A client that opts into\n\t// contextSupport will also support the `retriggerCharacters` on\n\t// `SignatureHelpOptions`.\n\t//\n\t// @since 3.15.0\n\tContextSupport bool `json:\"contextSupport,omitempty\"`\n}\n\n// Additional information about the context in which a signature help request was triggered.\n//\n// @since 3.15.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelpContext\ntype SignatureHelpContext struct {\n\t// Action that caused signature help to be triggered.\n\tTriggerKind SignatureHelpTriggerKind `json:\"triggerKind\"`\n\t// Character that caused signature help to be triggered.\n\t//\n\t// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`\n\tTriggerCharacter string `json:\"triggerCharacter,omitempty\"`\n\t// `true` if signature help was already showing when it was triggered.\n\t//\n\t// Retriggers occurs when the signature help is already active and can be caused by actions such as\n\t// typing a trigger character, a cursor move, or document content changes.\n\tIsRetrigger bool `json:\"isRetrigger\"`\n\t// The currently active `SignatureHelp`.\n\t//\n\t// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on\n\t// the user navigating through available signatures.\n\tActiveSignatureHelp *SignatureHelp `json:\"activeSignatureHelp,omitempty\"`\n}\n\n// Server Capabilities for a {@link SignatureHelpRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelpOptions\ntype SignatureHelpOptions struct {\n\t// List of characters that trigger signature help automatically.\n\tTriggerCharacters []string `json:\"triggerCharacters,omitempty\"`\n\t// List of characters that re-trigger signature help.\n\t//\n\t// These trigger characters are only active when signature help is already showing. All trigger characters\n\t// are also counted as re-trigger characters.\n\t//\n\t// @since 3.15.0\n\tRetriggerCharacters []string `json:\"retriggerCharacters,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// Parameters for a {@link SignatureHelpRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelpParams\ntype SignatureHelpParams struct {\n\t// The signature help context. This is only available if the client specifies\n\t// to send this using the client capability `textDocument.signatureHelp.contextSupport === true`\n\t//\n\t// @since 3.15.0\n\tContext *SignatureHelpContext `json:\"context,omitempty\"`\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Registration options for a {@link SignatureHelpRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureHelpRegistrationOptions\ntype SignatureHelpRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tSignatureHelpOptions\n}\n\n// How a signature help was triggered.\n//\n// @since 3.15.0\ntype SignatureHelpTriggerKind uint32\n\n// Represents the signature of something callable. A signature\n// can have a label, like a function-name, a doc-comment, and\n// a set of parameters.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#signatureInformation\ntype SignatureInformation struct {\n\t// The label of this signature. Will be shown in\n\t// the UI.\n\tLabel string `json:\"label\"`\n\t// The human-readable doc-comment of this signature. Will be shown\n\t// in the UI but can be omitted.\n\tDocumentation *Or_SignatureInformation_documentation `json:\"documentation,omitempty\"`\n\t// The parameters of this signature.\n\tParameters []ParameterInformation `json:\"parameters,omitempty\"`\n\t// The index of the active parameter.\n\t//\n\t// If `null`, no parameter of the signature is active (for example a named\n\t// argument that does not match any declared parameters). This is only valid\n\t// if the client specifies the client capability\n\t// `textDocument.signatureHelp.noActiveParameterSupport === true`\n\t//\n\t// If provided (or `null`), this is used in place of\n\t// `SignatureHelp.activeParameter`.\n\t//\n\t// @since 3.16.0\n\tActiveParameter *uint32 `json:\"activeParameter,omitempty\"`\n}\n\n// An interactive text edit.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#snippetTextEdit\ntype SnippetTextEdit struct {\n\t// The range of the text document to be manipulated.\n\tRange Range `json:\"range\"`\n\t// The snippet to be inserted.\n\tSnippet StringValue `json:\"snippet\"`\n\t// The actual identifier of the snippet edit.\n\tAnnotationID *ChangeAnnotationIdentifier `json:\"annotationId,omitempty\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#staleRequestSupportOptions\ntype StaleRequestSupportOptions struct {\n\t// The client will actively cancel the request.\n\tCancel bool `json:\"cancel\"`\n\t// The list of requests for which the client\n\t// will retry the request if it receives a\n\t// response with error code `ContentModified`\n\tRetryOnContentModified []string `json:\"retryOnContentModified\"`\n}\n\n// Static registration options to be returned in the initialize\n// request.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#staticRegistrationOptions\ntype StaticRegistrationOptions struct {\n\t// The id used to register the request. The id can be used to deregister\n\t// the request again. See also Registration#id.\n\tID string `json:\"id,omitempty\"`\n}\n\n// A string value used as a snippet is a template which allows to insert text\n// and to control the editor cursor when insertion happens.\n//\n// A snippet can define tab stops and placeholders with `$1`, `$2`\n// and `${3:foo}`. `$0` defines the final tab stop, it defaults to\n// the end of the snippet. Variables are defined with `$name` and\n// `${name:default value}`.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#stringValue\ntype StringValue struct {\n\t// The kind of string value.\n\tKind string `json:\"kind\"`\n\t// The snippet string.\n\tValue string `json:\"value\"`\n}\n\n// Represents information about programming constructs like variables, classes,\n// interfaces etc.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#symbolInformation\ntype SymbolInformation struct {\n\t// extends BaseSymbolInformation\n\t// Indicates if this symbol is deprecated.\n\t//\n\t// @deprecated Use tags instead\n\tDeprecated bool `json:\"deprecated,omitempty\"`\n\t// The location of this symbol. The location's range is used by a tool\n\t// to reveal the location in the editor. If the symbol is selected in the\n\t// tool the range's start information is used to position the cursor. So\n\t// the range usually spans more than the actual symbol's name and does\n\t// normally include things like visibility modifiers.\n\t//\n\t// The range doesn't have to denote a node range in the sense of an abstract\n\t// syntax tree. It can therefore not be used to re-construct a hierarchy of\n\t// the symbols.\n\tLocation Location `json:\"location\"`\n\t// The name of this symbol.\n\tName string `json:\"name\"`\n\t// The kind of this symbol.\n\tKind SymbolKind `json:\"kind\"`\n\t// Tags for this symbol.\n\t//\n\t// @since 3.16.0\n\tTags []SymbolTag `json:\"tags,omitempty\"`\n\t// The name of the symbol containing this symbol. This information is for\n\t// user interface purposes (e.g. to render a qualifier in the user interface\n\t// if necessary). It can't be used to re-infer a hierarchy for the document\n\t// symbols.\n\tContainerName string `json:\"containerName,omitempty\"`\n}\n\n// A symbol kind.\ntype SymbolKind uint32\n\n// Symbol tags are extra annotations that tweak the rendering of a symbol.\n//\n// @since 3.16\ntype SymbolTag uint32\n\n// Describe options to be used when registered for text document change events.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentChangeRegistrationOptions\ntype TextDocumentChangeRegistrationOptions struct {\n\t// How documents are synced to the server.\n\tSyncKind TextDocumentSyncKind `json:\"syncKind\"`\n\tTextDocumentRegistrationOptions\n}\n\n// Text document specific client capabilities.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentClientCapabilities\ntype TextDocumentClientCapabilities struct {\n\t// Defines which synchronization capabilities the client supports.\n\tSynchronization *TextDocumentSyncClientCapabilities `json:\"synchronization,omitempty\"`\n\t// Defines which filters the client supports.\n\t//\n\t// @since 3.18.0\n\tFilters *TextDocumentFilterClientCapabilities `json:\"filters,omitempty\"`\n\t// Capabilities specific to the `textDocument/completion` request.\n\tCompletion CompletionClientCapabilities `json:\"completion,omitempty\"`\n\t// Capabilities specific to the `textDocument/hover` request.\n\tHover *HoverClientCapabilities `json:\"hover,omitempty\"`\n\t// Capabilities specific to the `textDocument/signatureHelp` request.\n\tSignatureHelp *SignatureHelpClientCapabilities `json:\"signatureHelp,omitempty\"`\n\t// Capabilities specific to the `textDocument/declaration` request.\n\t//\n\t// @since 3.14.0\n\tDeclaration *DeclarationClientCapabilities `json:\"declaration,omitempty\"`\n\t// Capabilities specific to the `textDocument/definition` request.\n\tDefinition *DefinitionClientCapabilities `json:\"definition,omitempty\"`\n\t// Capabilities specific to the `textDocument/typeDefinition` request.\n\t//\n\t// @since 3.6.0\n\tTypeDefinition *TypeDefinitionClientCapabilities `json:\"typeDefinition,omitempty\"`\n\t// Capabilities specific to the `textDocument/implementation` request.\n\t//\n\t// @since 3.6.0\n\tImplementation *ImplementationClientCapabilities `json:\"implementation,omitempty\"`\n\t// Capabilities specific to the `textDocument/references` request.\n\tReferences *ReferenceClientCapabilities `json:\"references,omitempty\"`\n\t// Capabilities specific to the `textDocument/documentHighlight` request.\n\tDocumentHighlight *DocumentHighlightClientCapabilities `json:\"documentHighlight,omitempty\"`\n\t// Capabilities specific to the `textDocument/documentSymbol` request.\n\tDocumentSymbol DocumentSymbolClientCapabilities `json:\"documentSymbol,omitempty\"`\n\t// Capabilities specific to the `textDocument/codeAction` request.\n\tCodeAction CodeActionClientCapabilities `json:\"codeAction,omitempty\"`\n\t// Capabilities specific to the `textDocument/codeLens` request.\n\tCodeLens *CodeLensClientCapabilities `json:\"codeLens,omitempty\"`\n\t// Capabilities specific to the `textDocument/documentLink` request.\n\tDocumentLink *DocumentLinkClientCapabilities `json:\"documentLink,omitempty\"`\n\t// Capabilities specific to the `textDocument/documentColor` and the\n\t// `textDocument/colorPresentation` request.\n\t//\n\t// @since 3.6.0\n\tColorProvider *DocumentColorClientCapabilities `json:\"colorProvider,omitempty\"`\n\t// Capabilities specific to the `textDocument/formatting` request.\n\tFormatting *DocumentFormattingClientCapabilities `json:\"formatting,omitempty\"`\n\t// Capabilities specific to the `textDocument/rangeFormatting` request.\n\tRangeFormatting *DocumentRangeFormattingClientCapabilities `json:\"rangeFormatting,omitempty\"`\n\t// Capabilities specific to the `textDocument/onTypeFormatting` request.\n\tOnTypeFormatting *DocumentOnTypeFormattingClientCapabilities `json:\"onTypeFormatting,omitempty\"`\n\t// Capabilities specific to the `textDocument/rename` request.\n\tRename *RenameClientCapabilities `json:\"rename,omitempty\"`\n\t// Capabilities specific to the `textDocument/foldingRange` request.\n\t//\n\t// @since 3.10.0\n\tFoldingRange *FoldingRangeClientCapabilities `json:\"foldingRange,omitempty\"`\n\t// Capabilities specific to the `textDocument/selectionRange` request.\n\t//\n\t// @since 3.15.0\n\tSelectionRange *SelectionRangeClientCapabilities `json:\"selectionRange,omitempty\"`\n\t// Capabilities specific to the `textDocument/publishDiagnostics` notification.\n\tPublishDiagnostics PublishDiagnosticsClientCapabilities `json:\"publishDiagnostics,omitempty\"`\n\t// Capabilities specific to the various call hierarchy requests.\n\t//\n\t// @since 3.16.0\n\tCallHierarchy *CallHierarchyClientCapabilities `json:\"callHierarchy,omitempty\"`\n\t// Capabilities specific to the various semantic token request.\n\t//\n\t// @since 3.16.0\n\tSemanticTokens SemanticTokensClientCapabilities `json:\"semanticTokens,omitempty\"`\n\t// Capabilities specific to the `textDocument/linkedEditingRange` request.\n\t//\n\t// @since 3.16.0\n\tLinkedEditingRange *LinkedEditingRangeClientCapabilities `json:\"linkedEditingRange,omitempty\"`\n\t// Client capabilities specific to the `textDocument/moniker` request.\n\t//\n\t// @since 3.16.0\n\tMoniker *MonikerClientCapabilities `json:\"moniker,omitempty\"`\n\t// Capabilities specific to the various type hierarchy requests.\n\t//\n\t// @since 3.17.0\n\tTypeHierarchy *TypeHierarchyClientCapabilities `json:\"typeHierarchy,omitempty\"`\n\t// Capabilities specific to the `textDocument/inlineValue` request.\n\t//\n\t// @since 3.17.0\n\tInlineValue *InlineValueClientCapabilities `json:\"inlineValue,omitempty\"`\n\t// Capabilities specific to the `textDocument/inlayHint` request.\n\t//\n\t// @since 3.17.0\n\tInlayHint *InlayHintClientCapabilities `json:\"inlayHint,omitempty\"`\n\t// Capabilities specific to the diagnostic pull model.\n\t//\n\t// @since 3.17.0\n\tDiagnostic *DiagnosticClientCapabilities `json:\"diagnostic,omitempty\"`\n\t// Client capabilities specific to inline completions.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tInlineCompletion *InlineCompletionClientCapabilities `json:\"inlineCompletion,omitempty\"`\n}\n\n// An event describing a change to a text document. If only a text is provided\n// it is considered to be the full content of the document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentChangeEvent\ntype TextDocumentContentChangeEvent = TextDocumentContentChangePartial // (alias)\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentChangePartial\ntype TextDocumentContentChangePartial struct {\n\t// The range of the document that changed.\n\tRange *Range `json:\"range,omitempty\"`\n\t// The optional length of the range that got replaced.\n\t//\n\t// @deprecated use range instead.\n\tRangeLength *uint32 `json:\"rangeLength,omitempty\"`\n\t// The new text for the provided range.\n\tText string `json:\"text\"`\n}\n\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentChangeWholeDocument\ntype TextDocumentContentChangeWholeDocument struct {\n\t// The new text of the whole document.\n\tText string `json:\"text\"`\n}\n\n// Client capabilities for a text document content provider.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentClientCapabilities\ntype TextDocumentContentClientCapabilities struct {\n\t// Text document content provider supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// Text document content provider options.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentOptions\ntype TextDocumentContentOptions struct {\n\t// The schemes for which the server provides content.\n\tSchemes []string `json:\"schemes\"`\n}\n\n// Parameters for the `workspace/textDocumentContent` request.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentParams\ntype TextDocumentContentParams struct {\n\t// The uri of the text document.\n\tURI DocumentURI `json:\"uri\"`\n}\n\n// Parameters for the `workspace/textDocumentContent/refresh` request.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentRefreshParams\ntype TextDocumentContentRefreshParams struct {\n\t// The uri of the text document to refresh.\n\tURI DocumentURI `json:\"uri\"`\n}\n\n// Text document content provider registration options.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentRegistrationOptions\ntype TextDocumentContentRegistrationOptions struct {\n\tTextDocumentContentOptions\n\tStaticRegistrationOptions\n}\n\n// Result of the `workspace/textDocumentContent` request.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentContentResult\ntype TextDocumentContentResult struct {\n\t// The text content of the text document. Please note, that the content of\n\t// any subsequent open notifications for the text document might differ\n\t// from the returned content due to whitespace and line ending\n\t// normalizations done on the client\n\tText string `json:\"text\"`\n}\n\n// Describes textual changes on a text document. A TextDocumentEdit describes all changes\n// on a document version Si and after they are applied move the document to version Si+1.\n// So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any\n// kind of ordering. However the edits must be non overlapping.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentEdit\ntype TextDocumentEdit struct {\n\t// The text document to change.\n\tTextDocument OptionalVersionedTextDocumentIdentifier `json:\"textDocument\"`\n\t// The edits to be applied.\n\t//\n\t// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a\n\t// client capability.\n\t//\n\t// @since 3.18.0 - support for SnippetTextEdit. This is guarded using a\n\t// client capability.\n\tEdits []Or_TextDocumentEdit_edits_Elem `json:\"edits\"`\n}\n\n// A document filter denotes a document by different properties like\n// the {@link TextDocument.languageId language}, the {@link Uri.scheme scheme} of\n// its resource, or a glob-pattern that is applied to the {@link TextDocument.fileName path}.\n//\n// Glob patterns can have the following syntax:\n//\n//   - `*` to match one or more characters in a path segment\n//   - `?` to match on one character in a path segment\n//   - `**` to match any number of path segments, including none\n//   - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)\n//   - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n//   - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)\n//\n// @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }`\n// @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }`\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentFilter\ntype TextDocumentFilter = Or_TextDocumentFilter // (alias)\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentFilterClientCapabilities\ntype TextDocumentFilterClientCapabilities struct {\n\t// The client supports Relative Patterns.\n\t//\n\t// @since 3.18.0\n\tRelativePatternSupport bool `json:\"relativePatternSupport,omitempty\"`\n}\n\n// A document filter where `language` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentFilterLanguage\ntype TextDocumentFilterLanguage struct {\n\t// A language id, like `typescript`.\n\tLanguage string `json:\"language\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme,omitempty\"`\n\t// A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples.\n\t//\n\t// @since 3.18.0 - support for relative patterns. Whether clients support\n\t// relative patterns depends on the client capability\n\t// `textDocuments.filters.relativePatternSupport`.\n\tPattern *GlobPattern `json:\"pattern,omitempty\"`\n}\n\n// A document filter where `pattern` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentFilterPattern\ntype TextDocumentFilterPattern struct {\n\t// A language id, like `typescript`.\n\tLanguage string `json:\"language,omitempty\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme,omitempty\"`\n\t// A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples.\n\t//\n\t// @since 3.18.0 - support for relative patterns. Whether clients support\n\t// relative patterns depends on the client capability\n\t// `textDocuments.filters.relativePatternSupport`.\n\tPattern GlobPattern `json:\"pattern\"`\n}\n\n// A document filter where `scheme` is required field.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentFilterScheme\ntype TextDocumentFilterScheme struct {\n\t// A language id, like `typescript`.\n\tLanguage string `json:\"language,omitempty\"`\n\t// A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.\n\tScheme string `json:\"scheme\"`\n\t// A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples.\n\t//\n\t// @since 3.18.0 - support for relative patterns. Whether clients support\n\t// relative patterns depends on the client capability\n\t// `textDocuments.filters.relativePatternSupport`.\n\tPattern *GlobPattern `json:\"pattern,omitempty\"`\n}\n\n// A literal to identify a text document in the client.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentIdentifier\ntype TextDocumentIdentifier struct {\n\t// The text document's uri.\n\tURI DocumentURI `json:\"uri\"`\n}\n\n// An item to transfer a text document from the client to the\n// server.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentItem\ntype TextDocumentItem struct {\n\t// The text document's uri.\n\tURI DocumentURI `json:\"uri\"`\n\t// The text document's language identifier.\n\tLanguageID LanguageKind `json:\"languageId\"`\n\t// The version number of this document (it will increase after each\n\t// change, including undo/redo).\n\tVersion int32 `json:\"version\"`\n\t// The content of the opened text document.\n\tText string `json:\"text\"`\n}\n\n// A parameter literal used in requests to pass a text document and a position inside that\n// document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentPositionParams\ntype TextDocumentPositionParams struct {\n\t// The text document.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The position inside the text document.\n\t//\n\t// Deprecated: gopls should use [TextDocumentPositionParams.Range] instead.\n\tPosition Position `json:\"position\"`\n\t// Range is an optional field representing the user's text selection in the document.\n\t// If provided, the Position must be contained within this range.\n\t//\n\t// Note: This is a non-standard protocol extension. See microsoft/language-server-protocol#377.\n\tRange Range `json:\"range\"`\n}\n\n// General text document registration options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentRegistrationOptions\ntype TextDocumentRegistrationOptions struct {\n\t// A document selector to identify the scope of the registration. If set to null\n\t// the document selector provided on the client side will be used.\n\tDocumentSelector DocumentSelector `json:\"documentSelector\"`\n}\n\n// Represents reasons why a text document is saved.\ntype TextDocumentSaveReason uint32\n\n// Save registration options.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentSaveRegistrationOptions\ntype TextDocumentSaveRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tSaveOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentSyncClientCapabilities\ntype TextDocumentSyncClientCapabilities struct {\n\t// Whether text document synchronization supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports sending will save notifications.\n\tWillSave bool `json:\"willSave,omitempty\"`\n\t// The client supports sending a will save request and\n\t// waits for a response providing text edits which will\n\t// be applied to the document before it is saved.\n\tWillSaveWaitUntil bool `json:\"willSaveWaitUntil,omitempty\"`\n\t// The client supports did save notifications.\n\tDidSave bool `json:\"didSave,omitempty\"`\n}\n\n// Defines how the host (editor) should sync\n// document changes to the language server.\ntype TextDocumentSyncKind uint32\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocumentSyncOptions\ntype TextDocumentSyncOptions struct {\n\t// Open and close notifications are sent to the server. If omitted open close notification should not\n\t// be sent.\n\tOpenClose bool `json:\"openClose,omitempty\"`\n\t// Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full\n\t// and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.\n\tChange TextDocumentSyncKind `json:\"change,omitempty\"`\n\t// If present will save notifications are sent to the server. If omitted the notification should not be\n\t// sent.\n\tWillSave bool `json:\"willSave,omitempty\"`\n\t// If present will save wait until requests are sent to the server. If omitted the request should not be\n\t// sent.\n\tWillSaveWaitUntil bool `json:\"willSaveWaitUntil,omitempty\"`\n\t// If present save notifications are sent to the server. If omitted the notification should not be\n\t// sent.\n\tSave *SaveOptions `json:\"save,omitempty\"`\n}\n\n// A text edit applicable to a text document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textEdit\ntype TextEdit struct {\n\t// The range of the text document to be manipulated. To insert\n\t// text into a document create a range where start === end.\n\tRange Range `json:\"range\"`\n\t// The string to be inserted. For delete operations use an\n\t// empty string.\n\tNewText string `json:\"newText\"`\n}\ntype TokenFormat string\ntype TraceValue string\n\n// Since 3.6.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeDefinitionClientCapabilities\ntype TypeDefinitionClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `TypeDefinitionRegistrationOptions` return value\n\t// for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// The client supports additional metadata in the form of definition links.\n\t//\n\t// Since 3.14.0\n\tLinkSupport bool `json:\"linkSupport,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeDefinitionOptions\ntype TypeDefinitionOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeDefinitionParams\ntype TypeDefinitionParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeDefinitionRegistrationOptions\ntype TypeDefinitionRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tTypeDefinitionOptions\n\tStaticRegistrationOptions\n}\n\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyClientCapabilities\ntype TypeHierarchyClientCapabilities struct {\n\t// Whether implementation supports dynamic registration. If this is set to `true`\n\t// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`\n\t// return value for the corresponding server capability as well.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n}\n\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyItem\ntype TypeHierarchyItem struct {\n\t// The name of this item.\n\tName string `json:\"name\"`\n\t// The kind of this item.\n\tKind SymbolKind `json:\"kind\"`\n\t// Tags for this item.\n\tTags []SymbolTag `json:\"tags,omitempty\"`\n\t// More detail for this item, e.g. the signature of a function.\n\tDetail string `json:\"detail,omitempty\"`\n\t// The resource identifier of this item.\n\tURI DocumentURI `json:\"uri\"`\n\t// The range enclosing this symbol not including leading/trailing whitespace\n\t// but everything else, e.g. comments and code.\n\tRange Range `json:\"range\"`\n\t// The range that should be selected and revealed when this symbol is being\n\t// picked, e.g. the name of a function. Must be contained by the\n\t// {@link TypeHierarchyItem.range `range`}.\n\tSelectionRange Range `json:\"selectionRange\"`\n\t// A data entry field that is preserved between a type hierarchy prepare and\n\t// supertypes or subtypes requests. It could also be used to identify the\n\t// type hierarchy in the server, helping improve the performance on\n\t// resolving supertypes and subtypes.\n\tData any `json:\"data,omitempty\"`\n}\n\n// Type hierarchy options used during static registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyOptions\ntype TypeHierarchyOptions struct {\n\tWorkDoneProgressOptions\n}\n\n// The parameter of a `textDocument/prepareTypeHierarchy` request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyPrepareParams\ntype TypeHierarchyPrepareParams struct {\n\tTextDocumentPositionParams\n\tWorkDoneProgressParams\n}\n\n// Type hierarchy options used during static or dynamic registration.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyRegistrationOptions\ntype TypeHierarchyRegistrationOptions struct {\n\tTextDocumentRegistrationOptions\n\tTypeHierarchyOptions\n\tStaticRegistrationOptions\n}\n\n// The parameter of a `typeHierarchy/subtypes` request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchySubtypesParams\ntype TypeHierarchySubtypesParams struct {\n\tItem TypeHierarchyItem `json:\"item\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// The parameter of a `typeHierarchy/supertypes` request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchySupertypesParams\ntype TypeHierarchySupertypesParams struct {\n\tItem TypeHierarchyItem `json:\"item\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// created for Tuple\ntype UIntCommaUInt struct {\n\tFld0 uint32 `json:\"fld0\"`\n\tFld1 uint32 `json:\"fld1\"`\n}\n\n// A diagnostic report indicating that the last returned\n// report is still accurate.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#unchangedDocumentDiagnosticReport\ntype UnchangedDocumentDiagnosticReport struct {\n\t// A document diagnostic report indicating\n\t// no changes to the last result. A server can\n\t// only return `unchanged` if result ids are\n\t// provided.\n\tKind string `json:\"kind\"`\n\t// A result id which will be sent on the next\n\t// diagnostic request for the same document.\n\tResultID string `json:\"resultId\"`\n}\n\n// Moniker uniqueness level to define scope of the moniker.\n//\n// @since 3.16.0\ntype UniquenessLevel string\n\n// General parameters to unregister a request or notification.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#unregistration\ntype Unregistration struct {\n\t// The id used to unregister the request or notification. Usually an id\n\t// provided during the register request.\n\tID string `json:\"id\"`\n\t// The method to unregister for.\n\tMethod string `json:\"method\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#unregistrationParams\ntype UnregistrationParams struct {\n\tUnregisterations []Unregistration `json:\"unregisterations\"`\n}\n\n// A versioned notebook document identifier.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#versionedNotebookDocumentIdentifier\ntype VersionedNotebookDocumentIdentifier struct {\n\t// The version number of this notebook document.\n\tVersion int32 `json:\"version\"`\n\t// The notebook document's uri.\n\tURI URI `json:\"uri\"`\n}\n\n// A text document identifier to denote a specific version of a text document.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#versionedTextDocumentIdentifier\ntype VersionedTextDocumentIdentifier struct {\n\t// The version number of this document.\n\tVersion int32 `json:\"version\"`\n\tTextDocumentIdentifier\n}\ntype WatchKind = uint32 // The parameters sent in a will save text document notification.\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#willSaveTextDocumentParams\ntype WillSaveTextDocumentParams struct {\n\t// The document that will be saved.\n\tTextDocument TextDocumentIdentifier `json:\"textDocument\"`\n\t// The 'TextDocumentSaveReason'.\n\tReason TextDocumentSaveReason `json:\"reason\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#windowClientCapabilities\ntype WindowClientCapabilities struct {\n\t// It indicates whether the client supports server initiated\n\t// progress using the `window/workDoneProgress/create` request.\n\t//\n\t// The capability also controls Whether client supports handling\n\t// of progress notifications. If set servers are allowed to report a\n\t// `workDoneProgress` property in the request specific server\n\t// capabilities.\n\t//\n\t// @since 3.15.0\n\tWorkDoneProgress bool `json:\"workDoneProgress,omitempty\"`\n\t// Capabilities specific to the showMessage request.\n\t//\n\t// @since 3.16.0\n\tShowMessage *ShowMessageRequestClientCapabilities `json:\"showMessage,omitempty\"`\n\t// Capabilities specific to the showDocument request.\n\t//\n\t// @since 3.16.0\n\tShowDocument *ShowDocumentClientCapabilities `json:\"showDocument,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressBegin\ntype WorkDoneProgressBegin struct {\n\tKind string `json:\"kind\"`\n\t// Mandatory title of the progress operation. Used to briefly inform about\n\t// the kind of operation being performed.\n\t//\n\t// Examples: \"Indexing\" or \"Linking dependencies\".\n\tTitle string `json:\"title\"`\n\t// Controls if a cancel button should show to allow the user to cancel the\n\t// long running operation. Clients that don't support cancellation are allowed\n\t// to ignore the setting.\n\tCancellable bool `json:\"cancellable,omitempty\"`\n\t// Optional, more detailed associated progress message. Contains\n\t// complementary information to the `title`.\n\t//\n\t// Examples: \"3/25 files\", \"project/src/module2\", \"node_modules/some_dep\".\n\t// If unset, the previous progress message (if any) is still valid.\n\tMessage string `json:\"message,omitempty\"`\n\t// Optional progress percentage to display (value 100 is considered 100%).\n\t// If not provided infinite progress is assumed and clients are allowed\n\t// to ignore the `percentage` value in subsequent in report notifications.\n\t//\n\t// The value should be steadily rising. Clients are free to ignore values\n\t// that are not following this rule. The value range is [0, 100].\n\tPercentage *uint32 `json:\"percentage,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressCancelParams\ntype WorkDoneProgressCancelParams struct {\n\t// The token to be used to report progress.\n\tToken ProgressToken `json:\"token\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressCreateParams\ntype WorkDoneProgressCreateParams struct {\n\t// The token to be used to report progress.\n\tToken ProgressToken `json:\"token\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressEnd\ntype WorkDoneProgressEnd struct {\n\tKind string `json:\"kind\"`\n\t// Optional, a final message indicating to for example indicate the outcome\n\t// of the operation.\n\tMessage string `json:\"message,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressOptions\ntype WorkDoneProgressOptions struct {\n\tWorkDoneProgress bool `json:\"workDoneProgress,omitempty\"`\n}\n\n// created for And\ntype WorkDoneProgressOptionsAndTextDocumentRegistrationOptions struct {\n\tWorkDoneProgressOptions\n\tTextDocumentRegistrationOptions\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressParams\ntype WorkDoneProgressParams struct {\n\t// An optional token that a server can use to report work done progress.\n\tWorkDoneToken ProgressToken `json:\"workDoneToken,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workDoneProgressReport\ntype WorkDoneProgressReport struct {\n\tKind string `json:\"kind\"`\n\t// Controls enablement state of a cancel button.\n\t//\n\t// Clients that don't support cancellation or don't support controlling the button's\n\t// enablement state are allowed to ignore the property.\n\tCancellable bool `json:\"cancellable,omitempty\"`\n\t// Optional, more detailed associated progress message. Contains\n\t// complementary information to the `title`.\n\t//\n\t// Examples: \"3/25 files\", \"project/src/module2\", \"node_modules/some_dep\".\n\t// If unset, the previous progress message (if any) is still valid.\n\tMessage string `json:\"message,omitempty\"`\n\t// Optional progress percentage to display (value 100 is considered 100%).\n\t// If not provided infinite progress is assumed and clients are allowed\n\t// to ignore the `percentage` value in subsequent in report notifications.\n\t//\n\t// The value should be steadily rising. Clients are free to ignore values\n\t// that are not following this rule. The value range is [0, 100]\n\tPercentage *uint32 `json:\"percentage,omitempty\"`\n}\n\n// Workspace specific client capabilities.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceClientCapabilities\ntype WorkspaceClientCapabilities struct {\n\t// The client supports applying batch edits\n\t// to the workspace by supporting the request\n\t// 'workspace/applyEdit'\n\tApplyEdit bool `json:\"applyEdit,omitempty\"`\n\t// Capabilities specific to `WorkspaceEdit`s.\n\tWorkspaceEdit *WorkspaceEditClientCapabilities `json:\"workspaceEdit,omitempty\"`\n\t// Capabilities specific to the `workspace/didChangeConfiguration` notification.\n\tDidChangeConfiguration DidChangeConfigurationClientCapabilities `json:\"didChangeConfiguration,omitempty\"`\n\t// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.\n\tDidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:\"didChangeWatchedFiles,omitempty\"`\n\t// Capabilities specific to the `workspace/symbol` request.\n\tSymbol *WorkspaceSymbolClientCapabilities `json:\"symbol,omitempty\"`\n\t// Capabilities specific to the `workspace/executeCommand` request.\n\tExecuteCommand *ExecuteCommandClientCapabilities `json:\"executeCommand,omitempty\"`\n\t// The client has support for workspace folders.\n\t//\n\t// @since 3.6.0\n\tWorkspaceFolders bool `json:\"workspaceFolders,omitempty\"`\n\t// The client supports `workspace/configuration` requests.\n\t//\n\t// @since 3.6.0\n\tConfiguration bool `json:\"configuration,omitempty\"`\n\t// Capabilities specific to the semantic token requests scoped to the\n\t// workspace.\n\t//\n\t// @since 3.16.0.\n\tSemanticTokens *SemanticTokensWorkspaceClientCapabilities `json:\"semanticTokens,omitempty\"`\n\t// Capabilities specific to the code lens requests scoped to the\n\t// workspace.\n\t//\n\t// @since 3.16.0.\n\tCodeLens *CodeLensWorkspaceClientCapabilities `json:\"codeLens,omitempty\"`\n\t// The client has support for file notifications/requests for user operations on files.\n\t//\n\t// Since 3.16.0\n\tFileOperations *FileOperationClientCapabilities `json:\"fileOperations,omitempty\"`\n\t// Capabilities specific to the inline values requests scoped to the\n\t// workspace.\n\t//\n\t// @since 3.17.0.\n\tInlineValue *InlineValueWorkspaceClientCapabilities `json:\"inlineValue,omitempty\"`\n\t// Capabilities specific to the inlay hint requests scoped to the\n\t// workspace.\n\t//\n\t// @since 3.17.0.\n\tInlayHint *InlayHintWorkspaceClientCapabilities `json:\"inlayHint,omitempty\"`\n\t// Capabilities specific to the diagnostic requests scoped to the\n\t// workspace.\n\t//\n\t// @since 3.17.0.\n\tDiagnostics *DiagnosticWorkspaceClientCapabilities `json:\"diagnostics,omitempty\"`\n\t// Capabilities specific to the folding range requests scoped to the workspace.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tFoldingRange *FoldingRangeWorkspaceClientCapabilities `json:\"foldingRange,omitempty\"`\n\t// Capabilities specific to the `workspace/textDocumentContent` request.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tTextDocumentContent *TextDocumentContentClientCapabilities `json:\"textDocumentContent,omitempty\"`\n}\n\n// Parameters of the workspace diagnostic request.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceDiagnosticParams\ntype WorkspaceDiagnosticParams struct {\n\t// The additional identifier provided during registration.\n\tIdentifier string `json:\"identifier,omitempty\"`\n\t// The currently known diagnostic reports with their\n\t// previous result ids.\n\tPreviousResultIds []PreviousResultID `json:\"previousResultIds\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// A workspace diagnostic report.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceDiagnosticReport\ntype WorkspaceDiagnosticReport struct {\n\tItems []WorkspaceDocumentDiagnosticReport `json:\"items\"`\n}\n\n// A partial result for a workspace diagnostic report.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceDiagnosticReportPartialResult\ntype WorkspaceDiagnosticReportPartialResult struct {\n\tItems []WorkspaceDocumentDiagnosticReport `json:\"items\"`\n}\n\n// A workspace diagnostic document report.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceDocumentDiagnosticReport\ntype WorkspaceDocumentDiagnosticReport = Or_WorkspaceDocumentDiagnosticReport // (alias)\n// A workspace edit represents changes to many resources managed in the workspace. The edit\n// should either provide `changes` or `documentChanges`. If documentChanges are present\n// they are preferred over `changes` if the client can handle versioned document edits.\n//\n// Since version 3.13.0 a workspace edit can contain resource operations as well. If resource\n// operations are present clients need to execute the operations in the order in which they\n// are provided. So a workspace edit for example can consist of the following two changes:\n// (1) a create file a.txt and (2) a text document edit which insert text into file a.txt.\n//\n// An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into file a.txt) will\n// cause failure of the operation. How the client recovers from the failure is described by\n// the client capability: `workspace.workspaceEdit.failureHandling`\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceEdit\ntype WorkspaceEdit struct {\n\t// Holds changes to existing resources.\n\tChanges map[DocumentURI][]TextEdit `json:\"changes,omitempty\"`\n\t// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes\n\t// are either an array of `TextDocumentEdit`s to express changes to n different text documents\n\t// where each text document edit addresses a specific version of a text document. Or it can contain\n\t// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.\n\t//\n\t// Whether a client supports versioned document edits is expressed via\n\t// `workspace.workspaceEdit.documentChanges` client capability.\n\t//\n\t// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then\n\t// only plain `TextEdit`s using the `changes` property are supported.\n\tDocumentChanges []DocumentChange `json:\"documentChanges,omitempty\"`\n\t// A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and\n\t// delete file / folder operations.\n\t//\n\t// Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.\n\t//\n\t// @since 3.16.0\n\tChangeAnnotations map[ChangeAnnotationIdentifier]ChangeAnnotation `json:\"changeAnnotations,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceEditClientCapabilities\ntype WorkspaceEditClientCapabilities struct {\n\t// The client supports versioned document changes in `WorkspaceEdit`s\n\tDocumentChanges bool `json:\"documentChanges,omitempty\"`\n\t// The resource operations the client supports. Clients should at least\n\t// support 'create', 'rename' and 'delete' files and folders.\n\t//\n\t// @since 3.13.0\n\tResourceOperations []ResourceOperationKind `json:\"resourceOperations,omitempty\"`\n\t// The failure handling strategy of a client if applying the workspace edit\n\t// fails.\n\t//\n\t// @since 3.13.0\n\tFailureHandling *FailureHandlingKind `json:\"failureHandling,omitempty\"`\n\t// Whether the client normalizes line endings to the client specific\n\t// setting.\n\t// If set to `true` the client will normalize line ending characters\n\t// in a workspace edit to the client-specified new line\n\t// character.\n\t//\n\t// @since 3.16.0\n\tNormalizesLineEndings bool `json:\"normalizesLineEndings,omitempty\"`\n\t// Whether the client in general supports change annotations on text edits,\n\t// create file, rename file and delete file changes.\n\t//\n\t// @since 3.16.0\n\tChangeAnnotationSupport *ChangeAnnotationsSupportOptions `json:\"changeAnnotationSupport,omitempty\"`\n\t// Whether the client supports `WorkspaceEditMetadata` in `WorkspaceEdit`s.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tMetadataSupport bool `json:\"metadataSupport,omitempty\"`\n\t// Whether the client supports snippets as text edits.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tSnippetEditSupport bool `json:\"snippetEditSupport,omitempty\"`\n}\n\n// Additional data about a workspace edit.\n//\n// @since 3.18.0\n// @proposed\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceEditMetadata\ntype WorkspaceEditMetadata struct {\n\t// Signal to the editor that this edit is a refactoring.\n\tIsRefactoring bool `json:\"isRefactoring,omitempty\"`\n}\n\n// A workspace folder inside a client.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFolder\ntype WorkspaceFolder struct {\n\t// The associated URI for this workspace folder.\n\tURI URI `json:\"uri\"`\n\t// The name of the workspace folder. Used to refer to this\n\t// workspace folder in the user interface.\n\tName string `json:\"name\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFoldersServerCapabilities\ntype WorkspaceFolders5Gn struct {\n\t// The server has support for workspace folders\n\tSupported bool `json:\"supported,omitempty\"`\n\t// Whether the server wants to receive workspace folder\n\t// change notifications.\n\t//\n\t// If a string is provided the string is treated as an ID\n\t// under which the notification is registered on the client\n\t// side. The ID can be used to unregister for these events\n\t// using the `client/unregisterCapability` request.\n\tChangeNotifications string `json:\"changeNotifications,omitempty\"`\n}\n\n// The workspace folder change event.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFoldersChangeEvent\ntype WorkspaceFoldersChangeEvent struct {\n\t// The array of added workspace folders\n\tAdded []WorkspaceFolder `json:\"added\"`\n\t// The array of the removed workspace folders\n\tRemoved []WorkspaceFolder `json:\"removed\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFoldersInitializeParams\ntype WorkspaceFoldersInitializeParams struct {\n\t// The workspace folders configured in the client when the server starts.\n\t//\n\t// This property is only available if the client supports workspace folders.\n\t// It can be `null` if the client supports workspace folders but none are\n\t// configured.\n\t//\n\t// @since 3.6.0\n\tWorkspaceFolders []WorkspaceFolder `json:\"workspaceFolders,omitempty\"`\n}\n\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFoldersServerCapabilities\ntype WorkspaceFoldersServerCapabilities struct {\n\t// The server has support for workspace folders\n\tSupported bool `json:\"supported,omitempty\"`\n\t// Whether the server wants to receive workspace folder\n\t// change notifications.\n\t//\n\t// If a string is provided the string is treated as an ID\n\t// under which the notification is registered on the client\n\t// side. The ID can be used to unregister for these events\n\t// using the `client/unregisterCapability` request.\n\tChangeNotifications string `json:\"changeNotifications,omitempty\"`\n}\n\n// A full document diagnostic report for a workspace diagnostic result.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceFullDocumentDiagnosticReport\ntype WorkspaceFullDocumentDiagnosticReport struct {\n\t// The URI for which diagnostic information is reported.\n\tURI DocumentURI `json:\"uri\"`\n\t// The version number for which the diagnostics are reported.\n\t// If the document is not marked as open `null` can be provided.\n\tVersion int32 `json:\"version\"`\n\tFullDocumentDiagnosticReport\n}\n\n// Defines workspace specific capabilities of the server.\n//\n// @since 3.18.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceOptions\ntype WorkspaceOptions struct {\n\t// The server supports workspace folder.\n\t//\n\t// @since 3.6.0\n\tWorkspaceFolders *WorkspaceFolders5Gn `json:\"workspaceFolders,omitempty\"`\n\t// The server is interested in notifications/requests for operations on files.\n\t//\n\t// @since 3.16.0\n\tFileOperations *FileOperationOptions `json:\"fileOperations,omitempty\"`\n\t// The server supports the `workspace/textDocumentContent` request.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tTextDocumentContent *Or_WorkspaceOptions_textDocumentContent `json:\"textDocumentContent,omitempty\"`\n}\n\n// A special workspace symbol that supports locations without a range.\n//\n// See also SymbolInformation.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbol\ntype WorkspaceSymbol struct {\n\t// The location of the symbol. Whether a server is allowed to\n\t// return a location without a range depends on the client\n\t// capability `workspace.symbol.resolveSupport`.\n\t//\n\t// See SymbolInformation#location for more details.\n\tLocation OrPLocation_workspace_symbol `json:\"location\"`\n\t// A data entry field that is preserved on a workspace symbol between a\n\t// workspace symbol request and a workspace symbol resolve request.\n\tData any `json:\"data,omitempty\"`\n\tBaseSymbolInformation\n}\n\n// Client capabilities for a {@link WorkspaceSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbolClientCapabilities\ntype WorkspaceSymbolClientCapabilities struct {\n\t// Symbol request supports dynamic registration.\n\tDynamicRegistration bool `json:\"dynamicRegistration,omitempty\"`\n\t// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.\n\tSymbolKind *ClientSymbolKindOptions `json:\"symbolKind,omitempty\"`\n\t// The client supports tags on `SymbolInformation`.\n\t// Clients supporting tags have to handle unknown tags gracefully.\n\t//\n\t// @since 3.16.0\n\tTagSupport *ClientSymbolTagOptions `json:\"tagSupport,omitempty\"`\n\t// The client support partial workspace symbols. The client will send the\n\t// request `workspaceSymbol/resolve` to the server to resolve additional\n\t// properties.\n\t//\n\t// @since 3.17.0\n\tResolveSupport *ClientSymbolResolveOptions `json:\"resolveSupport,omitempty\"`\n}\n\n// Server capabilities for a {@link WorkspaceSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbolOptions\ntype WorkspaceSymbolOptions struct {\n\t// The server provides support to resolve additional\n\t// information for a workspace symbol.\n\t//\n\t// @since 3.17.0\n\tResolveProvider bool `json:\"resolveProvider,omitempty\"`\n\tWorkDoneProgressOptions\n}\n\n// The parameters of a {@link WorkspaceSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbolParams\ntype WorkspaceSymbolParams struct {\n\t// A query string to filter symbols by. Clients may send an empty\n\t// string here to request all symbols.\n\t//\n\t// The `query`-parameter should be interpreted in a *relaxed way* as editors\n\t// will apply their own highlighting and scoring on the results. A good rule\n\t// of thumb is to match case-insensitive and to simply check that the\n\t// characters of *query* appear in their order in a candidate symbol.\n\t// Servers shouldn't use prefix, substring, or similar strict matching.\n\tQuery string `json:\"query\"`\n\tWorkDoneProgressParams\n\tPartialResultParams\n}\n\n// Registration options for a {@link WorkspaceSymbolRequest}.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbolRegistrationOptions\ntype WorkspaceSymbolRegistrationOptions struct {\n\tWorkspaceSymbolOptions\n}\n\n// An unchanged document diagnostic report for a workspace diagnostic result.\n//\n// @since 3.17.0\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceUnchangedDocumentDiagnosticReport\ntype WorkspaceUnchangedDocumentDiagnosticReport struct {\n\t// The URI for which diagnostic information is reported.\n\tURI DocumentURI `json:\"uri\"`\n\t// The version number for which the diagnostics are reported.\n\t// If the document is not marked as open `null` can be provided.\n\tVersion int32 `json:\"version\"`\n\tUnchangedDocumentDiagnosticReport\n}\n\n// The initialize parameters\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#_InitializeParams\ntype XInitializeParams struct {\n\t// The process Id of the parent process that started\n\t// the server.\n\t//\n\t// Is `null` if the process has not been started by another process.\n\t// If the parent process is not alive then the server should exit.\n\tProcessID int32 `json:\"processId\"`\n\t// Information about the client\n\t//\n\t// @since 3.15.0\n\tClientInfo *ClientInfo `json:\"clientInfo,omitempty\"`\n\t// The locale the client is currently showing the user interface\n\t// in. This must not necessarily be the locale of the operating\n\t// system.\n\t//\n\t// Uses IETF language tags as the value's syntax\n\t// (See https://en.wikipedia.org/wiki/IETF_language_tag)\n\t//\n\t// @since 3.16.0\n\tLocale string `json:\"locale,omitempty\"`\n\t// The rootPath of the workspace. Is null\n\t// if no folder is open.\n\t//\n\t// @deprecated in favour of rootUri.\n\tRootPath string `json:\"rootPath,omitempty\"`\n\t// The rootUri of the workspace. Is null if no\n\t// folder is open. If both `rootPath` and `rootUri` are set\n\t// `rootUri` wins.\n\t//\n\t// @deprecated in favour of workspaceFolders.\n\tRootURI DocumentURI `json:\"rootUri\"`\n\t// The capabilities provided by the client (editor or tool)\n\tCapabilities ClientCapabilities `json:\"capabilities\"`\n\t// User provided initialization options.\n\tInitializationOptions any `json:\"initializationOptions,omitempty\"`\n\t// The initial trace setting. If omitted trace is disabled ('off').\n\tTrace *TraceValue `json:\"trace,omitempty\"`\n\tWorkDoneProgressParams\n}\n\n// The initialize parameters\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#_InitializeParams\ntype _InitializeParams struct {\n\t// The process Id of the parent process that started\n\t// the server.\n\t//\n\t// Is `null` if the process has not been started by another process.\n\t// If the parent process is not alive then the server should exit.\n\tProcessID int32 `json:\"processId\"`\n\t// Information about the client\n\t//\n\t// @since 3.15.0\n\tClientInfo *ClientInfo `json:\"clientInfo,omitempty\"`\n\t// The locale the client is currently showing the user interface\n\t// in. This must not necessarily be the locale of the operating\n\t// system.\n\t//\n\t// Uses IETF language tags as the value's syntax\n\t// (See https://en.wikipedia.org/wiki/IETF_language_tag)\n\t//\n\t// @since 3.16.0\n\tLocale string `json:\"locale,omitempty\"`\n\t// The rootPath of the workspace. Is null\n\t// if no folder is open.\n\t//\n\t// @deprecated in favour of rootUri.\n\tRootPath string `json:\"rootPath,omitempty\"`\n\t// The rootUri of the workspace. Is null if no\n\t// folder is open. If both `rootPath` and `rootUri` are set\n\t// `rootUri` wins.\n\t//\n\t// @deprecated in favour of workspaceFolders.\n\tRootURI DocumentURI `json:\"rootUri\"`\n\t// The capabilities provided by the client (editor or tool)\n\tCapabilities ClientCapabilities `json:\"capabilities\"`\n\t// User provided initialization options.\n\tInitializationOptions any `json:\"initializationOptions,omitempty\"`\n\t// The initial trace setting. If omitted trace is disabled ('off').\n\tTrace *TraceValue `json:\"trace,omitempty\"`\n\tWorkDoneProgressParams\n}\n\nconst (\n\t// Defines how values from a set of defaults and an individual item will be\n\t// merged.\n\t//\n\t// @since 3.18.0\n\t// The value from the individual item (if provided and not `null`) will be\n\t// used instead of the default.\n\tReplace ApplyKind = 1\n\t// The value from the item will be merged with the default.\n\t//\n\t// The specific rules for mergeing values are defined against each field\n\t// that supports merging.\n\tMerge ApplyKind = 2\n\t// A set of predefined code action kinds\n\t// Empty kind.\n\tEmpty CodeActionKind = \"\"\n\t// Base kind for quickfix actions: 'quickfix'\n\tQuickFix CodeActionKind = \"quickfix\"\n\t// Base kind for refactoring actions: 'refactor'\n\tRefactor CodeActionKind = \"refactor\"\n\t// Base kind for refactoring extraction actions: 'refactor.extract'\n\t//\n\t// Example extract actions:\n\t//\n\t//\n\t//  - Extract method\n\t//  - Extract function\n\t//  - Extract variable\n\t//  - Extract interface from class\n\t//  - ...\n\tRefactorExtract CodeActionKind = \"refactor.extract\"\n\t// Base kind for refactoring inline actions: 'refactor.inline'\n\t//\n\t// Example inline actions:\n\t//\n\t//\n\t//  - Inline function\n\t//  - Inline variable\n\t//  - Inline constant\n\t//  - ...\n\tRefactorInline CodeActionKind = \"refactor.inline\"\n\t// Base kind for refactoring move actions: `refactor.move`\n\t//\n\t// Example move actions:\n\t//\n\t//\n\t//  - Move a function to a new file\n\t//  - Move a property between classes\n\t//  - Move method to base class\n\t//  - ...\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tRefactorMove CodeActionKind = \"refactor.move\"\n\t// Base kind for refactoring rewrite actions: 'refactor.rewrite'\n\t//\n\t// Example rewrite actions:\n\t//\n\t//\n\t//  - Convert JavaScript function to class\n\t//  - Add or remove parameter\n\t//  - Encapsulate field\n\t//  - Make method static\n\t//  - Move method to base class\n\t//  - ...\n\tRefactorRewrite CodeActionKind = \"refactor.rewrite\"\n\t// Base kind for source actions: `source`\n\t//\n\t// Source code actions apply to the entire file.\n\tSource CodeActionKind = \"source\"\n\t// Base kind for an organize imports source action: `source.organizeImports`\n\tSourceOrganizeImports CodeActionKind = \"source.organizeImports\"\n\t// Base kind for auto-fix source actions: `source.fixAll`.\n\t//\n\t// Fix all actions automatically fix errors that have a clear fix that do not require user input.\n\t// They should not suppress errors or perform unsafe fixes such as generating new types or classes.\n\t//\n\t// @since 3.15.0\n\tSourceFixAll CodeActionKind = \"source.fixAll\"\n\t// Base kind for all code actions applying to the entire notebook's scope. CodeActionKinds using\n\t// this should always begin with `notebook.`\n\t//\n\t// @since 3.18.0\n\tNotebook CodeActionKind = \"notebook\"\n\t// Code action tags are extra annotations that tweak the behavior of a code action.\n\t//\n\t// @since 3.18.0 - proposed\n\t// Marks the code action as LLM-generated.\n\tLLMGenerated CodeActionTag = 1\n\t// The reason why code actions were requested.\n\t//\n\t// @since 3.17.0\n\t// Code actions were explicitly requested by the user or by an extension.\n\tCodeActionInvoked CodeActionTriggerKind = 1\n\t// Code actions were requested automatically.\n\t//\n\t// This typically happens when current selection in a file changes, but can\n\t// also be triggered when file content changes.\n\tCodeActionAutomatic CodeActionTriggerKind = 2\n\t// The kind of a completion entry.\n\tTextCompletion          CompletionItemKind = 1\n\tMethodCompletion        CompletionItemKind = 2\n\tFunctionCompletion      CompletionItemKind = 3\n\tConstructorCompletion   CompletionItemKind = 4\n\tFieldCompletion         CompletionItemKind = 5\n\tVariableCompletion      CompletionItemKind = 6\n\tClassCompletion         CompletionItemKind = 7\n\tInterfaceCompletion     CompletionItemKind = 8\n\tModuleCompletion        CompletionItemKind = 9\n\tPropertyCompletion      CompletionItemKind = 10\n\tUnitCompletion          CompletionItemKind = 11\n\tValueCompletion         CompletionItemKind = 12\n\tEnumCompletion          CompletionItemKind = 13\n\tKeywordCompletion       CompletionItemKind = 14\n\tSnippetCompletion       CompletionItemKind = 15\n\tColorCompletion         CompletionItemKind = 16\n\tFileCompletion          CompletionItemKind = 17\n\tReferenceCompletion     CompletionItemKind = 18\n\tFolderCompletion        CompletionItemKind = 19\n\tEnumMemberCompletion    CompletionItemKind = 20\n\tConstantCompletion      CompletionItemKind = 21\n\tStructCompletion        CompletionItemKind = 22\n\tEventCompletion         CompletionItemKind = 23\n\tOperatorCompletion      CompletionItemKind = 24\n\tTypeParameterCompletion CompletionItemKind = 25\n\t// Completion item tags are extra annotations that tweak the rendering of a completion\n\t// item.\n\t//\n\t// @since 3.15.0\n\t// Render a completion as obsolete, usually using a strike-out.\n\tComplDeprecated CompletionItemTag = 1\n\t// How a completion was triggered\n\t// Completion was triggered by typing an identifier (24x7 code\n\t// complete), manual invocation (e.g Ctrl+Space) or via API.\n\tInvoked CompletionTriggerKind = 1\n\t// Completion was triggered by a trigger character specified by\n\t// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.\n\tTriggerCharacter CompletionTriggerKind = 2\n\t// Completion was re-triggered as current completion list is incomplete\n\tTriggerForIncompleteCompletions CompletionTriggerKind = 3\n\t// The diagnostic's severity.\n\t// Reports an error.\n\tSeverityError DiagnosticSeverity = 1\n\t// Reports a warning.\n\tSeverityWarning DiagnosticSeverity = 2\n\t// Reports an information.\n\tSeverityInformation DiagnosticSeverity = 3\n\t// Reports a hint.\n\tSeverityHint DiagnosticSeverity = 4\n\t// The diagnostic tags.\n\t//\n\t// @since 3.15.0\n\t// Unused or unnecessary code.\n\t//\n\t// Clients are allowed to render diagnostics with this tag faded out instead of having\n\t// an error squiggle.\n\tUnnecessary DiagnosticTag = 1\n\t// Deprecated or obsolete code.\n\t//\n\t// Clients are allowed to rendered diagnostics with this tag strike through.\n\tDeprecated DiagnosticTag = 2\n\t// The document diagnostic report kinds.\n\t//\n\t// @since 3.17.0\n\t// A diagnostic report with a full\n\t// set of problems.\n\tDiagnosticFull DocumentDiagnosticReportKind = \"full\"\n\t// A report indicating that the last\n\t// returned report is still accurate.\n\tDiagnosticUnchanged DocumentDiagnosticReportKind = \"unchanged\"\n\t// A document highlight kind.\n\t// A textual occurrence.\n\tText DocumentHighlightKind = 1\n\t// Read-access of a symbol, like reading a variable.\n\tRead DocumentHighlightKind = 2\n\t// Write-access of a symbol, like writing to a variable.\n\tWrite DocumentHighlightKind = 3\n\t// Predefined error codes.\n\tParseError     ErrorCodes = -32700\n\tInvalidRequest ErrorCodes = -32600\n\tMethodNotFound ErrorCodes = -32601\n\tInvalidParams  ErrorCodes = -32602\n\tInternalError  ErrorCodes = -32603\n\t// Error code indicating that a server received a notification or\n\t// request before the server has received the `initialize` request.\n\tServerNotInitialized ErrorCodes = -32002\n\tUnknownErrorCode     ErrorCodes = -32001\n\t// Applying the workspace change is simply aborted if one of the changes provided\n\t// fails. All operations executed before the failing operation stay executed.\n\tAbort FailureHandlingKind = \"abort\"\n\t// All operations are executed transactional. That means they either all\n\t// succeed or no changes at all are applied to the workspace.\n\tTransactional FailureHandlingKind = \"transactional\"\n\t// If the workspace edit contains only textual file changes they are executed transactional.\n\t// If resource changes (create, rename or delete file) are part of the change the failure\n\t// handling strategy is abort.\n\tTextOnlyTransactional FailureHandlingKind = \"textOnlyTransactional\"\n\t// The client tries to undo the operations already executed. But there is no\n\t// guarantee that this is succeeding.\n\tUndo FailureHandlingKind = \"undo\"\n\t// The file event type\n\t// The file got created.\n\tCreated FileChangeType = 1\n\t// The file got changed.\n\tChanged FileChangeType = 2\n\t// The file got deleted.\n\tDeleted FileChangeType = 3\n\t// A pattern kind describing if a glob pattern matches a file a folder or\n\t// both.\n\t//\n\t// @since 3.16.0\n\t// The pattern matches a file only.\n\tFilePattern FileOperationPatternKind = \"file\"\n\t// The pattern matches a folder only.\n\tFolderPattern FileOperationPatternKind = \"folder\"\n\t// A set of predefined range kinds.\n\t// Folding range for a comment\n\tComment FoldingRangeKind = \"comment\"\n\t// Folding range for an import or include\n\tImports FoldingRangeKind = \"imports\"\n\t// Folding range for a region (e.g. `#region`)\n\tRegion FoldingRangeKind = \"region\"\n\t// Inlay hint kinds.\n\t//\n\t// @since 3.17.0\n\t// An inlay hint that for a type annotation.\n\tType InlayHintKind = 1\n\t// An inlay hint that is for a parameter.\n\tParameter InlayHintKind = 2\n\t// Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\t// Completion was triggered explicitly by a user gesture.\n\tInlineInvoked InlineCompletionTriggerKind = 1\n\t// Completion was triggered automatically while editing.\n\tInlineAutomatic InlineCompletionTriggerKind = 2\n\t// Defines whether the insert text in a completion item should be interpreted as\n\t// plain text or a snippet.\n\t// The primary text to be inserted is treated as a plain string.\n\tPlainTextTextFormat InsertTextFormat = 1\n\t// The primary text to be inserted is treated as a snippet.\n\t//\n\t// A snippet can define tab stops and placeholders with `$1`, `$2`\n\t// and `${3:foo}`. `$0` defines the final tab stop, it defaults to\n\t// the end of the snippet. Placeholders with equal identifiers are linked,\n\t// that is typing in one will update others too.\n\t//\n\t// See also: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax\n\tSnippetTextFormat InsertTextFormat = 2\n\t// How whitespace and indentation is handled during completion\n\t// item insertion.\n\t//\n\t// @since 3.16.0\n\t// The insertion or replace strings is taken as it is. If the\n\t// value is multi line the lines below the cursor will be\n\t// inserted using the indentation defined in the string value.\n\t// The client will not apply any kind of adjustments to the\n\t// string.\n\tAsIs InsertTextMode = 1\n\t// The editor adjusts leading whitespace of new lines so that\n\t// they match the indentation up to the cursor of the line for\n\t// which the item is accepted.\n\t//\n\t// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a\n\t// multi line completion item is indented using 2 tabs and all\n\t// following lines inserted will be indented using 2 tabs as well.\n\tAdjustIndentation InsertTextMode = 2\n\t// A request failed but it was syntactically correct, e.g the\n\t// method name was known and the parameters were valid. The error\n\t// message should contain human readable information about why\n\t// the request failed.\n\t//\n\t// @since 3.17.0\n\tRequestFailed LSPErrorCodes = -32803\n\t// The server cancelled the request. This error code should\n\t// only be used for requests that explicitly support being\n\t// server cancellable.\n\t//\n\t// @since 3.17.0\n\tServerCancelled LSPErrorCodes = -32802\n\t// The server detected that the content of a document got\n\t// modified outside normal conditions. A server should\n\t// NOT send this error code if it detects a content change\n\t// in it unprocessed messages. The result even computed\n\t// on an older state might still be useful for the client.\n\t//\n\t// If a client decides that a result is not of any use anymore\n\t// the client should cancel the request.\n\tContentModified LSPErrorCodes = -32801\n\t// The client has canceled a request and a server has detected\n\t// the cancel.\n\tRequestCancelled LSPErrorCodes = -32800\n\t// Predefined Language kinds\n\t// @since 3.18.0\n\tLangABAP         LanguageKind = \"abap\"\n\tLangWindowsBat   LanguageKind = \"bat\"\n\tLangBibTeX       LanguageKind = \"bibtex\"\n\tLangClojure      LanguageKind = \"clojure\"\n\tLangCoffeescript LanguageKind = \"coffeescript\"\n\tLangC            LanguageKind = \"c\"\n\tLangCPP          LanguageKind = \"cpp\"\n\tLangCSharp       LanguageKind = \"csharp\"\n\tLangCSS          LanguageKind = \"css\"\n\t// @since 3.18.0\n\t// @proposed\n\tLangD LanguageKind = \"d\"\n\t// @since 3.18.0\n\t// @proposed\n\tLangDelphi          LanguageKind = \"pascal\"\n\tLangDiff            LanguageKind = \"diff\"\n\tLangDart            LanguageKind = \"dart\"\n\tLangDockerfile      LanguageKind = \"dockerfile\"\n\tLangElixir          LanguageKind = \"elixir\"\n\tLangErlang          LanguageKind = \"erlang\"\n\tLangFSharp          LanguageKind = \"fsharp\"\n\tLangGitCommit       LanguageKind = \"git-commit\"\n\tLangGitRebase       LanguageKind = \"rebase\"\n\tLangGo              LanguageKind = \"go\"\n\tLangGroovy          LanguageKind = \"groovy\"\n\tLangHandlebars      LanguageKind = \"handlebars\"\n\tLangHaskell         LanguageKind = \"haskell\"\n\tLangHTML            LanguageKind = \"html\"\n\tLangIni             LanguageKind = \"ini\"\n\tLangJava            LanguageKind = \"java\"\n\tLangJavaScript      LanguageKind = \"javascript\"\n\tLangJavaScriptReact LanguageKind = \"javascriptreact\"\n\tLangJSON            LanguageKind = \"json\"\n\tLangLaTeX           LanguageKind = \"latex\"\n\tLangLess            LanguageKind = \"less\"\n\tLangLua             LanguageKind = \"lua\"\n\tLangMakefile        LanguageKind = \"makefile\"\n\tLangMarkdown        LanguageKind = \"markdown\"\n\tLangObjectiveC      LanguageKind = \"objective-c\"\n\tLangObjectiveCPP    LanguageKind = \"objective-cpp\"\n\t// @since 3.18.0\n\t// @proposed\n\tLangPascal          LanguageKind = \"pascal\"\n\tLangPerl            LanguageKind = \"perl\"\n\tLangPerl6           LanguageKind = \"perl6\"\n\tLangPHP             LanguageKind = \"php\"\n\tLangPowershell      LanguageKind = \"powershell\"\n\tLangPug             LanguageKind = \"jade\"\n\tLangPython          LanguageKind = \"python\"\n\tLangR               LanguageKind = \"r\"\n\tLangRazor           LanguageKind = \"razor\"\n\tLangRuby            LanguageKind = \"ruby\"\n\tLangRust            LanguageKind = \"rust\"\n\tLangSCSS            LanguageKind = \"scss\"\n\tLangSASS            LanguageKind = \"sass\"\n\tLangScala           LanguageKind = \"scala\"\n\tLangShaderLab       LanguageKind = \"shaderlab\"\n\tLangShellScript     LanguageKind = \"shellscript\"\n\tLangSQL             LanguageKind = \"sql\"\n\tLangSwift           LanguageKind = \"swift\"\n\tLangTypeScript      LanguageKind = \"typescript\"\n\tLangTypeScriptReact LanguageKind = \"typescriptreact\"\n\tLangTeX             LanguageKind = \"tex\"\n\tLangVisualBasic     LanguageKind = \"vb\"\n\tLangXML             LanguageKind = \"xml\"\n\tLangXSL             LanguageKind = \"xsl\"\n\tLangYAML            LanguageKind = \"yaml\"\n\t// Describes the content type that a client supports in various\n\t// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.\n\t//\n\t// Please note that `MarkupKinds` must not start with a `$`. This kinds\n\t// are reserved for internal usage.\n\t// Plain text is supported as a content format\n\tPlainText MarkupKind = \"plaintext\"\n\t// Markdown is supported as a content format\n\tMarkdown MarkupKind = \"markdown\"\n\t// The message type\n\t// An error message.\n\tError MessageType = 1\n\t// A warning message.\n\tWarning MessageType = 2\n\t// An information message.\n\tInfo MessageType = 3\n\t// A log message.\n\tLog MessageType = 4\n\t// A debug message.\n\t//\n\t// @since 3.18.0\n\t// @proposed\n\tDebug MessageType = 5\n\t// The moniker kind.\n\t//\n\t// @since 3.16.0\n\t// The moniker represent a symbol that is imported into a project\n\tImport MonikerKind = \"import\"\n\t// The moniker represents a symbol that is exported from a project\n\tExport MonikerKind = \"export\"\n\t// The moniker represents a symbol that is local to a project (e.g. a local\n\t// variable of a function, a class not visible outside the project, ...)\n\tLocal MonikerKind = \"local\"\n\t// A notebook cell kind.\n\t//\n\t// @since 3.17.0\n\t// A markup-cell is formatted source that is used for display.\n\tMarkup NotebookCellKind = 1\n\t// A code-cell is source code.\n\tCode NotebookCellKind = 2\n\t// A set of predefined position encoding kinds.\n\t//\n\t// @since 3.17.0\n\t// Character offsets count UTF-8 code units (e.g. bytes).\n\tUTF8 PositionEncodingKind = \"utf-8\"\n\t// Character offsets count UTF-16 code units.\n\t//\n\t// This is the default and must always be supported\n\t// by servers\n\tUTF16 PositionEncodingKind = \"utf-16\"\n\t// Character offsets count UTF-32 code units.\n\t//\n\t// Implementation note: these are the same as Unicode codepoints,\n\t// so this `PositionEncodingKind` may also be used for an\n\t// encoding-agnostic representation of character offsets.\n\tUTF32 PositionEncodingKind = \"utf-32\"\n\t// The client's default behavior is to select the identifier\n\t// according the to language's syntax rule.\n\tIdentifier PrepareSupportDefaultBehavior = 1\n\t// Supports creating new files and folders.\n\tCreate ResourceOperationKind = \"create\"\n\t// Supports renaming existing files and folders.\n\tRename ResourceOperationKind = \"rename\"\n\t// Supports deleting existing files and folders.\n\tDelete ResourceOperationKind = \"delete\"\n\t// A set of predefined token modifiers. This set is not fixed\n\t// an clients can specify additional token types via the\n\t// corresponding client capabilities.\n\t//\n\t// @since 3.16.0\n\tModDeclaration    SemanticTokenModifiers = \"declaration\"\n\tModDefinition     SemanticTokenModifiers = \"definition\"\n\tModReadonly       SemanticTokenModifiers = \"readonly\"\n\tModStatic         SemanticTokenModifiers = \"static\"\n\tModDeprecated     SemanticTokenModifiers = \"deprecated\"\n\tModAbstract       SemanticTokenModifiers = \"abstract\"\n\tModAsync          SemanticTokenModifiers = \"async\"\n\tModModification   SemanticTokenModifiers = \"modification\"\n\tModDocumentation  SemanticTokenModifiers = \"documentation\"\n\tModDefaultLibrary SemanticTokenModifiers = \"defaultLibrary\"\n\t// A set of predefined token types. This set is not fixed\n\t// an clients can specify additional token types via the\n\t// corresponding client capabilities.\n\t//\n\t// @since 3.16.0\n\tNamespaceType SemanticTokenTypes = \"namespace\"\n\t// Represents a generic type. Acts as a fallback for types which can't be mapped to\n\t// a specific type like class or enum.\n\tTypeType          SemanticTokenTypes = \"type\"\n\tClassType         SemanticTokenTypes = \"class\"\n\tEnumType          SemanticTokenTypes = \"enum\"\n\tInterfaceType     SemanticTokenTypes = \"interface\"\n\tStructType        SemanticTokenTypes = \"struct\"\n\tTypeParameterType SemanticTokenTypes = \"typeParameter\"\n\tParameterType     SemanticTokenTypes = \"parameter\"\n\tVariableType      SemanticTokenTypes = \"variable\"\n\tPropertyType      SemanticTokenTypes = \"property\"\n\tEnumMemberType    SemanticTokenTypes = \"enumMember\"\n\tEventType         SemanticTokenTypes = \"event\"\n\tFunctionType      SemanticTokenTypes = \"function\"\n\tMethodType        SemanticTokenTypes = \"method\"\n\tMacroType         SemanticTokenTypes = \"macro\"\n\tKeywordType       SemanticTokenTypes = \"keyword\"\n\tModifierType      SemanticTokenTypes = \"modifier\"\n\tCommentType       SemanticTokenTypes = \"comment\"\n\tStringType        SemanticTokenTypes = \"string\"\n\tNumberType        SemanticTokenTypes = \"number\"\n\tRegexpType        SemanticTokenTypes = \"regexp\"\n\tOperatorType      SemanticTokenTypes = \"operator\"\n\t// @since 3.17.0\n\tDecoratorType SemanticTokenTypes = \"decorator\"\n\t// @since 3.18.0\n\tLabelType SemanticTokenTypes = \"label\"\n\t// How a signature help was triggered.\n\t//\n\t// @since 3.15.0\n\t// Signature help was invoked manually by the user or by a command.\n\tSigInvoked SignatureHelpTriggerKind = 1\n\t// Signature help was triggered by a trigger character.\n\tSigTriggerCharacter SignatureHelpTriggerKind = 2\n\t// Signature help was triggered by the cursor moving or by the document content changing.\n\tSigContentChange SignatureHelpTriggerKind = 3\n\t// A symbol kind.\n\tFile          SymbolKind = 1\n\tModule        SymbolKind = 2\n\tNamespace     SymbolKind = 3\n\tPackage       SymbolKind = 4\n\tClass         SymbolKind = 5\n\tMethod        SymbolKind = 6\n\tProperty      SymbolKind = 7\n\tField         SymbolKind = 8\n\tConstructor   SymbolKind = 9\n\tEnum          SymbolKind = 10\n\tInterface     SymbolKind = 11\n\tFunction      SymbolKind = 12\n\tVariable      SymbolKind = 13\n\tConstant      SymbolKind = 14\n\tString        SymbolKind = 15\n\tNumber        SymbolKind = 16\n\tBoolean       SymbolKind = 17\n\tArray         SymbolKind = 18\n\tObject        SymbolKind = 19\n\tKey           SymbolKind = 20\n\tNull          SymbolKind = 21\n\tEnumMember    SymbolKind = 22\n\tStruct        SymbolKind = 23\n\tEvent         SymbolKind = 24\n\tOperator      SymbolKind = 25\n\tTypeParameter SymbolKind = 26\n\t// Symbol tags are extra annotations that tweak the rendering of a symbol.\n\t//\n\t// @since 3.16\n\t// Render a symbol as obsolete, usually using a strike-out.\n\tDeprecatedSymbol SymbolTag = 1\n\t// Represents reasons why a text document is saved.\n\t// Manually triggered, e.g. by the user pressing save, by starting debugging,\n\t// or by an API call.\n\tManual TextDocumentSaveReason = 1\n\t// Automatic after a delay.\n\tAfterDelay TextDocumentSaveReason = 2\n\t// When the editor lost focus.\n\tFocusOut TextDocumentSaveReason = 3\n\t// Defines how the host (editor) should sync\n\t// document changes to the language server.\n\t// Documents should not be synced at all.\n\tNone TextDocumentSyncKind = 0\n\t// Documents are synced by always sending the full content\n\t// of the document.\n\tFull TextDocumentSyncKind = 1\n\t// Documents are synced by sending the full content on open.\n\t// After that only incremental updates to the document are\n\t// send.\n\tIncremental TextDocumentSyncKind = 2\n\tRelative    TokenFormat          = \"relative\"\n\t// Turn tracing off.\n\tOff TraceValue = \"off\"\n\t// Trace messages only.\n\tMessages TraceValue = \"messages\"\n\t// Verbose message tracing.\n\tVerbose TraceValue = \"verbose\"\n\t// Moniker uniqueness level to define scope of the moniker.\n\t//\n\t// @since 3.16.0\n\t// The moniker is only unique inside a document\n\tDocument UniquenessLevel = \"document\"\n\t// The moniker is unique inside a project for which a dump got created\n\tProject UniquenessLevel = \"project\"\n\t// The moniker is unique inside the group to which a project belongs\n\tGroup UniquenessLevel = \"group\"\n\t// The moniker is unique inside the moniker scheme.\n\tScheme UniquenessLevel = \"scheme\"\n\t// The moniker is globally unique\n\tGlobal UniquenessLevel = \"global\"\n\t// Interested in create events.\n\tWatchCreate WatchKind = 1\n\t// Interested in change events\n\tWatchChange WatchKind = 2\n\t// Interested in delete events\n\tWatchDelete WatchKind = 4\n)\n"
  },
  {
    "path": "gopls/internal/protocol/tsserver.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated for LSP. DO NOT EDIT.\n\npackage protocol\n\n// Code generated from protocol/metaModel.json at ref release/protocol/3.17.6-next.14 (hash 66a087310eea0d60495ba3578d78f70409c403d9).\n// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.17.6-next.14/protocol/metaModel.json\n// LSP metaData.version = 3.17.0.\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\ntype Server interface {\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#progress\n\tProgress(context.Context, *ProgressParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#setTrace\n\tSetTrace(context.Context, *SetTraceParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls\n\tIncomingCalls(context.Context, *CallHierarchyIncomingCallsParams) ([]CallHierarchyIncomingCall, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_outgoingCalls\n\tOutgoingCalls(context.Context, *CallHierarchyOutgoingCallsParams) ([]CallHierarchyOutgoingCall, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeAction_resolve\n\tResolveCodeAction(context.Context, *CodeAction) (*CodeAction, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#codeLens_resolve\n\tResolveCodeLens(context.Context, *CodeLens) (*CodeLens, error)\n\t// To support microsoft/language-server-protocol#1164, the language server\n\t// need to read the form with client-supplied answers and either returns an\n\t// ExecuteCommandParams with errors in the form surfacing the error to the\n\t// client, or an ExecuteCommandParams with interactive properties empty (e.g\n\t// formFields, formAnswers) and user information integrated in original\n\t// properties.\n\t//\n\t// The language client may call \"command/resolve\" if the language server\n\t// returns an ExecuteCommandParams with errors or try asking the user for\n\t// completing the form again.\n\t// The language client may call \"command/resolve\" multiple times with user\n\t// filled (re-filled) answers in the form until it obtains an\n\t// ExecuteCommandParams with interactive properties empty (e.g. formFields,\n\t// formAnswers). by then the original properties contains all information,\n\t// the client can call \"workspace/executeCommand\" with the same param.\n\t//\n\t// Standard resolution (e.g., \"codeAction/resolve\") cannot be used here because\n\t// it is often triggered eagerly (e.g., for previews), prohibiting interactive\n\t// forms. \"command/resolve\" is introduced to handle the interactive flow\n\t// strictly *after* the user has explicitly indicated intention (e.g., by\n\t// clicking), making it safe for Code Actions and other refactorings.\n\t//\n\t// Note: This is a non-standard protocol extension.\n\tResolveCommand(context.Context, *ExecuteCommandParams) (*ExecuteCommandParams, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#completionItem_resolve\n\tResolveCompletionItem(context.Context, *CompletionItem) (*CompletionItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentLink_resolve\n\tResolveDocumentLink(context.Context, *DocumentLink) (*DocumentLink, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#exit\n\tExit(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initialize\n\tInitialize(context.Context, *ParamInitialize) (*InitializeResult, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#initialized\n\tInitialized(context.Context, *InitializedParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#inlayHint_resolve\n\tResolve(context.Context, *InlayHint) (*InlayHint, error)\n\t// InteractiveListEnum is the request handler for fetching dynamic enum options.\n\t//\n\t// This method is called by the client when the user interacts with a\n\t// FormFieldTypeLazyEnum field (e.g., typing in a combo box). The server\n\t// uses the provided Action and Params to determine the context (e.g.,\n\t// \"search workspace symbols for interfaces\") and returns a filtered list\n\t// of matching entries.\n\t//\n\t// Note: This is a non-standard protocol extension.\n\tInteractiveListEnum(context.Context, *InteractiveListEnumParams) ([]FormEnumEntry, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocument_didChange\n\tDidChangeNotebookDocument(context.Context, *DidChangeNotebookDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocument_didClose\n\tDidCloseNotebookDocument(context.Context, *DidCloseNotebookDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocument_didOpen\n\tDidOpenNotebookDocument(context.Context, *DidOpenNotebookDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#notebookDocument_didSave\n\tDidSaveNotebookDocument(context.Context, *DidSaveNotebookDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#shutdown\n\tShutdown(context.Context) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_codeAction\n\tCodeAction(context.Context, *CodeActionParams) ([]CodeAction, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_codeLens\n\tCodeLens(context.Context, *CodeLensParams) ([]CodeLens, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_colorPresentation\n\tColorPresentation(context.Context, *ColorPresentationParams) ([]ColorPresentation, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_completion\n\tCompletion(context.Context, *CompletionParams) (*CompletionList, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_declaration\n\tDeclaration(context.Context, *DeclarationParams) (*Or_textDocument_declaration, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_definition\n\tDefinition(context.Context, *DefinitionParams) ([]Location, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_diagnostic\n\tDiagnostic(context.Context, *DocumentDiagnosticParams) (*DocumentDiagnosticReport, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_didChange\n\tDidChange(context.Context, *DidChangeTextDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_didClose\n\tDidClose(context.Context, *DidCloseTextDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_didOpen\n\tDidOpen(context.Context, *DidOpenTextDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_didSave\n\tDidSave(context.Context, *DidSaveTextDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_documentColor\n\tDocumentColor(context.Context, *DocumentColorParams) ([]ColorInformation, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_documentHighlight\n\tDocumentHighlight(context.Context, *DocumentHighlightParams) ([]DocumentHighlight, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_documentLink\n\tDocumentLink(context.Context, *DocumentLinkParams) ([]DocumentLink, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_documentSymbol\n\tDocumentSymbol(context.Context, *DocumentSymbolParams) ([]any, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_foldingRange\n\tFoldingRange(context.Context, *FoldingRangeParams) ([]FoldingRange, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_formatting\n\tFormatting(context.Context, *DocumentFormattingParams) ([]TextEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_hover\n\tHover(context.Context, *HoverParams) (*Hover, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_implementation\n\tImplementation(context.Context, *ImplementationParams) ([]Location, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_inlayHint\n\tInlayHint(context.Context, *InlayHintParams) ([]InlayHint, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_inlineCompletion\n\tInlineCompletion(context.Context, *InlineCompletionParams) (*Or_Result_textDocument_inlineCompletion, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_inlineValue\n\tInlineValue(context.Context, *InlineValueParams) ([]InlineValue, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_linkedEditingRange\n\tLinkedEditingRange(context.Context, *LinkedEditingRangeParams) (*LinkedEditingRanges, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_moniker\n\tMoniker(context.Context, *MonikerParams) ([]Moniker, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_onTypeFormatting\n\tOnTypeFormatting(context.Context, *DocumentOnTypeFormattingParams) ([]TextEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareCallHierarchy\n\tPrepareCallHierarchy(context.Context, *CallHierarchyPrepareParams) ([]CallHierarchyItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareRename\n\tPrepareRename(context.Context, *PrepareRenameParams) (*PrepareRenameResult, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareTypeHierarchy\n\tPrepareTypeHierarchy(context.Context, *TypeHierarchyPrepareParams) ([]TypeHierarchyItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_rangeFormatting\n\tRangeFormatting(context.Context, *DocumentRangeFormattingParams) ([]TextEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_rangesFormatting\n\tRangesFormatting(context.Context, *DocumentRangesFormattingParams) ([]TextEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_references\n\tReferences(context.Context, *ReferenceParams) ([]Location, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_rename\n\tRename(context.Context, *RenameParams) (*WorkspaceEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_selectionRange\n\tSelectionRange(context.Context, *SelectionRangeParams) ([]SelectionRange, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_semanticTokens_full\n\tSemanticTokensFull(context.Context, *SemanticTokensParams) (*SemanticTokens, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_semanticTokens_full_delta\n\tSemanticTokensFullDelta(context.Context, *SemanticTokensDeltaParams) (any, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_semanticTokens_range\n\tSemanticTokensRange(context.Context, *SemanticTokensRangeParams) (*SemanticTokens, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_signatureHelp\n\tSignatureHelp(context.Context, *SignatureHelpParams) (*SignatureHelp, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_typeDefinition\n\tTypeDefinition(context.Context, *TypeDefinitionParams) ([]Location, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_willSave\n\tWillSave(context.Context, *WillSaveTextDocumentParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_willSaveWaitUntil\n\tWillSaveWaitUntil(context.Context, *WillSaveTextDocumentParams) ([]TextEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_subtypes\n\tSubtypes(context.Context, *TypeHierarchySubtypesParams) ([]TypeHierarchyItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_supertypes\n\tSupertypes(context.Context, *TypeHierarchySupertypesParams) ([]TypeHierarchyItem, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#window_workDoneProgress_cancel\n\tWorkDoneProgressCancel(context.Context, *WorkDoneProgressCancelParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_diagnostic\n\tDiagnosticWorkspace(context.Context, *WorkspaceDiagnosticParams) (*WorkspaceDiagnosticReport, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didChangeConfiguration\n\tDidChangeConfiguration(context.Context, *DidChangeConfigurationParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didChangeWatchedFiles\n\tDidChangeWatchedFiles(context.Context, *DidChangeWatchedFilesParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didChangeWorkspaceFolders\n\tDidChangeWorkspaceFolders(context.Context, *DidChangeWorkspaceFoldersParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didCreateFiles\n\tDidCreateFiles(context.Context, *CreateFilesParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didDeleteFiles\n\tDidDeleteFiles(context.Context, *DeleteFilesParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_didRenameFiles\n\tDidRenameFiles(context.Context, *RenameFilesParams) error\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_executeCommand\n\tExecuteCommand(context.Context, *ExecuteCommandParams) (any, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_symbol\n\tSymbol(context.Context, *WorkspaceSymbolParams) ([]SymbolInformation, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_textDocumentContent\n\tTextDocumentContent(context.Context, *TextDocumentContentParams) (*TextDocumentContentResult, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_willCreateFiles\n\tWillCreateFiles(context.Context, *CreateFilesParams) (*WorkspaceEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_willDeleteFiles\n\tWillDeleteFiles(context.Context, *DeleteFilesParams) (*WorkspaceEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_willRenameFiles\n\tWillRenameFiles(context.Context, *RenameFilesParams) (*WorkspaceEdit, error)\n\t// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspaceSymbol_resolve\n\tResolveWorkspaceSymbol(context.Context, *WorkspaceSymbol) (*WorkspaceSymbol, error)\n}\n\nfunc serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {\n\tresp, valid, err := ServerDispatchCall(ctx, server, r.Method(), r.Params())\n\tif !valid {\n\t\treturn false, nil\n\t}\n\n\tif err != nil {\n\t\treturn valid, reply(ctx, nil, err)\n\t} else {\n\t\treturn valid, reply(ctx, resp, nil)\n\t}\n}\n\nfunc ServerDispatchCall(ctx context.Context, server Server, method string, raw json.RawMessage) (resp any, _ bool, err error) {\n\tswitch method {\n\tcase \"$/progress\":\n\t\tvar params ProgressParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.Progress(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"$/setTrace\":\n\t\tvar params SetTraceParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.SetTrace(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"callHierarchy/incomingCalls\":\n\t\tvar params CallHierarchyIncomingCallsParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.IncomingCalls(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"callHierarchy/outgoingCalls\":\n\t\tvar params CallHierarchyOutgoingCallsParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.OutgoingCalls(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"codeAction/resolve\":\n\t\tvar params CodeAction\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveCodeAction(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"codeLens/resolve\":\n\t\tvar params CodeLens\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveCodeLens(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"command/resolve\":\n\t\tvar params ExecuteCommandParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveCommand(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"completionItem/resolve\":\n\t\tvar params CompletionItem\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveCompletionItem(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"documentLink/resolve\":\n\t\tvar params DocumentLink\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveDocumentLink(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"exit\":\n\t\terr := server.Exit(ctx)\n\t\treturn nil, true, err\n\n\tcase \"initialize\":\n\t\tvar params ParamInitialize\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Initialize(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"initialized\":\n\t\tvar params InitializedParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.Initialized(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"inlayHint/resolve\":\n\t\tvar params InlayHint\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Resolve(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"interactive/listEnum\":\n\t\tvar params InteractiveListEnumParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.InteractiveListEnum(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"notebookDocument/didChange\":\n\t\tvar params DidChangeNotebookDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidChangeNotebookDocument(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"notebookDocument/didClose\":\n\t\tvar params DidCloseNotebookDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidCloseNotebookDocument(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"notebookDocument/didOpen\":\n\t\tvar params DidOpenNotebookDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidOpenNotebookDocument(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"notebookDocument/didSave\":\n\t\tvar params DidSaveNotebookDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidSaveNotebookDocument(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"shutdown\":\n\t\terr := server.Shutdown(ctx)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/codeAction\":\n\t\tvar params CodeActionParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.CodeAction(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/codeLens\":\n\t\tvar params CodeLensParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.CodeLens(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/colorPresentation\":\n\t\tvar params ColorPresentationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ColorPresentation(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/completion\":\n\t\tvar params CompletionParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Completion(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/declaration\":\n\t\tvar params DeclarationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Declaration(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/definition\":\n\t\tvar params DefinitionParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Definition(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/diagnostic\":\n\t\tvar params DocumentDiagnosticParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Diagnostic(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/didChange\":\n\t\tvar params DidChangeTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidChange(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/didClose\":\n\t\tvar params DidCloseTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidClose(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/didOpen\":\n\t\tvar params DidOpenTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidOpen(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/didSave\":\n\t\tvar params DidSaveTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidSave(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/documentColor\":\n\t\tvar params DocumentColorParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.DocumentColor(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/documentHighlight\":\n\t\tvar params DocumentHighlightParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.DocumentHighlight(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/documentLink\":\n\t\tvar params DocumentLinkParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.DocumentLink(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/documentSymbol\":\n\t\tvar params DocumentSymbolParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.DocumentSymbol(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/foldingRange\":\n\t\tvar params FoldingRangeParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.FoldingRange(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/formatting\":\n\t\tvar params DocumentFormattingParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Formatting(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/hover\":\n\t\tvar params HoverParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Hover(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/implementation\":\n\t\tvar params ImplementationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Implementation(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/inlayHint\":\n\t\tvar params InlayHintParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.InlayHint(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/inlineCompletion\":\n\t\tvar params InlineCompletionParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.InlineCompletion(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/inlineValue\":\n\t\tvar params InlineValueParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.InlineValue(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/linkedEditingRange\":\n\t\tvar params LinkedEditingRangeParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.LinkedEditingRange(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/moniker\":\n\t\tvar params MonikerParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Moniker(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/onTypeFormatting\":\n\t\tvar params DocumentOnTypeFormattingParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.OnTypeFormatting(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/prepareCallHierarchy\":\n\t\tvar params CallHierarchyPrepareParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.PrepareCallHierarchy(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/prepareRename\":\n\t\tvar params PrepareRenameParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.PrepareRename(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/prepareTypeHierarchy\":\n\t\tvar params TypeHierarchyPrepareParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.PrepareTypeHierarchy(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/rangeFormatting\":\n\t\tvar params DocumentRangeFormattingParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.RangeFormatting(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/rangesFormatting\":\n\t\tvar params DocumentRangesFormattingParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.RangesFormatting(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/references\":\n\t\tvar params ReferenceParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.References(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/rename\":\n\t\tvar params RenameParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.Rename(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/selectionRange\":\n\t\tvar params SelectionRangeParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.SelectionRange(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/semanticTokens/full\":\n\t\tvar params SemanticTokensParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.SemanticTokensFull(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/semanticTokens/full/delta\":\n\t\tvar params SemanticTokensDeltaParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.SemanticTokensFullDelta(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/semanticTokens/range\":\n\t\tvar params SemanticTokensRangeParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.SemanticTokensRange(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/signatureHelp\":\n\t\tvar params SignatureHelpParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.SignatureHelp(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/typeDefinition\":\n\t\tvar params TypeDefinitionParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tif params.Range == (Range{}) {\n\t\t\tparams.Range = Range{\n\t\t\t\tStart: params.Position,\n\t\t\t\tEnd:   params.Position,\n\t\t\t}\n\t\t} else if !params.Range.Contains(params.Position) {\n\t\t\treturn nil, true, fmt.Errorf(\"position %v is outside the provided range %v.\", params.Position, params.Range)\n\t\t}\n\t\tresp, err := server.TypeDefinition(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"textDocument/willSave\":\n\t\tvar params WillSaveTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.WillSave(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"textDocument/willSaveWaitUntil\":\n\t\tvar params WillSaveTextDocumentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.WillSaveWaitUntil(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"typeHierarchy/subtypes\":\n\t\tvar params TypeHierarchySubtypesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Subtypes(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"typeHierarchy/supertypes\":\n\t\tvar params TypeHierarchySupertypesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Supertypes(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"window/workDoneProgress/cancel\":\n\t\tvar params WorkDoneProgressCancelParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.WorkDoneProgressCancel(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/diagnostic\":\n\t\tvar params WorkspaceDiagnosticParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.DiagnosticWorkspace(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/didChangeConfiguration\":\n\t\tvar params DidChangeConfigurationParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidChangeConfiguration(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/didChangeWatchedFiles\":\n\t\tvar params DidChangeWatchedFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidChangeWatchedFiles(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/didChangeWorkspaceFolders\":\n\t\tvar params DidChangeWorkspaceFoldersParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidChangeWorkspaceFolders(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/didCreateFiles\":\n\t\tvar params CreateFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidCreateFiles(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/didDeleteFiles\":\n\t\tvar params DeleteFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidDeleteFiles(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/didRenameFiles\":\n\t\tvar params RenameFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\terr := server.DidRenameFiles(ctx, &params)\n\t\treturn nil, true, err\n\n\tcase \"workspace/executeCommand\":\n\t\tvar params ExecuteCommandParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ExecuteCommand(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/symbol\":\n\t\tvar params WorkspaceSymbolParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.Symbol(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/textDocumentContent\":\n\t\tvar params TextDocumentContentParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.TextDocumentContent(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/willCreateFiles\":\n\t\tvar params CreateFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.WillCreateFiles(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/willDeleteFiles\":\n\t\tvar params DeleteFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.WillDeleteFiles(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspace/willRenameFiles\":\n\t\tvar params RenameFilesParams\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.WillRenameFiles(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tcase \"workspaceSymbol/resolve\":\n\t\tvar params WorkspaceSymbol\n\t\tif err := UnmarshalJSON(raw, &params); err != nil {\n\t\t\treturn nil, true, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tresp, err := server.ResolveWorkspaceSymbol(ctx, &params)\n\t\tif err != nil {\n\t\t\treturn nil, true, err\n\t\t}\n\t\treturn resp, true, nil\n\n\tdefault:\n\t\treturn nil, false, nil\n\t}\n}\n\nfunc (s *serverDispatcher) Progress(ctx context.Context, params *ProgressParams) error {\n\treturn s.sender.Notify(ctx, \"$/progress\", params)\n}\nfunc (s *serverDispatcher) SetTrace(ctx context.Context, params *SetTraceParams) error {\n\treturn s.sender.Notify(ctx, \"$/setTrace\", params)\n}\nfunc (s *serverDispatcher) IncomingCalls(ctx context.Context, params *CallHierarchyIncomingCallsParams) ([]CallHierarchyIncomingCall, error) {\n\tvar result []CallHierarchyIncomingCall\n\tif err := s.sender.Call(ctx, \"callHierarchy/incomingCalls\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) OutgoingCalls(ctx context.Context, params *CallHierarchyOutgoingCallsParams) ([]CallHierarchyOutgoingCall, error) {\n\tvar result []CallHierarchyOutgoingCall\n\tif err := s.sender.Call(ctx, \"callHierarchy/outgoingCalls\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveCodeAction(ctx context.Context, params *CodeAction) (*CodeAction, error) {\n\tvar result *CodeAction\n\tif err := s.sender.Call(ctx, \"codeAction/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveCodeLens(ctx context.Context, params *CodeLens) (*CodeLens, error) {\n\tvar result *CodeLens\n\tif err := s.sender.Call(ctx, \"codeLens/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveCommand(ctx context.Context, params *ExecuteCommandParams) (*ExecuteCommandParams, error) {\n\tvar result *ExecuteCommandParams\n\tif err := s.sender.Call(ctx, \"command/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveCompletionItem(ctx context.Context, params *CompletionItem) (*CompletionItem, error) {\n\tvar result *CompletionItem\n\tif err := s.sender.Call(ctx, \"completionItem/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveDocumentLink(ctx context.Context, params *DocumentLink) (*DocumentLink, error) {\n\tvar result *DocumentLink\n\tif err := s.sender.Call(ctx, \"documentLink/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Exit(ctx context.Context) error {\n\treturn s.sender.Notify(ctx, \"exit\", nil)\n}\nfunc (s *serverDispatcher) Initialize(ctx context.Context, params *ParamInitialize) (*InitializeResult, error) {\n\tvar result *InitializeResult\n\tif err := s.sender.Call(ctx, \"initialize\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Initialized(ctx context.Context, params *InitializedParams) error {\n\treturn s.sender.Notify(ctx, \"initialized\", params)\n}\nfunc (s *serverDispatcher) Resolve(ctx context.Context, params *InlayHint) (*InlayHint, error) {\n\tvar result *InlayHint\n\tif err := s.sender.Call(ctx, \"inlayHint/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) InteractiveListEnum(ctx context.Context, params *InteractiveListEnumParams) ([]FormEnumEntry, error) {\n\tvar result []FormEnumEntry\n\tif err := s.sender.Call(ctx, \"interactive/listEnum\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DidChangeNotebookDocument(ctx context.Context, params *DidChangeNotebookDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"notebookDocument/didChange\", params)\n}\nfunc (s *serverDispatcher) DidCloseNotebookDocument(ctx context.Context, params *DidCloseNotebookDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"notebookDocument/didClose\", params)\n}\nfunc (s *serverDispatcher) DidOpenNotebookDocument(ctx context.Context, params *DidOpenNotebookDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"notebookDocument/didOpen\", params)\n}\nfunc (s *serverDispatcher) DidSaveNotebookDocument(ctx context.Context, params *DidSaveNotebookDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"notebookDocument/didSave\", params)\n}\nfunc (s *serverDispatcher) Shutdown(ctx context.Context) error {\n\treturn s.sender.Call(ctx, \"shutdown\", nil, nil)\n}\nfunc (s *serverDispatcher) CodeAction(ctx context.Context, params *CodeActionParams) ([]CodeAction, error) {\n\tvar result []CodeAction\n\tif err := s.sender.Call(ctx, \"textDocument/codeAction\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) CodeLens(ctx context.Context, params *CodeLensParams) ([]CodeLens, error) {\n\tvar result []CodeLens\n\tif err := s.sender.Call(ctx, \"textDocument/codeLens\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ColorPresentation(ctx context.Context, params *ColorPresentationParams) ([]ColorPresentation, error) {\n\tvar result []ColorPresentation\n\tif err := s.sender.Call(ctx, \"textDocument/colorPresentation\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Completion(ctx context.Context, params *CompletionParams) (*CompletionList, error) {\n\tvar result *CompletionList\n\tif err := s.sender.Call(ctx, \"textDocument/completion\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Declaration(ctx context.Context, params *DeclarationParams) (*Or_textDocument_declaration, error) {\n\tvar result *Or_textDocument_declaration\n\tif err := s.sender.Call(ctx, \"textDocument/declaration\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Definition(ctx context.Context, params *DefinitionParams) ([]Location, error) {\n\tvar result []Location\n\tif err := s.sender.Call(ctx, \"textDocument/definition\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Diagnostic(ctx context.Context, params *DocumentDiagnosticParams) (*DocumentDiagnosticReport, error) {\n\tvar result *DocumentDiagnosticReport\n\tif err := s.sender.Call(ctx, \"textDocument/diagnostic\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DidChange(ctx context.Context, params *DidChangeTextDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/didChange\", params)\n}\nfunc (s *serverDispatcher) DidClose(ctx context.Context, params *DidCloseTextDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/didClose\", params)\n}\nfunc (s *serverDispatcher) DidOpen(ctx context.Context, params *DidOpenTextDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/didOpen\", params)\n}\nfunc (s *serverDispatcher) DidSave(ctx context.Context, params *DidSaveTextDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/didSave\", params)\n}\nfunc (s *serverDispatcher) DocumentColor(ctx context.Context, params *DocumentColorParams) ([]ColorInformation, error) {\n\tvar result []ColorInformation\n\tif err := s.sender.Call(ctx, \"textDocument/documentColor\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DocumentHighlight(ctx context.Context, params *DocumentHighlightParams) ([]DocumentHighlight, error) {\n\tvar result []DocumentHighlight\n\tif err := s.sender.Call(ctx, \"textDocument/documentHighlight\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DocumentLink(ctx context.Context, params *DocumentLinkParams) ([]DocumentLink, error) {\n\tvar result []DocumentLink\n\tif err := s.sender.Call(ctx, \"textDocument/documentLink\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DocumentSymbol(ctx context.Context, params *DocumentSymbolParams) ([]any, error) {\n\tvar result []any\n\tif err := s.sender.Call(ctx, \"textDocument/documentSymbol\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) FoldingRange(ctx context.Context, params *FoldingRangeParams) ([]FoldingRange, error) {\n\tvar result []FoldingRange\n\tif err := s.sender.Call(ctx, \"textDocument/foldingRange\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Formatting(ctx context.Context, params *DocumentFormattingParams) ([]TextEdit, error) {\n\tvar result []TextEdit\n\tif err := s.sender.Call(ctx, \"textDocument/formatting\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Hover(ctx context.Context, params *HoverParams) (*Hover, error) {\n\tvar result *Hover\n\tif err := s.sender.Call(ctx, \"textDocument/hover\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Implementation(ctx context.Context, params *ImplementationParams) ([]Location, error) {\n\tvar result []Location\n\tif err := s.sender.Call(ctx, \"textDocument/implementation\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) InlayHint(ctx context.Context, params *InlayHintParams) ([]InlayHint, error) {\n\tvar result []InlayHint\n\tif err := s.sender.Call(ctx, \"textDocument/inlayHint\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) InlineCompletion(ctx context.Context, params *InlineCompletionParams) (*Or_Result_textDocument_inlineCompletion, error) {\n\tvar result *Or_Result_textDocument_inlineCompletion\n\tif err := s.sender.Call(ctx, \"textDocument/inlineCompletion\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) InlineValue(ctx context.Context, params *InlineValueParams) ([]InlineValue, error) {\n\tvar result []InlineValue\n\tif err := s.sender.Call(ctx, \"textDocument/inlineValue\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) LinkedEditingRange(ctx context.Context, params *LinkedEditingRangeParams) (*LinkedEditingRanges, error) {\n\tvar result *LinkedEditingRanges\n\tif err := s.sender.Call(ctx, \"textDocument/linkedEditingRange\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Moniker(ctx context.Context, params *MonikerParams) ([]Moniker, error) {\n\tvar result []Moniker\n\tif err := s.sender.Call(ctx, \"textDocument/moniker\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) OnTypeFormatting(ctx context.Context, params *DocumentOnTypeFormattingParams) ([]TextEdit, error) {\n\tvar result []TextEdit\n\tif err := s.sender.Call(ctx, \"textDocument/onTypeFormatting\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) PrepareCallHierarchy(ctx context.Context, params *CallHierarchyPrepareParams) ([]CallHierarchyItem, error) {\n\tvar result []CallHierarchyItem\n\tif err := s.sender.Call(ctx, \"textDocument/prepareCallHierarchy\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) PrepareRename(ctx context.Context, params *PrepareRenameParams) (*PrepareRenameResult, error) {\n\tvar result *PrepareRenameResult\n\tif err := s.sender.Call(ctx, \"textDocument/prepareRename\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) PrepareTypeHierarchy(ctx context.Context, params *TypeHierarchyPrepareParams) ([]TypeHierarchyItem, error) {\n\tvar result []TypeHierarchyItem\n\tif err := s.sender.Call(ctx, \"textDocument/prepareTypeHierarchy\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) RangeFormatting(ctx context.Context, params *DocumentRangeFormattingParams) ([]TextEdit, error) {\n\tvar result []TextEdit\n\tif err := s.sender.Call(ctx, \"textDocument/rangeFormatting\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) RangesFormatting(ctx context.Context, params *DocumentRangesFormattingParams) ([]TextEdit, error) {\n\tvar result []TextEdit\n\tif err := s.sender.Call(ctx, \"textDocument/rangesFormatting\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) References(ctx context.Context, params *ReferenceParams) ([]Location, error) {\n\tvar result []Location\n\tif err := s.sender.Call(ctx, \"textDocument/references\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Rename(ctx context.Context, params *RenameParams) (*WorkspaceEdit, error) {\n\tvar result *WorkspaceEdit\n\tif err := s.sender.Call(ctx, \"textDocument/rename\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) SelectionRange(ctx context.Context, params *SelectionRangeParams) ([]SelectionRange, error) {\n\tvar result []SelectionRange\n\tif err := s.sender.Call(ctx, \"textDocument/selectionRange\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) SemanticTokensFull(ctx context.Context, params *SemanticTokensParams) (*SemanticTokens, error) {\n\tvar result *SemanticTokens\n\tif err := s.sender.Call(ctx, \"textDocument/semanticTokens/full\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) SemanticTokensFullDelta(ctx context.Context, params *SemanticTokensDeltaParams) (any, error) {\n\tvar result any\n\tif err := s.sender.Call(ctx, \"textDocument/semanticTokens/full/delta\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) SemanticTokensRange(ctx context.Context, params *SemanticTokensRangeParams) (*SemanticTokens, error) {\n\tvar result *SemanticTokens\n\tif err := s.sender.Call(ctx, \"textDocument/semanticTokens/range\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) SignatureHelp(ctx context.Context, params *SignatureHelpParams) (*SignatureHelp, error) {\n\tvar result *SignatureHelp\n\tif err := s.sender.Call(ctx, \"textDocument/signatureHelp\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) TypeDefinition(ctx context.Context, params *TypeDefinitionParams) ([]Location, error) {\n\tvar result []Location\n\tif err := s.sender.Call(ctx, \"textDocument/typeDefinition\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) WillSave(ctx context.Context, params *WillSaveTextDocumentParams) error {\n\treturn s.sender.Notify(ctx, \"textDocument/willSave\", params)\n}\nfunc (s *serverDispatcher) WillSaveWaitUntil(ctx context.Context, params *WillSaveTextDocumentParams) ([]TextEdit, error) {\n\tvar result []TextEdit\n\tif err := s.sender.Call(ctx, \"textDocument/willSaveWaitUntil\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Subtypes(ctx context.Context, params *TypeHierarchySubtypesParams) ([]TypeHierarchyItem, error) {\n\tvar result []TypeHierarchyItem\n\tif err := s.sender.Call(ctx, \"typeHierarchy/subtypes\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Supertypes(ctx context.Context, params *TypeHierarchySupertypesParams) ([]TypeHierarchyItem, error) {\n\tvar result []TypeHierarchyItem\n\tif err := s.sender.Call(ctx, \"typeHierarchy/supertypes\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) WorkDoneProgressCancel(ctx context.Context, params *WorkDoneProgressCancelParams) error {\n\treturn s.sender.Notify(ctx, \"window/workDoneProgress/cancel\", params)\n}\nfunc (s *serverDispatcher) DiagnosticWorkspace(ctx context.Context, params *WorkspaceDiagnosticParams) (*WorkspaceDiagnosticReport, error) {\n\tvar result *WorkspaceDiagnosticReport\n\tif err := s.sender.Call(ctx, \"workspace/diagnostic\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) DidChangeConfiguration(ctx context.Context, params *DidChangeConfigurationParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didChangeConfiguration\", params)\n}\nfunc (s *serverDispatcher) DidChangeWatchedFiles(ctx context.Context, params *DidChangeWatchedFilesParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didChangeWatchedFiles\", params)\n}\nfunc (s *serverDispatcher) DidChangeWorkspaceFolders(ctx context.Context, params *DidChangeWorkspaceFoldersParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didChangeWorkspaceFolders\", params)\n}\nfunc (s *serverDispatcher) DidCreateFiles(ctx context.Context, params *CreateFilesParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didCreateFiles\", params)\n}\nfunc (s *serverDispatcher) DidDeleteFiles(ctx context.Context, params *DeleteFilesParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didDeleteFiles\", params)\n}\nfunc (s *serverDispatcher) DidRenameFiles(ctx context.Context, params *RenameFilesParams) error {\n\treturn s.sender.Notify(ctx, \"workspace/didRenameFiles\", params)\n}\nfunc (s *serverDispatcher) ExecuteCommand(ctx context.Context, params *ExecuteCommandParams) (any, error) {\n\tvar result any\n\tif err := s.sender.Call(ctx, \"workspace/executeCommand\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) Symbol(ctx context.Context, params *WorkspaceSymbolParams) ([]SymbolInformation, error) {\n\tvar result []SymbolInformation\n\tif err := s.sender.Call(ctx, \"workspace/symbol\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) TextDocumentContent(ctx context.Context, params *TextDocumentContentParams) (*TextDocumentContentResult, error) {\n\tvar result *TextDocumentContentResult\n\tif err := s.sender.Call(ctx, \"workspace/textDocumentContent\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) WillCreateFiles(ctx context.Context, params *CreateFilesParams) (*WorkspaceEdit, error) {\n\tvar result *WorkspaceEdit\n\tif err := s.sender.Call(ctx, \"workspace/willCreateFiles\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) WillDeleteFiles(ctx context.Context, params *DeleteFilesParams) (*WorkspaceEdit, error) {\n\tvar result *WorkspaceEdit\n\tif err := s.sender.Call(ctx, \"workspace/willDeleteFiles\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) WillRenameFiles(ctx context.Context, params *RenameFilesParams) (*WorkspaceEdit, error) {\n\tvar result *WorkspaceEdit\n\tif err := s.sender.Call(ctx, \"workspace/willRenameFiles\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\nfunc (s *serverDispatcher) ResolveWorkspaceSymbol(ctx context.Context, params *WorkspaceSymbol) (*WorkspaceSymbol, error) {\n\tvar result *WorkspaceSymbol\n\tif err := s.sender.Call(ctx, \"workspaceSymbol/resolve\", params, &result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n"
  },
  {
    "path": "gopls/internal/protocol/uri.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage protocol\n\n// This file declares URI, DocumentURI, and its methods.\n//\n// For the LSP definition of these types, see\n// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#uri\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n)\n\n// A DocumentURI is the URI of a client editor document.\n//\n// According to the LSP specification:\n//\n//\tCare should be taken to handle encoding in URIs. For\n//\texample, some clients (such as VS Code) may encode colons\n//\tin drive letters while others do not. The URIs below are\n//\tboth valid, but clients and servers should be consistent\n//\twith the form they use themselves to ensure the other party\n//\tdoesn’t interpret them as distinct URIs. Clients and\n//\tservers should not assume that each other are encoding the\n//\tsame way (for example a client encoding colons in drive\n//\tletters cannot assume server responses will have encoded\n//\tcolons). The same applies to casing of drive letters - one\n//\tparty should not assume the other party will return paths\n//\twith drive letters cased the same as it.\n//\n//\tfile:///c:/project/readme.md\n//\tfile:///C%3A/project/readme.md\n//\n// This is done during JSON unmarshalling;\n// see [DocumentURI.UnmarshalText] for details.\ntype DocumentURI string\n\n// A URI is an arbitrary URL (e.g. https), not necessarily a file.\ntype URI = string\n\n// UnmarshalText implements decoding of DocumentURI values.\n//\n// In particular, it implements a systematic correction of various odd\n// features of the definition of DocumentURI in the LSP spec that\n// appear to be workarounds for bugs in VS Code. For example, it may\n// URI-encode the URI itself, so that colon becomes %3A, and it may\n// send file://foo.go URIs that have two slashes (not three) and no\n// hostname.\n//\n// We use UnmarshalText, not UnmarshalJSON, because it is called even\n// for non-addressable values such as keys and values of map[K]V,\n// where there is no pointer of type *K or *V on which to call\n// UnmarshalJSON. (See Go issue #28189 for more detail.)\n//\n// Non-empty DocumentURIs are valid \"file\"-scheme URIs.\n// The empty DocumentURI is valid.\nfunc (uri *DocumentURI) UnmarshalText(data []byte) (err error) {\n\t*uri, err = ParseDocumentURI(string(data))\n\treturn\n}\n\n// Clean returns the cleaned uri by triggering filepath.Clean underlying.\nfunc (uri DocumentURI) Clean() DocumentURI {\n\treturn URIFromPath(filepath.Clean(uri.Path()))\n}\n\n// Path returns the file path for the given URI.\n//\n// DocumentURI(\"\").Path() returns the empty string.\n//\n// Path panics if called on a URI that is not a valid filename.\nfunc (uri DocumentURI) Path() string {\n\tfilename, err := filename(uri)\n\tif err != nil {\n\t\t// e.g. ParseRequestURI failed.\n\t\t//\n\t\t// This can only affect DocumentURIs created by\n\t\t// direct string manipulation; all DocumentURIs\n\t\t// received from the client pass through\n\t\t// ParseRequestURI, which ensures validity.\n\t\tpanic(err)\n\t}\n\treturn filepath.FromSlash(filename)\n}\n\n// Base returns the base name of the file path of the given URI.\nfunc (uri DocumentURI) Base() string {\n\treturn filepath.Base(uri.Path())\n}\n\n// Dir returns the URI for the directory containing the receiver.\nfunc (uri DocumentURI) Dir() DocumentURI {\n\t// This function could be more efficiently implemented by avoiding any call\n\t// to Path(), but at least consolidates URI manipulation.\n\treturn URIFromPath(uri.DirPath())\n}\n\n// DirPath returns the file path to the directory containing this URI, which\n// must be a file URI.\nfunc (uri DocumentURI) DirPath() string {\n\treturn filepath.Dir(uri.Path())\n}\n\n// Encloses reports whether uri's path, considered as a sequence of segments,\n// is a prefix of file's path.\nfunc (uri DocumentURI) Encloses(file DocumentURI) bool {\n\treturn pathutil.InDir(uri.Path(), file.Path())\n}\n\n// Location returns the Location for the specified range of this URI's file.\nfunc (uri DocumentURI) Location(rng Range) Location {\n\treturn Location{URI: uri, Range: rng}\n}\n\nfunc filename(uri DocumentURI) (string, error) {\n\tif uri == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\t// This conservative check for the common case\n\t// of a simple non-empty absolute POSIX filename\n\t// avoids the allocation of a net.URL.\n\tif strings.HasPrefix(string(uri), \"file:///\") {\n\t\trest := string(uri)[len(\"file://\"):] // leave one slash\n\t\tfor i := 0; i < len(rest); i++ {\n\t\t\tb := rest[i]\n\t\t\t// Reject these cases:\n\t\t\tif b < ' ' || b == 0x7f || // control character\n\t\t\t\tb == '%' || b == '+' || // URI escape\n\t\t\t\tb == ':' || // Windows drive letter\n\t\t\t\tb == '&' || b == '?' { // authority or query\n\t\t\t\tgoto slow\n\t\t\t}\n\t\t\t// We do not reject '@' as it cannot be part of the\n\t\t\t// authority (e.g. user:pass@example.com) in a\n\t\t\t// \"file:///\" URL, and '@' commonly appears in file\n\t\t\t// paths such as GOMODCACHE/module@version/...\n\t\t}\n\t\treturn rest, nil\n\t}\nslow:\n\n\tu, err := url.ParseRequestURI(string(uri))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif u.Scheme != fileScheme {\n\t\treturn \"\", fmt.Errorf(\"only file URIs are supported, got %q from %q\", u.Scheme, uri)\n\t}\n\t// If the URI is a Windows URI, we trim the leading \"/\" and uppercase\n\t// the drive letter, which will never be case sensitive.\n\tif isWindowsDriveURIPath(u.Path) {\n\t\tu.Path = strings.ToUpper(string(u.Path[1])) + u.Path[2:]\n\t}\n\n\treturn u.Path, nil\n}\n\n// ParseDocumentURI interprets a string as a DocumentURI, applying VS\n// Code workarounds; see [DocumentURI.UnmarshalText] for details.\n// If \"s\" is a file name, use [URIFromPath] instead.\nfunc ParseDocumentURI(s string) (DocumentURI, error) {\n\tif s == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\tif !strings.HasPrefix(s, \"file://\") {\n\t\treturn \"\", fmt.Errorf(\"DocumentURI scheme is not 'file': %s\", s)\n\t}\n\n\t// VS Code sends URLs with only two slashes,\n\t// which are invalid. golang/go#39789.\n\tif !strings.HasPrefix(s, \"file:///\") {\n\t\ts = \"file:///\" + s[len(\"file://\"):]\n\t}\n\n\t// Even though the input is a URI, it may not be in canonical form. VS Code\n\t// in particular over-escapes :, @, etc. Unescape and re-encode to canonicalize.\n\tpath, err := url.PathUnescape(s[len(\"file://\"):])\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// File URIs from Windows may have lowercase drive letters.\n\t// Since drive letters are guaranteed to be case insensitive,\n\t// we change them to uppercase to remain consistent.\n\t// For example, file:///c:/x/y/z becomes file:///C:/x/y/z.\n\tif isWindowsDriveURIPath(path) {\n\t\tpath = path[:1] + strings.ToUpper(string(path[1])) + path[2:]\n\t}\n\tu := url.URL{Scheme: fileScheme, Path: path}\n\treturn DocumentURI(u.String()), nil\n}\n\n// URIFromPath returns DocumentURI for the supplied file path.\n// Given \"\", it returns \"\".\nfunc URIFromPath(path string) DocumentURI {\n\tif path == \"\" {\n\t\treturn \"\"\n\t}\n\tif !IsWindowsDrivePath(path) {\n\t\tif abs, err := filepath.Abs(path); err == nil {\n\t\t\tpath = abs\n\t\t}\n\t}\n\t// Check the file path again, in case it became absolute.\n\tif IsWindowsDrivePath(path) {\n\t\tpath = \"/\" + strings.ToUpper(string(path[0])) + path[1:]\n\t}\n\tpath = filepath.ToSlash(path)\n\tu := url.URL{\n\t\tScheme: fileScheme,\n\t\tPath:   path,\n\t}\n\treturn DocumentURI(u.String())\n}\n\nconst fileScheme = \"file\"\n\n// IsWindowsDrivePath returns true if the file path is of the form used by\n// Windows. We check if the path begins with a drive letter, followed by a \":\".\n// For example: C:/x/y/z.\nfunc IsWindowsDrivePath(path string) bool {\n\tif len(path) < 3 {\n\t\treturn false\n\t}\n\treturn unicode.IsLetter(rune(path[0])) && path[1] == ':'\n}\n\n// isWindowsDriveURIPath returns true if the file URI is of the format used by\n// Windows URIs. The url.Parse package does not specially handle Windows paths\n// (see golang/go#6027), so we check if the URI path has a drive prefix (e.g. \"/C:\").\nfunc isWindowsDriveURIPath(uri string) bool {\n\tif len(uri) < 4 {\n\t\treturn false\n\t}\n\treturn uri[0] == '/' && unicode.IsLetter(rune(uri[1])) && uri[2] == ':'\n}\n"
  },
  {
    "path": "gopls/internal/protocol/uri_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !windows\n\npackage protocol_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// TestURIFromPath tests the conversion between URIs and filenames. The test cases\n// include Windows-style URIs and filepaths, but we avoid having OS-specific\n// tests by using only forward slashes, assuming that the standard library\n// functions filepath.ToSlash and filepath.FromSlash do not need testing.\nfunc TestURIFromPath(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tpath, wantFile string\n\t\twantURI        protocol.DocumentURI\n\t}{\n\t\t{\n\t\t\tpath:     ``,\n\t\t\twantFile: ``,\n\t\t\twantURI:  protocol.DocumentURI(\"\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `C:/Windows/System32`,\n\t\t\twantFile: `C:/Windows/System32`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Windows/System32\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `C:/Go/src/bob.go`,\n\t\t\twantFile: `C:/Go/src/bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `c:/Go/src/bob.go`,\n\t\t\twantFile: `C:/Go/src/bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `/path/to/dir`,\n\t\t\twantFile: `/path/to/dir`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///path/to/dir\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `/a/b/c/src/bob.go`,\n\t\t\twantFile: `/a/b/c/src/bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///a/b/c/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `c:/Go/src/bob george/george/george.go`,\n\t\t\twantFile: `C:/Go/src/bob george/george/george.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob%20george/george/george.go\"),\n\t\t},\n\t} {\n\t\tgot := protocol.URIFromPath(test.path)\n\t\tif got != test.wantURI {\n\t\t\tt.Errorf(\"URIFromPath(%q): got %q, expected %q\", test.path, got, test.wantURI)\n\t\t}\n\t\tgotFilename := got.Path()\n\t\tif gotFilename != test.wantFile {\n\t\t\tt.Errorf(\"Filename(%q): got %q, expected %q\", got, gotFilename, test.wantFile)\n\t\t}\n\t}\n}\n\nfunc TestParseDocumentURI(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tinput    string\n\t\twant     string // string(DocumentURI) on success or error.Error() on failure\n\t\twantPath string // expected DocumentURI.Path on success\n\t}{\n\t\t{\n\t\t\tinput:    `file:///c:/Go/src/bob%20george/george/george.go`,\n\t\t\twant:     \"file:///C:/Go/src/bob%20george/george/george.go\",\n\t\t\twantPath: `C:/Go/src/bob george/george/george.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///C%3A/Go/src/bob%20george/george/george.go`,\n\t\t\twant:     \"file:///C:/Go/src/bob%20george/george/george.go\",\n\t\t\twantPath: `C:/Go/src/bob george/george/george.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///path/to/%25p%25ercent%25/per%25cent.go`,\n\t\t\twant:     `file:///path/to/%25p%25ercent%25/per%25cent.go`,\n\t\t\twantPath: `/path/to/%p%ercent%/per%cent.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///C%3A/`,\n\t\t\twant:     `file:///C:/`,\n\t\t\twantPath: `C:/`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///`,\n\t\t\twant:     `file:///`,\n\t\t\twantPath: `/`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file://wsl%24/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,\n\t\t\twant:     `file:///wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,\n\t\t\twantPath: `/wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,\n\t\t},\n\t\t{\n\t\t\tinput:    \"\",\n\t\t\twant:     \"\",\n\t\t\twantPath: \"\",\n\t\t},\n\t\t// Errors:\n\t\t{\n\t\t\tinput: \"https://go.dev/\",\n\t\t\twant:  \"DocumentURI scheme is not 'file': https://go.dev/\",\n\t\t},\n\t} {\n\t\turi, err := protocol.ParseDocumentURI(test.input)\n\t\tvar got string\n\t\tif err != nil {\n\t\t\tgot = err.Error()\n\t\t} else {\n\t\t\tgot = string(uri)\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"ParseDocumentURI(%q): got %q, want %q\", test.input, got, test.want)\n\t\t}\n\t\tif err == nil && uri.Path() != test.wantPath {\n\t\t\tt.Errorf(\"DocumentURI(%s).Path = %q, want %q\", uri,\n\t\t\t\turi.Path(), test.wantPath)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/protocol/uri_windows_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build windows\n\npackage protocol_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// TestURIFromPath tests the conversion between URIs and filenames. The test cases\n// include Windows-style URIs and filepaths, but we avoid having OS-specific\n// tests by using only forward slashes, assuming that the standard library\n// functions filepath.ToSlash and filepath.FromSlash do not need testing.\nfunc TestURIFromPath(t *testing.T) {\n\trootPath, err := filepath.Abs(\"/\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(rootPath) < 2 || rootPath[1] != ':' {\n\t\tt.Fatalf(\"malformed root path %q\", rootPath)\n\t}\n\tdriveLetter := string(rootPath[0])\n\n\tfor _, test := range []struct {\n\t\tpath, wantFile string\n\t\twantURI        protocol.DocumentURI\n\t}{\n\t\t{\n\t\t\tpath:     ``,\n\t\t\twantFile: ``,\n\t\t\twantURI:  protocol.DocumentURI(\"\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `C:\\Windows\\System32`,\n\t\t\twantFile: `C:\\Windows\\System32`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Windows/System32\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `C:\\Go\\src\\bob.go`,\n\t\t\twantFile: `C:\\Go\\src\\bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `c:\\Go\\src\\bob.go`,\n\t\t\twantFile: `C:\\Go\\src\\bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `\\path\\to\\dir`,\n\t\t\twantFile: driveLetter + `:\\path\\to\\dir`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///\" + driveLetter + \":/path/to/dir\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `\\a\\b\\c\\src\\bob.go`,\n\t\t\twantFile: driveLetter + `:\\a\\b\\c\\src\\bob.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///\" + driveLetter + \":/a/b/c/src/bob.go\"),\n\t\t},\n\t\t{\n\t\t\tpath:     `c:\\Go\\src\\bob george\\george\\george.go`,\n\t\t\twantFile: `C:\\Go\\src\\bob george\\george\\george.go`,\n\t\t\twantURI:  protocol.DocumentURI(\"file:///C:/Go/src/bob%20george/george/george.go\"),\n\t\t},\n\t} {\n\t\tgot := protocol.URIFromPath(test.path)\n\t\tif got != test.wantURI {\n\t\t\tt.Errorf(\"URIFromPath(%q): got %q, expected %q\", test.path, got, test.wantURI)\n\t\t}\n\t\tgotFilename := got.Path()\n\t\tif gotFilename != test.wantFile {\n\t\t\tt.Errorf(\"Filename(%q): got %q, expected %q\", got, gotFilename, test.wantFile)\n\t\t}\n\t}\n}\n\nfunc TestParseDocumentURI(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tinput    string\n\t\twant     string // string(DocumentURI) on success or error.Error() on failure\n\t\twantPath string // expected DocumentURI.Path on success\n\t}{\n\t\t{\n\t\t\tinput:    `file:///c:/Go/src/bob%20george/george/george.go`,\n\t\t\twant:     \"file:///C:/Go/src/bob%20george/george/george.go\",\n\t\t\twantPath: `C:\\Go\\src\\bob george\\george\\george.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///C%3A/Go/src/bob%20george/george/george.go`,\n\t\t\twant:     \"file:///C:/Go/src/bob%20george/george/george.go\",\n\t\t\twantPath: `C:\\Go\\src\\bob george\\george\\george.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///c:/path/to/%25p%25ercent%25/per%25cent.go`,\n\t\t\twant:     `file:///C:/path/to/%25p%25ercent%25/per%25cent.go`,\n\t\t\twantPath: `C:\\path\\to\\%p%ercent%\\per%cent.go`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///C%3A/`,\n\t\t\twant:     `file:///C:/`,\n\t\t\twantPath: `C:\\`,\n\t\t},\n\t\t{\n\t\t\tinput:    `file:///`,\n\t\t\twant:     `file:///`,\n\t\t\twantPath: `\\`,\n\t\t},\n\t\t{\n\t\t\tinput:    \"\",\n\t\t\twant:     \"\",\n\t\t\twantPath: \"\",\n\t\t},\n\t\t// Errors:\n\t\t{\n\t\t\tinput: \"https://go.dev/\",\n\t\t\twant:  \"DocumentURI scheme is not 'file': https://go.dev/\",\n\t\t},\n\t} {\n\t\turi, err := protocol.ParseDocumentURI(test.input)\n\t\tvar got string\n\t\tif err != nil {\n\t\t\tgot = err.Error()\n\t\t} else {\n\t\t\tgot = string(uri)\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"ParseDocumentURI(%q): got %q, want %q\", test.input, got, test.want)\n\t\t}\n\t\tif err == nil && uri.Path() != test.wantPath {\n\t\t\tt.Errorf(\"DocumentURI(%s).Path = %q, want %q\", uri,\n\t\t\t\turi.Path(), test.wantPath)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/assets/common.css",
    "content": "/* Copyright 2024 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/* inspired by pkg.go.dev's typography.css */\n\nbody {\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';\n  font-size: 1rem;\n  line-height: normal;\n}\n\nh1 {\n  font-size: 1.5rem;\n}\n\nh2 {\n  font-size: 1.375rem;\n}\n\nh3 {\n  font-size: 1.25rem;\n}\n\nh4 {\n  font-size: 1.125rem;\n}\n\nh5 {\n  font-size: 1rem;\n}\n\nh6 {\n  font-size: 0.875rem;\n}\n\nh1,\nh2,\nh3,\nh4 {\n  font-weight: 600;\n  line-height: 1.25em;\n  word-break: break-word;\n}\n\nh5,\nh6 {\n  font-weight: 500;\n  line-height: 1.3em;\n  word-break: break-word;\n}\n\np {\n  font-size: 1rem;\n  line-height: 1.5rem;\n  max-width: 60rem;\n}\n\nstrong {\n  font-weight: 600;\n}\n\ncode,\npre,\ntextarea.code {\n  font-family: Consolas, 'Liberation Mono', Menlo, monospace;\n  font-size: 0.875rem;\n  line-height: 1.5em;\n}\n\npre,\ntextarea.code {\n  background-color: #eee;\n  border: 3px;\n  border-radius: 3px;\n  color: black;\n  overflow-x: auto;\n  padding: 0.625rem;\n  tab-size: 4;\n  white-space: pre;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  font: inherit;\n}\n\na,\na:link,\na:visited {\n  color: rgb(0, 125, 156);\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: rgb(0, 125, 156);\n  text-decoration: underline;\n}\n\na:hover > * {\n  text-decoration: underline;\n}\n\n#disconnected {\n  position: fixed;\n  top: 1em;\n  left: 1em;\n  display: none; /* initially */\n  background-color: white;\n  border: thick solid red;\n  padding: 2em;\n}\n"
  },
  {
    "path": "gopls/internal/server/assets/common.js",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// httpGET requests a URL for its effects only.\n// (It is needed for /open URLs; see objHTML.)\nfunction httpGET(url) {\n\tvar x = new XMLHttpRequest();\n\tx.open(\"GET\", url, true);\n\tx.send();\n\treturn false; // disable usual <a href=...> behavior\n}\n\n// disconnect banner\nwindow.addEventListener('load', function() {\n\t// Create a hidden <div id='disconnected'> element.\n\tvar banner = document.createElement(\"div\");\n\tbanner.id = \"disconnected\";\n\tbanner.innerText = \"Gopls server has terminated. Page is inactive.\";\n\tdocument.body.appendChild(banner);\n\n\t// Start a GET /hang request. If it ever completes, the server\n\t// has disconnected. Reveal the banner in that case.\n\tvar x = new XMLHttpRequest();\n\tx.open(\"GET\", \"/hang\", true);\n\tx.onloadend = () => { banner.style.display = \"block\"; };\n\tx.send();\n});\n"
  },
  {
    "path": "gopls/internal/server/assets/splitpkg.css",
    "content": "/* Copyright 2025 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nli {\n\t\t\tlist-style: none;\n}\nspan.component {\n    display:\t\tinline-block;\n    min-width:\t\t8em;\n}\nspan.delete {\n    color:\t\tgrey;\n    opacity:\t\t0.3;\n}\nspan.delete:hover {\n\t\t\topacity: 1;\n}\nhr {\n    border-top:\t\tthin solid #EEE;\n}\np.help {\n    width:\t\t6in;\n    line-height:\t120%; /* tighter than default */\n    font-size:\t\t80%;\n    text-align:\t\tjustify;\n    text-justify:\tinter-word;\n    color:\t\t#AAA;\n}\n"
  },
  {
    "path": "gopls/internal/server/assets/splitpkg.js",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// data holds the application state, of Go type splitpkg.ResultJSON.\n// Each reload() replaces it by the current server state.\nvar data = null;\n\n// One-time setup.\nwindow.addEventListener('load', function() {\n  document.getElementById('add-component').addEventListener('click', onClickAddComponent);\n  document.getElementById('assign-apply').addEventListener('click', onClickApplyAssignment);\n\n  reload();\n});\n\n/**\n * onClickAddComponent adds a new component, posts it to the server,\n * and reloads the page.\n */\nfunction onClickAddComponent(event) {\n  const name = document.getElementById('new-component').value.trim();\n  if (name == \"\") {\n    alert(\"empty component name\");\n    return;\n  }\n  if (data.Components.Names.includes(name)) {\n    alert(\"duplicate component name\");\n    return;\n  }\n  data.Components.Names.push(name);\n  postComponents();\n  reload();\n}\n\n/**\n * onClickDeleteComponent deletes a component, posts it to the server,\n * and reloads the page.\n */\nfunction onClickDeleteComponent(event) {\n  const li = event.target.parentNode;\n  li.parentNode.removeChild(li);\n\n  const index = li.index; // of deleted component\n\n  const names = data.Components.Names;\n  names.splice(index, 1);\n\n  // Update assignments after implicit renumbering of components.\n  const assignments = data.Components.Assignments;\n  Object.entries(assignments).forEach(([k, compIndex]) => {\n    if (compIndex == index) {\n      assignments[k] = 0; // => default component\n    } else if (compIndex > index) {\n      assignments[k] = compIndex - 1;\n    }\n  });\n\n  postComponents();\n  reload();\n}\n\n/** postComponents notifies the server of a change in the Components information. */\nfunction postComponents() {\n  // Post the updated components.\n  const xhr = new XMLHttpRequest();\n  xhr.open(\"POST\", makeURL('/splitpkg-components'), false); // false => synchronous\n  xhr.setRequestHeader('Content-Type', 'application/json');\n  xhr.send(JSON.stringify(data.Components));\n  if (xhr.status === 200) {\n    // ok\n  } else {\n    alert(\"failed to post new component list: \" + xhr.statusText);\n    return;\n  }\n}\n\n/**\n * onClickApplyAssignment is called when the Apply button is clicked.\n * It updates the component assignment mapping.\n */\nfunction onClickApplyAssignment(event) {\n  const componentIndex = document.getElementById('assign-select').selectedIndex;\n\n  // Update the component assignment of each spec\n  // whose <li class='spec-node'> checkbox is checked.\n  document.querySelectorAll('li.spec-node').forEach((specItem) => {\n    const checkbox = specItem.firstChild;\n    if (checkbox.checked) {\n      data.Components.Assignments[specItem.dataset.name] = componentIndex;\n    }\n  });\n\n  postComponents(); // update the server\n  reload(); // recompute the page state\n}\n\n/**\n * reload requests the current server state,\n * updates the global 'data' variable,\n * and rebuilds the page DOM to reflect the state.\n */\nfunction reload() {\n  const xhr = new XMLHttpRequest();\n  xhr.open(\"GET\", makeURL('/splitpkg-json'), false); // false => synchronous\n  xhr.send(null);\n  if (xhr.status === 200) {\n    try {\n      data = JSON.parse(xhr.responseText);\n    } catch (e) {\n      alert(\"error parsing JSON: \" + e);\n      return null;\n    }\n  } else {\n    alert(\"request failed: \" + xhr.statusText);\n    return null;\n  }\n\n  // Ensure there is always a default component.\n  if (!data.Components.Names) { // undefined, null, or empty\n    data.Components.Names = [\"default\"];\n  }\n  if (!data.Components.Assignments) { // undefined, null, or empty\n    data.Components.Assignments = {};\n  }\n\n  // Rebuild list of components.\n  const componentsContainer = document.getElementById('components');\n  componentsContainer.replaceChildren(); // clear out previous state\n  const assignSelect = document.getElementById('assign-select');\n  assignSelect.replaceChildren(); // clear out previous state\n  const componentsList = document.createElement('ul');\n  componentsContainer.appendChild(componentsList);\n  data.Components.Names.forEach((name, i) => {\n      // <li>■ name ×\n    const li = document.createElement('li');\n    li.index = i; // custom index field holds component index (for onClickDeleteComponent)\n    componentsList.appendChild(li);\n\n    // ■ name\n    const span = document.createElement('span');\n    span.className = 'component';\n    span.style.color = componentColors[i % componentColors.length];\n    span.append('■ ', name)\n    li.append(span);\n\n    // ×\n    if (i > 0) { // the default component cannot be deleted\n      const xSpan = document.createElement('span');\n      xSpan.className = 'delete';\n      xSpan.append(' ×')\n      xSpan.addEventListener('click', onClickDeleteComponent);\n      li.append(xSpan);\n    }\n\n    // Add component to the assignment dropdown.\n    assignSelect.add(new Option(name, null));\n  })\n\n  // Rebuild list of decls grouped by file.\n  const filesContainer = document.getElementById('files');\n  filesContainer.replaceChildren(); // clear out previous state\n  data.Files.forEach(fileJson => {\n    filesContainer.appendChild(createFileDiv(fileJson));\n  });\n\n  // Display strongly connected components.\n  const deps = document.getElementById('deps');\n  deps.replaceChildren(); // clear out previous state\n  const depsList = document.createElement('ul');\n  deps.append(depsList);\n\n  // Be explicit if there are no component dependencies.\n  if (data.Edges.length == 0) {\n    const li = document.createElement('li');\n    depsList.append(li);\n    li.append(\"No dependencies\");\n    return;\n  }\n\n  // List all sets of mutually dependent components.\n  data.Cycles.forEach((scc) => {\n    const item = document.createElement('li');\n    item.append(\"⚠ Component cycle: \" +\n\t\tscc.map(index => data.Components.Names[index]).join(', '))\n    depsList.append(item);\n  })\n\n  // Show intercomponent edges.\n  data.Edges.forEach((edge) => {\n    const edgeItem = document.createElement('li');\n    depsList.append(edgeItem);\n\n    // component edge\n    const from = data.Components.Names[edge.From];\n    const to   = data.Components.Names[edge.To];\n    edgeItem.append((edge.Cyclic ? \"⚠ \" : \"\") + from + \" ➤ \" + to);\n\n    // sublist of symbol references that induced the edge\n    const refsList = document.createElement('ul');\n    edgeItem.appendChild(refsList);\n    refsList.className = 'refs-list';\n    edge.Refs.forEach(ref => {\n      refsList.appendChild(createRefItem(ref));\n    });\n  })\n}\n\n/**\n * makeURL returns a URL string with the specified path,\n * but preserving the current page's query parameters (view, pkg).\n */\nfunction makeURL(path) {\n  const url = new URL(window.location.href);\n  url.pathname = url.pathname.substring(0, url.pathname.lastIndexOf('/')) + path;\n  return url.href;\n}\n\n/** createFileDiv creates a <div> for a fileJSON object. */\nfunction createFileDiv(fileData) {\n  // Create the main container for the file entry.\n  const fileContainer = document.createElement('div');\n  fileContainer.className = 'file-node';\n\n  // Create and append the file's base name as a para.\n  const para = document.createElement('p');\n  fileContainer.appendChild(para);\n\n  // The file's checkbox applies in bulk to all specs within it.\n  var specCheckboxes = [];\n  const fileCheckbox = document.createElement('input');\n  fileCheckbox.type = 'checkbox';\n  fileCheckbox.addEventListener('click', (event) => {\n    // Select/deselect all specs belonging to the file.\n    const checked = event.target.checked;\n    specCheckboxes.forEach(checkbox => {\n      checkbox.checked = checked;\n    });\n  })\n  para.appendChild(fileCheckbox);\n  para.append(\"File \");\n\n  // Link file name to start of file.\n  const baseName = document.createElement('a');\n  para.appendChild(baseName);\n  baseName.className = 'file-link';\n  baseName.textContent = fileData.Base;\n  baseName.addEventListener('click', () => httpGET(fileData.URL));\n\n  // Process declarations if they exist.\n  if (fileData.Decls && fileData.Decls.length > 0) {\n    const declsList = document.createElement('ul');\n    declsList.className = 'decls-list';\n    // For now we flatten out the decl/spec grouping.\n    fileData.Decls.forEach(decl => {\n      if (decl.Specs && decl.Specs.length > 0) {\n        decl.Specs.forEach(spec => {\n          declsList.appendChild(createSpecItem(decl.Kind, spec, specCheckboxes));\n        });\n      }\n    });\n    fileContainer.appendChild(declsList);\n  }\n\n  return fileContainer;\n}\n\n/** createSpecItem creates an <li> element for a specJSON object (one declared name). */\nfunction createSpecItem(kind, specData, checkboxes) {\n  // <li><checkbox/>ⓕ <a>myfunc</a>...\n  const specItem = document.createElement('li');\n  specItem.className = 'spec-node';\n  specItem.dataset.name = specData.Name; // custom .name field holds symbol's unique logical name\n\n  // First child is a checkbox.\n  const specCheckbox = document.createElement('input');\n  specCheckbox.type = 'checkbox';\n  specItem.appendChild(specCheckbox);\n  checkboxes.push(specCheckbox);\n\n  // Next is the component assignment color swatch.\n  const assignSpan = document.createElement('span');\n  assignSpan.className = 'component-swatch';\n  assignSpan.textContent = \"■\";\n  {\n    var index = data.Components.Assignments[specData.Name]; // may be undefined\n    if (!index) {\n      index = 0; // default\n    }\n    assignSpan.style.color = componentColors[index % componentColors.length];\n    assignSpan.title = \"Component \" + data.Components.Names[index]; // tooltip\n  }\n  specItem.appendChild(assignSpan);\n\n  // Encircle the func/var/const/type indicator.\n  const symbolSpan = document.createElement('span');\n  const symbol = String.fromCodePoint(kind.codePointAt(0) - 'a'.codePointAt(0) + 'ⓐ'.codePointAt(0));\n  symbolSpan.title = kind; // tooltip\n  symbolSpan.append(`${symbol} `);\n  specItem.append(symbolSpan);\n\n  // Link name to declaration.\n  const specName = document.createElement('a');\n  specItem.appendChild(specName);\n  specName.textContent = ` ${specData.Name}`;\n  specName.addEventListener('click', () => httpGET(specData.URL));\n\n  return specItem;\n}\n\n/** createRefItem creates an <li> element for a refJSON object (a reference). */\nfunction createRefItem(refData) {\n  const refItem = document.createElement('li');\n  refItem.className = 'ref-node';\n\n  // Link (from -> to) to the reference in from.\n  const refLink = document.createElement('a');\n  refItem.appendChild(refLink);\n  refLink.addEventListener('click', () => httpGET(refData.URL));\n  refLink.textContent = \"${refData.From} ➤ ${refData.To}\";\n\n  return refItem;\n}\n\n/** componentColors is a palette of dark, high-contrast colors. */\nconst componentColors = [\n  \"#298429\",\n  \"#4B4B8F\",\n  \"#AD2C2C\",\n  \"#A62CA6\",\n  \"#6E65AF\",\n  \"#D15050\",\n  \"#2CA6A6\",\n  \"#C55656\",\n  \"#7B8C58\",\n  \"#587676\",\n  \"#B95EE1\",\n  \"#AF6D41\",\n];\n"
  },
  {
    "path": "gopls/internal/server/call_hierarchy.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) PrepareCallHierarchy(ctx context.Context, params *protocol.CallHierarchyPrepareParams) ([]protocol.CallHierarchyItem, error) {\n\tctx, done := event.Start(ctx, \"server.PrepareCallHierarchy\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.PrepareCallHierarchy(ctx, snapshot, fh, params.Range)\n\t}\n\treturn nil, nil // empty result\n}\n\nfunc (s *server) IncomingCalls(ctx context.Context, params *protocol.CallHierarchyIncomingCallsParams) ([]protocol.CallHierarchyIncomingCall, error) {\n\tctx, done := event.Start(ctx, \"server.IncomingCalls\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.Item.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.IncomingCalls(ctx, snapshot, fh, params.Item.Range)\n\t}\n\treturn nil, nil // empty result\n}\n\nfunc (s *server) OutgoingCalls(ctx context.Context, params *protocol.CallHierarchyOutgoingCallsParams) ([]protocol.CallHierarchyOutgoingCall, error) {\n\tctx, done := event.Start(ctx, \"server.OutgoingCalls\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.Item.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.OutgoingCalls(ctx, snapshot, fh, params.Item.Range.Start)\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/code_action.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) CodeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {\n\tctx, done := event.Start(ctx, \"server.CodeAction\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\turi := fh.URI()\n\tkind := snapshot.FileKind(fh)\n\n\t// Determine the supported code action kinds for this file.\n\t//\n\t// We interpret CodeActionKinds hierarchically, so refactor.rewrite\n\t// subsumes refactor.rewrite.change_quote, for example,\n\t// and \"\" (protocol.Empty) subsumes all kinds.\n\t// See ../protocol/codeactionkind.go for some code action theory.\n\t//\n\t// The Context.Only field specifies which code actions\n\t// the client wants. According to LSP 3.18 textDocument_codeAction,\n\t// an Only=[] should be interpreted as Only=[\"quickfix\"]:\n\t//\n\t//   \"In version 1.0 of the protocol, there weren’t any\n\t//   source or refactoring code actions. Code actions\n\t//   were solely used to (quick) fix code, not to\n\t//   write/rewrite code. So if a client asks for code\n\t//   actions without any kind, the standard quick fix\n\t//   code actions should be returned.\"\n\t//\n\t// However, this would deny clients (e.g. Vim+coc.nvim,\n\t// Emacs+eglot, and possibly others) the easiest and most\n\t// natural way of querying the server for the entire set of\n\t// available code actions. But reporting all available code\n\t// actions would be a nuisance for VS Code, since mere cursor\n\t// motion into a region with a code action (~anywhere) would\n\t// trigger a lightbulb usually associated with quickfixes.\n\t//\n\t// As a compromise, we use the trigger kind as a heuristic: if\n\t// the query was triggered by cursor motion (Automatic), we\n\t// respond with only quick fixes; if the query was invoked\n\t// explicitly (Invoked), we respond with all available\n\t// actions.\n\tcodeActionKinds := make(map[protocol.CodeActionKind]bool)\n\tif len(params.Context.Only) > 0 {\n\t\tfor _, kind := range params.Context.Only { // kind may be \"\" (=> all)\n\t\t\tcodeActionKinds[kind] = true\n\t\t}\n\t} else {\n\t\t// No explicit kind specified.\n\t\t// Heuristic: decide based on trigger.\n\t\tif triggerKind(params) == protocol.CodeActionAutomatic {\n\t\t\t// e.g. cursor motion: show only quick fixes\n\t\t\tcodeActionKinds[protocol.QuickFix] = true\n\t\t} else {\n\t\t\t// e.g. a menu selection (or unknown trigger kind,\n\t\t\t// as in our tests): show all available code actions.\n\t\t\tcodeActionKinds[protocol.Empty] = true\n\t\t}\n\t}\n\n\t// enabled reports whether the specified kind of code action is required.\n\tenabled := func(kind protocol.CodeActionKind) bool {\n\t\t// Given \"refactor.rewrite.foo\", check for it,\n\t\t// then \"refactor.rewrite\", \"refactor\", then \"\".\n\t\t// A false map entry prunes the search for ancestors.\n\t\t//\n\t\t// If codeActionKinds contains protocol.Empty (\"\"),\n\t\t// all kinds are enabled.\n\t\tfor {\n\t\t\tif v, ok := codeActionKinds[kind]; ok {\n\t\t\t\treturn v\n\t\t\t}\n\t\t\tif kind == \"\" {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// The \"source.test\" code action shouldn't be\n\t\t\t// returned to the client unless requested by\n\t\t\t// an exact match in Only.\n\t\t\t//\n\t\t\t// This mechanism exists to avoid a distracting\n\t\t\t// lightbulb (code action) on each Test function.\n\t\t\t// These actions are unwanted in VS Code because it\n\t\t\t// has Test Explorer, and in other editors because\n\t\t\t// the UX of executeCommand is unsatisfactory for tests:\n\t\t\t// it doesn't show the complete streaming output.\n\t\t\t// See https://github.com/joaotavora/eglot/discussions/1402\n\t\t\t// for a better solution. See also\n\t\t\t// https://github.com/golang/go/issues/67400.\n\t\t\t//\n\t\t\t// TODO(adonovan): consider instead switching on\n\t\t\t// codeActionTriggerKind. Perhaps other noisy Source\n\t\t\t// Actions should be guarded in the same way.\n\t\t\tif kind == settings.GoTest {\n\t\t\t\treturn false // don't search ancestors\n\t\t\t}\n\n\t\t\t// Try the parent.\n\t\t\tif dot := strings.LastIndexByte(string(kind), '.'); dot >= 0 {\n\t\t\t\tkind = kind[:dot] // \"refactor.foo\" -> \"refactor\"\n\t\t\t} else {\n\t\t\t\tkind = \"\" // \"refactor\" -> \"\"\n\t\t\t}\n\t\t}\n\t}\n\n\tswitch kind {\n\tcase file.Mod:\n\t\tvar actions []protocol.CodeAction\n\n\t\tfixes, err := s.codeActionsMatchingDiagnostics(ctx, fh.URI(), snapshot, params.Context.Diagnostics, enabled)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Group vulnerability fixes by their range, and select only the most\n\t\t// appropriate upgrades.\n\t\t//\n\t\t// TODO(rfindley): can this instead be accomplished on the diagnosis side,\n\t\t// so that code action handling remains uniform?\n\t\tvulnFixes := make(map[protocol.Range][]protocol.CodeAction)\n\tsearchFixes:\n\t\tfor _, fix := range fixes {\n\t\t\tfor _, diag := range fix.Diagnostics {\n\t\t\t\tif diag.Source == string(cache.Govulncheck) || diag.Source == string(cache.Vulncheck) {\n\t\t\t\t\tvulnFixes[diag.Range] = append(vulnFixes[diag.Range], fix)\n\t\t\t\t\tcontinue searchFixes\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions = append(actions, fix)\n\t\t}\n\n\t\tfor _, fixes := range vulnFixes {\n\t\t\tfixes = mod.SelectUpgradeCodeActions(fixes)\n\t\t\tactions = append(actions, fixes...)\n\t\t}\n\n\t\treturn actions, nil\n\n\tcase file.Go:\n\t\t// diagnostic-bundled code actions\n\t\t//\n\t\t// The diagnostics already have a UI presence (e.g. squiggly underline);\n\t\t// the associated action may additionally show (in VS Code) as a lightbulb.\n\t\t// Note s.codeActionsMatchingDiagnostics returns only fixes\n\t\t// detected during the analysis phase. golang.CodeActions computes\n\t\t// extra changes that can address some diagnostics.\n\t\tactions, err := s.codeActionsMatchingDiagnostics(ctx, uri, snapshot, params.Context.Diagnostics, enabled)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// computed code actions (may include quickfixes from diagnostics)\n\t\tmoreActions, err := golang.CodeActions(ctx, snapshot, s.Options(), fh, params.Range, params.Context.Diagnostics, enabled, triggerKind(params))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tactions = append(actions, moreActions...)\n\n\t\t// Don't suggest most fixes for generated files, since they are generally\n\t\t// not useful and some editors may apply them automatically on save.\n\t\t// (Unfortunately there's no reliable way to distinguish fixes from\n\t\t// queries, so we must list all kinds of queries here.)\n\t\t//\n\t\t// We make an exception for OrganizeImports, because\n\t\t// (a) it is needed when making temporary experimental\n\t\t//     changes (e.g. adding logging) in generated files, and\n\t\t// (b) it doesn't report diagnostics on well-formed code, and\n\t\t//     unedited generated files must be well formed.\n\t\tif golang.IsGenerated(ctx, snapshot, uri) {\n\t\t\tactions = slices.DeleteFunc(actions, func(a protocol.CodeAction) bool {\n\t\t\t\tswitch a.Kind {\n\t\t\t\tcase settings.GoTest,\n\t\t\t\t\tsettings.GoDoc,\n\t\t\t\t\tsettings.GoFreeSymbols,\n\t\t\t\t\tsettings.GoSplitPackage,\n\t\t\t\t\tsettings.GoAssembly,\n\t\t\t\t\tsettings.GoplsDocFeatures,\n\t\t\t\t\tsettings.GoToggleCompilerOptDetails:\n\t\t\t\t\treturn false // read-only query\n\t\t\t\tcase settings.OrganizeImports:\n\t\t\t\t\treturn false // fix allowed in generated files (see #73959)\n\t\t\t\t}\n\t\t\t\treturn true // potential write operation\n\t\t\t})\n\t\t}\n\n\t\treturn actions, nil\n\n\tdefault:\n\t\t// Unsupported file kind for a code action.\n\t\treturn nil, nil\n\t}\n}\n\nfunc triggerKind(params *protocol.CodeActionParams) protocol.CodeActionTriggerKind {\n\tif kind := params.Context.TriggerKind; kind != nil { // (some clients omit it)\n\t\treturn *kind\n\t}\n\treturn protocol.CodeActionUnknownTrigger\n}\n\n// ResolveCodeAction resolves missing Edit information (that is, computes the\n// details of the necessary patch) in the given code action using the provided\n// Data field of the CodeAction, which should contain the raw json of a protocol.Command.\n//\n// This should be called by the client before applying code actions, when the\n// client has code action resolve support.\n//\n// This feature allows capable clients to preview and selectively apply the diff\n// instead of applying the whole thing unconditionally through workspace/applyEdit.\nfunc (s *server) ResolveCodeAction(ctx context.Context, ca *protocol.CodeAction) (*protocol.CodeAction, error) {\n\tctx, done := event.Start(ctx, \"server.ResolveCodeAction\")\n\tdefer done()\n\n\t// Only resolve the code action if there is Data provided.\n\tvar cmd protocol.Command\n\tif ca.Data != nil {\n\t\tif err := protocol.UnmarshalJSON(*ca.Data, &cmd); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tca.Data = nil\n\tif cmd.Command != \"\" {\n\t\t// Try to resolve codeaction edits by running the command.\n\t\t//\n\t\t// Unfortunately, we can't simply report failure to execute the command, as\n\t\t// some clients (namely, VS Code with the Live Share extension) eagerly\n\t\t// resolve *all* code actions, and returning an error leads to spammy\n\t\t// popups. Instead, we simply set the command on the code action, and let\n\t\t// it fail if/when invoked (golang/go#75442).\n\t\t//\n\t\t// This is arguably a client-side bug, but we work around it as it causes\n\t\t// significant problems for our users.\n\t\t// https://github.com/microsoft/live-share/issues/5293\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   cmd.Command,\n\t\t\tArguments: cmd.Arguments,\n\t\t}\n\t\thandler := &commandHandler{\n\t\t\ts:      s,\n\t\t\tparams: params,\n\t\t}\n\t\tedit, err := command.Dispatch(ctx, params, handler)\n\t\tif err != nil {\n\t\t\t// Resolving edits failed, so just resolve the command.\n\t\t\tca.Command = &cmd\n\t\t\treturn ca, nil\n\t\t}\n\t\tvar ok bool\n\t\tif ca.Edit, ok = edit.(*protocol.WorkspaceEdit); !ok {\n\t\t\treturn nil, fmt.Errorf(\"unable to resolve code action %q\", ca.Title)\n\t\t}\n\t}\n\treturn ca, nil\n}\n\n// codeActionsMatchingDiagnostics creates code actions for the\n// provided diagnostics, by unmarshalling actions bundled in the\n// protocol.Diagnostic.Data field or, if there were none, by creating\n// actions from edits associated with a matching Diagnostic from the\n// set of stored diagnostics for this file.\nfunc (s *server) codeActionsMatchingDiagnostics(ctx context.Context, uri protocol.DocumentURI, snapshot *cache.Snapshot, pds []protocol.Diagnostic, enabled func(protocol.CodeActionKind) bool) ([]protocol.CodeAction, error) {\n\tvar actions []protocol.CodeAction\n\tvar unbundled []protocol.Diagnostic // diagnostics without bundled code actions in their Data field\n\tfor _, pd := range pds {\n\t\tbundled, err := cache.BundledLazyFixes(pd)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(bundled) > 0 {\n\t\t\tfor _, fix := range bundled {\n\t\t\t\tif enabled(fix.Kind) {\n\t\t\t\t\tactions = append(actions, fix)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// No bundled actions: keep searching for a match.\n\t\t\tunbundled = append(unbundled, pd)\n\t\t}\n\t}\n\n\tfor _, pd := range unbundled {\n\t\tfor _, sd := range s.findMatchingDiagnostics(uri, pd) {\n\t\t\tdiagActions, err := codeActionsForDiagnostic(ctx, snapshot, sd, &pd, enabled)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tactions = append(actions, diagActions...)\n\t\t}\n\t}\n\treturn actions, nil\n}\n\nfunc codeActionsForDiagnostic(ctx context.Context, snapshot *cache.Snapshot, sd *cache.Diagnostic, pd *protocol.Diagnostic, enabled func(protocol.CodeActionKind) bool) ([]protocol.CodeAction, error) {\n\tvar actions []protocol.CodeAction\n\tfor _, fix := range sd.SuggestedFixes {\n\t\tif !enabled(fix.ActionKind) {\n\t\t\tcontinue\n\t\t}\n\t\tvar changes []protocol.DocumentChange\n\t\tfor uri, edits := range fix.Edits {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tchange := protocol.DocumentChangeEdit(fh, edits)\n\t\t\tchanges = append(changes, change)\n\t\t}\n\t\tactions = append(actions, protocol.CodeAction{\n\t\t\tTitle:       fix.Title,\n\t\t\tKind:        fix.ActionKind,\n\t\t\tEdit:        protocol.NewWorkspaceEdit(changes...),\n\t\t\tCommand:     fix.Command,\n\t\t\tDiagnostics: []protocol.Diagnostic{*pd},\n\t\t})\n\t}\n\treturn actions, nil\n}\n\nfunc (s *server) findMatchingDiagnostics(uri protocol.DocumentURI, pd protocol.Diagnostic) []*cache.Diagnostic {\n\ts.diagnosticsMu.Lock()\n\tdefer s.diagnosticsMu.Unlock()\n\n\tvar sds []*cache.Diagnostic\n\tif fileDiags := s.diagnostics[uri]; fileDiags != nil {\n\t\tfor _, viewDiags := range fileDiags.byView {\n\t\t\tfor _, sd := range viewDiags.diagnostics {\n\t\t\t\t// extra space may have been trimmed when\n\t\t\t\t// converting to protocol.Diagnostic\n\t\t\t\tsameDiagnostic := pd.Message == strings.TrimSpace(sd.Message) &&\n\t\t\t\t\tprotocol.CompareRange(pd.Range, sd.Range) == 0 &&\n\t\t\t\t\tpd.Source == string(sd.Source)\n\n\t\t\t\tif sameDiagnostic {\n\t\t\t\t\tsds = append(sds, sd)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn sds\n}\n\nfunc (s *server) getSupportedCodeActions() []protocol.CodeActionKind {\n\tallCodeActionKinds := make(map[protocol.CodeActionKind]struct{})\n\tfor _, kinds := range s.Options().SupportedCodeActions {\n\t\tfor kind := range kinds {\n\t\t\tallCodeActionKinds[kind] = struct{}{}\n\t\t}\n\t}\n\tvar result []protocol.CodeActionKind\n\tfor kind := range allCodeActionKinds {\n\t\tresult = append(result, kind)\n\t}\n\tslices.Sort(result)\n\treturn result\n}\n\ntype unit = struct{}\n"
  },
  {
    "path": "gopls/internal/server/code_lens.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\ntype codeLensMetadata struct {\n\tSource string `json:\"source\"`\n}\n\n// CodeLens reports the set of available CodeLenses\n// (range-associated commands) in the given file.\nfunc (s *server) CodeLens(ctx context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) {\n\tctx, done := event.Start(ctx, \"server.CodeLens\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tvar lensFuncs map[settings.CodeLensSource]cache.CodeLensSourceFunc\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Mod:\n\t\tlensFuncs = mod.CodeLensSources()\n\tcase file.Go:\n\t\tlensFuncs = golang.CodeLensSources()\n\tdefault:\n\t\t// Unsupported file kind for a code lens.\n\t\treturn nil, nil\n\t}\n\tvar lenses []protocol.CodeLens\n\tfor kind, lensFunc := range lensFuncs {\n\t\tif !snapshot.Options().Codelenses[kind] {\n\t\t\tcontinue\n\t\t}\n\t\tadded, err := lensFunc(ctx, snapshot, fh)\n\t\t// Code lens is called on every keystroke, so we should just operate in\n\t\t// a best-effort mode, ignoring errors.\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, fmt.Sprintf(\"code lens %s failed\", kind), err)\n\t\t\tcontinue\n\t\t}\n\t\tlenses = append(lenses, added...)\n\t}\n\tfor i := range lenses {\n\t\tif lenses[i].Command == nil {\n\t\t\tcontinue\n\t\t}\n\t\tmeta := codeLensMetadata{Source: \"codelens\"}\n\t\tmetaBytes, err := json.Marshal(meta)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"failed to marshal codelens metadata\", err)\n\t\t\tcontinue\n\t\t}\n\t\tlenses[i].Command.Arguments = append(lenses[i].Command.Arguments, json.RawMessage(metaBytes))\n\t}\n\tsort.Slice(lenses, func(i, j int) bool {\n\t\ta, b := lenses[i], lenses[j]\n\t\tif cmp := protocol.CompareRange(a.Range, b.Range); cmp != 0 {\n\t\t\treturn cmp < 0\n\t\t}\n\t\treturn a.Command.Command < b.Command.Command\n\t})\n\treturn lenses, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/command.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/fatih/gomodifytags/modifytags\"\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/tokeninternal\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/scan\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\nfunc (s *server) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (any, error) {\n\tctx, done := event.Start(ctx, \"server.ExecuteCommand\")\n\tdefer done()\n\n\t// For test synchronization, always create a progress notification.\n\t//\n\t// This may be in addition to user-facing progress notifications created in\n\t// the course of command execution.\n\tif s.Options().VerboseWorkDoneProgress {\n\t\twork := s.progress.Start(ctx, params.Command, \"Verbose: running command...\", nil, nil)\n\t\tdefer work.End(ctx, \"Done.\")\n\t}\n\n\tif !slices.Contains(s.Options().SupportedCommands, params.Command) {\n\t\treturn nil, fmt.Errorf(\"%s is not a supported command\", params.Command)\n\t}\n\n\tif len(params.Arguments) > 0 {\n\t\tlast := params.Arguments[len(params.Arguments)-1]\n\t\tvar meta struct {\n\t\t\tSource string `json:\"source\"`\n\t\t}\n\t\tif err := json.Unmarshal(last, &meta); err == nil && meta.Source != \"\" {\n\t\t\tcommandName := strings.TrimPrefix(params.Command, \"gopls.\")\n\t\t\tcounterName := fmt.Sprintf(\"gopls/cmd/source:%s-%s\", commandName, meta.Source)\n\t\t\tcounter.New(counterName).Inc()\n\t\t\tparams.Arguments = params.Arguments[:len(params.Arguments)-1]\n\t\t}\n\t}\n\n\thandler := &commandHandler{\n\t\ts:      s,\n\t\tparams: params,\n\t}\n\treturn command.Dispatch(ctx, params, handler)\n}\n\ntype commandHandler struct {\n\ts      *server\n\tparams *protocol.ExecuteCommandParams\n}\n\nfunc (h *commandHandler) Modules(ctx context.Context, args command.ModulesArgs) (command.ModulesResult, error) {\n\t// keepModule filters modules based on the command args\n\tkeepModule := func(goMod protocol.DocumentURI) bool {\n\t\t// Does the directory enclose the view's go.mod file?\n\t\tif !args.Dir.Encloses(goMod) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Calculate the relative path\n\t\trel, err := filepath.Rel(args.Dir.Path(), goMod.Path())\n\t\tif err != nil {\n\t\t\treturn false // \"can't happen\" (see prior Encloses check)\n\t\t}\n\n\t\tassert(goMod.Base() == \"go.mod\", fmt.Sprintf(\"invalid go.mod path: want go.mod, got %q\", goMod.Path()))\n\n\t\t// Invariant: rel is a relative path without \"../\" segments and the last\n\t\t// segment is \"go.mod\"\n\t\tnparts := strings.Count(rel, string(filepath.Separator))\n\t\treturn args.MaxDepth < 0 || nparts <= args.MaxDepth\n\t}\n\n\t// Views may include:\n\t//   - go.work views containing one or more modules each;\n\t//   - go.mod views containing a single module each;\n\t//   - GOPATH and/or ad hoc views containing no modules.\n\t//\n\t// Retrieving a view via the request path would only work for a\n\t// non-recursive query for a go.mod view, and even in that case\n\t// [Session.SnapshotOf] doesn't work on directories. Thus we check every\n\t// view.\n\tvar result command.ModulesResult\n\tseen := map[protocol.DocumentURI]bool{}\n\tfor _, v := range h.s.session.Views() {\n\t\ts, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\treturn command.ModulesResult{}, err\n\t\t}\n\t\tdefer release()\n\n\t\tfor _, modFile := range v.ModFiles() {\n\t\t\tif !keepModule(modFile) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Deduplicate\n\t\t\tif seen[modFile] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[modFile] = true\n\n\t\t\tfh, err := s.ReadFile(ctx, modFile)\n\t\t\tif err != nil {\n\t\t\t\treturn command.ModulesResult{}, err\n\t\t\t}\n\t\t\tmod, err := s.ParseMod(ctx, fh)\n\t\t\tif err != nil {\n\t\t\t\treturn command.ModulesResult{}, err\n\t\t\t}\n\t\t\tif mod.File.Module == nil {\n\t\t\t\tcontinue // syntax contains errors\n\t\t\t}\n\t\t\tresult.Modules = append(result.Modules, command.Module{\n\t\t\t\tPath:    mod.File.Module.Mod.Path,\n\t\t\t\tVersion: mod.File.Module.Mod.Version,\n\t\t\t\tGoMod:   mod.URI,\n\t\t\t})\n\t\t}\n\t}\n\treturn result, nil\n}\n\nfunc (h *commandHandler) Packages(ctx context.Context, args command.PackagesArgs) (command.PackagesResult, error) {\n\t// Convert file arguments into directories\n\tdirs := make([]protocol.DocumentURI, len(args.Files))\n\tfor i, file := range args.Files {\n\t\tif filepath.Ext(file.Path()) == \".go\" {\n\t\t\tdirs[i] = file.Dir()\n\t\t} else {\n\t\t\tdirs[i] = file\n\t\t}\n\t}\n\n\tkeepPackage := func(pkg *metadata.Package) bool {\n\t\tfor _, file := range pkg.GoFiles {\n\t\t\tfor _, dir := range dirs {\n\t\t\t\tif file.Dir() == dir || args.Recursive && dir.Encloses(file) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tresult := command.PackagesResult{\n\t\tModule: make(map[string]command.Module),\n\t}\n\n\terr := h.run(ctx, commandConfig{\n\t\tprogress: \"Packages\",\n\t}, func(ctx context.Context, _ commandDeps) error {\n\t\tfor _, view := range h.s.session.Views() {\n\t\t\tsnapshot, release, err := view.Snapshot()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer release()\n\n\t\t\tmetas, err := snapshot.WorkspaceMetadata(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Filter out unwanted packages\n\t\t\tmetas = slices.DeleteFunc(metas, func(meta *metadata.Package) bool {\n\t\t\t\treturn meta.IsIntermediateTestVariant() ||\n\t\t\t\t\t!keepPackage(meta)\n\t\t\t})\n\n\t\t\tstart := len(result.Packages)\n\t\t\tfor _, meta := range metas {\n\t\t\t\tvar mod command.Module\n\t\t\t\tif meta.Module != nil {\n\t\t\t\t\tmod = command.Module{\n\t\t\t\t\t\tPath:    meta.Module.Path,\n\t\t\t\t\t\tVersion: meta.Module.Version,\n\t\t\t\t\t\tGoMod:   protocol.URIFromPath(meta.Module.GoMod),\n\t\t\t\t\t}\n\t\t\t\t\tresult.Module[mod.Path] = mod // Overwriting is ok\n\t\t\t\t}\n\n\t\t\t\tresult.Packages = append(result.Packages, command.Package{\n\t\t\t\t\tPath:       string(meta.PkgPath),\n\t\t\t\t\tForTest:    string(meta.ForTest),\n\t\t\t\t\tModulePath: mod.Path,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif args.Mode&command.NeedTests == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Make a single request to the index (per snapshot) to minimize the\n\t\t\t// performance hit\n\t\t\tvar ids []cache.PackageID\n\t\t\tfor _, meta := range metas {\n\t\t\t\tids = append(ids, meta.ID)\n\t\t\t}\n\n\t\t\tallTests, err := snapshot.Tests(ctx, ids...)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tfor i, tests := range allTests {\n\t\t\t\tpkg := &result.Packages[start+i]\n\t\t\t\tfileByPath := map[protocol.DocumentURI]*command.TestFile{}\n\t\t\t\tfor _, test := range tests.All() {\n\t\t\t\t\ttest := command.TestCase{\n\t\t\t\t\t\tName: test.Name,\n\t\t\t\t\t\tLoc:  test.Location,\n\t\t\t\t\t}\n\n\t\t\t\t\tfile, ok := fileByPath[test.Loc.URI]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tf := command.TestFile{\n\t\t\t\t\t\t\tURI: test.Loc.URI,\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti := len(pkg.TestFiles)\n\t\t\t\t\t\tpkg.TestFiles = append(pkg.TestFiles, f)\n\t\t\t\t\t\tfile = &pkg.TestFiles[i]\n\t\t\t\t\t\tfileByPath[test.Loc.URI] = file\n\t\t\t\t\t}\n\t\t\t\t\tfile.Tests = append(file.Tests, test)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t})\n\treturn result, err\n}\n\nfunc (h *commandHandler) MaybePromptForTelemetry(ctx context.Context) error {\n\t// if the server's TelemetryPrompt is true, it's likely the server already\n\t// handled prompting for it. Don't try to prompt again.\n\tif !h.s.options.TelemetryPrompt {\n\t\tgo h.s.maybePromptForTelemetry(ctx, true)\n\t}\n\treturn nil\n}\n\nfunc (*commandHandler) AddTelemetryCounters(_ context.Context, args command.AddTelemetryCountersArgs) error {\n\tif len(args.Names) != len(args.Values) {\n\t\treturn fmt.Errorf(\"Names and Values must have the same length\")\n\t}\n\t// invalid counter update requests will be silently dropped. (no audience)\n\tfor i, n := range args.Names {\n\t\tv := args.Values[i]\n\t\tif n == \"\" || v < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tcounter.Add(\"fwd/\"+n, v)\n\t}\n\treturn nil\n}\n\nfunc (c *commandHandler) AddTest(ctx context.Context, loc protocol.Location) (*protocol.WorkspaceEdit, error) {\n\tvar result *protocol.WorkspaceEdit\n\terr := c.run(ctx, commandConfig{\n\t\tforURI: loc.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tif deps.snapshot.FileKind(deps.fh) != file.Go {\n\t\t\treturn fmt.Errorf(\"can't add test for non-Go file\")\n\t\t}\n\t\tdocedits, show, err := golang.AddTestForFunc(ctx, deps.snapshot, loc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := applyChanges(ctx, c.s.client, docedits); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif show != nil {\n\t\t\tshowDocumentImpl(ctx, c.s.client, protocol.URI(show.URI), &show.Range, c.s.options)\n\t\t}\n\t\treturn nil\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) LSP(ctx context.Context, param command.LSPArgs) (any, error) {\n\tresponse, valid, err := protocol.ServerDispatchCall(ctx, c.s, param.Method, param.Param)\n\tif !valid {\n\t\treturn nil, fmt.Errorf(\"method %s does not exist\", param.Method)\n\t}\n\n\treturn response, err\n}\n\n// commandConfig configures common command set-up and execution.\ntype commandConfig struct {\n\trequireSave   bool                           // whether all files must be saved for the command to work\n\tprogress      string                         // title to use for progress reporting. If empty, no progress will be reported.\n\tprogressStyle settings.WorkDoneProgressStyle // style information for client-side progress display.\n\tforView       string                         // view to resolve to a snapshot; incompatible with forURI\n\tforURI        protocol.DocumentURI           // URI to resolve to a snapshot. If unset, snapshot will be nil.\n}\n\n// commandDeps is evaluated from a commandConfig. Note that not all fields may\n// be populated, depending on which configuration is set. See comments in-line\n// for details.\ntype commandDeps struct {\n\tsnapshot *cache.Snapshot    // present if cfg.forURI or forView was set\n\tfh       file.Handle        // present if cfg.forURI was set\n\twork     *progress.WorkDone // present if cfg.progress was set\n}\n\ntype commandFunc func(context.Context, commandDeps) error\n\n// These strings are reported as the final WorkDoneProgressEnd message\n// for each workspace/executeCommand request.\nconst (\n\tCommandCanceled  = \"canceled\"\n\tCommandFailed    = \"failed\"\n\tCommandCompleted = \"completed\"\n)\n\n// run performs command setup for command execution, and invokes the given run\n// function. If cfg.async is set, run executes the given func in a separate\n// goroutine, and returns as soon as setup is complete and the goroutine is\n// scheduled.\n//\n// Invariant: if the resulting error is non-nil, the given run func will\n// (eventually) be executed exactly once.\nfunc (c *commandHandler) run(ctx context.Context, cfg commandConfig, run commandFunc) (err error) {\n\tif cfg.requireSave {\n\t\tvar unsaved []string\n\t\tfor _, overlay := range c.s.session.Overlays() {\n\t\t\tif !overlay.SameContentsOnDisk() {\n\t\t\t\tunsaved = append(unsaved, overlay.URI().Path())\n\t\t\t}\n\t\t}\n\t\tif len(unsaved) > 0 {\n\t\t\treturn fmt.Errorf(\"All files must be saved first (unsaved: %v).\", unsaved)\n\t\t}\n\t}\n\tvar deps commandDeps\n\tvar release func()\n\tif cfg.forURI != \"\" && cfg.forView != \"\" {\n\t\treturn bug.Errorf(\"internal error: forURI=%q, forView=%q\", cfg.forURI, cfg.forView)\n\t}\n\tif cfg.forURI != \"\" {\n\t\tdeps.fh, deps.snapshot, release, err = c.s.session.FileOf(ctx, cfg.forURI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t} else if cfg.forView != \"\" {\n\t\tview, err := c.s.session.View(cfg.forView)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdeps.snapshot, release, err = view.Snapshot()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t} else {\n\t\trelease = func() {}\n\t}\n\t// Inv: release() must be called exactly once after this point.\n\t// In the async case, runcmd may outlive run().\n\n\tctx, cancel := context.WithCancel(xcontext.Detach(ctx))\n\tif cfg.progress != \"\" {\n\t\theader := \"\"\n\t\tif _, ok := c.s.options.SupportedWorkDoneProgressFormats[cfg.progressStyle]; ok && cfg.progressStyle != \"\" {\n\t\t\theader = fmt.Sprintf(\"style: %s\\n\\n\", cfg.progressStyle)\n\t\t}\n\t\tdeps.work = c.s.progress.Start(ctx, cfg.progress, header+\"Running...\", c.params.WorkDoneToken, cancel)\n\t}\n\truncmd := func() error {\n\t\tdefer release()\n\t\tdefer cancel()\n\t\terr := run(ctx, deps)\n\t\tif deps.work != nil {\n\t\t\tswitch {\n\t\t\tcase errors.Is(err, context.Canceled):\n\t\t\t\tdeps.work.End(ctx, CommandCanceled)\n\t\t\tcase err != nil:\n\t\t\t\tevent.Error(ctx, \"command error\", err)\n\t\t\t\tdeps.work.End(ctx, CommandFailed)\n\t\t\tdefault:\n\t\t\t\tdeps.work.End(ctx, CommandCompleted)\n\t\t\t}\n\t\t}\n\t\treturn err\n\t}\n\n\t// For legacy reasons, gopls.run_govulncheck must run asynchronously.\n\t// TODO(golang/vscode-go#3572): remove this (along with the\n\t// gopls.run_govulncheck command entirely) once VS Code only uses the new\n\t// gopls.vulncheck command.\n\tif c.params.Command == \"gopls.run_govulncheck\" {\n\t\tif cfg.progress == \"\" {\n\t\t\tlog.Fatalf(\"asynchronous command gopls.run_govulncheck does not enable progress reporting\")\n\t\t}\n\t\tgo func() {\n\t\t\tif err := runcmd(); err != nil {\n\t\t\t\tshowMessage(ctx, c.s.client, protocol.Error, err.Error())\n\t\t\t}\n\t\t}()\n\t\treturn nil\n\t}\n\n\treturn runcmd()\n}\n\nfunc (c *commandHandler) ApplyFix(ctx context.Context, args command.ApplyFixArgs) (*protocol.WorkspaceEdit, error) {\n\tvar result *protocol.WorkspaceEdit\n\terr := c.run(ctx, commandConfig{\n\t\t// Note: no progress here. Applying fixes should be quick.\n\t\tforURI: args.Location.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tchanges, err := golang.ApplyFix(ctx, args.Fix, deps.snapshot, deps.fh, args.Location.Range)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\twsedit := protocol.NewWorkspaceEdit(changes...)\n\t\tif args.ResolveEdits {\n\t\t\tresult = wsedit\n\t\t\treturn nil\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, changes)\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) RegenerateCgo(ctx context.Context, args command.URIArg) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Regenerating Cgo\",\n\t}, func(ctx context.Context, _ commandDeps) error {\n\t\treturn c.modifyState(ctx, FromRegenerateCgo, func() (*cache.Snapshot, func(), error) {\n\t\t\t// Resetting the view causes cgo to be regenerated via `go list`.\n\t\t\tv, err := c.s.session.ResetView(ctx, args.URI)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\treturn v.Snapshot()\n\t\t})\n\t})\n}\n\n// modifyState performs an operation that modifies the snapshot state.\n//\n// It causes a snapshot diagnosis for the provided ModificationSource.\nfunc (c *commandHandler) modifyState(ctx context.Context, source ModificationSource, work func() (*cache.Snapshot, func(), error)) error {\n\tvar wg sync.WaitGroup // tracks work done on behalf of this function, incl. diagnostics\n\twg.Add(1)\n\tdefer wg.Done()\n\n\t// Track progress on this operation for testing.\n\tif c.s.Options().VerboseWorkDoneProgress {\n\t\twork := c.s.progress.Start(ctx, DiagnosticWorkTitle(source), \"Calculating file diagnostics...\", nil, nil)\n\t\tgo func() {\n\t\t\twg.Wait()\n\t\t\twork.End(ctx, \"Done.\")\n\t\t}()\n\t}\n\tsnapshot, release, err := work()\n\tif err != nil {\n\t\treturn err\n\t}\n\twg.Go(func() {\n\t\t// Diagnosing with the background context ensures new snapshots are fully\n\t\t// diagnosed.\n\t\tc.s.diagnoseSnapshot(snapshot.BackgroundContext(), snapshot, nil, 0)\n\t\trelease()\n\t})\n\treturn nil\n}\n\nfunc (c *commandHandler) CheckUpgrades(ctx context.Context, args command.CheckUpgradesArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tforURI:   args.URI,\n\t\tprogress: \"Checking for upgrades\",\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\treturn c.modifyState(ctx, FromCheckUpgrades, func() (*cache.Snapshot, func(), error) {\n\t\t\tupgrades, err := c.s.getUpgrades(ctx, deps.snapshot, args.URI, args.Modules)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\treturn c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{\n\t\t\t\tModuleUpgrades: map[protocol.DocumentURI]map[string]string{args.URI: upgrades},\n\t\t\t})\n\t\t})\n\t})\n}\n\nfunc (c *commandHandler) AddDependency(ctx context.Context, args command.DependencyArgs) error {\n\treturn c.GoGetModule(ctx, args)\n}\n\nfunc (c *commandHandler) UpgradeDependency(ctx context.Context, args command.DependencyArgs) error {\n\treturn c.GoGetModule(ctx, args)\n}\n\nfunc (c *commandHandler) ResetGoModDiagnostics(ctx context.Context, args command.ResetGoModDiagnosticsArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tforURI: args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\treturn c.modifyState(ctx, FromResetGoModDiagnostics, func() (*cache.Snapshot, func(), error) {\n\t\t\treturn c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{\n\t\t\t\tModuleUpgrades: map[protocol.DocumentURI]map[string]string{\n\t\t\t\t\tdeps.fh.URI(): nil,\n\t\t\t\t},\n\t\t\t\tVulns: map[protocol.DocumentURI]*vulncheck.Result{\n\t\t\t\t\tdeps.fh.URI(): nil,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\t})\n}\n\nfunc (c *commandHandler) GoGetModule(ctx context.Context, args command.DependencyArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Running go get\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\treturn c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\treturn runGoGetModule(invoke, args.AddRequire, args.GoCmdArgs)\n\t\t})\n\t})\n}\n\n// TODO(rFindley): UpdateGoSum, Tidy, and Vendor could probably all be one command.\nfunc (c *commandHandler) UpdateGoSum(ctx context.Context, args command.URIArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Updating go.sum\",\n\t}, func(ctx context.Context, _ commandDeps) error {\n\t\tfor _, uri := range args.URIs {\n\t\t\tfh, snapshot, release, err := c.s.session.FileOf(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer release()\n\t\t\tif err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\t\t_, err := invoke(\"list\", \"all\")\n\t\t\t\treturn err\n\t\t\t}); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) Tidy(ctx context.Context, args command.URIArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Running go mod tidy\",\n\t}, func(ctx context.Context, _ commandDeps) error {\n\t\tfor _, uri := range args.URIs {\n\t\t\tfh, snapshot, release, err := c.s.session.FileOf(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer release()\n\t\t\tif err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\t\t_, err := invoke(\"mod\", \"tidy\")\n\t\t\t\treturn err\n\t\t\t}); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) Vendor(ctx context.Context, args command.URIArg) error {\n\treturn c.run(ctx, commandConfig{\n\t\trequireSave: true, // TODO(adonovan): probably not needed; but needs a test.\n\t\tprogress:    \"Running go mod vendor\",\n\t\tforURI:      args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\t// Use RunGoCommandPiped here so that we don't compete with any other go\n\t\t// command invocations. go mod vendor deletes modules.txt before recreating\n\t\t// it, and therefore can run into file locking issues on Windows if that\n\t\t// file is in use by another process, such as go list.\n\t\t//\n\t\t// If golang/go#44119 is resolved, go mod vendor will instead modify\n\t\t// modules.txt in-place. In that case we could theoretically allow this\n\t\t// command to run concurrently.\n\t\tstderr := new(bytes.Buffer)\n\t\tinv, cleanupInvocation, err := deps.snapshot.GoCommandInvocation(cache.NetworkOK, args.URI.DirPath(), \"mod\", []string{\"vendor\"})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cleanupInvocation()\n\t\terr = deps.snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, &bytes.Buffer{}, stderr)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"running go mod vendor failed: %v\\nstderr:\\n%s\", err, stderr.String())\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\trequireSave: true, // if go.mod isn't saved it could cause a problem\n\t\tforURI:      args.URI,\n\t}, func(ctx context.Context, _ commandDeps) error {\n\t\tfh, snapshot, release, err := c.s.session.FileOf(ctx, args.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer release()\n\t\tif err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\t_, err := invoke(\"mod\", \"edit\", \"-go\", args.Version)\n\t\t\treturn err\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Removing dependency\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\t// See the documentation for OnlyDiagnostic.\n\t\t//\n\t\t// TODO(rfindley): In Go 1.17+, we will be able to use the go command\n\t\t// without checking if the module is tidy.\n\t\tif args.OnlyDiagnostic {\n\t\t\treturn c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\t\tif err := runGoGetModule(invoke, false, []string{args.ModulePath + \"@none\"}); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\t_, err := invoke(\"mod\", \"tidy\")\n\t\t\t\treturn err\n\t\t\t})\n\t\t}\n\t\tpm, err := deps.snapshot.ParseMod(ctx, deps.fh)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tedits, err := dropDependency(pm, args.ModulePath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, []protocol.DocumentChange{protocol.DocumentChangeEdit(deps.fh, edits)})\n\t})\n}\n\n// dropDependency returns the edits to remove the given require from the go.mod\n// file.\nfunc dropDependency(pm *cache.ParsedModule, modulePath string) ([]protocol.TextEdit, error) {\n\t// We need a private copy of the parsed go.mod file, since we're going to\n\t// modify it.\n\tcopied, err := modfile.Parse(\"\", pm.Mapper.Content, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := copied.DropRequire(modulePath); err != nil {\n\t\treturn nil, err\n\t}\n\tcopied.Cleanup()\n\tnewContent, err := copied.Format()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Calculate the edits to be made due to the change.\n\tdiff := diff.Bytes(pm.Mapper.Content, newContent)\n\treturn protocol.EditsFromDiffEdits(pm.Mapper, diff)\n}\n\nfunc (c *commandHandler) Doc(ctx context.Context, args command.DocArgs) (protocol.URI, error) {\n\tif args.Location.URI == \"\" {\n\t\treturn \"\", errors.New(\"missing location URI\")\n\t}\n\n\tvar result protocol.URI\n\terr := c.run(ctx, commandConfig{\n\t\tprogress: \"\", // the operation should be fast\n\t\tforURI:   args.Location.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, deps.snapshot, args.Location.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstart, end, err := pgf.RangePos(args.Location.Range)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Start web server.\n\t\tweb, err := c.s.getWeb()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Compute package path and optional symbol fragment\n\t\t// (e.g. \"#Buffer.Len\") from the selection.\n\t\tpkgpath, fragment, _ := golang.DocFragment(pkg, pgf, start, end)\n\n\t\t// Direct the client to open the /pkg page.\n\t\tresult = web.PkgURL(deps.snapshot.View().ID(), pkgpath, fragment)\n\t\tif args.ShowDocument {\n\t\t\topenClientBrowser(ctx, c.s.client, \"Doc\", result, c.s.Options())\n\t\t}\n\n\t\treturn nil\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) RunTests(ctx context.Context, args command.RunTestsArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress:    \"Running go test\", // (asynchronous)\n\t\trequireSave: true,              // go test honors overlays, but tests themselves cannot\n\t\tforURI:      args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tjsonrpc2.Async(ctx) // don't block RPCs behind this command, since it can take a while\n\t\treturn c.runTests(ctx, deps.snapshot, deps.work, args.URI, args.Tests, args.Benchmarks)\n\t})\n}\n\nfunc (c *commandHandler) runTests(ctx context.Context, snapshot *cache.Snapshot, work *progress.WorkDone, uri protocol.DocumentURI, tests, benchmarks []string) error {\n\t// TODO: fix the error reporting when this runs async.\n\tmeta, err := snapshot.NarrowestMetadataForFile(ctx, uri)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpkgPath := string(meta.ForTest)\n\n\t// create output\n\tbuf := &bytes.Buffer{}\n\tew := progress.NewEventWriter(ctx, \"test\")\n\tout := io.MultiWriter(ew, progress.NewWorkDoneWriter(ctx, work), buf)\n\n\t// Run `go test -run Func` on each test.\n\tvar failedTests int\n\tfor _, funcName := range tests {\n\t\targs := []string{pkgPath, \"-v\", \"-count=1\", fmt.Sprintf(\"-run=^%s$\", regexp.QuoteMeta(funcName))}\n\t\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, uri.DirPath(), \"test\", args)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cleanupInvocation()\n\t\tif err := snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, out, out); err != nil {\n\t\t\tif errors.Is(err, context.Canceled) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfailedTests++\n\t\t}\n\t}\n\n\t// Run `go test -run=^$ -bench Func` on each test.\n\tvar failedBenchmarks int\n\tfor _, funcName := range benchmarks {\n\t\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, uri.DirPath(), \"test\", []string{\n\t\t\tpkgPath, \"-v\", \"-run=^$\", fmt.Sprintf(\"-bench=^%s$\", regexp.QuoteMeta(funcName)),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cleanupInvocation()\n\t\tif err := snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, out, out); err != nil {\n\t\t\tif errors.Is(err, context.Canceled) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfailedBenchmarks++\n\t\t}\n\t}\n\n\tvar title string\n\tif len(tests) > 0 && len(benchmarks) > 0 {\n\t\ttitle = \"tests and benchmarks\"\n\t} else if len(tests) > 0 {\n\t\ttitle = \"tests\"\n\t} else if len(benchmarks) > 0 {\n\t\ttitle = \"benchmarks\"\n\t} else {\n\t\treturn errors.New(\"No functions were provided\")\n\t}\n\tmessage := fmt.Sprintf(\"all %s passed\", title)\n\tif failedTests > 0 && failedBenchmarks > 0 {\n\t\tmessage = fmt.Sprintf(\"%d / %d tests failed and %d / %d benchmarks failed\", failedTests, len(tests), failedBenchmarks, len(benchmarks))\n\t} else if failedTests > 0 {\n\t\tmessage = fmt.Sprintf(\"%d / %d tests failed\", failedTests, len(tests))\n\t} else if failedBenchmarks > 0 {\n\t\tmessage = fmt.Sprintf(\"%d / %d benchmarks failed\", failedBenchmarks, len(benchmarks))\n\t}\n\tif failedTests > 0 || failedBenchmarks > 0 {\n\t\tmessage += \"\\n\" + buf.String()\n\t}\n\n\tshowMessage(ctx, c.s.client, protocol.Info, message)\n\n\tif failedTests > 0 || failedBenchmarks > 0 {\n\t\treturn errors.New(\"gopls.test command failed\")\n\t}\n\treturn nil\n}\n\nfunc (c *commandHandler) Generate(ctx context.Context, args command.GenerateArgs) error {\n\ttitle := \"Running go generate .\"\n\tif args.Recursive {\n\t\ttitle = \"Running go generate ./...\"\n\t}\n\treturn c.run(ctx, commandConfig{\n\t\trequireSave: true, // commands executed by go generate cannot honor overlays\n\t\tprogress:    title,\n\t\tforURI:      args.Dir,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\ter := progress.NewEventWriter(ctx, \"generate\")\n\n\t\tpattern := \".\"\n\t\tif args.Recursive {\n\t\t\tpattern = \"./...\"\n\t\t}\n\t\tinv, cleanupInvocation, err := deps.snapshot.GoCommandInvocation(cache.NetworkOK, args.Dir.Path(), \"generate\", []string{\"-x\", pattern})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cleanupInvocation()\n\t\tstderr := io.MultiWriter(er, progress.NewWorkDoneWriter(ctx, deps.work))\n\t\tif err := deps.snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, er, stderr); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) GoGetPackage(ctx context.Context, args command.GoGetPackageArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tforURI:   args.URI,\n\t\tprogress: \"Running go get\",\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tsnapshot := deps.snapshot\n\t\tmodURI := snapshot.GoModForFile(args.URI)\n\t\tif modURI == \"\" {\n\t\t\treturn fmt.Errorf(\"no go.mod file found for %s\", args.URI)\n\t\t}\n\t\ttempDir, cleanupModDir, err := cache.TempModDir(ctx, snapshot, modURI)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating a temp go.mod: %v\", err)\n\t\t}\n\t\tdefer cleanupModDir()\n\n\t\tinv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NetworkOK, modURI.DirPath(), \"list\",\n\t\t\t[]string{\"-f\", \"{{.Module.Path}}@{{.Module.Version}}\", \"-mod=mod\", \"-modfile=\" + filepath.Join(tempDir, \"go.mod\"), args.Pkg},\n\t\t\t\"GOWORK=off\",\n\t\t)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cleanupInvocation()\n\t\tstdout, err := snapshot.View().GoCommandRunner().Run(ctx, *inv)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tver := strings.TrimSpace(stdout.String())\n\t\treturn c.s.runGoModUpdateCommands(ctx, snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {\n\t\t\tif args.AddRequire {\n\t\t\t\tif err := addModuleRequire(invoke, []string{ver}); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\t_, err := invoke(append([]string{\"get\", \"-d\"}, args.Pkg)...)\n\t\t\treturn err\n\t\t})\n\t})\n}\n\nfunc (s *server) runGoModUpdateCommands(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, run func(invoke func(...string) (*bytes.Buffer, error)) error) error {\n\t// TODO(rfindley): can/should this use findRootPattern?\n\tmodURI := snapshot.GoModForFile(uri)\n\tif modURI == \"\" {\n\t\treturn fmt.Errorf(\"no go.mod file found for %s\", uri.Path())\n\t}\n\tnewModBytes, newSumBytes, err := snapshot.RunGoModUpdateCommands(ctx, modURI, run)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsumURI := protocol.URIFromPath(strings.TrimSuffix(modURI.Path(), \".mod\") + \".sum\")\n\n\tmodChange, err := computeEditChange(ctx, snapshot, modURI, newModBytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsumChange, err := computeEditChange(ctx, snapshot, sumURI, newSumBytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar changes []protocol.DocumentChange\n\tif modChange.Valid() {\n\t\tchanges = append(changes, modChange)\n\t}\n\tif sumChange.Valid() {\n\t\tchanges = append(changes, sumChange)\n\t}\n\treturn applyChanges(ctx, s.client, changes)\n}\n\n// computeEditChange computes the edit change required to transform the\n// snapshot file specified by uri to the provided new content.\n// Beware: returns a DocumentChange that is !Valid() if none were necessary.\n//\n// If the file is not open, computeEditChange simply writes the new content to\n// disk.\n//\n// TODO(rfindley): fix this API asymmetry. It should be up to the caller to\n// write the file or apply the edits.\nfunc computeEditChange(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, newContent []byte) (protocol.DocumentChange, error) {\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn protocol.DocumentChange{}, err\n\t}\n\toldContent, err := fh.Content()\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn protocol.DocumentChange{}, err\n\t}\n\n\tif bytes.Equal(oldContent, newContent) {\n\t\treturn protocol.DocumentChange{}, nil // note: result is !Valid()\n\t}\n\n\t// Sending a workspace edit to a closed file causes VS Code to open the\n\t// file and leave it unsaved. We would rather apply the changes directly,\n\t// especially to go.sum, which should be mostly invisible to the user.\n\tif !snapshot.IsOpen(uri) {\n\t\terr := os.WriteFile(uri.Path(), newContent, 0666)\n\t\treturn protocol.DocumentChange{}, err\n\t}\n\n\tm := protocol.NewMapper(fh.URI(), oldContent)\n\tdiff := diff.Bytes(oldContent, newContent)\n\ttextedits, err := protocol.EditsFromDiffEdits(m, diff)\n\tif err != nil {\n\t\treturn protocol.DocumentChange{}, err\n\t}\n\treturn protocol.DocumentChangeEdit(fh, textedits), nil\n}\n\nfunc applyChanges(ctx context.Context, cli protocol.Client, changes []protocol.DocumentChange) error {\n\tif len(changes) == 0 {\n\t\treturn nil\n\t}\n\tresponse, err := cli.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{\n\t\tEdit: *protocol.NewWorkspaceEdit(changes...),\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !response.Applied {\n\t\treturn fmt.Errorf(\"edits not applied because of %s\", response.FailureReason)\n\t}\n\treturn nil\n}\n\nfunc runGoGetModule(invoke func(...string) (*bytes.Buffer, error), addRequire bool, args []string) error {\n\tif addRequire {\n\t\tif err := addModuleRequire(invoke, args); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t_, err := invoke(append([]string{\"get\", \"-d\"}, args...)...)\n\treturn err\n}\n\nfunc addModuleRequire(invoke func(...string) (*bytes.Buffer, error), args []string) error {\n\t// Using go get to create a new dependency results in an\n\t// `// indirect` comment we may not want. The only way to avoid it\n\t// is to add the require as direct first. Then we can use go get to\n\t// update go.sum and tidy up.\n\t_, err := invoke(append([]string{\"mod\", \"edit\", \"-require\"}, args...)...)\n\treturn err\n}\n\n// TODO(rfindley): inline.\nfunc (s *server) getUpgrades(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, modules []string) (map[string]string, error) {\n\targs := append([]string{\"-mod=readonly\", \"-m\", \"-u\", \"-json\"}, modules...)\n\tinv, cleanup, err := snapshot.GoCommandInvocation(cache.NetworkOK, uri.DirPath(), \"list\", args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cleanup()\n\tstdout, err := snapshot.View().GoCommandRunner().Run(ctx, *inv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tupgrades := map[string]string{}\n\tfor dec := json.NewDecoder(stdout); dec.More(); {\n\t\tmod := &gocommand.ModuleJSON{}\n\t\tif err := dec.Decode(mod); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif mod.Update == nil {\n\t\t\tcontinue\n\t\t}\n\t\tupgrades[mod.Path] = mod.Update.Version\n\t}\n\treturn upgrades, nil\n}\n\nfunc (c *commandHandler) GCDetails(ctx context.Context, uri protocol.DocumentURI) error {\n\treturn c.run(ctx, commandConfig{\n\t\tforURI: uri,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\treturn c.modifyState(ctx, FromToggleCompilerOptDetails, func() (*cache.Snapshot, func(), error) {\n\t\t\t// Don't blindly use \"dir := deps.fh.URI().Dir()\"; validate.\n\t\t\tmeta, err := deps.snapshot.NarrowestMetadataForFile(ctx, deps.fh.URI())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tif len(meta.CompiledGoFiles) == 0 {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"package %q does not compile file %q\", meta.ID, deps.fh.URI())\n\t\t\t}\n\t\t\tdir := meta.CompiledGoFiles[0].Dir()\n\n\t\t\twant := !deps.snapshot.WantCompilerOptDetails(dir) // toggle per-directory flag\n\t\t\treturn c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{\n\t\t\t\tCompilerOptDetails: map[protocol.DocumentURI]bool{dir: want},\n\t\t\t})\n\t\t})\n\t})\n}\n\nfunc (c *commandHandler) ListKnownPackages(ctx context.Context, args command.URIArg) (command.ListKnownPackagesResult, error) {\n\tvar result command.ListKnownPackagesResult\n\terr := c.run(ctx, commandConfig{\n\t\tprogress: \"Listing packages\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tpkgs, err := golang.KnownPackagePaths(ctx, deps.snapshot, deps.fh)\n\t\tfor _, pkg := range pkgs {\n\t\t\tresult.Packages = append(result.Packages, string(pkg))\n\t\t}\n\t\treturn err\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) ListImports(ctx context.Context, args command.URIArg) (command.ListImportsResult, error) {\n\tvar result command.ListImportsResult\n\terr := c.run(ctx, commandConfig{\n\t\tforURI: args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tfh, err := deps.snapshot.ReadFile(ctx, args.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpgf, err := deps.snapshot.ParseGo(ctx, fh, parsego.Header)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfset := tokeninternal.FileSetFor(pgf.Tok)\n\t\tfor _, group := range astutil.Imports(fset, pgf.File) {\n\t\t\tfor _, imp := range group {\n\t\t\t\tif imp.Path == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvar name string\n\t\t\t\tif imp.Name != nil {\n\t\t\t\t\tname = imp.Name.Name\n\t\t\t\t}\n\t\t\t\tresult.Imports = append(result.Imports, command.FileImport{\n\t\t\t\t\tPath: string(metadata.UnquoteImportPath(imp)),\n\t\t\t\t\tName: name,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tmeta, err := deps.snapshot.NarrowestMetadataForFile(ctx, args.URI)\n\t\tif err != nil {\n\t\t\treturn err // e.g. cancelled\n\t\t}\n\t\tfor pkgPath := range meta.DepsByPkgPath {\n\t\t\tresult.PackageImports = append(result.PackageImports,\n\t\t\t\tcommand.PackageImport{Path: string(pkgPath)})\n\t\t}\n\t\tsort.Slice(result.PackageImports, func(i, j int) bool {\n\t\t\treturn result.PackageImports[i].Path < result.PackageImports[j].Path\n\t\t})\n\t\treturn nil\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) AddImport(ctx context.Context, args command.AddImportArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Adding import\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tedits, err := golang.AddImport(ctx, deps.snapshot, deps.fh, args.ImportPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not add import: %v\", err)\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, []protocol.DocumentChange{protocol.DocumentChangeEdit(deps.fh, edits)})\n\t})\n}\n\nfunc (c *commandHandler) ExtractToNewFile(ctx context.Context, args protocol.Location) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Extract to a new file\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tchanges, err := golang.ExtractToNewFile(ctx, deps.snapshot, deps.fh, args.Range)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, changes)\n\t})\n}\n\nfunc (c *commandHandler) StartDebugging(ctx context.Context, args command.DebuggingArgs) (result command.DebuggingResult, _ error) {\n\taddr := args.Addr\n\tif addr == \"\" {\n\t\taddr = \"localhost:0\"\n\t}\n\tdi := debug.GetInstance(ctx)\n\tif di == nil {\n\t\treturn result, errors.New(\"internal error: server has no debugging instance\")\n\t}\n\tlistenedAddr, err := di.Serve(ctx, addr)\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"starting debug server: %w\", err)\n\t}\n\tresult.URLs = []string{\"http://\" + listenedAddr}\n\topenClientBrowser(ctx, c.s.client, \"Debug\", result.URLs[0], c.s.Options())\n\treturn result, nil\n}\n\nfunc (c *commandHandler) StartProfile(ctx context.Context, args command.StartProfileArgs) (result command.StartProfileResult, _ error) {\n\tfile, err := os.CreateTemp(\"\", \"gopls-profile-*\")\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"creating temp profile file: %v\", err)\n\t}\n\n\tc.s.ongoingProfileMu.Lock()\n\tdefer c.s.ongoingProfileMu.Unlock()\n\n\tif c.s.ongoingProfile != nil {\n\t\tfile.Close() // ignore error\n\t\treturn result, fmt.Errorf(\"profile already started (for %q)\", c.s.ongoingProfile.Name())\n\t}\n\n\tif err := pprof.StartCPUProfile(file); err != nil {\n\t\tfile.Close() // ignore error\n\t\treturn result, fmt.Errorf(\"starting profile: %v\", err)\n\t}\n\n\tc.s.ongoingProfile = file\n\treturn result, nil\n}\n\nfunc (c *commandHandler) StopProfile(ctx context.Context, args command.StopProfileArgs) (result command.StopProfileResult, _ error) {\n\tc.s.ongoingProfileMu.Lock()\n\tdefer c.s.ongoingProfileMu.Unlock()\n\n\tprof := c.s.ongoingProfile\n\tc.s.ongoingProfile = nil\n\n\tif prof == nil {\n\t\treturn result, fmt.Errorf(\"no ongoing profile\")\n\t}\n\n\tpprof.StopCPUProfile()\n\tif err := prof.Close(); err != nil {\n\t\treturn result, fmt.Errorf(\"closing profile file: %v\", err)\n\t}\n\tresult.File = prof.Name()\n\treturn result, nil\n}\n\nfunc (c *commandHandler) FetchVulncheckResult(ctx context.Context, arg command.URIArg) (map[protocol.DocumentURI]*vulncheck.Result, error) {\n\tret := map[protocol.DocumentURI]*vulncheck.Result{}\n\terr := c.run(ctx, commandConfig{forURI: arg.URI}, func(ctx context.Context, deps commandDeps) error {\n\t\tif deps.snapshot.Options().Vulncheck == settings.ModeVulncheckImports {\n\t\t\tfor _, modfile := range deps.snapshot.View().ModFiles() {\n\t\t\t\tres, err := deps.snapshot.ModVuln(ctx, modfile)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tret[modfile] = res\n\t\t\t}\n\t\t}\n\t\t// Overwrite if there is any govulncheck-based result.\n\t\tmaps.Copy(ret, deps.snapshot.Vulnerabilities())\n\t\treturn nil\n\t})\n\treturn ret, err\n}\n\nconst GoVulncheckCommandTitle = \"govulncheck\"\n\nfunc (c *commandHandler) Vulncheck(ctx context.Context, args command.VulncheckArgs) (command.VulncheckResult, error) {\n\tif args.URI == \"\" {\n\t\treturn command.VulncheckResult{}, errors.New(\"VulncheckArgs is missing URI field\")\n\t}\n\n\tvar commandResult command.VulncheckResult\n\terr := c.run(ctx, commandConfig{\n\t\tprogress:      GoVulncheckCommandTitle,\n\t\tprogressStyle: settings.WorkDoneProgressStyleLog,\n\t\trequireSave:   true, // govulncheck cannot honor overlays\n\t\tforURI:        args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tjsonrpc2.Async(ctx) // run this in parallel with other requests: vulncheck can be slow.\n\n\t\tworkDoneWriter := progress.NewWorkDoneWriter(ctx, deps.work)\n\t\tresult, err := c.s.runVulncheck(ctx, deps.snapshot, args.URI, args.Pattern, workDoneWriter)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcommandResult.Result = result\n\t\tcommandResult.Token = deps.work.Token()\n\n\t\taffecting := make(map[string]bool, len(result.Entries))\n\t\tfor _, finding := range result.Findings {\n\t\t\tif len(finding.Trace) > 1 { // at least 2 frames if callstack exists (vulnerability, entry)\n\t\t\t\taffecting[finding.OSV] = true\n\t\t\t}\n\t\t}\n\t\tif len(affecting) == 0 {\n\t\t\tshowMessage(ctx, c.s.client, protocol.Info, \"No vulnerabilities found\")\n\t\t\treturn nil\n\t\t}\n\t\taffectingOSVs := make([]string, 0, len(affecting))\n\t\tfor id := range affecting {\n\t\t\taffectingOSVs = append(affectingOSVs, id)\n\t\t}\n\t\tsort.Strings(affectingOSVs)\n\n\t\tshowMessage(ctx, c.s.client, protocol.Warning, fmt.Sprintf(\"Found %v\", strings.Join(affectingOSVs, \", \")))\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn command.VulncheckResult{}, err\n\t}\n\treturn commandResult, nil\n}\n\n// RunGovulncheck is like Vulncheck (in fact, a copy), but is tweaked slightly\n// to run asynchronously rather than return a result.\n//\n// This logic was copied, rather than factored out, as this implementation is\n// slated for deletion.\n//\n// TODO(golang/vscode-go#3572)\n// TODO(hxjiang): deprecate gopls.run_govulncheck.\nfunc (c *commandHandler) RunGovulncheck(ctx context.Context, args command.VulncheckArgs) (command.RunVulncheckResult, error) {\n\t// Deduplicate the RunGovulncheck command so only one is running at a time.\n\tif !c.s.runGovulncheckInProgress.CompareAndSwap(false, true) {\n\t\tc.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{\n\t\t\tType:    protocol.Info,\n\t\t\tMessage: \"A govulncheck scan is already in progress.\",\n\t\t})\n\t\treturn command.RunVulncheckResult{}, nil\n\t}\n\n\tdefer c.s.runGovulncheckInProgress.Store(false)\n\n\tif args.URI == \"\" {\n\t\treturn command.RunVulncheckResult{}, errors.New(\"VulncheckArgs is missing URI field\")\n\t}\n\n\t// Return the workdone token so that clients can identify when this\n\t// vulncheck invocation is complete.\n\t//\n\t// Since the run function executes asynchronously, we use a channel to\n\t// synchronize the start of the run and return the token.\n\ttokenChan := make(chan protocol.ProgressToken, 1)\n\terr := c.run(ctx, commandConfig{\n\t\tprogress:    GoVulncheckCommandTitle,\n\t\trequireSave: true, // govulncheck cannot honor overlays\n\t\tforURI:      args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\ttokenChan <- deps.work.Token()\n\n\t\tworkDoneWriter := progress.NewWorkDoneWriter(ctx, deps.work)\n\t\tresult, err := c.s.runVulncheck(ctx, deps.snapshot, args.URI, args.Pattern, workDoneWriter)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\taffecting := make(map[string]bool, len(result.Entries))\n\t\tfor _, finding := range result.Findings {\n\t\t\tif len(finding.Trace) > 1 { // at least 2 frames if callstack exists (vulnerability, entry)\n\t\t\t\taffecting[finding.OSV] = true\n\t\t\t}\n\t\t}\n\t\tif len(affecting) == 0 {\n\t\t\tshowMessage(ctx, c.s.client, protocol.Info, \"No vulnerabilities found\")\n\t\t\treturn nil\n\t\t}\n\t\taffectingOSVs := make([]string, 0, len(affecting))\n\t\tfor id := range affecting {\n\t\t\taffectingOSVs = append(affectingOSVs, id)\n\t\t}\n\t\tsort.Strings(affectingOSVs)\n\n\t\tshowMessage(ctx, c.s.client, protocol.Warning, fmt.Sprintf(\"Found %v\", strings.Join(affectingOSVs, \", \")))\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn command.RunVulncheckResult{}, err\n\t}\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn command.RunVulncheckResult{}, ctx.Err()\n\tcase token := <-tokenChan:\n\t\treturn command.RunVulncheckResult{Token: token}, nil\n\t}\n}\n\n// runVulncheck executes a vulnerability scan and updates the server's state.\nfunc (s *server) runVulncheck(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, pattern string, out io.Writer) (*vulncheck.Result, error) {\n\tdir := uri.DirPath()\n\tresult, err := scan.RunGovulncheck(ctx, pattern, snapshot, dir, out)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Invalidate the view to store findings in the vulnerability cache.\n\tnewSnapshot, release, err := s.session.InvalidateView(ctx, snapshot.View(), cache.StateChange{\n\t\tVulns: map[protocol.DocumentURI]*vulncheck.Result{uri: result},\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\t// Diagnosing with the background context ensures new snapshots are fully\n\t// diagnosed.\n\ts.diagnoseSnapshot(newSnapshot.BackgroundContext(), newSnapshot, nil, 0)\n\n\treturn result, nil\n}\n\n// MemStats implements the MemStats command. It returns an error as a\n// future-proof API, but the resulting error is currently always nil.\nfunc (c *commandHandler) MemStats(ctx context.Context) (command.MemStatsResult, error) {\n\t// GC a few times for stable results.\n\truntime.GC()\n\truntime.GC()\n\truntime.GC()\n\tvar m runtime.MemStats\n\truntime.ReadMemStats(&m)\n\treturn command.MemStatsResult{\n\t\tHeapAlloc:  m.HeapAlloc,\n\t\tHeapInUse:  m.HeapInuse,\n\t\tTotalAlloc: m.TotalAlloc,\n\t}, nil\n}\n\n// WorkspaceStats implements the WorkspaceStats command, reporting information\n// about the current state of the loaded workspace for the current session.\nfunc (c *commandHandler) WorkspaceStats(ctx context.Context) (command.WorkspaceStatsResult, error) {\n\tvar res command.WorkspaceStatsResult\n\tres.Files = c.s.session.Cache().FileStats()\n\n\tfor _, view := range c.s.session.Views() {\n\t\tvs, err := collectViewStats(ctx, view)\n\t\tif err != nil {\n\t\t\treturn res, err\n\t\t}\n\t\tres.Views = append(res.Views, vs)\n\t}\n\treturn res, nil\n}\n\nfunc collectViewStats(ctx context.Context, view *cache.View) (command.ViewStats, error) {\n\ts, release, err := view.Snapshot()\n\tif err != nil {\n\t\treturn command.ViewStats{}, err\n\t}\n\tdefer release()\n\n\tallMD, err := s.AllMetadata(ctx)\n\tif err != nil {\n\t\treturn command.ViewStats{}, err\n\t}\n\tallPackages := collectPackageStats(allMD)\n\n\twsMD, err := s.WorkspaceMetadata(ctx)\n\tif err != nil {\n\t\treturn command.ViewStats{}, err\n\t}\n\tworkspacePackages := collectPackageStats(wsMD)\n\n\tvar ids []golang.PackageID\n\tfor _, mp := range wsMD {\n\t\tids = append(ids, mp.ID)\n\t}\n\n\tdiags, err := s.PackageDiagnostics(ctx, ids...)\n\tif err != nil {\n\t\treturn command.ViewStats{}, err\n\t}\n\n\tndiags := 0\n\tfor _, d := range diags {\n\t\tndiags += len(d)\n\t}\n\n\treturn command.ViewStats{\n\t\tGoCommandVersion:  view.GoVersionString(),\n\t\tAllPackages:       allPackages,\n\t\tWorkspacePackages: workspacePackages,\n\t\tDiagnostics:       ndiags,\n\t}, nil\n}\n\nfunc collectPackageStats(mps []*metadata.Package) command.PackageStats {\n\tvar stats command.PackageStats\n\tstats.Packages = len(mps)\n\tmodules := make(map[string]bool)\n\n\tfor _, mp := range mps {\n\t\tn := len(mp.CompiledGoFiles)\n\t\tstats.CompiledGoFiles += n\n\t\tif n > stats.LargestPackage {\n\t\t\tstats.LargestPackage = n\n\t\t}\n\t\tif mp.Module != nil {\n\t\t\tmodules[mp.Module.Path] = true\n\t\t}\n\t}\n\tstats.Modules = len(modules)\n\n\treturn stats\n}\n\n// RunGoWorkCommand invokes `go work <args>` with the provided arguments.\n//\n// args.InitFirst controls whether to first run `go work init`. This allows a\n// single command to both create and recursively populate a go.work file -- as\n// of writing there is no `go work init -r`.\n//\n// Some thought went into implementing this command. Unlike the go.mod commands\n// above, this command simply invokes the go command and relies on the client\n// to notify gopls of file changes via didChangeWatchedFile notifications.\n// We could instead run these commands with GOWORK set to a temp file, but that\n// poses the following problems:\n//   - directory locations in the resulting temp go.work file will be computed\n//     relative to the directory containing that go.work. If the go.work is in a\n//     tempdir, the directories will need to be translated to/from that dir.\n//   - it would be simpler to use a temp go.work file in the workspace\n//     directory, or whichever directory contains the real go.work file, but\n//     that sets a bad precedent of writing to a user-owned directory. We\n//     shouldn't start doing that.\n//   - Sending workspace edits to create a go.work file would require using\n//     the CreateFile resource operation, which would need to be tested in every\n//     client as we haven't used it before. We don't have time for that right\n//     now.\n//\n// Therefore, we simply require that the current go.work file is saved (if it\n// exists), and delegate to the go command.\nfunc (c *commandHandler) RunGoWorkCommand(ctx context.Context, args command.RunGoWorkArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Running go work command\",\n\t\tforView:  args.ViewID,\n\t}, func(ctx context.Context, deps commandDeps) (runErr error) {\n\t\tsnapshot := deps.snapshot\n\t\tview := snapshot.View()\n\t\tviewDir := snapshot.Folder().Path()\n\n\t\tif view.Type() != cache.GoWorkView && view.GoWork() != \"\" {\n\t\t\t// If we are not using an existing go.work file, GOWORK must be explicitly off.\n\t\t\t// TODO(rfindley): what about GO111MODULE=off?\n\t\t\treturn fmt.Errorf(\"cannot modify go.work files when GOWORK=off\")\n\t\t}\n\n\t\tvar gowork string\n\t\t// If the user has explicitly set GOWORK=off, we should warn them\n\t\t// explicitly and avoid potentially misleading errors below.\n\t\tif view.GoWork() != \"\" {\n\t\t\tgowork = view.GoWork().Path()\n\t\t\tfh, err := snapshot.ReadFile(ctx, view.GoWork())\n\t\t\tif err != nil {\n\t\t\t\treturn err // e.g. canceled\n\t\t\t}\n\t\t\tif !fh.SameContentsOnDisk() {\n\t\t\t\treturn fmt.Errorf(\"must save workspace file %s before running go work commands\", view.GoWork())\n\t\t\t}\n\t\t} else {\n\t\t\tif !args.InitFirst {\n\t\t\t\t// If go.work does not exist, we should have detected that and asked\n\t\t\t\t// for InitFirst.\n\t\t\t\treturn bug.Errorf(\"internal error: cannot run go work command: required go.work file not found\")\n\t\t\t}\n\t\t\tgowork = filepath.Join(viewDir, \"go.work\")\n\t\t\tif err := c.invokeGoWork(ctx, viewDir, gowork, []string{\"init\"}); err != nil {\n\t\t\t\treturn fmt.Errorf(\"running `go work init`: %v\", err)\n\t\t\t}\n\t\t}\n\n\t\treturn c.invokeGoWork(ctx, viewDir, gowork, args.Args)\n\t})\n}\n\nfunc (c *commandHandler) invokeGoWork(ctx context.Context, viewDir, gowork string, args []string) error {\n\tinv := gocommand.Invocation{\n\t\tVerb:       \"work\",\n\t\tArgs:       args,\n\t\tWorkingDir: viewDir,\n\t\tEnv:        append(os.Environ(), fmt.Sprintf(\"GOWORK=%s\", gowork)),\n\t}\n\tif _, err := c.s.session.GoCommandRunner().Run(ctx, inv); err != nil {\n\t\treturn fmt.Errorf(\"running go work command: %v\", err)\n\t}\n\treturn nil\n}\n\n// showMessage causes the client to show a progress or error message.\n//\n// It reports whether it succeeded. If it fails, it writes an error to\n// the server log, so most callers can safely ignore the result.\nfunc showMessage(ctx context.Context, cli protocol.Client, typ protocol.MessageType, message string) bool {\n\terr := cli.ShowMessage(ctx, &protocol.ShowMessageParams{\n\t\tType:    typ,\n\t\tMessage: message,\n\t})\n\tif err != nil {\n\t\tevent.Error(ctx, \"client.showMessage: %v\", err)\n\t\treturn false\n\t}\n\treturn true\n}\n\n// openClientBrowser causes the LSP client to open the specified URL\n// in an external browser.\n//\n// If the client does not support window/showDocument, a window/showMessage\n// request is instead used, with the format \"$title: open your browser to $url\".\nfunc openClientBrowser(ctx context.Context, cli protocol.Client, title string, url protocol.URI, opts *settings.Options) {\n\tif opts.ShowDocumentSupported {\n\t\tshowDocumentImpl(ctx, cli, url, nil, opts)\n\t} else {\n\t\tparams := &protocol.ShowMessageParams{\n\t\t\tType:    protocol.Info,\n\t\t\tMessage: fmt.Sprintf(\"%s: open your browser to %s\", title, url),\n\t\t}\n\t\tif err := cli.ShowMessage(ctx, params); err != nil {\n\t\t\tevent.Error(ctx, \"failed to show browser url\", err)\n\t\t}\n\t}\n}\n\n// openClientEditor causes the LSP client to open the specified document\n// and select the indicated range.\n//\n// Note that VS Code 1.87.2 doesn't currently raise the window; this is\n// https://github.com/microsoft/vscode/issues/207634\nfunc openClientEditor(ctx context.Context, cli protocol.Client, loc protocol.Location, opts *settings.Options) {\n\tif !opts.ShowDocumentSupported {\n\t\treturn // no op\n\t}\n\tshowDocumentImpl(ctx, cli, protocol.URI(loc.URI), &loc.Range, opts)\n}\n\nfunc showDocumentImpl(ctx context.Context, cli protocol.Client, url protocol.URI, rangeOpt *protocol.Range, opts *settings.Options) {\n\tif !opts.ShowDocumentSupported {\n\t\treturn // no op\n\t}\n\t// In principle we shouldn't send a showDocument request to a\n\t// client that doesn't support it, as reported by\n\t// ShowDocumentClientCapabilities. But even clients that do\n\t// support it may defer the real work of opening the document\n\t// asynchronously, to avoid deadlocks due to rentrancy.\n\t//\n\t// For example: client sends request to server; server sends\n\t// showDocument to client; client opens editor; editor causes\n\t// new RPC to be sent to server, which is still busy with\n\t// previous request. (This happens in eglot.)\n\t//\n\t// So we can't rely on the success/failure information.\n\t// That's the reason this function doesn't return an error.\n\n\t// \"External\" means run the system-wide handler (e.g. open(1)\n\t// on macOS or xdg-open(1) on Linux) for this URL, ignoring\n\t// TakeFocus and Selection. Note that this may still end up\n\t// opening the same editor (e.g. VSCode) for a file: URL.\n\tres, err := cli.ShowDocument(ctx, &protocol.ShowDocumentParams{\n\t\tURI:       url,\n\t\tExternal:  rangeOpt == nil,\n\t\tTakeFocus: true,\n\t\tSelection: rangeOpt, // optional\n\t})\n\tif err != nil {\n\t\tevent.Error(ctx, \"client.showDocument: %v\", err)\n\t} else if res != nil && !res.Success {\n\t\tevent.Log(ctx, fmt.Sprintf(\"client declined to open document %v\", url))\n\t}\n}\n\nfunc (c *commandHandler) ChangeSignature(ctx context.Context, args command.ChangeSignatureArgs) (*protocol.WorkspaceEdit, error) {\n\tcountChangeSignature.Inc()\n\tvar result *protocol.WorkspaceEdit\n\terr := c.run(ctx, commandConfig{\n\t\tforURI: args.Location.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tpkg, pgf, err := golang.NarrowestPackageForFile(ctx, deps.snapshot, args.Location.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// For now, gopls only supports parameter permutation or removal.\n\t\tvar perm []int\n\t\tfor _, newParam := range args.NewParams {\n\t\t\tif newParam.NewField != \"\" {\n\t\t\t\treturn fmt.Errorf(\"adding new parameters is currently unsupported\")\n\t\t\t}\n\t\t\tperm = append(perm, newParam.OldIndex)\n\t\t}\n\n\t\tdocedits, err := golang.ChangeSignature(ctx, deps.snapshot, pkg, pgf, args.Location.Range, perm)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\twsedit := protocol.NewWorkspaceEdit(docedits...)\n\t\tif args.ResolveEdits {\n\t\t\tresult = wsedit\n\t\t\treturn nil\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, docedits)\n\t})\n\treturn result, err\n}\n\nfunc (c *commandHandler) DiagnoseFiles(ctx context.Context, args command.DiagnoseFilesArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Diagnose files\",\n\t}, func(ctx context.Context, _ commandDeps) error {\n\n\t\t// TODO(rfindley): even better would be textDocument/diagnostics (golang/go#60122).\n\t\t// Though note that implementing pull diagnostics may cause some servers to\n\t\t// request diagnostics in an ad-hoc manner, and break our intentional pacing.\n\n\t\tctx, done := event.Start(ctx, \"commandHandler.DiagnoseFiles\")\n\t\tdefer done()\n\n\t\tsnapshots := make(map[*cache.Snapshot]bool)\n\t\tfor _, uri := range args.Files {\n\t\t\tfh, snapshot, release, err := c.s.session.FileOf(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif snapshots[snapshot] || snapshot.FileKind(fh) != file.Go {\n\t\t\t\trelease()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdefer release()\n\t\t\tsnapshots[snapshot] = true\n\t\t}\n\n\t\tvar wg sync.WaitGroup\n\t\tfor snapshot := range snapshots {\n\t\t\twg.Go(func() {\n\n\t\t\t\t// Use the operation context for diagnosis, rather than\n\t\t\t\t// snapshot.BackgroundContext, because this operation does not create\n\t\t\t\t// new snapshots (so they should also be diagnosed by other means).\n\t\t\t\tc.s.diagnoseSnapshot(ctx, snapshot, nil, 0)\n\t\t\t})\n\t\t}\n\t\twg.Wait()\n\n\t\treturn nil\n\t})\n}\n\nfunc (c *commandHandler) Views(ctx context.Context) ([]command.View, error) {\n\tvar summaries []command.View\n\tfor _, view := range c.s.session.Views() {\n\t\tsummaries = append(summaries, command.View{\n\t\t\tID:         view.ID(),\n\t\t\tType:       view.Type().String(),\n\t\t\tRoot:       view.Root(),\n\t\t\tFolder:     view.Folder().Dir,\n\t\t\tEnvOverlay: view.EnvOverlay(),\n\t\t})\n\t}\n\treturn summaries, nil\n}\n\nfunc (c *commandHandler) FreeSymbols(ctx context.Context, viewID string, loc protocol.Location) error {\n\tweb, err := c.s.getWeb()\n\tif err != nil {\n\t\treturn err\n\t}\n\turl := web.freesymbolsURL(viewID, loc)\n\topenClientBrowser(ctx, c.s.client, \"Free symbols\", url, c.s.Options())\n\treturn nil\n}\n\nfunc (c *commandHandler) SplitPackage(ctx context.Context, viewID, packageID string) error {\n\tweb, err := c.s.getWeb()\n\tif err != nil {\n\t\treturn err\n\t}\n\turl := web.splitpkgURL(viewID, packageID)\n\topenClientBrowser(ctx, c.s.client, \"SplitPackage\", url, c.s.Options())\n\treturn nil\n}\n\nfunc (c *commandHandler) Assembly(ctx context.Context, viewID, packageID, symbol string) error {\n\tweb, err := c.s.getWeb()\n\tif err != nil {\n\t\treturn err\n\t}\n\turl := web.assemblyURL(viewID, packageID, symbol)\n\topenClientBrowser(ctx, c.s.client, \"Assembly\", url, c.s.Options())\n\treturn nil\n}\n\nfunc (c *commandHandler) ClientOpenURL(ctx context.Context, url string) error {\n\t// Fall back to \"Gopls: open your browser...\" if we must send a showMessage\n\t// request, since we don't know the context of this command.\n\topenClientBrowser(ctx, c.s.client, \"Gopls\", url, c.s.Options())\n\treturn nil\n}\n\nfunc (c *commandHandler) ScanImports(ctx context.Context) error {\n\tfor _, v := range c.s.session.Views() {\n\t\tv.ScanImports()\n\t}\n\treturn nil\n}\n\nfunc (c *commandHandler) PackageSymbols(ctx context.Context, args command.PackageSymbolsArgs) (command.PackageSymbolsResult, error) {\n\tvar result command.PackageSymbolsResult\n\terr := c.run(ctx, commandConfig{\n\t\tforURI: args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tif deps.snapshot.FileKind(deps.fh) != file.Go {\n\t\t\t// golang/vscode-go#3681: fail silently, to avoid spurious error popups.\n\t\t\treturn nil\n\t\t}\n\t\tres, err := golang.PackageSymbols(ctx, deps.snapshot, args.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresult = res\n\t\treturn nil\n\t})\n\n\t// sort symbols for determinism\n\tsort.SliceStable(result.Symbols, func(i, j int) bool {\n\t\tiv, jv := result.Symbols[i], result.Symbols[j]\n\t\tif iv.Name == jv.Name {\n\t\t\treturn iv.Range.Start.Line < jv.Range.Start.Line\n\t\t}\n\t\treturn iv.Name < jv.Name\n\t})\n\n\treturn result, err\n}\n\n// optionsStringToMap transforms comma-separated options of the form\n// \"foo=bar,baz=quux\" to a go map. Returns nil if any options are malformed.\nfunc optionsStringToMap(options string) (map[string][]string, error) {\n\toptionsMap := make(map[string][]string)\n\tfor item := range strings.SplitSeq(options, \",\") {\n\t\tkey, option, found := strings.Cut(item, \"=\")\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"invalid option %q\", item)\n\t\t}\n\t\toptionsMap[key] = append(optionsMap[key], option)\n\t}\n\treturn optionsMap, nil\n}\n\nfunc (c *commandHandler) ModifyTags(ctx context.Context, args command.ModifyTagsArgs) error {\n\treturn c.run(ctx, commandConfig{\n\t\tprogress: \"Modifying tags\",\n\t\tforURI:   args.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tm := &modifytags.Modification{\n\t\t\tClear:        args.Clear,\n\t\t\tClearOptions: args.ClearOptions,\n\t\t\tValueFormat:  args.ValueFormat,\n\t\t\tOverwrite:    args.Overwrite,\n\t\t}\n\n\t\ttransform, err := parseTransform(args.Transform)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tm.Transform = transform\n\n\t\t// Each command involves either adding or removing tags, depending on\n\t\t// whether Add or Clear is set.\n\t\tif args.Add != \"\" {\n\t\t\tcountAddStructTags.Inc()\n\t\t\tm.Add = strings.Split(args.Add, \",\")\n\t\t} else if args.Clear {\n\t\t\tcountRemoveStructTags.Inc()\n\t\t}\n\t\tif args.AddOptions != \"\" {\n\t\t\tif options, err := optionsStringToMap(args.AddOptions); err != nil {\n\t\t\t\treturn err\n\t\t\t} else {\n\t\t\t\tm.AddOptions = options\n\t\t\t}\n\t\t}\n\t\tif args.Remove != \"\" {\n\t\t\tm.Remove = strings.Split(args.Remove, \",\")\n\t\t}\n\t\tif args.RemoveOptions != \"\" {\n\t\t\tif options, err := optionsStringToMap(args.RemoveOptions); err != nil {\n\t\t\t\treturn err\n\t\t\t} else {\n\t\t\t\tm.RemoveOptions = options\n\t\t\t}\n\t\t}\n\t\tfh, err := deps.snapshot.ReadFile(ctx, args.URI)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tchanges, err := golang.ModifyTags(ctx, deps.snapshot, fh, args, m)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, changes)\n\t})\n}\n\nfunc parseTransform(input string) (modifytags.Transform, error) {\n\tswitch input {\n\tcase \"camelcase\":\n\t\treturn modifytags.CamelCase, nil\n\tcase \"lispcase\":\n\t\treturn modifytags.LispCase, nil\n\tcase \"pascalcase\":\n\t\treturn modifytags.PascalCase, nil\n\tcase \"titlecase\":\n\t\treturn modifytags.TitleCase, nil\n\tcase \"keep\":\n\t\treturn modifytags.Keep, nil\n\tcase \"\":\n\t\tfallthrough\n\tcase \"snakecase\":\n\t\treturn modifytags.SnakeCase, nil\n\tdefault:\n\t\treturn modifytags.SnakeCase, fmt.Errorf(\"invalid Transform value\")\n\t}\n}\n\nfunc (c *commandHandler) MoveType(ctx context.Context, args command.MoveTypeArgs) error {\n\terr := c.run(ctx, commandConfig{\n\t\tforURI: args.Location.URI,\n\t}, func(ctx context.Context, deps commandDeps) error {\n\t\tchanges, err := golang.MoveType(ctx, deps.fh, deps.snapshot, args.Location, \"newpkg/new.go\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn applyChanges(ctx, c.s.client, changes)\n\t})\n\treturn err\n}\n"
  },
  {
    "path": "gopls/internal/server/completion.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/gopls/internal/work\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Completion(ctx context.Context, params *protocol.CompletionParams) (_ *protocol.CompletionList, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"completion\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.Completion\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif params.Range.Start != params.Range.End {\n\t\treturn nil, fmt.Errorf(\"textDocument/completion request only applicable for position\")\n\t}\n\tpos := params.Range.Start\n\n\tvar candidates []completion.CompletionItem\n\tvar surrounding *completion.Selection\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\tcandidates, surrounding, err = completion.Completion(ctx, snapshot, fh, pos, params.Context)\n\tcase file.Mod:\n\t\tcandidates, surrounding = nil, nil\n\tcase file.Work:\n\t\tcl, err := work.Completion(ctx, snapshot, fh, pos)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\treturn cl, nil\n\tcase file.Tmpl:\n\t\tvar cl *protocol.CompletionList\n\t\tcl, err = template.Completion(ctx, snapshot, fh, pos, params.Context)\n\t\tif err != nil {\n\t\t\tbreak // use common error handling, candidates==nil\n\t\t}\n\t\treturn cl, nil\n\t}\n\tif err != nil {\n\t\tevent.Error(ctx, \"no completions found\", err, label.Position.Of(pos))\n\t}\n\tif candidates == nil || surrounding == nil {\n\t\tcomplEmpty.Inc()\n\t\treturn &protocol.CompletionList{\n\t\t\tIsIncomplete: true,\n\t\t\tItems:        []protocol.CompletionItem{},\n\t\t}, nil\n\t}\n\n\t// When using deep completions/fuzzy matching, report results as incomplete so\n\t// client fetches updated completions after every key stroke.\n\toptions := snapshot.Options()\n\tincompleteResults := options.DeepCompletion || options.Matcher == settings.Fuzzy\n\n\titems, err := toProtocolCompletionItems(candidates, surrounding, options)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif snapshot.FileKind(fh) == file.Go {\n\t\ts.saveLastCompletion(fh.URI(), fh.Version(), items, params.Position)\n\t}\n\n\tif len(items) > 10 {\n\t\t// TODO(pjw): long completions are ok for field lists\n\t\tcomplLong.Inc()\n\t} else {\n\t\tcomplShort.Inc()\n\t}\n\treturn &protocol.CompletionList{\n\t\tIsIncomplete: incompleteResults,\n\t\tItems:        items,\n\t}, nil\n}\n\nfunc (s *server) saveLastCompletion(uri protocol.DocumentURI, version int32, items []protocol.CompletionItem, pos protocol.Position) {\n\ts.efficacyMu.Lock()\n\tdefer s.efficacyMu.Unlock()\n\ts.efficacyVersion = version\n\ts.efficacyURI = uri\n\ts.efficacyPos = pos\n\ts.efficacyItems = items\n}\n\n// toProtocolCompletionItems converts the candidates to the protocol completion items,\n// the candidates must be sorted based on score as it will be respected by client side.\nfunc toProtocolCompletionItems(candidates []completion.CompletionItem, surrounding *completion.Selection, options *settings.Options) ([]protocol.CompletionItem, error) {\n\treplaceRng, err := surrounding.Range()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tinsertRng0, err := surrounding.PrefixRange()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsuffix := surrounding.Suffix()\n\n\tvar (\n\t\titems                  = make([]protocol.CompletionItem, 0, len(candidates))\n\t\tnumDeepCompletionsSeen int\n\t)\n\tfor i, candidate := range candidates {\n\t\t// Limit the number of deep completions to not overwhelm the user in cases\n\t\t// with dozens of deep completion matches.\n\t\tif candidate.Depth > 0 {\n\t\t\tif !options.DeepCompletion {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif numDeepCompletionsSeen >= completion.MaxDeepCompletions {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnumDeepCompletionsSeen++\n\t\t}\n\t\tinsertText := candidate.InsertText\n\t\tif options.InsertTextFormat == protocol.SnippetTextFormat {\n\t\t\tinsertText = candidate.Snippet()\n\t\t}\n\n\t\t// This can happen if the client has snippets disabled but the\n\t\t// candidate only supports snippet insertion.\n\t\tif insertText == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar doc *protocol.Or_CompletionItem_documentation\n\t\tif candidate.Documentation != \"\" {\n\t\t\tvar value any\n\t\t\tif options.PreferredContentFormat == protocol.Markdown {\n\t\t\t\tvalue = protocol.MarkupContent{\n\t\t\t\t\tKind:  protocol.Markdown,\n\t\t\t\t\tValue: golang.DocCommentToMarkdown(candidate.Documentation, options),\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvalue = candidate.Documentation\n\t\t\t}\n\t\t\tdoc = &protocol.Or_CompletionItem_documentation{Value: value}\n\t\t}\n\t\tvar edits *protocol.Or_CompletionItem_textEdit\n\t\tif options.InsertReplaceSupported {\n\t\t\tinsertRng := insertRng0\n\t\t\tif suffix == \"\" || strings.Contains(insertText, suffix) {\n\t\t\t\tinsertRng = replaceRng\n\t\t\t}\n\t\t\t// Insert and Replace ranges share the same start position and\n\t\t\t// the same text edit but the end position may differ.\n\t\t\t// See the comment for the CompletionItem's TextEdit field.\n\t\t\t// https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#CompletionItem\n\t\t\tedits = &protocol.Or_CompletionItem_textEdit{\n\t\t\t\tValue: protocol.InsertReplaceEdit{\n\t\t\t\t\tNewText: insertText,\n\t\t\t\t\tInsert:  insertRng, // replace up to the cursor position.\n\t\t\t\t\tReplace: replaceRng,\n\t\t\t\t},\n\t\t\t}\n\t\t} else {\n\t\t\tedits = &protocol.Or_CompletionItem_textEdit{\n\t\t\t\tValue: protocol.TextEdit{\n\t\t\t\t\tNewText: insertText,\n\t\t\t\t\tRange:   replaceRng,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\titem := protocol.CompletionItem{\n\t\t\tLabel:               candidate.Label,\n\t\t\tDetail:              candidate.Detail,\n\t\t\tKind:                candidate.Kind,\n\t\t\tTextEdit:            edits,\n\t\t\tInsertTextFormat:    &options.InsertTextFormat,\n\t\t\tAdditionalTextEdits: candidate.AdditionalTextEdits,\n\t\t\t// This is a hack so that the client sorts completion results in the order\n\t\t\t// according to their score. This can be removed upon the resolution of\n\t\t\t// https://github.com/Microsoft/language-server-protocol/issues/348.\n\t\t\tSortText: fmt.Sprintf(\"%05d\", i),\n\n\t\t\t// Trim operators (VSCode doesn't like weird characters in\n\t\t\t// filterText).\n\t\t\tFilterText: strings.TrimLeft(candidate.InsertText, \"&*\"),\n\n\t\t\tPreselect:     i == 0,\n\t\t\tDocumentation: doc,\n\t\t\tTags:          protocol.NonNilSlice(candidate.Tags),\n\t\t\tDeprecated:    candidate.Deprecated,\n\t\t}\n\t\titems = append(items, item)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/counters.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport \"golang.org/x/telemetry/counter\"\n\n// Proposed counters for evaluating gopls code completion.\nvar (\n\tcomplEmpty = counter.New(\"gopls/completion/len:0\")    // count empty suggestions\n\tcomplShort = counter.New(\"gopls/completion/len:<=10\") // not empty, not long\n\tcomplLong  = counter.New(\"gopls/completion/len:>10\")  // returning more than 10 items\n\n\tchangeFull  = counter.New(\"gopls/completion/used:unknown\") // full file change in didChange\n\tcomplUnused = counter.New(\"gopls/completion/used:no\")      // did not use a completion\n\tcomplUsed   = counter.New(\"gopls/completion/used:yes\")     // used a completion\n\n\t// exported so tests can verify that counters are incremented\n\tCompletionCounters = []*counter.Counter{\n\t\tcomplEmpty,\n\t\tcomplShort,\n\t\tcomplLong,\n\t\tchangeFull,\n\t\tcomplUnused,\n\t\tcomplUsed,\n\t}\n)\n\n// Proposed counters for evaluating gopls change signature and rename. These\n// counters increment when the user attempts to perform one of these operations,\n// regardless of whether it succeeds.\nvar (\n\tcountChangeSignature = counter.New(\"gopls/changesig\")\n\n\tcountRename = counter.New(\"gopls/rename\")\n)\n\n// Proposed counters for evaluating gopls refactoring codeactions add struct\n// tags and remove struct tags.\nvar (\n\tcountAddStructTags = counter.New(\"gopls/structtags:add\")\n\n\tcountRemoveStructTags = counter.New(\"gopls/structtags:remove\")\n)\n\n// Proposed counters to evaluate vulncheck_prompt usage patterns.\nvar (\n\t// Vulncheck prompt user choices.\n\tcountVulncheckPromptYes    = counter.New(\"gopls/vulncheck-prompt/choice:yes\")\n\tcountVulncheckPromptNo     = counter.New(\"gopls/vulncheck-prompt/choice:no\")\n\tcountVulncheckPromptAlways = counter.New(\"gopls/vulncheck-prompt/choice:always\")\n\tcountVulncheckPromptNever  = counter.New(\"gopls/vulncheck-prompt/choice:never\")\n\n\t// Vulncheck prompt upgrade choice.\n\tcountVulncheckUpgradeAll    = counter.New(\"gopls/vulncheck-prompt/upgrade:yes\")\n\tcountVulncheckUpgradeIgnore = counter.New(\"gopls/vulncheck-prompt/upgrade:no\")\n)\n"
  },
  {
    "path": "gopls/internal/server/debug.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\n// assert panics with the given msg if cond is not true.\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/definition.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/goasm\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Definition(ctx context.Context, params *protocol.DefinitionParams) (_ []protocol.Location, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"definition\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.Definition\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\t// TODO(rfindley): definition requests should be multiplexed across all views.\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch kind := snapshot.FileKind(fh); kind {\n\tcase file.Tmpl:\n\t\treturn template.Definition(snapshot, fh, params.Range)\n\tcase file.Go:\n\t\treturn golang.Definition(ctx, snapshot, fh, params.Range)\n\tcase file.Asm:\n\t\treturn goasm.Definition(ctx, snapshot, fh, params.Range)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"can't find definitions for file type %s\", kind)\n\t}\n}\n\nfunc (s *server) TypeDefinition(ctx context.Context, params *protocol.TypeDefinitionParams) ([]protocol.Location, error) {\n\tctx, done := event.Start(ctx, \"server.TypeDefinition\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\t// TODO(rfindley): type definition requests should be multiplexed across all views.\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer release()\n\tswitch kind := snapshot.FileKind(fh); kind {\n\tcase file.Go:\n\t\treturn golang.TypeDefinition(ctx, snapshot, fh, params.Range)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"can't find type definitions for file type %s\", kind)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/diagnostics.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/work\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\n// Diagnostic implements the textDocument/diagnostic LSP request, reporting\n// diagnostics for the given file.\n//\n// This is a work in progress.\n// TODO(rfindley):\n//   - support RelatedDocuments? If so, how? Maybe include other package diagnostics?\n//   - support resultID (=snapshot ID)\n//   - support multiple views\n//   - add orphaned file diagnostics\n//   - support go.mod, go.work files\nfunc (s *server) Diagnostic(ctx context.Context, params *protocol.DocumentDiagnosticParams) (*protocol.DocumentDiagnosticReport, error) {\n\tctx, done := event.Start(ctx, \"server.Diagnostic\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tjsonrpc2.Async(ctx) // allow asynchronous collection of diagnostics\n\n\turi := fh.URI()\n\tkind := snapshot.FileKind(fh)\n\tvar diagnostics []*cache.Diagnostic\n\tswitch kind {\n\tcase file.Go:\n\t\tdiagnostics, err = golang.DiagnoseFile(ctx, snapshot, uri)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"pull diagnostics not supported for this file kind\")\n\t}\n\treturn &protocol.DocumentDiagnosticReport{\n\t\tValue: protocol.RelatedFullDocumentDiagnosticReport{\n\t\t\tFullDocumentDiagnosticReport: protocol.FullDocumentDiagnosticReport{\n\t\t\t\tItems: cache.ToProtocolDiagnostics(diagnostics...),\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\n// fileDiagnostics holds the current state of published diagnostics for a file.\ntype fileDiagnostics struct {\n\tpublishedHash file.Hash // hash of the last set of diagnostics published for this URI\n\tmustPublish   bool      // if set, publish diagnostics even if they haven't changed\n\n\t// Orphaned file diagnostics are not necessarily associated with any *View\n\t// (since they are orphaned). Instead, keep track of the modification ID at\n\t// which they were orphaned (see server.lastModificationID).\n\torphanedAt              uint64 // modification ID at which this file was orphaned.\n\torphanedFileDiagnostics []*cache.Diagnostic\n\n\t// Files may have their diagnostics computed by multiple views, and so\n\t// diagnostics are organized by View. See the documentation for update for more\n\t// details about how the set of file diagnostics evolves over time.\n\tbyView map[*cache.View]viewDiagnostics\n}\n\n// viewDiagnostics holds a set of file diagnostics computed from a given View.\ntype viewDiagnostics struct {\n\tsnapshot    uint64 // snapshot sequence ID\n\tversion     int32  // file version\n\tdiagnostics []*cache.Diagnostic\n}\n\n// common types; for brevity\ntype (\n\tviewSet = map[*cache.View]unit\n\tdiagMap = map[protocol.DocumentURI][]*cache.Diagnostic\n)\n\nfunc sortDiagnostics(d []*cache.Diagnostic) {\n\tsort.Slice(d, func(i int, j int) bool {\n\t\ta, b := d[i], d[j]\n\t\tif r := protocol.CompareRange(a.Range, b.Range); r != 0 {\n\t\t\treturn r < 0\n\t\t}\n\t\tif a.Source != b.Source {\n\t\t\treturn a.Source < b.Source\n\t\t}\n\t\treturn a.Message < b.Message\n\t})\n}\n\nfunc (s *server) diagnoseChangedViews(ctx context.Context, modID uint64, lastChange map[*cache.View][]protocol.DocumentURI, cause ModificationSource) {\n\t// Collect views needing diagnosis.\n\ts.modificationMu.Lock()\n\tneedsDiagnosis := moremaps.KeySlice(s.viewsToDiagnose)\n\ts.modificationMu.Unlock()\n\n\t// Diagnose views concurrently.\n\tvar wg sync.WaitGroup\n\tfor _, v := range needsDiagnosis {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\ts.modificationMu.Lock()\n\t\t\t// The View is shut down. Unlike below, no need to check\n\t\t\t// s.needsDiagnosis[v], since the view can never be diagnosed.\n\t\t\tdelete(s.viewsToDiagnose, v)\n\t\t\ts.modificationMu.Unlock()\n\t\t\tcontinue\n\t\t}\n\n\t\t// Collect uris for fast diagnosis. We only care about the most recent\n\t\t// change here, because this is just an optimization for the case where the\n\t\t// user is actively editing a single file.\n\t\turis := lastChange[v]\n\t\tif snapshot.Options().DiagnosticsTrigger == settings.DiagnosticsOnSave && cause == FromDidChange {\n\t\t\t// The user requested to update the diagnostics only on save.\n\t\t\t// Do not diagnose yet.\n\t\t\trelease()\n\t\t\tcontinue\n\t\t}\n\n\t\twg.Add(1)\n\t\tgo func(snapshot *cache.Snapshot, uris []protocol.DocumentURI) {\n\t\t\tdefer release()\n\t\t\tdefer wg.Done()\n\t\t\ts.diagnoseSnapshot(ctx, snapshot, uris, snapshot.Options().DiagnosticsDelay)\n\t\t\ts.modificationMu.Lock()\n\n\t\t\t// Only remove v from s.viewsToDiagnose if the context is not cancelled.\n\t\t\t// This ensures that the snapshot was not cloned before its state was\n\t\t\t// fully evaluated, and therefore avoids missing a change that was\n\t\t\t// irrelevant to an incomplete snapshot.\n\t\t\t//\n\t\t\t// See the documentation for s.viewsToDiagnose for details.\n\t\t\tif ctx.Err() == nil && s.viewsToDiagnose[v] <= modID {\n\t\t\t\tdelete(s.viewsToDiagnose, v)\n\t\t\t}\n\t\t\ts.modificationMu.Unlock()\n\t\t}(snapshot, uris)\n\t}\n\n\twg.Wait()\n\n\t// Diagnose orphaned files for the session.\n\torphanedFileDiagnostics, err := s.session.OrphanedFileDiagnostics(ctx)\n\tif err == nil {\n\t\terr = s.updateOrphanedFileDiagnostics(ctx, modID, orphanedFileDiagnostics)\n\t}\n\tif err != nil {\n\t\tif ctx.Err() == nil {\n\t\t\tevent.Error(ctx, \"warning: while diagnosing orphaned files\", err)\n\t\t}\n\t}\n}\n\n// diagnoseSnapshot computes and publishes diagnostics for the given snapshot.\n//\n// If delay is non-zero, computing diagnostics does not start until after this\n// delay has expired, to allow work to be cancelled by subsequent changes.\n//\n// If changedURIs is non-empty, it is a set of recently changed files that\n// should be diagnosed immediately, and onDisk reports whether these file\n// changes came from a change to on-disk files.\n//\n// If the provided context is cancelled, diagnostics may be partially\n// published. Therefore, the provided context should only be cancelled if there\n// will be a subsequent operation to make diagnostics consistent. In general,\n// if an operation creates a new snapshot, it is responsible for ensuring that\n// snapshot (or a subsequent snapshot in the same View) is eventually\n// diagnosed.\nfunc (s *server) diagnoseSnapshot(ctx context.Context, snapshot *cache.Snapshot, changedURIs []protocol.DocumentURI, delay time.Duration) {\n\tctx, done := event.Start(ctx, \"server.diagnoseSnapshot\", snapshot.Labels()...)\n\tdefer done()\n\n\tif delay > 0 {\n\t\t// 2-phase diagnostics.\n\t\t//\n\t\t// The first phase just parses and type-checks (but\n\t\t// does not analyze) packages directly affected by\n\t\t// file modifications.\n\t\t//\n\t\t// The second phase runs after the delay, and does everything.\n\n\t\tif len(changedURIs) > 0 {\n\t\t\tdiagnostics, err := diagnoseChangedFiles(ctx, snapshot, changedURIs)\n\t\t\tif err != nil {\n\t\t\t\tif ctx.Err() == nil {\n\t\t\t\t\tevent.Error(ctx, \"warning: while diagnosing changed files\", err, snapshot.Labels()...)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ts.updateDiagnostics(ctx, snapshot, diagnostics, false)\n\t\t}\n\n\t\tselect {\n\t\tcase <-time.After(delay):\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\t}\n\t}\n\n\tdiagnostics, err := s.diagnose(ctx, snapshot)\n\tif err != nil {\n\t\tif ctx.Err() == nil {\n\t\t\tevent.Error(ctx, \"warning: while diagnosing snapshot\", err, snapshot.Labels()...)\n\t\t}\n\t\treturn\n\t}\n\ts.updateDiagnostics(ctx, snapshot, diagnostics, true)\n}\n\nfunc diagnoseChangedFiles(ctx context.Context, snapshot *cache.Snapshot, uris []protocol.DocumentURI) (diagMap, error) {\n\tctx, done := event.Start(ctx, \"server.diagnoseChangedFiles\", snapshot.Labels()...)\n\tdefer done()\n\n\ttoDiagnose := make(map[metadata.PackageID]*metadata.Package)\n\tfor _, uri := range uris {\n\t\t// If the file is not open, don't diagnose its package.\n\t\t//\n\t\t// We don't care about fast diagnostics for files that are no longer open,\n\t\t// because the user isn't looking at them. Also, explicitly requesting a\n\t\t// package can lead to \"command-line-arguments\" packages if the file isn't\n\t\t// covered by the current View. By avoiding requesting packages for e.g.\n\t\t// unrelated file movement, we can minimize these unnecessary packages.\n\t\tif !snapshot.IsOpen(uri) {\n\t\t\tcontinue\n\t\t}\n\t\t// If the file is not known to the snapshot (e.g., if it was deleted),\n\t\t// don't diagnose it.\n\t\tif fh, err := snapshot.ReadFile(ctx, uri); err != nil || fh == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Don't request type-checking for builtin.go: it's not a real package.\n\t\tif snapshot.IsBuiltin(uri) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Don't diagnose files that are ignored by `go list` (e.g. testdata).\n\t\tif snapshot.IgnoredFile(uri) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Find all packages that include this file and diagnose them in parallel.\n\t\tmeta, err := snapshot.NarrowestMetadataForFile(ctx, uri)\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn nil, ctx.Err()\n\t\t\t}\n\t\t\t// TODO(findleyr): we should probably do something with the error here,\n\t\t\t// but as of now this can fail repeatedly if load fails, so can be too\n\t\t\t// noisy to log (and we'll handle things later in the slow pass).\n\t\t\tcontinue\n\t\t}\n\t\t// golang/go#65801: only diagnose changes to workspace packages. Otherwise,\n\t\t// diagnostics will be unstable, as the slow-path diagnostics will erase\n\t\t// them.\n\t\tif snapshot.IsWorkspacePackage(meta.ID) {\n\t\t\ttoDiagnose[meta.ID] = meta\n\t\t}\n\t}\n\tdiags, err := snapshot.PackageDiagnostics(ctx, moremaps.KeySlice(toDiagnose)...)\n\tif err != nil {\n\t\tif ctx.Err() == nil {\n\t\t\tevent.Error(ctx, \"warning: diagnostics failed\", err, snapshot.Labels()...)\n\t\t}\n\t\treturn nil, err\n\t}\n\t// golang/go#59587: guarantee that we compute type-checking diagnostics\n\t// for every compiled package file, otherwise diagnostics won't be quickly\n\t// cleared following a fix.\n\tfor _, meta := range toDiagnose {\n\t\tfor _, uri := range meta.CompiledGoFiles {\n\t\t\tif _, ok := diags[uri]; !ok {\n\t\t\t\tdiags[uri] = nil\n\t\t\t}\n\t\t}\n\t}\n\treturn diags, nil\n}\n\nfunc (s *server) diagnose(ctx context.Context, snapshot *cache.Snapshot) (diagMap, error) {\n\tctx, done := event.Start(ctx, \"server.diagnose\", snapshot.Labels()...)\n\tdefer done()\n\n\t// Wait for a free diagnostics slot.\n\t// TODO(adonovan): opt: shouldn't it be the analysis implementation's\n\t// job to de-dup and limit resource consumption? In any case this\n\t// function spends most its time waiting for awaitLoaded, at\n\t// least initially.\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tcase s.diagnosticsSema <- struct{}{}:\n\t}\n\tdefer func() {\n\t\t<-s.diagnosticsSema\n\t}()\n\n\tvar (\n\t\tdiagnosticsMu sync.Mutex\n\t\tdiagnostics   = make(diagMap)\n\t)\n\t// common code for dispatching diagnostics\n\tstore := func(operation string, diagsByFile diagMap, err error) {\n\t\tif err != nil {\n\t\t\tif ctx.Err() == nil {\n\t\t\t\tevent.Error(ctx, \"warning: while \"+operation, err, snapshot.Labels()...)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tdiagnosticsMu.Lock()\n\t\tdefer diagnosticsMu.Unlock()\n\t\tfor uri, diags := range diagsByFile {\n\t\t\tdiagnostics[uri] = append(diagnostics[uri], diags...)\n\t\t}\n\t}\n\n\t// Diagnostics below are organized by increasing specificity:\n\t//  go.work > mod > mod upgrade > mod vuln > package, etc.\n\n\t// Diagnose go.work file.\n\tworkReports, workErr := work.Diagnostics(ctx, snapshot)\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tstore(\"diagnosing go.work file\", workReports, workErr)\n\n\t// Diagnose go.mod file.\n\tmodReports, modErr := mod.ParseDiagnostics(ctx, snapshot)\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tstore(\"diagnosing go.mod file\", modReports, modErr)\n\n\t// Diagnose go.mod upgrades.\n\tupgradeReports, upgradeErr := mod.UpgradeDiagnostics(ctx, snapshot)\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tstore(\"diagnosing go.mod upgrades\", upgradeReports, upgradeErr)\n\n\t// Diagnose vulnerabilities.\n\tvulnReports, vulnErr := mod.VulnerabilityDiagnostics(ctx, snapshot)\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tstore(\"diagnosing vulnerabilities\", vulnReports, vulnErr)\n\n\tworkspacePkgs, err := snapshot.WorkspaceMetadata(ctx)\n\tif s.shouldIgnoreError(snapshot, err) {\n\t\treturn diagnostics, ctx.Err()\n\t}\n\n\tinitialErr := snapshot.InitializationError()\n\tif ctx.Err() != nil {\n\t\t// Don't update initialization status if the context is cancelled.\n\t\treturn nil, ctx.Err()\n\t}\n\n\tif initialErr != nil {\n\t\tstore(\"critical error\", initialErr.Diagnostics, nil)\n\t}\n\n\t// Show the error as a progress error report so that it appears in the\n\t// status bar. If a client doesn't support progress reports, the error\n\t// will still be shown as a ShowMessage. If there is no error, any running\n\t// error progress reports will be closed.\n\tstatusErr := initialErr\n\tif len(snapshot.Overlays()) == 0 {\n\t\t// Don't report a hanging status message if there are no open files at this\n\t\t// snapshot.\n\t\tstatusErr = nil\n\t}\n\ts.updateCriticalErrorStatus(ctx, snapshot, statusErr)\n\n\t// Diagnose template (.tmpl) files.\n\ttmplReports := template.Diagnostics(snapshot)\n\t// NOTE(rfindley): typeCheckSource is not accurate here.\n\t// (but this will be gone soon anyway).\n\tstore(\"diagnosing templates\", tmplReports, nil)\n\n\t// If there are no workspace packages, there is nothing to diagnose and\n\t// there are no orphaned files.\n\tif len(workspacePkgs) == 0 {\n\t\treturn diagnostics, nil\n\t}\n\n\tvar wg sync.WaitGroup // for potentially slow operations below\n\n\t// Maybe run go mod tidy (if it has been invalidated).\n\t//\n\t// Since go mod tidy can be slow, we run it concurrently to diagnostics.\n\twg.Go(func() {\n\t\tmodTidyReports, err := mod.TidyDiagnostics(ctx, snapshot)\n\t\tstore(\"running go mod tidy\", modTidyReports, err)\n\t})\n\n\t// Run type checking and go/analysis diagnosis of packages in parallel.\n\t//\n\t// For analysis, we use the *widest* package for each open file,\n\t// for two reasons:\n\t//\n\t// - Correctness: some analyzers (e.g. unused{param,func}) depend\n\t//   on it. If applied to a non-test package for which a\n\t//   corresponding test package exists, they make assumptions\n\t//   that are falsified in the test package, for example that\n\t//   all references to unexported symbols are visible to the\n\t//   analysis.\n\t//\n\t// - Efficiency: it may yield a smaller covering set of\n\t//   PackageIDs for a given set of files. For example, {x.go,\n\t//   x_test.go} is covered by the single package x_test using\n\t//   \"widest\". (Using \"narrowest\", it would be covered only by\n\t//   the pair of packages {x, x_test}, Originally we used all\n\t//   covering packages, so {x.go} alone would be analyzed\n\t//   twice.)\n\tvar (\n\t\ttoDiagnose = make(map[metadata.PackageID]*metadata.Package)\n\t\ttoAnalyze  = make(map[metadata.PackageID]*metadata.Package)\n\n\t\t// secondary index, used to eliminate narrower packages.\n\t\ttoAnalyzeWidest = make(map[golang.PackagePath]*metadata.Package)\n\t)\n\tfor _, mp := range workspacePkgs {\n\t\tvar hasNonIgnored, hasOpenFile bool\n\t\tfor _, uri := range mp.CompiledGoFiles {\n\t\t\tif !hasNonIgnored && !snapshot.IgnoredFile(uri) {\n\t\t\t\thasNonIgnored = true\n\t\t\t}\n\t\t\tif !hasOpenFile && snapshot.IsOpen(uri) {\n\t\t\t\thasOpenFile = true\n\t\t\t}\n\t\t}\n\t\tif hasNonIgnored {\n\t\t\ttoDiagnose[mp.ID] = mp\n\t\t\tif hasOpenFile {\n\t\t\t\tif prev, ok := toAnalyzeWidest[mp.PkgPath]; ok {\n\t\t\t\t\tif len(prev.CompiledGoFiles) >= len(mp.CompiledGoFiles) {\n\t\t\t\t\t\t// Previous entry is not narrower; keep it.\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// Evict previous (narrower) entry.\n\t\t\t\t\tdelete(toAnalyze, prev.ID)\n\t\t\t\t}\n\t\t\t\ttoAnalyze[mp.ID] = mp\n\t\t\t\ttoAnalyzeWidest[mp.PkgPath] = mp\n\t\t\t}\n\t\t}\n\t}\n\n\twg.Go(func() {\n\t\tcompilerOptDetailsDiags, err := s.compilerOptDetailsDiagnostics(ctx, snapshot, toDiagnose)\n\t\tstore(\"collecting compiler optimization details\", compilerOptDetailsDiags, err)\n\t})\n\n\t// Package diagnostics and analysis diagnostics must both be computed and\n\t// merged before they can be reported.\n\tvar pkgDiags, analysisDiags diagMap\n\t// Collect package diagnostics.\n\twg.Go(func() {\n\t\tvar err error\n\t\tpkgDiags, err = snapshot.PackageDiagnostics(ctx, moremaps.KeySlice(toDiagnose)...)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"warning: diagnostics failed\", err, snapshot.Labels()...)\n\t\t}\n\t})\n\n\t// Get diagnostics from analysis framework.\n\t// This includes type-error analyzers, which suggest fixes to compiler errors.\n\twg.Go(func() {\n\t\tvar err error\n\t\t// TODO(rfindley): here and above, we should avoid using the first result\n\t\t// if err is non-nil (though as of today it's OK).\n\t\tanalysisDiags, err = golang.Analyze(ctx, snapshot, toAnalyze, s.progress)\n\n\t\t// Filter out Hint diagnostics for closed files.\n\t\t// VS Code already omits Hint diagnostics in the Problems tab, but other\n\t\t// clients do not. This filter makes the visibility of Hints more similar\n\t\t// across clients.\n\t\tfor uri, diags := range analysisDiags {\n\t\t\tif !snapshot.IsOpen(uri) {\n\t\t\t\tnewDiags := slices.DeleteFunc(diags, func(diag *cache.Diagnostic) bool {\n\t\t\t\t\treturn diag.Severity == protocol.SeverityHint\n\t\t\t\t})\n\t\t\t\tif len(newDiags) == 0 {\n\t\t\t\t\tdelete(analysisDiags, uri)\n\t\t\t\t} else {\n\t\t\t\t\tanalysisDiags[uri] = newDiags\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"warning: analyzing package\", err, append(snapshot.Labels(), label.Package.Of(keys.Join(moremaps.KeySlice(toDiagnose))))...)\n\t\t\treturn\n\t\t}\n\t})\n\n\twg.Wait()\n\n\t// Merge analysis diagnostics with package diagnostics, and store the\n\t// resulting analysis diagnostics.\n\tcombinedDiags := make(diagMap)\n\tfor uri, adiags := range analysisDiags {\n\t\ttdiags := pkgDiags[uri]\n\t\tcombinedDiags[uri] = golang.CombineDiagnostics(tdiags, adiags)\n\t}\n\tfor uri, tdiags := range pkgDiags {\n\t\tif _, ok := combinedDiags[uri]; !ok {\n\t\t\tcombinedDiags[uri] = tdiags\n\t\t}\n\t}\n\tstore(\"type checking and analysing\", combinedDiags, nil) // error reported above\n\n\treturn diagnostics, nil\n}\n\nfunc (s *server) compilerOptDetailsDiagnostics(ctx context.Context, snapshot *cache.Snapshot, toDiagnose map[metadata.PackageID]*metadata.Package) (diagMap, error) {\n\t// Process requested diagnostics about compiler optimization details.\n\t//\n\t// TODO(rfindley): This should memoize its results if the package has not changed.\n\t// Consider that these points, in combination with the note below about\n\t// races, suggest that compiler optimization details should be tracked on the Snapshot.\n\tdiagnostics := make(diagMap)\n\tseenDirs := make(map[protocol.DocumentURI]bool)\n\tfor _, mp := range toDiagnose {\n\t\tif len(mp.CompiledGoFiles) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tdir := mp.CompiledGoFiles[0].Dir()\n\t\tif snapshot.WantCompilerOptDetails(dir) {\n\t\t\tif !seenDirs[dir] {\n\t\t\t\tseenDirs[dir] = true\n\n\t\t\t\tperFileDiags, err := golang.CompilerOptDetails(ctx, snapshot, dir)\n\t\t\t\tif err != nil {\n\t\t\t\t\tevent.Error(ctx, \"warning: compiler optimization details\", err, append(snapshot.Labels(), label.URI.Of(dir))...)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor uri, diags := range perFileDiags {\n\t\t\t\t\tdiagnostics[uri] = append(diagnostics[uri], diags...)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn diagnostics, nil\n}\n\n// mustPublishDiagnostics marks the uri as needing publication, independent of\n// whether the published contents have changed.\n//\n// This can be used for ensuring gopls publishes diagnostics after certain file\n// events.\nfunc (s *server) mustPublishDiagnostics(uri protocol.DocumentURI) {\n\ts.diagnosticsMu.Lock()\n\tdefer s.diagnosticsMu.Unlock()\n\n\tif s.diagnostics[uri] == nil {\n\t\ts.diagnostics[uri] = new(fileDiagnostics)\n\t}\n\ts.diagnostics[uri].mustPublish = true\n}\n\nconst WorkspaceLoadFailure = \"Error loading workspace\"\n\n// updateCriticalErrorStatus updates the critical error progress notification\n// based on err.\n//\n// If err is nil, or if there are no open files, it clears any existing error\n// progress report.\nfunc (s *server) updateCriticalErrorStatus(ctx context.Context, snapshot *cache.Snapshot, err *cache.InitializationError) {\n\ts.criticalErrorStatusMu.Lock()\n\tdefer s.criticalErrorStatusMu.Unlock()\n\n\t// Remove all newlines so that the error message can be formatted in a\n\t// status bar.\n\tvar errMsg string\n\tif err != nil {\n\t\terrMsg = strings.ReplaceAll(err.MainError.Error(), \"\\n\", \" \")\n\t}\n\n\tif s.criticalErrorStatus == nil {\n\t\tif errMsg != \"\" {\n\t\t\tevent.Error(ctx, \"errors loading workspace\", err.MainError, snapshot.Labels()...)\n\t\t\ts.criticalErrorStatus = s.progress.Start(ctx, WorkspaceLoadFailure, errMsg, nil, nil)\n\t\t}\n\t\treturn\n\t}\n\n\t// If an error is already shown to the user, update it or mark it as\n\t// resolved.\n\tif errMsg == \"\" {\n\t\ts.criticalErrorStatus.End(ctx, \"Done.\")\n\t\ts.criticalErrorStatus = nil\n\t} else {\n\t\ts.criticalErrorStatus.Report(ctx, errMsg, 0)\n\t}\n}\n\n// updateDiagnostics records the result of diagnosing a snapshot, and publishes\n// any diagnostics that need to be updated on the client.\nfunc (s *server) updateDiagnostics(ctx context.Context, snapshot *cache.Snapshot, diagnostics diagMap, final bool) {\n\tctx, done := event.Start(ctx, \"server.publishDiagnostics\")\n\tdefer done()\n\n\ts.diagnosticsMu.Lock()\n\tdefer s.diagnosticsMu.Unlock()\n\n\t// Before updating any diagnostics, check that the context (i.e. snapshot\n\t// background context) is not cancelled.\n\t//\n\t// If not, then we know that we haven't started diagnosing the next snapshot,\n\t// because the previous snapshot is cancelled before the next snapshot is\n\t// returned from Invalidate.\n\t//\n\t// Therefore, even if we publish stale diagnostics here, they should\n\t// eventually be overwritten with accurate diagnostics.\n\t//\n\t// TODO(rfindley): refactor the API to force that snapshots are diagnosed\n\t// after they are created.\n\tif ctx.Err() != nil {\n\t\treturn\n\t}\n\n\t// golang/go#65312: since the set of diagnostics depends on the set of views,\n\t// we get the views *after* locking diagnosticsMu. This ensures that\n\t// updateDiagnostics does not incorrectly delete diagnostics that have been\n\t// set for an existing view that was created between the call to\n\t// s.session.Views() and updateDiagnostics.\n\tviewMap := make(viewSet)\n\tfor _, v := range s.session.Views() {\n\t\tviewMap[v] = unit{}\n\t}\n\n\t// updateAndPublish updates diagnostics for a file, checking both the latest\n\t// diagnostics for the current snapshot, as well as reconciling the set of\n\t// views.\n\tupdateAndPublish := func(uri protocol.DocumentURI, f *fileDiagnostics, diags []*cache.Diagnostic) error {\n\t\tcurrent, ok := f.byView[snapshot.View()]\n\t\t// Update the stored diagnostics if:\n\t\t//  1. we've never seen diagnostics for this view,\n\t\t//  2. diagnostics are for an older snapshot, or\n\t\t//  3. we're overwriting with final diagnostics\n\t\t//\n\t\t// In other words, we shouldn't overwrite existing diagnostics for a\n\t\t// snapshot with non-final diagnostics. This avoids the race described at\n\t\t// https://github.com/golang/go/issues/64765#issuecomment-1890144575.\n\t\tif !ok || current.snapshot < snapshot.SequenceID() || (current.snapshot == snapshot.SequenceID() && final) {\n\t\t\tfh, err := snapshot.ReadFile(ctx, uri)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcurrent = viewDiagnostics{\n\t\t\t\tsnapshot:    snapshot.SequenceID(),\n\t\t\t\tversion:     fh.Version(),\n\t\t\t\tdiagnostics: diags,\n\t\t\t}\n\t\t\tif f.byView == nil {\n\t\t\t\tf.byView = make(map[*cache.View]viewDiagnostics)\n\t\t\t}\n\t\t\tf.byView[snapshot.View()] = current\n\t\t}\n\n\t\treturn s.publishFileDiagnosticsLocked(ctx, viewMap, uri, current.version, f)\n\t}\n\n\tseen := make(map[protocol.DocumentURI]bool)\n\tfor uri, diags := range diagnostics {\n\t\tf, ok := s.diagnostics[uri]\n\t\tif !ok {\n\t\t\tf = new(fileDiagnostics)\n\t\t\ts.diagnostics[uri] = f\n\t\t}\n\t\tseen[uri] = true\n\t\tif err := updateAndPublish(uri, f, diags); err != nil {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn\n\t\t\t} else {\n\t\t\t\tevent.Error(ctx, \"updateDiagnostics: failed to deliver diagnostics\", err, label.URI.Of(uri))\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(rfindley): perhaps we should clean up files that have no diagnostics.\n\t// One could imagine a large operation generating diagnostics for a great\n\t// number of files, after which gopls has to do more bookkeeping into the\n\t// future.\n\tif final {\n\t\tfor uri, f := range s.diagnostics {\n\t\t\tif !seen[uri] {\n\t\t\t\tif err := updateAndPublish(uri, f, nil); err != nil {\n\t\t\t\t\tif ctx.Err() != nil {\n\t\t\t\t\t\treturn\n\t\t\t\t\t} else {\n\t\t\t\t\t\tevent.Error(ctx, \"updateDiagnostics: failed to deliver diagnostics\", err, label.URI.Of(uri))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// updateOrphanedFileDiagnostics records and publishes orphaned file\n// diagnostics as a given modification time.\nfunc (s *server) updateOrphanedFileDiagnostics(ctx context.Context, modID uint64, diagnostics diagMap) error {\n\tviews := s.session.Views()\n\tviewSet := make(viewSet)\n\tfor _, v := range views {\n\t\tviewSet[v] = unit{}\n\t}\n\n\ts.diagnosticsMu.Lock()\n\tdefer s.diagnosticsMu.Unlock()\n\n\tfor uri, diags := range diagnostics {\n\t\tf, ok := s.diagnostics[uri]\n\t\tif !ok {\n\t\t\tf = new(fileDiagnostics)\n\t\t\ts.diagnostics[uri] = f\n\t\t}\n\t\tif f.orphanedAt > modID {\n\t\t\tcontinue\n\t\t}\n\t\tf.orphanedAt = modID\n\t\tf.orphanedFileDiagnostics = diags\n\t\t// TODO(rfindley): the version of this file is potentially inaccurate;\n\t\t// nevertheless, it should be eventually consistent, because all\n\t\t// modifications are diagnosed.\n\t\tfh, err := s.session.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := s.publishFileDiagnosticsLocked(ctx, viewSet, uri, fh.Version(), f); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Clear any stale orphaned file diagnostics.\n\tfor uri, f := range s.diagnostics {\n\t\tif f.orphanedAt < modID {\n\t\t\tf.orphanedFileDiagnostics = nil\n\t\t}\n\t\tfh, err := s.session.ReadFile(ctx, uri)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := s.publishFileDiagnosticsLocked(ctx, viewSet, uri, fh.Version(), f); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// publishFileDiagnosticsLocked publishes a fileDiagnostics value, while holding s.diagnosticsMu.\n//\n// If the publication succeeds, it updates f.publishedHash and f.mustPublish.\nfunc (s *server) publishFileDiagnosticsLocked(ctx context.Context, views viewSet, uri protocol.DocumentURI, version int32, f *fileDiagnostics) error {\n\t// We add a disambiguating suffix (e.g. \" [darwin,arm64]\") to\n\t// each diagnostic that doesn't occur in the default view;\n\t// see golang/go#65496.\n\ttype diagSuffix struct {\n\t\tdiag   *cache.Diagnostic\n\t\tsuffix string // \"\" for default build (or orphans)\n\t}\n\n\t// diagSuffixes records the set of view suffixes for a given diagnostic.\n\tdiagSuffixes := make(map[file.Hash][]diagSuffix)\n\tadd := func(diag *cache.Diagnostic, suffix string) {\n\t\th := diag.Hash()\n\t\tdiagSuffixes[h] = append(diagSuffixes[h], diagSuffix{diag, suffix})\n\t}\n\n\t// Construct the inverse mapping, from diagnostic (hash) to its suffixes (views).\n\tfor _, diag := range f.orphanedFileDiagnostics {\n\t\tadd(diag, \"\")\n\t}\n\n\tvar allViews []*cache.View\n\tfor view, viewDiags := range f.byView {\n\t\tif _, ok := views[view]; !ok {\n\t\t\tdelete(f.byView, view) // view no longer exists\n\t\t\tcontinue\n\t\t}\n\t\tif viewDiags.version != version {\n\t\t\tcontinue // a payload of diagnostics applies to a specific file version\n\t\t}\n\t\tallViews = append(allViews, view)\n\t}\n\n\t// Only report diagnostics from relevant views for a file. This avoids\n\t// spurious import errors when a view has only a partial set of dependencies\n\t// for a package (golang/go#66425).\n\t//\n\t// It's ok to use the session to derive the eligible views, because we\n\t// publish diagnostics following any state change, so the set of relevant\n\t// views is eventually consistent.\n\trelevantViews, err := cache.RelevantViews(ctx, s.session, uri, allViews)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(relevantViews) == 0 {\n\t\t// If we have no preferred diagnostics for a given file (i.e., the file is\n\t\t// not naturally nested within a view), then all diagnostics should be\n\t\t// considered valid.\n\t\t//\n\t\t// This could arise if the user jumps to definition outside the workspace.\n\t\t// There is no view that owns the file, so its diagnostics are valid from\n\t\t// any view.\n\t\trelevantViews = allViews\n\t}\n\n\tfor _, view := range relevantViews {\n\t\tviewDiags := f.byView[view]\n\t\t// Compute the view's suffix (e.g. \" [darwin,arm64]\").\n\t\tvar suffix string\n\t\t{\n\t\t\tvar words []string\n\t\t\tif view.GOOS() != runtime.GOOS {\n\t\t\t\twords = append(words, view.GOOS())\n\t\t\t}\n\t\t\tif view.GOARCH() != runtime.GOARCH {\n\t\t\t\twords = append(words, view.GOARCH())\n\t\t\t}\n\t\t\tif len(words) > 0 {\n\t\t\t\tsuffix = fmt.Sprintf(\" [%s]\", strings.Join(words, \",\"))\n\t\t\t}\n\t\t}\n\n\t\tfor _, diag := range viewDiags.diagnostics {\n\t\t\tadd(diag, suffix)\n\t\t}\n\t}\n\n\t// De-dup diagnostics across views by hash, and sort.\n\tvar (\n\t\thash   file.Hash\n\t\tunique []*cache.Diagnostic\n\t)\n\tfor h, items := range diagSuffixes {\n\t\t// Sort the items by ascending suffix, so that the\n\t\t// default view (if present) is first.\n\t\t// (The others are ordered arbitrarily.)\n\t\tsort.Slice(items, func(i, j int) bool {\n\t\t\treturn items[i].suffix < items[j].suffix\n\t\t})\n\n\t\t// If the diagnostic was not present in\n\t\t// the default view, add the view suffix.\n\t\tfirst := items[0]\n\t\tif first.suffix != \"\" {\n\t\t\tdiag2 := *first.diag // shallow copy\n\t\t\tdiag2.Message += first.suffix\n\t\t\tfirst.diag = &diag2\n\t\t\th = diag2.Hash() // update the hash\n\t\t}\n\n\t\thash.XORWith(h)\n\t\tunique = append(unique, first.diag)\n\t}\n\tsortDiagnostics(unique)\n\n\t// Publish, if necessary.\n\tif hash != f.publishedHash || f.mustPublish {\n\t\tif err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{\n\t\t\tDiagnostics: cache.ToProtocolDiagnostics(unique...),\n\t\t\tURI:         uri,\n\t\t\tVersion:     version, // 0 (\"on disk\") => omitted from JSON encoding\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.publishedHash = hash\n\t\tf.mustPublish = false\n\t}\n\treturn nil\n}\n\nfunc (s *server) shouldIgnoreError(snapshot *cache.Snapshot, err error) bool {\n\tif err == nil { // if there is no error at all\n\t\treturn false\n\t}\n\tif errors.Is(err, context.Canceled) {\n\t\treturn true\n\t}\n\t// If the folder has no Go code in it, we shouldn't spam the user with a warning.\n\t// TODO(rfindley): surely it is not correct to walk the folder here just to\n\t// suppress diagnostics, every time we compute diagnostics.\n\tvar hasGo bool\n\t_ = filepath.Walk(snapshot.Folder().Path(), func(_ string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !strings.HasSuffix(info.Name(), \".go\") {\n\t\t\treturn nil\n\t\t}\n\t\thasGo = true\n\t\treturn errors.New(\"done\")\n\t})\n\treturn !hasGo\n}\n"
  },
  {
    "path": "gopls/internal/server/folding_range.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) FoldingRange(ctx context.Context, params *protocol.FoldingRangeParams) ([]protocol.FoldingRange, error) {\n\tctx, done := event.Start(ctx, \"server.FoldingRange\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil // empty result\n\t}\n\treturn golang.FoldingRange(ctx, snapshot, fh, snapshot.Options().LineFoldingOnly)\n}\n"
  },
  {
    "path": "gopls/internal/server/format.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/work\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) {\n\tctx, done := event.Start(ctx, \"server.Formatting\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Mod:\n\t\treturn mod.Format(ctx, snapshot, fh)\n\tcase file.Go:\n\t\treturn golang.Format(ctx, snapshot, fh)\n\tcase file.Work:\n\t\treturn work.Format(ctx, snapshot, fh)\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/general.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\n// This file defines server methods related to initialization,\n// options, shutdown, and exit.\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\tdebuglog \"golang.org/x/tools/gopls/internal/debug/log\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/goversion\"\n\t\"golang.org/x/tools/gopls/internal/util/moremaps\"\n\t\"golang.org/x/tools/gopls/internal/util/moreslices\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\nfunc (s *server) Initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {\n\tctx, done := event.Start(ctx, \"server.Initialize\")\n\tdefer done()\n\n\tvar clientName string\n\tif params != nil && params.ClientInfo != nil {\n\t\tclientName = params.ClientInfo.Name\n\t}\n\trecordClientInfo(clientName)\n\n\ts.stateMu.Lock()\n\tif s.state >= serverInitializing {\n\t\tdefer s.stateMu.Unlock()\n\t\treturn nil, fmt.Errorf(\"%w: initialize called while server in %v state\", jsonrpc2.ErrInvalidRequest, s.state)\n\t}\n\ts.state = serverInitializing\n\ts.stateMu.Unlock()\n\n\ts.progress.SetSupportsWorkDoneProgress(params.Capabilities.Window.WorkDoneProgress)\n\n\toptions := s.Options().Clone()\n\t// TODO(rfindley): eliminate this defer.\n\tdefer func() { s.SetOptions(options) }()\n\n\t// Process initialization options.\n\t{\n\t\tres, errs := options.Set(params.InitializationOptions)\n\t\ts.handleOptionResult(ctx, res, errs)\n\t}\n\toptions.ForClientCapabilities(params.ClientInfo, params.Capabilities)\n\n\tif options.MaxFileCacheBytes > 0 {\n\t\tfilecache.SetBudget(options.MaxFileCacheBytes)\n\t}\n\n\tif options.ShowBugReports {\n\t\t// Report the next bug that occurs on the server.\n\t\tbug.Handle(func(b bug.Bug) {\n\t\t\tmsg := &protocol.ShowMessageParams{\n\t\t\t\tType:    protocol.Error,\n\t\t\t\tMessage: fmt.Sprintf(\"A bug occurred on the server: %s\\nLocation:%s\", b.Description, b.Key),\n\t\t\t}\n\t\t\tgo s.eventuallyShowMessage(context.Background(), msg)\n\t\t})\n\t}\n\n\tfolders := params.WorkspaceFolders\n\tif len(folders) == 0 {\n\t\tif params.RootURI != \"\" {\n\t\t\tfolders = []protocol.WorkspaceFolder{{\n\t\t\t\tURI:  string(params.RootURI),\n\t\t\t\tName: path.Base(params.RootURI.Path()),\n\t\t\t}}\n\t\t}\n\t}\n\ts.pendingFolders = append(s.pendingFolders, folders...)\n\n\tvar codeActionProvider any = true\n\tif ca := params.Capabilities.TextDocument.CodeAction; len(ca.CodeActionLiteralSupport.CodeActionKind.ValueSet) > 0 {\n\t\t// If the client has specified CodeActionLiteralSupport,\n\t\t// send the code actions we support.\n\t\t//\n\t\t// Using CodeActionOptions is only valid if codeActionLiteralSupport is set.\n\t\tcodeActionProvider = &protocol.CodeActionOptions{\n\t\t\tCodeActionKinds: s.getSupportedCodeActions(),\n\t\t\tResolveProvider: true,\n\t\t}\n\t}\n\n\tvar diagnosticProvider *protocol.Or_ServerCapabilities_diagnosticProvider\n\tif options.PullDiagnostics {\n\t\tdiagnosticProvider = &protocol.Or_ServerCapabilities_diagnosticProvider{\n\t\t\tValue: protocol.DiagnosticOptions{\n\t\t\t\tInterFileDependencies: true,\n\t\t\t\tWorkspaceDiagnostics:  false, // we don't support workspace/diagnostic\n\t\t\t},\n\t\t}\n\t}\n\n\tvar renameOpts any = true\n\tif r := params.Capabilities.TextDocument.Rename; r != nil && r.PrepareSupport {\n\t\trenameOpts = protocol.RenameOptions{\n\t\t\tPrepareProvider: r.PrepareSupport,\n\t\t}\n\t}\n\n\tvar semanticTokenProvider any\n\tif options.SemanticTokens {\n\t\tsemanticTokenProvider = protocol.SemanticTokensOptions{\n\t\t\tRange: &protocol.Or_SemanticTokensOptions_range{Value: true},\n\t\t\tFull:  &protocol.Or_SemanticTokensOptions_full{Value: true},\n\t\t\tLegend: protocol.SemanticTokensLegend{\n\t\t\t\tTokenTypes:     moreslices.ConvertStrings[string](semtok.Types),\n\t\t\t\tTokenModifiers: moreslices.ConvertStrings[string](semtok.Modifiers),\n\t\t\t},\n\t\t}\n\t}\n\n\tversionInfo := debug.VersionInfo()\n\n\tgoplsVersion, err := json.Marshal(versionInfo)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &protocol.InitializeResult{\n\t\tCapabilities: protocol.ServerCapabilities{\n\t\t\tCallHierarchyProvider: &protocol.Or_ServerCapabilities_callHierarchyProvider{Value: true},\n\t\t\tCodeActionProvider:    codeActionProvider,\n\t\t\tCodeLensProvider:      &protocol.CodeLensOptions{}, // must be non-nil to enable the code lens capability\n\t\t\tCompletionProvider: &protocol.CompletionOptions{\n\t\t\t\tTriggerCharacters: []string{\".\"},\n\t\t\t},\n\t\t\tDefinitionProvider:         &protocol.Or_ServerCapabilities_definitionProvider{Value: true},\n\t\t\tTypeDefinitionProvider:     &protocol.Or_ServerCapabilities_typeDefinitionProvider{Value: true},\n\t\t\tImplementationProvider:     &protocol.Or_ServerCapabilities_implementationProvider{Value: true},\n\t\t\tDocumentFormattingProvider: &protocol.Or_ServerCapabilities_documentFormattingProvider{Value: true},\n\t\t\tDocumentSymbolProvider:     &protocol.Or_ServerCapabilities_documentSymbolProvider{Value: true},\n\t\t\tWorkspaceSymbolProvider:    &protocol.Or_ServerCapabilities_workspaceSymbolProvider{Value: true},\n\t\t\tExecuteCommandProvider: &protocol.ExecuteCommandOptions{\n\t\t\t\tCommands: protocol.NonNilSlice(options.SupportedCommands),\n\t\t\t},\n\t\t\tFoldingRangeProvider:      &protocol.Or_ServerCapabilities_foldingRangeProvider{Value: true},\n\t\t\tHoverProvider:             &protocol.Or_ServerCapabilities_hoverProvider{Value: true},\n\t\t\tDocumentHighlightProvider: &protocol.Or_ServerCapabilities_documentHighlightProvider{Value: true},\n\t\t\tDocumentLinkProvider:      &protocol.DocumentLinkOptions{},\n\t\t\tInlayHintProvider:         protocol.InlayHintOptions{},\n\t\t\tDiagnosticProvider:        diagnosticProvider,\n\t\t\tReferencesProvider:        &protocol.Or_ServerCapabilities_referencesProvider{Value: true},\n\t\t\tRenameProvider:            renameOpts,\n\t\t\tSelectionRangeProvider:    &protocol.Or_ServerCapabilities_selectionRangeProvider{Value: true},\n\t\t\tSemanticTokensProvider:    semanticTokenProvider,\n\t\t\tSignatureHelpProvider: &protocol.SignatureHelpOptions{\n\t\t\t\tTriggerCharacters: []string{\"(\", \",\"},\n\t\t\t\t// Used to update or dismiss signature help when it's already active,\n\t\t\t\t// typically after a call expression is closed.\n\t\t\t\tRetriggerCharacters: []string{\")\"},\n\t\t\t},\n\t\t\tTextDocumentSync: &protocol.TextDocumentSyncOptions{\n\t\t\t\tChange:    protocol.Incremental,\n\t\t\t\tOpenClose: true,\n\t\t\t\tSave: &protocol.SaveOptions{\n\t\t\t\t\tIncludeText: false,\n\t\t\t\t},\n\t\t\t},\n\t\t\tTypeHierarchyProvider: &protocol.Or_ServerCapabilities_typeHierarchyProvider{Value: true},\n\t\t\tWorkspace: &protocol.WorkspaceOptions{\n\t\t\t\tWorkspaceFolders: &protocol.WorkspaceFolders5Gn{\n\t\t\t\t\tSupported:           true,\n\t\t\t\t\tChangeNotifications: \"workspace/didChangeWorkspaceFolders\",\n\t\t\t\t},\n\t\t\t\tFileOperations: &protocol.FileOperationOptions{\n\t\t\t\t\tDidCreate: &protocol.FileOperationRegistrationOptions{\n\t\t\t\t\t\tFilters: []protocol.FileOperationFilter{{\n\t\t\t\t\t\t\tScheme: \"file\",\n\t\t\t\t\t\t\t// gopls is only interested with files in .go extension.\n\t\t\t\t\t\t\tPattern: protocol.FileOperationPattern{Glob: \"**/*.go\"},\n\t\t\t\t\t\t}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExperimental: map[string]any{\n\t\t\t\t// interactiveResolveProvider lists the LSP objects that support\n\t\t\t\t// an interactive resolution stage. For instance, the presence of\n\t\t\t\t// \"command\" indicates that the server handles \"command/resolve\"\n\t\t\t\t// requests.\n\t\t\t\t//\n\t\t\t\t// Due to the existence of \"codeAction/resolve\" and language\n\t\t\t\t// clients that resolve code action eagerly, \"codeAction\" can\n\t\t\t\t// never be interactively resolved.\n\t\t\t\t//\n\t\t\t\t// TODO(hxjiang): experiment with interactively resolving\n\t\t\t\t// \"RenameParams\". See golang/go#69107.\n\t\t\t\t\"interactiveResolveProvider\": []string{\"command\"},\n\t\t\t},\n\t\t},\n\t\tServerInfo: &protocol.ServerInfo{\n\t\t\tName:    \"gopls\",\n\t\t\tVersion: string(goplsVersion),\n\t\t},\n\t}, nil\n}\n\nfunc (s *server) Initialized(ctx context.Context, params *protocol.InitializedParams) error {\n\tctx, done := event.Start(ctx, \"server.Initialized\")\n\tdefer done()\n\n\ts.stateMu.Lock()\n\tif s.state >= serverInitialized {\n\t\tdefer s.stateMu.Unlock()\n\t\treturn fmt.Errorf(\"%w: initialized called while server in %v state\", jsonrpc2.ErrInvalidRequest, s.state)\n\t}\n\ts.state = serverInitialized\n\ts.stateMu.Unlock()\n\n\tfor _, not := range s.notifications {\n\t\ts.client.ShowMessage(ctx, not) // ignore error\n\t}\n\ts.notifications = nil\n\n\ts.addFolders(ctx, s.pendingFolders)\n\n\ts.pendingFolders = nil\n\ts.checkViewGoVersions()\n\n\tvar registrations []protocol.Registration\n\toptions := s.Options()\n\tif options.ConfigurationSupported && options.DynamicConfigurationSupported {\n\t\tregistrations = append(registrations, protocol.Registration{\n\t\t\tID:     \"workspace/didChangeConfiguration\",\n\t\t\tMethod: \"workspace/didChangeConfiguration\",\n\t\t})\n\t}\n\tif len(registrations) > 0 {\n\t\tif err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{\n\t\t\tRegistrations: registrations,\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Ask (maybe) about enabling telemetry. Do this asynchronously, as it's OK\n\t// for users to ignore or dismiss the question.\n\tgo s.maybePromptForTelemetry(ctx, options.TelemetryPrompt)\n\n\treturn nil\n}\n\n// checkViewGoVersions checks whether any Go version used by a view is too old,\n// raising a showMessage notification if so.\n//\n// It should be called after views change.\nfunc (s *server) checkViewGoVersions() {\n\toldestVersion, fromBuild := go1Point(), true\n\tfor _, view := range s.session.Views() {\n\t\tviewVersion := view.GoVersion()\n\t\tif oldestVersion == -1 || viewVersion < oldestVersion {\n\t\t\toldestVersion, fromBuild = viewVersion, false\n\t\t}\n\t\tif viewVersion >= 0 {\n\t\t\tcounter.Inc(fmt.Sprintf(\"gopls/goversion:1.%d\", viewVersion))\n\t\t}\n\t}\n\n\tif msg, isError := goversion.Message(oldestVersion, fromBuild); msg != \"\" {\n\t\tmType := protocol.Warning\n\t\tif isError {\n\t\t\tmType = protocol.Error\n\t\t}\n\t\ts.eventuallyShowMessage(context.Background(), &protocol.ShowMessageParams{\n\t\t\tType:    mType,\n\t\t\tMessage: msg,\n\t\t})\n\t}\n}\n\n// go1Point returns the x in Go 1.x. If an error occurs extracting the go\n// version, it returns -1.\n//\n// Copied from the testenv package.\nfunc go1Point() int {\n\tfor i := len(build.Default.ReleaseTags) - 1; i >= 0; i-- {\n\t\tvar version int\n\t\tif _, err := fmt.Sscanf(build.Default.ReleaseTags[i], \"go1.%d\", &version); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treturn version\n\t}\n\treturn -1\n}\n\n// addFolders adds the specified list of \"folders\" (that's Windows for\n// directories) to the session. It does not return an error, though it\n// may report an error to the client over LSP if one or more folders\n// had problems, for example, folders with unsupported file system.\nfunc (s *server) addFolders(ctx context.Context, folders []protocol.WorkspaceFolder) {\n\toriginalViews := len(s.session.Views())\n\tviewErrors := make(map[protocol.URI]error)\n\n\t// Skip non-'file' scheme, or invalid workspace folders,\n\t// and log them form error reports.\n\t// VS Code's file system API\n\t// (https://code.visualstudio.com/api/references/vscode-api#FileSystem)\n\t// allows extension to define their own schemes and register\n\t// them with the workspace. We've seen gitlens://, decompileFs://, etc\n\t// but the list can grow over time.\n\tvar filtered []protocol.WorkspaceFolder\n\tfor _, f := range folders {\n\t\turi, err := protocol.ParseDocumentURI(f.URI)\n\t\tif err != nil {\n\t\t\tdebuglog.Warning.Logf(ctx, \"skip adding virtual folder %q - invalid folder URI: %v\", f.Name, err)\n\t\t\tcontinue\n\t\t}\n\t\tif s.session.HasView(uri) {\n\t\t\tdebuglog.Warning.Logf(ctx, \"skip adding the already added folder %q - its view has been created before\", f.Name)\n\t\t\tcontinue\n\t\t}\n\t\tfiltered = append(filtered, f)\n\t}\n\tfolders = filtered\n\n\tvar ndiagnose sync.WaitGroup // number of unfinished diagnose calls\n\tif s.Options().VerboseWorkDoneProgress {\n\t\twork := s.progress.Start(ctx, DiagnosticWorkTitle(FromInitialWorkspaceLoad), \"Calculating diagnostics for initial workspace load...\", nil, nil)\n\t\tdefer func() {\n\t\t\tgo func() {\n\t\t\t\tndiagnose.Wait()\n\t\t\t\twork.End(ctx, \"Done.\")\n\t\t\t}()\n\t\t}()\n\t}\n\t// Only one view gets to have a workspace.\n\tvar nsnapshots sync.WaitGroup // number of unfinished snapshot initializations\n\tfor _, folder := range folders {\n\t\turi, err := protocol.ParseDocumentURI(folder.URI)\n\t\tif err != nil {\n\t\t\tviewErrors[folder.URI] = fmt.Errorf(\"invalid folder URI: %v\", err)\n\t\t\tcontinue\n\t\t}\n\t\twork := s.progress.Start(ctx, \"Setting up workspace\", \"Loading packages...\", nil, nil)\n\t\tsnapshot, release, err := s.addView(ctx, folder.Name, uri)\n\t\tif err != nil {\n\t\t\tif err == cache.ErrViewExists {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tviewErrors[folder.URI] = err\n\t\t\twork.End(ctx, fmt.Sprintf(\"Error loading packages: %s\", err))\n\t\t\tcontinue\n\t\t}\n\t\t// Inv: release() must be called once.\n\n\t\t// Initialize snapshot asynchronously.\n\t\tinitialized := make(chan struct{})\n\t\tnsnapshots.Add(1)\n\t\tgo func() {\n\t\t\tsnapshot.AwaitInitialized(ctx)\n\t\t\twork.End(ctx, \"Finished loading packages.\")\n\t\t\tnsnapshots.Done()\n\t\t\tclose(initialized) // signal\n\t\t}()\n\n\t\t// Diagnose the newly created view asynchronously.\n\t\tndiagnose.Go(func() {\n\t\t\ts.diagnoseSnapshot(snapshot.BackgroundContext(), snapshot, nil, 0)\n\t\t\t<-initialized\n\t\t\trelease()\n\t\t})\n\t}\n\n\t// Wait for snapshots to be initialized so that all files are known.\n\t// (We don't need to wait for diagnosis to finish.)\n\tnsnapshots.Wait()\n\n\t// Register for file watching notifications, if they are supported.\n\tif err := s.updateWatchedDirectories(ctx); err != nil {\n\t\tevent.Error(ctx, \"failed to register for file watching notifications\", err)\n\t}\n\n\t// Report any errors using the protocol.\n\tif len(viewErrors) > 0 {\n\t\tvar errMsg strings.Builder\n\t\tfmt.Fprintf(&errMsg, \"Error loading workspace folders (expected %v, got %v)\\n\", len(folders), len(s.session.Views())-originalViews)\n\t\tfor uri, err := range viewErrors {\n\t\t\tfmt.Fprintf(&errMsg, \"failed to load view for %s: %v\\n\", uri, err)\n\t\t}\n\t\tshowMessage(ctx, s.client, protocol.Error, errMsg.String())\n\t}\n}\n\n// updateWatchedDirectories compares the current set of directories to watch\n// with the previously registered set of directories. If the set of directories\n// has changed, we unregister and re-register for file watching notifications.\n// updatedSnapshots is the set of snapshots that have been updated.\nfunc (s *server) updateWatchedDirectories(ctx context.Context) error {\n\tpatterns := s.session.FileWatchingGlobPatterns(ctx)\n\n\ts.watchedGlobPatternsMu.Lock()\n\tdefer s.watchedGlobPatternsMu.Unlock()\n\n\t// Nothing to do if the set of workspace directories is unchanged.\n\tif moremaps.SameKeys(s.watchedGlobPatterns, patterns) {\n\t\treturn nil\n\t}\n\n\t// If the set of directories to watch has changed, register the updates and\n\t// unregister the previously watched directories. This ordering avoids a\n\t// period where no files are being watched. Still, if a user makes on-disk\n\t// changes before these updates are complete, we may miss them for the new\n\t// directories.\n\tprevID := s.watchRegistrationCount - 1\n\tif err := s.registerWatchedDirectoriesLocked(ctx, patterns); err != nil {\n\t\treturn err\n\t}\n\tif prevID >= 0 {\n\t\treturn s.client.UnregisterCapability(ctx, &protocol.UnregistrationParams{\n\t\t\tUnregisterations: []protocol.Unregistration{{\n\t\t\t\tID:     watchedFilesCapabilityID(prevID),\n\t\t\t\tMethod: \"workspace/didChangeWatchedFiles\",\n\t\t\t}},\n\t\t})\n\t}\n\treturn nil\n}\n\nfunc watchedFilesCapabilityID(id int) string {\n\treturn fmt.Sprintf(\"workspace/didChangeWatchedFiles-%d\", id)\n}\n\n// registerWatchedDirectoriesLocked sends the workspace/didChangeWatchedFiles\n// registrations to the client and updates s.watchedDirectories.\n// The caller must not subsequently mutate patterns.\nfunc (s *server) registerWatchedDirectoriesLocked(ctx context.Context, patterns map[protocol.RelativePattern]unit) error {\n\tif !s.Options().DynamicWatchedFilesSupported {\n\t\treturn nil\n\t}\n\n\tsupportsRelativePatterns := s.Options().RelativePatternsSupported\n\n\ts.watchedGlobPatterns = patterns\n\twatchers := make([]protocol.FileSystemWatcher, 0, len(patterns)) // must be a slice\n\tval := protocol.WatchChange | protocol.WatchDelete | protocol.WatchCreate\n\tfor pattern := range patterns {\n\t\tvar value any\n\t\tif supportsRelativePatterns && pattern.BaseURI != \"\" {\n\t\t\tvalue = pattern\n\t\t} else {\n\t\t\tp := pattern.Pattern\n\t\t\tif pattern.BaseURI != \"\" {\n\t\t\t\tp = path.Join(filepath.ToSlash(pattern.BaseURI.Path()), p)\n\t\t\t}\n\t\t\tvalue = p\n\t\t}\n\t\twatchers = append(watchers, protocol.FileSystemWatcher{\n\t\t\tGlobPattern: protocol.GlobPattern{Value: value},\n\t\t\tKind:        &val,\n\t\t})\n\t}\n\n\tif err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{\n\t\tRegistrations: []protocol.Registration{{\n\t\t\tID:     watchedFilesCapabilityID(s.watchRegistrationCount),\n\t\t\tMethod: \"workspace/didChangeWatchedFiles\",\n\t\t\tRegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{\n\t\t\t\tWatchers: watchers,\n\t\t\t},\n\t\t}},\n\t}); err != nil {\n\t\treturn err\n\t}\n\ts.watchRegistrationCount++\n\treturn nil\n}\n\n// Options returns the current server options.\n//\n// The caller must not modify the result.\nfunc (s *server) Options() *settings.Options {\n\ts.optionsMu.Lock()\n\tdefer s.optionsMu.Unlock()\n\treturn s.options\n}\n\n// SetOptions sets the current server options.\n//\n// The caller must not subsequently modify the options.\nfunc (s *server) SetOptions(opts *settings.Options) {\n\ts.optionsMu.Lock()\n\tdefer s.optionsMu.Unlock()\n\ts.options = opts\n}\n\nfunc (s *server) newFolder(ctx context.Context, folder protocol.DocumentURI, name string, opts *settings.Options) (*cache.Folder, error) {\n\tenv, err := cache.FetchGoEnv(ctx, folder, opts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Increment folder counters.\n\tswitch {\n\tcase env.GOTOOLCHAIN == \"auto\" || strings.Contains(env.GOTOOLCHAIN, \"+auto\"):\n\t\tcounter.Inc(\"gopls/gotoolchain:auto\")\n\tcase env.GOTOOLCHAIN == \"path\" || strings.Contains(env.GOTOOLCHAIN, \"+path\"):\n\t\tcounter.Inc(\"gopls/gotoolchain:path\")\n\tcase env.GOTOOLCHAIN == \"local\": // local+auto and local+path handled above\n\t\tcounter.Inc(\"gopls/gotoolchain:local\")\n\tdefault:\n\t\tcounter.Inc(\"gopls/gotoolchain:other\")\n\t}\n\n\t// Record whether a driver is in use so that it appears in the\n\t// user's telemetry upload. Although we can't correlate the\n\t// driver information with the crash or bug.Report at the\n\t// granularity of the process instance, users that use a\n\t// driver tend to do so most of the time, so we'll get a\n\t// strong clue. See #60890 for an example of an issue where\n\t// this information would have been helpful.\n\tif env.EffectiveGOPACKAGESDRIVER != \"\" {\n\t\tcounter.Inc(\"gopls/gopackagesdriver\")\n\t}\n\n\treturn &cache.Folder{\n\t\tDir:     folder,\n\t\tName:    name,\n\t\tOptions: opts,\n\t\tEnv:     *env,\n\t}, nil\n}\n\n// fetchFolderOptions makes a workspace/configuration request for the given\n// folder, and populates options with the result.\n//\n// If folder is \"\", fetchFolderOptions makes an unscoped request.\nfunc (s *server) fetchFolderOptions(ctx context.Context, folder protocol.DocumentURI) (*settings.Options, error) {\n\topts := s.Options()\n\tif !opts.ConfigurationSupported {\n\t\treturn opts, nil\n\t}\n\tvar scopeURI *string\n\tif folder != \"\" {\n\t\tscope := string(folder)\n\t\tscopeURI = &scope\n\t}\n\tconfigs, err := s.client.Configuration(ctx, &protocol.ParamConfiguration{\n\t\tItems: []protocol.ConfigurationItem{{\n\t\t\tScopeURI: scopeURI,\n\t\t\tSection:  \"gopls\",\n\t\t}},\n\t},\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get workspace configuration from client (%s): %v\", folder, err)\n\t}\n\n\topts = opts.Clone()\n\tfor _, config := range configs {\n\t\tres, errs := opts.Set(config)\n\t\ts.handleOptionResult(ctx, res, errs)\n\t}\n\treturn opts, nil\n}\n\nfunc (s *server) eventuallyShowMessage(ctx context.Context, msg *protocol.ShowMessageParams) {\n\ts.stateMu.Lock()\n\tdefer s.stateMu.Unlock()\n\tif s.state == serverInitialized {\n\t\t_ = s.client.ShowMessage(ctx, msg) // ignore error\n\t}\n\ts.notifications = append(s.notifications, msg)\n}\n\nfunc (s *server) handleOptionResult(ctx context.Context, applied []telemetry.CounterPath, optionErrors []error) {\n\tfor _, path := range applied {\n\t\tpath = append(settings.CounterPath{\"gopls\", \"setting\"}, path...)\n\t\tcounter.Inc(path.FullName())\n\t}\n\n\tvar warnings, errs []string\n\tfor _, err := range optionErrors {\n\t\tif err == nil {\n\t\t\tpanic(\"nil error passed to handleOptionErrors\")\n\t\t}\n\t\tif errors.Is(err, new(settings.SoftError)) {\n\t\t\twarnings = append(warnings, err.Error())\n\t\t} else {\n\t\t\terrs = append(errs, err.Error())\n\t\t}\n\t}\n\n\t// Sort messages, but put errors first.\n\t//\n\t// Having stable content for the message allows clients to de-duplicate. This\n\t// matters because we may send duplicate warnings for clients that support\n\t// dynamic configuration: one for the initial settings, and then more for the\n\t// individual viewsettings.\n\tvar msgs []string\n\tmsgType := protocol.Warning\n\tif len(errs) > 0 {\n\t\tmsgType = protocol.Error\n\t\tsort.Strings(errs)\n\t\tmsgs = append(msgs, errs...)\n\t}\n\tif len(warnings) > 0 {\n\t\tsort.Strings(warnings)\n\t\tmsgs = append(msgs, warnings...)\n\t}\n\n\tif len(msgs) > 0 {\n\t\t// Settings\n\t\tcombined := \"Invalid settings: \" + strings.Join(msgs, \"; \")\n\t\tparams := &protocol.ShowMessageParams{\n\t\t\tType:    msgType,\n\t\t\tMessage: combined,\n\t\t}\n\t\ts.eventuallyShowMessage(ctx, params)\n\t}\n}\n\n// Shutdown implements the 'shutdown' LSP handler. It releases resources\n// associated with the server and waits for all ongoing work to complete.\nfunc (s *server) Shutdown(ctx context.Context) error {\n\tctx, done := event.Start(ctx, \"server.Shutdown\")\n\tdefer done()\n\n\ts.stateMu.Lock()\n\tdefer s.stateMu.Unlock()\n\tif s.state < serverInitialized {\n\t\tevent.Log(ctx, \"server shutdown without initialization\")\n\t}\n\tif s.state != serverShutDown {\n\t\t// Wait for the webserver (if any) to finish.\n\t\tif s.web != nil {\n\t\t\ts.web.server.Shutdown(ctx) // ignore error\n\t\t}\n\n\t\t// drop all the active views\n\t\ts.session.Shutdown(ctx)\n\t\ts.state = serverShutDown\n\t}\n\treturn nil\n}\n\nfunc (s *server) Exit(ctx context.Context) error {\n\tctx, done := event.Start(ctx, \"server.Exit\")\n\tdefer done()\n\n\ts.stateMu.Lock()\n\tdefer s.stateMu.Unlock()\n\n\ts.client.Close() // ignore error\n\n\tif s.state != serverShutDown {\n\t\t// TODO: We should be able to do better than this.\n\t\tos.Exit(1)\n\t}\n\t// We don't terminate the process on a normal exit, we just allow it to\n\t// close naturally if needed after the connection is closed.\n\treturn nil\n}\n\n// recordClientInfo records gopls client info.\nfunc recordClientInfo(clientName string) {\n\tkey := \"gopls/client:other\"\n\tswitch clientName {\n\tcase \"Visual Studio Code\":\n\t\tkey = \"gopls/client:vscode\"\n\tcase \"Visual Studio Code - Insiders\":\n\t\tkey = \"gopls/client:vscode-insiders\"\n\tcase \"VSCodium\":\n\t\tkey = \"gopls/client:vscodium\"\n\tcase \"code-server\":\n\t\t// https://github.com/coder/code-server/blob/3cb92edc76ecc2cfa5809205897d93d4379b16a6/ci/build/build-vscode.sh#L19\n\t\tkey = \"gopls/client:code-server\"\n\tcase \"Eglot\":\n\t\t// https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-03/msg00954.html\n\t\tkey = \"gopls/client:eglot\"\n\tcase \"govim\":\n\t\t// https://github.com/govim/govim/pull/1189\n\t\tkey = \"gopls/client:govim\"\n\tcase \"helix\":\n\t\t// https://github.com/helix-editor/helix/blob/d0218f7e78bc0c3af4b0995ab8bda66b9c542cf3/helix-lsp/src/client.rs#L714\n\t\tkey = \"gopls/client:helix\"\n\tcase \"Neovim\":\n\t\t// https://github.com/neovim/neovim/blob/42333ea98dfcd2994ee128a3467dfe68205154cd/runtime/lua/vim/lsp.lua#L1361\n\t\tkey = \"gopls/client:neovim\"\n\tcase \"coc.nvim\":\n\t\t// https://github.com/neoclide/coc.nvim/blob/3dc6153a85ed0f185abec1deb972a66af3fbbfb4/src/language-client/client.ts#L994\n\t\tkey = \"gopls/client:coc.nvim\"\n\tcase \"Sublime Text LSP\":\n\t\t// https://github.com/sublimelsp/LSP/blob/e608f878e7e9dd34aabe4ff0462540fadcd88fcc/plugin/core/sessions.py#L493\n\t\tkey = \"gopls/client:sublimetext\"\n\tcase \"Windsurf\":\n\t\tkey = \"gopls/client:windsurf\"\n\tcase \"Cursor\":\n\t\tkey = \"gopls/client:cursor\"\n\tcase \"Zed\", \"Zed Dev\", \"Zed Nightly\", \"Zed Preview\":\n\t\t// https: //github.com/zed-industries/zed/blob/0ac17526687bf11007f0fbb5c3b2ff463ce47293/crates/release_channel/src/lib.rs#L147\n\t\tkey = \"gopls/client:zed\"\n\tdefault:\n\t\t// Accumulate at least a local counter for an unknown\n\t\t// client name, but also fall through to count it as\n\t\t// \":other\" for collection.\n\t\tif clientName != \"\" {\n\t\t\tcounter.New(fmt.Sprintf(\"gopls/client-other:%s\", clientName)).Inc()\n\t\t}\n\t}\n\tcounter.Inc(key)\n}\n"
  },
  {
    "path": "gopls/internal/server/highlight.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) DocumentHighlight(ctx context.Context, params *protocol.DocumentHighlightParams) ([]protocol.DocumentHighlight, error) {\n\tctx, done := event.Start(ctx, \"server.DocumentHighlight\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Tmpl:\n\t\treturn template.Highlight(ctx, snapshot, fh, params.Range)\n\tcase file.Go:\n\t\trngs, err := golang.Highlight(ctx, snapshot, fh, params.Range)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"no highlight\", err)\n\t\t}\n\t\treturn rngs, nil\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/hover.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/gopls/internal/work\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Hover(ctx context.Context, params *protocol.HoverParams) (_ *protocol.Hover, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"hover\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.Hover\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Mod:\n\t\treturn mod.Hover(ctx, snapshot, fh, params.Range)\n\tcase file.Go:\n\t\tvar pkgURL func(path golang.PackagePath, fragment string) protocol.URI\n\t\tif snapshot.Options().LinksInHover == settings.LinksInHover_Gopls {\n\t\t\tweb, err := s.getWeb()\n\t\t\tif err != nil {\n\t\t\t\tevent.Error(ctx, \"failed to start web server\", err)\n\t\t\t} else {\n\t\t\t\tpkgURL = func(path golang.PackagePath, fragment string) protocol.URI {\n\t\t\t\t\treturn web.PkgURL(snapshot.View().ID(), path, fragment)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn golang.Hover(ctx, snapshot, fh, params.Range, pkgURL)\n\tcase file.Tmpl:\n\t\treturn template.Hover(ctx, snapshot, fh, params.Range)\n\tcase file.Work:\n\t\treturn work.Hover(ctx, snapshot, fh, params.Range)\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/implementation.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Implementation(ctx context.Context, params *protocol.ImplementationParams) (_ []protocol.Location, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"implementation\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.Implementation\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil // empty result\n\t}\n\treturn golang.Implementation(ctx, snapshot, fh, params.Range)\n}\n"
  },
  {
    "path": "gopls/internal/server/inlay_hint.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) InlayHint(ctx context.Context, params *protocol.InlayHintParams) ([]protocol.InlayHint, error) {\n\tctx, done := event.Start(ctx, \"server.InlayHint\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Mod:\n\t\treturn mod.InlayHint(ctx, snapshot, fh, params.Range)\n\tcase file.Go:\n\t\treturn golang.InlayHint(ctx, snapshot, fh, params.Range)\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/link.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"net/url\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"mvdan.cc/xurls/v2\"\n)\n\nfunc (s *server) DocumentLink(ctx context.Context, params *protocol.DocumentLinkParams) (links []protocol.DocumentLink, err error) {\n\tctx, done := event.Start(ctx, \"server.DocumentLink\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Mod:\n\t\tlinks, err = modLinks(ctx, snapshot, fh)\n\tcase file.Go:\n\t\tlinks, err = goLinks(ctx, snapshot, fh)\n\t}\n\t// Don't return errors for document links.\n\tif err != nil {\n\t\tevent.Error(ctx, \"failed to compute document links\", err, label.URI.Of(fh.URI()))\n\t\treturn nil, nil // empty result\n\t}\n\treturn links, nil // may be empty (for other file types)\n}\n\nfunc modLinks(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentLink, error) {\n\tpm, err := snapshot.ParseMod(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar links []protocol.DocumentLink\n\tfor _, rep := range pm.File.Replace {\n\t\tif modfile.IsDirectoryPath(rep.New.Path) {\n\t\t\t// Have local replacement, such as 'replace A => ../'.\n\t\t\tdep := []byte(rep.New.Path)\n\t\t\tstart, end := rep.Syntax.Start.Byte, rep.Syntax.End.Byte\n\t\t\ti := bytes.Index(pm.Mapper.Content[start:end], dep)\n\t\t\tif i < 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath := rep.New.Path\n\t\t\tif !filepath.IsAbs(path) {\n\t\t\t\tpath = filepath.Join(fh.URI().DirPath(), path)\n\t\t\t}\n\t\t\t// jump to the go.mod file of replaced module.\n\t\t\tpath = filepath.Join(filepath.Clean(path), \"go.mod\")\n\t\t\tl, err := toProtocolLink(pm.Mapper, protocol.URIFromPath(path).Path(), start+i, start+i+len(dep))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlinks = append(links, l)\n\t\t\tcontinue\n\t\t}\n\t}\n\n\tfor _, req := range pm.File.Require {\n\t\tif req.Syntax == nil {\n\t\t\tcontinue\n\t\t}\n\t\t// See golang/go#36998: don't link to modules matching GOPRIVATE.\n\t\tif snapshot.IsGoPrivatePath(req.Mod.Path) {\n\t\t\tcontinue\n\t\t}\n\t\tdep := []byte(req.Mod.Path)\n\t\tstart, end := req.Syntax.Start.Byte, req.Syntax.End.Byte\n\t\ti := bytes.Index(pm.Mapper.Content[start:end], dep)\n\t\tif i == -1 {\n\t\t\tcontinue\n\t\t}\n\n\t\tmod := req.Mod\n\t\t// respect the replacement when constructing a module link.\n\t\tif m, ok := pm.ReplaceMap[req.Mod]; ok {\n\t\t\t// Have: 'replace A v1.2.3 => A vx.x.x' or 'replace A v1.2.3 => B vx.x.x'.\n\t\t\tmod = m\n\t\t} else if m, ok := pm.ReplaceMap[module.Version{Path: req.Mod.Path}]; ok &&\n\t\t\t!modfile.IsDirectoryPath(m.Path) { // exclude local replacement.\n\t\t\t// Have: 'replace A => A vx.x.x' or 'replace A => B vx.x.x'.\n\t\t\tmod = m\n\t\t}\n\n\t\t// Shift the start position to the location of the\n\t\t// dependency within the require statement.\n\t\ttarget := cache.BuildLink(snapshot.Options().LinkTarget, \"mod/\"+mod.String(), \"\")\n\t\tl, err := toProtocolLink(pm.Mapper, target, start+i, start+i+len(dep))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlinks = append(links, l)\n\t}\n\t// TODO(ridersofrohan): handle links for replace and exclude directives.\n\tif syntax := pm.File.Syntax; syntax == nil {\n\t\treturn links, nil\n\t}\n\n\t// Get all the links that are contained in the comments of the file.\n\turlRegexp := xurls.Relaxed()\n\tfor _, expr := range pm.File.Syntax.Stmt {\n\t\tcomments := expr.Comment()\n\t\tif comments == nil {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, section := range [][]modfile.Comment{comments.Before, comments.Suffix, comments.After} {\n\t\t\tfor _, comment := range section {\n\t\t\t\tl, err := findLinksInString(urlRegexp, comment.Token, comment.Start.Byte, pm.Mapper)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tlinks = append(links, l...)\n\t\t\t}\n\t\t}\n\t}\n\treturn links, nil\n}\n\n// goLinks returns the set of hyperlink annotations for the specified Go file.\nfunc goLinks(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentLink, error) {\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar links []protocol.DocumentLink\n\n\t// Create links for import specs.\n\tif snapshot.Options().ImportShortcut.ShowLinks() {\n\n\t\t// If links are to pkg.go.dev, append module version suffixes.\n\t\t// This requires the import map from the package metadata. Ignore errors.\n\t\tvar depsByImpPath map[golang.ImportPath]golang.PackageID\n\t\tif strings.ToLower(snapshot.Options().LinkTarget) == \"pkg.go.dev\" {\n\t\t\tif meta, err := snapshot.NarrowestMetadataForFile(ctx, fh.URI()); err == nil {\n\t\t\t\tdepsByImpPath = meta.DepsByImpPath\n\t\t\t}\n\t\t}\n\n\t\tfor _, imp := range pgf.File.Imports {\n\t\t\timportPath := metadata.UnquoteImportPath(imp)\n\t\t\tif importPath == \"\" {\n\t\t\t\tcontinue // bad import\n\t\t\t}\n\t\t\t// See golang/go#36998: don't link to modules matching GOPRIVATE.\n\t\t\tif snapshot.IsGoPrivatePath(string(importPath)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\turlPath := string(importPath)\n\n\t\t\t// For pkg.go.dev, append module version suffix to package import path.\n\t\t\tif mp := snapshot.Metadata(depsByImpPath[importPath]); mp != nil && mp.Module != nil && cache.ResolvedPath(mp.Module) != \"\" && cache.ResolvedVersion(mp.Module) != \"\" {\n\t\t\t\turlPath = strings.Replace(urlPath, mp.Module.Path, cache.ResolvedString(mp.Module), 1)\n\t\t\t}\n\n\t\t\tstart, end, err := safetoken.Offsets(pgf.Tok, imp.Path.Pos(), imp.Path.End())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ttargetURL := cache.BuildLink(snapshot.Options().LinkTarget, urlPath, \"\")\n\t\t\t// Account for the quotation marks in the positions.\n\t\t\tl, err := toProtocolLink(pgf.Mapper, targetURL, start+len(`\"`), end-len(`\"`))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlinks = append(links, l)\n\t\t}\n\t}\n\n\turlRegexp := xurls.Relaxed()\n\n\t// Gather links found in string literals.\n\tvar str []*ast.BasicLit\n\tfor curLit := range pgf.Cursor().Preorder((*ast.BasicLit)(nil)) {\n\t\tlit := curLit.Node().(*ast.BasicLit)\n\t\tif lit.Kind == token.STRING {\n\t\t\tif _, ok := curLit.Parent().Node().(*ast.ImportSpec); ok {\n\t\t\t\tcontinue // ignore import strings\n\t\t\t}\n\t\t\tstr = append(str, lit)\n\t\t}\n\t}\n\tfor _, s := range str {\n\t\tstrOffset, err := safetoken.Offset(pgf.Tok, s.Pos())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tl, err := findLinksInString(urlRegexp, s.Value, strOffset, pgf.Mapper)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlinks = append(links, l...)\n\t}\n\n\t// Gather links found in comments.\n\tfor _, commentGroup := range pgf.File.Comments {\n\t\tfor _, comment := range commentGroup.List {\n\t\t\tcommentOffset, err := safetoken.Offset(pgf.Tok, comment.Pos())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tl, err := findLinksInString(urlRegexp, comment.Text, commentOffset, pgf.Mapper)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlinks = append(links, l...)\n\t\t}\n\t}\n\n\treturn links, nil\n}\n\n// acceptedSchemes controls the schemes that URLs must have to be shown to the\n// user. Other schemes can't be opened by LSP clients, so linkifying them is\n// distracting. See golang/go#43990.\nvar acceptedSchemes = map[string]bool{\n\t\"http\":  true,\n\t\"https\": true,\n}\n\n// findLinksInString is the user-supplied regular expression to match URL.\n// srcOffset is the start offset of 'src' within m's file.\nfunc findLinksInString(urlRegexp *regexp.Regexp, src string, srcOffset int, m *protocol.Mapper) ([]protocol.DocumentLink, error) {\n\tvar links []protocol.DocumentLink\n\tfor _, index := range urlRegexp.FindAllIndex([]byte(src), -1) {\n\t\tstart, end := index[0], index[1]\n\t\tlink := src[start:end]\n\t\tlinkURL, err := url.Parse(link)\n\t\t// Fallback: Linkify IP addresses as suggested in golang/go#18824.\n\t\tif err != nil {\n\t\t\tlinkURL, err = url.Parse(\"//\" + link)\n\t\t\t// Not all potential links will be valid, so don't return this error.\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\t// If the URL has no scheme, use https.\n\t\tif linkURL.Scheme == \"\" {\n\t\t\tlinkURL.Scheme = \"https\"\n\t\t}\n\t\tif !acceptedSchemes[linkURL.Scheme] {\n\t\t\tcontinue\n\t\t}\n\n\t\tl, err := toProtocolLink(m, linkURL.String(), srcOffset+start, srcOffset+end)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlinks = append(links, l)\n\t}\n\t// Handle golang/go#1234-style links.\n\tr := getIssueRegexp()\n\tfor _, index := range r.FindAllIndex([]byte(src), -1) {\n\t\tstart, end := index[0], index[1]\n\t\tmatches := r.FindStringSubmatch(src)\n\t\tif len(matches) < 4 {\n\t\t\tcontinue\n\t\t}\n\t\torg, repo, number := matches[1], matches[2], matches[3]\n\t\ttargetURL := fmt.Sprintf(\"https://github.com/%s/%s/issues/%s\", org, repo, number)\n\t\tl, err := toProtocolLink(m, targetURL, srcOffset+start, srcOffset+end)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlinks = append(links, l)\n\t}\n\treturn links, nil\n}\n\nfunc getIssueRegexp() *regexp.Regexp {\n\tonce.Do(func() {\n\t\tissueRegexp = regexp.MustCompile(`(\\w+)/([\\w-]+)#([0-9]+)`)\n\t})\n\treturn issueRegexp\n}\n\nvar (\n\tonce        sync.Once\n\tissueRegexp *regexp.Regexp\n)\n\nfunc toProtocolLink(m *protocol.Mapper, targetURL string, start, end int) (protocol.DocumentLink, error) {\n\trng, err := m.OffsetRange(start, end)\n\tif err != nil {\n\t\treturn protocol.DocumentLink{}, err\n\t}\n\treturn protocol.DocumentLink{\n\t\tRange:  rng,\n\t\tTarget: &targetURL,\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/prompt.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/telemetry\"\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// promptTimeout is the amount of time we wait for an ongoing prompt before\n// prompting again. This gives the user time to reply. However, at some point\n// we must assume that the client is not displaying the prompt, the user is\n// ignoring it, or the prompt has been disrupted in some way (e.g. by a gopls\n// crash).\nconst promptTimeout = 24 * time.Hour\n\n// gracePeriod is the amount of time we wait before sufficient telemetry data\n// is accumulated in the local directory, so users can have time to review\n// what kind of information will be collected and uploaded when prompting starts.\nconst gracePeriod = 7 * 24 * time.Hour\n\n// samplesPerMille is the prompt probability.\n// Token is an integer between [1, 1000] and is assigned when maybePromptForTelemetry\n// is called first time. Only the user with a token ∈ [1, samplesPerMille]\n// will be considered for prompting.\nconst samplesPerMille = 10 // 1% sample rate\n\n// The following constants are used for testing telemetry integration.\nconst (\n\tTelemetryPromptWorkTitle    = \"Checking telemetry prompt\"     // progress notification title, for awaiting in tests\n\tGoplsConfigDirEnvvar        = \"GOPLS_CONFIG_DIR\"              // overridden for testing\n\tFakeTelemetryModefileEnvvar = \"GOPLS_FAKE_TELEMETRY_MODEFILE\" // overridden for testing\n\tFakeSamplesPerMille         = \"GOPLS_FAKE_SAMPLES_PER_MILLE\"  // overridden for testing\n\tTelemetryYes                = \"Yes, I'd like to help.\"\n\tTelemetryNo                 = \"No, thanks.\"\n)\n\n// The following environment variables may be set by the client.\n// Exported for testing telemetry integration.\nconst (\n\tGoTelemetryGoplsClientStartTimeEnvvar = \"GOTELEMETRY_GOPLS_CLIENT_START_TIME\" // telemetry start time recorded in client\n\tGoTelemetryGoplsClientTokenEnvvar     = \"GOTELEMETRY_GOPLS_CLIENT_TOKEN\"      // sampling token\n)\n\n// getenv returns the effective environment variable value for the provided\n// key, looking up the key in the session environment before falling back on\n// the process environment.\nfunc (s *server) getenv(key string) string {\n\tif v, ok := s.Options().Env[key]; ok {\n\t\treturn v\n\t}\n\treturn os.Getenv(key)\n}\n\n// telemetryMode returns the current effective telemetry mode.\n// By default this is x/telemetry.Mode(), but it may be overridden for tests.\nfunc (s *server) telemetryMode() string {\n\tif fake := s.getenv(FakeTelemetryModefileEnvvar); fake != \"\" {\n\t\tif data, err := os.ReadFile(fake); err == nil {\n\t\t\treturn string(data)\n\t\t}\n\t\treturn \"local\"\n\t}\n\treturn telemetry.Mode()\n}\n\n// setTelemetryMode sets the current telemetry mode.\n// By default this calls x/telemetry.SetMode, but it may be overridden for\n// tests.\nfunc (s *server) setTelemetryMode(mode string) error {\n\tif fake := s.getenv(FakeTelemetryModefileEnvvar); fake != \"\" {\n\t\treturn os.WriteFile(fake, []byte(mode), 0666)\n\t}\n\treturn telemetry.SetMode(mode)\n}\n\n// maybePromptForTelemetry checks for the right conditions, and then prompts\n// the user to ask if they want to enable Go telemetry uploading. If the user\n// responds 'Yes', the telemetry mode is set to \"on\".\n//\n// The actual conditions for prompting are defensive, erring on the side of not\n// prompting.\n// If enabled is false, this will not prompt the user in any condition,\n// but will send work progress reports to help testing.\nfunc (s *server) maybePromptForTelemetry(ctx context.Context, enabled bool) {\n\tif s.Options().VerboseWorkDoneProgress {\n\t\twork := s.progress.Start(ctx, TelemetryPromptWorkTitle, \"Checking if gopls should prompt about telemetry...\", nil, nil)\n\t\tdefer work.End(ctx, \"Done.\")\n\t}\n\n\terrorf := func(format string, args ...any) {\n\t\terr := fmt.Errorf(format, args...)\n\t\tevent.Error(ctx, \"telemetry prompt failed\", err)\n\t}\n\n\t// Only prompt if we can read/write the prompt config file.\n\tconfigDir := s.getenv(GoplsConfigDirEnvvar) // set for testing\n\tif configDir == \"\" && testing.Testing() {\n\t\t// Unless tests set GoplsConfigDirEnvvar, the prompt is a no op.\n\t\t// We don't want tests to interact with os.UserConfigDir().\n\t\treturn\n\t}\n\tif configDir == \"\" {\n\t\tuserDir, err := os.UserConfigDir()\n\t\tif err != nil {\n\t\t\terrorf(\"unable to determine user config dir: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tconfigDir = filepath.Join(userDir, \"gopls\")\n\t}\n\n\t// Read the current prompt file.\n\n\tvar (\n\t\tpromptDir  = filepath.Join(configDir, \"prompt\")    // prompt configuration directory\n\t\tpromptFile = filepath.Join(promptDir, \"telemetry\") // telemetry prompt file\n\t)\n\n\t// prompt states, stored in the prompt file\n\tconst (\n\t\tpUnknown  = \"\"        // first time\n\t\tpNotReady = \"-\"       // user is not asked yet (either not sampled or not past the grace period)\n\t\tpYes      = \"yes\"     // user said yes\n\t\tpNo       = \"no\"      // user said no\n\t\tpPending  = \"pending\" // current prompt is still pending\n\t\tpFailed   = \"failed\"  // prompt was asked but failed\n\t)\n\tvalidStates := map[string]bool{\n\t\tpNotReady: true,\n\t\tpYes:      true,\n\t\tpNo:       true,\n\t\tpPending:  true,\n\t\tpFailed:   true,\n\t}\n\n\t// Parse the current prompt file.\n\tvar (\n\t\tstate    = pUnknown\n\t\tattempts = 0 // number of times we've asked already\n\n\t\t// the followings are recorded after gopls v0.17+.\n\t\ttoken        = 0   // valid token is [1, 1000]\n\t\tcreationTime int64 // unix time sec\n\t)\n\tif content, err := os.ReadFile(promptFile); err == nil {\n\t\tif n, _ := fmt.Sscanf(string(content), \"%s %d %d %d\", &state, &attempts, &creationTime, &token); (n == 2 || n == 4) && validStates[state] {\n\t\t\t// successfully parsed!\n\t\t\t//  ~ v0.16: must have only two fields, state and attempts.\n\t\t\t//  v0.17 ~: must have all four fields.\n\t\t} else {\n\t\t\tstate, attempts, creationTime, token = pUnknown, 0, 0, 0\n\t\t\t// TODO(hyangah): why do we want to present this as an error to user?\n\t\t\terrorf(\"malformed prompt result %q\", string(content))\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\terrorf(\"reading prompt file: %v\", err)\n\t\t// Something went wrong. Since we don't know how many times we've asked the\n\t\t// prompt, err on the side of not asking.\n\t\t//\n\t\t// But record this in telemetry, in case some users enable telemetry by\n\t\t// other means.\n\t\tcounter.New(\"gopls/telemetryprompt/corrupted\").Inc()\n\t\treturn\n\t}\n\n\tcounter.New(fmt.Sprintf(\"gopls/telemetryprompt/attempts:%d\", attempts)).Inc()\n\n\t// Check terminal conditions.\n\n\tif state == pYes {\n\t\t// Prompt has been accepted.\n\t\t//\n\t\t// We record this counter for every gopls session, rather than when the\n\t\t// prompt actually accepted below, because if we only recorded it in the\n\t\t// counter file at the time telemetry is enabled, we'd never upload it,\n\t\t// because we exclude any counter files that overlap with a time period\n\t\t// that has telemetry uploading is disabled.\n\t\tcounter.New(\"gopls/telemetryprompt/accepted\").Inc()\n\t\treturn\n\t}\n\tif state == pNo {\n\t\t// Prompt has been declined. In most cases, this means we'll never see the\n\t\t// counter below, but it's possible that the user may enable telemetry by\n\t\t// other means later on. If we see a significant number of users that have\n\t\t// accepted telemetry but declined the prompt, it may be an indication that\n\t\t// the prompt is not working well.\n\t\tcounter.New(\"gopls/telemetryprompt/declined\").Inc()\n\t\treturn\n\t}\n\tif attempts >= 5 { // pPending or pFailed\n\t\t// We've tried asking enough; give up. Record that the prompt expired, in\n\t\t// case the user decides to enable telemetry by other means later on.\n\t\t// (see also the pNo case).\n\t\tcounter.New(\"gopls/telemetryprompt/expired\").Inc()\n\t\treturn\n\t}\n\n\t// We only check enabled after (1) the work progress is started, and (2) the\n\t// prompt file has been read. (1) is for testing purposes, and (2) is so that\n\t// we record the \"gopls/telemetryprompt/accepted\" counter for every session.\n\tif !enabled {\n\t\treturn // prompt is disabled\n\t}\n\n\tif s.telemetryMode() == \"on\" || s.telemetryMode() == \"off\" {\n\t\t// Telemetry is already on or explicitly off -- nothing to ask about.\n\t\treturn\n\t}\n\n\t// Transition: pUnknown -> pNotReady\n\tif state == pUnknown {\n\t\t// First time; we need to make the prompt dir.\n\t\tif err := os.MkdirAll(promptDir, 0777); err != nil {\n\t\t\terrorf(\"creating prompt dir: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tstate = pNotReady\n\t}\n\n\t// Correct missing values.\n\tif creationTime == 0 {\n\t\tcreationTime = time.Now().Unix()\n\t\tif v := s.getenv(GoTelemetryGoplsClientStartTimeEnvvar); v != \"\" {\n\t\t\tif sec, err := strconv.ParseInt(v, 10, 64); err == nil && sec > 0 {\n\t\t\t\tcreationTime = sec\n\t\t\t}\n\t\t}\n\t}\n\tif token == 0 {\n\t\ttoken = rand.Intn(1000) + 1\n\t\tif v := s.getenv(GoTelemetryGoplsClientTokenEnvvar); v != \"\" {\n\t\t\tif tok, err := strconv.Atoi(v); err == nil && 1 <= tok && tok <= 1000 {\n\t\t\t\ttoken = tok\n\t\t\t}\n\t\t}\n\t}\n\n\t// Transition: pNotReady -> pPending if sampled\n\tif state == pNotReady {\n\t\tthreshold := samplesPerMille\n\t\tif v := s.getenv(FakeSamplesPerMille); v != \"\" {\n\t\t\tif t, err := strconv.Atoi(v); err == nil {\n\t\t\t\tthreshold = t\n\t\t\t}\n\t\t}\n\t\tif token <= threshold && time.Now().Unix()-creationTime > gracePeriod.Milliseconds()/1000 {\n\t\t\tstate = pPending\n\t\t}\n\t}\n\n\t// Acquire the lock and write the updated state to the prompt file before actually\n\t// prompting.\n\t//\n\t// This ensures that the prompt file is writeable, and that we increment the\n\t// attempt counter before we prompt, so that we don't end up in a failure\n\t// mode where we keep prompting and then failing to record the response.\n\n\trelease, ok, err := acquireLockFile(promptFile)\n\tif err != nil {\n\t\terrorf(\"acquiring prompt: %v\", err)\n\t\treturn\n\t}\n\tif !ok {\n\t\t// Another process is making decision.\n\t\treturn\n\t}\n\tdefer release()\n\n\tif state != pNotReady { // pPending or pFailed\n\t\tattempts++\n\t}\n\n\tpendingContent := fmt.Appendf(nil, \"%s %d %d %d\", state, attempts, creationTime, token)\n\tif err := os.WriteFile(promptFile, pendingContent, 0666); err != nil {\n\t\terrorf(\"writing pending state: %v\", err)\n\t\treturn\n\t}\n\n\tif state == pNotReady {\n\t\treturn\n\t}\n\n\tvar prompt = `Go telemetry helps us improve Go by periodically sending anonymous metrics and crash reports to the Go team. Learn more at https://go.dev/doc/telemetry.\n\nWould you like to enable Go telemetry?\n`\n\tif s.Options().LinkifyShowMessage {\n\t\tprompt = `Go telemetry helps us improve Go by periodically sending anonymous metrics and crash reports to the Go team. Learn more at [go.dev/doc/telemetry](https://go.dev/doc/telemetry).\n\nWould you like to enable Go telemetry?\n`\n\t}\n\t// TODO(rfindley): investigate a \"tell me more\" action in combination with ShowDocument.\n\taction, err := showMessageRequest(ctx, s.client, protocol.Info, prompt, TelemetryYes, TelemetryNo)\n\tif err != nil {\n\t\terrorf(\"ShowMessageRequest failed: %v\", err)\n\t}\n\n\tmessage := func(typ protocol.MessageType, msg string) {\n\t\tif !showMessage(ctx, s.client, typ, msg) {\n\t\t\t// Make sure we record that \"telemetry prompt failed\".\n\t\t\terrorf(\"showMessage failed: %v\", err)\n\t\t}\n\t}\n\n\tresult := pFailed\n\tif action == \"\" {\n\t\t// e.g. dialog was dismissed\n\t\terrorf(\"no response\")\n\t} else {\n\t\t// Response matches MessageActionItem.Title.\n\t\tswitch action {\n\t\tcase TelemetryYes:\n\t\t\tresult = pYes\n\t\t\tif err := s.setTelemetryMode(\"on\"); err == nil {\n\t\t\t\tmessage(protocol.Info, telemetryOnMessage(s.Options().LinkifyShowMessage))\n\t\t\t} else {\n\t\t\t\terrorf(\"enabling telemetry failed: %v\", err)\n\t\t\t\tmsg := fmt.Sprintf(\"Failed to enable Go telemetry: %v\\nTo enable telemetry manually, please run `go run golang.org/x/telemetry/cmd/gotelemetry@latest on`\", err)\n\t\t\t\tmessage(protocol.Error, msg)\n\t\t\t}\n\n\t\tcase TelemetryNo:\n\t\t\tresult = pNo\n\t\tdefault:\n\t\t\terrorf(\"unrecognized response %q\", action)\n\t\t\tmessage(protocol.Error, fmt.Sprintf(\"Unrecognized response %q\", action))\n\t\t}\n\t}\n\tresultContent := fmt.Appendf(nil, \"%s %d %d %d\", result, attempts, creationTime, token)\n\tif err := os.WriteFile(promptFile, resultContent, 0666); err != nil {\n\t\terrorf(\"error writing result state to prompt file: %v\", err)\n\t}\n}\n\n// showMessageRequest causes the client to show a prompt that the user can respond to.\n// It returns the title of the action the user selected, or \"\" if the user dismissed the prompt.\nfunc showMessageRequest(ctx context.Context, cli protocol.Client, typ protocol.MessageType, message string, actions ...string) (string, error) {\n\tvar actionItems []protocol.MessageActionItem\n\tfor _, action := range actions {\n\t\tactionItems = append(actionItems, protocol.MessageActionItem{Title: action})\n\t}\n\tparams := &protocol.ShowMessageRequestParams{\n\t\tType:    typ,\n\t\tMessage: message,\n\t\tActions: actionItems,\n\t}\n\t// Timeout used to wait for the user to respond to a message request.\n\tconst timeout = 15 * time.Second\n\tctx, cancel := context.WithTimeout(ctx, timeout)\n\tdefer cancel()\n\n\tresult, err := cli.ShowMessageRequest(ctx, params)\n\n\tif err != nil {\n\t\tif cause := context.Cause(ctx); cause == context.DeadlineExceeded || cause == context.Canceled {\n\t\t\treturn \"\", nil\n\t\t}\n\t\treturn \"\", err\n\t}\n\tif result == nil {\n\t\treturn \"\", nil // User dismissed the notification\n\t}\n\treturn result.Title, nil\n}\n\nfunc telemetryOnMessage(linkify bool) string {\n\tformat := `Thank you. Telemetry uploading is now enabled.\n\nTo disable telemetry uploading, run %s.\n`\n\tvar runCmd = \"`go run golang.org/x/telemetry/cmd/gotelemetry@latest local`\"\n\tif linkify {\n\t\trunCmd = \"[gotelemetry local](https://golang.org/x/telemetry/cmd/gotelemetry)\"\n\t}\n\treturn fmt.Sprintf(format, runCmd)\n}\n\n// acquireLockFile attempts to \"acquire a lock\" for writing to path.\n//\n// This is achieved by creating an exclusive lock file at <path>.lock. Lock\n// files expire after a period, at which point acquireLockFile will remove and\n// recreate the lock file.\n//\n// acquireLockFile fails if path is in a directory that doesn't exist.\nfunc acquireLockFile(path string) (func(), bool, error) {\n\tlockpath := path + \".lock\"\n\tfi, err := os.Stat(lockpath)\n\tif err == nil {\n\t\tif time.Since(fi.ModTime()) > promptTimeout {\n\t\t\t_ = os.Remove(lockpath) // ignore error\n\t\t} else {\n\t\t\treturn nil, false, nil\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\treturn nil, false, fmt.Errorf(\"statting lockfile: %v\", err)\n\t}\n\n\tf, err := os.OpenFile(lockpath, os.O_CREATE|os.O_EXCL, 0666)\n\tif err != nil {\n\t\tif os.IsExist(err) {\n\t\t\treturn nil, false, nil\n\t\t}\n\t\treturn nil, false, fmt.Errorf(\"creating lockfile: %v\", err)\n\t}\n\tfi, err = f.Stat()\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\trelease := func() {\n\t\t_ = f.Close() // ignore error\n\t\tfi2, err := os.Stat(lockpath)\n\t\tif err == nil && os.SameFile(fi, fi2) {\n\t\t\t// Only clean up the lockfile if it's the same file we created.\n\t\t\t// Otherwise, our lock has expired and something else has the lock.\n\t\t\t//\n\t\t\t// There's a race here, in that the file could have changed since the\n\t\t\t// stat above; but given that we've already waited 24h this is extremely\n\t\t\t// unlikely, and acceptable.\n\t\t\t_ = os.Remove(lockpath)\n\t\t}\n\t}\n\treturn release, true, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/prompt_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"path/filepath\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\nfunc TestAcquireFileLock(t *testing.T) {\n\tname := filepath.Join(t.TempDir(), \"config.json\")\n\n\tconst concurrency = 100\n\tvar acquired int32\n\tvar releasers [concurrency]func()\n\tdefer func() {\n\t\tfor _, r := range releasers {\n\t\t\tif r != nil {\n\t\t\t\tr()\n\t\t\t}\n\t\t}\n\t}()\n\n\tvar wg sync.WaitGroup\n\tfor i := range releasers {\n\t\twg.Go(func() {\n\n\t\t\trelease, ok, err := acquireLockFile(name)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Acquire failed: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif ok {\n\t\t\t\tatomic.AddInt32(&acquired, 1)\n\t\t\t\treleasers[i] = release\n\t\t\t}\n\t\t})\n\t}\n\n\twg.Wait()\n\n\tif acquired != 1 {\n\t\tt.Errorf(\"Acquire succeeded %d times, expected exactly 1\", acquired)\n\t}\n}\n\nfunc TestReleaseAndAcquireFileLock(t *testing.T) {\n\tname := filepath.Join(t.TempDir(), \"config.json\")\n\n\tacquire := func() (func(), bool) {\n\t\tt.Helper()\n\t\trelease, ok, err := acquireLockFile(name)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\treturn release, ok\n\t}\n\n\trelease, ok := acquire()\n\tif !ok {\n\t\tt.Fatal(\"failed to Acquire\")\n\t}\n\tif release2, ok := acquire(); ok {\n\t\trelease()\n\t\trelease2()\n\t\tt.Fatalf(\"Acquire succeeded unexpectedly\")\n\t}\n\n\trelease()\n\trelease3, ok := acquire()\n\trelease3()\n\tif !ok {\n\t\tt.Fatalf(\"failed to Acquire\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/references.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/mod\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) References(ctx context.Context, params *protocol.ReferenceParams) (_ []protocol.Location, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"references\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.References\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Tmpl:\n\t\treturn template.References(ctx, snapshot, fh, params)\n\tcase file.Go:\n\t\treturn golang.References(ctx, snapshot, fh, params.Range, params.Context.IncludeDeclaration)\n\tcase file.Mod:\n\t\treturn mod.References(ctx, snapshot, fh, params)\n\t}\n\treturn nil, nil // empty result\n}\n"
  },
  {
    "path": "gopls/internal/server/rename.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) {\n\tcountRename.Inc()\n\tctx, done := event.Start(ctx, \"server.Rename\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif kind := snapshot.FileKind(fh); kind != file.Go {\n\t\treturn nil, fmt.Errorf(\"cannot rename in file of type %s\", kind)\n\t}\n\n\tchanges, err := golang.Rename(ctx, snapshot, fh, params.Range, params.NewName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn protocol.NewWorkspaceEdit(changes...), nil\n}\n\n// PrepareRename implements the textDocument/prepareRename handler. It may\n// return (nil, nil) if there is no rename at the cursor position, but it is\n// not desirable to display an error to the user.\n//\n// TODO(rfindley): why wouldn't we want to show an error to the user, if the\n// user initiated a rename request at the cursor?\nfunc (s *server) PrepareRename(ctx context.Context, params *protocol.PrepareRenameParams) (*protocol.PrepareRenamePlaceholder, error) {\n\tctx, done := event.Start(ctx, \"server.PrepareRename\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif kind := snapshot.FileKind(fh); kind != file.Go {\n\t\treturn nil, fmt.Errorf(\"cannot rename in file of type %s\", kind)\n\t}\n\n\t// Do not return errors here, as it adds clutter.\n\t// Returning a nil result means there is not a valid rename.\n\titem, usererr, err := golang.PrepareRename(ctx, snapshot, fh, params.Range)\n\tif err != nil {\n\t\t// Return usererr here rather than err, to avoid cluttering the UI with\n\t\t// internal error details.\n\t\treturn nil, usererr\n\t}\n\treturn &protocol.PrepareRenamePlaceholder{\n\t\tRange:       item.Range,\n\t\tPlaceholder: item.Text,\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/resolve.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n)\n\n// Ths file contains the code to mediate user dialogs in the client\n\n// The logical flow is as follows:\n// 1. Client sends 'textDocument/codeAction'\n//    gopls respond with one or more CodeActions, including one with kind either\n//    'refactor.rewrite.addTags' or 'refactor.rewrite.removeTags'\n// 2. Client sends 'codeAction/resolve' with the selected CodeActions\n//    gopls returns the same CodeAction\n// 3. Client sends 'workspace/executeCommand' to get the dialog form\n//    gopls responds with the form to display to the user\n// 4. Client sends 'command/resolve' with the filled out form\n//    gopls responds, with 'workspace/applyEdit' saying what to do\n// 5. Client return ApplyWorkspaceEditResult with applied = true\n// 6. Client sends a textDocument/didChange notification, with the edits applied (optional)\n\n// In vscode-go, because it is a standard LSP client,\n// cannot do step 4 as described. Instead\n// it calls \"workspace/executeCommand\" with command 'gopls.lsp'\n// and parameter.Method \"command/resolve\".\n//\n// ExecuteCommand() calls command.Dispatch() which calls LSP()\n// which calls protocol.ServerDispatchCall(\"command/resolve\")\n// which calls ResolveCommand. command.Dispatch() switches on param.Command and LSP() passes param.Method\n// to ServerDispatchCall\n\n// The neovim flow is simpler, as 'command/resolve' can be invoked directly.\n\nvar AddTagsForm = []protocol.FormField{\n\t{\n\t\tDescription: `comma-separated list of tags to add; e.g.. \"json,xml\"`,\n\t\tType:        protocol.FormFieldTypeString{Kind: \"string\"},\n\t\tDefault:     \"json\",\n\t},\n\t{\n\t\tDescription: `transform rule for added tags, e.g., \"camelcase' or 'snakecase\"`,\n\t\tType: protocol.FormFieldTypeEnum{\n\t\t\tKind: \"enum\",\n\t\t\tEntries: []protocol.FormEnumEntry{\n\t\t\t\t{\n\t\t\t\t\t// MyField -> myField\n\t\t\t\t\tValue:       \"camelcase\",\n\t\t\t\t\tDescription: \"camelcase\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// MyField -> my-field\n\t\t\t\t\tValue:       \"lispcase\",\n\t\t\t\t\tDescription: \"lispcase\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// MyField -> MyField\n\t\t\t\t\tValue:       \"pascalcase\",\n\t\t\t\t\tDescription: \"pascalcase\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// MyField -> My Field\n\t\t\t\t\tValue:       \"titlecase\",\n\t\t\t\t\tDescription: \"titlecase\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// MyField -> my_field\n\t\t\t\t\tValue:       \"snakecase\",\n\t\t\t\t\tDescription: \"snakecase\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// keep the existing field name\n\t\t\t\t\tValue:       \"keep\",\n\t\t\t\t\tDescription: \"keep\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tDefault: \"camelcase\",\n\t},\n}\n\nvar RemoveTagsForm = []protocol.FormField{\n\t{\n\t\tDescription: `comma-separated list of tags to remove; e.g., \"json,xml\"`,\n\t\tType:        protocol.FormFieldTypeString{Kind: \"string\"},\n\t\tDefault:     \"json\", // TODO(?): put the existing tags here?\n\t},\n}\n\n// ResolveComamnd is called indirectly from WorkspaceCommand(), explained above.\nfunc (s *server) ResolveCommand(ctx context.Context, param *protocol.ExecuteCommandParams) (*protocol.ExecuteCommandParams, error) {\n\tswitch param.Command {\n\tcase \"gopls.modify_tags\":\n\t\treturn resolveModifyTags(param)\n\t}\n\treturn nil, notImplemented(fmt.Sprintf(\"ResolveCommand(%s)\", param.Command))\n}\n\nfunc resolveModifyTags(param *protocol.ExecuteCommandParams) (*protocol.ExecuteCommandParams, error) {\n\tvar a0 command.ModifyTagsArgs\n\tif err := command.UnmarshalArgs(param.Arguments, &a0); err != nil {\n\t\treturn nil, err\n\t}\n\tswitch a0.Modification {\n\tcase \"add\":\n\t\tswitch len(param.FormAnswers) {\n\t\tcase 0: // first call, return the form\n\t\t\tparam.FormFields = AddTagsForm\n\t\t\treturn param, nil\n\t\tcase 2: // second call, process the form\n\t\t\tvar ok bool\n\t\t\tif a0.Add, ok = param.FormAnswers[0].(string); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid type of first value, want string: %v\", param.FormAnswers[0])\n\t\t\t}\n\n\t\t\tif slices.Contains(strings.Split(a0.Add, \",\"), \"\") {\n\t\t\t\t// TODO(pjw): instead filter AddTagsForm to remove empty tags and tags containing spaces\n\t\t\t\tform := slices.Clone(AddTagsForm)\n\t\t\t\tform[0].Error = \"input tags should not contain empty tag\"\n\t\t\t\tparam.FormFields = form\n\t\t\t\treturn param, nil\n\t\t\t}\n\n\t\t\tif a0.Transform, ok = param.FormAnswers[1].(string); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid type of second value, want string: %v\", param.FormAnswers[1])\n\t\t\t}\n\t\t\t// PJW: what happens when the user enters a bad value? (i think the client handles it)\n\n\t\t\traw, err := command.MarshalArgs(a0)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tparam.FormAnswers = nil\n\t\t\tparam.FormFields = nil\n\t\t\tparam.Arguments = raw\n\t\t\treturn param, nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"modify tags command expecting 1 value from client, got %v\", len(param.FormAnswers))\n\t\t}\n\tcase \"remove\":\n\t\tswitch len(param.FormAnswers) {\n\t\tcase 0: // first call, return the form\n\t\t\t// TODO? show the user the current list of tags?\n\t\t\tparam.FormFields = RemoveTagsForm\n\t\t\treturn param, nil\n\t\tcase 1: // second call, process the form\n\t\t\tvar ok bool\n\t\t\tif a0.Remove, ok = param.FormAnswers[0].(string); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid type of value, want string: %v\", param.FormAnswers[0])\n\t\t\t}\n\t\t\traw, err := command.MarshalArgs(a0)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tparam.FormAnswers = nil\n\t\t\tparam.FormFields = nil\n\t\t\tparam.Arguments = raw\n\t\t\treturn param, nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"modify tags command expecting 1 value from client, got %v\", len(param.FormAnswers))\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported modify tags operation: %s\", a0.Modification)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/selection_range.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/gopls/internal/cache/parsego\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// SelectionRange defines the textDocument/selectionRange feature,\n// which, given a list of positions within a file,\n// reports a linked list of enclosing syntactic blocks, innermost first.\n//\n// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_selectionRange.\n//\n// This feature can be used by a client to implement \"expand selection\" in a\n// language-aware fashion. Multiple input positions are supported to allow\n// for multiple cursors, and the entire path up to the whole document is\n// returned for each cursor to avoid multiple round-trips when the user is\n// likely to issue this command multiple times in quick succession.\nfunc (s *server) SelectionRange(ctx context.Context, params *protocol.SelectionRangeParams) ([]protocol.SelectionRange, error) {\n\tctx, done := event.Start(ctx, \"server.SelectionRange\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif kind := snapshot.FileKind(fh); kind != file.Go {\n\t\treturn nil, fmt.Errorf(\"SelectionRange not supported for file of type %s\", kind)\n\t}\n\n\tpgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresult := make([]protocol.SelectionRange, len(params.Positions))\n\tfor i, protocolPos := range params.Positions {\n\t\tpos, err := pgf.PositionPos(protocolPos)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tpath, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)\n\n\t\ttail := &result[i] // tail of the Parent linked list, built head first\n\n\t\tfor j, node := range path {\n\t\t\trng, err := pgf.NodeRange(node)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\t// Add node to tail.\n\t\t\tif j > 0 {\n\t\t\t\ttail.Parent = &protocol.SelectionRange{}\n\t\t\t\ttail = tail.Parent\n\t\t\t}\n\t\t\ttail.Range = rng\n\t\t}\n\t}\n\n\treturn result, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/semantic.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) SemanticTokensFull(ctx context.Context, params *protocol.SemanticTokensParams) (*protocol.SemanticTokens, error) {\n\treturn s.semanticTokens(ctx, params.TextDocument, nil)\n}\n\nfunc (s *server) SemanticTokensRange(ctx context.Context, params *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) {\n\treturn s.semanticTokens(ctx, params.TextDocument, &params.Range)\n}\n\nfunc (s *server) semanticTokens(ctx context.Context, td protocol.TextDocumentIdentifier, rng *protocol.Range) (*protocol.SemanticTokens, error) {\n\tctx, done := event.Start(ctx, \"server.semanticTokens\", label.URI.Of(td.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, td.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif snapshot.Options().SemanticTokens {\n\t\tswitch snapshot.FileKind(fh) {\n\t\tcase file.Tmpl:\n\t\t\treturn template.SemanticTokens(ctx, snapshot, fh.URI())\n\t\tcase file.Go:\n\t\t\treturn golang.SemanticTokens(ctx, snapshot, fh, rng)\n\t\t}\n\t}\n\n\t// Not enabled, or unsupported file type: return empty result.\n\t//\n\t// Returning an empty response is necessary to invalidate\n\t// semantic tokens in VS Code (and perhaps other editors).\n\t// Previously, we returned an error, but that had the side effect\n\t// of noisy \"semantictokens are disabled\" logs on every keystroke.\n\t//\n\t// We must return a non-nil Data slice for JSON serialization.\n\t// We do not return an empty field with \"omitempty\" set,\n\t// as it is not marked optional in the protocol (golang/go#67885).\n\treturn &protocol.SemanticTokens{Data: []uint32{}}, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/server.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package server defines gopls' implementation of the LSP server\n// interface, [protocol.Server]. Call [New] to create an instance.\npackage server\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"embed\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\tpaths \"path\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cache/metadata\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/golang/splitpkg\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// New creates an LSP server and binds it to handle incoming client\n// messages on the supplied stream.\nfunc New(session *cache.Session, client protocol.ClientCloser, options *settings.Options) protocol.Server {\n\tconst concurrentAnalyses = 1\n\t// If this assignment fails to compile after a protocol\n\t// upgrade, it means that one or more new methods need new\n\t// stub declarations in unimplemented.go.\n\treturn &server{\n\t\tdiagnostics:         make(map[protocol.DocumentURI]*fileDiagnostics),\n\t\twatchedGlobPatterns: nil, // empty\n\t\tchangedFiles:        make(map[protocol.DocumentURI]unit),\n\t\tsession:             session,\n\t\tclient:              client,\n\t\tdiagnosticsSema:     make(chan unit, concurrentAnalyses),\n\t\tprogress:            progress.NewTracker(client),\n\t\toptions:             options,\n\t\tviewsToDiagnose:     make(map[*cache.View]uint64),\n\t}\n}\n\ntype serverState int\n\nconst (\n\tserverCreated      = serverState(iota)\n\tserverInitializing // set once the server has received \"initialize\" request\n\tserverInitialized  // set once the server has received \"initialized\" request\n\tserverShutDown\n)\n\nfunc (s serverState) String() string {\n\tswitch s {\n\tcase serverCreated:\n\t\treturn \"created\"\n\tcase serverInitializing:\n\t\treturn \"initializing\"\n\tcase serverInitialized:\n\t\treturn \"initialized\"\n\tcase serverShutDown:\n\t\treturn \"shutDown\"\n\t}\n\treturn fmt.Sprintf(\"(unknown state: %d)\", int(s))\n}\n\n// server implements the [protocol.Server] interface.\n//\n// A server holds the server-side state of a single client/server\n// session or connection; it conceptually corresponds to a single call\n// to accept(2), not to listen(2) as the name \"server\" might suggest.\ntype server struct {\n\tclient protocol.ClientCloser\n\n\tstateMu sync.Mutex\n\tstate   serverState\n\t// notifications generated before serverInitialized\n\tnotifications []*protocol.ShowMessageParams\n\n\tsession *cache.Session\n\n\t// changedFiles tracks files for which there has been a textDocument/didChange.\n\tchangedFilesMu sync.Mutex\n\tchangedFiles   map[protocol.DocumentURI]unit\n\n\t// folders is only valid between initialize and initialized, and holds the\n\t// set of folders to build views for when we are ready.\n\t// Only the valid, non-empty 'file'-scheme URIs will be added.\n\tpendingFolders []protocol.WorkspaceFolder\n\n\t// watchedGlobPatterns is the set of glob patterns that we have requested\n\t// the client watch on disk. It will be updated as the set of directories\n\t// that the server should watch changes.\n\t// The map field may be reassigned but the map is immutable.\n\twatchedGlobPatternsMu  sync.Mutex\n\twatchedGlobPatterns    map[protocol.RelativePattern]unit\n\twatchRegistrationCount int\n\n\tdiagnosticsMu sync.Mutex // guards map and its values\n\tdiagnostics   map[protocol.DocumentURI]*fileDiagnostics\n\n\t// diagnosticsSema limits the concurrency of diagnostics runs, which can be\n\t// expensive.\n\tdiagnosticsSema chan unit\n\n\tprogress *progress.Tracker\n\n\t// When the workspace fails to load, we show its status through a progress\n\t// report with an error message.\n\tcriticalErrorStatusMu sync.Mutex\n\tcriticalErrorStatus   *progress.WorkDone\n\n\t// Track an ongoing CPU profile created with the StartProfile command and\n\t// terminated with the StopProfile command.\n\tongoingProfileMu sync.Mutex\n\tongoingProfile   *os.File // if non-nil, an ongoing profile is writing to this file\n\n\t// Track most recently requested options.\n\toptionsMu sync.Mutex\n\toptions   *settings.Options\n\n\t// Track the most recent completion results, for measuring completion efficacy\n\tefficacyMu      sync.Mutex\n\tefficacyURI     protocol.DocumentURI\n\tefficacyVersion int32\n\tefficacyItems   []protocol.CompletionItem\n\tefficacyPos     protocol.Position\n\n\t// Web server (for package documentation, etc) associated with this\n\t// LSP server. Opened on demand, and closed during LSP Shutdown.\n\twebOnce sync.Once\n\tweb     *web\n\twebErr  error\n\n\t// # Modification tracking and diagnostics\n\t//\n\t// For the purpose of tracking diagnostics, we need a monotonically\n\t// increasing clock. Each time a change occurs on the server, this clock is\n\t// incremented and the previous diagnostics pass is cancelled. When the\n\t// changed is processed, the Session (via DidModifyFiles) determines which\n\t// Views are affected by the change and these views are added to the\n\t// viewsToDiagnose set. Then the server calls diagnoseChangedViews\n\t// in a separate goroutine. Any Views that successfully complete their\n\t// diagnostics are removed from the viewsToDiagnose set, provided they haven't\n\t// been subsequently marked for re-diagnosis (as determined by the latest\n\t// modificationID referenced by viewsToDiagnose).\n\t//\n\t// In this way, we enforce eventual completeness of the diagnostic set: any\n\t// views requiring diagnosis are diagnosed, though possibly at a later point\n\t// in time. Notably, the logic in Session.DidModifyFiles to determines if a\n\t// view needs diagnosis considers whether any packages in the view were\n\t// invalidated. Consider the following sequence of snapshots for a given view\n\t// V:\n\t//\n\t//     C1    C2\n\t//  S1 -> S2 -> S3\n\t//\n\t// In this case, suppose that S1 was fully type checked, and then two changes\n\t// C1 and C2 occur in rapid succession, to a file in their package graph but\n\t// perhaps not enclosed by V's root.  In this case, the logic of\n\t// DidModifyFiles will detect that V needs to be reloaded following C1. In\n\t// order for our eventual consistency to be sound, we need to avoid the race\n\t// where S2 is being diagnosed, C2 arrives, and S3 is not detected as needing\n\t// diagnosis because the relevant package has not yet been computed in S2. To\n\t// achieve this, we only remove V from viewsToDiagnose if the diagnosis of S2\n\t// completes before C2 is processed, which we can confirm by checking\n\t// S2.BackgroundContext().\n\tmodificationMu        sync.Mutex\n\tcancelPrevDiagnostics func()\n\tviewsToDiagnose       map[*cache.View]uint64 // View -> modification at which it last required diagnosis\n\tlastModificationID    uint64                 // incrementing clock\n\n\trunGovulncheckInProgress atomic.Bool\n}\n\nfunc (s *server) WorkDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {\n\tctx, done := event.Start(ctx, \"server.WorkDoneProgressCancel\")\n\tdefer done()\n\n\treturn s.progress.Cancel(params.Token)\n}\n\n// web encapsulates the web server associated with an LSP server.\n// It is used for package documentation and other queries\n// where HTML makes more sense than a client editor UI.\n//\n// Example URL:\n//\n//\thttp://127.0.0.1:PORT/gopls/SECRET/...\n//\n// where\n//   - PORT is the random port number;\n//   - \"gopls\" helps the reader guess which program is the server;\n//   - SECRET is the 64-bit token; and\n//   - ... is the material part of the endpoint.\n//\n// Valid endpoints:\n//\n//\topen?file=%s&line=%d&col=%d        - open a file\n//\tpkg/PKGPATH?view=%s                - show doc for package in a given view\n//\tassembly?pkg=%s&view=%s&symbol=%s  - show assembly of specified func symbol\n//\tfreesymbols?file=%s&range=%d:%d:%d:%d:&view=%s - show report of free symbols\n//\tsplitpkg?pkg=%s&view=%s            - show \"split package\" HTML for given package/view\n//\tsplitpkg-json?pkg=%s&view=%s       - query component dependency graph for given package/view\n//\tsplitpkg-components?pkg=%s&view=%s - update component definitions for given package/view\ntype web struct {\n\tserver *http.Server\n\taddr   url.URL // \"http://127.0.0.1:PORT/gopls/SECRET\"\n\tmux    *http.ServeMux\n}\n\n// getWeb returns the web server associated with this\n// LSP server, creating it on first request.\nfunc (s *server) getWeb() (*web, error) {\n\ts.webOnce.Do(func() {\n\t\ts.web, s.webErr = s.initWeb()\n\t})\n\treturn s.web, s.webErr\n}\n\n// initWeb starts the local web server through which gopls\n// serves package documentation and suchlike.\n//\n// Clients should use [getWeb].\nfunc (s *server) initWeb() (*web, error) {\n\t// Use 64 random bits as the base of the URL namespace.\n\t// This ensures that URLs are unguessable to any local\n\t// processes that connect to the server, preventing\n\t// exfiltration of source code.\n\t//\n\t// (Note: depending on the LSP client, URLs that are passed to\n\t// it via showDocument and that result in the opening of a\n\t// browser tab may be transiently published through the argv\n\t// array of the open(1) or xdg-open(1) command.)\n\ttoken := make([]byte, 8)\n\tif _, err := rand.Read(token); err != nil {\n\t\treturn nil, fmt.Errorf(\"generating secret token: %v\", err)\n\t}\n\n\t// Pick any free port.\n\tlistener, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// -- There should be no early returns after this point. --\n\n\t// The root mux is not authenticated.\n\trootMux := http.NewServeMux()\n\trootMux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n\t\thttp.Error(w, \"request URI lacks authentication segment\", http.StatusUnauthorized)\n\t})\n\trootMux.HandleFunc(\"/favicon.ico\", func(w http.ResponseWriter, req *http.Request) {\n\t\thttp.Redirect(w, req, \"/assets/favicon.ico\", http.StatusMovedPermanently)\n\t})\n\trootMux.HandleFunc(\"/hang\", func(w http.ResponseWriter, req *http.Request) {\n\t\t// This endpoint hangs until cancelled.\n\t\t// It is used by JS to detect server disconnect.\n\t\t<-req.Context().Done()\n\t})\n\n\t// Serve assets (JS, PNG, etc) from embedded data,\n\t// except during local development.\n\tfs := fs.FS(assets)\n\t// fs = os.DirFS(\"/Users/adonovan/w/xtools/gopls/internal/server\") // uncomment during development\n\trootMux.Handle(\"/assets/\", http.FileServer(http.FS(fs)))\n\n\tsecret := \"/gopls/\" + base64.RawURLEncoding.EncodeToString(token)\n\twebMux := http.NewServeMux()\n\trootMux.Handle(secret+\"/\", withPanicHandler(http.StripPrefix(secret, webMux)))\n\n\twebServer := &http.Server{Addr: listener.Addr().String(), Handler: rootMux}\n\tgo func() {\n\t\t// This should run until LSP Shutdown, at which point\n\t\t// it will return ErrServerClosed. Any other error\n\t\t// means it failed to start.\n\t\tif err := webServer.Serve(listener); err != nil {\n\t\t\tif err != http.ErrServerClosed {\n\t\t\t\tlog.Print(err)\n\t\t\t}\n\t\t}\n\t}()\n\n\tweb := &web{\n\t\tserver: webServer,\n\t\taddr:   url.URL{Scheme: \"http\", Host: webServer.Addr, Path: secret},\n\t\tmux:    webMux,\n\t}\n\n\t// The /src handler allows the browser to request that the\n\t// LSP client editor open a file; see web.SrcURL.\n\twebMux.HandleFunc(\"/src\", func(w http.ResponseWriter, req *http.Request) {\n\t\tif err := req.ParseForm(); err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\turi := protocol.URIFromPath(req.Form.Get(\"file\"))\n\t\tline, _ := strconv.Atoi(req.Form.Get(\"line\")) // 1-based\n\t\tcol, _ := strconv.Atoi(req.Form.Get(\"col\"))   // 1-based UTF-8\n\t\tposn := protocol.Position{\n\t\t\tLine:      uint32(line - 1),\n\t\t\tCharacter: uint32(col - 1), // TODO(adonovan): map to UTF-16\n\t\t}\n\t\topenClientEditor(req.Context(), s.client, protocol.Location{\n\t\t\tURI:   uri,\n\t\t\tRange: protocol.Range{Start: posn, End: posn},\n\t\t}, s.Options())\n\t})\n\n\t// getSnapshot returns the snapshot for the view=... request parameter.\n\t// On success, the caller must call the snapshot's release function;\n\t//  callers may assume that req.ParseForm succeeded.\n\t// On failure, it reports an HTTP error.\n\tgetSnapshot := func(w http.ResponseWriter, req *http.Request) (*cache.Snapshot, func(), bool) {\n\t\tif err := req.ParseForm(); err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn nil, nil, false\n\t\t}\n\t\tviewID := req.Form.Get(\"view\")\n\t\tif viewID == \"\" {\n\t\t\thttp.Error(w, \"no view=... parameter\", http.StatusBadRequest)\n\t\t\treturn nil, nil, false\n\t\t}\n\t\tview, err := s.session.View(viewID)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusNotFound)\n\t\t\treturn nil, nil, false\n\t\t}\n\t\tsnapshot, release, err := view.Snapshot()\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn nil, nil, false\n\t\t}\n\t\treturn snapshot, release, true\n\t}\n\n\t// The /pkg/PATH&view=... handler shows package documentation for PATH.\n\twebMux.Handle(\"/pkg/\", http.StripPrefix(\"/pkg/\", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Find package by path.\n\t\tpkgPath := metadata.PackagePath(req.URL.Path)\n\t\tmps := snapshot.MetadataGraph().ForPackagePath[pkgPath]\n\t\tif len(mps) == 0 {\n\t\t\t// TODO(adonovan): what should we do for external test packages?\n\t\t\thttp.Error(w, \"package not found\", http.StatusNotFound)\n\t\t\treturn\n\t\t}\n\t\tfound := mps[0]\n\n\t\t// Type-check the package and render its documentation.\n\t\tpkgs, err := snapshot.TypeCheck(req.Context(), found.ID)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tcontent, err := golang.PackageDocHTML(snapshot.View().ID(), pkgs[0], web)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tw.Write(content)\n\t})))\n\n\t// The /freesymbols?file=...&range=...&view=... handler shows\n\t// free symbols referenced by the selection.\n\twebMux.HandleFunc(\"/freesymbols\", func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Get selection range and type-check.\n\t\tloc := protocol.Location{\n\t\t\tURI: protocol.DocumentURI(req.Form.Get(\"file\")),\n\t\t}\n\t\tif _, err := fmt.Sscanf(req.Form.Get(\"range\"), \"%d:%d:%d:%d\",\n\t\t\t&loc.Range.Start.Line,\n\t\t\t&loc.Range.Start.Character,\n\t\t\t&loc.Range.End.Line,\n\t\t\t&loc.Range.End.Character,\n\t\t); err != nil {\n\t\t\thttp.Error(w, \"invalid range\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tpkg, pgf, err := golang.NarrowestPackageForFile(req.Context(), snapshot, loc.URI)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tstart, end, err := pgf.RangePos(loc.Range)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\t// Produce report.\n\t\thtml := golang.FreeSymbolsHTML(snapshot.View().ID(), pkg, pgf, start, end, web)\n\t\tw.Write(html)\n\t})\n\n\t// The /assembly?pkg=...&view=...&symbol=... handler shows\n\t// the assembly of the current function.\n\twebMux.HandleFunc(\"/assembly\", func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Get other parameters.\n\t\tvar (\n\t\t\tpkgID  = metadata.PackageID(req.Form.Get(\"pkg\"))\n\t\t\tsymbol = req.Form.Get(\"symbol\")\n\t\t)\n\t\tif pkgID == \"\" || symbol == \"\" {\n\t\t\thttp.Error(w, \"/assembly requires pkg, symbol\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tctx := req.Context()\n\t\tpkgs, err := snapshot.TypeCheck(ctx, pkgID)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tpkg := pkgs[0]\n\n\t\t// Produce report.\n\t\tgolang.AssemblyHTML(ctx, snapshot, w, pkg, symbol, web)\n\t})\n\n\t// The /splitpkg?pkg=...&view=... handler shows\n\t// the \"split package\" tool (HTML) for the specified package/view.\n\twebMux.HandleFunc(\"/splitpkg\", func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Get metadata for pkg.\n\t\tpkgID := metadata.PackageID(req.Form.Get(\"pkg\"))\n\t\tif pkgID == \"\" {\n\t\t\thttp.Error(w, \"/splitpkg requires pkg\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tmp := snapshot.Metadata(pkgID)\n\t\tif mp == nil {\n\t\t\thttp.Error(w, \"no such package: \"+string(pkgID), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tw.Write(splitpkg.HTML(mp.PkgPath))\n\t})\n\n\t// The /splitpkg-json?pkg=...&view=... handler returns the symbol reference graph.\n\twebMux.HandleFunc(\"/splitpkg-json\", func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Get type information for pkg.\n\t\tpkgID := metadata.PackageID(req.Form.Get(\"pkg\"))\n\t\tif pkgID == \"\" {\n\t\t\thttp.Error(w, \"/splitpkg-json requires pkg\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tpkgs, err := snapshot.TypeCheck(req.Context(), pkgID)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tpkg := pkgs[0]\n\n\t\tdata, err := splitpkg.JSON(pkg, web)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tw.Write(data)\n\t})\n\n\t// The /splitpkg-components?pkg=...&view=... handler updates the components mapping.\n\t// for the specified package, causing it to be saved persistently, and\n\t// returned by future /splitpkg-json queries.\n\twebMux.HandleFunc(\"/splitpkg-components\", func(w http.ResponseWriter, req *http.Request) {\n\t\tsnapshot, release, ok := getSnapshot(w, req)\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tdefer release()\n\n\t\t// Get metadata for pkg.\n\t\tpkgID := metadata.PackageID(req.Form.Get(\"pkg\"))\n\t\tif pkgID == \"\" {\n\t\t\thttp.Error(w, \"/splitpkg-components requires pkg\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tmp := snapshot.Metadata(pkgID)\n\t\tif mp == nil {\n\t\t\thttp.Error(w, \"no such package: \"+string(pkgID), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tdata, err := io.ReadAll(req.Body)\n\t\tif err != nil {\n\t\t\tmsg := fmt.Sprintf(\"reading request body: %v\", err)\n\t\t\thttp.Error(w, msg, http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tif err := splitpkg.UpdateComponentsJSON(pkgID, data); err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t})\n\n\treturn web, nil\n}\n\n// assets holds our static web server content.\n//\n//go:embed assets/*\nvar assets embed.FS\n\n// SrcURL returns a /src URL that, when visited, causes the client\n// editor to open the specified file/line/column (in 1-based UTF-8\n// coordinates).\n//\n// (Rendering may generate hundreds of positions across files of many\n// packages, so don't convert to LSP coordinates yet: wait until the\n// URL is opened.)\nfunc (w *web) SrcURL(filename string, line, col8 int) protocol.URI {\n\tquery := fmt.Sprintf(\"file=%s&line=%d&col=%d\",\n\t\turl.QueryEscape(filename),\n\t\tline,\n\t\tcol8)\n\treturn w.url(\"src\", query, \"\")\n}\n\n// PkgURL returns a /pkg URL for the documentation of the specified package.\n// The optional fragment must be of the form \"Println\" or \"Buffer.WriteString\".\nfunc (w *web) PkgURL(viewID string, path golang.PackagePath, fragment string) protocol.URI {\n\tquery := \"view=\" + url.QueryEscape(viewID)\n\treturn w.url(\"pkg/\"+string(path), query, fragment)\n}\n\n// freesymbolsURL returns a /freesymbols URL for a report\n// on the free symbols referenced within the selection span (loc).\nfunc (w *web) freesymbolsURL(viewID string, loc protocol.Location) protocol.URI {\n\tquery := fmt.Sprintf(\"file=%s&range=%d:%d:%d:%d&view=%s\",\n\t\turl.QueryEscape(string(loc.URI)),\n\t\tloc.Range.Start.Line,\n\t\tloc.Range.Start.Character,\n\t\tloc.Range.End.Line,\n\t\tloc.Range.End.Character,\n\t\turl.QueryEscape(viewID))\n\treturn w.url(\"freesymbols\", query, \"\")\n}\n\n// assemblyURL returns the URL of an assembly listing of the specified function symbol.\nfunc (w *web) assemblyURL(viewID, packageID, symbol string) protocol.URI {\n\tquery := fmt.Sprintf(\"view=%s&pkg=%s&symbol=%s\",\n\t\turl.QueryEscape(viewID),\n\t\turl.QueryEscape(packageID),\n\t\turl.QueryEscape(symbol))\n\treturn w.url(\"assembly\", query, \"\")\n}\n\n// splitpkgURL returns the URL of the \"split package\" HTML page for the specified package.\nfunc (w *web) splitpkgURL(viewID, packageID string) protocol.URI {\n\tquery := fmt.Sprintf(\"view=%s&pkg=%s\",\n\t\turl.QueryEscape(viewID),\n\t\turl.QueryEscape(packageID))\n\treturn w.url(\"splitpkg\", query, \"\")\n}\n\n// url returns a URL by joining a relative path, an (encoded) query,\n// and an (unencoded) fragment onto the authenticated base URL of the\n// web server.\nfunc (w *web) url(path, query, fragment string) protocol.URI {\n\turl2 := w.addr\n\turl2.Path = paths.Join(url2.Path, strings.TrimPrefix(path, \"/\"))\n\turl2.RawQuery = query\n\turl2.Fragment = fragment\n\treturn protocol.URI(url2.String())\n}\n\n// withPanicHandler wraps an HTTP handler with telemetry-reporting of\n// panics that would otherwise be silently recovered by the net/http\n// root handler.\nfunc withPanicHandler(h http.Handler) http.HandlerFunc {\n\treturn func(w http.ResponseWriter, req *http.Request) {\n\t\tpanicked := true\n\t\tdefer func() {\n\t\t\tif panicked {\n\t\t\t\tbug.Report(\"panic in HTTP handler\")\n\t\t\t}\n\t\t}()\n\t\th.ServeHTTP(w, req)\n\t\tpanicked = false\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/signature_help.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) SignatureHelp(ctx context.Context, params *protocol.SignatureHelpParams) (*protocol.SignatureHelp, error) {\n\tctx, done := event.Start(ctx, \"server.SignatureHelp\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tif snapshot.FileKind(fh) != file.Go {\n\t\treturn nil, nil // empty result\n\t}\n\n\tinfo, err := golang.SignatureHelp(ctx, snapshot, fh, params.Range, params.Context)\n\tif err != nil {\n\t\t// TODO(rfindley): is this correct? Apparently, returning an error from\n\t\t// signatureHelp is distracting in some editors, though I haven't confirmed\n\t\t// that recently.\n\t\t//\n\t\t// It's unclear whether we still need to avoid returning this error result.\n\t\tevent.Error(ctx, \"signature help failed\", err, label.Position.Of(params.Range.Start), label.Position.Of(params.Range.End))\n\t\treturn nil, nil\n\t}\n\tif info == nil {\n\t\treturn nil, nil\n\t}\n\treturn &protocol.SignatureHelp{\n\t\tSignatures:      []protocol.SignatureInformation{*info},\n\t\tActiveSignature: 0,\n\t\tActiveParameter: info.ActiveParameter,\n\t}, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/symbols.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/template\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) DocumentSymbol(ctx context.Context, params *protocol.DocumentSymbolParams) ([]any, error) {\n\tctx, done := event.Start(ctx, \"server.DocumentSymbol\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\n\tvar docSymbols []protocol.DocumentSymbol\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Tmpl:\n\t\tdocSymbols, err = template.DocumentSymbols(snapshot, fh)\n\tcase file.Go:\n\t\tdocSymbols, err = golang.DocumentSymbols(ctx, snapshot, fh)\n\tdefault:\n\t\treturn nil, nil // empty result\n\t}\n\tif err != nil {\n\t\tevent.Error(ctx, \"DocumentSymbols failed\", err)\n\t\treturn nil, nil // empty result\n\t}\n\t// Convert the symbols to an interface array.\n\t// TODO: Remove this once the lsp deprecates SymbolInformation.\n\tsymbols := make([]any, len(docSymbols))\n\tfor i, s := range docSymbols {\n\t\tif snapshot.Options().HierarchicalDocumentSymbolSupport {\n\t\t\tsymbols[i] = s\n\t\t\tcontinue\n\t\t}\n\t\t// If the client does not support hierarchical document symbols, then\n\t\t// we need to be backwards compatible for now and return SymbolInformation.\n\t\tsymbols[i] = protocol.SymbolInformation{\n\t\t\tName:       s.Name,\n\t\t\tKind:       s.Kind,\n\t\t\tDeprecated: s.Deprecated,\n\t\t\tLocation:   params.TextDocument.URI.Location(s.Range),\n\t\t}\n\t}\n\treturn symbols, nil\n}\n"
  },
  {
    "path": "gopls/internal/server/text_synchronization.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/label\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// ModificationSource identifies the origin of a change.\ntype ModificationSource int\n\nconst (\n\t// FromDidOpen is from a didOpen notification.\n\tFromDidOpen = ModificationSource(iota)\n\n\t// FromDidChange is from a didChange notification.\n\tFromDidChange\n\n\t// FromDidChangeWatchedFiles is from didChangeWatchedFiles notification.\n\tFromDidChangeWatchedFiles\n\n\t// FromDidSave is from a didSave notification.\n\tFromDidSave\n\n\t// FromDidClose is from a didClose notification.\n\tFromDidClose\n\n\t// FromDidChangeConfiguration is from a didChangeConfiguration notification.\n\tFromDidChangeConfiguration\n\n\t// FromRegenerateCgo refers to file modifications caused by regenerating\n\t// the cgo sources for the workspace.\n\tFromRegenerateCgo\n\n\t// FromInitialWorkspaceLoad refers to the loading of all packages in the\n\t// workspace when the view is first created.\n\tFromInitialWorkspaceLoad\n\n\t// FromCheckUpgrades refers to state changes resulting from the CheckUpgrades\n\t// command, which queries module upgrades.\n\tFromCheckUpgrades\n\n\t// FromResetGoModDiagnostics refers to state changes resulting from the\n\t// ResetGoModDiagnostics command.\n\tFromResetGoModDiagnostics\n\n\t// FromToggleCompilerOptDetails refers to state changes resulting from toggling\n\t// a package's compiler optimization details flag.\n\tFromToggleCompilerOptDetails\n)\n\nfunc (m ModificationSource) String() string {\n\tswitch m {\n\tcase FromDidOpen:\n\t\treturn \"opened files\"\n\tcase FromDidChange:\n\t\treturn \"changed files\"\n\tcase FromDidChangeWatchedFiles:\n\t\treturn \"files changed on disk\"\n\tcase FromDidSave:\n\t\treturn \"saved files\"\n\tcase FromDidClose:\n\t\treturn \"close files\"\n\tcase FromRegenerateCgo:\n\t\treturn \"regenerate cgo\"\n\tcase FromInitialWorkspaceLoad:\n\t\treturn \"initial workspace load\"\n\tcase FromCheckUpgrades:\n\t\treturn \"from check upgrades\"\n\tcase FromResetGoModDiagnostics:\n\t\treturn \"from resetting go.mod diagnostics\"\n\tdefault:\n\t\treturn \"unknown file modification\"\n\t}\n}\n\nfunc (s *server) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {\n\tctx, done := event.Start(ctx, \"server.DidOpen\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\turi := params.TextDocument.URI\n\t// There may not be any matching view in the current session. If that's\n\t// the case, try creating a new view based on the opened file path.\n\t//\n\t// TODO(golang/go#57979): revisit creating a folder here. We should separate\n\t// the logic for managing folders from the logic for managing views. But it\n\t// does make sense to ensure at least one workspace folder the first time a\n\t// file is opened, and we can't do that inside didModifyFiles because we\n\t// don't want to request configuration while holding a lock.\n\tif len(s.session.Views()) == 0 {\n\t\tdir := uri.DirPath()\n\t\ts.addFolders(ctx, []protocol.WorkspaceFolder{{\n\t\t\tURI:  string(protocol.URIFromPath(dir)),\n\t\t\tName: filepath.Base(dir),\n\t\t}})\n\t}\n\treturn s.didModifyFiles(ctx, []file.Modification{{\n\t\tURI:        uri,\n\t\tAction:     file.Open,\n\t\tVersion:    params.TextDocument.Version,\n\t\tText:       []byte(params.TextDocument.Text),\n\t\tLanguageID: params.TextDocument.LanguageID,\n\t}}, FromDidOpen)\n}\n\nfunc (s *server) DidChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {\n\tctx, done := event.Start(ctx, \"server.DidChange\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\turi := params.TextDocument.URI\n\ttext, err := s.changedText(ctx, uri, params.ContentChanges)\n\tif err != nil {\n\t\treturn err\n\t}\n\tc := file.Modification{\n\t\tURI:     uri,\n\t\tAction:  file.Change,\n\t\tVersion: params.TextDocument.Version,\n\t\tText:    text,\n\t}\n\tif err := s.didModifyFiles(ctx, []file.Modification{c}, FromDidChange); err != nil {\n\t\treturn err\n\t}\n\treturn s.warnAboutModifyingGeneratedFiles(ctx, uri)\n}\n\n// warnAboutModifyingGeneratedFiles shows a warning if a user tries to edit a\n// generated file for the first time.\nfunc (s *server) warnAboutModifyingGeneratedFiles(ctx context.Context, uri protocol.DocumentURI) error {\n\ts.changedFilesMu.Lock()\n\t_, ok := s.changedFiles[uri]\n\tif !ok {\n\t\ts.changedFiles[uri] = struct{}{}\n\t}\n\ts.changedFilesMu.Unlock()\n\n\t// This file has already been edited before.\n\tif ok {\n\t\treturn nil\n\t}\n\n\t// Warn the user that they are editing a generated file, but\n\t// don't try to stop them: there are often good reasons to do\n\t// so, such as adding temporary logging, or evaluating changes\n\t// to the generated code without the trouble of modifying the\n\t// generator logic (see #73959).\n\tsnapshot, release, err := s.session.SnapshotOf(ctx, uri)\n\tif err != nil {\n\t\treturn err\n\t}\n\tisGenerated := golang.IsGenerated(ctx, snapshot, uri)\n\trelease()\n\tif isGenerated {\n\t\tmsg := fmt.Sprintf(\"Warning: editing %s, a generated file.\", uri.Base())\n\t\tshowMessage(ctx, s.client, protocol.Warning, msg)\n\t}\n\treturn nil\n}\n\nfunc (s *server) DidChangeWatchedFiles(ctx context.Context, params *protocol.DidChangeWatchedFilesParams) error {\n\tctx, done := event.Start(ctx, \"server.DidChangeWatchedFiles\")\n\tdefer done()\n\n\tvar modifications []file.Modification\n\tfor _, change := range params.Changes {\n\t\taction := changeTypeToFileAction(change.Type)\n\t\tmodifications = append(modifications, file.Modification{\n\t\t\tURI:    change.URI,\n\t\t\tAction: action,\n\t\t\tOnDisk: true,\n\t\t})\n\t}\n\treturn s.didModifyFiles(ctx, modifications, FromDidChangeWatchedFiles)\n}\n\nfunc (s *server) DidSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {\n\tctx, done := event.Start(ctx, \"server.DidSave\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\tc := file.Modification{\n\t\tURI:    params.TextDocument.URI,\n\t\tAction: file.Save,\n\t}\n\tif params.Text != nil {\n\t\tc.Text = []byte(*params.Text)\n\t}\n\treturn s.didModifyFiles(ctx, []file.Modification{c}, FromDidSave)\n}\n\nfunc (s *server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {\n\tctx, done := event.Start(ctx, \"server.DidClose\", label.URI.Of(params.TextDocument.URI))\n\tdefer done()\n\n\treturn s.didModifyFiles(ctx, []file.Modification{\n\t\t{\n\t\t\tURI:     params.TextDocument.URI,\n\t\t\tAction:  file.Close,\n\t\t\tVersion: -1,\n\t\t\tText:    nil,\n\t\t},\n\t}, FromDidClose)\n}\n\nfunc (s *server) didModifyFiles(ctx context.Context, modifications []file.Modification, cause ModificationSource) error {\n\t// wg guards two conditions:\n\t//  1. didModifyFiles is complete\n\t//  2. the goroutine diagnosing changes on behalf of didModifyFiles is\n\t//     complete, if it was started\n\t//\n\t// Both conditions must be satisfied for the purpose of testing: we don't\n\t// want to observe the completion of change processing until we have received\n\t// all diagnostics as well as all server->client notifications done on behalf\n\t// of this function.\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tdefer wg.Done()\n\n\tif s.Options().VerboseWorkDoneProgress {\n\t\twork := s.progress.Start(ctx, DiagnosticWorkTitle(cause), \"Calculating file diagnostics...\", nil, nil)\n\t\tgo func() {\n\t\t\twg.Wait()\n\t\t\twork.End(ctx, \"Done.\")\n\t\t}()\n\t}\n\n\ts.stateMu.Lock()\n\tif s.state >= serverShutDown {\n\t\t// This state check does not prevent races below, and exists only to\n\t\t// produce a better error message. The actual race to the cache should be\n\t\t// guarded by Session.viewMu.\n\t\ts.stateMu.Unlock()\n\t\treturn errors.New(\"server is shut down\")\n\t}\n\ts.stateMu.Unlock()\n\n\t// If the set of changes included directories, expand those directories\n\t// to their files.\n\tmodifications = s.session.ExpandModificationsToDirectories(ctx, modifications)\n\n\ts.handleModuleChanges(ctx, modifications, cause)\n\n\tviewsToDiagnose, err := s.session.DidModifyFiles(ctx, modifications)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// golang/go#50267: diagnostics should be re-sent after each change.\n\tfor _, mod := range modifications {\n\t\ts.mustPublishDiagnostics(mod.URI)\n\t}\n\n\tmodCtx, modID := s.needsDiagnosis(ctx, viewsToDiagnose)\n\n\twg.Go(func() {\n\t\ts.diagnoseChangedViews(modCtx, modID, viewsToDiagnose, cause)\n\t})\n\n\t// After any file modifications, we need to update our watched files,\n\t// in case something changed. Compute the new set of directories to watch,\n\t// and if it differs from the current set, send updated registrations.\n\treturn s.updateWatchedDirectories(ctx)\n}\n\nfunc (s *server) handleModuleChanges(ctx context.Context, modifications []file.Modification, cause ModificationSource) {\n\t// If any change in this batch is not a module metadata file, gopls will treat\n\t// the entire batch as a bulk operation (like a git branch switch). This is to\n\t// avoid doing expensive dependency checks for every module file in a\n\t// large change, which is redundant during a full workspace load.\n\t//\n\t// This also accounts for \"atomic saves\" in editors like Vim/Neovim,\n\t// which may surface as a Delete + Create sequence in the file watcher\n\t// rather than a single Save event.\n\tif cause == FromDidChangeWatchedFiles {\n\t\tfor _, m := range modifications {\n\t\t\tswitch m.URI.Base() {\n\t\t\tcase \"go.mod\", \"go.sum\", \"go.work\", \"go.work.sum\":\n\t\t\t\t// Module metadata file; continue checking.\n\t\t\tdefault:\n\t\t\t\t// Batch contains non-module files; skip dependency checks.\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\turis := make(map[protocol.DocumentURI]struct{})\n\tfor _, m := range modifications {\n\t\tif (m.URI.Base() == \"go.mod\" || m.URI.Base() == \"go.work\") && (m.Action == file.Create || m.Action == file.Save) {\n\t\t\turis[m.URI] = struct{}{}\n\t\t}\n\t}\n\n\tfor uri := range uris {\n\t\tgo s.checkDependencyChanges(ctx, uri)\n\t}\n}\n\n// needsDiagnosis records the given views as needing diagnosis, returning the\n// context and modification id to use for said diagnosis.\n//\n// Only the keys of viewsToDiagnose are used; the changed files are irrelevant.\nfunc (s *server) needsDiagnosis(ctx context.Context, viewsToDiagnose map[*cache.View][]protocol.DocumentURI) (context.Context, uint64) {\n\ts.modificationMu.Lock()\n\tdefer s.modificationMu.Unlock()\n\tif s.cancelPrevDiagnostics != nil {\n\t\ts.cancelPrevDiagnostics()\n\t}\n\tmodCtx := xcontext.Detach(ctx)\n\tmodCtx, s.cancelPrevDiagnostics = context.WithCancel(modCtx)\n\ts.lastModificationID++\n\tmodID := s.lastModificationID\n\n\tfor v := range viewsToDiagnose {\n\t\tif needs, ok := s.viewsToDiagnose[v]; !ok || needs < modID {\n\t\t\ts.viewsToDiagnose[v] = modID\n\t\t}\n\t}\n\treturn modCtx, modID\n}\n\n// DiagnosticWorkTitle returns the title of the diagnostic work resulting from a\n// file change originating from the given cause.\nfunc DiagnosticWorkTitle(cause ModificationSource) string {\n\treturn fmt.Sprintf(\"diagnosing %v\", cause)\n}\n\nfunc (s *server) changedText(ctx context.Context, uri protocol.DocumentURI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {\n\tif len(changes) == 0 {\n\t\treturn nil, fmt.Errorf(\"%w: no content changes provided\", jsonrpc2.ErrInternal)\n\t}\n\n\t// Check if the client sent the full content of the file.\n\t// We accept a full content change even if the server expected incremental changes.\n\tif len(changes) == 1 && changes[0].Range == nil && changes[0].RangeLength == nil {\n\t\tchangeFull.Inc()\n\t\treturn []byte(changes[0].Text), nil\n\t}\n\treturn s.applyIncrementalChanges(ctx, uri, changes)\n}\n\nfunc (s *server) applyIncrementalChanges(ctx context.Context, uri protocol.DocumentURI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {\n\tfh, err := s.session.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcontent, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: file not found (%v)\", jsonrpc2.ErrInternal, err)\n\t}\n\tfor i, change := range changes {\n\t\t// TODO(adonovan): refactor to use diff.Apply, which is robust w.r.t.\n\t\t// out-of-order or overlapping changes---and much more efficient.\n\n\t\t// Make sure to update mapper along with the content.\n\t\tm := protocol.NewMapper(uri, content)\n\t\tif change.Range == nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: unexpected nil range for change\", jsonrpc2.ErrInternal)\n\t\t}\n\t\tstart, end, err := m.RangeOffsets(*change.Range)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif end < start {\n\t\t\treturn nil, fmt.Errorf(\"%w: invalid range for content change\", jsonrpc2.ErrInternal)\n\t\t}\n\t\tvar buf bytes.Buffer\n\t\tbuf.Write(content[:start])\n\t\tbuf.WriteString(change.Text)\n\t\tbuf.Write(content[end:])\n\t\tcontent = buf.Bytes()\n\t\tif i == 0 { // only look at the first change if there are seversl\n\t\t\t// TODO(pjw): understand multi-change)\n\t\t\ts.checkEfficacy(fh.URI(), fh.Version(), change)\n\t\t}\n\t}\n\treturn content, nil\n}\n\n// increment counters if any of the completions look like there were used\nfunc (s *server) checkEfficacy(uri protocol.DocumentURI, version int32, change protocol.TextDocumentContentChangePartial) {\n\ts.efficacyMu.Lock()\n\tdefer s.efficacyMu.Unlock()\n\tif s.efficacyURI != uri {\n\t\treturn\n\t}\n\t// gopls increments the version, the test client does not\n\tif version != s.efficacyVersion && version != s.efficacyVersion+1 {\n\t\treturn\n\t}\n\t// does any change at pos match a proposed completion item?\n\tfor _, item := range s.efficacyItems {\n\t\tif item.TextEdit == nil {\n\t\t\tcontinue\n\t\t}\n\t\t// CompletionTextEdit may have both insert/replace mode ranges.\n\t\t// According to the LSP spec, if an `InsertReplaceEdit` is returned\n\t\t// the edit's insert range must be a prefix of the edit's replace range,\n\t\t// that means it must be contained and starting at the same position.\n\t\t// The efficacy computation uses only the start range, so it is not\n\t\t// affected by whether the client applied the suggestion in insert\n\t\t// or replace mode. Let's just use the replace mode that was the default\n\t\t// in gopls for a while.\n\t\tedit, err := protocol.SelectCompletionTextEdit(item, false)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif edit.Range.Start == change.Range.Start {\n\t\t\t// the change and the proposed completion start at the same\n\t\t\tif (change.RangeLength == nil || *change.RangeLength == 0) && len(change.Text) == 1 {\n\t\t\t\t// a single character added it does not count as a completion\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tix := strings.Index(edit.NewText, \"$\")\n\t\t\tif ix < 0 && strings.HasPrefix(change.Text, edit.NewText) {\n\t\t\t\t// not a snippet, suggested completion is a prefix of the change\n\t\t\t\tcomplUsed.Inc()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif ix > 1 && strings.HasPrefix(change.Text, edit.NewText[:ix]) {\n\t\t\t\t// a snippet, suggested completion up to $ marker is a prefix of the change\n\t\t\t\tcomplUsed.Inc()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\tcomplUnused.Inc()\n}\n\nfunc changeTypeToFileAction(ct protocol.FileChangeType) file.Action {\n\tswitch ct {\n\tcase protocol.Changed:\n\t\treturn file.Change\n\tcase protocol.Created:\n\t\treturn file.Create\n\tcase protocol.Deleted:\n\t\treturn file.Delete\n\t}\n\treturn file.UnknownAction\n}\n"
  },
  {
    "path": "gopls/internal/server/type_hierarchy.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) PrepareTypeHierarchy(ctx context.Context, params *protocol.TypeHierarchyPrepareParams) ([]protocol.TypeHierarchyItem, error) {\n\tctx, done := event.Start(ctx, \"server.PrepareTypeHierarchy\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.TextDocument.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.PrepareTypeHierarchy(ctx, snapshot, fh, params.Range)\n\t}\n\treturn nil, fmt.Errorf(\"unsupported file type: %v\", fh)\n}\n\nfunc (s *server) Subtypes(ctx context.Context, params *protocol.TypeHierarchySubtypesParams) ([]protocol.TypeHierarchyItem, error) {\n\tctx, done := event.Start(ctx, \"server.Subtypes\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.Item.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.Subtypes(ctx, snapshot, fh, params.Item)\n\t}\n\treturn nil, fmt.Errorf(\"unsupported file type: %v\", fh)\n}\n\nfunc (s *server) Supertypes(ctx context.Context, params *protocol.TypeHierarchySupertypesParams) ([]protocol.TypeHierarchyItem, error) {\n\tctx, done := event.Start(ctx, \"server.Supertypes\")\n\tdefer done()\n\n\tfh, snapshot, release, err := s.session.FileOf(ctx, params.Item.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer release()\n\tswitch snapshot.FileKind(fh) {\n\tcase file.Go:\n\t\treturn golang.Supertypes(ctx, snapshot, fh, params.Item)\n\t}\n\treturn nil, fmt.Errorf(\"unsupported file type: %v\", fh)\n}\n"
  },
  {
    "path": "gopls/internal/server/unimplemented.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\n// This file defines the LSP server methods that gopls does not currently implement.\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\nfunc (s *server) ColorPresentation(context.Context, *protocol.ColorPresentationParams) ([]protocol.ColorPresentation, error) {\n\treturn nil, notImplemented(\"ColorPresentation\")\n}\n\nfunc (s *server) Declaration(context.Context, *protocol.DeclarationParams) (*protocol.Or_textDocument_declaration, error) {\n\treturn nil, notImplemented(\"Declaration\")\n}\n\nfunc (s *server) DiagnosticWorkspace(context.Context, *protocol.WorkspaceDiagnosticParams) (*protocol.WorkspaceDiagnosticReport, error) {\n\treturn nil, notImplemented(\"DiagnosticWorkspace\")\n}\n\nfunc (s *server) DidChangeNotebookDocument(context.Context, *protocol.DidChangeNotebookDocumentParams) error {\n\treturn notImplemented(\"DidChangeNotebookDocument\")\n}\n\nfunc (s *server) DidCloseNotebookDocument(context.Context, *protocol.DidCloseNotebookDocumentParams) error {\n\treturn notImplemented(\"DidCloseNotebookDocument\")\n}\n\nfunc (s *server) DidDeleteFiles(context.Context, *protocol.DeleteFilesParams) error {\n\treturn notImplemented(\"DidDeleteFiles\")\n}\n\nfunc (s *server) DidOpenNotebookDocument(context.Context, *protocol.DidOpenNotebookDocumentParams) error {\n\treturn notImplemented(\"DidOpenNotebookDocument\")\n}\n\nfunc (s *server) DidRenameFiles(context.Context, *protocol.RenameFilesParams) error {\n\treturn notImplemented(\"DidRenameFiles\")\n}\n\nfunc (s *server) DidSaveNotebookDocument(context.Context, *protocol.DidSaveNotebookDocumentParams) error {\n\treturn notImplemented(\"DidSaveNotebookDocument\")\n}\n\nfunc (s *server) DocumentColor(context.Context, *protocol.DocumentColorParams) ([]protocol.ColorInformation, error) {\n\treturn nil, notImplemented(\"DocumentColor\")\n}\n\nfunc (s *server) InlineCompletion(context.Context, *protocol.InlineCompletionParams) (*protocol.Or_Result_textDocument_inlineCompletion, error) {\n\treturn nil, notImplemented(\"InlineCompletion\")\n}\n\nfunc (s *server) InlineValue(context.Context, *protocol.InlineValueParams) ([]protocol.InlineValue, error) {\n\treturn nil, notImplemented(\"InlineValue\")\n}\n\nfunc (s *server) InteractiveListEnum(context.Context, *protocol.InteractiveListEnumParams) ([]protocol.FormEnumEntry, error) {\n\treturn nil, notImplemented(\"InteractiveListEnum\")\n}\n\nfunc (s *server) LinkedEditingRange(context.Context, *protocol.LinkedEditingRangeParams) (*protocol.LinkedEditingRanges, error) {\n\treturn nil, notImplemented(\"LinkedEditingRange\")\n}\n\nfunc (s *server) Moniker(context.Context, *protocol.MonikerParams) ([]protocol.Moniker, error) {\n\treturn nil, notImplemented(\"Moniker\")\n}\n\nfunc (s *server) OnTypeFormatting(context.Context, *protocol.DocumentOnTypeFormattingParams) ([]protocol.TextEdit, error) {\n\treturn nil, notImplemented(\"OnTypeFormatting\")\n}\n\nfunc (s *server) Progress(context.Context, *protocol.ProgressParams) error {\n\treturn notImplemented(\"Progress\")\n}\n\nfunc (s *server) RangeFormatting(context.Context, *protocol.DocumentRangeFormattingParams) ([]protocol.TextEdit, error) {\n\treturn nil, notImplemented(\"RangeFormatting\")\n}\n\nfunc (s *server) RangesFormatting(context.Context, *protocol.DocumentRangesFormattingParams) ([]protocol.TextEdit, error) {\n\treturn nil, notImplemented(\"RangesFormatting\")\n}\n\nfunc (s *server) Resolve(context.Context, *protocol.InlayHint) (*protocol.InlayHint, error) {\n\treturn nil, notImplemented(\"Resolve\")\n}\n\nfunc (s *server) ResolveCodeLens(context.Context, *protocol.CodeLens) (*protocol.CodeLens, error) {\n\treturn nil, notImplemented(\"ResolveCodeLens\")\n}\n\nfunc (s *server) ResolveCompletionItem(context.Context, *protocol.CompletionItem) (*protocol.CompletionItem, error) {\n\treturn nil, notImplemented(\"ResolveCompletionItem\")\n}\n\nfunc (s *server) ResolveDocumentLink(context.Context, *protocol.DocumentLink) (*protocol.DocumentLink, error) {\n\treturn nil, notImplemented(\"ResolveDocumentLink\")\n}\n\nfunc (s *server) ResolveWorkspaceSymbol(context.Context, *protocol.WorkspaceSymbol) (*protocol.WorkspaceSymbol, error) {\n\treturn nil, notImplemented(\"ResolveWorkspaceSymbol\")\n}\n\nfunc (s *server) SemanticTokensFullDelta(context.Context, *protocol.SemanticTokensDeltaParams) (any, error) {\n\treturn nil, notImplemented(\"SemanticTokensFullDelta\")\n}\n\nfunc (s *server) SetTrace(context.Context, *protocol.SetTraceParams) error {\n\treturn notImplemented(\"SetTrace\")\n}\n\nfunc (s *server) WillCreateFiles(context.Context, *protocol.CreateFilesParams) (*protocol.WorkspaceEdit, error) {\n\treturn nil, notImplemented(\"WillCreateFiles\")\n}\n\nfunc (s *server) WillDeleteFiles(context.Context, *protocol.DeleteFilesParams) (*protocol.WorkspaceEdit, error) {\n\treturn nil, notImplemented(\"WillDeleteFiles\")\n}\n\nfunc (s *server) WillRenameFiles(context.Context, *protocol.RenameFilesParams) (*protocol.WorkspaceEdit, error) {\n\treturn nil, notImplemented(\"WillRenameFiles\")\n}\n\nfunc (s *server) WillSave(context.Context, *protocol.WillSaveTextDocumentParams) error {\n\treturn notImplemented(\"WillSave\")\n}\n\nfunc (s *server) WillSaveWaitUntil(context.Context, *protocol.WillSaveTextDocumentParams) ([]protocol.TextEdit, error) {\n\treturn nil, notImplemented(\"WillSaveWaitUntil\")\n}\n\nfunc (s *server) TextDocumentContent(context.Context, *protocol.TextDocumentContentParams) (*protocol.TextDocumentContentResult, error) {\n\treturn nil, notImplemented(\"TextDocumentContent\")\n}\n\nfunc notImplemented(method string) error {\n\treturn fmt.Errorf(\"%w: %q not yet implemented\", jsonrpc2.ErrMethodNotFound, method)\n}\n"
  },
  {
    "path": "gopls/internal/server/vulncheck_prompt.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\nconst (\n\t// dependencyHashKind is the kind for the dependency hash in the filecache.\n\tdependencyHashKind = \"dephash\"\n\tmaxVulnsToShow     = 10\n)\n\ntype vulncheckAction string\n\nconst (\n\tvulncheckActionYes    vulncheckAction = \"Yes\"\n\tvulncheckActionNo     vulncheckAction = \"No\"\n\tvulncheckActionAlways vulncheckAction = \"Always\"\n\tvulncheckActionNever  vulncheckAction = \"Never\"\n\tvulncheckActionEmpty  vulncheckAction = \"\"\n)\n\ntype vulnupgradeAction string\n\nconst (\n\tvulnupgradeActionUpgradeAll vulnupgradeAction = \"Upgrade All\"\n\tvulnupgradeActionIgnore     vulnupgradeAction = \"Ignore\"\n\tvulnupgradeActionEmpty      vulnupgradeAction = \"\"\n)\n\n// computeGoModHash computes the SHA256 hash of the go.mod file's dependencies.\n// It only considers the Require, Exclude, and Replace directives and ignores\n// other parts of the file.\nfunc computeGoModHash(file *modfile.File) (string, error) {\n\th := sha256.New()\n\tfor _, req := range file.Require {\n\t\tif _, err := h.Write([]byte(req.Mod.Path + \"\\x00\" + req.Mod.Version)); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\tfor _, exc := range file.Exclude {\n\t\tif _, err := h.Write([]byte(exc.Mod.Path + \"\\x00\" + exc.Mod.Version)); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\tfor _, rep := range file.Replace {\n\t\tif _, err := h.Write([]byte(rep.Old.Path + \"\\x00\" + rep.Old.Version + \"\\x00\" + rep.New.Path + \"\\x00\" + rep.New.Version)); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn hex.EncodeToString(h.Sum(nil)), nil\n}\n\n// computeGoWorkHash computes the SHA256 hash of the go.work file's dependencies.\n// It only considers the Use and Replace directives and ignores other parts of\n// the file.\nfunc computeGoWorkHash(file *modfile.WorkFile) (string, error) {\n\th := sha256.New()\n\tfor _, use := range file.Use {\n\t\tif _, err := h.Write([]byte(use.Path + \"\\x00\")); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\tfor _, rep := range file.Replace {\n\t\tif _, err := h.Write([]byte(rep.Old.Path + \"\\x00\" + rep.Old.Version + \"\\x00\" + rep.New.Path + \"\\x00\" + rep.New.Version)); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn hex.EncodeToString(h.Sum(nil)), nil\n}\n\nfunc getDependencyHashes(uri protocol.DocumentURI) (contentHash string, pathHash [32]byte, err error) {\n\tcontent, err := os.ReadFile(uri.Path())\n\tif err != nil {\n\t\treturn \"\", [32]byte{}, err\n\t}\n\tfilename := filepath.Base(uri.Path())\n\tswitch filename {\n\tcase \"go.mod\":\n\t\tmodFile, err := modfile.Parse(filename, content, nil)\n\t\tif err != nil {\n\t\t\treturn \"\", [32]byte{}, err\n\t\t}\n\t\tcontentHash, err = computeGoModHash(modFile)\n\t\tif err != nil {\n\t\t\treturn \"\", [32]byte{}, err\n\t\t}\n\tcase \"go.work\":\n\t\tworkFile, err := modfile.ParseWork(filename, content, nil)\n\t\tif err != nil {\n\t\t\treturn \"\", [32]byte{}, err\n\t\t}\n\t\tcontentHash, err = computeGoWorkHash(workFile)\n\t\tif err != nil {\n\t\t\treturn \"\", [32]byte{}, err\n\t\t}\n\tdefault:\n\t\treturn \"\", [32]byte{}, fmt.Errorf(\"unsupported file: %s\", filename)\n\t}\n\tpathHash = sha256.Sum256([]byte(uri.Path()))\n\treturn contentHash, pathHash, nil\n}\n\nfunc (s *server) checkDependencyChanges(ctx context.Context, uri protocol.DocumentURI) {\n\tif s.Options().Vulncheck != settings.ModeVulncheckPrompt {\n\t\treturn\n\t}\n\tctx, done := event.Start(ctx, \"server.checkDependencyChanges\")\n\tdefer done()\n\n\tnewHash, pathHash, err := getDependencyHashes(uri)\n\tif err != nil {\n\t\tevent.Error(ctx, \"getting dependency hashes failed\", err)\n\t\treturn\n\t}\n\n\toldHashBytes, err := filecache.Get(dependencyHashKind, pathHash)\n\tif err != nil && err != filecache.ErrNotFound {\n\t\tevent.Error(ctx, \"reading old dependency hash from filecache failed\", err)\n\t\treturn\n\t}\n\toldHash := string(oldHashBytes)\n\n\tif oldHash != newHash {\n\t\tfileLink := fmt.Sprintf(\"[%s](%s)\", uri.Path(), string(uri))\n\t\tgovulncheckLink := \"[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)\"\n\t\tmessage := fmt.Sprintf(\"Dependencies have changed in %s, would you like to run %s to check for vulnerabilities?\", fileLink, govulncheckLink)\n\n\t\taction, err := getVulncheckPreference()\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"reading vulncheck preference failed\", err)\n\t\t}\n\n\t\tswitch action {\n\t\tcase vulncheckActionAlways:\n\t\t\tgo s.handleVulncheck(ctx, uri)\n\t\tcase vulncheckActionNever:\n\t\t\treturn\n\t\tcase vulncheckActionEmpty:\n\t\t\t// no previous preference stored, prompt the user.\n\t\t\tfallthrough\n\t\tdefault:\n\t\t\t// invalid value, clear preference and prompt the user again.\n\t\t\tchoice, err := showMessageRequest(ctx, s.client, protocol.Info, message, string(vulncheckActionYes), string(vulncheckActionNo), string(vulncheckActionAlways), string(vulncheckActionNever))\n\t\t\tif err != nil {\n\t\t\t\tevent.Error(ctx, \"showing dependency changed notification failed\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\taction = vulncheckAction(choice)\n\t\t\trecordVulncheckAction(action)\n\t\t\tif action == vulncheckActionAlways || action == vulncheckActionNever {\n\t\t\t\tif err := setVulncheckPreference(action); err != nil {\n\t\t\t\t\tevent.Error(ctx, \"writing vulncheck preference failed\", err)\n\t\t\t\t\tshowMessage(ctx, s.client, protocol.Error, fmt.Sprintf(\"Failed to save vulncheck preference: %v\", err))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif action == vulncheckActionYes || action == vulncheckActionAlways {\n\t\t\t\tgo s.handleVulncheck(ctx, uri)\n\t\t\t}\n\t\t\tif action == vulncheckActionEmpty {\n\t\t\t\t// No user input gathered from prompt.\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif err := filecache.Set(dependencyHashKind, pathHash, []byte(newHash)); err != nil {\n\t\t\tevent.Error(ctx, \"writing new dependency hash to filecache failed\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc recordVulncheckAction(action vulncheckAction) {\n\tswitch action {\n\tcase vulncheckActionYes:\n\t\tcountVulncheckPromptYes.Inc()\n\tcase vulncheckActionNo:\n\t\tcountVulncheckPromptNo.Inc()\n\tcase vulncheckActionAlways:\n\t\tcountVulncheckPromptAlways.Inc()\n\tcase vulncheckActionNever:\n\t\tcountVulncheckPromptNever.Inc()\n\t}\n}\n\nfunc recordVulncheckupgradeAction(action vulnupgradeAction) {\n\tswitch action {\n\tcase vulnupgradeActionUpgradeAll:\n\t\tcountVulncheckUpgradeAll.Inc()\n\tcase vulnupgradeActionIgnore:\n\t\tcountVulncheckUpgradeIgnore.Inc()\n\t}\n}\n\nfunc (s *server) handleVulncheck(ctx context.Context, uri protocol.DocumentURI) {\n\t_, snapshot, release, err := s.session.FileOf(ctx, uri)\n\tif err != nil {\n\t\tevent.Error(ctx, \"getting file snapshot failed\", err)\n\t\treturn\n\t}\n\tdefer release()\n\tctx = xcontext.Detach(ctx)\n\n\twork := s.progress.Start(ctx, GoVulncheckCommandTitle, \"Running govulncheck...\", nil, nil)\n\tdefer work.End(ctx, \"Done.\")\n\tworkDoneWriter := progress.NewWorkDoneWriter(ctx, work)\n\tresult, err := s.runVulncheck(ctx, snapshot, uri, \"./...\", workDoneWriter)\n\tif err != nil {\n\t\tevent.Error(ctx, \"govulncheck failed\", err)\n\t\tshowMessage(ctx, s.client, protocol.Error, fmt.Sprintf(\"govulncheck failed: %v\", err))\n\t\treturn\n\t}\n\n\taffecting, stdLibVulns, modulesToUpgrade := computeModulesToUpgrade(result.Findings)\n\tnumStdLib := len(stdLibVulns)\n\tif len(affecting) == 0 && numStdLib == 0 {\n\t\tshowMessage(ctx, s.client, protocol.Info, \"No vulnerabilities found.\")\n\t\treturn\n\t}\n\n\taffectingOSVs := slices.Sorted(maps.Keys(affecting))\n\tsort.Strings(affectingOSVs)\n\n\tvar b strings.Builder\n\tfmt.Fprintf(&b, \"Found %d actionable vulnerabilities and %d standard library vulnerabilities affecting your dependencies:\\n\\n\", len(affectingOSVs), numStdLib)\n\n\tfor i, id := range affectingOSVs {\n\t\tif i >= maxVulnsToShow {\n\t\t\tbreak\n\t\t}\n\t\tcveURL := fmt.Sprintf(\"https://pkg.go.dev/vuln/%s\", id)\n\t\tif s.Options().LinkifyShowMessage {\n\t\t\tfmt.Fprintf(&b, \"Vulnerability #%d: [%s](%s)\", i+1, id, cveURL)\n\t\t} else {\n\t\t\tfmt.Fprintf(&b, \"Vulnerability #%d: %s (%s)\", i+1, id, cveURL)\n\t\t}\n\t\tif i < len(affectingOSVs)-1 && i < maxVulnsToShow-1 {\n\t\t\tb.WriteString(\", \")\n\t\t}\n\t}\n\tif len(affectingOSVs) > maxVulnsToShow {\n\t\tfmt.Fprintf(&b, \"\\n\\n...and %d more.\", len(affectingOSVs)-maxVulnsToShow)\n\t}\n\n\tif numStdLib > 0 {\n\t\tif b.Len() > 0 {\n\t\t\tb.WriteString(\"\\n\\n\")\n\t\t}\n\t\tb.WriteString(\"Upgrading your Go version may address vulnerabilities in the standard library.\")\n\t}\n\n\tactions := []string{string(vulnupgradeActionIgnore)}\n\tif len(modulesToUpgrade) > 0 {\n\t\tactions = append([]string{string(vulnupgradeActionUpgradeAll)}, actions...)\n\t}\n\n\taction, err := showMessageRequest(ctx, s.client, protocol.Warning, b.String(), actions...)\n\tif err != nil {\n\t\tevent.Error(ctx, \"vulncheck remediation failed\", err)\n\t\treturn\n\t}\n\tupgradeAction := vulnupgradeAction(action)\n\trecordVulncheckupgradeAction(upgradeAction)\n\n\tif upgradeAction == vulnupgradeActionUpgradeAll {\n\t\tif err := s.upgradeModules(ctx, snapshot, uri, modulesToUpgrade); err != nil {\n\t\t\tevent.Error(ctx, \"upgrading modules failed\", err)\n\t\t}\n\t}\n}\n\nfunc computeModulesToUpgrade(findings []*govulncheck.Finding) (affecting map[string]bool, stdLibVulns map[string]bool, modulesToUpgrade map[string]string) {\n\taffecting = make(map[string]bool)\n\tstdLibVulns = make(map[string]bool)\n\tmodulesToUpgrade = make(map[string]string)\n\n\tfor _, f := range findings {\n\t\tif len(f.Trace) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmod := f.Trace[0].Module\n\t\t// An empty module path or \"stdlib\" indicates a standard library package.\n\t\t// These vulnerabilities cannot be remediated via module upgrades and\n\t\t// instead require updating the Go toolchain.\n\t\tif mod == \"stdlib\" || mod == \"\" {\n\t\t\tstdLibVulns[f.OSV] = true\n\t\t} else {\n\t\t\taffecting[f.OSV] = true\n\t\t\tif f.FixedVersion != \"\" {\n\t\t\t\tcurrent, ok := modulesToUpgrade[mod]\n\t\t\t\tif !ok || current == \"latest\" || semver.Compare(f.FixedVersion, current) > 0 {\n\t\t\t\t\tmodulesToUpgrade[mod] = f.FixedVersion\n\t\t\t\t}\n\t\t\t} else if _, ok := modulesToUpgrade[mod]; !ok {\n\t\t\t\tmodulesToUpgrade[mod] = \"latest\"\n\t\t\t}\n\t\t}\n\t}\n\treturn affecting, stdLibVulns, modulesToUpgrade\n}\n\nfunc (s *server) upgradeModules(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, modulesToUpgrade map[string]string) error {\n\tif err := s.runGoGet(ctx, snapshot, uri, modulesToUpgrade); err != nil {\n\t\treturn err\n\t}\n\tif err := s.runGoModTidy(ctx, snapshot, uri); err != nil {\n\t\treturn err\n\t}\n\n\tvar (\n\t\tupgradedStrs []string\n\t\tupgrades     []string\n\t)\n\tfor module, version := range modulesToUpgrade {\n\t\tupgrades = append(upgrades, module+\"@\"+version)\n\t\tupgradedStrs = append(upgradedStrs, fmt.Sprintf(\"%s to %s\", module, version))\n\t}\n\tsort.Strings(upgradedStrs)\n\n\tmsg := fmt.Sprintf(\"Successfully upgraded vulnerable modules:\\n %s\", strings.Join(upgradedStrs, \",\\n \"))\n\tshowMessage(ctx, s.client, protocol.Info, msg)\n\tif hash, pathHash, err := getDependencyHashes(uri); err == nil {\n\t\tif err := filecache.Set(dependencyHashKind, pathHash, []byte(hash)); err != nil {\n\t\t\tevent.Error(ctx, \"failed to update dependency hash after upgrade\", err)\n\t\t}\n\t} else {\n\t\tevent.Error(ctx, \"failed to get dependency hash after upgrade\", err)\n\t}\n\treturn nil\n}\n\nfunc (s *server) runGoGet(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, modulesToUpgrade map[string]string) error {\n\twork := s.progress.Start(ctx, \"Upgrading Modules\", \"Running go get...\", nil, nil)\n\tdefer work.End(ctx, \"Done.\")\n\n\tvar upgrades []string\n\tfor module, version := range modulesToUpgrade {\n\t\tupgrades = append(upgrades, module+\"@\"+version)\n\t}\n\n\tif err := runGoCommand(ctx, snapshot, uri, \"get\", upgrades); err != nil {\n\t\tmsg := fmt.Sprintf(\"Failed to upgrade modules: %v\", err)\n\t\tshowMessage(ctx, s.client, protocol.Error, msg)\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (s *server) runGoModTidy(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) error {\n\twork := s.progress.Start(ctx, \"Upgrading Modules\", \"Running go mod tidy...\", nil, nil)\n\tdefer work.End(ctx, \"Done.\")\n\n\tif err := runGoCommand(ctx, snapshot, uri, \"mod\", []string{\"tidy\"}); err != nil {\n\t\tevent.Error(ctx, \"go mod tidy failed\", err)\n\t\tshowMessage(ctx, s.client, protocol.Error, fmt.Sprintf(\"go mod tidy failed: %v\", err))\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc runGoCommand(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, verb string, args []string) error {\n\tdir := uri.DirPath()\n\tinv, cleanup, err := snapshot.GoCommandInvocation(cache.NetworkOK, dir, verb, args)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cleanup()\n\tvar stdout, stderr bytes.Buffer\n\tif err := snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, &stdout, &stderr); err != nil {\n\t\treturn fmt.Errorf(\"go %s %s failed: %v\\n-- stdout --\\n%s\\n-- stderr --\\n%s\", verb, strings.Join(args, \" \"), err, stdout.String(), stderr.String())\n\t}\n\treturn nil\n}\n\ntype vulncheckConfig struct {\n\tVulncheckMode string `json:\"vulncheck\"`\n}\n\nfunc getVulncheckPreference() (vulncheckAction, error) {\n\tconfigDir, err := os.UserConfigDir()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tpath := filepath.Join(configDir, \"gopls\", \"vulncheck\", \"settings.json\")\n\tcontent, err := os.ReadFile(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn \"\", nil\n\t\t}\n\t\treturn \"\", err\n\t}\n\tvar config vulncheckConfig\n\tif err := json.Unmarshal(content, &config); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn vulncheckAction(config.VulncheckMode), nil\n}\n\nfunc setVulncheckPreference(preference vulncheckAction) error {\n\tconfigDir, err := os.UserConfigDir()\n\tif err != nil {\n\t\treturn err\n\t}\n\tgoplsDir := filepath.Join(configDir, \"gopls\", \"vulncheck\")\n\tif err := os.MkdirAll(goplsDir, 0755); err != nil {\n\t\treturn err\n\t}\n\tpath := filepath.Join(goplsDir, \"settings.json\")\n\tconfig := vulncheckConfig{VulncheckMode: string(preference)}\n\tcontent, err := json.Marshal(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.WriteFile(path, content, 0644)\n}\n"
  },
  {
    "path": "gopls/internal/server/vulncheck_prompt_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/progress\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestComputeGoModHash(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tcontent string\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname:    \"empty file\",\n\t\t\tcontent: \"module example.com\",\n\t\t\twant:    \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\", // sha256 of empty string\n\t\t},\n\t\t{\n\t\t\tname: \"with require\",\n\t\t\tcontent: `\n\t\t\tmodule example.com\n\t\t\trequire (\n\t\t\t\tgolang.org/x/tools v0.1.0\n\t\t\t\tgolang.org/x/vuln v0.2.0\n\t\t\t)\n\t\t\t`,\n\t\t\twant: func() string {\n\t\t\t\th := sha256.New()\n\t\t\t\th.Write([]byte(\"golang.org/x/tools\\x00v0.1.0\"))\n\t\t\t\th.Write([]byte(\"golang.org/x/vuln\\x00v0.2.0\"))\n\t\t\t\treturn hex.EncodeToString(h.Sum(nil))\n\t\t\t}(),\n\t\t},\n\t\t{\n\t\t\tname: \"with exclude\",\n\t\t\tcontent: `\n\t\t\tmodule example.com\n\t\t\texclude (\n\t\t\t\tgolang.org/x/tools v0.1.0\n\t\t\t)\n\t\t\t`,\n\t\t\twant: func() string {\n\t\t\t\th := sha256.New()\n\t\t\t\th.Write([]byte(\"golang.org/x/tools\\x00v0.1.0\"))\n\t\t\t\treturn hex.EncodeToString(h.Sum(nil))\n\t\t\t}(),\n\t\t},\n\t\t{\n\t\t\tname: \"with replace\",\n\t\t\tcontent: `\n\t\t\tmodule example.com\n\t\t\treplace (\n\t\t\t\tgolang.org/x/tools v0.1.0 => golang.org/x/tools v0.2.0\n\t\t\t)\n\t\t\t`,\n\t\t\twant: func() string {\n\t\t\t\th := sha256.New()\n\t\t\t\th.Write([]byte(\"golang.org/x/tools\\x00v0.1.0\\x00golang.org/x/tools\\x00v0.2.0\"))\n\t\t\t\treturn hex.EncodeToString(h.Sum(nil))\n\t\t\t}(),\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tmodFile, err := modfile.Parse(\"go.mod\", []byte(tt.content), nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tgot, err := computeGoModHash(modFile)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"computeGoModHash() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"computeGoModHash() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestComputeGoWorkHash(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tcontent string\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname:    \"empty file\",\n\t\t\tcontent: \"go 1.25\",\n\t\t\twant:    \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\", // sha256 of empty string\n\t\t},\n\t\t{\n\t\t\tname: \"with use\",\n\t\t\tcontent: `\n\t\t\tgo 1.25\n\t\t\tuse (\n\t\t\t\t./foo\n\t\t\t\t./bar\n\t\t\t)\n\t\t\t`,\n\t\t\twant: func() string {\n\t\t\t\th := sha256.New()\n\t\t\t\th.Write([]byte(\"./foo\\x00\"))\n\t\t\t\th.Write([]byte(\"./bar\\x00\"))\n\t\t\t\treturn hex.EncodeToString(h.Sum(nil))\n\t\t\t}(),\n\t\t},\n\t\t{\n\t\t\tname: \"with replace\",\n\t\t\tcontent: `\n\t\t\tgo 1.25\n\t\t\treplace golang.org/x/tools v0.1.0 => ./tools\n\t\t\t`,\n\t\t\twant: func() string {\n\t\t\t\th := sha256.New()\n\t\t\t\th.Write([]byte(\"golang.org/x/tools\\x00v0.1.0\\x00./tools\\x00\"))\n\t\t\t\treturn hex.EncodeToString(h.Sum(nil))\n\t\t\t}(),\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tworkFile, err := modfile.ParseWork(\"go.work\", []byte(tt.content), nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tgot, err := computeGoWorkHash(workFile)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"computeGoWorkHash() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"computeGoWorkHash() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype mockClient struct {\n\tprotocol.Client\n\tshowMessageRequest func(context.Context, *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error)\n}\n\nfunc (c *mockClient) ShowMessageRequest(ctx context.Context, params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {\n\tif c.showMessageRequest != nil {\n\t\treturn c.showMessageRequest(ctx, params)\n\t}\n\treturn nil, nil\n}\n\nfunc (c *mockClient) ShowMessage(ctx context.Context, params *protocol.ShowMessageParams) error {\n\treturn nil\n}\n\nfunc (c *mockClient) Close() error {\n\treturn nil\n}\n\nfunc TestCheckDependencyChanges(t *testing.T) {\n\ttestenv.NeedsExec(t)\n\tconst (\n\t\tyes    = \"Yes\"\n\t\tno     = \"No\"\n\t\talways = \"Always\"\n\t\tnever  = \"Never\"\n\t)\n\n\ttests := []struct {\n\t\tname            string\n\t\tfilename        string\n\t\tvulncheckMode   settings.VulncheckMode\n\t\toldContent      string\n\t\tnewContent      string\n\t\tuserAction      string\n\t\twantPrompt      bool\n\t\twantHashUpdated bool\n\t}{\n\t\t{\n\t\t\tname:          \"go.mod: vulncheck disabled\",\n\t\t\tfilename:      \"go.mod\",\n\t\t\tvulncheckMode: settings.ModeVulncheckOff,\n\t\t\toldContent:    \"module example.com\",\n\t\t\tnewContent: `\n\t\t\tmodule example.com\n\t\t\trequire golang.org/x/tools v0.1.0\n\t\t\t`,\n\t\t\twantPrompt: false,\n\t\t},\n\t\t{\n\t\t\tname:          \"go.mod: no changes\",\n\t\t\tfilename:      \"go.mod\",\n\t\t\tvulncheckMode: settings.ModeVulncheckPrompt,\n\t\t\toldContent:    \"module example.com\",\n\t\t\tnewContent:    \"module example.com\",\n\t\t\twantPrompt:    false,\n\t\t},\n\t\t{\n\t\t\tname:          \"go.mod: user says yes\",\n\t\t\tfilename:      \"go.mod\",\n\t\t\tvulncheckMode: settings.ModeVulncheckPrompt,\n\t\t\toldContent:    \"module example.com\",\n\t\t\tnewContent: `\n\t\t\tmodule example.com\n\t\t\trequire golang.org/x/tools v0.1.0\n\t\t\t`,\n\t\t\tuserAction:      yes,\n\t\t\twantPrompt:      true,\n\t\t\twantHashUpdated: true,\n\t\t},\n\t\t{\n\t\t\tname:          \"go.work: user says yes\",\n\t\t\tfilename:      \"go.work\",\n\t\t\tvulncheckMode: settings.ModeVulncheckPrompt,\n\t\t\toldContent:    \"go 1.25\",\n\t\t\tnewContent: `\n\t\t\tgo 1.25\n\t\t\tuse ./foo\n\t\t\t`,\n\t\t\tuserAction:      yes,\n\t\t\twantPrompt:      true,\n\t\t\twantHashUpdated: true,\n\t\t},\n\t\t{\n\t\t\tname:          \"go.work: no changes\",\n\t\t\tfilename:      \"go.work\",\n\t\t\tvulncheckMode: settings.ModeVulncheckPrompt,\n\t\t\toldContent:    \"go 1.25\\nuse ./foo\",\n\t\t\tnewContent:    \"go 1.25\\nuse ./foo\",\n\t\t\twantPrompt:    false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Cleanup(func() {\n\t\t\t\tconfigDir, err := os.UserConfigDir()\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"os.UserConfigDir() failed: %v\", err)\n\t\t\t\t}\n\t\t\t\tif err := os.RemoveAll(filepath.Join(configDir, \"gopls\")); err != nil && !os.IsNotExist(err) {\n\t\t\t\t\tt.Fatalf(\"failed to clear user config: %v\", err)\n\t\t\t\t}\n\t\t\t})\n\t\t\tt.Setenv(\"HOME\", t.TempDir())\n\t\t\tctx := context.Background()\n\t\t\tvar promptShown bool\n\t\t\tclient := &mockClient{\n\t\t\t\tshowMessageRequest: func(ctx context.Context, params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {\n\t\t\t\t\tpromptShown = true\n\t\t\t\t\tif tt.userAction == \"\" {\n\t\t\t\t\t\treturn nil, nil\n\t\t\t\t\t}\n\t\t\t\t\treturn &protocol.MessageActionItem{Title: tt.userAction}, nil\n\t\t\t\t},\n\t\t\t}\n\t\t\ts := &server{\n\t\t\t\tclient:   client,\n\t\t\t\tsession:  cache.NewSession(ctx, cache.New(nil)),\n\t\t\t\tprogress: progress.NewTracker(client),\n\t\t\t\toptions: &settings.Options{\n\t\t\t\t\tUserOptions: settings.UserOptions{\n\t\t\t\t\t\tUIOptions: settings.UIOptions{\n\t\t\t\t\t\t\tDiagnosticOptions: settings.DiagnosticOptions{\n\t\t\t\t\t\t\t\tVulncheck: tt.vulncheckMode,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tdir := t.TempDir()\n\t\t\tfilePath := filepath.Join(dir, tt.filename)\n\t\t\tif err := os.WriteFile(filePath, []byte(tt.oldContent), 0644); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\turi := protocol.URIFromPath(filePath)\n\n\t\t\t// Set the initial hash in the cache.\n\t\t\toldHash, _, err := getDependencyHashes(uri)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tpathHash := sha256.Sum256([]byte(uri.Path()))\n\t\t\tif err := filecache.Set(dependencyHashKind, pathHash, []byte(oldHash)); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Simulate the file change.\n\t\t\tif err := os.WriteFile(filePath, []byte(tt.newContent), 0644); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\ts.checkDependencyChanges(ctx, uri)\n\n\t\t\tif promptShown != tt.wantPrompt {\n\t\t\t\tt.Errorf(\"promptShown = %v, want %v\", promptShown, tt.wantPrompt)\n\t\t\t}\n\n\t\t\t// Check if the hash was updated.\n\t\t\tnewHash, _, err := getDependencyHashes(uri)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tcachedHashBytes, err := filecache.Get(dependencyHashKind, pathHash)\n\t\t\tif err != nil && err != filecache.ErrNotFound {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tcachedHash := string(cachedHashBytes)\n\n\t\t\tif tt.wantHashUpdated {\n\t\t\t\tif cachedHash != newHash {\n\t\t\t\t\tt.Errorf(\"hash was not updated in cache\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif cachedHash == newHash && oldHash != newHash {\n\t\t\t\t\tt.Errorf(\"hash was updated in cache, but should not have been\")\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestVulncheckPreference(t *testing.T) {\n\tif runtime.GOARCH == \"wasm\" {\n\t\tt.Skip(\"test not supported in wasm\")\n\t}\n\tt.Cleanup(func() {\n\t\tconfigDir, err := os.UserConfigDir()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"os.UserConfigDir() failed: %v\", err)\n\t\t}\n\t\tif err := os.RemoveAll(filepath.Join(configDir, \"gopls\")); err != nil && !os.IsNotExist(err) {\n\t\t\tt.Fatalf(\"failed to clear user config: %v\", err)\n\t\t}\n\t})\n\tt.Setenv(\"HOME\", t.TempDir())\n\n\tpref, err := getVulncheckPreference()\n\tif err != nil {\n\t\tt.Fatalf(\"getVulncheckPreference() failed: %v\", err)\n\t}\n\tif pref != \"\" {\n\t\tt.Errorf(\"got %q, want empty string\", pref)\n\t}\n\n\twant := vulncheckActionAlways\n\tif err := setVulncheckPreference(want); err != nil {\n\t\tt.Fatalf(\"setVulncheckPreference() failed: %v\", err)\n\t}\n\n\tgot, err := getVulncheckPreference()\n\tif err != nil {\n\t\tt.Fatalf(\"getVulncheckPreference() failed: %v\", err)\n\t}\n\n\tif got != want {\n\t\tt.Errorf(\"got %q, want %q\", got, want)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/server/workspace.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/golang/completion\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {\n\tfor _, folder := range params.Event.Removed {\n\t\tif !strings.HasPrefix(folder.URI, \"file://\") {\n\t\t\t// Some clients that support virtual file systems may send workspace change messages\n\t\t\t// about workspace folders in the virtual file systems. addFolders must not add\n\t\t\t// those folders, so they don't need to be removed either.\n\t\t\tcontinue\n\t\t}\n\t\tdir, err := protocol.ParseDocumentURI(folder.URI)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid folder %q: %v\", folder.URI, err)\n\t\t}\n\t\tif !s.session.RemoveView(ctx, dir) {\n\t\t\treturn fmt.Errorf(\"view %q for %v not found\", folder.Name, folder.URI)\n\t\t}\n\t}\n\ts.addFolders(ctx, params.Event.Added)\n\treturn nil\n}\n\n// addView returns a Snapshot and a release function that must be\n// called when it is no longer needed.\nfunc (s *server) addView(ctx context.Context, name string, dir protocol.DocumentURI) (*cache.Snapshot, func(), error) {\n\ts.stateMu.Lock()\n\tstate := s.state\n\ts.stateMu.Unlock()\n\tif state < serverInitialized {\n\t\treturn nil, nil, fmt.Errorf(\"addView called before server initialized\")\n\t}\n\topts, err := s.fetchFolderOptions(ctx, dir)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tfolder, err := s.newFolder(ctx, dir, name, opts)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\t_, snapshot, release, err := s.session.NewView(ctx, folder)\n\treturn snapshot, release, err\n}\n\nfunc (s *server) DidChangeConfiguration(ctx context.Context, _ *protocol.DidChangeConfigurationParams) error {\n\tctx, done := event.Start(ctx, \"server.DidChangeConfiguration\")\n\tdefer done()\n\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tdefer wg.Done()\n\tif s.Options().VerboseWorkDoneProgress {\n\t\twork := s.progress.Start(ctx, DiagnosticWorkTitle(FromDidChangeConfiguration), \"Calculating diagnostics...\", nil, nil)\n\t\tgo func() {\n\t\t\twg.Wait()\n\t\t\twork.End(ctx, \"Done.\")\n\t\t}()\n\t}\n\n\t// Apply any changes to the session-level settings.\n\toptions, err := s.fetchFolderOptions(ctx, \"\")\n\tif err != nil {\n\t\treturn err\n\t}\n\ts.SetOptions(options)\n\n\t// Collect options for all workspace folders.\n\t// If none have changed, this is a no op.\n\tfolderOpts := make(map[protocol.DocumentURI]*settings.Options)\n\tchanged := false\n\t// The set of views is implicitly guarded by the fact that gopls processes\n\t// didChange notifications synchronously.\n\t//\n\t// TODO(rfindley): investigate this assumption: perhaps we should hold viewMu\n\t// here.\n\tviews := s.session.Views()\n\tfor _, view := range views {\n\t\tfolder := view.Folder()\n\t\tif folderOpts[folder.Dir] != nil {\n\t\t\tcontinue\n\t\t}\n\t\topts, err := s.fetchFolderOptions(ctx, folder.Dir)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif !reflect.DeepEqual(folder.Options, opts) {\n\t\t\tchanged = true\n\t\t}\n\t\tfolderOpts[folder.Dir] = opts\n\t}\n\tif !changed {\n\t\treturn nil\n\t}\n\n\tvar newFolders []*cache.Folder\n\tfor _, view := range views {\n\t\tfolder := view.Folder()\n\t\topts := folderOpts[folder.Dir]\n\t\tnewFolder, err := s.newFolder(ctx, folder.Dir, folder.Name, opts)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tnewFolders = append(newFolders, newFolder)\n\t}\n\ts.session.UpdateFolders(ctx, newFolders) // ignore error\n\n\t// The view set may have been updated above.\n\tviewsToDiagnose := make(map[*cache.View][]protocol.DocumentURI)\n\tfor _, view := range s.session.Views() {\n\t\tviewsToDiagnose[view] = nil\n\t}\n\n\tmodCtx, modID := s.needsDiagnosis(ctx, viewsToDiagnose)\n\twg.Go(func() {\n\t\ts.diagnoseChangedViews(modCtx, modID, viewsToDiagnose, FromDidChangeConfiguration)\n\t})\n\n\t// An options change may have affected the detected Go version.\n\ts.checkViewGoVersions()\n\n\tif options.MaxFileCacheBytes > 0 {\n\t\tfilecache.SetBudget(options.MaxFileCacheBytes)\n\t}\n\n\treturn nil\n}\n\nfunc (s *server) DidCreateFiles(ctx context.Context, params *protocol.CreateFilesParams) error {\n\tctx, done := event.Start(ctx, \"server.DidCreateFiles\")\n\tdefer done()\n\n\tvar allChanges []protocol.DocumentChange\n\tfor _, createdFile := range params.Files {\n\t\turi := protocol.DocumentURI(createdFile.URI)\n\t\tfh, snapshot, release, err := s.session.FileOf(ctx, uri)\n\t\tif err != nil {\n\t\t\tevent.Error(ctx, \"fail to call fileOf\", err)\n\t\t\tcontinue\n\t\t}\n\t\tdefer release()\n\n\t\tswitch snapshot.FileKind(fh) {\n\t\tcase file.Go:\n\t\t\tchange, err := completion.NewFile(ctx, snapshot, fh)\n\t\t\tif err != nil {\n\t\t\t\t// any error, including \"it's not a new file\"\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif change != nil {\n\t\t\t\tallChanges = append(allChanges, *change)\n\t\t\t}\n\t\tdefault:\n\t\t}\n\t}\n\n\treturn applyChanges(ctx, s.client, allChanges)\n}\n"
  },
  {
    "path": "gopls/internal/server/workspace_symbol.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage server\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/golang\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc (s *server) Symbol(ctx context.Context, params *protocol.WorkspaceSymbolParams) (_ []protocol.SymbolInformation, rerr error) {\n\trecordLatency := telemetry.StartLatencyTimer(\"symbol\")\n\tdefer func() {\n\t\trecordLatency(ctx, rerr)\n\t}()\n\n\tctx, done := event.Start(ctx, \"server.Symbol\")\n\tdefer done()\n\n\tviews := s.session.Views()\n\tmatcher := s.Options().SymbolMatcher\n\tstyle := s.Options().SymbolStyle\n\n\tvar snapshots []*cache.Snapshot\n\tfor _, v := range views {\n\t\tsnapshot, release, err := v.Snapshot()\n\t\tif err != nil {\n\t\t\tcontinue // snapshot is shutting down\n\t\t}\n\t\t// If err is non-nil, the snapshot is shutting down. Skip it.\n\t\tdefer release()\n\t\tsnapshots = append(snapshots, snapshot)\n\t}\n\treturn golang.WorkspaceSymbols(ctx, matcher, style, snapshots, params.Query)\n}\n"
  },
  {
    "path": "gopls/internal/settings/analysis.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings\n\nimport (\n\t\"log\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/appends\"\n\t\"golang.org/x/tools/go/analysis/passes/asmdecl\"\n\t\"golang.org/x/tools/go/analysis/passes/assign\"\n\t\"golang.org/x/tools/go/analysis/passes/atomic\"\n\t\"golang.org/x/tools/go/analysis/passes/atomicalign\"\n\t\"golang.org/x/tools/go/analysis/passes/bools\"\n\t\"golang.org/x/tools/go/analysis/passes/buildtag\"\n\t\"golang.org/x/tools/go/analysis/passes/cgocall\"\n\t\"golang.org/x/tools/go/analysis/passes/composite\"\n\t\"golang.org/x/tools/go/analysis/passes/copylock\"\n\t\"golang.org/x/tools/go/analysis/passes/deepequalerrors\"\n\t\"golang.org/x/tools/go/analysis/passes/defers\"\n\t\"golang.org/x/tools/go/analysis/passes/directive\"\n\t\"golang.org/x/tools/go/analysis/passes/errorsas\"\n\t\"golang.org/x/tools/go/analysis/passes/fieldalignment\"\n\t\"golang.org/x/tools/go/analysis/passes/framepointer\"\n\t\"golang.org/x/tools/go/analysis/passes/hostport\"\n\t\"golang.org/x/tools/go/analysis/passes/httpresponse\"\n\t\"golang.org/x/tools/go/analysis/passes/ifaceassert\"\n\t\"golang.org/x/tools/go/analysis/passes/inline\"\n\t\"golang.org/x/tools/go/analysis/passes/loopclosure\"\n\t\"golang.org/x/tools/go/analysis/passes/lostcancel\"\n\t\"golang.org/x/tools/go/analysis/passes/modernize\"\n\t\"golang.org/x/tools/go/analysis/passes/nilfunc\"\n\t\"golang.org/x/tools/go/analysis/passes/nilness\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/passes/shadow\"\n\t\"golang.org/x/tools/go/analysis/passes/shift\"\n\t\"golang.org/x/tools/go/analysis/passes/sigchanyzer\"\n\t\"golang.org/x/tools/go/analysis/passes/slog\"\n\t\"golang.org/x/tools/go/analysis/passes/sortslice\"\n\t\"golang.org/x/tools/go/analysis/passes/stdmethods\"\n\t\"golang.org/x/tools/go/analysis/passes/stdversion\"\n\t\"golang.org/x/tools/go/analysis/passes/stringintconv\"\n\t\"golang.org/x/tools/go/analysis/passes/structtag\"\n\t\"golang.org/x/tools/go/analysis/passes/testinggoroutine\"\n\t\"golang.org/x/tools/go/analysis/passes/tests\"\n\t\"golang.org/x/tools/go/analysis/passes/timeformat\"\n\t\"golang.org/x/tools/go/analysis/passes/unmarshal\"\n\t\"golang.org/x/tools/go/analysis/passes/unreachable\"\n\t\"golang.org/x/tools/go/analysis/passes/unsafeptr\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedresult\"\n\t\"golang.org/x/tools/go/analysis/passes/unusedwrite\"\n\t\"golang.org/x/tools/go/analysis/passes/waitgroup\"\n\t\"golang.org/x/tools/gopls/internal/analysis/deprecated\"\n\t\"golang.org/x/tools/gopls/internal/analysis/embeddirective\"\n\t\"golang.org/x/tools/gopls/internal/analysis/fillreturns\"\n\t\"golang.org/x/tools/gopls/internal/analysis/infertypeargs\"\n\t\"golang.org/x/tools/gopls/internal/analysis/maprange\"\n\t\"golang.org/x/tools/gopls/internal/analysis/nonewvars\"\n\t\"golang.org/x/tools/gopls/internal/analysis/noresultvalues\"\n\t\"golang.org/x/tools/gopls/internal/analysis/recursiveiter\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifycompositelit\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifyrange\"\n\t\"golang.org/x/tools/gopls/internal/analysis/simplifyslice\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedfunc\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedparams\"\n\t\"golang.org/x/tools/gopls/internal/analysis/unusedvariable\"\n\t\"golang.org/x/tools/gopls/internal/analysis/writestring\"\n\t\"golang.org/x/tools/gopls/internal/analysis/yield\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/goplsexport\"\n\t\"honnef.co/go/tools/analysis/lint\"\n)\n\nvar AllAnalyzers = slices.Concat(DefaultAnalyzers, StaticcheckAnalyzers)\n\n// Analyzer augments an [analysis.Analyzer] with additional LSP configuration.\n//\n// Analyzers are immutable, since they are shared across multiple LSP sessions.\ntype Analyzer struct {\n\tanalyzer    *analysis.Analyzer\n\tstaticcheck *lint.RawDocumentation // only for staticcheck analyzers\n\tnonDefault  bool                   // (sense is negated so we can mostly omit it)\n\tactionKinds []protocol.CodeActionKind\n\tseverity    protocol.DiagnosticSeverity\n\ttags        []protocol.DiagnosticTag\n}\n\n// Analyzer returns the [analysis.Analyzer] that this Analyzer wraps.\nfunc (a *Analyzer) Analyzer() *analysis.Analyzer { return a.analyzer }\n\n// Enabled reports whether the analyzer is enabled by the options.\n// This value can be configured per-analysis in user settings.\nfunc (a *Analyzer) Enabled(o *Options) bool {\n\t// An explicit setting by name takes precedence.\n\tif v, found := o.Analyses[a.Analyzer().Name]; found {\n\t\treturn v\n\t}\n\tif a.staticcheck != nil {\n\t\t// An explicit staticcheck={true,false} setting\n\t\t// enables/disables all staticcheck analyzers.\n\t\tif o.StaticcheckProvided {\n\t\t\treturn o.Staticcheck\n\t\t}\n\t\t// Respect staticcheck's off-by-default options too.\n\t\t// (This applies to only a handful of analyzers.)\n\t\tif a.staticcheck.NonDefault {\n\t\t\treturn false\n\t\t}\n\t}\n\t// Respect gopls' default setting.\n\treturn !a.nonDefault\n}\n\n// ActionKinds is the set of kinds of code action this analyzer produces.\n//\n// If left unset, it defaults to QuickFix.\n// TODO(rfindley): revisit.\nfunc (a *Analyzer) ActionKinds() []protocol.CodeActionKind { return a.actionKinds }\n\n// Severity is the severity set for diagnostics reported by this analyzer.\n// The default severity is SeverityWarning.\n//\n// While the LSP spec does not specify how severity should be used, here are\n// some guiding heuristics:\n//   - Error: for parse and type errors, which would stop the build.\n//   - Warning: for analyzer diagnostics reporting likely bugs.\n//   - Info: for analyzer diagnostics that do not indicate bugs, but may\n//     suggest inaccurate or superfluous code.\n//   - Hint: for analyzer diagnostics that do not indicate mistakes, but offer\n//     simplifications or modernizations. By their nature, hints should\n//     generally carry quick fixes.\n//\n// The difference between Info and Hint is particularly subtle. Importantly,\n// Hint diagnostics do not appear in the Problems tab in VS Code, so they are\n// less intrusive than Info diagnostics. The rule of thumb is this: use Info if\n// the diagnostic is not a bug, but the author probably didn't mean to write\n// the code that way. Use Hint if the diagnostic is not a bug and the author\n// intended to write the code that way, but there is a simpler or more modern\n// way to express the same logic. An 'unused' diagnostic is Info level, since\n// the author probably didn't mean to check in unreachable code. A 'modernize'\n// or 'deprecated' diagnostic is Hint level, since the author intended to write\n// the code that way, but now there is a better way.\nfunc (a *Analyzer) Severity() protocol.DiagnosticSeverity {\n\tif a.severity == 0 {\n\t\treturn protocol.SeverityWarning\n\t}\n\treturn a.severity\n}\n\n// Tags is extra tags (unnecessary, deprecated, etc) for diagnostics\n// reported by this analyzer.\nfunc (a *Analyzer) Tags() []protocol.DiagnosticTag { return a.tags }\n\n// String returns the name of this analyzer.\nfunc (a *Analyzer) String() string { return a.analyzer.String() }\n\n// DefaultAnalyzers holds the list of Analyzers available to all gopls\n// sessions, independent of build version. It is the source from which\n// gopls/doc/analyzers.md is generated.\nvar DefaultAnalyzers = []*Analyzer{\n\t// See [Analyzer.Severity] for guidance on setting analyzer severity below.\n\n\t// The traditional vet suite:\n\t{analyzer: appends.Analyzer},\n\t{analyzer: asmdecl.Analyzer},\n\t{analyzer: assign.Analyzer},\n\t{analyzer: atomic.Analyzer},\n\t{analyzer: bools.Analyzer},\n\t{analyzer: buildtag.Analyzer},\n\t{analyzer: cgocall.Analyzer},\n\t{analyzer: composite.Analyzer},\n\t{analyzer: copylock.Analyzer},\n\t{analyzer: defers.Analyzer},\n\t{\n\t\tanalyzer: deprecated.Analyzer,\n\t\tseverity: protocol.SeverityHint,\n\t\ttags:     []protocol.DiagnosticTag{protocol.Deprecated},\n\t},\n\t{analyzer: directive.Analyzer},\n\t{analyzer: errorsas.Analyzer},\n\t{analyzer: framepointer.Analyzer},\n\t{analyzer: httpresponse.Analyzer},\n\t{analyzer: ifaceassert.Analyzer},\n\t{analyzer: loopclosure.Analyzer},\n\t{analyzer: lostcancel.Analyzer},\n\t{analyzer: nilfunc.Analyzer},\n\t{analyzer: printf.Analyzer},\n\t{analyzer: shift.Analyzer},\n\t{analyzer: sigchanyzer.Analyzer},\n\t{analyzer: slog.Analyzer},\n\t{analyzer: stdmethods.Analyzer},\n\t{analyzer: stdversion.Analyzer},\n\t{analyzer: stringintconv.Analyzer},\n\t{analyzer: structtag.Analyzer},\n\t{analyzer: testinggoroutine.Analyzer},\n\t{analyzer: tests.Analyzer},\n\t{analyzer: timeformat.Analyzer},\n\t{analyzer: unmarshal.Analyzer},\n\t{analyzer: unreachable.Analyzer},\n\t{analyzer: unsafeptr.Analyzer},\n\t{analyzer: unusedresult.Analyzer},\n\n\t// not suitable for vet:\n\t// - some (nilness, yield) use go/ssa; see #59714.\n\t// - others don't meet the \"frequency\" criterion;\n\t//   see GOROOT/src/cmd/vet/README.\n\t{analyzer: atomicalign.Analyzer},\n\t{analyzer: deepequalerrors.Analyzer},\n\t{analyzer: nilness.Analyzer}, // uses go/ssa\n\t{analyzer: yield.Analyzer},   // uses go/ssa\n\t{analyzer: sortslice.Analyzer},\n\t{analyzer: embeddirective.Analyzer},\n\t{analyzer: waitgroup.Analyzer},     // to appear in cmd/vet@go1.25\n\t{analyzer: hostport.Analyzer},      // to appear in cmd/vet@go1.25\n\t{analyzer: recursiveiter.Analyzer}, // under evaluation\n\t{analyzer: writestring.Analyzer},\n\n\t// disabled due to high false positives\n\t{analyzer: shadow.Analyzer, severity: protocol.SeverityHint, nonDefault: true},         // very noisy\n\t{analyzer: fieldalignment.Analyzer, severity: protocol.SeverityHint, nonDefault: true}, // #67762, #76237\n\n\t// simplifiers and modernizers\n\t//\n\t// These analyzers offer mere style fixes on correct code,\n\t// thus they will never appear in cmd/vet and\n\t// their severity level is \"information\".\n\t//\n\t// gofmt -s suite\n\t{\n\t\tanalyzer:    simplifycompositelit.Analyzer,\n\t\tactionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},\n\t\tseverity:    protocol.SeverityInformation,\n\t},\n\t{\n\t\tanalyzer:    simplifyrange.Analyzer,\n\t\tactionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},\n\t\tseverity:    protocol.SeverityInformation,\n\t},\n\t{\n\t\tanalyzer:    simplifyslice.Analyzer,\n\t\tactionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix},\n\t\tseverity:    protocol.SeverityInformation,\n\t},\n\t// other simplifiers\n\t{analyzer: inline.Analyzer, severity: protocol.SeverityHint}, // (in -lazy_edit mode)\n\t{analyzer: infertypeargs.Analyzer, severity: protocol.SeverityInformation},\n\t{analyzer: maprange.Analyzer, severity: protocol.SeverityHint},\n\t{analyzer: unusedparams.Analyzer, severity: protocol.SeverityInformation},\n\t{analyzer: unusedfunc.Analyzer, severity: protocol.SeverityInformation},\n\t{analyzer: unusedwrite.Analyzer, severity: protocol.SeverityInformation}, // uses go/ssa\n\t// the modernize suite\n\t{analyzer: modernize.AnyAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.AppendClippedAnalyzer, severity: protocol.SeverityHint, nonDefault: true}, // not nil-preserving\n\t{analyzer: modernize.BLoopAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.ErrorsAsTypeModernizer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.FmtAppendfAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.ForVarAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.PlusBuildModernizer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.StdIteratorsModernizer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.MapsLoopAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.MinMaxAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.NewExprAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.OmitZeroAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.RangeIntAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.ReflectTypeForAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.SlicesContainsAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.SlicesDeleteAnalyzer, severity: protocol.SeverityHint, nonDefault: true}, // not nil-preserving\n\t{analyzer: modernize.SlicesSortAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.StringsBuilderAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.StringsCutModernizer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.StringsCutPrefixAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.StringsSeqAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.TestingContextAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.UnsafeFuncsModernizer, severity: protocol.SeverityHint},\n\t{analyzer: modernize.WaitGroupGoAnalyzer, severity: protocol.SeverityHint},\n\t{analyzer: goplsexport.AtomicTypesModernizer, severity: protocol.SeverityHint},\n\n\t// type-error analyzers\n\t// These analyzers enrich go/types errors with suggested fixes.\n\t// Since they exist only to attach their fixes to type errors, their\n\t// severity is irrelevant.\n\t{analyzer: fillreturns.Analyzer},\n\t{analyzer: nonewvars.Analyzer},\n\t{analyzer: noresultvalues.Analyzer},\n\t{analyzer: unusedvariable.Analyzer},\n}\n\nfunc init() {\n\tif err := inline.Analyzer.Flags.Set(\"lazy_edits\", \"true\"); err != nil {\n\t\tlog.Fatalf(\"setting inline -lazy_edits flag: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/settings/codeactionkind.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings\n\nimport \"golang.org/x/tools/gopls/internal/protocol\"\n\n// This file defines constants for non-standard CodeActions.\n\n// CodeAction kinds specific to gopls\n//\n// See ../protocol/tsprotocol.go for LSP standard kinds, including\n//\n//\tquickfix\n//\trefactor\n//\trefactor.extract\n//\trefactor.inline\n//\trefactor.move\n//\trefactor.rewrite\n//\tsource\n//\tsource.organizeImports\n//\tsource.fixAll\n//\tnotebook\n//\n// Kinds are hierarchical: \"refactor\" subsumes \"refactor.inline\",\n// which subsumes \"refactor.inline.call\". This rule implies that the\n// empty string, confusingly named protocol.Empty, subsumes all kinds.\n// The \"Only\" field in a CodeAction request may specify a category\n// such as \"refactor\"; any matching code action will be returned.\n//\n// All CodeActions returned by gopls use a specific leaf kind such as\n// \"refactor.inline.call\", except for quick fixes, which all use\n// \"quickfix\". TODO(adonovan): perhaps quick fixes should also be\n// hierarchical (e.g. quickfix.govulncheck.{reset,upgrade})?\n//\n// # VS Code\n//\n// The effects of CodeActionKind on the behavior of VS Code are\n// baffling and undocumented. Here's what we have observed.\n//\n// Clicking on the \"Refactor...\" menu item shows a submenu of actions\n// with kind=\"refactor.*\", and clicking on \"Source action...\" shows\n// actions with kind=\"source.*\". A lightbulb appears in both cases.\n//\n// A third menu, \"Quick fix...\", not found on the usual context\n// menu but accessible through the command palette or \"⌘.\",\n// does not set the Only field in its request, so the set of\n// kinds is determined by how the server interprets the default.\n// The LSP 3.18 guidance is that this should be treated\n// equivalent to Only=[\"quickfix\"], and that is what gopls\n// now does. (If the server responds with more kinds, they will\n// be displayed in menu subsections.)\n//\n// All of these CodeAction requests have triggerkind=Invoked.\n//\n// Cursor motion also performs a CodeAction request, but with\n// triggerkind=Automatic. Even if this returns a mix of action kinds,\n// only the \"refactor\" and \"quickfix\" actions seem to matter.\n// A lightbulb appears if that subset of actions is non-empty, and the\n// menu displays them. (This was noisy--see #65167--so gopls now only\n// reports diagnostic-associated code actions if kind is Invoked or\n// missing.)\n//\n// None of these CodeAction requests specifies a \"kind\" restriction;\n// the filtering is done on the response, by the client.\n//\n// In all these menus, VS Code organizes the actions' menu items\n// into groups based on their kind, with hardwired captions such as\n// \"Refactor...\", \"Extract\", \"Inline\", \"More actions\", and \"Quick fix\".\n//\n// The special category \"source.fixAll\" is intended for actions that\n// are unambiguously safe to apply so that clients may automatically\n// apply all actions matching this category on save. (That said, this\n// is not VS Code's default behavior; see editor.codeActionsOnSave.)\nconst (\n\t// source\n\tGoAssembly                 protocol.CodeActionKind = \"source.assembly\"\n\tGoDoc                      protocol.CodeActionKind = \"source.doc\"\n\tGoFreeSymbols              protocol.CodeActionKind = \"source.freesymbols\"\n\tGoSplitPackage             protocol.CodeActionKind = \"source.splitPackage\"\n\tGoTest                     protocol.CodeActionKind = \"source.test\"\n\tGoToggleCompilerOptDetails protocol.CodeActionKind = \"source.toggleCompilerOptDetails\"\n\tAddTest                    protocol.CodeActionKind = \"source.addTest\"\n\tOrganizeImports            protocol.CodeActionKind = \"source.organizeImports\"\n\n\t// gopls\n\tGoplsDocFeatures protocol.CodeActionKind = \"gopls.doc.features\"\n\n\t// refactor.rewrite\n\tRefactorRewriteChangeQuote        protocol.CodeActionKind = \"refactor.rewrite.changeQuote\"\n\tRefactorRewriteFillStruct         protocol.CodeActionKind = \"refactor.rewrite.fillStruct\"\n\tRefactorRewriteFillSwitch         protocol.CodeActionKind = \"refactor.rewrite.fillSwitch\"\n\tRefactorRewriteInvertIf           protocol.CodeActionKind = \"refactor.rewrite.invertIf\"\n\tRefactorRewriteJoinLines          protocol.CodeActionKind = \"refactor.rewrite.joinLines\"\n\tRefactorRewriteRemoveUnusedParam  protocol.CodeActionKind = \"refactor.rewrite.removeUnusedParam\"\n\tRefactorRewriteMoveParamLeft      protocol.CodeActionKind = \"refactor.rewrite.moveParamLeft\"\n\tRefactorRewriteMoveParamRight     protocol.CodeActionKind = \"refactor.rewrite.moveParamRight\"\n\tRefactorRewriteSplitLines         protocol.CodeActionKind = \"refactor.rewrite.splitLines\"\n\tRefactorRewriteEliminateDotImport protocol.CodeActionKind = \"refactor.rewrite.eliminateDotImport\"\n\tRefactorRewriteAddTags            protocol.CodeActionKind = \"refactor.rewrite.addTags\"\n\tRefactorRewriteRemoveTags         protocol.CodeActionKind = \"refactor.rewrite.removeTags\"\n\n\t// refactor.inline\n\tRefactorInlineCall     protocol.CodeActionKind = \"refactor.inline.call\"\n\tRefactorInlineVariable protocol.CodeActionKind = \"refactor.inline.variable\"\n\n\t// refactor.extract\n\tRefactorExtractConstant    protocol.CodeActionKind = \"refactor.extract.constant\"\n\tRefactorExtractConstantAll protocol.CodeActionKind = \"refactor.extract.constant-all\"\n\tRefactorExtractFunction    protocol.CodeActionKind = \"refactor.extract.function\"\n\tRefactorExtractMethod      protocol.CodeActionKind = \"refactor.extract.method\"\n\tRefactorExtractVariable    protocol.CodeActionKind = \"refactor.extract.variable\"\n\tRefactorExtractVariableAll protocol.CodeActionKind = \"refactor.extract.variable-all\"\n\tRefactorExtractToNewFile   protocol.CodeActionKind = \"refactor.extract.toNewFile\"\n\n\t// refactor.move\n\tRefactorMoveType protocol.CodeActionKind = \"refactor.move.moveType\"\n\n\t// Note: add new kinds to:\n\t// - the SupportedCodeActions map in default.go\n\t// - the codeActionProducers table in ../golang/codeaction.go\n\t// - the docs in ../../doc/features/transformation.md\n)\n"
  },
  {
    "path": "gopls/internal/settings/default.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n)\n\nvar (\n\toptionsOnce    sync.Once\n\tdefaultOptions *Options\n)\n\n// DefaultOptions is the options that are used for Gopls execution independent\n// of any externally provided configuration (LSP initialization, command\n// invocation, etc.).\n//\n// It is the source from which gopls/doc/settings.md is generated.\nfunc DefaultOptions(overrides ...func(*Options)) *Options {\n\toptionsOnce.Do(func() {\n\t\tvar commands []string\n\t\tfor _, c := range command.Commands {\n\t\t\tcommands = append(commands, c.String())\n\t\t}\n\t\tdefaultOptions = &Options{\n\t\t\tClientOptions: ClientOptions{\n\t\t\t\tInsertTextFormat:                           protocol.PlainTextTextFormat,\n\t\t\t\tPreferredContentFormat:                     protocol.Markdown,\n\t\t\t\tConfigurationSupported:                     true,\n\t\t\t\tDynamicConfigurationSupported:              true,\n\t\t\t\tDynamicRegistrationSemanticTokensSupported: true,\n\t\t\t\tDynamicWatchedFilesSupported:               true,\n\t\t\t\tLineFoldingOnly:                            false,\n\t\t\t\tHierarchicalDocumentSymbolSupport:          true,\n\t\t\t\tImportsSource:                              ImportsSourceGopls,\n\t\t\t},\n\t\t\tServerOptions: ServerOptions{\n\t\t\t\tSupportedCodeActions: map[file.Kind]map[protocol.CodeActionKind]bool{\n\t\t\t\t\tfile.Go: {\n\t\t\t\t\t\t// This should include specific leaves in the tree,\n\t\t\t\t\t\t// (e.g. refactor.inline.call) not generic branches\n\t\t\t\t\t\t// (e.g. refactor.inline or refactor).\n\t\t\t\t\t\tprotocol.SourceFixAll:            true,\n\t\t\t\t\t\tprotocol.SourceOrganizeImports:   true,\n\t\t\t\t\t\tprotocol.QuickFix:                true,\n\t\t\t\t\t\tGoAssembly:                       true,\n\t\t\t\t\t\tGoDoc:                            true,\n\t\t\t\t\t\tGoFreeSymbols:                    true,\n\t\t\t\t\t\tGoSplitPackage:                   true,\n\t\t\t\t\t\tGoplsDocFeatures:                 true,\n\t\t\t\t\t\tRefactorRewriteChangeQuote:       true,\n\t\t\t\t\t\tRefactorRewriteFillStruct:        true,\n\t\t\t\t\t\tRefactorRewriteFillSwitch:        true,\n\t\t\t\t\t\tRefactorRewriteInvertIf:          true,\n\t\t\t\t\t\tRefactorRewriteJoinLines:         true,\n\t\t\t\t\t\tRefactorRewriteRemoveUnusedParam: true,\n\t\t\t\t\t\tRefactorRewriteSplitLines:        true,\n\t\t\t\t\t\tRefactorInlineCall:               true,\n\t\t\t\t\t\tRefactorInlineVariable:           true,\n\t\t\t\t\t\tRefactorExtractConstant:          true,\n\t\t\t\t\t\tRefactorExtractConstantAll:       true,\n\t\t\t\t\t\tRefactorExtractFunction:          true,\n\t\t\t\t\t\tRefactorExtractMethod:            true,\n\t\t\t\t\t\tRefactorExtractVariable:          true,\n\t\t\t\t\t\tRefactorExtractVariableAll:       true,\n\t\t\t\t\t\tRefactorExtractToNewFile:         true,\n\t\t\t\t\t\tRefactorMoveType:                 true, // off while implementation unfinished\n\t\t\t\t\t\t// Not GoTest: it must be explicit in CodeActionParams.Context.Only\n\t\t\t\t\t},\n\t\t\t\t\tfile.Mod: {\n\t\t\t\t\t\tprotocol.SourceOrganizeImports: true,\n\t\t\t\t\t\tprotocol.QuickFix:              true,\n\t\t\t\t\t},\n\t\t\t\t\tfile.Work: {},\n\t\t\t\t\tfile.Sum:  {},\n\t\t\t\t\tfile.Tmpl: {},\n\t\t\t\t},\n\t\t\t\tSupportedCommands: commands,\n\t\t\t},\n\t\t\tUserOptions: UserOptions{\n\t\t\t\tBuildOptions: BuildOptions{\n\t\t\t\t\tExpandWorkspaceToModule: true,\n\t\t\t\t\tDirectoryFilters:        []string{\"-**/node_modules\"},\n\t\t\t\t\tTemplateExtensions:      []string{},\n\t\t\t\t\tStandaloneTags:          []string{\"ignore\"},\n\t\t\t\t\tWorkspaceFiles:          []string{},\n\t\t\t\t},\n\t\t\t\tUIOptions: UIOptions{\n\t\t\t\t\tDiagnosticOptions: DiagnosticOptions{\n\t\t\t\t\t\tAnnotations: map[Annotation]bool{\n\t\t\t\t\t\t\tBounds: true,\n\t\t\t\t\t\t\tEscape: true,\n\t\t\t\t\t\t\tInline: true,\n\t\t\t\t\t\t\tNil:    true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tVulncheck:                 ModeVulncheckPrompt,\n\t\t\t\t\t\tDiagnosticsDelay:          1 * time.Second,\n\t\t\t\t\t\tDiagnosticsTrigger:        DiagnosticsOnEdit,\n\t\t\t\t\t\tAnalysisProgressReporting: true,\n\t\t\t\t\t},\n\t\t\t\t\tInlayHintOptions: InlayHintOptions{\n\t\t\t\t\t\tHints: map[InlayHint]bool{},\n\t\t\t\t\t},\n\t\t\t\t\tDocumentationOptions: DocumentationOptions{\n\t\t\t\t\t\tHoverKind:    FullDocumentation,\n\t\t\t\t\t\tLinkTarget:   \"pkg.go.dev\",\n\t\t\t\t\t\tLinksInHover: LinksInHover_LinkTarget,\n\t\t\t\t\t},\n\t\t\t\t\tNavigationOptions: NavigationOptions{\n\t\t\t\t\t\tImportShortcut: BothShortcuts,\n\t\t\t\t\t\tSymbolMatcher:  SymbolFastFuzzy,\n\t\t\t\t\t\tSymbolStyle:    DynamicSymbols,\n\t\t\t\t\t\tSymbolScope:    AllSymbolScope,\n\t\t\t\t\t},\n\t\t\t\t\tCompletionOptions: CompletionOptions{\n\t\t\t\t\t\tMatcher:                        Fuzzy,\n\t\t\t\t\t\tCompletionBudget:               100 * time.Millisecond,\n\t\t\t\t\t\tExperimentalPostfixCompletions: true,\n\t\t\t\t\t\tCompleteFunctionCalls:          true,\n\t\t\t\t\t},\n\t\t\t\t\tCodelenses: map[CodeLensSource]bool{\n\t\t\t\t\t\tCodeLensGenerate:          true,\n\t\t\t\t\t\tCodeLensRegenerateCgo:     true,\n\t\t\t\t\t\tCodeLensTidy:              true,\n\t\t\t\t\t\tCodeLensUpgradeDependency: true,\n\t\t\t\t\t\tCodeLensVendor:            true,\n\t\t\t\t\t\tCodeLensRunGovulncheck:    true,\n\t\t\t\t\t},\n\t\t\t\t\tNewGoFileHeader:        true,\n\t\t\t\t\tRenameMovesSubpackages: false,\n\t\t\t\t},\n\t\t\t},\n\t\t\tInternalOptions: InternalOptions{\n\t\t\t\tCompleteUnimported:          true,\n\t\t\t\tCompletionDocumentation:     true,\n\t\t\t\tDeepCompletion:              true,\n\t\t\t\tSubdirWatchPatterns:         SubdirWatchPatternsAuto,\n\t\t\t\tReportAnalysisProgressAfter: 5 * time.Second,\n\t\t\t\tTelemetryPrompt:             false,\n\t\t\t\tLinkifyShowMessage:          false,\n\t\t\t\tIncludeReplaceInWorkspace:   false,\n\t\t\t\tZeroConfig:                  true,\n\t\t\t},\n\t\t}\n\t})\n\toptions := defaultOptions.Clone()\n\tfor _, override := range overrides {\n\t\tif override != nil {\n\t\t\toverride(options)\n\t\t}\n\t}\n\n\treturn options\n}\n"
  },
  {
    "path": "gopls/internal/settings/settings.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings\n\nimport (\n\t\"fmt\"\n\t\"maps\"\n\t\"math\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n)\n\n// An Annotation is a category of Go compiler optimization diagnostic.\ntype Annotation string\n\nconst (\n\t// Nil controls nil checks.\n\tNil Annotation = \"nil\"\n\n\t// Escape controls diagnostics about escape choices.\n\tEscape Annotation = \"escape\"\n\n\t// Inline controls diagnostics about inlining choices.\n\tInline Annotation = \"inline\"\n\n\t// Bounds controls bounds checking diagnostics.\n\tBounds Annotation = \"bounds\"\n)\n\n// Options holds various configuration that affects Gopls execution, organized\n// by the nature or origin of the settings.\n//\n// Options must be comparable with reflect.DeepEqual, and serializable with\n// [frob.Codec].\n//\n// This type defines both the logic of LSP-supplied option parsing\n// (see [SetOptions]), and the public documentation of options in\n// ../../doc/settings.md (generated by gopls/doc/generate).\n//\n// Each exported field of each embedded type such as \"ClientOptions\"\n// contributes a user-visible option setting. The option name is the\n// field name rendered in camelCase. Unlike most Go doc comments,\n// these fields should be documented using GitHub markdown.\ntype Options struct {\n\tClientOptions\n\tServerOptions\n\tUserOptions\n\tInternalOptions\n}\n\n// Debug returns a list of \"name = value\" strings for each Options field.\nfunc (o *Options) Debug() []string {\n\tvar res []string\n\n\tvar visitStruct func(v reflect.Value, path []string)\n\tvisitStruct = func(v reflect.Value, path []string) {\n\t\tfor i := range v.NumField() {\n\t\t\tf := v.Field(i)\n\t\t\tftyp := v.Type().Field(i)\n\t\t\tpath := append(path, ftyp.Name)\n\t\t\tif ftyp.Type.Kind() == reflect.Struct {\n\t\t\t\tvisitStruct(f, path)\n\t\t\t} else {\n\t\t\t\tres = append(res, fmt.Sprintf(\"%s = %#v\",\n\t\t\t\t\tstrings.Join(path, \".\"),\n\t\t\t\t\tf.Interface()))\n\t\t\t}\n\t\t}\n\t}\n\tvisitStruct(reflect.ValueOf(o).Elem(), nil)\n\n\treturn res\n}\n\n// ClientOptions holds LSP-specific configuration that is provided by the\n// client.\n//\n// ClientOptions must be comparable with reflect.DeepEqual.\ntype ClientOptions struct {\n\tClientInfo                                 protocol.ClientInfo\n\tInsertTextFormat                           protocol.InsertTextFormat\n\tInsertReplaceSupported                     bool\n\tConfigurationSupported                     bool\n\tDynamicConfigurationSupported              bool\n\tDynamicRegistrationSemanticTokensSupported bool\n\tDynamicWatchedFilesSupported               bool\n\tRelativePatternsSupported                  bool\n\tPreferredContentFormat                     protocol.MarkupKind\n\tLineFoldingOnly                            bool\n\tHierarchicalDocumentSymbolSupport          bool\n\tImportsSource                              ImportsSourceEnum `status:\"experimental\"`\n\tSemanticTypes                              []string\n\tSemanticMods                               []string\n\tRelatedInformationSupported                bool\n\tCompletionTags                             bool\n\tCompletionDeprecated                       bool\n\tSupportedResourceOperations                []protocol.ResourceOperationKind\n\tCodeActionResolveOptions                   []string\n\tShowDocumentSupported                      bool\n\t// SupportedWorkDoneProgressFormats specifies the formats supported by the\n\t// client for handling workdone progress metadata.\n\tSupportedWorkDoneProgressFormats map[WorkDoneProgressStyle]bool\n\t// SupportedInteractiveInputTypes specifies the interactive types supported\n\t// by the client.\n\tSupportedInteractiveInputTypes map[InteractiveInputType]bool\n}\n\n// ServerOptions holds LSP-specific configuration that is provided by the\n// server.\n//\n// ServerOptions must be comparable with reflect.DeepEqual.\ntype ServerOptions struct {\n\tSupportedCodeActions map[file.Kind]map[protocol.CodeActionKind]bool\n\tSupportedCommands    []string\n}\n\n// Note: BuildOptions must be comparable with reflect.DeepEqual.\ntype BuildOptions struct {\n\t// BuildFlags is the set of flags passed on to the build system when invoked.\n\t// It is applied to queries like `go list`, which is used when discovering files.\n\t// The most common use is to set `-tags`.\n\tBuildFlags []string\n\n\t// Env adds environment variables to external commands run by `gopls`, most notably `go list`.\n\tEnv map[string]string\n\n\t// DirectoryFilters can be used to exclude unwanted directories from the\n\t// workspace. By default, all directories are included. Filters are an\n\t// operator, `+` to include and `-` to exclude, followed by a path prefix\n\t// relative to the workspace folder. They are evaluated in order, and\n\t// the last filter that applies to a path controls whether it is included.\n\t// The path prefix can be empty, so an initial `-` excludes everything.\n\t//\n\t// DirectoryFilters also supports the `**` operator to match 0 or more directories.\n\t//\n\t// Examples:\n\t//\n\t// Exclude node_modules at current depth: `-node_modules`\n\t//\n\t// Exclude node_modules at any depth: `-**/node_modules`\n\t//\n\t// Include only project_a: `-` (exclude everything), `+project_a`\n\t//\n\t// Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`\n\tDirectoryFilters []string\n\n\t// TemplateExtensions gives the extensions of file names that are treated\n\t// as template files. (The extension\n\t// is the part of the file name after the final dot.)\n\tTemplateExtensions []string\n\n\t// obsolete, no effect\n\tMemoryMode string `status:\"experimental\"`\n\n\t// ExpandWorkspaceToModule determines which packages are considered\n\t// \"workspace packages\" when the workspace is using modules.\n\t//\n\t// Workspace packages affect the scope of workspace-wide operations. Notably,\n\t// gopls diagnoses all packages considered to be part of the workspace after\n\t// every keystroke, so by setting \"ExpandWorkspaceToModule\" to false, and\n\t// opening a nested workspace directory, you can reduce the amount of work\n\t// gopls has to do to keep your workspace up to date.\n\tExpandWorkspaceToModule bool `status:\"experimental\"`\n\n\t// StandaloneTags specifies a set of build constraints that identify\n\t// individual Go source files that make up the entire main package of an\n\t// executable.\n\t//\n\t// A common example of standalone main files is the convention of using the\n\t// directive `//go:build ignore` to denote files that are not intended to be\n\t// included in any package, for example because they are invoked directly by\n\t// the developer using `go run`.\n\t//\n\t// Gopls considers a file to be a standalone main file if and only if it has\n\t// package name \"main\" and has a build directive of the exact form\n\t// \"//go:build tag\" or \"// +build tag\", where tag is among the list of tags\n\t// configured by this setting. Notably, if the build constraint is more\n\t// complicated than a simple tag (such as the composite constraint\n\t// `//go:build tag && go1.18`), the file is not considered to be a standalone\n\t// main file.\n\t//\n\t// This setting is only supported when gopls is built with Go 1.16 or later.\n\tStandaloneTags []string\n\n\t// WorkspaceFiles configures the set of globs that match files defining the\n\t// logical build of the current workspace. Any on-disk changes to any files\n\t// matching a glob specified here will trigger a reload of the workspace.\n\t//\n\t// This setting need only be customized in environments with a custom\n\t// GOPACKAGESDRIVER.\n\tWorkspaceFiles []string\n}\n\n// Note: UIOptions must be comparable with reflect.DeepEqual.\ntype UIOptions struct {\n\tDocumentationOptions\n\tCompletionOptions\n\tNavigationOptions\n\tDiagnosticOptions\n\tInlayHintOptions\n\n\t// Codelenses overrides the enabled/disabled state of each of gopls'\n\t// sources of [Code Lenses](codelenses.md).\n\t//\n\t// Example Usage:\n\t//\n\t// ```json5\n\t// \"gopls\": {\n\t// ...\n\t//   \"codelenses\": {\n\t//     \"generate\": false,  // Don't show the `go generate` lens.\n\t//   }\n\t// ...\n\t// }\n\t// ```\n\tCodelenses map[CodeLensSource]bool\n\n\t// SemanticTokens determines whether gopls will return a\n\t// SemanticTokensProvider at initialization, or respond\n\t// to request for semantic tokens.\n\tSemanticTokens bool `status:\"experimental\"`\n\n\t// NoSemanticString turns off the sending of the semantic token 'string'\n\t//\n\t// Deprecated: Use SemanticTokenTypes[\"string\"] = false instead. See\n\t// golang/vscode-go#3632\n\tNoSemanticString bool `status:\"experimental\"`\n\n\t// NoSemanticNumber turns off the sending of the semantic token 'number'\n\t//\n\t// Deprecated: Use SemanticTokenTypes[\"number\"] = false instead. See\n\t// golang/vscode-go#3632.\n\tNoSemanticNumber bool `status:\"experimental\"`\n\n\t// SemanticTokenTypes configures the semantic token types. It allows\n\t// disabling types by setting each value to false.\n\t// By default, all types are enabled.\n\tSemanticTokenTypes map[string]bool `status:\"experimental\"`\n\n\t// SemanticTokenModifiers configures the semantic token modifiers. It allows\n\t// disabling modifiers by setting each value to false.\n\t// By default, all modifiers are enabled.\n\tSemanticTokenModifiers map[string]bool `status:\"experimental\"`\n\n\t// NewGoFileHeader enables automatic insertion of the copyright comment\n\t// and package declaration in a newly created Go file.\n\tNewGoFileHeader bool\n\n\t// RenameMovesSubpackages enables Rename operations on packages to\n\t// move subdirectories of the target package.\n\tRenameMovesSubpackages bool `status:\"experimental\"`\n}\n\n// A CodeLensSource identifies an (algorithmic) source of code lenses.\ntype CodeLensSource string\n\n// CodeLens sources\n//\n// These identifiers appear in the \"codelenses\" configuration setting,\n// and in the user documentation thereof, which is generated by\n// gopls/doc/generate/generate.go parsing this file.\n//\n// Doc comments should use GitHub Markdown.\n// The first line becomes the title.\n//\n// (For historical reasons, each code lens source identifier typically\n// matches the name of one of the command.Commands returned by it,\n// but that isn't essential.)\nconst (\n\t// Run `go generate`\n\t//\n\t// This codelens source annotates any `//go:generate` comments\n\t// with commands to run `go generate` in this directory, on\n\t// all directories recursively beneath this one.\n\t//\n\t// See [Generating code](https://go.dev/blog/generate) for\n\t// more details.\n\tCodeLensGenerate CodeLensSource = \"generate\"\n\n\t// Re-generate cgo declarations\n\t//\n\t// This codelens source annotates an `import \"C\"` declaration\n\t// with a command to re-run the [cgo\n\t// command](https://pkg.go.dev/cmd/cgo) to regenerate the\n\t// corresponding Go declarations.\n\t//\n\t// Use this after editing the C code in comments attached to\n\t// the import, or in C header files included by it.\n\tCodeLensRegenerateCgo CodeLensSource = \"regenerate_cgo\"\n\n\t// Run govulncheck\n\t//\n\t// This codelens source annotates the `module` directive in a go.mod file\n\t// with a command to run govulncheck synchronously.\n\t//\n\t// [Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\n\t// computes the set of functions reachable within your application, including\n\t// dependencies; queries a database of known security vulnerabilities; and\n\t// reports any potential problems it finds.\n\t//\n\t//gopls:status experimental\n\tCodeLensVulncheck CodeLensSource = \"vulncheck\"\n\n\t// Run govulncheck (legacy)\n\t//\n\t// This codelens source annotates the `module` directive in a go.mod file\n\t// with a command to run Govulncheck asynchronously.\n\t//\n\t// [Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that\n\t// computes the set of functions reachable within your application, including\n\t// dependencies; queries a database of known security vulnerabilities; and\n\t// reports any potential problems it finds.\n\tCodeLensRunGovulncheck CodeLensSource = \"run_govulncheck\"\n\n\t// Run tests and benchmarks\n\t//\n\t// This codelens source annotates each `Test` and `Benchmark`\n\t// function in a `*_test.go` file with a command to run it.\n\t//\n\t// This source is off by default because VS Code has\n\t// a client-side custom UI for testing, and because progress\n\t// notifications are not a great UX for streamed test output.\n\t// See:\n\t// - golang/go#67400 for a discussion of this feature.\n\t// - https://github.com/joaotavora/eglot/discussions/1402\n\t//   for an alternative approach.\n\tCodeLensTest CodeLensSource = \"test\"\n\n\t// Tidy go.mod file\n\t//\n\t// This codelens source annotates the `module` directive in a\n\t// go.mod file with a command to run [`go mod\n\t// tidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures\n\t// that the go.mod file matches the source code in the module.\n\tCodeLensTidy CodeLensSource = \"tidy\"\n\n\t// Update dependencies\n\t//\n\t// This codelens source annotates the `module` directive in a\n\t// go.mod file with commands to:\n\t//\n\t// - check for available upgrades,\n\t// - upgrade direct dependencies, and\n\t// - upgrade all dependencies transitively.\n\tCodeLensUpgradeDependency CodeLensSource = \"upgrade_dependency\"\n\n\t// Update vendor directory\n\t//\n\t// This codelens source annotates the `module` directive in a\n\t// go.mod file with a command to run [`go mod\n\t// vendor`](https://go.dev/ref/mod#go-mod-vendor), which\n\t// creates or updates the directory named `vendor` in the\n\t// module root so that it contains an up-to-date copy of all\n\t// necessary package dependencies.\n\tCodeLensVendor CodeLensSource = \"vendor\"\n)\n\n// Note: CompletionOptions must be comparable with reflect.DeepEqual.\ntype CompletionOptions struct {\n\t// Placeholders enables placeholders for function parameters or struct\n\t// fields in completion responses.\n\tUsePlaceholders bool\n\n\t// CompletionBudget is the soft latency goal for completion requests. Most\n\t// requests finish in a couple milliseconds, but in some cases deep\n\t// completions can take much longer. As we use up our budget we\n\t// dynamically reduce the search scope to ensure we return timely\n\t// results. Zero means unlimited.\n\tCompletionBudget time.Duration `status:\"debug\"`\n\n\t// Matcher sets the algorithm that is used when calculating completion\n\t// candidates.\n\tMatcher Matcher `status:\"advanced\"`\n\n\t// ExperimentalPostfixCompletions enables artificial method snippets\n\t// such as \"someSlice.sort!\".\n\tExperimentalPostfixCompletions bool `status:\"experimental\"`\n\n\t// CompleteFunctionCalls enables function call completion.\n\t//\n\t// When completing a statement, or when a function return type matches the\n\t// expected of the expression being completed, completion may suggest call\n\t// expressions (i.e. may include parentheses).\n\tCompleteFunctionCalls bool\n}\n\n// Note: DocumentationOptions must be comparable with reflect.DeepEqual.\ntype DocumentationOptions struct {\n\t// HoverKind controls the information that appears in the hover text.\n\t// SingleLine is intended for use only by authors of editor plugins.\n\tHoverKind HoverKind\n\n\t// LinkTarget is the base URL for links to Go package\n\t// documentation returned by LSP operations such as Hover and\n\t// DocumentLinks and in the CodeDescription field of each\n\t// Diagnostic.\n\t//\n\t// It might be one of:\n\t//\n\t// * `\"godoc.org\"`\n\t// * `\"pkg.go.dev\"`\n\t//\n\t// If company chooses to use its own `godoc.org`, its address can be used as well.\n\t//\n\t// Modules matching the GOPRIVATE environment variable will not have\n\t// documentation links in hover.\n\tLinkTarget string\n\n\t// LinksInHover controls the presence of documentation links in hover markdown.\n\tLinksInHover LinksInHoverEnum\n}\n\n// LinksInHoverEnum has legal values:\n//\n// - `false`, for no links;\n// - `true`, for links to the `linkTarget` domain; or\n// - `\"gopls\"`, for links to gopls' internal documentation viewer.\n//\n// Note: this type has special logic in loadEnums in generate.go.\n// Be sure to reflect enum and doc changes there!\ntype LinksInHoverEnum int\n\nconst (\n\tLinksInHover_None LinksInHoverEnum = iota\n\tLinksInHover_LinkTarget\n\tLinksInHover_Gopls\n)\n\n// MarshalJSON implements the json.Marshaler interface, so that the default\n// values are formatted correctly in documentation. (See [Options.setOne] for\n// the flexible custom unmarshaling behavior).\nfunc (l LinksInHoverEnum) MarshalJSON() ([]byte, error) {\n\tswitch l {\n\tcase LinksInHover_None:\n\t\treturn []byte(\"false\"), nil\n\tcase LinksInHover_LinkTarget:\n\t\treturn []byte(\"true\"), nil\n\tcase LinksInHover_Gopls:\n\t\treturn []byte(`\"gopls\"`), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid LinksInHover value %d\", l)\n\t}\n}\n\n// Note: FormattingOptions must be comparable with reflect.DeepEqual.\ntype FormattingOptions struct {\n\t// Local is the equivalent of the `goimports -local` flag, which puts\n\t// imports beginning with this string after third-party packages. It should\n\t// be the prefix of the import path whose imports should be grouped\n\t// separately.\n\t//\n\t// It is used when tidying imports (during an LSP Organize\n\t// Imports request) or when inserting new ones (for example,\n\t// during completion); an LSP Formatting request merely sorts the\n\t// existing imports.\n\tLocal string\n\n\t// Gofumpt indicates if we should run gofumpt formatting.\n\tGofumpt bool\n}\n\n// Note: DiagnosticOptions must be comparable with reflect.DeepEqual,\n// and frob-encodable (no interfaces).\ntype DiagnosticOptions struct {\n\t// Analyses specify analyses that the user would like to enable or disable.\n\t// A map of the names of analysis passes that should be enabled/disabled.\n\t// A full list of analyzers that gopls uses can be found in\n\t// [analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\n\t//\n\t// Example Usage:\n\t//\n\t// ```json5\n\t// ...\n\t// \"analyses\": {\n\t//   \"unreachable\": false, // Disable the unreachable analyzer.\n\t//   \"unusedvariable\": true  // Enable the unusedvariable analyzer.\n\t// }\n\t// ...\n\t// ```\n\tAnalyses map[string]bool\n\n\t// Staticcheck configures the default set of analyses staticcheck.io.\n\t// These analyses are documented on\n\t// [Staticcheck's website](https://staticcheck.io/docs/checks/).\n\t//\n\t// The \"staticcheck\" option has three values:\n\t// - false: disable all staticcheck analyzers\n\t// - true: enable all staticcheck analyzers\n\t// - unset: enable a subset of staticcheck analyzers\n\t//   selected by gopls maintainers for runtime efficiency\n\t//   and analytic precision.\n\t//\n\t// Regardless of this setting, individual analyzers can be\n\t// selectively enabled or disabled using the `analyses` setting.\n\tStaticcheck         bool `status:\"experimental\"`\n\tStaticcheckProvided bool `status:\"experimental\"` // = \"staticcheck\" was explicitly provided\n\n\t// Annotations specifies the various kinds of compiler\n\t// optimization details that should be reported as diagnostics\n\t// when enabled for a package by the \"Toggle compiler\n\t// optimization details\" (`gopls.gc_details`) command.\n\t//\n\t// (Some users care only about one kind of annotation in their\n\t// profiling efforts. More importantly, in large packages, the\n\t// number of annotations can sometimes overwhelm the user\n\t// interface and exceed the per-file diagnostic limit.)\n\t//\n\t// TODO(adonovan): rename this field to CompilerOptDetail.\n\tAnnotations map[Annotation]bool\n\n\t// Vulncheck enables vulnerability scanning.\n\tVulncheck VulncheckMode `status:\"experimental\"`\n\n\t// DiagnosticsDelay controls the amount of time that gopls waits\n\t// after the most recent file modification before computing deep diagnostics.\n\t// Simple diagnostics (parsing and type-checking) are always run immediately\n\t// on recently modified packages.\n\t//\n\t// This option must be set to a valid duration string, for example `\"250ms\"`.\n\tDiagnosticsDelay time.Duration `status:\"advanced\"`\n\n\t// DiagnosticsTrigger controls when to run diagnostics.\n\tDiagnosticsTrigger DiagnosticsTrigger `status:\"experimental\"`\n\n\t// AnalysisProgressReporting controls whether gopls sends progress\n\t// notifications when construction of its index of analysis facts is taking a\n\t// long time. Cancelling these notifications will cancel the indexing task,\n\t// though it will restart after the next change in the workspace.\n\t//\n\t// When a package is opened for the first time and heavyweight analyses such as\n\t// staticcheck are enabled, it can take a while to construct the index of\n\t// analysis facts for all its dependencies. The index is cached in the\n\t// filesystem, so subsequent analysis should be faster.\n\tAnalysisProgressReporting bool\n}\n\ntype InlayHintOptions struct {\n\t// Hints specify inlay hints that users want to see. A full list of hints\n\t// that gopls uses can be found in\n\t// [inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).\n\tHints map[InlayHint]bool `status:\"experimental\"`\n}\n\n// An InlayHint identifies a category of hint that may be\n// independently requested through the \"hints\" setting.\ntype InlayHint string\n\n// This is the source from which gopls/doc/inlayHints.md is generated.\nconst (\n\t// ParameterNames controls inlay hints for parameter names:\n\t// ```go\n\t// \tparseInt(/* str: */ \"123\", /* radix: */ 8)\n\t// ```\n\tParameterNames InlayHint = \"parameterNames\"\n\n\t// AssignVariableTypes controls inlay hints for variable types in assign statements:\n\t// ```go\n\t// \ti/* int*/, j/* int*/ := 0, len(r)-1\n\t// ```\n\tAssignVariableTypes InlayHint = \"assignVariableTypes\"\n\n\t// ConstantValues controls inlay hints for constant values:\n\t// ```go\n\t// \tconst (\n\t// \t\tKindNone   Kind = iota/* = 0*/\n\t// \t\tKindPrint/*  = 1*/\n\t// \t\tKindPrintf/* = 2*/\n\t// \t\tKindErrorf/* = 3*/\n\t// \t)\n\t// ```\n\tConstantValues InlayHint = \"constantValues\"\n\n\t// RangeVariableTypes controls inlay hints for variable types in range statements:\n\t// ```go\n\t// \tfor k/* int*/, v/* string*/ := range []string{} {\n\t// \t\tfmt.Println(k, v)\n\t// \t}\n\t// ```\n\tRangeVariableTypes InlayHint = \"rangeVariableTypes\"\n\n\t// CompositeLiteralTypes controls inlay hints for composite literal types:\n\t// ```go\n\t// \tfor _, c := range []struct {\n\t// \t\tin, want string\n\t// \t}{\n\t// \t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t// \t}\n\t// ```\n\tCompositeLiteralTypes InlayHint = \"compositeLiteralTypes\"\n\n\t// CompositeLiteralFieldNames inlay hints for composite literal field names:\n\t// ```go\n\t// \t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n\t// ```\n\tCompositeLiteralFieldNames InlayHint = \"compositeLiteralFields\"\n\n\t// FunctionTypeParameters inlay hints for implicit type parameters on generic functions:\n\t// ```go\n\t// \tmyFoo/*[int, string]*/(1, \"hello\")\n\t// ```\n\tFunctionTypeParameters InlayHint = \"functionTypeParameters\"\n\n\t// IgnoredError inlay hints for implicitly discarded errors:\n\t// ```go\n\t// \tf.Close() // ignore error\n\t// ```\n\t// This check inserts an `// ignore error` hint following any\n\t// statement that is a function call whose error result is\n\t// implicitly ignored.\n\t//\n\t// To suppress the hint, write an actual comment containing\n\t// \"ignore error\" following the call statement, or explicitly\n\t// assign the result to a blank variable. A handful of common\n\t// functions such as `fmt.Println` are excluded from the\n\t// check.\n\tIgnoredError InlayHint = \"ignoredError\"\n)\n\ntype NavigationOptions struct {\n\t// ImportShortcut specifies whether import statements should link to\n\t// documentation or go to definitions.\n\tImportShortcut ImportShortcut\n\n\t// SymbolMatcher sets the algorithm that is used when finding workspace symbols.\n\tSymbolMatcher SymbolMatcher `status:\"advanced\"`\n\n\t// SymbolStyle controls how symbols are qualified in symbol responses.\n\t//\n\t// Example Usage:\n\t//\n\t// ```json5\n\t// \"gopls\": {\n\t// ...\n\t//   \"symbolStyle\": \"Dynamic\",\n\t// ...\n\t// }\n\t// ```\n\tSymbolStyle SymbolStyle `status:\"advanced\"`\n\n\t// SymbolScope controls which packages are searched for workspace/symbol\n\t// requests. When the scope is \"workspace\", gopls searches only workspace\n\t// packages. When the scope is \"all\", gopls searches all loaded packages,\n\t// including dependencies and the standard library.\n\tSymbolScope SymbolScope\n}\n\n// UserOptions holds custom Gopls configuration (not part of the LSP) that is\n// modified by the client.\n//\n// UserOptions must be comparable with reflect.DeepEqual.\ntype UserOptions struct {\n\tBuildOptions\n\tUIOptions\n\tFormattingOptions\n\n\t// MaxFileCacheBytes sets a soft limit on the file cache size in bytes.\n\t// If zero, the default budget is used.\n\t//\n\t// The cache may temporarily use more than this amount.\n\t// Also, this parameter limits file contents; disk block usage\n\t// as measured by du(1) may be significantly higher.\n\tMaxFileCacheBytes int64 `status:\"experimental\"`\n\n\t// VerboseOutput enables additional debug logging.\n\tVerboseOutput bool `status:\"debug\"`\n}\n\n// EnvSlice returns Env as a slice of k=v strings.\nfunc (u *UserOptions) EnvSlice() []string {\n\tvar result []string\n\tfor k, v := range u.Env {\n\t\tresult = append(result, fmt.Sprintf(\"%v=%v\", k, v))\n\t}\n\treturn result\n}\n\n// SetEnvSlice sets Env from a slice of k=v strings.\nfunc (u *UserOptions) SetEnvSlice(env []string) {\n\tu.Env = map[string]string{}\n\tfor _, kv := range env {\n\t\tsplit := strings.SplitN(kv, \"=\", 2)\n\t\tif len(split) != 2 {\n\t\t\tcontinue\n\t\t}\n\t\tu.Env[split[0]] = split[1]\n\t}\n}\n\ntype WorkDoneProgressStyle string\n\nconst WorkDoneProgressStyleLog WorkDoneProgressStyle = \"log\"\n\ntype InteractiveInputType string\n\nconst (\n\tInteractiveInputTypeString  InteractiveInputType = \"string\"\n\tInteractiveInputTypeFileURI InteractiveInputType = \"fileURI\"\n\tInteractiveInputTypeBool    InteractiveInputType = \"bool\"\n\tInteractiveInputTypeNumber  InteractiveInputType = \"number\"\n\tInteractiveInputTypeEnum    InteractiveInputType = \"enum\"\n\tInteractiveInputTypeList    InteractiveInputType = \"list\"\n)\n\n// InternalOptions contains settings that are not intended for use by the\n// average user. These may be settings used by tests or outdated settings that\n// will soon be deprecated. Some of these settings may not even be configurable\n// by the user.\n//\n// TODO(rfindley): even though these settings are not intended for\n// modification, some of them should be surfaced in our documentation.\ntype InternalOptions struct {\n\t// MCPTools configures enabled tools (by tool name), overriding the defaults.\n\tMCPTools map[string]bool\n\n\t// VerboseWorkDoneProgress controls whether the LSP server should send\n\t// progress reports for all work done outside the scope of an RPC.\n\t// Used by the regression tests.\n\tVerboseWorkDoneProgress bool\n\n\t// The following options were previously available to users, but they\n\t// really shouldn't be configured by anyone other than \"power users\".\n\n\t// CompletionDocumentation enables documentation with completion results.\n\tCompletionDocumentation bool\n\n\t// CompleteUnimported enables completion for packages that you do not\n\t// currently import.\n\tCompleteUnimported bool\n\n\t// DeepCompletion enables the ability to return completions from deep\n\t// inside relevant entities, rather than just the locally accessible ones.\n\t//\n\t// Consider this example:\n\t//\n\t// ```go\n\t// package main\n\t//\n\t// import \"fmt\"\n\t//\n\t// type wrapString struct {\n\t//     str string\n\t// }\n\t//\n\t// func main() {\n\t//     x := wrapString{\"hello world\"}\n\t//     fmt.Printf(<>)\n\t// }\n\t// ```\n\t//\n\t// At the location of the `<>` in this program, deep completion would suggest\n\t// the result `x.str`.\n\tDeepCompletion bool\n\n\t// ShowBugReports causes a message to be shown when the first bug is reported\n\t// on the server.\n\t// This option applies only during initialization.\n\tShowBugReports bool\n\n\t// SubdirWatchPatterns configures the file watching glob patterns registered\n\t// by gopls.\n\t//\n\t// Some clients (namely VS Code) do not send workspace/didChangeWatchedFile\n\t// notifications for files contained in a directory when that directory is\n\t// deleted:\n\t// https://github.com/microsoft/vscode/issues/109754\n\t//\n\t// In this case, gopls would miss important notifications about deleted\n\t// packages. To work around this, gopls registers a watch pattern for each\n\t// directory containing Go files.\n\t//\n\t// Unfortunately, other clients experience performance problems with this\n\t// many watch patterns, so there is no single behavior that works well for\n\t// all clients.\n\t//\n\t// The \"subdirWatchPatterns\" setting allows configuring this behavior. Its\n\t// default value of \"auto\" attempts to guess the correct behavior based on\n\t// the client name. We'd love to avoid this specialization, but as described\n\t// above there is no single value that works for all clients.\n\t//\n\t// If any LSP client does not behave well with the default value (for\n\t// example, if like VS Code it drops file notifications), please file an\n\t// issue.\n\tSubdirWatchPatterns SubdirWatchPatterns\n\n\t// ReportAnalysisProgressAfter sets the duration for gopls to wait before starting\n\t// progress reporting for ongoing go/analysis passes.\n\t//\n\t// It is intended to be used for testing only.\n\tReportAnalysisProgressAfter time.Duration\n\n\t// TelemetryPrompt controls whether gopls prompts about enabling Go telemetry.\n\t//\n\t// Once the prompt is answered, gopls doesn't ask again, but TelemetryPrompt\n\t// can prevent the question from ever being asked in the first place.\n\tTelemetryPrompt bool\n\n\t// LinkifyShowMessage controls whether the client wants gopls\n\t// to linkify links in showMessage. e.g. [go.dev](https://go.dev).\n\tLinkifyShowMessage bool\n\n\t// IncludeReplaceInWorkspace controls whether locally replaced modules in a\n\t// go.mod file are treated like workspace modules.\n\t// Or in other words, if a go.mod file with local replaces behaves like a\n\t// go.work file.\n\tIncludeReplaceInWorkspace bool\n\n\t// ZeroConfig enables the zero-config algorithm for workspace layout,\n\t// dynamically creating build configurations for different modules,\n\t// directories, and GOOS/GOARCH combinations to cover open files.\n\tZeroConfig bool\n\n\t// PullDiagnostics enables support for pull diagnostics.\n\t//\n\t// TODO(rfindley): make pull diagnostics robust, and remove this option,\n\t// allowing pull diagnostics by default.\n\tPullDiagnostics bool\n}\n\ntype SubdirWatchPatterns string\n\nconst (\n\tSubdirWatchPatternsOn   SubdirWatchPatterns = \"on\"\n\tSubdirWatchPatternsOff  SubdirWatchPatterns = \"off\"\n\tSubdirWatchPatternsAuto SubdirWatchPatterns = \"auto\"\n)\n\ntype ImportShortcut string\n\nconst (\n\tBothShortcuts      ImportShortcut = \"Both\"\n\tLinkShortcut       ImportShortcut = \"Link\"\n\tDefinitionShortcut ImportShortcut = \"Definition\"\n)\n\nfunc (s ImportShortcut) ShowLinks() bool {\n\treturn s == BothShortcuts || s == LinkShortcut\n}\n\nfunc (s ImportShortcut) ShowDefinition() bool {\n\treturn s == BothShortcuts || s == DefinitionShortcut\n}\n\n// ImportsSourceEnum has legal values:\n//\n// - `off` to disable searching the file system for imports\n// - `gopls` to use the metadata graph and module cache index\n// - `goimports` for the old behavior, to be deprecated\ntype ImportsSourceEnum string\n\nconst (\n\tImportsSourceOff       ImportsSourceEnum = \"off\"\n\tImportsSourceGopls     ImportsSourceEnum = \"gopls\"\n\tImportsSourceGoimports ImportsSourceEnum = \"goimports\"\n)\n\ntype Matcher string\n\nconst (\n\tFuzzy           Matcher = \"Fuzzy\"\n\tCaseInsensitive Matcher = \"CaseInsensitive\"\n\tCaseSensitive   Matcher = \"CaseSensitive\"\n)\n\n// A SymbolMatcher controls the matching of symbols for workspace/symbol\n// requests.\ntype SymbolMatcher string\n\nconst (\n\tSymbolFuzzy           SymbolMatcher = \"Fuzzy\"\n\tSymbolFastFuzzy       SymbolMatcher = \"FastFuzzy\"\n\tSymbolCaseInsensitive SymbolMatcher = \"CaseInsensitive\"\n\tSymbolCaseSensitive   SymbolMatcher = \"CaseSensitive\"\n)\n\n// A SymbolStyle controls the formatting of symbols in workspace/symbol results.\ntype SymbolStyle string\n\nconst (\n\t// PackageQualifiedSymbols is package qualified symbols i.e.\n\t// \"pkg.Foo.Field\".\n\tPackageQualifiedSymbols SymbolStyle = \"Package\"\n\t// FullyQualifiedSymbols is fully qualified symbols, i.e.\n\t// \"path/to/pkg.Foo.Field\".\n\tFullyQualifiedSymbols SymbolStyle = \"Full\"\n\t// DynamicSymbols uses whichever qualifier results in the highest scoring\n\t// match for the given symbol query. Here a \"qualifier\" is any \"/\" or \".\"\n\t// delimited suffix of the fully qualified symbol. i.e. \"to/pkg.Foo.Field\" or\n\t// just \"Foo.Field\".\n\tDynamicSymbols SymbolStyle = \"Dynamic\"\n)\n\n// A SymbolScope controls the search scope for workspace/symbol requests.\ntype SymbolScope string\n\nconst (\n\t// WorkspaceSymbolScope matches symbols in workspace packages only.\n\tWorkspaceSymbolScope SymbolScope = \"workspace\"\n\t// AllSymbolScope matches symbols in any loaded package, including\n\t// dependencies.\n\tAllSymbolScope SymbolScope = \"all\"\n)\n\ntype HoverKind string\n\nconst (\n\tSingleLine            HoverKind = \"SingleLine\"\n\tNoDocumentation       HoverKind = \"NoDocumentation\"\n\tSynopsisDocumentation HoverKind = \"SynopsisDocumentation\"\n\tFullDocumentation     HoverKind = \"FullDocumentation\"\n\n\t// Structured is a misguided experimental setting that returns a JSON\n\t// hover format. This setting should not be used, as it will be removed in a\n\t// future release of gopls.\n\tStructured HoverKind = \"Structured\"\n)\n\ntype VulncheckMode string\n\nconst (\n\t// Vulncheck can be triggered via prompt.\n\tModeVulncheckPrompt VulncheckMode = \"Prompt\"\n\t// Disable vulnerability analysis.\n\tModeVulncheckOff VulncheckMode = \"Off\"\n\t// In Imports mode, `gopls` will report vulnerabilities that affect packages\n\t// directly and indirectly used by the analyzed main module.\n\tModeVulncheckImports VulncheckMode = \"Imports\"\n\n\t// TODO: VulncheckRequire, VulncheckCallgraph\n)\n\ntype DiagnosticsTrigger string\n\nconst (\n\t// Trigger diagnostics on file edit and save. (default)\n\tDiagnosticsOnEdit DiagnosticsTrigger = \"Edit\"\n\t// Trigger diagnostics only on file save. Events like initial workspace load\n\t// or configuration change will still trigger diagnostics.\n\tDiagnosticsOnSave DiagnosticsTrigger = \"Save\"\n\t// TODO: support \"Manual\"?\n)\n\ntype CounterPath = telemetry.CounterPath\n\n// Set updates *Options based on the provided JSON value:\n// null, bool, string, number, array, or object.\n//\n// The applied result describes settings that were applied. Each CounterPath\n// contains at least the name of the setting, but may also include sub-setting\n// names for settings that are themselves maps, and/or a non-empty bucket name\n// when bucketing is desirable.\n//\n// On failure, it returns one or more non-nil errors.\nfunc (o *Options) Set(value any) (applied []CounterPath, errs []error) {\n\tswitch value := value.(type) {\n\tcase nil:\n\tcase map[string]any:\n\t\tseen := make(map[string]struct{})\n\t\tfor name, value := range value {\n\t\t\t// Use only the last segment of a dotted name such as\n\t\t\t// ui.navigation.symbolMatcher. The other segments\n\t\t\t// are discarded, even without validation (!).\n\t\t\t// (They are supported to enable hierarchical names\n\t\t\t// in the VS Code graphical configuration UI.)\n\t\t\tsplit := strings.Split(name, \".\")\n\t\t\tname = split[len(split)-1]\n\n\t\t\tif _, ok := seen[name]; ok {\n\t\t\t\terrs = append(errs, fmt.Errorf(\"duplicate value for %s\", name))\n\t\t\t}\n\t\t\tseen[name] = struct{}{}\n\n\t\t\tpaths, err := o.setOne(name, value)\n\t\t\tif err != nil {\n\t\t\t\terr := fmt.Errorf(\"setting option %q: %w\", name, err)\n\t\t\t\terrs = append(errs, err)\n\t\t\t}\n\t\t\t_, soft := err.(*SoftError)\n\t\t\tif err == nil || soft {\n\t\t\t\tif len(paths) == 0 {\n\t\t\t\t\tpath := CounterPath{name, \"\"}\n\t\t\t\t\tapplied = append(applied, path)\n\t\t\t\t} else {\n\t\t\t\t\tfor _, subpath := range paths {\n\t\t\t\t\t\tpath := append(CounterPath{name}, subpath...)\n\t\t\t\t\t\tapplied = append(applied, path)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tdefault:\n\t\terrs = append(errs, fmt.Errorf(\"invalid options type %T (want JSON null or object)\", value))\n\t}\n\treturn applied, errs\n}\n\nfunc (o *Options) ForClientCapabilities(clientInfo *protocol.ClientInfo, caps protocol.ClientCapabilities) {\n\tif clientInfo != nil {\n\t\to.ClientInfo = *clientInfo\n\t}\n\tif caps.Workspace.WorkspaceEdit != nil {\n\t\to.SupportedResourceOperations = caps.Workspace.WorkspaceEdit.ResourceOperations\n\t}\n\t// Check if the client supports snippets in completion items.\n\tif c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {\n\t\to.InsertTextFormat = protocol.SnippetTextFormat\n\t}\n\to.InsertReplaceSupported = caps.TextDocument.Completion.CompletionItem.InsertReplaceSupport\n\tif caps.Window.ShowDocument != nil {\n\t\to.ShowDocumentSupported = caps.Window.ShowDocument.Support\n\t}\n\t// Check if the client supports configuration messages.\n\to.ConfigurationSupported = caps.Workspace.Configuration\n\to.DynamicConfigurationSupported = caps.Workspace.DidChangeConfiguration.DynamicRegistration\n\to.DynamicRegistrationSemanticTokensSupported = caps.TextDocument.SemanticTokens.DynamicRegistration\n\to.DynamicWatchedFilesSupported = caps.Workspace.DidChangeWatchedFiles.DynamicRegistration\n\to.RelativePatternsSupported = caps.Workspace.DidChangeWatchedFiles.RelativePatternSupport\n\n\t// Check which types of content format are supported by this client.\n\tif hover := caps.TextDocument.Hover; hover != nil && len(hover.ContentFormat) > 0 {\n\t\to.PreferredContentFormat = hover.ContentFormat[0]\n\t}\n\t// Check if the client supports only line folding.\n\n\tif fr := caps.TextDocument.FoldingRange; fr != nil {\n\t\t// TODO(pjw): add telemetry\n\t\to.LineFoldingOnly = fr.LineFoldingOnly\n\t}\n\t// Check if the client supports hierarchical document symbols.\n\to.HierarchicalDocumentSymbolSupport = caps.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport\n\n\t// Client's semantic tokens\n\to.SemanticTypes = caps.TextDocument.SemanticTokens.TokenTypes\n\to.SemanticMods = caps.TextDocument.SemanticTokens.TokenModifiers\n\t// we don't need Requests, as we support full functionality\n\t// we don't need Formats, as there is only one, for now\n\n\t// Check if the client supports diagnostic related information.\n\to.RelatedInformationSupported = caps.TextDocument.PublishDiagnostics.RelatedInformation\n\t// Check if the client completion support includes tags (preferred) or deprecation\n\tif caps.TextDocument.Completion.CompletionItem.TagSupport != nil &&\n\t\tcaps.TextDocument.Completion.CompletionItem.TagSupport.ValueSet != nil {\n\t\to.CompletionTags = true\n\t} else if caps.TextDocument.Completion.CompletionItem.DeprecatedSupport {\n\t\to.CompletionDeprecated = true\n\t}\n\n\t// Check if the client supports code actions resolving.\n\tif caps.TextDocument.CodeAction.DataSupport && caps.TextDocument.CodeAction.ResolveSupport != nil {\n\t\to.CodeActionResolveOptions = caps.TextDocument.CodeAction.ResolveSupport.Properties\n\t}\n\n\t// Client experimental capabilities.\n\tif experimental, ok := caps.Experimental.(map[string]any); ok {\n\t\tif formats, ok := experimental[\"progressMessageStyles\"].([]any); ok {\n\t\t\to.SupportedWorkDoneProgressFormats = make(map[WorkDoneProgressStyle]bool, len(formats))\n\t\t\tfor _, f := range formats {\n\t\t\t\to.SupportedWorkDoneProgressFormats[WorkDoneProgressStyle(f.(string))] = true\n\t\t\t}\n\t\t}\n\n\t\tif inputTypes, ok := experimental[\"interactiveInputTypes\"].([]any); ok {\n\t\t\to.SupportedInteractiveInputTypes = make(map[InteractiveInputType]bool, len(inputTypes))\n\t\t\tfor _, t := range inputTypes {\n\t\t\t\to.SupportedInteractiveInputTypes[InteractiveInputType(t.(string))] = true\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar codec = frob.CodecFor[*Options]()\n\nfunc (o *Options) Clone() *Options {\n\tdata := codec.Encode(o)\n\tvar clone *Options\n\tcodec.Decode(data, &clone)\n\treturn clone\n}\n\n// validateDirectoryFilter validates if the filter string\n// - is not empty\n// - start with either + or -\n// - doesn't contain currently unsupported glob operators: *, ?\nfunc validateDirectoryFilter(ifilter string) (string, error) {\n\tfilter := fmt.Sprint(ifilter)\n\tif filter == \"\" || (filter[0] != '+' && filter[0] != '-') {\n\t\treturn \"\", fmt.Errorf(\"invalid filter %v, must start with + or -\", filter)\n\t}\n\tsegs := strings.Split(filter[1:], \"/\")\n\tunsupportedOps := [...]string{\"?\", \"*\"}\n\tfor _, seg := range segs {\n\t\tif seg != \"**\" {\n\t\t\tfor _, op := range unsupportedOps {\n\t\t\t\tif strings.Contains(seg, op) {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid filter %v, operator %v not supported. If you want to have this operator supported, consider filing an issue\", filter, op)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn strings.TrimRight(filepath.FromSlash(filter), \"/\"), nil\n}\n\n// setOne updates a field of o based on the name and value.\n//\n// The applied result describes the counter values to be updated as a result of\n// the applied setting. If the result is nil, the default counter for this\n// setting should be updated.\n//\n// For example, if the setting name is \"foo\",\n//   - If applied is nil, update the count for \"foo\".\n//   - If applied is []CounterPath{{\"bucket\"}}, update the count for\n//     foo:bucket.\n//   - If applied is []CounterPath{{\"a\",\"b\"}, {\"c\",\"d\"}}, update foo/a:b and\n//     foo/c:d.\n//\n// It returns an error if the value was invalid or duplicate.\n// It is the caller's responsibility to augment the error with 'name'.\nfunc (o *Options) setOne(name string, value any) (applied []CounterPath, _ error) {\n\tswitch name {\n\tcase \"env\":\n\t\tenv, ok := value.(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid type %T (want JSON object)\", value)\n\t\t}\n\t\tif o.Env == nil {\n\t\t\to.Env = make(map[string]string)\n\t\t}\n\t\tfor k, v := range env {\n\t\t\t// For historic compatibility, we accept int too (e.g. CGO_ENABLED=1).\n\t\t\tswitch v.(type) {\n\t\t\tcase string, int:\n\t\t\t\to.Env[k] = fmt.Sprint(v)\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"invalid map value %T (want string)\", v)\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\n\tcase \"buildFlags\":\n\t\treturn nil, setStringSlice(&o.BuildFlags, value)\n\n\tcase \"directoryFilters\":\n\t\tfilterStrings, err := asStringSlice(value)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar filters []string\n\t\tfor _, filterStr := range filterStrings {\n\t\t\tfilter, err := validateDirectoryFilter(filterStr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tfilters = append(filters, strings.TrimRight(filepath.FromSlash(filter), \"/\"))\n\t\t}\n\t\to.DirectoryFilters = filters\n\t\treturn nil, nil\n\n\tcase \"workspaceFiles\":\n\t\treturn nil, setStringSlice(&o.WorkspaceFiles, value)\n\tcase \"completionDocumentation\":\n\t\treturn setBool(&o.CompletionDocumentation, value)\n\tcase \"usePlaceholders\":\n\t\treturn setBool(&o.UsePlaceholders, value)\n\tcase \"deepCompletion\":\n\t\treturn setBool(&o.DeepCompletion, value)\n\tcase \"completeUnimported\":\n\t\treturn setBool(&o.CompleteUnimported, value)\n\tcase \"completionBudget\":\n\t\treturn nil, setDuration(&o.CompletionBudget, value)\n\tcase \"importsSource\":\n\t\treturn setEnum(&o.ImportsSource, value,\n\t\t\tImportsSourceOff,\n\t\t\tImportsSourceGopls,\n\t\t\tImportsSourceGoimports)\n\tcase \"matcher\":\n\t\treturn setEnum(&o.Matcher, value,\n\t\t\tFuzzy,\n\t\t\tCaseSensitive,\n\t\t\tCaseInsensitive)\n\n\tcase \"symbolMatcher\":\n\t\treturn setEnum(&o.SymbolMatcher, value,\n\t\t\tSymbolFuzzy,\n\t\t\tSymbolFastFuzzy,\n\t\t\tSymbolCaseInsensitive,\n\t\t\tSymbolCaseSensitive)\n\n\tcase \"symbolStyle\":\n\t\treturn setEnum(&o.SymbolStyle, value,\n\t\t\tFullyQualifiedSymbols,\n\t\t\tPackageQualifiedSymbols,\n\t\t\tDynamicSymbols)\n\n\tcase \"symbolScope\":\n\t\treturn setEnum(&o.SymbolScope, value,\n\t\t\tWorkspaceSymbolScope,\n\t\t\tAllSymbolScope)\n\n\tcase \"hoverKind\":\n\t\t// TODO(rfindley): reinstate the deprecation of Structured hover by making\n\t\t// it a warning in gopls v0.N+1, and removing it in gopls v0.N+2.\n\t\treturn setEnum(&o.HoverKind, value,\n\t\t\tNoDocumentation,\n\t\t\tSingleLine,\n\t\t\tSynopsisDocumentation,\n\t\t\tFullDocumentation,\n\t\t\tStructured,\n\t\t)\n\n\tcase \"linkTarget\":\n\t\treturn nil, setString(&o.LinkTarget, value)\n\n\tcase \"linksInHover\":\n\t\tswitch value {\n\t\tcase false:\n\t\t\to.LinksInHover = LinksInHover_None\n\t\tcase true:\n\t\t\to.LinksInHover = LinksInHover_LinkTarget\n\t\tcase \"gopls\":\n\t\t\to.LinksInHover = LinksInHover_Gopls\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(`invalid value %s; expect false, true, or \"gopls\"`, value)\n\t\t}\n\t\treturn nil, nil\n\n\tcase \"importShortcut\":\n\t\treturn setEnum(&o.ImportShortcut, value,\n\t\t\tBothShortcuts,\n\t\t\tLinkShortcut,\n\t\t\tDefinitionShortcut)\n\n\tcase \"analyses\":\n\t\treturn setBoolMap(&o.Analyses, value)\n\n\tcase \"hints\":\n\t\treturn setBoolMap(&o.Hints, value)\n\n\tcase \"annotations\":\n\t\treturn setAnnotationMap(&o.Annotations, value)\n\n\tcase \"vulncheck\":\n\t\treturn setEnum(&o.Vulncheck, value,\n\t\t\tModeVulncheckOff,\n\t\t\tModeVulncheckImports,\n\t\t\tModeVulncheckPrompt)\n\n\tcase \"codelenses\", \"codelens\":\n\t\tlensOverrides, err := asBoolMap[CodeLensSource](value)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif o.Codelenses == nil {\n\t\t\to.Codelenses = make(map[CodeLensSource]bool)\n\t\t}\n\t\to.Codelenses = maps.Clone(o.Codelenses)\n\t\tmaps.Copy(o.Codelenses, lensOverrides)\n\n\t\tvar counts []CounterPath\n\t\tfor k, v := range lensOverrides {\n\t\t\tcounts = append(counts, CounterPath{string(k), fmt.Sprint(v)})\n\t\t}\n\n\t\tvar errs []string\n\t\tif name == \"codelens\" {\n\t\t\terrs = append(errs, deprecatedError(\"codelenses\").Error())\n\t\t}\n\t\tif lensOverrides[CodeLensRunGovulncheck] && lensOverrides[CodeLensVulncheck] {\n\t\t\terrs = append(errs, \"The 'run_govulncheck' codelens is superseded by the 'vulncheck' codelens. Only 'vulncheck' should be set.\")\n\t\t}\n\t\tif len(errs) > 0 {\n\t\t\treturn counts, &SoftError{msg: strings.Join(errs, \"\\n\")}\n\t\t}\n\t\treturn counts, nil\n\n\tcase \"staticcheck\":\n\t\to.StaticcheckProvided = true\n\t\treturn setBool(&o.Staticcheck, value)\n\n\tcase \"local\":\n\t\treturn nil, setString(&o.Local, value)\n\n\tcase \"maxFileCacheBytes\":\n\t\treturn setInt64(&o.MaxFileCacheBytes, value)\n\n\tcase \"verboseOutput\":\n\t\treturn setBool(&o.VerboseOutput, value)\n\n\tcase \"verboseWorkDoneProgress\":\n\t\treturn setBool(&o.VerboseWorkDoneProgress, value)\n\n\tcase \"showBugReports\":\n\t\treturn setBool(&o.ShowBugReports, value)\n\n\tcase \"gofumpt\":\n\t\treturn setBool(&o.Gofumpt, value)\n\n\tcase \"completeFunctionCalls\":\n\t\treturn setBool(&o.CompleteFunctionCalls, value)\n\n\tcase \"semanticTokens\":\n\t\treturn setBool(&o.SemanticTokens, value)\n\n\t// TODO(hxjiang): deprecate noSemanticString and noSemanticNumber.\n\tcase \"noSemanticString\":\n\t\tcounts, err := setBool(&o.NoSemanticString, value)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn counts, &SoftError{\"noSemanticString setting is deprecated, use semanticTokenTypes instead (though you can continue to apply them for the time being).\"}\n\n\tcase \"noSemanticNumber\":\n\t\tcounts, err := setBool(&o.NoSemanticNumber, value)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn counts, &SoftError{\"noSemanticNumber setting is deprecated, use semanticTokenTypes instead (though you can continue to apply them for the time being).\"}\n\n\tcase \"semanticTokenTypes\":\n\t\treturn setBoolMap(&o.SemanticTokenTypes, value)\n\n\tcase \"semanticTokenModifiers\":\n\t\treturn setBoolMap(&o.SemanticTokenModifiers, value)\n\n\tcase \"newGoFileHeader\":\n\t\treturn setBool(&o.NewGoFileHeader, value)\n\n\tcase \"expandWorkspaceToModule\":\n\t\t// See golang/go#63536: we can consider deprecating\n\t\t// expandWorkspaceToModule, but probably need to change the default\n\t\t// behavior in that case to *not* expand to the module.\n\t\treturn setBool(&o.ExpandWorkspaceToModule, value)\n\n\tcase \"experimentalPostfixCompletions\":\n\t\treturn setBool(&o.ExperimentalPostfixCompletions, value)\n\n\tcase \"templateExtensions\":\n\t\tswitch value := value.(type) {\n\t\tcase []any:\n\t\t\treturn nil, setStringSlice(&o.TemplateExtensions, value)\n\t\tcase nil:\n\t\t\to.TemplateExtensions = nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unexpected type %T (want JSON array of string)\", value)\n\t\t}\n\t\treturn nil, nil\n\n\tcase \"diagnosticsDelay\":\n\t\treturn nil, setDuration(&o.DiagnosticsDelay, value)\n\n\tcase \"diagnosticsTrigger\":\n\t\treturn setEnum(&o.DiagnosticsTrigger, value,\n\t\t\tDiagnosticsOnEdit,\n\t\t\tDiagnosticsOnSave)\n\n\tcase \"analysisProgressReporting\":\n\t\treturn setBool(&o.AnalysisProgressReporting, value)\n\n\tcase \"standaloneTags\":\n\t\treturn nil, setStringSlice(&o.StandaloneTags, value)\n\n\tcase \"subdirWatchPatterns\":\n\t\treturn setEnum(&o.SubdirWatchPatterns, value,\n\t\t\tSubdirWatchPatternsOn,\n\t\t\tSubdirWatchPatternsOff,\n\t\t\tSubdirWatchPatternsAuto)\n\n\tcase \"reportAnalysisProgressAfter\":\n\t\treturn nil, setDuration(&o.ReportAnalysisProgressAfter, value)\n\n\tcase \"telemetryPrompt\":\n\t\treturn setBool(&o.TelemetryPrompt, value)\n\n\tcase \"linkifyShowMessage\":\n\t\treturn setBool(&o.LinkifyShowMessage, value)\n\n\tcase \"includeReplaceInWorkspace\":\n\t\treturn setBool(&o.IncludeReplaceInWorkspace, value)\n\n\tcase \"zeroConfig\":\n\t\treturn setBool(&o.ZeroConfig, value)\n\n\tcase \"pullDiagnostics\":\n\t\treturn setBool(&o.PullDiagnostics, value)\n\n\tcase \"mcpTools\":\n\t\treturn setBoolMap(&o.MCPTools, value)\n\n\tcase \"renameMovesSubpackages\":\n\t\treturn setBool(&o.RenameMovesSubpackages, value)\n\n\t// deprecated and renamed settings\n\t//\n\t// These should never be deleted: there is essentially no cost\n\t// to providing a better error message indefinitely; it's not\n\t// as if we would ever want to recycle the name of a setting.\n\n\t// renamed\n\tcase \"experimentalDisabledAnalyses\":\n\t\treturn nil, deprecatedError(\"analyses\")\n\n\tcase \"disableDeepCompletion\":\n\t\treturn nil, deprecatedError(\"deepCompletion\")\n\n\tcase \"disableFuzzyMatching\":\n\t\treturn nil, deprecatedError(\"fuzzyMatching\")\n\n\tcase \"wantCompletionDocumentation\":\n\t\treturn nil, deprecatedError(\"completionDocumentation\")\n\n\tcase \"wantUnimportedCompletions\":\n\t\treturn nil, deprecatedError(\"completeUnimported\")\n\n\tcase \"fuzzyMatching\":\n\t\treturn nil, deprecatedError(\"matcher\")\n\n\tcase \"caseSensitiveCompletion\":\n\t\treturn nil, deprecatedError(\"matcher\")\n\n\tcase \"experimentalDiagnosticsDelay\":\n\t\treturn nil, deprecatedError(\"diagnosticsDelay\")\n\n\t// deprecated\n\n\tcase \"allowImplicitNetworkAccess\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"memoryMode\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"tempModFile\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"experimentalWorkspaceModule\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"experimentalTemplateSupport\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"experimentalWatchedFileDelay\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"experimentalPackageCacheKey\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"allowModfileModifications\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"allExperiments\":\n\t\t// golang/go#65548: this setting is a no-op, but we fail don't report it as\n\t\t// deprecated, since the nightly VS Code injects it.\n\t\t//\n\t\t// If, in the future, VS Code stops injecting this, we could theoretically\n\t\t// report an error here, but it also seems harmless to keep ignoring this\n\t\t// setting forever.\n\t\treturn nil, nil\n\n\tcase \"experimentalUseInvalidMetadata\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"newDiff\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"wantSuggestedFixes\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"noIncrementalSync\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"watchFileChanges\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tcase \"go-diff\":\n\t\treturn nil, deprecatedError(\"\")\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unexpected setting\")\n\t}\n}\n\n// EnabledSemanticTokenModifiers returns a map of modifiers to boolean.\nfunc (o *Options) EnabledSemanticTokenModifiers() map[semtok.Modifier]bool {\n\tcopy := make(map[semtok.Modifier]bool, len(o.SemanticTokenModifiers))\n\tfor k, v := range o.SemanticTokenModifiers {\n\t\tcopy[semtok.Modifier(k)] = v\n\t}\n\treturn copy\n}\n\n// EnabledSemanticTokenTypes returns a map of types to boolean.\nfunc (o *Options) EnabledSemanticTokenTypes() map[semtok.Type]bool {\n\tcopy := make(map[semtok.Type]bool, len(o.SemanticTokenTypes))\n\tfor k, v := range o.SemanticTokenTypes {\n\t\tcopy[semtok.Type(k)] = v\n\t}\n\tif o.NoSemanticString {\n\t\tcopy[semtok.TokString] = false\n\t}\n\tif o.NoSemanticNumber {\n\t\tcopy[semtok.TokNumber] = false\n\t}\n\treturn copy\n}\n\n// A SoftError is an error that does not affect the functionality of gopls.\ntype SoftError struct {\n\tmsg string\n}\n\nfunc (e *SoftError) Error() string {\n\treturn e.msg\n}\n\n// deprecatedError reports the current setting as deprecated.\n// The optional replacement is suggested to the user.\nfunc deprecatedError(replacement string) error {\n\tmsg := \"this setting is deprecated\"\n\tif replacement != \"\" {\n\t\tmsg = fmt.Sprintf(\"%s, use %q instead\", msg, replacement)\n\t}\n\treturn &SoftError{msg}\n}\n\n// setT() and asT() helpers: the setT forms write to the 'dest *T'\n// variable only on success, to reduce boilerplate in Option.set.\n\nfunc setBool(dest *bool, value any) ([]CounterPath, error) {\n\tb, err := asBool(value)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t*dest = b\n\treturn []CounterPath{{fmt.Sprint(b)}}, nil\n}\n\nfunc asBool(value any) (bool, error) {\n\tb, ok := value.(bool)\n\tif !ok {\n\t\treturn false, fmt.Errorf(\"invalid type %T (want bool)\", value)\n\t}\n\treturn b, nil\n}\n\nfunc setDuration(dest *time.Duration, value any) error {\n\tstr, err := asString(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\tparsed, err := time.ParseDuration(str)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*dest = parsed\n\treturn nil\n}\n\nfunc setAnnotationMap(dest *map[Annotation]bool, value any) ([]CounterPath, error) {\n\tall, err := asBoolMap[string](value)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar counters []CounterPath\n\t// Default to everything enabled by default.\n\tm := make(map[Annotation]bool)\n\tfor k, enabled := range all {\n\t\tvar a Annotation\n\t\tcnts, err := setEnum(&a, k,\n\t\t\tNil,\n\t\t\tEscape,\n\t\t\tInline,\n\t\t\tBounds)\n\t\tif err != nil {\n\t\t\t// In case of an error, process any legacy values.\n\t\t\tswitch k {\n\t\t\tcase \"noEscape\":\n\t\t\t\tm[Escape] = false\n\t\t\t\treturn nil, fmt.Errorf(`\"noEscape\" is deprecated, set \"Escape: false\" instead`)\n\n\t\t\tcase \"noNilcheck\":\n\t\t\t\tm[Nil] = false\n\t\t\t\treturn nil, fmt.Errorf(`\"noNilcheck\" is deprecated, set \"Nil: false\" instead`)\n\n\t\t\tcase \"noInline\":\n\t\t\t\tm[Inline] = false\n\t\t\t\treturn nil, fmt.Errorf(`\"noInline\" is deprecated, set \"Inline: false\" instead`)\n\n\t\t\tcase \"noBounds\":\n\t\t\t\tm[Bounds] = false\n\t\t\t\treturn nil, fmt.Errorf(`\"noBounds\" is deprecated, set \"Bounds: false\" instead`)\n\n\t\t\tdefault:\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tcounters = append(counters, cnts...)\n\t\tm[a] = enabled\n\t}\n\t*dest = m\n\treturn counters, nil\n}\n\nfunc setBoolMap[K ~string](dest *map[K]bool, value any) ([]CounterPath, error) {\n\tm, err := asBoolMap[K](value)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t*dest = m\n\tvar counts []CounterPath\n\tfor k, v := range m {\n\t\tcounts = append(counts, CounterPath{string(k), fmt.Sprint(v)})\n\t}\n\treturn counts, nil\n}\n\nfunc asBoolMap[K ~string](value any) (map[K]bool, error) {\n\tall, ok := value.(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid type %T (want JSON object)\", value)\n\t}\n\tm := make(map[K]bool)\n\tfor a, enabled := range all {\n\t\tb, ok := enabled.(bool)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid type %T for object field %q\", enabled, a)\n\t\t}\n\t\tm[K(a)] = b\n\t}\n\treturn m, nil\n}\n\nfunc setString(dest *string, value any) error {\n\tstr, err := asString(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*dest = str\n\treturn nil\n}\n\nfunc asString(value any) (string, error) {\n\tstr, ok := value.(string)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"invalid type %T (want string)\", value)\n\t}\n\treturn str, nil\n}\n\nfunc setStringSlice(dest *[]string, value any) error {\n\tslice, err := asStringSlice(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*dest = slice\n\treturn nil\n}\n\nfunc asStringSlice(value any) ([]string, error) {\n\tarray, ok := value.([]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid type %T (want JSON array of string)\", value)\n\t}\n\tvar slice []string\n\tfor _, elem := range array {\n\t\tstr, ok := elem.(string)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid array element type %T (want string)\", elem)\n\t\t}\n\t\tslice = append(slice, str)\n\t}\n\treturn slice, nil\n}\n\nfunc setEnum[S ~string](dest *S, value any, options ...S) ([]CounterPath, error) {\n\tenum, err := asEnum(value, options...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t*dest = enum\n\treturn []CounterPath{{string(enum)}}, nil\n}\n\nfunc asEnum[S ~string](value any, options ...S) (S, error) {\n\tstr, err := asString(value)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfor _, opt := range options {\n\t\tif strings.EqualFold(str, string(opt)) {\n\t\t\treturn opt, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"invalid option %q for enum\", str)\n}\n\nfunc setInt64(dest *int64, value any) ([]CounterPath, error) {\n\ti, err := asInt64(value)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t*dest = i\n\treturn []CounterPath{{fmt.Sprint(i)}}, nil\n}\n\nfunc asInt64(value any) (int64, error) {\n\tswitch v := value.(type) {\n\n\tcase float64:\n\t\t// Note that this is what we expect since JSON unmarshalling\n\t\t// into any produces float64 for numbers.\n\t\tif !isFinite(v) {\n\t\t\treturn 0, fmt.Errorf(\"invalid value %v (want finite number)\", v)\n\t\t}\n\t\tif v != math.Trunc(v) {\n\t\t\treturn 0, fmt.Errorf(\"invalid value %v (want integer)\", v)\n\t\t}\n\t\tif v != float64(int64(v)) {\n\t\t\treturn 0, fmt.Errorf(\"invalid value %v (not representable as int64)\", v)\n\t\t}\n\t\treturn int64(v), nil\n\tcase int64:\n\t\treturn v, nil\n\tcase int:\n\t\treturn int64(v), nil\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"invalid type %T (want int64)\", value)\n\t}\n}\n\n// isFinite reports whether f represents a finite rational value.\n// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).\nfunc isFinite(f float64) bool {\n\treturn math.Abs(f) <= math.MaxFloat64\n}\n"
  },
  {
    "path": "gopls/internal/settings/settings_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings_test\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/clonetest\"\n\t. \"golang.org/x/tools/gopls/internal/settings\"\n)\n\nfunc TestDefaultsEquivalence(t *testing.T) {\n\topts1 := DefaultOptions()\n\topts2 := DefaultOptions()\n\tif !reflect.DeepEqual(opts1, opts2) {\n\t\tt.Fatal(\"default options are not equivalent using reflect.DeepEqual\")\n\t}\n}\n\nfunc TestOptions_Set(t *testing.T) {\n\ttype testCase struct {\n\t\tname      string\n\t\tvalue     any\n\t\twantError bool\n\t\tcheck     func(Options) bool\n\t}\n\ttests := []testCase{\n\t\t{\n\t\t\tname:  \"symbolStyle\",\n\t\t\tvalue: \"Dynamic\",\n\t\t\tcheck: func(o Options) bool { return o.SymbolStyle == DynamicSymbols },\n\t\t},\n\t\t{\n\t\t\tname:      \"symbolStyle\",\n\t\t\tvalue:     \"\",\n\t\t\twantError: true,\n\t\t\tcheck:     func(o Options) bool { return o.SymbolStyle == \"\" },\n\t\t},\n\t\t{\n\t\t\tname:      \"symbolStyle\",\n\t\t\tvalue:     false,\n\t\t\twantError: true,\n\t\t\tcheck:     func(o Options) bool { return o.SymbolStyle == \"\" },\n\t\t},\n\t\t{\n\t\t\tname:  \"symbolMatcher\",\n\t\t\tvalue: \"caseInsensitive\",\n\t\t\tcheck: func(o Options) bool { return o.SymbolMatcher == SymbolCaseInsensitive },\n\t\t},\n\t\t{\n\t\t\tname:  \"completionBudget\",\n\t\t\tvalue: \"2s\",\n\t\t\tcheck: func(o Options) bool { return o.CompletionBudget == 2*time.Second },\n\t\t},\n\t\t{\n\t\t\tname:  \"codelenses\",\n\t\t\tvalue: map[string]any{\"generate\": true},\n\t\t\tcheck: func(o Options) bool { return o.Codelenses[\"generate\"] },\n\t\t},\n\t\t{\n\t\t\tname:  \"allExperiments\",\n\t\t\tvalue: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn true // just confirm that we handle this setting\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"hoverKind\",\n\t\t\tvalue: \"FullDocumentation\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == FullDocumentation\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"hoverKind\",\n\t\t\tvalue: \"NoDocumentation\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == NoDocumentation\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"hoverKind\",\n\t\t\tvalue: \"SingleLine\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == SingleLine\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"hoverKind\",\n\t\t\tvalue: \"Structured\",\n\t\t\t// wantError: true, // TODO(rfindley): reinstate this error\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == Structured\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"ui.documentation.hoverKind\",\n\t\t\tvalue: \"Structured\",\n\t\t\t// wantError: true, // TODO(rfindley): reinstate this error\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == Structured\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"hoverKind\",\n\t\t\tvalue: \"FullDocumentation\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == FullDocumentation\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"ui.documentation.hoverKind\",\n\t\t\tvalue: \"FullDocumentation\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.HoverKind == FullDocumentation\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"matcher\",\n\t\t\tvalue: \"Fuzzy\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Matcher == Fuzzy\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"matcher\",\n\t\t\tvalue: \"CaseSensitive\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Matcher == CaseSensitive\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"matcher\",\n\t\t\tvalue: \"CaseInsensitive\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Matcher == CaseInsensitive\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"env\",\n\t\t\tvalue: map[string]any{\"testing\": \"true\"},\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\tv, found := o.Env[\"testing\"]\n\t\t\t\treturn found && v == \"true\"\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:      \"env\",\n\t\t\tvalue:     []string{\"invalid\", \"input\"},\n\t\t\twantError: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Env == nil\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"directoryFilters\",\n\t\t\tvalue: []any{\"-node_modules\", \"+project_a\"},\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn len(o.DirectoryFilters) == 2\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:      \"directoryFilters\",\n\t\t\tvalue:     []any{\"invalid\"},\n\t\t\twantError: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn len(o.DirectoryFilters) == 0\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:      \"directoryFilters\",\n\t\t\tvalue:     []string{\"-invalid\", \"+type\"},\n\t\t\twantError: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn len(o.DirectoryFilters) == 0\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"annotations\",\n\t\t\tvalue: map[string]any{\n\t\t\t\t\"Nil\":      false,\n\t\t\t\t\"noBounds\": true,\n\t\t\t},\n\t\t\twantError: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn !o.Annotations[Nil] && !o.Annotations[Bounds]\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:      \"vulncheck\",\n\t\t\tvalue:     []any{\"invalid\"},\n\t\t\twantError: true,\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Vulncheck == \"\" // For invalid value, default to 'off'.\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"vulncheck\",\n\t\t\tvalue: \"Imports\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Vulncheck == ModeVulncheckImports // For invalid value, default to 'off'.\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"vulncheck\",\n\t\t\tvalue: \"imports\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Vulncheck == ModeVulncheckImports\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"vulncheck\",\n\t\t\tvalue: \"Prompt\",\n\t\t\tcheck: func(o Options) bool {\n\t\t\t\treturn o.Vulncheck == ModeVulncheckPrompt\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tvar opts Options\n\t\t_, err := opts.Set(map[string]any{test.name: test.value})\n\t\tif err != nil {\n\t\t\tif !test.wantError {\n\t\t\t\tt.Errorf(\"Options.set(%q, %v) failed: %v\",\n\t\t\t\t\ttest.name, test.value, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t} else if test.wantError {\n\t\t\tt.Fatalf(\"Options.set(%q, %v) succeeded unexpectedly\",\n\t\t\t\ttest.name, test.value)\n\t\t}\n\n\t\t// TODO: this could be made much better using cmp.Diff, if that becomes\n\t\t// available in this module.\n\t\tif !test.check(opts) {\n\t\t\tt.Errorf(\"Options.set(%q, %v): unexpected result %+v\", test.name, test.value, opts)\n\t\t}\n\t}\n}\n\nfunc TestOptions_Clone(t *testing.T) {\n\t// Test that the Options.Clone actually performs a deep clone of the Options\n\t// struct.\n\n\tgolden := clonetest.NonZero[*Options]()\n\topts := clonetest.NonZero[*Options]()\n\topts2 := opts.Clone()\n\n\t// The clone should be equivalent to the original.\n\tif diff := cmp.Diff(golden, opts2); diff != \"\" {\n\t\tt.Errorf(\"Clone() does not match original (-want +got):\\n%s\", diff)\n\t}\n\n\t// Mutating the clone should not mutate the original.\n\tclonetest.ZeroOut(opts2)\n\tif diff := cmp.Diff(golden, opts); diff != \"\" {\n\t\tt.Errorf(\"Mutating clone mutated the original (-want +got):\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/settings/staticcheck.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"honnef.co/go/tools/analysis/lint\"\n\t\"honnef.co/go/tools/quickfix\"\n\t\"honnef.co/go/tools/quickfix/qf1001\"\n\t\"honnef.co/go/tools/quickfix/qf1002\"\n\t\"honnef.co/go/tools/quickfix/qf1003\"\n\t\"honnef.co/go/tools/quickfix/qf1004\"\n\t\"honnef.co/go/tools/quickfix/qf1005\"\n\t\"honnef.co/go/tools/quickfix/qf1006\"\n\t\"honnef.co/go/tools/quickfix/qf1007\"\n\t\"honnef.co/go/tools/quickfix/qf1008\"\n\t\"honnef.co/go/tools/quickfix/qf1009\"\n\t\"honnef.co/go/tools/quickfix/qf1010\"\n\t\"honnef.co/go/tools/quickfix/qf1011\"\n\t\"honnef.co/go/tools/quickfix/qf1012\"\n\t\"honnef.co/go/tools/simple\"\n\t\"honnef.co/go/tools/simple/s1000\"\n\t\"honnef.co/go/tools/simple/s1001\"\n\t\"honnef.co/go/tools/simple/s1002\"\n\t\"honnef.co/go/tools/simple/s1003\"\n\t\"honnef.co/go/tools/simple/s1004\"\n\t\"honnef.co/go/tools/simple/s1005\"\n\t\"honnef.co/go/tools/simple/s1006\"\n\t\"honnef.co/go/tools/simple/s1007\"\n\t\"honnef.co/go/tools/simple/s1008\"\n\t\"honnef.co/go/tools/simple/s1009\"\n\t\"honnef.co/go/tools/simple/s1010\"\n\t\"honnef.co/go/tools/simple/s1011\"\n\t\"honnef.co/go/tools/simple/s1012\"\n\t\"honnef.co/go/tools/simple/s1016\"\n\t\"honnef.co/go/tools/simple/s1017\"\n\t\"honnef.co/go/tools/simple/s1018\"\n\t\"honnef.co/go/tools/simple/s1019\"\n\t\"honnef.co/go/tools/simple/s1020\"\n\t\"honnef.co/go/tools/simple/s1021\"\n\t\"honnef.co/go/tools/simple/s1023\"\n\t\"honnef.co/go/tools/simple/s1024\"\n\t\"honnef.co/go/tools/simple/s1025\"\n\t\"honnef.co/go/tools/simple/s1028\"\n\t\"honnef.co/go/tools/simple/s1029\"\n\t\"honnef.co/go/tools/simple/s1030\"\n\t\"honnef.co/go/tools/simple/s1031\"\n\t\"honnef.co/go/tools/simple/s1032\"\n\t\"honnef.co/go/tools/simple/s1033\"\n\t\"honnef.co/go/tools/simple/s1034\"\n\t\"honnef.co/go/tools/simple/s1035\"\n\t\"honnef.co/go/tools/simple/s1036\"\n\t\"honnef.co/go/tools/simple/s1037\"\n\t\"honnef.co/go/tools/simple/s1038\"\n\t\"honnef.co/go/tools/simple/s1039\"\n\t\"honnef.co/go/tools/simple/s1040\"\n\t\"honnef.co/go/tools/staticcheck\"\n\t\"honnef.co/go/tools/staticcheck/sa1000\"\n\t\"honnef.co/go/tools/staticcheck/sa1001\"\n\t\"honnef.co/go/tools/staticcheck/sa1002\"\n\t\"honnef.co/go/tools/staticcheck/sa1003\"\n\t\"honnef.co/go/tools/staticcheck/sa1004\"\n\t\"honnef.co/go/tools/staticcheck/sa1005\"\n\t\"honnef.co/go/tools/staticcheck/sa1006\"\n\t\"honnef.co/go/tools/staticcheck/sa1007\"\n\t\"honnef.co/go/tools/staticcheck/sa1008\"\n\t\"honnef.co/go/tools/staticcheck/sa1010\"\n\t\"honnef.co/go/tools/staticcheck/sa1011\"\n\t\"honnef.co/go/tools/staticcheck/sa1012\"\n\t\"honnef.co/go/tools/staticcheck/sa1013\"\n\t\"honnef.co/go/tools/staticcheck/sa1014\"\n\t\"honnef.co/go/tools/staticcheck/sa1015\"\n\t\"honnef.co/go/tools/staticcheck/sa1016\"\n\t\"honnef.co/go/tools/staticcheck/sa1017\"\n\t\"honnef.co/go/tools/staticcheck/sa1018\"\n\t\"honnef.co/go/tools/staticcheck/sa1019\"\n\t\"honnef.co/go/tools/staticcheck/sa1020\"\n\t\"honnef.co/go/tools/staticcheck/sa1021\"\n\t\"honnef.co/go/tools/staticcheck/sa1023\"\n\t\"honnef.co/go/tools/staticcheck/sa1024\"\n\t\"honnef.co/go/tools/staticcheck/sa1025\"\n\t\"honnef.co/go/tools/staticcheck/sa1026\"\n\t\"honnef.co/go/tools/staticcheck/sa1027\"\n\t\"honnef.co/go/tools/staticcheck/sa1028\"\n\t\"honnef.co/go/tools/staticcheck/sa1029\"\n\t\"honnef.co/go/tools/staticcheck/sa1030\"\n\t\"honnef.co/go/tools/staticcheck/sa1031\"\n\t\"honnef.co/go/tools/staticcheck/sa1032\"\n\t\"honnef.co/go/tools/staticcheck/sa2000\"\n\t\"honnef.co/go/tools/staticcheck/sa2001\"\n\t\"honnef.co/go/tools/staticcheck/sa2002\"\n\t\"honnef.co/go/tools/staticcheck/sa2003\"\n\t\"honnef.co/go/tools/staticcheck/sa3000\"\n\t\"honnef.co/go/tools/staticcheck/sa3001\"\n\t\"honnef.co/go/tools/staticcheck/sa4000\"\n\t\"honnef.co/go/tools/staticcheck/sa4001\"\n\t\"honnef.co/go/tools/staticcheck/sa4003\"\n\t\"honnef.co/go/tools/staticcheck/sa4004\"\n\t\"honnef.co/go/tools/staticcheck/sa4005\"\n\t\"honnef.co/go/tools/staticcheck/sa4006\"\n\t\"honnef.co/go/tools/staticcheck/sa4008\"\n\t\"honnef.co/go/tools/staticcheck/sa4009\"\n\t\"honnef.co/go/tools/staticcheck/sa4010\"\n\t\"honnef.co/go/tools/staticcheck/sa4011\"\n\t\"honnef.co/go/tools/staticcheck/sa4012\"\n\t\"honnef.co/go/tools/staticcheck/sa4013\"\n\t\"honnef.co/go/tools/staticcheck/sa4014\"\n\t\"honnef.co/go/tools/staticcheck/sa4015\"\n\t\"honnef.co/go/tools/staticcheck/sa4016\"\n\t\"honnef.co/go/tools/staticcheck/sa4017\"\n\t\"honnef.co/go/tools/staticcheck/sa4018\"\n\t\"honnef.co/go/tools/staticcheck/sa4019\"\n\t\"honnef.co/go/tools/staticcheck/sa4020\"\n\t\"honnef.co/go/tools/staticcheck/sa4021\"\n\t\"honnef.co/go/tools/staticcheck/sa4022\"\n\t\"honnef.co/go/tools/staticcheck/sa4023\"\n\t\"honnef.co/go/tools/staticcheck/sa4024\"\n\t\"honnef.co/go/tools/staticcheck/sa4025\"\n\t\"honnef.co/go/tools/staticcheck/sa4026\"\n\t\"honnef.co/go/tools/staticcheck/sa4027\"\n\t\"honnef.co/go/tools/staticcheck/sa4028\"\n\t\"honnef.co/go/tools/staticcheck/sa4029\"\n\t\"honnef.co/go/tools/staticcheck/sa4030\"\n\t\"honnef.co/go/tools/staticcheck/sa4031\"\n\t\"honnef.co/go/tools/staticcheck/sa4032\"\n\t\"honnef.co/go/tools/staticcheck/sa5000\"\n\t\"honnef.co/go/tools/staticcheck/sa5001\"\n\t\"honnef.co/go/tools/staticcheck/sa5002\"\n\t\"honnef.co/go/tools/staticcheck/sa5003\"\n\t\"honnef.co/go/tools/staticcheck/sa5004\"\n\t\"honnef.co/go/tools/staticcheck/sa5005\"\n\t\"honnef.co/go/tools/staticcheck/sa5007\"\n\t\"honnef.co/go/tools/staticcheck/sa5008\"\n\t\"honnef.co/go/tools/staticcheck/sa5009\"\n\t\"honnef.co/go/tools/staticcheck/sa5010\"\n\t\"honnef.co/go/tools/staticcheck/sa5011\"\n\t\"honnef.co/go/tools/staticcheck/sa5012\"\n\t\"honnef.co/go/tools/staticcheck/sa6000\"\n\t\"honnef.co/go/tools/staticcheck/sa6001\"\n\t\"honnef.co/go/tools/staticcheck/sa6002\"\n\t\"honnef.co/go/tools/staticcheck/sa6003\"\n\t\"honnef.co/go/tools/staticcheck/sa6005\"\n\t\"honnef.co/go/tools/staticcheck/sa6006\"\n\t\"honnef.co/go/tools/staticcheck/sa9001\"\n\t\"honnef.co/go/tools/staticcheck/sa9002\"\n\t\"honnef.co/go/tools/staticcheck/sa9003\"\n\t\"honnef.co/go/tools/staticcheck/sa9004\"\n\t\"honnef.co/go/tools/staticcheck/sa9005\"\n\t\"honnef.co/go/tools/staticcheck/sa9006\"\n\t\"honnef.co/go/tools/staticcheck/sa9007\"\n\t\"honnef.co/go/tools/staticcheck/sa9008\"\n\t\"honnef.co/go/tools/staticcheck/sa9009\"\n\t\"honnef.co/go/tools/stylecheck\"\n\t\"honnef.co/go/tools/stylecheck/st1000\"\n\t\"honnef.co/go/tools/stylecheck/st1001\"\n\t\"honnef.co/go/tools/stylecheck/st1003\"\n\t\"honnef.co/go/tools/stylecheck/st1005\"\n\t\"honnef.co/go/tools/stylecheck/st1006\"\n\t\"honnef.co/go/tools/stylecheck/st1008\"\n\t\"honnef.co/go/tools/stylecheck/st1011\"\n\t\"honnef.co/go/tools/stylecheck/st1012\"\n\t\"honnef.co/go/tools/stylecheck/st1013\"\n\t\"honnef.co/go/tools/stylecheck/st1015\"\n\t\"honnef.co/go/tools/stylecheck/st1016\"\n\t\"honnef.co/go/tools/stylecheck/st1017\"\n\t\"honnef.co/go/tools/stylecheck/st1018\"\n\t\"honnef.co/go/tools/stylecheck/st1019\"\n\t\"honnef.co/go/tools/stylecheck/st1020\"\n\t\"honnef.co/go/tools/stylecheck/st1021\"\n\t\"honnef.co/go/tools/stylecheck/st1022\"\n\t\"honnef.co/go/tools/stylecheck/st1023\"\n)\n\n// StaticcheckAnalyzers lists available Staticcheck analyzers.\nvar StaticcheckAnalyzers = initStaticcheckAnalyzers()\n\nfunc initStaticcheckAnalyzers() (res []*Analyzer) {\n\n\tmapSeverity := func(severity lint.Severity) protocol.DiagnosticSeverity {\n\t\tswitch severity {\n\t\tcase lint.SeverityError:\n\t\t\treturn protocol.SeverityError\n\t\tcase lint.SeverityDeprecated:\n\t\t\t// TODO(dh): in LSP, deprecated is a tag, not a severity.\n\t\t\t//   We'll want to support this once we enable SA5011.\n\t\t\treturn protocol.SeverityWarning\n\t\tcase lint.SeverityWarning:\n\t\t\treturn protocol.SeverityWarning\n\t\tcase lint.SeverityInfo:\n\t\t\treturn protocol.SeverityInformation\n\t\tcase lint.SeverityHint:\n\t\t\treturn protocol.SeverityHint\n\t\tdefault:\n\t\t\treturn protocol.SeverityWarning\n\t\t}\n\t}\n\n\t// We can't import buildir.Analyzer directly, so grab it from another analyzer.\n\tbuildir := sa1000.SCAnalyzer.Analyzer.Requires[0]\n\tif buildir.Name != \"buildir\" {\n\t\tpanic(\"sa1000.Requires[0] is not buildir\")\n\t}\n\n\tadd := func(a *lint.Analyzer, dflt bool) {\n\t\t// Assert that no analyzer that requires \"buildir\",\n\t\t// even indirectly, is enabled by default.\n\t\tif dflt {\n\t\t\tvar visit func(aa *analysis.Analyzer)\n\t\t\tvisit = func(aa *analysis.Analyzer) {\n\t\t\t\tif aa == buildir {\n\t\t\t\t\tlog.Fatalf(\"%s requires buildir (perhaps indirectly) yet is enabled by default\", a.Analyzer.Name)\n\t\t\t\t}\n\t\t\t\tfor _, req := range aa.Requires {\n\t\t\t\t\tvisit(req)\n\t\t\t\t}\n\t\t\t}\n\t\t\tvisit(a.Analyzer)\n\t\t}\n\t\tres = append(res, &Analyzer{\n\t\t\tanalyzer:    a.Analyzer,\n\t\t\tstaticcheck: a.Doc,\n\t\t\tnonDefault:  !dflt,\n\t\t\tseverity:    mapSeverity(a.Doc.Severity),\n\t\t})\n\t}\n\n\ttype M = map[*lint.Analyzer]any // value = true|false|nil\n\n\taddAll := func(suite string, upstream []*lint.Analyzer, config M) {\n\t\tfor _, a := range upstream {\n\t\t\tv, ok := config[a]\n\t\t\tif !ok {\n\t\t\t\tpanic(fmt.Sprintf(\"%s.Analyzers includes %s but config mapping does not; settings audit required\", suite, a.Analyzer.Name))\n\t\t\t}\n\t\t\tif v != nil {\n\t\t\t\tadd(a, v.(bool))\n\t\t\t}\n\t\t}\n\t}\n\n\t// For each analyzer in the four suites provided by\n\t// staticcheck, we provide a complete configuration, mapping\n\t// it to a boolean, indicating whether it should be on by\n\t// default in gopls, or nil to indicate explicitly that it has\n\t// been excluded (e.g. because it is redundant with an\n\t// existing vet analyzer such as printf, waitgroup, appends).\n\t//\n\t// This approach ensures that as suites grow, we make an\n\t// affirmative decision, positive or negative, about adding\n\t// new items.\n\t//\n\t// An analyzer may be off by default if:\n\t// - it requires, even indirectly, \"buildir\", which is like\n\t//   buildssa but uses facts, making it expensive;\n\t// - it has significant false positives;\n\t// - it reports on non-problematic style issues;\n\t// - its fixes are lossy (e.g. of comments) or not always sound;\n\t// - it reports \"maybes\", not \"definites\" (e.g. sa9001).\n\t// - it reports on harmless stylistic choices that may have\n\t//   been chosen deliberately for clarity or emphasis (e.g. s1005).\n\t// - it makes deductions from build tags that are not true\n\t//   for all configurations.\n\n\taddAll(\"simple\", simple.Analyzers, M{\n\t\ts1000.SCAnalyzer: true,\n\t\ts1001.SCAnalyzer: true,\n\t\ts1002.SCAnalyzer: false, // makes unsound deductions from build tags\n\t\ts1003.SCAnalyzer: true,\n\t\ts1004.SCAnalyzer: true,\n\t\ts1005.SCAnalyzer: false, // not a correctness/style issue\n\t\ts1006.SCAnalyzer: false, // makes unsound deductions from build tags\n\t\ts1007.SCAnalyzer: true,\n\t\ts1008.SCAnalyzer: false, // may lose important comments\n\t\ts1009.SCAnalyzer: true,\n\t\ts1010.SCAnalyzer: true,\n\t\ts1011.SCAnalyzer: false, // requires buildir\n\t\ts1012.SCAnalyzer: true,\n\t\ts1016.SCAnalyzer: false, // may rely on coincidental structural subtyping\n\t\ts1017.SCAnalyzer: true,\n\t\ts1018.SCAnalyzer: true,\n\t\ts1019.SCAnalyzer: true,\n\t\ts1020.SCAnalyzer: true,\n\t\ts1021.SCAnalyzer: false, // may lose important comments\n\t\ts1023.SCAnalyzer: true,\n\t\ts1024.SCAnalyzer: true,\n\t\ts1025.SCAnalyzer: false, // requires buildir\n\t\ts1028.SCAnalyzer: true,\n\t\ts1029.SCAnalyzer: false, // requires buildir\n\t\ts1030.SCAnalyzer: true,  // (tentative: see docs,\n\t\ts1031.SCAnalyzer: true,\n\t\ts1032.SCAnalyzer: true,\n\t\ts1033.SCAnalyzer: true,\n\t\ts1034.SCAnalyzer: true,\n\t\ts1035.SCAnalyzer: true,\n\t\ts1036.SCAnalyzer: true,\n\t\ts1037.SCAnalyzer: true,\n\t\ts1038.SCAnalyzer: true,\n\t\ts1039.SCAnalyzer: true,\n\t\ts1040.SCAnalyzer: true,\n\t})\n\n\taddAll(\"stylecheck\", stylecheck.Analyzers, M{\n\t\t// These are all slightly too opinionated to be on by default.\n\t\tst1000.SCAnalyzer: false,\n\t\tst1001.SCAnalyzer: false,\n\t\tst1003.SCAnalyzer: false,\n\t\tst1005.SCAnalyzer: false,\n\t\tst1006.SCAnalyzer: false,\n\t\tst1008.SCAnalyzer: false,\n\t\tst1011.SCAnalyzer: false,\n\t\tst1012.SCAnalyzer: false,\n\t\tst1013.SCAnalyzer: false,\n\t\tst1015.SCAnalyzer: false,\n\t\tst1016.SCAnalyzer: false,\n\t\tst1017.SCAnalyzer: false,\n\t\tst1018.SCAnalyzer: false,\n\t\tst1019.SCAnalyzer: false,\n\t\tst1020.SCAnalyzer: false,\n\t\tst1021.SCAnalyzer: false,\n\t\tst1022.SCAnalyzer: false,\n\t\tst1023.SCAnalyzer: false,\n\t})\n\n\t// These are not bug fixes but code transformations: some\n\t// reversible and value-neutral, of the kind typically listed\n\t// on the VS Code's Refactor/Source Action/Quick Fix menus.\n\t//\n\t// TODO(adonovan): plumb these to the appropriate menu,\n\t// as we do for code actions such as split/join lines.\n\taddAll(\"quickfix\", quickfix.Analyzers, M{\n\t\tqf1001.SCAnalyzer: false, // not always a style improvement\n\t\tqf1002.SCAnalyzer: true,\n\t\tqf1003.SCAnalyzer: true,\n\t\tqf1004.SCAnalyzer: true,\n\t\tqf1005.SCAnalyzer: false, // not always a style improvement\n\t\tqf1006.SCAnalyzer: false, // may lose important comments\n\t\tqf1007.SCAnalyzer: false, // may lose important comments\n\t\tqf1008.SCAnalyzer: false, // not always a style improvement\n\t\tqf1009.SCAnalyzer: true,\n\t\tqf1010.SCAnalyzer: true,\n\t\tqf1011.SCAnalyzer: false, // not always a style improvement\n\t\tqf1012.SCAnalyzer: true,\n\t})\n\n\taddAll(\"staticcheck\", staticcheck.Analyzers, M{\n\t\tsa1000.SCAnalyzer: false, // requires buildir\n\t\tsa1001.SCAnalyzer: true,\n\t\tsa1002.SCAnalyzer: false, // requires buildir\n\t\tsa1003.SCAnalyzer: false, // requires buildir\n\t\tsa1004.SCAnalyzer: true,\n\t\tsa1005.SCAnalyzer: true,\n\t\tsa1006.SCAnalyzer: nil,   // redundant wrt 'printf'\n\t\tsa1007.SCAnalyzer: false, // requires buildir\n\t\tsa1008.SCAnalyzer: true,\n\t\tsa1010.SCAnalyzer: false, // requires buildir\n\t\tsa1011.SCAnalyzer: false, // requires buildir\n\t\tsa1012.SCAnalyzer: true,\n\t\tsa1013.SCAnalyzer: true,\n\t\tsa1014.SCAnalyzer: false, // requires buildir\n\t\tsa1015.SCAnalyzer: false, // requires buildir\n\t\tsa1016.SCAnalyzer: true,\n\t\tsa1017.SCAnalyzer: false, // requires buildir\n\t\tsa1018.SCAnalyzer: false, // requires buildir\n\t\tsa1019.SCAnalyzer: nil,   // redundant wrt 'deprecated'\n\t\tsa1020.SCAnalyzer: false, // requires buildir\n\t\tsa1021.SCAnalyzer: false, // requires buildir\n\t\tsa1023.SCAnalyzer: false, // requires buildir\n\t\tsa1024.SCAnalyzer: false, // requires buildir\n\t\tsa1025.SCAnalyzer: false, // requires buildir\n\t\tsa1026.SCAnalyzer: false, // requires buildir\n\t\tsa1027.SCAnalyzer: false, // requires buildir\n\t\tsa1028.SCAnalyzer: false, // requires buildir\n\t\tsa1029.SCAnalyzer: false, // requires buildir\n\t\tsa1030.SCAnalyzer: false, // requires buildir\n\t\tsa1031.SCAnalyzer: false, // requires buildir\n\t\tsa1032.SCAnalyzer: false, // requires buildir\n\t\tsa2000.SCAnalyzer: nil,   // redundant wrt 'waitgroup'\n\t\tsa2001.SCAnalyzer: true,\n\t\tsa2002.SCAnalyzer: false, // requires buildir\n\t\tsa2003.SCAnalyzer: false, // requires buildir\n\t\tsa3000.SCAnalyzer: true,\n\t\tsa3001.SCAnalyzer: true,\n\t\tsa4000.SCAnalyzer: true,\n\t\tsa4001.SCAnalyzer: true,\n\t\tsa4003.SCAnalyzer: true,\n\t\tsa4004.SCAnalyzer: true,\n\t\tsa4005.SCAnalyzer: false, // requires buildir\n\t\tsa4006.SCAnalyzer: false, // requires buildir\n\t\tsa4008.SCAnalyzer: false, // requires buildir\n\t\tsa4009.SCAnalyzer: false, // requires buildir\n\t\tsa4010.SCAnalyzer: false, // requires buildir\n\t\tsa4011.SCAnalyzer: true,\n\t\tsa4012.SCAnalyzer: false, // requires buildir\n\t\tsa4013.SCAnalyzer: true,\n\t\tsa4014.SCAnalyzer: true,\n\t\tsa4015.SCAnalyzer: false, // requires buildir\n\t\tsa4016.SCAnalyzer: true,\n\t\tsa4017.SCAnalyzer: false, // requires buildir\n\t\tsa4018.SCAnalyzer: false, // requires buildir\n\t\tsa4019.SCAnalyzer: true,\n\t\tsa4020.SCAnalyzer: true,\n\t\tsa4021.SCAnalyzer: nil, // redundant wrt 'appends'\n\t\tsa4022.SCAnalyzer: true,\n\t\tsa4023.SCAnalyzer: false, // requires buildir\n\t\tsa4024.SCAnalyzer: true,\n\t\tsa4025.SCAnalyzer: true,\n\t\tsa4026.SCAnalyzer: true,\n\t\tsa4027.SCAnalyzer: true,\n\t\tsa4028.SCAnalyzer: true,\n\t\tsa4029.SCAnalyzer: true,\n\t\tsa4030.SCAnalyzer: true,\n\t\tsa4031.SCAnalyzer: false, // requires buildir\n\t\tsa4032.SCAnalyzer: true,\n\t\tsa5000.SCAnalyzer: false, // requires buildir\n\t\tsa5001.SCAnalyzer: true,\n\t\tsa5002.SCAnalyzer: false, // makes unsound deductions from build tags\n\t\tsa5003.SCAnalyzer: true,\n\t\tsa5004.SCAnalyzer: true,\n\t\tsa5005.SCAnalyzer: false, // requires buildir\n\t\tsa5007.SCAnalyzer: false, // requires buildir\n\t\tsa5008.SCAnalyzer: true,\n\t\tsa5009.SCAnalyzer: nil,   // requires buildir; redundant wrt 'printf' (#34494)\n\t\tsa5010.SCAnalyzer: false, // requires buildir\n\t\tsa5011.SCAnalyzer: false, // requires buildir\n\t\tsa5012.SCAnalyzer: false, // requires buildir\n\t\tsa6000.SCAnalyzer: false, // requires buildir\n\t\tsa6001.SCAnalyzer: false, // requires buildir\n\t\tsa6002.SCAnalyzer: false, // requires buildir\n\t\tsa6003.SCAnalyzer: false, // requires buildir\n\t\tsa6005.SCAnalyzer: true,\n\t\tsa6006.SCAnalyzer: true,\n\t\tsa9001.SCAnalyzer: false, // reports a \"maybe\" bug (low signal/noise)\n\t\tsa9002.SCAnalyzer: true,\n\t\tsa9003.SCAnalyzer: false, // requires buildir; NonDefault\n\t\tsa9004.SCAnalyzer: true,\n\t\tsa9005.SCAnalyzer: false, // requires buildir\n\t\tsa9006.SCAnalyzer: true,\n\t\tsa9007.SCAnalyzer: false, // requires buildir\n\t\tsa9008.SCAnalyzer: false, // requires buildir\n\t\tsa9009.SCAnalyzer: true,\n\t})\n\n\treturn res\n}\n"
  },
  {
    "path": "gopls/internal/settings/vet_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage settings_test\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/doc\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestVetSuite ensures that gopls's analyser suite is a superset of vet's.\n//\n// This test may fail spuriously if gopls/doc/generate.TestGenerated\n// fails. In that case retry after re-running the JSON generator.\nfunc TestVetSuite(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Read gopls' suite from the API JSON.\n\tgoplsAnalyzers := make(map[string]bool)\n\tvar api doc.API\n\tif err := json.Unmarshal([]byte(doc.JSON), &api); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, a := range api.Analyzers {\n\t\tgoplsAnalyzers[a.Name] = true\n\t}\n\n\t// Read vet's suite by parsing its help message.\n\tcmd := exec.Command(\"go\", \"tool\", \"vet\", \"help\")\n\tcmd.Stdout = new(strings.Builder)\n\tif err := cmd.Run(); err != nil {\n\t\tt.Fatalf(\"failed to run vet: %v\", err)\n\t}\n\tout := fmt.Sprint(cmd.Stdout)\n\t_, out, _ = strings.Cut(out, \"Registered analyzers:\\n\\n\")\n\tout, _, _ = strings.Cut(out, \"\\n\\n\")\n\tfor line := range strings.SplitSeq(out, \"\\n\") {\n\t\tname := strings.Fields(line)[0]\n\t\tif !goplsAnalyzers[name] {\n\t\t\tt.Errorf(\"gopls lacks vet analyzer %q\", name)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/telemetry/counterpath.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage telemetry\n\nimport \"strings\"\n\n// A CounterPath represents the components of a telemetry counter name.\n//\n// By convention, counter names follow the format path/to/counter:bucket. The\n// CounterPath holds the '/'-separated components of this path, along with a\n// final element representing the bucket.\n//\n// CounterPaths may be used to build up counters incrementally, such as when a\n// set of observed counters shared a common prefix, to be controlled by the\n// caller.\ntype CounterPath []string\n\n// FullName returns the counter name for the receiver.\nfunc (p CounterPath) FullName() string {\n\tif len(p) == 0 {\n\t\treturn \"\"\n\t}\n\tname := strings.Join([]string(p[:len(p)-1]), \"/\")\n\tif bucket := p[len(p)-1]; bucket != \"\" {\n\t\tname += \":\" + bucket\n\t}\n\treturn name\n}\n"
  },
  {
    "path": "gopls/internal/telemetry/counterpath_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage telemetry\n\nimport (\n\t\"testing\"\n)\n\n// TestCounterPath tests the formatting of various counter paths.\nfunc TestCounterPath(t *testing.T) {\n\ttests := []struct {\n\t\tpath CounterPath\n\t\twant string\n\t}{\n\t\t{\n\t\t\tpath: CounterPath{},\n\t\t\twant: \"\",\n\t\t},\n\t\t{\n\t\t\tpath: CounterPath{\"counter\"},\n\t\t\twant: \":counter\",\n\t\t},\n\t\t{\n\t\t\tpath: CounterPath{\"counter\", \"bucket\"},\n\t\t\twant: \"counter:bucket\",\n\t\t},\n\t\t{\n\t\t\tpath: CounterPath{\"path\", \"to\", \"counter\"},\n\t\t\twant: \"path/to:counter\",\n\t\t},\n\t\t{\n\t\t\tpath: CounterPath{\"multi\", \"component\", \"path\", \"bucket\"},\n\t\t\twant: \"multi/component/path:bucket\",\n\t\t},\n\t\t{\n\t\t\tpath: CounterPath{\"path\", \"\"},\n\t\t\twant: \"path\",\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tif got := tt.path.FullName(); got != tt.want {\n\t\t\tt.Errorf(\"CounterPath(%v).FullName() = %v, want %v\", tt.path, got, tt.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/telemetry/latency.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage telemetry\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/telemetry/counter\"\n)\n\n// latencyKey is used for looking up latency counters.\ntype latencyKey struct {\n\toperation, bucket string\n\tisError           bool\n}\n\nvar (\n\tlatencyBuckets = []struct {\n\t\tend  time.Duration\n\t\tname string\n\t}{\n\t\t{10 * time.Millisecond, \"<10ms\"},\n\t\t{50 * time.Millisecond, \"<50ms\"},\n\t\t{100 * time.Millisecond, \"<100ms\"},\n\t\t{200 * time.Millisecond, \"<200ms\"},\n\t\t{500 * time.Millisecond, \"<500ms\"},\n\t\t{1 * time.Second, \"<1s\"},\n\t\t{5 * time.Second, \"<5s\"},\n\t\t{24 * time.Hour, \"<24h\"},\n\t}\n\n\tlatencyCounterMu sync.Mutex\n\tlatencyCounters  = make(map[latencyKey]*counter.Counter) // lazily populated\n)\n\n// ForEachLatencyCounter runs the provided function for each current latency\n// counter measuring the given operation.\n//\n// Exported for testing.\nfunc ForEachLatencyCounter(operation string, isError bool, f func(*counter.Counter)) {\n\tlatencyCounterMu.Lock()\n\tdefer latencyCounterMu.Unlock()\n\n\tfor k, v := range latencyCounters {\n\t\tif k.operation == operation && k.isError == isError {\n\t\t\tf(v)\n\t\t}\n\t}\n}\n\n// getLatencyCounter returns the counter used to record latency of the given\n// operation in the given bucket.\nfunc getLatencyCounter(operation, bucket string, isError bool) *counter.Counter {\n\tlatencyCounterMu.Lock()\n\tdefer latencyCounterMu.Unlock()\n\n\tkey := latencyKey{operation, bucket, isError}\n\tc, ok := latencyCounters[key]\n\tif !ok {\n\t\tvar name string\n\t\tif isError {\n\t\t\tname = fmt.Sprintf(\"gopls/%s/error-latency:%s\", operation, bucket)\n\t\t} else {\n\t\t\tname = fmt.Sprintf(\"gopls/%s/latency:%s\", operation, bucket)\n\t\t}\n\t\tc = counter.New(name)\n\t\tlatencyCounters[key] = c\n\t}\n\treturn c\n}\n\n// StartLatencyTimer starts a timer for the gopls operation with the given\n// name, and returns a func to stop the timer and record the latency sample.\n//\n// If the context provided to the resulting func is done, no observation is\n// recorded.\nfunc StartLatencyTimer(operation string) func(context.Context, error) {\n\tstart := time.Now()\n\treturn func(ctx context.Context, err error) {\n\t\tif errors.Is(ctx.Err(), context.Canceled) {\n\t\t\t// Ignore timing where the operation is cancelled, it may be influenced\n\t\t\t// by client behavior.\n\t\t\treturn\n\t\t}\n\t\tlatency := time.Since(start)\n\t\tbucketIdx := sort.Search(len(latencyBuckets), func(i int) bool {\n\t\t\tbucket := latencyBuckets[i]\n\t\t\treturn latency < bucket.end\n\t\t})\n\t\tif bucketIdx < len(latencyBuckets) { // ignore latency longer than a day :)\n\t\t\tbucketName := latencyBuckets[bucketIdx].name\n\t\t\tgetLatencyCounter(operation, bucketName, err != nil).Inc()\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/telemetry/telemetry_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.21 && !openbsd && !js && !wasip1 && !solaris && !android && !386\n\npackage telemetry_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/telemetry/counter/countertest\" // requires go1.21+\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/telemetry\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\ttmp, err := os.MkdirTemp(\"\", \"gopls-telemetry-test-counters\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tcountertest.Open(tmp)\n\tcode := Main(m)\n\tos.RemoveAll(tmp) // ignore error (cleanup fails on Windows; golang/go#68243)\n\tos.Exit(code)\n}\n\nfunc TestTelemetry(t *testing.T) {\n\tvar (\n\t\tgoversion = \"\"\n\t\teditor    = \"vscode\" // We set ClientName(\"Visual Studio Code\") below.\n\t)\n\n\t// Run gopls once to determine the Go version.\n\tWithOptions(\n\t\tModes(Default),\n\t).Run(t, \"\", func(_ *testing.T, env *Env) {\n\t\tgoversion = strconv.Itoa(env.GoVersion())\n\t})\n\n\t// counters that should be incremented once per session\n\tsessionCounters := []*counter.Counter{\n\t\tcounter.New(\"gopls/client:\" + editor),\n\t\tcounter.New(\"gopls/goversion:1.\" + goversion),\n\t\tcounter.New(\"fwd/vscode/linter:a\"),\n\t\tcounter.New(\"gopls/gotoolchain:local\"),\n\t}\n\tinitialCounts := make([]uint64, len(sessionCounters))\n\tfor i, c := range sessionCounters {\n\t\tcount, err := countertest.ReadCounter(c)\n\t\tif err != nil {\n\t\t\tcontinue // counter db not open, or counter not found\n\t\t}\n\t\tinitialCounts[i] = count\n\t}\n\n\t// Verify that a properly configured session gets notified of a bug on the\n\t// server.\n\tWithOptions(\n\t\tModes(Default), // must be in-process to receive the bug report below\n\t\tSettings{\"showBugReports\": true},\n\t\tClientName(\"Visual Studio Code\"),\n\t\tEnvVars{\n\t\t\t\"GOTOOLCHAIN\": \"local\", // so that the local counter is incremented\n\t\t},\n\t).Run(t, \"\", func(_ *testing.T, env *Env) {\n\t\tgoversion = strconv.Itoa(env.GoVersion())\n\t\taddForwardedCounters(env, []string{\"vscode/linter:a\"}, []int64{1})\n\t\tconst desc = \"got a bug\"\n\n\t\t// This will increment a counter named something like:\n\t\t//\n\t\t// `gopls/bug\n\t\t// golang.org/x/tools/gopls/internal/util/bug.report:+35\n\t\t// golang.org/x/tools/gopls/internal/util/bug.Report:=68\n\t\t// golang.org/x/tools/gopls/internal/telemetry_test.TestTelemetry.func2:+4\n\t\t// golang.org/x/tools/gopls/internal/test/integration.(*Runner).Run.func1:+87\n\t\t// testing.tRunner:+150\n\t\t// runtime.goexit:+0`\n\t\t//\n\t\tbug.Report(desc) // want a stack counter with the trace starting from here.\n\n\t\tenv.Await(ShownMessage(desc))\n\t})\n\n\t// gopls/editor:client\n\t// gopls/goversion:1.x\n\t// fwd/vscode/linter:a\n\t// gopls/gotoolchain:local\n\tfor i, c := range sessionCounters {\n\t\twant := initialCounts[i] + 1\n\t\tgot, err := countertest.ReadCounter(c)\n\t\tif err != nil || got != want {\n\t\t\tt.Errorf(\"ReadCounter(%q) = (%v, %v), want (%v, nil)\", c.Name(), got, err, want)\n\t\t\tt.Logf(\"Current timestamp = %v\", time.Now().UTC())\n\t\t}\n\t}\n\n\t// gopls/bug\n\tbugcount := bug.BugReportCount\n\tcounts, err := countertest.ReadStackCounter(bugcount)\n\tif err != nil {\n\t\tt.Fatalf(\"ReadStackCounter(bugreportcount) failed - %v\", err)\n\t}\n\tif len(counts) != 1 || !hasEntry(counts, t.Name(), 1) {\n\t\tt.Errorf(\"read stackcounter(%q) = (%#v, %v), want one entry\", \"gopls/bug\", counts, err)\n\t\tt.Logf(\"Current timestamp = %v\", time.Now().UTC())\n\t}\n}\n\nfunc TestSettingTelemetry(t *testing.T) {\n\t// counters that should be incremented by each session\n\tsessionCounters := []*counter.Counter{\n\t\tcounter.New(\"gopls/setting/diagnosticsDelay\"),\n\t\tcounter.New(\"gopls/setting/staticcheck:true\"),\n\t\tcounter.New(\"gopls/setting/noSemanticString:true\"),\n\t\tcounter.New(\"gopls/setting/analyses/deprecated:false\"),\n\t}\n\n\tinitialCounts := make([]uint64, len(sessionCounters))\n\tfor i, c := range sessionCounters {\n\t\tcount, err := countertest.ReadCounter(c)\n\t\tif err != nil {\n\t\t\tcontinue // counter db not open, or counter not found\n\t\t}\n\t\tinitialCounts[i] = count\n\t}\n\n\t// Run gopls.\n\tWithOptions(\n\t\tModes(Default),\n\t\tSettings{\n\t\t\t\"staticcheck\": true,\n\t\t\t\"analyses\": map[string]bool{\n\t\t\t\t\"deprecated\": false,\n\t\t\t},\n\t\t\t\"diagnosticsDelay\": \"0s\",\n\t\t\t\"noSemanticString\": true,\n\t\t},\n\t).Run(t, \"\", func(_ *testing.T, env *Env) {\n\t})\n\n\tfor i, c := range sessionCounters {\n\t\tcount, err := countertest.ReadCounter(c)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"ReadCounter(%q) failed: %v\", c.Name(), err)\n\t\t\tcontinue\n\t\t}\n\t\tif count <= initialCounts[i] {\n\t\t\tt.Errorf(\"ReadCounter(%q) = %d, want > %d\", c.Name(), count, initialCounts[i])\n\t\t}\n\t}\n}\n\nfunc addForwardedCounters(env *Env, names []string, values []int64) {\n\targs, err := command.MarshalArgs(command.AddTelemetryCountersArgs{\n\t\tNames: names, Values: values,\n\t})\n\tif err != nil {\n\t\tenv.TB.Fatal(err)\n\t}\n\tvar res error\n\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\tCommand:   command.AddTelemetryCounters.String(),\n\t\tArguments: args,\n\t}, &res)\n\tif res != nil {\n\t\tenv.TB.Errorf(\"%v failed - %v\", command.AddTelemetryCounters, res)\n\t}\n}\n\nfunc hasEntry(counts map[string]uint64, pattern string, want uint64) bool {\n\tfor k, v := range counts {\n\t\tif strings.Contains(k, pattern) && v == want {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc TestLatencyCounter(t *testing.T) {\n\tconst operation = \"TestLatencyCounter\" // a unique operation name\n\n\tstop := telemetry.StartLatencyTimer(operation)\n\tstop(context.Background(), nil)\n\n\tfor isError, want := range map[bool]uint64{false: 1, true: 0} {\n\t\tif got := totalLatencySamples(t, operation, isError); got != want {\n\t\t\tt.Errorf(\"totalLatencySamples(operation=%v, isError=%v) = %d, want %d\", operation, isError, got, want)\n\t\t}\n\t}\n}\n\nfunc TestLatencyCounter_Error(t *testing.T) {\n\tconst operation = \"TestLatencyCounter_Error\" // a unique operation name\n\n\tstop := telemetry.StartLatencyTimer(operation)\n\tstop(context.Background(), errors.New(\"bad\"))\n\n\tfor isError, want := range map[bool]uint64{false: 0, true: 1} {\n\t\tif got := totalLatencySamples(t, operation, isError); got != want {\n\t\t\tt.Errorf(\"totalLatencySamples(operation=%v, isError=%v) = %d, want %d\", operation, isError, got, want)\n\t\t}\n\t}\n}\n\nfunc TestLatencyCounter_Cancellation(t *testing.T) {\n\tconst operation = \"TestLatencyCounter_Cancellation\"\n\n\tstop := telemetry.StartLatencyTimer(operation)\n\tctx, cancel := context.WithCancel(context.Background())\n\tcancel()\n\tstop(ctx, nil)\n\n\tfor isError, want := range map[bool]uint64{false: 0, true: 0} {\n\t\tif got := totalLatencySamples(t, operation, isError); got != want {\n\t\t\tt.Errorf(\"totalLatencySamples(operation=%v, isError=%v) = %d, want %d\", operation, isError, got, want)\n\t\t}\n\t}\n}\n\nfunc totalLatencySamples(t *testing.T, operation string, isError bool) uint64 {\n\tvar total uint64\n\ttelemetry.ForEachLatencyCounter(operation, isError, func(c *counter.Counter) {\n\t\tcount, err := countertest.ReadCounter(c)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"ReadCounter(%s) failed: %v\", c.Name(), err)\n\t\t} else {\n\t\t\ttotal += count\n\t\t}\n\t})\n\treturn total\n}\n\nfunc TestLatencyInstrumentation(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.test/a\ngo 1.18\n-- a.go --\npackage a\n\nfunc _() {\n\tx := 0\n\t_ = x\n}\n`\n\n\t// Verify that a properly configured session gets notified of a bug on the\n\t// server.\n\tWithOptions(\n\t\tModes(Default), // must be in-process to receive the bug report below\n\t).Run(t, files, func(_ *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tbefore := totalLatencySamples(t, \"completion\", false)\n\t\tloc := env.RegexpSearch(\"a.go\", \"()x\")\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tenv.Completion(loc)\n\t\t}\n\t\tafter := totalLatencySamples(t, \"completion\", false)\n\t\tif after-before < 10 {\n\t\t\tt.Errorf(\"after 10 completions, completion counter went from %d to %d\", before, after)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/template/completion.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/scanner\"\n\tgotoken \"go/token\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// information needed for completion\ntype completer struct {\n\tp      *parsed\n\tpos    protocol.Position\n\toffset int // offset of the start of the Token\n\tctx    protocol.CompletionContext\n\tsyms   map[string]symbol\n}\n\nfunc Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pos protocol.Position, context protocol.CompletionContext) (*protocol.CompletionList, error) {\n\tall := parseSet(snapshot.Templates())\n\tvar start int // the beginning of the Token (completed or not)\n\tsyms := make(map[string]symbol)\n\tvar p *parsed\n\tfor uri, fc := range all.files {\n\t\t// collect symbols from all template files\n\t\tfilterSyms(syms, fc.symbols)\n\t\tif uri.Path() != fh.URI().Path() {\n\t\t\tcontinue\n\t\t}\n\t\toffset, err := enclosingTokenStart(fc, pos)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tstart = offset\n\t\tp = fc\n\t}\n\tif p == nil {\n\t\t// this cannot happen unless the search missed a template file\n\t\treturn nil, fmt.Errorf(\"%s not found\", fh.Identity().URI.Path())\n\t}\n\tc := completer{\n\t\tp:      p,\n\t\tpos:    pos,\n\t\toffset: start + len(lbraces),\n\t\tctx:    context,\n\t\tsyms:   syms,\n\t}\n\treturn c.complete()\n}\n\nfunc filterSyms(syms map[string]symbol, ns []symbol) {\n\tfor _, xsym := range ns {\n\t\tswitch xsym.kind {\n\t\tcase protocol.Method, protocol.Package, protocol.Boolean, protocol.Namespace,\n\t\t\tprotocol.Function:\n\t\t\tsyms[xsym.name] = xsym // we don't care which symbol we get\n\t\tcase protocol.Variable:\n\t\t\tif xsym.name != \"dot\" {\n\t\t\t\tsyms[xsym.name] = xsym\n\t\t\t}\n\t\tcase protocol.Constant:\n\t\t\tif xsym.name == \"nil\" {\n\t\t\t\tsyms[xsym.name] = xsym\n\t\t\t}\n\t\t}\n\t}\n}\n\n// enclosingTokenStart returns the start offset of the enclosing token.\n// A (-1, non-nil) result indicates \"no enclosing token\".\nfunc enclosingTokenStart(fc *parsed, pos protocol.Position) (int, error) {\n\t// pos is the pos-th character. if the cursor is at the beginning\n\t// of the file, pos is 0. That is, we've only seen characters before pos\n\t// 1. pos might be in a Token, return tk.Start\n\t// 2. pos might be after an elided but before a Token, return elided\n\t// 3. return -1 for false\n\toffset, err := fc.mapper.PositionOffset(pos)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// TODO: opt: this could be a binary search, as the tokens are ordered\n\tfor _, tk := range fc.tokens {\n\t\tif tk.start+len(lbraces) <= offset && offset+len(rbraces) <= tk.end {\n\t\t\treturn tk.start, nil\n\t\t}\n\t}\n\n\tfor _, x := range fc.elided {\n\t\tif x+len(lbraces) > offset {\n\t\t\t// fc.elided is sorted, and x is the position where a '{{' was replaced\n\t\t\t// by '  '. We consider only cases where the replaced {{ is to the left\n\t\t\t// of the cursor.\n\t\t\tbreak\n\t\t}\n\t\t// If the interval [x,offset] does not contain Left or Right\n\t\t// then provide completions. (do we need the test for Right?)\n\t\tif !bytes.Contains(fc.buf[x:offset], lbraces) && !bytes.Contains(fc.buf[x:offset], rbraces) {\n\t\t\treturn x, nil\n\t\t}\n\t}\n\treturn -1, fmt.Errorf(\"no token enclosing %d\", pos)\n}\n\nvar (\n\tkeywords = []string{\"if\", \"with\", \"else\", \"block\", \"range\", \"template\", \"end}}\", \"end\"}\n\tglobals  = []string{\"and\", \"call\", \"html\", \"index\", \"slice\", \"js\", \"len\", \"not\", \"or\",\n\t\t\"urlquery\", \"printf\", \"println\", \"print\", \"eq\", \"ne\", \"le\", \"lt\", \"ge\", \"gt\"}\n)\n\n// find the completions. start is the offset of either the Token enclosing pos, or where\n// the incomplete token starts.\n// The error return is always nil.\nfunc (c *completer) complete() (*protocol.CompletionList, error) {\n\tans := &protocol.CompletionList{IsIncomplete: true, Items: []protocol.CompletionItem{}}\n\tstart, err := c.p.mapper.PositionOffset(c.pos)\n\tif err != nil {\n\t\treturn ans, err\n\t}\n\tsofar := c.p.buf[c.offset:start]\n\tif len(sofar) == 0 || sofar[len(sofar)-1] == ' ' || sofar[len(sofar)-1] == '\\t' {\n\t\treturn ans, nil\n\t}\n\t// sofar could be parsed by either c.analyzer() or scan(). The latter is precise\n\t// and slower, but fast enough\n\twords := scan(sofar)\n\t// 1. if pattern starts $, show variables\n\t// 2. if pattern starts ., show methods (and . by itself?)\n\t// 3. if len(words) == 1, show firstWords (but if it were a |, show functions and globals)\n\t// 4. ...? (parenthetical expressions, arguments, ...) (packages, namespaces, nil?)\n\tif len(words) == 0 {\n\t\treturn nil, nil // if this happens, why were we called?\n\t}\n\tpattern := words[len(words)-1]\n\tif pattern[0] == '$' {\n\t\t// should we also return a raw \"$\"?\n\t\tfor _, s := range c.syms {\n\t\t\tif s.kind == protocol.Variable && weakMatch(s.name, pattern) > 0 {\n\t\t\t\tans.Items = append(ans.Items, protocol.CompletionItem{\n\t\t\t\t\tLabel:  s.name,\n\t\t\t\t\tKind:   protocol.VariableCompletion,\n\t\t\t\t\tDetail: \"Variable\",\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn ans, nil\n\t}\n\tif pattern[0] == '.' {\n\t\tfor _, s := range c.syms {\n\t\t\tif s.kind == protocol.Method && weakMatch(\".\"+s.name, pattern) > 0 {\n\t\t\t\tans.Items = append(ans.Items, protocol.CompletionItem{\n\t\t\t\t\tLabel:  s.name,\n\t\t\t\t\tKind:   protocol.MethodCompletion,\n\t\t\t\t\tDetail: \"Method/member\",\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn ans, nil\n\t}\n\t// could we get completion attempts in strings or numbers, and if so, do we care?\n\t// globals\n\tfor _, kw := range globals {\n\t\tif weakMatch(kw, pattern) != 0 {\n\t\t\tans.Items = append(ans.Items, protocol.CompletionItem{\n\t\t\t\tLabel:  kw,\n\t\t\t\tKind:   protocol.KeywordCompletion,\n\t\t\t\tDetail: \"Function\",\n\t\t\t})\n\t\t}\n\t}\n\t// and functions\n\tfor _, s := range c.syms {\n\t\tif s.kind == protocol.Function && weakMatch(s.name, pattern) != 0 {\n\t\t\tans.Items = append(ans.Items, protocol.CompletionItem{\n\t\t\t\tLabel:  s.name,\n\t\t\t\tKind:   protocol.FunctionCompletion,\n\t\t\t\tDetail: \"Function\",\n\t\t\t})\n\t\t}\n\t}\n\t// keywords if we're at the beginning\n\tif len(words) <= 1 || len(words[len(words)-2]) == 1 && words[len(words)-2][0] == '|' {\n\t\tfor _, kw := range keywords {\n\t\t\tif weakMatch(kw, pattern) != 0 {\n\t\t\t\tans.Items = append(ans.Items, protocol.CompletionItem{\n\t\t\t\t\tLabel:  kw,\n\t\t\t\t\tKind:   protocol.KeywordCompletion,\n\t\t\t\t\tDetail: \"keyword\",\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn ans, nil\n}\n\n// version of c.analyze that uses go/scanner.\nfunc scan(buf []byte) []string {\n\tfset := gotoken.NewFileSet()\n\tfp := fset.AddFile(\"\", -1, len(buf))\n\tvar sc scanner.Scanner\n\tsc.Init(fp, buf, func(pos gotoken.Position, msg string) {}, scanner.ScanComments)\n\tans := make([]string, 0, 10) // preallocating gives a measurable savings\n\tfor {\n\t\t_, tok, lit := sc.Scan() // tok is an int\n\t\tif tok == gotoken.EOF {\n\t\t\tbreak // done\n\t\t} else if tok == gotoken.SEMICOLON && lit == \"\\n\" {\n\t\t\tcontinue // don't care, but probably can't happen\n\t\t} else if tok == gotoken.PERIOD {\n\t\t\tans = append(ans, \".\") // lit is empty\n\t\t} else if tok == gotoken.IDENT && len(ans) > 0 && ans[len(ans)-1] == \".\" {\n\t\t\tans[len(ans)-1] = \".\" + lit\n\t\t} else if tok == gotoken.IDENT && len(ans) > 0 && ans[len(ans)-1] == \"$\" {\n\t\t\tans[len(ans)-1] = \"$\" + lit\n\t\t} else if lit != \"\" {\n\t\t\tans = append(ans, lit)\n\t\t}\n\t}\n\treturn ans\n}\n\n// pattern is what the user has typed\nfunc weakMatch(choice, pattern string) float64 {\n\tlower := strings.ToLower(choice)\n\t// for now, use only lower-case everywhere\n\tpattern = strings.ToLower(pattern)\n\t// The first char has to match\n\tif pattern[0] != lower[0] {\n\t\treturn 0\n\t}\n\t// If they start with ., then the second char has to match\n\tfrom := 1\n\tif pattern[0] == '.' {\n\t\tif len(pattern) < 2 {\n\t\t\treturn 1 // pattern just a ., so it matches\n\t\t}\n\t\tif pattern[1] != lower[1] {\n\t\t\treturn 0\n\t\t}\n\t\tfrom = 2\n\t}\n\t// check that all the characters of pattern occur as a subsequence of choice\n\ti, j := from, from\n\tfor ; i < len(lower) && j < len(pattern); j++ {\n\t\tif pattern[j] == lower[i] {\n\t\t\ti++\n\t\t\tif i >= len(lower) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t}\n\t}\n\tif j < len(pattern) {\n\t\treturn 0\n\t}\n\treturn 1\n}\n"
  },
  {
    "path": "gopls/internal/template/completion_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"log\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc init() {\n\tlog.SetFlags(log.Lshortfile)\n}\n\ntype tparse struct {\n\tmarked string   // ^ shows where to ask for completions. (The user just typed the following character.)\n\twanted []string // expected completions; nil => no enclosing token\n}\n\n// Test completions in templates that parse enough (if completion needs symbols)\n// Seen characters up to the ^\nfunc TestParsed(t *testing.T) {\n\tfor _, test := range []tparse{\n\t\t{\"{{x}}{{12. xx^\", nil}, // https://github.com/golang/go/issues/50430\n\t\t{`<table class=\"chroma\" data-new-comment-url=\"{{if $.PageIsPullFiles}}{{$.Issue.HTMLURL}}/files/reviews/new_comment{{else}}{{$.CommitHTML}}/new_comment^{{end}}\">`, nil},\n\t\t{\"{{i^f}}\", []string{\"index\", \"if\"}},\n\t\t{\"{{if .}}{{e^ {{end}}\", []string{\"eq\", \"end}}\", \"else\", \"end\"}},\n\t\t{\"{{foo}}{{f^\", []string{\"foo\"}},\n\t\t{\"{{$^}}\", []string{\"$\"}},\n\t\t{\"{{$x:=4}}{{$^\", []string{\"$x\"}},\n\t\t{\"{{$x:=4}}{{$ ^ \", []string{}},\n\t\t{\"{{len .Modified}}{{.^Mo\", []string{\"Modified\"}},\n\t\t{\"{{len .Modified}}{{.mf^\", []string{\"Modified\"}},\n\t\t{\"{{$^ }}\", []string{\"$\"}},\n\t\t{\"{{$a =3}}{{$^\", []string{\"$a\"}},\n\t\t// .two is not good here: fix someday\n\t\t{`{{.Modified}}{{.^{{if $.one.two}}xxx{{end}}`, []string{\"Modified\", \"one\", \"two\"}},\n\t\t{`{{.Modified}}{{.o^{{if $.one.two}}xxx{{end}}`, []string{\"one\"}},\n\t\t{\"{{.Modiifed}}{{.one.t^{{if $.one.two}}xxx{{end}}\", []string{\"two\"}},\n\t\t{`{{block \"foo\" .}}{{i^`, []string{\"index\", \"if\"}},\n\t\t{\"{{in^{{Internal}}\", []string{\"index\", \"Internal\", \"if\"}},\n\t\t// simple number has no completions\n\t\t{\"{{4^e\", []string{}},\n\t\t// simple string has no completions\n\t\t{\"{{`e^\", []string{}},\n\t\t{\"{{`No i^\", []string{}}, // example of why go/scanner is used\n\t\t{\"{{xavier}}{{12. x^\", []string{\"xavier\"}},\n\t} {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tvar got []string\n\t\t\tif c := testCompleter(t, test); c != nil {\n\t\t\t\tans, _ := c.complete()\n\t\t\t\tfor _, a := range ans.Items {\n\t\t\t\t\tgot = append(got, a.Label)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(got) != len(test.wanted) {\n\t\t\t\tt.Fatalf(\"%q: got %q, wanted %q %d,%d\", test.marked, got, test.wanted, len(got), len(test.wanted))\n\t\t\t}\n\t\t\tsort.Strings(test.wanted)\n\t\t\tsort.Strings(got)\n\t\t\tfor i := 0; i < len(got); i++ {\n\t\t\t\tif test.wanted[i] != got[i] {\n\t\t\t\t\tt.Fatalf(\"%q at %d: got %v, wanted %v\", test.marked, i, got, test.wanted)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc testCompleter(t *testing.T, tx tparse) *completer {\n\t// seen chars up to ^\n\toffset := strings.Index(tx.marked, \"^\")\n\tbuf := strings.Replace(tx.marked, \"^\", \"\", 1)\n\tp := parseBuffer(\"\", []byte(buf))\n\tif p.parseErr != nil {\n\t\tt.Logf(\"%q: %v\", tx.marked, p.parseErr)\n\t}\n\tpos, err := p.mapper.OffsetPosition(offset)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tstart, err := enclosingTokenStart(p, pos)\n\tif err != nil {\n\t\tif start == -1 {\n\t\t\treturn nil // no enclosing token\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\tsyms := make(map[string]symbol)\n\tfilterSyms(syms, p.symbols)\n\treturn &completer{\n\t\tp:      p,\n\t\tpos:    pos,\n\t\toffset: start + len(lbraces),\n\t\tctx:    protocol.CompletionContext{TriggerKind: protocol.Invoked},\n\t\tsyms:   syms,\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/template/highlight.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc Highlight(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.DocumentHighlight, error) {\n\tbuf, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tp := parseBuffer(fh.URI(), buf)\n\tstart, end, err := p.mapper.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif p.parseErr == nil {\n\t\tfor _, s := range p.symbols {\n\t\t\tif s.start <= start && end < s.start+s.len {\n\t\t\t\treturn markSymbols(p, s)\n\t\t\t}\n\t\t}\n\t}\n\n\t// these tokens exist whether or not there was a parse error\n\t// (symbols require a successful parse)\n\tfor _, tok := range p.tokens {\n\t\tif tok.start <= start && end < tok.end {\n\t\t\twordAt := wordAt(p.buf, start)\n\t\t\tif len(wordAt) > 0 {\n\t\t\t\treturn markWordInToken(p, wordAt)\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO: find the 'word' at pos, etc: someday\n\t// until then we get the default action, which doesn't respect word boundaries\n\treturn nil, nil\n}\n\nfunc markSymbols(p *parsed, sym symbol) ([]protocol.DocumentHighlight, error) {\n\tvar ans []protocol.DocumentHighlight\n\tfor _, s := range p.symbols {\n\t\tif s.name == sym.name {\n\t\t\tkind := protocol.Read\n\t\t\tif s.vardef {\n\t\t\t\tkind = protocol.Write\n\t\t\t}\n\t\t\trng, err := p.mapper.OffsetRange(s.offsets())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tans = append(ans, protocol.DocumentHighlight{\n\t\t\t\tRange: rng,\n\t\t\t\tKind:  kind,\n\t\t\t})\n\t\t}\n\t}\n\treturn ans, nil\n}\n\n// A token is {{...}}, and this marks words in the token that equal the give word\nfunc markWordInToken(p *parsed, wordAt string) ([]protocol.DocumentHighlight, error) {\n\tvar ans []protocol.DocumentHighlight\n\tpat, err := regexp.Compile(fmt.Sprintf(`\\b%s\\b`, wordAt))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%q: unmatchable word (%v)\", wordAt, err)\n\t}\n\tfor _, tok := range p.tokens {\n\t\tmatches := pat.FindAllIndex(p.buf[tok.start:tok.end], -1)\n\t\tfor _, match := range matches {\n\t\t\trng, err := p.mapper.OffsetRange(match[0], match[1])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tans = append(ans, protocol.DocumentHighlight{\n\t\t\t\tRange: rng,\n\t\t\t\tKind:  protocol.Text,\n\t\t\t})\n\t\t}\n\t}\n\treturn ans, nil\n}\n\n// wordAt returns the word the cursor is in (meaning in or just before)\nfunc wordAt(buf []byte, pos int) string {\n\tif pos >= len(buf) {\n\t\treturn \"\"\n\t}\n\tafter := moreRe.Find(buf[pos:])\n\tif len(after) == 0 {\n\t\treturn \"\" // end of the word\n\t}\n\tgot := wordRe.Find(buf[:pos+len(after)])\n\treturn string(got)\n}\n\nvar (\n\twordRe = regexp.MustCompile(`[$]?\\w+$`)\n\tmoreRe = regexp.MustCompile(`^[$]?\\w+`)\n)\n"
  },
  {
    "path": "gopls/internal/template/implementations.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/semtok\"\n)\n\n// line number (1-based) and message\nvar errRe = regexp.MustCompile(`template.*:(\\d+): (.*)`)\n\n// Diagnostics returns parse errors. There is only one per file.\n// The errors are not always helpful. For instance { {end}}\n// will likely point to the end of the file.\nfunc Diagnostics(snapshot *cache.Snapshot) map[protocol.DocumentURI][]*cache.Diagnostic {\n\tdiags := make(map[protocol.DocumentURI][]*cache.Diagnostic)\n\tfor uri, fh := range snapshot.Templates() {\n\t\tdiags[uri] = diagnoseOne(fh)\n\t}\n\treturn diags\n}\n\nfunc diagnoseOne(fh file.Handle) []*cache.Diagnostic {\n\t// no need for skipTemplate check, as Diagnose is called on the\n\t// snapshot's template files\n\tbuf, err := fh.Content()\n\tif err != nil {\n\t\t// TODO: Is a Diagnostic with no Range useful? event.Error also?\n\t\tmsg := fmt.Sprintf(\"failed to read %s (%v)\", fh.URI().Path(), err)\n\t\treturn []*cache.Diagnostic{{\n\t\t\tMessage:  msg,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tURI:      fh.URI(),\n\t\t\tSource:   cache.TemplateError,\n\t\t}}\n\t}\n\tp := parseBuffer(fh.URI(), buf)\n\tif p.parseErr == nil {\n\t\treturn nil\n\t}\n\n\terrorf := func(format string, args ...any) []*cache.Diagnostic {\n\t\tmsg := fmt.Sprintf(\"malformed template error %q: %s\",\n\t\t\tp.parseErr.Error(),\n\t\t\tfmt.Sprintf(format, args...))\n\t\trng, err := p.mapper.OffsetRange(0, 1) // first UTF-16 code\n\t\tif err != nil {\n\t\t\trng = protocol.Range{} // start of file\n\t\t}\n\t\treturn []*cache.Diagnostic{{\n\t\t\tMessage:  msg,\n\t\t\tSeverity: protocol.SeverityError,\n\t\t\tRange:    rng,\n\t\t\tURI:      fh.URI(),\n\t\t\tSource:   cache.TemplateError,\n\t\t}}\n\t}\n\n\t// errors look like `template: :40: unexpected \"}\" in operand`\n\t// so the string needs to be parsed\n\tmatches := errRe.FindStringSubmatch(p.parseErr.Error())\n\tif len(matches) != 3 {\n\t\treturn errorf(\"expected 3 matches, got %d (%v)\", len(matches), matches)\n\t}\n\tlineno, err := strconv.Atoi(matches[1])\n\tif err != nil {\n\t\treturn errorf(\"couldn't convert %q to int, %v\", matches[1], err)\n\t}\n\tmsg := matches[2]\n\n\t// Compute the range for the whole (1-based) line.\n\trng, err := lineRange(p.mapper, lineno)\n\tif err != nil {\n\t\treturn errorf(\"invalid position: %v\", err)\n\t}\n\n\treturn []*cache.Diagnostic{{\n\t\tMessage:  msg,\n\t\tSeverity: protocol.SeverityError,\n\t\tRange:    rng,\n\t\tSource:   cache.TemplateError,\n\t}}\n}\n\n// Definition finds the definitions of the symbol at loc. It\n// does not understand scoping (if any) in templates. This code is\n// for definitions, type definitions, and implementations.\n// Results only for variables and templates.\nfunc Definition(snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {\n\tx, _, err := symAtRange(fh, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsym := x.name\n\tans := []protocol.Location{}\n\t// PJW: this is probably a pattern to abstract\n\ta := parseSet(snapshot.Templates())\n\tfor _, p := range a.files {\n\t\tfor _, s := range p.symbols {\n\t\t\tif !s.vardef || s.name != sym {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tloc, err := p.mapper.OffsetLocation(s.offsets())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tans = append(ans, loc)\n\t\t}\n\t}\n\treturn ans, nil\n}\n\nfunc Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (*protocol.Hover, error) {\n\tsym, p, err := symAtRange(fh, rng)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar value string\n\tswitch sym.kind {\n\tcase protocol.Function:\n\t\tvalue = fmt.Sprintf(\"function: %s\", sym.name)\n\tcase protocol.Variable:\n\t\tvalue = fmt.Sprintf(\"variable: %s\", sym.name)\n\tcase protocol.Constant:\n\t\tvalue = fmt.Sprintf(\"constant %s\", sym.name)\n\tcase protocol.Method: // field or method\n\t\tvalue = fmt.Sprintf(\"%s: field or method\", sym.name)\n\tcase protocol.Package: // template use, template def (PJW: do we want two?)\n\t\tvalue = fmt.Sprintf(\"template %s\\n(add definition)\", sym.name)\n\tcase protocol.Namespace:\n\t\tvalue = fmt.Sprintf(\"template %s defined\", sym.name)\n\tcase protocol.Number:\n\t\tvalue = \"number\"\n\tcase protocol.String:\n\t\tvalue = \"string\"\n\tcase protocol.Boolean:\n\t\tvalue = \"boolean\"\n\tdefault:\n\t\tvalue = fmt.Sprintf(\"oops, sym=%#v\", sym)\n\t}\n\n\tsymRng, err := p.mapper.OffsetRange(sym.offsets())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &protocol.Hover{\n\t\tRange: symRng,\n\t\tContents: protocol.MarkupContent{\n\t\t\tKind:  protocol.Markdown,\n\t\t\tValue: value,\n\t\t},\n\t}, nil\n}\n\nfunc References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, params *protocol.ReferenceParams) ([]protocol.Location, error) {\n\tsym, _, err := symAtRange(fh, params.Range)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif sym.name == \"\" {\n\t\treturn nil, fmt.Errorf(\"no symbol at position\")\n\t}\n\tans := []protocol.Location{}\n\n\ta := parseSet(snapshot.Templates())\n\tfor _, p := range a.files {\n\t\tfor _, s := range p.symbols {\n\t\t\tif s.name != sym.name {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif s.vardef && !params.Context.IncludeDeclaration {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tloc, err := p.mapper.OffsetLocation(s.offsets())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tans = append(ans, loc)\n\t\t}\n\t}\n\t// TODO: do these need to be sorted? (a.files is a map)\n\treturn ans, nil\n}\n\nfunc SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, spn protocol.DocumentURI) (*protocol.SemanticTokens, error) {\n\tfh, err := snapshot.ReadFile(ctx, spn)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbuf, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tp := parseBuffer(fh.URI(), buf)\n\n\tvar items []semtok.Token\n\tfor _, t := range p.tokens {\n\t\tif t.start == t.end {\n\t\t\tcontinue // vscode doesn't like 0-length tokens\n\t\t}\n\t\tpos, err := p.mapper.OffsetPosition(t.start)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// TODO(adonovan): don't ignore the rng restriction, if any.\n\t\titems = append(items, semtok.Token{\n\t\t\tLine:  pos.Line,\n\t\t\tStart: pos.Character,\n\t\t\tLen:   uint32(protocol.UTF16Len(p.buf[t.start:t.end])),\n\t\t\tType:  semtok.TokMacro,\n\t\t})\n\t}\n\treturn &protocol.SemanticTokens{\n\t\tData: semtok.Encode(items, nil, nil),\n\t\t// for small cache, some day. for now, the LSP client ignores this\n\t\t// (that is, when the LSP client starts returning these, we can cache)\n\t\tResultID: fmt.Sprintf(\"%v\", time.Now()),\n\t}, nil\n}\n\n// TODO: still need to do rename, etc\n\nfunc symAtRange(fh file.Handle, rng protocol.Range) (*symbol, *parsed, error) {\n\tbuf, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tp := parseBuffer(fh.URI(), buf)\n\tstart, end, err := p.mapper.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tvar syms []symbol\n\tfor _, s := range p.symbols {\n\t\tif s.start <= start && end <= s.start+s.len {\n\t\t\tsyms = append(syms, s)\n\t\t}\n\t}\n\tif len(syms) == 0 {\n\t\treturn nil, p, fmt.Errorf(\"no symbol found\")\n\t}\n\tsym := syms[0]\n\treturn &sym, p, nil\n}\n"
  },
  {
    "path": "gopls/internal/template/parse.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package template contains code for dealing with templates\npackage template\n\n// template files are small enough that the code reprocesses them each time\n// this may be a bad choice for projects with lots of template files.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"regexp\"\n\t\"sort\"\n\t\"text/template\"\n\t\"text/template/parse\"\n\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nvar (\n\tlbraces = []byte(\"{{\")\n\trbraces = []byte(\"}}\")\n)\n\ntype parsed struct {\n\tbuf    []byte // contents\n\tmapper *protocol.Mapper\n\telided []int // offsets where lbraces was replaced by blanks\n\n\t// tokens are matched lbraces-rbraces pairs, computed before trying to parse\n\ttokens []token\n\n\t// result of parsing\n\tnamed    []*template.Template // the template and embedded templates\n\tparseErr error\n\tsymbols  []symbol\n\tstack    []parse.Node // used while computing symbols\n}\n\n// A token is a single {{...}}.\ntype token struct {\n\tstart, end int // 0-based byte offset from start of template\n}\n\n// set contains the Parse of all the template files\ntype set struct {\n\tfiles map[protocol.DocumentURI]*parsed\n}\n\n// parseSet returns the set of the snapshot's tmpl files\n// (maybe cache these, but then avoiding import cycles needs code rearrangements)\n//\n// TODO(adonovan): why doesn't parseSet return an error?\nfunc parseSet(tmpls map[protocol.DocumentURI]file.Handle) *set {\n\tall := make(map[protocol.DocumentURI]*parsed)\n\tfor uri, fh := range tmpls {\n\t\tbuf, err := fh.Content()\n\t\tif err != nil {\n\t\t\t// TODO(pjw): decide what to do with these errors\n\t\t\tlog.Printf(\"failed to read %s (%v)\", fh.URI().Path(), err)\n\t\t\tcontinue\n\t\t}\n\t\tall[uri] = parseBuffer(uri, buf)\n\t}\n\treturn &set{files: all}\n}\n\nfunc parseBuffer(uri protocol.DocumentURI, buf []byte) *parsed {\n\tans := &parsed{\n\t\tbuf:    buf,\n\t\tmapper: protocol.NewMapper(uri, buf),\n\t}\n\tif len(buf) == 0 {\n\t\treturn ans\n\t}\n\tans.setTokens() // ans.buf may be a new []byte\n\tt, err := template.New(\"\").Parse(string(ans.buf))\n\tif err != nil {\n\t\tfuncs := make(template.FuncMap)\n\t\tfor t == nil && ans.parseErr == nil {\n\t\t\t// in 1.17 it may be possible to avoid getting this error\n\t\t\t//  template: :2: function \"foo\" not defined\n\t\t\tmatches := parseErrR.FindStringSubmatch(err.Error())\n\t\t\tif len(matches) == 2 {\n\t\t\t\t// suppress the error by giving it a function with the right name\n\t\t\t\tfuncs[matches[1]] = func() any { return nil }\n\t\t\t\tt, err = template.New(\"\").Funcs(funcs).Parse(string(ans.buf))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tans.parseErr = err // unfixed error\n\t\t\treturn ans\n\t\t}\n\t}\n\tans.named = t.Templates()\n\t// set the symbols\n\tfor _, t := range ans.named {\n\t\tans.stack = append(ans.stack, t.Root)\n\t\tans.findSymbols()\n\t\tif t.Name() != \"\" {\n\t\t\t// defining a template. The pos is just after {{define...}} (or {{block...}}?)\n\t\t\tat, sz := ans.findLiteralBefore(int(t.Root.Pos))\n\t\t\ts := symbol{start: at, len: sz, name: t.Name(), kind: protocol.Namespace, vardef: true}\n\t\t\tans.symbols = append(ans.symbols, s)\n\t\t}\n\t}\n\n\tsort.Slice(ans.symbols, func(i, j int) bool {\n\t\tleft, right := ans.symbols[i], ans.symbols[j]\n\t\tif left.start != right.start {\n\t\t\treturn left.start < right.start\n\t\t}\n\t\tif left.vardef != right.vardef {\n\t\t\treturn left.vardef\n\t\t}\n\t\treturn left.kind < right.kind\n\t})\n\treturn ans\n}\n\n// findLiteralBefore locates the first preceding string literal\n// returning its offset and length in buf or (-1, 0) if there is none.\n// Assume double-quoted string rather than backquoted string for now.\nfunc (p *parsed) findLiteralBefore(pos int) (int, int) {\n\tleft, right := -1, -1\n\tfor i := pos - 1; i >= 0; i-- {\n\t\tif p.buf[i] != '\"' {\n\t\t\tcontinue\n\t\t}\n\t\tif right == -1 {\n\t\t\tright = i\n\t\t\tcontinue\n\t\t}\n\t\tleft = i\n\t\tbreak\n\t}\n\tif left == -1 {\n\t\treturn -1, 0\n\t}\n\treturn left + 1, right - left - 1\n}\n\nvar (\n\tparseErrR = regexp.MustCompile(`template:.*function \"([^\"]+)\" not defined`)\n)\n\nfunc (p *parsed) setTokens() {\n\tconst (\n\t\t// InRaw and InString only occur inside an action (SeenLeft)\n\t\tStart = iota\n\t\tInRaw\n\t\tInString\n\t\tSeenLeft\n\t)\n\tstate := Start\n\tvar left, oldState int\n\tfor n := 0; n < len(p.buf); n++ {\n\t\tc := p.buf[n]\n\t\tswitch state {\n\t\tcase InRaw:\n\t\t\tif c == '`' {\n\t\t\t\tstate = oldState\n\t\t\t}\n\t\tcase InString:\n\t\t\tif c == '\"' && !isEscaped(p.buf[:n]) {\n\t\t\t\tstate = oldState\n\t\t\t}\n\t\tcase SeenLeft:\n\t\t\tif c == '`' {\n\t\t\t\toldState = state // it's SeenLeft, but a little clearer this way\n\t\t\t\tstate = InRaw\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c == '\"' {\n\t\t\t\toldState = state\n\t\t\t\tstate = InString\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif bytes.HasPrefix(p.buf[n:], rbraces) {\n\t\t\t\tright := n + len(rbraces)\n\t\t\t\ttok := token{start: left, end: right}\n\t\t\t\tp.tokens = append(p.tokens, tok)\n\t\t\t\tstate = Start\n\t\t\t}\n\t\t\t// If we see (unquoted) lbraces then the original left is probably the user\n\t\t\t// typing. Suppress the original left\n\t\t\tif bytes.HasPrefix(p.buf[n:], lbraces) {\n\t\t\t\tp.elideAt(left)\n\t\t\t\tleft = n\n\t\t\t\tn += len(lbraces) - 1 // skip the rest\n\t\t\t}\n\t\tcase Start:\n\t\t\tif bytes.HasPrefix(p.buf[n:], lbraces) {\n\t\t\t\tleft = n\n\t\t\t\tstate = SeenLeft\n\t\t\t\tn += len(lbraces) - 1 // skip the rest (avoids {{{ bug)\n\t\t\t}\n\t\t}\n\t}\n\t// this error occurs after typing {{ at the end of the file\n\tif state != Start {\n\t\t// Unclosed lbraces. remove the lbraces at left\n\t\tp.elideAt(left)\n\t}\n}\n\nfunc (p *parsed) elideAt(left int) {\n\tif p.elided == nil {\n\t\t// p.buf is the same buffer that v.Read() returns, so copy it.\n\t\t// (otherwise the next time it's parsed, elided information is lost)\n\t\tp.buf = bytes.Clone(p.buf)\n\t}\n\tfor i := range lbraces {\n\t\tp.buf[left+i] = ' '\n\t}\n\tp.elided = append(p.elided, left)\n}\n\n// isEscaped reports whether the byte after buf is escaped\nfunc isEscaped(buf []byte) bool {\n\tbackSlashes := 0\n\tfor j := len(buf) - 1; j >= 0 && buf[j] == '\\\\'; j-- {\n\t\tbackSlashes++\n\t}\n\treturn backSlashes%2 == 1\n}\n\n// lineRange returns the range for the entire specified (1-based) line.\nfunc lineRange(m *protocol.Mapper, line int) (protocol.Range, error) {\n\tposn := protocol.Position{Line: uint32(line - 1)}\n\n\t// start of line\n\tstart, err := m.PositionOffset(posn)\n\tif err != nil {\n\t\treturn protocol.Range{}, err\n\t}\n\n\t// end of line (or file)\n\tposn.Line++\n\tend := len(m.Content) // EOF\n\tif offset, err := m.PositionOffset(posn); err != nil {\n\t\tend = offset - len(\"\\n\")\n\t}\n\n\treturn m.OffsetRange(start, end)\n}\n\n// -- debugging --\n\nfunc (p *parsed) writeNode(w io.Writer, n parse.Node) {\n\twr := wrNode{p: p, w: w}\n\twr.writeNode(n, \"\")\n}\n\ntype wrNode struct {\n\tp *parsed\n\tw io.Writer\n}\n\nfunc (wr wrNode) writeNode(n parse.Node, indent string) {\n\tif n == nil {\n\t\treturn\n\t}\n\tat := func(pos parse.Pos) string {\n\t\toffset := int(pos)\n\t\tposn, err := wr.p.mapper.OffsetPosition(offset)\n\t\tif err != nil {\n\t\t\treturn fmt.Sprintf(\"<bad pos %d: %v>\", pos, err)\n\t\t}\n\t\treturn fmt.Sprintf(\"(%d)%v:%v\", pos, posn.Line, posn.Character)\n\t}\n\tswitch x := n.(type) {\n\tcase *parse.ActionNode:\n\t\tfmt.Fprintf(wr.w, \"%sActionNode at %s\\n\", indent, at(x.Pos))\n\t\twr.writeNode(x.Pipe, indent+\". \")\n\tcase *parse.BoolNode:\n\t\tfmt.Fprintf(wr.w, \"%sBoolNode at %s, %v\\n\", indent, at(x.Pos), x.True)\n\tcase *parse.BranchNode:\n\t\tfmt.Fprintf(wr.w, \"%sBranchNode at %s\\n\", indent, at(x.Pos))\n\t\twr.writeNode(x.Pipe, indent+\"Pipe. \")\n\t\twr.writeNode(x.List, indent+\"List. \")\n\t\twr.writeNode(x.ElseList, indent+\"Else. \")\n\tcase *parse.ChainNode:\n\t\tfmt.Fprintf(wr.w, \"%sChainNode at %s, %v\\n\", indent, at(x.Pos), x.Field)\n\tcase *parse.CommandNode:\n\t\tfmt.Fprintf(wr.w, \"%sCommandNode at %s, %d children\\n\", indent, at(x.Pos), len(x.Args))\n\t\tfor _, a := range x.Args {\n\t\t\twr.writeNode(a, indent+\". \")\n\t\t}\n\t//case *parse.CommentNode: // 1.16\n\tcase *parse.DotNode:\n\t\tfmt.Fprintf(wr.w, \"%sDotNode at %s\\n\", indent, at(x.Pos))\n\tcase *parse.FieldNode:\n\t\tfmt.Fprintf(wr.w, \"%sFieldNode at %s, %v\\n\", indent, at(x.Pos), x.Ident)\n\tcase *parse.IdentifierNode:\n\t\tfmt.Fprintf(wr.w, \"%sIdentifierNode at %s, %v\\n\", indent, at(x.Pos), x.Ident)\n\tcase *parse.IfNode:\n\t\tfmt.Fprintf(wr.w, \"%sIfNode at %s\\n\", indent, at(x.Pos))\n\t\twr.writeNode(&x.BranchNode, indent+\". \")\n\tcase *parse.ListNode:\n\t\tif x == nil {\n\t\t\treturn // nil BranchNode.ElseList\n\t\t}\n\t\tfmt.Fprintf(wr.w, \"%sListNode at %s, %d children\\n\", indent, at(x.Pos), len(x.Nodes))\n\t\tfor _, n := range x.Nodes {\n\t\t\twr.writeNode(n, indent+\". \")\n\t\t}\n\tcase *parse.NilNode:\n\t\tfmt.Fprintf(wr.w, \"%sNilNode at %s\\n\", indent, at(x.Pos))\n\tcase *parse.NumberNode:\n\t\tfmt.Fprintf(wr.w, \"%sNumberNode at %s, %s\\n\", indent, at(x.Pos), x.Text)\n\tcase *parse.PipeNode:\n\t\tif x == nil {\n\t\t\treturn // {{template \"xxx\"}}\n\t\t}\n\t\tfmt.Fprintf(wr.w, \"%sPipeNode at %s, %d vars, %d cmds, IsAssign:%v\\n\",\n\t\t\tindent, at(x.Pos), len(x.Decl), len(x.Cmds), x.IsAssign)\n\t\tfor _, d := range x.Decl {\n\t\t\twr.writeNode(d, indent+\"Decl. \")\n\t\t}\n\t\tfor _, c := range x.Cmds {\n\t\t\twr.writeNode(c, indent+\"Cmd. \")\n\t\t}\n\tcase *parse.RangeNode:\n\t\tfmt.Fprintf(wr.w, \"%sRangeNode at %s\\n\", indent, at(x.Pos))\n\t\twr.writeNode(&x.BranchNode, indent+\". \")\n\tcase *parse.StringNode:\n\t\tfmt.Fprintf(wr.w, \"%sStringNode at %s, %s\\n\", indent, at(x.Pos), x.Quoted)\n\tcase *parse.TemplateNode:\n\t\tfmt.Fprintf(wr.w, \"%sTemplateNode at %s, %s\\n\", indent, at(x.Pos), x.Name)\n\t\twr.writeNode(x.Pipe, indent+\". \")\n\tcase *parse.TextNode:\n\t\tfmt.Fprintf(wr.w, \"%sTextNode at %s, len %d\\n\", indent, at(x.Pos), len(x.Text))\n\tcase *parse.VariableNode:\n\t\tfmt.Fprintf(wr.w, \"%sVariableNode at %s, %v\\n\", indent, at(x.Pos), x.Ident)\n\tcase *parse.WithNode:\n\t\tfmt.Fprintf(wr.w, \"%sWithNode at %s\\n\", indent, at(x.Pos))\n\t\twr.writeNode(&x.BranchNode, indent+\". \")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/template/parse_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport \"testing\"\n\nfunc TestSymbols(t *testing.T) {\n\tfor i, test := range []struct {\n\t\tbuf       string\n\t\twantNamed int      // expected number of named templates\n\t\tsyms      []string // expected symbols (start, len, name, kind, def?)\n\t}{\n\t\t{`\n{{if (foo .X.Y)}}{{$A := \"hi\"}}{{.Z $A}}{{else}}\n{{$A.X 12}}\n{{foo (.X.Y) 23 ($A.Zü)}}\n{{end}}`, 1, []string{\n\t\t\t\"{7,3,foo,Function,false}\",\n\t\t\t\"{12,1,X,Method,false}\",\n\t\t\t\"{14,1,Y,Method,false}\",\n\t\t\t\"{21,2,$A,Variable,true}\",\n\t\t\t\"{26,4,,String,false}\",\n\t\t\t\"{35,1,Z,Method,false}\",\n\t\t\t\"{38,2,$A,Variable,false}\",\n\t\t\t\"{53,2,$A,Variable,false}\",\n\t\t\t\"{56,1,X,Method,false}\",\n\t\t\t\"{57,2,,Number,false}\",\n\t\t\t\"{64,3,foo,Function,false}\",\n\t\t\t\"{70,1,X,Method,false}\",\n\t\t\t\"{72,1,Y,Method,false}\",\n\t\t\t\"{75,2,,Number,false}\",\n\t\t\t\"{80,2,$A,Variable,false}\",\n\t\t\t\"{83,3,Zü,Method,false}\",\n\t\t\t\"{94,3,,Constant,false}\",\n\t\t}},\n\t\t{`{{define \"zzz\"}}{{.}}{{end}}\n{{template \"zzz\"}}`, 2, []string{\n\t\t\t\"{10,3,zzz,Namespace,true}\",\n\t\t\t\"{18,1,dot,Variable,false}\",\n\t\t\t\"{41,3,zzz,Package,false}\",\n\t\t}},\n\t\t{`{{block \"aaa\" foo}}b{{end}}`, 2, []string{\n\t\t\t\"{9,3,aaa,Namespace,true}\",\n\t\t\t\"{9,3,aaa,Package,false}\",\n\t\t\t\"{14,3,foo,Function,false}\",\n\t\t\t\"{19,1,,Constant,false}\",\n\t\t}},\n\t\t{\"\", 0, nil},\n\t\t{`{{/* this is\na comment */}}`, 1, nil}, // https://go.dev/issue/74635\n\t} {\n\t\tgot := parseBuffer(\"\", []byte(test.buf))\n\t\tif got.parseErr != nil {\n\t\t\tt.Error(got.parseErr)\n\t\t\tcontinue\n\t\t}\n\t\tif len(got.named) != test.wantNamed {\n\t\t\tt.Errorf(\"%d: got %d, expected %d\", i, len(got.named), test.wantNamed)\n\t\t}\n\t\tfor n, s := range got.symbols {\n\t\t\tif s.String() != test.syms[n] {\n\t\t\t\tt.Errorf(\"%d: got %s, expected %s\", i, s.String(), test.syms[n])\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestWordAt(t *testing.T) {\n\twant := []string{\"\", \"\", \"$A\", \"$A\", \"\", \"\", \"\", \"\", \"\", \"\",\n\t\t\"\", \"\", \"\", \"if\", \"if\", \"\", \"$A\", \"$A\", \"\", \"\",\n\t\t\"B\", \"\", \"\", \"end\", \"end\", \"end\", \"\", \"\", \"\"}\n\tbuf := []byte(\"{{$A := .}}{{if $A}}B{{end}}\")\n\tfor i := range buf {\n\t\tgot := wordAt(buf, i)\n\t\tif got != want[i] {\n\t\t\tt.Errorf(\"for %d, got %q, wanted %q\", i, got, want[i])\n\t\t}\n\t}\n}\n\nfunc TestQuotes(t *testing.T) {\n\tfor _, s := range []struct {\n\t\ttmpl      string\n\t\ttokCnt    int\n\t\telidedCnt int8\n\t}{\n\t\t{\"{{- /*comment*/ -}}\", 1, 0},\n\t\t{\"{{/*`\\ncomment\\n`*/}}\", 1, 0},\n\t\t//{\"{{foo\\nbar}}\\n\", 1, 0}, // this action spanning lines parses in 1.16\n\t\t{\"{{\\\"{{foo}}{{\\\"}}\", 1, 0},\n\t\t{\"{{\\n{{- when}}\", 1, 1},          // corrected\n\t\t{\"{{{{if .}}xx{{\\n{{end}}\", 2, 2}, // corrected\n\t} {\n\t\tp := parseBuffer(\"\", []byte(s.tmpl))\n\t\tif len(p.tokens) != s.tokCnt {\n\t\t\tt.Errorf(\"%#v: got %d tokens, expected %d\", s, len(p.tokens), s.tokCnt)\n\t\t}\n\t\tif p.parseErr != nil {\n\t\t\tt.Errorf(\"%q: %v\", string(p.buf), p.parseErr)\n\t\t}\n\t\tif len(p.elided) != int(s.elidedCnt) {\n\t\t\tt.Errorf(\"%#v: elided %d, expected %d\", s, len(p.elided), s.elidedCnt)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/template/symbols.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"text/template/parse\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// in local coordinates, to be translated to protocol.DocumentSymbol\ntype symbol struct {\n\tstart  int // 0-based byte offset, for sorting\n\tlen    int // of source, in bytes\n\tname   string\n\tkind   protocol.SymbolKind\n\tvardef bool // is this a variable definition?\n\t// do we care about selection range, or children?\n\t// no children yet, and selection range is the same as range\n}\n\nfunc (s symbol) offsets() (start, end int) {\n\treturn s.start, s.start + s.len\n}\n\nfunc (s symbol) String() string {\n\treturn fmt.Sprintf(\"{%d,%d,%s,%s,%v}\", s.start, s.len, s.name, s.kind, s.vardef)\n}\n\n// for FieldNode or VariableNode (or ChainNode?)\nfunc (p *parsed) fields(flds []string, x parse.Node) []symbol {\n\tans := []symbol{}\n\t// guessing that there are no embedded blanks allowed. The doc is unclear\n\tlookfor := \"\"\n\tswitch x.(type) {\n\tcase *parse.FieldNode:\n\t\tfor _, f := range flds {\n\t\t\tlookfor += \".\" + f // quadratic, but probably ok\n\t\t}\n\tcase *parse.VariableNode:\n\t\tlookfor = flds[0]\n\t\tfor i := 1; i < len(flds); i++ {\n\t\t\tlookfor += \".\" + flds[i]\n\t\t}\n\tcase *parse.ChainNode: // PJW, what are these?\n\t\tfor _, f := range flds {\n\t\t\tlookfor += \".\" + f // quadratic, but probably ok\n\t\t}\n\tdefault:\n\t\t// If these happen they will happen even if gopls is restarted\n\t\t// and the users does the same thing, so it is better not to panic.\n\t\t// context.Background() is used because we don't have access\n\t\t// to any other context. [we could, but it would be complicated]\n\t\tevent.Log(context.Background(), fmt.Sprintf(\"%T unexpected in fields()\", x))\n\t\treturn nil\n\t}\n\tif len(lookfor) == 0 {\n\t\tevent.Log(context.Background(), fmt.Sprintf(\"no strings in fields() %#v\", x))\n\t\treturn nil\n\t}\n\tstartsAt := int(x.Position())\n\tix := bytes.Index(p.buf[startsAt:], []byte(lookfor)) // HasPrefix? PJW?\n\tif ix < 0 || ix > len(lookfor) {                     // lookfor expected to be at start (or so)\n\t\t// probably golang.go/#43388, so back up\n\t\tstartsAt -= len(flds[0]) + 1\n\t\tix = bytes.Index(p.buf[startsAt:], []byte(lookfor)) // ix might be 1? PJW\n\t\tif ix < 0 {\n\t\t\treturn ans\n\t\t}\n\t}\n\tat := ix + startsAt\n\tfor _, f := range flds {\n\t\tat += 1 // .\n\t\tkind := protocol.Method\n\t\tif f[0] == '$' {\n\t\t\tkind = protocol.Variable\n\t\t}\n\t\tsym := symbol{name: f, kind: kind, start: at, len: len(f)}\n\t\tif kind == protocol.Variable && len(p.stack) > 1 {\n\t\t\tif pipe, ok := p.stack[len(p.stack)-2].(*parse.PipeNode); ok {\n\t\t\t\tfor _, y := range pipe.Decl {\n\t\t\t\t\tif x == y {\n\t\t\t\t\t\tsym.vardef = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tans = append(ans, sym)\n\t\tat += len(f)\n\t}\n\treturn ans\n}\n\nfunc (p *parsed) findSymbols() {\n\tif len(p.stack) == 0 {\n\t\treturn\n\t}\n\tn := p.stack[len(p.stack)-1]\n\tpop := func() {\n\t\tp.stack = p.stack[:len(p.stack)-1]\n\t}\n\tif n == nil { // allowing nil simplifies the code\n\t\tpop()\n\t\treturn\n\t}\n\tnxt := func(nd parse.Node) {\n\t\tp.stack = append(p.stack, nd)\n\t\tp.findSymbols()\n\t}\n\tswitch x := n.(type) {\n\tcase *parse.ActionNode:\n\t\tnxt(x.Pipe)\n\tcase *parse.BoolNode:\n\t\t// need to compute the length from the value\n\t\tmsg := fmt.Sprintf(\"%v\", x.True)\n\t\tp.symbols = append(p.symbols, symbol{start: int(x.Pos), len: len(msg), kind: protocol.Boolean})\n\tcase *parse.BranchNode:\n\t\tnxt(x.Pipe)\n\t\tnxt(x.List)\n\t\tnxt(x.ElseList)\n\tcase *parse.ChainNode:\n\t\tp.symbols = append(p.symbols, p.fields(x.Field, x)...)\n\t\tnxt(x.Node)\n\tcase *parse.CommandNode:\n\t\tfor _, a := range x.Args {\n\t\t\tnxt(a)\n\t\t}\n\t//case *parse.CommentNode: // go 1.16\n\t//\tlog.Printf(\"implement %d\", x.Type())\n\tcase *parse.DotNode:\n\t\tsym := symbol{name: \"dot\", kind: protocol.Variable, start: int(x.Pos), len: 1}\n\t\tp.symbols = append(p.symbols, sym)\n\tcase *parse.FieldNode:\n\t\tp.symbols = append(p.symbols, p.fields(x.Ident, x)...)\n\tcase *parse.IdentifierNode:\n\t\tsym := symbol{name: x.Ident, kind: protocol.Function, start: int(x.Pos), len: len(x.Ident)}\n\t\tp.symbols = append(p.symbols, sym)\n\tcase *parse.IfNode:\n\t\tnxt(&x.BranchNode)\n\tcase *parse.ListNode:\n\t\tif x != nil { // wretched typed nils. Node should have an IfNil\n\t\t\tfor _, nd := range x.Nodes {\n\t\t\t\tnxt(nd)\n\t\t\t}\n\t\t}\n\tcase *parse.NilNode:\n\t\tsym := symbol{name: \"nil\", kind: protocol.Constant, start: int(x.Pos), len: 3}\n\t\tp.symbols = append(p.symbols, sym)\n\tcase *parse.NumberNode:\n\t\t// no name; ascii\n\t\tp.symbols = append(p.symbols, symbol{start: int(x.Pos), len: len(x.Text), kind: protocol.Number})\n\tcase *parse.PipeNode:\n\t\tif x == nil { // {{template \"foo\"}}\n\t\t\treturn\n\t\t}\n\t\tfor _, d := range x.Decl {\n\t\t\tnxt(d)\n\t\t}\n\t\tfor _, c := range x.Cmds {\n\t\t\tnxt(c)\n\t\t}\n\tcase *parse.RangeNode:\n\t\tnxt(&x.BranchNode)\n\tcase *parse.StringNode:\n\t\t// no name\n\t\tp.symbols = append(p.symbols, symbol{start: int(x.Pos), len: len(x.Quoted), kind: protocol.String})\n\tcase *parse.TemplateNode:\n\t\t// invoking a template, e.g. {{define \"foo\"}}\n\t\t// x.Pos is the index of \"foo\".\n\t\t// The logic below assumes that the literal is trivial.\n\t\tp.symbols = append(p.symbols, symbol{name: x.Name, kind: protocol.Package, start: int(x.Pos) + len(`\"`), len: len(x.Name)})\n\t\tnxt(x.Pipe)\n\tcase *parse.TextNode:\n\t\tif len(x.Text) == 1 && x.Text[0] == '\\n' {\n\t\t\tbreak\n\t\t}\n\t\t// nothing to report, but build one for hover\n\t\tp.symbols = append(p.symbols, symbol{start: int(x.Pos), len: len(x.Text), kind: protocol.Constant})\n\tcase *parse.VariableNode:\n\t\tp.symbols = append(p.symbols, p.fields(x.Ident, x)...)\n\tcase *parse.WithNode:\n\t\tnxt(&x.BranchNode)\n\t}\n\tpop()\n}\n\n// DocumentSymbols returns a hierarchy of the symbols defined in a template file.\n// (The hierarchy is flat. SymbolInformation might be better.)\nfunc DocumentSymbols(snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentSymbol, error) {\n\tbuf, err := fh.Content()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tp := parseBuffer(fh.URI(), buf)\n\tif p.parseErr != nil {\n\t\treturn nil, p.parseErr\n\t}\n\tvar ans []protocol.DocumentSymbol\n\tfor _, sym := range p.symbols {\n\t\tif sym.kind == protocol.Constant {\n\t\t\tcontinue\n\t\t}\n\t\tdetail := kindStr(sym.kind)\n\t\tif detail == \"Namespace\" {\n\t\t\tdetail = \"Template\"\n\t\t}\n\t\tif sym.vardef {\n\t\t\tdetail += \"(def)\"\n\t\t} else {\n\t\t\tdetail += \"(use)\"\n\t\t}\n\t\trng, err := p.mapper.OffsetRange(sym.offsets())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tans = append(ans, protocol.DocumentSymbol{\n\t\t\tName:           sym.name,\n\t\t\tDetail:         detail,\n\t\t\tKind:           sym.kind,\n\t\t\tRange:          rng,\n\t\t\tSelectionRange: rng, // or should this be the entire {{...}}?\n\t\t})\n\t}\n\treturn ans, nil\n}\n\nfunc kindStr(k protocol.SymbolKind) string {\n\tn := int(k)\n\tif n < 1 || n >= len(kindNames) {\n\t\treturn fmt.Sprintf(\"?SymbolKind %d?\", n)\n\t}\n\treturn kindNames[n]\n}\n\nvar kindNames = []string{\n\t\"\",\n\t\"File\",\n\t\"Module\",\n\t\"Namespace\",\n\t\"Package\",\n\t\"Class\",\n\t\"Method\",\n\t\"Property\",\n\t\"Field\",\n\t\"Constructor\",\n\t\"Enum\",\n\t\"Interface\",\n\t\"Function\",\n\t\"Variable\",\n\t\"Constant\",\n\t\"String\",\n\t\"Number\",\n\t\"Boolean\",\n\t\"Array\",\n\t\"Object\",\n\t\"Key\",\n\t\"Null\",\n\t\"EnumMember\",\n\t\"Struct\",\n\t\"Event\",\n\t\"Operator\",\n\t\"TypeParameter\",\n}\n"
  },
  {
    "path": "gopls/internal/test/compare/text.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage compare\n\nimport (\n\t\"bytes\"\n\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// Text returns a formatted unified diff of the edits to go from want to\n// got, returning \"\" if and only if want == got.\n//\n// This function is intended for use in testing, and panics if any error occurs\n// while computing the diff. It is not sufficiently tested for production use.\nfunc Text(want, got string) string {\n\treturn NamedText(\"want\", \"got\", want, got)\n}\n\n// NamedText is like text, but allows passing custom names of the 'want' and\n// 'got' content.\nfunc NamedText(wantName, gotName, want, got string) string {\n\tif want == got {\n\t\treturn \"\"\n\t}\n\n\t// Add newlines to avoid verbose newline messages (\"No newline at end of file\").\n\tunified := diff.Unified(wantName, gotName, want+\"\\n\", got+\"\\n\")\n\n\t// Defensively assert that we get an actual diff, so that we guarantee the\n\t// invariant that we return \"\" if and only if want == got.\n\t//\n\t// This is probably unnecessary, but convenient.\n\tif unified == \"\" {\n\t\tpanic(\"empty diff for non-identical input\")\n\t}\n\n\treturn unified\n}\n\n// Bytes is like Text but using byte slices.\nfunc Bytes(want, got []byte) string {\n\tif bytes.Equal(want, got) {\n\t\treturn \"\" // common case\n\t}\n\treturn Text(string(want), string(got))\n}\n"
  },
  {
    "path": "gopls/internal/test/compare/text_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage compare_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n)\n\nfunc TestText(t *testing.T) {\n\ttests := []struct {\n\t\tgot, want, wantDiff string\n\t}{\n\t\t{\"\", \"\", \"\"},\n\t\t{\"equal\", \"equal\", \"\"},\n\t\t{\"a\", \"b\", \"--- want\\n+++ got\\n@@ -1 +1 @@\\n-b\\n+a\\n\"},\n\t\t{\"a\\nd\\nc\\n\", \"a\\nb\\nc\\n\", \"--- want\\n+++ got\\n@@ -1,4 +1,4 @@\\n a\\n-b\\n+d\\n c\\n \\n\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tif gotDiff := compare.Text(test.want, test.got); gotDiff != test.wantDiff {\n\t\t\tt.Errorf(\"compare.Text(%q, %q) =\\n%q, want\\n%q\", test.want, test.got, gotDiff, test.wantDiff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/bench_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cmd\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/fakenet\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n\t\"golang.org/x/tools/internal/pprof\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\nvar (\n\tgoplsPath = flag.String(\"gopls_path\", \"\", \"if set, use this gopls for testing; incompatible with -gopls_commit\")\n\n\tinstallGoplsOnce sync.Once // guards installing gopls at -gopls_commit\n\tgoplsCommit      = flag.String(\"gopls_commit\", \"\", \"if set, install and use gopls at this commit for testing; incompatible with -gopls_path\")\n\n\tcpuProfile   = flag.String(\"gopls_cpuprofile\", \"\", \"if set, the cpu profile file suffix; see \\\"Profiling\\\" in the package doc\")\n\tmemProfile   = flag.String(\"gopls_memprofile\", \"\", \"if set, the mem profile file suffix; see \\\"Profiling\\\" in the package doc\")\n\tallocProfile = flag.String(\"gopls_allocprofile\", \"\", \"if set, the alloc profile file suffix; see \\\"Profiling\\\" in the package doc\")\n\tblockProfile = flag.String(\"gopls_blockprofile\", \"\", \"if set, the block profile file suffix; see \\\"Profiling\\\" in the package doc\")\n\ttrace        = flag.String(\"gopls_trace\", \"\", \"if set, the trace file suffix; see \\\"Profiling\\\" in the package doc\")\n\n\t// If non-empty, tempDir is a temporary working dir that was created by this\n\t// test suite.\n\tmakeTempDirOnce sync.Once // guards creation of the temp dir\n\ttempDir         string\n)\n\n// if runAsGopls is \"true\", run the gopls command instead of the testing.M.\nconst runAsGopls = \"_GOPLS_BENCH_RUN_AS_GOPLS\"\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tif os.Getenv(runAsGopls) == \"true\" {\n\t\ttool.Main(context.Background(), cmd.New(), os.Args[1:])\n\t\tos.Exit(0)\n\t}\n\tevent.SetExporter(nil) // don't log to stderr\n\tcode := m.Run()\n\tif err := cleanup(); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"cleaning up after benchmarks: %v\\n\", err)\n\t\tif code == 0 {\n\t\t\tcode = 1\n\t\t}\n\t}\n\tos.Exit(code)\n}\n\n// getTempDir returns the temporary directory to use for benchmark files,\n// creating it if necessary.\nfunc getTempDir() string {\n\tmakeTempDirOnce.Do(func() {\n\t\tvar err error\n\t\ttempDir, err = os.MkdirTemp(\"\", \"gopls-bench\")\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t})\n\treturn tempDir\n}\n\n// shallowClone performs a shallow clone of repo into dir at the given\n// 'commitish' ref (any commit reference understood by git).\n//\n// The directory dir must not already exist.\nfunc shallowClone(dir, repo, commitish string) error {\n\tif err := os.Mkdir(dir, 0750); err != nil {\n\t\treturn fmt.Errorf(\"creating dir for %s: %v\", repo, err)\n\t}\n\n\t// Set a timeout for git fetch. If this proves flaky, it can be removed.\n\tctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)\n\tdefer cancel()\n\n\t// Use a shallow fetch to download just the relevant commit.\n\tshInit := fmt.Sprintf(\"git init && git fetch --depth=1 %q %q && git checkout FETCH_HEAD\", repo, commitish)\n\tinitCmd := exec.CommandContext(ctx, \"/bin/sh\", \"-c\", shInit)\n\tinitCmd.Dir = dir\n\tif output, err := initCmd.CombinedOutput(); err != nil {\n\t\treturn fmt.Errorf(\"checking out %s: %v\\n%s\", repo, err, output)\n\t}\n\treturn nil\n}\n\n// connectEditor connects a fake editor session in the given dir, using the\n// given editor config.\nfunc connectEditor(dir string, config fake.EditorConfig, ts servertest.Connector) (*fake.Sandbox, *fake.Editor, *integration.Awaiter, error) {\n\ts, err := fake.NewSandbox(&fake.SandboxConfig{\n\t\tWorkdir: dir,\n\t\tGOPROXY: \"https://proxy.golang.org\",\n\t})\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\n\ta := integration.NewAwaiter(s.Workdir)\n\teditor, err := fake.NewEditor(s, config).Connect(context.Background(), ts, a.Hooks())\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\n\treturn s, editor, a, nil\n}\n\n// newGoplsConnector returns a connector that connects to a new gopls process,\n// executed with the provided arguments.\nfunc newGoplsConnector(args []string) (servertest.Connector, error) {\n\tif *goplsPath != \"\" && *goplsCommit != \"\" {\n\t\tpanic(\"can't set both -gopls_path and -gopls_commit\")\n\t}\n\tvar (\n\t\tgoplsPath = *goplsPath\n\t\tenv       []string\n\t)\n\tif *goplsCommit != \"\" {\n\t\tgoplsPath = getInstalledGopls()\n\t}\n\tif goplsPath == \"\" {\n\t\tvar err error\n\t\tgoplsPath, err = os.Executable()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tenv = []string{fmt.Sprintf(\"%s=true\", runAsGopls)}\n\t}\n\treturn &SidecarServer{\n\t\tgoplsPath: goplsPath,\n\t\tenv:       env,\n\t\targs:      args,\n\t}, nil\n}\n\n// profileArgs returns additional command-line arguments to use when invoking\n// gopls, to enable the user-requested profiles.\n//\n// If wantCPU is set, CPU profiling is enabled as well. Some tests may want to\n// instrument profiling around specific critical sections of the benchmark,\n// rather than the entire process.\n//\n// TODO(rfindley): like CPU, all of these would be better served by a custom\n// command. Very rarely do we care about memory usage as the process exits: we\n// care about specific points in time during the benchmark. mem and alloc\n// should be snapshotted, and tracing should be bracketed around critical\n// sections.\nfunc profileArgs(name string, wantCPU bool) []string {\n\tvar args []string\n\tif wantCPU && *cpuProfile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"-profile.cpu=%s\", qualifiedName(name, *cpuProfile)))\n\t}\n\tif *memProfile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"-profile.mem=%s\", qualifiedName(name, *memProfile)))\n\t}\n\tif *allocProfile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"-profile.alloc=%s\", qualifiedName(name, *allocProfile)))\n\t}\n\tif *blockProfile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"-profile.block=%s\", qualifiedName(name, *blockProfile)))\n\t}\n\tif *trace != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"-profile.trace=%s\", qualifiedName(name, *trace)))\n\t}\n\treturn args\n}\n\nfunc qualifiedName(args ...string) string {\n\treturn strings.Join(args, \".\")\n}\n\n// getInstalledGopls builds gopls at the given -gopls_commit, returning the\n// path to the gopls binary.\nfunc getInstalledGopls() string {\n\tif *goplsCommit == \"\" {\n\t\tpanic(\"must provide -gopls_commit\")\n\t}\n\ttoolsDir := filepath.Join(getTempDir(), \"gopls_build\")\n\tgoplsPath := filepath.Join(toolsDir, \"gopls\", \"gopls\")\n\n\tinstallGoplsOnce.Do(func() {\n\t\tlog.Printf(\"installing gopls: checking out x/tools@%s into %s\\n\", *goplsCommit, toolsDir)\n\t\tif err := shallowClone(toolsDir, \"https://go.googlesource.com/tools\", *goplsCommit); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\n\t\tlog.Println(\"installing gopls: building...\")\n\t\tbld := exec.Command(\"go\", \"build\", \".\")\n\t\tbld.Dir = filepath.Join(toolsDir, \"gopls\")\n\t\tif output, err := bld.CombinedOutput(); err != nil {\n\t\t\tlog.Fatalf(\"building gopls: %v\\n%s\", err, output)\n\t\t}\n\n\t\t// Confirm that the resulting path now exists.\n\t\tif _, err := os.Stat(goplsPath); err != nil {\n\t\t\tlog.Fatalf(\"os.Stat(%s): %v\", goplsPath, err)\n\t\t}\n\t})\n\treturn goplsPath\n}\n\n// A SidecarServer starts (and connects to) a separate gopls process at the\n// given path.\ntype SidecarServer struct {\n\tgoplsPath string\n\tenv       []string // additional environment bindings\n\targs      []string // command-line arguments\n}\n\n// Connect creates new io.Pipes and binds them to the underlying StreamServer.\n//\n// It implements the servertest.Connector interface.\nfunc (s *SidecarServer) Connect(ctx context.Context) jsonrpc2.Conn {\n\t// Note: don't use CommandContext here, as we want gopls to exit gracefully\n\t// in order to write out profile data.\n\t//\n\t// We close the connection on context cancellation below.\n\tcmd := exec.Command(s.goplsPath, s.args...)\n\n\tstdin, err := cmd.StdinPipe()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tcmd.Stderr = os.Stderr\n\tcmd.Env = append(os.Environ(), s.env...)\n\tif err := cmd.Start(); err != nil {\n\t\tlog.Fatalf(\"starting gopls: %v\", err)\n\t}\n\n\tgo func() {\n\t\t// If we don't log.Fatal here, benchmarks may hang indefinitely if gopls\n\t\t// exits abnormally.\n\t\t//\n\t\t// TODO(rfindley): ideally we would shut down the connection gracefully,\n\t\t// but that doesn't currently work.\n\t\tif err := cmd.Wait(); err != nil {\n\t\t\tlog.Fatalf(\"gopls invocation failed with error: %v\", err)\n\t\t}\n\t}()\n\n\tclientStream := jsonrpc2.NewHeaderStream(fakenet.NewConn(\"stdio\", stdout, stdin))\n\tclientConn := jsonrpc2.NewConn(clientStream)\n\n\tgo func() {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tclientConn.Close()   // ignore error\n\t\t\tclientStream.Close() // ignore error\n\t\tcase <-clientConn.Done():\n\t\t}\n\t}()\n\n\treturn clientConn\n}\n\n// startProfileIfSupported checks to see if the remote gopls instance supports\n// the start/stop profiling commands. If so, it starts profiling and returns a\n// function that stops profiling and records the total CPU seconds sampled in the\n// cpu_seconds benchmark metric.\n//\n// If the remote gopls instance does not support profiling commands, this\n// function returns nil.\n//\n// If the supplied userSuffix is non-empty, the profile is written to\n// <repo>.<userSuffix>, and not deleted when the benchmark exits. Otherwise,\n// the profile is written to a temp file that is deleted after the cpu_seconds\n// metric has been computed.\nfunc startProfileIfSupported(b *testing.B, env *integration.Env, name string) func() {\n\tif !env.Editor.HasCommand(command.StartProfile) {\n\t\treturn nil\n\t}\n\tb.StopTimer()\n\tstopProfile := env.StartProfile()\n\tb.StartTimer()\n\treturn func() {\n\t\tb.StopTimer()\n\t\tprofFile := stopProfile()\n\t\ttotalCPU, err := totalCPUForProfile(profFile)\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"reading profile: %v\", err)\n\t\t}\n\t\tb.ReportMetric(totalCPU.Seconds()/float64(b.N), \"cpu_seconds/op\")\n\t\tif *cpuProfile != \"\" {\n\t\t\t// Read+write to avoid exdev errors.\n\t\t\tdata, err := os.ReadFile(profFile)\n\t\t\tif err != nil {\n\t\t\t\tb.Fatalf(\"reading profile: %v\", err)\n\t\t\t}\n\t\t\tname := qualifiedName(name, *cpuProfile)\n\t\t\tif err := os.WriteFile(name, data, 0666); err != nil {\n\t\t\t\tb.Fatalf(\"writing profile: %v\", err)\n\t\t\t}\n\t\t}\n\t\tif err := os.Remove(profFile); err != nil {\n\t\t\tb.Errorf(\"removing profile file: %v\", err)\n\t\t}\n\t}\n}\n\n// totalCPUForProfile reads the pprof profile with the given file name, parses,\n// and aggregates the total CPU sampled during the profile.\nfunc totalCPUForProfile(filename string) (time.Duration, error) {\n\tprotoGz, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\trd, err := gzip.NewReader(bytes.NewReader(protoGz))\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"creating gzip reader for %s: %v\", filename, err)\n\t}\n\tdata, err := io.ReadAll(rd)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"reading %s: %v\", filename, err)\n\t}\n\treturn pprof.TotalTime(data)\n}\n\n// closeBuffer stops the benchmark timer and closes the buffer with the given\n// name.\n//\n// It may be used to clean up files opened in the shared environment during\n// benchmarking.\nfunc closeBuffer(b *testing.B, env *integration.Env, name string) {\n\tb.StopTimer()\n\tenv.CloseBuffer(name)\n\tenv.AfterChange()\n\tb.StartTimer()\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/codeaction_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc BenchmarkCodeAction(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\t\t\tenv.AfterChange()\n\n\t\t\tenv.CodeActionForFile(test.file, nil) // pre-warm\n\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"hover\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.CodeActionForFile(test.file, nil)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCodeActionFollowingEdit(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\t\t\tenv.EditBuffer(test.file, protocol.TextEdit{NewText: \"// __TEST_PLACEHOLDER_0__\\n\"})\n\t\t\tenv.AfterChange()\n\n\t\t\tenv.CodeActionForFile(test.file, nil) // pre-warm\n\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"hover\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tedits := atomic.AddInt64(&editID, 1)\n\t\t\t\tenv.EditBuffer(test.file, protocol.TextEdit{\n\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\tStart: protocol.Position{Line: 0, Character: 0},\n\t\t\t\t\t\tEnd:   protocol.Position{Line: 1, Character: 0},\n\t\t\t\t\t},\n\t\t\t\t\t// Increment the placeholder text, to ensure cache misses.\n\t\t\t\t\tNewText: fmt.Sprintf(\"// __TEST_PLACEHOLDER_%d__\\n\", edits),\n\t\t\t\t})\n\t\t\t\tenv.CodeActionForFile(test.file, nil)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/completion_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\nvar completionGOPATH = flag.String(\"completion_gopath\", \"\", \"if set, use this GOPATH for BenchmarkCompletion\")\n\ntype completionBenchOptions struct {\n\tfile, locationRegexp string\n\n\t// Hooks to run edits before initial completion\n\tsetup            func(*Env) // run before the benchmark starts\n\tbeforeCompletion func(*Env) // run before each completion\n}\n\n// Deprecated: new tests should be expressed in BenchmarkCompletion.\nfunc benchmarkCompletion(options completionBenchOptions, b *testing.B) {\n\trepo := getRepo(b, \"tools\")\n\t_ = repo.sharedEnv(b) // ensure cache is warm\n\tenv := repo.newEnv(b, fake.EditorConfig{}, \"completion\", false)\n\tdefer env.Close()\n\n\t// Run edits required for this completion.\n\tif options.setup != nil {\n\t\toptions.setup(env)\n\t}\n\n\t// Run a completion to make sure the system is warm.\n\tloc := env.RegexpSearch(options.file, options.locationRegexp)\n\tcompletions := env.Completion(loc)\n\n\tif testing.Verbose() {\n\t\tfmt.Println(\"Results:\")\n\t\tfor i := 0; i < len(completions.Items); i++ {\n\t\t\tfmt.Printf(\"\\t%d. %v\\n\", i, completions.Items[i])\n\t\t}\n\t}\n\n\tb.Run(\"tools\", func(b *testing.B) {\n\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(\"tools\", \"completion\")); stopAndRecord != nil {\n\t\t\tdefer stopAndRecord()\n\t\t}\n\n\t\tfor b.Loop() {\n\t\t\tif options.beforeCompletion != nil {\n\t\t\t\toptions.beforeCompletion(env)\n\t\t\t}\n\t\t\tenv.Completion(loc)\n\t\t}\n\t})\n}\n\n// endRangeInBuffer returns the position for last character in the buffer for\n// the given file.\nfunc endRangeInBuffer(env *Env, name string) protocol.Range {\n\tbuffer := env.BufferText(name)\n\tm := protocol.NewMapper(\"\", []byte(buffer))\n\trng, err := m.OffsetRange(len(buffer), len(buffer))\n\tif err != nil {\n\t\tenv.TB.Fatal(err)\n\t}\n\treturn rng\n}\n\n// Benchmark struct completion in tools codebase.\nfunc BenchmarkStructCompletion(b *testing.B) {\n\tfile := \"internal/lsp/cache/session.go\"\n\n\tsetup := func(env *Env) {\n\t\tenv.OpenFile(file)\n\t\tenv.EditBuffer(file, protocol.TextEdit{\n\t\t\tRange:   endRangeInBuffer(env, file),\n\t\t\tNewText: \"\\nvar testVariable map[string]bool = Session{}.\\n\",\n\t\t})\n\t}\n\n\tbenchmarkCompletion(completionBenchOptions{\n\t\tfile:           file,\n\t\tlocationRegexp: `var testVariable map\\[string\\]bool = Session{}(\\.)`,\n\t\tsetup:          setup,\n\t}, b)\n}\n\n// Benchmark import completion in tools codebase.\nfunc BenchmarkImportCompletion(b *testing.B) {\n\tconst file = \"internal/lsp/source/completion/completion.go\"\n\tbenchmarkCompletion(completionBenchOptions{\n\t\tfile:           file,\n\t\tlocationRegexp: `go\\/()`,\n\t\tsetup:          func(env *Env) { env.OpenFile(file) },\n\t}, b)\n}\n\n// Benchmark slice completion in tools codebase.\nfunc BenchmarkSliceCompletion(b *testing.B) {\n\tfile := \"internal/lsp/cache/session.go\"\n\n\tsetup := func(env *Env) {\n\t\tenv.OpenFile(file)\n\t\tenv.EditBuffer(file, protocol.TextEdit{\n\t\t\tRange:   endRangeInBuffer(env, file),\n\t\t\tNewText: \"\\nvar testVariable []byte = \\n\",\n\t\t})\n\t}\n\n\tbenchmarkCompletion(completionBenchOptions{\n\t\tfile:           file,\n\t\tlocationRegexp: `var testVariable \\[\\]byte (=)`,\n\t\tsetup:          setup,\n\t}, b)\n}\n\n// Benchmark deep completion in function call in tools codebase.\nfunc BenchmarkFuncDeepCompletion(b *testing.B) {\n\tfile := \"internal/lsp/source/completion/completion.go\"\n\tfileContent := `\nfunc (c *completer) _() {\n\tc.inference.kindMatches(c.)\n}\n`\n\tsetup := func(env *Env) {\n\t\tenv.OpenFile(file)\n\t\toriginalBuffer := env.BufferText(file)\n\t\tenv.EditBuffer(file, protocol.TextEdit{\n\t\t\tRange: endRangeInBuffer(env, file),\n\t\t\t// TODO(rfindley): this is a bug: it should just be fileContent.\n\t\t\tNewText: originalBuffer + fileContent,\n\t\t})\n\t}\n\n\tbenchmarkCompletion(completionBenchOptions{\n\t\tfile:           file,\n\t\tlocationRegexp: `func \\(c \\*completer\\) _\\(\\) {\\n\\tc\\.inference\\.kindMatches\\((c)`,\n\t\tsetup:          setup,\n\t}, b)\n}\n\ntype completionTest struct {\n\trepo           string\n\tname           string\n\tfile           string // repo-relative file to create\n\tcontent        string // file content\n\tlocationRegexp string // regexp for completion\n}\n\nvar completionTests = []completionTest{\n\t{\n\t\t\"tools\",\n\t\t\"selector\",\n\t\t\"internal/lsp/source/completion/completion2.go\",\n\t\t`\npackage completion\n\nfunc (c *completer) _() {\n\tc.inference.kindMatches(c.)\n}\n`,\n\t\t`func \\(c \\*completer\\) _\\(\\) {\\n\\tc\\.inference\\.kindMatches\\((c)`,\n\t},\n\t{\n\t\t\"tools\",\n\t\t\"unimportedident\",\n\t\t\"internal/lsp/source/completion/completion2.go\",\n\t\t`\npackage completion\n\nfunc (c *completer) _() {\n\tlo\n}\n`,\n\t\t`lo()`,\n\t},\n\t{\n\t\t\"tools\",\n\t\t\"unimportedselector\",\n\t\t\"internal/lsp/source/completion/completion2.go\",\n\t\t`\npackage completion\n\nfunc (c *completer) _() {\n\tlog.\n}\n`,\n\t\t`log\\.()`,\n\t},\n\t{\n\t\t\"kubernetes\",\n\t\t\"selector\",\n\t\t\"pkg/kubelet/kubelet2.go\",\n\t\t`\npackage kubelet\n\nfunc (kl *Kubelet) _() {\n\tkl.\n}\n`,\n\t\t`kl\\.()`,\n\t},\n\t{\n\t\t\"kubernetes\",\n\t\t\"identifier\",\n\t\t\"pkg/kubelet/kubelet2.go\",\n\t\t`\npackage kubelet\n\nfunc (kl *Kubelet) _() {\n\tk // here\n}\n`,\n\t\t`k() // here`,\n\t},\n\t{\n\t\t\"oracle\",\n\t\t\"selector\",\n\t\t\"dataintegration/pivot2.go\",\n\t\t`\npackage dataintegration\n\nfunc (p *Pivot) _() {\n\tp.\n}\n`,\n\t\t`p\\.()`,\n\t},\n}\n\n// Benchmark completion following an arbitrary edit.\n//\n// Edits force type-checked packages to be invalidated, so we want to measure\n// how long it takes before completion results are available.\nfunc BenchmarkCompletion(b *testing.B) {\n\tfor _, test := range completionTests {\n\t\tb.Run(fmt.Sprintf(\"%s_%s\", test.repo, test.name), func(b *testing.B) {\n\t\t\tfor _, followingEdit := range []bool{true, false} {\n\t\t\t\tb.Run(fmt.Sprintf(\"edit=%v\", followingEdit), func(b *testing.B) {\n\t\t\t\t\tfor _, completeUnimported := range []bool{true, false} {\n\t\t\t\t\t\tb.Run(fmt.Sprintf(\"unimported=%v\", completeUnimported), func(b *testing.B) {\n\t\t\t\t\t\t\tfor _, budget := range []string{\"0s\", \"100ms\"} {\n\t\t\t\t\t\t\t\tb.Run(fmt.Sprintf(\"budget=%s\", budget), func(b *testing.B) {\n\t\t\t\t\t\t\t\t\trunCompletion(b, test, followingEdit, completeUnimported, budget)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\n// For optimizing unimported completion, it can be useful to benchmark with a\n// huge GOMODCACHE.\nvar gomodcache = flag.String(\"gomodcache\", \"\", \"optional GOMODCACHE for unimported completion benchmarks\")\n\nfunc runCompletion(b *testing.B, test completionTest, followingEdit, completeUnimported bool, budget string) {\n\trepo := getRepo(b, test.repo)\n\tgopath := *completionGOPATH\n\tif gopath == \"\" {\n\t\t// use a warm GOPATH\n\t\tsharedEnv := repo.sharedEnv(b)\n\t\tgopath = sharedEnv.Sandbox.GOPATH()\n\t}\n\tenvvars := map[string]string{\n\t\t\"GOPATH\": gopath,\n\t}\n\n\tif *gomodcache != \"\" {\n\t\tenvvars[\"GOMODCACHE\"] = *gomodcache\n\t}\n\n\tenv := repo.newEnv(b, fake.EditorConfig{\n\t\tEnv: envvars,\n\t\tSettings: map[string]any{\n\t\t\t\"completeUnimported\": completeUnimported,\n\t\t\t\"completionBudget\":   budget,\n\t\t},\n\t}, \"completion\", false)\n\tdefer env.Close()\n\n\tenv.CreateBuffer(test.file, \"// __TEST_PLACEHOLDER_0__\\n\"+test.content)\n\teditPlaceholder := func() {\n\t\tedits := atomic.AddInt64(&editID, 1)\n\t\tenv.EditBuffer(test.file, protocol.TextEdit{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 0, Character: 0},\n\t\t\t\tEnd:   protocol.Position{Line: 1, Character: 0},\n\t\t\t},\n\t\t\t// Increment the placeholder text, to ensure cache misses.\n\t\t\tNewText: fmt.Sprintf(\"// __TEST_PLACEHOLDER_%d__\\n\", edits),\n\t\t})\n\t}\n\tenv.AfterChange()\n\n\t// Run a completion to make sure the system is warm.\n\tloc := env.RegexpSearch(test.file, test.locationRegexp)\n\tcompletions := env.Completion(loc)\n\n\tif testing.Verbose() {\n\t\tfmt.Println(\"Results:\")\n\t\tfor i, item := range completions.Items {\n\t\t\tfmt.Printf(\"\\t%d. %v\\n\", i, item)\n\t\t}\n\t}\n\n\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"completion\")); stopAndRecord != nil {\n\t\tdefer stopAndRecord()\n\t}\n\n\tfor b.Loop() {\n\t\tif followingEdit {\n\t\t\teditPlaceholder()\n\t\t}\n\t\tloc := env.RegexpSearch(test.file, test.locationRegexp)\n\t\tenv.Completion(loc)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/definition_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"testing\"\n)\n\nfunc BenchmarkDefinition(b *testing.B) {\n\ttests := []struct {\n\t\trepo   string\n\t\tfile   string\n\t\tregexp string\n\t}{\n\t\t{\"istio\", \"pkg/config/model.go\", `gogotypes\\.(MarshalAny)`},\n\t\t{\"google-cloud-go\", \"httpreplay/httpreplay.go\", `proxy\\.(ForRecording)`},\n\t\t{\"kubernetes\", \"pkg/controller/lookup_cache.go\", `hashutil\\.(DeepHashObject)`},\n\t\t{\"kuma\", \"api/generic/insights.go\", `proto\\.(Message)`},\n\t\t{\"pkgsite\", \"internal/log/log.go\", `derrors\\.(Wrap)`},\n\t\t{\"starlark\", \"starlark/eval.go\", \"prog.compiled.(Encode)\"},\n\t\t{\"tools\", \"internal/lsp/cache/check.go\", `(snapshot)\\) buildKey`},\n\t}\n\n\tfor _, test := range tests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\tloc := env.RegexpSearch(test.file, test.regexp)\n\t\t\tenv.Await(env.DoneWithOpen())\n\t\t\tenv.FirstDefinition(loc) // pre-warm the query, and open the target file\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"definition\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.FirstDefinition(loc) // pre-warm the query\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/diagnostic_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\n// BenchmarkDiagnosePackageFiles measures how long it takes to request\n// diagnostics for 10 files in a single package, following a change to that\n// package.\n//\n// This can be used to measure the efficiency of pull diagnostics\n// (golang/go#53275).\nfunc BenchmarkDiagnosePackageFiles(b *testing.B) {\n\tif testing.Short() {\n\t\tb.Skip(\"pull diagnostics are not supported by the benchmark dashboard baseline\")\n\t}\n\n\tenv := getRepo(b, \"kubernetes\").newEnv(b, fake.EditorConfig{\n\t\tSettings: map[string]any{\n\t\t\t\"pullDiagnostics\": true, // currently required for pull diagnostic support\n\t\t},\n\t}, \"diagnosePackageFiles\", false)\n\n\t// 10 arbitrary files in a single package.\n\tfiles := []string{\n\t\t\"pkg/kubelet/active_deadline.go\",      // 98 lines\n\t\t\"pkg/kubelet/active_deadline_test.go\", // 95 lines\n\t\t\"pkg/kubelet/kubelet.go\",              // 2439 lines\n\t\t\"pkg/kubelet/kubelet_pods.go\",         // 2061 lines\n\t\t\"pkg/kubelet/kubelet_network.go\",      // 70 lines\n\t\t\"pkg/kubelet/kubelet_network_test.go\", // 46 lines\n\t\t\"pkg/kubelet/pod_workers.go\",          // 1323 lines\n\t\t\"pkg/kubelet/pod_workers_test.go\",     // 1758 lines\n\t\t\"pkg/kubelet/runonce.go\",              // 175 lines\n\t\t\"pkg/kubelet/volume_host.go\",          // 297 lines\n\t}\n\n\tenv.Await(InitialWorkspaceLoad)\n\n\tfor _, file := range files {\n\t\tenv.OpenFile(file)\n\t}\n\n\tenv.AfterChange()\n\n\tedit := makeEditFunc(env, files[0])\n\n\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(\"kubernetes\", \"diagnosePackageFiles\")); stopAndRecord != nil {\n\t\tdefer stopAndRecord()\n\t}\n\n\tfor b.Loop() {\n\t\tedit()\n\t\tvar wg sync.WaitGroup\n\t\tfor _, file := range files {\n\t\t\twg.Go(func() {\n\t\t\t\tfileDiags := env.Diagnostics(file)\n\t\t\t\tfor _, d := range fileDiags {\n\t\t\t\t\tif d.Severity == protocol.SeverityError {\n\t\t\t\t\t\tb.Errorf(\"unexpected error diagnostic: %s\", d.Message)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\twg.Wait()\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/didchange_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\n// Use a global edit counter as bench function may execute multiple times, and\n// we want to avoid cache hits. Use time.Now to also avoid cache hits from the\n// shared file cache.\nvar editID int64 = time.Now().UnixNano()\n\ntype changeTest struct {\n\trepo    string // repo identifier + optional disambiguating \".foo\" suffix\n\tfile    string\n\tcanSave bool\n}\n\nvar didChangeTests = []changeTest{\n\t{\"google-cloud-go\", \"internal/annotate.go\", true},\n\t{\"istio\", \"pkg/fuzz/util.go\", true},\n\t{\"kubernetes\", \"pkg/controller/lookup_cache.go\", true},\n\t// disable kubernetes.types as it fails on the builders, but not locally on mac or glinux\n\t// error is didchange_test.go:134: formatting before save: editing \"...\"\": column is beyond end of line;\n\t{\"kubernetes.types\", \"staging/src/k8s.io/api/core/v1/types.go\", false}, // results in 25K file batch!\n\t{\"kuma\", \"api/generic/insights.go\", true},\n\t{\"oracle\", \"dataintegration/data_type.go\", false}, // diagnoseSave fails because this package is generated\n\t{\"pkgsite\", \"internal/frontend/server.go\", true},\n\t{\"starlark\", \"starlark/eval.go\", true},\n\t{\"tools\", \"internal/lsp/cache/snapshot.go\", true},\n}\n\n// BenchmarkDidChange benchmarks modifications of a single file by making\n// synthetic modifications in a comment. It controls pacing by waiting for the\n// server to actually start processing the didChange notification before\n// proceeding. Notably it does not wait for diagnostics to complete.\nfunc BenchmarkDidChange(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\t// Insert the text we'll be modifying at the top of the file.\n\t\t\tedit := makeEditFunc(env, test.file)\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"didchange\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\t\t\tb.ResetTimer()\n\n\t\t\tfor b.Loop() {\n\t\t\t\tedit()\n\t\t\t\tenv.Await(env.StartedChange())\n\t\t\t}\n\t\t})\n\t}\n}\n\n// makeEditFunc prepares the given file for incremental editing, by inserting a\n// placeholder comment that will be overwritten with a new unique value by each\n// call to the resulting function. While makeEditFunc awaits gopls to finish\n// processing the initial edit, the callback for incremental edits does not\n// await any gopls state.\n//\n// This is used for benchmarks that must repeatedly invalidate a file's\n// contents.\n//\n// TODO(rfindley): use this throughout.\nfunc makeEditFunc(env *Env, file string) func() {\n\t// Insert the text we'll be modifying at the top of the file.\n\tenv.EditBuffer(file, protocol.TextEdit{NewText: \"// __TEST_PLACEHOLDER_0__\\n\"})\n\tenv.AfterChange()\n\n\treturn func() {\n\t\tedits := atomic.AddInt64(&editID, 1)\n\t\tenv.EditBuffer(file, protocol.TextEdit{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 0, Character: 0},\n\t\t\t\tEnd:   protocol.Position{Line: 1, Character: 0},\n\t\t\t},\n\t\t\t// Increment the placeholder text, to ensure cache misses.\n\t\t\tNewText: fmt.Sprintf(\"// __TEST_PLACEHOLDER_%d__\\n\", edits),\n\t\t})\n\t}\n}\n\nfunc BenchmarkDiagnoseChange(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\trunChangeDiagnosticsBenchmark(b, test, false, \"diagnoseChange\")\n\t}\n}\n\n// TODO(rfindley): add a benchmark for with a metadata-affecting change, when\n// this matters.\nfunc BenchmarkDiagnoseSave(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\trunChangeDiagnosticsBenchmark(b, test, true, \"diagnoseSave\")\n\t}\n}\n\n// runChangeDiagnosticsBenchmark runs a benchmark to edit the test file and\n// await the resulting diagnostics pass. If save is set, the file is also saved.\nfunc runChangeDiagnosticsBenchmark(b *testing.B, test changeTest, save bool, operation string) {\n\tb.Run(test.repo, func(b *testing.B) {\n\t\tif !test.canSave {\n\t\t\tb.Skipf(\"skipping as %s cannot be saved\", test.file)\n\t\t}\n\t\tsharedEnv := getRepo(b, test.repo).sharedEnv(b)\n\t\tconfig := fake.EditorConfig{\n\t\t\tEnv: map[string]string{\n\t\t\t\t\"GOPATH\": sharedEnv.Sandbox.GOPATH(),\n\t\t\t},\n\t\t\tSettings: map[string]any{\n\t\t\t\t\"diagnosticsDelay\": \"0s\",\n\t\t\t},\n\t\t}\n\t\t// Use a new env to avoid the diagnostic delay: we want to measure how\n\t\t// long it takes to produce the diagnostics.\n\t\tenv := getRepo(b, test.repo).newEnv(b, config, operation, false)\n\t\tdefer env.Close()\n\t\tenv.OpenFile(test.file)\n\t\t// Insert the text we'll be modifying at the top of the file.\n\t\tenv.EditBuffer(test.file, protocol.TextEdit{NewText: \"// __TEST_PLACEHOLDER_0__\\n\"})\n\t\tif save {\n\t\t\tenv.SaveBuffer(test.file)\n\t\t}\n\t\tenv.AfterChange()\n\t\tb.ResetTimer()\n\n\t\t// We must use an extra subtest layer here, so that we only set up the\n\t\t// shared env once (otherwise we pay additional overhead and the profiling\n\t\t// flags don't work).\n\t\tb.Run(\"diagnose\", func(b *testing.B) {\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, operation)); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\t\t\tfor b.Loop() {\n\t\t\t\tedits := atomic.AddInt64(&editID, 1)\n\t\t\t\tenv.EditBuffer(test.file, protocol.TextEdit{\n\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\tStart: protocol.Position{Line: 0, Character: 0},\n\t\t\t\t\t\tEnd:   protocol.Position{Line: 1, Character: 0},\n\t\t\t\t\t},\n\t\t\t\t\t// Increment the placeholder text, to ensure cache misses.\n\t\t\t\t\tNewText: fmt.Sprintf(\"// __TEST_PLACEHOLDER_%d__\\n\", edits),\n\t\t\t\t})\n\t\t\t\tif save {\n\t\t\t\t\tenv.SaveBuffer(test.file)\n\t\t\t\t}\n\t\t\t\tenv.AfterChange()\n\t\t\t}\n\t\t})\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The bench package implements benchmarks for various LSP operations.\n//\n// Benchmarks check out specific commits of popular and/or exemplary\n// repositories, and script an external gopls process via a fake text editor.\n// By default, benchmarks run the test executable as gopls (using a special\n// \"gopls mode\" environment variable). A different gopls binary may be used by\n// setting the -gopls_path or -gopls_commit flags.\n//\n// This package is a work in progress.\n//\n// # Profiling\n//\n// Benchmark functions run gopls in a separate process, which means the normal\n// test flags for profiling aren't useful. Instead the -gopls_cpuprofile,\n// -gopls_memprofile, -gopls_allocprofile, -gopls_blockprofile, and\n// -gopls_trace flags may be used to pass through profiling to the gopls\n// subprocess.\n//\n// Each of these flags sets a suffix for the respective gopls profile, which is\n// named according to the schema <repo>.<operation>.<suffix>. For example,\n// setting -gopls_cpuprofile=cpu will result in profiles named tools.iwl.cpu,\n// tools.rename.cpu, etc. In some cases, these profiles are for the entire\n// gopls subprocess (as in the initial workspace load), whereas in others they\n// span only the critical section of the benchmark. It is up to each benchmark\n// to implement profiling as appropriate.\n//\n// # Integration with perf.golang.org\n//\n// Benchmarks that run with -short are automatically tracked by\n// perf.golang.org, at\n// https://perf.golang.org/dashboard/?benchmark=all&repository=tools&branch=release-branch.go1.20\n//\n// # TODO\n//   - add more benchmarks, and more repositories\n//   - fix the perf dashboard to not require the branch= parameter\n//   - improve this documentation\npackage bench\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/hover_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"testing\"\n)\n\nfunc BenchmarkHover(b *testing.B) {\n\ttests := []struct {\n\t\trepo   string\n\t\tfile   string\n\t\tregexp string\n\t}{\n\t\t{\"google-cloud-go\", \"httpreplay/httpreplay.go\", `proxy\\.(ForRecording)`},\n\t\t{\"istio\", \"pkg/config/model.go\", `gogotypes\\.(MarshalAny)`},\n\t\t{\"kubernetes\", \"pkg/apis/core/types.go\", \"type (Pod)\"},\n\t\t{\"kuma\", \"api/generic/insights.go\", `proto\\.(Message)`},\n\t\t{\"pkgsite\", \"internal/log/log.go\", `derrors\\.(Wrap)`},\n\t\t{\"starlark\", \"starlark/eval.go\", \"prog.compiled.(Encode)\"},\n\t\t{\"tools\", \"internal/lsp/cache/check.go\", `(snapshot)\\) buildKey`},\n\t}\n\n\tfor _, test := range tests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\tloc := env.RegexpSearch(test.file, test.regexp)\n\t\t\tenv.AfterChange()\n\n\t\t\tenv.Hover(loc) // pre-warm the query\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"hover\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.Hover(loc) // pre-warm the query\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/implementations_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport \"testing\"\n\nfunc BenchmarkImplementations(b *testing.B) {\n\ttests := []struct {\n\t\trepo   string\n\t\tfile   string\n\t\tregexp string\n\t}{\n\t\t{\"google-cloud-go\", \"httpreplay/httpreplay.go\", `type (Recorder)`},\n\t\t{\"istio\", \"pkg/config/mesh/watcher.go\", `type (Watcher)`},\n\t\t{\"kubernetes\", \"pkg/controller/lookup_cache.go\", `objectWithMeta`},\n\t\t{\"kuma\", \"api/generic/insights.go\", `type (Insight)`},\n\t\t{\"pkgsite\", \"internal/datasource.go\", `type (DataSource)`},\n\t\t{\"starlark\", \"syntax/syntax.go\", `type (Expr)`},\n\t\t{\"tools\", \"internal/lsp/source/view.go\", `type (Snapshot)`},\n\t}\n\n\tfor _, test := range tests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\tloc := env.RegexpSearch(test.file, test.regexp)\n\t\t\tenv.AfterChange()\n\t\t\tenv.Implementations(loc) // pre-warm the query\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"implementations\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.Implementations(loc)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/imports_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\nvar gopath = flag.String(\"gopath\", \"\", \"if set, run goimports scan with this GOPATH value\")\n\nfunc BenchmarkInitialGoimportsScan(b *testing.B) {\n\tif *gopath == \"\" {\n\t\t// This test doesn't make much sense with a tiny module cache.\n\t\t// For now, don't bother trying to construct a huge cache, since it likely\n\t\t// wouldn't work well on the perf builder. Instead, this benchmark only\n\t\t// runs with a pre-existing GOPATH.\n\t\tb.Skip(\"imports scan requires an explicit GOPATH to be set with -gopath\")\n\t}\n\n\trepo := getRepo(b, \"tools\") // since this a test of module cache scanning, any repo will do\n\n\tfor b.Loop() {\n\t\tfunc() {\n\t\t\t// Unfortunately we (intentionally) don't support resetting the module\n\t\t\t// cache scan state, so in order to have an accurate benchmark we must\n\t\t\t// effectively restart gopls on every iteration.\n\t\t\t//\n\t\t\t// Warning: this can cause this benchmark to run quite slowly if the\n\t\t\t// observed time (when the timer is running) is a tiny fraction of the\n\t\t\t// actual time.\n\t\t\tb.StopTimer()\n\t\t\tconfig := fake.EditorConfig{\n\t\t\t\tEnv: map[string]string{\"GOPATH\": *gopath},\n\t\t\t}\n\t\t\tenv := repo.newEnv(b, config, \"imports\", false)\n\t\t\tdefer env.Close()\n\t\t\tenv.Await(InitialWorkspaceLoad)\n\n\t\t\t// Create a buffer with a dangling selector where the receiver is a single\n\t\t\t// character ('a') that matches a large fraction of the module cache.\n\t\t\tenv.CreateBuffer(\"internal/lsp/cache/temp.go\", `\n// This is a temp file to exercise goimports scan of the module cache.\npackage cache\n\nfunc _() {\n\t_ = a.B // a dangling selector causes goimports to scan many packages\n}\n`)\n\t\t\tenv.AfterChange()\n\n\t\t\t// Force a scan of the imports cache, so that the goimports algorithm\n\t\t\t// observes all directories.\n\t\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\t\tCommand: command.ScanImports.String(),\n\t\t\t}, nil)\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, \"importsscan\"); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tb.StartTimer()\n\t\t\tif false {\n\t\t\t\t// golang/go#67923: testing resuming imports scanning after a\n\t\t\t\t// cancellation.\n\t\t\t\t//\n\t\t\t\t// Cancelling and then resuming the scan should take around the same\n\t\t\t\t// amount of time.\n\t\t\t\tctx, cancel := context.WithTimeout(env.Ctx, 50*time.Millisecond)\n\t\t\t\tdefer cancel()\n\t\t\t\tif err := env.Editor.OrganizeImports(ctx, \"internal/lsp/cache/temp.go\"); err != nil {\n\t\t\t\t\tb.Logf(\"organize imports failed: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tenv.OrganizeImports(\"internal/lsp/cache/temp.go\")\n\t\t}()\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/iwl_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\n// BenchmarkInitialWorkspaceLoad benchmarks the initial workspace load time for\n// a new editing session.\n//\n// The OpenFiles variant of this test is more realistic: who cares if gopls is\n// initialized if you can't use it? However, this test is left as is to\n// preserve the validity of historical data, and to represent the baseline\n// performance of validating the workspace state.\nfunc BenchmarkInitialWorkspaceLoad(b *testing.B) {\n\trepoNames := []string{\n\t\t\"google-cloud-go\",\n\t\t\"istio\",\n\t\t\"kubernetes\",\n\t\t\"kuma\",\n\t\t\"oracle\",\n\t\t\"pkgsite\",\n\t\t\"starlark\",\n\t\t\"tools\",\n\t\t\"hashiform\",\n\t}\n\tfor _, repoName := range repoNames {\n\t\tb.Run(repoName, func(b *testing.B) {\n\t\t\trepo := getRepo(b, repoName)\n\t\t\t// get the (initialized) shared env to ensure the cache is warm.\n\t\t\t// Reuse its GOPATH so that we get cache hits for things in the module\n\t\t\t// cache.\n\t\t\tsharedEnv := repo.sharedEnv(b)\n\t\t\tb.ResetTimer()\n\n\t\t\tfor b.Loop() {\n\t\t\t\tdoIWL(b, sharedEnv.Sandbox.GOPATH(), repo, nil)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// BenchmarkInitialWorkspaceLoadOpenFiles benchmarks the initial workspace load\n// after opening one or more files.\n//\n// It may differ significantly from [BenchmarkInitialWorkspaceLoad], since\n// there is various active state that is proportional to the number of open\n// files.\nfunc BenchmarkInitialWorkspaceLoadOpenFiles(b *testing.B) {\n\tfor _, t := range didChangeTests {\n\t\tb.Run(t.repo, func(b *testing.B) {\n\t\t\trepo := getRepo(b, t.repo)\n\t\t\tsharedEnv := repo.sharedEnv(b)\n\t\t\tb.ResetTimer()\n\n\t\t\tfor b.Loop() {\n\t\t\t\tdoIWL(b, sharedEnv.Sandbox.GOPATH(), repo, []string{t.file})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc doIWL(b *testing.B, gopath string, repo *repo, openfiles []string) {\n\t// Exclude the time to set up the env from the benchmark time, as this may\n\t// involve installing gopls and/or checking out the repo dir.\n\tb.StopTimer()\n\tconfig := fake.EditorConfig{Env: map[string]string{\"GOPATH\": gopath}}\n\tenv := repo.newEnv(b, config, \"iwl\", true)\n\tdefer env.Close()\n\tb.StartTimer()\n\n\t// TODO(rfindley): not awaiting the IWL here leads to much more volatile\n\t// results. Investigate.\n\tenv.Await(InitialWorkspaceLoad)\n\n\tfor _, f := range openfiles {\n\t\tenv.OpenFile(f)\n\t}\n\n\tenv.AfterChange()\n\n\tif env.Editor.HasCommand(command.MemStats) {\n\t\tb.StopTimer()\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand: command.MemStats.String(),\n\t\t}\n\t\tvar memstats command.MemStatsResult\n\t\tenv.ExecuteCommand(params, &memstats)\n\t\tb.ReportMetric(float64(memstats.HeapAlloc), \"alloc_bytes\")\n\t\tb.ReportMetric(float64(memstats.HeapInUse), \"in_use_bytes\")\n\t\tb.ReportMetric(float64(memstats.TotalAlloc), \"total_alloc_bytes\")\n\t\tb.StartTimer()\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/references_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport \"testing\"\n\nfunc BenchmarkReferences(b *testing.B) {\n\ttests := []struct {\n\t\trepo   string\n\t\tfile   string\n\t\tregexp string\n\t}{\n\t\t{\"google-cloud-go\", \"httpreplay/httpreplay.go\", `func (NewRecorder)`},\n\t\t{\"istio\", \"pkg/config/model.go\", \"type (Meta)\"},\n\t\t{\"kubernetes\", \"pkg/controller/lookup_cache.go\", \"type (objectWithMeta)\"}, // TODO: choose an exported identifier\n\t\t{\"kuma\", \"pkg/events/interfaces.go\", \"type (Event)\"},\n\t\t{\"pkgsite\", \"internal/log/log.go\", \"func (Infof)\"},\n\t\t{\"starlark\", \"syntax/syntax.go\", \"type (Ident)\"},\n\t\t{\"tools\", \"internal/lsp/source/view.go\", \"type (Snapshot)\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\tloc := env.RegexpSearch(test.file, test.regexp)\n\t\t\tenv.AfterChange()\n\t\t\tenv.References(loc) // pre-warm the query\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"references\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.References(loc)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/reload_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage bench\n\nimport (\n\t\"fmt\"\n\t\"path\"\n\t\"regexp\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// BenchmarkReload benchmarks reloading a file metadata after a change to an import.\n//\n// This ensures we are able to diagnose a changed file without reloading all\n// invalidated packages. See also golang/go#61344\nfunc BenchmarkReload(b *testing.B) {\n\ttype replace map[string]string\n\ttests := []struct {\n\t\trepo string\n\t\tfile string\n\t\t// replacements must be 'reversible', in the sense that the replacing\n\t\t// string is unique.\n\t\treplace replace\n\t}{\n\t\t// pkg/util/hash is transitively imported by a large number of packages. We\n\t\t// should not need to reload those packages to get a diagnostic.\n\t\t{\"kubernetes\", \"pkg/util/hash/hash.go\", replace{`\"hash\"`: `\"hashx\"`}},\n\t\t{\"kubernetes\", \"pkg/kubelet/kubelet.go\", replace{\n\t\t\t`\"k8s.io/kubernetes/pkg/kubelet/config\"`: `\"k8s.io/kubernetes/pkg/kubelet/configx\"`,\n\t\t}},\n\t}\n\n\tfor _, test := range tests {\n\t\tb.Run(fmt.Sprintf(\"%s/%s\", test.repo, path.Base(test.file)), func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\tenv.AfterChange()\n\n\t\t\tprofileName := qualifiedName(\"reload\", test.repo, path.Base(test.file))\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, profileName); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tb.ResetTimer()\n\t\t\tfor b.Loop() {\n\t\t\t\t// Mutate the file. This may result in cache hits, but that's OK: the\n\t\t\t\t// goal is to ensure that we don't reload more than just the current\n\t\t\t\t// package.\n\t\t\t\tfor k, v := range test.replace {\n\t\t\t\t\tenv.RegexpReplace(test.file, regexp.QuoteMeta(k), v)\n\t\t\t\t}\n\t\t\t\t// Note: don't use env.AfterChange() here: we only want to await the\n\t\t\t\t// first diagnostic.\n\t\t\t\t//\n\t\t\t\t// Awaiting a full diagnosis would await diagnosing everything, which\n\t\t\t\t// would require reloading everything.\n\t\t\t\tenv.Await(Diagnostics(ForFile(test.file)))\n\t\t\t\tfor k, v := range test.replace {\n\t\t\t\t\tenv.RegexpReplace(test.file, regexp.QuoteMeta(v), k)\n\t\t\t\t}\n\t\t\t\tenv.Await(NoDiagnostics(ForFile(test.file)))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/rename_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc BenchmarkRename(b *testing.B) {\n\ttests := []struct {\n\t\trepo     string\n\t\tfile     string\n\t\tregexp   string\n\t\tbaseName string\n\t}{\n\t\t{\"google-cloud-go\", \"httpreplay/httpreplay.go\", `func (NewRecorder)`, \"NewRecorder\"},\n\t\t{\"istio\", \"pkg/config/model.go\", `(Namespace) string`, \"Namespace\"},\n\t\t{\"kubernetes\", \"pkg/controller/lookup_cache.go\", `hashutil\\.(DeepHashObject)`, \"DeepHashObject\"},\n\t\t{\"kuma\", \"pkg/events/interfaces.go\", `Delete`, \"Delete\"},\n\t\t{\"pkgsite\", \"internal/log/log.go\", `func (Infof)`, \"Infof\"},\n\t\t{\"starlark\", \"starlark/eval.go\", `Program\\) (Filename)`, \"Filename\"},\n\t\t{\"tools\", \"internal/lsp/cache/snapshot.go\", `meta \\*(metadataGraph)`, \"metadataGraph\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tnames := 0 // bench function may execute multiple times\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tloc := env.RegexpSearch(test.file, test.regexp)\n\t\t\tenv.Await(env.DoneWithOpen())\n\t\t\tenv.Rename(loc, test.baseName+\"X\") // pre-warm the query\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"rename\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tnames++\n\t\t\t\tnewName := fmt.Sprintf(\"%s%d\", test.baseName, names)\n\t\t\t\tenv.Rename(loc, newName)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/repo_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\n// repos holds shared repositories for use in benchmarks.\n//\n// These repos were selected to represent a variety of different types of\n// codebases.\nvar repos = map[string]*repo{\n\t// google-cloud-go has 145 workspace modules (!), and is quite large.\n\t\"google-cloud-go\": {\n\t\tname:   \"google-cloud-go\",\n\t\turl:    \"https://github.com/googleapis/google-cloud-go.git\",\n\t\tcommit: \"07da765765218debf83148cc7ed8a36d6e8921d5\",\n\t\tinDir:  flag.String(\"cloud_go_dir\", \"\", \"if set, reuse this directory as google-cloud-go@07da7657\"),\n\t},\n\n\t// Used by x/benchmarks; large.\n\t\"istio\": {\n\t\tname:   \"istio\",\n\t\turl:    \"https://github.com/istio/istio\",\n\t\tcommit: \"1.17.0\",\n\t\tinDir:  flag.String(\"istio_dir\", \"\", \"if set, reuse this directory as istio@v1.17.0\"),\n\t},\n\n\t// Kubernetes is a large repo with many dependencies, and in the past has\n\t// been about as large a repo as gopls could handle.\n\t\"kubernetes\": {\n\t\tname:   \"kubernetes\",\n\t\turl:    \"https://github.com/kubernetes/kubernetes\",\n\t\tcommit: \"v1.24.0\",\n\t\tshort:  true,\n\t\tinDir:  flag.String(\"kubernetes_dir\", \"\", \"if set, reuse this directory as kubernetes@v1.24.0\"),\n\t},\n\n\t// A large, industrial application.\n\t\"kuma\": {\n\t\tname:   \"kuma\",\n\t\turl:    \"https://github.com/kumahq/kuma\",\n\t\tcommit: \"2.1.1\",\n\t\tinDir:  flag.String(\"kuma_dir\", \"\", \"if set, reuse this directory as kuma@v2.1.1\"),\n\t},\n\n\t// A repo containing a very large package (./dataintegration).\n\t\"oracle\": {\n\t\tname:   \"oracle\",\n\t\turl:    \"https://github.com/oracle/oci-go-sdk.git\",\n\t\tcommit: \"v65.43.0\",\n\t\tshort:  true,\n\t\tinDir:  flag.String(\"oracle_dir\", \"\", \"if set, reuse this directory as oracle/oci-go-sdk@v65.43.0\"),\n\t},\n\n\t// x/pkgsite is familiar and represents a common use case (a webserver). It\n\t// also has a number of static non-go files and template files.\n\t\"pkgsite\": {\n\t\tname:   \"pkgsite\",\n\t\turl:    \"https://go.googlesource.com/pkgsite\",\n\t\tcommit: \"81f6f8d4175ad0bf6feaa03543cc433f8b04b19b\",\n\t\tshort:  true,\n\t\tinDir:  flag.String(\"pkgsite_dir\", \"\", \"if set, reuse this directory as pkgsite@81f6f8d4\"),\n\t},\n\n\t// A tiny self-contained project.\n\t\"starlark\": {\n\t\tname:   \"starlark\",\n\t\turl:    \"https://github.com/google/starlark-go\",\n\t\tcommit: \"3f75dec8e4039385901a30981e3703470d77e027\",\n\t\tshort:  true,\n\t\tinDir:  flag.String(\"starlark_dir\", \"\", \"if set, reuse this directory as starlark@3f75dec8\"),\n\t},\n\n\t// The current repository, which is medium-small and has very few dependencies.\n\t\"tools\": {\n\t\tname:   \"tools\",\n\t\turl:    \"https://go.googlesource.com/tools\",\n\t\tcommit: \"gopls/v0.9.0\",\n\t\tshort:  true,\n\t\tinDir:  flag.String(\"tools_dir\", \"\", \"if set, reuse this directory as x/tools@v0.9.0\"),\n\t},\n\n\t// A repo of similar size to kubernetes, but with substantially more\n\t// complex types that led to a serious performance regression (issue #60621).\n\t\"hashiform\": {\n\t\tname:   \"hashiform\",\n\t\turl:    \"https://github.com/hashicorp/terraform-provider-aws\",\n\t\tcommit: \"ac55de2b1950972d93feaa250d7505d9ed829c7c\",\n\t\tinDir:  flag.String(\"hashiform_dir\", \"\", \"if set, reuse this directory as hashiform@ac55de2\"),\n\t},\n}\n\n// getRepo gets the requested repo, and skips the test if -short is set and\n// repo is not configured as a short repo.\n//\n// The name may include an optional \".foo\" suffix after the repo\n// identifier. This allows several tests to use the same repo but have\n// distinct test names and associated file names.\nfunc getRepo(tb testing.TB, name string) *repo {\n\ttb.Helper()\n\tname, _, _ = strings.Cut(name, \".\") // remove \".foo\" suffix\n\trepo := repos[name]\n\tif repo == nil {\n\t\ttb.Fatalf(\"repo %s does not exist\", name)\n\t}\n\tif !repo.short && testing.Short() {\n\t\ttb.Skipf(\"large repo %s does not run with -short\", repo.name)\n\t}\n\treturn repo\n}\n\n// A repo represents a working directory for a repository checked out at a\n// specific commit.\n//\n// Repos are used for sharing state across benchmarks that operate on the same\n// codebase.\ntype repo struct {\n\t// static configuration\n\tname   string  // must be unique, used for subdirectory\n\turl    string  // repo url\n\tcommit string  // full commit hash or tag\n\tshort  bool    // whether this repo runs with -short\n\tinDir  *string // if set, use this dir as url@commit, and don't delete\n\n\tdirOnce sync.Once\n\tdir     string // directory containing source code checked out to url@commit\n\n\t// shared editor state\n\teditorOnce sync.Once\n\teditor     *fake.Editor\n\tsandbox    *fake.Sandbox\n\tawaiter    *Awaiter\n}\n\n// reusableDir return a reusable directory for benchmarking, or \"\".\n//\n// If the user specifies a directory, the test will create and populate it\n// on the first run and re-use it on subsequent runs. Otherwise it will\n// create, populate, and delete a temporary directory.\nfunc (r *repo) reusableDir() string {\n\tif r.inDir == nil {\n\t\treturn \"\"\n\t}\n\treturn *r.inDir\n}\n\n// getDir returns directory containing repo source code, creating it if\n// necessary. It is safe for concurrent use.\nfunc (r *repo) getDir() string {\n\tr.dirOnce.Do(func() {\n\t\tif r.dir = r.reusableDir(); r.dir == \"\" {\n\t\t\tr.dir = filepath.Join(getTempDir(), r.name)\n\t\t}\n\n\t\t_, err := os.Stat(r.dir)\n\t\tswitch {\n\t\tcase os.IsNotExist(err):\n\t\t\tlog.Printf(\"cloning %s@%s into %s\", r.url, r.commit, r.dir)\n\t\t\tif err := shallowClone(r.dir, r.url, r.commit); err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\tcase err != nil:\n\t\t\tlog.Fatal(err)\n\t\tdefault:\n\t\t\tlog.Printf(\"reusing %s as %s@%s\", r.dir, r.url, r.commit)\n\t\t}\n\t})\n\treturn r.dir\n}\n\n// sharedEnv returns a shared benchmark environment. It is safe for concurrent\n// use.\n//\n// Every call to sharedEnv uses the same editor and sandbox, as a means to\n// avoid reinitializing the editor for large repos. Calling repo.Close cleans\n// up the shared environment.\n//\n// Repos in the package-local Repos var are closed at the end of the test main\n// function.\nfunc (r *repo) sharedEnv(tb testing.TB) *Env {\n\tr.editorOnce.Do(func() {\n\t\tdir := r.getDir()\n\n\t\tstart := time.Now()\n\t\tlog.Printf(\"starting initial workspace load for %s\", r.name)\n\t\tts, err := newGoplsConnector(profileArgs(r.name, false))\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tr.sandbox, r.editor, r.awaiter, err = connectEditor(dir, fake.EditorConfig{}, ts)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"connecting editor: %v\", err)\n\t\t}\n\n\t\tif err := r.awaiter.Await(context.Background(), InitialWorkspaceLoad); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tlog.Printf(\"initial workspace load (cold) for %s took %v\", r.name, time.Since(start))\n\t})\n\n\treturn &Env{\n\t\tTB:      tb,\n\t\tCtx:     context.Background(),\n\t\tEditor:  r.editor,\n\t\tSandbox: r.sandbox,\n\t\tAwaiter: r.awaiter,\n\t}\n}\n\n// newEnv returns a new Env connected to a new gopls process communicating\n// over stdin/stdout. It is safe for concurrent use.\n//\n// It is the caller's responsibility to call Close on the resulting Env when it\n// is no longer needed.\nfunc (r *repo) newEnv(tb testing.TB, config fake.EditorConfig, forOperation string, cpuProfile bool) *Env {\n\tdir := r.getDir()\n\n\targs := profileArgs(qualifiedName(r.name, forOperation), cpuProfile)\n\tts, err := newGoplsConnector(args)\n\tif err != nil {\n\t\ttb.Fatal(err)\n\t}\n\tsandbox, editor, awaiter, err := connectEditor(dir, config, ts)\n\tif err != nil {\n\t\tlog.Fatalf(\"connecting editor: %v\", err)\n\t}\n\n\treturn &Env{\n\t\tTB:      tb,\n\t\tCtx:     context.Background(),\n\t\tEditor:  editor,\n\t\tSandbox: sandbox,\n\t\tAwaiter: awaiter,\n\t}\n}\n\n// Close cleans up shared state referenced by the repo.\nfunc (r *repo) Close() error {\n\tvar errBuf bytes.Buffer\n\tif r.editor != nil {\n\t\tif err := r.editor.Close(context.Background()); err != nil {\n\t\t\tfmt.Fprintf(&errBuf, \"closing editor: %v\", err)\n\t\t}\n\t}\n\tif r.sandbox != nil {\n\t\tif err := r.sandbox.Close(); err != nil {\n\t\t\tfmt.Fprintf(&errBuf, \"closing sandbox: %v\", err)\n\t\t}\n\t}\n\tif r.dir != \"\" && r.reusableDir() == \"\" {\n\t\tif err := os.RemoveAll(r.dir); err != nil {\n\t\t\tfmt.Fprintf(&errBuf, \"cleaning dir: %v\", err)\n\t\t}\n\t}\n\tif errBuf.Len() > 0 {\n\t\treturn errors.New(errBuf.String())\n\t}\n\treturn nil\n}\n\n// cleanup cleans up state that is shared across benchmark functions.\nfunc cleanup() error {\n\tvar errBuf bytes.Buffer\n\tfor _, repo := range repos {\n\t\tif err := repo.Close(); err != nil {\n\t\t\tfmt.Fprintf(&errBuf, \"closing %q: %v\", repo.name, err)\n\t\t}\n\t}\n\tif tempDir != \"\" {\n\t\tif err := os.RemoveAll(tempDir); err != nil {\n\t\t\tfmt.Fprintf(&errBuf, \"cleaning tempDir: %v\", err)\n\t\t}\n\t}\n\tif errBuf.Len() > 0 {\n\t\treturn errors.New(errBuf.String())\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/stress_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n)\n\n// github.com/pilosa/pilosa is a repository that has historically caused\n// significant memory problems for Gopls. We use it for a simple stress test\n// that types arbitrarily in a file with lots of dependents.\n\nvar pilosaPath = flag.String(\"pilosa_path\", \"\", \"Path to a directory containing \"+\n\t\"github.com/pilosa/pilosa, for stress testing. Do not set this unless you \"+\n\t\"know what you're doing!\")\n\nfunc TestPilosaStress(t *testing.T) {\n\t// TODO(rfindley): revisit this test and make it is hermetic: it should check\n\t// out pilosa into a directory.\n\t//\n\t// Note: This stress test has not been run recently, and may no longer\n\t// function properly.\n\tif *pilosaPath == \"\" {\n\t\tt.Skip(\"-pilosa_path not configured\")\n\t}\n\n\tsandbox, err := fake.NewSandbox(&fake.SandboxConfig{\n\t\tWorkdir: *pilosaPath,\n\t\tGOPROXY: \"https://proxy.golang.org\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tserver := lsprpc.NewStreamServer(cache.New(nil), false, nil)\n\tts := servertest.NewPipeServer(server, jsonrpc2.NewRawStream)\n\n\tctx := context.Background()\n\teditor, err := fake.NewEditor(sandbox, fake.EditorConfig{}).Connect(ctx, ts, fake.ClientHooks{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfiles := []string{\n\t\t\"cmd.go\",\n\t\t\"internal/private.pb.go\",\n\t\t\"roaring/roaring.go\",\n\t\t\"roaring/roaring_internal_test.go\",\n\t\t\"server/handler_test.go\",\n\t}\n\tfor _, file := range files {\n\t\tif err := editor.OpenFile(ctx, file); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tctx, cancel := context.WithTimeout(ctx, 10*time.Minute)\n\tdefer cancel()\n\n\ti := 1\n\t// MagicNumber is an identifier that occurs in roaring.go. Just change it\n\t// arbitrarily.\n\tif err := editor.RegexpReplace(ctx, \"roaring/roaring.go\", \"MagicNumber\", fmt.Sprintf(\"MagicNumber%d\", 1)); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tdefault:\n\t\t}\n\t\tif err := editor.RegexpReplace(ctx, \"roaring/roaring.go\", fmt.Sprintf(\"MagicNumber%d\", i), fmt.Sprintf(\"MagicNumber%d\", i+1)); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// Simulate (very fast) typing.\n\t\t//\n\t\t// Typing 80 wpm ~150ms per keystroke.\n\t\ttime.Sleep(150 * time.Millisecond)\n\t\ti++\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/tests_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage bench\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc BenchmarkPackagesCommand(b *testing.B) {\n\t// By convention, x/benchmarks runs the gopls benchmarks with -short, so that\n\t// we can use this flag to filter out benchmarks that should not be run by\n\t// the perf builder.\n\t//\n\t// In this case, the benchmark must be skipped because the current baseline\n\t// (gopls@v0.11.0) lacks the gopls.package command.\n\tif testing.Short() {\n\t\tb.Skip(\"not supported by the benchmark dashboard baseline\")\n\t}\n\n\ttests := []struct {\n\t\trepo    string\n\t\tfiles   []string\n\t\trecurse bool\n\t}{\n\t\t{\"tools\", []string{\"internal/lsp/debounce_test.go\"}, false},\n\t}\n\tfor _, test := range tests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\targs := command.PackagesArgs{\n\t\t\t\tMode: command.NeedTests,\n\t\t\t}\n\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tfor _, file := range test.files {\n\t\t\t\tenv.OpenFile(file)\n\t\t\t\tdefer closeBuffer(b, env, file)\n\t\t\t\targs.Files = append(args.Files, env.Editor.DocumentURI(file))\n\t\t\t}\n\t\t\tenv.AfterChange()\n\n\t\t\tresult := executePackagesCmd(b, env, args) // pre-warm\n\n\t\t\t// sanity check JSON {en,de}coding\n\t\t\tvar pkgs command.PackagesResult\n\t\t\tdata, err := json.Marshal(result)\n\t\t\tif err != nil {\n\t\t\t\tb.Fatal(err)\n\t\t\t}\n\t\t\terr = json.Unmarshal(data, &pkgs)\n\t\t\tif err != nil {\n\t\t\t\tb.Fatal(err)\n\t\t\t}\n\t\t\tvar haveTest bool\n\t\t\tfor _, pkg := range pkgs.Packages {\n\t\t\t\tfor _, file := range pkg.TestFiles {\n\t\t\t\t\tif len(file.Tests) > 0 {\n\t\t\t\t\t\thaveTest = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !haveTest {\n\t\t\t\tb.Fatalf(\"Expected tests\")\n\t\t\t}\n\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"packages\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\texecutePackagesCmd(b, env, args)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc executePackagesCmd(t testing.TB, env *integration.Env, args command.PackagesArgs) any {\n\tt.Helper()\n\tcmd := command.NewPackagesCommand(\"Packages\", args)\n\tresult, err := env.Editor.Server.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{\n\t\tCommand:   command.Packages.String(),\n\t\tArguments: cmd.Arguments,\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/typing_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// BenchmarkTyping simulates typing steadily in a single file at different\n// paces.\n//\n// The key metric for this benchmark is not latency, but cpu_seconds per\n// operation.\nfunc BenchmarkTyping(b *testing.B) {\n\tfor _, test := range didChangeTests {\n\t\tb.Run(test.repo, func(b *testing.B) {\n\t\t\tenv := getRepo(b, test.repo).sharedEnv(b)\n\t\t\tenv.OpenFile(test.file)\n\t\t\tdefer closeBuffer(b, env, test.file)\n\n\t\t\t// Insert the text we'll be modifying at the top of the file.\n\t\t\tenv.EditBuffer(test.file, protocol.TextEdit{NewText: \"// __TEST_PLACEHOLDER_0__\\n\"})\n\t\t\tenv.AfterChange()\n\n\t\t\tdelays := []time.Duration{\n\t\t\t\t10 * time.Millisecond,  // automated changes\n\t\t\t\t50 * time.Millisecond,  // very fast mashing, or fast key sequences\n\t\t\t\t150 * time.Millisecond, // avg interval for 80wpm typing.\n\t\t\t}\n\n\t\t\tfor _, delay := range delays {\n\t\t\t\tb.Run(delay.String(), func(b *testing.B) {\n\t\t\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, \"typing\")); stopAndRecord != nil {\n\t\t\t\t\t\tdefer stopAndRecord()\n\t\t\t\t\t}\n\t\t\t\t\tticker := time.NewTicker(delay)\n\t\t\t\t\tfor b.Loop() {\n\t\t\t\t\t\tedits := atomic.AddInt64(&editID, 1)\n\t\t\t\t\t\tenv.EditBuffer(test.file, protocol.TextEdit{\n\t\t\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\t\t\tStart: protocol.Position{Line: 0, Character: 0},\n\t\t\t\t\t\t\t\tEnd:   protocol.Position{Line: 1, Character: 0},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// Increment the placeholder text, to ensure cache misses.\n\t\t\t\t\t\t\tNewText: fmt.Sprintf(\"// __TEST_PLACEHOLDER_%d__\\n\", edits),\n\t\t\t\t\t\t})\n\t\t\t\t\t\t<-ticker.C\n\t\t\t\t\t}\n\t\t\t\t\tb.StopTimer()\n\t\t\t\t\tticker.Stop()\n\t\t\t\t\tenv.AfterChange() // wait for all change processing to complete\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/unimported_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/modindex\"\n)\n\n// This code is designed to show the comparative effectiveness\n// of the current and the old ways of doing unimported completions.\n// It should only be run by hand when there is an existing module\n// cache and module cache index. It compares the two algorithms\n// for various values of the completion budget. \"gopls\" is the\n// current algorithm, \"goimports\" is the old one. [On my workstation\n// the old algorithms occasionally fails to find the completion,\n// and when it does it is more than 10 times slower.]\nfunc BenchmarkLocalModcache(b *testing.B) {\n\tb.Skip(\"only run by hand\")\n\tbudgets := []string{\"0s\", \"100ms\", \"200ms\", \"500ms\", \"1s\", \"5s\"}\n\tsources := []string{\"gopls\", \"goimports\"}\n\tfor _, budget := range budgets {\n\t\tb.Run(fmt.Sprintf(\"budget=%s\", budget), func(b *testing.B) {\n\t\t\tfor _, source := range sources {\n\t\t\t\tb.Run(fmt.Sprintf(\"source=%s\", source), func(b *testing.B) {\n\t\t\t\t\trunModcacheCompletion(b, budget, source)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc runModcacheCompletion(b *testing.B, budget, source string) {\n\t// First set up the program to be edited\n\tgomod := `\nmodule mod.com\n\ngo 1.21\n`\n\tpat := `\npackage main\nvar _ = %s.%s\n`\n\tpkg, name, modcache := findSym(b)\n\tname, _, _ = strings.Cut(name, \" \")\n\tmainfile := fmt.Sprintf(pat, pkg, name)\n\t// Second, create the Env and start gopls\n\tdir := getTempDir()\n\tif err := os.Mkdir(dir, 0750); err != nil {\n\t\tif !os.IsExist(err) {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\tdefer os.RemoveAll(dir) // is this right? needed?\n\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), []byte(gomod), 0644); err != nil {\n\t\tb.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(dir, \"main.go\"), []byte(mainfile), 0644); err != nil {\n\t\tb.Fatal(err)\n\t}\n\tts, err := newGoplsConnector(nil)\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\t// PJW: put better EditorConfig here\n\tenvvars := map[string]string{\n\t\t\"GOMODCACHE\": modcache,\n\t\t//\"GOPATH\":     sandbox.GOPATH(), // do we need a GOPATH?\n\t}\n\tfc := fake.EditorConfig{\n\t\tEnv: envvars,\n\t\tSettings: map[string]any{\n\t\t\t\"completeUnimported\": true,\n\t\t\t\"completionBudget\":   budget, // \"0s\", \"100ms\"\n\t\t\t\"importsSource\":      source, // \"gopls\" or \"goimports\"\n\t\t},\n\t}\n\tsandbox, editor, awaiter, err := connectEditor(dir, fc, ts)\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tdefer sandbox.Close()\n\tdefer editor.Close(context.Background())\n\tif err := awaiter.Await(context.Background(), InitialWorkspaceLoad); err != nil {\n\t\tb.Fatal(err)\n\t}\n\tenv := &Env{\n\t\tTB:      b,\n\t\tCtx:     context.Background(),\n\t\tEditor:  editor,\n\t\tSandbox: sandbox,\n\t\tAwaiter: awaiter,\n\t}\n\t// Check that completion works as expected\n\tenv.CreateBuffer(\"main.go\", mainfile)\n\tenv.AfterChange()\n\tloc := env.RegexpSearch(\"main.go\", name)\n\tcompletions := env.Completion(loc)\n\tif len(completions.Items) == 0 {\n\t\tb.Error(\"no completions\")\n\t}\n\n\t// run benchmark\n\tfor b.Loop() {\n\t\tloc := env.RegexpSearch(\"main.go\", name)\n\t\tenv.Completion(loc)\n\t}\n}\n\n// find some symbol in the module cache\nfunc findSym(t testing.TB) (pkg, name, gomodcache string) {\n\tinitForTest(t) // set modindex.IndexDir\n\tcmd := exec.Command(\"go\", \"env\", \"GOMODCACHE\")\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tmodcache := strings.TrimSpace(string(out))\n\tix, err := modindex.Read(modcache)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif ix == nil {\n\t\tt.Fatal(\"nil index\")\n\t}\n\t// find some symbol in the module cache\n\tnth := 100 // or something\n\tfor _, e := range ix.Entries {\n\t\tif token.IsExported(e.PkgName) || strings.HasPrefix(e.PkgName, \"_\") {\n\t\t\tcontinue // weird stuff in module cache\n\t\t}\n\n\t\tfor _, nm := range e.Names {\n\t\t\tnth--\n\t\t\tif nth == 0 {\n\t\t\t\treturn e.PkgName, nm, modcache\n\t\t\t}\n\t\t}\n\t}\n\tt.Fatalf(\"index doesn't have enough usable names, need another %d\", nth)\n\treturn \"\", \"\", modcache\n}\n\n// Set IndexDir, avoiding the special case for tests,\nfunc initForTest(t testing.TB) {\n\tdir, err := os.UserCacheDir()\n\tif err != nil {\n\t\tt.Fatalf(\"os.UserCacheDir: %v\", err)\n\t}\n\tdir = filepath.Join(dir, \"goimports\")\n\tmodindex.IndexDir = dir\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/bench/workspace_symbols_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bench\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n)\n\nvar symbolQuery = flag.String(\"symbol_query\", \"test\", \"symbol query to use in benchmark\")\n\n// BenchmarkWorkspaceSymbols benchmarks the time to execute a workspace symbols\n// request (controlled by the -symbol_query flag).\nfunc BenchmarkWorkspaceSymbols(b *testing.B) {\n\tfor name := range repos {\n\t\tb.Run(name, func(b *testing.B) {\n\t\t\tenv := getRepo(b, name).sharedEnv(b)\n\t\t\tstart := time.Now()\n\t\t\tsymbols := env.Symbol(*symbolQuery) // warm the cache\n\n\t\t\tif testing.Verbose() {\n\t\t\t\tfmt.Printf(\"Results (after %s):\\n\", time.Since(start))\n\t\t\t\tfor i, symbol := range symbols {\n\t\t\t\t\tfmt.Printf(\"\\t%d. %s (%s)\\n\", i, symbol.Name, symbol.ContainerName)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tb.ResetTimer()\n\n\t\t\tif stopAndRecord := startProfileIfSupported(b, env, qualifiedName(name, \"workspaceSymbols\")); stopAndRecord != nil {\n\t\t\t\tdefer stopAndRecord()\n\t\t\t}\n\n\t\t\tfor b.Loop() {\n\t\t\t\tenv.Symbol(*symbolQuery)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/codelens/codelens_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage codelens\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nfunc TestDisablingCodeLens(t *testing.T) {\n\tconst workspace = `\n-- go.mod --\nmodule codelens.test\n\ngo 1.12\n-- lib.go --\npackage lib\n\ntype Number int\n\nconst (\n\tZero Number = iota\n\tOne\n\tTwo\n)\n\n//` + `go:generate stringer -type=Number\n`\n\ttests := []struct {\n\t\tlabel        string\n\t\tenabled      map[string]bool\n\t\twantCodeLens bool\n\t}{\n\t\t{\n\t\t\tlabel:        \"default\",\n\t\t\twantCodeLens: true,\n\t\t},\n\t\t{\n\t\t\tlabel:        \"generate disabled\",\n\t\t\tenabled:      map[string]bool{string(settings.CodeLensGenerate): false},\n\t\t\twantCodeLens: false,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tSettings{\"codelenses\": test.enabled},\n\t\t\t).Run(t, workspace, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"lib.go\")\n\t\t\t\tlens := env.CodeLens(\"lib.go\")\n\t\t\t\tif gotCodeLens := len(lens) > 0; gotCodeLens != test.wantCodeLens {\n\t\t\t\t\tt.Errorf(\"got codeLens: %t, want %t\", gotCodeLens, test.wantCodeLens)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nconst proxyWithLatest = `\n-- golang.org/x/hello@v1.3.3/go.mod --\nmodule golang.org/x/hello\n\ngo 1.12\n-- golang.org/x/hello@v1.3.3/hi/hi.go --\npackage hi\n\nvar Goodbye error\n-- golang.org/x/hello@v1.2.3/go.mod --\nmodule golang.org/x/hello\n\ngo 1.12\n-- golang.org/x/hello@v1.2.3/hi/hi.go --\npackage hi\n\nvar Goodbye error\n`\n\n// This test confirms the full functionality of the code lenses for updating\n// dependencies in a go.mod file, when using a go.work file. It checks for the\n// code lens that suggests an update and then executes the command associated\n// with that code lens. A regression test for golang/go#39446. It also checks\n// that these code lenses only affect the diagnostics and contents of the\n// containing go.mod file.\nfunc TestUpgradeCodelens_Workspace(t *testing.T) {\n\tconst shouldUpdateDep = `\n-- go.work --\ngo 1.18\n\nuse (\n\t./a\n\t./b\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.14\n\nrequire golang.org/x/hello v1.2.3\n-- a/go.sum --\ngolang.org/x/hello v1.2.3 h1:7Wesfkx/uBd+eFgPrq0irYj/1XfmbvLV8jZ/W7C2Dwg=\ngolang.org/x/hello v1.2.3/go.mod h1:OgtlzsxVMUUdsdQCIDYgaauCTH47B8T8vofouNJfzgY=\n-- a/main.go --\npackage main\n\nimport \"golang.org/x/hello/hi\"\n\nfunc main() {\n\t_ = hi.Goodbye\n}\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.14\n\nrequire golang.org/x/hello v1.2.3\n-- b/go.sum --\ngolang.org/x/hello v1.2.3 h1:7Wesfkx/uBd+eFgPrq0irYj/1XfmbvLV8jZ/W7C2Dwg=\ngolang.org/x/hello v1.2.3/go.mod h1:OgtlzsxVMUUdsdQCIDYgaauCTH47B8T8vofouNJfzgY=\n-- b/main.go --\npackage main\n\nimport (\n\t\"golang.org/x/hello/hi\"\n)\n\nfunc main() {\n\t_ = hi.Goodbye\n}\n`\n\n\tconst wantGoModA = `module mod.com/a\n\ngo 1.14\n\nrequire golang.org/x/hello v1.3.3\n`\n\t// Applying the diagnostics or running the codelenses for a/go.mod\n\t// should not change the contents of b/go.mod\n\tconst wantGoModB = `module mod.com/b\n\ngo 1.14\n\nrequire golang.org/x/hello v1.2.3\n`\n\n\tfor _, commandTitle := range []string{\n\t\t\"Upgrade transitive dependencies\",\n\t\t\"Upgrade direct dependencies\",\n\t} {\n\t\tt.Run(commandTitle, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tProxyFiles(proxyWithLatest),\n\t\t\t).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"a/go.mod\")\n\t\t\t\tenv.OpenFile(\"b/go.mod\")\n\t\t\t\tvar lens protocol.CodeLens\n\t\t\t\tvar found bool\n\t\t\t\tfor _, l := range env.CodeLens(\"a/go.mod\") {\n\t\t\t\t\tif l.Command.Title == commandTitle {\n\t\t\t\t\t\tlens = l\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !found {\n\t\t\t\t\tt.Fatalf(\"found no command with the title %s\", commandTitle)\n\t\t\t\t}\n\t\t\t\tif err := env.Editor.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{\n\t\t\t\t\tCommand:   lens.Command.Command,\n\t\t\t\t\tArguments: lens.Command.Arguments,\n\t\t\t\t}, nil); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tenv.AfterChange()\n\t\t\t\tif got := env.BufferText(\"a/go.mod\"); got != wantGoModA {\n\t\t\t\t\tt.Fatalf(\"a/go.mod upgrade failed:\\n%s\", compare.Text(wantGoModA, got))\n\t\t\t\t}\n\t\t\t\tif got := env.BufferText(\"b/go.mod\"); got != wantGoModB {\n\t\t\t\t\tt.Fatalf(\"b/go.mod changed unexpectedly:\\n%s\", compare.Text(wantGoModB, got))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\tfor _, vendoring := range []bool{false, true} {\n\t\tt.Run(fmt.Sprintf(\"Upgrade individual dependency vendoring=%v\", vendoring), func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tProxyFiles(proxyWithLatest),\n\t\t\t).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {\n\t\t\t\tif vendoring {\n\t\t\t\t\tenv.RunGoCommandInDirWithEnv(\"a\", []string{\"GOWORK=off\"}, \"mod\", \"vendor\")\n\t\t\t\t}\n\t\t\t\tenv.AfterChange()\n\t\t\t\tenv.OpenFile(\"a/go.mod\")\n\t\t\t\tenv.OpenFile(\"b/go.mod\")\n\n\t\t\t\tenv.ExecuteCodeLensCommand(\"a/go.mod\", command.CheckUpgrades, nil)\n\t\t\t\td := &protocol.PublishDiagnosticsParams{}\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromCheckUpgrades), 1, true),\n\t\t\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", `require`), WithMessage(\"can be upgraded\")),\n\t\t\t\t\tReadDiagnostics(\"a/go.mod\", d),\n\t\t\t\t\t// We do not want there to be a diagnostic for b/go.mod,\n\t\t\t\t\t// but there may be some subtlety in timing here, where this\n\t\t\t\t\t// should always succeed, but may not actually test the correct\n\t\t\t\t\t// behavior.\n\t\t\t\t\tNoDiagnostics(env.AtRegexp(\"b/go.mod\", `require`)),\n\t\t\t\t)\n\t\t\t\t// Check for upgrades in b/go.mod and then clear them.\n\t\t\t\tenv.ExecuteCodeLensCommand(\"b/go.mod\", command.CheckUpgrades, nil)\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromCheckUpgrades), 2, true),\n\t\t\t\t\tDiagnostics(env.AtRegexp(\"b/go.mod\", `require`), WithMessage(\"can be upgraded\")),\n\t\t\t\t)\n\t\t\t\tenv.ExecuteCodeLensCommand(\"b/go.mod\", command.ResetGoModDiagnostics, nil)\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromResetGoModDiagnostics), 1, true),\n\t\t\t\t\tNoDiagnostics(ForFile(\"b/go.mod\")),\n\t\t\t\t)\n\n\t\t\t\t// Apply the diagnostics to a/go.mod.\n\t\t\t\tenv.ApplyQuickFixes(\"a/go.mod\", d.Diagnostics)\n\t\t\t\tenv.AfterChange()\n\t\t\t\tif got := env.BufferText(\"a/go.mod\"); got != wantGoModA {\n\t\t\t\t\tt.Fatalf(\"a/go.mod upgrade failed:\\n%s\", compare.Text(wantGoModA, got))\n\t\t\t\t}\n\t\t\t\tif got := env.BufferText(\"b/go.mod\"); got != wantGoModB {\n\t\t\t\t\tt.Fatalf(\"b/go.mod changed unexpectedly:\\n%s\", compare.Text(wantGoModB, got))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestUpgradeCodelens_ModVendor(t *testing.T) {\n\t// This test checks the regression of golang/go#66055. The upgrade codelens\n\t// should work in a mod vendor context (the test above using a go.work file\n\t// was not broken).\n\ttestenv.NeedsGoCommand1Point(t, 22)\n\n\tconst shouldUpdateDep = `\n-- go.mod --\nmodule mod.com/a\n\ngo 1.22\n\nrequire golang.org/x/hello v1.2.3\n-- main.go --\npackage main\n\nimport \"golang.org/x/hello/hi\"\n\nfunc main() {\n\t_ = hi.Goodbye\n}\n`\n\n\tconst wantGoModA = `module mod.com/a\n\ngo 1.22\n\nrequire golang.org/x/hello v1.3.3\n`\n\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxyWithLatest),\n\t).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"mod\", \"vendor\")\n\t\tenv.AfterChange()\n\t\tenv.OpenFile(\"go.mod\")\n\n\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.CheckUpgrades, nil)\n\t\td := &protocol.PublishDiagnosticsParams{}\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromCheckUpgrades), 1, true),\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", `require`), WithMessage(\"can be upgraded\")),\n\t\t\tReadDiagnostics(\"go.mod\", d),\n\t\t)\n\n\t\t// Apply the diagnostics to a/go.mod.\n\t\tenv.ApplyQuickFixes(\"go.mod\", d.Diagnostics)\n\t\tenv.AfterChange()\n\t\tif got := env.BufferText(\"go.mod\"); got != wantGoModA {\n\t\t\tt.Fatalf(\"go.mod upgrade failed:\\n%s\", compare.Text(wantGoModA, got))\n\t\t}\n\t})\n}\n\nfunc TestUnusedDependenciesCodelens(t *testing.T) {\n\tconst proxy = `\n-- golang.org/x/hello@v1.0.0/go.mod --\nmodule golang.org/x/hello\n\ngo 1.14\n-- golang.org/x/hello@v1.0.0/hi/hi.go --\npackage hi\n\nvar Goodbye error\n-- golang.org/x/unused@v1.0.0/go.mod --\nmodule golang.org/x/unused\n\ngo 1.14\n-- golang.org/x/unused@v1.0.0/nouse/nouse.go --\npackage nouse\n\nvar NotUsed error\n`\n\n\tconst shouldRemoveDep = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire golang.org/x/hello v1.0.0\nrequire golang.org/x/unused v1.0.0\n\n// EOF\n-- main.go --\npackage main\n\nimport \"golang.org/x/hello/hi\"\n\nfunc main() {\n\t_ = hi.Goodbye\n}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t).Run(t, shouldRemoveDep, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.RegexpReplace(\"go.mod\", \"// EOF\", \"// EOF unsaved edit\") // unsaved edits ok\n\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.Tidy, nil)\n\t\tenv.AfterChange()\n\t\tgot := env.BufferText(\"go.mod\")\n\t\tconst wantGoMod = `module mod.com\n\ngo 1.14\n\nrequire golang.org/x/hello v1.0.0\n\n// EOF unsaved edit\n`\n\t\tif got != wantGoMod {\n\t\t\tt.Fatalf(\"go.mod tidy failed:\\n%s\", compare.Text(wantGoMod, got))\n\t\t}\n\t})\n}\n\nfunc TestRegenerateCgo(t *testing.T) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\tconst workspace = `\n-- go.mod --\nmodule example.com\n\ngo 1.12\n-- cgo.go --\npackage x\n\n/*\nint fortythree() { return 42; }\n*/\nimport \"C\"\n\nfunc Foo() {\n\tprint(C.fortytwo())\n}\n`\n\tRun(t, workspace, func(t *testing.T, env *Env) {\n\t\t// Open the file. We have a nonexistant symbol that will break cgo processing.\n\t\tenv.OpenFile(\"cgo.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"cgo.go\", ``), WithMessage(\"go list failed to return CompiledGoFiles\")),\n\t\t)\n\n\t\t// Fix the C function name. We haven't regenerated cgo, so nothing should be fixed.\n\t\tenv.RegexpReplace(\"cgo.go\", `int fortythree`, \"int fortytwo\")\n\t\tenv.SaveBuffer(\"cgo.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"cgo.go\", ``), WithMessage(\"go list failed to return CompiledGoFiles\")),\n\t\t)\n\n\t\t// Regenerate cgo, fixing the diagnostic.\n\t\tenv.ExecuteCodeLensCommand(\"cgo.go\", command.RegenerateCgo, nil)\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromRegenerateCgo), 1, true),\n\t\t\tNoDiagnostics(ForFile(\"cgo.go\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/completion/completion18_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\n// This file is misnamed; it has no version constraints.\n// TODO(adonovan):  fold into completion_test.go\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// test generic receivers\nfunc TestGenericReceiver(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\ntype SyncMap[K any, V comparable] struct {}\nfunc (s *SyncMap[K,V]) f() {}\ntype XX[T any] struct {}\ntype UU[T any] struct {}\nfunc (s SyncMap[XX,string]) g(v UU) {}\n`\n\n\ttests := []struct {\n\t\tpat  string\n\t\twant []string\n\t}{\n\t\t{\"s .Syn\", []string{\"SyncMap[K, V]\"}},\n\t\t{\"Map.X\", []string{}}, // This is probably wrong, Maybe \"XX\"?\n\t\t{\"v U\", []string{\"UU\", \"uint\", \"uint16\", \"uint32\", \"uint64\", \"uint8\", \"uintptr\"}}, // not U[T]\n\t}\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tfor _, tst := range tests {\n\t\t\tloc := env.RegexpSearch(\"main.go\", tst.pat)\n\t\t\tloc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(tst.pat)))\n\t\t\tcompletions := env.Completion(loc)\n\t\t\tresult := compareCompletionLabels(tst.want, completions.Items)\n\t\t\tif result != \"\" {\n\t\t\t\tt.Errorf(\"%s: wanted %v\", result, tst.want)\n\t\t\t\tfor i, g := range completions.Items {\n\t\t\t\t\tt.Errorf(\"got %d %s %s\", i, g.Label, g.Detail)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestFuzzFunc(t *testing.T) {\n\t// The behavior under test is derived from the std module,\n\t// not the x/tools/internal/stdlib linked into gopls.\n\ttestenv.NeedsGoCommand1Point(t, 25) // go1.25 added TBF.Attr\n\n\t// use the example from the package documentation\n\tmodfile := `\n-- go.mod --\nmodule mod.com\n\ngo 1.25\n`\n\tpart0 := `package foo\nimport \"testing\"\nfunc FuzzNone(f *testing.F) {\n\tf.Add(12) // better not find this f.Add\n}\nfunc FuzzHex(f *testing.F) {\n\tfor _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {\n\t\tf.Ad`\n\tpart1 := `d(seed)\n\t}\n\tf.F`\n\tpart2 := `uzz(func(t *testing.T, in []byte) {\n\t\tenc := hex.EncodeToString(in)\n\t\tout, err := hex.DecodeString(enc)\n\t\tif err != nil {\n\t\t  f.Failed()\n\t\t}\n\t\tif !bytes.Equal(in, out) {\n\t\t  t.Fatalf(\"%v: round trip: %v, %s\", in, out, f.Name())\n\t\t}\n\t})\n}\n`\n\tdata := modfile + `-- a_test.go --\n` + part0 + `\n-- b_test.go --\n` + part0 + part1 + `\n-- c_test.go --\n` + part0 + part1 + part2\n\n\ttests := []struct {\n\t\tfile string\n\t\tpat  string\n\t\twant []string\n\t}{\n\t\t// To avoid breaking these assertions as the \"testing\" package evolves,\n\t\t// use an optional (?) suffix for newer symbols.\n\t\t{\"a_test.go\", \"f.A()d\", []string{\"Add\", \"ArtifactDir?\", \"Attr\"}}, // Attr is 1.25, Artifact is 1.26\n\t\t{\"c_test.go\", \" f.F()\", []string{\"Failed\"}},\n\t\t{\"c_test.go\", \"f.N()\", []string{\"Name\"}},\n\t\t{\"b_test.go\", \"f.F()\", []string{\"Fuzz(func(t *testing.T, a []byte)\", \"Fail\", \"FailNow\",\n\t\t\t\"Failed\", \"Fatal\", \"Fatalf\"}},\n\t}\n\tRun(t, data, func(t *testing.T, env *Env) {\n\t\tfor _, test := range tests {\n\t\t\tenv.OpenFile(test.file)\n\t\t\tenv.Await(env.DoneWithOpen())\n\t\t\tloc := env.RegexpSearch(test.file, test.pat)\n\t\t\tcompletions := env.Completion(loc)\n\t\t\tresult := compareCompletionLabels(test.want, completions.Items)\n\t\t\tif result != \"\" {\n\t\t\t\tt.Errorf(\"pat=%q <<%s>>\", test.pat, result)\n\t\t\t\tfor i, it := range completions.Items {\n\t\t\t\t\tt.Errorf(\"%d got %q %q\", i, it.Label, it.Detail)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/completion/completion_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/telemetry/counter/countertest\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/modindex\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/blah/blah.go --\npackage hello\n\nconst Name = \"Hello\"\n`\n\nfunc TestPackageCompletion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- cmd/main.go --\npackage main\n-- cmd/testfile.go --\npackage\n-- fruits/apple.go --\npackage apple\n\nfun apple() int {\n\treturn 0\n}\n\n-- fruits/testfile.go --\n// this is a comment\n\n/*\n this is a multiline comment\n*/\n\nimport \"fmt\"\n\nfunc test() {}\n\n-- fruits/testfile2.go --\npackage\n\n-- fruits/testfile3.go --\npac\n-- 123f_r.u~its-123/testfile.go --\npackage\n\n-- .invalid-dir@-name/testfile.go --\npackage\n`\n\tvar (\n\t\ttestfile4 = \"\"\n\t\ttestfile5 = \"/*a comment*/ \"\n\t\ttestfile6 = \"/*a comment*/\\n\"\n\t)\n\tfor _, tc := range []struct {\n\t\tname          string\n\t\tfilename      string\n\t\tcontent       *string\n\t\ttriggerRegexp string\n\t\twant          []string\n\t\teditRegexp    string\n\t}{\n\t\t{\n\t\t\tname:          \"main package completion after package keyword\",\n\t\t\tfilename:      \"cmd/testfile.go\",\n\t\t\ttriggerRegexp: \"package()\",\n\t\t\twant:          []string{\"package main\", \"package cmd\", \"package cmd_test\"},\n\t\t\teditRegexp:    \"package\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion at valid position\",\n\t\t\tfilename:      \"fruits/testfile.go\",\n\t\t\ttriggerRegexp: \"\\n()\",\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    \"\\n()\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion in a comment\",\n\t\t\tfilename:      \"fruits/testfile.go\",\n\t\t\ttriggerRegexp: \"th()is\",\n\t\t\twant:          nil,\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion in a multiline comment\",\n\t\t\tfilename:      \"fruits/testfile.go\",\n\t\t\ttriggerRegexp: `\\/\\*\\n()`,\n\t\t\twant:          nil,\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion at invalid position\",\n\t\t\tfilename:      \"fruits/testfile.go\",\n\t\t\ttriggerRegexp: \"import \\\"fmt\\\"\\n()\",\n\t\t\twant:          nil,\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion after package keyword\",\n\t\t\tfilename:      \"fruits/testfile2.go\",\n\t\t\ttriggerRegexp: \"package()\",\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    \"package\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion with 'pac' prefix\",\n\t\t\tfilename:      \"fruits/testfile3.go\",\n\t\t\ttriggerRegexp: \"pac()\",\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    \"pac\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion for empty file\",\n\t\t\tfilename:      \"fruits/testfile4.go\",\n\t\t\ttriggerRegexp: \"^$\",\n\t\t\tcontent:       &testfile4,\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    \"^$\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion without terminal newline\",\n\t\t\tfilename:      \"fruits/testfile5.go\",\n\t\t\ttriggerRegexp: `\\*\\/ ()`,\n\t\t\tcontent:       &testfile5,\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    `\\*\\/ ()`,\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion on terminal newline\",\n\t\t\tfilename:      \"fruits/testfile6.go\",\n\t\t\ttriggerRegexp: `\\*\\/\\n()`,\n\t\t\tcontent:       &testfile6,\n\t\t\twant:          []string{\"package apple\", \"package apple_test\", \"package fruits\", \"package fruits_test\", \"package main\"},\n\t\t\teditRegexp:    `\\*\\/\\n()`,\n\t\t},\n\t\t// Issue golang/go#44680\n\t\t{\n\t\t\tname:          \"package completion for dir name with punctuation\",\n\t\t\tfilename:      \"123f_r.u~its-123/testfile.go\",\n\t\t\ttriggerRegexp: \"package()\",\n\t\t\twant:          []string{\"package fruits123\", \"package fruits123_test\", \"package main\"},\n\t\t\teditRegexp:    \"package\",\n\t\t},\n\t\t{\n\t\t\tname:          \"package completion for invalid dir name\",\n\t\t\tfilename:      \".invalid-dir@-name/testfile.go\",\n\t\t\ttriggerRegexp: \"package()\",\n\t\t\twant:          []string{\"package main\"},\n\t\t\teditRegexp:    \"package\",\n\t\t},\n\t} {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tif tc.content != nil {\n\t\t\t\t\tenv.WriteWorkspaceFile(tc.filename, *tc.content)\n\t\t\t\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\t\t\t\t}\n\t\t\t\tenv.OpenFile(tc.filename)\n\t\t\t\tcompletions := env.Completion(env.RegexpSearch(tc.filename, tc.triggerRegexp))\n\n\t\t\t\t// Check that the completion item suggestions are in the range\n\t\t\t\t// of the file. {Start,End}.Line are zero-based.\n\t\t\t\tlineCount := len(strings.Split(env.BufferText(tc.filename), \"\\n\"))\n\t\t\t\tfor _, item := range completions.Items {\n\t\t\t\t\tfor _, mode := range []string{\"replace\", \"insert\"} {\n\t\t\t\t\t\tedit, err := protocol.SelectCompletionTextEdit(item, mode == \"replace\")\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tt.Fatalf(\"unexpected text edit in completion item (%v): %v\", mode, err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif start := int(edit.Range.Start.Line); start > lineCount {\n\t\t\t\t\t\t\tt.Fatalf(\"unexpected text edit range (%v) start line number: got %d, want <= %d\", mode, start, lineCount)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif end := int(edit.Range.End.Line); end > lineCount {\n\t\t\t\t\t\t\tt.Fatalf(\"unexpected text edit range (%v) end line number: got %d, want <= %d\", mode, end, lineCount)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif tc.want != nil {\n\t\t\t\t\texpectedLoc := env.RegexpSearch(tc.filename, tc.editRegexp)\n\t\t\t\t\tfor _, item := range completions.Items {\n\t\t\t\t\t\tfor _, mode := range []string{\"replace\", \"insert\"} {\n\t\t\t\t\t\t\tedit, _ := protocol.SelectCompletionTextEdit(item, mode == \"replace\")\n\t\t\t\t\t\t\tgotRng := edit.Range\n\t\t\t\t\t\t\tif expectedLoc.Range != gotRng {\n\t\t\t\t\t\t\t\tt.Errorf(\"unexpected completion range (%v) for completion item %s: got %v, want %v\",\n\t\t\t\t\t\t\t\t\tmode, item.Label, gotRng, expectedLoc.Range)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdiff := compareCompletionLabels(tc.want, completions.Items)\n\t\t\t\tif diff != \"\" {\n\t\t\t\t\tt.Error(diff)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestPackageNameCompletion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- math/add.go --\npackage ma\n`\n\n\twant := []string{\"ma\", \"ma_test\", \"main\", \"math\", \"math_test\"}\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"math/add.go\")\n\t\tcompletions := env.Completion(env.RegexpSearch(\"math/add.go\", \"package ma()\"))\n\n\t\tdiff := compareCompletionLabels(want, completions.Items)\n\t\tif diff != \"\" {\n\t\t\tt.Fatal(diff)\n\t\t}\n\t})\n}\n\n// compareCompletionLabels returns a non-empty string reporting the\n// difference (if any) between the labels of the actual completion\n// items (gotItems) and the expected list (want).\n//\n// A want item with a \"?\" suffix is optional.\n//\n// TODO(rfindley): audit/clean up call sites for this helper, to ensure\n// consistent test errors.\nfunc compareCompletionLabels(want []string, gotItems []protocol.CompletionItem) string {\n\tvar got []string\n\tfor _, item := range gotItems {\n\t\tgot = append(got, item.Label)\n\t\tif item.Label != item.InsertText && item.TextEdit == nil {\n\t\t\t// Label should be the same as InsertText, if InsertText is to be used\n\t\t\treturn fmt.Sprintf(\"label not the same as InsertText %#v\", item)\n\t\t}\n\t}\n\n\tif len(got) == 0 && len(want) == 0 {\n\t\treturn \"\" // treat nil and the empty slice as equivalent\n\t}\n\n\t// A 'want' item with a '?' suffix is optional, to ease\n\t// migration across versions. Remove any that are not present\n\t// in the 'got' set.\n\tvar out []string\n\tfor _, item := range want {\n\t\titem, optional := strings.CutSuffix(item, \"?\")\n\t\tif optional && !slices.Contains(got, item) {\n\t\t\tcontinue // optional item is missing\n\t\t}\n\t\tout = append(out, item)\n\t}\n\twant = out\n\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\treturn fmt.Sprintf(\"completion item mismatch (-want +got):\\n%s\", diff)\n\t}\n\treturn \"\"\n}\n\nfunc TestIssue74611(t *testing.T) {\n\t// Completions should not offer symbols from unimported packages\n\t// that cannot be imported because they are \"internal\".\n\t//\n\t// Ideally, we should test std case as well but because mocking\n\t// a fake stdlib is hard, we just test the 3rd user case.\n\t// std test is done interactively.\n\tconst files = `-- go.mod --\nmodule mod.com/cmd\n\ngo 1.21\n\n-- a.go --\npackage pkg\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"call Println to use fmt\")\n\t_ = maps\n} // (completion requested at start of line)\n`\n\n\tWithOptions().Run(t, files, func(t *testing.T, env *Env) {\n\t\tfilename := \"a.go\"\n\t\t// Trigger unimported completions for the maps package.\n\t\tenv.OpenFile(filename)\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(filename, `()\\n\\}`)\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Fatalf(\"no completion items\")\n\t\t}\n\t\truntimeMaps := `\"internal/runtime/maps\"`\n\t\tfound := slices.ContainsFunc(completions.Items, func(item protocol.CompletionItem) bool {\n\t\t\treturn item.Detail == runtimeMaps\n\t\t})\n\n\t\tif found {\n\t\t\tt.Fatalf(\"unwanted completion: %s\", runtimeMaps)\n\t\t}\n\t})\n}\n\nfunc TestUnimportedCompletion(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire example.com v1.2.3\n-- main.go --\npackage main\n\nfunc main() {\n\t_ = blah\n}\n-- main2.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc _() {\n\t_ = blah.Hello\n}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t// Make sure the dependency is in the module cache and accessible for\n\t\t// unimported completions, and then remove it before proceeding.\n\t\tenv.RemoveWorkspaceFile(\"main2.go\")\n\t\tenv.RunGoCommand(\"mod\", \"tidy\")\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\t// Trigger unimported completions for the example.com/blah package.\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"main.go\", \"()ah\")\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Fatalf(\"no completion items\")\n\t\t}\n\t\tenv.AcceptCompletion(loc, completions.Items[0]) // adds blah import to main.go\n\t\tenv.Await(env.DoneWithChange())\n\n\t\t// Trigger completions once again for the blah.<> selector.\n\t\tenv.RegexpReplace(\"main.go\", \"_ = blah\", \"_ = blah.\")\n\t\tenv.Await(env.DoneWithChange())\n\t\tloc = env.RegexpSearch(\"main.go\", `()\\n\\}`)\n\t\tcompletions = env.Completion(loc)\n\t\tif len(completions.Items) != 1 {\n\t\t\tt.Fatalf(\"expected 1 completion item, got %v\", len(completions.Items))\n\t\t}\n\t\titem := completions.Items[0]\n\t\tif item.Label != \"Name\" {\n\t\t\tt.Fatalf(\"expected completion item blah.Name, got %v\", item.Label)\n\t\t}\n\t\tenv.AcceptCompletion(loc, item)\n\n\t\t// Await the diagnostics to add example.com/blah to the go.mod file.\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"example.com/blah\"`)),\n\t\t)\n\t})\n}\n\n// Test that completions still work with an undownloaded module, golang/go#43333.\nfunc TestUndownloadedModule(t *testing.T) {\n\t// mod.com depends on example.com, but only in a file that's hidden by a\n\t// build tag, so the IWL won't download example.com. That will cause errors\n\t// in the go list -m call performed by the imports package.\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire example.com v1.2.3\n-- useblah.go --\n// +build hidden\n\npackage pkg\nimport \"example.com/blah\"\nvar _ = blah.Name\n-- mainmod/mainmod.go --\npackage mainmod\n\nconst Name = \"mainmod\"\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t\tProxyFiles(proxy)).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"import.go\", \"package pkg\\nvar _ = mainmod.Name\\n\")\n\t\tenv.SaveBuffer(\"import.go\")\n\t\tcontent := env.ReadWorkspaceFile(\"import.go\")\n\t\tif !strings.Contains(content, `import \"mod.com/mainmod`) {\n\t\t\tt.Errorf(\"expected import of mod.com/mainmod in %q\", content)\n\t\t}\n\t})\n}\n\n// Test that we can doctor the source code enough so the file is\n// parseable and completion works as expected.\nfunc TestSourceFixup(t *testing.T) {\n\t// This example relies on the fixer to turn \"s.\" into \"s._\" so\n\t// that it parses as a SelectorExpr with only local problems,\n\t// instead of snarfing up the following declaration of S\n\t// looking for an identifier; thus completion offers s.i.\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo.go --\npackage foo\n\nfunc _() {\n\tvar s S\n\tif s.\n}\n\ntype S struct {\n\ti int\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tcompletions := env.Completion(env.RegexpSearch(\"foo.go\", `if s\\.()`))\n\t\tdiff := compareCompletionLabels([]string{\"i\"}, completions.Items)\n\t\tif diff != \"\" {\n\t\t\tt.Fatal(diff)\n\t\t}\n\t})\n}\n\nfunc TestCompletion_Issue45510(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc _() {\n\ttype a *a\n\tvar aaaa1, aaaa2 a\n\tvar _ a = aaaa\n\n\ttype b a\n\tvar bbbb1, bbbb2 b\n\tvar _ b = bbbb\n}\n\ntype (\n\tc *d\n\td *e\n\te **c\n)\n\nfunc _() {\n\tvar (\n\t\txxxxc c\n\t\txxxxd d\n\t\txxxxe e\n\t)\n\n\tvar _ c = xxxx\n\tvar _ d = xxxx\n\tvar _ e = xxxx\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\n\t\ttests := []struct {\n\t\t\tre   string\n\t\t\twant []string\n\t\t}{\n\t\t\t{`var _ a = aaaa()`, []string{\"aaaa1\", \"aaaa2\"}},\n\t\t\t{`var _ b = bbbb()`, []string{\"bbbb1\", \"bbbb2\"}},\n\t\t\t{`var _ c = xxxx()`, []string{\"xxxxc\", \"xxxxd\", \"xxxxe\"}},\n\t\t\t{`var _ d = xxxx()`, []string{\"xxxxc\", \"xxxxd\", \"xxxxe\"}},\n\t\t\t{`var _ e = xxxx()`, []string{\"xxxxc\", \"xxxxd\", \"xxxxe\"}},\n\t\t}\n\t\tfor _, tt := range tests {\n\t\t\tcompletions := env.Completion(env.RegexpSearch(\"main.go\", tt.re))\n\t\t\tdiff := compareCompletionLabels(tt.want, completions.Items)\n\t\t\tif diff != \"\" {\n\t\t\t\tt.Errorf(\"%s: %s\", tt.re, diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestCompletionDeprecation(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule test.com\n\ngo 1.16\n-- prog.go --\npackage waste\n// Deprecated: use newFoof.\nfunc fooFunc() bool {\n\treturn false\n}\n\n// Deprecated: bad.\nconst badPi = 3.14\n\nfunc doit() {\n\tif fooF\n\tpanic()\n\tx := badP\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"prog.go\")\n\t\tloc := env.RegexpSearch(\"prog.go\", \"if fooF\")\n\t\tloc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(\"if fooF\")))\n\t\tcompletions := env.Completion(loc)\n\t\tdiff := compareCompletionLabels([]string{\"fooFunc\"}, completions.Items)\n\t\tif diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tif completions.Items[0].Tags == nil {\n\t\t\tt.Errorf(\"expected Tags to show deprecation %#v\", completions.Items[0].Tags)\n\t\t}\n\t\tloc = env.RegexpSearch(\"prog.go\", \"= badP\")\n\t\tloc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(\"= badP\")))\n\t\tcompletions = env.Completion(loc)\n\t\tdiff = compareCompletionLabels([]string{\"badPi\"}, completions.Items)\n\t\tif diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tif completions.Items[0].Tags == nil {\n\t\t\tt.Errorf(\"expected Tags to show deprecation %#v\", completions.Items[0].Tags)\n\t\t}\n\t})\n}\n\nfunc TestUnimportedCompletion_VSCodeIssue1489(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"a\")\n\tmath.Sqr\n}\n`\n\tWithOptions(\n\t\tWindowsLineEndings(),\n\t\tSettings{\"ui.completion.usePlaceholders\": true},\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t// Trigger unimported completions for the mod.com package.\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"main.go\", \"Sqr()\")\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Fatalf(\"no completion items\")\n\t\t}\n\t\tenv.AcceptCompletion(loc, completions.Items[0])\n\t\tenv.Await(env.DoneWithChange())\n\t\tgot := env.BufferText(\"main.go\")\n\t\twant := \"package main\\r\\n\\r\\nimport (\\r\\n\\t\\\"fmt\\\"\\r\\n\\t\\\"math\\\"\\r\\n)\\r\\n\\r\\nfunc main() {\\r\\n\\tfmt.Println(\\\"a\\\")\\r\\n\\tmath.Sqrt(${1:x float64})\\r\\n}\\r\\n\"\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"unimported completion (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestUnimportedCompletion_VSCodeIssue3365(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n\n-- main.go --\npackage main\n\nfunc main() {\n\tprintln(strings.TLower)\n}\n\nvar Lower = \"\"\n`\n\tfind := func(t *testing.T, completions *protocol.CompletionList, name string) protocol.CompletionItem {\n\t\tt.Helper()\n\t\tif completions == nil || len(completions.Items) == 0 {\n\t\t\tt.Fatalf(\"no completion items\")\n\t\t}\n\t\tfor _, i := range completions.Items {\n\t\t\tif i.Label == name {\n\t\t\t\treturn i\n\t\t\t}\n\t\t}\n\t\tt.Fatalf(\"no item with label %q\", name)\n\t\treturn protocol.CompletionItem{}\n\t}\n\n\tfor _, supportInsertReplace := range []bool{true, false} {\n\t\tt.Run(fmt.Sprintf(\"insertReplaceSupport=%v\", supportInsertReplace), func(t *testing.T) {\n\t\t\tcapabilities := fmt.Sprintf(`{ \"textDocument\": { \"completion\": { \"completionItem\": {\"insertReplaceSupport\":%t, \"snippetSupport\": false } } } }`, supportInsertReplace)\n\t\t\trunner := WithOptions(\n\t\t\t\tCapabilitiesJSON([]byte(capabilities)),\n\t\t\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t\t\t)\n\t\t\trunner.Run(t, src, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"main.go\")\n\t\t\t\tenv.Await(env.DoneWithOpen())\n\t\t\t\torig := env.BufferText(\"main.go\")\n\n\t\t\t\t// We try to trigger completion at \"println(strings.T<>Lower)\"\n\t\t\t\t// and accept the completion candidate that matches the 'accept' label.\n\t\t\t\tinsertModeWant := \"println(strings.ToUpperLower)\"\n\t\t\t\tif !supportInsertReplace {\n\t\t\t\t\tinsertModeWant = \"println(strings.ToUpper)\"\n\t\t\t\t}\n\t\t\t\ttestcases := []struct {\n\t\t\t\t\tmode   string\n\t\t\t\t\taccept string\n\t\t\t\t\twant   string\n\t\t\t\t}{\n\t\t\t\t\t{\n\t\t\t\t\t\tmode:   \"insert\",\n\t\t\t\t\t\taccept: \"ToUpper\",\n\t\t\t\t\t\twant:   insertModeWant,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tmode:   \"insert\",\n\t\t\t\t\t\taccept: \"ToLower\",\n\t\t\t\t\t\twant:   \"println(strings.ToLower)\", // The suffix 'Lower' is included in the text edit.\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tmode:   \"replace\",\n\t\t\t\t\t\taccept: \"ToUpper\",\n\t\t\t\t\t\twant:   \"println(strings.ToUpper)\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tmode:   \"replace\",\n\t\t\t\t\t\taccept: \"ToLower\",\n\t\t\t\t\t\twant:   \"println(strings.ToLower)\",\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tfor _, tc := range testcases {\n\t\t\t\t\tt.Logf(\"mode=%q accept=%q\", tc.mode, tc.accept)\n\t\t\t\t\tenv.SetSuggestionInsertReplaceMode(tc.mode == \"replace\")\n\t\t\t\t\tenv.SetBufferContent(\"main.go\", orig)\n\t\t\t\t\tloc := env.RegexpSearch(\"main.go\", `()Lower\\)`)\n\t\t\t\t\tcompletions := env.Completion(loc)\n\t\t\t\t\titem := find(t, completions, tc.accept)\n\t\t\t\t\tenv.AcceptCompletion(loc, item)\n\t\t\t\t\tgot := env.BufferText(\"main.go\")\n\t\t\t\t\tif !strings.Contains(got, tc.want) {\n\t\t\t\t\t\tt.Errorf(\"unexpected state after completion:\\n%v\\nwanted %v\", got, tc.want)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\nfunc TestUnimportedCompletionHasPlaceholders60269(t *testing.T) {\n\t// We can't express this as a marker test because it doesn't support AcceptCompletion.\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\nvar _ = b.F\n\n-- b/b.go --\npackage b\n\nfunc F0(a, b int, c float64) {}\nfunc F1(int, chan *string) {}\nfunc F2[K, V any](map[K]V, chan V) {} // missing type parameters was issue #60959\nfunc F3[K comparable, V any](map[K]V, chan V) {}\n`\n\tWithOptions(\n\t\tWindowsLineEndings(),\n\t\tSettings{\"ui.completion.usePlaceholders\": true,\n\t\t\t\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\t// The table lists the expected completions of b.F as they appear in Items.\n\t\tconst common = \"package a\\r\\n\\r\\nimport \\\"example.com/b\\\"\\r\\n\\r\\nvar _ = \"\n\t\tfor i, want := range []string{\n\t\t\tcommon + \"b.F0(${1:a int}, ${2:b int}, ${3:c float64})\\r\\n\",\n\t\t\tcommon + \"b.F1(${1:_ int}, ${2:_ chan *string})\\r\\n\",\n\t\t\tcommon + \"b.F2(${1:_ map[K]V}, ${2:_ chan V})\\r\\n\",\n\t\t\tcommon + \"b.F3(${1:_ map[K]V}, ${2:_ chan V})\\r\\n\",\n\t\t} {\n\t\t\tloc := env.RegexpSearch(\"a/a.go\", \"b.F()\")\n\t\t\tcompletions := env.Completion(loc)\n\t\t\tif len(completions.Items) == 0 {\n\t\t\t\tt.Fatalf(\"no completion items\")\n\t\t\t}\n\t\t\tsaved := env.BufferText(\"a/a.go\")\n\t\t\tenv.AcceptCompletion(loc, completions.Items[i])\n\t\t\tenv.Await(env.DoneWithChange())\n\t\t\tgot := env.BufferText(\"a/a.go\")\n\t\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"%d: unimported completion (-want +got):\\n%s\", i, diff)\n\t\t\t}\n\t\t\tenv.SetBufferContent(\"a/a.go\", saved) // restore\n\t\t}\n\t})\n}\n\nfunc TestPackageMemberCompletionAfterSyntaxError(t *testing.T) {\n\t// This test documents the current broken behavior due to golang/go#58833.\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\n-- main.go --\npackage main\n\nimport \"math\"\n\nfunc main() {\n\tmath.Sqrt(,0)\n\tmath.Ldex\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"main.go\", \"Ldex()\")\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Fatalf(\"no completion items\")\n\t\t}\n\t\tenv.AcceptCompletion(loc, completions.Items[0])\n\t\tenv.Await(env.DoneWithChange())\n\t\tgot := env.BufferText(\"main.go\")\n\t\t// The completion of math.Ldex after the syntax error on the\n\t\t// previous line is not \"math.Ldexp\" but \"math.Ldexmath.Abs\".\n\t\t// (In VSCode, \"Abs\" wrongly appears in the completion menu.)\n\t\t// This is a consequence of poor error recovery in the parser\n\t\t// causing \"math.Ldex\" to become a BadExpr.\n\t\twant := \"package main\\n\\nimport \\\"math\\\"\\n\\nfunc main() {\\n\\tmath.Sqrt(,0)\\n\\tmath.Ldexmath.Abs(${1:})\\n}\\n\"\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"unimported completion (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestCompleteAllFields(t *testing.T) {\n\t// This test verifies that completion results always include all struct fields.\n\t// See golang/go#53992.\n\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- p/p.go --\npackage p\n\nimport (\n\t\"fmt\"\n\n\t. \"net/http\"\n\t. \"runtime\"\n\t. \"go/types\"\n\t. \"go/parser\"\n\t. \"go/ast\"\n)\n\ntype S struct {\n\ta, b, c, d, e, f, g, h, i, j, k, l, m int\n\tn, o, p, q, r, s, t, u, v, w, x, y, z int\n}\n\nfunc _() {\n\tvar s S\n\tfmt.Println(s.)\n}\n`\n\n\tWithOptions(Settings{\n\t\t\"completionBudget\": \"1ns\", // must be non-zero as 0 => infinity\n\t}).Run(t, src, func(t *testing.T, env *Env) {\n\t\twantFields := make(map[string]bool)\n\t\tfor c := 'a'; c <= 'z'; c++ {\n\t\t\twantFields[string(c)] = true\n\t\t}\n\n\t\tenv.OpenFile(\"p/p.go\")\n\t\t// Make an arbitrary edit to ensure we're not hitting the cache.\n\t\tenv.EditBuffer(\"p/p.go\", fake.NewEdit(0, 0, 0, 0, fmt.Sprintf(\"// current time: %v\\n\", time.Now())))\n\t\tloc := env.RegexpSearch(\"p/p.go\", `s\\.()`)\n\t\tcompletions := env.Completion(loc)\n\t\tgotFields := make(map[string]bool)\n\t\tfor _, item := range completions.Items {\n\t\t\tif item.Kind == protocol.FieldCompletion {\n\t\t\t\tgotFields[item.Label] = true\n\t\t\t}\n\t\t}\n\n\t\tif diff := cmp.Diff(wantFields, gotFields); diff != \"\" {\n\t\t\tt.Errorf(\"Completion(...) returned mismatching fields (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestDefinition(t *testing.T) {\n\tfiles := `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- a_test.go --\npackage foo\n`\n\ttests := []struct {\n\t\tline string   // the sole line in the buffer after the package statement\n\t\tpat  string   // the pattern to search for\n\t\twant []string // expected completions\n\t}{\n\t\t{\"func T\", \"T\", []string{\"TestXxx(t *testing.T)\", \"TestMain(m *testing.M)\"}},\n\t\t{\"func T()\", \"T\", []string{\"TestMain\", \"Test\"}},\n\t\t{\"func TestM\", \"TestM\", []string{\"TestMain(m *testing.M)\", \"TestM(t *testing.T)\"}},\n\t\t{\"func TestM()\", \"TestM\", []string{\"TestMain\"}},\n\t\t{\"func TestMi\", \"TestMi\", []string{\"TestMi(t *testing.T)\"}},\n\t\t{\"func TestMi()\", \"TestMi\", nil},\n\t\t{\"func TestG\", \"TestG\", []string{\"TestG(t *testing.T)\"}},\n\t\t{\"func TestG(\", \"TestG\", nil},\n\t\t{\"func Ben\", \"B\", []string{\"BenchmarkXxx(b *testing.B)\"}},\n\t\t{\"func Ben(\", \"Ben\", []string{\"Benchmark\"}},\n\t\t{\"func BenchmarkFoo\", \"BenchmarkFoo\", []string{\"BenchmarkFoo(b *testing.B)\"}},\n\t\t{\"func BenchmarkFoo(\", \"BenchmarkFoo\", nil},\n\t\t{\"func Fuz\", \"F\", []string{\"FuzzXxx(f *testing.F)\"}},\n\t\t{\"func Fuz(\", \"Fuz\", []string{\"Fuzz\"}},\n\t\t{\"func Testx\", \"Testx\", nil},\n\t\t{\"func TestMe(t *testing.T)\", \"TestMe\", nil},\n\t\t{\"func Te(t *testing.T)\", \"Te\", []string{\"TestMain\", \"Test\"}},\n\t}\n\tfname := \"a_test.go\"\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(fname)\n\t\tenv.Await(env.DoneWithOpen())\n\t\tfor _, test := range tests {\n\t\t\tenv.SetBufferContent(fname, \"package foo\\n\"+test.line)\n\t\t\tloc := env.RegexpSearch(fname, test.pat)\n\t\t\tloc.Range.Start.Character += uint32(protocol.UTF16Len([]byte(test.pat)))\n\t\t\tcompletions := env.Completion(loc)\n\t\t\tif diff := compareCompletionLabels(test.want, completions.Items); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// Test that completing a definition replaces source text when applied, golang/go#56852.\nfunc TestDefinitionReplaceRange(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n`\n\n\ttests := []struct {\n\t\tname          string\n\t\tbefore, after string\n\t}{\n\t\t{\n\t\t\tname: \"func TestMa\",\n\t\t\tbefore: `\npackage foo_test\n\nfunc TestMa\n`,\n\t\t\tafter: `\npackage foo_test\n\nfunc TestMain(m *testing.M)\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"func TestSome\",\n\t\t\tbefore: `\npackage foo_test\n\nfunc TestSome\n`,\n\t\t\tafter: `\npackage foo_test\n\nfunc TestSome(t *testing.T)\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"func Bench\",\n\t\t\tbefore: `\npackage foo_test\n\nfunc Bench\n`,\n\t\t\t// Note: Snippet with escaped }.\n\t\t\tafter: `\npackage foo_test\n\nfunc Benchmark${1:Xxx}(b *testing.B) {\n\t$0\n\\}\n`,\n\t\t},\n\t}\n\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"foo_test.go\", \"\")\n\n\t\tfor _, tst := range tests {\n\t\t\ttst.before = strings.Trim(tst.before, \"\\n\")\n\t\t\ttst.after = strings.Trim(tst.after, \"\\n\")\n\t\t\tenv.SetBufferContent(\"foo_test.go\", tst.before)\n\n\t\t\tloc := env.RegexpSearch(\"foo_test.go\", tst.name)\n\t\t\tloc.Range.Start.Character = uint32(protocol.UTF16Len([]byte(tst.name)))\n\t\t\tcompletions := env.Completion(loc)\n\t\t\tif len(completions.Items) == 0 {\n\t\t\t\tt.Fatalf(\"no completion items\")\n\t\t\t}\n\n\t\t\tenv.AcceptCompletion(loc, completions.Items[0])\n\t\t\tenv.Await(env.DoneWithChange())\n\t\t\tif buf := env.BufferText(\"foo_test.go\"); buf != tst.after {\n\t\t\t\tt.Errorf(\"%s:incorrect completion: got %q, want %q\", tst.name, buf, tst.after)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestGoWorkCompletion(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\n\nuse ./a\nuse ./a/ba\nuse ./a/b/\nuse ./dir/foo\nuse ./dir/foobar/\nuse ./missing/\n-- a/go.mod --\n-- go.mod --\n-- a/bar/go.mod --\n-- a/b/c/d/e/f/go.mod --\n-- dir/bar --\n-- dir/foobar/go.mod --\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\n\t\ttests := []struct {\n\t\t\tre   string\n\t\t\twant []string\n\t\t}{\n\t\t\t{`use ()\\.`, []string{\".\", \"./a\", \"./a/bar\", \"./dir/foobar\"}},\n\t\t\t{`use \\.()`, []string{\"\", \"/a\", \"/a/bar\", \"/dir/foobar\"}},\n\t\t\t{`use \\./()`, []string{\"a\", \"a/bar\", \"dir/foobar\"}},\n\t\t\t{`use ./a()`, []string{\"\", \"/b/c/d/e/f\", \"/bar\"}},\n\t\t\t{`use ./a/b()`, []string{\"/c/d/e/f\", \"ar\"}},\n\t\t\t{`use ./a/b/()`, []string{`c/d/e/f`}},\n\t\t\t{`use ./a/ba()`, []string{\"r\"}},\n\t\t\t{`use ./dir/foo()`, []string{\"bar\"}},\n\t\t\t{`use ./dir/foobar/()`, []string{}},\n\t\t\t{`use ./missing/()`, []string{}},\n\t\t}\n\t\tfor _, tt := range tests {\n\t\t\tcompletions := env.Completion(env.RegexpSearch(\"go.work\", tt.re))\n\t\t\tdiff := compareCompletionLabels(tt.want, completions.Items)\n\t\t\tif diff != \"\" {\n\t\t\t\tt.Errorf(\"%s: %s\", tt.re, diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nconst reverseInferenceSrcPrelude = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- a.go --\npackage a\n\ntype InterfaceA interface {\n\timplA()\n}\n\ntype InterfaceB interface {\n\timplB()\n}\n\n\ntype TypeA struct{}\n\nfunc (TypeA) implA() {}\n\ntype TypeX string\n\nfunc (TypeX) implB() {}\n\ntype TypeB struct{}\n\nfunc (TypeB) implB() {}\n\ntype TypeC struct{} // should have no impact\n\ntype Wrap[T any] struct {\n\tinner *T\n}\n\nfunc NewWrap[T any](x T) Wrap[T] {\n\treturn Wrap[T]{inner: &x}\n}\n\nfunc DoubleWrap[T any, U any](t T, u U) (Wrap[T], Wrap[U]) {\n\treturn Wrap[T]{inner: &t}, Wrap[U]{inner: &u}\n}\n\nfunc IntWrap[T int32 | int64](x T) Wrap[T] {\n\treturn Wrap[T]{inner: &x}\n}\n\nvar ia InterfaceA\nvar ib InterfaceB\n\nvar avar TypeA\nvar bvar TypeB\n\nvar i int\nvar i32 int32\nvar i64 int64\n`\n\nfunc TestReverseInferCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar _ Wrap[int64] = IntWrap()\n\t}\n\t`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcompl := env.RegexpSearch(\"a.go\", `IntWrap\\(()\\)`)\n\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(compl)\n\n\t\twantLabel := []string{\"i64\", \"i\", \"i32\", \"int64()\"}\n\n\t\t// only check the prefix due to formatting differences with escaped characters\n\t\twantText := []string{\"i64\", \"int64(i\", \"int64(i32\", \"int64(\"}\n\n\t\tfor i, item := range result.Items[:len(wantLabel)] {\n\t\t\tif diff := cmp.Diff(wantLabel[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected label mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\n\t\t\tif insertText, ok := item.TextEdit.Value.(protocol.InsertReplaceEdit); ok {\n\t\t\t\tif diff := cmp.Diff(wantText[i], insertText.NewText[:len(wantText[i])]); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"Completion: unexpected insertText mismatch (checks prefix only) (-want +got):\\n%s\", diff)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestInterfaceReverseInferCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar wa Wrap[InterfaceA]\n\t\tvar wb Wrap[InterfaceB]\n\t\twb = NewWrap() // wb is of type Wrap[InterfaceB]\n\t}\n\t`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcompl := env.RegexpSearch(\"a.go\", `NewWrap\\(()\\)`)\n\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(compl)\n\n\t\twantLabel := []string{\"ib\", \"bvar\", \"wb.inner\", \"TypeB{}\", \"TypeX()\", \"nil\"}\n\n\t\t// only check the prefix due to formatting differences with escaped characters\n\t\twantText := []string{\"ib\", \"InterfaceB(\", \"*wb.inner\", \"InterfaceB(\", \"InterfaceB(\", \"nil\"}\n\n\t\tfor i, item := range result.Items[:len(wantLabel)] {\n\t\t\tif diff := cmp.Diff(wantLabel[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected label mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\n\t\t\tif insertText, ok := item.TextEdit.Value.(protocol.InsertReplaceEdit); ok {\n\t\t\t\tif diff := cmp.Diff(wantText[i], insertText.NewText[:len(wantText[i])]); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"Completion: unexpected insertText mismatch (checks prefix only) (-want +got):\\n%s\", diff)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestInvalidReverseInferenceDefaultsToConstraintCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar wa Wrap[InterfaceA]\n\t\t// This is ambiguous, so default to the constraint rather the inference.\n\t\twa = IntWrap()\n\t}\n\t`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcompl := env.RegexpSearch(\"a.go\", `IntWrap\\(()\\)`)\n\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(compl)\n\n\t\twantLabel := []string{\"i32\", \"i64\", \"nil\"}\n\n\t\tfor i, item := range result.Items[:len(wantLabel)] {\n\t\t\tif diff := cmp.Diff(wantLabel[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected label mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestInterfaceReverseInferTypeParamCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar wa Wrap[InterfaceA]\n\t\tvar wb Wrap[InterfaceB]\n\t\twb = NewWrap[]()\n\t}\n\t`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcompl := env.RegexpSearch(\"a.go\", `NewWrap\\[()\\]\\(\\)`)\n\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(compl)\n\t\twant := []string{\"InterfaceB\", \"TypeB\", \"TypeX\", \"InterfaceA\", \"TypeA\"}\n\t\tfor i, item := range result.Items[:len(want)] {\n\t\t\tif diff := cmp.Diff(want[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestInvalidReverseInferenceTypeParamDefaultsToConstraintCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar wa Wrap[InterfaceA]\n\t\t// This is ambiguous, so default to the constraint rather the inference.\n\t\twb = IntWrap[]()\n\t}\n\t`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcompl := env.RegexpSearch(\"a.go\", `IntWrap\\[()\\]\\(\\)`)\n\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(compl)\n\t\twant := []string{\"int32\", \"int64\"}\n\t\tfor i, item := range result.Items[:len(want)] {\n\t\t\tif diff := cmp.Diff(want[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestReverseInferDoubleTypeParamCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc main() {\n\t\tvar wa Wrap[InterfaceA]\n\t\tvar wb Wrap[InterfaceB]\n\n\t\twa, wb = DoubleWrap[]()\n\t\t// _ is necessary to trick the parser into an index list expression\n\t\twa, wb = DoubleWrap[InterfaceA, _]()\n\t}\n\t`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\tcompl := env.RegexpSearch(\"a.go\", `DoubleWrap\\[()\\]\\(\\)`)\n\t\tresult := env.Completion(compl)\n\n\t\twantLabel := []string{\"InterfaceA\", \"TypeA\", \"InterfaceB\", \"TypeB\", \"TypeC\"}\n\n\t\tfor i, item := range result.Items[:len(wantLabel)] {\n\t\t\tif diff := cmp.Diff(wantLabel[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected label mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\n\t\tcompl = env.RegexpSearch(\"a.go\", `DoubleWrap\\[InterfaceA, ()_\\]\\(\\)`)\n\t\tresult = env.Completion(compl)\n\n\t\twantLabel = []string{\"InterfaceB\", \"TypeB\", \"TypeX\", \"InterfaceA\", \"TypeA\"}\n\n\t\tfor i, item := range result.Items[:len(wantLabel)] {\n\t\t\tif diff := cmp.Diff(wantLabel[i], item.Label); diff != \"\" {\n\t\t\t\tt.Errorf(\"Completion: unexpected label mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestDoubleParamReturnCompletion(t *testing.T) {\n\tsrc := reverseInferenceSrcPrelude + `\n\tfunc concrete() (Wrap[InterfaceA], Wrap[InterfaceB]) {\n\t\treturn DoubleWrap[]()\n\t}\n\n\tfunc concrete2() (Wrap[InterfaceA], Wrap[InterfaceB]) {\n\t\treturn DoubleWrap[InterfaceA, _]()\n\t}\n\t`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\ttests := map[string][]string{\n\t\t\t`DoubleWrap\\[()\\]\\(\\)`:               {\"InterfaceA\", \"TypeA\", \"InterfaceB\", \"TypeB\", \"TypeC\"},\n\t\t\t`DoubleWrap\\[InterfaceA, ()\\_\\]\\(\\)`: {\"InterfaceB\", \"TypeB\", \"TypeX\", \"InterfaceA\", \"TypeA\"},\n\t\t}\n\n\t\tfor re, wantLabels := range tests {\n\t\t\tcompl := env.RegexpSearch(\"a.go\", re)\n\t\t\tresult := env.Completion(compl)\n\t\t\tif len(result.Items) < len(wantLabels) {\n\t\t\t\tt.Fatalf(\"Completion(%q) returned mismatching labels: got %v, want at least labels %v\", re, result.Items, wantLabels)\n\t\t\t}\n\t\t\tfor i, item := range result.Items[:len(wantLabels)] {\n\t\t\t\tif diff := cmp.Diff(wantLabels[i], item.Label); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"Completion(%q): unexpected label mismatch (-want +got):\\n%s\", re, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestBuiltinCompletion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- a.go --\npackage a\n\nfunc _() {\n\t// here\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tresult := env.Completion(env.RegexpSearch(\"a.go\", `()\\/\\/ here`))\n\t\tbuiltins := []string{\n\t\t\t\"any\", \"append\", \"bool\", \"byte\", \"cap\", \"close\",\n\t\t\t\"comparable\", \"complex\", \"complex128\", \"complex64\", \"copy\", \"delete\",\n\t\t\t\"error\", \"false\", \"float32\", \"float64\", \"imag\", \"int\", \"int16\", \"int32\",\n\t\t\t\"int64\", \"int8\", \"len\", \"make\", \"new\", \"panic\", \"print\", \"println\", \"real\",\n\t\t\t\"recover\", \"rune\", \"string\", \"true\", \"uint\", \"uint16\", \"uint32\", \"uint64\",\n\t\t\t\"uint8\", \"uintptr\", \"nil\",\n\t\t}\n\t\tif testenv.Go1Point() >= 21 {\n\t\t\tbuiltins = append(builtins, \"clear\", \"max\", \"min\")\n\t\t}\n\t\tsort.Strings(builtins)\n\t\tvar got []string\n\n\t\tfor _, item := range result.Items {\n\t\t\t// TODO(rfindley): for flexibility, ignore zero while it is being\n\t\t\t// implemented. Remove this if/when zero lands.\n\t\t\tif item.Label != \"zero\" {\n\t\t\t\tgot = append(got, item.Label)\n\t\t\t}\n\t\t}\n\t\tsort.Strings(got)\n\n\t\tif diff := cmp.Diff(builtins, got); diff != \"\" {\n\t\t\tt.Errorf(\"Completion: unexpected mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestOverlayCompletion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo.test\n\ngo 1.18\n\n-- foo/foo.go --\npackage foo\n\ntype Foo struct{}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"nodisk/nodisk.go\", `\npackage nodisk\n\nimport (\n\t\"foo.test/foo\"\n)\n\nfunc _() {\n\tfoo.Foo()\n}\n`)\n\t\tlist := env.Completion(env.RegexpSearch(\"nodisk/nodisk.go\", \"foo.()Foo\"))\n\t\twant := []string{\"Foo\"}\n\t\tvar got []string\n\t\tfor _, item := range list.Items {\n\t\t\tgot = append(got, item.Label)\n\t\t}\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"Completion: unexpected mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\n// Fix for golang/go#60062: unimported completion included \"golang.org/toolchain\" results.\n// and check that functions (from the standard library) have snippets\nfunc TestToolchainCompletions(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo.test/foo\n\ngo 1.21\n\n-- foo.go --\npackage foo\n\nfunc _() {\n\tos.Open\n}\n\nfunc _() {\n\tstrings\n}\n`\n\n\tconst proxy = `\n-- golang.org/toolchain@v0.0.1-go1.21.1.linux-amd64/go.mod --\nmodule golang.org/toolchain\n-- golang.org/toolchain@v0.0.1-go1.21.1.linux-amd64/src/os/os.go --\npackage os\n\nfunc Open() {}\n-- golang.org/toolchain@v0.0.1-go1.21.1.linux-amd64/src/strings/strings.go --\npackage strings\n\nfunc Join() {}\n`\n\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"mod\", \"download\", \"golang.org/toolchain@v0.0.1-go1.21.1.linux-amd64\")\n\t\tenv.OpenFile(\"foo.go\")\n\n\t\tfor _, pattern := range []string{\"os.Open()\", \"string()\"} {\n\t\t\tloc := env.RegexpSearch(\"foo.go\", pattern)\n\t\t\tres := env.Completion(loc)\n\t\t\tfor _, item := range res.Items {\n\t\t\t\tif strings.Contains(item.Detail, \"golang.org/toolchain\") {\n\t\t\t\t\tt.Errorf(\"Completion(...) returned toolchain item %#v\", item)\n\t\t\t\t}\n\t\t\t\tif strings.HasPrefix(item.Detail, \"func\") {\n\t\t\t\t\t// check that there are snippets\n\t\t\t\t\tx, ok := item.TextEdit.Value.(protocol.InsertReplaceEdit)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"item.TextEdit.Value unexpected type %T\", item.TextEdit.Value)\n\t\t\t\t\t}\n\t\t\t\t\tif !strings.Contains(x.NewText, \"${1\") {\n\t\t\t\t\t\tt.Errorf(\"expected snippet in %q\", x.NewText)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\n// when completing using the module cache, prefer things mentioned\n// in the go.mod file.\nfunc TestIssue61208(t *testing.T) {\n\n\tconst cache = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.22\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.22\n-- random.org@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Hello\"\n`\n\tconst files = `\n-- go.mod --\nmodule mod.com\ngo 1.22\nrequire random.org v1.2.3\n-- main.go --\npackage main\nvar _ = blah.\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\tmx := fake.UnpackTxt(cache)\n\tfor k, v := range mx {\n\t\tfname := filepath.Join(modcache, k)\n\t\tdir := filepath.Dir(fname)\n\t\tos.MkdirAll(dir, 0777) // ignore error\n\t\tif err := os.WriteFile(fname, v, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tWithOptions(\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tWriteGoSum(\".\"),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t\tNoLogsOnError(),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"main.go\", \"blah.()\")\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) != 1 {\n\t\t\tt.Errorf(\"got %d, expected 1\", len(completions.Items))\n\t\t\tfor _, x := range completions.Items {\n\t\t\t\tt.Logf(\"%#v\", x.AdditionalTextEdits[0].NewText)\n\t\t\t}\n\t\t}\n\t\tif got := completions.Items[0].AdditionalTextEdits[0].NewText; !strings.Contains(got, `\"random.org`) {\n\t\t\tt.Errorf(\"got %q, expected a `random.org`\", got)\n\t\t}\n\t})\n}\n\n// show that the efficacy counters get exercised. Fortunately a small program\n// exercises them all\nfunc TestCounters(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\ngo 1.21\n-- x.go --\npackage foo\n\nfunc main() {\n}\n\n`\n\tWithOptions(\n\t\tModes(Default),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tcts := func() map[*counter.Counter]uint64 {\n\t\t\tans := make(map[*counter.Counter]uint64)\n\t\t\tfor _, c := range server.CompletionCounters {\n\t\t\t\tans[c], _ = countertest.ReadCounter(c)\n\t\t\t}\n\t\t\treturn ans\n\t\t}\n\t\tbefore := cts()\n\t\tenv.OpenFile(\"x.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tsaved := env.BufferText(\"x.go\")\n\t\tlines := strings.Split(saved, \"\\n\")\n\t\t// make sure the unused counter is exercised\n\t\tloc := env.RegexpSearch(\"x.go\", \"main\")\n\t\tloc.Range.End = loc.Range.Start\n\t\tenv.Completion(loc)                       // ignore the proposed completions\n\t\tenv.RegexpReplace(\"x.go\", \"main\", \"Main\") // completions are unused\n\t\tenv.SetBufferContent(\"x.go\", saved)       // restore x.go\n\t\t// used:no\n\n\t\t// all the action is after 4 characters on line 2 (counting from 0)\n\t\tfor i := 2; i < len(lines); i++ {\n\t\t\tl := lines[i]\n\t\t\tloc.Range.Start.Line = uint32(i)\n\t\t\tfor j := 4; j < len(l); j++ {\n\t\t\t\tloc.Range.Start.Character = uint32(j)\n\t\t\t\tloc.Range.End = loc.Range.Start\n\t\t\t\tres := env.Completion(loc)\n\t\t\t\tif len(res.Items) > 0 {\n\t\t\t\t\tr := res.Items[0]\n\t\t\t\t\tenv.AcceptCompletion(loc, r)\n\t\t\t\t\tenv.SetBufferContent(\"x.go\", saved)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tafter := cts()\n\t\tfor c := range after {\n\t\t\tif after[c] <= before[c] {\n\t\t\t\tt.Errorf(\"%s did not increase\", c.Name())\n\t\t\t}\n\t\t}\n\t})\n}\n\n// find import foo \"bar\" for foo.xxx\nfunc TestImportAlias(t *testing.T) {\n\ttestenv.NeedsGoCommand1Point(t, 24) // we will find math/rand/v2\n\tconst files = `\n-- a.go --\npackage x\nvar _ = xrand.\n-- b.go --\npackage x\n\nimport xrand \"math/rand\"\n\nvar _ = xrand.Int()\n\n-- go.mod --\nmodule foo.com\n\ngo 1.24.2\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"a.go\", \"xrand.()\")\n\t\tcompls := env.Completion(loc)\n\t\tif len(compls.Items) == 0 {\n\t\t\tt.Fatal(\"no completions\")\n\t\t}\n\t\tone := compls.Items[0].AdditionalTextEdits[0].NewText\n\t\tif one != \"\\nimport xrand \\\"math/rand\\\"\\n\" {\n\t\t\tt.Errorf(\"wrong import %q\", one)\n\t\t}\n\t})\n}\n\nfunc TestModIndexDirEmpty(t *testing.T) {\n\t// Test for issue #75505. Do not run this test in parallel.\n\t// Test that if modindex.IndexDir is empty, we still get stdlib completions\n\t// but not unimported completions from modules.\n\n\t// Save/restore IndexDir, and set it to empty string.\n\t// This simulates having no module cache.\n\told := modindex.IndexDir\n\tmodindex.IndexDir = \"\"\n\tdefer func() { modindex.IndexDir = old }()\n\t// for the paranoid, with modindex.IndexDir = old here, the test fails\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\ngo 1.22\nrequire example.com v1.2.3\n-- main.go --\npackage main\nfunc main() {\n\t_ = fmt.P\n\t_ = blah.N\n}\n-- main2.go --\npackage main\nimport \"example.com/blah\"\nfunc _() {\n\t_ = blah.Hello\n}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy), // providing example.com through GOPROXY to the go command\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t// We need example.com in the module cache, but not\n\t\t// otherwise available to the completion logic.\n\t\tenv.RemoveWorkspaceFile(\"main2.go\")\n\t\tenv.RunGoCommand(\"mod\", \"tidy\")\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\t// 1. Check stdlib completion (should work)\n\t\tloc := env.RegexpSearch(\"main.go\", \"fmt.P()\")\n\t\tcompletions := env.Completion(loc)\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Errorf(\"stdlib completion failed to find fmt.Print...\")\n\t\t}\n\n\t\t// 2. Check unimported completion (should fail)\n\t\t// We look for \"blah.H\" which is from example.com\n\t\tloc = env.RegexpSearch(\"main.go\", \"blah.N()\")\n\t\tcompletions = env.Completion(loc)\n\n\t\t// We expect NO unimported completions for blah.Name because modindex is disabled.\n\t\tfor _, item := range completions.Items {\n\t\t\t// We shouldn't get candidate from example.com/blah.\n\t\t\tif strings.Contains(item.Detail, \"example.com/blah\") {\n\t\t\t\tt.Errorf(\"unexpected unimported completion for blah with empty IndexDir: %v\", item)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/completion/fixedbugs_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestPackageCompletionCrash_Issue68169(t *testing.T) {\n\t// This test reproduces the scenario of golang/go#68169, a crash in\n\t// completion.Selection.Suffix.\n\t//\n\t// The file content here is extracted from the issue.\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.18\n-- playdos/play.go --\npackage   // comment (to preserve spaces)\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"playdos/play.go\")\n\t\t// Previously, this call would crash gopls as it was incorrectly computing\n\t\t// the surrounding completion suffix.\n\t\tcompletions := env.Completion(env.RegexpSearch(\"playdos/play.go\", \"package  ()\"))\n\t\tif len(completions.Items) == 0 {\n\t\t\tt.Fatal(\"Completion() returned empty results\")\n\t\t}\n\t\t// Sanity check: we should get package clause completion.\n\t\tif got, want := completions.Items[0].Label, \"package playdos\"; got != want {\n\t\t\tt.Errorf(\"Completion()[0].Label == %s, want %s\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestFixInitStatementCrash_Issue72026(t *testing.T) {\n\t// This test checks that we don't crash when the if condition overflows the\n\t// file (as is possible with a malformed struct type).\n\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.18\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"p.go\", \"package p\\nfunc _() {\\n\\tfor i := struct\")\n\t\tenv.AfterChange()\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/completion/postfix_snippet_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage completion\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestPostfixSnippetCompletion(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n`\n\n\tcases := []struct {\n\t\tname              string\n\t\tbefore, after     string\n\t\tallowMultipleItem bool\n\t}{\n\t\t{\n\t\t\tname: \"sort\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.sort\n}\n`,\n\t\t\tafter: `\npackage foo\n\nimport \"sort\"\n\nfunc _() {\n\tvar foo []int\n\tsort.Slice(foo, func(i, j int) bool {\n\t$0\n})\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"sort_renamed_sort_package\",\n\t\t\tbefore: `\npackage foo\n\nimport blahsort \"sort\"\n\nvar j int\n\nfunc _() {\n\tvar foo []int\n\tfoo.sort\n}\n`,\n\t\t\tafter: `\npackage foo\n\nimport blahsort \"sort\"\n\nvar j int\n\nfunc _() {\n\tvar foo []int\n\tblahsort.Slice(foo, func(i, j2 int) bool {\n\t$0\n})\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"last\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar s struct { i []int }\n\ts.i.last\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar s struct { i []int }\n\ts.i[len(s.i)-1]\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"reverse\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.reverse\n}\n`,\n\t\t\tafter: `\npackage foo\n\nimport \"slices\"\n\nfunc _() {\n\tvar foo []int\n\tslices.Reverse(foo)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"slice_range\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\ttype myThing struct{}\n\tvar foo []myThing\n\tfoo.range\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\ttype myThing struct{}\n\tvar foo []myThing\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"append_stmt\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.append\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo = append(foo, $0)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"append_expr\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tvar _ []int = foo.append\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tvar _ []int = append(foo, $0)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"slice_copy\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.copy\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfooCopy := make([]int, len(foo))\ncopy(fooCopy, foo)\n\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"map_range\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.range\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"map_clear\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.clear\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfor k := range foo {\n\tdelete(foo, k)\n}\n\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"map_keys\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.keys\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tkeys := make([]string, 0, len(foo))\nfor k := range foo {\n\tkeys = append(keys, k)\n}\n\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"channel_range\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tfoo := make(chan int)\n\tfoo.range\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tfoo := make(chan int)\n\tfor ${1:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"var\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() (int, error) { return 0, nil }\n\nfunc _() {\n\tfoo().var\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc foo() (int, error) { return 0, nil }\n\nfunc _() {\n\t${1:}, ${2:} := foo()\n}\n`,\n\t\t\tallowMultipleItem: true,\n\t\t},\n\t\t{\n\t\t\tname: \"var_single_value\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() error { return nil }\n\nfunc _() {\n\tfoo().var\n}\n`,\n\t\t\tallowMultipleItem: true,\n\t\t\tafter: `\npackage foo\n\nfunc foo() error { return nil }\n\nfunc _() {\n\t${1:} := foo()\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"var_same_type\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() (int, int) { return 0, 0 }\n\nfunc _() {\n\tfoo().var\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc foo() (int, int) { return 0, 0 }\n\nfunc _() {\n\t${1:}, ${2:} := foo()\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"print_scalar\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo int\n\tfoo.print\n}\n`,\n\t\t\tafter: `\npackage foo\n\nimport \"fmt\"\n\nfunc _() {\n\tvar foo int\n\tfmt.Printf(\"foo: %v\\n\", foo)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"print_multi\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() (int, error) { return 0, nil }\n\nfunc _() {\n\tfoo().print\n}\n`,\n\t\t\tafter: `\npackage foo\n\nimport \"fmt\"\n\nfunc foo() (int, error) { return 0, nil }\n\nfunc _() {\n\tfmt.Println(foo())\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"string split\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() []string {\n\tx := \"test\"\n\treturn x.split\n}`,\n\t\t\tafter: `\npackage foo\n\nimport \"strings\"\n\nfunc foo() []string {\n\tx := \"test\"\n\treturn strings.Split(x, \"$0\")\n}`,\n\t\t},\n\t\t{\n\t\t\tname: \"string slice join\",\n\t\t\tbefore: `\npackage foo\n\nfunc foo() string {\n\tx := []string{\"a\", \"test\"}\n\treturn x.join\n}`,\n\t\t\tafter: `\npackage foo\n\nimport \"strings\"\n\nfunc foo() string {\n\tx := []string{\"a\", \"test\"}\n\treturn strings.Join(x, \"$0\")\n}`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil interface\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo error\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo error\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil pointer\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo *int\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo *int\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil slice\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil map\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]any\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]any\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil channel\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo chan int\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo chan int\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"if not nil function\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo func()\n\tfoo.ifnotnil\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo func()\n\tif foo != nil {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"slice_len\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.len\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tlen(foo)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"map_len\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.len\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tlen(foo)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname:              \"slice_for\",\n\t\t\tallowMultipleItem: true,\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.for\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfor ${1:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname:              \"map_for\",\n\t\t\tallowMultipleItem: true,\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.for\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfor ${1:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname:              \"chan_for\",\n\t\t\tallowMultipleItem: true,\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo chan int\n\tfoo.for\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo chan int\n\tfor ${1:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"slice_forr\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.forr\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"slice_forr\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfoo.forr\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo []int\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"map_forr\",\n\t\t\tbefore: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfoo.forr\n}\n`,\n\t\t\tafter: `\npackage foo\n\nfunc _() {\n\tvar foo map[string]int\n\tfor ${1:}, ${2:} := range foo {\n\t$0\n}\n}\n`,\n\t\t},\n\t}\n\n\tr := WithOptions(\n\t\tSettings{\n\t\t\t\"experimentalPostfixCompletions\": true,\n\t\t},\n\t)\n\tr.Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"foo.go\", \"\")\n\n\t\tfor _, c := range cases {\n\t\t\tt.Run(c.name, func(t *testing.T) {\n\t\t\t\tc.before = strings.Trim(c.before, \"\\n\")\n\t\t\t\tc.after = strings.Trim(c.after, \"\\n\")\n\n\t\t\t\tenv.SetBufferContent(\"foo.go\", c.before)\n\n\t\t\t\tloc := env.RegexpSearch(\"foo.go\", `()\\n\\}`)\n\t\t\t\tcompletions := env.Completion(loc)\n\t\t\t\tif len(completions.Items) < 1 {\n\t\t\t\t\tt.Fatalf(\"expected at least one completion, got %v\", completions.Items)\n\t\t\t\t}\n\t\t\t\tif !c.allowMultipleItem && len(completions.Items) > 1 {\n\t\t\t\t\tt.Fatalf(\"expected one completion, got %v\", completions.Items)\n\t\t\t\t}\n\n\t\t\t\tenv.AcceptCompletion(loc, completions.Items[0])\n\n\t\t\t\tif buf := env.BufferText(\"foo.go\"); buf != c.after {\n\t\t\t\t\tt.Errorf(\"\\nGOT:\\n%s\\nEXPECTED:\\n%s\", buf, c.after)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/debug/debug_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage debug\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tos.Exit(Main(m))\n}\n\nfunc TestBugNotification(t *testing.T) {\n\t// Verify that a properly configured session gets notified of a bug on the\n\t// server.\n\tWithOptions(\n\t\tModes(Default), // must be in-process to receive the bug report below\n\t\tSettings{\"showBugReports\": true},\n\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\tconst desc = \"got a bug\"\n\t\tbug.Report(desc)\n\t\tenv.Await(ShownMessage(desc))\n\t})\n}\n\n// TestStartDebugging executes a gopls.start_debugging command to\n// start the internal web server.\nfunc TestStartDebugging(t *testing.T) {\n\tWithOptions(\n\t\tModes(Default), // doesn't work in Forwarded mode\n\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\t// Start a debugging server.\n\t\tres, err := startDebugging(env.Ctx, env.Editor.Server, &command.DebuggingArgs{\n\t\t\tAddr: \"\", // any free port\n\t\t})\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"startDebugging: %v\", err)\n\t\t}\n\n\t\t// Assert that the server requested that the\n\t\t// client show the debug page in a browser.\n\t\tdebugURL := res.URLs[0]\n\t\tenv.Await(ShownDocument(debugURL))\n\n\t\t// Send a request to the debug server and ensure it responds.\n\t\tresp, err := http.Get(debugURL)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdefer resp.Body.Close()\n\t\tdata, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"reading HTTP response body: %v\", err)\n\t\t}\n\t\tconst want = \"<title>Gopls\"\n\t\tif !strings.Contains(string(data), want) {\n\t\t\tt.Errorf(\"GET %s response does not contain %q: <<%s>>\", debugURL, want, data)\n\t\t}\n\t})\n}\n\n// startDebugging starts a debugging server.\n// TODO(adonovan): move into command package?\nfunc startDebugging(ctx context.Context, server protocol.Server, args *command.DebuggingArgs) (*command.DebuggingResult, error) {\n\trawArgs, err := command.MarshalArgs(args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres0, err := server.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{\n\t\tCommand:   command.StartDebugging.String(),\n\t\tArguments: rawArgs,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// res0 is the result of a schemaless (map[string]any) JSON decoding.\n\t// Re-encode and decode into the correct Go struct type.\n\t// TODO(adonovan): fix (*serverDispatcher).ExecuteCommand.\n\tdata, err := json.Marshal(res0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar res *command.DebuggingResult\n\tif err := json.Unmarshal(data, &res); err != nil {\n\t\treturn nil, err\n\t}\n\treturn res, nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/analysis_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// Test for the timeformat analyzer, following golang/vscode-go#2406.\n//\n// This test checks that applying the suggested fix from the analyzer resolves\n// the diagnostic warning.\nfunc TestTimeFormatAnalyzer(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\tnow := time.Now()\n\tfmt.Println(now.Format(\"2006-02-01\"))\n}`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"2006-02-01\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\nfunc TestAnalysisProgressReporting(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- main.go --\npackage main\n\nfunc main() {\n}`\n\n\ttests := []struct {\n\t\tsetting bool\n\t\twant    Expectation\n\t}{\n\t\t{true, CompletedWork(cache.AnalysisProgressTitle, 1, true)},\n\t\t{false, Not(CompletedWork(cache.AnalysisProgressTitle, 1, true))},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprint(test.setting), func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tSettings{\n\t\t\t\t\t\"reportAnalysisProgressAfter\": \"0s\",\n\t\t\t\t\t\"analysisProgressReporting\":   test.setting,\n\t\t\t\t},\n\t\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"main.go\")\n\t\t\t\tenv.AfterChange(test.want)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Test the embed directive analyzer.\n//\n// There is a fix for missing imports, but it should not trigger for other\n// kinds of issues reported by the analayzer, here the variable\n// declaration following the embed directive is wrong.\nfunc TestNoSuggestedFixesForEmbedDirectiveDeclaration(t *testing.T) {\n\tconst generated = `\n-- go.mod --\nmodule mod.com\n\ngo 1.20\n\n-- foo.txt --\nFOO\n\n-- main.go --\npackage main\n\nimport _ \"embed\"\n\n//go:embed foo.txt\nvar foo, Bar string\n\nfunc main() {\n\t_ = foo\n}\n`\n\tRun(t, generated, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"//go:embed\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tif fixes := env.GetQuickFixes(\"main.go\", d.Diagnostics); len(fixes) != 0 {\n\t\t\tt.Errorf(\"got quick fixes %v, wanted none\", fixes)\n\t\t}\n\t})\n}\n\nfunc TestAnalysisFiltering(t *testing.T) {\n\t// This test checks that hint level diagnostics are only surfaced for open\n\t// files.\n\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.20\n\n-- a.go --\npackage p\n\nvar X interface{}\n\n-- b.go --\npackage p\n\nvar Y interface{}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(ForFile(\"a.go\"), WithMessage(\"replaced by any\")),\n\t\t\tNoDiagnostics(ForFile(\"b.go\")),\n\t\t)\n\t})\n}\n\nfunc TestModernizationConsistency_Issue75000(t *testing.T) {\n\ttestenv.SkipAfterGoCommand1Point(t, 24)\n\ttestenv.NeedsGoCommand1Point(t, 22) // uses range-over-int\n\n\t// This test checks that we don't offer modernization suggestions when the\n\t// ambient Go version is older than the modernized APIs.\n\t//\n\t// The code is from golang/go#75000, where gopls suggested to use\n\t// `waitgroup.Go` even though the user was on 1.24.\n\n\tconst src = `\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\nfunc doit(i int) {\n\tfmt.Println(\"i = \", i)\n}\n\nfunc main() {\n\tvar wg sync.WaitGroup\n\tfor i := range 5 {\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\tdoit(i)\n\t\t}()\n\t}\n\n\twg.Wait()\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/builtin_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestIssue44866(t *testing.T) {\n\tsrc := `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a.go --\npackage a\n\nconst (\n\tc = iota\n)\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"a.go\", \"iota\"))\n\t\tif !strings.HasSuffix(string(loc.URI), \"builtin.go\") {\n\t\t\tt.Fatalf(\"jumped to %q, want builtin.go\", loc.URI)\n\t\t}\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"builtin.go\")))\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/diagnostics_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\n// Use mod.com for all go.mod files due to golang/go#35230.\nconst exampleProgram = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello World.\")\n}`\n\nfunc TestDiagnosticErrorInEditedFile(t *testing.T) {\n\t// This test is very basic: start with a clean Go program, make an error, and\n\t// get a diagnostic for that error. However, it also demonstrates how to\n\t// combine Expectations to await more complex state in the editor.\n\tRunMultiple{\n\t\t{\"golist\", WithOptions(Modes(Default))},\n\t\t{\"gopackages\", WithOptions(\n\t\t\tModes(Default),\n\t\t\tFakeGoPackagesDriver(t),\n\t\t)},\n\t}.Run(t, exampleProgram, func(t *testing.T, env *Env) {\n\t\t// Deleting the 'n' at the end of Println should generate a single error\n\t\t// diagnostic.\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.RegexpReplace(\"main.go\", \"Printl(n)\", \"\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"Printl\")),\n\t\t\t// Assert that this test has sent no error logs to the client. This is not\n\t\t\t// strictly necessary for testing this regression, but is included here\n\t\t\t// as an example of using the NoErrorLogs() expectation. Feel free to\n\t\t\t// delete.\n\t\t\tNoErrorLogs(),\n\t\t)\n\t})\n}\n\nfunc TestMissingImportDiagsClearOnFirstFile(t *testing.T) {\n\tconst onlyMod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"pullDiagnostics\": true,\n\t\t},\n\t).Run(t, onlyMod, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", `package main\n\nfunc _() {\n\tlog.Println()\n}\n`)\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", \"log\")))\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tif got := env.Diagnostics(\"main.go\"); len(got) != 0 {\n\t\t\tt.Errorf(\"got %d diagnostics, want 0\", len(got))\n\t\t}\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\nfunc TestDiagnosticErrorInNewFile(t *testing.T) {\n\tconst brokenFile = `package main\n\nconst Foo = \"abc\n`\n\tRunMultiple{\n\t\t{\"golist\", WithOptions(Modes(Default))},\n\t\t// Since this test requires loading an overlay,\n\t\t// it verifies that the fake go/packages driver honors overlays.\n\t\t{\"gopackages\", WithOptions(\n\t\t\tModes(Default),\n\t\t\tFakeGoPackagesDriver(t),\n\t\t)},\n\t}.Run(t, brokenFile, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"broken.go\", brokenFile)\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"broken.go\", \"\\\"abc\")))\n\t})\n}\n\n// badPackage contains a duplicate definition of the 'A' const.\nconst badPackage = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a.go --\npackage consts\n\nconst A = 1\n-- b.go --\npackage consts\n\nconst A = 2\n`\n\nfunc TestDiagnosticClearingOnEdit(t *testing.T) {\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"pullDiagnostics\": true,\n\t\t},\n\t).Run(t, badPackage, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b.go\")\n\n\t\tfor _, f := range []string{\"a.go\", \"b.go\"} {\n\t\t\tif got := env.Diagnostics(f); len(got) != 1 {\n\t\t\t\tt.Errorf(\"textDocument/diagnostic(%s) returned %d diagnostics, want 1. Got %v\", f, len(got), got)\n\t\t\t}\n\t\t}\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", \"A = 1\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b.go\", \"A = 2\")),\n\t\t)\n\n\t\t// Fix the error by editing the const name A in b.go to `B`.\n\t\tenv.RegexpReplace(\"b.go\", \"(A) = 2\", \"B\")\n\t\tfor _, f := range []string{\"a.go\", \"b.go\"} {\n\t\t\tif got := env.Diagnostics(f); len(got) != 0 {\n\t\t\t\tt.Errorf(\"textDocument/diagnostic(%s) returned %d diagnostics, want 0. Got %v\", f, len(got), got)\n\t\t\t}\n\t\t}\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"b.go\")),\n\t\t)\n\t})\n}\n\nfunc TestDiagnosticClearingOnDelete_Issue37049(t *testing.T) {\n\tRun(t, badPackage, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", \"A = 1\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b.go\", \"A = 2\")),\n\t\t)\n\t\tenv.RemoveWorkspaceFile(\"b.go\")\n\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"b.go\")),\n\t\t)\n\t})\n}\n\nfunc TestDiagnosticClearingOnClose(t *testing.T) {\n\tRun(t, badPackage, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"c.go\", `package consts\n\nconst A = 3`)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", \"A = 1\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b.go\", \"A = 2\")),\n\t\t\tDiagnostics(env.AtRegexp(\"c.go\", \"A = 3\")),\n\t\t)\n\t\tenv.CloseBuffer(\"c.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", \"A = 1\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b.go\", \"A = 2\")),\n\t\t\tNoDiagnostics(ForFile(\"c.go\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#37978.\nfunc TestIssue37978(t *testing.T) {\n\tRun(t, exampleProgram, func(t *testing.T, env *Env) {\n\t\t// Create a new workspace-level directory and empty file.\n\t\tenv.CreateBuffer(\"c/c.go\", \"\")\n\n\t\t// Write the file contents with a missing import.\n\t\tenv.EditBuffer(\"c/c.go\", protocol.TextEdit{\n\t\t\tNewText: `package c\n\nconst A = http.MethodGet\n`,\n\t\t})\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"c/c.go\", \"http.MethodGet\")),\n\t\t)\n\t\t// Save file, which will organize imports, adding the expected import.\n\t\t// Expect the diagnostics to clear.\n\t\tenv.SaveBuffer(\"c/c.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#38878: good a.go, bad a_test.go, remove a_test.go but its errors remain\n// If the file is open in the editor, this is working as intended\n// If the file is not open in the editor, the errors go away\nconst test38878 = `\n-- go.mod --\nmodule foo\n\ngo 1.12\n-- a.go --\npackage x\n\n// import \"fmt\"\n\nfunc f() {}\n\n-- a_test.go --\npackage x\n\nimport \"testing\"\n\nfunc TestA(t *testing.T) {\n\tf(3)\n}\n`\n\n// Tests golang/go#38878: deleting a test file should clear its errors, and\n// not break the workspace.\nfunc TestDeleteTestVariant(t *testing.T) {\n\tRun(t, test38878, func(t *testing.T, env *Env) {\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"a_test.go\", `f\\((3)\\)`)))\n\t\tenv.RemoveWorkspaceFile(\"a_test.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"a_test.go\")))\n\n\t\t// Make sure the test variant has been removed from the workspace by\n\t\t// triggering a metadata load.\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.RegexpReplace(\"a.go\", `// import`, \"import\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"a.go\", `\"fmt\"`)))\n\t})\n}\n\n// Tests golang/go#38878: deleting a test file on disk while it's still open\n// should not clear its errors.\nfunc TestDeleteTestVariant_DiskOnly(t *testing.T) {\n\tRun(t, test38878, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a_test.go\")\n\t\tenv.AfterChange(Diagnostics(AtPosition(\"a_test.go\", 5, 3)))\n\t\tenv.Sandbox.Workdir.RemoveFile(context.Background(), \"a_test.go\") // ignore error\n\t\tenv.AfterChange(Diagnostics(AtPosition(\"a_test.go\", 5, 3)))\n\t})\n}\n\n// TestNoMod confirms that gopls continues to work when a user adds a go.mod\n// file to their workspace.\nfunc TestNoMod(t *testing.T) {\n\tconst noMod = `\n-- main.go --\npackage main\n\nimport \"mod.com/bob\"\n\nfunc main() {\n\tbob.Hello()\n}\n-- bob/bob.go --\npackage bob\n\nfunc Hello() {\n\tvar x int\n}\n`\n\n\tt.Run(\"manual\", func(t *testing.T) {\n\t\tRun(t, noMod, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"mod.com/bob\"`)),\n\t\t\t)\n\t\t\tenv.CreateBuffer(\"go.mod\", `module mod.com\n\n\tgo 1.12\n`)\n\t\t\tenv.SaveBuffer(\"go.mod\")\n\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"bob/bob.go\", \"x\")),\n\t\t\t\tReadDiagnostics(\"bob/bob.go\", &d),\n\t\t\t)\n\t\t\tif len(d.Diagnostics) != 1 {\n\t\t\t\tt.Fatalf(\"expected 1 diagnostic, got %v\", len(d.Diagnostics))\n\t\t\t}\n\t\t})\n\t})\n\tt.Run(\"initialized\", func(t *testing.T) {\n\t\tRun(t, noMod, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"mod.com/bob\"`)),\n\t\t\t)\n\t\t\tenv.RunGoCommand(\"mod\", \"init\", \"mod.com\")\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"bob/bob.go\", \"x\")),\n\t\t\t)\n\t\t})\n\t})\n\n\tt.Run(\"without workspace module\", func(t *testing.T) {\n\t\tWithOptions(\n\t\t\tModes(Default),\n\t\t).Run(t, noMod, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"mod.com/bob\"`)),\n\t\t\t)\n\t\t\tif _, err := env.Sandbox.RunGoCommand(env.Ctx, \"\", \"mod\", []string{\"init\", \"mod.com\"}, nil, true); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"bob/bob.go\", \"x\")),\n\t\t\t)\n\t\t})\n\t})\n}\n\n// Tests golang/go#38267.\nfunc TestIssue38267(t *testing.T) {\n\tconst testPackage = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- lib.go --\npackage lib\n\nfunc Hello(x string) {\n\t_ = x\n}\n-- lib_test.go --\npackage lib\n\nimport \"testing\"\n\ntype testStruct struct{\n\tname string\n}\n\nfunc TestHello(t *testing.T) {\n\ttestStructs := []*testStruct{\n\t\t&testStruct{\"hello\"},\n\t\t&testStruct{\"goodbye\"},\n\t}\n\tfor y := range testStructs {\n\t\t_ = y\n\t}\n}\n`\n\n\tRun(t, testPackage, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib_test.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(AtPosition(\"lib_test.go\", 10, 2)),\n\t\t\tDiagnostics(AtPosition(\"lib_test.go\", 11, 2)),\n\t\t)\n\t\tenv.OpenFile(\"lib.go\")\n\t\tenv.RegexpReplace(\"lib.go\", \"_ = x\", \"var y int\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"lib.go\", \"y int\")),\n\t\t\tNoDiagnostics(ForFile(\"lib_test.go\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#38328.\nfunc TestPackageChange_Issue38328(t *testing.T) {\n\tconst packageChange = `\n-- go.mod --\nmodule fake\n\ngo 1.12\n-- a.go --\npackage foo\nfunc main() {}\n`\n\tRun(t, packageChange, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.RegexpReplace(\"a.go\", \"foo\", \"foox\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a.go\")),\n\t\t)\n\t})\n}\n\nconst testPackageWithRequire = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire foo.test v1.2.3\n-- print.go --\npackage lib\n\nimport (\n\t\"fmt\"\n\n\t\"foo.test/bar\"\n)\n\nfunc PrintAnswer() {\n\tfmt.Printf(\"answer: %s\", bar.Answer)\n}\n`\n\nconst testPackageWithRequireProxy = `\n-- foo.test@v1.2.3/go.mod --\nmodule foo.test\n\ngo 1.12\n-- foo.test@v1.2.3/bar/const.go --\npackage bar\n\nconst Answer = 42\n`\n\nfunc TestResolveDiagnosticWithDownload(t *testing.T) {\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(testPackageWithRequireProxy),\n\t).Run(t, testPackageWithRequire, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"print.go\")\n\t\t// Check that gopackages correctly loaded this dependency. We should get a\n\t\t// diagnostic for the wrong formatting type.\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"print.go\", \"%s\"),\n\t\t\t\tWithMessage(\"wrong type int\"),\n\t\t\t),\n\t\t)\n\t})\n}\n\nfunc TestMissingDependency(t *testing.T) {\n\tRun(t, testPackageWithRequire, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"print.go\")\n\t\tenv.Await(\n\t\t\t// Log messages are asynchronous to other events on the LSP stream, so we\n\t\t\t// can't use OnceMet or AfterChange here.\n\t\t\tLogMatching(protocol.Error, \"initial workspace load failed\", 1, false),\n\t\t)\n\t})\n}\n\n// Tests golang/go#36951.\nfunc TestAdHocPackages_Issue36951(t *testing.T) {\n\tconst adHoc = `\n-- b/b.go --\npackage b\n\nfunc Hello() {\n\tvar x int\n}\n`\n\tRun(t, adHoc, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#37984: GOPATH should be read from the go command.\nfunc TestNoGOPATH_Issue37984(t *testing.T) {\n\tconst files = `\n-- main.go --\npackage main\n\nfunc _() {\n\tfmt.Println(\"Hello World\")\n}\n`\n\tWithOptions(\n\t\tEnvVars{\n\t\t\t\"GOPATH\":      \"\",\n\t\t\t\"GO111MODULE\": \"off\",\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", \"fmt\")))\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\n// Tests golang/go#38669.\nfunc TestEqualInEnv_Issue38669(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nvar _ = x.X\n-- x/x.go --\npackage x\n\nvar X = 0\n`\n\tWithOptions(\n\t\tEnvVars{\"GOFLAGS\": \"-tags=foo\"},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OrganizeImports(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\n// Tests golang/go#38467.\nfunc TestNoSuggestedFixesForGeneratedFiles_Issue38467(t *testing.T) {\n\t// This test ensures that gopls' CodeAction handler suppresses\n\t// diagnostics in generated code. Beware that many analyzers\n\t// themselves suppress diagnostics in generated files, in\n\t// particular the low-status \"simplifiers\" (modernize,\n\t// simplify{range,slice,compositelit}), so we use the hostport\n\t// analyzer here.\n\tconst generated = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\n// Code generated by generator.go. DO NOT EDIT.\n\npackage main\n\nimport (\"fmt\"; \"net\")\n\nfunc _() {\n\taddr := fmt.Sprintf(\"%s:%d\", \"localhost\", 12345)\n\tnet.Dial(\"tcp\", addr)\n}\n`\n\tRun(t, generated, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(AtPosition(\"main.go\", 7, 21)),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tif fixes := env.GetQuickFixes(\"main.go\", d.Diagnostics); len(fixes) != 0 {\n\t\t\tt.Errorf(\"got quick fixes %v, wanted none\", fixes)\n\t\t}\n\t})\n}\n\n// Expect a module/GOPATH error if there is an error in the file at startup.\n// Tests golang/go#37279.\nfunc TestBrokenWorkspace_OutsideModule(t *testing.T) {\n\tconst noModule = `\n-- a.go --\npackage foo\n\nimport \"mod.com/hello\"\n\nfunc f() {\n\thello.Goodbye()\n}\n`\n\tRun(t, noModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\t// AdHoc views are not critical errors, but their missing import\n\t\t\t// diagnostics should specifically mention GOROOT or GOPATH (and not\n\t\t\t// modules).\n\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a.go\", `\"mod.com`),\n\t\t\t\tWithMessage(\"in GOROOT\"),\n\t\t\t),\n\t\t)\n\t\t// Deleting the import dismisses the warning.\n\t\tenv.RegexpReplace(\"a.go\", `import \"mod.com/hello\"`, \"\")\n\t\tenv.AfterChange(\n\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t)\n\t})\n}\n\nfunc TestNonGoFolder(t *testing.T) {\n\tconst files = `\n-- hello.txt --\nhi mom\n`\n\tfor _, go111module := range []string{\"on\", \"off\", \"\"} {\n\t\tt.Run(fmt.Sprintf(\"GO111MODULE_%v\", go111module), func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tEnvVars{\"GO111MODULE\": go111module},\n\t\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Tests the repro case from golang/go#38602. Diagnostics are now handled properly,\n// which blocks type checking.\nfunc TestConflictingMainPackageErrors(t *testing.T) {\n\tconst collision = `\n-- x/x.go --\npackage x\n\nimport \"x/hello\"\n\nfunc Hello() {\n\thello.HiThere()\n}\n-- x/main.go --\npackage main\n\nfunc main() {\n\tfmt.Println(\"\")\n}\n`\n\tWithOptions(\n\t\tInGOPATH(),\n\t\tEnvVars{\"GO111MODULE\": \"off\"},\n\t).Run(t, collision, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"x/x.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"x/x.go\", `^`), WithMessage(\"found packages main (main.go) and x (x.go)\")),\n\t\t\tDiagnostics(env.AtRegexp(\"x/main.go\", `^`), WithMessage(\"found packages main (main.go) and x (x.go)\")),\n\t\t)\n\n\t\t// We don't recover cleanly from the errors without good overlay support.\n\t\tif testenv.Go1Point() >= 16 {\n\t\t\tenv.RegexpReplace(\"x/x.go\", `package x`, `package main`)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"x/main.go\", `fmt`)),\n\t\t\t)\n\t\t}\n\t})\n}\n\nconst ardanLabsProxy = `\n-- github.com/ardanlabs/conf@v1.2.3/go.mod --\nmodule github.com/ardanlabs/conf\n\ngo 1.12\n-- github.com/ardanlabs/conf@v1.2.3/conf.go --\npackage conf\n\nvar ErrHelpWanted error\n`\n\n// Test for golang/go#38211.\nfunc Test_issue38211(t *testing.T) {\n\tconst ardanLabs = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main.go --\npackage main\n\nimport \"github.com/ardanlabs/conf\"\n\nfunc main() {\n\t_ = conf.ErrHelpWanted\n}\n`\n\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\n\topts := []RunOption{\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tProxyFiles(ardanLabsProxy),\n\t\t//WriteGoSum(\".\"), // TODO(golang/go#74594): uncommenting this causes mysterious failure; investigate and make the error clearer (go list?)\n\t}\n\n\tt.Run(\"setup\", func(t *testing.T) {\n\t\t// Forcibly populate GOMODCACHE\n\t\t// so OrganizeImports can later rely on it.\n\t\tWithOptions(opts...).Run(t, ardanLabs, func(t *testing.T, env *Env) {\n\t\t\t// TODO(adonovan): why doesn't RunGoCommand respect EnvVars??\n\t\t\t// (That was the motivation to use Sandbox.RunGoCommand\n\t\t\t// rather than execute go mod download directly!)\n\t\t\t// See comment at CleanModCache and golang/go#74595.\n\t\t\tenviron := []string{\"GOMODCACHE=\" + modcache}\n\t\t\t_, err := env.Sandbox.RunGoCommand(env.Ctx, \"\", \"get\", []string{\"github.com/ardanlabs/conf@v1.2.3\"}, environ, false)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t})\n\t})\n\n\tWithOptions(opts...).Run(t, ardanLabs, func(t *testing.T, env *Env) {\n\t\t// Expect a \"no module provides package\" diagnostic.\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", `\"github.com/ardanlabs/conf\"`),\n\t\t\t\tWithMessage(\"no required module provides package\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\n\t\t// Apply the suggested fix to make the go.mod file\n\t\t// require \"github.com/ardanlabs/conf\".\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.SaveBuffer(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\n\t\t// Comment out the sole use of conf,\n\t\t// causing an \"unused import\" diagnostic.\n\t\tenv.RegexpReplace(\"main.go\", \"_ = conf.ErrHelpWanted\", \"//_ = conf.ErrHelpWanted\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", `\"github.com/ardanlabs/conf\"`),\n\t\t\t\tWithMessage(\"imported and not used\")),\n\t\t)\n\n\t\t// Remove the import using OrganizeImports, leading\n\t\t// to an \"unused require\" diagnostic in the go.mod.\n\t\tenv.SaveBuffer(\"main.go\") // => OrganizeImports\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"go.mod\", \"require github.com/ardanlabs/conf\"),\n\t\t\t\tWithMessage(\"not used in this module\")),\n\t\t\tReadDiagnostics(\"go.mod\", &d),\n\t\t)\n\n\t\t// Apply the suggested fix to remove the \"require\" directive.\n\t\tenv.ApplyQuickFixes(\"go.mod\", d.Diagnostics)\n\t\tenv.SaveBuffer(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"go.mod\")),\n\t\t)\n\n\t\t// Uncomment the use of the import.\n\t\t// OrganizeImports should add the import.\n\t\t// Expect another \"no required module provides package\"\n\t\t// diagnostic, bringing us full circle.\n\t\tenv.RegexpReplace(\"main.go\", \"//_ = conf.ErrHelpWanted\", \"_ = conf.ErrHelpWanted\")\n\t\tenv.SaveBuffer(\"main.go\") // => OrganizeImports\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", `\"github.com/ardanlabs/conf\"`),\n\t\t\t\tWithMessage(\"no required module provides package\")),\n\t\t)\n\t})\n}\n\n// Test for golang/go#38207.\nfunc TestNewModule_Issue38207(t *testing.T) {\n\tconst emptyFile = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\n`\n\tWithOptions(\n\t\tProxyFiles(ardanLabsProxy),\n\t).Run(t, emptyFile, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", `package main\n\nimport \"github.com/ardanlabs/conf\"\n\nfunc main() {\n\t_ = conf.ErrHelpWanted\n}\n`)\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"github.com/ardanlabs/conf\"`), WithMessage(\"no required module\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// Test for golang/go#36960.\nfunc TestNewFileBadImports_Issue36960(t *testing.T) {\n\tconst simplePackage = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- a/a1.go --\npackage a\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println(\"hi\")\n}\n`\n\tRun(t, simplePackage, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a1.go\")\n\t\tenv.CreateBuffer(\"a/a2.go\", ``)\n\t\tenv.SaveBufferWithoutActions(\"a/a2.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a1.go\")),\n\t\t)\n\t\tenv.EditBuffer(\"a/a2.go\", fake.NewEdit(0, 0, 0, 0, `package a`))\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a1.go\")),\n\t\t)\n\t})\n}\n\n// This test tries to replicate the workflow of a user creating a new x test.\n// It also tests golang/go#39315.\nfunc TestManuallyCreatingXTest(t *testing.T) {\n\t// Create a package that already has a test variant (in-package test).\n\tconst testVariant = `\n-- go.mod --\nmodule mod.com\n\ngo 1.15\n-- hello/hello.go --\npackage hello\n\nfunc Hello() {\n\tvar x int\n}\n-- hello/hello_test.go --\npackage hello\n\nimport \"testing\"\n\nfunc TestHello(t *testing.T) {\n\tvar x int\n\tHello()\n}\n`\n\tRun(t, testVariant, func(t *testing.T, env *Env) {\n\t\t// Open the file, triggering the workspace load.\n\t\t// There are errors in the code to ensure all is working as expected.\n\t\tenv.OpenFile(\"hello/hello.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"hello/hello.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"hello/hello_test.go\", \"x\")),\n\t\t)\n\n\t\t// Create an empty file with the intention of making it an x test.\n\t\t// This resembles a typical flow in an editor like VS Code, in which\n\t\t// a user would create an empty file and add content, saving\n\t\t// intermittently.\n\t\t// TODO(rstambler): There might be more edge cases here, as file\n\t\t// content can be added incrementally.\n\t\tenv.CreateBuffer(\"hello/hello_x_test.go\", ``)\n\n\t\t// Save the empty file (no actions since formatting will fail).\n\t\tenv.SaveBufferWithoutActions(\"hello/hello_x_test.go\")\n\n\t\t// Add the content. The missing import is for the package under test.\n\t\tenv.EditBuffer(\"hello/hello_x_test.go\", fake.NewEdit(0, 0, 0, 0, `package hello_test\n\nimport (\n\t\"testing\"\n)\n\nfunc TestHello(t *testing.T) {\n\thello.Hello()\n}\n`))\n\t\t// Expect a diagnostic for the missing import. Save, which should\n\t\t// trigger import organization. The diagnostic should clear.\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"hello/hello_x_test.go\", \"hello.Hello\")),\n\t\t)\n\t\tenv.SaveBuffer(\"hello/hello_x_test.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"hello/hello_x_test.go\")),\n\t\t)\n\t})\n}\n\n// Reproduce golang/go#40690.\nfunc TestCreateOnlyXTest(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo/foo.go --\npackage foo\n-- foo/bar_test.go --\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/bar_test.go\")\n\t\tenv.EditBuffer(\"foo/bar_test.go\", fake.NewEdit(0, 0, 0, 0, \"package foo\"))\n\t\tenv.Await(env.DoneWithChange())\n\t\tenv.RegexpReplace(\"foo/bar_test.go\", \"package foo\", `package foo_test\n\nimport \"testing\"\n\nfunc TestX(t *testing.T) {\n\tvar x int\n}\n`)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"foo/bar_test.go\", \"x\")),\n\t\t)\n\t})\n}\n\nfunc TestChangePackageName(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo/foo.go --\npackage foo\n-- foo/bar_test.go --\npackage foo_\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/bar_test.go\")\n\t\tenv.AfterChange()\n\t\tenv.RegexpReplace(\"foo/bar_test.go\", \"package foo_\", \"package foo_test\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"foo/bar_test.go\")),\n\t\t\tNoDiagnostics(ForFile(\"foo/foo.go\")),\n\t\t)\n\t})\n}\n\nfunc TestIgnoredFiles(t *testing.T) {\n\tconst ws = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- _foo/x.go --\npackage x\n\nvar _ = foo.Bar\n`\n\tRun(t, ws, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"_foo/x.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"_foo/x.go\")),\n\t\t)\n\t})\n}\n\n// Partially reproduces golang/go#38977, moving a file between packages.\n// It also gets hit by some go command bug fixed in 1.15, but we don't\n// care about that so much here.\nfunc TestDeletePackage(t *testing.T) {\n\tconst ws = `\n-- go.mod --\nmodule mod.com\n\ngo 1.15\n-- a/a.go --\npackage a\n\nconst A = 1\n\n-- b/b.go --\npackage b\n\nimport \"mod.com/a\"\n\nconst B = a.A\n\n-- c/c.go --\npackage c\n\nimport \"mod.com/a\"\n\nconst C = a.A\n`\n\tRun(t, ws, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b/b.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\t// Delete c/c.go, the only file in package c.\n\t\tenv.RemoveWorkspaceFile(\"c/c.go\")\n\n\t\t// We should still get diagnostics for files that exist.\n\t\tenv.RegexpReplace(\"b/b.go\", `a.A`, \"a.Nonexistant\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", `Nonexistant`)),\n\t\t)\n\t})\n}\n\n// This is a copy of the scenario_default/quickfix_empty_files.txt test from\n// govim. Reproduces golang/go#39646.\nfunc TestQuickFixEmptyFiles(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n`\n\t// To fully recreate the govim tests, we create files by inserting\n\t// a newline, adding to the file, and then deleting the newline.\n\t// Wait for each event to process to avoid cancellations and force\n\t// package loads.\n\twriteGoVim := func(env *Env, name, content string) {\n\t\tenv.WriteWorkspaceFile(name, \"\")\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\tenv.CreateBuffer(name, \"\\n\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\tenv.EditBuffer(name, fake.NewEdit(1, 0, 1, 0, content))\n\t\tenv.Await(env.DoneWithChange())\n\n\t\tenv.EditBuffer(name, fake.NewEdit(0, 0, 1, 0, \"\"))\n\t\tenv.Await(env.DoneWithChange())\n\t}\n\n\tconst p = `package p; func DoIt(s string) {};`\n\tconst main = `package main\n\nimport \"mod.com/p\"\n\nfunc main() {\n\tp.DoIt(5)\n}\n`\n\t// A simple version of the test that reproduces most of the problems it\n\t// exposes.\n\tt.Run(\"short\", func(t *testing.T) {\n\t\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\t\twriteGoVim(env, \"p/p.go\", p)\n\t\t\twriteGoVim(env, \"main.go\", main)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"5\")),\n\t\t\t)\n\t\t})\n\t})\n\n\t// A full version that replicates the whole flow of the test.\n\tt.Run(\"full\", func(t *testing.T) {\n\t\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\t\twriteGoVim(env, \"p/p.go\", p)\n\t\t\twriteGoVim(env, \"main.go\", main)\n\t\t\twriteGoVim(env, \"p/p_test.go\", `package p\n\nimport \"testing\"\n\nfunc TestDoIt(t *testing.T) {\n\tDoIt(5)\n}\n`)\n\t\t\twriteGoVim(env, \"p/x_test.go\", `package p_test\n\nimport (\n\t\"testing\"\n\n\t\"mod.com/p\"\n)\n\nfunc TestDoIt(t *testing.T) {\n\tp.DoIt(5)\n}\n`)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"5\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"p/p_test.go\", \"5\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"p/x_test.go\", \"5\")),\n\t\t\t)\n\t\t\tenv.RegexpReplace(\"p/p.go\", \"s string\", \"i int\")\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\t\tNoDiagnostics(ForFile(\"p/p_test.go\")),\n\t\t\t\tNoDiagnostics(ForFile(\"p/x_test.go\")),\n\t\t\t)\n\t\t})\n\t})\n}\n\nfunc TestSingleFile(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.13\n-- a/a.go --\npackage a\n\nfunc _() {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\t// Empty workspace folders.\n\t\tWorkspaceFolders(),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// Reproduces the case described in\n// https://github.com/golang/go/issues/39296#issuecomment-652058883.\nfunc TestPkgm(t *testing.T) {\n\tconst basic = `\n-- go.mod --\nmodule mod.com\n\ngo 1.15\n-- foo/foo.go --\npackage foo\n\nimport \"fmt\"\n\nfunc Foo() {\n\tfmt.Println(\"\")\n}\n`\n\tRun(t, basic, func(t *testing.T, env *Env) {\n\t\tenv.WriteWorkspaceFile(\"foo/foo_test.go\", `package main\n\nfunc main() {\n\n}`)\n\t\tenv.OpenFile(\"foo/foo_test.go\")\n\t\tenv.RegexpReplace(\"foo/foo_test.go\", `package main`, `package foo`)\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"foo/foo.go\")))\n\t})\n}\n\nfunc TestClosingBuffer(t *testing.T) {\n\tconst basic = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\tRun(t, basic, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"foo.go\", `package main`)\n\t\tenv.AfterChange()\n\t\tenv.CloseBuffer(\"foo.go\")\n\t\tenv.AfterChange(NoLogMatching(protocol.Info, \"packages=0\"))\n\t})\n}\n\n// Reproduces golang/go#38424.\nfunc TestCutAndPaste(t *testing.T) {\n\tconst basic = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main2.go --\npackage main\n`\n\tRun(t, basic, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", \"\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\tenv.SaveBufferWithoutActions(\"main.go\")\n\t\tenv.Await(env.DoneWithSave(), env.DoneWithChangeWatchedFiles())\n\n\t\tenv.EditBuffer(\"main.go\", fake.NewEdit(0, 0, 0, 0, `package main\n\nfunc main() {\n}\n`))\n\t\tenv.Await(env.DoneWithChange())\n\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tenv.Await(env.DoneWithSave(), env.DoneWithChangeWatchedFiles())\n\n\t\tenv.EditBuffer(\"main.go\", fake.NewEdit(0, 0, 4, 0, \"\"))\n\t\tenv.Await(env.DoneWithChange())\n\n\t\tenv.EditBuffer(\"main.go\", fake.NewEdit(0, 0, 0, 0, `package main\n\nfunc main() {\n\tvar x int\n}\n`))\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// Reproduces golang/go#39763.\nfunc TestInvalidPackageName(t *testing.T) {\n\tconst pkgDefault = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage default\n\nfunc main() {}\n`\n\tRun(t, pkgDefault, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", \"default\"),\n\t\t\t\tWithMessage(\"expected 'IDENT'\"),\n\t\t\t),\n\t\t)\n\t})\n}\n\n// This test verifies that the workspace scope is effectively limited to the\n// workspace folder, if expandWorkspaceToModule is set.\nfunc TestExpandWorkspaceToModule(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/main.go --\npackage main\n\nfunc main() {}\n-- main.go --\npackage main\n\nfunc main() {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\"),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"x\")),\n\t\t)\n\t})\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\"),\n\t\tSettings{\"expandWorkspaceToModule\": false},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// This test verifies that the workspace scope is effectively limited to the\n// set of active modules.\n//\n// We should not get diagnostics or file watching patterns for paths outside of\n// the active workspace.\nfunc TestWorkspaceModules(t *testing.T) {\n\tconst mod = `\n-- go.work --\ngo 1.18\n\nuse a\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.12\n-- a/a.go --\npackage a\n\nfunc _() {\n\tvar x int\n}\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"subdirWatchPatterns\": \"on\",\n\t\t},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\t// Writing this file may cause the snapshot to 'know' about the file b, but\n\t\t// that shouldn't cause it to watch the 'b' directory.\n\t\tenv.WriteWorkspaceFile(\"b/b.go\", `package b\n\nfunc _() {\n\tvar x int\n}\n`)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tFileWatchMatching(\"a$\"),\n\t\t\tNoFileWatchMatching(\"b$\"),\n\t\t)\n\t})\n}\n\nfunc TestSimplifyCompositeLitDiagnostic(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\ntype t struct {\n\tmsg string\n}\n\nfunc main() {\n\tx := []t{t{\"msg\"}}\n\tfmt.Println(x)\n}\n`\n\n\tWithOptions(\n\t\tSettings{\"staticcheck\": true},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `t{\"msg\"}`), WithMessage(\"redundant type\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tif tags := d.Diagnostics[0].Tags; len(tags) == 0 || tags[0] != protocol.Unnecessary {\n\t\t\tt.Errorf(\"wanted Unnecessary tag on diagnostic, got %v\", tags)\n\t\t}\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\n// Test some secondary diagnostics\nfunc TestSecondaryDiagnostics(t *testing.T) {\n\tconst dir = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\nfunc main() {\n\tpanic(\"not here\")\n}\n-- other.go --\npackage main\nfunc main() {}\n`\n\tRun(t, dir, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OpenFile(\"other.go\")\n\t\tvar mainDiags, otherDiags protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"main.go\", &mainDiags),\n\t\t\tReadDiagnostics(\"other.go\", &otherDiags),\n\t\t)\n\t\tif len(mainDiags.Diagnostics) != 1 {\n\t\t\tt.Fatalf(\"main.go, got %d diagnostics, expected 1\", len(mainDiags.Diagnostics))\n\t\t}\n\t\tkeep := mainDiags.Diagnostics[0]\n\t\tif len(otherDiags.Diagnostics) != 1 {\n\t\t\tt.Fatalf(\"other.go: got %d diagnostics, expected 1\", len(otherDiags.Diagnostics))\n\t\t}\n\t\tif len(otherDiags.Diagnostics[0].RelatedInformation) != 1 {\n\t\t\tt.Fatalf(\"got %d RelatedInformations, expected 1\", len(otherDiags.Diagnostics[0].RelatedInformation))\n\t\t}\n\t\t// check that the RelatedInformation matches the error from main.go\n\t\tc := otherDiags.Diagnostics[0].RelatedInformation[0]\n\t\tif c.Location.Range != keep.Range {\n\t\t\tt.Errorf(\"locations don't match. Got %v expected %v\", c.Location.Range, keep.Range)\n\t\t}\n\t})\n}\n\nfunc TestOrphanedFiles(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nfunc main() {\n\tvar x int\n}\n-- a/a_exclude.go --\n// +build exclude\n\npackage a\n\nfunc _() {\n\tvar x int\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t)\n\t\tenv.OpenFile(\"a/a_exclude.go\")\n\n\t\tloadOnce := LogMatching(protocol.Info, \"query=.*file=.*a_exclude.go\", 1, false)\n\n\t\t// can't use OnceMet or AfterChange as logs are async\n\t\tenv.Await(loadOnce)\n\t\t// ...but ensure that the change has been fully processed before editing.\n\t\t// Otherwise, there may be a race where the snapshot is cloned before all\n\t\t// state changes resulting from the load have been processed\n\t\t// (golang/go#61521).\n\t\tenv.AfterChange()\n\n\t\t// Check that orphaned files are not reloaded, by making a change in\n\t\t// a.go file and confirming that the workspace diagnosis did not reload\n\t\t// a_exclude.go.\n\t\t//\n\t\t// This is racy (but fails open) because logs are asynchronous to other LSP\n\t\t// operations. There's a chance gopls _did_ log, and we just haven't seen\n\t\t// it yet.\n\t\tenv.RegexpReplace(\"a/a.go\", \"package a\", \"package a // arbitrary comment\")\n\t\tenv.AfterChange(loadOnce)\n\t})\n}\n\nfunc TestSwig(t *testing.T) {\n\tif _, err := exec.LookPath(\"swig\"); err != nil {\n\t\tt.Skip(\"skipping test: swig not available\")\n\t}\n\tif _, err := exec.LookPath(\"g++\"); err != nil {\n\t\tt.Skip(\"skipping test: g++ not available\")\n\t}\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- pkg/simple/export_swig.go --\npackage simple\n\nfunc ExportSimple(x, y int) int {\n\treturn Gcd(x, y)\n}\n-- pkg/simple/simple.swigcxx --\n%module simple\n\n%inline %{\nextern int gcd(int x, int y)\n{\n  int g;\n  g = y;\n  while (x > 0) {\n    g = x;\n    x = y % x;\n    y = g;\n  }\n  return g;\n}\n%}\n-- main.go --\npackage a\n\nfunc main() {\n\tvar x int\n}\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoDiagnostics(WithMessage(\"illegal character U+0023 '#'\")),\n\t\t)\n\t})\n}\n\n// When foo_test.go is opened, gopls will object to the borked package name.\n// This test asserts that when the package name is fixed, gopls will soon after\n// have no more complaints about it.\n// https://github.com/golang/go/issues/41061\nfunc TestRenamePackage(t *testing.T) {\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/blah/blah.go --\npackage hello\n\nconst Name = \"Hello\"\n`\n\n\tconst contents = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tblah.Hello()\n}\n-- bob.go --\npackage main\n-- foo/foo.go --\npackage foo\n-- foo/foo_test.go --\npackage foo_\n`\n\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tInGOPATH(),\n\t\tEnvVars{\"GO111MODULE\": \"off\"},\n\t).Run(t, contents, func(t *testing.T, env *Env) {\n\t\t// Simulate typing character by character.\n\t\tenv.OpenFile(\"foo/foo_test.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tenv.RegexpReplace(\"foo/foo_test.go\", \"_\", \"_t\")\n\t\tenv.Await(env.DoneWithChange())\n\t\tenv.RegexpReplace(\"foo/foo_test.go\", \"_t\", \"_test\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"foo/foo_test.go\")),\n\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t)\n\t})\n}\n\n// TestProgressBarErrors confirms that critical workspace load errors are shown\n// and updated via progress reports.\nfunc TestProgressBarErrors(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodul mod.com\n\ngo 1.12\n-- main.go --\npackage main\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tOutstandingWork(server.WorkspaceLoadFailure, \"unknown directive\"),\n\t\t)\n\t\tenv.EditBuffer(\"go.mod\", fake.NewEdit(0, 0, 3, 0, `module mod.com\n\ngo 1.hello\n`))\n\t\t// As of golang/go#42529, go.mod changes do not reload the workspace until\n\t\t// they are saved.\n\t\tenv.SaveBufferWithoutActions(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tOutstandingWork(server.WorkspaceLoadFailure, \"invalid go version\"),\n\t\t)\n\t\tenv.RegexpReplace(\"go.mod\", \"go 1.hello\", \"go 1.12\")\n\t\tenv.SaveBufferWithoutActions(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t)\n\t})\n}\n\nfunc TestDeleteDirectory(t *testing.T) {\n\tconst mod = `\n-- bob/bob.go --\npackage bob\n\nfunc Hello() {\n\tvar x int\n}\n-- go.mod --\nmodule mod.com\n-- cmd/main.go --\npackage main\n\nimport \"mod.com/bob\"\n\nfunc main() {\n\tbob.Hello()\n}\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t// Now that we don't watch subdirs by default (except for VS Code),\n\t\t\t// we must explicitly ask gopls to requests subdir watch patterns.\n\t\t\t\"subdirWatchPatterns\": \"on\",\n\t\t},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tFileWatchMatching(\"bob\"),\n\t\t)\n\t\tenv.RemoveWorkspaceFile(\"bob\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"cmd/main.go\", `\"mod.com/bob\"`)),\n\t\t\tNoDiagnostics(ForFile(\"bob/bob.go\")),\n\t\t\tNoFileWatchMatching(\"bob\"),\n\t\t)\n\t})\n}\n\n// Confirms that circular imports are tested and reported.\nfunc TestCircularImports(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- self/self.go --\npackage self\n\nimport _ \"mod.com/self\"\nfunc Hello() {}\n-- double/a/a.go --\npackage a\n\nimport _ \"mod.com/double/b\"\n-- double/b/b.go --\npackage b\n\nimport _ \"mod.com/double/a\"\n-- triple/a/a.go --\npackage a\n\nimport _ \"mod.com/triple/b\"\n-- triple/b/b.go --\npackage b\n\nimport _ \"mod.com/triple/c\"\n-- triple/c/c.go --\npackage c\n\nimport _ \"mod.com/triple/a\"\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"self/self.go\", `_ \"mod.com/self\"`), WithMessage(\"import cycle not allowed\")),\n\t\t\tDiagnostics(env.AtRegexp(\"double/a/a.go\", `_ \"mod.com/double/b\"`), WithMessage(\"import cycle not allowed\")),\n\t\t\tDiagnostics(env.AtRegexp(\"triple/a/a.go\", `_ \"mod.com/triple/b\"`), WithMessage(\"import cycle not allowed\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#46667: deleting a problematic import path should resolve\n// import cycle errors.\nfunc TestResolveImportCycle(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.test\n\ngo 1.16\n-- a/a.go --\npackage a\n\nimport \"mod.test/b\"\n\nconst A = b.A\nconst B = 2\n-- b/b.go --\npackage b\n\nimport \"mod.test/a\"\n\nconst A = 1\nconst B = a.B\n\t`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.OpenFile(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\t// The Go command sometimes tells us about only one of the import cycle\n\t\t\t// errors below. Also, sometimes we get an error during type checking\n\t\t\t// instead of during list, due to missing metadata. This is likely due to\n\t\t\t// a race.\n\t\t\t// For robustness of this test, succeed if we get any reasonable error.\n\t\t\t//\n\t\t\t// TODO(golang/go#52904): we should get *both* of these errors.\n\t\t\t// TODO(golang/go#64899): we should always get an import cycle error\n\t\t\t// rather than a missing metadata error.\n\t\t\tAnyOf(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", `\"mod.test/b\"`)),\n\t\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", `\"mod.test/a\"`)),\n\t\t\t),\n\t\t)\n\t\tenv.RegexpReplace(\"b/b.go\", `const B = a\\.B`, \"\")\n\t\tenv.SaveBuffer(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t)\n\t})\n}\n\nfunc TestBadImport(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport (\n\t_ \"nosuchpkg\"\n)\n`\n\tt.Run(\"module\", func(t *testing.T) {\n\t\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"nosuchpkg\"`), WithMessage(`could not import nosuchpkg (no required module provides package \"nosuchpkg\"`)),\n\t\t\t)\n\t\t})\n\t})\n\tt.Run(\"GOPATH\", func(t *testing.T) {\n\t\tWithOptions(\n\t\t\tInGOPATH(),\n\t\t\tEnvVars{\"GO111MODULE\": \"off\"},\n\t\t\tModes(Default),\n\t\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"nosuchpkg\"`), WithMessage(`cannot find package \"nosuchpkg\"`)),\n\t\t\t)\n\t\t})\n\t})\n}\n\nfunc TestNestedModules(t *testing.T) {\n\tconst proxy = `\n-- nested.com@v1.0.0/go.mod --\nmodule nested.com\n\ngo 1.12\n-- nested.com@v1.0.0/hello/hello.go --\npackage hello\n\nfunc Hello() {}\n`\n\n\tconst nested = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire nested.com v1.0.0\n-- main.go --\npackage main\n\nimport \"nested.com/hello\"\n\nfunc main() {\n\thello.Hello()\n}\n-- nested/go.mod --\nmodule nested.com\n\n-- nested/hello/hello.go --\npackage hello\n\nfunc Hello() {\n\thelloHelper()\n}\n-- nested/hello/hello_helper.go --\npackage hello\n\nfunc helloHelper() {}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t\tModes(Default),\n\t).Run(t, nested, func(t *testing.T, env *Env) {\n\t\t// Expect a diagnostic in a nested module.\n\t\tenv.OpenFile(\"nested/hello/hello.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"nested/hello/hello.go\")),\n\t\t)\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"nested/hello/hello.go\", \"helloHelper\"))\n\t\twant := \"nested/hello/hello_helper.go\"\n\t\tif got := env.Sandbox.Workdir.URIToPath(loc.URI); got != want {\n\t\t\tt.Errorf(\"Definition() returned %q, want %q\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestAdHocPackagesReloading(t *testing.T) {\n\tconst nomod = `\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\tRun(t, nomod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.RegexpReplace(\"main.go\", \"{}\", \"{ var x int; }\") // simulate typing\n\t\tenv.AfterChange(NoLogMatching(protocol.Info, \"packages=1\"))\n\t})\n}\n\nfunc TestBuildTagChange(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo.go --\n// decoy comment\n// +build hidden\n// decoy comment\n\npackage foo\nvar Foo = 1\n-- bar.go --\npackage foo\nvar Bar = Foo\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"bar.go\", `Foo`)))\n\t\tenv.RegexpReplace(\"foo.go\", `\\+build`, \"\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"bar.go\")))\n\t})\n\n}\n\nfunc TestIssue44736(t *testing.T) {\n\tconst files = `\n\t-- go.mod --\nmodule blah.com\n\ngo 1.16\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tasdf\n\tfmt.Printf(\"This is a test %v\")\n\tfdas\n}\n-- other.go --\npackage main\n\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OpenFile(\"other.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"asdf\")),\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"fdas\")),\n\t\t)\n\t\tenv.SetBufferContent(\"other.go\", \"package main\\n\\nasdf\")\n\t\t// The new diagnostic in other.go should not suppress diagnostics in main.go.\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"other.go\", \"asdf\"), WithMessage(\"expected declaration\")),\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"asdf\")),\n\t\t)\n\t})\n}\n\nfunc TestInitialization(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- main.go --\npackage main\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tenv.RegexpReplace(\"go.mod\", \"module\", \"modul\")\n\t\tenv.SaveBufferWithoutActions(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tNoLogMatching(protocol.Error, \"initial workspace load failed\"),\n\t\t)\n\t})\n}\n\n// This test confirms that the view does not reinitialize when a go.mod file is\n// opened.\nfunc TestNoReinitialize(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.Await(\n\t\t\t// Check that we have only loaded \"<dir>/...\" once.\n\t\t\t// Log messages are asynchronous to other events on the LSP stream, so we\n\t\t\t// can't use OnceMet or AfterChange here.\n\t\t\tLogMatching(protocol.Info, `.*query=.*\\.\\.\\..*`, 1, false),\n\t\t)\n\t})\n}\n\nfunc TestLangVersion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nconst C = 0b10\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `0b10`), WithMessage(\"go1.13 or later\")),\n\t\t)\n\t\tenv.WriteWorkspaceFile(\"go.mod\", \"module mod.com \\n\\ngo 1.13\\n\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\nfunc TestNoQuickFixForUndeclaredConstraint(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n\nfunc F[T C](_ T) {\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `C`)),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tif fixes := env.GetQuickFixes(\"main.go\", d.Diagnostics); len(fixes) != 0 {\n\t\t\tt.Errorf(\"got quick fixes %v, wanted none\", fixes)\n\t\t}\n\t})\n}\n\nfunc TestEditGoDirective(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- main.go --\npackage main\n\nfunc F[T any](_ T) {\n}\n`\n\tRun(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `T any`), WithMessage(\"type parameter\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\nfunc TestEditGoDirectiveWorkspace(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- go.work --\ngo 1.18\n\nuse .\n-- main.go --\npackage main\n\nfunc F[T any](_ T) {\n}\n`\n\tRun(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.\n\t\tvar d protocol.PublishDiagnosticsParams\n\n\t\t// We should have a diagnostic because generics are not supported at 1.16.\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `T any`), WithMessage(\"type parameter\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\n\t\t// This diagnostic should have a quick fix to edit the go version.\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\n\t\t// Once the edit is applied, the problematic diagnostics should be\n\t\t// resolved.\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// This test demonstrates that analysis facts are correctly propagated\n// across packages.\nfunc TestInterpackageAnalysis(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\n-- a/a.go --\npackage a\n\nimport \"example.com/b\"\n\nfunc _() {\n\tnew(b.B).Printf(\"%d\", \"s\") // printf error\n}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/c\"\n\ntype B struct{}\n\nfunc (B) Printf(format string, args ...interface{}) {\n\tc.MyPrintf(format, args...)\n}\n\n-- c/c.go --\npackage c\n\nimport \"fmt\"\n\nfunc MyPrintf(format string, args ...interface{}) {\n\tfmt.Printf(format, args...)\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a/a.go\", \"%d\"),\n\t\t\t\tWithMessage(\"format %d has arg \\\"s\\\" of wrong type string\"),\n\t\t\t),\n\t\t)\n\t})\n}\n\n// This test ensures that only Analyzers with RunDespiteErrors=true\n// are invoked on a package that would not compile, even if the errors\n// are distant and localized.\nfunc TestErrorsThatPreventAnalysis(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\n-- a/a.go --\npackage a\n\nimport \"fmt\"\nimport \"sync\"\nimport _ \"example.com/b\"\n\nfunc _() {\n\t// The copylocks analyzer (RunDespiteErrors, FactTypes={}) does run.\n\tvar mu sync.Mutex\n\tmu2 := mu // copylocks error, reported\n\t_ = &mu2\n\n\t// The printf analyzer (!RunDespiteErrors, FactTypes!={}) does not run:\n\t//  (c, printf) failed because of type error in c\n\t//  (b, printf) and (a, printf) do not run because of failed prerequisites.\n\tfmt.Printf(\"%d\", \"s\") // printf error, unreported\n\n\t// The bools analyzer (!RunDespiteErrors, FactTypes={}) does not run:\n\tvar cond bool\n\t_ = cond != true && cond != true // bools error, unreported\n}\n\n-- b/b.go --\npackage b\n\nimport _ \"example.com/c\"\n\n-- c/c.go --\npackage c\n\nvar _ = 1 / \"\" // type error\n\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tvar diags protocol.PublishDiagnosticsParams\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"mu2 := (mu)\"), WithMessage(\"assignment copies lock value\")),\n\t\t\tReadDiagnostics(\"a/a.go\", &diags))\n\n\t\t// Assert that there were no other diagnostics.\n\t\t// In particular:\n\t\t// - \"fmt.Printf\" does not trigger a [printf] finding;\n\t\t// - \"cond != true\" does not trigger a [bools] finding.\n\t\t//\n\t\t// We use this check in preference to NoDiagnosticAtRegexp\n\t\t// as it is robust in case of minor mistakes in the position\n\t\t// regexp, and because it reports unexpected diagnostics.\n\t\tif got, want := len(diags.Diagnostics), 1; got != want {\n\t\t\tt.Errorf(\"got %d diagnostics in a/a.go, want %d:\", got, want)\n\t\t\tfor i, diag := range diags.Diagnostics {\n\t\t\t\tt.Logf(\"Diagnostics[%d] = %+v\", i, diag)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// This test demonstrates the deprecated symbol analyzer\n// produces deprecation notices with expected severity and tags.\nfunc TestDeprecatedAnalysis(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\n-- a/a.go --\npackage a\n\nimport \"example.com/b\"\n\nfunc _() {\n\tnew(b.B).Obsolete() // deprecated\n}\n\n-- b/b.go --\npackage b\n\ntype B struct{}\n\n// Deprecated: use New instead.\nfunc (B) Obsolete() {}\n\nfunc (B) New() {}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a/a.go\", \"new.*Obsolete\"),\n\t\t\t\tWithMessage(\"use New instead.\"),\n\t\t\t\tWithSeverityTags(\"deprecated\", protocol.SeverityHint, []protocol.DiagnosticTag{protocol.Deprecated}),\n\t\t\t),\n\t\t)\n\t})\n}\n\nfunc TestDiagnosticsOnlyOnSaveFile(t *testing.T) {\n\t// This functionality is broken because the new orphaned file diagnostics\n\t// logic wants to publish diagnostics for changed files, independent of any\n\t// snapshot diagnostics pass, and this causes stale diagnostics to be\n\t// invalidated.\n\t//\n\t// We can fix this behavior more correctly by also honoring the\n\t// diagnosticsTrigger in DiagnoseOrphanedFiles, but that would require\n\t// resolving configuration that is independent of the snapshot. In other\n\t// words, we need to figure out which cache.Folder.Options applies to the\n\t// changed file, even if it does not have a snapshot.\n\tt.Skip(\"temporary skip for golang/go#57979: revisit after zero-config logic is in place\")\n\n\tconst onlyMod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n\tFoo()\n}\n-- foo.go --\npackage main\n\nfunc Foo() {}\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"diagnosticsTrigger\": \"Save\",\n\t\t},\n\t).Run(t, onlyMod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tenv.RegexpReplace(\"foo.go\", \"(Foo)\", \"Bar\") // Makes reference to Foo undefined/undeclared.\n\t\tenv.AfterChange(NoDiagnostics())            // No diagnostics update until file save.\n\n\t\tenv.SaveBuffer(\"foo.go\")\n\t\t// Compiler's error message about undeclared names vary depending on the version,\n\t\t// but must be explicit about the problematic name.\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", \"Foo\"), WithMessage(\"Foo\")))\n\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.RegexpReplace(\"main.go\", \"(Foo)\", \"Bar\")\n\t\t// No diagnostics update until file save. That results in outdated diagnostic.\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", \"Bar\"), WithMessage(\"Foo\")))\n\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/golist_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestGoListErrors(t *testing.T) {\n\ttestenv.NeedsTool(t, \"cgo\")\n\n\tconst src = `\n-- go.mod --\nmodule a.com\n\ngo 1.18\n-- a/a.go --\npackage a\n\nimport\n-- c/c.go --\npackage c\n\n/*\nint fortythree() { return 42; }\n*/\nimport \"C\"\n\nfunc Foo() {\n\tprint(C.fortytwo())\n}\n-- p/p.go --\npackage p\n\nimport \"a.com/q\"\n\nconst P = q.Q + 1\n-- q/q.go --\npackage q\n\nimport \"a.com/p\"\n\nconst Q = p.P + 1\n`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a/a.go\", \"import\\n()\"),\n\t\t\t\tFromSource(string(cache.ParseError)),\n\t\t\t),\n\t\t\tDiagnostics(\n\t\t\t\tAtPosition(\"c/c.go\", 0, 0),\n\t\t\t\tFromSource(string(cache.ListError)),\n\t\t\t\tWithMessage(\"may indicate failure to perform cgo processing\"),\n\t\t\t),\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"p/p.go\", `\"a.com/q\"`),\n\t\t\t\tFromSource(string(cache.ListError)),\n\t\t\t\tWithMessage(\"import cycle not allowed\"),\n\t\t\t),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/gopackagesdriver_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test that the import error does not mention GOPATH when building with\n// go/packages driver.\nfunc TestBrokenWorkspace_GOPACKAGESDRIVER(t *testing.T) {\n\t// A go.mod file is actually needed here, because the fake go/packages driver\n\t// uses go list behind the scenes, and we load go/packages driver workspaces\n\t// with ./...\n\tconst files = `\n-- go.mod --\nmodule m\ngo 1.12\n\n-- a.go --\npackage foo\n\nimport \"mod.com/hello\"\n`\n\tWithOptions(\n\t\tFakeGoPackagesDriver(t),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a.go\", `\"mod.com`),\n\t\t\t\tWithMessage(\"go/packages driver\"),\n\t\t\t),\n\t\t)\n\t\t// Deleting the import removes the error.\n\t\tenv.RegexpReplace(\"a.go\", `import \"mod.com/hello\"`, \"\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a.go\")),\n\t\t)\n\t})\n}\n\nfunc TestValidImportCheck_GoPackagesDriver(t *testing.T) {\n\tconst files = `\n-- go.work --\nuse .\n\n-- go.mod --\nmodule example.com\ngo 1.0\n\n-- a/a.go --\npackage a\nimport _ \"example.com/b/internal/c\"\n\n-- b/internal/c/c.go --\npackage c\n`\n\n\t// Note that 'go list' produces an error (\"use of internal package %q not allowed\")\n\t// and gopls produces another (\"invalid use of internal package %q\") with source=compiler.\n\t// Here we assert that the second one is not reported with a go/packages driver.\n\t// (We don't assert that the first is missing, because the test driver wraps go list!)\n\n\t// go list\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(Diagnostics(WithMessage(`invalid use of internal package \"example.com/b/internal/c\"`)))\n\t})\n\n\t// test driver\n\tWithOptions(\n\t\tFakeGoPackagesDriver(t),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(NoDiagnostics(WithMessage(`invalid use of internal package \"example.com/b/internal/c\"`)))\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/invalidation_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test for golang/go#50267: diagnostics should be re-sent after a file is\n// opened.\nfunc TestDiagnosticsAreResentAfterCloseOrOpen(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- main.go --\npackage main\n\nfunc _() {\n\tx := 2\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) { // Create a new workspace-level directory and empty file.\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar afterOpen protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"main.go\", &afterOpen),\n\t\t)\n\t\tenv.CloseBuffer(\"main.go\")\n\t\tvar afterClose protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"main.go\", &afterClose),\n\t\t)\n\t\tif afterOpen.Version == afterClose.Version {\n\t\t\tt.Errorf(\"publishDiagnostics: got the same version after closing (%d) as after opening\", afterOpen.Version)\n\t\t}\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar afterReopen protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"main.go\", &afterReopen),\n\t\t)\n\t\tif afterReopen.Version == afterClose.Version {\n\t\t\tt.Errorf(\"pubslishDiagnostics: got the same version after reopening (%d) as after closing\", afterClose.Version)\n\t\t}\n\t})\n}\n\n// Test for the \"chatty\" diagnostics: gopls should re-send diagnostics for\n// changed files after every file change, even if diagnostics did not change.\nfunc TestChattyDiagnostics(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- main.go --\npackage main\n\nfunc _() {\n\tx := 2\n}\n\n// Irrelevant comment #0\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) { // Create a new workspace-level directory and empty file.\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\n\t\tif len(d.Diagnostics) != 1 {\n\t\t\tt.Fatalf(\"len(Diagnostics) = %d, want 1\", len(d.Diagnostics))\n\t\t}\n\t\tmsg := d.Diagnostics[0].Message\n\n\t\tfor i := range 5 {\n\t\t\tbefore := d.Version\n\t\t\tenv.RegexpReplace(\"main.go\", \"Irrelevant comment #.\", fmt.Sprintf(\"Irrelevant comment #%d\", i))\n\t\t\tenv.AfterChange(\n\t\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t\t)\n\n\t\t\tif d.Version == before {\n\t\t\t\tt.Errorf(\"after change, got version %d, want new version\", d.Version)\n\t\t\t}\n\n\t\t\t// As a sanity check, make sure we have the same diagnostic.\n\t\t\tif len(d.Diagnostics) != 1 {\n\t\t\t\tt.Fatalf(\"len(Diagnostics) = %d, want 1\", len(d.Diagnostics))\n\t\t\t}\n\t\t\tnewMsg := d.Diagnostics[0].Message\n\t\t\tif newMsg != msg {\n\t\t\t\tt.Errorf(\"after change, got message %q, want %q\", newMsg, msg)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestCreatingPackageInvalidatesDiagnostics_Issue66384(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.15\n-- main.go --\npackage main\n\nimport \"example.com/pkg\"\n\nfunc main() {\n\tvar _ pkg.Thing\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"example.com/pkg\"`)),\n\t\t)\n\t\t// In order for this test to reproduce golang/go#66384, we have to create\n\t\t// the buffer, wait for loads, and *then* \"type out\" the contents. Doing so\n\t\t// reproduces the conditions of the bug report, that typing the package\n\t\t// name itself doesn't invalidate the broken import.\n\t\tenv.CreateBuffer(\"pkg/pkg.go\", \"\")\n\t\tenv.AfterChange()\n\t\tenv.EditBuffer(\"pkg/pkg.go\", protocol.TextEdit{NewText: \"package pkg\\ntype Thing struct{}\\n\"})\n\t\tenv.AfterChange()\n\t\tenv.SaveBuffer(\"pkg/pkg.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tenv.SetBufferContent(\"pkg/pkg.go\", \"package pkg\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", \"Thing\")))\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/diagnostics/undeclared_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diagnostics\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestUndeclaredDiagnostics(t *testing.T) {\n\tsrc := `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nfunc _() int {\n\treturn x\n}\n-- b/b.go --\npackage b\n\nfunc _() int {\n\tvar y int\n\ty = y\n\treturn y\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tisUnnecessary := func(diag protocol.Diagnostic) bool {\n\t\t\treturn slices.Contains(diag.Tags, protocol.Unnecessary)\n\t\t}\n\n\t\t// 'x' is undeclared, but still necessary.\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tvar adiags protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t\tReadDiagnostics(\"a/a.go\", &adiags),\n\t\t)\n\t\tif got := len(adiags.Diagnostics); got != 1 {\n\t\t\tt.Errorf(\"len(Diagnostics) = %d, want 1\", got)\n\t\t}\n\t\tif diag := adiags.Diagnostics[0]; isUnnecessary(diag) {\n\t\t\tt.Errorf(\"%v tagged unnecessary, want necessary\", diag)\n\t\t}\n\n\t\t// 'y = y' is pointless, and should be detected as unnecessary.\n\t\tenv.OpenFile(\"b/b.go\")\n\t\tvar bdiags protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"y = y\")),\n\t\t\tReadDiagnostics(\"b/b.go\", &bdiags),\n\t\t)\n\t\tif got := len(bdiags.Diagnostics); got != 1 {\n\t\t\tt.Errorf(\"len(Diagnostics) = %d, want 1\", got)\n\t\t}\n\t\tif diag := bdiags.Diagnostics[0]; !isUnnecessary(diag) {\n\t\t\tt.Errorf(\"%v tagged necessary, want unnecessary\", diag)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/doc.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package integration provides a framework for writing integration tests of gopls.\n//\n// The behaviors that matter to users, and the scenarios they\n// typically describe in bug report, are usually expressed in terms of\n// editor interactions. For example: \"When I open my editor in this\n// directory, navigate to this file, and change this line, I get a\n// diagnostic that doesn't make sense\". The integration package\n// provides an API for gopls maintainers to express these types of\n// user interactions in ordinary Go tests, validate them, and run them\n// in a variety of execution modes.\n//\n// # Test package setup\n//\n// The integration test package uses a couple of uncommon patterns to reduce\n// boilerplate in test bodies. First, it is intended to be imported as \".\" so\n// that helpers do not need to be qualified. Second, it requires some setup\n// that is currently implemented in the integration.Main function, which must be\n// invoked by TestMain. Therefore, a minimal integration testing package looks\n// like this:\n//\n//\tpackage feature\n//\n//\timport (\n//\t\t\"fmt\"\n//\t\t\"testing\"\n//\n//\t\t\"golang.org/x/tools/gopls/internal/hooks\"\n//\t\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n//\t)\n//\n//\tfunc TestMain(m *testing.M) {\n//\t\tos.Exit(Main(m, hooks.Options))\n//\t}\n//\n// # Writing a simple integration test\n//\n// To run an integration test use the integration.Run function, which accepts a\n// txtar-encoded archive defining the initial workspace state. This function\n// sets up the workspace in a temporary directory, creates a fake text editor,\n// starts gopls, and initializes an LSP session. It then invokes the provided\n// test function with an *Env encapsulating the newly created\n// environment. Because gopls may be run in various modes (as a sidecar or\n// daemon process, with different settings), the test runner may perform this\n// process multiple times, re-running the test function each time with a new\n// environment.\n//\n//\tfunc TestOpenFile(t *testing.T) {\n//\t\tconst files = `\n//\t-- go.mod --\n//\tmodule mod.com\n//\n//\tgo 1.12\n//\t-- foo.go --\n//\tpackage foo\n//\t`\n//\t\tRun(t, files, func(t *testing.T, env *Env) {\n//\t\t\tenv.OpenFile(\"foo.go\")\n//\t\t})\n//\t}\n//\n// # Configuring integration test execution\n//\n// The integration package exposes several options that affect the setup process\n// described above. To use these options, use the WithOptions function:\n//\n//\tWithOptions(opts...).Run(...)\n//\n// See options.go for a full list of available options.\n//\n// # Operating on editor state\n//\n// To operate on editor state within the test body, the Env type provides\n// access to the workspace directory (Env.SandBox), text editor (Env.Editor),\n// LSP server (Env.Server), and 'awaiter' (Env.Awaiter).\n//\n// In most cases, operations on these primitive building blocks of the\n// integration test environment expect a Context (which should be a child of\n// env.Ctx), and return an error. To avoid boilerplate, the Env exposes a set\n// of wrappers in wrappers.go for use in scripting:\n//\n//\tenv.CreateBuffer(\"c/c.go\", \"\")\n//\tenv.EditBuffer(\"c/c.go\", editor.Edit{\n//\t\tText: `package c`,\n//\t})\n//\n// These wrappers thread through Env.Ctx, and call t.Fatal on any errors.\n//\n// # Expressing expectations\n//\n// The general pattern for an integration test is to script interactions with the\n// fake editor and sandbox, and assert that gopls behaves correctly after each\n// state change. Unfortunately, this is complicated by the fact that state\n// changes are communicated to gopls via unidirectional client->server\n// notifications (didOpen, didChange, etc.), and resulting gopls behavior such\n// as diagnostics, logs, or messages is communicated back via server->client\n// notifications. Therefore, within integration tests we must be able to say \"do\n// this, and then eventually gopls should do that\". To achieve this, the\n// integration package provides a framework for expressing conditions that must\n// eventually be met, in terms of the Expectation type.\n//\n// To express the assertion that \"eventually gopls must meet these\n// expectations\", use env.Await(...):\n//\n//\tenv.RegexpReplace(\"x/x.go\", `package x`, `package main`)\n//\tenv.Await(env.DiagnosticAtRegexp(\"x/main.go\", `fmt`))\n//\n// Await evaluates the provided expectations atomically, whenever the client\n// receives a state-changing notification from gopls. See expectation.go for a\n// full list of available expectations.\n//\n// A problem with this model is that if gopls never meets the provided\n// expectations, the test runner will hang until the test timeout\n// (which defaults to 10m). There are two ways to work around this\n// poor behavior:\n//\n//  1. Use a precondition to define precisely when we expect conditions to be\n//     met. Gopls provides the OnceMet(precondition, expectations...) pattern\n//     to express (\"once this precondition is met, the following expectations\n//     must all hold\"). To instrument preconditions, gopls uses verbose\n//     progress notifications to inform the client about ongoing work (see\n//     CompletedWork). The most common precondition is to wait for gopls to be\n//     done processing all change notifications, for which the integration package\n//     provides the AfterChange helper. For example:\n//\n//     // We expect diagnostics to be cleared after gopls is done processing the\n//     // didSave notification.\n//     env.SaveBuffer(\"a/go.mod\")\n//     env.AfterChange(EmptyDiagnostics(\"a/go.mod\"))\n//\n//  2. Set a shorter timeout during development, if you expect to be breaking\n//     tests. By setting the environment variable GOPLS_INTEGRATION_TEST_TIMEOUT=5s,\n//     integration tests will time out after 5 seconds.\n//\n// # Tips & Tricks\n//\n// Here are some tips and tricks for working with integration tests:\n//\n//  1. Set the environment variable GOPLS_INTEGRRATION_TEST_TIMEOUT=5s during development.\n//  2. Run tests with  -short. This will only run integration tests in the\n//     default gopls execution mode.\n//  3. Use capture groups to narrow regexp positions. All regular-expression\n//     based positions (such as DiagnosticAtRegexp) will match the position of\n//     the first capture group, if any are provided. This can be used to\n//     identify a specific position in the code for a pattern that may occur in\n//     multiple places. For example `var (mu) sync.Mutex` matches the position\n//     of \"mu\" within the variable declaration.\n//  4. Read diagnostics into a variable to implement more complicated\n//     assertions about diagnostic state in the editor. To do this, use the\n//     pattern OnceMet(precondition, ReadDiagnostics(\"file.go\", &d)) to capture\n//     the current diagnostics as soon as the precondition is met. This is\n//     preferable to accessing the diagnostics directly, as it avoids races.\npackage integration\n"
  },
  {
    "path": "gopls/internal/test/integration/env.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n)\n\n// Env holds the building blocks of an editor testing environment, providing\n// wrapper methods that hide the boilerplate of plumbing contexts and checking\n// errors.\n// Call [Env.Shutdown] for cleaning up resources after the test.\ntype Env struct {\n\tTB  testing.TB\n\tCtx context.Context\n\n\t// Most tests should not need to access the scratch area, editor, server, or\n\t// connection, but they are available if needed.\n\tSandbox *fake.Sandbox\n\tServer  servertest.Connector\n\n\t// Editor is owned by the Env, and shut down\n\tEditor *fake.Editor\n\n\tAwaiter *Awaiter\n\n\t// MCPServer, MCPSession and EventChan is owned by the Env, and shut down.\n\t// Only available if the test enables MCP Server.\n\tMCPServer  *httptest.Server\n\tMCPSession *mcp.ClientSession\n}\n\n// nextAwaiterRegistration is used to create unique IDs for various Awaiter\n// registrations.\nvar nextAwaiterRegistration atomic.Uint64\n\n// An Awaiter keeps track of relevant LSP state, so that it may be asserted\n// upon with Expectations.\n//\n// Wire it into a fake.Editor using Awaiter.Hooks().\n//\n// TODO(rfindley): consider simply merging Awaiter with the fake.Editor. It\n// probably is not worth its own abstraction.\ntype Awaiter struct {\n\tworkdir *fake.Workdir\n\n\tmu sync.Mutex\n\t// For simplicity, each waiter gets a unique ID.\n\tstate   State\n\twaiters map[uint64]*condition\n\n\t// collectors map a registration to the collection of messages that have been\n\t// received since the registration was created.\n\tdocCollectors     map[uint64][]*protocol.ShowDocumentParams\n\tmessageCollectors map[uint64][]*protocol.ShowMessageParams\n}\n\nfunc NewAwaiter(workdir *fake.Workdir) *Awaiter {\n\treturn &Awaiter{\n\t\tworkdir: workdir,\n\t\tstate: State{\n\t\t\tdiagnostics:   make(map[string]*protocol.PublishDiagnosticsParams),\n\t\t\twork:          make(map[protocol.ProgressToken]*workProgress),\n\t\t\tstartedWork:   make(map[string]uint64),\n\t\t\tcompletedWork: make(map[string]uint64),\n\t\t},\n\t\twaiters: make(map[uint64]*condition),\n\t}\n}\n\n// Hooks returns LSP client hooks required for awaiting asynchronous expectations.\nfunc (a *Awaiter) Hooks() fake.ClientHooks {\n\treturn fake.ClientHooks{\n\t\tOnDiagnostics:            a.onDiagnostics,\n\t\tOnLogMessage:             a.onLogMessage,\n\t\tOnWorkDoneProgressCreate: a.onWorkDoneProgressCreate,\n\t\tOnProgress:               a.onProgress,\n\t\tOnShowDocument:           a.onShowDocument,\n\t\tOnShowMessage:            a.onShowMessage,\n\t\tOnShowMessageRequest:     a.onShowMessageRequest,\n\t\tOnRegisterCapability:     a.onRegisterCapability,\n\t\tOnUnregisterCapability:   a.onUnregisterCapability,\n\t}\n}\n\n// State encapsulates the server state TODO: explain more\ntype State struct {\n\t// diagnostics are a map of relative path->diagnostics params\n\tdiagnostics        map[string]*protocol.PublishDiagnosticsParams\n\tlogs               []*protocol.LogMessageParams\n\tshowDocument       []*protocol.ShowDocumentParams\n\tshowMessage        []*protocol.ShowMessageParams\n\tshowMessageRequest []*protocol.ShowMessageRequestParams\n\n\tregistrations          []*protocol.RegistrationParams\n\tregisteredCapabilities map[string]protocol.Registration\n\tunregistrations        []*protocol.UnregistrationParams\n\n\t// outstandingWork is a map of token->work summary. All tokens are assumed to\n\t// be string, though the spec allows for numeric tokens as well.\n\twork          map[protocol.ProgressToken]*workProgress\n\tstartedWork   map[string]uint64 // title -> count of 'begin'\n\tcompletedWork map[string]uint64 // title -> count of 'end'\n}\n\ntype workProgress struct {\n\ttitle, msg, endMsg string\n\tpercent            float64\n\tcomplete           bool // seen 'end'\n}\n\ntype awaitResult struct {\n\tverdict Verdict\n\treason  string\n}\n\n// A condition is satisfied when its expectation is [Met] or [Unmeetable]. The\n// result is sent on the verdict channel.\ntype condition struct {\n\texpectation Expectation\n\tverdict     chan awaitResult\n}\n\nfunc (a *Awaiter) onDiagnostics(_ context.Context, d *protocol.PublishDiagnosticsParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\tpth := a.workdir.URIToPath(d.URI)\n\ta.state.diagnostics[pth] = d\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) onShowDocument(_ context.Context, params *protocol.ShowDocumentParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\t// Update any outstanding listeners.\n\tfor id, s := range a.docCollectors {\n\t\ta.docCollectors[id] = append(s, params)\n\t}\n\n\ta.state.showDocument = append(a.state.showDocument, params)\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\n// ListenToShownDocuments registers a listener to incoming showDocument\n// notifications. Call the resulting func to deregister the listener and\n// receive all notifications that have occurred since the listener was\n// registered.\nfunc (a *Awaiter) ListenToShownDocuments() func() []*protocol.ShowDocumentParams {\n\tid := nextAwaiterRegistration.Add(1)\n\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\tif a.docCollectors == nil {\n\t\ta.docCollectors = make(map[uint64][]*protocol.ShowDocumentParams)\n\t}\n\ta.docCollectors[id] = nil\n\n\treturn func() []*protocol.ShowDocumentParams {\n\t\ta.mu.Lock()\n\t\tdefer a.mu.Unlock()\n\t\tparams := a.docCollectors[id]\n\t\tdelete(a.docCollectors, id)\n\t\treturn params\n\t}\n}\n\nfunc (a *Awaiter) onShowMessage(_ context.Context, params *protocol.ShowMessageParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\t// Update any outstanding listeners.\n\tfor id, s := range a.messageCollectors {\n\t\ta.messageCollectors[id] = append(s, params)\n\t}\n\n\ta.state.showMessage = append(a.state.showMessage, params)\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\n// ListenToShownMessages registers a listener to incoming showMessage\n// notifications. Call the resulting func to deregister the listener and\n// receive all notifications that have occurred since the listener was\n// registered.\n//\n// ListenToShownMessages should be called before the operation that\n// generates the showMessage event to ensure that the event is\n// reliably collected.\nfunc (a *Awaiter) ListenToShownMessages() func() []*protocol.ShowMessageParams {\n\tid := nextAwaiterRegistration.Add(1)\n\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\tif a.messageCollectors == nil {\n\t\ta.messageCollectors = make(map[uint64][]*protocol.ShowMessageParams)\n\t}\n\ta.messageCollectors[id] = nil\n\n\treturn func() []*protocol.ShowMessageParams {\n\t\ta.mu.Lock()\n\t\tdefer a.mu.Unlock()\n\t\tparams := a.messageCollectors[id]\n\t\tdelete(a.messageCollectors, id)\n\t\treturn params\n\t}\n}\n\nfunc (a *Awaiter) onShowMessageRequest(_ context.Context, m *protocol.ShowMessageRequestParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\ta.state.showMessageRequest = append(a.state.showMessageRequest, m)\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) onLogMessage(_ context.Context, m *protocol.LogMessageParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\ta.state.logs = append(a.state.logs, m)\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) onWorkDoneProgressCreate(_ context.Context, m *protocol.WorkDoneProgressCreateParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\ta.state.work[m.Token] = &workProgress{}\n\treturn nil\n}\n\nfunc (a *Awaiter) onProgress(_ context.Context, m *protocol.ProgressParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\twork, ok := a.state.work[m.Token]\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"got progress report for unknown report %v: %v\", m.Token, m))\n\t}\n\tv := m.Value.(map[string]any)\n\tswitch kind := v[\"kind\"]; kind {\n\tcase \"begin\":\n\t\twork.title = v[\"title\"].(string)\n\t\ta.state.startedWork[work.title]++\n\t\tif msg, ok := v[\"message\"]; ok {\n\t\t\twork.msg = msg.(string)\n\t\t}\n\tcase \"report\":\n\t\tif pct, ok := v[\"percentage\"]; ok {\n\t\t\twork.percent = pct.(float64)\n\t\t}\n\t\tif msg, ok := v[\"message\"]; ok {\n\t\t\twork.msg = msg.(string)\n\t\t}\n\tcase \"end\":\n\t\twork.complete = true\n\t\ta.state.completedWork[work.title]++\n\t\tif msg, ok := v[\"message\"]; ok {\n\t\t\twork.endMsg = msg.(string)\n\t\t}\n\t}\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) onRegisterCapability(_ context.Context, m *protocol.RegistrationParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\ta.state.registrations = append(a.state.registrations, m)\n\tif a.state.registeredCapabilities == nil {\n\t\ta.state.registeredCapabilities = make(map[string]protocol.Registration)\n\t}\n\tfor _, reg := range m.Registrations {\n\t\ta.state.registeredCapabilities[reg.Method] = reg\n\t}\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) onUnregisterCapability(_ context.Context, m *protocol.UnregistrationParams) error {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\ta.state.unregistrations = append(a.state.unregistrations, m)\n\ta.checkConditionsLocked()\n\treturn nil\n}\n\nfunc (a *Awaiter) checkConditionsLocked() {\n\tfor id, condition := range a.waiters {\n\t\tif v, why := condition.expectation.Check(a.state); v != Unmet {\n\t\t\tdelete(a.waiters, id)\n\t\t\tcondition.verdict <- awaitResult{v, why}\n\t\t}\n\t}\n}\n\n// Await blocks until the given expectations are all simultaneously met.\n//\n// Generally speaking Await should be avoided because it blocks indefinitely if\n// gopls ends up in a state where the expectations are never going to be met.\n// Use AfterChange or OnceMet instead, so that the runner knows when to stop\n// waiting.\nfunc (e *Env) Await(expectations ...Expectation) {\n\te.TB.Helper()\n\tif err := e.Awaiter.Await(e.Ctx, AllOf(expectations...)); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// OnceMet blocks until the precondition is met by the state or becomes\n// unmeetable. If it was met, OnceMet checks that the state meets all\n// expectations in mustMeets.\nfunc (e *Env) OnceMet(pre Expectation, mustMeets ...Expectation) {\n\te.TB.Helper()\n\te.Await(OnceMet(pre, AllOf(mustMeets...)))\n}\n\n// Await waits for all expectations to simultaneously be met. It should only be\n// called from the main test goroutine.\nfunc (a *Awaiter) Await(ctx context.Context, expectation Expectation) error {\n\ta.mu.Lock()\n\t// Before adding the waiter, we check if the condition is currently met or\n\t// failed to avoid a race where the condition was realized before Await was\n\t// called.\n\tswitch verdict, why := expectation.Check(a.state); verdict {\n\tcase Met:\n\t\ta.mu.Unlock()\n\t\treturn nil\n\tcase Unmeetable:\n\t\terr := fmt.Errorf(\"unmeetable expectation:\\n%s\\nreason:\\n%s\", indent(expectation.Description), indent(why))\n\t\ta.mu.Unlock()\n\t\treturn err\n\t}\n\tcond := &condition{\n\t\texpectation: expectation,\n\t\tverdict:     make(chan awaitResult),\n\t}\n\ta.waiters[nextAwaiterRegistration.Add(1)] = cond\n\ta.mu.Unlock()\n\n\tvar err error\n\tselect {\n\tcase <-ctx.Done():\n\t\terr = ctx.Err()\n\tcase res := <-cond.verdict:\n\t\tif res.verdict != Met {\n\t\t\terr = fmt.Errorf(\"the following condition is %s:\\n%s\\nreason:\\n%s\",\n\t\t\t\tres.verdict, indent(expectation.Description), indent(res.reason))\n\t\t}\n\t}\n\treturn err\n}\n\n// indent indents all lines of msg, including the first.\nfunc indent(msg string) string {\n\tconst prefix = \"  \"\n\treturn prefix + strings.ReplaceAll(msg, \"\\n\", \"\\n\"+prefix)\n}\n\n// CleanModCache cleans the specified GOMODCACHE.\n//\n// TODO(golang/go#74595): this is only necessary as the module cache cleaning of the\n// sandbox does not respect GOMODCACHE set via EnvVars. We should fix this, but\n// that is probably part of a larger refactoring of the sandbox that I'm not\n// inclined to undertake. --rfindley.\n//\n// (For similar problems caused by the same bug, see Test_issue38211; see also\n// comment in Sandbox.Env.)\nfunc CleanModCache(t *testing.T, modcache string) {\n\tcmd := exec.Command(\"go\", \"clean\", \"-modcache\")\n\tcmd.Env = append(os.Environ(), \"GOMODCACHE=\"+modcache, \"GOTOOLCHAIN=local\")\n\tif output, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Errorf(\"cleaning modcache: %v\\noutput:\\n%s\", err, string(output))\n\t}\n}\n\n// CodeActionByKind returns the first action of (exactly) the specified kind, or an error.\nfunc CodeActionByKind(actions []protocol.CodeAction, kind protocol.CodeActionKind) (*protocol.CodeAction, error) {\n\tfor _, act := range actions {\n\t\tif act.Kind == kind {\n\t\t\treturn &act, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"can't find action with kind %s, only %#v\", kind, actions)\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/env_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestProgressUpdating(t *testing.T) {\n\ta := &Awaiter{\n\t\tstate: State{\n\t\t\twork:          make(map[protocol.ProgressToken]*workProgress),\n\t\t\tstartedWork:   make(map[string]uint64),\n\t\t\tcompletedWork: make(map[string]uint64),\n\t\t},\n\t}\n\tctx := context.Background()\n\tif err := a.onWorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{\n\t\tToken: \"foo\",\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := a.onWorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{\n\t\tToken: \"bar\",\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tupdates := []struct {\n\t\ttoken string\n\t\tvalue any\n\t}{\n\t\t{\"foo\", protocol.WorkDoneProgressBegin{Kind: \"begin\", Title: \"foo work\"}},\n\t\t{\"bar\", protocol.WorkDoneProgressBegin{Kind: \"begin\", Title: \"bar work\"}},\n\t\t{\"foo\", protocol.WorkDoneProgressEnd{Kind: \"end\"}},\n\t\t{\"bar\", protocol.WorkDoneProgressReport{Kind: \"report\", Percentage: varOf[uint32](42)}},\n\t}\n\tfor _, update := range updates {\n\t\tparams := &protocol.ProgressParams{\n\t\t\tToken: update.token,\n\t\t\tValue: update.value,\n\t\t}\n\t\tdata, err := json.Marshal(params)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tvar unmarshaled protocol.ProgressParams\n\t\tif err := json.Unmarshal(data, &unmarshaled); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := a.onProgress(ctx, &unmarshaled); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tif got, want := a.state.completedWork[\"foo work\"], uint64(1); got != want {\n\t\tt.Errorf(`completedWork[\"foo work\"] = %d, want %d`, got, want)\n\t}\n\tgot := *a.state.work[\"bar\"]\n\twant := workProgress{title: \"bar work\", percent: 42}\n\tif got != want {\n\t\tt.Errorf(\"work progress for \\\"bar\\\": %v, want %v\", got, want)\n\t}\n}\n\n// varOf returns a new variable whose value is x.\nfunc varOf[T any](x T) *T { return &x }\n"
  },
  {
    "path": "gopls/internal/test/integration/expectation.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"maps\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/util/constraints\"\n)\n\nvar (\n\t// InitialWorkspaceLoad is an expectation that the workspace initial load has\n\t// completed. It is verified via workdone reporting.\n\tInitialWorkspaceLoad = CompletedWork(server.DiagnosticWorkTitle(server.FromInitialWorkspaceLoad), 1, false)\n)\n\n// A Verdict is the result of checking an expectation against the current\n// editor state.\ntype Verdict int\n\n// Order matters for the following constants: verdicts are sorted in order of\n// decisiveness.\nconst (\n\t// Met indicates that an expectation is satisfied by the current state.\n\tMet Verdict = iota\n\t// Unmet indicates that an expectation is not currently met, but could be met\n\t// in the future.\n\tUnmet\n\t// Unmeetable indicates that an expectation cannot be satisfied in the\n\t// future.\n\tUnmeetable\n)\n\nfunc (v Verdict) String() string {\n\tswitch v {\n\tcase Met:\n\t\treturn \"Met\"\n\tcase Unmet:\n\t\treturn \"Unmet\"\n\tcase Unmeetable:\n\t\treturn \"Unmeetable\"\n\t}\n\treturn fmt.Sprintf(\"unrecognized verdict %d\", v)\n}\n\n// An Expectation is an expected property of the state of the LSP client.\n// The Check function reports whether the property is met.\n//\n// Expectations are combinators. By composing them, tests may express\n// complex expectations in terms of simpler ones.\ntype Expectation struct {\n\t// Check returns the verdict of this expectation for the given state.\n\t// If the vertict is not [Met], the second result should return a reason\n\t// that the verdict is not (yet) met.\n\tCheck func(State) (Verdict, string)\n\n\t// Description holds a noun-phrase identifying what the expectation checks.\n\t//\n\t// TODO(rfindley): revisit existing descriptions to ensure they compose nicely.\n\tDescription string\n}\n\n// OnceMet returns an Expectation that, once the precondition is met, asserts\n// that mustMeet is met.\nfunc OnceMet(pre, post Expectation) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tswitch v, why := pre.Check(s); v {\n\t\tcase Unmeetable, Unmet:\n\t\t\treturn v, fmt.Sprintf(\"precondition is %s: %s\", v, why)\n\t\tcase Met:\n\t\t\tv, why := post.Check(s)\n\t\t\tif v != Met {\n\t\t\t\treturn Unmeetable, fmt.Sprintf(\"postcondition is not met:\\n%s\", indent(why))\n\t\t\t}\n\t\t\treturn Met, \"\"\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unknown precondition verdict %s\", v))\n\t\t}\n\t}\n\tdesc := fmt.Sprintf(\"once the following is met:\\n%s\\nmust have:\\n%s\",\n\t\tindent(pre.Description), indent(post.Description))\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// Not inverts the sense of an expectation: a met expectation is unmet, and an\n// unmet expectation is met.\nfunc Not(e Expectation) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tswitch v, _ := e.Check(s); v {\n\t\tcase Met:\n\t\t\treturn Unmet, \"condition unexpectedly satisfied\"\n\t\tcase Unmet, Unmeetable:\n\t\t\treturn Met, \"\"\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected verdict %v\", v))\n\t\t}\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"not: %s\", e.Description),\n\t}\n}\n\n// AnyOf returns an expectation that is satisfied when any of the given\n// expectations is met.\nfunc AnyOf(anyOf ...Expectation) Expectation {\n\tif len(anyOf) == 1 {\n\t\treturn anyOf[0] // avoid unnecessary boilerplate\n\t}\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, e := range anyOf {\n\t\t\tverdict, _ := e.Check(s)\n\t\t\tif verdict == Met {\n\t\t\t\treturn Met, \"\"\n\t\t\t}\n\t\t}\n\t\treturn Unmet, \"none of the expectations were met\"\n\t}\n\tdescription := describeExpectations(anyOf...)\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"any of:\\n%s\", description),\n\t}\n}\n\n// AllOf expects that all given expectations are met.\nfunc AllOf(allOf ...Expectation) Expectation {\n\tif len(allOf) == 1 {\n\t\treturn allOf[0] // avoid unnecessary boilerplate\n\t}\n\tcheck := func(s State) (Verdict, string) {\n\t\tvar (\n\t\t\tverdict = Met\n\t\t\treason  string\n\t\t)\n\t\tfor _, e := range allOf {\n\t\t\tv, why := e.Check(s)\n\t\t\tif v > verdict {\n\t\t\t\tverdict = v\n\t\t\t\treason = why\n\t\t\t}\n\t\t}\n\t\treturn verdict, reason\n\t}\n\tdesc := describeExpectations(allOf...)\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"all of:\\n%s\", indent(desc)),\n\t}\n}\n\nfunc describeExpectations(expectations ...Expectation) string {\n\tvar descriptions []string\n\tfor _, e := range expectations {\n\t\tdescriptions = append(descriptions, e.Description)\n\t}\n\treturn strings.Join(descriptions, \"\\n\")\n}\n\n// ReadDiagnostics is an Expectation that stores the current diagnostics for\n// fileName in into, whenever it is evaluated.\n//\n// It can be used in combination with OnceMet or AfterChange to capture the\n// state of diagnostics when other expectations are satisfied.\nfunc ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tdiags, ok := s.diagnostics[fileName]\n\t\tif !ok {\n\t\t\treturn Unmeetable, fmt.Sprintf(\"no diagnostics for %q\", fileName)\n\t\t}\n\t\t*into = *diags\n\t\treturn Met, \"\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"read diagnostics for %q\", fileName),\n\t}\n}\n\n// ReadAllDiagnostics is an expectation that stores all published diagnostics\n// into the provided map, whenever it is evaluated.\n//\n// It can be used in combination with OnceMet or AfterChange to capture the\n// state of diagnostics when other expectations are satisfied.\nfunc ReadAllDiagnostics(into *map[string]*protocol.PublishDiagnosticsParams) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tallDiags := maps.Clone(s.diagnostics)\n\t\t*into = allDiags\n\t\treturn Met, \"\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: \"read all diagnostics\",\n\t}\n}\n\n// ShownDocument asserts that the client has received a\n// ShowDocumentRequest for the given URI.\nfunc ShownDocument(uri protocol.URI) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, params := range s.showDocument {\n\t\t\tif params.URI == uri {\n\t\t\t\treturn Met, \"\"\n\t\t\t}\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"no ShowDocumentRequest received for %s\", uri)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"received window/showDocument for URI %s\", uri),\n\t}\n}\n\n// ShownDocuments is an expectation that appends each showDocument\n// request into the provided slice, whenever it is evaluated.\n//\n// It can be used in combination with OnceMet or AfterChange to\n// capture the set of showDocument requests when other expectations\n// are satisfied.\nfunc ShownDocuments(into *[]*protocol.ShowDocumentParams) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\t*into = append(*into, s.showDocument...)\n\t\treturn Met, \"\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: \"read shown documents\",\n\t}\n}\n\n// NoShownMessage asserts that the editor has not received a ShowMessage.\nfunc NoShownMessage(containing string) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, m := range s.showMessage {\n\t\t\tif strings.Contains(m.Message, containing) {\n\t\t\t\t// Format the message (which may contain newlines) as a block quote.\n\t\t\t\tmsg := fmt.Sprintf(\"\\\"\\\"\\\"\\n%s\\n\\\"\\\"\\\"\", strings.TrimSpace(m.Message))\n\t\t\t\treturn Unmeetable, fmt.Sprintf(\"observed the following message:\\n%s\", indent(msg))\n\t\t\t}\n\t\t}\n\t\treturn Met, \"\"\n\t}\n\tvar desc string\n\tif containing != \"\" {\n\t\tdesc = fmt.Sprintf(\"received no ShowMessage containing %q\", containing)\n\t} else {\n\t\tdesc = \"received no ShowMessage requests\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// ShownMessage asserts that the editor has received a ShowMessageRequest\n// containing the given substring.\nfunc ShownMessage(containing string) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, m := range s.showMessage {\n\t\t\tif strings.Contains(m.Message, containing) {\n\t\t\t\treturn Met, \"\"\n\t\t\t}\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"no ShowMessage containing %q\", containing)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"received window/showMessage containing %q\", containing),\n\t}\n}\n\n// ShownMessageRequest asserts that the editor has received a\n// ShowMessageRequest with message matching the given regular expression.\nfunc ShownMessageRequest(matchingRegexp string) Expectation {\n\tmsgRE := regexp.MustCompile(matchingRegexp)\n\tcheck := func(s State) (Verdict, string) {\n\t\tif len(s.showMessageRequest) == 0 {\n\t\t\treturn Unmet, \"no ShowMessageRequest have been received\"\n\t\t}\n\t\tfor _, m := range s.showMessageRequest {\n\t\t\tif msgRE.MatchString(m.Message) {\n\t\t\t\treturn Met, \"\"\n\t\t\t}\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"no ShowMessageRequest (out of %d) match %q\", len(s.showMessageRequest), matchingRegexp)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"ShowMessageRequest matching %q\", matchingRegexp),\n\t}\n}\n\n// DoneDiagnosingChanges expects that diagnostics are complete from common\n// change notifications: didOpen, didChange, didSave, didChangeWatchedFiles,\n// and didClose.\n//\n// This can be used when multiple notifications may have been sent, such as\n// when a didChange is immediately followed by a didSave. It is insufficient to\n// simply await NoOutstandingWork, because the LSP client has no control over\n// when the server starts processing a notification. Therefore, we must keep\n// track of\nfunc (e *Env) DoneDiagnosingChanges() Expectation {\n\tstats := e.Editor.Stats()\n\tstatsBySource := map[server.ModificationSource]uint64{\n\t\tserver.FromDidOpen:                stats.DidOpen,\n\t\tserver.FromDidChange:              stats.DidChange,\n\t\tserver.FromDidSave:                stats.DidSave,\n\t\tserver.FromDidChangeWatchedFiles:  stats.DidChangeWatchedFiles,\n\t\tserver.FromDidClose:               stats.DidClose,\n\t\tserver.FromDidChangeConfiguration: stats.DidChangeConfiguration,\n\t}\n\n\tvar expected []server.ModificationSource\n\tfor k, v := range statsBySource {\n\t\tif v > 0 {\n\t\t\texpected = append(expected, k)\n\t\t}\n\t}\n\n\t// Sort for stability.\n\tslices.Sort(expected)\n\n\tvar all []Expectation\n\tfor _, source := range expected {\n\t\tall = append(all, CompletedWork(server.DiagnosticWorkTitle(source), statsBySource[source], true))\n\t}\n\n\treturn AllOf(all...)\n}\n\n// AfterChange expects that the given expectations will be met after all\n// state-changing notifications have been processed by the server.\n// Specifically, it awaits the awaits completion of the process of diagnosis\n// after the following notifications, before checking the given expectations:\n//   - textDocument/didOpen\n//   - textDocument/didChange\n//   - textDocument/didSave\n//   - textDocument/didClose\n//   - workspace/didChangeWatchedFiles\n//   - workspace/didChangeConfiguration\nfunc (e *Env) AfterChange(expectations ...Expectation) {\n\te.TB.Helper()\n\te.OnceMet(\n\t\te.DoneDiagnosingChanges(),\n\t\texpectations...,\n\t)\n}\n\n// DoneWithOpen expects all didOpen notifications currently sent by the editor\n// to be completely processed.\nfunc (e *Env) DoneWithOpen() Expectation {\n\topens := e.Editor.Stats().DidOpen\n\treturn CompletedWork(server.DiagnosticWorkTitle(server.FromDidOpen), opens, true)\n}\n\n// StartedChange expects that the server has at least started processing all\n// didChange notifications sent from the client.\nfunc (e *Env) StartedChange() Expectation {\n\tchanges := e.Editor.Stats().DidChange\n\treturn StartedWork(server.DiagnosticWorkTitle(server.FromDidChange), changes)\n}\n\n// DoneWithChange expects all didChange notifications currently sent by the\n// editor to be completely processed.\nfunc (e *Env) DoneWithChange() Expectation {\n\tchanges := e.Editor.Stats().DidChange\n\treturn CompletedWork(server.DiagnosticWorkTitle(server.FromDidChange), changes, true)\n}\n\n// DoneWithSave expects all didSave notifications currently sent by the editor\n// to be completely processed.\nfunc (e *Env) DoneWithSave() Expectation {\n\tsaves := e.Editor.Stats().DidSave\n\treturn CompletedWork(server.DiagnosticWorkTitle(server.FromDidSave), saves, true)\n}\n\n// StartedChangeWatchedFiles expects that the server has at least started\n// processing all didChangeWatchedFiles notifications sent from the client.\nfunc (e *Env) StartedChangeWatchedFiles() Expectation {\n\tchanges := e.Editor.Stats().DidChangeWatchedFiles\n\treturn StartedWork(server.DiagnosticWorkTitle(server.FromDidChangeWatchedFiles), changes)\n}\n\n// DoneWithChangeWatchedFiles expects all didChangeWatchedFiles notifications\n// currently sent by the editor to be completely processed.\nfunc (e *Env) DoneWithChangeWatchedFiles() Expectation {\n\tchanges := e.Editor.Stats().DidChangeWatchedFiles\n\treturn CompletedWork(server.DiagnosticWorkTitle(server.FromDidChangeWatchedFiles), changes, true)\n}\n\n// DoneWithClose expects all didClose notifications currently sent by the\n// editor to be completely processed.\nfunc (e *Env) DoneWithClose() Expectation {\n\tchanges := e.Editor.Stats().DidClose\n\treturn CompletedWork(server.DiagnosticWorkTitle(server.FromDidClose), changes, true)\n}\n\n// StartedWork expect a work item to have been started >= atLeast times.\n//\n// See CompletedWork.\nfunc StartedWork(title string, atLeast uint64) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tstarted := s.startedWork[title]\n\t\tif started >= atLeast {\n\t\t\treturn Met, \"\"\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"started work %d %s\", started, pluralize(\"time\", started))\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"started work %q at least %d %s\", title, atLeast, pluralize(\"time\", atLeast)),\n\t}\n}\n\n// CompletedWork expects a work item to have been completed >= atLeast times.\n//\n// Since the Progress API doesn't include any hidden metadata, we must use the\n// progress notification title to identify the work we expect to be completed.\nfunc CompletedWork(title string, count uint64, atLeast bool) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tcompleted := s.completedWork[title]\n\t\tif completed == count || atLeast && completed > count {\n\t\t\treturn Met, \"\"\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"completed %d %s\", completed, pluralize(\"time\", completed))\n\t}\n\tdesc := fmt.Sprintf(\"completed work %q %v %s\", title, count, pluralize(\"time\", count))\n\tif atLeast {\n\t\tdesc = fmt.Sprintf(\"completed work %q at least %d %s\", title, count, pluralize(\"time\", count))\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// pluralize adds an 's' suffix to name if n > 1.\nfunc pluralize[T constraints.Integer](name string, n T) string {\n\tif n > 1 {\n\t\treturn name + \"s\"\n\t}\n\treturn name\n}\n\ntype WorkStatus struct {\n\t// Last seen message from either `begin` or `report` progress.\n\tMsg string\n\t// Message sent with `end` progress message.\n\tEndMsg string\n}\n\n// CompletedProgressToken expects that workDone progress is complete for the given\n// progress token. When non-nil WorkStatus is provided, it will be filled\n// when the expectation is met.\n//\n// If the token is not a progress token that the client has seen, this\n// expectation is Unmeetable.\nfunc CompletedProgressToken(token protocol.ProgressToken, into *WorkStatus) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\twork, ok := s.work[token]\n\t\tif !ok {\n\t\t\treturn Unmeetable, \"no matching work items\"\n\t\t}\n\t\tif work.complete {\n\t\t\tif into != nil {\n\t\t\t\tinto.Msg = work.msg\n\t\t\t\tinto.EndMsg = work.endMsg\n\t\t\t}\n\t\t\treturn Met, \"\"\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"work is not complete; last message: %q\", work.msg)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"completed work for token %v\", token),\n\t}\n}\n\n// CompletedProgress expects that there is exactly one workDone progress with\n// the given title, and is satisfied when that progress completes. If it is\n// met, the corresponding status is written to the into argument.\n//\n// TODO(rfindley): refactor to eliminate the redundancy with CompletedWork.\n// This expectation is a vestige of older workarounds for asynchronous command\n// execution.\nfunc CompletedProgress(title string, into *WorkStatus) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tvar work *workProgress\n\t\tfor _, w := range s.work {\n\t\t\tif w.title == title {\n\t\t\t\tif work != nil {\n\t\t\t\t\treturn Unmeetable, \"multiple matching work items\"\n\t\t\t\t}\n\t\t\t\twork = w\n\t\t\t}\n\t\t}\n\t\tif work == nil {\n\t\t\treturn Unmeetable, \"no matching work items\"\n\t\t}\n\t\tif work.complete {\n\t\t\tif into != nil {\n\t\t\t\tinto.Msg = work.msg\n\t\t\t\tinto.EndMsg = work.endMsg\n\t\t\t}\n\t\t\treturn Met, \"\"\n\t\t}\n\t\treturn Unmet, fmt.Sprintf(\"work is not complete; last message: %q\", work.msg)\n\t}\n\tdesc := fmt.Sprintf(\"exactly 1 completed workDoneProgress with title %v\", title)\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// OutstandingWork expects a work item to be outstanding. The given title must\n// be an exact match, whereas the given msg must only be contained in the work\n// item's message.\nfunc OutstandingWork(title, msg string) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, work := range s.work {\n\t\t\tif work.complete {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif work.title == title && strings.Contains(work.msg, msg) {\n\t\t\t\treturn Met, \"\"\n\t\t\t}\n\t\t}\n\t\treturn Unmet, \"no matching work\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: fmt.Sprintf(\"outstanding work: %q containing %q\", title, msg),\n\t}\n}\n\n// NoOutstandingWork asserts that there is no work initiated using the LSP\n// $/progress API that has not completed.\n//\n// If non-nil, the ignore func is used to ignore certain work items for the\n// purpose of this check.\n//\n// TODO(rfindley): consider refactoring to treat outstanding work the same way\n// we treat diagnostics: with an algebra of filters.\nfunc NoOutstandingWork(ignore func(title, msg string) bool) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tfor _, w := range s.work {\n\t\t\tif w.complete {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif w.title == \"\" {\n\t\t\t\t// A token that has been created but not yet used.\n\t\t\t\t//\n\t\t\t\t// TODO(rfindley): this should be separated in the data model: until\n\t\t\t\t// the \"begin\" notification, work should not be in progress.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif ignore != nil && ignore(w.title, w.msg) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn Unmet, fmt.Sprintf(\"found outstanding work %q: %q\", w.title, w.msg)\n\t\t}\n\t\treturn Met, \"\"\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: \"no outstanding work\",\n\t}\n}\n\n// IgnoreTelemetryPromptWork may be used in conjunction with NoOutStandingWork\n// to ignore the telemetry prompt.\nfunc IgnoreTelemetryPromptWork(title, msg string) bool {\n\treturn title == server.TelemetryPromptWorkTitle\n}\n\n// NoErrorLogs asserts that the client has not received any log messages of\n// error severity.\nfunc NoErrorLogs() Expectation {\n\treturn NoLogMatching(protocol.Error, \"\")\n}\n\n// LogMatching asserts that the client has received a log message\n// of type typ matching the regexp re a certain number of times.\n//\n// The count argument specifies the expected number of matching logs. If\n// atLeast is set, this is a lower bound, otherwise there must be exactly count\n// matching logs.\n//\n// Logs are asynchronous to other LSP messages, so this expectation should not\n// be used with combinators such as OnceMet or AfterChange that assert on\n// ordering with respect to other operations.\nfunc LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) Expectation {\n\trec, err := regexp.Compile(re)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tcheck := func(state State) (Verdict, string) {\n\t\tvar found int\n\t\tfor _, msg := range state.logs {\n\t\t\tif msg.Type == typ && rec.Match([]byte(msg.Message)) {\n\t\t\t\tfound++\n\t\t\t}\n\t\t}\n\t\t// Check for an exact or \"at least\" match.\n\t\tif found == count || (found >= count && atLeast) {\n\t\t\treturn Met, \"\"\n\t\t}\n\t\t// If we require an exact count, and have received more than expected, the\n\t\t// expectation can never be met.\n\t\tverdict := Unmet\n\t\tif found > count && !atLeast {\n\t\t\tverdict = Unmeetable\n\t\t}\n\t\treturn verdict, fmt.Sprintf(\"found %d matching logs\", found)\n\t}\n\tdesc := fmt.Sprintf(\"log message matching %q expected %v times\", re, count)\n\tif atLeast {\n\t\tdesc = fmt.Sprintf(\"log message matching %q expected at least %v times\", re, count)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// NoLogMatching asserts that the client has not received a log message\n// of type typ matching the regexp re. If re is an empty string, any log\n// message is considered a match.\nfunc NoLogMatching(typ protocol.MessageType, re string) Expectation {\n\tvar r *regexp.Regexp\n\tif re != \"\" {\n\t\tvar err error\n\t\tr, err = regexp.Compile(re)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\tcheck := func(state State) (Verdict, string) {\n\t\tfor _, msg := range state.logs {\n\t\t\tif msg.Type != typ {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif r == nil || r.Match([]byte(msg.Message)) {\n\t\t\t\treturn Unmeetable, fmt.Sprintf(\"found matching log %q\", msg.Message)\n\t\t\t}\n\t\t}\n\t\treturn Met, \"\"\n\t}\n\tdesc := fmt.Sprintf(\"no %s log messages\", typ)\n\tif re != \"\" {\n\t\tdesc += fmt.Sprintf(\" matching %q\", re)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: desc,\n\t}\n}\n\n// FileWatchMatching expects that a file registration matches re.\nfunc FileWatchMatching(re string) Expectation {\n\treturn Expectation{\n\t\tCheck:       checkFileWatch(re, Met, Unmet),\n\t\tDescription: fmt.Sprintf(\"file watch matching %q\", re),\n\t}\n}\n\n// NoFileWatchMatching expects that no file registration matches re.\nfunc NoFileWatchMatching(re string) Expectation {\n\treturn Expectation{\n\t\tCheck:       checkFileWatch(re, Unmet, Met),\n\t\tDescription: fmt.Sprintf(\"no file watch matching %q\", re),\n\t}\n}\n\nfunc checkFileWatch(re string, onMatch, onNoMatch Verdict) func(State) (Verdict, string) {\n\trec := regexp.MustCompile(re)\n\treturn func(s State) (Verdict, string) {\n\t\tr := s.registeredCapabilities[\"workspace/didChangeWatchedFiles\"]\n\t\twatchers := jsonProperty(r.RegisterOptions, \"watchers\").([]any)\n\t\tfor _, watcher := range watchers {\n\t\t\tpattern := jsonProperty(watcher, \"globPattern\").(string)\n\t\t\tif rec.MatchString(pattern) {\n\t\t\t\treturn onMatch, fmt.Sprintf(\"matches watcher pattern %q\", pattern)\n\t\t\t}\n\t\t}\n\t\treturn onNoMatch, \"no matching watchers\"\n\t}\n}\n\n// jsonProperty extracts a value from a path of JSON property names, assuming\n// the default encoding/json unmarshaling to the empty interface (i.e.: that\n// JSON objects are unmarshalled as map[string]interface{})\n//\n// For example, if obj is unmarshalled from the following json:\n//\n//\t{\n//\t\t\"foo\": { \"bar\": 3 }\n//\t}\n//\n// Then jsonProperty(obj, \"foo\", \"bar\") will be 3.\nfunc jsonProperty(obj any, path ...string) any {\n\tif len(path) == 0 || obj == nil {\n\t\treturn obj\n\t}\n\tm := obj.(map[string]any)\n\treturn jsonProperty(m[path[0]], path[1:]...)\n}\n\nfunc formatDiagnostic(d protocol.Diagnostic) string {\n\treturn fmt.Sprintf(\"%d:%d [%s]: %s\\n\", d.Range.Start.Line, d.Range.Start.Character, d.Source, d.Message)\n}\n\n// Diagnostics asserts that there is at least one diagnostic matching the given\n// filters.\nfunc Diagnostics(filters ...DiagnosticFilter) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tdiags := flattenDiagnostics(s)\n\t\tfor _, filter := range filters {\n\t\t\tvar filtered []flatDiagnostic\n\t\t\tfor _, d := range diags {\n\t\t\t\tif filter.check(d.name, d.diag) {\n\t\t\t\t\tfiltered = append(filtered, d)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(filtered) == 0 {\n\t\t\t\t// Reprinting the description of the filters is too verbose.\n\t\t\t\t//\n\t\t\t\t// We can probably do better here, but for now just format the\n\t\t\t\t// diagnostics.\n\t\t\t\tvar b bytes.Buffer\n\t\t\t\tfor name, params := range s.diagnostics {\n\t\t\t\t\tfmt.Fprintf(&b, \"\\t%s (version %d):\\n\", name, params.Version)\n\t\t\t\t\tfor _, d := range params.Diagnostics {\n\t\t\t\t\t\tfmt.Fprintf(&b, \"\\t\\t%s\", formatDiagnostic(d))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Unmet, fmt.Sprintf(\"diagnostics:\\n%s\", b.String())\n\t\t\t}\n\t\t\tdiags = filtered\n\t\t}\n\t\treturn Met, \"\"\n\t}\n\tvar descs []string\n\tfor _, filter := range filters {\n\t\tdescs = append(descs, filter.desc)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: \"any diagnostics \" + strings.Join(descs, \", \"),\n\t}\n}\n\n// NoDiagnostics asserts that there are no diagnostics matching the given\n// filters. Notably, if no filters are supplied this assertion checks that\n// there are no diagnostics at all, for any file.\nfunc NoDiagnostics(filters ...DiagnosticFilter) Expectation {\n\tcheck := func(s State) (Verdict, string) {\n\t\tdiags := flattenDiagnostics(s)\n\t\tfor _, filter := range filters {\n\t\t\tvar filtered []flatDiagnostic\n\t\t\tfor _, d := range diags {\n\t\t\t\tif filter.check(d.name, d.diag) {\n\t\t\t\t\tfiltered = append(filtered, d)\n\t\t\t\t}\n\t\t\t}\n\t\t\tdiags = filtered\n\t\t}\n\t\tif len(diags) > 0 {\n\t\t\td := diags[0]\n\t\t\twhy := fmt.Sprintf(\"have diagnostic: %s: %v\", d.name, formatDiagnostic(d.diag))\n\t\t\treturn Unmet, why\n\t\t}\n\t\treturn Met, \"\"\n\t}\n\tvar descs []string\n\tfor _, filter := range filters {\n\t\tdescs = append(descs, filter.desc)\n\t}\n\treturn Expectation{\n\t\tCheck:       check,\n\t\tDescription: \"no diagnostics \" + strings.Join(descs, \", \"),\n\t}\n}\n\ntype flatDiagnostic struct {\n\tname string\n\tdiag protocol.Diagnostic\n}\n\nfunc flattenDiagnostics(state State) []flatDiagnostic {\n\tvar result []flatDiagnostic\n\tfor name, diags := range state.diagnostics {\n\t\tfor _, diag := range diags.Diagnostics {\n\t\t\tresult = append(result, flatDiagnostic{name, diag})\n\t\t}\n\t}\n\treturn result\n}\n\n// -- Diagnostic filters --\n\n// A DiagnosticFilter filters the set of diagnostics, for assertion with\n// Diagnostics or NoDiagnostics.\ntype DiagnosticFilter struct {\n\tdesc  string\n\tcheck func(name string, _ protocol.Diagnostic) bool\n}\n\n// ForFile filters to diagnostics matching the sandbox-relative file name.\nfunc ForFile(name string) DiagnosticFilter {\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"for file %q\", name),\n\t\tcheck: func(diagName string, _ protocol.Diagnostic) bool {\n\t\t\treturn diagName == name\n\t\t},\n\t}\n}\n\n// FromSource filters to diagnostics matching the given diagnostics source.\nfunc FromSource(source string) DiagnosticFilter {\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"with source %q\", source),\n\t\tcheck: func(_ string, d protocol.Diagnostic) bool {\n\t\t\treturn d.Source == source\n\t\t},\n\t}\n}\n\n// AtRegexp filters to diagnostics in the file with sandbox-relative path name,\n// at the first position matching the given regexp pattern.\n//\n// TODO(rfindley): pass in the editor to expectations, so that they may depend\n// on editor state and AtRegexp can be a function rather than a method.\nfunc (e *Env) AtRegexp(name, pattern string) DiagnosticFilter {\n\tloc := e.RegexpSearch(name, pattern)\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"at the first position (%v) matching %#q in %q\", loc.Range.Start, pattern, name),\n\t\tcheck: func(diagName string, d protocol.Diagnostic) bool {\n\t\t\treturn diagName == name && d.Range.Start == loc.Range.Start\n\t\t},\n\t}\n}\n\n// AtPosition filters to diagnostics at location name:line:character, for a\n// sandbox-relative path name.\n//\n// Line and character are 0-based, and character measures UTF-16 codes.\n//\n// Note: prefer the more readable AtRegexp.\nfunc AtPosition(name string, line, character uint32) DiagnosticFilter {\n\tpos := protocol.Position{Line: line, Character: character}\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"at %s:%d:%d\", name, line, character),\n\t\tcheck: func(diagName string, d protocol.Diagnostic) bool {\n\t\t\treturn diagName == name && d.Range.Start == pos\n\t\t},\n\t}\n}\n\n// WithMessage filters to diagnostics whose message contains the given\n// substring.\nfunc WithMessage(substring string) DiagnosticFilter {\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"with message containing %q\", substring),\n\t\tcheck: func(_ string, d protocol.Diagnostic) bool {\n\t\t\treturn strings.Contains(d.Message, substring)\n\t\t},\n\t}\n}\n\n// WithSeverityTags filters to diagnostics whose severity and tags match\n// the given expectation.\nfunc WithSeverityTags(diagName string, severity protocol.DiagnosticSeverity, tags []protocol.DiagnosticTag) DiagnosticFilter {\n\treturn DiagnosticFilter{\n\t\tdesc: fmt.Sprintf(\"with diagnostic %q with severity %q and tag %#q\", diagName, severity, tags),\n\t\tcheck: func(_ string, d protocol.Diagnostic) bool {\n\t\t\treturn d.Source == diagName && d.Severity == severity && cmp.Equal(d.Tags, tags)\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/client.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake/glob\"\n)\n\n// ClientHooks are a set of optional hooks called during handling of\n// the corresponding client method (see protocol.Client for the\n// LSP server-to-client RPCs) in order to make test expectations\n// awaitable.\ntype ClientHooks struct {\n\tOnLogMessage             func(context.Context, *protocol.LogMessageParams) error\n\tOnDiagnostics            func(context.Context, *protocol.PublishDiagnosticsParams) error\n\tOnWorkDoneProgressCreate func(context.Context, *protocol.WorkDoneProgressCreateParams) error\n\tOnProgress               func(context.Context, *protocol.ProgressParams) error\n\tOnShowDocument           func(context.Context, *protocol.ShowDocumentParams) error\n\tOnShowMessage            func(context.Context, *protocol.ShowMessageParams) error\n\tOnShowMessageRequest     func(context.Context, *protocol.ShowMessageRequestParams) error\n\tOnRegisterCapability     func(context.Context, *protocol.RegistrationParams) error\n\tOnUnregisterCapability   func(context.Context, *protocol.UnregistrationParams) error\n}\n\n// Client is an implementation of the [protocol.Client] interface\n// based on the test's fake [Editor]. It mostly delegates\n// functionality to hooks that can be configured by tests.\ntype Client struct {\n\teditor      *Editor\n\thooks       ClientHooks\n\tonApplyEdit atomic.Pointer[ApplyEditHandler] // hook for marker tests to intercept edits\n}\n\ntype ApplyEditHandler = func(context.Context, *protocol.WorkspaceEdit) error\n\n// SetApplyEditHandler sets the (non-nil) handler for ApplyEdit\n// downcalls, and returns a function to restore the previous one.\n// Use it around client-to-server RPCs to capture the edits.\n// The default handler is c.Editor.onApplyEdit\nfunc (c *Client) SetApplyEditHandler(h ApplyEditHandler) func() {\n\tif h == nil {\n\t\tpanic(\"h is nil\")\n\t}\n\tprev := c.onApplyEdit.Swap(&h)\n\treturn func() {\n\t\tif c.onApplyEdit.Swap(prev) != &h {\n\t\t\tpanic(\"improper nesting of SetApplyEditHandler, restore\")\n\t\t}\n\t}\n}\n\nfunc (c *Client) CodeLensRefresh(context.Context) error { return nil }\n\nfunc (c *Client) InlayHintRefresh(context.Context) error { return nil }\n\nfunc (c *Client) DiagnosticRefresh(context.Context) error { return nil }\n\nfunc (c *Client) FoldingRangeRefresh(context.Context) error { return nil }\n\nfunc (c *Client) InlineValueRefresh(context.Context) error { return nil }\n\nfunc (c *Client) SemanticTokensRefresh(context.Context) error { return nil }\n\nfunc (c *Client) LogTrace(context.Context, *protocol.LogTraceParams) error { return nil }\n\nfunc (c *Client) TextDocumentContentRefresh(context.Context, *protocol.TextDocumentContentRefreshParams) error {\n\treturn nil\n}\n\nfunc (c *Client) ShowMessage(ctx context.Context, params *protocol.ShowMessageParams) error {\n\tif c.hooks.OnShowMessage != nil {\n\t\treturn c.hooks.OnShowMessage(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) ShowMessageRequest(ctx context.Context, params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {\n\tif c.hooks.OnShowMessageRequest != nil {\n\t\tif err := c.hooks.OnShowMessageRequest(ctx, params); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif c.editor.config.MessageResponder != nil {\n\t\treturn c.editor.config.MessageResponder(params)\n\t}\n\treturn nil, nil // don't choose, which is effectively dismissing the message\n}\n\nfunc (c *Client) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {\n\tif c.hooks.OnLogMessage != nil {\n\t\treturn c.hooks.OnLogMessage(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) Event(ctx context.Context, event *any) error {\n\treturn nil\n}\n\nfunc (c *Client) PublishDiagnostics(ctx context.Context, params *protocol.PublishDiagnosticsParams) error {\n\tif c.hooks.OnDiagnostics != nil {\n\t\treturn c.hooks.OnDiagnostics(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) WorkspaceFolders(context.Context) ([]protocol.WorkspaceFolder, error) {\n\treturn []protocol.WorkspaceFolder{}, nil\n}\n\nfunc (c *Client) Configuration(_ context.Context, p *protocol.ParamConfiguration) ([]any, error) {\n\tresults := make([]any, len(p.Items))\n\tfor i, item := range p.Items {\n\t\tif item.ScopeURI != nil && *item.ScopeURI == \"\" {\n\t\t\treturn nil, fmt.Errorf(`malformed ScopeURI \"\"`)\n\t\t}\n\t\tif item.Section == \"gopls\" {\n\t\t\tconfig := c.editor.Config()\n\t\t\tresults[i] = makeSettings(c.editor.sandbox, config, item.ScopeURI)\n\t\t}\n\t}\n\treturn results, nil\n}\n\nfunc (c *Client) RegisterCapability(ctx context.Context, params *protocol.RegistrationParams) error {\n\tif c.hooks.OnRegisterCapability != nil {\n\t\tif err := c.hooks.OnRegisterCapability(ctx, params); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// Update file watching patterns.\n\t//\n\t// TODO(rfindley): We could verify more here, like verify that the\n\t// registration ID is distinct, and that the capability is not currently\n\t// registered.\n\tfor _, registration := range params.Registrations {\n\t\tif registration.Method == \"workspace/didChangeWatchedFiles\" {\n\t\t\t// Marshal and unmarshal to interpret RegisterOptions as\n\t\t\t// DidChangeWatchedFilesRegistrationOptions.\n\t\t\traw, err := json.Marshal(registration.RegisterOptions)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"marshaling registration options: %v\", err)\n\t\t\t}\n\t\t\tvar opts protocol.DidChangeWatchedFilesRegistrationOptions\n\t\t\tif err := json.Unmarshal(raw, &opts); err != nil {\n\t\t\t\treturn fmt.Errorf(\"unmarshaling registration options: %v\", err)\n\t\t\t}\n\t\t\tvar globs []*glob.Glob\n\t\t\tfor _, watcher := range opts.Watchers {\n\t\t\t\tvar globPattern string\n\t\t\t\tswitch pattern := watcher.GlobPattern.Value.(type) {\n\t\t\t\tcase protocol.Pattern:\n\t\t\t\t\tglobPattern = pattern\n\t\t\t\tcase protocol.RelativePattern:\n\t\t\t\t\tglobPattern = path.Join(filepath.ToSlash(pattern.BaseURI.Path()), pattern.Pattern)\n\t\t\t\t}\n\t\t\t\t// TODO(rfindley): honor the watch kind.\n\t\t\t\tg, err := glob.Parse(globPattern)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error parsing glob pattern %q: %v\", watcher.GlobPattern, err)\n\t\t\t\t}\n\t\t\t\tglobs = append(globs, g)\n\t\t\t}\n\t\t\tc.editor.mu.Lock()\n\t\t\tc.editor.watchPatterns = globs\n\t\t\tc.editor.mu.Unlock()\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (c *Client) UnregisterCapability(ctx context.Context, params *protocol.UnregistrationParams) error {\n\tif c.hooks.OnUnregisterCapability != nil {\n\t\treturn c.hooks.OnUnregisterCapability(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) Progress(ctx context.Context, params *protocol.ProgressParams) error {\n\tif c.hooks.OnProgress != nil {\n\t\treturn c.hooks.OnProgress(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {\n\tif c.hooks.OnWorkDoneProgressCreate != nil {\n\t\treturn c.hooks.OnWorkDoneProgressCreate(ctx, params)\n\t}\n\treturn nil\n}\n\nfunc (c *Client) ShowDocument(ctx context.Context, params *protocol.ShowDocumentParams) (*protocol.ShowDocumentResult, error) {\n\tif c.hooks.OnShowDocument != nil {\n\t\tif err := c.hooks.OnShowDocument(ctx, params); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &protocol.ShowDocumentResult{Success: true}, nil\n\t}\n\treturn nil, nil\n}\n\nfunc (c *Client) ApplyEdit(ctx context.Context, params *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) {\n\tif len(params.Edit.Changes) > 0 {\n\t\treturn &protocol.ApplyWorkspaceEditResult{FailureReason: \"Edit.Changes is unsupported\"}, nil\n\t}\n\tonApplyEdit := c.editor.applyWorkspaceEdit\n\tif ptr := c.onApplyEdit.Load(); ptr != nil {\n\t\tonApplyEdit = *ptr\n\t}\n\tif err := onApplyEdit(ctx, &params.Edit); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &protocol.ApplyWorkspaceEditResult{Applied: true}, nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/doc.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fake provides a fake implementation of an LSP-enabled\n// text editor, its LSP client plugin, and a Sandbox environment for\n// use in integration tests.\n//\n// The Editor type provides a high level API for text editor operations\n// (open/modify/save/close a buffer, jump to definition, etc.), and the Client\n// type exposes an LSP client for the editor that can be connected to a\n// language server. By default, the Editor and Client should be compliant with\n// the LSP spec: their intended use is to verify server compliance with the\n// spec in a variety of environment. Possible future enhancements of these\n// types may allow them to misbehave in configurable ways, but that is not\n// their primary use.\n//\n// The Sandbox type provides a facility for executing tests with a temporary\n// directory, module proxy, and GOPATH.\npackage fake\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/edit.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// NewEdit creates an edit replacing all content between the 0-based\n// (startLine, startColumn) and (endLine, endColumn) with text.\n//\n// Columns measure UTF-16 codes.\nfunc NewEdit(startLine, startColumn, endLine, endColumn uint32, text string) protocol.TextEdit {\n\treturn protocol.TextEdit{\n\t\tRange: protocol.Range{\n\t\t\tStart: protocol.Position{Line: startLine, Character: startColumn},\n\t\t\tEnd:   protocol.Position{Line: endLine, Character: endColumn},\n\t\t},\n\t\tNewText: text,\n\t}\n}\n\n// applyEdits applies the edits to a file with the specified lines,\n// and returns a new slice containing the lines of the patched file.\n// It is a wrapper around diff.Apply; see that function for preconditions.\nfunc applyEdits(mapper *protocol.Mapper, edits []protocol.TextEdit, windowsLineEndings bool) ([]byte, error) {\n\tdiffEdits, err := protocol.EditsToDiffEdits(mapper, edits)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpatched, err := diff.ApplyBytes(mapper.Content, diffEdits)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif windowsLineEndings {\n\t\tpatched = toWindowsLineEndings(patched)\n\t}\n\treturn patched, nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/edit_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestApplyEdits(t *testing.T) {\n\ttests := []struct {\n\t\tlabel   string\n\t\tcontent string\n\t\tedits   []protocol.TextEdit\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tlabel: \"empty content\",\n\t\t},\n\t\t{\n\t\t\tlabel:   \"empty edit\",\n\t\t\tcontent: \"hello\",\n\t\t\tedits:   []protocol.TextEdit{},\n\t\t\twant:    \"hello\",\n\t\t},\n\t\t{\n\t\t\tlabel:   \"unicode edit\",\n\t\t\tcontent: \"hello, 日本語\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(0, 7, 0, 10, \"world\"),\n\t\t\t},\n\t\t\twant: \"hello, world\",\n\t\t},\n\t\t{\n\t\t\tlabel:   \"range edit\",\n\t\t\tcontent: \"ABC\\nDEF\\nGHI\\nJKL\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(1, 1, 2, 3, \"12\\n345\"),\n\t\t\t},\n\t\t\twant: \"ABC\\nD12\\n345\\nJKL\",\n\t\t},\n\t\t{\n\t\t\tlabel:   \"regression test for issue #57627\",\n\t\t\tcontent: \"go 1.18\\nuse moda/a\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(1, 0, 1, 0, \"\\n\"),\n\t\t\t\tNewEdit(2, 0, 2, 0, \"\\n\"),\n\t\t\t},\n\t\t\twant: \"go 1.18\\n\\nuse moda/a\\n\",\n\t\t},\n\t\t{\n\t\t\tlabel:   \"end before start\",\n\t\t\tcontent: \"ABC\\nDEF\\nGHI\\nJKL\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(2, 3, 1, 1, \"12\\n345\"),\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tlabel:   \"out of bounds line\",\n\t\t\tcontent: \"ABC\\nDEF\\nGHI\\nJKL\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(1, 1, 4, 3, \"12\\n345\"),\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tlabel:   \"out of bounds column\",\n\t\t\tcontent: \"ABC\\nDEF\\nGHI\\nJKL\",\n\t\t\tedits: []protocol.TextEdit{\n\t\t\t\tNewEdit(1, 4, 2, 3, \"12\\n345\"),\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tgot, err := applyEdits(protocol.NewMapper(\"\", []byte(test.content)), test.edits, false)\n\t\t\tif (err != nil) != test.wantErr {\n\t\t\t\tt.Errorf(\"got err %v, want error: %t\", err, test.wantErr)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got := string(got); got != test.want {\n\t\t\t\tt.Errorf(\"got %q, want %q\", got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/editor.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"maps\"\n\t\"math/rand/v2\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake/glob\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/pathutil\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// Editor is a fake client editor.  It keeps track of client state and can be\n// used for writing LSP tests.\ntype Editor struct {\n\n\t// Server, client, and sandbox are concurrency safe and written only\n\t// at construction time, so do not require synchronization.\n\tServer     protocol.Server\n\tcancelConn func()\n\tserverConn jsonrpc2.Conn\n\tclient     *Client\n\tsandbox    *Sandbox\n\n\t// TODO(rfindley): buffers should be keyed by protocol.DocumentURI.\n\tmu                       sync.Mutex\n\tconfig                   EditorConfig      // editor configuration\n\tbuffers                  map[string]buffer // open buffers (relative path -> buffer content)\n\twatchPatterns            []*glob.Glob      // glob patterns to watch\n\tsuggestionUseReplaceMode bool\n\n\t// These fields are populated by Connect.\n\tserverCapabilities protocol.ServerCapabilities\n\tsemTokOpts         protocol.SemanticTokensOptions\n\n\t// Call metrics for the purpose of expectations. This is done in an ad-hoc\n\t// manner for now. Perhaps in the future we should do something more\n\t// systematic. Guarded with a separate mutex as calls may need to be accessed\n\t// asynchronously via callbacks into the Editor.\n\tcallsMu sync.Mutex\n\tcalls   CallCounts\n}\n\n// CallCounts tracks the number of protocol notifications of different types.\ntype CallCounts struct {\n\tDidOpen, DidChange, DidSave, DidChangeWatchedFiles, DidClose, DidChangeConfiguration uint64\n}\n\n// buffer holds information about an open buffer in the editor.\ntype buffer struct {\n\tversion int              // monotonic version; incremented on edits\n\tpath    string           // relative path in the workspace\n\tmapper  *protocol.Mapper // buffer content\n\tdirty   bool             // if true, content is unsaved (TODO(rfindley): rename this field)\n}\n\nfunc (b buffer) text() string {\n\treturn string(b.mapper.Content)\n}\n\n// EditorConfig configures the editor's LSP session. This is similar to\n// golang.UserOptions, but we use a separate type here so that we expose only\n// that configuration which we support.\n//\n// The zero value for EditorConfig is the default configuration.\ntype EditorConfig struct {\n\t// ClientName sets the clientInfo.name for the LSP session (in the initialize request).\n\t//\n\t// Since this can only be set during initialization, changing this field via\n\t// Editor.ChangeConfiguration has no effect.\n\t//\n\t// If empty, \"fake.Editor\" is used.\n\tClientName string\n\n\t// Env holds environment variables to apply on top of the default editor\n\t// environment. When applying these variables, the special string\n\t// $SANDBOX_WORKDIR is replaced by the absolute path to the sandbox working\n\t// directory.\n\tEnv map[string]string\n\n\t// WorkspaceFolders is the workspace folders to configure on the LSP server.\n\t// Each workspace folder is a file path relative to the sandbox workdir, or\n\t// a uri (used when testing behavior with virtual file system or non-'file'\n\t// scheme document uris).\n\t//\n\t// As special cases, if WorkspaceFolders is nil the editor defaults to\n\t// configuring a single workspace folder corresponding to the workdir root.\n\t// To explicitly send no workspace folders, use an empty (non-nil) slice.\n\tWorkspaceFolders []string\n\n\t// NoDefaultWorkspaceFiles is used to specify whether the fake editor\n\t// should give a default workspace folder when WorkspaceFolders is nil.\n\t// When it's true, the editor will pass original WorkspaceFolders as is to the LSP server.\n\tNoDefaultWorkspaceFiles bool\n\n\t// RelRootPath is the root path which will be converted to rootUri to configure on the LSP server.\n\tRelRootPath string\n\n\t// Whether to edit files with windows line endings.\n\tWindowsLineEndings bool\n\n\t// Map of language ID -> regexp to match, used to set the file type of new\n\t// buffers. Applied as an overlay on top of the following defaults:\n\t//  \"go\"     -> \".*\\.go\"\n\t//  \"go.mod\" -> \"go\\.mod\"\n\t//  \"go.sum\" -> \"go\\.sum\"\n\t//  \"gotmpl\" -> \".*tmpl\"\n\t//  \"go.s\"   -> \".*\\.s\"\n\tFileAssociations map[protocol.LanguageKind]string\n\n\t// Settings holds user-provided configuration for the LSP server.\n\tSettings map[string]any\n\n\t// FolderSettings holds user-provided per-folder configuration, if any.\n\t//\n\t// It maps each folder (as a relative path to the sandbox workdir) to its\n\t// configuration mapping (like Settings).\n\tFolderSettings map[string]map[string]any\n\n\t// CapabilitiesJSON holds JSON client capabilities to overlay over the\n\t// editor's default client capabilities.\n\t//\n\t// Specifically, this JSON string will be unmarshalled into the editor's\n\t// client capabilities struct, before sending to the server.\n\tCapabilitiesJSON []byte\n\n\t// If non-nil, MessageResponder is used to respond to ShowMessageRequest\n\t// messages.\n\tMessageResponder func(params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error)\n\n\t// MaxMessageDelay is used for fuzzing message delivery to reproduce test\n\t// flakes.\n\tMaxMessageDelay time.Duration\n}\n\n// NewEditor creates a new Editor.\nfunc NewEditor(sandbox *Sandbox, config EditorConfig) *Editor {\n\treturn &Editor{\n\t\tbuffers: make(map[string]buffer),\n\t\tsandbox: sandbox,\n\t\tconfig:  config,\n\t}\n}\n\n// Connect configures the editor to communicate with an LSP server on conn. It\n// is not concurrency safe, and should be called at most once, before using the\n// editor.\n//\n// It returns the editor, so that it may be called as follows:\n//\n//\teditor, err := NewEditor(s).Connect(ctx, conn, hooks)\nfunc (e *Editor) Connect(ctx context.Context, connector servertest.Connector, hooks ClientHooks) (*Editor, error) {\n\tbgCtx, cancelConn := context.WithCancel(xcontext.Detach(ctx))\n\tconn := connector.Connect(bgCtx)\n\te.cancelConn = cancelConn\n\n\te.serverConn = conn\n\te.Server = protocol.ServerDispatcher(conn)\n\te.client = &Client{editor: e, hooks: hooks}\n\thandler := protocol.ClientHandler(e.client, jsonrpc2.MethodNotFound)\n\tif e.config.MaxMessageDelay > 0 {\n\t\thandler = DelayedHandler(e.config.MaxMessageDelay, handler)\n\t}\n\tconn.Go(bgCtx, protocol.Handlers(handler))\n\n\tif err := e.initialize(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\te.sandbox.Workdir.AddWatcher(e.onFileChanges)\n\treturn e, nil\n}\n\n// DelayedHandler waits [0, maxDelay) before handling each message.\nfunc DelayedHandler(maxDelay time.Duration, handler jsonrpc2.Handler) jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\t\tdelay := time.Duration(rand.Int64N(int64(maxDelay)))\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\tcase <-time.After(delay):\n\t\t}\n\t\treturn handler(ctx, reply, req)\n\t}\n}\n\nfunc (e *Editor) Stats() CallCounts {\n\te.callsMu.Lock()\n\tdefer e.callsMu.Unlock()\n\treturn e.calls\n}\n\n// Shutdown issues the 'shutdown' LSP notification.\nfunc (e *Editor) Shutdown(ctx context.Context) error {\n\tif e.Server != nil {\n\t\tif err := e.Server.Shutdown(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"Shutdown: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// Exit issues the 'exit' LSP notification.\nfunc (e *Editor) Exit(ctx context.Context) error {\n\tif e.Server != nil {\n\t\t// Not all LSP clients issue the exit RPC, but we do so here to ensure that\n\t\t// we gracefully handle it on multi-session servers.\n\t\tif err := e.Server.Exit(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"Exit: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// Close disconnects the LSP client session.\n// TODO(rfindley): rename to 'Disconnect'.\nfunc (e *Editor) Close(ctx context.Context) error {\n\tif err := e.Shutdown(ctx); err != nil {\n\t\treturn err\n\t}\n\tif err := e.Exit(ctx); err != nil {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\te.cancelConn()\n\t}()\n\n\t// called close on the editor should result in the connection closing\n\tselect {\n\tcase <-e.serverConn.Done():\n\t\t// connection closed itself\n\t\treturn nil\n\tcase <-ctx.Done():\n\t\treturn fmt.Errorf(\"connection not closed: %w\", ctx.Err())\n\t}\n}\n\n// Client returns the LSP client for this editor.\nfunc (e *Editor) Client() *Client {\n\treturn e.client\n}\n\n// makeSettings builds the settings map for use in LSP settings RPCs.\nfunc makeSettings(sandbox *Sandbox, config EditorConfig, scopeURI *protocol.URI) map[string]any {\n\tenv := make(map[string]string)\n\tmaps.Copy(env, sandbox.GoEnv())\n\tmaps.Copy(env, config.Env)\n\tfor k, v := range env {\n\t\tv = strings.ReplaceAll(v, \"$SANDBOX_WORKDIR\", sandbox.Workdir.RootURI().Path())\n\t\tenv[k] = v\n\t}\n\n\tsettings := map[string]any{\n\t\t\"env\": env,\n\n\t\t// Use verbose progress reporting so that integration tests can assert on\n\t\t// asynchronous operations being completed (such as diagnosing a snapshot).\n\t\t\"verboseWorkDoneProgress\": true,\n\n\t\t// Set an unlimited completion budget, so that tests don't flake because\n\t\t// completions are too slow.\n\t\t\"completionBudget\": \"0s\",\n\t}\n\n\tfor k, v := range config.Settings {\n\t\tif k == \"env\" {\n\t\t\tpanic(\"must not provide env via the EditorConfig.Settings field: use the EditorConfig.Env field instead\")\n\t\t}\n\t\tsettings[k] = v\n\t}\n\n\t// If the server is requesting configuration for a specific scope, apply\n\t// settings for the nearest folder that has customized settings, if any.\n\tif scopeURI != nil {\n\t\tvar (\n\t\t\tscopePath       = protocol.DocumentURI(*scopeURI).Path()\n\t\t\tclosestDir      string         // longest dir with settings containing the scope, if any\n\t\t\tclosestSettings map[string]any // settings for that dir, if any\n\t\t)\n\t\tfor relPath, settings := range config.FolderSettings {\n\t\t\tdir := sandbox.Workdir.AbsPath(relPath)\n\t\t\tif strings.HasPrefix(scopePath+string(filepath.Separator), dir+string(filepath.Separator)) && len(dir) > len(closestDir) {\n\t\t\t\tclosestDir = dir\n\t\t\t\tclosestSettings = settings\n\t\t\t}\n\t\t}\n\t\tif closestSettings != nil {\n\t\t\tmaps.Copy(settings, closestSettings)\n\t\t}\n\t}\n\n\treturn settings\n}\n\nfunc (e *Editor) initialize(ctx context.Context) error {\n\tconfig := e.Config()\n\n\tclientName := config.ClientName\n\tif clientName == \"\" {\n\t\tclientName = \"fake.Editor\"\n\t}\n\n\tparams := &protocol.ParamInitialize{}\n\tparams.ClientInfo = &protocol.ClientInfo{\n\t\tName:    clientName,\n\t\tVersion: \"v1.0.0\",\n\t}\n\tparams.InitializationOptions = makeSettings(e.sandbox, config, nil)\n\n\tparams.WorkspaceFolders = makeWorkspaceFolders(e.sandbox, config.WorkspaceFolders, config.NoDefaultWorkspaceFiles)\n\tparams.RootURI = protocol.URIFromPath(config.RelRootPath)\n\tif !uriRE.MatchString(config.RelRootPath) { // relative file path\n\t\tparams.RootURI = e.sandbox.Workdir.URI(config.RelRootPath)\n\t}\n\n\tcapabilities, err := clientCapabilities(config)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshalling EditorConfig.CapabilitiesJSON: %v\", err)\n\t}\n\tparams.Capabilities = capabilities\n\n\ttrace := protocol.TraceValue(\"messages\")\n\tparams.Trace = &trace\n\t// TODO: support workspace folders.\n\tif e.Server != nil {\n\t\tresp, err := e.Server.Initialize(ctx, params)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"initialize: %w\", err)\n\t\t}\n\t\tsemTokOpts, err := marshalUnmarshal[protocol.SemanticTokensOptions](resp.Capabilities.SemanticTokensProvider)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unmarshalling semantic tokens options: %v\", err)\n\t\t}\n\t\te.serverCapabilities = resp.Capabilities\n\t\te.semTokOpts = semTokOpts\n\n\t\tif err := e.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {\n\t\t\treturn fmt.Errorf(\"initialized: %w\", err)\n\t\t}\n\t}\n\t// TODO: await initial configuration here, or expect gopls to manage that?\n\treturn nil\n}\n\nfunc clientCapabilities(cfg EditorConfig) (protocol.ClientCapabilities, error) {\n\tvar capabilities protocol.ClientCapabilities\n\t// Set various client capabilities that are sought by gopls.\n\tcapabilities.Workspace.Configuration = true // support workspace/configuration\n\tcapabilities.TextDocument.Completion.CompletionItem.TagSupport = &protocol.CompletionItemTagOptions{}\n\tcapabilities.TextDocument.Completion.CompletionItem.TagSupport.ValueSet = []protocol.CompletionItemTag{protocol.ComplDeprecated}\n\tcapabilities.TextDocument.Completion.CompletionItem.SnippetSupport = true\n\tcapabilities.TextDocument.Completion.CompletionItem.InsertReplaceSupport = true\n\tcapabilities.TextDocument.SemanticTokens.Requests.Full = &protocol.Or_ClientSemanticTokensRequestOptions_full{Value: true}\n\tcapabilities.Window.WorkDoneProgress = true                                                // support window/workDoneProgress\n\tcapabilities.Window.ShowDocument = &protocol.ShowDocumentClientCapabilities{Support: true} // support window/showDocument\n\tcapabilities.TextDocument.SemanticTokens.TokenTypes = []string{\n\t\t\"namespace\", \"type\", \"class\", \"enum\", \"interface\",\n\t\t\"struct\", \"typeParameter\", \"parameter\", \"variable\", \"property\", \"enumMember\",\n\t\t\"event\", \"function\", \"method\", \"macro\", \"keyword\", \"modifier\", \"comment\",\n\t\t\"string\", \"number\", \"regexp\", \"operator\",\n\t\t// Additional types supported by this client:\n\t\t\"label\",\n\t}\n\tcapabilities.TextDocument.SemanticTokens.TokenModifiers = []string{\n\t\t\"declaration\", \"definition\", \"readonly\", \"static\",\n\t\t\"deprecated\", \"abstract\", \"async\", \"modification\", \"documentation\", \"defaultLibrary\",\n\t\t// Additional modifiers supported by this client:\n\t\t\"interface\", \"struct\", \"signature\", \"pointer\", \"array\", \"map\", \"slice\", \"chan\", \"string\", \"number\", \"bool\", \"invalid\",\n\t}\n\t// Request that the server provide its complete list of code action kinds.\n\tcapabilities.TextDocument.CodeAction = protocol.CodeActionClientCapabilities{\n\t\tDataSupport: true,\n\t\tResolveSupport: &protocol.ClientCodeActionResolveOptions{\n\t\t\tProperties: []string{\"edit\"},\n\t\t},\n\t\tCodeActionLiteralSupport: protocol.ClientCodeActionLiteralOptions{\n\t\t\tCodeActionKind: protocol.ClientCodeActionKindOptions{\n\t\t\t\tValueSet: []protocol.CodeActionKind{protocol.Empty}, // => all\n\t\t\t},\n\t\t},\n\t}\n\t// The LSP tests have historically enabled this flag,\n\t// but really we should test both ways for older editors.\n\tcapabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = true\n\t// Glob pattern watching is enabled.\n\tcapabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration = true\n\t// \"rename\" operations are used for package renaming.\n\t//\n\t// TODO(rfindley): add support for other resource operations (create, delete, ...)\n\tcapabilities.Workspace.WorkspaceEdit = &protocol.WorkspaceEditClientCapabilities{\n\t\tResourceOperations: []protocol.ResourceOperationKind{\n\t\t\t\"rename\",\n\t\t},\n\t}\n\n\t// Apply capabilities overlay.\n\tif cfg.CapabilitiesJSON != nil {\n\t\tif err := json.Unmarshal(cfg.CapabilitiesJSON, &capabilities); err != nil {\n\t\t\treturn protocol.ClientCapabilities{}, fmt.Errorf(\"unmarshalling EditorConfig.CapabilitiesJSON: %v\", err)\n\t\t}\n\t}\n\treturn capabilities, nil\n}\n\n// Returns the connected LSP server's capabilities.\n// Only populated after a call to [Editor.Connect].\nfunc (e *Editor) ServerCapabilities() protocol.ServerCapabilities {\n\treturn e.serverCapabilities\n}\n\n// marshalUnmarshal is a helper to json Marshal and then Unmarshal as a\n// different type. Used to work around cases where our protocol types are not\n// specific.\nfunc marshalUnmarshal[T any](v any) (T, error) {\n\tvar t T\n\tdata, err := json.Marshal(v)\n\tif err != nil {\n\t\treturn t, err\n\t}\n\terr = json.Unmarshal(data, &t)\n\treturn t, err\n}\n\n// HasCommand reports whether the connected server supports the command with the given ID.\nfunc (e *Editor) HasCommand(cmd command.Command) bool {\n\treturn slices.Contains(e.serverCapabilities.ExecuteCommandProvider.Commands, cmd.String())\n}\n\n// Examples: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml\nvar uriRE = regexp.MustCompile(`^[a-z][a-z0-9+\\-.]*://\\S+`)\n\n// makeWorkspaceFolders creates a slice of workspace folders to use for\n// this editing session, based on the editor configuration.\nfunc makeWorkspaceFolders(sandbox *Sandbox, paths []string, useEmpty bool) (folders []protocol.WorkspaceFolder) {\n\tif len(paths) == 0 {\n\t\tif useEmpty {\n\t\t\treturn nil\n\t\t}\n\t\tpaths = []string{string(sandbox.Workdir.RelativeTo)}\n\t}\n\n\tfor _, path := range paths {\n\t\turi := path\n\t\tif !uriRE.MatchString(path) { // relative file path\n\t\t\turi = string(sandbox.Workdir.URI(path))\n\t\t}\n\t\tfolders = append(folders, protocol.WorkspaceFolder{\n\t\t\tURI:  uri,\n\t\t\tName: filepath.Base(uri),\n\t\t})\n\t}\n\n\treturn folders\n}\n\n// onFileChanges is registered to be called by the Workdir on any writes that\n// go through the Workdir API. It is called synchronously by the Workdir.\nfunc (e *Editor) onFileChanges(ctx context.Context, evts []protocol.FileEvent) {\n\tif e.Server == nil {\n\t\treturn\n\t}\n\n\t// e may be locked when onFileChanges is called, but it is important that we\n\t// synchronously increment this counter so that we can subsequently assert on\n\t// the number of expected DidChangeWatchedFiles calls.\n\te.callsMu.Lock()\n\te.calls.DidChangeWatchedFiles++\n\te.callsMu.Unlock()\n\n\t// Since e may be locked, we must run this mutation asynchronously.\n\tgo func() {\n\t\te.mu.Lock()\n\t\tdefer e.mu.Unlock()\n\t\tfor _, evt := range evts {\n\t\t\t// Always send an on-disk change, even for events that seem useless\n\t\t\t// because they're shadowed by an open buffer.\n\t\t\tpath := e.sandbox.Workdir.URIToPath(evt.URI)\n\t\t\tif buf, ok := e.buffers[path]; ok {\n\t\t\t\t// Following VS Code, don't honor deletions or changes to dirty buffers.\n\t\t\t\tif buf.dirty || evt.Type == protocol.Deleted {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tcontent, err := e.sandbox.Workdir.ReadFile(path)\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue // A race with some other operation.\n\t\t\t\t}\n\t\t\t\t// No need to update if the buffer content hasn't changed.\n\t\t\t\tif string(content) == buf.text() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// During shutdown, this call will fail. Ignore the error.\n\t\t\t\t_ = e.setBufferContentLocked(ctx, path, false, content, nil)\n\t\t\t}\n\t\t}\n\t\tvar matchedEvts []protocol.FileEvent\n\t\tfor _, evt := range evts {\n\t\t\tfilename := filepath.ToSlash(evt.URI.Path())\n\t\t\tfor _, g := range e.watchPatterns {\n\t\t\t\tif g.Match(filename) {\n\t\t\t\t\tmatchedEvts = append(matchedEvts, evt)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// TODO(rfindley): don't send notifications while locked.\n\t\te.Server.DidChangeWatchedFiles(ctx, &protocol.DidChangeWatchedFilesParams{\n\t\t\tChanges: matchedEvts,\n\t\t})\n\t}()\n}\n\n// OpenFile creates a buffer for the given workdir-relative file.\n//\n// If the file is already open, it is a no-op.\nfunc (e *Editor) OpenFile(ctx context.Context, path string) error {\n\tif e.HasBuffer(path) {\n\t\treturn nil\n\t}\n\tcontent, err := e.sandbox.Workdir.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif e.Config().WindowsLineEndings {\n\t\tcontent = toWindowsLineEndings(content)\n\t}\n\treturn e.createBuffer(ctx, path, false, content)\n}\n\n// toWindowsLineEndings checks whether content has windows line endings.\n//\n// If so, it returns content unmodified. If not, it returns a new byte slice modified to use CRLF line endings.\nfunc toWindowsLineEndings(content []byte) []byte {\n\tabnormal := false\n\tfor i, b := range content {\n\t\tif b == '\\n' && (i == 0 || content[i-1] != '\\r') {\n\t\t\tabnormal = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !abnormal {\n\t\treturn content\n\t}\n\tvar buf bytes.Buffer\n\tfor i, b := range content {\n\t\tif b == '\\n' && (i == 0 || content[i-1] != '\\r') {\n\t\t\tbuf.WriteByte('\\r')\n\t\t}\n\t\tbuf.WriteByte(b)\n\t}\n\treturn buf.Bytes()\n}\n\n// CreateBuffer creates a new unsaved buffer corresponding to the workdir path,\n// containing the given textual content.\nfunc (e *Editor) CreateBuffer(ctx context.Context, path, content string) error {\n\treturn e.createBuffer(ctx, path, true, []byte(content))\n}\n\nfunc (e *Editor) createBuffer(ctx context.Context, path string, dirty bool, content []byte) error {\n\te.mu.Lock()\n\n\tif _, ok := e.buffers[path]; ok {\n\t\te.mu.Unlock()\n\t\treturn fmt.Errorf(\"buffer %q already exists\", path)\n\t}\n\n\turi := e.sandbox.Workdir.URI(path)\n\tbuf := buffer{\n\t\tversion: 1,\n\t\tpath:    path,\n\t\tmapper:  protocol.NewMapper(uri, content),\n\t\tdirty:   dirty,\n\t}\n\te.buffers[path] = buf\n\n\titem := e.textDocumentItem(buf)\n\te.mu.Unlock()\n\n\treturn e.sendDidOpen(ctx, item)\n}\n\n// textDocumentItem builds a protocol.TextDocumentItem for the given buffer.\n//\n// Precondition: e.mu must be held.\nfunc (e *Editor) textDocumentItem(buf buffer) protocol.TextDocumentItem {\n\treturn protocol.TextDocumentItem{\n\t\tURI:        e.sandbox.Workdir.URI(buf.path),\n\t\tLanguageID: languageID(buf.path, e.config.FileAssociations),\n\t\tVersion:    int32(buf.version),\n\t\tText:       buf.text(),\n\t}\n}\n\nfunc (e *Editor) sendDidOpen(ctx context.Context, item protocol.TextDocumentItem) error {\n\tif e.Server != nil {\n\t\tif err := e.Server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{\n\t\t\tTextDocument: item,\n\t\t}); err != nil {\n\t\t\treturn fmt.Errorf(\"DidOpen: %w\", err)\n\t\t}\n\t\te.callsMu.Lock()\n\t\te.calls.DidOpen++\n\t\te.callsMu.Unlock()\n\t}\n\treturn nil\n}\n\nvar defaultFileAssociations = map[protocol.LanguageKind]*regexp.Regexp{\n\t\"go\":      regexp.MustCompile(`^.*\\.go$`), // '$' is important: don't match .gotmpl!\n\t\"go.mod\":  regexp.MustCompile(`^go\\.mod$`),\n\t\"go.sum\":  regexp.MustCompile(`^go(\\.work)?\\.sum$`),\n\t\"go.work\": regexp.MustCompile(`^go\\.work$`),\n\t\"gotmpl\":  regexp.MustCompile(`^.*tmpl$`),\n\t\"go.s\":    regexp.MustCompile(`\\.s$`),\n}\n\n// languageID returns the language identifier for the path p given the user\n// configured fileAssociations.\nfunc languageID(p string, fileAssociations map[protocol.LanguageKind]string) protocol.LanguageKind {\n\tbase := path.Base(p)\n\tfor lang, re := range fileAssociations {\n\t\tre := regexp.MustCompile(re)\n\t\tif re.MatchString(base) {\n\t\t\treturn lang\n\t\t}\n\t}\n\tfor lang, re := range defaultFileAssociations {\n\t\tif re.MatchString(base) {\n\t\t\treturn lang\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// CloseBuffer removes the current buffer (regardless of whether it is saved).\n// CloseBuffer returns an error if the buffer is not open.\nfunc (e *Editor) CloseBuffer(ctx context.Context, path string) error {\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\tif !ok {\n\t\te.mu.Unlock()\n\t\treturn ErrUnknownBuffer\n\t}\n\tdelete(e.buffers, path)\n\te.mu.Unlock()\n\n\treturn e.sendDidClose(ctx, e.TextDocumentIdentifier(path))\n}\n\nfunc (e *Editor) sendDidClose(ctx context.Context, doc protocol.TextDocumentIdentifier) error {\n\tif e.Server != nil {\n\t\tif err := e.Server.DidClose(ctx, &protocol.DidCloseTextDocumentParams{\n\t\t\tTextDocument: doc,\n\t\t}); err != nil {\n\t\t\treturn fmt.Errorf(\"DidClose: %w\", err)\n\t\t}\n\t\te.callsMu.Lock()\n\t\te.calls.DidClose++\n\t\te.callsMu.Unlock()\n\t}\n\treturn nil\n}\n\nfunc (e *Editor) DocumentURI(path string) protocol.DocumentURI {\n\treturn e.sandbox.Workdir.URI(path)\n}\n\nfunc (e *Editor) TextDocumentIdentifier(path string) protocol.TextDocumentIdentifier {\n\treturn protocol.TextDocumentIdentifier{\n\t\tURI: e.DocumentURI(path),\n\t}\n}\n\n// SaveBuffer writes the content of the buffer specified by the given path to\n// the filesystem.\nfunc (e *Editor) SaveBuffer(ctx context.Context, path string) error {\n\tif err := e.OrganizeImports(ctx, path); err != nil {\n\t\treturn fmt.Errorf(\"organizing imports before save: %w\", err)\n\t}\n\tif err := e.FormatBuffer(ctx, path); err != nil {\n\t\treturn fmt.Errorf(\"formatting before save: %w\", err)\n\t}\n\treturn e.SaveBufferWithoutActions(ctx, path)\n}\n\nfunc (e *Editor) SaveBufferWithoutActions(ctx context.Context, path string) error {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tbuf, ok := e.buffers[path]\n\tif !ok {\n\t\treturn fmt.Errorf(\"unknown buffer: %q\", path)\n\t}\n\tcontent := buf.text()\n\tincludeText := false\n\tsyncOptions, ok := e.serverCapabilities.TextDocumentSync.(protocol.TextDocumentSyncOptions)\n\tif ok {\n\t\tincludeText = syncOptions.Save.IncludeText\n\t}\n\n\tdocID := e.TextDocumentIdentifier(buf.path)\n\tif e.Server != nil {\n\t\tif err := e.Server.WillSave(ctx, &protocol.WillSaveTextDocumentParams{\n\t\t\tTextDocument: docID,\n\t\t\tReason:       protocol.Manual,\n\t\t}); err != nil {\n\t\t\treturn fmt.Errorf(\"WillSave: %w\", err)\n\t\t}\n\t}\n\tif err := e.sandbox.Workdir.WriteFile(ctx, path, content); err != nil {\n\t\treturn fmt.Errorf(\"writing %q: %w\", path, err)\n\t}\n\n\tbuf.dirty = false\n\te.buffers[path] = buf\n\n\tif e.Server != nil {\n\t\tparams := &protocol.DidSaveTextDocumentParams{\n\t\t\tTextDocument: docID,\n\t\t}\n\t\tif includeText {\n\t\t\tparams.Text = &content\n\t\t}\n\t\tif err := e.Server.DidSave(ctx, params); err != nil {\n\t\t\treturn fmt.Errorf(\"DidSave: %w\", err)\n\t\t}\n\t\te.callsMu.Lock()\n\t\te.calls.DidSave++\n\t\te.callsMu.Unlock()\n\t}\n\treturn nil\n}\n\n// ErrNoMatch is returned if a regexp search fails.\nvar (\n\tErrNoMatch       = errors.New(\"no match\")\n\tErrUnknownBuffer = errors.New(\"unknown buffer\")\n)\n\n// regexpLocation returns the location of the first occurrence of either re\n// or its singular subgroup. It returns ErrNoMatch if the regexp doesn't match.\nfunc regexpLocation(mapper *protocol.Mapper, re string) (protocol.Location, error) {\n\tvar start, end int\n\trec, err := regexp.Compile(re)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tindexes := rec.FindSubmatchIndex(mapper.Content)\n\tif indexes == nil {\n\t\treturn protocol.Location{}, ErrNoMatch\n\t}\n\tswitch len(indexes) {\n\tcase 2:\n\t\t// no subgroups: return the range of the regexp expression\n\t\tstart, end = indexes[0], indexes[1]\n\tcase 4:\n\t\t// one subgroup: return its range\n\t\tstart, end = indexes[2], indexes[3]\n\tdefault:\n\t\treturn protocol.Location{}, fmt.Errorf(\"invalid search regexp %q: expect either 0 or 1 subgroups, got %d\", re, len(indexes)/2-1)\n\t}\n\treturn mapper.OffsetLocation(start, end)\n}\n\n// RegexpSearch returns the Location of the first match for re in the buffer\n// bufName. For convenience, RegexpSearch supports the following two modes:\n//  1. If re has no subgroups, return the position of the match for re itself.\n//  2. If re has one subgroup, return the position of the first subgroup.\n//\n// It returns an error re is invalid, has more than one subgroup, or doesn't\n// match the buffer.\nfunc (e *Editor) RegexpSearch(bufName, re string) (protocol.Location, error) {\n\te.mu.Lock()\n\tbuf, ok := e.buffers[bufName]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn protocol.Location{}, ErrUnknownBuffer\n\t}\n\treturn regexpLocation(buf.mapper, re)\n}\n\n// RegexpReplace edits the buffer corresponding to path by replacing the first\n// instance of re, or its first subgroup, with the replace text. See\n// RegexpSearch for more explanation of these two modes.\n// It returns an error if re is invalid, has more than one subgroup, or doesn't\n// match the buffer.\nfunc (e *Editor) RegexpReplace(ctx context.Context, path, re, replace string) error {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tbuf, ok := e.buffers[path]\n\tif !ok {\n\t\treturn ErrUnknownBuffer\n\t}\n\tloc, err := regexpLocation(buf.mapper, re)\n\tif err != nil {\n\t\treturn err\n\t}\n\tedits := []protocol.TextEdit{{\n\t\tRange:   loc.Range,\n\t\tNewText: replace,\n\t}}\n\tpatched, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"editing %q: %v\", path, err)\n\t}\n\treturn e.setBufferContentLocked(ctx, path, true, patched, edits)\n}\n\n// EditBuffer applies the given test edits to the buffer identified by path.\nfunc (e *Editor) EditBuffer(ctx context.Context, path string, edits []protocol.TextEdit) error {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\treturn e.editBufferLocked(ctx, path, edits)\n}\n\nfunc (e *Editor) SetBufferContent(ctx context.Context, path, content string) error {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\treturn e.setBufferContentLocked(ctx, path, true, []byte(content), nil)\n}\n\n// HasBuffer reports whether the file name is open in the editor.\nfunc (e *Editor) HasBuffer(name string) bool {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\t_, ok := e.buffers[name]\n\treturn ok\n}\n\n// BufferText returns the content of the buffer with the given name, or \"\" if\n// the file at that path is not open. The second return value reports whether\n// the file is open.\nfunc (e *Editor) BufferText(name string) (string, bool) {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tbuf, ok := e.buffers[name]\n\tif !ok {\n\t\treturn \"\", false\n\t}\n\treturn buf.text(), true\n}\n\n// Mapper returns the protocol.Mapper for the given buffer name, if it is open.\nfunc (e *Editor) Mapper(name string) (*protocol.Mapper, error) {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tbuf, ok := e.buffers[name]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no mapper for %q\", name)\n\t}\n\treturn buf.mapper, nil\n}\n\n// BufferVersion returns the current version of the buffer corresponding to\n// name (or 0 if it is not being edited).\nfunc (e *Editor) BufferVersion(name string) int {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\treturn e.buffers[name].version\n}\n\nfunc (e *Editor) editBufferLocked(ctx context.Context, path string, edits []protocol.TextEdit) error {\n\tbuf, ok := e.buffers[path]\n\tif !ok {\n\t\treturn fmt.Errorf(\"unknown buffer %q\", path)\n\t}\n\tcontent, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"editing %q: %v; edits:\\n%v\", path, err, edits)\n\t}\n\treturn e.setBufferContentLocked(ctx, path, true, content, edits)\n}\n\nfunc (e *Editor) setBufferContentLocked(ctx context.Context, path string, dirty bool, content []byte, fromEdits []protocol.TextEdit) error {\n\tbuf, ok := e.buffers[path]\n\tif !ok {\n\t\treturn fmt.Errorf(\"unknown buffer %q\", path)\n\t}\n\tbuf.mapper = protocol.NewMapper(buf.mapper.URI, content)\n\tbuf.version++\n\tbuf.dirty = dirty\n\te.buffers[path] = buf\n\n\t// A simple heuristic: if there is only one edit, send it incrementally.\n\t// Otherwise, send the entire content.\n\tvar evt protocol.TextDocumentContentChangeEvent\n\tif len(fromEdits) == 1 {\n\t\tevt.Range = &fromEdits[0].Range\n\t\tevt.Text = fromEdits[0].NewText\n\t} else {\n\t\tevt.Text = buf.text()\n\t}\n\tparams := &protocol.DidChangeTextDocumentParams{\n\t\tTextDocument: protocol.VersionedTextDocumentIdentifier{\n\t\t\tVersion:                int32(buf.version),\n\t\t\tTextDocumentIdentifier: e.TextDocumentIdentifier(buf.path),\n\t\t},\n\t\tContentChanges: []protocol.TextDocumentContentChangeEvent{evt},\n\t}\n\tif e.Server != nil {\n\t\tif err := e.Server.DidChange(ctx, params); err != nil {\n\t\t\treturn fmt.Errorf(\"DidChange: %w\", err)\n\t\t}\n\t\te.callsMu.Lock()\n\t\te.calls.DidChange++\n\t\te.callsMu.Unlock()\n\t}\n\treturn nil\n}\n\n// Definitions returns the definitions of the symbol at the given\n// location in an open buffer.\nfunc (e *Editor) Definitions(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {\n\tif err := e.checkBufferLocation(loc); err != nil {\n\t\treturn nil, err\n\t}\n\tparams := &protocol.DefinitionParams{}\n\tparams.TextDocument.URI = loc.URI\n\tparams.Position = loc.Range.Start\n\n\treturn e.Server.Definition(ctx, params)\n}\n\n// TypeDefinitions returns the type definitions of the symbol at the\n// given location in an open buffer.\nfunc (e *Editor) TypeDefinitions(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {\n\tif err := e.checkBufferLocation(loc); err != nil {\n\t\treturn nil, err\n\t}\n\tparams := &protocol.TypeDefinitionParams{}\n\tparams.TextDocument.URI = loc.URI\n\tparams.Position = loc.Range.Start\n\tparams.Range = loc.Range\n\n\treturn e.Server.TypeDefinition(ctx, params)\n}\n\n// Symbol performs a workspace symbol search using query\nfunc (e *Editor) Symbol(ctx context.Context, query string) ([]protocol.SymbolInformation, error) {\n\tparams := &protocol.WorkspaceSymbolParams{Query: query}\n\treturn e.Server.Symbol(ctx, params)\n}\n\n// OrganizeImports requests and performs the source.organizeImports codeAction.\nfunc (e *Editor) OrganizeImports(ctx context.Context, path string) error {\n\tloc := e.sandbox.Workdir.EntireFile(path)\n\t_, err := e.applyCodeActions(ctx, loc, nil, protocol.SourceOrganizeImports)\n\treturn err\n}\n\n// RefactorRewrite requests and performs the source.refactorRewrite codeAction.\nfunc (e *Editor) RefactorRewrite(ctx context.Context, loc protocol.Location) error {\n\tapplied, err := e.applyCodeActions(ctx, loc, nil, protocol.RefactorRewrite)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif applied == 0 {\n\t\treturn fmt.Errorf(\"no refactorings were applied\")\n\t}\n\treturn nil\n}\n\n// ApplyQuickFixes requests and performs the quickfix codeAction.\nfunc (e *Editor) ApplyQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) error {\n\tapplied, err := e.applyCodeActions(ctx, loc, diagnostics, protocol.SourceFixAll, protocol.QuickFix)\n\tif applied == 0 {\n\t\treturn fmt.Errorf(\"no quick fixes were applied\")\n\t}\n\treturn err\n}\n\n// ApplyCodeAction applies the given code action.\nfunc (e *Editor) ApplyCodeAction(ctx context.Context, action protocol.CodeAction) error {\n\t// Resolve the code actions if necessary and supported.\n\tif action.Edit == nil {\n\t\teditSupport, err := e.EditResolveSupport()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif editSupport {\n\t\t\tca, err := e.Server.ResolveCodeAction(ctx, &action)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\taction = *ca\n\t\t}\n\t}\n\n\tif action.Edit != nil {\n\t\tfor _, change := range action.Edit.DocumentChanges {\n\t\t\tif change.TextDocumentEdit != nil {\n\t\t\t\tpath := e.sandbox.Workdir.URIToPath(change.TextDocumentEdit.TextDocument.URI)\n\t\t\t\tif int32(e.buffers[path].version) != change.TextDocumentEdit.TextDocument.Version {\n\t\t\t\t\t// Skip edits for old versions.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err := e.EditBuffer(ctx, path, protocol.AsTextEdits(change.TextDocumentEdit.Edits)); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"editing buffer %q: %w\", path, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Execute any commands. The specification says that commands are\n\t// executed after edits are applied.\n\tif action.Command != nil {\n\t\tif err := e.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{\n\t\t\tCommand:   action.Command.Command,\n\t\t\tArguments: action.Command.Arguments,\n\t\t}, nil); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// Some commands may edit files on disk.\n\treturn e.sandbox.Workdir.CheckForFileChanges(ctx)\n}\n\nfunc (e *Editor) Diagnostics(ctx context.Context, path string) ([]protocol.Diagnostic, error) {\n\tif e.Server == nil {\n\t\treturn nil, errors.New(\"not connected\")\n\t}\n\te.mu.Lock()\n\tcapabilities := e.serverCapabilities.DiagnosticProvider\n\te.mu.Unlock()\n\n\tif capabilities == nil {\n\t\treturn nil, errors.New(\"server does not support pull diagnostics\")\n\t}\n\tswitch capabilities.Value.(type) {\n\tcase nil:\n\t\treturn nil, errors.New(\"server does not support pull diagnostics\")\n\tcase protocol.DiagnosticOptions:\n\tcase protocol.DiagnosticRegistrationOptions:\n\t\t// We could optionally check TextDocumentRegistrationOptions here to\n\t\t// see if any filters apply to path.\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unknown DiagnosticsProvider type %T\", capabilities.Value))\n\t}\n\n\tparams := &protocol.DocumentDiagnosticParams{\n\t\tTextDocument: e.TextDocumentIdentifier(path),\n\t}\n\tresult, err := e.Server.Diagnostic(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treport, ok := result.Value.(protocol.RelatedFullDocumentDiagnosticReport)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unexpected diagnostics report type %T\", result)\n\t}\n\treturn report.Items, nil\n}\n\n// GetQuickFixes returns the available quick fix code actions.\nfunc (e *Editor) GetQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {\n\treturn e.CodeActions(ctx, loc, diagnostics, protocol.QuickFix, protocol.SourceFixAll)\n}\n\nfunc (e *Editor) applyCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) (int, error) {\n\tactions, err := e.CodeActions(ctx, loc, diagnostics, only...)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tapplied := 0\n\tfor _, action := range actions {\n\t\tif action.Title == \"\" {\n\t\t\treturn 0, fmt.Errorf(\"empty title for code action\")\n\t\t}\n\t\tapplied++\n\t\tif err := e.ApplyCodeAction(ctx, action); err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\treturn applied, nil\n}\n\n// TODO(rfindley): add missing documentation to exported methods here.\n\nfunc (e *Editor) CodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) ([]protocol.CodeAction, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tparams := &protocol.CodeActionParams{}\n\tparams.TextDocument.URI = loc.URI\n\tparams.Context.Only = only\n\tparams.Range = loc.Range // may be zero => whole file\n\tif diagnostics != nil {\n\t\tparams.Context.Diagnostics = diagnostics\n\t}\n\treturn e.Server.CodeAction(ctx, params)\n}\n\nfunc (e *Editor) ExecuteCodeLensCommand(ctx context.Context, path string, cmd command.Command, result any) error {\n\tlenses, err := e.CodeLens(ctx, path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar lens protocol.CodeLens\n\tvar found bool\n\tfor _, l := range lenses {\n\t\tif l.Command.Command == cmd.String() {\n\t\t\tlens = l\n\t\t\tfound = true\n\t\t}\n\t}\n\tif !found {\n\t\treturn fmt.Errorf(\"found no command with the ID %s\", cmd)\n\t}\n\treturn e.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{\n\t\tCommand:   lens.Command.Command,\n\t\tArguments: lens.Command.Arguments,\n\t}, result)\n}\n\n// ExecuteCommand makes a workspace/executeCommand request to the connected LSP\n// server, if any.\n//\n// Result contains a pointer to a variable to be populated by json.Unmarshal.\nfunc (e *Editor) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams, result any) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\tvar match bool\n\tif e.serverCapabilities.ExecuteCommandProvider != nil {\n\t\t// Ensure that this command was actually listed as a supported command.\n\t\tif slices.Contains(e.serverCapabilities.ExecuteCommandProvider.Commands, params.Command) {\n\t\t\tmatch = true\n\t\t}\n\t}\n\tif !match {\n\t\treturn fmt.Errorf(\"unsupported command %q\", params.Command)\n\t}\n\tresponse, err := e.Server.ExecuteCommand(ctx, params)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Some commands use the go command, which writes directly to disk.\n\t// For convenience, check for those changes.\n\tif err := e.sandbox.Workdir.CheckForFileChanges(ctx); err != nil {\n\t\treturn fmt.Errorf(\"checking for file changes: %v\", err)\n\t}\n\tif result != nil {\n\t\t// ExecuteCommand already unmarshalled the response without knowing\n\t\t// its schema, using the generic map[string]any representation.\n\t\t// Encode and decode again, this time into a typed variable.\n\t\t//\n\t\t// This could be improved by generating a jsonrpc2 command client from the\n\t\t// command.Interface, but that should only be done if we're consolidating\n\t\t// this part of the tsprotocol generation.\n\t\t//\n\t\t// TODO(rfindley): we could also improve this by having ExecuteCommand return\n\t\t// a json.RawMessage, similar to what we do with arguments.\n\t\tdata, err := json.Marshal(response)\n\t\tif err != nil {\n\t\t\treturn bug.Errorf(\"marshalling response: %v\", err)\n\t\t}\n\t\tif err := json.Unmarshal(data, result); err != nil {\n\t\t\treturn fmt.Errorf(\"unmarshalling response: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// FormatBuffer gofmts a Go file.\nfunc (e *Editor) FormatBuffer(ctx context.Context, path string) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\te.mu.Lock()\n\tversion := e.buffers[path].version\n\te.mu.Unlock()\n\tparams := &protocol.DocumentFormattingParams{}\n\tparams.TextDocument.URI = e.sandbox.Workdir.URI(path)\n\tedits, err := e.Server.Formatting(ctx, params)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"textDocument/formatting: %w\", err)\n\t}\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tif versionAfter := e.buffers[path].version; versionAfter != version {\n\t\treturn fmt.Errorf(\"before receipt of formatting edits, buffer version changed from %d to %d\", version, versionAfter)\n\t}\n\tif len(edits) == 0 {\n\t\treturn nil\n\t}\n\treturn e.editBufferLocked(ctx, path, edits)\n}\n\nfunc (e *Editor) checkBufferLocation(loc protocol.Location) error {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\tbuf, ok := e.buffers[path]\n\tif !ok {\n\t\treturn fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\n\t_, _, err := buf.mapper.RangeOffsets(loc.Range)\n\treturn err\n}\n\n// RunGenerate runs `go generate` non-recursively in the workdir-relative dir\n// path. It does not report any resulting file changes as a watched file\n// change, so must be followed by a call to Workdir.CheckForFileChanges once\n// the generate command has completed.\n// TODO(rFindley): this shouldn't be necessary anymore. Delete it.\nfunc (e *Editor) RunGenerate(ctx context.Context, dir string) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\tabsDir := e.sandbox.Workdir.AbsPath(dir)\n\tcmd := command.NewGenerateCommand(\"\", command.GenerateArgs{\n\t\tDir:       protocol.URIFromPath(absDir),\n\t\tRecursive: false,\n\t})\n\tparams := &protocol.ExecuteCommandParams{\n\t\tCommand:   cmd.Command,\n\t\tArguments: cmd.Arguments,\n\t}\n\tif err := e.ExecuteCommand(ctx, params, nil); err != nil {\n\t\treturn fmt.Errorf(\"running generate: %v\", err)\n\t}\n\t// Unfortunately we can't simply poll the workdir for file changes here,\n\t// because server-side command may not have completed. In integration tests, we can\n\t// Await this state change, but here we must delegate that responsibility to\n\t// the caller.\n\treturn nil\n}\n\n// CodeLens executes a codelens request on the server.\nfunc (e *Editor) CodeLens(ctx context.Context, path string) ([]protocol.CodeLens, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.CodeLensParams{\n\t\tTextDocument: e.TextDocumentIdentifier(path),\n\t}\n\tlens, err := e.Server.CodeLens(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn lens, nil\n}\n\n// Completion executes a completion request on the server.\nfunc (e *Editor) Completion(ctx context.Context, loc protocol.Location) (*protocol.CompletionList, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.CompletionParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\tcompletions, err := e.Server.Completion(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn completions, nil\n}\n\nfunc (e *Editor) DidCreateFiles(ctx context.Context, files ...protocol.DocumentURI) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\tparams := &protocol.CreateFilesParams{}\n\tfor _, file := range files {\n\t\tparams.Files = append(params.Files, protocol.FileCreate{\n\t\t\tURI: string(file),\n\t\t})\n\t}\n\treturn e.Server.DidCreateFiles(ctx, params)\n}\n\nfunc (e *Editor) SetSuggestionInsertReplaceMode(_ context.Context, useReplaceMode bool) {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\te.suggestionUseReplaceMode = useReplaceMode\n}\n\n// AcceptCompletion accepts a completion for the given item\n// at the given position based on the editor's suggestion insert mode.\n// The server provides separate insert/replace ranges only if the\n// Editor declares `InsertReplaceSupport` capability during initialization.\n// Otherwise, it returns a single range and the insert/replace mode is ignored.\nfunc (e *Editor) AcceptCompletion(ctx context.Context, loc protocol.Location, item protocol.CompletionItem) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\t_, ok := e.buffers[path]\n\tif !ok {\n\t\treturn fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tedit, err := protocol.SelectCompletionTextEdit(item, e.suggestionUseReplaceMode)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn e.editBufferLocked(ctx, path, append([]protocol.TextEdit{\n\t\tedit,\n\t}, item.AdditionalTextEdits...))\n}\n\n// Symbols executes a workspace/symbols request on the server.\nfunc (e *Editor) Symbols(ctx context.Context, sym string) ([]protocol.SymbolInformation, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tparams := &protocol.WorkspaceSymbolParams{Query: sym}\n\tans, err := e.Server.Symbol(ctx, params)\n\treturn ans, err\n}\n\n// CodeLens executes a codelens request on the server.\nfunc (e *Editor) InlayHint(ctx context.Context, path string) ([]protocol.InlayHint, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.InlayHintParams{\n\t\tTextDocument: e.TextDocumentIdentifier(path),\n\t}\n\thints, err := e.Server.InlayHint(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn hints, nil\n}\n\n// References returns references to the object at loc, as returned by\n// the connected LSP server. If no server is connected, it returns (nil, nil).\nfunc (e *Editor) References(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.ReferenceParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\tContext: protocol.ReferenceContext{\n\t\t\tIncludeDeclaration: true,\n\t\t},\n\t}\n\tlocations, err := e.Server.References(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn locations, nil\n}\n\n// Rename performs a rename of the object at loc to newName, using the\n// connected LSP server. If no server is connected, it returns nil.\nfunc (e *Editor) Rename(ctx context.Context, loc protocol.Location, newName string) error {\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\n\t// Verify that PrepareRename succeeds.\n\tprepareParams := &protocol.PrepareRenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\tif _, err := e.Server.PrepareRename(ctx, prepareParams); err != nil {\n\t\treturn fmt.Errorf(\"preparing rename: %v\", err)\n\t}\n\n\tparams := &protocol.RenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\tNewName:                    newName,\n\t}\n\twsedit, err := e.Server.Rename(ctx, params)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn e.applyWorkspaceEdit(ctx, wsedit)\n}\n\n// Implementations returns implementations for the object at loc, as\n// returned by the connected LSP server. If no server is connected, it returns\n// (nil, nil).\nfunc (e *Editor) Implementations(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.ImplementationParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\treturn e.Server.Implementation(ctx, params)\n}\n\nfunc (e *Editor) SignatureHelp(ctx context.Context, loc protocol.Location) (*protocol.SignatureHelp, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.SignatureHelpParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t}\n\treturn e.Server.SignatureHelp(ctx, params)\n}\n\nfunc (e *Editor) RenameFile(ctx context.Context, oldPath, newPath string) error {\n\tclosed, opened, err := e.renameBuffers(oldPath, newPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, c := range closed {\n\t\tif err := e.sendDidClose(ctx, c); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor _, o := range opened {\n\t\tif err := e.sendDidOpen(ctx, o); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Finally, perform the renaming on disk.\n\tif err := e.sandbox.Workdir.RenameFile(ctx, oldPath, newPath); err != nil {\n\t\treturn fmt.Errorf(\"renaming sandbox file: %w\", err)\n\t}\n\treturn nil\n}\n\n// renameBuffers renames in-memory buffers affected by the renaming of\n// oldPath->newPath, returning the resulting text documents that must be closed\n// and opened over the LSP.\nfunc (e *Editor) renameBuffers(oldPath, newPath string) (closed []protocol.TextDocumentIdentifier, opened []protocol.TextDocumentItem, _ error) {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\n\t// In case either oldPath or newPath is absolute, convert to absolute paths\n\t// before checking for containment.\n\toldAbs := e.sandbox.Workdir.AbsPath(oldPath)\n\tnewAbs := e.sandbox.Workdir.AbsPath(newPath)\n\n\t// Collect buffers that are affected by the given file or directory renaming.\n\tbuffersToRename := make(map[string]string) // old path -> new path\n\n\tfor path := range e.buffers {\n\t\tabs := e.sandbox.Workdir.AbsPath(path)\n\t\tif oldAbs == abs || pathutil.InDir(oldAbs, abs) {\n\t\t\trel, err := filepath.Rel(oldAbs, abs)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"filepath.Rel(%q, %q): %v\", oldAbs, abs, err)\n\t\t\t}\n\t\t\tnabs := filepath.Join(newAbs, rel)\n\t\t\tnewPath := e.sandbox.Workdir.RelPath(nabs)\n\t\t\tbuffersToRename[path] = newPath\n\t\t}\n\t}\n\n\t// Update buffers, and build protocol changes.\n\tfor old, new := range buffersToRename {\n\t\tbuf := e.buffers[old]\n\t\tdelete(e.buffers, old)\n\t\tbuf.version = 1\n\t\tbuf.path = new\n\t\te.buffers[new] = buf\n\n\t\tclosed = append(closed, e.TextDocumentIdentifier(old))\n\t\topened = append(opened, e.textDocumentItem(buf))\n\t}\n\n\treturn closed, opened, nil\n}\n\n// applyWorkspaceEdit applies the sequence of document changes in\n// wsedit to the Editor.\n//\n// See also:\n//   - changedFiles in ../../marker/marker_test.go for the\n//     handler used by the marker test to intercept edits.\n//   - client.applyWorkspaceEdit in ../../../cmd/cmd.go for the\n//     CLI variant.\nfunc (e *Editor) applyWorkspaceEdit(ctx context.Context, wsedit *protocol.WorkspaceEdit) error {\n\turiToPath := e.sandbox.Workdir.URIToPath\n\n\tfor _, change := range wsedit.DocumentChanges {\n\t\tswitch {\n\t\tcase change.TextDocumentEdit != nil:\n\t\t\tif err := e.applyTextDocumentEdit(ctx, *change.TextDocumentEdit); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase change.RenameFile != nil:\n\t\t\told := uriToPath(change.RenameFile.OldURI)\n\t\t\tnew := uriToPath(change.RenameFile.NewURI)\n\t\t\tif err := e.RenameFile(ctx, old, new); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase change.CreateFile != nil:\n\t\t\tpath := uriToPath(change.CreateFile.URI)\n\t\t\tif err := e.CreateBuffer(ctx, path, \"\"); err != nil {\n\t\t\t\treturn err // e.g. already exists\n\t\t\t}\n\n\t\tcase change.DeleteFile != nil:\n\t\t\tpath := uriToPath(change.DeleteFile.URI)\n\t\t\t// The specified URI could be a file or a directory.\n\t\t\tfiles, err := e.sandbox.Workdir.ListFiles(path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif len(files) > 0 {\n\t\t\t\t// Directory is not empty. If \"Recursive\" is true, we delete\n\t\t\t\t// every file in the folder. Otherwise, we continue without\n\t\t\t\t// deleting the directory.\n\t\t\t\tif change.DeleteFile.Options != nil && change.DeleteFile.Options.Recursive {\n\t\t\t\t\tfor _, f := range files {\n\t\t\t\t\t\t_ = e.CloseBuffer(ctx, f) // returns error if not open\n\t\t\t\t\t\tif err := e.sandbox.Workdir.RemoveFile(ctx, f); err != nil {\n\t\t\t\t\t\t\treturn err // e.g. doesn't exist\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t_ = e.CloseBuffer(ctx, path) // returns error if not open\n\t\t\tif err := e.sandbox.Workdir.RemoveFile(ctx, path); err != nil {\n\t\t\t\treturn err // e.g. doesn't exist\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn bug.Errorf(\"invalid DocumentChange\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (e *Editor) applyTextDocumentEdit(ctx context.Context, change protocol.TextDocumentEdit) error {\n\tpath := e.sandbox.Workdir.URIToPath(change.TextDocument.URI)\n\tif ver := int32(e.BufferVersion(path)); ver != change.TextDocument.Version {\n\t\treturn fmt.Errorf(\"buffer versions for %q do not match: have %d, editing %d\", path, ver, change.TextDocument.Version)\n\t}\n\tif !e.HasBuffer(path) {\n\t\terr := e.OpenFile(ctx, path)\n\t\tif os.IsNotExist(err) {\n\t\t\t// TODO: it's unclear if this is correct. Here we create the buffer (with\n\t\t\t// version 1), then apply edits. Perhaps we should apply the edits before\n\t\t\t// sending the didOpen notification.\n\t\t\terr = e.CreateBuffer(ctx, path, \"\")\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn e.EditBuffer(ctx, path, protocol.AsTextEdits(change.Edits))\n}\n\n// Config returns the current editor configuration.\nfunc (e *Editor) Config() EditorConfig {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\treturn e.config\n}\n\nfunc (e *Editor) SetConfig(cfg EditorConfig) {\n\te.mu.Lock()\n\te.config = cfg\n\te.mu.Unlock()\n}\n\n// ChangeConfiguration sets the new editor configuration, and if applicable\n// sends a didChangeConfiguration notification.\n//\n// An error is returned if the change notification failed to send.\nfunc (e *Editor) ChangeConfiguration(ctx context.Context, newConfig EditorConfig) error {\n\te.SetConfig(newConfig)\n\tif e.Server != nil {\n\t\tvar params protocol.DidChangeConfigurationParams // empty: gopls ignores the Settings field\n\t\tif err := e.Server.DidChangeConfiguration(ctx, &params); err != nil {\n\t\t\treturn err\n\t\t}\n\t\te.callsMu.Lock()\n\t\te.calls.DidChangeConfiguration++\n\t\te.callsMu.Unlock()\n\t}\n\treturn nil\n}\n\n// ChangeWorkspaceFolders sets the new workspace folders, and sends a\n// didChangeWorkspaceFolders notification to the server.\n//\n// The given folders must all be unique.\nfunc (e *Editor) ChangeWorkspaceFolders(ctx context.Context, folders []string) error {\n\tconfig := e.Config()\n\n\t// capture existing folders so that we can compute the change.\n\toldFolders := makeWorkspaceFolders(e.sandbox, config.WorkspaceFolders, config.NoDefaultWorkspaceFiles)\n\tnewFolders := makeWorkspaceFolders(e.sandbox, folders, config.NoDefaultWorkspaceFiles)\n\tconfig.WorkspaceFolders = folders\n\te.SetConfig(config)\n\n\tif e.Server == nil {\n\t\treturn nil\n\t}\n\n\tvar params protocol.DidChangeWorkspaceFoldersParams\n\n\t// Keep track of old workspace folders that must be removed.\n\ttoRemove := make(map[protocol.URI]protocol.WorkspaceFolder)\n\tfor _, folder := range oldFolders {\n\t\ttoRemove[folder.URI] = folder\n\t}\n\n\t// Sanity check: if we see a folder twice the algorithm below doesn't work,\n\t// so track seen folders to ensure that we panic in that case.\n\tseen := make(map[protocol.URI]protocol.WorkspaceFolder)\n\tfor _, folder := range newFolders {\n\t\tif _, ok := seen[folder.URI]; ok {\n\t\t\tpanic(fmt.Sprintf(\"folder %s seen twice\", folder.URI))\n\t\t}\n\n\t\t// If this folder already exists, we don't want to remove it.\n\t\t// Otherwise, we need to add it.\n\t\tif _, ok := toRemove[folder.URI]; ok {\n\t\t\tdelete(toRemove, folder.URI)\n\t\t} else {\n\t\t\tparams.Event.Added = append(params.Event.Added, folder)\n\t\t}\n\t}\n\n\tfor _, v := range toRemove {\n\t\tparams.Event.Removed = append(params.Event.Removed, v)\n\t}\n\n\treturn e.Server.DidChangeWorkspaceFolders(ctx, &params)\n}\n\n// ResolveCodeAction executes a codeAction/resolve request on the server.\nfunc (e *Editor) ResolveCodeAction(ctx context.Context, action *protocol.CodeAction) (*protocol.CodeAction, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\treturn e.Server.ResolveCodeAction(ctx, action)\n}\n\n// CodeAction executes a codeAction request on the server.\n// If loc.Range is zero, the whole file is implied.\n// To reduce distraction, the trigger action (unknown, automatic, invoked)\n// may affect what actions are offered.\nfunc (e *Editor) CodeAction(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, trigger protocol.CodeActionTriggerKind) ([]protocol.CodeAction, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\te.mu.Lock()\n\t_, ok := e.buffers[path]\n\te.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %q is not open\", path)\n\t}\n\tparams := &protocol.CodeActionParams{\n\t\tTextDocument: e.TextDocumentIdentifier(path),\n\t\tContext: protocol.CodeActionContext{\n\t\t\tDiagnostics: diagnostics,\n\t\t\tTriggerKind: &trigger,\n\t\t\tOnly:        []protocol.CodeActionKind{protocol.Empty}, // => all\n\t\t},\n\t\tRange: loc.Range, // may be zero\n\t}\n\tlens, err := e.Server.CodeAction(ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn lens, nil\n}\n\nfunc (e *Editor) EditResolveSupport() (bool, error) {\n\tcapabilities, err := clientCapabilities(e.Config())\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn capabilities.TextDocument.CodeAction.ResolveSupport != nil && slices.Contains(capabilities.TextDocument.CodeAction.ResolveSupport.Properties, \"edit\"), nil\n}\n\n// Hover triggers a hover at the given position in an open buffer.\n// It may return (nil, zero) if no symbol was selected.\nfunc (e *Editor) Hover(ctx context.Context, loc protocol.Location) (*protocol.MarkupContent, protocol.Location, error) {\n\tif err := e.checkBufferLocation(loc); err != nil {\n\t\treturn nil, protocol.Location{}, err\n\t}\n\tparams := &protocol.HoverParams{}\n\tparams.TextDocument.URI = loc.URI\n\tparams.Position = loc.Range.Start\n\tparams.Range = loc.Range\n\n\tresp, err := e.Server.Hover(ctx, params)\n\tif err != nil {\n\t\treturn nil, protocol.Location{}, fmt.Errorf(\"hover: %w\", err)\n\t}\n\tif resp == nil {\n\t\treturn nil, protocol.Location{}, nil // e.g. no selected symbol\n\t}\n\treturn &resp.Contents, loc.URI.Location(resp.Range), nil\n}\n\nfunc (e *Editor) DocumentLink(ctx context.Context, path string) ([]protocol.DocumentLink, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tparams := &protocol.DocumentLinkParams{}\n\tparams.TextDocument.URI = e.sandbox.Workdir.URI(path)\n\treturn e.Server.DocumentLink(ctx, params)\n}\n\nfunc (e *Editor) DocumentHighlight(ctx context.Context, loc protocol.Location) ([]protocol.DocumentHighlight, error) {\n\tif e.Server == nil {\n\t\treturn nil, nil\n\t}\n\tif err := e.checkBufferLocation(loc); err != nil {\n\t\treturn nil, err\n\t}\n\tparams := &protocol.DocumentHighlightParams{}\n\tparams.TextDocument.URI = loc.URI\n\tparams.Position = loc.Range.Start\n\n\treturn e.Server.DocumentHighlight(ctx, params)\n}\n\n// SemanticTokensFull invokes textDocument/semanticTokens/full, and interprets\n// its result.\nfunc (e *Editor) SemanticTokensFull(ctx context.Context, path string) ([]SemanticToken, error) {\n\tp := &protocol.SemanticTokensParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{\n\t\t\tURI: e.sandbox.Workdir.URI(path),\n\t\t},\n\t}\n\tresp, err := e.Server.SemanticTokensFull(ctx, p)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcontent, ok := e.BufferText(path)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %s is not open\", path)\n\t}\n\treturn e.interpretTokens(resp.Data, content), nil\n}\n\n// SemanticTokensRange invokes textDocument/semanticTokens/range, and\n// interprets its result.\nfunc (e *Editor) SemanticTokensRange(ctx context.Context, loc protocol.Location) ([]SemanticToken, error) {\n\tp := &protocol.SemanticTokensRangeParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},\n\t\tRange:        loc.Range,\n\t}\n\tresp, err := e.Server.SemanticTokensRange(ctx, p)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpath := e.sandbox.Workdir.URIToPath(loc.URI)\n\t// As noted above: buffers should be keyed by protocol.DocumentURI.\n\tcontent, ok := e.BufferText(path)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"buffer %s is not open\", path)\n\t}\n\treturn e.interpretTokens(resp.Data, content), nil\n}\n\n// A SemanticToken is an interpreted semantic token value.\ntype SemanticToken struct {\n\tToken     string\n\tTokenType string\n\tMod       string\n}\n\n// Note: previously this function elided comment, string, and number tokens.\n// Instead, filtering of token types should be done by the caller.\nfunc (e *Editor) interpretTokens(x []uint32, contents string) []SemanticToken {\n\tlegend := e.semTokOpts.Legend\n\tlines := strings.Split(contents, \"\\n\")\n\tans := []SemanticToken{}\n\tline, col := 1, 1\n\tfor i := 0; i < len(x); i += 5 {\n\t\tline += int(x[i])\n\t\tcol += int(x[i+1])\n\t\tif x[i] != 0 { // new line\n\t\t\tcol = int(x[i+1]) + 1 // 1-based column numbers\n\t\t}\n\t\tsz := x[i+2]\n\t\tt := legend.TokenTypes[x[i+3]]\n\t\tl := x[i+4]\n\t\tvar mods []string\n\t\tfor i, mod := range legend.TokenModifiers {\n\t\t\tif l&(1<<i) != 0 {\n\t\t\t\tmods = append(mods, mod)\n\t\t\t}\n\t\t}\n\t\t// Preexisting note: \"col is a utf-8 offset\"\n\t\t// TODO(rfindley): is that true? Or is it UTF-16, like other columns in the LSP?\n\t\ttok := lines[line-1][col-1 : col-1+int(sz)]\n\t\tans = append(ans, SemanticToken{tok, t, strings.Join(mods, \" \")})\n\t}\n\treturn ans\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/editor_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nconst exampleProgram = `\n-- go.mod --\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello World.\")\n}\n`\n\nfunc TestClientEditing(t *testing.T) {\n\tws, err := NewSandbox(&SandboxConfig{Files: UnpackTxt(exampleProgram)})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer ws.Close()\n\tctx := context.Background()\n\teditor := NewEditor(ws, EditorConfig{})\n\tif err := editor.OpenFile(ctx, \"main.go\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := editor.EditBuffer(ctx, \"main.go\", []protocol.TextEdit{\n\t\t{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 5, Character: 14},\n\t\t\t\tEnd:   protocol.Position{Line: 5, Character: 26},\n\t\t\t},\n\t\t\tNewText: \"Hola, mundo.\",\n\t\t},\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := editor.buffers[\"main.go\"].text()\n\twant := `package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hola, mundo.\")\n}\n`\n\tif got != want {\n\t\tt.Errorf(\"got text %q, want %q\", got, want)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/glob/glob.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package glob implements an LSP-compliant glob pattern matcher for testing.\npackage glob\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// A Glob is an LSP-compliant glob pattern, as defined by the spec:\n// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#documentFilter\n//\n// NOTE: this implementation is currently only intended for testing. In order\n// to make it production ready, we'd need to:\n//   - verify it against the VS Code implementation\n//   - add more tests\n//   - microbenchmark, likely avoiding the element interface\n//   - resolve the question of what is meant by \"character\". If it's a UTF-16\n//     code (as we suspect) it'll be a bit more work.\n//\n// Quoting from the spec:\n// Glob patterns can have the following syntax:\n//   - `*` to match one or more characters in a path segment\n//   - `?` to match on one character in a path segment\n//   - `**` to match any number of path segments, including none\n//   - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}`\n//     matches all TypeScript and JavaScript files)\n//   - `[]` to declare a range of characters to match in a path segment\n//     (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n//   - `[!...]` to negate a range of characters to match in a path segment\n//     (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but\n//     not `example.0`)\n//\n// Expanding on this:\n//   - '/' matches one or more literal slashes.\n//   - any other character matches itself literally.\ntype Glob struct {\n\telems []element // pattern elements\n}\n\n// Parse builds a Glob for the given pattern, returning an error if the pattern\n// is invalid.\nfunc Parse(pattern string) (*Glob, error) {\n\tg, _, err := parse(pattern, false)\n\treturn g, err\n}\n\nfunc parse(pattern string, nested bool) (*Glob, string, error) {\n\tg := new(Glob)\n\tfor len(pattern) > 0 {\n\t\tswitch pattern[0] {\n\t\tcase '/':\n\t\t\tpattern = pattern[1:]\n\t\t\tg.elems = append(g.elems, slash{})\n\n\t\tcase '*':\n\t\t\tif len(pattern) > 1 && pattern[1] == '*' {\n\t\t\t\tif (len(g.elems) > 0 && g.elems[len(g.elems)-1] != slash{}) || (len(pattern) > 2 && pattern[2] != '/') {\n\t\t\t\t\treturn nil, \"\", errors.New(\"** may only be adjacent to '/'\")\n\t\t\t\t}\n\t\t\t\tpattern = pattern[2:]\n\t\t\t\tg.elems = append(g.elems, starStar{})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpattern = pattern[1:]\n\t\t\tg.elems = append(g.elems, star{})\n\n\t\tcase '?':\n\t\t\tpattern = pattern[1:]\n\t\t\tg.elems = append(g.elems, anyChar{})\n\n\t\tcase '{':\n\t\t\tvar gs group\n\t\t\tfor pattern[0] != '}' {\n\t\t\t\tpattern = pattern[1:]\n\t\t\t\tg, pat, err := parse(pattern, true)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, \"\", err\n\t\t\t\t}\n\t\t\t\tif len(pat) == 0 {\n\t\t\t\t\treturn nil, \"\", errors.New(\"unmatched '{'\")\n\t\t\t\t}\n\t\t\t\tpattern = pat\n\t\t\t\tgs = append(gs, g)\n\t\t\t}\n\t\t\tpattern = pattern[1:]\n\t\t\tg.elems = append(g.elems, gs)\n\n\t\tcase '}', ',':\n\t\t\tif nested {\n\t\t\t\treturn g, pattern, nil\n\t\t\t}\n\t\t\tpattern = g.parseLiteral(pattern, false)\n\n\t\tcase '[':\n\t\t\tpattern = pattern[1:]\n\t\t\tif len(pattern) == 0 {\n\t\t\t\treturn nil, \"\", errBadRange\n\t\t\t}\n\t\t\tnegate := false\n\t\t\tif pattern[0] == '!' {\n\t\t\t\tpattern = pattern[1:]\n\t\t\t\tnegate = true\n\t\t\t}\n\t\t\tlow, sz, err := readRangeRune(pattern)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", err\n\t\t\t}\n\t\t\tpattern = pattern[sz:]\n\t\t\tif len(pattern) == 0 || pattern[0] != '-' {\n\t\t\t\treturn nil, \"\", errBadRange\n\t\t\t}\n\t\t\tpattern = pattern[1:]\n\t\t\thigh, sz, err := readRangeRune(pattern)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", err\n\t\t\t}\n\t\t\tpattern = pattern[sz:]\n\t\t\tif len(pattern) == 0 || pattern[0] != ']' {\n\t\t\t\treturn nil, \"\", errBadRange\n\t\t\t}\n\t\t\tpattern = pattern[1:]\n\t\t\tg.elems = append(g.elems, charRange{negate, low, high})\n\n\t\tdefault:\n\t\t\tpattern = g.parseLiteral(pattern, nested)\n\t\t}\n\t}\n\treturn g, \"\", nil\n}\n\n// helper for decoding a rune in range elements, e.g. [a-z]\nfunc readRangeRune(input string) (rune, int, error) {\n\tr, sz := utf8.DecodeRuneInString(input)\n\tvar err error\n\tif r == utf8.RuneError {\n\t\t// See the documentation for DecodeRuneInString.\n\t\tswitch sz {\n\t\tcase 0:\n\t\t\terr = errBadRange\n\t\tcase 1:\n\t\t\terr = errInvalidUTF8\n\t\t}\n\t}\n\treturn r, sz, err\n}\n\nvar (\n\terrBadRange    = errors.New(\"'[' patterns must be of the form [x-y]\")\n\terrInvalidUTF8 = errors.New(\"invalid UTF-8 encoding\")\n)\n\nfunc (g *Glob) parseLiteral(pattern string, nested bool) string {\n\tvar specialChars string\n\tif nested {\n\t\tspecialChars = \"*?{[/},\"\n\t} else {\n\t\tspecialChars = \"*?{[/\"\n\t}\n\tend := strings.IndexAny(pattern, specialChars)\n\tif end == -1 {\n\t\tend = len(pattern)\n\t}\n\tg.elems = append(g.elems, literal(pattern[:end]))\n\treturn pattern[end:]\n}\n\nfunc (g *Glob) String() string {\n\tvar b strings.Builder\n\tfor _, e := range g.elems {\n\t\tfmt.Fprint(&b, e)\n\t}\n\treturn b.String()\n}\n\n// element holds a glob pattern element, as defined below.\ntype element fmt.Stringer\n\n// element types.\ntype (\n\tslash     struct{} // One or more '/' separators\n\tliteral   string   // string literal, not containing /, *, ?, {}, or []\n\tstar      struct{} // *\n\tanyChar   struct{} // ?\n\tstarStar  struct{} // **\n\tgroup     []*Glob  // {foo, bar, ...} grouping\n\tcharRange struct { // [a-z] character range\n\t\tnegate    bool\n\t\tlow, high rune\n\t}\n)\n\nfunc (s slash) String() string    { return \"/\" }\nfunc (l literal) String() string  { return string(l) }\nfunc (s star) String() string     { return \"*\" }\nfunc (a anyChar) String() string  { return \"?\" }\nfunc (s starStar) String() string { return \"**\" }\nfunc (g group) String() string {\n\tvar parts []string\n\tfor _, g := range g {\n\t\tparts = append(parts, g.String())\n\t}\n\treturn \"{\" + strings.Join(parts, \",\") + \"}\"\n}\nfunc (r charRange) String() string {\n\treturn \"[\" + string(r.low) + \"-\" + string(r.high) + \"]\"\n}\n\n// Match reports whether the input string matches the glob pattern.\nfunc (g *Glob) Match(input string) bool {\n\treturn match(g.elems, input)\n}\n\nfunc match(elems []element, input string) (ok bool) {\n\tvar elem any\n\tfor len(elems) > 0 {\n\t\telem, elems = elems[0], elems[1:]\n\t\tswitch elem := elem.(type) {\n\t\tcase slash:\n\t\t\tif len(input) == 0 || input[0] != '/' {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor input[0] == '/' {\n\t\t\t\tinput = input[1:]\n\t\t\t}\n\n\t\tcase starStar:\n\t\t\t// Special cases:\n\t\t\t//  - **/a matches \"a\"\n\t\t\t//  - **/ matches everything\n\t\t\t//\n\t\t\t// Note that if ** is followed by anything, it must be '/' (this is\n\t\t\t// enforced by Parse).\n\t\t\tif len(elems) > 0 {\n\t\t\t\telems = elems[1:]\n\t\t\t}\n\n\t\t\t// A trailing ** matches anything.\n\t\t\tif len(elems) == 0 {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Backtracking: advance pattern segments until the remaining pattern\n\t\t\t// elements match.\n\t\t\tfor len(input) != 0 {\n\t\t\t\tif match(elems, input) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\t_, input = split(input)\n\t\t\t}\n\t\t\treturn false\n\n\t\tcase literal:\n\t\t\tif !strings.HasPrefix(input, string(elem)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tinput = input[len(elem):]\n\n\t\tcase star:\n\t\t\tvar segInput string\n\t\t\tsegInput, input = split(input)\n\n\t\t\telemEnd := len(elems)\n\t\t\tfor i, e := range elems {\n\t\t\t\tif e == (slash{}) {\n\t\t\t\t\telemEnd = i\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tsegElems := elems[:elemEnd]\n\t\t\telems = elems[elemEnd:]\n\n\t\t\t// A trailing * matches the entire segment.\n\t\t\tif len(segElems) == 0 {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Backtracking: advance characters until remaining subpattern elements\n\t\t\t// match.\n\t\t\tmatched := false\n\t\t\tfor i := range segInput {\n\t\t\t\tif match(segElems, segInput[i:]) {\n\t\t\t\t\tmatched = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !matched {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\tcase anyChar:\n\t\t\tif len(input) == 0 || input[0] == '/' {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tinput = input[1:]\n\n\t\tcase group:\n\t\t\t// Append remaining pattern elements to each group member looking for a\n\t\t\t// match.\n\t\t\tvar branch []element\n\t\t\tfor _, m := range elem {\n\t\t\t\tbranch = branch[:0]\n\t\t\t\tbranch = append(branch, m.elems...)\n\t\t\t\tbranch = append(branch, elems...)\n\t\t\t\tif match(branch, input) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\n\t\tcase charRange:\n\t\t\tif len(input) == 0 || input[0] == '/' {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tc, sz := utf8.DecodeRuneInString(input)\n\t\t\tif c < elem.low || c > elem.high {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tinput = input[sz:]\n\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"segment type %T not implemented\", elem))\n\t\t}\n\t}\n\n\treturn len(input) == 0\n}\n\n// split returns the portion before and after the first slash\n// (or sequence of consecutive slashes). If there is no slash\n// it returns (input, nil).\nfunc split(input string) (first, rest string) {\n\ti := strings.IndexByte(input, '/')\n\tif i < 0 {\n\t\treturn input, \"\"\n\t}\n\tfirst = input[:i]\n\tfor j := i; j < len(input); j++ {\n\t\tif input[j] != '/' {\n\t\t\treturn first, input[j:]\n\t\t}\n\t}\n\treturn first, \"\"\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/glob/glob_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage glob_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake/glob\"\n)\n\nfunc TestParseErrors(t *testing.T) {\n\ttests := []string{\n\t\t\"***\",\n\t\t\"ab{c\",\n\t\t\"[]\",\n\t\t\"[a-]\",\n\t\t\"ab{c{d}\",\n\t}\n\n\tfor _, test := range tests {\n\t\t_, err := glob.Parse(test)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"Parse(%q) succeeded unexpectedly\", test)\n\t\t}\n\t}\n}\n\nfunc TestMatch(t *testing.T) {\n\ttests := []struct {\n\t\tpattern, input string\n\t\twant           bool\n\t}{\n\t\t// Basic cases.\n\t\t{\"\", \"\", true},\n\t\t{\"\", \"a\", false},\n\t\t{\"\", \"/\", false},\n\t\t{\"abc\", \"abc\", true},\n\n\t\t// ** behavior\n\t\t{\"**\", \"abc\", true},\n\t\t{\"**/abc\", \"abc\", true},\n\t\t{\"**\", \"abc/def\", true},\n\t\t{\"{a/**/c,a/**/d}\", \"a/b/c\", true},\n\t\t{\"{a/**/c,a/**/d}\", \"a/b/c/d\", true},\n\t\t{\"{a/**/c,a/**/e}\", \"a/b/c/d\", false},\n\t\t{\"{a/**/c,a/**/e,a/**/d}\", \"a/b/c/d\", true},\n\t\t{\"{/a/**/c,a/**/e,a/**/d}\", \"a/b/c/d\", true},\n\t\t{\"{/a/**/c,a/**/e,a/**/d}\", \"/a/b/c/d\", false},\n\t\t{\"{/a/**/c,a/**/e,a/**/d}\", \"/a/b/c\", true},\n\t\t{\"{/a/**/e,a/**/e,a/**/d}\", \"/a/b/c\", false},\n\n\t\t// * and ? behavior\n\t\t{\"/*\", \"/a\", true},\n\t\t{\"*\", \"foo\", true},\n\t\t{\"*o\", \"foo\", true},\n\t\t{\"*o\", \"foox\", false},\n\t\t{\"f*o\", \"foo\", true},\n\t\t{\"f*o\", \"fo\", true},\n\t\t{\"fo?\", \"foo\", true},\n\t\t{\"fo?\", \"fox\", true},\n\t\t{\"fo?\", \"fooo\", false},\n\t\t{\"fo?\", \"fo\", false},\n\t\t{\"?\", \"a\", true},\n\t\t{\"?\", \"ab\", false},\n\t\t{\"?\", \"\", false},\n\t\t{\"*?\", \"\", false},\n\t\t{\"?b\", \"ab\", true},\n\t\t{\"?c\", \"ab\", false},\n\n\t\t// {} behavior\n\t\t{\"ab{c,d}e\", \"abce\", true},\n\t\t{\"ab{c,d}e\", \"abde\", true},\n\t\t{\"ab{c,d}e\", \"abxe\", false},\n\t\t{\"ab{c,d}e\", \"abe\", false},\n\t\t{\"{a,b}c\", \"ac\", true},\n\t\t{\"{a,b}c\", \"bc\", true},\n\t\t{\"{a,b}c\", \"ab\", false},\n\t\t{\"a{b,c}\", \"ab\", true},\n\t\t{\"a{b,c}\", \"ac\", true},\n\t\t{\"a{b,c}\", \"bc\", false},\n\t\t{\"ab{c{1,2},d}e\", \"abc1e\", true},\n\t\t{\"ab{c{1,2},d}e\", \"abde\", true},\n\t\t{\"ab{c{1,2},d}e\", \"abc1f\", false},\n\t\t{\"ab{c{1,2},d}e\", \"abce\", false},\n\t\t{\"ab{c[}-~]}d\", \"abc}d\", true},\n\t\t{\"ab{c[}-~]}d\", \"abc~d\", true},\n\t\t{\"ab{c[}-~],y}d\", \"abcxd\", false},\n\t\t{\"ab{c[}-~],y}d\", \"abyd\", true},\n\t\t{\"ab{c[}-~],y}d\", \"abd\", false},\n\t\t{\"{a/b/c,d/e/f}\", \"a/b/c\", true},\n\t\t{\"/ab{/c,d}e\", \"/ab/ce\", true},\n\t\t{\"/ab{/c,d}e\", \"/ab/cf\", false},\n\n\t\t// [-] behavior\n\t\t{\"[a-c]\", \"a\", true},\n\t\t{\"[a-c]\", \"b\", true},\n\t\t{\"[a-c]\", \"c\", true},\n\t\t{\"[a-c]\", \"d\", false},\n\t\t{\"[a-c]\", \" \", false},\n\n\t\t// Realistic examples.\n\t\t{\"**/*.{ts,js}\", \"path/to/foo.ts\", true},\n\t\t{\"**/*.{ts,js}\", \"path/to/foo.js\", true},\n\t\t{\"**/*.{ts,js}\", \"path/to/foo.go\", false},\n\t}\n\n\tfor _, test := range tests {\n\t\tg, err := glob.Parse(test.pattern)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"New(%q) failed unexpectedly: %v\", test.pattern, err)\n\t\t}\n\t\tif got := g.Match(test.input); got != test.want {\n\t\t\tt.Errorf(\"New(%q).Match(%q) = %t, want %t\", test.pattern, test.input, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/proxy.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/proxydir\"\n)\n\n// WriteProxy creates a new proxy file tree using the txtar-encoded content,\n// and returns its URL.\nfunc WriteProxy(tmpdir string, files map[string][]byte) (string, error) {\n\ttype moduleVersion struct {\n\t\tmodulePath, version string\n\t}\n\t// Transform into the format expected by the proxydir package.\n\tfilesByModule := make(map[moduleVersion]map[string][]byte)\n\tfor name, data := range files {\n\t\tmodulePath, version, suffix := splitModuleVersionPath(name)\n\t\tmv := moduleVersion{modulePath, version}\n\t\tif _, ok := filesByModule[mv]; !ok {\n\t\t\tfilesByModule[mv] = make(map[string][]byte)\n\t\t}\n\t\tfilesByModule[mv][suffix] = data\n\t}\n\tfor mv, files := range filesByModule {\n\t\t// Don't hoist this check out of the loop:\n\t\t// the problem is benign if filesByModule is empty.\n\t\tif strings.Contains(tmpdir, \"#\") {\n\t\t\treturn \"\", fmt.Errorf(\"WriteProxy's tmpdir contains '#', which is unsuitable for GOPROXY. (If tmpdir was derived from testing.T.Name, use t.Run to ensure that each subtest has a unique name.)\")\n\t\t}\n\t\tif err := proxydir.WriteModuleVersion(tmpdir, mv.modulePath, mv.version, files); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error writing %s@%s: %v\", mv.modulePath, mv.version, err)\n\t\t}\n\t}\n\treturn proxydir.ToURL(tmpdir), nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/sandbox.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/robustio\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// Sandbox holds a collection of temporary resources to use for working with Go\n// code in tests.\ntype Sandbox struct {\n\tgopath          string\n\trootdir         string\n\tgoproxy         string\n\tWorkdir         *Workdir\n\tgoCommandRunner gocommand.Runner\n}\n\n// SandboxConfig controls the behavior of a test sandbox. The zero value\n// defines a reasonable default.\ntype SandboxConfig struct {\n\t// RootDir sets the base directory to use when creating temporary\n\t// directories. If not specified, defaults to a new temporary directory.\n\tRootDir string\n\t// Files holds a txtar-encoded archive of files to populate the initial state\n\t// of the working directory.\n\t//\n\t// For convenience, the special substring \"$SANDBOX_WORKDIR\" is replaced with\n\t// the sandbox's resolved working directory before writing files.\n\tFiles map[string][]byte\n\t// InGoPath specifies that the working directory should be within the\n\t// temporary GOPATH.\n\tInGoPath bool\n\t// Workdir configures the working directory of the Sandbox. It behaves as\n\t// follows:\n\t//  - if set to an absolute path, use that path as the working directory.\n\t//  - if set to a relative path, create and use that path relative to the\n\t//    sandbox.\n\t//  - if unset, default to a the 'work' subdirectory of the sandbox.\n\t//\n\t// This option is incompatible with InGoPath or Files.\n\tWorkdir string\n\t// ProxyFiles holds a txtar-encoded archive of files to populate a file-based\n\t// Go proxy.\n\tProxyFiles map[string][]byte\n\t// GOPROXY is the explicit GOPROXY value that should be used for the sandbox.\n\t//\n\t// This option is incompatible with ProxyFiles.\n\tGOPROXY string\n}\n\n// NewSandbox creates a collection of named temporary resources, with a\n// working directory populated by the txtar-encoded content in srctxt, and a\n// file-based module proxy populated with the txtar-encoded content in\n// proxytxt.\n//\n// If rootDir is non-empty, it will be used as the root of temporary\n// directories created for the sandbox. Otherwise, a new temporary directory\n// will be used as root.\n//\n// TODO(rfindley): the sandbox abstraction doesn't seem to carry its weight.\n// Sandboxes should be composed out of their building-blocks, rather than via a\n// monolithic configuration.\nfunc NewSandbox(config *SandboxConfig) (_ *Sandbox, err error) {\n\tif config == nil {\n\t\tconfig = new(SandboxConfig)\n\t}\n\tif err := validateConfig(*config); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid SandboxConfig: %v\", err)\n\t}\n\n\tsb := &Sandbox{}\n\tdefer func() {\n\t\t// Clean up if we fail at any point in this constructor.\n\t\tif err != nil {\n\t\t\tsb.Close() // ignore error\n\t\t}\n\t}()\n\n\trootDir := config.RootDir\n\tif rootDir == \"\" {\n\t\trootDir, err = os.MkdirTemp(config.RootDir, \"gopls-sandbox-\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"creating temporary workdir: %v\", err)\n\t\t}\n\t}\n\tsb.rootdir = rootDir\n\tsb.gopath = filepath.Join(sb.rootdir, \"gopath\")\n\tif err := os.Mkdir(sb.gopath, 0755); err != nil {\n\t\treturn nil, err\n\t}\n\tif config.GOPROXY != \"\" {\n\t\tsb.goproxy = config.GOPROXY\n\t} else {\n\t\tproxydir := filepath.Join(sb.rootdir, \"proxy\")\n\t\tif err := os.Mkdir(proxydir, 0755); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsb.goproxy, err = WriteProxy(proxydir, config.ProxyFiles)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\t// Short-circuit writing the workdir if we're given an absolute path, since\n\t// this is used for running in an existing directory.\n\t// TODO(findleyr): refactor this to be less of a workaround.\n\tif filepath.IsAbs(config.Workdir) {\n\t\tsb.Workdir, err = NewWorkdir(config.Workdir, nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn sb, nil\n\t}\n\tvar workdir string\n\tif config.Workdir == \"\" {\n\t\tif config.InGoPath {\n\t\t\t// Set the working directory as $GOPATH/src.\n\t\t\tworkdir = filepath.Join(sb.gopath, \"src\")\n\t\t} else if workdir == \"\" {\n\t\t\tworkdir = filepath.Join(sb.rootdir, \"work\")\n\t\t}\n\t} else {\n\t\t// relative path\n\t\tworkdir = filepath.Join(sb.rootdir, config.Workdir)\n\t}\n\tif err := os.MkdirAll(workdir, 0755); err != nil {\n\t\treturn nil, err\n\t}\n\tsb.Workdir, err = NewWorkdir(workdir, config.Files)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn sb, nil\n}\n\nfunc UnpackTxt(txt string) map[string][]byte {\n\tdataMap := make(map[string][]byte)\n\tarchive := txtar.Parse([]byte(txt))\n\tfor _, f := range archive.Files {\n\t\tif _, ok := dataMap[f.Name]; ok {\n\t\t\tpanic(fmt.Sprintf(\"found file %q twice\", f.Name))\n\t\t}\n\t\tdataMap[f.Name] = f.Data\n\t}\n\treturn dataMap\n}\n\nfunc validateConfig(config SandboxConfig) error {\n\tif filepath.IsAbs(config.Workdir) && (len(config.Files) > 0 || config.InGoPath) {\n\t\treturn errors.New(\"absolute Workdir cannot be set in conjunction with Files or InGoPath\")\n\t}\n\tif config.Workdir != \"\" && config.InGoPath {\n\t\treturn errors.New(\"Workdir cannot be set in conjunction with InGoPath\")\n\t}\n\tif config.GOPROXY != \"\" && config.ProxyFiles != nil {\n\t\treturn errors.New(\"GOPROXY cannot be set in conjunction with ProxyFiles\")\n\t}\n\treturn nil\n}\n\n// splitModuleVersionPath extracts module information from files stored in the\n// directory structure modulePath@version/suffix.\n// For example:\n//\n//\tsplitModuleVersionPath(\"mod.com@v1.2.3/package\") = (\"mod.com\", \"v1.2.3\", \"package\")\nfunc splitModuleVersionPath(path string) (modulePath, version, suffix string) {\n\tparts := strings.Split(path, \"/\")\n\tvar modulePathParts []string\n\tfor i, p := range parts {\n\t\tif strings.Contains(p, \"@\") {\n\t\t\tmv := strings.SplitN(p, \"@\", 2)\n\t\t\tmodulePathParts = append(modulePathParts, mv[0])\n\t\t\treturn strings.Join(modulePathParts, \"/\"), mv[1], strings.Join(parts[i+1:], \"/\")\n\t\t}\n\t\tmodulePathParts = append(modulePathParts, p)\n\t}\n\t// Default behavior: this is just a module path.\n\treturn path, \"\", \"\"\n}\n\nfunc (sb *Sandbox) RootDir() string {\n\treturn sb.rootdir\n}\n\n// GOPATH returns the value of the Sandbox GOPATH.\nfunc (sb *Sandbox) GOPATH() string {\n\treturn sb.gopath\n}\n\n// GoEnv returns the default environment variables that can be used for\n// invoking Go commands in the sandbox.\nfunc (sb *Sandbox) GoEnv() map[string]string {\n\treturn map[string]string{\n\t\t\"GOPATH\":           sb.GOPATH(),\n\t\t\"GOPROXY\":          sb.goproxy,\n\t\t\"GO111MODULE\":      \"\",\n\t\t\"GOSUMDB\":          \"off\",\n\t\t\"GOPACKAGESDRIVER\": \"off\",\n\t\t\"GOTOOLCHAIN\":      \"local\", // tests should not download toolchains\n\t\t// TODO(golang/go#74595): Why don't we respect GOMODCACHE in the\n\t\t// settings.env? See comment at env.CleanModCache.\n\t\t\"GOMODCACHE\": \"\",\n\t}\n}\n\n// goCommandInvocation returns a new gocommand.Invocation initialized with the\n// sandbox environment variables and working directory.\nfunc (sb *Sandbox) goCommandInvocation() gocommand.Invocation {\n\tvar vars []string\n\tfor k, v := range sb.GoEnv() {\n\t\tvars = append(vars, fmt.Sprintf(\"%s=%s\", k, v))\n\t}\n\tinv := gocommand.Invocation{\n\t\tEnv: vars,\n\t}\n\t// sb.Workdir may be nil if we exited the constructor with errors (we call\n\t// Close to clean up any partial state from the constructor, which calls\n\t// RunGoCommand).\n\tif sb.Workdir != nil {\n\t\tinv.WorkingDir = string(sb.Workdir.RelativeTo)\n\t}\n\treturn inv\n}\n\n// RunGoCommand executes a go command in the sandbox and returns its standard\n// output. If checkForFileChanges is true, the sandbox scans the working\n// directory and emits file change events for any file changes it finds.\nfunc (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args, env []string, checkForFileChanges bool) ([]byte, error) {\n\tinv := sb.goCommandInvocation()\n\tinv.Verb = verb\n\tinv.Args = args\n\tinv.Env = append(inv.Env, env...)\n\tif dir != \"\" {\n\t\tinv.WorkingDir = sb.Workdir.AbsPath(dir)\n\t}\n\tstdout, stderr, _, err := sb.goCommandRunner.RunRaw(ctx, inv)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"go command failed (stdout: %s) (stderr: %s): %v\", stdout.String(), stderr.String(), err)\n\t}\n\t// Since running a go command may result in changes to workspace files,\n\t// check if we need to send any \"watched\" file events.\n\t//\n\t// TODO(rFindley): this side-effect can impact the usability of the sandbox\n\t//                 for benchmarks. Consider refactoring.\n\tif sb.Workdir != nil && checkForFileChanges {\n\t\tif err := sb.Workdir.CheckForFileChanges(ctx); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"checking for file changes: %w\", err)\n\t\t}\n\t}\n\treturn stdout.Bytes(), nil\n}\n\n// GoVersion checks the version of the go command.\n// It returns the X in Go 1.X.\nfunc (sb *Sandbox) GoVersion(ctx context.Context) (int, error) {\n\tinv := sb.goCommandInvocation()\n\treturn gocommand.GoVersion(ctx, inv, &sb.goCommandRunner)\n}\n\n// Close removes all state associated with the sandbox.\nfunc (sb *Sandbox) Close() error {\n\tvar goCleanErr error\n\t// Careful: sb may not be fully initialized.\n\tif sb.gopath != \"\" && sb.Workdir != nil {\n\t\t// Important: run this command in RootDir so that it doesn't interact with\n\t\t// any toolchain downloads that may occur\n\t\t_, goCleanErr = sb.RunGoCommand(context.Background(), sb.RootDir(), \"clean\", []string{\"-modcache\"}, nil, false)\n\t}\n\terr := robustio.RemoveAll(sb.rootdir)\n\tif err != nil || goCleanErr != nil {\n\t\treturn fmt.Errorf(\"error(s) cleaning sandbox: cleaning modcache: %v; removing files: %v\", goCleanErr, err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/workdir.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/robustio\"\n)\n\n// RelativeTo is a helper for operations relative to a given directory.\ntype RelativeTo string\n\n// AbsPath returns an absolute filesystem path for the workdir-relative path.\nfunc (r RelativeTo) AbsPath(path string) string {\n\tfp := filepath.FromSlash(path)\n\tif filepath.IsAbs(fp) {\n\t\treturn fp\n\t}\n\treturn filepath.Join(string(r), filepath.FromSlash(path))\n}\n\n// RelPath returns a '/'-encoded path relative to the working directory (or an\n// absolute path if the file is outside of workdir)\nfunc (r RelativeTo) RelPath(fp string) string {\n\troot := string(r)\n\tif rel, err := filepath.Rel(root, fp); err == nil && !strings.HasPrefix(rel, \"..\") {\n\t\treturn filepath.ToSlash(rel)\n\t}\n\treturn filepath.ToSlash(fp)\n}\n\n// writeFileData writes content to the relative path, replacing the special\n// token $SANDBOX_WORKDIR with the relative root given by rel. It does not\n// trigger any file events.\nfunc writeFileData(path string, content []byte, rel RelativeTo) error {\n\tcontent = bytes.ReplaceAll(content, []byte(\"$SANDBOX_WORKDIR\"), []byte(rel))\n\tfp := rel.AbsPath(path)\n\tif err := os.MkdirAll(filepath.Dir(fp), 0755); err != nil {\n\t\treturn fmt.Errorf(\"creating nested directory: %w\", err)\n\t}\n\tbackoff := 1 * time.Millisecond\n\tfor {\n\t\terr := os.WriteFile(fp, content, 0644)\n\t\tif err != nil {\n\t\t\t// This lock file violation is not handled by the robustio package, as it\n\t\t\t// indicates a real race condition that could be avoided.\n\t\t\tif isWindowsErrLockViolation(err) {\n\t\t\t\ttime.Sleep(backoff)\n\t\t\t\tbackoff *= 2\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"writing %q: %w\", path, err)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// isWindowsErrLockViolation reports whether err is ERROR_LOCK_VIOLATION\n// on Windows.\nvar isWindowsErrLockViolation = func(error) bool { return false }\n\n// Workdir is a temporary working directory for tests. It exposes file\n// operations in terms of relative paths, and fakes file watching by triggering\n// events on file operations.\ntype Workdir struct {\n\tRelativeTo\n\n\twatcherMu sync.Mutex\n\twatchers  []func(context.Context, []protocol.FileEvent)\n\n\tfileMu sync.Mutex\n\t// File identities we know about, for the purpose of detecting changes.\n\t//\n\t// Since files is only used for detecting _changes_, we are tolerant of\n\t// fileIDs that may have hash and mtime coming from different states of the\n\t// file: if either are out of sync, then the next poll should detect a\n\t// discrepancy. It is OK if we detect too many changes, but not OK if we miss\n\t// changes.\n\t//\n\t// For that matter, this mechanism for detecting changes can still be flaky\n\t// on platforms where mtime is very coarse (such as older versions of WSL).\n\t// It would be much better to use a proper fs event library, but we can't\n\t// currently import those into x/tools.\n\t//\n\t// TODO(golang/go#52284): replace this polling mechanism with a\n\t// cross-platform library for filesystem notifications.\n\tfiles map[string]fileID\n}\n\n// NewWorkdir writes the txtar-encoded file data in txt to dir, and returns a\n// Workdir for operating on these files using relative paths.\nfunc NewWorkdir(dir string, files map[string][]byte) (*Workdir, error) {\n\tw := &Workdir{RelativeTo: RelativeTo(dir)}\n\tfor name, data := range files {\n\t\tif err := writeFileData(name, data, w.RelativeTo); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"writing to workdir: %w\", err)\n\t\t}\n\t}\n\t_, err := w.pollFiles() // poll files to populate the files map.\n\treturn w, err\n}\n\n// fileID identifies a file version on disk.\ntype fileID struct {\n\tmtime time.Time\n\thash  string // empty if mtime is old enough to be reliable; otherwise a file digest\n}\n\nfunc hashFile(data []byte) string {\n\treturn fmt.Sprintf(\"%x\", sha256.Sum256(data))\n}\n\n// RootURI returns the root URI for this working directory of this scratch\n// environment.\nfunc (w *Workdir) RootURI() protocol.DocumentURI {\n\treturn protocol.URIFromPath(string(w.RelativeTo))\n}\n\n// AddWatcher registers the given func to be called on any file change.\nfunc (w *Workdir) AddWatcher(watcher func(context.Context, []protocol.FileEvent)) {\n\tw.watcherMu.Lock()\n\tw.watchers = append(w.watchers, watcher)\n\tw.watcherMu.Unlock()\n}\n\n// URI returns the URI to a the workdir-relative path.\nfunc (w *Workdir) URI(path string) protocol.DocumentURI {\n\treturn protocol.URIFromPath(w.AbsPath(path))\n}\n\n// URIToPath converts a uri to a workdir-relative path (or an absolute path,\n// if the uri is outside of the workdir).\nfunc (w *Workdir) URIToPath(uri protocol.DocumentURI) string {\n\treturn w.RelPath(uri.Path())\n}\n\n// EntireFile returns the entire extent of the file named by the workdir-relative path.\nfunc (w *Workdir) EntireFile(path string) protocol.Location {\n\treturn protocol.Location{URI: w.URI(path)}\n}\n\n// ReadFile reads a text file specified by a workdir-relative path.\nfunc (w *Workdir) ReadFile(path string) ([]byte, error) {\n\tbackoff := 1 * time.Millisecond\n\tfor {\n\t\tb, err := os.ReadFile(w.AbsPath(path))\n\t\tif err != nil {\n\t\t\tif runtime.GOOS == \"plan9\" && strings.HasSuffix(err.Error(), \" exclusive use file already open\") {\n\t\t\t\t// Plan 9 enforces exclusive access to locked files.\n\t\t\t\t// Give the owner time to unlock it and retry.\n\t\t\t\ttime.Sleep(backoff)\n\t\t\t\tbackoff *= 2\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\treturn b, nil\n\t}\n}\n\n// RegexpSearch searches the file corresponding to path for the first position\n// matching re.\nfunc (w *Workdir) RegexpSearch(path string, re string) (protocol.Location, error) {\n\tcontent, err := w.ReadFile(path)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tmapper := protocol.NewMapper(w.URI(path), content)\n\treturn regexpLocation(mapper, re)\n}\n\n// RemoveFile removes a workdir-relative file path and notifies watchers of the\n// change.\nfunc (w *Workdir) RemoveFile(ctx context.Context, path string) error {\n\tfp := w.AbsPath(path)\n\tif err := robustio.RemoveAll(fp); err != nil {\n\t\treturn fmt.Errorf(\"removing %q: %w\", path, err)\n\t}\n\n\treturn w.CheckForFileChanges(ctx)\n}\n\n// WriteFiles writes the text file content to workdir-relative paths and\n// notifies watchers of the changes.\nfunc (w *Workdir) WriteFiles(ctx context.Context, files map[string]string) error {\n\tfor path, content := range files {\n\t\tfp := w.AbsPath(path)\n\t\t_, err := os.Stat(fp)\n\t\tif err != nil && !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"checking if %q exists: %w\", path, err)\n\t\t}\n\t\tif err := writeFileData(path, []byte(content), w.RelativeTo); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn w.CheckForFileChanges(ctx)\n}\n\n// WriteFile writes text file content to a workdir-relative path and notifies\n// watchers of the change.\nfunc (w *Workdir) WriteFile(ctx context.Context, path, content string) error {\n\treturn w.WriteFiles(ctx, map[string]string{path: content})\n}\n\n// RenameFile performs an on disk-renaming of the workdir-relative oldPath to\n// workdir-relative newPath, and notifies watchers of the changes.\n//\n// oldPath must either be a regular file or in the same directory as newPath.\nfunc (w *Workdir) RenameFile(ctx context.Context, oldPath, newPath string) error {\n\toldAbs := w.AbsPath(oldPath)\n\tnewAbs := w.AbsPath(newPath)\n\n\t// For os.Rename, “OS-specific restrictions may apply when oldpath and newpath\n\t// are in different directories.” If that applies here, we may fall back to\n\t// ReadFile, WriteFile, and RemoveFile to perform the rename non-atomically.\n\t//\n\t// However, the fallback path only works for regular files: renaming a\n\t// directory would be much more complex and isn't needed for our tests.\n\tfallbackOk := false\n\tif filepath.Dir(oldAbs) != filepath.Dir(newAbs) {\n\t\tfi, err := os.Stat(oldAbs)\n\t\tif err == nil && !fi.Mode().IsRegular() {\n\t\t\treturn &os.PathError{\n\t\t\t\tOp:   \"RenameFile\",\n\t\t\t\tPath: oldPath,\n\t\t\t\tErr:  fmt.Errorf(\"%w: file is not regular and not in the same directory as %s\", os.ErrInvalid, newPath),\n\t\t\t}\n\t\t}\n\t\tfallbackOk = true\n\t}\n\n\tvar renameErr error\n\tconst debugFallback = false\n\tif fallbackOk && debugFallback {\n\t\trenameErr = fmt.Errorf(\"%w: debugging fallback path\", os.ErrInvalid)\n\t} else {\n\t\trenameErr = robustio.Rename(oldAbs, newAbs)\n\t}\n\tif renameErr != nil {\n\t\tif !fallbackOk {\n\t\t\treturn renameErr // The OS-specific Rename restrictions do not apply.\n\t\t}\n\n\t\tcontent, err := w.ReadFile(oldPath)\n\t\tif err != nil {\n\t\t\t// If we can't even read the file, the error from Rename may be accurate.\n\t\t\treturn renameErr\n\t\t}\n\t\tfi, err := os.Stat(newAbs)\n\t\tif err == nil {\n\t\t\tif fi.IsDir() {\n\t\t\t\t// “If newpath already exists and is not a directory, Rename replaces it.”\n\t\t\t\t// But if it is a directory, maybe not?\n\t\t\t\treturn renameErr\n\t\t\t}\n\t\t\t// On most platforms, Rename replaces the named file with a new file,\n\t\t\t// rather than overwriting the existing file it in place. Mimic that\n\t\t\t// behavior here.\n\t\t\tif err := robustio.RemoveAll(newAbs); err != nil {\n\t\t\t\t// Maybe we don't have permission to replace newPath?\n\t\t\t\treturn renameErr\n\t\t\t}\n\t\t} else if !os.IsNotExist(err) {\n\t\t\t// If the destination path already exists or there is some problem with it,\n\t\t\t// the error from Rename may be accurate.\n\t\t\treturn renameErr\n\t\t}\n\t\tif writeErr := writeFileData(newPath, content, w.RelativeTo); writeErr != nil {\n\t\t\t// At this point we have tried to actually write the file.\n\t\t\t// If it still doesn't exist, assume that the error from Rename was accurate:\n\t\t\t// for example, maybe we don't have permission to create the new path.\n\t\t\t// Otherwise, return the error from the write, which may indicate some\n\t\t\t// other problem (such as a full disk).\n\t\t\tif _, statErr := os.Stat(newAbs); !os.IsNotExist(statErr) {\n\t\t\t\treturn writeErr\n\t\t\t}\n\t\t\treturn renameErr\n\t\t}\n\t\tif err := robustio.RemoveAll(oldAbs); err != nil {\n\t\t\t// If we failed to remove the old file, that may explain the Rename error too.\n\t\t\t// Make a best effort to back out the write to the new path.\n\t\t\trobustio.RemoveAll(newAbs) // ignore error\n\t\t\treturn renameErr\n\t\t}\n\t}\n\n\treturn w.CheckForFileChanges(ctx)\n}\n\n// ListFiles returns a new sorted list of the relative paths of files in dir,\n// recursively.\nfunc (w *Workdir) ListFiles(dir string) ([]string, error) {\n\tabsDir := w.AbsPath(dir)\n\tvar paths []string\n\tif err := filepath.Walk(absDir, func(fp string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif info.Mode()&(fs.ModeDir|fs.ModeSymlink) == 0 {\n\t\t\tpaths = append(paths, w.RelPath(fp))\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\tsort.Strings(paths)\n\treturn paths, nil\n}\n\n// CheckForFileChanges walks the working directory and checks for any files\n// that have changed since the last poll.\nfunc (w *Workdir) CheckForFileChanges(ctx context.Context) error {\n\tevts, err := w.pollFiles()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(evts) == 0 {\n\t\treturn nil\n\t}\n\tw.watcherMu.Lock()\n\twatchers := slices.Clone(w.watchers)\n\tw.watcherMu.Unlock()\n\tfor _, w := range watchers {\n\t\tw(ctx, evts)\n\t}\n\treturn nil\n}\n\n// pollFiles updates w.files and calculates FileEvents corresponding to file\n// state changes since the last poll. It does not call sendEvents.\nfunc (w *Workdir) pollFiles() ([]protocol.FileEvent, error) {\n\tw.fileMu.Lock()\n\tdefer w.fileMu.Unlock()\n\n\tnewFiles := make(map[string]fileID)\n\tvar evts []protocol.FileEvent\n\tif err := filepath.Walk(string(w.RelativeTo), func(fp string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// Skip directories and symbolic links (which may be links to directories).\n\t\t//\n\t\t// The latter matters for repos like Kubernetes, which use symlinks.\n\t\tif info.Mode()&(fs.ModeDir|fs.ModeSymlink) != 0 {\n\t\t\treturn nil\n\t\t}\n\n\t\t// Opt: avoid reading the file if mtime is sufficiently old to be reliable.\n\t\t//\n\t\t// If mtime is recent, it may not sufficiently identify the file contents:\n\t\t// a subsequent write could result in the same mtime. For these cases, we\n\t\t// must read the file contents.\n\t\tid := fileID{mtime: info.ModTime()}\n\t\tif time.Since(info.ModTime()) < 2*time.Second {\n\t\t\tdata, err := os.ReadFile(fp)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tid.hash = hashFile(data)\n\t\t}\n\t\tpath := w.RelPath(fp)\n\t\tnewFiles[path] = id\n\n\t\tif w.files != nil {\n\t\t\toldID, ok := w.files[path]\n\t\t\tdelete(w.files, path)\n\t\t\tswitch {\n\t\t\tcase !ok:\n\t\t\t\tevts = append(evts, protocol.FileEvent{\n\t\t\t\t\tURI:  w.URI(path),\n\t\t\t\t\tType: protocol.Created,\n\t\t\t\t})\n\t\t\tcase oldID != id:\n\t\t\t\tchanged := true\n\n\t\t\t\t// Check whether oldID and id do not match because oldID was polled at\n\t\t\t\t// a recent enough to time such as to require hashing.\n\t\t\t\t//\n\t\t\t\t// In this case, read the content to check whether the file actually\n\t\t\t\t// changed.\n\t\t\t\tif oldID.mtime.Equal(id.mtime) && oldID.hash != \"\" && id.hash == \"\" {\n\t\t\t\t\tdata, err := os.ReadFile(fp)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tif hashFile(data) == oldID.hash {\n\t\t\t\t\t\tchanged = false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif changed {\n\t\t\t\t\tevts = append(evts, protocol.FileEvent{\n\t\t\t\t\t\tURI:  w.URI(path),\n\t\t\t\t\t\tType: protocol.Changed,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Any remaining files must have been deleted.\n\tfor path := range w.files {\n\t\tevts = append(evts, protocol.FileEvent{\n\t\t\tURI:  w.URI(path),\n\t\t\tType: protocol.Deleted,\n\t\t})\n\t}\n\tw.files = newFiles\n\treturn evts, nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/workdir_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nconst sharedData = `\n-- go.mod --\ngo 1.12\n-- nested/README.md --\nHello World!\n`\n\n// newWorkdir sets up a temporary Workdir with the given txtar-encoded content.\n// It also configures an eventBuffer to receive file event notifications. These\n// notifications are sent synchronously for each operation, such that once a\n// workdir file operation has returned the caller can expect that any relevant\n// file notifications are present in the buffer.\n//\n// It is the caller's responsibility to call the returned cleanup function.\nfunc newWorkdir(t *testing.T, txt string) (*Workdir, *eventBuffer, func()) {\n\tt.Helper()\n\n\ttmpdir, err := os.MkdirTemp(\"\", \"goplstest-workdir-\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twd, err := NewWorkdir(tmpdir, UnpackTxt(txt))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcleanup := func() {\n\t\tif err := os.RemoveAll(tmpdir); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n\n\tbuf := new(eventBuffer)\n\twd.AddWatcher(buf.onEvents)\n\treturn wd, buf, cleanup\n}\n\n// eventBuffer collects events from a file watcher.\ntype eventBuffer struct {\n\tmu     sync.Mutex\n\tevents []protocol.FileEvent\n}\n\n// onEvents collects adds events to the buffer; to be used with Workdir.AddWatcher.\nfunc (c *eventBuffer) onEvents(_ context.Context, events []protocol.FileEvent) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tc.events = append(c.events, events...)\n}\n\n// take empties the buffer, returning its previous contents.\nfunc (c *eventBuffer) take() []protocol.FileEvent {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tevts := c.events\n\tc.events = nil\n\treturn evts\n}\n\nfunc TestWorkdir_ReadFile(t *testing.T) {\n\twd, _, cleanup := newWorkdir(t, sharedData)\n\tdefer cleanup()\n\n\tgot, err := wd.ReadFile(\"nested/README.md\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := \"Hello World!\\n\"\n\tif got := string(got); got != want {\n\t\tt.Errorf(\"reading workdir file, got %q, want %q\", got, want)\n\t}\n}\n\nfunc TestWorkdir_WriteFile(t *testing.T) {\n\twd, events, cleanup := newWorkdir(t, sharedData)\n\tdefer cleanup()\n\tctx := context.Background()\n\n\ttests := []struct {\n\t\tpath     string\n\t\twantType protocol.FileChangeType\n\t}{\n\t\t{\"data.txt\", protocol.Created},\n\t\t{\"nested/README.md\", protocol.Changed},\n\t}\n\n\tfor _, test := range tests {\n\t\tif err := wd.WriteFile(ctx, test.path, \"42\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tes := events.take()\n\t\tif got := len(es); got != 1 {\n\t\t\tt.Fatalf(\"len(events) = %d, want 1\", got)\n\t\t}\n\t\tpath := wd.URIToPath(es[0].URI)\n\t\tif path != test.path {\n\t\t\tt.Errorf(\"event path = %q, want %q\", path, test.path)\n\t\t}\n\t\tif es[0].Type != test.wantType {\n\t\t\tt.Errorf(\"event type = %v, want %v\", es[0].Type, test.wantType)\n\t\t}\n\t\tgot, err := wd.ReadFile(test.path)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twant := \"42\"\n\t\tif got := string(got); got != want {\n\t\t\tt.Errorf(\"ws.ReadFile(%q) = %q, want %q\", test.path, got, want)\n\t\t}\n\t}\n}\n\n// Test for file notifications following file operations.\nfunc TestWorkdir_FileWatching(t *testing.T) {\n\twd, events, cleanup := newWorkdir(t, \"\")\n\tdefer cleanup()\n\tctx := context.Background()\n\n\tmust := func(err error) {\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\ttype changeMap map[string]protocol.FileChangeType\n\tcheckEvent := func(wantChanges changeMap) {\n\t\tgotChanges := make(changeMap)\n\t\tfor _, e := range events.take() {\n\t\t\tgotChanges[wd.URIToPath(e.URI)] = e.Type\n\t\t}\n\t\tif diff := cmp.Diff(wantChanges, gotChanges); diff != \"\" {\n\t\t\tt.Errorf(\"mismatching file events (-want +got):\\n%s\", diff)\n\t\t}\n\t}\n\n\tmust(wd.WriteFile(ctx, \"foo.go\", \"package foo\"))\n\tcheckEvent(changeMap{\"foo.go\": protocol.Created})\n\n\tmust(wd.RenameFile(ctx, \"foo.go\", \"bar.go\"))\n\tcheckEvent(changeMap{\"foo.go\": protocol.Deleted, \"bar.go\": protocol.Created})\n\n\tmust(wd.RemoveFile(ctx, \"bar.go\"))\n\tcheckEvent(changeMap{\"bar.go\": protocol.Deleted})\n}\n\nfunc TestWorkdir_CheckForFileChanges(t *testing.T) {\n\tt.Skip(\"broken on darwin-amd64-10_12\")\n\twd, events, cleanup := newWorkdir(t, sharedData)\n\tdefer cleanup()\n\tctx := context.Background()\n\n\tcheckChange := func(wantPath string, wantType protocol.FileChangeType) {\n\t\tif err := wd.CheckForFileChanges(ctx); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tev := events.take()\n\t\tif len(ev) == 0 {\n\t\t\tt.Fatal(\"no file events received\")\n\t\t}\n\t\tgotEvt := ev[0]\n\t\tgotPath := wd.URIToPath(gotEvt.URI)\n\t\t// Only check relative path and Type\n\t\tif gotPath != wantPath || gotEvt.Type != wantType {\n\t\t\tt.Errorf(\"file events: got %v, want {Path: %s, Type: %v}\", gotEvt, wantPath, wantType)\n\t\t}\n\t}\n\t// Sleep some positive amount of time to ensure a distinct mtime.\n\tif err := writeFileData(\"go.mod\", []byte(\"module foo.test\\n\"), wd.RelativeTo); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcheckChange(\"go.mod\", protocol.Changed)\n\tif err := writeFileData(\"newFile\", []byte(\"something\"), wd.RelativeTo); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcheckChange(\"newFile\", protocol.Created)\n\tfp := wd.AbsPath(\"newFile\")\n\tif err := os.Remove(fp); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcheckChange(\"newFile\", protocol.Deleted)\n}\n\nfunc TestSplitModuleVersionPath(t *testing.T) {\n\ttests := []struct {\n\t\tpath                                string\n\t\twantModule, wantVersion, wantSuffix string\n\t}{\n\t\t{\"foo.com@v1.2.3/bar\", \"foo.com\", \"v1.2.3\", \"bar\"},\n\t\t{\"foo.com/module@v1.2.3/bar\", \"foo.com/module\", \"v1.2.3\", \"bar\"},\n\t\t{\"foo.com@v1.2.3\", \"foo.com\", \"v1.2.3\", \"\"},\n\t\t{\"std@v1.14.0\", \"std\", \"v1.14.0\", \"\"},\n\t\t{\"another/module/path\", \"another/module/path\", \"\", \"\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tmodule, version, suffix := splitModuleVersionPath(test.path)\n\t\tif module != test.wantModule || version != test.wantVersion || suffix != test.wantSuffix {\n\t\t\tt.Errorf(\"splitModuleVersionPath(%q) =\\n\\t(%q, %q, %q)\\nwant\\n\\t(%q, %q, %q)\",\n\t\t\t\ttest.path, module, version, suffix, test.wantModule, test.wantVersion, test.wantSuffix)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/fake/workdir_windows.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake\n\nimport (\n\t\"errors\"\n\t\"syscall\"\n)\n\nfunc init() {\n\t// constants copied from GOROOT/src/internal/syscall/windows/syscall_windows.go\n\tconst (\n\t\tERROR_LOCK_VIOLATION syscall.Errno = 33\n\t)\n\n\tisWindowsErrLockViolation = func(err error) bool {\n\t\treturn errors.Is(err, ERROR_LOCK_VIOLATION)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/hover/hover_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage hover\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\n// TestIssue77675 verifies that hovering over a raw string literal containing\n// Windows line endings (\\r\\n) does not cause an out-of-bounds panic.\nfunc TestIssue77675(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.20\n\n-- main.go --\npackage main\n\nfunc _() {\n    _ = ` + \"`\" + `foo\n\nbar\nbaz` + \"`\" + `\n}\n`\n\tWithOptions(\n\t\tWindowsLineEndings(),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.RegexpSearch(\"main.go\", \"baz()\")\n\t\tcontent, l := env.Hover(loc)\n\t\tif !l.Empty() {\n\t\t\tt.Errorf(\"hover expect empty range got: %v\", l)\n\t\t}\n\t\tif content != nil {\n\t\t\tt.Errorf(\"hover expect empty result got: %v\", content)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/inlayhints/inlayhints_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage inlayhint\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nfunc TestEnablingInlayHints(t *testing.T) {\n\tconst workspace = `\n-- go.mod --\nmodule inlayHint.test\ngo 1.12\n-- lib.go --\npackage lib\ntype Number int\nconst (\n\tZero Number = iota\n\tOne\n\tTwo\n)\n`\n\ttests := []struct {\n\t\tlabel         string\n\t\tenabled       map[string]bool\n\t\twantInlayHint bool\n\t}{\n\t\t{\n\t\t\tlabel:         \"default\",\n\t\t\twantInlayHint: false,\n\t\t},\n\t\t{\n\t\t\tlabel:         \"enable const\",\n\t\t\tenabled:       map[string]bool{string(settings.ConstantValues): true},\n\t\t\twantInlayHint: true,\n\t\t},\n\t\t{\n\t\t\tlabel:         \"enable parameter names\",\n\t\t\tenabled:       map[string]bool{string(settings.ParameterNames): true},\n\t\t\twantInlayHint: false,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tSettings{\n\t\t\t\t\t\"hints\": test.enabled,\n\t\t\t\t},\n\t\t\t).Run(t, workspace, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"lib.go\")\n\t\t\t\tlens := env.InlayHints(\"lib.go\")\n\t\t\t\tif gotInlayHint := len(lens) > 0; gotInlayHint != test.wantInlayHint {\n\t\t\t\t\tt.Errorf(\"got inlayHint: %t, want %t\", gotInlayHint, test.wantInlayHint)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/addtest_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestAddTest is a basic test of interaction with the \"gopls.add_test\" code action.\nfunc TestAddTest(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nimport(\n\t\"context\"\n)\n\nfunc Foo(ctx context.Context, in string) string {return in}\n\n-- a/a_test.go --\npackage a_test\n\nimport(\n\t\"testing\"\n)\n\nfunc TestExisting(t *testing.T) {}\n`\n\tconst want = `package a_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"example.com/a\"\n)\n\nfunc TestExisting(t *testing.T) {}\n\nfunc TestFoo(t *testing.T) {\n\ttests := []struct {\n\t\tname string // description of this test case\n\t\t// Named input parameters for target function.\n\t\tin   string\n\t\twant string\n\t}{\n\t\t// TODO: Add test cases.\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot := a.Foo(context.Background(), tt.in)\n\t\t\t// TODO: update the condition below to compare got with tt.want.\n\t\t\tif true {\n\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\tloc := env.RegexpSearch(\"a/a.go\", \"Foo\")\n\t\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"CodeAction: %v\", err)\n\t\t}\n\t\taction, err := CodeActionByKind(actions, settings.AddTest)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\taction, err = env.Editor.ResolveCodeAction(env.Ctx, action)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Execute the command.\n\t\t// Its side effect should be a single showDocument request.\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   action.Command.Command,\n\t\t\tArguments: action.Command.Arguments,\n\t\t}\n\n\t\tlisten := env.Awaiter.ListenToShownDocuments()\n\t\tenv.ExecuteCommand(params, nil)\n\t\t// Wait until we finish writing to the file.\n\t\tenv.AfterChange()\n\t\tif got := env.BufferText(\"a/a_test.go\"); got != want {\n\t\t\tt.Errorf(\"gopls.add_test returned unexpected diff (-want +got):\\n%s\", compare.Text(want, got))\n\t\t}\n\n\t\tgot := listen()\n\t\tif len(got) != 1 {\n\t\t\tt.Errorf(\"gopls.add_test: got %d showDocument requests, want 1: %v\", len(got), got)\n\t\t} else {\n\t\t\tif want := protocol.URI(env.Sandbox.Workdir.URI(\"a/a_test.go\")); got[0].URI != want {\n\t\t\t\tt.Errorf(\"gopls.add_test: got showDocument requests for %v, want %v\", got[0].URI, want)\n\t\t\t}\n\n\t\t\t// Pointing to the line of test function declaration.\n\t\t\tif want := (protocol.Range{\n\t\t\t\tStart: protocol.Position{\n\t\t\t\t\tLine: 11,\n\t\t\t\t},\n\t\t\t\tEnd: protocol.Position{\n\t\t\t\t\tLine: 11,\n\t\t\t\t},\n\t\t\t}); *got[0].Selection != want {\n\t\t\t\tt.Errorf(\"gopls.add_test: got showDocument requests selection for %v, want %v\", *got[0].Selection, want)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/call_hierarchy_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test for golang/go#49125\nfunc TestCallHierarchy_Issue49125(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- p.go --\npackage pkg\n`\n\t// TODO(rfindley): this could probably just be a marker test.\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tloc := env.RegexpSearch(\"p.go\", \"pkg\")\n\n\t\tvar params protocol.CallHierarchyPrepareParams\n\t\tparams.TextDocument.URI = loc.URI\n\t\tparams.Position = loc.Range.Start\n\n\t\t// Check that this doesn't panic.\n\t\tenv.Editor.Server.PrepareCallHierarchy(env.Ctx, &params)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/codeactions_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// This test exercises the filtering of code actions in generated files.\n// Most code actions, being potential edits, are discarded, but\n// some (GoTest, GoDoc) are pure queries, and so are allowed.\nfunc TestCodeActionsInGeneratedFiles(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.19\n\n-- src/a.go --\npackage a\n\nfunc f() { g() }\nfunc g() {}\n-- gen/a.go --\n// Code generated by hand; DO NOT EDIT.\npackage a\n\nfunc f() { g() }\nfunc g() {}\n\n-- issue72742/a.go --\npackage main\n\nfunc main(){\n\tfmt.Println(\"helloworld\")\n}\n`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tcheck := func(filename string, re string, want []protocol.CodeActionKind) {\n\t\t\tenv.OpenFile(filename)\n\t\t\tloc := env.RegexpSearch(filename, re)\n\t\t\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\ttype kinds = []protocol.CodeActionKind\n\t\t\tgot := make(kinds, 0)\n\t\t\tfor _, act := range actions {\n\t\t\t\tgot = append(got, act.Kind)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"%s: unexpected CodeActionKinds: (-want +got):\\n%s\",\n\t\t\t\t\tfilename, diff)\n\t\t\t\tt.Log(actions)\n\t\t\t}\n\t\t}\n\n\t\tcheck(\"src/a.go\", `g\\(\\)`, []protocol.CodeActionKind{\n\t\t\tsettings.AddTest,\n\t\t\tsettings.GoAssembly,\n\t\t\tsettings.GoDoc,\n\t\t\tsettings.GoFreeSymbols,\n\t\t\tsettings.GoSplitPackage,\n\t\t\tsettings.GoToggleCompilerOptDetails,\n\t\t\tsettings.RefactorInlineCall,\n\t\t\tsettings.GoplsDocFeatures,\n\t\t})\n\n\t\tcheck(\"gen/a.go\", `g\\(\\)`, []protocol.CodeActionKind{\n\t\t\tsettings.GoAssembly,\n\t\t\tsettings.GoDoc,\n\t\t\tsettings.GoFreeSymbols,\n\t\t\tsettings.GoSplitPackage,\n\t\t\tsettings.GoToggleCompilerOptDetails,\n\t\t\tsettings.GoplsDocFeatures,\n\t\t})\n\n\t\tcheck(\"issue72742/a.go\", `fmt`, []protocol.CodeActionKind{\n\t\t\tsettings.OrganizeImports,\n\t\t\tsettings.AddTest,\n\t\t\tsettings.GoAssembly,\n\t\t\tsettings.GoDoc,\n\t\t\tsettings.GoFreeSymbols,\n\t\t\tsettings.GoSplitPackage,\n\t\t\tsettings.GoToggleCompilerOptDetails,\n\t\t\tsettings.GoplsDocFeatures,\n\t\t})\n\t})\n}\n\n// Test refactor.inline.call is not included in automatically triggered code action\n// unless users want refactoring.\n//\n// (The mechanism behind this behavior has changed. It was added when\n// we used to interpret CodeAction(Only=[]) as \"all kinds\", which was\n// a distracting nuisance (too many lightbulbs); this was fixed by\n// adding special logic to refactor.inline.call to respect the trigger\n// kind; but now we do this for all actions (for similar reasons) and\n// interpret Only=[] as Only=[quickfix] unless triggerKind=invoked;\n// except that the test client always requests CodeAction(Only=[\"\"]).\n// So, we should remove the special logic from refactorInlineCall\n// and vary the Only parameter used by the test client.)\nfunc TestVSCodeIssue65167(t *testing.T) {\n\tconst vim1 = `package main\n\nfunc main() {\n\tFunc()  // range to be selected\n}\n\nfunc Func() int { return 0 }\n`\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", vim1)\n\t\tfor _, trigger := range []protocol.CodeActionTriggerKind{\n\t\t\tprotocol.CodeActionUnknownTrigger,\n\t\t\tprotocol.CodeActionInvoked,\n\t\t\tprotocol.CodeActionAutomatic,\n\t\t} {\n\t\t\tt.Run(fmt.Sprintf(\"trigger=%v\", trigger), func(t *testing.T) {\n\t\t\t\tfor _, selectedRange := range []bool{false, true} {\n\t\t\t\t\tt.Run(fmt.Sprintf(\"range=%t\", selectedRange), func(t *testing.T) {\n\t\t\t\t\t\tloc := env.RegexpSearch(\"main.go\", \"Func\")\n\t\t\t\t\t\tif !selectedRange {\n\t\t\t\t\t\t\t// assume the cursor is placed at the beginning of `Func`, so end==start.\n\t\t\t\t\t\t\tloc.Range.End = loc.Range.Start\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactions := env.CodeAction(loc, nil, trigger)\n\t\t\t\t\t\twant := trigger != protocol.CodeActionAutomatic || selectedRange\n\t\t\t\t\t\tif got := slices.ContainsFunc(actions, func(act protocol.CodeAction) bool {\n\t\t\t\t\t\t\treturn act.Kind == settings.RefactorInlineCall\n\t\t\t\t\t\t}); got != want {\n\t\t\t\t\t\t\tt.Errorf(\"got refactor.inline.call = %t, want %t\", got, want)\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}\n\n// TestDescendingRange isn't really a test of CodeAction at all: it\n// merely tests the response of the server to any (start, end) range\n// that is descending. See #74394.\nfunc TestDescendingRange(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.19\n\n-- a/a.go --\npackage a\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tloc := env.RegexpSearch(\"a/a.go\", \"package\")\n\t\trng := &loc.Range\n\t\trng.Start, rng.End = rng.End, rng.Start\n\t\t_, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\tgot, wantSubstr := fmt.Sprint(err), \"start (offset 7) > end (offset 0)\"\n\t\tif !strings.Contains(got, wantSubstr) {\n\t\t\tt.Fatalf(\"CodeAction error: got %q, want substring %q\", got, wantSubstr)\n\t\t}\n\t})\n}\n\n// TestIssue76235 is a regression test for a crash in CodeAction\n// (refactor.extract.variable-all). It can't be a marker test since\n// the fixed behavior is a no-op: no code actions, no crash.\nfunc TestIssue76235(t *testing.T) {\n\tconst src = `\n-- a/a.go --\npackage a; func f([3]int)\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tloc := env.RegexpSearch(\"a/a.go\", \"3\")\n\t\tenv.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger) // ignore error\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/compileropt_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestCompilerOptDetails exercises the \"{Show,Hide} compiler optimization details\" code action.\nfunc TestCompilerOptDetails(t *testing.T) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the compiler optimization details code action doesn't work on Android\")\n\t}\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(42)\n}\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tactions := env.CodeActionForFile(\"main.go\", nil)\n\n\t\t// Execute the \"Show compiler optimization details\" command.\n\t\tdocAction, err := CodeActionByKind(actions, settings.GoToggleCompilerOptDetails)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   docAction.Command.Command,\n\t\t\tArguments: docAction.Command.Arguments,\n\t\t}\n\t\tenv.ExecuteCommand(params, nil)\n\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromToggleCompilerOptDetails), 1, true),\n\t\t\tDiagnostics(\n\t\t\t\tForFile(\"main.go\"),\n\t\t\t\tAtPosition(\"main.go\", 5, 13), // (LSP coordinates)\n\t\t\t\tWithMessage(\"42 escapes\"),\n\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t),\n\t\t)\n\n\t\t// Diagnostics should be reported even on unsaved\n\t\t// edited buffers, thanks to the magic of overlays.\n\t\tenv.SetBufferContent(\"main.go\", `\npackage main\nfunc main() { _ = f }\nfunc f(x int) *int { return &x }`)\n\t\tenv.AfterChange(Diagnostics(\n\t\t\tForFile(\"main.go\"),\n\t\t\tWithMessage(\"x escapes\"),\n\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t))\n\n\t\t// Toggle the flag again so now it should be off.\n\t\tenv.ExecuteCommand(params, nil)\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromToggleCompilerOptDetails), 2, true),\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// TestCompilerOptDetails_perDirectory exercises that the \"want\n// optimization details\" flag has per-directory cardinality.\nfunc TestCompilerOptDetails_perDirectory(t *testing.T) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the compiler optimization details code action doesn't work on Android\")\n\t}\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc F(x int) any { return &x }\n\n-- a/a_test.go --\npackage a\n\nfunc G(x int) any { return &x }\n\n-- a/a_x_test.go --\npackage a_test\n\nfunc H(x int) any { return &x }\n`\n\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\t// toggle executes the \"Toggle compiler optimization details\"\n\t\t// command within a file, and asserts that it has the specified title.\n\t\ttoggle := func(filename, wantTitle string) {\n\t\t\tenv.OpenFile(filename)\n\t\t\tactions := env.CodeActionForFile(filename, nil)\n\n\t\t\tdocAction, err := CodeActionByKind(actions, settings.GoToggleCompilerOptDetails)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif docAction.Title != wantTitle {\n\t\t\t\tt.Errorf(\"CodeAction.Title = %q, want %q\", docAction.Title, wantTitle)\n\t\t\t}\n\t\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\t\tCommand:   docAction.Command.Command,\n\t\t\t\tArguments: docAction.Command.Arguments,\n\t\t\t}\n\t\t\tenv.ExecuteCommand(params, nil)\n\t\t}\n\n\t\t// Show diagnostics for directory a/ from one file.\n\t\t// Diagnostics are reported for all three packages.\n\t\ttoggle(\"a/a.go\", `Show compiler optimization details for \"a\"`)\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromToggleCompilerOptDetails), 1, true),\n\t\t\tDiagnostics(\n\t\t\t\tForFile(\"a/a.go\"),\n\t\t\t\tAtPosition(\"a/a.go\", 2, 7),\n\t\t\t\tWithMessage(\"x escapes to heap\"),\n\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t),\n\t\t\tDiagnostics(\n\t\t\t\tForFile(\"a/a_test.go\"),\n\t\t\t\tAtPosition(\"a/a_test.go\", 2, 7),\n\t\t\t\tWithMessage(\"x escapes to heap\"),\n\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t),\n\t\t\tDiagnostics(\n\t\t\t\tForFile(\"a/a_x_test.go\"),\n\t\t\t\tAtPosition(\"a/a_x_test.go\", 2, 7),\n\t\t\t\tWithMessage(\"x escapes to heap\"),\n\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t),\n\t\t)\n\n\t\t// Hide diagnostics for the directory from a different file.\n\t\t// All diagnostics disappear.\n\t\ttoggle(\"a/a_test.go\", `Hide compiler optimization details for \"a\"`)\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromToggleCompilerOptDetails), 2, true),\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"a/a_test.go\")),\n\t\t\tNoDiagnostics(ForFile(\"a/a_x_test.go\")),\n\t\t)\n\t})\n}\n\n// TestCompilerOptDetails_config exercises that the \"want optimization\n// details\" flag honors the \"annotation\" configuration setting.\nfunc TestCompilerOptDetails_config(t *testing.T) {\n\tif runtime.GOOS == \"android\" {\n\t\tt.Skipf(\"the compiler optimization details code action doesn't work on Android\")\n\t}\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc F(x int) any { return &x         } // escape(x escapes to heap)\nfunc G()          { defer func(){} () } // cannotInlineFunction(unhandled op DEFER)\n`\n\n\tfor _, escape := range []bool{true, false} {\n\t\tWithOptions(\n\t\t\tSettings{\"annotations\": map[string]any{\"inline\": true, \"escape\": escape}},\n\t\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\tactions := env.CodeActionForFile(\"a/a.go\", nil)\n\n\t\t\tdocAction, err := CodeActionByKind(actions, settings.GoToggleCompilerOptDetails)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\t\tCommand:   docAction.Command.Command,\n\t\t\t\tArguments: docAction.Command.Arguments,\n\t\t\t}\n\t\t\tenv.ExecuteCommand(params, nil)\n\n\t\t\tenv.OnceMet(\n\t\t\t\tCompletedWork(server.DiagnosticWorkTitle(server.FromToggleCompilerOptDetails), 1, true),\n\t\t\t\tcond(escape, Diagnostics, NoDiagnostics)(\n\t\t\t\t\tForFile(\"a/a.go\"),\n\t\t\t\t\tAtPosition(\"a/a.go\", 2, 7),\n\t\t\t\t\tWithMessage(\"x escapes to heap\"),\n\t\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t\t),\n\t\t\t\tDiagnostics(\n\t\t\t\t\tForFile(\"a/a.go\"),\n\t\t\t\t\tAtPosition(\"a/a.go\", 3, 5),\n\t\t\t\t\tWithMessage(\"cannotInlineFunction(unhandled op DEFER)\"),\n\t\t\t\t\tWithSeverityTags(\"optimizer details\", protocol.SeverityInformation, nil),\n\t\t\t\t),\n\t\t\t)\n\t\t})\n\t}\n}\n\nfunc cond[T any](cond bool, x, y T) T {\n\tif cond {\n\t\treturn x\n\t} else {\n\t\treturn y\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/configuration_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// Test that enabling and disabling produces the expected results of showing\n// and hiding staticcheck analysis results.\nfunc TestChangeConfiguration(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nimport \"errors\"\n\n// FooErr should be called ErrFoo (ST1012)\nvar FooErr = errors.New(\"foo\")\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t\tcfg := env.Editor.Config()\n\t\tcfg.Settings = map[string]any{\n\t\t\t\"staticcheck\": true,\n\t\t}\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"var (FooErr)\")),\n\t\t)\n\t})\n}\n\nfunc TestIdenticalConfiguration(t *testing.T) {\n\t// This test checks that changing configuration does not cause views to be\n\t// recreated if there is no configuration change.\n\tconst files = `\n-- a.go --\npackage p\n\nfunc _() {\n\tvar x *int\n\ty := *x\n\t_ = y\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t// Sanity check: before disabling the nilness analyzer, we should have a\n\t\t// diagnostic for the nil dereference.\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tForFile(\"a.go\"),\n\t\t\t\tWithMessage(\"nil dereference\"),\n\t\t\t),\n\t\t)\n\n\t\t// Collect the view ID before changing configuration.\n\t\tviewID := func() string {\n\t\t\tt.Helper()\n\t\t\tviews := env.Views()\n\t\t\tif len(views) != 1 {\n\t\t\t\tt.Fatalf(\"got %d views, want 1\", len(views))\n\t\t\t}\n\t\t\treturn views[0].ID\n\t\t}\n\t\tbefore := viewID()\n\n\t\t// Now disable the nilness analyzer.\n\t\tcfg := env.Editor.Config()\n\t\tcfg.Settings = map[string]any{\n\t\t\t\"analyses\": map[string]any{\n\t\t\t\t\"nilness\": false,\n\t\t\t},\n\t\t}\n\n\t\t// This should cause the diagnostic to disappear...\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(),\n\t\t)\n\t\t// ...and we should be on the second view.\n\t\tafter := viewID()\n\t\tif after == before {\n\t\t\tt.Errorf(\"after configuration change, got view %q (same as before), want new view\", after)\n\t\t}\n\n\t\t// Now change configuration again, this time with the same configuration as\n\t\t// before. We should still have no diagnostics...\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(),\n\t\t)\n\t\t// ...and we should still be on the second view.\n\t\tif got := viewID(); got != after {\n\t\t\tt.Errorf(\"after second configuration change, got view %q, want %q\", got, after)\n\t\t}\n\t})\n}\n\n// Test that clients can configure per-workspace configuration, which is\n// queried via the scopeURI of a workspace/configuration request.\n// (this was broken in golang/go#65519).\nfunc TestWorkspaceConfiguration(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com/config\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"example.com/config/b\"\n\nfunc _() {\n\t_ = b.B{2}\n}\n\n-- b/b.go --\npackage b\n\ntype B struct {\n\tF int\n}\n`\n\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\"),\n\t\tFolderSettings{\n\t\t\t\"a\": {\n\t\t\t\t\"analyses\": map[string]bool{\n\t\t\t\t\t\"composites\": false,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n\n// TestMajorOptionsChange is like TestChangeConfiguration, but modifies an\n// an open buffer before making a major (but inconsequential) change that\n// causes gopls to recreate the view.\n//\n// Gopls should not get confused about buffer content when recreating the view.\nfunc TestMajorOptionsChange(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nimport \"errors\"\n\nvar ErrFoo = errors.New(\"foo\")\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\t// Introduce a staticcheck diagnostic. It should be detected when we enable\n\t\t// staticcheck later.\n\t\tenv.RegexpReplace(\"a/a.go\", \"ErrFoo\", \"FooErr\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t\tcfg := env.Editor.Config()\n\t\t// Any change to environment recreates the view, but this should not cause\n\t\t// gopls to get confused about the content of a/a.go: we should get the\n\t\t// staticcheck diagnostic below.\n\t\tcfg.Env = map[string]string{\n\t\t\t\"AN_ARBITRARY_VAR\": \"FOO\",\n\t\t}\n\t\tcfg.Settings = map[string]any{\n\t\t\t\"staticcheck\": true,\n\t\t}\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"var (FooErr)\")),\n\t\t)\n\t})\n}\n\nfunc TestStaticcheckWarning(t *testing.T) {\n\t// Note: keep this in sync with TestChangeConfiguration.\n\ttestenv.SkipAfterGo1Point(t, 19)\n\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nimport \"errors\"\n\n// FooErr should be called ErrFoo (ST1012)\nvar FooErr = errors.New(\"foo\")\n`\n\n\tWithOptions(\n\t\tSettings{\"staticcheck\": true},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tShownMessage(\"staticcheck is not supported\"),\n\t\t)\n\t})\n}\n\nfunc TestDeprecatedSettings(t *testing.T) {\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"experimentalUseInvalidMetadata\": true,\n\t\t\t\"experimentalWatchedFileDelay\":   \"1s\",\n\t\t\t\"experimentalWorkspaceModule\":    true,\n\t\t\t\"tempModfile\":                    true,\n\t\t\t\"allowModfileModifications\":      true,\n\t\t\t\"allowImplicitNetworkAccess\":     true,\n\t\t},\n\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tShownMessage(\"experimentalWorkspaceModule\"),\n\t\t\tShownMessage(\"experimentalUseInvalidMetadata\"),\n\t\t\tShownMessage(\"experimentalWatchedFileDelay\"),\n\t\t\tShownMessage(\"tempModfile\"),\n\t\t\tShownMessage(\"allowModfileModifications\"),\n\t\t\tShownMessage(\"allowImplicitNetworkAccess\"),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/debugserver_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestStartDebugging(t *testing.T) {\n\tWithOptions(\n\t\tModes(Forwarded),\n\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\targs, err := command.MarshalArgs(command.DebuggingArgs{})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.StartDebugging.String(),\n\t\t\tArguments: args,\n\t\t}\n\t\tvar result command.DebuggingResult\n\t\tenv.ExecuteCommand(params, &result)\n\t\tif got, want := len(result.URLs), 2; got != want {\n\t\t\tt.Fatalf(\"got %d urls, want %d; urls: %#v\", got, want, result.URLs)\n\t\t}\n\t\tfor i, u := range result.URLs {\n\t\t\tresp, err := http.Get(u)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"getting url #%d (%q): %v\", i, u, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\t\t\tif got, want := resp.StatusCode, http.StatusOK; got != want {\n\t\t\t\tt.Errorf(\"debug server #%d returned HTTP %d, want %d\", i, got, want)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/definition_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nconst internalDefinition = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(message)\n}\n-- const.go --\npackage main\n\nconst message = \"Hello World.\"\n`\n\nfunc TestGoToInternalDefinition(t *testing.T) {\n\tRun(t, internalDefinition, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", \"message\"))\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"const.go\"; name != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t\tif want := env.RegexpSearch(\"const.go\", \"message\"); loc != want {\n\t\t\tt.Errorf(\"Definition: got location %v, want %v\", loc, want)\n\t\t}\n\t})\n}\n\nconst linknameDefinition = `\n-- go.mod --\nmodule mod.com\n\n-- upper/upper.go --\npackage upper\n\nimport (\n\t_ \"unsafe\"\n\n\t_ \"mod.com/middle\"\n)\n\n//go:linkname foo mod.com/lower.bar\nfunc foo() string\n\n-- middle/middle.go --\npackage middle\n\nimport (\n\t_ \"mod.com/lower\"\n)\n\n-- lower/lower.s --\n\n-- lower/lower.go --\npackage lower\n\nfunc bar() string {\n\treturn \"bar as foo\"\n}`\n\nfunc TestGoToLinknameDefinition(t *testing.T) {\n\tRun(t, linknameDefinition, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"upper/upper.go\")\n\n\t\t// Jump from directives 2nd arg.\n\t\tstart := env.RegexpSearch(\"upper/upper.go\", `lower.bar`)\n\t\tloc := env.FirstDefinition(start)\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"lower/lower.go\"; name != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t\tif want := env.RegexpSearch(\"lower/lower.go\", `bar`); loc != want {\n\t\t\tt.Errorf(\"Definition: got position %v, want %v\", loc, want)\n\t\t}\n\t})\n}\n\nconst linknameDefinitionReverse = `\n-- go.mod --\nmodule mod.com\n\n-- upper/upper.s --\n\n-- upper/upper.go --\npackage upper\n\nimport (\n\t_ \"mod.com/middle\"\n)\n\nfunc foo() string\n\n-- middle/middle.go --\npackage middle\n\nimport (\n\t_ \"mod.com/lower\"\n)\n\n-- lower/lower.go --\npackage lower\n\nimport _ \"unsafe\"\n\n//go:linkname bar mod.com/upper.foo\nfunc bar() string {\n\treturn \"bar as foo\"\n}`\n\nfunc TestGoToLinknameDefinitionInReverseDep(t *testing.T) {\n\tRun(t, linknameDefinitionReverse, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lower/lower.go\")\n\n\t\t// Jump from directives 2nd arg.\n\t\tstart := env.RegexpSearch(\"lower/lower.go\", `upper.foo`)\n\t\tloc := env.FirstDefinition(start)\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"upper/upper.go\"; name != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t\tif want := env.RegexpSearch(\"upper/upper.go\", `foo`); loc != want {\n\t\t\tt.Errorf(\"Definition: got position %v, want %v\", loc, want)\n\t\t}\n\t})\n}\n\n// The linkname directive connects two packages not related in the import graph.\nconst linknameDefinitionDisconnected = `\n-- go.mod --\nmodule mod.com\n\n-- a/a.go --\npackage a\n\nimport (\n\t_ \"unsafe\"\n)\n\n//go:linkname foo mod.com/b.bar\nfunc foo() string\n\n-- b/b.go --\npackage b\n\nfunc bar() string {\n\treturn \"bar as foo\"\n}`\n\nfunc TestGoToLinknameDefinitionDisconnected(t *testing.T) {\n\tRun(t, linknameDefinitionDisconnected, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\t// Jump from directives 2nd arg.\n\t\tstart := env.RegexpSearch(\"a/a.go\", `b.bar`)\n\t\tloc := env.FirstDefinition(start)\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"b/b.go\"; name != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t\tif want := env.RegexpSearch(\"b/b.go\", `bar`); loc != want {\n\t\t\tt.Errorf(\"Definition: got position %v, want %v\", loc, want)\n\t\t}\n\t})\n}\n\nconst stdlibDefinition = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Printf()\n}`\n\nfunc TestGoToStdlibDefinition_Issue37045(t *testing.T) {\n\tRun(t, stdlibDefinition, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `fmt.(Printf)`))\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif got, want := path.Base(name), \"print.go\"; got != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t\tenv.OpenFile(name)\n\n\t\t// Test that we can jump to definition from outside our workspace.\n\t\t// See golang.org/issues/37045.\n\t\tnewLoc := env.FirstDefinition(loc)\n\t\tnewName := env.Sandbox.Workdir.URIToPath(newLoc.URI)\n\t\tif newName != name {\n\t\t\tt.Errorf(\"Definition is not idempotent: got %q, want %q\", newName, name)\n\t\t}\n\t\tif newLoc != loc {\n\t\t\tt.Errorf(\"Definition is not idempotent: got %v, want %v\", newLoc, loc)\n\t\t}\n\t})\n}\n\nfunc TestUnexportedStdlib_Issue40809(t *testing.T) {\n\tRun(t, stdlibDefinition, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `fmt.(Printf)`))\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tenv.OpenFile(name)\n\n\t\tloc = env.RegexpSearch(name, `:=\\s*(newPrinter)\\(\\)`)\n\n\t\t// Check that we can find references on a reference\n\t\trefs := env.References(loc)\n\t\tif len(refs) < 5 {\n\t\t\tt.Errorf(\"expected 5+ references to newPrinter, found: %#v\", refs)\n\t\t}\n\n\t\tloc = env.FirstDefinition(loc)\n\t\tcontent, _ := env.Hover(loc)\n\t\tif !strings.Contains(content.Value, \"newPrinter\") {\n\t\t\tt.Fatal(\"definition of newPrinter went to the incorrect place\")\n\t\t}\n\t\t// And on the definition too.\n\t\trefs = env.References(loc)\n\t\tif len(refs) < 5 {\n\t\t\tt.Errorf(\"expected 5+ references to newPrinter, found: %#v\", refs)\n\t\t}\n\t})\n}\n\n// Test the hover on an error's Error function.\n// This can't be done via the marker tests because Error is a builtin.\nfunc TestHoverOnError(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n\tvar err error\n\terr.Error()\n}`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tcontent, _ := env.Hover(env.RegexpSearch(\"main.go\", \"Error\"))\n\t\tif content == nil {\n\t\t\tt.Fatalf(\"nil hover content for Error\")\n\t\t}\n\t\twant := \"```go\\nfunc (error).Error() string\\n```\"\n\t\tif content.Value != want {\n\t\t\tt.Fatalf(\"hover failed:\\n%s\", compare.Text(want, content.Value))\n\t\t}\n\t})\n}\n\nfunc TestImportShortcut(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {}\n`\n\tfor _, tt := range []struct {\n\t\twantLinks      int\n\t\timportShortcut string\n\t}{\n\t\t{1, \"Link\"},\n\t\t{0, \"Definition\"},\n\t\t{1, \"Both\"},\n\t} {\n\t\tt.Run(tt.importShortcut, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tSettings{\"importShortcut\": tt.importShortcut},\n\t\t\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"main.go\")\n\t\t\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `\"fmt\"`))\n\t\t\t\tif loc == (protocol.Location{}) {\n\t\t\t\t\tt.Fatalf(\"expected definition, got none\")\n\t\t\t\t}\n\t\t\t\tlinks := env.DocumentLink(\"main.go\")\n\t\t\t\tif len(links) != tt.wantLinks {\n\t\t\t\t\tt.Fatalf(\"expected %v links, got %v\", tt.wantLinks, len(links))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Test for golang/go#47825.\nfunc TestImportTestVariant(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- client/test/role.go --\npackage test\n\nimport _ \"mod.com/client\"\n\ntype RoleSetup struct{}\n-- client/client_role_test.go --\npackage client_test\n\nimport (\n\t\"testing\"\n\t_ \"mod.com/client\"\n\tctest \"mod.com/client/test\"\n)\n\nfunc TestClient(t *testing.T) {\n\t_ = ctest.RoleSetup{}\n}\n-- client/client_test.go --\npackage client\n\nimport \"testing\"\n\nfunc TestClient(t *testing.T) {}\n-- client.go --\npackage client\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"client/client_role_test.go\")\n\t\tenv.FirstDefinition(env.RegexpSearch(\"client/client_role_test.go\", \"RoleSetup\"))\n\t})\n}\n\n// This test exercises a crashing pattern from golang/go#49223.\nfunc TestGoToCrashingDefinition_Issue49223(t *testing.T) {\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tparams := &protocol.DefinitionParams{}\n\t\tparams.TextDocument.URI = protocol.DocumentURI(\"fugitive%3A///Users/user/src/mm/ems/.git//0/pkg/domain/treasury/provider.go\")\n\t\tparams.Position.Character = 18\n\t\tparams.Position.Line = 0\n\t\tenv.Editor.Server.Definition(env.Ctx, params) // ignore error\n\t})\n}\n\n// TestVendoringInvalidatesMetadata ensures that gopls uses the\n// correct metadata even after an external 'go mod vendor' command\n// causes packages to move; see issue #55995.\n// See also TestImplementationsInVendor, which tests the same fix.\nfunc TestVendoringInvalidatesMetadata(t *testing.T) {\n\tt.Skip(\"golang/go#56169: file watching does not capture vendor dirs\")\n\n\tconst proxy = `\n-- other.com/b@v1.0.0/go.mod --\nmodule other.com/b\ngo 1.14\n\n-- other.com/b@v1.0.0/b.go --\npackage b\nconst K = 0\n`\n\tconst src = `\n-- go.mod --\nmodule example.com/a\ngo 1.14\nrequire other.com/b v1.0.0\n\n-- a.go --\npackage a\nimport \"other.com/b\"\nconst _ = b.K\n\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t\tModes(Default), // fails in 'experimental' mode\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t// Enable to debug go.sum mismatch, which may appear as\n\t\t// \"module lookup disabled by GOPROXY=off\", confusingly.\n\t\tif false {\n\t\t\tenv.DumpGoSum(\".\")\n\t\t}\n\n\t\tenv.OpenFile(\"a.go\")\n\t\trefLoc := env.RegexpSearch(\"a.go\", \"K\") // find \"b.K\" reference\n\n\t\t// Initially, b.K is defined in the module cache.\n\t\tgotLoc := env.FirstDefinition(refLoc)\n\t\tgotFile := env.Sandbox.Workdir.URIToPath(gotLoc.URI)\n\t\twantCache := filepath.ToSlash(env.Sandbox.GOPATH()) + \"/pkg/mod/other.com/b@v1.0.0/b.go\"\n\t\tif gotFile != wantCache {\n\t\t\tt.Errorf(\"Definition, before: got file %q, want %q\", gotFile, wantCache)\n\t\t}\n\n\t\t// Run 'go mod vendor' outside the editor.\n\t\tenv.RunGoCommand(\"mod\", \"vendor\")\n\n\t\t// Synchronize changes to watched files.\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\t// Now, b.K is defined in the vendor tree.\n\t\tgotLoc = env.FirstDefinition(refLoc)\n\t\twantVendor := \"vendor/other.com/b/b.go\"\n\t\tif gotFile != wantVendor {\n\t\t\tt.Errorf(\"Definition, after go mod vendor: got file %q, want %q\", gotFile, wantVendor)\n\t\t}\n\n\t\t// Delete the vendor tree.\n\t\tif err := os.RemoveAll(env.Sandbox.Workdir.AbsPath(\"vendor\")); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// Notify the server of the deletion.\n\t\tif err := env.Sandbox.Workdir.CheckForFileChanges(env.Ctx); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Synchronize again.\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\t// b.K is once again defined in the module cache.\n\t\tgotLoc = env.FirstDefinition(gotLoc)\n\t\tgotFile = env.Sandbox.Workdir.URIToPath(gotLoc.URI)\n\t\tif gotFile != wantCache {\n\t\t\tt.Errorf(\"Definition, after rm -rf vendor: got file %q, want %q\", gotFile, wantCache)\n\t\t}\n\t})\n}\n\nconst embedDefinition = `\n-- go.mod --\nmodule mod.com\n\n-- main.go --\npackage main\n\nimport (\n\t\"embed\"\n)\n\n//go:embed *.txt\nvar foo embed.FS\n\nfunc main() {}\n\n-- skip.sql --\nSKIP\n\n-- foo.txt --\nFOO\n\n-- skip.bat --\nSKIP\n`\n\nfunc TestEmbedDefinition(t *testing.T) {\n\tRun(t, embedDefinition, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\n\t\tstart := env.RegexpSearch(\"main.go\", `\\*.txt`)\n\t\tloc := env.FirstDefinition(start)\n\n\t\tname := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"foo.txt\"; name != want {\n\t\t\tt.Errorf(\"Definition: got file %q, want %q\", name, want)\n\t\t}\n\t})\n}\n\nfunc TestDefinitionOfErrorErrorMethod(t *testing.T) {\n\tconst src = `Regression test for a panic in definition of error.Error (of course).\ngolang/go#64086\n\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a.go --\npackage a\n\nfunc _(err error) {\n\t_ = err.Error()\n}\n\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\tstart := env.RegexpSearch(\"a.go\", `Error`)\n\t\tloc := env.FirstDefinition(start)\n\n\t\tif !strings.HasSuffix(string(loc.URI), \"builtin.go\") {\n\t\t\tt.Errorf(\"Definition(err.Error) = %#v, want builtin.go\", loc)\n\t\t}\n\t})\n}\n\nfunc TestAssemblyDefinition(t *testing.T) {\n\t// This test cannot be expressed as a marker test because\n\t// the expect package ignores markers (@loc) within a .s file.\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\n-- foo_darwin_arm64.s --\n\n// assembly implementation\nTEXT ·foo(SB),NOSPLIT,$0\n\tRET\n\n-- a.go --\n//go:build darwin && arm64\n\npackage a\n\n// Go declaration\nfunc foo(int) int\n\nvar _ = foo(123) // call\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\tlocString := func(loc protocol.Location) string {\n\t\t\treturn fmt.Sprintf(\"%s:%s\", loc.URI.Base(), loc.Range)\n\t\t}\n\n\t\t// Definition at the call\"foo(123)\" takes us to the Go declaration.\n\t\tcallLoc := env.RegexpSearch(\"a.go\", regexp.QuoteMeta(\"foo(123)\"))\n\t\tdeclLoc := env.FirstDefinition(callLoc)\n\t\tif got, want := locString(declLoc), \"a.go:5:5-5:8\"; got != want {\n\t\t\tt.Errorf(\"Definition(call): got %s, want %s\", got, want)\n\t\t}\n\n\t\t// Definition a second time takes us to the assembly implementation.\n\t\timplLoc := env.FirstDefinition(declLoc)\n\t\tif got, want := locString(implLoc), \"foo_darwin_arm64.s:2:6-2:9\"; got != want {\n\t\t\tt.Errorf(\"Definition(go decl): got %s, want %s\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestPackageKeyInvalidationAfterSave(t *testing.T) {\n\t// This test is a little subtle, but catches a bug that slipped through\n\t// testing of https://go.dev/cl/614165, which moved active packages to the\n\t// packageHandle.\n\t//\n\t// The bug was that after a format-and-save operation, the save marks the\n\t// package as dirty but doesn't change its identity. In other words, this is\n\t// the sequence of change:\n\t//\n\t//  S_0 --format--> S_1 --save--> S_2\n\t//\n\t// A package is computed on S_0, invalidated in S_1 and immediately\n\t// invalidated again in S_2. Due to an invalidation bug, the validity of the\n\t// package from S_0 was checked by comparing the identical keys of S_1 and\n\t// S_2, and so the stale package from S_0 was marked as valid.\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\n-- a.go --\npackage a\n\nfunc Foo() {\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\tfooLoc := env.RegexpSearch(\"a.go\", \"()Foo\")\n\t\tloc0 := env.FirstDefinition(fooLoc)\n\n\t\t// Insert a space that will be removed by formatting.\n\t\tenv.EditBuffer(\"a.go\", protocol.TextEdit{\n\t\t\tRange:   fooLoc.Range,\n\t\t\tNewText: \" \",\n\t\t})\n\t\tenv.SaveBuffer(\"a.go\") // reformats the file before save\n\t\tenv.AfterChange()\n\t\tloc1 := env.FirstDefinition(env.RegexpSearch(\"a.go\", \"Foo\"))\n\t\tif diff := cmp.Diff(loc0, loc1); diff != \"\" {\n\t\t\tt.Errorf(\"mismatching locations (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestCommentDefinition_Issue69616(t *testing.T) {\n\t// This test exercises a few edge cases discovered by telemetry in\n\t// golang/go#69616, namely situations where a parsed Go file might\n\t// not have an associated scope in the package types.Info.\n\t//\n\t// The files below set up two types of edge cases:\n\t//  - a 'compiled' Go file that isn't actually type-checked, because it has\n\t//    the wrong package name\n\t//  - a non-compiled Go file (unsafe.go).\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.21\n-- cmd/main.go --\npackage main\n\nimport \"unsafe\"\n\nvar _  = unsafe.Offsetof\n\nfunc Foo() {}\n-- cmd/x.go --\npackage x\n\n// Bar is like [Foo]\nfunc Bar() {}\n`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\t// First, check that we don't produce a crash or bug when\n\t\t// finding definitions in a 'compiled' go file that isn't actually type\n\t\t// checked.\n\t\tenv.OpenFile(\"cmd/x.go\")\n\t\t_, _ = env.Editor.Definitions(env.Ctx, env.RegexpSearch(\"cmd/x.go\", \"()Foo\"))\n\n\t\t// Next, go to the unsafe package, and find the doc link to [Sizeof].\n\t\t// It will also fail to resolve, because unsafe.go isn't compiled, but\n\t\t// again should not panic or result in a bug.\n\t\tenv.OpenFile(\"cmd/main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"cmd/main.go\", `unsafe\\.(Offsetof)`))\n\t\tunsafePath := loc.URI.Path()\n\t\tenv.OpenFile(unsafePath)\n\t\t_, _ = env.Editor.Definitions(env.Ctx,\n\t\t\tenv.RegexpSearch(unsafePath, `\\[()Sizeof\\]`))\n\t})\n}\nfunc TestUndefinedLabel_Issue76625(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.22\n-- a.go --\npackage a\n\nfunc UndefinedLabel() {\n\tfor i := range 10 {\n\t\tif i > 2 {\n\t\t\tgoto undefinedLabel\n\t\t}\n\t}\n}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\texpectedErr := \"undefined label\"\n\t\tgotoUndefined := env.RegexpSearch(\"a.go\", `goto`)\n\t\t_, err := env.Editor.Definitions(env.Ctx, gotoUndefined)\n\t\tif err == nil {\n\t\t\tt.Fatalf(\"request succeeded unexpectedly, want error %s\", err)\n\t\t}\n\t\tif !strings.Contains(err.Error(), expectedErr) {\n\t\t\tt.Fatalf(\"received unexpected error message %s, want %s\", err, expectedErr)\n\t\t}\n\t})\n\n}\n\nfunc TestDefinition_embedSeparator(t *testing.T) {\n\t// This test checks that Definition on a //go:embed glob pattern reports\n\t// the location of the (first) matching file. It is a regression test for\n\t// a path-separator bug on Windows (https://go.dev/issue/77131).\n\t//\n\t// It can't be expressed as a marker test because it would require\n\t// a @def marker within a //go:embed directive.\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.22\n\n-- a/subdir/embed.txt --\nhello\n\n-- a/a.go --\npackage a\n\nimport _ \"embed\"\n\n//go:embed subdir/embed.txt\nvar _ string\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"a/a.go\", \"subdir\"))\n\t\tgot := fileLocations(env, []protocol.Location{loc})\n\t\twant := []string{\"a/subdir/embed.txt:1\"}\n\t\tif !reflect.DeepEqual(got, want) {\n\t\t\tt.Errorf(\"Definition at 'subdir' returned %v, want %v\", got, want)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/embed_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestMissingPatternDiagnostic(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n-- x.go --\npackage x\n\nimport (\n\t_ \"embed\"\n)\n\n// Issue 47436\nfunc F() {}\n\n//go:embed NONEXISTENT\nvar Foo string\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"x.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"x.go\", `NONEXISTENT`),\n\t\t\t\tWithMessage(\"no matching files found\"),\n\t\t\t),\n\t\t)\n\t\tenv.RegexpReplace(\"x.go\", `NONEXISTENT`, \"x.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"x.go\")))\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/extract_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestExtractFunction(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc Foo() int {\n\ta := 5\n\treturn a\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.RegexpSearch(\"main.go\", `a := 5\\n.*return a`)\n\t\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Find the extract function code action.\n\t\tvar extractFunc *protocol.CodeAction\n\t\tfor _, action := range actions {\n\t\t\tif action.Kind == settings.RefactorExtractFunction {\n\t\t\t\textractFunc = &action\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif extractFunc == nil {\n\t\t\tt.Fatal(\"could not find extract function action\")\n\t\t}\n\n\t\tenv.ApplyCodeAction(*extractFunc)\n\t\twant := `package main\n\nfunc Foo() int {\n\treturn newFunction()\n}\n\nfunc newFunction() int {\n\ta := 5\n\treturn a\n}\n`\n\t\tif got := env.BufferText(\"main.go\"); got != want {\n\t\t\tt.Fatalf(\"TestExtractFunction failed:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestExtractLabel(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc Foo(x []int) int {\n\tvar i int\n\tfor i = range x {\n\t\tif x[i] == 10 {\n\t\t\tgoto found\n\t\t}\n\t}\n\tpanic(\"not found\")\nfound:\n\n\tif i < 2 {\n\t}\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.RegexpSearch(\"main.go\", `(?s)for.*found:`)\n\t\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Find the extract function code action.\n\t\tvar extractFunc *protocol.CodeAction\n\t\tfor _, action := range actions {\n\t\t\tif action.Kind == settings.RefactorExtractFunction {\n\t\t\t\textractFunc = &action\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif extractFunc == nil {\n\t\t\tt.Fatal(\"could not find extract function action\")\n\t\t}\n\n\t\tenv.ApplyCodeAction(*extractFunc)\n\t\twant := `package main\n\nfunc Foo(x []int) int {\n\tvar i int\n\tnewFunction(i, x)\n\n\tif i < 2 {\n\t}\n}\n\nfunc newFunction(i int, x []int) {\n\tfor i = range x {\n\t\tif x[i] == 10 {\n\t\t\tgoto found\n\t\t}\n\t}\n\tpanic(\"not found\")\nfound:\n}\n`\n\t\tif got := env.BufferText(\"main.go\"); got != want {\n\t\t\tt.Fatalf(\"TestExtractlabel failed:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/failures_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// This is a slight variant of TestHoverOnError in definition_test.go\n// that includes a line directive, which makes no difference since\n// gopls ignores line directives.\nfunc TestHoverFailure(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a.y --\nDWIM(main)\n\n-- main.go --\n//line a.y:1\npackage main\n\nfunc main() {\n\tvar err error\n\terr.Error()\n}`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tcontent, _ := env.Hover(env.RegexpSearch(\"main.go\", \"Error\"))\n\t\tif content == nil {\n\t\t\tt.Fatalf(\"Hover('Error') returned nil\")\n\t\t}\n\t\twant := \"```go\\nfunc (error).Error() string\\n```\"\n\t\tif content.Value != want {\n\t\t\tt.Fatalf(\"wrong Hover('Error') content:\\n%s\", compare.Text(want, content.Value))\n\t\t}\n\t})\n}\n\n// This test demonstrates a case where gopls is not at all confused by\n// line directives, because it completely ignores them.\nfunc TestFailingDiagnosticClearingOnEdit(t *testing.T) {\n\t// badPackageDup contains a duplicate definition of the 'A' const.\n\t// This is a minor variant of TestDiagnosticClearingOnEdit from\n\t// diagnostics_test.go, with a line directive, which makes no difference.\n\tconst badPackageDup = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a.go --\npackage consts\n\nconst A = 1\n-- b.go --\npackage consts\n//line gen.go:5\nconst A = 2\n`\n\n\tRun(t, badPackageDup, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"b.go\", `A = 2`), WithMessage(\"A redeclared\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", `A = 1`), WithMessage(\"other declaration\")),\n\t\t)\n\n\t\t// Fix the error by editing the const name A in b.go to `B`.\n\t\tenv.RegexpReplace(\"b.go\", \"(A) = 2\", \"B\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"b.go\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/filecache_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestMaxFileCacheBytes(t *testing.T) {\n\tbefore := filecache.SetBudget(-1)\n\tdefer filecache.SetBudget(before)\n\n\t// Use a value large enough to ensure there are no\n\t// side effects, as file cache GC is global.\n\tconst budget int64 = 50e9 // 50GB\n\n\tintegration.WithOptions(\n\t\tintegration.Settings(map[string]any{\n\t\t\t\"maxFileCacheBytes\": budget,\n\t\t}),\n\t).Run(t, \"\", func(t *testing.T, env *integration.Env) {\n\t\t// Verify that budget is set.\n\t\tif got := filecache.SetBudget(-1); got != int64(budget) {\n\t\t\tt.Errorf(\"initial budget: got %d, want %d\", got, budget)\n\t\t}\n\n\t\tconst newBudget int64 = 55e9 // 55GB\n\t\tcfg := env.Editor.Config()\n\t\tcfg.Settings[\"maxFileCacheBytes\"] = newBudget\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange()\n\n\t\t// Verify that the budget was updated.\n\t\tif got := filecache.SetBudget(-1); got != int64(newBudget) {\n\t\t\tt.Errorf(\"updated budget: got %d, want %d\", got, newBudget)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/fix_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// A basic test for fillstruct, now that it uses a command and supports resolve edits.\nfunc TestFillStruct(t *testing.T) {\n\ttc := []struct {\n\t\tname         string\n\t\tcapabilities string\n\t\twantCommand  bool\n\t}{\n\t\t{\"default\", \"{}\", false},\n\t\t{\"no data support\", `{\"textDocument\": {\"codeAction\": {\"dataSupport\": false, \"resolveSupport\": {\"properties\": [\"edit\"]}}}}`, true},\n\t\t{\"no resolve support\", `{\"textDocument\": {\"codeAction\": {\"dataSupport\": true, \"resolveSupport\": {\"properties\": []}}}}`, true},\n\t\t{\"data and resolve support\", `{\"textDocument\": {\"codeAction\": {\"dataSupport\": true, \"resolveSupport\": {\"properties\": [\"edit\"]}}}}`, false},\n\t}\n\n\tconst basic = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main.go --\npackage main\n\ntype Info struct {\n\tWordCounts map[string]int\n\tWords []string\n}\n\nfunc Foo() {\n\t_ = Info{}\n}\n`\n\n\tfor _, tt := range tc {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trunner := WithOptions(CapabilitiesJSON([]byte(tt.capabilities)))\n\n\t\t\trunner.Run(t, basic, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"main.go\")\n\t\t\t\tfixes, err := env.Editor.CodeActions(env.Ctx, env.RegexpSearch(\"main.go\", \"Info{}\"), nil, settings.RefactorRewriteFillStruct)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif len(fixes) != 1 {\n\t\t\t\t\tt.Fatalf(\"expected 1 code action, got %v\", len(fixes))\n\t\t\t\t}\n\t\t\t\tif tt.wantCommand {\n\t\t\t\t\tif fixes[0].Command == nil || fixes[0].Data != nil {\n\t\t\t\t\t\tt.Errorf(\"expected code action to have command not data, got %v\", fixes[0])\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif fixes[0].Command != nil || fixes[0].Data == nil {\n\t\t\t\t\t\tt.Errorf(\"expected code action to have command not data, got %v\", fixes[0])\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply the code action (handles resolving the code action), and check that the result is correct.\n\t\t\t\tif err := env.Editor.RefactorRewrite(env.Ctx, env.RegexpSearch(\"main.go\", \"Info{}\")); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\twant := `package main\n\ntype Info struct {\n\tWordCounts map[string]int\n\tWords []string\n}\n\nfunc Foo() {\n\t_ = Info{\n\t\tWordCounts: map[string]int{},\n\t\tWords:      []string{},\n\t}\n}\n`\n\t\t\t\tif got := env.BufferText(\"main.go\"); got != want {\n\t\t\t\t\tt.Fatalf(\"TestFillStruct failed:\\n%s\", compare.Text(want, got))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestFillReturns(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc Foo() error {\n\treturn\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\t// The error message here changed in 1.18; \"return values\" covers both forms.\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `return`), WithMessage(\"return values\")),\n\t\t\tReadDiagnostics(\"main.go\", &d),\n\t\t)\n\t\tvar quickFixes []*protocol.CodeAction\n\t\tfor _, act := range env.CodeActionForFile(\"main.go\", d.Diagnostics) {\n\t\t\tif act.Kind == protocol.QuickFix {\n\t\t\t\tact := act // remove in go1.22\n\t\t\t\tquickFixes = append(quickFixes, &act)\n\t\t\t}\n\t\t}\n\t\tif len(quickFixes) != 1 {\n\t\t\tt.Fatalf(\"expected 1 quick fix, got %d:\\n%v\", len(quickFixes), quickFixes)\n\t\t}\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\nfunc TestUnusedParameter_Issue63755(t *testing.T) {\n\t// This test verifies the fix for #63755, where codeActions panicked on parameters\n\t// of functions with no function body.\n\n\t// We should not detect parameters as unused for external functions.\n\n\tconst files = `\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- external.go --\npackage external\n\nfunc External(z int)\n\nfunc _() {\n\tExternal(1)\n}\n\t`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"external.go\")\n\t\t_, err := env.Editor.CodeAction(env.Ctx, env.RegexpSearch(\"external.go\", \"z\"), nil, protocol.CodeActionUnknownTrigger)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// yay, no panic\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/formatting_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nconst unformattedProgram = `\n-- main.go --\npackage main\nimport \"fmt\"\nfunc main(  ) {\n\tfmt.Println(\"Hello World.\")\n}\n-- main.go.golden --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello World.\")\n}\n`\n\nfunc TestFormatting(t *testing.T) {\n\tRun(t, unformattedProgram, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.FormatBuffer(\"main.go\")\n\t\tgot := env.BufferText(\"main.go\")\n\t\twant := env.ReadWorkspaceFile(\"main.go.golden\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Tests golang/go#36824.\nfunc TestFormattingOneLine36824(t *testing.T) {\n\tconst onelineProgram = `\n-- a.go --\npackage main; func f() {}\n\n-- a.go.formatted --\npackage main\n\nfunc f() {}\n`\n\tRun(t, onelineProgram, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.FormatBuffer(\"a.go\")\n\t\tgot := env.BufferText(\"a.go\")\n\t\twant := env.ReadWorkspaceFile(\"a.go.formatted\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Tests golang/go#36824.\nfunc TestFormattingOneLineImports36824(t *testing.T) {\n\tconst onelineProgramA = `\n-- a.go --\npackage x; func f() {fmt.Println()}\n\n-- a.go.imported --\npackage x\n\nimport \"fmt\"\n\nfunc f() { fmt.Println() }\n`\n\tRun(t, onelineProgramA, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.OrganizeImports(\"a.go\")\n\t\tgot := env.BufferText(\"a.go\")\n\t\twant := env.ReadWorkspaceFile(\"a.go.imported\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestFormattingOneLineRmImports36824(t *testing.T) {\n\tconst onelineProgramB = `\n-- a.go --\npackage x; import \"os\"; func f() {}\n\n-- a.go.imported --\npackage x\n\nfunc f() {}\n`\n\tRun(t, onelineProgramB, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.OrganizeImports(\"a.go\")\n\t\tgot := env.BufferText(\"a.go\")\n\t\twant := env.ReadWorkspaceFile(\"a.go.imported\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nconst disorganizedProgram = `\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"errors\"\n)\nfunc main(  ) {\n\tfmt.Println(errors.New(\"bad\"))\n}\n-- main.go.organized --\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\nfunc main(  ) {\n\tfmt.Println(errors.New(\"bad\"))\n}\n-- main.go.formatted --\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tfmt.Println(errors.New(\"bad\"))\n}\n`\n\nfunc TestOrganizeImports(t *testing.T) {\n\tRun(t, disorganizedProgram, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OrganizeImports(\"main.go\")\n\t\tgot := env.BufferText(\"main.go\")\n\t\twant := env.ReadWorkspaceFile(\"main.go.organized\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestFormattingOnSave(t *testing.T) {\n\tRun(t, disorganizedProgram, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tgot := env.BufferText(\"main.go\")\n\t\twant := env.ReadWorkspaceFile(\"main.go.formatted\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Tests various possibilities for comments in files with CRLF line endings.\n// Import organization in these files has historically been a source of bugs.\nfunc TestCRLFLineEndings(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tissue, input, want string\n\t}{\n\t\t{\n\t\t\tissue: \"41057\",\n\t\t\twant: `package main\n\n/*\nHi description\n*/\nfunc Hi() {\n}\n`,\n\t\t},\n\t\t{\n\t\t\tissue: \"42646\",\n\t\t\twant: `package main\n\nimport (\n\t\"fmt\"\n)\n\n/*\nfunc upload(c echo.Context) error {\n\tif err := r.ParseForm(); err != nil {\n\t\tfmt.Fprintf(w, \"ParseForm() err: %v\", err)\n\t\treturn\n\t}\n\tfmt.Fprintf(w, \"POST request successful\")\n\tpath_ver := r.FormValue(\"path_ver\")\n\tukclin_ver := r.FormValue(\"ukclin_ver\")\n\n\tfmt.Fprintf(w, \"Name = %s\\n\", path_ver)\n\tfmt.Fprintf(w, \"Address = %s\\n\", ukclin_ver)\n}\n*/\n\nfunc main() {\n\tconst server_port = 8080\n\tfmt.Printf(\"port: %d\\n\", server_port)\n}\n`,\n\t\t},\n\t\t{\n\t\t\tissue: \"42923\",\n\t\t\twant: `package main\n\n// Line 1.\n// aa\ntype Tree struct {\n\tarr []string\n}\n`,\n\t\t},\n\t\t{\n\t\t\tissue: \"47200\",\n\t\t\tinput: `package main\n\nimport \"fmt\"\n\nfunc main() {\n\tmath.Sqrt(9)\n\tfmt.Println(\"hello\")\n}\n`,\n\t\t\twant: `package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc main() {\n\tmath.Sqrt(9)\n\tfmt.Println(\"hello\")\n}\n`,\n\t\t},\n\t} {\n\t\tt.Run(tt.issue, func(t *testing.T) {\n\t\t\tRun(t, \"-- main.go --\", func(t *testing.T, env *Env) {\n\t\t\t\tinput := tt.input\n\t\t\t\tif input == \"\" {\n\t\t\t\t\tinput = tt.want\n\t\t\t\t}\n\t\t\t\tcrlf := strings.ReplaceAll(input, \"\\n\", \"\\r\\n\")\n\t\t\t\tenv.CreateBuffer(\"main.go\", crlf)\n\t\t\t\tenv.Await(env.DoneWithOpen())\n\t\t\t\tenv.OrganizeImports(\"main.go\")\n\t\t\t\tgot := env.BufferText(\"main.go\")\n\t\t\t\tgot = strings.ReplaceAll(got, \"\\r\\n\", \"\\n\") // convert everything to LF for simplicity\n\t\t\t\tif tt.want != got {\n\t\t\t\t\tt.Errorf(\"unexpected content after save:\\n%s\", compare.Text(tt.want, got))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestGofumptFormatting(t *testing.T) {\n\t// Exercise some gofumpt formatting rules:\n\t//  - No empty lines following an assignment operator\n\t//  - Octal integer literals should use the 0o prefix on modules using Go\n\t//    1.13 and later. Requires LangVersion to be correctly resolved.\n\t//  - std imports must be in a separate group at the top. Requires ModulePath\n\t//    to be correctly resolved.\n\tconst input = `\n-- go.mod --\nmodule foo\n\ngo 1.17\n-- foo.go --\npackage foo\n\nimport (\n\t\"foo/bar\"\n\t\"fmt\"\n)\n\nconst perm = 0755\n\nfunc foo() {\n\tfoo :=\n\t\t\"bar\"\n\tfmt.Println(foo, bar.Bar)\n}\n-- foo.go.formatted --\npackage foo\n\nimport (\n\t\"fmt\"\n\n\t\"foo/bar\"\n)\n\nconst perm = 0o755\n\nfunc foo() {\n\tfoo := \"bar\"\n\tfmt.Println(foo, bar.Bar)\n}\n-- bar/bar.go --\npackage bar\n\nconst Bar = 42\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"gofumpt\": true,\n\t\t},\n\t).Run(t, input, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tenv.FormatBuffer(\"foo.go\")\n\t\tgot := env.BufferText(\"foo.go\")\n\t\twant := env.ReadWorkspaceFile(\"foo.go.formatted\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"unexpected formatting result:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestGofumpt_Issue61692(t *testing.T) {\n\tconst input = `\n-- go.mod --\nmodule foo\n\ngo 1.21rc3\n-- foo.go --\npackage foo\n\nfunc _() {\n\tfoo :=\n\t\t\"bar\"\n}\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"gofumpt\": true,\n\t\t},\n\t).Run(t, input, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tenv.FormatBuffer(\"foo.go\") // golang/go#61692: must not panic\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/generate_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// TODO(rfindley): figure out why go generate fails on android builders.\n\n//go:build !android\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestGenerateProgress(t *testing.T) {\n\tconst generatedWorkspace = `\n-- go.mod --\nmodule fake.test\n\ngo 1.14\n-- generate.go --\n// +build ignore\n\npackage main\n\nimport (\n\t\"os\"\n)\n\nfunc main() {\n\tos.WriteFile(\"generated.go\", []byte(\"package \" + os.Args[1] + \"\\n\\nconst Answer = 21\"), 0644)\n}\n\n-- lib1/lib.go --\npackage lib1\n\n//` + `go:generate go run ../generate.go lib1\n\n-- lib2/lib.go --\npackage lib2\n\n//` + `go:generate go run ../generate.go lib2\n\n-- main.go --\npackage main\n\nimport (\n\t\"fake.test/lib1\"\n\t\"fake.test/lib2\"\n)\n\nfunc main() {\n\tprintln(lib1.Answer + lib2.Answer)\n}\n`\n\n\tRun(t, generatedWorkspace, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"lib1.(Answer)\")),\n\t\t)\n\t\tenv.RunGenerate(\"./lib1\")\n\t\tenv.RunGenerate(\"./lib2\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\nfunc TestGenerateUseNetwork(t *testing.T) {\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.21\n-- example.com@v1.2.3/main.go --\npackage main\n\nfunc main() {\n\tprintln(\"hello world\")\n}\n`\n\tconst generatedWorkspace = `\n-- go.mod --\nmodule fake.test\n\ngo 1.21\n-- main.go --\n\npackage main\n\n//go:` + /* hide this string from the go command */ `generate go run example.com@latest\n\n`\n\tWithOptions(ProxyFiles(proxy)).\n\t\tRun(t, generatedWorkspace, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t)\n\t\t\tenv.RunGenerate(\"./\")\n\t\t})\n}\n\nfunc TestEditingGeneratedFileWarning(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.21\n\n-- a/a.go --\n// Code generated by me. DO NOT EDIT.\n\npackage a\n\nvar x = 1\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tcollectMessages := env.Awaiter.ListenToShownMessages()\n\t\tenv.RegexpReplace(\"a/a.go\", \"var\", \"const\")\n\t\tenv.Await(env.DoneWithChange())\n\t\tmessages := collectMessages()\n\n\t\tconst want = \"Warning: editing a.go, a generated file.\"\n\t\tif len(messages) != 1 || messages[0].Message != want {\n\t\t\tfor _, message := range messages {\n\t\t\t\tt.Errorf(\"got message %q\", message.Message)\n\t\t\t}\n\t\t\tt.Errorf(\"no %q warning\", want)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/highlight_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestWorkspacePackageHighlight(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n\tvar A string = \"A\"\n\tx := \"x-\" + A\n\tprintln(A, x)\n}`\n\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tconst file = \"main.go\"\n\t\tenv.OpenFile(file)\n\t\tloc := env.FirstDefinition(env.RegexpSearch(file, `var (A) string`))\n\n\t\tcheckHighlights(env, loc, 3)\n\t})\n}\n\nfunc TestStdPackageHighlight_Issue43511(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Printf()\n}`\n\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tdefLoc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `fmt\\.(Printf)`))\n\t\tfile := env.Sandbox.Workdir.URIToPath(defLoc.URI)\n\t\tenv.OpenFile(file)\n\t\tloc := env.RegexpSearch(file, `func Printf\\((format) string`)\n\n\t\tcheckHighlights(env, loc, 2)\n\t})\n}\n\nfunc TestThirdPartyPackageHighlight_Issue43511(t *testing.T) {\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/global/global.go --\npackage global\n\nconst A = 1\n\nfunc foo() {\n\t_ = A\n}\n\nfunc bar() int {\n\treturn A + A\n}\n-- example.com@v1.2.3/local/local.go --\npackage local\n\nfunc foo() int {\n\tconst b = 2\n\n\treturn b * b * (b+1) + b\n}`\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n-- main.go --\npackage main\n\nimport (\n\t_ \"example.com/global\"\n\t_ \"example.com/local\"\n)\n\nfunc main() {}`\n\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tWriteGoSum(\".\"),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\n\t\tdefLoc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `\"example.com/global\"`))\n\t\tfile := env.Sandbox.Workdir.URIToPath(defLoc.URI)\n\t\tenv.OpenFile(file)\n\t\tloc := env.RegexpSearch(file, `const (A)`)\n\t\tcheckHighlights(env, loc, 4)\n\n\t\tdefLoc = env.FirstDefinition(env.RegexpSearch(\"main.go\", `\"example.com/local\"`))\n\t\tfile = env.Sandbox.Workdir.URIToPath(defLoc.URI)\n\t\tenv.OpenFile(file)\n\t\tloc = env.RegexpSearch(file, `const (b)`)\n\t\tcheckHighlights(env, loc, 5)\n\t})\n}\n\nfunc checkHighlights(env *Env, loc protocol.Location, highlightCount int) {\n\tt := env.TB\n\tt.Helper()\n\n\thighlights := env.DocumentHighlight(loc)\n\tif len(highlights) != highlightCount {\n\t\tt.Fatalf(\"expected %v highlight(s), got %v\", highlightCount, len(highlights))\n\t}\n\n\treferences := env.References(loc)\n\tif len(highlights) != len(references) {\n\t\tt.Fatalf(\"number of highlights and references is expected to be equal: %v != %v\", len(highlights), len(references))\n\t}\n\n\tsort.Slice(highlights, func(i, j int) bool {\n\t\treturn protocol.CompareRange(highlights[i].Range, highlights[j].Range) < 0\n\t})\n\tsort.Slice(references, func(i, j int) bool {\n\t\treturn protocol.CompareRange(references[i].Range, references[j].Range) < 0\n\t})\n\tfor i := range highlights {\n\t\tif highlights[i].Range != references[i].Range {\n\t\t\tt.Errorf(\"highlight and reference ranges are expected to be equal: %v != %v\", highlights[i].Range, references[i].Range)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/hover_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\nfunc TestHoverUnexported(t *testing.T) {\n\tconst proxy = `\n-- golang.org/x/structs@v1.0.0/go.mod --\nmodule golang.org/x/structs\n\ngo 1.21\n\n-- golang.org/x/structs@v1.0.0/types.go --\npackage structs\n\ntype Mixed struct {\n\t// Exported comment\n\tExported   int\n\tunexported string\n}\n\nfunc printMixed(m Mixed) {\n\tprintln(m)\n}\n`\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.21\n\nrequire golang.org/x/structs v1.0.0\n-- main.go --\npackage main\n\nimport \"golang.org/x/structs\"\n\nfunc main() {\n\tvar m structs.Mixed\n\t_ = m.Exported\n}\n`\n\n\t// TODO: use a nested workspace folder here.\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tWriteGoSum(\".\"),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tmixedLoc := env.RegexpSearch(\"main.go\", \"Mixed\")\n\t\tgot, _ := env.Hover(mixedLoc)\n\t\tif !strings.Contains(got.Value, \"unexported\") {\n\t\t\tt.Errorf(\"Workspace hover: missing expected field 'unexported'. Got:\\n%q\", got.Value)\n\t\t}\n\n\t\tcacheLoc := env.FirstDefinition(mixedLoc)\n\t\tcacheFile := env.Sandbox.Workdir.URIToPath(cacheLoc.URI)\n\t\tenv.OpenFile(cacheFile)\n\t\targLoc := env.RegexpSearch(cacheFile, \"printMixed.*(Mixed)\")\n\t\tgot, _ = env.Hover(argLoc)\n\t\tif !strings.Contains(got.Value, \"unexported\") {\n\t\t\tt.Errorf(\"Non-workspace hover: missing expected field 'unexported'. Got:\\n%q\", got.Value)\n\t\t}\n\n\t\texportedFieldLoc := env.RegexpSearch(\"main.go\", \"Exported\")\n\t\tgot, _ = env.Hover(exportedFieldLoc)\n\t\tif !strings.Contains(got.Value, \"comment\") {\n\t\t\tt.Errorf(\"Workspace hover: missing comment for field 'Exported'. Got:\\n%q\", got.Value)\n\t\t}\n\t})\n}\n\nfunc TestHoverIntLiteral(t *testing.T) {\n\tconst source = `\n-- main.go --\npackage main\n\nvar (\n\tbigBin = 0b1001001\n)\n\nvar hex = 0xe34e\n\nfunc main() {\n}\n`\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\thexExpected := \"58190\"\n\t\tgot, _ := env.Hover(env.RegexpSearch(\"main.go\", \"0xe\"))\n\t\tif got != nil && !strings.Contains(got.Value, hexExpected) {\n\t\t\tt.Errorf(\"Hover: missing expected field '%s'. Got:\\n%q\", hexExpected, got.Value)\n\t\t}\n\n\t\tbinExpected := \"73\"\n\t\tgot, _ = env.Hover(env.RegexpSearch(\"main.go\", \"0b1\"))\n\t\tif got != nil && !strings.Contains(got.Value, binExpected) {\n\t\t\tt.Errorf(\"Hover: missing expected field '%s'. Got:\\n%q\", binExpected, got.Value)\n\t\t}\n\t})\n}\n\n// Tests that hovering does not trigger the panic in golang/go#48249.\nfunc TestPanicInHoverBrokenCode(t *testing.T) {\n\t// Note: this test can not be expressed as a marker test, as it must use\n\t// content without a trailing newline.\n\tconst source = `\n-- main.go --\npackage main\n\ntype Example struct`\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Editor.Hover(env.Ctx, env.RegexpSearch(\"main.go\", \"Example\"))\n\t})\n}\n\nfunc TestHoverRune_48492(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.EditBuffer(\"main.go\", fake.NewEdit(0, 0, 1, 0, \"package main\\nfunc main() {\\nconst x = `\\nfoo\\n`\\n}\"))\n\t\tenv.Editor.Hover(env.Ctx, env.RegexpSearch(\"main.go\", \"foo\"))\n\t})\n}\n\nfunc TestHoverImport(t *testing.T) {\n\tconst packageDoc1 = \"Package lib1 hover documentation\"\n\tconst packageDoc2 = \"Package lib2 hover documentation\"\n\ttests := []struct {\n\t\thoverPackage string\n\t\twant         string\n\t\twantError    bool\n\t}{\n\t\t{\n\t\t\t\"mod.com/lib1\",\n\t\t\tpackageDoc1,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"mod.com/lib2\",\n\t\t\tpackageDoc2,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"mod.com/lib3\",\n\t\t\t\"\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"mod.com/lib4\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t}\n\tsource := fmt.Sprintf(`\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- lib1/a.go --\n// %s\npackage lib1\n\nconst C = 1\n\n-- lib1/b.go --\npackage lib1\n\nconst D = 1\n\n-- lib2/a.go --\n// %s\npackage lib2\n\nconst E = 1\n\n-- lib3/a.go --\npackage lib3\n\nconst F = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib1\"\n\t\"mod.com/lib2\"\n\t\"mod.com/lib3\"\n\t\"mod.com/lib4\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n\t`, packageDoc1, packageDoc2)\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tfor _, test := range tests {\n\t\t\tgot, _, err := env.Editor.Hover(env.Ctx, env.RegexpSearch(\"main.go\", test.hoverPackage))\n\t\t\tif test.wantError {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Errorf(\"Hover(%q) succeeded unexpectedly\", test.hoverPackage)\n\t\t\t\t}\n\t\t\t} else if !strings.Contains(got.Value, test.want) {\n\t\t\t\tt.Errorf(\"Hover(%q): got:\\n%q\\nwant:\\n%q\", test.hoverPackage, got.Value, test.want)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestHoverPackageIdent(t *testing.T) {\n\tconst packageDoc1 = \"Package lib1 hover documentation\"\n\tconst packageDoc2 = \"Package lib2 hover documentation\"\n\ttests := []struct {\n\t\thoverIdent string\n\t\twant       string\n\t\twantError  bool\n\t}{\n\t\t{\n\t\t\t\"lib1\",\n\t\t\tpackageDoc1,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"lib2\",\n\t\t\tpackageDoc2,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"lib3\",\n\t\t\t\"\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"lib4\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t}\n\tsource := fmt.Sprintf(`\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- lib1/a.go --\n// %s\npackage lib1\n\nconst C = 1\n\n-- lib1/b.go --\npackage lib1\n\nconst D = 1\n\n-- lib2/a.go --\n// %s\npackage lib2\n\nconst E = 1\n\n-- lib3/a.go --\npackage lib3\n\nconst F = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib1\"\n\t\"mod.com/lib2\"\n\t\"mod.com/lib3\"\n\t\"mod.com/lib4\"\n)\n\nfunc main() {\n\tprintln(lib1.C)\n\tprintln(lib2.E)\n\tprintln(lib3.F)\n\tprintln(lib4.Z)\n}\n\t`, packageDoc1, packageDoc2)\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tfor _, test := range tests {\n\t\t\tgot, _, err := env.Editor.Hover(env.Ctx, env.RegexpSearch(\"main.go\", \"(\"+test.hoverIdent+\")\\\\.\"))\n\t\t\tif test.wantError {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Errorf(\"Hover(%q) succeeded unexpectedly\", test.hoverIdent)\n\t\t\t\t}\n\t\t\t} else if !strings.Contains(got.Value, test.want) {\n\t\t\t\tt.Errorf(\"Hover(%q): got:\\n%q\\nwant:\\n%q\", test.hoverIdent, got.Value, test.want)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// for x/tools/gopls: unhandled named anchor on the hover #57048\nfunc TestHoverTags(t *testing.T) {\n\tconst source = `\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n\n-- lib/a.go --\n\n// variety of execution modes.\n//\n// # Test package setup\n//\n// The regression test package uses a couple of uncommon patterns to reduce\npackage lib\n\n-- a.go --\n\tpackage main\n\timport \"mod.com/lib\"\n\n\tconst A = 1\n\n}\n`\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tt.Run(\"tags\", func(t *testing.T) {\n\t\t\tenv.OpenFile(\"a.go\")\n\t\t\tz := env.RegexpSearch(\"a.go\", \"lib\")\n\t\t\tt.Logf(\"%#v\", z)\n\t\t\tgot, _ := env.Hover(env.RegexpSearch(\"a.go\", \"lib\"))\n\t\t\tif strings.Contains(got.Value, \"{#hdr-\") {\n\t\t\t\tt.Errorf(\"Hover: got {#hdr- tag:\\n%q\", got)\n\t\t\t}\n\t\t})\n\t})\n}\n\n// This is a regression test for Go issue #57625.\nfunc TestHoverModMissingModuleStmt(t *testing.T) {\n\tconst source = `\n-- go.mod --\ngo 1.16\n`\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.Hover(env.RegexpSearch(\"go.mod\", \"go\")) // no panic\n\t})\n}\n\nfunc TestHoverCompletionMarkdown(t *testing.T) {\n\tconst source = `\n-- go.mod --\nmodule mod.com\ngo 1.19\n-- main.go --\npackage main\n// Just says [hello].\n//\n// [hello]: https://en.wikipedia.org/wiki/Hello\nfunc Hello() string {\n\tHello() //Here\n    return \"hello\"\n}\n`\n\tRun(t, source, func(t *testing.T, env *Env) {\n\t\t// Hover, Completion, and SignatureHelp should all produce markdown\n\t\t// check that the markdown for SignatureHelp and Completion are\n\t\t// the same, and contained in that for Hover (up to trailing \\n)\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.RegexpSearch(\"main.go\", \"func ()Hello\")\n\t\thover, _ := env.Hover(loc)\n\t\thoverContent := hover.Value\n\n\t\tloc = env.RegexpSearch(\"main.go\", `Hello()\\(\\) \\/\\/Here`) // Hello_() //Here\n\t\tcompletions := env.Completion(loc)\n\t\tsignatures := env.SignatureHelp(loc)\n\n\t\tif len(completions.Items) != 1 {\n\t\t\tt.Errorf(\"got %d completions, expected 1\", len(completions.Items))\n\t\t}\n\t\tif len(signatures.Signatures) != 1 {\n\t\t\tt.Errorf(\"got %d signatures, expected 1\", len(signatures.Signatures))\n\t\t}\n\t\titem := completions.Items[0].Documentation.Value\n\t\tvar itemContent string\n\t\tif x, ok := item.(protocol.MarkupContent); !ok || x.Kind != protocol.Markdown {\n\t\t\tt.Fatalf(\"%#v is not markdown\", item)\n\t\t} else {\n\t\t\titemContent = strings.Trim(x.Value, \"\\n\")\n\t\t}\n\t\tsig := signatures.Signatures[0].Documentation.Value\n\t\tvar sigContent string\n\t\tif x, ok := sig.(protocol.MarkupContent); !ok || x.Kind != protocol.Markdown {\n\t\t\tt.Fatalf(\"%#v is not markdown\", item)\n\t\t} else {\n\t\t\tsigContent = x.Value\n\t\t}\n\t\tif itemContent != sigContent {\n\t\t\tt.Errorf(\"item:%q not sig:%q\", itemContent, sigContent)\n\t\t}\n\t\tif !strings.Contains(hoverContent, itemContent) {\n\t\t\tt.Errorf(\"hover:%q does not contain sig;%q\", hoverContent, sigContent)\n\t\t}\n\t})\n}\n\n// Test that the generated markdown contains links for Go references.\n// https://github.com/golang/go/issues/58352\nfunc TestHoverLinks(t *testing.T) {\n\tconst input = `\n-- go.mod --\ngo 1.19\nmodule mod.com\n-- main.go --\npackage main\n// [fmt]\nvar A int\n// [fmt.Println]\nvar B int\n// [golang.org/x/tools/go/packages.Package.String]\nvar C int\n`\n\tvar tests = []struct {\n\t\tpat string\n\t\tans string\n\t}{\n\t\t{\"A\", \"fmt\"},\n\t\t{\"B\", \"fmt#Println\"},\n\t\t{\"C\", \"golang.org/x/tools/go/packages#Package.String\"},\n\t}\n\tfor _, test := range tests {\n\t\tRun(t, input, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"main.go\")\n\t\t\tloc := env.RegexpSearch(\"main.go\", test.pat)\n\t\t\thover, _ := env.Hover(loc)\n\t\t\thoverContent := hover.Value\n\t\t\twant := fmt.Sprintf(\"%s/%s\", \"https://pkg.go.dev\", test.ans)\n\t\t\tif !strings.Contains(hoverContent, want) {\n\t\t\t\tt.Errorf(\"hover:%q does not contain link %q\", hoverContent, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nconst linknameHover = `\n-- go.mod --\nmodule mod.com\n\n-- upper/upper.go --\npackage upper\n\nimport (\n\t_ \"unsafe\"\n\t_ \"mod.com/lower\"\n)\n\n//go:linkname foo mod.com/lower.bar\nfunc foo() string\n\n-- lower/lower.go --\npackage lower\n\n// bar does foo.\nfunc bar() string {\n\treturn \"foo by bar\"\n}`\n\nfunc TestHoverLinknameDirective(t *testing.T) {\n\tRun(t, linknameHover, func(t *testing.T, env *Env) {\n\t\t// Jump from directives 2nd arg.\n\t\tenv.OpenFile(\"upper/upper.go\")\n\t\tfrom := env.RegexpSearch(\"upper/upper.go\", `lower.bar`)\n\n\t\thover, _ := env.Hover(from)\n\t\tcontent := hover.Value\n\n\t\texpect := \"bar does foo\"\n\t\tif !strings.Contains(content, expect) {\n\t\t\tt.Errorf(\"hover: %q does not contain: %q\", content, expect)\n\t\t}\n\t})\n}\n\nfunc TestHoverGoWork_Issue60821(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.19\n\nuse (\n\tmoda\n\tmodb\n)\n-- moda/go.mod --\n\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\t\t// Neither of the requests below should crash gopls.\n\t\t_, _, _ = env.Editor.Hover(env.Ctx, env.RegexpSearch(\"go.work\", \"moda\"))\n\t\t_, _, _ = env.Editor.Hover(env.Ctx, env.RegexpSearch(\"go.work\", \"modb\"))\n\t})\n}\n\nconst embedHover = `\n-- go.mod --\nmodule mod.com\ngo 1.19\n-- main.go --\npackage main\n\nimport \"embed\"\n\n//go:embed *.txt\nvar foo embed.FS\n\nfunc main() {\n}\n-- foo.txt --\nFOO\n-- bar.txt --\nBAR\n-- baz.txt --\nBAZ\n-- other.sql --\nSKIPPED\n-- dir.txt/skip.txt --\nSKIPPED\n`\n\nfunc TestHoverEmbedDirective(t *testing.T) {\n\tRun(t, embedHover, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tfrom := env.RegexpSearch(\"main.go\", `\\*.txt`)\n\n\t\tgot, _ := env.Hover(from)\n\t\tif got == nil {\n\t\t\tt.Fatalf(\"hover over //go:embed arg not found\")\n\t\t}\n\t\tcontent := got.Value\n\n\t\twants := []string{\"foo.txt\", \"bar.txt\", \"baz.txt\"}\n\t\tfor _, want := range wants {\n\t\t\tif !strings.Contains(content, want) {\n\t\t\t\tt.Errorf(\"hover: %q does not contain: %q\", content, want)\n\t\t\t}\n\t\t}\n\n\t\t// A directory should never be matched, even if it happens to have a matching name.\n\t\t// Content in subdirectories should not match on only one asterisk.\n\t\tskips := []string{\"other.sql\", \"dir.txt\", \"skip.txt\"}\n\t\tfor _, skip := range skips {\n\t\t\tif strings.Contains(content, skip) {\n\t\t\t\tt.Errorf(\"hover: %q should not contain: %q\", content, skip)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestHoverBrokenImport_Issue60592(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule testdata\ngo 1.18\n\n-- p.go --\npackage main\n\nimport foo \"a\"\n\nfunc _() {\n\tfoo.Print()\n}\n\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\t// This request should not crash gopls.\n\t\t_, _, _ = env.Editor.Hover(env.Ctx, env.RegexpSearch(\"p.go\", \"foo[.]\"))\n\t})\n}\n\nfunc TestHoverInternalLinks(t *testing.T) {\n\tconst src = `\n-- main.go --\npackage main\n\nimport \"errors\"\n\nfunc main() {\n\terrors.New(\"oops\")\n}\n`\n\tfor _, test := range []struct {\n\t\tlinksInHover any    // JSON configuration value\n\t\twantRE       string // pattern to match the Hover Markdown output\n\t}{\n\t\t{\n\t\t\ttrue, // default: use options.LinkTarget domain\n\t\t\tregexp.QuoteMeta(\"[`errors.New` on pkg.go.dev](https://pkg.go.dev/errors#New)\"),\n\t\t},\n\t\t{\n\t\t\t\"gopls\", // use gopls' internal viewer\n\t\t\t\"\\\\[`errors.New` in gopls doc viewer\\\\]\\\\(http://127.0.0.1:[0-9]+/gopls/[^/]+/pkg/errors\\\\?view=[0-9]+#New\\\\)\",\n\t\t},\n\t} {\n\t\tWithOptions(\n\t\t\tSettings{\"linksInHover\": test.linksInHover},\n\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"main.go\")\n\t\t\tgot, _ := env.Hover(env.RegexpSearch(\"main.go\", \"New\"))\n\t\t\tif m, err := regexp.MatchString(test.wantRE, got.Value); err != nil {\n\t\t\t\tt.Fatalf(\"bad regexp in test: %v\", err)\n\t\t\t} else if !m {\n\t\t\t\tt.Fatalf(\"hover output does not match %q; got:\\n\\n%s\", test.wantRE, got.Value)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestHoverInternalLinksIssue68116(t *testing.T) {\n\t// Links for the internal viewer should not include a module version suffix:\n\t// the package path and the view are an unambiguous key; see #68116.\n\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n\n-- example.com@v1.2.3/a/a.go --\npackage a\n\n// F is a function.\nfunc F()\n`\n\n\tconst mod = `\n-- go.mod --\nmodule main\n\ngo 1.12\n\nrequire example.com v1.2.3\n\n-- main.go --\npackage main\n\nimport \"example.com/a\"\n\nfunc main() {\n\ta.F()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tSettings{\"linksInHover\": \"gopls\"},\n\t\tWriteGoSum(\".\"),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tgot, _ := env.Hover(env.RegexpSearch(\"main.go\", \"F\"))\n\t\tconst wantRE = \"\\\\[`a.F` in gopls doc viewer\\\\]\\\\(http://127.0.0.1:[0-9]+/gopls/[^/]+/pkg/example.com/a\\\\?view=[0-9]+#F\\\\)\" // no version\n\t\tif m, err := regexp.MatchString(wantRE, got.Value); err != nil {\n\t\t\tt.Fatalf(\"bad regexp in test: %v\", err)\n\t\t} else if !m {\n\t\t\tt.Fatalf(\"hover output does not match %q; got:\\n\\n%s\", wantRE, got.Value)\n\t\t}\n\t})\n}\n\nfunc TestHoverBuiltinFile(t *testing.T) {\n\t// This test verifies that hovering in the builtin file provides the same\n\t// hover content as hovering over a use of a builtin.\n\n\tconst src = `\n-- p.go --\npackage p\n\nfunc _() {\n\tconst (\n\t\t_ = iota\n\t\t_ = true\n\t)\n\tvar (\n\t\t_ any\n\t\terr error = e{} // avoid nil deref warning\n\t)\n\t_ = err.Error\n\tprintln(\"Hello\")\n\t_ = min(1, 2)\n}\n\n// e implements Error, for use above.\ntype e struct{}\nfunc (e) Error() string\n`\n\n\t// Test hovering over various builtins with different kinds of declarations.\n\ttests := []string{\n\t\t\"iota\",\n\t\t\"true\",\n\t\t\"any\",\n\t\t\"error\",\n\t\t\"Error\",\n\t\t\"println\",\n\t\t\"min\",\n\t}\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.AfterChange(NoDiagnostics()) // avoid accidental compiler errors\n\n\t\tfor _, builtin := range tests {\n\t\t\tuseLocation := env.RegexpSearch(\"p.go\", builtin)\n\t\t\tcalleeHover, _ := env.Hover(useLocation)\n\t\t\tdeclLocation := env.FirstDefinition(useLocation)\n\t\t\tenv.OpenFile(env.Sandbox.Workdir.URIToPath(declLocation.URI))\n\t\t\tdeclHover, _ := env.Hover(declLocation)\n\t\t\tif diff := cmp.Diff(calleeHover, declHover); diff != \"\" {\n\t\t\t\tt.Errorf(\"Hover mismatch (-callee hover +decl hover):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestHoverStdlibWithAvailableVersion(t *testing.T) {\n\tconst src = `\n-- stdlib.go --\npackage stdlib\n\nimport \"fmt\"\nimport \"context\"\nimport \"crypto\"\nimport \"regexp\"\nimport \"go/doc/comment\"\n\ntype testRegexp = *regexp.Regexp\n\nfunc _() {\n\tvar ctx context.Context\n\tctx = context.Background()\n\tif ctx.Err(); e == context.Canceled {\n\t\tfmt.Println(\"Canceled\")\n\t\tfmt.Printf(\"%v\", crypto.SHA512_224)\n\t}\n\t_ := fmt.Appendf(make([]byte, 100), \"world, %d\", 23)\n\n\tvar re = regexp.MustCompile(\"\\n{2,}\")\n\tcopy := re.Copy()\n\tvar testRE testRegexp\n\ttestRE.Longest()\n\n\tvar pr comment.Printer\n\tpr.HeadingID = func(*comment.Heading) string { return \"\" }\n}\n`\n\n\ttestcases := []struct {\n\t\tsymbolRE      string // regexp matching symbol to hover over\n\t\tshouldContain bool\n\t\ttargetString  string\n\t}{\n\t\t{\"Println\", false, \"go1.0\"},   // package-level func\n\t\t{\"Appendf\", true, \"go1.19\"},   // package-level func\n\t\t{\"Background\", true, \"go1.7\"}, // package-level func\n\t\t{\"Canceled\", true, \"go1.7\"},   // package-level var\n\t\t{\"Context\", true, \"go1.7\"},    // package-level type\n\t\t{\"SHA512_224\", true, \"go1.5\"}, // package-level const\n\t\t{\"Copy\", true, \"go1.6\"},       // method\n\t\t{\"Longest\", true, \"go1.1\"},    // method with alias receiver\n\t\t{\"HeadingID\", true, \"go1.19\"}, // field\n\t}\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"stdlib.go\")\n\t\tfor _, tc := range testcases {\n\t\t\tcontent, _ := env.Hover(env.RegexpSearch(\"stdlib.go\", tc.symbolRE))\n\t\t\tif tc.shouldContain && !strings.Contains(content.Value, tc.targetString) {\n\t\t\t\tt.Errorf(\"Hover(%q) should contain string %s\", tc.symbolRE, tc.targetString)\n\t\t\t}\n\t\t\tif !tc.shouldContain && strings.Contains(content.Value, tc.targetString) {\n\t\t\t\tt.Errorf(\"Hover(%q) should not contain string %s\", tc.symbolRE, tc.targetString)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/import_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestAddImport(t *testing.T) {\n\tconst before = `package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"hello world\")\n}\n`\n\n\tconst want = `package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tfmt.Println(\"hello world\")\n}\n`\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", before)\n\t\tcmd := command.NewAddImportCommand(\"Add Import\", command.AddImportArgs{\n\t\t\tURI:        env.Sandbox.Workdir.URI(\"main.go\"),\n\t\t\tImportPath: \"bytes\",\n\t\t})\n\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.AddImport.String(),\n\t\t\tArguments: cmd.Arguments,\n\t\t}, nil)\n\t\tgot := env.BufferText(\"main.go\")\n\t\tif got != want {\n\t\t\tt.Fatalf(\"gopls.add_import failed\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestListImports(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo.go --\npackage foo\nconst C = 1\n-- import_strings_test.go --\npackage foo\nimport (\n\tx \"strings\"\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {}\n-- import_testing_test.go --\npackage foo\n\nimport \"testing\"\n\nfunc TestFoo2(t *testing.T) {}\n`\n\ttests := []struct {\n\t\tfilename string\n\t\twant     command.ListImportsResult\n\t}{\n\t\t{\n\t\t\tfilename: \"import_strings_test.go\",\n\t\t\twant: command.ListImportsResult{\n\t\t\t\tImports: []command.FileImport{\n\t\t\t\t\t{Name: \"x\", Path: \"strings\"},\n\t\t\t\t\t{Path: \"testing\"},\n\t\t\t\t},\n\t\t\t\tPackageImports: []command.PackageImport{\n\t\t\t\t\t{Path: \"strings\"},\n\t\t\t\t\t{Path: \"testing\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tfilename: \"import_testing_test.go\",\n\t\t\twant: command.ListImportsResult{\n\t\t\t\tImports: []command.FileImport{\n\t\t\t\t\t{Path: \"testing\"},\n\t\t\t\t},\n\t\t\t\tPackageImports: []command.PackageImport{\n\t\t\t\t\t{Path: \"strings\"},\n\t\t\t\t\t{Path: \"testing\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tfor _, tt := range tests {\n\t\t\tcmd := command.NewListImportsCommand(\"List Imports\", command.URIArg{\n\t\t\t\tURI: env.Sandbox.Workdir.URI(tt.filename),\n\t\t\t})\n\t\t\tvar result command.ListImportsResult\n\t\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\t\tCommand:   command.ListImports.String(),\n\t\t\t\tArguments: cmd.Arguments,\n\t\t\t}, &result)\n\t\t\tif diff := cmp.Diff(tt.want, result); diff != \"\" {\n\t\t\t\tt.Errorf(\"unexpected list imports result for %q (-want +got):\\n%s\", tt.filename, diff)\n\t\t\t}\n\t\t}\n\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/imports_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/modindex\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\n// Tests golang/go#38815.\nfunc TestIssue38815(t *testing.T) {\n\tconst needs = `\n-- go.mod --\nmodule foo\n\ngo 1.12\n-- a.go --\npackage main\nfunc f() {}\n`\n\tconst ntest = `package main\nfunc TestZ(t *testing.T) {\n\tf()\n}\n`\n\tconst want = `package main\n\nimport \"testing\"\n\nfunc TestZ(t *testing.T) {\n\tf()\n}\n`\n\n\t// it was returning\n\t// \"package main\\nimport \\\"testing\\\"\\npackage main...\"\n\tRun(t, needs, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"a_test.go\", ntest)\n\t\tenv.SaveBuffer(\"a_test.go\")\n\t\tgot := env.BufferText(\"a_test.go\")\n\t\tif want != got {\n\t\t\tt.Errorf(\"got\\n%q, wanted\\n%q\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestIssue59124(t *testing.T) {\n\tconst stuff = `\n-- go.mod --\nmodule foo\ngo 1.19\n-- a.go --\n//line foo.y:102\npackage main\n\nimport \"fmt\"\n\n//this comment is necessary for failure\nfunc _() {\n\tfmt.Println(\"hello\")\n}\n`\n\tRun(t, stuff, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\twas := env.BufferText(\"a.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tenv.OrganizeImports(\"a.go\")\n\t\tis := env.BufferText(\"a.go\")\n\t\tif diff := compare.Text(was, is); diff != \"\" {\n\t\t\tt.Errorf(\"unexpected diff after organizeImports:\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestIssue66407(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\ngo 1.21\n-- a.go --\npackage foo\n\nfunc f(x float64) float64 {\n\treturn x +  rand.Float64()\n}\n-- b.go --\npackage foo\n\nfunc _() {\n\t_ = rand.Int63()\n}\n`\n\tWithOptions(Modes(Default)).\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a.go\")\n\t\t\twas := env.BufferText(\"a.go\")\n\t\t\tenv.OrganizeImports(\"a.go\")\n\t\t\tis := env.BufferText(\"a.go\")\n\t\t\t// expect complaint that module is before 1.22\n\t\t\tenv.AfterChange(Diagnostics(ForFile(\"a.go\")))\n\t\t\tdiff := compare.Text(was, is)\n\t\t\t// check that it found the 'right' rand\n\t\t\tif !strings.Contains(diff, `import \"math/rand/v2\"`) {\n\t\t\t\tt.Errorf(\"expected rand/v2, got %q\", diff)\n\t\t\t}\n\t\t\tenv.OpenFile(\"b.go\")\n\t\t\twas = env.BufferText(\"b.go\")\n\t\t\tenv.OrganizeImports(\"b.go\")\n\t\t\t// a.go still has its module problem but b.go is fine\n\t\t\tenv.AfterChange(Diagnostics(ForFile(\"a.go\")),\n\t\t\t\tNoDiagnostics(ForFile(\"b.go\")))\n\t\t\tis = env.BufferText(\"b.go\")\n\t\t\tdiff = compare.Text(was, is)\n\t\t\tif !strings.Contains(diff, `import \"math/rand\"`) {\n\t\t\t\tt.Errorf(\"expected math/rand, got %q\", diff)\n\t\t\t}\n\t\t})\n}\n\nfunc TestVim1(t *testing.T) {\n\tconst vim1 = `package main\n\nimport \"fmt\"\n\nvar foo = 1\nvar bar = 2\n\nfunc main() {\n\tfmt.Printf(\"This is a test %v\\n\", foo)\n\tfmt.Printf(\"This is another test %v\\n\", foo)\n\tfmt.Printf(\"This is also a test %v\\n\", foo)\n}\n`\n\n\t// The file remains unchanged, but if there any quick fixes\n\t// are returned, they confuse vim (according to CL 233117).\n\t// Therefore check for no QuickFix CodeActions.\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", vim1)\n\t\tenv.OrganizeImports(\"main.go\")\n\n\t\t// Assert no quick fixes.\n\t\tfor _, act := range env.CodeActionForFile(\"main.go\", nil) {\n\t\t\tif act.Kind == protocol.QuickFix {\n\t\t\t\tt.Errorf(\"unexpected quick fix action: %#v\", act)\n\t\t\t}\n\t\t}\n\t\tif t.Failed() {\n\t\t\tgot := env.BufferText(\"main.go\")\n\t\t\tif got == vim1 {\n\t\t\t\tt.Errorf(\"no changes\")\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"got\\n%q\", got)\n\t\t\t\tt.Errorf(\"was\\n%q\", vim1)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestVim2(t *testing.T) {\n\tconst vim2 = `package main\n\nimport (\n\t\"fmt\"\n\n\t\"example.com/blah\"\n\n\t\"rubbish.com/useless\"\n)\n\nfunc main() {\n\tfmt.Println(blah.Name, useless.Name)\n}\n`\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"main.go\", vim2)\n\t\tenv.OrganizeImports(\"main.go\")\n\n\t\t// Assert no quick fixes.\n\t\tfor _, act := range env.CodeActionForFile(\"main.go\", nil) {\n\t\t\tif act.Kind == protocol.QuickFix {\n\t\t\t\tt.Errorf(\"unexpected quick-fix action: %#v\", act)\n\t\t\t}\n\t\t}\n\t})\n}\n\nconst exampleProxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/x/x.go --\npackage x\n\nconst X = 1\n-- example.com@v1.2.3/y/y.go --\npackage y\n\nconst Y = 2\n`\n\nfunc TestGOMODCACHE(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n-- main.go --\npackage main\n\nimport \"example.com/x\"\n\nvar _, _ = x.X, y.Y\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\n\topts := []RunOption{\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tProxyFiles(exampleProxy),\n\t\tWriteGoSum(\".\"),\n\t}\n\n\t// Force go list to populate GOMODCACHE\n\t// so OrganizeImports can later rely on it.\n\tt.Run(\"setup\", func(t *testing.T) {\n\t\tWithOptions(opts...).Run(t, files, func(t *testing.T, env *Env) {})\n\t})\n\n\tWithOptions(opts...).Run(t, files, func(t *testing.T, env *Env) {\n\t\t// Expect y is undefined.\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", `y.Y`),\n\t\t\t\tWithMessage(\"undefined\")),\n\t\t)\n\n\t\t// Apply suggested fix via OrganizeImports.\n\t\tenv.SaveBuffer(\"main.go\") // => OrganizeImports\n\t\tif true {\n\t\t\t// according to https://github.com/golang/go/issues/77894\n\t\t\t// this test is flaky. Print some possibly helpful diagnostic\n\t\t\t// information.\n\t\t\tix, err := modindex.Read(modcache)\n\t\t\tif err != nil {\n\t\t\t\tt.Logf(\"could not read modcache index: %v\", err)\n\t\t\t} else if len(ix.Entries) != 2 {\n\t\t\t\tt.Logf(\"%d modcache entries\", len(ix.Entries))\n\t\t\t\tif len(ix.Entries) == 0 {\n\t\t\t\t\tfis, err := os.ReadDir(modcache)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Logf(\"could not read modcache dir: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tt.Logf(\"%d modcache files\", len(fis))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\n\t\t// Verify that y.Y is defined within the module cache.\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `y.(Y)`))\n\t\tpath := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif !strings.HasPrefix(path, filepath.ToSlash(modcache)) {\n\t\t\tt.Errorf(\"found module dependency outside of GOMODCACHE: got %v, wanted subdir of %v\", path, filepath.ToSlash(modcache))\n\t\t}\n\t})\n}\n\n// make sure it gets the v2\n/* marker test?\n\nAdd proxy data with the special proxy/ prefix (see gopls/internal/test/marker/testdata/quickfix/unusedrequire.txt).\nInvoke the organizeImports codeaction directly (see gopls/internal/test/marker/testdata/codeaction/imports.txt, but use the edit=golden named argument instead of result= to minimize the size of the golden output.\n*/\nfunc Test58382(t *testing.T) {\n\tfiles := `-- main.go --\npackage main\nimport \"fmt\"\nfunc main() {\n\tfmt.Println(xurls.Relaxed().FindAllString())\n}\n-- go.mod --\nmodule demo\ngo 1.20\n`\n\tcache := `-- mvdan.cc/xurls@v2.5.0/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n--  github.com/mvdan/xurls/v2@v1.1.0/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\tmx := fake.UnpackTxt(cache)\n\n\tfor k, v := range mx {\n\t\tfname := filepath.Join(modcache, k)\n\t\tdir := filepath.Dir(fname)\n\t\tos.MkdirAll(dir, 0777) // ignore error\n\t\tif err := os.WriteFile(fname, v, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif true {\n\t\t\t// for diagnosing flakiness\n\t\t\tt.Logf(\"wrote %s:%d\", fname, len(v))\n\t\t}\n\t}\n\tWithOptions(\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tWriteGoSum(\".\"),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t\tNoLogsOnError(),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tout := env.BufferText(\"main.go\")\n\t\tif !strings.Contains(out, \"xurls/v2\") {\n\t\t\tt.Errorf(\"did not get v2 in %q\", out)\n\t\t\t// golang/go#77552 finds this test flaky, so print out more\n\t\t\tix, err := modindex.Read(modcache)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tt.Logf(\"%d entries\", len(ix.Entries))\n\t\t\tfor i, e := range ix.Entries {\n\t\t\t\tt.Logf(\"%d: %s, %s, %d\", i, e.ImportPath, e.Dir, len(e.Names))\n\t\t\t}\n\t\t}\n\t})\n}\n\n// get the version requested in the go.mod file, not /v2\nfunc Test61208(t *testing.T) {\n\tfiles := `-- main.go --\npackage main\nimport \"fmt\"\nfunc main() {\n\tfmt.Println(xurls.Relaxed().FindAllString())\n}\n-- go.mod --\nmodule demo\ngo 1.20\nrequire github.com/mvdan/xurls v1.1.0\n`\n\tcache := `-- mvdan.cc/xurls/v2@v2.5.0/a/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n--  github.com/mvdan/xurls@v1.1.0/a/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\tmx := fake.UnpackTxt(cache)\n\tfor k, v := range mx {\n\t\tfname := filepath.Join(modcache, k)\n\t\tdir := filepath.Dir(fname)\n\t\tos.MkdirAll(dir, 0777) // ignore error\n\t\tif err := os.WriteFile(fname, v, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tWithOptions(\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tWriteGoSum(\".\"),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tout := env.BufferText(\"main.go\")\n\t\tif !strings.Contains(out, \"github.com/mvdan/xurls\") {\n\t\t\tt.Errorf(\"did not get github.com/mvdan/xurls in %q\", out)\n\t\t}\n\t})\n}\n\n// get the version already used in the module\nfunc Test60663(t *testing.T) {\n\tfiles := `-- main.go --\npackage main\nimport \"fmt\"\nfunc main() {\n\tfmt.Println(xurls.Relaxed().FindAllString())\n}\n-- go.mod --\nmodule demo\ngo 1.20\n-- a.go --\npackage main\nimport \"github.com/mvdan/xurls\"\nvar _ = xurls.Relaxed()\n`\n\tcache := `-- mvdan.cc/xurls/v2@v2.5.0/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n--  github.com/mvdan/xurls@v1.1.0/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\tmx := fake.UnpackTxt(cache)\n\tfor k, v := range mx {\n\t\tfname := filepath.Join(modcache, k)\n\t\tdir := filepath.Dir(fname)\n\t\tos.MkdirAll(dir, 0777) // ignore error\n\t\tif err := os.WriteFile(fname, v, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tWithOptions(\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tWriteGoSum(\".\"),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tout := env.BufferText(\"main.go\")\n\t\tif !strings.Contains(out, \"github.com/mvdan/xurls\") {\n\t\t\tt.Errorf(\"did not get github.com/mvdan/xurls in %q\", out)\n\t\t}\n\t})\n}\n\n// use the import from a different package in the same module\nfunc Test44510(t *testing.T) {\n\tconst files = `-- go.mod --\nmodule test\ngo 1.19\n-- foo/foo.go --\npackage main\nimport strs \"strings\"\nvar _ = strs.Count\n-- bar/bar.go --\npackage main\nvar _ = strs.Builder\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t).Run(t, files, func(T *testing.T, env *Env) {\n\t\tenv.OpenFile(\"bar/bar.go\")\n\t\tenv.SaveBuffer(\"bar/bar.go\")\n\t\tbuf := env.BufferText(\"bar/bar.go\")\n\t\tif !strings.Contains(buf, \"strs\") {\n\t\t\tt.Error(buf)\n\t\t}\n\t})\n}\n\nfunc TestIssue67156(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com/a\n\ngo 1.20\n\nrequire example.com v1.2.3\n\n-- main.go --\npackage main\n\nimport \"example.com/x\"\n\nvar _, _ = x.X, y.Y\n`\n\tmodcache := t.TempDir()\n\tbase := filepath.Base(modcache)\n\tdefer CleanModCache(t, modcache)\n\n\t// Construct a very unclean module cache whose length exceeds the length of\n\t// the clean directory path, to reproduce the crash in golang/go#67156\n\tconst sep = string(filepath.Separator)\n\tmodcache += strings.Repeat(sep+\"..\"+sep+base, 10)\n\n\topts := []RunOption{\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tProxyFiles(exampleProxy),\n\t\tWriteGoSum(\".\"),\n\t}\n\n\tt.Run(\"setup\", func(t *testing.T) {\n\t\t// Force go list to populate GOMODCACHE.\n\t\tWithOptions(opts...).Run(t, files, func(t *testing.T, env *Env) {})\n\n\t\t// Update module index.\n\t\tif ix, err := modindex.Update(modcache); err != nil {\n\t\t\tt.Fatalf(\"failed to obtain updated module index: %v\", err)\n\t\t} else if len(ix.Entries) != 2 {\n\t\t\tt.Fatalf(\"got %v, want 2 entries\", ix)\n\t\t}\n\t})\n\n\tWithOptions(opts...).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"main.go\", `y.Y`)))\n\t\tenv.SaveBuffer(\"main.go\") // => OrganizeImports\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"main.go\")))\n\t})\n}\n\n// Tests golang/go#40685.\nfunc TestAcceptImportsQuickFixTestVariant(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nimport (\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n\tos.Stat(\"\")\n}\n-- a/a_test.go --\npackage a\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestA(t *testing.T) {\n\tos.Stat(\"\")\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"os.Stat\")),\n\t\t\tReadDiagnostics(\"a/a.go\", &d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"a/a.go\", d.Diagnostics)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t})\n}\n\n// Test of golang/go#70755\nfunc TestQuickFixIssue70755(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\ngo 1.19.0 // with go 1.23.0 this fails on some builders\n-- bar/bar.go --\npackage notbar\ntype NotBar struct {}\n-- baz/baz.go --\npackage baz\ntype Baz struct {}\n-- foo/foo.go --\npackage foo\ntype Foo struct {\n\tbar notbar.NotBar\n\tbaz baz.Baz\n}`\n\tWithOptions(\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls}).\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"foo/foo.go\")\n\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\tenv.AfterChange(ReadDiagnostics(\"foo/foo.go\", &d))\n\t\t\tenv.ApplyQuickFixes(\"foo/foo.go\", d.Diagnostics)\n\t\t\t// at this point 'import notbar \"mod.com/bar\"' has been added\n\t\t\t// but it's still missing the import of \"mod.com/baz\"\n\t\t\ty := env.BufferText(\"foo/foo.go\")\n\t\t\tif !strings.Contains(y, `notbar \"mod.com/bar\"`) {\n\t\t\t\tt.Error(\"quick fix did not find notbar\")\n\t\t\t}\n\t\t\tenv.SaveBuffer(\"foo/foo.go\")\n\t\t\tenv.AfterChange(NoDiagnostics(ForFile(\"foo/foo.go\")))\n\t\t})\n}\n\n// Test for golang/go#52784\nfunc TestGoWorkImports(t *testing.T) {\n\tconst pkg = `\n-- go.work --\ngo 1.19\n\nuse (\n        ./caller\n        ./mod\n)\n-- caller/go.mod --\nmodule caller.com\n\ngo 1.18\n\nrequire mod.com v0.0.0\n\nreplace mod.com => ../mod\n-- caller/caller.go --\npackage main\n\nfunc main() {\n        a.Test()\n}\n-- mod/go.mod --\nmodule mod.com\n\ngo 1.18\n-- mod/a/a.go --\npackage a\n\nfunc Test() {\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"caller/caller.go\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"caller/caller.go\", \"a.Test\")))\n\n\t\t// Saving caller.go should trigger goimports, which should find a.Test in\n\t\t// the mod.com module, thanks to the go.work file.\n\t\tenv.SaveBuffer(\"caller/caller.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"caller/caller.go\")))\n\t})\n}\n\n// prefer the undeprecated alternative 70736\nfunc TestDeprecated70736(t *testing.T) {\n\tt.Logf(\"GOOS %s, GARCH %s version %s\", runtime.GOOS, runtime.GOARCH, runtime.Version())\n\tfiles := `-- main.go --\npackage main\nfunc main() {\n\tvar v = xurls.Relaxed().FindAllString()\n\tvar w = xurls.A\n}\n-- go.mod --\nmodule demo\ngo 1.20\n`\n\tcache := `-- mvdan.cc/xurls/v2@v2.5.0/xurls.go --\npackage xurls\n// Deprecated:\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\nvar A int\n--  github.com/mvdan/xurls@v1.1.0/xurls.go --\npackage xurls\nfunc Relaxed() *regexp.Regexp {\nreturn nil\n}\nvar A int\n`\n\tmodcache := t.TempDir()\n\tdefer CleanModCache(t, modcache)\n\tmx := fake.UnpackTxt(cache)\n\tfor k, v := range mx {\n\t\tfname := filepath.Join(modcache, k)\n\t\tdir := filepath.Dir(fname)\n\t\tos.MkdirAll(dir, 0777) // ignore error\n\t\tif err := os.WriteFile(fname, v, 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tWithOptions(\n\t\tEnvVars{\"GOMODCACHE\": modcache},\n\t\tWriteGoSum(\".\"),\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tout := env.BufferText(\"main.go\")\n\t\tif strings.Contains(out, \"xurls/v2\") {\n\t\t\tt.Errorf(\"chose deprecated v2 in %q\", out)\n\t\t}\n\t})\n}\n\n// Find the non-test package asked for in a test\nfunc TestTestImports(t *testing.T) {\n\tconst pkg = `\n-- go.work --\ngo 1.19\n\nuse (\n        ./caller\n        ./mod\n\t\t./xxx\n)\n-- caller/go.mod --\nmodule caller.com\n\ngo 1.18\n\nrequire mod.com v0.0.0\nrequire xxx.com v0.0.0\n\nreplace mod.com => ../mod\nreplace xxx.com => ../xxx\n-- caller/caller_test.go --\npackage main\n\nvar _ = a.Test\n-- xxx/go.mod --\nmodule xxx.com\n\ngo 1.18\n-- xxx/a/a_test.go --\npackage a\n\nfunc Test() {\n}\n-- mod/go.mod --\nmodule mod.com\n\ngo 1.18\n-- mod/a/a.go --\npackage a\n\nfunc Test() {\n}\n`\n\tWithOptions(Modes(Default)).Run(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"caller/caller_test.go\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"caller/caller_test.go\", \"a.Test\")))\n\n\t\t// Saving caller_test.go should trigger goimports, which should find a.Test in\n\t\t// the mod.com module, thanks to the go.work file.\n\t\tenv.SaveBuffer(\"caller/caller_test.go\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"caller/caller_test.go\")))\n\t\tbuf := env.BufferText(\"caller/caller_test.go\")\n\t\tif !strings.Contains(buf, \"mod.com/a\") {\n\t\t\tt.Errorf(\"got %q, expected a mod.com/a\", buf)\n\t\t}\n\t})\n}\n\n// this test replaces 'package bar' with 'package foo'\n// saves the file, and then looks for the import in the main package.s\nfunc Test67973(t *testing.T) {\n\tconst files = `-- go.mod --\nmodule hello\ngo 1.19\n-- hello.go --\npackage main\nvar _ = foo.Bar\n-- internal/foo/foo.go --\npackage bar\nfunc Bar() {}\n`\n\tWithOptions(\n\t\tSettings{\"importsSource\": settings.ImportsSourceGopls},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"hello.go\")\n\t\tenv.AfterChange(env.DoneWithOpen())\n\t\tenv.SaveBuffer(\"hello.go\")\n\t\tenv.OpenFile(\"internal/foo/foo.go\")\n\t\tenv.RegexpReplace(\"internal/foo/foo.go\", \"bar\", \"foo\")\n\t\tenv.SaveBuffer(\"internal/foo/foo.go\")\n\t\tenv.SaveBuffer(\"hello.go\")\n\t\tbuf := env.BufferText(\"hello.go\")\n\t\tif !strings.Contains(buf, \"internal/foo\") {\n\t\t\tt.Errorf(`expected import \"hello/internal/foo\" but got %q`, buf)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/link_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestHoverAndDocumentLink(t *testing.T) {\n\tconst program = `\n-- go.mod --\nmodule mod.test\n\ngo 1.12\n\nrequire import.test v1.2.3\n\nrequire replace.test v1.2.3\nreplace replace.test => replace.test v1.2.4\n\nrequire replace.fixed.test v1.2.3\nreplace replace.fixed.test v1.2.3 => replace.fixed.test v1.2.4\n\nrequire replace.another.test v1.2.3\nreplace replace.another.test => another.test v1.2.3\n\n\nreplace example.com/non-exist => ./\nreplace example.com/non-exist1 => ../work/\n\n-- main.go --\npackage main\n\nimport \"import.test/pkg\"\nimport \"replace.test/replace\"\nimport \"replace.fixed.test/fixed\"\nimport \"replace.another.test/another\"\n\nfunc main() {\n\t// Issue 43990: this is not a link that most users can open from an LSP\n\t// client: mongodb://not.a.link.com\n\tprintln(pkg.Hello)\n\tprintln(replace.Hello)\n\tprintln(fixed.Hello)\n\tprintln(another.Hello)\n}`\n\n\tconst proxy = `\n-- import.test@v1.2.3/go.mod --\nmodule import.test\n\ngo 1.12\n-- import.test@v1.2.3/pkg/const.go --\n// package documentation\npackage pkg\n\n\n-- replace.test@v1.2.4/go.mod --\nmodule replace.test\n\ngo 1.12\n-- replace.test@v1.2.4/replace/const.go --\npackage replace\n\nconst Hello = \"Hello\"\n\n-- replace.fixed.test@v1.2.4/go.mod --\nmodule replace.fixed.test\n\ngo 1.12\n-- replace.fixed.test@v1.2.4/fixed/const.go --\npackage fixed\n\nconst Hello = \"Hello\"\n\n-- another.test@v1.2.3/go.mod --\nmodule another.test\n\ngo 1.12\n-- another.test@v1.2.3/another/const.go --\npackage another\n\nconst Hello = \"Hello\"\n`\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tWriteGoSum(\".\"),\n\t).Run(t, program, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OpenFile(\"go.mod\")\n\n\t\tconst (\n\t\t\tmodImportLink        = \"https://pkg.go.dev/mod/import.test@v1.2.3\"\n\t\t\tmodReplaceLink       = \"https://pkg.go.dev/mod/replace.test@v1.2.4\"\n\t\t\tmodReplaceFixedeLink = \"https://pkg.go.dev/mod/replace.fixed.test@v1.2.4\"\n\t\t\tmodAnotherLink       = \"https://pkg.go.dev/mod/another.test@v1.2.3\"\n\n\t\t\tpkgImportLink       = \"https://pkg.go.dev/import.test@v1.2.3/pkg\"\n\t\t\tpkgReplaceLink      = \"https://pkg.go.dev/replace.test@v1.2.4/replace\"\n\t\t\tpkgReplaceFixedLink = \"https://pkg.go.dev/replace.fixed.test@v1.2.4/fixed\"\n\t\t\tpkgAnotherLink      = \"https://pkg.go.dev/another.test@v1.2.3/another\"\n\t\t\tpkgDoc              = \"package documentation\"\n\t\t)\n\n\t\t// First, check that we get the expected links via hover and documentLink.\n\t\tcontent, _ := env.Hover(env.RegexpSearch(\"main.go\", \"()pkg.Hello\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgImportLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgImportLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"main.go\", \"()replace.Hello\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgReplaceLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgReplaceLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"main.go\", \"()fixed.Hello\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgReplaceFixedLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgReplaceFixedLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"main.go\", \"()another.Hello\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgAnotherLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgAnotherLink)\n\t\t}\n\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"go.mod\", \"()import.test\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgImportLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgImportLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"go.mod\", \"()replace.test\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgReplaceLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgReplaceLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"go.mod\", \"()replace.fixed.test\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgReplaceFixedLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgReplaceFixedLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"go.mod\", \"()replace.another.test\"))\n\t\tif content == nil || !strings.Contains(content.Value, pkgAnotherLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want contains %q\", content, pkgAnotherLink)\n\t\t}\n\n\t\tgetLinks := func(links []protocol.DocumentLink) []string {\n\t\t\tvar got []string\n\t\t\tfor i := range links {\n\t\t\t\tgot = append(got, *links[i].Target)\n\t\t\t}\n\t\t\treturn got\n\t\t}\n\t\tlinks := env.DocumentLink(\"main.go\")\n\t\tgot, want := getLinks(links), []string{\n\t\t\tpkgImportLink,\n\t\t\tpkgReplaceLink,\n\t\t\tpkgReplaceFixedLink,\n\t\t\tpkgAnotherLink,\n\t\t}\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"documentLink: got links %v for main.go, want links %v\", got, want)\n\t\t}\n\n\t\tlinks = env.DocumentLink(\"go.mod\")\n\t\tlocalReplacePath := filepath.Join(env.Sandbox.Workdir.RootURI().Path(), \"go.mod\")\n\t\tgot, want = getLinks(links), []string{\n\t\t\tlocalReplacePath, localReplacePath,\n\t\t\tmodImportLink,\n\t\t\tmodReplaceLink,\n\t\t\tmodReplaceFixedeLink,\n\t\t\tmodAnotherLink,\n\t\t}\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"documentLink: got links %v for go.mod, want links %v\", got, want)\n\t\t}\n\n\t\t// Then change the environment to make these links private.\n\t\tcfg := env.Editor.Config()\n\t\tcfg.Env = map[string]string{\"GOPRIVATE\": \"import.test\"}\n\t\tenv.ChangeConfiguration(cfg)\n\n\t\t// Finally, verify that the links are gone.\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"main.go\", \"()pkg.Hello\"))\n\t\tif content == nil || strings.Contains(content.Value, pkgImportLink) {\n\t\t\tt.Errorf(\"hover: got %v in main.go, want non-empty hover without %q\", content, pkgImportLink)\n\t\t}\n\t\tcontent, _ = env.Hover(env.RegexpSearch(\"go.mod\", \"()import.test\"))\n\t\tif content == nil || strings.Contains(content.Value, modImportLink) {\n\t\t\tt.Errorf(\"hover: got %v in go.mod, want contains %q\", content, modImportLink)\n\t\t}\n\n\t\tlinks = env.DocumentLink(\"main.go\")\n\t\tgot, want = getLinks(links), []string{\n\t\t\tpkgReplaceLink,\n\t\t\tpkgReplaceFixedLink,\n\t\t\tpkgAnotherLink,\n\t\t}\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"documentLink: got links %v for main.go, want links %v\", got, want)\n\t\t}\n\n\t\tlinks = env.DocumentLink(\"go.mod\")\n\t\tgot, want = getLinks(links), []string{\n\t\t\tlocalReplacePath, localReplacePath,\n\t\t\tmodReplaceLink,\n\t\t\tmodReplaceFixedeLink,\n\t\t\tmodAnotherLink,\n\t\t}\n\t\tif !slices.Equal(got, want) {\n\t\t\tt.Errorf(\"documentLink: got links %v for go.mod, want links %v\", got, want)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/misc_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/telemetry/counter/countertest\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\ttmp, err := os.MkdirTemp(\"\", \"gopls-misc-test-counters\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tcountertest.Open(tmp)\n\tcode := Main(m)\n\tos.RemoveAll(tmp) // ignore error (cleanup fails on Windows; golang/go#68243)\n\tos.Exit(code)\n}\n\n// TestDocumentURIFix ensures that a DocumentURI supplied by the\n// client is subject to the \"fixing\" operation documented at\n// [protocol.DocumentURI.UnmarshalText]. The details of the fixing are\n// tested in the protocol package; here we aim to test only that it\n// occurs at all.\nfunc TestDocumentURIFix(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule testdata\ngo 1.18\n\n-- a.go --\npackage a\n\nconst K = 1\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tloc := env.RegexpSearch(\"a.go\", \"K\")\n\t\tpath := strings.TrimPrefix(string(loc.URI), \"file://\") // (absolute)\n\n\t\tcheck := func() {\n\t\t\tt.Helper()\n\t\t\tt.Logf(\"URI = %s\", loc.URI)\n\t\t\tcontent, _ := env.Hover(loc) // must succeed\n\t\t\tif content == nil || !strings.Contains(content.Value, \"const K\") {\n\t\t\t\tt.Errorf(\"wrong content: %#v\", content)\n\t\t\t}\n\t\t}\n\n\t\t// Regular URI (e.g. file://$TMPDIR/TestDocumentURIFix/default/work/a.go)\n\t\tcheck()\n\n\t\t// URL-encoded path (e.g. contains %2F instead of last /)\n\t\tloc.URI = protocol.DocumentURI(\"file://\" + strings.Replace(path, \"/a.go\", \"%2Fa.go\", 1))\n\t\tcheck()\n\n\t\t// We intentionally do not test further cases (e.g.\n\t\t// file:// without a third slash) as it would quickly\n\t\t// get bogged down in irrelevant details of the\n\t\t// fake editor's own handling of URIs.\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/modify_tags_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestModifyTags(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.20\n\n-- a.go --\npackage a\n\ntype A struct {\n\tB string\n\tC int\n\tD bool\n\tE string\n}\n\n-- b.go --\npackage b\n\ntype B struct {\n\tB string ` + \"`json:\\\"b,omitempty\\\"`\" + `\n\tC int    ` + \"`json:\\\"c,omitempty\\\"`\" + `\n\tD bool   ` + \"`json:\\\"d,omitempty\\\"`\" + `\n\tE string ` + \"`json:\\\"e,omitempty\\\"`\" + `\n}\n\n-- c.go --\npackage c\n\ntype C struct {\n\tB string\n\tC int\n\tD bool ` + \"`json:\\\"d,omitempty\\\"`\" + `\n\tE string\n}\n`\n\n\tconst wantAddTagsEntireStruct = `package a\n\ntype A struct {\n\tB string ` + \"`json:\\\"b,omitempty\\\"`\" + `\n\tC int    ` + \"`json:\\\"c,omitempty\\\"`\" + `\n\tD bool   ` + \"`json:\\\"d,omitempty\\\"`\" + `\n\tE string ` + \"`json:\\\"e,omitempty\\\"`\" + `\n}\n`\n\n\tconst wantRemoveTags = `package b\n\ntype B struct {\n\tB string\n\tC int\n\tD bool   ` + \"`json:\\\"d,omitempty\\\"`\" + `\n\tE string ` + \"`json:\\\"e,omitempty\\\"`\" + `\n}\n`\n\n\tconst wantAddTagsSingleLine = `package a\n\ntype A struct {\n\tB string\n\tC int\n\tD bool ` + \"`json:\\\"d,omitempty\\\"`\" + `\n\tE string\n}\n`\n\n\tconst wantRemoveOptions = `package c\n\ntype C struct {\n\tB string\n\tC int\n\tD bool ` + \"`json:\\\"d\\\"`\" + `\n\tE string\n}\n`\n\n\ttests := []struct {\n\t\tfile string\n\t\targs command.ModifyTagsArgs\n\t\twant string\n\t}{\n\t\t{file: \"a.go\", args: command.ModifyTagsArgs{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 2, Character: 0},\n\t\t\t\tEnd:   protocol.Position{Line: 8, Character: 0},\n\t\t\t},\n\t\t\tAdd:        \"json\",\n\t\t\tAddOptions: \"json=omitempty\",\n\t\t}, want: wantAddTagsEntireStruct},\n\t\t{file: \"b.go\", args: command.ModifyTagsArgs{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 3, Character: 2},\n\t\t\t\tEnd:   protocol.Position{Line: 4, Character: 6},\n\t\t\t},\n\t\t\tRemove: \"json\",\n\t\t}, want: wantRemoveTags},\n\t\t{file: \"a.go\", args: command.ModifyTagsArgs{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 5, Character: 0},\n\t\t\t\tEnd:   protocol.Position{Line: 5, Character: 7},\n\t\t\t},\n\t\t\tAdd:        \"json\",\n\t\t\tAddOptions: \"json=omitempty\",\n\t\t}, want: wantAddTagsSingleLine},\n\t\t{file: \"c.go\", args: command.ModifyTagsArgs{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: protocol.Position{Line: 3, Character: 0},\n\t\t\t\tEnd:   protocol.Position{Line: 7, Character: 0},\n\t\t\t},\n\t\t\tRemoveOptions: \"json=omitempty\",\n\t\t}, want: wantRemoveOptions},\n\t}\n\n\tfor _, test := range tests {\n\t\tintegration.Run(t, files, func(t *testing.T, env *integration.Env) {\n\t\t\turi := env.Sandbox.Workdir.URI(test.file)\n\t\t\targs, err := command.MarshalArgs(\n\t\t\t\tcommand.ModifyTagsArgs{\n\t\t\t\t\tURI:           uri,\n\t\t\t\t\tRange:         test.args.Range,\n\t\t\t\t\tAdd:           test.args.Add,\n\t\t\t\t\tAddOptions:    test.args.AddOptions,\n\t\t\t\t\tRemove:        test.args.Remove,\n\t\t\t\t\tRemoveOptions: test.args.RemoveOptions,\n\t\t\t\t},\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar res any\n\t\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\t\tCommand:   command.ModifyTags.String(),\n\t\t\t\tArguments: args,\n\t\t\t}, &res)\n\t\t\t// Wait until we finish writing to the file.\n\t\t\tenv.AfterChange()\n\t\t\tif got := env.BufferText(test.file); got != test.want {\n\t\t\t\tt.Errorf(\"modify_tags returned unexpected diff (-want +got):\\n%s\", compare.Text(test.want, got))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/multiple_adhoc_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestMultipleAdHocPackages(t *testing.T) {\n\tRun(t, `\n-- a/a.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"\")\n}\n-- a/b.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() () {\n\tfmt.Println(\"\")\n}\n`, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tif list := env.Completion(env.RegexpSearch(\"a/a.go\", \"()Println\")); list == nil || len(list.Items) == 0 {\n\t\t\tt.Fatal(\"expected completions, got none\")\n\t\t}\n\t\tenv.OpenFile(\"a/b.go\")\n\t\tif list := env.Completion(env.RegexpSearch(\"a/b.go\", \"()Println\")); list == nil || len(list.Items) == 0 {\n\t\t\tt.Fatal(\"expected completions, got none\")\n\t\t}\n\t\tif list := env.Completion(env.RegexpSearch(\"a/a.go\", \"()Println\")); list == nil || len(list.Items) == 0 {\n\t\t\tt.Fatal(\"expected completions, got none\")\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/package_symbols_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestPackageSymbols(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.20\n\n-- a.go --\npackage a\n\nvar A = \"var\"\ntype S struct{}\n\nfunc (s *S) M1() {}\n-- b.go --\npackage a\n\nvar b = 1\n\nfunc (s *S) M2() {}\n\nfunc (s *S) M3() {}\n\nfunc F() {}\n-- unloaded.go --\n//go:build unloaded\n\npackage a\n\nvar Unloaded int\n`\n\tintegration.Run(t, files, func(t *testing.T, env *integration.Env) {\n\t\taURI := env.Sandbox.Workdir.URI(\"a.go\")\n\t\tbURI := env.Sandbox.Workdir.URI(\"b.go\")\n\t\targs, err := command.MarshalArgs(command.PackageSymbolsArgs{\n\t\t\tURI: aURI,\n\t\t})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tvar res command.PackageSymbolsResult\n\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.PackageSymbols.String(),\n\t\t\tArguments: args,\n\t\t}, &res)\n\n\t\twant := command.PackageSymbolsResult{\n\t\t\tPackageName: \"a\",\n\t\t\tFiles:       []protocol.DocumentURI{aURI, bURI},\n\t\t\tSymbols: []command.PackageSymbol{\n\t\t\t\t{Name: \"A\", Kind: protocol.Variable, File: 0},\n\t\t\t\t{Name: \"F\", Kind: protocol.Function, File: 1},\n\t\t\t\t{Name: \"S\", Kind: protocol.Struct, File: 0, Children: []command.PackageSymbol{\n\t\t\t\t\t{Name: \"M1\", Kind: protocol.Method, File: 0},\n\t\t\t\t\t{Name: \"M2\", Kind: protocol.Method, File: 1},\n\t\t\t\t\t{Name: \"M3\", Kind: protocol.Method, File: 1},\n\t\t\t\t}},\n\t\t\t\t{Name: \"b\", Kind: protocol.Variable, File: 1},\n\t\t\t},\n\t\t}\n\t\tignore := cmpopts.IgnoreFields(command.PackageSymbol{}, \"Range\", \"SelectionRange\", \"Detail\")\n\t\tif diff := cmp.Diff(want, res, ignore); diff != \"\" {\n\t\t\tt.Errorf(\"package_symbols returned unexpected diff (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tfor file, want := range map[string]command.PackageSymbolsResult{\n\t\t\t\"go.mod\": {},\n\t\t\t\"unloaded.go\": {\n\t\t\t\tPackageName: \"a\",\n\t\t\t\tFiles:       []protocol.DocumentURI{env.Sandbox.Workdir.URI(\"unloaded.go\")},\n\t\t\t\tSymbols: []command.PackageSymbol{\n\t\t\t\t\t{Name: \"Unloaded\", Kind: protocol.Variable, File: 0},\n\t\t\t\t},\n\t\t\t},\n\t\t} {\n\t\t\turi := env.Sandbox.Workdir.URI(file)\n\t\t\targs, err := command.MarshalArgs(command.PackageSymbolsArgs{\n\t\t\t\tURI: uri,\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar res command.PackageSymbolsResult\n\t\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\t\tCommand:   command.PackageSymbols.String(),\n\t\t\t\tArguments: args,\n\t\t\t}, &res)\n\n\t\t\tif diff := cmp.Diff(want, res, ignore); diff != \"\" {\n\t\t\t\tt.Errorf(\"package_symbols returned unexpected diff (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/prompt_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/telemetry/counter/countertest\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test prompt file in old and new formats are handled as expected.\nfunc TestTelemetryPrompt_PromptFile(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\n\tdefaultTelemetryStartTime := \"1714521600\" // 2024-05-01\n\tdefaultToken := \"7\"\n\tsamplesPerMille := \"500\"\n\n\ttestCases := []struct {\n\t\tname, in, want string\n\t\twantPrompt     bool\n\t}{\n\t\t{\n\t\t\tname:       \"empty\",\n\t\t\tin:         \"\",\n\t\t\twant:       \"failed 1 1714521600 7\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.15-format/invalid\",\n\t\t\tin:         \"pending\",\n\t\t\twant:       \"failed 1 1714521600 7\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.15-format/pPending\",\n\t\t\tin:         \"pending 1\",\n\t\t\twant:       \"failed 2 1714521600 7\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.15-format/pPending\",\n\t\t\tin:         \"failed 1\",\n\t\t\twant:       \"failed 2 1714521600 7\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname: \"v0.15-format/pYes\",\n\t\t\tin:   \"yes 1\",\n\t\t\twant: \"yes 1\", // untouched since short-circuited\n\t\t},\n\t\t{\n\t\t\tname: \"v0.16-format/pNotReady\",\n\t\t\tin:   \"- 0 1714521600 1000\",\n\t\t\twant: \"- 0 1714521600 1000\",\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.16-format/pPending\",\n\t\t\tin:         \"pending 1 1714521600 1\",\n\t\t\twant:       \"failed 2 1714521600 1\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.16-format/pFailed\",\n\t\t\tin:         \"failed 2 1714521600 1\",\n\t\t\twant:       \"failed 3 1714521600 1\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"v0.16-format/invalid\",\n\t\t\tin:         \"xxx 0 12345 678\",\n\t\t\twant:       \"failed 1 1714521600 7\",\n\t\t\twantPrompt: true,\n\t\t},\n\t\t{\n\t\t\tname: \"v0.16-format/extra\",\n\t\t\tin:   \"- 0 1714521600 1000 7777 xxx\",\n\t\t\twant: \"- 0 1714521600 1000\", // drop extra\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\t\t\tgoplsConfigDir := t.TempDir()\n\t\t\tpromptDir := filepath.Join(goplsConfigDir, \"prompt\")\n\t\t\tpromptFile := filepath.Join(promptDir, \"telemetry\")\n\n\t\t\tif err := os.MkdirAll(promptDir, 0777); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif err := os.WriteFile(promptFile, []byte(tc.in), 0666); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tWithOptions(\n\t\t\t\tModes(Default), // no need to run this in all modes\n\t\t\t\tEnvVars{\n\t\t\t\t\tserver.GoplsConfigDirEnvvar:                  goplsConfigDir,\n\t\t\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: defaultTelemetryStartTime,\n\t\t\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     defaultToken,\n\t\t\t\t\tserver.FakeSamplesPerMille:                   samplesPerMille,\n\t\t\t\t},\n\t\t\t\tSettings{\n\t\t\t\t\t\"telemetryPrompt\": true,\n\t\t\t\t},\n\t\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\t\texpectation := ShownMessageRequest(\".*Would you like to enable Go telemetry?\")\n\t\t\t\tif !tc.wantPrompt {\n\t\t\t\t\texpectation = Not(expectation)\n\t\t\t\t}\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 1, true),\n\t\t\t\t\texpectation,\n\t\t\t\t)\n\t\t\t\tif got, err := os.ReadFile(promptFile); err != nil || string(got) != tc.want {\n\t\t\t\t\tt.Fatalf(\"(%q) -> (%q, %v), want %q\", tc.in, got, err, tc.want)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Test that gopls prompts for telemetry only when it is supposed to.\nfunc TestTelemetryPrompt_Conditions_Mode(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\n\tfor _, enabled := range []bool{true, false} {\n\t\tt.Run(fmt.Sprintf(\"telemetryPrompt=%v\", enabled), func(t *testing.T) {\n\t\t\tfor _, initialMode := range []string{\"\", \"local\", \"off\", \"on\"} {\n\t\t\t\tt.Run(fmt.Sprintf(\"initial_mode=%s\", initialMode), func(t *testing.T) {\n\t\t\t\t\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\t\t\t\t\tif initialMode != \"\" {\n\t\t\t\t\t\tif err := os.WriteFile(modeFile, []byte(initialMode), 0666); err != nil {\n\t\t\t\t\t\t\tt.Fatal(err)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ttelemetryStartTime := time.Now().Add(-8 * 24 * time.Hour) // telemetry started a while ago\n\t\t\t\t\tWithOptions(\n\t\t\t\t\t\tModes(Default), // no need to run this in all modes\n\t\t\t\t\t\tEnvVars{\n\t\t\t\t\t\t\tserver.GoplsConfigDirEnvvar:                  t.TempDir(),\n\t\t\t\t\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\t\t\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: strconv.FormatInt(telemetryStartTime.Unix(), 10),\n\t\t\t\t\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     \"1\", // always sample because samplingPerMille >= 1.\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSettings{\n\t\t\t\t\t\t\t\"telemetryPrompt\": enabled,\n\t\t\t\t\t\t},\n\t\t\t\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\t\t\t\twantPrompt := enabled && (initialMode == \"\" || initialMode == \"local\")\n\t\t\t\t\t\texpectation := ShownMessageRequest(\".*Would you like to enable Go telemetry?\")\n\t\t\t\t\t\tif !wantPrompt {\n\t\t\t\t\t\t\texpectation = Not(expectation)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.OnceMet(\n\t\t\t\t\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 1, true),\n\t\t\t\t\t\t\texpectation,\n\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test that gopls prompts for telemetry only after instrumenting for a while, and\n// when the token is within the range for sample.\nfunc TestTelemetryPrompt_Conditions_StartTimeAndSamplingToken(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\tday := 24 * time.Hour\n\tsamplesPerMille := 50\n\tfor _, token := range []int{1, samplesPerMille, samplesPerMille + 1} {\n\t\twantSampled := token <= samplesPerMille\n\t\tt.Run(fmt.Sprintf(\"to_sample=%t/tokens=%d\", wantSampled, token), func(t *testing.T) {\n\t\t\tfor _, elapsed := range []time.Duration{8 * day, 1 * day, 0} {\n\t\t\t\ttelemetryStartTimeOrEmpty := \"\"\n\t\t\t\tif elapsed > 0 {\n\t\t\t\t\ttelemetryStartTimeOrEmpty = strconv.FormatInt(time.Now().Add(-elapsed).Unix(), 10)\n\t\t\t\t}\n\t\t\t\tt.Run(fmt.Sprintf(\"elapsed=%s\", elapsed), func(t *testing.T) {\n\t\t\t\t\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\t\t\t\t\tWithOptions(\n\t\t\t\t\t\tModes(Default), // no need to run this in all modes\n\t\t\t\t\t\tEnvVars{\n\t\t\t\t\t\t\tserver.GoplsConfigDirEnvvar:                  t.TempDir(),\n\t\t\t\t\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\t\t\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: telemetryStartTimeOrEmpty,\n\t\t\t\t\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     strconv.Itoa(token),\n\t\t\t\t\t\t\tserver.FakeSamplesPerMille:                   strconv.Itoa(samplesPerMille), // want token ∈ [1, 50] is always sampled.\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSettings{\n\t\t\t\t\t\t\t\"telemetryPrompt\": true,\n\t\t\t\t\t\t},\n\t\t\t\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\t\t\t\twantPrompt := wantSampled && elapsed > 7*day\n\t\t\t\t\t\texpectation := ShownMessageRequest(\".*Would you like to enable Go telemetry?\")\n\t\t\t\t\t\tif !wantPrompt {\n\t\t\t\t\t\t\texpectation = Not(expectation)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.OnceMet(\n\t\t\t\t\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 1, true),\n\t\t\t\t\t\t\texpectation,\n\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test that responding to the telemetry prompt results in the expected state.\nfunc TestTelemetryPrompt_Response(t *testing.T) {\n\tif !countertest.SupportedPlatform {\n\t\tt.Skip(\"requires counter support\")\n\t}\n\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\n\tvar (\n\t\tacceptanceCounter = \"gopls/telemetryprompt/accepted\"\n\t\tdeclinedCounter   = \"gopls/telemetryprompt/declined\"\n\t\tattempt1Counter   = \"gopls/telemetryprompt/attempts:1\"\n\t\tallCounters       = []string{acceptanceCounter, declinedCounter, attempt1Counter}\n\t)\n\n\t// To avoid (but not prevent) the flakes encountered in golang/go#68659, we\n\t// need to perform our first read before starting to increment counters.\n\t//\n\t// ReadCounter checks to see if the counter file needs to be rotated before\n\t// reading. When files are rotated, all previous counts are lost. Calling\n\t// ReadCounter here reduces the window for a flake due to this rotation (the\n\t// file was originally was located during countertest.Open in TestMain).\n\t//\n\t// golang/go#71590 tracks the larger problems with the countertest library.\n\t//\n\t// (The counter name below is arbitrary.)\n\t_, _ = countertest.ReadCounter(counter.New(\"issue68659\"))\n\n\t// We must increment counters in order for the initial reads below to\n\t// succeed.\n\t//\n\t// TODO(rfindley): ReadCounter should simply return 0 for uninitialized\n\t// counters.\n\tfor _, name := range allCounters {\n\t\tcounter.New(name).Inc()\n\t}\n\n\treadCounts := func(t *testing.T) map[string]uint64 {\n\t\tt.Helper()\n\t\tcounts := make(map[string]uint64)\n\t\tfor _, name := range allCounters {\n\t\t\tcount, err := countertest.ReadCounter(counter.New(name))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"ReadCounter(%q) failed: %v\", name, err)\n\t\t\t}\n\t\t\tcounts[name] = count\n\t\t}\n\t\treturn counts\n\t}\n\n\ttests := []struct {\n\t\tname       string // subtest name\n\t\tresponse   string // response to choose for the telemetry dialog\n\t\twantMode   string // resulting telemetry mode\n\t\twantMsg    string // substring contained in the follow-up popup (if empty, no popup is expected)\n\t\twantInc    uint64 // expected 'prompt accepted' counter increment\n\t\twantCounts map[string]uint64\n\t}{\n\t\t{\"yes\", server.TelemetryYes, \"on\", \"uploading is now enabled\", 1, map[string]uint64{\n\t\t\tacceptanceCounter: 1,\n\t\t\tdeclinedCounter:   0,\n\t\t\tattempt1Counter:   1,\n\t\t}},\n\t\t{\"no\", server.TelemetryNo, \"\", \"\", 0, map[string]uint64{\n\t\t\tacceptanceCounter: 0,\n\t\t\tdeclinedCounter:   1,\n\t\t\tattempt1Counter:   1,\n\t\t}},\n\t\t{\"empty\", \"\", \"\", \"\", 0, map[string]uint64{\n\t\t\tacceptanceCounter: 0,\n\t\t\tdeclinedCounter:   0,\n\t\t\tattempt1Counter:   1,\n\t\t}},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tinitialCounts := readCounts(t)\n\t\t\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\t\t\ttelemetryStartTime := time.Now().Add(-8 * 24 * time.Hour)\n\t\t\tmsgRE := regexp.MustCompile(\".*Would you like to enable Go telemetry?\")\n\t\t\trespond := func(m *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {\n\t\t\t\tif msgRE.MatchString(m.Message) {\n\t\t\t\t\tfor _, item := range m.Actions {\n\t\t\t\t\t\tif item.Title == test.response {\n\t\t\t\t\t\t\treturn &item, nil\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif test.response != \"\" {\n\t\t\t\t\t\tt.Errorf(\"action item %q not found\", test.response)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tWithOptions(\n\t\t\t\tModes(Default), // no need to run this in all modes\n\t\t\t\tEnvVars{\n\t\t\t\t\tserver.GoplsConfigDirEnvvar:                  t.TempDir(),\n\t\t\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: strconv.FormatInt(telemetryStartTime.Unix(), 10),\n\t\t\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     \"1\", // always sample because samplingPerMille >= 1.\n\t\t\t\t},\n\t\t\t\tSettings{\n\t\t\t\t\t\"telemetryPrompt\": true,\n\t\t\t\t},\n\t\t\t\tMessageResponder(respond),\n\t\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\t\tvar postConditions []Expectation\n\t\t\t\tif test.wantMsg != \"\" {\n\t\t\t\t\tpostConditions = append(postConditions, ShownMessage(test.wantMsg))\n\t\t\t\t}\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 1, true),\n\t\t\t\t\tpostConditions...,\n\t\t\t\t)\n\t\t\t\tgotMode := \"\"\n\t\t\t\tif contents, err := os.ReadFile(modeFile); err == nil {\n\t\t\t\t\tgotMode = string(contents)\n\t\t\t\t} else if !os.IsNotExist(err) {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif gotMode != test.wantMode {\n\t\t\t\t\tt.Errorf(\"after prompt, mode=%s, want %s\", gotMode, test.wantMode)\n\t\t\t\t}\n\n\t\t\t\t// We increment the acceptance counter when checking the prompt file\n\t\t\t\t// before prompting, so start a second, transient gopls session and\n\t\t\t\t// verify that the acceptance counter is incremented.\n\t\t\t\tenv2 := ConnectGoplsEnv(t, env.Ctx, env.Sandbox, env.Editor.Config(), env.Server)\n\t\t\t\tenv2.Await(CompletedWork(server.TelemetryPromptWorkTitle, 1, true))\n\t\t\t\tif err := env2.Editor.Close(env2.Ctx); err != nil {\n\t\t\t\t\tt.Errorf(\"closing second editor: %v\", err)\n\t\t\t\t}\n\n\t\t\t\tgotCounts := readCounts(t)\n\t\t\t\tfor k := range gotCounts {\n\t\t\t\t\tgotCounts[k] -= initialCounts[k]\n\t\t\t\t}\n\t\t\t\tif diff := cmp.Diff(test.wantCounts, gotCounts); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"counter mismatch (-want +got):\\n%s\", diff)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Test that we stop asking about telemetry after the user ignores the question\n// 5 times.\nfunc TestTelemetryPrompt_GivingUp(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\n\t// For this test, we want to share state across gopls sessions.\n\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\ttelemetryStartTime := time.Now().Add(-30 * 24 * time.Hour)\n\tconfigDir := t.TempDir()\n\n\tconst maxPrompts = 5 // internal prompt limit defined by gopls\n\n\tfor i := range maxPrompts + 1 {\n\t\tWithOptions(\n\t\t\tModes(Default), // no need to run this in all modes\n\t\t\tEnvVars{\n\t\t\t\tserver.GoplsConfigDirEnvvar:                  configDir,\n\t\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: strconv.FormatInt(telemetryStartTime.Unix(), 10),\n\t\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     \"1\", // always sample because samplingPerMille >= 1.\n\t\t\t},\n\t\t\tSettings{\n\t\t\t\t\"telemetryPrompt\": true,\n\t\t\t},\n\t\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t\twantPrompt := i < maxPrompts\n\t\t\texpectation := ShownMessageRequest(\".*Would you like to enable Go telemetry?\")\n\t\t\tif !wantPrompt {\n\t\t\t\texpectation = Not(expectation)\n\t\t\t}\n\t\t\tenv.OnceMet(\n\t\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 1, true),\n\t\t\t\texpectation,\n\t\t\t)\n\t\t})\n\t}\n}\n\n// Test that gopls prompts for telemetry only when it is supposed to.\nfunc TestTelemetryPrompt_Conditions_Command(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\tmodeFile := filepath.Join(t.TempDir(), \"mode\")\n\ttelemetryStartTime := time.Now().Add(-8 * 24 * time.Hour)\n\tWithOptions(\n\t\tModes(Default), // no need to run this in all modes\n\t\tEnvVars{\n\t\t\tserver.GoplsConfigDirEnvvar:                  t.TempDir(),\n\t\t\tserver.FakeTelemetryModefileEnvvar:           modeFile,\n\t\t\tserver.GoTelemetryGoplsClientStartTimeEnvvar: fmt.Sprintf(\"%d\", telemetryStartTime.Unix()),\n\t\t\tserver.GoTelemetryGoplsClientTokenEnvvar:     \"1\", // always sample because samplingPerMille >= 1.\n\t\t},\n\t\tSettings{\n\t\t\t// off because we are testing\n\t\t\t// if we can trigger the prompt with command.\n\t\t\t\"telemetryPrompt\": false,\n\t\t},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tcmd := command.NewMaybePromptForTelemetryCommand(\"prompt\")\n\t\tvar err error\n\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\tCommand: cmd.Command,\n\t\t}, &err)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\texpectation := ShownMessageRequest(\".*Would you like to enable Go telemetry?\")\n\t\tenv.OnceMet(\n\t\t\tCompletedWork(server.TelemetryPromptWorkTitle, 2, true),\n\t\t\texpectation,\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/references_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestStdlibReferences(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Print()\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `fmt.(Print)`))\n\t\tenv.OpenFile(env.Sandbox.Workdir.URIToPath(loc.URI))\n\t\trefs, err := env.Editor.References(env.Ctx, loc)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif len(refs) != 2 {\n\t\t\t// TODO(adonovan): make this assertion less maintainer-hostile.\n\t\t\tt.Fatalf(\"got %v reference(s), want 2\", len(refs))\n\t\t}\n\t\t// The first reference is guaranteed to be the definition.\n\t\tif got, want := refs[1].URI, env.Sandbox.Workdir.URI(\"main.go\"); got != want {\n\t\t\tt.Errorf(\"found reference in %v, wanted %v\", got, want)\n\t\t}\n\t})\n}\n\n// This is a regression test for golang/go#48400 (a panic).\nfunc TestReferencesOnErrorMethod(t *testing.T) {\n\t// Ideally this would actually return the correct answer,\n\t// instead of merely failing gracefully.\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\ntype t interface {\n\terror\n}\n\ntype s struct{}\n\nfunc (*s) Error() string {\n\treturn \"\"\n}\n\nfunc _() {\n\tvar s s\n\t_ = s.Error()\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", `Error`))\n\t\trefs, err := env.Editor.References(env.Ctx, loc)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"references on (*s).Error failed: %v\", err)\n\t\t}\n\t\t// TODO(adonovan): this test is crying out for marker support in integration tests.\n\t\tvar buf strings.Builder\n\t\tfor _, ref := range refs {\n\t\t\tfmt.Fprintf(&buf, \"%s %s\\n\", env.Sandbox.Workdir.URIToPath(ref.URI), ref.Range)\n\t\t}\n\t\tgot := buf.String()\n\t\twant := \"main.go 8:10-8:15\\n\" + // (*s).Error decl\n\t\t\t\"main.go 14:7-14:12\\n\" // s.Error() call\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"unexpected references on (*s).Error (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\nfunc TestDefsRefsBuiltins(t *testing.T) {\n\t// TODO(adonovan): add unsafe.{SliceData,String,StringData} in later go versions.\n\tconst files = `\n-- go.mod --\nmodule example.com\ngo 1.16\n\n-- a.go --\npackage a\n\nimport \"unsafe\"\n\nconst _ = iota\nvar _ error\nvar _ int\nvar _ = append()\nvar _ = unsafe.Pointer(nil)\nvar _ = unsafe.Add(nil, nil)\nvar _ = unsafe.Sizeof(0)\nvar _ = unsafe.Alignof(0)\nvar _ = unsafe.Slice(nil, 0)\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tfor name := range strings.FieldsSeq(\n\t\t\t\"iota error int nil append iota Pointer Sizeof Alignof Add Slice\") {\n\t\t\tloc := env.RegexpSearch(\"a.go\", `\\b`+name+`\\b`)\n\n\t\t\t// definition -> {builtin,unsafe}.go\n\t\t\tdef := env.FirstDefinition(loc)\n\t\t\tif (!strings.HasSuffix(string(def.URI), \"builtin.go\") &&\n\t\t\t\t!strings.HasSuffix(string(def.URI), \"unsafe.go\")) ||\n\t\t\t\tdef.Range.Start.Line == 0 {\n\t\t\t\tt.Errorf(\"definition(%q) = %v, want {builtin,unsafe}.go\",\n\t\t\t\t\tname, def)\n\t\t\t}\n\n\t\t\t// \"references to (builtin \"Foo\"|unsafe.Foo) are not supported\"\n\t\t\t_, err := env.Editor.References(env.Ctx, loc)\n\t\t\tgotErr := fmt.Sprint(err)\n\t\t\tif !strings.Contains(gotErr, \"references to\") ||\n\t\t\t\t!strings.Contains(gotErr, \"not supported\") ||\n\t\t\t\t!strings.Contains(gotErr, name) {\n\t\t\t\tt.Errorf(\"references(%q) error: got %q, want %q\",\n\t\t\t\t\tname, gotErr, \"references to ... are not supported\")\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestPackageReferences(t *testing.T) {\n\ttests := []struct {\n\t\tpackageName  string\n\t\twantRefCount int\n\t\twantFiles    []string\n\t}{\n\t\t{\n\t\t\t\"lib1\",\n\t\t\t3,\n\t\t\t[]string{\n\t\t\t\t\"main.go\",\n\t\t\t\t\"lib1/a.go\",\n\t\t\t\t\"lib1/b.go\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"lib2\",\n\t\t\t2,\n\t\t\t[]string{\n\t\t\t\t\"main.go\",\n\t\t\t\t\"lib2/a.go\",\n\t\t\t},\n\t\t},\n\t}\n\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib1/a.go --\npackage lib1\n\nconst A = 1\n\n-- lib1/b.go --\npackage lib1\n\nconst B = 1\n\n-- lib2/a.go --\npackage lib2\n\nconst C = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib1\"\n\t\"mod.com/lib2\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tfor _, test := range tests {\n\t\t\tfile := fmt.Sprintf(\"%s/a.go\", test.packageName)\n\t\t\tenv.OpenFile(file)\n\t\t\tloc := env.RegexpSearch(file, test.packageName)\n\t\t\trefs := env.References(loc)\n\t\t\tif len(refs) != test.wantRefCount {\n\t\t\t\t// TODO(adonovan): make this assertion less maintainer-hostile.\n\t\t\t\tt.Fatalf(\"got %v reference(s), want %d\", len(refs), test.wantRefCount)\n\t\t\t}\n\t\t\tvar refURIs []string\n\t\t\tfor _, ref := range refs {\n\t\t\t\trefURIs = append(refURIs, string(ref.URI))\n\t\t\t}\n\t\t\tfor _, base := range test.wantFiles {\n\t\t\t\thasBase := false\n\t\t\t\tfor _, ref := range refURIs {\n\t\t\t\t\tif strings.HasSuffix(ref, base) {\n\t\t\t\t\t\thasBase = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !hasBase {\n\t\t\t\t\tt.Fatalf(\"got [%v], want reference ends with \\\"%v\\\"\", strings.Join(refURIs, \",\"), base)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\n// Test for golang/go#43144.\n//\n// Verify that we search for references and implementations in intermediate\n// test variants.\nfunc TestReferencesInTestVariants(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo.mod\n\ngo 1.12\n-- foo/foo.go --\npackage foo\n\nimport \"foo.mod/bar\"\n\nconst Foo = 42\n\ntype T int\ntype InterfaceM interface{ M() }\ntype InterfaceF interface{ F() }\n\nfunc _() {\n\t_ = bar.Blah\n}\n\n-- foo/foo_test.go --\npackage foo\n\ntype Fer struct{}\nfunc (Fer) F() {}\n\n-- bar/bar.go --\npackage bar\n\nvar Blah = 123\n\n-- bar/bar_test.go --\npackage bar\n\ntype Mer struct{}\nfunc (Mer) M() {}\n\nfunc TestBar() {\n\t_ = Blah\n}\n-- bar/bar_x_test.go --\npackage bar_test\n\nimport (\n\t\"foo.mod/bar\"\n\t\"foo.mod/foo\"\n)\n\ntype Mer struct{}\nfunc (Mer) M() {}\n\nfunc _() {\n\t_ = bar.Blah\n\t_ = foo.Foo\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\n\t\trefTests := []struct {\n\t\t\tre       string\n\t\t\twantRefs []string\n\t\t}{\n\t\t\t// Blah is referenced:\n\t\t\t// - inside the foo.mod/bar (ordinary) package\n\t\t\t// - inside the foo.mod/bar [foo.mod/bar.test] test variant package\n\t\t\t// - from the foo.mod/bar_test [foo.mod/bar.test] x_test package\n\t\t\t// - from the foo.mod/foo package\n\t\t\t{\"Blah\", []string{\"bar/bar.go:3\", \"bar/bar_test.go:7\", \"bar/bar_x_test.go:12\", \"foo/foo.go:12\"}},\n\n\t\t\t// Foo is referenced in bar_x_test.go via the intermediate test variant\n\t\t\t// foo.mod/foo [foo.mod/bar.test].\n\t\t\t{\"Foo\", []string{\"bar/bar_x_test.go:13\", \"foo/foo.go:5\"}},\n\t\t}\n\n\t\tfor _, test := range refTests {\n\t\t\tloc := env.RegexpSearch(\"foo/foo.go\", test.re)\n\t\t\trefs := env.References(loc)\n\n\t\t\tgot := fileLocations(env, refs)\n\t\t\tif diff := cmp.Diff(test.wantRefs, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"References(%q) returned unexpected diff (-want +got):\\n%s\", test.re, diff)\n\t\t\t}\n\t\t}\n\n\t\timplTests := []struct {\n\t\t\tre        string\n\t\t\twantImpls []string\n\t\t}{\n\t\t\t// InterfaceM is implemented both in foo.mod/bar [foo.mod/bar.test] (which\n\t\t\t// doesn't import foo), and in foo.mod/bar_test [foo.mod/bar.test], which\n\t\t\t// imports the test variant of foo.\n\t\t\t{\"InterfaceM\", []string{\"bar/bar_test.go:3\", \"bar/bar_x_test.go:8\"}},\n\n\t\t\t// A search within the ordinary package to should find implementations\n\t\t\t// (Fer) within the augmented test package.\n\t\t\t{\"InterfaceF\", []string{\"foo/foo_test.go:3\"}},\n\t\t}\n\n\t\tfor _, test := range implTests {\n\t\t\tloc := env.RegexpSearch(\"foo/foo.go\", test.re)\n\t\t\timpls := env.Implementations(loc)\n\n\t\t\tgot := fileLocations(env, impls)\n\t\t\tif diff := cmp.Diff(test.wantImpls, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"Implementations(%q) returned unexpected diff (-want +got):\\n%s\", test.re, diff)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// This is a regression test for Issue #56169, in which interface\n// implementations in vendored modules were not found. The actual fix\n// was the same as for #55995; see TestVendoringInvalidatesMetadata.\nfunc TestImplementationsInVendor(t *testing.T) {\n\tconst proxy = `\n-- other.com/b@v1.0.0/go.mod --\nmodule other.com/b\ngo 1.14\n\n-- other.com/b@v1.0.0/b.go --\npackage b\ntype B int\nfunc (B) F() {}\n`\n\tconst src = `\n-- go.mod --\nmodule example.com/a\ngo 1.14\nrequire other.com/b v1.0.0\n\n-- a.go --\npackage a\nimport \"other.com/b\"\ntype I interface { F() }\nvar _ b.B\n\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t\tModes(Default), // fails in 'experimental' mode\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t// Enable to debug go.sum mismatch, which may appear as\n\t\t// \"module lookup disabled by GOPROXY=off\", confusingly.\n\t\tif false {\n\t\t\tenv.DumpGoSum(\".\")\n\t\t}\n\n\t\tcheckVendor := func(locs []protocol.Location, wantVendor bool) {\n\t\t\tif len(locs) != 1 {\n\t\t\t\tt.Errorf(\"got %d locations, want 1\", len(locs))\n\t\t\t} else if strings.Contains(string(locs[0].URI), \"/vendor/\") != wantVendor {\n\t\t\t\tt.Errorf(\"got location %s, wantVendor=%t\", locs[0], wantVendor)\n\t\t\t}\n\t\t}\n\n\t\tenv.OpenFile(\"a.go\")\n\t\trefLoc := env.RegexpSearch(\"a.go\", \"I\") // find \"I\" reference\n\n\t\t// Initially, a.I has one implementation b.B in\n\t\t// the module cache, not the vendor tree.\n\t\tcheckVendor(env.Implementations(refLoc), false)\n\n\t\t// Run 'go mod vendor' outside the editor.\n\t\tenv.RunGoCommand(\"mod\", \"vendor\")\n\n\t\t// Synchronize changes to watched files.\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\t// Now, b.B is found in the vendor tree.\n\t\tcheckVendor(env.Implementations(refLoc), true)\n\n\t\t// Delete the vendor tree.\n\t\tif err := os.RemoveAll(env.Sandbox.Workdir.AbsPath(\"vendor\")); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// Notify the server of the deletion.\n\t\tif err := env.Sandbox.Workdir.CheckForFileChanges(env.Ctx); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Synchronize again.\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\n\t\t// b.B is once again defined in the module cache.\n\t\tcheckVendor(env.Implementations(refLoc), false)\n\t})\n}\n\n// This test can't be expressed as a marker test because the marker\n// test framework opens all files (which is a bit of a hack), creating\n// a <command-line-arguments> package for packages that otherwise\n// wouldn't be found from the go.work file.\nfunc TestReferencesFromWorkspacePackages59674(t *testing.T) {\n\tconst src = `\n-- a/go.mod --\nmodule example.com/a\ngo 1.12\n\n-- b/go.mod --\nmodule example.com/b\ngo 1.12\n\n-- c/go.mod --\nmodule example.com/c\ngo 1.12\n\n-- lib/go.mod --\nmodule example.com/lib\ngo 1.12\n\n-- go.work --\nuse ./a\nuse ./b\n// don't use ./c\nuse ./lib\n\n-- a/a.go --\npackage a\n\nimport \"example.com/lib\"\n\nvar _ = lib.F // query here\n\n-- b/b.go --\npackage b\n\nimport \"example.com/lib\"\n\nvar _ = lib.F // also found by references\n\n-- c/c.go --\npackage c\n\nimport \"example.com/lib\"\n\nvar _ = lib.F // this reference should not be reported\n\n-- lib/lib.go --\npackage lib\n\nfunc F() {} // declaration\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\trefLoc := env.RegexpSearch(\"a/a.go\", \"F\")\n\t\tgot := fileLocations(env, env.References(refLoc))\n\t\twant := []string{\"a/a.go:5\", \"b/b.go:5\", \"lib/lib.go:3\"}\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"incorrect References (-want +got):\\n%s\", diff)\n\t\t}\n\t})\n}\n\n// Test an 'implementation' query on a type that implements 'error'.\n// (Unfortunately builtin locations cannot be expressed using @loc\n// in the marker test framework.)\nfunc TestImplementationsOfError(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a.go --\npackage a\n\ntype Error2 interface {\n\tError() string\n}\n\ntype MyError int\nfunc (MyError) Error() string { return \"\" }\n\ntype MyErrorPtr int\nfunc (*MyErrorPtr) Error() string { return \"\" }\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\tfor _, test := range []struct {\n\t\t\tre   string\n\t\t\twant []string\n\t\t}{\n\t\t\t// error type\n\t\t\t{\"Error2\", []string{\"a.go:10\", \"a.go:7\", \"std:builtin/builtin.go\"}},\n\t\t\t{\"MyError\", []string{\"a.go:3\", \"std:builtin/builtin.go\"}},\n\t\t\t{\"MyErrorPtr\", []string{\"a.go:3\", \"std:builtin/builtin.go\"}},\n\t\t\t// error.Error method\n\t\t\t{\"(Error).. string\", []string{\"a.go:11\", \"a.go:8\", \"std:builtin/builtin.go\"}},\n\t\t\t{\"MyError. (Error)\", []string{\"a.go:4\", \"std:builtin/builtin.go\"}},\n\t\t\t{\"MyErrorPtr. (Error)\", []string{\"a.go:4\", \"std:builtin/builtin.go\"}},\n\t\t} {\n\t\t\tmatchLoc := env.RegexpSearch(\"a.go\", test.re)\n\t\t\timpls := env.Implementations(matchLoc)\n\t\t\tgot := fileLocations(env, impls)\n\t\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\t\tt.Errorf(\"Implementations(%q) = %q, want %q\",\n\t\t\t\t\ttest.re, got, test.want)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// fileLocations returns a new sorted array of the\n// relative file name and line number of each location.\n// Duplicates are not removed.\n// Standard library filenames are abstracted for robustness.\nfunc fileLocations(env *integration.Env, locs []protocol.Location) []string {\n\tgot := make([]string, 0, len(locs))\n\tfor _, loc := range locs {\n\t\tpath := env.Sandbox.Workdir.URIToPath(loc.URI) // (slashified)\n\t\tif i := strings.LastIndex(path, \"/src/\"); i >= 0 && filepath.IsAbs(path) {\n\t\t\t// Absolute path with \"src\" segment: assume it's in GOROOT.\n\t\t\t// Strip directory and don't add line/column since they are fragile.\n\t\t\tpath = \"std:\" + path[i+len(\"/src/\"):]\n\t\t} else {\n\t\t\tpath = fmt.Sprintf(\"%s:%d\", path, loc.Range.Start.Line+1)\n\t\t}\n\t\tgot = append(got, path)\n\t}\n\tsort.Strings(got)\n\treturn got\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/rename_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestPrepareRenameMainPackage(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tfmt.Println(1)\n}\n`\n\tconst wantErr = \"can't rename package \\\"main\\\"\"\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.RegexpSearch(\"main.go\", `main`)\n\t\tparams := &protocol.PrepareRenameParams{\n\t\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\t}\n\t\t_, err := env.Editor.Server.PrepareRename(env.Ctx, params)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"missing can't rename package main error from PrepareRename\")\n\t\t}\n\n\t\tif err.Error() != wantErr {\n\t\t\tt.Errorf(\"got %v, want %v\", err.Error(), wantErr)\n\t\t}\n\t})\n}\n\n// Test case for golang/go#56227\nfunc TestRenameWithUnsafeSlice(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- p.go --\npackage p\n\nimport \"unsafe\"\n\ntype T struct{}\n\nfunc (T) M() {}\n\nfunc _() {\n\tx := [3]int{1, 2, 3}\n\tptr := unsafe.Pointer(&x)\n\t_ = unsafe.Slice((*int)(ptr), 3)\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.Rename(env.RegexpSearch(\"p.go\", \"M\"), \"N\") // must not panic\n\t})\n}\n\nfunc TestPrepareRenameWithNoPackageDeclaration(t *testing.T) {\n\tconst files = `\ngo 1.14\n-- lib/a.go --\nimport \"fmt\"\n\nconst A = 1\n\nfunc bar() {\n\tfmt.Println(\"Bar\")\n}\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\terr := env.Editor.Rename(env.Ctx, env.RegexpSearch(\"lib/a.go\", \"fmt\"), \"fmt1\")\n\t\tif got, want := fmt.Sprint(err), \"no identifier found\"; got != want {\n\t\t\tt.Errorf(\"Rename: got error %v, want %v\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestPrepareRenameFailWithUnknownModule(t *testing.T) {\n\tconst files = `\ngo 1.14\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tconst wantErr = \"can't rename package: missing module information for package\"\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tloc := env.RegexpSearch(\"lib/a.go\", \"lib\")\n\t\tparams := &protocol.PrepareRenameParams{\n\t\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\t}\n\t\t_, err := env.Editor.Server.PrepareRename(env.Ctx, params)\n\t\tif err == nil || !strings.Contains(err.Error(), wantErr) {\n\t\t\tt.Errorf(\"missing cannot rename packages with unknown module from PrepareRename\")\n\t\t}\n\t})\n}\n\n// This test ensures that each import of a renamed package\n// is also renamed if it would otherwise create a conflict.\nfunc TestRenamePackageWithConflicts(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst B = 1\n\n-- lib/x/a.go --\npackage nested1\n\nconst C = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\t\"mod.com/lib/nested\"\n\tnested1 \"mod.com/lib/x\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\t// Don't rename subpackages.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", `nested2 \"mod.com/nested\"`)\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/lib/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `nested1 \"mod.com/lib/x\"`)\n\t})\n\n\tWithOptions(Settings{\"renameMovesSubpackages\": true}).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\t// Rename subpackages.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", `nested2 \"mod.com/nested\"`)\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `nested1 \"mod.com/nested/x\"`)\n\t})\n}\n\nfunc TestRenamePackageWithAlias(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst B = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\tlib1 \"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `lib1 \"mod.com/lib/nested\"`)\n\t})\n}\n\nfunc TestRenamePackageWithDifferentDirectoryPath(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/nested/a.go --\npackage foo\n\nconst B = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\tfoo \"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\t// Don't rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `foo \"mod.com/lib/nested\"`)\n\t})\n\n\tWithOptions(Settings{\"renameMovesSubpackages\": true}).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\t// Rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `foo \"mod.com/nested/nested\"`)\n\t})\n}\n\nfunc TestRenamePackage(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/b.go --\npackage lib\n\nconst B = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst C = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\t\"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"lib1\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"lib1/a.go\", \"package lib1\")\n\t\tenv.RegexpSearch(\"lib1/b.go\", \"package lib1\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/lib1\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/lib/nested\")\n\t})\n}\n\n// Test for golang/go#47564.\nfunc TestRenameInTestVariant(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- stringutil/stringutil.go --\npackage stringutil\n\nfunc Identity(s string) string {\n\treturn s\n}\n-- stringutil/stringutil_test.go --\npackage stringutil\n\nfunc TestIdentity(t *testing.T) {\n\tif got := Identity(\"foo\"); got != \"foo\" {\n\t\tt.Errorf(\"bad\")\n\t}\n}\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"mod.com/stringutil\"\n)\n\nfunc main() {\n\tfmt.Println(stringutil.Identity(\"hello world\"))\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.Rename(env.RegexpSearch(\"main.go\", `stringutil\\.(Identity)`), \"Identityx\")\n\t\tenv.OpenFile(\"stringutil/stringutil_test.go\")\n\t\ttext := env.BufferText(\"stringutil/stringutil_test.go\")\n\t\tif !strings.Contains(text, \"Identityx\") {\n\t\t\tt.Errorf(\"stringutil/stringutil_test.go: missing expected token `Identityx` after rename:\\n%s\", text)\n\t\t}\n\t})\n}\n\n// This is a test that rename operation initiated by the editor function as expected.\nfunc TestRenameFileFromEditor(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n-- a/a.go --\npackage a\n\nconst X = 1\n-- a/x.go --\npackage a\n\nconst X = 2\n-- b/b.go --\npackage b\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t// Rename files and verify that diagnostics are affected accordingly.\n\n\t\t// Initially, we should have diagnostics on both X's, for their duplicate declaration.\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"X\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/x.go\", \"X\")),\n\t\t)\n\n\t\t// Moving x.go should make the diagnostic go away.\n\t\tenv.RenameFile(\"a/x.go\", \"b/x.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),               // no more duplicate declarations\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"package\")), // as package names mismatch\n\t\t)\n\n\t\t// Renaming should also work on open buffers.\n\t\tenv.OpenFile(\"b/x.go\")\n\n\t\t// Moving x.go back to a/ should cause the diagnostics to reappear.\n\t\tenv.RenameFile(\"b/x.go\", \"a/x.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"X\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/x.go\", \"X\")),\n\t\t)\n\n\t\t// Renaming the entire directory should move both the open and closed file.\n\t\tenv.RenameFile(\"a\", \"x\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"x/a.go\", \"X\")),\n\t\t\tDiagnostics(env.AtRegexp(\"x/x.go\", \"X\")),\n\t\t)\n\n\t\t// As a sanity check, verify that x/x.go is open.\n\t\tif text := env.BufferText(\"x/x.go\"); text == \"\" {\n\t\t\tt.Fatal(\"got empty buffer for x/x.go\")\n\t\t}\n\t})\n}\n\nfunc TestRenamePackage_Tests(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/b.go --\npackage lib\n\nconst B = 1\n\n-- lib/a_test.go --\npackage lib_test\n\nimport (\n\t\"mod.com/lib\"\n\t\"fmt\n)\n\nconst C = 1\n\n-- lib/b_test.go --\npackage lib\n\nimport (\n\t\"fmt\n)\n\nconst D = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst D = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\t\"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"lib1\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"lib1/a.go\", \"package lib1\")\n\t\tenv.RegexpSearch(\"lib1/b.go\", \"package lib1\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/lib1\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/lib/nested\")\n\n\t\t// Check if the test package is renamed\n\t\tenv.RegexpSearch(\"lib1/a_test.go\", \"package lib1_test\")\n\t\tenv.RegexpSearch(\"lib1/b_test.go\", \"package lib1\")\n\t})\n}\n\nfunc TestRenamePackage_NestedModule(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\nuse (\n\t.\n\t./foo/bar\n\t./foo/baz\n)\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\nrequire (\n    mod.com/foo/bar v0.0.0\n)\n\nreplace (\n\tmod.com/foo/bar => ./foo/bar\n\tmod.com/foo/baz => ./foo/baz\n)\n-- foo/foo.go --\npackage foo\n\nimport \"fmt\"\n\nfunc Bar() {\n\tfmt.Println(\"In foo before renamed to foox.\")\n}\n\n-- foo/bar/go.mod --\nmodule mod.com/foo/bar\n\n-- foo/bar/bar.go --\npackage bar\n\nconst Msg = \"Hi from package bar\"\n\n-- foo/baz/go.mod --\nmodule mod.com/foo/baz\n\n-- foo/baz/baz.go --\npackage baz\n\nconst Msg = \"Hi from package baz\"\n\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"mod.com/foo/bar\"\n\t\"mod.com/foo/baz\"\n\t\"mod.com/foo\"\n)\n\nfunc main() {\n\tfoo.Bar()\n\tfmt.Println(bar.Msg)\n\tfmt.Println(baz.Msg)\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\t\tenv.Rename(env.RegexpSearch(\"foo/foo.go\", \"foo\"), \"foox\")\n\n\t\tenv.RegexpSearch(\"foox/foo.go\", \"package foox\")\n\t\t// Don't rename subpackages.\n\t\tenv.OpenFile(\"foo/bar/bar.go\")\n\t\tenv.OpenFile(\"foo/bar/go.mod\")\n\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/foo/bar\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/foox\")\n\t\tenv.RegexpSearch(\"main.go\", \"foox.Bar()\")\n\n\t\tenv.RegexpSearch(\"go.mod\", \"./foo/bar\")\n\t\tenv.RegexpSearch(\"go.mod\", \"./foo/baz\")\n\t})\n\n\tWithOptions(Settings{\"renameMovesSubpackages\": true}).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\t\tenv.Rename(env.RegexpSearch(\"foo/foo.go\", \"foo\"), \"foox\")\n\n\t\tenv.RegexpSearch(\"foox/foo.go\", \"package foox\")\n\t\t// Rename subpackages.\n\t\tenv.OpenFile(\"foox/bar/bar.go\")\n\t\tenv.OpenFile(\"foox/bar/go.mod\")\n\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/foo/bar\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/foox\")\n\t\tenv.RegexpSearch(\"main.go\", \"foox.Bar()\")\n\n\t\tenv.RegexpSearch(\"go.mod\", \"./foox/bar\")\n\t\tenv.RegexpSearch(\"go.mod\", \"./foox/baz\")\n\t})\n}\n\nfunc TestRenamePackage_DuplicateImport(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst B = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\tlib1 \"mod.com/lib\"\n\tlib2 \"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `lib1 \"mod.com/nested\"`)\n\t\t// Don't rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `lib2 \"mod.com/lib/nested\"`)\n\t})\n\n\tWithOptions(Settings{\"renameMovesSubpackages\": true}).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `lib1 \"mod.com/nested\"`)\n\t\t// Rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `lib2 \"mod.com/nested/nested\"`)\n\t})\n}\n\nfunc TestRenamePackage_DuplicateBlankImport(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nconst A = 1\n\n-- lib/nested/a.go --\npackage nested\n\nconst B = 1\n\n-- main.go --\npackage main\n\nimport (\n\t\"mod.com/lib\"\n\t_ \"mod.com/lib\"\n\tlib1 \"mod.com/lib/nested\"\n)\n\nfunc main() {\n\tprintln(\"Hello\")\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `_ \"mod.com/nested\"`)\n\t\t// Don't rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `lib1 \"mod.com/lib/nested\"`)\n\t})\n\n\tWithOptions(Settings{\"renameMovesSubpackages\": true}).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"nested\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"nested/a.go\", \"package nested\")\n\t\tenv.RegexpSearch(\"main.go\", \"mod.com/nested\")\n\t\tenv.RegexpSearch(\"main.go\", `_ \"mod.com/nested\"`)\n\t\t// Rename subpackages.\n\t\tenv.RegexpSearch(\"main.go\", `lib1 \"mod.com/nested/nested\"`)\n\t})\n}\n\nfunc TestRenamePackage_TestVariant(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo/foo.go --\npackage foo\n\nconst Foo = 42\n-- bar/bar.go --\npackage bar\n\nimport \"mod.com/foo\"\n\nconst Bar = foo.Foo\n-- bar/bar_test.go --\npackage bar\n\nimport \"mod.com/foo\"\n\nconst Baz = foo.Foo\n-- testdata/bar/bar.go --\npackage bar\n\nimport \"mod.com/foox\"\n\nconst Bar = foox.Foo\n-- testdata/bar/bar_test.go --\npackage bar\n\nimport \"mod.com/foox\"\n\nconst Baz = foox.Foo\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\t\tenv.Rename(env.RegexpSearch(\"foo/foo.go\", \"package (foo)\"), \"foox\")\n\n\t\tcheckTestdata(t, env)\n\t})\n}\n\nfunc TestRenamePackage_IntermediateTestVariant(t *testing.T) {\n\t// In this test set up, we have the following import edges:\n\t//   bar_test -> baz -> foo -> bar\n\t//   bar_test -> foo -> bar\n\t//   bar_test -> bar\n\t//\n\t// As a consequence, bar_x_test.go is in the reverse closure of both\n\t// `foo [bar.test]` and `baz [bar.test]`. This test confirms that we don't\n\t// produce duplicate edits in this case.\n\tconst files = `\n-- go.mod --\nmodule foo.mod\n\ngo 1.12\n-- foo/foo.go --\npackage foo\n\nimport \"foo.mod/bar\"\n\nconst Foo = 42\n\nconst _ = bar.Bar\n-- baz/baz.go --\npackage baz\n\nimport \"foo.mod/foo\"\n\nconst Baz = foo.Foo\n-- bar/bar.go --\npackage bar\n\nvar Bar = 123\n-- bar/bar_test.go --\npackage bar\n\nconst _ = Bar\n-- bar/bar_x_test.go --\npackage bar_test\n\nimport (\n\t\"foo.mod/bar\"\n\t\"foo.mod/baz\"\n\t\"foo.mod/foo\"\n)\n\nconst _ = bar.Bar + baz.Baz + foo.Foo\n-- testdata/foox/foo.go --\npackage foox\n\nimport \"foo.mod/bar\"\n\nconst Foo = 42\n\nconst _ = bar.Bar\n-- testdata/baz/baz.go --\npackage baz\n\nimport \"foo.mod/foox\"\n\nconst Baz = foox.Foo\n-- testdata/bar/bar_x_test.go --\npackage bar_test\n\nimport (\n\t\"foo.mod/bar\"\n\t\"foo.mod/baz\"\n\t\"foo.mod/foox\"\n)\n\nconst _ = bar.Bar + baz.Baz + foox.Foo\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\t\tenv.Rename(env.RegexpSearch(\"foo/foo.go\", \"package (foo)\"), \"foox\")\n\n\t\tcheckTestdata(t, env)\n\t})\n}\n\nfunc TestRenamePackage_Nesting(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nimport \"mod.com/lib/nested\"\n\nconst A = 1 + nested.B\n-- lib/nested/a.go --\npackage nested\n\nconst B = 1\n-- other/other.go --\npackage other\n\nimport (\n\t\"mod.com/lib\"\n\t\"mod.com/lib/nested\"\n)\n\nconst C = lib.A + nested.B\n-- testdata/libx/a.go --\npackage libx\n\nimport \"mod.com/lib/nested\"\n\nconst A = 1 + nested.B\n-- testdata/other/other.go --\npackage other\n\nimport (\n\t\"mod.com/libx\"\n\t\"mod.com/lib/nested\"\n)\n\nconst C = libx.A + nested.B\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"package (lib)\"), \"libx\")\n\n\t\tcheckTestdata(t, env)\n\t})\n}\n\nfunc TestRenamePackage_InvalidName(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nimport \"mod.com/lib/nested\"\n\nconst A = 1 + nested.B\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tloc := env.RegexpSearch(\"lib/a.go\", \"package (lib)\")\n\n\t\tfor _, badName := range []string{\"$$$\", \"lib_test\"} {\n\t\t\tif err := env.Editor.Rename(env.Ctx, loc, badName); err == nil {\n\t\t\t\tt.Errorf(\"Rename(lib, libx) succeeded unexpectedly\")\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestRenamePackage_InternalPackage(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- lib/a.go --\npackage lib\n\nimport (\n\t\"fmt\"\n\t\"mod.com/lib/internal/x\"\n)\n\nconst A = 1\n\nfunc print() {\n\tfmt.Println(x.B)\n}\n\n-- lib/internal/x/a.go --\npackage x\n\nconst B = 1\n\n-- main.go --\npackage main\n\nimport \"mod.com/lib\"\n\nfunc main() {\n\tlib.print()\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"lib/internal/x/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/internal/x/a.go\", \"x\"), \"utils\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"lib/a.go\", \"mod.com/lib/internal/utils\")\n\t\tenv.RegexpSearch(\"lib/a.go\", \"utils.B\")\n\n\t\t// Check if the test package is renamed\n\t\tenv.RegexpSearch(\"lib/internal/utils/a.go\", \"package utils\")\n\n\t\tenv.OpenFile(\"lib/a.go\")\n\t\tenv.Rename(env.RegexpSearch(\"lib/a.go\", \"lib\"), \"lib1\")\n\n\t\t// Check if the new package name exists.\n\t\tenv.RegexpSearch(\"lib1/a.go\", \"package lib1\")\n\t\t// Don't rename subpackages.\n\t\tenv.RegexpSearch(\"lib1/a.go\", \"mod.com/lib/internal/utils\")\n\t\tenv.RegexpSearch(\"main.go\", `import \"mod.com/lib1\"`)\n\t\tenv.RegexpSearch(\"main.go\", \"lib1.print()\")\n\t})\n}\nfunc TestRenamePackage_InvalidPackageMove(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.21\n-- test1/test1.go --\npackage test1\n\n-- test2/test2.go --\npackage test2\n\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"test1/test1.go\")\n\t\tloc := env.RegexpSearch(\"test1/test1.go\", \"test1\")\n\t\tfor _, test := range []struct{ badName, expectedErrMatch string }{\n\t\t\t{\"test2\", \"invalid package identifier\"},\n\t\t\t{\"mod.com/test2\", \"not empty\"},\n\t\t\t{\"differentmod.com/test2\", \"cannot move package across module boundary\"},\n\t\t\t{\"mod.com/$$$\", \"invalid package name\"},\n\t\t\t{\"mod*.$+\", \"invalid package path\"},\n\t\t\t{\"mod.commmm\", \"cannot move package across module boundary\"},\n\t\t} {\n\t\t\terr := env.Editor.Rename(env.Ctx, loc, test.badName)\n\t\t\tif err == nil {\n\t\t\t\tt.Errorf(\"Rename to %s succeeded unexpectedly\", test.badName)\n\t\t\t} else if !strings.Contains(err.Error(), test.expectedErrMatch) {\n\t\t\t\tt.Errorf(\"Rename to %s produced incorrect error message, got %s, want %s\", test.badName, err.Error(), test.expectedErrMatch)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// checkTestdata checks that current buffer contents match their corresponding\n// expected content in the testdata directory.\nfunc checkTestdata(t *testing.T, env *Env) {\n\tt.Helper()\n\tfiles := env.ListFiles(\"testdata\")\n\tif len(files) == 0 {\n\t\tt.Fatal(\"no files in testdata directory\")\n\t}\n\tfor _, file := range files {\n\t\tsuffix := strings.TrimPrefix(file, \"testdata/\")\n\t\tgot := env.BufferText(suffix)\n\t\twant := env.ReadWorkspaceFile(file)\n\t\tif diff := compare.Text(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"Rename: unexpected buffer content for %s (-want +got):\\n%s\", suffix, diff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/semantictokens_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\nfunc TestBadURICrash_VSCodeIssue1498(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\n\ngo 1.12\n\n-- main.go --\npackage main\n\nfunc main() {}\n\n`\n\tWithOptions(\n\t\tModes(Default),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tparams := &protocol.SemanticTokensParams{}\n\t\tconst badURI = \"http://foo\"\n\t\tparams.TextDocument.URI = badURI\n\t\t// This call panicked in the past: golang/vscode-go#1498.\n\t\t_, err := env.Editor.Server.SemanticTokensFull(env.Ctx, params)\n\n\t\t// Requests to an invalid URI scheme now result in an LSP error.\n\t\tgot := fmt.Sprint(err)\n\t\twant := `DocumentURI scheme is not 'file': http://foo`\n\t\tif !strings.Contains(got, want) {\n\t\t\tt.Errorf(\"SemanticTokensFull error is %v, want substring %q\", got, want)\n\t\t}\n\t})\n}\n\n// fix bug involving type parameters and regular parameters\n// (golang/vscode-go#2527)\nfunc TestSemantic_2527(t *testing.T) {\n\t// these are the expected types of identifiers in text order\n\twant := []fake.SemanticToken{\n\t\t{Token: \"package\", TokenType: \"keyword\"},\n\t\t{Token: \"foo\", TokenType: \"namespace\"},\n\t\t{Token: \"// comment\", TokenType: \"comment\"},\n\t\t{Token: \"func\", TokenType: \"keyword\"},\n\t\t{Token: \"Add\", TokenType: \"function\", Mod: \"definition signature\"},\n\t\t{Token: \"T\", TokenType: \"typeParameter\", Mod: \"definition\"},\n\t\t{Token: \"int\", TokenType: \"type\", Mod: \"defaultLibrary number\"},\n\t\t{Token: \"target\", TokenType: \"parameter\", Mod: \"definition\"},\n\t\t{Token: \"T\", TokenType: \"typeParameter\"},\n\t\t{Token: \"l\", TokenType: \"parameter\", Mod: \"definition slice\"},\n\t\t{Token: \"T\", TokenType: \"typeParameter\"},\n\t\t{Token: \"T\", TokenType: \"typeParameter\"},\n\t\t{Token: \"return\", TokenType: \"keyword\"},\n\t\t{Token: \"append\", TokenType: \"function\", Mod: \"defaultLibrary\"},\n\t\t{Token: \"l\", TokenType: \"parameter\", Mod: \"slice\"},\n\t\t{Token: \"target\", TokenType: \"parameter\"},\n\t\t{Token: \"for\", TokenType: \"keyword\"},\n\t\t{Token: \"range\", TokenType: \"keyword\"},\n\t\t{Token: \"l\", TokenType: \"parameter\", Mod: \"slice\"},\n\t\t{Token: \"// test coverage\", TokenType: \"comment\"},\n\t\t{Token: \"return\", TokenType: \"keyword\"},\n\t\t{Token: \"nil\", TokenType: \"variable\", Mod: \"readonly defaultLibrary\"},\n\t}\n\tsrc := `\n-- go.mod --\nmodule example.com\n\ngo 1.19\n-- main.go --\npackage foo\n// comment\nfunc Add[T int](target T, l []T) []T {\n\treturn append(l, target)\n\tfor range l {} // test coverage\n\treturn nil\n}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t\tSettings{\"semanticTokens\": true},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"for range\")),\n\t\t)\n\t\tseen := env.SemanticTokensFull(\"main.go\")\n\t\tif x := cmp.Diff(want, seen); x != \"\" {\n\t\t\tt.Errorf(\"Semantic tokens do not match (-want +got):\\n%s\", x)\n\t\t}\n\t})\n\n}\n\n// fix inconsistency in TypeParameters\n// https://github.com/golang/go/issues/57619\nfunc TestSemantic_57619(t *testing.T) {\n\tsrc := `\n-- go.mod --\nmodule example.com\n\ngo 1.19\n-- main.go --\npackage foo\ntype Smap[K int, V any] struct {\n\tStore map[K]V\n}\nfunc (s *Smap[K, V]) Get(k K) (V, bool) {\n\tv, ok := s.Store[k]\n\treturn v, ok\n}\nfunc New[K int, V any]() Smap[K, V] {\n\treturn Smap[K, V]{Store: make(map[K]V)}\n}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t\tSettings{\"semanticTokens\": true},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tseen := env.SemanticTokensFull(\"main.go\")\n\t\tfor i, s := range seen {\n\t\t\tif (s.Token == \"K\" || s.Token == \"V\") && s.TokenType != \"typeParameter\" {\n\t\t\t\tt.Errorf(\"%d: expected K and V to be type parameters, but got %v\", i, s)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestSemanticGoDirectives(t *testing.T) {\n\tsrc := `\n-- go.mod --\nmodule example.com\n\ngo 1.19\n-- main.go --\npackage foo\n\n//go:linkname now time.Now\nfunc now()\n\n//go:noinline\nfunc foo() {}\n\n// Mentioning go:noinline should not tokenize.\n\n//go:notadirective\nfunc bar() {}\n`\n\twant := []fake.SemanticToken{\n\t\t{Token: \"package\", TokenType: \"keyword\"},\n\t\t{Token: \"foo\", TokenType: \"namespace\"},\n\n\t\t{Token: \"//\", TokenType: \"comment\"},\n\t\t{Token: \"go:linkname\", TokenType: \"namespace\"},\n\t\t{Token: \"now time.Now\", TokenType: \"comment\"},\n\t\t{Token: \"func\", TokenType: \"keyword\"},\n\t\t{Token: \"now\", TokenType: \"function\", Mod: \"definition signature\"},\n\n\t\t{Token: \"//\", TokenType: \"comment\"},\n\t\t{Token: \"go:noinline\", TokenType: \"namespace\"},\n\t\t{Token: \"func\", TokenType: \"keyword\"},\n\t\t{Token: \"foo\", TokenType: \"function\", Mod: \"definition signature\"},\n\n\t\t{Token: \"// Mentioning go:noinline should not tokenize.\", TokenType: \"comment\"},\n\n\t\t{Token: \"//go:notadirective\", TokenType: \"comment\"},\n\t\t{Token: \"func\", TokenType: \"keyword\"},\n\t\t{Token: \"bar\", TokenType: \"function\", Mod: \"definition signature\"},\n\t}\n\n\tWithOptions(\n\t\tModes(Default),\n\t\tSettings{\"semanticTokens\": true},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tseen := env.SemanticTokensFull(\"main.go\")\n\t\tif x := cmp.Diff(want, seen); x != \"\" {\n\t\t\tt.Errorf(\"Semantic tokens do not match (-want +got):\\n%s\", x)\n\t\t}\n\t})\n}\n\n// Make sure no zero-length tokens occur\nfunc TestSemantic_65254(t *testing.T) {\n\tsrc := `\n-- go.mod --\nmodule example.com\n\t\ngo 1.21\n-- main.go --\npackage main\n\n/* a comment with an\n\nempty line\n*/\n\nconst bad = `\n\n\tsrc += \"`foo\" + `\n\t` + \"bar`\"\n\twant := []fake.SemanticToken{\n\t\t{Token: \"package\", TokenType: \"keyword\"},\n\t\t{Token: \"main\", TokenType: \"namespace\"},\n\t\t{Token: \"/* a comment with an\", TokenType: \"comment\"},\n\t\t// --- Note that the zero length line does not show up\n\t\t{Token: \"empty line\", TokenType: \"comment\"},\n\t\t{Token: \"*/\", TokenType: \"comment\"},\n\t\t{Token: \"const\", TokenType: \"keyword\"},\n\t\t{Token: \"bad\", TokenType: \"variable\", Mod: \"definition readonly\"},\n\t\t{Token: \"`foo\", TokenType: \"string\"},\n\t\t// --- Note the zero length line does not show up\n\t\t{Token: \"\\tbar`\", TokenType: \"string\"},\n\t}\n\tWithOptions(\n\t\tModes(Default),\n\t\tSettings{\"semanticTokens\": true},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tseen := env.SemanticTokensFull(\"main.go\")\n\t\tif x := cmp.Diff(want, seen); x != \"\" {\n\t\t\tt.Errorf(\"Semantic tokens do not match (-want +got):\\n%s\", x)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/settings_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestEmptyDirectoryFilters_Issue51843(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n}\n`\n\n\tWithOptions(\n\t\tSettings{\"directoryFilters\": []string{\"\"}},\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\t// No need to do anything. Issue golang/go#51843 is triggered by the empty\n\t\t// directory filter above.\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/shared_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Smoke test that simultaneous editing sessions in the same workspace works.\nfunc TestSimultaneousEdits(t *testing.T) {\n\tconst sharedProgram = `\n-- go.mod --\nmodule mod\n\ngo 1.12\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello World.\")\n}`\n\n\tWithOptions(\n\t\tModes(DefaultModes()&(Forwarded|SeparateProcess)),\n\t).Run(t, sharedProgram, func(t *testing.T, env1 *Env) {\n\t\t// Create a second test session connected to the same workspace and server\n\t\t// as the first.\n\t\tenv2 := ConnectGoplsEnv(t, env1.Ctx, env1.Sandbox, env1.Editor.Config(), env1.Server)\n\t\tenv2.Await(InitialWorkspaceLoad)\n\t\t// In editor #1, break fmt.Println as before.\n\t\tenv1.OpenFile(\"main.go\")\n\t\tenv1.RegexpReplace(\"main.go\", \"Printl(n)\", \"\")\n\t\t// In editor #2 remove the closing brace.\n\t\tenv2.OpenFile(\"main.go\")\n\t\tenv2.RegexpReplace(\"main.go\", \"\\\\)\\n(})\", \"\")\n\n\t\t// Now check that we got different diagnostics in each environment.\n\t\tenv1.AfterChange(Diagnostics(env1.AtRegexp(\"main.go\", \"Printl\")))\n\t\tenv2.AfterChange(Diagnostics(env2.AtRegexp(\"main.go\", \"$\")))\n\n\t\t// Now close editor #2, and verify that operation in editor #1 is\n\t\t// unaffected.\n\t\tif err := env2.Editor.Close(env2.Ctx); err != nil {\n\t\t\tt.Errorf(\"closing second editor: %v\", err)\n\t\t}\n\n\t\tenv1.RegexpReplace(\"main.go\", \"Printl\", \"Println\")\n\t\tenv1.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/signature_help_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestSignatureHelpInNonWorkspacePackage(t *testing.T) {\n\tconst files = `\n-- a/go.mod --\nmodule a.com\n\ngo 1.18\n-- a/a/a.go --\npackage a\n\nfunc DoSomething(int) {}\n\nfunc _() {\n\tDoSomething()\n}\n-- b/go.mod --\nmodule b.com\ngo 1.18\n\nrequire a.com v1.0.0\n\nreplace a.com => ../a\n-- b/b/b.go --\npackage b\n\nimport \"a.com/a\"\n\nfunc _() {\n\ta.DoSomething()\n}\n`\n\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\"),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a/a.go\")\n\t\tenv.OpenFile(\"b/b/b.go\")\n\t\tsignatureHelp := func(filename string) *protocol.SignatureHelp {\n\t\t\tloc := env.RegexpSearch(filename, `DoSomething\\(()\\)`)\n\t\t\tvar params protocol.SignatureHelpParams\n\t\t\tparams.TextDocument.URI = loc.URI\n\t\t\tparams.Position = loc.Range.Start\n\t\t\thelp, err := env.Editor.Server.SignatureHelp(env.Ctx, &params)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\treturn help\n\t\t}\n\t\tahelp := signatureHelp(\"a/a/a.go\")\n\t\tbhelp := signatureHelp(\"b/b/b.go\")\n\n\t\tif diff := cmp.Diff(ahelp, bhelp); diff != \"\" {\n\t\t\tt.Fatal(diff)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/staticcheck_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestStaticcheckGenerics(t *testing.T) {\n\t// CL 583778 causes buildir not to run on packages that use\n\t// range-over-func, since it might otherwise crash. But nearly\n\t// all packages will soon meet this description, so the\n\t// analyzers in this test will not run, and the test will fail.\n\t// TODO(adonovan): reenable once dominikh/go-tools#1494 is fixed.\n\tt.Skip(\"disabled until buildir supports range-over-func (dominikh/go-tools#1494)\")\n\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- a/a.go --\npackage a\n\nimport (\n\t\"errors\"\n\t\"sort\"\n\t\"strings\"\n)\n\nfunc Zero[P any]() P {\n\tvar p P\n\treturn p\n}\n\ntype Inst[P any] struct {\n\tField P\n}\n\nfunc testGenerics[P *T, T any](p P) {\n\t// Calls to instantiated functions should not break checks.\n\tslice := Zero[string]()\n\tsort.Slice(slice, func(i, j int) bool {\n\t\treturn slice[i] < slice[j]\n\t})\n\n\t// Usage of instantiated fields should not break checks.\n\tg := Inst[string]{\"hello\"}\n\tg.Field = strings.TrimLeft(g.Field, \"12234\")\n\n\t// Use of type parameters should not break checks.\n\tvar q P\n\tp = q // SA4009: p is overwritten before its first use\n\tq = &*p // SA4001: &* will be simplified\n}\n\n\n// FooErr should be called ErrFoo (ST1012)\nvar FooErr error = errors.New(\"foo\")\n`\n\n\tWithOptions(\n\t\tSettings{\"staticcheck\": true},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"sort.Slice\"), FromSource(\"sortslice\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"sort.Slice.(slice)\"), FromSource(\"SA1028\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"var (FooErr)\"), FromSource(\"ST1012\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", `\"12234\"`), FromSource(\"SA1024\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"testGenerics.*(p P)\"), FromSource(\"SA4009\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"q = (&\\\\*p)\"), FromSource(\"SA4001\")),\n\t\t)\n\t})\n}\n\n// Test for golang/go#56270: an analysis with related info should not panic if\n// analysis.RelatedInformation.End is not set.\nfunc TestStaticcheckRelatedInfo(t *testing.T) {\n\t// CL 583778 causes buildir not to run on packages that use\n\t// range-over-func, since it might otherwise crash. But nearly\n\t// all packages will soon meet this description, so the\n\t// analyzers in this test will not run, and the test will fail.\n\t// TODO(adonovan): reenable once dominikh/go-tools#1494 is fixed.\n\tt.Skip(\"disabled until buildir supports range-over-func (dominikh/go-tools#1494)\")\n\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n-- p.go --\npackage p\n\nimport (\n\t\"fmt\"\n)\n\nfunc Foo(enabled interface{}) {\n\tif enabled, ok := enabled.(bool); ok {\n\t} else {\n\t\t_ = fmt.Sprintf(\"invalid type %T\", enabled) // enabled is always bool here\n\t}\n}\n`\n\n\tWithOptions(\n\t\tSettings{\"staticcheck\": true},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"p.go\", \", (enabled)\"), FromSource(\"SA9008\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/test_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\n// This file defines tests of the source.test (\"Run tests and\n// benchmarks\") code action.\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestRunTestsAndBenchmarks(t *testing.T) {\n\tfile := filepath.Join(t.TempDir(), \"out\")\n\tos.Setenv(\"TESTFILE\", file) // ignore error\n\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.19\n\n-- a/a.go --\npackage a\n\n-- a/a_test.go --\npackage a\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc Test(t *testing.T) {\n\tos.WriteFile(os.Getenv(\"TESTFILE\"), []byte(\"ok\"), 0644)\n}\n\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a_test.go\")\n\t\tloc := env.RegexpSearch(\"a/a_test.go\", \"WriteFile\")\n\n\t\t// Request code actions. (settings.GoTest is special:\n\t\t// it is returned only when explicitly requested.)\n\t\tactions, err := env.Editor.Server.CodeAction(env.Ctx, &protocol.CodeActionParams{\n\t\t\tTextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},\n\t\t\tRange:        loc.Range,\n\t\t\tContext: protocol.CodeActionContext{\n\t\t\t\tOnly: []protocol.CodeActionKind{settings.GoTest},\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif len(actions) != 1 {\n\t\t\tt.Fatalf(\"CodeAction returned %#v, want one source.test action\", actions)\n\t\t}\n\t\tif actions[0].Command == nil {\n\t\t\tt.Fatalf(\"CodeActions()[0] has no Command\")\n\t\t}\n\n\t\t// Execute test.\n\t\t// (ExecuteCommand fails if the test fails.)\n\t\tt.Logf(\"Running %s...\", actions[0].Title)\n\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\tCommand:   actions[0].Command.Command,\n\t\t\tArguments: actions[0].Command.Arguments,\n\t\t}, nil)\n\n\t\t// Check test had expected side effect.\n\t\tdata, err := os.ReadFile(file)\n\t\tif string(data) != \"ok\" {\n\t\t\tt.Fatalf(\"Test did not write expected content of %s; ReadFile returned (%q, %v)\", file, data, err)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/vendor_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nconst basicProxy = `\n-- golang.org/x/hello@v1.2.3/go.mod --\nmodule golang.org/x/hello\n\ngo 1.14\n-- golang.org/x/hello@v1.2.3/hi/hi.go --\npackage hi\n\nvar Goodbye error\n`\n\nfunc TestInconsistentVendoring(t *testing.T) {\n\tconst pkgThatUsesVendoring = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire golang.org/x/hello v1.2.3\n-- vendor/modules.txt --\n-- a/a1.go --\npackage a\n\nimport \"golang.org/x/hello/hi\"\n\nfunc _() {\n\t_ = hi.Goodbye\n\tvar q int // hardcode a diagnostic\n}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t\tProxyFiles(basicProxy),\n\t\tWriteGoSum(\".\"),\n\t).Run(t, pkgThatUsesVendoring, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a1.go\")\n\t\td := &protocol.PublishDiagnosticsParams{}\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"module mod.com\"), WithMessage(\"Inconsistent vendoring\")),\n\t\t\tReadDiagnostics(\"go.mod\", d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"go.mod\", d.Diagnostics)\n\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a1.go\", `q int`), WithMessage(\"not used\")),\n\t\t)\n\t})\n}\n\nfunc TestWindowsVendoring_Issue56291(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire golang.org/x/hello v1.2.3\n-- main.go --\npackage main\n\nimport \"golang.org/x/hello/hi\"\n\nfunc main() {\n\t_ = hi.Goodbye\n}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t\tProxyFiles(basicProxy),\n\t\tWriteGoSum(\".\"),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tenv.RunGoCommand(\"mod\", \"tidy\")\n\t\tenv.RunGoCommand(\"mod\", \"vendor\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tenv.RegexpReplace(\"main.go\", `import \"golang.org/x/hello/hi\"`, \"\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"hi.Goodbye\")),\n\t\t)\n\t\tenv.SaveBuffer(\"main.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/vuln_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/vulntest\"\n)\n\nfunc TestRunGovulncheckError(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo.go --\npackage foo\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tcmd := command.NewRunGovulncheckCommand(\"Run Vulncheck Exp\", command.VulncheckArgs{\n\t\t\tURI: \"/invalid/file/url\", // invalid arg\n\t\t})\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.RunGovulncheck.String(),\n\t\t\tArguments: cmd.Arguments,\n\t\t}\n\n\t\tvar result any\n\t\terr := env.Editor.ExecuteCommand(env.Ctx, params, &result)\n\t\t// We want an error!\n\t\tif err == nil {\n\t\t\tt.Errorf(\"got success, want invalid file URL error. Result: %v\", result)\n\t\t}\n\t})\n}\n\nfunc TestVulncheckError(t *testing.T) {\n\t// This test checks an error of the gopls.vulncheck command, which should be\n\t// returned synchronously.\n\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- foo.go --\npackage foo\n\nfunc F() { // build error incomplete\n`\n\tWithOptions(\n\t\tEnvVars{\n\t\t\t\"_GOPLS_TEST_BINARY_RUN_AS_GOPLS\": \"true\", // needed to run `gopls vulncheck`.\n\t\t},\n\t\tSettings{\n\t\t\t\"codelenses\": map[string]bool{\n\t\t\t\t\"run_govulncheck\": true,\n\t\t\t\t\"vulncheck\":       true,\n\t\t\t},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tvar result command.VulncheckResult\n\t\terr := env.Editor.ExecuteCodeLensCommand(env.Ctx, \"go.mod\", command.Vulncheck, &result)\n\t\tif err == nil {\n\t\t\tt.Fatalf(\"govulncheck succeeded unexpectedly: %v\", result)\n\t\t}\n\t\tvar ws WorkStatus\n\t\tenv.Await(\n\t\t\tCompletedProgress(server.GoVulncheckCommandTitle, &ws),\n\t\t)\n\t\twantEndMsg, wantMsgPart := \"failed\", \"There are errors with the provided package patterns:\"\n\t\tif ws.EndMsg != \"failed\" || !strings.Contains(ws.Msg, wantMsgPart) || !strings.Contains(err.Error(), wantMsgPart) {\n\t\t\tt.Errorf(\"work status = %+v, want {EndMessage: %q, Message: %q}\", ws, wantEndMsg, wantMsgPart)\n\t\t}\n\t})\n}\n\nconst vulnsData = `\n-- GO-2022-01.yaml --\nmodules:\n  - module: golang.org/amod\n    versions:\n      - introduced: 1.0.0\n      - fixed: 1.0.4\n    packages:\n      - package: golang.org/amod/avuln\n        symbols:\n          - VulnData.Vuln1\n          - VulnData.Vuln2\ndescription: >\n    vuln in amod is found\nsummary: vuln in amod\nreferences:\n  - href: pkg.go.dev/vuln/GO-2022-01\n-- GO-2022-03.yaml --\nmodules:\n  - module: golang.org/amod\n    versions:\n      - introduced: 1.0.0\n      - fixed: 1.0.6\n    packages:\n      - package: golang.org/amod/avuln\n        symbols:\n          - nonExisting\ndescription: >\n  unaffecting vulnerability is found\nsummary: unaffecting vulnerability\n-- GO-2022-02.yaml --\nmodules:\n  - module: golang.org/bmod\n    packages:\n      - package: golang.org/bmod/bvuln\n        symbols:\n          - Vuln\ndescription: |\n    vuln in bmod is found.\n    \n    This is a long description\n    of this vulnerability.\nsummary: vuln in bmod (no fix)\nreferences:\n  - href: pkg.go.dev/vuln/GO-2022-03\n-- GO-2022-04.yaml --\nmodules:\n  - module: golang.org/bmod\n    packages:\n      - package: golang.org/bmod/unused\n        symbols:\n          - Vuln\ndescription: |\n    vuln in bmod/somethingelse is found\nsummary: vuln in bmod/somethingelse\nreferences:\n  - href: pkg.go.dev/vuln/GO-2022-04\n-- GOSTDLIB.yaml --\nmodules:\n  - module: stdlib\n    versions:\n      - introduced: 1.18.0\n    packages:\n      - package: archive/zip\n        symbols:\n          - OpenReader\nsummary: vuln in GOSTDLIB\nreferences:\n  - href: pkg.go.dev/vuln/GOSTDLIB\n`\n\nfunc TestRunGovulncheckStd(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n-- main.go --\npackage main\n\nimport (\n        \"archive/zip\"\n        \"fmt\"\n)\n\nfunc main() {\n        _, err := zip.OpenReader(\"file.zip\")  // vulnerability id: GOSTDLIB\n        fmt.Println(err)\n}\n`\n\n\tdb, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\n\tfor _, legacy := range []bool{false, true} {\n\t\tt.Run(fmt.Sprintf(\"legacy=%v\", legacy), func(t *testing.T) {\n\t\t\tlenses := map[string]bool{\"vulncheck\": !legacy, \"run_govulncheck\": legacy}\n\t\t\tWithOptions(\n\t\t\t\tEnvVars{\n\t\t\t\t\t// Let the analyzer read vulnerabilities data from the testdata/vulndb.\n\t\t\t\t\t\"GOVULNDB\": db.URI(),\n\t\t\t\t\t// When fetchinging stdlib package vulnerability info,\n\t\t\t\t\t// behave as if our go version is go1.19 for this testing.\n\t\t\t\t\t// The default behavior is to run `go env GOVERSION` (which isn't mutable env var).\n\t\t\t\t\tcache.GoVersionForVulnTest:        \"go1.19\",\n\t\t\t\t\t\"_GOPLS_TEST_BINARY_RUN_AS_GOPLS\": \"true\", // needed to run `gopls vulncheck`.\n\t\t\t\t},\n\t\t\t\tSettings{\n\t\t\t\t\t\"codelenses\": lenses,\n\t\t\t\t},\n\t\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"go.mod\")\n\n\t\t\t\t// Run Command included in the codelens.\n\n\t\t\t\tvar result *vulncheck.Result\n\t\t\t\tvar expectation Expectation\n\t\t\t\tif legacy {\n\t\t\t\t\tvar r command.RunVulncheckResult\n\t\t\t\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.RunGovulncheck, &r)\n\t\t\t\t\texpectation = CompletedProgressToken(r.Token, nil)\n\t\t\t\t} else {\n\t\t\t\t\tvar r command.VulncheckResult\n\t\t\t\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.Vulncheck, &r)\n\t\t\t\t\tresult = r.Result\n\t\t\t\t\texpectation = CompletedProgress(server.GoVulncheckCommandTitle, nil)\n\t\t\t\t}\n\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\texpectation,\n\t\t\t\t\tShownMessage(\"Found GOSTDLIB\"),\n\t\t\t\t\tNoDiagnostics(ForFile(\"go.mod\")),\n\t\t\t\t)\n\t\t\t\ttestFetchVulncheckResult(t, env, \"go.mod\", result, map[string]fetchVulncheckResult{\n\t\t\t\t\t\"go.mod\": {IDs: []string{\"GOSTDLIB\"}, Mode: vulncheck.ModeGovulncheck},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestFetchVulncheckResultStd(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n\nimport (\n        \"archive/zip\"\n        \"fmt\"\n)\n\nfunc main() {\n        _, err := zip.OpenReader(\"file.zip\")  // vulnerability id: GOSTDLIB\n        fmt.Println(err)\n}\n`\n\n\tdb, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\tWithOptions(\n\t\tEnvVars{\n\t\t\t// Let the analyzer read vulnerabilities data from the testdata/vulndb.\n\t\t\t\"GOVULNDB\": db.URI(),\n\t\t\t// When fetchinging stdlib package vulnerability info,\n\t\t\t// behave as if our go version is go1.18 for this testing.\n\t\t\tcache.GoVersionForVulnTest:        \"go1.18\",\n\t\t\t\"_GOPLS_TEST_BINARY_RUN_AS_GOPLS\": \"true\", // needed to run `gopls vulncheck`.\n\t\t},\n\t\tSettings{\"ui.diagnostic.vulncheck\": \"Imports\"},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"go.mod\")),\n\t\t\t// we don't publish diagnostics for standard library vulnerability yet.\n\t\t)\n\t\ttestFetchVulncheckResult(t, env, \"\", nil, map[string]fetchVulncheckResult{\n\t\t\t\"go.mod\": {\n\t\t\t\tIDs:  []string{\"GOSTDLIB\"},\n\t\t\t\tMode: vulncheck.ModeImports,\n\t\t\t},\n\t\t})\n\t})\n}\n\n// fetchVulncheckResult summarizes a vulncheck result for a single file.\ntype fetchVulncheckResult struct {\n\tIDs  []string\n\tMode vulncheck.AnalysisMode\n}\n\n// testFetchVulncheckResult checks that calling gopls.fetch_vulncheck_result\n// returns the expected summarized results contained in the want argument.\n//\n// If fromRun is non-nil, it is the result of running running vulncheck for\n// runPath, and testFetchVulncheckResult also checks that the fetched result\n// for runPath matches fromRun.\n//\n// This awkward factoring is an artifact of a transition from fetching\n// vulncheck results asynchronously, to allowing the command to run\n// asynchronously, yet returning the result synchronously from the client's\n// perspective.\n//\n// TODO(rfindley): once VS Code no longer depends on fetching results\n// asynchronously, we can remove gopls.fetch_vulncheck_result, and simplify or\n// remove this helper.\nfunc testFetchVulncheckResult(t *testing.T, env *Env, runPath string, fromRun *vulncheck.Result, want map[string]fetchVulncheckResult) {\n\tt.Helper()\n\n\tvar result map[protocol.DocumentURI]*vulncheck.Result\n\tfetchCmd := command.NewFetchVulncheckResultCommand(\"fetch\", command.URIArg{\n\t\tURI: env.Sandbox.Workdir.URI(\"go.mod\"),\n\t})\n\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\tCommand:   fetchCmd.Command,\n\t\tArguments: fetchCmd.Arguments,\n\t}, &result)\n\n\tfor _, v := range want {\n\t\tsort.Strings(v.IDs)\n\t}\n\tsummarize := func(r *vulncheck.Result) fetchVulncheckResult {\n\t\tosv := map[string]bool{}\n\t\tfor _, v := range r.Findings {\n\t\t\tosv[v.OSV] = true\n\t\t}\n\t\tids := make([]string, 0, len(osv))\n\t\tfor id := range osv {\n\t\t\tids = append(ids, id)\n\t\t}\n\t\tsort.Strings(ids)\n\t\treturn fetchVulncheckResult{\n\t\t\tIDs:  ids,\n\t\t\tMode: r.Mode,\n\t\t}\n\t}\n\tgot := map[string]fetchVulncheckResult{}\n\tfor k, r := range result {\n\t\tmodfile := env.Sandbox.Workdir.RelPath(k.Path())\n\t\tgot[modfile] = summarize(r)\n\t}\n\tif fromRun != nil {\n\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"fetch vulncheck result = got %v, want %v: diff %v\", got, want, diff)\n\t\t}\n\t\tif diff := cmp.Diff(summarize(fromRun), got[runPath]); diff != \"\" {\n\t\t\tt.Errorf(\"fetched vulncheck result differs from returned (-returned, +fetched):\\n%s\", diff)\n\t\t}\n\t}\n}\n\nconst workspace1 = `\n-- go.mod --\nmodule golang.org/entry\n\ngo 1.18\n\nrequire golang.org/cmod v1.1.3\n\nrequire (\n\tgolang.org/amod v1.0.0 // indirect\n\tgolang.org/bmod v0.5.0 // indirect\n)\n-- x/x.go --\npackage x\n\nimport \t(\n   \"golang.org/cmod/c\"\n   \"golang.org/entry/y\"\n)\n\nfunc X() {\n\tc.C1().Vuln1() // vuln use: X -> Vuln1\n}\n\nfunc CallY() {\n\ty.Y()  // vuln use: CallY -> y.Y -> bvuln.Vuln \n}\n\n-- y/y.go --\npackage y\n\nimport \"golang.org/cmod/c\"\n\nfunc Y() {\n\tc.C2()() // vuln use: Y -> bvuln.Vuln\n}\n`\n\n// cmod/c imports amod/avuln and bmod/bvuln.\nconst proxy1 = `\n-- golang.org/cmod@v1.1.3/go.mod --\nmodule golang.org/cmod\n\ngo 1.12\n-- golang.org/cmod@v1.1.3/c/c.go --\npackage c\n\nimport (\n\t\"golang.org/amod/avuln\"\n\t\"golang.org/bmod/bvuln\"\n)\n\ntype I interface {\n\tVuln1()\n}\n\nfunc C1() I {\n\tv := avuln.VulnData{}\n\tv.Vuln2() // vuln use\n\treturn v\n}\n\nfunc C2() func() {\n\treturn bvuln.Vuln\n}\n-- golang.org/amod@v1.0.0/go.mod --\nmodule golang.org/amod\n\ngo 1.14\n-- golang.org/amod@v1.0.0/avuln/avuln.go --\npackage avuln\n\ntype VulnData struct {}\nfunc (v VulnData) Vuln1() {}\nfunc (v VulnData) Vuln2() {}\n-- golang.org/amod@v1.0.4/go.mod --\nmodule golang.org/amod\n\ngo 1.14\n-- golang.org/amod@v1.0.4/avuln/avuln.go --\npackage avuln\n\ntype VulnData struct {}\nfunc (v VulnData) Vuln1() {}\nfunc (v VulnData) Vuln2() {}\n\n-- golang.org/bmod@v0.5.0/go.mod --\nmodule golang.org/bmod\n\ngo 1.14\n-- golang.org/bmod@v0.5.0/bvuln/bvuln.go --\npackage bvuln\n\nfunc Vuln() {\n\t// something evil\n}\n-- golang.org/bmod@v0.5.0/unused/unused.go --\npackage unused\n\nfunc Vuln() {\n\t// something evil\n}\n-- golang.org/amod@v1.0.6/go.mod --\nmodule golang.org/amod\n\ngo 1.14\n-- golang.org/amod@v1.0.6/avuln/avuln.go --\npackage avuln\n\ntype VulnData struct {}\nfunc (v VulnData) Vuln1() {}\nfunc (v VulnData) Vuln2() {}\n`\n\nfunc vulnTestEnv(proxyData string) (*vulntest.DB, []RunOption, error) {\n\tdb, err := vulntest.NewDatabase(context.Background(), []byte(vulnsData))\n\tif err != nil {\n\t\treturn nil, nil, nil\n\t}\n\tsettings := Settings{\n\t\t\"codelenses\": map[string]bool{\n\t\t\t\"run_govulncheck\": true,\n\t\t},\n\t}\n\tev := EnvVars{\n\t\t// Let the analyzer read vulnerabilities data from the testdata/vulndb.\n\t\t\"GOVULNDB\": db.URI(),\n\t\t// When fetching stdlib package vulnerability info,\n\t\t// behave as if our go version is go1.18 for this testing.\n\t\t// The default behavior is to run `go env GOVERSION` (which isn't mutable env var).\n\t\tcache.GoVersionForVulnTest:        \"go1.18\",\n\t\t\"_GOPLS_TEST_BINARY_RUN_AS_GOPLS\": \"true\", // needed to run `gopls vulncheck`.\n\t\t\"GOSUMDB\":                         \"off\",\n\t}\n\treturn db, []RunOption{ProxyFiles(proxyData), ev, settings, WriteGoSum(\".\")}, nil\n}\n\nfunc TestRunVulncheckPackageDiagnostics(t *testing.T) {\n\tdb, opts0, err := vulnTestEnv(proxy1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\n\tcheckVulncheckDiagnostics := func(env *Env, t *testing.T) {\n\t\tenv.OpenFile(\"go.mod\")\n\n\t\tgotDiagnostics := &protocol.PublishDiagnosticsParams{}\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", `golang.org/amod`)),\n\t\t\tReadDiagnostics(\"go.mod\", gotDiagnostics),\n\t\t)\n\n\t\ttestFetchVulncheckResult(t, env, \"\", nil, map[string]fetchVulncheckResult{\n\t\t\t\"go.mod\": {\n\t\t\t\tIDs:  []string{\"GO-2022-01\", \"GO-2022-02\", \"GO-2022-03\"},\n\t\t\t\tMode: vulncheck.ModeImports,\n\t\t\t},\n\t\t})\n\n\t\twantVulncheckDiagnostics := map[string]vulnDiagExpectation{\n\t\t\t\"golang.org/amod\": {\n\t\t\t\tdiagnostics: []vulnDiag{\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/amod has known vulnerabilities GO-2022-01, GO-2022-03.\",\n\t\t\t\t\t\tseverity: protocol.SeverityInformation,\n\t\t\t\t\t\tsource:   string(cache.Vulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Run govulncheck to verify\",\n\t\t\t\t\t\t\t\"Upgrade to v1.0.6\",\n\t\t\t\t\t\t\t\"Upgrade to latest\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\"Run govulncheck to verify\",\n\t\t\t\t\t\"Upgrade to v1.0.6\",\n\t\t\t\t\t\"Upgrade to latest\",\n\t\t\t\t},\n\t\t\t\thover: []string{\"GO-2022-01\", \"Fixed in v1.0.4.\", \"GO-2022-03\"},\n\t\t\t},\n\t\t\t\"golang.org/bmod\": {\n\t\t\t\tdiagnostics: []vulnDiag{\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/bmod has a vulnerability GO-2022-02.\",\n\t\t\t\t\t\tseverity: protocol.SeverityInformation,\n\t\t\t\t\t\tsource:   string(cache.Vulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Run govulncheck to verify\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\"Run govulncheck to verify\",\n\t\t\t\t},\n\t\t\t\thover: []string{\"GO-2022-02\", \"vuln in bmod (no fix)\", \"No fix is available.\"},\n\t\t\t},\n\t\t}\n\n\t\tfor pattern, want := range wantVulncheckDiagnostics {\n\t\t\tmodPathDiagnostics := testVulnDiagnostics(t, env, pattern, want, gotDiagnostics)\n\n\t\t\tgotActions := env.CodeActionForFile(\"go.mod\", modPathDiagnostics)\n\t\t\tif diff := diffCodeActions(gotActions, want.codeActions); diff != \"\" {\n\t\t\t\tt.Errorf(\"code actions for %q do not match, got %v, want %v\\n%v\\n\", pattern, gotActions, want.codeActions, diff)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\n\twantNoVulncheckDiagnostics := func(env *Env, t *testing.T) {\n\t\tenv.OpenFile(\"go.mod\")\n\n\t\tgotDiagnostics := &protocol.PublishDiagnosticsParams{}\n\t\tenv.AfterChange(\n\t\t\tReadDiagnostics(\"go.mod\", gotDiagnostics),\n\t\t)\n\n\t\tif len(gotDiagnostics.Diagnostics) > 0 {\n\t\t\tt.Errorf(\"Unexpected diagnostics: %v\", stringify(gotDiagnostics))\n\t\t}\n\t\ttestFetchVulncheckResult(t, env, \"\", nil, map[string]fetchVulncheckResult{})\n\t}\n\n\tfor _, tc := range []struct {\n\t\tname            string\n\t\tsetting         Settings\n\t\twantDiagnostics bool\n\t}{\n\t\t{\"imports\", Settings{\"ui.diagnostic.vulncheck\": \"Imports\"}, true},\n\t\t{\"default\", Settings{}, false},\n\t\t{\"invalid\", Settings{\"ui.diagnostic.vulncheck\": \"invalid\"}, false},\n\t} {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\t// override the settings options to enable diagnostics\n\t\t\topts := append(opts0, tc.setting)\n\t\t\tWithOptions(opts...).Run(t, workspace1, func(t *testing.T, env *Env) {\n\t\t\t\t// TODO(hyangah): implement it, so we see GO-2022-01, GO-2022-02, and GO-2022-03.\n\t\t\t\t// Check that the actions we get when including all diagnostics at a location return the same result\n\t\t\t\tif tc.wantDiagnostics {\n\t\t\t\t\tcheckVulncheckDiagnostics(env, t)\n\t\t\t\t} else {\n\t\t\t\t\twantNoVulncheckDiagnostics(env, t)\n\t\t\t\t}\n\n\t\t\t\tif tc.name == \"imports\" && tc.wantDiagnostics {\n\t\t\t\t\t// test we get only govulncheck-based diagnostics after \"run govulncheck\".\n\t\t\t\t\tvar result command.RunVulncheckResult\n\t\t\t\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.RunGovulncheck, &result)\n\t\t\t\t\tgotDiagnostics := &protocol.PublishDiagnosticsParams{}\n\t\t\t\t\tenv.OnceMet(\n\t\t\t\t\t\tCompletedProgressToken(result.Token, nil),\n\t\t\t\t\t\tShownMessage(\"Found\"),\n\t\t\t\t\t)\n\t\t\t\t\tenv.OnceMet(\n\t\t\t\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"golang.org/bmod\")),\n\t\t\t\t\t\tReadDiagnostics(\"go.mod\", gotDiagnostics),\n\t\t\t\t\t)\n\t\t\t\t\t// We expect only one diagnostic for GO-2022-02.\n\t\t\t\t\tcount := 0\n\t\t\t\t\tfor _, diag := range gotDiagnostics.Diagnostics {\n\t\t\t\t\t\tif strings.Contains(diag.Message, \"GO-2022-02\") {\n\t\t\t\t\t\t\tcount++\n\t\t\t\t\t\t\tif got, want := diag.Severity, protocol.SeverityWarning; got != want {\n\t\t\t\t\t\t\t\tt.Errorf(\"Diagnostic for GO-2022-02 = %v, want %v\", got, want)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif count != 1 {\n\t\t\t\t\t\tt.Errorf(\"Unexpected number of diagnostics about GO-2022-02 = %v, want 1:\\n%+v\", count, stringify(gotDiagnostics))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// TestRunGovulncheck_Expiry checks that govulncheck results expire after a\n// certain amount of time.\nfunc TestRunGovulncheck_Expiry(t *testing.T) {\n\t// For this test, set the max age to a duration smaller than the sleep below.\n\tdefer func(prev time.Duration) {\n\t\tcache.MaxGovulncheckResultAge = prev\n\t}(cache.MaxGovulncheckResultAge)\n\tcache.MaxGovulncheckResultAge = 99 * time.Millisecond\n\n\tdb, opts0, err := vulnTestEnv(proxy1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\n\tWithOptions(opts0...).Run(t, workspace1, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.OpenFile(\"x/x.go\")\n\n\t\tvar result command.RunVulncheckResult\n\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.RunGovulncheck, &result)\n\t\tenv.OnceMet(\n\t\t\tCompletedProgressToken(result.Token, nil),\n\t\t\tShownMessage(\"Found\"),\n\t\t)\n\t\t// Sleep long enough for the results to expire.\n\t\ttime.Sleep(100 * time.Millisecond)\n\t\t// Make an arbitrary edit to force re-diagnosis of the workspace.\n\t\tenv.RegexpReplace(\"x/x.go\", \"package x\", \"package x \")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(env.AtRegexp(\"go.mod\", \"golang.org/bmod\")),\n\t\t)\n\t})\n}\n\nfunc stringify(a any) string {\n\tdata, _ := json.Marshal(a)\n\treturn string(data)\n}\n\nfunc TestRunVulncheckWarning(t *testing.T) {\n\tdb, opts, err := vulnTestEnv(proxy1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\tWithOptions(opts...).Run(t, workspace1, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\n\t\tvar result command.RunVulncheckResult\n\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.RunGovulncheck, &result)\n\t\tgotDiagnostics := &protocol.PublishDiagnosticsParams{}\n\t\tenv.OnceMet(\n\t\t\tCompletedProgressToken(result.Token, nil),\n\t\t\tShownMessage(\"Found\"),\n\t\t)\n\t\t// Vulncheck diagnostics asynchronous to the vulncheck command.\n\t\tenv.OnceMet(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", `golang.org/amod`)),\n\t\t\tReadDiagnostics(\"go.mod\", gotDiagnostics),\n\t\t)\n\n\t\ttestFetchVulncheckResult(t, env, \"go.mod\", nil, map[string]fetchVulncheckResult{\n\t\t\t// All vulnerabilities (symbol-level, import-level, module-level) are reported.\n\t\t\t\"go.mod\": {IDs: []string{\"GO-2022-01\", \"GO-2022-02\", \"GO-2022-03\", \"GO-2022-04\"}, Mode: vulncheck.ModeGovulncheck},\n\t\t})\n\t\tenv.OpenFile(\"x/x.go\")\n\t\tenv.OpenFile(\"y/y.go\")\n\t\twantDiagnostics := map[string]vulnDiagExpectation{\n\t\t\t\"golang.org/amod\": {\n\t\t\t\tapplyAction: \"Upgrade to v1.0.6\",\n\t\t\t\tdiagnostics: []vulnDiag{\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/amod has a vulnerability used in the code: GO-2022-01.\",\n\t\t\t\t\t\tseverity: protocol.SeverityWarning,\n\t\t\t\t\t\tsource:   string(cache.Govulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Upgrade to v1.0.4\",\n\t\t\t\t\t\t\t\"Upgrade to latest\",\n\t\t\t\t\t\t\t\"Reset govulncheck result\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/amod has a vulnerability GO-2022-03 that is not used in the code.\",\n\t\t\t\t\t\tseverity: protocol.SeverityInformation,\n\t\t\t\t\t\tsource:   string(cache.Govulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Upgrade to v1.0.6\",\n\t\t\t\t\t\t\t\"Upgrade to latest\",\n\t\t\t\t\t\t\t\"Reset govulncheck result\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\"Upgrade to v1.0.6\",\n\t\t\t\t\t\"Upgrade to latest\",\n\t\t\t\t\t\"Reset govulncheck result\",\n\t\t\t\t},\n\t\t\t\thover: []string{\"GO-2022-01\", \"Fixed in v1.0.4.\", \"GO-2022-03\"},\n\t\t\t},\n\t\t\t\"golang.org/bmod\": {\n\t\t\t\tdiagnostics: []vulnDiag{\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/bmod has a vulnerability used in the code: GO-2022-02.\",\n\t\t\t\t\t\tseverity: protocol.SeverityWarning,\n\t\t\t\t\t\tsource:   string(cache.Govulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Reset govulncheck result\", // no fix, but we should give an option to reset.\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\"Reset govulncheck result\", // no fix, but we should give an option to reset.\n\t\t\t\t},\n\t\t\t\thover: []string{\"GO-2022-02\", \"vuln in bmod (no fix)\", \"No fix is available.\"},\n\t\t\t},\n\t\t}\n\n\t\tfor mod, want := range wantDiagnostics {\n\t\t\tmodPathDiagnostics := testVulnDiagnostics(t, env, mod, want, gotDiagnostics)\n\n\t\t\t// Check that the actions we get when including all diagnostics at a location return the same result\n\t\t\tgotActions := env.CodeActionForFile(\"go.mod\", modPathDiagnostics)\n\t\t\tif diff := diffCodeActions(gotActions, want.codeActions); diff != \"\" {\n\t\t\t\tt.Errorf(\"code actions for %q do not match, expected %v, got %v\\n%v\\n\", mod, want.codeActions, gotActions, diff)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Apply the code action matching applyAction.\n\t\t\tif want.applyAction == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, action := range gotActions {\n\t\t\t\tif action.Title == want.applyAction {\n\t\t\t\t\tenv.ApplyCodeAction(action)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tenv.Await(env.DoneWithChangeWatchedFiles())\n\t\twantGoMod := `module golang.org/entry\n\ngo 1.18\n\nrequire golang.org/cmod v1.1.3\n\nrequire (\n\tgolang.org/amod v1.0.6 // indirect\n\tgolang.org/bmod v0.5.0 // indirect\n)\n`\n\t\tif got := env.BufferText(\"go.mod\"); got != wantGoMod {\n\t\t\tt.Fatalf(\"go.mod vulncheck fix failed:\\n%s\", compare.Text(wantGoMod, got))\n\t\t}\n\t})\n}\n\nfunc diffCodeActions(gotActions []protocol.CodeAction, want []string) string {\n\tvar gotTitles []string\n\tfor _, ca := range gotActions {\n\t\tgotTitles = append(gotTitles, ca.Title)\n\t}\n\treturn cmp.Diff(want, gotTitles)\n}\n\nconst workspace2 = `\n-- go.mod --\nmodule golang.org/entry\n\ngo 1.18\n\nrequire golang.org/bmod v0.5.0\n\n-- x/x.go --\npackage x\n\nimport \"golang.org/bmod/bvuln\"\n\nfunc F() {\n\t// Calls a benign func in bvuln.\n\tbvuln.OK()\n}\n`\n\nconst proxy2 = `\n-- golang.org/bmod@v0.5.0/bvuln/bvuln.go --\npackage bvuln\n\nfunc Vuln() {} // vulnerable.\nfunc OK() {} // ok.\n`\n\nfunc TestGovulncheckInfo(t *testing.T) {\n\tdb, opts, err := vulnTestEnv(proxy2)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\tWithOptions(opts...).Run(t, workspace2, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tvar result command.RunVulncheckResult\n\t\tenv.ExecuteCodeLensCommand(\"go.mod\", command.RunGovulncheck, &result)\n\t\tgotDiagnostics := &protocol.PublishDiagnosticsParams{}\n\t\tenv.OnceMet(\n\t\t\tCompletedProgressToken(result.Token, nil),\n\t\t\tShownMessage(\"No vulnerabilities found\"), // only count affecting vulnerabilities.\n\t\t)\n\n\t\t// Vulncheck diagnostics asynchronous to the vulncheck command.\n\t\tenv.OnceMet(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"golang.org/bmod\")),\n\t\t\tReadDiagnostics(\"go.mod\", gotDiagnostics),\n\t\t)\n\n\t\ttestFetchVulncheckResult(t, env, \"go.mod\", nil, map[string]fetchVulncheckResult{\n\t\t\t\"go.mod\": {IDs: []string{\"GO-2022-02\", \"GO-2022-04\"}, Mode: vulncheck.ModeGovulncheck},\n\t\t})\n\t\t// wantDiagnostics maps a module path in the require\n\t\t// section of a go.mod to diagnostics that will be returned\n\t\t// when running vulncheck.\n\t\twantDiagnostics := map[string]vulnDiagExpectation{\n\t\t\t\"golang.org/bmod\": {\n\t\t\t\tdiagnostics: []vulnDiag{\n\t\t\t\t\t{\n\t\t\t\t\t\tmsg:      \"golang.org/bmod has a vulnerability GO-2022-02 that is not used in the code.\",\n\t\t\t\t\t\tseverity: protocol.SeverityInformation,\n\t\t\t\t\t\tsource:   string(cache.Govulncheck),\n\t\t\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\t\t\"Reset govulncheck result\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcodeActions: []string{\n\t\t\t\t\t\"Reset govulncheck result\",\n\t\t\t\t},\n\t\t\t\thover: []string{\"GO-2022-02\", \"vuln in bmod (no fix)\", \"No fix is available.\"},\n\t\t\t},\n\t\t}\n\n\t\tvar allActions []protocol.CodeAction\n\t\tfor mod, want := range wantDiagnostics {\n\t\t\tmodPathDiagnostics := testVulnDiagnostics(t, env, mod, want, gotDiagnostics)\n\t\t\t// Check that the actions we get when including all diagnostics at a location return the same result\n\t\t\tgotActions := env.CodeActionForFile(\"go.mod\", modPathDiagnostics)\n\t\t\tallActions = append(allActions, gotActions...)\n\t\t\tif diff := diffCodeActions(gotActions, want.codeActions); diff != \"\" {\n\t\t\t\tt.Errorf(\"code actions for %q do not match, expected %v, got %v\\n%v\\n\", mod, want.codeActions, gotActions, diff)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Clear Diagnostics by using one of the reset code actions.\n\t\tvar reset protocol.CodeAction\n\t\tfor _, a := range allActions {\n\t\t\tif a.Title == \"Reset govulncheck result\" {\n\t\t\t\treset = a\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif reset.Title != \"Reset govulncheck result\" {\n\t\t\tt.Errorf(\"failed to find a 'Reset govulncheck result' code action, got %v\", allActions)\n\t\t}\n\t\tenv.ApplyCodeAction(reset)\n\n\t\tenv.Await(NoDiagnostics(ForFile(\"go.mod\")))\n\t})\n}\n\n// testVulnDiagnostics finds the require or module statement line for the requireMod in go.mod file\n// and runs checks if diagnostics and code actions associated with the line match expectation.\nfunc testVulnDiagnostics(t *testing.T, env *Env, pattern string, want vulnDiagExpectation, got *protocol.PublishDiagnosticsParams) []protocol.Diagnostic {\n\tt.Helper()\n\tloc := env.RegexpSearch(\"go.mod\", pattern)\n\tvar modPathDiagnostics []protocol.Diagnostic\n\tfor _, w := range want.diagnostics {\n\t\t// Find the diagnostics at loc.start.\n\t\tvar diag *protocol.Diagnostic\n\t\tfor _, g := range got.Diagnostics {\n\t\t\tif g.Range.Start == loc.Range.Start && w.msg == g.Message {\n\t\t\t\tmodPathDiagnostics = append(modPathDiagnostics, g)\n\t\t\t\tdiag = &g\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif diag == nil {\n\t\t\tt.Errorf(\"no diagnostic at %q matching %q found\\n\", pattern, w.msg)\n\t\t\tcontinue\n\t\t}\n\t\tif diag.Severity != w.severity || diag.Source != w.source {\n\t\t\tt.Errorf(\"incorrect (severity, source) for %q, want (%s, %s) got (%s, %s)\\n\", w.msg, w.severity, w.source, diag.Severity, diag.Source)\n\t\t}\n\t\t// Check expected code actions appear.\n\t\tgotActions := env.CodeActionForFile(\"go.mod\", []protocol.Diagnostic{*diag})\n\t\tif diff := diffCodeActions(gotActions, w.codeActions); diff != \"\" {\n\t\t\tt.Errorf(\"code actions for %q do not match, want %v, got %v\\n%v\\n\", w.msg, w.codeActions, gotActions, diff)\n\t\t\tcontinue\n\t\t}\n\t}\n\t// Check that useful info is supplemented as hover.\n\tif len(want.hover) > 0 {\n\t\thover, _ := env.Hover(loc)\n\t\tfor _, part := range want.hover {\n\t\t\tif !strings.Contains(hover.Value, part) {\n\t\t\t\tt.Errorf(\"hover contents for %q do not match, want %v, got %v\\n\", pattern, strings.Join(want.hover, \",\"), hover.Value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn modPathDiagnostics\n}\n\ntype vulnRelatedInfo struct {\n\tFilename string\n\tLine     uint32\n\tMessage  string\n}\n\ntype vulnDiag struct {\n\tmsg      string\n\tseverity protocol.DiagnosticSeverity\n\t// codeActions is a list titles of code actions that we get with this\n\t// diagnostics as the context.\n\tcodeActions []string\n\t// relatedInfo is related info message prefixed by the file base.\n\t// See summarizeRelatedInfo.\n\trelatedInfo []vulnRelatedInfo\n\t// diagnostic source.\n\tsource string\n}\n\n// vulnDiagExpectation maps a module path in the require\n// section of a go.mod to diagnostics that will be returned\n// when running vulncheck.\ntype vulnDiagExpectation struct {\n\t// applyAction is the title of the code action to run for this module.\n\t// If empty, no code actions will be executed.\n\tapplyAction string\n\t// diagnostics is the list of diagnostics we expect at the require line for\n\t// the module path.\n\tdiagnostics []vulnDiag\n\t// codeActions is a list titles of code actions that we get with context\n\t// diagnostics.\n\tcodeActions []string\n\t// hover message is the list of expected hover message parts for this go.mod require line.\n\t// all parts must appear in the hover message.\n\thover []string\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/misc/workspace_symbol_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage misc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestWorkspaceSymbolMissingMetadata(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n-- a.go --\npackage p\n\nconst K1 = \"a.go\"\n-- exclude.go --\n\n//go:build exclude\n// +build exclude\n\npackage exclude\n\nconst K2 = \"exclude.go\"\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tcheckSymbols(env, \"K\", \"K1\")\n\n\t\t// Opening up an ignored file will result in an overlay with missing\n\t\t// metadata, but this shouldn't break workspace symbols requests.\n\t\tenv.OpenFile(\"exclude.go\")\n\t\tcheckSymbols(env, \"K\", \"K1\")\n\t})\n}\n\nfunc TestWorkspaceSymbolSorting(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n-- a/a.go --\npackage a\n\nconst (\n\tFoo = iota\n\tFooBar\n\tFooey\n\tFooex\n\tFooest\n)\n`\n\n\tvar symbolMatcher = string(settings.SymbolFastFuzzy)\n\tWithOptions(\n\t\tSettings{\"symbolMatcher\": symbolMatcher},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tcheckSymbols(env, \"Foo\",\n\t\t\t\"Foo\",    // prefer exact segment matches first\n\t\t\t\"FooBar\", // ...followed by exact word matches\n\t\t\t\"Fooex\",  // shorter than Fooest, FooBar, lexically before Fooey\n\t\t\t\"Fooey\",  // shorter than Fooest, Foobar\n\t\t\t\"Fooest\",\n\t\t)\n\t})\n}\n\nfunc TestWorkspaceSymbolSpecialPatterns(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n-- a/a.go --\npackage a\n\nconst (\n\tAxxBxxCxx\n\tABC\n)\n`\n\n\tvar symbolMatcher = string(settings.SymbolFastFuzzy)\n\tWithOptions(\n\t\tSettings{\"symbolMatcher\": symbolMatcher},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tcheckSymbols(env, \"ABC\", \"ABC\", \"AxxBxxCxx\")\n\t\tcheckSymbols(env, \"'ABC\", \"ABC\")\n\t\tcheckSymbols(env, \"^mod.com\", \"mod.com/a.ABC\", \"mod.com/a.AxxBxxCxx\")\n\t\tcheckSymbols(env, \"^mod.com Axx\", \"mod.com/a.AxxBxxCxx\")\n\t\tcheckSymbols(env, \"C$\", \"ABC\")\n\t})\n}\n\nfunc checkSymbols(env *Env, query string, want ...string) {\n\tenv.TB.Helper()\n\tvar got []string\n\tfor _, info := range env.Symbol(query) {\n\t\tgot = append(got, info.Name)\n\t}\n\tif diff := cmp.Diff(got, want); diff != \"\" {\n\t\tenv.TB.Errorf(\"unexpected Symbol(%q) result (+want -got):\\n%s\", query, diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/modfile/modfile_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modfile\n\nimport (\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nconst workspaceProxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nfunc SaySomething() {\n\tfmt.Println(\"something\")\n}\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/bye/bye.go --\npackage bye\n\nfunc Goodbye() {\n\tprintln(\"Bye\")\n}\n`\n\nconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/blah/blah.go --\npackage hello\n\nconst Name = \"Hello\"\n`\n\nfunc TestModFileModification(t *testing.T) {\n\tconst untidyModule = `\n-- a/go.mod --\nmodule mod.com\n\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tprintln(blah.Name)\n}\n`\n\n\trunner := RunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}\n\n\tt.Run(\"basic\", func(t *testing.T) {\n\t\trunner.Run(t, untidyModule, func(t *testing.T, env *Env) {\n\t\t\t// Open the file and make sure that the initial workspace load does not\n\t\t\t// modify the go.mod file.\n\t\t\tgoModContent := env.ReadWorkspaceFile(\"a/go.mod\")\n\t\t\tenv.OpenFile(\"a/main.go\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"\\\"example.com/blah\\\"\")),\n\t\t\t)\n\t\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != goModContent {\n\t\t\t\tt.Fatalf(\"go.mod changed on disk:\\n%s\", compare.Text(goModContent, got))\n\t\t\t}\n\t\t\t// Save the buffer, which will format and organize imports.\n\t\t\t// Confirm that the go.mod file still does not change.\n\t\t\tenv.SaveBuffer(\"a/main.go\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"\\\"example.com/blah\\\"\")),\n\t\t\t)\n\t\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != goModContent {\n\t\t\t\tt.Fatalf(\"go.mod changed on disk:\\n%s\", compare.Text(goModContent, got))\n\t\t\t}\n\t\t})\n\t})\n\n\t// Reproduce golang/go#40269 by deleting and recreating main.go.\n\tt.Run(\"delete main.go\", func(t *testing.T) {\n\t\trunner.Run(t, untidyModule, func(t *testing.T, env *Env) {\n\t\t\tgoModContent := env.ReadWorkspaceFile(\"a/go.mod\")\n\t\t\tmainContent := env.ReadWorkspaceFile(\"a/main.go\")\n\t\t\tenv.OpenFile(\"a/main.go\")\n\t\t\tenv.SaveBuffer(\"a/main.go\")\n\n\t\t\t// Ensure that we're done processing all the changes caused by opening\n\t\t\t// and saving above. If not, we may run into a file locking issue on\n\t\t\t// windows.\n\t\t\t//\n\t\t\t// If this proves insufficient, env.RemoveWorkspaceFile can be updated to\n\t\t\t// retry file lock errors on windows.\n\t\t\tenv.AfterChange()\n\t\t\tenv.RemoveWorkspaceFile(\"a/main.go\")\n\n\t\t\t// TODO(rfindley): awaiting here shouldn't really be necessary. We should\n\t\t\t// be consistent eventually.\n\t\t\t//\n\t\t\t// Probably this was meant to exercise a race with the change below.\n\t\t\tenv.AfterChange()\n\n\t\t\tenv.WriteWorkspaceFile(\"a/main.go\", mainContent)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"\\\"example.com/blah\\\"\")),\n\t\t\t)\n\t\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != goModContent {\n\t\t\t\tt.Fatalf(\"go.mod changed on disk:\\n%s\", compare.Text(goModContent, got))\n\t\t\t}\n\t\t})\n\t})\n}\n\nfunc TestGoGetFix(t *testing.T) {\n\tconst mod = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nvar _ = blah.Name\n`\n\n\tconst want = `module mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n`\n\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, mod, func(t *testing.T, env *Env) {\n\t\tif strings.Contains(t.Name(), \"workspace_module\") {\n\t\t\tt.Skip(\"workspace module mode doesn't set -mod=readonly\")\n\t\t}\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", `\"example.com/blah\"`)),\n\t\t\tReadDiagnostics(\"a/main.go\", &d),\n\t\t)\n\t\tvar goGetDiag protocol.Diagnostic\n\t\tfor _, diag := range d.Diagnostics {\n\t\t\tif strings.Contains(diag.Message, \"could not import\") {\n\t\t\t\tgoGetDiag = diag\n\t\t\t}\n\t\t}\n\t\tenv.ApplyQuickFixes(\"a/main.go\", []protocol.Diagnostic{goGetDiag})\n\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"unexpected go.mod content:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Tests that multiple missing dependencies gives good single fixes.\nfunc TestMissingDependencyFixes(t *testing.T) {\n\tconst mod = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\nimport \"random.org/blah\"\n\nvar _, _ = blah.Name, hello.Name\n`\n\n\tconst want = `module mod.com\n\ngo 1.12\n\nrequire random.org v1.2.3\n`\n\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", `\"random.org/blah\"`)),\n\t\t\tReadDiagnostics(\"a/main.go\", &d),\n\t\t)\n\t\tvar randomDiag protocol.Diagnostic\n\t\tfor _, diag := range d.Diagnostics {\n\t\t\tif strings.Contains(diag.Message, \"random.org\") {\n\t\t\t\trandomDiag = diag\n\t\t\t}\n\t\t}\n\t\tenv.ApplyQuickFixes(\"a/main.go\", []protocol.Diagnostic{randomDiag})\n\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"unexpected go.mod content:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Tests that multiple missing dependencies gives good single fixes.\nfunc TestMissingDependencyFixesWithGoWork(t *testing.T) {\n\tconst mod = `\n-- go.work --\ngo 1.18\n\nuse (\n\t./a\n)\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\nimport \"random.org/blah\"\n\nvar _, _ = blah.Name, hello.Name\n`\n\n\tconst want = `module mod.com\n\ngo 1.12\n\nrequire random.org v1.2.3\n`\n\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", `\"random.org/blah\"`)),\n\t\t\tReadDiagnostics(\"a/main.go\", &d),\n\t\t)\n\t\tvar randomDiag protocol.Diagnostic\n\t\tfor _, diag := range d.Diagnostics {\n\t\t\tif strings.Contains(diag.Message, \"random.org\") {\n\t\t\t\trandomDiag = diag\n\t\t\t}\n\t\t}\n\t\tenv.ApplyQuickFixes(\"a/main.go\", []protocol.Diagnostic{randomDiag})\n\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"unexpected go.mod content:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestIndirectDependencyFix(t *testing.T) {\n\tconst mod = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3 // indirect\n-- a/go.sum --\nexample.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tfmt.Println(blah.Name)\n`\n\tconst want = `module mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n`\n\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/go.mod\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"// indirect\")),\n\t\t\tReadDiagnostics(\"a/go.mod\", &d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"a/go.mod\", d.Diagnostics)\n\t\tif got := env.BufferText(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"unexpected go.mod content:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Test to reproduce golang/go#39041. It adds a new require to a go.mod file\n// that already has an unused require.\nfunc TestNewDepWithUnusedDep(t *testing.T) {\n\n\tconst proxy = `\n-- github.com/esimov/caire@v1.2.5/go.mod --\nmodule github.com/esimov/caire\n\ngo 1.12\n-- github.com/esimov/caire@v1.2.5/caire.go --\npackage caire\n\nfunc RemoveTempImage() {}\n-- google.golang.org/protobuf@v1.20.0/go.mod --\nmodule google.golang.org/protobuf\n\ngo 1.12\n-- google.golang.org/protobuf@v1.20.0/hello/hello.go --\npackage hello\n`\n\tconst repro = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire google.golang.org/protobuf v1.20.0\n-- a/go.sum --\ngithub.com/esimov/caire v1.2.5 h1:OcqDII/BYxcBYj3DuwDKjd+ANhRxRqLa2n69EGje7qw=\ngithub.com/esimov/caire v1.2.5/go.mod h1:mXnjRjg3+WUtuhfSC1rKRmdZU9vJZyS1ZWU0qSvJhK8=\ngoogle.golang.org/protobuf v1.20.0 h1:y9T1vAtFKQg0faFNMOxJU7WuEqPWolVkjIkU6aI8qCY=\ngoogle.golang.org/protobuf v1.20.0/go.mod h1:FcqsytGClbtLv1ot8NvsJHjBi0h22StKVP+K/j2liKA=\n-- a/main.go --\npackage main\n\nimport (\n    \"github.com/esimov/caire\"\n)\n\nfunc _() {\n    caire.RemoveTempImage()\n}`\n\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, repro, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", `\"github.com/esimov/caire\"`)),\n\t\t\tReadDiagnostics(\"a/main.go\", &d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"a/main.go\", d.Diagnostics)\n\t\twant := `module mod.com\n\ngo 1.14\n\nrequire (\n\tgithub.com/esimov/caire v1.2.5\n\tgoogle.golang.org/protobuf v1.20.0\n)\n`\n\t\tif got := env.ReadWorkspaceFile(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"TestNewDepWithUnusedDep failed:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// TODO: For this test to be effective, the sandbox's file watcher must respect\n// the file watching GlobPattern in the capability registration. See\n// golang/go#39384.\nfunc TestModuleChangesOnDisk(t *testing.T) {\n\tconst mod = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n-- a/go.sum --\nexample.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n-- a/main.go --\npackage main\n\nfunc main() {\n\tfmt.Println(blah.Name)\n`\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, mod, func(t *testing.T, env *Env) {\n\t\t// With zero-config gopls, we must open a/main.go to have a View including a/go.mod.\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"require\")),\n\t\t)\n\t\tenv.RunGoCommandInDir(\"a\", \"mod\", \"tidy\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/go.mod\")),\n\t\t)\n\t})\n}\n\n// Tests golang/go#39784: a missing indirect dependency, necessary\n// due to blah@v2.0.0's incomplete go.mod file.\nfunc TestBadlyVersionedModule(t *testing.T) {\n\tconst proxy = `\n-- example.com/blah/@v/v1.0.0.mod --\nmodule example.com\n\ngo 1.12\n-- example.com/blah@v1.0.0/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- example.com/blah/v2/@v/v2.0.0.mod --\nmodule example.com\n\ngo 1.12\n-- example.com/blah/v2@v2.0.0/blah.go --\npackage blah\n\nimport \"example.com/blah\"\n\nvar V1Name = blah.Name\nconst Name = \"Blah\"\n`\n\tconst files = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com/blah/v2 v2.0.0\n-- a/go.sum --\nexample.com/blah v1.0.0 h1:kGPlWJbMsn1P31H9xp/q2mYI32cxLnCvauHN0AVaHnc=\nexample.com/blah v1.0.0/go.mod h1:PZUQaGFeVjyDmAE8ywmLbmDn3fj4Ws8epg4oLuDzW3M=\nexample.com/blah/v2 v2.0.0 h1:DNPsFPkKtTdxclRheaMCiYAoYizp6PuBzO0OmLOO0pY=\nexample.com/blah/v2 v2.0.0/go.mod h1:UZiKbTwobERo/hrqFLvIQlJwQZQGxWMVY4xere8mj7w=\n-- a/main.go --\npackage main\n\nimport \"example.com/blah/v2\"\n\nvar _ = blah.Name\n`\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}.Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tenv.OpenFile(\"a/go.mod\")\n\t\tvar modDiags protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(\n\t\t\t// We would like for the error to appear in the v2 module, but\n\t\t\t// as of writing non-workspace packages are not diagnosed.\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", `\"example.com/blah/v2\"`), WithMessage(\"no required module provides\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", `require example.com/blah/v2`), WithMessage(\"no required module provides\")),\n\t\t\tReadDiagnostics(\"a/go.mod\", &modDiags),\n\t\t)\n\n\t\tenv.ApplyQuickFixes(\"a/go.mod\", modDiags.Diagnostics)\n\t\tconst want = `module mod.com\n\ngo 1.12\n\nrequire (\n\texample.com/blah v1.0.0 // indirect\n\texample.com/blah/v2 v2.0.0\n)\n`\n\t\tenv.SaveBuffer(\"a/go.mod\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"a/main.go\")))\n\t\tif got := env.BufferText(\"a/go.mod\"); got != want {\n\t\t\tt.Fatalf(\"suggested fixes failed:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\n// Reproduces golang/go#38232.\nfunc TestUnknownRevision(t *testing.T) {\n\tif runtime.GOOS == \"plan9\" {\n\t\tt.Skipf(\"skipping test that fails for unknown reasons on plan9; see https://go.dev/issue/50477\")\n\t}\n\tconst unknown = `\n-- a/go.mod --\nmodule mod.com\n\nrequire (\n\texample.com v1.2.2\n)\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tvar x = blah.Name\n}\n`\n\n\trunner := RunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(proxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(proxy))},\n\t}\n\t// Start from a bad state/bad IWL, and confirm that we recover.\n\tt.Run(\"bad\", func(t *testing.T) {\n\t\trunner.Run(t, unknown, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/go.mod\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"example.com v1.2.2\")),\n\t\t\t)\n\t\t\tenv.RegexpReplace(\"a/go.mod\", \"v1.2.2\", \"v1.2.3\")\n\t\t\tenv.SaveBuffer(\"a/go.mod\") // Save to trigger diagnostics.\n\n\t\t\td := protocol.PublishDiagnosticsParams{}\n\t\t\tenv.AfterChange(\n\t\t\t\t// Make sure the diagnostic mentions the new version -- the old diagnostic is in the same place.\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"example.com v1.2.3\"), WithMessage(\"example.com@v1.2.3\")),\n\t\t\t\tReadDiagnostics(\"a/go.mod\", &d),\n\t\t\t)\n\t\t\tqfs := env.GetQuickFixes(\"a/go.mod\", d.Diagnostics)\n\t\t\tif len(qfs) == 0 {\n\t\t\t\tt.Fatalf(\"got 0 code actions to fix %v, wanted at least 1\", d.Diagnostics)\n\t\t\t}\n\t\t\tenv.ApplyCodeAction(qfs[0]) // Arbitrarily pick a single fix to apply. Applying all of them seems to cause trouble in this particular test.\n\t\t\tenv.SaveBuffer(\"a/go.mod\")  // Save to trigger diagnostics.\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/go.mod\")),\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"x = \")),\n\t\t\t)\n\t\t})\n\t})\n\n\tconst known = `\n-- a/go.mod --\nmodule mod.com\n\nrequire (\n\texample.com v1.2.3\n)\n-- a/go.sum --\nexample.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tvar x = blah.Name\n}\n`\n\t// Start from a good state, transform to a bad state, and confirm that we\n\t// still recover.\n\tt.Run(\"good\", func(t *testing.T) {\n\t\trunner.Run(t, known, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/go.mod\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"x = \")),\n\t\t\t)\n\t\t\tenv.RegexpReplace(\"a/go.mod\", \"v1.2.3\", \"v1.2.2\")\n\t\t\tenv.SaveBuffer(\"a/go.mod\") // go.mod changes must be on disk\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"example.com v1.2.2\")),\n\t\t\t)\n\t\t\tenv.RegexpReplace(\"a/go.mod\", \"v1.2.2\", \"v1.2.3\")\n\t\t\tenv.SaveBuffer(\"a/go.mod\") // go.mod changes must be on disk\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"x = \")),\n\t\t\t)\n\t\t})\n\t})\n}\n\n// Confirm that an error in an indirect dependency of a requirement is surfaced\n// as a diagnostic in the go.mod file.\nfunc TestErrorInIndirectDependency(t *testing.T) {\n\tconst badProxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n\nrequire random.org v1.2.3 // indirect\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.org@v1.2.3/go.mod --\nmodule bob.org\n\ngo 1.12\n-- random.org@v1.2.3/blah/blah.go --\npackage hello\n\nconst Name = \"Hello\"\n`\n\tconst module = `\n-- a/go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire example.com v1.2.3\n-- a/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tprintln(blah.Name)\n}\n`\n\tRunMultiple{\n\t\t{\"default\", WithOptions(ProxyFiles(badProxy), WorkspaceFolders(\"a\"))},\n\t\t{\"nested\", WithOptions(ProxyFiles(badProxy))},\n\t}.Run(t, module, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/go.mod\", \"require example.com v1.2.3\")),\n\t\t)\n\t})\n}\n\n// A copy of govim's config_set_env_goflags_mod_readonly test.\nfunc TestGovimModReadonly(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.13\n-- main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tprintln(blah.Name)\n}\n`\n\tWithOptions(\n\t\tEnvVars{\"GOFLAGS\": \"-mod=readonly\"},\n\t\tProxyFiles(proxy),\n\t\tModes(Default),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\toriginal := env.ReadWorkspaceFile(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"example.com/blah\"`)),\n\t\t)\n\t\tgot := env.ReadWorkspaceFile(\"go.mod\")\n\t\tif got != original {\n\t\t\tt.Fatalf(\"go.mod file modified:\\n%s\", compare.Text(original, got))\n\t\t}\n\t\tenv.RunGoCommand(\"get\", \"example.com/blah@v1.2.3\")\n\t\tenv.RunGoCommand(\"mod\", \"tidy\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\nfunc TestMultiModuleModDiagnostics(t *testing.T) {\n\tconst mod = `\n-- go.work --\ngo 1.18\n\nuse (\n\ta\n\tb\n)\n-- a/go.mod --\nmodule moda.com\n\ngo 1.14\n\nrequire (\n\texample.com v1.2.3\n)\n-- a/go.sum --\nexample.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n-- a/main.go --\npackage main\n\nfunc main() {}\n-- b/go.mod --\nmodule modb.com\n\nrequire example.com v1.2.3\n\ngo 1.14\n-- b/main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tblah.SaySomething()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"a/go.mod\", \"example.com v1.2.3\"),\n\t\t\t\tWithMessage(\"is not used\"),\n\t\t\t),\n\t\t)\n\t})\n}\n\nfunc TestModTidyWithBuildTags(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main.go --\n// +build bob\n\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tblah.SaySomething()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tSettings{\"buildFlags\": []string{\"-tags\", \"bob\"}},\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", `\"example.com/blah\"`)),\n\t\t)\n\t})\n}\n\nfunc TestModTypoDiagnostic(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\tRun(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.RegexpReplace(\"go.mod\", \"module\", \"modul\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"modul\")),\n\t\t)\n\t})\n}\n\nfunc TestSumUpdateFixesDiagnostics(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire (\n\texample.com v1.2.3\n)\n-- main.go --\npackage main\n\nimport (\n\t\"example.com/blah\"\n)\n\nfunc main() {\n\tprintln(blah.Name)\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\td := &protocol.PublishDiagnosticsParams{}\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"go.mod\", `example.com v1.2.3`),\n\t\t\t\tWithMessage(\"go.sum is out of sync\"),\n\t\t\t),\n\t\t\tReadDiagnostics(\"go.mod\", d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"go.mod\", d.Diagnostics)\n\t\tenv.SaveBuffer(\"go.mod\") // Save to trigger diagnostics.\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"go.mod\")),\n\t\t)\n\t})\n}\n\n// This test confirms that editing a go.mod file only causes metadata\n// to be invalidated when it's saved.\nfunc TestGoModInvalidatesOnSave(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n\thello()\n}\n-- hello.go --\npackage main\n\nfunc hello() {}\n`\n\tWithOptions(\n\t\t// TODO(rFindley) this doesn't work in multi-module workspace mode, because\n\t\t// it keeps around the last parsing modfile. Update this test to also\n\t\t// exercise the workspace module.\n\t\tModes(Default),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tenv.RegexpReplace(\"go.mod\", \"module\", \"modul\")\n\t\t// Confirm that we still have metadata with only on-disk edits.\n\t\tenv.OpenFile(\"main.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"main.go\", \"hello\"))\n\t\tif loc.URI.Base() != \"hello.go\" {\n\t\t\tt.Fatalf(\"expected definition in hello.go, got %s\", loc.URI)\n\t\t}\n\t\t// Confirm that we no longer have metadata when the file is saved.\n\t\tenv.SaveBufferWithoutActions(\"go.mod\")\n\t\t_, err := env.Editor.Definitions(env.Ctx, env.RegexpSearch(\"main.go\", \"hello\"))\n\t\tif err == nil {\n\t\t\tt.Fatalf(\"expected error, got none\")\n\t\t}\n\t})\n}\n\nfunc TestRemoveUnusedDependency(t *testing.T) {\n\tconst proxy = `\n-- hasdep.com@v1.2.3/go.mod --\nmodule hasdep.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n-- hasdep.com@v1.2.3/a/a.go --\npackage a\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n-- random.com@v1.2.3/go.mod --\nmodule random.com\n\ngo 1.12\n-- random.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n`\n\tt.Run(\"almost tidied\", func(t *testing.T) {\n\t\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire hasdep.com v1.2.3\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\t\tWithOptions(\n\t\t\tProxyFiles(proxy),\n\t\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"go.mod\")\n\t\t\td := &protocol.PublishDiagnosticsParams{}\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"require hasdep.com v1.2.3\")),\n\t\t\t\tReadDiagnostics(\"go.mod\", d),\n\t\t\t)\n\t\t\tconst want = `module mod.com\n\ngo 1.12\n`\n\t\t\tenv.ApplyQuickFixes(\"go.mod\", d.Diagnostics)\n\t\t\tif got := env.BufferText(\"go.mod\"); got != want {\n\t\t\t\tt.Fatalf(\"unexpected content in go.mod:\\n%s\", compare.Text(want, got))\n\t\t\t}\n\t\t})\n\t})\n\n\tt.Run(\"not tidied\", func(t *testing.T) {\n\t\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire hasdep.com v1.2.3\nrequire random.com v1.2.3\n-- main.go --\npackage main\n\nfunc main() {}\n`\n\t\tWithOptions(\n\t\t\tWriteGoSum(\".\"),\n\t\t\tProxyFiles(proxy),\n\t\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\t\td := &protocol.PublishDiagnosticsParams{}\n\t\t\tenv.OpenFile(\"go.mod\")\n\t\t\tpos := env.RegexpSearch(\"go.mod\", \"require hasdep.com v1.2.3\").Range.Start\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(AtPosition(\"go.mod\", pos.Line, pos.Character)),\n\t\t\t\tReadDiagnostics(\"go.mod\", d),\n\t\t\t)\n\t\t\tconst want = `module mod.com\n\ngo 1.12\n\nrequire random.com v1.2.3\n`\n\t\t\tvar diagnostics []protocol.Diagnostic\n\t\t\tfor _, d := range d.Diagnostics {\n\t\t\t\tif d.Range.Start.Line != pos.Line {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdiagnostics = append(diagnostics, d)\n\t\t\t}\n\t\t\tenv.ApplyQuickFixes(\"go.mod\", diagnostics)\n\t\t\tif got := env.BufferText(\"go.mod\"); got != want {\n\t\t\t\tt.Fatalf(\"unexpected content in go.mod:\\n%s\", compare.Text(want, got))\n\t\t\t}\n\t\t})\n\t})\n}\n\nfunc TestSumUpdateQuickFix(t *testing.T) {\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire (\n\texample.com v1.2.3\n)\n-- main.go --\npackage main\n\nimport (\n\t\"example.com/blah\"\n)\n\nfunc main() {\n\tblah.Hello()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tModes(Default),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.mod\")\n\t\tparams := &protocol.PublishDiagnosticsParams{}\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"go.mod\", `example.com`),\n\t\t\t\tWithMessage(\"go.sum is out of sync\"),\n\t\t\t),\n\t\t\tReadDiagnostics(\"go.mod\", params),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"go.mod\", params.Diagnostics)\n\t\tconst want = `example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n`\n\t\tif got := env.ReadWorkspaceFile(\"go.sum\"); got != want {\n\t\t\tt.Fatalf(\"unexpected go.sum contents:\\n%s\", compare.Text(want, got))\n\t\t}\n\t})\n}\n\nfunc TestDownloadDeps(t *testing.T) {\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n\nrequire random.org v1.2.3\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nimport \"random.org/bye\"\n\nfunc SaySomething() {\n\tbye.Goodbye()\n}\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/bye/bye.go --\npackage bye\n\nfunc Goodbye() {\n\tprintln(\"Bye\")\n}\n`\n\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- main.go --\npackage main\n\nimport (\n\t\"example.com/blah\"\n)\n\nfunc main() {\n\tblah.SaySomething()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tModes(Default),\n\t).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\td := &protocol.PublishDiagnosticsParams{}\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"main.go\", `\"example.com/blah\"`),\n\t\t\t\tWithMessage(`could not import example.com/blah (no required module provides package \"example.com/blah\")`),\n\t\t\t),\n\t\t\tReadDiagnostics(\"main.go\", d),\n\t\t)\n\t\tenv.ApplyQuickFixes(\"main.go\", d.Diagnostics)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\tNoDiagnostics(ForFile(\"go.mod\")),\n\t\t)\n\t})\n}\n\nfunc TestInvalidGoVersion(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo foo\n-- main.go --\npackage main\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", `go foo`), WithMessage(\"invalid go version\")),\n\t\t)\n\t\tenv.WriteWorkspaceFile(\"go.mod\", \"module mod.com \\n\\ngo 1.12\\n\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"go.mod\")))\n\t})\n}\n\n// This is a regression test for a bug in the line-oriented implementation\n// of the \"apply diffs\" operation used by the fake editor.\nfunc TestIssue57627(t *testing.T) {\n\tconst files = `\n-- go.work --\npackage main\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\t\tenv.SetBufferContent(\"go.work\", \"go 1.18\\nuse moda/a\")\n\t\tenv.SaveBuffer(\"go.work\") // doesn't fail\n\t})\n}\n\nfunc TestInconsistentMod(t *testing.T) {\n\tconst proxy = `\n-- golang.org/x/mod@v0.7.0/go.mod --\ngo 1.20\nmodule golang.org/x/mod\n-- golang.org/x/mod@v0.7.0/a.go --\npackage mod\nfunc AutoQuote(string) string { return \"\"}\n-- golang.org/x/mod@v0.9.0/go.mod --\ngo 1.20\nmodule golang.org/x/mod\n-- golang.org/x/mod@v0.9.0/a.go --\npackage mod\nfunc AutoQuote(string) string { return \"\"}\n`\n\tconst files = `\n-- go.work --\ngo 1.20\nuse (\n\t./a\n\t./b\n)\n\n-- a/go.mod --\nmodule a.mod.com\ngo 1.20\nrequire golang.org/x/mod v0.6.0 // yyy\nreplace golang.org/x/mod v0.6.0 => golang.org/x/mod v0.7.0\n-- a/main.go --\npackage main\nimport \"golang.org/x/mod\"\nimport \"fmt\"\nfunc main() {fmt.Println(mod.AutoQuote(\"\"))}\n\n-- b/go.mod --\nmodule b.mod.com\ngo 1.20\nrequire golang.org/x/mod v0.9.0 // xxx\n-- b/main.go --\npackage aaa\nimport \"golang.org/x/mod\"\nimport \"fmt\"\nfunc main() {fmt.Println(mod.AutoQuote(\"\"))}\nvar A int\n\n-- b/c/go.mod --\nmodule c.b.mod.com\ngo 1.20\nrequire b.mod.com v0.4.2\nreplace b.mod.com => ../\n-- b/c/main.go --\npackage main\nimport \"b.mod.com/aaa\"\nimport \"fmt\"\nfunc main() {fmt.Println(aaa.A)}\n`\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t\tModes(Default),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/go.mod\")\n\t\tahints := env.InlayHints(\"a/go.mod\")\n\t\tif len(ahints) != 1 {\n\t\t\tt.Errorf(\"expected exactly one hint, got %d: %#v\", len(ahints), ahints)\n\t\t}\n\t\tenv.OpenFile(\"b/c/go.mod\")\n\t\tbhints := env.InlayHints(\"b/c/go.mod\")\n\t\tif len(bhints) != 0 {\n\t\t\tt.Errorf(\"expected no hints, got %d: %#v\", len(bhints), bhints)\n\t\t}\n\t})\n\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/modfile/tempmodfile_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modfile\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// This test replaces an older, problematic test (golang/go#57784). But it has\n// been a long time since the go command would mutate go.mod files.\n//\n// TODO(golang/go#61970): the tempModfile setting should be removed entirely.\nfunc TestTempModfileUnchanged(t *testing.T) {\n\t// badMod has a go.mod file that is missing a go directive.\n\tconst badMod = `\n-- go.mod --\nmodule badmod.test/p\n-- p.go --\npackage p\n`\n\n\tWithOptions(\n\t\tModes(Default), // no reason to test this with a remote gopls\n\t\tProxyFiles(workspaceProxy),\n\t\tSettings{\n\t\t\t\"tempModfile\": true,\n\t\t},\n\t).Run(t, badMod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.AfterChange()\n\t\twant := \"module badmod.test/p\\n\"\n\t\tgot := env.ReadWorkspaceFile(\"go.mod\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"go.mod content:\\n%s\\nwant:\\n%s\", got, want)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/options.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"maps\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/drivertest\"\n)\n\ntype runConfig struct {\n\teditor        fake.EditorConfig\n\tsandbox       fake.SandboxConfig\n\tmodes         Mode\n\tnoLogsOnError bool\n\twriteGoSum    []string\n}\n\nfunc defaultConfig() runConfig {\n\treturn runConfig{\n\t\teditor: fake.EditorConfig{\n\t\t\tSettings: map[string]any{\n\t\t\t\t// Shorten the diagnostic delay to speed up test execution (else we'd add\n\t\t\t\t// the default delay to each assertion about diagnostics)\n\t\t\t\t\"diagnosticsDelay\": \"10ms\",\n\t\t\t},\n\t\t},\n\t}\n}\n\n// A RunOption augments the behavior of the test runner.\ntype RunOption interface {\n\tset(*runConfig)\n}\n\ntype optionSetter func(*runConfig)\n\nfunc (f optionSetter) set(opts *runConfig) {\n\tf(opts)\n}\n\n// ProxyFiles configures a file proxy using the given txtar-encoded string.\nfunc ProxyFiles(txt string) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.sandbox.ProxyFiles = fake.UnpackTxt(txt)\n\t})\n}\n\n// WriteGoSum causes the environment to write a go.sum file for the requested\n// relative directories (via `go list -mod=mod`), before starting gopls.\n//\n// Useful for tests that use ProxyFiles, but don't care about crafting the\n// go.sum content.\nfunc WriteGoSum(dirs ...string) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.writeGoSum = dirs\n\t})\n}\n\n// Modes configures the execution modes that the test should run in.\n//\n// By default, modes are configured by the test runner. If this option is set,\n// it overrides the set of default modes and the test runs in exactly these\n// modes.\nfunc Modes(modes Mode) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\tif opts.modes != 0 {\n\t\t\tpanic(\"modes set more than once\")\n\t\t}\n\t\topts.modes = modes\n\t})\n}\n\n// NoLogsOnError turns off dumping the LSP logs on test failures.\nfunc NoLogsOnError() RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.noLogsOnError = true\n\t})\n}\n\n// WindowsLineEndings configures the editor to use windows line endings.\nfunc WindowsLineEndings() RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.WindowsLineEndings = true\n\t})\n}\n\n// ClientName sets the LSP client name.\nfunc ClientName(name string) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.ClientName = name\n\t})\n}\n\n// CapabilitiesJSON sets the capabalities json.\nfunc CapabilitiesJSON(capabilities []byte) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.CapabilitiesJSON = capabilities\n\t})\n}\n\n// Settings sets user-provided configuration for the LSP server.\n//\n// As a special case, the env setting must not be provided via Settings: use\n// EnvVars instead.\ntype Settings map[string]any\n\nfunc (s Settings) set(opts *runConfig) {\n\tif opts.editor.Settings == nil {\n\t\topts.editor.Settings = make(map[string]any)\n\t}\n\tmaps.Copy(opts.editor.Settings, s)\n}\n\n// WorkspaceFolders configures the workdir-relative workspace folders or uri\n// to send to the LSP server. By default the editor sends a single workspace folder\n// corresponding to the workdir root. To explicitly configure no workspace\n// folders, use WorkspaceFolders with no arguments.\nfunc WorkspaceFolders(relFolders ...string) RunOption {\n\tif len(relFolders) == 0 {\n\t\t// Use an empty non-nil slice to signal explicitly no folders.\n\t\trelFolders = []string{}\n\t}\n\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.WorkspaceFolders = relFolders\n\t})\n}\n\n// NoDefaultWorkspaceFiles is used to specify whether the fake editor\n// should give a default workspace folder to the LSP server.\n// When it's true, the editor will pass original WorkspaceFolders to the LSP server.\nfunc NoDefaultWorkspaceFiles() RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.NoDefaultWorkspaceFiles = true\n\t})\n}\n\n// RootPath configures the roo path which will be converted to rootUri and sent to the LSP server.\nfunc RootPath(relpath string) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.RelRootPath = relpath\n\t})\n}\n\n// FolderSettings defines per-folder workspace settings, keyed by relative path\n// to the folder.\n//\n// Use in conjunction with WorkspaceFolders to have different settings for\n// different folders.\ntype FolderSettings map[string]Settings\n\nfunc (fs FolderSettings) set(opts *runConfig) {\n\t// Re-use the Settings type, for symmetry, but translate back into maps for\n\t// the editor config.\n\tfolders := make(map[string]map[string]any)\n\tfor k, v := range fs {\n\t\tfolders[k] = v\n\t}\n\topts.editor.FolderSettings = folders\n}\n\n// EnvVars sets environment variables for the LSP session. When applying these\n// variables to the session, the special string $SANDBOX_WORKDIR is replaced by\n// the absolute path to the sandbox working directory.\ntype EnvVars map[string]string\n\nfunc (e EnvVars) set(opts *runConfig) {\n\tif opts.editor.Env == nil {\n\t\topts.editor.Env = make(map[string]string)\n\t}\n\tmaps.Copy(opts.editor.Env, e)\n}\n\n// FakeGoPackagesDriver configures gopls to run with a fake GOPACKAGESDRIVER\n// environment variable.\nfunc FakeGoPackagesDriver(t *testing.T) RunOption {\n\tenv := drivertest.Env(t)\n\tvars := make(EnvVars)\n\tfor _, e := range env {\n\t\tkv := strings.SplitN(e, \"=\", 2)\n\t\tvars[kv[0]] = kv[1]\n\t}\n\treturn vars\n}\n\n// InGOPATH configures the workspace working directory to be GOPATH, rather\n// than a separate working directory for use with modules.\nfunc InGOPATH() RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.sandbox.InGoPath = true\n\t})\n}\n\n// MessageResponder configures the editor to respond to\n// window/showMessageRequest messages using the provided function.\nfunc MessageResponder(f func(*protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error)) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.MessageResponder = f\n\t})\n}\n\n// DelayMessages can be used to fuzz message delivery delays for the purpose of\n// reproducing test flakes.\n//\n// (Even though this option may be unused, keep it around to aid in debugging\n// future flakes.)\nfunc DelayMessages(upto time.Duration) RunOption {\n\treturn optionSetter(func(opts *runConfig) {\n\t\topts.editor.MaxMessageDelay = upto\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/regtest.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/cmd\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/internal/drivertest\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\nvar (\n\trunSubprocessTests       = flag.Bool(\"enable_gopls_subprocess_tests\", false, \"run integration tests against a gopls subprocess (default: in-process)\")\n\tgoplsBinaryPath          = flag.String(\"gopls_test_binary\", \"\", \"path to the gopls binary for use as a remote, for use with the -enable_gopls_subprocess_tests flag\")\n\ttimeout                  = flag.Duration(\"timeout\", defaultTimeout(), \"if nonzero, default timeout for each integration test; defaults to GOPLS_INTEGRATION_TEST_TIMEOUT\")\n\tskipCleanup              = flag.Bool(\"skip_cleanup\", false, \"whether to skip cleaning up temp directories\")\n\tprintGoroutinesOnFailure = flag.Bool(\"print_goroutines\", false, \"whether to print goroutines info on failure\")\n\tprintLogs                = flag.Bool(\"print_logs\", false, \"whether to print LSP logs\")\n)\n\nfunc defaultTimeout() time.Duration {\n\ts := os.Getenv(\"GOPLS_INTEGRATION_TEST_TIMEOUT\")\n\tif s == \"\" {\n\t\treturn 0\n\t}\n\td, err := time.ParseDuration(s)\n\tif err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"invalid GOPLS_INTEGRATION_TEST_TIMEOUT %q: %v\\n\", s, err)\n\t\tos.Exit(2)\n\t}\n\treturn d\n}\n\nvar runner *Runner\n\nfunc Run(t *testing.T, files string, f TestFunc) {\n\trunner.Run(t, files, f)\n}\n\nfunc WithOptions(opts ...RunOption) configuredRunner {\n\treturn configuredRunner{opts: opts}\n}\n\ntype configuredRunner struct {\n\topts []RunOption\n}\n\nfunc (r configuredRunner) Run(t *testing.T, files string, f TestFunc) {\n\t// Print a warning if the test's temporary directory is not\n\t// suitable as a workspace folder, as this may lead to\n\t// otherwise-cryptic failures. This situation typically occurs\n\t// when an arbitrary string (e.g. \"foo.\") is used as a subtest\n\t// name, on a platform with filename restrictions (e.g. no\n\t// trailing period on Windows).\n\ttmp := t.TempDir()\n\tif err := cache.CheckPathValid(tmp); err != nil {\n\t\tt.Logf(\"Warning: testing.T.TempDir(%s) is not valid as a workspace folder: %s\",\n\t\t\ttmp, err)\n\t}\n\n\trunner.Run(t, files, f, r.opts...)\n}\n\n// RunMultiple runs a test multiple times, with different options.\n// The runner should be constructed with [WithOptions].\n//\n// TODO(rfindley): replace Modes with selective use of RunMultiple.\ntype RunMultiple []struct {\n\tName   string\n\tRunner interface {\n\t\tRun(t *testing.T, files string, f TestFunc)\n\t}\n}\n\nfunc (r RunMultiple) Run(t *testing.T, files string, f TestFunc) {\n\tfor _, runner := range r {\n\t\tt.Run(runner.Name, func(t *testing.T) {\n\t\t\trunner.Runner.Run(t, files, f)\n\t\t})\n\t}\n}\n\n// DefaultModes returns the default modes to run for each regression test (they\n// may be reconfigured by the tests themselves).\nfunc DefaultModes() Mode {\n\tmodes := Default\n\tif !testing.Short() {\n\t\t// TODO(rfindley): we should just run a few select integration tests in\n\t\t// \"Forwarded\" mode, and call it a day. No need to run every single test in\n\t\t// two ways.\n\t\tmodes |= Forwarded\n\t}\n\tif *runSubprocessTests {\n\t\tmodes |= SeparateProcess\n\t}\n\treturn modes\n}\n\nvar runFromMain = false // true if Main has been called\n\n// Main sets up and tears down the shared integration test state.\nfunc Main(m *testing.M) (code int) {\n\t// Provide an entrypoint for tests that use a fake go/packages driver.\n\tdrivertest.RunIfChild()\n\n\tdefer func() {\n\t\tif runner != nil {\n\t\t\tif err := runner.Close(); err != nil {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"closing test runner: %v\\n\", err)\n\t\t\t\t// Cleanup is broken in go1.12 and earlier, and sometimes flakes on\n\t\t\t\t// Windows due to file locking, but this is OK for our CI.\n\t\t\t\t//\n\t\t\t\t// Fail on go1.13+, except for windows and android which have shutdown problems.\n\t\t\t\tif testenv.Go1Point() >= 13 && runtime.GOOS != \"windows\" && runtime.GOOS != \"android\" {\n\t\t\t\t\tif code == 0 {\n\t\t\t\t\t\tcode = 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n\n\trunFromMain = true\n\n\t// golang/go#54461: enable additional debugging around hanging Go commands.\n\tgocommand.DebugHangingGoCommands = true\n\n\t// If this magic environment variable is set, run gopls instead of the test\n\t// suite. See the documentation for runTestAsGoplsEnvvar for more details.\n\tif os.Getenv(runTestAsGoplsEnvvar) == \"true\" {\n\t\ttool.Main(context.Background(), cmd.New(), os.Args[1:])\n\t\treturn 0\n\t}\n\n\tif !testenv.HasExec() {\n\t\tfmt.Printf(\"skipping all tests: exec not supported on %s/%s\\n\", runtime.GOOS, runtime.GOARCH)\n\t\treturn 0\n\t}\n\ttestenv.ExitIfSmallMachine()\n\n\tflag.Parse()\n\n\t// Disable GOPACKAGESDRIVER, as it can cause spurious test failures.\n\tos.Setenv(\"GOPACKAGESDRIVER\", \"off\") // ignore error\n\n\tif skipReason := checkBuilder(); skipReason != \"\" {\n\t\tfmt.Printf(\"Skipping all tests: %s\\n\", skipReason)\n\t\treturn 0\n\t}\n\n\tif err := testenv.HasTool(\"go\"); err != nil {\n\t\tfmt.Println(\"Missing go command\")\n\t\treturn 1\n\t}\n\n\trunner = &Runner{\n\t\tDefaultModes:             DefaultModes(),\n\t\tTimeout:                  *timeout,\n\t\tPrintGoroutinesOnFailure: *printGoroutinesOnFailure,\n\t\tSkipCleanup:              *skipCleanup,\n\t\tstore:                    memoize.NewStore(memoize.NeverEvict),\n\t}\n\n\trunner.goplsPath = *goplsBinaryPath\n\tif runner.goplsPath == \"\" {\n\t\tvar err error\n\t\trunner.goplsPath, err = os.Executable()\n\t\tif err != nil {\n\t\t\tpanic(fmt.Sprintf(\"finding test binary path: %v\", err))\n\t\t}\n\t}\n\n\tdir, err := os.MkdirTemp(\"\", \"gopls-test-\")\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"creating temp directory: %v\", err))\n\t}\n\trunner.tempDir = dir\n\n\tFilterToolchainPathAndGOROOT()\n\n\treturn m.Run()\n}\n\n// FilterToolchainPathAndGOROOT updates the PATH and GOROOT environment\n// variables for the current process to effectively revert the changes made by\n// the go command when performing a toolchain switch in the context of `go\n// test` (see golang/go#68005).\n//\n// It does this by looking through PATH for a go command that is NOT a\n// toolchain go command, and adjusting PATH to find that go command. Then it\n// unsets GOROOT in order to use the default GOROOT for that go command.\n//\n// TODO(rfindley): this is very much a hack, so that our 1.21 and 1.22 builders\n// actually exercise integration with older go commands. In golang/go#69321, we\n// hope to do better.\nfunc FilterToolchainPathAndGOROOT() {\n\tif localGo, first := findLocalGo(); localGo != \"\" && !first {\n\t\tdir := filepath.Dir(localGo)\n\t\tpath := os.Getenv(\"PATH\")\n\t\tos.Setenv(\"PATH\", dir+string(os.PathListSeparator)+path) // ignore error\n\t\tos.Unsetenv(\"GOROOT\")                                    // Remove the GOROOT value that was added by toolchain switch.\n\t}\n}\n\n// findLocalGo returns a path to a local (=non-toolchain) Go version, or the\n// empty string if none is found.\n//\n// The second result reports if path matches the result of exec.LookPath.\nfunc findLocalGo() (path string, first bool) {\n\tpaths := filepath.SplitList(os.Getenv(\"PATH\"))\n\tfor _, path := range paths {\n\t\t// Use a simple heuristic to filter out toolchain paths.\n\t\tif strings.Contains(path, \"toolchain@v0.0.1-go\") && filepath.Base(path) == \"bin\" {\n\t\t\tcontinue // toolchain path\n\t\t}\n\t\tfullPath := filepath.Join(path, \"go\")\n\t\tfi, err := os.Stat(fullPath)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif fi.Mode()&0111 != 0 {\n\t\t\tfirst := false\n\t\t\tpathGo, err := exec.LookPath(\"go\")\n\t\t\tif err == nil {\n\t\t\t\tfirst = fullPath == pathGo\n\t\t\t}\n\t\t\treturn fullPath, first\n\t\t}\n\t}\n\treturn \"\", false\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/runner.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// Mode is a bitmask that defines for which execution modes a test should run.\n//\n// Each mode controls several aspects of gopls' configuration:\n//   - Which server options to use for gopls sessions\n//   - Whether to use a shared cache\n//   - Whether to use a shared server\n//   - Whether to run the server in-process or in a separate process\n//\n// The behavior of each mode with respect to these aspects is summarized below.\n// TODO(rfindley, cleanup): rather than using arbitrary names for these modes,\n// we can compose them explicitly out of the features described here, allowing\n// individual tests more freedom in constructing problematic execution modes.\n// For example, a test could assert on a certain behavior when running on a\n// separate process. Moreover, we could unify 'Modes' with 'Options', and use\n// RunMultiple rather than a hard-coded loop through modes.\n//\n// Mode            | Options      | Shared Cache? | Shared Server? | In-process?\n// ---------------------------------------------------------------------------\n// Default         | Default      | Y             | N              | Y\n// Forwarded       | Default      | Y             | Y              | Y\n// SeparateProcess | Default      | Y             | Y              | N\ntype Mode int\n\nconst (\n\t// Default mode runs gopls with the default options, communicating over pipes\n\t// to emulate the lsp sidecar execution mode, which communicates over\n\t// stdin/stdout.\n\t//\n\t// It uses separate servers for each test, but a shared cache, to avoid\n\t// duplicating work when processing GOROOT.\n\tDefault Mode = 1 << iota\n\n\t// Forwarded uses the default options, but forwards connections to a shared\n\t// in-process gopls server.\n\tForwarded\n\n\t// SeparateProcess uses the default options, but forwards connection to an\n\t// external gopls daemon.\n\t//\n\t// Only supported on GOOS=linux.\n\tSeparateProcess\n)\n\nfunc (m Mode) String() string {\n\tswitch m {\n\tcase Default:\n\t\treturn \"default\"\n\tcase Forwarded:\n\t\treturn \"forwarded\"\n\tcase SeparateProcess:\n\t\treturn \"separate process\"\n\tdefault:\n\t\treturn \"unknown mode\"\n\t}\n}\n\n// A Runner runs tests in gopls execution environments, as specified by its\n// modes. For modes that share state (for example, a shared cache or common\n// remote), any tests that execute on the same Runner will share the same\n// state.\ntype Runner struct {\n\t// Configuration\n\tDefaultModes             Mode          // modes to run for each test\n\tTimeout                  time.Duration // per-test timeout, if set\n\tPrintGoroutinesOnFailure bool          // whether to dump goroutines on test failure\n\tSkipCleanup              bool          // if set, don't delete test data directories when the test exits\n\n\t// Immutable state shared across test invocations\n\tgoplsPath string         // path to the gopls executable (for SeparateProcess mode)\n\ttempDir   string         // shared parent temp directory\n\tstore     *memoize.Store // shared store\n\n\t// Lazily allocated resources\n\ttsOnce sync.Once\n\tts     *servertest.TCPServer // shared in-process test server (\"forwarded\" mode)\n\n\tstartRemoteOnce sync.Once\n\tremoteSocket    string // unix domain socket for shared daemon (\"separate process\" mode)\n\tremoteErr       error\n\tcancelRemote    func()\n}\n\ntype TestFunc func(t *testing.T, env *Env)\n\n// Run executes the test function in the default configured gopls execution\n// modes. For each a test run, a new workspace is created containing the\n// un-txtared files specified by filedata.\nfunc (r *Runner) Run(t *testing.T, files string, test TestFunc, opts ...RunOption) {\n\t// TODO(rfindley): this function has gotten overly complicated, and warrants\n\t// refactoring.\n\n\tif !runFromMain {\n\t\t// Main performs various setup precondition checks.\n\t\t// While it could theoretically be made OK for a Runner to be used outside\n\t\t// of Main, it is simpler to enforce that we only use the Runner from\n\t\t// integration test suites.\n\t\tt.Fatal(\"integration.Runner.Run must be run from integration.Main\")\n\t}\n\n\ttests := []struct {\n\t\tname      string\n\t\tmode      Mode\n\t\tgetServer func() jsonrpc2.StreamServer\n\t}{\n\t\t{\"default\", Default, r.defaultServer},\n\t\t{\"forwarded\", Forwarded, r.forwardedServer},\n\t\t{\"separate_process\", SeparateProcess, r.separateProcessServer},\n\t}\n\n\tfor _, tc := range tests {\n\t\tconfig := defaultConfig()\n\t\tfor _, opt := range opts {\n\t\t\topt.set(&config)\n\t\t}\n\t\tmodes := r.DefaultModes\n\t\tif config.modes != 0 {\n\t\t\tmodes = config.modes\n\t\t}\n\t\tif modes&tc.mode == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\t// TODO(rfindley): once jsonrpc2 shutdown is fixed, we should not leak\n\t\t\t// goroutines in this test function.\n\t\t\t// stacktest.NoLeak(t)\n\n\t\t\tctx := context.Background()\n\t\t\tif r.Timeout != 0 {\n\t\t\t\tvar cancel context.CancelFunc\n\t\t\t\tctx, cancel = context.WithTimeout(ctx, r.Timeout)\n\t\t\t\tdefer cancel()\n\t\t\t} else if d, ok := testenv.Deadline(t); ok {\n\t\t\t\ttimeout := time.Until(d) * 19 / 20 // Leave an arbitrary 5% for cleanup.\n\t\t\t\tvar cancel context.CancelFunc\n\t\t\t\tctx, cancel = context.WithTimeout(ctx, timeout)\n\t\t\t\tdefer cancel()\n\t\t\t}\n\n\t\t\t// TODO(rfindley): do we need an instance at all? Can it be removed?\n\t\t\tctx = debug.WithInstance(ctx, \"\")\n\n\t\t\trootDir := filepath.Join(r.tempDir, filepath.FromSlash(t.Name()))\n\t\t\tif err := os.MkdirAll(rootDir, 0755); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tfiles := fake.UnpackTxt(files)\n\t\t\tif config.editor.WindowsLineEndings {\n\t\t\t\tfor name, data := range files {\n\t\t\t\t\tfiles[name] = bytes.ReplaceAll(data, []byte(\"\\n\"), []byte(\"\\r\\n\"))\n\t\t\t\t}\n\t\t\t}\n\t\t\tconfig.sandbox.Files = files\n\t\t\tconfig.sandbox.RootDir = rootDir\n\t\t\tsandbox, err := fake.NewSandbox(&config.sandbox)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer func() {\n\t\t\t\tif !r.SkipCleanup {\n\t\t\t\t\tif err := sandbox.Close(); err != nil {\n\t\t\t\t\t\tpprof.Lookup(\"goroutine\").WriteTo(os.Stderr, 1) // ignore error\n\t\t\t\t\t\tt.Errorf(\"closing the sandbox: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\t// Write the go.sum file for the requested directories, before starting the server.\n\t\t\tfor _, dir := range config.writeGoSum {\n\t\t\t\tif _, err := sandbox.RunGoCommand(context.Background(), dir, \"list\", []string{\"-mod=mod\", \"./...\"}, []string{\"GOWORK=off\"}, true); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tss := tc.getServer()\n\n\t\t\tframer := jsonrpc2.NewRawStream\n\t\t\tls := &loggingFramer{}\n\t\t\tframer = ls.framer(jsonrpc2.NewRawStream)\n\t\t\tts := servertest.NewPipeServer(ss, framer)\n\n\t\t\tenv := ConnectGoplsEnv(t, ctx, sandbox, config.editor, ts)\n\t\t\tdefer func() {\n\t\t\t\tif t.Failed() && r.PrintGoroutinesOnFailure {\n\t\t\t\t\tpprof.Lookup(\"goroutine\").WriteTo(os.Stderr, 1) // ignore error\n\t\t\t\t}\n\t\t\t\tif (t.Failed() && !config.noLogsOnError) || *printLogs {\n\t\t\t\t\tls.printBuffers(t.Name(), os.Stderr)\n\t\t\t\t}\n\t\t\t\t// For tests that failed due to a timeout, don't fail to shutdown\n\t\t\t\t// because ctx is done.\n\t\t\t\t//\n\t\t\t\t// There is little point to setting an arbitrary timeout for closing\n\t\t\t\t// the editor: in general we want to clean up before proceeding to the\n\t\t\t\t// next test, and if there is a deadlock preventing closing it will\n\t\t\t\t// eventually be handled by the `go test` timeout.\n\t\t\t\tif err := env.Editor.Close(xcontext.Detach(ctx)); err != nil {\n\t\t\t\t\tt.Errorf(\"closing editor: %v\", err)\n\t\t\t\t}\n\t\t\t}()\n\t\t\t// Always await the initial workspace load.\n\t\t\tenv.Await(InitialWorkspaceLoad)\n\t\t\ttest(t, env)\n\t\t})\n\t}\n}\n\n// ConnectGoplsEnv creates a new Gopls environment for the given sandbox,\n// editor config, and server connector.\n//\n// TODO(rfindley): significantly refactor the way testing environments are\n// constructed.\nfunc ConnectGoplsEnv(t testing.TB, ctx context.Context, sandbox *fake.Sandbox, config fake.EditorConfig, connector servertest.Connector) *Env {\n\tawaiter := NewAwaiter(sandbox.Workdir)\n\teditor, err := fake.NewEditor(sandbox, config).Connect(ctx, connector, awaiter.Hooks())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tenv := &Env{\n\t\tTB:      t,\n\t\tCtx:     ctx,\n\t\tSandbox: sandbox,\n\t\tServer:  connector,\n\t\tEditor:  editor,\n\t\tAwaiter: awaiter,\n\t}\n\treturn env\n}\n\n// longBuilders maps builders that are skipped when -short is set to a\n// (possibly empty) justification.\nvar longBuilders = map[string]string{\n\t\"x_tools-gotip-openbsd-amd64\":  \"go.dev/issue/72145\",\n\t\"x_tools-go1.24-openbsd-amd64\": \"go.dev/issue/72145\",\n\t\"x_tools-go1.23-openbsd-amd64\": \"go.dev/issue/72145\",\n\n\t\"darwin-amd64-10_12\":      \"\",\n\t\"freebsd-amd64-race\":      \"\",\n\t\"illumos-amd64\":           \"\",\n\t\"netbsd-arm-bsiegert\":     \"\",\n\t\"solaris-amd64-oraclerel\": \"\",\n\t\"windows-arm-zx2c4\":       \"\",\n\t\"linux-ppc64le-power9osu\": \"go.dev/issue/66748\",\n}\n\n// TODO(rfindley): inline into Main.\nfunc checkBuilder() string {\n\tbuilder := os.Getenv(\"GO_BUILDER_NAME\")\n\tif reason, ok := longBuilders[builder]; ok && testing.Short() {\n\t\tif reason != \"\" {\n\t\t\treturn fmt.Sprintf(\"skipping %s with -short due to %s\", builder, reason)\n\t\t} else {\n\t\t\treturn fmt.Sprintf(\"skipping %s with -short\", builder)\n\t\t}\n\t}\n\treturn \"\"\n}\n\ntype loggingFramer struct {\n\tmu  sync.Mutex\n\tbuf *safeBuffer\n}\n\n// safeBuffer is a threadsafe buffer for logs.\ntype safeBuffer struct {\n\tmu  sync.Mutex\n\tbuf bytes.Buffer\n}\n\nfunc (b *safeBuffer) Write(p []byte) (int, error) {\n\tb.mu.Lock()\n\tdefer b.mu.Unlock()\n\treturn b.buf.Write(p)\n}\n\nfunc (s *loggingFramer) framer(f jsonrpc2.Framer) jsonrpc2.Framer {\n\treturn func(nc net.Conn) jsonrpc2.Stream {\n\t\ts.mu.Lock()\n\t\tframed := false\n\t\tif s.buf == nil {\n\t\t\ts.buf = &safeBuffer{buf: bytes.Buffer{}}\n\t\t\tframed = true\n\t\t}\n\t\ts.mu.Unlock()\n\t\tstream := f(nc)\n\t\tif framed {\n\t\t\treturn protocol.LoggingStream(stream, s.buf)\n\t\t}\n\t\treturn stream\n\t}\n}\n\nfunc (s *loggingFramer) printBuffers(testname string, w io.Writer) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif s.buf == nil {\n\t\treturn\n\t}\n\tfmt.Fprintf(os.Stderr, \"#### Start Gopls Test Logs for %q\\n\", testname)\n\ts.buf.mu.Lock()\n\tio.Copy(w, &s.buf.buf)\n\ts.buf.mu.Unlock()\n\tfmt.Fprintf(os.Stderr, \"#### End Gopls Test Logs for %q\\n\", testname)\n}\n\n// defaultServer handles the Default execution mode.\nfunc (r *Runner) defaultServer() jsonrpc2.StreamServer {\n\treturn lsprpc.NewStreamServer(cache.New(r.store), false, nil)\n}\n\n// forwardedServer handles the Forwarded execution mode.\nfunc (r *Runner) forwardedServer() jsonrpc2.StreamServer {\n\tr.tsOnce.Do(func() {\n\t\tctx := context.Background()\n\t\tctx = debug.WithInstance(ctx, \"\")\n\t\tss := lsprpc.NewStreamServer(cache.New(nil), false, nil)\n\t\tr.ts = servertest.NewTCPServer(ctx, ss, nil)\n\t})\n\treturn newForwarder(\"tcp\", r.ts.Addr)\n}\n\n// runTestAsGoplsEnvvar triggers TestMain to run gopls instead of running\n// tests. It's a trick to allow tests to find a binary to use to start a gopls\n// subprocess.\nconst runTestAsGoplsEnvvar = \"_GOPLS_TEST_BINARY_RUN_AS_GOPLS\"\n\n// separateProcessServer handles the SeparateProcess execution mode.\nfunc (r *Runner) separateProcessServer() jsonrpc2.StreamServer {\n\tif runtime.GOOS != \"linux\" {\n\t\tpanic(\"separate process execution mode is only supported on linux\")\n\t}\n\n\tr.startRemoteOnce.Do(func() {\n\t\tsocketDir, err := os.MkdirTemp(r.tempDir, \"gopls-test-socket\")\n\t\tif err != nil {\n\t\t\tr.remoteErr = err\n\t\t\treturn\n\t\t}\n\t\tr.remoteSocket = filepath.Join(socketDir, \"gopls-test-daemon\")\n\n\t\t// The server should be killed by when the test runner exits, but to be\n\t\t// conservative also set a listen timeout.\n\t\targs := []string{\"serve\", \"-listen\", \"unix;\" + r.remoteSocket, \"-listen.timeout\", \"1m\"}\n\n\t\tctx, cancel := context.WithCancel(context.Background())\n\t\tcmd := exec.CommandContext(ctx, r.goplsPath, args...)\n\t\tcmd.Env = append(os.Environ(), runTestAsGoplsEnvvar+\"=true\")\n\n\t\t// Start the external gopls process. This is still somewhat racy, as we\n\t\t// don't know when gopls binds to the socket, but the gopls forwarder\n\t\t// client has built-in retry behavior that should mostly mitigate this\n\t\t// problem (and if it doesn't, we probably want to improve the retry\n\t\t// behavior).\n\t\tif err := cmd.Start(); err != nil {\n\t\t\tcancel()\n\t\t\tr.remoteSocket = \"\"\n\t\t\tr.remoteErr = err\n\t\t} else {\n\t\t\tr.cancelRemote = cancel\n\t\t\t// Spin off a goroutine to wait, so that we free up resources when the\n\t\t\t// server exits.\n\t\t\tgo cmd.Wait()\n\t\t}\n\t})\n\n\treturn newForwarder(\"unix\", r.remoteSocket)\n}\n\nfunc newForwarder(network, address string) jsonrpc2.StreamServer {\n\tserver, err := lsprpc.NewForwarder(network+\";\"+address, nil)\n\tif err != nil {\n\t\t// This should never happen, as we are passing an explicit address.\n\t\tpanic(fmt.Sprintf(\"internal error: unable to create forwarder: %v\", err))\n\t}\n\treturn server\n}\n\n// Close cleans up resource that have been allocated to this workspace.\nfunc (r *Runner) Close() error {\n\tvar errmsgs []string\n\tif r.ts != nil {\n\t\tif err := r.ts.Close(); err != nil {\n\t\t\terrmsgs = append(errmsgs, err.Error())\n\t\t}\n\t}\n\tif r.cancelRemote != nil {\n\t\tr.cancelRemote()\n\t}\n\tif !r.SkipCleanup {\n\t\tif err := os.RemoveAll(r.tempDir); err != nil {\n\t\t\terrmsgs = append(errmsgs, err.Error())\n\t\t}\n\t}\n\tif len(errmsgs) > 0 {\n\t\treturn fmt.Errorf(\"errors closing the test runner:\\n\\t%s\", strings.Join(errmsgs, \"\\n\\t\"))\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/template/template_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage template\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nfunc TestMultilineTokens(t *testing.T) {\n\t// 51731: panic: runtime error: slice bounds out of range [38:3]\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n-- hi.tmpl --\n{{if (foÜx .X.Y)}}😀{{$A := \n\t\"hi\"\n\t}}{{.Z $A}}{{else}}\n{{$A.X 12}}\n{{foo (.X.Y) 23 ($A.Z)}}\n{{end}}\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"templateExtensions\": []string{\"tmpl\"},\n\t\t\t\"semanticTokens\":     true,\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tvar p protocol.SemanticTokensParams\n\t\tp.TextDocument.URI = env.Sandbox.Workdir.URI(\"hi.tmpl\")\n\t\ttoks, err := env.Editor.Server.SemanticTokensFull(env.Ctx, &p)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"semantic token failed: %v\", err)\n\t\t}\n\t\tif toks == nil || len(toks.Data) == 0 {\n\t\t\tt.Errorf(\"got no semantic tokens\")\n\t\t}\n\t})\n}\n\nfunc TestMultilineTokensAgain(t *testing.T) {\n\t// Regression tests for a crash; see go.dev/issue/74635.\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n-- hi.tmpl --\n{{/* this is\na comment */}}\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"templateExtensions\": []string{\"tmpl\"},\n\t\t\t\"semanticTokens\":     true,\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tvar p protocol.SemanticTokensParams\n\t\tp.TextDocument.URI = env.Sandbox.Workdir.URI(\"hi.tmpl\")\n\t\ttoks, err := env.Editor.Server.SemanticTokensFull(env.Ctx, &p)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"semantic token failed: %v\", err)\n\t\t}\n\t\tif toks == nil || len(toks.Data) == 0 {\n\t\t\tt.Errorf(\"got no semantic tokens\")\n\t\t}\n\t})\n}\n\nfunc TestTemplatesFromExtensions(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- hello.tmpl --\n{{range .Planets}}\nHello {{}} <-- missing body\n{{end}}\n`\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"templateExtensions\": []string{\"tmpl\"},\n\t\t\t\"semanticTokens\":     true,\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t// TODO: can we move this diagnostic onto {{}}?\n\t\tvar diags protocol.PublishDiagnosticsParams\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"hello.tmpl\", \"()Hello {{}}\")),\n\t\t\tReadDiagnostics(\"hello.tmpl\", &diags),\n\t\t)\n\t\td := diags.Diagnostics // issue 50786: check for Source\n\t\tif len(d) != 1 {\n\t\t\tt.Errorf(\"expected 1 diagnostic, got %d\", len(d))\n\t\t\treturn\n\t\t}\n\t\tif d[0].Source != \"template\" {\n\t\t\tt.Errorf(\"expected Source 'template', got %q\", d[0].Source)\n\t\t}\n\t\t// issue 50801 (even broken templates could return some semantic tokens)\n\t\tvar p protocol.SemanticTokensParams\n\t\tp.TextDocument.URI = env.Sandbox.Workdir.URI(\"hello.tmpl\")\n\t\ttoks, err := env.Editor.Server.SemanticTokensFull(env.Ctx, &p)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"semantic token failed: %v\", err)\n\t\t}\n\t\tif toks == nil || len(toks.Data) == 0 {\n\t\t\tt.Errorf(\"got no semantic tokens\")\n\t\t}\n\n\t\tenv.WriteWorkspaceFile(\"hello.tmpl\", \"{{range .Planets}}\\nHello {{.}}\\n{{end}}\")\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"hello.tmpl\")))\n\t})\n}\n\nfunc TestTemplatesObserveDirectoryFilters(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.tmpl --\nA {{}} <-- missing body\n-- b/b.tmpl --\nB {{}} <-- missing body\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"directoryFilters\":   []string{\"-b\"},\n\t\t\t\"templateExtensions\": []string{\"tmpl\"},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.tmpl\", \"()A\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.tmpl\")),\n\t\t)\n\t})\n}\n\nfunc TestTemplatesFromLangID(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"hello.tmpl\", \"\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"hello.tmpl\")), // Don't get spurious errors for empty templates.\n\t\t)\n\t\tenv.SetBufferContent(\"hello.tmpl\", \"{{range .Planets}}\\nHello {{}}\\n{{end}}\")\n\t\tenv.Await(Diagnostics(env.AtRegexp(\"hello.tmpl\", \"()Hello {{}}\")))\n\t\tenv.RegexpReplace(\"hello.tmpl\", \"{{}}\", \"{{.}}\")\n\t\tenv.Await(NoDiagnostics(ForFile(\"hello.tmpl\")))\n\t})\n}\n\nfunc TestClosingTemplatesMakesDiagnosticsDisappear(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- hello.tmpl --\n{{range .Planets}}\nHello {{}} <-- missing body\n{{end}}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"hello.tmpl\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"hello.tmpl\", \"()Hello {{}}\")),\n\t\t)\n\t\t// Since we don't have templateExtensions configured, closing hello.tmpl\n\t\t// should make its diagnostics disappear.\n\t\tenv.CloseBuffer(\"hello.tmpl\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"hello.tmpl\")),\n\t\t)\n\t})\n}\n\nfunc TestMultipleSuffixes(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- b.gotmpl --\n{{define \"A\"}}goo{{end}}\n-- a.tmpl --\n{{template \"A\"}}\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"templateExtensions\": []string{\"tmpl\", \"gotmpl\"},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.tmpl\")\n\t\tx := env.RegexpSearch(\"a.tmpl\", `()A`)\n\t\tloc := env.FirstDefinition(x)\n\t\tenv.OpenFile(env.Sandbox.Workdir.URIToPath(loc.URI))\n\t\trefs := env.References(loc)\n\t\tif len(refs) != 2 {\n\t\t\tt.Fatalf(\"got %v reference(s), want 2\", len(refs))\n\t\t}\n\t\t// make sure we got one from b.gotmpl\n\t\twant := env.Sandbox.Workdir.URI(\"b.gotmpl\")\n\t\tif refs[0].URI != want && refs[1].URI != want {\n\t\t\tt.Errorf(\"failed to find reference to %s\", shorten(want))\n\t\t\tfor i, r := range refs {\n\t\t\t\tt.Logf(\"%d: URI:%s %v\", i, shorten(r.URI), r.Range)\n\t\t\t}\n\t\t}\n\n\t\tcontent, nloc := env.Hover(loc)\n\t\tif loc != nloc {\n\t\t\tt.Errorf(\"loc? got %v, wanted %v\", nloc, loc)\n\t\t}\n\t\tif content.Value != \"template A defined\" {\n\t\t\tt.Errorf(\"got %s, wanted 'template A defined\", content.Value)\n\t\t}\n\t})\n}\n\n// shorten long URIs\nfunc shorten(fn protocol.DocumentURI) string {\n\tif len(fn) <= 20 {\n\t\treturn string(fn)\n\t}\n\tpieces := strings.Split(string(fn), \"/\")\n\tif len(pieces) < 2 {\n\t\treturn string(fn)\n\t}\n\tj := len(pieces)\n\treturn pieces[j-2] + \"/\" + pieces[j-1]\n}\n\nfunc TestCompletionPanic_Issue57621(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- hello.tmpl --\n{{range .Planets}}\nHello {{\n{{end}}\n`\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"hello.tmpl\")\n\t\t// None of these should panic.\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Hello ()\\{\\{`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Hello \\{()\\{`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Hello \\{\\{()`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `()\\{\\{range`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `\\{()\\{range`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `\\{\\{()range`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Planets()}}`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Planets}()}`))\n\t\tenv.Completion(env.RegexpSearch(\"hello.tmpl\", `Planets}}()`))\n\t})\n}\n\n// Hover needs tests\n"
  },
  {
    "path": "gopls/internal/test/integration/watch/setting_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage watch\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestSubdirWatchPatterns(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n-- subdir/subdir.go --\npackage subdir\n`\n\n\ttests := []struct {\n\t\tclientName          string\n\t\tsubdirWatchPatterns string\n\t\twantWatched         bool\n\t}{\n\t\t{\"other client\", \"on\", true},\n\t\t{\"other client\", \"off\", false},\n\t\t{\"other client\", \"auto\", false},\n\t\t{\"Visual Studio Code\", \"auto\", true},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"%s_%s\", test.clientName, test.subdirWatchPatterns), func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tClientName(test.clientName),\n\t\t\t\tSettings{\n\t\t\t\t\t\"subdirWatchPatterns\": test.subdirWatchPatterns,\n\t\t\t\t},\n\t\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tvar expectation Expectation\n\t\t\t\tif test.wantWatched {\n\t\t\t\t\texpectation = FileWatchMatching(\"subdir\")\n\t\t\t\t} else {\n\t\t\t\t\texpectation = NoFileWatchMatching(\"subdir\")\n\t\t\t\t}\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\t\texpectation,\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// This test checks that we surface errors for invalid subdir watch patterns,\n// as the triple of (\"off\"|\"on\"|\"auto\") may be confusing to users inclined to\n// use (true|false) or some other truthy value.\nfunc TestSubdirWatchPatterns_BadValues(t *testing.T) {\n\ttests := []struct {\n\t\tbadValue    any\n\t\twantMessage string\n\t}{\n\t\t{true, \"invalid type bool (want string)\"},\n\t\t{false, \"invalid type bool (want string)\"},\n\t\t{\"yes\", `invalid option \"yes\"`},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprint(test.badValue), func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tSettings{\n\t\t\t\t\t\"subdirWatchPatterns\": test.badValue,\n\t\t\t\t},\n\t\t\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\t\t\tenv.OnceMet(\n\t\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\t\tShownMessage(test.wantMessage),\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/watch/watch_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage watch\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nfunc TestEditFile(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- a/a.go --\npackage a\n\nfunc _() {\n\tvar x int\n}\n`\n\t// Edit the file when it's *not open* in the workspace, and check that\n\t// diagnostics are updated.\n\tt.Run(\"unopened\", func(t *testing.T) {\n\t\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t\t)\n\t\t\tenv.WriteWorkspaceFile(\"a/a.go\", `package a; func _() {};`)\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t})\n\t})\n\n\t// Edit the file when it *is open* in the workspace, and check that\n\t// diagnostics are *not* updated.\n\tt.Run(\"opened\", func(t *testing.T) {\n\t\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\t// Insert a trivial edit so that we don't automatically update the buffer\n\t\t\t// (see CL 267577).\n\t\t\tenv.EditBuffer(\"a/a.go\", fake.NewEdit(0, 0, 0, 0, \" \"))\n\t\t\tenv.AfterChange()\n\t\t\tenv.WriteWorkspaceFile(\"a/a.go\", `package a; func _() {};`)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t\t)\n\t\t})\n\t})\n}\n\n// Edit a dependency on disk and expect a new diagnostic.\nfunc TestEditDependency(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- b/b.go --\npackage b\n\nfunc B() int { return 0 }\n-- a/a.go --\npackage a\n\nimport (\n\t\"mod.com/b\"\n)\n\nfunc _() {\n\t_ = b.B()\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange()\n\t\tenv.WriteWorkspaceFile(\"b/b.go\", `package b; func B() {};`)\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"b.B\")),\n\t\t)\n\t})\n}\n\n// Edit both the current file and one of its dependencies on disk and\n// expect diagnostic changes.\nfunc TestEditFileAndDependency(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- b/b.go --\npackage b\n\nfunc B() int { return 0 }\n-- a/a.go --\npackage a\n\nimport (\n\t\"mod.com/b\"\n)\n\nfunc _() {\n\tvar x int\n\t_ = b.B()\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t)\n\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\"b/b.go\": `package b; func B() {};`,\n\t\t\t\"a/a.go\": `package a\n\nimport \"mod.com/b\"\n\nfunc _() {\n\tb.B()\n}`,\n\t\t})\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t)\n\t})\n}\n\n// Delete a dependency and expect a new diagnostic.\nfunc TestDeleteDependency(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- b/b.go --\npackage b\n\nfunc B() int { return 0 }\n-- a/a.go --\npackage a\n\nimport (\n\t\"mod.com/b\"\n)\n\nfunc _() {\n\t_ = b.B()\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange()\n\t\tenv.RemoveWorkspaceFile(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"\\\"mod.com/b\\\"\")),\n\t\t)\n\t})\n}\n\n// Create a dependency on disk and expect the diagnostic to go away.\nfunc TestCreateDependency(t *testing.T) {\n\tconst missing = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- b/b.go --\npackage b\n\nfunc B() int { return 0 }\n-- a/a.go --\npackage a\n\nimport (\n\t\"mod.com/c\"\n)\n\nfunc _() {\n\tc.C()\n}\n`\n\tRun(t, missing, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"\\\"mod.com/c\\\"\")),\n\t\t)\n\t\tenv.WriteWorkspaceFile(\"c/c.go\", `package c; func C() {};`)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t})\n}\n\n// Create a new dependency and add it to the file on disk.\n// This is similar to what might happen if you switch branches.\nfunc TestCreateAndAddDependency(t *testing.T) {\n\tconst original = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- a/a.go --\npackage a\n\nfunc _() {}\n`\n\tRun(t, original, func(t *testing.T, env *Env) {\n\t\tenv.WriteWorkspaceFile(\"c/c.go\", `package c; func C() {};`)\n\t\tenv.WriteWorkspaceFile(\"a/a.go\", `package a; import \"mod.com/c\"; func _() { c.C() }`)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t})\n}\n\n// Create a new file that defines a new symbol, in the same package.\nfunc TestCreateFile(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- a/a.go --\npackage a\n\nfunc _() {\n\thello()\n}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"hello\")),\n\t\t)\n\t\tenv.WriteWorkspaceFile(\"a/a2.go\", `package a; func hello() {};`)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t)\n\t})\n}\n\n// Add a new method to an interface and implement it.\n// Inspired by the structure of internal/golang and internal/cache.\nfunc TestCreateImplementation(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- b/b.go --\npackage b\n\ntype B interface{\n\tHello() string\n}\n\nfunc SayHello(bee B) {\n\tprintln(bee.Hello())\n}\n-- a/a.go --\npackage a\n\nimport \"mod.com/b\"\n\ntype X struct {}\n\nfunc (_ X) Hello() string {\n\treturn \"\"\n}\n\nfunc _() {\n\tx := X{}\n\tb.SayHello(x)\n}\n`\n\tconst newMethod = `package b\ntype B interface{\n\tHello() string\n\tBye() string\n}\n\nfunc SayHello(bee B) {\n\tprintln(bee.Hello())\n}`\n\tconst implementation = `package a\n\nimport \"mod.com/b\"\n\ntype X struct {}\n\nfunc (_ X) Hello() string {\n\treturn \"\"\n}\n\nfunc (_ X) Bye() string {\n\treturn \"\"\n}\n\nfunc _() {\n\tx := X{}\n\tb.SayHello(x)\n}`\n\n\t// Add the new method before the implementation. Expect diagnostics.\n\tt.Run(\"method before implementation\", func(t *testing.T) {\n\t\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.WriteWorkspaceFile(\"b/b.go\", newMethod)\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(AtPosition(\"a/a.go\", 12, 12)),\n\t\t\t)\n\t\t\tenv.WriteWorkspaceFile(\"a/a.go\", implementation)\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t})\n\t})\n\t// Add the new implementation before the new method. Expect no diagnostics.\n\tt.Run(\"implementation before method\", func(t *testing.T) {\n\t\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.WriteWorkspaceFile(\"a/a.go\", implementation)\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t\tenv.WriteWorkspaceFile(\"b/b.go\", newMethod)\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t})\n\t})\n\t// Add both simultaneously. Expect no diagnostics.\n\tt.Run(\"implementation and method simultaneously\", func(t *testing.T) {\n\t\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\t\"a/a.go\": implementation,\n\t\t\t\t\"b/b.go\": newMethod,\n\t\t\t})\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\t)\n\t\t})\n\t})\n}\n\n// Tests golang/go#38498. Delete a file and then force a reload.\n// Assert that we no longer try to load the file.\nfunc TestDeleteFiles(t *testing.T) {\n\t// TODO(rfindley): this test is brittle, because it depends on underspecified\n\t// logging behavior around loads.\n\t//\n\t// We should have a robust way to test loads. It should be possible to assert\n\t// on the specific loads that have occurred, and without the synchronization\n\t// problems associated with logging.\n\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- a/a.go --\npackage a\n\nfunc _() {\n\tvar _ int\n}\n-- a/a_unneeded.go --\npackage a\n`\n\tt.Run(\"close then delete\", func(t *testing.T) {\n\t\tWithOptions(\n\t\t\t// verboseOutput causes Snapshot.load to log package files.\n\t\t\t// (see the TODO above: this is brittle)\n\t\t\tSettings{\"verboseOutput\": true},\n\t\t).Run(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\tenv.OpenFile(\"a/a_unneeded.go\")\n\t\t\tenv.Await(\n\t\t\t\t// Log messages are asynchronous to other events on the LSP stream, so we\n\t\t\t\t// can't use OnceMet or AfterChange here.\n\t\t\t\tLogMatching(protocol.Info, \"a_unneeded.go\", 1, false),\n\t\t\t)\n\n\t\t\t// Close and delete the open file, mimicking what an editor would do.\n\t\t\tenv.CloseBuffer(\"a/a_unneeded.go\")\n\t\t\tenv.RemoveWorkspaceFile(\"a/a_unneeded.go\")\n\t\t\tenv.RegexpReplace(\"a/a.go\", \"var _ int\", \"fmt.Println(\\\"\\\")\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"fmt\")),\n\t\t\t)\n\t\t\tenv.SaveBuffer(\"a/a.go\")\n\t\t\tenv.Await(\n\t\t\t\t// There should only be one log message containing\n\t\t\t\t// a_unneeded.go, from the initial workspace load, which we\n\t\t\t\t// check for earlier. If there are more, there's a bug.\n\t\t\t\tLogMatching(protocol.Info, \"a_unneeded.go\", 1, false),\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t})\n\t})\n\n\tt.Run(\"delete then close\", func(t *testing.T) {\n\t\tWithOptions(\n\t\t\tSettings{\"verboseOutput\": true},\n\t\t).Run(t, pkg, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\tenv.OpenFile(\"a/a_unneeded.go\")\n\t\t\tenv.Await(\n\t\t\t\tLogMatching(protocol.Info, \"a_unneeded.go\", 1, false),\n\t\t\t)\n\n\t\t\t// Delete and then close the file.\n\t\t\tenv.RemoveWorkspaceFile(\"a/a_unneeded.go\")\n\t\t\tenv.CloseBuffer(\"a/a_unneeded.go\")\n\t\t\tenv.RegexpReplace(\"a/a.go\", \"var _ int\", \"fmt.Println(\\\"\\\")\")\n\t\t\tenv.AfterChange(\n\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"fmt\")),\n\t\t\t)\n\t\t\tenv.SaveBuffer(\"a/a.go\")\n\t\t\tenv.Await(\n\t\t\t\t// There should only be one log message containing\n\t\t\t\t// a_unneeded.go, from the initial workspace load, which we\n\t\t\t\t// check for earlier. If there are more, there's a bug.\n\t\t\t\tLogMatching(protocol.Info, \"a_unneeded.go\", 1, false),\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t)\n\t\t})\n\t})\n}\n\n// This change reproduces the behavior of switching branches, with multiple\n// files being created and deleted. The key change here is the movement of a\n// symbol from one file to another in a given package through a deletion and\n// creation. To reproduce an issue with metadata invalidation in batched\n// changes, the last change in the batch is an on-disk file change that doesn't\n// require metadata invalidation.\nfunc TestMoveSymbol(t *testing.T) {\n\tconst pkg = `\n-- go.mod --\nmodule mod.com\n\ngo 1.14\n-- main.go --\npackage main\n\nimport \"mod.com/a\"\n\nfunc main() {\n\tvar x int\n\tx = a.Hello\n\tprintln(x)\n}\n-- a/a1.go --\npackage a\n\nvar Hello int\n-- a/a2.go --\npackage a\n\nfunc _() {}\n`\n\tRun(t, pkg, func(t *testing.T, env *Env) {\n\t\tenv.WriteWorkspaceFile(\"a/a3.go\", \"package a\\n\\nvar Hello int\\n\")\n\t\tenv.RemoveWorkspaceFile(\"a/a1.go\")\n\t\tenv.WriteWorkspaceFile(\"a/a2.go\", \"package a; func _() {};\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// Reproduce golang/go#40456.\nfunc TestChangeVersion(t *testing.T) {\n\tconst proxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n\nfunc X(x int) {}\n-- example.com@v1.2.2/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.2/blah/blah.go --\npackage blah\n\nconst Name = \"Blah\"\n\nfunc X() {}\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/blah/blah.go --\npackage hello\n\nconst Name = \"Hello\"\n`\n\tconst mod = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\nrequire example.com v1.2.2\n-- main.go --\npackage main\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tblah.X()\n}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy)).Run(t, mod, func(t *testing.T, env *Env) {\n\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\"go.mod\": `module mod.com\n\ngo 1.12\n\nrequire example.com v1.2.3\n`,\n\t\t\t\"main.go\": `package main\n\nimport (\n\t\"example.com/blah\"\n)\n\nfunc main() {\n\tblah.X(1)\n}\n`,\n\t\t})\n\t\tenv.AfterChange(\n\t\t\tenv.DoneWithChangeWatchedFiles(),\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// Reproduces golang/go#40340.\nfunc TestSwitchFromGOPATHToModuleMode(t *testing.T) {\n\tconst files = `\n-- foo/blah/blah.go --\npackage blah\n\nconst Name = \"\"\n-- main.go --\npackage main\n\nimport \"foo/blah\"\n\nfunc main() {\n\t_ = blah.Name\n}\n`\n\tWithOptions(\n\t\tInGOPATH(),\n\t\tModes(Default), // golang/go#57521: this test is temporarily failing in 'experimental' mode\n\t\tEnvVars{\"GO111MODULE\": \"auto\"},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t\tif _, err := env.Sandbox.RunGoCommand(env.Ctx, \"\", \"mod\", []string{\"init\", \"mod.com\"}, nil, true); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// TODO(golang/go#57558, golang/go#57512): file watching is asynchronous,\n\t\t// and we must wait for the view to be reconstructed before touching\n\t\t// main.go, so that the new view \"knows\" about main.go. This is a bug, but\n\t\t// awaiting the change here avoids it.\n\t\tenv.AfterChange()\n\n\t\tenv.RegexpReplace(\"main.go\", `\"foo/blah\"`, `\"mod.com/foo/blah\"`)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t)\n\t})\n}\n\n// Reproduces golang/go#40487.\nfunc TestSwitchFromModulesToGOPATH(t *testing.T) {\n\tconst files = `\n-- foo/go.mod --\nmodule mod.com\n\ngo 1.14\n-- foo/blah/blah.go --\npackage blah\n\nconst Name = \"\"\n-- foo/main.go --\npackage main\n\nimport \"mod.com/blah\"\n\nfunc main() {\n\t_ = blah.Name\n}\n`\n\tWithOptions(\n\t\tInGOPATH(),\n\t\tEnvVars{\"GO111MODULE\": \"auto\"},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/main.go\")\n\t\tenv.RemoveWorkspaceFile(\"foo/go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"foo/main.go\", `\"mod.com/blah\"`)),\n\t\t)\n\t\tenv.RegexpReplace(\"foo/main.go\", `\"mod.com/blah\"`, `\"foo/blah\"`)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"foo/main.go\")),\n\t\t)\n\t})\n}\n\nfunc TestNewSymbolInTestVariant(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nfunc bob() {}\n-- a/a_test.go --\npackage a\n\nimport \"testing\"\n\nfunc TestBob(t *testing.T) {\n\tbob()\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t// Add a new symbol to the package under test and use it in the test\n\t\t// variant. Expect no diagnostics.\n\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\"a/a.go\": `package a\n\nfunc bob() {}\nfunc george() {}\n`,\n\t\t\t\"a/a_test.go\": `package a\n\nimport \"testing\"\n\nfunc TestAll(t *testing.T) {\n\tbob()\n\tgeorge()\n}\n`,\n\t\t})\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\tNoDiagnostics(ForFile(\"a/a_test.go\")),\n\t\t)\n\t\t// Now, add a new file to the test variant and use its symbol in the\n\t\t// original test file. Expect no diagnostics.\n\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\"a/a_test.go\": `package a\n\nimport \"testing\"\n\nfunc TestAll(t *testing.T) {\n\tbob()\n\tgeorge()\n\thi()\n}\n`,\n\t\t\t\"a/a2_test.go\": `package a\n\nimport \"testing\"\n\nfunc hi() {}\n\nfunc TestSomething(t *testing.T) {}\n`,\n\t\t})\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/a_test.go\")),\n\t\t\tNoDiagnostics(ForFile(\"a/a2_test.go\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/assembly_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\nimport (\n\t\"regexp\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestAssembly is a basic test of the web-based assembly listing.\nfunc TestAssembly(t *testing.T) {\n\ttestenv.NeedsGoCommand1Point(t, 22) // for up-to-date assembly listing\n\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nfunc f(x int) int {\n\tprintln(\"hello\")\n\tdefer println(\"world\")\n\treturn x\n}\n\nfunc g() {\n\tprintln(\"goodbye\")\n}\n\nvar v = [...]int{\n\tf(123),\n\tf(456),\n}\n\nfunc init() {\n\tf(789)\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\t// Get the report and do some minimal checks for sensible results.\n\t\t//\n\t\t// Use only portable instructions below! Remember that\n\t\t// this is a test of plumbing, not compilation, so\n\t\t// it's better to skip the tests, rather than refine\n\t\t// them, on any architecture that gives us trouble\n\t\t// (e.g. uses JAL for CALL, or BL<cc> for RET).\n\t\t// We conservatively test only on the two most popular\n\t\t// architectures.\n\t\t{\n\t\t\tloc := env.RegexpSearch(\"a/a.go\", \"println\")\n\t\t\treport := asmFor(t, env, loc)\n\t\t\tcheckMatch(t, true, report, `TEXT.*example.com/a.f`)\n\t\t\tswitch runtime.GOARCH {\n\t\t\tcase \"amd64\", \"arm64\":\n\t\t\t\tcheckMatch(t, true, report, `CALL\truntime.printlock`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\truntime.printstring`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\truntime.printunlock`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\texample.com/a.f.deferwrap`)\n\t\t\t\tcheckMatch(t, true, report, `RET`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\truntime.morestack_noctxt`)\n\t\t\t}\n\n\t\t\t// Nested functions are also shown.\n\t\t\t//\n\t\t\t// The condition here was relaxed to unblock go.dev/cl/639515.\n\t\t\tcheckMatch(t, true, report, `example.com/a.f.deferwrap`)\n\n\t\t\t// But other functions are not.\n\t\t\tcheckMatch(t, false, report, `TEXT.*example.com/a.g`)\n\t\t}\n\n\t\t// Check that code in a package-level var initializer is found too.\n\t\t{\n\t\t\tloc := env.RegexpSearch(\"a/a.go\", `f\\(123\\)`)\n\t\t\treport := asmFor(t, env, loc)\n\t\t\tswitch runtime.GOARCH {\n\t\t\tcase \"amd64\", \"arm64\":\n\t\t\t\tcheckMatch(t, true, report, `TEXT.*example.com/a.init`)\n\t\t\t\tcheckMatch(t, true, report, `MOV.?\t\\$123`)\n\t\t\t\tcheckMatch(t, true, report, `MOV.?\t\\$456`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\texample.com/a.f`)\n\t\t\t}\n\t\t}\n\n\t\t// And code in a source-level init function.\n\t\t{\n\t\t\tloc := env.RegexpSearch(\"a/a.go\", `f\\(789\\)`)\n\t\t\treport := asmFor(t, env, loc)\n\t\t\tswitch runtime.GOARCH {\n\t\t\tcase \"amd64\", \"arm64\":\n\t\t\t\tcheckMatch(t, true, report, `TEXT.*example.com/a.init`)\n\t\t\t\tcheckMatch(t, true, report, `MOV.?\t\\$789`)\n\t\t\t\tcheckMatch(t, true, report, `CALL\texample.com/a.f`)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// TestTestAssembly exercises assembly listing of tests.\nfunc TestTestAssembly(t *testing.T) {\n\ttestenv.NeedsGoCommand1Point(t, 22) // for up-to-date assembly listing\n\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a_test.go --\npackage a\n\nimport \"testing\"\n\nfunc Test1(*testing.T) { println(0) }\n\n-- a/a_x_test.go --\npackage a_test\n\nimport \"testing\"\n\nfunc Test2(*testing.T) { println(0) }\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tfor _, test := range []struct {\n\t\t\tfilename, symbol string\n\t\t}{\n\t\t\t{\"a/a_test.go\", \"example.com/a.Test1\"},\n\t\t\t{\"a/a_x_test.go\", \"example.com/a_test.Test2\"},\n\t\t} {\n\t\t\tenv.OpenFile(test.filename)\n\t\t\tloc := env.RegexpSearch(test.filename, `println`)\n\t\t\treport := asmFor(t, env, loc)\n\t\t\tcheckMatch(t, true, report, `TEXT.*`+regexp.QuoteMeta(test.symbol))\n\t\t\tswitch runtime.GOARCH {\n\t\t\tcase \"amd64\", \"arm64\":\n\t\t\t\tcheckMatch(t, true, report, `CALL\truntime.printint`)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// asmFor returns the HTML document served by gopls for a \"Browse assembly\"\n// command at the specified location in an open file.\nfunc asmFor(t *testing.T, env *Env, loc protocol.Location) []byte {\n\t_, content := codeActionWebPage(t, env, settings.GoAssembly, loc)\n\treturn content\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/flight_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\nimport (\n\t\"encoding/json\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestFlightRecorder checks that the flight recorder is minimally functional.\nfunc TestFlightRecorder(t *testing.T) {\n\t// The usual UNIX mechanisms cause timely termination of the\n\t// cmd/trace process, but this doesn't happen on Windows,\n\t// leading to CI failures because of process->file locking.\n\t// Rather than invent a complex mechanism, skip the test:\n\t// this feature is only for gopls developers anyway.\n\t// Better long term solutions are CL 677262 and issue #66843.\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"not reliable on windows\")\n\t}\n\n\t// This is a global hammer; it won't play nicely with\n\t// multiple concurrent tests of Flight Recorder.\n\tt.Cleanup(debug.KillTraceViewers)\n\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nconst A = 1\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\t// Start the debug server.\n\t\tvar result command.DebuggingResult\n\t\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.StartDebugging.String(),\n\t\t\tArguments: []json.RawMessage{json.RawMessage(\"{}\")}, // no args -> pick port\n\t\t}, &result)\n\t\turi := result.URLs[0]\n\t\tt.Logf(\"StartDebugging: URLs[0] = %s\", uri)\n\n\t\t// Check the debug server page is sensible.\n\t\tdoc1 := get(t, uri)\n\t\tcheckMatch(t, true, doc1, \"Gopls server information\")\n\t\tcheckMatch(t, true, doc1, `<a href=\"/flightrecorder\">Flight recorder</a>`)\n\n\t\t// \"Click\" the Flight Recorder link.\n\t\t// It should redirect to the web server\n\t\t// of a \"go tool trace\" process.\n\t\t// The resulting web page is entirely programmatic,\n\t\t// so we check for an arbitrary expected symbol.\n\t\tdoc2 := get(t, uri+\"/flightrecorder\")\n\t\tcheckMatch(t, true, doc2, `onTraceViewerImportFail`)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/freesymbols_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestFreeSymbols is a basic test of interaction with the \"free symbols\" web report.\nfunc TestFreeSymbols(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nimport \"fmt\"\nimport \"bytes\"\n\nfunc f(buf bytes.Buffer, greeting string) {\n/* « */\n\tfmt.Fprintf(&buf, \"%s\", greeting)\n\tbuf.WriteString(fmt.Sprint(\"foo\"))\n\tbuf.WriteByte(0)\n/* » */\n\tbuf.Write(nil)\n}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\t// Invoke the \"Browse free symbols\" code\n\t\t// action to start the server.\n\t\tloc := env.RegexpSearch(\"a/a.go\", \"«((?:.|\\n)*)»\")\n\t\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"CodeAction: %v\", err)\n\t\t}\n\t\taction, err := CodeActionByKind(actions, settings.GoFreeSymbols)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Execute the command.\n\t\t// Its side effect should be a single showDocument request.\n\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   action.Command.Command,\n\t\t\tArguments: action.Command.Arguments,\n\t\t}\n\t\tvar result command.DebuggingResult\n\t\tcollectDocs := env.Awaiter.ListenToShownDocuments()\n\t\tenv.ExecuteCommand(params, &result)\n\t\tdoc := shownDocument(t, collectDocs(), \"http:\")\n\t\tif doc == nil {\n\t\t\tt.Fatalf(\"no showDocument call had 'file:' prefix\")\n\t\t}\n\t\tt.Log(\"showDocument(package doc) URL:\", doc.URI)\n\n\t\t// Get the report and do some minimal checks for sensible results.\n\t\treport := get(t, doc.URI)\n\t\tcheckMatch(t, true, report, `<li>import \"<a .*'>fmt</a>\" // for Fprintf, Sprint</li>`)\n\t\tcheckMatch(t, true, report, `<li>var <a .*>buf</a>  bytes.Buffer</li>`)\n\t\tcheckMatch(t, true, report, `<li>func <a .*>WriteByte</a>  func\\(c byte\\) error</li>`)\n\t\tcheckMatch(t, true, report, `<li>func <a .*>WriteString</a>  func\\(s string\\) \\(n int, err error\\)</li>`)\n\t\tcheckMatch(t, false, report, `<li>func <a .*>Write</a>`) // not in selection\n\t\tcheckMatch(t, true, report, `<li>var <a .*>greeting</a>  string</li>`)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/pkdoc_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\nimport (\n\t\"fmt\"\n\t\"html\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TODO(adonovan): define marker test verbs for checking package docs.\n\n// TestBrowsePkgDoc provides basic coverage of the \"Browse package\n// documentation\", which creates a web server on demand.\nfunc TestBrowsePkgDoc(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nconst A = 1\n\ntype G[T any] int\nfunc (G[T]) F(int, int, int, int, int, int, int, ...int) {}\n\n// EOF\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t// Assert that the HTML page contains the expected const declaration.\n\t\t// (We may need to make allowances for HTML markup.)\n\t\tenv.OpenFile(\"a/a.go\")\n\t\turi1 := viewPkgDoc(t, env, env.Sandbox.Workdir.EntireFile(\"a/a.go\"))\n\t\tdoc1 := get(t, uri1)\n\t\tcheckMatch(t, true, doc1, \"const A =.*1\")\n\n\t\t// Regression test for signature truncation (#67287, #67294).\n\t\tcheckMatch(t, true, doc1, regexp.QuoteMeta(\"func (G[T]) F(int, int, int, ...)\"))\n\n\t\t// Check that edits to the buffer (even unsaved) are\n\t\t// reflected in the HTML document.\n\t\tenv.RegexpReplace(\"a/a.go\", \"// EOF\", \"func NewFunc() {}\")\n\t\tenv.Await(env.DoneDiagnosingChanges())\n\t\tdoc2 := get(t, uri1)\n\t\tcheckMatch(t, true, doc2, \"func NewFunc\")\n\n\t\t// TODO(adonovan): assert some basic properties of the\n\t\t// HTML document using something like\n\t\t// golang.org/x/pkgsite/internal/testing/htmlcheck.\n\n\t\t// Grab the URL in the HTML source link for NewFunc.\n\t\t// (We don't have a DOM or JS interpreter so we have\n\t\t// to know something of the document internals here.)\n\t\trx := regexp.MustCompile(`<h3 id='NewFunc'.*httpGET\\(\"(.*)\"\\)`)\n\t\tsrcURL := html.UnescapeString(string(rx.FindSubmatch(doc2)[1]))\n\n\t\t// Fetch the document. Its result isn't important,\n\t\t// but it must have the side effect of another showDocument\n\t\t// downcall, this time for a \"file:\" URL, causing the\n\t\t// client editor to navigate to the source file.\n\t\tt.Log(\"extracted /src URL\", srcURL)\n\t\tcollectDocs := env.Awaiter.ListenToShownDocuments()\n\t\tget(t, srcURL)\n\n\t\t// Check that shown location is that of NewFunc.\n\t\tshownSource := shownDocument(t, collectDocs(), \"file:\")\n\t\tgotLoc := protocol.Location{\n\t\t\tURI:   protocol.DocumentURI(shownSource.URI), // fishy conversion\n\t\t\tRange: *shownSource.Selection,\n\t\t}\n\t\tt.Log(\"showDocument(source file) URL:\", gotLoc)\n\t\twantLoc := env.RegexpSearch(\"a/a.go\", `func ()NewFunc`)\n\t\tif gotLoc != wantLoc {\n\t\t\tt.Errorf(\"got location %v, want %v\", gotLoc, wantLoc)\n\t\t}\n\t})\n}\n\nfunc TestShowDocumentUnsupported(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a.go --\npackage a\n\nconst A = 1\n`\n\n\tfor _, supported := range []bool{false, true} {\n\t\tt.Run(fmt.Sprintf(\"supported=%v\", supported), func(t *testing.T) {\n\t\t\topts := []RunOption{Modes(Default)}\n\t\t\tif !supported {\n\t\t\t\topts = append(opts, CapabilitiesJSON([]byte(`\n{\n\t\"window\": {\n\t\t\"showDocument\": {\n\t\t\t\"support\": false\n\t\t}\n\t}\n}`)))\n\t\t\t}\n\t\t\tWithOptions(opts...).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"a.go\")\n\t\t\t\t// Invoke the \"Browse package documentation\" code\n\t\t\t\t// action to start the server.\n\t\t\t\tactions := env.CodeAction(env.Sandbox.Workdir.EntireFile(\"a.go\"), nil, 0)\n\t\t\t\tdocAction, err := CodeActionByKind(actions, settings.GoDoc)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\t// Execute the command.\n\t\t\t\t// Its side effect should be a single showDocument request.\n\t\t\t\tparams := &protocol.ExecuteCommandParams{\n\t\t\t\t\tCommand:   docAction.Command.Command,\n\t\t\t\t\tArguments: docAction.Command.Arguments,\n\t\t\t\t}\n\t\t\t\tvar result any\n\t\t\t\tcollectDocs := env.Awaiter.ListenToShownDocuments()\n\t\t\t\tcollectMessages := env.Awaiter.ListenToShownMessages()\n\t\t\t\tenv.ExecuteCommand(params, &result)\n\n\t\t\t\t// golang/go#70342: just because the command has finished does not mean\n\t\t\t\t// that we will have received the necessary notifications. Synchronize\n\t\t\t\t// using progress reports.\n\t\t\t\tenv.Await(CompletedWork(params.Command, 1, false))\n\n\t\t\t\twantDocs, wantMessages := 0, 1\n\t\t\t\tif supported {\n\t\t\t\t\twantDocs, wantMessages = 1, 0\n\t\t\t\t}\n\n\t\t\t\tdocs := collectDocs()\n\t\t\t\tmessages := collectMessages()\n\n\t\t\t\tif gotDocs := len(docs); gotDocs != wantDocs {\n\t\t\t\t\tt.Errorf(\"gopls.doc: got %d showDocument requests, want %d\", gotDocs, wantDocs)\n\t\t\t\t}\n\t\t\t\tif gotMessages := len(messages); gotMessages != wantMessages {\n\t\t\t\t\tt.Errorf(\"gopls.doc: got %d showMessage requests, want %d\", gotMessages, wantMessages)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestPkgDocNoPanic66449(t *testing.T) {\n\t// This particular input triggered a latent bug in doc.New\n\t// that would corrupt the AST while filtering out unexported\n\t// symbols such as b, causing nodeHTML to panic.\n\t// Now it doesn't crash.\n\t//\n\t// We also check cross-reference anchors for all symbols.\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\n// The 'π' suffix is to elimimate spurious matches with other HTML substrings,\n// in particular the random base64 secret tokens that appear in gopls URLs.\n\nvar Vπ, vπ = 0, 0\nconst Cπ, cπ = 0, 0\n\nfunc Fπ()\nfunc fπ()\n\ntype Tπ int\ntype tπ int\n\nfunc (Tπ) Mπ() {}\nfunc (Tπ) mπ() {}\n\nfunc (tπ) Mπ() {}\nfunc (tπ) mπ() {}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\turi1 := viewPkgDoc(t, env, env.Sandbox.Workdir.EntireFile(\"a/a.go\"))\n\n\t\tdoc := get(t, uri1)\n\t\t// (Ideally our code rendering would also\n\t\t// eliminate unexported symbols...)\n\t\tcheckMatch(t, true, doc, \"var Vπ, vπ = .*0.*0\")\n\t\tcheckMatch(t, true, doc, \"const Cπ, cπ = .*0.*0\")\n\n\t\t// Unexported funcs/types/... must still be discarded.\n\t\tcheckMatch(t, true, doc, \"Fπ\")\n\t\tcheckMatch(t, false, doc, \"fπ\")\n\t\tcheckMatch(t, true, doc, \"Tπ\")\n\t\tcheckMatch(t, false, doc, \"tπ\")\n\n\t\t// Also, check that anchors exist (only) for exported symbols.\n\t\t// exported:\n\t\tcheckMatch(t, true, doc, \"<a id='Vπ'\")\n\t\tcheckMatch(t, true, doc, \"<a id='Cπ'\")\n\t\tcheckMatch(t, true, doc, \"<h3 id='Tπ'\")\n\t\tcheckMatch(t, true, doc, \"<h3 id='Fπ'\")\n\t\tcheckMatch(t, true, doc, \"<h4 id='Tπ.Mπ'\")\n\t\t// unexported:\n\t\tcheckMatch(t, false, doc, \"<a id='vπ'\")\n\t\tcheckMatch(t, false, doc, \"<a id='cπ'\")\n\t\tcheckMatch(t, false, doc, \"<h3 id='tπ'\")\n\t\tcheckMatch(t, false, doc, \"<h3 id='fπ'\")\n\t\tcheckMatch(t, false, doc, \"<h4 id='Tπ.mπ'\")\n\t\tcheckMatch(t, false, doc, \"<h4 id='tπ.Mπ'\")\n\t\tcheckMatch(t, false, doc, \"<h4 id='tπ.mπ'\")\n\t})\n}\n\n// TestPkgDocNavigation tests that the symbol selector and index of\n// symbols are well formed.\nfunc TestPkgDocNavigation(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nfunc Func1(int, string, bool, []string) (int, error)\nfunc Func2(x, y int, a, b string) (int, error)\n\ntype Type struct {}\nfunc (t Type) Method() {}\nfunc (p *Type) PtrMethod() {}\n\nfunc Constructor() Type\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\turi1 := viewPkgDoc(t, env, env.Sandbox.Workdir.EntireFile(\"a/a.go\"))\n\t\tdoc := get(t, uri1)\n\n\t\tq := regexp.QuoteMeta\n\n\t\t// selector\n\t\tcheckMatch(t, true, doc, q(`<option label='Func1(_, _, _, _)' value='#Func1'/>`))\n\t\tcheckMatch(t, true, doc, q(`<option label='Func2(x, y, a, b)' value='#Func2'/>`))\n\t\tcheckMatch(t, true, doc, q(`<option label='Type' value='#Type'/>`))\n\t\tcheckMatch(t, true, doc, q(`<option label='Constructor()' value='#Constructor'/>`))\n\t\tcheckMatch(t, true, doc, q(`<option label='(t) Method()' value='#Type.Method'/>`))\n\t\tcheckMatch(t, true, doc, q(`<option label='(p) PtrMethod()' value='#Type.PtrMethod'/>`))\n\n\t\t// index\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Func1'>func Func1(int, string, bool, ...) (int, error)</a></li>`))\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Func2'>func Func2(x int, y int, a string, ...) (int, error)</a></li>`))\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Type'>type Type</a></li>`))\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Constructor'>func Constructor() Type</a></li>`))\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Type.Method'>func (t Type) Method()</a></li>`))\n\t\tcheckMatch(t, true, doc, q(`<li><a href='#Type.PtrMethod'>func (p *Type) PtrMethod()</a></li>`))\n\t})\n}\n\n// TestPkgDocContext tests that the gopls.doc command title and /pkg\n// URL are appropriate for the current selection. It is effectively a\n// test of golang.DocFragment.\nfunc TestPkgDocContext(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nimport \"fmt\"\nimport \"bytes\"\n\nfunc A() {\n\tfmt.Println()\n\tnew(bytes.Buffer).Write(nil)\n}\n\nconst K = 123\n\ntype T int\nfunc (*T) M() { /*in T.M*/}\n\n`\n\n\tviewRE := regexp.MustCompile(\"view=[0-9]*\")\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tfor _, test := range []struct {\n\t\t\tre   string // regexp indicating selected portion of input file\n\t\t\twant string // suffix of expected URL after /pkg/\n\t\t}{\n\t\t\t// current package\n\t\t\t{\"package a\", \"example.com/a?view=1\"},  // outside any decl\n\t\t\t{\"in T.M\", \"example.com/a?view=1#T.M\"}, // inside method (*T).M\n\t\t\t{\"123\", \"example.com/a?view=1#K\"},      // inside const/var decl\n\t\t\t{\"T int\", \"example.com/a?view=1#T\"},    // inside type decl\n\n\t\t\t// imported\n\t\t\t{\"\\\"fmt\\\"\", \"fmt?view=1\"},              // in import spec\n\t\t\t{\"fmt()[.]\", \"fmt?view=1\"},             // use of PkgName\n\t\t\t{\"Println\", \"fmt?view=1#Println\"},      // use of imported pkg-level symbol\n\t\t\t{\"fmt.Println\", \"fmt?view=1#Println\"},  // qualified identifier\n\t\t\t{\"Write\", \"bytes?view=1#Buffer.Write\"}, // use of imported method\n\n\t\t\t// TODO(adonovan):\n\t\t\t// - xtest package -> ForTest\n\t\t\t// - field of imported struct -> nope\n\t\t\t// - exported method of nonexported type from another package\n\t\t\t//   (e.g. types.Named.Obj) -> nope\n\t\t\t// Also: assert that Command.Title looks nice.\n\t\t} {\n\t\t\turi := viewPkgDoc(t, env, env.RegexpSearch(\"a/a.go\", test.re))\n\t\t\t_, got, ok := strings.Cut(uri, \"/pkg/\")\n\t\t\tif !ok {\n\t\t\t\tt.Errorf(\"pattern %q => %s (invalid /pkg URL)\", test.re, uri)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Normalize the view ID, which varies by integration test mode.\n\t\t\tgot = viewRE.ReplaceAllString(got, \"view=1\")\n\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"pattern %q => %s; want %s\", test.re, got, test.want)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// TestPkgDocFileImports tests that the doc links are rendered\n// as URLs based on the correct import mapping for the file in\n// which they appear.\nfunc TestPkgDocFileImports(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\ngo 1.20\n\n-- a/a1.go --\n// Package a refers to [b.T] [b.U] [alias.D] [d.D] [c.T] [c.U] [nope.Nope]\npackage a\n\nimport \"mod.com/b\"\nimport alias \"mod.com/d\"\n\n// [b.T] indeed refers to b.T.\n//\n// [alias.D] refers to d.D\n// but [d.D] also refers to d.D.\ntype A1 int\n\n-- a/a2.go --\npackage a\n\nimport b \"mod.com/c\"\n\n// [b.U] actually refers to c.U.\ntype A2 int\n\n-- b/b.go --\npackage b\n\ntype T int\ntype U int\n\n-- c/c.go --\npackage c\n\ntype T int\ntype U int\n\n-- d/d.go --\npackage d\n\ntype D int\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a1.go\")\n\t\turi1 := viewPkgDoc(t, env, env.Sandbox.Workdir.EntireFile(\"a/a1.go\"))\n\t\tdoc := get(t, uri1)\n\n\t\t// Check that the doc links are resolved using the\n\t\t// appropriate import mapping for the file in which\n\t\t// they appear.\n\t\tcheckMatch(t, true, doc, `pkg/mod.com/b\\?.*#T\">b.T</a> indeed refers to b.T`)\n\t\tcheckMatch(t, true, doc, `pkg/mod.com/c\\?.*#U\">b.U</a> actually refers to c.U`)\n\n\t\t// Check that doc links can be resolved using either\n\t\t// the original or the local name when they refer to a\n\t\t// renaming import. (Local names are preferred.)\n\t\tcheckMatch(t, true, doc, `pkg/mod.com/d\\?.*#D\">alias.D</a> refers to d.D`)\n\t\tcheckMatch(t, true, doc, `pkg/mod.com/d\\?.*#D\">d.D</a> also refers to d.D`)\n\n\t\t// Check that links in the package doc comment are\n\t\t// resolved, and relative to the correct file (a1.go).\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/b\\?.*#T\">b.T</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/b\\?.*#U\">b.U</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/d\\?.*#D\">alias.D</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/d\\?.*#D\">d.D</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/c\\?.*#T\">c.T</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.*pkg/mod.com/c\\?.*#U\">c.U</a>`)\n\t\tcheckMatch(t, true, doc, `Package a refers to.* \\[nope.Nope\\]`)\n\t})\n}\n\n// TestPkgDocConstructorOfUnexported tests that exported constructor\n// functions (NewT) whose result type (t) is unexported are not\n// discarded but are presented as ordinary top-level functions (#69553).\nfunc TestPkgDocConstructorOfUnexported(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.com\ngo 1.20\n\n-- a/a.go --\npackage a\n\nfunc A() {}\nfunc Z() {}\n\ntype unexported int\nfunc NewUnexported() unexported // exported constructor of unexported type\n\ntype Exported int\nfunc NewExported() Exported // exported constructor of exported type\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\turi1 := viewPkgDoc(t, env, env.Sandbox.Workdir.EntireFile(\"a/a.go\"))\n\t\tdoc := get(t, uri1)\n\n\t\twant := regexp.QuoteMeta(`\n<optgroup label='Functions'>\n  <option label='A()' value='#A'/>\n  <option label='NewUnexported()' value='#NewUnexported'/>\n  <option label='Z()' value='#Z'/>\n</optgroup>\n<optgroup label='Types'>\n  <option label='Exported' value='#Exported'/>\n</optgroup>\n<optgroup label='type Exported'>\n  <option label='NewExported()' value='#NewExported'/>\n</optgroup>`)\n\t\tcheckMatch(t, true, doc, want)\n\t})\n}\n\n// viewPkgDoc invokes the \"Browse package documentation\" code action\n// at the specified location. It returns the URI of the document, or\n// fails the test.\nfunc viewPkgDoc(t *testing.T, env *Env, loc protocol.Location) protocol.URI {\n\t// Invoke the \"Browse package documentation\" code\n\t// action to start the server.\n\tactions := env.CodeAction(loc, nil, 0)\n\tdocAction, err := CodeActionByKind(actions, settings.GoDoc)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Execute the command.\n\t// Its side effect should be a single showDocument request.\n\tparams := &protocol.ExecuteCommandParams{\n\t\tCommand:   docAction.Command.Command,\n\t\tArguments: docAction.Command.Arguments,\n\t}\n\tvar result any\n\tcollectDocs := env.Awaiter.ListenToShownDocuments()\n\tenv.ExecuteCommand(params, &result)\n\n\tdoc := shownDocument(t, collectDocs(), \"http:\")\n\tif doc == nil {\n\t\tt.Fatalf(\"no showDocument call had 'http:' prefix\")\n\t}\n\tif false {\n\t\tt.Log(\"showDocument(package doc) URL:\", doc.URI)\n\t}\n\treturn doc.URI\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/splitpkg_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/golang/splitpkg\"\n\t\"golang.org/x/tools/gopls/internal/settings\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestSplitPackage is a basic test of the web-based split package tool.\nfunc TestSplitPackage(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nfunc a() { b1() }\n\nfunc b1() { b2() }\nfunc b2() { b1(); c() }\n\n// EOF\n-- a/b.go --\npackage a\n\nfunc c() { d() }\n\nfunc d() {}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\n\t\t// Get the web page and do some rudimentary checks.\n\t\t// Most of the action happens in *.js (which we can't test)\n\t\t// and in interaction with the JSON endpoints (which we can).\n\t\tloc := env.RegexpSearch(\"a/a.go\", \"package\")\n\t\turi, page := codeActionWebPage(t, env, settings.GoSplitPackage, loc)\n\n\t\tcheckMatch(t, true, page, `<h1>Split package example.com/a</h1>`)\n\n\t\t// Now we interact using JSON, basically a trivial Go\n\t\t// version of the splitpkg.js code.\n\n\t\t// jsonHTTP performs a JSON-over-HTTP request to the specified path.\n\t\tjsonHTTP := func(method, path string, in, out any) {\n\t\t\t// Replace the /splitpkg portion of the main page's URL,\n\t\t\t// keeping everything else.\n\t\t\tu, err := url.Parse(uri)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"parsing URL: %v\", err)\n\t\t\t}\n\t\t\tu.Path = strings.ReplaceAll(u.Path, \"/splitpkg\", path)\n\n\t\t\t// HTTP\n\t\t\tinJSON, err := json.Marshal(in)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"encoding input: %v\", err)\n\t\t\t}\n\t\t\tt.Logf(\"%s: in=%s\", path, inJSON)\n\t\t\treq, err := http.NewRequest(method, u.String(), bytes.NewReader(inJSON))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"NewRequest: %v\", err)\n\t\t\t}\n\t\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t\t\tresp, err := http.DefaultClient.Do(req)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"HTTP request: %v\", err)\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\t\t\toutJSON, err := io.ReadAll(resp.Body)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"reading output: %v\", err)\n\t\t\t}\n\t\t\tt.Logf(\"%s: out=%s\", path, outJSON)\n\t\t\tif out != nil {\n\t\t\t\tif err := json.Unmarshal(outJSON, out); err != nil {\n\t\t\t\t\tt.Fatalf(\"decoding output: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// checkFileDecls queries the current package's decls grouped by file\n\t\t// and asserts that they match the description of the wanted state.\n\t\tcheckFileDecls := func(want string) {\n\t\t\tvar res splitpkg.ResultJSON\n\t\t\tjsonHTTP(\"GET\", \"/splitpkg-json\", nil, &res)\n\n\t\t\tvar lines []string\n\t\t\tfor _, file := range res.Files {\n\t\t\t\tvar buf strings.Builder\n\t\t\t\tfmt.Fprintf(&buf, \"file %s:\", file.Base)\n\t\t\t\tfor _, decl := range file.Decls {\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tfmt.Fprintf(&buf, \" %s %s;\", decl.Kind, spec.Name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines = append(lines, buf.String())\n\t\t\t}\n\t\t\tslices.Sort(lines)\n\t\t\tgot := strings.Join(lines, \"\\n\")\n\n\t\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"unexpected file decls:\\ngot:\\n%s\\nwant:\\n%s\\ndiff:\\n%s\", got, want, diff)\n\t\t\t}\n\t\t}\n\n\t\t// checkEdges queries the current decomposition and asserts\n\t\t// that it matches the description of the wanted state.\n\t\tcheckEdges := func(want string) {\n\t\t\tvar res splitpkg.ResultJSON\n\t\t\tjsonHTTP(\"GET\", \"/splitpkg-json\", nil, &res)\n\n\t\t\tvar lines []string\n\t\t\tfor _, edge := range res.Edges {\n\t\t\t\tvar buf strings.Builder\n\t\t\t\tfmt.Fprintf(&buf, \"edge %s -> %s:\", res.Components.Names[edge.From], res.Components.Names[edge.To])\n\t\t\t\tif edge.Cyclic {\n\t\t\t\t\tbuf.WriteString(\" ⚠\")\n\t\t\t\t}\n\t\t\t\tfor _, ref := range edge.Refs {\n\t\t\t\t\tfmt.Fprintf(&buf, \" %s -> %s;\", ref.From, ref.To)\n\t\t\t\t}\n\t\t\t\tlines = append(lines, buf.String())\n\t\t\t}\n\t\t\tslices.Sort(lines)\n\t\t\tgot := strings.Join(lines, \"\\n\")\n\t\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"unexpected component edges:\\ngot:\\n%s\\nwant:\\n%s\\ndiff:\\n%s\", got, want, diff)\n\t\t\t}\n\t\t}\n\n\t\t// Check the initial file/decl state.\n\t\tcheckFileDecls(`\nfile a.go: func a; func b1; func b2;\nfile b.go: func c; func d;`[1:])\n\n\t\t// Check that the set of decls updates as we edit the files.\n\t\tenv.RegexpReplace(\"a/a.go\", \"// EOF\", \"func b3() {}\")\n\t\tenv.Await(env.DoneDiagnosingChanges())\n\t\tcheckFileDecls(`\nfile a.go: func a; func b1; func b2; func b3;\nfile b.go: func c; func d;`[1:])\n\n\t\t// Post a cyclic decomposition. Check the report.\n\t\tjsonHTTP(\"POST\", \"/splitpkg-components\", splitpkg.ComponentsJSON{\n\t\t\tNames:       []string{\"zero\", \"one\", \"two\", \"three\"},\n\t\t\tAssignments: map[string]int{\"a\": 0, \"b1\": 1, \"b2\": 2, \"c\": 3, \"d\": 3},\n\t\t}, nil)\n\t\tcheckEdges(`\nedge one -> two: ⚠ b1 -> b2;\nedge two -> one: ⚠ b2 -> b1;\nedge two -> three: b2 -> c;\nedge zero -> one: a -> b1;`[1:])\n\n\t\t// Post an acyclic decomposition. Check the report.\n\t\tjsonHTTP(\"POST\", \"/splitpkg-components\", splitpkg.ComponentsJSON{\n\t\t\tNames:       []string{\"zero\", \"one\", \"two\", \"three\"},\n\t\t\tAssignments: map[string]int{\"a\": 0, \"b1\": 1, \"b2\": 1, \"c\": 2, \"d\": 3},\n\t\t}, nil)\n\t\tcheckEdges(`\nedge one -> two: b2 -> c;\nedge two -> three: c -> d;\nedge zero -> one: a -> b1;`[1:])\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/web/util_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage web_test\n\n// This file defines web server testing utilities.\n\nimport (\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(integration.Main(m))\n}\n\n// shownDocument returns the first shown document matching the URI prefix.\n// It may be nil.\n// As a side effect, it clears the list of accumulated shown documents.\nfunc shownDocument(t *testing.T, shown []*protocol.ShowDocumentParams, prefix string) *protocol.ShowDocumentParams {\n\tt.Helper()\n\tvar first *protocol.ShowDocumentParams\n\tfor _, sd := range shown {\n\t\tif strings.HasPrefix(sd.URI, prefix) {\n\t\t\tif first != nil {\n\t\t\t\tt.Errorf(\"got multiple showDocument requests: %#v\", shown)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tfirst = sd\n\t\t}\n\t}\n\treturn first\n}\n\n// get fetches the content of a document over HTTP.\nfunc get(t *testing.T, url string) []byte {\n\tt.Helper()\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer resp.Body.Close()\n\tgot, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn got\n}\n\n// checkMatch asserts that got matches (or doesn't match, if !want) the pattern.\nfunc checkMatch(t *testing.T, want bool, got []byte, pattern string) {\n\tt.Helper()\n\tif regexp.MustCompile(pattern).Match(got) != want {\n\t\tif want {\n\t\t\tt.Errorf(\"input did not match wanted pattern %q; got:\\n%s\", pattern, got)\n\t\t} else {\n\t\t\tt.Errorf(\"input matched unwanted pattern %q; got:\\n%s\", pattern, got)\n\t\t}\n\t}\n}\n\n// codeActionWebPage returns the URL and content of the page opened by the specified code action.\nfunc codeActionWebPage(t *testing.T, env *integration.Env, kind protocol.CodeActionKind, loc protocol.Location) (string, []byte) {\n\tactions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)\n\tif err != nil {\n\t\tt.Fatalf(\"CodeAction: %v\", err)\n\t}\n\taction, err := integration.CodeActionByKind(actions, kind)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\taction, err = env.Editor.ResolveCodeAction(env.Ctx, action)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Execute the command.\n\t// Its side effect should be a single showDocument request.\n\tparams := &protocol.ExecuteCommandParams{\n\t\tCommand:   action.Command.Command,\n\t\tArguments: action.Command.Arguments,\n\t}\n\tvar result command.DebuggingResult\n\tcollectDocs := env.Awaiter.ListenToShownDocuments()\n\tenv.ExecuteCommand(params, &result)\n\tdoc := shownDocument(t, collectDocs(), \"http:\")\n\tif doc == nil {\n\t\tt.Fatalf(\"no showDocument call had 'file:' prefix\")\n\t}\n\tt.Log(\"showDocument(package doc) URL:\", doc.URI)\n\n\treturn doc.URI, get(t, doc.URI)\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/adhoc_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test for golang/go#57209: editing a file in an ad-hoc package should not\n// trigger conflicting diagnostics.\nfunc TestAdhoc_Edits(t *testing.T) {\n\tconst files = `\n-- a.go --\npackage foo\n\nconst X = 1\n\n-- b.go --\npackage foo\n\n// import \"errors\"\n\nconst Y = X\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b.go\")\n\n\t\tfor range 10 {\n\t\t\tenv.RegexpReplace(\"b.go\", `// import \"errors\"`, `import \"errors\"`)\n\t\t\tenv.RegexpReplace(\"b.go\", `import \"errors\"`, `// import \"errors\"`)\n\t\t\tenv.AfterChange(NoDiagnostics())\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/broken_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/server\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// This file holds various tests for UX with respect to broken workspaces.\n//\n// TODO: consolidate other tests here.\n//\n// TODO: write more tests:\n//  - an explicit GOWORK value that doesn't exist\n//  - using modules and/or GOWORK inside of GOPATH?\n\n// Test for golang/go#53933\nfunc TestBrokenWorkspace_DuplicateModules(t *testing.T) {\n\t// This proxy module content is replaced by the workspace, but is still\n\t// required for module resolution to function in the Go command.\n\tconst proxy = `\n-- example.com/foo@v0.0.1/go.mod --\nmodule example.com/foo\n\ngo 1.12\n`\n\n\tconst src = `\n-- go.work --\ngo 1.18\n\nuse (\n\t./package1\n\t./package1/vendor/example.com/foo\n\t./package2\n\t./package2/vendor/example.com/foo\n)\n\n-- package1/go.mod --\nmodule mod.test\n\ngo 1.18\n\nrequire example.com/foo v0.0.1\n-- package1/main.go --\npackage main\n\nimport \"example.com/foo\"\n\nfunc main() {\n\t_ = foo.CompleteMe\n}\n-- package1/vendor/example.com/foo/go.mod --\nmodule example.com/foo\n\ngo 1.18\n-- package1/vendor/example.com/foo/foo.go --\npackage foo\n\nconst CompleteMe = 111\n-- package2/go.mod --\nmodule mod2.test\n\ngo 1.18\n\nrequire example.com/foo v0.0.1\n-- package2/main.go --\npackage main\n\nimport \"example.com/foo\"\n\nfunc main() {\n\t_ = foo.CompleteMe\n}\n-- package2/vendor/example.com/foo/go.mod --\nmodule example.com/foo\n\ngo 1.18\n-- package2/vendor/example.com/foo/foo.go --\npackage foo\n\nconst CompleteMe = 222\n`\n\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"package1/main.go\")\n\t\tenv.AfterChange(\n\t\t\tOutstandingWork(server.WorkspaceLoadFailure, `module example.com/foo appears multiple times in workspace`),\n\t\t)\n\n\t\t// Remove the redundant vendored copy of example.com.\n\t\tenv.WriteWorkspaceFile(\"go.work\", `go 1.18\n\t\tuse (\n\t\t\t./package1\n\t\t\t./package2\n\t\t\t./package2/vendor/example.com/foo\n\t\t)\n\t\t`)\n\t\tenv.AfterChange(NoOutstandingWork(IgnoreTelemetryPromptWork))\n\n\t\t// Check that definitions in package1 go to the copy vendored in package2.\n\t\tlocation := string(env.FirstDefinition(env.RegexpSearch(\"package1/main.go\", \"CompleteMe\")).URI)\n\t\tconst wantLocation = \"package2/vendor/example.com/foo/foo.go\"\n\t\tif !strings.HasSuffix(location, wantLocation) {\n\t\t\tt.Errorf(\"got definition of CompleteMe at %q, want %q\", location, wantLocation)\n\t\t}\n\t})\n}\n\n// Test for golang/go#43186: correcting the module path should fix errors\n// without restarting gopls.\nfunc TestBrokenWorkspace_WrongModulePath(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.testx\n\ngo 1.18\n-- p/internal/foo/foo.go --\npackage foo\n\nconst C = 1\n-- p/internal/bar/bar.go --\npackage bar\n\nimport \"mod.test/p/internal/foo\"\n\nconst D = foo.C + 1\n-- p/internal/bar/bar_test.go --\npackage bar_test\n\nimport (\n\t\"mod.test/p/internal/foo\"\n\t. \"mod.test/p/internal/bar\"\n)\n\nconst E = D + foo.C\n-- p/internal/baz/baz_test.go --\npackage baz_test\n\nimport (\n\tnamed \"mod.test/p/internal/bar\"\n)\n\nconst F = named.D - 3\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p/internal/bar/bar.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"p/internal/bar/bar.go\", \"\\\"mod.test/p/internal/foo\\\"\")),\n\t\t)\n\t\tenv.OpenFile(\"go.mod\")\n\t\tenv.RegexpReplace(\"go.mod\", \"mod.testx\", \"mod.test\")\n\t\tenv.SaveBuffer(\"go.mod\") // saving triggers a reload\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n\nfunc TestMultipleModules_Warning(t *testing.T) {\n\tt.Skip(\"temporary skip for golang/go#57979: revisit after zero-config logic is in place\")\n\n\tmsgForVersion := func(ver int) string {\n\t\tif ver >= 18 {\n\t\t\treturn `gopls was not able to find modules in your workspace.`\n\t\t} else {\n\t\t\treturn `gopls requires a module at the root of your workspace.`\n\t\t}\n\t}\n\n\tconst modules = `\n-- a/go.mod --\nmodule a.com\n\ngo 1.12\n-- a/a.go --\npackage a\n-- a/empty.go --\n// an empty file\n-- b/go.mod --\nmodule b.com\n\ngo 1.12\n-- b/b.go --\npackage b\n`\n\tfor _, go111module := range []string{\"on\", \"auto\"} {\n\t\tt.Run(\"GO111MODULE=\"+go111module, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tModes(Default),\n\t\t\t\tEnvVars{\"GO111MODULE\": go111module},\n\t\t\t).Run(t, modules, func(t *testing.T, env *Env) {\n\t\t\t\tver := env.GoVersion()\n\t\t\t\tmsg := msgForVersion(ver)\n\t\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\t\tenv.OpenFile(\"a/empty.go\")\n\t\t\t\tenv.OpenFile(\"b/go.mod\")\n\t\t\t\tenv.AfterChange(\n\t\t\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"package a\")),\n\t\t\t\t\tDiagnostics(env.AtRegexp(\"b/go.mod\", \"module b.com\")),\n\t\t\t\t\tOutstandingWork(server.WorkspaceLoadFailure, msg),\n\t\t\t\t)\n\n\t\t\t\t// Changing the workspace folders to the valid modules should resolve\n\t\t\t\t// the workspace errors and diagnostics.\n\t\t\t\t//\n\t\t\t\t// TODO(rfindley): verbose work tracking doesn't follow changing the\n\t\t\t\t// workspace folder, therefore we can't invoke AfterChange here.\n\t\t\t\tenv.ChangeWorkspaceFolders(\"a\", \"b\")\n\t\t\t\tenv.Await(\n\t\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t\t\tNoDiagnostics(ForFile(\"b/go.mod\")),\n\t\t\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\t\t)\n\n\t\t\t\tenv.ChangeWorkspaceFolders(\".\")\n\n\t\t\t\t// TODO(rfindley): when GO111MODULE=auto, we need to open or change a\n\t\t\t\t// file here in order to detect a critical error. This is because gopls\n\t\t\t\t// has forgotten about a/a.go, and therefore doesn't hit the heuristic\n\t\t\t\t// \"all packages are command-line-arguments\".\n\t\t\t\t//\n\t\t\t\t// This is broken, and could be fixed by adjusting the heuristic to\n\t\t\t\t// account for the scenario where there are *no* workspace packages, or\n\t\t\t\t// (better) trying to get workspace packages for each open file. See\n\t\t\t\t// also golang/go#54261.\n\t\t\t\tenv.OpenFile(\"b/b.go\")\n\t\t\t\tenv.AfterChange(\n\t\t\t\t\t// TODO(rfindley): fix these missing diagnostics.\n\t\t\t\t\t// Diagnostics(env.AtRegexp(\"a/a.go\", \"package a\")),\n\t\t\t\t\t// Diagnostics(env.AtRegexp(\"b/go.mod\", \"module b.com\")),\n\t\t\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"package b\")),\n\t\t\t\t\tOutstandingWork(server.WorkspaceLoadFailure, msg),\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t}\n\n\t// Expect no warning if GO111MODULE=auto in a directory in GOPATH.\n\tt.Run(\"GOPATH_GO111MODULE_auto\", func(t *testing.T) {\n\t\tWithOptions(\n\t\t\tModes(Default),\n\t\t\tEnvVars{\"GO111MODULE\": \"auto\"},\n\t\t\tInGOPATH(),\n\t\t).Run(t, modules, func(t *testing.T, env *Env) {\n\t\t\tenv.OpenFile(\"a/a.go\")\n\t\t\tenv.AfterChange(\n\t\t\t\tNoDiagnostics(ForFile(\"a/a.go\")),\n\t\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\t)\n\t\t})\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/didcreatefiles_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TestAutoFillPackageDecl tests that creation of a new .go file causes\n// gopls to choose a sensible package name and fill in the package declaration.\nfunc TestAutoFillPackageDecl(t *testing.T) {\n\tconst existFiles = `\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n\n-- dog/a_test.go --\npackage dog\n-- fruits/apple.go --\npackage apple\n\nfun apple() int {\n\treturn 0\n}\n\n-- license/license.go --\n/* Copyright 2025 The Go Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file. */\n\npackage license\n\n-- license1/license.go --\n// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage license1\n\n-- cmd/main.go --\npackage main\n\n-- integration/a_test.go --\npackage integration_test\n\n-- nopkg/testfile.go --\npackage\n`\n\tfor _, tc := range []struct {\n\t\tname    string\n\t\tnewfile string\n\t\twant    string\n\t}{\n\t\t{\n\t\t\tname:    \"new file in folder with a_test.go\",\n\t\t\tnewfile: \"dog/newfile.go\",\n\t\t\twant:    \"package dog\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with go file\",\n\t\t\tnewfile: \"fruits/newfile.go\",\n\t\t\twant:    \"package apple\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new test file in folder with go file\",\n\t\t\tnewfile: \"fruits/newfile_test.go\",\n\t\t\twant:    \"package apple\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with go file that contains license comment\",\n\t\t\tnewfile: \"license/newfile.go\",\n\t\t\twant: `/* Copyright 2025 The Go Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file. */\n\npackage license\n`,\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with go file that contains license comment\",\n\t\t\tnewfile: \"license1/newfile.go\",\n\t\t\twant: `// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage license1\n`,\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with main package\",\n\t\t\tnewfile: \"cmd/newfile.go\",\n\t\t\twant:    \"package main\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in empty folder\",\n\t\t\tnewfile: \"empty_folder/newfile.go\",\n\t\t\twant:    \"package emptyfolder\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with integration_test package\",\n\t\t\tnewfile: \"integration/newfile.go\",\n\t\t\twant:    \"package integration\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new test file in folder with integration_test package\",\n\t\t\tnewfile: \"integration/newfile_test.go\",\n\t\t\twant:    \"package integration\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"new file in folder with incomplete package clause\",\n\t\t\tnewfile: \"incomplete/newfile.go\",\n\t\t\twant:    \"package incomplete\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"package completion for dir name with punctuation\",\n\t\t\tnewfile: \"123f_r.u~its-123/newfile.go\",\n\t\t\twant:    \"package fruits123\\n\",\n\t\t},\n\t\t{\n\t\t\tname:    \"package completion for dir name with invalid dir name\",\n\t\t\tnewfile: \"123f_r.u~its-123/newfile.go\",\n\t\t\twant:    \"package fruits123\\n\",\n\t\t},\n\t} {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tcreateFiles := fmt.Sprintf(\"%s\\n-- %s --\", existFiles, tc.newfile)\n\t\t\tRun(t, createFiles, func(t *testing.T, env *Env) {\n\t\t\t\tenv.DidCreateFiles(env.Editor.DocumentURI(tc.newfile))\n\t\t\t\t// save buffer to ensure the edits take effects in the file system.\n\t\t\t\tif err := env.Editor.SaveBuffer(context.Background(), tc.newfile); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif got := env.FileContent(tc.newfile); tc.want != got {\n\t\t\t\t\tt.Fatalf(\"want '%s' but got '%s'\", tc.want, got)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/directoryfilters_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// This file contains regression tests for the directoryFilters setting.\n//\n// TODO:\n//  - consolidate some of these tests into a single test\n//  - add more tests for changing directory filters\n\nfunc TestDirectoryFilters(t *testing.T) {\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tWorkspaceFolders(\"pkg\"),\n\t\tSettings{\n\t\t\t\"directoryFilters\": []string{\"-inner\"},\n\t\t},\n\t).Run(t, workspaceModule, func(t *testing.T, env *Env) {\n\t\tsyms := env.Symbol(\"Hi\")\n\t\tsort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })\n\t\tfor _, s := range syms {\n\t\t\tif strings.Contains(s.ContainerName, \"inner\") {\n\t\t\t\tt.Errorf(\"WorkspaceSymbol: found symbol %q with container %q, want \\\"inner\\\" excluded\", s.Name, s.ContainerName)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestDirectoryFiltersLoads(t *testing.T) {\n\t// exclude, and its error, should be excluded from the workspace.\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.12\n-- exclude/exclude.go --\npackage exclude\n\nconst _ = Nonexistant\n`\n\n\tWithOptions(\n\t\tSettings{\"directoryFilters\": []string{\"-exclude\"}},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoDiagnostics(ForFile(\"exclude/x.go\")),\n\t\t)\n\t})\n}\n\nfunc TestDirectoryFiltersTransitiveDep(t *testing.T) {\n\t// Even though exclude is excluded from the workspace, it should\n\t// still be importable as a non-workspace package.\n\tconst files = `\n-- go.mod --\nmodule example.com\n\ngo 1.12\n-- include/include.go --\npackage include\nimport \"example.com/exclude\"\n\nconst _ = exclude.X\n-- exclude/exclude.go --\npackage exclude\n\nconst _ = Nonexistant // should be ignored, since this is a non-workspace package\nconst X = 1\n`\n\n\tWithOptions(\n\t\tSettings{\"directoryFilters\": []string{\"-exclude\"}},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoDiagnostics(ForFile(\"exclude/exclude.go\")), // filtered out\n\t\t\tNoDiagnostics(ForFile(\"include/include.go\")), // successfully builds\n\t\t)\n\t})\n}\n\n// Test for golang/go#46438: support for '**' in directory filters.\nfunc TestDirectoryFilters_Wildcard(t *testing.T) {\n\tfilters := []string{\"-**/bye\"}\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tWorkspaceFolders(\"pkg\"),\n\t\tSettings{\n\t\t\t\"directoryFilters\": filters,\n\t\t},\n\t).Run(t, workspaceModule, func(t *testing.T, env *Env) {\n\t\tsyms := env.Symbol(\"Bye\")\n\t\tsort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })\n\t\tfor _, s := range syms {\n\t\t\tif strings.Contains(s.ContainerName, \"bye\") {\n\t\t\t\tt.Errorf(\"WorkspaceSymbol: found symbol %q with container %q with filters %v\", s.Name, s.ContainerName, filters)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// Test for golang/go#52993: wildcard directoryFilters should apply to\n// goimports scanning as well.\nfunc TestDirectoryFilters_ImportScanning(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.12\n-- main.go --\npackage main\n\nfunc main() {\n\tbye.Goodbye()\n\thi.Hello()\n}\n-- p/bye/bye.go --\npackage bye\n\nfunc Goodbye() {}\n-- hi/hi.go --\npackage hi\n\nfunc Hello() {}\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"directoryFilters\": []string{\"-**/bye\", \"-hi\"},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tbeforeSave := env.BufferText(\"main.go\")\n\t\tenv.OrganizeImports(\"main.go\")\n\t\tgot := env.BufferText(\"main.go\")\n\t\tif got != beforeSave {\n\t\t\tt.Errorf(\"after organizeImports code action, got modified buffer:\\n%s\", got)\n\t\t}\n\t})\n}\n\n// Test for golang/go#52993: non-wildcard directoryFilters should still be\n// applied relative to the workspace folder, not the module root.\nfunc TestDirectoryFilters_MultiRootImportScanning(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\n\nuse (\n\ta\n\tb\n)\n-- a/go.mod --\nmodule mod1.test\n\ngo 1.18\n-- a/main.go --\npackage main\n\nfunc main() {\n\thi.Hi()\n}\n-- a/hi/hi.go --\npackage hi\n\nfunc Hi() {}\n-- b/go.mod --\nmodule mod2.test\n\ngo 1.18\n-- b/main.go --\npackage main\n\nfunc main() {\n\thi.Hi()\n}\n-- b/hi/hi.go --\npackage hi\n\nfunc Hi() {}\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"directoryFilters\": []string{\"-hi\"}, // this test fails with -**/hi\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tbeforeSave := env.BufferText(\"a/main.go\")\n\t\tenv.OrganizeImports(\"a/main.go\")\n\t\tgot := env.BufferText(\"a/main.go\")\n\t\tif got == beforeSave {\n\t\t\tt.Errorf(\"after organizeImports code action, got identical buffer:\\n%s\", got)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/fromenv_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test that setting go.work via environment variables or settings works.\nfunc TestUseGoWorkOutsideTheWorkspace(t *testing.T) {\n\t// As discussed in\n\t// https://github.com/golang/go/issues/59458#issuecomment-1513794691, we must\n\t// use \\-separated paths in go.work use directives for this test to work\n\t// correctly on windows.\n\tvar files = fmt.Sprintf(`\n-- work/a/go.mod --\nmodule a.com\n\ngo 1.12\n-- work/a/a.go --\npackage a\n-- work/b/go.mod --\nmodule b.com\n\ngo 1.12\n-- work/b/b.go --\npackage b\n\nfunc _() {\n\tx := 1 // unused\n}\n-- other/c/go.mod --\nmodule c.com\n\ngo 1.18\n-- other/c/c.go --\npackage c\n-- config/go.work --\ngo 1.18\n\nuse (\n\t%s\n\t%s\n\t%s\n)\n`,\n\t\tfilepath.Join(\"$SANDBOX_WORKDIR\", \"work\", \"a\"),\n\t\tfilepath.Join(\"$SANDBOX_WORKDIR\", \"work\", \"b\"),\n\t\tfilepath.Join(\"$SANDBOX_WORKDIR\", \"other\", \"c\"),\n\t)\n\n\tWithOptions(\n\t\tWorkspaceFolders(\"work\"), // use a nested workspace dir, so that GOWORK is outside the workspace\n\t\tEnvVars{\"GOWORK\": filepath.Join(\"$SANDBOX_WORKDIR\", \"config\", \"go.work\")},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t// When we have an explicit GOWORK set, we should get a file watch request.\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tFileWatchMatching(`other`),\n\t\t\tFileWatchMatching(`config.go\\.work`),\n\t\t)\n\t\tenv.Await(FileWatchMatching(`config.go\\.work`))\n\t\t// Even though work/b is not open, we should get its diagnostics as it is\n\t\t// included in the workspace.\n\t\tenv.OpenFile(\"work/a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"work/b/b.go\", \"x := 1\"), WithMessage(\"not used\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/goversion_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"flag\"\n\t\"os\"\n\t\"runtime\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nvar go121bin = flag.String(\"go121bin\", \"\", \"bin directory containing go 1.21 or later\")\n\n// TODO(golang/go#65917): delete this test once we no longer support building\n// gopls with older Go versions.\nfunc TestCanHandlePatchVersions(t *testing.T) {\n\t// This test verifies the fixes for golang/go#66195 and golang/go#66636 --\n\t// that gopls does not crash when encountering a go version with a patch\n\t// number in the go.mod file.\n\t//\n\t// This is tricky to test, because the regression requires that gopls is\n\t// built with an older go version, and then the environment is upgraded to\n\t// have a more recent go. To set up this scenario, the test requires a path\n\t// to a bin directory containing go1.21 or later.\n\tif *go121bin == \"\" {\n\t\tt.Skip(\"-go121bin directory is not set\")\n\t}\n\n\tif runtime.GOOS != \"linux\" && runtime.GOOS != \"darwin\" {\n\t\tt.Skip(\"requires linux or darwin\") // for PATH separator\n\t}\n\n\tpath := os.Getenv(\"PATH\")\n\tt.Setenv(\"PATH\", *go121bin+\":\"+path)\n\n\tconst files = `\n-- go.mod --\nmodule example.com/bar\n\ngo 1.21.1\n\n-- p.go --\npackage bar\n\ntype I interface { string }\n`\n\n\tWithOptions(\n\t\tEnvVars{\n\t\t\t\"PATH\": path,\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"p.go\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/metadata_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TODO(rfindley): move workspace tests related to metadata bugs into this\n// file.\n\nfunc TestFixImportDecl(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.test\n\ngo 1.12\n-- p.go --\npackage p\n\nimport (\n\t_ \"fmt\"\n\nconst C = 42\n`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"p.go\")\n\t\tenv.RegexpReplace(\"p.go\", \"\\\"fmt\\\"\", \"\\\"fmt\\\"\\n)\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"p.go\")),\n\t\t)\n\t})\n}\n\n// Test that moving ignoring a file via build constraints causes diagnostics to\n// be resolved.\nfunc TestIgnoreFile(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.test\n\ngo 1.12\n-- foo.go --\npackage main\n\nfunc main() {}\n-- bar.go --\npackage main\n\nfunc main() {}\n\t`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo.go\")\n\t\tenv.OpenFile(\"bar.go\")\n\t\tenv.OnceMet(\n\t\t\tenv.DoneWithOpen(),\n\t\t\tDiagnostics(env.AtRegexp(\"foo.go\", \"func (main)\")),\n\t\t\tDiagnostics(env.AtRegexp(\"bar.go\", \"func (main)\")),\n\t\t)\n\n\t\t// Ignore bar.go. This should resolve diagnostics.\n\t\tenv.RegexpReplace(\"bar.go\", \"package main\", \"//go:build ignore\\n\\npackage main\")\n\n\t\t// To make this test pass with experimentalUseInvalidMetadata, we could make\n\t\t// an arbitrary edit that invalidates the snapshot, at which point the\n\t\t// orphaned diagnostics will be invalidated.\n\t\t//\n\t\t// But of course, this should not be necessary: we should invalidate stale\n\t\t// information when fresh metadata arrives.\n\t\t// env.RegexpReplace(\"foo.go\", \"package main\", \"package main // test\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"foo.go\")),\n\t\t\tNoDiagnostics(ForFile(\"bar.go\")),\n\t\t)\n\n\t\t// If instead of 'ignore' (which gopls treats as a standalone package) we\n\t\t// used a different build tag, we should get a warning about having no\n\t\t// packages for bar.go\n\t\tenv.RegexpReplace(\"bar.go\", \"ignore\", \"excluded\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"bar.go\", \"package (main)\"), WithMessage(\"excluded due to its build tags\")),\n\t\t)\n\t})\n}\n\nfunc TestReinitializeRepeatedly(t *testing.T) {\n\tconst multiModule = `\n-- go.work --\ngo 1.18\n\nuse (\n\tmoda/a\n\tmodb\n)\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/go.sum --\nb.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=\nb.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n\t// AAA\n}\n-- modb/go.mod --\nmodule b.com\n\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t\tSettings{\n\t\t\t// For this test, we want workspace diagnostics to start immediately\n\t\t\t// during change processing.\n\t\t\t\"diagnosticsDelay\": \"0\",\n\t\t},\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tenv.AfterChange()\n\n\t\t// This test verifies that we fully process workspace reinitialization\n\t\t// (which allows GOPROXY), even when the reinitialized snapshot is\n\t\t// invalidated by subsequent changes.\n\t\t//\n\t\t// First, update go.work to remove modb. This will cause reinitialization\n\t\t// to fetch b.com from the proxy.\n\t\tenv.WriteWorkspaceFile(\"go.work\", \"go 1.18\\nuse moda/a\")\n\t\t// Next, wait for gopls to start processing the change. Because we've set\n\t\t// diagnosticsDelay to zero, this will start diagnosing the workspace (and\n\t\t// try to reinitialize on the snapshot context).\n\t\tenv.Await(env.StartedChangeWatchedFiles())\n\t\t// Finally, immediately make a file change to cancel the previous\n\t\t// operation. This is racy, but will usually cause initialization to be\n\t\t// canceled.\n\t\tenv.RegexpReplace(\"moda/a/a.go\", \"AAA\", \"BBB\")\n\t\tenv.AfterChange()\n\t\t// Now, to satisfy a definition request, gopls will try to reload moda. But\n\t\t// without access to the proxy (because this is no longer a\n\t\t// reinitialization), this loading will fail.\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\tgot := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"b.com@v1.2.3/b/b.go\"; !strings.HasSuffix(got, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, got)\n\t\t}\n\t})\n}\n\n// Test for golang/go#59458. With lazy module loading, we may not need\n// transitively required modules.\nfunc TestNestedModuleLoading_Issue59458(t *testing.T) {\n\t// In this test, module b.com/nested requires b.com/other, which in turn\n\t// requires b.com, but b.com/nested does not reach b.com through the package\n\t// graph. Therefore, b.com/nested does not need b.com on 1.17 and later,\n\t// thanks to graph pruning.\n\t//\n\t// We verify that we can load b.com/nested successfully. Previously, we\n\t// couldn't, because loading the pattern b.com/nested/... matched the module\n\t// b.com, which exists in the module graph but does not have a go.sum entry.\n\n\tconst proxy = `\n-- b.com@v1.2.3/go.mod --\nmodule b.com\n\ngo 1.18\n-- b.com@v1.2.3/b/b.go --\npackage b\n\nfunc Hello() {}\n\n-- b.com/other@v1.4.6/go.mod --\nmodule b.com/other\n\ngo 1.18\n\nrequire b.com v1.2.3\n-- b.com/other@v1.4.6/go.sun --\nb.com v1.2.3 h1:AGjCxWRJLUuJiZ21IUTByr9buoa6+B6Qh5LFhVLKpn4=\n-- b.com/other@v1.4.6/bar/bar.go --\npackage bar\n\nimport \"b.com/b\"\n\nfunc _() {\n\tb.Hello()\n}\n-- b.com/other@v1.4.6/foo/foo.go --\npackage foo\n\nconst Foo = 0\n`\n\n\tconst files = `\n-- go.mod --\nmodule b.com/nested\n\ngo 1.18\n\nrequire b.com/other v1.4.6\n-- nested.go --\npackage nested\n\nimport \"b.com/other/foo\"\n\nconst C = foo.Foo\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoDiagnostics(),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/misspelling_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// Test for golang/go#57081.\nfunc TestFormattingMisspelledURI(t *testing.T) {\n\tif runtime.GOOS != \"windows\" && runtime.GOOS != \"darwin\" {\n\t\tt.Skip(\"golang/go#57081 only reproduces on case-insensitive filesystems.\")\n\t}\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.19\n-- foo.go --\npackage foo\n\nconst  C = 2 // extra space is intentional\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"Foo.go\")\n\t\tenv.FormatBuffer(\"Foo.go\")\n\t\twant := env.BufferText(\"Foo.go\")\n\n\t\tif want == \"\" {\n\t\t\tt.Fatalf(\"Foo.go is empty\")\n\t\t}\n\n\t\t// In golang/go#57081, we observed that if overlay cases don't match, gopls\n\t\t// will find (and format) the on-disk contents rather than the overlay,\n\t\t// resulting in invalid edits.\n\t\t//\n\t\t// Verify that this doesn't happen, by confirming that formatting is\n\t\t// idempotent.\n\t\tenv.FormatBuffer(\"Foo.go\")\n\t\tgot := env.BufferText(\"Foo.go\")\n\t\tif diff := compare.Text(want, got); diff != \"\" {\n\t\t\tt.Errorf(\"invalid content after second formatting:\\n%s\", diff)\n\t\t}\n\t})\n}\n\n// Test that we can find packages for open files with different spelling on\n// case-insensitive file systems.\nfunc TestPackageForMisspelledURI(t *testing.T) {\n\tt.Skip(\"golang/go#57081: this test fails because the Go command does not load Foo.go correctly\")\n\tif runtime.GOOS != \"windows\" && runtime.GOOS != \"darwin\" {\n\t\tt.Skip(\"golang/go#57081 only reproduces on case-insensitive filesystems.\")\n\t}\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.19\n-- foo.go --\npackage foo\n\nconst C = D\n-- bar.go --\npackage foo\n\nconst D = 2\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"Foo.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/modules_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestModulesCmd(t *testing.T) {\n\tconst goModView = `\n-- go.mod --\nmodule foo\n\n-- pkg/pkg.go --\npackage pkg\nfunc Pkg()\n\n-- bar/bar.go --\npackage bar\nfunc Bar()\n\n-- bar/baz/go.mod --\nmodule baz\n\n-- bar/baz/baz.go --\npackage baz\nfunc Baz()\n`\n\n\tconst goWorkView = `\n-- go.work --\nuse ./foo\nuse ./bar\n\n-- foo/go.mod --\nmodule foo\n\n-- foo/foo.go --\npackage foo\nfunc Foo()\n\n-- bar/go.mod --\nmodule bar\n\n-- bar/bar.go --\npackage bar\nfunc Bar()\n`\n\n\tt.Run(\"go.mod view\", func(t *testing.T) {\n\t\t// If baz isn't loaded, it will not be included\n\t\tt.Run(\"unloaded\", func(t *testing.T) {\n\t\t\tRun(t, goModView, func(t *testing.T, env *Env) {\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"\"), -1, []command.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\n\t\t// With baz loaded and recursion enabled, baz will be included\n\t\tt.Run(\"recurse\", func(t *testing.T) {\n\t\t\tRun(t, goModView, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"bar/baz/baz.go\")\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"\"), -1, []command.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"baz\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"bar/baz/go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\n\t\t// With recursion=1, baz will not be included\n\t\tt.Run(\"depth\", func(t *testing.T) {\n\t\t\tRun(t, goModView, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"bar/baz/baz.go\")\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"\"), 1, []command.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\n\t\t// Baz will be included if it is requested specifically\n\t\tt.Run(\"nested\", func(t *testing.T) {\n\t\t\tRun(t, goModView, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"bar/baz/baz.go\")\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"bar/baz\"), 0, []command.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"baz\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"bar/baz/go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t})\n\n\tt.Run(\"go.work view\", func(t *testing.T) {\n\t\tt.Run(\"base\", func(t *testing.T) {\n\t\t\tRun(t, goWorkView, func(t *testing.T, env *Env) {\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"\"), 0, nil)\n\t\t\t})\n\t\t})\n\n\t\tt.Run(\"recursive\", func(t *testing.T) {\n\t\t\tRun(t, goWorkView, func(t *testing.T, env *Env) {\n\t\t\t\tcheckModules(t, env, env.Editor.DocumentURI(\"\"), -1, []command.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"bar\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"bar/go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"foo/go.mod\"),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t})\n}\n\nfunc checkModules(t testing.TB, env *Env, dir protocol.DocumentURI, maxDepth int, want []command.Module) {\n\tt.Helper()\n\n\tcmd := command.NewModulesCommand(\"Modules\", command.ModulesArgs{Dir: dir, MaxDepth: maxDepth})\n\tvar result command.ModulesResult\n\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\tCommand:   command.Modules.String(),\n\t\tArguments: cmd.Arguments,\n\t}, &result)\n\n\t// The ordering of results is undefined and modules from a go.work view are\n\t// retrieved from a map, so sort the results to ensure consistency\n\tsort.Slice(result.Modules, func(i, j int) bool {\n\t\ta, b := result.Modules[i], result.Modules[j]\n\t\treturn strings.Compare(a.Path, b.Path) < 0\n\t})\n\n\tdiff := cmp.Diff(want, result.Modules)\n\tif diff != \"\" {\n\t\tt.Errorf(\"Modules(%v) returned unexpected diff (-want +got):\\n%s\", dir, diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/multi_folder_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\n// TODO(rfindley): update the marker tests to support the concept of multiple\n// workspace folders, and move this there.\nfunc TestMultiView_Diagnostics(t *testing.T) {\n\t// In the past, gopls would only diagnose one View at a time\n\t// (the last to have changed).\n\t//\n\t// This test verifies that gopls can maintain diagnostics for multiple Views.\n\tconst files = `\n\n-- a/go.mod --\nmodule golang.org/lsptests/a\n\ngo 1.20\n-- a/a.go --\npackage a\n\nfunc _() {\n\tx := 1 // unused\n}\n-- b/go.mod --\nmodule golang.org/lsptests/b\n\ngo 1.20\n-- b/b.go --\npackage b\n\nfunc _() {\n\ty := 2 // unused\n}\n`\n\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\", \"b\"),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"y\")),\n\t\t)\n\t})\n}\n\nfunc TestMultiView_LocalReplace(t *testing.T) {\n\t// This is a regression test for #66145, where gopls attempted to load a\n\t// package in a locally replaced module as a workspace package, resulting in\n\t// spurious import diagnostics because the module graph had been pruned.\n\n\tconst proxy = `\n-- example.com/c@v1.2.3/go.mod --\nmodule example.com/c\n\ngo 1.20\n\n-- example.com/c@v1.2.3/c.go --\npackage c\n\nconst C = 3\n\n`\n\t// In the past, gopls would only diagnose one View at a time\n\t// (the last to have changed).\n\t//\n\t// This test verifies that gopls can maintain diagnostics for multiple Views.\n\tconst files = `\n-- a/go.mod --\nmodule golang.org/lsptests/a\n\ngo 1.20\n\nrequire golang.org/lsptests/b v1.2.3\n\nreplace golang.org/lsptests/b => ../b\n\n-- a/a.go --\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nconst A = b.B - 1\n\n-- b/go.mod --\nmodule golang.org/lsptests/b\n\ngo 1.20\n\nrequire example.com/c v1.2.3\n\n-- b/go.sum --\nexample.com/c v1.2.3 h1:hsOPhoHQLZPEn7l3kNya3fR3SfqW0/rafZMP8ave6fg=\nexample.com/c v1.2.3/go.mod h1:4uG6Y5qX88LrEd4KfRoiguHZIbdLKUEHD1wXqPyrHcA=\n-- b/b.go --\npackage b\n\nconst B = 2\n\n-- b/unrelated/u.go --\npackage unrelated\n\nimport \"example.com/c\"\n\nconst U = c.C\n`\n\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\", \"b\"),\n\t\tProxyFiles(proxy),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t// Opening unrelated first ensures that when we compute workspace packages\n\t\t// for the \"a\" workspace, it includes the unrelated package, which will be\n\t\t// unloadable from a as there is no a/go.sum.\n\t\tenv.OpenFile(\"b/unrelated/u.go\")\n\t\tenv.AfterChange()\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/packages_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestPackages(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\n\n-- foo.go --\npackage foo\nfunc Foo()\n\n-- bar/bar.go --\npackage bar\nfunc Bar()\n\n-- baz/go.mod --\nmodule baz\n\n-- baz/baz.go --\npackage baz\nfunc Baz()\n`\n\n\tt.Run(\"file\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"foo.go\")}, false, 0, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{})\n\t\t})\n\t})\n\n\tt.Run(\"package\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"bar\")}, false, 0, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo/bar\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{})\n\t\t})\n\t})\n\n\tt.Run(\"workspace\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"\")}, true, 0, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo/bar\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{})\n\t\t})\n\t})\n\n\tt.Run(\"nested module\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t// Load the nested module\n\t\t\tenv.OpenFile(\"baz/baz.go\")\n\n\t\t\t// Request packages using the URI of the nested module _directory_\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"baz\")}, true, 0, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"baz\",\n\t\t\t\t\tModulePath: \"baz\",\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"baz\": {\n\t\t\t\t\tPath:  \"baz\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"baz/go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{})\n\t\t})\n\t})\n}\n\nfunc TestPackagesWithTests(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\n\n-- foo.go --\npackage foo\nimport \"testing\"\nfunc Foo()\nfunc TestFoo2(t *testing.T)\nfunc foo()\n\n-- foo_test.go --\npackage foo\nimport \"testing\"\nfunc TestFoo(t *testing.T)\nfunc Issue70927(*error)\nfunc Test_foo(t *testing.T)\n\n-- foo2_test.go --\npackage foo_test\nimport \"testing\"\nfunc TestBar(t *testing.T) {}\n\n-- baz/baz_test.go --\npackage baz\nimport \"testing\"\nfunc TestBaz(*testing.T)\nfunc BenchmarkBaz(*testing.B)\nfunc FuzzBaz(*testing.F)\nfunc ExampleBaz()\n\n-- bat/go.mod --\nmodule bat\n\n-- bat/bat_test.go --\npackage bat\nimport \"testing\"\nfunc Test(*testing.T)\n`\n\n\tt.Run(\"file\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"foo_test.go\")}, false, command.NeedTests, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tForTest:    \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestFoo\"},\n\t\t\t\t\t\t\t\t{Name: \"Test_foo\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo_test\",\n\t\t\t\t\tForTest:    \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo2_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestBar\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{\n\t\t\t\t\"func TestFoo(t *testing.T)\",\n\t\t\t\t\"func Test_foo(t *testing.T)\",\n\t\t\t\t\"func TestBar(t *testing.T) {}\",\n\t\t\t})\n\t\t})\n\t})\n\n\tt.Run(\"package\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"baz\")}, false, command.NeedTests, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo/baz\",\n\t\t\t\t\tForTest:    \"foo/baz\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"baz/baz_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"BenchmarkBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"FuzzBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"ExampleBaz\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{\n\t\t\t\t\"func TestBaz(*testing.T)\",\n\t\t\t\t\"func BenchmarkBaz(*testing.B)\",\n\t\t\t\t\"func FuzzBaz(*testing.F)\",\n\t\t\t\t\"func ExampleBaz()\",\n\t\t\t})\n\t\t})\n\t})\n\n\tt.Run(\"workspace\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\".\")}, true, command.NeedTests, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo\",\n\t\t\t\t\tForTest:    \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestFoo\"},\n\t\t\t\t\t\t\t\t{Name: \"Test_foo\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo/baz\",\n\t\t\t\t\tForTest:    \"foo/baz\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"baz/baz_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"BenchmarkBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"FuzzBaz\"},\n\t\t\t\t\t\t\t\t{Name: \"ExampleBaz\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:       \"foo_test\",\n\t\t\t\t\tForTest:    \"foo\",\n\t\t\t\t\tModulePath: \"foo\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo2_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"TestBar\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"foo\": {\n\t\t\t\t\tPath:  \"foo\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{\n\t\t\t\t\"func TestFoo(t *testing.T)\",\n\t\t\t\t\"func Test_foo(t *testing.T)\",\n\t\t\t\t\"func TestBaz(*testing.T)\",\n\t\t\t\t\"func BenchmarkBaz(*testing.B)\",\n\t\t\t\t\"func FuzzBaz(*testing.F)\",\n\t\t\t\t\"func ExampleBaz()\",\n\t\t\t\t\"func TestBar(t *testing.T) {}\",\n\t\t\t})\n\t\t})\n\t})\n\n\tt.Run(\"nested module\", func(t *testing.T) {\n\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t// Load the nested module\n\t\t\tenv.OpenFile(\"bat/bat_test.go\")\n\n\t\t\t// Request packages using the URI of the nested module _directory_\n\t\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"bat\")}, true, command.NeedTests, []command.Package{\n\t\t\t\t{\n\t\t\t\t\tPath:       \"bat\",\n\t\t\t\t\tForTest:    \"bat\",\n\t\t\t\t\tModulePath: \"bat\",\n\t\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"bat/bat_test.go\"),\n\t\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t\t{Name: \"Test\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, map[string]command.Module{\n\t\t\t\t\"bat\": {\n\t\t\t\t\tPath:  \"bat\",\n\t\t\t\t\tGoMod: env.Editor.DocumentURI(\"bat/go.mod\"),\n\t\t\t\t},\n\t\t\t}, []string{\n\t\t\t\t\"func Test(*testing.T)\",\n\t\t\t})\n\t\t})\n\t})\n}\n\nfunc TestPackagesWithSubtests(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\n\n-- foo_test.go --\npackage foo\n\nimport \"testing\"\n\n// Verify that examples don't break subtest detection\nfunc ExampleFoo() {}\n\nfunc TestFoo(t *testing.T) {\n\tt.Run(\"Bar\", func(t *testing.T) {\n\t\tt.Run(\"Baz\", func(t *testing.T) {})\n\t})\n\tt.Run(\"Bar\", func(t *testing.T) {})\n\tt.Run(\"Bar\", func(t *testing.T) {})\n\tt.Run(\"with space\", func(t *testing.T) {})\n\n\tvar x X\n\ty := func(t *testing.T) {\n\t\tt.Run(\"VarSub\", func(t *testing.T) {})\n\t}\n\tt.Run(\"SubtestFunc\", SubtestFunc)\n\tt.Run(\"SubtestMethod\", x.SubtestMethod)\n\tt.Run(\"SubtestVar\", y)\n}\n\nfunc SubtestFunc(t *testing.T) {\n\tt.Run(\"FuncSub\", func(t *testing.T) {})\n}\n\ntype X int\nfunc (X) SubtestMethod(t *testing.T) {\n\tt.Run(\"MethodSub\", func(t *testing.T) {})\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"foo_test.go\")}, false, command.NeedTests, []command.Package{\n\t\t\t{\n\t\t\t\tPath:       \"foo\",\n\t\t\t\tForTest:    \"foo\",\n\t\t\t\tModulePath: \"foo\",\n\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t{\n\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo_test.go\"),\n\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t{Name: \"ExampleFoo\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/Bar\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/Bar/Baz\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/Bar#01\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/Bar#02\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/with_space\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/SubtestFunc\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/SubtestFunc/FuncSub\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/SubtestMethod\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/SubtestMethod/MethodSub\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/SubtestVar\"},\n\t\t\t\t\t\t\t// {Name: \"TestFoo/SubtestVar/VarSub\"}, // TODO\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}, map[string]command.Module{\n\t\t\t\"foo\": {\n\t\t\t\tPath:  \"foo\",\n\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t},\n\t\t}, []string{\n\t\t\t\"func ExampleFoo() {}\",\n\t\t\t`func TestFoo(t *testing.T) {\n\tt.Run(\"Bar\", func(t *testing.T) {\n\t\tt.Run(\"Baz\", func(t *testing.T) {})\n\t})\n\tt.Run(\"Bar\", func(t *testing.T) {})\n\tt.Run(\"Bar\", func(t *testing.T) {})\n\tt.Run(\"with space\", func(t *testing.T) {})\n\n\tvar x X\n\ty := func(t *testing.T) {\n\t\tt.Run(\"VarSub\", func(t *testing.T) {})\n\t}\n\tt.Run(\"SubtestFunc\", SubtestFunc)\n\tt.Run(\"SubtestMethod\", x.SubtestMethod)\n\tt.Run(\"SubtestVar\", y)\n}`,\n\t\t\t\"t.Run(\\\"Bar\\\", func(t *testing.T) {\\n\\t\\tt.Run(\\\"Baz\\\", func(t *testing.T) {})\\n\\t})\",\n\t\t\t`t.Run(\"Baz\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"Bar\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"Bar\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"with space\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"SubtestFunc\", SubtestFunc)`,\n\t\t\t`t.Run(\"FuncSub\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"SubtestMethod\", x.SubtestMethod)`,\n\t\t\t`t.Run(\"MethodSub\", func(t *testing.T) {})`,\n\t\t\t`t.Run(\"SubtestVar\", y)`,\n\t\t})\n\t})\n}\n\nfunc TestRecursiveSubtest(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule foo\n\n-- foo_test.go --\npackage foo\n\nimport \"testing\"\n\nfunc TestFoo(t *testing.T) { t.Run(\"Foo\", TestFoo) }\nfunc TestBar(t *testing.T) { t.Run(\"Foo\", TestFoo) }\n\nfunc TestBaz(t *testing.T) {\n\tvar sub func(t *testing.T)\n\tsub = func(t *testing.T) { t.Run(\"Sub\", sub) }\n\tt.Run(\"Sub\", sub)\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tcheckPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI(\"foo_test.go\")}, false, command.NeedTests, []command.Package{\n\t\t\t{\n\t\t\t\tPath:       \"foo\",\n\t\t\t\tForTest:    \"foo\",\n\t\t\t\tModulePath: \"foo\",\n\t\t\t\tTestFiles: []command.TestFile{\n\t\t\t\t\t{\n\t\t\t\t\t\tURI: env.Editor.DocumentURI(\"foo_test.go\"),\n\t\t\t\t\t\tTests: []command.TestCase{\n\t\t\t\t\t\t\t{Name: \"TestFoo\"},\n\t\t\t\t\t\t\t{Name: \"TestFoo/Foo\"},\n\t\t\t\t\t\t\t{Name: \"TestBar\"},\n\t\t\t\t\t\t\t{Name: \"TestBar/Foo\"},\n\t\t\t\t\t\t\t{Name: \"TestBaz\"},\n\t\t\t\t\t\t\t{Name: \"TestBaz/Sub\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}, map[string]command.Module{\n\t\t\t\"foo\": {\n\t\t\t\tPath:  \"foo\",\n\t\t\t\tGoMod: env.Editor.DocumentURI(\"go.mod\"),\n\t\t\t},\n\t\t}, []string{\n\t\t\t`func TestFoo(t *testing.T) { t.Run(\"Foo\", TestFoo) }`,\n\t\t\t`t.Run(\"Foo\", TestFoo)`,\n\t\t\t`func TestBar(t *testing.T) { t.Run(\"Foo\", TestFoo) }`,\n\t\t\t`t.Run(\"Foo\", TestFoo)`,\n\t\t\t`func TestBaz(t *testing.T) {\n\tvar sub func(t *testing.T)\n\tsub = func(t *testing.T) { t.Run(\"Sub\", sub) }\n\tt.Run(\"Sub\", sub)\n}`,\n\t\t\t`t.Run(\"Sub\", sub)`,\n\t\t})\n\t})\n}\n\nfunc checkPackages(t testing.TB, env *Env, files []protocol.DocumentURI, recursive bool, mode command.PackagesMode, wantPkg []command.Package, wantModule map[string]command.Module, wantSource []string) {\n\tt.Helper()\n\n\tcmd := command.NewPackagesCommand(\"Packages\", command.PackagesArgs{Files: files, Recursive: recursive, Mode: mode})\n\tvar result command.PackagesResult\n\tenv.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\tCommand:   command.Packages.String(),\n\t\tArguments: cmd.Arguments,\n\t}, &result)\n\n\t// The ordering of packages is undefined so sort the results to ensure\n\t// consistency\n\tsort.Slice(result.Packages, func(i, j int) bool {\n\t\ta, b := result.Packages[i], result.Packages[j]\n\t\tc := strings.Compare(a.Path, b.Path)\n\t\tif c != 0 {\n\t\t\treturn c < 0\n\t\t}\n\t\treturn strings.Compare(a.ForTest, b.ForTest) < 0\n\t})\n\n\t// Instead of testing the exact values of the test locations (which would\n\t// make these tests significantly more trouble to maintain), verify the\n\t// source range they refer to.\n\tgotSource := []string{} // avoid issues with comparing null to []\n\tfor i := range result.Packages {\n\t\tpkg := &result.Packages[i]\n\t\tfor i := range pkg.TestFiles {\n\t\t\tfile := &pkg.TestFiles[i]\n\t\t\tenv.OpenFile(file.URI.Path())\n\n\t\t\tfor i := range file.Tests {\n\t\t\t\ttest := &file.Tests[i]\n\t\t\t\tgotSource = append(gotSource, env.FileContentAt(test.Loc))\n\t\t\t\ttest.Loc = protocol.Location{}\n\t\t\t}\n\t\t}\n\t}\n\n\tif diff := cmp.Diff(wantPkg, result.Packages); diff != \"\" {\n\t\tt.Errorf(\"Packages(%v) returned unexpected packages (-want +got):\\n%s\", files, diff)\n\t}\n\n\tif diff := cmp.Diff(wantModule, result.Module); diff != \"\" {\n\t\tt.Errorf(\"Packages(%v) returned unexpected modules (-want +got):\\n%s\", files, diff)\n\t}\n\n\t// Don't check the source if the response is incorrect\n\tif !t.Failed() {\n\t\tif diff := cmp.Diff(wantSource, gotSource); diff != \"\" {\n\t\t\tt.Errorf(\"Packages(%v) returned unexpected test case ranges (-want +got):\\n%s\", files, diff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/quickfix_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestQuickFix_UseModule(t *testing.T) {\n\tt.Skip(\"temporary skip for golang/go#57979: with zero-config gopls these files are no longer orphaned\")\n\n\tconst files = `\n-- go.work --\ngo 1.20\n\nuse (\n\t./a\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main\n\nimport \"mod.com/a/lib\"\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- a/lib/lib.go --\npackage lib\n\nconst C = \"b\"\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main\n\nimport \"mod.com/b/lib\"\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- b/lib/lib.go --\npackage lib\n\nconst C = \"b\"\n`\n\n\tfor _, title := range []string{\n\t\t\"Use this module\",\n\t\t\"Use all modules\",\n\t} {\n\t\tt.Run(title, func(t *testing.T) {\n\t\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"b/main.go\")\n\t\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\t\tenv.AfterChange(ReadDiagnostics(\"b/main.go\", &d))\n\t\t\t\tfixes := env.GetQuickFixes(\"b/main.go\", d.Diagnostics)\n\t\t\t\tvar toApply []protocol.CodeAction\n\t\t\t\tfor _, fix := range fixes {\n\t\t\t\t\tif strings.Contains(fix.Title, title) {\n\t\t\t\t\t\ttoApply = append(toApply, fix)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(toApply) != 1 {\n\t\t\t\t\tt.Fatalf(\"codeAction: got %d quick fixes matching %q, want 1; got: %v\", len(toApply), title, toApply)\n\t\t\t\t}\n\t\t\t\tenv.ApplyCodeAction(toApply[0])\n\t\t\t\tenv.AfterChange(NoDiagnostics())\n\t\t\t\twant := `go 1.20\n\nuse (\n\t./a\n\t./b\n)\n`\n\t\t\t\tgot := env.ReadWorkspaceFile(\"go.work\")\n\t\t\t\tif diff := compare.Text(want, got); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"unexpected go.work content:\\n%s\", diff)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestQuickFix_AddGoWork(t *testing.T) {\n\tt.Skip(\"temporary skip for golang/go#57979: with zero-config gopls these files are no longer orphaned\")\n\n\tconst files = `\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main\n\nimport \"mod.com/a/lib\"\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- a/lib/lib.go --\npackage lib\n\nconst C = \"b\"\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main\n\nimport \"mod.com/b/lib\"\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- b/lib/lib.go --\npackage lib\n\nconst C = \"b\"\n`\n\n\ttests := []struct {\n\t\tname  string\n\t\tfile  string\n\t\ttitle string\n\t\twant  string // expected go.work content, excluding go directive line\n\t}{\n\t\t{\n\t\t\t\"use b\",\n\t\t\t\"b/main.go\",\n\t\t\t\"Add a go.work file using this module\",\n\t\t\t`\nuse ./b\n`,\n\t\t},\n\t\t{\n\t\t\t\"use a\",\n\t\t\t\"a/main.go\",\n\t\t\t\"Add a go.work file using this module\",\n\t\t\t`\nuse ./a\n`,\n\t\t},\n\t\t{\n\t\t\t\"use all\",\n\t\t\t\"a/main.go\",\n\t\t\t\"Add a go.work file using all modules\",\n\t\t\t`\nuse (\n\t./a\n\t./b\n)\n`,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(test.file)\n\t\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\t\tenv.AfterChange(ReadDiagnostics(test.file, &d))\n\t\t\t\tfixes := env.GetQuickFixes(test.file, d.Diagnostics)\n\t\t\t\tvar toApply []protocol.CodeAction\n\t\t\t\tfor _, fix := range fixes {\n\t\t\t\t\tif strings.Contains(fix.Title, test.title) {\n\t\t\t\t\t\ttoApply = append(toApply, fix)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(toApply) != 1 {\n\t\t\t\t\tt.Fatalf(\"codeAction: got %d quick fixes matching %q, want 1; got: %v\", len(toApply), test.title, toApply)\n\t\t\t\t}\n\t\t\t\tenv.ApplyCodeAction(toApply[0])\n\t\t\t\tenv.AfterChange(\n\t\t\t\t\tNoDiagnostics(ForFile(test.file)),\n\t\t\t\t)\n\n\t\t\t\tgot := env.ReadWorkspaceFile(\"go.work\")\n\t\t\t\t// Ignore the `go` directive, which we assume is on the first line of\n\t\t\t\t// the go.work file. This allows the test to be independent of go version.\n\t\t\t\tgot = strings.Join(strings.Split(got, \"\\n\")[1:], \"\\n\")\n\t\t\t\tif diff := compare.Text(test.want, got); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"unexpected go.work content:\\n%s\", diff)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestQuickFix_UnsavedGoWork(t *testing.T) {\n\tt.Skip(\"temporary skip for golang/go#57979: with zero-config gopls these files are no longer orphaned\")\n\n\tconst files = `\n-- go.work --\ngo 1.21\n\nuse (\n\t./a\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main\n\nfunc main() {}\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main\n\nfunc main() {}\n`\n\n\tfor _, title := range []string{\n\t\t\"Use this module\",\n\t\t\"Use all modules\",\n\t} {\n\t\tt.Run(title, func(t *testing.T) {\n\t\t\tRun(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"go.work\")\n\t\t\t\tenv.OpenFile(\"b/main.go\")\n\t\t\t\tenv.RegexpReplace(\"go.work\", \"go 1.21\", \"go 1.21 // arbitrary comment\")\n\t\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\t\tenv.AfterChange(ReadDiagnostics(\"b/main.go\", &d))\n\t\t\t\tfixes := env.GetQuickFixes(\"b/main.go\", d.Diagnostics)\n\t\t\t\tvar toApply []protocol.CodeAction\n\t\t\t\tfor _, fix := range fixes {\n\t\t\t\t\tif strings.Contains(fix.Title, title) {\n\t\t\t\t\t\ttoApply = append(toApply, fix)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(toApply) != 1 {\n\t\t\t\t\tt.Fatalf(\"codeAction: got %d quick fixes matching %q, want 1; got: %v\", len(toApply), title, toApply)\n\t\t\t\t}\n\t\t\t\tfix := toApply[0]\n\t\t\t\terr := env.Editor.ApplyCodeAction(env.Ctx, fix)\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatalf(\"codeAction(%q) succeeded unexpectedly\", fix.Title)\n\t\t\t\t}\n\n\t\t\t\tif got := err.Error(); !strings.Contains(got, \"must save\") {\n\t\t\t\t\tt.Errorf(\"codeAction(%q) returned error %q, want containing \\\"must save\\\"\", fix.Title, err)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestQuickFix_GOWORKOff(t *testing.T) {\n\tt.Skip(\"temporary skip for golang/go#57979: with zero-config gopls these files are no longer orphaned\")\n\n\tconst files = `\n-- go.work --\ngo 1.21\n\nuse (\n\t./a\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main\n\nfunc main() {}\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main\n\nfunc main() {}\n`\n\n\tfor _, title := range []string{\n\t\t\"Use this module\",\n\t\t\"Use all modules\",\n\t} {\n\t\tt.Run(title, func(t *testing.T) {\n\t\t\tWithOptions(\n\t\t\t\tEnvVars{\"GOWORK\": \"off\"},\n\t\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\t\tenv.OpenFile(\"go.work\")\n\t\t\t\tenv.OpenFile(\"b/main.go\")\n\t\t\t\tvar d protocol.PublishDiagnosticsParams\n\t\t\t\tenv.AfterChange(ReadDiagnostics(\"b/main.go\", &d))\n\t\t\t\tfixes := env.GetQuickFixes(\"b/main.go\", d.Diagnostics)\n\t\t\t\tvar toApply []protocol.CodeAction\n\t\t\t\tfor _, fix := range fixes {\n\t\t\t\t\tif strings.Contains(fix.Title, title) {\n\t\t\t\t\t\ttoApply = append(toApply, fix)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(toApply) != 1 {\n\t\t\t\t\tt.Fatalf(\"codeAction: got %d quick fixes matching %q, want 1; got: %v\", len(toApply), title, toApply)\n\t\t\t\t}\n\t\t\t\tfix := toApply[0]\n\t\t\t\terr := env.Editor.ApplyCodeAction(env.Ctx, fix)\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatalf(\"codeAction(%q) succeeded unexpectedly\", fix.Title)\n\t\t\t\t}\n\n\t\t\t\tif got := err.Error(); !strings.Contains(got, \"GOWORK=off\") {\n\t\t\t\t\tt.Errorf(\"codeAction(%q) returned error %q, want containing \\\"GOWORK=off\\\"\", fix.Title, err)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc TestStubMethods64087(t *testing.T) {\n\t// We can't use the @fix or @quickfixerr or @codeaction\n\t// because the error now reported by the corrected logic\n\t// is internal and silently causes no fix to be offered.\n\t//\n\t// See also the similar TestStubMethods64545 below.\n\n\tconst files = `\nThis is a regression test for a panic (issue #64087) in stub methods.\n\nThe illegal expression int(\"\") caused a \"cannot convert\" error that\nspuriously triggered the \"stub methods\" in a function whose return\nstatement had too many operands, leading to an out-of-bounds index.\n\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a.go --\npackage a\n\nfunc f() error {\n\treturn nil, myerror{int(\"\")}\n}\n\ntype myerror struct{any}\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\t// Expect a \"wrong result count\" diagnostic.\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(ReadDiagnostics(\"a.go\", &d))\n\n\t\t// In no particular order, we expect:\n\t\t//  \"...too many return values...\" (compiler)\n\t\t//  \"...cannot convert...\" (compiler)\n\t\t// and possibly:\n\t\t//  \"...too many return values...\" (fillreturns)\n\t\t// We check only for the first of these.\n\t\tfound := false\n\t\tfor i, diag := range d.Diagnostics {\n\t\t\tt.Logf(\"Diagnostics[%d] = %q (%s)\", i, diag.Message, diag.Source)\n\t\t\tif strings.Contains(diag.Message, \"too many return\") {\n\t\t\t\tfound = true\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tt.Fatalf(\"Expected WrongResultCount diagnostic not found.\")\n\t\t}\n\n\t\t// GetQuickFixes should not panic (the original bug).\n\t\tfixes := env.GetQuickFixes(\"a.go\", d.Diagnostics)\n\n\t\t// We should not be offered a \"stub methods\" fix.\n\t\tfor _, fix := range fixes {\n\t\t\tif strings.Contains(fix.Title, \"Implement error\") {\n\t\t\t\tt.Errorf(\"unexpected 'stub methods' fix: %#v\", fix)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestStubMethods64545(t *testing.T) {\n\t// We can't use the @fix or @quickfixerr or @codeaction\n\t// because the error now reported by the corrected logic\n\t// is internal and silently causes no fix to be offered.\n\t//\n\t// TODO(adonovan): we may need to generalize this test and\n\t// TestStubMethods64087 if this happens a lot.\n\n\tconst files = `\nThis is a regression test for a panic (issue #64545) in stub methods.\n\nThe illegal expression int(\"\") caused a \"cannot convert\" error that\nspuriously triggered the \"stub methods\" in a function whose var\nspec had no RHS values, leading to an out-of-bounds index.\n\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a.go --\npackage a\n\nvar _ [int(\"\")]byte\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\n\t\t// Expect a \"cannot convert\" diagnostic, and perhaps others.\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(ReadDiagnostics(\"a.go\", &d))\n\n\t\tfound := false\n\t\tfor i, diag := range d.Diagnostics {\n\t\t\tt.Logf(\"Diagnostics[%d] = %q (%s)\", i, diag.Message, diag.Source)\n\t\t\tif strings.Contains(diag.Message, \"cannot convert\") {\n\t\t\t\tfound = true\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tt.Fatalf(\"Expected 'cannot convert' diagnostic not found.\")\n\t\t}\n\n\t\t// GetQuickFixes should not panic (the original bug).\n\t\tfixes := env.GetQuickFixes(\"a.go\", d.Diagnostics)\n\n\t\t// We should not be offered a \"stub methods\" fix.\n\t\tfor _, fix := range fixes {\n\t\t\tif strings.Contains(fix.Title, \"Implement error\") {\n\t\t\t\tt.Errorf(\"unexpected 'stub methods' fix: %#v\", fix)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// quick fix didn't offer add imports\nfunc TestIssue70755(t *testing.T) {\n\tfiles := `\n-- go.mod --\nmodule failure.com\ngo 1.23\n-- bar/bar.go --\npackage notbar\ntype NotBar struct{}\n-- baz/baz.go --\npackage baz\ntype Baz struct{}\n-- foo/foo.go --\npackage foo\ntype foo struct {\nbar notbar.NotBar\nbzz baz.Baz\n}\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"foo/foo.go\")\n\t\tvar d protocol.PublishDiagnosticsParams\n\t\tenv.AfterChange(ReadDiagnostics(\"foo/foo.go\", &d))\n\t\t// should get two, one for undefined notbar\n\t\t// and one for undefined baz\n\t\tfixes := env.GetQuickFixes(\"foo/foo.go\", d.Diagnostics)\n\t\tif len(fixes) != 2 {\n\t\t\tt.Fatalf(\"got %v, want 2 quick fixes\", fixes)\n\t\t}\n\t\tgood := 0\n\t\tvar failures strings.Builder\n\t\tfor _, f := range fixes {\n\t\t\tti := f.Title\n\t\t\t// these may be overly white-space sensitive\n\t\t\tif ti == \"Add import: notbar \\\"failure.com/bar\\\"\" ||\n\t\t\t\tti == \"Add import:  \\\"failure.com/baz\\\"\" {\n\t\t\t\tgood++\n\t\t\t} else {\n\t\t\t\tfailures.WriteString(ti)\n\t\t\t}\n\t\t}\n\t\tif good != 2 {\n\t\t\tt.Errorf(\"failed to find\\n%q, got\\n%q\\n%q\", failures.String(), fixes[0].Title,\n\t\t\t\tfixes[1].Title)\n\t\t}\n\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/standalone_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"sort\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestStandaloneFiles(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.16\n-- lib/lib.go --\npackage lib\n\nconst K = 0\n\ntype I interface {\n\tM()\n}\n-- lib/ignore.go --\n//go:build ignore\n\npackage main\n\nimport (\n\t\"mod.test/lib\"\n)\n\nconst K = 1\n\ntype Mer struct{}\nfunc (Mer) M()\n\nfunc main() {\n\tprintln(lib.K + K)\n}\n`\n\tWithOptions(\n\t\t// On Go 1.17 and earlier, this test fails with\n\t\t// experimentalWorkspaceModule. Not investigated, as\n\t\t// experimentalWorkspaceModule will be removed.\n\t\tModes(Default),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t// Initially, gopls should not know about the standalone file as it hasn't\n\t\t// been opened. Therefore, we should only find one symbol 'K'.\n\t\t//\n\t\t// (The choice of \"K\" is a little sleazy: it was originally \"C\" until\n\t\t// we started adding \"unsafe\" to the workspace unconditionally, which\n\t\t// caused a spurious match of \"unsafe.Slice\". But in practice every\n\t\t// workspace depends on unsafe.)\n\t\tsyms := env.Symbol(\"K\")\n\t\tif got, want := len(syms), 1; got != want {\n\t\t\tt.Errorf(\"got %d symbols, want %d (%+v)\", got, want, syms)\n\t\t}\n\n\t\t// Similarly, we should only find one reference to \"K\", and no\n\t\t// implementations of I.\n\t\tcheckLocations := func(method string, gotLocations []protocol.Location, wantFiles ...string) {\n\t\t\tvar gotFiles []string\n\t\t\tfor _, l := range gotLocations {\n\t\t\t\tgotFiles = append(gotFiles, env.Sandbox.Workdir.URIToPath(l.URI))\n\t\t\t}\n\t\t\tsort.Strings(gotFiles)\n\t\t\tsort.Strings(wantFiles)\n\t\t\tif diff := cmp.Diff(wantFiles, gotFiles); diff != \"\" {\n\t\t\t\tt.Errorf(\"%s(...): unexpected locations (-want +got):\\n%s\", method, diff)\n\t\t\t}\n\t\t}\n\n\t\tenv.OpenFile(\"lib/lib.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\n\t\t// Replacing K with D should not cause any workspace diagnostics, since we\n\t\t// haven't yet opened the standalone file.\n\t\tenv.RegexpReplace(\"lib/lib.go\", \"K\", \"D\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tenv.RegexpReplace(\"lib/lib.go\", \"D\", \"K\")\n\t\tenv.AfterChange(NoDiagnostics())\n\n\t\trefs := env.References(env.RegexpSearch(\"lib/lib.go\", \"K\"))\n\t\tcheckLocations(\"References\", refs, \"lib/lib.go\")\n\n\t\timpls := env.Implementations(env.RegexpSearch(\"lib/lib.go\", \"I\"))\n\t\tcheckLocations(\"Implementations\", impls) // no implementations\n\n\t\t// Opening the standalone file should not result in any diagnostics.\n\t\tenv.OpenFile(\"lib/ignore.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\n\t\t// Having opened the standalone file, we should find its symbols in the\n\t\t// workspace.\n\t\tsyms = env.Symbol(\"K\")\n\t\tif got, want := len(syms), 2; got != want {\n\t\t\tt.Fatalf(\"got %d symbols, want %d\", got, want)\n\t\t}\n\n\t\tfoundMainK := false\n\t\tvar symNames []string\n\t\tfor _, sym := range syms {\n\t\t\tsymNames = append(symNames, sym.Name)\n\t\t\tif sym.Name == \"main.K\" {\n\t\t\t\tfoundMainK = true\n\t\t\t}\n\t\t}\n\t\tif !foundMainK {\n\t\t\tt.Errorf(\"WorkspaceSymbol(\\\"K\\\") = %v, want containing main.K\", symNames)\n\t\t}\n\n\t\t// We should resolve workspace definitions in the standalone file.\n\t\tfileLoc := env.FirstDefinition(env.RegexpSearch(\"lib/ignore.go\", \"lib.(K)\"))\n\t\tfile := env.Sandbox.Workdir.URIToPath(fileLoc.URI)\n\t\tif got, want := file, \"lib/lib.go\"; got != want {\n\t\t\tt.Errorf(\"Definition(lib.K) = %v, want %v\", got, want)\n\t\t}\n\n\t\t// ...as well as intra-file definitions\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"lib/ignore.go\", \"\\\\+ (K)\"))\n\t\twantLoc := env.RegexpSearch(\"lib/ignore.go\", \"const (K)\")\n\t\tif loc != wantLoc {\n\t\t\tt.Errorf(\"Definition(K) = %v, want %v\", loc, wantLoc)\n\t\t}\n\n\t\t// Renaming \"lib.K\" to \"lib.D\" should cause a diagnostic in the standalone\n\t\t// file.\n\t\tenv.RegexpReplace(\"lib/lib.go\", \"K\", \"D\")\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"lib/ignore.go\", \"lib.(K)\")))\n\n\t\t// Undoing the replacement should fix diagnostics\n\t\tenv.RegexpReplace(\"lib/lib.go\", \"D\", \"K\")\n\t\tenv.AfterChange(NoDiagnostics())\n\n\t\t// Now that our workspace has no errors, we should be able to find\n\t\t// references and rename.\n\t\trefs = env.References(env.RegexpSearch(\"lib/lib.go\", \"K\"))\n\t\tcheckLocations(\"References\", refs, \"lib/lib.go\", \"lib/ignore.go\")\n\n\t\timpls = env.Implementations(env.RegexpSearch(\"lib/lib.go\", \"I\"))\n\t\tcheckLocations(\"Implementations\", impls, \"lib/ignore.go\")\n\n\t\t// Renaming should rename in the standalone package.\n\t\tenv.Rename(env.RegexpSearch(\"lib/lib.go\", \"K\"), \"D\")\n\t\tenv.RegexpSearch(\"lib/ignore.go\", \"lib.D\")\n\t})\n}\n\nfunc TestStandaloneFiles_Configuration(t *testing.T) {\n\tconst files = `\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n-- lib.go --\npackage lib // without this package, files are loaded as command-line-arguments\n-- ignore.go --\n//go:build ignore\n\npackage main\n\n// An arbitrary comment.\n\nfunc main() {}\n-- standalone.go --\n//go:build standalone\n\npackage main\n\nfunc main() {}\n`\n\n\tWithOptions(\n\t\tSettings{\n\t\t\t\"standaloneTags\": []string{\"standalone\", \"script\"},\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"ignore.go\")\n\t\tenv.OpenFile(\"standalone.go\")\n\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"ignore.go\", \"package (main)\")),\n\t\t\tNoDiagnostics(ForFile(\"standalone.go\")),\n\t\t)\n\n\t\tcfg := env.Editor.Config()\n\t\tcfg.Settings = map[string]any{\n\t\t\t\"standaloneTags\": []string{\"ignore\"},\n\t\t}\n\t\tenv.ChangeConfiguration(cfg)\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"ignore.go\")),\n\t\t\tDiagnostics(env.AtRegexp(\"standalone.go\", \"package (main)\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/std_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestStdWorkspace(t *testing.T) {\n\t// This test checks that we actually load workspace packages when opening\n\t// GOROOT.\n\t//\n\t// In golang/go#65801, we failed to do this because go/packages returns nil\n\t// Module for std and cmd.\n\t//\n\t// Because this test loads std as a workspace, it may be slow on smaller\n\t// builders.\n\tif testing.Short() {\n\t\tt.Skip(\"skipping with -short: loads GOROOT\")\n\t}\n\n\t// The test also fails on Windows because an absolute path does not match\n\t// (likely a misspelling due to slashes).\n\t// TODO(rfindley): investigate and fix this on windows.\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"skipping on windows: fails to misspelled paths\")\n\t}\n\n\t// Query GOROOT. This is slightly more precise than e.g. runtime.GOROOT, as\n\t// it queries the go command in the environment.\n\tcmd := exec.Command(\"go\", \"env\", \"GOROOT\")\n\t// Run with GOTOOLCHAIN=local so as to not be affected by toolchain upgrades\n\t// in the current directory (which is affected by gopls' go.mod file).\n\t// This was golang/go#70187\n\tcmd.Env = append(os.Environ(), \"GOTOOLCHAIN=local\")\n\tgoroot, err := cmd.Output()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tstdDir := filepath.Join(strings.TrimSpace(string(goroot)), \"src\")\n\tWithOptions(\n\t\tModes(Default), // This test may be slow. No reason to run it multiple times.\n\t\tWorkspaceFolders(stdDir),\n\t).Run(t, \"\", func(t *testing.T, env *Env) {\n\t\t// Find parser.ParseFile. Query with `'` to get an exact match.\n\t\tsyms := env.Symbol(\"'go/parser.ParseFile\")\n\t\tif len(syms) != 1 {\n\t\t\tt.Fatalf(\"got %d symbols, want exactly 1. Symbols:\\n%v\", len(syms), syms)\n\t\t}\n\t\tparserPath := syms[0].Location.URI.Path()\n\t\tenv.OpenFile(parserPath)\n\n\t\t// Find the reference to ast.File from the signature of ParseFile. This\n\t\t// helps guard against matching a comment.\n\t\tastFile := env.RegexpSearch(parserPath, `func ParseFile\\(.*ast\\.(File)`)\n\t\trefs := env.References(astFile)\n\n\t\t// If we've successfully loaded workspace packages for std, we should find\n\t\t// a reference in go/types.\n\t\tfoundGoTypesReference := false\n\t\tfor _, ref := range refs {\n\t\t\tif strings.Contains(string(ref.URI), \"go/types\") {\n\t\t\t\tfoundGoTypesReference = true\n\t\t\t}\n\t\t}\n\t\tif !foundGoTypesReference {\n\t\t\tt.Errorf(\"references(ast.File) did not return a go/types reference. Refs:\\n%v\", refs)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/vendor_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestWorkspacePackagesExcludesVendor(t *testing.T) {\n\t// This test verifies that packages in the vendor directory are not workspace\n\t// packages. This would be an easy mistake for gopls to make, since mod\n\t// vendoring excludes go.mod files, and therefore the nearest go.mod file for\n\t// vendored packages is often the workspace mod file.\n\tconst proxy = `\n-- other.com/b@v1.0.0/go.mod --\nmodule other.com/b\n\ngo 1.18\n\n-- other.com/b@v1.0.0/b.go --\npackage b\n\ntype B int\n\nfunc _() {\n\tvar V int // unused\n}\n`\n\tconst src = `\n-- go.mod --\nmodule example.com/a\ngo 1.14\nrequire other.com/b v1.0.0\n\n-- a.go --\npackage a\n\nimport \"other.com/b\"\n\nvar _ b.B\n\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t\tModes(Default),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"mod\", \"vendor\")\n\t\t// Uncomment for updated go.sum contents.\n\t\t// env.DumpGoSum(\".\")\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(), // as b is not a workspace package\n\t\t)\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"a.go\", `b\\.(B)`))\n\t\tenv.OpenFile(env.Sandbox.Workdir.URIToPath(loc.URI))\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"vendor/other.com/b/b.go\", \"V\"), WithMessage(\"not used\")),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/workspace_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/goversion\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/testenv\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\tos.Exit(Main(m))\n}\n\nconst workspaceProxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nimport \"fmt\"\n\nfunc SaySomething() {\n\tfmt.Println(\"something\")\n}\n-- random.org@v1.2.3/go.mod --\nmodule random.org\n\ngo 1.12\n-- random.org@v1.2.3/bye/bye.go --\npackage bye\n\nfunc Goodbye() {\n\tprintln(\"Bye\")\n}\n`\n\n// TODO: Add a replace directive.\nconst workspaceModule = `\n-- pkg/go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire (\n\texample.com v1.2.3\n\trandom.org v1.2.3\n)\n-- pkg/go.sum --\nexample.com v1.2.3 h1:veRD4tUnatQRgsULqULZPjeoBGFr2qBhevSCZllD2Ds=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\nrandom.org v1.2.3 h1:+JE2Fkp7gS0zsHXGEQJ7hraom3pNTlkxC4b2qPfA+/Q=\nrandom.org v1.2.3/go.mod h1:E9KM6+bBX2g5ykHZ9H27w16sWo3QwgonyjM44Dnej3I=\n-- pkg/main.go --\npackage main\n\nimport (\n\t\"example.com/blah\"\n\t\"mod.com/inner\"\n\t\"random.org/bye\"\n)\n\nfunc main() {\n\tblah.SaySomething()\n\tinner.Hi()\n\tbye.Goodbye()\n}\n-- pkg/main2.go --\npackage main\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Print(\"%s\")\n}\n-- pkg/inner/inner.go --\npackage inner\n\nimport \"example.com/blah\"\n\nfunc Hi() {\n\tblah.SaySomething()\n}\n-- goodbye/bye/bye.go --\npackage bye\n\nfunc Bye() {}\n-- goodbye/go.mod --\nmodule random.org\n\ngo 1.12\n`\n\n// Confirm that find references returns all of the references in the module,\n// regardless of what the workspace root is.\nfunc TestReferences(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tname, rootPath string\n\t}{\n\t\t{\n\t\t\tname:     \"module root\",\n\t\t\trootPath: \"pkg\",\n\t\t},\n\t\t{\n\t\t\tname:     \"subdirectory\",\n\t\t\trootPath: \"pkg/inner\",\n\t\t},\n\t} {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\topts := []RunOption{ProxyFiles(workspaceProxy)}\n\t\t\tif tt.rootPath != \"\" {\n\t\t\t\topts = append(opts, WorkspaceFolders(tt.rootPath))\n\t\t\t}\n\t\t\tWithOptions(opts...).Run(t, workspaceModule, func(t *testing.T, env *Env) {\n\t\t\t\tf := \"pkg/inner/inner.go\"\n\t\t\t\tenv.OpenFile(f)\n\t\t\t\tlocations := env.References(env.RegexpSearch(f, `SaySomething`))\n\t\t\t\twant := 3\n\t\t\t\tif got := len(locations); got != want {\n\t\t\t\t\tt.Fatalf(\"expected %v locations, got %v\", want, got)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Make sure that analysis diagnostics are cleared for the whole package when\n// the only opened file is closed. This test was inspired by the experience in\n// VS Code, where clicking on a reference result triggers a\n// textDocument/didOpen without a corresponding textDocument/didClose.\nfunc TestClearAnalysisDiagnostics(t *testing.T) {\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tWorkspaceFolders(\"pkg/inner\"),\n\t).Run(t, workspaceModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"pkg/main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"pkg/main2.go\", \"fmt.Print\")),\n\t\t)\n\t\tenv.CloseBuffer(\"pkg/main.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"pkg/main2.go\")),\n\t\t)\n\t})\n}\n\n// TestReloadOnlyOnce checks that changes to the go.mod file do not result in\n// redundant package loads (golang/go#54473).\n//\n// Note that this test may be fragile, as it depends on specific structure to\n// log messages around reinitialization. Nevertheless, it is important for\n// guarding against accidentally duplicate reloading.\nfunc TestReloadOnlyOnce(t *testing.T) {\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t\tWorkspaceFolders(\"pkg\"),\n\t).Run(t, workspaceModule, func(t *testing.T, env *Env) {\n\t\tdir := env.Sandbox.Workdir.URI(\"goodbye\").Path()\n\t\tgoModWithReplace := fmt.Sprintf(`%s\nreplace random.org => %s\n`, env.ReadWorkspaceFile(\"pkg/go.mod\"), dir)\n\t\tenv.WriteWorkspaceFile(\"pkg/go.mod\", goModWithReplace)\n\t\tenv.Await(\n\t\t\tLogMatching(protocol.Info, `packages\\.Load #\\d+\\n`, 2, false),\n\t\t)\n\t})\n}\n\nconst workspaceModuleProxy = `\n-- example.com@v1.2.3/go.mod --\nmodule example.com\n\ngo 1.12\n-- example.com@v1.2.3/blah/blah.go --\npackage blah\n\nimport \"fmt\"\n\nfunc SaySomething() {\n\tfmt.Println(\"something\")\n}\n-- b.com@v1.2.3/go.mod --\nmodule b.com\n\ngo 1.12\n-- b.com@v1.2.3/b/b.go --\npackage b\n\nfunc Hello() {}\n`\n\nconst multiModule = `\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/go.sum --\nb.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=\nb.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n-- modb/go.mod --\nmodule b.com\n\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n`\n\nfunc TestAutomaticWorkspaceModule_Interdependent(t *testing.T) {\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"work\", \"init\")\n\t\tenv.RunGoCommand(\"work\", \"use\", \"-r\", \".\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"moda/a/a.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t\tNoDiagnostics(env.AtRegexp(\"moda/a/a.go\", `\"b.com/b\"`)),\n\t\t)\n\t})\n}\n\nfunc TestWorkspaceVendoring(t *testing.T) {\n\ttestenv.NeedsGoCommand1Point(t, 22)\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"work\", \"init\")\n\t\tenv.RunGoCommand(\"work\", \"use\", \"moda/a\")\n\t\tenv.AfterChange()\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tenv.RunGoCommand(\"work\", \"vendor\")\n\t\tenv.AfterChange()\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"b.(Hello)\"))\n\t\tconst want = \"vendor/b.com/b/b.go\"\n\t\tif got := env.Sandbox.Workdir.URIToPath(loc.URI); got != want {\n\t\t\tt.Errorf(\"Definition: got location %q, want %q\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestModuleWithExclude(t *testing.T) {\n\tconst proxy = `\n-- c.com@v1.2.3/go.mod --\nmodule c.com\n\ngo 1.12\n\nrequire b.com v1.2.3\n-- c.com@v1.2.3/blah/blah.go --\npackage blah\n\nimport \"fmt\"\n\nfunc SaySomething() {\n\tfmt.Println(\"something\")\n}\n-- b.com@v1.2.3/go.mod --\nmodule b.com\n\ngo 1.12\n-- b.com@v1.2.4/b/b.go --\npackage b\n\nfunc Hello() {}\n-- b.com@v1.2.4/go.mod --\nmodule b.com\n\ngo 1.12\n`\n\tconst files = `\n-- go.mod --\nmodule a.com\n\nrequire c.com v1.2.3\n\nexclude b.com v1.2.3\n-- main.go --\npackage a\n\nfunc main() {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\tWriteGoSum(\".\"),\n\t\tProxyFiles(proxy),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tDiagnostics(env.AtRegexp(\"main.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// This change tests that the version of the module used changes after it has\n// been deleted from the workspace.\n//\n// TODO(golang/go#55331): delete this placeholder along with experimental\n// workspace module.\nfunc TestDeleteModule_Interdependent(t *testing.T) {\n\tconst multiModule = `\n-- go.work --\ngo 1.18\n\nuse (\n\tmoda/a\n\tmodb\n)\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/go.sum --\nb.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=\nb.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n-- modb/go.mod --\nmodule b.com\n\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\toriginalLoc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\toriginal := env.Sandbox.Workdir.URIToPath(originalLoc.URI)\n\t\tif want := \"modb/b/b.go\"; !strings.HasSuffix(original, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, original)\n\t\t}\n\t\tenv.AfterChange()\n\n\t\tenv.RemoveWorkspaceFile(\"modb/b/b.go\")\n\t\tenv.RemoveWorkspaceFile(\"modb/go.mod\")\n\t\tenv.WriteWorkspaceFile(\"go.work\", \"go 1.18\\nuse moda/a\")\n\t\tenv.AfterChange()\n\n\t\tgotLoc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\tgot := env.Sandbox.Workdir.URIToPath(gotLoc.URI)\n\t\tif want := \"b.com@v1.2.3/b/b.go\"; !strings.HasSuffix(got, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, got)\n\t\t}\n\t})\n}\n\n// Tests that the version of the module used changes after it has been added\n// to the workspace.\nfunc TestCreateModule_Interdependent(t *testing.T) {\n\tconst multiModule = `\n-- go.work --\ngo 1.18\n\nuse (\n\tmoda/a\n)\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/go.sum --\nb.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=\nb.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\toriginal := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\tif want := \"b.com@v1.2.3/b/b.go\"; !strings.HasSuffix(original, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, original)\n\t\t}\n\t\tenv.WriteWorkspaceFiles(map[string]string{\n\t\t\t\"go.work\": `go 1.18\n\nuse (\n\tmoda/a\n\tmodb\n)\n`,\n\t\t\t\"modb/go.mod\": \"module b.com\",\n\t\t\t\"modb/b/b.go\": `package b\n\nfunc Hello() int {\n\tvar x int\n}\n`,\n\t\t})\n\t\tenv.AfterChange(Diagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")))\n\t\tgotLoc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\tgot := env.Sandbox.Workdir.URIToPath(gotLoc.URI)\n\t\tif want := \"modb/b/b.go\"; !strings.HasSuffix(got, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, original)\n\t\t}\n\t})\n}\n\n// This test confirms that a gopls workspace can recover from initialization\n// with one invalid module.\nfunc TestOneBrokenModule(t *testing.T) {\n\tconst multiModule = `\n-- go.work --\ngo 1.18\n\nuse (\n\tmoda/a\n\tmodb\n)\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n-- modb/go.mod --\nmodul b.com // typo here\n\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"modb/go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(AtPosition(\"modb/go.mod\", 0, 0)),\n\t\t)\n\t\tenv.RegexpReplace(\"modb/go.mod\", \"modul\", \"module\")\n\t\tenv.SaveBufferWithoutActions(\"modb/go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// TestBadGoWork exercises the panic from golang/vscode-go#2121.\nfunc TestBadGoWork(t *testing.T) {\n\tconst files = `\n-- go.work --\nuse ./bar\n-- bar/go.mod --\nmodule example.com/bar\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\t})\n}\n\nfunc TestUseGoWork(t *testing.T) {\n\t// This test validates certain functionality related to using a go.work\n\t// file to specify workspace modules.\n\tconst multiModule = `\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/go.sum --\nb.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=\nb.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n-- modb/go.mod --\nmodule b.com\n\nrequire example.com v1.2.3\n-- modb/go.sum --\nexample.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=\nexample.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n-- go.work --\ngo 1.17\n\nuse (\n\t./moda/a\n)\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t\tSettings{\n\t\t\t\"subdirWatchPatterns\": \"on\",\n\t\t},\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\t// Initially, the go.work should cause only the a.com module to be loaded,\n\t\t// so we shouldn't get any file watches for modb. Further validate this by\n\t\t// jumping to a definition in b.com and ensuring that we go to the module\n\t\t// cache.\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoFileWatchMatching(\"modb\"),\n\t\t)\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\n\t\t// To verify which modules are loaded, we'll jump to the definition of\n\t\t// b.Hello.\n\t\tcheckHelloLocation := func(want string) error {\n\t\t\tloc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\t\tfile := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\t\tif !strings.HasSuffix(file, want) {\n\t\t\t\treturn fmt.Errorf(\"expected %s, got %v\", want, file)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\t// Initially this should be in the module cache, as b.com is not replaced.\n\t\tif err := checkHelloLocation(\"b.com@v1.2.3/b/b.go\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Now, modify the go.work file on disk to activate the b.com module in\n\t\t// the workspace.\n\t\tenv.WriteWorkspaceFile(\"go.work\", `\ngo 1.17\n\nuse (\n\t./moda/a\n\t./modb\n)\n`)\n\n\t\t// As of golang/go#54069, writing go.work to the workspace triggers a\n\t\t// workspace reload, and new file watches.\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t\t// TODO(golang/go#60340): we don't get a file watch yet, because\n\t\t\t// updateWatchedDirectories runs before snapshot.load. Instead, we get it\n\t\t\t// after the next change (the didOpen below).\n\t\t\t// FileWatchMatching(\"modb\"),\n\t\t)\n\n\t\t// Jumping to definition should now go to b.com in the workspace.\n\t\tif err := checkHelloLocation(\"modb/b/b.go\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Now, let's modify the go.work *overlay* (not on disk), and verify that\n\t\t// this change is only picked up once it is saved.\n\t\tenv.OpenFile(\"go.work\")\n\t\tenv.AfterChange(\n\t\t\t// TODO(golang/go#60340): delete this expectation in favor of\n\t\t\t// the commented-out expectation above, once we fix the evaluation order\n\t\t\t// of file watches. We should not have to wait for a second change to get\n\t\t\t// the correct watches.\n\t\t\tFileWatchMatching(\"modb\"),\n\t\t)\n\t\tenv.SetBufferContent(\"go.work\", `go 1.17\n\nuse (\n\t./moda/a\n)`)\n\n\t\t// Simply modifying the go.work file does not cause a reload, so we should\n\t\t// still jump within the workspace.\n\t\t//\n\t\t// TODO: should editing the go.work above cause modb diagnostics to be\n\t\t// suppressed?\n\t\tenv.AfterChange()\n\t\tif err := checkHelloLocation(\"modb/b/b.go\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Saving should reload the workspace.\n\t\tenv.SaveBufferWithoutActions(\"go.work\")\n\t\tif err := checkHelloLocation(\"b.com@v1.2.3/b/b.go\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Since no file in modb is open, there should be no view containing\n\t\t// modb/go.mod, and we should clear its diagnostics.\n\t\tenv.AfterChange(NoDiagnostics(ForFile(\"modb/go.mod\")))\n\n\t\t// Test Formatting.\n\t\tenv.SetBufferContent(\"go.work\", `go 1.18\n  use      (\n\n\n\n\t\t./moda/a\n)\n`) // TODO(matloob): For some reason there's a \"start position 7:0 is out of bounds\" error when the \")\" is on the last character/line in the file. Rob probably knows what's going on.\n\t\tenv.SaveBuffer(\"go.work\")\n\t\tenv.AfterChange()\n\t\tgotWorkContents := env.ReadWorkspaceFile(\"go.work\")\n\t\twantWorkContents := `go 1.18\n\nuse (\n\t./moda/a\n)\n`\n\t\tif gotWorkContents != wantWorkContents {\n\t\t\tt.Fatalf(\"formatted contents of workspace: got %q; want %q\", gotWorkContents, wantWorkContents)\n\t\t}\n\t})\n}\n\nfunc TestUseGoWorkDiagnosticMissingModule(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\n\nuse ./foo\n-- bar/go.mod --\nmodule example.com/bar\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.work\", \"use\"), WithMessage(\"directory ./foo does not contain a module\")),\n\t\t)\n\t\t// The following tests is a regression test against an issue where we weren't\n\t\t// copying the workFile struct field on workspace when a new one was created in\n\t\t// (*workspace).invalidate. Set the buffer content to a working file so that\n\t\t// invalidate recognizes the workspace to be change and copies over the workspace\n\t\t// struct, and then set the content back to the old contents to make sure\n\t\t// the diagnostic still shows up.\n\t\tenv.SetBufferContent(\"go.work\", \"go 1.18 \\n\\n use ./bar\\n\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(env.AtRegexp(\"go.work\", \"use\")),\n\t\t)\n\t\tenv.SetBufferContent(\"go.work\", \"go 1.18 \\n\\n use ./foo\\n\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.work\", \"use\"), WithMessage(\"directory ./foo does not contain a module\")),\n\t\t)\n\t})\n}\n\nfunc TestUseGoWorkDiagnosticSyntaxError(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\n\nusa ./foo\nreplace\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.work\", \"usa\"), WithMessage(\"unknown directive: usa\")),\n\t\t\tDiagnostics(env.AtRegexp(\"go.work\", \"replace\"), WithMessage(\"usage: replace\")),\n\t\t)\n\t})\n}\n\nfunc TestUseGoWorkHover(t *testing.T) {\n\tconst files = `\n-- go.work --\ngo 1.18\n\nuse ./foo\nuse (\n\t./bar\n\t./bar/baz\n)\n-- foo/go.mod --\nmodule example.com/foo\n-- bar/go.mod --\nmodule example.com/bar\n-- bar/baz/go.mod --\nmodule example.com/bar/baz\n`\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"go.work\")\n\n\t\ttcs := map[string]string{\n\t\t\t`\\./foo`:      \"example.com/foo\",\n\t\t\t`(?m)\\./bar$`: \"example.com/bar\",\n\t\t\t`\\./bar/baz`:  \"example.com/bar/baz\",\n\t\t}\n\n\t\tfor hoverRE, want := range tcs {\n\t\t\tgot, _ := env.Hover(env.RegexpSearch(\"go.work\", hoverRE))\n\t\t\tif got.Value != want {\n\t\t\t\tt.Errorf(`hover on %q: got %q, want %q`, hoverRE, got, want)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc TestExpandToGoWork(t *testing.T) {\n\tconst workspace = `\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hello()\n}\n-- modb/go.mod --\nmodule b.com\n\nrequire example.com v1.2.3\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n-- go.work --\ngo 1.17\n\nuse (\n\t./moda/a\n\t./modb\n)\n`\n\tWithOptions(\n\t\tWorkspaceFolders(\"moda/a\"),\n\t).Run(t, workspace, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"moda/a/a.go\")\n\t\tenv.Await(env.DoneWithOpen())\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"moda/a/a.go\", \"Hello\"))\n\t\tfile := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\twant := \"modb/b/b.go\"\n\t\tif !strings.HasSuffix(file, want) {\n\t\t\tt.Errorf(\"expected %s, got %v\", want, file)\n\t\t}\n\t})\n}\n\nfunc TestInnerGoWork(t *testing.T) {\n\t// This test checks that gopls honors a go.work file defined\n\t// inside a go module (golang/go#63917).\n\tconst workspace = `\n-- go.mod --\nmodule a.com\n\nrequire b.com v1.2.3\n-- a/go.work --\ngo 1.18\n\nuse (\n\t..\n\t../b\n)\n-- a/a.go --\npackage a\n\nimport \"b.com/b\"\n\nvar _ = b.B\n-- b/go.mod --\nmodule b.com/b\n\n-- b/b.go --\npackage b\n\nconst B = 0\n`\n\tWithOptions(\n\t\t// This doesn't work if we open the outer module. I'm not sure it should,\n\t\t// since the go.work file does not apply to the entire module, just a\n\t\t// subdirectory.\n\t\tWorkspaceFolders(\"a\"),\n\t).Run(t, workspace, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"a/a.go\", \"b.(B)\"))\n\t\tgot := env.Sandbox.Workdir.URIToPath(loc.URI)\n\t\twant := \"b/b.go\"\n\t\tif got != want {\n\t\t\tt.Errorf(\"Definition(b.B): got %q, want %q\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestNonWorkspaceFileCreation(t *testing.T) {\n\tconst files = `\n-- work/go.mod --\nmodule mod.com\n\ngo 1.12\n-- work/x.go --\npackage x\n`\n\n\tconst code = `\npackage foo\nimport \"fmt\"\nvar _ = fmt.Printf\n`\n\tWithOptions(\n\t\tWorkspaceFolders(\"work\"), // so that outside/... is outside the workspace\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.CreateBuffer(\"outside/foo.go\", \"\")\n\t\tenv.EditBuffer(\"outside/foo.go\", fake.NewEdit(0, 0, 0, 0, code))\n\t\tenv.FirstDefinition(env.RegexpSearch(\"outside/foo.go\", `Printf`))\n\t})\n}\n\nfunc TestGoWork_V2Module(t *testing.T) {\n\t// When using a go.work, we must have proxy content even if it is replaced.\n\tconst proxy = `\n-- b.com/v2@v2.1.9/go.mod --\nmodule b.com/v2\n\ngo 1.12\n-- b.com/v2@v2.1.9/b/b.go --\npackage b\n\nfunc Ciao()() int {\n\treturn 0\n}\n`\n\n\tconst multiModule = `\n-- go.work --\ngo 1.18\n\nuse (\n\tmoda/a\n\tmodb\n\tmodb/v2\n\tmodc\n)\n-- moda/a/go.mod --\nmodule a.com\n\nrequire b.com/v2 v2.1.9\n-- moda/a/a.go --\npackage a\n\nimport (\n\t\"b.com/v2/b\"\n)\n\nfunc main() {\n\tvar x int\n\t_ = b.Hi()\n}\n-- modb/go.mod --\nmodule b.com\n\n-- modb/b/b.go --\npackage b\n\nfunc Hello() int {\n\tvar x int\n}\n-- modb/v2/go.mod --\nmodule b.com/v2\n\n-- modb/v2/b/b.go --\npackage b\n\nfunc Hi() int {\n\tvar x int\n}\n-- modc/go.mod --\nmodule gopkg.in/yaml.v1 // test gopkg.in versions\n-- modc/main.go --\npackage main\n\nfunc main() {\n\tvar x int\n}\n`\n\n\tWithOptions(\n\t\tProxyFiles(proxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\t// TODO(rfindley): assert on the full set of diagnostics here. We\n\t\t\t// should ensure that we don't have a diagnostic at b.Hi in a.go.\n\t\t\tDiagnostics(env.AtRegexp(\"moda/a/a.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"modb/v2/b/b.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"modc/main.go\", \"x\")),\n\t\t)\n\t})\n}\n\n// Confirm that a fix for a tidy module will correct all modules in the\n// workspace.\nfunc TestMultiModule_OneBrokenModule(t *testing.T) {\n\t// In the earlier 'experimental workspace mode', gopls would aggregate go.sum\n\t// entries for the workspace module, allowing it to correctly associate\n\t// missing go.sum with diagnostics. With go.work files, this doesn't work:\n\t// the go.command will happily write go.work.sum.\n\tt.Skip(\"golang/go#57509: go.mod diagnostics do not work in go.work mode\")\n\tconst files = `\n-- go.work --\ngo 1.18\n\nuse (\n\ta\n\tb\n)\n-- go.work.sum --\n-- a/go.mod --\nmodule a.com\n\ngo 1.12\n-- a/main.go --\npackage main\n-- b/go.mod --\nmodule b.com\n\ngo 1.12\n\nrequire (\n\texample.com v1.2.3\n)\n-- b/go.sum --\n-- b/main.go --\npackage b\n\nimport \"example.com/blah\"\n\nfunc main() {\n\tblah.Hello()\n}\n`\n\tWithOptions(\n\t\tProxyFiles(workspaceProxy),\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tparams := &protocol.PublishDiagnosticsParams{}\n\t\tenv.OpenFile(\"b/go.mod\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(\n\t\t\t\tenv.AtRegexp(\"go.mod\", `example.com v1.2.3`),\n\t\t\t\tWithMessage(\"go.sum is out of sync\"),\n\t\t\t),\n\t\t\tReadDiagnostics(\"b/go.mod\", params),\n\t\t)\n\t\tfor _, d := range params.Diagnostics {\n\t\t\tif !strings.Contains(d.Message, \"go.sum is out of sync\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tactions := env.GetQuickFixes(\"b/go.mod\", []protocol.Diagnostic{d})\n\t\t\tif len(actions) != 2 {\n\t\t\t\tt.Fatalf(\"expected 2 code actions, got %v\", len(actions))\n\t\t\t}\n\t\t\tenv.ApplyQuickFixes(\"b/go.mod\", []protocol.Diagnostic{d})\n\t\t}\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"b/go.mod\")),\n\t\t)\n\t})\n}\n\n// Tests the fix for golang/go#52500.\nfunc TestChangeTestVariant_Issue52500(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule mod.test\n\ngo 1.12\n-- main_test.go --\npackage main_test\n\ntype Server struct{}\n\nconst MainConst = otherConst\n-- other_test.go --\npackage main_test\n\nconst otherConst = 0\n\nfunc (Server) Foo() {}\n`\n\n\tRun(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"other_test.go\")\n\t\tenv.RegexpReplace(\"other_test.go\", \"main_test\", \"main\")\n\n\t\t// For this test to function, it is necessary to wait on both of the\n\t\t// expectations below: the bug is that when switching the package name in\n\t\t// other_test.go from main->main_test, metadata for main_test is not marked\n\t\t// as invalid. So we need to wait for the metadata of main_test.go to be\n\t\t// updated before moving other_test.go back to the main_test package.\n\t\tenv.Await(\n\t\t\tDiagnostics(env.AtRegexp(\"other_test.go\", \"Server\")),\n\t\t\tDiagnostics(env.AtRegexp(\"main_test.go\", \"otherConst\")),\n\t\t)\n\t\tenv.RegexpReplace(\"other_test.go\", \"main\", \"main_test\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"other_test.go\")),\n\t\t\tNoDiagnostics(ForFile(\"main_test.go\")),\n\t\t)\n\n\t\t// This will cause a test failure if other_test.go is not in any package.\n\t\t_ = env.FirstDefinition(env.RegexpSearch(\"other_test.go\", \"Server\"))\n\t})\n}\n\n// Test for golang/go#48929.\nfunc TestClearNonWorkspaceDiagnostics(t *testing.T) {\n\tconst ws = `\n-- go.work --\ngo 1.18\n\nuse (\n        ./b\n)\n-- a/go.mod --\nmodule a\n\ngo 1.17\n-- a/main.go --\npackage main\n\nfunc main() {\n   var V string\n}\n-- b/go.mod --\nmodule b\n\ngo 1.17\n-- b/main.go --\npackage b\n\nimport (\n        _ \"fmt\"\n)\n`\n\tRun(t, ws, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"b/main.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/main.go\")),\n\t\t)\n\t\tenv.OpenFile(\"a/main.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/main.go\", \"V\"), WithMessage(\"not used\")),\n\t\t)\n\t\t// Here, diagnostics are added because of zero-config gopls.\n\t\t// In the past, they were added simply due to diagnosing changed files.\n\t\t// (see TestClearNonWorkspaceDiagnostics_NoView below for a\n\t\t// reimplementation of that test).\n\t\tif got, want := len(env.Views()), 2; got != want {\n\t\t\tt.Errorf(\"after opening a/main.go, got %d views, want %d\", got, want)\n\t\t}\n\t\tenv.CloseBuffer(\"a/main.go\")\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"a/main.go\")),\n\t\t)\n\t\tif got, want := len(env.Views()), 1; got != want {\n\t\t\tt.Errorf(\"after closing a/main.go, got %d views, want %d\", got, want)\n\t\t}\n\t})\n}\n\n// This test is like TestClearNonWorkspaceDiagnostics, but bypasses the\n// zero-config algorithm by opening a nested workspace folder.\n//\n// We should still compute diagnostics correctly for open packages.\nfunc TestClearNonWorkspaceDiagnostics_NoView(t *testing.T) {\n\tconst ws = `\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.18\n\nrequire example.com/b v1.2.3\n\nreplace example.com/b => ../b\n\n-- a/a.go --\npackage a\n\nimport \"example.com/b\"\n\nfunc _() {\n\tV := b.B // unused\n}\n\n-- b/go.mod --\nmodule b\n\ngo 1.18\n\n-- b/b.go --\npackage b\n\nconst B = 2\n\nfunc _() {\n\tvar V int // unused\n}\n\n-- b/b2.go --\npackage b\n\nconst B2 = B\n\n-- c/c.go --\npackage main\n\nfunc main() {\n\tvar V int // unused\n}\n`\n\tWithOptions(\n\t\tWorkspaceFolders(\"a\"),\n\t).Run(t, ws, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\t\tenv.OpenFile(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tDiagnostics(env.AtRegexp(\"b/b.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\n\t\t// Opening b/b.go should not result in a new view, because b is not\n\t\t// contained in a workspace folder.\n\t\t//\n\t\t// Yet we should get diagnostics for b, because it is open.\n\t\tif got, want := len(env.Views()), 1; got != want {\n\t\t\tt.Errorf(\"after opening b/b.go, got %d views, want %d\", got, want)\n\t\t}\n\t\tenv.CloseBuffer(\"b/b.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\n\t\t// We should get references in the b package.\n\t\tbUse := env.RegexpSearch(\"a/a.go\", `b\\.(B)`)\n\t\trefs := env.References(bUse)\n\t\twantRefs := []string{\"a/a.go\", \"b/b.go\", \"b/b2.go\"}\n\t\tvar gotRefs []string\n\t\tfor _, ref := range refs {\n\t\t\tgotRefs = append(gotRefs, env.Sandbox.Workdir.URIToPath(ref.URI))\n\t\t}\n\t\tsort.Strings(gotRefs)\n\t\tif diff := cmp.Diff(wantRefs, gotRefs); diff != \"\" {\n\t\t\tt.Errorf(\"references(b.B) mismatch (-want +got)\\n%s\", diff)\n\t\t}\n\n\t\t// Opening c/c.go should also not result in a new view, yet we should get\n\t\t// orphaned file diagnostics.\n\t\tenv.OpenFile(\"c/c.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tDiagnostics(env.AtRegexp(\"c/c.go\", \"V\"), WithMessage(\"not used\")),\n\t\t)\n\t\tif got, want := len(env.Views()), 1; got != want {\n\t\t\tt.Errorf(\"after opening b/b.go, got %d views, want %d\", got, want)\n\t\t}\n\n\t\tenv.CloseBuffer(\"c/c.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\t\tenv.CloseBuffer(\"a/a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"a/a.go\", \"V\"), WithMessage(\"not used\")),\n\t\t\tNoDiagnostics(ForFile(\"b/b.go\")),\n\t\t\tNoDiagnostics(ForFile(\"c/c.go\")),\n\t\t)\n\t})\n}\n\n// Test that we don't get a version warning when the Go version in PATH is\n// supported.\nfunc TestOldGoNotification_SupportedVersion(t *testing.T) {\n\tv := goVersion(t)\n\tif v < goversion.OldestSupported() {\n\t\tt.Skipf(\"go version 1.%d is unsupported\", v)\n\t}\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.OnceMet(\n\t\t\tInitialWorkspaceLoad,\n\t\t\tNoShownMessage(\"upgrade\"),\n\t\t)\n\t})\n}\n\n// Test that we do get a version warning when the Go version in PATH is\n// unsupported, though this test may never execute if we stop running CI at\n// legacy Go versions (see also TestOldGoNotification_Fake)\nfunc TestOldGoNotification_UnsupportedVersion(t *testing.T) {\n\tv := goVersion(t)\n\tif v >= goversion.OldestSupported() {\n\t\tt.Skipf(\"go version 1.%d is supported\", v)\n\t}\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.Await(\n\t\t\t// Note: cannot use OnceMet(InitialWorkspaceLoad, ...) here, as the\n\t\t\t// upgrade message may race with the IWL.\n\t\t\tShownMessage(\"Please upgrade\"),\n\t\t)\n\t})\n}\n\nfunc TestOldGoNotification_Fake(t *testing.T) {\n\t// Get the Go version from path, and make sure it's unsupported.\n\t//\n\t// In the future we'll stop running CI on legacy Go versions. By mutating the\n\t// oldest supported Go version here, we can at least ensure that the\n\t// ShowMessage pop-up works.\n\tctx := context.Background()\n\tversion, err := gocommand.GoVersion(ctx, gocommand.Invocation{}, &gocommand.Runner{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func(t []goversion.Support) {\n\t\tgoversion.Supported = t\n\t}(goversion.Supported)\n\tgoversion.Supported = []goversion.Support{\n\t\t{GoVersion: version, InstallGoplsVersion: \"v1.0.0\"},\n\t}\n\n\tRun(t, \"\", func(t *testing.T, env *Env) {\n\t\tenv.Await(\n\t\t\t// Note: cannot use OnceMet(InitialWorkspaceLoad, ...) here, as the\n\t\t\t// upgrade message may race with the IWL.\n\t\t\tShownMessage(\"Please upgrade\"),\n\t\t)\n\t})\n}\n\n// goVersion returns the version of the Go command in PATH.\nfunc goVersion(t *testing.T) int {\n\tt.Helper()\n\tctx := context.Background()\n\tgoversion, err := gocommand.GoVersion(ctx, gocommand.Invocation{}, &gocommand.Runner{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn goversion\n}\n\nfunc TestGoworkMutation(t *testing.T) {\n\tWithOptions(\n\t\tProxyFiles(workspaceModuleProxy),\n\t).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\tenv.RunGoCommand(\"work\", \"init\")\n\t\tenv.RunGoCommand(\"work\", \"use\", \"-r\", \".\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"moda/a/a.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t\tNoDiagnostics(env.AtRegexp(\"moda/a/a.go\", `b\\.Hello`)),\n\t\t)\n\t\tenv.RunGoCommand(\"work\", \"edit\", \"-dropuse\", \"modb\")\n\t\tenv.Await(\n\t\t\tDiagnostics(env.AtRegexp(\"moda/a/a.go\", \"x\")),\n\t\t\tNoDiagnostics(env.AtRegexp(\"modb/b/b.go\", \"x\")),\n\t\t\tDiagnostics(env.AtRegexp(\"moda/a/a.go\", `b\\.Hello`)),\n\t\t)\n\t})\n}\n\nfunc TestInitializeWithNonFileWorkspaceFolders(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tname          string\n\t\tfolders       []string\n\t\twantViewRoots []string\n\t}{\n\t\t{\n\t\t\tname:          \"real,virtual\",\n\t\t\tfolders:       []string{\"modb\", \"virtual:///virtualpath\"},\n\t\t\twantViewRoots: []string{\"./modb\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"virtual,real\",\n\t\t\tfolders:       []string{\"virtual:///virtualpath\", \"modb\"},\n\t\t\twantViewRoots: []string{\"./modb\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"real,virtual,real\",\n\t\t\tfolders:       []string{\"moda/a\", \"virtual:///virtualpath\", \"modb\"},\n\t\t\twantViewRoots: []string{\"./moda/a\", \"./modb\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"virtual\",\n\t\t\tfolders:       []string{\"virtual:///virtualpath\"},\n\t\t\twantViewRoots: nil,\n\t\t},\n\t} {\n\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\topts := []RunOption{ProxyFiles(workspaceProxy), WorkspaceFolders(tt.folders...)}\n\t\t\tWithOptions(opts...).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\t\t\tsummary := func(typ cache.ViewType, root, folder string) command.View {\n\t\t\t\t\treturn command.View{\n\t\t\t\t\t\tType:   typ.String(),\n\t\t\t\t\t\tRoot:   env.Sandbox.Workdir.URI(root),\n\t\t\t\t\t\tFolder: env.Sandbox.Workdir.URI(folder),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcheckViews := func(want ...command.View) {\n\t\t\t\t\tgot := env.Views()\n\t\t\t\t\tif diff := cmp.Diff(want, got, cmpopts.IgnoreFields(command.View{}, \"ID\")); diff != \"\" {\n\t\t\t\t\t\tt.Errorf(\"SummarizeViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar wantViews []command.View\n\t\t\t\tfor _, root := range tt.wantViewRoots {\n\t\t\t\t\twantViews = append(wantViews, summary(cache.GoModView, root, root))\n\t\t\t\t}\n\t\t\t\tenv.Await(\n\t\t\t\t\tLogMatching(protocol.Warning, \"skip adding virtual folder\", 1, false),\n\t\t\t\t)\n\t\t\t\tcheckViews(wantViews...)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// TestChangeAddedWorkspaceFolders tests issue71967 which an editor sends the following requests.\n//\n//  1. send an initialization request with rootURI but no workspaceFolders,\n//     which gopls helps to find a workspaceFolders for it.\n//  2. send a DidChangeWorkspaceFolders request with the exact the same folder gopls helps to find.\n//\n// It uses the same approach to simulate the scenario, and ensure we can skip the already added file.\nfunc TestChangeAddedWorkspaceFolders(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tname          string\n\t\tafter         []string\n\t\twantViewRoots []string\n\t}{\n\t\t{\n\t\t\tname:          \"add an already added file\",\n\t\t\tafter:         []string{\"modb\"},\n\t\t\twantViewRoots: []string{\"./modb\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"add an already added file but with an ending slash\",\n\t\t\tafter:         []string{\"modb/\"},\n\t\t\twantViewRoots: []string{\"./modb\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"add an already added file and a new file\",\n\t\t\tafter:         []string{\"modb\", \"moda/a\"},\n\t\t\twantViewRoots: []string{\"./modb\", \"moda/a\"},\n\t\t},\n\t} {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\topts := []RunOption{ProxyFiles(workspaceProxy), RootPath(\"modb\"), NoDefaultWorkspaceFiles()}\n\t\t\tWithOptions(opts...).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\t\t\tsummary := func(typ cache.ViewType, root, folder string) command.View {\n\t\t\t\t\treturn command.View{\n\t\t\t\t\t\tType:   typ.String(),\n\t\t\t\t\t\tRoot:   env.Sandbox.Workdir.URI(root),\n\t\t\t\t\t\tFolder: env.Sandbox.Workdir.URI(folder),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcheckViews := func(want ...command.View) {\n\t\t\t\t\tgot := env.Views()\n\t\t\t\t\tif diff := cmp.Diff(want, got, cmpopts.IgnoreFields(command.View{}, \"ID\")); diff != \"\" {\n\t\t\t\t\t\tt.Errorf(\"SummarizeViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar wantViews []command.View\n\t\t\t\tfor _, root := range tt.wantViewRoots {\n\t\t\t\t\twantViews = append(wantViews, summary(cache.GoModView, root, root))\n\t\t\t\t}\n\t\t\t\tenv.ChangeWorkspaceFolders(tt.after...)\n\t\t\t\tenv.Await(\n\t\t\t\t\tLogMatching(protocol.Warning, \"skip adding the already added folder\", 1, false),\n\t\t\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\t\t)\n\t\t\t\tcheckViews(wantViews...)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Test that non-file scheme Document URIs in ChangeWorkspaceFolders\n// notification does not produce errors.\nfunc TestChangeNonFileWorkspaceFolders(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tname          string\n\t\tbefore        []string\n\t\tafter         []string\n\t\twantViewRoots []string\n\t}{\n\t\t{\n\t\t\tname:          \"add\",\n\t\t\tbefore:        []string{\"modb\"},\n\t\t\tafter:         []string{\"modb\", \"moda/a\", \"virtual:///virtualpath\"},\n\t\t\twantViewRoots: []string{\"./modb\", \"moda/a\"},\n\t\t},\n\t\t{\n\t\t\tname:          \"remove\",\n\t\t\tbefore:        []string{\"modb\", \"virtual:///virtualpath\", \"moda/a\"},\n\t\t\tafter:         []string{\"modb\"},\n\t\t\twantViewRoots: []string{\"./modb\"},\n\t\t},\n\t} {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\topts := []RunOption{ProxyFiles(workspaceProxy), WorkspaceFolders(tt.before...)}\n\t\t\tWithOptions(opts...).Run(t, multiModule, func(t *testing.T, env *Env) {\n\t\t\t\tsummary := func(typ cache.ViewType, root, folder string) command.View {\n\t\t\t\t\treturn command.View{\n\t\t\t\t\t\tType:   typ.String(),\n\t\t\t\t\t\tRoot:   env.Sandbox.Workdir.URI(root),\n\t\t\t\t\t\tFolder: env.Sandbox.Workdir.URI(folder),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcheckViews := func(want ...command.View) {\n\t\t\t\t\tgot := env.Views()\n\t\t\t\t\tif diff := cmp.Diff(want, got, cmpopts.IgnoreFields(command.View{}, \"ID\")); diff != \"\" {\n\t\t\t\t\t\tt.Errorf(\"SummarizeViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar wantViews []command.View\n\t\t\t\tfor _, root := range tt.wantViewRoots {\n\t\t\t\t\twantViews = append(wantViews, summary(cache.GoModView, root, root))\n\t\t\t\t}\n\t\t\t\tenv.ChangeWorkspaceFolders(tt.after...)\n\t\t\t\tenv.Await(\n\t\t\t\t\tLogMatching(protocol.Warning, \"skip adding virtual folder\", 1, false),\n\t\t\t\t\tNoOutstandingWork(IgnoreTelemetryPromptWork),\n\t\t\t\t)\n\t\t\t\tcheckViews(wantViews...)\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/workspace/zero_config_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage workspace\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\n\t. \"golang.org/x/tools/gopls/internal/test/integration\"\n)\n\nfunc TestAddAndRemoveGoWork(t *testing.T) {\n\t// Use a workspace with a module in the root directory to exercise the case\n\t// where a go.work is added to the existing root directory. This verifies\n\t// that we're detecting changes to the module source, not just the root\n\t// directory.\n\tconst nomod = `\n-- go.mod --\nmodule a.com\n\ngo 1.16\n-- main.go --\npackage main\n\nfunc main() {}\n-- b/go.mod --\nmodule b.com\n\ngo 1.16\n-- b/main.go --\npackage main\n\nfunc main() {}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t).Run(t, nomod, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"main.go\")\n\t\tenv.OpenFile(\"b/main.go\")\n\n\t\tsummary := func(typ cache.ViewType, root, folder string) command.View {\n\t\t\treturn command.View{\n\t\t\t\tType:   typ.String(),\n\t\t\t\tRoot:   env.Sandbox.Workdir.URI(root),\n\t\t\t\tFolder: env.Sandbox.Workdir.URI(folder),\n\t\t\t}\n\t\t}\n\t\tcheckViews := func(want ...command.View) {\n\t\t\tgot := env.Views()\n\t\t\tif diff := cmp.Diff(want, got, cmpopts.IgnoreFields(command.View{}, \"ID\")); diff != \"\" {\n\t\t\t\tt.Errorf(\"SummarizeViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\n\t\t// Zero-config gopls makes this work.\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\tNoDiagnostics(env.AtRegexp(\"b/main.go\", \"package (main)\")),\n\t\t)\n\t\tcheckViews(summary(cache.GoModView, \".\", \".\"), summary(cache.GoModView, \"b\", \".\"))\n\n\t\tenv.WriteWorkspaceFile(\"go.work\", `go 1.16\n\nuse (\n\t.\n\tb\n)\n`)\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tcheckViews(summary(cache.GoWorkView, \".\", \".\"))\n\n\t\t// Removing the go.work file should put us back where we started.\n\t\tenv.RemoveWorkspaceFile(\"go.work\")\n\n\t\t// Again, zero-config gopls makes this work.\n\t\tenv.AfterChange(\n\t\t\tNoDiagnostics(ForFile(\"main.go\")),\n\t\t\tNoDiagnostics(env.AtRegexp(\"b/main.go\", \"package (main)\")),\n\t\t)\n\t\tcheckViews(summary(cache.GoModView, \".\", \".\"), summary(cache.GoModView, \"b\", \".\"))\n\n\t\t// Close and reopen b, to ensure the views are adjusted accordingly.\n\t\tenv.CloseBuffer(\"b/main.go\")\n\t\tenv.AfterChange()\n\t\tcheckViews(summary(cache.GoModView, \".\", \".\"))\n\n\t\tenv.OpenFile(\"b/main.go\")\n\t\tenv.AfterChange()\n\t\tcheckViews(summary(cache.GoModView, \".\", \".\"), summary(cache.GoModView, \"b\", \".\"))\n\t})\n}\n\nfunc TestOpenAndClosePorts(t *testing.T) {\n\t// This test checks that as we open and close files requiring a different\n\t// port, the set of Views is adjusted accordingly.\n\tconst files = `\n-- go.mod --\nmodule a.com/a\n\ngo 1.20\n\n-- a_linux.go --\npackage a\n\n-- a_darwin.go --\npackage a\n\n-- a_windows.go --\npackage a\n`\n\n\tWithOptions(\n\t\tEnvVars{\n\t\t\t\"GOOS\": \"linux\", // assume that linux is the default GOOS\n\t\t},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tsummary := func(envOverlay ...string) command.View {\n\t\t\treturn command.View{\n\t\t\t\tType:       cache.GoModView.String(),\n\t\t\t\tRoot:       env.Sandbox.Workdir.URI(\".\"),\n\t\t\t\tFolder:     env.Sandbox.Workdir.URI(\".\"),\n\t\t\t\tEnvOverlay: envOverlay,\n\t\t\t}\n\t\t}\n\t\tcheckViews := func(want ...command.View) {\n\t\t\tgot := env.Views()\n\t\t\tif diff := cmp.Diff(want, got, cmpopts.IgnoreFields(command.View{}, \"ID\")); diff != \"\" {\n\t\t\t\tt.Errorf(\"SummarizeViews() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\t\tcheckViews(summary())\n\t\tenv.OpenFile(\"a_linux.go\")\n\t\tcheckViews(summary())\n\t\tenv.OpenFile(\"a_darwin.go\")\n\t\tcheckViews(\n\t\t\tsummary(),\n\t\t\tsummary(\"GOARCH=amd64\", \"GOOS=darwin\"),\n\t\t)\n\t\tenv.OpenFile(\"a_windows.go\")\n\t\tcheckViews(\n\t\t\tsummary(),\n\t\t\tsummary(\"GOARCH=amd64\", \"GOOS=darwin\"),\n\t\t\tsummary(\"GOARCH=amd64\", \"GOOS=windows\"),\n\t\t)\n\t\tenv.CloseBuffer(\"a_darwin.go\")\n\t\tcheckViews(\n\t\t\tsummary(),\n\t\t\tsummary(\"GOARCH=amd64\", \"GOOS=windows\"),\n\t\t)\n\t\tenv.CloseBuffer(\"a_linux.go\")\n\t\tcheckViews(\n\t\t\tsummary(),\n\t\t\tsummary(\"GOARCH=amd64\", \"GOOS=windows\"),\n\t\t)\n\t\tenv.CloseBuffer(\"a_windows.go\")\n\t\tcheckViews(summary())\n\t})\n}\n\nfunc TestCriticalErrorsInOrphanedFiles(t *testing.T) {\n\t// This test checks that as we open and close files requiring a different\n\t// port, the set of Views is adjusted accordingly.\n\tconst files = `\n-- go.mod --\nmodul golang.org/lsptests/broken\n\ngo 1.20\n\n-- a.go --\npackage broken\n\nconst C = 0\n`\n\n\tRun(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"go.mod\", \"modul\")),\n\t\t\tDiagnostics(env.AtRegexp(\"a.go\", \"broken\"), WithMessage(\"initialization failed\")),\n\t\t)\n\t})\n}\n\nfunc TestGoModReplace(t *testing.T) {\n\t// This test checks that we treat locally replaced modules as workspace\n\t// modules, according to the \"includeReplaceInWorkspace\" setting.\n\tconst files = `\n-- moda/go.mod --\nmodule golang.org/a\n\nrequire golang.org/b v1.2.3\n\nreplace golang.org/b => ../modb\n\ngo 1.20\n\n-- moda/a.go --\npackage a\n\nimport \"golang.org/b\"\n\nconst A = b.B\n\n-- modb/go.mod --\nmodule golang.org/b\n\ngo 1.20\n\n-- modb/b.go --\npackage b\n\nconst B = 1\n`\n\n\tfor useReplace, expectation := range map[bool]Expectation{\n\t\ttrue:  FileWatchMatching(\"modb\"),\n\t\tfalse: NoFileWatchMatching(\"modb\"),\n\t} {\n\t\tWithOptions(\n\t\t\tWorkspaceFolders(\"moda\"),\n\t\t\tSettings{\n\t\t\t\t\"includeReplaceInWorkspace\": useReplace,\n\t\t\t},\n\t\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\t\tenv.OnceMet(\n\t\t\t\tInitialWorkspaceLoad,\n\t\t\t\texpectation,\n\t\t\t)\n\t\t})\n\t}\n}\n\nfunc TestDisableZeroConfig(t *testing.T) {\n\t// This test checks that we treat locally replaced modules as workspace\n\t// modules, according to the \"includeReplaceInWorkspace\" setting.\n\tconst files = `\n-- moda/go.mod --\nmodule golang.org/a\n\ngo 1.20\n\n-- moda/a.go --\npackage a\n\n-- modb/go.mod --\nmodule golang.org/b\n\ngo 1.20\n\n-- modb/b.go --\npackage b\n\n`\n\n\tWithOptions(\n\t\tSettings{\"zeroConfig\": false},\n\t).Run(t, files, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"moda/a.go\")\n\t\tenv.OpenFile(\"modb/b.go\")\n\t\tenv.AfterChange()\n\t\tif got := env.Views(); len(got) != 1 || got[0].Type != cache.AdHocView.String() {\n\t\t\tt.Errorf(\"Views: got %v, want one adhoc view\", got)\n\t\t}\n\t})\n}\n\nfunc TestVendorExcluded(t *testing.T) {\n\t// Test that we don't create Views for vendored modules.\n\t//\n\t// We construct the vendor directory manually here, as `go mod vendor` will\n\t// omit the go.mod file. This synthesizes the setup of Kubernetes, where the\n\t// entire module is vendored through a symlinked directory.\n\tconst src = `\n-- go.mod --\nmodule example.com/a\n\ngo 1.18\n\nrequire other.com/b v1.0.0\n\n-- a.go --\npackage a\nimport \"other.com/b\"\nvar _ b.B\n\n-- vendor/modules.txt --\n# other.com/b v1.0.0\n## explicit; go 1.14\nother.com/b\n\n-- vendor/other.com/b/go.mod --\nmodule other.com/b\ngo 1.14\n\n-- vendor/other.com/b/b.go --\npackage b\ntype B int\n\nfunc _() {\n\tvar V int // unused\n}\n`\n\tWithOptions(\n\t\tModes(Default),\n\t).Run(t, src, func(t *testing.T, env *Env) {\n\t\tenv.OpenFile(\"a.go\")\n\t\tenv.AfterChange(NoDiagnostics())\n\t\tloc := env.FirstDefinition(env.RegexpSearch(\"a.go\", `b\\.(B)`))\n\t\tif !strings.Contains(string(loc.URI), \"/vendor/\") {\n\t\t\tt.Fatalf(\"Definition(b.B) = %v, want vendored location\", loc.URI)\n\t\t}\n\t\tenv.OpenFile(env.Sandbox.Workdir.URIToPath(loc.URI))\n\t\tenv.AfterChange(\n\t\t\tDiagnostics(env.AtRegexp(\"vendor/other.com/b/b.go\", \"V\"), WithMessage(\"not used\")),\n\t\t)\n\n\t\tif views := env.Views(); len(views) != 1 {\n\t\t\tt.Errorf(\"After opening /vendor/, got %d views, want 1. Views:\\n%v\", len(views), views)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/test/integration/wrappers.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage integration\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"path\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/protocol/command\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// RemoveWorkspaceFile deletes a file on disk but does nothing in the\n// editor. It calls t.Fatal on any error.\nfunc (e *Env) RemoveWorkspaceFile(name string) {\n\te.TB.Helper()\n\tif err := e.Sandbox.Workdir.RemoveFile(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ReadWorkspaceFile reads a file from the workspace, calling t.Fatal on any\n// error.\nfunc (e *Env) ReadWorkspaceFile(name string) string {\n\te.TB.Helper()\n\tcontent, err := e.Sandbox.Workdir.ReadFile(name)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn string(content)\n}\n\n// WriteWorkspaceFile writes a file to disk but does nothing in the editor.\n// It calls t.Fatal on any error.\nfunc (e *Env) WriteWorkspaceFile(name, content string) {\n\te.TB.Helper()\n\tif err := e.Sandbox.Workdir.WriteFile(e.Ctx, name, content); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// WriteWorkspaceFiles deletes a file on disk but does nothing in the\n// editor. It calls t.Fatal on any error.\nfunc (e *Env) WriteWorkspaceFiles(files map[string]string) {\n\te.TB.Helper()\n\tif err := e.Sandbox.Workdir.WriteFiles(e.Ctx, files); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ListFiles lists relative paths to files in the given directory.\n// It calls t.Fatal on any error.\nfunc (e *Env) ListFiles(dir string) []string {\n\te.TB.Helper()\n\tpaths, err := e.Sandbox.Workdir.ListFiles(dir)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn paths\n}\n\n// OpenFile opens a file in the editor, calling t.Fatal on any error.\nfunc (e *Env) OpenFile(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.OpenFile(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// CreateBuffer creates a buffer in the editor, calling t.Fatal on any error.\nfunc (e *Env) CreateBuffer(name string, content string) {\n\te.TB.Helper()\n\tif err := e.Editor.CreateBuffer(e.Ctx, name, content); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// BufferText returns the current buffer contents for the file with the given\n// relative path, calling t.Fatal if the file is not open in a buffer.\nfunc (e *Env) BufferText(name string) string {\n\te.TB.Helper()\n\ttext, ok := e.Editor.BufferText(name)\n\tif !ok {\n\t\te.TB.Fatalf(\"buffer %q is not open\", name)\n\t}\n\treturn text\n}\n\n// CloseBuffer closes an editor buffer without saving, calling t.Fatal on any\n// error.\nfunc (e *Env) CloseBuffer(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.CloseBuffer(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// EditBuffer applies edits to an editor buffer, calling t.Fatal on any error.\nfunc (e *Env) EditBuffer(name string, edits ...protocol.TextEdit) {\n\te.TB.Helper()\n\tif err := e.Editor.EditBuffer(e.Ctx, name, edits); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\nfunc (e *Env) SetBufferContent(name string, content string) {\n\te.TB.Helper()\n\tif err := e.Editor.SetBufferContent(e.Ctx, name, content); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// FileContent returns the file content for name that applies to the current\n// editing session: it returns the buffer content for an open file, the\n// on-disk content for an unopened file, or \"\" for a non-existent file.\nfunc (e *Env) FileContent(name string) string {\n\te.TB.Helper()\n\ttext, ok := e.Editor.BufferText(name)\n\tif ok {\n\t\treturn text\n\t}\n\tcontent, err := e.Sandbox.Workdir.ReadFile(name)\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\treturn \"\"\n\t\t} else {\n\t\t\te.TB.Fatal(err)\n\t\t}\n\t}\n\treturn string(content)\n}\n\n// FileContentAt returns the file content at the given location, using the\n// file's mapper.\nfunc (e *Env) FileContentAt(location protocol.Location) string {\n\te.TB.Helper()\n\tmapper, err := e.Editor.Mapper(location.URI.Path())\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\tstart, end, err := mapper.RangeOffsets(location.Range)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn string(mapper.Content[start:end])\n}\n\n// RegexpSearch returns the starting position of the first match for re in the\n// buffer specified by name, calling t.Fatal on any error. It first searches\n// for the position in open buffers, then in workspace files.\nfunc (e *Env) RegexpSearch(name, re string) protocol.Location {\n\te.TB.Helper()\n\tloc, err := e.Editor.RegexpSearch(name, re)\n\tif err == fake.ErrUnknownBuffer {\n\t\tloc, err = e.Sandbox.Workdir.RegexpSearch(name, re)\n\t}\n\tif err != nil {\n\t\te.TB.Fatalf(\"RegexpSearch: %v, %v for %q\", name, err, re)\n\t}\n\treturn loc\n}\n\n// RegexpReplace replaces the first group in the first match of regexpStr with\n// the replace text, calling t.Fatal on any error.\nfunc (e *Env) RegexpReplace(name, regexpStr, replace string) {\n\te.TB.Helper()\n\tif err := e.Editor.RegexpReplace(e.Ctx, name, regexpStr, replace); err != nil {\n\t\te.TB.Fatalf(\"RegexpReplace: %v\", err)\n\t}\n}\n\n// SaveBuffer saves an editor buffer, calling t.Fatal on any error.\nfunc (e *Env) SaveBuffer(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.SaveBuffer(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\nfunc (e *Env) SaveBufferWithoutActions(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.SaveBufferWithoutActions(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// FirstDefinition returns the first definition of the symbol at the\n// selected location, calling t.Fatal on error.\nfunc (e *Env) FirstDefinition(loc protocol.Location) protocol.Location {\n\te.TB.Helper()\n\tlocs, err := e.Editor.Definitions(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\tif len(locs) == 0 {\n\t\te.TB.Fatalf(\"no definitions\")\n\t}\n\treturn locs[0]\n}\n\n// FirstTypeDefinition returns the first type definition of the symbol\n// at the selected location, calling t.Fatal on error.\nfunc (e *Env) FirstTypeDefinition(loc protocol.Location) protocol.Location {\n\te.TB.Helper()\n\tlocs, err := e.Editor.TypeDefinitions(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\tif len(locs) == 0 {\n\t\te.TB.Fatalf(\"no type definitions\")\n\t}\n\treturn locs[0]\n}\n\n// FormatBuffer formats the editor buffer, calling t.Fatal on any error.\nfunc (e *Env) FormatBuffer(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.FormatBuffer(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// OrganizeImports processes the source.organizeImports codeAction, calling\n// t.Fatal on any error.\nfunc (e *Env) OrganizeImports(name string) {\n\te.TB.Helper()\n\tif err := e.Editor.OrganizeImports(e.Ctx, name); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ApplyQuickFixes processes the quickfix codeAction, calling t.Fatal on any error.\nfunc (e *Env) ApplyQuickFixes(path string, diagnostics []protocol.Diagnostic) {\n\te.TB.Helper()\n\tloc := e.Sandbox.Workdir.EntireFile(path)\n\tif err := e.Editor.ApplyQuickFixes(e.Ctx, loc, diagnostics); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ApplyCodeAction applies the given code action, calling t.Fatal on any error.\nfunc (e *Env) ApplyCodeAction(action protocol.CodeAction) {\n\te.TB.Helper()\n\tif err := e.Editor.ApplyCodeAction(e.Ctx, action); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// Diagnostics returns diagnostics for the given file, calling t.Fatal on any\n// error.\nfunc (e *Env) Diagnostics(name string) []protocol.Diagnostic {\n\te.TB.Helper()\n\tdiags, err := e.Editor.Diagnostics(e.Ctx, name)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn diags\n}\n\n// GetQuickFixes returns the available quick fix code actions, calling t.Fatal\n// on any error.\nfunc (e *Env) GetQuickFixes(path string, diagnostics []protocol.Diagnostic) []protocol.CodeAction {\n\te.TB.Helper()\n\tloc := e.Sandbox.Workdir.EntireFile(path)\n\tactions, err := e.Editor.GetQuickFixes(e.Ctx, loc, diagnostics)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn actions\n}\n\n// Hover in the editor, calling t.Fatal on any error.\n// It may return (nil, zero) even on success.\nfunc (e *Env) Hover(loc protocol.Location) (*protocol.MarkupContent, protocol.Location) {\n\te.TB.Helper()\n\tc, loc, err := e.Editor.Hover(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn c, loc\n}\n\nfunc (e *Env) DocumentLink(name string) []protocol.DocumentLink {\n\te.TB.Helper()\n\tlinks, err := e.Editor.DocumentLink(e.Ctx, name)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn links\n}\n\nfunc (e *Env) DocumentHighlight(loc protocol.Location) []protocol.DocumentHighlight {\n\te.TB.Helper()\n\thighlights, err := e.Editor.DocumentHighlight(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn highlights\n}\n\n// RunGenerate runs \"go generate\" in the given dir, calling t.Fatal on any error.\n// It waits for the generate command to complete and checks for file changes\n// before returning.\nfunc (e *Env) RunGenerate(dir string) {\n\te.TB.Helper()\n\tif err := e.Editor.RunGenerate(e.Ctx, dir); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\te.Await(NoOutstandingWork(IgnoreTelemetryPromptWork))\n\t// Ideally the editor.Workspace would handle all synthetic file watching, but\n\t// we help it out here as we need to wait for the generate command to\n\t// complete before checking the filesystem.\n\te.CheckForFileChanges()\n}\n\n// RunGoCommand runs the given command in the sandbox's default working\n// directory.\nfunc (e *Env) RunGoCommand(verb string, args ...string) []byte {\n\te.TB.Helper()\n\tout, err := e.Sandbox.RunGoCommand(e.Ctx, \"\", verb, args, nil, true)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn out\n}\n\n// RunGoCommandInDir is like RunGoCommand, but executes in the given\n// relative directory of the sandbox.\nfunc (e *Env) RunGoCommandInDir(dir, verb string, args ...string) {\n\te.TB.Helper()\n\tif _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, nil, true); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// RunGoCommandInDirWithEnv is like RunGoCommand, but executes in the given\n// relative directory of the sandbox with the given additional environment variables.\nfunc (e *Env) RunGoCommandInDirWithEnv(dir string, env []string, verb string, args ...string) {\n\te.TB.Helper()\n\tif _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, env, true); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// GoVersion checks the version of the go command.\n// It returns the X in Go 1.X.\nfunc (e *Env) GoVersion() int {\n\te.TB.Helper()\n\tv, err := e.Sandbox.GoVersion(e.Ctx)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn v\n}\n\n// DumpGoSum prints the correct go.sum contents for dir in txtar format,\n// for use in creating integration tests.\nfunc (e *Env) DumpGoSum(dir string) {\n\te.TB.Helper()\n\n\tif _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, \"list\", []string{\"-mod=mod\", \"./...\"}, nil, true); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\tsumFile := path.Join(dir, \"go.sum\")\n\te.TB.Log(\"\\n\\n-- \" + sumFile + \" --\\n\" + e.ReadWorkspaceFile(sumFile))\n\te.TB.Fatal(\"see contents above\")\n}\n\n// CheckForFileChanges triggers a manual poll of the workspace for any file\n// changes since creation, or since last polling. It is a workaround for the\n// lack of true file watching support in the fake workspace.\nfunc (e *Env) CheckForFileChanges() {\n\te.TB.Helper()\n\tif err := e.Sandbox.Workdir.CheckForFileChanges(e.Ctx); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// CodeLens calls textDocument/codeLens for the given path, calling t.Fatal on\n// any error.\nfunc (e *Env) CodeLens(path string) []protocol.CodeLens {\n\te.TB.Helper()\n\tlens, err := e.Editor.CodeLens(e.Ctx, path)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn lens\n}\n\n// ExecuteCodeLensCommand executes the command for the code lens matching the\n// given command name.\n//\n// result is a pointer to a variable to be populated by json.Unmarshal.\nfunc (e *Env) ExecuteCodeLensCommand(path string, cmd command.Command, result any) {\n\te.TB.Helper()\n\tif err := e.Editor.ExecuteCodeLensCommand(e.Ctx, path, cmd, result); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ExecuteCommand executes the requested command in the editor, calling t.Fatal\n// on any error.\n//\n// result is a pointer to a variable to be populated by json.Unmarshal.\nfunc (e *Env) ExecuteCommand(params *protocol.ExecuteCommandParams, result any) {\n\te.TB.Helper()\n\tif err := e.Editor.ExecuteCommand(e.Ctx, params, result); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// Views returns the server's views.\nfunc (e *Env) Views() []command.View {\n\tvar summaries []command.View\n\tcmd := command.NewViewsCommand(\"\")\n\te.ExecuteCommand(&protocol.ExecuteCommandParams{\n\t\tCommand:   cmd.Command,\n\t\tArguments: cmd.Arguments,\n\t}, &summaries)\n\treturn summaries\n}\n\n// StartProfile starts a CPU profile with the given name, using the\n// gopls.start_profile custom command. It calls t.Fatal on any error.\n//\n// The resulting stop function must be called to stop profiling (using the\n// gopls.stop_profile custom command).\nfunc (e *Env) StartProfile() (stop func() string) {\n\t// TODO(golang/go#61217): revisit the ergonomics of these command APIs.\n\t//\n\t// This would be a lot simpler if we generated params constructors.\n\targs, err := command.MarshalArgs(command.StartProfileArgs{})\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\tparams := &protocol.ExecuteCommandParams{\n\t\tCommand:   command.StartProfile.String(),\n\t\tArguments: args,\n\t}\n\tvar result command.StartProfileResult\n\te.ExecuteCommand(params, &result)\n\n\treturn func() string {\n\t\tstopArgs, err := command.MarshalArgs(command.StopProfileArgs{})\n\t\tif err != nil {\n\t\t\te.TB.Fatal(err)\n\t\t}\n\t\tstopParams := &protocol.ExecuteCommandParams{\n\t\t\tCommand:   command.StopProfile.String(),\n\t\t\tArguments: stopArgs,\n\t\t}\n\t\tvar result command.StopProfileResult\n\t\te.ExecuteCommand(stopParams, &result)\n\t\treturn result.File\n\t}\n}\n\n// InlayHints calls textDocument/inlayHints for the given path, calling t.Fatal on\n// any error.\nfunc (e *Env) InlayHints(path string) []protocol.InlayHint {\n\te.TB.Helper()\n\thints, err := e.Editor.InlayHint(e.Ctx, path)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn hints\n}\n\n// Symbol calls workspace/symbol\nfunc (e *Env) Symbol(query string) []protocol.SymbolInformation {\n\te.TB.Helper()\n\tans, err := e.Editor.Symbols(e.Ctx, query)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn ans\n}\n\n// References wraps Editor.References, calling t.Fatal on any error.\nfunc (e *Env) References(loc protocol.Location) []protocol.Location {\n\te.TB.Helper()\n\tlocations, err := e.Editor.References(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn locations\n}\n\n// Rename wraps Editor.Rename, calling t.Fatal on any error.\nfunc (e *Env) Rename(loc protocol.Location, newName string) {\n\te.TB.Helper()\n\tif err := e.Editor.Rename(e.Ctx, loc, newName); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// Implementations wraps Editor.Implementations, calling t.Fatal on any error.\nfunc (e *Env) Implementations(loc protocol.Location) []protocol.Location {\n\te.TB.Helper()\n\tlocations, err := e.Editor.Implementations(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn locations\n}\n\n// RenameFile wraps Editor.RenameFile, calling t.Fatal on any error.\nfunc (e *Env) RenameFile(oldPath, newPath string) {\n\te.TB.Helper()\n\tif err := e.Editor.RenameFile(e.Ctx, oldPath, newPath); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// SignatureHelp wraps Editor.SignatureHelp, calling t.Fatal on error\nfunc (e *Env) SignatureHelp(loc protocol.Location) *protocol.SignatureHelp {\n\te.TB.Helper()\n\tsighelp, err := e.Editor.SignatureHelp(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn sighelp\n}\n\n// Completion executes a completion request on the server.\nfunc (e *Env) Completion(loc protocol.Location) *protocol.CompletionList {\n\te.TB.Helper()\n\tcompletions, err := e.Editor.Completion(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn completions\n}\n\nfunc (e *Env) DidCreateFiles(files ...protocol.DocumentURI) {\n\te.TB.Helper()\n\terr := e.Editor.DidCreateFiles(e.Ctx, files...)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\nfunc (e *Env) SetSuggestionInsertReplaceMode(useReplaceMode bool) {\n\te.TB.Helper()\n\te.Editor.SetSuggestionInsertReplaceMode(e.Ctx, useReplaceMode)\n}\n\n// AcceptCompletion accepts a completion for the given item at the given\n// position.\nfunc (e *Env) AcceptCompletion(loc protocol.Location, item protocol.CompletionItem) {\n\te.TB.Helper()\n\tif err := e.Editor.AcceptCompletion(e.Ctx, loc, item); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// CodeActionForFile calls textDocument/codeAction for the entire\n// file, and calls t.Fatal if there were errors.\nfunc (e *Env) CodeActionForFile(path string, diagnostics []protocol.Diagnostic) []protocol.CodeAction {\n\treturn e.CodeAction(e.Sandbox.Workdir.EntireFile(path), diagnostics, protocol.CodeActionUnknownTrigger)\n}\n\n// CodeAction calls textDocument/codeAction for a selection,\n// and calls t.Fatal if there were errors.\nfunc (e *Env) CodeAction(loc protocol.Location, diagnostics []protocol.Diagnostic, trigger protocol.CodeActionTriggerKind) []protocol.CodeAction {\n\te.TB.Helper()\n\tactions, err := e.Editor.CodeAction(e.Ctx, loc, diagnostics, trigger)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn actions\n}\n\n// ChangeConfiguration updates the editor config, calling t.Fatal on any error.\nfunc (e *Env) ChangeConfiguration(newConfig fake.EditorConfig) {\n\te.TB.Helper()\n\tif err := e.Editor.ChangeConfiguration(e.Ctx, newConfig); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// ChangeWorkspaceFolders updates the editor workspace folders, calling t.Fatal\n// on any error.\nfunc (e *Env) ChangeWorkspaceFolders(newFolders ...string) {\n\te.TB.Helper()\n\tif err := e.Editor.ChangeWorkspaceFolders(e.Ctx, newFolders); err != nil {\n\t\te.TB.Fatal(err)\n\t}\n}\n\n// SemanticTokensFull invokes textDocument/semanticTokens/full, calling t.Fatal\n// on any error.\nfunc (e *Env) SemanticTokensFull(path string) []fake.SemanticToken {\n\te.TB.Helper()\n\ttoks, err := e.Editor.SemanticTokensFull(e.Ctx, path)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn toks\n}\n\n// SemanticTokensRange invokes textDocument/semanticTokens/range, calling t.Fatal\n// on any error.\nfunc (e *Env) SemanticTokensRange(loc protocol.Location) []fake.SemanticToken {\n\te.TB.Helper()\n\ttoks, err := e.Editor.SemanticTokensRange(e.Ctx, loc)\n\tif err != nil {\n\t\te.TB.Fatal(err)\n\t}\n\treturn toks\n}\n\n// Close shuts down resources associated with the environment, calling t.Error\n// on any error.\nfunc (e *Env) Close() {\n\tctx := xcontext.Detach(e.Ctx)\n\tif e.MCPSession != nil {\n\t\tif err := e.MCPSession.Close(); err != nil {\n\t\t\te.TB.Errorf(\"closing MCP session: %v\", err)\n\t\t}\n\t}\n\tif e.MCPServer != nil {\n\t\te.MCPServer.Close()\n\t}\n\tif err := e.Editor.Close(ctx); err != nil {\n\t\te.TB.Errorf(\"closing editor: %v\", err)\n\t}\n\tif err := e.Sandbox.Close(); err != nil {\n\t\te.TB.Errorf(\"cleaning up sandbox: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage marker defines a framework for running \"marker\" tests, each\ndefined by a file in the testdata subdirectory.\n\nUse this command to run the tests, from the gopls module:\n\n\t$ go test ./internal/test/marker [-update]\n\nA marker test uses the '//@' syntax of the x/tools/internal/expect package to\nannotate source code with various information such as locations and arguments\nof LSP operations to be executed by the test. The syntax following '@' is\nparsed as a comma-separated list of Go-like function calls, which we refer to\nas 'markers' (or sometimes 'marks'), for example\n\n\t//@ foo(a, \"b\", 3), bar(0)\n\nUnlike ordinary Go, the marker syntax also supports optional named arguments\nusing the syntax name=value. If provided, named arguments must appear after all\npositional arguments, though their ordering with respect to other named\narguments does not matter. For example\n\n\t//@ foo(a, \"b\", d=4, c=3)\n\nEach marker causes a corresponding function to be called in the test. Some\nmarkers are declarations; for example, @loc declares a name for a source\nlocation. Others have effects, such as executing an LSP operation and asserting\nthat it behaved as expected. See the Marker types documentation below for the\nlist of all supported markers.\n\nEach call argument is converted to the type of the corresponding parameter of\nthe designated function. The conversion logic may use the surrounding context,\nsuch as the position or nearby text. See the Argument conversion section below\nfor the full set of special conversions. As a special case, the blank\nidentifier '_' is treated as the zero value of the parameter type.\n\nThe test runner collects test cases by searching the given directory for\nfiles with the .txt extension. Each file is interpreted as a txtar archive,\nwhich is extracted to a temporary directory. The relative path to the .txt\nfile is used as the subtest name. The preliminary section of the file\n(before the first archive entry) is a free-form comment.\n\n# Special files\n\nThere are several types of file within the test archive that are given special\ntreatment by the test runner:\n\n  - \"skip\": the presence of this file causes the test to be skipped, with\n    its content used as the skip message.\n\n  - \"flags\": this file is treated as a whitespace-separated list of flags\n    that configure the MarkerTest instance. Supported flags:\n\n    -{min,max}_go=go1.20 sets the {min,max}imum Go runtime version for the test\n    (inclusive).\n    -{min,max}_go_command=go1.20 sets the {min,max}imum Go command version for\n    the test (inclusive).\n    -cgo requires that CGO_ENABLED is set and the cgo tool is available.\n    -write_sumfile=a,b,c instructs the test runner to generate go.sum files\n    in these directories before running the test.\n    -skip_goos=a,b,c instructs the test runner to skip the test for the\n    listed GOOS values.\n    -skip_goarch=a,b,c does the same for GOARCH.\n    TODO(rfindley): using build constraint expressions for -skip_go{os,arch} would\n    be clearer.\n    -ignore_extra_diags suppresses errors for unmatched diagnostics\n    -filter_builtins=false disables the filtering of builtins from\n    completion results.\n    -filter_keywords=false disables the filtering of keywords from\n    completion results.\n    -errors_ok=true suppresses errors for Error level log entries.\n\n    TODO(rfindley): support flag values containing whitespace.\n\n  - \"settings.json\": this file is parsed as JSON, and used as the\n    session configuration (see gopls/doc/settings.md)\n\n  - \"capabilities.json\": this file is parsed as JSON client capabilities,\n    and applied as an overlay over the default editor client capabilities.\n    see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#clientCapabilities\n    for more details.\n\n  - \"env\": this file is parsed as a list of VAR=VALUE fields specifying the\n    editor environment.\n\n  - Golden files: Within the archive, file names starting with '@' are\n    treated as \"golden\" content, and are not written to disk, but instead are\n    made available to test methods expecting an argument of type *Golden,\n    using the identifier following '@'. For example, if the first parameter of\n    Foo were of type *Golden, the test runner would convert the identifier a\n    in the call @foo(a, \"b\", 3) into a *Golden by collecting golden file\n    data starting with \"@a/\". As a special case, for tests that only need one\n    golden file, the data contained in the file \"@a\" is indexed in the *Golden\n    value by the empty string \"\".\n\n  - proxy files: any file starting with proxy/ is treated as a Go proxy\n    file. If present, these files are written to a separate temporary\n    directory and GOPROXY is set to file://<proxy directory>.\n\n# Marker types\n\nMarkers are of two kinds: \"value markers\" and \"action markers\". Value markers\nare processed in a first pass, and define named values that may be referred to\nas arguments to action markers. For example, the @loc marker defines a named\nlocation that may be used wherever a location is expected. Value markers cannot\nrefer to names defined by other value markers. Action markers are processed in\na second pass and perform some action such as testing an LSP operation.\n\nBelow, we list supported markers using function signatures, augmented with the\nnamed argument support name=value, as described above. The types referred to in\nthe signatures below are described in the Argument conversion section.\n\nHere is the list of supported value markers:\n\n  - loc(name, location): specifies the name for a location in the source. These\n    locations may be referenced by other markers. Naturally, the location\n    argument may be specified only as a string or regular expression in the\n    first pass.\n    The predeclared locations BUILTIN and UNSAFE match any location in the\n    GOROOT/src/{builtin/builtin,unsafe/unsafe}.go file, regardless of GOROOT.\n\n  - defloc(name, location): performs a textDocument/definition request at the\n    src location, and binds the result to the given name. This may be used to\n    refer to positions in the standard library.\n\n  - hiloc(name, location, kind): defines a documentHighlight value of the\n    given location and kind. Use its label in a @highlightall marker to\n    indicate the expected result of a highlight query.\n\n  - item(name, details, kind): defines a completionItem with the provided\n    fields. This information is not positional, and therefore @item markers\n    may occur anywhere in the source. Use in conjunction with @complete,\n    @snippet, or @rank.\n\n    TODO(rfindley): rethink whether floating @item annotations are the best\n    way to specify completion results.\n\nHere is the list of supported action markers:\n\n  - acceptcompletion(location, label, golden): specifies that accepting the\n    completion candidate produced at the given location with provided label\n    results in the given golden state.\n\n  - codeaction(start location, kind string, diag=regexp, end=location, action=golden, edit=golden, result=golden, err=stringMatcher)\n\n    Specifies a code action to request at the location, with given kind.\n    If diag is set, the code action must be associated with the given\n    diagnostic.\n    If end is set, the location is defined to be between start.Start and\n    end.End.\n\n    Exactly one of action, edit, result, or err must be set:\n    If action is set, it is a golden reference to a JSON blob representing the\n    resolved code action, which is not applied.\n    If edit is set, it is a golden reference to the edits resulting from the\n    code action.\n    If result is set, it is a golden reference to the full set of changed files\n    resulting from the code action.\n    If err is set, it is expected to match the error resulting from applying\n    the code action.\n\n  - codelens(location, title): specifies that a codelens is expected at the\n    given location, with given title. Must be used in conjunction with\n    @codelenses.\n\n  - codelenses(): specifies that textDocument/codeLens should be run for the\n    current document, with results compared to the @codelens annotations in\n    the current document.\n\n  - complete(location, ...items): specifies expected completion results at\n    the given location. Must be used in conjunction with @item.\n\n  - diag(location, regexp, exact=bool): specifies an expected diagnostic\n    matching the given regexp at the given location. The test runner requires a\n    1:1 correspondence between observed diagnostics and diag annotations. The\n    diagnostics source and kind fields are ignored, to reduce fuss.\n\n    The specified location must match the start position of the diagnostic,\n    but end positions are ignored unless exact=true.\n\n    TODO(adonovan): in the older marker framework, the annotation asserted two\n    additional fields (source=\"compiler\", kind=\"error\"). Restore them using\n    optional named arguments.\n\n  - def(src, want ...location): performs a textDocument/definition request at\n    the src location, and checks that the resulting set of locations matches want.\n\n  - documentLink(golden): asserts that textDocument/documentLink returns\n    links as described by the golden file.\n\n  - foldingrange(golden): performs a textDocument/foldingRange for the\n    current document, and compare with the golden content, which is the\n    original source annotated with numbered tags delimiting the resulting\n    ranges (e.g. <1 kind=\"...\"> ... </1>).\n\n  - format(golden): performs a textDocument/format request for the enclosing\n    file, and compare against the named golden file. If the formatting\n    request succeeds, the golden file must contain the resulting formatted\n    source. If the formatting request fails, the golden file must contain\n    the error message.\n\n  - highlightall(all ...documentHighlight): makes a textDocument/highlight\n    request at each location in \"all\" and checks that the result is \"all\".\n    In other words, given highlightall(X1, X2, ..., Xn), it checks that\n    highlight(X1) = highlight(X2) = ... = highlight(Xn) = {X1, X2, ..., Xn}.\n    In general, highlight sets are not equivalence classes; for asymmetric\n    cases, use @highlight instead.\n    Each element of \"all\" is the label of a @hiloc marker.\n\n  - highlight(src location, dsts ...documentHighlight): makes a\n    textDocument/highlight request at the given src location, which should\n    highlight the provided dst locations and kinds.\n\n  - hover(src, dst location, sm stringMatcher): performs a textDocument/hover\n    at the src location, and checks that the result is the dst location, with\n    matching hover content. Be careful to avoid self-satisfying hover markers:\n    if the hover content literally includes the marker comment itself,\n    it will always contain the expected string! A backslash escape may help.\n\n  - hovererr(src, sm stringMatcher): performs a textDocument/hover at the src\n    location, and checks that the error matches the given stringMatcher.\n\n  - implementation(src location, want ...location, err=stringMatcher):\n    makes a textDocument/implementation query at the src location and\n    checks that the resulting set of locations matches want. If err is\n    set, the implementation query must fail with the expected error.\n\n  - incomingcalls(src location, want ...location): makes a\n    callHierarchy/incomingCalls query at the src location, and checks that\n    the set of call.From locations matches want.\n    (These locations are the declarations of the functions enclosing\n    the calls, not the calls themselves.)\n\n  - outgoingcalls(src location, want ...location): makes a\n    callHierarchy/outgoingCalls query at the src location, and checks that\n    the set of call.To locations matches want.\n\n  - preparerename(src location, placeholder string, span=location): asserts\n    that a textDocument/prepareRename request at the src location has the given\n    placeholder text. If present, the optional span argument is verified to be\n    the span of the prepareRename result. If placeholder is \"\", this is treated\n    as a negative assertion and prepareRename should return nil.\n\n  - quickfix(location, regexp, golden): like diag, the location and\n    regexp identify an expected diagnostic, which must have exactly one\n    associated \"quickfix\" code action.\n    This action is executed for its editing effects on the source files.\n    Like rename, the golden directory contains the expected transformed files.\n\n  - quickfixerr(location, regexp, wantError): specifies that the\n    quickfix operation should fail with an error that matches the expectation.\n    (Failures in the computation to offer a fix do not generally result\n    in LSP errors, so this marker is not appropriate for testing them.)\n\n  - rank(location, ...string OR completionItem): executes a\n    textDocument/completion request at the given location, and verifies that\n    each expected completion item occurs in the results, in the expected order.\n    Items may be specified as string literal completion labels, or as\n    references to a completion item created with the @item marker.\n    Other unexpected completion items are allowed to occur in the results, and\n    are ignored. A \"!\" prefix on a label asserts that the symbol is not a\n    completion candidate.\n\n  - refs(location, want ...location): executes a textDocument/references request\n    at the first location and asserts that the resulting set of locations\n    matches want. The first want location must be the declaration (assumedly\n    unique).\n\n  - rename(location, new, golden): specifies a renaming of the\n    identifier at the specified location to the new name.\n    The golden directory contains the transformed files.\n\n  - renameerr(location, new, wantError): specifies a renaming that\n    fails with an error that matches the expectation.\n\n  - signature(location, label, active): specifies that\n    signatureHelp at the given location should match the provided string, with\n    the active parameter (an index) highlighted.\n\n  - snippet(location, string OR completionItem, snippet): executes a\n    textDocument/completion request at the location, and searches for a result\n    with label matching that its second argument, which may be a string literal\n    or a reference to a completion item created by the @item marker (in which\n    case the item's label is used). It checks that the resulting snippet\n    matches the provided snippet.\n\n  - subtypes  (src location, want ...location),\n    supertypes(src location, want ...location):\n    execute a textDocument/prepareTypeHierarchy request at the src\n    location, followed by a typeHierarchy/{sub,super}types request on\n    the first response, and check that the result contains the list\n    of wanted locations in order.\n\n  - symbol(golden): makes a textDocument/documentSymbol request\n    for the enclosing file, formats the response with one symbol\n    per line, sorts it, and compares against the named golden file.\n    Each line is of the form:\n\n    dotted.symbol.name kind \"detail\" +n lines\n\n    where the \"+n lines\" part indicates that the declaration spans\n    several lines. The test otherwise makes no attempt to check\n    location information. There is no point to using more than one\n    @symbol marker in a given file.\n\n  - token(location, tokenType, mod): makes a textDocument/semanticTokens/range\n    request at the given location, and asserts that the result includes\n    exactly one token with the given token type and modifier string.\n\n  - typedef(src, want ...location, err=stringMatcher): performs a\n    textDocument/typeDefinition request at the src location, and checks that the\n    resulting set of locations matches want. If err is set, the type definition\n    query must fail with the expected error.\n\n  - workspacesymbol(query, golden): makes a workspace/symbol request for the\n    given query, formats the response with one symbol per line, and compares\n    against the named golden file. As workspace symbols are by definition a\n    workspace-wide request, the location of the workspace symbol marker does\n    not matter. Each line is of the form:\n\n    location name kind\n\n  - mcptool(name string, arg string, location=location, output=golden):\n    Executes an MCP tool call using the provided tool name and args (a\n    JSON-encoded value). Any string or []string values in the JSON input object\n    are modified to replace the substring '$WORKDIR' with the actual working\n    directory of the test. Furthermore, if 'location' is provided, it is used\n    to populate the 'location' property of the JSON input with the given LSP\n    source location. The test then asserts that the MCP server's response\n    matches the content of the golden file identified by output. For\n    portability, all filepath separators in the output are normalized to '/',\n    even if they occur outside of a path context.\n\n# Expected locations\nMarker tests that compare expected sets of locations (e.g. def, refs) only check\nfor set equality, so the order and cardinality of locations does not matter. Of\nall markers that specify expected locations, only subtypes and supertypes check\nfor order.\n\n# Argument conversion\n\nMarker arguments are first parsed by the internal/expect package, which accepts\nthe following tokens as defined by the Go spec:\n  - string, int64, float64, and rune literals\n  - true and false\n  - nil\n  - identifiers (type expect.Identifier)\n  - regular expressions, denoted the two tokens re\"abc\" (type *regexp.Regexp)\n\nThese values are passed as arguments to the corresponding parameter of the\ntest function. Additional value conversions may occur for these argument ->\nparameter type pairs:\n\n  - string->regexp: the argument is parsed as a regular expressions.\n\n  - string->location: the argument is converted to the location of the first\n    instance of the argument in the file content starting from the beginning of\n    the line containing the note. Multi-line matches are permitted, but the\n    match must begin before the note.\n\n  - regexp->location: the argument is converted to the location of the first\n    match for the argument in the file content starting from the beginning of\n    the line containing the note. Multi-line matches are permitted, but the\n    match must begin before the note. If the regular expression contains\n    exactly one subgroup, the position of the subgroup is used rather than the\n    position of the submatch.\n\n  - name->location: the argument is replaced by the named location.\n\n  - name->Golden: the argument is used to look up golden content prefixed by\n    @<argument>.\n\n  - {string,regexp,identifier}->stringMatcher: a stringMatcher type\n    specifies an expected string, either in the form of a substring\n    that must be present, a regular expression that it must match, or an\n    identifier (e.g. foo) such that the archive entry @foo exists and\n    contains the exact expected string.\n    stringMatchers are used by some markers to match positive results\n    (outputs) and by other markers to match error messages.\n\n# Example\n\nHere is a complete example:\n\n\tThis test checks hovering over constants.\n\n\t-- a.go --\n\tpackage a\n\n\tconst abc = 0x2a //@hover(\"b\", \"abc\", abc),hover(\" =\", \"abc\", abc)\n\n\t-- @abc --\n\t```go\n\tconst abc untyped int = 42\n\t```\n\n\t@hover(\"b\", \"abc\", abc),hover(\" =\", \"abc\", abc)\n\nIn this example, the @hover annotation tells the test runner to run the\nhoverMarker function, which has parameters:\n\n\t(mark marker, src, dst protocol.Location, g *Golden).\n\nThe first argument holds the test context, including fake editor with open\nfiles, and sandboxed directory.\n\nArgument converters translate the \"b\" and \"abc\" arguments into locations by\ninterpreting each one as a substring (or as a regular expression, if of the\nform re\"a|b\") and finding the location of its first occurrence starting on the\npreceding portion of the line, and the abc identifier into a the golden content\ncontained in the file @abc. Then the hoverMarker method executes a\ntextDocument/hover LSP request at the src position, and ensures the result\nspans \"abc\", with the markdown content from @abc. (Note that the markdown\ncontent includes the expect annotation as the doc comment.)\n\nThe next hover on the same line asserts the same result, but initiates the\nhover immediately after \"abc\" in the source. This tests that we find the\npreceding identifier when hovering.\n\n# Updating golden files\n\nTo update golden content in the test archive, it is easier to regenerate\ncontent automatically rather than edit it by hand. To do this, run the\ntests with the -update flag. Only tests that actually run will be updated.\n\nIn some cases, golden content will vary by Go version (for example, gopls\nproduces different markdown at Go versions before the 1.19 go/doc update).\nBy convention, the golden content in test archives should match the output\nat Go tip. Each test function can normalize golden content for older Go\nversions.\n\nNote that -update does not cause missing @diag or @loc markers to be added.\n\n# TODO\n\n  - Rename the files .txtar.\n  - Eliminate all *err markers, preferring named arguments.\n  - In failed assertions, display locations using symbolic @loc names where available.\n*/\npackage marker\n"
  },
  {
    "path": "gopls/internal/test/marker/marker_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage marker\n\n// This file defines the marker test framework.\n// See doc.go for extensive documentation.\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io/fs\"\n\t\"log\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/debug\"\n\t\"golang.org/x/tools/gopls/internal/lsprpc\"\n\tinternalmcp \"golang.org/x/tools/gopls/internal/mcp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/test/compare\"\n\t\"golang.org/x/tools/gopls/internal/test/integration\"\n\t\"golang.org/x/tools/gopls/internal/test/integration/fake\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/servertest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nvar update = flag.Bool(\"update\", false, \"if set, update test data during marker tests\")\n\nfunc TestMain(m *testing.M) {\n\tbug.PanicOnBugs = true\n\ttestenv.ExitIfSmallMachine()\n\t// Disable GOPACKAGESDRIVER, as it can cause spurious test failures.\n\tos.Setenv(\"GOPACKAGESDRIVER\", \"off\") // ignore error\n\tintegration.FilterToolchainPathAndGOROOT()\n\tos.Exit(m.Run())\n}\n\n// Test runs the marker tests from the testdata directory.\n//\n// See package documentation for details on how marker tests work.\n//\n// These tests were inspired by (and in many places copied from) a previous\n// iteration of the marker tests built on top of the packagestest framework.\n// Key design decisions motivating this reimplementation are as follows:\n//   - The old tests had a single global session, causing interaction at a\n//     distance and several awkward workarounds.\n//   - The old tests could not be safely parallelized, because certain tests\n//     manipulated the server options\n//   - Relatedly, the old tests did not have a logic grouping of assertions into\n//     a single unit, resulting in clusters of files serving clusters of\n//     entangled assertions.\n//   - The old tests used locations in the source as test names and as the\n//     identity of golden content, meaning that a single edit could change the\n//     name of an arbitrary number of subtests, and making it difficult to\n//     manually edit golden content.\n//   - The old tests did not hew closely to LSP concepts, resulting in, for\n//     example, each marker implementation doing its own position\n//     transformations, and inventing its own mechanism for configuration.\n//   - The old tests had an ad-hoc session initialization process. The integration\n//     test environment has had more time devoted to its initialization, and has a\n//     more convenient API.\n//   - The old tests lacked documentation, and often had failures that were hard\n//     to understand. By starting from scratch, we can revisit these aspects.\nfunc Test(t *testing.T) {\n\tif testing.Short() {\n\t\tbuilder := os.Getenv(\"GO_BUILDER_NAME\")\n\t\t// Note that HasPrefix(builder, \"darwin-\" only matches legacy builders.\n\t\t// LUCI builder names start with x_tools-goN.NN.\n\t\t// We want to exclude solaris on both legacy and LUCI builders, as\n\t\t// it is timing out.\n\t\tif strings.HasPrefix(builder, \"darwin-\") || strings.Contains(builder, \"solaris\") {\n\t\t\tt.Skip(\"golang/go#64473: skipping with -short: this test is too slow on darwin and solaris builders\")\n\t\t}\n\t\tif strings.HasSuffix(builder, \"freebsd-amd64-race\") {\n\t\t\tt.Skip(\"golang/go#71731: the marker tests are too slow to run on the amd64-race builder\")\n\t\t}\n\t}\n\t// The marker tests must be able to run go/packages.Load.\n\ttestenv.NeedsGoPackages(t)\n\n\tconst dir = \"testdata\"\n\ttests, err := loadMarkerTests(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Opt: use a shared cache.\n\tcache := cache.New(nil)\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tif test.skipReason != \"\" {\n\t\t\t\tt.Skip(test.skipReason)\n\t\t\t}\n\t\t\tif slices.Contains(test.skipGOOS, runtime.GOOS) {\n\t\t\t\tt.Skipf(\"skipping on %s due to -skip_goos\", runtime.GOOS)\n\t\t\t}\n\t\t\tif slices.Contains(test.skipGOARCH, runtime.GOARCH) {\n\t\t\t\tt.Skipf(\"skipping on %s due to -skip_goarch\", runtime.GOARCH)\n\t\t\t}\n\n\t\t\t// TODO(rfindley): it may be more useful to have full support for build\n\t\t\t// constraints.\n\t\t\tif test.minGoVersion != \"\" {\n\t\t\t\tvar go1point int\n\t\t\t\tif _, err := fmt.Sscanf(test.minGoVersion, \"go1.%d\", &go1point); err != nil {\n\t\t\t\t\tt.Fatalf(\"parsing -min_go version: %v\", err)\n\t\t\t\t}\n\t\t\t\ttestenv.NeedsGo1Point(t, go1point)\n\t\t\t}\n\t\t\tif test.maxGoVersion != \"\" {\n\t\t\t\t// A max Go version may be useful when (e.g.) a recent go/types\n\t\t\t\t// fix makes it impossible to reproduce a certain older crash.\n\t\t\t\tvar go1point int\n\t\t\t\tif _, err := fmt.Sscanf(test.maxGoVersion, \"go1.%d\", &go1point); err != nil {\n\t\t\t\t\tt.Fatalf(\"parsing -max_go version: %v\", err)\n\t\t\t\t}\n\t\t\t\ttestenv.SkipAfterGo1Point(t, go1point)\n\t\t\t}\n\t\t\tif test.minGoCommandVersion != \"\" {\n\t\t\t\tvar go1point int\n\t\t\t\tif _, err := fmt.Sscanf(test.minGoCommandVersion, \"go1.%d\", &go1point); err != nil {\n\t\t\t\t\tt.Fatalf(\"parsing -min_go_command version: %v\", err)\n\t\t\t\t}\n\t\t\t\ttestenv.NeedsGoCommand1Point(t, go1point)\n\t\t\t}\n\t\t\tif test.maxGoCommandVersion != \"\" {\n\t\t\t\tvar go1point int\n\t\t\t\tif _, err := fmt.Sscanf(test.maxGoCommandVersion, \"go1.%d\", &go1point); err != nil {\n\t\t\t\t\tt.Fatalf(\"parsing -max_go_command version: %v\", err)\n\t\t\t\t}\n\t\t\t\ttestenv.SkipAfterGoCommand1Point(t, go1point)\n\t\t\t}\n\t\t\tif test.cgo {\n\t\t\t\tif os.Getenv(\"CGO_ENABLED\") == \"0\" {\n\t\t\t\t\t// NeedsTool causes the test to fail if cgo is available but disabled\n\t\t\t\t\t// on the current platform through the environment. I'm not sure why it\n\t\t\t\t\t// behaves this way, but if CGO_ENABLED=0 is set, we want to skip.\n\t\t\t\t\tt.Skip(\"skipping due to CGO_ENABLED=0\")\n\t\t\t\t}\n\t\t\t\ttestenv.NeedsTool(t, \"cgo\")\n\t\t\t}\n\n\t\t\tconfig := fake.EditorConfig{\n\t\t\t\tSettings:         test.settings,\n\t\t\t\tCapabilitiesJSON: test.capabilities,\n\t\t\t\tEnv:              test.env,\n\t\t\t}\n\n\t\t\tif _, ok := config.Settings[\"diagnosticsDelay\"]; !ok {\n\t\t\t\tif config.Settings == nil {\n\t\t\t\t\tconfig.Settings = make(map[string]any)\n\t\t\t\t}\n\t\t\t\tconfig.Settings[\"diagnosticsDelay\"] = \"10ms\"\n\t\t\t}\n\n\t\t\t// inv: config.Settings != nil\n\n\t\t\trun := &markerTestRun{\n\t\t\t\ttest:       test,\n\t\t\t\tenv:        newEnv(t, cache, test.files, test.proxyFiles, test.writeGoSum, config, test.mcp),\n\t\t\t\tsettings:   config.Settings,\n\t\t\t\tvalues:     make(map[expect.Identifier]any),\n\t\t\t\tdiags:      make(map[protocol.Location][]protocol.Diagnostic),\n\t\t\t\textraNotes: make(map[protocol.DocumentURI]map[string][]*expect.Note),\n\t\t\t}\n\t\t\tdefer run.env.Close()\n\n\t\t\t// Support built-in pseudo-locations here.\n\t\t\t// fmtLoc coerces \"got\" Locations to these forms\n\t\t\t// so they can be compared without depending\n\t\t\t// on line numbers in external files.\n\t\t\t//\n\t\t\t// (We could actually define \"builtin:int\" etc\n\t\t\t// with the correct file/line/col for each\n\t\t\t// builtin symbol, but that doesn't seem to be\n\t\t\t// where the bugs are.)\n\t\t\trun.values[\"BUILTIN\"] = protocol.Location{\n\t\t\t\tURI: \"file:///pseudo/builtin/builtin.go\",\n\t\t\t}\n\t\t\trun.values[\"UNSAFE\"] = protocol.Location{\n\t\t\t\tURI: \"file:///pseudo/unsafe/unsafe.go\",\n\t\t\t}\n\n\t\t\t// Open all files so that we operate consistently with LSP clients, and\n\t\t\t// (pragmatically) so that we have a Mapper available via the fake\n\t\t\t// editor.\n\t\t\t//\n\t\t\t// This also allows avoiding mutating the editor state in tests.\n\t\t\tfor file := range test.files {\n\t\t\t\trun.env.OpenFile(file)\n\t\t\t}\n\n\t\t\tallDiags := make(map[string][]protocol.Diagnostic)\n\t\t\tif run.env.Editor.ServerCapabilities().DiagnosticProvider != nil {\n\t\t\t\tfor name := range test.files {\n\t\t\t\t\t// golang/go#53275: support pull diagnostics for go.mod and go.work\n\t\t\t\t\t// files.\n\t\t\t\t\tif strings.HasSuffix(name, \".go\") {\n\t\t\t\t\t\tallDiags[name] = run.env.Diagnostics(name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Wait for the didOpen notifications to be processed, then collect\n\t\t\t\t// diagnostics.\n\n\t\t\t\trun.env.AfterChange()\n\t\t\t\tvar diags map[string]*protocol.PublishDiagnosticsParams\n\t\t\t\trun.env.AfterChange(integration.ReadAllDiagnostics(&diags))\n\t\t\t\tfor path, params := range diags {\n\t\t\t\t\tallDiags[path] = params.Diagnostics\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor path, diags := range allDiags {\n\t\t\t\turi := run.env.Sandbox.Workdir.URI(path)\n\t\t\t\tfor _, diag := range diags {\n\t\t\t\t\tloc := protocol.Location{\n\t\t\t\t\t\tURI: uri,\n\t\t\t\t\t\tRange: protocol.Range{\n\t\t\t\t\t\t\tStart: diag.Range.Start,\n\t\t\t\t\t\t\tEnd:   diag.Range.Start, // ignore end positions\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t\trun.diags[loc] = append(run.diags[loc], diag)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar markers []marker\n\t\t\tfor _, note := range test.notes {\n\t\t\t\tmark := marker{run: run, note: note}\n\t\t\t\tif fn, ok := valueMarkerFuncs[note.Name]; ok {\n\t\t\t\t\tfn(mark)\n\t\t\t\t} else if _, ok := actionMarkerFuncs[note.Name]; ok {\n\t\t\t\t\tmarkers = append(markers, mark) // save for later\n\t\t\t\t} else {\n\t\t\t\t\turi := mark.uri()\n\t\t\t\t\tif run.extraNotes[uri] == nil {\n\t\t\t\t\t\trun.extraNotes[uri] = make(map[string][]*expect.Note)\n\t\t\t\t\t}\n\t\t\t\t\trun.extraNotes[uri][note.Name] = append(run.extraNotes[uri][note.Name], note)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Invoke each remaining marker in the test.\n\t\t\tfor _, mark := range markers {\n\t\t\t\tactionMarkerFuncs[mark.note.Name](mark)\n\t\t\t}\n\n\t\t\t// Any remaining (un-eliminated) diagnostics are an error.\n\t\t\tif !test.ignoreExtraDiags {\n\t\t\t\tfor loc, diags := range run.diags {\n\t\t\t\t\tfor _, diag := range diags {\n\t\t\t\t\t\t// Note that loc is collapsed (start==end).\n\t\t\t\t\t\t// For formatting, show the exact span.\n\t\t\t\t\t\texactLoc := protocol.Location{\n\t\t\t\t\t\t\tURI:   loc.URI,\n\t\t\t\t\t\t\tRange: diag.Range,\n\t\t\t\t\t\t}\n\t\t\t\t\t\tt.Errorf(\"%s: unexpected diagnostic: %q\", run.fmtLoc(exactLoc), diag.Message)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// TODO(rfindley): use these for whole-file marker tests.\n\t\t\tfor uri, extras := range run.extraNotes {\n\t\t\t\tfor name, extra := range extras {\n\t\t\t\t\tif len(extra) > 0 {\n\t\t\t\t\t\tt.Errorf(\"%s: %d unused %q markers\", run.env.Sandbox.Workdir.URIToPath(uri), len(extra), name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now that all markers have executed, check whether there where any\n\t\t\t// unexpected error logs.\n\t\t\t// This guards against noisiness: see golang/go#66746)\n\t\t\tif !test.errorsOK {\n\t\t\t\trun.env.AfterChange(integration.NoErrorLogs())\n\t\t\t}\n\n\t\t\tformatted, err := formatTest(test)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"formatTest: %v\", err)\n\t\t\t} else if *update {\n\t\t\t\tfilename := filepath.Join(dir, test.name)\n\t\t\t\tif err := os.WriteFile(filename, formatted, 0o644); err != nil {\n\t\t\t\t\tt.Error(err)\n\t\t\t\t}\n\t\t\t} else if !t.Failed() {\n\t\t\t\t// Verify that the testdata has not changed.\n\t\t\t\t//\n\t\t\t\t// Only check this if the test hasn't already failed, otherwise we'd\n\t\t\t\t// report duplicate mismatches of golden data.\n\t\t\t\t// Otherwise, verify that formatted content matches.\n\t\t\t\tif diff := compare.NamedText(\"formatted\", \"on-disk\", string(formatted), string(test.content)); diff != \"\" {\n\t\t\t\t\t// at this point, the txtar file created by the test and the expected txtar file on the\n\t\t\t\t\t// disk differ. The differences are irrelevant if they are only the contents\n\t\t\t\t\t// of files from a unified diff. These files are dependent on which diff algorithm was used,\n\t\t\t\t\t// so instead checkDiffs has already checked that they correctly express the difference between\n\t\t\t\t\t// the test input and the test output. (If the test code uses the diff that created them, then\n\t\t\t\t\t// they would not differ, but that diff algorithms has been replaced.)\n\t\t\t\t\tcheckDifferences(t, test.content, formatted)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tif abs, err := filepath.Abs(dir); err == nil && t.Failed() {\n\t\tt.Logf(\"(Filenames are relative to %s.)\", abs)\n\t}\n}\n\n// checkDifferences reports whether the txtars in result and disk\n// differ, other than in the contents of golden files containing unified diffs\nfunc checkDifferences(t *testing.T, result, disk []byte) {\n\tgot := txtar.Parse(result) // the computed slice of file retains the ordering in result\n\twant := txtar.Parse(disk)\n\tfor i, tf := range got.Files {\n\t\tif i >= len(want.Files) {\n\t\t\tt.Errorf(\"test failed to create file %s\", tf.Name)\n\t\t\tcontinue\n\t\t}\n\t\t// if they are both golden files (name starts with @) and both unified diffs\n\t\t// (both start with @@, then the difference is insignificant)\n\t\tff := want.Files[i]\n\t\tif strings.HasPrefix(tf.Name, \"@\") && strings.HasPrefix(ff.Name, \"@\") && tf.Name == ff.Name &&\n\t\t\tbytes.HasPrefix(tf.Data, []byte(\"@@\")) && bytes.HasPrefix(ff.Data, []byte(\"@@\")) {\n\t\t\tcontinue\n\t\t}\n\t\tif !bytes.Equal(tf.Data, ff.Data) {\n\t\t\tt.Errorf(\"%s differs, got:%q want:%q\", tf.Name, tf.Data, ff.Data)\n\t\t}\n\t}\n}\n\n// A marker holds state for the execution of a single @marker\n// annotation in the source.\ntype marker struct {\n\trun  *markerTestRun\n\tnote *expect.Note\n}\n\n// ctx returns the mark context.\nfunc (m marker) ctx() context.Context { return m.run.env.Ctx }\n\n// T returns the testing.TB for this mark.\nfunc (m marker) T() testing.TB { return m.run.env.TB }\n\n// server returns the LSP server for the marker test run.\nfunc (m marker) editor() *fake.Editor { return m.run.env.Editor }\n\n// server returns the LSP server for the marker test run.\nfunc (m marker) server() protocol.Server { return m.run.env.Editor.Server }\n\n// uri returns the URI of the file containing the marker.\nfunc (mark marker) uri() protocol.DocumentURI {\n\treturn mark.run.env.Sandbox.Workdir.URI(mark.run.test.fset.File(mark.note.Pos).Name())\n}\n\n// document returns a protocol.TextDocumentIdentifier for the current file.\nfunc (mark marker) document() protocol.TextDocumentIdentifier {\n\treturn protocol.TextDocumentIdentifier{URI: mark.uri()}\n}\n\n// path returns the relative path to the file containing the marker.\nfunc (mark marker) path() string {\n\treturn mark.run.env.Sandbox.Workdir.RelPath(mark.run.test.fset.File(mark.note.Pos).Name())\n}\n\n// mapper returns a *protocol.Mapper for the current file.\nfunc (mark marker) mapper() *protocol.Mapper {\n\tmapper, err := mark.editor().Mapper(mark.path())\n\tif err != nil {\n\t\tmark.T().Fatalf(\"failed to get mapper for current mark: %v\", err)\n\t}\n\treturn mapper\n}\n\n// errorf reports a formatted error with a prefix indicating the position of\n// the marker note.\n//\n// It formats the error message using mark.sprintf.\nfunc (mark marker) errorf(format string, args ...any) {\n\tmark.T().Helper()\n\tmsg := mark.sprintf(format, args...)\n\t// TODO(adonovan): consider using fmt.Fprintf(os.Stderr)+t.Fail instead of\n\t// t.Errorf to avoid reporting uninteresting positions in the Go source of\n\t// the driver. However, this loses the order of stderr wrt \"FAIL: TestFoo\"\n\t// subtest dividers.\n\tmark.T().Errorf(\"%s: %s\", mark.run.fmtPos(mark.note.Pos), msg)\n}\n\n// valueMarkerFunc returns a wrapper around a function that allows it to be\n// called during the processing of value markers (e.g. @value(v, 123)) with marker\n// arguments converted to function parameters. The provided function's first\n// parameter must be of type 'marker', and it must return a value.\n//\n// Unlike action markers, which are executed for actions such as test\n// assertions, value markers are all evaluated first, and each computes\n// a value that is recorded by its identifier, which is the marker's first\n// argument. These values may be referred to from an action marker by\n// this identifier, e.g. @action(... , v, ...).\n//\n// For example, given a fn with signature\n//\n//\tfunc(mark marker, label, details, kind string) CompletionItem\n//\n// The result of valueMarkerFunc can associated with @item notes, and invoked\n// as follows:\n//\n//\t//@item(FooCompletion, \"Foo\", \"func() int\", \"func\")\n//\n// The provided fn should not mutate the test environment.\nfunc valueMarkerFunc(fn any) func(marker) {\n\tftype := reflect.TypeOf(fn)\n\tif ftype.NumIn() == 0 || ftype.In(0) != markerType {\n\t\tpanic(fmt.Sprintf(\"value marker function %#v must accept marker as its first argument\", ftype))\n\t}\n\tif ftype.NumOut() != 1 {\n\t\tpanic(fmt.Sprintf(\"value marker function %#v must have exactly 1 result\", ftype))\n\t}\n\n\treturn func(mark marker) {\n\t\tif len(mark.note.Args) == 0 || !is[expect.Identifier](mark.note.Args[0]) {\n\t\t\tmark.errorf(\"first argument to a value marker function must be an identifier\")\n\t\t\treturn\n\t\t}\n\t\tid := mark.note.Args[0].(expect.Identifier)\n\t\tif alt, ok := mark.run.values[id]; ok {\n\t\t\tmark.errorf(\"%s already declared as %T\", id, alt)\n\t\t\treturn\n\t\t}\n\t\targs := append([]any{mark}, mark.note.Args[1:]...)\n\t\targValues, err := convertArgs(mark, ftype, args)\n\t\tif err != nil {\n\t\t\tmark.errorf(\"%v\", err)\n\t\t\treturn\n\t\t}\n\t\tresults := reflect.ValueOf(fn).Call(argValues)\n\t\tmark.run.values[id] = results[0].Interface()\n\t}\n}\n\n// actionMarkerFunc returns a wrapper around a function that allows it to be\n// called during the processing of action markers (e.g. @action(\"abc\", 123))\n// with marker arguments converted to function parameters. The provided\n// function's first parameter must be of type 'marker', and it must not return\n// any values. Any named arguments that may be used by the marker func must be\n// listed in allowedNames.\n//\n// The provided fn should not mutate the test environment.\nfunc actionMarkerFunc(fn any, allowedNames ...string) func(marker) {\n\tftype := reflect.TypeOf(fn)\n\tif ftype.NumIn() == 0 || ftype.In(0) != markerType {\n\t\tpanic(fmt.Sprintf(\"action marker function %#v must accept marker as its first argument\", ftype))\n\t}\n\tif ftype.NumOut() != 0 {\n\t\tpanic(fmt.Sprintf(\"action marker function %#v cannot have results\", ftype))\n\t}\n\n\tvar allowed map[string]bool\n\tif len(allowedNames) > 0 {\n\t\tallowed = make(map[string]bool)\n\t\tfor _, name := range allowedNames {\n\t\t\tallowed[name] = true\n\t\t}\n\t}\n\n\treturn func(mark marker) {\n\t\tfor name := range mark.note.NamedArgs {\n\t\t\tif !allowed[name] {\n\t\t\t\tmark.errorf(\"unexpected named argument %q\", name)\n\t\t\t}\n\t\t}\n\n\t\targs := append([]any{mark}, mark.note.Args...)\n\t\targValues, err := convertArgs(mark, ftype, args)\n\t\tif err != nil {\n\t\t\tmark.errorf(\"%v\", err)\n\t\t\treturn\n\t\t}\n\t\treflect.ValueOf(fn).Call(argValues)\n\t}\n}\n\nfunc convertArgs(mark marker, ftype reflect.Type, args []any) ([]reflect.Value, error) {\n\tvar (\n\t\targValues []reflect.Value\n\t\tpnext     int          // next param index\n\t\tp         reflect.Type // current param\n\t)\n\tfor i, arg := range args {\n\t\tif i < ftype.NumIn() {\n\t\t\tp = ftype.In(pnext)\n\t\t\tpnext++\n\t\t} else if p == nil || !ftype.IsVariadic() {\n\t\t\t// The actual number of arguments expected by the mark varies, depending\n\t\t\t// on whether this is a value marker or an action marker.\n\t\t\t//\n\t\t\t// Since this error indicates a bug, probably OK to have an imprecise\n\t\t\t// error message here.\n\t\t\treturn nil, fmt.Errorf(\"too many arguments to %s\", mark.note.Name)\n\t\t}\n\t\telemType := p\n\t\tif ftype.IsVariadic() && pnext == ftype.NumIn() {\n\t\t\telemType = p.Elem()\n\t\t}\n\t\tvar v reflect.Value\n\t\tif id, ok := arg.(expect.Identifier); ok && id == \"_\" {\n\t\t\tv = reflect.Zero(elemType)\n\t\t} else {\n\t\t\ta, err := convert(mark, arg, elemType)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tv = reflect.ValueOf(a)\n\t\t}\n\t\targValues = append(argValues, v)\n\t}\n\t// Check that we have sufficient arguments. If the function is variadic, we\n\t// do not need arguments for the final parameter.\n\tif pnext < ftype.NumIn()-1 || pnext == ftype.NumIn()-1 && !ftype.IsVariadic() {\n\t\t// Same comment as above: OK to be vague here.\n\t\treturn nil, fmt.Errorf(\"not enough arguments to %s\", mark.note.Name)\n\t}\n\treturn argValues, nil\n}\n\n// namedArg returns the named argument for name, or the default value.\nfunc namedArg[T any](mark marker, name string, dflt T) T {\n\tif v, ok := mark.note.NamedArgs[name]; ok {\n\t\tif e, ok := v.(T); ok {\n\t\t\treturn e\n\t\t} else {\n\t\t\tv, err := convert(mark, v, reflect.TypeOf(dflt))\n\t\t\tif err != nil {\n\t\t\t\tmark.errorf(\"invalid value for %q: could not convert %v (%T) to %T\", name, v, v, dflt)\n\t\t\t\treturn dflt\n\t\t\t}\n\t\t\treturn v.(T)\n\t\t}\n\t}\n\treturn dflt\n}\n\nfunc namedArgFunc[T any](mark marker, name string, f func(marker, any) (T, error), dflt T) T {\n\tif v, ok := mark.note.NamedArgs[name]; ok {\n\t\tif v2, err := f(mark, v); err == nil {\n\t\t\treturn v2\n\t\t} else {\n\t\t\tmark.errorf(\"invalid value for %q: %v: %v\", name, v, err)\n\t\t}\n\t}\n\treturn dflt\n}\n\nfunc exactlyOneNamedArg(mark marker, names ...string) bool {\n\tvar found []string\n\tfor _, name := range names {\n\t\tif _, ok := mark.note.NamedArgs[name]; ok {\n\t\t\tfound = append(found, name)\n\t\t}\n\t}\n\tif len(found) != 1 {\n\t\tmark.errorf(\"need exactly one of %v to be set, got %v\", names, found)\n\t\treturn false\n\t}\n\treturn true\n}\n\n// is reports whether arg is a T.\nfunc is[T any](arg any) bool {\n\t_, ok := arg.(T)\n\treturn ok\n}\n\n// Supported value marker functions. See [valueMarkerFunc] for more details.\nvar valueMarkerFuncs = map[string]func(marker){\n\t\"loc\":    valueMarkerFunc(locMarker),\n\t\"item\":   valueMarkerFunc(completionItemMarker),\n\t\"hiloc\":  valueMarkerFunc(highlightLocationMarker),\n\t\"defloc\": valueMarkerFunc(defLocMarker),\n}\n\n// Supported action marker functions. See [actionMarkerFunc] for more details.\n//\n// See doc.go for marker documentation.\nvar actionMarkerFuncs = map[string]func(marker){\n\t\"acceptcompletion\": actionMarkerFunc(acceptCompletionMarker),\n\t\"codeaction\":       actionMarkerFunc(codeActionMarker, \"end\", \"diag\", \"action\", \"result\", \"edit\", \"err\"),\n\t\"codelenses\":       actionMarkerFunc(codeLensesMarker),\n\t\"complete\":         actionMarkerFunc(completeMarker),\n\t\"def\":              actionMarkerFunc(defMarker),\n\t\"diag\":             actionMarkerFunc(diagMarker, \"exact\"),\n\t\"documentlink\":     actionMarkerFunc(documentLinkMarker),\n\t\"foldingrange\":     actionMarkerFunc(foldingRangeMarker),\n\t\"format\":           actionMarkerFunc(formatMarker),\n\t\"highlight\":        actionMarkerFunc(highlightMarker),\n\t\"highlightall\":     actionMarkerFunc(highlightAllMarker),\n\t\"hover\":            actionMarkerFunc(hoverMarker),\n\t\"hovererr\":         actionMarkerFunc(hoverErrMarker),\n\t\"implementation\":   actionMarkerFunc(implementationMarker, \"err\"),\n\t\"incomingcalls\":    actionMarkerFunc(incomingCallsMarker),\n\t\"inlayhints\":       actionMarkerFunc(inlayhintsMarker),\n\t\"outgoingcalls\":    actionMarkerFunc(outgoingCallsMarker),\n\t\"preparerename\":    actionMarkerFunc(prepareRenameMarker, \"span\"),\n\t\"rank\":             actionMarkerFunc(rankMarker),\n\t\"refs\":             actionMarkerFunc(refsMarker),\n\t\"rename\":           actionMarkerFunc(renameMarker),\n\t\"renameerr\":        actionMarkerFunc(renameErrMarker),\n\t\"selectionrange\":   actionMarkerFunc(selectionRangeMarker),\n\t\"signature\":        actionMarkerFunc(signatureMarker),\n\t\"snippet\":          actionMarkerFunc(snippetMarker),\n\t\"subtypes\":         actionMarkerFunc(subtypesMarker),\n\t\"supertypes\":       actionMarkerFunc(supertypesMarker),\n\t\"quickfix\":         actionMarkerFunc(quickfixMarker),\n\t\"quickfixerr\":      actionMarkerFunc(quickfixErrMarker),\n\t\"symbol\":           actionMarkerFunc(symbolMarker),\n\t\"token\":            actionMarkerFunc(tokenMarker),\n\t\"typedef\":          actionMarkerFunc(typedefMarker, \"err\"),\n\t\"workspacesymbol\":  actionMarkerFunc(workspaceSymbolMarker),\n\t\"mcptool\":          actionMarkerFunc(mcpToolMarker, \"location\", \"output\"),\n}\n\n// markerTest holds all the test data extracted from a test txtar archive.\n//\n// See the documentation for RunMarkerTests for more information on the archive\n// format.\ntype markerTest struct {\n\tname         string                        // relative path to the txtar file in the testdata dir\n\tfset         *token.FileSet                // fileset used for parsing notes\n\tcontent      []byte                        // raw test content\n\tarchive      *txtar.Archive                // original test archive\n\tsettings     map[string]any                // gopls settings\n\tcapabilities []byte                        // content of capabilities.json file\n\tenv          map[string]string             // editor environment\n\tproxyFiles   map[string][]byte             // proxy content\n\tfiles        map[string][]byte             // data files from the archive (excluding special files)\n\tnotes        []*expect.Note                // extracted notes from data files\n\tgolden       map[expect.Identifier]*Golden // extracted golden content, by identifier name\n\n\tskipReason string   // the skip reason extracted from the \"skip\" archive file\n\tflags      []string // flags extracted from the special \"flags\" archive file.\n\n\t// Parsed flags values. See the flag definitions below for documentation.\n\tminGoVersion, maxGoVersion               string // min/max version of Go runtime\n\tminGoCommandVersion, maxGoCommandVersion string // min/max version of ambient go command\n\n\tcgo              bool\n\twriteGoSum       []string\n\tskipGOOS         []string\n\tskipGOARCH       []string\n\tignoreExtraDiags bool\n\tfilterBuiltins   bool\n\tfilterKeywords   bool\n\terrorsOK         bool\n\tmcp              bool\n}\n\n// flagSet returns the flagset used for parsing the special \"flags\" file in the\n// test archive.\nfunc (t *markerTest) flagSet() *flag.FlagSet {\n\tflags := flag.NewFlagSet(t.name, flag.ContinueOnError)\n\tflags.StringVar(&t.minGoVersion, \"min_go\", \"\", \"if set, the minimum go1.X version required for this test\")\n\tflags.StringVar(&t.maxGoVersion, \"max_go\", \"\", \"if set, the maximum go1.X version required for this test\")\n\tflags.StringVar(&t.minGoCommandVersion, \"min_go_command\", \"\", \"if set, the minimum go1.X go command version required for this test\")\n\tflags.StringVar(&t.maxGoCommandVersion, \"max_go_command\", \"\", \"if set, the maximum go1.X go command version required for this test\")\n\tflags.BoolVar(&t.cgo, \"cgo\", false, \"if set, requires cgo (both the cgo tool and CGO_ENABLED=1)\")\n\tflags.Var((*stringListValue)(&t.writeGoSum), \"write_sumfile\", \"if set, write the sumfile for these directories\")\n\tflags.Var((*stringListValue)(&t.skipGOOS), \"skip_goos\", \"if set, skip this test on these GOOS values\")\n\tflags.Var((*stringListValue)(&t.skipGOARCH), \"skip_goarch\", \"if set, skip this test on these GOARCH values\")\n\tflags.BoolVar(&t.ignoreExtraDiags, \"ignore_extra_diags\", false, \"if set, suppress errors for unmatched diagnostics\")\n\tflags.BoolVar(&t.filterBuiltins, \"filter_builtins\", true, \"if set, filter builtins from completion results\")\n\tflags.BoolVar(&t.filterKeywords, \"filter_keywords\", true, \"if set, filter keywords from completion results\")\n\tflags.BoolVar(&t.errorsOK, \"errors_ok\", false, \"if set, Error level log messages are acceptable in this test\")\n\tflags.BoolVar(&t.mcp, \"mcp\", false, \"if set, enable model context protocol client and server in this test\")\n\treturn flags\n}\n\n// stringListValue implements flag.Value.\ntype stringListValue []string\n\nfunc (l *stringListValue) Set(s string) error {\n\tif s != \"\" {\n\t\tfor d := range strings.SplitSeq(s, \",\") {\n\t\t\t*l = append(*l, strings.TrimSpace(d))\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (l stringListValue) String() string {\n\treturn strings.Join([]string(l), \",\")\n}\n\nfunc (mark *marker) getGolden(id expect.Identifier) *Golden {\n\tt := mark.run.test\n\tgolden, ok := t.golden[id]\n\t// If there was no golden content for this identifier, we must create one\n\t// to handle the case where -update is set: we need a place to store\n\t// the updated content.\n\tif !ok {\n\t\tgolden = &Golden{id: id}\n\n\t\t// TODO(adonovan): the separation of markerTest (the\n\t\t// static aspects) from markerTestRun (the dynamic\n\t\t// ones) is evidently bogus because here we modify\n\t\t// markerTest during execution. Let's merge the two.\n\t\tt.golden[id] = golden\n\t}\n\tif golden.firstReference == \"\" {\n\t\tgolden.firstReference = mark.path()\n\t}\n\treturn golden\n}\n\n// Golden holds extracted golden content for a single @<name> prefix.\n//\n// When -update is set, golden captures the updated golden contents for later\n// writing.\ntype Golden struct {\n\tid             expect.Identifier\n\tfirstReference string            // file name first referencing this golden content\n\tdata           map[string][]byte // key \"\" => @id itself\n\tupdated        map[string][]byte\n}\n\n// Get returns golden content for the given name, which corresponds to the\n// relative path following the golden prefix @<name>/. For example, to access\n// the content of @foo/path/to/result.json from the Golden associated with\n// @foo, name should be \"path/to/result.json\".\n//\n// If -update is set, the given update function will be called to get the\n// updated golden content that should be written back to testdata.\n//\n// Marker functions must use this method instead of accessing data entries\n// directly otherwise the -update operation will delete those entries.\n//\n// TODO(rfindley): rethink the logic here. We may want to separate Get and Set,\n// and not delete golden content that isn't set.\nfunc (g *Golden) Get(t testing.TB, name string, updated []byte) ([]byte, bool) {\n\tif existing, ok := g.updated[name]; ok {\n\t\t// Multiple tests may reference the same golden data, but if they do they\n\t\t// must agree about its expected content.\n\t\tif diff := compare.NamedText(\"existing\", \"updated\", string(existing), string(updated)); diff != \"\" {\n\t\t\tt.Errorf(\"conflicting updates for golden data %s/%s:\\n%s\", g.id, name, diff)\n\t\t}\n\t}\n\tif g.updated == nil {\n\t\tg.updated = make(map[string][]byte)\n\t}\n\tg.updated[name] = updated\n\tif *update {\n\t\treturn updated, true\n\t}\n\n\tres, ok := g.data[name]\n\treturn res, ok\n}\n\n// loadMarkerTests walks the given dir looking for .txt files, which it\n// interprets as a txtar archive.\n//\n// See the documentation for RunMarkerTests for more details on the test data\n// archive.\nfunc loadMarkerTests(dir string) ([]*markerTest, error) {\n\tvar tests []*markerTest\n\terr := filepath.WalkDir(dir, func(path string, _ fs.DirEntry, err error) error {\n\t\tif strings.HasSuffix(path, \".txt\") {\n\t\t\tcontent, err := os.ReadFile(path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tname := filepath.ToSlash(strings.TrimPrefix(path, dir+string(filepath.Separator)))\n\t\t\ttest, err := loadMarkerTest(name, content)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%s: %v\", path, err)\n\t\t\t}\n\t\t\ttests = append(tests, test)\n\t\t}\n\t\treturn err\n\t})\n\treturn tests, err\n}\n\nfunc loadMarkerTest(name string, content []byte) (*markerTest, error) {\n\tarchive := txtar.Parse(content)\n\tif len(archive.Files) == 0 {\n\t\treturn nil, fmt.Errorf(\"txtar file has no '-- filename --' sections\")\n\t}\n\tif bytes.Contains(archive.Comment, []byte(\"\\n-- \")) {\n\t\t// This check is conservative, but the comment is only a comment.\n\t\treturn nil, fmt.Errorf(\"ill-formed '-- filename --' header in comment\")\n\t}\n\ttest := &markerTest{\n\t\tname:    name,\n\t\tfset:    token.NewFileSet(),\n\t\tcontent: content,\n\t\tarchive: archive,\n\t\tfiles:   make(map[string][]byte),\n\t\tgolden:  make(map[expect.Identifier]*Golden),\n\t}\n\tseen := make(map[string]bool)\n\tfor _, file := range archive.Files {\n\t\tif seen[file.Name] {\n\t\t\treturn nil, fmt.Errorf(\"duplicate archive section %q\", file.Name)\n\t\t}\n\t\tseen[file.Name] = true\n\t\tswitch {\n\t\tcase file.Name == \"skip\":\n\t\t\treason := strings.ReplaceAll(string(file.Data), \"\\n\", \" \")\n\t\t\treason = strings.TrimSpace(reason)\n\t\t\ttest.skipReason = reason\n\n\t\tcase file.Name == \"flags\":\n\t\t\ttest.flags = strings.Fields(string(file.Data))\n\n\t\tcase file.Name == \"settings.json\":\n\t\t\tif err := json.Unmarshal(file.Data, &test.settings); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\tcase file.Name == \"capabilities.json\":\n\t\t\ttest.capabilities = file.Data // lazily unmarshalled by the editor\n\n\t\tcase file.Name == \"env\":\n\t\t\ttest.env = make(map[string]string)\n\t\t\tfields := strings.Fields(string(file.Data))\n\t\t\tfor _, field := range fields {\n\t\t\t\tkey, value, ok := strings.Cut(field, \"=\")\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"env vars must be formatted as var=value, got %q\", field)\n\t\t\t\t}\n\t\t\t\ttest.env[key] = value\n\t\t\t}\n\n\t\tcase strings.HasPrefix(file.Name, \"@\"): // golden content\n\t\t\tidstring, name, _ := strings.Cut(file.Name[len(\"@\"):], \"/\")\n\t\t\tid := expect.Identifier(idstring)\n\t\t\t// Note that a file.Name of just \"@id\" gives (id, name) = (\"id\", \"\").\n\t\t\tif _, ok := test.golden[id]; !ok {\n\t\t\t\ttest.golden[id] = &Golden{\n\t\t\t\t\tid:   id,\n\t\t\t\t\tdata: make(map[string][]byte),\n\t\t\t\t}\n\t\t\t}\n\t\t\ttest.golden[id].data[name] = file.Data\n\n\t\tcase strings.HasPrefix(file.Name, \"proxy/\"):\n\t\t\tname := file.Name[len(\"proxy/\"):]\n\t\t\tif test.proxyFiles == nil {\n\t\t\t\ttest.proxyFiles = make(map[string][]byte)\n\t\t\t}\n\t\t\ttest.proxyFiles[name] = file.Data\n\n\t\tdefault: // ordinary file content\n\t\t\tnotes, err := expect.Parse(test.fset, file.Name, file.Data)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing notes in %q: %v\", file.Name, err)\n\t\t\t}\n\n\t\t\t// Reject common misspelling: \"// @mark\".\n\t\t\t// TODO(adonovan): permit \"// @\" within a string. Detect multiple spaces.\n\t\t\tif i := bytes.Index(file.Data, []byte(\"// @\")); i >= 0 {\n\t\t\t\tline := 1 + bytes.Count(file.Data[:i], []byte(\"\\n\"))\n\t\t\t\treturn nil, fmt.Errorf(\"%s:%d: unwanted space before marker (// @)\", file.Name, line)\n\t\t\t}\n\n\t\t\t// The 'go list' command doesn't work correct with modules named\n\t\t\t// testdata\", so don't allow it as a module name (golang/go#65406).\n\t\t\t// (Otherwise files within it will end up in an ad hoc\n\t\t\t// package, \"command-line-arguments/$TMPDIR/...\".)\n\t\t\tif filepath.Base(file.Name) == \"go.mod\" &&\n\t\t\t\tbytes.Contains(file.Data, []byte(\"module testdata\")) {\n\t\t\t\treturn nil, fmt.Errorf(\"'testdata' is not a valid module name\")\n\t\t\t}\n\n\t\t\ttest.notes = append(test.notes, notes...)\n\t\t\ttest.files[file.Name] = file.Data\n\t\t}\n\n\t\t// Print a warning if we see what looks like \"-- filename --\"\n\t\t// without the second \"--\". It's not necessarily wrong,\n\t\t// but it should almost never appear in our test inputs.\n\t\tif bytes.Contains(file.Data, []byte(\"\\n-- \")) {\n\t\t\tlog.Printf(\"ill-formed '-- filename --' header in %s?\", file.Name)\n\t\t}\n\t}\n\n\t// Parse flags after loading files, as they may have been set by the \"flags\" file.\n\tset := test.flagSet()\n\tif err := set.Parse(test.flags); err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing flags: %v\", err)\n\t}\n\tif set.NArg() > 0 {\n\t\treturn nil, fmt.Errorf(\"surplus arguments after flags: %q\", set.Args())\n\t}\n\n\treturn test, nil\n}\n\n// formatTest formats the test as a txtar archive.\nfunc formatTest(test *markerTest) ([]byte, error) {\n\tarch := &txtar.Archive{\n\t\tComment: test.archive.Comment,\n\t}\n\n\tupdatedGolden := make(map[string][]byte)\n\tfirstReferences := make(map[string]string)\n\tfor id, g := range test.golden {\n\t\tfor name, data := range g.updated {\n\t\t\tfilename := \"@\" + path.Join(string(id), name) // name may be \"\"\n\t\t\tupdatedGolden[filename] = data\n\t\t\tfirstReferences[filename] = g.firstReference\n\t\t}\n\t}\n\n\t// Preserve the original ordering of archive files.\n\tfor _, file := range test.archive.Files {\n\t\tswitch file.Name {\n\t\t// Preserve configuration files exactly as they were. They must have parsed\n\t\t// if we got this far.\n\t\tcase \"skip\", \"flags\", \"settings.json\", \"capabilities.json\", \"env\":\n\t\t\tarch.Files = append(arch.Files, file)\n\t\tdefault:\n\t\t\tif _, ok := test.files[file.Name]; ok { // ordinary file\n\t\t\t\tarch.Files = append(arch.Files, file)\n\t\t\t} else if strings.HasPrefix(file.Name, \"proxy/\") { // proxy file\n\t\t\t\tarch.Files = append(arch.Files, file)\n\t\t\t} else if data, ok := updatedGolden[file.Name]; ok { // golden file\n\t\t\t\tarch.Files = append(arch.Files, txtar.File{Name: file.Name, Data: data})\n\t\t\t\tdelete(updatedGolden, file.Name)\n\t\t\t}\n\t\t}\n\t}\n\n\t// ...but insert new golden files after their first reference.\n\tvar newGoldenFiles []txtar.File\n\tfor filename, data := range updatedGolden {\n\t\t// TODO(rfindley): it looks like this implicitly removes trailing newlines\n\t\t// from golden content. Is there any way to fix that? Perhaps we should\n\t\t// just make the diff tolerant of missing newlines?\n\t\tnewGoldenFiles = append(newGoldenFiles, txtar.File{Name: filename, Data: data})\n\t}\n\t// Sort new golden files lexically.\n\tsort.Slice(newGoldenFiles, func(i, j int) bool {\n\t\treturn newGoldenFiles[i].Name < newGoldenFiles[j].Name\n\t})\n\tfor _, g := range newGoldenFiles {\n\t\tinsertAt := len(arch.Files)\n\t\tif firstRef := firstReferences[g.Name]; firstRef != \"\" {\n\t\t\tfor i, f := range arch.Files {\n\t\t\t\tif f.Name == firstRef {\n\t\t\t\t\t// Insert alphabetically among golden files following the test file.\n\t\t\t\t\tfor i++; i < len(arch.Files); i++ {\n\t\t\t\t\t\tf := arch.Files[i]\n\t\t\t\t\t\tif !strings.HasPrefix(f.Name, \"@\") || f.Name >= g.Name {\n\t\t\t\t\t\t\tinsertAt = i\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tarch.Files = slices.Insert(arch.Files, insertAt, g)\n\t}\n\n\treturn txtar.Format(arch), nil\n}\n\n// newEnv creates a new environment for a marker test.\n//\n// TODO(rfindley): simplify and refactor the construction of testing\n// environments across integration tests, marker tests, and benchmarks.\nfunc newEnv(t *testing.T, cache *cache.Cache, files, proxyFiles map[string][]byte, writeGoSum []string, config fake.EditorConfig, enableMCP bool) *integration.Env {\n\tsandbox, err := fake.NewSandbox(&fake.SandboxConfig{\n\t\tRootDir:    t.TempDir(),\n\t\tFiles:      files,\n\t\tProxyFiles: proxyFiles,\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, dir := range writeGoSum {\n\t\tif _, err := sandbox.RunGoCommand(context.Background(), dir, \"list\", []string{\"-mod=mod\", \"...\"}, []string{\"GOWORK=off\"}, true); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\t// Put a debug instance in the context to prevent logging to stderr.\n\t// See associated TODO in runner.go: we should revisit this pattern.\n\tctx := context.Background()\n\tctx = debug.WithInstance(ctx, \"\")\n\n\tawaiter := integration.NewAwaiter(sandbox.Workdir)\n\n\tss := lsprpc.NewStreamServer(cache, false, nil)\n\n\tvar mcpServer *httptest.Server\n\tif enableMCP {\n\t\tmcpServer = httptest.NewServer(internalmcp.HTTPHandler(ss, false, nil))\n\t}\n\n\tserver := servertest.NewPipeServer(ss, jsonrpc2.NewRawStream)\n\teditor, err := fake.NewEditor(sandbox, config).Connect(ctx, server, awaiter.Hooks())\n\tif err != nil {\n\t\tsandbox.Close() // ignore error\n\t\tt.Fatal(err)\n\t}\n\n\tif err := awaiter.Await(ctx, integration.OnceMet(\n\t\tintegration.InitialWorkspaceLoad,\n\t\tintegration.NoShownMessage(\"\"),\n\t)); err != nil {\n\t\tsandbox.Close() // ignore error\n\t\tt.Fatal(err)\n\t}\n\n\tvar mcpSession *mcp.ClientSession\n\tif enableMCP {\n\t\tclient := mcp.NewClient(&mcp.Implementation{Name: \"test\", Version: \"v1.0.0\"}, nil)\n\t\tmcpSession, err = client.Connect(ctx, &mcp.SSEClientTransport{Endpoint: mcpServer.URL}, nil)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"fail to connect to mcp server: %v\", err)\n\t\t}\n\t}\n\n\treturn &integration.Env{\n\t\tTB:         t,\n\t\tCtx:        ctx,\n\t\tEditor:     editor,\n\t\tSandbox:    sandbox,\n\t\tAwaiter:    awaiter,\n\t\tMCPSession: mcpSession,\n\t\tMCPServer:  mcpServer,\n\t}\n}\n\n// A markerTestRun holds the state of one run of a marker test archive.\ntype markerTestRun struct {\n\ttest     *markerTest\n\tenv      *integration.Env\n\tsettings map[string]any\n\n\t// Collected information.\n\t// Each @diag/@quickfix marker eliminates an entry from diags.\n\tvalues map[expect.Identifier]any\n\tdiags  map[protocol.Location][]protocol.Diagnostic // diagnostics by position; location end == start\n\n\t// Notes that weren't associated with a top-level marker func. They may be\n\t// consumed by another marker (e.g. @codelenses collects @codelens markers).\n\t// Any notes that aren't consumed are flagged as an error.\n\textraNotes map[protocol.DocumentURI]map[string][]*expect.Note\n}\n\n// sprintf returns a formatted string after applying pre-processing to\n// arguments of the following types:\n//   - token.Pos: formatted using (*markerTestRun).fmtPos\n//   - protocol.Location: formatted using (*markerTestRun).fmtLoc\nfunc (c *marker) sprintf(format string, args ...any) string {\n\tif false {\n\t\t_ = fmt.Sprintf(format, args...) // enable vet printf checker\n\t}\n\tvar args2 []any\n\tfor _, arg := range args {\n\t\tswitch arg := arg.(type) {\n\t\tcase token.Pos:\n\t\t\targs2 = append(args2, c.run.fmtPos(arg))\n\t\tcase protocol.Location:\n\t\t\targs2 = append(args2, c.run.fmtLoc(arg))\n\t\tdefault:\n\t\t\targs2 = append(args2, arg)\n\t\t}\n\t}\n\treturn fmt.Sprintf(format, args2...)\n}\n\n// fmtPos formats the given pos in the context of the test, using\n// archive-relative paths for files and including the line number in the full\n// archive file.\nfunc (run *markerTestRun) fmtPos(pos token.Pos) string {\n\tfile := run.test.fset.File(pos)\n\tif file == nil {\n\t\trun.env.TB.Errorf(\"position %d not in test fileset\", pos)\n\t\treturn \"<invalid location>\"\n\t}\n\tm, err := run.env.Editor.Mapper(file.Name())\n\tif err != nil {\n\t\trun.env.TB.Errorf(\"%s\", err)\n\t\treturn \"<invalid location>\"\n\t}\n\tloc, err := m.PosLocation(file, pos, pos)\n\tif err != nil {\n\t\trun.env.TB.Errorf(\"Mapper(%s).PosLocation failed: %v\", file.Name(), err)\n\t}\n\treturn run.fmtLoc(loc)\n}\n\n// fmtLoc formats the given location in the context of the test, using\n// archive-relative paths for files and including the line number in the full\n// archive file.\nfunc (run *markerTestRun) fmtLoc(loc protocol.Location) string {\n\tif loc == (protocol.Location{}) {\n\t\trun.env.TB.Errorf(\"unable to find %s in test archive\", loc)\n\t\treturn \"<invalid location>\"\n\t}\n\n\t// Format builtin locations as \"file:///pseudo/builtin/builtin.go:0:0\",\n\t// which is the predefined BUILTIN marker; ditto UNSAFE.\n\tif strings.HasSuffix(string(loc.URI), \"src/unsafe/unsafe.go\") ||\n\t\tstrings.HasSuffix(string(loc.URI), \"src/builtin/builtin.go\") {\n\t\tname := filepath.Base(filepath.Dir(loc.URI.Path())) // \"unsafe\" or \"builtin\"\n\t\tloc.URI = protocol.DocumentURI(\"file:///pseudo/\" + name + \"/\" + name + \".go\")\n\t\tloc.Range = protocol.Range{}\n\t}\n\n\tlines := bytes.Count(run.test.archive.Comment, []byte(\"\\n\"))\n\tvar name string\n\tfor _, f := range run.test.archive.Files {\n\t\tlines++ // -- separator --\n\t\turi := run.env.Sandbox.Workdir.URI(f.Name)\n\t\tif uri == loc.URI {\n\t\t\tname = f.Name\n\t\t\tbreak\n\t\t}\n\t\tlines += bytes.Count(f.Data, []byte(\"\\n\"))\n\t}\n\tif name == \"\" {\n\t\t// Fall back to formatting the \"lsp\" location.\n\t\t// These will be in UTF-16, but we probably don't need to clarify that,\n\t\t// since it will be implied by the file:// URI format.\n\t\treturn summarizeLoc(string(loc.URI),\n\t\t\tint(loc.Range.Start.Line), int(loc.Range.Start.Character),\n\t\t\tint(loc.Range.End.Line), int(loc.Range.End.Character))\n\t}\n\tname, startLine, startCol, endLine, endCol := run.mapLocation(loc)\n\tinnerSpan := summarizeLoc(name, startLine, startCol, endLine, endCol)\n\touterSpan := summarizeLoc(run.test.name, lines+startLine, startCol, lines+endLine, endCol)\n\treturn fmt.Sprintf(\"%s (%s)\", innerSpan, outerSpan)\n}\n\n// mapLocation returns the relative path and utf8 span of the corresponding\n// location, which must be a valid location in an archive file.\nfunc (run *markerTestRun) mapLocation(loc protocol.Location) (name string, startLine, startCol, endLine, endCol int) {\n\t// Note: Editor.Mapper fails if loc.URI is not open, but we always open all\n\t// archive files, so this is probably OK.\n\t//\n\t// In the future, we may want to have the editor read contents from disk if\n\t// the URI is not open.\n\tname = run.env.Sandbox.Workdir.URIToPath(loc.URI)\n\tm, err := run.env.Editor.Mapper(name)\n\tif err != nil {\n\t\trun.env.TB.Errorf(\"internal error: %v\", err)\n\t\treturn\n\t}\n\tstart, end, err := m.RangeOffsets(loc.Range)\n\tif err != nil {\n\t\trun.env.TB.Errorf(\"error formatting location %s: %v\", loc, err)\n\t\treturn\n\t}\n\tstartLine, startCol = m.OffsetLineCol8(start)\n\tendLine, endCol = m.OffsetLineCol8(end)\n\treturn name, startLine, startCol, endLine, endCol\n}\n\n// fmtLocForGolden is like fmtLoc, but chooses more succinct and stable\n// formatting, such as would be used for formatting locations in Golden\n// content.\nfunc (run *markerTestRun) fmtLocForGolden(loc protocol.Location) string {\n\tif loc == (protocol.Location{}) {\n\t\treturn \"<invalid location>\"\n\t}\n\tname := run.env.Sandbox.Workdir.URIToPath(loc.URI)\n\t// Note: we check IsAbs on filepaths rather than the slash-ified name for\n\t// accurate handling of windows drive letters.\n\tif filepath.IsAbs(filepath.FromSlash(name)) {\n\t\t// Don't format any position information in this case, since it will be\n\t\t// volatile.\n\t\treturn \"<external>\"\n\t}\n\treturn summarizeLoc(run.mapLocation(loc))\n}\n\n// summarizeLoc formats a summary of the given location, in the form\n//\n//\t<name>:<startLine>:<startCol>[-[<endLine>:]endCol]\nfunc summarizeLoc(name string, startLine, startCol, endLine, endCol int) string {\n\tspan := fmt.Sprintf(\"%s:%d:%d\", name, startLine, startCol)\n\tif startLine != endLine || startCol != endCol {\n\t\tspan += \"-\"\n\t\tif endLine != startLine {\n\t\t\tspan += fmt.Sprintf(\"%d:\", endLine)\n\t\t}\n\t\tspan += fmt.Sprintf(\"%d\", endCol)\n\t}\n\treturn span\n}\n\n// ---- converters ----\n\n// Types with special handling.\nvar (\n\tgoldenType        = reflect.TypeFor[*Golden]()\n\tmarkerType        = reflect.TypeFor[marker]()\n\tstringMatcherType = reflect.TypeFor[stringMatcher]()\n)\n\n// Custom conversions.\n//\n// These functions are called after valueMarkerFuncs have run to convert\n// arguments into the desired parameter types.\n//\n// Converters should return an error rather than calling marker.errorf().\nvar customConverters = map[reflect.Type]func(marker, any) (any, error){\n\treflect.TypeFor[protocol.Location](): converter(convertLocation),\n\treflect.TypeFor[completionLabel]():   converter(convertCompletionLabel),\n}\n\n// converter transforms a typed argument conversion function to an untyped\n// conversion function.\nfunc converter[T any](f func(marker, any) (T, error)) func(marker, any) (any, error) {\n\treturn func(m marker, arg any) (any, error) {\n\t\treturn f(m, arg)\n\t}\n}\n\nfunc convert(mark marker, arg any, paramType reflect.Type) (any, error) {\n\t// Handle stringMatcher and golden parameters before resolving identifiers,\n\t// because golden content lives in a separate namespace from other\n\t// identifiers.\n\t// TODO(rfindley): simplify by flattening the namespace. This interacts\n\t// poorly with named argument resolution.\n\tswitch paramType {\n\tcase stringMatcherType:\n\t\treturn convertStringMatcher(mark, arg)\n\tcase goldenType:\n\t\tid, ok := arg.(expect.Identifier)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid input type %T: golden key must be an identifier\", arg)\n\t\t}\n\t\treturn mark.getGolden(id), nil\n\t}\n\tif id, ok := arg.(expect.Identifier); ok {\n\t\tif arg2, ok := mark.run.values[id]; ok {\n\t\t\targ = arg2\n\t\t}\n\t}\n\tif converter, ok := customConverters[paramType]; ok {\n\t\targ2, err := converter(mark, arg)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\targ = arg2\n\t}\n\tif reflect.TypeOf(arg).AssignableTo(paramType) {\n\t\treturn arg, nil // no conversion required\n\t}\n\treturn nil, fmt.Errorf(\"cannot convert %v (%T) to %s\", arg, arg, paramType)\n}\n\n// convertNamedArgLocation is a workaround for converting locations referenced\n// by a named argument. See the TODO in [convert]: this wouldn't be necessary\n// if we flattened the namespace such that golden content lived in the same\n// namespace as values.\nfunc convertNamedArgLocation(mark marker, arg any) (protocol.Location, error) {\n\tif id, ok := arg.(expect.Identifier); ok {\n\t\tif v, ok := mark.run.values[id]; ok {\n\t\t\tif loc, ok := v.(protocol.Location); ok {\n\t\t\t\treturn loc, nil\n\t\t\t}\n\t\t\treturn protocol.Location{}, fmt.Errorf(\"invalid location value %v\", v)\n\t\t}\n\t}\n\treturn convertLocation(mark, arg)\n}\n\n// convertLocation converts a string or regexp argument into the protocol\n// location corresponding to the first position of the string (or first match\n// of the regexp) in the line preceding the note.\nfunc convertLocation(mark marker, arg any) (protocol.Location, error) {\n\t// matchContent is used to match the given argument against the file content\n\t// starting at the marker line.\n\tvar matchContent func([]byte) (int, int, error)\n\n\tswitch arg := arg.(type) {\n\tcase protocol.Location:\n\t\treturn arg, nil // nothing to do\n\tcase string:\n\t\tmatchContent = func(content []byte) (int, int, error) {\n\t\t\tidx := bytes.Index(content, []byte(arg))\n\t\t\tif idx < 0 {\n\t\t\t\treturn 0, 0, fmt.Errorf(\"substring %q not found\", arg)\n\t\t\t}\n\t\t\treturn idx, idx + len(arg), nil\n\t\t}\n\tcase *regexp.Regexp:\n\t\tmatchContent = func(content []byte) (int, int, error) {\n\t\t\tmatches := arg.FindSubmatchIndex(content)\n\t\t\tif len(matches) == 0 {\n\t\t\t\treturn 0, 0, fmt.Errorf(\"no match for regexp %q\", arg)\n\t\t\t}\n\t\t\tswitch len(matches) {\n\t\t\tcase 2:\n\t\t\t\t// no subgroups: return the range of the regexp expression\n\t\t\t\treturn matches[0], matches[1], nil\n\t\t\tcase 4:\n\t\t\t\t// one subgroup: return its range\n\t\t\t\treturn matches[2], matches[3], nil\n\t\t\tdefault:\n\t\t\t\treturn 0, 0, fmt.Errorf(\"invalid location regexp %q: expect either 0 or 1 subgroups, got %d\", arg, len(matches)/2-1)\n\t\t\t}\n\t\t}\n\tdefault:\n\t\treturn protocol.Location{}, fmt.Errorf(\"cannot convert argument type %T to location (must be a string or regexp to match the preceding line)\", arg)\n\t}\n\n\t// Now use matchFunc to match a range starting on the marker line.\n\n\tfile := mark.run.test.fset.File(mark.note.Pos)\n\tposn := safetoken.Position(file, mark.note.Pos)\n\tlineStart := file.LineStart(posn.Line)\n\tlineStartOff, lineEndOff, err := safetoken.Offsets(file, lineStart, mark.note.Pos)\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tm := mark.mapper()\n\tstart, end, err := matchContent(m.Content[lineStartOff:])\n\tif err != nil {\n\t\treturn protocol.Location{}, err\n\t}\n\tstartOff, endOff := lineStartOff+start, lineStartOff+end\n\tif startOff > lineEndOff {\n\t\t// The start of the match must be between the start of the line and the\n\t\t// marker position (inclusive).\n\t\treturn protocol.Location{}, fmt.Errorf(\"no matching range found starting on the current line\")\n\t}\n\treturn m.OffsetLocation(startOff, endOff)\n}\n\n// completionLabel is a special parameter type that may be converted from a\n// string literal, or extracted from a completion item.\n//\n// See [convertCompletionLabel].\ntype completionLabel string\n\n// convertCompletionLabel coerces an argument to a [completionLabel] parameter\n// type.\n//\n// If the arg is a string, it is trivially converted. If the arg is a\n// completionItem, its label is extracted.\n//\n// This allows us to stage a migration of the \"snippet\" marker to a simpler\n// model where the completion label can just be listed explicitly.\nfunc convertCompletionLabel(mark marker, arg any) (completionLabel, error) {\n\tswitch arg := arg.(type) {\n\tcase string:\n\t\treturn completionLabel(arg), nil\n\tcase completionItem:\n\t\treturn completionLabel(arg.Label), nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"cannot convert argument type %T to completion label (must be a string or completion item)\", arg)\n\t}\n}\n\n// convertStringMatcher converts a string, regexp, or identifier\n// argument into a stringMatcher. The string is a substring of the\n// expected error, the regexp is a pattern than matches the expected\n// error, and the identifier is a golden file containing the expected\n// error.\nfunc convertStringMatcher(mark marker, arg any) (stringMatcher, error) {\n\tswitch arg := arg.(type) {\n\tcase string:\n\t\treturn stringMatcher{substr: arg}, nil\n\tcase *regexp.Regexp:\n\t\treturn stringMatcher{pattern: arg}, nil\n\tcase expect.Identifier:\n\t\tgolden := mark.getGolden(arg)\n\t\treturn stringMatcher{golden: golden}, nil\n\tdefault:\n\t\treturn stringMatcher{}, fmt.Errorf(\"cannot convert %T to wantError (want: string, regexp, or identifier)\", arg)\n\t}\n}\n\n// A stringMatcher represents an expectation of a specific string value.\n//\n// It may be indicated in one of three ways, in 'expect' notation:\n//   - an identifier 'foo', to compare (exactly) with the contents of the golden\n//     section @foo;\n//   - a pattern expression re\"ab.*c\", to match against a regular expression;\n//   - a string literal \"abc\", to check for a substring.\ntype stringMatcher struct {\n\tgolden  *Golden\n\tpattern *regexp.Regexp\n\tsubstr  string\n}\n\n// empty reports whether the receiver is an empty stringMatcher.\nfunc (sm stringMatcher) empty() bool {\n\treturn sm.golden == nil && sm.pattern == nil && sm.substr == \"\"\n}\n\nfunc (sm stringMatcher) String() string {\n\tif sm.golden != nil {\n\t\treturn fmt.Sprintf(\"content from @%s entry\", sm.golden.id)\n\t} else if sm.pattern != nil {\n\t\treturn fmt.Sprintf(\"content matching %#q\", sm.pattern)\n\t} else {\n\t\treturn fmt.Sprintf(\"content with substring %q\", sm.substr)\n\t}\n}\n\n// checkErr asserts that the given error matches the stringMatcher's expectations.\nfunc (sm stringMatcher) checkErr(mark marker, err error) {\n\tif err == nil {\n\t\tmark.errorf(\"@%s succeeded unexpectedly, want %v\", mark.note.Name, sm)\n\t\treturn\n\t}\n\tsm.check(mark, err.Error())\n}\n\n// check asserts that the given content matches the stringMatcher's expectations.\nfunc (sm stringMatcher) check(mark marker, got string) {\n\tif sm.golden != nil {\n\t\tcompareGolden(mark, []byte(got), sm.golden)\n\t} else if sm.pattern != nil {\n\t\t// Content must match the regular expression pattern.\n\t\tif !sm.pattern.MatchString(got) {\n\t\t\tmark.errorf(\"got %q, does not match pattern %#q\", got, sm.pattern)\n\t\t}\n\t} else if !strings.Contains(got, sm.substr) {\n\t\t// Content must contain the expected substring.\n\t\tmark.errorf(\"got %q, want substring %q\", got, sm.substr)\n\t}\n}\n\n// checkChangedFiles compares the files changed by an operation with their expected (golden) state.\nfunc checkChangedFiles(mark marker, changed map[string][]byte, golden *Golden) {\n\t// Check changed files match expectations.\n\tfor filename, got := range changed {\n\t\tif want, ok := golden.Get(mark.T(), filename, got); !ok {\n\t\t\tmark.errorf(\"%s: unexpected change to file %s; got:\\n%s\",\n\t\t\t\tmark.note.Name, filename, got)\n\t\t} else if string(got) != string(want) {\n\t\t\tmark.errorf(\"%s: wrong file content for %s:\\n-- got --\\n%s\\n-- want --\\n%s\\n-- diff --\\n%s\",\n\t\t\t\tmark.note.Name, filename, got, want,\n\t\t\t\tcompare.Bytes(want, got))\n\t\t}\n\t}\n\n\t// Report unmet expectations.\n\tfor filename := range golden.data {\n\t\tif _, ok := changed[filename]; !ok {\n\t\t\twant, _ := golden.Get(mark.T(), filename, nil)\n\t\t\tmark.errorf(\"%s: missing change to file %s; want:\\n%s\",\n\t\t\t\tmark.note.Name, filename, want)\n\t\t}\n\t}\n}\n\n// checkDiffs checks that the diff content stored in the given golden directory\n// converts the original contents into the changed contents.\n// (This logic is strange because hundreds of existing marker tests were created\n// containing a modified version of unified diffs.)\nfunc checkDiffs(mark marker, changed map[string][]byte, golden *Golden) {\n\tfor name, after := range changed {\n\t\tbefore := mark.run.env.FileContent(name)\n\t\tedits := diff.Lines(before, string(after))\n\t\td, err := diff.ToUnified(\"before\", \"after\", before, edits, 0)\n\t\tif err != nil {\n\t\t\t// Can't happen: edits are consistent.\n\t\t\tlog.Fatalf(\"internal error in diff.ToUnified: %v\", err)\n\t\t}\n\t\t// Trim the unified header from diffs, as it is unnecessary and repetitive.\n\t\t// (an artifact of ToUnified, but not stored in the marker files)\n\t\tdifflines := strings.Split(d, \"\\n\")\n\t\tvar got string\n\t\tif len(difflines) >= 2 && strings.HasPrefix(difflines[1], \"+++\") {\n\t\t\tgot = strings.Join(difflines[2:], \"\\n\")\n\t\t} else {\n\t\t\tgot = d // \"\" in packagedecl.txt:147\n\t\t}\n\t\t// the call to Get is so that the -update flag will update the test.\n\t\t// normally it just returns 'got'.\n\t\tif tdiffs, ok := golden.Get(mark.T(), name, []byte(got)); !ok {\n\t\t\tmark.errorf(\"%s: unexpected change to file %s; got diff:\\n%s\",\n\t\t\t\tmark.note.Name, name, got)\n\t\t\treturn\n\t\t} else {\n\t\t\t// restore the ToUnified header lines deleted above\n\t\t\t// before calling ApplyUnified\n\t\t\tdiffsFromTest := \"--- \\n+++ \\n\" + string(tdiffs)\n\t\t\twant, err := diff.ApplyUnified(diffsFromTest, before)\n\t\t\tif err != nil {\n\t\t\t\tmark.errorf(\"%s: ApplyUnified(%q,%q) failed: %v\",\n\t\t\t\t\tmark.note.Name, before, after, err)\n\t\t\t}\n\t\t\tif want != string(after) {\n\t\t\t\tmark.errorf(\"%s: got\\n%q expected\\n%q\",\n\t\t\t\t\tmark.note.Name, want, string(after))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Report unmet expectations.\n\tfor filename := range golden.data {\n\t\tif _, ok := changed[filename]; !ok {\n\t\t\twant, _ := golden.Get(mark.T(), filename, nil)\n\t\t\tmark.errorf(\"%s: missing change to file %s; want:\\n%s\",\n\t\t\t\tmark.note.Name, filename, want)\n\t\t}\n\t}\n}\n\n// ---- marker functions ----\n\n// TODO(rfindley): consolidate documentation of these markers. They are already\n// documented above, so much of the documentation here is redundant.\n\n// completionItem is a simplified summary of a completion item.\ntype completionItem struct {\n\tLabel, Detail, Kind, Documentation string\n}\n\nfunc completionItemMarker(mark marker, label string, other ...string) completionItem {\n\tif len(other) > 3 {\n\t\tmark.errorf(\"too many arguments to @item: expect at most 4\")\n\t}\n\titem := completionItem{\n\t\tLabel: label,\n\t}\n\tif len(other) > 0 {\n\t\titem.Detail = other[0]\n\t}\n\tif len(other) > 1 {\n\t\titem.Kind = other[1]\n\t}\n\tif len(other) > 2 {\n\t\titem.Documentation = other[2]\n\t}\n\treturn item\n}\n\nfunc rankMarker(mark marker, src protocol.Location, items ...completionLabel) {\n\t// Separate positive and negative items (expectations).\n\tvar pos, neg []completionLabel\n\tfor _, item := range items {\n\t\tif strings.HasPrefix(string(item), \"!\") {\n\t\t\tneg = append(neg, item)\n\t\t} else {\n\t\t\tpos = append(pos, item)\n\t\t}\n\t}\n\n\t// Collect results that are present in items, preserving their order.\n\tlist := mark.run.env.Completion(src)\n\tvar got []string\n\tfor _, g := range list.Items {\n\t\tfor _, w := range pos {\n\t\t\tif g.Label == string(w) {\n\t\t\t\tgot = append(got, g.Label)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tfor _, w := range neg {\n\t\t\tif g.Label == string(w[len(\"!\"):]) {\n\t\t\t\tmark.errorf(\"got unwanted completion: %s\", g.Label)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tvar want []string\n\tfor _, w := range pos {\n\t\twant = append(want, string(w))\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tmark.errorf(\"completion rankings do not match (-want +got):\\n%s\", diff)\n\t}\n}\n\nfunc snippetMarker(mark marker, src protocol.Location, label completionLabel, want string) {\n\tlist := mark.run.env.Completion(src)\n\tvar (\n\t\tfound bool\n\t\tgot   string\n\t\tall   []string // for errors\n\t)\n\titems := filterBuiltinsAndKeywords(mark, list.Items)\n\tfor _, i := range items {\n\t\tall = append(all, i.Label)\n\t\tif i.Label == string(label) {\n\t\t\tfound = true\n\t\t\tif i.TextEdit != nil {\n\t\t\t\tif edit, err := protocol.SelectCompletionTextEdit(i, false); err == nil {\n\t\t\t\t\tgot = edit.NewText\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\tif !found {\n\t\tmark.errorf(\"no completion item found matching %s (got: %v)\", label, all)\n\t\treturn\n\t}\n\tif got != want {\n\t\tmark.errorf(\"snippets do not match: got:\\n%q\\nwant:\\n%q\", got, want)\n\t}\n}\n\n// completeMarker implements the @complete marker, running\n// textDocument/completion at the given src location and asserting that the\n// results match the expected results.\nfunc completeMarker(mark marker, src protocol.Location, want ...completionItem) {\n\tlist := mark.run.env.Completion(src)\n\titems := filterBuiltinsAndKeywords(mark, list.Items)\n\tvar got []completionItem\n\tfor i, item := range items {\n\t\tsimplified := completionItem{\n\t\t\tLabel:  item.Label,\n\t\t\tDetail: item.Detail,\n\t\t\tKind:   fmt.Sprint(item.Kind),\n\t\t}\n\t\tif item.Documentation != nil {\n\t\t\tswitch v := item.Documentation.Value.(type) {\n\t\t\tcase string:\n\t\t\t\tsimplified.Documentation = v\n\t\t\tcase protocol.MarkupContent:\n\t\t\t\tsimplified.Documentation = strings.TrimSpace(v.Value) // trim newlines\n\t\t\t}\n\t\t}\n\t\t// Support short-hand notation: if Detail, Kind, or Documentation are omitted from the\n\t\t// item, don't match them.\n\t\tif i < len(want) {\n\t\t\tif want[i].Detail == \"\" {\n\t\t\t\tsimplified.Detail = \"\"\n\t\t\t}\n\t\t\tif want[i].Kind == \"\" {\n\t\t\t\tsimplified.Kind = \"\"\n\t\t\t}\n\t\t\tif want[i].Documentation == \"\" {\n\t\t\t\tsimplified.Documentation = \"\"\n\t\t\t}\n\t\t}\n\t\tgot = append(got, simplified)\n\t}\n\tif len(want) == 0 {\n\t\twant = nil // got is nil if empty\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tmark.errorf(\"Completion(...) returned unexpected results (-want +got):\\n%s\", diff)\n\t}\n}\n\n// filterBuiltinsAndKeywords filters out builtins and keywords from completion\n// results.\n//\n// It over-approximates, and does not detect if builtins are shadowed.\nfunc filterBuiltinsAndKeywords(mark marker, items []protocol.CompletionItem) []protocol.CompletionItem {\n\tkeep := 0\n\tfor _, item := range items {\n\t\tif mark.run.test.filterKeywords && item.Kind == protocol.KeywordCompletion {\n\t\t\tcontinue\n\t\t}\n\t\tif mark.run.test.filterBuiltins && types.Universe.Lookup(item.Label) != nil {\n\t\t\tcontinue\n\t\t}\n\t\titems[keep] = item\n\t\tkeep++\n\t}\n\treturn items[:keep]\n}\n\n// acceptCompletionMarker implements the @acceptCompletion marker, running\n// textDocument/completion at the given src location and accepting the\n// candidate with the given label. The resulting source must match the provided\n// golden content.\nfunc acceptCompletionMarker(mark marker, src protocol.Location, label string, golden *Golden) {\n\tlist := mark.run.env.Completion(src)\n\tvar selected *protocol.CompletionItem\n\tfor _, item := range list.Items {\n\t\tif item.Label == label {\n\t\t\tselected = &item\n\t\t\tbreak\n\t\t}\n\t}\n\tif selected == nil {\n\t\tmark.errorf(\"Completion(...) did not return an item labeled %q\", label)\n\t\treturn\n\t}\n\tedit, err := protocol.SelectCompletionTextEdit(*selected, false)\n\tif err != nil {\n\t\tmark.errorf(\"Completion(...) did not return a valid edit: %v\", err)\n\t\treturn\n\t}\n\tfilename := mark.path()\n\tmapper := mark.mapper()\n\tpatched, _, err := protocol.ApplyEdits(mapper, append([]protocol.TextEdit{edit}, selected.AdditionalTextEdits...))\n\tif err != nil {\n\t\tmark.errorf(\"ApplyProtocolEdits failed: %v\", err)\n\t\treturn\n\t}\n\tchanges := map[string][]byte{filename: patched}\n\t// Check the file state.\n\tcheckChangedFiles(mark, changes, golden)\n}\n\n// defMarker implements the @def marker, running textDocument/definition at\n// the given location and asserting that there the results match want.\nfunc defMarker(mark marker, loc protocol.Location, want ...protocol.Location) {\n\tenv := mark.run.env\n\tgot, err := env.Editor.Definitions(env.Ctx, loc)\n\tif err != nil {\n\t\tmark.errorf(\"definition request failed: %v\", err)\n\t\treturn\n\t}\n\n\tif err := compareLocations(mark, got, want); err != nil {\n\t\tmark.errorf(\"def failed: %v\", err)\n\t}\n}\n\n// typedefMarker implements the @typedef marker.\nfunc typedefMarker(mark marker, loc protocol.Location, want ...protocol.Location) {\n\twantErr := namedArgFunc(mark, \"err\", convertStringMatcher, stringMatcher{})\n\n\tenv := mark.run.env\n\tgot, err := env.Editor.TypeDefinitions(env.Ctx, loc)\n\tif err != nil && wantErr.empty() {\n\t\tmark.errorf(\"typeDefinition at %s failed: %v\", loc, err)\n\t\treturn\n\t}\n\tif !wantErr.empty() {\n\t\twantErr.checkErr(mark, err)\n\t\treturn\n\t}\n\n\tif err := compareLocations(mark, got, want); err != nil {\n\t\tmark.errorf(\"typedef failed: %v\", err)\n\t}\n}\n\nfunc foldingRangeMarker(mark marker, g *Golden) {\n\tenv := mark.run.env\n\tranges, err := mark.server().FoldingRange(env.Ctx, &protocol.FoldingRangeParams{\n\t\tTextDocument: mark.document(),\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"foldingRange failed: %v\", err)\n\t\treturn\n\t}\n\tvar edits []protocol.TextEdit\n\tinsert := func(line, char uint32, text string) {\n\t\tpos := protocol.Position{Line: line, Character: char}\n\t\tedits = append(edits, protocol.TextEdit{\n\t\t\tRange: protocol.Range{\n\t\t\t\tStart: pos,\n\t\t\t\tEnd:   pos,\n\t\t\t},\n\t\t\tNewText: text,\n\t\t})\n\t}\n\tfor i, rng := range ranges {\n\t\t// We assume the server populates these optional fields.\n\t\tinsert(*rng.StartLine, *rng.StartCharacter, fmt.Sprintf(\"<%d kind=%q>\", i, rng.Kind))\n\t\tinsert(*rng.EndLine, *rng.EndCharacter, fmt.Sprintf(\"</%d>\", i))\n\t}\n\tfilename := mark.path()\n\tmapper, err := env.Editor.Mapper(filename)\n\tif err != nil {\n\t\tmark.errorf(\"Editor.Mapper(%s) failed: %v\", filename, err)\n\t\treturn\n\t}\n\tgot, _, err := protocol.ApplyEdits(mapper, edits)\n\tif err != nil {\n\t\tmark.errorf(\"ApplyProtocolEdits failed: %v\", err)\n\t\treturn\n\t}\n\twant, _ := g.Get(mark.T(), \"\", got)\n\tif diff := compare.Bytes(want, got); diff != \"\" {\n\t\tmark.errorf(\"foldingRange mismatch:\\n%s\", diff)\n\t}\n}\n\n// formatMarker implements the @format marker.\nfunc formatMarker(mark marker, golden *Golden) {\n\tedits, err := mark.server().Formatting(mark.ctx(), &protocol.DocumentFormattingParams{\n\t\tTextDocument: mark.document(),\n\t})\n\tvar got []byte\n\tif err != nil {\n\t\tgot = []byte(err.Error() + \"\\n\") // all golden content is newline terminated\n\t} else {\n\t\tenv := mark.run.env\n\t\tfilename := mark.path()\n\t\tmapper, err := env.Editor.Mapper(filename)\n\t\tif err != nil {\n\t\t\tmark.errorf(\"Editor.Mapper(%s) failed: %v\", filename, err)\n\t\t}\n\n\t\tgot, _, err = protocol.ApplyEdits(mapper, edits)\n\t\tif err != nil {\n\t\t\tmark.errorf(\"ApplyProtocolEdits failed: %v\", err)\n\t\t\treturn\n\t\t}\n\t}\n\n\tcompareGolden(mark, got, golden)\n}\n\nfunc highlightLocationMarker(mark marker, loc protocol.Location, kindName expect.Identifier) protocol.DocumentHighlight {\n\tvar kind protocol.DocumentHighlightKind\n\tswitch kindName {\n\tcase \"read\":\n\t\tkind = protocol.Read\n\tcase \"write\":\n\t\tkind = protocol.Write\n\tcase \"text\":\n\t\tkind = protocol.Text\n\tdefault:\n\t\tmark.errorf(\"invalid highlight kind: %q\", kindName)\n\t}\n\n\treturn protocol.DocumentHighlight{\n\t\tRange: loc.Range,\n\t\tKind:  kind,\n\t}\n}\n\nfunc sortDocumentHighlights(s []protocol.DocumentHighlight) {\n\tsort.Slice(s, func(i, j int) bool {\n\t\treturn protocol.CompareRange(s[i].Range, s[j].Range) < 0\n\t})\n}\n\n// highlightAllMarker makes textDocument/highlight\n// requests at locations of equivalence classes. Given input\n// highlightall(X1, X2, ..., Xn), the marker checks\n// highlight(X1) = highlight(X2) = ... = highlight(Xn) = {X1, X2, ..., Xn}.\n// It is not the general rule for all highlighting, and use @highlight\n// for asymmetric cases.\n//\n// TODO(b/288111111): this is a bit of a hack. We should probably\n// have a more general way of testing that a function is idempotent.\nfunc highlightAllMarker(mark marker, all ...protocol.DocumentHighlight) {\n\tsortDocumentHighlights(all)\n\tfor _, src := range all {\n\t\tloc := mark.uri().Location(src.Range)\n\t\tgot := mark.run.env.DocumentHighlight(loc)\n\t\tsortDocumentHighlights(got)\n\n\t\tif d := cmp.Diff(all, got); d != \"\" {\n\t\t\tmark.errorf(\"DocumentHighlight(%v) mismatch (-want +got):\\n%s\", loc, d)\n\t\t}\n\t}\n}\n\nfunc highlightMarker(mark marker, src protocol.DocumentHighlight, dsts ...protocol.DocumentHighlight) {\n\tloc := mark.uri().Location(src.Range)\n\tgot := mark.run.env.DocumentHighlight(loc)\n\n\tsortDocumentHighlights(got)\n\tsortDocumentHighlights(dsts)\n\n\tif diff := cmp.Diff(dsts, got, cmpopts.EquateEmpty()); diff != \"\" {\n\t\tmark.errorf(\"DocumentHighlight(%v) mismatch (-want +got):\\n%s\", src, diff)\n\t}\n}\n\nfunc hoverMarker(mark marker, src, dst protocol.Location, sc stringMatcher) {\n\tcontent, gotDst := mark.run.env.Hover(src)\n\tif gotDst != dst {\n\t\tmark.errorf(\"hover location does not match:\\n\\tgot: %s\\n\\twant %s)\", mark.run.fmtLoc(gotDst), mark.run.fmtLoc(dst))\n\t}\n\tgotMD := \"\"\n\tif content != nil {\n\t\tgotMD = content.Value\n\n\t\t// Normalize the absolute path for cross-platform consistency before\n\t\t// replacement. This ensures Windows paths (e.g., \"C:/...\") become\n\t\t// \"/C:/...\" to match Unix-like paths.\n\t\tabs := mark.run.env.Sandbox.Workdir.RootURI().Path()\n\t\tif protocol.IsWindowsDrivePath(abs) {\n\t\t\tabs = \"/\" + abs\n\t\t}\n\t\tgotMD = strings.ReplaceAll(gotMD, filepath.ToSlash(abs), \"$WORKDIR\")\n\t}\n\tsc.check(mark, gotMD)\n}\n\nfunc hoverErrMarker(mark marker, src protocol.Location, em stringMatcher) {\n\t_, _, err := mark.editor().Hover(mark.ctx(), src)\n\tem.checkErr(mark, err)\n}\n\n// locMarker implements the @loc marker.\nfunc locMarker(mark marker, loc protocol.Location) protocol.Location { return loc }\n\n// defLocMarker implements the @defloc marker, which binds a location to the\n// (first) result of a jump-to-definition request.\nfunc defLocMarker(mark marker, loc protocol.Location) protocol.Location {\n\treturn mark.run.env.FirstDefinition(loc)\n}\n\n// diagMarker implements the @diag marker. It eliminates diagnostics from\n// the observed set in mark.test.\nfunc diagMarker(mark marker, loc protocol.Location, re *regexp.Regexp) {\n\texact := namedArg(mark, \"exact\", false)\n\tif _, ok := removeDiagnostic(mark, loc, exact, re); !ok {\n\t\tmark.errorf(\"no diagnostic at %v matches %q\", loc, re)\n\t}\n}\n\n// removeDiagnostic looks for a diagnostic matching loc at the given position.\n//\n// If found, it returns (diag, true), and eliminates the matched diagnostic\n// from the unmatched set.\n//\n// If not found, it returns (protocol.Diagnostic{}, false).\nfunc removeDiagnostic(mark marker, loc protocol.Location, matchEnd bool, re *regexp.Regexp) (protocol.Diagnostic, bool) {\n\tkey := loc\n\tkey.Range.End = key.Range.Start // diagnostics ignore end position.\n\tdiags := mark.run.diags[key]\n\tfor i, diag := range diags {\n\t\tif re.MatchString(diag.Message) && (!matchEnd || diag.Range.End == loc.Range.End) {\n\t\t\tmark.run.diags[key] = slices.Delete(diags, i, i+1)\n\t\t\treturn diag, true\n\t\t}\n\t}\n\treturn protocol.Diagnostic{}, false\n}\n\n// renameMarker implements the @rename(location, new, golden) marker.\nfunc renameMarker(mark marker, loc protocol.Location, newName string, golden *Golden) {\n\tchanged, err := rename(mark.run.env, loc, newName)\n\tif err != nil {\n\t\tmark.errorf(\"rename failed: %v. (Use @renameerr for expected errors.)\", err)\n\t\treturn\n\t}\n\tcheckDiffs(mark, changed, golden)\n}\n\n// renameErrMarker implements the @renamererr(location, new, error) marker.\nfunc renameErrMarker(mark marker, loc protocol.Location, newName string, wantErr stringMatcher) {\n\t_, err := rename(mark.run.env, loc, newName)\n\twantErr.checkErr(mark, err)\n}\n\nfunc selectionRangeMarker(mark marker, loc protocol.Location, g *Golden) {\n\tranges, err := mark.server().SelectionRange(mark.ctx(), &protocol.SelectionRangeParams{\n\t\tTextDocument: mark.document(),\n\t\tPositions:    []protocol.Position{loc.Range.Start},\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"SelectionRange failed: %v\", err)\n\t\treturn\n\t}\n\tvar buf bytes.Buffer\n\tm := mark.mapper()\n\tfor i, path := range ranges {\n\t\tfmt.Fprintf(&buf, \"Ranges %d:\", i)\n\t\trng := path\n\t\tfor {\n\t\t\ts, e, err := m.RangeOffsets(rng.Range)\n\t\t\tif err != nil {\n\t\t\t\tmark.errorf(\"RangeOffsets failed: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar snippet string\n\t\t\tif e-s < 30 {\n\t\t\t\tsnippet = string(m.Content[s:e])\n\t\t\t} else {\n\t\t\t\tsnippet = string(m.Content[s:s+15]) + \"...\" + string(m.Content[e-15:e])\n\t\t\t}\n\n\t\t\tfmt.Fprintf(&buf, \"\\n\\t%v %q\", rng.Range, strings.ReplaceAll(snippet, \"\\n\", \"\\\\n\"))\n\n\t\t\tif rng.Parent == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\trng = *rng.Parent\n\t\t}\n\t\tbuf.WriteRune('\\n')\n\t}\n\tcompareGolden(mark, buf.Bytes(), g)\n}\n\nfunc tokenMarker(mark marker, loc protocol.Location, tokenType, mod string) {\n\ttokens := mark.run.env.SemanticTokensRange(loc)\n\tif len(tokens) != 1 {\n\t\tmark.errorf(\"got %d tokens, want 1\", len(tokens))\n\t\treturn\n\t}\n\ttok := tokens[0]\n\tif tok.TokenType != tokenType {\n\t\tmark.errorf(\"token type = %q, want %q\", tok.TokenType, tokenType)\n\t}\n\tif tok.Mod != mod {\n\t\tmark.errorf(\"token mod = %q, want %q\", tok.Mod, mod)\n\t}\n}\n\nfunc signatureMarker(mark marker, src protocol.Location, label string, active int64) {\n\tgot := mark.run.env.SignatureHelp(src)\n\tvar gotLabels []string // for better error messages\n\tif got != nil {\n\t\tfor _, s := range got.Signatures {\n\t\t\tgotLabels = append(gotLabels, s.Label)\n\t\t}\n\t}\n\tif label == \"\" {\n\t\t// A null result is expected.\n\t\t// (There's no point having a @signatureerr marker\n\t\t// because the server handler suppresses all errors.)\n\t\tif got != nil && len(gotLabels) > 0 {\n\t\t\tmark.errorf(\"signatureHelp = %v, want 0 signatures\", gotLabels)\n\t\t}\n\t\treturn\n\t}\n\tif got == nil || len(got.Signatures) != 1 {\n\t\tmark.errorf(\"signatureHelp = %v, want exactly 1 signature\", gotLabels)\n\t\treturn\n\t}\n\tif got := gotLabels[0]; got != label {\n\t\tmark.errorf(\"signatureHelp: got label %q, want %q\", got, label)\n\t}\n\tgotActiveParameter := int64(-1) // => missing\n\tif got.ActiveParameter != nil {\n\t\tgotActiveParameter = int64(*got.ActiveParameter)\n\t}\n\tif gotActiveParameter != active {\n\t\tmark.errorf(\"signatureHelp: got active parameter %d, want %d\", gotActiveParameter, active)\n\t}\n}\n\n// rename returns the new contents of the files that would be modified\n// by renaming the identifier at loc to newName.\nfunc rename(env *integration.Env, loc protocol.Location, newName string) (map[string][]byte, error) {\n\t// We call Server.Rename directly, instead of\n\t//   env.Editor.Rename(env.Ctx, loc, newName)\n\t// to isolate Rename from PrepareRename, and because we don't\n\t// want to modify the file system in a scenario with multiple\n\t// @rename markers.\n\n\twsedit, err := env.Editor.Server.Rename(env.Ctx, &protocol.RenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),\n\t\tNewName:                    newName,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn changedFiles(env, wsedit.DocumentChanges)\n}\n\n// changedFiles applies the given sequence of document changes to the\n// editor buffer content, recording the final contents in the returned map.\n// The actual editor state is not changed.\n// Deleted files are indicated by a content of []byte(nil).\n//\n// See also:\n//   - Editor.applyWorkspaceEdit ../integration/fake/editor.go for the\n//     implementation of this operation used in normal testing.\n//   - client.applyWorkspaceEdit in ../../../cmd/cmd.go for the\n//     CLI variant.\nfunc changedFiles(env *integration.Env, changes []protocol.DocumentChange) (map[string][]byte, error) {\n\turiToPath := env.Sandbox.Workdir.URIToPath\n\n\t// latest maps each updated file name to a mapper holding its\n\t// current contents, or nil if the file has been deleted.\n\tlatest := make(map[protocol.DocumentURI]*protocol.Mapper)\n\n\t// read reads a file. It returns an error if the file never\n\t// existed or was deleted.\n\tread := func(uri protocol.DocumentURI) (*protocol.Mapper, error) {\n\t\tif m, ok := latest[uri]; ok {\n\t\t\tif m == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"read: file %s was deleted\", uri)\n\t\t\t}\n\t\t\treturn m, nil\n\t\t}\n\t\treturn env.Editor.Mapper(uriToPath(uri))\n\t}\n\n\t// write (over)writes a file. A nil content indicates a deletion.\n\twrite := func(uri protocol.DocumentURI, content []byte) {\n\t\tvar m *protocol.Mapper\n\t\tif content != nil {\n\t\t\tm = protocol.NewMapper(uri, content)\n\t\t}\n\t\tlatest[uri] = m\n\t}\n\n\t// Process the sequence of changes.\n\tfor _, change := range changes {\n\t\tswitch {\n\t\tcase change.TextDocumentEdit != nil:\n\t\t\turi := change.TextDocumentEdit.TextDocument.URI\n\t\t\tm, err := read(uri)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err // missing\n\t\t\t}\n\t\t\tpatched, _, err := protocol.ApplyEdits(m, protocol.AsTextEdits(change.TextDocumentEdit.Edits))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err // bad edit\n\t\t\t}\n\t\t\twrite(uri, patched)\n\n\t\tcase change.RenameFile != nil:\n\t\t\told := change.RenameFile.OldURI\n\t\t\tnew := change.RenameFile.NewURI\n\t\t\tinfo, err := os.Stat(old.Path())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif info.IsDir() {\n\t\t\t\t// Walk through all the files in the old directory and copy\n\t\t\t\t// their content to the new directory.\n\t\t\t\t// TODO(mkalil): This currently only handles renaming the file's\n\t\t\t\t// innermost directory. Need to handle renames of outer directories\n\t\t\t\t// directories when implementing package move refactoring.\n\t\t\t\tfor _, file := range env.ListFiles(old.Path()) {\n\t\t\t\t\toldFile := protocol.URIFromPath(path.Join(old.Path(), path.Base(file)))\n\t\t\t\t\tm, err := read(oldFile)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err // missing\n\t\t\t\t\t}\n\t\t\t\t\twrite(oldFile, nil)\n\n\t\t\t\t\tnewFile := protocol.URIFromPath(path.Join(new.Path(), path.Base(file)))\n\t\t\t\t\tif _, err := read(oldFile); err == nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"RenameFile: destination %s exists\", new)\n\t\t\t\t\t}\n\t\t\t\t\twrite(newFile, m.Content)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm, err := read(old)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err // missing\n\t\t\t\t}\n\t\t\t\twrite(old, nil)\n\n\t\t\t\tif _, err := read(old); err == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"RenameFile: destination %s exists\", new)\n\t\t\t\t}\n\t\t\t\twrite(new, m.Content)\n\t\t\t}\n\n\t\tcase change.CreateFile != nil:\n\t\t\turi := change.CreateFile.URI\n\t\t\tif _, err := read(uri); err == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"CreateFile %s: file exists\", uri)\n\t\t\t}\n\t\t\twrite(uri, []byte(\"\")) // initially empty\n\n\t\tcase change.DeleteFile != nil:\n\t\t\turi := change.DeleteFile.URI\n\t\t\tif _, err := read(uri); err != nil {\n\t\t\t\t// The specified URI could be a file or a directory.\n\t\t\t\tfiles := env.ListFiles(uriToPath(uri))\n\t\t\t\tif files == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"DeleteFile %s: file does not exist\", uri)\n\t\t\t\t}\n\t\t\t\tif len(files) > 0 {\n\t\t\t\t\t// Directory is not empty. If \"Recursive\" is true, we delete\n\t\t\t\t\t// every file in the folder. Otherwise, we continue without\n\t\t\t\t\t// deleting the directory.\n\t\t\t\t\tif change.DeleteFile.Options != nil && change.DeleteFile.Options.Recursive {\n\t\t\t\t\t\tfor _, f := range files {\n\t\t\t\t\t\t\twrite(protocol.URIFromPath(f), nil)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\twrite(uri, nil)\n\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid DocumentChange\")\n\t\t}\n\t}\n\n\t// Convert into result form.\n\tresult := make(map[string][]byte)\n\tfor uri, mapper := range latest {\n\t\tvar content []byte\n\t\tif mapper != nil {\n\t\t\tcontent = mapper.Content\n\t\t}\n\t\tresult[uriToPath(uri)] = content\n\t}\n\n\treturn result, nil\n}\n\nfunc codeActionMarker(mark marker, loc protocol.Location, kind string) {\n\tif !exactlyOneNamedArg(mark, \"action\", \"edit\", \"result\", \"err\") {\n\t\treturn\n\t}\n\n\tif end := namedArgFunc(mark, \"end\", convertNamedArgLocation, protocol.Location{}); end.URI != \"\" {\n\t\tif end.URI != loc.URI {\n\t\t\tmark.errorf(\"end marker is in a different file (%s)\", filepath.Base(loc.URI.Path()))\n\t\t\treturn\n\t\t}\n\t\tloc.Range.End = end.Range.End\n\t}\n\n\tvar (\n\t\tedit       = namedArg(mark, \"edit\", expect.Identifier(\"\"))\n\t\tresult     = namedArg(mark, \"result\", expect.Identifier(\"\"))\n\t\twantAction = namedArg(mark, \"action\", expect.Identifier(\"\"))\n\t\twantErr    = namedArgFunc(mark, \"err\", convertStringMatcher, stringMatcher{})\n\t)\n\n\tvar diag *protocol.Diagnostic\n\tif re := namedArg(mark, \"diag\", (*regexp.Regexp)(nil)); re != nil {\n\t\td, ok := removeDiagnostic(mark, loc, false, re)\n\t\tif !ok {\n\t\t\tmark.errorf(\"no diagnostic at %v matches %q\", loc, re)\n\t\t\treturn\n\t\t}\n\t\tdiag = &d\n\t}\n\n\taction, err := resolveCodeAction(mark.run.env, loc.URI, loc.Range, protocol.CodeActionKind(kind), diag)\n\tif err != nil {\n\t\tif !wantErr.empty() {\n\t\t\twantErr.checkErr(mark, err)\n\t\t} else {\n\t\t\tmark.errorf(\"resolveCodeAction failed: %v\", err)\n\t\t}\n\t\treturn\n\t}\n\n\t// If when 'action' is set, we simply compare the action, and don't apply it.\n\tif wantAction != \"\" {\n\t\tg := mark.getGolden(wantAction)\n\t\tif action == nil {\n\t\t\tmark.errorf(\"no matching codeAction\")\n\t\t\treturn\n\t\t}\n\t\tdata, err := json.MarshalIndent(action, \"\", \"\\t\")\n\t\tif err != nil {\n\t\t\tmark.errorf(\"failed to marshal codeaction: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tdata = bytes.ReplaceAll(data, []byte(mark.run.env.Sandbox.Workdir.RootURI()), []byte(\"$WORKDIR\"))\n\t\tcompareGolden(mark, data, g)\n\t\treturn\n\t}\n\n\tchanges, err := applyCodeAction(mark.run.env, action)\n\tif err != nil {\n\t\tif !wantErr.empty() {\n\t\t\twantErr.checkErr(mark, err)\n\t\t} else {\n\t\t\tmark.errorf(\"codeAction failed: %v\", err)\n\t\t}\n\t\treturn\n\t}\n\tchanged, err := changedFiles(mark.run.env, changes)\n\tif err != nil {\n\t\tmark.errorf(\"changedFiles failed: %v\", err)\n\t\treturn\n\t}\n\n\tswitch {\n\tcase edit != \"\":\n\t\tg := mark.getGolden(edit)\n\t\tcheckDiffs(mark, changed, g)\n\tcase result != \"\":\n\t\tg := mark.getGolden(result)\n\t\t// Check the file state.\n\t\tcheckChangedFiles(mark, changed, g)\n\tcase !wantErr.empty():\n\t\twantErr.checkErr(mark, err)\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n\n// codeLensesMarker runs the @codelenses() marker, collecting @codelens marks\n// in the current file and comparing with the result of the\n// textDocument/codeLens RPC.\nfunc codeLensesMarker(mark marker) {\n\ttype codeLens struct {\n\t\tRange protocol.Range\n\t\tTitle string\n\t}\n\n\tlenses := mark.run.env.CodeLens(mark.path())\n\tvar got []codeLens\n\tfor _, lens := range lenses {\n\t\ttitle := \"\"\n\t\tif lens.Command != nil {\n\t\t\ttitle = lens.Command.Title\n\t\t}\n\t\tgot = append(got, codeLens{lens.Range, title})\n\t}\n\n\tvar want []codeLens\n\tmark.consumeExtraNotes(\"codelens\", actionMarkerFunc(func(_ marker, loc protocol.Location, title string) {\n\t\twant = append(want, codeLens{loc.Range, title})\n\t}))\n\n\tfor _, s := range [][]codeLens{got, want} {\n\t\tsort.Slice(s, func(i, j int) bool {\n\t\t\tli, lj := s[i], s[j]\n\t\t\tif c := protocol.CompareRange(li.Range, lj.Range); c != 0 {\n\t\t\t\treturn c < 0\n\t\t\t}\n\t\t\treturn li.Title < lj.Title\n\t\t})\n\t}\n\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tmark.errorf(\"codelenses: unexpected diff (-want +got):\\n%s\", diff)\n\t}\n}\n\nfunc documentLinkMarker(mark marker, g *Golden) {\n\tvar b bytes.Buffer\n\tlinks := mark.run.env.DocumentLink(mark.path())\n\tfor _, l := range links {\n\t\tif l.Target == nil {\n\t\t\tmark.errorf(\"%s: nil link target\", l.Range)\n\t\t\tcontinue\n\t\t}\n\t\tloc := mark.uri().Location(l.Range)\n\t\tfmt.Fprintln(&b, mark.run.fmtLocForGolden(loc), *l.Target)\n\t}\n\n\tcompareGolden(mark, b.Bytes(), g)\n}\n\n// consumeExtraNotes runs the provided func for each extra note with the given\n// name, and deletes all matching notes.\nfunc (mark marker) consumeExtraNotes(name string, f func(marker)) {\n\turi := mark.uri()\n\tnotes := mark.run.extraNotes[uri][name]\n\tdelete(mark.run.extraNotes[uri], name)\n\n\tfor _, note := range notes {\n\t\tf(marker{run: mark.run, note: note})\n\t}\n}\n\n// quickfixMarker implements the @quickfix(location, regexp,\n// kind, golden) marker. It acts like @diag(location, regexp), to set\n// the expectation of a diagnostic, but then it applies the \"quickfix\"\n// code action (which must be unique) suggested by the matched diagnostic.\nfunc quickfixMarker(mark marker, loc protocol.Location, re *regexp.Regexp, golden *Golden) {\n\tloc.Range.End = loc.Range.Start // diagnostics ignore end position.\n\t// Find and remove the matching diagnostic.\n\tdiag, ok := removeDiagnostic(mark, loc, false, re)\n\tif !ok {\n\t\tmark.errorf(\"no diagnostic at %v matches %q\", loc, re)\n\t\treturn\n\t}\n\n\t// Apply the fix it suggests.\n\tchanged, err := codeAction(mark.run.env, loc.URI, diag.Range, \"quickfix\", &diag)\n\tif err != nil {\n\t\tmark.errorf(\"quickfix failed: %v. (Use @quickfixerr for expected errors.)\", err)\n\t\treturn\n\t}\n\n\t// Check the file state.\n\tcheckDiffs(mark, changed, golden)\n}\n\nfunc quickfixErrMarker(mark marker, loc protocol.Location, re *regexp.Regexp, wantErr stringMatcher) {\n\tloc.Range.End = loc.Range.Start // diagnostics ignore end position.\n\t// Find and remove the matching diagnostic.\n\tdiag, ok := removeDiagnostic(mark, loc, false, re)\n\tif !ok {\n\t\tmark.errorf(\"no diagnostic at %v matches %q\", loc, re)\n\t\treturn\n\t}\n\n\t// Apply the fix it suggests.\n\t_, err := codeAction(mark.run.env, loc.URI, diag.Range, \"quickfix\", &diag)\n\twantErr.checkErr(mark, err)\n}\n\n// codeAction executes a textDocument/codeAction request for the specified\n// location and kind. If diag is non-nil, it is used as the code action\n// context.\n//\n// The resulting map contains resulting file contents after the code action is\n// applied. Currently, this function does not support code actions that return\n// edits directly; it only supports code action commands.\nfunc codeAction(env *integration.Env, uri protocol.DocumentURI, rng protocol.Range, kind protocol.CodeActionKind, diag *protocol.Diagnostic) (map[string][]byte, error) {\n\taction, err := resolveCodeAction(env, uri, rng, kind, diag)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tchanges, err := applyCodeAction(env, action)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn changedFiles(env, changes)\n}\n\n// resolveCodeAction resolves the code action specified by the given location,\n// kind, and diagnostic.\nfunc resolveCodeAction(env *integration.Env, uri protocol.DocumentURI, rng protocol.Range, kind protocol.CodeActionKind, diag *protocol.Diagnostic) (*protocol.CodeAction, error) {\n\t// Request all code actions that apply to the diagnostic.\n\t// A production client would set Only=[kind],\n\t// but we can give a better error if we don't filter.\n\tparams := &protocol.CodeActionParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{URI: uri},\n\t\tRange:        rng,\n\t\tContext: protocol.CodeActionContext{\n\t\t\tOnly: []protocol.CodeActionKind{protocol.Empty}, // => all\n\t\t},\n\t}\n\tif diag != nil {\n\t\tparams.Context.Diagnostics = []protocol.Diagnostic{*diag}\n\t}\n\n\tactions, err := env.Editor.Server.CodeAction(env.Ctx, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Find the sole candidate CodeAction of exactly the specified kind\n\t// (e.g. refactor.inline.call).\n\tvar candidates []protocol.CodeAction\n\tfor _, act := range actions {\n\t\tif act.Kind == kind {\n\t\t\tcandidates = append(candidates, act)\n\t\t}\n\t}\n\tif len(candidates) != 1 {\n\t\tvar msg bytes.Buffer\n\t\tfmt.Fprintf(&msg, \"found %d CodeActions of kind %s for this diagnostic, want 1\", len(candidates), kind)\n\t\tfor _, act := range actions {\n\t\t\tfmt.Fprintf(&msg, \"\\n\\tfound %q (%s)\", act.Title, act.Kind)\n\t\t}\n\t\treturn nil, errors.New(msg.String())\n\t}\n\taction := candidates[0]\n\n\t// Resolve code action edits first if the client has resolve support\n\t// and the code action has no edits.\n\tif action.Edit == nil {\n\t\teditSupport, err := env.Editor.EditResolveSupport()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif editSupport {\n\t\t\tresolved, err := env.Editor.Server.ResolveCodeAction(env.Ctx, &action)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taction = *resolved\n\t\t}\n\t}\n\n\treturn &action, nil\n}\n\n// applyCodeAction applies the given code action, and captures the resulting\n// document changes.\nfunc applyCodeAction(env *integration.Env, action *protocol.CodeAction) ([]protocol.DocumentChange, error) {\n\t// Collect any server-initiated changes created by workspace/applyEdit.\n\t//\n\t// We set up this handler immediately, not right before executing the code\n\t// action command, so we can assert that neither the codeAction request nor\n\t// codeAction resolve request cause edits as a side effect (golang/go#71405).\n\tvar changes []protocol.DocumentChange\n\trestore := env.Editor.Client().SetApplyEditHandler(func(ctx context.Context, wsedit *protocol.WorkspaceEdit) error {\n\t\tchanges = append(changes, wsedit.DocumentChanges...)\n\t\treturn nil\n\t})\n\tdefer restore()\n\n\tif action.Edit == nil && action.Command == nil {\n\t\tpanic(\"bad action\")\n\t}\n\n\t// Apply the codeAction.\n\t//\n\t// Spec:\n\t//  \"If a code action provides an edit and a command, first the edit is\n\t//  executed and then the command.\"\n\t// An action may specify an edit and/or a command, to be\n\t// applied in that order. But since applyDocumentChanges(env,\n\t// action.Edit.DocumentChanges) doesn't compose, for now we\n\t// assert that actions return one or the other.\n\tif action.Edit != nil {\n\t\tif len(action.Edit.Changes) > 0 {\n\t\t\tenv.TB.Errorf(\"internal error: discarding unexpected CodeAction{Kind=%s, Title=%q}.Edit.Changes\", action.Kind, action.Title)\n\t\t}\n\t\tif action.Edit.DocumentChanges != nil {\n\t\t\tif action.Command != nil {\n\t\t\t\tenv.TB.Errorf(\"internal error: discarding unexpected CodeAction{Kind=%s, Title=%q}.Command\", action.Kind, action.Title)\n\t\t\t}\n\t\t\treturn action.Edit.DocumentChanges, nil\n\t\t}\n\t}\n\n\tif action.Command != nil {\n\t\t// This is a typical CodeAction command:\n\t\t//\n\t\t//   Title:     \"Implement error\"\n\t\t//   Command:   gopls.apply_fix\n\t\t//   Arguments: [{\"Fix\":\"stub_methods\",\"URI\":\".../a.go\",\"Range\":...}}]\n\t\t//\n\t\t// The client makes an ExecuteCommand RPC to the server,\n\t\t// which dispatches it to the ApplyFix handler.\n\t\t// ApplyFix dispatches to the \"stub_methods\" fixer (the meat).\n\t\t// The server then makes an ApplyEdit RPC to the client,\n\t\t// whose WorkspaceEditFunc hook temporarily gathers the edits\n\t\t// instead of applying them.\n\n\t\tif _, err := env.Editor.Server.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{\n\t\t\tCommand:   action.Command.Command,\n\t\t\tArguments: action.Command.Arguments,\n\t\t}); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn changes, nil // populated as a side effect of ExecuteCommand\n\t}\n\n\treturn nil, nil\n}\n\n// refsMarker implements the @refs marker.\nfunc refsMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\trefs := func(includeDeclaration bool, want []protocol.Location) error {\n\t\tgot, err := mark.server().References(mark.ctx(), &protocol.ReferenceParams{\n\t\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(src),\n\t\t\tContext: protocol.ReferenceContext{\n\t\t\t\tIncludeDeclaration: includeDeclaration,\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn compareLocations(mark, got, want)\n\t}\n\n\tfor _, includeDeclaration := range []bool{false, true} {\n\t\t// Ignore first 'want' location if we didn't request the declaration.\n\t\t// TODO(adonovan): don't assume a single declaration:\n\t\t// there may be >1 if corresponding methods are considered.\n\t\twant := want\n\t\tif !includeDeclaration && len(want) > 0 {\n\t\t\twant = want[1:]\n\t\t}\n\t\tif err := refs(includeDeclaration, want); err != nil {\n\t\t\tmark.errorf(\"refs(includeDeclaration=%t) failed: %v\",\n\t\t\t\tincludeDeclaration, err)\n\t\t}\n\t}\n}\n\n// implementationMarker implements the @implementation marker.\nfunc implementationMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\twantErr := namedArgFunc(mark, \"err\", convertStringMatcher, stringMatcher{})\n\n\tgot, err := mark.server().Implementation(mark.ctx(), &protocol.ImplementationParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(src),\n\t})\n\tif err != nil && wantErr.empty() {\n\t\tmark.errorf(\"implementation at %s failed: %v\", src, err)\n\t\treturn\n\t}\n\tif !wantErr.empty() {\n\t\twantErr.checkErr(mark, err)\n\t\treturn\n\t}\n\tif err := compareLocations(mark, got, want); err != nil {\n\t\tmark.errorf(\"implementation: %v\", err)\n\t}\n}\n\nfunc mcpToolMarker(mark marker, tool string, rawArgs string) {\n\tif !mark.run.test.mcp {\n\t\tmark.errorf(\"mcp not enabled: add -mcp\")\n\t\treturn\n\t}\n\targs := make(map[string]any)\n\tif err := json.Unmarshal([]byte(rawArgs), &args); err != nil {\n\t\tmark.errorf(\"fail to unmarshal arguments to map[string]any: %v\", err)\n\t\treturn\n\t}\n\n\t// substitutePaths replaces instances of $WORKDIR in string or []string values with\n\t// the actual working directory.\n\tvar substitutePaths func(any) any\n\tsubstitutePaths = func(v any) any {\n\t\tswitch v := v.(type) {\n\t\tcase string:\n\t\t\treturn strings.ReplaceAll(v, \"$WORKDIR\", mark.run.env.Sandbox.Workdir.RootURI().Path())\n\n\t\tcase []any:\n\t\t\tfor i, e := range v {\n\t\t\t\tif _, ok := e.(string); ok {\n\t\t\t\t\tv[i] = substitutePaths(e).(string)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn v\n\t}\n\t// Hack: replace '$WORKDIR' in string arguments with the actual sandbox\n\t// working directory.\n\tfor k, v := range args {\n\t\targs[k] = substitutePaths(v)\n\t}\n\n\tif loc := namedArg(mark, \"location\", protocol.Location{}); loc != (protocol.Location{}) {\n\t\targs[\"location\"] = loc\n\t}\n\n\tres, err := mark.run.env.MCPSession.CallTool(mark.ctx(), &mcp.CallToolParams{\n\t\tName:      tool,\n\t\tArguments: args,\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"failed to call mcp tool: %v\", err)\n\t\treturn\n\t}\n\n\tvar buf bytes.Buffer\n\tfor i, c := range res.Content {\n\t\ttext, ok := c.(*mcp.TextContent)\n\t\tif !ok {\n\t\t\tmark.errorf(\"unsupported return content[%v] type: %T\", i, c)\n\t\t\tcontinue\n\t\t}\n\t\tbuf.WriteString(text.Text)\n\t}\n\tif !bytes.HasSuffix(buf.Bytes(), []byte{'\\n'}) {\n\t\tbuf.WriteString(\"\\n\") // all golden content is newline terminated\n\t}\n\n\tgot := buf.String()\n\t// For portability, replace all (potential) filepath separators with \"/\".\n\tgot = strings.ReplaceAll(got, string(filepath.Separator), \"/\")\n\t// To ensure consistent unified diff output, the working directory path\n\t// is replaced with \"$WORKDIR\". This addresses cases where MCP tools\n\t// include absolute file paths in generated diffs.\n\tgot = strings.ReplaceAll(got, filepath.ToSlash(mark.run.env.Sandbox.Workdir.RootURI().Path()), \"$WORKDIR\")\n\n\toutput := namedArg(mark, \"output\", expect.Identifier(\"\"))\n\tgolden := mark.getGolden(output)\n\twant, _ := golden.Get(mark.T(), \"\", []byte(got))\n\tif diff := compare.Text(string(want), got); diff != \"\" {\n\t\tmark.errorf(\"unexpected mcp tools call %s return: diff:\\n%s\", tool, diff)\n\t}\n}\n\nfunc incomingCallsMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\tgetCalls := func(item protocol.CallHierarchyItem) ([]protocol.Location, error) {\n\t\tcalls, err := mark.server().IncomingCalls(mark.ctx(), &protocol.CallHierarchyIncomingCallsParams{Item: item})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar locs []protocol.Location\n\t\tfor _, call := range calls {\n\t\t\tlocs = append(locs, call.From.URI.Location(call.From.Range))\n\t\t}\n\t\treturn locs, nil\n\t}\n\tcallHierarchy(mark, src, getCalls, want)\n}\n\nfunc outgoingCallsMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\tgetCalls := func(item protocol.CallHierarchyItem) ([]protocol.Location, error) {\n\t\tcalls, err := mark.server().OutgoingCalls(mark.ctx(), &protocol.CallHierarchyOutgoingCallsParams{Item: item})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar locs []protocol.Location\n\t\tfor _, call := range calls {\n\t\t\tlocs = append(locs, call.To.URI.Location(call.To.Range))\n\t\t}\n\t\treturn locs, nil\n\t}\n\tcallHierarchy(mark, src, getCalls, want)\n}\n\ntype callHierarchyFunc = func(protocol.CallHierarchyItem) ([]protocol.Location, error)\n\nfunc callHierarchy(mark marker, src protocol.Location, getCalls callHierarchyFunc, want []protocol.Location) {\n\titems, err := mark.server().PrepareCallHierarchy(mark.ctx(), &protocol.CallHierarchyPrepareParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(src),\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"PrepareCallHierarchy failed: %v\", err)\n\t\treturn\n\t}\n\tif nitems := len(items); nitems != 1 {\n\t\tmark.errorf(\"PrepareCallHierarchy returned %d items, want exactly 1\", nitems)\n\t\treturn\n\t}\n\titem := items[0]\n\tif loc := item.URI.Location(item.Range); loc != src {\n\t\tmark.errorf(\"PrepareCallHierarchy found call %v, want %v\", loc, src)\n\t\treturn\n\t}\n\tcalls, err := getCalls(items[0])\n\tif err != nil {\n\t\tmark.errorf(\"call hierarchy failed: %v\", err)\n\t\treturn\n\t}\n\tif err := compareLocations(mark, calls, want); err != nil {\n\t\tmark.errorf(\"%s failed: %v\", mark.note.Name, err)\n\t}\n}\n\nfunc inlayhintsMarker(mark marker, g *Golden) {\n\thints := mark.run.env.InlayHints(mark.path())\n\n\t// Map inlay hints to text edits.\n\tedits := make([]protocol.TextEdit, len(hints))\n\tfor i, hint := range hints {\n\t\tvar paddingLeft, paddingRight string\n\t\tif hint.PaddingLeft {\n\t\t\tpaddingLeft = \" \"\n\t\t}\n\t\tif hint.PaddingRight {\n\t\t\tpaddingRight = \" \"\n\t\t}\n\t\tedits[i] = protocol.TextEdit{\n\t\t\tRange:   protocol.Range{Start: hint.Position, End: hint.Position},\n\t\t\tNewText: fmt.Sprintf(\"<%s%s%s>\", paddingLeft, hint.Label[0].Value, paddingRight),\n\t\t}\n\t}\n\n\tm := mark.mapper()\n\tgot, _, err := protocol.ApplyEdits(m, edits)\n\tif err != nil {\n\t\tmark.errorf(\"ApplyProtocolEdits: %v\", err)\n\t\treturn\n\t}\n\n\tcompareGolden(mark, got, g)\n}\n\nfunc prepareRenameMarker(mark marker, src protocol.Location, placeholder string) {\n\tparams := &protocol.PrepareRenameParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(src),\n\t}\n\tgot, err := mark.server().PrepareRename(mark.ctx(), params)\n\tif err != nil {\n\t\tmark.T().Fatal(err)\n\t}\n\tif placeholder == \"\" {\n\t\tif got != nil {\n\t\t\tmark.errorf(\"PrepareRename(...) = %v, want nil\", got)\n\t\t}\n\t\treturn\n\t}\n\n\twant := &protocol.PrepareRenameResult{\n\t\tPlaceholder: placeholder,\n\t}\n\tif span := namedArg(mark, \"span\", protocol.Location{}); span != (protocol.Location{}) {\n\t\twant.Range = span.Range\n\t} else {\n\t\tgot.Range = protocol.Range{} // ignore Range\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tmark.errorf(\"mismatching PrepareRename result:\\n%s\", diff)\n\t}\n}\n\nfunc subtypesMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\ttypeHierarchy(mark, src, want, func(item protocol.TypeHierarchyItem) ([]protocol.TypeHierarchyItem, error) {\n\t\treturn mark.server().Subtypes(mark.ctx(), &protocol.TypeHierarchySubtypesParams{Item: item})\n\t})\n}\n\nfunc supertypesMarker(mark marker, src protocol.Location, want ...protocol.Location) {\n\ttypeHierarchy(mark, src, want, func(item protocol.TypeHierarchyItem) ([]protocol.TypeHierarchyItem, error) {\n\t\treturn mark.server().Supertypes(mark.ctx(), &protocol.TypeHierarchySupertypesParams{Item: item})\n\t})\n}\n\ntype typeHierarchyFunc = func(item protocol.TypeHierarchyItem) ([]protocol.TypeHierarchyItem, error)\n\nfunc typeHierarchy(mark marker, src protocol.Location, want []protocol.Location, get typeHierarchyFunc) {\n\titems, err := mark.server().PrepareTypeHierarchy(mark.ctx(), &protocol.TypeHierarchyPrepareParams{\n\t\tTextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(src),\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"PrepareTypeHierarchy failed: %v\", err)\n\t\treturn\n\t}\n\tif nitems := len(items); nitems != 1 {\n\t\tmark.errorf(\"PrepareTypeHierarchy returned %d items, want exactly 1\", nitems)\n\t\treturn\n\t}\n\tif loc := (protocol.Location{URI: items[0].URI, Range: items[0].Range}); loc != src {\n\t\tmark.errorf(\"PrepareTypeHierarchy found type %v, want %v\", loc, src)\n\t\treturn\n\t}\n\titems, err = get(items[0])\n\tif err != nil {\n\t\tmark.errorf(\"type hierarchy failed: %v\", err)\n\t\treturn\n\t}\n\tgot := []protocol.Location{} // non-nil; cmp.Diff cares\n\tfor _, item := range items {\n\t\tgot = append(got, item.URI.Location(item.Range))\n\t}\n\tif d := cmp.Diff(want, got); d != \"\" {\n\t\tmark.errorf(\"type hierarchy: unexpected results (-want +got):\\n%s\", d)\n\t}\n}\n\n// symbolMarker implements the @symbol marker.\nfunc symbolMarker(mark marker, golden *Golden) {\n\t// Retrieve information about all symbols in this file.\n\tsymbols, err := mark.server().DocumentSymbol(mark.ctx(), &protocol.DocumentSymbolParams{\n\t\tTextDocument: protocol.TextDocumentIdentifier{URI: mark.uri()},\n\t})\n\tif err != nil {\n\t\tmark.errorf(\"DocumentSymbol request failed: %v\", err)\n\t\treturn\n\t}\n\n\t// Format symbols one per line, sorted (in effect) by first column, a dotted name.\n\tvar lines []string\n\tfor _, symbol := range symbols {\n\t\t// Each result element is a union of (legacy)\n\t\t// SymbolInformation and (new) DocumentSymbol,\n\t\t// so we ascertain which one and then transcode.\n\t\tdata, err := json.Marshal(symbol)\n\t\tif err != nil {\n\t\t\tmark.T().Fatal(err)\n\t\t}\n\t\tif _, ok := symbol.(map[string]any)[\"location\"]; ok {\n\t\t\t// This case is not reached because Editor initialization\n\t\t\t// enables HierarchicalDocumentSymbolSupport.\n\t\t\t// TODO(adonovan): test this too.\n\t\t\tvar sym protocol.SymbolInformation\n\t\t\tif err := json.Unmarshal(data, &sym); err != nil {\n\t\t\t\tmark.T().Fatal(err)\n\t\t\t}\n\t\t\tmark.errorf(\"fake Editor doesn't support SymbolInformation\")\n\n\t\t} else {\n\t\t\tvar sym protocol.DocumentSymbol // new hierarchical hotness\n\t\t\tif err := json.Unmarshal(data, &sym); err != nil {\n\t\t\t\tmark.T().Fatal(err)\n\t\t\t}\n\n\t\t\t// Print each symbol in the response tree.\n\t\t\tvar visit func(sym protocol.DocumentSymbol, prefix []string)\n\t\t\tvisit = func(sym protocol.DocumentSymbol, prefix []string) {\n\t\t\t\tvar out strings.Builder\n\t\t\t\tout.WriteString(strings.Join(prefix, \".\"))\n\t\t\t\tfmt.Fprintf(&out, \" %q\", sym.Detail)\n\t\t\t\tif delta := sym.Range.End.Line - sym.Range.Start.Line; delta > 0 {\n\t\t\t\t\tfmt.Fprintf(&out, \" +%d lines\", delta)\n\t\t\t\t}\n\t\t\t\tlines = append(lines, out.String())\n\n\t\t\t\tfor _, child := range sym.Children {\n\t\t\t\t\tvisit(child, append(prefix, child.Name))\n\t\t\t\t}\n\t\t\t}\n\t\t\tvisit(sym, []string{sym.Name})\n\t\t}\n\t}\n\tsort.Strings(lines)\n\tlines = append(lines, \"\") // match trailing newline in .txtar file\n\tgot := []byte(strings.Join(lines, \"\\n\"))\n\n\t// Compare with golden.\n\twant, ok := golden.Get(mark.T(), \"\", got)\n\tif !ok {\n\t\tmark.errorf(\"%s: missing golden file @%s\", mark.note.Name, golden.id)\n\t} else if diff := cmp.Diff(string(got), string(want)); diff != \"\" {\n\t\tmark.errorf(\"%s: unexpected output: got:\\n%s\\nwant:\\n%s\\ndiff:\\n%s\",\n\t\t\tmark.note.Name, got, want, diff)\n\t}\n}\n\n// compareLocations returns an error message if got and want are not\n// the same set of locations. The marker is used only for fmtLoc.\nfunc compareLocations(mark marker, got, want []protocol.Location) error {\n\ttoStrings := func(locs []protocol.Location) []string {\n\t\tstrs := make([]string, len(locs))\n\t\tfor i, loc := range locs {\n\t\t\tstrs[i] = mark.run.fmtLoc(loc)\n\t\t}\n\t\tsort.Strings(strs)\n\t\treturn strs\n\t}\n\tif diff := cmp.Diff(toStrings(want), toStrings(got)); diff != \"\" {\n\t\treturn fmt.Errorf(\"incorrect result locations: (got %d, want %d):\\n%s\",\n\t\t\tlen(got), len(want), diff)\n\t}\n\treturn nil\n}\n\nfunc workspaceSymbolMarker(mark marker, query string, golden *Golden) {\n\tparams := &protocol.WorkspaceSymbolParams{\n\t\tQuery: query,\n\t}\n\n\tgotSymbols, err := mark.server().Symbol(mark.ctx(), params)\n\tif err != nil {\n\t\tmark.errorf(\"Symbol(%q) failed: %v\", query, err)\n\t\treturn\n\t}\n\tvar got bytes.Buffer\n\tfor _, s := range gotSymbols {\n\t\t// Omit the txtar position of the symbol location; otherwise edits to the\n\t\t// txtar archive lead to unexpected failures.\n\t\tloc := mark.run.fmtLocForGolden(s.Location)\n\t\tif loc == \"\" {\n\t\t\tloc = \"<unknown>\"\n\t\t}\n\t\tfmt.Fprintf(&got, \"%s %s %s\\n\", loc, s.Name, s.Kind)\n\t}\n\n\tcompareGolden(mark, got.Bytes(), golden)\n}\n\n// compareGolden compares the content of got with that of g.Get(\"\"), reporting\n// errors on any mismatch.\n//\n// TODO(rfindley): use this helper in more places.\nfunc compareGolden(mark marker, got []byte, g *Golden) {\n\twant, ok := g.Get(mark.T(), \"\", got)\n\tif !ok {\n\t\tmark.errorf(\"missing golden file @%s\", g.id)\n\t\treturn\n\t}\n\t// Normalize newline termination: archive files (i.e. Golden content) can't\n\t// contain non-newline terminated files, except in the special case where the\n\t// file is completely empty.\n\t//\n\t// Note that txtar partitions a contiguous byte slice, so we must copy before\n\t// appending.\n\tnormalize := func(s []byte) []byte {\n\t\tif n := len(s); n > 0 && s[n-1] != '\\n' {\n\t\t\ts = append(s[:n:n], '\\n') // don't mutate array\n\t\t}\n\t\treturn s\n\t}\n\tgot = normalize(got)\n\twant = normalize(want)\n\tif diff := compare.Bytes(want, got); diff != \"\" {\n\t\tmark.errorf(\"%s does not match @%s:\\n%s\", mark.note.Name, g.id, diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/callhierarchy/callhierarchy.txt",
    "content": "This test checks call hierarchy queries.\n\n-ignore_extra_diags due to the initialization cycle.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/callhierarchy\n\n-- incoming/incoming.go --\npackage incoming\n\nimport \"golang.org/lsptests/callhierarchy\"\n\n// A is exported to test incoming calls across packages\nfunc A() { //@loc(incomingA, \"A\")\n\tcallhierarchy.D()\n}\n\n-- outgoing/outgoing.go --\npackage outgoing\n\n// B is exported to test outgoing calls across packages\nfunc B() { //@loc(outgoingB, \"B\")\n}\n\n-- hierarchy.go --\npackage callhierarchy //@loc(hPkg, \"callhierarchy\")\n\nimport \"golang.org/lsptests/callhierarchy/outgoing\"\n\nfunc a() { //@loc(hA, \"a\")\n\tD()\n}\n\nfunc b() { //@loc(hB, \"b\")\n\tD()\n}\n\n// C is an exported function\nfunc C() { //@loc(hC, \"C\")\n\tD()\n\tD()\n}\n\n// To test hierarchy across function literals\nvar x = func() { D() } //@loc(hX, \"x\"),loc(hXGlobal, \"x\")\n\n// D is exported to test incoming/outgoing calls across packages\nfunc D() { //@ loc(hD, \"D\"), incomingcalls(hD, hA, hB, hC, hXGlobal, incomingA), outgoingcalls(hD, hE, hF, hG, hH, hI, Generic, outgoingB)\n\te()\n\tx()\n\tF()\n\toutgoing.B()\n\n\tfunc() {\n\t\tg()\n\t}()\n\n\tvar i Interface = impl{}\n\ti.H()\n\ti.I()\n\n\ts := Struct{}\n\ts.J()\n\ts.K()\n\n\tGeneric[string]()\n}\n\nfunc e() {} //@loc(hE, \"e\")\n\n// F is an exported function\nfunc F() {} //@loc(hF, \"F\")\n\nfunc g() {} //@loc(hG, \"g\")\n\ntype Interface interface {\n\tH() //@loc(hH, \"H\")\n\tI() //@loc(hI, \"I\")\n}\n\ntype impl struct{}\n\nfunc (i impl) H() {}\nfunc (i impl) I() {}\n\ntype Struct struct {\n\tJ func() //@loc(hJ, \"J\")\n\tK func() //@loc(hK, \"K\")\n}\n\nfunc Generic[T any]() //@loc(Generic, \"Generic\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/callhierarchy/issue64451.txt",
    "content": "This test checks call hierarchy queries involving lambdas, which are\ntreated as mere statements of their enclosing name function, since\nwe can't track calls to them.\n\nCalls from a global var decl are reported at the ValueSpec.Names.\n\nSee golang/go#64451.\n\n-- go.mod --\nmodule example.com\ngo 1.0\n\n-- a/a.go --\npackage a\n\nfunc Foo() {   //@ loc(Foo, \"Foo\")\n\tbar()\n}\n\nfunc bar() { \t\t\t//@ loc(bar, \"bar\")\n\tgo func() { baz() }()\n}\n\nfunc baz() {   //@ loc(baz, \"baz\")\n\tbluh()\n}\n\nfunc bluh() {   //@ loc(bluh, \"bluh\")\n\tprint()\n}\n\nvar _ = func() int { //@ loc(global, \"_\")\n\tbaz()\n\treturn 0\n}()\n\nfunc init() { //@ loc(init, \"init\")\n\tbaz()\n}\n\n//@ outgoingcalls(Foo, bar)\n//@ outgoingcalls(bar, baz)\n//@ outgoingcalls(baz, bluh)\n//@ outgoingcalls(bluh)\n//@ outgoingcalls(init, baz)\n\n//@ incomingcalls(Foo)\n//@ incomingcalls(bar, Foo)\n//@ incomingcalls(baz, bar, global, init)\n//@ incomingcalls(bluh, baz)\n//@ incomingcalls(init)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/callhierarchy/issue66923.txt",
    "content": "Regression test for a crash (#66923) in outgoing calls\nto a built-in function (unsafe.Slice).\n\n-- go.mod --\nmodule example.com\ngo 1.17\n\n-- a/a.go --\npackage a\n\nimport \"unsafe\"\n\nfunc A() []int { //@ loc(A, \"A\"), outgoingcalls(A, UNSAFE)\n\treturn unsafe.Slice(new(int), 1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/callhierarchy/issue75230.txt",
    "content": "Regression test for a crash (golang/go#75230) in outgoing calls\nto a built-in method (error.Error).\n\nWe (arbitrarily) don't show calls to built-ins without a package,\nsuch as error.Error, hence the empty result asserted below.\n\n-- go.mod --\nmodule example.com\ngo 1.17\n\n-- a/a.go --\npackage a\n\nfunc A(err error) string { //@ loc(A, \"A\"), outgoingcalls(A)\n\treturn err.Error()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/add_struct_tags.txt",
    "content": "This test checks the behavior of the 'Add struct tags' code action without dialogs.\n\n-- flags --\n-ignore_extra_diags\n\n-- addtags.go --\npackage addtags\n\ntype A struct {\n\tx int //@codeaction(\"x\", \"refactor.rewrite.addTags\", edit=singleline)\n\ty int //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.addTags\", edit=twolines)\n\tz int //@codeaction(re`()n`, \"refactor.rewrite.addTags\", edit=entirestruct)\n}\n-- @entirestruct/addtags.go --\n@@ -4,3 +4,3 @@\n-\tx int //@codeaction(\"x\", \"refactor.rewrite.addTags\", edit=singleline)\n-\ty int //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.addTags\", edit=twolines)\n-\tz int //@codeaction(re`()n`, \"refactor.rewrite.addTags\", edit=entirestruct)\n+\tx int `json:\"x\"` //@codeaction(\"x\", \"refactor.rewrite.addTags\", edit=singleline)\n+\ty int `json:\"y\"` //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.addTags\", edit=twolines)\n+\tz int `json:\"z\"` //@codeaction(re`()n`, \"refactor.rewrite.addTags\", edit=entirestruct)\n-- @singleline/addtags.go --\n@@ -4 +4 @@\n-\tx int //@codeaction(\"x\", \"refactor.rewrite.addTags\", edit=singleline)\n+\tx int `json:\"x\"` //@codeaction(\"x\", \"refactor.rewrite.addTags\", edit=singleline)\n-- @twolines/addtags.go --\n@@ -5,2 +5,2 @@\n-\ty int //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.addTags\", edit=twolines)\n-\tz int //@codeaction(re`()n`, \"refactor.rewrite.addTags\", edit=entirestruct)\n+\ty int `json:\"y\"` //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.addTags\", edit=twolines)\n+\tz int `json:\"z\"` //@codeaction(re`()n`, \"refactor.rewrite.addTags\", edit=entirestruct)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/addtest.txt",
    "content": "This test checks the behavior of the 'add test for FUNC' code action.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/addtest\n\ngo 1.18\n\n-- copyrightandbuildconstraint/copyrightandbuildconstraint.go --\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.18\n\n// Package main is for lsp test.\npackage main\n\nfunc Foo(in string) string {return in} //@codeaction(\"Foo\", \"source.addTest\", edit=with_copyright_build_constraint)\n\n-- @with_copyright_build_constraint/copyrightandbuildconstraint/copyrightandbuildconstraint_test.go --\n@@ -0,0 +1,32 @@\n+// Copyright 2020 The Go Authors. All rights reserved.\n+// Use of this source code is governed by a BSD-style\n+// license that can be found in the LICENSE file.\n+\n+//go:build go1.18\n+\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/copyrightandbuildconstraint\"\n+\t\"testing\"\n+)\n+\n+func TestFoo(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := main.Foo(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- buildconstraint/buildconstraint.go --\n//go:build go1.18\n\n// Package copyright is for lsp test.\npackage copyright\n\nfunc Foo(in string) string {return in} //@codeaction(\"Foo\", \"source.addTest\", edit=with_build_constraint)\n\n-- @with_build_constraint/buildconstraint/buildconstraint_test.go --\n@@ -0,0 +1,28 @@\n+//go:build go1.18\n+\n+package copyright_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/buildconstraint\"\n+\t\"testing\"\n+)\n+\n+func TestFoo(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := copyright.Foo(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- missingtestfile/missingtestfile.go --\npackage main\n\ntype Bar struct {}\n\ntype foo struct {}\n\nfunc ExportedFunction(in string) string {return in} //@codeaction(\"ExportedFunction\", \"source.addTest\", edit=missing_test_file_exported_function)\n\nfunc UnexportedInputParam(in string, f foo) string {return in} //@codeaction(\"UnexportedInputParam\", \"source.addTest\", edit=missing_test_file_function_unexported_input)\n\nfunc unexportedFunction(in string) string {return in} //@codeaction(\"unexportedFunction\", \"source.addTest\", edit=missing_test_file_unexported_function)\n\nfunc (*Bar) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=missing_test_file_exported_recv_exported_method)\n\nfunc (*Bar) UnexportedInputParam(in string, f foo) string {return in} //@codeaction(\"UnexportedInputParam\", \"source.addTest\", edit=missing_test_file_method_unexported_input)\n\nfunc (*foo) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=missing_test_file_unexported_recv)\n\n-- @missing_test_file_exported_function/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,26 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/missingtestfile\"\n+\t\"testing\"\n+)\n+\n+func TestExportedFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := main.ExportedFunction(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedFunction() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @missing_test_file_exported_recv_exported_method/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,28 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/missingtestfile\"\n+\t\"testing\"\n+)\n+\n+func TestBar_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b main.Bar\n+\t\t\tgot := b.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @missing_test_file_function_unexported_input/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,24 @@\n+package main\n+\n+import \"testing\"\n+\n+func TestUnexportedInputParam(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\tf    foo\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := UnexportedInputParam(tt.in, tt.f)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"UnexportedInputParam() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @missing_test_file_method_unexported_input/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,26 @@\n+package main\n+\n+import \"testing\"\n+\n+func TestBar_UnexportedInputParam(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\tf    foo\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b Bar\n+\t\t\tgot := b.UnexportedInputParam(tt.in, tt.f)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"UnexportedInputParam() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @missing_test_file_unexported_function/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,23 @@\n+package main\n+\n+import \"testing\"\n+\n+func Test_unexportedFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := unexportedFunction(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedFunction() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @missing_test_file_unexported_recv/missingtestfile/missingtestfile_test.go --\n@@ -0,0 +1,25 @@\n+package main\n+\n+import \"testing\"\n+\n+func Test_foo_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar f foo\n+\t\t\tgot := f.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- xpackagetestfile/xpackagetestfile.go --\npackage main\n\nfunc ExportedFunction(in string) string {return in} //@codeaction(\"ExportedFunction\", \"source.addTest\", edit=xpackage_exported_function)\nfunc unexportedFunction(in string) string {return in} //@codeaction(\"unexportedFunction\", \"source.addTest\", edit=xpackage_unexported_function)\n\ntype Bar struct {}\n\nfunc (*Bar) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=xpackage_exported_recv_exported_method)\nfunc (*Bar) unexportedMethod(in string) string {return in} //@codeaction(\"unexportedMethod\", \"source.addTest\", edit=xpackage_exported_recv_unexported_method)\n\ntype foo struct {}\n\nfunc (*foo) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=xpackage_unexported_recv_exported_method)\nfunc (*foo) unexportedMethod(in string) string {return in} //@codeaction(\"unexportedMethod\", \"source.addTest\", edit=xpackage_unexported_recv_unexported_method)\n\n-- xpackagetestfile/xpackagetestfile_test.go --\npackage main\n\n-- @xpackage_exported_function/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,22 @@\n+import \"testing\"\n+\n+\n+func TestExportedFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := ExportedFunction(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedFunction() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @xpackage_unexported_function/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,22 @@\n+import \"testing\"\n+\n+\n+func Test_unexportedFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot := unexportedFunction(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedFunction() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @xpackage_exported_recv_exported_method/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func TestBar_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b Bar\n+\t\t\tgot := b.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @xpackage_exported_recv_unexported_method/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func TestBar_unexportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b Bar\n+\t\t\tgot := b.unexportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @xpackage_unexported_recv_exported_method/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func Test_foo_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar f foo\n+\t\t\tgot := f.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @xpackage_unexported_recv_unexported_method/xpackagetestfile/xpackagetestfile_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func Test_foo_unexportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar f foo\n+\t\t\tgot := f.unexportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- aliasreceiver/aliasreceiver.go --\npackage main\n\ntype bar0 struct {}\ntype bar1 = bar0\ntype Bar = bar1\n\nfunc (*Bar) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=pointer_receiver_exported_method)\nfunc (*Bar) unexportedMethod(in string) string {return in} //@codeaction(\"unexportedMethod\", \"source.addTest\", edit=pointer_receiver_unexported_method)\n\ntype foo0 struct {}\ntype foo1 = foo0\ntype foo = foo1\n\nfunc (foo) ExportedMethod(in string) string {return in} //@codeaction(\"ExportedMethod\", \"source.addTest\", edit=alias_receiver_exported_method)\nfunc (foo) unexportedMethod(in string) string {return in} //@codeaction(\"unexportedMethod\", \"source.addTest\", edit=alias_receiver_unexported_method)\n\ntype baz0 struct{}\ntype baz1 = baz0\ntype baz = baz1\n\nfunc newBaz0() baz0 {return baz0{}}\n\nfunc (baz) method(in string) string {return in} //@codeaction(\"method\", \"source.addTest\", edit=alias_constructor_on_underlying_type)\n\ntype qux0 struct{}\ntype qux1 = qux0\ntype qux2 = qux1\ntype Qux = *qux2\n\nfunc newQux1() (qux1, error) {return qux1{}, nil}\n\nfunc (Qux) method(in string) string {return in} //@codeaction(\"method\", \"source.addTest\", edit=alias_constructor_on_different_alias_type)\n\n-- aliasreceiver/aliasreceiver_test.go --\npackage main\n\n-- @pointer_receiver_exported_method/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func TestBar_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b Bar\n+\t\t\tgot := b.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @pointer_receiver_unexported_method/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func TestBar_unexportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar b Bar\n+\t\t\tgot := b.unexportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @alias_receiver_exported_method/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func Test_foo_ExportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar f foo\n+\t\t\tgot := f.ExportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"ExportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @alias_receiver_unexported_method/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,24 @@\n+import \"testing\"\n+\n+\n+func Test_foo_unexportedMethod(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\t// TODO: construct the receiver type.\n+\t\t\tvar f foo\n+\t\t\tgot := f.unexportedMethod(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"unexportedMethod() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @alias_constructor_on_underlying_type/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,23 @@\n+import \"testing\"\n+\n+\n+func Test_baz_method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tb := newBaz0()\n+\t\t\tgot := b.method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @alias_constructor_on_different_alias_type/aliasreceiver/aliasreceiver_test.go --\n@@ -3 +3,26 @@\n+import \"testing\"\n+\n+\n+func TestQux_method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tq, err := newQux1()\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot := q.method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- multiinputoutput/multiinputoutput.go --\npackage main\n\nfunc Foo(in, in2, in3, in4 string) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Foo\", \"source.addTest\", edit=multi_input_output)\n\n-- @multi_input_output/multiinputoutput/multiinputoutput_test.go --\n@@ -0,0 +1,37 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/multiinputoutput\"\n+\t\"testing\"\n+)\n+\n+func TestFoo(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin    string\n+\t\tin2   string\n+\t\tin3   string\n+\t\tin4   string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.Foo(tt.in, tt.in2, tt.in3, tt.in4)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- xpackagerename/xpackagerename.go --\npackage main\n\nimport (\n  mytime \"time\"\n  myast \"go/ast\"\n  mytest \"testing\"\n)\n\nvar local mytest.T\n\nfunc Foo(t mytime.Time, a *myast.Node) (mytime.Time, *myast.Node) {return t, a} //@codeaction(\"Foo\", \"source.addTest\", edit=xpackage_rename)\n\n-- @xpackage_rename/xpackagerename/xpackagerename_test.go --\n@@ -0,0 +1,33 @@\n+package main_test\n+\n+import(\n+\tmyast \"go/ast\"\n+\t\"golang.org/lsptests/addtest/xpackagerename\"\n+\tmytest \"testing\"\n+\tmytime \"time\"\n+)\n+\n+func TestFoo(t *mytest.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tt     mytime.Time\n+\t\ta     *myast.Node\n+\t\twant  mytime.Time\n+\t\twant2 *myast.Node\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *mytest.T) {\n+\t\t\tgot, got2 := main.Foo(tt.t, tt.a)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- xtestpackagerename/xtestpackagerename.go --\npackage main\n\nimport (\n  mytime \"time\"\n  myast \"go/ast\"\n  mytest \"testing\"\n)\n\nvar local mytest.T\n\nfunc Foo(t mytime.Time, a *myast.Node) (mytime.Time, *myast.Node) {return t, a} //@codeaction(\"Foo\", \"source.addTest\", edit=xtest_package_rename)\n\n-- xtestpackagerename/xtestpackagerename_test.go --\npackage main_test\n\nimport (\n\tyourast \"go/ast\"\n\tyourtest \"testing\"\n\tyourtime \"time\"\n)\n\nvar fooTime = yourtime.Time{}\nvar fooNode = yourast.Node{}\nvar fooT yourtest.T\n\n-- @xtest_package_rename/xtestpackagerename/xtestpackagerename_test.go --\n@@ -7 +7,2 @@\n+\n+\t\"golang.org/lsptests/addtest/xtestpackagerename\"\n@@ -13 +15,25 @@\n+\n+func TestFoo(t *yourtest.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tt     yourtime.Time\n+\t\ta     *yourast.Node\n+\t\twant  yourtime.Time\n+\t\twant2 *yourast.Node\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *yourtest.T) {\n+\t\t\tgot, got2 := main.Foo(tt.t, tt.a)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Foo() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- returnwitherror/returnwitherror.go --\npackage main\n\nfunc OnlyErr() error {return nil} //@codeaction(\"OnlyErr\", \"source.addTest\", edit=return_only_error)\nfunc StringErr() (string, error) {return \"\", nil} //@codeaction(\"StringErr\", \"source.addTest\", edit=return_string_error)\nfunc MultipleStringErr() (string, string, string, error) {return \"\", \"\", \"\", nil} //@codeaction(\"MultipleStringErr\", \"source.addTest\", edit=return_multiple_string_error)\n\n-- @return_only_error/returnwitherror/returnwitherror_test.go --\n@@ -0,0 +1,29 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/returnwitherror\"\n+\t\"testing\"\n+)\n+\n+func TestOnlyErr(t *testing.T) {\n+\ttests := []struct {\n+\t\tname    string // description of this test case\n+\t\twantErr bool\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgotErr := main.OnlyErr()\n+\t\t\tif gotErr != nil {\n+\t\t\t\tif !tt.wantErr {\n+\t\t\t\t\tt.Errorf(\"OnlyErr() failed: %v\", gotErr)\n+\t\t\t\t}\n+\t\t\t\treturn\n+\t\t\t}\n+\t\t\tif tt.wantErr {\n+\t\t\t\tt.Fatal(\"OnlyErr() succeeded unexpectedly\")\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @return_string_error/returnwitherror/returnwitherror_test.go --\n@@ -0,0 +1,34 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/returnwitherror\"\n+\t\"testing\"\n+)\n+\n+func TestStringErr(t *testing.T) {\n+\ttests := []struct {\n+\t\tname    string // description of this test case\n+\t\twant    string\n+\t\twantErr bool\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, gotErr := main.StringErr()\n+\t\t\tif gotErr != nil {\n+\t\t\t\tif !tt.wantErr {\n+\t\t\t\t\tt.Errorf(\"StringErr() failed: %v\", gotErr)\n+\t\t\t\t}\n+\t\t\t\treturn\n+\t\t\t}\n+\t\t\tif tt.wantErr {\n+\t\t\t\tt.Fatal(\"StringErr() succeeded unexpectedly\")\n+\t\t\t}\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"StringErr() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @return_multiple_string_error/returnwitherror/returnwitherror_test.go --\n@@ -0,0 +1,42 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/returnwitherror\"\n+\t\"testing\"\n+)\n+\n+func TestMultipleStringErr(t *testing.T) {\n+\ttests := []struct {\n+\t\tname    string // description of this test case\n+\t\twant    string\n+\t\twant2   string\n+\t\twant3   string\n+\t\twantErr bool\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3, gotErr := main.MultipleStringErr()\n+\t\t\tif gotErr != nil {\n+\t\t\t\tif !tt.wantErr {\n+\t\t\t\t\tt.Errorf(\"MultipleStringErr() failed: %v\", gotErr)\n+\t\t\t\t}\n+\t\t\t\treturn\n+\t\t\t}\n+\t\t\tif tt.wantErr {\n+\t\t\t\tt.Fatal(\"MultipleStringErr() succeeded unexpectedly\")\n+\t\t\t}\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"MultipleStringErr() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"MultipleStringErr() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"MultipleStringErr() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- constructor/constructor.go --\npackage main\n\n// Constructor returns the type T.\nfunc NewReturnType() ReturnType {return ReturnType{}}\n\ntype ReturnType struct {}\n\nfunc (*ReturnType) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_return_type)\n\n// Constructor returns the type T and an error.\nfunc NewReturnTypeError() (ReturnTypeError, error) {return ReturnTypeError{}, nil}\n\ntype ReturnTypeError struct {}\n\nfunc (*ReturnTypeError) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_return_type_error)\n\n// Constructor returns the type *T.\nfunc NewReturnPtr() *ReturnPtr {return nil}\n\ntype ReturnPtr struct {}\n\nfunc (*ReturnPtr) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_return_ptr)\n\n// Constructor returns the type *T and an error.\nfunc NewReturnPtrError() (*ReturnPtrError, error) {return nil, nil}\n\ntype ReturnPtrError struct {}\n\nfunc (*ReturnPtrError) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_return_ptr_error)\n\n-- @constructor_return_type/constructor/constructor_test.go --\n@@ -0,0 +1,27 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructor\"\n+\t\"testing\"\n+)\n+\n+func TestReturnType_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewReturnType()\n+\t\t\tgot := r.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @constructor_return_type_error/constructor/constructor_test.go --\n@@ -0,0 +1,30 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructor\"\n+\t\"testing\"\n+)\n+\n+func TestReturnTypeError_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr, err := main.NewReturnTypeError()\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot := r.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @constructor_return_ptr/constructor/constructor_test.go --\n@@ -0,0 +1,27 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructor\"\n+\t\"testing\"\n+)\n+\n+func TestReturnPtr_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewReturnPtr()\n+\t\t\tgot := r.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @constructor_return_ptr_error/constructor/constructor_test.go --\n@@ -0,0 +1,30 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructor\"\n+\t\"testing\"\n+)\n+\n+func TestReturnPtrError_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr, err := main.NewReturnPtrError()\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot := r.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- constructorcomparison/constructorcomparison.go --\npackage main\n\n// Foo have two constructors. NewFoo is preferred over others.\nfunc CreateAFoo() Foo {return Foo{}}\nfunc NewFoo() Foo {return Foo{}}\n\ntype Foo struct{}\n\nfunc (*Foo) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_comparison_new)\n\n// Bar have two constructors. Bar is preferred due to alphabetical ordering.\nfunc ABar() (Bar, error) {return Bar{}, nil}\n// func CreateABar() Bar {return Bar{}}\n\ntype Bar struct{}\n\nfunc (*Bar) Method(in string) string {return in} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_comparison_alphabetical)\n\n-- @constructor_comparison_new/constructorcomparison/constructorcomparison_test.go --\n@@ -0,0 +1,27 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructorcomparison\"\n+\t\"testing\"\n+)\n+\n+func TestFoo_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tf := main.NewFoo()\n+\t\t\tgot := f.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @constructor_comparison_alphabetical/constructorcomparison/constructorcomparison_test.go --\n@@ -0,0 +1,30 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/constructorcomparison\"\n+\t\"testing\"\n+)\n+\n+func TestBar_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tin   string\n+\t\twant string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tb, err := main.ABar()\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot := b.Method(tt.in)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- unnamedparam/unnamedparam.go --\npackage main\n\nimport \"time\"\n\nfunc FooInputBasic(one, two, _ string, _ int) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Foo\", \"source.addTest\", edit=function_basic_type)\n\nfunc FooInputStruct(one string, _ time.Time) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Foo\", \"source.addTest\", edit=function_struct_type)\n\nfunc FooInputPtr(one string, _ *time.Time) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Foo\", \"source.addTest\", edit=function_ptr_type)\n\nfunc FooInputFunc(one string, _ func(time.Time) *time.Time) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Foo\", \"source.addTest\", edit=function_func_type)\n\ntype BarInputBasic struct{}\n\nfunc NewBarInputBasic(one, two, _ string, _ int) *BarInputBasic {return nil}\n\nfunc (r *BarInputBasic) Method(one, two, _ string, _ int) {} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_basic_type)\n\ntype BarInputStruct struct{}\n\nfunc NewBarInputStruct(one string, _ time.Time) *BarInputStruct {return nil}\n\nfunc (r *BarInputStruct) Method(one string, _ time.Time) {} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_struct_type)\n\ntype BarInputPtr struct{}\n\nfunc NewBarInputPtr(one string, _ *time.Time) *BarInputPtr {return nil}\n\nfunc (r *BarInputPtr) Method(one string, _ *time.Time) {} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_ptr_type)\n\ntype BarInputFunction struct{}\n\nfunc NewBarInputFunction(one string, _ func(time.Time) *time.Time) *BarInputFunction {return nil}\n\nfunc (r *BarInputFunction) Method(one string, _ func(time.Time) *time.Time) {} //@codeaction(\"Method\", \"source.addTest\", edit=constructor_func_type)\n\n-- @function_basic_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,35 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+)\n+\n+func TestFooInputBasic(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tone   string\n+\t\ttwo   string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.FooInputBasic(tt.one, tt.two, \"\", 0)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputBasic() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputBasic() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputBasic() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @function_func_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,35 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestFooInputFunc(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tone   string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.FooInputFunc(tt.one, nil)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputFunc() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputFunc() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputFunc() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @function_ptr_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,35 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestFooInputPtr(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tone   string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.FooInputPtr(tt.one, nil)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputPtr() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputPtr() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputPtr() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @function_struct_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,35 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestFooInputStruct(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\tone   string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.FooInputStruct(tt.one, time.Time{})\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputStruct() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputStruct() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"FooInputStruct() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @constructor_basic_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,26 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+)\n+\n+func TestBarInputBasic_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for receiver constructor.\n+\t\tcone string\n+\t\tctwo string\n+\t\t// Named input parameters for target function.\n+\t\tone string\n+\t\ttwo string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewBarInputBasic(tt.cone, tt.ctwo, \"\", 0)\n+\t\t\tr.Method(tt.one, tt.two, \"\", 0)\n+\t\t})\n+\t}\n+}\n-- @constructor_func_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,25 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestBarInputFunction_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for receiver constructor.\n+\t\tcone string\n+\t\t// Named input parameters for target function.\n+\t\tone string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewBarInputFunction(tt.cone, nil)\n+\t\t\tr.Method(tt.one, nil)\n+\t\t})\n+\t}\n+}\n-- @constructor_ptr_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,25 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestBarInputPtr_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for receiver constructor.\n+\t\tcone string\n+\t\t// Named input parameters for target function.\n+\t\tone string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewBarInputPtr(tt.cone, nil)\n+\t\t\tr.Method(tt.one, nil)\n+\t\t})\n+\t}\n+}\n-- @constructor_struct_type/unnamedparam/unnamedparam_test.go --\n@@ -0,0 +1,25 @@\n+package main_test\n+\n+import(\n+\t\"golang.org/lsptests/addtest/unnamedparam\"\n+\t\"testing\"\n+\t\"time\"\n+)\n+\n+func TestBarInputStruct_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for receiver constructor.\n+\t\tcone string\n+\t\t// Named input parameters for target function.\n+\t\tone string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tr := main.NewBarInputStruct(tt.cone, time.Time{})\n+\t\t\tr.Method(tt.one, time.Time{})\n+\t\t})\n+\t}\n+}\n-- contextinput/contextinput.go --\npackage main\n\nimport \"context\"\n\nfunc Function(ctx context.Context, _, _ string) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Function\", \"source.addTest\", edit=function_context)\n\ntype Foo struct {}\n\nfunc NewFoo(ctx context.Context) (*Foo, error) {return nil, nil}\n\nfunc (*Foo) Method(ctx context.Context, _, _ string)  (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Method\", \"source.addTest\", edit=method_context)\n-- contextinput/contextinput_test.go --\npackage main_test\n\nimport renamedctx \"context\"\n\nvar local renamedctx.Context\n\n-- @function_context/contextinput/contextinput_test.go --\n@@ -3 +3,3 @@\n-import renamedctx \"context\"\n+import (\n+\trenamedctx \"context\"\n+\t\"testing\"\n@@ -5 +7,3 @@\n+\t\"golang.org/lsptests/addtest/contextinput\"\n+)\n+\n@@ -7 +12,26 @@\n+\n+func TestFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname  string // description of this test case\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.Function(renamedctx.Background(), \"\", \"\")\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @method_context/contextinput/contextinput_test.go --\n@@ -3 +3,3 @@\n-import renamedctx \"context\"\n+import (\n+\trenamedctx \"context\"\n+\t\"testing\"\n@@ -5 +7,3 @@\n+\t\"golang.org/lsptests/addtest/contextinput\"\n+)\n+\n@@ -7 +12,30 @@\n+\n+func TestFoo_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname  string // description of this test case\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tf, err := main.NewFoo(renamedctx.Background())\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot, got2, got3 := f.Method(renamedctx.Background(), \"\", \"\")\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- typeparameter/typeparameter.go --\npackage main\n\nfunc Function[T any] () {} // no suggested fix\n\ntype Foo struct {}\n\nfunc NewFoo()\n\nfunc (*Foo) Method[T any]() {} // no suggested fix\n-- varargsinput/varargsinput.go --\npackage main\n\nfunc Function(args ...string) (out, out1, out2 string) {return args[0], \"\", \"\"} //@codeaction(\"Function\", \"source.addTest\", edit=function_varargsinput)\n\ntype Foo struct {}\n\nfunc NewFoo(args ...string) (*Foo, error) { \n    _ = args\n    return nil, nil \n}\n\nfunc (*Foo) Method(args ...string)  (out, out1, out2 string) {return args[0], \"\", \"\"} //@codeaction(\"Method\", \"source.addTest\", edit=method_varargsinput)\n-- varargsinput/varargsinput_test.go --\npackage main_test\n-- @function_varargsinput/varargsinput/varargsinput_test.go --\n@@ -2 +2,34 @@\n+\n+import (\n+\t\"testing\"\n+\n+\t\"golang.org/lsptests/addtest/varargsinput\"\n+)\n+\n+func TestFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for target function.\n+\t\targs  []string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.Function(tt.args...)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @method_varargsinput/varargsinput/varargsinput_test.go --\n@@ -2 +2,40 @@\n+\n+import (\n+\t\"testing\"\n+\n+\t\"golang.org/lsptests/addtest/varargsinput\"\n+)\n+\n+func TestFoo_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname string // description of this test case\n+\t\t// Named input parameters for receiver constructor.\n+\t\tcargs []string\n+\t\t// Named input parameters for target function.\n+\t\targs  []string\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tf, err := main.NewFoo(tt.cargs...)\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot, got2, got3 := f.Method(tt.args...)\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- unusedvarargsinput/unusedvarargsinput.go --\npackage main\n\nfunc Function(_ ...string) (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Function\", \"source.addTest\", edit=function_unusedvarargsinput)\n\ntype Foo struct {}\n\nfunc NewFoo(_ ...string) (*Foo, error) { \n    return nil, nil \n}\n\nfunc (*Foo) Method(_ ...string)  (out, out1, out2 string) {return \"\", \"\", \"\"} //@codeaction(\"Method\", \"source.addTest\", edit=method_unusedvarargsinput)\n-- unusedvarargsinput/unusedvarargsinput_test.go --\npackage main_test\n-- @function_unusedvarargsinput/unusedvarargsinput/unusedvarargsinput_test.go --\n@@ -2 +2,32 @@\n+\n+import (\n+\t\"testing\"\n+\n+\t\"golang.org/lsptests/addtest/unusedvarargsinput\"\n+)\n+\n+func TestFunction(t *testing.T) {\n+\ttests := []struct {\n+\t\tname  string // description of this test case\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tgot, got2, got3 := main.Function()\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Function() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n-- @method_unusedvarargsinput/unusedvarargsinput/unusedvarargsinput_test.go --\n@@ -2 +2,36 @@\n+\n+import (\n+\t\"testing\"\n+\n+\t\"golang.org/lsptests/addtest/unusedvarargsinput\"\n+)\n+\n+func TestFoo_Method(t *testing.T) {\n+\ttests := []struct {\n+\t\tname  string // description of this test case\n+\t\twant  string\n+\t\twant2 string\n+\t\twant3 string\n+\t}{\n+\t\t// TODO: Add test cases.\n+\t}\n+\tfor _, tt := range tests {\n+\t\tt.Run(tt.name, func(t *testing.T) {\n+\t\t\tf, err := main.NewFoo()\n+\t\t\tif err != nil {\n+\t\t\t\tt.Fatalf(\"could not construct receiver type: %v\", err)\n+\t\t\t}\n+\t\t\tgot, got2, got3 := f.Method()\n+\t\t\t// TODO: update the condition below to compare got with tt.want.\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got, tt.want)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got2, tt.want2)\n+\t\t\t}\n+\t\t\tif true {\n+\t\t\t\tt.Errorf(\"Method() = %v, want %v\", got3, tt.want3)\n+\t\t\t}\n+\t\t})\n+\t}\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/change_quote.txt",
    "content": "This test checks the behavior of the 'change quote' code action.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/changequote\n\ngo 1.18\n\n-- a.go --\npackage changequote\n\nimport (\n\t\"fmt\"\n)\n\nfunc foo() {\n\tvar s string\n\ts = \"hello\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a1)\n\ts = `hello` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a2)\n\ts = \"hello\\tworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a3)\n\ts = `hello\tworld` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a4)\n\ts = \"hello\\nworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a5)\n\t// add a comment  to avoid affect diff compute\n\ts = `hello\nworld` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a6)\n\ts = \"hello\\\"world\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a7)\n\ts = `hello\"world` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a8)\n\ts = \"hello\\x1bworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", err=re\"found 0 CodeActions\")\n\ts = \"hello`world\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", err=re\"found 0 CodeActions\")\n\ts = \"hello\\x7fworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", err=re\"found 0 CodeActions\")\n\tfmt.Println(s)\n}\n\n-- @a1/a.go --\n@@ -9 +9 @@\n-\ts = \"hello\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a1)\n+\ts = `hello` //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a1)\n-- @a2/a.go --\n@@ -10 +10 @@\n-\ts = `hello` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a2)\n+\ts = \"hello\" //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a2)\n-- @a3/a.go --\n@@ -11 +11 @@\n-\ts = \"hello\\tworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a3)\n+\ts = `hello\tworld` //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a3)\n-- @a4/a.go --\n@@ -12 +12 @@\n-\ts = `hello\tworld` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a4)\n+\ts = \"hello\\tworld\" //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a4)\n-- @a5/a.go --\n@@ -13 +13,2 @@\n-\ts = \"hello\\nworld\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a5)\n+\ts = `hello\n+world` //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a5)\n-- @a6/a.go --\n@@ -15,2 +15 @@\n-\ts = `hello\n-world` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a6)\n+\ts = \"hello\\nworld\" //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a6)\n-- @a7/a.go --\n@@ -17 +17 @@\n-\ts = \"hello\\\"world\" //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a7)\n+\ts = `hello\"world` //@codeaction(`\"`, \"refactor.rewrite.changeQuote\", edit=a7)\n-- @a8/a.go --\n@@ -18 +18 @@\n-\ts = `hello\"world` //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a8)\n+\ts = \"hello\\\"world\" //@codeaction(\"`\", \"refactor.rewrite.changeQuote\", edit=a8)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/eliminate_dot_import.txt",
    "content": "This test checks the behavior of the 'remove dot import' code action.\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a.go --\npackage dotimport\n\n// Base case: action is OK.\n\nimport (\n\t. \"fmt\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a1)\n\t. \"bytes\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a2)\n\t. \"time\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a3)\n)\n\nvar _ = a\n\nfunc a() {\n\tPrintln(\"hello\")\n\n\tbuf := NewBuffer(nil)\n\tbuf.Grow(10)\n\n\t_ = Ticker{C: nil}\n}\n\n-- @a1/a.go --\n@@ -6 +6 @@\n-\t. \"fmt\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a1)\n+\t\"fmt\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a1)\n@@ -14 +14 @@\n-\tPrintln(\"hello\")\n+\tfmt.Println(\"hello\")\n-- @a2/a.go --\n@@ -7 +7 @@\n-\t. \"bytes\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a2)\n+\t\"bytes\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a2)\n@@ -16 +16 @@\n-\tbuf := NewBuffer(nil)\n+\tbuf := bytes.NewBuffer(nil)\n-- @a3/a.go --\n@@ -8 +8 @@\n-\t. \"time\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a3)\n+\t\"time\" //@codeaction(`.`, \"refactor.rewrite.eliminateDotImport\", edit=a3)\n@@ -19 +19 @@\n-\t_ = Ticker{C: nil}\n+\t_ = time.Ticker{C: nil}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract-variadic-63287.txt",
    "content": "This test exercises extract on a variadic function.\nIt is a regression test for bug #63287 in which\nthe final parameter's \"...\" would go missing.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\n//@codeaction(block, \"refactor.extract.function\", edit=out)\n\nfunc _() {\n\tvar logf func(string, ...any)\n\t{ println(logf) } //@loc(block, re`{[^}]*}`)\n}\n\n-- @out/a/a.go --\n@@ -7 +7 @@\n-\t{ println(logf) } //@loc(block, re`{[^}]*}`)\n+\t{ newFunction(logf) } //@loc(block, re`{[^}]*}`)\n@@ -10 +10,4 @@\n+func newFunction(logf func( string,  ...any)) {\n+\tprintln(logf)\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_anonymous_struct.txt",
    "content": "This test checks of the behavior of extract function when the extracted block includes anonymous structs.\n-- go.mod --\nmodule mod.com\n\ngo 1.12\n-- a/a.go --\npackage a\n\nfunc _() {\n\tvar x struct{ y int } //@codeaction(\"var\", \"refactor.extract.function\", end=endA, result=anonA)\n\tprintln(x.y) //@loc(endA, \")\")\n}\n\n-- b/b.go --\npackage b\n\nfunc _() {\n\ttype T struct {\n\t\ty int\n\t}\n\tvar x T //@codeaction(\"var\", \"refactor.extract.function\", end=endB, err=\"the code refers to a local type\")\n\tprintln(x.y) //@loc(endB, \")\")\n}\n\n-- @anonA/a/a.go --\npackage a\n\nfunc _() {\n\tnewFunction() //@loc(endA, \")\")\n}\n\nfunc newFunction() {\n\tvar x struct{ y int } //@codeaction(\"var\", \"refactor.extract.function\", end=endA, result=anonA)\n\tprintln(x.y)\n}\n\n-- d/d.go --\npackage d\n\nfunc _() {\n\ts := []struct{ y int }{\n\t\t{y: 1},\n\t\t{y: 2},\n\t}\n\tfor _, v := range s { //@codeaction(\"for\", \"refactor.extract.function\", end=endD, result=anonD)\n\t\tprintln(v.y)\n\t} //@loc(endD, \"}\")\n}\n\n-- @anonD/d/d.go --\npackage d\n\nfunc _() {\n\ts := []struct{ y int }{\n\t\t{y: 1},\n\t\t{y: 2},\n\t}\n\tnewFunction(s) //@loc(endD, \"}\")\n}\n\nfunc newFunction(s []struct{y int}) {\n\tfor _, v := range s { //@codeaction(\"for\", \"refactor.extract.function\", end=endD, result=anonD)\n\t\tprintln(v.y)\n\t}\n}\n\n-- e/e.go --\npackage e\n\nfunc _() {\n\tvar x int\n\ts := []struct { //@codeaction(\"s\", \"refactor.extract.function\", end=endE, result=anonE)\n\t\ty int\n\t}{\n\t\t{y: 1},\n\t\t{y: 2},\n\t}\n\tx = s[0].y //@loc(endE, \"x = s[0].y\")\n\tprintln(x)\n}\n\n-- @anonE/e/e.go --\npackage e\n\nfunc _() {\n\tvar x int\n\tx = newFunction(x) //@loc(endE, \"x = s[0].y\")\n\tprintln(x)\n}\n\nfunc newFunction(x int) int {\n\ts := []struct { //@codeaction(\"s\", \"refactor.extract.function\", end=endE, result=anonE)\n\t\ty int\n\t}{\n\t\t{y: 1},\n\t\t{y: 2},\n\t}\n\tx = s[0].y\n\treturn x\n}\n\n-- f/f.go --\npackage f\nfunc _() int {\n\tx := struct{ y int } { y: 1 } //@codeaction(\"x\", \"refactor.extract.function\", end=endF, result=anonF)\n\treturn x.y //@loc(endF, \"y\")\n}\n\n-- @anonF/f/f.go --\npackage f\nfunc _() int {\n\treturn newFunction() //@loc(endF, \"y\")\n}\n\nfunc newFunction() int {\n\tx := struct{ y int }{y: 1} //@codeaction(\"x\", \"refactor.extract.function\", end=endF, result=anonF)\n\treturn x.y\n}\n\n-- g/g.go --\npackage g\n\nimport \"fmt\"\n\nfunc _() error {\n\tx := struct{ y error }{fmt.Errorf(\"test error\")}\n\treturn x.y //@ loc(endG, \"y\"), codeaction(\"return\", \"refactor.extract.function\", end=endG, result=anonG)\n}\n\n-- @anonG/g/g.go --\npackage g\n\nimport \"fmt\"\n\nfunc _() error {\n\tx := struct{ y error }{fmt.Errorf(\"test error\")}\n\treturn newFunction(x) //@ loc(endG, \"y\"), codeaction(\"return\", \"refactor.extract.function\", end=endG, result=anonG)\n}\n\nfunc newFunction(x struct{y error}) error {\n\treturn x.y\n}\n\n-- h/h.go --\npackage h\n\nimport \"fmt\"\n\nfunc _() string {\n\ttype A error\n\ttype B struct {\n\t\tA\n\t}\n\ta := B{A: fmt.Errorf(\"test error\")} //@codeaction(\"a\", \"refactor.extract.function\", end=endH, err=\"the code refers to a local type\")\n\treturn a.Error() //@loc(endH, \"Error()\")\n}\n\n-- i/i.go --\npackage i\n\nimport \"fmt\"\n\nfunc _() string {\n\tvar a struct{ e error } //@codeaction(\"var\", \"refactor.extract.function\", end=endI, result=anonI)\n\ta.e = fmt.Errorf(\"test error\")\n\treturn a.e.Error() //@loc(endI, \"Error()\")\n}\n\n-- @anonI/i/i.go --\npackage i\n\nimport \"fmt\"\n\nfunc _() string {\n\treturn newFunction() //@loc(endI, \"Error()\")\n}\n\nfunc newFunction() string {\n\tvar a struct{ e error } //@codeaction(\"var\", \"refactor.extract.function\", end=endI, result=anonI)\n\ta.e = fmt.Errorf(\"test error\")\n\treturn a.e.Error()\n}\n\n-- j/j.go --\npackage j\n\nimport \"unsafe\"\n\nfunc _() uintptr {\n\tvar x struct{ p unsafe.Pointer }\n\ty := uintptr(x.p) //@codeaction(\"y\", \"refactor.extract.function\", end=endJ, result=anonJ)\n\treturn y //@loc(endJ, \"y\")\n}\n\n-- @anonJ/j/j.go --\npackage j\n\nimport \"unsafe\"\n\nfunc _() uintptr {\n\tvar x struct{ p unsafe.Pointer }\n\treturn newFunction(x) //@loc(endJ, \"y\")\n}\n\nfunc newFunction(x struct{p unsafe.Pointer}) uintptr {\n\ty := uintptr(x.p) //@codeaction(\"y\", \"refactor.extract.function\", end=endJ, result=anonJ)\n\treturn y\n}\n\n-- k/k.go --\npackage k\n\nimport \"unsafe\"\n\nfunc _(x int) unsafe.Pointer {\n\ttype A struct {\n\t\tp unsafe.Pointer\n\t}\n\tc := A{p: unsafe.Pointer(&x)} //@codeaction(\"c\", \"refactor.extract.function\", end=endK, err=\"the code refers to a local type\")\n\treturn c.p //@loc(endK, \"c.p\")\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_control.txt",
    "content": "This test verifies various behaviors of function extraction involving free control statements.\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- freecontrol.go --\npackage extract\n\n//@codeaction(ifCondContinue, \"refactor.extract.function\", edit=freeControl1)\n//@codeaction(ifCondGotoLabel, \"refactor.extract.function\", edit=freeControl2)\n//@codeaction(ifCondGotoLabelWithLabel, \"refactor.extract.function\", edit=freeControl3)\n//@codeaction(multipleCtrl, \"refactor.extract.function\", edit=freeControl4)\n//@codeaction(multipleCtrlNotAllSelected, \"refactor.extract.function\", edit=freeControl5)\n//@codeaction(ctrlVarExists, \"refactor.extract.function\", edit=freeControl6)\n//@codeaction(twoReturns, \"refactor.extract.function\", edit=freeControl7)\n//@codeaction(forWithLabel, \"refactor.extract.function\", edit=freeControl8)\n\nfunc FuncContinue(cond bool) {\n\tfor range \"abc\" {\n\t\tif cond { //@ loc(ifCondContinue, re`(?s)if.*println.0.`)\n\t\t\tcontinue\n\t\t}\n\t\tprintln(0)\n\t}\n}\n\nfunc FuncGoTo(cond bool) {\n\tfor range \"abc\" {\n\t\tif cond { //@ loc(ifCondGotoLabel, re`(?s)if.*println.1.`), loc(ifCondGotoLabelWithLabel, re`(?s)if.*goto.label1....`)\n\t\t\tgoto label1\n\t\t}\n\tlabel1:\n\t\tprintln(1)\n\t}\n}\n\nfunc FuncMultipleCtrl(x int) {\n\tfor range \"abc\" {\n\t\tif x < 10 { //@ loc(multipleCtrl, re`(?s)if.x.*return...next1....`), loc(multipleCtrlNotAllSelected, re`(?s)if.x.*break....`)\n\t\t\tcontinue\n\t\t}\n\t\tif x > 2 {\n\t\t\tbreak\n\t\t}\n\t\tif x == 1 {\n\t\t\treturn //next1\n\t\t}\n\t}\n}\n\nfunc FuncCtrlVarExists(x int) {\n\tctrl := \"abc\"\n\tfor range ctrl {\n\t\tif x < 10 { //@ loc(ctrlVarExists, re`(?s)if.x.*continue...next2....`)\n\t\t\tcontinue //next2\n\t\t}\n\t}\n}\n\nfunc FuncTwoReturns(x int) int {\n outer:\n\tfor range \"abc\" {\n\t\tif x < 10 { //@ loc(twoReturns, re`(?s)if.x.*return.1....`)\n\t\t\treturn 0\n\t\t}\n\t\ttest := x - 4\n\t\tif test > 2 {\n\t\t\tcontinue\n\t\t}\n\t\tif test == 10 {\n\t\t\treturn 1\n\t\t}\n\n\t\tfor range \"def\" { //@ loc(forWithLabel, re`(?s)for.*outer.........`)\n\t\t\tif x < 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif x > 10 {\n\t\t\t\tcontinue outer\n\t\t\t}\n\t\t}\n\t}\n\treturn 0\n}\n-- @freeControl1/freecontrol.go --\n@@ -14 +14,3 @@\n-\t\tif cond { //@ loc(ifCondContinue, re`(?s)if.*println.0.`)\n+\t\tctrl := newFunction(cond)\n+\t\tswitch ctrl {\n+\t\tcase 1:\n@@ -17 +19 @@\n-\t\tprintln(0)\n@@ -21 +22,8 @@\n+func newFunction(cond bool) int {\n+\tif cond { //@ loc(ifCondContinue, re`(?s)if.*println.0.`)\n+\t\treturn 1\n+\t}\n+\tprintln(0)\n+\treturn 0\n+}\n+\n-- @freeControl2/freecontrol.go --\n@@ -23,5 +23 @@\n-\t\tif cond { //@ loc(ifCondGotoLabel, re`(?s)if.*println.1.`), loc(ifCondGotoLabelWithLabel, re`(?s)if.*goto.label1....`)\n-\t\t\tgoto label1\n-\t\t}\n-\tlabel1:\n-\t\tprintln(1)\n+\t\tnewFunction(cond)\n@@ -31 +27,8 @@\n+func newFunction(cond bool) {\n+\tif cond { //@ loc(ifCondGotoLabel, re`(?s)if.*println.1.`), loc(ifCondGotoLabelWithLabel, re`(?s)if.*goto.label1....`)\n+\t\tgoto label1\n+\t}\n+label1:\n+\tprintln(1)\n+}\n+\n-- @freeControl3/freecontrol.go --\n@@ -23 +23,3 @@\n-\t\tif cond { //@ loc(ifCondGotoLabel, re`(?s)if.*println.1.`), loc(ifCondGotoLabelWithLabel, re`(?s)if.*goto.label1....`)\n+\t\tctrl := newFunction(cond)\n+\t\tswitch ctrl {\n+\t\tcase 1:\n@@ -31 +33,7 @@\n+func newFunction(cond bool) int {\n+\tif cond { //@ loc(ifCondGotoLabel, re`(?s)if.*println.1.`), loc(ifCondGotoLabelWithLabel, re`(?s)if.*goto.label1....`)\n+\t\treturn 1\n+\t}\n+\treturn 0\n+}\n+\n-- @freeControl4/freecontrol.go --\n@@ -33,2 +33,3 @@\n-\t\tif x < 10 { //@ loc(multipleCtrl, re`(?s)if.x.*return...next1....`), loc(multipleCtrlNotAllSelected, re`(?s)if.x.*break....`)\n-\t\t\tcontinue\n+\t\tshouldReturn, ctrl := newFunction(x)\n+\t\tif shouldReturn {\n+\t\t\treturn\n@@ -36 +37,4 @@\n-\t\tif x > 2 {\n+\t\tswitch ctrl {\n+\t\tcase 1:\n+\t\t\tcontinue\n+\t\tcase 2:\n@@ -39,3 +43 @@\n-\t\tif x == 1 {\n-\t\t\treturn //next1\n-\t\t}\n@@ -45 +46,14 @@\n+func newFunction(x int) (bool, int) {\n+\tif x < 10 { //@ loc(multipleCtrl, re`(?s)if.x.*return...next1....`), loc(multipleCtrlNotAllSelected, re`(?s)if.x.*break....`)\n+\t\treturn false, 1\n+\t}\n+\tif x > 2 {\n+\t\treturn false, 2\n+\t}\n+\tif x == 1 {\n+\t\treturn true, //next1\n+\t\t0\n+\t}\n+\treturn false, 0\n+}\n+\n-- @freeControl5/freecontrol.go --\n@@ -33 +33,3 @@\n-\t\tif x < 10 { //@ loc(multipleCtrl, re`(?s)if.x.*return...next1....`), loc(multipleCtrlNotAllSelected, re`(?s)if.x.*break....`)\n+\t\tctrl := newFunction(x)\n+\t\tswitch ctrl {\n+\t\tcase 1:\n@@ -35,2 +37 @@\n-\t\t}\n-\t\tif x > 2 {\n+\t\tcase 2:\n@@ -45 +46,10 @@\n+func newFunction(x int) int {\n+\tif x < 10 { //@ loc(multipleCtrl, re`(?s)if.x.*return...next1....`), loc(multipleCtrlNotAllSelected, re`(?s)if.x.*break....`)\n+\t\treturn 1\n+\t}\n+\tif x > 2 {\n+\t\treturn 2\n+\t}\n+\treturn 0\n+}\n+\n-- @freeControl6/freecontrol.go --\n@@ -48,2 +48,4 @@\n-\t\tif x < 10 { //@ loc(ctrlVarExists, re`(?s)if.x.*continue...next2....`)\n-\t\t\tcontinue //next2\n+\t\tctrl1 := newFunction(x)\n+\t\tswitch ctrl1 {\n+\t\tcase 1:\n+\t\t\tcontinue\n@@ -54 +56,7 @@\n+func newFunction(x int) int {\n+\tif x < 10 { //@ loc(ctrlVarExists, re`(?s)if.x.*continue...next2....`)\n+\t\treturn 1 //next2\n+\t}\n+\treturn 0\n+}\n+\n-- @freeControl7/freecontrol.go --\n@@ -57,2 +57,3 @@\n-\t\tif x < 10 { //@ loc(twoReturns, re`(?s)if.x.*return.1....`)\n-\t\t\treturn 0\n+\t\ti, shouldReturn, ctrl := newFunction(x)\n+\t\tif shouldReturn {\n+\t\t\treturn i\n@@ -60,2 +61,2 @@\n-\t\ttest := x - 4\n-\t\tif test > 2 {\n+\t\tswitch ctrl {\n+\t\tcase 1:\n@@ -64,3 +65 @@\n-\t\tif test == 10 {\n-\t\t\treturn 1\n-\t\t}\n@@ -79 +77,14 @@\n+\n+func newFunction(x int) (int, bool, int) {\n+\tif x < 10 { //@ loc(twoReturns, re`(?s)if.x.*return.1....`)\n+\t\treturn 0, true, 0\n+\t}\n+\ttest := x - 4\n+\tif test > 2 {\n+\t\treturn 0, false, 1\n+\t}\n+\tif test == 10 {\n+\t\treturn 1, true, 0\n+\t}\n+\treturn 0, false, 0\n+}\n-- @freeControl8/freecontrol.go --\n@@ -68,5 +68,3 @@\n-\t\tfor range \"def\" { //@ loc(forWithLabel, re`(?s)for.*outer.........`)\n-\t\t\tif x < 2 {\n-\t\t\t\tcontinue\n-\t\t\t}\n-\t\t\tif x > 10 {\n+\t\tctrl := newFunction(x)\n+\t\tswitch ctrl {\n+\t\tcase 1:\n@@ -74 +72 @@\n-\t\t\t}\n@@ -79 +76,12 @@\n+\n+func newFunction(x int) int {\n+\tfor range \"def\" { //@ loc(forWithLabel, re`(?s)for.*outer.........`)\n+\t\tif x < 2 {\n+\t\t\tcontinue\n+\t\t}\n+\t\tif x > 10 {\n+\t\t\treturn 1\n+\t\t}\n+\t}\n+\treturn 0\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_control_label.txt",
    "content": "This test verifies the behavior of extract function when the extracted block contains:\n- At least one free branch statement\n- A labeled branch statement and its label, where the corresponding LabeledStmt\nmay or may not be an EmptyStmt.\nSee golang/go#77157\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n\n-- extractwithlabel.go --\npackage extract\n\n//@codeaction(extractWithLabelAndStmt, \"refactor.extract.function\", edit=labelAndStmt)\n//@codeaction(extractWithLabelOnly, \"refactor.extract.function\", edit=labelOnly)\n\nfunc FuncGoTo(a int) {\n\tfor range \"abc\" {\n        if a > 5 { //@ loc(extractWithLabelAndStmt, re`(?s)if.*println.1.`), loc(extractWithLabelOnly, re`(?s)if.*label1:`)\n            continue\n        }\n\t\tif a == 10 {\n\t\t\tgoto label1\n\t\t}\n\tlabel1:\n\t\tprintln(1)\n\t}\n}\n\n-- @labelAndStmt/extractwithlabel.go --\n@@ -8 +8,3 @@\n-        if a > 5 { //@ loc(extractWithLabelAndStmt, re`(?s)if.*println.1.`), loc(extractWithLabelOnly, re`(?s)if.*label1:`)\n+        ctrl := newFunction(a)\n+        switch ctrl {\n+        case 1:\n@@ -11,5 +13 @@\n-\t\tif a == 10 {\n-\t\t\tgoto label1\n-\t\t}\n-\tlabel1:\n-\t\tprintln(1)\n@@ -19 +16,12 @@\n+func newFunction(a int) int {\n+\tif a > 5 { //@ loc(extractWithLabelAndStmt, re`(?s)if.*println.1.`), loc(extractWithLabelOnly, re`(?s)if.*label1:`)\n+\t\treturn 1\n+\t}\n+\tif a == 10 {\n+\t\tgoto label1\n+\t}\n+label1:\n+\tprintln(1)\n+\treturn 0\n+}\n+\n-- @labelOnly/extractwithlabel.go --\n@@ -8 +8,3 @@\n-        if a > 5 { //@ loc(extractWithLabelAndStmt, re`(?s)if.*println.1.`), loc(extractWithLabelOnly, re`(?s)if.*label1:`)\n+        ctrl := newFunction(a)\n+        switch ctrl {\n+        case 1:\n@@ -11,4 +13 @@\n-\t\tif a == 10 {\n-\t\t\tgoto label1\n-\t\t}\n-\tlabel1:\n@@ -19 +17,12 @@\n+func newFunction(a int) int {\n+\tif a > 5 { //@ loc(extractWithLabelAndStmt, re`(?s)if.*println.1.`), loc(extractWithLabelOnly, re`(?s)if.*label1:`)\n+\t\treturn 1\n+\t}\n+\tif a == 10 {\n+\t\tgoto label1\n+\t}\n+label1:\n+\t;\n+\treturn 0\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_method.txt",
    "content": "This test exercises function and method extraction.\n\n-- flags --\n-ignore_extra_diags\n\n-- basic.go --\npackage extract\n\n//@codeaction(A_XLessThanYP, \"refactor.extract.method\", edit=meth1)\n//@codeaction(A_XLessThanYP, \"refactor.extract.function\", edit=func1)\n//@codeaction(A_AddP1, \"refactor.extract.method\", edit=meth2)\n//@codeaction(A_AddP1, \"refactor.extract.function\", edit=func2)\n//@codeaction(A_AddP2, \"refactor.extract.method\", edit=meth3)\n//@codeaction(A_AddP2, \"refactor.extract.function\", edit=func3)\n//@codeaction(A_XLessThanY, \"refactor.extract.method\", edit=meth4)\n//@codeaction(A_XLessThanY, \"refactor.extract.function\", edit=func4)\n//@codeaction(A_Add1, \"refactor.extract.method\", edit=meth5)\n//@codeaction(A_Add1, \"refactor.extract.function\", edit=func5)\n//@codeaction(A_Add2, \"refactor.extract.method\", edit=meth6)\n//@codeaction(A_Add2, \"refactor.extract.function\", edit=func6)\n\ntype A struct {\n\tx int\n\ty int\n}\n\nfunc (a *A) XLessThanYP() bool {\n\treturn a.x < a.y //@loc(A_XLessThanYP, re`return.*a\\.y`)\n}\n\nfunc (a *A) AddP() int {\n\tsum := a.x + a.y //@loc(A_AddP1, re`sum.*a\\.y`)\n\treturn sum       //@loc(A_AddP2, re`return.*?sum`)\n}\n\nfunc (a A) XLessThanY() bool {\n\treturn a.x < a.y //@loc(A_XLessThanY, re`return.*a\\.y`)\n}\n\nfunc (a A) Add() int {\n\tsum := a.x + a.y //@loc(A_Add1, re`sum.*a\\.y`)\n\treturn sum       //@loc(A_Add2, re`return.*?sum`)\n}\n\n-- @func1/basic.go --\n@@ -22 +22 @@\n-\treturn a.x < a.y //@loc(A_XLessThanYP, re`return.*a\\.y`)\n+\treturn newFunction(a) //@loc(A_XLessThanYP, re`return.*a\\.y`)\n@@ -25 +25,4 @@\n+func newFunction(a *A) bool {\n+\treturn a.x < a.y\n+}\n+\n-- @func2/basic.go --\n@@ -26 +26 @@\n-\tsum := a.x + a.y //@loc(A_AddP1, re`sum.*a\\.y`)\n+\tsum := newFunction(a) //@loc(A_AddP1, re`sum.*a\\.y`)\n@@ -30 +30,5 @@\n+func newFunction(a *A) int {\n+\tsum := a.x + a.y\n+\treturn sum\n+}\n+\n-- @func3/basic.go --\n@@ -27 +27 @@\n-\treturn sum       //@loc(A_AddP2, re`return.*?sum`)\n+\treturn newFunction(sum)       //@loc(A_AddP2, re`return.*?sum`)\n@@ -30 +30,4 @@\n+func newFunction(sum int) int {\n+\treturn sum\n+}\n+\n-- @func4/basic.go --\n@@ -31 +31 @@\n-\treturn a.x < a.y //@loc(A_XLessThanY, re`return.*a\\.y`)\n+\treturn newFunction(a) //@loc(A_XLessThanY, re`return.*a\\.y`)\n@@ -34 +34,4 @@\n+func newFunction(a A) bool {\n+\treturn a.x < a.y\n+}\n+\n-- @func5/basic.go --\n@@ -35 +35 @@\n-\tsum := a.x + a.y //@loc(A_Add1, re`sum.*a\\.y`)\n+\tsum := newFunction(a) //@loc(A_Add1, re`sum.*a\\.y`)\n@@ -39 +39,5 @@\n+func newFunction(a A) int {\n+\tsum := a.x + a.y\n+\treturn sum\n+}\n+\n-- @func6/basic.go --\n@@ -36 +36 @@\n-\treturn sum       //@loc(A_Add2, re`return.*?sum`)\n+\treturn newFunction(sum)       //@loc(A_Add2, re`return.*?sum`)\n@@ -39 +39,4 @@\n+func newFunction(sum int) int {\n+\treturn sum\n+}\n+\n-- @meth1/basic.go --\n@@ -22 +22 @@\n-\treturn a.x < a.y //@loc(A_XLessThanYP, re`return.*a\\.y`)\n+\treturn a.newMethod() //@loc(A_XLessThanYP, re`return.*a\\.y`)\n@@ -25 +25,4 @@\n+func (a *A) newMethod() bool {\n+\treturn a.x < a.y\n+}\n+\n-- @meth2/basic.go --\n@@ -26 +26 @@\n-\tsum := a.x + a.y //@loc(A_AddP1, re`sum.*a\\.y`)\n+\tsum := a.newMethod() //@loc(A_AddP1, re`sum.*a\\.y`)\n@@ -30 +30,5 @@\n+func (a *A) newMethod() int {\n+\tsum := a.x + a.y\n+\treturn sum\n+}\n+\n-- @meth3/basic.go --\n@@ -27 +27 @@\n-\treturn sum       //@loc(A_AddP2, re`return.*?sum`)\n+\treturn a.newMethod(sum)       //@loc(A_AddP2, re`return.*?sum`)\n@@ -30 +30,4 @@\n+func (*A) newMethod(sum int) int {\n+\treturn sum\n+}\n+\n-- @meth4/basic.go --\n@@ -31 +31 @@\n-\treturn a.x < a.y //@loc(A_XLessThanY, re`return.*a\\.y`)\n+\treturn a.newMethod() //@loc(A_XLessThanY, re`return.*a\\.y`)\n@@ -34 +34,4 @@\n+func (a A) newMethod() bool {\n+\treturn a.x < a.y\n+}\n+\n-- @meth5/basic.go --\n@@ -35 +35 @@\n-\tsum := a.x + a.y //@loc(A_Add1, re`sum.*a\\.y`)\n+\tsum := a.newMethod() //@loc(A_Add1, re`sum.*a\\.y`)\n@@ -39 +39,5 @@\n+func (a A) newMethod() int {\n+\tsum := a.x + a.y\n+\treturn sum\n+}\n+\n-- @meth6/basic.go --\n@@ -36 +36 @@\n-\treturn sum       //@loc(A_Add2, re`return.*?sum`)\n+\treturn a.newMethod(sum)       //@loc(A_Add2, re`return.*?sum`)\n@@ -39 +39,4 @@\n+func (A) newMethod(sum int) int {\n+\treturn sum\n+}\n+\n-- context.go --\npackage extract\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\n//@codeaction(B_AddP, \"refactor.extract.method\", edit=contextMeth1)\n//@codeaction(B_AddP, \"refactor.extract.function\", edit=contextFunc1)\n//@codeaction(B_LongList, \"refactor.extract.method\", edit=contextMeth2)\n//@codeaction(B_LongList, \"refactor.extract.function\", edit=contextFunc2)\n//@codeaction(B_AddPWithB, \"refactor.extract.function\", edit=contextFuncB)\n//@codeaction(B_LongListWithT, \"refactor.extract.function\", edit=contextFuncT)\n\ntype B struct {\n\tx int\n\ty int\n}\n\t\nfunc (b *B) AddP(ctx context.Context) (int, error) {\n\tsum := b.x + b.y\n\treturn sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\\.Err\\(\\)`)\n}\n\nfunc (b *B) LongList(ctx context.Context) (int, error) {\n\tp1 := 1\n\tp2 := 1\n\tp3 := 1\n\treturn p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\\.Err\\(\\)`)\n}\n\nfunc (b *B) AddPWithB(ctx context.Context, tB *testing.B) (int, error) {\n\tsum := b.x + b.y //@loc(B_AddPWithB, re`(?s:^.*?Err\\(\\))`)\n\ttB.Skip()\n\treturn sum, ctx.Err()\n}\n\nfunc (b *B) LongListWithT(ctx context.Context, t *testing.T) (int, error) {\n\tp1 := 1\n\tp2 := 1\n\tp3 := 1\n\tp4 := p1 + p2 //@loc(B_LongListWithT, re`(?s:^.*?Err\\(\\))`)\n\tt.Skip()\n\treturn p4 + p3, ctx.Err()\n}\n-- @contextMeth1/context.go --\n@@ -22 +22 @@\n-\treturn sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\\.Err\\(\\)`)\n+\treturn b.newMethod(ctx, sum) //@loc(B_AddP, re`return.*ctx\\.Err\\(\\)`)\n@@ -25 +25,4 @@\n+func (*B) newMethod(ctx context.Context, sum int) (int, error) {\n+\treturn sum, ctx.Err()\n+}\n+\n-- @contextMeth2/context.go --\n@@ -29 +29 @@\n-\treturn p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\\.Err\\(\\)`)\n+\treturn b.newMethod(ctx, p1, p2, p3) //@loc(B_LongList, re`return.*ctx\\.Err\\(\\)`)\n@@ -32 +32,4 @@\n+func (*B) newMethod(ctx context.Context, p1 int, p2 int, p3 int) (int, error) {\n+\treturn p1 + p2 + p3, ctx.Err()\n+}\n+\n-- @contextFunc2/context.go --\n@@ -29 +29 @@\n-\treturn p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\\.Err\\(\\)`)\n+\treturn newFunction(ctx, p1, p2, p3) //@loc(B_LongList, re`return.*ctx\\.Err\\(\\)`)\n@@ -32 +32,4 @@\n+func newFunction(ctx context.Context, p1 int, p2 int, p3 int) (int, error) {\n+\treturn p1 + p2 + p3, ctx.Err()\n+}\n+\n-- @contextFunc1/context.go --\n@@ -22 +22 @@\n-\treturn sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\\.Err\\(\\)`)\n+\treturn newFunction(ctx, sum) //@loc(B_AddP, re`return.*ctx\\.Err\\(\\)`)\n@@ -25 +25,4 @@\n+func newFunction(ctx context.Context, sum int) (int, error) {\n+\treturn sum, ctx.Err()\n+}\n+\n-- @contextFuncB/context.go --\n@@ -33 +33,4 @@\n+\treturn newFunction(ctx, tB, b)\n+}\n+\n+func newFunction(ctx context.Context, tB *testing.B, b *B) (int, error) {\n-- @contextFuncT/context.go --\n@@ -42 +42,4 @@\n+\treturn newFunction(ctx, t, p1, p2, p3)\n+}\n+\n+func newFunction(ctx context.Context, t *testing.T, p1 int, p2 int, p3 int) (int, error) {\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_return_err.txt",
    "content": "This test verifies various behaviors of function extraction when every return statement in the extracted block is an error handling return.\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- errhandling.go --\npackage err_handling\nimport (\n    \"encoding/json\"\n    \"fmt\"\n)\n\n//@codeaction(errHandlingBlk1, \"refactor.extract.function\", edit=err_handling_1)\n//@codeaction(errHandlingBlk2, \"refactor.extract.function\", edit=err_handling_2)\n//@codeaction(errHandlingBlk3, \"refactor.extract.function\", edit=err_handling_3)\n//@codeaction(errHandlingBlk4, \"refactor.extract.function\", edit=err_handling_4)\n//@codeaction(errHandlingBlk5, \"refactor.extract.function\", edit=err_handling_5)\n\nfunc Func() error {\n\ta, err := json.Marshal(0) //@loc(errHandlingBlk1, re`(?s)a.*err1....`)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"1: %w\", err)\n\t}\n\tb, err1 := json.Marshal(0)\n\tif err1 != nil {\n\t\treturn fmt.Errorf(\"2: %w\", err1)\n\t}\n\tfmt.Println(string(a), string(b))\n\treturn nil\n}\n\nfunc FuncReturnsInt() (int, error) {\n\ta, err := json.Marshal(0) //@loc(errHandlingBlk2, re`(?s)a.*err2....`)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"1: %w\", err)\n\t}\n\tb, err2 := json.Marshal(0)\n\tif err2 != nil {\n\t\treturn 1, fmt.Errorf(\"2: %w\", err2)\n\t}\n\tfmt.Println(string(a), string(b))\n\treturn 3, nil\n}\n\nfunc FuncHasNilReturns() error {\n\tif _, err := json.Marshal(0); err != nil { //@loc(errHandlingBlk3, re`(?s)if.*return.nil`)\n\t\treturn err\n\t}\n\tif _, err := json.Marshal(1); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc FuncHasOtherReturns() ([]byte, error) {\n\tif a, err := json.Marshal(0); err != nil { //@loc(errHandlingBlk4, re`(?s)if.*Marshal.1.`)\n\t\treturn a, err\n\t}\n\treturn json.Marshal(1)\n}\n\nfunc FuncErrNameAlreadyExists(err error) ([]byte, error) {\n\tif a, err := json.Marshal(0); err != nil { //@loc(errHandlingBlk5, re`(?s)if.*a,.err...`)\n\t\treturn a, err\n\t}\n\tif a, err := json.Marshal(3); err != nil {\n\t\treturn a, err\n\t}\n\treturn []byte{}, nil\n}\n\n-- @err_handling_1/errhandling.go --\n@@ -14 +14,9 @@\n+\ta, b, err := newFunction()\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tfmt.Println(string(a), string(b))\n+\treturn nil\n+}\n+\n+func newFunction() ([]byte, []byte, error) {\n@@ -16 +25 @@\n-\t\treturn fmt.Errorf(\"1: %w\", err)\n+\t\treturn nil, nil, fmt.Errorf(\"1: %w\", err)\n@@ -20 +29 @@\n-\t\treturn fmt.Errorf(\"2: %w\", err1)\n+\t\treturn nil, nil, fmt.Errorf(\"2: %w\", err1)\n@@ -22,2 +31 @@\n-\tfmt.Println(string(a), string(b))\n-\treturn nil\n+\treturn a, b, nil\n-- @err_handling_2/errhandling.go --\n@@ -27 +27,9 @@\n+\ta, b, i, err := newFunction()\n+\tif err != nil {\n+\t\treturn i, err\n+\t}\n+\tfmt.Println(string(a), string(b))\n+\treturn 3, nil\n+}\n+\n+func newFunction() ([]byte, []byte, int, error) {\n@@ -29 +38 @@\n-\t\treturn 0, fmt.Errorf(\"1: %w\", err)\n+\t\treturn nil, nil, 0, fmt.Errorf(\"1: %w\", err)\n@@ -33 +42 @@\n-\t\treturn 1, fmt.Errorf(\"2: %w\", err2)\n+\t\treturn nil, nil, 1, fmt.Errorf(\"2: %w\", err2)\n@@ -35,2 +44 @@\n-\tfmt.Println(string(a), string(b))\n-\treturn 3, nil\n+\treturn a, b, 0, nil\n-- @err_handling_3/errhandling.go --\n@@ -40 +40,4 @@\n+\treturn newFunction()\n+}\n+\n+func newFunction() error {\n-- @err_handling_4/errhandling.go --\n@@ -50 +50,4 @@\n+\treturn newFunction()\n+}\n+\n+func newFunction() ([]byte, error) {\n-- @err_handling_5/errhandling.go --\n@@ -57 +57,8 @@\n+\tresult, err1 := newFunction()\n+\tif err1 != nil {\n+\t\treturn result, err1\n+\t}\n+\treturn []byte{}, nil\n+}\n+\n+func newFunction() ([]byte, error) {\n@@ -63 +71 @@\n-\treturn []byte{}, nil\n+\treturn nil, nil\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable-67905.txt",
    "content": "This test verifies the fix for golang/go#67905: Extract variable from type\nswitch produces invalid code\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- extract_switch.go --\npackage extract\n\nimport (\n\t\"io\"\n)\n\nfunc f() io.Reader\n\nfunc main() {\n\tswitch r := f().(type) { //@codeaction(\"f()\", \"refactor.extract.variable\", edit=type_switch_func_call)\n\tdefault:\n\t\t_ = r\n\t}\n}\n\n-- @type_switch_func_call/extract_switch.go --\n@@ -10 +10,2 @@\n-\tswitch r := f().(type) { //@codeaction(\"f()\", \"refactor.extract.variable\", edit=type_switch_func_call)\n+\tnewVar := f()\n+\tswitch r := newVar.(type) { //@codeaction(\"f()\", \"refactor.extract.variable\", edit=type_switch_func_call)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable-70563.txt",
    "content": "This test verifies the fix for golang/go#70563: refactor.extract.variable\ninserts new statement before the scope of its free symbols.\n\n-- flags --\n-ignore_extra_diags\n\n-- inside_else.go --\npackage extract\n\nfunc _() {\n\tif x := 1; true {\n\n\t} else if y := x + 1; true { //@codeaction(\"x + 1\", \"refactor.extract.variable\", err=re\"else-if's init has free variable\")\n\n\t}\n}\n-- inside_case.go --\npackage extract\n\nfunc _() {\n\tswitch x := 1; x {\n\tcase x + 1: //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"switch's init has free variable\")\n\t\ty := x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"switch's init has free variable\")\n\t\t_ = y\n\tcase 3:\n\t\ty := x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"switch's init has free variable\")\n\t\t_ = y\n\t}\n}\n-- parent_if.go --\npackage extract\n\nfunc _() {\n\tif x := 1; x > 0 {\n\t\ty = x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"if-statement's init has free variable\")\n\t} else {\n\t\ty = x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"if-statement's init has free variable\")\n\t}\n}\n-- parent_switch.go --\npackage extract\n\nfunc _() {\n\tswitch x := 1; x {\n\tcase 1:\n\t\ty = x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"switch's init has free variable\")\n\tcase 3:\n\t\ty = x + 1 //@codeaction(\"x + 1\", \"refactor.extract.variable-all\", err=re\"switch's init has free variable\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable-if.txt",
    "content": "This test checks the behavior of the 'extract variable/constant' code actions\nwhen the optimal place for the new declaration is within the \"if\" statement,\nlike so:\n\n   if x := 1 + 2 or y + y ; true {\n   } else if x > 0 {\n   }\n\nA future refactor.variable implementation that does this should avoid\nusing a 'const' declaration, which is not legal at that location.\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage a\n\nfunc constant() {\n\tif true {\n\t} else if 1 + 2 > 0 { //@ codeaction(\"1 + 2\", \"refactor.extract.constant\", edit=constant)\n\t}\n}\n\nfunc variable(y int) {\n\tif true {\n\t} else if y + y > 0 { //@ codeaction(\"y + y\", \"refactor.extract.variable\", edit=variable)\n\t}\n}\n\n-- @constant/a.go --\n@@ -4 +4 @@\n+\tconst newConst = 1 + 2\n@@ -5 +6 @@\n-\t} else if 1 + 2 > 0 { //@ codeaction(\"1 + 2\", \"refactor.extract.constant\", edit=constant)\n+\t} else if newConst > 0 { //@ codeaction(\"1 + 2\", \"refactor.extract.constant\", edit=constant)\n-- @variable/a.go --\n@@ -10 +10 @@\n+\tnewVar := y + y\n@@ -11 +12 @@\n-\t} else if y + y > 0 { //@ codeaction(\"y + y\", \"refactor.extract.variable\", edit=variable)\n+\t} else if newVar > 0 { //@ codeaction(\"y + y\", \"refactor.extract.variable\", edit=variable)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable-inexact.txt",
    "content": "This test checks that extract variable/constant permits:\n- extraneous whitespace in the selection\n- function literals\n- pointer dereference expressions\n- parenthesized expressions\n\n-- a.go --\npackage a\n\nfunc _(ptr *int) {\n\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2 \", \"refactor.extract.constant\", edit=spaces)\n\tvar _ = func() {} //@codeaction(\"func() {}\", \"refactor.extract.variable\", edit=funclit)\n\tvar _ = *ptr      //@codeaction(\"*ptr\", \"refactor.extract.variable\", edit=ptr)\n\tvar _ = (ptr)     //@codeaction(\"(ptr)\", \"refactor.extract.variable\", edit=paren)\n}\n\n-- @spaces/a.go --\n@@ -4 +4,2 @@\n-\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2 \", \"refactor.extract.constant\", edit=spaces)\n+\tconst newConst = 1 + 2\n+\tvar _ = newConst + 3 //@codeaction(\"1 + 2 \", \"refactor.extract.constant\", edit=spaces)\n-- @funclit/a.go --\n@@ -5 +5,2 @@\n-\tvar _ = func() {} //@codeaction(\"func() {}\", \"refactor.extract.variable\", edit=funclit)\n+\tnewVar := func() {}\n+\tvar _ = newVar //@codeaction(\"func() {}\", \"refactor.extract.variable\", edit=funclit)\n-- @ptr/a.go --\n@@ -6 +6,2 @@\n-\tvar _ = *ptr      //@codeaction(\"*ptr\", \"refactor.extract.variable\", edit=ptr)\n+\tnewVar := *ptr\n+\tvar _ = newVar      //@codeaction(\"*ptr\", \"refactor.extract.variable\", edit=ptr)\n-- @paren/a.go --\n@@ -7 +7,2 @@\n-\tvar _ = (ptr)     //@codeaction(\"(ptr)\", \"refactor.extract.variable\", edit=paren)\n+\tnewVar := (ptr)\n+\tvar _ = newVar     //@codeaction(\"(ptr)\", \"refactor.extract.variable\", edit=paren)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable-toplevel.txt",
    "content": "This test checks the behavior of the 'extract variable/constant' code action\nat top level (outside any function). See issue #70665.\n\n-- a.go --\npackage a\n\nconst Length = len(\"hello\") + 2 //@codeaction(`len(\"hello\")`, \"refactor.extract.constant\", edit=lenhello)\n\nvar Slice = append([]int{}, 1, 2, 3) //@codeaction(\"[]int{}\", \"refactor.extract.variable\", edit=sliceliteral)\n\ntype SHA256 [32]byte //@codeaction(\"32\", \"refactor.extract.constant\", edit=arraylen)\n\nfunc F([2]int) {} //@codeaction(\"2\", \"refactor.extract.constant\", edit=paramtypearraylen)\n\n-- @lenhello/a.go --\n@@ -3 +3,2 @@\n-const Length = len(\"hello\") + 2 //@codeaction(`len(\"hello\")`, \"refactor.extract.constant\", edit=lenhello)\n+const newConst = len(\"hello\")\n+const Length = newConst + 2 //@codeaction(`len(\"hello\")`, \"refactor.extract.constant\", edit=lenhello)\n-- @sliceliteral/a.go --\n@@ -5 +5,2 @@\n-var Slice = append([]int{}, 1, 2, 3) //@codeaction(\"[]int{}\", \"refactor.extract.variable\", edit=sliceliteral)\n+var newVar = []int{}\n+var Slice = append(newVar, 1, 2, 3) //@codeaction(\"[]int{}\", \"refactor.extract.variable\", edit=sliceliteral)\n-- @arraylen/a.go --\n@@ -7 +7,2 @@\n-type SHA256 [32]byte //@codeaction(\"32\", \"refactor.extract.constant\", edit=arraylen)\n+const newConst = 32\n+type SHA256 [newConst]byte //@codeaction(\"32\", \"refactor.extract.constant\", edit=arraylen)\n-- @paramtypearraylen/a.go --\n@@ -9 +9,2 @@\n-func F([2]int) {} //@codeaction(\"2\", \"refactor.extract.constant\", edit=paramtypearraylen)\n+const newConst = 2\n+func F([newConst]int) {} //@codeaction(\"2\", \"refactor.extract.constant\", edit=paramtypearraylen)\n-- b/b.go --\npackage b\n\n// Check that package- and file-level name collisions are avoided.\n\nimport newVar3 \"errors\"\n\nvar newVar, newVar1, newVar2 any // these names are taken already\nvar _ = newVar3.New(\"\")\nvar a, b int\nvar C = a + b //@codeaction(\"a + b\", \"refactor.extract.variable\", edit=fresh)\n\n-- @fresh/b/b.go --\n@@ -10 +10,2 @@\n-var C = a + b //@codeaction(\"a + b\", \"refactor.extract.variable\", edit=fresh)\n+var newVar4 = a + b\n+var C = newVar4 //@codeaction(\"a + b\", \"refactor.extract.variable\", edit=fresh)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable.txt",
    "content": "This test checks the behavior of the 'extract variable/constant' code action.\nSee extract_variable_resolve.txt for the same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- basic_lit.go --\npackage extract\n\nfunc _() {\n\tvar _ = 1 + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n\tvar _ = 3 + 4 //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n}\n\n-- @basic_lit1/basic_lit.go --\n@@ -4 +4,2 @@\n-\tvar _ = 1 + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n+\tconst newConst = 1\n+\tvar _ = newConst + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n-- @basic_lit2/basic_lit.go --\n@@ -5 +5,2 @@\n-\tvar _ = 3 + 4 //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n+\tconst newConst = 3 + 4\n+\tvar _ = newConst //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n-- func_call.go --\npackage extract\n\nimport \"strconv\"\n\nfunc _() {\n\tx0 := append([]int{}, 1) //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n\tstr := \"1\"\n\tb, err := strconv.Atoi(str) //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n}\n\n-- @func_call1/func_call.go --\n@@ -6 +6,2 @@\n-\tx0 := append([]int{}, 1) //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n+\tnewVar := append([]int{}, 1)\n+\tx0 := newVar //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n-- @func_call2/func_call.go --\n@@ -8 +8,2 @@\n-\tb, err := strconv.Atoi(str) //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n+\tnewVar, newVar1 := strconv.Atoi(str)\n+\tb, err := newVar, newVar1 //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n-- scope.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tx0 := 0\n\tif true {\n\t\ty := ast.CompositeLit{} //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n\t}\n\tif true {\n\t\tx := !false //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n\t}\n}\n\n-- @scope1/scope.go --\n@@ -8 +8,2 @@\n-\t\ty := ast.CompositeLit{} //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n+\t\tnewVar := ast.CompositeLit{}\n+\t\ty := newVar //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n-- @scope2/scope.go --\n@@ -11 +11,2 @@\n-\t\tx := !false //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n+\t\tconst newConst = !false\n+\t\tx := newConst //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable_all.txt",
    "content": "This test checks the behavior of the 'replace all occurrences of expression' code action, with resolve support.\nSee extract_variable_all_resolve.txt for the same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- basic_lit.go --\npackage extract_all\n\nfunc _() {\n\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n}\n-- @basic_lit/basic_lit.go --\n@@ -4,2 +4,3 @@\n-\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n-\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n+\tconst newConst = 1 + 2\n+\tvar _ = newConst + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n+\tvar _ = newConst + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n-- nested_scope.go --\npackage extract_all\n\nfunc _() {\n\tnewConst1 := 0\n\tif true {\n\t\tx := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n\t}\n\tif true {\n\t\tnewConst := 0\n\t\tif false {\n\t\t\ty := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n\t\t}\n\t}\n\tz := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n}\n-- @nested_scope/nested_scope.go --\n@@ -5 +5 @@\n+\tconst newConst2 = 1 + 2 + 3\n@@ -6 +7 @@\n-\t\tx := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\t\tx := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n@@ -11 +12 @@\n-\t\t\ty := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\t\t\ty := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n@@ -14 +15 @@\n-\tz := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\tz := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n-- function_call.go --\npackage extract_all\n\nimport \"fmt\"\n\nfunc _() {\n\tresult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n\tif result != \"\" {\n\t\tanotherResult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n\t\t_ = anotherResult\n\t}\n}\n-- @replace_func_call/function_call.go --\n@@ -6 +6,2 @@\n-\tresult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n+\tnewVar := fmt.Sprintf(\"%d\", 42)\n+\tresult := newVar //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n@@ -8 +9 @@\n-\t\tanotherResult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n+\t\tanotherResult := newVar //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n-- composite_literals.go --\npackage extract_all\n\nfunc _() {\n\tdata := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n\tprocessData(data)\n\tmoreData := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n\tprocessData(moreData)\n}\n\nfunc processData(d []int) {}\n-- @composite/composite_literals.go --\n@@ -4 +4,2 @@\n-\tdata := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n+\tnewVar := []int{1, 2, 3}\n+\tdata := newVar //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n@@ -6 +7 @@\n-\tmoreData := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n+\tmoreData := newVar //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n-- selector.go --\npackage extract_all\n\ntype MyStruct struct {\n\tValue int\n}\n\nfunc _() {\n\ts := MyStruct{Value: 10}\n\tv := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n\tif v > 0 {\n\t\tw := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n\t\t_ = w\n\t}\n}\n-- @sel/selector.go --\n@@ -9 +9,2 @@\n-\tv := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n+\tnewVar := s.Value\n+\tv := newVar //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n@@ -11 +12 @@\n-\t\tw := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n+\t\tw := newVar //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n-- index.go --\npackage extract_all\n\nfunc _() {\n\tarr := []int{1, 2, 3}\n\tval := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n\tval2 := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n}\n-- @index/index.go --\n@@ -5,2 +5,3 @@\n-\tval := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n-\tval2 := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n+\tnewVar := arr[0]\n+\tval := newVar //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n+\tval2 := newVar //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n-- slice_expr.go --\npackage extract_all\n\nfunc _() {\n\tdata := []int{1, 2, 3, 4, 5}\n\tpart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n\tanotherPart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n}\n-- @slice/slice_expr.go --\n@@ -5,2 +5,3 @@\n-\tpart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n-\tanotherPart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n+\tnewVar := data[1:3]\n+\tpart := newVar //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n+\tanotherPart := newVar //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n-- nested_func.go --\npackage extract_all\n\nfunc outer() {\n\tinner := func() {\n\t\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n\t\t_ = val\n\t}\n\tinner()\n\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n\t_ = val\n}\n-- @nested/nested_func.go --\n@@ -4 +4 @@\n+\tconst newConst = 100 + 200\n@@ -5 +6 @@\n-\t\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n+\t\tval := newConst //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n@@ -9 +10 @@\n-\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n+\tval := newConst //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n-- switch.go --\npackage extract_all\n\nfunc _() {\n\tvalue := 2\n\tswitch value {\n\tcase 1:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\tcase 2:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\tdefault:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\t}\n}\n-- @switch/switch.go --\n@@ -5 +5 @@\n+\tnewVar := value * 10\n@@ -7 +8 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n@@ -10 +11 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n@@ -13 +14 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n-- switch_single.go --\npackage extract_all\n\nfunc _() {\n\tvalue := 2\n\tswitch value {\n\tcase 1:\n\t\tresult := value * 10\n\t\t_ = result\n\tcase 2:\n\t\tresult := value * 10\n\t\t_ = result\n\tdefault:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n\t\t_ = result\n\t}\n}\n-- @switch_single/switch_single.go --\n@@ -13 +13,2 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n+\t\tnewVar := value * 10\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n-- func_list.go --\npackage extract_all\n\nfunc _() {\n\tx := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket1, edit=func_list)\n\t\tb := 1\n\t\treturn b + a\n\t} //@loc(closeBracket1, \"}\")\n\ty := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket2, edit=func_list)\n\t\tb := 1\n\t\treturn b + a\n\t}//@loc(closeBracket2, \"}\")\n}\n-- @func_list/func_list.go --\n@@ -4 +4 @@\n-\tx := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket1, edit=func_list)\n+\tnewVar := func(a int) int {\n@@ -7,5 +7,3 @@\n-\t} //@loc(closeBracket1, \"}\")\n-\ty := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket2, edit=func_list)\n-\t\tb := 1\n-\t\treturn b + a\n-\t}//@loc(closeBracket2, \"}\")\n+\t}\n+\tx := newVar //@loc(closeBracket1, \"}\")\n+\ty := newVar//@loc(closeBracket2, \"}\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable_all_resolve.txt",
    "content": "This test checks the behavior of the 'replace all occurrences of expression' code action, with resolve support.\nSee extract_variable_all.txt for the same test without resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": true,\n\t\t\t\"resolveSupport\": {\n\t\t\t\t\"properties\": [\"edit\"]\n\t\t\t}\n\t\t}\n\t}\n}\n-- flags --\n-ignore_extra_diags\n\n-- basic_lit.go --\npackage extract_all\n\nfunc _() {\n\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n}\n-- @basic_lit/basic_lit.go --\n@@ -4,2 +4,3 @@\n-\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n-\tvar _ = 1 + 2 + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n+\tconst newConst = 1 + 2\n+\tvar _ = newConst + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n+\tvar _ = newConst + 3 //@codeaction(\"1 + 2\", \"refactor.extract.constant-all\", edit=basic_lit)\n-- nested_scope.go --\npackage extract_all\n\nfunc _() {\n\tnewConst1 := 0\n\tif true {\n\t\tx := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n\t}\n\tif true {\n\t\tnewConst := 0\n\t\tif false {\n\t\t\ty := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n\t\t}\n\t}\n\tz := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n}\n-- @nested_scope/nested_scope.go --\n@@ -5 +5 @@\n+\tconst newConst2 = 1 + 2 + 3\n@@ -6 +7 @@\n-\t\tx := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\t\tx := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n@@ -11 +12 @@\n-\t\t\ty := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\t\t\ty := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n@@ -14 +15 @@\n-\tz := 1 + 2 + 3 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n+\tz := newConst2 //@codeaction(\"1 + 2 + 3\", \"refactor.extract.constant-all\", edit=nested_scope)\n-- function_call.go --\npackage extract_all\n\nimport \"fmt\"\n\nfunc _() {\n\tresult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n\tif result != \"\" {\n\t\tanotherResult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n\t\t_ = anotherResult\n\t}\n}\n-- @replace_func_call/function_call.go --\n@@ -6 +6,2 @@\n-\tresult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n+\tnewVar := fmt.Sprintf(\"%d\", 42)\n+\tresult := newVar //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n@@ -8 +9 @@\n-\t\tanotherResult := fmt.Sprintf(\"%d\", 42) //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n+\t\tanotherResult := newVar //@codeaction(`fmt.Sprintf(\"%d\", 42)`, \"refactor.extract.variable-all\", edit=replace_func_call)\n-- composite_literals.go --\npackage extract_all\n\nfunc _() {\n\tdata := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n\tprocessData(data)\n\tmoreData := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n\tprocessData(moreData)\n}\n\nfunc processData(d []int) {}\n-- @composite/composite_literals.go --\n@@ -4 +4,2 @@\n-\tdata := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n+\tnewVar := []int{1, 2, 3}\n+\tdata := newVar //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n@@ -6 +7 @@\n-\tmoreData := []int{1, 2, 3} //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n+\tmoreData := newVar //@codeaction(\"[]int{1, 2, 3}\", \"refactor.extract.variable-all\", edit=composite)\n-- selector.go --\npackage extract_all\n\ntype MyStruct struct {\n\tValue int\n}\n\nfunc _() {\n\ts := MyStruct{Value: 10}\n\tv := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n\tif v > 0 {\n\t\tw := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n\t\t_ = w\n\t}\n}\n-- @sel/selector.go --\n@@ -9 +9,2 @@\n-\tv := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n+\tnewVar := s.Value\n+\tv := newVar //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n@@ -11 +12 @@\n-\t\tw := s.Value //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n+\t\tw := newVar //@codeaction(\"s.Value\", \"refactor.extract.variable-all\", edit=sel)\n-- index.go --\npackage extract_all\n\nfunc _() {\n\tarr := []int{1, 2, 3}\n\tval := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n\tval2 := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n}\n-- @index/index.go --\n@@ -5,2 +5,3 @@\n-\tval := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n-\tval2 := arr[0] //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n+\tnewVar := arr[0]\n+\tval := newVar //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n+\tval2 := newVar //@codeaction(\"arr[0]\", \"refactor.extract.variable-all\", edit=index)\n-- slice_expr.go --\npackage extract_all\n\nfunc _() {\n\tdata := []int{1, 2, 3, 4, 5}\n\tpart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n\tanotherPart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n}\n-- @slice/slice_expr.go --\n@@ -5,2 +5,3 @@\n-\tpart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n-\tanotherPart := data[1:3] //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n+\tnewVar := data[1:3]\n+\tpart := newVar //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n+\tanotherPart := newVar //@codeaction(\"data[1:3]\", \"refactor.extract.variable-all\", edit=slice)\n-- nested_func.go --\npackage extract_all\n\nfunc outer() {\n\tinner := func() {\n\t\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n\t\t_ = val\n\t}\n\tinner()\n\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n\t_ = val\n}\n-- @nested/nested_func.go --\n@@ -4 +4 @@\n+\tconst newConst = 100 + 200\n@@ -5 +6 @@\n-\t\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n+\t\tval := newConst //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n@@ -9 +10 @@\n-\tval := 100 + 200 //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n+\tval := newConst //@codeaction(\"100 + 200\", \"refactor.extract.constant-all\", edit=nested)\n-- switch.go --\npackage extract_all\n\nfunc _() {\n\tvalue := 2\n\tswitch value {\n\tcase 1:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\tcase 2:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\tdefault:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n\t\t_ = result\n\t}\n}\n-- @switch/switch.go --\n@@ -5 +5 @@\n+\tnewVar := value * 10\n@@ -7 +8 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n@@ -10 +11 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n@@ -13 +14 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable-all\", edit=switch)\n-- switch_single.go --\npackage extract_all\n\nfunc _() {\n\tvalue := 2\n\tswitch value {\n\tcase 1:\n\t\tresult := value * 10\n\t\t_ = result\n\tcase 2:\n\t\tresult := value * 10\n\t\t_ = result\n\tdefault:\n\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n\t\t_ = result\n\t}\n}\n-- @switch_single/switch_single.go --\n@@ -13 +13,2 @@\n-\t\tresult := value * 10 //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n+\t\tnewVar := value * 10\n+\t\tresult := newVar //@codeaction(\"value * 10\", \"refactor.extract.variable\", edit=switch_single)\n-- func_list.go --\npackage extract_all\n\nfunc _() {\n\tx := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket1, edit=func_list)\n\t\tb := 1\n\t\treturn b + a\n\t} //@loc(closeBracket1, \"}\")\n\ty := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket2, edit=func_list)\n\t\tb := 1\n\t\treturn b + a\n\t}//@loc(closeBracket2, \"}\")\n}\n-- @func_list/func_list.go --\n@@ -4 +4 @@\n-\tx := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket1, edit=func_list)\n+\tnewVar := func(a int) int {\n@@ -7,5 +7,3 @@\n-\t} //@loc(closeBracket1, \"}\")\n-\ty := func(a int) int { //@codeaction(\"func\", \"refactor.extract.variable-all\", end=closeBracket2, edit=func_list)\n-\t\tb := 1\n-\t\treturn b + a\n-\t}//@loc(closeBracket2, \"}\")\n+\t}\n+\tx := newVar //@loc(closeBracket1, \"}\")\n+\ty := newVar//@loc(closeBracket2, \"}\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extract_variable_resolve.txt",
    "content": "This test checks the behavior of the 'extract variable/constant' code action, with resolve support.\nSee extract_variable.txt for the same test without resolve support.\n\n-- flags --\n-ignore_extra_diags\n\n-- basic_lit.go --\npackage extract\n\nfunc _() {\n\tvar _ = 1 + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n\tvar _ = 3 + 4 //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n}\n\n-- @basic_lit1/basic_lit.go --\n@@ -4 +4,2 @@\n-\tvar _ = 1 + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n+\tconst newConst = 1\n+\tvar _ = newConst + 2 //@codeaction(\"1\", \"refactor.extract.constant\", edit=basic_lit1)\n-- @basic_lit2/basic_lit.go --\n@@ -5 +5,2 @@\n-\tvar _ = 3 + 4 //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n+\tconst newConst = 3 + 4\n+\tvar _ = newConst //@codeaction(\"3 + 4\", \"refactor.extract.constant\", edit=basic_lit2)\n-- func_call.go --\npackage extract\n\nimport \"strconv\"\n\nfunc _() {\n\tx0 := append([]int{}, 1) //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n\tstr := \"1\"\n\tb, err := strconv.Atoi(str) //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n}\n\n-- @func_call1/func_call.go --\n@@ -6 +6,2 @@\n-\tx0 := append([]int{}, 1) //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n+\tnewVar := append([]int{}, 1)\n+\tx0 := newVar //@codeaction(\"append([]int{}, 1)\", \"refactor.extract.variable\", edit=func_call1)\n-- @func_call2/func_call.go --\n@@ -8 +8,2 @@\n-\tb, err := strconv.Atoi(str) //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n+\tnewVar, newVar1 := strconv.Atoi(str)\n+\tb, err := newVar, newVar1 //@codeaction(\"strconv.Atoi(str)\", \"refactor.extract.variable\", edit=func_call2)\n-- scope.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tx0 := 0\n\tif true {\n\t\ty := ast.CompositeLit{} //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n\t}\n\tif true {\n\t\tx := !false //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n\t}\n}\n\n-- @scope1/scope.go --\n@@ -8 +8,2 @@\n-\t\ty := ast.CompositeLit{} //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n+\t\tnewVar := ast.CompositeLit{}\n+\t\ty := newVar //@codeaction(\"ast.CompositeLit{}\", \"refactor.extract.variable\", edit=scope1)\n-- @scope2/scope.go --\n@@ -11 +11,2 @@\n-\t\tx := !false //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n+\t\tconst newConst = !false\n+\t\tx := newConst //@codeaction(\"!false\", \"refactor.extract.constant\", edit=scope2)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/extracttofile.txt",
    "content": "This test checks the behavior of the 'extract to a new file' code action.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/extracttofile\n\ngo 1.18\n\n-- a.go --\npackage main\n\n// docs\nfunc fn() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=function_declaration)\n\nfunc fn2() {} //@codeaction(\"fn2\", \"refactor.extract.toNewFile\", edit=only_select_func_name)\n\nfunc fn3() {} //@codeaction(re`()fn3`, \"refactor.extract.toNewFile\", edit=zero_width_selection_on_func_name)\n\n// docs\ntype T int //@codeaction(\"type\", \"refactor.extract.toNewFile\", edit=type_declaration)\n\n// docs\nvar V int //@codeaction(\"var\", \"refactor.extract.toNewFile\", edit=var_declaration)\n\n// docs\nconst K = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration)\n\nconst ( //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration_multiple_specs)\n    P = iota\n    Q\n    R\n)\n\nfunc fnA () {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", end=mdEnd, result=multiple_declarations)\n\n// unattached comment\n\nfunc fnB () {} //@loc(mdEnd, \"}\")\n\n-- @const_declaration_multiple_specs/p.go --\n@@ -0,0 +1,7 @@\n+package main\n+\n+const ( //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration_multiple_specs)\n+\tP = iota\n+\tQ\n+\tR\n+)\n-- @multiple_declarations/fna.go --\npackage main\n\nfunc fnA() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", end=mdEnd, result=multiple_declarations)\n\n// unattached comment\n\nfunc fnB() {}\n-- @multiple_declarations/a.go --\npackage main\n\n// docs\nfunc fn() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=function_declaration)\n\nfunc fn2() {} //@codeaction(\"fn2\", \"refactor.extract.toNewFile\", edit=only_select_func_name)\n\nfunc fn3() {} //@codeaction(re`()fn3`, \"refactor.extract.toNewFile\", edit=zero_width_selection_on_func_name)\n\n// docs\ntype T int //@codeaction(\"type\", \"refactor.extract.toNewFile\", edit=type_declaration)\n\n// docs\nvar V int //@codeaction(\"var\", \"refactor.extract.toNewFile\", edit=var_declaration)\n\n// docs\nconst K = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration)\n\nconst ( //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration_multiple_specs)\n    P = iota\n    Q\n    R\n)\n\n//@loc(mdEnd, \"}\")\n\n-- @const_declaration_multiple_specs/a.go --\n@@ -19,6 +19 @@\n-const ( //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration_multiple_specs)\n-    P = iota\n-    Q\n-    R\n-)\n-\n-- existing.go --\n-- existing2.go --\n-- existing2.1.go --\n-- b.go --\npackage main\nfunc existing() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict)\nfunc existing2() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict_again)\n\n-- single_import.go --\npackage main\nimport \"fmt\"\nfunc F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=single_import)\n    fmt.Println()\n}\n\n-- multiple_imports.go --\npackage main\nimport (\n    \"fmt\"\n    \"log\"\n    time1 \"time\"\n)\nfunc init(){\n    log.Println()\n}\nfunc F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=multiple_imports)\n    fmt.Println()\n}\nfunc g() string{ //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=renamed_import)\n    return time1.Now().string()\n}\n\n-- blank_import.go --\npackage main\nimport _ \"fmt\"\nfunc F() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=blank_import)\n\n\n\n-- @blank_import/blank_import.go --\n@@ -3 +3 @@\n-func F() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=blank_import)\n+//@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=blank_import)\n-- @blank_import/f.go --\n@@ -0,0 +1,3 @@\n+package main\n+\n+func F() {}\n-- @const_declaration/a.go --\n@@ -16,2 +16 @@\n-// docs\n-const K = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration)\n+//@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=const_declaration)\n-- @const_declaration/k.go --\n@@ -0,0 +1,4 @@\n+package main\n+\n+// docs\n+const K = \"\"\n-- @file_name_conflict/b.go --\n@@ -2 +2 @@\n-func existing() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict)\n+//@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict)\n-- @file_name_conflict/existing.1.go --\n@@ -0,0 +1,3 @@\n+package main\n+\n+func existing() {}\n-- @file_name_conflict_again/b.go --\n@@ -3 +3 @@\n-func existing2() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict_again)\n+//@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=file_name_conflict_again)\n-- @file_name_conflict_again/existing2.2.go --\n@@ -0,0 +1,3 @@\n+package main\n+\n+func existing2() {}\n-- @function_declaration/a.go --\n@@ -3,2 +3 @@\n-// docs\n-func fn() {} //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=function_declaration)\n+//@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=function_declaration)\n-- @function_declaration/fn.go --\n@@ -0,0 +1,4 @@\n+package main\n+\n+// docs\n+func fn() {}\n-- @multiple_imports/f.go --\n@@ -0,0 +1,9 @@\n+package main\n+\n+import (\n+\t\"fmt\"\n+)\n+\n+func F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=multiple_imports)\n+\tfmt.Println()\n+}\n-- @multiple_imports/multiple_imports.go --\n@@ -3 +3 @@\n-    \"fmt\"\n+    \n@@ -10,3 +10 @@\n-func F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=multiple_imports)\n-    fmt.Println()\n-}\n-- @only_select_func_name/a.go --\n@@ -6 +6 @@\n-func fn2() {} //@codeaction(\"fn2\", \"refactor.extract.toNewFile\", edit=only_select_func_name)\n+//@codeaction(\"fn2\", \"refactor.extract.toNewFile\", edit=only_select_func_name)\n-- @only_select_func_name/fn2.go --\n@@ -0,0 +1,3 @@\n+package main\n+\n+func fn2() {}\n-- @single_import/f.go --\n@@ -0,0 +1,9 @@\n+package main\n+\n+import (\n+\t\"fmt\"\n+)\n+\n+func F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=single_import)\n+\tfmt.Println()\n+}\n-- @single_import/single_import.go --\n@@ -2,4 +2 @@\n-import \"fmt\"\n-func F() { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=single_import)\n-    fmt.Println()\n-}\n-- @type_declaration/a.go --\n@@ -10,2 +10 @@\n-// docs\n-type T int //@codeaction(\"type\", \"refactor.extract.toNewFile\", edit=type_declaration)\n+//@codeaction(\"type\", \"refactor.extract.toNewFile\", edit=type_declaration)\n-- @type_declaration/t.go --\n@@ -0,0 +1,4 @@\n+package main\n+\n+// docs\n+type T int\n-- @var_declaration/a.go --\n@@ -13,2 +13 @@\n-// docs\n-var V int //@codeaction(\"var\", \"refactor.extract.toNewFile\", edit=var_declaration)\n+//@codeaction(\"var\", \"refactor.extract.toNewFile\", edit=var_declaration)\n-- @var_declaration/v.go --\n@@ -0,0 +1,4 @@\n+package main\n+\n+// docs\n+var V int\n-- @zero_width_selection_on_func_name/a.go --\n@@ -8 +8 @@\n-func fn3() {} //@codeaction(re`()fn3`, \"refactor.extract.toNewFile\", edit=zero_width_selection_on_func_name)\n+//@codeaction(re`()fn3`, \"refactor.extract.toNewFile\", edit=zero_width_selection_on_func_name)\n-- @zero_width_selection_on_func_name/fn3.go --\n@@ -0,0 +1,3 @@\n+package main\n+\n+func fn3() {}\n-- @renamed_import/g.go --\n@@ -0,0 +1,9 @@\n+package main\n+\n+import (\n+\ttime1 \"time\"\n+)\n+\n+func g() string { //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=renamed_import)\n+\treturn time1.Now().string()\n+}\n-- @renamed_import/multiple_imports.go --\n@@ -5 +5 @@\n-    time1 \"time\"\n+    \n@@ -13,4 +13 @@\n-func g() string{ //@codeaction(\"func\", \"refactor.extract.toNewFile\", edit=renamed_import)\n-    return time1.Now().string()\n-}\n-\n-- copyright.go --\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\n// docs\nconst C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyright)\n\n-- @copyright/c.go --\n@@ -0,0 +1,8 @@\n+// Copyright 2020 The Go Authors. All rights reserved.\n+// Use of this source code is governed by a BSD-style\n+// license that can be found in the LICENSE file.\n+\n+package main\n+\n+// docs\n+const C = \"\"\n-- @copyright/copyright.go --\n@@ -7,2 +7 @@\n-// docs\n-const C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyright)\n+//@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyright)\n-- buildconstraint.go --\n//go:build go1.18\n\npackage main\n\n// docs\nconst C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=buildconstraint)\n\n-- @buildconstraint/buildconstraint.go --\n@@ -5,2 +5 @@\n-// docs\n-const C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=buildconstraint)\n+//@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=buildconstraint)\n-- @buildconstraint/c.go --\n@@ -0,0 +1,6 @@\n+//go:build go1.18\n+\n+package main\n+\n+// docs\n+const C = \"\"\n-- copyrightandbuildconstraint.go --\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.18\n\npackage main\n\n// docs\nconst C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyrightandbuildconstraint)\n-- @copyrightandbuildconstraint/c.go --\n@@ -0,0 +1,10 @@\n+// Copyright 2020 The Go Authors. All rights reserved.\n+// Use of this source code is governed by a BSD-style\n+// license that can be found in the LICENSE file.\n+\n+//go:build go1.18\n+\n+package main\n+\n+// docs\n+const C = \"\"\n-- @copyrightandbuildconstraint/copyrightandbuildconstraint.go --\n@@ -9,2 +9 @@\n-// docs\n-const C = \"\" //@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyrightandbuildconstraint)\n+//@codeaction(\"const\", \"refactor.extract.toNewFile\", edit=copyrightandbuildconstraint)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/failedresolve.txt",
    "content": "This test checks that failing to produce edits doesn't fail the\ncodeAction/resolve operation. Instead, we simply return the action\nwith its command, and let the action fail when its command is applied\n(golang/go#75442).\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/failedresolve\n\ngo 1.18\n\n-- resolve.go --\npackage extract\n\nfunc _() {\n\tif x := 1; true {\n\n\t} else if y := x + 1; true { //@codeaction(\"x + 1\", \"refactor.extract.variable\", action=act)\n\n\t}\n}\n\n-- apply.go --\npackage extract\n\nfunc _() {\n\tif x := 1; true {\n\n\t} else if y := x + 1; true { //@codeaction(\"x + 1\", \"refactor.extract.variable\", err=re\"cannot find location to insert\")\n\n\t}\n}\n\n-- @act --\n{\n\t\"title\": \"Extract variable\",\n\t\"kind\": \"refactor.extract.variable\",\n\t\"command\": {\n\t\t\"title\": \"Extract variable\",\n\t\t\"command\": \"gopls.apply_fix\",\n\t\t\"arguments\": [\n\t\t\t{\n\t\t\t\t\"Fix\": \"extract_variable\",\n\t\t\t\t\"Location\": {\n\t\t\t\t\t\"uri\": \"$WORKDIR/resolve.go\",\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"start\": {\n\t\t\t\t\t\t\t\"line\": 5,\n\t\t\t\t\t\t\t\"character\": 16\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"end\": {\n\t\t\t\t\t\t\t\"line\": 5,\n\t\t\t\t\t\t\t\"character\": 21\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"ResolveEdits\": true\n\t\t\t}\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/fill_struct.txt",
    "content": "This test checks the behavior of the 'fill struct' code action.\nSee fill_struct_resolve.txt for same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/fillstruct\n\ngo 1.18\n\n-- data/data.go --\npackage data\n\ntype B struct {\n\tExportedInt   int\n\tunexportedInt int\n}\n\n-- a.go --\npackage fillstruct\n\nimport (\n\t\"golang.org/lsptests/fillstruct/data\"\n)\n\ntype basicStruct struct {\n\tfoo int\n}\n\nvar _ = basicStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n\ntype twoArgStruct struct {\n\tfoo int\n\tbar string\n}\n\nvar _ = twoArgStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n\ntype nestedStruct struct {\n\tbar   string\n\tbasic basicStruct\n}\n\nvar _ = nestedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n\nvar _ = data.B{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n-- @a1/a.go --\n@@ -11 +11,3 @@\n-var _ = basicStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n+var _ = basicStruct{\n+\tfoo: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n-- @a2/a.go --\n@@ -18 +18,4 @@\n-var _ = twoArgStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n+var _ = twoArgStruct{\n+\tfoo: 0,\n+\tbar: \"\",\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n-- @a3/a.go --\n@@ -25 +25,4 @@\n-var _ = nestedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n+var _ = nestedStruct{\n+\tbar:   \"\",\n+\tbasic: basicStruct{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n-- @a4/a.go --\n@@ -27 +27,3 @@\n-var _ = data.B{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n+var _ = data.B{\n+\tExportedInt: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n-- a2.go --\npackage fillstruct\n\ntype typedStruct struct {\n\tm  map[string]int\n\ts  []int\n\tc  chan int\n\tc1 <-chan int\n\ta  [2]string\n}\n\nvar _ = typedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n\ntype funStruct struct {\n\tfn func(i int) int\n}\n\nvar _ = funStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n\ntype funStructComplex struct {\n\tfn func(i int, s string) (string, int)\n}\n\nvar _ = funStructComplex{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n\ntype funStructEmpty struct {\n\tfn func()\n}\n\nvar _ = funStructEmpty{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n\n-- @a21/a2.go --\n@@ -11 +11,7 @@\n-var _ = typedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n+var _ = typedStruct{\n+\tm:  map[string]int{},\n+\ts:  []int{},\n+\tc:  make(chan int),\n+\tc1: make(<-chan int),\n+\ta:  [2]string{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n-- @a22/a2.go --\n@@ -17 +17,5 @@\n-var _ = funStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n+var _ = funStruct{\n+\tfn: func(i int) int {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n-- @a23/a2.go --\n@@ -23 +23,5 @@\n-var _ = funStructComplex{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n+var _ = funStructComplex{\n+\tfn: func(i int, s string) (string, int) {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n-- @a24/a2.go --\n@@ -29 +29,5 @@\n-var _ = funStructEmpty{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n+var _ = funStructEmpty{\n+\tfn: func() {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n-- a3.go --\npackage fillstruct\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n)\n\ntype Foo struct {\n\tA int\n}\n\ntype Bar struct {\n\tX *Foo\n\tY *Foo\n}\n\nvar _ = Bar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n\ntype importedStruct struct {\n\tm  map[*ast.CompositeLit]ast.Field\n\ts  []ast.BadExpr\n\ta  [3]token.Token\n\tc  chan ast.EmptyStmt\n\tfn func(ast_decl ast.DeclStmt) ast.Ellipsis\n\tst ast.CompositeLit\n}\n\nvar _ = importedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n\ntype pointerBuiltinStruct struct {\n\tb *bool\n\ts *string\n\ti *int\n}\n\nvar _ = pointerBuiltinStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n\nvar _ = []ast.UnaryExpr{\n\t{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n}\n\nvar _ = []ast.UnaryExpr{{}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n-- @a31/a3.go --\n@@ -17 +17,4 @@\n-var _ = Bar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n+var _ = Bar{\n+\tX: &Foo{},\n+\tY: &Foo{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n-- @a32/a3.go --\n@@ -28 +28,10 @@\n-var _ = importedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n+var _ = importedStruct{\n+\tm: map[*ast.CompositeLit]ast.Field{},\n+\ts: []ast.BadExpr{},\n+\ta: [3]token.Token{},\n+\tc: make(chan ast.EmptyStmt),\n+\tfn: func(ast_decl ast.DeclStmt) ast.Ellipsis {\n+\t\tpanic(\"TODO\")\n+\t},\n+\tst: ast.CompositeLit{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n-- @a33/a3.go --\n@@ -36 +36,5 @@\n-var _ = pointerBuiltinStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n+var _ = pointerBuiltinStruct{\n+\tb: new(bool),\n+\ts: new(string),\n+\ti: new(int),\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n-- @a34/a3.go --\n@@ -39 +39,5 @@\n-\t{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n+\t{\n+\t\tOpPos: 0,\n+\t\tOp:    0,\n+\t\tX:     nil,\n+\t}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n-- @a35/a3.go --\n@@ -42 +42,5 @@\n-var _ = []ast.UnaryExpr{{}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n+var _ = []ast.UnaryExpr{{\n+\tOpPos: 0,\n+\tOp:    0,\n+\tX:     nil,\n+}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n-- a4.go --\npackage fillstruct\n\nimport \"go/ast\"\n\ntype iStruct struct {\n\tX int\n}\n\ntype sStruct struct {\n\tstr string\n}\n\ntype multiFill struct {\n\tnum   int\n\tstrin string\n\tarr   []int\n}\n\ntype assignStruct struct {\n\tn ast.Node\n}\n\nfunc fill() {\n\tvar x int\n\tvar _ = iStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n\n\tvar s string\n\tvar _ = sStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n\n\tvar n int\n\t_ = []int{}\n\tif true {\n\t\tarr := []int{1, 2}\n\t}\n\tvar _ = multiFill{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n\n\tvar node *ast.CompositeLit\n\tvar _ = assignStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n}\n\n-- @a41/a4.go --\n@@ -25 +25,3 @@\n-\tvar _ = iStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n+\tvar _ = iStruct{\n+\t\tX: x,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n-- @a42/a4.go --\n@@ -28 +28,3 @@\n-\tvar _ = sStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n+\tvar _ = sStruct{\n+\t\tstr: s,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n-- @a43/a4.go --\n@@ -35 +35,5 @@\n-\tvar _ = multiFill{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n+\tvar _ = multiFill{\n+\t\tnum:   n,\n+\t\tstrin: s,\n+\t\tarr:   []int{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n-- @a45/a4.go --\n@@ -38 +38,3 @@\n-\tvar _ = assignStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n+\tvar _ = assignStruct{\n+\t\tn: node,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n-- fillStruct.go --\npackage fillstruct\n\ntype StructB struct{}\n\ntype StructA struct {\n\tunexportedIntField int\n\tExportedIntField   int\n\tMapA               map[int]string\n\tArray              []int\n\tStructB\n}\n\ntype StructA2 struct {\n\tB *StructB\n}\n\ntype StructA3 struct {\n\tB StructB\n}\n\nfunc fill() {\n\ta := StructA{}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n\tb := StructA2{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n\tc := StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n\tif true {\n\t\t_ = StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n\t}\n}\n\n-- @fillStruct1/fillStruct.go --\n@@ -22 +22,7 @@\n-\ta := StructA{}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n+\ta := StructA{\n+\t\tunexportedIntField: 0,\n+\t\tExportedIntField:   0,\n+\t\tMapA:               map[int]string{},\n+\t\tArray:              []int{},\n+\t\tStructB:            StructB{},\n+\t}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n-- @fillStruct2/fillStruct.go --\n@@ -23 +23,3 @@\n-\tb := StructA2{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n+\tb := StructA2{\n+\t\tB: &StructB{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n-- @fillStruct3/fillStruct.go --\n@@ -24 +24,3 @@\n-\tc := StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n+\tc := StructA3{\n+\t\tB: StructB{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n-- @fillStruct4/fillStruct.go --\n@@ -26 +26,3 @@\n-\t\t_ = StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n+\t\t_ = StructA3{\n+\t\t\tB: StructB{},\n+\t\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n-- fillStruct_anon.go --\npackage fillstruct\n\ntype StructAnon struct {\n\ta struct{}\n\tb map[string]any\n\tc map[string]struct {\n\t\td int\n\t\te bool\n\t}\n}\n\nfunc fill() {\n\t_ := StructAnon{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n}\n-- @fillStruct_anon/fillStruct_anon.go --\n@@ -13 +13,8 @@\n-\t_ := StructAnon{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n+\t_ := StructAnon{\n+\t\ta: struct{}{},\n+\t\tb: map[string]any{},\n+\t\tc: map[string]struct {\n+\t\t\td int\n+\t\t\te bool\n+\t\t}{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n-- fillStruct_nested.go --\npackage fillstruct\n\ntype StructB struct {\n\tStructC\n}\n\ntype StructC struct {\n\tunexportedInt int\n}\n\nfunc nested() {\n\tc := StructB{\n\t\tStructC: StructC{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n\t}\n}\n\n-- @fill_nested/fillStruct_nested.go --\n@@ -13 +13,3 @@\n-\t\tStructC: StructC{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n+\t\tStructC: StructC{\n+\t\t\tunexportedInt: 0,\n+\t\t}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n-- fillStruct_package.go --\npackage fillstruct\n\nimport (\n\th2 \"net/http\"\n\n\t\"golang.org/lsptests/fillstruct/data\"\n)\n\nfunc unexported() {\n\ta := data.B{}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n\t_ = h2.Client{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n}\n-- @fillStruct_package1/fillStruct_package.go --\n@@ -10 +10,3 @@\n-\ta := data.B{}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n+\ta := data.B{\n+\t\tExportedInt: 0,\n+\t}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n-- @fillStruct_package2/fillStruct_package.go --\n@@ -11 +11,8 @@\n-\t_ = h2.Client{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n+\t_ = h2.Client{\n+\t\tTransport: nil,\n+\t\tCheckRedirect: func(req *h2.Request, via []*h2.Request) error {\n+\t\t\tpanic(\"TODO\")\n+\t\t},\n+\t\tJar:     nil,\n+\t\tTimeout: 0,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n-- fillStruct_partial.go --\npackage fillstruct\n\ntype StructPartialA struct {\n\tPrefilledInt int\n\tUnfilledInt  int\n\tStructPartialB\n}\n\ntype StructPartialB struct {\n\tPrefilledInt int\n\tUnfilledInt  int\n}\n\nfunc fill() {\n\ta := StructPartialA{\n\t\tPrefilledInt: 5,\n\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_partial1)\n\tb := StructPartialB{\n\t\t/* this comment should disappear */\n\t\tPrefilledInt: 7, // This comment should be blown away.\n\t\t/* As should\n\t\tthis one */\n\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_partial2)\n}\n\n-- @fillStruct_partial1/fillStruct_partial.go --\n@@ -16 +16,3 @@\n-\t\tPrefilledInt: 5,\n+\t\tPrefilledInt:   5,\n+\t\tUnfilledInt:    0,\n+\t\tStructPartialB: StructPartialB{},\n-- @fillStruct_partial2/fillStruct_partial.go --\n@@ -23 +23 @@\n+\t\tUnfilledInt: 0,\n-- fillStruct_spaces.go --\npackage fillstruct\n\ntype StructD struct {\n\tExportedIntField int\n}\n\nfunc spaces() {\n\td := StructD{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n}\n\n-- @fillStruct_spaces/fillStruct_spaces.go --\n@@ -8 +8,3 @@\n-\td := StructD{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n+\td := StructD{\n+\t\tExportedIntField: 0,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n-- fillStruct_unsafe.go --\npackage fillstruct\n\nimport \"unsafe\"\n\ntype unsafeStruct struct {\n\tx int\n\tp unsafe.Pointer\n}\n\nfunc fill() {\n\t_ := unsafeStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n}\n\n-- @fillStruct_unsafe/fillStruct_unsafe.go --\n@@ -11 +11,4 @@\n-\t_ := unsafeStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n+\t_ := unsafeStruct{\n+\t\tx: 0,\n+\t\tp: nil,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n-- typeparams.go --\npackage fillstruct\n\ntype emptyStructWithTypeParams[A any] struct{}\n\nvar _ = emptyStructWithTypeParams[int]{} // no suggested fix\n\ntype basicStructWithTypeParams[T any] struct {\n\tfoo T\n}\n\nvar _ = basicStructWithTypeParams[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n\ntype twoArgStructWithTypeParams[F, B any] struct {\n\tfoo F\n\tbar B\n}\n\nvar _ = twoArgStructWithTypeParams[string, int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n\nvar _ = twoArgStructWithTypeParams[int, string]{\n\tbar: \"bar\",\n} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams3)\n\ntype nestedStructWithTypeParams struct {\n\tbar   string\n\tbasic basicStructWithTypeParams[int]\n}\n\nvar _ = nestedStructWithTypeParams{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n\nfunc _[T any]() {\n\ttype S struct{ t T }\n\t_ = S{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n\n\ttype P struct{ t *T }\n\t_ = P{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n\n\ttype Alias[u any] = struct {\n\t\tx u\n\t\ty *T\n\t}\n\t_ = Alias[string]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n\n\ttype Named[u any] struct {\n\t\tx u\n\t\ty T\n\t}\n\t_ = Named[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n}\n-- @typeparams1/typeparams.go --\n@@ -11 +11,3 @@\n-var _ = basicStructWithTypeParams[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n+var _ = basicStructWithTypeParams[int]{\n+\tfoo: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n-- @typeparams2/typeparams.go --\n@@ -18 +18,4 @@\n-var _ = twoArgStructWithTypeParams[string, int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n+var _ = twoArgStructWithTypeParams[string, int]{\n+\tfoo: \"\",\n+\tbar: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n-- @typeparams3/typeparams.go --\n@@ -22 +22 @@\n+\tfoo: 0,\n-- @typeparams4/typeparams.go --\n@@ -29 +29,4 @@\n-var _ = nestedStructWithTypeParams{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n+var _ = nestedStructWithTypeParams{\n+\tbar:   \"\",\n+\tbasic: basicStructWithTypeParams[int]{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n-- @typeparams5/typeparams.go --\n@@ -33 +33,3 @@\n-\t_ = S{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n+\t_ = S{\n+\t\tt: *new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n-- @typeparams6/typeparams.go --\n@@ -36 +36,3 @@\n-\t_ = P{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n+\t_ = P{\n+\t\tt: new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n-- @typeparams7/typeparams.go --\n@@ -42 +42,4 @@\n-\t_ = Alias[string]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n+\t_ = Alias[string]{\n+\t\tx: \"\",\n+\t\ty: new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n-- @typeparams8/typeparams.go --\n@@ -48 +48,4 @@\n-\t_ = Named[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n+\t_ = Named[int]{\n+\t\tx: 0,\n+\t\ty: *new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n-- issue63921.go --\npackage fillstruct\n\n// Test for golang/go#63921: fillstruct panicked with invalid fields.\ntype invalidStruct struct {\n  F int\n  Undefined\n}\n\nfunc _() {\n  // Note: the golden content for issue63921 is empty: fillstruct produces no\n  // edits, but does not panic.\n  invalidStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=issue63921)\n}\n-- named/named.go --\npackage named\n\ntype foo struct {}\ntype aliasFoo = foo\n\nfunc _() {\n\ttype namedInt int\n\ttype namedString string\n\ttype namedBool bool\n\ttype namedPointer *foo\n\ttype namedSlice []foo\n\ttype namedInterface interface{ Error() string }\n\ttype namedChan chan int\n\ttype namedMap map[string]foo\n\ttype namedSignature func(string) string\n\ttype namedStruct struct{}\n\ttype namedArray [3]foo\n\ttype namedAlias aliasFoo\n\n\ttype bar struct {\n\t\tnamedInt namedInt\n\t\tnamedString namedString\n\t\tnamedBool namedBool\n\t\tnamedPointer namedPointer\n\t\tnamedSlice namedSlice\n\t\tnamedInterface namedInterface\n\t\tnamedChan namedChan\n\t\tnamedMap namedMap\n\t\tnamedSignature namedSignature\n\t\tnamedStruct namedStruct\n\t\tnamedArray namedArray\n\t\tnamedAlias namedAlias\n\t}\n\n\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n}\n-- @named/named/named.go --\n@@ -35 +35,14 @@\n-\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n+\tbar{\n+\t\tnamedInt:       0,\n+\t\tnamedString:    \"\",\n+\t\tnamedBool:      false,\n+\t\tnamedPointer:   nil,\n+\t\tnamedSlice:     namedSlice{},\n+\t\tnamedInterface: nil,\n+\t\tnamedChan:      nil,\n+\t\tnamedMap:       namedMap{},\n+\t\tnamedSignature: nil,\n+\t\tnamedStruct:    namedStruct{},\n+\t\tnamedArray:     namedArray{},\n+\t\tnamedAlias:     namedAlias{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n-- alias/alias.go --\npackage alias\n\ntype foo struct {}\ntype aliasFoo = foo\n\nfunc _() {\n\ttype aliasInt = int\n\ttype aliasString = string\n\ttype aliasBool = bool\n\ttype aliasPointer = *foo\n\ttype aliasSlice = []foo\n\ttype aliasInterface = interface{ Error() string }\n\ttype aliasChan = chan int\n\ttype aliasMap = map[string]foo\n\ttype aliasSignature = func(string) string\n\ttype aliasStruct = struct{ bar string }\n\ttype aliasArray = [3]foo\n\ttype aliasNamed = foo\n\n\ttype bar struct {\n\t\taliasInt aliasInt\n\t\taliasString aliasString\n\t\taliasBool aliasBool\n\t\taliasPointer aliasPointer\n\t\taliasSlice aliasSlice\n\t\taliasInterface aliasInterface\n\t\taliasChan aliasChan\n\t\taliasMap aliasMap\n\t\taliasSignature aliasSignature\n\t\taliasStruct aliasStruct\n\t\taliasArray aliasArray\n\t\taliasNamed aliasNamed\n\t}\n\n\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n}\n-- @alias/alias/alias.go --\n@@ -35 +35,14 @@\n-\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n+\tbar{\n+\t\taliasInt:       0,\n+\t\taliasString:    \"\",\n+\t\taliasBool:      false,\n+\t\taliasPointer:   nil,\n+\t\taliasSlice:     aliasSlice{},\n+\t\taliasInterface: nil,\n+\t\taliasChan:      nil,\n+\t\taliasMap:       aliasMap{},\n+\t\taliasSignature: nil,\n+\t\taliasStruct:    aliasStruct{},\n+\t\taliasArray:     aliasArray{},\n+\t\taliasNamed:     aliasNamed{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n-- preserveformat/preserveformat.go --\npackage preserveformat\n\ntype (\n\tNode struct {\n\t\tValue int\n\t}\n\tGraph struct {\n\t\tNodes []*Node `json:\"\"`\n\t\tEdges map[*Node]*Node\n\t\tOther string\n\t}\n)\n\nfunc _() {\n\t_ := &Graph{\n\t\t// comments at the start preserved\n\t\tNodes: []*Node{\n\t\t\t{Value: 0}, // comments in the middle preserved\n\t\t\t// between lines\n\t\t\t{Value: 0},\n\t\t}, // another comment\n\t\t// comment group\n\t\t// below\n\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=preserveformat)\n}\n-- @preserveformat/preserveformat/preserveformat.go --\n@@ -24 +24,2 @@\n+\t\tEdges: map[*Node]*Node{},\n+\t\tOther: \"\",\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/fill_struct_resolve.txt",
    "content": "This test checks the behavior of the 'fill struct' code action, with resolve support.\nSee fill_struct.txt for same test without resolve support.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/fillstruct\n\ngo 1.18\n\n-- data/data.go --\npackage data\n\ntype B struct {\n\tExportedInt   int\n\tunexportedInt int\n}\n\n-- a.go --\npackage fillstruct\n\nimport (\n\t\"golang.org/lsptests/fillstruct/data\"\n)\n\ntype basicStruct struct {\n\tfoo int\n}\n\nvar _ = basicStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n\ntype twoArgStruct struct {\n\tfoo int\n\tbar string\n}\n\nvar _ = twoArgStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n\ntype nestedStruct struct {\n\tbar   string\n\tbasic basicStruct\n}\n\nvar _ = nestedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n\nvar _ = data.B{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n-- @a1/a.go --\n@@ -11 +11,3 @@\n-var _ = basicStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n+var _ = basicStruct{\n+\tfoo: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a1)\n-- @a2/a.go --\n@@ -18 +18,4 @@\n-var _ = twoArgStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n+var _ = twoArgStruct{\n+\tfoo: 0,\n+\tbar: \"\",\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a2)\n-- @a3/a.go --\n@@ -25 +25,4 @@\n-var _ = nestedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n+var _ = nestedStruct{\n+\tbar:   \"\",\n+\tbasic: basicStruct{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a3)\n-- @a4/a.go --\n@@ -27 +27,3 @@\n-var _ = data.B{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n+var _ = data.B{\n+\tExportedInt: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a4)\n-- a2.go --\npackage fillstruct\n\ntype typedStruct struct {\n\tm  map[string]int\n\ts  []int\n\tc  chan int\n\tc1 <-chan int\n\ta  [2]string\n}\n\nvar _ = typedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n\ntype funStruct struct {\n\tfn func(i int) int\n}\n\nvar _ = funStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n\ntype funStructComplex struct {\n\tfn func(i int, s string) (string, int)\n}\n\nvar _ = funStructComplex{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n\ntype funStructEmpty struct {\n\tfn func()\n}\n\nvar _ = funStructEmpty{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n\n-- @a21/a2.go --\n@@ -11 +11,7 @@\n-var _ = typedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n+var _ = typedStruct{\n+\tm:  map[string]int{},\n+\ts:  []int{},\n+\tc:  make(chan int),\n+\tc1: make(<-chan int),\n+\ta:  [2]string{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a21)\n-- @a22/a2.go --\n@@ -17 +17,5 @@\n-var _ = funStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n+var _ = funStruct{\n+\tfn: func(i int) int {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a22)\n-- @a23/a2.go --\n@@ -23 +23,5 @@\n-var _ = funStructComplex{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n+var _ = funStructComplex{\n+\tfn: func(i int, s string) (string, int) {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a23)\n-- @a24/a2.go --\n@@ -29 +29,5 @@\n-var _ = funStructEmpty{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n+var _ = funStructEmpty{\n+\tfn: func() {\n+\t\tpanic(\"TODO\")\n+\t},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a24)\n-- a3.go --\npackage fillstruct\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n)\n\ntype Foo struct {\n\tA int\n}\n\ntype Bar struct {\n\tX *Foo\n\tY *Foo\n}\n\nvar _ = Bar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n\ntype importedStruct struct {\n\tm  map[*ast.CompositeLit]ast.Field\n\ts  []ast.BadExpr\n\ta  [3]token.Token\n\tc  chan ast.EmptyStmt\n\tfn func(ast_decl ast.DeclStmt) ast.Ellipsis\n\tst ast.CompositeLit\n}\n\nvar _ = importedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n\ntype pointerBuiltinStruct struct {\n\tb *bool\n\ts *string\n\ti *int\n}\n\nvar _ = pointerBuiltinStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n\nvar _ = []ast.UnaryExpr{\n\t{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n}\n\nvar _ = []ast.UnaryExpr{{}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n-- @a31/a3.go --\n@@ -17 +17,4 @@\n-var _ = Bar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n+var _ = Bar{\n+\tX: &Foo{},\n+\tY: &Foo{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a31)\n-- @a32/a3.go --\n@@ -28 +28,10 @@\n-var _ = importedStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n+var _ = importedStruct{\n+\tm: map[*ast.CompositeLit]ast.Field{},\n+\ts: []ast.BadExpr{},\n+\ta: [3]token.Token{},\n+\tc: make(chan ast.EmptyStmt),\n+\tfn: func(ast_decl ast.DeclStmt) ast.Ellipsis {\n+\t\tpanic(\"TODO\")\n+\t},\n+\tst: ast.CompositeLit{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a32)\n-- @a33/a3.go --\n@@ -36 +36,5 @@\n-var _ = pointerBuiltinStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n+var _ = pointerBuiltinStruct{\n+\tb: new(bool),\n+\ts: new(string),\n+\ti: new(int),\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a33)\n-- @a34/a3.go --\n@@ -39 +39,5 @@\n-\t{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n+\t{\n+\t\tOpPos: 0,\n+\t\tOp:    0,\n+\t\tX:     nil,\n+\t}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a34)\n-- @a35/a3.go --\n@@ -42 +42,5 @@\n-var _ = []ast.UnaryExpr{{}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n+var _ = []ast.UnaryExpr{{\n+\tOpPos: 0,\n+\tOp:    0,\n+\tX:     nil,\n+}} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a35)\n-- a4.go --\npackage fillstruct\n\nimport \"go/ast\"\n\ntype iStruct struct {\n\tX int\n}\n\ntype sStruct struct {\n\tstr string\n}\n\ntype multiFill struct {\n\tnum   int\n\tstrin string\n\tarr   []int\n}\n\ntype assignStruct struct {\n\tn ast.Node\n}\n\nfunc fill() {\n\tvar x int\n\tvar _ = iStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n\n\tvar s string\n\tvar _ = sStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n\n\tvar n int\n\t_ = []int{}\n\tif true {\n\t\tarr := []int{1, 2}\n\t}\n\tvar _ = multiFill{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n\n\tvar node *ast.CompositeLit\n\tvar _ = assignStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n}\n\n-- @a41/a4.go --\n@@ -25 +25,3 @@\n-\tvar _ = iStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n+\tvar _ = iStruct{\n+\t\tX: x,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a41)\n-- @a42/a4.go --\n@@ -28 +28,3 @@\n-\tvar _ = sStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n+\tvar _ = sStruct{\n+\t\tstr: s,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a42)\n-- @a43/a4.go --\n@@ -35 +35,5 @@\n-\tvar _ = multiFill{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n+\tvar _ = multiFill{\n+\t\tnum:   n,\n+\t\tstrin: s,\n+\t\tarr:   []int{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a43)\n-- @a45/a4.go --\n@@ -38 +38,3 @@\n-\tvar _ = assignStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n+\tvar _ = assignStruct{\n+\t\tn: node,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=a45)\n-- fillStruct.go --\npackage fillstruct\n\ntype StructA struct {\n\tunexportedIntField int\n\tExportedIntField   int\n\tMapA               map[int]string\n\tArray              []int\n\tStructB\n}\n\ntype StructA2 struct {\n\tB *StructB\n}\n\ntype StructA3 struct {\n\tB StructB\n}\n\nfunc fill() {\n\ta := StructA{}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n\tb := StructA2{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n\tc := StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n\tif true {\n\t\t_ = StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n\t}\n}\n\n-- @fillStruct1/fillStruct.go --\n@@ -20 +20,7 @@\n-\ta := StructA{}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n+\ta := StructA{\n+\t\tunexportedIntField: 0,\n+\t\tExportedIntField:   0,\n+\t\tMapA:               map[int]string{},\n+\t\tArray:              []int{},\n+\t\tStructB:            StructB{},\n+\t}  //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct1)\n-- @fillStruct2/fillStruct.go --\n@@ -21 +21,3 @@\n-\tb := StructA2{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n+\tb := StructA2{\n+\t\tB: &StructB{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct2)\n-- @fillStruct3/fillStruct.go --\n@@ -22 +22,3 @@\n-\tc := StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n+\tc := StructA3{\n+\t\tB: StructB{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct3)\n-- @fillStruct4/fillStruct.go --\n@@ -24 +24,3 @@\n-\t\t_ = StructA3{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n+\t\t_ = StructA3{\n+\t\t\tB: StructB{},\n+\t\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct4)\n-- fillStruct_anon.go --\npackage fillstruct\n\ntype StructAnon struct {\n\ta struct{}\n\tb map[string]any\n\tc map[string]struct {\n\t\td int\n\t\te bool\n\t}\n}\n\nfunc fill() {\n\t_ := StructAnon{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n}\n-- @fillStruct_anon/fillStruct_anon.go --\n@@ -13 +13,8 @@\n-\t_ := StructAnon{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n+\t_ := StructAnon{\n+\t\ta: struct{}{},\n+\t\tb: map[string]any{},\n+\t\tc: map[string]struct {\n+\t\t\td int\n+\t\t\te bool\n+\t\t}{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_anon)\n-- fillStruct_nested.go --\npackage fillstruct\n\ntype StructB struct {\n\tStructC\n}\n\ntype StructC struct {\n\tunexportedInt int\n}\n\nfunc nested() {\n\tc := StructB{\n\t\tStructC: StructC{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n\t}\n}\n\n-- @fill_nested/fillStruct_nested.go --\n@@ -13 +13,3 @@\n-\t\tStructC: StructC{}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n+\t\tStructC: StructC{\n+\t\t\tunexportedInt: 0,\n+\t\t}, //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fill_nested)\n-- fillStruct_package.go --\npackage fillstruct\n\nimport (\n\th2 \"net/http\"\n\n\t\"golang.org/lsptests/fillstruct/data\"\n)\n\nfunc unexported() {\n\ta := data.B{}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n\t_ = h2.Client{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n}\n-- @fillStruct_package1/fillStruct_package.go --\n@@ -10 +10,3 @@\n-\ta := data.B{}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n+\ta := data.B{\n+\t\tExportedInt: 0,\n+\t}   //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package1)\n-- @fillStruct_package2/fillStruct_package.go --\n@@ -11 +11,8 @@\n-\t_ = h2.Client{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n+\t_ = h2.Client{\n+\t\tTransport: nil,\n+\t\tCheckRedirect: func(req *h2.Request, via []*h2.Request) error {\n+\t\t\tpanic(\"TODO\")\n+\t\t},\n+\t\tJar:     nil,\n+\t\tTimeout: 0,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_package2)\n-- fillStruct_partial.go --\npackage fillstruct\n\ntype StructPartialA struct {\n\tPrefilledInt int\n\tUnfilledInt  int\n\tStructPartialB\n}\n\ntype StructPartialB struct {\n\tPrefilledInt int\n\tUnfilledInt  int\n}\n\nfunc fill() {\n\ta := StructPartialA{\n\t\tPrefilledInt: 5,\n\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_partial1)\n\tb := StructPartialB{\n\t\t/* this comment should be preserved */\n\t\tPrefilledInt: 7, // This comment should be preserved.\n\t\t/* As should\n\t\tthis one */\n\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_partial2)\n}\n\n-- @fillStruct_partial1/fillStruct_partial.go --\n@@ -16 +16,3 @@\n-\t\tPrefilledInt: 5,\n+\t\tPrefilledInt:   5,\n+\t\tUnfilledInt:    0,\n+\t\tStructPartialB: StructPartialB{},\n-- @fillStruct_partial2/fillStruct_partial.go --\n@@ -23 +23 @@\n+\t\tUnfilledInt: 0,\n-- fillStruct_spaces.go --\npackage fillstruct\n\ntype StructD struct {\n\tExportedIntField int\n}\n\nfunc spaces() {\n\td := StructD{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n}\n\n-- @fillStruct_spaces/fillStruct_spaces.go --\n@@ -8 +8,3 @@\n-\td := StructD{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n+\td := StructD{\n+\t\tExportedIntField: 0,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_spaces)\n-- fillStruct_unsafe.go --\npackage fillstruct\n\nimport \"unsafe\"\n\ntype unsafeStruct struct {\n\tx int\n\tp unsafe.Pointer\n}\n\nfunc fill() {\n\t_ := unsafeStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n}\n\n-- @fillStruct_unsafe/fillStruct_unsafe.go --\n@@ -11 +11,4 @@\n-\t_ := unsafeStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n+\t_ := unsafeStruct{\n+\t\tx: 0,\n+\t\tp: nil,\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=fillStruct_unsafe)\n-- typeparams.go --\npackage fillstruct\n\ntype emptyStructWithTypeParams[A any] struct{}\n\nvar _ = emptyStructWithTypeParams[int]{} // no suggested fix\n\ntype basicStructWithTypeParams[T any] struct {\n\tfoo T\n}\n\nvar _ = basicStructWithTypeParams[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n\ntype twoArgStructWithTypeParams[F, B any] struct {\n\tfoo F\n\tbar B\n}\n\nvar _ = twoArgStructWithTypeParams[string, int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n\nvar _ = twoArgStructWithTypeParams[int, string]{\n\tbar: \"bar\",\n} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams3)\n\ntype nestedStructWithTypeParams struct {\n\tbar   string\n\tbasic basicStructWithTypeParams[int]\n}\n\nvar _ = nestedStructWithTypeParams{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n\nfunc _[T any]() {\n\ttype S struct{ t T }\n\t_ = S{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n\n\ttype P struct{ t *T }\n\t_ = P{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n\n\ttype Alias[u any] = struct {\n\t\tx u\n\t\ty *T\n\t}\n\t_ = Alias[string]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n\n\ttype Named[u any] struct {\n\t\tx u\n\t\ty T\n\t}\n\t_ = Named[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n}\n-- @typeparams1/typeparams.go --\n@@ -11 +11,3 @@\n-var _ = basicStructWithTypeParams[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n+var _ = basicStructWithTypeParams[int]{\n+\tfoo: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams1)\n-- @typeparams2/typeparams.go --\n@@ -18 +18,4 @@\n-var _ = twoArgStructWithTypeParams[string, int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n+var _ = twoArgStructWithTypeParams[string, int]{\n+\tfoo: \"\",\n+\tbar: 0,\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams2)\n-- @typeparams3/typeparams.go --\n@@ -22 +22 @@\n+\tfoo: 0,\n-- @typeparams4/typeparams.go --\n@@ -29 +29,4 @@\n-var _ = nestedStructWithTypeParams{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n+var _ = nestedStructWithTypeParams{\n+\tbar:   \"\",\n+\tbasic: basicStructWithTypeParams[int]{},\n+} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams4)\n-- @typeparams5/typeparams.go --\n@@ -33 +33,3 @@\n-\t_ = S{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n+\t_ = S{\n+\t\tt: *new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams5)\n-- @typeparams6/typeparams.go --\n@@ -36 +36,3 @@\n-\t_ = P{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n+\t_ = P{\n+\t\tt: new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams6)\n-- @typeparams7/typeparams.go --\n@@ -42 +42,4 @@\n-\t_ = Alias[string]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n+\t_ = Alias[string]{\n+\t\tx: \"\",\n+\t\ty: new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams7)\n-- @typeparams8/typeparams.go --\n@@ -48 +48,4 @@\n-\t_ = Named[int]{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n+\t_ = Named[int]{\n+\t\tx: 0,\n+\t\ty: *new(T),\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=typeparams8)\n-- issue63921.go --\npackage fillstruct\n\n// Test for golang/go#63921: fillstruct panicked with invalid fields.\ntype invalidStruct struct {\n  F int\n  Undefined\n}\n\nfunc _() {\n  // Note: the golden content for issue63921 is empty: fillstruct produces no\n  // edits, but does not panic.\n  invalidStruct{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=issue63921)\n}\n-- named/named.go --\npackage named\n\ntype foo struct {}\ntype aliasFoo = foo\n\nfunc _() {\n\ttype namedInt int\n\ttype namedString string\n\ttype namedBool bool\n\ttype namedPointer *foo\n\ttype namedSlice []foo\n\ttype namedInterface interface{ Error() string }\n\ttype namedChan chan int\n\ttype namedMap map[string]foo\n\ttype namedSignature func(string) string\n\ttype namedStruct struct{}\n\ttype namedArray [3]foo\n\ttype namedAlias aliasFoo\n\n\ttype bar struct {\n\t\tnamedInt namedInt\n\t\tnamedString namedString\n\t\tnamedBool namedBool\n\t\tnamedPointer namedPointer\n\t\tnamedSlice namedSlice\n\t\tnamedInterface namedInterface\n\t\tnamedChan namedChan\n\t\tnamedMap namedMap\n\t\tnamedSignature namedSignature\n\t\tnamedStruct namedStruct\n\t\tnamedArray namedArray\n\t\tnamedAlias namedAlias\n\t}\n\n\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n}\n-- @named/named/named.go --\n@@ -35 +35,14 @@\n-\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n+\tbar{\n+\t\tnamedInt:       0,\n+\t\tnamedString:    \"\",\n+\t\tnamedBool:      false,\n+\t\tnamedPointer:   nil,\n+\t\tnamedSlice:     namedSlice{},\n+\t\tnamedInterface: nil,\n+\t\tnamedChan:      nil,\n+\t\tnamedMap:       namedMap{},\n+\t\tnamedSignature: nil,\n+\t\tnamedStruct:    namedStruct{},\n+\t\tnamedArray:     namedArray{},\n+\t\tnamedAlias:     namedAlias{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=named)\n-- alias/alias.go --\npackage alias\n\ntype foo struct {}\ntype aliasFoo = foo\n\nfunc _() {\n\ttype aliasInt = int\n\ttype aliasString = string\n\ttype aliasBool = bool\n\ttype aliasPointer = *foo\n\ttype aliasSlice = []foo\n\ttype aliasInterface = interface{ Error() string }\n\ttype aliasChan = chan int\n\ttype aliasMap = map[string]foo\n\ttype aliasSignature = func(string) string\n\ttype aliasStruct = struct{ bar string }\n\ttype aliasArray = [3]foo\n\ttype aliasNamed = foo\n\n\ttype bar struct {\n\t\taliasInt aliasInt\n\t\taliasString aliasString\n\t\taliasBool aliasBool\n\t\taliasPointer aliasPointer\n\t\taliasSlice aliasSlice\n\t\taliasInterface aliasInterface\n\t\taliasChan aliasChan\n\t\taliasMap aliasMap\n\t\taliasSignature aliasSignature\n\t\taliasStruct aliasStruct\n\t\taliasArray aliasArray\n\t\taliasNamed aliasNamed\n\t}\n\n\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n}\n-- @alias/alias/alias.go --\n@@ -35 +35,14 @@\n-\tbar{} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n+\tbar{\n+\t\taliasInt:       0,\n+\t\taliasString:    \"\",\n+\t\taliasBool:      false,\n+\t\taliasPointer:   nil,\n+\t\taliasSlice:     aliasSlice{},\n+\t\taliasInterface: nil,\n+\t\taliasChan:      nil,\n+\t\taliasMap:       aliasMap{},\n+\t\taliasSignature: nil,\n+\t\taliasStruct:    aliasStruct{},\n+\t\taliasArray:     aliasArray{},\n+\t\taliasNamed:     aliasNamed{},\n+\t} //@codeaction(\"}\", \"refactor.rewrite.fillStruct\", edit=alias)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/fill_switch.txt",
    "content": "This test checks the behavior of the 'fill switch' code action.\nSee fill_switch_resolve.txt for same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/fillswitch\n\ngo 1.18\n\n-- data/data.go --\npackage data\n\ntype TypeB int\n\nconst (\n  TypeBOne TypeB = iota\n  TypeBTwo\n  TypeBThree\n)\n\n-- a.go --\npackage fillswitch\n\nimport (\n\t\"golang.org/lsptests/fillswitch/data\"\n)\n\ntype typeA int\n\nconst (\n\ttypeAOne typeA = iota\n\ttypeATwo\n\ttypeAThree\n)\n\ntype notification interface {\n\tisNotification()\n}\n\ntype notificationOne struct{}\n\nfunc (notificationOne) isNotification() {}\n\ntype notificationTwo struct{}\n\nfunc (notificationTwo) isNotification() {}\n\nfunc doSwitch() {\n\tvar b data.TypeB\n\tswitch b {\n\tcase data.TypeBOne: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a1)\n\t}\n\n\tvar a typeA\n\tswitch a {\n\tcase typeAThree: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a2)\n\t}\n\n\tvar n notification\n\tswitch n.(type) { //@codeaction(\"{\", \"refactor.rewrite.fillSwitch\", edit=a3)\n\t}\n\n\tswitch nt := n.(type) { //@codeaction(\"{\", \"refactor.rewrite.fillSwitch\", edit=a4)\n\t}\n\n\tvar s struct {\n\t\ta typeA\n\t}\n\n\tswitch s.a {\n\tcase typeAThree: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a5)\n\t}\n}\n-- @a1/a.go --\n@@ -31 +31,4 @@\n+\tcase data.TypeBThree:\n+\tcase data.TypeBTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected data.TypeB: %#v\", b))\n-- @a2/a.go --\n@@ -36 +36,4 @@\n+\tcase typeAOne:\n+\tcase typeATwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.typeA: %#v\", a))\n-- @a3/a.go --\n@@ -40 +40,4 @@\n+\tcase notificationOne:\n+\tcase notificationTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.notification: %#v\", n))\n-- @a4/a.go --\n@@ -43 +43,4 @@\n+\tcase notificationOne:\n+\tcase notificationTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.notification: %#v\", nt))\n-- @a5/a.go --\n@@ -51 +51,4 @@\n+\tcase typeAOne:\n+\tcase typeATwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.typeA: %#v\", s.a))\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/fill_switch_resolve.txt",
    "content": "This test checks the behavior of the 'fill switch' code action, with resolve support.\nSee fill_switch.txt for same test without resolve support.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/fillswitch\n\ngo 1.18\n\n-- data/data.go --\npackage data\n\ntype TypeB int\n\nconst (\n  TypeBOne TypeB = iota\n  TypeBTwo\n  TypeBThree\n)\n\n-- a.go --\npackage fillswitch\n\nimport (\n\t\"golang.org/lsptests/fillswitch/data\"\n)\n\ntype typeA int\n\nconst (\n\ttypeAOne typeA = iota\n\ttypeATwo\n\ttypeAThree\n)\n\ntype notification interface {\n\tisNotification()\n}\n\ntype notificationOne struct{}\n\nfunc (notificationOne) isNotification() {}\n\ntype notificationTwo struct{}\n\nfunc (notificationTwo) isNotification() {}\n\nfunc doSwitch() {\n\tvar b data.TypeB\n\tswitch b {\n\tcase data.TypeBOne: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a1)\n\t}\n\n\tvar a typeA\n\tswitch a {\n\tcase typeAThree: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a2)\n\t}\n\n\tvar n notification\n\tswitch n.(type) { //@codeaction(\"{\", \"refactor.rewrite.fillSwitch\", edit=a3)\n\t}\n\n\tswitch nt := n.(type) { //@codeaction(\"{\", \"refactor.rewrite.fillSwitch\", edit=a4)\n\t}\n\n\tvar s struct {\n\t\ta typeA\n\t}\n\n\tswitch s.a {\n\tcase typeAThree: //@codeaction(\":\", \"refactor.rewrite.fillSwitch\", edit=a5)\n\t}\n}\n-- @a1/a.go --\n@@ -31 +31,4 @@\n+\tcase data.TypeBThree:\n+\tcase data.TypeBTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected data.TypeB: %#v\", b))\n-- @a2/a.go --\n@@ -36 +36,4 @@\n+\tcase typeAOne:\n+\tcase typeATwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.typeA: %#v\", a))\n-- @a3/a.go --\n@@ -40 +40,4 @@\n+\tcase notificationOne:\n+\tcase notificationTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.notification: %#v\", n))\n-- @a4/a.go --\n@@ -43 +43,4 @@\n+\tcase notificationOne:\n+\tcase notificationTwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.notification: %#v\", nt))\n-- @a5/a.go --\n@@ -51 +51,4 @@\n+\tcase typeAOne:\n+\tcase typeATwo:\n+\tdefault:\n+\t\tpanic(fmt.Sprintf(\"unexpected fillswitch.typeA: %#v\", s.a))\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/functionextraction.txt",
    "content": "This test verifies various behaviors of function extraction.\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- basic.go --\npackage extract\n\nfunc _() { //@codeaction(\"{\", \"refactor.extract.function\", end=closeBracket, result=outer)\n\ta := 1    //@codeaction(\"a\", \"refactor.extract.function\", end=end, result=inner)\n\t_ = a + 4 //@loc(end, \"4\")\n} //@loc(closeBracket, \"}\")\n\n-- @outer/basic.go --\npackage extract\n\nfunc _() { //@codeaction(\"{\", \"refactor.extract.function\", end=closeBracket, result=outer)\n\tnewFunction() //@loc(end, \"4\")\n}\n\nfunc newFunction() {\n\ta := 1 //@codeaction(\"a\", \"refactor.extract.function\", end=end, result=inner)\n\t_ = a + 4\n} //@loc(closeBracket, \"}\")\n\n-- @inner/basic.go --\npackage extract\n\nfunc _() { //@codeaction(\"{\", \"refactor.extract.function\", end=closeBracket, result=outer)\n\tnewFunction() //@loc(end, \"4\")\n}\n\nfunc newFunction() {\n\ta := 1 //@codeaction(\"a\", \"refactor.extract.function\", end=end, result=inner)\n\t_ = a + 4\n} //@loc(closeBracket, \"}\")\n\n-- return.go --\npackage extract\n\nfunc _() bool {\n\tx := 1\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=ifend, result=return)\n\t\treturn true\n\t} //@loc(ifend, \"}\")\n\treturn false\n}\n\n-- @return/return.go --\npackage extract\n\nfunc _() bool {\n\tx := 1\n\tb, shouldReturn := newFunction(x)\n\tif shouldReturn {\n\t\treturn b\n\t} //@loc(ifend, \"}\")\n\treturn false\n}\n\nfunc newFunction(x int) (bool, bool) {\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=ifend, result=return)\n\t\treturn true, true\n\t}\n\treturn false, false\n}\n\n-- return_nonnested.go --\npackage extract\n\nfunc _() bool {\n\tx := 1 //@codeaction(\"x\", \"refactor.extract.function\", end=rnnEnd, result=rnn)\n\tif x == 0 {\n\t\treturn true\n\t}\n\treturn false //@loc(rnnEnd, \"false\")\n}\n\n-- @rnn/return_nonnested.go --\npackage extract\n\nfunc _() bool {\n\treturn newFunction() //@loc(rnnEnd, \"false\")\n}\n\nfunc newFunction() bool {\n\tx := 1 //@codeaction(\"x\", \"refactor.extract.function\", end=rnnEnd, result=rnn)\n\tif x == 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n-- return_complex.go --\npackage extract\n\nimport \"fmt\"\n\nfunc _() (int, string, error) {\n\tx := 1\n\ty := \"hello\"\n\tz := \"bye\" //@codeaction(\"z\", \"refactor.extract.function\", end=rcEnd, result=rc)\n\tif y == z {\n\t\treturn x, y, fmt.Errorf(\"same\")\n\t} else if false {\n\t\tz = \"hi\"\n\t\treturn x, z, nil\n\t} //@loc(rcEnd, \"}\")\n\treturn x, z, nil\n}\n\n-- @rc/return_complex.go --\npackage extract\n\nimport \"fmt\"\n\nfunc _() (int, string, error) {\n\tx := 1\n\ty := \"hello\"\n\tz, i, s, err, shouldReturn := newFunction(y, x)\n\tif shouldReturn {\n\t\treturn i, s, err\n\t} //@loc(rcEnd, \"}\")\n\treturn x, z, nil\n}\n\nfunc newFunction(y string, x int) (string, int, string, error, bool) {\n\tz := \"bye\" //@codeaction(\"z\", \"refactor.extract.function\", end=rcEnd, result=rc)\n\tif y == z {\n\t\treturn \"\", x, y, fmt.Errorf(\"same\"), true\n\t} else if false {\n\t\tz = \"hi\"\n\t\treturn \"\", x, z, nil, true\n\t}\n\treturn z, 0, \"\", nil, false\n}\n\n-- return_complex_nonnested.go --\npackage extract\n\nimport \"fmt\"\n\nfunc _() (int, string, error) {\n\tx := 1\n\ty := \"hello\"\n\tz := \"bye\" //@codeaction(\"z\", \"refactor.extract.function\", end=rcnnEnd, result=rcnn)\n\tif y == z {\n\t\treturn x, y, fmt.Errorf(\"same\")\n\t} else if false {\n\t\tz = \"hi\"\n\t\treturn x, z, nil\n\t}\n\treturn x, z, nil //@loc(rcnnEnd, \"nil\")\n}\n\n-- @rcnn/return_complex_nonnested.go --\npackage extract\n\nimport \"fmt\"\n\nfunc _() (int, string, error) {\n\tx := 1\n\ty := \"hello\"\n\treturn newFunction(y, x) //@loc(rcnnEnd, \"nil\")\n}\n\nfunc newFunction(y string, x int) (int, string, error) {\n\tz := \"bye\" //@codeaction(\"z\", \"refactor.extract.function\", end=rcnnEnd, result=rcnn)\n\tif y == z {\n\t\treturn x, y, fmt.Errorf(\"same\")\n\t} else if false {\n\t\tz = \"hi\"\n\t\treturn x, z, nil\n\t}\n\treturn x, z, nil\n}\n\n-- return_func_lit.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tast.Inspect(ast.NewIdent(\"a\"), func(n ast.Node) bool {\n\t\tif n == nil { //@codeaction(\"if\", \"refactor.extract.function\", end=rflEnd, result=rfl)\n\t\t\treturn true\n\t\t} //@loc(rflEnd, \"}\")\n\t\treturn false\n\t})\n}\n\n-- @rfl/return_func_lit.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tast.Inspect(ast.NewIdent(\"a\"), func(n ast.Node) bool {\n\t\tb, shouldReturn := newFunction(n)\n\t\tif shouldReturn {\n\t\t\treturn b\n\t\t} //@loc(rflEnd, \"}\")\n\t\treturn false\n\t})\n}\n\nfunc newFunction(n ast.Node) (bool, bool) {\n\tif n == nil { //@codeaction(\"if\", \"refactor.extract.function\", end=rflEnd, result=rfl)\n\t\treturn true, true\n\t}\n\treturn false, false\n}\n\n-- return_func_lit_nonnested.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tast.Inspect(ast.NewIdent(\"a\"), func(n ast.Node) bool {\n\t\tif n == nil { //@codeaction(\"if\", \"refactor.extract.function\", end=rflnnEnd, result=rflnn)\n\t\t\treturn true\n\t\t}\n\t\treturn false //@loc(rflnnEnd, \"false\")\n\t})\n}\n\n-- @rflnn/return_func_lit_nonnested.go --\npackage extract\n\nimport \"go/ast\"\n\nfunc _() {\n\tast.Inspect(ast.NewIdent(\"a\"), func(n ast.Node) bool {\n\t\treturn newFunction(n) //@loc(rflnnEnd, \"false\")\n\t})\n}\n\nfunc newFunction(n ast.Node) bool {\n\tif n == nil { //@codeaction(\"if\", \"refactor.extract.function\", end=rflnnEnd, result=rflnn)\n\t\treturn true\n\t}\n\treturn false\n}\n\n-- return_init.go --\npackage extract\n\nfunc _() string {\n\tx := 1\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=riEnd, result=ri)\n\t\tx = 3\n\t\treturn \"a\"\n\t} //@loc(riEnd, \"}\")\n\tx = 2\n\treturn \"b\"\n}\n\n-- @ri/return_init.go --\npackage extract\n\nfunc _() string {\n\tx := 1\n\ts, shouldReturn := newFunction(x)\n\tif shouldReturn {\n\t\treturn s\n\t} //@loc(riEnd, \"}\")\n\tx = 2\n\treturn \"b\"\n}\n\nfunc newFunction(x int) (string, bool) {\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=riEnd, result=ri)\n\t\tx = 3\n\t\treturn \"a\", true\n\t}\n\treturn \"\", false\n}\n\n-- return_init_nonnested.go --\npackage extract\n\nfunc _() string {\n\tx := 1\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=rinnEnd, result=rinn)\n\t\tx = 3\n\t\treturn \"a\"\n\t}\n\tx = 2\n\treturn \"b\" //@loc(rinnEnd, \"\\\"b\\\"\")\n}\n\n-- @rinn/return_init_nonnested.go --\npackage extract\n\nfunc _() string {\n\tx := 1\n\treturn newFunction(x) //@loc(rinnEnd, \"\\\"b\\\"\")\n}\n\nfunc newFunction(x int) string {\n\tif x == 0 { //@codeaction(\"if\", \"refactor.extract.function\", end=rinnEnd, result=rinn)\n\t\tx = 3\n\t\treturn \"a\"\n\t}\n\tx = 2\n\treturn \"b\"\n}\n\n-- args_returns.go --\npackage extract\n\nfunc _() {\n\ta := 1\n\ta = 5     //@codeaction(\"a\", \"refactor.extract.function\", end=araend, result=ara)\n\ta = a + 2 //@loc(araend, \"2\")\n\n\tb := a * 2 //@codeaction(\"b\", \"refactor.extract.function\", end=arbend, result=arb)\n\t_ = b + 4  //@loc(arbend, \"4\")\n}\n\n-- @ara/args_returns.go --\npackage extract\n\nfunc _() {\n\ta := 1\n\ta = newFunction(a) //@loc(araend, \"2\")\n\n\tb := a * 2 //@codeaction(\"b\", \"refactor.extract.function\", end=arbend, result=arb)\n\t_ = b + 4  //@loc(arbend, \"4\")\n}\n\nfunc newFunction(a int) int {\n\ta = 5 //@codeaction(\"a\", \"refactor.extract.function\", end=araend, result=ara)\n\ta = a + 2\n\treturn a\n}\n\n-- @arb/args_returns.go --\npackage extract\n\nfunc _() {\n\ta := 1\n\ta = 5     //@codeaction(\"a\", \"refactor.extract.function\", end=araend, result=ara)\n\ta = a + 2 //@loc(araend, \"2\")\n\n\tnewFunction(a)  //@loc(arbend, \"4\")\n}\n\nfunc newFunction(a int) {\n\tb := a * 2 //@codeaction(\"b\", \"refactor.extract.function\", end=arbend, result=arb)\n\t_ = b + 4\n}\n\n-- scope.go --\npackage extract\n\nfunc _() {\n\tnewFunction := 1\n\ta := newFunction //@codeaction(\"a\", \"refactor.extract.function\", end=\"newFunction\", result=scope)\n\t_ = a // avoid diagnostic\n}\n\nfunc newFunction1() int {\n\treturn 1\n}\n\nvar _ = newFunction1\n\n-- @scope/scope.go --\npackage extract\n\nfunc _() {\n\tnewFunction := 1\n\ta := newFunction2(newFunction) //@codeaction(\"a\", \"refactor.extract.function\", end=\"newFunction\", result=scope)\n\t_ = a // avoid diagnostic\n}\n\nfunc newFunction2(newFunction int) int {\n\ta := newFunction\n\treturn a\n}\n\nfunc newFunction1() int {\n\treturn 1\n}\n\nvar _ = newFunction1\n\n-- smart_initialization.go --\npackage extract\n\nfunc _() {\n\tvar a []int\n\ta = append(a, 2) //@codeaction(\"a\", \"refactor.extract.function\", end=siEnd, result=si)\n\tb := 4           //@loc(siEnd, \"4\")\n\ta = append(a, b)\n}\n\n-- @si/smart_initialization.go --\npackage extract\n\nfunc _() {\n\tvar a []int\n\ta, b := newFunction(a)           //@loc(siEnd, \"4\")\n\ta = append(a, b)\n}\n\nfunc newFunction(a []int) ([]int, int) {\n\ta = append(a, 2) //@codeaction(\"a\", \"refactor.extract.function\", end=siEnd, result=si)\n\tb := 4\n\treturn a, b\n}\n\n-- smart_return.go --\npackage extract\n\nfunc _() {\n\tvar b []int\n\tvar a int\n\ta = 2 //@codeaction(\"a\", \"refactor.extract.function\", end=srEnd, result=sr)\n\tb = []int{}\n\tb = append(b, a) //@loc(srEnd, \")\")\n\tb[0] = 1\n}\n\n-- @sr/smart_return.go --\npackage extract\n\nfunc _() {\n\tvar b []int\n\tvar a int\n\tb = newFunction(a, b) //@loc(srEnd, \")\")\n\tb[0] = 1\n}\n\nfunc newFunction(a int, b []int) []int {\n\ta = 2 //@codeaction(\"a\", \"refactor.extract.function\", end=srEnd, result=sr)\n\tb = []int{}\n\tb = append(b, a)\n\treturn b\n}\n\n-- unnecessary_param.go --\npackage extract\n\nfunc _() {\n\tvar b []int\n\ta := 2 //@codeaction(\"a\", \"refactor.extract.function\", end=upEnd, result=up)\n\tb = []int{}\n\tb = append(b, a) //@loc(upEnd, \")\")\n\tb[0] = 1\n\tif a == 2 {\n\t\treturn\n\t}\n}\n\n-- @up/unnecessary_param.go --\npackage extract\n\nfunc _() {\n\tvar b []int\n\ta, b := newFunction(b) //@loc(upEnd, \")\")\n\tb[0] = 1\n\tif a == 2 {\n\t\treturn\n\t}\n}\n\nfunc newFunction(b []int) (int, []int) {\n\ta := 2 //@codeaction(\"a\", \"refactor.extract.function\", end=upEnd, result=up)\n\tb = []int{}\n\tb = append(b, a)\n\treturn a, b\n}\n\n-- comment.go --\npackage extract\n\nfunc _() {\n\ta := /* comment in the middle of a line */ 1 //@codeaction(\"a\", \"refactor.extract.function\", end=commentEnd, result=comment1)\n\t// Comment on its own line  //@codeaction(\"Comment\", \"refactor.extract.function\", end=commentEnd, result=comment2)\n\t_ = a + 4 //@loc(commentEnd, \"4\"),codeaction(\"_\", \"refactor.extract.function\", end=lastComment, result=comment3)\n\t// Comment right after 3 + 4\n\n\t// Comment after with space //@loc(lastComment, \"Comment\")\n}\n\n-- @comment1/comment.go --\npackage extract\n\nfunc _() {\n\tnewFunction() //@loc(commentEnd, \"4\"),codeaction(\"_\", \"refactor.extract.function\", end=lastComment, result=comment3)\n\t// Comment right after 3 + 4\n\n\t// Comment after with space //@loc(lastComment, \"Comment\")\n}\n\nfunc newFunction() {\n\ta := /* comment in the middle of a line */ 1 //@codeaction(\"a\", \"refactor.extract.function\", end=commentEnd, result=comment1)\n\t// Comment on its own line  //@codeaction(\"Comment\", \"refactor.extract.function\", end=commentEnd, result=comment2)\n\t_ = a + 4\n}\n\n-- @comment2/comment.go --\npackage extract\n\nfunc _() {\n\ta := /* comment in the middle of a line */ 1 //@codeaction(\"a\", \"refactor.extract.function\", end=commentEnd, result=comment1)\n\t// Comment on its own line  //@codeaction(\"Comment\", \"refactor.extract.function\", end=commentEnd, result=comment2)\n\tnewFunction(a) //@loc(commentEnd, \"4\"),codeaction(\"_\", \"refactor.extract.function\", end=lastComment, result=comment3)\n\t// Comment right after 3 + 4\n\n\t// Comment after with space //@loc(lastComment, \"Comment\")\n}\n\nfunc newFunction(a int) {\n\t_ = a + 4\n}\n\n-- @comment3/comment.go --\npackage extract\n\nfunc _() {\n\ta := /* comment in the middle of a line */ 1 //@codeaction(\"a\", \"refactor.extract.function\", end=commentEnd, result=comment1)\n\t// Comment on its own line  //@codeaction(\"Comment\", \"refactor.extract.function\", end=commentEnd, result=comment2)\n\tnewFunction(a) //@loc(commentEnd, \"4\"),codeaction(\"_\", \"refactor.extract.function\", end=lastComment, result=comment3)\n\t// Comment right after 3 + 4\n\n\t// Comment after with space //@loc(lastComment, \"Comment\")\n}\n\nfunc newFunction(a int) {\n\t_ = a + 4\n}\n\n-- redefine.go --\npackage extract\n\nimport \"strconv\"\n\nfunc _() {\n\ti, err := strconv.Atoi(\"1\")\n\tu, err := strconv.Atoi(\"2\") //@codeaction(re`u.*\\)`, \"refactor.extract.function\", result=redefine)\n\tif i == u || err == nil {\n\t\treturn\n\t}\n}\n\n-- @redefine/redefine.go --\npackage extract\n\nimport \"strconv\"\n\nfunc _() {\n\ti, err := strconv.Atoi(\"1\")\n\tu, err := newFunction() //@codeaction(re`u.*\\)`, \"refactor.extract.function\", result=redefine)\n\tif i == u || err == nil {\n\t\treturn\n\t}\n}\n\nfunc newFunction() (int, error) {\n\tu, err := strconv.Atoi(\"2\")\n\treturn u, err\n}\n\n-- anonymousfunc.go --\npackage extract\nimport \"cmp\"\nimport \"slices\"\n\n// issue go#64821\nfunc _() {\n\tvar s []string //@codeaction(\"var\", \"refactor.extract.function\", end=anonEnd, result=anon1)\n\tslices.SortFunc(s, func(a, b string) int {\n\t\treturn cmp.Compare(a, b)\n\t})\n\tprintln(s) //@loc(anonEnd, \")\")\n}\n\n-- @anon1/anonymousfunc.go --\npackage extract\nimport \"cmp\"\nimport \"slices\"\n\n// issue go#64821\nfunc _() {\n\tnewFunction() //@loc(anonEnd, \")\")\n}\n\nfunc newFunction() {\n\tvar s []string //@codeaction(\"var\", \"refactor.extract.function\", end=anonEnd, result=anon1)\n\tslices.SortFunc(s, func(a, b string) int {\n\t\treturn cmp.Compare(a, b)\n\t})\n\tprintln(s)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/functionextraction_issue44813.txt",
    "content": "This test verifies the fix for golang/go#44813: extraction failure when there\nare blank identifiers.\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- p.go --\npackage extract\n\nimport \"fmt\"\n\nfunc main() {\n\tx := []rune{} //@codeaction(\"x\", \"refactor.extract.function\", end=end, result=ext)\n\ts := \"HELLO\"\n\tfor _, c := range s {\n\t\tx = append(x, c)\n\t} //@loc(end, \"}\")\n\tfmt.Printf(\"%x\\n\", x)\n}\n\n-- @ext/p.go --\npackage extract\n\nimport \"fmt\"\n\nfunc main() {\n\tx := newFunction() //@loc(end, \"}\")\n\tfmt.Printf(\"%x\\n\", x)\n}\n\nfunc newFunction() []rune {\n\tx := []rune{} //@codeaction(\"x\", \"refactor.extract.function\", end=end, result=ext)\n\ts := \"HELLO\"\n\tfor _, c := range s {\n\t\tx = append(x, c)\n\t}\n\treturn x\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/functionextraction_issue50851.txt",
    "content": "This test checks that function extraction moves comments along with the\nextracted code.\n\n-- main.go --\npackage main\n\ntype F struct{}\n\nfunc (f *F) _() {\n\tprintln(\"a\")\n\n\tprintln(\"b\") //@ codeaction(\"print\", \"refactor.extract.function\", end=end, result=result)\n\t// This line prints the third letter of the alphabet.\n\tprintln(\"c\") //@loc(end, \")\")\n\n\tprintln(\"d\")\n}\n-- @result/main.go --\npackage main\n\ntype F struct{}\n\nfunc (f *F) _() {\n\tprintln(\"a\")\n\n\tnewFunction() //@loc(end, \")\")\n\n\tprintln(\"d\")\n}\n\nfunc newFunction() {\n\tprintln(\"b\") //@ codeaction(\"print\", \"refactor.extract.function\", end=end, result=result)\n\t// This line prints the third letter of the alphabet.\n\tprintln(\"c\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/functionextraction_issue66289.txt",
    "content": "\n-- a.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"encoding/json\"\n)\n\nfunc F() error {\n\ta, err := json.Marshal(0) //@codeaction(\"a\", \"refactor.extract.function\", end=endF, result=F)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"1: %w\", err)\n\t}\n\tb, err := json.Marshal(0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"2: %w\", err)\n\t} //@loc(endF, \"}\")\n\tfmt.Printf(\"%s %s\", a, b)\n\treturn nil\n}\n\n-- @F/a.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"encoding/json\"\n)\n\nfunc F() error {\n\ta, b, err := newFunction()\n\tif err != nil {\n\t\treturn err\n\t} //@loc(endF, \"}\")\n\tfmt.Printf(\"%s %s\", a, b)\n\treturn nil\n}\n\nfunc newFunction() ([]byte, []byte, error) {\n\ta, err := json.Marshal(0) //@codeaction(\"a\", \"refactor.extract.function\", end=endF, result=F)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"1: %w\", err)\n\t}\n\tb, err := json.Marshal(0)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"2: %w\", err)\n\t}\n\treturn a, b, nil\n}\n\n-- b.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n)\n\nfunc G() (x, y int) {\n\tv := rand.Int() //@codeaction(\"v\", \"refactor.extract.function\", end=endG, result=G)\n\tif v < 0 {\n\t\treturn 1, 2\n\t}\n\tif v > 0 {\n\t\treturn 3, 4\n\t} //@loc(endG, \"}\")\n\tfmt.Println(v)\n\treturn 5, 6\n}\n-- @G/b.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n)\n\nfunc G() (x, y int) {\n\tv, x1, y1, shouldReturn := newFunction()\n\tif shouldReturn {\n\t\treturn x1, y1\n\t} //@loc(endG, \"}\")\n\tfmt.Println(v)\n\treturn 5, 6\n}\n\nfunc newFunction() (int, int, int, bool) {\n\tv := rand.Int() //@codeaction(\"v\", \"refactor.extract.function\", end=endG, result=G)\n\tif v < 0 {\n\t\treturn 0, 1, 2, true\n\t}\n\tif v > 0 {\n\t\treturn 0, 3, 4, true\n\t}\n\treturn v, 0, 0, false\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/functionextraction_issue73972.txt",
    "content": "This test verifies the fix for golang/go#73972: extraction should\nnot modify the return statements of anonymous functions.\n\n-- go.mod --\nmodule mod.test/extract\n\ngo 1.18\n\n-- a.go --\npackage extract\n\nimport (\n    \"fmt\"\n    \"strings\"\n)\n\nfunc main() {\n\tb := strings.ContainsFunc(\"a\", func(_ rune) bool { //@codeaction(\"b\", \"refactor.extract.function\", end=end, result=ext)\n\t\treturn false\n\t})\n\tif b {\n\t\treturn\n\t} //@loc(end, \"}\")\n\tfmt.Println(b)\n}\n\n-- @ext/a.go --\npackage extract\n\nimport (\n    \"fmt\"\n    \"strings\"\n)\n\nfunc main() {\n\tb, shouldReturn := newFunction()\n\tif shouldReturn {\n\t\treturn\n\t} //@loc(end, \"}\")\n\tfmt.Println(b)\n}\n\nfunc newFunction() (bool, bool) {\n\tb := strings.ContainsFunc(\"a\", func(_ rune) bool { //@codeaction(\"b\", \"refactor.extract.function\", end=end, result=ext)\n\t\treturn false\n\t})\n\tif b {\n\t\treturn false, true\n\t}\n\treturn b, false\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/grouplines.txt",
    "content": "This test exercises the refactoring of putting arguments, return values, and composite literal elements into a\nsingle line.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- func_arg/func_arg.go --\npackage func_arg\n\nfunc A(\n\ta string,\n\tb, c int64,\n\tx int /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=func_arg)*/,\n\ty int,\n) (r1 string, r2, r3 int64, r4 int, r5 int) {\n\treturn a, b, c, x, y\n}\n\n-- @func_arg/func_arg/func_arg.go --\npackage func_arg\n\nfunc A(a string, b, c int64, x int /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=func_arg)*/, y int) (r1 string, r2, r3 int64, r4 int, r5 int) {\n\treturn a, b, c, x, y\n}\n\n-- func_ret/func_ret.go --\npackage func_ret\n\nfunc A(a string, b, c int64, x int, y int) (\n\tr1 string /*@codeaction(\"r1\", \"refactor.rewrite.joinLines\", result=func_ret)*/,\n\tr2, r3 int64,\n\tr4 int,\n\tr5 int,\n) {\n\treturn a, b, c, x, y\n}\n\n-- @func_ret/func_ret/func_ret.go --\npackage func_ret\n\nfunc A(a string, b, c int64, x int, y int) (r1 string /*@codeaction(\"r1\", \"refactor.rewrite.joinLines\", result=func_ret)*/, r2, r3 int64, r4 int, r5 int) {\n\treturn a, b, c, x, y\n}\n\n-- functype_arg/functype_arg.go --\npackage functype_arg\n\ntype A func(\n\ta string,\n\tb, c int64,\n\tx int /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=functype_arg)*/,\n\ty int,\n) (r1 string, r2, r3 int64, r4 int, r5 int)\n\n-- @functype_arg/functype_arg/functype_arg.go --\npackage functype_arg\n\ntype A func(a string, b, c int64, x int /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=functype_arg)*/, y int) (r1 string, r2, r3 int64, r4 int, r5 int)\n\n-- functype_ret/functype_ret.go --\npackage functype_ret\n\ntype A func(a string, b, c int64, x int, y int) (\n\tr1 string /*@codeaction(\"r1\", \"refactor.rewrite.joinLines\", result=functype_ret)*/,\n\tr2, r3 int64,\n\tr4 int,\n\tr5 int,\n)\n\n-- @functype_ret/functype_ret/functype_ret.go --\npackage functype_ret\n\ntype A func(a string, b, c int64, x int, y int) (r1 string /*@codeaction(\"r1\", \"refactor.rewrite.joinLines\", result=functype_ret)*/, r2, r3 int64, r4 int, r5 int)\n\n-- func_call/func_call.go --\npackage func_call\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(\n\t\t1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=func_call)*/,\n\t\t2,\n\t\t3,\n\t\tfmt.Sprintf(\"hello %d\", 4),\n\t)\n}\n\n-- @func_call/func_call/func_call.go --\npackage func_call\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=func_call)*/, 2, 3, fmt.Sprintf(\"hello %d\", 4))\n}\n\n-- indent/indent.go --\npackage indent\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(\n        1,\n        2,\n        3,\n        fmt.Sprintf(\n            \"hello %d\" /*@codeaction(\"hello\", \"refactor.rewrite.joinLines\", result=indent)*/,\n            4,\n        ))\n}\n\n-- @indent/indent/indent.go --\npackage indent\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(\n        1,\n        2,\n        3,\n        fmt.Sprintf(\"hello %d\" /*@codeaction(\"hello\", \"refactor.rewrite.joinLines\", result=indent)*/, 4))\n}\n\n-- structelts/structelts.go --\npackage structelts\n\ntype A struct{\n\ta int\n\tb int\n}\n\nfunc F() {\n\t_ = A{\n\t\ta: 1,\n\t\tb: 2 /*@codeaction(\"b\", \"refactor.rewrite.joinLines\", result=structelts)*/,\n\t}\n}\n\n-- @structelts/structelts/structelts.go --\npackage structelts\n\ntype A struct{\n\ta int\n\tb int\n}\n\nfunc F() {\n\t_ = A{a: 1, b: 2 /*@codeaction(\"b\", \"refactor.rewrite.joinLines\", result=structelts)*/}\n}\n\n-- sliceelts/sliceelts.go --\npackage sliceelts\n\nfunc F() {\n\t_ = []int{\n\t\t1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=sliceelts)*/,\n\t\t2,\n\t}\n}\n\n-- @sliceelts/sliceelts/sliceelts.go --\npackage sliceelts\n\nfunc F() {\n\t_ = []int{1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=sliceelts)*/, 2}\n}\n\n-- mapelts/mapelts.go --\npackage mapelts\n\nfunc F() {\n\t_ = map[string]int{\n\t\t\"a\": 1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=mapelts)*/,\n\t\t\"b\": 2,\n\t}\n}\n\n-- @mapelts/mapelts/mapelts.go --\npackage mapelts\n\nfunc F() {\n\t_ = map[string]int{\"a\": 1 /*@codeaction(\"1\", \"refactor.rewrite.joinLines\", result=mapelts)*/, \"b\": 2}\n}\n\n-- starcomment/starcomment.go --\npackage starcomment\n\nfunc A(\n\t/*1*/ x /*2*/ string /*3*/ /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=starcomment)*/,\n\t/*4*/ y /*5*/ int /*6*/,\n) (string, int) {\n\treturn x, y\n}\n\n-- @starcomment/starcomment/starcomment.go --\npackage starcomment\n\nfunc A(/*1*/ x /*2*/ string /*3*/ /*@codeaction(\"x\", \"refactor.rewrite.joinLines\", result=starcomment)*/, /*4*/ y /*5*/ int /*6*/) (string, int) {\n\treturn x, y\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/import-shadows-builtin.txt",
    "content": "This is a regression test for bug #63592 in \"organize imports\" whereby\nthe new imports would shadow predeclared names.\n\nIn the original example, the conflict was between predeclared error\ntype and the unfortunately named package github.com/coreos/etcd/error,\nbut this example uses a package with the ludicrous name of complex128.\n\nThe new behavior is that we will not attempt to import packages\nthat shadow predeclared names. (Ideally we would do that only if\nthe predeclared name is actually referenced in the file, which\ncomplex128 happens to be in this example, but that's a trickier\nanalysis than the internal/imports package is game for.)\n\nThe name complex127 works as usual.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- complex128/a.go --\npackage complex128\n\nvar V int\n\n-- complex127/a.go --\npackage complex127\n\nvar V int\n\n-- main.go --\npackage main\n\nimport () //@codeaction(\"import\", \"source.organizeImports\", result=out)\n\nfunc main() {\n\tcomplex128.V() //@diag(\"V\", re\"type complex128 has no field\")\n\tcomplex127.V() //@diag(\"complex127\", re\"(undeclared|undefined)\")\n}\n\nfunc _() {\n\tvar _ complex128 = 1 + 2i\n}\n-- @out/main.go --\npackage main\n\nimport \"example.com/complex127\" //@codeaction(\"import\", \"source.organizeImports\", result=out)\n\nfunc main() {\n\tcomplex128.V() //@diag(\"V\", re\"type complex128 has no field\")\n\tcomplex127.V() //@diag(\"complex127\", re\"(undeclared|undefined)\")\n}\n\nfunc _() {\n\tvar _ complex128 = 1 + 2i\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/imports-generated.txt",
    "content": "This test verifies that the 'source.organizeImports' code action\nis offered in generated files (see #73959).\n\n-- go.mod --\nmodule example.com\ngo 1.21\n\n-- a.go --\n// Code generated by me. DO NOT EDIT.\n\npackage a //@codeaction(\"a\", \"source.organizeImports\", result=out)\n\nfunc _() {\n\tfmt.Println(\"hello\") //@diag(\"fmt\", re\"undefined\")\n}\n\n-- @out/a.go --\n// Code generated by me. DO NOT EDIT.\n\npackage a //@codeaction(\"a\", \"source.organizeImports\", result=out)\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println(\"hello\") //@diag(\"fmt\", re\"undefined\")\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/imports.txt",
    "content": "This test verifies the behavior of the 'source.organizeImports' code action.\n\n-- go.mod --\nmodule mod.test/imports\n\ngo 1.18\n\n-- add.go --\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=add)\n\nimport (\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n\tbytes.NewBuffer(nil) //@diag(\"bytes\", re\"(undeclared|undefined)\")\n}\n\n-- @add/add.go --\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=add)\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n\tbytes.NewBuffer(nil) //@diag(\"bytes\", re\"(undeclared|undefined)\")\n}\n\n-- good.go --\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", err=re\"found 0 CodeActions\")\n\nimport \"fmt\"\n\nfunc _() {\nfmt.Println(\"\")\n}\n\n-- issue35458.go --\n\n\n\n\n\n// package doc\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=issue35458)\n\n\n\n\n\n\nfunc _() {\n\tprintln(\"Hello, world!\")\n}\n\n\n\n\n\n\n\n\n-- @issue35458/issue35458.go --\n// package doc\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=issue35458)\n\n\n\n\n\n\nfunc _() {\n\tprintln(\"Hello, world!\")\n}\n\n\n\n\n\n\n\n\n-- multi.go --\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=multi)\n\nimport \"fmt\"\n\nimport \"bytes\" //@diag(\"\\\"bytes\\\"\", re\"not used\")\n\nfunc _() {\n\tfmt.Println(\"\")\n}\n\n-- @multi/multi.go --\npackage imports //@codeaction(\"imports\", \"source.organizeImports\", result=multi)\n\nimport \"fmt\"\n\n//@diag(\"\\\"bytes\\\"\", re\"not used\")\n\nfunc _() {\n\tfmt.Println(\"\")\n}\n\n-- needs.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=needs)\n\nfunc goodbye() {\n\tfmt.Printf(\"HI\") //@diag(\"fmt\", re\"(undeclared|undefined)\")\n\tlog.Printf(\"byeeeee\") //@diag(\"log\", re\"(undeclared|undefined)\")\n}\n\n-- @needs/needs.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=needs)\n\nimport (\n\t\"fmt\"\n\t\"log\"\n)\n\nfunc goodbye() {\n\tfmt.Printf(\"HI\") //@diag(\"fmt\", re\"(undeclared|undefined)\")\n\tlog.Printf(\"byeeeee\") //@diag(\"log\", re\"(undeclared|undefined)\")\n}\n\n-- remove.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=remove)\n\nimport (\n\t\"bytes\" //@diag(\"\\\"bytes\\\"\", re\"not used\")\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n}\n\n-- @remove/remove.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=remove)\n\nimport (\n\t\"fmt\"\n)\n\nfunc _() {\n\tfmt.Println(\"\")\n}\n\n-- removeall.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=removeall)\n\nimport (\n\t\"bytes\" //@diag(\"\\\"bytes\\\"\", re\"not used\")\n\t\"fmt\" //@diag(\"\\\"fmt\\\"\", re\"not used\")\n\n)\n\nfunc _() {\n}\n\n-- @removeall/removeall.go --\npackage imports //@codeaction(\"package\", \"source.organizeImports\", result=removeall)\n\n//@diag(\"\\\"fmt\\\"\", re\"not used\")\n\nfunc _() {\n}\n\n-- twolines.go --\npackage imports\nfunc main()  {} //@codeaction(\"main\", \"source.organizeImports\", err=re\"found 0\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-lhs-var-method.txt",
    "content": "We should not offer a code action to inline 'v' where it appears on the\nleft-hand side of an assignment: method with pointer receiver.\n\nRegression test for issue #75200.\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- c/c.go --\npackage c\n\nimport \"fmt\"\n\ntype V int\n\nfunc (V) Method() { }\n\nfunc (*V) PointerMethod() { }\n\nfunc _() {\n    var v V = V(123)\n    v = V(13)\n    v.Method() //@codeaction(\"v\", \"refactor.inline.variable\", result=inlineV)\n    v.PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    (v).PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    var vptr *V = &v\n    vptr.PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptr)\n    (vptr).PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptrpar)\n    fmt.Println(v, vptr)\n}\n\n-- @inlineV/c/c.go --\npackage c\n\nimport \"fmt\"\n\ntype V int\n\nfunc (V) Method() { }\n\nfunc (*V) PointerMethod() { }\n\nfunc _() {\n    var v V = V(123)\n    v = V(13)\n    V(123).Method() //@codeaction(\"v\", \"refactor.inline.variable\", result=inlineV)\n    v.PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    (v).PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    var vptr *V = &v\n    vptr.PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptr)\n    (vptr).PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptrpar)\n    fmt.Println(v, vptr)\n}\n\n-- @inlintVptr/c/c.go --\npackage c\n\nimport \"fmt\"\n\ntype V int\n\nfunc (V) Method() { }\n\nfunc (*V) PointerMethod() { }\n\nfunc _() {\n    var v V = V(123)\n    v = V(13)\n    v.Method() //@codeaction(\"v\", \"refactor.inline.variable\", result=inlineV)\n    v.PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    (v).PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    var vptr *V = &v\n    (&v).PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptr)\n    (vptr).PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptrpar)\n    fmt.Println(v, vptr)\n}\n\n-- @inlintVptrpar/c/c.go --\npackage c\n\nimport \"fmt\"\n\ntype V int\n\nfunc (V) Method() { }\n\nfunc (*V) PointerMethod() { }\n\nfunc _() {\n    var v V = V(123)\n    v = V(13)\n    v.Method() //@codeaction(\"v\", \"refactor.inline.variable\", result=inlineV)\n    v.PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    (v).PointerMethod() //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    var vptr *V = &v\n    vptr.PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptr)\n    (&v).PointerMethod() //@codeaction(\"vptr\", \"refactor.inline.variable\", result=inlintVptrpar)\n    fmt.Println(v, vptr)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-lhs-var.txt",
    "content": "We should not offer a code action to inline 'v' where it appears on the\nleft-hand side of an assignment\n\nRegression test for issue #75200.\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- c/c.go --\npackage c\n\nimport \"fmt\"\n\nfunc _() {\n    v := 13\n    v = 78 //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n\n    v += 78 //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    v -= 78 //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    v *= 78 //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n\n    v++ //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    v-- //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n\n    fmt.Println(v)\n\n    x := &v //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    x = (&v) //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n    x = &(v) //@codeaction(\"v\", \"refactor.inline.variable\", err=\"0 CodeActions of kind refactor.inline.variable\")\n\n    fmt.Println(x)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-var-74347.txt",
    "content": "This is a regression test of a crash in refactor.inline.variable.\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n       x := func(notfree int) { _ = notfree }\n       println(x) //@codeaction(\"x\", \"refactor.inline.variable\", result=out)\n}\n-- @out/a/a.go --\npackage a\n\nfunc _() {\n       x := func(notfree int) { _ = notfree }\n       println(func(notfree int) { _ = notfree }) //@codeaction(\"x\", \"refactor.inline.variable\", result=out)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-var-74347b.txt",
    "content": "This is regression test of a second crash in\nrefactor.inline.variable covered by #74347.\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\ttype S struct{ F int }\n\tx := S{F: 0}\n\t_ = x //@codeaction(\"x\", \"refactor.inline.variable\", result=out)\n}\n\n-- @out/a/a.go --\npackage a\n\nfunc _() {\n\ttype S struct{ F int }\n\tx := S{F: 0}\n\t_ = S{F: 0} //@codeaction(\"x\", \"refactor.inline.variable\", result=out)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-var-76144.txt",
    "content": "Regression test for #76144, a panic in refactor.inline.variable.\n\nIt was fixed by CL 683535, making it logically a dup of #74347.\n\n-- a/a.go --\npackage main\n\ntype A struct {\n\tName string\n}\n\nfunc F(m map[string]A) {\n\thuman := A{\n\t\tName: \"foo\",\n\t}\n\tm[\"foo\"] = human //@codeaction(\"hu\", \"refactor.inline.variable\", result=out)\n}\n-- @out/a/a.go --\npackage main\n\ntype A struct {\n\tName string\n}\n\nfunc F(m map[string]A) {\n\thuman := A{\n\t\tName: \"foo\",\n\t}\n\tm[\"foo\"] = A{\n\tName: \"foo\",\n} //@codeaction(\"hu\", \"refactor.inline.variable\", result=out)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-var-parens.txt",
    "content": "Test that refactor.inline.variable adds parens as needed to preserve\noperator precedence (go.dev/issue/77381).\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tx := 3 + 4\n\tprint(x) //@codeaction(\"x\", \"refactor.inline.variable\", result=one)\n\tprint(2 * x) //@codeaction(\"x\", \"refactor.inline.variable\", result=two)\n}\n-- @one/a/a.go --\npackage a\n\nfunc _() {\n\tx := 3 + 4\n\tprint(3 + 4) //@codeaction(\"x\", \"refactor.inline.variable\", result=one)\n\tprint(2 * x) //@codeaction(\"x\", \"refactor.inline.variable\", result=two)\n}\n-- @two/a/a.go --\npackage a\n\nfunc _() {\n\tx := 3 + 4\n\tprint(x) //@codeaction(\"x\", \"refactor.inline.variable\", result=one)\n\tprint(2 * (3 + 4)) //@codeaction(\"x\", \"refactor.inline.variable\", result=two)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-var.txt",
    "content": "This is a test of the refactor.inline.variable code action.\n\n-- go.mod --\nmodule example.com/a\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"fmt\"\n\nfunc _(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(s) //@codeaction(\"s\", \"refactor.inline.variable\", result=inlineS)\n}\n\n-- @inlineS/a/a.go --\npackage a\n\nimport \"fmt\"\n\nfunc _(x int) {\n\ts := fmt.Sprintf(\"+%d\", x)\n\tprintln(fmt.Sprintf(\"+%d\", x)) //@codeaction(\"s\", \"refactor.inline.variable\", result=inlineS)\n}\n\n-- b/b.go --\npackage b\n\nimport \"fmt\"\n\nfunc _(x int) {\n\ts2 := fmt.Sprintf(\"+%d\", x)\n\t{\n\t\tx := \"shadow\"\n\t\tprintln(s2, x) //@codeaction(\"s2\", \"refactor.inline.variable\", err=re`refers to \"x\".*shadowed.*at line 8`)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline-version.txt",
    "content": "Test of caller/callee Go version compatibility check (#75726).\n\n-- go.work --\nuse .\nuse ./b\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"example.com/b\"\n\nvar _ = b.Add(1, 2) //@ codeaction(\"Add\", \"refactor.inline.call\", end=\")\", err=`cannot inline call to b.Add (declared using go1.20) into a file using go1.18`)\n\n-- b/go.mod --\nmodule example.com/b\ngo 1.20\n\n-- b/b.go --\npackage b\n\nfunc Add(x, y int) int { return x + y }\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline.txt",
    "content": "This is a minimal test of the refactor.inline.call code action, without resolve support.\nSee inline_resolve.txt for same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- go.mod --\nmodule example.com/codeaction\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tprintln(add(1, 2)) //@codeaction(\"add\", \"refactor.inline.call\", end=\")\", result=inline)\n}\n\nfunc add(x, y int) int { return x + y }\n\n-- @inline/a/a.go --\npackage a\n\nfunc _() {\n\tprintln(1 + 2) //@codeaction(\"add\", \"refactor.inline.call\", end=\")\", result=inline)\n}\n\nfunc add(x, y int) int { return x + y }\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline_issue67336.txt",
    "content": "This is the test case from golang/go#67335, where the inlining resulted in bad\nformatting.\n\nThe __unused__ import results in removal after a subsequent \"organize imports\" step.\n\n-- go.mod --\nmodule example.com\n\ngo 1.20\n\n-- define/my/typ/foo.go --\npackage typ\ntype T int\n\n-- some/other/pkg/foo.go --\npackage pkg\nimport \"context\"\nimport \"example.com/define/my/typ\"\nfunc Foo(typ.T) context.Context{ return nil }\n\n-- one/more/pkg/foo.go --\npackage pkg\nfunc Bar() {}\n\n-- to/be/inlined/foo.go --\npackage inlined\n\nimport \"context\"\nimport \"example.com/some/other/pkg\"\nimport \"example.com/define/my/typ\"\n\nfunc Baz(ctx context.Context) context.Context {\n\treturn pkg.Foo(typ.T(5))\n}\n\n-- b/c/foo.go --\npackage c\nimport (\n\t\"context\"\n\t\"example.com/to/be/inlined\"\n\t\"example.com/one/more/pkg\"\n)\n\nconst (\n\t// This is a constant\n\tSomeConst = 5\n)\n\nfunc _() {\n\tinlined.Baz(context.TODO()) //@ codeaction(\"Baz\", \"refactor.inline.call\", result=inline)\n\tpkg.Bar()\n}\n\n-- @inline/b/c/foo.go --\npackage c\nimport (\n\t\"context\"\n\t\n\t\"example.com/one/more/pkg\"\n\tpkg0 \"example.com/some/other/pkg\"\n\t\"example.com/define/my/typ\"\n)\n\nconst (\n\t// This is a constant\n\tSomeConst = 5\n)\n\nfunc _() {\n\tvar _ context.Context = context.TODO()\npkg0.Foo(typ.T(5)) //@ codeaction(\"Baz\", \"refactor.inline.call\", result=inline)\n\tpkg.Bar()\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline_issue68554.txt",
    "content": "This test checks that inlining removes unnecessary interface conversions.\n\n-- main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nfunc _(d discard) {\n\tg(d) //@codeaction(\"g\", \"refactor.inline.call\", result=out)\n}\n\nfunc g(w io.Writer) { fmt.Println(w) }\n\nvar _ discard\ntype discard struct{}\nfunc (discard) Write(p []byte) (int, error) { return len(p), nil }\n-- @out/main.go --\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nfunc _(d discard) {\n\tfmt.Println(d) //@codeaction(\"g\", \"refactor.inline.call\", result=out)\n}\n\nfunc g(w io.Writer) { fmt.Println(w) }\n\nvar _ discard\ntype discard struct{}\nfunc (discard) Write(p []byte) (int, error) { return len(p), nil }\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/inline_resolve.txt",
    "content": "This is a minimal test of the refactor.inline.call code actions, with resolve support.\nSee inline.txt for same test without resolve support.\n\n-- go.mod --\nmodule example.com/codeaction\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tprintln(add(1, 2)) //@codeaction(\"add\", \"refactor.inline.call\", end=\")\", result=inline)\n}\n\nfunc add(x, y int) int { return x + y }\n\n-- @inline/a/a.go --\npackage a\n\nfunc _() {\n\tprintln(1 + 2) //@codeaction(\"add\", \"refactor.inline.call\", end=\")\", result=inline)\n}\n\nfunc add(x, y int) int { return x + y }\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/invertif.txt",
    "content": "This test exercises the 'invert if condition' code action.\n\n-- p.go --\npackage invertif\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc Boolean() {\n\tb := true\n\tif b { //@codeaction(\"if b\", \"refactor.rewrite.invertIf\", edit=boolean)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc BooleanFn() {\n\tif os.IsPathSeparator('X') { //@codeaction(\"if os.IsPathSeparator('X')\", \"refactor.rewrite.invertIf\", edit=boolean_fn)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\n// Note that the comment here jumps to the wrong location.\nfunc DontRemoveParens() {\n\ta := false\n\tb := true\n\tif !(a ||\n\t\tb) { //@codeaction(\"b\", \"refactor.rewrite.invertIf\", edit=dont_remove_parens)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc ElseIf() {\n\t// No inversion expected when there's not else clause\n\tif len(os.Args) > 2 {\n\t\tfmt.Println(\"A\")\n\t}\n\n\t// No inversion expected for else-if, that would become unreadable\n\tif len(os.Args) > 2 {\n\t\tfmt.Println(\"A\")\n\t} else if os.Args[0] == \"X\" { //@codeaction(re\"if os.Args.0. == .X.\", \"refactor.rewrite.invertIf\", edit=else_if)\n\t\tfmt.Println(\"B\")\n\t} else {\n\t\tfmt.Println(\"C\")\n\t}\n}\n\nfunc GreaterThan() {\n\tif len(os.Args) > 2 { //@codeaction(\"i\", \"refactor.rewrite.invertIf\", edit=greater_than)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc NotBoolean() {\n\tb := true\n\tif !b { //@codeaction(\"if !b\", \"refactor.rewrite.invertIf\", edit=not_boolean)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc RemoveElse() {\n\tif true { //@codeaction(\"if true\", \"refactor.rewrite.invertIf\", edit=remove_else)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t\treturn\n\t}\n\n\tfmt.Println(\"C\")\n}\n\nfunc RemoveParens() {\n\tb := true\n\tif !(b) { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=remove_parens)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc Semicolon() {\n\tif _, err := fmt.Println(\"x\"); err != nil { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=semicolon)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc SemicolonAnd() {\n\tif n, err := fmt.Println(\"x\"); err != nil && n > 0 { //@codeaction(\"f\", \"refactor.rewrite.invertIf\", edit=semicolon_and)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\nfunc SemicolonOr() {\n\tif n, err := fmt.Println(\"x\"); err != nil || n < 5 { //@codeaction(re\"if n, err := fmt.Println..x..; err != nil .. n < 5\", \"refactor.rewrite.invertIf\", edit=semicolon_or)\n\t\tfmt.Println(\"A\")\n\t} else {\n\t\tfmt.Println(\"B\")\n\t}\n}\n\n-- @boolean/p.go --\n@@ -10,3 +10 @@\n-\tif b { //@codeaction(\"if b\", \"refactor.rewrite.invertIf\", edit=boolean)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif !b {\n@@ -14 +12,2 @@\n+\t} else { //@codeaction(\"if b\", \"refactor.rewrite.invertIf\", edit=boolean)\n+\t\tfmt.Println(\"A\")\n-- @boolean_fn/p.go --\n@@ -18,3 +18 @@\n-\tif os.IsPathSeparator('X') { //@codeaction(\"if os.IsPathSeparator('X')\", \"refactor.rewrite.invertIf\", edit=boolean_fn)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif !os.IsPathSeparator('X') {\n@@ -22 +20,2 @@\n+\t} else { //@codeaction(\"if os.IsPathSeparator('X')\", \"refactor.rewrite.invertIf\", edit=boolean_fn)\n+\t\tfmt.Println(\"A\")\n-- @dont_remove_parens/p.go --\n@@ -29,4 +29,2 @@\n-\tif !(a ||\n-\t\tb) { //@codeaction(\"b\", \"refactor.rewrite.invertIf\", edit=dont_remove_parens)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif (a ||\n+\t\tb) {\n@@ -34 +32,2 @@\n+\t} else { //@codeaction(\"b\", \"refactor.rewrite.invertIf\", edit=dont_remove_parens)\n+\t\tfmt.Println(\"A\")\n-- @else_if/p.go --\n@@ -46,3 +46 @@\n-\t} else if os.Args[0] == \"X\" { //@codeaction(re\"if os.Args.0. == .X.\", \"refactor.rewrite.invertIf\", edit=else_if)\n-\t\tfmt.Println(\"B\")\n-\t} else {\n+\t} else if os.Args[0] != \"X\" {\n@@ -50 +48,2 @@\n+\t} else { //@codeaction(re\"if os.Args.0. == .X.\", \"refactor.rewrite.invertIf\", edit=else_if)\n+\t\tfmt.Println(\"B\")\n-- @greater_than/p.go --\n@@ -54,3 +54 @@\n-\tif len(os.Args) > 2 { //@codeaction(\"i\", \"refactor.rewrite.invertIf\", edit=greater_than)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif len(os.Args) <= 2 {\n@@ -58 +56,2 @@\n+\t} else { //@codeaction(\"i\", \"refactor.rewrite.invertIf\", edit=greater_than)\n+\t\tfmt.Println(\"A\")\n-- @not_boolean/p.go --\n@@ -63,3 +63 @@\n-\tif !b { //@codeaction(\"if !b\", \"refactor.rewrite.invertIf\", edit=not_boolean)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif b {\n@@ -67 +65,2 @@\n+\t} else { //@codeaction(\"if !b\", \"refactor.rewrite.invertIf\", edit=not_boolean)\n+\t\tfmt.Println(\"A\")\n-- @remove_else/p.go --\n@@ -71,3 +71 @@\n-\tif true { //@codeaction(\"if true\", \"refactor.rewrite.invertIf\", edit=remove_else)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif false {\n@@ -78 +76,3 @@\n+\t//@codeaction(\"if true\", \"refactor.rewrite.invertIf\", edit=remove_else)\n+\tfmt.Println(\"A\")\n+\n-- @remove_parens/p.go --\n@@ -83,3 +83 @@\n-\tif !(b) { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=remove_parens)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif b {\n@@ -87 +85,2 @@\n+\t} else { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=remove_parens)\n+\t\tfmt.Println(\"A\")\n-- @semicolon/p.go --\n@@ -91,3 +91 @@\n-\tif _, err := fmt.Println(\"x\"); err != nil { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=semicolon)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif _, err := fmt.Println(\"x\"); err == nil {\n@@ -95 +93,2 @@\n+\t} else { //@codeaction(\"if\", \"refactor.rewrite.invertIf\", edit=semicolon)\n+\t\tfmt.Println(\"A\")\n-- @semicolon_and/p.go --\n@@ -99,3 +99 @@\n-\tif n, err := fmt.Println(\"x\"); err != nil && n > 0 { //@codeaction(\"f\", \"refactor.rewrite.invertIf\", edit=semicolon_and)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif n, err := fmt.Println(\"x\"); err == nil || n <= 0 {\n@@ -103 +101,2 @@\n+\t} else { //@codeaction(\"f\", \"refactor.rewrite.invertIf\", edit=semicolon_and)\n+\t\tfmt.Println(\"A\")\n-- @semicolon_or/p.go --\n@@ -107,3 +107 @@\n-\tif n, err := fmt.Println(\"x\"); err != nil || n < 5 { //@codeaction(re\"if n, err := fmt.Println..x..; err != nil .. n < 5\", \"refactor.rewrite.invertIf\", edit=semicolon_or)\n-\t\tfmt.Println(\"A\")\n-\t} else {\n+\tif n, err := fmt.Println(\"x\"); err == nil && n >= 5 {\n@@ -111 +109,2 @@\n+\t} else { //@codeaction(re\"if n, err := fmt.Println..x..; err != nil .. n < 5\", \"refactor.rewrite.invertIf\", edit=semicolon_or)\n+\t\tfmt.Println(\"A\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/issue64558.txt",
    "content": "Test of an inlining failure due to an ill-typed input program (#64558).\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tf(1, 2) //@ diag(\"2\", re\"too many arguments\"), codeaction(\"f\", \"refactor.inline.call\", end=\")\", err=re`inlining failed \\(\"too many arguments\"\\), likely because inputs were ill-typed`)\n}\n\nfunc f(int) {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/issue70268.txt",
    "content": "This test verifies the remove of unused parameters in case of syntax errors.\nIssue golang/go#70268.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\nfunc A(x, unused int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- @a/a/a.go --\npackage a\n\nfunc A(x int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- b/b.go --\npackage b\n\nimport \"unused.mod/a\"\n\nfunc main(){\n\ta.A/*dsdd*/(/*cccc*/ 1,\n\n\n\t) //@diag(\")\", re\"not enough arguments\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/moveparam.txt",
    "content": "This test checks basic functionality of the \"move parameter left/right\" code\naction.\n\nNote that in many of these tests, a permutation can either be expressed as\na parameter move left or right. In these cases, the codeaction assertions\ndeliberately share the same golden data.\n\n-- go.mod --\nmodule example.com/moveparam\n\ngo 1.19\n\n-- basic/basic.go --\npackage basic\n\nfunc Foo(a, b int) int { //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=basic), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=basic)\n\treturn a + b\n}\n\nfunc _() {\n\tx, y := 1, 2\n\tz := Foo(x, y)\n\t_ = z\n}\n\n-- basic/caller/caller.go --\npackage caller\n\nimport \"example.com/moveparam/basic\"\n\nfunc a() int { return 1 }\nfunc b() int { return 2 }\n\n// Check that we can refactor a call in a toplevel var decl.\nvar _ = basic.Foo(1, 2)\n\n// Check that we can refactor a call with effects in a toplevel var decl.\nvar _ = basic.Foo(a(), b())\n\nfunc _() {\n\t// check various refactorings in a function body, and comment handling.\n\t_ = basic.Foo(1, 2) // with comments\n\t// another comment\n\t_ = basic.Foo(3, 4)\n\tx := 4\n\tx = basic.Foo(x /* this is an inline comment */, 5)\n}\n\n-- @basic/basic/basic.go --\npackage basic\n\nfunc Foo(b, a int) int { //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=basic), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=basic)\n\treturn a + b\n}\n\nfunc _() {\n\tx, y := 1, 2\n\tz := Foo(y, x)\n\t_ = z\n}\n-- @basic/basic/caller/caller.go --\npackage caller\n\nimport \"example.com/moveparam/basic\"\n\nfunc a() int { return 1 }\nfunc b() int { return 2 }\n\n// Check that we can refactor a call in a toplevel var decl.\nvar _ = basic.Foo(2, 1)\n\n// Check that we can refactor a call with effects in a toplevel var decl.\nvar _ = basic.Foo(b(), a())\n\nfunc _() {\n\t// check various refactorings in a function body, and comment handling.\n\t_ = basic.Foo(2, 1) // with comments\n\t// another comment\n\t_ = basic.Foo(4, 3)\n\tx := 4\n\tx = basic.Foo(5, x)\n}\n-- method/method.go --\npackage method\n\ntype T struct{}\n\nfunc (T) Foo(a, b int) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=method), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=method)\n\nfunc _() {\n\tvar t T\n\tt.Foo(1, 2)\n\t// TODO(rfindley): test method expressions here, once they are handled.\n}\n\n-- method/caller/caller.go --\npackage caller\n\nimport \"example.com/moveparam/method\"\n\nfunc _() {\n\tvar t method.T\n\tt.Foo(1, 2)\n}\n\n-- @method/method/caller/caller.go --\npackage caller\n\nimport \"example.com/moveparam/method\"\n\nfunc _() {\n\tvar t method.T\n\tt.Foo(2, 1)\n}\n-- @method/method/method.go --\npackage method\n\ntype T struct{}\n\nfunc (T) Foo(b, a int) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=method), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=method)\n\nfunc _() {\n\tvar t T\n\tt.Foo(2, 1)\n\t// TODO(rfindley): test method expressions here, once they are handled.\n}\n-- fieldlist/joinfield.go --\npackage fieldlist\n\nfunc JoinField(a int, b string, c int) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=joinfield), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=joinfield)\n\nfunc _() {\n\tJoinField(1, \"2\", 3)\n}\n\n-- @joinfield/fieldlist/joinfield.go --\npackage fieldlist\n\nfunc JoinField(b string, a, c int) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=joinfield), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=joinfield)\n\nfunc _() {\n\tJoinField(\"2\", 1, 3)\n}\n-- fieldlist/splitfield.go --\npackage fieldlist\n\nfunc SplitField(a int, b, c string) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=splitfield), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=splitfield)\n\nfunc _() {\n\tSplitField(1, \"2\", \"3\")\n}\n\n-- @splitfield/fieldlist/splitfield.go --\npackage fieldlist\n\nfunc SplitField(b string, a int, c string) {} //@codeaction(\"a\", \"refactor.rewrite.moveParamRight\", result=splitfield), codeaction(\"b\", \"refactor.rewrite.moveParamLeft\", result=splitfield)\n\nfunc _() {\n\tSplitField(\"2\", 1, \"3\")\n}\n-- unnamed/unnamed.go --\npackage unnamed\n\nfunc Unnamed(int, string) { //@codeaction(\"int\", \"refactor.rewrite.moveParamRight\", result=unnamed)\n}\n\nfunc _() {\n\tUnnamed(1, \"hi\")\n}\n-- @unnamed/unnamed/unnamed.go --\npackage unnamed\n\nfunc Unnamed(string, int) { //@codeaction(\"int\", \"refactor.rewrite.moveParamRight\", result=unnamed)\n}\n\nfunc _() {\n\tUnnamed(\"hi\", 1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/moveparam_issue70599.txt",
    "content": "This test checks the fixes for bugs encountered while bug-bashing on the\nmovement refactoring.\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- unnecessaryconversion.go --\npackage a\n\n// We should not add unnecessary conversions to concrete arguments to concrete\n// parameters when the parameter use is in assignment context.\n\ntype Hash [32]byte\n\nfunc Cache(key [32]byte, value any) { //@codeaction(\"key\", \"refactor.rewrite.moveParamRight\", result=conversion)\n\t// Not implemented.\n}\n\nfunc _() {\n\tvar k Hash\n\tCache(k, 0)\n\tCache(Hash{}, 1)\n\tCache([32]byte{}, 2)\n}\n\n-- @conversion/unnecessaryconversion.go --\npackage a\n\n// We should not add unnecessary conversions to concrete arguments to concrete\n// parameters when the parameter use is in assignment context.\n\ntype Hash [32]byte\n\nfunc Cache(value any, key [32]byte) { //@codeaction(\"key\", \"refactor.rewrite.moveParamRight\", result=conversion)\n\t// Not implemented.\n}\n\nfunc _() {\n\tvar k Hash\n\tCache(0, k)\n\tCache(1, Hash{})\n\tCache(2, [32]byte{})\n}\n-- shortvardecl.go --\npackage a\n\nfunc Short(x, y int) (int, int) { //@codeaction(\"x\", \"refactor.rewrite.moveParamRight\", result=short)\n\treturn x, y\n}\n\nfunc _() {\n\tx, y := Short(0, 1)\n\t_, _ = x, y\n}\n\nfunc _() {\n\tvar x, y int\n\tx, y = Short(0, 1)\n\t_, _ = x, y\n}\n\nfunc _() {\n\t_, _ = Short(0, 1)\n}\n-- @short/shortvardecl.go --\npackage a\n\nfunc Short(y, x int) (int, int) { //@codeaction(\"x\", \"refactor.rewrite.moveParamRight\", result=short)\n\treturn x, y\n}\n\nfunc _() {\n\tx, y := Short(1, 0)\n\t_, _ = x, y\n}\n\nfunc _() {\n\tvar x, y int\n\tx, y = Short(1, 0)\n\t_, _ = x, y\n}\n\nfunc _() {\n\t_, _ = Short(1, 0)\n}\n-- variadic.go --\npackage a\n\n// We should not offer movement involving variadic parameters if it is not well\n// supported.\n\nfunc Variadic(x int, y ...string) { //@codeaction(\"x\", \"refactor.rewrite.moveParamRight\", err=\"0 CodeActions\"), codeaction(\"y\", \"refactor.rewrite.moveParamLeft\", err=\"0 CodeActions\")\n}\n\nfunc _() {\n\tVariadic(1, \"a\", \"b\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/remove_struct_tags.txt",
    "content": "This test checks the behavior of the 'Remove struct tags' code action without dialogs.\n\n-- flags --\n-ignore_extra_diags\n\n-- removetags.go --\npackage removetags\n\ntype A struct {\n\tx int `json:\"x\"` //@codeaction(\"x\", \"refactor.rewrite.removeTags\", edit=singleline)\n\ty int `json:\"y\"` //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.removeTags\", edit=twolines)\n\tz int `json:\"z\"` //@codeaction(re`()n`, \"refactor.rewrite.removeTags\", edit=entirestruct)\n}\n-- @entirestruct/removetags.go --\n@@ -4,3 +4,3 @@\n-\tx int `json:\"x\"` //@codeaction(\"x\", \"refactor.rewrite.removeTags\", edit=singleline)\n-\ty int `json:\"y\"` //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.removeTags\", edit=twolines)\n-\tz int `json:\"z\"` //@codeaction(re`()n`, \"refactor.rewrite.removeTags\", edit=entirestruct)\n+\tx int //@codeaction(\"x\", \"refactor.rewrite.removeTags\", edit=singleline)\n+\ty int //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.removeTags\", edit=twolines)\n+\tz int //@codeaction(re`()n`, \"refactor.rewrite.removeTags\", edit=entirestruct)\n-- @singleline/removetags.go --\n@@ -4 +4 @@\n-\tx int `json:\"x\"` //@codeaction(\"x\", \"refactor.rewrite.removeTags\", edit=singleline)\n+\tx int //@codeaction(\"x\", \"refactor.rewrite.removeTags\", edit=singleline)\n-- @twolines/removetags.go --\n@@ -5,2 +5,2 @@\n-\ty int `json:\"y\"` //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.removeTags\", edit=twolines)\n-\tz int `json:\"z\"` //@codeaction(re`()n`, \"refactor.rewrite.removeTags\", edit=entirestruct)\n+\ty int //@codeaction(re`(?s)y.*.z int`, \"refactor.rewrite.removeTags\", edit=twolines)\n+\tz int //@codeaction(re`()n`, \"refactor.rewrite.removeTags\", edit=entirestruct)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam.txt",
    "content": "This test exercises the refactoring to remove unused parameters.\nSee removeparam_resolve.txt for same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc A(x, unused int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- @a/a/a.go --\npackage a\n\nfunc A(x int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- a/a2.go --\npackage a\n\nfunc _() {\n\tA(1, 2)\n}\n\n-- a/a_test.go --\npackage a\n\nfunc _() {\n\tA(1, 2)\n}\n\n-- a/a_x_test.go --\npackage a_test\n\nimport \"unused.mod/a\"\n\nfunc _() {\n\ta.A(1, 2)\n}\n\n-- b/b.go --\npackage b\n\nimport \"unused.mod/a\"\n\nfunc f() int {\n\treturn 1\n}\n\nfunc g() int {\n\treturn 2\n}\n\nfunc _() {\n\ta.A(f(), 1)\n}\n\nvar _ = g\n\n-- @a/a/a2.go --\npackage a\n\nfunc _() {\n\tA(1)\n}\n-- @a/a/a_test.go --\npackage a\n\nfunc _() {\n\tA(1)\n}\n-- @a/a/a_x_test.go --\npackage a_test\n\nimport \"unused.mod/a\"\n\nfunc _() {\n\ta.A(1)\n}\n-- @a/b/b.go --\npackage b\n\nimport \"unused.mod/a\"\n\nfunc f() int {\n\treturn 1\n}\n\nfunc g() int {\n\treturn 2\n}\n\nfunc _() {\n\ta.A(f())\n}\n\nvar _ = g\n-- field/field.go --\npackage field\n\nfunc Field(x int, field int) { //@codeaction(\"int\", \"refactor.rewrite.removeUnusedParam\", result=field)\n}\n\nfunc _() {\n\tField(1, 2)\n}\n-- @field/field/field.go --\npackage field\n\nfunc Field(field int) { //@codeaction(\"int\", \"refactor.rewrite.removeUnusedParam\", result=field)\n}\n\nfunc _() {\n\tField(2)\n}\n-- ellipsis/ellipsis.go --\npackage ellipsis\n\nfunc Ellipsis(...any) { //@codeaction(\"any\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis)\n}\n\nfunc _() {\n\t// TODO(rfindley): investigate the broken formatting resulting from these inlinings.\n\tEllipsis()\n\tEllipsis(1)\n\tEllipsis(1, 2)\n\tEllipsis(1, f(), g())\n\tEllipsis(h())\n\tEllipsis(i()...)\n}\n\nfunc f() int\nfunc g() int\nfunc h() (int, int)\nfunc i() []any\n\n-- @ellipsis/ellipsis/ellipsis.go --\npackage ellipsis\n\nfunc Ellipsis() { //@codeaction(\"any\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis)\n}\n\nfunc _() {\n\t// TODO(rfindley): investigate the broken formatting resulting from these inlinings.\n\tEllipsis()\n\tEllipsis()\n\tEllipsis()\n\tEllipsis()\n\tfunc(_ ...any) {\n\t\tEllipsis()\n\t}(h())\n\tEllipsis()\n}\n\nfunc f() int\nfunc g() int\nfunc h() (int, int)\nfunc i() []any\n-- ellipsis2/ellipsis2.go --\npackage ellipsis2\n\nfunc Ellipsis2(_, _ int, rest ...int) { //@codeaction(\"_\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis2)\n}\n\nfunc _() {\n\tEllipsis2(1,2,3)\n\tEllipsis2(h())\n\tEllipsis2(1,2, []int{3, 4}...)\n}\n\nfunc h() (int, int)\n\n-- @ellipsis2/ellipsis2/ellipsis2.go --\npackage ellipsis2\n\nfunc Ellipsis2(_ int, rest ...int) { //@codeaction(\"_\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis2)\n}\n\nfunc _() {\n\tEllipsis2(2, 3)\n\tfunc(_, blank0 int, rest ...int) {\n\t\tEllipsis2(blank0, rest...)\n\t}(h())\n\tEllipsis2(2, []int{3, 4}...)\n}\n\nfunc h() (int, int)\n-- overlapping/overlapping.go --\npackage overlapping\n\nfunc Overlapping(i int) int { //@codeaction(re\"(i) int\", \"refactor.rewrite.removeUnusedParam\", err=re\"overlapping\")\n\treturn 0\n}\n\nfunc _() {\n\tx := Overlapping(Overlapping(0))\n\t_ = x\n}\n\n-- effects/effects.go --\npackage effects\n\nfunc effects(x, y int) int { //@ diag(\"y\", re\"unused\"), codeaction(\"y\", \"refactor.rewrite.removeUnusedParam\", result=effects)\n\treturn x\n}\n\nfunc f() int\nfunc g() int\n\nfunc _() {\n\teffects(f(), g())\n\teffects(f(), g())\n}\n-- @effects/effects/effects.go --\npackage effects\n\nfunc effects(x int) int { //@ diag(\"y\", re\"unused\"), codeaction(\"y\", \"refactor.rewrite.removeUnusedParam\", result=effects)\n\treturn x\n}\n\nfunc f() int\nfunc g() int\n\nfunc _() {\n\teffects(f())\n\teffects(f())\n}\n-- recursive/recursive.go --\npackage recursive\n\nfunc Recursive(x int) int { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=recursive)\n\treturn Recursive(1)\n}\n\n-- @recursive/recursive/recursive.go --\npackage recursive\n\nfunc Recursive() int { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=recursive)\n\treturn Recursive()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_formatting.txt",
    "content": "This test exercises behavior of change signature refactoring with respect to\ncomments.\n\nCurrently, inline comments around arguments or parameters are dropped, which is\nprobably acceptable. Fixing this is likely intractible without fixing comment\nrepresentation in the AST.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\n// A doc comment.\nfunc A(x /* used parameter */, unused int /* unused parameter */ ) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\t// about to return\n\treturn x // returning\n\t// just returned\n}\n\n// This function makes calls.\nfunc _() {\n\t// about to call\n\tA(one() /* used arg */, 2 /* unused arg */) // calling\n\t// just called\n}\n\nfunc one() int {\n\t// I should be unaffected!\n\treturn 1\n}\n\n-- @a/a/a.go --\npackage a\n\n// A doc comment.\nfunc A(x int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\t// about to return\n\treturn x // returning\n\t// just returned\n}\n\n// This function makes calls.\nfunc _() {\n\t// about to call\n\tA(one()) // calling\n\t// just called\n}\n\nfunc one() int {\n\t// I should be unaffected!\n\treturn 1\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_funcvalue.txt",
    "content": "This test exercises change signature refactoring handling of function values.\n\nTODO(rfindley): use a literalization strategy to allow these references.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc A(x, unused int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", err=re\"non-call function reference\")\n\treturn x\n}\n\nfunc _() {\n\t_ = A\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_imports.txt",
    "content": "This test checks the behavior of removing a parameter with respect to various\nimport scenarios.\n\nWholly unused imports are expected to be removed by a subsequent\n\"organize imports\" step.\n\n-- go.mod --\nmodule mod.test\n\ngo 1.21\n\n\n-- a/a1.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan, <-b.Chan)\n}\n\n-- a/a2.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan, <-b.Chan)\n\tb.B(<-b.Chan, <-b.Chan)\n}\n\n-- a/a3.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan, <-b.Chan)\n}\n\nfunc _() {\n\tb.B(<-b.Chan, <-b.Chan)\n}\n\n-- a/a4.go --\npackage a\n\n// TODO(rfindley/adonovan): inlining here adds an additional import of\n// mod.test/b. Can we do better?\nimport (\n\t. \"mod.test/b\"\n)\n\nfunc _() {\n\tB(<-Chan, <-Chan)\n}\n\n-- b/b.go --\npackage b\n\nimport \"mod.test/c\"\n\nvar Chan chan c.C\n\nfunc B(x, y c.C) { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=b)\n}\n\n-- @b/a/a3.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan)\n}\n\nfunc _() {\n\tb.B(<-b.Chan)\n}\n-- @b/a/a2.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan)\n\tb.B(<-b.Chan)\n}\n-- @b/a/a1.go --\npackage a\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tb.B(<-b.Chan)\n}\n-- @b/a/a4.go --\npackage a\n\n// TODO(rfindley/adonovan): inlining here adds an additional import of\n// mod.test/b. Can we do better?\nimport (\n\t\"mod.test/b\"\n\t. \"mod.test/b\"\n)\n\nfunc _() {\n\tb.B(<-Chan)\n}\n-- @b/b/b.go --\npackage b\n\nimport \"mod.test/c\"\n\nvar Chan chan c.C\n\nfunc B(y c.C) { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=b)\n}\n-- c/c.go --\npackage c\n\ntype C int\n\n-- d/d.go --\npackage d\n\n// Removing the parameter should remove this import.\nimport \"mod.test/c\"\n\nfunc D(x c.C) { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=d)\n}\n\nfunc _() {\n\tD(1)\n}\n\n-- @d/d/d.go --\npackage d\n\n// Removing the parameter should remove this import.\n\nfunc D() { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=d)\n}\n\nfunc _() {\n\tD()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_issue65217.txt",
    "content": "This test reproduces condition of golang/go#65217, where the inliner created an\nunnecessary eta abstraction.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype S struct{}\n\nfunc (S) Int() int { return 0 }\n\nfunc _() {\n\tvar s S\n\t_ = f(s, s.Int())\n\tvar j int\n\tj = f(s, s.Int())\n\t_ = j\n}\n\nfunc _() {\n\tvar s S\n\ti := f(s, s.Int())\n\t_ = i\n}\n\nfunc f(unused S, i int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=rewrite), diag(\"unused\", re`unused`)\n\treturn i\n}\n\n-- @rewrite/a/a.go --\npackage a\n\ntype S struct{}\n\nfunc (S) Int() int { return 0 }\n\nfunc _() {\n\tvar s S\n\t_ = f(s.Int())\n\tvar j int\n\tj = f(s.Int())\n\t_ = j\n}\n\nfunc _() {\n\tvar s S\n\ti := f(s.Int())\n\t_ = i\n}\n\nfunc f(i int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=rewrite), diag(\"unused\", re`unused`)\n\treturn i\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_method.txt",
    "content": "This test verifies that gopls can remove unused parameters from methods.\n\nSpecifically, check\n1. basic removal of unused parameters, when the receiver is named, locally and\n   across package boundaries\n2. handling of unnamed receivers\n3. no panics related to references through interface satisfaction\n\n-- go.mod --\nmodule example.com/rm\n\ngo 1.20\n\n-- basic.go --\npackage rm\n\ntype Basic int\n\nfunc (t Basic) Foo(x int) { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=basic)\n}\n\nfunc _(b Basic) {\n\tb.Foo(1)\n\t// TODO(rfindley): methodexprs should not get rewritten as methods.\n\tBasic.Foo(1, 2)\n}\n\n-- basicuse/p.go --\npackage basicuse\n\nimport \"example.com/rm\"\n\nfunc _() {\n\tx := new(rm.Basic)\n\tx.Foo(sideEffects())\n\trm.Basic.Foo(1,2)\n}\n\nfunc sideEffects() int\n\ntype Fooer interface {\n\tFoo(int)\n}\n\n// Dynamic calls aren't rewritten.\n// Previously, this would cause a bug report or crash (golang/go#69896).\nfunc _(f Fooer) {\n\tf.Foo(1)\n}\n\n-- @basic/basic.go --\npackage rm\n\ntype Basic int\n\nfunc (t Basic) Foo() { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=basic)\n}\n\nfunc _(b Basic) {\n\tb.Foo()\n\t// TODO(rfindley): methodexprs should not get rewritten as methods.\n\tBasic(1).Foo()\n}\n-- @basic/basicuse/p.go --\npackage basicuse\n\nimport \"example.com/rm\"\n\nfunc _() {\n\tx := new(rm.Basic)\n\tx.Foo()\n\trm.Basic(1).Foo()\n}\n\nfunc sideEffects() int\n\ntype Fooer interface {\n\tFoo(int)\n}\n\n// Dynamic calls aren't rewritten.\n// Previously, this would cause a bug report or crash (golang/go#69896).\nfunc _(f Fooer) {\n\tf.Foo(1)\n}\n-- missingrecv.go --\npackage rm\n\ntype Missing struct{}\n\nvar R2 int\n\nfunc (Missing) M(a, b, c, r0 int) (r1 int) { //@codeaction(\"b\", \"refactor.rewrite.removeUnusedParam\", result=missingrecv)\n\treturn a + c\n}\n\nfunc _() {\n\tm := &Missing{}\n\t_ = m.M(1, 2, 3, 4)\n}\n\n-- missingrecvuse/p.go --\npackage missingrecvuse\n\nimport \"example.com/rm\"\n\nfunc _() {\n\tx := rm.Missing{}\n\tx.M(1, sideEffects(), 3, 4)\n}\n\nfunc sideEffects() int\n\n-- @missingrecv/missingrecv.go --\npackage rm\n\ntype Missing struct{}\n\nvar R2 int\n\nfunc (Missing) M(a, c, r0 int) (r1 int) { //@codeaction(\"b\", \"refactor.rewrite.removeUnusedParam\", result=missingrecv)\n\treturn a + c\n}\n\nfunc _() {\n\tm := &Missing{}\n\t_ = m.M(1, 3, 4)\n}\n-- @missingrecv/missingrecvuse/p.go --\npackage missingrecvuse\n\nimport \"example.com/rm\"\n\nfunc _() {\n\tx := rm.Missing{}\n\tx.M(1, 3, 4)\n}\n\nfunc sideEffects() int\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_resolve.txt",
    "content": "This test exercises the refactoring to remove unused parameters, with resolve support.\nSee removeparam.txt for same test without resolve support.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc A(x, unused int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- @a/a/a.go --\npackage a\n\nfunc A(x int) int { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", result=a)\n\treturn x\n}\n\n-- a/a2.go --\npackage a\n\nfunc _() {\n\tA(1, 2)\n}\n\n-- a/a_test.go --\npackage a\n\nfunc _() {\n\tA(1, 2)\n}\n\n-- a/a_x_test.go --\npackage a_test\n\nimport \"unused.mod/a\"\n\nfunc _() {\n\ta.A(1, 2)\n}\n\n-- b/b.go --\npackage b\n\nimport \"unused.mod/a\"\n\nfunc f() int {\n\treturn 1\n}\n\nfunc g() int {\n\treturn 2\n}\n\nfunc _() {\n\ta.A(f(), 1)\n}\n\nvar _ = g\n\n-- @a/a/a2.go --\npackage a\n\nfunc _() {\n\tA(1)\n}\n-- @a/a/a_test.go --\npackage a\n\nfunc _() {\n\tA(1)\n}\n-- @a/a/a_x_test.go --\npackage a_test\n\nimport \"unused.mod/a\"\n\nfunc _() {\n\ta.A(1)\n}\n-- @a/b/b.go --\npackage b\n\nimport \"unused.mod/a\"\n\nfunc f() int {\n\treturn 1\n}\n\nfunc g() int {\n\treturn 2\n}\n\nfunc _() {\n\ta.A(f())\n}\n\nvar _ = g\n-- field/field.go --\npackage field\n\nfunc Field(x int, field int) { //@codeaction(\"int\", \"refactor.rewrite.removeUnusedParam\", result=field)\n}\n\nfunc _() {\n\tField(1, 2)\n}\n-- @field/field/field.go --\npackage field\n\nfunc Field(field int) { //@codeaction(\"int\", \"refactor.rewrite.removeUnusedParam\", result=field)\n}\n\nfunc _() {\n\tField(2)\n}\n-- ellipsis/ellipsis.go --\npackage ellipsis\n\nfunc Ellipsis(...any) { //@codeaction(\"any\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis)\n}\n\nfunc _() {\n\t// TODO(rfindley): investigate the broken formatting resulting from these inlinings.\n\tEllipsis()\n\tEllipsis(1)\n\tEllipsis(1, 2)\n\tEllipsis(1, f(), g())\n\tEllipsis(h())\n\tEllipsis(i()...)\n}\n\nfunc f() int\nfunc g() int\nfunc h() (int, int)\nfunc i() []any\n\n-- @ellipsis/ellipsis/ellipsis.go --\npackage ellipsis\n\nfunc Ellipsis() { //@codeaction(\"any\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis)\n}\n\nfunc _() {\n\t// TODO(rfindley): investigate the broken formatting resulting from these inlinings.\n\tEllipsis()\n\tEllipsis()\n\tEllipsis()\n\tEllipsis()\n\tfunc(_ ...any) {\n\t\tEllipsis()\n\t}(h())\n\tEllipsis()\n}\n\nfunc f() int\nfunc g() int\nfunc h() (int, int)\nfunc i() []any\n-- ellipsis2/ellipsis2.go --\npackage ellipsis2\n\nfunc Ellipsis2(_, _ int, rest ...int) { //@codeaction(\"_\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis2)\n}\n\nfunc _() {\n\tEllipsis2(1,2,3)\n\tEllipsis2(h())\n\tEllipsis2(1,2, []int{3, 4}...)\n}\n\nfunc h() (int, int)\n\n-- @ellipsis2/ellipsis2/ellipsis2.go --\npackage ellipsis2\n\nfunc Ellipsis2(_ int, rest ...int) { //@codeaction(\"_\", \"refactor.rewrite.removeUnusedParam\", result=ellipsis2)\n}\n\nfunc _() {\n\tEllipsis2(2, 3)\n\tfunc(_, blank0 int, rest ...int) {\n\t\tEllipsis2(blank0, rest...)\n\t}(h())\n\tEllipsis2(2, []int{3, 4}...)\n}\n\nfunc h() (int, int)\n-- overlapping/overlapping.go --\npackage overlapping\n\nfunc Overlapping(i int) int { //@codeaction(re\"(i) int\", \"refactor.rewrite.removeUnusedParam\", err=re\"overlapping\")\n\treturn 0\n}\n\nfunc _() {\n\tx := Overlapping(Overlapping(0))\n\t_ = x\n}\n\n-- effects/effects.go --\npackage effects\n\nfunc effects(x, y int) int { //@codeaction(\"y\", \"refactor.rewrite.removeUnusedParam\", result=effects), diag(\"y\", re\"unused\")\n\treturn x\n}\n\nfunc f() int\nfunc g() int\n\nfunc _() {\n\teffects(f(), g())\n\teffects(f(), g())\n}\n-- @effects/effects/effects.go --\npackage effects\n\nfunc effects(x int) int { //@codeaction(\"y\", \"refactor.rewrite.removeUnusedParam\", result=effects), diag(\"y\", re\"unused\")\n\treturn x\n}\n\nfunc f() int\nfunc g() int\n\nfunc _() {\n\teffects(f())\n\teffects(f())\n}\n-- recursive/recursive.go --\npackage recursive\n\nfunc Recursive(x int) int { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=recursive)\n\treturn Recursive(1)\n}\n\n-- @recursive/recursive/recursive.go --\npackage recursive\n\nfunc Recursive() int { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=recursive)\n\treturn Recursive()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_satisfies.txt",
    "content": "This test verifies that gopls can remove unused parameters from methods,\nwhen that method satisfies an interface.\n\nFor now, we just update static calls. In the future, we should compute the set\nof dynamic calls that must change (and therefore, the set of concrete functions\nthat must be modified), in order to produce the desired outcome for our users.\n\nDoing so would be more complicated, so for now this test simply records the\ncurrent behavior.\n\n-- go.mod --\nmodule example.com/rm\n\ngo 1.20\n\n-- p.go --\npackage rm\n\ntype T int\n\nfunc (t T) Foo(x int) { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=basic)\n}\n\n-- @basic/p.go --\npackage rm\n\ntype T int\n\nfunc (t T) Foo() { //@codeaction(\"x\", \"refactor.rewrite.removeUnusedParam\", result=basic)\n}\n\n-- @basic/use/use.go --\npackage use\n\nimport \"example.com/rm\"\n\ntype Fooer interface {\n\tFoo(int)\n}\n\nvar _ Fooer = rm.T(0)\n\nfunc _() {\n\tvar x rm.T\n\tx.Foo()\n}\n-- use/use.go --\npackage use\n\nimport \"example.com/rm\"\n\ntype Fooer interface{\n\tFoo(int)\n}\n\nvar _ Fooer = rm.T(0)\n\nfunc _() {\n\tvar x rm.T\n\tx.Foo(1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/removeparam_witherrs.txt",
    "content": "This test checks that we can't remove parameters for packages with errors.\n\n-- p.go --\npackage p\n\nfunc foo(unused int) { //@codeaction(\"unused\", \"refactor.rewrite.removeUnusedParam\", err=re\"found 0\")\n}\n\nfunc _() {\n\tfoo(\"\") //@diag(`\"\"`, re\"cannot use\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/splitlines-variadic.txt",
    "content": "This is a regression test for #70519, in which the ellipsis\nof a variadic call would go missing after split/join lines.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nvar a, b, c []any\nfunc f(any, any, ...any)\n\nfunc _() {\n\tf(a, b, c...) //@codeaction(\"a\", \"refactor.rewrite.splitLines\", result=split)\n\n\tf(\n\t\ta,\n\t\tb,\n\t\tc..., /*@codeaction(\"c\", \"refactor.rewrite.joinLines\", result=joined)*/\n\t)\n}\n\n-- @split/a/a.go --\npackage a\n\nvar a, b, c []any\nfunc f(any, any, ...any)\n\nfunc _() {\n\tf(\n\t\ta,\n\t\tb,\n\t\tc...,\n\t) //@codeaction(\"a\", \"refactor.rewrite.splitLines\", result=split)\n\n\tf(\n\t\ta,\n\t\tb,\n\t\tc..., /*@codeaction(\"c\", \"refactor.rewrite.joinLines\", result=joined)*/\n\t)\n}\n\n-- @joined/a/a.go --\npackage a\n\nvar a, b, c []any\nfunc f(any, any, ...any)\n\nfunc _() {\n\tf(a, b, c...) //@codeaction(\"a\", \"refactor.rewrite.splitLines\", result=split)\n\n\tf(a, b, c..., /*@codeaction(\"c\", \"refactor.rewrite.joinLines\", result=joined)*/)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codeaction/splitlines.txt",
    "content": "This test exercises the refactoring of putting arguments, results, and composite literal elements\ninto separate lines.\n\n-- go.mod --\nmodule unused.mod\n\ngo 1.18\n\n-- func_arg/func_arg.go --\npackage func_arg\n\nfunc A(a string, b, c int64, x int, y int) (r1 string, r2, r3 int64, r4 int, r5 int) { //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=func_arg)\n\treturn a, b, c, x, y\n}\n\n-- @func_arg/func_arg/func_arg.go --\npackage func_arg\n\nfunc A(\n\ta string,\n\tb, c int64,\n\tx int,\n\ty int,\n) (r1 string, r2, r3 int64, r4 int, r5 int) { //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=func_arg)\n\treturn a, b, c, x, y\n}\n\n-- func_ret/func_ret.go --\npackage func_ret\n\nfunc A(a string, b, c int64, x int, y int) (r1 string, r2, r3 int64, r4 int, r5 int) { //@codeaction(\"r1\", \"refactor.rewrite.splitLines\", result=func_ret)\n\treturn a, b, c, x, y\n}\n\n-- @func_ret/func_ret/func_ret.go --\npackage func_ret\n\nfunc A(a string, b, c int64, x int, y int) (\n\tr1 string,\n\tr2, r3 int64,\n\tr4 int,\n\tr5 int,\n) { //@codeaction(\"r1\", \"refactor.rewrite.splitLines\", result=func_ret)\n\treturn a, b, c, x, y\n}\n\n-- functype_arg/functype_arg.go --\npackage functype_arg\n\ntype A func(a string, b, c int64, x int, y int) (r1 string, r2, r3 int64, r4 int, r5 int) //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=functype_arg)\n\n-- @functype_arg/functype_arg/functype_arg.go --\npackage functype_arg\n\ntype A func(\n\ta string,\n\tb, c int64,\n\tx int,\n\ty int,\n) (r1 string, r2, r3 int64, r4 int, r5 int) //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=functype_arg)\n\n-- functype_ret/functype_ret.go --\npackage functype_ret\n\ntype A func(a string, b, c int64, x int, y int) (r1 string, r2, r3 int64, r4 int, r5 int) //@codeaction(\"r1\", \"refactor.rewrite.splitLines\", result=functype_ret)\n\n-- @functype_ret/functype_ret/functype_ret.go --\npackage functype_ret\n\ntype A func(a string, b, c int64, x int, y int) (\n\tr1 string,\n\tr2, r3 int64,\n\tr4 int,\n\tr5 int,\n) //@codeaction(\"r1\", \"refactor.rewrite.splitLines\", result=functype_ret)\n\n-- func_call/func_call.go --\npackage func_call\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(1, 2, 3, fmt.Sprintf(\"hello %d\", 4)) //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=func_call)\n}\n\n-- @func_call/func_call/func_call.go --\npackage func_call\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(\n\t\t1,\n\t\t2,\n\t\t3,\n\t\tfmt.Sprintf(\"hello %d\", 4),\n\t) //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=func_call)\n}\n\n-- indent/indent.go --\npackage indent\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(1, 2, 3, fmt.Sprintf(\"hello %d\", 4)) //@codeaction(\"hello\", \"refactor.rewrite.splitLines\", result=indent)\n}\n\n-- @indent/indent/indent.go --\npackage indent\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.Println(1, 2, 3, fmt.Sprintf(\n\t\t\"hello %d\",\n\t\t4,\n\t)) //@codeaction(\"hello\", \"refactor.rewrite.splitLines\", result=indent)\n}\n\n-- indent2/indent2.go --\npackage indent2\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.\n\t\tPrintln(1, 2, 3, fmt.Sprintf(\"hello %d\", 4)) //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=indent2)\n}\n\n-- @indent2/indent2/indent2.go --\npackage indent2\n\nimport \"fmt\"\n\nfunc F() {\n\tfmt.\n\t\tPrintln(\n\t\t\t1,\n\t\t\t2,\n\t\t\t3,\n\t\t\tfmt.Sprintf(\"hello %d\", 4),\n\t\t) //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=indent2)\n}\n\n-- structelts/structelts.go --\npackage structelts\n\ntype A struct{\n\ta int\n\tb int\n}\n\nfunc F() {\n\t_ = A{a: 1, b: 2} //@codeaction(\"b\", \"refactor.rewrite.splitLines\", result=structelts)\n}\n\n-- @structelts/structelts/structelts.go --\npackage structelts\n\ntype A struct{\n\ta int\n\tb int\n}\n\nfunc F() {\n\t_ = A{\n\t\ta: 1,\n\t\tb: 2,\n\t} //@codeaction(\"b\", \"refactor.rewrite.splitLines\", result=structelts)\n}\n\n-- sliceelts/sliceelts.go --\npackage sliceelts\n\nfunc F() {\n\t_ = []int{1, 2} //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=sliceelts)\n}\n\n-- @sliceelts/sliceelts/sliceelts.go --\npackage sliceelts\n\nfunc F() {\n\t_ = []int{\n\t\t1,\n\t\t2,\n\t} //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=sliceelts)\n}\n\n-- mapelts/mapelts.go --\npackage mapelts\n\nfunc F() {\n\t_ = map[string]int{\"a\": 1, \"b\": 2} //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=mapelts)\n}\n\n-- @mapelts/mapelts/mapelts.go --\npackage mapelts\n\nfunc F() {\n\t_ = map[string]int{\n\t\t\"a\": 1,\n\t\t\"b\": 2,\n\t} //@codeaction(\"1\", \"refactor.rewrite.splitLines\", result=mapelts)\n}\n\n-- starcomment/starcomment.go --\npackage starcomment\n\nfunc A(/*1*/ x /*2*/ string /*3*/, /*4*/ y /*5*/ int /*6*/) (string, int) { //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=starcomment)\n\treturn x, y\n}\n\n-- @starcomment/starcomment/starcomment.go --\npackage starcomment\n\nfunc A(\n\t/*1*/ x /*2*/ string /*3*/,\n\t/*4*/ y /*5*/ int /*6*/,\n) (string, int) { //@codeaction(\"x\", \"refactor.rewrite.splitLines\", result=starcomment)\n\treturn x, y\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codelens/generate.txt",
    "content": "This test exercises the \"generate\" codelens.\n\n-- generate.go --\n//@codelenses()\n\npackage generate\n\n//go:generate echo Hi //@ codelens(\"//go:generate\", \"run go generate\"), codelens(\"//go:generate\", \"run go generate ./...\")\n//go:generate echo I shall have no CodeLens\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/codelens/test.txt",
    "content": "This file tests codelenses for test functions.\n\nTODO: for some reason these code lens have zero width. Does that affect their\nutility/visibility in various LSP clients?\n\n-- settings.json --\n{\n\t\"codelenses\": {\n\t\t\"test\": true\n\t}\n}\n\n-- p_test.go --\n//@codelenses()\n\npackage codelens //@codelens(re\"()package codelens\", \"run file benchmarks\")\n\nimport \"testing\"\n\nfunc TestMain(m *testing.M) {} // no code lens for TestMain\n\nfunc TestFuncWithCodeLens(t *testing.T) { //@codelens(re\"()func\", \"run test\")\n}\n\nfunc thisShouldNotHaveACodeLens(t *testing.T) { //@diag(\"t \", re\"unused parameter\")\n\tprintln() // nonempty body => \"unused parameter\"\n}\n\nfunc BenchmarkFuncWithCodeLens(b *testing.B) { //@codelens(re\"()func\", \"run benchmark\")\n}\n\nfunc helper() {} // expect no code lens\n\nfunc _() {\n\t// pacify unusedfunc\n\tthisShouldNotHaveACodeLens(nil)\n\thelper()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/address.txt",
    "content": "This test exercises the reference and dereference completion modifiers.\n\nTODO: remove the need to set \"literalCompletions\" here, as this is one of the\nfew places this setting is needed.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- address/address.go --\npackage address\n\nfunc wantsPtr(*int)            {}\nfunc wantsVariadicPtr(...*int) {}\n\nfunc wantsVariadic(...int) {}\n\ntype foo struct{ c int } //@item(addrFieldC, \"c\", \"int\", \"field\")\n\nfunc _() {\n\tvar (\n\t\ta string //@item(addrA, \"a\", \"string\", \"var\")\n\t\tb int    //@item(addrB, \"b\", \"int\", \"var\")\n\t)\n\n\twantsPtr()   //@rank(re\"()\\\\)\", addrB, addrA),snippet(re\"()\\\\)\", addrB, \"&b\")\n\twantsPtr(&b) //@snippet(re\"()\\\\)\", addrB, \"b\")\n\n\twantsVariadicPtr() //@rank(re\"()\\\\)\", addrB, addrA),snippet(re\"()\\\\)\", addrB, \"&b\")\n\n\tvar s foo\n\ts.c          //@item(addrDeepC, \"s.c\", \"int\", \"field\")\n\twantsPtr()   //@snippet(re\"()\\\\)\", addrDeepC, \"&s.c\")\n\twantsPtr(s)  //@snippet(re\"()\\\\)\", addrDeepC, \"&s.c\")\n\twantsPtr(&s) //@snippet(re\"()\\\\)\", addrDeepC, \"s.c\")\n\n\t// don't add \"&\" in item (it gets added as an additional edit)\n\twantsPtr(&s.c) //@snippet(re\"()\\\\)\", addrFieldC, \"c\")\n\n\t// check dereferencing as well\n\tvar c *int    //@item(addrCPtr, \"c\", \"*int\", \"var\")\n\tvar _ int = _ //@rank(re\"= ()\", addrCPtr, addrA),snippet(re\"= ()\", addrCPtr, \"*c\")\n\n\twantsVariadic() //@rank(re\"()\\\\)\", addrCPtr, addrA),snippet(re\"()\\\\)\", addrCPtr, \"*c\")\n\n\tvar d **int   //@item(addrDPtr, \"d\", \"**int\", \"var\")\n\tvar _ int = _ //@rank(re\"= ()\", addrDPtr, addrA),snippet(re\"= ()\", addrDPtr, \"**d\")\n\n\ttype namedPtr *int\n\tvar np namedPtr //@item(addrNamedPtr, \"np\", \"namedPtr\", \"var\")\n\n\tvar _ int = _ //@rank(re\"= ()\", addrNamedPtr, addrA)\n\n\t// don't get tripped up by recursive pointer type\n\ttype dontMessUp *dontMessUp //@item(dontMessUp, \"dontMessUp\", \"*dontMessUp\", \"type\")\n\tvar dmu *dontMessUp //@item(addrDMU, \"dmu\", \"*dontMessUp\", \"var\")\n\n\tvar _ int = dmu //@complete(re\"dmu()\", addrDMU, dontMessUp)\n}\n\nfunc (f foo) ptr() *foo { return &f }\n\nfunc _() {\n\tgetFoo := func() foo { return foo{} }\n\n\t// not addressable\n\tgetFoo().c //@item(addrGetFooC, \"getFoo().c\", \"int\", \"field\")\n\n\t// addressable\n\tgetFoo().ptr().c //@item(addrGetFooPtrC, \"getFoo().ptr().c\", \"int\", \"field\")\n\n\twantsPtr()   //@snippet(re\"()\\\\)\", addrGetFooPtrC, \"&getFoo().ptr().c\")\n\twantsPtr(&g) //@snippet(re\"()\\\\)\", addrGetFooPtrC, \"getFoo().ptr().c\")\n}\n\ntype nested struct {\n\tf foo\n}\n\nfunc _() {\n\tgetNested := func() nested { return nested{} }\n\n\tgetNested().f.c       //@item(addrNestedC, \"getNested().f.c\", \"int\", \"field\")\n\tgetNested().f.ptr().c //@item(addrNestedPtrC, \"getNested().f.ptr().c\", \"int\", \"field\")\n\n\t// addrNestedC is not addressable, so rank lower\n\twantsPtr(getNestedfc) //@complete(re\"()\\\\)\", addrNestedPtrC, addrNestedC)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/alias.txt",
    "content": "This test checks completion related to aliases.\n\n-- flags --\n-ignore_extra_diags\n\n-- aliases.go --\npackage aliases\n\n// Copied from the old builtins.go, which has been ported to the new marker tests.\n/* string */ //@item(string, \"string\", \"\", \"type\")\n/* int */ //@item(int, \"int\", \"\", \"type\")\n/* float32 */ //@item(float32, \"float32\", \"\", \"type\")\n/* float64 */ //@item(float64, \"float64\", \"\", \"type\")\n\ntype p struct{}\n\ntype s[a int | string] = p\n\nfunc _() {\n\ts[]{} //@rank(re\"()]\", int, float64)\n}\n\nfunc takesGeneric[a int | string](s[a]) {\n\t\"s[a]{}\" //@item(tpInScopeLit, \"s[a]{}\", \"\", \"var\")\n\ttakesGeneric() //@rank(re\"()\\\\)\", tpInScopeLit),snippet(re\"()\\\\)\", tpInScopeLit, \"s[a]{\\\\}\")\n}\n\nfunc _() {\n\ts[int]{} //@item(tpInstLit, \"s[int]{}\", \"\", \"var\")\n\ttakesGeneric[int]() //@rank(re\"()\\\\)\", tpInstLit),snippet(re\"()\\\\)\", tpInstLit, \"s[int]{\\\\}\")\n\n\t\"s[...]{}\" //@item(tpUninstLit, \"s[...]{}\", \"\", \"var\")\n\ttakesGeneric() //@rank(re\"()\\\\)\", tpUninstLit),snippet(re\"()\\\\)\", tpUninstLit, \"s[${1:}]{\\\\}\")\n}\n\n\ntype myType int //@item(flType, \"myType\", \"int\", \"type\")\n\ntype myt[T int] myType //@item(aflType, \"myt[T]\", \"int\", \"type\")\n\nfunc (my myt) _() {} //@complete(re\"()\\\\) _\", flType, aflType)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/anon.txt",
    "content": "This test checks completion related to anonymous structs.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"deepCompletion\": false\n}\n\n-- anon.go --\npackage anon\n\n// Literal completion results.\n/* int() */ //@item(int, \"int()\", \"int\", \"var\")\n\nfunc _() {\n\tfor _, _ := range []struct {\n\t\ti, j int //@item(anonI, \"i\", \"int\", \"field\"),item(anonJ, \"j\", \"int\", \"field\")\n\t}{\n\t\t{\n\t\t\ti: 1,\n\t\t\t//@complete(\"\", anonJ)\n\t\t},\n\t\t{\n\t\t\t//@complete(\"\", anonI, anonJ, int)\n\t\t},\n\t} {\n\t\tcontinue\n\t}\n\n\ts := struct{ f int }{  } //@item(anonF, \"f\", \"int\", \"field\"),item(structS, \"s\", \"struct{...}\", \"var\"),complete(re\"()  }\", anonF, int)\n\n\t_ = map[struct{ x int }]int{ //@item(anonX, \"x\", \"int\", \"field\")\n\t\tstruct{ x int }{  }: 1, //@complete(re\"()  }\", anonX, int, structS)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/append.txt",
    "content": "This test checks behavior of completion within append expressions.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/append\n\ngo 1.18\n\n-- append.go --\npackage append\n\nfunc foo([]string)  {}\nfunc bar(...string) {}\n\nfunc _() {\n\tvar (\n\t\taInt     []int    //@item(appendInt, \"aInt\", \"[]int\", \"var\")\n\t\taStrings []string //@item(appendStrings, \"aStrings\", \"[]string\", \"var\")\n\t\taString  string   //@item(appendString, \"aString\", \"string\", \"var\")\n\t)\n\n\tappend(aStrings, a)                     //@rank(re\"()\\\\)\", appendString, appendInt)\n\tvar _ any = append(aStrings, a) //@rank(re\"()\\\\)\", appendString, appendInt)\n\tvar _ []string = append(oops, a)        //@rank(re\"()\\\\)\", appendString, appendInt)\n\n\tfoo(append())                  //@rank(re\"()\\\\)\\\\)\", appendStrings, appendInt),rank(re\"()\\\\)\\\\)\", appendStrings, appendString)\n\tfoo(append([]string{}, a))     //@rank(re\"()\\\\)\\\\)\", appendStrings, appendInt),rank(re\"()\\\\)\\\\)\", appendString, appendInt),snippet(re\"()\\\\)\\\\)\", appendStrings, \"aStrings...\")\n\tfoo(append([]string{}, \"\", a)) //@rank(re\"()\\\\)\\\\)\", appendString, appendInt),rank(re\"()\\\\)\\\\)\", appendString, appendStrings)\n\n\t// Don't add \"...\" to append() argument.\n\tbar(append()) //@snippet(re\"()\\\\)\\\\)\", appendStrings, \"aStrings\")\n\n\ttype baz struct{}\n\tbaz{}                       //@item(appendBazLiteral, \"baz{}\", \"\", \"var\")\n\tvar bazzes []baz            //@item(appendBazzes, \"bazzes\", \"[]baz\", \"var\")\n\tvar bazzy baz               //@item(appendBazzy, \"bazzy\", \"baz\", \"var\")\n\tbazzes = append(bazzes, ba) //@rank(re\"()\\\\)\", appendBazzy, appendBazLiteral, appendBazzes)\n\n\tvar b struct{ b []baz }\n\tb.b                  //@item(appendNestedBaz, \"b.b\", \"[]baz\", \"field\")\n\tb.b = append(b.b, b) //@rank(re\"()\\\\)\", appendBazzy, appendBazLiteral, appendNestedBaz)\n\n\tvar aStringsPtr *[]string  //@item(appendStringsPtr, \"aStringsPtr\", \"*[]string\", \"var\")\n\tfoo(append([]string{}, a)) //@snippet(re\"()\\\\)\\\\)\", appendStringsPtr, \"*aStringsPtr...\")\n\n\tfoo(append([]string{}, *a)) //@snippet(re\"()\\\\)\\\\)\", appendStringsPtr, \"aStringsPtr...\")\n}\n\n-- append2.go --\npackage append\n\nfunc _() {\n\t_ = append(a, struct) //@complete(re\"()\\\\)\", structs)\n}\n\n//@item(structs, \"structs\", `\"structs\"`)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/assign.txt",
    "content": "This test checks that completion considers assignability when ranking results.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/assign\n\ngo 1.18\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- assign.go --\npackage assign\n\nimport \"golang.org/lsptests/assign/internal/secret\"\n\nfunc _() {\n\tsecret.Hello()\n\tvar (\n\t\tmyInt int //@item(assignInt, \"myInt\", \"int\", \"var\")\n\t\tmyStr string //@item(assignStr, \"myStr\", \"string\", \"var\")\n\t)\n\n\tvar _ string = my //@rank(re\"() \\\\/\\\\/\", assignStr, assignInt)\n\tvar _ string = //@rank(re\"() \\\\/\\\\/\", assignStr, assignInt)\n}\n\nfunc _() {\n\tvar a string = a //@complete(re\"() \\\\/\\\\/\")\n}\n\nfunc _() {\n\tfooBar := fooBa //@complete(re\"() \\\\/\\\\/\"),item(assignFooBar, \"fooBar\", \"\", \"var\")\n\tabc, fooBar := 123, fooBa //@complete(re\"() \\\\/\\\\/\", assignFooBar)\n\t{\n\t\tfooBar := fooBa //@complete(re\"() \\\\/\\\\/\", assignFooBar)\n\t}\n}\n\n-- internal/secret/secret.go --\npackage secret\n\nfunc Hello() {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/bad.txt",
    "content": "This test exercises completion in the presence of type errors.\n\nNote: this test was ported from the old marker tests, which did not enable\nunimported completion. Enabling it causes matches in e.g. crypto/rand.\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- go.mod --\nmodule bad.test\n\ngo 1.18\n\n-- bad/bad0.go --\npackage bad\n\nfunc stuff() { //@item(stuff, \"stuff\", \"func()\", \"func\")\n\tx := \"heeeeyyyy\"\n\trandom2(x) //@diag(\"x\", re\"cannot use x \\\\(variable of type string\\\\) as int value in argument to random2\")\n\trandom2(1) //@complete(re\"()dom\", random, random2, random3)\n\ty := 3     //@diag(\"y\", re\"declared (and|but) not used\")\n}\n\ntype bob struct { //@item(bob, \"bob\", \"struct{...}\", \"struct\")\n\tx int\n}\n\nfunc _() {\n\tvar q int\n\t_ = &bob{\n\t\tf: q, //@diag(\"f: q\", re\"unknown field f in struct literal\")\n\t}\n}\n\n-- bad/bad1.go --\npackage bad\n\n// See #36637\ntype stateFunc func() stateFunc //@item(stateFunc, \"stateFunc\", \"func() stateFunc\", \"type\")\n\nvar a unknown //@item(global_a, \"a\", \"unknown\", \"var\"),diag(\"unknown\", re\"(undeclared name|undefined): unknown\")\n\nfunc random() int { //@item(random, \"random\", \"func() int\", \"func\")\n\t//@complete(\"\", global_a, bob, random, random2, random3, stateFunc, stuff)\n\treturn 0\n}\n\nfunc random2(y int) int { //@item(random2, \"random2\", \"func(y int) int\", \"func\"),item(bad_y_param, \"y\", \"int\", \"var\")\n\tx := 6       //@item(x, \"x\", \"int\", \"var\"),diag(\"x\", re\"declared (and|but) not used\")\n\tvar q blah   //@item(q, \"q\", \"blah\", \"var\"),diag(\"q\", re\"declared (and|but) not used\"),diag(\"blah\", re\"(undeclared name|undefined): blah\")\n\tvar t **blob //@item(t, \"t\", \"**blob\", \"var\"),diag(\"t\", re\"declared (and|but) not used\"),diag(\"blob\", re\"(undeclared name|undefined): blob\")\n\t//@complete(\"\", q, t, x, bad_y_param, global_a, bob, random, random2, random3, stateFunc, stuff)\n\n\treturn y\n}\n\nfunc random3(y ...int) { //@item(random3, \"random3\", \"func(y ...int)\", \"func\"),item(y_variadic_param, \"y\", \"[]int\", \"var\")\n\t//@complete(\"\", y_variadic_param, global_a, bob, random, random2, random3, stateFunc, stuff)\n\n\tvar ch chan (favType1)   //@item(ch, \"ch\", \"chan (favType1)\", \"var\"),diag(\"ch\", re\"declared (and|but) not used\"),diag(\"favType1\", re\"(undeclared name|undefined): favType1\")\n\tvar m map[keyType]int    //@item(m, \"m\", \"map[keyType]int\", \"var\"),diag(\"m\", re\"declared (and|but) not used\"),diag(\"keyType\", re\"(undeclared name|undefined): keyType\")\n\tvar arr []favType2       //@item(arr, \"arr\", \"[]favType2\", \"var\"),diag(\"arr\", re\"declared (and|but) not used\"),diag(\"favType2\", re\"(undeclared name|undefined): favType2\")\n\tvar fn1 func() badResult //@item(fn1, \"fn1\", \"func() badResult\", \"var\"),diag(\"fn1\", re\"declared (and|but) not used\"),diag(\"badResult\", re\"(undeclared name|undefined): badResult\")\n\tvar fn2 func(badParam)   //@item(fn2, \"fn2\", \"func(badParam)\", \"var\"),diag(\"fn2\", re\"declared (and|but) not used\"),diag(\"badParam\", re\"(undeclared name|undefined): badParam\")\n\t//@complete(\"\", arr, ch, fn1, fn2, m, y_variadic_param, global_a, bob, random, random2, random3, stateFunc, stuff)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/basic_lit.txt",
    "content": "This test checks completion related to basic literals.\n\n-- flags --\n-ignore_extra_diags\n\n-- basiclit.go --\npackage basiclit\n\nfunc _() {\n\tvar a int // something for lexical completions\n\n\t_ = \"hello.\" //@complete(re\"()\\\\.\")\n\n\t_ = 1 //@complete(re\"() \\\\/\\\\/\")\n\n\t_ = 1. //@complete(re\"()\\\\.\")\n\n\t_ = 'a' //@complete(re\"()\\\\' \")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/builtins.txt",
    "content": "This test checks completion of Go builtins.\n\n-- flags --\n-ignore_extra_diags\n-filter_builtins=false\n\n-- builtin_args.go --\npackage builtins\n\nfunc _() {\n\tvar (\n\t\taSlice    []int          //@item(builtinSlice, \"aSlice\", \"[]int\", \"var\")\n\t\taMap      map[string]int //@item(builtinMap, \"aMap\", \"map[string]int\", \"var\")\n\t\taString   string         //@item(builtinString, \"aString\", \"string\", \"var\")\n\t\taArray    [0]int         //@item(builtinArray, \"aArray\", \"[0]int\", \"var\")\n\t\taArrayPtr *[0]int        //@item(builtinArrayPtr, \"aArrayPtr\", \"*[0]int\", \"var\")\n\t\taChan     chan int       //@item(builtinChan, \"aChan\", \"chan int\", \"var\")\n\t\taPtr      *int           //@item(builtinPtr, \"aPtr\", \"*int\", \"var\")\n\t\taInt      int            //@item(builtinInt, \"aInt\", \"int\", \"var\")\n\t)\n\n\ttype (\n\t\taSliceType []int          //@item(builtinSliceType, \"aSliceType\", \"[]int\", \"type\")\n\t\taChanType  chan int       //@item(builtinChanType, \"aChanType\", \"chan int\", \"type\")\n\t\taMapType   map[string]int //@item(builtinMapType, \"aMapType\", \"map[string]int\", \"type\")\n\t)\n\n\tclose() //@rank(re\"()\\\\)\", builtinChan, builtinSlice)\n\n\tappend() //@rank(re\"()\\\\)\", builtinSlice, builtinChan)\n\n\tvar _ []byte = append([]byte(nil), \"\"...) //@rank(re\"()\\\\) \\\\/\\\\/\")\n\n\tcopy()           //@rank(re\"()\\\\)\", builtinSlice, builtinChan)\n\tcopy(aSlice, aS) //@rank(re\"()\\\\)\", builtinSlice, builtinString)\n\tcopy(aS, aSlice) //@rank(re\"(),\", builtinSlice, builtinString)\n\n\tdelete()         //@rank(re\"()\\\\)\", builtinMap, builtinChan)\n\tdelete(aMap, aS) //@rank(re\"()\\\\)\", builtinString, builtinSlice)\n\n\taMapFunc := func() map[int]int { //@item(builtinMapFunc, \"aMapFunc\", \"func() map[int]int\", \"var\")\n\t\treturn nil\n\t}\n\tdelete() //@rank(re\"()\\\\)\", builtinMapFunc, builtinSlice)\n\n\tlen() //@rank(re\"()\\\\)\", builtinSlice, builtinInt),rank(re\"()\\\\)\", builtinMap, builtinInt),rank(re\"()\\\\)\", builtinString, builtinInt),rank(re\"()\\\\)\", builtinArray, builtinInt),rank(re\"()\\\\)\", builtinArrayPtr, builtinPtr),rank(re\"()\\\\)\", builtinChan, builtinInt)\n\n\tcap() //@rank(re\"()\\\\)\", builtinSlice, builtinMap),rank(re\"()\\\\)\", builtinArray, builtinString),rank(re\"()\\\\)\", builtinArrayPtr, builtinPtr),rank(re\"()\\\\)\", builtinChan, builtinInt)\n\n\tmake()              //@rank(re\"()\\\\)\", builtinMapType, int),rank(re\"()\\\\)\", builtinChanType, int),rank(re\"()\\\\)\", builtinSliceType, int),rank(re\"()\\\\)\", builtinMapType, int)\n\tmake(aSliceType, a) //@rank(re\"()\\\\)\", builtinInt, builtinSlice)\n\n\ttype myInt int\n\tvar mi myInt        //@item(builtinMyInt, \"mi\", \"myInt\", \"var\")\n\tmake(aSliceType, m) //@snippet(re\"()\\\\)\", builtinMyInt, \"mi\")\n\n\tvar _ []int = make() //@rank(re\"()\\\\)\", builtinSliceType, builtinMapType)\n\n\ttype myStruct struct{}  //@item(builtinStructType, \"myStruct\", \"struct{...}\", \"struct\")\n\tvar _ *myStruct = new() //@rank(re\"()\\\\)\", builtinStructType, int)\n\n\tfor k := range a { //@rank(re\"() {\", builtinSlice, builtinInt),rank(re\"() {\", builtinString, builtinInt),rank(re\"() {\", builtinChan, builtinInt),rank(re\"() {\", builtinArray, builtinInt),rank(re\"() {\", builtinArrayPtr, builtinInt),rank(re\"() {\", builtinMap, builtinInt),\n\t}\n\n\tfor k, v := range a { //@rank(re\"() {\", builtinSlice, builtinChan)\n\t}\n\n\t<-a //@rank(re\"() \\\\/\\\\/\", builtinChan, builtinInt)\n}\n\n-- builtin_types.go --\npackage builtins\n\nfunc _() {\n\tvar _ []bool //@item(builtinBoolSliceType, \"[]bool\", \"[]bool\", \"type\")\n\n\tvar _ []bool = make() //@rank(re\"()\\\\)\", builtinBoolSliceType, int)\n\n\tvar _ []bool = make([], 0) //@rank(re\"(),\", bool, int)\n\n\tvar _ [][]bool = make([][], 0) //@rank(re\"(),\", bool, int)\n}\n\n-- builtins.go --\npackage builtins\n\n// Definitions of builtin completion items that are still used in tests.\n\n/* bool */ //@item(bool, \"bool\", \"\", \"type\")\n/* complex(r float64, i float64) */ //@item(complex, \"complex\", \"func(r float64, i float64) complex128\", \"func\")\n/* float32 */ //@item(float32, \"float32\", \"\", \"type\")\n/* float64 */ //@item(float64, \"float64\", \"\", \"type\")\n/* imag(c complex128) float64 */ //@item(imag, \"imag\", \"func(c complex128) float64\", \"func\")\n/* int */ //@item(int, \"int\", \"\", \"type\")\n/* iota */ //@item(iota, \"iota\", \"\", \"const\")\n/* string */ //@item(string, \"string\", \"\", \"type\")\n/* true */ //@item(_true, \"true\", \"\", \"const\")\n\n-- constants.go --\npackage builtins\n\nfunc _() {\n\tconst (\n\t\tfoo = iota //@complete(re\"() \\\\/\\\\/\", iota)\n\t)\n\n\tiota //@complete(re\"() \\\\/\\\\/\")\n\n\tvar iota int //@item(iotaVar, \"iota\", \"int\", \"var\")\n\n\tiota //@complete(re\"() \\\\/\\\\/\", iotaVar)\n}\n\nfunc _() {\n\tvar twoRedUpEnd bool //@item(TRUEVar, \"twoRedUpEnd\", \"bool\", \"var\")\n\n\tvar _ bool = true //@rank(re\"() \\\\/\\\\/\", _true, TRUEVar)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/casesensitive.txt",
    "content": "This test exercises the caseSensitive completion matcher.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"matcher\": \"caseSensitive\"\n}\n\n-- casesensitive.go --\npackage casesensitive\n\nfunc _() {\n\tvar lower int //@item(lower, \"lower\", \"int\", \"var\")\n\tvar Upper int //@item(upper, \"Upper\", \"int\", \"var\")\n\n\tl //@complete(re\"() \\\\/\\\\/\", lower)\n\tU //@complete(re\"() \\\\/\\\\/\", upper)\n\n\tL //@complete(re\"() \\\\/\\\\/\")\n\tu //@complete(re\"() \\\\/\\\\/\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/cast.txt",
    "content": "This test checks completion related to casts.\n\n-- flags --\n-ignore_extra_diags\n\n-- cast.go --\npackage cast\n\nfunc _() {\n\tfoo := struct{x int}{x: 1} //@item(x_field, \"x\", \"int\", \"field\")\n\t_ = float64(foo.x) //@complete(re\"()x\", x_field)\n}\n\nfunc _() {\n\tfoo := struct{x int}{x: 1}\n\t_ = float64(foo. //@complete(re\"() \\\\/\", x_field)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/channel.txt",
    "content": "This test checks completion related to channels.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- channel.go --\npackage channel\n\nfunc _() {\n\tvar (\n\t\taa = \"123\" //@item(channelAA, \"aa\", \"string\", \"var\")\n\t\tab = 123   //@item(channelAB, \"ab\", \"int\", \"var\")\n\t)\n\n\t{\n\t\ttype myChan chan int\n\t\tvar mc myChan\n\t\tmc <- a //@complete(re\"() \\\\/\\\\/\", channelAB, channelAA)\n\t}\n\n\t{\n\t\tvar ac chan int //@item(channelAC, \"ac\", \"chan int\", \"var\")\n\t\ta <- a //@complete(re\"() <-\", channelAC, channelAA, channelAB)\n\t}\n\n\t{\n\t\tvar foo chan int //@item(channelFoo, \"foo\", \"chan int\", \"var\")\n\t\twantsInt := func(int) {} //@item(channelWantsInt, \"wantsInt\", \"func(int)\", \"var\")\n\t\twantsInt(<-) //@rank(re\"()\\\\)\", channelFoo, channelAB)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/comment.txt",
    "content": "This test checks behavior of completion within comments.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/comment\n\ngo 1.18\n\n-- p.go --\npackage comment_completion\n\nvar p bool\n\n//@complete(re\"//()\")\n\nfunc _() {\n\tvar a int\n\n\tswitch a {\n\tcase 1:\n\t\t//@complete(re\"//()\")\n\t\t_ = a\n\t}\n\n\tvar b chan int\n\tselect {\n\tcase <-b:\n\t\t//@complete(re\"//()\")\n\t\t_ = b\n\t}\n\n\tvar (\n\t\t//@complete(re\"//()\")\n\t\t_ = a\n\t)\n}\n\n// //@complete(re\"() \", variableC)\nvar C string //@item(variableC, \"C\", \"string\", \"var\") //@complete(re\"() \", variableC)\n\n// //@complete(re\"() \", constant)\nconst Constant = \"example\" //@item(constant, \"Constant\", \"string\", \"const\") //@complete(re\"() \", constant)\n\n// //@complete(re\"() \", structType, fieldB, fieldA)\ntype StructType struct { //@item(structType, \"StructType\", \"struct{...}\", \"struct\") //@complete(re\"() \", structType, fieldA, fieldB)\n\t// //@complete(re\"() \", fieldA, structType, fieldB)\n\tA string //@item(fieldA, \"A\", \"string\", \"field\") //@complete(re\"() \", fieldA, structType, fieldB)\n\tb int    //@item(fieldB, \"b\", \"int\", \"field\") //@complete(re\"() \", fieldB, structType, fieldA)\n}\n\n// //@complete(re\"() \", method, structRecv, paramX, resultY, fieldB, fieldA)\nfunc (structType *StructType) Method(X int) (Y int) { //@item(structRecv, \"structType\", \"*StructType\", \"var\"),item(method, \"Method\", \"func(X int) (Y int)\", \"method\"),item(paramX, \"X\", \"int\", \"var\"),item(resultY, \"Y\", \"int\", \"var\")\n\t// //@complete(re\"() \", method, structRecv, paramX, resultY, fieldB, fieldA)\n\treturn\n}\n\n// //@complete(re\"() \", newType)\ntype NewType string //@item(newType, \"NewType\", \"string\", \"type\") //@complete(re\"() \", newType)\n\n// //@complete(re\"() \", testInterface, testA, testB)\ntype TestInterface interface { //@item(testInterface, \"TestInterface\", \"interface{...}\", \"interface\")\n\t// //@complete(re\"() \", testA, testInterface, testB)\n\tTestA(L string) (M int) //@item(testA, \"TestA\", \"func(L string) (M int)\", \"method\"),item(paramL, \"L\", \"var\", \"string\"),item(resM, \"M\", \"var\", \"int\") //@complete(re\"() \", testA, testInterface, testB)\n\tTestB(N int) bool       //@item(testB, \"TestB\", \"func(N int) bool\", \"method\"),item(paramN, \"N\", \"var\", \"int\") //@complete(re\"() \", testB, testInterface, testA)\n}\n\n// //@complete(re\"() \", function)\nfunc Function() int { //@item(function, \"Function\", \"func() int\", \"func\") //@complete(re\"() \", function)\n\t// //@complete(re\"() \", function)\n\treturn 0\n}\n\n// This tests multiline block comments and completion with prefix\n// Lorem Ipsum Multili//@complete(re\"()Multi\", multiline)\n// Lorem ipsum dolor sit ametom\nfunc Multiline() int { //@item(multiline, \"Multiline\", \"func() int\", \"func\")\n\t// //@complete(re\"() \", multiline)\n\treturn 0\n}\n\n// This test checks that gopls does not panic if the receiver is syntactically\n// present but empty.\n//\n// //@complete(re\"() \")\nfunc () _() {}\n\n\n// This test checks that gopls does not panic if there is a duplicate declaration.\nfunc f() {}\n\n// //@complete(re\"() \")\nfunc () f() {}"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/complit.txt",
    "content": "This test checks completion related to composite literals.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- complit.go --\npackage complit\n\n// Literal completion results.\n/* int() */ //@item(int, \"int()\", \"int\", \"var\")\n\n// general completions\n\ntype position struct { //@item(structPosition, \"position\", \"struct{...}\", \"struct\")\n\tX, Y int //@item(fieldX, \"X\", \"int\", \"field\"),item(fieldY, \"Y\", \"int\", \"field\")\n}\n\nfunc _() {\n\t_ = position{\n\t\t//@complete(\"\", fieldX, fieldY, int, structPosition)\n\t}\n\t_ = position{\n\t\tX: 1,\n\t\t//@complete(\"\", fieldY)\n\t}\n\t_ = position{\n\t\t//@complete(\"\", fieldX)\n\t\tY: 1,\n\t}\n\t_ = []*position{\n        {\n            //@complete(\"\", fieldX, fieldY, int, structPosition)\n        },\n\t}\n}\n\nfunc _() {\n\tvar (\n\t\taa string //@item(aaVar, \"aa\", \"string\", \"var\")\n\t\tab int    //@item(abVar, \"ab\", \"int\", \"var\")\n\t)\n\n\t_ = map[int]int{\n\t\ta: a, //@complete(re\"():\", abVar, aaVar),complete(re\"(),\", abVar, aaVar)\n\t}\n\n\t_ = map[int]int{\n\t\t//@complete(\"\", abVar, int, aaVar, structPosition)\n\t}\n\n\t_ = []string{a: \"\"} //@complete(re\"():\", abVar, aaVar)\n\t_ = [1]string{a: \"\"} //@complete(re\"():\", abVar, aaVar)\n\n\t_ = position{X: a}   //@complete(re\"()}\", abVar, aaVar)\n\t_ = position{a}      //@complete(re\"()}\", abVar, aaVar)\n\t_ = position{a, }      //@complete(re\"()}\", abVar, int, aaVar, structPosition)\n\n\t_ = []int{a}  //@complete(re\"()}\", abVar, aaVar)\n\t_ = [1]int{a} //@complete(re\"()}\", abVar, aaVar)\n\n\ttype myStruct struct {\n\t\tAA int    //@item(fieldAA, \"AA\", \"int\", \"field\")\n\t\tAB string //@item(fieldAB, \"AB\", \"string\", \"field\")\n\t}\n\n\t_ = myStruct{\n\t\tAB: a, //@complete(re\"(),\", aaVar, abVar)\n\t}\n\n\tvar s myStruct\n\n\t_ = map[int]string{1: \"\" + s.A}                                //@complete(re\"()}\", fieldAB, fieldAA)\n\t_ = map[int]string{1: (func(i int) string { return \"\" })(s.A)} //@complete(re\"()\\\\)}\", fieldAA, fieldAB)\n\t_ = map[int]string{1: func() string { s.A }}                   //@complete(re\"() }\", fieldAA, fieldAB)\n\n\t_ = position{s.A} //@complete(re\"()}\", fieldAA, fieldAB)\n\n\tvar X int //@item(varX, \"X\", \"int\", \"var\")\n\t_ = position{X}      //@complete(re\"()}\", fieldX, varX)\n}\n\nfunc _() {\n\ttype foo struct{} //@item(complitFoo, \"foo\", \"struct{...}\", \"struct\")\n\n\tvar _ *foo = &fo{} //@snippet(re\"()\\\\{\", complitFoo, \"foo\")\n\tvar _ *foo = fo{} //@snippet(re\"()\\\\{\", complitFoo, \"&foo\")\n\n\tstruct { a, b *foo }{\n\t\ta: &fo{}, //@rank(re\"(){\", complitFoo)\n\t\tb: fo{}, //@snippet(re\"()\\\\{\", complitFoo, \"&foo\")\n\t}\n}\n\nfunc _() {\n\t_ := position{\n\t\tX: 1, //@complete(re\"()X\", fieldX),complete(re\"() 1\", int, structPosition)\n\t\tY: ,  //@complete(re\"():\", fieldY),complete(re\"() ,\", int, structPosition)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/constant.txt",
    "content": "This test checks completion related to constants.\n\n-- flags --\n-ignore_extra_diags\n\n-- constant.go --\npackage constant\n\nconst x = 1 //@item(constX, \"x\", \"int\", \"const\")\n\nconst (\n\ta int = iota << 2 //@item(constA, \"a\", \"int\", \"const\")\n\tb                 //@item(constB, \"b\", \"int\", \"const\")\n\tc                 //@item(constC, \"c\", \"int\", \"const\")\n)\n\nfunc _() {\n\tconst y = \"hi\" //@item(constY, \"y\", \"string\", \"const\")\n\t//@complete(\"\", constY, constA, constB, constC, constX)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/danglingstmt.txt",
    "content": "This test checks that completion works as expected in the presence of\nincomplete statements that may affect parser recovery.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/dangling\n\ngo 1.18\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"deepCompletion\": false\n}\n\n-- dangling_for.go --\npackage danglingstmt\n\nfunc _() {\n\tfor bar //@rank(re\"() \\\\/\\\\/\", danglingBar)\n}\n\nfunc bar() bool { //@item(danglingBar, \"bar\", \"func() bool\", \"func\")\n\treturn true\n}\n\n-- dangling_for_init.go --\npackage danglingstmt\n\nfunc _() {\n\tfor i := bar //@rank(re\"() \\\\/\\\\/\", danglingBar2)\n}\n\nfunc bar2() int { //@item(danglingBar2, \"bar2\", \"func() int\", \"func\")\n\treturn 0\n}\n\n-- dangling_for_init_cond.go --\npackage danglingstmt\n\nfunc _() {\n\tfor i := bar3(); i > bar //@rank(re\"() \\\\/\\\\/\", danglingBar3)\n}\n\nfunc bar3() int { //@item(danglingBar3, \"bar3\", \"func() int\", \"func\")\n\treturn 0\n}\n\n-- dangling_for_init_cond_post.go --\npackage danglingstmt\n\nfunc _() {\n\tfor i := bar4(); i > bar4(); i += bar //@rank(re\"() \\\\/\\\\/\", danglingBar4)\n}\n\nfunc bar4() int { //@item(danglingBar4, \"bar4\", \"func() int\", \"func\")\n\treturn 0\n}\n\n-- dangling_if.go --\npackage danglingstmt\n\nfunc _() {\n\tif foo //@rank(re\"() \\\\/\\\\/\", danglingFoo)\n}\n\nfunc foo() bool { //@item(danglingFoo, \"foo\", \"func() bool\", \"func\")\n\treturn true\n}\n\n-- dangling_if_eof.go --\npackage danglingstmt\n\nfunc bar5() bool { //@item(danglingBar5, \"bar5\", \"func() bool\", \"func\")\n\treturn true\n}\n\nfunc _() {\n\tif b //@rank(re\"() \\\\/\\\\/\", danglingBar5)\n\n-- dangling_if_init.go --\npackage danglingstmt\n\nfunc _() {\n\tif i := foo //@rank(re\"() \\\\/\\\\/\", danglingFoo2)\n}\n\nfunc foo2() bool { //@item(danglingFoo2, \"foo2\", \"func() bool\", \"func\")\n\treturn true\n}\n\n-- dangling_if_init_cond.go --\npackage danglingstmt\n\nfunc _() {\n\tif i := 123; foo //@rank(re\"() \\\\/\\\\/\", danglingFoo3)\n}\n\nfunc foo3() bool { //@item(danglingFoo3, \"foo3\", \"func() bool\", \"func\")\n\treturn true\n}\n\n-- dangling_multiline_if.go --\npackage danglingstmt\n\nfunc walrus() bool { //@item(danglingWalrus, \"walrus\", \"func() bool\", \"func\")\n\treturn true\n}\n\nfunc _() {\n\tif true &&\n\t\twalrus //@complete(re\"() \\\\/\\\\/\", danglingWalrus)\n}\n\n-- dangling_selector_1.go --\npackage danglingstmt\n\nfunc _() {\n\tx. //@rank(re\"() \\\\/\\\\/\", danglingI)\n}\n\nvar x struct { i int } //@item(danglingI, \"i\", \"int\", \"field\")\n\n-- dangling_selector_2.go --\npackage danglingstmt\n\n// TODO: re-enable this test, which was broken when the foo package was removed.\n// (we can replicate the relevant definitions in the new marker test)\n// import \"golang.org/lsptests/foo\"\n\nfunc _() {\n\tfoo. // rank(re\"() \\\\/\\\\/\", Foo)\n\tvar _ = []string{foo.} // rank(re\"()}\", Foo)\n}\n\n-- dangling_switch_init.go --\npackage danglingstmt\n\nfunc _() {\n\tswitch i := baz //@rank(re\"() \\\\/\\\\/\", danglingBaz)\n}\n\nfunc baz() int { //@item(danglingBaz, \"baz\", \"func() int\", \"func\")\n\treturn 0\n}\n\n-- dangling_switch_init_tag.go --\npackage danglingstmt\n\nfunc _() {\n\tswitch i := 0; baz //@rank(re\"() \\\\/\\\\/\", danglingBaz2)\n}\n\nfunc baz2() int { //@item(danglingBaz2, \"baz2\", \"func() int\", \"func\")\n\treturn 0\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/deep.txt",
    "content": "This test exercises deep completion.\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"matcher\": \"caseInsensitive\"\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- deep/deep.go --\npackage deep\n\nimport \"context\"\n\ntype deepA struct {\n\tb deepB //@item(deepBField, \"b\", \"deepB\", \"field\")\n}\n\ntype deepB struct {\n}\n\nfunc wantsDeepB(deepB) {}\n\nfunc _() {\n\tvar a deepA   //@item(deepAVar, \"a\", \"deepA\", \"var\")\n\ta.b           //@item(deepABField, \"a.b\", \"deepB\", \"field\")\n\twantsDeepB(a) //@complete(re\"()\\\\)\", deepABField, deepAVar)\n\n\tdeepA{a} //@snippet(re\"()}\", deepABField, \"a.b\")\n}\n\nfunc wantsContext(context.Context) {}\n\nfunc _() {\n\tcontext.Background() //@item(ctxBackground, \"context.Background\", \"func() context.Context\", \"func\", \"Background returns a non-nil, empty Context.\")\n\tcontext.TODO()       //@item(ctxTODO, \"context.TODO\", \"func() context.Context\", \"func\", \"TODO returns a non-nil, empty Context.\")\n\n\twantsContext(c) //@rank(re\"()\\\\)\", ctxBackground),rank(re\"()\\\\)\", ctxTODO)\n}\n\nfunc _() {\n\tvar cork struct{ err error }\n\tcork.err         //@item(deepCorkErr, \"cork.err\", \"error\", \"field\")\n\tcontext          //@item(deepContextPkg, \"context\", \"\\\"context\\\"\", \"package\")\n\tvar _ error = co // rank(re\"() \\\\/\\\\/\", deepCorkErr, deepContextPkg)\n}\n\nfunc _() {\n\t// deepCircle is circular.\n\ttype deepCircle struct {\n\t\t*deepCircle\n\t}\n\tvar circle deepCircle   //@item(deepCircle, \"circle\", \"deepCircle\", \"var\")\n\tcircle.deepCircle       //@item(deepCircleField, \"circle.deepCircle\", \"*deepCircle\", \"field\")\n\tvar _ deepCircle = circ //@complete(re\"() \\\\/\\\\/\", deepCircle, deepCircleField),snippet(re\"() \\\\/\\\\/\", deepCircleField, \"*circle.deepCircle\")\n}\n\nfunc _() {\n\ttype deepEmbedC struct {\n\t}\n\ttype deepEmbedB struct {\n\t\tdeepEmbedC\n\t}\n\ttype deepEmbedA struct {\n\t\tdeepEmbedB\n\t}\n\n\twantsC := func(deepEmbedC) {}\n\n\tvar a deepEmbedA //@item(deepEmbedA, \"a\", \"deepEmbedA\", \"var\")\n\ta.deepEmbedB     //@item(deepEmbedB, \"a.deepEmbedB\", \"deepEmbedB\", \"field\")\n\ta.deepEmbedC     //@item(deepEmbedC, \"a.deepEmbedC\", \"deepEmbedC\", \"field\")\n\twantsC(a)        //@complete(re\"()\\\\)\", deepEmbedC, deepEmbedA, deepEmbedB)\n}\n\nfunc _() {\n\ttype nested struct {\n\t\ta int\n\t\tn *nested //@item(deepNestedField, \"n\", \"*nested\", \"field\")\n\t}\n\n\tnested{\n\t\ta: 123, //@complete(re\"() \\\\/\\\\/\", deepNestedField)\n\t}\n}\n\nfunc _() {\n\tvar a struct {\n\t\tb struct {\n\t\t\tc int\n\t\t}\n\t\td int\n\t}\n\n\ta.d   //@item(deepAD, \"a.d\", \"int\", \"field\")\n\ta.b.c //@item(deepABC, \"a.b.c\", \"int\", \"field\")\n\ta.b   //@item(deepAB, \"a.b\", \"struct{...}\", \"field\")\n\ta     //@item(deepA, \"a\", \"struct{...}\", \"var\")\n\n\t// \"a.d\" should be ranked above the deeper \"a.b.c\"\n\tvar i int\n\ti = a //@complete(re\"() \\\\/\\\\/\", deepAD, deepABC, deepA, deepAB)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/deep2.txt",
    "content": "This test exercises deep completion.\n\nIt was originally bundled with deep.go, but is split into a separate test as\nthe new marker tests do not permit mutating server options for individual\nmarks.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- deep/deep2.go --\npackage deep\n\ntype foo struct {\n\tb bar\n}\n\nfunc (f foo) bar() bar {\n\treturn f.b\n}\n\nfunc (f foo) barPtr() *bar {\n\treturn &f.b\n}\n\ntype bar struct{}\n\nfunc (b bar) valueReceiver() int {\n\treturn 0\n}\n\nfunc (b *bar) ptrReceiver() int {\n\treturn 0\n}\n\nfunc _() {\n\tvar (\n\t\ti int\n\t\tf foo\n\t)\n\n\tf.bar().valueReceiver    //@item(deepBarValue, \"f.bar().valueReceiver\", \"func() int\", \"method\")\n\tf.barPtr().ptrReceiver   //@item(deepBarPtrPtr, \"f.barPtr().ptrReceiver\", \"func() int\", \"method\")\n\tf.barPtr().valueReceiver //@item(deepBarPtrValue, \"f.barPtr().valueReceiver\", \"func() int\", \"method\")\n\n\ti = fbar //@complete(re\"() \\\\/\\\\/\", deepBarValue, deepBarPtrPtr, deepBarPtrValue)\n}\n\nfunc (b baz) Thing() struct{ val int } {\n\treturn b.thing\n}\n\ntype baz struct {\n\tthing struct{ val int }\n}\n\nfunc (b baz) _() {\n\tb.Thing().val    //@item(deepBazMethVal, \"b.Thing().val\", \"int\", \"field\")\n\tb.thing.val      //@item(deepBazFieldVal, \"b.thing.val\", \"int\", \"field\")\n\tvar _ int = bval //@rank(re\"() \\\\/\\\\/\", deepBazFieldVal, deepBazMethVal)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/errors.txt",
    "content": "This test checks completion related to errors.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"deepCompletion\": false\n}\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- errors.go --\npackage errors\n\nimport (\n\t\"golang.org/lsptests/types\"\n)\n\nfunc _() {\n\tbob.Bob() //@complete(re\"()\\\\.\")\n\ttypes.b //@complete(re\"() \\\\/\\\\/\", Bob_interface)\n}\n\n-- types/types.go --\npackage types\n\ntype Bob interface { //@item(Bob_interface, \"Bob\", \"interface{...}\", \"interface\")\n\tBobby()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/field_list.txt",
    "content": "This test checks completion related to field lists.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- field_list.go --\npackage fieldlist\n\nvar myInt int   //@item(flVar, \"myInt\", \"int\", \"var\")\ntype myType int //@item(flType, \"myType\", \"int\", \"type\")\n\nfunc (my) _()    {} //@complete(re\"()\\\\) _\", flType)\nfunc (my my) _() {} //@complete(re\"() my\\\\)\"),complete(re\"()\\\\) _\", flType)\n\nfunc (myType) _() {} //@complete(re\"()\\\\) {\", flType)\n\nfunc (myType) _(my my) {} //@complete(re\"() my\\\\)\"),complete(re\"()\\\\) {\", flType)\n\nfunc (myType) _() my {} //@complete(re\"() {\", flType)\n\nfunc (myType) _() (my my) {} //@complete(re\"() my\"),complete(re\"()\\\\) {\", flType)\n\nfunc _() {\n\tvar _ struct {\n\t\t//@complete(\"\", flType)\n\t\tm my //@complete(re\"() my\"),complete(re\"() \\\\/\\\\/\", flType)\n\t}\n\n\tvar _ interface {\n\t\t//@complete(\"\", flType)\n\t\tm() my //@complete(re\"()\\\\(\"),complete(re\"() \\\\/\\\\/\", flType)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/foobarbaz.txt",
    "content": "This test ports some arbitrary tests from the old marker framework, that were\n*mostly* about completion.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"deepCompletion\": false,\n\t\"experimentalPostfixCompletions\": false\n}\n\n-- go.mod --\nmodule foobar.test\n\ngo 1.18\n\n-- foo/foo.go --\npackage foo //@loc(PackageFoo, \"foo\"),item(PackageFooItem, \"foo\", \"\\\"foobar.test/foo\\\"\", \"package\")\n\ntype StructFoo struct { //@loc(StructFooLoc, \"StructFoo\"), item(StructFoo, \"StructFoo\", \"struct{...}\", \"struct\")\n\tValue int //@item(Value, \"Value\", \"int\", \"field\")\n}\n\n// Pre-set this marker, as we don't have a \"source\" for it in this package.\n/* Error() */ //@item(Error, \"Error\", \"func() string\", \"method\")\n\nfunc Foo() { //@item(Foo, \"Foo\", \"func()\", \"func\")\n\tvar err error\n\terr.Error() //@complete(re\"()E\", Error)\n}\n\nfunc _() {\n\tvar sFoo StructFoo           //@complete(re\"()t\", StructFoo)\n\tif x := sFoo; x.Value == 1 { //@complete(re\"()V\", Value), typedef(\"sFoo\", StructFooLoc)\n\t\treturn\n\t}\n}\n\nfunc _() {\n\tshadowed := 123\n\t{\n\t\tshadowed := \"hi\" //@item(shadowed, \"shadowed\", \"string\", \"var\")\n\t\tsha              //@complete(re\"()a\", shadowed), diag(\"sha\", re\"(undefined|undeclared)\")\n\t\t_ = shadowed\n\t}\n}\n\ntype IntFoo int //@loc(IntFooLoc, \"IntFoo\"), item(IntFoo, \"IntFoo\", \"int\", \"type\")\n\n-- bar/bar.go --\npackage bar\n\nimport (\n\t\"foobar.test/foo\" //@item(foo, \"foo\", \"\\\"foobar.test/foo\\\"\", \"package\")\n)\n\nfunc helper(i foo.IntFoo) {} //@item(helper, \"helper\", \"func(i foo.IntFoo)\", \"func\")\n\nfunc _() {\n\thelp //@complete(re\"()l\", helper)\n\t_ = foo.StructFoo{} //@complete(re\"()S\", IntFoo, StructFoo)\n}\n\n// Bar is a function.\nfunc Bar() { //@item(Bar, \"Bar\", \"func()\", \"func\", \"Bar is a function.\")\n\tfoo.Foo()        //@complete(re\"()F\", Foo, IntFoo, StructFoo)\n\tvar _ foo.IntFoo //@complete(re\"()I\", IntFoo, StructFoo)\n\tfoo.()           //@complete(re\"()\\\\(\", Foo, IntFoo, StructFoo), diag(\")\", re\"expected type\")\n}\n\n// These items weren't present in the old marker tests (due to settings), but\n// we may as well include them.\n//@item(intConversion, \"int()\"), item(fooFoo, \"foo.Foo\")\n//@item(fooIntFoo, \"foo.IntFoo\"), item(fooStructFoo, \"foo.StructFoo\")\n\nfunc _() {\n\tvar Valentine int //@item(Valentine, \"Valentine\", \"int\", \"var\")\n\n\t_ = foo.StructFoo{ //@diag(\"foo\", re\"unkeyed fields\")\n\t\tValu //@complete(re\"() \\\\/\\\\/\", Value)\n\t}\n  \t_ = foo.StructFoo{ //@diag(\"foo\", re\"unkeyed fields\")\n\t\tVa        //@complete(re\"()a\", Value, Valentine)\n\n\t}\n\t_ = foo.StructFoo{\n\t\tValue: 5, //@complete(re\"()a\", Value)\n\t}\n\t_ = foo.StructFoo{\n\t\t//@complete(re\"()//\", Value, Valentine, intConversion, foo, helper, Bar)\n\t}\n\t_ = foo.StructFoo{\n\t\tValue: Valen //@complete(re\"()le\", Valentine)\n\t}\n\t_ = foo.StructFoo{\n\t\tValue:       //@complete(re\"() \\\\/\\\\/\", Valentine, intConversion, foo, helper, Bar)\n\t}\n\t_ = foo.StructFoo{\n\t\tValue:       //@complete(re\"() \", Valentine, intConversion, foo, helper, Bar)\n\t}\n}\n\n-- baz/baz.go --\npackage baz\n\nimport (\n\t\"foobar.test/bar\"\n\n\tf \"foobar.test/foo\"\n)\n\nvar FooStruct f.StructFoo\n\nfunc Baz() {\n\tdefer bar.Bar() //@complete(re\"()B\", Bar)\n\t// TODO: Test completion here.\n\tdefer bar.B //@diag(re\"bar.B()\", re\"must be function call\")\n\tvar x f.IntFoo  //@complete(re\"()n\", IntFoo), typedef(\"x\", IntFooLoc)\n\tbar.Bar()       //@complete(re\"()B\", Bar)\n}\n\nfunc _() {\n\tbob := f.StructFoo{Value: 5}\n\tif x := bob. //@complete(re\"() \\\\/\\\\/\", Value)\n\tswitch true == false {\n\t\tcase true:\n\t\t\tif x := bob. //@complete(re\"() \\\\/\\\\/\", Value)\n\t\tcase false:\n\t}\n\tif x := bob.Va //@complete(re\"()a\", Value)\n\tswitch true == true {\n\t\tdefault:\n\t}\n}\n\n-- arraytype/arraytype.go --\npackage arraytype\n\nimport (\n\t\"foobar.test/foo\"\n)\n\nfunc _() {\n\tvar (\n\t\tval string //@item(atVal, \"val\", \"string\", \"var\")\n\t)\n\n\t[] //@complete(re\"() \\\\/\\\\/\", atVal, PackageFooItem)\n\n\t[]val //@complete(re\"() \\\\/\\\\/\")\n\n\t[]foo.StructFoo //@complete(re\"() \\\\/\\\\/\", StructFoo)\n\n\t[]foo.StructFoo(nil) //@complete(re\"()\\\\(\", StructFoo)\n\n\t[]*foo.StructFoo //@complete(re\"() \\\\/\\\\/\", StructFoo)\n\n\t[...]foo.StructFoo //@complete(re\"() \\\\/\\\\/\", StructFoo)\n\n\t[2][][4]foo.StructFoo //@complete(re\"() \\\\/\\\\/\", StructFoo)\n\n\t[]struct { f []foo.StructFoo } //@complete(re\"() }\", StructFoo)\n}\n\nfunc _() {\n\ttype myInt int //@item(atMyInt, \"myInt\", \"int\", \"type\")\n\n\tvar mark []myInt //@item(atMark, \"mark\", \"[]myInt\", \"var\")\n\n\tvar s []myInt //@item(atS, \"s\", \"[]myInt\", \"var\")\n\ts = []m //@complete(re\"() \\\\/\\\\/\", atMyInt)\n\n\tvar a [1]myInt\n\ta = [1]m //@complete(re\"() \\\\/\\\\/\", atMyInt)\n\n\tvar ds [][]myInt\n\tds = [][]m //@complete(re\"() \\\\/\\\\/\", atMyInt)\n}\n\nfunc _() {\n\tvar b [0]byte //@item(atByte, \"b\", \"[0]byte\", \"var\")\n\tvar _ []byte = b //@snippet(re\"() \\\\/\\\\/\", atByte, \"b[:]\")\n}\n\n-- badstmt/badstmt.go --\npackage badstmt\n\nimport (\n\t\"foobar.test/foo\"\n)\n\n// (The syntax error causes suppression of diagnostics for type errors.\n// See issue #59888.)\n\nfunc _(x int) {\n\tdefer foo.F //@complete(re\"() \\\\/\\\\/\", Foo, IntFoo, StructFoo)\n\tdefer foo.F //@complete(re\"() \\\\/\\\\/\", Foo, IntFoo, StructFoo)\n}\n\nfunc _() {\n\tswitch true {\n\tcase true:\n\t\tgo foo.F //@complete(re\"() \\\\/\\\\/\", Foo, IntFoo, StructFoo)\n\t}\n}\n\nfunc _() {\n\tdefer func() {\n\t\tfoo.F //@complete(re\"() \\\\/\\\\/\", Foo, IntFoo, StructFoo), snippet(re\"() \\\\/\\\\/\", Foo, \"Foo()\")\n\n\t\tfoo. //@rank(re\"() \\\\/\\\\/\", Foo)\n\t}\n}\n\n-- badstmt/badstmt_2.go --\npackage badstmt\n\nimport (\n\t\"foobar.test/foo\"\n)\n\nfunc _() {\n\tdefer func() { foo. } //@rank(re\"() }\", Foo)\n}\n\n-- badstmt/badstmt_3.go --\npackage badstmt\n\nimport (\n\t\"foobar.test/foo\"\n)\n\nfunc _() {\n\tgo foo. //@rank(re\"() \\\\/\\\\/\", Foo, IntFoo), snippet(re\"() \\\\/\\\\/\", Foo, \"Foo()\")\n}\n\n-- badstmt/badstmt_4.go --\npackage badstmt\n\nimport (\n\t\"foobar.test/foo\"\n)\n\nfunc _() {\n\tgo func() {\n\t\tdefer foo. //@rank(re\"() \\\\/\\\\/\", Foo, IntFoo)\n\t}\n}\n\n-- selector/selector.go --\npackage selector\n\nimport (\n\t\"foobar.test/bar\"\n)\n\ntype S struct {\n\tB, A, C int //@item(Bf, \"B\", \"int\", \"field\"),item(Af, \"A\", \"int\", \"field\"),item(Cf, \"C\", \"int\", \"field\")\n}\n\nfunc _() {\n\t_ = S{}.; //@complete(re\"();\", Af, Bf, Cf)\n}\n\ntype bob struct { a int } //@item(a, \"a\", \"int\", \"field\")\ntype george struct { b int }\ntype jack struct { c int } //@item(c, \"c\", \"int\", \"field\")\ntype jill struct { d int }\n\nfunc (b *bob) george() *george {} //@item(george, \"george\", \"func() *george\", \"method\")\nfunc (g *george) jack() *jack {}\nfunc (j *jack) jill() *jill {} //@item(jill, \"jill\", \"func() *jill\", \"method\")\n\nfunc _() {\n\tb := &bob{}\n\ty := b.george().\n\t\tjack();\n\ty.; //@complete(re\"();\", c, jill)\n}\n\nfunc _() {\n\tbar. //@complete(re\"() \\\\/\", Bar)\n\tx := 5\n\n\tvar b *bob\n\tb. //@complete(re\"() \\\\/\", a, george)\n\ty, z := 5, 6\n\n\tb. //@complete(re\"() \\\\/\", a, george)\n\ty, z, a, b, c := 5, 6\n}\n\nfunc _() {\n\tbar. //@complete(re\"() \\\\/\", Bar)\n\tbar.Bar()\n\n\tbar. //@complete(re\"() \\\\/\", Bar)\n\tgo f()\n}\n\nfunc _() {\n\tvar b *bob\n\tif y != b. //@complete(re\"() \\\\/\", a, george)\n\tz := 5\n\n\tif z + y + 1 + b. //@complete(re\"() \\\\/\", a, george)\n\tr, s, t := 4, 5\n\n\tif y != b. //@complete(re\"() \\\\/\", a, george)\n\tz = 5\n\n\tif z + y + 1 + b. //@complete(re\"() \\\\/\", a, george)\n\tr = 4\n}\n\n-- literal_snippets/literal_snippets.go --\npackage literal_snippets\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"go/ast\"\n\t\"net/http\"\n\t\"sort\"\n\n\t\"golang.org/lsptests/foo\"\n)\n\nfunc _() {\n\t[]int{}        //@item(litIntSlice, \"[]int{}\", \"\", \"var\")\n\t&[]int{}       //@item(litIntSliceAddr, \"&[]int{}\", \"\", \"var\")\n\tmake([]int, 0) //@item(makeIntSlice, \"make([]int, 0)\", \"\", \"func\")\n\n\tvar _ *[]int = in //@snippet(re\"() \\\\/\\\\/\", litIntSliceAddr, \"&[]int{$0\\\\}\")\n\tvar _ **[]int = in //@complete(re\"() \\\\/\\\\/\")\n\n\tvar slice []int\n\tslice = i //@snippet(re\"() \\\\/\\\\/\", litIntSlice, \"[]int{$0\\\\}\")\n\tslice = m //@snippet(re\"() \\\\/\\\\/\", makeIntSlice, \"make([]int, ${1:})\")\n}\n\nfunc _() {\n\ttype namedInt []int\n\n\tnamedInt{}        //@item(litNamedSlice, \"namedInt{}\", \"\", \"var\")\n\tmake(namedInt, 0) //@item(makeNamedSlice, \"make(namedInt, 0)\", \"\", \"func\")\n\n\tvar namedSlice namedInt\n\tnamedSlice = n //@snippet(re\"() \\\\/\\\\/\", litNamedSlice, \"namedInt{$0\\\\}\")\n\tnamedSlice = m //@snippet(re\"() \\\\/\\\\/\", makeNamedSlice, \"make(namedInt, ${1:})\")\n}\n\nfunc _() {\n\tmake(chan int) //@item(makeChan, \"make(chan int)\", \"\", \"func\")\n\n\tvar ch chan int\n\tch = m //@snippet(re\"() \\\\/\\\\/\", makeChan, \"make(chan int)\")\n}\n\nfunc _() {\n\tmap[string]struct{}{}     //@item(litMap, \"map[string]struct{}{}\", \"\", \"var\")\n\tmake(map[string]struct{}) //@item(makeMap, \"make(map[string]struct{})\", \"\", \"func\")\n\n\tvar m map[string]struct{}\n\tm = m //@snippet(re\"() \\\\/\\\\/\", litMap, \"map[string]struct{\\\\}{$0\\\\}\")\n\tm = m //@snippet(re\"() \\\\/\\\\/\", makeMap, \"make(map[string]struct{\\\\})\")\n\n\tstruct{}{} //@item(litEmptyStruct, \"struct{}{}\", \"\", \"var\")\n\n\tm[\"hi\"] = s //@snippet(re\"() \\\\/\\\\/\", litEmptyStruct, \"struct{\\\\}{\\\\}\")\n}\n\nfunc _() {\n\ttype myStruct struct{ i int } //@item(myStructType, \"myStruct\", \"struct{...}\", \"struct\")\n\n\tmyStruct{}  //@item(litStruct, \"myStruct{}\", \"\", \"var\")\n\t&myStruct{} //@item(litStructPtr, \"&myStruct{}\", \"\", \"var\")\n\n\tvar ms myStruct\n\tms = m //@snippet(re\"() \\\\/\\\\/\", litStruct, \"myStruct{$0\\\\}\")\n\n\tvar msPtr *myStruct\n\tmsPtr = m //@snippet(re\"() \\\\/\\\\/\", litStructPtr, \"&myStruct{$0\\\\}\")\n\n\tmsPtr = &m //@snippet(re\"() \\\\/\\\\/\", litStruct, \"myStruct{$0\\\\}\")\n\n\ttype myStructCopy struct { i int } //@item(myStructCopyType, \"myStructCopy\", \"struct{...}\", \"struct\")\n\n\t// Don't offer literal completion for convertible structs.\n\tms = myStruct //@complete(re\"() \\\\/\\\\/\", litStruct, myStructType, myStructCopyType)\n}\n\ntype myImpl struct{}\n\nfunc (myImpl) foo() {}\n\nfunc (*myImpl) bar() {}\n\ntype myBasicImpl string\n\nfunc (myBasicImpl) foo() {}\n\nfunc _() {\n\ttype myIntf interface {\n\t\tfoo()\n\t}\n\n\tmyImpl{} //@item(litImpl, \"myImpl{}\", \"\", \"var\")\n\n\tvar mi myIntf\n\tmi = m //@snippet(re\"() \\\\/\\\\/\", litImpl, \"myImpl{\\\\}\")\n\n\tmyBasicImpl() //@item(litBasicImpl, \"myBasicImpl()\", \"string\", \"var\")\n\n\tmi = m //@snippet(re\"() \\\\/\\\\/\", litBasicImpl, \"myBasicImpl($0)\")\n\n\t// only satisfied by pointer to myImpl\n\ttype myPtrIntf interface {\n\t\tbar()\n\t}\n\n\t&myImpl{} //@item(litImplPtr, \"&myImpl{}\", \"\", \"var\")\n\n\tvar mpi myPtrIntf\n\tmpi = m //@snippet(re\"() \\\\/\\\\/\", litImplPtr, \"&myImpl{\\\\}\")\n}\n\nfunc _() {\n\tvar s struct{ i []int } //@item(litSliceField, \"i\", \"[]int\", \"field\")\n\tvar foo []int\n\t// no literal completions after selector\n\tfoo = s.i //@complete(re\"() \\\\/\\\\/\", litSliceField)\n}\n\nfunc _() {\n\ttype myStruct struct{ i int } //@item(litMyStructType, \"myStruct\", \"struct{...}\", \"struct\")\n\tmyStruct{} //@item(litMyStruct, \"myStruct{}\", \"\", \"var\")\n\n\tfoo := func(s string, args ...myStruct) {}\n\t// Don't give literal slice candidate for variadic arg.\n\t// Do give literal candidates for variadic element.\n\tfoo(\"\", myStruct) //@complete(re\"()\\\\)\", litMyStruct, litMyStructType)\n}\n\nfunc _() {\n\tBuffer{} //@item(litBuffer, \"Buffer{}\", \"\", \"var\")\n\n\tvar b *bytes.Buffer\n\tb = bytes.Bu //@snippet(re\"() \\\\/\\\\/\", litBuffer, \"Buffer{\\\\}\")\n}\n\nfunc _() {\n\t_ = \"func(...) {}\" //@item(litFunc, \"func(...) {}\", \"\", \"var\")\n\n\t// no literal \"func\" completions\n\thttp.Handle(\"\", fun) //@complete(re\"()\\\\)\")\n\n\tvar namedReturn func(s string) (b bool)\n\tnamedReturn = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(s string) (b bool) {$0\\\\}\")\n\n\tvar multiReturn func() (bool, int)\n\tmultiReturn = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func() (bool, int) {$0\\\\}\")\n\n\tvar multiNamedReturn func() (b bool, i int)\n\tmultiNamedReturn = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func() (b bool, i int) {$0\\\\}\")\n\n\tvar duplicateParams func(myImpl, int, myImpl)\n\tduplicateParams = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(mi1 myImpl, i int, mi2 myImpl) {$0\\\\}\")\n\n\ttype aliasImpl = myImpl\n\tvar aliasParams func(aliasImpl) aliasImpl\n\taliasParams = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(ai aliasImpl) aliasImpl {$0\\\\}\")\n\n\tconst two = 2\n\tvar builtinTypes func([]int, [two]bool, map[string]string, struct{ i int }, interface{ foo() }, <-chan int)\n\tbuiltinTypes = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(i1 []int, b [2]bool, m map[string]string, s struct{i int\\\\}, i2 interface{foo()\\\\}, c <-chan int) {$0\\\\}\")\n\n\tvar _ func(ast.Node) = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(n ast.Node) {$0\\\\}\")\n\tvar _ func(error) = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(err error) {$0\\\\}\")\n\tvar _ func(context.Context) = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(ctx context.Context) {$0\\\\}\")\n\n\ttype context struct {}\n\tvar _ func(context) = f //@snippet(re\"() \\\\/\\\\/\", litFunc, \"func(ctx context) {$0\\\\}\")\n}\n\nfunc _() {\n\tfloat64() //@item(litFloat64, \"float64()\", \"float64\", \"var\")\n\n\t// don't complete to \"&float64()\"\n\tvar _ *float64 = float64 //@complete(re\"() \\\\/\\\\/\")\n\n\tvar f float64\n\tf = fl //@complete(re\"() \\\\/\\\\/\", litFloat64),snippet(re\"() \\\\/\\\\/\", litFloat64, \"float64($0)\")\n\n\ttype myInt int\n\tmyInt() //@item(litMyInt, \"myInt()\", \"\", \"var\")\n\n\tvar mi myInt\n\tmi = my //@snippet(re\"() \\\\/\\\\/\", litMyInt, \"myInt($0)\")\n}\n\nfunc _() {\n\ttype ptrStruct struct {\n\t\tp *ptrStruct\n\t}\n\n\tptrStruct{} //@item(litPtrStruct, \"ptrStruct{}\", \"\", \"var\")\n\n\tptrStruct{\n\t\tp: &ptrSt, //@rank(re\"(),\", litPtrStruct)\n\t}\n\n\t&ptrStruct{} //@item(litPtrStructPtr, \"&ptrStruct{}\", \"\", \"var\")\n\n\t&ptrStruct{\n\t\tp: ptrSt, //@rank(re\"(),\", litPtrStructPtr)\n\t}\n}\n\nfunc _() {\n\tf := func(...[]int) {}\n\tf() //@snippet(re\"()\\\\)\", litIntSlice, \"[]int{$0\\\\}\")\n}\n\n\nfunc _() {\n\t// don't complete to \"untyped int()\"\n\t[]int{}[untyped] //@complete(re\"()\\\\] \\\\/\\\\/\")\n}\n\ntype Tree[T any] struct{}\n\nfunc (tree Tree[T]) Do(f func(s T)) {}\n\nfunc _() {\n\tvar t Tree[string]\n\tt.Do(fun) //@complete(re\"()\\\\)\", litFunc), snippet(re\"()\\\\)\", litFunc, \"func(s string) {$0\\\\}\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/func_rank.txt",
    "content": "This test checks various ranking of completion results within function call\ncontext.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"deepCompletion\": false\n}\n\n-- func_rank.go --\npackage func_rank\n\nimport \"net/http\"\n\nvar stringAVar = \"var\"    //@item(stringAVar, \"stringAVar\", \"string\", \"var\")\nfunc stringBFunc() string { return \"str\" } //@item(stringBFunc, \"stringBFunc\", \"func() string\", \"func\")\ntype stringer struct{}    //@item(stringer, \"stringer\", \"struct{...}\", \"struct\")\n\nfunc _() stringer //@complete(re\"()tr\", stringer)\n\nfunc _(val stringer) {} //@complete(re\"()tr\", stringer)\n\nfunc (stringer) _() {} //@complete(re\"()tr\", stringer)\n\nfunc _() {\n\tvar s struct {\n\t\tAA int    //@item(rankAA, \"AA\", \"int\", \"field\")\n\t\tAB string //@item(rankAB, \"AB\", \"string\", \"field\")\n\t\tAC int    //@item(rankAC, \"AC\", \"int\", \"field\")\n\t}\n\tfnStr := func(string) {}\n\tfnStr(s.A)      //@complete(re\"()\\\\)\", rankAB, rankAA, rankAC)\n\tfnStr(\"\" + s.A) //@complete(re\"()\\\\)\", rankAB, rankAA, rankAC)\n\n\tfnInt := func(int) {}\n\tfnInt(-s.A) //@complete(re\"()\\\\)\", rankAA, rankAC, rankAB)\n\n\t// no expected type\n\tfnInt(func() int { s.A }) //@complete(re\"() }\", rankAA, rankAB, rankAC)\n\tfnInt(s.A())              //@complete(re\"()\\\\(\\\\)\", rankAA, rankAC, rankAB)\n\tfnInt([]int{}[s.A])       //@complete(re\"()\\\\]\\\\)\", rankAA, rankAC, rankAB)\n\tfnInt([]int{}[:s.A])      //@complete(re\"()\\\\]\\\\)\", rankAA, rankAC, rankAB)\n\n\tfnInt(s.A.(int)) //@complete(re\"()\\\\.\\\\(\", rankAA, rankAC, rankAB)\n\n\tfnPtr := func(*string) {}\n\tfnPtr(&s.A) //@complete(re\"()\\\\)\", rankAB, rankAA, rankAC)\n\n\tvar aaPtr *string //@item(rankAAPtr, \"aaPtr\", \"*string\", \"var\")\n\tvar abPtr *int    //@item(rankABPtr, \"abPtr\", \"*int\", \"var\")\n\tfnInt(*a)         //@complete(re\"()\\\\)\", rankABPtr, rankAAPtr, stringAVar)\n\n\t_ = func() string {\n\t\treturn s.A //@complete(re\"() \\\\/\\\\/\", rankAB, rankAA, rankAC)\n\t}\n}\n\ntype foo struct {\n\tfooPrivateField int //@item(rankFooPrivField, \"fooPrivateField\", \"int\", \"field\")\n\tFooPublicField  int //@item(rankFooPubField, \"FooPublicField\", \"int\", \"field\")\n}\n\nfunc (foo) fooPrivateMethod() int { //@item(rankFooPrivMeth, \"fooPrivateMethod\", \"func() int\", \"method\")\n\treturn 0\n}\n\nfunc (foo) FooPublicMethod() int { //@item(rankFooPubMeth, \"FooPublicMethod\", \"func() int\", \"method\")\n\treturn 0\n}\n\nfunc _() {\n\tvar _ int = foo{}. //@rank(re\"() \\\\/\\\\/\", rankFooPrivField, rankFooPubField),rank(re\"() \\\\/\\\\/\", rankFooPrivMeth, rankFooPubMeth),rank(re\"() \\\\/\\\\/\", rankFooPrivField, rankFooPrivMeth)\n}\n\nfunc _() {\n\tHandleFunc //@item(httpHandleFunc, \"HandleFunc\", \"func(pattern string, handler func(http.ResponseWriter, *http.Request))\", \"func\")\n\tHandlerFunc //@item(httpHandlerFunc, \"HandlerFunc\", \"func(http.ResponseWriter, *http.Request)\", \"type\")\n\n\thttp.HandleFunc //@rank(re\"() \\\\/\\\\/\", httpHandleFunc, httpHandlerFunc)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/func_sig.txt",
    "content": "This test checks completion related to function signatures.\n\n-- flags --\n-ignore_extra_diags\n\n-- func_sig.go --\npackage funcsig\n\ntype someType int //@item(sigSomeType, \"someType\", \"int\", \"type\")\n\n// Don't complete \"foo\" in signature.\nfunc (foo someType) _() { //@item(sigFoo, \"foo\", \"someType\", \"var\"),complete(re\"()\\\\) {\", sigSomeType)\n\n\t//@complete(\"\", sigFoo, sigSomeType)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/func_snippets.txt",
    "content": "This test exercises function snippets using generics.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": true\n}\n\n-- go.mod --\nmodule golang.org/lsptests/snippets\n\ngo 1.18\n\n-- funcsnippets.go --\npackage snippets\n\ntype SyncMap[K comparable, V any] struct{}\n\nfunc NewSyncMap[K comparable, V any]() (result *SyncMap[K, V]) { //@item(NewSyncMap, \"NewSyncMap\", \"\", \"\")\n\treturn\n}\n\nfunc Identity[P ~int](p P) P { //@item(Identity, \"Identity\", \"\", \"\")\n\treturn p\n}\n\nfunc _() {\n\t_ = NewSyncM //@snippet(re\"() \\\\/\\\\/\", NewSyncMap, \"NewSyncMap[${1:K comparable}, ${2:V any}]()\")\n\t_ = Identi //@snippet(re\"() \\\\/\\\\/\", Identity, \"Identity(${1:p P})\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/func_value.txt",
    "content": "This test checks completion related to function values.\n\n-- flags --\n-ignore_extra_diags\n\n-- func_value.go --\npackage funcvalue\n\nfunc fooFunc() int { //@item(fvFooFunc, \"fooFunc\", \"func() int\", \"func\")\n\treturn 0\n}\n\nvar _ = fooFunc() //@item(fvFooFuncCall, \"fooFunc\", \"func() int\", \"func\")\n\nvar fooVar = func() int { //@item(fvFooVar, \"fooVar\", \"func() int\", \"var\")\n\treturn 0\n}\n\nvar _ = fooVar() //@item(fvFooVarCall, \"fooVar\", \"func() int\", \"var\")\n\ntype myFunc func() int\n\nvar fooType myFunc = fooVar //@item(fvFooType, \"fooType\", \"myFunc\", \"var\")\n\nvar _ = fooType() //@item(fvFooTypeCall, \"fooType\", \"func() int\", \"var\")\n\nfunc _() {\n\tvar f func() int\n\tf = foo //@complete(re\"() \\\\/\\\\/\", fvFooFunc, fvFooType, fvFooVar)\n\n\tvar i int\n\ti = foo //@complete(re\"() \\\\/\\\\/\", fvFooFuncCall, fvFooTypeCall, fvFooVarCall)\n}\n\n-- generic/func_value.go --\npackage funcvalue\n\ntype bar struct{}\n\nfunc (b bar) Num() int {\n\treturn 0\n}\n\nfunc Bar[T any]() bar {\n\treturn bar{}\n}\n\nfunc BarWithArg[T any](a int) bar {\n\treturn bar{}\n}\n\nfunc (b bar) Bar2() bar {\n\treturn b\n}\n\nfunc _() {\n\tBar[T].Num //@item(bar, \"Bar[T]().Num\", \"func() int\", \"method\")\n\tBar[T].Bar2().Num //@item(bar2, \"Bar[T]().Bar2().Num\", \"func() int\", \"method\")\n\tvar i int\n\ti = Num //@complete(re\"() \\\\/\\\\/\", bar, bar2)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/fuzzy.txt",
    "content": "This test exercises fuzzy completion matching.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- fuzzy/fuzzy.go --\npackage fuzzy\n\nfunc _() {\n\tvar a struct {\n\t\tfabar  int\n\t\tfooBar string\n\t}\n\n\ta.fabar  //@item(fuzzFabarField, \"a.fabar\", \"int\", \"field\")\n\ta.fooBar //@item(fuzzFooBarField, \"a.fooBar\", \"string\", \"field\")\n\n\tafa //@complete(re\"() \\\\/\\\\/\", fuzzFabarField, fuzzFooBarField)\n\tafb //@complete(re\"() \\\\/\\\\/\", fuzzFooBarField, fuzzFabarField)\n\n\tfab //@complete(re\"() \\\\/\\\\/\", fuzzFabarField)\n\n\tvar myString string\n\tmyString = af //@complete(re\"() \\\\/\\\\/\", fuzzFooBarField, fuzzFabarField)\n\n\tvar b struct {\n\t\tc struct {\n\t\t\td struct {\n\t\t\t\te struct {\n\t\t\t\t\tabc string\n\t\t\t\t}\n\t\t\t\tabc float32\n\t\t\t}\n\t\t\tabc bool\n\t\t}\n\t\tabc int\n\t}\n\n\tb.abc       //@item(fuzzABCInt, \"b.abc\", \"int\", \"field\")\n\tb.c.abc     //@item(fuzzABCbool, \"b.c.abc\", \"bool\", \"field\")\n\tb.c.d.abc   //@item(fuzzABCfloat, \"b.c.d.abc\", \"float32\", \"field\")\n\tb.c.d.e.abc //@item(fuzzABCstring, \"b.c.d.e.abc\", \"string\", \"field\")\n\n\t// in depth order by default\n\tabc //@complete(re\"() \\\\/\\\\/\", fuzzABCInt, fuzzABCbool, fuzzABCfloat)\n\n\t// deep candidate that matches expected type should still ranked first\n\tvar s string\n\ts = abc //@complete(re\"() \\\\/\\\\/\", fuzzABCstring, fuzzABCInt, fuzzABCbool)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/imported-std.txt",
    "content": "Test of imported completions respecting the effective Go version of the file.\n\n(See \"un-\" prefixed file for same test of unimported completions.)\n\nThese symbols below were introduced to go/types in go1.22:\n\n  Alias\n  Info.FileVersions\n  (Checker).PkgNameOf\n\nThe underlying logic depends on versions.FileVersion, which only\nbehaves correctly in go1.22. (When go1.22 is assured, we can remove\nthe min_go flag but leave the test inputs unchanged.)\n\n-- flags --\n-ignore_extra_diags\n-min_go_command=go1.22\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\nimport \"go/ast\"\nimport \"go/token\"\nimport \"go/types\"\n\n// package-level decl\nvar _ = types.Sat //@rank(re\"()Sat\", \"Satisfies\")\nvar _ = types.Ali //@rank(re\"()Ali\", \"!Alias\")\n\n// field\nvar _ = new(types.Info).Use //@rank(re\"()Use\", \"Uses\")\nvar _ = new(types.Info).Fil //@rank(re\"()Fil\", \"!FileVersions\")\n\n// method\nvar _ = new(types.Checker).Obje //@rank(re\"()Obje\", \"ObjectOf\")\nvar _ = new(types.Checker).PkgN //@rank(re\"()PkgN\", \"!PkgNameOf\")\n\n-- b/b.go --\n//go:build go1.22\n\npackage a\n\nimport \"go/ast\"\nimport \"go/token\"\nimport \"go/types\"\n\n// package-level decl\nvar _ = types.Sat //@rank(re\"()Sat\", \"Satisfies\")\nvar _ = types.Ali //@rank(re\"()Ali\", \"Alias\")\n\n// field\nvar _ = new(types.Info).Use //@rank(re\"()Use\", \"Uses\")\nvar _ = new(types.Info).Fil //@rank(re\"()Fil\", \"FileVersions\")\n\n// method\nvar _ = new(types.Checker).Obje //@rank(re\"()Obje\", \"ObjectOf\")\nvar _ = new(types.Checker).PkgN //@rank(re\"()PkgN\", \"PkgNameOf\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/index.txt",
    "content": "This test checks completion related to index expressions.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- index.go --\npackage index\n\nfunc _() {\n\tvar (\n\t\taa = \"123\" //@item(indexAA, \"aa\", \"string\", \"var\")\n\t\tab = 123   //@item(indexAB, \"ab\", \"int\", \"var\")\n\t)\n\n\tvar foo [1]int\n\tfoo[a]  //@complete(re\"()\\\\]\", indexAB, indexAA)\n\tfoo[:a] //@complete(re\"()\\\\]\", indexAB, indexAA)\n\ta[:a]   //@complete(re\"()\\\\[\", indexAA, indexAB)\n\ta[a]    //@complete(re\"()\\\\[\", indexAA, indexAB)\n\n\tvar bar map[string]int\n\tbar[a] //@complete(re\"()\\\\]\", indexAA, indexAB)\n\n\ttype myMap map[string]int\n\tvar baz myMap\n\tbaz[a] //@complete(re\"()\\\\]\", indexAA, indexAB)\n\n\ttype myInt int\n\tvar mi myInt //@item(indexMyInt, \"mi\", \"myInt\", \"var\")\n\tfoo[m]       //@snippet(re\"()\\\\]\", indexMyInt, \"mi\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/interfacerank.txt",
    "content": "This test checks that completion ranking accounts for interface assignability.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"deepCompletion\": false\n}\n\n-- p.go --\n\npackage interfacerank\n\ntype foo interface {\n\tfoo()\n}\n\ntype fooImpl int\n\nfunc (*fooImpl) foo() {}\n\nfunc wantsFoo(foo) {}\n\nfunc _() {\n\tvar (\n\t\taa string   //@item(irAA, \"aa\", \"string\", \"var\")\n\t\tab *fooImpl //@item(irAB, \"ab\", \"*fooImpl\", \"var\")\n\t)\n\n\twantsFoo(a) //@complete(re\"()\\\\)\", irAB, irAA)\n\n\tvar ac fooImpl //@item(irAC, \"ac\", \"fooImpl\", \"var\")\n\twantsFoo(&a)   //@complete(re\"()\\\\)\", irAC, irAA, irAB)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue51783.txt",
    "content": "Regression test for \"completion gives unneeded generic type\ninstantiation snippet\", #51783.\n\nType parameters that can be inferred from the arguments\nare not part of the offered completion snippet.\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage a\n\n// identity has a single simple type parameter.\n// The completion omits the instantiation.\nfunc identity[T any](x T) T\n\n// clone has a second type parameter that is nonetheless constrained by the parameter.\n// The completion omits the instantiation.\nfunc clone[S ~[]E, E any](s S) S\n\n// unconstrained has a type parameter constrained only by the result.\n// The completion suggests instantiation.\nfunc unconstrained[X, Y any](x X) Y\n\n// partial has three type parameters,\n// only the last two of which may be omitted as they\n// are constrained by the arguments.\nfunc partial[R any, S ~[]E, E any](s S) R\n\n//@item(identity, \"identity\", \"details\", \"kind\")\n//@item(clone, \"clone\", \"details\", \"kind\")\n//@item(unconstrained, \"unconstrained\", \"details\", \"kind\")\n//@item(partial, \"partial\", \"details\", \"kind\")\n\nfunc _() {\n\t_ = identity //@snippet(re\"()identity\", identity, \"identity(${1:})\")\n\n\t_ = clone //@snippet(re\"()clone\", clone, \"clone(${1:})\")\n\n\t_ = unconstrained //@snippet(re\"()unconstrained\", unconstrained, \"unconstrained[${1:}](${2:})\")\n\n\t_ = partial //@snippet(re\"()partial\", partial, \"partial[${1:}](${2:})\")\n\n\t// Result-type inference permits us to omit Y in this (rare) case,\n\t// but completion doesn't support that.\n\tvar _ int = unconstrained //@snippet(re\"()unconstrained\", unconstrained, \"unconstrained[${1:}](${2:})\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue56505.txt",
    "content": "Test for golang/go#56505: completion on variables of type *error should not\npanic.\n\n-- flags --\n-ignore_extra_diags\n\n-- issue.go --\npackage issues\n\nfunc _() {\n\tvar e *error\n\te.x //@complete(re\"() \\\\/\\\\/\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue59096.txt",
    "content": "This test exercises the panic in golang/go#59096: completing at a syntactic\ntype-assert expression was panicking because gopls was translating it into\na (malformed) selector expr.\n\n-- settings.json --\n{\n\t\"importsSource\": \"gopls\"\n}\n\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tb.(foo) //@complete(re\"b.()\", B), diag(\"b\", re\"(undefined|undeclared name): b\")\n}\n\n//@item(B, \"B\", \"const (from \\\"example.com/b\\\")\", \"const\")\n\n-- b/b.go --\npackage b\n\nconst B = 0\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue60545.txt",
    "content": "This test checks that unimported completion is case-insensitive.\n\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n\n-- settings.json --\n{\n\t\"importsSource\": \"gopls\"\n}\n\n-- main.go --\npackage main\n\n//@item(Print, \"Print\", \"func (from \\\"fmt\\\")\", \"func\")\n//@item(Printf, \"Printf\", \"func (from \\\"fmt\\\")\", \"func\")\n//@item(Println, \"Println\", \"func (from \\\"fmt\\\")\", \"func\")\n\nfunc main() {\n\tfmt.p //@complete(re\"fmt.p()\", Print, Printf, Println), diag(\"fmt\", re\"(undefined|undeclared)\")\n}\n\n-- other.go --\npackage main\n\n// Including another package that imports \"fmt\" causes completion to use the\n// existing metadata, which is the codepath leading to golang/go#60545.\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println()\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue62141.txt",
    "content": "This test checks that we don't suggest completion to an untyped conversion such\nas \"untyped float(abcdef)\".\n\n-- main.go --\npackage main\n\nfunc main() {\n\tabcdef := 32 //@diag(\"abcdef\", re\"not used\")\n\tx := 1.0 / abcd //@acceptcompletion(re\"abcd()\", \"abcdef\", int), diag(\"x\", re\"not used\"), diag(\"abcd\", re\"(undefined|undeclared)\")\n\n\t// Verify that we don't suggest converting compatible untyped constants.\n\tconst untypedConst = 42\n\ty := 1.1 / untypedC //@acceptcompletion(re\"untypedC()\", \"untypedConst\", untyped), diag(\"y\", re\"not used\"), diag(\"untypedC\", re\"(undefined|undeclared)\")\n}\n\n-- @int/main.go --\npackage main\n\nfunc main() {\n\tabcdef := 32 //@diag(\"abcdef\", re\"not used\")\n\tx := 1.0 / float64(abcdef) //@acceptcompletion(re\"abcd()\", \"abcdef\", int), diag(\"x\", re\"not used\"), diag(\"abcd\", re\"(undefined|undeclared)\")\n\n\t// Verify that we don't suggest converting compatible untyped constants.\n\tconst untypedConst = 42\n\ty := 1.1 / untypedC //@acceptcompletion(re\"untypedC()\", \"untypedConst\", untyped), diag(\"y\", re\"not used\"), diag(\"untypedC\", re\"(undefined|undeclared)\")\n}\n\n-- @untyped/main.go --\npackage main\n\nfunc main() {\n\tabcdef := 32 //@diag(\"abcdef\", re\"not used\")\n\tx := 1.0 / abcd //@acceptcompletion(re\"abcd()\", \"abcdef\", int), diag(\"x\", re\"not used\"), diag(\"abcd\", re\"(undefined|undeclared)\")\n\n\t// Verify that we don't suggest converting compatible untyped constants.\n\tconst untypedConst = 42\n\ty := 1.1 / untypedConst //@acceptcompletion(re\"untypedC()\", \"untypedConst\", untyped), diag(\"y\", re\"not used\"), diag(\"untypedC\", re\"(undefined|undeclared)\")\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue62560.txt",
    "content": "This test verifies that completion of package members in unimported packages\nreflects their fuzzy score, even when those members are present in the\ntransitive import graph of the main module. (For technical reasons, this was\nthe nature of the regression in golang/go#62560.)\n\n-- go.mod --\nmodule mod.test\n\n-- foo/foo.go --\npackage foo\n\nfunc _() {\n\tjson.U //@rank(re\"U()\", \"Unmarshal\", \"InvalidUTF8Error\"), diag(\"json\", re\"(undefined|undeclared)\")\n}\n\n-- bar/bar.go --\npackage bar\n\nimport _ \"encoding/json\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue62676.txt",
    "content": "This test verifies that unimported completion respects the usePlaceholders setting.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": false\n}\n\n-- go.mod --\nmodule mod.test\n\ngo 1.21\n\n-- foo/foo.go --\npackage foo\n\nfunc _() {\n\t// This uses goimports-based completion; TODO: this should insert snippets.\n\tos.Open //@acceptcompletion(re\"Open()\", \"Open\", open)\n}\n\nfunc _() {\n\t// This uses metadata-based completion.\n\terrors.New //@acceptcompletion(re\"New()\", \"New\", new)\n}\n\n-- bar/bar.go --\npackage bar\n\nimport _ \"errors\" // important: doesn't transitively import os.\n\n-- @new/foo/foo.go --\npackage foo\n\nimport \"errors\"\n\nfunc _() {\n\t// This uses goimports-based completion; TODO: this should insert snippets.\n\tos.Open //@acceptcompletion(re\"Open()\", \"Open\", open)\n}\n\nfunc _() {\n\t// This uses metadata-based completion.\n\terrors.New(${1:}) //@acceptcompletion(re\"New()\", \"New\", new)\n}\n\n-- @open/foo/foo.go --\npackage foo\n\nimport \"os\"\n\nfunc _() {\n\t// This uses goimports-based completion; TODO: this should insert snippets.\n\tos.Open(${1:}) //@acceptcompletion(re\"Open()\", \"Open\", open)\n}\n\nfunc _() {\n\t// This uses metadata-based completion.\n\terrors.New //@acceptcompletion(re\"New()\", \"New\", new)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue70636.txt",
    "content": "This test reproduces the crash of golang/go#70636, an out of bounds error when\nanalyzing a return statement with more results than the signature expects.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- p.go --\npackage p\n\nvar xx int\nvar xy string\n\n\nfunc _() {\n\treturn Foo(x) //@ rank(re\"x()\", \"xx\", \"xy\")\n}\n\nfunc Foo[T any](t T) T {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/issue72753.txt",
    "content": "This test checks that completion gives correct completion for\nincomplete AssignStmt with multiple left-hand vars.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": false\n}\n\n-- go.mod --\nmodule mod.test\n\ngo 1.21\n\n-- string.go --\npackage a\n\nfunc _(left, right string){\n\tleft, ri //@acceptcompletion(re\"ri()\", \"right\", string)\n}\n\n-- @string/string.go --\npackage a\n\nfunc _(left, right string){\n\tleft, right //@acceptcompletion(re\"ri()\", \"right\", string)\n}\n\n-- array.go --\npackage a\nfunc _(right string) {\n\tvar left [3]int\n\tleft[0], ri //@acceptcompletion(re\"ri()\", \"right\", array)\n}\n\n-- @array/array.go --\npackage a\nfunc _(right string) {\n\tvar left [3]int\n\tleft[0], right //@acceptcompletion(re\"ri()\", \"right\", array)\n}\n\n-- slice.go --\npackage a\nfunc _(right string) {\n\tvar left []int\n\tleft[0], ri //@acceptcompletion(re\"ri()\", \"right\", slice)\n}\n\n-- @slice/slice.go --\npackage a\nfunc _(right string) {\n\tvar left []int\n\tleft[0], right //@acceptcompletion(re\"ri()\", \"right\", slice)\n}\n\n-- map.go --\npackage a\nfunc _(right string) {\n\tvar left map[int]int\n\tleft[0], ri //@acceptcompletion(re\"ri()\", \"right\", map)\n}\n\n-- @map/map.go --\npackage a\nfunc _(right string) {\n\tvar left map[int]int\n\tleft[0], right //@acceptcompletion(re\"ri()\", \"right\", map)\n}\n\n-- star.go --\npackage a\nfunc _(right string) {\n\tvar left *int\n\t*left, ri //@acceptcompletion(re\"ri()\", \"right\", star)\n}\n\n-- @star/star.go --\npackage a\nfunc _(right string) {\n\tvar left *int\n\t*left, right //@acceptcompletion(re\"ri()\", \"right\", star)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/keywords.txt",
    "content": "This test checks completion of Go keywords.\n\n-- flags --\n-ignore_extra_diags\n-filter_keywords=false\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"matcher\": \"caseInsensitive\",\n\t\"experimentalPostfixCompletions\": false\n}\n\n-- keywords.go --\npackage keywords\n\n//@rank(\"\", type),rank(\"\", func),rank(\"\", var),rank(\"\", const),rank(\"\", import)\n\nfunc _() {\n\tvar test int //@rank(re\"() \\\\/\\\\/\", int, interface)\n\tvar tChan chan int\n\tvar _ m //@complete(re\"() \\\\/\\\\/\", map)\n\tvar _ f //@complete(re\"() \\\\/\\\\/\", func)\n\tvar _ c //@complete(re\"() \\\\/\\\\/\", chan)\n\n\tvar _ str //@rank(re\"() \\\\/\\\\/\", string, struct)\n\n\ttype _ int //@rank(re\"() \\\\/\\\\/\", interface, int)\n\n\ttype _ str //@rank(re\"() \\\\/\\\\/\", struct, string)\n\n\tswitch test {\n\tcase 1: // TODO: trying to complete case here will break because the parser won't return *ast.Ident\n\t\tb //@complete(re\"() \\\\/\\\\/\", break)\n\tcase 2:\n\t\tf //@complete(re\"() \\\\/\\\\/\", fallthrough, for)\n\t\tr //@complete(re\"() \\\\/\\\\/\", return)\n\t\td //@complete(re\"() \\\\/\\\\/\", default, defer)\n\t\tc //@complete(re\"() \\\\/\\\\/\", case, const)\n\t}\n\n\tswitch test.(type) {\n\tcase fo: //@complete(re\"():\")\n\tcase int:\n\t\tb //@complete(re\"() \\\\/\\\\/\", break)\n\tcase int32:\n\t\tf //@complete(re\"() \\\\/\\\\/\", for)\n\t\td //@complete(re\"() \\\\/\\\\/\", default, defer)\n\t\tr //@complete(re\"() \\\\/\\\\/\", return)\n\t\tc //@complete(re\"() \\\\/\\\\/\", case, const)\n\t}\n\n\tselect {\n\tcase <-tChan:\n\t\tb //@complete(re\"() \\\\/\\\\/\", break)\n\t\tc //@complete(re\"() \\\\/\\\\/\", case, const)\n\t}\n\n\tfor index := 0; index < test; index++ {\n\t\tc //@complete(re\"() \\\\/\\\\/\", const, continue)\n\t\tb //@complete(re\"() \\\\/\\\\/\", break)\n\t}\n\n\tfor range []int{} {\n\t\tc //@complete(re\"() \\\\/\\\\/\", const, continue)\n\t\tb //@complete(re\"() \\\\/\\\\/\", break)\n\t}\n\n\t// Test function level keywords\n\n\t//Using 2 characters to test because map output order is random\n\tsw //@complete(re\"() \\\\/\\\\/\", switch)\n\tse //@complete(re\"() \\\\/\\\\/\", select)\n\n\tf //@complete(re\"() \\\\/\\\\/\", for)\n\td //@complete(re\"() \\\\/\\\\/\", defer)\n\tg //@rank(re\"() \\\\/\\\\/\", go),rank(re\"() \\\\/\\\\/\", goto)\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n\ti //@complete(re\"() \\\\/\\\\/\", if)\n\te //@complete(re\"() \\\\/\\\\/\", else)\n\tv //@complete(re\"() \\\\/\\\\/\", var)\n\tc //@complete(re\"() \\\\/\\\\/\", const)\n\n\tfor i := r //@complete(re\"() \\\\/\\\\/\", range)\n}\n\n/* package */ //@item(package, \"package\", \"\", \"keyword\")\n/* import */ //@item(import, \"import\", \"\", \"keyword\")\n/* func */ //@item(func, \"func\", \"\", \"keyword\")\n/* type */ //@item(type, \"type\", \"\", \"keyword\")\n/* var */ //@item(var, \"var\", \"\", \"keyword\")\n/* const */ //@item(const, \"const\", \"\", \"keyword\")\n/* break */ //@item(break, \"break\", \"\", \"keyword\")\n/* default */ //@item(default, \"default\", \"\", \"keyword\")\n/* case */ //@item(case, \"case\", \"\", \"keyword\")\n/* defer */ //@item(defer, \"defer\", \"\", \"keyword\")\n/* go */ //@item(go, \"go\", \"\", \"keyword\")\n/* for */ //@item(for, \"for\", \"\", \"keyword\")\n/* if */ //@item(if, \"if\", \"\", \"keyword\")\n/* else */ //@item(else, \"else\", \"\", \"keyword\")\n/* switch */ //@item(switch, \"switch\", \"\", \"keyword\")\n/* select */ //@item(select, \"select\", \"\", \"keyword\")\n/* fallthrough */ //@item(fallthrough, \"fallthrough\", \"\", \"keyword\")\n/* continue */ //@item(continue, \"continue\", \"\", \"keyword\")\n/* return */ //@item(return, \"return\", \"\", \"keyword\")\n/* goto */ //@item(goto, \"goto\", \"\", \"keyword\")\n/* struct */ //@item(struct, \"struct\", \"\", \"keyword\")\n/* interface */ //@item(interface, \"interface\", \"\", \"keyword\")\n/* map */ //@item(map, \"map\", \"\", \"keyword\")\n/* chan */ //@item(chan, \"chan\", \"\", \"keyword\")\n/* range */ //@item(range, \"range\", \"\", \"keyword\")\n/* string */ //@item(string, \"string\", \"\", \"type\")\n/* int */ //@item(int, \"int\", \"\", \"type\")\n\n-- accidental_keywords.go --\npackage keywords\n\n// non-matching candidate - shouldn't show up as completion\nvar apple = \"apple\"\n\nfunc _() {\n\tfoo.bar() // insert some extra statements to exercise our AST surgery\n\tvariance := 123 //@item(kwVariance, \"variance\", \"int\", \"var\")\n\tfoo.bar()\n\tprintln(var) //@complete(re\"()\\\\)\", kwVariance)\n}\n\nfunc _() {\n\tfoo.bar()\n\tvar s struct { variance int } //@item(kwVarianceField, \"variance\", \"int\", \"field\")\n\tfoo.bar()\n\ts.var //@complete(re\"() \\\\/\\\\/\", kwVarianceField)\n}\n\nfunc _() {\n\tchannel := 123 //@item(kwChannel, \"channel\", \"int\", \"var\")\n\tchan //@complete(re\"() \\\\/\\\\/\", kwChannel)\n\tfoo.bar()\n}\n\nfunc _() {\n\tfoo.bar()\n\tvar typeName string //@item(kwTypeName, \"typeName\", \"string\", \"var\")\n\tfoo.bar()\n\ttype //@complete(re\"() \\\\/\\\\/\", kwTypeName)\n}\n-- empty_select.go --\npackage keywords\n\nfunc _() {\n\tselect {\n\t\tc //@complete(re\"() \\\\/\\\\/\", case)\n\t}\n}\n-- empty_switch.go --\npackage keywords\n\nfunc _() {\n\tswitch {\n\t\t//@complete(\"\", case, default)\n\t}\n\n\tswitch test.(type) {\n\t\td //@complete(re\"() \\\\/\\\\/\", default)\n\t}\n}\n\n-- default_name_var_switch.go --\npackage keywords\n\nfunc _() {\n\tvar defaultVar int //@item(defaultVar, \"defaultVar\", \"int\", \"var\")\n\tswitch defaultVar {\n\t\tcase 1:\n\t\t\tprintln(\"helloworld\")\n\t\td //@complete(re\"() \\\\/\\\\/\", default, defaultVar, defer)\n\t}\n\tswitch defaultVar {\n\t\tdefault:\n\t\td //@complete(re\"() \\\\/\\\\/\", defaultVar, defer)\n\t}\n\tvar nested int\n\tswitch defaultVar {\n\t\tcase 1:\n\t\t\tswitch nested {\n\t\t\t\tdefault:\n\t\t\t\t\tprintln(\"\")\n\t\t\t}\n\t\td //@complete(re\"() \\\\/\\\\/\", default, defaultVar, defer)\n\t}\n}\n\n-- return_different_func.go --\npackage keywords\n\n/* return  */ //@item(returnWithSpace, \"return \", \"\", \"keyword\")\n\n\nfunc _ () int {\n\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n}\n\nfunc _ () (int, int) {\n\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n}\n\nfunc _ () (_ int) {\n\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n}\n\nfunc _ () (_ int) {\n\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n}\n\nfunc _ () (_, _ int) {\n\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n}\n\nfunc _ () (_, a int) {\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n}\n\nfunc _ () {\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n}\n\nfunc _ () (a int) {\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n}\n\nfunc _ () (a, b int) {\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n}\n\nfunc _ () (a, b int, c string) {\n\tr //@complete(re\"() \\\\/\\\\/\", return)\n}\n\nfunc _ () (a int) {\n\t_ = func (){\n\t\tr //@complete(re\"() \\\\/\\\\/\", return)\n\t}\n\treturn\n}\n\nfunc _ () int {\n\t_ = func () (a int) {\n\t\t// func lit will be affected by outer function.\n\t\tr //@complete(re\"() \\\\/\\\\/\", returnWithSpace)\n\t}\n\treturn\n}\n\nfunc _ () {\n\t_ = func () int {\n\t\t// func lit will be affected by outer function.\n\t\tr //@complete(re\"() \\\\/\\\\/\", return)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/labels.txt",
    "content": "This test checks completion of labels.\n\n-- flags --\n-ignore_extra_diags\n\n-- labels.go --\npackage labels\n\nfunc _() {\n\tgoto F //@complete(re\"() \\\\/\\\\/\", label1, label5)\n\nFoo1: //@item(label1, \"Foo1\", \"label\", \"const\")\n\tfor a, b := range []int{} {\n\tFoo2: //@item(label2, \"Foo2\", \"label\", \"const\")\n\t\tswitch {\n\t\tcase true:\n\t\t\tbreak F //@complete(re\"() \\\\/\\\\/\", label2, label1)\n\n\t\t\tcontinue F //@complete(re\"() \\\\/\\\\/\", label1)\n\n\t\t\t{\n\t\t\tFooUnjumpable:\n\t\t\t}\n\n\t\t\tgoto F //@complete(re\"() \\\\/\\\\/\", label1, label2, label4, label5)\n\n\t\t\tfunc() {\n\t\t\t\tgoto F //@complete(re\"() \\\\/\\\\/\", label3)\n\n\t\t\t\tbreak F //@complete(re\"() \\\\/\\\\/\")\n\n\t\t\t\tcontinue F //@complete(re\"() \\\\/\\\\/\")\n\n\t\t\tFoo3: //@item(label3, \"Foo3\", \"label\", \"const\")\n\t\t\t}()\n\t\t}\n\n\tFoo4: //@item(label4, \"Foo4\", \"label\", \"const\")\n\t\tswitch any(a).(type) {\n\t\tcase int:\n\t\t\tbreak F //@complete(re\"() \\\\/\\\\/\", label4, label1)\n\t\t}\n\t}\n\n\tbreak F //@complete(re\"() \\\\/\\\\/\")\n\n\tcontinue F //@complete(re\"() \\\\/\\\\/\")\n\nFoo5: //@item(label5, \"Foo5\", \"label\", \"const\")\n\tfor {\n\t\tbreak F //@complete(re\"() \\\\/\\\\/\", label5)\n\t}\n\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/lit.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n\n-- foo/foo.go --\npackage foo\n\ntype StructFoo struct{ F int }\n\n-- a.go --\npackage a\n\nimport \"mod.test/foo\"\n\nfunc _() {\n\tStructFoo{} //@item(litStructFoo, \"StructFoo{}\", \"struct{...}\", \"struct\")\n\n\tvar sfp *foo.StructFoo\n\t// Don't insert the \"&\" before \"StructFoo{}\".\n\tsfp = foo.Str //@snippet(re\"() \\\\/\\\\/\", litStructFoo, \"StructFoo{$0\\\\}\")\n\n\tvar sf foo.StructFoo\n\tsf = foo.Str //@snippet(re\"() \\\\/\\\\/\", litStructFoo, \"StructFoo{$0\\\\}\")\n\tsf = foo. //@snippet(re\"() \\\\/\\\\/\", litStructFoo, \"StructFoo{$0\\\\}\")\n}\n\n-- http.go --\npackage a\n\nimport (\n\t\"net/http\"\n\t\"sort\"\n)\n\nfunc _() {\n\tsort.Slice(nil, fun) //@snippet(re\"()\\\\)\", litFunc, \"func(i, j int) bool {$0\\\\}\")\n\n\thttp.HandleFunc(\"\", f) //@snippet(re\"()\\\\)\", litFunc, \"func(w http.ResponseWriter, r *http.Request) {$0\\\\}\")\n\n\t//@item(litFunc, \"func(...) {}\", \"\", \"var\")\n\thttp.HandlerFunc() //@item(handlerFunc, \"http.HandlerFunc()\", \"\", \"var\")\n\thttp.Handle(\"\", http.HandlerFunc()) //@snippet(re\"()\\\\)\\\\)\", litFunc, \"func(w http.ResponseWriter, r *http.Request) {$0\\\\}\")\n\thttp.Handle(\"\", h) //@snippet(re\"()\\\\)\", handlerFunc, \"http.HandlerFunc($0)\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/maps.txt",
    "content": "This test checks completion of map keys and values.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- maps.go --\npackage maps\n\nfunc _() {\n\tvar aVar int          //@item(mapVar, \"aVar\", \"int\", \"var\")\n\n\t// not comparabale\n\ttype aSlice []int     //@item(mapSliceType, \"aSlice\", \"[]int\", \"type\")\n\n\t*aSlice     //@item(mapSliceTypePtr, \"*aSlice\", \"[]int\", \"type\")\n\n\t// comparable\n\ttype aStruct struct{} //@item(mapStructType, \"aStruct\", \"struct{...}\", \"struct\")\n\n\tmap[]a{} //@complete(re\"()\\\\]\", mapSliceType, mapStructType),snippet(re\"()]\", mapSliceType, \"*aSlice\")\n\n\tmap[a]a{} //@complete(re\"()\\\\]\", mapSliceType, mapStructType)\n\tmap[a]a{} //@complete(re\"(){\", mapSliceType, mapStructType)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/multi_return.txt",
    "content": "This test checks various ranking of completion results related to functions\nwith multiple return values.\n\n-- flags --\n-ignore_extra_diags\n\n-- multireturn.go --\npackage multireturn\n\nfunc f0() {} //@item(multiF0, \"f0\", \"func()\", \"func\")\n\nfunc f1(int) int { return 0 } //@item(multiF1, \"f1\", \"func(int) int\", \"func\")\n\nfunc f2(int, int) (int, int) { return 0, 0 } //@item(multiF2, \"f2\", \"func(int, int) (int, int)\", \"func\")\n\nfunc f2Str(string, string) (string, string) { return \"\", \"\" } //@item(multiF2Str, \"f2Str\", \"func(string, string) (string, string)\", \"func\")\n\nfunc f3(int, int, int) (int, int, int) { return 0, 0, 0 } //@item(multiF3, \"f3\", \"func(int, int, int) (int, int, int)\", \"func\")\n\nfunc _() {\n\t_ := f //@rank(re\"() \\\\/\\\\/\", multiF1, multiF2)\n\n\t_, _ := f //@rank(re\"() \\\\/\\\\/\", multiF2, multiF0),rank(re\"() \\\\/\\\\/\", multiF1, multiF0)\n\n\t_, _ := _, f //@rank(re\"() \\\\/\\\\/\", multiF1, multiF2),rank(re\"() \\\\/\\\\/\", multiF1, multiF0)\n\n\t_, _ := f, abc //@rank(re\"(), abc\", multiF1, multiF2)\n\n\tf1()     //@rank(re\"()\\\\)\", multiF1, multiF0)\n\tf1(f)    //@rank(re\"()\\\\)\", multiF1, multiF2)\n\tf2(f)    //@rank(re\"()\\\\)\", multiF2, multiF3),rank(re\"()\\\\)\", multiF1, multiF3)\n\tf2(1, f) //@rank(re\"()\\\\)\", multiF1, multiF2),rank(re\"()\\\\)\", multiF1, multiF0)\n\tf2(1, )  //@rank(re\"()\\\\)\", multiF1, multiF2),rank(re\"()\\\\)\", multiF1, multiF0)\n\tf2Str()  //@rank(re\"()\\\\)\", multiF2Str, multiF2)\n\n\tvar i int\n\ti, _ := f //@rank(re\"() \\\\/\\\\/\", multiF2, multiF2Str)\n\n\tvar s string\n\t_, s := f //@rank(re\"() \\\\/\\\\/\", multiF2Str, multiF2)\n\n\tbanana, s = f //@rank(re\"() \\\\/\\\\/\", multiF2, multiF3)\n\n\tvar variadic func(int, ...int)\n\tvariadic() //@rank(re\"()\\\\)\", multiF1, multiF0),rank(re\"()\\\\)\", multiF2, multiF0),rank(re\"()\\\\)\", multiF3, multiF0)\n}\n\nfunc _() {\n\tvar baz func(...any)\n\n\tvar otterNap func() (int, int) //@item(multiTwo, \"otterNap\", \"func() (int, int)\", \"var\")\n\tvar one int                    //@item(multiOne, \"one\", \"int\", \"var\")\n\n\tbaz(on) //@rank(re\"()\\\\)\", multiOne, multiTwo)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/nested_complit.txt",
    "content": "This test checks completion of nested composite literals;\n\nParser recovery changed in Go 1.20, so this test requires at least that\nversion for consistency.\n\n-- flags --\n-ignore_extra_diags\n\n-- nested_complit.go --\npackage nested_complit\n\ntype ncFoo struct {} //@item(structNCFoo, \"ncFoo\", \"struct{...}\", \"struct\")\n\ntype ncBar struct { //@item(structNCBar, \"ncBar\", \"struct{...}\", \"struct\")\n\tbaz []ncFoo\n}\n\nfunc _() {\n\t_ = []ncFoo{} //@item(litNCFoo, \"[]ncFoo{}\", \"\", \"var\")\n\t_ = make([]ncFoo, 0) //@item(makeNCFoo, \"make([]ncFoo, 0)\", \"\", \"func\")\n\n\t_ := ncBar{\n\t\tbaz: [] //@complete(re\"() \\\\/\\\\/\", litNCFoo, makeNCFoo, structNCBar, structNCFoo)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/postfix.txt",
    "content": "These tests check that postfix completions do and do not show up in certain\ncases. Tests for the postfix completion contents are implemented as ad-hoc\nintegration tests.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/snippets\n\ngo 1.18\n\n-- postfix.go --\npackage snippets\n\nimport (\n\t\"strconv\"\n)\n\nfunc _() {\n\tvar foo []int\n\tfoo.append //@rank(re\"() \\\\/\\\\/\", postfixAppend)\n\n\t[]int{}.append //@complete(re\"() \\\\/\\\\/\")\n\n\t[]int{}.last //@complete(re\"() \\\\/\\\\/\")\n\n\n\tfoo.copy //@rank(re\"() \\\\/\\\\/\", postfixCopy)\n\n\tvar s struct{ i []int }\n\ts.i.copy //@rank(re\"() \\\\/\\\\/\", postfixCopy)\n\n\tvar _ []int = s.i.copy //@complete(re\"() \\\\/\\\\/\")\n\n\tvar blah func() []int\n\tblah().append //@complete(re\"() \\\\/\\\\/\")\n}\n\nfunc _() {\n\t/* append! */ //@item(postfixAppend, \"append!\", \"append and re-assign slice\", \"snippet\")\n\t/* copy! */ //@item(postfixCopy, \"copy!\", \"duplicate slice\", \"snippet\")\n\t/* for! */ //@item(postfixFor, \"for!\", \"range over slice by index\", \"snippet\")\n\t/* forr! */ //@item(postfixForr, \"forr!\", \"range over slice by index and value\", \"snippet\")\n\t/* last! */ //@item(postfixLast, \"last!\", \"s[len(s)-1]\", \"snippet\")\n\t/* len! */ //@item(postfixLen, \"len!\", \"len(s)\", \"snippet\")\n\t/* print! */ //@item(postfixPrint, \"print!\", \"print to stdout\", \"snippet\")\n\t/* range! */ //@item(postfixRange, \"range!\", \"range over slice\", \"snippet\")\n\t/* reverse! */ //@item(postfixReverse, \"reverse!\", \"reverse slice\", \"snippet\")\n\t/* sort! */ //@item(postfixSort, \"sort!\", \"sort.Slice()\", \"snippet\")\n\t/* var! */ //@item(postfixVar, \"var!\", \"assign to variable\", \"snippet\")\n\t/* ifnotnil! */ //@item(postfixIfNotNil, \"ifnotnil!\", \"if expr != nil\", \"snippet\")\n\n\tvar foo []int\n\tfoo. //@complete(re\"() \\\\/\\\\/\", postfixAppend, postfixCopy, postfixFor, postfixForr, postfixIfNotNil, postfixLast, postfixLen, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixVar)\n\tfoo = nil\n\n\tfoo.append //@snippet(re\"() \\\\/\\\\/\", postfixAppend, \"foo = append(foo, $0)\")\n\tfoo.copy //snippet(re\"() \\\\/\\\\/\", postfixCopy, \"fooCopy := make([]int, len(foo))\\ncopy($fooCopy, foo)\\n\")\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixFor, \"for ${1:} := range foo {\\n\\t$0\\n}\")\n\tfoo.forr //@snippet(re\"() \\\\/\\\\/\", postfixForr, \"for ${1:}, ${2:} := range foo {\\n\\t$0\\n}\")\n\tfoo.last //@snippet(re\"() \\\\/\\\\/\", postfixLast, \"foo[len(foo)-1]\")\n\tfoo.len //@snippet(re\"() \\\\/\\\\/\", postfixLen, \"len(foo)\")\n\tfoo.print //@snippet(re\"() \\\\/\\\\/\", postfixPrint, `fmt.Printf(\"foo: %v\\n\", foo)`)\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRange, \"for ${1:}, ${2:} := range foo {\\n\\t$0\\n}\")\n\tfoo.reverse //@snippet(re\"() \\\\/\\\\/\", postfixReverse, \"slices.Reverse(foo)\")\n\tfoo.sort //@snippet(re\"() \\\\/\\\\/\", postfixSort, \"sort.Slice(foo, func(i, j int) bool {\\n\\t$0\\n})\")\n\tfoo.va //@snippet(re\"() \\\\/\\\\/\", postfixVar, \"${1:} := foo\")\n\tfoo.ifnotnil //@snippet(re\"() \\\\/\\\\/\", postfixIfNotNil, \"if foo != nil {\\n\\t$0\\n}\")\n}\n\nfunc _() {\n\t/* for! */ //@item(postfixForMap, \"for!\", \"range over map by key\", \"snippet\")\n\t/* forr! */ //@item(postfixForrMap, \"forr!\", \"range over map by key and value\", \"snippet\")\n\t/* range! */ //@item(postfixRangeMap, \"range!\", \"range over map\", \"snippet\")\n\t/* clear! */ //@item(postfixClear, \"clear!\", \"clear map contents\", \"snippet\")\n\t/* keys! */ //@item(postfixKeys, \"keys!\", \"create slice of keys\", \"snippet\")\n\n\tvar foo map[int]int\n\tfoo. //@complete(re\"() \\\\/\\\\/\", postfixClear, postfixForMap, postfixForrMap, postfixIfNotNil, postfixKeys, postfixLen, postfixPrint, postfixRangeMap, postfixVar)\n\n\tfoo = nil\n\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixFor, \"for ${1:} := range foo {\\n\\t$0\\n}\")\n\tfoo.forr //@snippet(re\"() \\\\/\\\\/\", postfixForr, \"for ${1:}, ${2:} := range foo {\\n\\t$0\\n}\")\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRange, \"for ${1:}, ${2:} := range foo {\\n\\t$0\\n}\")\n\tfoo.clear //@snippet(re\"() \\\\/\\\\/\", postfixClear, \"for k := range foo {\\n\\tdelete(foo, k)\\n}\\n\")\n\tfoo.keys //@snippet(re\"() \\\\/\\\\/\", postfixKeys, \"keys := make([]int, 0, len(foo))\\nfor k := range foo {\\n\\tkeys = append(keys, k)\\n}\\n\")\n}\n\nfunc _() {\n\t/* for! */ //@item(postfixForChannel, \"for!\", \"range over channel\", \"snippet\")\n\t/* range! */ //@item(postfixRangeChannel, \"range!\", \"range over channel\", \"snippet\")\n\n\tvar foo chan int\n\tfoo. //@complete(re\"() \\\\/\\\\/\", postfixForChannel, postfixIfNotNil, postfixLen, postfixPrint, postfixRangeChannel, postfixVar)\n\n\tfoo = nil\n\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixForChannel, \"for ${1:} := range foo {\\n\\t$0\\n}\")\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRangeChannel, \"for ${1:} := range foo {\\n\\t$0\\n}\")\n}\n\ntype T struct {\n\tName string\n}\n\nfunc _() (string, T, map[string]string, error) {\n\t/* iferr! */ //@item(postfixIfErr, \"iferr!\", \"check error and return\", \"snippet\")\n\t/* variferr! */ //@item(postfixVarIfErr, \"variferr!\", \"assign variables and check error\", \"snippet\")\n\t/* var! */ //@item(postfixVars, \"var!\", \"assign to variables\", \"snippet\")\n\n\tstrconv.Atoi(\"32\"). //@complete(re\"() \\\\/\\\\/\", postfixIfErr, postfixPrint, postfixVars, postfixVarIfErr)\n\n\tvar err error\n\terr.iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:}\\n}\\n\")\n\n\tstrconv.Atoi(\"32\").iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if _, err := strconv.Atoi(\\\"32\\\"); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:}\\n}\\n\")\n\n\tstrconv.Atoi(\"32\").variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:}, ${2:} := strconv.Atoi(\\\"32\\\")\\nif ${2:} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${3:}\\n}\\n\")\n\n\t// test function return multiple errors\n\tvar foo func() (error, error)\n\tfoo().iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if _, err := foo(); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:}\\n}\\n\")\n\tfoo().variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:}, ${2:} := foo()\\nif ${2:} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${3:}\\n}\\n\")\n\n\t// test function just return error\n\tvar bar func() error\n\tbar().iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if err := bar(); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:}\\n}\\n\")\n\tbar().variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:} := bar()\\nif ${1:} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${2:}\\n}\\n\")\n}\n\nfunc _(){\n\t/* tostring! */ //@item(postfixToString, \"tostring!\", \"[]byte to string\", \"snippet\")\n\tvar bs []byte\n\tbs. //@complete(re\"() \\\\/\\\\/\", postfixAppend, postfixCopy, postfixFor, postfixForr, postfixIfNotNil, postfixLast, postfixLen, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixToString, postfixVar)\n\tbs = nil\n\n\t/* tobytes! */ //@item(postfixToBytes, \"tobytes!\", \"string to []byte\", \"snippet\")\n\t/* split! */ //@item(postfixSplit, \"split!\", \"split string\", \"snippet\")\n\tvar s string\n\ts. //@complete(re\"() \\\\/\\\\/\", postfixPrint, postfixSplit, postfixToBytes, postfixVar)\n\ts = \"\"\n\n\t/* tostring! */ //@item(postfixIntToString, \"tostring!\", \"int to string\", \"snippet\")\n\tvar i int\n\ti. //@complete(re\"() \\\\/\\\\/\", postfixPrint, postfixIntToString, postfixVar)\n\ti = 0\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/postfix_placeholder.txt",
    "content": "These tests check that postfix completions  when enable usePlaceholders\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": true\n}\n\n-- go.mod --\nmodule golang.org/lsptests/snippets\n\ngo 1.18\n\n-- postfix.go --\npackage snippets\n\nimport (\n\t\"strconv\"\n)\n\nfunc _() {\n\t/* for! */ //@item(postfixFor, \"for!\", \"range over slice by index\", \"snippet\")\n\t/* forr! */ //@item(postfixForr, \"forr!\", \"range over slice by index and value\", \"snippet\")\n\t/* range! */ //@item(postfixRange, \"range!\", \"range over slice\", \"snippet\")\n\t/* var! */ //@item(postfixVar, \"var!\", \"assign to variable\", \"snippet\")\n\n\tvar foo []int\n\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixFor, \"for ${1:i} := range foo {\\n\\t$0\\n}\")\n\tfoo.forr //@snippet(re\"() \\\\/\\\\/\", postfixForr, \"for ${1:i}, ${2:v} := range foo {\\n\\t$0\\n}\")\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRange, \"for ${1:i}, ${2:v} := range foo {\\n\\t$0\\n}\")\n\tfoo.va //@snippet(re\"() \\\\/\\\\/\", postfixVar, \"${1:i} := foo\")\n}\n\nfunc _() {\n\t/* for! */ //@item(postfixForMap, \"for!\", \"range over map by key\", \"snippet\")\n\t/* forr! */ //@item(postfixForrMap, \"forr!\", \"range over map by key and value\", \"snippet\")\n\t/* range! */ //@item(postfixRangeMap, \"range!\", \"range over map\", \"snippet\")\n\n\tvar foo map[int]int\n\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixFor, \"for ${1:k} := range foo {\\n\\t$0\\n}\")\n\tfoo.forr //@snippet(re\"() \\\\/\\\\/\", postfixForr, \"for ${1:k}, ${2:v} := range foo {\\n\\t$0\\n}\")\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRange, \"for ${1:k}, ${2:v} := range foo {\\n\\t$0\\n}\")\n}\n\nfunc _() {\n\t/* for! */ //@item(postfixForChannel, \"for!\", \"range over channel\", \"snippet\")\n\t/* range! */ //@item(postfixRangeChannel, \"range!\", \"range over channel\", \"snippet\")\n\n\tvar foo chan int\n\n\tfoo.fo //@snippet(re\"() \\\\/\\\\/\", postfixForChannel, \"for ${1:e} := range foo {\\n\\t$0\\n}\")\n\tfoo.rang //@snippet(re\"() \\\\/\\\\/\", postfixRangeChannel, \"for ${1:e} := range foo {\\n\\t$0\\n}\")\n}\n\ntype T struct {\n\tName string\n}\n\nfunc _() (string, T, map[string]string, error) {\n\t/* iferr! */ //@item(postfixIfErr, \"iferr!\", \"check error and return\", \"snippet\")\n\t/* variferr! */ //@item(postfixVarIfErr, \"variferr!\", \"assign variables and check error\", \"snippet\")\n\t/* var! */ //@item(postfixVars, \"var!\", \"assign to variables\", \"snippet\")\n\n\n\tvar err error\n\terr.iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:err}\\n}\\n\")\n\tstrconv.Atoi(\"32\").iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if _, err := strconv.Atoi(\\\"32\\\"); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:err}\\n}\\n\")\n\tstrconv.Atoi(\"32\").variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:i}, ${2:err} := strconv.Atoi(\\\"32\\\")\\nif ${2:err} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${3:${2:err}}\\n}\\n\")\n\n\t// test function return multiple errors\n\tvar foo func() (error, error)\n\tfoo().iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if _, err := foo(); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:err}\\n}\\n\")\n\tfoo().variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:err2}, ${2:err} := foo()\\nif ${2:err} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${3:${2:err}}\\n}\\n\")\n\n\t// test function just return error\n\tvar bar func() error\n\tbar().iferr //@snippet(re\"() \\\\/\\\\/\", postfixIfErr, \"if err := bar(); err != nil {\\n\\treturn \\\"\\\", T{}, nil, ${1:err}\\n}\\n\")\n\tbar().variferr //@snippet(re\"() \\\\/\\\\/\", postfixVarIfErr, \"${1:err2} := bar()\\nif ${1:err2} != nil {\\n\\treturn \\\"\\\", T{}, nil, ${2:${1:err2}}\\n}\\n\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/printf.txt",
    "content": "This test checks various ranking of completion results related to printf.\n\n-- flags --\n-ignore_extra_diags\n\n-- printf.go --\npackage printf\n\nimport \"fmt\"\n\nfunc myPrintf(string, ...any) {}\n\nfunc _() {\n\tvar (\n\t\taInt      int          //@item(printfInt, \"aInt\", \"int\", \"var\")\n\t\taFloat    float64      //@item(printfFloat, \"aFloat\", \"float64\", \"var\")\n\t\taString   string       //@item(printfString, \"aString\", \"string\", \"var\")\n\t\taBytes    []byte       //@item(printfBytes, \"aBytes\", \"[]byte\", \"var\")\n\t\taStringer fmt.Stringer //@item(printfStringer, \"aStringer\", \"fmt.Stringer\", \"var\")\n\t\taError    error        //@item(printfError, \"aError\", \"error\", \"var\")\n\t\taBool     bool         //@item(printfBool, \"aBool\", \"bool\", \"var\")\n\t)\n\n\tmyPrintf(\"%d\", a)       //@rank(re\"()\\\\)\", printfInt, printfFloat)\n\tmyPrintf(\"%s\", a)       //@rank(re\"()\\\\)\", printfString, printfInt),rank(re\"()\\\\)\", printfBytes, printfInt),rank(re\"()\\\\)\", printfStringer, printfInt),rank(re\"()\\\\)\", printfError, printfInt)\n\tmyPrintf(\"%w\", a)       //@rank(re\"()\\\\)\", printfError, printfInt)\n\tmyPrintf(\"%x %[1]b\", a) //@rank(re\"()\\\\)\", printfInt, printfString)\n\n\tfmt.Printf(\"%t\", a) //@rank(re\"()\\\\)\", printfBool, printfInt)\n\n\tfmt.Fprintf(nil, \"%f\", a) //@rank(re\"()\\\\)\", printfFloat, printfInt)\n\n\tfmt.Sprintf(\"%[2]q %[1]*.[3]*[4]f\",\n\t\ta, //@rank(re\"(),\", printfInt, printfFloat)\n\t\ta, //@rank(re\"(),\", printfString, printfFloat)\n\t\ta, //@rank(re\"(),\", printfInt, printfFloat)\n\t\ta, //@rank(re\"(),\", printfFloat, printfInt)\n\t)\n\n  // Don't insert as \"&aStringer\"\n\tfmt.Printf(\"%p\", a) //@snippet(re\"()\\\\)\", printfStringer, \"aStringer\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/randv2.txt",
    "content": "Unimported completions has to find math/rand/v2\n-- flags --\n-min_go_command=go1.22\n\n-- settings.json --\n{\n\t\"importsSource\": \"gopls\"\n}\n\n-- go.mod --\nmodule unimported.test\n\ngo 1.22\n\n-- main.go --\npackage main\nvar _ = rand.Int64 //@complete(re\"()Int64\", Int64, Int64N, x64, Uint64, Uint64N), diag(\"rand\", re\"undefined: rand\")\n// ordering of these requires completion order be deterministic\n// for now, we do not know the types. Awaiting CL 665335\n//@item(Int64, \"Int64\", \"func (from \\\"math/rand/v2\\\")\", \"func\")\n//@item(Int64N, \"Int64N\", \"func (from \\\"math/rand/v2\\\")\", \"func\")\n//@item(x64, \"Uint64\", \"func (from \\\"math/rand\\\")\", \"func\")\n//@item(Uint64, \"Uint64\", \"func (from \\\"math/rand/v2\\\")\", \"func\")\n//@item(Uint64N, \"Uint64N\", \"func (from \\\"math/rand/v2\\\")\", \"func\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/range_func.txt",
    "content": "This test shows we prefer rangeable funcs in range statements.\n\n-- flags --\n-ignore_extra_diags\n\n-- range_func.go --\npackage rangefunc\n\nfunc iterNot(func(int)) {}\nfunc iter0(func() bool) {}\nfunc iter1(func(int) bool) {}\nfunc iter2(func(int, int) bool)\n\nfunc _() {\n\tfor range i { //@rank(re\"() {\", \"iter0\", \"iterNot\"),rank(re\"() {\", \"iter1\", \"iterNot\"),rank(re\"() {\", \"iter2\", \"iterNot\")\n\t}\n\n\tfor k := range i { //@rank(re\"() {\", \"iter1\", \"iterNot\"),rank(re\"() {\", \"iter1\", \"iter0\"),rank(re\"() {\", \"iter2\", \"iter0\")\n\t}\n\n\tfor k, v := range i { //@rank(re\"() {\", \"iter2\", \"iterNot\"),rank(re\"() {\", \"iter2\", \"iter0\"),rank(re\"() {\", \"iter2\", \"iter1\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/rank.txt",
    "content": "This test checks various ranking of completion results.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false,\n\t\"deepCompletion\": false\n}\n\n-- go.mod --\nmodule golang.org/lsptests/rank\n\ngo 1.18\n\n-- struct/struct_rank.go --\npackage struct_rank\n\ntype foo struct {\n\tc int //@item(c_rank, \"c\", \"int\", \"field\")\n\tb int //@item(b_rank, \"b\", \"int\", \"field\")\n\ta int //@item(a_rank, \"a\", \"int\", \"field\")\n}\n\nfunc f() {\n\tfoo := foo{} //@rank(re\"()}\", c_rank, b_rank, a_rank)\n}\n\n-- assign_rank.go --\npackage rank\n\n// Literal completion results.\n/* int() */ //@item(int, \"int()\", \"int\", \"var\")\n/* string() */ //@item(string, \"string()\", \"string\", \"var\")\n\nvar (\n\tapple int = 3         //@item(apple, \"apple\", \"int\", \"var\")\n\tpear string = \"hello\" //@item(pear, \"pear\", \"string\", \"var\")\n)\n\nfunc _() {\n\torange := 1      //@item(orange, \"orange\", \"int\", \"var\")\n\tgrape := \"hello\" //@item(grape, \"grape\", \"string\", \"var\")\n\torange, grape = 2, \"hello\"  //@complete(re\"() \\\"\", grape, pear, string, orange, apple)\n}\n\nfunc _() {\n\tvar pineapple int //@item(pineapple, \"pineapple\", \"int\", \"var\")\n\tpineapple = 1    //@complete(re\"() 1\", pineapple, apple, int, pear)\n\n\ty := //@complete(re\"() \\\\/\", pineapple, apple, pear)\n}\n\n-- binexpr_rank.go --\npackage rank\n\nfunc _() {\n  _ = 5 +  ; //@complete(re\"() ;\", apple, pear)\n  y :=  + 5; //@complete(re\"() +\", apple, pear)\n\n  if 6 ==  {} //@complete(re\"() {\", apple, pear)\n}\n\n-- boolexpr_rank.go --\npackage rank\n\nfunc _() {\n\tsomeRandomBoolFunc := func() bool { //@item(boolExprFunc, \"someRandomBoolFunc\", \"func() bool\", \"var\")\n\t\treturn true\n\t}\n\n\tvar foo, bar int     //@item(boolExprBar, \"bar\", \"int\", \"var\")\n\tif foo == 123 && b { //@rank(re\"() {\", boolExprBar, boolExprFunc)\n\t}\n}\n\n-- convert_rank.go --\npackage rank\n\nimport \"time\"\n\n// Copied from the old builtins.go, which has been ported to the new marker tests.\n/* complex(r float64, i float64) */ //@item(complex, \"complex\", \"func(r float64, i float64) complex128\", \"func\")\n\nfunc _() {\n\ttype strList []string\n\twantsStrList := func(strList) {}\n\n\tvar (\n\t\tconvA string   //@item(convertA, \"convA\", \"string\", \"var\")\n\t\tconvB []string //@item(convertB, \"convB\", \"[]string\", \"var\")\n\t)\n\twantsStrList(strList(conv)) //@complete(re\"()\\\\)\\\\)\", convertB, convertA)\n}\n\nfunc _() {\n\ttype myInt int\n\n\tconst (\n\t\tconvC        = \"hi\"    //@item(convertC, \"convC\", \"string\", \"const\")\n\t\tconvD        = 123     //@item(convertD, \"convD\", \"int\", \"const\")\n\t\tconvE int    = 123     //@item(convertE, \"convE\", \"int\", \"const\")\n\t\tconvF string = \"there\" //@item(convertF, \"convF\", \"string\", \"const\")\n\t\tconvG myInt  = 123     //@item(convertG, \"convG\", \"myInt\", \"const\")\n\t)\n\n\tvar foo int\n\tfoo = conv //@rank(re\"() \\\\/\\\\/\", convertE, convertD)\n\n\tvar mi myInt\n\tmi = conv //@rank(re\"() \\\\/\\\\/\", convertG, convertD, convertE)\n\tmi + conv //@rank(re\"() \\\\/\\\\/\", convertG, convertD, convertE)\n\n\t1 + conv //@rank(re\"() \\\\/\\\\/\", convertD, convertC),rank(re\"() \\\\/\\\\/\", convertE, convertC),rank(re\"() \\\\/\\\\/\", convertG, convertC)\n\n\ttype myString string\n\tvar ms myString\n\tms = conv //@rank(re\"() \\\\/\\\\/\", convertC, convertF)\n\n\ttype myUint uint32\n\tvar mu myUint\n\tmu = conv //@rank(re\"() \\\\/\\\\/\", convertD, convertE)\n\n\t// don't downrank constants when assigning to any\n\tvar _ any = c //@rank(re\"() \\\\/\\\\/\", convertD, complex)\n\n\tvar _ time.Duration = conv //@rank(re\"() \\\\/\\\\/\", convertD, convertE),snippet(re\"() \\\\/\\\\/\", convertE, \"time.Duration(convE)\")\n\n\tvar convP myInt   //@item(convertP, \"convP\", \"myInt\", \"var\")\n\tvar _ *int = conv //@snippet(re\"() \\\\/\\\\/\", convertP, \"(*int)(&convP)\")\n\n\tvar ff float64 //@item(convertFloat, \"ff\", \"float64\", \"var\")\n\tf == convD     //@snippet(re\"() =\", convertFloat, \"ff\")\n}\n\n-- switch_rank.go --\npackage rank\n\nimport \"time\"\n\nfunc _() {\n\tswitch pear {\n\tcase _: //@rank(re\"()_\", pear, apple)\n\t}\n\n\ttime.Monday //@item(timeMonday, \"time.Monday\", \"time.Weekday\", \"const\"),item(monday ,\"Monday\", \"time.Weekday\", \"const\")\n\ttime.Friday //@item(timeFriday, \"time.Friday\", \"time.Weekday\", \"const\"),item(friday ,\"Friday\", \"time.Weekday\", \"const\")\n\n\tnow := time.Now()\n\tnow.Weekday //@item(nowWeekday, \"now.Weekday\", \"func() time.Weekday\", \"method\")\n\n\tthen := time.Now()\n\tthen.Weekday //@item(thenWeekday, \"then.Weekday\", \"func() time.Weekday\", \"method\")\n\n\tswitch time.Weekday(0) {\n\tcase time.Monday, time.Tuesday:\n\tcase time.Wednesday, time.Thursday:\n\tcase time.Saturday, time.Sunday:\n\t// TODO: these tests were disabled because they require deep completion\n\t// (which would break other tests)\n\tcase t: // rank(re\"():\", timeFriday, timeMonday)\n\tcase time.: //@rank(re\"():\", friday, monday)\n\n\tcase now.Weekday():\n\tcase week: // rank(re\"():\", thenWeekday, nowWeekday)\n\t}\n}\n\n-- type_assert_rank.go --\npackage rank\n\nfunc _() {\n\ttype flower int //@item(flower, \"flower\", \"int\", \"type\")\n\tvar fig string  //@item(fig, \"fig\", \"string\", \"var\")\n\n\t_ = interface{}(nil).(f) //@complete(re\"()\\\\) \\\\/\\\\/\", flower)\n}\n\n-- type_switch_rank.go --\npackage rank\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n)\n\nfunc _() {\n\ttype basket int   //@item(basket, \"basket\", \"int\", \"type\")\n\tvar banana string //@item(banana, \"banana\", \"string\", \"var\")\n\n\tswitch interface{}(pear).(type) {\n\tcase b: //@complete(re\"():\", basket)\n\t\tb //@complete(re\"() \\\\/\\\\/\", banana, basket)\n\t}\n\n\tIdent  //@item(astIdent, \"Ident\", \"struct{...}\", \"struct\")\n\tIfStmt //@item(astIfStmt, \"IfStmt\", \"struct{...}\", \"struct\")\n\n\tswitch ast.Node(nil).(type) {\n\tcase *ast.Ident:\n\tcase *ast.I: //@rank(re\"():\", astIfStmt, astIdent)\n\t}\n\n\tStringer   //@item(fmtStringer, \"Stringer\", \"interface{...}\", \"interface\")\n\tGoStringer //@item(fmtGoStringer, \"GoStringer\", \"interface{...}\", \"interface\")\n\n\tswitch interface{}(nil).(type) {\n\tcase fmt.Stringer: //@rank(re\"():\", fmtStringer, fmtGoStringer)\n\t}\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/snippet.txt",
    "content": "This test checks basic completion snippet support.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/snippet\n\n-- snippet.go --\npackage snippets\n\n// Pre-set this marker, as we don't have a \"source\" for it in this package.\n// The comment is used to create a synthetic completion item.\n//\n// TODO(rfindley): allow completion markers to refer to ad-hoc items inline,\n// without this trick.\n/* Error() */ //@item(Error, \"Error\", \"func() string\", \"method\")\n\ntype AliasType = int //@item(sigAliasType, \"AliasType\", \"AliasType\", \"type\")\n\nfunc foo(i int, b bool) {} //@item(snipFoo, \"foo\", \"func(i int, b bool)\", \"func\")\nfunc bar(fn func()) func()    {} //@item(snipBar, \"bar\", \"func(fn func())\", \"func\")\nfunc baz(at AliasType, b bool) {} //@item(snipBaz, \"baz\", \"func(at AliasType, b bool)\", \"func\")\n\ntype Foo struct {\n\tBar int //@item(snipFieldBar, \"Bar\", \"int\", \"field\")\n\tFunc func(at AliasType) error //@item(snipFieldFunc, \"Func\", \"func(at AliasType) error\", \"field\")\n}\n\nfunc (Foo) Baz() func() {} //@item(snipMethodBaz, \"Baz\", \"func() func()\", \"method\")\nfunc (Foo) BazBar() func() {} //@item(snipMethodBazBar, \"BazBar\", \"func() func()\", \"method\")\nfunc (Foo) BazBaz(at AliasType) func() {} //@item(snipMethodBazBaz, \"BazBaz\", \"func(at AliasType) func()\", \"method\")\n\nfunc _() {\n\tf //@snippet(re\"() \\\\/\\\\/\", snipFoo, \"foo(${1:})\")\n\n\tbar //@snippet(re\"() \\\\/\\\\/\", snipBar, \"bar(${1:})\")\n\n\tbaz() //@snippet(re\"()\\\\(\", snipBaz, \"baz\")\n\n\tbar(nil) //@snippet(re\"()\\\\(\", snipBar, \"bar\")\n\tbar(ba) //@snippet(re\"()\\\\)\", snipBar, \"bar(${1:})\")\n\tvar f Foo\n\tbar(f.Ba) //@snippet(re\"()\\\\)\", snipMethodBaz, \"Baz()\")\n\t(bar)(nil) //@snippet(re\"()\\\\)\", snipBar, \"bar(${1:})\")\n\t(f.Ba)() //@snippet(re\"()\\\\)\", snipMethodBaz, \"Baz()\")\n\n\tFoo{\n\t\tB //@snippet(re\"() \\\\/\\\\/\", snipFieldBar, \"Bar: ${1:},\")\n\t}\n\n\tFoo{\n\t\tF //@snippet(re\"() \\\\/\\\\/\", snipFieldFunc, \"Func: ${1:},\")\n\t}\n\n\tFoo{B} //@snippet(re\"()}\", snipFieldBar, \"Bar: ${1:}\")\n\tFoo{} //@snippet(re\"()}\", snipFieldBar, \"Bar: ${1:}\")\n\n\tFoo{Foo{}.B} //@snippet(re\"()} \", snipFieldBar, \"Bar\")\n\n\tvar err error\n\terr.Error() //@snippet(re\"()E\", Error, \"Error()\")\n\tf.Baz()     //@snippet(re\"()B\", snipMethodBaz, \"Baz()\")\n\n\tf.Baz()     //@snippet(re\"()\\\\(\", snipMethodBazBar, \"BazBar\")\n\n\tf.Baz()     //@snippet(re\"()B\", snipMethodBazBaz, \"BazBaz(${1:})\")\n}\n\nfunc _() {\n\ttype bar struct {\n\t\ta int\n\t\tb float64 //@item(snipBarB, \"b\", \"float64\")\n\t}\n\tbar{b} //@snippet(re\"()}\", snipBarB, \"b: ${1:}\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/snippet_placeholder.txt",
    "content": "This test checks basic completion snippet support, using placeholders.\n\nUnlike the old marker tests, the new marker tests assume static configuration\n(as defined by settings.json), and therefore there is duplication between this\ntest and snippet.txt. This is a price we pay so that we don't have to mutate\nthe server during testing.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": true\n}\n\n-- go.mod --\nmodule golang.org/lsptests/snippet\n\n-- snippet.go --\npackage snippets\n\n// Pre-set this marker, as we don't have a \"source\" for it in this package.\n/* Error() */ //@item(Error, \"Error\", \"func() string\", \"method\")\n\ntype AliasType = int //@item(sigAliasType, \"AliasType\", \"AliasType\", \"type\")\n\nfunc foo(i int, b bool) {} //@item(snipFoo, \"foo\", \"func(i int, b bool)\", \"func\")\nfunc bar(fn func()) func()    {} //@item(snipBar, \"bar\", \"func(fn func())\", \"func\")\nfunc baz(at AliasType, b bool) {} //@item(snipBaz, \"baz\", \"func(at AliasType, b bool)\", \"func\")\n\ntype Foo struct {\n\tBar int //@item(snipFieldBar, \"Bar\", \"int\", \"field\")\n\tFunc func(at AliasType) error //@item(snipFieldFunc, \"Func\", \"func(at AliasType) error\", \"field\")\n}\n\nfunc (Foo) Baz() func() {} //@item(snipMethodBaz, \"Baz\", \"func() func()\", \"method\")\nfunc (Foo) BazBar() func() {} //@item(snipMethodBazBar, \"BazBar\", \"func() func()\", \"method\")\nfunc (Foo) BazBaz(at AliasType) func() {} //@item(snipMethodBazBaz, \"BazBaz\", \"func(at AliasType) func()\", \"method\")\n\nfunc _() {\n\tf //@snippet(re\"() \\\\/\\\\/\", snipFoo, \"foo(${1:i int}, ${2:b bool})\")\n\n\tbar //@snippet(re\"() \\\\/\\\\/\", snipBar, \"bar(${1:fn func()})\")\n\n\tbaz //@snippet(re\"() \\\\/\\\\/\", snipBaz, \"baz(${1:at AliasType}, ${2:b bool})\")\n\n\tbar(nil) //@snippet(re\"()\\\\(\", snipBar, \"bar\")\n\tbar(ba) //@snippet(re\"()\\\\)\", snipBar, \"bar(${1:fn func()})\")\n\tvar f Foo\n\tbar(f.Ba) //@snippet(re\"()\\\\)\", snipMethodBaz, \"Baz()\")\n\t(bar)(nil) //@snippet(re\"()\\\\)\", snipBar, \"bar(${1:fn func()})\")\n\t(f.Ba)() //@snippet(re\"()\\\\)\", snipMethodBaz, \"Baz()\")\n\n\tFoo{\n\t\tB //@snippet(re\"() \\\\/\\\\/\", snipFieldBar, \"Bar: ${1:int},\")\n\t}\n\n\tFoo{\n\t\tF //@snippet(re\"() \\\\/\\\\/\", snipFieldFunc, \"Func: ${1:func(at AliasType) error},\")\n\t}\n\n\tFoo{B} //@snippet(re\"()}\", snipFieldBar, \"Bar: ${1:int}\")\n\tFoo{} //@snippet(re\"()}\", snipFieldBar, \"Bar: ${1:int}\")\n\n\tFoo{Foo{}.B} //@snippet(re\"()} \", snipFieldBar, \"Bar\")\n\n\tvar err error\n\terr.Error() //@snippet(re\"()E\", Error, \"Error()\")\n\tf.Baz()     //@snippet(re\"()B\", snipMethodBaz, \"Baz()\")\n\n\tf.Baz()     //@snippet(re\"()\\\\(\", snipMethodBazBar, \"BazBar\")\n\n\tf.Baz()     //@snippet(re\"()B\", snipMethodBazBaz, \"BazBaz(${1:at AliasType})\")\n}\n\nfunc _() {\n\ttype bar struct {\n\t\ta int\n\t\tb float64 //@item(snipBarB, \"b\", \"field\")\n\t}\n\tbar{b} //@snippet(re\"()}\", snipBarB, \"b: ${1:float64}\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/statements.txt",
    "content": "This test exercises completion around various statements.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"usePlaceholders\": true\n}\n\n-- go.mod --\nmodule golang.org/lsptests/statements\n\n-- append.go --\npackage statements\n\nfunc _() {\n\ttype mySlice []int\n\n\tvar (\n\t\tabc    []int   //@item(stmtABC, \"abc\", \"[]int\", \"var\")\n\t\tabcdef mySlice //@item(stmtABCDEF, \"abcdef\", \"mySlice\", \"var\")\n\t)\n\n\t/* abcdef = append(abcdef, ) */ //@item(stmtABCDEFAssignAppend, \"abcdef = append(abcdef, )\", \"\", \"func\")\n\n\t// don't offer \"abc = append(abc, )\" because \"abc\" isn't necessarily\n\t// better than \"abcdef\".\n\tabc //@complete(re\"() \\\\/\\\\/\", stmtABC, stmtABCDEF)\n\n\tabcdef //@complete(re\"() \\\\/\\\\/\", stmtABCDEF, stmtABCDEFAssignAppend)\n\n\t/* append(abc, ) */ //@item(stmtABCAppend, \"append(abc, )\", \"\", \"func\")\n\n\tabc = app //@snippet(re\"() \\\\/\\\\/\", stmtABCAppend, \"append(abc, ${1:})\")\n}\n\nfunc _() {\n\tvar s struct{ xyz []int }\n\n\t/* xyz = append(s.xyz, ) */ //@item(stmtXYZAppend, \"xyz = append(s.xyz, )\", \"\", \"func\")\n\n\ts.x //@snippet(re\"() \\\\/\\\\/\", stmtXYZAppend, \"xyz = append(s.xyz, ${1:})\")\n\n\t/* s.xyz = append(s.xyz, ) */ //@item(stmtDeepXYZAppend, \"s.xyz = append(s.xyz, )\", \"\", \"func\")\n\n\tsx //@snippet(re\"() \\\\/\\\\/\", stmtDeepXYZAppend, \"s.xyz = append(s.xyz, ${1:})\")\n}\n\nfunc _() {\n\tvar foo [][]int\n\n\t/* append(foo[0], ) */ //@item(stmtFooAppend, \"append(foo[0], )\", \"\", \"func\")\n\n\tfoo[0] = app //@complete(re\"() \\\\/\\\\/\", stmtFooAppend),snippet(re\"() \\\\/\\\\/\", stmtFooAppend, \"append(foo[0], ${1:})\")\n}\n\n-- if_err_check_return.go --\npackage statements\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"os\"\n)\n\nfunc one() (int, float32, io.Writer, *int, []int, bytes.Buffer, error) {\n\t/* if err != nil { return err } */ //@item(stmtOneIfErrReturn, \"if err != nil { return err }\", \"\", \"\")\n\t/* err != nil { return err } */ //@item(stmtOneErrReturn, \"err != nil { return err }\", \"\", \"\")\n\n\t_, err := os.Open(\"foo\")\n\t//@snippet(\"\", stmtOneIfErrReturn, \"if err != nil {\\n\\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\\\}, ${1:err}\\n\\\\}\")\n\n\t_, err = os.Open(\"foo\")\n\ti //@snippet(re\"() \\\\/\\\\/\", stmtOneIfErrReturn, \"if err != nil {\\n\\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\\\}, ${1:err}\\n\\\\}\")\n\n\t_, err = os.Open(\"foo\")\n\tif er //@snippet(re\"() \\\\/\\\\/\", stmtOneErrReturn, \"err != nil {\\n\\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\\\}, ${1:err}\\n\\\\}\")\n\n\t_, err = os.Open(\"foo\")\n\tif //@snippet(re\"() \\\\/\\\\/\", stmtOneIfErrReturn, \"if err != nil {\\n\\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\\\}, ${1:err}\\n\\\\}\")\n\n\t_, err = os.Open(\"foo\")\n\tif //@snippet(re\"()\\\\/\\\\/\", stmtOneIfErrReturn, \"if err != nil {\\n\\treturn 0, 0, nil, nil, nil, bytes.Buffer{\\\\}, ${1:err}\\n\\\\}\")\n}\n\n-- if_err_check_return2.go --\npackage statements\n\nimport \"os\"\n\nfunc two() error {\n\tvar s struct{ err error }\n\n\t/* if s.err != nil { return s.err } */ //@item(stmtTwoIfErrReturn, \"if s.err != nil { return s.err }\", \"\", \"\")\n\n\t_, s.err = os.Open(\"foo\")\n\t//@snippet(\"\", stmtTwoIfErrReturn, \"if s.err != nil {\\n\\treturn ${1:s.err}\\n\\\\}\")\n}\n\n-- if_err_check_return3.go --\npackage statements\n\nimport \"os\"\n\n// Check that completion logic handles an invalid return type.\nfunc badReturn() (NotAType, error) {\n\t_, err := os.Open(\"foo\")\n\t//@snippet(\"\", stmtOneIfErrReturn, \"if err != nil {\\n\\treturn , ${1:err}\\n\\\\}\")\n\n\t_, err = os.Open(\"foo\")\n\tif er //@snippet(re\"() \\\\/\\\\/\", stmtOneErrReturn, \"err != nil {\\n\\treturn , ${1:err}\\n\\\\}\")\n}\n\n-- if_err_check_test.go --\npackage statements\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestErr(t *testing.T) {\n\t/* if err != nil { t.Fatal(err) } */ //@item(stmtOneIfErrTFatal, \"if err != nil { t.Fatal(err) }\", \"\", \"\")\n\n\t_, err := os.Open(\"foo\")\n\t//@snippet(\"\", stmtOneIfErrTFatal, \"if err != nil {\\n\\tt.Fatal(err)\\n\\\\}\")\n}\n\nfunc BenchmarkErr(b *testing.B) {\n\t/* if err != nil { b.Fatal(err) } */ //@item(stmtOneIfErrBFatal, \"if err != nil { b.Fatal(err) }\", \"\", \"\")\n\n\t_, err := os.Open(\"foo\")\n\t//@snippet(\"\", stmtOneIfErrBFatal, \"if err != nil {\\n\\tb.Fatal(err)\\n\\\\}\")\n}\n\n-- return.go --\npackage statements\n\n//@item(stmtReturnZeroValues, `return 0, \"\", nil`)\n\nfunc foo() (int, string, error) {\n\tret //@snippet(re\"() \", stmtReturnZeroValues, \"return ${1:0}, ${2:\\\"\\\"}, ${3:nil}\")\n}\n\nfunc bar() (int, string, error) {\n\treturn //@snippet(re\"() \", stmtReturnZeroValues, \"return ${1:0}, ${2:\\\"\\\"}, ${3:nil}\")\n}\n\n\n//@item(stmtReturnInvalidValues, `return `)\n\nfunc invalidReturnStatement() NotAType {\n\treturn //@snippet(re\"() \", stmtReturnInvalidValues, \"return ${1:}\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/testy.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule testy.test\n\ngo 1.18\n\n-- types/types.go --\npackage types\n\n\n-- signature/signature.go --\npackage signature\n\ntype Alias = int\n\n-- snippets/snippets.go --\npackage snippets\n\nimport (\n\t\"testy.test/signature\"\n\tt \"testy.test/types\"\n)\n\nfunc X(_ map[signature.Alias]t.CoolAlias) (map[signature.Alias]t.CoolAlias) {\n\treturn nil\n}\n\n-- testy/testy.go --\npackage testy\n\nfunc a() { //@item(funcA, \"a\", \"func()\", \"func\")\n\t//@complete(\"\", funcA)\n}\n\n\n-- testy/testy_test.go --\npackage testy\n\nimport (\n\t\"testing\"\n\n\tsig \"testy.test/signature\"\n\t\"testy.test/snippets\"\n)\n\nfunc TestSomething(t *testing.T) { //@item(TestSomething, \"TestSomething(t *testing.T)\", \"\", \"func\")\n\tvar x int //@loc(testyX, \"x\"), diag(\"x\", re\"declared (and|but) not used\")\n\ta()       //@loc(testyA, \"a\")\n}\n\nfunc _() {\n\t_ = snippets.X(nil) //@signature(\"nil\", \"X(_ map[sig.Alias]types.CoolAlias) map[sig.Alias]types.CoolAlias\", 0)\n\tvar _ sig.Alias\n}\n\nfunc issue63578(err error) {\n\terr.Error() //@signature(re\"()\\\\)\", \"Error() string\", -1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/type_assert.txt",
    "content": "This test checks completion related to type assertions.\n\n-- flags --\n-ignore_extra_diags\n\n-- type_assert.go --\npackage typeassert\n\ntype abc interface { //@item(abcIntf, \"abc\", \"interface{...}\", \"interface\")\n\tabc()\n}\n\ntype abcImpl struct{} //@item(abcImpl, \"abcImpl\", \"struct{...}\", \"struct\")\nfunc (abcImpl) abc()\n\ntype abcPtrImpl struct{} //@item(abcPtrImpl, \"abcPtrImpl\", \"struct{...}\", \"struct\")\nfunc (*abcPtrImpl) abc()\n\ntype abcNotImpl struct{} //@item(abcNotImpl, \"abcNotImpl\", \"struct{...}\", \"struct\")\n\nfunc _() {\n\tvar a abc\n\tswitch a.(type) {\n\tcase ab: //@complete(re\"():\", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)\n\tcase *ab: //@complete(re\"():\", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)\n\t}\n\n\ta.(ab)  //@complete(re\"()\\\\)\", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)\n\ta.(*ab) //@complete(re\"()\\\\)\", abcImpl, abcPtrImpl, abcIntf, abcNotImpl)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/type_mods.txt",
    "content": "This test check completion snippets with type modifiers.\n\n-- flags --\n-ignore_extra_diags\n\n-- typemods.go --\npackage typemods\n\nfunc fooFunc() func() int {\n\treturn func() int {\n\t\treturn 0\n\t}\n}\n\nfunc fooPtr() *int {\n\treturn nil\n}\n\nfunc _() {\n\tvar _ int = foo //@snippet(re\"() \\\\/\\\\/\", \"fooFunc\", \"fooFunc()()\"),snippet(re\"() \\\\/\\\\/\", \"fooPtr\", \"*fooPtr()\")\n}\n\nfunc _() {\n\tvar m map[int][]chan int\n\n\tvar _ int = m //@snippet(re\"() \\\\/\\\\/\", \"m\", \"<-m[${1:}][${2:}]\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/type_params.txt",
    "content": "This test checks various ranking of completion results related to type\nparameters.\n\n-- flags --\n-ignore_extra_diags\n\n-- type_params.go --\npackage typeparams\n\n// Copied from the old builtins.go, which has been ported to the new marker tests.\n/* string */ //@item(string, \"string\", \"\", \"type\")\n/* float32 */ //@item(float32, \"float32\", \"\", \"type\")\n/* float64 */ //@item(float64, \"float64\", \"\", \"type\")\n/* int */ //@item(int, \"int\", \"\", \"type\")\n\nfunc one[a int | string]()            {}\nfunc two[a int | string, b float64 | int]() {}\ntype three[a any] int\n\nfunc _() {\n\tone[]() //@rank(re\"()]\", string, float64)\n\ttwo[]() //@rank(re\"()]\", int, float64)\n\ttwo[int, f]() //@rank(re\"()]\", float64, float32)\n\tint(three[]) //@rank(re\"()]\") // must not crash (golang/go#70889)\n}\n\nfunc slices[a []int | []float64]() {} //@item(tpInts, \"[]int\", \"[]int\", \"type\"),item(tpFloats, \"[]float64\", \"[]float64\", \"type\")\n\nfunc _() {\n\tslices[]() //@rank(re\"()]\", tpInts),rank(re\"()]\", tpFloats)\n}\n\ntype s[a int | string] struct{}\n\nfunc _() {\n\ts[]{} //@rank(re\"()]\", int, float64)\n}\n\nfunc takesGeneric[a int | string](s[a]) {\n\t\"s[a]{}\" //@item(tpInScopeLit, \"s[a]{}\", \"\", \"var\")\n\ttakesGeneric() //@rank(re\"()\\\\)\", tpInScopeLit),snippet(re\"()\\\\)\", tpInScopeLit, \"s[a]{\\\\}\")\n}\n\nfunc _() {\n\ts[int]{} //@item(tpInstLit, \"s[int]{}\", \"\", \"var\")\n\ttakesGeneric[int]() //@rank(re\"()\\\\)\", tpInstLit),snippet(re\"()\\\\)\", tpInstLit, \"s[int]{\\\\}\")\n\n\t\"s[...]{}\" //@item(tpUninstLit, \"s[...]{}\", \"\", \"var\")\n\ttakesGeneric() //@rank(re\"()\\\\)\", tpUninstLit),snippet(re\"()\\\\)\", tpUninstLit, \"s[${1:}]{\\\\}\")\n}\n\nfunc returnTP[A int | float64](a A) A { //@item(returnTP, \"returnTP\", \"something\", \"func\")\n\treturn a\n}\n\nfunc _() {\n\tvar _ int = returnTP //@snippet(re\"() \\\\/\\\\/\", returnTP, \"returnTP(${1:})\")\n\n\tvar aa int //@item(tpInt, \"aa\", \"int\", \"var\")\n\tvar ab float64 //@item(tpFloat, \"ab\", \"float64\", \"var\")\n\treturnTP[int](a) //@rank(re\"()\\\\)\", tpInt, tpFloat)\n}\n\nfunc takesFunc[T any](func(T) T) {\n\tvar _ func(t T) T = f //@snippet(re\"() \\\\/\\\\/\", tpLitFunc, \"func(t T) T {$0\\\\}\")\n}\n\nfunc _() {\n\t_ = \"func(...) {}\" //@item(tpLitFunc, \"func(...) {}\", \"\", \"var\")\n\ttakesFunc() //@snippet(re\"()\\\\)\", tpLitFunc, \"func(${1:}) ${2:} {$0\\\\}\")\n\ttakesFunc[int]() //@snippet(re\"()\\\\)\", tpLitFunc, \"func(i int) int {$0\\\\}\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/type_params_reverse_infer.txt",
    "content": "-- flags --\n-ignore_extra_diags\n\n-- declarations.go --\npackage x\n\nimport (\n\t\"cmp\"\n\t\"io\"\n\t\"os\"\n)\n\nvar File *os.File\n\nfunc A[T cmp.Ordered](T) int { return 0 }\n\nfunc B[T comparable](T) int { return 0 }\n\nfunc C[T int | string](T) int { return 0 }\n\nfunc D[T io.Reader](T) int { return 0 }\n\n-- a.go --\npackage x\n\nfunc _(i int) {\n\ti = A(File.Nam) //@acceptcompletion(re\"Nam()\", \"Name\", A)\n}\n\n-- @A/a.go --\npackage x\n\nfunc _(i int) {\n\ti = A(File.Name()) //@acceptcompletion(re\"Nam()\", \"Name\", A)\n}\n\n-- b.go --\npackage x\n\nfunc _(i int) {\n\ti = B(File.Nam) //@acceptcompletion(re\"Nam()\", \"Name\", B)\n}\n\n-- @B/b.go --\npackage x\n\nfunc _(i int) {\n\ti = B(File.Name()) //@acceptcompletion(re\"Nam()\", \"Name\", B)\n}\n\n-- c.go --\npackage x\n\nfunc _(i int) {\n\ti = C(File.Nam) //@acceptcompletion(re\"Nam()\", \"Name\", C)\n}\n\n-- @C/c.go --\npackage x\n\nfunc _(i int) {\n\ti = C(File.Name()) //@acceptcompletion(re\"Nam()\", \"Name\", C)\n}\n\n-- d.go --\npackage x\n\nfunc _(i int) {\n\ti = D(Fil) //@acceptcompletion(re\"Fil()\", \"File\", D)\n}\n\n-- @D/d.go --\npackage x\n\nfunc _(i int) {\n\ti = D(File) //@acceptcompletion(re\"Fil()\", \"File\", D)\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/unimported-std.txt",
    "content": "Test of unimported completions respecting the effective Go version of the file.\n\n(See unprefixed file for same test of imported completions.)\n\nThese symbols below were introduced to go/types in go1.22:\n\n  Alias\n  Info.FileVersions\n  (Checker).PkgNameOf\n\nThe underlying logic depends on versions.FileVersion, which only\nbehaves correctly in go1.22. (When go1.22 is assured, we can remove\nthe min_go flag but leave the test inputs unchanged.)\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\n// package-level func\nvar _ = types.Sat //@rank(re\"()Sat\", \"Satisfies\")\nvar _ = types.Ali //@rank(re\"()Ali\", \"!Alias\")\n\n// (We don't offer completions of methods\n// of types from unimported packages, so the fact that\n// we don't implement std version filtering isn't evident.)\n\n// field\nvar _ = new(types.Info).Use //@rank(re\"()Use\", \"!Uses\")\nvar _ = new(types.Info).Fil //@rank(re\"()Fil\", \"!FileVersions\")\n\n// method\nvar _ = new(types.Checker).Obje //@rank(re\"()Obje\", \"!ObjectOf\")\nvar _ = new(types.Checker).PkgN //@rank(re\"()PkgN\", \"!PkgNameOf\")\n\n-- b/b.go --\n//go:build go1.22\n\npackage a\n\n// package-level decl\nvar _ = types.Sat //@rank(re\"()Sat\", \"Satisfies\")\nvar _ = types.Ali //@rank(re\"()Ali\", \"Alias\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/unimported.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"importsSource\": \"gopls\"\n}\n\n-- go.mod --\nmodule unimported.test\n\ngo 1.18\n\n-- unimported/export_test.go --\npackage unimported\n\nvar TestExport int //@item(testexport, \"TestExport\", \"var (from \\\"unimported.test/unimported\\\")\", \"var\")\n\n-- signature/signature.go --\npackage signature\n\nfunc Foo() {}\n\n-- foo/foo.go --\npackage foo\n\ntype StructFoo struct{ F int }\n\n-- baz/baz.go --\npackage baz\n\nimport (\n\tf \"unimported.test/foo\"\n)\n\nvar FooStruct f.StructFoo\n\n-- unimported/unimported.go --\npackage unimported\n\nfunc _() {\n\thttp //@complete(re\"()p\", http, httptest, httptrace, httputil)\n\t// container/ring is extremely unlikely to be imported by anything, so shouldn't have type information.\n\tring.Ring     //@complete(re\"R()ing\", ringring)\n\tsignature.Foo //@complete(re\"()Foo\", signaturefoo)\n\n\tcontext.Bac //@complete(re\"() \\\\/\\\\/\", contextBackground)\n}\n\n// Create markers for unimported std lib packages. Only for use by this test.\n/* http */ //@item(http, \"http\", \"\\\"net/http\\\"\", \"package\")\n/* httptest */ //@item(httptest, \"httptest\", \"\\\"net/http/httptest\\\"\", \"package\")\n/* httptrace */ //@item(httptrace, \"httptrace\", \"\\\"net/http/httptrace\\\"\", \"package\")\n/* httputil */ //@item(httputil, \"httputil\", \"\\\"net/http/httputil\\\"\", \"package\")\n\n/* ring.Ring */ //@item(ringring, \"Ring\", \"type (from \\\"container/ring\\\")\", \"var\")\n\n/* signature.Foo */ //@item(signaturefoo, \"Foo\", \"func (from \\\"unimported.test/signature\\\")\", \"func\")\n\n/* context.Background */ //@item(contextBackground, \"Background\", \"func (from \\\"context\\\")\", \"func\")\n\n// Now that we no longer type-check imported completions,\n// we don't expect the context.Background().Err method (see golang/go#58663).\n/* context.Background().Err */ //@item(contextBackgroundErr, \"Background().Err\", \"func (from \\\"context\\\")\", \"method\")\n\n-- unimported/unimported_cand_type.go --\npackage unimported\n\nimport (\n\t_ \"context\"\n\n\t\"unimported.test/baz\"\n)\n\nfunc _() {\n\tfoo.StructFoo{} //@item(litFooStructFoo, \"foo.StructFoo{}\", \"struct{...}\", \"struct\")\n\n\t// We get the literal completion for \"foo.StructFoo{}\" even though we haven't\n\t// imported \"foo\" yet.\n\tbaz.FooStruct = f //@snippet(re\"() \\\\/\\\\/\", litFooStructFoo, \"foo.StructFoo{$0\\\\}\")\n}\n\n-- unimported/x_test.go --\npackage unimported_test\n\nimport (\n\t\"testing\"\n)\n\nfunc TestSomething(t *testing.T) {\n\t_ = unimported.TestExport //@complete(re\"()TestExport\", testexport)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/unresolved.txt",
    "content": "This test verifies gopls does not crash on fake \"resolved\" types.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"completeUnimported\": false\n}\n\n-- unresolved.go --\npackage unresolved\n\nfunc foo(any) {\n\tfoo(func(i, j f //@complete(re\"() \\\\/\\\\/\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/unsafe.txt",
    "content": "This test checks completion of symbols in the 'unsafe' package.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"matcher\": \"caseinsensitive\"\n}\n\n-- unsafe.go --\npackage unsafe\n\nimport (\n\t\"unsafe\"\n)\n\n// Pre-set this marker, as we don't have a \"source\" for it in this package.\n/* unsafe.Sizeof */ //@item(Sizeof, \"Sizeof\", \"invalid type\", \"text\")\n\nfunc _() {\n\tx := struct{}{}\n\t_ = unsafe.Sizeof(x) //@complete(re\"()z\", Sizeof)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/completion/variadic.txt",
    "content": "This test checks completion related to variadic functions.\n\n-- flags --\n-ignore_extra_diags\n\n-- variadic.go --\npackage variadic\n\nfunc foo(i int, strs ...string) {}\n\nfunc bar() []string { //@item(vFunc, \"bar\", \"func() []string\", \"func\")\n\treturn nil\n}\n\nfunc _() {\n\tvar (\n\t\ti  int        //@item(vInt, \"i\", \"int\", \"var\")\n\t\ts  string     //@item(vStr, \"s\", \"string\", \"var\")\n\t\tss []string   //@item(vStrSlice, \"ss\", \"[]string\", \"var\")\n\t\tv any //@item(vIntf, \"v\", \"any\", \"var\")\n\t)\n\n\tfoo()           //@rank(re\"()\\\\)\", vInt, vStr),rank(re\"()\\\\)\", vInt, vStrSlice)\n\tfoo(123, )      //@rank(re\"()\\\\)\", vStr, vInt),rank(re\"()\\\\)\", vStrSlice, vInt)\n\tfoo(123, \"\", )  //@rank(re\"()\\\\)\", vStr, vInt),rank(re\"()\\\\)\", vStr, vStrSlice)\n\tfoo(123, s, \"\") //@rank(re\"(), \\\"\", vStr, vStrSlice)\n\n  // snippet will add the \"...\" for you\n\tfoo(123, ) //@snippet(re\"()\\\\)\", vStrSlice, \"ss...\"),snippet(re\"()\\\\)\", vFunc, \"bar()...\"),snippet(re\"()\\\\)\", vStr, \"s\")\n\n\t// don't add \"...\" for any\n\tfoo(123, ) //@snippet(re\"()\\\\)\", vIntf, \"v\")\n}\n\nfunc qux(...func()) {}\nfunc f()            {} //@item(vVarArg, \"f\", \"func()\", \"func\")\n\nfunc _() {\n\tqux(f) //@snippet(re\"()\\\\)\", vVarArg, \"f\")\n}\n\nfunc _() {\n\tfoo(0, []string{}...) //@complete(re\"()\\\\)\")\n}\n\n-- variadic_intf.go --\npackage variadic\n\ntype baz interface {\n\tbaz()\n}\n\nfunc wantsBaz(...baz) {}\n\ntype bazImpl int\n\nfunc (bazImpl) baz() {}\n\nfunc _() {\n\tvar (\n\t\timpls []bazImpl //@item(vImplSlice, \"impls\", \"[]bazImpl\", \"var\")\n\t\timpl  bazImpl   //@item(vImpl, \"impl\", \"bazImpl\", \"var\")\n\t\tbazes []baz     //@item(vIntfSlice, \"bazes\", \"[]baz\", \"var\")\n\t)\n\n\twantsBaz() //@rank(re\"()\\\\)\", vImpl, vImplSlice),rank(re\"()\\\\)\", vIntfSlice, vImplSlice)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/configuration/static.txt",
    "content": "This test confirms that gopls honors configuration even if the client does not\nsupport dynamic configuration.\n\n-- capabilities.json --\n{\n\t\"configuration\": false\n}\n\n-- settings.json --\n{\n\t\"usePlaceholders\": true,\n\t\"analyses\": {\n\t\t\"composites\": false\n\t}\n}\n\n-- go.mod --\nmodule example.com/config\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"example.com/config/b\"\n\nfunc Identity[P ~int](p P) P { //@item(Identity, \"Identity\", \"\", \"\")\n\treturn p\n}\n\nfunc _() {\n\t_ = b.B{2}\n\t_ = Identi //@snippet(re\"ti()\", Identity, \"Identity(${1:p P})\"), diag(\"Ident\", re\"(undefined|undeclared)\")\n}\n\n-- b/b.go --\npackage b\n\ntype B struct {\n\tF int\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/asm.txt",
    "content": "This test exercises the Definition request in a Go assembly file.\n\nFor now we support only references to package-level symbols defined in\nthe same package or a dependency.\n\nRepeatedly jumping to Definition on ff ping-pongs between the Go and\nassembly declarations.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport _ \"fmt\"\nimport _ \"example.com/b\"\n\nfunc ff() //@ loc(ffgo, \"ff\"), def(\"ff\", ffasm)\n\nvar _ = ff // pacify unusedfunc analyzer\n\n-- a/asm.s --\n// portable assembly\n\nTEXT ·ff(SB), $16                       //@ loc(ffasm, \"ff\"), def(\"ff\", ffgo)\n        CALL    example·com∕b·B         //@ def(\"com\", bB)\n        JMP     ·ff                     //@ def(\"ff\", ffgo)\n\tJMP     label\t\t\t//@ def(\"label\", label)\nlabel:\t\t\t\t\t//@ loc(label,\"label\")\n        RET\n\n-- b/b.go --\npackage b\n\nfunc B() {} //@ loc(bB, \"B\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/branch.txt",
    "content": "This test checks definition operations in branch statements break, goto and continue.\n\nWe suppress staticheck since it also gives a diagnostic\nabout the break being ineffective.\n\n-- settings.json --\n{\n\t\"staticcheck\": false\n}\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"log\"\n\nfunc BreakLoop() {\n\tfor i := 0; i < 10; i++ {\n\t\tif i > 6 {\n\t\t\tbreak //@def(\"break\", rbrace1)\n\t\t}\n\t} //@loc(rbrace1, `}`)\n}\n\nfunc BreakNestedLoop() {\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 5; j++ {\n\t\t\tif j > 1 {\n\t\t\t\tbreak //@def(\"break\", rbrace2)\n\t\t\t}\n\t\t} //@loc(rbrace2, `}`)\n\t}\n}\n\nfunc BreakNestedLoopWithLabel() {\n\tOuter:\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 5; j++ {\n\t\t\tif j > 1 {\n\t\t\t\tbreak Outer//@def(\"break\", outerparen)\n\t\t\t}\n\t\t}\n\t} //@loc(outerparen, `}`)\n}\n\nfunc BreakSwitch(i int) {\n\tswitch i {\n\t\tcase 1:\n\t\t\tbreak //@def(\"break\", rbrace4)\n\t\tcase 2:\n\t\t\tlog.Printf(\"2\")\n\t\tcase 3:\n\t\t\tlog.Printf(\"3\")\n\t} //@loc(rbrace4, `}`)\n}\n\nfunc BreakSwitchLabel(i int) {\nloop:\n\tfor {\n\t\tswitch i {\n\t\tcase 1:\n\t\t\tbreak loop //@def(\"break\", loopparen)\n\t\tcase 2:\n\t\t\tlog.Printf(\"2\")\n\t\tcase 3:\n\t\t\tcontinue loop\n\t\t}\n\t} //@loc(loopparen, `}`)\n}\n\nfunc BreakSelect(c, quit chan int) {\n\tx, y := 0, 1\n\tfor {\n\t\tselect {\n\t\tcase c <- x:\n\t\t\tx, y = y, x+y\n\t\tbreak //@def(\"break\", rbrace5)\n\t\tcase <-quit:\n\t\t\tlog.Println(\"quit\")\n\t\t\treturn\n\t\t} //@loc(rbrace5, `}`)\n\t}\n}\n\nfunc BreakWithContinue() {\n\tfor j := 0; j < 5; j++ {\n\t\tif (j < 4) {\n\t\t\tcontinue\n\t\t}\n\t\tbreak //@def(\"break\", rbrace6)\n\t} //@loc(rbrace6, `}`)\n}\n\nfunc GotoNestedLoop() {\n\tOuter: //@loc(outer, \"Outer\")\n\tfor i := 0; i < 10; i++ {\n\t\tfor j := 0; j < 5; j++ {\n\t\t\tif (j > 1) {\n\t\t\t\tgoto Outer//@def(\"goto\", outer)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc ContinueLoop() {\n\tfor j := 0; j < 5; j++ { //@loc(for3, `for`)\n\t\tif (j < 4) {\n\t\t\tcontinue //@def(\"continue\", for3)\n\t\t}\n\t\tbreak\n\t}\n}\n\nfunc ContinueDoubleLoop() {\n\tfor i := 0; i < 10; i++ { //@loc(for4, `for`)\n\t\tfor j := 0; j < 5; j++ {\n\t\t\tif (j > 1) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif (i > 7) {\n\t\t\tcontinue//@def(\"continue\", for4)\n\t\t}\n\t}\n}\n\nfunc BreakInBlockStmt() {\n\tfor {\n\t\tif 0 < 10 {\n\t\t\t{\n\t\t\t\tbreak //@def(\"break\", rbrace9)\n\t\t\t}\n\t\t}\n\t} //@loc(rbrace9, `}`)\n}\n\nfunc BreakInLabeledStmt() {\n\touter:\n\tfor {\n\t\tgoto inner\n\tinner:\n\t\tbreak outer //@def(\"break\", for5)\n\t} //@loc(for5, `}`)\n}\n\nfunc BreakToLabel(n int) {\n\touter1:\n\t\tswitch n {\n\t\t\tcase 1:\n\t\t\t\tprint(\"1\")\n\t\t\t\tfor i := 0; i < 10; i++ {\n\t\t\t\tif i > 3 {\n\t\t\t\t\tbreak outer1 //@def(\"break\", outer1)\n\t\t\t\t}\n\t\t\t}\n\t\t} //@loc(outer1, \"}\")\n}\n\nfunc ContinueToLabel(n int) {\n\touter1:\n\t\tfor { //@loc(outer2, \"for\")\n\t\t\tswitch n {\n\t\t\tcase 1:\n\t\t\t\tprint(\"1\")\n\t\t\t\tfor i := 0; i < 10; i++ {\n\t\t\t\t\tif i > 3 {\n\t\t\t\t\t\tcontinue outer1 //@def(\"continue\", outer2)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/branch_issue73797.txt",
    "content": "This test checks the case of a definition operation on a \"continue\" with an invalid label.\nIn gotip, the typechecker no longer associates the continue statement with its invalid label,\nso this test case should only be run for go1.24 or earlier.\nSee the related change in go/types: https://go-review.git.corp.google.com/c/go/+/638257\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc InvalidLabel() {\n    label:\n\tfor i := 0; i < 10; i++ {\n\t}\n\tfor i := 0; i < 10; i++ { //@loc(for, \"for\")\n\t\tcontinue label //@def(\"continue\", for)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/branch_issue73797_go124.txt",
    "content": "This test checks the case of a definition operation on a \"continue\" with an invalid label.\nIn gotip, the typechecker no longer associates the continue statement with its invalid label,\nso this test case should only be run for go1.24 or earlier.\nSee the related change in go/types: https://go-review.git.corp.google.com/c/go/+/638257\n\n-- flags --\n-max_go=go1.24\n-ignore_extra_diags\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc InvalidLabel() {\n    label:\n\tfor i := 0; i < 10; i++ {\n\t}\n\tfor i := 0; i < 10; i++ {\n\t\tcontinue label //@def(\"continue\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/cgo.txt",
    "content": "This test is ported from the old marker tests.\nIt tests hover and definition for cgo declarations.\n\n-- flags --\n-cgo\n\n-- go.mod --\nmodule cgo.test\n\ngo 1.18\n\n-- cgo/cgo.go --\npackage cgo\n\n/*\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid myprint(char* s) {\n\tprintf(\"%s\\n\", s);\n}\n*/\nimport \"C\"\n\nimport (\n\t\"fmt\"\n\t\"unsafe\"\n)\n\nfunc Example() { //@loc(cgoexample, \"Example\"), item(cgoexampleItem, \"Example\", \"func()\", \"func\")\n\tfmt.Println()\n\tcs := C.CString(\"Hello from stdio\\n\")\n\tC.myprint(cs)\n\tC.free(unsafe.Pointer(cs))\n}\n\nfunc _() {\n\tExample() //@hover(\"ample\", \"Example\", hoverExample), def(\"ample\", cgoexample), complete(re\"()ample\", cgoexampleItem)\n}\n\n-- @hoverExample --\n```go\nfunc Example()\n```\n\n---\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/cgo.test/cgo#Example)\n-- usecgo/usecgo.go --\npackage cgoimport\n\nimport (\n\t\"cgo.test/cgo\"\n)\n\nfunc _() {\n\tcgo.Example() //@hover(\"ample\", \"Example\", hoverImportedExample), def(\"ample\", cgoexample), complete(re\"()ample\", cgoexampleItem)\n}\n-- @hoverImportedExample --\n```go\nfunc cgo.Example()\n```\n\n---\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/cgo.test/cgo#Example)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/comment.txt",
    "content": "This test executes definition requests over doc links.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n\n-- path/path.go --\npackage path\n\nfunc Join() //@loc(Join, \"Join\")\n\n-- a.go --\npackage p\n\nimport \"strconv\" //@loc(strconv, `\"strconv\"`)\nimport pathpkg \"mod.com/path\"\nimport _ \"unsafe\"\n\nconst NumberBase = 10 //@loc(NumberBase, \"NumberBase\")\n\n// [Conv] converts s to an int. //@def(\"Conv\", Conv)\nfunc Conv(s string) int { //@loc(Conv, \"Conv\")\n\t// [strconv.ParseInt] parses s and returns the integer corresponding to it. //@def(\"strconv\", strconv)\n\t// [NumberBase] is the base to use for number parsing. //@def(\"NumberBase\", NumberBase)\n\ti, _ := strconv.ParseInt(s, NumberBase, 64)\n\treturn int(i)\n}\n\ntype T struct {\n\tField int //@ loc(Field, \"Field\")\n}\n\nfunc (T) Method() {} //@ loc(Method, \"Method\")\n\n// The declared and imported names of the package both work:\n// [path.Join]    //@ def(\"Join\", Join)\n// [pathpkg.Join] //@ def(\"Join\", Join)\n//\n// Also, both [T.Field] and //@ def(\"Field\", Field)\n// [T.Method] are supported. //@ def(\"Method\", Method)\nfunc _() {\n\tpathpkg.Join()\n}\n\n// Built-in and unsafe symbols work too.\n// [unsafe.Pointer] //@def(\"Pointer\", UNSAFE)\n// [unsafe.Slice]   //@def(\"Slice\", UNSAFE)\n// [int]            //@def(\"int\", BUILTIN)\n// [error]          //@def(\"error\", BUILTIN)\n// [error.Error]    //@def(\"Error\", BUILTIN)\nfunc _()\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/embed.txt",
    "content": "This test checks definition and hover operations over embedded fields and methods.\n\nIts size expectations assume a 64-bit machine,\nand correct sizes information requires go1.21.\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A string //@loc(AString, \"A\")\n\nfunc (_ A) Hi() {} //@loc(AHi, \"Hi\")\n\ntype S struct {\n\tField int //@loc(SField, \"Field\")\n\tR         // embed a struct\n\tH         // embed an interface\n}\n\ntype R struct {\n\tField2 int //@loc(RField2, \"Field2\")\n}\n\nfunc (r R) Hey() {} //@loc(RHey, \"Hey\")\n\ntype H interface { //@loc(H, \"H\")\n\tGoodbye() //@loc(HGoodbye, \"Goodbye\")\n}\n\ntype I interface { //@loc(I, \"I\")\n\tB() //@loc(IB, \"B\")\n\tJ\n}\n\ntype J interface { //@loc(J, \"J\")\n\tHello() //@loc(JHello, \"Hello\")\n}\n\n-- b/b.go --\npackage b\n\nimport \"mod.com/a\" //@loc(AImport, re\"\\\"[^\\\"]*\\\"\")\n\ntype embed struct {\n\tF int //@loc(F, \"F\")\n}\n\nfunc (embed) M() //@loc(M, \"M\")\n\ntype Embed struct {\n\tembed\n\t*a.A\n\ta.I\n\ta.S\n}\n\nfunc _() {\n\te := Embed{}\n\te.Hi()      //@def(\"Hi\", AHi),hover(\"Hi\", \"Hi\", AHi)\n\te.B()       //@def(\"B\", IB),hover(\"B\", \"B\", IB)\n\t_ = e.Field     //@def(\"Field\", SField),hover(\"Field\", \"Field\", SField)\n\t_ = e.Field2    //@def(\"Field2\", RField2),hover(\"Field2\", \"Field2\", RField2)\n\te.Hello()   //@def(\"Hello\", JHello),hover(\"Hello\", \"Hello\",JHello)\n\te.Hey()     //@def(\"Hey\", RHey),hover(\"Hey\", \"Hey\", RHey)\n\te.Goodbye() //@def(\"Goodbye\", HGoodbye),hover(\"Goodbye\", \"Goodbye\", HGoodbye)\n\te.M() //@def(\"M\", M),hover(\"M\", \"M\", M)\n\t_ = e.F //@def(\"F\", F),hover(\"F\", \"F\", F)\n}\n\ntype aAlias = a.A //@loc(aAlias, \"aAlias\")\n\ntype S1 struct { //@loc(S1, \"S1\")\n\tF1     int //@loc(S1F1, \"F1\")\n\tS2         //@loc(S1S2, \"S2\"),def(\"S2\", S2),hover(\"S2\", \"S2\", S2)\n\ta.A        //@def(\"A\", AString),hover(\"A\", \"A\", aA)\n\taAlias     //@def(\"a\", aAlias),hover(\"a\", \"aAlias\", aAlias)\n}\n\ntype S2 struct { //@loc(S2, \"S2\")\n\tF1   string //@loc(S2F1, \"F1\")\n\tF2   int    //@loc(S2F2, \"F2\")\n\t*a.A        //@def(\"A\", AString),def(\"a\",AImport)\n}\n\ntype S3 struct {\n\tF1 struct {\n\t\ta.A //@def(\"A\", AString)\n\t}\n}\n\nfunc Bar() {\n\tvar x S1    //@def(\"S1\", S1),hover(\"S1\", \"S1\", S1)\n\t_ = x.S2    //@def(\"S2\", S1S2),hover(\"S2\", \"S2\", S1S2)\n\t_ = x.F1    //@def(\"F1\", S1F1),hover(\"F1\", \"F1\", S1F1)\n\t_ = x.F2    //@def(\"F2\", S2F2),hover(\"F2\", \"F2\", S2F2)\n\t_ = x.S2.F1 //@def(\"F1\", S2F1),hover(\"F1\", \"F1\", S2F1)\n}\n\n-- b/c.go --\npackage b\n\nvar _ = S1{ //@def(\"S1\", S1),hover(\"S1\", \"S1\", S1)\n\tF1: 99, //@def(\"F1\", S1F1),hover(\"F1\", \"F1\", S1F1)\n}\n\n-- @AHi --\n```go\nfunc (a.A) Hi()\n```\n\n---\n\n[`(a.A).Hi` on pkg.go.dev](https://pkg.go.dev/mod.com/a#A.Hi)\n-- @F --\n```go\nfield F int // through embed\n```\n\n---\n\n@loc(F, \"F\")\n\n\n---\n\n[`(b.Embed).F` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.F)\n-- @HGoodbye --\n```go\nfunc (a.H) Goodbye()\n```\n\n---\n\n@loc(HGoodbye, \"Goodbye\")\n\n\n---\n\n[`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/mod.com/a#H.Goodbye)\n-- @IB --\n```go\nfunc (a.I) B()\n```\n\n---\n\n@loc(IB, \"B\")\n\n\n---\n\n[`(a.I).B` on pkg.go.dev](https://pkg.go.dev/mod.com/a#I.B)\n-- @JHello --\n```go\nfunc (a.J) Hello()\n```\n\n---\n\n@loc(JHello, \"Hello\")\n\n\n---\n\n[`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/mod.com/a#J.Hello)\n-- @M --\n```go\nfunc (embed) M()\n```\n\n---\n\n[`(b.Embed).M` on pkg.go.dev](https://pkg.go.dev/mod.com/b#Embed.M)\n-- @RField2 --\n```go\nfield Field2 int // through S, R\n```\n\n---\n\n@loc(RField2, \"Field2\")\n\n\n---\n\n[`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Field2)\n-- @RHey --\n```go\nfunc (r a.R) Hey()\n```\n\n---\n\n[`(a.R).Hey` on pkg.go.dev](https://pkg.go.dev/mod.com/a#R.Hey)\n-- @S1 --\n```go\ntype S1 struct {\n\tF1     int //@loc(S1F1, \"F1\")\n\tS2         //@loc(S1S2, \"S2\"),def(\"S2\", S2),hover(\"S2\", \"S2\", S2)\n\ta.A        //@def(\"A\", AString),hover(\"A\", \"A\", aA)\n\taAlias     //@def(\"a\", aAlias),hover(\"a\", \"aAlias\", aAlias)\n}\n```\n\n---\n\n```go\n// Embedded fields:\nF2 int // through S2 \n```\n\n---\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1)\n-- @S1F1 --\n```go\nfield F1 int\n```\n\n---\n\n@loc(S1F1, \"F1\")\n\n\n---\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.F1)\n-- @S1S2 --\n```go\nfield S2 S2\n```\n\n---\n\n@loc(S1S2, \"S2\"),def(\"S2\", S2),hover(\"S2\", \"S2\", S2)\n\n\n---\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.S2)\n-- @S2 --\n```go\nfield S2 S2 // size=32 (0x20), offset=8\n```\n\n---\n\n@loc(S1S2, \"S2\"),def(\"S2\", S2),hover(\"S2\", \"S2\", S2)\n\n\n---\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S1.S2)\n-- @S2F1 --\n```go\nfield F1 string\n```\n\n---\n\n@loc(S2F1, \"F1\")\n\n\n---\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F1)\n-- @S2F2 --\n```go\nfield F2 int // through S2\n```\n\n---\n\n@loc(S2F2, \"F2\")\n\n\n---\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/mod.com/b#S2.F2)\n-- @SField --\n```go\nfield Field int // through S\n```\n\n---\n\n@loc(SField, \"Field\")\n\n\n---\n\n[`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/mod.com/a#S.Field)\n-- @aA --\n```go\nfield A a.A // size=16 (0x10), offset=40 (0x28)\n```\n-- @aAlias --\n```go\nfield aAlias aAlias // size=16 (0x10), offset=56 (0x38)\n```\n\n---\n\n@def(\"a\", aAlias),hover(\"a\", \"aAlias\", aAlias)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/import.txt",
    "content": "This test checks definition and hover over imports.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- foo/foo.go --\npackage foo\n\ntype Foo struct{}\n\n// DoFoo does foo.\nfunc DoFoo() {} //@loc(DoFoo, \"DoFoo\")\n-- bar/bar.go --\npackage bar\n\nimport (\n\tmyFoo \"mod.com/foo\" //@loc(myFoo, \"myFoo\")\n)\n\nvar _ *myFoo.Foo //@def(\"myFoo\", myFoo),hover(\"myFoo\", \"myFoo\", myFoo)\n-- bar/dotimport.go --\npackage bar\n\nimport . \"mod.com/foo\"\n\nfunc _() {\n\t// variable of type foo.Foo\n\tvar _ Foo //@hover(\"_\", \"_\", FooVar)\n\n\tDoFoo() //@hover(\"DoFoo\", \"DoFoo\", DoFoo)\n}\n-- @DoFoo --\n```go\nfunc DoFoo()\n```\n\n---\n\nDoFoo does foo.\n\n\n---\n\n[`foo.DoFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo#DoFoo)\n-- @FooVar --\n```go\nvar _ Foo\n```\n\n---\n\nvariable of type foo.Foo\n-- @myFoo --\n```go\npackage foo\n```\n\n---\n\n[`myFoo` on pkg.go.dev](https://pkg.go.dev/mod.com/foo)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/misc.txt",
    "content": "This test exercises miscellaneous definition and hover requests.\n\nIts size expectations assume a 64-bit machine.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- go.mod --\nmodule mod.com\n\ngo 1.16\n\n-- flags --\n-skip_goarch=386,arm\n\n-- a.go --\npackage a //@loc(aPackage, re\"package (a)\"),hover(aPackage, aPackage, aPackage)\n\nvar (\n\t// x is a variable.\n\tx string //@loc(x, \"x\"),hover(x, x, hoverx)\n)\n\n// Constant block. When I hover on h, I should see this comment.\nconst (\n\t// When I hover on g, I should see this comment.\n\tg = 1 //@hover(\"g\", \"g\", hoverg)\n\n\th = 2 //@hover(\"h\", \"h\", hoverh)\n)\n\n// z is a variable too.\nvar z string //@loc(z, \"z\"),hover(z, z, hoverz)\n\nfunc AStuff() { //@loc(AStuff, \"AStuff\")\n\tx := 5\n\tRandom2(x) //@def(\"dom2\", Random2)\n\tRandom()   //@def(\"()\", Random)\n}\n\ntype H interface { //@loc(H, \"H\")\n\tGoodbye()\n}\n\ntype I interface { //@loc(I, \"I\")\n\tB()\n\tJ\n}\n\ntype J interface { //@loc(J, \"J\")\n\tHello()\n}\n\nfunc _() {\n\t// 1st type declaration block\n\ttype (\n\t\ta struct { //@hover(\"a\", \"a\", hoverDeclBlocka)\n\t\t\tx string\n\t\t}\n\t)\n\n\t// 2nd type declaration block\n\ttype (\n\t\t// b has a comment\n\t\tb struct{} //@hover(\"b\", \"b\", hoverDeclBlockb)\n\t)\n\n\t// 3rd type declaration block\n\ttype (\n\t\t// c is a struct\n\t\tc struct { //@hover(\"c\", \"c\", hoverDeclBlockc)\n\t\t\tf string\n\t\t}\n\n\t\td string //@hover(\"d\", \"d\", hoverDeclBlockd)\n\t)\n\n\ttype (\n\t\te struct { //@hover(\"e\", \"e\", hoverDeclBlocke)\n\t\t\tf float64\n\t\t} // e has a comment\n\t)\n}\n\nvar (\n\thh H //@hover(\"H\", \"H\", hoverH)\n\tii I //@hover(\"I\", \"I\", hoverI)\n\tjj J //@hover(\"J\", \"J\", hoverJ)\n)\n-- a_test.go --\npackage a\n\nimport (\n\t\"testing\"\n)\n\nfunc TestA(t *testing.T) { //@hover(\"TestA\", \"TestA\", hoverTestA)\n}\n-- random.go --\npackage a\n\nfunc Random() int { //@loc(Random, \"Random\")\n\ty := 6 + 7\n\treturn y\n}\n\nfunc Random2(y int) int { //@loc(Random2, \"Random2\"),loc(RandomParamY, \"y\")\n\treturn y //@def(\"y\", RandomParamY),hover(\"y\", \"y\", hovery)\n}\n\ntype Pos struct {\n\tx, y int //@loc(PosX, \"x\"),loc(PosY, \"y\")\n}\n\n// Typ has a comment. Its fields do not.\ntype Typ struct{ field string } //@loc(TypField, \"field\")\n\nfunc _() {\n\tx := &Typ{}\n\t_ = x.field //@def(\"field\", TypField),hover(\"field\", \"field\", hoverfield)\n}\n\nfunc (p *Pos) Sum() int { //@loc(PosSum, \"Sum\")\n\treturn p.x + p.y //@hover(\"x\", \"x\", hoverpx)\n}\n\nfunc _() {\n\tvar p Pos\n\t_ = p.Sum() //@def(\"()\", PosSum),hover(re\"Sum()\", `Sum`, hoverSum)\n}\n-- @aPackage --\n```go\npackage a\n```\n\n---\n\n - Package path: mod.com\n - Module: mod.com\n - Language version: go1.16\n-- @hoverDeclBlocka --\n```go\ntype a struct { // size=16 (0x10)\n\tx string\n}\n```\n\n---\n\n1st type declaration block\n-- @hoverDeclBlockb --\n```go\ntype b struct{} // size=0\n```\n\n---\n\nb has a comment\n-- @hoverDeclBlockc --\n```go\ntype c struct { // size=16 (0x10)\n\tf string\n}\n```\n\n---\n\nc is a struct\n-- @hoverDeclBlockd --\n```go\ntype d string // size=16 (0x10)\n```\n\n---\n\n3rd type declaration block\n-- @hoverDeclBlocke --\n```go\ntype e struct { // size=8\n\tf float64\n}\n```\n\n---\n\ne has a comment\n-- @hoverH --\n```go\ntype H interface {\n\tGoodbye()\n}\n```\n\n---\n\n[`a.H` on pkg.go.dev](https://pkg.go.dev/mod.com#H)\n-- @hoverI --\n```go\ntype I interface {\n\tB()\n\tJ\n}\n```\n\n---\n\n```go\nfunc (J) Hello()\n```\n\n---\n\n[`a.I` on pkg.go.dev](https://pkg.go.dev/mod.com#I)\n-- @hoverJ --\n```go\ntype J interface {\n\tHello()\n}\n```\n\n---\n\n[`a.J` on pkg.go.dev](https://pkg.go.dev/mod.com#J)\n-- @hoverSum --\n```go\nfunc (p *Pos) Sum() int\n```\n\n---\n\n[`(a.Pos).Sum` on pkg.go.dev](https://pkg.go.dev/mod.com#Pos.Sum)\n-- @hoverTestA --\n```go\nfunc TestA(t *testing.T)\n```\n-- @hoverfield --\n```go\nfield field string\n```\n-- @hoverg --\n```go\nconst g untyped int = 1\n```\n\n---\n\nWhen I hover on g, I should see this comment.\n-- @hoverh --\n```go\nconst h untyped int = 2\n```\n\n---\n\nConstant block. When I hover on h, I should see this comment.\n-- @hoverpx --\n```go\nfield x int\n```\n\n---\n\n@loc(PosX, \"x\"),loc(PosY, \"y\")\n-- @hoverx --\n```go\nvar x string\n```\n\n---\n\nx is a variable.\n-- @hovery --\n```go\nvar y int\n```\n-- @hoverz --\n```go\nvar z string\n```\n\n---\n\nz is a variable too.\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/nearby.txt",
    "content": "This test checks the \"nearby\" logic of golang.objectsAt\nas used by Definition. The query is on the \"*\" of \"*T\"\nyet resolves to T.\n\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype T int\t//@ loc(T, \"T\")\n\nvar _ * T\t//@ def(\"*\", T)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/return.txt",
    "content": "This test checks definition operations in function return statements. \nGo to definition on 'return' should go to the result parameter list.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc Hi() string { //@loc(HiReturn, \"string\")\n    return \"Hello\" //@def(\"return\", HiReturn)\n}\n\nfunc Bye() (int, int, int) { //@loc(ByeReturn, \"(int, int, int)\")\n    return 1, 2, 3 //@def(\"return\", ByeReturn)\n}\n\nfunc TestLit() {\n    f := func(a, b int) bool { return a*b < 100 } //@loc(FuncLitReturn, \"bool\"),def(\"return\", FuncLitReturn)\n    f(1, 2)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/standalone.txt",
    "content": "This test checks the behavior of standalone packages, in particular documenting\nour failure to support test files as standalone packages (golang/go#64233).\n\n-- go.mod --\nmodule golang.org/lsptests/a\n\ngo 1.20\n\n-- a.go --\npackage a\n\nfunc F() {} //@loc(F, \"F\")\n\n-- standalone.go --\n//go:build ignore\npackage main\n\nimport \"golang.org/lsptests/a\"\n\nfunc main() {\n\ta.F() //@def(\"F\", F)\n}\n\n-- standalone_test.go --\n//go:build ignore\npackage main //@diag(\"main\", re\"No packages found\")\n\nimport \"golang.org/lsptests/a\"\n\nfunc main() {\n\ta.F() //@hovererr(\"F\", \"no package\")\n}\n\n-- standalone_x_test.go --\n//go:build ignore\npackage main_test //@diag(\"main\", re\"No packages found\")\n\nimport \"golang.org/lsptests/a\"\n\nfunc main() {\n\ta.F() //@hovererr(\"F\", \"no package\")\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/definition/standalone_issue64557.txt",
    "content": "This test checks that we can load standalone files that use cgo.\n\n-- flags --\n-cgo\n\n-- go.mod --\nmodule example.com\n\n-- main.go --\n//go:build ignore\n\npackage main\n\nimport (\n\t\"C\"\n\n\t\"example.com/a\"\n)\n\nfunc F() {} //@loc(F, \"F\")\n\nfunc main() {\n\tF() //@def(\"F\", F)\n\tprintln(a.A) //@def(\"A\", A)\n}\n\n-- a/a.go --\npackage a\n\nconst A = 0 //@loc(A, \"A\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/addgowork.txt",
    "content": "This test demonstrates diagnostics for adding a go.work file.\n\nQuick-fixes change files on disk, so are tested by integration tests.\n\nTODO(rfindley): improve the \"cannot find package\" import errors.\n\n-- skip --\nThese diagnostics are no longer produced, because in golang/go#57979\n(zero-config gopls) we made gopls function independent of a go.work file.\nPreserving this test as we may want to re-enable the code actions go manage\na go.work file.\n\nNote that in go.dev/issue/60584#issuecomment-1622238115, this test was flaky.\nHowever, critical error logic has since been rewritten.\n\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main //@diag(\"main\", re\"add a go.work file\")\n\nimport \"mod.com/a/lib\" //@diag(\"\\\"mod.com\", re\"cannot find package\")\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- a/lib/lib.go --\npackage lib //@diag(\"lib\", re\"add a go.work file\")\n\nconst C = \"b\"\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main //@diag(\"main\", re\"add a go.work file\")\n\nimport \"mod.com/b/lib\" //@diag(\"\\\"mod.com\", re\"cannot find package\")\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- b/lib/lib.go --\npackage lib //@diag(\"lib\", re\"add a go.work file\")\n\nconst C = \"b\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/analyzers.txt",
    "content": "Test of warning diagnostics from various analyzers:\ncopylocks, printf, slog, tests, timeformat, nilness, and cgocall.\n\n-- settings.json --\n{\n\t\"pullDiagnostics\": true\n}\n\n-- go.mod --\nmodule example.com\ngo 1.23\n\n-- flags --\n-min_go_command=go1.23\n-cgo\n\n-- bad/bad_test.go --\npackage bad\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"log/slog\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n)\n\n// copylocks\nfunc _() {\n\tvar x sync.Mutex\n\t_ = x //@diag(\"x\", re\"assignment copies lock value to _: sync.Mutex\")\n}\n\n// printf\nfunc _() {\n\tprintfWrapper(\"%s\") //@diag(re`%s`, re\"example.com/bad.printfWrapper format %s reads arg #1, but call has 0 args\")\n}\n\nfunc printfWrapper(format string, args ...any) {\n\tfmt.Printf(format, args...)\n}\n\n// tests\nfunc Testbad(t *testing.T) { //@diag(\"Testbad\", re\"Testbad has malformed name: first letter after 'Test' must not be lowercase\")\n}\n\n// timeformat\nfunc _() {\n\tnow := time.Now()\n\tfmt.Println(now.Format(\"2006-02-01\")) //@diag(\"2006-02-01\", re\"2006-02-01 should be 2006-01-02\")\n}\n\n// nilness\nfunc _(ptr *int) {\n\tif ptr == nil {\n\t\t_ = *ptr //@diag(\"*ptr\", re\"nil dereference in load\")\n\t}\n}\n\n// unusedwrite\nfunc _(s struct{x int}) {\n\ts.x = 1  //@diag(\"x\", re\"unused write to field x\")\n}\n\n// slog\nfunc _() {\n\tslog.Info(\"msg\", 1) //@diag(\"1\", re`slog.Info arg \"1\" should be a string or a slog.Attr`)\n}\n\n// waitgroup\nfunc _() {\n\tvar wg sync.WaitGroup\n\tgo func() {\n\t\twg.Add(1) //@diag(\"(\", re\"WaitGroup.Add called from inside new goroutine\")\n\t}()\n}\n\n// inline\nfunc _() {\n\tf()  //@diag(\"f\", re\"Call of bad.f should be inlined\")\n}\n\n//go:fix inline\nfunc f() { fmt.Println(1) }\n\n// recursiveiter\nfunc F() iter.Seq[int] {\n\treturn func(yield func(int) bool) {\n\t\tfor range F() {} //@ diag(\"range\", re\"inefficient recursion in iterator F\")\n\t}\n}\n\n-- cgocall/cgocall.go --\npackage cgocall\n\n// Note: this test must be in a separate package, as the unsafe import\n// silences the unusedwrite analyzer.\nimport \"unsafe\"\n\n// void f(void *ptr) {}\nimport \"C\"\n\n// cgocall\nfunc _(c chan bool) {\n\tC.f(unsafe.Pointer(&c)) //@ diag(\"unsafe\", re\"passing Go type with embedded pointer to C\")\n}\n\n-- maprange/maprange.go --\npackage maprange\n\nimport \"maps\"\n\nfunc _(m map[int]int) {\n\tfor range maps.Keys(m) {} //@ diag(\"maps.Keys\", re\"unnecessary and inefficient call of maps.Keys\")\n}\n\n-- unusedresult/unusedresult.go --\npackage unusedresult\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Appendf(nil, \"%d\", 1) //@ diag(\"fmt.Appendf\", re\"result.*not used\")\n}\n\n-- staticcheck/staticcheck.go --\npackage staticcheck\n\n// staticcheck includes hundreds of other analyzers.\n// Here we test only two: one enabled by default, one disabled.\n\nfunc S1000(ch chan int) {\n\tselect { case <-ch: } //@ diag(\"select\", re\"use .*receive instead of select\")\n}\n\nfunc S1011(x, y []int) {\n\tfor _, e := range y {\n\t\tx = append(x, e) // no \"replace loop with append\" diagnostic\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/excludedfile.txt",
    "content": "This test demonstrates diagnostics for various forms of file exclusion.\n\nNote: this test used to also check the errors when a file was excluded due to\nan inactive module, or mismatching GOOS/GOARCH, comment, but with zero-config\ngopls (golang/go#57979) and improved build tag support (golang/go#29202), we no\nlonger get these errors.\n\n-- go.work --\ngo 1.21\n\nuse (\n\t./a\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\n-- a/a_plan9.go --\npackage a // Not excluded, due to improved build tag support.\n\n-- a/a_ignored.go --\n//go:build skip\npackage a //@diag(re\"package (a)\", re\"excluded due to its build tags\")\n\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/b.go --\npackage b // Not excluded, due to zero-config gopls.\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/generated.txt",
    "content": "Test of \"undeclared\" diagnostic in generated code.\n\n-- settings.json --\n{\n\t\"pullDiagnostics\": true\n}\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- generated.go --\n// Code generated by generator.go. DO NOT EDIT.\n\npackage generated\n\nfunc _() {\n\tvar y int //@diag(\"y\", re\"declared (and|but) not used\")\n}\n\n-- generator.go --\npackage generated\n\nfunc _() {\n\tvar x int //@diag(\"x\", re\"declared (and|but) not used\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/initcycle.txt",
    "content": "This test verifies that gopls spreads initialization cycle errors across\nmultiple declarations.\n\nWe set -ignore_extra_diags due to golang/go#65877: gopls produces redundant\ndiagnostics for initialization cycles.\n\n-- flags --\n-ignore_extra_diags\n\n-- p.go --\npackage p\n\nvar X = Y //@diag(\"X\", re\"initialization cycle\")\n\nvar Y = Z //@diag(\"Y\", re\"initialization cycle\")\n\nvar Z = X //@diag(\"Z\", re\"initialization cycle\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue56943.txt",
    "content": "This test verifies that we produce diagnostics related to mismatching\nunexported interface methods in non-workspace packages.\n\nPreviously, we would fail to produce a diagnostic because we trimmed the AST.\nSee golang/go#56943.\n-- settings.json --\n{\n\t\"pullDiagnostics\": true\n}\n\n-- main.go --\npackage main\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n)\n\nfunc main() {\n\tvar a int               //@diag(re\"(a) int\", re\"declared.*not used\")\n\tvar _ ast.Expr = node{} //@diag(\"node{}\", re\"missing.*exprNode\")\n}\n\ntype node struct{}\n\nfunc (node) Pos() token.Pos { return 0 }\nfunc (node) End() token.Pos { return 0 }\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue59005.txt",
    "content": "This test verifies that we don't drop type checking errors on the floor when we\nfail to compute positions for their related errors.\n\n-- go.mod --\nmodule play.ground\n\n-- p.go --\npackage p\n\nimport (\n\t. \"play.ground/foo\"\n)\n\nconst C = 1 //@diag(\"C\", re\"C already declared through dot-import\")\nvar _ = C\n\n-- foo/foo.go --\npackage foo\n\nconst C = 2\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue60544.txt",
    "content": "This test exercises a crash due to treatment of \"comparable\" in methodset\ncalculation (golang/go#60544).\n\n-- main.go --\npackage main\n\ntype X struct{}\n\nfunc (X) test(x comparable) {} //@diag(\"comparable\", re\"outside a type constraint\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue60605.txt",
    "content": "This test verifies that we can export constants with unknown kind.\nPreviously, the exporter would panic while attempting to convert such constants\nto their target type (float64, in this case).\n\n-- go.mod --\nmodule mod.txt/p\n\ngo 1.20\n-- p.go --\npackage p\n\nconst EPSILON float64 = 1e- //@diag(re\"1e-()\", re\"exponent has no digits\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue64547.txt",
    "content": "This test checks the fix for golang/go#64547: the lostcancel analyzer reports\ndiagnostics that overflow the file.\n\n-- p.go --\npackage p\n\nimport \"context\"\n\nfunc _() {\n\t_, cancel := context.WithCancel(context.Background()) //@diag(\"_, cancel\", re\"not used on all paths\")\n\tif false {\n\t\tcancel()\n\t}\n} //@diag(\"}\", re\"may be reached without using the cancel\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue67360.txt",
    "content": "Regression test for #67360.\n\nThis file causes go list to report a \"use of internal package\ncmd/internal/browser\" error. (It is important that this be a real\ninternal std package.) The line directive caused the position of the\nerror to lack a column. A bug in the error parser filled in 0, not 1,\nfor the missing information, and this is an invalid value in the\n1-based UTF-8 domain, leading to a panic.\n\n-- foo.go --\n//line foo.go:1\npackage main                    //@ diag(re\"package\", re\"internal package.*not allowed\")\nimport _ \"cmd/internal/browser\" //@ diag(re`\"`, re\"could not import\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue69505.txt",
    "content": "This test checks that diagnostics ranges computed with the TypeErrorEndPos\nheuristic span at least a full token.\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- main.go --\npackage main\n\nimport \"example.com/foo-bar\" //@ diag(re`\"[^\"]*\"`, re`not used`, exact=true)\n\nfunc f(int) {}\n\nfunc main() {\n\tvar x int\n\t_ = x + 1.e+0i //@ diag(\"1.e+0i\", re`truncated`, exact=true)\n}\n\n-- foo-bar/baz.go --\npackage foo\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue70791.txt",
    "content": "In addition to the Diagnostic, the SA4023 analyzer reports a\nRelatedInformation at the position of b.B, in an another package.\nSince this is in a dependency package, we cannot resolve to\nprotocol.Location coordinates. This used to trigger an assertion, but\nnow we resolve the location approximately.\n\nThis is a regression test for #70791.\n\n-- settings.json --\n{\"analyses\": {\"SA4023\": true}}\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport \"example.com/b\"\n\nvar _ = b.B() == nil //@ diag(\"b.B\", re\"comparison is never true\")\n\n-- b/b.go --\npackage b\n\nfunc B() any { return (*int)(nil) }\n\n\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/issue71812.txt",
    "content": "This input causes the unreachable analyzer to report a diagnostic\nabout the var decl statement. Since the computed End pos of\nast.StructType is beyond EOF, validation of SuggestedFixes fails.\nThis used to trigger an assertion in gopls' analysis driver.\n\nSee golang/go#71659 (and also #71812).\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\nfunc _() { return; var x struct{\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/osarch_suffix.txt",
    "content": "This test verifies that we add an [os,arch] suffix to each diagnostic\nthat doesn't appear in the default build (=runtime.{GOOS,GOARCH}).\n\nSee golang/go#65496.\n\nThe two p/*.go files below are written to trigger the same diagnostic\n(range, message, source, etc) but varying only by URI.\n\nIn the q test, a single location in the common code q.go has two\ndiagnostics, one of which is tagged.\n\nThis test would fail on openbsd/riscv64 because it will be the same as\nthe default build, so we skip that platform. And it would fail on\n*/riscv64 merely because it produces a diagnostic that doesn't include\nthe riscv64 component (since it's the default). So we disable it for\nthat GOOS or GOARCH. But the purpose of the test is not coverage\nacross all configurations, only to test the mechanism in some configs.\n\n-- flags --\n-skip_goos=openbsd\n-skip_goarch=riscv64\n\n-- go.mod --\nmodule example.com\n\n-- p/p.go --\npackage p\n\nvar _ fmt.Stringer //@diag(\"fmt\", re\"unde.*: fmt$\")\n\n-- p/p_openbsd_riscv64.go --\npackage p\n\nvar _ fmt.Stringer //@diag(\"fmt\", re\"unde.*: fmt \\\\[openbsd,riscv64\\\\]\")\n\n-- q/q_default.go --\n//+build !openbsd && !riscv64\n\npackage q\n\nfunc f(int) int\n\n-- q/q_openbsd_riscv64.go --\npackage q\n\nfunc f(string) int\n\n-- q/q.go --\npackage q\n\nvar _ = f() //@ diag(\")\", re`.*want \\(string\\) \\[openbsd,riscv64\\]`), diag(\")\", re`.*want \\(int\\)$`)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/parseerr.txt",
    "content": "\nThis test exercises diagnostics produced for syntax errors.\n\nBecause parser error recovery can be quite lossy, diagnostics\nfor type errors are suppressed in files with syntax errors;\nsee issue #59888. But diagnostics are reported for type errors\nin well-formed files of the same package.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- bad.go --\npackage p\n\nfunc f() {\n\tappend(\"\") // no diagnostic for type error in file containing syntax error\n}\n\nfunc .() {} //@diag(re\"func ().\", re\"expected 'IDENT', found '.'\")\n\n-- good.go --\npackage p\n\nfunc g() {\n\tappend(\"\") //@diag(re`\"\"`, re\"a slice\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/rundespiteerrors.txt",
    "content": "This test verifies that analyzers without RunDespiteErrors are not\nexecuted on a package containing type errors (see issue #54762).\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a.go --\npackage a\n\nfunc _() {\n\t// A type error.\n\t_ = 1 + \"\" //@diag(`1 + \"\"`, re\"mismatched types|cannot convert\")\n\n\t// A violation of an analyzer for which RunDespiteErrors=false:\n\t// no (simplifyrange, warning) diagnostic is produced; the diag\n\t// comment is merely illustrative.\n\tfor _ = range \"\" { //diag(\"for _\", \"simplify range expression\", )\n\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/stdversion.txt",
    "content": "Test of \"too new\" diagnostics from the stdversion analyzer.\n\nThis test references go1.21 symbols from std, but the analyzer itself\ndepends on the go1.22 behavior of versions.FileVersion.\n\nSee also go/analysis/passes/stdversion/testdata/test.txtar,\nwhich runs the same test in the analysistest framework.\n\n-- flags --\n-min_go_command=go1.22\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\nimport \"go/types\"\n\nfunc _() {\n\t// old package-level type\n\tvar _ types.Info // ok: defined by go1.0\n\n\t// new field of older type\n\t_ = new(types.Info).FileVersions //@diag(\"FileVersions\", re`types.FileVersions requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new method of older type\n\t_ = new(types.Info).PkgNameOf //@diag(\"PkgNameOf\", re`types.PkgNameOf requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new package-level type\n\tvar a types.Alias //@diag(\"Alias\", re`types.Alias requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new method of new type\n\ta.Underlying() // no diagnostic\n}\n\n-- sub/go.mod --\nmodule example.com/sub\n\ngo 1.21\n\n-- sub/sub.go --\npackage sub\n\nimport \"go/types\"\n\nfunc _() {\n\t// old package-level type\n\tvar _ types.Info // ok: defined by go1.0\n\n\t// new field of older type\n\t_ = new(types.Info).FileVersions //@diag(\"FileVersions\", re`types.FileVersions requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new method of older type\n\t_ = new(types.Info).PkgNameOf //@diag(\"PkgNameOf\", re`types.PkgNameOf requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new package-level type\n\tvar a types.Alias //@diag(\"Alias\", re`types.Alias requires go1.22 or later \\(module is go1.21\\)`)\n\n\t// new method of new type\n\ta.Underlying() // no diagnostic\n}\n\n-- sub/tagged.go --\n//go:build go1.22\n\npackage sub\n\nimport \"go/types\"\n\nfunc _() {\n\t// old package-level type\n\tvar _ types.Info\n\n\t// new field of older type\n\t_ = new(types.Info).FileVersions\n\n\t// new method of older type\n\t_ = new(types.Info).PkgNameOf\n\n\t// new package-level type\n\tvar a types.Alias\n\n\t// new method of new type\n\ta.Underlying()\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/stdversion_synctest.txt",
    "content": "This test verifies that \"too new\" diagnostics from the stdversion analyzer\nare suppressed for synctest when the go version is go1.24 or later.\nSee golang/go#75367\n\nSet max to go1.25 since the synctest experiment was removed in go1.26.\n\n-- env --\nGOEXPERIMENT=synctest\n-- flags --\n-min_go_command=go1.24\n-max_go_command=go1.25\n\n-- go.mod --\nmodule example.com\n\ngo 1.24\n\n-- a/a.go --\n//go:build goexperiment.synctest || go1.25\npackage a\n\nimport \"testing/synctest\"\n\nfunc _() {\n\tsynctest.Wait() // no diagnostic, see golang/go#75367\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/strangefiles.txt",
    "content": "This test checks diagnostics on files that are strange for one reason or\nanother.\n\nNote(rfindley): ported from the old marker tests. I'm not sure why these were\nwritten originally.\n\n-ignore_extra_diags is required because the marker framework fails for\nnoparse.go, and we therefore can't match the EOF error.\n\n-- flags --\n-ignore_extra_diags\n-errors_ok\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n-- %percent/perc%ent.go --\npackage percent //@diag(\"percent\", re\"No packages\")\n\n-- noparse/noparse.go --\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/typeerr.txt",
    "content": "\nThis test exercises diagnostics produced for type errors\nin the absence of syntax errors.\n\nThe type error was chosen to exercise the 'nonewvars' type-error analyzer.\n(The 'undeclaredname' analyzer depends on the text of the go/types\n\"undeclared name\" error, which changed in go1.20.)\n\nThe append() type error was also carefully chosen to have text and\nposition that are invariant across all versions of Go run by the builders.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- typeerr.go --\npackage a\n\nfunc f(x int) {\n\tappend(\"\") //@diag(re`\"\"`, re\"a slice\")\n\n\tx := 123 //@diag(re\"x := 123\", re\"no new variables\"), quickfix(re\"():\", re\"no new variables\", fix)\n}\n\n-- @fix/typeerr.go --\n@@ -6 +6 @@\n-\tx := 123 //@diag(re\"x := 123\", re\"no new variables\"), quickfix(re\"():\", re\"no new variables\", fix)\n+\tx = 123 //@diag(re\"x := 123\", re\"no new variables\"), quickfix(re\"():\", re\"no new variables\", fix)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/useinternal.txt",
    "content": "This test checks a diagnostic for invalid use of internal packages.\n\nThis list error changed in Go 1.21.\n\nSee TestValidImportCheck_GoPackagesDriver for a test that no diagnostic\nis produced when using a GOPACKAGESDRIVER (such as for Bazel).\n\n-- go.mod --\nmodule bad.test\n\ngo 1.18\n\n-- assign/internal/secret/secret.go --\npackage secret\n\nfunc Hello() {}\n\n-- bad/bad.go --\npackage bad\n\nimport _ \"bad.test/assign/internal/secret\" //@diag(\"\\\"bad.test/assign/internal/secret\\\"\", re\"could not import bad.test/assign/internal/secret \\\\(invalid use of internal package \\\"bad.test/assign/internal/secret\\\"\\\\)\"),diag(\"_\", re\"use of internal package bad.test/assign/internal/secret not allowed\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/diagnostics/usemodule.txt",
    "content": "This test demonstrates diagnostics for a module that is missing from the\ngo.work file.\n\nQuick-fixes change files on disk, so are tested by integration tests.\n\n-- skip --\nTemporary skip due to golang/go#57979, with zero-config gopls, these modules\nare no longer orphaned.\n\n-- go.work --\ngo 1.21\n\nuse (\n\t./a\n)\n\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.18\n\n-- a/main.go --\npackage main\n\nimport \"mod.com/a/lib\"\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- a/lib/lib.go --\npackage lib\n\nconst C = \"b\"\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.18\n\n-- b/main.go --\npackage main //@diag(\"main\", re\"add this module to your go.work\")\n\nimport \"mod.com/b/lib\" //@diag(\"\\\"mod.com\", re\"not included in a workspace module\")\n\nfunc main() {\n\t_ = lib.C\n}\n\n-- b/lib/lib.go --\npackage lib //@diag(\"lib\", re\"add this module to your go.work\")\n\nconst C = \"b\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue59318.txt",
    "content": "Previously, this test verifies that we can load multiple orphaned files as\ncommand-line-arguments packages. In the distant past, we would load only one\nbecause go/packages returns at most one command-line-arguments package per\nquery.\n\nWith zero-config gopls, these packages are successfully loaded as ad-hoc\npackages.\n\n-- a/main.go --\npackage main\n\nfunc main() {\n\tvar a int //@diag(re\"var (a)\", re\"not used\")\n}\n-- b/main.go --\npackage main\n\nfunc main() {\n\tvar b int //@diag(re\"var (b)\", re\"not used\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue59944.txt",
    "content": "This test verifies that gopls does not panic when encountering the go/types\nbug described in golang/go#59944: the Bindingf function is not included in\nthe methodset of its receiver type.\n\nAdapted from the code in question from the issue.\n\nThe flag -ignore_extra_diags is included, as this bug was fixed in Go 1.24, so\nthat now the code below may produce a diagnostic.\n\n-- flags --\n-cgo\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.12\n\n-- cgo.go --\npackage x\n\nimport \"fmt\"\n\n/*\nstruct layout {\n\tint field;\n};\n*/\nimport \"C\"\n\ntype Layout = C.struct_layout\n\n// Bindingf is a printf wrapper. This was necessary to trigger the panic in\n// objectpath while encoding facts.\nfunc (l *Layout) Bindingf(format string, args ...any) {\n\tfmt.Printf(format, args...)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue61543.txt",
    "content": "This test verifies that we fail loudly if a module name contains\ncommand-line-arguments.\n\n-- flags --\n-errors_ok\n\n-- go.mod --\nmodule command-line-arguments //@diag(\"module\", re`command-line-arguments.*disallowed`)\n\ngo 1.12\n\n-- x/x.go --\npackage x //@diag(\"x\", re`command-line-arguments.*disallowed`)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue66109.txt",
    "content": "This test exercises the crash in golang/go#66109: a dangling reference due to\ntest variants of a command-line-arguments package.\n\nDepends on go1.22+ go list errors.\n\n-- flags --\n-min_go_command=go1.22\n\n-- go.mod --\nmodule example.com/tools\n\ngo 1.22\n\n-- tools_test.go --\n//go:build tools\n\npackage tools //@diag(\"tools\", re\"No packages found\")\n\nimport (\n\t_ \"example.com/tools/tool\"\n)\n\n-- tool/tool.go --\npackage main\n\nfunc main() {\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue66250.txt",
    "content": "This bug checks the fix for golang/go#66250. Package references should not\ncrash when one package file lacks a package name.\n\nTODO(rfindley): the -ignore_extra_diags flag is only necessary because of\nproblems matching diagnostics in the broken file, likely due to poor parser\nrecovery.\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage x //@refs(\"x\", \"x\")\n\n-- b.go --\n\nfunc _() {\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue66876.txt",
    "content": "This test checks that gopls successfully suppresses loopclosure diagnostics\nwhen the go.mod go version is set to a 1.22 toolchain version (1.22.x).\n\nIn golang/go#66876, gopls failed to handle this correctly.\n\n-- flags --\n-min_go_command=go1.22\n\n-- go.mod --\nmodule example.com/loopclosure\n\ngo 1.22.0\n\n-- p.go --\npackage main\n\nvar x int //@loc(x, \"x\")\n\nfunc main() {\n\t// Verify that type checking actually succeeded by jumping to\n\t// an arbitrary definition.\n\t_ = x //@def(\"x\", x)\n\n\tfor i := range 10 {\n\t\tgo func() { println(i) }()\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue71044.txt",
    "content": "This test checks that we don't crash while completing receivers that may happen\nto be builtin types (due to invalid code). This crash was reported by telemetry\nin golang/go#71044.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com/amap\n\ngo 1.18\n\n-- a.go --\npackage amap\n\nimport \"unsafe\"\n\nfunc (unsafe.Pointer) _() {} //@ rank(re\"()unsafe\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/fixedbugs/issue74581.txt",
    "content": "This test checks that gopls does not panic when requesting code actions\nfor an import that fails to resolve a package name (such as renaming \"C\").\n\n-- flags --\n-cgo\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a.go --\npackage p //@ diag(re\"^\", re`cannot rename import \"C\"`), diag(re\"^\", re\"go list failed\")\n\nimport . \"C\" //@ codeaction(\".\", \"refactor.rewrite.eliminateDotImport\", err=\"found 0 CodeActions\"), diag(re`[.]`, re`cannot rename import \"C\"`)\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/foldingrange/a.txt",
    "content": "This test checks basic behavior of textDocument/foldingRange.\n\n-- a.go --\npackage folding //@foldingrange(raw)\n\nimport (\n\t\"fmt\"\n\t_ \"log\"\n\t\"sort\"\n\t\"time\"\n)\n\nimport _ \"os\"\n\n// Bar is a function.\n// With a multiline doc comment.\nfunc Bar() (\n\tstring,\n) {\n\t/* This is a single line comment */\n\tswitch {\n\tcase true:\n\t\tif true {\n\t\t\tfmt.Println(\"true\")\n\t\t} else {\n\t\t\tfmt.Println(\"false\")\n\t\t}\n\tcase false:\n\t\tfmt.Println(\"false\")\n\tdefault:\n\t\tfmt.Println(\"default\")\n\t}\n\t/* This is a multiline\n\tblock\n\tcomment */\n\n\t/* This is a multiline\n\tblock\n\tcomment */\n\t// Followed by another comment.\n\t_ = []int{\n\t\t1,\n\t\t2,\n\t\t3,\n\t}\n\t_ = [2]string{\"d\",\n\t\t\"e\",\n\t}\n\t_ = map[string]int{\n\t\t\"a\": 1,\n\t\t\"b\": 2,\n\t\t\"c\": 3,\n\t}\n\ttype T struct {\n\t\tf string\n\t\tg int\n\t\th string\n\t}\n\t_ = T{\n\t\tf: \"j\",\n\t\tg: 4,\n\t\th: \"i\",\n\t}\n\tx, y := make(chan bool), make(chan bool)\n\tselect {\n\tcase val := <-x:\n\t\tif val {\n\t\t\tfmt.Println(\"true from x\")\n\t\t} else {\n\t\t\tfmt.Println(\"false from x\")\n\t\t}\n\tcase <-y:\n\t\tfmt.Println(\"y\")\n\tdefault:\n\t\tfmt.Println(\"default\")\n\t}\n\t// This is a multiline comment\n\t// that is not a doc comment.\n\treturn `\nthis string\nis not indented`\n}\n\nfunc _() {\n\tslice := []int{1, 2, 3}\n\tsort.Slice(slice, func(i, j int) bool {\n\t\ta, b := slice[i], slice[j]\n\t\treturn a > b\n\t})\n\n\tsort.Slice(slice, func(i, j int) bool { return slice[i] > slice[j] })\n\n\tsort.Slice(\n\t\tslice,\n\t\tfunc(i, j int) bool {\n\t\t\treturn slice[i] > slice[j]\n\t\t},\n\t)\n\n\tfmt.Println(\n\t\t1, 2, 3,\n\t\t4,\n\t)\n\n\tfmt.Println(1, 2, 3,\n\t\t4, 5, 6,\n\t\t7, 8, 9,\n\t\t10)\n\n\t// Call with ellipsis.\n\t_ = fmt.Errorf(\n\t\t\"test %d %d\",\n\t\t[]any{1, 2, 3}...,\n\t)\n\n\t// Check multiline string.\n\tfmt.Println(\n\t\t`multi\n\t\tline\n\t\tstring\n\t\t`,\n\t\t1, 2, 3,\n\t)\n\n\t// Call without arguments.\n\t_ = time.Now()\n}\n\nfunc _(\n\ta int, b int,\n\tc int,\n) {\n}\n\nfunc _() { // comment\n\n}\n\n-- @raw --\npackage folding //@foldingrange(raw)\n\nimport (<0 kind=\"imports\">\n\t\"fmt\"\n\t_ \"log\"\n\t\"sort\"\n\t\"time\"\n</0>)\n\nimport _ \"os\"\n\n// Bar is a function.<1 kind=\"comment\">\n// With a multiline doc comment.</1>\nfunc Bar() (<2 kind=\"\">\n\tstring,\n</2>) {<3 kind=\"\">\n\t/* This is a single line comment */\n\tswitch {<4 kind=\"\">\n\tcase true:<5 kind=\"\">\n\t\tif true {<6 kind=\"\">\n\t\t\tfmt.Println(<7 kind=\"\">\"true\"</7>)\n\t\t</6>} else {<8 kind=\"\">\n\t\t\tfmt.Println(<9 kind=\"\">\"false\"</9>)\n\t\t</8>}</5>\n\tcase false:<10 kind=\"\">\n\t\tfmt.Println(<11 kind=\"\">\"false\"</11>)</10>\n\tdefault:<12 kind=\"\">\n\t\tfmt.Println(<13 kind=\"\">\"default\"</13>)</12>\n\t</4>}\n\t/* This is a multiline<14 kind=\"comment\">\n\tblock\n\tcomment */</14>\n\n\t/* This is a multiline<15 kind=\"comment\">\n\tblock\n\tcomment */\n\t// Followed by another comment.</15>\n\t_ = []int{<16 kind=\"\">\n\t\t1,\n\t\t2,\n\t\t3,\n\t</16>}\n\t_ = [2]string{<17 kind=\"\">\"d\",\n\t\t\"e\",\n\t</17>}\n\t_ = map[string]int{<18 kind=\"\">\n\t\t\"a\": 1,\n\t\t\"b\": 2,\n\t\t\"c\": 3,\n\t</18>}\n\ttype T struct {<19 kind=\"\">\n\t\tf string\n\t\tg int\n\t\th string\n\t</19>}\n\t_ = T{<20 kind=\"\">\n\t\tf: \"j\",\n\t\tg: 4,\n\t\th: \"i\",\n\t</20>}\n\tx, y := make(<21 kind=\"\">chan bool</21>), make(<22 kind=\"\">chan bool</22>)\n\tselect {<23 kind=\"\">\n\tcase val := <-x:<24 kind=\"\">\n\t\tif val {<25 kind=\"\">\n\t\t\tfmt.Println(<26 kind=\"\">\"true from x\"</26>)\n\t\t</25>} else {<27 kind=\"\">\n\t\t\tfmt.Println(<28 kind=\"\">\"false from x\"</28>)\n\t\t</27>}</24>\n\tcase <-y:<29 kind=\"\">\n\t\tfmt.Println(<30 kind=\"\">\"y\"</30>)</29>\n\tdefault:<31 kind=\"\">\n\t\tfmt.Println(<32 kind=\"\">\"default\"</32>)</31>\n\t</23>}\n\t// This is a multiline comment<33 kind=\"comment\">\n\t// that is not a doc comment.</33>\n\treturn <34 kind=\"\">`\nthis string\nis not indented`</34>\n</3>}\n\nfunc _() {<35 kind=\"\">\n\tslice := []int{<36 kind=\"\">1, 2, 3</36>}\n\tsort.Slice(<37 kind=\"\">slice, func(<38 kind=\"\">i, j int</38>) bool {<39 kind=\"\">\n\t\ta, b := slice[i], slice[j]\n\t\treturn a > b\n\t</39>}</37>)\n\n\tsort.Slice(<40 kind=\"\">slice, func(<41 kind=\"\">i, j int</41>) bool {<42 kind=\"\"> return slice[i] > slice[j] </42>}</40>)\n\n\tsort.Slice(<43 kind=\"\">\n\t\tslice,\n\t\tfunc(<44 kind=\"\">i, j int</44>) bool {<45 kind=\"\">\n\t\t\treturn slice[i] > slice[j]\n\t\t</45>},\n\t</43>)\n\n\tfmt.Println(<46 kind=\"\">\n\t\t1, 2, 3,\n\t\t4,\n\t</46>)\n\n\tfmt.Println(<47 kind=\"\">1, 2, 3,\n\t\t4, 5, 6,\n\t\t7, 8, 9,\n\t\t10</47>)\n\n\t// Call with ellipsis.\n\t_ = fmt.Errorf(<48 kind=\"\">\n\t\t\"test %d %d\",\n\t\t[]any{<49 kind=\"\">1, 2, 3</49>}...,\n\t</48>)\n\n\t// Check multiline string.\n\tfmt.Println(<50 kind=\"\">\n\t\t<51 kind=\"\">`multi\n\t\tline\n\t\tstring\n\t\t`</51>,\n\t\t1, 2, 3,\n\t</50>)\n\n\t// Call without arguments.\n\t_ = time.Now()\n</35>}\n\nfunc _(<52 kind=\"\">\n\ta int, b int,\n\tc int,\n</52>) {<53 kind=\"\">\n</53>}\n\nfunc _() {<54 kind=\"\"> // comment\n\n</54>}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/foldingrange/a_lineonly.txt",
    "content": "This test checks basic behavior of the textDocument/foldingRange, when the\neditor only supports line folding.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"foldingRange\": {\n\t\t\t\"lineFoldingOnly\": true\n\t\t}\n\t}\n}\n-- a.go --\npackage folding //@foldingrange(raw)\n\nimport (\n\t\"fmt\"\n\t_ \"log\"\n\t\"sort\"\n\t\"time\"\n)\n\nimport _ \"os\"\n\n// Bar is a function.\n// With a multiline doc comment.\nfunc Bar() string {\n\t/* This is a single line comment */\n\tswitch {\n\tcase true:\n\t\tif true {\n\t\t\tfmt.Println(\"true\")\n\t\t} else {\n\t\t\tfmt.Println(\"false\")\n\t\t}\n\tcase false:\n\t\tfmt.Println(\"false\")\n\tdefault:\n\t\tfmt.Println(\"default\")\n\t}\n\t/* This is a multiline\n\tblock\n\tcomment */\n\n\t/* This is a multiline\n\tblock\n\tcomment */\n\t// Followed by another comment.\n\t_ = []int{\n\t\t1,\n\t\t2,\n\t\t3,\n\t}\n\t_ = [2]string{\"d\",\n\t\t\"e\",\n\t}\n\t_ = map[string]int{\n\t\t\"a\": 1,\n\t\t\"b\": 2,\n\t\t\"c\": 3,\n\t}\n\ttype T struct {\n\t\tf string\n\t\tg int\n\t\th string\n\t}\n\t_ = T{\n\t\tf: \"j\",\n\t\tg: 4,\n\t\th: \"i\",\n\t}\n\tx, y := make(chan bool), make(chan bool)\n\tselect {\n\tcase val := <-x:\n\t\tif val {\n\t\t\tfmt.Println(\"true from x\")\n\t\t} else {\n\t\t\tfmt.Println(\"false from x\")\n\t\t}\n\tcase <-y:\n\t\tfmt.Println(\"y\")\n\tdefault:\n\t\tfmt.Println(\"default\")\n\t}\n\t// This is a multiline comment\n\t// that is not a doc comment.\n\treturn `\nthis string\nis not indented`\n}\n\nfunc _() {\n\tslice := []int{1, 2, 3}\n\tsort.Slice(slice, func(i, j int) bool {\n\t\ta, b := slice[i], slice[j]\n\t\treturn a > b\n\t})\n\n\tsort.Slice(slice, func(i, j int) bool { return slice[i] > slice[j] })\n\n\tsort.Slice(\n\t\tslice,\n\t\tfunc(i, j int) bool {\n\t\t\treturn slice[i] > slice[j]\n\t\t},\n\t)\n\n\tfmt.Println(\n\t\t1, 2, 3,\n\t\t4,\n\t)\n\n\tfmt.Println(1, 2, 3,\n\t\t4, 5, 6,\n\t\t7, 8, 9,\n\t\t10)\n\n\t// Call with ellipsis.\n\t_ = fmt.Errorf(\n\t\t\"test %d %d\",\n\t\t[]any{1, 2, 3}...,\n\t)\n\n\t// Check multiline string.\n\tfmt.Println(\n\t\t`multi\n\t\tline\n\t\tstring\n\t\t`,\n\t\t1, 2, 3,\n\t)\n\n\t// Call without arguments.\n\t_ = time.Now()\n}\n\nfunc _(\n\ta int, b int,\n\tc int,\n) {\n}\n-- @raw --\npackage folding //@foldingrange(raw)\n\nimport (<0 kind=\"imports\">\n\t\"fmt\"\n\t_ \"log\"\n\t\"sort\"\n\t\"time\"</0>\n)\n\nimport _ \"os\"\n\n// Bar is a function.<1 kind=\"comment\">\n// With a multiline doc comment.</1>\nfunc Bar() string {<2 kind=\"\">\n\t/* This is a single line comment */\n\tswitch {<3 kind=\"\">\n\tcase true:<4 kind=\"\">\n\t\tif true {<5 kind=\"\">\n\t\t\tfmt.Println(\"true\")</5>\n\t\t} else {<6 kind=\"\">\n\t\t\tfmt.Println(\"false\")</6>\n\t\t}</4>\n\tcase false:<7 kind=\"\">\n\t\tfmt.Println(\"false\")</7>\n\tdefault:<8 kind=\"\">\n\t\tfmt.Println(\"default\")</3></8>\n\t}\n\t/* This is a multiline<9 kind=\"comment\">\n\tblock\n\tcomment */</9>\n\n\t/* This is a multiline<10 kind=\"comment\">\n\tblock\n\tcomment */\n\t// Followed by another comment.</10>\n\t_ = []int{<11 kind=\"\">\n\t\t1,\n\t\t2,\n\t\t3,</11>\n\t}\n\t_ = [2]string{<12 kind=\"\">\"d\",\n\t\t\"e\",</12>\n\t}\n\t_ = map[string]int{<13 kind=\"\">\n\t\t\"a\": 1,\n\t\t\"b\": 2,\n\t\t\"c\": 3,</13>\n\t}\n\ttype T struct {<14 kind=\"\">\n\t\tf string\n\t\tg int\n\t\th string</14>\n\t}\n\t_ = T{<15 kind=\"\">\n\t\tf: \"j\",\n\t\tg: 4,\n\t\th: \"i\",</15>\n\t}\n\tx, y := make(chan bool), make(chan bool)\n\tselect {<16 kind=\"\">\n\tcase val := <-x:<17 kind=\"\">\n\t\tif val {<18 kind=\"\">\n\t\t\tfmt.Println(\"true from x\")</18>\n\t\t} else {<19 kind=\"\">\n\t\t\tfmt.Println(\"false from x\")</19>\n\t\t}</17>\n\tcase <-y:<20 kind=\"\">\n\t\tfmt.Println(\"y\")</20>\n\tdefault:<21 kind=\"\">\n\t\tfmt.Println(\"default\")</16></21>\n\t}\n\t// This is a multiline comment<22 kind=\"comment\">\n\t// that is not a doc comment.</22>\n\treturn <23 kind=\"\">`\nthis string\nis not indented`</2></23>\n}\n\nfunc _() {<24 kind=\"\">\n\tslice := []int{1, 2, 3}\n\tsort.Slice(<25 kind=\"\">slice, func(i, j int) bool {<26 kind=\"\">\n\t\ta, b := slice[i], slice[j]\n\t\treturn a > b</25></26>\n\t})\n\n\tsort.Slice(slice, func(i, j int) bool { return slice[i] > slice[j] })\n\n\tsort.Slice(<27 kind=\"\">\n\t\tslice,\n\t\tfunc(i, j int) bool {<28 kind=\"\">\n\t\t\treturn slice[i] > slice[j]</28>\n\t\t},</27>\n\t)\n\n\tfmt.Println(<29 kind=\"\">\n\t\t1, 2, 3,\n\t\t4,</29>\n\t)\n\n\tfmt.Println(<30 kind=\"\">1, 2, 3,\n\t\t4, 5, 6,\n\t\t7, 8, 9,</30>\n\t\t10)\n\n\t// Call with ellipsis.\n\t_ = fmt.Errorf(<31 kind=\"\">\n\t\t\"test %d %d\",\n\t\t[]any{1, 2, 3}...,</31>\n\t)\n\n\t// Check multiline string.\n\tfmt.Println(<32 kind=\"\">\n\t\t<33 kind=\"\">`multi\n\t\tline\n\t\tstring\n\t\t`</33>,\n\t\t1, 2, 3,</32>\n\t)\n\n\t// Call without arguments.\n\t_ = time.Now()</24>\n}\n\nfunc _(<34 kind=\"\">\n\ta int, b int,\n\tc int,</34>\n) {\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/foldingrange/bad.txt",
    "content": "This test verifies behavior of textDocument/foldingRange in the presence of\nunformatted syntax.\n\n-- a.go --\npackage folding //@foldingrange(raw)\n\nimport ( \"fmt\"\n\t_ \"log\"\n)\n\nimport ( \n\t_ \"os\" )\n\t\n// BadBar is a function.\nfunc BadBar() string { x := true\n\tif x { \n\t\t// This is the only foldable thing in this file when lineFoldingOnly\n\t\tfmt.Println(\"true\")\n\t} else {\n\t\tfmt.Println(\"false\") }\n\treturn \"\"\n}\n-- @raw --\npackage folding //@foldingrange(raw)\n\nimport (<0 kind=\"imports\"> \"fmt\"\n\t_ \"log\"\n</0>)\n\nimport (<1 kind=\"imports\"> \n\t_ \"os\" </1>)\n\t\n// BadBar is a function.\nfunc BadBar() string {<2 kind=\"\"> x := true\n\tif x {<3 kind=\"\"> \n\t\t// This is the only foldable thing in this file when lineFoldingOnly\n\t\tfmt.Println(<4 kind=\"\">\"true\"</4>)\n\t</3>} else {<5 kind=\"\">\n\t\tfmt.Println(<6 kind=\"\">\"false\"</6>) </5>}\n\treturn \"\"\n</2>}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/foldingrange/parse_errors.txt",
    "content": "This test verifies that textDocument/foldingRange does not panic\nand produces no folding ranges if a file contains errors.\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage folding //@foldingrange(raw)\n\n// No comma.\nfunc _(\n\ta string\n) {}\n\n// Extra brace.\nfunc _() {}}\n-- @raw --\npackage folding //@foldingrange(raw)\n\n// No comma.\nfunc _(\n\ta string\n) {}\n\n// Extra brace.\nfunc _() {}}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/format/format.txt",
    "content": "This test checks basic behavior of textDocument/formatting requests.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- good.go --\npackage format //@format(good)\n\nimport (\n\t\"log\"\n)\n\nfunc goodbye() {\n\tlog.Printf(\"byeeeee\")\n}\n\n-- @good --\npackage format //@format(good)\n\nimport (\n\t\"log\"\n)\n\nfunc goodbye() {\n\tlog.Printf(\"byeeeee\")\n}\n-- bad.go --\npackage format //@format(bad)\n\nimport (\n\t\"runtime\"\n\t\"fmt\"\n\t\"log\"\n)\n\nfunc hello() {\n\n\n\n\n\tvar x int //@diag(\"x\", re\"declared (and|but) not used\")\n}\n\nfunc hi() {\n\truntime.NumCPU()\n\tfmt.Printf(\"\")\n\n\tlog.Printf(\"\")\n}\n-- @bad --\npackage format //@format(bad)\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"runtime\"\n)\n\nfunc hello() {\n\n\tvar x int //@diag(\"x\", re\"declared (and|but) not used\")\n}\n\nfunc hi() {\n\truntime.NumCPU()\n\tfmt.Printf(\"\")\n\n\tlog.Printf(\"\")\n}\n-- newline.go --\npackage format //@format(newline)\nfunc _() {}\n-- @newline --\npackage format //@format(newline)\nfunc _()       {}\n-- oneline.go --\npackage format //@format(oneline)\n-- @oneline --\npackage format //@format(oneline)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/format/generated.txt",
    "content": "This test checks that formatting includes generated files too\n(reversing https://go.dev/cl/365295 to address issue #49555).\n\nSee https://github.com/golang/go/issues/73959.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\ngo 1.21\n\n-- a/a.go --\n// Code generated by me. DO NOT EDIT.\n\npackage a; import \"fmt\"; func main() { fmt.Println(\"hello\") }\n\n//@format(out)\n\n-- @out --\n// Code generated by me. DO NOT EDIT.\n\npackage a\n\nimport \"fmt\"\n\nfunc main() { fmt.Println(\"hello\") }\n\n//@format(out)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/format/issue59554.txt",
    "content": "Test case for golang/go#59554: data corruption on formatting due to line\ndirectives.\n\nNote that gofumpt is needed for this test case, as it reformats var decls into\nshort var decls.\n\n-- settings.json --\n{\n\t\"formatting.gofumpt\": true\n}\n\n-- main.go --\npackage main //@format(main)\n\nfunc Match(data []byte) int {\n//line :1\n\tvar idx = ^uint(0)\n\t_ = idx\n\treturn -1\n}\n-- @main --\npackage main //@format(main)\n\nfunc Match(data []byte) int {\n//line :1\n\tidx := ^uint(0)\n\t_ = idx\n\treturn -1\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/format/noparse.txt",
    "content": "This test checks that formatting does not run on code that has parse errors.\n\n-- parse.go --\npackage noparse_format //@format(parse)\n\nfunc _() {\nf() //@diag(\"f\", re\"(undefined|undeclared name): f\")\n}\n-- @parse --\npackage noparse_format //@format(parse)\n\nfunc _() {\n\tf() //@diag(\"f\", re\"(undefined|undeclared name): f\")\n}\n-- noparse.go --\npackage noparse_format //@format(noparse)\n\n// The nonewvars expectation asserts that the go/analysis framework ran.\n\nfunc what() {\n\tvar hi func()\n\tif {\t\thi() //@diag(re\"(){\", re\".*missing.*\")\n\t}\n\thi := nil\n}\n-- @noparse --\n7:5: missing condition in if statement\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/controlflow.txt",
    "content": "This test verifies document highlighting for control flow.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- p.go --\npackage p\n\n-- issue60589.go --\npackage p\n\n// This test verifies that control flow highlighting correctly\n// accounts for multi-name result parameters.\n// In golang/go#60589, it did not.\n\nfunc _() (foo int, bar, baz string) { //@ hiloc(func, \"func\", text), hiloc(foo, \"foo\", text), hiloc(fooint, \"foo int\", text), hiloc(int, \"int\", text), hiloc(bar, \"bar\", text), hiloc(beforebaz, \" baz\", text), hiloc(baz, \"baz\", text), hiloc(barbazstring, \"bar, baz string\", text), hiloc(beforestring, re`() string`, text), hiloc(string, \"string\", text)\n\treturn 0, \"1\", \"2\" //@ hiloc(return, `return 0, \"1\", \"2\"`, text), hiloc(l0, \"0\", text), hiloc(l1, `\"1\"`, text), hiloc(l2, `\"2\"`, text)\n}\n\n// Assertions, expressed here to avoid clutter above.\n// Note that when the cursor is over the field type, there is some\n// (likely harmless) redundancy.\n\n//@ highlight(func, func, return)\n//@ highlight(foo, foo, l0)\n//@ highlight(int, fooint, int, l0)\n//@ highlight(bar, bar, l1)\n//@ highlight(beforebaz)\n//@ highlight(baz, baz, l2)\n//@ highlight(beforestring, baz, l2)\n//@ highlight(string, barbazstring, string, l1, l2)\n//@ highlight(l0, foo, l0)\n//@ highlight(l1, bar, l1)\n//@ highlight(l2, baz, l2)\n\n// Check that duplicate result names do not cause\n// inaccurate highlighting.\n\nfunc _() (x, x int32) { //@ loc(locx1, re`\\((x)`), loc(locx2, re`(x) int`), hiloc(x1, re`\\((x)`, text), hiloc(x2, re`(x) int`, text), diag(locx1, re\"redeclared\"), diag(locx2, re\"redeclared\")\n\treturn 1, 2 //@ hiloc(one, \"1\", text), hiloc(two, \"2\", text)\n}\n\n//@ highlight(one, one, x1)\n//@ highlight(two, two, x2)\n//@ highlight(x1, x1, one)\n//@ highlight(x2, x2, two)\n\n-- issue65516.go --\npackage p\n\n// This test checks that gopls doesn't crash while highlighting\n// functions with no body (golang/go#65516).\n\nfunc Foo() (int, string) //@hiloc(noBodyInt, \"int\", text), hiloc(noBodyFunc, \"func\", text)\n//@highlight(noBodyInt, noBodyInt), highlight(noBodyFunc, noBodyFunc)\n\n-- issue65952.go --\npackage p\n\n// This test checks  that gopls doesn't crash while highlighting\n// return values in functions with no results.\n\nfunc _() {\n\treturn 0 //@hiloc(ret1, \"0\", text), diag(\"0\", re\"too many return\")\n\t//@highlight(ret1, ret1)\n}\n\nfunc _() () {\n\treturn 0 //@hiloc(ret2, \"0\", text), diag(\"0\", re\"too many return\")\n\t//@highlight(ret2, ret2)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/highlight.txt",
    "content": "This test checks basic functionality of the textDocument/highlight request.\n\n-- highlights.go --\npackage highlights\n\nimport (\n\t\"fmt\"         //@hiloc(fmtImp, \"\\\"fmt\\\"\", text),highlightall(fmtImp, fmt1, fmt2, fmt3, fmt4)\n\th2 \"net/http\" //@hiloc(hImp, \"h2\", text),highlightall(hImp, hUse)\n\t\"sort\"\n)\n\ntype F struct{ bar int } //@hiloc(barDeclaration, \"bar\", text),highlightall(barDeclaration, bar1, bar2, bar3)\n\nfunc _() F {\n\treturn F{\n\t\tbar: 123, //@hiloc(bar1, \"bar\", write)\n\t}\n}\n\nvar foo = F{bar: 52} //@hiloc(fooDeclaration, \"foo\", write),hiloc(bar2, \"bar\", write),highlightall(fooDeclaration, fooUse)\n\nfunc Print() { //@hiloc(printFunc, \"Print\", text),highlightall(printFunc, printTest)\n\t_ = h2.Client{} //@hiloc(hUse, \"h2\", text)\n\n\tfmt.Println(foo) //@hiloc(fooUse, \"foo\", read),hiloc(fmt1, \"fmt\", text)\n\tfmt.Print(\"yo\")  //@hiloc(printSep, \"Print\", text),highlightall(printSep, print1, print2),hiloc(fmt2, \"fmt\", text)\n}\n\nfunc (x *F) Inc() { //@hiloc(xRightDecl, \"x\", text),hiloc(xLeftDecl, \" *\", text),highlightall(xRightDecl, xUse),highlight(xLeftDecl, xRightDecl, xUse)\n\tx.bar++ //@hiloc(xUse, \"x\", read),hiloc(bar3, \"bar\", write)\n}\n\nfunc testFunctions() {\n\tfmt.Print(\"main start\") //@hiloc(print1, \"Print\", text),hiloc(fmt3, \"fmt\", text)\n\tfmt.Print(\"ok\")         //@hiloc(print2, \"Print\", text),hiloc(fmt4, \"fmt\", text)\n\tPrint()                 //@hiloc(printTest, \"Print\", text)\n}\n\n// DocumentHighlight is undefined, so its uses below are type errors.\n// Nevertheless, document highlighting should still work.\n//@diag(locdoc1, re\"undefined|undeclared\"), diag(locdoc2, re\"undefined|undeclared\"), diag(locdoc3, re\"undefined|undeclared\")\n\nfunc toProtocolHighlight(rngs []int) []DocumentHighlight { //@loc(locdoc1, \"DocumentHighlight\"), hiloc(doc1, \"DocumentHighlight\", text),hiloc(docRet1, \"[]DocumentHighlight\", text),highlight(doc1, docRet1, doc1, doc2, doc3, result)\n\tresult := make([]DocumentHighlight, 0, len(rngs)) //@loc(locdoc2, \"DocumentHighlight\"), hiloc(doc2, \"DocumentHighlight\", text),highlight(doc2, doc1, doc2, doc3)\n\tfor _, rng := range rngs {\n\t\tresult = append(result, DocumentHighlight{ //@loc(locdoc3, \"DocumentHighlight\"), hiloc(doc3, \"DocumentHighlight\", text),highlight(doc3, doc1, doc2, doc3)\n\t\t\tRange: rng,\n\t\t})\n\t}\n\treturn result //@hiloc(result, \"result\", text)\n}\n\nfunc testForLoops() {\n\tfor i := 0; i < 10; i++ { //@hiloc(forDecl1, \"for\", text),highlightall(forDecl1, brk1, cont1)\n\t\tif i > 8 {\n\t\t\tbreak //@hiloc(brk1, \"break\", text)\n\t\t}\n\t\tif i < 2 {\n\t\t\tfor j := 1; j < 10; j++ { //@hiloc(forDecl2, \"for\", text),highlightall(forDecl2, cont2)\n\t\t\t\tif j < 3 {\n\t\t\t\t\tfor k := 1; k < 10; k++ { //@hiloc(forDecl3, \"for\", text),highlightall(forDecl3, cont3)\n\t\t\t\t\t\tif k < 3 {\n\t\t\t\t\t\t\tcontinue //@hiloc(cont3, \"continue\", text)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue //@hiloc(cont2, \"continue\", text)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue //@hiloc(cont1, \"continue\", text)\n\t\t}\n\t}\n\n\tarr := []int{}\n\tfor i := range arr { //@hiloc(forDecl4, \"for\", text),highlightall(forDecl4, brk4, cont4)\n\t\tif i > 8 {\n\t\t\tbreak //@hiloc(brk4, \"break\", text)\n\t\t}\n\t\tif i < 4 {\n\t\t\tcontinue //@hiloc(cont4, \"continue\", text)\n\t\t}\n\t}\n\nOuter:\n\tfor i := 0; i < 10; i++ { //@hiloc(forDecl5, \"for\", text),highlightall(forDecl5, brk5, brk6, brk8)\n\t\tbreak //@hiloc(brk5, \"break\", text)\n\t\tfor { //@hiloc(forDecl6, \"for\", text),highlightall(forDecl6, cont5), diag(\"for\", re\"unreachable\")\n\t\t\tif i == 1 {\n\t\t\t\tbreak Outer //@hiloc(brk6, \"break Outer\", text)\n\t\t\t}\n\t\t\tswitch i { //@hiloc(switch1, \"switch\", text),highlightall(switch1, brk7)\n\t\t\tcase 5:\n\t\t\t\tbreak //@hiloc(brk7, \"break\", text)\n\t\t\tcase 6:\n\t\t\t\tcontinue //@hiloc(cont5, \"continue\", text)\n\t\t\tcase 7:\n\t\t\t\tbreak Outer //@hiloc(brk8, \"break Outer\", text)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc testSwitch() {\n\tvar i, j int\n\nL1:\n\tfor { //@hiloc(forDecl7, \"for\", text),highlightall(forDecl7, brk10, cont6)\n\tL2:\n\t\tswitch i { //@hiloc(switch2, \"switch\", text),highlightall(switch2, brk11, brk12, brk13)\n\t\tcase 1:\n\t\t\tswitch j { //@hiloc(switch3, \"switch\", text),highlightall(switch3, brk9)\n\t\t\tcase 1:\n\t\t\t\tbreak //@hiloc(brk9, \"break\", text)\n\t\t\tcase 2:\n\t\t\t\tbreak L1 //@hiloc(brk10, \"break L1\", text)\n\t\t\tcase 3:\n\t\t\t\tbreak L2 //@hiloc(brk11, \"break L2\", text)\n\t\t\tdefault:\n\t\t\t\tcontinue //@hiloc(cont6, \"continue\", text)\n\t\t\t}\n\t\tcase 2:\n\t\t\tbreak //@hiloc(brk12, \"break\", text)\n\t\tdefault:\n\t\t\tbreak L2 //@hiloc(brk13, \"break L2\", text)\n\t\t}\n\t}\n}\n\nfunc testReturn() bool { //@hiloc(func1, \"func\", text),hiloc(bool1, \"bool\", text),highlight(func1, func1, fullRet11, fullRet12),highlight(bool1, bool1, false1, bool2, true1)\n\tif 1 < 2 {\n\t\treturn false //@hiloc(ret11, \"return\", text),hiloc(fullRet11, \"return false\", text),hiloc(false1, \"false\", text),highlight(ret11, func1, fullRet11, fullRet12)\n\t}\n\tcandidates := []int{}\n\tsort.SliceStable(candidates, func(i, j int) bool { //@hiloc(func2, \"func\", text),hiloc(bool2, \"bool\", text),highlight(func2, func2, fullRet2)\n\t\treturn candidates[i] > candidates[j] //@hiloc(ret2, \"return\", text),hiloc(fullRet2, \"return candidates[i] > candidates[j]\", text),highlight(ret2, func2, fullRet2)\n\t})\n\treturn true //@hiloc(ret12, \"return\", text),hiloc(fullRet12, \"return true\", text),hiloc(true1, \"true\", text),highlight(ret12, func1, fullRet11, fullRet12)\n}\n\nfunc testReturnFields() float64 { //@hiloc(retVal1, \"float64\", text),highlight(retVal1, retVal1, retVal11, retVal21)\n\tif 1 < 2 {\n\t\treturn 20.1 //@hiloc(retVal11, \"20.1\", text),highlight(retVal11, retVal1, retVal11, retVal21)\n\t}\n\tz := 4.3 //@hiloc(zDecl, \"z\", write)\n\treturn z //@hiloc(retVal21, \"z\", text),highlight(retVal21, retVal1, retVal11, zDecl, retVal21)\n}\n\nfunc testReturnMultipleFields() (float32, string) { //@hiloc(retVal31, \"float32\", text),hiloc(retVal32, \"string\", text),highlight(retVal31, retVal31, retVal41, retVal51),highlight(retVal32, retVal32, retVal42, retVal52)\n\ty := \"im a var\" //@hiloc(yDecl, \"y\", write),\n\tif 1 < 2 {\n\t\treturn 20.1, y //@hiloc(retVal41, \"20.1\", text),hiloc(retVal42, \"y\", text),highlight(retVal41, retVal31, retVal41, retVal51),highlight(retVal42, retVal32, yDecl, retVal42, retVal52)\n\t}\n\treturn 4.9, \"test\" //@hiloc(retVal51, \"4.9\", text),hiloc(retVal52, \"\\\"test\\\"\", text),highlight(retVal51, retVal31, retVal41, retVal51),highlight(retVal52, retVal32, retVal42, retVal52)\n}\n\nfunc testReturnFunc() int32 { //@hiloc(retCall, \"int32\", text)\n\tmulch := 1          //@hiloc(mulchDec, \"mulch\", write),highlight(mulchDec, mulchDec, mulchRet)\n\treturn int32(mulch) //@hiloc(mulchRet, \"mulch\", read),hiloc(retFunc, \"int32\", text),hiloc(retTotal, \"int32(mulch)\", text),highlight(mulchRet, mulchDec, mulchRet),highlight(retFunc, retCall, retFunc, retTotal)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/highlight_kind.txt",
    "content": "This test checks textDocument/highlight with highlight kinds.\nFor example, a use of a variable is reported as a \"read\",\nand an assignment to a variable is reported as a \"write\".\n(Note that the details don't align exactly with the Go\ntype-checker notions of values versus addressable variables).\n\n\n-- highlight_kind.go --\npackage a\n\ntype Nest struct {\n\tnest *Nest //@hiloc(fNest, \"nest\", text)\n}\ntype MyMap map[string]string\n\ntype NestMap map[Nest]Nest\n\nfunc _() {\n\tconst constIdent = 1 //@hiloc(constIdent, \"constIdent\", write)\n\t//@highlightall(constIdent)\n\tvar varNoInit int    //@hiloc(varNoInit, \"varNoInit\", write)\n\t(varNoInit) = 1      //@hiloc(varNoInitAssign, \"varNoInit\", write)\n\t_ = varNoInit        //@hiloc(varNoInitRead, \"varNoInit\", read)\n\t//@highlightall(varNoInit, varNoInitAssign, varNoInitRead)\n\n\tstr, num := \"hello\", 2 //@hiloc(str, \"str\", write), hiloc(num, \"num\", write)\n\t_, _ = str, num        //@hiloc(strRead, \"str\", read), hiloc(numRead, \"num\", read)\n\t//@highlightall(str, strRead, strMapKey, strMapVal, strMyMapKey, strMyMapVal, strMyMapSliceKey, strMyMapSliceVal, strMyMapPtrSliceKey, strMyMapPtrSliceVal)\n\t//@highlightall(num, numRead, numAddr, numIncr, numMul)\n\tnest := &Nest{nest: nil} //@hiloc(nest, \"nest\", write),hiloc(fNestComp, re`(nest):`, write)\n\tnest.nest = &Nest{}      //@hiloc(nestSelX, \"nest\", read), hiloc(fNestSel, re`(nest) =`, write)\n\t*nest.nest = Nest{}      //@hiloc(nestSelXStar, \"nest\", read), hiloc(fNestSelStar, re`(nest) =`, write)\n\t//@highlightall(nest, nestSelX, nestSelXStar, nestMapVal)\n\t//@highlightall(fNest, fNestComp, fNestSel, fNestSelStar, fNestSliceComp, fNestPtrSliceComp, fNestMapKey)\n\n\tpInt := &num //@hiloc(pInt, \"pInt\", write),hiloc(numAddr, \"num\", read)\n\t// StarExpr is reported as \"write\" in GoLand and Rust Analyzer\n\t*pInt = 3               //@hiloc(pIntStar, \"pInt\", write)\n\tvar ppInt **int = &pInt //@hiloc(ppInt, \"ppInt\", write),hiloc(pIntAddr, re`&(pInt)`, read)\n\t**ppInt = 4             //@hiloc(ppIntStar, \"ppInt\", write)\n\t*(*ppInt) = 4           //@hiloc(ppIntParen, \"ppInt\", write)\n\t//@highlightall(pInt, pIntStar, pIntAddr)\n\t//@highlightall(ppInt, ppIntStar, ppIntParen)\n\n\tnum++    //@hiloc(numIncr, \"num\", write)\n\tnum *= 1 //@hiloc(numMul, \"num\", write)\n\n\tvar ch chan int = make(chan int, 10) //@hiloc(ch, \"ch\", write)\n\tch <- 3                              //@hiloc(chSend, \"ch\", write)\n\t<-ch                                 //@hiloc(chRecv, \"ch\", read)\n\t//@highlightall(ch, chSend, chRecv)\n\n\tvar nums []int = []int{1, 2} //@hiloc(nums, \"nums\", write)\n\t// IndexExpr is reported as \"read\" in GoLand, Rust Analyzer and Java JDT\n\tnums[0] = 1 //@hiloc(numsIndex, \"nums\", read)\n\t//@highlightall(nums, numsIndex)\n\n\tmapLiteral := map[string]string{ //@hiloc(mapLiteral, \"mapLiteral\", write)\n\t\tstr: str, //@hiloc(strMapKey, \"str\", read),hiloc(strMapVal, re`(str),`, read)\n\t}\n\tfor key, value := range mapLiteral { //@hiloc(mapKey, \"key\", write), hiloc(mapVal, \"value\", write), hiloc(mapLiteralRange, \"mapLiteral\", read)\n\t\t_, _ = key, value //@hiloc(mapKeyRead, \"key\", read), hiloc(mapValRead, \"value\", read)\n\t}\n\t//@highlightall(mapLiteral, mapLiteralRange)\n\t//@highlightall(mapKey, mapKeyRead)\n\t//@highlightall(mapVal, mapValRead)\n\n\tnestSlice := []Nest{\n\t\t{nest: nil}, //@hiloc(fNestSliceComp, \"nest\", write)\n\t}\n\tnestPtrSlice := []*Nest{\n\t\t{nest: nil}, //@hiloc(fNestPtrSliceComp, \"nest\", write)\n\t}\n\tmyMap := MyMap{\n\t\tstr: str, //@hiloc(strMyMapKey, \"str\", read),hiloc(strMyMapVal, re`(str),`, read)\n\t}\n\tmyMapSlice := []MyMap{\n\t\t{str: str}, //@hiloc(strMyMapSliceKey, \"str\", read),hiloc(strMyMapSliceVal, re`: (str)`, read)\n\t}\n\tmyMapPtrSlice := []*MyMap{\n\t\t{str: str}, //@hiloc(strMyMapPtrSliceKey, \"str\", read),hiloc(strMyMapPtrSliceVal, re`: (str)`, read)\n\t}\n\tnestMap := NestMap{\n\t\tNest{nest: nil}: *nest, //@hiloc(fNestMapKey, \"nest\", write), hiloc(nestMapVal, re`(nest),`, read)\n\t}\n\n\t_, _, _, _, _, _ = myMap, nestSlice, nestPtrSlice, myMapSlice, myMapPtrSlice, nestMap\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/highlight_printf.txt",
    "content": "\nThis test checks functionality of the printf-like directives and operands highlight.\n-- flags --\n-ignore_extra_diags\n-- highlights.go --\npackage highlightprintf\nimport (\n\t\"fmt\"\n)\n\nfunc BasicPrintfHighlights() {\n\tfmt.Printf(\"Hello %s, you have %d new messages!\", \"Alice\", 5) //@hiloc(normals, \"%s\", write),hiloc(normalarg0, \"\\\"Alice\\\"\", read),highlightall(normals, normalarg0)\n\tfmt.Printf(\"Hello %s, you have %d new messages!\", \"Alice\", 5) //@hiloc(normald, \"%d\", write),hiloc(normalargs1, \"5\", read),highlightall(normald, normalargs1)\n}\n\nfunc ComplexPrintfHighlights() {\n\tfmt.Printf(\"Hello %#3.4s, you have %-2.3d new messages!\", \"Alice\", 5) //@hiloc(complexs, \"%#3.4s\", write),hiloc(complexarg0, \"\\\"Alice\\\"\", read),highlightall(complexs, complexarg0)\n\tfmt.Printf(\"Hello %#3.4s, you have %-2.3d new messages!\", \"Alice\", 5) //@hiloc(complexd, \"%-2.3d\", write),hiloc(complexarg1, \"5\", read),highlightall(complexd, complexarg1)\n}\n\nfunc MissingDirectives() {\n\tfmt.Printf(\"Hello %s, you have 5 new messages!\", \"Alice\", 5) //@hiloc(missings, \"%s\", write),hiloc(missingargs0, \"\\\"Alice\\\"\", read),highlightall(missings, missingargs0)\n}\n\nfunc TooManyDirectives() {\n\tfmt.Printf(\"Hello %s, you have %d new %s %q messages!\", \"Alice\", 5) //@hiloc(toomanys, \"%s\", write),hiloc(toomanyargs0, \"\\\"Alice\\\"\", read),highlightall(toomanys, toomanyargs0)\n\tfmt.Printf(\"Hello %s, you have %d new %s %q messages!\", \"Alice\", 5) //@hiloc(toomanyd, \"%d\", write),hiloc(toomanyargs1, \"5\", read),highlightall(toomanyd, toomanyargs1)\n}\n\nfunc VerbIsPercentage() {\n\tfmt.Printf(\"%4.2% %d\", 6) //@hiloc(z1, \"%d\", write),hiloc(z2, \"6\", read),highlightall(z1, z2)\n}\n\nfunc SpecialChars() {\n\tfmt.Printf(\"Hello \\n %s, you \\t \\n have %d new messages!\", \"Alice\", 5) //@hiloc(specials, \"%s\", write),hiloc(specialargs0, \"\\\"Alice\\\"\", read),highlightall(specials, specialargs0)\n\tfmt.Printf(\"Hello \\n %s, you \\t \\n have %d new messages!\", \"Alice\", 5) //@hiloc(speciald, \"%d\", write),hiloc(specialargs1, \"5\", read),highlightall(speciald, specialargs1)\n}\n\nfunc Escaped() {\n\tfmt.Printf(\"Hello %% \\n %s, you \\t%% \\n have %d new m%%essages!\", \"Alice\", 5) //@hiloc(escapeds, \"%s\", write),hiloc(escapedargs0, \"\\\"Alice\\\"\", read),highlightall(escapeds, escapedargs0)\n\tfmt.Printf(\"Hello %% \\n %s, you \\t%% \\n have %d new m%%essages!\", \"Alice\", 5) //@hiloc(escapedd, \"%s\", write),hiloc(escapedargs1, \"\\\"Alice\\\"\", read),highlightall(escapedd, escapedargs1)\n\tfmt.Printf(\"%d \\nss \\x25[2]d\", 234, 123) //@hiloc(zz1, \"%d\", write),hiloc(zz2, \"234\", read),highlightall(zz1,zz2)\n\tfmt.Printf(\"%d \\nss \\x25[2]d\", 234, 123) //@hiloc(zz3, \"\\\\x25[2]d\", write),hiloc(zz4, \"123\", read),highlightall(zz3,zz4)\n}\n\nfunc Indexed() {\n\tfmt.Printf(\"%[1]d\", 3) //@hiloc(i1, \"%[1]d\", write),hiloc(i2, \"3\", read),highlightall(i1, i2)\n\tfmt.Printf(\"%[1]*d\", 3, 6) //@hiloc(i3, \"[1]*\", write),hiloc(i4, \"3\", read),hiloc(i5, \"d\", write),hiloc(i6, \"6\", read),highlightall(i3, i4),highlightall(i5, i6)\n\tfmt.Printf(\"%[2]*[1]d\", 3, 4) //@hiloc(i7, \"[2]*\", write),hiloc(i8, \"4\", read),hiloc(i9, \"[1]d\", write),hiloc(i10, \"3\", read),highlightall(i7, i8),highlightall(i9, i10)\n\tfmt.Printf(\"%[2]*.[1]*[3]d\", 4, 5, 6) //@hiloc(i11, \"[2]*\", write),hiloc(i12, \"5\", read),hiloc(i13, \".[1]*\", write),hiloc(i14, \"4\", read),hiloc(i15, \"[3]d\", write),hiloc(i16, \"6\", read),highlightall(i11, i12),highlightall(i13, i14),highlightall(i15, i16)\n}\n\nfunc MultipleIndexed() {\n\tfmt.Printf(\"%[1]d %[1].2d\", 3) //@hiloc(m1, \"%[1]d\", write),hiloc(m2, \"3\", read),hiloc(m3, \"%[1].2d\", write),highlightall(m1, m2, m3)\n}\n\n// This test checks that gopls doesn't crash (index out of bounds)\n// while haven't fill the last non-variadic argument.\nfunc NoEffectOnUnfinishedArg() {\n\tvar s string //@hiloc(var, \"s\", write)\n\tfmt.Fprintf(s) //@hiloc(firstArg, \"s\", read),highlightall(var, firstArg)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/issue60435.txt",
    "content": "This is a regression test for issue 60435:\nHighlighting \"net/http\" shouldn't have any effect\non an import path that contains it as a substring,\nsuch as httptest.\n\n-- highlights.go --\npackage highlights\n\nimport (\n\t\"net/http\"          //@hiloc(httpImp, `\"net/http\"`, text)\n\t\"net/http/httptest\" //@hiloc(httptestImp, `\"net/http/httptest\"`, text)\n)\n\nvar _ = httptest.NewRequest\nvar _ = http.NewRequest //@hiloc(here, \"http\", text), highlight(here, here, httpImp)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/issue68918.txt",
    "content": "Regression test for https://github.com/golang/go/issues/68918:\ncrash due to missing type information in CompositeLit.\n\nThe corresponding go/types fix in Go 1.24 introduces a\nnew error message, hence the -ignore_extra_diags flag.\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage a\n\nvar _ = T{{ x }} //@hiloc(x, \"x\", text), diag(\"T\", re\"undefined\"), diag(\"{ \", re\"missing type\")\n\n//@highlight(x, x)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/highlight/switchbreak.txt",
    "content": "This is a regression test for issue 65752: a break in a switch should\nhighlight the switch, not the enclosing loop.\n\nWe suppress staticheck since it also gives a diagnostic\nabout the break being ineffective.\n\n-- settings.json --\n{\n\t\"staticcheck\": false\n}\n\n-- a.go --\npackage a\n\nfunc _(x any) {\n\tfor {\n\t\t// type switch\n\t\tswitch x.(type) { //@hiloc(tswitch, \"switch\", text)\n\t\tdefault:\n\t\t\tbreak //@hiloc(tbreak, \"break\", text),highlight(tbreak, tswitch, tbreak)\n\t\t}\n\n\t\t// value switch\n\t\tswitch { //@hiloc(vswitch, \"switch\", text)\n\t\tdefault:\n\t\t\tbreak //@hiloc(vbreak, \"break\", text), highlight(vbreak, vswitch, vbreak)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/basiclit.txt",
    "content": "This test checks gopls behavior when hovering over basic literals.\n\nSkipped on ppc64 as there appears to be a bug on aix-ppc64: golang/go#67526.\n\n-- flags --\n-skip_goarch=ppc64\n\n-- basiclit.go --\npackage basiclit\n\nfunc _() {\n\t_ = 'a' //@hover(\"'a'\", \"'a'\", latinA)\n\t_ = 0x61 //@hover(\"0x61\", \"0x61\", latinAHex)\n\n\t_ = '\\u2211' //@hover(\"'\\\\u2211'\", \"'\\\\u2211'\", summation)\n\t_ = '\\u2211' //@hover(re\"u22()11\", \"'\\\\u2211'\", summation)\n\t_ = 0x2211 //@hover(\"0x2211\", \"0x2211\", summationHex)\n\t_ = \"foo \\u2211 bar\" //@hover(\"\\\\u2211\", \"\\\\u2211\", summation)\n\n\t_ = '\\a' //@hover(\"'\\\\a'\", \"'\\\\a'\", control)\n\t_ = \"foo \\a bar\" //@hover(\"\\\\a\", \"\\\\a\", control)\n\n\t_ = '\\U0001F30A' //@hover(\"'\\\\U0001F30A'\", \"'\\\\U0001F30A'\", waterWave)\n\t_ = 0x0001F30A //@hover(\"0x0001F30A\", \"0x0001F30A\", waterWaveHex)\n\t_ = 0X0001F30A //@hover(\"0X0001F30A\", \"0X0001F30A\", waterWaveHex)\n\t_ = \"foo \\U0001F30A bar\" //@hover(\"\\\\U0001F30A\", \"\\\\U0001F30A\", waterWave)\n\n\t_ = '\\x7E' //@hover(\"'\\\\x7E'\", \"'\\\\x7E'\", tilde)\n\t_ = \"foo \\x7E bar\" //@hover(\"\\\\x7E\", \"\\\\x7E\", tilde)\n\t_ = \"foo \\a bar\" //@hover(\"\\\\a\", \"\\\\a\", control)\n\n\t_ = '\\173' //@hover(\"'\\\\173'\", \"'\\\\173'\", leftCurly)\n\t_ = \"foo \\173 bar\" //@hover(\"\\\\173\",\"\\\\173\", leftCurly)\n\t_ = \"foo \\173 bar \\u2211 baz\" //@hover(\"\\\\173\",\"\\\\173\", leftCurly)\n\t_ = \"foo \\173 bar \\u2211 baz\" //@hover(\"\\\\u2211\",\"\\\\u2211\", summation)\n\t_ = \"foo\\173bar\\u2211baz\" //@hover(\"\\\\173\",\"\\\\173\", leftCurly)\n\t_ = \"foo\\173bar\\u2211baz\" //@hover(\"\\\\u2211\",\"\\\\u2211\", summation)\n\n\t// incorrect position\n\t_ = \"foo\\173bar\\u2211baz\" //@hover(\"az\",_,_)\n\n\t// search for runes in string only if there is an escaped sequence\n\t_ = \"hello\" //@hover(`\"hello\"`, _, _)\n\n\t// incorrect escaped rune sequences\n\t_ = '\\0' //@hover(\"'\\\\0'\", _, _),diag(re`\\\\0()'`, re\"illegal character\")\n\t_ = '\\u22111' //@hover(\"'\\\\u22111'\", _, _)\n\t_ = '\\U00110000' //@hover(\"'\\\\U00110000'\", _, _)\n\t_ = '\\u12e45'//@hover(\"'\\\\u12e45'\", _, _)\n\t_ = '\\xa' //@hover(\"'\\\\xa'\", _, _)\n\t_ = 'aa' //@hover(\"'aa'\", _, _)\n\n\t// other basic lits\n\t_ = 1 //@hover(\"1\", _, _)\n\t_ = 1.2 //@hover(\"1.2\", _, _)\n\t_ = 1.2i //@hover(\"1.2i\", _, _)\n\t_ = 0123 //@hover(\"0123\", _, _)\n\t_ = 0b1001 //@hover(\"0b\", \"0b1001\", binaryNumber)\n\t_ = 0B1001 //@hover(\"0B\", \"0B1001\", binaryNumber)\n\t_ = 0o77 //@hover(\"0o\", \"0o77\", octalNumber)\n\t_ = 0O77 //@hover(\"0O\", \"0O77\", octalNumber)\n\t_ = 0x1234567890 //@hover(\"0x1234567890\", \"0x1234567890\", hexNumber)\n\t_ = 0X1234567890 //@hover(\"0X1234567890\", \"0X1234567890\", hexNumber)\n\t_ = 0x1000000000000000000 //@hover(\"0x1\", \"0x1000000000000000000\", bigHex)\n}\n-- @bigHex --\n4722366482869645213696\n-- @binaryNumber --\n9\n-- @control --\nU+0007, control\n-- @hexNumber --\n78187493520\n-- @latinA --\n'a', U+0061, LATIN SMALL LETTER A\n-- @latinAHex --\n97, 'a', U+0061, LATIN SMALL LETTER A\n-- @leftCurly --\n'{', U+007B, LEFT CURLY BRACKET\n-- @octalNumber --\n63\n-- @summation --\n'∑', U+2211, N-ARY SUMMATION\n-- @summationHex --\n8721, '∑', U+2211, N-ARY SUMMATION\n-- @tilde --\n'~', U+007E, TILDE\n-- @waterWave --\n'🌊', U+1F30A, WATER WAVE\n-- @waterWaveHex --\n127754, '🌊', U+1F30A, WATER WAVE\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/comment.txt",
    "content": "This test checks hovering over doc links in comments.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.20\n\n-- a.go --\npackage p\n\nimport (\n\t\"unsafe\"\n\n\t\"mod.com/util\" //@hover(`\"mod.com/util\"`, `\"mod.com/util\"`, strconv)\n)\n\n// [NumberBase] is the base to use for number parsing. //@hover(\"NumberBase\", \"NumberBase\", NumberBase),hover(re\"()NumberBase\", \"NumberBase\", NumberBase),hover(re\"NumberBase()\", \"NumberBase\", NumberBase)\nconst NumberBase = 10\n\n// [Conv] converts s to an int. //@hover(\"Conv\", \"Conv\", Conv)\nfunc Conv(s string) int {\n\t// [util.ParseInt] parses s and returns the integer corresponding to it. //@hover(\"util\", \"util\", util),hover(\"ParseInt\", \"ParseInt\", strconvParseInt)\n\t// [NumberBase] is the base to use for number parsing.\n\ti, _ := util.ParseInt(s, NumberBase, 64)\n\treturn int(i)\n}\n\n// UnsafeConv converts s to a byte slice using [unsafe.Pointer]. hover(\"Pointer\", \"Pointer\", unsafePointer)\nfunc UnsafeConv(s string) []byte {\n\tp := unsafe.StringData(s)\n\tb := unsafe.Slice(p, len(s))\n\treturn b\n}\n\n-- util/conv.go --\n// Package util provides utility functions.\npackage util\n\nimport \"strconv\"\n\n// ParseInt interprets a string s in the given base (0, 2 to 36) and\n// bit size (0 to 64) and returns the corresponding value i.\nfunc ParseInt(s string, base int, bitSize int) (int64, error) {\n\treturn strconv.ParseInt(s, base, bitSize)\n}\n\n-- @Conv --\n```go\nfunc Conv(s string) int\n```\n\n---\n\n[Conv](file://$WORKDIR/a.go#13,6) converts s to an int. //@hover(\"Conv\", \"Conv\", Conv)\n\n\n---\n\n[`p.Conv` on pkg.go.dev](https://pkg.go.dev/mod.com#Conv)\n-- @NumberBase --\n```go\nconst NumberBase untyped int = 10\n```\n\n---\n\n[NumberBase](file://$WORKDIR/a.go#10,7) is the base to use for number parsing. //@hover(\"NumberBase\", \"NumberBase\", NumberBase),hover(re\"()NumberBase\", \"NumberBase\", NumberBase),hover(re\"NumberBase()\", \"NumberBase\", NumberBase)\n\n\n---\n\n[`p.NumberBase` on pkg.go.dev](https://pkg.go.dev/mod.com#NumberBase)\n-- @strconv --\n```go\npackage util\n```\n\n---\n\nPackage util provides utility functions.\n-- @strconvParseInt --\n```go\nfunc ParseInt(s string, base int, bitSize int) (int64, error)\n```\n\n---\n\nParseInt interprets a string s in the given base (0, 2 to 36) and bit size (0 to 64) and returns the corresponding value i.\n\n\n---\n\n[`util.ParseInt` on pkg.go.dev](https://pkg.go.dev/mod.com/util#ParseInt)\n-- @util --\n```go\npackage util\n```\n\n---\n\nPackage util provides utility functions.\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/const.txt",
    "content": "This test checks hovering over constants.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.17\n\n-- c.go --\npackage c\n\nimport (\n\t\"math\"\n\t\"time\"\n)\n\nconst X = 0 //@hover(\"X\", \"X\", bX)\n\n// dur is a constant of type time.Duration.\nconst dur = 15*time.Minute + 10*time.Second + 350*time.Millisecond //@hover(\"dur\", \"dur\", dur)\n\nconst _ = dur // pacify unusedfunc\n\n// MaxFloat32 is used in another package.\nconst MaxFloat32 = 0x1p127 * (1 + (1 - 0x1p-23))\n\n// Numbers.\nfunc _() {\n\tconst hex, bin = 0xe34e, 0b1001001\n\n\tconst (\n\t\t// no inline comment\n\t\tdecimal = 153\n\n\t\tnumberWithUnderscore int64 = 10_000_000_000\n\t\toctal                      = 0o777\n\t\texpr                       = 2 << (0b111&0b101 - 2)\n\t\tboolean                    = (55 - 3) == (26 * 2)\n\t)\n\n\t_ = decimal              //@hover(\"decimal\", \"decimal\", decimalConst)\n\t_ = hex                  //@hover(\"hex\", \"hex\", hexConst)\n\t_ = bin                  //@hover(\"bin\", \"bin\", binConst)\n\t_ = numberWithUnderscore //@hover(\"numberWithUnderscore\", \"numberWithUnderscore\", numberWithUnderscoreConst)\n\t_ = octal                //@hover(\"octal\", \"octal\", octalConst)\n\t_ = expr                 //@hover(\"expr\", \"expr\", exprConst)\n\t_ = boolean              //@hover(\"boolean\", \"boolean\", boolConst)\n\n\tconst ln10 = 2.30258509299404568401799145468436420760110148862877297603332790\n\n\t_ = ln10 //@hover(\"ln10\", \"ln10\", ln10Const)\n}\n\n// Iota.\nfunc _() {\n\tconst (\n\t\ta = 1 << iota\n\t\tb\n\t)\n\n\t_ = a //@hover(\"a\", \"a\", aIota)\n\t_ = b //@hover(\"b\", \"b\", bIota)\n}\n\n// Strings.\nfunc _() {\n\tconst (\n\t\tstr     = \"hello\" + \" \" + \"world\"\n\t\tlongStr = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eget ipsum non nunc\nmolestie mattis id quis augue. Mauris dictum tincidunt ipsum, in auctor arcu congue eu.\nMorbi hendrerit fringilla libero commodo varius. Vestibulum in enim rutrum, rutrum tellus\naliquet, luctus enim. Nunc sem ex, consectetur id porta nec, placerat vel urna.`\n\t)\n\n\t_ = str     //@hover(\"str\", \"str\", strConst)\n\t_ = longStr //@hover(\"longStr\", \"longStr\", longStrConst)\n}\n\n// Constants from other packages.\nfunc _() {\n\t_ = math.Log2E //@hover(\"Log2E\", \"Log2E\", log2eConst)\n}\n\n-- @bX --\n```go\nconst X untyped int = 0\n```\n\n---\n\n@hover(\"X\", \"X\", bX)\n\n\n---\n\n[`c.X` on pkg.go.dev](https://pkg.go.dev/mod.com#X)\n-- @dur --\n```go\nconst dur time.Duration = 15*time.Minute + 10*time.Second + 350*time.Millisecond // 15m10.35s\n```\n\n---\n\ndur is a constant of type time.Duration.\n-- @decimalConst --\n```go\nconst decimal untyped int = 153\n```\n\n---\n\nno inline comment\n-- @hexConst --\n```go\nconst hex untyped int = 0xe34e // 58190\n```\n-- @binConst --\n```go\nconst bin untyped int = 0b1001001 // 73\n```\n-- @numberWithUnderscoreConst --\n```go\nconst numberWithUnderscore int64 = 10_000_000_000 // 10000000000\n```\n-- @octalConst --\n```go\nconst octal untyped int = 0o777 // 511\n```\n-- @exprConst --\n```go\nconst expr untyped int = 2 << (0b111&0b101 - 2) // 16\n```\n-- @boolConst --\n```go\nconst boolean untyped bool = (55 - 3) == (26 * 2) // true\n```\n-- @ln10Const --\n```go\nconst ln10 untyped float = 2.30258509299404568401799145468436420760110148862877297603332790 // 2.30259\n```\n-- @aIota --\n```go\nconst a untyped int = 1 << iota // 1\n```\n-- @bIota --\n```go\nconst b untyped int = 2\n```\n-- @strConst --\n```go\nconst str untyped string = \"hello world\"\n```\n-- @longStrConst --\n```go\nconst longStr untyped string = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur e...\n```\n-- @log2eConst --\n```go\nconst math.Log2E untyped float = 1 / Ln2 // 1.4427\n```\n\n---\n\nMathematical constants.\n\n\n---\n\n[`math.Log2E` on pkg.go.dev](https://pkg.go.dev/math#Log2E)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/embed.txt",
    "content": "This test checks that hover reports accessible embedded fields\n(after the doc comment  and before the accessible methods).\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- q/q.go --\npackage q\n\ntype Q struct {\n\tOne int\n\ttwo string\n\tq2[chan int]\n}\n\ntype q2[T any] struct {\n\tThree *T\n\tfour string\n}\n\n-- p.go --\npackage p\n\nimport \"example.com/q\"\n\n// doc\ntype P struct {\n\tq.Q\n}\n\nfunc (P) m() {}\n\nvar p P //@hover(\"P\", \"P\", P)\n\nvar _, _ = P.m, p // pacify unusedfunc\n\ntype A struct {\n\t*B\n}\n\ntype B struct {\n\t*C\n}\n\ntype C struct {\n\t*D\n}\n\ntype D struct {\n\tE int\n}\n\ntype X struct{\n\t*Y\n}\n\ntype Y struct {\n\t*Z\n}\n\ntype Z struct{\n\tz int\n}\n\nvar a A\nvar _ = a.E //@hover(\"E\", \"E\", E)\n\nvar x struct {\n\t*X\n}\nvar _ = x.z //@hover(\"z\", \"z\", Z)\n\ntype Al2 = int\ntype N struct{\n\tx Al2\n\ty struct{ ZA }\n}\ntype Al = *N\ntype S struct{ Al }\ntype ZA = *Z\nvar _ = new(S).x //@hover(\"x\", \"x\", X)\nvar _ = new(S).y.z //@hover(\"z\", \"z\", Zz), hover(\"y\", \"y\", y)\n\n-- @P --\n```go\ntype P struct {\n\tq.Q\n}\n```\n\n---\n\ndoc\n\n\n```go\n// Embedded fields:\nOne   int       // through Q    \nThree *chan int // through Q.q2 \n```\n\n```go\nfunc (P) m()\n```\n\n---\n\n[`p.P` on pkg.go.dev](https://pkg.go.dev/example.com#P)\n-- @E --\n```go\nfield E int // through *B, *C, *D\n```\n\n---\n\n[`(p.D).E` on pkg.go.dev](https://pkg.go.dev/example.com#D.E)\n-- @Z --\n```go\nfield z int // through *X, *Y, *Z\n```\n-- @X --\n```go\nfield x Al2 // through Al\n```\n-- @Zz --\n```go\nfield z int // through ZA\n```\n-- @y --\n```go\nfield y struct{ZA} // through Al\n```\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/expression.txt",
    "content": "This test checks that hovering over a range reveals the expression type.\n\n-- a.go --\npackage a\n\nimport \"time\"\n\nconst (\n    _ = 'a' + 2//@hover(\"'a' + 2\", \"'a' + 2\", \"99\")\n\n    _ = \"A\" + \"B\"//@hover(\"\\\"A\\\" + \\\"B\\\"\", \"\\\"A\\\" + \\\"B\\\"\", \"AB\")\n\n    _ = 2 * 3 * 4//@hover(\"3 * 4\", \"2 * 3 * 4\", \"24\")\n\n    _ = (1 < 2)//@hover(\"1 < 2\", \"1 < 2\", \"true\")\n\n    _ = (1 + 2i) * (3 + 4i)//@hover(\"(1 + 2i) * (3 + 4i)\", \"(1 + 2i) * (3 + 4i)\", \"(-5 + 10i)\")\n)\n\ntype Foo struct {\n    foo string\n}\n\nfunc _() {\n    // type of slice expression.\n    ints := []int{}\n    _ = ints[1:2]//@hover(\"ints[1:2]\", \"ints[1:2]\", \"[]int\")\n\n    foos := []Foo{}\n    _ = foos[1:2]//@hover(\"foos[1:2]\", \"foos[1:2]\", \"[]Foo\")\n\n    // type of map expression\n    m := map[string]int{\"one\": 1}\n    _ = m[\"one\"]//@hover(\"m[\\\"one\\\"]\", \"m[\\\"one\\\"]\", \"int\")\n\n    // type of channel expression\n    ch := make(chan bool)\n    _ = <-ch//@hover(\"<-ch\", \"<-ch\", \"bool\")\n\n    // type of pointer expression\n    ptr := &ch//@hover(\"&ch\", \"&ch\", \"*chan bool\")\n    _ = *ptr//@hover(\"*ptr\", \"*ptr\", \"chan bool\")\n\n    // type of unary\n    _ = -ints[0]//@hover(\"-ints[0]\", \"-ints[0]\", \"int\")\n\n    // type of type assertion\n    var x any\n\n    _ = x.(*Foo)//@hover(\"x.(*Foo)\", \"x.(*Foo)\", \"*Foo\"),diag(re\"x.()\", re\"nil dereference in type assertion\")\n\n    // Expression inside of switch statement does not have a type. \n    switch x := x.(type) {//@hover(\"x.(type)\",_, _)\n    default:\n        _ = x\n    }\n\n    // type of function/method return value.\n    _ = time.Now().UTC().Add(10 * time.Minute)//@hover(\"time.Now().UTC()\", \"time.Now().UTC()\", \"time.Time\")\n\n    // type of function/method signature.\n    _ = time.Now().UTC().Add(10 * time.Minute)//@hover(\"time.Now().UTC\", \"time.Now().UTC\", \"func() time.Time\")\n\n    // type of field\n    var t time.Timer\n    _ = <-t.C//@hover(\"t.C\", \"t.C\", \"<-chan time.Time\"),hover(\"<-t.C\", \"<-t.C\", \"time.Time\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/fileuri.txt",
    "content": "This test demonstrates file uri over doc link in hover.\n\n-- settings.json --\n{\n\t\"hoverKind\": \"FullDocumentation\"\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- main.go --\npackage main\n\nimport (\n    \"example.com/foo\"\n)\n\nfunc main() {\n    // Call [foo.Foo]//@hover(\"Foo\", \"Foo\", Foo)\n    foo.Foo()//@hover(\"Foo\", \"Foo\", fooFoo)\n}\n\n-- foo/foo.go --\n// package foo defines function [Foo]//@hover(\"Foo\", \"Foo\", Foo)\npackage foo\n\nimport(\n    \"example.com/a\"\n    \"example.com/b\"\n)\n\n// doc comment for Foo will reference the following\n//\n// two packages [a] and [b]\n//\n// a type [a.A]\n//\n// a type's field [a.A.A]\n//\n// a type's method [a.A.Bar]\n//\n// an interface [a.I]\n//\n// an interface's method [a.I.Foo]\n//\n// a const [b.B]\n//\n// a variable [b.V]\n//\n// a doc link [xtools github website]\n//\n// [xtools github website]: https://github.com/golang/tools\nfunc Foo() {} //@hover(\"Foo\", \"Foo\", Foo)\n-- a/a.go --\npackage a\n\ntype A struct {\n    A string\n}\n\nfunc (*A) Bar(){}\n\ntype I interface {\n    Foo()\n}\n\n-- b/b.go --\npackage b\n\nimport (\n    \"example.com/a\"\n)\n\nconst B = 3\n\nvar V = 4\n-- @Foo --\n```go\nfunc Foo()\n```\n\n---\n\ndoc comment for Foo will reference the following\n\ntwo packages [a](file://$WORKDIR/foo/foo.go#5,5) and [b](file://$WORKDIR/foo/foo.go#6,5)\n\na type [a.A](file://$WORKDIR/a/a.go#3,6)\n\na type's field [a.A.A](file://$WORKDIR/a/a.go#4,5)\n\na type's method [a.A.Bar](file://$WORKDIR/a/a.go#7,11)\n\nan interface [a.I](file://$WORKDIR/a/a.go#9,6)\n\nan interface's method [a.I.Foo](file://$WORKDIR/a/a.go#10,5)\n\na const [b.B](file://$WORKDIR/b/b.go#7,7)\n\na variable [b.V](file://$WORKDIR/b/b.go#9,5)\n\na doc link [xtools github website](https://github.com/golang/tools)\n\n\n---\n\n[`foo.Foo` on pkg.go.dev](https://pkg.go.dev/example.com/foo#Foo)\n-- @fooFoo --\n```go\nfunc foo.Foo()\n```\n\n---\n\ndoc comment for Foo will reference the following\n\ntwo packages [a](file://$WORKDIR/foo/foo.go#5,5) and [b](file://$WORKDIR/foo/foo.go#6,5)\n\na type [a.A](file://$WORKDIR/a/a.go#3,6)\n\na type's field [a.A.A](file://$WORKDIR/a/a.go#4,5)\n\na type's method [a.A.Bar](file://$WORKDIR/a/a.go#7,11)\n\nan interface [a.I](file://$WORKDIR/a/a.go#9,6)\n\nan interface's method [a.I.Foo](file://$WORKDIR/a/a.go#10,5)\n\na const [b.B](file://$WORKDIR/b/b.go#7,7)\n\na variable [b.V](file://$WORKDIR/b/b.go#9,5)\n\na doc link [xtools github website](https://github.com/golang/tools)\n\n\n---\n\n[`foo.Foo` on pkg.go.dev](https://pkg.go.dev/example.com/foo#Foo)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/generics.txt",
    "content": "This file contains tests for hovering over generic Go code.\n\nRequires go1.20+ for the new go/doc/comment package, and a change in Go 1.20\nthat affected the formatting of constraint interfaces.\n\nIts size expectations assume a 64-bit machine.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\n// A go.mod is require for correct pkgsite links.\n// TODO(rfindley): don't link to ad-hoc or command-line-arguments packages!\nmodule mod.com\n\ngo 1.18\n\n-- issue68213.go --\npackage generics\n\n// Hovering over an interface with empty type set must not panic.\ntype empty interface { //@hover(\"empty\", \"empty\", empty)\n\tint\n\tstring\n}\n\n-- @empty --\n```go\ntype empty interface { // size=16 (0x10)\n\tint\n\tstring\n}\n```\n\n---\n\nHovering over an interface with empty type set must not panic.\n-- generics.go --\npackage generics\n\ntype value[T any] struct { //@hover(\"lue\", \"value\", value),hover(\"T\", \"T\", valueT)\n\tval T   //@hover(\"T\", \"T\", valuevalT)\n\tQ   int64 //@hover(\"Q\", \"Q\", valueQ)\n}\n\ntype Value[T any] struct { //@hover(\"T\", \"T\", ValueT)\n\tval T   //@hover(\"T\", \"T\", ValuevalT)\n\tQ   int64 //@hover(\"Q\", \"Q\", ValueQ)\n}\n\nfunc F[P interface{ ~int | string }]() { //@hover(\"P\", \"P\", Ptparam)\n\tvar _ P //@hover(\"P\",\"P\",Pvar)\n}\n\n-- @value --\n```go\ntype value[T any] struct {\n\tval T     //@hover(\"T\", \"T\", valuevalT)\n\tQ   int64 //@hover(\"Q\", \"Q\", valueQ)\n}\n```\n-- @valueT --\n```go\ntype parameter T any\n```\n-- @valuevalT --\n```go\ntype parameter T any\n```\n-- @valueQ --\n```go\nfield Q int64 // size=8\n```\n\n---\n\n@hover(\"Q\", \"Q\", valueQ)\n-- @ValueT --\n```go\ntype parameter T any\n```\n-- @ValuevalT --\n```go\ntype parameter T any\n```\n-- @ValueQ --\n```go\nfield Q int64 // size=8\n```\n\n---\n\n@hover(\"Q\", \"Q\", ValueQ)\n\n\n---\n\n[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)\n-- @Ptparam --\n```go\ntype parameter P interface{~int | string}\n```\n-- @Pvar --\n```go\ntype parameter P interface{~int | string}\n```\n-- inferred.go --\npackage generics\n\nfunc app[S interface{ ~[]E }, E any](s S, e E) S {\n\treturn append(s, e)\n}\n\nfunc _() {\n\t_ = app[[]int]             //@hover(\"app\", \"app\", appint)\n\t_ = app[[]int, int]        //@hover(\"app\", \"app\", appint)\n\t_ = app[[]int]([]int{}, 0) //@hover(\"app\", \"app\", appint), diag(\"[[]int]\", re\"unnecessary\")\n\t_ = app([]int{}, 0)        //@hover(\"app\", \"app\", appint)\n}\n\n-- @appint --\n```go\nfunc app(s []int, e int) []int // func[S interface{~[]E}, E any](s S, e E) S\n```\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/godef.txt",
    "content": "This test was ported from 'godef' in the old marker tests.\nIt tests various hover and definition requests.\n\n-- go.mod --\nmodule godef.test\n\ngo 1.18\n\n-- a/a_x_test.go --\npackage a_test\n\nimport (\n\t\"testing\"\n)\n\nfunc TestA2(t *testing.T) { //@hover(\"TestA2\", \"TestA2\", TestA2)\n\tNonexistant() //@diag(\"Nonexistant\", re\"(undeclared name|undefined): Nonexistant\")\n}\n\n-- @TestA2 --\n```go\nfunc TestA2(t *testing.T)\n```\n-- @ember --\n```go\nfield Member string\n```\n\n---\n\n@loc(Member, \"Member\")\n\n\n---\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing.Member)\n-- a/d.go --\npackage a //@hover(\"a\", _, a)\n\nimport \"fmt\"\n\ntype Thing struct { //@loc(Thing, \"Thing\")\n\tMember string //@loc(Member, \"Member\")\n}\n\nvar Other Thing //@loc(Other, \"Other\")\n\nfunc Things(val []string) []Thing { //@loc(Things, \"Things\")\n\treturn nil\n}\n\nfunc (t Thing) Method(i int) string { //@loc(Method, \"Method\")\n\treturn t.Member\n}\n\nfunc (t Thing) Method3() {\n}\n\nfunc (t *Thing) Method2(i int, j int) (error, string) {\n\treturn nil, t.Member\n}\n\nfunc (t *Thing) private() {\n}\n\nfunc useThings() {\n\tt := Thing{ //@hover(\"ing\", \"Thing\", ing)\n\t\tMember: \"string\", //@hover(\"ember\", \"Member\", ember), def(\"ember\", Member)\n\t}\n\tfmt.Print(t.Member) //@hover(\"ember\", \"Member\", ember), def(\"ember\", Member)\n\tfmt.Print(Other)    //@hover(\"ther\", \"Other\", ther), def(\"ther\", Other)\n\tThings(nil)         //@hover(\"ings\", \"Things\", ings), def(\"ings\", Things)\n\tt.Method(0)         //@hover(\"eth\", \"Method\", eth), def(\"eth\", Method)\n}\n\ntype NextThing struct { //@loc(NextThing, \"NextThing\")\n\tThing\n\tValue int\n}\n\nfunc (n NextThing) another() string {\n\treturn n.Member\n}\n\n// Shadows Thing.Method3\nfunc (n *NextThing) Method3() int {\n\treturn n.Value\n}\n\nvar nextThing NextThing //@hover(\"NextThing\", \"NextThing\", NextThing), def(\"NextThing\", NextThing)\n\n-- @ings --\n```go\nfunc Things(val []string) []Thing\n```\n\n---\n\n[`a.Things` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Things)\n-- @ther --\n```go\nvar Other Thing\n```\n\n---\n\n@loc(Other, \"Other\")\n\n\n---\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Other)\n-- @a --\n-- @ing --\n```go\ntype Thing struct {\n\tMember string //@loc(Member, \"Member\")\n}\n```\n\n---\n\n```go\nfunc (t Thing) Method(i int) string\nfunc (t *Thing) Method2(i int, j int) (error, string)\nfunc (t Thing) Method3()\nfunc (t *Thing) private()\n```\n\n---\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing)\n-- @NextThing --\n```go\ntype NextThing struct {\n\tThing\n\tValue int\n}\n```\n\n---\n\n```go\n// Embedded fields:\nMember string // through Thing \n```\n\n```go\nfunc (t Thing) Method(i int) string\nfunc (t *Thing) Method2(i int, j int) (error, string)\nfunc (n *NextThing) Method3() int\nfunc (n NextThing) another() string\nfunc (t *Thing) private()\n```\n\n---\n\n[`a.NextThing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#NextThing)\n-- @eth --\n```go\nfunc (t Thing) Method(i int) string\n```\n\n---\n\n[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing.Method)\n-- a/f.go --\n// Package a is a package for testing go to definition.\npackage a\n\nimport \"fmt\"\n\nfunc TypeStuff() {\n\tvar x string\n\n\tswitch y := any(x).(type) { //@loc(y, \"y\"), hover(\"y\", \"y\", y) , def(\"y\", y)\n\tcase int: //@loc(intY, \"int\")\n\t\tfmt.Printf(\"%v\", y) //@hover(\"y\", \"y\", inty), def(\"y\", y)\n\tcase string: //@loc(stringY, \"string\")\n\t\tfmt.Printf(\"%v\", y) //@hover(\"y\", \"y\", stringy), def(\"y\", y)\n\t}\n\n}\n-- @inty --\n```go\nvar y int\n```\n-- @stringy --\n```go\nvar y string\n```\n-- @y --\n```go\nvar y any\n```\n-- a/h.go --\npackage a\n\nfunc _() {\n\ttype s struct {\n\t\tnested struct {\n\t\t\t// nested number\n\t\t\tnumber int64 //@loc(nestedNumber, \"number\")\n\t\t}\n\t\tnested2 []struct {\n\t\t\t// nested string\n\t\t\tstr string //@loc(nestedString, \"str\")\n\t\t}\n\t\tx struct {\n\t\t\tx struct {\n\t\t\t\tx struct {\n\t\t\t\t\tx struct {\n\t\t\t\t\t\tx struct {\n\t\t\t\t\t\t\t// nested map\n\t\t\t\t\t\t\tm map[string]float64 //@loc(nestedMap, \"m\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar t s\n\t_ = t.nested.number  //@hover(\"number\", \"number\", nestedNumber), def(\"number\", nestedNumber)\n\t_ = t.nested2[0].str //@hover(\"str\", \"str\", nestedString), def(\"str\", nestedString)\n\t_ = t.x.x.x.x.x.m    //@hover(\"m\", \"m\", nestedMap), def(\"m\", nestedMap)\n}\n\nfunc _() {\n\tvar s struct {\n\t\t// a field\n\t\ta int //@loc(structA, \"a\")\n\t\t// b nested struct\n\t\tb struct { //@loc(structB, \"b\")\n\t\t\t// c field of nested struct\n\t\t\tc int //@loc(structC, \"c\")\n\t\t}\n\t}\n\t_ = s.a   //@def(\"a\", structA)\n\t_ = s.b   //@def(\"b\", structB)\n\t_ = s.b.c //@def(\"c\", structC)\n\n\tvar arr []struct {\n\t\t// d field\n\t\td int //@loc(arrD, \"d\")\n\t\t// e nested struct\n\t\te struct { //@loc(arrE, \"e\")\n\t\t\t// f field of nested struct\n\t\t\tf int //@loc(arrF, \"f\")\n\t\t}\n\t}\n\t_ = arr[0].d   //@def(\"d\", arrD)\n\t_ = arr[0].e   //@def(\"e\", arrE)\n\t_ = arr[0].e.f //@def(\"f\", arrF)\n\n\tvar complex []struct {\n\t\tc <-chan map[string][]struct {\n\t\t\t// h field\n\t\t\th int //@loc(complexH, \"h\")\n\t\t\t// i nested struct\n\t\t\ti struct { //@loc(complexI, \"i\")\n\t\t\t\t// j field of nested struct\n\t\t\t\tj int //@loc(complexJ, \"j\")\n\t\t\t}\n\t\t}\n\t}\n\t_ = (<-complex[0].c)[\"0\"][0].h   //@def(\"h\", complexH)\n\t_ = (<-complex[0].c)[\"0\"][0].i   //@def(\"i\", complexI)\n\t_ = (<-complex[0].c)[\"0\"][0].i.j //@def(\"j\", complexJ)\n\n\tvar mapWithStructKey map[struct { //@diag(\"struct\", re\"invalid map key\")\n\t\t// X key field\n\t\tx []string //@loc(mapStructKeyX, \"x\")\n\t}]int\n\tfor k := range mapWithStructKey {\n\t\t_ = k.x //@def(\"x\", mapStructKeyX)\n\t}\n\n\tvar mapWithStructKeyAndValue map[struct {\n\t\t// Y key field\n\t\ty string //@loc(mapStructKeyY, \"y\")\n\t}]struct {\n\t\t// X value field\n\t\tx string //@loc(mapStructValueX, \"x\")\n\t}\n\tfor k, v := range mapWithStructKeyAndValue {\n\t\t// TODO: we don't show docs for y field because both map key and value\n\t\t// are structs. And in this case, we parse only map value\n\t\t_ = k.y //@hover(\"y\", \"y\", hoverStructKeyY), def(\"y\", mapStructKeyY)\n\t\t_ = v.x //@hover(\"x\", \"x\", hoverStructKeyX), def(\"x\", mapStructValueX)\n\t}\n\n\tvar i []map[string]interface {\n\t\t// open method comment\n\t\topen() error //@loc(openMethod, \"open\")\n\t}\n\ti[0][\"1\"].open() //@hover(\"pen\",\"open\", openMethod), def(\"open\", openMethod)\n}\n\nfunc _() {\n\ttest := struct {\n\t\t// test description\n\t\tdesc string //@loc(testDescription, \"desc\")\n\t}{}\n\t_ = test.desc //@def(\"desc\", testDescription)\n\n\tfor _, tt := range []struct {\n\t\t// test input\n\t\tin map[string][]struct { //@loc(testInput, \"in\")\n\t\t\t// test key\n\t\t\tkey string //@loc(testInputKey, \"key\")\n\t\t\t// test value\n\t\t\tvalue any //@loc(testInputValue, \"value\")\n\t\t}\n\t\tresult struct {\n\t\t\tv <-chan struct {\n\t\t\t\t// expected test value\n\t\t\t\tvalue int //@loc(testResultValue, \"value\")\n\t\t\t}\n\t\t}\n\t}{} {\n\t\t_ = tt.in               //@def(\"in\", testInput)\n\t\t_ = tt.in[\"0\"][0].key   //@def(\"key\", testInputKey)\n\t\t_ = tt.in[\"0\"][0].value //@def(\"value\", testInputValue)\n\n\t\t_ = (<-tt.result.v).value //@def(\"value\", testResultValue)\n\t}\n}\n\nfunc _() {\n\tgetPoints := func() []struct {\n\t\t// X coord\n\t\tx int //@loc(returnX, \"x\")\n\t\t// Y coord\n\t\ty int //@loc(returnY, \"y\")\n\t} {\n\t\treturn nil\n\t}\n\n\tr := getPoints()\n\t_ = r[0].x //@def(\"x\", returnX)\n\t_ = r[0].y //@def(\"y\", returnY)\n}\n-- @hoverStructKeyX --\n```go\nfield x string\n```\n\n---\n\nX value field\n-- @hoverStructKeyY --\n```go\nfield y string\n```\n\n---\n\nY key field\n-- @nestedNumber --\n```go\nfield number int64\n```\n\n---\n\nnested number\n-- @nestedString --\n```go\nfield str string\n```\n\n---\n\nnested string\n-- @openMethod --\n```go\nfunc (interface) open() error\n```\n\n---\n\nopen method comment\n-- @nestedMap --\n```go\nfield m map[string]float64\n```\n\n---\n\nnested map\n-- b/e.go --\npackage b\n\nimport (\n\t\"fmt\"\n\n\t\"godef.test/a\"\n)\n\nfunc useThings() {\n\tt := a.Thing{}      //@loc(bStructType, \"ing\")\n\tfmt.Print(t.Member) //@loc(bMember, \"ember\")\n\tfmt.Print(a.Other)  //@loc(bVar, \"ther\")\n\ta.Things(nil)          //@loc(bFunc, \"ings\")\n}\n\n/*@\ndef(bStructType, Thing)\ndef(bMember, Member)\ndef(bVar, Other)\ndef(bFunc, Things)\n*/\n\nfunc _() {\n\tvar x any\n\tswitch x := x.(type) { //@hover(\"x\", \"x\", xInterface)\n\tcase string: //@loc(eString, \"string\")\n\t\tfmt.Println(x) //@hover(\"x\", \"x\", xString)\n\tcase int: //@loc(eInt, \"int\")\n\t\tfmt.Println(x) //@hover(\"x\", \"x\", xInt)\n\t}\n}\n-- @xInt --\n```go\nvar x int\n```\n-- @xInterface --\n```go\nvar x any\n```\n-- @xString --\n```go\nvar x string\n```\n-- broken/unclosedIf.go --\npackage broken\n\nimport \"fmt\"\n\nfunc unclosedIf() {\n\tif false {\n\t\tvar myUnclosedIf string              //@loc(myUnclosedIf, \"myUnclosedIf\")\n\t\tfmt.Printf(\"s = %v\\n\", myUnclosedIf) //@def(\"my\", myUnclosedIf)\n}\n\nfunc _() {} //@diag(\"_\", re\"expected\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/goprivate.txt",
    "content": "This test checks that links in hover obey GOPRIVATE.\n\n-- env --\nGOPRIVATE=mod.com\n-- go.mod --\nmodule mod.com\n-- p.go --\npackage p\n\n// T should not be linked, as it is private.\ntype T struct{} //@hover(\"T\", \"T\", T)\n-- lib/lib.go --\npackage lib\n\n// GOPRIVATE should also match nested packages.\ntype L struct{} //@hover(\"L\", \"L\", L)\n-- @L --\n```go\ntype L struct{} // size=0\n```\n\n---\n\nGOPRIVATE should also match nested packages.\n-- @T --\n```go\ntype T struct{} // size=0\n```\n\n---\n\nT should not be linked, as it is private.\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/hover-74351.txt",
    "content": "Regression test for crash in hover on an alias to a built-in named type.\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A = error //@hover(\"A\", \"A\", out)\n\n-- @out --\n```go\ntype A = error // size=16 (0x10)\n\ntype error interface {\n\tError() string\n}\n```\n\n---\n\n@hover(\"A\", \"A\", out)\n\n\n```go\nfunc (error) Error() string\n```\n\n---\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/example.com/a#A)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/hover.txt",
    "content": "This test demonstrates some basic features of hover.\n\nOne of those features is the display of per-file variation in\nconfiguration, including GODEBUG. We use panicnil from go1.21 as an\narbitrary GODEBUG; if it goes away, pick another from\nhttps://go.dev/doc/godebug#history.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- flags --\n-min_go_command=go1.21\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a.go --\n// package comment\npackage aa //@hover(\"aa\", \"aa\", aa)\n\nconst abc = 0x2a //@hover(\"b\", \"abc\", abc),hover(re\"() =\", \"abc\", abc)\n\n-- a2.go --\n\n//go:build go1.21\n\npackage aa //@hover(\"aa\", \"aa\", aa2)\n\n-- typeswitch.go --\npackage aa\n\nfunc _() {\n\tvar y any\n\tswitch x := y.(type) { //@hover(\"x\", \"x\", x)\n\tcase int:\n\t\tprintln(x) //@hover(\"x\", \"x\", xint)\n\t}\n}\n-- cmd/main.go --\n//go:debug panicnil=0\n\n// Note that since GODEBUG shows only settings that differ from\n// the current toolchain, the output here depends on the toolchain used.\npackage main //@hover(\"main\", \"main\", main)\n\nfunc main() {\n}\n\n-- @abc --\n```go\nconst abc untyped int = 0x2a // 42\n```\n\n---\n\n@hover(\"b\", \"abc\", abc),hover(re\"() =\", \"abc\", abc)\n-- @x --\n```go\nvar x any\n```\n-- @xint --\n```go\nvar x int\n```\n-- @aa --\n```go\npackage aa\n```\n\n---\n\npackage comment\n\n\n---\n\n - Package path: example.com\n - Module: example.com\n - Language version: go1.18\n-- @aa2 --\n```go\npackage aa\n```\n\n---\n\npackage comment\n\n\n---\n\n - Package path: example.com\n - Module: example.com\n - Language version (current file): go1.21\n-- @main --\n```go\npackage main\n```\n\n---\n\nNote that since GODEBUG shows only settings that differ from the current toolchain, the output here depends on the toolchain used.\n\n\n---\n\n - Package path: example.com/cmd\n - Module: example.com\n - Language version: go1.18\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/hover_alias.txt",
    "content": "This test checks gopls behavior when hovering over alias type.\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- main.go --\npackage main\n\nimport \"mod.com/a\"\nimport \"mod.com/b\"\n\ntype ToTypeDecl = b.RealType //@hover(\"ToTypeDecl\", \"ToTypeDecl\", ToTypeDecl)\n\ntype ToAlias = a.Alias //@hover(\"ToAlias\", \"ToAlias\", ToAlias)\n\ntype ToAliasWithComment = a.AliasWithComment //@hover(\"ToAliasWithComment\", \"ToAliasWithComment\", ToAliasWithComment)\n\n-- a/a.go --\npackage a\nimport \"mod.com/b\"\n\ntype Alias = b.RealType\n\n// AliasWithComment is a type alias with comments.\ntype AliasWithComment = b.RealType\n\n-- b/b.go --\npackage b\n// RealType is a real type rather than an alias type.\ntype RealType struct {\n\tName string\n\tAge int\n}\n\n-- generic/a.go --\npackage generic\nfunc generic[T any]() {}\n\ntype Named string\ntype Alias = Named\n\nfunc _(){\n\tgeneric[Alias]() //@hover(\"Alias\", \"Alias\", Alias)\n}\n\n-- @ToTypeDecl --\n```go\ntype ToTypeDecl = b.RealType // size=24 (0x18)\n\ntype RealType struct {\n\tName string\n\tAge  int\n}\n```\n\n---\n\n@hover(\"ToTypeDecl\", \"ToTypeDecl\", ToTypeDecl)\n\n\n---\n\n[`main.ToTypeDecl` on pkg.go.dev](https://pkg.go.dev/mod.com#ToTypeDecl)\n-- @ToAlias --\n```go\ntype ToAlias = a.Alias // size=24 (0x18)\n```\n\n---\n\n@hover(\"ToAlias\", \"ToAlias\", ToAlias)\n\n\n---\n\n[`main.ToAlias` on pkg.go.dev](https://pkg.go.dev/mod.com#ToAlias)\n-- @ToAliasWithComment --\n```go\ntype ToAliasWithComment = a.AliasWithComment // size=24 (0x18)\n```\n\n---\n\n@hover(\"ToAliasWithComment\", \"ToAliasWithComment\", ToAliasWithComment)\n\n\n---\n\n[`main.ToAliasWithComment` on pkg.go.dev](https://pkg.go.dev/mod.com#ToAliasWithComment)\n-- @Alias --\n```go\ntype Alias = Named\n\ntype Named string\n```\n\n---\n\n[`generic.Alias` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#Alias)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/issue74361.txt",
    "content": "-- flags --\n-skip_goarch=386,arm\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- go.mod --\nmodule mod.com\n\n-- a/a.go --\npackage a\n\ntype (\n\tNamed  int\n\tAlias  = Named\n\tAlias2 = Alias\n)\n\nvar (\n\tnamed  Named\n\talias  Alias //@hover(\"alias\", \"alias\", alias)\n\talias2 Alias2 //@hover(\"alias2\", \"alias2\", alias2)\n)\n\n-- @alias --\n```go\nvar alias Alias\n```\n\n---\n\n@hover(\"alias\", \"alias\", alias)\n-- @alias2 --\n```go\nvar alias2 Alias2\n```\n\n---\n\n@hover(\"alias2\", \"alias2\", alias2)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/issue75975.txt",
    "content": "This test checks that hovering over an embedded field\nreports information about the field, not its type.\n\nWe put backslash escapes in the hover expectation as the @hover marker\nappears on the same line as the declaration. Otherwise the hover doc\ncontent, which includes the comment containing the marker itself,\nwould trivially satisfy itself no matter what text we expect!\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule mod.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A struct {\n\tbyte\n\tS string //@ hover(\"S\", \"S\", \"field S string // size=16 (0x10), offset=8\\n\")\n}\n\ntype B struct {\n\tbyte\n\tS //@ hover(\"S\", \"S\", \"field S S // size=1, class=8, offset=1\\n\")\n}\n\ntype C struct {\n\tbyte\n\t*S // hover(\"S\", \"S\", \"field S S // size=1, class=8, offset=1\\n\")\n}\n\ntype S byte\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/issues.txt",
    "content": "This test verifies fixes for various issues reported for hover.\n\n-- go.mod --\nmodule golang.org/lsptests\n\n-- issue64239/p.go --\npackage issue64239\n\n// golang/go#64239: hover fails for objects in the unsafe package.\n\nimport \"unsafe\"\n\nvar _ = unsafe.Sizeof(struct{}{}) //@hover(\"Sizeof\", \"Sizeof\", \"`Sizeof` on pkg.go.dev\")\n\n-- issue64237/p.go --\npackage issue64237\n\n// golang/go#64237: hover panics for broken imports.\n\nimport \"golang.org/lsptests/nonexistant\" //@diag(\"\\\"golang\", re\"could not import\")\n\nvar _ = nonexistant.Value //@hovererr(\"nonexistant\", \"no package data\")\n\n-- issue69362/p.go --\npackage issue69362\n\n// golang/go#69362: hover panics over undefined implicits.\n\nfunc _() {\n\tswitch x := y.(type) { //@diag(\"y\", re\"undefined\"), hover(\"x\", \"x\", \"\")\n\tcase int:\n\t\t_ = x\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/json.txt",
    "content": "This test demonstrates support for \"hoverKind\": \"Structured\".\n\nIts size expectations assume a 64-bit machine.\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule example.com/p\n\ngo 1.18\n\n-- settings.json --\n{\n\t\"hoverKind\": \"Structured\"\n}\n-- p.go --\npackage p\n\n// MyType is a type.\ntype MyType struct { //@ hover(\"MyType\", \"MyType\", MyType)\n\tF int // a field\n\tS string // a string field\n}\n\n// MyFunc is a function.\nfunc MyFunc(i int) string { //@ hover(\"MyFunc\", \"MyFunc\", MyFunc)\n\treturn \"\"\n}\n-- @MyFunc --\n{\"synopsis\":\"MyFunc is a function.\",\"fullDocumentation\":\"MyFunc is a function.\\n\",\"signature\":\"func MyFunc(i int) string\",\"singleLine\":\"func MyFunc(i int) string\",\"symbolName\":\"p.MyFunc\",\"linkPath\":\"example.com/p\",\"linkAnchor\":\"MyFunc\"}\n-- @MyType --\n{\"synopsis\":\"MyType is a type.\",\"fullDocumentation\":\"MyType is a type.\\n\",\"signature\":\"type MyType struct { // size=24 (0x18)\\n\\tF int    // a field\\n\\tS string // a string field\\n}\\n\",\"singleLine\":\"type MyType struct{F int; S string}\",\"symbolName\":\"p.MyType\",\"linkPath\":\"example.com/p\",\"linkAnchor\":\"MyType\"}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/linkable.txt",
    "content": "This test checks that we correctly determine pkgsite links for various\nidentifiers.\n\nWe should only produce links that work, meaning the object is reachable via the\npackage's public API.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- p.go --\npackage p\n\ntype E struct {\n\tEmbed int64\n}\n\n// T is in the package scope, and so should be linkable.\ntype T struct{ //@hover(\"T\", \"T\", T)\n\t// Only exported fields should be linkable\n\n\tf int64 //@hover(\"f\", \"f\", f)\n\tF int64 //@hover(\"F\", \"F\", F)\n\n\tE\n\n\t// TODO(rfindley): is the link here correct? It ignores N.\n\tN struct {\n\t\t// Nested fields should also be linkable.\n\t\tNested int64 //@hover(\"Nested\", \"Nested\", Nested)\n\t}\n}\n// M is an exported method, and so should be linkable.\nfunc (T) M() {}\n\n// m is not exported, and so should not be linkable.\nfunc (T) m() {}\n\nvar _ = T.m\n\nfunc _() {\n\tvar t T\n\n\t// Embedded fields should be linkable.\n\t_ = t.Embed //@hover(\"Embed\", \"Embed\", Embed)\n\n\t// Local variables should not be linkable, even if they are capitalized.\n\tvar X int64 //@hover(\"X\", \"X\", X)\n\t_ = X\n\n\t// Local types should not be linkable, even if they are capitalized.\n\ttype Local struct { //@hover(\"Local\", \"Local\", Local)\n\t\tE\n\t}\n\n\t// But the embedded field should still be linkable.\n\tvar l Local\n\t_ = l.Embed //@hover(\"Embed\", \"Embed\", Embed)\n}\n-- @Embed --\n```go\nfield Embed int64 // through E\n```\n\n---\n\n[`(p.E).Embed` on pkg.go.dev](https://pkg.go.dev/mod.com#E.Embed)\n-- @F --\n```go\nfield F int64 // size=8, offset=8\n```\n\n---\n\n@hover(\"F\", \"F\", F)\n\n\n---\n\n[`(p.T).F` on pkg.go.dev](https://pkg.go.dev/mod.com#T.F)\n-- @Local --\n```go\ntype Local struct { // size=8\n\tE\n}\n```\n\n---\n\nLocal types should not be linkable, even if they are capitalized.\n\n\n```go\n// Embedded fields:\nEmbed int64 // through E \n```\n-- @Nested --\n```go\nfield Nested int64 // size=8, offset=0\n```\n\n---\n\nNested fields should also be linkable.\n-- @T --\n```go\ntype T struct { // size=32 (0x20)\n\tf int64 //@hover(\"f\", \"f\", f)\n\tF int64 //@hover(\"F\", \"F\", F)\n\n\tE\n\n\t// TODO(rfindley): is the link here correct? It ignores N.\n\tN struct {\n\t\t// Nested fields should also be linkable.\n\t\tNested int64 //@hover(\"Nested\", \"Nested\", Nested)\n\t}\n}\n```\n\n---\n\nT is in the package scope, and so should be linkable.\n\n\n```go\n// Embedded fields:\nEmbed int64 // through E \n```\n\n```go\nfunc (T) M()\nfunc (T) m()\n```\n\n---\n\n[`p.T` on pkg.go.dev](https://pkg.go.dev/mod.com#T)\n-- @X --\n```go\nvar X int64\n```\n\n---\n\nLocal variables should not be linkable, even if they are capitalized.\n-- @f --\n```go\nfield f int64 // size=8, offset=0\n```\n\n---\n\n@hover(\"f\", \"f\", f)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/linkable_generics.txt",
    "content": "This file contains tests for documentation links to generic code in hover.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n\n-- a.go --\npackage a\n\nimport \"mod.com/generic\"\n\nfunc _() {\n\t// Hovering over instantiated object should produce accurate type\n\t// information, but link to the generic declarations.\n\n\tvar x generic.GT[int] //@hover(\"GT\", \"GT\", xGT)\n\t_ = x.F //@hover(\"x\", \"x\", x),hover(\"F\", \"F\", xF)\n\n\tf := generic.GF[int] //@hover(\"GF\", \"GF\", fGF)\n\t_ = f //@hover(\"f\", \"f\", f)\n}\n\n-- generic/generic.go --\npackage generic\n\n// Hovering over type parameters should link to documentation.\n//\n// TODO(rfindley): should it? We should probably link to the type.\ntype GT[P any] struct{ //@hover(\"GT\", \"GT\", GT),hover(\"P\", \"P\", GTP)\n\tF P //@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n}\n\nfunc (GT[P]) M(p P) { //@hover(\"GT\", \"GT\", GTrecv),hover(\"M\",\"M\", M),hover(re\"p (P)\", re\"p (P)\", pP)\n}\n\nfunc GF[P any] (p P) { //@hover(\"GF\", \"GF\", GF)\n}\n\n-- @F --\n```go\nfield F P\n```\n\n---\n\n@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n\n\n---\n\n[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)\n-- @FP --\n```go\ntype parameter P any\n```\n-- @GF --\n```go\nfunc GF[P any](p P)\n```\n\n---\n\n[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)\n-- @GT --\n```go\ntype GT[P any] struct {\n\tF P //@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n}\n```\n\n---\n\nHovering over type parameters should link to documentation.\n\nTODO(rfindley): should it? We should probably link to the type.\n\n\n```go\nfunc (GT[P]) M(p P)\n```\n\n---\n\n[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)\n-- @GTP --\n```go\ntype parameter P any\n```\n-- @GTrecv --\n```go\ntype GT[P any] struct {\n\tF P //@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n}\n```\n\n---\n\nHovering over type parameters should link to documentation.\n\nTODO(rfindley): should it? We should probably link to the type.\n\n\n```go\nfunc (GT[P]) M(p P)\n```\n\n---\n\n[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)\n-- @M --\n```go\nfunc (GT[P]) M(p P)\n```\n\n---\n\n[`(generic.GT).M` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.M)\n-- @f --\n```go\nvar f func(p int)\n```\n-- @fGF --\n```go\nfunc generic.GF(p int) // func[P any](p P)\n```\n\n---\n\n[`generic.GF` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GF)\n-- @pP --\n```go\ntype parameter P any\n```\n-- @x --\n```go\nvar x generic.GT[int]\n```\n\n---\n\n@hover(\"GT\", \"GT\", xGT)\n-- @xF --\n```go\nfield F int\n```\n\n---\n\n@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n\n\n---\n\n[`(generic.GT).F` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT.F)\n-- @xGT --\n```go\ntype GT[P any] struct {\n\tF P //@hover(\"F\", \"F\", F),hover(\"P\", \"P\", FP)\n}\n```\n\n---\n\nHovering over type parameters should link to documentation.\n\nTODO(rfindley): should it? We should probably link to the type.\n\n\n```go\nfunc (generic.GT[P]) M(p P)\n```\n\n---\n\n[`generic.GT` on pkg.go.dev](https://pkg.go.dev/mod.com/generic#GT)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/linkname.txt",
    "content": "This test check hover on the 2nd argument in go:linkname directives.\n\n-- go.mod --\nmodule mod.com\n\n-- upper/upper.go --\npackage upper\n\nimport (\n\t_ \"unsafe\"\n\t_ \"mod.com/lower\"\n)\n\n//go:linkname foo mod.com/lower.bar //@hover(\"mod.com/lower.bar\", \"mod.com/lower.bar\", bar)\nfunc foo() string\n\n-- lower/lower.go --\npackage lower\n\n// bar does foo.\nfunc bar() string {\n\treturn \"foo by bar\"\n}\n\nvar _ = bar\n\n-- @bar --\n```go\nfunc bar() string\n```\n\n---\n\nbar does foo.\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/methods.txt",
    "content": "This test checks the formatting of the list of accessible methods.\n\nObserve that:\n- interface methods that appear in the syntax are not repeated\n  in the method set of the type;\n- promoted methods of structs are shown;\n- receiver variables are correctly named;\n- receiver variables have a pointer type if appropriate;\n- only accessible methods are shown.\n\n-- go.mod --\nmodule example.com\n\n-- lib/lib.go --\npackage lib\n\ntype I interface {\n\tA()\n\tb()\n\tJ\n}\n\ntype J interface { C() }\n\ntype S struct { I }\nfunc (s S) A() {}\nfunc (s S) b() {}\nfunc (s *S) PA() {}\nfunc (s *S) pb() {}\n\nvar _ = (*S).pb\n\n-- a/a.go --\npackage a\n\nimport \"example.com/lib\"\n\nvar _ lib.I //@hover(\"I\", \"I\", I)\nvar _ lib.J //@hover(\"J\", \"J\", J)\nvar _ lib.S //@hover(\"S\", \"S\", S)\n\n-- @I --\n```go\ntype I interface {\n\tA()\n\tb()\n\tJ\n}\n```\n\n---\n\n```go\nfunc (lib.J) C()\n```\n\n---\n\n[`lib.I` on pkg.go.dev](https://pkg.go.dev/example.com/lib#I)\n-- @J --\n```go\ntype J interface{ C() }\n```\n\n---\n\n[`lib.J` on pkg.go.dev](https://pkg.go.dev/example.com/lib#J)\n-- @S --\n```go\ntype S struct{ I }\n```\n\n---\n\n```go\nfunc (s lib.S) A()\nfunc (lib.J) C()\nfunc (s *lib.S) PA()\n```\n\n---\n\n[`lib.S` on pkg.go.dev](https://pkg.go.dev/example.com/lib#S)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/pointerdoclink.txt",
    "content": "This test verifies the fix for golang/go#77329.\nDoc links to pointer types should be formatted correctly.\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\ntype Foo int\n\ntype Baz string\n\n// Bar is a [*Foo]\nvar Bar *Foo //@hover(\"Bar\", \"Bar\", Bar)\n\n// Buzz is a [*Baz] with trailing space\nvar Buzz *Baz //@hover(\"Buzz\", \"Buzz\", Buzz)\n\n-- @Bar --\n```go\nvar Bar *Foo\n```\n\n---\n\nBar is a [\\*Foo](file://$WORKDIR/a/a.go#3,6)\n\n\n---\n\n[`a.Bar` on pkg.go.dev](https://pkg.go.dev/example.com/a#Bar)\n-- @Buzz --\n```go\nvar Buzz *Baz\n```\n\n---\n\nBuzz is a [\\*Baz](file://$WORKDIR/a/a.go#5,6) with trailing space\n\n\n---\n\n[`a.Buzz` on pkg.go.dev](https://pkg.go.dev/example.com/a#Buzz)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/return.txt",
    "content": "This test checks that hovering over a return statement reveals the result type.\n\n-- a.go --\npackage a\n\nfunc _() int {\n    return 1 //@hover(\"return\", \"return 1\", \"returns (int)\")\n}\n\nfunc _() (int, int) {\n    return 1, 2 //@hover(\"return\", \"return 1, 2\", \"returns (int, int)\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/sizeoffset.txt",
    "content": "This test checks that hover reports the sizes of vars/types,\nand the offsets of struct fields.\n\nNotes:\n- this only works on the declaring identifier, not on refs.\n- the size of a type is undefined if it depends on type parameters.\n- the offset of a field is undefined if it or any preceding field\n  has undefined size/alignment.\n- the test's size expectations assumes a 64-bit machine.\n- requires go1.22 because size information was inaccurate before.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- flags --\n-skip_goarch=386,arm\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n-- a.go --\npackage a\n\ntype T struct {         //@ hover(\"T\", \"T\", T)\n\ta int\t\t//@ hover(\"a\", \"a\", a)\n\tU U\t\t//@ hover(\"U\", \"U\", U)\n\ty, z int\t//@ hover(\"y\", \"y\", y), hover(\"z\", \"z\", z)\n}\n\ntype U struct {\n\tslice []string\n}\n\ntype G[T any] struct {\n\tp T\t\t//@ hover(\"p\", \"p\", p)\n\tq int\t\t//@ hover(\"q\", \"q\", q)\n}\n\nvar _ struct {\n\tGint    G[int]    //@ hover(\"Gint\",    \"Gint\",    Gint)\n\tGstring G[string] //@ hover(\"Gstring\", \"Gstring\", Gstring)\n}\n\ntype wasteful struct { //@ hover(\"wasteful\", \"wasteful\", wasteful)\n\ta bool\n\tb [2]string\n\tc bool\n}\n\ntype sizeclass struct { //@ hover(\"sizeclass\", \"sizeclass\", sizeclass)\n\ta [5]*int\n}\n\n-- @T --\n```go\ntype T struct { // size=48 (0x30)\n\ta    int //@ hover(\"a\", \"a\", a)\n\tU    U   //@ hover(\"U\", \"U\", U)\n\ty, z int //@ hover(\"y\", \"y\", y), hover(\"z\", \"z\", z)\n}\n```\n\n---\n\n[`a.T` on pkg.go.dev](https://pkg.go.dev/example.com#T)\n-- @wasteful --\n```go\ntype wasteful struct { // size=48 (0x30) (29% wasted)\n\ta bool\n\tb [2]string\n\tc bool\n}\n```\n-- @sizeclass --\n```go\ntype sizeclass struct { // size=40 (0x28), class=48 (0x30)\n\ta [5]*int\n}\n```\n-- @a --\n```go\nfield a int // size=8, offset=0\n```\n\n---\n\n@ hover(\"a\", \"a\", a)\n-- @U --\n```go\nfield U U // size=24 (0x18), offset=8\n```\n\n---\n\n@ hover(\"U\", \"U\", U)\n\n\n---\n\n[`(a.T).U` on pkg.go.dev](https://pkg.go.dev/example.com#T.U)\n-- @y --\n```go\nfield y int // size=8, offset=32 (0x20)\n```\n\n---\n\n@ hover(\"y\", \"y\", y), hover(\"z\", \"z\", z)\n-- @z --\n```go\nfield z int // size=8, offset=40 (0x28)\n```\n\n---\n\n@ hover(\"y\", \"y\", y), hover(\"z\", \"z\", z)\n-- @p --\n```go\nfield p T\n```\n\n---\n\n@ hover(\"p\", \"p\", p)\n-- @q --\n```go\nfield q int // size=8\n```\n\n---\n\n@ hover(\"q\", \"q\", q)\n-- @Gint --\n```go\nfield Gint G[int] // size=16 (0x10), offset=0\n```\n\n---\n\n@ hover(\"Gint\",    \"Gint\",    Gint)\n-- @Gstring --\n```go\nfield Gstring G[string] // size=24 (0x18), offset=16 (0x10)\n```\n\n---\n\n@ hover(\"Gstring\", \"Gstring\", Gstring)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/std.txt",
    "content": "This test checks hover results for built-in or standard library symbols.\n\nIt uses synopsis documentation as full documentation for some of these\nbuilt-ins varies across Go versions, where as it just so happens that the\nsynopsis does not.\n\nIn the future we may need to limit this test to the latest Go version to avoid\ndocumentation churn.\n\n-- settings.json --\n{\n\t\"hoverKind\": \"SynopsisDocumentation\"\n}\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n\n-- std.go --\npackage std\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"sync\"\n)\n\nfunc _() {\n\tvar err error         //@loc(err, \"err\")\n\tfmt.Printf(\"%v\", err) //@def(\"err\", err)\n\n\tvar _ string       //@hover(\"string\", \"string\", hoverstring)\n\t_ = make([]int, 0) //@hover(\"make\", \"make\", hovermake)\n\n\tvar mu sync.Mutex\n\tmu.Lock() //@hover(\"Lock\", \"Lock\", hoverLock)\n\n\tvar typ *types.Named //@hover(\"types\", \"types\", hoverTypes)\n\ttyp.Obj().Name()     //@hover(\"Name\", \"Name\", hoverName)\n}\n-- @hoverLock --\n```go\nfunc (m *sync.Mutex) Lock()\n```\n\n---\n\nLock locks m.\n\n\n---\n\n[`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync#Mutex.Lock)\n-- @hoverName --\n```go\nfunc (obj *types.object) Name() string\n```\n\n---\n\nName returns the object's (package-local, unqualified) name.\n\n\n---\n\n[`(types.TypeName).Name` on pkg.go.dev](https://pkg.go.dev/go/types#TypeName.Name)\n-- @hoverTypes --\n```go\npackage types\n```\n\n---\n\nPackage types declares the data types and implements the algorithms for type-checking of Go packages.\n\n\n---\n\n[`types` on pkg.go.dev](https://pkg.go.dev/go/types)\n-- @hovermake --\n```go\nfunc make(t Type, size ...int) Type\n```\n\n---\n\nThe make built-in function allocates and initializes an object of type slice, map, or chan (only).\n\n\n---\n\n[`make` on pkg.go.dev](https://pkg.go.dev/builtin#make)\n-- @hoverstring --\n```go\ntype string string\n```\n\n---\n\nstring is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text.\n\n\n---\n\n[`string` on pkg.go.dev](https://pkg.go.dev/builtin#string)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/hover/structfield.txt",
    "content": "This test checks that the complete struct field is\nshown on hover (including struct tags and comments).\n\n-- go.mod --\nmodule example.com\n\n-- lib/lib.go --\npackage lib\n\ntype Something struct {\n    // Field with a tag\n    Field int `json:\"field\"`\n}\n\nfunc DoSomething() Something {\n    var s Something\n    s.Field = 42  //@hover(\"i\", \"Field\", field)\n    return s\n}\n\n-- @field --\n```go\nfield Field int `json:\"field\"`\n```\n\n---\n\nField with a tag\n\n\n---\n\n[`(lib.Something).Field` on pkg.go.dev](https://pkg.go.dev/example.com/lib#Something.Field)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/basic.txt",
    "content": "Basic test of implementation query.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- implementation/implementation.go --\npackage implementation\n\nimport \"example.com/other\"\n\ntype ImpP struct{} //@loc(ImpP, \"ImpP\"),implementation(\"ImpP\", Laugher, OtherLaugher)\n\nfunc (*ImpP) Laugh() { //@loc(LaughP, \"Laugh\"),implementation(\"Laugh\", Laugh, OtherLaugh)\n}\n\ntype ImpS struct{} //@loc(ImpS, \"ImpS\"),implementation(\"ImpS\", Laugher, OtherLaugher)\n\nfunc (ImpS) Laugh() { //@loc(LaughS, \"Laugh\"),implementation(\"Laugh\", Laugh, OtherLaugh)\n}\n\ntype Laugher interface { //@loc(Laugher, \"Laugher\"),implementation(\"Laugher\", ImpP, OtherImpP, ImpS, OtherLaugher, OtherImpS, EmbedsImpP)\n\tLaugh() //@loc(Laugh, \"Laugh\"),implementation(\"Laugh\", LaughP, OtherLaughP, LaughS, OtherLaugh, OtherLaughS)\n}\n\ntype Foo struct { //@implementation(\"Foo\", Joker)\n\tother.Foo\n}\n\ntype Joker interface { //@loc(Joker, \"Joker\")\n\tJoke() //@loc(Joke, \"Joke\"),implementation(\"Joke\", ImpJoker)\n}\n\ntype cryer int //@implementation(\"cryer\", Cryer)\n\nfunc (cryer) Cry(other.CryType) {} //@loc(CryImpl, \"Cry\"),implementation(\"Cry\", Cry)\n\ntype Empty any //@implementation(\"Empty\")\n\nvar _ interface{ Joke() } //@implementation(\"Joke\", Joke, ImpJoker)\n\ntype EmbedsImpP struct { //@loc(EmbedsImpP, \"EmbedsImpP\")\n\tImpP //@implementation(\"ImpP\", Laugher, OtherLaugher)\n}\n\nvar _ error //@defloc(StdError, \"error\")\n\ntype MyError struct {} //@implementation(\"MyError\", StdError)\n\nfunc (MyError) Error() string { return \"bah\" }\n\n-- other/other.go --\npackage other\n\ntype ImpP struct{} //@loc(OtherImpP, \"ImpP\")\n\nfunc (*ImpP) Laugh() { //@loc(OtherLaughP, \"Laugh\")\n}\n\ntype ImpS struct{} //@loc(OtherImpS, \"ImpS\")\n\nfunc (ImpS) Laugh() { //@loc(OtherLaughS, \"Laugh\")\n}\n\ntype ImpI interface { //@loc(OtherLaugher, \"ImpI\")\n\tLaugh() //@loc(OtherLaugh, \"Laugh\")\n}\n\ntype Foo struct { //@implementation(\"Foo\", Joker)\n}\n\nfunc (Foo) Joke() { //@loc(ImpJoker, \"Joke\"),implementation(\"Joke\", Joke)\n}\n\ntype CryType int\n\ntype Cryer interface { //@loc(Cryer, \"Cryer\")\n\tCry(CryType) //@loc(Cry, \"Cry\"),implementation(\"Cry\", CryImpl)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/generics-basicalias.txt",
    "content": "Test of special case of 'implementation' query: aliases of basic types\n(rune vs int32) in the \"tricky\" (=generic) algorithm for unifying\nmethod signatures.\n\nWe test both the local (intra-package) and global (cross-package)\nalgorithms.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype C[T any] struct{}\nfunc (C[T]) F(rune, T) {} //@ loc(aCF, \"F\"), implementation(\"F\", aIF, bIF)\n\ntype I[T any] interface{ F(int32, T) } //@ loc(aIF, \"F\"), implementation(\"F\", aCF, bCF, bIF)\n\n-- b/b.go --\npackage b\n\ntype C[T any] struct{}\nfunc (C[T]) F(rune, T) {} //@ loc(bCF, \"F\"), implementation(\"F\", aIF, bIF)\n\ntype I[T any] interface{ F(int32, T) } //@ loc(bIF, \"F\"), implementation(\"F\", aCF, aIF, bCF)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/generics.txt",
    "content": "Test of 'implementation' query on generic types.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- implementation/implementation.go --\npackage implementation\n\ntype GenIface[T any] interface { //@loc(GenIface, \"GenIface\"),implementation(\"GenIface\", GC, GenConc, GI, GIString, GenConcString)\n\tF(int, string, T) //@loc(GenIfaceF, \"F\"),implementation(\"F\", GCF, GenConcF, GIF)\n}\n\ntype GenConc[U any] int //@loc(GenConc, \"GenConc\"),implementation(\"GenConc\", GI, GIString, GenIface)\n\nfunc (GenConc[V]) F(int, string, V) {} //@loc(GenConcF, \"F\"),implementation(\"F\", GIF, GenIfaceF)\n\ntype GenConcString struct{ GenConc[string] } //@loc(GenConcString, \"GenConcString\"),implementation(GenConcString, GIString, GI, GenIface)\n\n-- other/other.go --\npackage other\n\ntype GI[T any] interface { //@loc(GI, \"GI\"),implementation(\"GI\", GenConc, GenIface, GenConcString, GIString, GC)\n\tF(int, string, T) //@loc(GIF, \"F\"),implementation(\"F\", GenIfaceF, GenConcF, GCF)\n}\n\ntype GIString GI[string] //@loc(GIString, \"GIString\"),implementation(\"GIString\", GenConcString, GenIface, GenConc, GI, GC)\n\ntype GC[U any] int //@loc(GC, \"GC\"),implementation(\"GC\", GenIface, GI, GIString)\n\nfunc (GC[V]) F(int, string, V) {} //@loc(GCF, \"F\"),implementation(\"F\", GenIfaceF, GIF)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/issue43655.txt",
    "content": "This test verifies that we fine implementations of the built-in error interface.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- p.go --\npackage p\n\ntype errA struct{ error } //@loc(errA, \"errA\")\n\ntype errB struct{} //@loc(errB, \"errB\")\nfunc (errB) Error() string{ return \"\" } //@loc(errBError, \"Error\")\n\ntype notAnError struct{}\nfunc (notAnError) Error() int { return 0 }\n\nfunc _() {\n\tvar _ error //@implementation(\"error\", errA, errB)\n\tvar a errA\n\t_ = a.Error //@implementation(\"Error\", errBError)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/issue67041.txt",
    "content": "This test verifies that Implementations uses the correct object when querying\nlocal implementations. As described in golang/go#67041, a bug led to it\ncomparing types from different realms.\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A struct{}\n\ntype Aer interface { //@loc(Aer, \"Aer\")\n\tGetA() A\n}\n\ntype X struct{} //@loc(X, \"X\")\n\nfunc (X) GetA() A\n\n-- a/a_test.go --\npackage a\n\n// Verify that we also find implementations in a test variant.\ntype Y struct{} //@loc(Y, \"Y\")\n\nfunc (Y) GetA() A\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nvar _ a.X //@implementation(\"X\", Aer)\n\nvar _ a.Aer //@implementation(\"Aer\", X, Y)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/issue68641.txt",
    "content": "Regression test that Implementation(I) returns J even when I and J are\nboth interfaces; see issue #68641. Previously, interface/interface\nmatches were never reported.\n\nHowever, the direction of the query is determined by the concreteness\nof the query type: Implements on a.B, an interface, reports types that\nare assignable to it, a.C; but Implements on concrete a.impl reports\nonly interface types to which it may be assigned, and there is no way\nto query from interface B to find the (wider) interface A. (This would\nbe a useful feature of LSP though; see\nhttps://github.com/microsoft/language-server-protocol/issues/2037.)\n\nThe test exercises both the local (intra-) and global (cross-package)\nalgorithms and checks that they are consistent.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype A interface { //@ loc(aA, \"A\"), implementation(\"A\", aB, aC, aimpl, bA, bB, bC, bimpl)\n\tA() //@ loc(aAA, \"A\"), implementation(\"A\", aimplA, bimplA, bAA)\n}\n\ntype B interface { //@ loc(aB, \"B\"), implementation(\"B\", aC, aimpl, bB, bC, bimpl)\n\tA\n\tB()\n}\n\ntype C interface { //@ loc(aC, \"C\"), implementation(\"C\", aimpl, bC, bimpl)\n\tB\n\tC()\n}\n\ntype impl int //@ loc(aimpl, \"impl\"), implementation(\"impl\", aA, aB, aC, bA, bB, bC)\n\nfunc (impl) A() //@ loc(aimplA, \"A\")\nfunc (impl) B()\nfunc (impl) C()\n\n-- b/b.go --\npackage b\n\ntype A interface { //@ loc(bA, \"A\"), implementation(\"A\", aA, aB, aC, aimpl, bB, bC, bimpl)\n\tA() //@ loc(bAA, \"A\")\n}\n\ntype B interface { //@ loc(bB, \"B\"), implementation(\"B\", aB, aC, aimpl, bC, bimpl)\n\tA\n\tB()\n}\n\ntype C interface { //@ loc(bC, \"C\"), implementation(\"C\", aC, aimpl, bimpl)\n\tB\n\tC()\n}\n\ntype impl int //@ loc(bimpl, \"impl\"), implementation(\"impl\", aA, aB, aC, bA, bB, bC)\n\nfunc (impl) A() //@ loc(bimplA, \"A\")\nfunc (impl) B()\nfunc (impl) C()\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/issue74305.txt",
    "content": "Regression test for a crash, #74305.\n\n-- go.mod --\nmodule example.com\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nvar _ = undefined() //@ diag(\"undefined\", re\"undefined\"), implementation(\"(\", err=\"not a dynamic function call\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/implementation/signature.txt",
    "content": "Test of local Implementation queries using function signatures.\n\nAssertions:\n- Query on \"func\" of a function type returns the corresponding concrete functions.\n- Query on \"func\" of a concrete function returns corresponding function types.\n- Query on \"(\" of a dynamic function call returns corresponding function types.\n- Different signatures (Nullary vs Handler) don't correspond.\n\nThe @loc markers use the suffixes Func, Type, Call for the three kinds.\nEach query maps between these two sets: {Func} <=> {Type,Call}.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\n// R is short for Record.\ntype R struct{}\n\n// H is short for Handler.\ntype H func(*R) //@ loc(HType, \"func\"), implementation(\"func\", aFunc, bFunc, cFunc)\n\nfunc aFunc(*R) {} //@ loc(aFunc, \"func\"), implementation(\"func\", HType, hParamType, hCall)\n\nvar bFunc = func(*R) {} //@ loc(bFunc, \"func\"), implementation(\"func\", hParamType, hCall, HType)\n\nfunc nullary() { //@ loc(nullaryFunc, \"func\"), implementation(\"func\", Nullary, fieldCall)\n\tcFunc := func(*R) {} //@ loc(cFunc, \"func\"), implementation(\"func\", hParamType, hCall, HType)\n\t_ = cFunc\n}\n\ntype Nullary func() //@ loc(Nullary, \"func\")\n\nfunc _(\n\th func(*R)) { //@ loc(hParamType, \"func\"), implementation(\"func\", aFunc, bFunc, cFunc)\n\n\t_ = aFunc    // pacify unusedfunc\n\t_ = bFunc    // pacify unusedfunc\n\t_ = nullary  // pacify unusedfunc\n\t_ = h\n\n\th(nil) //@ loc(hCall, \"(\"), implementation(\"(\", aFunc, bFunc, cFunc)\n}\n\n// generics:\n\nfunc _[T any](complex128) {\n\tf1 := func(T)      int { return 0 } //@ loc(f1Func, \"func\"), implementation(\"func\", fParamType, fCall, f1Call, f2Call)\n\tf2 := func(string) int { return 0 } //@ loc(f2Func, \"func\"), implementation(\"func\", fParamType, fCall, f1Call, f2Call)\n\tf3 := func(int)    int { return 0 } //@ loc(f3Func, \"func\"), implementation(\"func\", f1Call)\n\n\tf1(*new(T)) //@ loc(f1Call, \"(\"), implementation(\"(\", f1Func, f2Func, f3Func, f4Func)\n\tf2(\"\")      //@ loc(f2Call, \"(\"), implementation(\"(\", f1Func, f2Func, f4Func)\n\t_ = f3      // not called\n}\n\nfunc f4[T any](T) int { return 0 } //@ loc(f4Func, \"func\"), implementation(\"func\", fParamType, fCall, f1Call, f2Call)\n\nvar _ = f4[string] // pacify unusedfunc\n\nfunc _(\n\tf func(string) int, //@ loc(fParamType, \"func\"), implementation(\"func\", f1Func, f2Func, f4Func)\n\terr error) {\n\n\tf(\"\") //@ loc(fCall, \"(\"), implementation(\"(\", f1Func, f2Func, f4Func)\n\n\tstruct{x Nullary}{}.x() //@ loc(fieldCall, \"(\"), implementation(\"(\", nullaryFunc)\n\n\t// Calls that are not dynamic function calls:\n\t_ = len(\"\")          //@ implementation(\"(\", err=\"not a dynamic function call\")\n\t_ = int(0)           //@ implementation(\"(\", err=\"not a dynamic function call\")\n\t_ = error.Error(nil) //@ implementation(\"(\", err=\"not a dynamic function call\")\n\t_ = err.Error()      //@ implementation(\"(\", err=\"not a dynamic function call\")\n\t_ = f4(0)            //@ implementation(\"(\", err=\"not a dynamic function call\"), loc(f4Call, \"(\")\n}\n\n\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/inlayhints/ignored-error.txt",
    "content": "Test of \"ignore error\" inlay hint (#73930).\n\n- f.Close() generates a hint, except when followed by\n  an \"// ignore error\" comment, or in a \"_ = f.Close()\" stmt.\n- fmt.Println() is exempted.\n\n-- settings.json --\n{\"hints\": {\"ignoredError\": true}}\n\n-- p/p.go --\npackage p //@inlayhints(out)\n\nimport ( \"os\"; \"fmt\" )\n\nfunc _(f *os.File) {\n\tf.WriteString(\"hello\")\n\tf.Close()\n}\n\nfunc _(f *os.File) {\n\tf.Close() // irrelevant comment\n}\n\nfunc _(f *os.File) {\n\tf.Close() // ignore error\n}\n\nfunc _(f *os.File) {\n\t_ = f.Close()\n}\n\nfunc _() {\n\tfmt.Println()\n}\n\nfunc _(f *os.File) {\n\t// Allow horizontal space before comment.\n\tnew(os.File).Close() // ignore error\n\tf.Close()            // ignore error\n}\n\n-- @out --\npackage p //@inlayhints(out)\n\nimport ( \"os\"; \"fmt\" )\n\nfunc _(f *os.File) {\n\tf.WriteString(\"hello\")< // ignore error>\n\tf.Close()< // ignore error>\n}\n\nfunc _(f *os.File) {\n\tf.Close()< // ignore error> // irrelevant comment\n}\n\nfunc _(f *os.File) {\n\tf.Close() // ignore error\n}\n\nfunc _(f *os.File) {\n\t_ = f.Close()\n}\n\nfunc _() {\n\tfmt.Println()\n}\n\nfunc _(f *os.File) {\n\t// Allow horizontal space before comment.\n\tnew(os.File).Close() // ignore error\n\tf.Close()            // ignore error\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/inlayhints/inlayhints.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"hints\": {\n\t\t\"assignVariableTypes\": true,\n\t\t\"compositeLiteralFields\": true,\n\t\t\"compositeLiteralTypes\": true,\n\t\t\"constantValues\": true,\n\t\t\"functionTypeParameters\": true,\n\t\t\"parameterNames\": true,\n\t\t\"rangeVariabletypes\": true\n\t}\n}\n\n-- composite_literals.go --\npackage inlayHint //@inlayhints(complit)\n\nimport \"fmt\"\n\nfunc fieldNames() {\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\tstruct{ in, want string }{\"Hello, world\", \"dlrow ,olleH\"},\n\t\t{\"Hello, 世界\", \"界世 ,olleH\"},\n\t\t{\"\", \"\"},\n\t} {\n\t\tfmt.Println(c.in == c.want)\n\t}\n}\n\nfunc fieldNamesPointers() {\n\tfor _, c := range []*struct {\n\t\tin, want string\n\t}{\n\t\t&struct{ in, want string }{\"Hello, world\", \"dlrow ,olleH\"},\n\t\t{\"Hello, 世界\", \"界世 ,olleH\"},\n\t\t{\"\", \"\"},\n\t} {\n\t\tfmt.Println(c.in == c.want)\n\t}\n}\n\n-- @complit --\npackage inlayHint //@inlayhints(complit)\n\nimport \"fmt\"\n\nfunc fieldNames() {\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\tstruct{ in, want string }{<in: >\"Hello, world\", <want: >\"dlrow ,olleH\"},\n\t\t<struct{in string; want string}>{<in: >\"Hello, 世界\", <want: >\"界世 ,olleH\"},\n\t\t<struct{in string; want string}>{<in: >\"\", <want: >\"\"},\n\t} {\n\t\tfmt.Println(<a...: >c.in == c.want)\n\t}\n}\n\nfunc fieldNamesPointers() {\n\tfor _, c := range []*struct {\n\t\tin, want string\n\t}{\n\t\t&struct{ in, want string }{<in: >\"Hello, world\", <want: >\"dlrow ,olleH\"},\n\t\t<&struct{in string; want string}>{<in: >\"Hello, 世界\", <want: >\"界世 ,olleH\"},\n\t\t<&struct{in string; want string}>{<in: >\"\", <want: >\"\"},\n\t} {\n\t\tfmt.Println(<a...: >c.in == c.want)\n\t}\n}\n\n-- constant_values.go --\npackage inlayHint //@inlayhints(values)\n\nconst True = true\n\ntype Kind int\n\nconst (\n\tKindNone Kind = iota\n\tKindPrint\n\tKindPrintf\n\tKindErrorf\n)\n\nconst (\n\tu         = iota * 4\n\tv float64 = iota * 42\n\tw         = iota * 42\n)\n\nconst (\n\ta, b = 1, 2\n\tc, d\n\te, f = 5 * 5, \"hello\" + \"world\"\n\tg, h\n\ti, j = true, f\n)\n\n// No hint\nconst (\n\tInt     = 3\n\tFloat   = 3.14\n\tBool    = true\n\tRune    = '3'\n\tComplex = 2.7i\n\tString  = \"Hello, world!\"\n)\n\nvar (\n\tvarInt     = 3\n\tvarFloat   = 3.14\n\tvarBool    = true\n\tvarRune    = '3' + '4'\n\tvarComplex = 2.7i\n\tvarString  = \"Hello, world!\"\n)\n\n-- @values --\npackage inlayHint //@inlayhints(values)\n\nconst True = true\n\ntype Kind int\n\nconst (\n\tKindNone Kind = iota< = 0>\n\tKindPrint< = 1>\n\tKindPrintf< = 2>\n\tKindErrorf< = 3>\n)\n\nconst (\n\tu         = iota * 4< = 0>\n\tv float64 = iota * 42< = 42>\n\tw         = iota * 42< = 84>\n)\n\nconst (\n\ta, b = 1, 2\n\tc, d< = 1, 2>\n\te, f = 5 * 5, \"hello\" + \"world\"< = 25, \"helloworld\">\n\tg, h< = 25, \"helloworld\">\n\ti, j = true, f< = true, \"helloworld\">\n)\n\n// No hint\nconst (\n\tInt     = 3\n\tFloat   = 3.14\n\tBool    = true\n\tRune    = '3'\n\tComplex = 2.7i\n\tString  = \"Hello, world!\"\n)\n\nvar (\n\tvarInt     = 3\n\tvarFloat   = 3.14\n\tvarBool    = true\n\tvarRune    = '3' + '4'\n\tvarComplex = 2.7i\n\tvarString  = \"Hello, world!\"\n)\n\n-- parameter_names.go --\npackage inlayHint //@inlayhints(parameters)\n\nimport \"fmt\"\n\nfunc hello(name string) string {\n\treturn \"Hello \" + name\n}\n\nfunc helloWorld() string {\n\treturn hello(\"World\")\n}\n\ntype foo struct{}\n\nfunc (*foo) bar(baz string, qux int) int {\n\tif baz != \"\" {\n\t\treturn qux + 1\n\t}\n\treturn qux\n}\n\nfunc kase(foo int, bar bool, baz ...string) {\n\tfmt.Println(foo, bar, baz)\n}\n\nfunc kipp(foo string, bar, baz string) {\n\tfmt.Println(foo, bar, baz)\n}\n\nfunc plex(foo, bar string, baz string) {\n\tfmt.Println(foo, bar, baz)\n}\n\nfunc tars(foo string, bar, baz string) {\n\tfmt.Println(foo, bar, baz)\n}\n\nfunc foobar() {\n\tvar x foo\n\tx.bar(\"\", 1)\n\tkase(0, true, \"c\", \"d\", \"e\")\n\tkipp(\"a\", \"b\", \"c\")\n\tplex(\"a\", \"b\", \"c\")\n\ttars(\"a\", \"b\", \"c\")\n\tfoo, bar, baz := \"a\", \"b\", \"c\"\n\tkipp(foo, bar, baz)\n\tplex(\"a\", bar, baz)\n\ttars(foo+foo, (bar), \"c\")\n\n}\n\n-- @parameters --\npackage inlayHint //@inlayhints(parameters)\n\nimport \"fmt\"\n\nfunc hello(name string) string {\n\treturn \"Hello \" + name\n}\n\nfunc helloWorld() string {\n\treturn hello(<name: >\"World\")\n}\n\ntype foo struct{}\n\nfunc (*foo) bar(baz string, qux int) int {\n\tif baz != \"\" {\n\t\treturn qux + 1\n\t}\n\treturn qux\n}\n\nfunc kase(foo int, bar bool, baz ...string) {\n\tfmt.Println(<a...: >foo, bar, baz)\n}\n\nfunc kipp(foo string, bar, baz string) {\n\tfmt.Println(<a...: >foo, bar, baz)\n}\n\nfunc plex(foo, bar string, baz string) {\n\tfmt.Println(<a...: >foo, bar, baz)\n}\n\nfunc tars(foo string, bar, baz string) {\n\tfmt.Println(<a...: >foo, bar, baz)\n}\n\nfunc foobar() {\n\tvar x foo\n\tx.bar(<baz: >\"\", <qux: >1)\n\tkase(<foo: >0, <bar: >true, <baz...: >\"c\", \"d\", \"e\")\n\tkipp(<foo: >\"a\", <bar: >\"b\", <baz: >\"c\")\n\tplex(<foo: >\"a\", <bar: >\"b\", <baz: >\"c\")\n\ttars(<foo: >\"a\", <bar: >\"b\", <baz: >\"c\")\n\tfoo< string>, bar< string>, baz< string> := \"a\", \"b\", \"c\"\n\tkipp(foo, bar, baz)\n\tplex(<foo: >\"a\", bar, baz)\n\ttars(<foo: >foo+foo, <bar: >(bar), <baz: >\"c\")\n\n}\n\n-- type_params.go --\npackage inlayHint //@inlayhints(typeparams)\n\nfunc main() {\n\tints := map[string]int64{\n\t\t\"first\":  34,\n\t\t\"second\": 12,\n\t}\n\n\tfloats := map[string]float64{\n\t\t\"first\":  35.98,\n\t\t\"second\": 26.99,\n\t}\n\n\tSumIntsOrFloats[string, int64](ints)\n\tSumIntsOrFloats[string, float64](floats)\n\n\tSumIntsOrFloats(ints)\n\tSumIntsOrFloats(floats)\n\n\tSumNumbers(ints)\n\tSumNumbers(floats)\n}\n\ntype Number interface {\n\tint64 | float64\n}\n\nfunc SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {\n\tvar s V\n\tfor _, v := range m {\n\t\ts += v\n\t}\n\treturn s\n}\n\nfunc SumNumbers[K comparable, V Number](m map[K]V) V {\n\tvar s V\n\tfor _, v := range m {\n\t\ts += v\n\t}\n\treturn s\n}\n\n-- @typeparams --\npackage inlayHint //@inlayhints(typeparams)\n\nfunc main() {\n\tints< map[string]int64> := map[string]int64{\n\t\t\"first\":  34,\n\t\t\"second\": 12,\n\t}\n\n\tfloats< map[string]float64> := map[string]float64{\n\t\t\"first\":  35.98,\n\t\t\"second\": 26.99,\n\t}\n\n\tSumIntsOrFloats[string, int64](<m: >ints)\n\tSumIntsOrFloats[string, float64](<m: >floats)\n\n\tSumIntsOrFloats<[string, int64]>(<m: >ints)\n\tSumIntsOrFloats<[string, float64]>(<m: >floats)\n\n\tSumNumbers<[string, int64]>(<m: >ints)\n\tSumNumbers<[string, float64]>(<m: >floats)\n}\n\ntype Number interface {\n\tint64 | float64\n}\n\nfunc SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {\n\tvar s V\n\tfor _, v := range m {\n\t\ts += v\n\t}\n\treturn s\n}\n\nfunc SumNumbers[K comparable, V Number](m map[K]V) V {\n\tvar s V\n\tfor _, v := range m {\n\t\ts += v\n\t}\n\treturn s\n}\n\n-- variable_types.go --\npackage inlayHint //@inlayhints(vartypes)\n\nfunc assignTypes() {\n\tvar x string\n\tvar y = \"\"\n\ti, j := 0, len([]string{})-1\n\tprintln(i, j)\n}\n\nfunc rangeTypes() {\n\tfor k, v := range []string{} {\n\t\tprintln(k, v)\n\t}\n}\n\nfunc funcLitType() {\n\tmyFunc := func(a string) string { return \"\" }\n}\n\nfunc compositeLitType() {\n\tfoo := map[string]any{\"\": \"\"}\n}\n\n-- @vartypes --\npackage inlayHint //@inlayhints(vartypes)\n\nfunc assignTypes() {\n\tvar x string\n\tvar y = \"\"\n\ti< int>, j< int> := 0, len([]string{})-1\n\tprintln(i, j)\n}\n\nfunc rangeTypes() {\n\tfor k, v := range []string{} {\n\t\tprintln(k, v)\n\t}\n}\n\nfunc funcLitType() {\n\tmyFunc< func(a string) string> := func(a string) string { return \"\" }\n}\n\nfunc compositeLitType() {\n\tfoo< map[string]any> := map[string]any{\"\": \"\"}\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/inlayhints/issue67142.txt",
    "content": "Regression test for golang/go#67142.\n\n-- flags --\n-ignore_extra_diags\n\n-- settings.json --\n{\n\t\"hints\": {\n\t\t\"assignVariableTypes\": true,\n\t\t\"compositeLiteralFields\": true,\n\t\t\"compositeLiteralTypes\": true,\n\t\t\"constantValues\": true,\n\t\t\"functionTypeParameters\": true,\n\t\t\"parameterNames\": true,\n\t\t\"rangeVariabletypes\": true\n\t}\n}\n\n-- go.mod --\nmodule w\n\ngo 1.21.9\n\n-- p.go --\n//@inlayhints(out)\npackage p\n\nvar _ = rand.Float64()\n\n-- @out --\n//@inlayhints(out)\npackage p\n\nvar _ = rand.Float64()\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/links/links.txt",
    "content": "This test verifies behavior of textDocument/documentLink.\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n-- foo/foo.go --\npackage foo\n\ntype StructFoo struct {}\n\n-- links/links.go --\npackage links //@documentlink(links)\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/lsptests/foo\"\n\n\t_ \"database/sql\"\n)\n\nvar (\n\t_ fmt.Formatter\n\t_ foo.StructFoo\n\t_ errors.Formatter //@diag(\"errors\", re\"(undeclared|undefined)\")\n)\n\n// Foo function\nfunc Foo() string {\n\t/*https://example.com/comment */\n\n\turl := \"https://example.com/string_literal\"\n\treturn url\n\n\t// TODO(golang/go#1234): Link the relevant issue.\n\t// TODO(microsoft/vscode-go#12): Another issue.\n}\n\n-- @links --\nlinks/links.go:4:3-6 https://pkg.go.dev/fmt\nlinks/links.go:6:3-26 https://pkg.go.dev/golang.org/lsptests/foo\nlinks/links.go:8:5-17 https://pkg.go.dev/database/sql\nlinks/links.go:21:10-44 https://example.com/string_literal\nlinks/links.go:19:4-31 https://example.com/comment\nlinks/links.go:24:10-24 https://github.com/golang/go/issues/1234\nlinks/links.go:25:10-32 https://github.com/microsoft/vscode-go/issues/12\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/context.txt",
    "content": "This test exercises the \"go_context\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- settings.json --\n{\n    \"mcpTools\": {\n        \"go_context\": true\n    }\n}\n\n-- go.mod --\nmodule example.com\n\n-- a/main.go --\n// File doc for main.go part 1.\npackage main\n\n// File doc for main.go part 2.\nimport(\n    \"example.com/a/comment\"\n)\n\n// File doc for main.go part 3.\n\n// doc comment for func foo.\nfunc foo() {//@mcptool(\"go_context\", `{\"file\": \"$WORKDIR/a/main.go\"}`, output=withComment)\n    comment.Foo(\"\", 0)\n}\n\n-- a/a.go --\n// File doc for a.go.\npackage main\n\n// doc comment for func a.\nfunc a () {}\n\n// doc comment for type b.\ntype b struct {}\n\n// doc comment for const c.\nconst c = \"\"\n\n// doc comment for var d.\nvar d int\n\n-- a/comment/doc.go --\n// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage doc for package comment.\n*/\npackage comment\n\n-- a/comment/comment.go --\n// File doc for comment.go part 1.\npackage comment\n\n// File doc for comment.go part 2.\nimport (\n    // comment for package renaming.\n    myfmt \"fmt\"\n)\n\n// File doc for comment.go part 3.\n\n// doc comment for comment.Foo\nfunc Foo(foo string, _ int) {\n    myfmt.Printf(\"%s\", foo)\n}\n\n// Random comment floating around.\n\n-- @withComment --\nCurrent package \"example.com/a\" (package main):\n\nmain.go (current file):\n```go\n// File doc for main.go part 1.\npackage main\n\n// File doc for main.go part 2.\nimport(\n    \"example.com/a/comment\"\n)\n\n// File doc for main.go part 3.\n\n// doc comment for func foo.\nfunc foo()\n\n```\n\na.go:\n```go\n// File doc for a.go.\npackage main\n\n// doc comment for func a.\nfunc a ()\n\n// doc comment for type b.\ntype b struct {}\n// doc comment for const c.\nconst c = \"\"\n// doc comment for var d.\nvar d int\n```\n\nCurrent file \"main.go\" contains this import declaration:\n```go\nimport(\n    \"example.com/a/comment\"\n)\n```\n\nThe imported packages declare the following symbols:\n\n\"example.com/a/comment\" (package comment)\ncomment.go:\n```go\n// File doc for comment.go part 1.\npackage comment\n\n// File doc for comment.go part 2.\nimport (\n    // comment for package renaming.\n    myfmt \"fmt\"\n)\n\n// File doc for comment.go part 3.\n\n// doc comment for comment.Foo\nfunc Foo(foo string, _ int)\n\n```\n\ndoc.go:\n```go\n/*\nPackage doc for package comment.\n*/\npackage comment\n\n```\n\n-- b/main.go --\npackage main\n\nimport(\n    \"example.com/b/function\"\n)\n\nfunc testFunction() {//@mcptool(\"go_context\", `{\"file\":\"$WORKDIR/b/main.go\"}`, output=withFunction)\n    function.Foo(0, \"\")\n}\n\n-- b/function/function.go --\npackage function\n\nfunc Foo(int, string) {}\n\nfunc foo(string, int) {}\n\ntype unexported struct {}\n\nfunc (*unexported) unexported(int) {}\n\nfunc (*unexported) Exported(int) {}\n\ntype Exported struct{}\n\nfunc (*Exported) unexported(int) {}\n\nfunc (*Exported) Exported(int) {}\n\n-- @withFunction --\nCurrent package \"example.com/b\" (package main):\n\nmain.go (current file):\n```go\npackage main\n\nimport(\n    \"example.com/b/function\"\n)\n\nfunc testFunction()\n\n```\n\nCurrent file \"main.go\" contains this import declaration:\n```go\nimport(\n    \"example.com/b/function\"\n)\n```\n\nThe imported packages declare the following symbols:\n\n\"example.com/b/function\" (package function)\nfunction.go:\n```go\npackage function\n\nfunc Foo(int, string)\n\ntype Exported struct{}\n\nfunc (*Exported) Exported(int)\n\n```\n\n-- c/main.go --\npackage main\n\nimport(\n    \"example.com/c/types\"\n)\n\nvar x types.Exported //@mcptool(\"go_context\", `{\"file\":\"$WORKDIR/c/main.go\"}`, output=withType)\n\n-- c/types/types.go --\npackage types\n\n// Doc for exported.\ntype Exported struct {\n    // Doc for exported.\n    Exported string\n    // Doc for unexported.\n    unexported string\n}\n\n// Doc for types.\ntype (\n    // Doc for Foo first line.\n    // Doc for Foo second line.\n    Foo struct {\n        foo string\n    }\n\n    // Doc for foo.\n    foo struct {}\n\n    // Doc for Bar.\n    Bar struct {\n        bar string\n    }\n\n    // Doc for bar.\n    bar struct {}\n)\n\n-- @withType --\nCurrent package \"example.com/c\" (package main):\n\nmain.go (current file):\n```go\npackage main\n\nimport(\n    \"example.com/c/types\"\n)\n\nvar x types.Exported\n```\n\nCurrent file \"main.go\" contains this import declaration:\n```go\nimport(\n    \"example.com/c/types\"\n)\n```\n\nThe imported packages declare the following symbols:\n\n\"example.com/c/types\" (package types)\ntypes.go:\n```go\npackage types\n\n// Doc for exported.\ntype Exported struct {\n    // Doc for exported.\n    Exported string\n    // Doc for unexported.\n    unexported string\n}\n\n// Doc for types.\ntype (\n    // Doc for Foo first line.\n    // Doc for Foo second line.\n    Foo struct {\n        foo string\n    }\n    // Doc for Bar.\n    Bar struct {\n        bar string\n    }\n)\n\n```\n\n-- d/main.go --\npackage main\n\nimport(\n    \"example.com/d/values\"\n)\n\nvar y values.ConstFoo //@mcptool(\"go_context\", `{\"file\":\"$WORKDIR/d/main.go\"}`, output=withValue)\n\n-- d/values/consts.go --\npackage values\n\nconst (\n    // doc for ConstFoo\n    ConstFoo = \"Foo\" // comment for ConstFoo\n    // doc for constFoo\n    constFoo = \"foo\" // comment for constFoo\n    // doc for ConstBar\n    ConstBar = \"Bar\" // comment for ConstBar\n    // doc for constBar\n    constBar = \"bar\" // comment for constBar\n)\n\n// doc for ConstExported\nconst ConstExported = \"Exported\" // comment for ConstExported\n\n// doc for constUnexported\nvar constUnexported = \"unexported\" // comment for constUnexported\n\n-- d/values/vars.go --\npackage values\n\nvar (\n    // doc for VarFoo\n    VarFoo = \"Foo\" // comment for VarFoo\n    // doc for varFoo\n    varFoo = \"foo\" // comment for varFoo\n    // doc for VarBar\n    VarBar = \"Bar\" // comment for VarBar\n    // doc for varBar\n    varBar = \"bar\" // comment for varBar\n)\n\n// doc for VarExported\nvar VarExported = \"Exported\" // comment for VarExported\n\n// doc for varUnexported\nvar varUnexported = \"unexported\" // comment for varUnexported\n\n-- @withValue --\nCurrent package \"example.com/d\" (package main):\n\nmain.go (current file):\n```go\npackage main\n\nimport(\n    \"example.com/d/values\"\n)\n\nvar y values.ConstFoo\n```\n\nCurrent file \"main.go\" contains this import declaration:\n```go\nimport(\n    \"example.com/d/values\"\n)\n```\n\nThe imported packages declare the following symbols:\n\n\"example.com/d/values\" (package values)\nconsts.go:\n```go\npackage values\n\nconst (\n    // doc for ConstFoo\n    ConstFoo = \"Foo\" // comment for ConstFoo\n    // doc for ConstBar\n    ConstBar = \"Bar\" // comment for ConstBar\n)\n\n// doc for ConstExported\nconst ConstExported = \"Exported\" // comment for ConstExported\n\n```\n\nvars.go:\n```go\npackage values\n\nvar (\n    // doc for VarFoo\n    VarFoo = \"Foo\" // comment for VarFoo\n    // doc for VarBar\n    VarBar = \"Bar\" // comment for VarBar\n)\n\n// doc for VarExported\nvar VarExported = \"Exported\" // comment for VarExported\n\n```\n\n-- e/main.go --\npackage main\n\nfunc main() {} //@mcptool(\"go_context\", `{\"file\":\"$WORKDIR/e/main.go\"}`, output=samePackage)\n\n-- e/foo.go --\npackage main\n\nvar (\n    foo string\n    Foo string\n)\n\n-- e/bar.go --\npackage main\n\nconst (\n    bar = \"\"\n    Bar = \"\"\n)\n\n-- e/baz.go --\npackage main\n\nfunc baz(int) string {\n    return \"\"\n}\n\nfunc Baz(string) int {\n    return 0\n}\n\n-- @samePackage --\nCurrent package \"example.com/e\" (package main):\n\nmain.go (current file):\n```go\npackage main\n\nfunc main()\n\n```\n\nbar.go:\n```go\npackage main\n\nconst (\n    bar = \"\"\n    Bar = \"\"\n)\n```\n\nbaz.go:\n```go\npackage main\n\nfunc baz(int) string\n\nfunc Baz(string) int\n\n```\n\nfoo.go:\n```go\npackage main\n\nvar (\n    foo string\n    Foo string\n)\n```\n\n-- f/main.go --\npackage main\n\nimport \"fmt\"\n\nfunc Foo() { //@mcptool(\"go_context\", `{\"file\":\"$WORKDIR/f/main.go\"}`, output=withoutStdLib)\n    fmt.Println(\"foo\")\n}\n\n-- @withoutStdLib --\nCurrent package \"example.com/f\" (package main):\n\nmain.go (current file):\n```go\npackage main\n\nimport \"fmt\"\n\nfunc Foo()\n\n```\n\nCurrent file \"main.go\" contains this import declaration:\n```go\nimport \"fmt\"\n```\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/file_context.txt",
    "content": "This test exercises the \"go_file_context\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\n-- a/main.go --\npackage main\n\nimport \"example.com/a/other\"\n\nfunc main() { //@mcptool(\"go_file_context\", `{\"file\": \"$WORKDIR/a/main.go\"}`, output=content)\n\tother.Foo()\n\t_ = other.Bar\n}\n\n-- a/other/other.go --\npackage other\n\n// Foo should have a doc comment.\nfunc Foo() {\n\t// The body should be ignored\n}\n\nvar Bar int // line comments get dropped\n\nvar Baz string // Baz is not referenced\n\n-- @content --\nFile `$WORKDIR/a/main.go` is in package \"example.com/a\".\nBelow is a summary of the APIs it uses from other files.\nTo read the full API of any package, use go_package_api.\nReferenced declarations from $WORKDIR/a/other/other.go (package \"example.com/a/other\"):\n```go\n// Foo should have a doc comment.\nfunc Foo()\n\nvar Bar int\n```\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/file_diagnostics.txt",
    "content": "This test exercises the \"go_file_diagnostics\" MCP tool.\n\nSome diagnostics from the \"printf\" analyzer carry fixes, and those fixes have edits.\n(Not all fixes have edits; some analyzers rely on gopls to compute them lazily.)\n\nThe printf analyzer only reports a fix in files using >= go1.24.\n\n-- flags --\n-mcp\n-min_go_command=go1.24\n\n-- settings.json --\n{\n    \"mcpTools\": {\n        \"go_file_diagnostics\": true\n    }\n}\n\n-- go.mod --\nmodule example.com\ngo 1.24\n\n-- a/main.go --\npackage main\n\nfunc foo() {} //@loc(foo, \"foo\")\n\n//@mcptool(\"go_file_diagnostics\", `{\"file\":\"$WORKDIR/a/main.go\"}`, output=unused)\n//@diag(foo, re\"unused\")\n-- @unused --\n2:5-2:8: [Information] function \"foo\" is unused\nFix:\n--- $WORKDIR/a/main.go\n+++ $WORKDIR/a/main.go\n@@ -1,6 +1,6 @@\n package main\n \n-func foo() {} //@loc(foo, \"foo\")\n+\n \n //@mcptool(\"go_file_diagnostics\", `{\"file\":\"$WORKDIR/a/main.go\"}`, output=unused)\n //@diag(foo, re\"unused\")\n\n\n-- b/main.go --\npackage main\n\nimport \"fmt\"\n\n// (diagnostic with fix)\nvar (\n\tmsg string\n\t_ = fmt.Sprintf(msg) //@ diag(\"msg\", re\"non-constant format string\")\n)\n\n// (diagnostic without fix)\nvar _ = fmt.Sprintf(\"%d\", \"hello\") //@ diag(\"%d\", re\"%d .* wrong type string\")\n\n//@ mcptool(\"go_file_diagnostics\", `{\"file\":\"$WORKDIR/b/main.go\"}`, output=diagnosePrintf)\n\n-- @diagnosePrintf --\n7:17-7:20: [Warning] non-constant format string in call to fmt.Sprintf\nFix:\n--- $WORKDIR/b/main.go\n+++ $WORKDIR/b/main.go\n@@ -5,7 +5,7 @@\n // (diagnostic with fix)\n var (\n \tmsg string\n-\t_ = fmt.Sprintf(msg) //@ diag(\"msg\", re\"non-constant format string\")\n+\t_ = fmt.Sprintf(\"%s\", msg) //@ diag(\"msg\", re\"non-constant format string\")\n )\n \n // (diagnostic without fix)\n\n\n11:21-11:23: [Warning] fmt.Sprintf format %d has arg \"hello\" of wrong type string\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/file_metadata.txt",
    "content": "This test exercises the \"go_file_metadata\" MCP tool.\n\n-- flags --\n-mcp\n\n-- settings.json --\n{\n    \"mcpTools\": {\n        \"go_file_metadata\": true\n    }\n}\n-- go.mod --\nmodule example.com/cmd\n\ngo 1.21\n\n-- main.go --\npackage main\n\n//@mcptool(\"go_file_metadata\", `{\"file\":\"$WORKDIR/main.go\"}`, output=metadata)\n\nfunc main() {\n\n}\n-- @metadata --\nFile `$WORKDIR/main.go` is in package \"example.com/cmd\", which has the following files:\n\t$WORKDIR/main.go\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/package_api.txt",
    "content": "This test exercises the \"go_package_api\" MCP tool.\n\n-- flags --\n-mcp\n\n-- go.mod --\nmodule example.com/mod\n\n//@mcptool(\"go_package_api\", `{\"packagePaths\":[\"example.com/mod/lib\"]}`, output=outline)\n\ngo 1.21\n\n-- main.go --\npackage main\n\nimport \"example.com/mod/lib\"\n\nfunc main() {\n\tprintln(lib.Foo(0))\n}\n-- lib/lib.go --\npackage lib\n\ntype T int\n\nfunc Foo(int) string {\n\treturn \"\"\n}\n\n-- lib/lib_test.go --\npackage lib\n\nimport \"testing\"\n\nfunc Test(*testing.T) {\n}\n\n-- @outline --\n\"example.com/mod/lib\" (package lib)\nlib.go:\n```go\npackage lib\n\ntype T int\n\nfunc Foo(int) string\n\n```\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/references.txt",
    "content": "This test exercises the \"go_references\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\n-- settings.json --\n{\n    \"mcpTools\": {\n        \"go_references\": true\n    }\n}\n\n-- a/a.go --\npackage a\n\nfunc Foo() {} //@loc(Foo, \"Foo\")\n\nfunc callFoo() {\n    Foo()\n}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc callFoo() {\n    a.Foo()\n}\n\n//@mcptool(\"go_references\", `{}`, location=Foo, output=threeref)\n\n-- @threeref --\nThe object has 3 references. Their locations are listed below\nReference 1\nLocated in the file: $WORKDIR/a/a.go\nThe reference is located on line 2, which has content `func Foo() {} //@loc(Foo, \"Foo\")`\n\nReference 2\nLocated in the file: $WORKDIR/a/a.go\nThe reference is located on line 5, which has content `Foo()`\n\nReference 3\nLocated in the file: $WORKDIR/b/b.go\nThe reference is located on line 5, which has content `a.Foo()`\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/rename_symbol.txt",
    "content": "This test exercises the \"go_rename_symbol\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\n//@mcptool(\"go_rename_symbol\", `{\"file\":\"$WORKDIR/a/a.go\",\"symbol\":\"Foo\", \"new_name\": \"Bar\"}`, output=aFoo)\n//@mcptool(\"go_rename_symbol\", `{\"file\":\"$WORKDIR/a/a.go\",\"symbol\":\"NonExistent\", \"new_name\": \"Bar\"}`, output=aErr)\n\n-- a/a.go --\npackage a\n\nfunc Foo() {}\n\nfunc callFoo() {\n    Foo()\n}\n\n-- @aFoo --\nThe following changes are necessary to rename the symbol:\n--- $WORKDIR/a/a.go\n+++ $WORKDIR/a/a.go\n@@ -1,8 +1,8 @@\n package a\n \n-func Foo() {}\n+func Bar() {}\n \n func callFoo() {\n-    Foo()\n+    Bar()\n }\n \n\n\n-- @aErr --\nfailed to resolve name \"NonExistent\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/search.txt",
    "content": "This test exercises the \"go_search\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n//@mcptool(\"go_search\", `{\"query\": \"foo\"}`, output=foo)\n//@mcptool(\"go_search\", `{\"query\": \"bar\"}`, output=bar)\n//@mcptool(\"go_search\", `{\"query\": \"baz\"}`, output=baz)\n\n-- main.go --\npackage main\n\nimport (\n\t\"example.com/a\"\n\t\"example.com/b\"\n)\n\nfunc FOO() {}\n\ntype baz int\n\nfunc main() {\n\tprintln(a.Foo + b.Ar)\n}\n-- a/a.go --\npackage a\n\nconst (\n\tFoo = 1\n\tBar = 2\n)\n\ntype B struct {\n\tar string\n}\n\n-- b/b.go --\npackage b\n\nconst (\n\taZ = 1\n\tAr = 2\n)\n\nvar fOo = 3\n\n-- @foo --\nTop symbol matches:\n\tFOO (Function in `$WORKDIR/main.go`)\n\tFoo (Constant in `$WORKDIR/a/a.go`)\n\tfOo (Variable in `$WORKDIR/b/b.go`)\n-- @bar --\nTop symbol matches:\n\tBar (Constant in `$WORKDIR/a/a.go`)\n\tb.Ar (Constant in `$WORKDIR/b/b.go`)\n\tB.ar (Field in `$WORKDIR/a/a.go`)\n-- @baz --\nTop symbol matches:\n\tbaz (Type in `$WORKDIR/main.go`)\n\tb.aZ (Constant in `$WORKDIR/b/b.go`)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/symbol_references.txt",
    "content": "This test exercises the \"go_symbol_references\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\n// TODO(rfindley): add error assertions here.\n\n//@mcptool(\"go_symbol_references\", `{\"file\":\"$WORKDIR/a/a.go\",\"symbol\":\"Foo\"}`, output=aFoo)\n//@mcptool(\"go_symbol_references\", `{\"file\":\"$WORKDIR/b/b.go\",\"symbol\":\"a.Foo\"}`, output=aFoo)\n//@mcptool(\"go_symbol_references\", `{\"file\":\"$WORKDIR/a/a.go\",\"symbol\":\"T.Bar\"}`, output=aBar)\n//@mcptool(\"go_symbol_references\", `{\"file\":\"$WORKDIR/b/b.go\",\"symbol\":\"a.T.Bar\"}`, output=aBar)\n\n-- a/a.go --\npackage a\n\nfunc Foo() {}\n\nfunc callFoo() {\n    Foo()\n}\n\ntype T int\n\nfunc (T) Bar() {}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc callFoo() {\n    a.Foo()\n}\n\n-- @aFoo --\nThe object has 3 references. Their locations are listed below\nReference 1\nLocated in the file: $WORKDIR/a/a.go\nThe reference is located on line 2, which has content `func Foo() {}`\n\nReference 2\nLocated in the file: $WORKDIR/a/a.go\nThe reference is located on line 5, which has content `Foo()`\n\nReference 3\nLocated in the file: $WORKDIR/b/b.go\nThe reference is located on line 5, which has content `a.Foo()`\n\n-- @aBar --\nThe object has 1 references. Their locations are listed below\nReference 1\nLocated in the file: $WORKDIR/a/a.go\nThe reference is located on line 10, which has content `func (T) Bar() {}`\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/workspace.txt",
    "content": "This test exercises the \"go_workspace\" MCP tool.\n\n-- flags --\n-mcp\n-min_go_command=go1.23\n\n-- go.work --\ngo 1.23.0\n\n//@mcptool(\"go_workspace\", `{}`, output=workspace)\n\nuse (\n\t./a\n\t./b\n)\n\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.23.0\n\n-- a/a.go --\npackage a\n\n-- b/go.mod --\nmodule example.com/b\n\ngo 1.23.0\n\n-- b/b.go --\npackage b\n\n-- @workspace --\nThe `$WORKDIR` directory is in the go workspace defined by `$WORKDIR/go.work`, with the following main modules:\n\t$WORKDIR/a/go.mod (module example.com/a)\n\t$WORKDIR/b/go.mod (module example.com/b)\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/workspace_diagnostics.txt",
    "content": "This test exercises the \"go_diagnostics\" MCP tool.\n\n-- flags --\n-mcp\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n//@mcptool(\"go_diagnostics\", `{\"files\":[\"$WORKDIR/a/a.go\"]}`, output=diagnostics)\n//@mcptool(\"go_diagnostics\", `{\"files\":[\"$WORKDIR/b/b.go\"]}`, output=diagnostics)\n//@mcptool(\"go_diagnostics\", `{\"files\":[\"$WORKDIR/main.go\"]}`, output=diagnostics)\n\n-- main.go --\npackage main\n\nimport (\n\t\"example.com/a\"\n\t\"example.com/b\"\n)\n\nfunc main() int {\n\ta.Print(b.B)\n\treturn 0\n}\n\n-- a/a.go --\npackage a\n\nfunc Print(x string) {\n\tprintln(x)\n}\n\n-- b/b.go --\npackage b\n\nconst B = 1\n\n-- b/b2.go --\n\nconst B = 2\n\n-- @diagnostics --\nFile `$WORKDIR/b/b2.go` has the following diagnostics:\n1:0-1:0: [Error] expected 'package', found 'const'\n\nFile `$WORKDIR/main.go` has the following diagnostics:\n7:5-7:9: [Error] func main must have no arguments and no return values\n8:9-8:12: [Error] cannot use b.B (untyped int constant 1) as string value in argument to a.Print\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/mcptools/workspace_diagnostics_empty.txt",
    "content": "This test exercises the \"go_diagnostics\" MCP tool.\n\n-- flags --\n-mcp\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n//@mcptool(\"go_diagnostics\", `{\"files\":[\"$WORKDIR/main.go\"]}`, output=diagnostics)\n//@mcptool(\"go_diagnostics\", `{\"files\":[]}`, output=diagnostics)\n//@mcptool(\"go_diagnostics\", `{}`, output=diagnostics)\n\n-- main.go --\npackage main\n\nfunc main() {\n\tprintln(\"Hello world\")\n}\n\n-- @diagnostics --\nNo diagnostics.\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/modfile/godebug.txt",
    "content": "This test basic gopls functionality in a workspace with a godebug\ndirective in its modfile.\n\nWe use panicnil from go1.21 as an arbitrary GODEBUG; if it goes away,\npick another from https://go.dev/doc/godebug#history.\n\n-- flags --\n-min_go_command=go1.23\n\n-- go.mod --\nmodule example.com/m\n\ngo 1.23\n\ngodebug (\n\tpanicnil=0\n)\ngodebug panicnil=1\n\n-- a/a.go --\npackage a\n\nimport \"example.com/m/b\"\n\nconst A = b.B //@def(\"B\", B)\n\n-- b/b.go --\npackage b\n\nconst B = 42 //@loc(B, \"B\")\n\n-- format/go.mod --\nmodule example.com/m/format //@format(formatted)\n\ngodebug (\npanicnil=0\n)\ngodebug      panicnil=1\n-- @formatted --\nmodule example.com/m/format //@format(formatted)\n\ngodebug (\n\tpanicnil=0\n)\n\ngodebug panicnil=1\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/modfile/godebug_bad.txt",
    "content": "This test checks that we surface the error for unexpected godebug values.\n\nTODO(golang/go#67623): the diagnostic should be on the bad godebug value.\n\n-- flags --\n-min_go_command=go1.23\n-errors_ok\n\n-- go.mod --\nmodule example.com/m //@diag(\"module\", re`unknown godebug \"panicnull\"`)\n\ngo 1.23\n\ngodebug (\n\tpanicnull=0 // misspelled\n)\ngodebug panicnil=1\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/embeddirective.txt",
    "content": "This test checks the quick fix to add a missing \"embed\" import.\n\n-- embed.txt --\ntext\n-- fix_import.go --\npackage embeddirective\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n\n//go:embed embed.txt //@quickfix(\"//go:embed\", re`must import \"embed\"`, fix_import)\nvar T string\n\nfunc _() {\n\t_ = os.Stdin\n\t_ = io.EOF\n}\n-- @fix_import/fix_import.go --\n@@ -4 +4 @@\n+\t_ \"embed\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/infertypeargs.txt",
    "content": "This test verifies the infertypeargs refactoring.\n\n-- go.mod --\nmodule mod.test/infertypeargs\n\ngo 1.18\n\n-- p.go --\npackage infertypeargs\n\nfunc app[S interface{ ~[]E }, E any](s S, e E) S {\n\treturn append(s, e)\n}\n\nfunc _() {\n\t_ = app[[]int]\n\t_ = app[[]int, int]\n\t_ = app[[]int]([]int{}, 0) //@quickfix(\"[[]int]\", re\"unnecessary type arguments\", infer)\n\t_ = app([]int{}, 0)\n}\n\n-- @infer/p.go --\n@@ -10 +10 @@\n-\t_ = app[[]int]([]int{}, 0) //@quickfix(\"[[]int]\", re\"unnecessary type arguments\", infer)\n+\t_ = app([]int{}, 0) //@quickfix(\"[[]int]\", re\"unnecessary type arguments\", infer)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/issue65024.txt",
    "content": "Regression example.com for #65024, \"incorrect package qualification when\nstubbing method in v2 module\".\n\nThe second test (a-a) ensures that we don't use path-based heuristics\nto guess the PkgName of an import.\n\n-- a/v2/go.mod --\nmodule example.com/a/v2\ngo 1.18\n\n-- a/v2/a.go --\npackage a\n\ntype I interface { F() T }\n\ntype T struct {}\n\n-- a/v2/b/b.go --\npackage b\n\nimport \"example.com/a/v2\"\n\ntype B struct{}\n\nvar _ a.I = &B{} //@ quickfix(\"&B{}\", re\"does not implement\", out)\n\n// This line makes the diff tidier.\n\n-- @out/a/v2/b/b.go --\n@@ -7 +7,5 @@\n+// F implements [a.I].\n+func (b *B) F() a.T {\n+\tpanic(\"unimplemented\")\n+}\n+\n@@ -10 +15 @@\n-\n-- a-a/v2/go.mod --\n// This module has a hyphenated name--how posh.\n// It won't do to use it as an identifier.\n// The correct name is the one in the package decl,\n// which in this case is not what the path heuristic would guess.\nmodule example.com/a-a/v2\ngo 1.18\n\n-- a-a/v2/a.go --\npackage a\ntype I interface { F() T }\ntype T struct {}\n\n-- a-a/v2/b/b.go --\npackage b\n\n// Note: no existing import of a.\n\ntype B struct{}\n\nvar _ I = &B{} //@ quickfix(\"&B{}\", re\"does not implement\", out2)\n\n// This line makes the diff tidier.\n\n-- a-a/v2/b/import-a-I.go --\npackage b\nimport \"example.com/a-a/v2\"\ntype I = a.I\n\n-- @out2/a-a/v2/b/b.go --\n@@ -3 +3,2 @@\n+import a \"example.com/a-a/v2\"\n+\n@@ -7 +9,5 @@\n+// F implements [a.I].\n+func (b *B) F() a.T {\n+\tpanic(\"unimplemented\")\n+}\n+\n@@ -10 +17 @@\n-\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/noresultvalues.txt",
    "content": "This test checks the quick fix for removing extra return values.\n\nNote: gopls should really discard unnecessary return statements.\n\n-- noresultvalues.go --\npackage typeerrors\n\nfunc x() { return nil } //@quickfix(\"nil\", re\"too many return\", x)\n\nfunc y() { return nil, \"hello\" } //@quickfix(\"nil\", re\"too many return\", y)\n-- @x/noresultvalues.go --\n@@ -3 +3 @@\n-func x() { return nil } //@quickfix(\"nil\", re\"too many return\", x)\n+func x() { return } //@quickfix(\"nil\", re\"too many return\", x)\n-- @y/noresultvalues.go --\n@@ -5 +5 @@\n-func y() { return nil, \"hello\" } //@quickfix(\"nil\", re\"too many return\", y)\n+func y() { return } //@quickfix(\"nil\", re\"too many return\", y)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/self_assignment.txt",
    "content": "Test of the suggested fix to remove unnecessary assignments.\n\n-- a.go --\npackage quickfix\n\nimport (\n\t\"log\"\n)\n\nfunc _() {\n\ts := \"hiiiiiii\"\n\ts = s //@quickfix(\"s = s\", re\"self-assignment\", fix)\n\tlog.Print(s)\n}\n\n-- @fix/a.go --\n@@ -9 +9 @@\n-\ts = s //@quickfix(\"s = s\", re\"self-assignment\", fix)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stub.txt",
    "content": "This test checks the 'implement interface' quick fix.\n\n-- go.mod --\nmodule golang.org/lsptests/stub\n\ngo 1.18\n\n-- other/other.go --\npackage other\n\nimport (\n\t\"bytes\"\n\trenamed_context \"context\"\n)\n\ntype Interface interface {\n\tGet(renamed_context.Context) *bytes.Buffer\n}\n\n-- add_selector.go --\npackage stub\n\nimport \"io\"\n\n// This file tests that if an interface\n// method references a type from its own package\n// then our implementation must add the import/package selector\n// in the concrete method if the concrete type is outside of the interface\n// package\nvar _ io.ReaderFrom = &readerFrom{} //@quickfix(\"&readerFrom\", re\"cannot use\", readerFrom)\n\ntype readerFrom struct{}\n-- @readerFrom/add_selector.go --\n@@ -13 +13,5 @@\n+\n+// ReadFrom implements [io.ReaderFrom].\n+func (*readerFrom) ReadFrom(r io.Reader) (n int64, err error) {\n+\tpanic(\"unimplemented\")\n+}\n-- assign.go --\npackage stub\n\nimport \"io\"\n\nfunc _() {\n\tvar br io.ByteWriter\n\tbr = &byteWriter{} //@quickfix(\"&\", re\"does not implement\", assign)\n\t_ = br\n}\n\ntype byteWriter struct{}\n-- @assign/assign.go --\n@@ -12 +12,5 @@\n+\n+// WriteByte implements [io.ByteWriter].\n+func (b *byteWriter) WriteByte(c byte) error {\n+\tpanic(\"unimplemented\")\n+}\n-- assign_multivars.go --\npackage stub\n\nimport \"io\"\n\nfunc _() {\n\tvar br io.ByteWriter\n\tvar i int\n\ti, br = 1, &multiByteWriter{} //@quickfix(\"&\", re\"does not implement\", assign_multivars)\n\t_, _ = i, br\n}\n\ntype multiByteWriter struct{}\n-- @assign_multivars/assign_multivars.go --\n@@ -13 +13,5 @@\n+\n+// WriteByte implements [io.ByteWriter].\n+func (m *multiByteWriter) WriteByte(c byte) error {\n+\tpanic(\"unimplemented\")\n+}\n-- call_expr.go --\npackage stub\n\nfunc main() {\n\tcheck(&callExpr{}) //@quickfix(\"&\", re\"does not implement\", call_expr)\n}\n\nfunc check(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\ntype callExpr struct{}\n-- @call_expr/call_expr.go --\n@@ -14 +14,5 @@\n+\n+// Error implements [error].\n+func (c *callExpr) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n-- embedded.go --\npackage stub\n\nimport (\n\t\"io\"\n\t\"sort\"\n)\n\nvar _ embeddedInterface = (*embeddedConcrete)(nil) //@quickfix(\"(\", re\"does not implement\", embedded)\n\ntype embeddedConcrete struct{}\n\ntype embeddedInterface interface {\n\tsort.Interface\n\tio.Reader\n}\n-- @embedded/embedded.go --\n@@ -12 +12,20 @@\n+// Len implements [embeddedInterface].\n+func (e *embeddedConcrete) Len() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n+// Less implements [embeddedInterface].\n+func (e *embeddedConcrete) Less(i int, j int) bool {\n+\tpanic(\"unimplemented\")\n+}\n+\n+// Read implements [embeddedInterface].\n+func (e *embeddedConcrete) Read(p []byte) (n int, err error) {\n+\tpanic(\"unimplemented\")\n+}\n+\n+// Swap implements [embeddedInterface].\n+func (e *embeddedConcrete) Swap(i int, j int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- err.go --\npackage stub\n\nfunc _() {\n\tvar br error = &customErr{} //@quickfix(\"&\", re\"does not implement\", err)\n\t_ = br\n}\n\ntype customErr struct{}\n-- @err/err.go --\n@@ -9 +9,5 @@\n+\n+// Error implements [error].\n+func (c *customErr) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n-- function_return.go --\npackage stub\n\nimport (\n\t\"io\"\n)\n\nfunc newCloser() io.Closer {\n\treturn closer{} //@quickfix(\"c\", re\"does not implement\", function_return)\n}\n\ntype closer struct{}\n-- @function_return/function_return.go --\n@@ -12 +12,5 @@\n+\n+// Close implements [io.Closer].\n+func (c closer) Close() error {\n+\tpanic(\"unimplemented\")\n+}\n-- successive_function_return.go --\npackage stub\n\nimport (\n\t\"io\"\n)\n\nfunc _() (a, b int, c io.Closer) {\n\treturn 1, 2, closer2{} //@quickfix(\"c\", re\"does not implement\", successive)\n}\n\ntype closer2 struct{}\n-- @successive/successive_function_return.go --\n@@ -12 +12,5 @@\n+\n+// Close implements [io.Closer].\n+func (c closer2) Close() error {\n+\tpanic(\"unimplemented\")\n+}\n-- generic_receiver.go --\npackage stub\n\nimport \"io\"\n\n// This file tests that the stub method generator accounts for concrete\n// types that have type parameters defined.\nvar _ io.ReaderFrom = &genReader[string, int]{} //@quickfix(\"&genReader\", re\"does not implement\", generic_receiver)\n\ntype genReader[T, Y any] struct {\n\tT T\n\tY Y\n}\n-- @generic_receiver/generic_receiver.go --\n@@ -13 +13,5 @@\n+\n+// ReadFrom implements [io.ReaderFrom].\n+func (g *genReader[T, Y]) ReadFrom(r io.Reader) (n int64, err error) {\n+\tpanic(\"unimplemented\")\n+}\n-- ignored_imports.go --\npackage stub\n\nimport (\n\t\"compress/zlib\"\n\t. \"io\"\n\t_ \"io\"\n)\n\n// This file tests that dot-imports and underscore imports\n// are properly ignored and that a new import is added to\n// reference method types\n\nvar (\n\t_ Reader\n\t_ zlib.Resetter = (*ignoredResetter)(nil) //@quickfix(\"(\", re\"does not implement\", ignored_imports)\n)\n\ntype ignoredResetter struct{}\n-- @ignored_imports/ignored_imports.go --\n@@ -19 +19,5 @@\n+\n+// Reset implements [zlib.Resetter].\n+func (i *ignoredResetter) Reset(r Reader, dict []byte) error {\n+\tpanic(\"unimplemented\")\n+}\n-- issue2606.go --\npackage stub\n\ntype I interface{ error }\n\ntype C int\n\nvar _ I = C(0) //@quickfix(\"C\", re\"does not implement\", issue2606)\n-- @issue2606/issue2606.go --\n@@ -7 +7,5 @@\n+// Error implements [I].\n+func (c C) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- multi_var.go --\npackage stub\n\nimport \"io\"\n\n// This test ensures that a variable declaration that\n// has multiple values on the same line can still be\n// analyzed correctly to target the interface implementation\n// diagnostic.\nvar one, two, three io.Reader = nil, &multiVar{}, nil //@quickfix(\"&\", re\"does not implement\", multi_var)\n\ntype multiVar struct{}\n-- @multi_var/multi_var.go --\n@@ -12 +12,5 @@\n+\n+// Read implements [io.Reader].\n+func (m *multiVar) Read(p []byte) (n int, err error) {\n+\tpanic(\"unimplemented\")\n+}\n-- pointer.go --\npackage stub\n\nimport \"io\"\n\nfunc getReaderFrom() io.ReaderFrom {\n\treturn &pointerImpl{} //@quickfix(\"&\", re\"does not implement\", pointer)\n}\n\ntype pointerImpl struct{}\n-- @pointer/pointer.go --\n@@ -10 +10,5 @@\n+\n+// ReadFrom implements [io.ReaderFrom].\n+func (p *pointerImpl) ReadFrom(r io.Reader) (n int64, err error) {\n+\tpanic(\"unimplemented\")\n+}\n-- renamed_import.go --\npackage stub\n\nimport (\n\t\"compress/zlib\"\n\tmyio \"io\"\n)\n\nvar _ zlib.Resetter = &myIO{} //@quickfix(\"&\", re\"does not implement\", renamed_import)\nvar _ myio.Reader\n\ntype myIO struct{}\n-- @renamed_import/renamed_import.go --\n@@ -12 +12,5 @@\n+\n+// Reset implements [zlib.Resetter].\n+func (m *myIO) Reset(r myio.Reader, dict []byte) error {\n+\tpanic(\"unimplemented\")\n+}\n-- renamed_import_iface.go --\npackage stub\n\nimport (\n\t\"golang.org/lsptests/stub/other\"\n)\n\n// This file tests that if an interface\n// method references an import from its own package\n// that the concrete type does not yet import, and that import happens\n// to be renamed, then we prefer the renaming of the interface.\nvar _ other.Interface = &otherInterfaceImpl{} //@quickfix(\"&otherInterfaceImpl\", re\"does not implement\", renamed_import_iface)\n\ntype otherInterfaceImpl struct{}\n-- @renamed_import_iface/renamed_import_iface.go --\n@@ -4 +4,2 @@\n+\t\"bytes\"\n+\t\"context\"\n@@ -14 +16,5 @@\n+\n+// Get implements [other.Interface].\n+func (o *otherInterfaceImpl) Get(context.Context) *bytes.Buffer {\n+\tpanic(\"unimplemented\")\n+}\n-- stdlib.go --\npackage stub\n\nimport (\n\t\"io\"\n)\n\nvar _ io.Writer = writer{} //@quickfix(\"w\", re\"does not implement\", stdlib)\n\ntype writer struct{}\n-- @stdlib/stdlib.go --\n@@ -10 +10,5 @@\n+\n+// Write implements [io.Writer].\n+func (w writer) Write(p []byte) (n int, err error) {\n+\tpanic(\"unimplemented\")\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/basic.txt",
    "content": "This test exercises basic 'stub methods' functionality.\nSee basic_resolve.txt for the same test with resolve support.\n\n-- capabilities.json --\n{\n\t\"textDocument\": {\n\t\t\"codeAction\": {\n\t\t\t\"dataSupport\": false,\n\t\t\t\"resolveSupport\": {}\n\t\t}\n\t}\n}\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype C int\n\nvar _ error = C(0) //@quickfix(re\"C.0.\", re\"missing method Error\", stub)\n-- @stub/a/a.go --\n@@ -5 +5,5 @@\n+// Error implements [error].\n+func (c C) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/basic_resolve.txt",
    "content": "This test exercises basic 'stub methods' functionality, with resolve support.\nSee basic.txt for the same test without resolve support.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype C int\n\nvar _ error = C(0) //@quickfix(re\"C.0.\", re\"missing method Error\", stub)\n-- @stub/a/a.go --\n@@ -5 +5,5 @@\n+// Error implements [error].\n+func (c C) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/fromcall_basic.txt",
    "content": "This test checks the basic of 'Declare missing method T.f' quick fix.\n\n-- basic_stub.go --\npackage fromcallbasic\n\ntype Basic struct{}\n\nfunc basic() {\n\ti := 1\n\tb := Basic{}\n\tf(b.basic(i)) //@quickfix(\"basic\", re\"has no field or method\", basic)\n}\n\nfunc f(i int) string { return \"s\" }\n-- @basic/basic_stub.go --\n@@ -5 +5,4 @@\n+func (b Basic) basic(i int) int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- pointer.go --\npackage fromcallbasic\n\ntype P struct{}\n\nfunc recv_param_pointer() {\n\tp := &P{}\n\ti := 42\n\tp.pointer(&i) //@quickfix(\"pointer\", re\"has no field or method\", pointer)\n}\n-- @pointer/pointer.go --\n@@ -5 +5,4 @@\n+func (p *P) pointer(i *int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- other.go --\npackage fromcallbasic\n\ntype TypeDeclInOtherFile struct{}\n\n-- this.go --\npackage fromcallbasic\n\nfunc fun() {\n\ti := 1\n\tt := TypeDeclInOtherFile{}\n\tt.other(i) //@quickfix(\"other\", re\"has no field or method\", del_other)\n}\n-- @del_other/other.go --\n@@ -5 +5,3 @@\n+func (t TypeDeclInOtherFile) other(i int) {\n+\tpanic(\"unimplemented\")\n+}\n-- should_insert_after.go --\npackage fromcallbasic\n\ntype HasMethod struct{}\n\nfunc (h *HasMethod) m() {\n\th.should_insert_after() //@quickfix(\"should_insert_after\", re\"has no field or method\", insert)\n}\n-- @insert/should_insert_after.go --\n@@ -8 +8,4 @@\n+\n+func (h *HasMethod) should_insert_after() {\n+\tpanic(\"unimplemented\")\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/fromcall_params.txt",
    "content": "This test checks the param name and type of the generated missing method based on CallExpr.\n\n-- basic_stub.go --\npackage fromcallparams\n\ntype A struct{}\n\nfunc untypedParams() {\n\ta := A{}\n\ta.untyped(\"s\", 42, 4.12, make(map[string]int), []int{1}, [1]int{1}, make(chan string)) //@quickfix(\"untyped\", re\"has no field or method\", basic)\n}\n-- @basic/basic_stub.go --\n@@ -5 +5,4 @@\n+func (a A) untyped(s string, i int, f float64, m map[string]int, param5 []int, param6 [1]int, ch chan string) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- nonexistent_type.go --\npackage fromcallparams\n\ntype B struct{}\n\nfunc invalidBasicKindParam() {\n\tb := B{}\n\tb.basicKind(NonExistentType{}) //@quickfix(\"basicKind\", re\"has no field or method\", nonexistent),diag(re\"NonExistentType\",re\"undefined: NonExistentType\")\n}\n-- @nonexistent/nonexistent_type.go --\n@@ -5 +5,4 @@\n+func (b B) basicKind(param any) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- pass_param_by_ident.go --\npackage fromcallparams\n\ntype C struct{}\n\nfunc passParamByIdent() {\n\tc := C{}\n\tstringVar := \"some string\"\n\tintVar := 1\n\tsliceVar := []int{1}\n\tc.ident(stringVar, intVar, sliceVar) //@quickfix(\"ident\", re\"has no field or method\", ident)\n}\n-- @ident/pass_param_by_ident.go --\n@@ -5 +5,4 @@\n+func (c C) ident(stringVar string, intVar int, sliceVar []int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- tail_param_name.go --\npackage fromcallparams\n\ntype Tail struct{}\n\ntype TypeWithLongName struct{}\n\nfunc TailParamName() {\n\tt := Tail{}\n\tt.longName(TypeWithLongName{}) //@quickfix(\"longName\", re\"has no field or method\", trail)\n}\n-- @trail/tail_param_name.go --\n@@ -5 +5,4 @@\n+func (t Tail) longName(name TypeWithLongName) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- selector_param_name.go --\npackage fromcallparams\n\nimport \"net/http\"\n\ntype Select struct{}\n\nfunc selectExpr() {\n\ts := Select{}\n\ts.sel(http.ErrNotMultipart) //@quickfix(\"sel\", re\"has no field or method\", select)\n}\n-- @select/selector_param_name.go --\n@@ -7 +7,4 @@\n+func (s Select) sel(multipart *http.ProtocolError) {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/fromcall_returns.txt",
    "content": "This test checks the return type of the generated missing method based on CallExpr.\n\n-- param.go --\npackage fromcallreturns\n\ntype A struct{}\n\nfunc inferFromParam() {\n\ta := A{}\n\tf(a.as_param()) //@quickfix(\"as_param\", re\"has no field or method\", infer_param)\n}\n\nfunc f(i int) {}\n-- @infer_param/param.go --\n@@ -5 +5,4 @@\n+func (a A) as_param() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- assign.go --\npackage fromcallreturns\n\ntype Assign struct{}\n\nfunc inferReturnfromAssign() {\n\tvar assign int //@diag(\"assign\",re\"not used\")\n\ta := Assign{}\n\tassign = a.as_assign() //@quickfix(\"as_assign\", re\"has no field or method\", infer_assign)\n}\n-- @infer_assign/assign.go --\n@@ -5 +5,4 @@\n+func (a Assign) as_assign() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- multiple_assign.go --\npackage fromcallreturns\n\ntype MultiAssign struct{}\n\nfunc inferReturnfromMultipleAssign() {\n\tvar assign1 int //@diag(\"assign1\",re\"not used\")\n\tvar assign2 int //@diag(\"assign2\",re\"not used\")\n\tm := MultiAssign{}\n\tassign1, assign2 = m.multi_assign() //@quickfix(\"multi_assign\", re\"has no field or method\", infer_multiple_assign)\n}\n-- @infer_multiple_assign/multiple_assign.go --\n@@ -5 +5,4 @@\n+func (m MultiAssign) multi_assign() (int, int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- multiple_return_in_param.go --\npackage fromcallreturns\n\ntype MultiReturn struct{}\n\nfunc inferMultipleReturnInParam() {\n\tm := MultiReturn{}\n\tm.param_has_multi_return(multiReturn()) //@quickfix(\"param_has_multi_return\", re\"has no field or method\", multiple_return)\n}\n\nfunc multiReturn() (int, int) {\n\treturn 1, 1\n}\n-- @multiple_return/multiple_return_in_param.go --\n@@ -5 +5,4 @@\n+func (m MultiReturn) param_has_multi_return(i int, param2 int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- error_nodes.go --\npackage fromcallreturns\n\ntype E struct{}\n\nfunc all_error() {\n\te := E{}\n\terrorFunc(e.errors(undefined1(), undefined2(), undefined3{})) //@quickfix(\"errors\", re\"has no field or method\", all_error),diag(\"undefined1\",re\"undefined\"),diag(\"undefined2\",re\"undefined\"),diag(\"undefined3\",re\"undefined\")\n}\nfunc errorFunc(u undefined4) {} //@diag(\"undefined4\",re\"undefined\")\n-- @all_error/error_nodes.go --\n@@ -5 +5,4 @@\n+func (e E) errors(param any, param2 any, param3 any) any {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- paren.go --\npackage fromcallreturns\n\ntype Paren struct{}\n\nfunc paren() {\n\tp := Paren{}\n\tfn()((p.surroundingParen())) //@quickfix(\"surroundingParen\", re\"has no field or method\", surrounding_paren)\n}\n\nfunc fn() func(i int) {\n\treturn func(i int) {}\n}\n-- @surrounding_paren/paren.go --\n@@ -5 +5,4 @@\n+func (p Paren) surroundingParen() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- if_stmt.go --\npackage fromcallreturns\n\ntype IfStruct struct{}\n\nfunc testIfStmt() {\n\ti := IfStruct{}\n\tif i.isValid() { //@quickfix(\"isValid\", re\"has no field or method\", infer_if_stmt)\n\t\t// do something\n\t}\n}\n-- @infer_if_stmt/if_stmt.go --\n@@ -5 +5,4 @@\n+func (i IfStruct) isValid() bool {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- for_stmt.go --\npackage fromcallreturns\n\ntype ForStruct struct{}\n\nfunc testForStmt() {\n\tf := ForStruct{}\n\tfor f.hasNext() { //@quickfix(\"hasNext\", re\"has no field or method\", infer_for_stmt1)\n\t\t// do something\n\t}\n\tfor i := 0; f.inside(); i++ { //@quickfix(\"inside\", re\"has no field or method\", infer_for_stmt2)\n\t\t// do something\n\t}\n}\n-- @infer_for_stmt1/for_stmt.go --\n@@ -5 +5,4 @@\n+func (f ForStruct) hasNext() bool {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_for_stmt2/for_stmt.go --\n@@ -5 +5,4 @@\n+func (f ForStruct) inside() bool {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- unary.go --\npackage fromcallreturns\n\ntype Unary struct{}\n\nfunc testUnaryExpr() {\n\tu := Unary{}\n\ta, b, c, d := !u.Boolean(), -u.Minus(), +u.Plus(), ^u.Xor() //@quickfix(\"Boolean\", re\"has no field or method\", infer_unary_expr1),quickfix(\"Minus\", re\"has no field or method\", infer_unary_expr2),quickfix(\"Plus\", re\"has no field or method\", infer_unary_expr3),quickfix(\"Xor\", re\"has no field or method\", infer_unary_expr4)\n\t_, _, _, _ = a, b, c, d\n}\n-- @infer_unary_expr1/unary.go --\n@@ -5 +5,4 @@\n+func (u Unary) Boolean() bool {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_unary_expr2/unary.go --\n@@ -5 +5,4 @@\n+func (u Unary) Minus() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_unary_expr3/unary.go --\n@@ -5 +5,4 @@\n+func (u Unary) Plus() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_unary_expr4/unary.go --\n@@ -5 +5,4 @@\n+func (u Unary) Xor() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- binary.go --\npackage fromcallreturns\n\ntype Binary struct{}\n\nfunc testBinaryExpr() {\n\tb := Binary{}\n\t_ = 1 + b.Num()   //@quickfix(\"Num\", re\"has no field or method\", infer_binary_expr1)\n\t_ = \"s\" + b.Str() //@quickfix(\"Str\", re\"has no field or method\", infer_binary_expr2)\n}\n-- @infer_binary_expr1/binary.go --\n@@ -5 +5,4 @@\n+func (b Binary) Num() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_binary_expr2/binary.go --\n@@ -5 +5,4 @@\n+func (b Binary) Str() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- value.go --\npackage fromcallreturns\n\ntype Value struct{}\n\nfunc v() {\n\tv := Value{}\n\tvar a, b int = v.Multi()     //@quickfix(\"Multi\", re\"has no field or method\", infer_value_expr1)\n\tvar c, d int = 4, v.Single() //@quickfix(\"Single\", re\"has no field or method\", infer_value_expr2)\n\t_, _, _, _ = a, b, c, d\n}\n-- @infer_value_expr1/value.go --\n@@ -5 +5,4 @@\n+func (v Value) Multi() (int, int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_value_expr2/value.go --\n@@ -5 +5,4 @@\n+func (v Value) Single() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- return.go --\npackage fromcallreturns\n\ntype Return struct{}\n\nfunc r() {\n\tr := Return{}\n\t_ = func() (int, int) {\n\t\treturn r.Multi() //@quickfix(\"Multi\", re\"has no field or method\", infer_retrun_expr1)\n\t}\n\t_ = func() string {\n\t\treturn r.Single() //@quickfix(\"Single\", re\"has no field or method\", infer_retrun_expr2)\n\t}\n}\n-- @infer_retrun_expr1/return.go --\n@@ -5 +5,4 @@\n+func (r Return) Multi() (int, int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @infer_retrun_expr2/return.go --\n@@ -5 +5,4 @@\n+func (r Return) Single() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- successive_return.go --\npackage fromcallreturns\n\ntype R struct{}\n\nfunc _() (x int, y, z string, k int64) {\n\tr := R{}\n\t_ = func() (a, b float32, c int) {\n\t\treturn r.Multi() //@quickfix(\"Multi\", re\"has no field or method\", successive1)\n\t}\n\treturn 3, \"\", r.Single(), 6 //@quickfix(\"Single\", re\"has no field or method\", successive2)\n}\n-- @successive1/successive_return.go --\n@@ -5 +5,4 @@\n+func (r R) Multi() (float32, float32, int) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- @successive2/successive_return.go --\n@@ -5 +5,4 @@\n+func (r R) Single() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/issue61693.txt",
    "content": "This test exercises stub methods functionality with variadic parameters.\n\nIn golang/go#61693 stubmethods was panicking in this case.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.18\n-- main.go --\npackage main\n\ntype C int\n\nfunc F(err ...error) {}\n\nfunc _() {\n\tvar x error\n\tF(x, C(0)) //@quickfix(re\"C.0.\", re\"missing method Error\", stub)\n}\n-- @stub/main.go --\n@@ -5 +5,5 @@\n+// Error implements [error].\n+func (c C) Error() string {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/issue61830.txt",
    "content": "This test verifies that method stubbing qualifies types relative to the current\npackage.\n\n-- p.go --\npackage p\n\nimport \"io\"\n\ntype B struct{}\n\ntype I interface {\n\tM(io.Reader, B)\n}\n\ntype A struct{}\n\nvar _ I = &A{} //@quickfix(re\"&A..\", re\"missing method M\", stub)\n-- @stub/p.go --\n@@ -13 +13,5 @@\n+// M implements [I].\n+func (a *A) M(io.Reader, B) {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/issue64078.txt",
    "content": "This test verifies that the named receiver is generated.\n\n-- p.go --\npackage p\n\ntype A struct{}\n\nfunc (aa *A) M1() {\n\tpanic(\"unimplemented\")\n}\n\ntype I interface {\n\tM1()\n\tM2(aa string)\n\tM3(bb string)\n\tM4() (aa string)\n}\n\nvar _ I = &A{} //@quickfix(re\"&A..\", re\"missing method M\", stub)\n-- @stub/p.go --\n@@ -5 +5,15 @@\n+// M2 implements [I].\n+func (*A) M2(aa string) {\n+\tpanic(\"unimplemented\")\n+}\n+\n+// M3 implements [I].\n+func (aa *A) M3(bb string) {\n+\tpanic(\"unimplemented\")\n+}\n+\n+// M4 implements [I].\n+func (*A) M4() (aa string) {\n+\tpanic(\"unimplemented\")\n+}\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/issue64114.txt",
    "content": "This test verifies that the embedded field has a method with the same name.\n\n-- issue64114.go --\npackage stub\n\n// Regression test for issue #64114: code action \"implement\" is not listed.\n\nvar _ WriteTest = (*WriteStruct)(nil) //@quickfix(\"(\", re\"does not implement\", issue64114)\n\ntype WriterTwoStruct struct{}\n\n// Write implements [io.ReadWriter].\nfunc (t *WriterTwoStruct) RRRR(str string) error {\n\tpanic(\"unimplemented\")\n}\n\ntype WriteTest interface {\n\tRRRR()\n\tWWWW()\n}\n\ntype WriteStruct struct {\n\tWriterTwoStruct\n}\n-- @issue64114/issue64114.go --\n@@ -22 +22,5 @@\n+\n+// WWWW implements [WriteTest].\n+func (w *WriteStruct) WWWW() {\n+\tpanic(\"unimplemented\")\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/shadowedmethods.txt",
    "content": "This test exercises verifies that the stubmethods quickfix does not shadow existing methods.\nSee golang/go#77130.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.22\n\n-- main.go --\npackage main\n\ntype I interface {\n\tFoo()\n\tBar()\n}\n\ntype B struct {\n\t*A\n}\n\ntype A struct {\n}\n\nfunc (a *A) Foo() {\n}\n\n// Interface I requires implementing Foo() and Bar(). B embeds A, and A already\n// implements Foo. To avoid method shadowing, the stub for B should only\n// implement Bar and not Foo.\nvar _ I = (*B)(nil) //@quickfix(re\"..B..nil.\", re\"missing method\", stub)\n\n-- @stub/main.go --\n@@ -12 +12,5 @@\n+// Bar implements [I].\n+func (b *B) Bar() {\n+\tpanic(\"unimplemented\")\n+}\n+\n@@ -22 +27 @@\n-\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/stubmethods/stuberrors.txt",
    "content": "This test verifies two types of errors when generating interface method stubs:\n1. adding method __ would conflict with (or shadow) existing field\n2. method __ already exists but has the wrong type\n\n-- go.mod --\nmodule mod.com\n\ngo 1.22\n\n-- wrong/type.go --\npackage wrongtype\n\ntype I interface {\n\tFoo()\n\tBar()\n}\n\ntype B struct {\n\t*A\n}\n\ntype A struct {}\n\nfunc (a *A) Foo() {}\nfunc (b *B) Foo(bool) {} // method Foo exists on B but has the wrong type\n\nvar _ I = (*B)(nil) //@quickfixerr(re\"..B..nil.\", re\"missing method\", \"already exists but has the wrong type\")\n\n-- field/conflict.go --\npackage fieldconflict\n\ntype I interface {\n\tFoo()\n\tBar()\n}\n\ntype B struct {\n\t*A\n}\n\ntype A struct {\n    Bar int // implementing a method \"Bar\" would conflict with existing field \"Bar\"\n}\n\nfunc (a *A) Foo() {}\nvar _ I = (*B)(nil) //@quickfixerr(re\"..B..nil.\", re\"is a field, not a method\", \"would conflict with (or shadow) existing field\")\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/undeclared/diag.txt",
    "content": "This test checks @diag reports for undeclared variables and functions.\n\n-- x.go --\npackage undeclared\n\nfunc x() int {\n\tvar z int\n\tz = y //@diag(\"y\", re\"(undeclared name|undefined): y\")\n\tif z == m { //@diag(\"m\", re\"(undeclared name|undefined): m\")\n\t\tz = 1\n\t}\n\n\tif z == 1 {\n\t\tz = 1\n\t} else if z == n+1 { //@diag(\"n\", re\"(undeclared name|undefined): n\")\n\t\tz = 1\n\t}\n\n\tswitch z {\n\tcase 10:\n\t\tz = 1\n\tcase aa: //@diag(\"aa\", re\"(undeclared name|undefined): aa\")\n\t\tz = 1\n\t}\n\treturn z\n}\n-- channels.go --\npackage undeclared\n\nfunc channels(s string) {\n\tundefinedChannels(c()) //@diag(\"undefinedChannels\", re\"(undeclared name|undefined): undefinedChannels\")\n}\n\nfunc c() (<-chan string, chan string) {\n\treturn make(<-chan string), make(chan string)\n}\n-- consecutive_params.go --\npackage undeclared\n\nfunc consecutiveParams() {\n\tvar s string\n\tundefinedConsecutiveParams(s, s) //@diag(\"undefinedConsecutiveParams\", re\"(undeclared name|undefined): undefinedConsecutiveParams\")\n}\n-- error_param.go --\npackage undeclared\n\nfunc errorParam() {\n\tvar err error\n\tundefinedErrorParam(err) //@diag(\"undefinedErrorParam\", re\"(undeclared name|undefined): undefinedErrorParam\")\n}\n-- literals.go --\npackage undeclared\n\ntype T struct{}\n\nfunc literals() {\n\tundefinedLiterals(\"hey compiler\", T{}, &T{}) //@diag(\"undefinedLiterals\", re\"(undeclared name|undefined): undefinedLiterals\")\n}\n-- operation.go --\npackage undeclared\n\nimport \"time\"\n\nfunc operation() {\n\tundefinedOperation(10 * time.Second) //@diag(\"undefinedOperation\", re\"(undeclared name|undefined): undefinedOperation\")\n}\n-- selector.go --\npackage undeclared\n\nfunc selector() {\n\tm := map[int]bool{}\n\tundefinedSelector(m[1]) //@diag(\"undefinedSelector\", re\"(undeclared name|undefined): undefinedSelector\")\n}\n-- slice.go --\npackage undeclared\n\nfunc slice() {\n\tundefinedSlice([]int{1, 2}) //@diag(\"undefinedSlice\", re\"(undeclared name|undefined): undefinedSlice\")\n}\n-- tuple.go --\npackage undeclared\n\nfunc tuple() {\n\tundefinedTuple(b()) //@diag(\"undefinedTuple\", re\"(undeclared name|undefined): undefinedTuple\")\n}\n\nfunc b() (string, error) {\n\treturn \"\", nil\n}\n-- unique.go --\npackage undeclared\n\nfunc uniqueArguments() {\n\tvar s string\n\tvar i int\n\tundefinedUniqueArguments(s, i, s) //@diag(\"undefinedUniqueArguments\", re\"(undeclared name|undefined): undefinedUniqueArguments\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/undeclared/missingfunction.txt",
    "content": "This test checks the quick fix for undefined functions.\n\n-- channels.go --\npackage missingfunction\n\nfunc channels(s string) {\n\tundefinedChannels(c()) //@quickfix(\"undefinedChannels\", re\"(undeclared|undefined)\", channels)\n}\n\nfunc c() (<-chan string, chan string) {\n\treturn make(<-chan string), make(chan string)\n}\n-- @channels/channels.go --\n@@ -7 +7,4 @@\n+func undefinedChannels(ch1 <-chan string, ch2 chan string) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- consecutive.go --\npackage missingfunction\n\nfunc consecutiveParams() {\n\tvar s string\n\tundefinedConsecutiveParams(s, s) //@quickfix(\"undefinedConsecutiveParams\", re\"(undeclared|undefined)\", consecutive)\n}\n-- @consecutive/consecutive.go --\n@@ -7 +7,4 @@\n+\n+func undefinedConsecutiveParams(s1, s2 string) {\n+\tpanic(\"unimplemented\")\n+}\n-- error.go --\npackage missingfunction\n\nfunc errorParam() {\n\tvar err error\n\tundefinedErrorParam(err) //@quickfix(\"undefinedErrorParam\", re\"(undeclared|undefined)\", error)\n}\n-- @error/error.go --\n@@ -7 +7,4 @@\n+\n+func undefinedErrorParam(err error) {\n+\tpanic(\"unimplemented\")\n+}\n-- literals.go --\npackage missingfunction\n\ntype T struct{}\n\nfunc literals() {\n\tundefinedLiterals(\"hey compiler\", T{}, &T{}) //@quickfix(\"undefinedLiterals\", re\"(undeclared|undefined)\", literals)\n}\n-- @literals/literals.go --\n@@ -8 +8,4 @@\n+\n+func undefinedLiterals(s string, t1 T, t2 *T) {\n+\tpanic(\"unimplemented\")\n+}\n-- operation.go --\npackage missingfunction\n\nimport \"time\"\n\nfunc operation() {\n\tundefinedOperation(10 * time.Second) //@quickfix(\"undefinedOperation\", re\"(undeclared|undefined)\", operation)\n}\n-- @operation/operation.go --\n@@ -8 +8,4 @@\n+\n+func undefinedOperation(duration time.Duration) {\n+\tpanic(\"unimplemented\")\n+}\n-- selector.go --\npackage missingfunction\n\nfunc selector() {\n\tm := map[int]bool{}\n\tundefinedSelector(m[1]) //@quickfix(\"undefinedSelector\", re\"(undeclared|undefined)\", selector)\n}\n-- @selector/selector.go --\n@@ -7 +7,4 @@\n+\n+func undefinedSelector(b bool) {\n+\tpanic(\"unimplemented\")\n+}\n-- slice.go --\npackage missingfunction\n\nfunc slice() {\n\tundefinedSlice([]int{1, 2}) //@quickfix(\"undefinedSlice\", re\"(undeclared|undefined)\", slice)\n}\n-- @slice/slice.go --\n@@ -6 +6,4 @@\n+\n+func undefinedSlice(i []int) {\n+\tpanic(\"unimplemented\")\n+}\n-- tuple.go --\npackage missingfunction\n\nfunc tuple() {\n\tundefinedTuple(b()) //@quickfix(\"undefinedTuple\", re\"(undeclared|undefined)\", tuple)\n}\n\nfunc b() (string, error) {\n\treturn \"\", nil\n}\n-- @tuple/tuple.go --\n@@ -7 +7,4 @@\n+func undefinedTuple(s string, err error) {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- unique_params.go --\npackage missingfunction\n\nfunc uniqueArguments() {\n\tvar s string\n\tvar i int\n\tundefinedUniqueArguments(s, i, s) //@quickfix(\"undefinedUniqueArguments\", re\"(undeclared|undefined)\", unique)\n}\n-- @unique/unique_params.go --\n@@ -8 +8,4 @@\n+\n+func undefinedUniqueArguments(s1 string, i int, s2 string) {\n+\tpanic(\"unimplemented\")\n+}\n-- param.go --\npackage missingfunction\n\nfunc inferFromParam() {\n\tf(as_param()) //@quickfix(\"as_param\", re\"undefined\", infer_param)\n}\n\nfunc f(i int) {}\n-- @infer_param/param.go --\n@@ -7 +7,4 @@\n+func as_param() int {\n+\tpanic(\"unimplemented\")\n+}\n+\n-- assign.go --\npackage missingfunction\n\nfunc inferFromAssign() {\n\ti := 42\n\ti = i\n\ti = assign() //@quickfix(\"assign\", re\"undefined\", infer_assign)\n}\n-- @infer_assign/assign.go --\n@@ -8 +8,4 @@\n+\n+func assign() int {\n+\tpanic(\"unimplemented\")\n+}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/undeclared/undeclared_variable.txt",
    "content": "Tests of suggested fixes for \"undeclared name\" diagnostics,\nwhich are of (\"compiler\", \"error\") type.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a.go --\npackage undeclared_var\n\nfunc a() {\n\tz, _ := 1+y, 11 //@quickfix(\"y\", re\"(undeclared name|undefined): y\", a)\n\t_ = z\n}\n\n-- @a/a.go --\n@@ -4 +4 @@\n+\ty := 0\n-- b.go --\npackage undeclared_var\n\nfunc b() {\n\tif 100 < 90 {\n\t} else if 100 > n+2 { //@quickfix(\"n\", re\"(undeclared name|undefined): n\", b)\n\t}\n}\n\n-- @b/b.go --\n@@ -4 +4 @@\n+\tn := 0\n-- c.go --\npackage undeclared_var\n\nfunc c() {\n\tfor i < 200 { //@quickfix(\"i\", re\"(undeclared name|undefined): i\", c)\n\t}\n\tr() //@diag(\"r\", re\"(undeclared name|undefined): r\")\n}\n\n-- @c/c.go --\n@@ -4 +4 @@\n+\ti := 0\n-- add_colon.go --\npackage undeclared_var\n\nfunc addColon() {\n\tac = 1 //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", add_colon)\n}\n\n-- @add_colon/add_colon.go --\n@@ -4 +4 @@\n-\tac = 1 //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", add_colon)\n+\tac := 1 //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", add_colon)\n-- add_colon_first.go --\npackage undeclared_var\n\nfunc addColonAtFirstStmt() {\n\tac = 1\n\tac = 2\n\tac = 3\n\tb := ac //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", add_colon_first)\n}\n\n-- @add_colon_first/add_colon_first.go --\n@@ -4 +4 @@\n-\tac = 1\n+\tac := 1\n-- self_assign.go --\npackage undeclared_var\n\nfunc selfAssign() {\n\tac = ac + 1\n\tac = ac + 2 //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", lhs)\n\tac = ac + 3 //@quickfix(\"ac + 3\", re\"(undeclared name|undefined): ac\", rhs)\n}\n\n-- @lhs/self_assign.go --\n@@ -4 +4 @@\n+\tac := nil\n-- @rhs/self_assign.go --\n@@ -4 +4 @@\n+\tac := 0\n-- correct_type.go --\npackage undeclared_var\nimport \"fmt\"\nfunc selfAssign() {\n\tfmt.Printf(ac) //@quickfix(\"ac\", re\"(undeclared name|undefined): ac\", string)\n}\n-- @string/correct_type.go --\n@@ -4 +4 @@\n+\tac := \"\"\n-- ignore.go --\npackage undeclared_var\nimport \"fmt\"\ntype Foo struct {\n\tbar int\n}\nfunc selfAssign() {\n\tf := Foo{}\n\tb = f.bar\n\tc := bar //@quickfix(\"bar\", re\"(undeclared name|undefined): bar\", ignore)\n}\n-- @ignore/ignore.go --\n@@ -9 +9 @@\n+\tbar := nil\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/undeclared/undeclaredfunc.txt",
    "content": "This test checks the quick fix for \"undeclared: f\" that declares the\nmissing function. See #47558.\n\n-- a.go --\npackage a\n\nfunc _() int { return f(1, \"\") } //@quickfix(re\"f.1\", re\"unde(fined|clared name): f\", x)\n\n-- @x/a.go --\n@@ -3 +3 @@\n-func _() int { return f(1, \"\") } //@quickfix(re\"f.1\", re\"unde(fined|clared name): f\", x)\n+func _() int { return f(1, \"\") }\n@@ -5 +5,4 @@\n+func f(i int, s string) int {\n+\tpanic(\"unimplemented\")\n+} //@quickfix(re\"f.1\", re\"unde(fined|clared name): f\", x)\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/unusedrequire.txt",
    "content": "This test checks the suggested fix to remove unused require statements from\ngo.mod files.\n\n-- flags --\n-write_sumfile=a\n\n-- proxy/example.com@v1.0.0/x.go --\npackage pkg\nconst X = 1\n\n-- a/go.mod --\nmodule mod.com\n\ngo 1.14\n\nrequire example.com v1.0.0 //@quickfix(\"require\", re\"not used\", a)\n\n-- @a/a/go.mod --\n@@ -4,3 +4 @@\n-\n-require example.com v1.0.0 //@quickfix(\"require\", re\"not used\", a)\n-\n-- a/main.go --\npackage main\nfunc main() {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/quickfix/unusedrequire_gowork.txt",
    "content": "This test checks the suggested fix to remove unused require statements from\ngo.mod files, when a go.work file is used.\n\nNote that unlike unusedrequire.txt, we need not write go.sum files when\na go.work file is used.\n\n-- proxy/example.com@v1.0.0/x.go --\npackage pkg\nconst X = 1\n\n-- go.work --\ngo 1.21\n\nuse (\n\t./a\n\t./b\n)\n-- a/go.mod --\nmodule mod.com/a\n\ngo 1.14\n\nrequire example.com v1.0.0 //@quickfix(\"require\", re\"not used\", a)\n\n-- @a/a/go.mod --\n@@ -4,3 +4 @@\n-\n-require example.com v1.0.0 //@quickfix(\"require\", re\"not used\", a)\n-\n-- a/main.go --\npackage main\nfunc main() {}\n\n-- b/go.mod --\nmodule mod.com/b\n\ngo 1.14\n\nrequire example.com v1.0.0 //@quickfix(\"require\", re\"not used\", b)\n\n-- @b/b/go.mod --\n@@ -4,3 +4 @@\n-\n-require example.com v1.0.0 //@quickfix(\"require\", re\"not used\", b)\n-\n-- b/main.go --\npackage main\nfunc main() {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/crosspackage.txt",
    "content": "Test of basic cross-package references.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype X struct {\n\tY int //@loc(typeXY, \"Y\")\n}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc GetXes() []a.X {\n\treturn []a.X{\n\t\t{\n\t\t\tY: 1, //@loc(GetXesY, \"Y\"), refs(\"Y\", typeXY, GetXesY, anotherXY)\n\t\t},\n\t}\n}\n\n-- c/c.go --\npackage c\n\nimport \"example.com/b\"\n\nfunc _() {\n        xes := b.GetXes()\n        for _, x := range xes { //@loc(defX, \"x\")\n                _ = x.Y //@loc(useX, \"x\"), loc(anotherXY, \"Y\"), loc(beforeX, re\"()x\"), loc(afterX, re\"()x\"), loc(beforeY, re\"()Y\"), loc(afterY, re\"Y()\")\n\t\t\t\t//@refs(beforeY, typeXY, anotherXY, GetXesY)\n\t\t\t\t//@refs(afterY, typeXY, anotherXY, GetXesY)\n\t\t\t\t//@refs(anotherXY, typeXY, anotherXY, GetXesY)\n\n\t\t\t\t//@refs(beforeX, defX, useX)\n\t\t\t\t//@refs(afterX, defX, useX)\n\t\t\t\t//@refs(useX, defX, useX)\n        }\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/imports.txt",
    "content": "Test of references to local package names (imports).\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"os\" //@loc(osDef, `\"os\"`), refs(\"os\", osDef, osUse)\n\nimport fmt2 \"fmt\" //@loc(fmt2Def, `fmt2`), refs(\"fmt2\", fmt2Def, fmt2Use)\n\nfunc _() {\n\tos.Getwd() //@loc(osUse, \"os\")\n\tfmt2.Println() //@loc(fmt2Use, \"fmt2\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/interfaces.txt",
    "content": "Test of references applied to concrete and interface types that are\nrelated by assignability. The result includes references to both.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype first interface {\n\tcommon() //@loc(firCommon, \"common\"), refs(\"common\", firCommon, xCommon, zCommon)\n\tfirstMethod() //@loc(firMethod, \"firstMethod\"), refs(\"firstMethod\", firMethod, xfMethod, zfMethod)\n}\n\ntype second interface {\n\tcommon() //@loc(secCommon, \"common\"), refs(\"common\", secCommon, yCommon, zCommon)\n\tsecondMethod() //@loc(secMethod, \"secondMethod\"), refs(\"secondMethod\", secMethod, ysMethod, zsMethod)\n}\n\ntype s struct {}\n\nfunc (*s) common() {} //@loc(sCommon, \"common\"), refs(\"common\", sCommon, xCommon, yCommon, zCommon)\n\nfunc (*s) firstMethod() {} //@loc(sfMethod, \"firstMethod\"), refs(\"firstMethod\", sfMethod, xfMethod, zfMethod)\n\nfunc (*s) secondMethod() {} //@loc(ssMethod, \"secondMethod\"), refs(\"secondMethod\", ssMethod, ysMethod, zsMethod)\n\nfunc main() {\n\tvar x first = &s{}\n\tvar y second = &s{}\n\n\tx.common() //@loc(xCommon, \"common\"), refs(\"common\", firCommon, xCommon, zCommon)\n\tx.firstMethod() //@loc(xfMethod, \"firstMethod\"), refs(\"firstMethod\", firMethod, xfMethod, zfMethod)\n\ty.common() //@loc(yCommon, \"common\"), refs(\"common\", secCommon, yCommon, zCommon)\n\ty.secondMethod() //@loc(ysMethod, \"secondMethod\"), refs(\"secondMethod\", secMethod, ysMethod, zsMethod)\n\n\tvar z *s = &s{}\n\tz.firstMethod() //@loc(zfMethod, \"firstMethod\"), refs(\"firstMethod\", sfMethod, xfMethod, zfMethod)\n\tz.secondMethod() //@loc(zsMethod, \"secondMethod\"), refs(\"secondMethod\", ssMethod, ysMethod, zsMethod)\n\tz.common() //@loc(zCommon, \"common\"), refs(\"common\", sCommon, xCommon, yCommon, zCommon)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/intrapackage.txt",
    "content": "Basic test of references within a single package.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype i int //@loc(decli, \"i\"), refs(\"i\", decli, argi, returni, embeddedi)\n\nfunc _(_ i) []bool { //@loc(argi, \"i\")\n\treturn nil\n}\n\nfunc _(_ []byte) i { //@loc(returni, \"i\")\n\treturn 0\n}\n\nvar q string //@loc(declq, \"q\"), refs(\"q\", declq, assignq, bobq)\n\nvar Q string //@loc(declQ, \"Q\"), refs(\"Q\", declQ)\n\nfunc _() {\n\tq = \"hello\" //@loc(assignq, \"q\")\n\tbob := func(_ string) {}\n\tbob(q) //@loc(bobq, \"q\")\n}\n\ntype e struct {\n\ti //@loc(embeddedi, \"i\"), refs(\"i\", embeddedi, embeddediref)\n}\n\nfunc _() {\n\t_ = e{}.i //@loc(embeddediref, \"i\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue58506.txt",
    "content": "Regression test for 'references' bug golang/go#58506.\n\nThe 'references' query below, applied to method A.F, implicitly uses\nthe 'implementation' operation. The correct response includes two\nreferences to B.F, one from package b and one from package d.\nHowever, the incremental 'implementation' algorithm had a bug that\ncause it to fail to report the reference from package b.\n\nThe reason was that the incremental implementation uses different\nalgorithms for the local and global cases (with disjoint results), and\nthat when it discovered that type A satisfies interface B and thus\nthat B.F must be included among the global search targets, the\nimplementation forgot to also search package b for local references\nto B.F.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A int\n\nfunc (A) F() {} //@loc(refa, \"F\"), refs(\"F\", refa, refb, refd)\n\n-- b/b.go --\npackage b\n\nimport (\n\t\"example.com/a\"\n\t\"example.com/c\"\n)\n\ntype B interface{ F() }\n\nvar _ B = a.A(0)\nvar _ B = c.C(0)\n\nvar _ = B.F //@loc(refb, \"F\")\n\n-- c/c.go --\npackage c\n\ntype C int\n\n// Even though C.F is \"rename coupled\" to A.F by B.F,\n// it should not be among the results.\nfunc (C) F() {}\n\n-- d/d.go --\npackage d\n\nimport \"example.com/b\"\n\nvar _ any = b.B.F //@loc(refd, \"F\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue59851.txt",
    "content": "Regression test for 'references' bug golang/go#59851.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype Iface interface {\n     Method()\n}\n\ntype implOne struct{}\n\nfunc (implOne) Method() {} //@loc(def1, \"Method\"), refs(def1, def1, ref1, iref, ireftest)\n\nvar _ = implOne.Method //@loc(ref1, \"Method\")\nvar _ = Iface(nil).Method //@loc(iref, \"Method\")\n\n-- a/a_test.go --\npackage a\n\ntype implTwo struct{}\n\nfunc (implTwo) Method() {} //@loc(def2, \"Method\"), refs(def2, def2, iref, ref2, ireftest)\n\nvar _ = implTwo.Method //@loc(ref2, \"Method\")\nvar _ = Iface(nil).Method //@loc(ireftest, \"Method\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue60369.txt",
    "content": "Regression test for 'references' bug golang/go#60369: a references\nquery on the embedded type name T in struct{p.T} instead reports all\nreferences to the package name p.\n\nThe bug was fixed in release go1.21 of go/types.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype A struct{}\nconst C = 0\n\n-- b/b.go --\npackage b\n\nimport a \"example.com/a\" //@loc(adef, \"a\")\ntype s struct {\n\ta.A //@loc(Aref1, \"A\"), loc(aref1, \"a\"), refs(Aref1, Aref1, Aref3), refs(aref1, adef, aref1, aref2, aref3)\n}\nvar _ a.A //@loc(aref2, re\" (a)\"), loc(Aref2, \"A\")\nvar _ = s{}.A //@loc(Aref3, \"A\")\nconst _ = a.C //@loc(aref3, \"a\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue60622.txt",
    "content": "Regression test for 'references' bug golang/go#60622:\nreferences to methods of generics were missing.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype G[T any] struct{}\n\nfunc (G[T]) M() {} //@loc(Mdef, \"M\"), refs(Mdef, Mdef, Mref)\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc _() {\n\tnew(a.G[int]).M() //@loc(Mref, \"M\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue60676.txt",
    "content": "This test verifies that even after importing from export data, the references\nalgorithm is able to find all references to struct fields or methods that are\nshared by types from multiple packages. See golang/go#60676.\n\nNote that the marker test runner awaits the initial workspace load, so export\ndata should be populated at the time references are requested.\n\n-- go.mod --\nmodule mod.test\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype A struct {\n\tF int //@loc(FDef, \"F\")\n\tE //@loc(EDef, \"E\")\n}\n\ntype E struct {\n\tG string //@loc(GDef, \"G\")\n}\n\ntype AI interface {\n\tM() //@loc(MDef, \"M\")\n\tEI\n\terror\n}\n\ntype EI interface {\n\tN() //@loc(NDef, \"N\")\n}\n\ntype T[P any] struct{ f P }\n\ntype Error error\n\n\n-- b/b.go --\npackage b\n\nimport \"mod.test/a\"\n\ntype B a.A\n\ntype BI a.AI\n\ntype T a.T[int] // must not panic\n\n-- c/c.go --\npackage c\n\nimport \"mod.test/b\"\n\nfunc _() {\n\tx := b.B{\n\t\tF: 42, //@refs(\"F\", FDef, \"F\", Fuse)\n\t}\n\tx.G = \"hi\" //@refs(\"G\", GDef, \"G\")\n\t_ = x.E //@refs(\"E\", EDef, \"E\")\n\t_ = x.F //@loc(Fuse, \"F\")\n}\n\nfunc _(y b.BI) {\n\t_ = y.M //@refs(\"M\", MDef, \"M\")\n\t_ = y.N //@refs(\"N\", NDef, \"N\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue61618.txt",
    "content": "Regression test for 'references' bug golang/go#61618:\nreferences to instantiated fields were missing.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a.go --\npackage a\n\n// This file is adapted from the example in the issue.\n\ntype builder[S ~[]F, F ~string] struct {\n\tname string\n\telements S //@loc(def, \"elements\"), refs(def, def, assign, use)\n\telemData map[F][]ElemData[F]\n}\n\ntype ElemData[F ~string] struct {\n  Name F\n}\n\ntype BuilderImpl[S ~[]F, F ~string] struct{ builder[S, F] }\n\nfunc NewBuilderImpl[S ~[]F, F ~string](name string)  *BuilderImpl[S, F] {\n  impl := &BuilderImpl[S,F]{\n\tbuilder[S, F]{\n\t  name: name,\n\t  elements: S{}, //@loc(assign, \"elements\"), refs(assign, def, assign, use)\n\t  elemData: map[F][]ElemData[F]{},\n\t},\n  }\n\n  _ = impl.elements //@loc(use, \"elements\"), refs(use, def, assign, use)\n  return impl\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue67978.txt",
    "content": "\nThis test exercises a references query on an exported method that\nconflicts with a field name. This ill-typed input violates the\nassumption that if type T has a method, then the method set of T is\nnonempty, which led to a crash.\n\nSee https://github.com/golang/go/issues/67978.\n\n-- a.go --\npackage p\n\ntype E struct { X int } //@ diag(re\"()X\", re\"field.*same name\")\n\nfunc (E) X() {} //@ loc(a, \"X\"), refs(\"X\", a, b), diag(re\"()X\", re\"method.*same name\")\n\nvar _ = new(E).X //@ loc(b, \"X\")\n\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue75810.txt",
    "content": "-- go.work --\ngo 1.22\n\nuse ./a\nuse ./b\nuse ./c\n\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.22\n\nrequire example.com/b v0.0.1 //@ refs(\"/b\", bmod, a_b, a2_b, a3_b)\n\n-- a/a.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a_b, `\"example.com/b\"`)\n\nvar _ = b.B\n\n-- a/a2.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a2_b, `\"example.com/b\"`)\n\nvar _ = b.B\n\n-- a/a3/a3.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a3_b, `\"example.com/b\"`)\n\nvar _ = b.B\n\n-- b/go.mod --\nmodule example.com/b //@ loc(bmod, re\"^.*?b\")\n\ngo 1.22\n\n-- b/b.go --\npackage b\n\nvar B int\n\n-- c/go.mod --\nmodule example.com/c\n\ngo 1.22\n\nrequire example.com/a v0.0.1\nrequire example.com/b v0.0.1 //@ refs(\"/b\",bmod, c_b)\n-- c/c.go --\npackage c\n\nimport \"example.com/b\" //@ loc(c_b, `\"example.com/b\"`)\n\nvar _ = b.B\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue75810A.txt",
    "content": "Find references to example.com/b, but not to example.com/b/x\n-- go.work --\ngo 1.22\n\nuse ./a\nuse ./b\nuse ./b/x\nuse ./c\n\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.22\n\nrequire example.com/b v0.0.1 //@ refs(\"/b\", bmod, a_b, a2_b, a3_b)\n-- a/a.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a_b, `\"example.com/b\"`)\nimport \"example.com/b/x\" //@ loc(a4_x, `\"example.com/b/x\"`)\n\nvar _ = b.B\nvar _ = x.X\n\n-- a/a2.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a2_b, `\"example.com/b\"`)\n\nvar _ = b.B\n\n-- a/a3/a3.go --\npackage a\n\nimport \"example.com/b\" //@ loc(a3_b, `\"example.com/b\"`)\nimport \"example.com/b/x\" //@ loc(a3_x, `\"example.com/b/x\"`)\n\n\nvar _ = b.B\nvar _ = x.X\n\n-- b/go.mod --\nmodule example.com/b //@ loc(bmod, re\"^.*?b\")\n\ngo 1.22\n\n-- b/b.go --\npackage b\n\nvar B int\n\n-- b/x/go.mod --\nmodule example.com/b/x\n\ngo 1.22\n\n-- b/x/x.go --\npackage x\n\nvar X int\n-- c/go.mod --\nmodule example.com/c\n\ngo 1.22\n\nrequire example.com/a v0.0.1\nrequire example.com/b v0.0.1 //@ refs(\"/b\", bmod, c_b)\n-- c/c.go --\npackage c\n\nimport \"example.com/b\" //@ loc(c_b, `\"example.com/b\"`)\n\nvar _ = b.B\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/issue76872.txt",
    "content": "This test exercises a references query at a position where an empty selection\nmight be considered enclosed both by the node before (Ident) and the node after\n(FuncType). It ensures that we find the reference of the syntax node before the\ncursor.\n\nSee https://github.com/golang/go/issues/76872.\n\n-- main.go --\npackage main\n\n// re\"foo()\" matches the zero-width position after \"foo\", not the call parens.\nfunc foo() {} //@ loc(decl, \"foo\"), refs(re\"foo()\", decl, call)\n\nfunc _() {\n\tfoo() //@ loc(call, \"foo\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/shadow.txt",
    "content": "Test of references in the presence of shadowing.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tx := 123 //@loc(x1, \"x\"), refs(\"x\", x1, x1ref)\n\t_ = x //@loc(x1ref, \"x\")\n\t{\n\t\tx := \"hi\" //@loc(x2, \"x\"), refs(\"x\", x2, x2ref)\n\t\t_ = x //@loc(x2ref, \"x\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/test.txt",
    "content": "Test of references between the extra files of a test variant\nand the regular package.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc fn() {} //@loc(def, \"fn\"), refs(\"fn\", def, use)\n\ntype t struct { g int } //@loc(gdef, \"g\")\ntype u struct { t }\n\nvar _ = new(u).g //@loc(gref, \"g\"), refs(\"g\", gdef, gref)\n// TODO(adonovan): fix: gref2 and gdef2 are missing.\n\n-- a/a_test.go --\npackage a\n\nfunc _() {\n\tfn() //@loc(use, \"fn\")\n\n\t_ = new(u).g //@loc(gref2, \"g\"), refs(\"g\", gdef2, gref, gref2)\n}\n\n// This declaration changes the meaning of u.t in the test.\nfunc (u) g() {} //@loc(gdef2, \"g\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/references/typeswitch.txt",
    "content": "Tests of reference to implicit type switch vars, which are\na special case in go/types.Info{Def,Use,Implicits}.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _(x any) {\n\tswitch y := x.(type) { //@loc(yDecl, \"y\"), refs(\"y\", yDecl, yInt, yDefault)\n\tcase int:\n\t\tprintln(y) //@loc(yInt, \"y\"), refs(\"y\", yDecl, yInt, yDefault)\n\tdefault:\n\t\tprintln(y) //@loc(yDefault, \"y\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/bad.txt",
    "content": "This test checks that rename fails in the presence of errors.\n\n-- go.mod --\nmodule golang.org/lsptests/bad\n\ngo 1.18\n\n-- bad.go --\npackage bad\n\ntype myStruct struct {\n}\n\nfunc (s *myStruct) sFunc() bool { //@renameerr(\"sFunc\", \"rFunc\", \"not possible because \\\"bad.go\\\" in \\\"golang.org/lsptests/bad\\\" has errors\")\n\treturn s.Bad //@diag(\"Bad\", re\"no field or method\")\n}\n\n-- bad_test.go --\npackage bad\n\n\n-- badsyntax/badsyntax.go --\npackage badsyntax\n\ntype S struct {}\n\nfunc (s *S) sFunc() bool { //@renameerr(\"sFunc\", \"rFunc\", \"not possible because \\\"badsyntax.go\\\" in \\\"golang.org/lsptests/bad/badsyntax\\\" has errors\")\n\t# //@diag(\"#\", re\"expected statement, found\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/basic.txt",
    "content": "This test performs basic coverage of 'rename' within a single package.\n\n-- basic.go --\npackage p\n\nfunc _(x int) { println(x) } //@rename(\"x\", \"y\", xToy)\n\n-- @xToy/basic.go --\n@@ -3 +3 @@\n-func _(x int) { println(x) } //@rename(\"x\", \"y\", xToy)\n+func _(y int) { println(y) } //@rename(\"x\", \"y\", xToy)\n-- alias.go --\npackage p\n\n// from golang/go#61625\ntype LongNameHere struct{}\ntype A = LongNameHere //@rename(\"A\", \"B\", AToB)\nfunc Foo() A\n\n-- errors.go --\npackage p\n\nfunc _(x []int) { //@renameerr(\"_\", \"blank\", `can't rename \"_\"`)\n\tx = append(x, 1) //@renameerr(\"append\", \"blank\", \"built in and cannot be renamed\")\n\tx = nil //@renameerr(\"nil\", \"blank\", \"built in and cannot be renamed\")\n\tx = nil //@renameerr(\"x\", \"x\", \"old and new names are the same: x\")\n\t_ = 1 //@renameerr(\"1\", \"x\", \"no identifier found\")\n}\n\n-- @AToB/alias.go --\n@@ -5,2 +5,2 @@\n-type A = LongNameHere //@rename(\"A\", \"B\", AToB)\n-func Foo() A\n+type B = LongNameHere //@rename(\"A\", \"B\", AToB)\n+func Foo() B\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/conflict.txt",
    "content": "This test exercises some renaming conflict scenarios\nand ensures that the errors are informative.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- super/p.go --\npackage super\n\nvar x int\n\nfunc _(y int) {\n\tprintln(x)\n\tprintln(y) //@renameerr(\"y\", \"x\", errSuperBlockConflict)\n}\n\n-- @errSuperBlockConflict --\nsuper/p.go:5:8: renaming this var \"y\" to \"x\"\nsuper/p.go:6:10:\twould shadow this reference\nsuper/p.go:3:5:\tto the var declared here\n-- sub/p.go --\npackage sub\n\nvar a int\n\nfunc _(b int) {\n\tprintln(a) //@renameerr(\"a\", \"b\", errSubBlockConflict)\n\tprintln(b)\n}\n\n-- @errSubBlockConflict --\nsub/p.go:3:5: renaming this var \"a\" to \"b\"\nsub/p.go:6:10:\twould cause this reference to become shadowed\nsub/p.go:5:8:\tby this intervening var definition\n-- pkgname/p.go --\npackage pkgname\n\nimport e1 \"errors\" //@renameerr(\"e1\", \"errors\", errImportConflict)\nimport \"errors\"\n\nvar _ = errors.New\nvar _ = e1.New\n\n-- @errImportConflict --\npkgname/p.go:3:8: renaming this imported package name \"e1\" to \"errors\"\npkgname/p.go:4:8:\tconflicts with imported package name in same block\n-- pkgname2/p1.go --\npackage pkgname2\nvar x int\n\n-- pkgname2/p2.go --\npackage pkgname2\nimport \"errors\" //@renameerr(\"errors\", \"x\", errImportConflict2)\nvar _ = errors.New\n\n-- @errImportConflict2 --\npkgname2/p2.go:2:8: renaming this imported package name \"errors\" to \"x\" would conflict\npkgname2/p1.go:2:5:\twith this package member var\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/crosspkg.txt",
    "content": "This test checks cross-package renaming.\n\n-- go.mod --\nmodule golang.org/lsptests/rename\n\ngo 1.18\n\n-- crosspkg/crosspkg.go --\npackage crosspkg\n\nfunc Foo() { //@rename(\"Foo\", \"Dolphin\", FooToDolphin)\n\n}\n\nvar Bar int //@rename(\"Bar\", \"Tomato\", BarToTomato)\n\n-- crosspkg/another/another.go --\npackage another\n\ntype (\n\tI interface{ F() }\n\tC struct{ I }\n)\n\nfunc (C) g()\n\nfunc _() {\n\tvar x I = C{}\n\tx.F() //@rename(\"F\", \"G\", FToG)\n}\n\nvar _ = C.g\n\n-- crosspkg/other/other.go --\npackage other\n\nimport \"golang.org/lsptests/rename/crosspkg\"\n\nfunc Other() {\n\tcrosspkg.Bar //@diag(\"crosspkg\", re\"not used\")\n\tcrosspkg.Foo() //@rename(\"Foo\", \"Flamingo\", FooToFlamingo)\n}\n\n-- @BarToTomato/crosspkg/crosspkg.go --\n@@ -7 +7 @@\n-var Bar int //@rename(\"Bar\", \"Tomato\", BarToTomato)\n+var Tomato int //@rename(\"Bar\", \"Tomato\", BarToTomato)\n-- @BarToTomato/crosspkg/other/other.go --\n@@ -6 +6 @@\n-\tcrosspkg.Bar //@diag(\"crosspkg\", re\"not used\")\n+\tcrosspkg.Tomato //@diag(\"crosspkg\", re\"not used\")\n-- @FToG/crosspkg/another/another.go --\n@@ -4 +4 @@\n-\tI interface{ F() }\n+\tI interface{ G() }\n@@ -12 +12 @@\n-\tx.F() //@rename(\"F\", \"G\", FToG)\n+\tx.G() //@rename(\"F\", \"G\", FToG)\n-- @FooToDolphin/crosspkg/crosspkg.go --\n@@ -3 +3 @@\n-func Foo() { //@rename(\"Foo\", \"Dolphin\", FooToDolphin)\n+func Dolphin() { //@rename(\"Foo\", \"Dolphin\", FooToDolphin)\n-- @FooToDolphin/crosspkg/other/other.go --\n@@ -7 +7 @@\n-\tcrosspkg.Foo() //@rename(\"Foo\", \"Flamingo\", FooToFlamingo)\n+\tcrosspkg.Dolphin() //@rename(\"Foo\", \"Flamingo\", FooToFlamingo)\n-- @FooToFlamingo/crosspkg/crosspkg.go --\n@@ -3 +3 @@\n-func Foo() { //@rename(\"Foo\", \"Dolphin\", FooToDolphin)\n+func Flamingo() { //@rename(\"Foo\", \"Dolphin\", FooToDolphin)\n-- @FooToFlamingo/crosspkg/other/other.go --\n@@ -7 +7 @@\n-\tcrosspkg.Foo() //@rename(\"Foo\", \"Flamingo\", FooToFlamingo)\n+\tcrosspkg.Flamingo() //@rename(\"Foo\", \"Flamingo\", FooToFlamingo)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/doclink.txt",
    "content": "This test checks that doc links are also handled correctly (golang/go#64495).\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n\n-- a/a.go --\npackage a\n\n// Foo just for test [Foo]\n// reference others objects [A] [B] [C] [C.F] [C.PF]\nfunc Foo() {} //@rename(\"Foo\", \"Bar\", FooToBar)\n\nconst A = 1 //@rename(\"A\", \"AA\", AToAA)\n\nvar B = 1 //@rename(\"B\", \"BB\", BToBB)\n\ntype C int //@rename(\"C\", \"CC\", CToCC)\n\nfunc (C) F() {} //@rename(\"F\", \"FF\", FToFF)\n\nfunc (*C) PF() {} //@rename(\"PF\", \"PFF\", PFToPFF)\n\n// D just for test [*D]\ntype D int //@rename(\"D\", \"DD\", DToDD)\n\n// E test generic type doc link [E] [E.Foo]\ntype E[T any] struct { //@rename(\"E\", \"EE\", EToEE)\n\tField T\n}\n\nfunc (E[T]) Foo() {} //@rename(\"Foo\", \"Bar\", EFooToEBar)\n\n-- b/b.go --\npackage b\n\nimport aa \"example.com/a\" //@rename(\"aa\", \"a\", pkgRename)\n\n// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n// reference pointer type [*aa.D]\n// reference generic type links [aa.E] [aa.E.Foo]\nfunc FooBar() {\n\taa.Foo()\n\tvar e aa.E[int]\n\te.Foo()\n}\n\n\n-- @FooToBar/a/a.go --\n@@ -3 +3 @@\n-// Foo just for test [Foo]\n+// Bar just for test [Bar]\n@@ -5 +5 @@\n-func Foo() {} //@rename(\"Foo\", \"Bar\", FooToBar)\n+func Bar() {} //@rename(\"Foo\", \"Bar\", FooToBar)\n-- @FooToBar/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Bar] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n@@ -9 +9 @@\n-\taa.Foo()\n+\taa.Bar()\n-- @AToAA/a/a.go --\n@@ -4 +4 @@\n-// reference others objects [A] [B] [C] [C.F] [C.PF]\n+// reference others objects [AA] [B] [C] [C.F] [C.PF]\n@@ -7 +7 @@\n-const A = 1 //@rename(\"A\", \"AA\", AToAA)\n+const AA = 1 //@rename(\"A\", \"AA\", AToAA)\n-- @AToAA/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Foo] [aa.AA] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n-- @BToBB/a/a.go --\n@@ -4 +4 @@\n-// reference others objects [A] [B] [C] [C.F] [C.PF]\n+// reference others objects [A] [BB] [C] [C.F] [C.PF]\n@@ -9 +9 @@\n-var B = 1 //@rename(\"B\", \"BB\", BToBB)\n+var BB = 1 //@rename(\"B\", \"BB\", BToBB)\n-- @BToBB/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Foo] [aa.A] [aa.BB] [aa.C] [aa.C.F] [aa.C.PF]\n-- @CToCC/a/a.go --\n@@ -4 +4 @@\n-// reference others objects [A] [B] [C] [C.F] [C.PF]\n+// reference others objects [A] [B] [CC] [CC.F] [CC.PF]\n@@ -11 +11 @@\n-type C int //@rename(\"C\", \"CC\", CToCC)\n+type CC int //@rename(\"C\", \"CC\", CToCC)\n@@ -13 +13 @@\n-func (C) F() {} //@rename(\"F\", \"FF\", FToFF)\n+func (CC) F() {} //@rename(\"F\", \"FF\", FToFF)\n@@ -15 +15 @@\n-func (*C) PF() {} //@rename(\"PF\", \"PFF\", PFToPFF)\n+func (*CC) PF() {} //@rename(\"PF\", \"PFF\", PFToPFF)\n-- @CToCC/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.CC] [aa.CC.F] [aa.CC.PF]\n-- @FToFF/a/a.go --\n@@ -4 +4 @@\n-// reference others objects [A] [B] [C] [C.F] [C.PF]\n+// reference others objects [A] [B] [C] [C.FF] [C.PF]\n@@ -13 +13 @@\n-func (C) F() {} //@rename(\"F\", \"FF\", FToFF)\n+func (C) FF() {} //@rename(\"F\", \"FF\", FToFF)\n-- @FToFF/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.FF] [aa.C.PF]\n-- @PFToPFF/a/a.go --\n@@ -4 +4 @@\n-// reference others objects [A] [B] [C] [C.F] [C.PF]\n+// reference others objects [A] [B] [C] [C.F] [C.PFF]\n@@ -15 +15 @@\n-func (*C) PF() {} //@rename(\"PF\", \"PFF\", PFToPFF)\n+func (*C) PFF() {} //@rename(\"PF\", \"PFF\", PFToPFF)\n-- @PFToPFF/b/b.go --\n@@ -5 +5 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n+// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PFF]\n-- @pkgRename/b/b.go --\n@@ -3 +3 @@\n-import aa \"example.com/a\" //@rename(\"aa\", \"a\", pkgRename)\n+import \"example.com/a\" //@rename(\"aa\", \"a\", pkgRename)\n@@ -5,3 +5,3 @@\n-// FooBar just for test [aa.Foo] [aa.A] [aa.B] [aa.C] [aa.C.F] [aa.C.PF]\n-// reference pointer type [*aa.D]\n-// reference generic type links [aa.E] [aa.E.Foo]\n+// FooBar just for test [a.Foo] [a.A] [a.B] [a.C] [a.C.F] [a.C.PF]\n+// reference pointer type [*a.D]\n+// reference generic type links [a.E] [a.E.Foo]\n@@ -9,2 +9,2 @@\n-\taa.Foo()\n-\tvar e aa.E[int]\n+\ta.Foo()\n+\tvar e a.E[int]\n-- @DToDD/a/a.go --\n@@ -17,2 +17,2 @@\n-// D just for test [*D]\n-type D int //@rename(\"D\", \"DD\", DToDD)\n+// DD just for test [*DD]\n+type DD int //@rename(\"D\", \"DD\", DToDD)\n-- @DToDD/b/b.go --\n@@ -6 +6 @@\n-// reference pointer type [*aa.D]\n+// reference pointer type [*aa.DD]\n-- @EToEE/a/a.go --\n@@ -20,2 +20,2 @@\n-// E test generic type doc link [E] [E.Foo]\n-type E[T any] struct { //@rename(\"E\", \"EE\", EToEE)\n+// EE test generic type doc link [EE] [EE.Foo]\n+type EE[T any] struct { //@rename(\"E\", \"EE\", EToEE)\n@@ -25 +25 @@\n-func (E[T]) Foo() {} //@rename(\"Foo\", \"Bar\", EFooToEBar)\n+func (EE[T]) Foo() {} //@rename(\"Foo\", \"Bar\", EFooToEBar)\n-- @EToEE/b/b.go --\n@@ -7 +7 @@\n-// reference generic type links [aa.E] [aa.E.Foo]\n+// reference generic type links [aa.EE] [aa.EE.Foo]\n@@ -10 +10 @@\n-\tvar e aa.E[int]\n+\tvar e aa.EE[int]\n-- @EFooToEBar/a/a.go --\n@@ -20 +20 @@\n-// E test generic type doc link [E] [E.Foo]\n+// E test generic type doc link [E] [E.Bar]\n@@ -25 +25 @@\n-func (E[T]) Foo() {} //@rename(\"Foo\", \"Bar\", EFooToEBar)\n+func (E[T]) Bar() {} //@rename(\"Foo\", \"Bar\", EFooToEBar)\n-- @EFooToEBar/b/b.go --\n@@ -7 +7 @@\n-// reference generic type links [aa.E] [aa.E.Foo]\n+// reference generic type links [aa.E] [aa.E.Bar]\n@@ -11 +11 @@\n-\te.Foo()\n+\te.Bar()\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/embed.txt",
    "content": "This test exercises renaming of types used as embedded fields.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype A int //@rename(\"A\", \"A2\", type)\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\ntype B struct { a.A } //@rename(\"A\", \"A3\", embedA)\n\nvar _ = new(B).A //@renameerr(\"A\", \"A4\", errAnonField)\n\ntype C int\n\ntype D struct {\n    C //@rename(\"C\", \"C2\", embedC)\n}\n\n-- @errAnonField --\nan embedded field must be renamed at its declaration (since it renames the type too)\n-- @type/a/a.go --\n@@ -3 +3 @@\n-type A int //@rename(\"A\", \"A2\", type)\n+type A2 int //@rename(\"A\", \"A2\", type)\n-- @type/b/b.go --\n@@ -5 +5 @@\n-type B struct { a.A } //@rename(\"A\", \"A3\", embedA)\n+type B struct { a.A2 } //@rename(\"A\", \"A3\", embedA)\n@@ -7 +7 @@\n-var _ = new(B).A //@renameerr(\"A\", \"A4\", errAnonField)\n+var _ = new(B).A2 //@renameerr(\"A\", \"A4\", errAnonField)\n-- @embedA/a/a.go --\n@@ -3 +3 @@\n-type A int //@rename(\"A\", \"A2\", type)\n+type A3 int //@rename(\"A\", \"A2\", type)\n-- @embedA/b/b.go --\n@@ -5 +5 @@\n-type B struct { a.A } //@rename(\"A\", \"A3\", embedA)\n+type B struct { a.A3 } //@rename(\"A\", \"A3\", embedA)\n@@ -7 +7 @@\n-var _ = new(B).A //@renameerr(\"A\", \"A4\", errAnonField)\n+var _ = new(B).A3 //@renameerr(\"A\", \"A4\", errAnonField)\n-- @embedC/b/b.go --\n@@ -9 +9 @@\n-type C int\n+type C2 int\n@@ -12 +12 @@\n-    C //@rename(\"C\", \"C2\", embedC)\n+    C2 //@rename(\"C\", \"C2\", embedC)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/func.txt",
    "content": "This test checks basic functionality for renaming (=changing) a function\nsignature.\n\n-- go.mod --\nmodule example.com\n\ngo 1.20\n\n-- a/a.go --\npackage a\n\n//@rename(Foo, \"func(i int, s string)\", unchanged)\n//@rename(Foo, \"func(s string, i int)\", reverse)\n//@rename(Foo, \"func(s string)\", dropi)\n//@rename(Foo, \"func(i int)\", drops)\n//@rename(Foo, \"func()\", dropboth)\n//@renameerr(Foo, \"func(i int, s string, t bool)\", \"not yet supported\")\n//@renameerr(Foo, \"func(i string)\", \"not yet supported\")\n//@renameerr(Foo, \"func(i int, s string) int\", \"not yet supported\")\n\nfunc Foo(i int, s string) { //@loc(Foo, \"func\")\n}\n\nfunc _() {\n\tFoo(0, \"hi\")\n}\n-- @dropboth/a/a.go --\n@@ -12 +12 @@\n-func Foo(i int, s string) { //@loc(Foo, \"func\")\n+func Foo() { //@loc(Foo, \"func\")\n@@ -16 +16 @@\n-\tFoo(0, \"hi\")\n+\tFoo()\n-- @dropi/a/a.go --\n@@ -12 +12 @@\n-func Foo(i int, s string) { //@loc(Foo, \"func\")\n+func Foo(s string) { //@loc(Foo, \"func\")\n@@ -16 +16 @@\n-\tFoo(0, \"hi\")\n+\tFoo(\"hi\")\n-- @drops/a/a.go --\n@@ -12 +12 @@\n-func Foo(i int, s string) { //@loc(Foo, \"func\")\n+func Foo(i int) { //@loc(Foo, \"func\")\n@@ -16 +16 @@\n-\tFoo(0, \"hi\")\n+\tFoo(0)\n-- @reverse/a/a.go --\n@@ -12 +12 @@\n-func Foo(i int, s string) { //@loc(Foo, \"func\")\n+func Foo(s string, i int) { //@loc(Foo, \"func\")\n@@ -16 +16 @@\n-\tFoo(0, \"hi\")\n+\tFoo(\"hi\", 0)\n-- @unchanged/a/a.go --\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/generics.txt",
    "content": "This test exercises various renaming features on generic code.\n\nFixed bugs:\n\n- golang/go#61614: renaming a method of a type in a package that uses type\n  parameter composite lits used to panic, because previous iterations of the\n  satisfy analysis did not account for this language feature.\n\n- golang/go#61635: renaming type parameters did not work when they were\n  capitalized and the package was imported by another package.\n\n-- go.mod --\nmodule example.com\ngo 1.20\n\n-- a.go --\npackage a\n\ntype I int\n\nfunc (I) m() {} //@rename(\"m\", \"M\", mToM)\n\nfunc _[P ~[]int]() {\n\t_ = P{}\n}\n\nvar _ = I.m\n\n-- @mToM/a.go --\n@@ -5 +5 @@\n-func (I) m() {} //@rename(\"m\", \"M\", mToM)\n+func (I) M() {} //@rename(\"m\", \"M\", mToM)\n@@ -11 +11 @@\n-var _ = I.m\n+var _ = I.M\n-- g.go --\npackage a\n\ntype S[P any] struct { //@rename(\"P\", \"Q\", PToQ)\n\tP P\n\tF func(P) P\n}\n\nfunc F[R any](r R) {\n\tvar _ R //@rename(\"R\", \"S\", RToS)\n}\n\n-- @PToQ/g.go --\n@@ -3,3 +3,3 @@\n-type S[P any] struct { //@rename(\"P\", \"Q\", PToQ)\n-\tP P\n-\tF func(P) P\n+type S[Q any] struct { //@rename(\"P\", \"Q\", PToQ)\n+\tP Q\n+\tF func(Q) Q\n-- @RToS/g.go --\n@@ -8,2 +8,2 @@\n-func F[R any](r R) {\n-\tvar _ R //@rename(\"R\", \"S\", RToS)\n+func F[S any](r S) {\n+\tvar _ S //@rename(\"R\", \"S\", RToS)\n-- issue61635/p.go --\npackage issue61635\n\ntype builder[S ~[]F, F ~string] struct { //@rename(\"S\", \"T\", SToT)\n\tname string\n\telements S\n\telemData map[F][]ElemData[F]\n\t// other fields...\n}\n\ntype ElemData[F ~string] struct {\n  Name F\n  // other fields...\n}\n\ntype BuilderImpl[S ~[]F, F ~string] struct{ builder[S, F] }\n\n-- importer/i.go --\npackage importer\n\nimport \"example.com/issue61635\" // importing is necessary to repro golang/go#61635\n\nvar _ issue61635.ElemData[string]\n\n-- @SToT/issue61635/p.go --\n@@ -3 +3 @@\n-type builder[S ~[]F, F ~string] struct { //@rename(\"S\", \"T\", SToT)\n+type builder[T ~[]F, F ~string] struct { //@rename(\"S\", \"T\", SToT)\n@@ -5 +5 @@\n-\telements S\n+\telements T\n-- instances/type.go --\npackage instances\n\ntype R[P any] struct { //@rename(\"R\", \"u\", Rtou)\n\tNext *R[P] //@rename(\"R\", \"s\", RTos)\n}\n\nfunc (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n\tvar x R[P]\n\treturn rv.Do(x) //@rename(\"Do\", \"Do2\", DoToDo2)\n}\n\nfunc _() {\n\tvar x R[int] //@rename(\"R\", \"r\", RTor)\n\tx = x.Do(x)\n}\n\n-- @RTos/instances/type.go --\n@@ -3,2 +3,2 @@\n-type R[P any] struct { //@rename(\"R\", \"u\", Rtou)\n-\tNext *R[P] //@rename(\"R\", \"s\", RTos)\n+type s[P any] struct { //@rename(\"R\", \"u\", Rtou)\n+\tNext *s[P] //@rename(\"R\", \"s\", RTos)\n@@ -7,2 +7,2 @@\n-func (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n-\tvar x R[P]\n+func (rv s[P]) Do(s[P]) s[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n+\tvar x s[P]\n@@ -13 +13 @@\n-\tvar x R[int] //@rename(\"R\", \"r\", RTor)\n+\tvar x s[int] //@rename(\"R\", \"r\", RTor)\n-- @Rtou/instances/type.go --\n@@ -3,2 +3,2 @@\n-type R[P any] struct { //@rename(\"R\", \"u\", Rtou)\n-\tNext *R[P] //@rename(\"R\", \"s\", RTos)\n+type u[P any] struct { //@rename(\"R\", \"u\", Rtou)\n+\tNext *u[P] //@rename(\"R\", \"s\", RTos)\n@@ -7,2 +7,2 @@\n-func (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n-\tvar x R[P]\n+func (rv u[P]) Do(u[P]) u[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n+\tvar x u[P]\n@@ -13 +13 @@\n-\tvar x R[int] //@rename(\"R\", \"r\", RTor)\n+\tvar x u[int] //@rename(\"R\", \"r\", RTor)\n-- @DoToDo1/instances/type.go --\n@@ -7 +7 @@\n-func (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n+func (rv R[P]) Do1(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n@@ -9 +9 @@\n-\treturn rv.Do(x) //@rename(\"Do\", \"Do2\", DoToDo2)\n+\treturn rv.Do1(x) //@rename(\"Do\", \"Do2\", DoToDo2)\n@@ -14 +14 @@\n-\tx = x.Do(x)\n+\tx = x.Do1(x)\n-- @DoToDo2/instances/type.go --\n@@ -7 +7 @@\n-func (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n+func (rv R[P]) Do2(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n@@ -9 +9 @@\n-\treturn rv.Do(x) //@rename(\"Do\", \"Do2\", DoToDo2)\n+\treturn rv.Do2(x) //@rename(\"Do\", \"Do2\", DoToDo2)\n@@ -14 +14 @@\n-\tx = x.Do(x)\n+\tx = x.Do2(x)\n-- instances/func.go --\npackage instances\n\nfunc Foo[P any](p P) { //@rename(\"Foo\", \"Bar\", FooToBar)\n\tFoo(p) //@rename(\"Foo\", \"Baz\", FooToBaz)\n}\n\n-- @FooToBar/instances/func.go --\n@@ -3,2 +3,2 @@\n-func Foo[P any](p P) { //@rename(\"Foo\", \"Bar\", FooToBar)\n-\tFoo(p) //@rename(\"Foo\", \"Baz\", FooToBaz)\n+func Bar[P any](p P) { //@rename(\"Foo\", \"Bar\", FooToBar)\n+\tBar(p) //@rename(\"Foo\", \"Baz\", FooToBaz)\n-- @FooToBaz/instances/func.go --\n@@ -3,2 +3,2 @@\n-func Foo[P any](p P) { //@rename(\"Foo\", \"Bar\", FooToBar)\n-\tFoo(p) //@rename(\"Foo\", \"Baz\", FooToBaz)\n+func Baz[P any](p P) { //@rename(\"Foo\", \"Bar\", FooToBar)\n+\tBaz(p) //@rename(\"Foo\", \"Baz\", FooToBaz)\n-- @RTor/instances/type.go --\n@@ -3,2 +3,2 @@\n-type R[P any] struct { //@rename(\"R\", \"u\", Rtou)\n-\tNext *R[P] //@rename(\"R\", \"s\", RTos)\n+type r[P any] struct { //@rename(\"R\", \"u\", Rtou)\n+\tNext *r[P] //@rename(\"R\", \"s\", RTos)\n@@ -7,2 +7,2 @@\n-func (rv R[P]) Do(R[P]) R[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n-\tvar x R[P]\n+func (rv r[P]) Do(r[P]) r[P] { //@rename(\"Do\", \"Do1\", DoToDo1)\n+\tvar x r[P]\n@@ -13 +13 @@\n-\tvar x R[int] //@rename(\"R\", \"r\", RTor)\n+\tvar x r[int] //@rename(\"R\", \"r\", RTor)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/generics_basic.txt",
    "content": "This test exercise basic renaming of generic code.\n\n-- embedded.go --\npackage a\n\ntype foo[P any] int //@rename(\"foo\", \"bar\", fooTobar)\n\nvar x struct{ foo[int] }\n\nvar _ = x.foo\n\n-- @fooTobar/embedded.go --\n@@ -3 +3 @@\n-type foo[P any] int //@rename(\"foo\", \"bar\", fooTobar)\n+type bar[P any] int //@rename(\"foo\", \"bar\", fooTobar)\n@@ -5 +5 @@\n-var x struct{ foo[int] }\n+var x struct{ bar[int] }\n@@ -7 +7 @@\n-var _ = x.foo\n+var _ = x.bar\n-- generics.go --\npackage a\n\ntype G[P any] struct {\n\tF int\n}\n\nfunc (G[_]) M() {}\n\nfunc F[P any](P) {\n\tvar p P //@rename(\"P\", \"Q\", PToQ)\n\t_ = p\n}\n\nfunc _() {\n\tvar x G[int] //@rename(\"G\", \"H\", GToH)\n\t_ = x.F      //@rename(\"F\", \"K\", FToK)\n\tx.M()        //@rename(\"M\", \"N\", MToN)\n\n\tvar y G[string]\n\t_ = y.F\n\ty.M()\n}\n\n-- @FToK/generics.go --\n@@ -4 +4 @@\n-\tF int\n+\tK int\n@@ -16 +16 @@\n-\t_ = x.F      //@rename(\"F\", \"K\", FToK)\n+\t_ = x.K      //@rename(\"F\", \"K\", FToK)\n@@ -20 +20 @@\n-\t_ = y.F\n+\t_ = y.K\n-- @GToH/generics.go --\n@@ -3 +3 @@\n-type G[P any] struct {\n+type H[P any] struct {\n@@ -7 +7 @@\n-func (G[_]) M() {}\n+func (H[_]) M() {}\n@@ -15 +15 @@\n-\tvar x G[int] //@rename(\"G\", \"H\", GToH)\n+\tvar x H[int] //@rename(\"G\", \"H\", GToH)\n@@ -19 +19 @@\n-\tvar y G[string]\n+\tvar y H[string]\n-- @MToN/generics.go --\n@@ -7 +7 @@\n-func (G[_]) M() {}\n+func (G[_]) N() {}\n@@ -17 +17 @@\n-\tx.M()        //@rename(\"M\", \"N\", MToN)\n+\tx.N()        //@rename(\"M\", \"N\", MToN)\n@@ -21 +21 @@\n-\ty.M()\n+\ty.N()\n-- @PToQ/generics.go --\n@@ -9,2 +9,2 @@\n-func F[P any](P) {\n-\tvar p P //@rename(\"P\", \"Q\", PToQ)\n+func F[Q any](Q) {\n+\tvar p Q //@rename(\"P\", \"Q\", PToQ)\n-- unions.go --\npackage a\n\ntype T string //@rename(\"T\", \"R\", TToR)\n\ntype C interface {\n\tT | ~int //@rename(\"T\", \"S\", TToS)\n}\n\n-- @TToR/unions.go --\n@@ -3 +3 @@\n-type T string //@rename(\"T\", \"R\", TToR)\n+type R string //@rename(\"T\", \"R\", TToR)\n@@ -6 +6 @@\n-\tT | ~int //@rename(\"T\", \"S\", TToS)\n+\tR | ~int //@rename(\"T\", \"S\", TToS)\n-- @TToS/unions.go --\n@@ -3 +3 @@\n-type T string //@rename(\"T\", \"R\", TToR)\n+type S string //@rename(\"T\", \"R\", TToR)\n@@ -6 +6 @@\n-\tT | ~int //@rename(\"T\", \"S\", TToS)\n+\tS | ~int //@rename(\"T\", \"S\", TToS)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue39614.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- p.go --\npackage issue39614\n\nfunc fn() {\n\tvar foo bool //@rename(\"foo\", \"bar\", fooTobar)\n\tmake(map[string]bool\n\tif true {\n\t}\n}\n\n-- @fooTobar/p.go --\n@@ -4 +4 @@\n-\tvar foo bool //@rename(\"foo\", \"bar\", fooTobar)\n+\tvar bar bool //@rename(\"foo\", \"bar\", fooTobar)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue42134.txt",
    "content": "Regression test for #42134,\n\"rename fails to update doc comment for local variable of function type\"\n\n-- 1.go --\npackage issue42134\n\nfunc _() {\n\t// foo computes things.\n\tfoo := func() {}\n\n\tfoo() //@rename(\"foo\", \"bar\", fooTobar)\n}\n-- @fooTobar/1.go --\n@@ -4,2 +4,2 @@\n-\t// foo computes things.\n-\tfoo := func() {}\n+\t// bar computes things.\n+\tbar := func() {}\n@@ -7 +7 @@\n-\tfoo() //@rename(\"foo\", \"bar\", fooTobar)\n+\tbar() //@rename(\"foo\", \"bar\", fooTobar)\n-- 2.go --\npackage issue42134\n\nimport \"fmt\"\n\nfunc _() {\n\t// minNumber is a min number.\n\t// Second line.\n\tminNumber := min(1, 2)\n\tfmt.Println(minNumber) //@rename(\"minNumber\", \"res\", minNumberTores)\n}\n\nfunc min(a, b int) int { return a + b }\n-- @minNumberTores/2.go --\n@@ -6 +6 @@\n-\t// minNumber is a min number.\n+\t// res is a min number.\n@@ -8,2 +8,2 @@\n-\tminNumber := min(1, 2)\n-\tfmt.Println(minNumber) //@rename(\"minNumber\", \"res\", minNumberTores)\n+\tres := min(1, 2)\n+\tfmt.Println(res) //@rename(\"minNumber\", \"res\", minNumberTores)\n-- 3.go --\npackage issue42134\n\nfunc _() {\n\t/*\n\ttests contains test cases\n\t*/\n\ttests := []struct { //@rename(\"tests\", \"testCases\", testsTotestCases)\n\t\tin, out string\n\t}{}\n\t_ = tests\n}\n-- @testsTotestCases/3.go --\n@@ -5 +5 @@\n-\ttests contains test cases\n+\ttestCases contains test cases\n@@ -7 +7 @@\n-\ttests := []struct { //@rename(\"tests\", \"testCases\", testsTotestCases)\n+\ttestCases := []struct { //@rename(\"tests\", \"testCases\", testsTotestCases)\n@@ -10 +10 @@\n-\t_ = tests\n+\t_ = testCases\n-- 4.go --\npackage issue42134\n\nfunc _() {\n\t// a is equal to 5. Comment must stay the same\n\n\ta := 5\n\t_ = a //@rename(\"a\", \"b\", aTob)\n}\n-- @aTob/4.go --\n@@ -6,2 +6,2 @@\n-\ta := 5\n-\t_ = a //@rename(\"a\", \"b\", aTob)\n+\tb := 5\n+\t_ = b //@rename(\"a\", \"b\", aTob)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue42301.txt",
    "content": "This test verifies the fix for golang/go#42301: renaming an ident inside its doc\ncomment should also rename the ident.\n\n-- go.mod --\nmodule example.com\n\ngo 1.21\n-- a/a.go --\npackage a\n\n// Foo doesn't do anything, Foo is just an empty function. //@rename(re\"()Foo\", \"Bar\", fooToBar), renameerr(re\"()anything\", \"Bar\", \"no identifier found\")\nfunc Foo() {}\n\nfunc _() {\n\tFoo()\n}\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\n\nfunc _() {\n\ta.Foo()\n}\n\n-- c/c.go --\npackage c\n\n// A is an empty struct. //@rename(re\"()A\", \"B\", aToB)\ntype A struct {}\n\n-- d/d.go --\npackage d\n\n// Bar doesn't do anything, Bar is just an empty function. //@rename(re\", ()Bar\", \"Foo\", barToFoo)\nfunc Bar() {}\n\n-- @aToB/c/c.go --\n@@ -3,2 +3,2 @@\n-// A is an empty struct. //@rename(re\"()A\", \"B\", aToB)\n-type A struct {}\n+// B is an empty struct. //@rename(re\"()B\", \"B\", aToB)\n+type B struct {}\n-- @barToFoo/d/d.go --\n@@ -3,2 +3,2 @@\n-// Bar doesn't do anything, Bar is just an empty function. //@rename(re\", ()Bar\", \"Foo\", barToFoo)\n-func Bar() {}\n+// Foo doesn't do anything, Foo is just an empty function. //@rename(re\", ()Foo\", \"Foo\", barToFoo)\n+func Foo() {}\n-- @fooToBar/a/a.go --\n@@ -3,2 +3,2 @@\n-// Foo doesn't do anything, Foo is just an empty function. //@rename(re\"()Foo\", \"Bar\", fooToBar), renameerr(re\"()anything\", \"Bar\", \"no identifier found\")\n-func Foo() {}\n+// Bar doesn't do anything, Bar is just an empty function. //@rename(re\"()Bar\", \"Bar\", fooToBar), renameerr(re\"()anything\", \"Bar\", \"no identifier found\")\n+func Bar() {}\n@@ -7 +7 @@\n-\tFoo()\n+\tBar()\n-- @fooToBar/b/b.go --\n@@ -6 +6 @@\n-\ta.Foo()\n+\ta.Bar()\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue43616.txt",
    "content": "This test verifies the fix for golang/go#43616: renaming mishandles embedded\nfields.\n\n-- p.go --\npackage issue43616\n\ntype foo int //@rename(\"foo\", \"bar\", fooToBar),preparerename(\"oo\",\"foo\",span=\"foo\")\n\nvar x struct{ foo } //@rename(\"foo\", \"baz\", fooToBaz)\n\nvar _ = x.foo //@renameerr(\"foo\", \"quux\", \"must be renamed at its declaration\")\n-- @fooToBar/p.go --\n@@ -3 +3 @@\n-type foo int //@rename(\"foo\", \"bar\", fooToBar),preparerename(\"oo\",\"foo\",span=\"foo\")\n+type bar int //@rename(\"foo\", \"bar\", fooToBar),preparerename(\"oo\",\"foo\",span=\"foo\")\n@@ -5 +5 @@\n-var x struct{ foo } //@rename(\"foo\", \"baz\", fooToBaz)\n+var x struct{ bar } //@rename(\"foo\", \"baz\", fooToBaz)\n@@ -7 +7 @@\n-var _ = x.foo //@renameerr(\"foo\", \"quux\", \"must be renamed at its declaration\")\n+var _ = x.bar //@renameerr(\"foo\", \"quux\", \"must be renamed at its declaration\")\n-- @fooToBaz/p.go --\n@@ -3 +3 @@\n-type foo int //@rename(\"foo\", \"bar\", fooToBar),preparerename(\"oo\",\"foo\",span=\"foo\")\n+type baz int //@rename(\"foo\", \"bar\", fooToBar),preparerename(\"oo\",\"foo\",span=\"foo\")\n@@ -5 +5 @@\n-var x struct{ foo } //@rename(\"foo\", \"baz\", fooToBaz)\n+var x struct{ baz } //@rename(\"foo\", \"baz\", fooToBaz)\n@@ -7 +7 @@\n-var _ = x.foo //@renameerr(\"foo\", \"quux\", \"must be renamed at its declaration\")\n+var _ = x.baz //@renameerr(\"foo\", \"quux\", \"must be renamed at its declaration\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue57479.txt",
    "content": "Test renaming a parameter to the name of an imported package\nreferenced by one of the function parameters.\n\nSee golang/go#57479\n\n-- go.mod --\nmodule golang.org/lsptests/rename\n\ngo 1.18\n-- a/a.go --\npackage a\n\nimport (\n    \"fmt\"\n    \"math\"\n)\n\nfunc _(x fmt.Stringer) {} //@rename(\"x\", \"fmt\", xToFmt)\n\nfunc _(x int, y fmt.Stringer) {} //@rename(\"x\", \"fmt\", xyToFmt)\n\nfunc _(x [math.MaxInt]bool) {} //@rename(\"x\", \"math\", xToMath)\n-- @xToFmt/a/a.go --\n@@ -8 +8 @@\n-func _(x fmt.Stringer) {} //@rename(\"x\", \"fmt\", xToFmt)\n+func _(fmt fmt.Stringer) {} //@rename(\"x\", \"fmt\", xToFmt)\n-- @xToMath/a/a.go --\n@@ -12 +12 @@\n-func _(x [math.MaxInt]bool) {} //@rename(\"x\", \"math\", xToMath)\n+func _(math [math.MaxInt]bool) {} //@rename(\"x\", \"math\", xToMath)\n-- @xyToFmt/a/a.go --\n@@ -10 +10 @@\n-func _(x int, y fmt.Stringer) {} //@rename(\"x\", \"fmt\", xyToFmt)\n+func _(fmt int, y fmt.Stringer) {} //@rename(\"x\", \"fmt\", xyToFmt)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue60752.txt",
    "content": "\nThis test renames a receiver, type parameter, parameter or result var\nwhose name matches a package-level decl. Prior to go1.22, this used to\ncause a spurious shadowing error because of an edge case in the\nbehavior of types.Scope for function parameters and results.\n\nThis is a regression test for issue #60752, a bug in the type checker.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/type.go --\npackage a\n\ntype t int\n\n-- a/recv.go --\npackage a\n\nfunc (v t) _() {} //@ rename(\"v\", \"t\", recv)\n\n-- a/param.go --\npackage a\n\nfunc _(v t) {} //@ rename(\"v\", \"t\", param)\n\n-- a/result.go --\npackage a\n\nfunc _() (v t) { return } //@ rename(\"v\", \"t\", result)\n\n-- a/typeparam.go --\npackage a\n\nfunc _[v t]() {} //@ renameerr(\"v\", \"t\", re\"would shadow (.|\\n)*type.go:3:6\")\n\n-- b/b.go --\npackage b\n\nimport _ \"example.com/a\"\n\n-- @param/a/param.go --\n@@ -3 +3 @@\n-func _(v t) {} //@ rename(\"v\", \"t\", param)\n+func _(t t) {} //@ rename(\"v\", \"t\", param)\n-- @recv/a/recv.go --\n@@ -3 +3 @@\n-func (v t) _() {} //@ rename(\"v\", \"t\", recv)\n+func (t t) _() {} //@ rename(\"v\", \"t\", recv)\n-- @result/a/result.go --\n@@ -3 +3 @@\n-func _() (v t) { return } //@ rename(\"v\", \"t\", result)\n+func _() (t t) { return } //@ rename(\"v\", \"t\", result)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue60789.txt",
    "content": "\nThis test renames an exported method of an unexported type,\nwhich is an edge case for objectpath, since it computes a path\nfrom a syntax package that is no good when applied to an\nexport data package.\n\nSee issue #60789.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype unexported int\nfunc (unexported) F() {} //@rename(\"F\", \"G\", fToG)\n\nvar _ = unexported(0).F\n\n-- b/b.go --\npackage b\n\n// The existence of this package is sufficient to exercise\n// the bug even though it cannot reference a.unexported.\n\nimport _ \"example.com/a\"\n\n-- @fToG/a/a.go --\n@@ -4 +4 @@\n-func (unexported) F() {} //@rename(\"F\", \"G\", fToG)\n+func (unexported) G() {} //@rename(\"F\", \"G\", fToG)\n@@ -6 +6 @@\n-var _ = unexported(0).F\n+var _ = unexported(0).G\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue61294.txt",
    "content": "\nThis test renames a parameter var whose name is the same as a\npackage-level var, which revealed a bug in isLocal.\n\nThis is a regression test for issue #61294.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc One()\n\nfunc Two(One int) //@rename(\"One\", \"Three\", OneToThree)\n\n-- b/b.go --\npackage b\n\nimport _ \"example.com/a\"\n\n-- @OneToThree/a/a.go --\n@@ -5 +5 @@\n-func Two(One int) //@rename(\"One\", \"Three\", OneToThree)\n+func Two(Three int) //@rename(\"One\", \"Three\", OneToThree)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue61640.txt",
    "content": "This test verifies that gopls can rename instantiated fields.\n\n-- a.go --\npackage a\n\n// This file is adapted from the example in the issue.\n\ntype builder[S ~[]int] struct {\n\telements S //@rename(\"elements\", \"elements2\", OneToTwo)\n}\n\ntype BuilderImpl[S ~[]int] struct{ builder[S] }\n\nfunc NewBuilderImpl[S ~[]int](name string)  *BuilderImpl[S] {\n  impl := &BuilderImpl[S]{\n\tbuilder[S]{\n\t  elements: S{},\n\t},\n  }\n\n  _ = impl.elements\n  return impl\n}\n-- @OneToTwo/a.go --\n@@ -6 +6 @@\n-\telements S //@rename(\"elements\", \"elements2\", OneToTwo)\n+\telements2 S //@rename(\"elements\", \"elements2\", OneToTwo)\n@@ -14 +14 @@\n-\t  elements: S{},\n+\t  elements2: S{},\n@@ -18 +18 @@\n-  _ = impl.elements\n+  _ = impl.elements2\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue61813.txt",
    "content": "This test exercises the panic reported in golang/go#61813.\n\n-- p.go --\npackage p\n\ntype P struct{}\n\nfunc (P) M() {} //@rename(\"M\", \"N\", MToN)\n\nvar _ = []*P{{}}\n-- @MToN/p.go --\n@@ -5 +5 @@\n-func (P) M() {} //@rename(\"M\", \"N\", MToN)\n+func (P) N() {} //@rename(\"M\", \"N\", MToN)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue65098.txt",
    "content": "This is a test for issue 65098: a renaming in package a does not\npropagate to package b, even though the two packages are coupled via\nan assignment in c, which is renamed.\n\n     c\n    / \\\n   a   b\n\nThe bug (a dup of #58461) is not yet fixed, so the golden file records\nthe wrong behavior (i.e. no changes to package b).\nTODO(adonovan): fix.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype I interface {\n\tF() //@ rename(\"F\", \"FF\", fToFF)\n}\n\n-- b/b.go --\npackage b\n\ntype S struct{}\n\nfunc (s S) F() {}\n\n-- c/c.go --\npackage c\n\nimport (\n\t\"example.com/a\"\n\t\"example.com/b\"\n)\n\nvar _ a.I = b.S{}\nvar _ = a.I.F\n\n-- @fToFF/a/a.go --\n@@ -4 +4 @@\n-\tF() //@ rename(\"F\", \"FF\", fToFF)\n+\tFF() //@ rename(\"F\", \"FF\", fToFF)\n-- @fToFF/c/c.go --\n@@ -9 +9 @@\n-var _ = a.I.F\n+var _ = a.I.FF\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue67069.txt",
    "content": "This test verifies spurious pkgname conflicts.\nIssue golang/go#67069.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- go.mod --\nmodule example\ngo 1.19\n\n-- aa/a.go --\npackage aa\n\nvar cc int //@rename(\"cc\", \"aa\", CToA)\nconst C = 0\nconst D = 0\n\n-- aa/a_test.go --\npackage aa_test\n\nimport \"example/aa\"\n\nvar _ = aa.C //@rename(\"aa\", \"bb\", AToB)\n-- @CToA/aa/a.go --\n@@ -3 +3 @@\n-var cc int //@rename(\"cc\", \"aa\", CToA)\n+var aa int //@rename(\"cc\", \"aa\", CToA)\n-- @AToB/aa/a_test.go --\n@@ -3 +3 @@\n-import \"example/aa\"\n+import bb \"example/aa\"\n@@ -5 +5 @@\n-var _ = aa.C //@rename(\"aa\", \"bb\", AToB)\n+var _ = bb.C //@rename(\"aa\", \"bb\", AToB)\n-- bb/b.go --\npackage bb\n\nimport \"example/aa\"\n\nvar _ = aa.C\nvar bb int //@renameerr(\"bb\", \"aa\", errImportConflict)\n\n-- @errImportConflict --\nbb/b.go:6:5: renaming this var \"bb\" to \"aa\" would conflict\nbb/b.go:3:8:\twith this imported package name\n-- aa/a_internal_test.go --\npackage aa\n\nvar _ = D //@rename(\"D\", \"aa\", DToA)\n-- @DToA/aa/a_internal_test.go --\n@@ -3 +3 @@\n-var _ = D //@rename(\"D\", \"aa\", DToA)\n+var _ = aa //@rename(\"D\", \"aa\", DToA)\n-- @DToA/aa/a.go --\n@@ -5 +5 @@\n-const D = 0\n+const aa = 0\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/issue70968.txt",
    "content": "Test that an (ill-typed) redeclaration of a name, which causes\ntypes.Info.Defs to lack an entry, doesn't lead to gopls to crash in\nrenaming. Now, it proceeds with a partial rename.\n\nSee golang/go#70968\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype T int               //@ diag(\"T\", re\"T redeclared\")\ntype T struct { f int }  //@ diag(\"T\", re\"T redeclared\"), rename(\"f\", \"g\", out)\n\n-- @out/a/a.go --\n@@ -4 +4 @@\n-type T struct { f int }  //@ diag(\"T\", re\"T redeclared\"), rename(\"f\", \"g\", out)\n+type T struct { g int }  //@ diag(\"T\", re\"T redeclared\"), rename(\"f\", \"g\", out)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/methods.txt",
    "content": "This test exercises renaming of interface methods.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\ntype A int\n\nfunc (A) F() {} //@renameerr(\"F\", \"G\", errAfToG)\n\n-- b/b.go --\npackage b\n\nimport \"example.com/a\"\nimport \"example.com/c\"\n\ntype B interface { F() } //@rename(\"F\", \"G\", BfToG)\n\nvar _ B = a.A(0)\nvar _ B = c.C(0)\n\nvar _ = B.F\n\n-- c/c.go --\npackage c\n\ntype C int\n\nfunc (C) F() {} //@renameerr(\"F\", \"G\", errCfToG)\n\n-- d/d.go --\npackage d\n\nimport \"example.com/b\"\n\nvar _ = b.B.F\n\n-- @errAfToG --\na/a.go:5:10: renaming this method \"F\" to \"G\"\nb/b.go:6:6:\twould make example.com/a.A no longer assignable to interface B\nb/b.go:6:20:\t(rename example.com/b.B.F if you intend to change both types)\n-- @BfToG/b/b.go --\n@@ -6 +6 @@\n-type B interface { F() } //@rename(\"F\", \"G\", BfToG)\n+type B interface { G() } //@rename(\"F\", \"G\", BfToG)\n@@ -11 +11 @@\n-var _ = B.F\n+var _ = B.G\n-- @BfToG/d/d.go --\n@@ -5 +5 @@\n-var _ = b.B.F\n+var _ = b.B.G\n-- @errCfToG --\nc/c.go:5:10: renaming this method \"F\" to \"G\"\nb/b.go:6:6:\twould make example.com/c.C no longer assignable to interface B\nb/b.go:6:20:\t(rename example.com/b.B.F if you intend to change both types)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/packagedecl.txt",
    "content": "This test verifies the behavior of renaming a package declaration when package move is enabled.\nIt tests the following:\n- Invalid renames:\n\t- Moving across a module boundary\n\t- Moving to a package that already exists\n\n- Renames edge cases:\n\t- Naming collisions\n\t- Renaming to internal package\n\t\t- Not allowed when there is some importer of the package to be moved\n\t\tthat is not in the internal package\n\t- Impact of renaming on _test packages\n\t- Renaming with the exact same path - no edits produced\n\n-- flags --\n-ignore_extra_diags\n\n-- go.work --\nuse .\nuse ./othermoddir\n\n-- go.mod --\nmodule golang.org/lsptests/rename\n\nreplace golang.org/lsptests/six/four => ./six/four\n\ngo 1.20\n-- one/one.go --\npackage one //@ rename(\"one\", \"golang.org/lsptests/rename/one\", sameName), rename(\"one\", \"golang.org/lsptests/rename/two\", newNameSameDir), renameerr(\"one\", \"golang.org/lsptests/otherdir/one\", re\"cannot move package across module boundary\")\n\n-- three/three.go --\npackage three //@ renameerr(\"three\", \"golang.org/lsptests/othermod/three\", re\"cannot move package across module boundary\"), renameerr(\"three\", \"golang.org/lsptests/rename/one\", re\"not empty\")\n\n\n-- six/six.go --\npackage six //@ renameerr(\"six\", \"golang.org/lsptests/rename/$$$\", re\"invalid package name\")\n\nimport \"golang.org/lsptests/rename/six/four\"\n\nfunc Foo() {\n\tfour.Bar()\n}\n\n-- six/four/four.go --\npackage four //@ rename(\"four\", \"golang.org/lsptests/rename/five\", moveUpOneDir), renameerr(\"four\", \"../relative\", re\"specifying relative paths in package rename not yet supported\")\n\nfunc Bar() {}\n\n-- seven/seven/seven.go --\npackage seven\n\nimport\n(\n\t\"golang.org/lsptests/rename/six/four\"\n\tfive \"golang.org/lsptests/rename/six\"\n)\n\nfunc foo() {\n\tfour.Bar()\n}\n\n-- importsnine/importsnine.go --\npackage importsnine //@ rename(\"importsnine\", \"golang.org/lsptests/rename/nine/internal/importsnine\", allowedInternal) // only importers of this package are already in the internal package, so okay to move it\n\nimport (\n\t\"golang.org/lsptests/rename/nine/nine/nine\"\n)\n\n-- nine/nine/nine/nine.go --\npackage nine //@ renameerr(\"nine\", \"golang.org/lsptests/rename/nine/internal/nine\", re\"package move would result in illegal internal import\")\n\n-- nine/internal/helpers.go --\npackage internal\n\nimport \"golang.org/lsptests/rename/importsnine\"\n\n-- seven/eight/eight.go --\npackage eight //@ rename(\"eight\", \"golang.org/lsptests/rename/six/eight\", differentDir), rename(\"eight\", \"golang.org/lsptests/rename/nine/nine/nine/eight\", moveDownTwoDirs)\n-- fix/fix.go --\npackage fix //@ rename(\"fix\", \"golang.org/lsptests/rename/newFix\", renameWithTestPkg)\n\nimport (\n\t\"golang.org/lsptests/rename/seven/eight\"\n\t)\n\n-- seven/eight/other/other.go --\npackage other //@ rename(\"other\", \"golang.org/lsptests/rename/seven/eight/other/newDir1/newDir2\", createNewDir)\n\n-- seven/eight/other/newDir1/newDir2/newDir3/test.go --\npackage newDir3 // verifies that we can move the package above into a directory that already exists but is empty\n\n-- fix/fix_test.go --\npackage fix_test\n-- othermoddir/othermod/other.go --\npackage othermod\n\nimport \"golang.org/lsptests/rename/nine/nine/nine\"\n\n\n-- othermoddir/go.mod --\nmodule mod.com/other\n\n-- foo/windows.go --\n//go:build windows\npackage foo\n\n-- foo/default.go --\n//go:build !windows\npackage foo //@ renameerr(\"foo\", \"golang.org/lsptests/rename/foo2\", re\"ignored files\")\n\n-- bar/bar.go --\npackage foobar //@ renameerr(\"foobar\", \"golang.org/lsptests/rename/otherpath\", re\"does not match directory base name\")\n\n-- @moveDownTwoDirs/nine/nine/nine/eight/eight.go --\n@@ -0,0 +1 @@\n+package eight //@ rename(\"eight\", \"golang.org/lsptests/rename/six/eight\", differentDir), rename(\"eight\", \"golang.org/lsptests/rename/nine/nine/nine/eight\", moveDownTwoDirs)\n-- @moveDownTwoDirs/seven/eight/eight.go --\n@@ -1 +0,0 @@\n-package eight //@ rename(\"eight\", \"golang.org/lsptests/rename/six/eight\", differentDir), rename(\"eight\", \"golang.org/lsptests/rename/nine/nine/nine/eight\", moveDownTwoDirs)\n-- @moveUpOneDir/five/four.go --\n@@ -0,0 +1,4 @@\n+package five //@ rename(\"four\", \"golang.org/lsptests/rename/five\", moveUpOneDir), renameerr(\"four\", \"../relative\", re\"specifying relative paths in package rename not yet supported\")\n+\n+func Bar() {}\n+\n-- @moveUpOneDir/six/four/four.go --\n@@ -1,4 +0,0 @@\n-package four //@ rename(\"four\", \"golang.org/lsptests/rename/five\", moveUpOneDir), renameerr(\"four\", \"../relative\", re\"specifying relative paths in package rename not yet supported\")\n-\n-func Bar() {}\n-\n-- @moveUpOneDir/seven/seven/seven.go --\n@@ -5 +5 @@\n-\t\"golang.org/lsptests/rename/six/four\"\n+\tfive1 \"golang.org/lsptests/rename/five\"\n@@ -10 +10 @@\n-\tfour.Bar()\n+\tfive1.Bar()\n-- @newNameSameDir/one/one.go --\n@@ -1,2 +0,0 @@\n-package one //@ rename(\"one\", \"golang.org/lsptests/rename/one\", sameName), rename(\"one\", \"golang.org/lsptests/rename/two\", newNameSameDir), renameerr(\"one\", \"golang.org/lsptests/otherdir/one\", re\"cannot move package across module boundary\")\n-\n-- @newNameSameDir/two/one.go --\n@@ -0,0 +1,2 @@\n+package two //@ rename(\"one\", \"golang.org/lsptests/rename/one\", sameName), rename(\"one\", \"golang.org/lsptests/rename/two\", newNameSameDir), renameerr(\"one\", \"golang.org/lsptests/otherdir/one\", re\"cannot move package across module boundary\")\n+\n-- @sameName/one/one.go --\n-- @moveUpOneDir/six/six.go --\n@@ -3 +3 @@\n-import \"golang.org/lsptests/rename/six/four\"\n+import \"golang.org/lsptests/rename/five\"\n@@ -6 +6 @@\n-\tfour.Bar()\n+\tfive.Bar()\n-- @moveUpOneDir/go.mod --\n@@ -3 +3 @@\n-replace golang.org/lsptests/six/four => ./six/four\n+replace golang.org/lsptests/six/four => ./five\n-- @differentDir/seven/eight/eight.go --\n@@ -1 +0,0 @@\n-package eight //@ rename(\"eight\", \"golang.org/lsptests/rename/six/eight\", differentDir), rename(\"eight\", \"golang.org/lsptests/rename/nine/nine/nine/eight\", moveDownTwoDirs)\n-- @differentDir/six/eight/eight.go --\n@@ -0,0 +1 @@\n+package eight //@ rename(\"eight\", \"golang.org/lsptests/rename/six/eight\", differentDir), rename(\"eight\", \"golang.org/lsptests/rename/nine/nine/nine/eight\", moveDownTwoDirs)\n-- @differentDir/fix/fix.go --\n@@ -4 +4 @@\n-\t\"golang.org/lsptests/rename/seven/eight\"\n+\t\"golang.org/lsptests/rename/six/eight\"\n-- @moveDownTwoDirs/fix/fix.go --\n@@ -4 +4 @@\n-\t\"golang.org/lsptests/rename/seven/eight\"\n+\t\"golang.org/lsptests/rename/nine/nine/nine/eight\"\n-- @allowedInternal/importsnine/importsnine.go --\n@@ -1,6 +0,0 @@\n-package importsnine //@ rename(\"importsnine\", \"golang.org/lsptests/rename/nine/internal/importsnine\", allowedInternal) // only importers of this package are already in the internal package, so okay to move it\n-\n-import (\n-\t\"golang.org/lsptests/rename/nine/nine/nine\"\n-)\n-\n-- @allowedInternal/nine/internal/helpers.go --\n@@ -3 +3 @@\n-import \"golang.org/lsptests/rename/importsnine\"\n+import \"golang.org/lsptests/rename/nine/internal/importsnine\"\n-- @allowedInternal/nine/internal/importsnine/importsnine.go --\n@@ -0,0 +1,6 @@\n+package importsnine //@ rename(\"importsnine\", \"golang.org/lsptests/rename/nine/internal/importsnine\", allowedInternal) // only importers of this package are already in the internal package, so okay to move it\n+\n+import (\n+\t\"golang.org/lsptests/rename/nine/nine/nine\"\n+)\n+\n-- @renameWithTestPkg/fix/fix.go --\n@@ -1,6 +0,0 @@\n-package fix //@ rename(\"fix\", \"golang.org/lsptests/rename/newFix\", renameWithTestPkg)\n-\n-import (\n-\t\"golang.org/lsptests/rename/seven/eight\"\n-\t)\n-\n-- @renameWithTestPkg/fix/fix_test.go --\n@@ -1 +0,0 @@\n-package fix_test\n-- @renameWithTestPkg/newFix/fix.go --\n@@ -0,0 +1,6 @@\n+package newFix //@ rename(\"fix\", \"golang.org/lsptests/rename/newFix\", renameWithTestPkg)\n+\n+import (\n+\t\"golang.org/lsptests/rename/seven/eight\"\n+\t)\n+\n-- @renameWithTestPkg/newFix/fix_test.go --\n@@ -0,0 +1 @@\n+package newFix_test\n-- @createNewDir/seven/eight/other/other.go --\n@@ -1,2 +0,0 @@\n-package other //@ rename(\"other\", \"golang.org/lsptests/rename/seven/eight/other/newDir1/newDir2\", createNewDir)\n-\n-- @createNewDir/seven/eight/other/newDir1/newDir2/other.go --\n@@ -0,0 +1,2 @@\n+package newDir2 //@ rename(\"other\", \"golang.org/lsptests/rename/seven/eight/other/newDir1/newDir2\", createNewDir)\n+\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/pkgpath.txt",
    "content": "Test of PkgName renaming initiated over ImportSpec.Path.\n\n-- go.mod --\nmodule example.com\n\n-- a/a.go --\npackage a\n\nimport \"example.com/b\" //@rename(\"b\", \"c\", bToc)\n\nvar _ = b.B\n\n-- a/a2.go --\npackage a\n\nimport b \"example.com/b\" //@rename(re\"/(b)\", \"c\", bToc2)\n\nvar _ = b.B\n\n-- b/b.go --\npackage b\n\nconst B = 0\n\n-- @bToc/a/a.go --\n@@ -3 +3 @@\n-import \"example.com/b\" //@rename(\"b\", \"c\", bToc)\n+import c \"example.com/b\" //@rename(\"b\", \"c\", bToc)\n@@ -5 +5 @@\n-var _ = b.B\n+var _ = c.B\n-- @bToc2/a/a2.go --\n@@ -3 +3 @@\n-import b \"example.com/b\" //@rename(re\"/(b)\", \"c\", bToc2)\n+import c \"example.com/b\" //@rename(re\"/(b)\", \"c\", bToc2)\n@@ -5 +5 @@\n-var _ = b.B\n+var _ = c.B\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/prepare.txt",
    "content": "This test verifies the behavior of textDocument/prepareRename.\n\n-- settings.json --\n{\n\t\"deepCompletion\": false\n}\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n-- types/types.go --\npackage types\n\ntype CoolAlias = int //@item(CoolAlias, \"CoolAlias\", \"int\", \"type\")\n\ntype X struct { //@item(X_struct, \"X\", \"struct{...}\", \"struct\")\n\tx int\n}\n\ntype Y struct { //@item(Y_struct, \"Y\", \"struct{...}\", \"struct\")\n\ty int\n}\n\n\ntype Bob interface { //@item(Bob_interface, \"Bob\", \"interface{...}\", \"interface\")\n\tBobby()\n}\n\nfunc (*X) Bobby() {}\nfunc (*Y) Bobby() {}\n\n-- good/good0.go --\npackage good\n\nvar _ = stuff\n\nfunc stuff() { //@item(good_stuff, \"stuff\", \"func()\", \"func\"),preparerename(\"stu\", \"stuff\", span=\"stuff\")\n\tx := 5\n\trandom2(x) //@preparerename(\"dom\", \"random2\", span=\"random2\")\n}\n\n-- good/good1.go --\npackage good\n\nimport (\n\t\"golang.org/lsptests/types\" //@item(types_import, \"types\", \"\\\"golang.org/lsptests/types\\\"\", \"package\")\n)\n\nvar _ = random\n\nfunc random() int { //@item(good_random, \"random\", \"func() int\", \"func\")\n\t_ = \"random() int\" //@preparerename(\"random\", \"\")\n\ty := 6 + 7         //@preparerename(\"7\", \"\")\n\treturn y           //@preparerename(\"return\", \"\", span=\"\")\n}\n\nfunc random2(y int) int { //@item(good_random2, \"random2\", \"func(y int) int\", \"func\"),item(good_y_param, \"y\", \"int\", \"var\")\n\t//@complete(\"\", good_y_param, types_import, good_random, good_random2, good_stuff)\n\tvar b types.Bob = &types.X{}   //@preparerename(\"ypes\",\"types\", span=\"types\")\n\tif _, ok := b.(*types.X); ok { //@complete(re\"()X\", X_struct, Y_struct, Bob_interface, CoolAlias)\n\t\t_ = 0 // suppress \"empty branch\" diagnostic\n\t}\n\n\treturn y\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/prepare_func.txt",
    "content": "This test verifies the behavior of textDocument/prepareRename on function declarations.\n\n-- settings.json --\n{\n\t\"deepCompletion\": false\n}\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- main.go --\npackage main\n\nfunc _(i int) //@ preparerename(\"unc\", \"func(i int)\", span=\"func\")\n\nfunc _(i int) //@ preparerename(\"func\", \"func(i int)\")\n\nfunc _(a, b int) //@ preparerename(\"func\", \"func(a, b int)\")\n\nfunc _(a, _ int) //@ preparerename(\"func\", \"func(a, _0 int)\")\n\nfunc _(a, _, _ int) //@ preparerename(\"func\", \"func(a, _0, _1 int)\")\n\nfunc _(a, _, _, d int, _ string) //@ preparerename(\"func\", \"func(a, _0, _1, d int, _2 string)\")\n\nfunc _(a int, b string) //@ preparerename(\"func\", \"func(a int, b string)\")\n\nfunc _(a int, b ...string) //@ preparerename(\"func\", \"func(a int, b ...string)\")\n\nfunc _(a int, b string) error //@ preparerename(\"func\", \"func(a int, b string) error\")\n\nfunc _(a int, b string) (int, error) //@ preparerename(\"func\", \"func(a int, b string) (int, error)\")\n\nfunc _( //@ preparerename(\"func\", \"func(a int, b string)\")\n  a int,\n\tb string,\n)\n\nfunc _( //@ preparerename(\"func\", \"func(a int, b string) (int, error)\")\n  a int,\n\tb string,\n) (int, error)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/prepare_move.txt",
    "content": "This test verifies the behavior of textDocument/prepareRename - we prompt with the full package path.\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.20\n\n-- b/b.go --\npackage b //@ preparerename(\"b\", \"golang.org/lsptests/b\")\n\n-- a/other.go --\n// We prompt with the full package path, but changing a package directory is disabled when the package name does not match its directory base name. \npackage other //@ preparerename(\"other\", \"golang.org/lsptests/a\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/random.txt",
    "content": "This test ports some \"random\" rename tests from the old marker tests.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests/rename\n\ngo 1.18\n-- a/a.go --\npackage a\n\nimport (\n\tlg \"log\"\n\t\"fmt\" //@rename(\"fmt\", \"fmty\", fmtTofmty)\n\tf2 \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n)\n\nfunc Random() int {\n\ty := 6 + 7\n\treturn y\n}\n\nfunc Random2(y int) int { //@rename(\"y\", \"z\", yToz)\n\treturn y\n}\n\ntype Pos struct {\n\tx, y int\n}\n\nfunc (p *Pos) Sum() int {\n\treturn p.x + p.y //@rename(\"x\", \"myX\", xTomyX)\n}\n\nfunc _() {\n\tvar p Pos   //@rename(\"p\", \"pos\", pTopos)\n\t_ = p.Sum() //@rename(\"Sum\", \"GetSum\", SumToGetSum)\n}\n\nfunc sw() {\n\tvar x any\n\n\tswitch y := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n\tcase int:\n\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n\tcase string:\n\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n\tdefault:\n\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n\t}\n}\n-- @SumToGetSum/a/a.go --\n@@ -22 +22 @@\n-func (p *Pos) Sum() int {\n+func (p *Pos) GetSum() int {\n@@ -28 +28 @@\n-\t_ = p.Sum() //@rename(\"Sum\", \"GetSum\", SumToGetSum)\n+\t_ = p.GetSum() //@rename(\"Sum\", \"GetSum\", SumToGetSum)\n-- @f2Tof2name/a/a.go --\n@@ -6 +6 @@\n-\tf2 \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n+\tf2name \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2name.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @f2Tofmt2/a/a.go --\n@@ -6 +6 @@\n-\tf2 \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n+\tfmt2 \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tfmt2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @fmtTof2y/a/a.go --\n@@ -6 +6 @@\n-\tf2 \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n+\tf2y \"fmt\" //@rename(\"f2\", \"f2name\", f2Tof2name),rename(\"fmt\", \"f2y\", fmtTof2y)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2y.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @fmtTofmty/a/a.go --\n@@ -5 +5 @@\n-\t\"fmt\" //@rename(\"fmt\", \"fmty\", fmtTofmty)\n+\tfmty \"fmt\" //@rename(\"fmt\", \"fmty\", fmtTofmty)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tfmty.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n-- @fmtToformat/a/a.go --\n@@ -5 +5 @@\n-\t\"fmt\" //@rename(\"fmt\", \"fmty\", fmtTofmty)\n+\tformat \"fmt\" //@rename(\"fmt\", \"fmty\", fmtTofmty)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tformat.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n-- @lgTolog/a/a.go --\n@@ -4 +4 @@\n-\tlg \"log\"\n+\t\"log\"\n@@ -38 +38 @@\n-\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n+\t\tlog.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n-- @pTopos/a/a.go --\n@@ -27,2 +27,2 @@\n-\tvar p Pos   //@rename(\"p\", \"pos\", pTopos)\n-\t_ = p.Sum() //@rename(\"Sum\", \"GetSum\", SumToGetSum)\n+\tvar pos Pos   //@rename(\"p\", \"pos\", pTopos)\n+\t_ = pos.Sum() //@rename(\"Sum\", \"GetSum\", SumToGetSum)\n-- @xTomyX/a/a.go --\n@@ -19 +19 @@\n-\tx, y int\n+\tmyX, y int\n@@ -23 +23 @@\n-\treturn p.x + p.y //@rename(\"x\", \"myX\", xTomyX)\n+\treturn p.myX + p.y //@rename(\"x\", \"myX\", xTomyX)\n-- @yToy0/a/a.go --\n@@ -34 +34 @@\n-\tswitch y := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n+\tswitch y0 := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tfmt.Printf(\"%d\", y0) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n@@ -38 +38 @@\n-\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n+\t\tlg.Printf(\"%s\", y0) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2.Printf(\"%v\", y0) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @yToy1/a/a.go --\n@@ -34 +34 @@\n-\tswitch y := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n+\tswitch y1 := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tfmt.Printf(\"%d\", y1) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n@@ -38 +38 @@\n-\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n+\t\tlg.Printf(\"%s\", y1) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2.Printf(\"%v\", y1) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @yToy2/a/a.go --\n@@ -34 +34 @@\n-\tswitch y := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n+\tswitch y2 := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tfmt.Printf(\"%d\", y2) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n@@ -38 +38 @@\n-\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n+\t\tlg.Printf(\"%s\", y2) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2.Printf(\"%v\", y2) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @yToy3/a/a.go --\n@@ -34 +34 @@\n-\tswitch y := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n+\tswitch y3 := x.(type) { //@rename(\"y\", \"y0\", yToy0)\n@@ -36 +36 @@\n-\t\tfmt.Printf(\"%d\", y) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n+\t\tfmt.Printf(\"%d\", y3) //@rename(\"y\", \"y1\", yToy1),rename(\"fmt\", \"format\", fmtToformat)\n@@ -38 +38 @@\n-\t\tlg.Printf(\"%s\", y) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n+\t\tlg.Printf(\"%s\", y3) //@rename(\"y\", \"y2\", yToy2),rename(\"lg\", \"log\", lgTolog)\n@@ -40 +40 @@\n-\t\tf2.Printf(\"%v\", y) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n+\t\tf2.Printf(\"%v\", y3) //@rename(\"y\", \"y3\", yToy3),rename(\"f2\", \"fmt2\", f2Tofmt2)\n-- @yToz/a/a.go --\n@@ -14,2 +14,2 @@\n-func Random2(y int) int { //@rename(\"y\", \"z\", yToz)\n-\treturn y\n+func Random2(z int) int { //@rename(\"y\", \"z\", yToz)\n+\treturn z\n-- b/b.go --\npackage b\n\nvar c int //@renameerr(\"int\", \"uint\", re\"cannot be renamed\")\n\nfunc _() {\n\ta := 1 //@rename(\"a\", \"error\", aToerror)\n\ta = 2\n\t_ = a\n}\n\nvar (\n\t// Hello there.\n\t// Foo does the thing.\n\tFoo int //@rename(\"Foo\", \"Bob\", FooToBob)\n)\n\n/*\nHello description\n*/\nfunc Hello() {} //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n\n-- c/c.go --\npackage c\n\nimport \"golang.org/lsptests/rename/b\"\n\nfunc _() {\n\tb.Hello() //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n}\n\n-- c/c2.go --\npackage c\n\n//go:embed Static/*\nvar Static embed.FS //@rename(\"Static\", \"static\", StaticTostatic)\n\n-- @FooToBob/b/b.go --\n@@ -13,2 +13,2 @@\n-\t// Foo does the thing.\n-\tFoo int //@rename(\"Foo\", \"Bob\", FooToBob)\n+\t// Bob does the thing.\n+\tBob int //@rename(\"Foo\", \"Bob\", FooToBob)\n-- @HelloToGoodbye/b/b.go --\n@@ -18 +18 @@\n-Hello description\n+Goodbye description\n@@ -20 +20 @@\n-func Hello() {} //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n+func Goodbye() {} //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n-- @aToerror/b/b.go --\n@@ -6,3 +6,3 @@\n-\ta := 1 //@rename(\"a\", \"error\", aToerror)\n-\ta = 2\n-\t_ = a\n+\terror := 1 //@rename(\"a\", \"error\", aToerror)\n+\terror = 2\n+\t_ = error\n-- @HelloToGoodbye/c/c.go --\n@@ -6 +6 @@\n-\tb.Hello() //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n+\tb.Goodbye() //@rename(\"Hello\", \"Goodbye\", HelloToGoodbye)\n-- @StaticTostatic/c/c2.go --\n@@ -4 +4 @@\n-var Static embed.FS //@rename(\"Static\", \"static\", StaticTostatic)\n+var static embed.FS //@rename(\"Static\", \"static\", StaticTostatic)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/recv.txt",
    "content": "This test exercises renaming of method receivers (golang/go#41892).\n\nNotes:\n- x to print fails for A.J because it would shadow the built-in print;\n  that renaming is quietly skipped.\n- various combinations of named, aliases, and pointers are tested.\n- package b exercises generics.\n- renaming a receiver declaration causes the broader renaming;\n  renaming a receiver use (see vrefz) effects only a local renaming.\n\n-- a/a.go --\npackage a\n\ntype T int\ntype A = T\n\nfunc (T) F()   {}\nfunc (t T) G() {} //@rename(\"t\", \"x\", tx)\nfunc (U T) H() {} //@rename(\"U\", \"v\", Uv)\nfunc (_ T) I() {}\nfunc (v A) J() { print(-v) } //@rename(re\"-(v)\", \"z\", vrefz)\nfunc (w *T) K() {}\nfunc (x *A) L() {} //@rename(\"x\", \"print\", xprint)\n\n-- @tx/a/a.go --\n@@ -7,2 +7,2 @@\n-func (t T) G() {} //@rename(\"t\", \"x\", tx)\n-func (U T) H() {} //@rename(\"U\", \"v\", Uv)\n+func (x T) G() {} //@rename(\"t\", \"x\", tx)\n+func (x T) H() {} //@rename(\"U\", \"v\", Uv)\n@@ -10,2 +10,2 @@\n-func (v A) J() { print(-v) } //@rename(re\"-(v)\", \"z\", vrefz)\n-func (w *T) K() {}\n+func (x A) J() { print(-x) } //@rename(re\"-(v)\", \"z\", vrefz)\n+func (x *T) K() {}\n-- @Uv/a/a.go --\n@@ -7,2 +7,2 @@\n-func (t T) G() {} //@rename(\"t\", \"x\", tx)\n-func (U T) H() {} //@rename(\"U\", \"v\", Uv)\n+func (v T) G() {} //@rename(\"t\", \"x\", tx)\n+func (v T) H() {} //@rename(\"U\", \"v\", Uv)\n@@ -11,2 +11,2 @@\n-func (w *T) K() {}\n-func (x *A) L() {} //@rename(\"x\", \"print\", xprint)\n+func (v *T) K() {}\n+func (v *A) L() {} //@rename(\"x\", \"print\", xprint)\n-- @xprint/a/a.go --\n@@ -7,2 +7,2 @@\n-func (t T) G() {} //@rename(\"t\", \"x\", tx)\n-func (U T) H() {} //@rename(\"U\", \"v\", Uv)\n+func (print T) G() {} //@rename(\"t\", \"x\", tx)\n+func (print T) H() {} //@rename(\"U\", \"v\", Uv)\n@@ -11,2 +11,2 @@\n-func (w *T) K() {}\n-func (x *A) L() {} //@rename(\"x\", \"print\", xprint)\n+func (print *T) K() {}\n+func (print *A) L() {} //@rename(\"x\", \"print\", xprint)\n-- @vrefz/a/a.go --\n@@ -10 +10 @@\n-func (v A) J() { print(-v) } //@rename(re\"-(v)\", \"z\", vrefz)\n+func (z A) J() { print(-z) } //@rename(re\"-(v)\", \"z\", vrefz)\n-- b/b.go --\npackage b\n\ntype C[T any] int\nfunc (r C[T]) F() {} //@rename(\"r\", \"c\", rc)\nfunc (r C[T]) G() {}\n\n-- @rc/b/b.go --\n@@ -4,2 +4,2 @@\n-func (r C[T]) F() {} //@rename(\"r\", \"c\", rc)\n-func (r C[T]) G() {}\n+func (c C[T]) F() {} //@rename(\"r\", \"c\", rc)\n+func (c C[T]) G() {}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/shadow.txt",
    "content": "\n-- shadow.go --\npackage shadow\n\nfunc _() {\n\ta := true\n\tb, c, _ := A(), B(), D() //@renameerr(\"A\", \"a\", re\"shadowed\"),rename(\"B\", \"b\", BTob),renameerr(\"b\", \"c\", re\"conflict\"),rename(\"D\", \"d\", DTod)\n\td := false\n\t_, _, _, _ = a, b, c, d\n}\n\nfunc A() int {\n\treturn 0\n}\n\nfunc B() int {\n\treturn 0\n}\n\nfunc D() int {\n\treturn 0\n}\n-- @BTob/shadow.go --\n@@ -5 +5 @@\n-\tb, c, _ := A(), B(), D() //@renameerr(\"A\", \"a\", re\"shadowed\"),rename(\"B\", \"b\", BTob),renameerr(\"b\", \"c\", re\"conflict\"),rename(\"D\", \"d\", DTod)\n+\tb, c, _ := A(), b(), D() //@renameerr(\"A\", \"a\", re\"shadowed\"),rename(\"B\", \"b\", BTob),renameerr(\"b\", \"c\", re\"conflict\"),rename(\"D\", \"d\", DTod)\n@@ -14 +14 @@\n-func B() int {\n+func b() int {\n-- @DTod/shadow.go --\n@@ -5 +5 @@\n-\tb, c, _ := A(), B(), D() //@renameerr(\"A\", \"a\", re\"shadowed\"),rename(\"B\", \"b\", BTob),renameerr(\"b\", \"c\", re\"conflict\"),rename(\"D\", \"d\", DTod)\n+\tb, c, _ := A(), B(), d() //@renameerr(\"A\", \"a\", re\"shadowed\"),rename(\"B\", \"b\", BTob),renameerr(\"b\", \"c\", re\"conflict\"),rename(\"D\", \"d\", DTod)\n@@ -18 +18 @@\n-func D() int {\n+func d() int {\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/testy.txt",
    "content": "\n-- flags --\n-ignore_extra_diags\n\n-- testy.go --\npackage testy\n\ntype tt int //@rename(\"tt\", \"testyType\", ttTotestyType)\n\nfunc a() {\n\tfoo := 42 //@rename(\"foo\", \"bar\", fooTobar)\n}\n-- testy_test.go --\npackage testy\n\nimport \"testing\"\n\nfunc TestSomething(t *testing.T) {\n\tvar x int //@rename(\"x\", \"testyX\", xTotestyX)\n\ta()       //@rename(\"a\", \"b\", aTob)\n}\n-- @aTob/testy.go --\n@@ -5 +5 @@\n-func a() {\n+func b() {\n-- @aTob/testy_test.go --\n@@ -7 +7 @@\n-\ta()       //@rename(\"a\", \"b\", aTob)\n+\tb()       //@rename(\"a\", \"b\", aTob)\n-- @fooTobar/testy.go --\n@@ -6 +6 @@\n-\tfoo := 42 //@rename(\"foo\", \"bar\", fooTobar)\n+\tbar := 42 //@rename(\"foo\", \"bar\", fooTobar)\n-- @ttTotestyType/testy.go --\n@@ -3 +3 @@\n-type tt int //@rename(\"tt\", \"testyType\", ttTotestyType)\n+type testyType int //@rename(\"tt\", \"testyType\", ttTotestyType)\n-- @xTotestyX/testy_test.go --\n@@ -6 +6 @@\n-\tvar x int //@rename(\"x\", \"testyX\", xTotestyX)\n+\tvar testyX int //@rename(\"x\", \"testyX\", xTotestyX)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/typeswitch.txt",
    "content": "This test covers the special case of renaming a type switch var.\n\n-- p.go --\npackage p\n\nfunc _(x any) {\n\tswitch y := x.(type) { //@rename(\"y\", \"z\", yToZ)\n\tcase string:\n\t\tprint(y) //@rename(\"y\", \"z\", yToZ)\n\tdefault:\n\t\tprint(y) //@rename(\"y\", \"z\", yToZ)\n\t}\n}\n\n-- @yToZ/p.go --\n@@ -4 +4 @@\n-\tswitch y := x.(type) { //@rename(\"y\", \"z\", yToZ)\n+\tswitch z := x.(type) { //@rename(\"y\", \"z\", yToZ)\n@@ -6 +6 @@\n-\t\tprint(y) //@rename(\"y\", \"z\", yToZ)\n+\t\tprint(z) //@rename(\"y\", \"z\", yToZ)\n@@ -8 +8 @@\n-\t\tprint(y) //@rename(\"y\", \"z\", yToZ)\n+\t\tprint(z) //@rename(\"y\", \"z\", yToZ)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/rename/unexported.txt",
    "content": "\nThis test attempts to rename a.S.X to x, which would make it\ninaccessible from its external test package. The rename tool\nshould report an error rather than wrecking the program.\nSee issue #59403.\n\n-- go.mod --\nmodule example.com\ngo 1.12\n\n-- a/a.go --\npackage a\n\nvar S struct{ X int } //@renameerr(\"X\", \"x\", oops)\n\n-- a/a_test.go --\npackage a_test\n\nimport \"example.com/a\"\n\nvar Y = a.S.X\n\n-- @oops --\na/a.go:3:15: renaming \"X\" to \"x\" would make it unexported\na/a_test.go:5:13:\tbreaking references from packages such as \"example.com/a_test\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/selectionrange/selectionrange.txt",
    "content": "This test checks selection range functionality.\n\n-- foo.go --\npackage foo\n\nimport \"time\"\n\nfunc Bar(x, y int, t time.Time) int {\n\tzs := []int{1, 2, 3} //@selectionrange(\"1\", a)\n\n\tfor _, z := range zs {\n\t\tx = x + z + y + zs[1] //@selectionrange(\"1\", b)\n\t}\n\n\treturn x + y //@selectionrange(\"+\", c)\n}\n-- @a --\nRanges 0:\n\t5:13-5:14 \"1\"\n\t5:7-5:21 \"[]int{1, 2, 3}\"\n\t5:1-5:21 \"zs := []int{1, 2, 3}\"\n\t4:36-12:1 \"{\\\\n\\tzs := []int{...range(\\\"+\\\", c)\\\\n}\"\n\t4:0-12:1 \"func Bar(x, y i...range(\\\"+\\\", c)\\\\n}\"\n\t0:0-12:1 \"package foo\\\\n\\\\nim...range(\\\"+\\\", c)\\\\n}\"\n-- @b --\nRanges 0:\n\t8:21-8:22 \"1\"\n\t8:18-8:23 \"zs[1]\"\n\t8:6-8:23 \"x + z + y + zs[1]\"\n\t8:2-8:23 \"x = x + z + y + zs[1]\"\n\t7:22-9:2 \"{\\\\n\\t\\tx = x + z +...ange(\\\"1\\\", b)\\\\n\\t}\"\n\t7:1-9:2 \"for _, z := ran...ange(\\\"1\\\", b)\\\\n\\t}\"\n\t4:36-12:1 \"{\\\\n\\tzs := []int{...range(\\\"+\\\", c)\\\\n}\"\n\t4:0-12:1 \"func Bar(x, y i...range(\\\"+\\\", c)\\\\n}\"\n\t0:0-12:1 \"package foo\\\\n\\\\nim...range(\\\"+\\\", c)\\\\n}\"\n-- @c --\nRanges 0:\n\t11:8-11:13 \"x + y\"\n\t11:1-11:13 \"return x + y\"\n\t4:36-12:1 \"{\\\\n\\tzs := []int{...range(\\\"+\\\", c)\\\\n}\"\n\t4:0-12:1 \"func Bar(x, y i...range(\\\"+\\\", c)\\\\n}\"\n\t0:0-12:1 \"package foo\\\\n\\\\nim...range(\\\"+\\\", c)\\\\n}\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/signature/generic.txt",
    "content": "This test checks signature help on generic signatures.\n\n-- g.go --\npackage g\n\ntype M[K comparable, V any] map[K]V\n\n// golang/go#61189: signatureHelp must handle pointer receivers.\nfunc (m *M[K, V]) Get(k K) V {\n\treturn (*m)[k]\n}\n\nfunc Get[K comparable, V any](m M[K, V], k K) V {\n\treturn m[k]\n}\n\nfunc _() {\n\tvar m M[int, string]\n\t_ = m.Get(0)  //@signature(\"(\", \"Get(k int) string\", -1)\n\t_ = Get(m, 0) //@signature(\"0\", \"Get(m M[int, string], k int) string\", 1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/signature/issue63804.txt",
    "content": "Regression test for #63804: conversion to built-in type caused panic.\n\nthe server's Signature method never returns an actual error,\nso the best we can assert is that there is no result.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nvar _ = int(123) //@signature(\"123\", \"\", 0)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/signature/issue69552.txt",
    "content": "Regression test for #69552: panic in activeParam of a builtin, when requesting\nsignature help outside of the argument list.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\t_ = len([]int{}) //@signature(\"en\", \"len(v Type) int\", -1)\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/signature/signature.txt",
    "content": "This test exercises basic tests for signature help.\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule golang.org/lsptests\n\ngo 1.18\n\n-- signature/signature.go --\n// Package signature has tests for signature help.\npackage signature\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"math/big\"\n\t\"fmt\"\n)\n\nfunc Foo(a string, b int) (c bool) {\n\treturn\n}\n\nfunc Bar(float64, ...byte) {\n}\n\nfunc FooArr(a []int) {\n\n}\n\nfunc NoArgs() {\n}\n\ntype myStruct struct{}\n\ntype Bar struct {\n\tA, B, C, D string\n}\n\nfunc (*myStruct) foo(e *json.Decoder) (*big.Int, error) {\n\treturn nil, nil\n}\n\ntype MyType struct{}\n\ntype MyFunc func(foo int) string\n\ntype Alias = int\ntype OtherAlias = int\ntype StringAlias = string\n\nfunc AliasSlice(a []*Alias) (b Alias)                                 { return 0 }\nfunc AliasMap(a map[*Alias]StringAlias) (b, c map[*Alias]StringAlias) { return nil, nil }\nfunc OtherAliasMap(a, b map[Alias]OtherAlias) map[Alias]OtherAlias    { return nil }\n\nfunc Qux() {\n\tFoo(\"foo\", 123) //@signature(re\"()\\\\(\", \"Foo(a string, b int) (c bool)\", -1)\n\tFoo(\"foo\", 123) //@signature(re\"()123\", \"Foo(a string, b int) (c bool)\", 1)\n\tFoo(\"foo\", 123) //@signature(re\"(),\", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo(\"foo\", 123) //@signature(re\"() 1\", \"Foo(a string, b int) (c bool)\", 1)\n\tFoo(\"foo\", 123) //@signature(re\"()\\\\)\", \"Foo(a string, b int) (c bool)\", 1)\n\tFoo(\"foo\", 123) //@signature(re\"()o\", \"Foo(a string, b int) (c bool)\", -1)\n\t_ = Foo //@signature(re\"()o\", \"Foo(a string, b int) (c bool)\", -1)\n\tFoo //@signature(re\"()o\", \"Foo(a string, b int) (c bool)\", -1)\n\tFoo() //@signature(re\"()\\\\(\", \"Foo(a string, b int) (c bool)\", -1)\n\n\tBar(13.37, 0x13)       //@signature(re\"()13.37\", \"Bar(float64, ...byte)\", 0)\n\tBar(13.37, 0x37)       //@signature(re\"()0x37\", \"Bar(float64, ...byte)\", 1)\n\tBar(13.37, 1, 2, 3, 4) //@signature(re\"()4\", \"Bar(float64, ...byte)\", 1)\n\n\tNoArgs() //@signature(re\"()\\\\(\", \"NoArgs()\", -1)\n\tNoArgs //@signature(re\"()s\", \"NoArgs()\", -1)\n\n\tfn := func(hi, there string) func(i int) rune {\n\t\treturn func(int) rune { return 0 }\n\t}\n\n\tfn(\"hi\", \"there\")    //@signature(re\"()hi\", \"\", 0)\n\tfn(\"hi\", \"there\")    //@signature(re\"(),\", \"fn(hi string, there string) func(i int) rune\", 0)\n\tfn(\"hi\", \"there\")(1) //@signature(re\"()1\", \"func(i int) rune\", 0)\n\n\tfnPtr := &fn\n\t(*fnPtr)(\"hi\", \"there\") //@signature(re\"(),\", \"func(hi string, there string) func(i int) rune\", 0)\n\n\tvar fnIntf any = Foo\n\tfnIntf.(func(string, int) bool)(\"hi\", 123) //@signature(re\"()123\", \"func(string, int) bool\", 1)\n\n\t(&bytes.Buffer{}).Next(2) //@signature(re\"()2\", \"Next(n int) []byte\", 0)\n\n\tmyFunc := MyFunc(func(n int) string { return \"\" })\n\tmyFunc(123) //@signature(re\"()123\", \"myFunc(foo int) string\", 0)\n\n\tvar ms myStruct\n\tms.foo(nil) //@signature(re\"()nil\", \"foo(e *json.Decoder) (*big.Int, error)\", 0)\n\n\t_ = make([]int, 1, 2) //@signature(re\"()2\", \"make(t Type, size ...int) Type\", 1)\n\n\tFoo(myFunc(123), 456) //@signature(re\"()o\\\\(\", \"Foo(a string, b int) (c bool)\", -1)\n\tFoo(myFunc(123), 456) //@signature(re\"()\\\\(m\", \"Foo(a string, b int) (c bool)\", -1)\n\tFoo( myFunc(123), 456) //@signature(re\"() m\", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo(myFunc(123), 456) //@signature(re\"(), \", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo(myFunc(123), 456) //@signature(re\"()456\", \"Foo(a string, b int) (c bool)\", 1)\n\tFoo(myFunc) //@signature(re\"()\\\\)\", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo(myFunc(123), 456) //@signature(re\"()\\\\(1\", \"myFunc(foo int) string\", -1)\n\tFoo(myFunc(123), 456) //@signature(re\"()123\", \"myFunc(foo int) string\", 0)\n\n\tfmt.Println //@signature(re\"()ln\", \"Println(a ...any) (n int, err error)\", -1)\n\tfmt.Println(myFunc) //@signature(re\"()ln\", \"Println(a ...any) (n int, err error)\", -1)\n\tfmt.Println(myFunc) //@signature(re\"()Func\", \"myFunc(foo int) string\", -1)\n\n\tvar hi string = \"hello\"\n\tvar wl string = \" world: %s\"\n\tfmt.Println(fmt.Sprintf(wl, myFunc)) //@signature(re\"()Func\", \"myFunc(foo int) string\", -1)\n\tfmt.Println(fmt.Sprintf(wl, myFunc)) //@signature(re\"()wl\", \"Sprintf(format string, a ...any) string\", 0)\n\tfmt.Println(fmt.Sprintf(wl, myFunc)) //@signature(re\"() m\", \"Sprintf(format string, a ...any) string\", 1)\n\tfmt.Println(hi, fmt.Sprintf(wl, myFunc)) //@signature(re\"()Sprint\", \"Sprintf(format string, a ...any) string\", -1)\n\tfmt.Println(hi, fmt.Sprintf(wl, myFunc)) //@signature(re\"() fmt\", \"Println(a ...any) (n int, err error)\", 0)\n\tfmt.Println(hi, fmt.Sprintf(wl, myFunc)) //@signature(re\"()hi\", \"Println(a ...any) (n int, err error)\", 0)\n\n\tpanic(\"oops!\")            //@signature(re\"()\\\\)\", \"panic(v any)\", 0)\n\tprintln(\"hello\", \"world\") //@signature(re\"(),\", \"println(args ...Type)\", 0)\n\n\tHello(func() {\n\t\t//@signature(re\"()\\\\/\\\\/\", \"\", 0)\n\t})\n\n\tAliasSlice()    //@signature(re\"()\\\\)\", \"AliasSlice(a []*Alias) (b Alias)\", 0)\n\tAliasMap()      //@signature(re\"()\\\\)\", \"AliasMap(a map[*Alias]StringAlias) (b map[*Alias]StringAlias, c map[*Alias]StringAlias)\", 0)\n\tOtherAliasMap() //@signature(re\"()\\\\)\", \"OtherAliasMap(a map[Alias]OtherAlias, b map[Alias]OtherAlias) map[Alias]OtherAlias\", 0)\n\n\tvar l []Foo\n\tl = append(l, Foo{ //@signature(re\"(),\", \"append(slice []Type, elems ...Type) []Type\", 0)\n\t\tA: \"hello\", //@signature(re\"(),\", \"\", 0)\n\t\tB: \"world\", //@signature(re\"(),\", \"\", 0)\n\t})\n\n\tFooArr([]int{1, 2, 3, 4, 5}) //@signature(re\"()1\", \"\", 0)\n}\n\nfunc Hello(func()) {}\n\n-- signature/signature2.go --\npackage signature\n\nfunc _() {\n\tFoo(//@signature(re\"()\\\\/\\\\/\", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo.//@signature(re\"()\\\\/\\\\/\", \"Foo(a string, b int) (c bool)\", 0)\n\tFoo.//@signature(re\"()oo\", \"Foo(a string, b int) (c bool)\", 0)\n}\n\n-- signature/signature3.go --\npackage signature\n\nfunc _() {\n\tFoo(\"hello\",//@signature(re\"()\\\\/\\\\/\", \"Foo(a string, b int) (c bool)\", 1)\n}\n\n-- signature/nonsignature.go --\npackage signature\n\nvar x = (1) //@signature(re\"()1\\\\)\", \"\", 0)\n\n-- signature/signature_test.go --\npackage signature_test\n\nimport (\n\t\"testing\"\n\n\tsig \"golang.org/lsptests/signature\"\n)\n\nfunc TestSignature(t *testing.T) {\n\tsig.AliasSlice()    //@signature(re\"()\\\\)\", \"AliasSlice(a []*sig.Alias) (b sig.Alias)\", 0)\n\tsig.AliasMap()      //@signature(re\"()\\\\)\", \"AliasMap(a map[*sig.Alias]sig.StringAlias) (b map[*sig.Alias]sig.StringAlias, c map[*sig.Alias]sig.StringAlias)\", 0)\n\tsig.OtherAliasMap() //@signature(re\"()\\\\)\", \"OtherAliasMap(a map[sig.Alias]sig.OtherAlias, b map[sig.Alias]sig.OtherAlias) map[sig.Alias]sig.OtherAlias\", 0)\n}\n\n-- snippets/snippets.go --\npackage snippets\n\nimport (\n\t\"golang.org/lsptests/signature\"\n)\n\ntype CoolAlias = int //@item(CoolAlias, \"CoolAlias\", \"int\", \"type\")\n\ntype structy struct {\n\tx signature.MyType\n}\n\nfunc X(_ map[signature.Alias]CoolAlias) (map[signature.Alias]CoolAlias) {\n\treturn nil\n}\n\nfunc _() {\n\tX() //@signature(re\"()\\\\)\", \"X(_ map[signature.Alias]CoolAlias) map[signature.Alias]CoolAlias\", 0)\n\t_ = signature.MyType{} //@item(literalMyType, \"signature.MyType{}\", \"\", \"var\")\n\ts := structy{\n\t\tx: //@snippet(re\"() \\\\/\\\\/\", literalMyType, \"signature.MyType{\\\\}\")\n\t}\n}\n\n-- importedcomplit/importedcomplit.go --\npackage importedcomplit\n\nimport (\n\t// TODO(rfindley): re-enable after moving to new framework\n\t// \"golang.org/lsptests/foo\"\n\n\t// import completions (separate blocks to avoid comment alignment)\n\t\"crypto/elli\" //@complete(re\"i()\\\"\", cryptoImport)\n\n\t\"fm\" //@complete(re\"m()\\\"\", fmtImport)\n\n\t\"go/pars\" //@complete(re\"s()\\\"\", parserImport)\n\n\tnamedParser \"go/pars\" //@complete(re\"s()\\\"\", parserImport)\n\n\t\"golang.org/lspte\" //@complete(re\"e()\\\"\", lsptestsImport)\n\n\t\"golang.org/lsptests/sign\" //@complete(re\"n()\\\"\", signatureImport)\n\n\t\"golang.org/lsptests/sign\" //@complete(re\"()ests\", lsptestsImport)\n\n\t\"golang.org/lsptests/signa\" //@complete(re\"()na\", signatureImport)\n)\n\nfunc _() {\n\tvar V int //@item(icVVar, \"V\", \"int\", \"var\")\n\n\t// TODO(rfindley): re-enable after moving to new framework\n\t// _ = foo.StructFoo{V} // complete(\"}\", Value, icVVar)\n}\n\nfunc _() {\n\tvar (\n\t\taa string //@item(icAAVar, \"aa\", \"string\", \"var\")\n\t\tab int    //@item(icABVar, \"ab\", \"int\", \"var\")\n\t)\n\n\t// TODO(rfindley): re-enable after moving to new framework\n\t// _ = foo.StructFoo{a} // complete(\"}\", abVar, aaVar)\n\n\tvar s struct {\n\t\tAA string //@item(icFieldAA, \"AA\", \"string\", \"field\")\n\t\tAB int    //@item(icFieldAB, \"AB\", \"int\", \"field\")\n\t}\n\n\t// TODO(rfindley): re-enable after moving to new framework\n\t//_ = foo.StructFoo{s.} // complete(\"}\", icFieldAB, icFieldAA)\n}\n\n/* \"fmt\" */ //@item(fmtImport, \"fmt\", \"\\\"fmt\\\"\", \"package\")\n/* \"go/parser\" */ //@item(parserImport, \"parser\", \"\\\"go/parser\\\"\", \"package\")\n/* \"golang.org/lsptests/signature\" */ //@item(signatureImport, \"signature\", \"\\\"golang.org/lsptests/signature\\\"\", \"package\")\n/* \"golang.org/lsptests/\" */ //@item(lsptestsImport, \"lsptests/\", \"\\\"golang.org/lsptests/\\\"\", \"package\")\n/* \"crypto/elliptic\" */ //@item(cryptoImport, \"elliptic\", \"\\\"crypto/elliptic\\\"\", \"package\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/symbol/basic.txt",
    "content": "Basic tests of textDocument/documentSymbols.\n\n-- settings.json --\n{\"analyses\": {\"unusedfunc\": false}}\n\n-- symbol.go --\npackage main\n\n//@symbol(want)\n\nimport \"io\"\n\nvar _ = 1\n\nvar x = 42\n\nvar nested struct {\n\tnestedField struct {\n\t\tf int\n\t}\n}\n\nconst y = 43\n\ntype Number int\n\ntype Alias = string\n\ntype NumberAlias = Number\n\ntype (\n\tBoolean   bool\n\tBoolAlias = bool\n)\n\ntype Foo struct {\n\tQuux\n\tW         io.Writer\n\tBar       int\n\tbaz       string\n\tfuncField func(int) int\n}\n\ntype Quux struct {\n\tX, Y float64\n}\n\ntype EmptyStruct struct{}\n\nfunc (f Foo) Baz() string {\n\treturn f.baz\n}\n\nfunc _() {}\n\nfunc (q *Quux) Do() {}\n\nfunc main() {\n}\n\ntype Stringer interface {\n\tString() string\n}\n\ntype ABer interface {\n\tB()\n\tA() string\n}\n\ntype WithEmbeddeds interface {\n\tDo()\n\tABer\n\tio.Writer\n}\n\ntype EmptyInterface any\n\nfunc Dunk() int { return 0 }\n\nfunc dunk() {}\n\nvar _ = dunk\n\n-- @want --\n(*Quux).Do \"func()\"\n(Foo).Baz \"func() string\" +2 lines\nABer \"interface{...}\" +3 lines\nABer.A \"func() string\"\nABer.B \"func()\"\nAlias \"string\"\nBoolAlias \"bool\"\nBoolean \"bool\"\nDunk \"func() int\"\nEmptyInterface \"any\"\nEmptyStruct \"struct{}\"\nFoo \"struct{...}\" +6 lines\nFoo.Bar \"int\"\nFoo.Quux \"Quux\"\nFoo.W \"io.Writer\"\nFoo.baz \"string\"\nFoo.funcField \"func(int) int\"\nNumber \"int\"\nNumberAlias \"Number\"\nQuux \"struct{...}\" +2 lines\nQuux.X \"float64\"\nQuux.Y \"float64\"\nStringer \"interface{...}\" +2 lines\nStringer.String \"func() string\"\nWithEmbeddeds \"interface{...}\" +4 lines\nWithEmbeddeds.ABer \"ABer\"\nWithEmbeddeds.Do \"func()\"\nWithEmbeddeds.Writer \"io.Writer\"\ndunk \"func()\"\nmain \"func()\" +1 lines\nnested \"struct{...}\" +4 lines\nnested.nestedField \"struct{...}\" +2 lines\nnested.nestedField.f \"int\"\nx \"\"\ny \"\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/symbol/generic.txt",
    "content": "Basic tests of textDocument/documentSymbols with generics.\n\n-- symbol.go --\n//@symbol(want)\n\npackage main\n\ntype T[P any] struct {\n\tF P\n}\n\ntype Constraint interface {\n\t~int | struct{ int }\n\tinterface{ M() }\n}\n\n-- @want --\nConstraint \"interface{...}\" +3 lines\nConstraint.interface{...} \"\"\nConstraint.interface{...}.M \"func()\"\nConstraint.~int | struct{int} \"\"\nT \"struct{...}\" +2 lines\nT.F \"P\"\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/comment.txt",
    "content": "This test checks the semantic tokens in comments (golang/go#64648).\n\nThere will be doc links in the comments to reference other objects. Parse these\nlinks and output tokens according to the referenced object types, so that the\neditor can highlight them. This will help in checking the doc link errors and\nreading comments in the code.\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- a.go --\npackage p\n\nimport \"strconv\"\n\nconst A = 1\nvar B = 2\n\ntype Foo int\n\n\n// [F] accept a [Foo], and print it. //@token(\"F\", \"function\", \"signature\"),token(\"Foo\", \"type\", \"number\")\nfunc F(v Foo) {\n\tprintln(v)\n\n}\n\n/*\n\t[F1] print [A] and [B] //@token(\"F1\", \"function\", \"signature\"),token(\"A\", \"variable\", \"readonly number\"),token(\"B\", \"variable\", \"static number\")\n*/\nfunc F1() {\n\t// print [A] and [B]. //@token(\"A\", \"variable\", \"readonly number\"),token(\"B\", \"variable\", \"static number\")\n\tprintln(A, B)\n}\n\n// [F2] use [strconv.Atoi] convert s, then print it //@token(\"F2\", \"function\", \"signature\"),token(\"strconv\", \"namespace\", \"\"),token(\"Atoi\", \"function\", \"signature\")\nfunc F2(s string) {\n\ta, _ := strconv.Atoi(\"42\")\n\tb, _ := strconv.Atoi(\"42\")\n\tprintln(a, b)  // this is a tail comment in F2 //hover(F2, \"F2\", F2)\n}\n-- b.go --\npackage p\n\n// [F3] accept [*Foo]\t//@token(\"F3\", \"function\", \"signature\"),token(\"Foo\", \"type\", \"number\")\nfunc F3(v *Foo) {\n\tprintln(*v)\n}\n\n// [F4] equal [strconv.Atoi]\t//@token(\"F4\", \"function\", \"signature\"),token(\"strconv\", \"namespace\", \"\"),token(\"Atoi\", \"function\", \"signature\")\nfunc F4(s string) (int, error) {\n\treturn 0, nil\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/format.txt",
    "content": "This test checks semanticTokens for format string placeholders.\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- format.go --\npackage format\n\nimport \"fmt\"\n\nfunc PrintfTests() {\n\tvar i int\n\tvar x float64\n\tfmt.Printf(\"%b %d %f\", 3, i, x) //@ token(\"%b\", \"string\", \"format\"), token(\"%d\", \"string\", \"format\"),token(\"%f\", \"string\", \"format\"),\n\tfmt.Printf(\"lit1%blit2%dlit3%flit4\", 3, i, x) //@ token(\"%b\", \"string\", \"format\"), token(\"%d\", \"string\", \"format\"),token(\"%f\", \"string\", \"format\"),token(\"lit1\", \"string\", \"\"),token(\"lit2\", \"string\", \"\"),token(\"lit3\", \"string\", \"\"),\n\tfmt.Printf(\"%% %d lit2\", 3, i, x) //@ token(\"%d\", \"string\", \"format\"),token(\"%%\", \"string\", \"\"),token(\"lit2\", \"string\", \"\"),\n\tfmt.Printf(\"Hello %% \\n %s, you \\t%% \\n have %d new m%%essages!\", \"Alice\", 5) //@ token(\"%s\", \"string\", \"format\"),token(\"%d\", \"string\", \"format\")\n\tfmt.Printf(\"%d \\nss \\x25[2]d\", 234, 123) //@ token(\"%d\", \"string\", \"format\"),token(\"\\\\x25[2]d\", \"string\", \"format\")\n\tfmt.Printf(\"start%[2]*.[1]*[3]dmiddle%send\", 4, 5, 6) //@ token(\"%[2]*.[1]*[3]d\", \"string\", \"format\"),token(\"start\", \"string\", \"\"),token(\"%s\", \"string\", \"format\"),token(\"middle\", \"string\", \"\"),token(\"end\", \"string\", \"\")\n}\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/illformed.txt",
    "content": "This test checks semanticTokens on ill-formed code.\n(Regression test for #68205.)\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- a.go --\npackage p\n\ntype _ <-<-chan int //@ token(\"<-\", \"operator\", \"\"), token(\"chan\", \"keyword\", \"\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/issue66809.txt",
    "content": "This is a regression test for #66809 (missing modifiers for\ndeclarations of function-type variables).\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- main.go --\npackage main\n\nfunc main() {\n    foo := func(x string) string { return x }\t//@token(\"foo\", \"variable\", \"definition signature\")\n    _ = foo    \t\t\t\t\t//@token(\"foo\", \"variable\", \"signature\")\n    foo(\"hello\")\t\t\t\t//@token(\"foo\", \"variable\", \"signature\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/issue70251.txt",
    "content": "This is a regression test for #70251 (missing modifiers for\npredeclared interfaces).\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- a/a.go --\npackage a\n\nvar _ any   //@token(\"any\", \"type\", \"defaultLibrary interface\")\nvar _ error //@token(\"error\", \"type\", \"defaultLibrary interface\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/modifiers.txt",
    "content": "This test checks the output of semanticTokens modifiers.\n(including test for #70219.)\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- flags --\n-ignore_extra_diags\n\n-- standard.go --\npackage modifiers\n\nfunc _() {\n\ta, b := false, true //@ token(\"false\", \"variable\", \"readonly defaultLibrary\"), token(\"true\", \"variable\", \"readonly defaultLibrary\")\n}\n\nconst (\n\tc = iota //@ token(\"iota\", \"variable\", \"readonly defaultLibrary number\")\n)\n\n-- custom.go --\npackage modifiers\n\ntype Foo struct{}\n\nfunc _() {\n\tvar array [2]string //@ token(\"array\", \"variable\", \"definition array\")\n\tarray = [2]string{\"\", \"\"} //@ token(\"array\", \"variable\", \"array\")\n\n\tvar b bool //@ token(\"b\", \"variable\", \"definition bool\")\n\tb = true //@ token(\"b\", \"variable\", \"bool\")\n\n\tvar c chan string //@ token(\"c\", \"variable\", \"definition chan\")\n\tc = make(chan string) //@ token(\"c\", \"variable\", \"chan\")\n\n\ttype inter interface{} //@ token(\"inter\", \"type\", \"definition interface\")\n\n\tvar m map[string]string //@ token(\"m\", \"variable\", \"definition map\")\n\tm = make(map[string]string) //@ token(\"m\", \"variable\", \"map\")\n\n\tvar number int //@ token(\"number\", \"variable\", \"definition number\")\n\tnumber = 1 //@ token(\"number\", \"variable\", \"number\")\n\n\tvar ptr *Foo //@ token(\"ptr\", \"variable\", \"definition pointer\")\n\tptr = nil //@ token(\"ptr\", \"variable\", \"pointer\")\n\n\tvar sig func(string) //@ token(\"sig\", \"variable\", \"definition signature\")\n\tsig = nil //@ token(\"sig\", \"variable\", \"signature\")\n\n\tvar slice []string //@ token(\"slice\", \"variable\", \"definition slice\")\n\tslice = nil //@ token(\"slice\", \"variable\", \"slice\")\n\n\tvar str string //@ token(\"str\", \"variable\", \"definition string\")\n\tstr = \"\" //@ token(\"str\", \"variable\", \"string\")\n\n\tvar foo Foo //@ token(\"foo\", \"variable\", \"definition struct\")\n\tfoo = Foo{} //@ token(\"foo\", \"variable\", \"struct\")\n}\n\n// Tests of various types.Var kinds (#77344).\n\ntype T struct {\n\tfield int //@ token(\"field\", \"property\", \"definition number\")\n}\n\nfunc (recv *T) method(param int) (result int) { //@ token(\"recv\", \"parameter\", \"definition pointer\"), token(\"param\", \"parameter\", \"definition number\"), token(\"result\", \"variable\", \"definition number\")\n     var local int //@ token(\"local\", \"variable\", \"definition number\")\n}\n\nvar global int //@ token(\"global\", \"variable\", \"definition static number\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/token/range.txt",
    "content": "This test checks the output of textDocument/semanticTokens/range.\n\nTODO: add more assertions.\n\n-- settings.json --\n{\n\t\"semanticTokens\": true\n}\n\n-- a.go --\npackage p //@token(\"package\", \"keyword\", \"\")\n\nconst C = 42 //@token(\"C\", \"variable\", \"definition readonly number\")\n\nfunc F() { //@token(\"F\", \"function\", \"definition signature\")\n\tx := 2 + 3//@token(\"x\", \"variable\", \"definition number\"),token(\"2\", \"number\", \"\"),token(\"+\", \"operator\", \"\")\n\t_ = x //@token(\"x\", \"variable\", \"number\")\n\t_ = F //@token(\"F\", \"function\", \"signature\")\n}\n\nfunc _() {\n\t// A goto's label cannot be found by ascending the syntax tree.\n\tgoto loop //@ token(\"goto\", \"keyword\", \"\"), token(\"loop\", \"label\", \"\")\n\nloop: //@token(\"loop\", \"label\", \"definition\")\n\tfor {\n\t\tcontinue loop //@ token(\"continue\", \"keyword\", \"\"), token(\"loop\", \"label\", \"\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/typedef/expression.txt",
    "content": "This test checks textDocument/typeDefinition over a range reveals the expression type.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n\n-- a/a.go --\npackage a\n\nimport \"mod.com/b\"\n\nfunc foo() (b.Bar, b.Baz, error) {\n    return b.Bar{}, \"\", nil\n}\n\nfunc main() {\n    _, _, _ = foo()//@typedef(\"foo()\", Bar, Baz, BUILTIN)\n}\n\n-- b/b.go --\npackage b\n\ntype Bar struct {}//@loc(Bar, \"Bar\")\n\ntype Baz string//@loc(Baz, \"Baz\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/typedef/issue60544.txt",
    "content": "Regression test for golang/go#60544.\n\n-- go.mod --\nmodule mod.com\n\ngo 1.19\n-- main.go --\npackage main\n\nfunc F[T comparable]() {}//@typedef(re\"comparable()\", BUILTIN)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/typedef/typedef.txt",
    "content": "This test exercises the textDocument/typeDefinition action.\n\n-- typedef.go --\npackage typedef\n\ntype Struct struct { //@loc(Struct, \"Struct\"),\n\tField string\n}\n\ntype Int int //@loc(Int, \"Int\")\n\nfunc _() {\n\tvar (\n\t\tvalue Struct\n\t\tpoint *Struct\n\t)\n\t_ = value //@typedef(re\"value()\", Struct)\n\t_ = point //@typedef(re\"point()\", Struct)\n\n\tvar (\n\t\tarray   [3]Struct\n\t\tslice   []Struct\n\t\tch      chan Struct\n\t\tcomplex [3]chan *[5][]Int\n\t)\n\t_ = array   //@typedef(re\"array()\", Struct)\n\t_ = slice   //@typedef(re\"slice()\", Struct)\n\t_ = ch      //@typedef(re\"ch()\", Struct)\n\t_ = complex //@typedef(re\"complex()\", Int)\n\n\tvar s struct {\n\t\tx struct {\n\t\t\txx struct {\n\t\t\t\tfield1 []Struct\n\t\t\t\tfield2 []Int\n\t\t\t}\n\t\t}\n\t}\n\t_ = s.x.xx.field1 //@typedef(re\"field1()\", Struct)\n\t_ = s.x.xx.field2 //@typedef(re\"field2()\", Int)\n}\n\n// type def returns function return types' location.\n\nfunc F1() Int                              { return 0 }\nfunc F2() error                            { return nil }\nfunc F3() (Int, float64)                   { return 0, 0 }\nfunc F4() (Int, error)                     { return 0, nil }\nfunc F5() (Struct, int, bool, error)       { return Struct{}, 0, false, nil }\nfunc F6() (**int, Int, bool, *error)       { return nil, 0, false, nil }\nfunc F7() (int, float64, error, Struct)    { return 0, 0, nil, Struct{} }\nfunc F8() (int, float64, ***Struct, error) { return 0, 0, nil, nil }\n\n// type def returns error.\n\nfunc E1() {}\nfunc E2() (int, bool) { return 0, true }\n\nfunc _() {\n\tF1() //@typedef(re\"F1()\", Int)\n\tF2() //@typedef(re\"F2()\", BUILTIN)\n\tF3() //@typedef(re\"F3()\", Int, BUILTIN)\n\tF4() //@typedef(re\"F4()\", Int, BUILTIN)\n\tF5() //@typedef(re\"F5()\", Struct, BUILTIN, BUILTIN, BUILTIN)\n\tF6() //@typedef(re\"F6()\", BUILTIN, Int, BUILTIN, BUILTIN)\n\tF7() //@typedef(re\"F7()\", BUILTIN, BUILTIN, BUILTIN, Struct)\n\tF8() //@typedef(re\"F8()\", BUILTIN, BUILTIN, Struct, BUILTIN)\n\n\tE1() //@typedef(re\"E1()\", err=\"cannot find type name(s)\")\n\tE2() //@typedef(re\"E2()\", BUILTIN, BUILTIN)\n\n\tf := func() Int { return 0 }\n\tf() //@typedef(re\"f()\", Int)\n}\n\n// https://github.com/golang/go/issues/38589#issuecomment-620350922\nfunc _() {\n\ttype myFunc func(int) Int //@loc(myFunc, \"myFunc\")\n\n\tvar foo myFunc\n\t_ = foo() //@typedef(re\"foo()\", myFunc), diag(\")\", re\"not enough arguments\")\n}\n\nfunc _() {\n\t// Any expression is fair game for typeDefinition;\n\t// it needn't be a referring identifier.\n\t// In this example it's the r-paren of a call expr.\n\tfunc() Struct {\n\t\tpanic(0)\n\t}() //@typedef(re\"\\\\)()\", Struct)\n\n\t// And in this one, it's the composite literal enclosing the\n\t// KeyValueExpr denoted by the colon (which must not be adjacent\n\t// to either they key or the value!).\n\t_ = Struct{Field  :  \"\"} //@typedef(re\":\", Struct)\n}\n\n// edge case: type-switch implicits.\n// y in \"switch y\" has no type; use x instead.\nfunc _(x any) {\n\tswitch y := x.(type) { //@typedef(re\"y()\", BUILTIN)\n\tcase Int:\n\t\t_ = y //@typedef(re\"y()\", Int)\n\tcase Struct:\n\t\t_ = y //@typedef(re\"y()\", Struct)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/typehierarchy/basic.txt",
    "content": "Basic test of type hierarchy.\n\nWe pose the same queries across two identical packages to exercise\nthe local and global algorithms.\n\nTODO(adonovan): test other properties of the result, such as kind.\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- a/a.go --\npackage a\n\ntype I interface { F() } //@ loc(I, \"I\")\n\ntype J interface { F(); G() } //@ loc(J, \"J\")\n\ntype S int  //@ loc(S, \"S\")\n\nfunc (S) F() {}\nfunc (S) G() {}\n\n//@subtypes(S)\n//@subtypes(I, J, S, BI, BJ, BS)\n//@subtypes(J, S, BJ, BS)\n\n//@supertypes(S, I, J, BI, BJ)\n//@supertypes(I, BI)\n//@supertypes(J, I, BI, BJ)\n\n-- b/b.go --\npackage b\n\ntype BI interface { F() } //@ loc(BI, \"BI\")\n\ntype BJ interface { F(); G() } //@ loc(BJ, \"BJ\")\n\ntype BS int  //@ loc(BS, \"BS\")\n\nfunc (BS) F() {}\nfunc (BS) G() {}\n\n//@subtypes(BS)\n//@subtypes(BI, BJ, BS, I, J, S)\n//@subtypes(BJ, BS, J, S)\n\n//@supertypes(BS, BI, BJ, I, J)\n//@supertypes(BI, I)\n//@supertypes(BJ, BI, I, J)\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workfile/godebug.txt",
    "content": "This test basic gopls functionality in a workspace with a godebug\ndirective in its modfile.\n\nWe use panicnil from go1.21 as an arbitrary GODEBUG; if it goes away,\npick another from https://go.dev/doc/godebug#history.\n\n-- flags --\n-min_go_command=go1.23\n\n-- a/go.work --\ngo 1.23\n\nuse .\n\ngodebug (\n\tpanicnil=0\n)\ngodebug panicnil=1\n\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.23\n\n-- a/a.go --\npackage a\n\nimport \"example.com/a/b\"\n\nconst A = b.B //@def(\"B\", B)\n\n-- a/b/b.go --\npackage b\n\nconst B = 42 //@loc(B, \"B\")\n\n-- format/go.work --\ngo 1.23 //@format(formatted)\n\nuse .\n\ngodebug (\npanicnil=0\n)\ngodebug     panicnil=1\n\n-- @formatted --\ngo 1.23 //@format(formatted)\n\nuse .\n\ngodebug (\n\tpanicnil=0\n)\n\ngodebug panicnil=1\n-- format/go.mod --\nmodule example.com/format\n\ngo 1.23\n\n-- format/p.go --\npackage format\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workfile/godebug_bad.txt",
    "content": "This test checks that we surface the error for unexpected godebug values.\n\nTODO(golang/go#67623): the diagnostic should be on the bad godebug value.\n\n-- flags --\n-min_go_command=go1.23\n-errors_ok\n\n-- go.work --\ngo 1.23\n\nuse .\n\ngodebug (\n\tpanicnull=0 // misspelled\n)\ngodebug panicnil=1\n\n-- go.mod --\nmodule example.com/m //@diag(\"module\", re`unknown godebug \"panicnull\"`)\n\ngo 1.23\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/allscope.txt",
    "content": "This test verifies behavior when \"symbolScope\" is set to \"all\".\n\n-- settings.json --\n{\n\t\"symbolStyle\": \"full\",\n\t\"symbolMatcher\": \"casesensitive\",\n\t\"symbolScope\": \"all\"\n}\n\n-- go.mod --\nmodule mod.test/symbols\n\ngo 1.18\n\n-- query.go --\npackage symbols\n\n//@workspacesymbol(\"fmt.Println\", println)\n\n-- fmt/fmt.go --\npackage fmt\n\nimport \"fmt\"\n\nfunc Println(s string) {\n\tfmt.Println(s)\n}\n-- @println --\nfmt/fmt.go:5:6-13 mod.test/symbols/fmt.Println Function\n<external> fmt.Println Function\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/caseinsensitive.txt",
    "content": "This file contains test for symbol matches using the caseinsensitive matcher.\n\n-- settings.json --\n{\n\t\"symbolMatcher\": \"caseinsensitive\"\n}\n\n-- go.mod --\nmodule mod.test/caseinsensitive\n\ngo 1.18\n\n-- p.go --\npackage caseinsensitive\n\n//@workspacesymbol(\"\", blank)\n//@workspacesymbol(\"randomgophervar\", randomgophervar)\n\nvar RandomGopherVariableA int\nvar randomgopherVariableB int\nvar RandomGopherOtherVariable int\n\nvar _ = randomgopherVariableB // pacify unusedfunc\n\n-- @blank --\n-- @randomgophervar --\np.go:6:5-26 RandomGopherVariableA Variable\np.go:7:5-26 randomgopherVariableB Variable\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/casesensitive.txt",
    "content": "This file contains tests for symbol matches using the casesensitive matcher.\n\nFor historical reasons, it also verifies general behavior of the symbol search.\n\n-- settings.json --\n{\n\t\"symbolMatcher\": \"casesensitive\",\n\t\"analyses\": {\"unusedfunc\": false}\n}\n\n-- go.mod --\nmodule mod.test/casesensitive\n\ngo 1.18\n\n-- main.go --\npackage main\n\n//@workspacesymbol(\"main.main\", main)\n//@workspacesymbol(\"p.Message\", Message)\n//@workspacesymbol(\"main.myvar\", myvar)\n//@workspacesymbol(\"main.myType\", myType)\n//@workspacesymbol(\"main.myType.Blahblah\", blahblah)\n//@workspacesymbol(\"main.myStruct\", myStruct)\n//@workspacesymbol(\"main.myStruct.myStructField\", myStructField)\n//@workspacesymbol(\"main.myInterface\", myInterface)\n//@workspacesymbol(\"main.myInterface.DoSomeCoolStuff\", DoSomeCoolStuff)\n//@workspacesymbol(\"main.embed.myStruct\", embeddedStruct)\n//@workspacesymbol(\"main.embed.nestedStruct.nestedStruct2.int\", int)\n//@workspacesymbol(\"main.embed.nestedInterface.myInterface\", nestedInterface)\n//@workspacesymbol(\"main.embed.nestedInterface.nestedMethod\", nestedMethod)\n//@workspacesymbol(\"dunk\", dunk)\n//@workspacesymbol(\"Dunk\", Dunk)\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\nfunc main() { // function\n\tfmt.Println(\"Hello\")\n}\n\nvar myvar int // variable\n\ntype myType string // basic type\n\ntype myDecoder json.Decoder // to use the encoding/json import\n\nfunc (m *myType) Blahblah() {} // method\n\ntype myStruct struct { // struct type\n\tmyStructField int // struct field\n}\n\ntype myInterface interface { // interface\n\tDoSomeCoolStuff() string // interface method\n}\n\ntype embed struct {\n\tmyStruct\n\n\tnestedStruct struct {\n\t\tnestedField int\n\n\t\tnestedStruct2 struct {\n\t\t\tint\n\t\t}\n\t}\n\n\tnestedInterface interface {\n\t\tmyInterface\n\t\tnestedMethod()\n\t}\n}\n\nfunc Dunk() int { return 0 }\n\nfunc dunk() {}\n\nvar _ = dunk\n\n-- p/p.go --\npackage p\n\nconst Message = \"Hello World.\" // constant\n-- @DoSomeCoolStuff --\nmain.go:41:2-17 main.myInterface.DoSomeCoolStuff Method\n-- @Dunk --\nmain.go:61:6-10 Dunk Function\n-- @Message --\np/p.go:3:7-14 p.Message Constant\n-- @blahblah --\nmain.go:34:18-26 main.myType.Blahblah Method\n-- @dunk --\nmain.go:63:6-10 dunk Function\n-- @int --\nmain.go:51:4-7 main.embed.nestedStruct.nestedStruct2.int Field\n-- @main --\nmain.go:24:6-10 main.main Function\n-- @myInterface --\nmain.go:40:6-17 main.myInterface Interface\nmain.go:41:2-17 main.myInterface.DoSomeCoolStuff Method\n-- @myStruct --\nmain.go:36:6-14 main.myStruct Struct\nmain.go:37:2-15 main.myStruct.myStructField Field\n-- @myStructField --\nmain.go:37:2-15 main.myStruct.myStructField Field\n-- @myType --\nmain.go:30:6-12 main.myType Class\nmain.go:34:18-26 main.myType.Blahblah Method\n-- @myvar --\nmain.go:28:5-10 main.myvar Variable\n-- @nestedInterface --\nmain.go:56:3-14 main.embed.nestedInterface.myInterface Interface\n-- @nestedMethod --\nmain.go:57:3-15 main.embed.nestedInterface.nestedMethod Method\n-- @embeddedStruct --\nmain.go:45:2-10 main.embed.myStruct Field\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/issue44806.txt",
    "content": "This test verifies the fix for the crash encountered in golang/go#44806.\n\n-- go.mod --\nmodule mod.test/symbol\n\ngo 1.18\n-- symbol.go --\npackage symbol\n\n//@workspacesymbol(\"M\", M)\n\ntype T struct{}\n\n// We should accept all valid receiver syntax when scanning symbols.\nfunc (*(T)) M1() {}\nfunc (*T) M2()   {}\nfunc (T) M3()    {}\nfunc ((T)) M4()    {}\nfunc ((*T)) M5()   {}\n\n-- @M --\nsymbol.go:8:13-15 T.M1 Method\nsymbol.go:9:11-13 T.M2 Method\nsymbol.go:10:10-12 T.M3 Method\nsymbol.go:11:12-14 T.M4 Method\nsymbol.go:12:13-15 T.M5 Method\nsymbol.go:5:6-7 symbol.T Struct\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/workspacesymbol.txt",
    "content": "This test contains tests for basic functionality of the workspace/symbol\nrequest.\n\nTODO(rfindley): add a test for the legacy 'fuzzy' symbol matcher using setting (\"symbolMatcher\": \"fuzzy\"). This test uses the default matcher (\"fastFuzzy\").\n\n-- flags --\n-ignore_extra_diags\n\n-- go.mod --\nmodule mod.test/symbols\n\ngo 1.18\n\n-- query.go --\npackage symbols\n\n//@workspacesymbol(\"rgop\", rgop)\n//@workspacesymbol(\"randoma\", randoma)\n//@workspacesymbol(\"randomb\", randomb)\n\n-- a/a.go --\npackage a\n\nvar RandomGopherVariableA = \"a\"\n\nconst RandomGopherConstantA = \"a\"\n\nconst (\n\trandomgopherinvariable = iota\n)\n\n-- a/a_test.go --\npackage a\n\nvar RandomGopherTestVariableA = \"a\"\n\n-- a/a_x_test.go --\npackage a_test\n\nvar RandomGopherXTestVariableA = \"a\"\n\n-- b/b.go --\npackage b\n\nvar RandomGopherVariableB = \"b\"\n\ntype RandomGopherStructB struct {\n\tBar int\n}\n\n-- @rgop --\nb/b.go:5:6-25 RandomGopherStructB Struct\na/a.go:5:7-28 RandomGopherConstantA Constant\na/a.go:3:5-26 RandomGopherVariableA Variable\nb/b.go:3:5-26 RandomGopherVariableB Variable\na/a_test.go:3:5-30 RandomGopherTestVariableA Variable\na/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable\na/a.go:8:2-24 randomgopherinvariable Constant\nb/b.go:6:2-5 RandomGopherStructB.Bar Field\n-- @randoma --\na/a.go:5:7-28 RandomGopherConstantA Constant\na/a.go:3:5-26 RandomGopherVariableA Variable\nb/b.go:3:5-26 RandomGopherVariableB Variable\na/a.go:8:2-24 randomgopherinvariable Constant\na/a_test.go:3:5-30 RandomGopherTestVariableA Variable\na/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable\nb/b.go:6:2-5 RandomGopherStructB.Bar Field\n-- @randomb --\nb/b.go:5:6-25 RandomGopherStructB Struct\na/a.go:3:5-26 RandomGopherVariableA Variable\nb/b.go:3:5-26 RandomGopherVariableB Variable\na/a.go:8:2-24 randomgopherinvariable Constant\na/a_test.go:3:5-30 RandomGopherTestVariableA Variable\na/a_x_test.go:3:5-31 RandomGopherXTestVariableA Variable\nb/b.go:6:2-5 RandomGopherStructB.Bar Field\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/workspacesymbol/wsscope.txt",
    "content": "This test verifies behavior when \"symbolScope\" is set to \"workspace\".\n\n-- settings.json --\n{\n\t\"symbolStyle\": \"full\",\n\t\"symbolMatcher\": \"casesensitive\",\n\t\"symbolScope\": \"workspace\"\n}\n\n-- go.mod --\nmodule mod.test/symbols\n\ngo 1.18\n\n-- query.go --\npackage symbols\n\n//@workspacesymbol(\"fmt.Println\", println)\n\n-- fmt/fmt.go --\npackage fmt\n\nimport \"fmt\"\n\nfunc Println(s string) {\n\tfmt.Println(s)\n}\n-- @println --\nfmt/fmt.go:5:6-13 mod.test/symbols/fmt.Println Function\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/zeroconfig/adhoc.txt",
    "content": "This test checks that gopls works with multiple ad-hoc packages, which lack\na go.mod file.\n\nWe should be able to import standard library packages, get diagnostics, and\nreference symbols defined in the same directory.\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(mainMsg) //@def(\"mainMsg\", mainMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n-- main2.go --\npackage main\n\nconst mainMsg = \"main\" //@loc(mainMsg, \"mainMsg\")\n\n-- a/a.go --\npackage a\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println(aMsg) //@def(\"aMsg\", aMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- a/a2.go --\npackage a\n\nconst aMsg = \"a\" //@loc(aMsg, \"aMsg\")\n\n-- b/b.go --\npackage b\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println(bMsg) //@def(\"bMsg\", bMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- b/b2.go --\npackage b\n\nconst bMsg = \"b\" //@loc(bMsg, \"bMsg\")\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/zeroconfig/dynamicports.txt",
    "content": "This test checks that the zero-config algorithm selects Views to cover first\nclass ports.\n\nIn this test, package a imports b, and b imports c. Package a contains files\nconstrained by go:build directives, package b contains files constrained by the\nGOOS matching their file name, and package c is unconstrained. Various\nassertions check that diagnostics and navigation work as expected.\n\n-- go.mod --\nmodule golang.org/lsptests\n\n-- a/a.go --\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nvar _ = b.F //@loc(F, \"F\")\n\n-- a/linux64.go --\n//go:build (linux && amd64)\n\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nvar _ int = 1<<32 -1 // OK on 64 bit platforms. Compare linux32.go below.\n\nvar (\n\t_ = b.LinuxOnly   //@def(\"LinuxOnly\", LinuxOnly)\n\t_ = b.DarwinOnly  //@diag(\"DarwinOnly\", re\"(undefined|declared)\")\n\t_ = b.WindowsOnly //@diag(\"WindowsOnly\", re\"(undefined|declared)\")\n)\n\n-- a/linux32.go --\n//go:build (linux && 386)\n\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nvar _ int = 1<<32 -1 //@diag(\"1<<32\", re\"overflows\")\n\nvar (\n\t_ = b.LinuxOnly   //@def(\"LinuxOnly\", LinuxOnly)\n\t_ = b.DarwinOnly  //@diag(\"DarwinOnly\", re\"(undefined|declared)\")\n\t_ = b.WindowsOnly //@diag(\"WindowsOnly\", re\"(undefined|declared)\")\n)\n\n-- a/darwin64.go --\n//go:build (darwin && amd64)\n\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nvar (\n\t_ = b.LinuxOnly   //@diag(\"LinuxOnly\", re\"(undefined|declared)\")\n\t_ = b.DarwinOnly  //@def(\"DarwinOnly\", DarwinOnly)\n\t_ = b.WindowsOnly //@diag(\"WindowsOnly\", re\"(undefined|declared)\")\n)\n\n-- a/windows64.go --\n//go:build (windows && amd64)\n\npackage a\n\nimport \"golang.org/lsptests/b\"\n\nvar (\n\t_ = b.LinuxOnly   //@diag(\"LinuxOnly\", re\"(undefined|declared)\")\n\t_ = b.DarwinOnly  //@diag(\"DarwinOnly\", re\"(undefined|declared)\")\n\t_ = b.WindowsOnly //@def(\"WindowsOnly\", WindowsOnly)\n)\n\n-- b/b_other.go --\n//go:build !linux && !darwin && !windows\npackage b\n\nfunc F() {}\n\n-- b/b_linux.go --\npackage b\n\nimport \"golang.org/lsptests/c\"\n\nfunc F() { //@refs(\"F\", \"F\", F)\n\tx := c.Common //@diag(\"x\", re\"not used\"),def(\"Common\", Common)\n}\n\nconst LinuxOnly = \"darwin\" //@loc(LinuxOnly, \"LinuxOnly\")\n\n-- b/b_darwin.go --\npackage b\n\nimport \"golang.org/lsptests/c\"\n\nfunc F() { //@refs(\"F\", \"F\", F)\n\tx := c.Common //@diag(\"x\", re\"not used\"),def(\"Common\", Common)\n}\n\nconst DarwinOnly = \"darwin\" //@loc(DarwinOnly, \"DarwinOnly\")\n\n-- b/b_windows.go --\npackage b\n\nimport \"golang.org/lsptests/c\"\n\nfunc F() { //@refs(\"F\", \"F\", F)\n\tx := c.Common //@diag(\"x\", re\"not used\"),def(\"Common\", Common)\n}\n\nconst WindowsOnly = \"windows\" //@loc(WindowsOnly, \"WindowsOnly\")\n\n-- c/c.go --\npackage c\n\nconst Common = 0 //@loc(Common, \"Common\")\n\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/zeroconfig/nested.txt",
    "content": "This test checks that gopls works with nested modules, including multiple\nnested modules.\n\n-- main.go --\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(mainMsg) //@def(\"mainMsg\", mainMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n-- main2.go --\npackage main\n\nconst mainMsg = \"main\" //@loc(mainMsg, \"mainMsg\")\n\n-- mod1/go.mod --\nmodule golang.org/lsptests/mod1\n\ngo 1.20\n\n-- mod1/a/a.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"golang.org/lsptests/mod1/b\"\n)\n\nfunc _() {\n\tfmt.Println(b.Msg) //@def(\"Msg\", Msg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- mod1/a/tagged.go --\n//go:build tag1\n\n// golang/go#60776: verify that we get an accurate error about build tags\n// here, rather than an inaccurate error suggesting to add a go.work\n// file (which won't help).\npackage a //@diag(re`package (a)`, re`excluded due to its build tags`)\n\n-- mod1/b/b.go --\npackage b\n\nconst Msg = \"1\" //@loc(Msg, \"Msg\")\n\n-- mod2/go.mod --\nmodule golang.org/lsptests/mod2\n\nrequire golang.org/lsptests/mod1 v0.0.1\n\nreplace golang.org/lsptests/mod1 => ../mod1\n\ngo 1.20\n\n-- mod2/c/c.go --\npackage c\n\nimport (\n\t\"fmt\"\n\t\"golang.org/lsptests/mod1/b\"\n)\n\nfunc _() {\n\tfmt.Println(b.Msg) //@def(\"Msg\", Msg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n"
  },
  {
    "path": "gopls/internal/test/marker/testdata/zeroconfig/nonworkspacemodule.txt",
    "content": "This test checks that gopls works with modules that aren't included in the\nworkspace file.\n\n-- go.work --\ngo 1.20\n\nuse (\n\t./a\n\t./b\n)\n\n-- a/go.mod --\nmodule golang.org/lsptests/a\n\ngo 1.18\n\n-- a/a.go --\npackage a\n\nimport (\n\t\"fmt\"\n\t\"golang.org/lsptests/a/lib\"\n)\n\nfunc _() {\n\tfmt.Println(lib.Msg) //@def(\"Msg\", aMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- a/lib/lib.go --\npackage lib\n\nconst Msg = \"hi\" //@loc(aMsg, \"Msg\")\n\n-- b/go.mod --\nmodule golang.org/lsptests/b\n\ngo 1.18\n\n-- b/b.go --\npackage b\n\nimport (\n\t\"fmt\"\n\t\"golang.org/lsptests/b/lib\"\n)\n\nfunc main() {\n\tfmt.Println(lib.Msg) //@def(\"Msg\", bMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- b/lib/lib.go --\npackage lib\n\nconst Msg = \"hi\" //@loc(bMsg, \"Msg\")\n\n-- c/go.mod --\nmodule golang.org/lsptests/c\n\ngo 1.18\n\n-- c/c.go --\npackage c\n\nimport (\n\t\"fmt\"\n\t\"golang.org/lsptests/c/lib\"\n)\n\nfunc main() {\n\tfmt.Println(lib.Msg) //@def(\"Msg\", cMsg)\n\tfmt.Println(undef) //@diag(\"undef\", re\"undefined|undeclared\")\n}\n\n-- c/lib/lib.go --\npackage lib\n\nconst Msg = \"hi\" //@loc(cMsg, \"Msg\")\n"
  },
  {
    "path": "gopls/internal/util/README.md",
    "content": "# util\n\nThis directory is not a Go package.\n\nIts subdirectories are for utility packages, defined as implementation\nhelpers (not core machinery) that are used in different ways across\nthe gopls codebase."
  },
  {
    "path": "gopls/internal/util/asm/parse.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package asm provides a simple parser for Go assembly files.\npackage asm\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n\t\"unicode\"\n)\n\n// Kind describes the nature of an identifier in an assembly file.\ntype Kind uint8\n\nconst (\n\tInvalid Kind = iota // reserved zero value; not used by Ident\n\tRef                 // arbitrary reference to symbol or control label\n\tText                // definition of TEXT (function) symbol\n\tGlobal              // definition of GLOBL (var) symbol\n\tData                // initialization of GLOBL (var) symbol; effectively a reference\n\tLabel               // definition of control label\n)\n\nfunc (k Kind) String() string {\n\tif int(k) < len(kindString) {\n\t\treturn kindString[k]\n\t}\n\treturn fmt.Sprintf(\"Kind(%d)\", k)\n}\n\nvar kindString = [...]string{\n\tInvalid: \"invalid\",\n\tRef:     \"ref\",\n\tText:    \"text\",\n\tGlobal:  \"global\",\n\tData:    \"data\",\n\tLabel:   \"label\",\n}\n\n// A file represents a parsed file of Go assembly language.\ntype File struct {\n\tIdents []Ident\n\n\t// TODO(adonovan): use token.File? This may be important in a\n\t// future in which analyzers can report diagnostics in .s files.\n}\n\n// Ident represents an identifier in an assembly file.\ntype Ident struct {\n\tName   string // symbol name (after correcting [·∕]); Name[0]='.' => current package\n\tOffset int    // zero-based byte offset\n\tKind   Kind\n}\n\n// End returns the identifier's end offset.\nfunc (id Ident) End() int { return id.Offset + len(id.Name) }\n\n// Parse extracts identifiers from Go assembly files.\n// Since it is a best-effort parser, it never returns an error.\nfunc Parse(content []byte) *File {\n\tvar idents []Ident\n\toffset := 0 // byte offset of start of current line\n\n\t// TODO(adonovan) use a proper tokenizer that respects\n\t// comments, string literals, line continuations, etc.\n\tscan := bufio.NewScanner(bytes.NewReader(content))\n\tfor ; scan.Scan(); offset += len(scan.Bytes()) + len(\"\\n\") {\n\t\tline := scan.Text()\n\n\t\t// Strip comments.\n\t\tif idx := strings.Index(line, \"//\"); idx >= 0 {\n\t\t\tline = line[:idx]\n\t\t}\n\n\t\t// Skip blank lines.\n\t\tif strings.TrimSpace(line) == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check for label definitions (ending with colon).\n\t\tif colon := strings.IndexByte(line, ':'); colon > 0 {\n\t\t\tlabel := strings.TrimSpace(line[:colon])\n\t\t\tif isIdent(label) {\n\t\t\t\tidents = append(idents, Ident{\n\t\t\t\t\tName:   label,\n\t\t\t\t\tOffset: offset + strings.Index(line, label),\n\t\t\t\t\tKind:   Label,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Split line into words.\n\t\twords := strings.Fields(line)\n\t\tif len(words) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// A line of the form\n\t\t//    TEXT ·sym<ABIInternal>(SB),NOSPLIT,$12\n\t\t// declares a text symbol \"·sym\".\n\t\tif len(words) > 1 {\n\t\t\tkind := Invalid\n\t\t\tswitch words[0] {\n\t\t\tcase \"TEXT\":\n\t\t\t\tkind = Text\n\t\t\tcase \"GLOBL\":\n\t\t\t\tkind = Global\n\t\t\tcase \"DATA\":\n\t\t\t\tkind = Data\n\t\t\t}\n\t\t\tif kind != Invalid {\n\t\t\t\tsym := words[1]\n\t\t\t\tsym = cutBefore(sym, \",\") // strip \",NOSPLIT,$12\" etc\n\t\t\t\tsym = cutBefore(sym, \"(\") // \"sym(SB)\" -> \"sym\"\n\t\t\t\tsym = cutBefore(sym, \"<\") // \"sym<ABIInternal>\" -> \"sym\"\n\t\t\t\tsym = strings.TrimSpace(sym)\n\t\t\t\tif isIdent(sym) {\n\t\t\t\t\t// (The Index call assumes sym is not itself \"TEXT\" etc.)\n\t\t\t\t\tidents = append(idents, Ident{\n\t\t\t\t\t\tName:   cleanup(sym),\n\t\t\t\t\t\tKind:   kind,\n\t\t\t\t\t\tOffset: offset + strings.Index(line, sym),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Find references in the rest of the line.\n\t\tpos := 0\n\t\tfor _, word := range words {\n\t\t\t// Find actual position of word within line.\n\t\t\ttokenPos := strings.Index(line[pos:], word)\n\t\t\tif tokenPos < 0 {\n\t\t\t\tpanic(line)\n\t\t\t}\n\t\t\ttokenPos += pos\n\t\t\tpos = tokenPos + len(word)\n\n\t\t\t// Reject probable instruction mnemonics (e.g. MOV).\n\t\t\tif len(word) >= 2 && word[0] != '·' &&\n\t\t\t\t!strings.ContainsFunc(word, unicode.IsLower) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif word[0] == '$' {\n\t\t\t\tword = word[1:]\n\t\t\t\ttokenPos++\n\n\t\t\t\t// Reject probable immediate values (e.g. \"$123\").\n\t\t\t\tif !strings.ContainsFunc(word, isNonDigit) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reject probably registers (e.g. \"PC\").\n\t\t\tif len(word) <= 3 && !strings.ContainsFunc(word, unicode.IsLower) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Probable identifier reference.\n\t\t\t//\n\t\t\t// TODO(adonovan): handle FP symbols correctly;\n\t\t\t// sym+8(FP) is essentially a comment about\n\t\t\t// stack slot 8, not a reference to a symbol\n\t\t\t// with a declaration somewhere; so they form\n\t\t\t// an equivalence class without a canonical\n\t\t\t// declaration.\n\t\t\t//\n\t\t\t// TODO(adonovan): handle pseudoregisters and field\n\t\t\t// references such as:\n\t\t\t//    MOVD\t$runtime·g0(SB), g      // pseudoreg\n\t\t\t//    MOVD\tR0, g_stackguard0(g)    // field ref\n\n\t\t\tsym := cutBefore(word, \"(\") // \"·sym(SB)\" => \"sym\"\n\t\t\tsym = cutBefore(sym, \"+\")   // \"sym+8(FP)\" => \"sym\"\n\t\t\tsym = cutBefore(sym, \"<\")   // \"sym<ABIInternal>\" =>> \"sym\"\n\t\t\tif isIdent(sym) {\n\t\t\t\tidents = append(idents, Ident{\n\t\t\t\t\tName:   cleanup(sym),\n\t\t\t\t\tKind:   Ref,\n\t\t\t\t\tOffset: offset + tokenPos,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t_ = scan.Err() // ignore scan errors\n\n\treturn &File{Idents: idents}\n}\n\n// isIdent reports whether s is a valid Go assembly identifier.\nfunc isIdent(s string) bool {\n\tfor i, r := range s {\n\t\tif !isIdentRune(r, i) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn len(s) > 0\n}\n\n// cutBefore returns the portion of s before the first occurrence of sep, if any.\nfunc cutBefore(s, sep string) string {\n\tif before, _, ok := strings.Cut(s, sep); ok {\n\t\treturn before\n\t}\n\treturn s\n}\n\n// cleanup converts a symbol name from assembler syntax to linker syntax.\nfunc cleanup(sym string) string {\n\treturn repl.Replace(sym)\n}\n\nvar repl = strings.NewReplacer(\n\t\"·\", \".\", // (U+00B7 MIDDLE DOT)\n\t\"∕\", \"/\", // (U+2215 DIVISION SLASH)\n)\n\nfunc isNonDigit(r rune) bool { return !unicode.IsDigit(r) }\n\n// -- plundered from GOROOT/src/cmd/asm/internal/asm/parse.go --\n\n// We want center dot (·) and division slash (∕) to work as identifier characters.\nfunc isIdentRune(ch rune, i int) bool {\n\tif unicode.IsLetter(ch) {\n\t\treturn true\n\t}\n\tswitch ch {\n\tcase '_': // Underscore; traditional.\n\t\treturn true\n\tcase '\\u00B7': // Represents the period in runtime.exit. U+00B7 '·' middle dot\n\t\treturn true\n\tcase '\\u2215': // Represents the slash in runtime/debug.setGCPercent. U+2215 '∕' division slash\n\t\treturn true\n\t}\n\t// Digits are OK only after the first character.\n\treturn i > 0 && unicode.IsDigit(ch)\n}\n"
  },
  {
    "path": "gopls/internal/util/asm/parse_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage asm_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/util/asm\"\n)\n\n// TestIdents checks that (likely) identifiers are extracted in the expected places.\nfunc TestIdents(t *testing.T) {\n\tsrc := []byte(`\n// This is a nonsense file containing a variety of syntax.\n\n#include \"foo.h\"\n#ifdef MACRO\nDATA hello<>+0x00(SB)/64, $\"Hello\"\nGLOBL hello<(SB), RODATA, $64\n#endif\n\nTEXT mypkg·f(SB),NOSPLIT,$0\n\tMOVD\tR1, 16(RSP) // another comment\n\tMOVD\t$otherpkg·data(SB), R2\n\tJMP\tlabel\nlabel:\n\tBL\t·g(SB)\n\nTEXT ·g(SB),NOSPLIT,$0\n\tMOVD\t$runtime·g0(SB), g\n\tMOVD\tR0, g_stackguard0(g)\n\tMOVD\tR0, (g_stack+stack_lo)(g)\n`[1:])\n\tconst filename = \"asm.s\"\n\tm := protocol.NewMapper(protocol.URIFromPath(filename), src)\n\tfile := asm.Parse(src)\n\n\twant := `\nasm.s:5:6-11:\tdata \"hello\"\nasm.s:6:7-12:\tglobal \"hello\"\nasm.s:9:6-13:\ttext \"mypkg.f\"\nasm.s:11:8-21:\tref \"otherpkg.data\"\nasm.s:12:6-11:\tref \"label\"\nasm.s:13:1-6:\tlabel \"label\"\nasm.s:14:5-7:\tref \".g\"\nasm.s:16:6-8:\ttext \".g\"\nasm.s:17:8-18:\tref \"runtime.g0\"\nasm.s:17:25-26:\tref \"g\"\nasm.s:18:11-24:\tref \"g_stackguard0\"\n`[1:]\n\tvar buf bytes.Buffer\n\tfor _, id := range file.Idents {\n\t\tline, col := m.OffsetLineCol8(id.Offset)\n\t\t_, endCol := m.OffsetLineCol8(id.Offset + len(id.Name))\n\t\tfmt.Fprintf(&buf, \"%s:%d:%d-%d:\\t%s %q\\n\", filename, line, col, endCol, id.Kind, id.Name)\n\t}\n\tgot := buf.String()\n\tif got != want {\n\t\tt.Errorf(\"got:\\n%s\\nwant:\\n%s\\ndiff:\\n%s\", got, want, cmp.Diff(want, got))\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/browser/README.md",
    "content": "This package is a copy of cmd/internal/browser from the go distribution"
  },
  {
    "path": "gopls/internal/util/browser/browser.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package browser provides utilities for interacting with users' browsers.\npackage browser\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"time\"\n)\n\n// Commands returns a list of possible commands to use to open a url.\nfunc Commands() [][]string {\n\tvar cmds [][]string\n\tif exe := os.Getenv(\"BROWSER\"); exe != \"\" {\n\t\tcmds = append(cmds, []string{exe})\n\t}\n\tswitch runtime.GOOS {\n\tcase \"darwin\":\n\t\tcmds = append(cmds, []string{\"/usr/bin/open\"})\n\tcase \"windows\":\n\t\tcmds = append(cmds, []string{\"cmd\", \"/c\", \"start\"})\n\tdefault:\n\t\tif os.Getenv(\"DISPLAY\") != \"\" {\n\t\t\t// xdg-open is only for use in a desktop environment.\n\t\t\tcmds = append(cmds, []string{\"xdg-open\"})\n\t\t}\n\t}\n\tcmds = append(cmds,\n\t\t[]string{\"chrome\"},\n\t\t[]string{\"google-chrome\"},\n\t\t[]string{\"chromium\"},\n\t\t[]string{\"firefox\"},\n\t)\n\treturn cmds\n}\n\n// Open tries to open url in a browser and reports whether it succeeded.\nfunc Open(url string) bool {\n\tfor _, args := range Commands() {\n\t\tcmd := exec.Command(args[0], append(args[1:], url)...)\n\t\tif cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// appearsSuccessful reports whether the command appears to have run successfully.\n// If the command runs longer than the timeout, it's deemed successful.\n// If the command runs within the timeout, it's deemed successful if it exited cleanly.\nfunc appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool {\n\terrc := make(chan error, 1)\n\tgo func() {\n\t\terrc <- cmd.Wait()\n\t}()\n\n\tselect {\n\tcase <-time.After(timeout):\n\t\treturn true\n\tcase err := <-errc:\n\t\treturn err == nil\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/bug/bug.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package bug provides utilities for reporting internal bugs, and being\n// notified when they occur.\n//\n// Philosophically, because gopls runs as a sidecar process that the user does\n// not directly control, sometimes it keeps going on broken invariants rather\n// than panicking. In those cases, bug reports provide a mechanism to alert\n// developers and capture relevant metadata.\npackage bug\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/telemetry/counter\"\n)\n\n// PanicOnBugs controls whether to panic when bugs are reported.\n//\n// It may be set to true during testing.\n//\n// TODO(adonovan): should we make the default true, and\n// suppress it only in the product (gopls/main.go)?\nvar PanicOnBugs = false\n\nvar (\n\tmu        sync.Mutex\n\texemplars map[string]Bug\n\thandlers  []func(Bug)\n)\n\n// A Bug represents an unexpected event or broken invariant. They are used for\n// capturing metadata that helps us understand the event.\n//\n// Bugs are JSON-serializable.\ntype Bug struct {\n\tFile        string    // file containing the call to bug.Report\n\tLine        int       // line containing the call to bug.Report\n\tDescription string    // description of the bug\n\tKey         string    // key identifying the bug (file:line if available)\n\tStack       string    // call stack\n\tAtTime      time.Time // time the bug was reported\n}\n\n// Reportf reports a formatted bug message.\nfunc Reportf(format string, args ...any) {\n\treport(fmt.Sprintf(format, args...))\n}\n\n// Errorf calls fmt.Errorf for the given arguments, and reports the resulting\n// error message as a bug.\nfunc Errorf(format string, args ...any) error {\n\terr := fmt.Errorf(format, args...)\n\treport(err.Error())\n\treturn err\n}\n\n// Report records a new bug encountered on the server.\n// It uses reflection to report the position of the immediate caller.\nfunc Report(description string) {\n\treport(description)\n}\n\n// BugReportCount is a telemetry counter that tracks # of bug reports.\nvar BugReportCount = counter.NewStack(\"gopls/bug\", 16)\n\nfunc report(description string) {\n\t_, file, line, ok := runtime.Caller(2) // all exported reporting functions call report directly\n\n\tkey := \"<missing callsite>\"\n\tif ok {\n\t\tkey = fmt.Sprintf(\"%s:%d\", file, line)\n\t}\n\n\tif PanicOnBugs {\n\t\tpanic(fmt.Sprintf(\"%s: %s\", key, description))\n\t}\n\n\tbug := Bug{\n\t\tFile:        file,\n\t\tLine:        line,\n\t\tDescription: description,\n\t\tKey:         key,\n\t\tStack:       string(debug.Stack()),\n\t\tAtTime:      time.Now(),\n\t}\n\n\tnewBug := false\n\tmu.Lock()\n\tif _, ok := exemplars[key]; !ok {\n\t\tif exemplars == nil {\n\t\t\texemplars = make(map[string]Bug)\n\t\t}\n\t\texemplars[key] = bug // capture one exemplar per key\n\t\tnewBug = true\n\t}\n\thh := handlers\n\thandlers = nil\n\tmu.Unlock()\n\n\tif newBug {\n\t\tBugReportCount.Inc()\n\t}\n\t// Call the handlers outside the critical section since a\n\t// handler may itself fail and call bug.Report. Since handlers\n\t// are one-shot, the inner call should be trivial.\n\tfor _, handle := range hh {\n\t\thandle(bug)\n\t}\n}\n\n// Handle adds a handler function that will be called with the next\n// bug to occur on the server. The handler only ever receives one bug.\n// It is called synchronously, and should return in a timely manner.\nfunc Handle(h func(Bug)) {\n\tmu.Lock()\n\tdefer mu.Unlock()\n\thandlers = append(handlers, h)\n}\n\n// List returns a slice of bug exemplars -- the first bugs to occur at each\n// callsite.\nfunc List() []Bug {\n\tmu.Lock()\n\tdefer mu.Unlock()\n\n\tvar bugs []Bug\n\n\tfor _, bug := range exemplars {\n\t\tbugs = append(bugs, bug)\n\t}\n\n\tsort.Slice(bugs, func(i, j int) bool {\n\t\treturn bugs[i].Key < bugs[j].Key\n\t})\n\n\treturn bugs\n}\n"
  },
  {
    "path": "gopls/internal/util/bug/bug_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bug\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc resetForTesting() {\n\texemplars = nil\n\thandlers = nil\n}\n\nfunc TestListBugs(t *testing.T) {\n\tdefer resetForTesting()\n\n\tReport(\"bad\")\n\n\twantBugs(t, \"bad\")\n\n\tfor i := range 3 {\n\t\tReport(fmt.Sprintf(\"index:%d\", i))\n\t}\n\n\twantBugs(t, \"bad\", \"index:0\")\n}\n\nfunc wantBugs(t *testing.T, want ...string) {\n\tt.Helper()\n\n\tbugs := List()\n\tif got, want := len(bugs), len(want); got != want {\n\t\tt.Errorf(\"List(): got %d bugs, want %d\", got, want)\n\t\treturn\n\t}\n\n\tfor i, b := range bugs {\n\t\tif got, want := b.Description, want[i]; got != want {\n\t\t\tt.Errorf(\"bug.List()[%d] = %q, want %q\", i, got, want)\n\t\t}\n\t}\n}\n\nfunc TestBugHandler(t *testing.T) {\n\tdefer resetForTesting()\n\n\tReport(\"unseen\")\n\n\t// Both handlers are called, in order of registration, only once.\n\tvar got string\n\tHandle(func(b Bug) { got += \"1:\" + b.Description })\n\tHandle(func(b Bug) { got += \"2:\" + b.Description })\n\n\tReport(\"seen\")\n\n\tReport(\"again\")\n\n\tif want := \"1:seen2:seen\"; got != want {\n\t\tt.Errorf(\"got %q, want %q\", got, want)\n\t}\n}\n\nfunc TestBugJSON(t *testing.T) {\n\tb1 := Bug{\n\t\tFile:        \"foo.go\",\n\t\tLine:        1,\n\t\tDescription: \"a bug\",\n\t\tKey:         \"foo.go:1\",\n\t\tStack:       \"<stack>\",\n\t\tAtTime:      time.Now(),\n\t}\n\n\tdata, err := json.Marshal(b1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar b2 Bug\n\tif err := json.Unmarshal(data, &b2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif diff := cmp.Diff(b1, b2); diff != \"\" {\n\t\tt.Errorf(\"bugs differ after JSON Marshal/Unmarshal (-b1 +b2):\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/constraints/constraint.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package constraints defines a set of useful constraints to be used\n// with type parameters.\npackage constraints\n\n// Copied from x/exp/constraints.\n\n// Signed is a constraint that permits any signed integer type.\n// If future releases of Go add new predeclared signed integer types,\n// this constraint will be modified to include them.\ntype Signed interface {\n\t~int | ~int8 | ~int16 | ~int32 | ~int64\n}\n\n// Unsigned is a constraint that permits any unsigned integer type.\n// If future releases of Go add new predeclared unsigned integer types,\n// this constraint will be modified to include them.\ntype Unsigned interface {\n\t~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr\n}\n\n// Integer is a constraint that permits any integer type.\n// If future releases of Go add new predeclared integer types,\n// this constraint will be modified to include them.\ntype Integer interface {\n\tSigned | Unsigned\n}\n\n// Float is a constraint that permits any floating-point type.\n// If future releases of Go add new predeclared floating-point types,\n// this constraint will be modified to include them.\ntype Float interface {\n\t~float32 | ~float64\n}\n\n// Complex is a constraint that permits any complex numeric type.\n// If future releases of Go add new predeclared complex numeric types,\n// this constraint will be modified to include them.\ntype Complex interface {\n\t~complex64 | ~complex128\n}\n\n// Ordered is a constraint that permits any ordered type: any type\n// that supports the operators < <= >= >.\n// If future releases of Go add new ordered types,\n// this constraint will be modified to include them.\ntype Ordered interface {\n\tInteger | Float | ~string\n}\n"
  },
  {
    "path": "gopls/internal/util/cursorutil/util.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cursorutil provides utility functions for working with [inspector.Cursor].\n//\n// It should create no additional dependencies beyond those of Cursor\n// itself, so that functions can be promoted to the public API of\n// Cursor in due course.\npackage cursorutil\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\n// FirstEnclosing returns the first value from [cursor.Enclosing] as\n// both a designated type and a [inspector.Cursor] pointing to it.\n//\n// It returns the zero value if it is not found.\n//\n// A common usage is:\n//\n//\tcall, callCur := cursorutil.FirstEnclosing[*ast.CallExpr](cur)\n//\tif call == nil {\n//\t\t// Not Found\n//\t}\nfunc FirstEnclosing[N ast.Node](cur inspector.Cursor) (N, inspector.Cursor) {\n\tvar typ N\n\tfor cur := range cur.Enclosing(typ) {\n\t\treturn cur.Node().(N), cur\n\t}\n\treturn typ, inspector.Cursor{}\n}\n\n// Path returns the specified node followed by all its ancestors up to the file.\n// Use it as an adaptor between cursors and code that works with PathEnclosingInterval.\n// Ultimately all such code should be eliminated.\nfunc Path(cur inspector.Cursor) (path []ast.Node) {\n\tfor cur := range cur.Enclosing() {\n\t\tpath = append(path, cur.Node())\n\t}\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/util/fakenet/conn.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fakenet\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n)\n\n// NewConn returns a net.Conn built on top of the supplied reader and writer.\n// It decouples the read and write on the conn from the underlying stream\n// to enable Close to abort ones that are in progress.\n// It's primary use is to fake a network connection from stdin and stdout.\nfunc NewConn(name string, in io.ReadCloser, out io.WriteCloser) net.Conn {\n\tc := &fakeConn{\n\t\tname:   name,\n\t\treader: newFeeder(in.Read),\n\t\twriter: newFeeder(out.Write),\n\t\tin:     in,\n\t\tout:    out,\n\t}\n\tgo c.reader.run()\n\tgo c.writer.run()\n\treturn c\n}\n\ntype fakeConn struct {\n\tname   string\n\treader *connFeeder\n\twriter *connFeeder\n\tin     io.ReadCloser\n\tout    io.WriteCloser\n}\n\ntype fakeAddr string\n\n// connFeeder serializes calls to the source function (io.Reader.Read or\n// io.Writer.Write) by delegating them to a channel. This also allows calls to\n// be intercepted when the connection is closed, and cancelled early if the\n// connection is closed while the calls are still outstanding.\ntype connFeeder struct {\n\tsource func([]byte) (int, error)\n\tinput  chan []byte\n\tresult chan feedResult\n\tmu     sync.Mutex\n\tclosed bool\n\tdone   chan struct{}\n}\n\ntype feedResult struct {\n\tn   int\n\terr error\n}\n\nfunc (c *fakeConn) Close() error {\n\tc.reader.close()\n\tc.writer.close()\n\tc.in.Close()\n\tc.out.Close()\n\treturn nil\n}\n\nfunc (c *fakeConn) Read(b []byte) (n int, err error)   { return c.reader.do(b) }\nfunc (c *fakeConn) Write(b []byte) (n int, err error)  { return c.writer.do(b) }\nfunc (c *fakeConn) LocalAddr() net.Addr                { return fakeAddr(c.name) }\nfunc (c *fakeConn) RemoteAddr() net.Addr               { return fakeAddr(c.name) }\nfunc (c *fakeConn) SetDeadline(t time.Time) error      { return nil }\nfunc (c *fakeConn) SetReadDeadline(t time.Time) error  { return nil }\nfunc (c *fakeConn) SetWriteDeadline(t time.Time) error { return nil }\nfunc (a fakeAddr) Network() string                     { return \"fake\" }\nfunc (a fakeAddr) String() string                      { return string(a) }\n\nfunc newFeeder(source func([]byte) (int, error)) *connFeeder {\n\treturn &connFeeder{\n\t\tsource: source,\n\t\tinput:  make(chan []byte),\n\t\tresult: make(chan feedResult),\n\t\tdone:   make(chan struct{}),\n\t}\n}\n\nfunc (f *connFeeder) close() {\n\tf.mu.Lock()\n\tif !f.closed {\n\t\tf.closed = true\n\t\tclose(f.done)\n\t}\n\tf.mu.Unlock()\n}\n\nfunc (f *connFeeder) do(b []byte) (n int, err error) {\n\t// send the request to the worker\n\tselect {\n\tcase f.input <- b:\n\tcase <-f.done:\n\t\treturn 0, io.EOF\n\t}\n\t// get the result from the worker\n\tselect {\n\tcase r := <-f.result:\n\t\treturn r.n, r.err\n\tcase <-f.done:\n\t\treturn 0, io.EOF\n\t}\n}\n\nfunc (f *connFeeder) run() {\n\tvar b []byte\n\tfor {\n\t\t// wait for an input request\n\t\tselect {\n\t\tcase b = <-f.input:\n\t\tcase <-f.done:\n\t\t\treturn\n\t\t}\n\t\t// invoke the underlying method\n\t\tn, err := f.source(b)\n\t\t// send the result back to the requester\n\t\tselect {\n\t\tcase f.result <- feedResult{n: n, err: err}:\n\t\tcase <-f.done:\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/fingerprint/fingerprint.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fingerprint defines a function to [Encode] types as strings\n// with the property that identical types have equal string encodings,\n// in most cases. In the remaining cases (mostly involving generic\n// types), the encodings can be parsed using [Parse] into [Tree] form\n// and matched using [Matches].\npackage fingerprint\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/scanner\"\n)\n\n// Encode returns an encoding of a [types.Type] such that, in\n// most cases, Encode(x) == Encode(y) iff [types.Identical](x, y).\n//\n// For a minority of types, mostly involving type parameters, identity\n// cannot be reduced to string comparison; these types are called\n// \"tricky\", and are indicated by the boolean result.\n//\n// In general, computing identity correctly for tricky types requires\n// the type checker. However, the fingerprint encoding can be parsed\n// by [Parse] into a [Tree] form that permits simple matching sufficient\n// to allow a type parameter to unify with any subtree; see [Match].\n//\n// In the standard library, 99.8% of package-level types have a\n// non-tricky method-set. The most common exceptions are due to type\n// parameters.\n//\n// fingerprint.Encode is defined only for the signature types of functions\n// and methods. It must not be called for \"untyped\" basic types, nor\n// the type of a generic function.\nfunc Encode(t types.Type) (_ string, tricky bool) { return fingerprint(t) }\n\n// A Tree is a parsed form of a fingerprint for use with [Matches].\ntype Tree struct{ tree sexpr }\n\n// String returns the tree in an unspecified human-readable form.\nfunc (tree Tree) String() string {\n\tvar out strings.Builder\n\twriteSexpr(&out, tree.tree)\n\treturn out.String()\n}\n\n// Parse parses a fingerprint into tree form.\n//\n// The input must have been produced by [Encode] at the same source\n// version; parsing is thus infallible.\nfunc Parse(fp string) Tree {\n\treturn Tree{parseFingerprint(fp)}\n}\n\n// Matches reports whether two fingerprint trees match, meaning that\n// under some conditions (for example, particular instantiations of\n// type parameters) the two types may be identical.\nfunc Matches(x, y Tree) bool {\n\treturn unify(x.tree, y.tree)\n}\n\n// Fingerprint syntax\n//\n// The lexical syntax is essentially Lisp S-expressions:\n//\n//      expr = STRING | INTEGER | IDENT | '(' expr... ')'\n//\n// where the tokens are as defined by text/scanner.\n//\n// The grammar of expression forms is:\n//\n//      τ = IDENT                       -- named or basic type\n//        | (qual STRING IDENT)         -- qualified named type\n//        | (array INTEGER τ)\n//        | (slice τ)\n//        | (ptr τ)\n//        | (chan IDENT τ)\n//        | (func τ v? τ)               -- signature params, results, variadic?\n//        | (map τ τ)\n//        | (struct field*)\n//        | (tuple τ*)\n//        | (interface)                 -- nonempty interface (lossy)\n//        | (typeparam INTEGER)\n//        | (inst τ τ...)               -- instantiation of a named type\n//\n//  field = IDENT IDENT STRING τ        -- name, embedded?, tag, type\n\nfunc fingerprint(t types.Type) (string, bool) {\n\tvar buf strings.Builder\n\ttricky := false\n\tvar print func(t types.Type)\n\tprint = func(t types.Type) {\n\t\tswitch t := t.(type) {\n\t\tcase *types.Alias:\n\t\t\tprint(types.Unalias(t))\n\n\t\tcase *types.Named:\n\t\t\ttargs := t.TypeArgs()\n\t\t\tif targs != nil {\n\t\t\t\tbuf.WriteString(\"(inst \")\n\t\t\t}\n\t\t\ttname := t.Obj()\n\t\t\tif tname.Pkg() != nil {\n\t\t\t\tfmt.Fprintf(&buf, \"(qual %q %s)\", tname.Pkg().Path(), tname.Name())\n\t\t\t} else if tname.Name() != \"error\" && tname.Name() != \"comparable\" {\n\t\t\t\tpanic(tname) // error and comparable the only named types with no package\n\t\t\t} else {\n\t\t\t\tbuf.WriteString(tname.Name())\n\t\t\t}\n\t\t\tif targs != nil {\n\t\t\t\tfor t0 := range targs.Types() {\n\t\t\t\t\tbuf.WriteByte(' ')\n\t\t\t\t\tprint(t0)\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(\")\")\n\t\t\t}\n\n\t\tcase *types.Array:\n\t\t\tfmt.Fprintf(&buf, \"(array %d \", t.Len())\n\t\t\tprint(t.Elem())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Slice:\n\t\t\tbuf.WriteString(\"(slice \")\n\t\t\tprint(t.Elem())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Pointer:\n\t\t\tbuf.WriteString(\"(ptr \")\n\t\t\tprint(t.Elem())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Map:\n\t\t\tbuf.WriteString(\"(map \")\n\t\t\tprint(t.Key())\n\t\t\tbuf.WriteByte(' ')\n\t\t\tprint(t.Elem())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Chan:\n\t\t\tfmt.Fprintf(&buf, \"(chan %d \", t.Dir())\n\t\t\tprint(t.Elem())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Tuple:\n\t\t\tbuf.WriteString(\"(tuple\")\n\t\t\tfor v := range t.Variables() {\n\t\t\t\tbuf.WriteByte(' ')\n\t\t\t\tprint(v.Type())\n\t\t\t}\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Basic:\n\t\t\t// Print byte/uint8 as \"byte\" instead of calling\n\t\t\t// BasicType.String, which prints the two distinctly\n\t\t\t// (even though their Kinds are numerically equal).\n\t\t\t// Ditto for rune/int32.\n\t\t\tswitch t.Kind() {\n\t\t\tcase types.Byte:\n\t\t\t\tbuf.WriteString(\"byte\")\n\t\t\tcase types.Rune:\n\t\t\t\tbuf.WriteString(\"rune\")\n\t\t\tcase types.UnsafePointer:\n\t\t\t\tbuf.WriteString(`(qual \"unsafe\" Pointer)`)\n\t\t\tdefault:\n\t\t\t\tif t.Info()&types.IsUntyped != 0 {\n\t\t\t\t\tpanic(\"fingerprint of untyped type\")\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(t.String())\n\t\t\t}\n\n\t\tcase *types.Signature:\n\t\t\tbuf.WriteString(\"(func \")\n\t\t\tprint(t.Params())\n\t\t\tif t.Variadic() {\n\t\t\t\tbuf.WriteString(\" v\")\n\t\t\t}\n\t\t\tbuf.WriteByte(' ')\n\t\t\tprint(t.Results())\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Struct:\n\t\t\t// Non-empty unnamed struct types in method\n\t\t\t// signatures are vanishingly rare.\n\t\t\tbuf.WriteString(\"(struct\")\n\t\t\tfor i := range t.NumFields() {\n\t\t\t\tf := t.Field(i)\n\t\t\t\tname := f.Name()\n\t\t\t\tif !f.Exported() {\n\t\t\t\t\tname = fmt.Sprintf(\"(qual %q %s)\", f.Pkg().Path(), name)\n\t\t\t\t}\n\n\t\t\t\t// This isn't quite right for embedded type aliases.\n\t\t\t\t// (See types.TypeString(StructType) and #44410 for context.)\n\t\t\t\t// But this is vanishingly rare.\n\t\t\t\tfmt.Fprintf(&buf, \" %s %t %q \", name, f.Embedded(), t.Tag(i))\n\t\t\t\tprint(f.Type())\n\t\t\t}\n\t\t\tbuf.WriteByte(')')\n\n\t\tcase *types.Interface:\n\t\t\tif t.NumMethods() == 0 {\n\t\t\t\tbuf.WriteString(\"any\") // common case\n\t\t\t} else {\n\t\t\t\t// Interface assignability is particularly\n\t\t\t\t// tricky due to the possibility of recursion.\n\t\t\t\t// However, nontrivial interface type literals\n\t\t\t\t// are exceedingly rare in function signatures.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): add disambiguating precision\n\t\t\t\t// (e.g. number of methods, their IDs and arities)\n\t\t\t\t// as needs arise (i.e. collisions are observed).\n\t\t\t\ttricky = true\n\t\t\t\tbuf.WriteString(\"(interface)\")\n\t\t\t}\n\n\t\tcase *types.TypeParam:\n\t\t\t// Matching of type parameters will require\n\t\t\t// parsing fingerprints and unification.\n\t\t\ttricky = true\n\t\t\tfmt.Fprintf(&buf, \"(%s %d)\", symTypeparam, t.Index())\n\n\t\tdefault: // incl. *types.Union\n\t\t\tpanic(t)\n\t\t}\n\t}\n\n\tprint(t)\n\n\treturn buf.String(), tricky\n}\n\n// sexpr defines the representation of a fingerprint tree.\ntype (\n\tsexpr  any // = string | int | symbol | *cons | nil\n\tsymbol string\n\tcons   struct{ car, cdr sexpr }\n)\n\n// parseFingerprint returns the type encoded by fp in tree form.\n//\n// The input must have been produced by [fingerprint] at the same\n// source version; parsing is thus infallible.\nfunc parseFingerprint(fp string) sexpr {\n\tvar scan scanner.Scanner\n\tscan.Error = func(scan *scanner.Scanner, msg string) { panic(msg) }\n\tscan.Init(strings.NewReader(fp))\n\n\t// next scans a token and updates tok.\n\tvar tok rune\n\tnext := func() { tok = scan.Scan() }\n\n\tnext()\n\n\t// parse parses a fingerprint and returns its tree.\n\tvar parse func() sexpr\n\tparse = func() sexpr {\n\t\tif tok == '(' {\n\t\t\tnext()         // consume '('\n\t\t\tvar head sexpr // empty list\n\t\t\ttailcdr := &head\n\t\t\tfor tok != ')' {\n\t\t\t\tcell := &cons{car: parse()}\n\t\t\t\t*tailcdr = cell\n\t\t\t\ttailcdr = &cell.cdr\n\t\t\t}\n\t\t\tnext() // consume ')'\n\t\t\treturn head\n\t\t}\n\n\t\ts := scan.TokenText()\n\t\tswitch tok {\n\t\tcase scanner.Ident:\n\t\t\tnext() // consume IDENT\n\t\t\treturn symbol(s)\n\n\t\tcase scanner.Int:\n\t\t\tnext() // consume INT\n\t\t\ti, err := strconv.Atoi(s)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\treturn i\n\n\t\tcase scanner.String:\n\t\t\tnext() // consume STRING\n\t\t\ts, err := strconv.Unquote(s)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\treturn s\n\n\t\tdefault:\n\t\t\tpanic(tok)\n\t\t}\n\t}\n\n\treturn parse()\n}\n\n// writeSexpr formats an S-expression.\n// It is provided for debugging.\nfunc writeSexpr(out *strings.Builder, x sexpr) {\n\tswitch x := x.(type) {\n\tcase nil:\n\t\tout.WriteString(\"()\")\n\tcase string:\n\t\tfmt.Fprintf(out, \"%q\", x)\n\tcase int:\n\t\tfmt.Fprintf(out, \"%d\", x)\n\tcase symbol:\n\t\tout.WriteString(string(x))\n\tcase *cons:\n\t\tout.WriteString(\"(\")\n\t\tfor {\n\t\t\twriteSexpr(out, x.car)\n\t\t\tif x.cdr == nil {\n\t\t\t\tbreak\n\t\t\t} else if cdr, ok := x.cdr.(*cons); ok {\n\t\t\t\tx = cdr\n\t\t\t\tout.WriteByte(' ')\n\t\t\t} else {\n\t\t\t\t// Dotted list: should never happen,\n\t\t\t\t// but support it for debugging.\n\t\t\t\tout.WriteString(\" . \")\n\t\t\t\tprint(x.cdr)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tout.WriteString(\")\")\n\tdefault:\n\t\tpanic(x)\n\t}\n}\n\n// unify reports whether x and y match, in the presence of type parameters.\n// The constraints on type parameters are ignored, but each type parameter must\n// have a consistent binding.\nfunc unify(x, y sexpr) bool {\n\n\t// maxTypeParam returns the maximum type parameter index in x.\n\tvar maxTypeParam func(x sexpr) int\n\tmaxTypeParam = func(x sexpr) int {\n\t\tif i := typeParamIndex(x); i >= 0 {\n\t\t\treturn i\n\t\t}\n\t\tif c, ok := x.(*cons); ok {\n\t\t\treturn max(maxTypeParam(c.car), maxTypeParam(c.cdr))\n\t\t}\n\t\treturn -1\n\t}\n\n\t// xBindings[i] is the binding for type parameter #i in x, and similarly for y.\n\t// Although type parameters are nominally bound to sexprs, each bindings[i]\n\t// is a *sexpr, so unbound variables can share a binding.\n\txBindings := make([]*sexpr, maxTypeParam(x)+1)\n\tfor i := range len(xBindings) {\n\t\txBindings[i] = new(sexpr)\n\t}\n\tyBindings := make([]*sexpr, maxTypeParam(y)+1)\n\tfor i := range len(yBindings) {\n\t\tyBindings[i] = new(sexpr)\n\t}\n\n\t// bind sets binding b to s from bindings if it does not occur in s.\n\tbind := func(b *sexpr, s sexpr, bindings []*sexpr) bool {\n\t\t// occurs reports whether b is present in s.\n\t\tvar occurs func(s sexpr) bool\n\t\toccurs = func(s sexpr) bool {\n\t\t\tif j := typeParamIndex(s); j >= 0 {\n\t\t\t\treturn b == bindings[j]\n\t\t\t}\n\t\t\tif c, ok := s.(*cons); ok {\n\t\t\t\treturn occurs(c.car) || occurs(c.cdr)\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\n\t\tif occurs(s) {\n\t\t\treturn false\n\t\t}\n\t\t*b = s\n\t\treturn true\n\t}\n\n\tvar uni func(x, y sexpr) bool\n\tuni = func(x, y sexpr) bool {\n\t\tvar bx, by *sexpr\n\t\tix := typeParamIndex(x)\n\t\tif ix >= 0 {\n\t\t\tbx = xBindings[ix]\n\t\t}\n\t\tiy := typeParamIndex(y)\n\t\tif iy >= 0 {\n\t\t\tby = yBindings[iy]\n\t\t}\n\n\t\tif bx != nil || by != nil {\n\t\t\t// If both args are type params and neither is bound, have them share a binding.\n\t\t\tif bx != nil && by != nil && *bx == nil && *by == nil {\n\t\t\t\txBindings[ix] = yBindings[iy]\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Treat param bindings like original args in what follows.\n\t\t\tif bx != nil && *bx != nil {\n\t\t\t\tx = *bx\n\t\t\t}\n\t\t\tif by != nil && *by != nil {\n\t\t\t\ty = *by\n\t\t\t}\n\t\t\t// If the x param is unbound, bind it to y.\n\t\t\tif bx != nil && *bx == nil {\n\t\t\t\treturn bind(bx, y, yBindings)\n\t\t\t}\n\t\t\t// If the y param is unbound, bind it to x.\n\t\t\tif by != nil && *by == nil {\n\t\t\t\treturn bind(by, x, xBindings)\n\t\t\t}\n\t\t\t// Unify the binding of a bound parameter.\n\t\t\treturn uni(x, y)\n\t\t}\n\n\t\t// Neither arg is a type param.\n\t\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\t\treturn false // type mismatch\n\t\t}\n\t\tswitch x := x.(type) {\n\t\tcase nil, string, int, symbol:\n\t\t\treturn x == y\n\t\tcase *cons:\n\t\t\ty := y.(*cons)\n\t\t\tif !uni(x.car, y.car) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif x.cdr == nil {\n\t\t\t\treturn y.cdr == nil\n\t\t\t}\n\t\t\tif y.cdr == nil {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn uni(x.cdr, y.cdr)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unify %T %T\", x, y))\n\t\t}\n\t}\n\t// At least one param is bound. Unify its binding with the other.\n\treturn uni(x, y)\n}\n\n// typeParamIndex returns the index of the type parameter,\n// if x has the form \"(typeparam INTEGER)\", otherwise -1.\nfunc typeParamIndex(x sexpr) int {\n\tif x, ok := x.(*cons); ok {\n\t\tif sym, ok := x.car.(symbol); ok && sym == symTypeparam {\n\t\t\treturn x.cdr.(*cons).car.(int)\n\t\t}\n\t}\n\treturn -1\n}\n\nconst symTypeparam = \"typeparam\"\n"
  },
  {
    "path": "gopls/internal/util/fingerprint/fingerprint_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fingerprint_test\n\nimport (\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/gopls/internal/util/fingerprint\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// Test runs the fingerprint encoder, decoder, and printer\n// on the types of all package-level symbols in gopls, and ensures\n// that parse+print is lossless.\nfunc Test(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping slow test\")\n\t}\n\n\tcfg := &packages.Config{Mode: packages.NeedTypes}\n\tpkgs, err := packages.Load(cfg, \"std\", \"golang.org/x/tools/gopls/...\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Record the fingerprint of each logical type (equivalence\n\t// class of types.Types) and assert that they are all equal.\n\t// (Non-tricky types only.)\n\tvar fingerprints typeutil.Map\n\n\tfor _, pkg := range pkgs {\n\t\tswitch pkg.Types.Path() {\n\t\tcase \"unsafe\", \"builtin\":\n\t\t\tcontinue\n\t\t}\n\t\tscope := pkg.Types.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\tobj := scope.Lookup(name)\n\t\t\ttyp := obj.Type()\n\n\t\t\tif basic, ok := typ.(*types.Basic); ok &&\n\t\t\t\tbasic.Info()&types.IsUntyped != 0 {\n\t\t\t\tcontinue // untyped constant\n\t\t\t}\n\n\t\t\tfp, tricky := fingerprint.Encode(typ) // check Type encoder doesn't panic\n\n\t\t\t// All equivalent (non-tricky) types have the same fingerprint.\n\t\t\tif !tricky {\n\t\t\t\tif prevfp, ok := fingerprints.At(typ).(string); !ok {\n\t\t\t\t\tfingerprints.Set(typ, fp)\n\t\t\t\t} else if fp != prevfp {\n\t\t\t\t\tt.Errorf(\"inconsistent fingerprints for type %v:\\n- old: %s\\n- new: %s\",\n\t\t\t\t\t\ttyp, fp, prevfp)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttree := fingerprint.Parse(fp) // check parser doesn't panic\n\t\t\tfp2 := tree.String()          // check formatter doesn't pannic\n\n\t\t\t// A parse+print round-trip should be lossless.\n\t\t\tif fp != fp2 {\n\t\t\t\tt.Errorf(\"%s: %v: parse+print changed fingerprint:\\n\"+\n\t\t\t\t\t\"was: %s\\ngot: %s\\ntype: %v\",\n\t\t\t\t\tpkg.Fset.Position(obj.Pos()), obj, fp, fp2, typ)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestMatches exercises the matching algorithm for generic types.\nfunc TestMatches(t *testing.T) {\n\tconst src = `\n-- go.mod --\nmodule example.com\ngo 1.24\n\n-- a/a.go --\npackage a\n\ntype Int = int\ntype String = string\n\n// Eq.Equal matches casefold.Equal.\ntype Eq[T any] interface { Equal(T, T) bool }\ntype casefold struct{}\nfunc (casefold) Equal(x, y string) bool\n\n// A matches AString.\ntype A[T any] = struct { x T }\ntype AString = struct { x string }\n\nfunc C1[T any](int, T, ...string) T { panic(0) }\nfunc C2[U any](int, int, ...U) bool { panic(0) }\nfunc C3(int, bool, ...string) rune\nfunc C4(int, bool, ...string)\nfunc C5(int, float64, bool, string) bool\nfunc C6(int, bool, ...string) bool\n\nfunc DAny[T any](Named[T]) { panic(0) }\nfunc DString(Named[string])\nfunc DInt(Named[int])\n\ntype Named[T any] struct { x T }\n\nfunc E1(byte) rune\nfunc E2(uint8) int32\nfunc E3(int8) uint32\n\n// generic vs. generic\nfunc F1[T any](T) { panic(0) }\nfunc F2[T any](*T) { panic(0) }\nfunc F3[T any](T, T) { panic(0) }\nfunc F4[U any](U, *U) { panic(0) }\nfunc F5[T, U any](T, U, U) { panic(0) }\nfunc F6[T any](T, int, T) { panic(0) }\nfunc F7[T any](bool, T, T) { panic(0) }\nfunc F8[V any](*V, int, int) { panic(0) }\nfunc F9[V any](V, *V, V) { panic(0) }\n`\n\tpkg := testfiles.LoadPackages(t, txtar.Parse([]byte(src)), \"./a\")[0]\n\tscope := pkg.Types.Scope()\n\tfor _, test := range []struct {\n\t\ta, b   string\n\t\tmethod string // optional field or method\n\t\twant   bool\n\t}{\n\t\t{\"Eq\", \"casefold\", \"Equal\", true},\n\t\t{\"A\", \"AString\", \"\", true},\n\t\t{\"A\", \"Eq\", \"\", false}, // completely unrelated\n\t\t{\"C1\", \"C2\", \"\", false},\n\t\t{\"C1\", \"C3\", \"\", false},\n\t\t{\"C1\", \"C4\", \"\", false},\n\t\t{\"C1\", \"C5\", \"\", false},\n\t\t{\"C1\", \"C6\", \"\", true},\n\t\t{\"C2\", \"C3\", \"\", false},\n\t\t{\"C2\", \"C4\", \"\", false},\n\t\t{\"C3\", \"C4\", \"\", false},\n\t\t{\"DAny\", \"DString\", \"\", true},\n\t\t{\"DAny\", \"DInt\", \"\", true},\n\t\t{\"DString\", \"DInt\", \"\", false}, // different instantiations of Named\n\t\t{\"E1\", \"E2\", \"\", true},         // byte and rune are just aliases\n\t\t{\"E2\", \"E3\", \"\", false},\n\t\t// The following tests cover all of the type param cases of unify.\n\t\t{\"F1\", \"F2\", \"\", true},  // F1[*int] = F2[int]\n\t\t{\"F3\", \"F4\", \"\", false}, // would require U identical to *U, prevented by occur check\n\t\t{\"F5\", \"F6\", \"\", true},  // one param is bound, the other is not\n\t\t{\"F6\", \"F7\", \"\", false}, // both are bound\n\t\t{\"F5\", \"F8\", \"\", true},  // T=*int, U=int, V=int\n\t\t{\"F5\", \"F9\", \"\", false}, // T is unbound, V is bound, and T occurs in V\n\t} {\n\t\tlookup := func(name string) types.Type {\n\t\t\tobj := scope.Lookup(name)\n\t\t\tif obj == nil {\n\t\t\t\tt.Fatalf(\"Lookup %s failed\", name)\n\t\t\t}\n\t\t\tif test.method != \"\" {\n\t\t\t\tobj, _, _ = types.LookupFieldOrMethod(obj.Type(), true, pkg.Types, test.method)\n\t\t\t\tif obj == nil {\n\t\t\t\t\tt.Fatalf(\"Lookup %s.%s failed\", name, test.method)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn obj.Type()\n\t\t}\n\n\t\tcheck := func(sa, sb string, want bool) {\n\t\t\tt.Helper()\n\n\t\t\ta := lookup(sa)\n\t\t\tb := lookup(sb)\n\n\t\t\tafp, _ := fingerprint.Encode(a)\n\t\t\tbfp, _ := fingerprint.Encode(b)\n\n\t\t\tatree := fingerprint.Parse(afp)\n\t\t\tbtree := fingerprint.Parse(bfp)\n\n\t\t\tgot := fingerprint.Matches(atree, btree)\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"a=%s b=%s method=%s: unify returned %t for these inputs:\\n- %s\\n- %s\",\n\t\t\t\t\tsa, sb, test.method, got, a, b)\n\t\t\t}\n\t\t}\n\n\t\tcheck(test.a, test.b, test.want)\n\t\t// Matches is symmetric\n\t\tcheck(test.b, test.a, test.want)\n\t\t// Matches is reflexive\n\t\tcheck(test.a, test.a, true)\n\t\tcheck(test.b, test.b, true)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/frob/frob.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package frob is a fast restricted object encoder/decoder in the\n// spirit of encoding/gob.\n//\n// As with gob, types that recursively contain functions, channels,\n// and unsafe.Pointers cannot be encoded, but frob has these\n// additional restrictions:\n//\n//   - Interface values are not supported; this avoids the need for\n//     the encoding to describe types.\n//\n//   - Private struct fields are ignored.\n//\n//   - The encoding is unspecified and subject to change, so the encoder\n//     and decoder must exactly agree on their implementation and on the\n//     definitions of the target types.\n//\n//   - Lengths (of arrays, slices, and maps) are currently assumed to\n//     fit in 32 bits.\n//\n//   - There is no error handling. All errors are reported by panicking.\n//\n//   - Values are serialized as trees, not graphs, so shared subgraphs\n//     are encoded repeatedly.\n//\n//   - No attempt is made to detect cyclic data structures.\npackage frob\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"sync\"\n)\n\n// A Codec[T] is an immutable encoder and decoder for values of type T.\ntype Codec[T any] struct{ frob *frob }\n\n// CodecFor[T] returns a codec for values of type T.\n// It panics if type T is unsuitable.\nfunc CodecFor[T any]() Codec[T] {\n\tfrobsMu.Lock()\n\tdefer frobsMu.Unlock()\n\treturn Codec[T]{frobFor(reflect.TypeFor[T]())}\n}\n\nfunc (codec Codec[T]) Encode(v T) []byte          { return codec.frob.Encode(v) }\nfunc (codec Codec[T]) Decode(data []byte, ptr *T) { codec.frob.Decode(data, ptr) }\n\nvar (\n\tfrobsMu sync.Mutex\n\tfrobs   = make(map[reflect.Type]*frob)\n)\n\n// A frob is an encoder/decoder for a specific type.\ntype frob struct {\n\tt     reflect.Type\n\tkind  reflect.Kind\n\telems []*frob // elem (array/slice/ptr), key+value (map), fields (struct)\n}\n\n// frobFor returns the frob for a particular type.\n// Precondition: caller holds frobsMu.\nfunc frobFor(t reflect.Type) *frob {\n\tfr, ok := frobs[t]\n\tif !ok {\n\t\tfr = &frob{t: t, kind: t.Kind()}\n\t\tfrobs[t] = fr\n\n\t\tswitch fr.kind {\n\t\tcase reflect.Bool,\n\t\t\treflect.Int,\n\t\t\treflect.Int8,\n\t\t\treflect.Int16,\n\t\t\treflect.Int32,\n\t\t\treflect.Int64,\n\t\t\treflect.Uint,\n\t\t\treflect.Uint8,\n\t\t\treflect.Uint16,\n\t\t\treflect.Uint32,\n\t\t\treflect.Uint64,\n\t\t\treflect.Uintptr,\n\t\t\treflect.Float32,\n\t\t\treflect.Float64,\n\t\t\treflect.Complex64,\n\t\t\treflect.Complex128,\n\t\t\treflect.String:\n\n\t\tcase reflect.Array,\n\t\t\treflect.Slice,\n\t\t\treflect.Pointer:\n\t\t\tfr.addElem(fr.t.Elem())\n\n\t\tcase reflect.Map:\n\t\t\tfr.addElem(fr.t.Key())\n\t\t\tfr.addElem(fr.t.Elem())\n\n\t\tcase reflect.Struct:\n\t\t\tfor i := 0; i < fr.t.NumField(); i++ {\n\t\t\t\tfield := fr.t.Field(i)\n\t\t\t\tif field.PkgPath != \"\" {\n\t\t\t\t\tcontinue // skip unexported field\n\t\t\t\t}\n\t\t\t\tfr.addElem(field.Type)\n\t\t\t}\n\n\t\tdefault:\n\t\t\t// chan, func, interface, unsafe.Pointer\n\t\t\tpanic(fmt.Sprintf(\"type %v is not supported by frob\", fr.t))\n\t\t}\n\t}\n\treturn fr\n}\n\nfunc (fr *frob) addElem(t reflect.Type) {\n\tfr.elems = append(fr.elems, frobFor(t))\n}\n\nconst magic = \"frob\"\n\nfunc (fr *frob) Encode(v any) []byte {\n\trv := reflect.ValueOf(v)\n\tif rv.Type() != fr.t {\n\t\tpanic(fmt.Sprintf(\"got %v, want %v\", rv.Type(), fr.t))\n\t}\n\tw := &writer{}\n\tw.bytes([]byte(magic))\n\tfr.encode(w, rv)\n\tif uint64(len(w.data))>>32 != 0 {\n\t\tpanic(\"too large\") // includes all cases where len doesn't fit in 32 bits\n\t}\n\treturn w.data\n}\n\n// encode appends the encoding of value v, whose type must be fr.t.\nfunc (fr *frob) encode(out *writer, v reflect.Value) {\n\tswitch fr.kind {\n\tcase reflect.Bool:\n\t\tvar b byte\n\t\tif v.Bool() {\n\t\t\tb = 1\n\t\t}\n\t\tout.uint8(b)\n\tcase reflect.Int:\n\t\tout.uint64(uint64(v.Int()))\n\tcase reflect.Int8:\n\t\tout.uint8(uint8(v.Int()))\n\tcase reflect.Int16:\n\t\tout.uint16(uint16(v.Int()))\n\tcase reflect.Int32:\n\t\tout.uint32(uint32(v.Int()))\n\tcase reflect.Int64:\n\t\tout.uint64(uint64(v.Int()))\n\tcase reflect.Uint:\n\t\tout.uint64(v.Uint())\n\tcase reflect.Uint8:\n\t\tout.uint8(uint8(v.Uint()))\n\tcase reflect.Uint16:\n\t\tout.uint16(uint16(v.Uint()))\n\tcase reflect.Uint32:\n\t\tout.uint32(uint32(v.Uint()))\n\tcase reflect.Uint64:\n\t\tout.uint64(v.Uint())\n\tcase reflect.Uintptr:\n\t\tout.uint64(v.Uint())\n\tcase reflect.Float32:\n\t\tout.uint32(math.Float32bits(float32(v.Float())))\n\tcase reflect.Float64:\n\t\tout.uint64(math.Float64bits(v.Float()))\n\tcase reflect.Complex64:\n\t\tz := complex64(v.Complex())\n\t\tout.uint32(math.Float32bits(real(z)))\n\t\tout.uint32(math.Float32bits(imag(z)))\n\tcase reflect.Complex128:\n\t\tz := v.Complex()\n\t\tout.uint64(math.Float64bits(real(z)))\n\t\tout.uint64(math.Float64bits(imag(z)))\n\n\tcase reflect.Array:\n\t\tlen := v.Type().Len()\n\t\telem := fr.elems[0]\n\t\tfor i := range len {\n\t\t\telem.encode(out, v.Index(i))\n\t\t}\n\n\tcase reflect.Slice:\n\t\tlen := v.Len()\n\t\tout.uint32(uint32(len))\n\t\tif len > 0 {\n\t\t\telem := fr.elems[0]\n\t\t\tif elem.kind == reflect.Uint8 {\n\t\t\t\t// []byte fast path\n\t\t\t\tout.bytes(v.Bytes())\n\t\t\t} else {\n\t\t\t\tfor i := range len {\n\t\t\t\t\telem.encode(out, v.Index(i))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase reflect.Map:\n\t\tlen := v.Len()\n\t\tout.uint32(uint32(len))\n\t\tif len > 0 {\n\t\t\tkfrob, vfrob := fr.elems[0], fr.elems[1]\n\t\t\tfor iter := v.MapRange(); iter.Next(); {\n\t\t\t\tkfrob.encode(out, iter.Key())\n\t\t\t\tvfrob.encode(out, iter.Value())\n\t\t\t}\n\t\t}\n\n\tcase reflect.Pointer:\n\t\tif v.IsNil() {\n\t\t\tout.uint8(0)\n\t\t} else {\n\t\t\tout.uint8(1)\n\t\t\tfr.elems[0].encode(out, v.Elem())\n\t\t}\n\n\tcase reflect.String:\n\t\tlen := v.Len()\n\t\tout.uint32(uint32(len))\n\t\tif len > 0 {\n\t\t\tout.data = append(out.data, v.String()...)\n\t\t}\n\n\tcase reflect.Struct:\n\t\tfor i, elem := range fr.elems {\n\t\t\telem.encode(out, v.Field(i))\n\t\t}\n\n\tdefault:\n\t\tpanic(fr.t)\n\t}\n}\n\nfunc (fr *frob) Decode(data []byte, ptr any) {\n\trv := reflect.ValueOf(ptr).Elem()\n\tif rv.Type() != fr.t {\n\t\tpanic(fmt.Sprintf(\"got %v, want %v\", rv.Type(), fr.t))\n\t}\n\trd := &reader{data}\n\tif len(data) < len(magic) || string(rd.bytes(len(magic))) != magic {\n\t\tpanic(\"not a frob-encoded message\") // (likely an empty message)\n\t}\n\tfr.decode(rd, rv)\n\tif len(rd.data) > 0 {\n\t\tpanic(\"surplus bytes\")\n\t}\n}\n\n// decode reads from in, decodes a value, and sets addr to it.\n// addr must be a zero-initialized addressable variable of type fr.t.\nfunc (fr *frob) decode(in *reader, addr reflect.Value) {\n\tswitch fr.kind {\n\tcase reflect.Bool:\n\t\taddr.SetBool(in.uint8() != 0)\n\tcase reflect.Int:\n\t\taddr.SetInt(int64(in.uint64()))\n\tcase reflect.Int8:\n\t\taddr.SetInt(int64(in.uint8()))\n\tcase reflect.Int16:\n\t\taddr.SetInt(int64(in.uint16()))\n\tcase reflect.Int32:\n\t\taddr.SetInt(int64(in.uint32()))\n\tcase reflect.Int64:\n\t\taddr.SetInt(int64(in.uint64()))\n\tcase reflect.Uint:\n\t\taddr.SetUint(in.uint64())\n\tcase reflect.Uint8:\n\t\taddr.SetUint(uint64(in.uint8()))\n\tcase reflect.Uint16:\n\t\taddr.SetUint(uint64(in.uint16()))\n\tcase reflect.Uint32:\n\t\taddr.SetUint(uint64(in.uint32()))\n\tcase reflect.Uint64:\n\t\taddr.SetUint(in.uint64())\n\tcase reflect.Uintptr:\n\t\taddr.SetUint(in.uint64())\n\tcase reflect.Float32:\n\t\taddr.SetFloat(float64(math.Float32frombits(in.uint32())))\n\tcase reflect.Float64:\n\t\taddr.SetFloat(math.Float64frombits(in.uint64()))\n\tcase reflect.Complex64:\n\t\taddr.SetComplex(complex128(complex(\n\t\t\tmath.Float32frombits(in.uint32()),\n\t\t\tmath.Float32frombits(in.uint32()),\n\t\t)))\n\tcase reflect.Complex128:\n\t\taddr.SetComplex(complex(\n\t\t\tmath.Float64frombits(in.uint64()),\n\t\t\tmath.Float64frombits(in.uint64()),\n\t\t))\n\n\tcase reflect.Array:\n\t\tlen := fr.t.Len()\n\t\tfor i := range len {\n\t\t\tfr.elems[0].decode(in, addr.Index(i))\n\t\t}\n\n\tcase reflect.Slice:\n\t\tlen := int(in.uint32())\n\t\tif len > 0 {\n\t\t\telem := fr.elems[0]\n\t\t\tif elem.kind == reflect.Uint8 {\n\t\t\t\t// []byte fast path\n\t\t\t\t// (Not addr.SetBytes: we must make a copy.)\n\t\t\t\taddr.Set(reflect.AppendSlice(addr, reflect.ValueOf(in.bytes(len))))\n\t\t\t} else {\n\t\t\t\taddr.Set(reflect.MakeSlice(fr.t, len, len))\n\t\t\t\tfor i := range len {\n\t\t\t\t\telem.decode(in, addr.Index(i))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase reflect.Map:\n\t\tlen := int(in.uint32())\n\t\tif len > 0 {\n\t\t\tm := reflect.MakeMapWithSize(fr.t, len)\n\t\t\taddr.Set(m)\n\t\t\tkfrob, vfrob := fr.elems[0], fr.elems[1]\n\t\t\tk := reflect.New(kfrob.t).Elem()\n\t\t\tv := reflect.New(vfrob.t).Elem()\n\t\t\tfor range len {\n\t\t\t\tk.SetZero()\n\t\t\t\tv.SetZero()\n\t\t\t\tkfrob.decode(in, k)\n\t\t\t\tvfrob.decode(in, v)\n\t\t\t\tm.SetMapIndex(k, v)\n\t\t\t}\n\t\t}\n\n\tcase reflect.Pointer:\n\t\tisNil := in.uint8() == 0\n\t\tif !isNil {\n\t\t\tptr := reflect.New(fr.elems[0].t)\n\t\t\taddr.Set(ptr)\n\t\t\tfr.elems[0].decode(in, ptr.Elem())\n\t\t}\n\n\tcase reflect.String:\n\t\tlen := int(in.uint32())\n\t\tif len > 0 {\n\t\t\taddr.SetString(string(in.bytes(len)))\n\t\t}\n\n\tcase reflect.Struct:\n\t\tfor i, elem := range fr.elems {\n\t\t\telem.decode(in, addr.Field(i))\n\t\t}\n\n\tdefault:\n\t\tpanic(fr.t)\n\t}\n}\n\nvar le = binary.LittleEndian\n\ntype reader struct{ data []byte }\n\nfunc (r *reader) uint8() uint8 {\n\tv := r.data[0]\n\tr.data = r.data[1:]\n\treturn v\n}\n\nfunc (r *reader) uint16() uint16 {\n\tv := le.Uint16(r.data)\n\tr.data = r.data[2:]\n\treturn v\n}\n\nfunc (r *reader) uint32() uint32 {\n\tv := le.Uint32(r.data)\n\tr.data = r.data[4:]\n\treturn v\n}\n\nfunc (r *reader) uint64() uint64 {\n\tv := le.Uint64(r.data)\n\tr.data = r.data[8:]\n\treturn v\n}\n\nfunc (r *reader) bytes(n int) []byte {\n\tv := r.data[:n]\n\tr.data = r.data[n:]\n\treturn v\n}\n\ntype writer struct{ data []byte }\n\nfunc (w *writer) uint8(v uint8)   { w.data = append(w.data, v) }\nfunc (w *writer) uint16(v uint16) { w.data = le.AppendUint16(w.data, v) }\nfunc (w *writer) uint32(v uint32) { w.data = le.AppendUint32(w.data, v) }\nfunc (w *writer) uint64(v uint64) { w.data = le.AppendUint64(w.data, v) }\nfunc (w *writer) bytes(v []byte)  { w.data = append(w.data, v...) }\n"
  },
  {
    "path": "gopls/internal/util/frob/frob_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage frob_test\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/frob\"\n)\n\nfunc TestBasics(t *testing.T) {\n\ttype Basics struct {\n\t\tA []*string\n\t\tB [2]int\n\t\tC *Basics\n\t\tD map[string]int\n\t\tE []byte\n\t\tF []string\n\t}\n\tcodec := frob.CodecFor[Basics]()\n\n\ts1, s2 := \"hello\", \"world\"\n\tx := Basics{\n\t\tA: []*string{&s1, nil, &s2},\n\t\tB: [...]int{1, 2},\n\t\tC: &Basics{\n\t\t\tB: [...]int{3, 4},\n\t\t\tD: map[string]int{\"one\": 1},\n\t\t},\n\t\tE: []byte(\"hello\"),\n\t\tF: []string{s1, s2},\n\t}\n\tvar y Basics\n\tcodec.Decode(codec.Encode(x), &y)\n\tif !reflect.DeepEqual(x, y) {\n\t\tt.Fatalf(\"bad roundtrip: got %#v, want %#v\", y, x)\n\t}\n}\n\nfunc TestInts(t *testing.T) {\n\ttype Ints struct {\n\t\tU    uint\n\t\tU8   uint8\n\t\tU16  uint16\n\t\tU32  uint32\n\t\tU64  uint64\n\t\tUP   uintptr\n\t\tI    int\n\t\tI8   int8\n\t\tI16  int16\n\t\tI32  int32\n\t\tI64  int64\n\t\tF32  float32\n\t\tF64  float64\n\t\tC64  complex64\n\t\tC128 complex128\n\t}\n\tcodec := frob.CodecFor[Ints]()\n\n\t// maxima\n\tmax1 := Ints{\n\t\tU:    math.MaxUint,\n\t\tU8:   math.MaxUint8,\n\t\tU16:  math.MaxUint16,\n\t\tU32:  math.MaxUint32,\n\t\tU64:  math.MaxUint64,\n\t\tUP:   math.MaxUint,\n\t\tI:    math.MaxInt,\n\t\tI8:   math.MaxInt8,\n\t\tI16:  math.MaxInt16,\n\t\tI32:  math.MaxInt32,\n\t\tI64:  math.MaxInt64,\n\t\tF32:  math.MaxFloat32,\n\t\tF64:  math.MaxFloat64,\n\t\tC64:  complex(math.MaxFloat32, math.MaxFloat32),\n\t\tC128: complex(math.MaxFloat64, math.MaxFloat64),\n\t}\n\tvar max2 Ints\n\tcodec.Decode(codec.Encode(max1), &max2)\n\tif !reflect.DeepEqual(max1, max2) {\n\t\tt.Fatalf(\"max: bad roundtrip: got %#v, want %#v\", max2, max1)\n\t}\n\n\t// minima\n\tmin1 := Ints{\n\t\tI:    math.MinInt,\n\t\tI8:   math.MinInt8,\n\t\tI16:  math.MinInt16,\n\t\tI32:  math.MinInt32,\n\t\tI64:  math.MinInt64,\n\t\tF32:  -math.MaxFloat32,\n\t\tF64:  -math.MaxFloat32,\n\t\tC64:  complex(-math.MaxFloat32, -math.MaxFloat32),\n\t\tC128: complex(-math.MaxFloat64, -math.MaxFloat64),\n\t}\n\tvar min2 Ints\n\tcodec.Decode(codec.Encode(min1), &min2)\n\tif !reflect.DeepEqual(min1, min2) {\n\t\tt.Fatalf(\"min: bad roundtrip: got %#v, want %#v\", min2, min1)\n\t}\n\n\t// negatives (other than MinInt), to exercise conversions\n\tneg1 := Ints{\n\t\tI:   -1,\n\t\tI8:  -1,\n\t\tI16: -1,\n\t\tI32: -1,\n\t\tI64: -1,\n\t}\n\tvar neg2 Ints\n\tcodec.Decode(codec.Encode(neg1), &neg2)\n\tif !reflect.DeepEqual(neg1, neg2) {\n\t\tt.Fatalf(\"neg: bad roundtrip: got %#v, want %#v\", neg2, neg1)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/goversion/goversion.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package goversions defines gopls's policy for which versions of Go it supports.\npackage goversion\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Support holds information about end-of-life Go version support.\n//\n// Exposed for testing.\ntype Support struct {\n\t// GoVersion is the Go version to which these settings relate.\n\tGoVersion int\n\n\t// DeprecatedVersion is the first version of gopls that no longer supports\n\t// this Go version.\n\t//\n\t// If unset, the version is already deprecated.\n\tDeprecatedVersion string\n\n\t// InstallGoplsVersion is the latest gopls version that supports this Go\n\t// version without warnings.\n\tInstallGoplsVersion string\n}\n\n// Supported maps Go versions to the gopls version in which support will\n// be deprecated, and the final gopls version supporting them without warnings.\n// Keep this in sync with gopls/doc/index.md.\n//\n// Must be sorted in ascending order of Go version.\n//\n// Exposed (and mutable) for testing.\nvar Supported = []Support{\n\t{12, \"\", \"v0.7.5\"},\n\t{15, \"\", \"v0.9.5\"},\n\t{16, \"\", \"v0.11.0\"},\n\t{17, \"\", \"v0.11.0\"},\n\t{18, \"\", \"v0.14.2\"},\n\t{19, \"v0.17.0\", \"v0.15.3\"},\n\t{20, \"v0.17.0\", \"v0.15.3\"},\n}\n\n// OldestSupported is the last X in Go 1.X that this version of gopls\n// supports without warnings.\n//\n// Exported for testing.\nfunc OldestSupported() int {\n\treturn Supported[len(Supported)-1].GoVersion + 1\n}\n\n// Message returns the message to display if the user has the given Go\n// version, if any. The goVersion variable is the X in Go 1.X. If\n// fromBuild is set, the Go version is the version used to build\n// gopls. Otherwise, it is the go command version.\n//\n// The second component of the result indicates whether the message is\n// an error, not a mere warning.\n//\n// If goVersion is invalid (< 0), it returns \"\", false.\nfunc Message(goVersion int, fromBuild bool) (string, bool) {\n\tif goVersion < 0 {\n\t\treturn \"\", false\n\t}\n\n\tfor _, v := range Supported {\n\t\tif goVersion <= v.GoVersion {\n\t\t\tvar msgBuilder strings.Builder\n\n\t\t\tisError := true\n\t\t\tif fromBuild {\n\t\t\t\tfmt.Fprintf(&msgBuilder, \"Gopls was built with Go version 1.%d\", goVersion)\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(&msgBuilder, \"Found Go version 1.%d\", goVersion)\n\t\t\t}\n\t\t\tif v.DeprecatedVersion != \"\" {\n\t\t\t\t// not deprecated yet, just a warning\n\t\t\t\tfmt.Fprintf(&msgBuilder, \", which will be unsupported by gopls %s. \", v.DeprecatedVersion)\n\t\t\t\tisError = false // warning\n\t\t\t} else {\n\t\t\t\tfmt.Fprint(&msgBuilder, \", which is not supported by this version of gopls. \")\n\t\t\t}\n\t\t\tfmt.Fprintf(&msgBuilder, \"Please upgrade to Go 1.%d or later and reinstall gopls. \", OldestSupported())\n\t\t\tfmt.Fprintf(&msgBuilder, \"If you can't upgrade and want this message to go away, please install gopls %s. \", v.InstallGoplsVersion)\n\t\t\tfmt.Fprint(&msgBuilder, \"See https://go.dev/s/gopls-support-policy for more details.\")\n\n\t\t\treturn msgBuilder.String(), isError\n\t\t}\n\t}\n\treturn \"\", false\n}\n"
  },
  {
    "path": "gopls/internal/util/goversion/goversion_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage goversion_test\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/goversion\"\n)\n\nfunc TestMessage(t *testing.T) {\n\t// Note(rfindley): this test is a change detector, as it must be updated\n\t// whenever we deprecate a version.\n\t//\n\t// However, I chose to leave it as is since it gives us confidence in error\n\t// messages served for Go versions that we no longer support (and therefore\n\t// no longer run in CI).\n\ttype test struct {\n\t\tgoVersion    int\n\t\tfromBuild    bool\n\t\twantContains []string // string fragments that we expect to see\n\t\twantIsError  bool     // an error, not a mere warning\n\t}\n\n\tdeprecated := func(goVersion int, lastVersion string) test {\n\t\treturn test{\n\t\t\tgoVersion: goVersion,\n\t\t\tfromBuild: false,\n\t\t\twantContains: []string{\n\t\t\t\tfmt.Sprintf(\"Found Go version 1.%d\", goVersion),\n\t\t\t\t\"not supported\",\n\t\t\t\tfmt.Sprintf(\"upgrade to Go 1.%d\", goversion.OldestSupported()),\n\t\t\t\tfmt.Sprintf(\"install gopls %s\", lastVersion),\n\t\t\t},\n\t\t\twantIsError: true,\n\t\t}\n\t}\n\n\ttests := []test{\n\t\t{-1, false, nil, false},\n\t\tdeprecated(12, \"v0.7.5\"),\n\t\tdeprecated(13, \"v0.9.5\"),\n\t\tdeprecated(15, \"v0.9.5\"),\n\t\tdeprecated(16, \"v0.11.0\"),\n\t\tdeprecated(17, \"v0.11.0\"),\n\t\tdeprecated(18, \"v0.14.2\"),\n\t\t{19, false, []string{\"Found Go version 1.19\", \"unsupported by gopls v0.17.0\", \"upgrade to Go 1.21\", \"install gopls v0.15.3\"}, false},\n\t\t{19, true, []string{\"Gopls was built with Go version 1.19\", \"unsupported by gopls v0.17.0\", \"upgrade to Go 1.21\", \"install gopls v0.15.3\"}, false},\n\t\t{20, false, []string{\"Found Go version 1.20\", \"unsupported by gopls v0.17.0\", \"upgrade to Go 1.21\", \"install gopls v0.15.3\"}, false},\n\t\t{20, true, []string{\"Gopls was built with Go version 1.20\", \"unsupported by gopls v0.17.0\", \"upgrade to Go 1.21\", \"install gopls v0.15.3\"}, false},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotMsg, gotIsError := goversion.Message(test.goVersion, test.fromBuild)\n\n\t\tif len(test.wantContains) == 0 && gotMsg != \"\" {\n\t\t\tt.Errorf(\"versionMessage(%d) = %q, want \\\"\\\"\", test.goVersion, gotMsg)\n\t\t}\n\n\t\tfor _, want := range test.wantContains {\n\t\t\tif !strings.Contains(gotMsg, want) {\n\t\t\t\tt.Errorf(\"versionMessage(%d) = %q, want containing %q\", test.goVersion, gotMsg, want)\n\t\t\t}\n\t\t}\n\n\t\tif gotIsError != test.wantIsError {\n\t\t\tt.Errorf(\"versionMessage(%d) isError = %v, want %v\", test.goVersion, gotIsError, test.wantIsError)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/immutable/immutable.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The immutable package defines immutable wrappers around common data\n// structures. These are used for additional type safety inside gopls.\n//\n// See the \"persistent\" package for copy-on-write data structures.\npackage immutable\n\nimport (\n\t\"iter\"\n\t\"maps\"\n)\n\n// Map is an immutable wrapper around an ordinary Go map.\ntype Map[K comparable, V any] struct {\n\tm map[K]V\n}\n\n// MapOf wraps the given Go map.\n//\n// The caller must not subsequently mutate the map.\nfunc MapOf[K comparable, V any](m map[K]V) Map[K, V] {\n\treturn Map[K, V]{m}\n}\n\n// Value returns the mapped value for k.\n// It is equivalent to the commaok form of an ordinary go map, and returns\n// (zero, false) if the key is not present.\nfunc (m Map[K, V]) Value(k K) (V, bool) {\n\tv, ok := m.m[k]\n\treturn v, ok\n}\n\n// Len returns the number of entries in the Map.\nfunc (m Map[K, V]) Len() int {\n\treturn len(m.m)\n}\n\n// All returns an iterator over each mapped (key, value) pair.\nfunc (m Map[K, V]) All() iter.Seq2[K, V] {\n\treturn maps.All(m.m)\n}\n"
  },
  {
    "path": "gopls/internal/util/lru/lru.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The lru package implements a fixed-size in-memory LRU cache.\npackage lru\n\nimport (\n\t\"container/heap\"\n\t\"fmt\"\n\t\"sync\"\n)\n\n// A Cache is a fixed-size in-memory LRU cache, storing values of type V keyed\n// by keys of type K.\ntype Cache[K comparable, V any] struct {\n\timpl *cache\n}\n\n// Get retrieves the value for the specified key.\n// If the key is found, its access time is updated.\n//\n// The second result reports whether the key was found.\nfunc (c *Cache[K, V]) Get(key K) (V, bool) {\n\tv, ok := c.impl.get(key)\n\tif !ok {\n\t\tvar zero V\n\t\treturn zero, false\n\t}\n\t// Handle untyped nil explicitly to avoid a panic in the type assertion\n\t// below.\n\tif v == nil {\n\t\tvar zero V\n\t\treturn zero, true\n\t}\n\treturn v.(V), true\n}\n\n// Set stores a value for the specified key, using its given size to update the\n// current cache size, evicting old entries as necessary to fit in the cache\n// capacity.\n//\n// Size must be a non-negative value. If size is larger than the cache\n// capacity, the value is not stored and the cache is not modified.\nfunc (c *Cache[K, V]) Set(key K, value V, size int) {\n\tc.impl.set(key, value, size)\n}\n\n// New creates a new Cache with the given capacity, which must be positive.\n//\n// The cache capacity uses arbitrary units, which are specified during the Set\n// operation.\nfunc New[K comparable, V any](capacity int) *Cache[K, V] {\n\tif capacity == 0 {\n\t\tpanic(\"zero capacity\")\n\t}\n\n\treturn &Cache[K, V]{&cache{\n\t\tcapacity: capacity,\n\t\tm:        make(map[any]*entry),\n\t}}\n}\n\n// cache is the non-generic implementation of [Cache].\n//\n// (Using a generic wrapper around a non-generic impl avoids unnecessary\n// \"stenciling\" or code duplication.)\ntype cache struct {\n\tcapacity int\n\n\tmu    sync.Mutex\n\tused  int            // used capacity, in user-specified units\n\tm     map[any]*entry // k/v lookup\n\tlru   queue          // min-atime priority queue of *entry\n\tclock int64          // clock time, incremented whenever the cache is updated\n}\n\ntype entry struct {\n\tkey   any\n\tvalue any\n\tsize  int   // caller-specified size\n\tatime int64 // last access / set time\n\tindex int   // index of entry in the heap slice\n}\n\nfunc (c *cache) get(key any) (any, bool) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tc.clock++ // every access updates the clock\n\n\tif e, ok := c.m[key]; ok { // cache hit\n\t\te.atime = c.clock\n\t\theap.Fix(&c.lru, e.index)\n\t\treturn e.value, true\n\t}\n\n\treturn nil, false\n}\n\nfunc (c *cache) set(key, value any, size int) {\n\tif size < 0 {\n\t\tpanic(fmt.Sprintf(\"size must be non-negative, got %d\", size))\n\t}\n\tif size > c.capacity {\n\t\treturn // uncacheable\n\t}\n\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tc.clock++\n\n\t// Remove the existing cache entry for key, if it exists.\n\te, ok := c.m[key]\n\tif ok {\n\t\tc.used -= e.size\n\t\theap.Remove(&c.lru, e.index)\n\t\tdelete(c.m, key)\n\t}\n\n\t// Evict entries until the new value will fit.\n\tnewUsed := c.used + size\n\tif newUsed < 0 {\n\t\treturn // integer overflow; return silently\n\t}\n\tc.used = newUsed\n\tfor c.used > c.capacity {\n\t\t// evict oldest entry\n\t\te = heap.Pop(&c.lru).(*entry)\n\t\tc.used -= e.size\n\t\tdelete(c.m, e.key)\n\t}\n\n\t// Store the new value.\n\t// Opt: e is evicted, so it can be reused to reduce allocation.\n\tif e == nil {\n\t\te = new(entry)\n\t}\n\te.key = key\n\te.value = value\n\te.size = size\n\te.atime = c.clock\n\tc.m[e.key] = e\n\theap.Push(&c.lru, e)\n\n\tif len(c.m) != len(c.lru) {\n\t\tpanic(\"map and LRU are inconsistent\")\n\t}\n}\n\n// -- priority queue boilerplate --\n\n// queue is a min-atime priority queue of cache entries.\ntype queue []*entry\n\nfunc (q queue) Len() int { return len(q) }\n\nfunc (q queue) Less(i, j int) bool { return q[i].atime < q[j].atime }\n\nfunc (q queue) Swap(i, j int) {\n\tq[i], q[j] = q[j], q[i]\n\tq[i].index = i\n\tq[j].index = j\n}\n\nfunc (q *queue) Push(x any) {\n\te := x.(*entry)\n\te.index = len(*q)\n\t*q = append(*q, e)\n}\n\nfunc (q *queue) Pop() any {\n\tlast := len(*q) - 1\n\te := (*q)[last]\n\t(*q)[last] = nil // aid GC\n\t*q = (*q)[:last]\n\treturn e\n}\n"
  },
  {
    "path": "gopls/internal/util/lru/lru_fuzz_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lru_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/lru\"\n)\n\n// Simple fuzzing test for consistency.\nfunc FuzzCache(f *testing.F) {\n\ttype op struct {\n\t\tset        bool\n\t\tkey, value byte\n\t}\n\tf.Fuzz(func(t *testing.T, data []byte) {\n\t\tvar ops []op\n\t\tfor len(data) >= 3 {\n\t\t\tops = append(ops, op{data[0]%2 == 0, data[1], data[2]})\n\t\t\tdata = data[3:]\n\t\t}\n\t\tcache := lru.New[byte, byte](100)\n\t\tvar reference [256]byte\n\t\tfor _, op := range ops {\n\t\t\tif op.set {\n\t\t\t\treference[op.key] = op.value\n\t\t\t\tcache.Set(op.key, op.value, 1)\n\t\t\t} else {\n\t\t\t\tif v, ok := cache.Get(op.key); ok && v != reference[op.key] {\n\t\t\t\t\tt.Fatalf(\"cache.Get(%d) = %d, want %d\", op.key, v, reference[op.key])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gopls/internal/util/lru/lru_nil_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lru_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/lru\"\n)\n\nfunc TestSetUntypedNil(t *testing.T) {\n\tcache := lru.New[any, any](100 * 1e6)\n\tcache.Set(nil, nil, 1)\n\tif got, ok := cache.Get(nil); !ok || got != nil {\n\t\tt.Errorf(\"cache.Get(nil) = %v, %v, want nil, true\", got, ok)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/lru/lru_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lru_test\n\nimport (\n\t\"bytes\"\n\tcryptorand \"crypto/rand\"\n\t\"fmt\"\n\t\"log\"\n\tmathrand \"math/rand\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/util/lru\"\n)\n\nfunc TestCache(t *testing.T) {\n\ttype get struct {\n\t\tkey  string\n\t\twant string\n\t}\n\ttype set struct {\n\t\tkey, value string\n\t}\n\n\ttests := []struct {\n\t\tlabel string\n\t\tsteps []any\n\t}{\n\t\t{\"empty cache\", []any{\n\t\t\tget{\"a\", \"\"},\n\t\t\tget{\"b\", \"\"},\n\t\t}},\n\t\t{\"zero-length string\", []any{\n\t\t\tset{\"a\", \"\"},\n\t\t\tget{\"a\", \"\"},\n\t\t}},\n\t\t{\"under capacity\", []any{\n\t\t\tset{\"a\", \"123\"},\n\t\t\tset{\"b\", \"456\"},\n\t\t\tget{\"a\", \"123\"},\n\t\t\tget{\"b\", \"456\"},\n\t\t}},\n\t\t{\"over capacity\", []any{\n\t\t\tset{\"a\", \"123\"},\n\t\t\tset{\"b\", \"456\"},\n\t\t\tset{\"c\", \"78901\"},\n\t\t\tget{\"a\", \"\"},\n\t\t\tget{\"b\", \"456\"},\n\t\t\tget{\"c\", \"78901\"},\n\t\t}},\n\t\t{\"access ordering\", []any{\n\t\t\tset{\"a\", \"123\"},\n\t\t\tset{\"b\", \"456\"},\n\t\t\tget{\"a\", \"123\"},\n\t\t\tset{\"c\", \"78901\"},\n\t\t\tget{\"a\", \"123\"},\n\t\t\tget{\"b\", \"\"},\n\t\t\tget{\"c\", \"78901\"},\n\t\t}},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tc := lru.New[string, string](10)\n\t\t\tfor i, step := range test.steps {\n\t\t\t\tswitch step := step.(type) {\n\t\t\t\tcase get:\n\t\t\t\t\tif got, _ := c.Get(step.key); got != step.want {\n\t\t\t\t\t\tt.Errorf(\"#%d: c.Get(%q) = %q, want %q\", i, step.key, got, step.want)\n\t\t\t\t\t}\n\t\t\t\tcase set:\n\t\t\t\t\tc.Set(step.key, step.value, len(step.value))\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestConcurrency exercises concurrent access to the same entry.\n//\n// It is a copy of TestConcurrency from the filecache package.\nfunc TestConcurrency(t *testing.T) {\n\tkey := uniqueKey()\n\tconst N = 100 // concurrency level\n\n\t// Construct N distinct values, each larger\n\t// than a typical 4KB OS file buffer page.\n\tvar values [N][8192]byte\n\tfor i := range values {\n\t\tif _, err := mathrand.Read(values[i][:]); err != nil {\n\t\t\tt.Fatalf(\"rand: %v\", err)\n\t\t}\n\t}\n\n\tcache := lru.New[[32]byte, []byte](100 * 1e6) // 100MB cache\n\n\t// get calls Get and verifies that the cache entry\n\t// matches one of the values passed to Set.\n\tget := func(mustBeFound bool) error {\n\t\tgot, ok := cache.Get(key)\n\t\tif !ok {\n\t\t\tif !mustBeFound {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"Get did not return a value\")\n\t\t}\n\t\tfor _, want := range values {\n\t\t\tif bytes.Equal(want[:], got) {\n\t\t\t\treturn nil // a match\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"Get returned a value that was never Set\")\n\t}\n\n\t// Perform N concurrent calls to Set and Get.\n\t// All sets must succeed.\n\t// All gets must return nothing, or one of the Set values;\n\t// there is no third possibility.\n\tvar group errgroup.Group\n\tfor i := range values {\n\t\tv := values[i][:]\n\t\tgroup.Go(func() error {\n\t\t\tcache.Set(key, v, len(v))\n\t\t\treturn nil\n\t\t})\n\t\tgroup.Go(func() error { return get(false) })\n\t}\n\tif err := group.Wait(); err != nil {\n\t\tif strings.Contains(err.Error(), \"operation not supported\") ||\n\t\t\tstrings.Contains(err.Error(), \"not implemented\") {\n\t\t\tt.Skipf(\"skipping: %v\", err)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\t// A final Get must report one of the values that was Set.\n\tif err := get(true); err != nil {\n\t\tt.Fatalf(\"final Get failed: %v\", err)\n\t}\n}\n\n// uniqueKey returns a key that has never been used before.\nfunc uniqueKey() (key [32]byte) {\n\tif _, err := cryptorand.Read(key[:]); err != nil {\n\t\tlog.Fatalf(\"rand: %v\", err)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/util/memoize/memoize.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package memoize defines a \"promise\" abstraction that enables\n// memoization of the result of calling an expensive but idempotent\n// function.\n//\n// Call p = NewPromise(f) to obtain a promise for the future result of\n// calling f(), and call p.Get() to obtain that result. All calls to\n// p.Get return the result of a single call of f().\n// Get blocks if the function has not finished (or started).\n//\n// A Store is a map of arbitrary keys to promises. Use Store.Promise\n// to create a promise in the store. All calls to Handle(k) return the\n// same promise as long as it is in the store. These promises are\n// reference-counted and must be explicitly released. Once the last\n// reference is released, the promise is removed from the store.\npackage memoize\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"runtime/trace\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// Function is the type of a function that can be memoized.\n//\n// If the arg is a RefCounted, its Acquire/Release operations are called.\n//\n// The argument must not materially affect the result of the function\n// in ways that are not captured by the promise's key, since if\n// Promise.Get is called twice concurrently, with the same (implicit)\n// key but different arguments, the Function is called only once but\n// its result must be suitable for both callers.\n//\n// The main purpose of the argument is to avoid the Function closure\n// needing to retain large objects (in practice: the snapshot) in\n// memory that can be supplied at call time by any caller.\ntype Function func(ctx context.Context, arg any) any\n\n// A RefCounted is a value whose functional lifetime is determined by\n// reference counting.\n//\n// Its Acquire method is called before the Function is invoked, and\n// the corresponding release is called when the Function returns.\n// Usually both events happen within a single call to Get, so Get\n// would be fine with a \"borrowed\" reference, but if the context is\n// cancelled, Get may return before the Function is complete, causing\n// the argument to escape, and potential premature destruction of the\n// value. For a reference-counted type, this requires a pair of\n// increment/decrement operations to extend its life.\ntype RefCounted interface {\n\t// Acquire prevents the value from being destroyed until the\n\t// returned function is called.\n\tAcquire() func()\n}\n\n// A Promise represents the future result of a call to a function.\ntype Promise struct {\n\tdebug string // for observability\n\n\t// refcount is the reference count in the containing Store, used by\n\t// Store.Promise. It is guarded by Store.promisesMu on the containing Store.\n\trefcount int32\n\n\tmu sync.Mutex\n\n\t// A Promise starts out IDLE, waiting for something to demand\n\t// its evaluation. It then transitions into RUNNING state.\n\t//\n\t// While RUNNING, waiters tracks the number of Get calls\n\t// waiting for a result, and the done channel is used to\n\t// notify waiters of the next state transition. Once\n\t// evaluation finishes, value is set, state changes to\n\t// COMPLETED, and done is closed, unblocking waiters.\n\t//\n\t// Alternatively, as Get calls are cancelled, they decrement\n\t// waiters. If it drops to zero, the inner context is\n\t// cancelled, computation is abandoned, and state resets to\n\t// IDLE to start the process over again.\n\tstate state\n\t// done is set in running state, and closed when exiting it.\n\tdone chan struct{}\n\t// cancel is set in running state. It cancels computation.\n\tcancel context.CancelFunc\n\t// waiters is the number of Gets outstanding.\n\twaiters uint\n\t// the function that will be used to populate the value\n\tfunction Function\n\t// value is set in completed state.\n\tvalue any\n}\n\n// NewPromise returns a promise for the future result of calling the\n// specified function.\n//\n// The debug string is used to classify promises in logs and metrics.\n// It should be drawn from a small set.\nfunc NewPromise(debug string, function Function) *Promise {\n\tif function == nil {\n\t\tpanic(\"nil function\")\n\t}\n\treturn &Promise{\n\t\tdebug:    debug,\n\t\tfunction: function,\n\t}\n}\n\ntype state int\n\nconst (\n\tstateIdle      = iota // newly constructed, or last waiter was cancelled\n\tstateRunning          // start was called and not cancelled\n\tstateCompleted        // function call ran to completion\n)\n\n// Cached returns the value associated with a promise.\n//\n// It will never cause the value to be generated.\n// It will return the cached value, if present.\nfunc (p *Promise) Cached() any {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\tif p.state == stateCompleted {\n\t\treturn p.value\n\t}\n\treturn nil\n}\n\n// Get returns the value associated with a promise.\n//\n// All calls to Promise.Get on a given promise return the\n// same result but the function is called (to completion) at most once.\n//\n// If the value is not yet ready, the underlying function will be invoked.\n//\n// If ctx is cancelled, Get returns (nil, Canceled).\n// If all concurrent calls to Get are cancelled, the context provided\n// to the function is cancelled. A later call to Get may attempt to\n// call the function again.\nfunc (p *Promise) Get(ctx context.Context, arg any) (any, error) {\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\tp.mu.Lock()\n\tswitch p.state {\n\tcase stateIdle:\n\t\treturn p.run(ctx, arg)\n\tcase stateRunning:\n\t\treturn p.wait(ctx)\n\tcase stateCompleted:\n\t\tdefer p.mu.Unlock()\n\t\treturn p.value, nil\n\tdefault:\n\t\tpanic(\"unknown state\")\n\t}\n}\n\n// run starts p.function and returns the result. p.mu must be locked.\nfunc (p *Promise) run(ctx context.Context, arg any) (any, error) {\n\tchildCtx, cancel := context.WithCancel(xcontext.Detach(ctx))\n\tp.cancel = cancel\n\tp.state = stateRunning\n\tp.done = make(chan struct{})\n\tfunction := p.function // Read under the lock\n\n\t// Make sure that the argument isn't destroyed while we're running in it.\n\trelease := func() {}\n\tif rc, ok := arg.(RefCounted); ok {\n\t\trelease = rc.Acquire()\n\t}\n\n\tgo func() {\n\t\ttrace.WithRegion(childCtx, fmt.Sprintf(\"Promise.run %s\", p.debug), func() {\n\t\t\tdefer release()\n\t\t\t// Just in case the function does something expensive without checking\n\t\t\t// the context, double-check we're still alive.\n\t\t\tif childCtx.Err() != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tv := function(childCtx, arg)\n\t\t\tif childCtx.Err() != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tp.mu.Lock()\n\t\t\tdefer p.mu.Unlock()\n\t\t\t// It's theoretically possible that the promise has been cancelled out\n\t\t\t// of the run that started us, and then started running again since we\n\t\t\t// checked childCtx above. Even so, that should be harmless, since each\n\t\t\t// run should produce the same results.\n\t\t\tif p.state != stateRunning {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tp.value = v\n\t\t\tp.function = nil // aid GC\n\t\t\tp.state = stateCompleted\n\t\t\tclose(p.done)\n\t\t})\n\t}()\n\n\treturn p.wait(ctx)\n}\n\n// wait waits for the value to be computed, or ctx to be cancelled. p.mu must be locked.\nfunc (p *Promise) wait(ctx context.Context) (any, error) {\n\tp.waiters++\n\tdone := p.done\n\tp.mu.Unlock()\n\n\tselect {\n\tcase <-done:\n\t\tp.mu.Lock()\n\t\tdefer p.mu.Unlock()\n\t\tif p.state == stateCompleted {\n\t\t\treturn p.value, nil\n\t\t}\n\t\treturn nil, nil\n\tcase <-ctx.Done():\n\t\tp.mu.Lock()\n\t\tdefer p.mu.Unlock()\n\t\tp.waiters--\n\t\tif p.waiters == 0 && p.state == stateRunning {\n\t\t\tp.cancel()\n\t\t\tclose(p.done)\n\t\t\tp.state = stateIdle\n\t\t\tp.done = nil\n\t\t\tp.cancel = nil\n\t\t}\n\t\treturn nil, ctx.Err()\n\t}\n}\n\n// An EvictionPolicy controls the eviction behavior of keys in a Store when\n// they no longer have any references.\ntype EvictionPolicy int\n\nconst (\n\t// ImmediatelyEvict evicts keys as soon as they no longer have references.\n\tImmediatelyEvict EvictionPolicy = iota\n\n\t// NeverEvict does not evict keys.\n\tNeverEvict\n)\n\n// A Store maps arbitrary keys to reference-counted promises.\n//\n// The zero value is a valid Store, though a store may also be created via\n// NewStore if a custom EvictionPolicy is required.\ntype Store struct {\n\tevictionPolicy EvictionPolicy\n\n\tpromisesMu sync.Mutex\n\tpromises   map[any]*Promise\n}\n\n// NewStore creates a new store with the given eviction policy.\nfunc NewStore(policy EvictionPolicy) *Store {\n\treturn &Store{evictionPolicy: policy}\n}\n\n// Promise returns a reference-counted promise for the future result of\n// calling the specified function.\n//\n// Calls to Promise with the same key return the same promise, incrementing its\n// reference count.  The caller must call the returned function to decrement\n// the promise's reference count when it is no longer needed. The returned\n// function must not be called more than once.\n//\n// Once the last reference has been released, the promise is removed from the\n// store.\nfunc (store *Store) Promise(key any, function Function) (*Promise, func()) {\n\tstore.promisesMu.Lock()\n\tp, ok := store.promises[key]\n\tif !ok {\n\t\tp = NewPromise(reflect.TypeOf(key).String(), function)\n\t\tif store.promises == nil {\n\t\t\tstore.promises = map[any]*Promise{}\n\t\t}\n\t\tstore.promises[key] = p\n\t}\n\tp.refcount++\n\tstore.promisesMu.Unlock()\n\n\tvar released int32\n\trelease := func() {\n\t\tif !atomic.CompareAndSwapInt32(&released, 0, 1) {\n\t\t\tpanic(\"release called more than once\")\n\t\t}\n\t\tstore.promisesMu.Lock()\n\n\t\tp.refcount--\n\t\tif p.refcount == 0 && store.evictionPolicy != NeverEvict {\n\t\t\t// Inv: if p.refcount > 0, then store.promises[key] == p.\n\t\t\tdelete(store.promises, key)\n\t\t}\n\t\tstore.promisesMu.Unlock()\n\t}\n\n\treturn p, release\n}\n\n// Stats returns the number of each type of key in the store.\nfunc (s *Store) Stats() map[reflect.Type]int {\n\tresult := map[reflect.Type]int{}\n\n\ts.promisesMu.Lock()\n\tdefer s.promisesMu.Unlock()\n\n\tfor k := range s.promises {\n\t\tresult[reflect.TypeOf(k)]++\n\t}\n\treturn result\n}\n\n// DebugOnlyIterate iterates through the store and, for each completed\n// promise, calls f(k, v) for the map key k and function result v.  It\n// should only be used for debugging purposes.\nfunc (s *Store) DebugOnlyIterate(f func(k, v any)) {\n\ts.promisesMu.Lock()\n\tdefer s.promisesMu.Unlock()\n\n\tfor k, p := range s.promises {\n\t\tif v := p.Cached(); v != nil {\n\t\t\tf(k, v)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/memoize/memoize_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage memoize_test\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/util/memoize\"\n)\n\nfunc TestGet(t *testing.T) {\n\tvar store memoize.Store\n\n\tevaled := 0\n\n\th, release := store.Promise(\"key\", func(context.Context, any) any {\n\t\tevaled++\n\t\treturn \"res\"\n\t})\n\tdefer release()\n\texpectGet(t, h, \"res\")\n\texpectGet(t, h, \"res\")\n\tif evaled != 1 {\n\t\tt.Errorf(\"got %v calls to function, wanted 1\", evaled)\n\t}\n}\n\nfunc expectGet(t *testing.T, h *memoize.Promise, wantV any) {\n\tt.Helper()\n\tgotV, gotErr := h.Get(context.Background(), nil)\n\tif gotV != wantV || gotErr != nil {\n\t\tt.Fatalf(\"Get() = %v, %v, wanted %v, nil\", gotV, gotErr, wantV)\n\t}\n}\n\nfunc TestNewPromise(t *testing.T) {\n\tcalls := 0\n\tf := func(context.Context, any) any {\n\t\tcalls++\n\t\treturn calls\n\t}\n\n\t// All calls to Get on the same promise return the same result.\n\tp1 := memoize.NewPromise(\"debug\", f)\n\texpectGet(t, p1, 1)\n\texpectGet(t, p1, 1)\n\n\t// A new promise calls the function again.\n\tp2 := memoize.NewPromise(\"debug\", f)\n\texpectGet(t, p2, 2)\n\texpectGet(t, p2, 2)\n\n\t// The original promise is unchanged.\n\texpectGet(t, p1, 1)\n}\n\nfunc TestStoredPromiseRefCounting(t *testing.T) {\n\tvar store memoize.Store\n\tv1 := false\n\tv2 := false\n\tp1, release1 := store.Promise(\"key1\", func(context.Context, any) any {\n\t\treturn &v1\n\t})\n\tp2, release2 := store.Promise(\"key2\", func(context.Context, any) any {\n\t\treturn &v2\n\t})\n\texpectGet(t, p1, &v1)\n\texpectGet(t, p2, &v2)\n\n\texpectGet(t, p1, &v1)\n\texpectGet(t, p2, &v2)\n\n\tp2Copy, release2Copy := store.Promise(\"key2\", func(context.Context, any) any {\n\t\treturn &v1\n\t})\n\tif p2 != p2Copy {\n\t\tt.Error(\"Promise returned a new value while old is not destroyed yet\")\n\t}\n\texpectGet(t, p2Copy, &v2)\n\n\trelease2()\n\tif got, want := v2, false; got != want {\n\t\tt.Errorf(\"after destroying first v2 ref, got %v, want %v\", got, want)\n\t}\n\trelease2Copy()\n\tif got, want := v1, false; got != want {\n\t\tt.Errorf(\"after destroying v2, got %v, want %v\", got, want)\n\t}\n\trelease1()\n\n\tp2Copy, release2Copy = store.Promise(\"key2\", func(context.Context, any) any {\n\t\treturn &v2\n\t})\n\tif p2 == p2Copy {\n\t\tt.Error(\"Promise returned previously destroyed value\")\n\t}\n\trelease2Copy()\n}\n\nfunc TestPromiseDestroyedWhileRunning(t *testing.T) {\n\t// Test that calls to Promise.Get return even if the promise is destroyed while running.\n\n\tvar store memoize.Store\n\tc := make(chan int)\n\n\tvar v int\n\th, release := store.Promise(\"key\", func(ctx context.Context, _ any) any {\n\t\t<-c\n\t\t<-c\n\t\tif err := ctx.Err(); err != nil {\n\t\t\tt.Errorf(\"ctx.Err() = %v, want nil\", err)\n\t\t}\n\t\treturn &v\n\t})\n\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // arbitrary timeout; may be removed if it causes flakes\n\tdefer cancel()\n\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tvar got any\n\tvar err error\n\tgo func() {\n\t\tgot, err = h.Get(ctx, nil)\n\t\twg.Done()\n\t}()\n\n\tc <- 0    // send once to enter the promise function\n\trelease() // release before the promise function returns\n\tc <- 0    // let the promise function proceed\n\n\twg.Wait()\n\n\tif err != nil {\n\t\tt.Errorf(\"Get() failed: %v\", err)\n\t}\n\tif got != &v {\n\t\tt.Errorf(\"Get() = %v, want %v\", got, v)\n\t}\n}\n\nfunc TestDoubleReleasePanics(t *testing.T) {\n\tvar store memoize.Store\n\t_, release := store.Promise(\"key\", func(ctx context.Context, _ any) any { return 0 })\n\n\tpanicked := false\n\n\tfunc() {\n\t\tdefer func() {\n\t\t\tif recover() != nil {\n\t\t\t\tpanicked = true\n\t\t\t}\n\t\t}()\n\t\trelease()\n\t\trelease()\n\t}()\n\n\tif !panicked {\n\t\tt.Errorf(\"calling release() twice did not panic\")\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/moremaps/maps.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage moremaps\n\nimport (\n\t\"cmp\"\n\t\"iter\"\n\t\"maps\"\n\t\"slices\"\n)\n\n// Arbitrary returns an arbitrary (key, value) entry from the map and ok is true, if\n// the map is not empty. Otherwise, it returns zero values for K and V, and false.\nfunc Arbitrary[K comparable, V any](m map[K]V) (_ K, _ V, ok bool) {\n\tfor k, v := range m {\n\t\treturn k, v, true\n\t}\n\treturn\n}\n\n// Group returns a new non-nil map containing the elements of s grouped by the\n// keys returned from the key func.\nfunc Group[K comparable, V any](s []V, key func(V) K) map[K][]V {\n\tm := make(map[K][]V)\n\tfor _, v := range s {\n\t\tk := key(v)\n\t\tm[k] = append(m[k], v)\n\t}\n\treturn m\n}\n\n// KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)).\nfunc KeySlice[M ~map[K]V, K comparable, V any](m M) []K {\n\tr := make([]K, 0, len(m))\n\tfor k := range m {\n\t\tr = append(r, k)\n\t}\n\treturn r\n}\n\n// ValueSlice returns the values of the map M, like slices.Collect(maps.Values(m)).\nfunc ValueSlice[M ~map[K]V, K comparable, V any](m M) []V {\n\tr := make([]V, 0, len(m))\n\tfor _, v := range m {\n\t\tr = append(r, v)\n\t}\n\treturn r\n}\n\n// SameKeys reports whether x and y have equal sets of keys.\nfunc SameKeys[K comparable, V1, V2 any](x map[K]V1, y map[K]V2) bool {\n\tignoreValues := func(V1, V2) bool { return true }\n\treturn maps.EqualFunc(x, y, ignoreValues)\n}\n\n// Sorted returns an iterator over the entries of m in key order.\nfunc Sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] {\n\t// TODO(adonovan): use maps.Sorted if proposal #68598 is accepted.\n\treturn func(yield func(K, V) bool) {\n\t\tkeys := KeySlice(m)\n\t\tslices.Sort(keys)\n\t\tfor _, k := range keys {\n\t\t\tif !yield(k, m[k]) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// SortedFunc returns an iterator over the entries of m in the key order determined by cmp.\nfunc SortedFunc[M ~map[K]V, K comparable, V any](m M, cmp func(x, y K) int) iter.Seq2[K, V] {\n\t// TODO(adonovan): use maps.SortedFunc if proposal #68598 is accepted.\n\treturn func(yield func(K, V) bool) {\n\t\tkeys := KeySlice(m)\n\t\tslices.SortFunc(keys, cmp)\n\t\tfor _, k := range keys {\n\t\t\tif !yield(k, m[k]) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/moreslices/slices.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage moreslices\n\n// Remove removes all values equal to elem from slice.\n//\n// The closest equivalent in the standard slices package is:\n//\n//\tDeleteFunc(func(x T) bool { return x == elem })\nfunc Remove[T comparable](slice []T, elem T) []T {\n\tout := slice[:0]\n\tfor _, v := range slice {\n\t\tif v != elem {\n\t\t\tout = append(out, v)\n\t\t}\n\t}\n\treturn out\n}\n\n// ConvertStrings converts a slice of type A (with underlying type string)\n// to a slice of type B (with underlying type string).\nfunc ConvertStrings[B, A ~string](input []A) []B {\n\tresult := make([]B, len(input))\n\tfor i, v := range input {\n\t\tresult[i] = B(string(v))\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "gopls/internal/util/morestrings/strings.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage morestrings\n\nimport \"strings\"\n\n// CutLast is the \"last\" analogue of [strings.Cut].\nfunc CutLast(s, sep string) (before, after string, ok bool) {\n\tif i := strings.LastIndex(s, sep); i >= 0 {\n\t\treturn s[:i], s[i+len(sep):], true\n\t}\n\treturn s, \"\", false\n}\n"
  },
  {
    "path": "gopls/internal/util/pathutil/util.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pathutil\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// InDir checks whether path is in the file tree rooted at dir.\n// It checks only the lexical form of the file names.\n// It does not consider symbolic links.\n//\n// Copied from go/src/cmd/go/internal/search/search.go.\nfunc InDir(dir, path string) bool {\n\tpv := strings.ToUpper(filepath.VolumeName(path))\n\tdv := strings.ToUpper(filepath.VolumeName(dir))\n\tpath = path[len(pv):]\n\tdir = dir[len(dv):]\n\tswitch {\n\tdefault:\n\t\treturn false\n\tcase pv != dv:\n\t\treturn false\n\tcase len(path) == len(dir):\n\t\tif path == dir {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\tcase dir == \"\":\n\t\treturn path != \"\"\n\tcase len(path) > len(dir):\n\t\tif dir[len(dir)-1] == filepath.Separator {\n\t\t\tif path[:len(dir)] == dir {\n\t\t\t\treturn path[len(dir):] != \"\"\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\tif path[len(dir)] == filepath.Separator && path[:len(dir)] == dir {\n\t\t\tif len(path) == len(dir)+1 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn path[len(dir)+1:] != \"\"\n\t\t}\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/persistent/map.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The persistent package defines various persistent data structures;\n// that is, data structures that can be efficiently copied and modified\n// in sublinear time.\npackage persistent\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"math/rand\"\n\t\"strings\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/gopls/internal/util/constraints\"\n)\n\n// Implementation details:\n// * Each value is reference counted by nodes which hold it.\n// * Each node is reference counted by its parent nodes.\n// * Each map is considered a top-level parent node from reference counting perspective.\n// * Each change does always effectively produce a new top level node.\n//\n// Functions which operate directly with nodes do have a notation in form of\n// `foo(arg1:+n1, arg2:+n2) (ret1:+n3)`.\n// Each argument is followed by a delta change to its reference counter.\n// In case if no change is expected, the delta will be `-0`.\n//\n// TODO(rfindley): add Update(K, func(V, bool) V), as we have several instances\n// of the Get-<check>-Set pattern that could be optimized.\n\n// Map is an associative mapping from keys to values.\n//\n// Maps can be Cloned in constant time.\n// Get, Set, and Delete operations are done on average in logarithmic time.\n// Maps can be merged (via SetAll) in O(m log(n/m)) time for maps of size n and m, where m < n.\n//\n// Values are reference counted, and a client-supplied release function\n// is called when a value is no longer referenced by a map or any clone.\n//\n// Internally the implementation is based on a randomized persistent treap:\n// https://en.wikipedia.org/wiki/Treap.\n//\n// The zero value is ready to use.\ntype Map[K constraints.Ordered, V any] struct {\n\t// Map is a generic wrapper around a non-generic implementation to avoid a\n\t// significant increase in the size of the executable.\n\troot *mapNode\n}\n\nfunc (*Map[K, V]) less(l, r any) bool {\n\treturn l.(K) < r.(K)\n}\n\nfunc (m *Map[K, V]) String() string {\n\tvar buf strings.Builder\n\tbuf.WriteByte('{')\n\tvar sep string\n\tfor k, v := range m.All() {\n\t\tfmt.Fprintf(&buf, \"%s%v: %v\", sep, k, v)\n\t\tsep = \", \"\n\t}\n\tbuf.WriteByte('}')\n\treturn buf.String()\n}\n\ntype mapNode struct {\n\tkey         any\n\tvalue       *refValue\n\tweight      uint64\n\trefCount    int32\n\tleft, right *mapNode\n}\n\ntype refValue struct {\n\trefCount int32\n\tvalue    any\n\trelease  func(key, value any)\n}\n\nfunc newNodeWithRef[K constraints.Ordered, V any](key K, value V, release func(key, value any)) *mapNode {\n\treturn &mapNode{\n\t\tkey: key,\n\t\tvalue: &refValue{\n\t\t\tvalue:    value,\n\t\t\trelease:  release,\n\t\t\trefCount: 1,\n\t\t},\n\t\trefCount: 1,\n\t\tweight:   rand.Uint64(),\n\t}\n}\n\nfunc (node *mapNode) shallowCloneWithRef() *mapNode {\n\tatomic.AddInt32(&node.value.refCount, 1)\n\treturn &mapNode{\n\t\tkey:      node.key,\n\t\tvalue:    node.value,\n\t\tweight:   node.weight,\n\t\trefCount: 1,\n\t}\n}\n\nfunc (node *mapNode) incref() *mapNode {\n\tif node != nil {\n\t\tatomic.AddInt32(&node.refCount, 1)\n\t}\n\treturn node\n}\n\nfunc (node *mapNode) decref() {\n\tif node == nil {\n\t\treturn\n\t}\n\tif atomic.AddInt32(&node.refCount, -1) == 0 {\n\t\tif atomic.AddInt32(&node.value.refCount, -1) == 0 {\n\t\t\tif node.value.release != nil {\n\t\t\t\tnode.value.release(node.key, node.value.value)\n\t\t\t}\n\t\t\tnode.value.value = nil\n\t\t\tnode.value.release = nil\n\t\t}\n\t\tnode.left.decref()\n\t\tnode.right.decref()\n\t}\n}\n\n// Clone returns a copy of the given map. It is a responsibility of the caller\n// to Destroy it at later time.\nfunc (pm *Map[K, V]) Clone() *Map[K, V] {\n\treturn &Map[K, V]{\n\t\troot: pm.root.incref(),\n\t}\n}\n\n// Destroy destroys the map.\n//\n// After Destroy, the Map should not be used again.\nfunc (pm *Map[K, V]) Destroy() {\n\t// The implementation of these two functions is the same,\n\t// but their intent is different.\n\tpm.Clear()\n}\n\n// Clear removes all entries from the map.\nfunc (pm *Map[K, V]) Clear() {\n\tpm.root.decref()\n\tpm.root = nil\n}\n\n// Keys returns the ascending sequence of keys present in the map.\nfunc (pm *Map[K, V]) Keys() iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tpm.root.forEach(func(k, _ any) bool {\n\t\t\treturn yield(k.(K))\n\t\t})\n\t}\n}\n\n// All returns the sequence of map entries in ascending key order.\nfunc (pm *Map[K, V]) All() iter.Seq2[K, V] {\n\treturn func(yield func(K, V) bool) {\n\t\tpm.root.forEach(func(k, v any) bool {\n\t\t\treturn yield(k.(K), v.(V))\n\t\t})\n\t}\n}\n\nfunc (node *mapNode) forEach(yield func(key, value any) bool) bool {\n\treturn node == nil ||\n\t\tnode.left.forEach(yield) &&\n\t\t\tyield(node.key, node.value.value) &&\n\t\t\tnode.right.forEach(yield)\n}\n\n// Get returns the map value associated with the specified key.\n// The ok result indicates whether an entry was found in the map.\nfunc (pm *Map[K, V]) Get(key K) (V, bool) {\n\tnode := pm.root\n\tfor node != nil {\n\t\tif key < node.key.(K) {\n\t\t\tnode = node.left\n\t\t} else if node.key.(K) < key {\n\t\t\tnode = node.right\n\t\t} else {\n\t\t\treturn node.value.value.(V), true\n\t\t}\n\t}\n\tvar zero V\n\treturn zero, false\n}\n\n// SetAll updates the map with key/value pairs from the other map, overwriting existing keys.\n// It is equivalent to calling Set for each entry in the other map but is more efficient.\nfunc (pm *Map[K, V]) SetAll(other *Map[K, V]) {\n\troot := pm.root\n\tpm.root = union(root, other.root, pm.less, true)\n\troot.decref()\n}\n\n// Set updates the value associated with the specified key.\n// If release is non-nil, it will be called with entry's key and value once the\n// key is no longer contained in the map or any clone.\n//\n// TODO(adonovan): fix release, which has the wrong type.\nfunc (pm *Map[K, V]) Set(key K, value V, release func(key, value any)) {\n\tfirst := pm.root\n\tsecond := newNodeWithRef(key, value, release)\n\tpm.root = union(first, second, pm.less, true)\n\tfirst.decref()\n\tsecond.decref()\n}\n\n// union returns a new tree which is a union of first and second one.\n// If overwrite is set to true, second one would override a value for any duplicate keys.\n//\n// union(first:-0, second:-0) (result:+1)\n// Union borrows both subtrees without affecting their refcount and returns a\n// new reference that the caller is expected to call decref.\nfunc union(first, second *mapNode, less func(any, any) bool, overwrite bool) *mapNode {\n\tif first == nil {\n\t\treturn second.incref()\n\t}\n\tif second == nil {\n\t\treturn first.incref()\n\t}\n\n\tif first.weight < second.weight {\n\t\tsecond, first, overwrite = first, second, !overwrite\n\t}\n\n\tleft, mid, right := split(second, first.key, less, false)\n\tvar result *mapNode\n\tif overwrite && mid != nil {\n\t\tresult = mid.shallowCloneWithRef()\n\t} else {\n\t\tresult = first.shallowCloneWithRef()\n\t}\n\tresult.weight = first.weight\n\tresult.left = union(first.left, left, less, overwrite)\n\tresult.right = union(first.right, right, less, overwrite)\n\tleft.decref()\n\tmid.decref()\n\tright.decref()\n\treturn result\n}\n\n// split the tree midway by the key into three different ones.\n// Return three new trees: left with all nodes with smaller than key, mid with\n// the node matching the key, right with all nodes larger than key.\n// If there are no nodes in one of trees, return nil instead of it.\n// If requireMid is set (such as during deletion), then all return arguments\n// are nil if mid is not found.\n//\n// split(n:-0) (left:+1, mid:+1, right:+1)\n// Split borrows n without affecting its refcount, and returns three\n// new references that the caller is expected to call decref.\nfunc split(n *mapNode, key any, less func(any, any) bool, requireMid bool) (left, mid, right *mapNode) {\n\tif n == nil {\n\t\treturn nil, nil, nil\n\t}\n\n\tif less(n.key, key) {\n\t\tleft, mid, right := split(n.right, key, less, requireMid)\n\t\tif requireMid && mid == nil {\n\t\t\treturn nil, nil, nil\n\t\t}\n\t\tnewN := n.shallowCloneWithRef()\n\t\tnewN.left = n.left.incref()\n\t\tnewN.right = left\n\t\treturn newN, mid, right\n\t} else if less(key, n.key) {\n\t\tleft, mid, right := split(n.left, key, less, requireMid)\n\t\tif requireMid && mid == nil {\n\t\t\treturn nil, nil, nil\n\t\t}\n\t\tnewN := n.shallowCloneWithRef()\n\t\tnewN.left = right\n\t\tnewN.right = n.right.incref()\n\t\treturn left, mid, newN\n\t}\n\tmid = n.shallowCloneWithRef()\n\treturn n.left.incref(), mid, n.right.incref()\n}\n\n// Delete deletes the value for a key.\n//\n// The result reports whether the key was present in the map.\nfunc (pm *Map[K, V]) Delete(key K) bool {\n\troot := pm.root\n\tleft, mid, right := split(root, key, pm.less, true)\n\tif mid == nil {\n\t\treturn false\n\t}\n\tpm.root = merge(left, right)\n\tleft.decref()\n\tmid.decref()\n\tright.decref()\n\troot.decref()\n\treturn true\n}\n\n// merge two trees while preserving the weight invariant.\n// All nodes in left must have smaller keys than any node in right.\n//\n// merge(left:-0, right:-0) (result:+1)\n// Merge borrows its arguments without affecting their refcount\n// and returns a new reference that the caller is expected to call decref.\nfunc merge(left, right *mapNode) *mapNode {\n\tswitch {\n\tcase left == nil:\n\t\treturn right.incref()\n\tcase right == nil:\n\t\treturn left.incref()\n\tcase left.weight > right.weight:\n\t\troot := left.shallowCloneWithRef()\n\t\troot.left = left.left.incref()\n\t\troot.right = merge(left.right, right)\n\t\treturn root\n\tdefault:\n\t\troot := right.shallowCloneWithRef()\n\t\troot.left = merge(left, right.left)\n\t\troot.right = right.right.incref()\n\t\treturn root\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/persistent/map_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage persistent\n\nimport (\n\t\"fmt\"\n\t\"maps\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\ntype mapEntry struct {\n\tkey   int\n\tvalue int\n}\n\ntype validatedMap struct {\n\timpl     *Map[int, int]\n\texpected map[int]int      // current key-value mapping.\n\tdeleted  map[mapEntry]int // maps deleted entries to their clock time of last deletion\n\tseen     map[mapEntry]int // maps seen entries to their clock time of last insertion\n\tclock    int\n}\n\nfunc TestSimpleMap(t *testing.T) {\n\tdeletedEntries := make(map[mapEntry]int)\n\tseenEntries := make(map[mapEntry]int)\n\n\tm1 := &validatedMap{\n\t\timpl:     new(Map[int, int]),\n\t\texpected: make(map[int]int),\n\t\tdeleted:  deletedEntries,\n\t\tseen:     seenEntries,\n\t}\n\n\tm3 := m1.clone()\n\tvalidateRef(t, m1, m3)\n\tm3.set(t, 8, 8)\n\tvalidateRef(t, m1, m3)\n\tm3.destroy()\n\n\tassertSameMap(t, entrySet(deletedEntries), map[mapEntry]struct{}{\n\t\t{key: 8, value: 8}: {},\n\t})\n\n\tvalidateRef(t, m1)\n\tm1.set(t, 1, 1)\n\tvalidateRef(t, m1)\n\tm1.set(t, 2, 2)\n\tvalidateRef(t, m1)\n\tm1.set(t, 3, 3)\n\tvalidateRef(t, m1)\n\tm1.remove(t, 2)\n\tvalidateRef(t, m1)\n\tm1.set(t, 6, 6)\n\tvalidateRef(t, m1)\n\n\tassertSameMap(t, entrySet(deletedEntries), map[mapEntry]struct{}{\n\t\t{key: 2, value: 2}: {},\n\t\t{key: 8, value: 8}: {},\n\t})\n\n\tm2 := m1.clone()\n\tvalidateRef(t, m1, m2)\n\tm1.set(t, 6, 60)\n\tvalidateRef(t, m1, m2)\n\tm1.remove(t, 1)\n\tvalidateRef(t, m1, m2)\n\n\tgotAllocs := int(testing.AllocsPerRun(10, func() {\n\t\tm1.impl.Delete(100)\n\t\tm1.impl.Delete(1)\n\t}))\n\twantAllocs := 0\n\tif gotAllocs != wantAllocs {\n\t\tt.Errorf(\"wanted %d allocs, got %d\", wantAllocs, gotAllocs)\n\t}\n\n\tfor i := 10; i < 14; i++ {\n\t\tm1.set(t, i, i)\n\t\tvalidateRef(t, m1, m2)\n\t}\n\n\tm1.set(t, 10, 100)\n\tvalidateRef(t, m1, m2)\n\n\tm1.remove(t, 12)\n\tvalidateRef(t, m1, m2)\n\n\tm2.set(t, 4, 4)\n\tvalidateRef(t, m1, m2)\n\tm2.set(t, 5, 5)\n\tvalidateRef(t, m1, m2)\n\n\tm1.destroy()\n\n\tassertSameMap(t, entrySet(deletedEntries), map[mapEntry]struct{}{\n\t\t{key: 2, value: 2}:    {},\n\t\t{key: 6, value: 60}:   {},\n\t\t{key: 8, value: 8}:    {},\n\t\t{key: 10, value: 10}:  {},\n\t\t{key: 10, value: 100}: {},\n\t\t{key: 11, value: 11}:  {},\n\t\t{key: 12, value: 12}:  {},\n\t\t{key: 13, value: 13}:  {},\n\t})\n\n\tm2.set(t, 7, 7)\n\tvalidateRef(t, m2)\n\n\tm2.destroy()\n\n\tassertSameMap(t, entrySet(seenEntries), entrySet(deletedEntries))\n}\n\nfunc TestRandomMap(t *testing.T) {\n\tdeletedEntries := make(map[mapEntry]int)\n\tseenEntries := make(map[mapEntry]int)\n\n\tm := &validatedMap{\n\t\timpl:     new(Map[int, int]),\n\t\texpected: make(map[int]int),\n\t\tdeleted:  deletedEntries,\n\t\tseen:     seenEntries,\n\t}\n\n\tkeys := make([]int, 0, 1000)\n\tfor i := range 1000 {\n\t\tkey := rand.Intn(10000)\n\t\tm.set(t, key, key)\n\t\tkeys = append(keys, key)\n\n\t\tif i%10 == 1 {\n\t\t\tindex := rand.Intn(len(keys))\n\t\t\tlast := len(keys) - 1\n\t\t\tkey = keys[index]\n\t\t\tkeys[index], keys[last] = keys[last], keys[index]\n\t\t\tkeys = keys[:last]\n\n\t\t\tm.remove(t, key)\n\t\t}\n\t}\n\n\tm.destroy()\n\tassertSameMap(t, entrySet(seenEntries), entrySet(deletedEntries))\n}\n\nfunc entrySet(m map[mapEntry]int) map[mapEntry]struct{} {\n\tset := make(map[mapEntry]struct{})\n\tfor k := range m {\n\t\tset[k] = struct{}{}\n\t}\n\treturn set\n}\n\nfunc TestUpdate(t *testing.T) {\n\tdeletedEntries := make(map[mapEntry]int)\n\tseenEntries := make(map[mapEntry]int)\n\n\tm1 := &validatedMap{\n\t\timpl:     new(Map[int, int]),\n\t\texpected: make(map[int]int),\n\t\tdeleted:  deletedEntries,\n\t\tseen:     seenEntries,\n\t}\n\tm2 := m1.clone()\n\n\tm1.set(t, 1, 1)\n\tm1.set(t, 2, 2)\n\tm2.set(t, 2, 20)\n\tm2.set(t, 3, 3)\n\tm1.setAll(t, m2)\n\n\tm1.destroy()\n\tm2.destroy()\n\tassertSameMap(t, entrySet(seenEntries), entrySet(deletedEntries))\n}\n\nfunc validateRef(t *testing.T, maps ...*validatedMap) {\n\tt.Helper()\n\n\tactualCountByEntry := make(map[mapEntry]int32)\n\tnodesByEntry := make(map[mapEntry]map[*mapNode]struct{})\n\texpectedCountByEntry := make(map[mapEntry]int32)\n\tfor i, m := range maps {\n\t\tdfsRef(m.impl.root, actualCountByEntry, nodesByEntry)\n\t\tdumpMap(t, fmt.Sprintf(\"%d:\", i), m.impl.root)\n\t}\n\tfor entry, nodes := range nodesByEntry {\n\t\texpectedCountByEntry[entry] = int32(len(nodes))\n\t}\n\tassertSameMap(t, expectedCountByEntry, actualCountByEntry)\n}\n\nfunc dfsRef(node *mapNode, countByEntry map[mapEntry]int32, nodesByEntry map[mapEntry]map[*mapNode]struct{}) {\n\tif node == nil {\n\t\treturn\n\t}\n\n\tentry := mapEntry{key: node.key.(int), value: node.value.value.(int)}\n\tcountByEntry[entry] = atomic.LoadInt32(&node.value.refCount)\n\n\tnodes, ok := nodesByEntry[entry]\n\tif !ok {\n\t\tnodes = make(map[*mapNode]struct{})\n\t\tnodesByEntry[entry] = nodes\n\t}\n\tnodes[node] = struct{}{}\n\n\tdfsRef(node.left, countByEntry, nodesByEntry)\n\tdfsRef(node.right, countByEntry, nodesByEntry)\n}\n\nfunc dumpMap(t *testing.T, prefix string, n *mapNode) {\n\tif n == nil {\n\t\tt.Logf(\"%s nil\", prefix)\n\t\treturn\n\t}\n\tt.Logf(\"%s {key: %v, value: %v (ref: %v), ref: %v, weight: %v}\", prefix, n.key, n.value.value, n.value.refCount, n.refCount, n.weight)\n\tdumpMap(t, prefix+\"l\", n.left)\n\tdumpMap(t, prefix+\"r\", n.right)\n}\n\nfunc (vm *validatedMap) validate(t *testing.T) {\n\tt.Helper()\n\n\tvalidateNode(t, vm.impl.root)\n\n\t// Note: this validation may not make sense if maps were constructed using\n\t// SetAll operations. If this proves to be problematic, remove the clock,\n\t// deleted, and seen fields.\n\tfor key, value := range vm.expected {\n\t\tentry := mapEntry{key: key, value: value}\n\t\tif deleteAt := vm.deleted[entry]; deleteAt > vm.seen[entry] {\n\t\t\tt.Fatalf(\"entry is deleted prematurely, key: %d, value: %d\", key, value)\n\t\t}\n\t}\n\n\tactualMap := make(map[int]int, len(vm.expected))\n\tfor key, value := range vm.impl.All() {\n\t\tif other, ok := actualMap[key]; ok {\n\t\t\tt.Fatalf(\"key is present twice, key: %d, first value: %d, second value: %d\", key, value, other)\n\t\t}\n\t\tactualMap[key] = value\n\t}\n\n\tassertSameMap(t, actualMap, vm.expected)\n}\n\nfunc validateNode(t *testing.T, node *mapNode) {\n\tif node == nil {\n\t\treturn\n\t}\n\n\tif node.left != nil {\n\t\tif node.key.(int) < node.left.key.(int) {\n\t\t\tt.Fatalf(\"left child has larger key: %v vs %v\", node.left.key, node.key)\n\t\t}\n\t\tif node.left.weight > node.weight {\n\t\t\tt.Fatalf(\"left child has larger weight: %v vs %v\", node.left.weight, node.weight)\n\t\t}\n\t}\n\n\tif node.right != nil {\n\t\tif node.right.key.(int) < node.key.(int) {\n\t\t\tt.Fatalf(\"right child has smaller key: %v vs %v\", node.right.key, node.key)\n\t\t}\n\t\tif node.right.weight > node.weight {\n\t\t\tt.Fatalf(\"right child has larger weight: %v vs %v\", node.right.weight, node.weight)\n\t\t}\n\t}\n\n\tvalidateNode(t, node.left)\n\tvalidateNode(t, node.right)\n}\n\nfunc (vm *validatedMap) setAll(t *testing.T, other *validatedMap) {\n\tvm.impl.SetAll(other.impl)\n\n\t// Note: this is buggy because we are not updating vm.clock, vm.deleted, or\n\t// vm.seen.\n\tmaps.Copy(vm.expected, other.expected)\n\tvm.validate(t)\n}\n\nfunc (vm *validatedMap) set(t *testing.T, key, value int) {\n\tentry := mapEntry{key: key, value: value}\n\n\tvm.clock++\n\tvm.seen[entry] = vm.clock\n\n\tvm.impl.Set(key, value, func(deletedKey, deletedValue any) {\n\t\tif deletedKey != key || deletedValue != value {\n\t\t\tt.Fatalf(\"unexpected passed in deleted entry: %v/%v, expected: %v/%v\", deletedKey, deletedValue, key, value)\n\t\t}\n\t\t// Not safe if closure shared between two validatedMaps.\n\t\tvm.deleted[entry] = vm.clock\n\t})\n\tvm.expected[key] = value\n\tvm.validate(t)\n\n\tgotValue, ok := vm.impl.Get(key)\n\tif !ok || gotValue != value {\n\t\tt.Fatalf(\"unexpected get result after insertion, key: %v, expected: %v, got: %v (%v)\", key, value, gotValue, ok)\n\t}\n}\n\nfunc (vm *validatedMap) remove(t *testing.T, key int) {\n\tvm.clock++\n\tdeleted := vm.impl.Delete(key)\n\tif _, ok := vm.expected[key]; ok != deleted {\n\t\tt.Fatalf(\"Delete(%d) = %t, want %t\", key, deleted, ok)\n\t}\n\tdelete(vm.expected, key)\n\tvm.validate(t)\n\n\tgotValue, ok := vm.impl.Get(key)\n\tif ok {\n\t\tt.Fatalf(\"unexpected get result after removal, key: %v, got: %v\", key, gotValue)\n\t}\n}\n\nfunc (vm *validatedMap) clone() *validatedMap {\n\texpected := make(map[int]int, len(vm.expected))\n\tmaps.Copy(expected, vm.expected)\n\n\treturn &validatedMap{\n\t\timpl:     vm.impl.Clone(),\n\t\texpected: expected,\n\t\tdeleted:  vm.deleted,\n\t\tseen:     vm.seen,\n\t}\n}\n\nfunc (vm *validatedMap) destroy() {\n\tvm.impl.Destroy()\n}\n\nfunc assertSameMap(t *testing.T, map1, map2 any) {\n\tt.Helper()\n\n\tif !reflect.DeepEqual(map1, map2) {\n\t\tt.Fatalf(\"different maps:\\n%v\\nvs\\n%v\", map1, map2)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/persistent/race_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build race\n\npackage persistent\n\nimport (\n\t\"context\"\n\t\"maps\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n)\n\n// TestConcurrency exercises concurrent map access.\n// It doesn't assert anything, but it runs under the race detector.\nfunc TestConcurrency(t *testing.T) {\n\tctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)\n\tdefer cancel()\n\tvar orig Map[int, int] // maps subset of [0-10] to itself (values aren't interesting)\n\tfor i := range 10 {\n\t\torig.Set(i, i, func(k, v any) { /* just for good measure*/ })\n\t}\n\tg, ctx := errgroup.WithContext(ctx)\n\tconst N = 10 // concurrency level\n\tg.SetLimit(N)\n\tfor range N {\n\t\tg.Go(func() error {\n\t\t\t// Each thread has its own clone of the original,\n\t\t\t// sharing internal structures. Each map is accessed\n\t\t\t// only by a single thread; the shared data is immutable.\n\t\t\tm := orig.Clone()\n\n\t\t\t// Run until the timeout.\n\t\t\tfor ctx.Err() == nil {\n\t\t\t\tfor i := range 1000 {\n\t\t\t\t\tkey := i % 10\n\n\t\t\t\t\tswitch {\n\t\t\t\t\tcase i%2 == 0:\n\t\t\t\t\t\t_, _ = m.Get(key)\n\t\t\t\t\tcase i%11 == 0:\n\t\t\t\t\t\tm.Set(key, key, func(key, value any) {})\n\t\t\t\t\tcase i%13 == 0:\n\t\t\t\t\t\t_ = maps.Collect(m.All())\n\t\t\t\t\tcase i%17 == 0:\n\t\t\t\t\t\t_ = m.Delete(key)\n\t\t\t\t\tcase i%19 == 0:\n\t\t\t\t\t\t_ = m.Keys()\n\t\t\t\t\tcase i%31 == 0:\n\t\t\t\t\t\t_ = m.String()\n\t\t\t\t\tcase i%23 == 0:\n\t\t\t\t\t\t_ = m.Clone()\n\t\t\t\t\t}\n\t\t\t\t\t// Don't call m.Clear(), as it would\n\t\t\t\t\t// disentangle the various maps from each other.\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tg.Wait() // no errors\n}\n"
  },
  {
    "path": "gopls/internal/util/persistent/set.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage persistent\n\nimport (\n\t\"iter\"\n\n\t\"golang.org/x/tools/gopls/internal/util/constraints\"\n)\n\n// Set is a collection of elements of type K.\n//\n// It uses immutable data structures internally, so that sets can be cloned in\n// constant time.\n//\n// The zero value is a valid empty set.\ntype Set[K constraints.Ordered] struct {\n\timpl *Map[K, struct{}]\n}\n\n// Clone creates a copy of the receiver.\nfunc (s *Set[K]) Clone() *Set[K] {\n\tclone := new(Set[K])\n\tif s.impl != nil {\n\t\tclone.impl = s.impl.Clone()\n\t}\n\treturn clone\n}\n\n// Destroy destroys the set.\n//\n// After Destroy, the Set should not be used again.\nfunc (s *Set[K]) Destroy() {\n\tif s.impl != nil {\n\t\ts.impl.Destroy()\n\t}\n}\n\n// Contains reports whether s contains the given key.\nfunc (s *Set[K]) Contains(key K) bool {\n\tif s.impl == nil {\n\t\treturn false\n\t}\n\t_, ok := s.impl.Get(key)\n\treturn ok\n}\n\n// All returns the sequence of set elements in ascending order.\nfunc (s *Set[K]) All() iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tif s.impl != nil {\n\t\t\ts.impl.root.forEach(func(k, _ any) bool {\n\t\t\t\treturn yield(k.(K))\n\t\t\t})\n\t\t}\n\t}\n}\n\n// AddAll adds all elements from other to the receiver set.\nfunc (s *Set[K]) AddAll(other *Set[K]) {\n\tif other.impl != nil {\n\t\tif s.impl == nil {\n\t\t\ts.impl = new(Map[K, struct{}])\n\t\t}\n\t\ts.impl.SetAll(other.impl)\n\t}\n}\n\n// Add adds an element to the set.\nfunc (s *Set[K]) Add(key K) {\n\tif s.impl == nil {\n\t\ts.impl = new(Map[K, struct{}])\n\t}\n\ts.impl.Set(key, struct{}{}, nil)\n}\n\n// Remove removes an element from the set.\nfunc (s *Set[K]) Remove(key K) {\n\tif s.impl != nil {\n\t\ts.impl.Delete(key)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/persistent/set_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage persistent_test\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/gopls/internal/util/constraints\"\n\t\"golang.org/x/tools/gopls/internal/util/persistent\"\n)\n\nfunc TestSet(t *testing.T) {\n\tconst (\n\t\tadd = iota\n\t\tremove\n\t)\n\ttype op struct {\n\t\top int\n\t\tv  int\n\t}\n\n\ttests := []struct {\n\t\tlabel string\n\t\tops   []op\n\t\twant  []int\n\t}{\n\t\t{\"empty\", nil, nil},\n\t\t{\"singleton\", []op{{add, 1}}, []int{1}},\n\t\t{\"add and remove\", []op{\n\t\t\t{add, 1},\n\t\t\t{remove, 1},\n\t\t}, nil},\n\t\t{\"interleaved and remove\", []op{\n\t\t\t{add, 1},\n\t\t\t{add, 2},\n\t\t\t{remove, 1},\n\t\t\t{add, 3},\n\t\t}, []int{2, 3}},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.label, func(t *testing.T) {\n\t\t\tvar s persistent.Set[int]\n\t\t\tfor _, op := range test.ops {\n\t\t\t\tswitch op.op {\n\t\t\t\tcase add:\n\t\t\t\t\ts.Add(op.v)\n\t\t\t\tcase remove:\n\t\t\t\t\ts.Remove(op.v)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif d := diff(&s, test.want); d != \"\" {\n\t\t\t\tt.Errorf(\"unexpected diff:\\n%s\", d)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSet_Clone(t *testing.T) {\n\ts1 := new(persistent.Set[int])\n\ts1.Add(1)\n\ts1.Add(2)\n\ts2 := s1.Clone()\n\ts1.Add(3)\n\ts2.Add(4)\n\tif d := diff(s1, []int{1, 2, 3}); d != \"\" {\n\t\tt.Errorf(\"s1: unexpected diff:\\n%s\", d)\n\t}\n\tif d := diff(s2, []int{1, 2, 4}); d != \"\" {\n\t\tt.Errorf(\"s2: unexpected diff:\\n%s\", d)\n\t}\n}\n\nfunc TestSet_AddAll(t *testing.T) {\n\ts1 := new(persistent.Set[int])\n\ts1.Add(1)\n\ts1.Add(2)\n\ts2 := new(persistent.Set[int])\n\ts2.Add(2)\n\ts2.Add(3)\n\ts2.Add(4)\n\ts3 := new(persistent.Set[int])\n\n\ts := new(persistent.Set[int])\n\ts.AddAll(s1)\n\ts.AddAll(s2)\n\ts.AddAll(s3)\n\n\tif d := diff(s1, []int{1, 2}); d != \"\" {\n\t\tt.Errorf(\"s1: unexpected diff:\\n%s\", d)\n\t}\n\tif d := diff(s2, []int{2, 3, 4}); d != \"\" {\n\t\tt.Errorf(\"s2: unexpected diff:\\n%s\", d)\n\t}\n\tif d := diff(s3, nil); d != \"\" {\n\t\tt.Errorf(\"s3: unexpected diff:\\n%s\", d)\n\t}\n\tif d := diff(s, []int{1, 2, 3, 4}); d != \"\" {\n\t\tt.Errorf(\"s: unexpected diff:\\n%s\", d)\n\t}\n}\n\nfunc diff[K constraints.Ordered](got *persistent.Set[K], want []K) string {\n\twantSet := make(map[K]struct{})\n\tfor _, w := range want {\n\t\twantSet[w] = struct{}{}\n\t}\n\tvar diff []string\n\tfor key := range got.All() {\n\t\tif _, ok := wantSet[key]; !ok {\n\t\t\tdiff = append(diff, fmt.Sprintf(\"+%v\", key))\n\t\t}\n\t}\n\tfor key := range wantSet {\n\t\tif !got.Contains(key) {\n\t\t\tdiff = append(diff, fmt.Sprintf(\"-%v\", key))\n\t\t}\n\t}\n\tif len(diff) > 0 {\n\t\td := new(strings.Builder)\n\t\tfor _, l := range diff {\n\t\t\tfmt.Fprintln(d, l)\n\t\t}\n\t\treturn d.String()\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "gopls/internal/util/safetoken/safetoken.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package safetoken provides wrappers around methods in go/token,\n// that return errors rather than panicking.\n//\n// It also provides a central place for workarounds in the underlying\n// packages. The use of this package's functions instead of methods of\n// token.File (such as Offset, Position, and PositionFor) is mandatory\n// throughout the gopls codebase and enforced by a static check.\npackage safetoken\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n)\n\n// Offset returns f.Offset(pos), but first checks that the file\n// contains the pos.\n//\n// The definition of \"contains\" here differs from that of token.File\n// in order to work around a bug in the parser (issue #57490): during\n// error recovery, the parser may create syntax nodes whose computed\n// End position is 1 byte beyond EOF, which would cause\n// token.File.Offset to panic. The workaround is that this function\n// accepts a Pos that is exactly 1 byte beyond EOF and maps it to the\n// EOF offset.\nfunc Offset(f *token.File, pos token.Pos) (int, error) {\n\tif !inRange(f, pos) {\n\t\t// Accept a Pos that is 1 byte beyond EOF,\n\t\t// and map it to the EOF offset.\n\t\t// (Workaround for #57490.)\n\t\tif int(pos) == f.Base()+f.Size()+1 {\n\t\t\treturn f.Size(), nil\n\t\t}\n\n\t\treturn -1, fmt.Errorf(\"pos %d is not in range [%d:%d] of file %s\",\n\t\t\tpos, f.Base(), f.Base()+f.Size(), f.Name())\n\t}\n\treturn int(pos) - f.Base(), nil\n}\n\n// Offsets returns Offset(start) and Offset(end).\n// It returns an error if either failed, or if start > end.\nfunc Offsets(f *token.File, start, end token.Pos) (int, int, error) {\n\tstartOffset, err := Offset(f, start)\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"start: %v\", err)\n\t}\n\tendOffset, err := Offset(f, end)\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"end: %v\", err)\n\t}\n\tif start > end {\n\t\treturn 0, 0, fmt.Errorf(\"start (offset %d) > end (offset %d)\", start, end)\n\t}\n\treturn startOffset, endOffset, nil\n}\n\n// Pos returns f.Pos(offset), but first checks that the offset is\n// non-negative and not larger than the size of the file.\nfunc Pos(f *token.File, offset int) (token.Pos, error) {\n\tif !(0 <= offset && offset <= f.Size()) {\n\t\treturn token.NoPos, fmt.Errorf(\"offset %d is not in range for file %s of size %d\", offset, f.Name(), f.Size())\n\t}\n\treturn token.Pos(f.Base() + offset), nil\n}\n\n// inRange reports whether file f contains position pos,\n// according to the invariants of token.File.\n//\n// This function is not public because of the ambiguity it would\n// create w.r.t. the definition of \"contains\". Use Offset instead.\nfunc inRange(f *token.File, pos token.Pos) bool {\n\treturn token.Pos(f.Base()) <= pos && pos <= token.Pos(f.Base()+f.Size())\n}\n\n// Position returns the Position for the pos value in the given file.\n//\n// p must be NoPos, a valid Pos in the range of f, or exactly 1 byte\n// beyond the end of f. (See [Offset] for explanation.)\n// Any other value causes a panic.\n//\n// Line directives (//line comments) are ignored.\nfunc Position(f *token.File, pos token.Pos) token.Position {\n\t// Work around issue #57490.\n\tif int(pos) == f.Base()+f.Size()+1 {\n\t\tpos--\n\t}\n\n\t// TODO(adonovan): centralize the workaround for\n\t// golang/go#41029 (newline at EOF) here too.\n\n\treturn f.PositionFor(pos, false)\n}\n\n// Line returns the line number for the given offset in the given file.\nfunc Line(f *token.File, pos token.Pos) int {\n\treturn Position(f, pos).Line\n}\n\n// StartPosition converts a start Pos in the FileSet into a Position.\n//\n// Call this function only if start represents the start of a token or\n// parse tree, such as the result of Node.Pos().  If start is the end of\n// an interval, such as Node.End(), call EndPosition instead, as it\n// may need the correction described at [Position].\nfunc StartPosition(fset *token.FileSet, start token.Pos) (_ token.Position) {\n\tif f := fset.File(start); f != nil {\n\t\treturn Position(f, start)\n\t}\n\treturn\n}\n\n// EndPosition converts an end Pos in the FileSet into a Position.\n//\n// Call this function only if pos represents the end of\n// a non-empty interval, such as the result of Node.End().\nfunc EndPosition(fset *token.FileSet, end token.Pos) (_ token.Position) {\n\tif f := fset.File(end); f != nil && int(end) > f.Base() {\n\t\treturn Position(f, end)\n\t}\n\n\t// Work around issue #57490.\n\tif f := fset.File(end - 1); f != nil {\n\t\treturn Position(f, end)\n\t}\n\n\treturn\n}\n"
  },
  {
    "path": "gopls/internal/util/safetoken/safetoken_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage safetoken_test\n\nimport (\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/gopls/internal/util/safetoken\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestWorkaroundIssue57490(t *testing.T) {\n\t// During error recovery the parser synthesizes various close\n\t// tokens at EOF, causing the End position of incomplete\n\t// syntax nodes, computed as Rbrace+len(\"}\"), to be beyond EOF.\n\tsrc := `package p; func f() { var x struct`\n\tfset := token.NewFileSet()\n\tfile, _ := parser.ParseFile(fset, \"a.go\", src, parser.SkipObjectResolution)\n\ttf := fset.File(file.FileStart)\n\n\t// Add another file to the FileSet.\n\tfile2, _ := parser.ParseFile(fset, \"b.go\", \"package q\", parser.SkipObjectResolution)\n\n\t// This is the ambiguity of #57490...\n\tif file.End() != file2.Pos() {\n\t\tt.Errorf(\"file.End() %d != %d file2.Pos()\", file.End(), file2.Pos())\n\t}\n\t// ...which causes these statements to panic.\n\tif false {\n\t\ttf.Offset(file.End())   // panic: invalid Pos value 36 (should be in [1, 35])\n\t\ttf.Position(file.End()) // panic: invalid Pos value 36 (should be in [1, 35])\n\t}\n\n\t// The offset of the EOF position is the file size.\n\toffset, err := safetoken.Offset(tf, file.End()-1)\n\tif err != nil || offset != tf.Size() {\n\t\tt.Errorf(\"Offset(EOF) = (%d, %v), want token.File.Size %d\", offset, err, tf.Size())\n\t}\n\n\t// The offset of the file.End() position, 1 byte beyond EOF,\n\t// is also the size of the file.\n\toffset, err = safetoken.Offset(tf, file.End())\n\tif err != nil || offset != tf.Size() {\n\t\tt.Errorf(\"Offset(ast.File.End()) = (%d, %v), want token.File.Size %d\", offset, err, tf.Size())\n\t}\n\n\tif got, want := safetoken.Position(tf, file.End()).String(), \"a.go:1:35\"; got != want {\n\t\tt.Errorf(\"Position(ast.File.End()) = %s, want %s\", got, want)\n\t}\n\n\tif got, want := safetoken.EndPosition(fset, file.End()).String(), \"a.go:1:35\"; got != want {\n\t\tt.Errorf(\"EndPosition(ast.File.End()) = %s, want %s\", got, want)\n\t}\n\n\t// Note that calling StartPosition on an end may yield the wrong file:\n\tif got, want := safetoken.StartPosition(fset, file.End()).String(), \"b.go:1:1\"; got != want {\n\t\tt.Errorf(\"StartPosition(ast.File.End()) = %s, want %s\", got, want)\n\t}\n}\n\n// To reduce the risk of panic, or bugs for which this package\n// provides a workaround, this test statically reports references to\n// forbidden methods of token.File or FileSet throughout gopls and\n// suggests alternatives.\nfunc TestGoplsSourceDoesNotCallTokenFileMethods(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\ttestenv.NeedsLocalXTools(t)\n\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedName | packages.NeedModule | packages.NeedCompiledGoFiles | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,\n\t}\n\tcfg.Env = os.Environ()\n\tcfg.Env = append(cfg.Env,\n\t\t\"GOPACKAGESDRIVER=off\",\n\t\t\"GOWORK=off\", // necessary for -mod=mod below\n\t\t\"GOFLAGS=-mod=mod\",\n\t)\n\n\tpkgs, err := packages.Load(cfg, \"go/token\", \"golang.org/x/tools/gopls/...\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar tokenPkg *packages.Package\n\tfor _, pkg := range pkgs {\n\t\tif pkg.PkgPath == \"go/token\" {\n\t\t\ttokenPkg = pkg\n\t\t\tbreak\n\t\t}\n\t}\n\tif tokenPkg == nil {\n\t\tt.Fatal(\"missing package go/token\")\n\t}\n\n\tFile := tokenPkg.Types.Scope().Lookup(\"File\")\n\tFileSet := tokenPkg.Types.Scope().Lookup(\"FileSet\")\n\n\talternative := make(map[types.Object]string)\n\tsetAlternative := func(recv types.Object, old, new string) {\n\t\toldMethod, _, _ := types.LookupFieldOrMethod(recv.Type(), true, recv.Pkg(), old)\n\t\talternative[oldMethod] = new\n\t}\n\tsetAlternative(File, \"Line\", \"safetoken.Line\")\n\tsetAlternative(File, \"Offset\", \"safetoken.Offset\")\n\tsetAlternative(File, \"Position\", \"safetoken.Position\")\n\tsetAlternative(File, \"PositionFor\", \"safetoken.Position\")\n\tsetAlternative(FileSet, \"Position\", \"safetoken.StartPosition or EndPosition\")\n\tsetAlternative(FileSet, \"PositionFor\", \"safetoken.StartPosition or EndPosition\")\n\n\tfor _, pkg := range pkgs {\n\t\tswitch pkg.PkgPath {\n\t\tcase \"go/token\",\n\t\t\t\"golang.org/x/tools/gopls/internal/util/safetoken\", // this package\n\t\t\t\"golang.org/x/tools/gopls/internal/cache/parsego\":  // copies go/parser/resolver.go\n\t\t\tcontinue // allow calls within these packages\n\t\t}\n\n\t\tfor ident, obj := range pkg.TypesInfo.Uses {\n\t\t\tif alt, ok := alternative[obj]; ok {\n\t\t\t\tposn := safetoken.StartPosition(pkg.Fset, ident.Pos())\n\t\t\t\tfmt.Fprintf(os.Stderr, \"%s: forbidden use of %v; use %s instead.\\n\", posn, obj, alt)\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/util/tokeninternal/tokeninternal.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// package tokeninternal provides convenient helpers for the go/token package.\npackage tokeninternal\n\nimport (\n\t\"go/token\"\n\t\"slices\"\n)\n\n// FileSetFor returns a new FileSet containing a sequence of new Files with\n// the same base, size, and line as the input files, for use in APIs that\n// require a FileSet.\n//\n// Precondition: the input files must be non-overlapping, and sorted in order\n// of their Base.\nfunc FileSetFor(files ...*token.File) *token.FileSet {\n\tfset := token.NewFileSet()\n\tfset.AddExistingFiles(files...)\n\treturn fset\n}\n\n// CloneFileSet creates a new FileSet holding all files in fset. It does not\n// create copies of the token.Files in fset: they are added to the resulting\n// FileSet unmodified.\nfunc CloneFileSet(fset *token.FileSet) *token.FileSet {\n\treturn FileSetFor(slices.Collect(fset.Iterate)...)\n}\n"
  },
  {
    "path": "gopls/internal/util/typesutil/typesutil.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesutil\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/gopls/internal/util/bug\"\n)\n\n// FormatTypeParams turns TypeParamList into its Go representation, such as:\n// [T, Y]. Note that it does not print constraints as this is mainly used for\n// formatting type params in method receivers.\nfunc FormatTypeParams(tparams *types.TypeParamList) string {\n\tif tparams == nil || tparams.Len() == 0 {\n\t\treturn \"\"\n\t}\n\tvar buf bytes.Buffer\n\tbuf.WriteByte('[')\n\tfor i := 0; i < tparams.Len(); i++ {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tbuf.WriteString(tparams.At(i).Obj().Name())\n\t}\n\tbuf.WriteByte(']')\n\treturn buf.String()\n}\n\n// TypesFromContext returns the type (or perhaps zero or multiple types)\n// of the \"hole\" into which the expression identified by path must fit.\n//\n// For example, given\n//\n//\ts, i := \"\", 0\n//\ts, i = EXPR\n//\n// the hole that must be filled by EXPR has type (string, int).\n//\n// It returns nil on failure.\nfunc TypesFromContext(info *types.Info, cur inspector.Cursor) []types.Type {\n\tanyType := types.Universe.Lookup(\"any\").Type()\n\tvar typs []types.Type\n\n\t// TODO: do cur = unparenEnclosing(cur), once CL 701035 lands.\n\tfor cur.ParentEdgeKind() == edge.ParenExpr_X {\n\t\tcur = cur.Parent()\n\t}\n\n\tvalidType := func(t types.Type) types.Type {\n\t\tif t != nil && !containsInvalid(t) {\n\t\t\treturn types.Default(t)\n\t\t} else {\n\t\t\treturn anyType\n\t\t}\n\t}\n\n\tek, idx := cur.ParentEdge()\n\tswitch ek {\n\tcase edge.AssignStmt_Lhs, edge.AssignStmt_Rhs:\n\t\tassign := cur.Parent().Node().(*ast.AssignStmt)\n\t\t// Append all lhs's type\n\t\tif len(assign.Rhs) == 1 {\n\t\t\tfor _, lhs := range assign.Lhs {\n\t\t\t\tt := info.TypeOf(lhs)\n\t\t\t\ttyps = append(typs, validType(t))\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\t// Lhs and Rhs counts do not match, give up\n\t\tif len(assign.Lhs) != len(assign.Rhs) {\n\t\t\tbreak\n\t\t}\n\t\t// Append corresponding index of lhs's type\n\t\tif ek == edge.AssignStmt_Rhs {\n\t\t\tt := info.TypeOf(assign.Lhs[idx])\n\t\t\ttyps = append(typs, validType(t))\n\t\t}\n\tcase edge.ValueSpec_Names, edge.ValueSpec_Type, edge.ValueSpec_Values:\n\t\tspec := cur.Parent().Node().(*ast.ValueSpec)\n\t\tif len(spec.Values) == 1 {\n\t\t\tfor _, lhs := range spec.Names {\n\t\t\t\tt := info.TypeOf(lhs)\n\t\t\t\ttyps = append(typs, validType(t))\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tif len(spec.Values) != len(spec.Names) {\n\t\t\tbreak\n\t\t}\n\t\tt := info.TypeOf(spec.Type)\n\t\ttyps = append(typs, validType(t))\n\tcase edge.ReturnStmt_Results:\n\t\treturnstmt := cur.Parent().Node().(*ast.ReturnStmt)\n\t\tsig := EnclosingSignature(cur, info)\n\t\tif sig == nil || sig.Results() == nil {\n\t\t\tbreak\n\t\t}\n\t\tretsig := sig.Results()\n\t\t// Append all return declarations' type\n\t\tif len(returnstmt.Results) == 1 {\n\t\t\tfor v := range retsig.Variables() {\n\t\t\t\tt := v.Type()\n\t\t\t\ttyps = append(typs, validType(t))\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\t// Return declaration and actual return counts do not match, give up\n\t\tif retsig.Len() != len(returnstmt.Results) {\n\t\t\tbreak\n\t\t}\n\t\t// Append corresponding index of return declaration's type\n\t\tt := retsig.At(idx).Type()\n\t\ttyps = append(typs, validType(t))\n\n\tcase edge.CallExpr_Args:\n\t\tcall := cur.Parent().Node().(*ast.CallExpr)\n\t\tt := info.TypeOf(call.Fun)\n\t\tif t == nil {\n\t\t\tbreak\n\t\t}\n\n\t\tif sig, ok := t.Underlying().(*types.Signature); ok {\n\t\t\tvar paramType types.Type\n\t\t\tif sig.Variadic() && idx >= sig.Params().Len()-1 {\n\t\t\t\tv := sig.Params().At(sig.Params().Len() - 1)\n\t\t\t\tif s, _ := v.Type().(*types.Slice); s != nil {\n\t\t\t\t\tparamType = s.Elem()\n\t\t\t\t}\n\t\t\t} else if idx < sig.Params().Len() {\n\t\t\t\tparamType = sig.Params().At(idx).Type()\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif paramType == nil || containsInvalid(paramType) {\n\t\t\t\tparamType = anyType\n\t\t\t}\n\t\t\ttyps = append(typs, paramType)\n\t\t}\n\tcase edge.IfStmt_Cond:\n\t\ttyps = append(typs, types.Typ[types.Bool])\n\tcase edge.ForStmt_Cond:\n\t\ttyps = append(typs, types.Typ[types.Bool])\n\tcase edge.UnaryExpr_X:\n\t\tunexpr := cur.Parent().Node().(*ast.UnaryExpr)\n\t\tvar t types.Type\n\t\tswitch unexpr.Op {\n\t\tcase token.NOT:\n\t\t\tt = types.Typ[types.Bool]\n\t\tcase token.ADD, token.SUB, token.XOR:\n\t\t\tt = types.Typ[types.Int]\n\t\tdefault:\n\t\t\tt = anyType\n\t\t}\n\t\ttyps = append(typs, t)\n\tcase edge.BinaryExpr_X, edge.BinaryExpr_Y:\n\t\tbinexpr := cur.Parent().Node().(*ast.BinaryExpr)\n\t\tswitch ek {\n\t\tcase edge.BinaryExpr_X:\n\t\t\tt := info.TypeOf(binexpr.Y)\n\t\t\ttyps = append(typs, validType(t))\n\t\tcase edge.BinaryExpr_Y:\n\t\t\tt := info.TypeOf(binexpr.X)\n\t\t\ttyps = append(typs, validType(t))\n\t\t}\n\tdefault:\n\t\t// TODO: support other kinds of \"holes\" as the need arises.\n\t}\n\treturn typs\n}\n\n// containsInvalid checks if the type name contains \"invalid type\",\n// which is not a valid syntax to generate.\nfunc containsInvalid(t types.Type) bool {\n\ttypeString := types.TypeString(t, nil)\n\treturn strings.Contains(typeString, types.Typ[types.Invalid].String())\n}\n\n// EnclosingSignature returns the signature of the innermost\n// function enclosing the syntax node denoted by cur.\n// It returns nil if the node is not within a function,\n// or the function's type information is missing.\nfunc EnclosingSignature(cur inspector.Cursor, info *types.Info) *types.Signature {\nloop:\n\tfor c := range cur.Enclosing((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {\n\t\tswitch n := c.Node().(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif f, ok := info.Defs[n.Name]; ok {\n\t\t\t\treturn f.Type().(*types.Signature)\n\t\t\t}\n\t\t\tbug.Reportf(\"FuncDecl defines no types.Func (#70666)\")\n\t\t\tbreak loop\n\t\tcase *ast.FuncLit:\n\t\t\tif f, ok := info.Types[n]; ok {\n\t\t\t\treturn f.Type.(*types.Signature)\n\t\t\t}\n\t\t\tbug.Reportf(\"FuncLit has no type (#70666)\")\n\t\t\tbreak loop\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/version/version.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package version manages the gopls version.\n//\n// The VersionOverride variable may be used to set the gopls version at link\n// time.\npackage version\n\nimport \"runtime/debug\"\n\nvar VersionOverride = \"\"\n\n// Version returns the gopls version.\n//\n// By default, this is read from runtime/debug.ReadBuildInfo, but may be\n// overridden by the [VersionOverride] variable.\nfunc Version() string {\n\tif VersionOverride != \"\" {\n\t\treturn VersionOverride\n\t}\n\tif info, ok := debug.ReadBuildInfo(); ok {\n\t\tif info.Main.Version != \"\" {\n\t\t\treturn info.Main.Version\n\t\t}\n\t}\n\treturn \"(unknown)\"\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/copier.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n//go:generate go run ./copier.go\n\n// Copier is a tool to automate copy of govulncheck's internal files.\n//\n//   - copy golang.org/x/vuln/internal/osv/ to osv\n//   - copy golang.org/x/vuln/internal/govulncheck/ to govulncheck\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/edit\"\n)\n\nfunc main() {\n\tlog.SetPrefix(\"copier: \")\n\tlog.SetFlags(log.Lshortfile)\n\n\tsrcMod := \"golang.org/x/vuln\"\n\tsrcModVers := \"@latest\"\n\tsrcDir, srcVer := downloadModule(srcMod + srcModVers)\n\n\tcfg := rewrite{\n\t\tbanner:        fmt.Sprintf(\"// Code generated by copying from %v@%v (go run copier.go); DO NOT EDIT.\", srcMod, srcVer),\n\t\tsrcImportPath: \"golang.org/x/vuln/internal\",\n\t\tdstImportPath: currentPackagePath(),\n\t}\n\n\tcopyFiles(\"osv\", filepath.Join(srcDir, \"internal\", \"osv\"), cfg)\n\tcopyFiles(\"govulncheck\", filepath.Join(srcDir, \"internal\", \"govulncheck\"), cfg)\n}\n\ntype rewrite struct {\n\t// DO NOT EDIT marker to add at the beginning\n\tbanner string\n\t// rewrite srcImportPath with dstImportPath\n\tsrcImportPath string\n\tdstImportPath string\n}\n\nfunc copyFiles(dst, src string, cfg rewrite) {\n\tentries, err := os.ReadDir(src)\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to read dir: %v\", err)\n\t}\n\tif err := os.MkdirAll(dst, 0777); err != nil {\n\t\tlog.Fatalf(\"failed to create dir: %v\", err)\n\t}\n\n\tfor _, e := range entries {\n\t\tfname := e.Name()\n\t\t// we need only non-test go files.\n\t\tif e.IsDir() || !strings.HasSuffix(fname, \".go\") || strings.HasSuffix(fname, \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\t\tdata, err := os.ReadFile(filepath.Join(src, fname))\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, fname, data, parser.ParseComments|parser.ImportsOnly)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"parsing source module:\\n%s\", err)\n\t\t}\n\n\t\tbuf := edit.NewBuffer(data)\n\t\tat := func(p token.Pos) int {\n\t\t\treturn fset.File(p).Offset(p)\n\t\t}\n\n\t\t// Add banner right after the copyright statement (the first comment)\n\t\tbannerInsert, banner := f.FileStart, cfg.banner\n\t\tif len(f.Comments) > 0 && strings.HasPrefix(f.Comments[0].Text(), \"Copyright \") {\n\t\t\tbannerInsert = f.Comments[0].End()\n\t\t\tbanner = \"\\n\\n\" + banner\n\t\t}\n\t\tbuf.Replace(at(bannerInsert), at(bannerInsert), banner)\n\n\t\t// Adjust imports\n\t\tfor _, spec := range f.Imports {\n\t\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t\tif strings.HasPrefix(path, cfg.srcImportPath) {\n\t\t\t\tnewPath := strings.Replace(path, cfg.srcImportPath, cfg.dstImportPath, 1)\n\t\t\t\tbuf.Replace(at(spec.Path.Pos()), at(spec.Path.End()), strconv.Quote(newPath))\n\t\t\t}\n\t\t}\n\t\tdata = buf.Bytes()\n\n\t\tif err := os.WriteFile(filepath.Join(dst, fname), data, 0666); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc downloadModule(srcModVers string) (dir, ver string) {\n\tvar stdout, stderr bytes.Buffer\n\tcmd := exec.Command(\"go\", \"mod\", \"download\", \"-json\", srcModVers)\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\tif err := cmd.Run(); err != nil {\n\t\tlog.Fatalf(\"go mod download -json %s: %v\\n%s%s\", srcModVers, err, stderr.Bytes(), stdout.Bytes())\n\t}\n\tvar info struct {\n\t\tDir     string\n\t\tVersion string\n\t}\n\tif err := json.Unmarshal(stdout.Bytes(), &info); err != nil {\n\t\tlog.Fatalf(\"go mod download -json %s: invalid JSON output: %v\\n%s%s\", srcModVers, err, stderr.Bytes(), stdout.Bytes())\n\t}\n\treturn info.Dir, info.Version\n}\n\nfunc currentPackagePath() string {\n\tvar stdout, stderr bytes.Buffer\n\tcmd := exec.Command(\"go\", \"list\", \".\")\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\tif err := cmd.Run(); err != nil {\n\t\tlog.Fatalf(\"go list: %v\\n%s%s\", err, stderr.Bytes(), stdout.Bytes())\n\t}\n\treturn strings.TrimSpace(stdout.String())\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/govulncheck/govulncheck.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copying from golang.org/x/vuln@v1.0.1 (go run copier.go); DO NOT EDIT.\n\n// Package govulncheck contains the JSON output structs for govulncheck.\npackage govulncheck\n\nimport (\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n)\n\nconst (\n\t// ProtocolVersion is the current protocol version this file implements\n\tProtocolVersion = \"v1.0.0\"\n)\n\n// Message is an entry in the output stream. It will always have exactly one\n// field filled in.\ntype Message struct {\n\tConfig   *Config    `json:\"config,omitempty\"`\n\tProgress *Progress  `json:\"progress,omitempty\"`\n\tOSV      *osv.Entry `json:\"osv,omitempty\"`\n\tFinding  *Finding   `json:\"finding,omitempty\"`\n}\n\n// Config must occur as the first message of a stream and informs the client\n// about the information used to generate the findings.\n// The only required field is the protocol version.\ntype Config struct {\n\t// ProtocolVersion specifies the version of the JSON protocol.\n\tProtocolVersion string `json:\"protocol_version\"`\n\n\t// ScannerName is the name of the tool, for example, govulncheck.\n\t//\n\t// We expect this JSON format to be used by other tools that wrap\n\t// govulncheck, which will have a different name.\n\tScannerName string `json:\"scanner_name,omitempty\"`\n\n\t// ScannerVersion is the version of the tool.\n\tScannerVersion string `json:\"scanner_version,omitempty\"`\n\n\t// DB is the database used by the tool, for example,\n\t// vuln.go.dev.\n\tDB string `json:\"db,omitempty\"`\n\n\t// LastModified is the last modified time of the data source.\n\tDBLastModified *time.Time `json:\"db_last_modified,omitempty\"`\n\n\t// GoVersion is the version of Go used for analyzing standard library\n\t// vulnerabilities.\n\tGoVersion string `json:\"go_version,omitempty\"`\n\n\t// ScanLevel instructs govulncheck to analyze at a specific level of detail.\n\t// Valid values include module, package and symbol.\n\tScanLevel ScanLevel `json:\"scan_level,omitempty\"`\n}\n\n// Progress messages are informational only, intended to allow users to monitor\n// the progress of a long running scan.\n// A stream must remain fully valid and able to be interpreted with all progress\n// messages removed.\ntype Progress struct {\n\t// A time stamp for the message.\n\tTimestamp *time.Time `json:\"time,omitempty\"`\n\n\t// Message is the progress message.\n\tMessage string `json:\"message,omitempty\"`\n}\n\n// Vuln represents a single OSV entry.\ntype Finding struct {\n\t// OSV is the id of the detected vulnerability.\n\tOSV string `json:\"osv,omitempty\"`\n\n\t// FixedVersion is the module version where the vulnerability was\n\t// fixed. This is empty if a fix is not available.\n\t//\n\t// If there are multiple fixed versions in the OSV report, this will\n\t// be the fixed version in the latest range event for the OSV report.\n\t//\n\t// For example, if the range events are\n\t// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version\n\t// will be empty.\n\t//\n\t// For the stdlib, we will show the fixed version closest to the\n\t// Go version that is used. For example, if a fix is available in 1.17.5 and\n\t// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the\n\t// fixed version.\n\tFixedVersion string `json:\"fixed_version,omitempty\"`\n\n\t// Trace contains an entry for each frame in the trace.\n\t//\n\t// Frames are sorted starting from the imported vulnerable symbol\n\t// until the entry point. The first frame in Frames should match\n\t// Symbol.\n\t//\n\t// In binary mode, trace will contain a single-frame with no position\n\t// information.\n\t//\n\t// When a package is imported but no vulnerable symbol is called, the trace\n\t// will contain a single-frame with no symbol or position information.\n\tTrace []*Frame `json:\"trace,omitempty\"`\n}\n\n// Frame represents an entry in a finding trace.\ntype Frame struct {\n\t// Module is the module path of the module containing this symbol.\n\t//\n\t// Importable packages in the standard library will have the path \"stdlib\".\n\tModule string `json:\"module\"`\n\n\t// Version is the module version from the build graph.\n\tVersion string `json:\"version,omitempty\"`\n\n\t// Package is the import path.\n\tPackage string `json:\"package,omitempty\"`\n\n\t// Function is the function name.\n\tFunction string `json:\"function,omitempty\"`\n\n\t// Receiver is the receiver type if the called symbol is a method.\n\t//\n\t// The client can create the final symbol name by\n\t// prepending Receiver to FuncName.\n\tReceiver string `json:\"receiver,omitempty\"`\n\n\t// Position describes an arbitrary source position\n\t// including the file, line, and column location.\n\t// A Position is valid if the line number is > 0.\n\tPosition *Position `json:\"position,omitempty\"`\n}\n\n// Position represents arbitrary source position.\ntype Position struct {\n\tFilename string `json:\"filename,omitempty\"` // filename, if any\n\tOffset   int    `json:\"offset\"`             // byte offset, starting at 0\n\tLine     int    `json:\"line\"`               // line number, starting at 1\n\tColumn   int    `json:\"column\"`             // column number, starting at 1 (byte count)\n}\n\n// ScanLevel represents the detail level at which a scan occurred.\n// This can be necessary to correctly interpret the findings, for instance if\n// a scan is at symbol level and a finding does not have a symbol it means the\n// vulnerability was imported but not called. If the scan however was at\n// \"package\" level, that determination cannot be made.\ntype ScanLevel string\n\nconst (\n\tscanLevelModule  = \"module\"\n\tscanLevelPackage = \"package\"\n\tscanLevelSymbol  = \"symbol\"\n)\n\n// WantSymbols can be used to check whether the scan level is one that is able\n// to generate symbols called findings.\nfunc (l ScanLevel) WantSymbols() bool { return l == scanLevelSymbol }\n"
  },
  {
    "path": "gopls/internal/vulncheck/govulncheck/handler.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copying from golang.org/x/vuln@v1.0.1 (go run copier.go); DO NOT EDIT.\n\npackage govulncheck\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n)\n\n// Handler handles messages to be presented in a vulnerability scan output\n// stream.\ntype Handler interface {\n\t// Config communicates introductory message to the user.\n\tConfig(config *Config) error\n\n\t// Progress is called to display a progress message.\n\tProgress(progress *Progress) error\n\n\t// OSV is invoked for each osv Entry in the stream.\n\tOSV(entry *osv.Entry) error\n\n\t// Finding is called for each vulnerability finding in the stream.\n\tFinding(finding *Finding) error\n}\n\n// HandleJSON reads the json from the supplied stream and hands the decoded\n// output to the handler.\nfunc HandleJSON(from io.Reader, to Handler) error {\n\tdec := json.NewDecoder(from)\n\tfor dec.More() {\n\t\tmsg := Message{}\n\t\t// decode the next message in the stream\n\t\tif err := dec.Decode(&msg); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// dispatch the message\n\t\tvar err error\n\t\tif msg.Config != nil {\n\t\t\terr = to.Config(msg.Config)\n\t\t}\n\t\tif msg.Progress != nil {\n\t\t\terr = to.Progress(msg.Progress)\n\t\t}\n\t\tif msg.OSV != nil {\n\t\t\terr = to.OSV(msg.OSV)\n\t\t}\n\t\tif msg.Finding != nil {\n\t\t\terr = to.Finding(msg.Finding)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/govulncheck/jsonhandler.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copying from golang.org/x/vuln@v1.0.1 (go run copier.go); DO NOT EDIT.\n\npackage govulncheck\n\nimport (\n\t\"encoding/json\"\n\n\t\"io\"\n\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n)\n\ntype jsonHandler struct {\n\tenc *json.Encoder\n}\n\n// NewJSONHandler returns a handler that writes govulncheck output as json.\nfunc NewJSONHandler(w io.Writer) Handler {\n\tenc := json.NewEncoder(w)\n\tenc.SetIndent(\"\", \"  \")\n\treturn &jsonHandler{enc: enc}\n}\n\n// Config writes config block in JSON to the underlying writer.\nfunc (h *jsonHandler) Config(config *Config) error {\n\treturn h.enc.Encode(Message{Config: config})\n}\n\n// Progress writes a progress message in JSON to the underlying writer.\nfunc (h *jsonHandler) Progress(progress *Progress) error {\n\treturn h.enc.Encode(Message{Progress: progress})\n}\n\n// OSV writes an osv entry in JSON to the underlying writer.\nfunc (h *jsonHandler) OSV(entry *osv.Entry) error {\n\treturn h.enc.Encode(Message{OSV: entry})\n}\n\n// Finding writes a finding in JSON to the underlying writer.\nfunc (h *jsonHandler) Finding(finding *Finding) error {\n\treturn h.enc.Encode(Message{Finding: finding})\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/osv/osv.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copying from golang.org/x/vuln@v1.0.1 (go run copier.go); DO NOT EDIT.\n\n// Package osv implements the Go OSV vulnerability format\n// (https://go.dev/security/vuln/database#schema), which is a subset of\n// the OSV shared vulnerability format\n// (https://ossf.github.io/osv-schema), with database and\n// ecosystem-specific meanings and fields.\n//\n// As this package is intended for use with the Go vulnerability\n// database, only the subset of features which are used by that\n// database are implemented (for instance, only the SEMVER affected\n// range type is implemented).\npackage osv\n\nimport \"time\"\n\n// RangeType specifies the type of version range being recorded and\n// defines the interpretation of the RangeEvent object's Introduced\n// and Fixed fields.\n//\n// In this implementation, only the \"SEMVER\" type is supported.\n//\n// See https://ossf.github.io/osv-schema/#affectedrangestype-field.\ntype RangeType string\n\n// RangeTypeSemver indicates a semantic version as defined by\n// SemVer 2.0.0, with no leading \"v\" prefix.\nconst RangeTypeSemver RangeType = \"SEMVER\"\n\n// Ecosystem identifies the overall library ecosystem.\n// In this implementation, only the \"Go\" ecosystem is supported.\ntype Ecosystem string\n\n// GoEcosystem indicates the Go ecosystem.\nconst GoEcosystem Ecosystem = \"Go\"\n\n// Pseudo-module paths used to describe vulnerabilities\n// in the Go standard library and toolchain.\nconst (\n\t// GoStdModulePath is the pseudo-module path string used\n\t// to describe vulnerabilities in the Go standard library.\n\tGoStdModulePath = \"stdlib\"\n\t// GoCmdModulePath is the pseudo-module path string used\n\t// to describe vulnerabilities in the go command.\n\tGoCmdModulePath = \"toolchain\"\n)\n\n// Module identifies the Go module containing the vulnerability.\n// Note that this field is called \"package\" in the OSV specification.\n//\n// See https://ossf.github.io/osv-schema/#affectedpackage-field.\ntype Module struct {\n\t// The Go module path. Required.\n\t// For the Go standard library, this is \"stdlib\".\n\t// For the Go toolchain, this is \"toolchain.\"\n\tPath string `json:\"name\"`\n\t// The ecosystem containing the module. Required.\n\t// This should always be \"Go\".\n\tEcosystem Ecosystem `json:\"ecosystem\"`\n}\n\n// RangeEvent describes a single module version that either\n// introduces or fixes a vulnerability.\n//\n// Exactly one of Introduced and Fixed must be present. Other range\n// event types (e.g, \"last_affected\" and \"limit\") are not supported in\n// this implementation.\n//\n// See https://ossf.github.io/osv-schema/#affectedrangesevents-fields.\ntype RangeEvent struct {\n\t// Introduced is a version that introduces the vulnerability.\n\t// A special value, \"0\", represents a version that sorts before\n\t// any other version, and should be used to indicate that the\n\t// vulnerability exists from the \"beginning of time\".\n\tIntroduced string `json:\"introduced,omitempty\"`\n\t// Fixed is a version that fixes the vulnerability.\n\tFixed string `json:\"fixed,omitempty\"`\n}\n\n// Range describes the affected versions of the vulnerable module.\n//\n// See https://ossf.github.io/osv-schema/#affectedranges-field.\ntype Range struct {\n\t// Type is the version type that should be used to interpret the\n\t// versions in Events. Required.\n\t// In this implementation, only the \"SEMVER\" type is supported.\n\tType RangeType `json:\"type\"`\n\t// Events is a list of versions representing the ranges in which\n\t// the module is vulnerable. Required.\n\t// The events should be sorted, and MUST represent non-overlapping\n\t// ranges.\n\t// There must be at least one RangeEvent containing a value for\n\t// Introduced.\n\t// See https://ossf.github.io/osv-schema/#examples for examples.\n\tEvents []RangeEvent `json:\"events\"`\n}\n\n// Reference type is a reference (link) type.\ntype ReferenceType string\n\nconst (\n\t// ReferenceTypeAdvisory is a published security advisory for\n\t// the vulnerability.\n\tReferenceTypeAdvisory = ReferenceType(\"ADVISORY\")\n\t// ReferenceTypeArticle is an article or blog post describing the vulnerability.\n\tReferenceTypeArticle = ReferenceType(\"ARTICLE\")\n\t// ReferenceTypeReport is a report, typically on a bug or issue tracker, of\n\t// the vulnerability.\n\tReferenceTypeReport = ReferenceType(\"REPORT\")\n\t// ReferenceTypeFix is a source code browser link to the fix (e.g., a GitHub commit).\n\tReferenceTypeFix = ReferenceType(\"FIX\")\n\t// ReferenceTypePackage is a home web page for the package.\n\tReferenceTypePackage = ReferenceType(\"PACKAGE\")\n\t// ReferenceTypeEvidence is a demonstration of the validity of a vulnerability claim.\n\tReferenceTypeEvidence = ReferenceType(\"EVIDENCE\")\n\t// ReferenceTypeWeb is a web page of some unspecified kind.\n\tReferenceTypeWeb = ReferenceType(\"WEB\")\n)\n\n// Reference is a reference URL containing additional information,\n// advisories, issue tracker entries, etc., about the vulnerability.\n//\n// See https://ossf.github.io/osv-schema/#references-field.\ntype Reference struct {\n\t// The type of reference. Required.\n\tType ReferenceType `json:\"type\"`\n\t// The fully-qualified URL of the reference. Required.\n\tURL string `json:\"url\"`\n}\n\n// Affected gives details about a module affected by the vulnerability.\n//\n// See https://ossf.github.io/osv-schema/#affected-fields.\ntype Affected struct {\n\t// The affected Go module. Required.\n\t// Note that this field is called \"package\" in the OSV specification.\n\tModule Module `json:\"package\"`\n\t// The module version ranges affected by the vulnerability.\n\tRanges []Range `json:\"ranges,omitempty\"`\n\t// Details on the affected packages and symbols within the module.\n\tEcosystemSpecific EcosystemSpecific `json:\"ecosystem_specific\"`\n}\n\n// Package contains additional information about an affected package.\n// This is an ecosystem-specific field for the Go ecosystem.\ntype Package struct {\n\t// Path is the package import path. Required.\n\tPath string `json:\"path,omitempty\"`\n\t// GOOS is the execution operating system where the symbols appear, if\n\t// known.\n\tGOOS []string `json:\"goos,omitempty\"`\n\t// GOARCH specifies the execution architecture where the symbols appear, if\n\t// known.\n\tGOARCH []string `json:\"goarch,omitempty\"`\n\t// Symbols is a list of function and method names affected by\n\t// this vulnerability. Methods are listed as <recv>.<method>.\n\t//\n\t// If included, only programs which use these symbols will be marked as\n\t// vulnerable by `govulncheck`. If omitted, any program which imports this\n\t// package will be marked vulnerable.\n\tSymbols []string `json:\"symbols,omitempty\"`\n}\n\n// EcosystemSpecific contains additional information about the vulnerable\n// module for the Go ecosystem.\n//\n// See https://go.dev/security/vuln/database#schema.\ntype EcosystemSpecific struct {\n\t// Packages is the list of affected packages within the module.\n\tPackages []Package `json:\"imports,omitempty\"`\n}\n\n// Entry represents a vulnerability in the Go OSV format, documented\n// in https://go.dev/security/vuln/database#schema.\n// It is a subset of the OSV schema (https://ossf.github.io/osv-schema).\n// Only fields that are published in the Go Vulnerability Database\n// are supported.\ntype Entry struct {\n\t// SchemaVersion is the OSV schema version used to encode this\n\t// vulnerability.\n\tSchemaVersion string `json:\"schema_version,omitempty\"`\n\t// ID is a unique identifier for the vulnerability. Required.\n\t// The Go vulnerability database issues IDs of the form\n\t// GO-<YEAR>-<ENTRYID>.\n\tID string `json:\"id\"`\n\t// Modified is the time the entry was last modified. Required.\n\tModified time.Time `json:\"modified,omitempty\"`\n\t// Published is the time the entry should be considered to have\n\t// been published.\n\tPublished time.Time `json:\"published,omitempty\"`\n\t// Withdrawn is the time the entry should be considered to have\n\t// been withdrawn. If the field is missing, then the entry has\n\t// not been withdrawn.\n\tWithdrawn *time.Time `json:\"withdrawn,omitempty\"`\n\t// Aliases is a list of IDs for the same vulnerability in other\n\t// databases.\n\tAliases []string `json:\"aliases,omitempty\"`\n\t// Summary gives a one-line, English textual summary of the vulnerability.\n\t// It is recommended that this field be kept short, on the order of no more\n\t// than 120 characters.\n\tSummary string `json:\"summary,omitempty\"`\n\t// Details contains additional English textual details about the vulnerability.\n\tDetails string `json:\"details\"`\n\t// Affected contains information on the modules and versions\n\t// affected by the vulnerability.\n\tAffected []Affected `json:\"affected\"`\n\t// References contains links to more information about the\n\t// vulnerability.\n\tReferences []Reference `json:\"references,omitempty\"`\n\t// Credits contains credits to entities that helped find or fix the\n\t// vulnerability.\n\tCredits []Credit `json:\"credits,omitempty\"`\n\t// DatabaseSpecific contains additional information about the\n\t// vulnerability, specific to the Go vulnerability database.\n\tDatabaseSpecific *DatabaseSpecific `json:\"database_specific,omitempty\"`\n}\n\n// Credit represents a credit for the discovery, confirmation, patch, or\n// other event in the life cycle of a vulnerability.\n//\n// See https://ossf.github.io/osv-schema/#credits-fields.\ntype Credit struct {\n\t// Name is the name, label, or other identifier of the individual or\n\t// entity being credited. Required.\n\tName string `json:\"name\"`\n}\n\n// DatabaseSpecific contains additional information about the\n// vulnerability, specific to the Go vulnerability database.\n//\n// See https://go.dev/security/vuln/database#schema.\ntype DatabaseSpecific struct {\n\t// The URL of the Go advisory for this vulnerability, of the form\n\t// \"https://pkg.go.dev/GO-YYYY-XXXX\".\n\tURL string `json:\"url,omitempty\"`\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/scan/command.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage scan\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n\t\"golang.org/x/vuln/scan\"\n)\n\n// Main implements gopls vulncheck.\nfunc Main(ctx context.Context, args ...string) error {\n\t// wrapping govulncheck.\n\tcmd := scan.Command(ctx, args...)\n\tif err := cmd.Start(); err != nil {\n\t\treturn err\n\t}\n\treturn cmd.Wait()\n}\n\n// RunGovulncheck implements the codelens \"Run Govulncheck\"\n// that runs 'gopls vulncheck' and converts the output to gopls's internal data\n// used for diagnostics and hover message construction.\n//\n// TODO(rfindley): this should accept a *View (which exposes) Options, rather\n// than a snapshot.\nfunc RunGovulncheck(ctx context.Context, pattern string, snapshot *cache.Snapshot, dir string, log io.Writer) (*vulncheck.Result, error) {\n\tvulncheckargs := []string{\n\t\t\"vulncheck\", \"--\",\n\t\t\"-json\",\n\t\t\"-mode\", \"source\",\n\t\t\"-scan\", \"symbol\",\n\t}\n\tif dir != \"\" {\n\t\tvulncheckargs = append(vulncheckargs, \"-C\", dir)\n\t}\n\tif db := cache.GetEnv(snapshot, \"GOVULNDB\"); db != \"\" {\n\t\tvulncheckargs = append(vulncheckargs, \"-db\", db)\n\t}\n\tvulncheckargs = append(vulncheckargs, pattern)\n\t// TODO: support -tags. need to compute tags args from opts.BuildFlags.\n\t// TODO: support -test.\n\n\tir, iw := io.Pipe()\n\thandler := &govulncheckHandler{logger: log, osvs: map[string]*osv.Entry{}}\n\n\tstderr := new(bytes.Buffer)\n\tvar g errgroup.Group\n\t// We run the govulncheck's analysis in a separate process as it can\n\t// consume a lot of CPUs and memory, and terminates: a separate process\n\t// is a perfect garbage collector and affords us ways to limit its resource usage.\n\tg.Go(func() error {\n\t\tdefer iw.Close()\n\n\t\tcmd := exec.CommandContext(ctx, os.Args[0], vulncheckargs...)\n\t\tcmd.Env = getEnvSlices(snapshot)\n\t\tif goversion := cache.GetEnv(snapshot, cache.GoVersionForVulnTest); goversion != \"\" {\n\t\t\t// Let govulncheck API use a different Go version using the (undocumented) hook\n\t\t\t// in https://go.googlesource.com/vuln/+/v1.0.1/internal/scan/run.go#76\n\t\t\tcmd.Env = append(cmd.Env, \"GOVERSION=\"+goversion)\n\t\t}\n\t\tcmd.Stderr = stderr // stream vulncheck's STDERR as progress reports\n\t\tcmd.Stdout = iw     // let the other goroutine parses the result.\n\n\t\tif err := cmd.Start(); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to start govulncheck: %v\", err)\n\t\t}\n\t\tif err := cmd.Wait(); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to run govulncheck: %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\tg.Go(func() error {\n\t\treturn govulncheck.HandleJSON(ir, handler)\n\t})\n\tif err := g.Wait(); err != nil {\n\t\tif stderr.Len() > 0 {\n\t\t\tlog.Write(stderr.Bytes())\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to read govulncheck output: %v: stderr:\\n%s\", err, stderr)\n\t}\n\n\tfindings := handler.findings // sort so the findings in the result is deterministic.\n\tsort.Slice(findings, func(i, j int) bool {\n\t\tx, y := findings[i], findings[j]\n\t\tif x.OSV != y.OSV {\n\t\t\treturn x.OSV < y.OSV\n\t\t}\n\t\treturn x.Trace[0].Package < y.Trace[0].Package\n\t})\n\tresult := &vulncheck.Result{\n\t\tMode:     vulncheck.ModeGovulncheck,\n\t\tAsOf:     time.Now(),\n\t\tEntries:  handler.osvs,\n\t\tFindings: findings,\n\t}\n\treturn result, nil\n}\n\ntype govulncheckHandler struct {\n\tlogger io.Writer // forward progress reports to logger.\n\n\tosvs     map[string]*osv.Entry\n\tfindings []*govulncheck.Finding\n}\n\n// Config implements vulncheck.Handler.\nfunc (h *govulncheckHandler) Config(config *govulncheck.Config) error {\n\tif config.GoVersion != \"\" {\n\t\tfmt.Fprintf(h.logger, \"Go: %v\\n\", config.GoVersion)\n\t}\n\tif config.ScannerName != \"\" {\n\t\tscannerName := fmt.Sprintf(\"Scanner: %v\", config.ScannerName)\n\t\tif config.ScannerVersion != \"\" {\n\t\t\tscannerName += \"@\" + config.ScannerVersion\n\t\t}\n\t\tfmt.Fprintln(h.logger, scannerName)\n\t}\n\tif config.DB != \"\" {\n\t\tdbInfo := fmt.Sprintf(\"DB: %v\", config.DB)\n\t\tif config.DBLastModified != nil {\n\t\t\tdbInfo += fmt.Sprintf(\" (DB updated: %v)\", config.DBLastModified.String())\n\t\t}\n\t\tfmt.Fprintln(h.logger, dbInfo)\n\t}\n\treturn nil\n}\n\n// Finding implements vulncheck.Handler.\nfunc (h *govulncheckHandler) Finding(finding *govulncheck.Finding) error {\n\th.findings = append(h.findings, finding)\n\treturn nil\n}\n\n// OSV implements vulncheck.Handler.\nfunc (h *govulncheckHandler) OSV(entry *osv.Entry) error {\n\th.osvs[entry.ID] = entry\n\treturn nil\n}\n\n// Progress implements vulncheck.Handler.\nfunc (h *govulncheckHandler) Progress(progress *govulncheck.Progress) error {\n\tif progress.Message != \"\" {\n\t\tfmt.Fprintf(h.logger, \"%v\\n\", progress.Message)\n\t}\n\treturn nil\n}\n\nfunc getEnvSlices(snapshot *cache.Snapshot) []string {\n\treturn append(os.Environ(), snapshot.Options().EnvSlice()...)\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/semver/semver.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package semver provides shared utilities for manipulating\n// Go semantic versions.\npackage semver\n\nimport (\n\t\"strings\"\n\n\t\"golang.org/x/mod/semver\"\n)\n\n// addSemverPrefix adds a 'v' prefix to s if it isn't already prefixed\n// with 'v' or 'go'. This allows us to easily test go-style SEMVER\n// strings against normal SEMVER strings.\nfunc addSemverPrefix(s string) string {\n\tif !strings.HasPrefix(s, \"v\") && !strings.HasPrefix(s, \"go\") {\n\t\treturn \"v\" + s\n\t}\n\treturn s\n}\n\n// removeSemverPrefix removes the 'v' or 'go' prefixes from go-style\n// SEMVER strings, for usage in the public vulnerability format.\nfunc removeSemverPrefix(s string) string {\n\ts = strings.TrimPrefix(s, \"v\")\n\ts = strings.TrimPrefix(s, \"go\")\n\treturn s\n}\n\n// CanonicalizeSemverPrefix turns a SEMVER string into the canonical\n// representation using the 'v' prefix, as used by the OSV format.\n// Input may be a bare SEMVER (\"1.2.3\"), Go prefixed SEMVER (\"go1.2.3\"),\n// or already canonical SEMVER (\"v1.2.3\").\nfunc CanonicalizeSemverPrefix(s string) string {\n\treturn addSemverPrefix(removeSemverPrefix(s))\n}\n\n// Valid returns whether v is valid semver, allowing\n// either a \"v\", \"go\" or no prefix.\nfunc Valid(v string) bool {\n\treturn semver.IsValid(CanonicalizeSemverPrefix(v))\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/semver/semver_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage semver\n\nimport (\n\t\"testing\"\n)\n\nfunc TestCanonicalize(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tv    string\n\t\twant string\n\t}{\n\t\t{\"v1.2.3\", \"v1.2.3\"},\n\t\t{\"1.2.3\", \"v1.2.3\"},\n\t\t{\"go1.2.3\", \"v1.2.3\"},\n\t} {\n\t\tgot := CanonicalizeSemverPrefix(test.v)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"want %s; got %s\", test.want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/types.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// go:generate go run copier.go\n\npackage vulncheck\n\nimport (\n\t\"time\"\n\n\tgvc \"golang.org/x/tools/gopls/internal/vulncheck/govulncheck\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n)\n\n// Result is the result of vulnerability scanning.\ntype Result struct {\n\t// Entries contains all vulnerabilities that are called or imported by\n\t// the analyzed module. Keys are Entry.IDs.\n\tEntries map[string]*osv.Entry\n\t// Findings are vulnerabilities found by vulncheck or import-based analysis.\n\t// Ordered by the OSV IDs and the package names.\n\tFindings []*gvc.Finding\n\n\t// Mode contains the source of the vulnerability info.\n\t// Clients of the gopls.fetch_vulncheck_result command may need\n\t// to interpret the vulnerabilities differently based on the\n\t// analysis mode. For example, Vuln without callstack traces\n\t// indicate a vulnerability that is not used if the result was\n\t// from 'govulncheck' analysis mode. On the other hand, Vuln\n\t// without callstack traces just implies the package with the\n\t// vulnerability is known to the workspace and we do not know\n\t// whether the vulnerable symbols are actually used or not.\n\tMode AnalysisMode `json:\",omitempty\"`\n\n\t// AsOf describes when this Result was computed using govulncheck.\n\t// It is valid only with the govulncheck analysis mode.\n\tAsOf time.Time\n}\n\ntype AnalysisMode string\n\nconst (\n\tModeInvalid     AnalysisMode = \"\" // zero value\n\tModeGovulncheck AnalysisMode = \"govulncheck\"\n\tModeImports     AnalysisMode = \"imports\"\n)\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/db.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package vulntest provides helpers for vulncheck functionality testing.\npackage vulntest\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// NewDatabase returns a read-only DB containing the provided\n// txtar-format collection of vulnerability reports.\n// Each vulnerability report is a YAML file whose format\n// is defined in golang.org/x/vulndb/doc/format.md.\n// A report file name must have the id as its base name,\n// and have .yaml as its extension.\n//\n//\tdb, err := NewDatabase(ctx, reports)\n//\t...\n//\tdefer db.Clean()\n//\tclient, err := NewClient(db)\n//\t...\n//\n// The returned DB's Clean method must be called to clean up the\n// generated database.\nfunc NewDatabase(ctx context.Context, txtarReports []byte) (*DB, error) {\n\tdisk, err := os.MkdirTemp(\"\", \"vulndb-test\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := generateDB(ctx, txtarReports, disk, false); err != nil {\n\t\tos.RemoveAll(disk) // ignore error\n\t\treturn nil, err\n\t}\n\n\treturn &DB{disk: disk}, nil\n}\n\n// DB is a read-only vulnerability database on disk.\n// Users can use this database with golang.org/x/vuln APIs\n// by setting the `VULNDB` environment variable.\ntype DB struct {\n\tdisk string\n}\n\n// URI returns the file URI that can be used for VULNDB environment\n// variable.\nfunc (db *DB) URI() string {\n\tu := protocol.URIFromPath(filepath.Join(db.disk, \"ID\"))\n\treturn string(u)\n}\n\n// Clean deletes the database.\nfunc (db *DB) Clean() error {\n\treturn os.RemoveAll(db.disk)\n}\n\n//\n// The following was selectively copied from golang.org/x/vulndb/internal/database\n//\n\nconst (\n\tdbURL = \"https://pkg.go.dev/vuln/\"\n\n\t// idDirectory is the name of the directory that contains entries\n\t// listed by their IDs.\n\tidDirectory = \"ID\"\n\n\t// cmdModule is the name of the module containing Go toolchain\n\t// binaries.\n\tcmdModule = \"cmd\"\n\n\t// stdModule is the name of the module containing Go std packages.\n\tstdModule = \"std\"\n)\n\n// generateDB generates the file-based vuln DB in the directory jsonDir.\nfunc generateDB(ctx context.Context, txtarData []byte, jsonDir string, indent bool) error {\n\tarchive := txtar.Parse(txtarData)\n\n\tentries, err := generateEntries(ctx, archive)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn writeEntriesByID(filepath.Join(jsonDir, idDirectory), entries, indent)\n}\n\nfunc generateEntries(_ context.Context, archive *txtar.Archive) ([]osv.Entry, error) {\n\tnow := time.Now()\n\tvar entries []osv.Entry\n\tfor _, f := range archive.Files {\n\t\tif !strings.HasSuffix(f.Name, \".yaml\") {\n\t\t\tcontinue\n\t\t}\n\t\tr, err := readReport(bytes.NewReader(f.Data))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tname := strings.TrimSuffix(filepath.Base(f.Name), filepath.Ext(f.Name))\n\t\tlinkName := fmt.Sprintf(\"%s%s\", dbURL, name)\n\t\tentry := generateOSVEntry(name, linkName, now, *r)\n\t\tentries = append(entries, entry)\n\t}\n\treturn entries, nil\n}\n\nfunc writeEntriesByID(idDir string, entries []osv.Entry, indent bool) error {\n\t// Write a directory containing entries by ID.\n\tif err := os.MkdirAll(idDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create directory %q: %v\", idDir, err)\n\t}\n\tfor _, e := range entries {\n\t\toutPath := filepath.Join(idDir, e.ID+\".json\")\n\t\tif err := writeJSON(outPath, e, indent); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc writeJSON(filename string, value any, indent bool) (err error) {\n\tj, err := jsonMarshal(value, indent)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.WriteFile(filename, j, 0644)\n}\n\nfunc jsonMarshal(v any, indent bool) ([]byte, error) {\n\tif indent {\n\t\treturn json.MarshalIndent(v, \"\", \"  \")\n\t}\n\treturn json.Marshal(v)\n}\n\n// generateOSVEntry create an osv.Entry for a report. In addition to the report, it\n// takes the ID for the vuln and a URL that will point to the entry in the vuln DB.\n// It returns the osv.Entry and a list of module paths that the vuln affects.\nfunc generateOSVEntry(id, url string, lastModified time.Time, r Report) osv.Entry {\n\tentry := osv.Entry{\n\t\tID:               id,\n\t\tPublished:        r.Published,\n\t\tModified:         lastModified,\n\t\tWithdrawn:        r.Withdrawn,\n\t\tSummary:          r.Summary,\n\t\tDetails:          r.Description,\n\t\tDatabaseSpecific: &osv.DatabaseSpecific{URL: url},\n\t}\n\n\tmoduleMap := make(map[string]bool)\n\tfor _, m := range r.Modules {\n\t\tswitch m.Module {\n\t\tcase stdModule:\n\t\t\tmoduleMap[osv.GoStdModulePath] = true\n\t\tcase cmdModule:\n\t\t\tmoduleMap[osv.GoCmdModulePath] = true\n\t\tdefault:\n\t\t\tmoduleMap[m.Module] = true\n\t\t}\n\t\tentry.Affected = append(entry.Affected, toAffected(m))\n\t}\n\tfor _, ref := range r.References {\n\t\tentry.References = append(entry.References, osv.Reference{\n\t\t\tType: ref.Type,\n\t\t\tURL:  ref.URL,\n\t\t})\n\t}\n\treturn entry\n}\n\nfunc AffectedRanges(versions []VersionRange) []osv.Range {\n\ta := osv.Range{Type: osv.RangeTypeSemver}\n\tif len(versions) == 0 || versions[0].Introduced == \"\" {\n\t\ta.Events = append(a.Events, osv.RangeEvent{Introduced: \"0\"})\n\t}\n\tfor _, v := range versions {\n\t\tif v.Introduced != \"\" {\n\t\t\ta.Events = append(a.Events, osv.RangeEvent{Introduced: v.Introduced.Canonical()})\n\t\t}\n\t\tif v.Fixed != \"\" {\n\t\t\ta.Events = append(a.Events, osv.RangeEvent{Fixed: v.Fixed.Canonical()})\n\t\t}\n\t}\n\treturn []osv.Range{a}\n}\n\nfunc toOSVPackages(pkgs []*Package) (imps []osv.Package) {\n\tfor _, p := range pkgs {\n\t\tsyms := slices.Clone(p.Symbols)\n\t\tsyms = append(syms, p.DerivedSymbols...)\n\t\tsort.Strings(syms)\n\t\timps = append(imps, osv.Package{\n\t\t\tPath:    p.Package,\n\t\t\tGOOS:    p.GOOS,\n\t\t\tGOARCH:  p.GOARCH,\n\t\t\tSymbols: syms,\n\t\t})\n\t}\n\treturn imps\n}\n\nfunc toAffected(m *Module) osv.Affected {\n\tname := m.Module\n\tswitch name {\n\tcase stdModule:\n\t\tname = osv.GoStdModulePath\n\tcase cmdModule:\n\t\tname = osv.GoCmdModulePath\n\t}\n\treturn osv.Affected{\n\t\tModule: osv.Module{\n\t\t\tPath:      name,\n\t\t\tEcosystem: osv.GoEcosystem,\n\t\t},\n\t\tRanges: AffectedRanges(m.Versions),\n\t\tEcosystemSpecific: osv.EcosystemSpecific{\n\t\t\tPackages: toOSVPackages(m.Packages),\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/db_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vulntest\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n)\n\nvar update = flag.Bool(\"update\", false, \"update golden files in testdata/\")\n\nfunc TestNewDatabase(t *testing.T) {\n\tctx := context.Background()\n\n\tin, err := os.ReadFile(\"testdata/report.yaml\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tin = append([]byte(\"-- GO-2020-0001.yaml --\\n\"), in...)\n\n\tdb, err := NewDatabase(ctx, in)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer db.Clean()\n\tdbpath := protocol.DocumentURI(db.URI()).Path()\n\n\t// The generated JSON file will be in DB/GO-2022-0001.json.\n\tgot := readOSVEntry(t, filepath.Join(dbpath, \"GO-2020-0001.json\"))\n\tgot.Modified = time.Time{}\n\n\tif *update {\n\t\tupdateTestData(t, got, \"testdata/GO-2020-0001.json\")\n\t}\n\n\twant := readOSVEntry(t, \"testdata/GO-2020-0001.json\")\n\twant.Modified = time.Time{}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"mismatch (-want +got):\\n%s\", diff)\n\t}\n}\n\nfunc updateTestData(t *testing.T, got *osv.Entry, fname string) {\n\tcontent, err := json.MarshalIndent(got, \"\", \"\\t\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(fname, content, 0666); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tt.Logf(\"updated %v\", fname)\n}\n\nfunc readOSVEntry(t *testing.T, filename string) *osv.Entry {\n\tt.Helper()\n\tcontent, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar entry osv.Entry\n\tif err := json.Unmarshal(content, &entry); err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn &entry\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/report.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vulntest\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/tools/gopls/internal/vulncheck/osv\"\n\t\"gopkg.in/yaml.v3\"\n)\n\n//\n// The following was selectively copied from golang.org/x/vulndb/internal/report\n//\n\n// readReport reads a Report in YAML format.\nfunc readReport(in io.Reader) (*Report, error) {\n\td := yaml.NewDecoder(in)\n\t// Require that all fields in the file are in the struct.\n\t// This corresponds to v2's UnmarshalStrict.\n\td.KnownFields(true)\n\tvar r Report\n\tif err := d.Decode(&r); err != nil {\n\t\treturn nil, fmt.Errorf(\"yaml.Decode: %v\", err)\n\t}\n\treturn &r, nil\n}\n\n// Report represents a vulnerability report in the vulndb.\n// See https://go.googlesource.com/vulndb/+/refs/heads/master/doc/format.md\ntype Report struct {\n\tID string `yaml:\",omitempty\"`\n\n\tModules []*Module `yaml:\",omitempty\"`\n\n\t// Summary is a short phrase describing the vulnerability.\n\tSummary string `yaml:\",omitempty\"`\n\n\t// Description is the CVE description from an existing CVE. If we are\n\t// assigning a CVE ID ourselves, use CVEMetadata.Description instead.\n\tDescription string     `yaml:\",omitempty\"`\n\tPublished   time.Time  `yaml:\",omitempty\"`\n\tWithdrawn   *time.Time `yaml:\",omitempty\"`\n\n\tReferences []*Reference `yaml:\",omitempty\"`\n}\n\n// Write writes r to filename in YAML format.\nfunc (r *Report) Write(filename string) (err error) {\n\tf, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = r.encode(f)\n\terr2 := f.Close()\n\tif err == nil {\n\t\terr = err2\n\t}\n\treturn err\n}\n\n// ToString encodes r to a YAML string.\nfunc (r *Report) ToString() (string, error) {\n\tvar b strings.Builder\n\tif err := r.encode(&b); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn b.String(), nil\n}\n\nfunc (r *Report) encode(w io.Writer) error {\n\te := yaml.NewEncoder(w)\n\tdefer e.Close()\n\te.SetIndent(4)\n\treturn e.Encode(r)\n}\n\ntype VersionRange struct {\n\tIntroduced Version `yaml:\"introduced,omitempty\"`\n\tFixed      Version `yaml:\"fixed,omitempty\"`\n}\n\ntype Module struct {\n\tModule   string         `yaml:\",omitempty\"`\n\tVersions []VersionRange `yaml:\",omitempty\"`\n\tPackages []*Package     `yaml:\",omitempty\"`\n}\n\ntype Package struct {\n\tPackage string   `yaml:\",omitempty\"`\n\tGOOS    []string `yaml:\"goos,omitempty\"`\n\tGOARCH  []string `yaml:\"goarch,omitempty\"`\n\t// Symbols originally identified as vulnerable.\n\tSymbols []string `yaml:\",omitempty\"`\n\t// Additional vulnerable symbols, computed from Symbols via static analysis\n\t// or other technique.\n\tDerivedSymbols []string `yaml:\"derived_symbols,omitempty\"`\n}\n\n// Version is a SemVer 2.0.0 semantic version with no leading \"v\" prefix,\n// as used by OSV.\ntype Version string\n\n// V returns the version with a \"v\" prefix.\nfunc (v Version) V() string {\n\treturn \"v\" + string(v)\n}\n\n// IsValid reports whether v is a valid semantic version string.\nfunc (v Version) IsValid() bool {\n\treturn semver.IsValid(v.V())\n}\n\n// Before reports whether v < v2.\nfunc (v Version) Before(v2 Version) bool {\n\treturn semver.Compare(v.V(), v2.V()) < 0\n}\n\n// Canonical returns the canonical formatting of the version.\nfunc (v Version) Canonical() string {\n\treturn strings.TrimPrefix(semver.Canonical(v.V()), \"v\")\n}\n\n// A Reference is a link to some external resource.\n//\n// For ease of typing, References are represented in the YAML as a\n// single-element mapping of type to URL.\ntype Reference osv.Reference\n\nfunc (r *Reference) MarshalYAML() (any, error) {\n\treturn map[string]string{\n\t\tstrings.ToLower(string(r.Type)): r.URL,\n\t}, nil\n}\n\nfunc (r *Reference) UnmarshalYAML(n *yaml.Node) (err error) {\n\tif n.Kind != yaml.MappingNode || len(n.Content) != 2 || n.Content[0].Kind != yaml.ScalarNode || n.Content[1].Kind != yaml.ScalarNode {\n\t\treturn &yaml.TypeError{Errors: []string{\n\t\t\tfmt.Sprintf(\"line %d: report.Reference must contain a mapping with one value\", n.Line),\n\t\t}}\n\t}\n\tr.Type = osv.ReferenceType(strings.ToUpper(n.Content[0].Value))\n\tr.URL = n.Content[1].Value\n\treturn nil\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/report_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vulntest\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc readAll(t *testing.T, filename string) io.Reader {\n\td, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn bytes.NewReader(d)\n}\n\nfunc TestRoundTrip(t *testing.T) {\n\t// A report shouldn't change after being read and then written.\n\tin := filepath.Join(\"testdata\", \"report.yaml\")\n\tr, err := readReport(readAll(t, in))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tout := filepath.Join(t.TempDir(), \"report.yaml\")\n\tif err := r.Write(out); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twant, err := os.ReadFile(in)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot, err := os.ReadFile(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"mismatch (-want, +got):\\n%s\", diff)\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/stdlib.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vulntest\n\nimport (\n\t\"strings\"\n\n\t\"golang.org/x/mod/module\"\n)\n\n// maybeStdlib reports whether the given import path could be part of the Go\n// standard library, by reporting whether the first component lacks a '.'.\nfunc maybeStdlib(path string) bool {\n\tif err := module.CheckImportPath(path); err != nil {\n\t\treturn false\n\t}\n\tif i := strings.IndexByte(path, '/'); i != -1 {\n\t\tpath = path[:i]\n\t}\n\treturn !strings.Contains(path, \".\")\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/stdlib_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage vulntest\n\nimport \"testing\"\n\nfunc TestMaybeStdlib(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tin   string\n\t\twant bool\n\t}{\n\t\t{\"\", false},\n\t\t{\"math/crypto\", true},\n\t\t{\"github.com/pkg/errors\", false},\n\t\t{\"Path is unknown\", false},\n\t} {\n\t\tgot := maybeStdlib(test.in)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"%q: got %t, want %t\", test.in, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/testdata/GO-2020-0001.json",
    "content": "{\n\t\"id\": \"GO-2020-0001\",\n\t\"modified\": \"0001-01-01T00:00:00Z\",\n\t\"published\": \"0001-01-01T00:00:00Z\",\n\t\"details\": \"The default Formatter for the Logger middleware (LoggerConfig.Formatter),\\nwhich is included in the Default engine, allows attackers to inject arbitrary\\nlog entries by manipulating the request path.\\n\",\n\t\"affected\": [\n\t\t{\n\t\t\t\"package\": {\n\t\t\t\t\"name\": \"github.com/gin-gonic/gin\",\n\t\t\t\t\"ecosystem\": \"Go\"\n\t\t\t},\n\t\t\t\"ranges\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"SEMVER\",\n\t\t\t\t\t\"events\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"introduced\": \"0\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"fixed\": \"1.6.0\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"ecosystem_specific\": {\n\t\t\t\t\"imports\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"path\": \"github.com/gin-gonic/gin\",\n\t\t\t\t\t\t\"symbols\": [\n\t\t\t\t\t\t\t\"defaultLogFormatter\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t],\n\t\"references\": [\n\t\t{\n\t\t\t\"type\": \"FIX\",\n\t\t\t\"url\": \"https://github.com/gin-gonic/gin/pull/1234\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"FIX\",\n\t\t\t\"url\": \"https://github.com/gin-gonic/gin/commit/abcdefg\"\n\t\t}\n\t],\n\t\"database_specific\": {\n\t\t\"url\": \"https://pkg.go.dev/vuln/GO-2020-0001\"\n\t}\n}"
  },
  {
    "path": "gopls/internal/vulncheck/vulntest/testdata/report.yaml",
    "content": "modules:\n    - module: github.com/gin-gonic/gin\n      versions:\n        - fixed: 1.6.0\n      packages:\n        - package: github.com/gin-gonic/gin\n          symbols:\n            - defaultLogFormatter\ndescription: |\n    The default Formatter for the Logger middleware (LoggerConfig.Formatter),\n    which is included in the Default engine, allows attackers to inject arbitrary\n    log entries by manipulating the request path.\nreferences:\n    - fix: https://github.com/gin-gonic/gin/pull/1234\n    - fix: https://github.com/gin-gonic/gin/commit/abcdefg\n"
  },
  {
    "path": "gopls/internal/work/completion.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage work\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) (*protocol.CompletionList, error) {\n\tctx, done := event.Start(ctx, \"work.Completion\")\n\tdefer done()\n\n\t// Get the position of the cursor.\n\tpw, err := snapshot.ParseWork(ctx, fh)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting go.work file handle: %w\", err)\n\t}\n\tcursor, err := pw.Mapper.PositionOffset(position)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"computing cursor offset: %w\", err)\n\t}\n\n\t// Find the use statement the user is in.\n\tuse, pathStart, _ := usePath(pw, cursor, cursor)\n\tif use == nil {\n\t\treturn &protocol.CompletionList{}, nil\n\t}\n\tcompletingFrom := use.Path[:cursor-pathStart]\n\n\t// We're going to find the completions of the user input\n\t// (completingFrom) by doing a walk on the innermost directory\n\t// of the given path, and comparing the found paths to make sure\n\t// that they match the component of the path after the\n\t// innermost directory.\n\t//\n\t// We'll maintain two paths when doing this: pathPrefixSlash\n\t// is essentially the path the user typed in, and pathPrefixAbs\n\t// is the path made absolute from the go.work directory.\n\n\tpathPrefixSlash := completingFrom\n\tpathPrefixAbs := filepath.FromSlash(pathPrefixSlash)\n\tif !filepath.IsAbs(pathPrefixAbs) {\n\t\tpathPrefixAbs = filepath.Join(pw.URI.DirPath(), pathPrefixAbs)\n\t}\n\n\t// pathPrefixDir is the directory that will be walked to find matches.\n\t// If pathPrefixSlash is not explicitly a directory boundary (is either equivalent to \".\" or\n\t// ends in a separator) we need to examine its parent directory to find sibling files that\n\t// match.\n\tdepthBound := 5\n\tpathPrefixDir, pathPrefixBase := pathPrefixAbs, \"\"\n\tpathPrefixSlashDir := pathPrefixSlash\n\tif filepath.Clean(pathPrefixSlash) != \".\" && !strings.HasSuffix(pathPrefixSlash, \"/\") {\n\t\tdepthBound++\n\t\tpathPrefixDir, pathPrefixBase = filepath.Split(pathPrefixAbs)\n\t\tpathPrefixSlashDir = dirNonClean(pathPrefixSlash)\n\t}\n\n\tvar completions []string\n\t// Stop traversing deeper once we've hit 10k files to try to stay generally under 100ms.\n\tconst numSeenBound = 10000\n\tvar numSeen int\n\tstopWalking := errors.New(\"hit numSeenBound\")\n\terr = filepath.WalkDir(pathPrefixDir, func(wpath string, entry fs.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\t// golang/go#64225: an error reading a dir is expected, as the user may\n\t\t\t// be typing out a use directive for a directory that doesn't exist.\n\t\t\treturn nil\n\t\t}\n\t\tif numSeen > numSeenBound {\n\t\t\t// Stop traversing if we hit bound.\n\t\t\treturn stopWalking\n\t\t}\n\t\tnumSeen++\n\n\t\t// rel is the path relative to pathPrefixDir.\n\t\t// Make sure that it has pathPrefixBase as a prefix\n\t\t// otherwise it won't match the beginning of the\n\t\t// base component of the path the user typed in.\n\t\trel := strings.TrimPrefix(wpath[len(pathPrefixDir):], string(filepath.Separator))\n\t\tif entry.IsDir() && wpath != pathPrefixDir && !strings.HasPrefix(rel, pathPrefixBase) {\n\t\t\treturn filepath.SkipDir\n\t\t}\n\n\t\t// Check for a match (a module directory).\n\t\tif filepath.Base(rel) == \"go.mod\" {\n\t\t\trelDir := strings.TrimSuffix(dirNonClean(rel), string(os.PathSeparator))\n\t\t\tcompletionPath := join(pathPrefixSlashDir, filepath.ToSlash(relDir))\n\n\t\t\tif !strings.HasPrefix(completionPath, completingFrom) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif strings.HasSuffix(completionPath, \"/\") {\n\t\t\t\t// Don't suggest paths that end in \"/\". This happens\n\t\t\t\t// when the input is a path that ends in \"/\" and\n\t\t\t\t// the completion is empty.\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcompletion := completionPath[len(completingFrom):]\n\t\t\tif completingFrom == \"\" && !strings.HasPrefix(completion, \"./\") {\n\t\t\t\t// Bias towards \"./\" prefixes.\n\t\t\t\tcompletion = join(\".\", completion)\n\t\t\t}\n\n\t\t\tcompletions = append(completions, completion)\n\t\t}\n\n\t\tif depth := strings.Count(rel, string(filepath.Separator)); depth >= depthBound {\n\t\t\treturn filepath.SkipDir\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil && !errors.Is(err, stopWalking) {\n\t\treturn nil, fmt.Errorf(\"walking to find completions: %w\", err)\n\t}\n\n\tsort.Strings(completions)\n\n\titems := []protocol.CompletionItem{} // must be a slice\n\tfor _, c := range completions {\n\t\titems = append(items, protocol.CompletionItem{\n\t\t\tLabel:      c,\n\t\t\tInsertText: c,\n\t\t})\n\t}\n\treturn &protocol.CompletionList{Items: items}, nil\n}\n\n// dirNonClean is filepath.Dir, without the Clean at the end.\nfunc dirNonClean(path string) string {\n\tvol := filepath.VolumeName(path)\n\ti := len(path) - 1\n\tfor i >= len(vol) && !os.IsPathSeparator(path[i]) {\n\t\ti--\n\t}\n\treturn path[len(vol) : i+1]\n}\n\nfunc join(a, b string) string {\n\tif a == \"\" {\n\t\treturn b\n\t}\n\tif b == \"\" {\n\t\treturn a\n\t}\n\treturn strings.TrimSuffix(a, \"/\") + \"/\" + b\n}\n"
  },
  {
    "path": "gopls/internal/work/diagnostics.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage work\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Diagnostics(ctx context.Context, snapshot *cache.Snapshot) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {\n\tctx, done := event.Start(ctx, \"work.Diagnostics\", snapshot.Labels()...)\n\tdefer done()\n\n\treports := map[protocol.DocumentURI][]*cache.Diagnostic{}\n\turi := snapshot.View().GoWork()\n\tif uri == \"\" {\n\t\treturn nil, nil\n\t}\n\tfh, err := snapshot.ReadFile(ctx, uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treports[fh.URI()] = []*cache.Diagnostic{}\n\tdiagnostics, err := diagnoseOne(ctx, snapshot, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, d := range diagnostics {\n\t\tfh, err := snapshot.ReadFile(ctx, d.URI)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treports[fh.URI()] = append(reports[fh.URI()], d)\n\t}\n\n\treturn reports, nil\n}\n\nfunc diagnoseOne(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]*cache.Diagnostic, error) {\n\tpw, err := snapshot.ParseWork(ctx, fh)\n\tif err != nil {\n\t\tif pw == nil || len(pw.ParseErrors) == 0 {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn pw.ParseErrors, nil\n\t}\n\n\t// Add diagnostic if a directory does not contain a module.\n\tvar diagnostics []*cache.Diagnostic\n\tfor _, use := range pw.File.Use {\n\t\trng, err := pw.Mapper.OffsetRange(use.Syntax.Start.Byte, use.Syntax.End.Byte)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tmodfh, err := snapshot.ReadFile(ctx, modFileURI(pw, use))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif _, err := modfh.Content(); err != nil && os.IsNotExist(err) {\n\t\t\tdiagnostics = append(diagnostics, &cache.Diagnostic{\n\t\t\t\tURI:      fh.URI(),\n\t\t\t\tRange:    rng,\n\t\t\t\tSeverity: protocol.SeverityError,\n\t\t\t\tSource:   cache.WorkFileError,\n\t\t\t\tMessage:  fmt.Sprintf(\"directory %v does not contain a module\", use.Path),\n\t\t\t})\n\t\t}\n\t}\n\treturn diagnostics, nil\n}\n\nfunc modFileURI(pw *cache.ParsedWorkFile, use *modfile.Use) protocol.DocumentURI {\n\tworkdir := pw.URI.DirPath()\n\n\tmodroot := filepath.FromSlash(use.Path)\n\tif !filepath.IsAbs(modroot) {\n\t\tmodroot = filepath.Join(workdir, modroot)\n\t}\n\n\treturn protocol.URIFromPath(filepath.Join(modroot, \"go.mod\"))\n}\n"
  },
  {
    "path": "gopls/internal/work/format.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage work\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]protocol.TextEdit, error) {\n\tctx, done := event.Start(ctx, \"work.Format\")\n\tdefer done()\n\n\tpw, err := snapshot.ParseWork(ctx, fh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tformatted := modfile.Format(pw.File.Syntax)\n\t// Calculate the edits to be made due to the change.\n\tdiffs := diff.Bytes(pw.Mapper.Content, formatted)\n\treturn protocol.EditsFromDiffEdits(pw.Mapper, diffs)\n}\n"
  },
  {
    "path": "gopls/internal/work/hover.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage work\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/gopls/internal/cache\"\n\t\"golang.org/x/tools/gopls/internal/file\"\n\t\"golang.org/x/tools/gopls/internal/protocol\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\nfunc Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (*protocol.Hover, error) {\n\t// We only provide hover information for the view's go.work file.\n\tif fh.URI() != snapshot.View().GoWork() {\n\t\treturn nil, nil\n\t}\n\n\tctx, done := event.Start(ctx, \"work.Hover\")\n\tdefer done()\n\n\t// Get the position of the cursor.\n\tpw, err := snapshot.ParseWork(ctx, fh)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting go.work file handle: %w\", err)\n\t}\n\tstartOffset, endOffset, err := pw.Mapper.RangeOffsets(rng)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"computing cursor offset: %w\", err)\n\t}\n\n\t// Confirm that the cursor is inside a use statement, and then find\n\t// the position of the use statement's directory path.\n\tuse, pathStart, pathEnd := usePath(pw, startOffset, endOffset)\n\n\t// The cursor position is not on a use statement.\n\tif use == nil {\n\t\treturn nil, nil\n\t}\n\n\t// Get the mod file denoted by the use.\n\tmodfh, err := snapshot.ReadFile(ctx, modFileURI(pw, use))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting modfile handle: %w\", err)\n\t}\n\tpm, err := snapshot.ParseMod(ctx, modfh)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting modfile handle: %w\", err)\n\t}\n\tif pm.File.Module == nil {\n\t\treturn nil, fmt.Errorf(\"modfile has no module declaration\")\n\t}\n\tmod := pm.File.Module.Mod\n\n\t// Get the range to highlight for the hover.\n\tpathRng, err := pw.Mapper.OffsetRange(pathStart, pathEnd)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\toptions := snapshot.Options()\n\treturn &protocol.Hover{\n\t\tContents: protocol.MarkupContent{\n\t\t\tKind:  options.PreferredContentFormat,\n\t\t\tValue: mod.Path,\n\t\t},\n\t\tRange: pathRng,\n\t}, nil\n}\n\nfunc usePath(pw *cache.ParsedWorkFile, startOffset, endOffset int) (use *modfile.Use, pathStart, pathEnd int) {\n\tfor _, u := range pw.File.Use {\n\t\tpath := []byte(u.Path)\n\t\ts, e := u.Syntax.Start.Byte, u.Syntax.End.Byte\n\t\ti := bytes.Index(pw.Mapper.Content[s:e], path)\n\t\tif i == -1 {\n\t\t\t// This should not happen.\n\t\t\tcontinue\n\t\t}\n\t\t// Shift the start position to the location of the\n\t\t// module directory within the use statement.\n\t\tpathStart, pathEnd = s+i, s+i+len(path)\n\t\tif pathStart <= startOffset && endOffset <= pathEnd {\n\t\t\treturn u, pathStart, pathEnd\n\t\t}\n\t}\n\treturn nil, 0, 0\n}\n"
  },
  {
    "path": "gopls/main.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Gopls (pronounced “go please”) is an LSP server for Go.\n// The Language Server Protocol allows any text editor\n// to be extended with IDE-like features;\n// see https://langserver.org/ for details.\n//\n// See https://go.dev/gopls for comprehensive documentation on Gopls.\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/telemetry\"\n\t\"golang.org/x/telemetry/counter\"\n\t\"golang.org/x/tools/gopls/internal/cmd\"\n\t\"golang.org/x/tools/gopls/internal/filecache\"\n\tversionpkg \"golang.org/x/tools/gopls/internal/version\"\n\t\"golang.org/x/tools/internal/tool\"\n)\n\nvar version = \"\" // if set by the linker, overrides the gopls version\n\nfunc main() {\n\tversionpkg.VersionOverride = version\n\n\ttelemetry.Start(telemetry.Config{\n\t\tReportCrashes: true,\n\t\tUpload:        true,\n\t})\n\n\t// Force early creation of the filecache and refuse to start\n\t// if there were unexpected errors such as ENOSPC. This\n\t// minimizes the window of exposure to deletion of the\n\t// executable, and ensures that all subsequent calls to\n\t// filecache.Get cannot fail for these two reasons;\n\t// see issue #67433.\n\t//\n\t// This leaves only one likely cause for later failures:\n\t// deletion of the cache while gopls is running. If the\n\t// problem continues, we could periodically stat the cache\n\t// directory (for example at the start of every RPC) and\n\t// either re-create it or just fail the RPC with an\n\t// informative error and terminate the process.\n\tif _, err := filecache.Get(\"nonesuch\", [32]byte{}); err != nil && err != filecache.ErrNotFound {\n\t\tcounter.Inc(\"gopls/nocache\")\n\t\tlog.Fatalf(\"gopls cannot access its persistent index (disk full?): %v\", err)\n\t}\n\n\tctx := context.Background()\n\ttool.Main(ctx, cmd.New(), os.Args[1:])\n}\n"
  },
  {
    "path": "imports/forward.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package imports implements a Go pretty-printer (like package \"go/format\")\n// that also adds or removes import statements as necessary.\npackage imports // import \"golang.org/x/tools/imports\"\n\nimport (\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n\tintimp \"golang.org/x/tools/internal/imports\"\n)\n\n// Options specifies options for processing files.\ntype Options struct {\n\tFragment  bool // Accept fragment of a source file (no package statement)\n\tAllErrors bool // Report all errors (not just the first 10 on different lines)\n\n\tComments  bool // Print comments (true if nil *Options provided)\n\tTabIndent bool // Use tabs for indent (true if nil *Options provided)\n\tTabWidth  int  // Tab width (8 if nil *Options provided)\n\n\tFormatOnly bool // Disable the insertion and deletion of imports\n}\n\n// Debug controls verbose logging.\nvar Debug = false\n\n// LocalPrefix is a comma-separated string of import path prefixes, which, if\n// set, instructs Process to sort the import paths with the given prefixes\n// into another group after 3rd-party packages.\nvar LocalPrefix string\n\n// Process formats and adjusts imports for the provided file.\n// If opt is nil the defaults are used, and if src is nil the source\n// is read from the filesystem.\n//\n// Note that filename's directory influences which imports can be chosen,\n// so it is important that filename be accurate.\n// To process data “as if” it were in filename, pass the data as a non-nil src.\nfunc Process(filename string, src []byte, opt *Options) ([]byte, error) {\n\tvar err error\n\tif src == nil {\n\t\tsrc, err = os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif opt == nil {\n\t\topt = &Options{Comments: true, TabIndent: true, TabWidth: 8}\n\t}\n\tintopt := &intimp.Options{\n\t\tEnv: &intimp.ProcessEnv{\n\t\t\tGocmdRunner: &gocommand.Runner{},\n\t\t},\n\t\tLocalPrefix: LocalPrefix,\n\t\tAllErrors:   opt.AllErrors,\n\t\tComments:    opt.Comments,\n\t\tFormatOnly:  opt.FormatOnly,\n\t\tFragment:    opt.Fragment,\n\t\tTabIndent:   opt.TabIndent,\n\t\tTabWidth:    opt.TabWidth,\n\t}\n\tif Debug {\n\t\tintopt.Env.Logf = log.Printf\n\t}\n\treturn intimp.Process(filename, src, intopt)\n}\n\n// VendorlessPath returns the devendorized version of the import path ipath.\n// For example, VendorlessPath(\"foo/barbendor/a/b\") return \"a/b\".\nfunc VendorlessPath(ipath string) string {\n\treturn intimp.VendorlessPath(ipath)\n}\n"
  },
  {
    "path": "internal/aliases/aliases.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage aliases\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// New creates a new TypeName in Package pkg that\n// is an alias for the type rhs.\nfunc New(pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName {\n\ttname := types.NewTypeName(pos, pkg, name, nil)\n\ttypes.NewAlias(tname, rhs).SetTypeParams(tparams)\n\treturn tname\n}\n"
  },
  {
    "path": "internal/aliases/aliases_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage aliases_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/aliases\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestNew tests that [aliases.New] creates a *types.Alias of a type\n// whose underlying and Unaliased type is *Named.\nfunc TestNew(t *testing.T) {\n\tconst source = `\n\tpackage p\n\n\ttype Named int\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"p\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\texpr := `*Named`\n\ttv, err := types.Eval(fset, pkg, 0, expr)\n\tif err != nil {\n\t\tt.Fatalf(\"Eval(%s) failed: %v\", expr, err)\n\t}\n\n\tA := aliases.New(token.NoPos, pkg, \"A\", tv.Type, nil)\n\tif got, want := A.Name(), \"A\"; got != want {\n\t\tt.Errorf(\"Expected A.Name()==%q. got %q\", want, got)\n\t}\n\n\tif got, want := A.Type().Underlying(), tv.Type; got != want {\n\t\tt.Errorf(\"Expected A.Type().Underlying()==%q. got %q\", want, got)\n\t}\n\tif got, want := types.Unalias(A.Type()), tv.Type; got != want {\n\t\tt.Errorf(\"Expected Unalias(A)==%q. got %q\", want, got)\n\t}\n\tif _, ok := A.Type().(*types.Alias); !ok {\n\t\tt.Errorf(\"Expected A.Type() to be a *types.Alias; got %q\", A.Type())\n\t}\n}\n\n// TestNewParameterizedAlias tests that [aliases.New] can create a parameterized alias\n// A[T] of a type whose underlying and Unaliased type is *T. The test then\n// instantiates A[Named] and checks that the underlying and Unaliased type\n// of A[Named] is *Named.\n//\n// Requires aliastypeparams GOEXPERIMENT.\nfunc TestNewParameterizedAlias(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\tif testenv.Go1Point() == 23 {\n\t\ttestenv.NeedsGoExperiment(t, \"aliastypeparams\")\n\t}\n\n\tconst source = `\n\tpackage p\n\n\ttype Named int\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"p\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// type A[T ~int] = *T\n\ttparam := types.NewTypeParam(\n\t\ttypes.NewTypeName(token.NoPos, pkg, \"T\", nil),\n\t\ttypes.NewUnion([]*types.Term{types.NewTerm(true, types.Typ[types.Int])}),\n\t)\n\tptrT := types.NewPointer(tparam)\n\tA := aliases.New(token.NoPos, pkg, \"A\", ptrT, []*types.TypeParam{tparam})\n\tif got, want := A.Name(), \"A\"; got != want {\n\t\tt.Errorf(\"New: got %q, want %q\", got, want)\n\t}\n\n\tif got, want := A.Type().Underlying(), ptrT; !types.Identical(got, want) {\n\t\tt.Errorf(\"A.Type().Underlying (%q) is not identical to %q\", got, want)\n\t}\n\tif got, want := types.Unalias(A.Type()), ptrT; !types.Identical(got, want) {\n\t\tt.Errorf(\"Unalias(A)==%q is not identical to %q\", got, want)\n\t}\n\n\tif _, ok := A.Type().(*types.Alias); !ok {\n\t\tt.Errorf(\"Expected A.Type() to be a types.Alias(). got %q\", A.Type())\n\t}\n\n\tpkg.Scope().Insert(A) // Add A to pkg so it is available to types.Eval.\n\n\tnamed, ok := pkg.Scope().Lookup(\"Named\").(*types.TypeName)\n\tif !ok {\n\t\tt.Fatalf(\"Failed to Lookup(%q) in package %s\", \"Named\", pkg)\n\t}\n\tptrNamed := types.NewPointer(named.Type())\n\n\tconst expr = `A[Named]`\n\ttv, err := types.Eval(fset, pkg, 0, expr)\n\tif err != nil {\n\t\tt.Fatalf(\"Eval(%s) failed: %v\", expr, err)\n\t}\n\n\tif got, want := tv.Type.Underlying(), ptrNamed; !types.Identical(got, want) {\n\t\tt.Errorf(\"A[Named].Type().Underlying (%q) is not identical to %q\", got, want)\n\t}\n\tif got, want := types.Unalias(tv.Type), ptrNamed; !types.Identical(got, want) {\n\t\tt.Errorf(\"Unalias(A[Named])==%q is not identical to %q\", got, want)\n\t}\n}\n"
  },
  {
    "path": "internal/analysis/README",
    "content": "\nThis is not a package. Do not add *.go files here."
  },
  {
    "path": "internal/analysis/analyzerutil/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package analyzerutil provides implementation helpers for analyzers.\npackage analyzerutil\n"
  },
  {
    "path": "internal/analysis/analyzerutil/extractdoc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analyzerutil\n\nimport (\n\t\"fmt\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strings\"\n)\n\n// MustExtractDoc is like [ExtractDoc] but it panics on error.\n//\n// To use, define a doc.go file such as:\n//\n//\t// Package halting defines an analyzer of program termination.\n//\t//\n//\t// # Analyzer halting\n//\t//\n//\t// halting: reports whether execution will halt.\n//\t//\n//\t// The halting analyzer reports a diagnostic for functions\n//\t// that run forever. To suppress the diagnostics, try inserting\n//\t// a 'break' statement into each loop.\n//\tpackage halting\n//\n//\timport _ \"embed\"\n//\n//\t//go:embed doc.go\n//\tvar doc string\n//\n// And declare your analyzer as:\n//\n//\tvar Analyzer = &analysis.Analyzer{\n//\t\tName:             \"halting\",\n//\t\tDoc:              analyzerutil.MustExtractDoc(doc, \"halting\"),\n//\t\t...\n//\t}\nfunc MustExtractDoc(content, name string) string {\n\tdoc, err := ExtractDoc(content, name)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn doc\n}\n\n// ExtractDoc extracts a section of a package doc comment from the\n// provided contents of an analyzer package's doc.go file.\n//\n// A section is a portion of the comment between one heading and\n// the next, using this form:\n//\n//\t# Analyzer NAME\n//\n//\tNAME: SUMMARY\n//\n//\tFull description...\n//\n// where NAME matches the name argument, and SUMMARY is a brief\n// verb-phrase that describes the analyzer. The following lines, up\n// until the next heading or the end of the comment, contain the full\n// description. ExtractDoc returns the portion following the colon,\n// which is the form expected by Analyzer.Doc.\n//\n// Example:\n//\n//\t# Analyzer printf\n//\n//\tprintf: checks consistency of calls to printf\n//\n//\tThe printf analyzer checks consistency of calls to printf.\n//\tHere is the complete description...\n//\n// This notation allows a single doc comment to provide documentation\n// for multiple analyzers, each in its own section.\n// The HTML anchors generated for each heading are predictable.\n//\n// It returns an error if the content was not a valid Go source file\n// containing a package doc comment with a heading of the required\n// form.\n//\n// This machinery enables the package documentation (typically\n// accessible via the web at https://pkg.go.dev/) and the command\n// documentation (typically printed to a terminal) to be derived from\n// the same source and formatted appropriately.\nfunc ExtractDoc(content, name string) (string, error) {\n\tif content == \"\" {\n\t\treturn \"\", fmt.Errorf(\"empty Go source file\")\n\t}\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"\", content, parser.ParseComments|parser.PackageClauseOnly)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"not a Go source file\")\n\t}\n\tif f.Doc == nil {\n\t\treturn \"\", fmt.Errorf(\"Go source file has no package doc comment\")\n\t}\n\tfor section := range strings.SplitSeq(f.Doc.Text(), \"\\n# \") {\n\t\tif body := strings.TrimPrefix(section, \"Analyzer \"+name); body != section &&\n\t\t\tbody != \"\" &&\n\t\t\tbody[0] == '\\r' || body[0] == '\\n' {\n\t\t\tbody = strings.TrimSpace(body)\n\t\t\trest := strings.TrimPrefix(body, name+\":\")\n\t\t\tif rest == body {\n\t\t\t\treturn \"\", fmt.Errorf(\"'Analyzer %s' heading not followed by '%s: summary...' line\", name, name)\n\t\t\t}\n\t\t\treturn strings.TrimSpace(rest), nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"package doc comment contains no 'Analyzer %s' heading\", name)\n}\n"
  },
  {
    "path": "internal/analysis/analyzerutil/extractdoc_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analyzerutil_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/analysis/analyzerutil\"\n)\n\nfunc TestExtractDoc(t *testing.T) {\n\tconst multi = `// Copyright\n\n//+build tag\n\n// Package foo\n//\n// # Irrelevant heading\n//\n// This is irrelevant doc.\n//\n// # Analyzer nocolon\n//\n// This one has the wrong form for this line.\n//\n// # Analyzer food\n//\n// food: reports dining opportunities\n//\n// This is the doc for analyzer 'food'.\n//\n// # Analyzer foo\n//\n// foo: reports diagnostics\n//\n// This is the doc for analyzer 'foo'.\n//\n// # Analyzer bar\n//\n// bar: reports drinking opportunities\n//\n// This is the doc for analyzer 'bar'.\npackage blah\n\nvar x = syntax error\n`\n\n\tfor _, test := range []struct {\n\t\tcontent, name string\n\t\twant          string // doc or \"error: %w\" string\n\t}{\n\t\t{\"\", \"foo\",\n\t\t\t\"error: empty Go source file\"},\n\t\t{\"//foo\", \"foo\",\n\t\t\t\"error: not a Go source file\"},\n\t\t{\"//foo\\npackage foo\", \"foo\",\n\t\t\t\"error: package doc comment contains no 'Analyzer foo' heading\"},\n\t\t{multi, \"foo\",\n\t\t\t\"reports diagnostics\\n\\nThis is the doc for analyzer 'foo'.\"},\n\t\t{multi, \"bar\",\n\t\t\t\"reports drinking opportunities\\n\\nThis is the doc for analyzer 'bar'.\"},\n\t\t{multi, \"food\",\n\t\t\t\"reports dining opportunities\\n\\nThis is the doc for analyzer 'food'.\"},\n\t\t{multi, \"nope\",\n\t\t\t\"error: package doc comment contains no 'Analyzer nope' heading\"},\n\t\t{multi, \"nocolon\",\n\t\t\t\"error: 'Analyzer nocolon' heading not followed by 'nocolon: summary...' line\"},\n\t} {\n\t\tgot, err := analyzerutil.ExtractDoc(test.content, test.name)\n\t\tif err != nil {\n\t\t\tgot = \"error: \" + err.Error()\n\t\t}\n\t\tif test.want != got {\n\t\t\tt.Errorf(\"ExtractDoc(%q) returned <<%s>>, want <<%s>>, given input <<%s>>\",\n\t\t\t\ttest.name, got, test.want, test.content)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/analysis/analyzerutil/readfile.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analyzerutil\n\n// This file defines helpers for calling [analysis.Pass.ReadFile].\n\nimport (\n\t\"go/token\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// ReadFile reads a file and adds it to the FileSet in pass\n// so that we can report errors against it using lineStart.\nfunc ReadFile(pass *analysis.Pass, filename string) ([]byte, *token.File, error) {\n\treadFile := pass.ReadFile\n\tif readFile == nil {\n\t\treadFile = os.ReadFile\n\t}\n\tcontent, err := readFile(filename)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\ttf := pass.Fset.AddFile(filename, -1, len(content))\n\ttf.SetLinesForContent(content)\n\treturn content, tf, nil\n}\n"
  },
  {
    "path": "internal/analysis/analyzerutil/version.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage analyzerutil\n\nimport (\n\t\"go/ast\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// FileUsesGoVersion reports whether the specified file may use features of the\n// specified version of Go (e.g. \"go1.24\").\n//\n// It returns false when version information is not available,\n// such as for parsed files that are ignored by the type checker.\n//\n// Tip: we recommend using this check \"late\", just before calling\n// pass.Report, rather than \"early\" (when entering each ast.File, or\n// each candidate node of interest, during the traversal), because the\n// operation is not free, yet is not a highly selective filter: the\n// fraction of files that pass most version checks is high and\n// increases over time.\nfunc FileUsesGoVersion(pass *analysis.Pass, file *ast.File, version string) (_res bool) {\n\tfileVersion, ok := pass.TypesInfo.FileVersions[file]\n\tif !ok {\n\t\treturn false // be conservative in the absence of information (e.g. IgnoredFiles)\n\t}\n\n\t// Standard packages that are part of toolchain bootstrapping\n\t// are not considered to use a version of Go later than the\n\t// current bootstrap toolchain version.\n\t// The bootstrap rule does not cover tests,\n\t// and some tests (e.g. debug/elf/file_test.go) rely on this.\n\tpkgpath := pass.Pkg.Path()\n\tif packagepath.IsStdPackage(pkgpath) &&\n\t\tstdlib.IsBootstrapPackage(pkgpath) && // (excludes \"*_test\" external test packages)\n\t\t!strings.HasSuffix(pass.Fset.File(file.Pos()).Name(), \"_test.go\") { // (excludes all tests)\n\t\tfileVersion = stdlib.BootstrapVersion.String() // package must bootstrap\n\t}\n\n\treturn !versions.Before(fileVersion, version)\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/fix.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package driverutil defines implementation helper functions for\n// analysis drivers such as unitchecker, {single,multi}checker, and\n// analysistest.\npackage driverutil\n\n// This file defines the -fix logic common to unitchecker and\n// {single,multi}checker.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"maps\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/internal/astutil/free\"\n\t\"golang.org/x/tools/internal/diff\"\n)\n\n// FixAction abstracts a checker action (running one analyzer on one\n// package) for the purposes of applying its diagnostics' fixes.\ntype FixAction struct {\n\tName         string         // e.g. \"analyzer@package\"\n\tPkg          *types.Package // (for import removal)\n\tFiles        []*ast.File\n\tFileSet      *token.FileSet\n\tReadFileFunc ReadFileFunc\n\tDiagnostics  []analysis.Diagnostic\n}\n\n// ApplyFixes attempts to apply the first suggested fix associated\n// with each diagnostic reported by the specified actions.\n// All fixes must have been validated by [ValidateFixes].\n//\n// Each fix is treated as an independent change; fixes are merged in\n// an arbitrary deterministic order as if by a three-way diff tool\n// such as the UNIX diff3 command or 'git merge'. Any fix that cannot be\n// cleanly merged is discarded, in which case the final summary tells\n// the user to re-run the tool.\n// TODO(adonovan): make the checker tool re-run the analysis itself.\n//\n// When the same file is analyzed as a member of both a primary\n// package \"p\" and a test-augmented package \"p [p.test]\", there may be\n// duplicate diagnostics and fixes. One set of fixes will be applied\n// and the other will be discarded; but re-running the tool may then\n// show zero fixes, which may cause the confused user to wonder what\n// happened to the other ones.\n// TODO(adonovan): consider pre-filtering completely identical fixes.\n//\n// A common reason for overlapping fixes is duplicate additions of the\n// same import. The merge algorithm may often cleanly resolve such\n// fixes, coalescing identical edits, but the merge may sometimes be\n// confused by nearby changes.\n//\n// Even when merging succeeds, there is no guarantee that the\n// composition of the two fixes is semantically correct. Coalescing\n// identical edits is appropriate for imports, but not for, say,\n// increments to a counter variable; the correct resolution in that\n// case might be to increment it twice.\n//\n// Or consider two fixes that each delete the penultimate reference to\n// a local variable: each fix is sound individually, and they may be\n// textually distant from each other, but when both are applied, the\n// program is no longer valid because it has an unreferenced local\n// variable. (ApplyFixes solves the analogous problem for imports by\n// eliminating imports whose name is unreferenced in the remainder of\n// the fixed file.)\n//\n// Merging depends on both the order of fixes and they order of edits\n// within them. For example, if three fixes add import \"a\" twice and\n// import \"b\" once, the two imports of \"a\" may be combined if they\n// appear in order [a, a, b], or not if they appear as [a, b, a].\n// TODO(adonovan): investigate an algebraic approach to imports;\n// that is, for fixes to Go source files, convert changes within the\n// import(...) portion of the file into semantic edits, compose those\n// edits algebraically, then convert the result back to edits.\n//\n// applyFixes returns success if all fixes are valid, could be cleanly\n// merged, and the corresponding files were successfully updated.\n//\n// If printDiff (from the -diff flag) is set, instead of updating the\n// files it display the final patch composed of all the cleanly merged\n// fixes. (It is tempting to factor printDiff as just a variant of\n// writeFile that is provided the old and new content, but it's hard\n// to generate a good summary that way.)\n//\n// TODO(adonovan): handle file-system level aliases such as symbolic\n// links using robustio.FileID.\nfunc ApplyFixes(actions []FixAction, writeFile func(filename string, content []byte) error, printDiff, verbose bool) error {\n\tgenerated := make(map[*token.File]bool)\n\n\t// Select fixes to apply.\n\t//\n\t// If there are several for a given Diagnostic, choose the first.\n\t// Preserve the order of iteration, for determinism.\n\ttype fixact struct {\n\t\tfix *analysis.SuggestedFix\n\t\tact FixAction\n\t}\n\tvar fixes []*fixact\n\tfor _, act := range actions {\n\t\tfor _, file := range act.Files {\n\t\t\ttokFile := act.FileSet.File(file.FileStart)\n\t\t\t// Memoize, since there may be many actions\n\t\t\t// for the same package (list of files).\n\t\t\tif _, seen := generated[tokFile]; !seen {\n\t\t\t\tgenerated[tokFile] = ast.IsGenerated(file)\n\t\t\t}\n\t\t}\n\n\t\tfor _, diag := range act.Diagnostics {\n\t\t\tfor i := range diag.SuggestedFixes {\n\t\t\t\tfix := &diag.SuggestedFixes[i]\n\t\t\t\tif i == 0 {\n\t\t\t\t\tfixes = append(fixes, &fixact{fix, act})\n\t\t\t\t} else {\n\t\t\t\t\t// TODO(adonovan): abstract the logger.\n\t\t\t\t\tlog.Printf(\"%s: ignoring alternative fix %q\", act.Name, fix.Message)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Read file content on demand, from the virtual\n\t// file system that fed the analyzer (see #62292).\n\t//\n\t// This cache assumes that all successful reads for the same\n\t// file name return the same content.\n\t// (It is tempting to group fixes by package and do the\n\t// merge/apply/format steps one package at a time, but\n\t// packages are not disjoint, due to test variants, so this\n\t// would not really address the issue.)\n\tbaselineContent := make(map[string][]byte)\n\tgetBaseline := func(readFile ReadFileFunc, filename string) ([]byte, error) {\n\t\tcontent, ok := baselineContent[filename]\n\t\tif !ok {\n\t\t\tvar err error\n\t\t\tcontent, err = readFile(filename)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tbaselineContent[filename] = content\n\t\t}\n\t\treturn content, nil\n\t}\n\n\t// Apply each fix, updating the current state\n\t// only if the entire fix can be cleanly merged.\n\tvar (\n\t\taccumulatedEdits = make(map[string][]diff.Edit)\n\t\tfilePkgs         = make(map[string]*types.Package) // maps each file to an arbitrary package that includes it\n\n\t\tgoodFixes    = 0 // number of fixes cleanly applied\n\t\tskippedFixes = 0 // number of fixes skipped (because e.g. edits a generated file)\n\t)\nfixloop:\n\tfor _, fixact := range fixes {\n\t\t// Skip a fix if any of its edits touch a generated file.\n\t\tfor _, edit := range fixact.fix.TextEdits {\n\t\t\tfile := fixact.act.FileSet.File(edit.Pos)\n\t\t\tif generated[file] {\n\t\t\t\tskippedFixes++\n\t\t\t\tcontinue fixloop\n\t\t\t}\n\t\t}\n\n\t\t// Convert analysis.TextEdits to diff.Edits, grouped by file.\n\t\t// Precondition: a prior call to validateFix succeeded.\n\t\tfileEdits := make(map[string][]diff.Edit)\n\t\tfor _, edit := range fixact.fix.TextEdits {\n\t\t\tfile := fixact.act.FileSet.File(edit.Pos)\n\n\t\t\tfilePkgs[file.Name()] = fixact.act.Pkg\n\n\t\t\tbaseline, err := getBaseline(fixact.act.ReadFileFunc, file.Name())\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"skipping fix to file %s: %v\", file.Name(), err)\n\t\t\t\tcontinue fixloop\n\t\t\t}\n\n\t\t\t// We choose to treat size mismatch as a serious error,\n\t\t\t// as it indicates a concurrent write to at least one file,\n\t\t\t// and possibly others (consider a git checkout, for example).\n\t\t\tif file.Size() != len(baseline) {\n\t\t\t\treturn fmt.Errorf(\"concurrent file modification detected in file %s (size changed from %d -> %d bytes); aborting fix\",\n\t\t\t\t\tfile.Name(), file.Size(), len(baseline))\n\t\t\t}\n\n\t\t\tfileEdits[file.Name()] = append(fileEdits[file.Name()], diff.Edit{\n\t\t\t\tStart: file.Offset(edit.Pos),\n\t\t\t\tEnd:   file.Offset(edit.End),\n\t\t\t\tNew:   string(edit.NewText),\n\t\t\t})\n\t\t}\n\n\t\t// Apply each set of edits by merging atop\n\t\t// the previous accumulated state.\n\t\tafter := make(map[string][]diff.Edit)\n\t\tfor file, edits := range fileEdits {\n\t\t\tif prev := accumulatedEdits[file]; len(prev) > 0 {\n\t\t\t\tmerged, ok := diff.Merge(prev, edits)\n\t\t\t\tif !ok {\n\t\t\t\t\t// debugging\n\t\t\t\t\tif false {\n\t\t\t\t\t\tlog.Printf(\"%s: fix %s conflicts\", fixact.act.Name, fixact.fix.Message)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue fixloop // conflict\n\t\t\t\t}\n\t\t\t\tedits = merged\n\t\t\t}\n\t\t\tafter[file] = edits\n\t\t}\n\n\t\t// The entire fix applied cleanly; commit it.\n\t\tgoodFixes++\n\t\tmaps.Copy(accumulatedEdits, after)\n\t\t// debugging\n\t\tif false {\n\t\t\tlog.Printf(\"%s: fix %s applied\", fixact.act.Name, fixact.fix.Message)\n\t\t}\n\t}\n\tbadFixes := len(fixes) - goodFixes - skippedFixes // number of fixes that could not be applied\n\n\t// Show diff or update files to final state.\n\tvar files []string\n\tfor file := range accumulatedEdits {\n\t\tfiles = append(files, file)\n\t}\n\tsort.Strings(files) // for deterministic -diff\n\tvar filesUpdated, totalFiles int\n\tfor _, file := range files {\n\t\tedits := accumulatedEdits[file]\n\t\tif len(edits) == 0 {\n\t\t\tcontinue // the diffs annihilated (a miracle?)\n\t\t}\n\n\t\t// Apply accumulated fixes.\n\t\tbaseline := baselineContent[file] // (cache hit)\n\t\tfinal, err := diff.ApplyBytes(baseline, edits)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"internal error in diff.ApplyBytes: %v\", err)\n\t\t}\n\n\t\t// Attempt to format each file.\n\t\tif formatted, err := FormatSourceRemoveImports(filePkgs[file], final); err == nil {\n\t\t\tfinal = formatted\n\t\t}\n\n\t\tif printDiff {\n\t\t\t// Since we formatted the file, we need to recompute the diff.\n\t\t\tunified := diff.Unified(file+\" (old)\", file+\" (new)\", string(baseline), string(final))\n\t\t\t// TODO(adonovan): abstract the I/O.\n\t\t\tos.Stdout.WriteString(unified)\n\n\t\t} else {\n\t\t\t// write file\n\t\t\ttotalFiles++\n\t\t\tif err := writeFile(file, final); err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t\tcontinue // (causes ApplyFix to return an error)\n\t\t\t}\n\t\t\tfilesUpdated++\n\t\t}\n\t}\n\n\t// TODO(adonovan): consider returning a structured result that\n\t// maps each SuggestedFix to its status:\n\t// - invalid\n\t// - secondary, not selected\n\t// - applied\n\t// - had conflicts.\n\t// and a mapping from each affected file to:\n\t// - its final/original content pair, and\n\t// - whether formatting was successful.\n\t// Then file writes and the UI can be applied by the caller\n\t// in whatever form they like.\n\n\t// If victory was incomplete, report an error that indicates partial progress.\n\t//\n\t// badFixes > 0 indicates that we decided not to attempt some\n\t// fixes due to conflicts or failure to read the source; still\n\t// it's a relatively benign situation since the user can\n\t// re-run the tool, and we may still make progress.\n\t//\n\t// filesUpdated < totalFiles indicates that some file updates\n\t// failed. This should be rare, but is a serious error as it\n\t// may apply half a fix, or leave the files in a bad state.\n\t//\n\t// These numbers are potentially misleading:\n\t// The denominator includes duplicate conflicting fixes due to\n\t// common files in packages \"p\" and \"p [p.test]\", which may\n\t// have been fixed and won't appear in the re-run.\n\t// TODO(adonovan): eliminate identical fixes as an initial\n\t// filtering step.\n\t//\n\t// TODO(adonovan): should we log that n files were updated in case of total victory?\n\tif badFixes > 0 || filesUpdated < totalFiles {\n\t\tif printDiff {\n\t\t\treturn fmt.Errorf(\"%d of %s skipped (e.g. due to conflicts)\",\n\t\t\t\tbadFixes,\n\t\t\t\tplural(len(fixes), \"fix\", \"fixes\"))\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"applied %d of %s; %s updated. (Re-run the command to apply more.)\",\n\t\t\t\tgoodFixes,\n\t\t\t\tplural(len(fixes), \"fix\", \"fixes\"),\n\t\t\t\tplural(filesUpdated, \"file\", \"files\"))\n\t\t}\n\t}\n\n\tif verbose {\n\t\tif skippedFixes > 0 {\n\t\t\tlog.Printf(\"skipped %s that would edit generated files\",\n\t\t\t\tplural(skippedFixes, \"fix\", \"fixes\"))\n\t\t}\n\t\tlog.Printf(\"applied %s, updated %s\",\n\t\t\tplural(len(fixes), \"fix\", \"fixes\"),\n\t\t\tplural(filesUpdated, \"file\", \"files\"))\n\t}\n\n\treturn nil\n}\n\n// FormatSourceRemoveImports is a variant of [format.Source] that\n// removes imports that became redundant when fixes were applied.\n//\n// Import removal is necessarily heuristic since we do not have type\n// information for the fixed file and thus cannot accurately tell\n// whether k is among the free names of T{k: 0}, which requires\n// knowledge of whether T is a struct type.\n//\n// Like [imports.Process] (the core of x/tools/cmd/goimports), it also\n// merges import decls.\nfunc FormatSourceRemoveImports(pkg *types.Package, src []byte) ([]byte, error) {\n\t// This function was reduced from the \"strict entire file\"\n\t// path through [format.Source].\n\n\tfset := token.NewFileSet()\n\tfile, err := parser.ParseFile(fset, \"fixed.go\", src, parser.ParseComments|parser.SkipObjectResolution)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tast.SortImports(fset, file)\n\n\tremoveUnneededImports(fset, pkg, file)\n\n\t// TODO(adonovan): to generate cleaner edits when adding an import,\n\t// consider adding a call to imports.mergeImports; however, it does\n\t// cause comments to migrate.\n\n\t// printerNormalizeNumbers means to canonicalize number literal prefixes\n\t// and exponents while printing. See https://golang.org/doc/go1.13#gofmt.\n\t//\n\t// This value is defined in go/printer specifically for go/format and cmd/gofmt.\n\tconst printerNormalizeNumbers = 1 << 30\n\tcfg := &printer.Config{\n\t\tMode:     printer.UseSpaces | printer.TabIndent | printerNormalizeNumbers,\n\t\tTabwidth: 8,\n\t}\n\tvar buf bytes.Buffer\n\tif err := cfg.Fprint(&buf, fset, file); err != nil {\n\t\treturn nil, err\n\t}\n\treturn buf.Bytes(), nil\n}\n\n// removeUnneededImports removes import specs that are not referenced\n// within the fixed file. It uses [free.Names] to heuristically\n// approximate the set of imported names needed by the body of the\n// file based only on syntax.\n//\n// pkg provides type information about the unmodified package, in\n// particular the name that would implicitly be declared by a\n// non-renaming import of a given existing dependency.\nfunc removeUnneededImports(fset *token.FileSet, pkg *types.Package, file *ast.File) {\n\t// Map each existing dependency and its transitive dependencies to its default import name.\n\t// (We'll need this to interpret non-renaming imports.)\n\tpackageNames := make(map[string]string)\n\tvar visit func(pkg *types.Package)\n\tvisit = func(pkg *types.Package) {\n\t\tif packageNames[pkg.Path()] == \"\" {\n\t\t\tpackageNames[pkg.Path()] = pkg.Name()\n\t\t\tfor _, imp := range pkg.Imports() {\n\t\t\t\tvisit(imp)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, imp := range pkg.Imports() {\n\t\tvisit(imp)\n\t}\n\n\t// Compute the set of free names of the file,\n\t// ignoring its import decls.\n\tfreenames := make(map[string]bool)\n\tfor _, decl := range file.Decls {\n\t\tif decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {\n\t\t\tcontinue // skip import\n\t\t}\n\n\t\t// TODO(adonovan): we could do better than includeComplitIdents=false\n\t\t// since we have type information about the unmodified package,\n\t\t// which is a good source of heuristics.\n\t\tconst includeComplitIdents = false\n\t\tmaps.Copy(freenames, free.Names(decl, includeComplitIdents))\n\t}\n\n\t// Check whether each import's declared name is free (referenced) by the file.\n\tvar deletions []func()\n\tfor _, spec := range file.Imports {\n\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\tif err != nil {\n\t\t\tcontinue //  malformed import; ignore\n\t\t}\n\t\texplicit := \"\" // explicit PkgName, if any\n\t\tif spec.Name != nil {\n\t\t\texplicit = spec.Name.Name\n\t\t}\n\t\tname := explicit // effective PkgName\n\t\tif name == \"\" {\n\t\t\t// Non-renaming import: use package's default name.\n\t\t\tname = packageNames[path]\n\t\t}\n\t\tswitch name {\n\t\tcase \"\":\n\t\t\tcontinue // assume it's a new import, and we didn't find its default name while searching the import graph\n\t\tcase \".\":\n\t\t\tcontinue // dot imports are tricky\n\t\tcase \"_\":\n\t\t\tcontinue // keep blank imports\n\t\t}\n\t\tif !freenames[name] {\n\t\t\t// Import's effective name is not free in (not used by) the file.\n\t\t\t// Enqueue it for deletion after the loop.\n\t\t\tdeletions = append(deletions, func() {\n\t\t\t\tastutil.DeleteNamedImport(fset, file, explicit, path)\n\t\t\t})\n\t\t}\n\t}\n\n\t// Apply the deletions.\n\tfor _, del := range deletions {\n\t\tdel()\n\t}\n}\n\n// plural returns \"n nouns\", selecting the plural form as approriate.\nfunc plural(n int, singular, plural string) string {\n\tif n == 1 {\n\t\treturn \"1 \" + singular\n\t} else {\n\t\treturn fmt.Sprintf(\"%d %s\", n, plural)\n\t}\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/print.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage driverutil\n\n// This file defined output helpers common to all drivers.\n\nimport (\n\t\"cmp\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// TODO(adonovan): don't accept an io.Writer if we don't report errors.\n// Either accept a bytes.Buffer (infallible), or return a []byte.\n\n// PrintPlain prints a diagnostic in plain text form.\n// If contextLines is nonnegative, it also prints the\n// offending line plus this many lines of context.\nfunc PrintPlain(out io.Writer, fset *token.FileSet, contextLines int, diag analysis.Diagnostic) {\n\tprint := func(pos, end token.Pos, message string) {\n\t\tposn := fset.Position(pos)\n\t\tfmt.Fprintf(out, \"%s: %s\\n\", posn, message)\n\n\t\t// show offending line plus N lines of context.\n\t\tif contextLines >= 0 {\n\t\t\tend := fset.Position(end)\n\t\t\tif !end.IsValid() {\n\t\t\t\tend = posn\n\t\t\t}\n\t\t\t// TODO(adonovan): highlight the portion of the line indicated\n\t\t\t// by pos...end using ASCII art, terminal colors, etc?\n\t\t\tdata, _ := os.ReadFile(posn.Filename)\n\t\t\tlines := strings.Split(string(data), \"\\n\")\n\t\t\tfor i := posn.Line - contextLines; i <= end.Line+contextLines; i++ {\n\t\t\t\tif 1 <= i && i <= len(lines) {\n\t\t\t\t\tfmt.Fprintf(out, \"%d\\t%s\\n\", i, lines[i-1])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprint(diag.Pos, diag.End, diag.Message)\n\tfor _, rel := range diag.Related {\n\t\tprint(rel.Pos, rel.End, \"\\t\"+rel.Message)\n\t}\n}\n\n// A JSONTree is a mapping from package ID to analysis name to result.\n// Each result is either a jsonError or a list of JSONDiagnostic.\ntype JSONTree map[string]map[string]any\n\n// A TextEdit describes the replacement of a portion of a file.\n// Start and End are zero-based half-open indices into the original byte\n// sequence of the file, and New is the new text.\ntype JSONTextEdit struct {\n\tFilename string `json:\"filename\"`\n\tStart    int    `json:\"start\"`\n\tEnd      int    `json:\"end\"`\n\tNew      string `json:\"new\"`\n}\n\n// A JSONSuggestedFix describes an edit that should be applied as a whole or not\n// at all. It might contain multiple TextEdits/text_edits if the SuggestedFix\n// consists of multiple non-contiguous edits.\ntype JSONSuggestedFix struct {\n\tMessage string         `json:\"message\"`\n\tEdits   []JSONTextEdit `json:\"edits\"`\n}\n\n// A JSONDiagnostic describes the JSON schema of an analysis.Diagnostic.\ntype JSONDiagnostic struct {\n\tCategory       string                   `json:\"category,omitempty\"`\n\tPosn           string                   `json:\"posn\"` // e.g. \"file.go:line:column\"\n\tEnd            string                   `json:\"end\"`  // (ditto)\n\tMessage        string                   `json:\"message\"`\n\tSuggestedFixes []JSONSuggestedFix       `json:\"suggested_fixes,omitempty\"`\n\tRelated        []JSONRelatedInformation `json:\"related,omitempty\"`\n}\n\n// A JSONRelated describes a secondary position and message related to\n// a primary diagnostic.\ntype JSONRelatedInformation struct {\n\tPosn    string `json:\"posn\"` // e.g. \"file.go:line:column\"\n\tEnd     string `json:\"end\"`  // (ditto)\n\tMessage string `json:\"message\"`\n}\n\n// Add adds the result of analysis 'name' on package 'id'.\n// The result is either a list of diagnostics or an error.\nfunc (tree JSONTree) Add(fset *token.FileSet, id, name string, diags []analysis.Diagnostic, err error) {\n\tvar v any\n\tif err != nil {\n\t\ttype jsonError struct {\n\t\t\tErr string `json:\"error\"`\n\t\t}\n\t\tv = jsonError{err.Error()}\n\t} else if len(diags) > 0 {\n\t\tdiagnostics := make([]JSONDiagnostic, 0, len(diags))\n\t\tfor _, f := range diags {\n\t\t\tvar fixes []JSONSuggestedFix\n\t\t\tfor _, fix := range f.SuggestedFixes {\n\t\t\t\tvar edits []JSONTextEdit\n\t\t\t\tfor _, edit := range fix.TextEdits {\n\t\t\t\t\tedits = append(edits, JSONTextEdit{\n\t\t\t\t\t\tFilename: fset.Position(edit.Pos).Filename,\n\t\t\t\t\t\tStart:    fset.Position(edit.Pos).Offset,\n\t\t\t\t\t\tEnd:      fset.Position(edit.End).Offset,\n\t\t\t\t\t\tNew:      string(edit.NewText),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tfixes = append(fixes, JSONSuggestedFix{\n\t\t\t\t\tMessage: fix.Message,\n\t\t\t\t\tEdits:   edits,\n\t\t\t\t})\n\t\t\t}\n\t\t\tvar related []JSONRelatedInformation\n\t\t\tfor _, r := range f.Related {\n\t\t\t\trelated = append(related, JSONRelatedInformation{\n\t\t\t\t\tPosn:    fset.Position(r.Pos).String(),\n\t\t\t\t\tEnd:     fset.Position(cmp.Or(r.End, r.Pos)).String(),\n\t\t\t\t\tMessage: r.Message,\n\t\t\t\t})\n\t\t\t}\n\t\t\tjdiag := JSONDiagnostic{\n\t\t\t\tCategory:       f.Category,\n\t\t\t\tPosn:           fset.Position(f.Pos).String(),\n\t\t\t\tEnd:            fset.Position(cmp.Or(f.End, f.Pos)).String(),\n\t\t\t\tMessage:        f.Message,\n\t\t\t\tSuggestedFixes: fixes,\n\t\t\t\tRelated:        related,\n\t\t\t}\n\t\t\tdiagnostics = append(diagnostics, jdiag)\n\t\t}\n\t\tv = diagnostics\n\t}\n\tif v != nil {\n\t\tm, ok := tree[id]\n\t\tif !ok {\n\t\t\tm = make(map[string]any)\n\t\t\ttree[id] = m\n\t\t}\n\t\tm[name] = v\n\t}\n}\n\nfunc (tree JSONTree) Print(out io.Writer) error {\n\tdata, err := json.MarshalIndent(tree, \"\", \"\\t\")\n\tif err != nil {\n\t\tlog.Panicf(\"internal error: JSON marshaling failed: %v\", err)\n\t}\n\t_, err = fmt.Fprintf(out, \"%s\\n\", data)\n\treturn err\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/readfile.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage driverutil\n\n// This file defines helpers for implementing [analysis.Pass.ReadFile].\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// A ReadFileFunc is a function that returns the\n// contents of a file, such as [os.ReadFile].\ntype ReadFileFunc = func(filename string) ([]byte, error)\n\n// CheckedReadFile returns a wrapper around a Pass.ReadFile\n// function that performs the appropriate checks.\nfunc CheckedReadFile(pass *analysis.Pass, readFile ReadFileFunc) ReadFileFunc {\n\treturn func(filename string) ([]byte, error) {\n\t\tif err := CheckReadable(pass, filename); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn readFile(filename)\n\t}\n}\n\n// CheckReadable enforces the access policy defined by the ReadFile field of [analysis.Pass].\nfunc CheckReadable(pass *analysis.Pass, filename string) error {\n\tif slices.Contains(pass.OtherFiles, filename) ||\n\t\tslices.Contains(pass.IgnoredFiles, filename) {\n\t\treturn nil\n\t}\n\tfor _, f := range pass.Files {\n\t\tif pass.Fset.File(f.FileStart).Name() == filename {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files\", filename)\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/url.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage driverutil\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// ResolveURL resolves the URL field for a Diagnostic from an Analyzer\n// and returns the URL. See Diagnostic.URL for details.\nfunc ResolveURL(a *analysis.Analyzer, d analysis.Diagnostic) (string, error) {\n\tif d.URL == \"\" && d.Category == \"\" && a.URL == \"\" {\n\t\treturn \"\", nil // do nothing\n\t}\n\traw := d.URL\n\tif d.URL == \"\" && d.Category != \"\" {\n\t\traw = \"#\" + d.Category\n\t}\n\tu, err := url.Parse(raw)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid Diagnostic.URL %q: %s\", raw, err)\n\t}\n\tbase, err := url.Parse(a.URL)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid Analyzer.URL %q: %s\", a.URL, err)\n\t}\n\treturn base.ResolveReference(u).String(), nil\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/url_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage driverutil_test\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n)\n\nfunc TestResolveURLs(t *testing.T) {\n\t// TestResolveURL test the 12 different combinations for how URLs can be resolved\n\t// when Analyzer.URL are Diagnostic.Category are empty or non-empty, and when\n\t// Diagnostic.URL is empty, absolute or relative.\n\n\taURL := &analysis.Analyzer{URL: \"https://analyzer.example\"}\n\tnoURL := &analysis.Analyzer{URL: \"\"}\n\ttests := []struct {\n\t\tanalyzer   *analysis.Analyzer\n\t\tdiagnostic analysis.Diagnostic\n\t\twant       string\n\t}{\n\t\t{noURL, analysis.Diagnostic{Category: \"\", URL: \"\"}, \"\"},\n\t\t{noURL, analysis.Diagnostic{Category: \"\", URL: \"#relative\"}, \"#relative\"},\n\t\t{noURL, analysis.Diagnostic{Category: \"\", URL: \"https://absolute.diagnostic\"}, \"https://absolute.diagnostic\"},\n\t\t{noURL, analysis.Diagnostic{Category: \"category\", URL: \"\"}, \"#category\"},\n\t\t{noURL, analysis.Diagnostic{Category: \"category\", URL: \"#relative\"}, \"#relative\"},\n\t\t{noURL, analysis.Diagnostic{Category: \"category\", URL: \"https://absolute.diagnostic\"}, \"https://absolute.diagnostic\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"\", URL: \"\"}, \"https://analyzer.example\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"\", URL: \"#relative\"}, \"https://analyzer.example#relative\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"\", URL: \"https://absolute.diagnostic\"}, \"https://absolute.diagnostic\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"category\", URL: \"\"}, \"https://analyzer.example#category\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"category\", URL: \"#relative\"}, \"https://analyzer.example#relative\"},\n\t\t{aURL, analysis.Diagnostic{Category: \"category\", URL: \"https://absolute.diagnostic\"}, \"https://absolute.diagnostic\"},\n\t}\n\tfor _, c := range tests {\n\t\tgot, err := driverutil.ResolveURL(c.analyzer, c.diagnostic)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unexpected error from ResolveURL %s\", err)\n\t\t} else if got != c.want {\n\t\t\tt.Errorf(\"ResolveURL(%q,%v)=%q. want %s\", c.analyzer.URL, c.diagnostic, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestResolveURLErrors(t *testing.T) {\n\ttests := []struct {\n\t\tanalyzer   *analysis.Analyzer\n\t\tdiagnostic analysis.Diagnostic\n\t\twant       string\n\t}{\n\t\t{&analysis.Analyzer{URL: \":not a url\"}, analysis.Diagnostic{Category: \"\", URL: \"#relative\"}, \"invalid Analyzer.URL\"},\n\t\t{&analysis.Analyzer{URL: \"https://analyzer.example\"}, analysis.Diagnostic{Category: \"\", URL: \":not a URL\"}, \"invalid Diagnostic.URL\"},\n\t}\n\tfor _, c := range tests {\n\t\t_, err := driverutil.ResolveURL(c.analyzer, c.diagnostic)\n\t\tif got := fmt.Sprint(err); !strings.HasPrefix(got, c.want) {\n\t\t\tt.Errorf(\"ResolveURL(%q, %q) expected an error starting with %q. got %q\", c.analyzer.URL, c.diagnostic.URL, c.want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/analysis/driverutil/validatefix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage driverutil\n\n// This file defines the validation of SuggestedFixes.\n\nimport (\n\t\"cmp\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\n// ValidateFixes validates the set of fixes for a single diagnostic.\n// Any error indicates a bug in the originating analyzer.\n//\n// It updates fixes so that fixes[*].End.IsValid().\n//\n// It may be used as part of an analysis driver implementation.\nfunc ValidateFixes(fset *token.FileSet, a *analysis.Analyzer, fixes []analysis.SuggestedFix) error {\n\tfixMessages := make(map[string]bool)\n\tfor i := range fixes {\n\t\tfix := &fixes[i]\n\t\tif fixMessages[fix.Message] {\n\t\t\treturn fmt.Errorf(\"analyzer %q suggests two fixes with same Message (%s)\", a.Name, fix.Message)\n\t\t}\n\t\tfixMessages[fix.Message] = true\n\t\tif err := validateFix(fset, fix); err != nil {\n\t\t\treturn fmt.Errorf(\"analyzer %q suggests invalid fix (%s): %v\", a.Name, fix.Message, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// validateFix validates a single fix.\n// Any error indicates a bug in the originating analyzer.\n//\n// It updates fix so that fix.End.IsValid().\nfunc validateFix(fset *token.FileSet, fix *analysis.SuggestedFix) error {\n\n\t// Stably sort edits by Pos. This ordering puts insertions\n\t// (end = start) before deletions (end > start) at the same\n\t// point, but uses a stable sort to preserve the order of\n\t// multiple insertions at the same point.\n\tslices.SortStableFunc(fix.TextEdits, func(x, y analysis.TextEdit) int {\n\t\tif sign := cmp.Compare(x.Pos, y.Pos); sign != 0 {\n\t\t\treturn sign\n\t\t}\n\t\treturn cmp.Compare(x.End, y.End)\n\t})\n\n\tvar prev *analysis.TextEdit\n\tfor i := range fix.TextEdits {\n\t\tedit := &fix.TextEdits[i]\n\n\t\t// Validate edit individually.\n\t\tstart := edit.Pos\n\t\tfile := fset.File(start)\n\t\tif file == nil {\n\t\t\treturn fmt.Errorf(\"no token.File for TextEdit.Pos (%v)\", edit.Pos)\n\t\t}\n\t\tfileEnd := token.Pos(file.Base() + file.Size())\n\t\tif end := edit.End; end.IsValid() {\n\t\t\tif end < start {\n\t\t\t\treturn fmt.Errorf(\"TextEdit.Pos (%v) > TextEdit.End (%v)\", edit.Pos, edit.End)\n\t\t\t}\n\t\t\tendFile := fset.File(end)\n\t\t\tif endFile != file && end < fileEnd+10 {\n\t\t\t\t// Relax the checks below in the special case when the end position\n\t\t\t\t// is only slightly beyond EOF, as happens when End is computed\n\t\t\t\t// (as in ast.{Struct,Interface}Type) rather than based on\n\t\t\t\t// actual token positions. In such cases, truncate end to EOF.\n\t\t\t\t//\n\t\t\t\t// This is a workaround for #71659; see:\n\t\t\t\t// https://github.com/golang/go/issues/71659#issuecomment-2651606031\n\t\t\t\t// A better fix would be more faithful recording of token\n\t\t\t\t// positions (or their absence) in the AST.\n\t\t\t\tedit.End = fileEnd\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif endFile == nil {\n\t\t\t\treturn fmt.Errorf(\"no token.File for TextEdit.End (%v; File(start).FileEnd is %d)\", end, file.Base()+file.Size())\n\t\t\t}\n\t\t\tif endFile != file {\n\t\t\t\treturn fmt.Errorf(\"edit #%d spans files (%v and %v)\",\n\t\t\t\t\ti, file.Position(edit.Pos), endFile.Position(edit.End))\n\t\t\t}\n\t\t} else {\n\t\t\tedit.End = start // update the SuggestedFix\n\t\t}\n\t\tif eof := fileEnd; edit.End > eof {\n\t\t\treturn fmt.Errorf(\"end is (%v) beyond end of file (%v)\", edit.End, eof)\n\t\t}\n\n\t\t// Validate the sequence of edits:\n\t\t// properly ordered, no overlapping deletions\n\t\tif prev != nil && edit.Pos < prev.End {\n\t\t\txpos := fset.Position(prev.Pos)\n\t\t\txend := fset.Position(prev.End)\n\t\t\typos := fset.Position(edit.Pos)\n\t\t\tyend := fset.Position(edit.End)\n\t\t\treturn fmt.Errorf(\"overlapping edits to %s (%d:%d-%d:%d and %d:%d-%d:%d)\",\n\t\t\t\txpos.Filename,\n\t\t\t\txpos.Line, xpos.Column,\n\t\t\t\txend.Line, xend.Column,\n\t\t\t\typos.Line, ypos.Column,\n\t\t\t\tyend.Line, yend.Column,\n\t\t\t)\n\t\t}\n\t\tprev = edit\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/analysis/generated/generated.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package generated defines an analyzer whose result makes it\n// convenient to skip diagnostics within generated files.\npackage generated\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName:       \"generated\",\n\tDoc:        \"detect which Go files are generated\",\n\tURL:        \"https://pkg.go.dev/golang.org/x/tools/internal/analysis/generated\",\n\tResultType: reflect.TypeFor[*Result](),\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tset := make(map[*token.File]bool)\n\t\tfor _, file := range pass.Files {\n\t\t\tif ast.IsGenerated(file) {\n\t\t\t\tset[pass.Fset.File(file.FileStart)] = true\n\t\t\t}\n\t\t}\n\t\treturn &Result{fset: pass.Fset, generatedFiles: set}, nil\n\t},\n}\n\ntype Result struct {\n\tfset           *token.FileSet\n\tgeneratedFiles map[*token.File]bool\n}\n\n// IsGenerated reports whether the position is within a generated file.\nfunc (r *Result) IsGenerated(pos token.Pos) bool {\n\treturn r.generatedFiles[r.fset.File(pos)]\n}\n"
  },
  {
    "path": "internal/analysis/typeindex/typeindex.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typeindex defines an analyzer that provides a\n// [golang.org/x/tools/internal/typesinternal/typeindex.Index].\n//\n// Like [golang.org/x/tools/go/analysis/passes/inspect], it is\n// intended to be used as a helper by other analyzers; it reports no\n// diagnostics of its own.\npackage typeindex\n\nimport (\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/passes/inspect\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"typeindex\",\n\tDoc:  \"indexes of type information for later passes\",\n\tURL:  \"https://pkg.go.dev/golang.org/x/tools/internal/analysis/typeindex\",\n\tRun: func(pass *analysis.Pass) (any, error) {\n\t\tinspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)\n\t\treturn typeindex.New(inspect, pass.Pkg, pass.TypesInfo), nil\n\t},\n\tRunDespiteErrors: true,\n\tRequires:         []*analysis.Analyzer{inspect.Analyzer},\n\tResultType:       reflect.TypeFor[*typeindex.Index](),\n}\n"
  },
  {
    "path": "internal/astutil/clone.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"go/ast\"\n\t\"reflect\"\n)\n\n// CloneNode returns a deep copy of a Node.\n// It omits pointers to ast.{Scope,Object} variables.\nfunc CloneNode[T ast.Node](n T) T {\n\treturn cloneNode(n).(T)\n}\n\nfunc cloneNode(n ast.Node) ast.Node {\n\tvar clone func(x reflect.Value) reflect.Value\n\tset := func(dst, src reflect.Value) {\n\t\tsrc = clone(src)\n\t\tif src.IsValid() {\n\t\t\tdst.Set(src)\n\t\t}\n\t}\n\tclone = func(x reflect.Value) reflect.Value {\n\t\tswitch x.Kind() {\n\t\tcase reflect.Pointer:\n\t\t\tif x.IsNil() {\n\t\t\t\treturn x\n\t\t\t}\n\t\t\t// Skip fields of types potentially involved in cycles.\n\t\t\tswitch x.Interface().(type) {\n\t\t\tcase *ast.Object, *ast.Scope:\n\t\t\t\treturn reflect.Zero(x.Type())\n\t\t\t}\n\t\t\ty := reflect.New(x.Type().Elem())\n\t\t\tset(y.Elem(), x.Elem())\n\t\t\treturn y\n\n\t\tcase reflect.Struct:\n\t\t\ty := reflect.New(x.Type()).Elem()\n\t\t\tfor i := 0; i < x.Type().NumField(); i++ {\n\t\t\t\tset(y.Field(i), x.Field(i))\n\t\t\t}\n\t\t\treturn y\n\n\t\tcase reflect.Slice:\n\t\t\tif x.IsNil() {\n\t\t\t\treturn x\n\t\t\t}\n\t\t\ty := reflect.MakeSlice(x.Type(), x.Len(), x.Cap())\n\t\t\tfor i := 0; i < x.Len(); i++ {\n\t\t\t\tset(y.Index(i), x.Index(i))\n\t\t\t}\n\t\t\treturn y\n\n\t\tcase reflect.Interface:\n\t\t\ty := reflect.New(x.Type()).Elem()\n\t\t\tset(y, x.Elem())\n\t\t\treturn y\n\n\t\tcase reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer:\n\t\t\tpanic(x) // unreachable in AST\n\n\t\tdefault:\n\t\t\treturn x // bool, string, number\n\t\t}\n\t}\n\treturn clone(reflect.ValueOf(n)).Interface().(ast.Node)\n}\n"
  },
  {
    "path": "internal/astutil/comment.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"iter\"\n\t\"strings\"\n)\n\n// Deprecation returns the paragraph of the doc comment that starts with the\n// conventional \"Deprecation: \" marker, as defined by\n// https://go.dev/wiki/Deprecated, or \"\" if the documented symbol is not\n// deprecated.\nfunc Deprecation(doc *ast.CommentGroup) string {\n\tfor p := range strings.SplitSeq(doc.Text(), \"\\n\\n\") {\n\t\t// There is still some ambiguity for deprecation message. This function\n\t\t// only returns the paragraph introduced by \"Deprecated: \". More\n\t\t// information related to the deprecation may follow in additional\n\t\t// paragraphs, but the deprecation message should be able to stand on\n\t\t// its own. See golang/go#38743.\n\t\tif strings.HasPrefix(p, \"Deprecated: \") {\n\t\t\treturn p\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// -- plundered from the future (CL 605517, issue #68021) --\n\n// TODO(adonovan): replace with ast.Directive in go1.26 (#68021).\n// Beware of our local mods to handle analysistest\n// \"want\" comments on the same line.\n\n// A directive is a comment line with special meaning to the Go\n// toolchain or another tool. It has the form:\n//\n//\t//tool:name args\n//\n// The \"tool:\" portion is missing for the three directives named\n// line, extern, and export.\n//\n// See https://go.dev/doc/comment#Syntax for details of Go comment\n// syntax and https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives\n// for details of directives used by the Go compiler.\ntype Directive struct {\n\tPos  token.Pos // of preceding \"//\"\n\tTool string\n\tName string\n\tArgs string // may contain internal spaces\n}\n\n// isDirective reports whether c is a comment directive.\n// This code is also in go/printer.\nfunc isDirective(c string) bool {\n\t// \"//line \" is a line directive.\n\t// \"//extern \" is for gccgo.\n\t// \"//export \" is for cgo.\n\t// (The // has been removed.)\n\tif strings.HasPrefix(c, \"line \") || strings.HasPrefix(c, \"extern \") || strings.HasPrefix(c, \"export \") {\n\t\treturn true\n\t}\n\n\t// \"//[a-z0-9]+:[a-z0-9]\"\n\t// (The // has been removed.)\n\tcolon := strings.Index(c, \":\")\n\tif colon <= 0 || colon+1 >= len(c) {\n\t\treturn false\n\t}\n\tfor i := 0; i <= colon+1; i++ {\n\t\tif i == colon {\n\t\t\tcontinue\n\t\t}\n\t\tb := c[i]\n\t\tif !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Directives returns the directives within the comment.\nfunc Directives(g *ast.CommentGroup) (res []*Directive) {\n\tif g != nil {\n\t\t// Avoid (*ast.CommentGroup).Text() as it swallows directives.\n\t\tfor _, c := range g.List {\n\t\t\tif len(c.Text) > 2 &&\n\t\t\t\tc.Text[1] == '/' &&\n\t\t\t\tc.Text[2] != ' ' &&\n\t\t\t\tisDirective(c.Text[2:]) {\n\n\t\t\t\ttool, nameargs, ok := strings.Cut(c.Text[2:], \":\")\n\t\t\t\tif !ok {\n\t\t\t\t\t// Must be one of {line,extern,export}.\n\t\t\t\t\ttool, nameargs = \"\", tool\n\t\t\t\t}\n\t\t\t\tname, args, _ := strings.Cut(nameargs, \" \") // tab??\n\t\t\t\t// Permit an additional line comment after the args, chiefly to support\n\t\t\t\t// [golang.org/x/tools/go/analysis/analysistest].\n\t\t\t\targs, _, _ = strings.Cut(args, \"//\")\n\t\t\t\tres = append(res, &Directive{\n\t\t\t\t\tPos:  c.Slash,\n\t\t\t\t\tTool: tool,\n\t\t\t\t\tName: name,\n\t\t\t\t\tArgs: strings.TrimSpace(args),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// Comments returns an iterator over the comments overlapping the specified interval.\nfunc Comments(file *ast.File, start, end token.Pos) iter.Seq[*ast.Comment] {\n\t// TODO(adonovan): optimize use binary O(log n) instead of linear O(n) search.\n\treturn func(yield func(*ast.Comment) bool) {\n\t\tfor _, cg := range file.Comments {\n\t\t\tfor _, co := range cg.List {\n\t\t\t\tif co.Pos() > end {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif co.End() < start {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif !yield(co) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/comment_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nfunc TestComments(t *testing.T) {\n\tsrc := `\npackage main\n\n// A\nfunc fn() { }`\n\tvar fset token.FileSet\n\tf, err := parser.ParseFile(&fset, \"\", []byte(src), parser.ParseComments|parser.AllErrors)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcommentA := f.Comments[0].List[0]\n\tcommentAMidPos := (commentA.Pos() + commentA.End()) / 2\n\n\twant := []*ast.Comment{commentA}\n\ttestCases := []struct {\n\t\tname       string\n\t\tstart, end token.Pos\n\t\twant       []*ast.Comment\n\t}{\n\t\t{name: \"comment totally overlaps with given interval\", start: f.Pos(), end: f.End(), want: want},\n\t\t{name: \"interval from file start to mid of comment A\", start: f.Pos(), end: commentAMidPos, want: want},\n\t\t{name: \"interval from mid of comment A to file end\", start: commentAMidPos, end: commentA.End(), want: want},\n\t\t{name: \"interval from start of comment A to mid of comment A\", start: commentA.Pos(), end: commentAMidPos, want: want},\n\t\t{name: \"interval from mid of comment A to comment A end\", start: commentAMidPos, end: commentA.End(), want: want},\n\t\t{name: \"interval at the start of comment A\", start: commentA.Pos(), end: commentA.Pos(), want: want},\n\t\t{name: \"interval at the end of comment A\", start: commentA.End(), end: commentA.End(), want: want},\n\t\t{name: \"interval from file start to the front of comment A start\", start: f.Pos(), end: commentA.Pos() - 1, want: nil},\n\t\t{name: \"interval from the position after end of comment A to file end\", start: commentA.End() + 1, end: f.End(), want: nil},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tvar got []*ast.Comment\n\t\t\tfor co := range astutil.Comments(f, tc.start, tc.end) {\n\t\t\t\tgot = append(got, co)\n\t\t\t}\n\t\t\tif !slices.Equal(got, tc.want) {\n\t\t\t\tt.Errorf(\"%s: got %v, want %v\", tc.name, got, tc.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/equal.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"reflect\"\n)\n\n// Equal reports whether two nodes are structurally equal,\n// ignoring fields of type [token.Pos], [ast.Object],\n// and [ast.Scope], and comments.\n//\n// The operands x and y may be nil.\n// A nil slice is not equal to an empty slice.\n//\n// The provided function determines whether two identifiers\n// should be considered identical.\nfunc Equal(x, y ast.Node, identical func(x, y *ast.Ident) bool) bool {\n\tif x == nil || y == nil {\n\t\treturn x == y\n\t}\n\treturn equal(reflect.ValueOf(x), reflect.ValueOf(y), identical)\n}\n\n// EqualSyntax reports whether x and y are equal.\n// Identifiers are considered equal if they are spelled the same.\n// Comments are ignored.\nfunc EqualSyntax(x, y ast.Expr) bool {\n\tsameName := func(x, y *ast.Ident) bool { return x.Name == y.Name }\n\treturn Equal(x, y, sameName)\n}\n\nfunc equal(x, y reflect.Value, identical func(x, y *ast.Ident) bool) bool {\n\t// Ensure types are the same\n\tif x.Type() != y.Type() {\n\t\treturn false\n\t}\n\tswitch x.Kind() {\n\tcase reflect.Pointer:\n\t\tif x.IsNil() || y.IsNil() {\n\t\t\treturn x.IsNil() == y.IsNil()\n\t\t}\n\t\tswitch t := x.Interface().(type) {\n\t\t// Skip fields of types potentially involved in cycles.\n\t\tcase *ast.Object, *ast.Scope, *ast.CommentGroup:\n\t\t\treturn true\n\t\tcase *ast.Ident:\n\t\t\treturn identical(t, y.Interface().(*ast.Ident))\n\t\tdefault:\n\t\t\treturn equal(x.Elem(), y.Elem(), identical)\n\t\t}\n\n\tcase reflect.Interface:\n\t\tif x.IsNil() || y.IsNil() {\n\t\t\treturn x.IsNil() == y.IsNil()\n\t\t}\n\t\treturn equal(x.Elem(), y.Elem(), identical)\n\n\tcase reflect.Struct:\n\t\tfor i := range x.NumField() {\n\t\t\txf := x.Field(i)\n\t\t\tyf := y.Field(i)\n\t\t\t// Skip position fields.\n\t\t\tif xpos, ok := xf.Interface().(token.Pos); ok {\n\t\t\t\typos := yf.Interface().(token.Pos)\n\t\t\t\t// Numeric value of a Pos is not significant but its \"zeroness\" is,\n\t\t\t\t// because it is often significant, e.g. CallExpr.Variadic(Ellipsis), ChanType.Arrow.\n\t\t\t\tif xpos.IsValid() != ypos.IsValid() {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t} else if !equal(xf, yf, identical) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase reflect.Slice:\n\t\tif x.IsNil() || y.IsNil() {\n\t\t\treturn x.IsNil() == y.IsNil()\n\t\t}\n\t\tif x.Len() != y.Len() {\n\t\t\treturn false\n\t\t}\n\t\tfor i := range x.Len() {\n\t\t\tif !equal(x.Index(i), y.Index(i), identical) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase reflect.String:\n\t\treturn x.String() == y.String()\n\n\tcase reflect.Bool:\n\t\treturn x.Bool() == y.Bool()\n\n\tcase reflect.Int:\n\t\treturn x.Int() == y.Int()\n\n\tdefault:\n\t\tpanic(x)\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/fields.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"go/ast\"\n\t\"iter\"\n)\n\n// FlatFields 'flattens' an ast.FieldList, returning an iterator over each\n// (name, field) combination in the list. For unnamed fields, the identifier is\n// nil.\nfunc FlatFields(list *ast.FieldList) iter.Seq2[*ast.Ident, *ast.Field] {\n\treturn func(yield func(*ast.Ident, *ast.Field) bool) {\n\t\tif list == nil {\n\t\t\treturn\n\t\t}\n\n\t\tfor _, field := range list.List {\n\t\t\tif len(field.Names) == 0 {\n\t\t\t\tif !yield(nil, field) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor _, name := range field.Names {\n\t\t\t\t\tif !yield(name, field) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/fields_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage astutil_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/astutil\"\n)\n\nfunc TestFlatFields(t *testing.T) {\n\ttests := []struct {\n\t\tparams string\n\t\twant   string\n\t}{\n\t\t{\"\", \"\"},\n\t\t{\"a int\", \"a int\"},\n\t\t{\"int\", \"int\"},\n\t\t{\"a, b int\", \"a int, b int\"},\n\t\t{\"a, b, c int\", \"a int, b int, c int\"},\n\t\t{\"int, string\", \"int, string\"},\n\t\t{\"_ int, b string\", \"_ int, b string\"},\n\t\t{\"a, _ int, b string\", \"a int, _ int, b string\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tsrc := fmt.Sprintf(\"package p; func _(%s)\", test.params)\n\t\tf, err := parser.ParseFile(token.NewFileSet(), \"\", src, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tparams := f.Decls[0].(*ast.FuncDecl).Type.Params\n\t\tvar got bytes.Buffer\n\t\tfor name, field := range astutil.FlatFields(params) {\n\t\t\tif got.Len() > 0 {\n\t\t\t\tgot.WriteString(\", \")\n\t\t\t}\n\t\t\tif name != nil {\n\t\t\t\tfmt.Fprintf(&got, \"%s \", name.Name)\n\t\t\t}\n\t\t\tgot.WriteString(types.ExprString(field.Type))\n\t\t}\n\t\tif got := got.String(); got != test.want {\n\t\t\t// align 'got' and 'want' for easier inspection\n\t\t\tt.Errorf(\"FlatFields(%q):\\n got: %q\\nwant: %q\", test.params, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/free/free.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package free defines utilities for computing the free variables of\n// a syntax tree without type information. This is inherently\n// heuristic because of the T{f: x} ambiguity, in which f may or may\n// not be a lexical reference depending on whether T is a struct type.\npackage free\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n)\n\n// Copied, with considerable changes, from go/parser/resolver.go\n// at af53bd2c03.\n\n// Names computes an approximation to the set of free names of the AST\n// at node n based solely on syntax.\n//\n// In the absence of composite literals, the set of free names is exact. Composite\n// literals introduce an ambiguity that can only be resolved with type information:\n// whether F is a field name or a value in `T{F: ...}`.\n// If includeComplitIdents is true, this function conservatively assumes\n// T is not a struct type, so freeishNames overapproximates: the resulting\n// set may contain spurious entries that are not free lexical references\n// but are references to struct fields.\n// If includeComplitIdents is false, this function assumes that T *is*\n// a struct type, so freeishNames underapproximates: the resulting set\n// may omit names that are free lexical references.\n//\n// TODO(adonovan): includeComplitIdents is a crude hammer: the caller\n// may have partial or heuristic information about whether a given T\n// is struct type. Replace includeComplitIdents with a hook to query\n// the caller.\n//\n// The code is based on go/parser.resolveFile, but heavily simplified. Crucial\n// differences are:\n//   - Instead of resolving names to their objects, this function merely records\n//     whether they are free.\n//   - Labels are ignored: they do not refer to values.\n//   - This is never called on ImportSpecs, so the function panics if it sees one.\nfunc Names(n ast.Node, includeComplitIdents bool) map[string]bool {\n\tv := &freeVisitor{\n\t\tfree:                 make(map[string]bool),\n\t\tincludeComplitIdents: includeComplitIdents,\n\t}\n\t// Begin with a scope, even though n might not be a form that establishes a scope.\n\t// For example, n might be:\n\t//    x := ...\n\t// Then we need to add the first x to some scope.\n\tv.openScope()\n\tast.Walk(v, n)\n\tv.closeScope()\n\tif v.scope != nil {\n\t\tpanic(\"unbalanced scopes\")\n\t}\n\treturn v.free\n}\n\n// A freeVisitor holds state for a free-name analysis.\ntype freeVisitor struct {\n\tscope                *scope          // the current innermost scope\n\tfree                 map[string]bool // free names seen so far\n\tincludeComplitIdents bool            // include identifier key in composite literals\n}\n\n// scope contains all the names defined in a lexical scope.\n// It is like ast.Scope, but without deprecation warnings.\ntype scope struct {\n\tnames map[string]bool\n\touter *scope\n}\n\nfunc (s *scope) defined(name string) bool {\n\tfor ; s != nil; s = s.outer {\n\t\tif s.names[name] {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (v *freeVisitor) Visit(n ast.Node) ast.Visitor {\n\tswitch n := n.(type) {\n\n\t// Expressions.\n\tcase *ast.Ident:\n\t\tv.use(n)\n\n\tcase *ast.FuncLit:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walkFuncType(nil, n.Type)\n\t\tv.walkBody(n.Body)\n\n\tcase *ast.SelectorExpr:\n\t\tv.walk(n.X)\n\t\t// Skip n.Sel: it cannot be free.\n\n\tcase *ast.StructType:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walkFieldList(n.Fields)\n\n\tcase *ast.FuncType:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walkFuncType(nil, n)\n\n\tcase *ast.CompositeLit:\n\t\tv.walk(n.Type)\n\t\tfor _, e := range n.Elts {\n\t\t\tif kv, _ := e.(*ast.KeyValueExpr); kv != nil {\n\t\t\t\tif ident, _ := kv.Key.(*ast.Ident); ident != nil {\n\t\t\t\t\t// It is not possible from syntax alone to know whether\n\t\t\t\t\t// an identifier used as a composite literal key is\n\t\t\t\t\t// a struct field (if n.Type is a struct) or a value\n\t\t\t\t\t// (if n.Type is a map, slice or array).\n\t\t\t\t\tif v.includeComplitIdents {\n\t\t\t\t\t\t// Over-approximate by treating both cases as potentially\n\t\t\t\t\t\t// free names.\n\t\t\t\t\t\tv.use(ident)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Under-approximate by ignoring potentially free names.\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tv.walk(kv.Key)\n\t\t\t\t}\n\t\t\t\tv.walk(kv.Value)\n\t\t\t} else {\n\t\t\t\tv.walk(e)\n\t\t\t}\n\t\t}\n\n\tcase *ast.InterfaceType:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walkFieldList(n.Methods)\n\n\t// Statements\n\tcase *ast.AssignStmt:\n\t\twalkSlice(v, n.Rhs)\n\t\tif n.Tok == token.DEFINE {\n\t\t\tv.shortVarDecl(n.Lhs)\n\t\t} else {\n\t\t\twalkSlice(v, n.Lhs)\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\t// Ignore labels.\n\t\tv.walk(n.Stmt)\n\n\tcase *ast.BranchStmt:\n\t\t// Ignore labels.\n\n\tcase *ast.BlockStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\twalkSlice(v, n.List)\n\n\tcase *ast.IfStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walk(n.Init)\n\t\tv.walk(n.Cond)\n\t\tv.walk(n.Body)\n\t\tv.walk(n.Else)\n\n\tcase *ast.CaseClause:\n\t\twalkSlice(v, n.List)\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\twalkSlice(v, n.Body)\n\n\tcase *ast.SwitchStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walk(n.Init)\n\t\tv.walk(n.Tag)\n\t\tv.walkBody(n.Body)\n\n\tcase *ast.TypeSwitchStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tif n.Init != nil {\n\t\t\tv.walk(n.Init)\n\t\t}\n\t\tv.walk(n.Assign)\n\t\t// We can use walkBody here because we don't track label scopes.\n\t\tv.walkBody(n.Body)\n\n\tcase *ast.CommClause:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walk(n.Comm)\n\t\twalkSlice(v, n.Body)\n\n\tcase *ast.SelectStmt:\n\t\tv.walkBody(n.Body)\n\n\tcase *ast.ForStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walk(n.Init)\n\t\tv.walk(n.Cond)\n\t\tv.walk(n.Post)\n\t\tv.walk(n.Body)\n\n\tcase *ast.RangeStmt:\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walk(n.X)\n\t\tvar lhs []ast.Expr\n\t\tif n.Key != nil {\n\t\t\tlhs = append(lhs, n.Key)\n\t\t}\n\t\tif n.Value != nil {\n\t\t\tlhs = append(lhs, n.Value)\n\t\t}\n\t\tif len(lhs) > 0 {\n\t\t\tif n.Tok == token.DEFINE {\n\t\t\t\tv.shortVarDecl(lhs)\n\t\t\t} else {\n\t\t\t\twalkSlice(v, lhs)\n\t\t\t}\n\t\t}\n\t\tv.walk(n.Body)\n\n\t// Declarations\n\tcase *ast.GenDecl:\n\t\tswitch n.Tok {\n\t\tcase token.CONST, token.VAR:\n\t\t\tfor _, spec := range n.Specs {\n\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\twalkSlice(v, spec.Values)\n\t\t\t\tv.walk(spec.Type)\n\t\t\t\tv.declare(spec.Names...)\n\t\t\t}\n\n\t\tcase token.TYPE:\n\t\t\tfor _, spec := range n.Specs {\n\t\t\t\tspec := spec.(*ast.TypeSpec)\n\t\t\t\t// Go spec: The scope of a type identifier declared inside a\n\t\t\t\t// function begins at the identifier in the TypeSpec and ends\n\t\t\t\t// at the end of the innermost containing block.\n\t\t\t\tv.declare(spec.Name)\n\t\t\t\tif spec.TypeParams != nil {\n\t\t\t\t\tv.openScope()\n\t\t\t\t\tdefer v.closeScope()\n\t\t\t\t\tv.walkTypeParams(spec.TypeParams)\n\t\t\t\t}\n\t\t\t\tv.walk(spec.Type)\n\t\t\t}\n\n\t\tcase token.IMPORT:\n\t\t\tpanic(\"encountered import declaration in free analysis\")\n\t\t}\n\n\tcase *ast.FuncDecl:\n\t\tif n.Recv == nil && n.Name.Name != \"init\" { // package-level function\n\t\t\tv.declare(n.Name)\n\t\t}\n\t\tv.openScope()\n\t\tdefer v.closeScope()\n\t\tv.walkTypeParams(n.Type.TypeParams)\n\t\tv.walkFuncType(n.Recv, n.Type)\n\t\tv.walkBody(n.Body)\n\n\tdefault:\n\t\treturn v\n\t}\n\n\treturn nil\n}\n\nfunc (v *freeVisitor) openScope() {\n\tv.scope = &scope{map[string]bool{}, v.scope}\n}\n\nfunc (v *freeVisitor) closeScope() {\n\tv.scope = v.scope.outer\n}\n\nfunc (v *freeVisitor) walk(n ast.Node) {\n\tif n != nil {\n\t\tast.Walk(v, n)\n\t}\n}\n\nfunc (v *freeVisitor) walkFuncType(recv *ast.FieldList, typ *ast.FuncType) {\n\t// First use field types...\n\tv.walkRecvFieldType(recv)\n\tv.walkFieldTypes(typ.Params)\n\tv.walkFieldTypes(typ.Results)\n\n\t// ...then declare field names.\n\tv.declareFieldNames(recv)\n\tv.declareFieldNames(typ.Params)\n\tv.declareFieldNames(typ.Results)\n}\n\n// A receiver field is not like a param or result field because\n// \"func (recv R[T]) method()\" uses R but declares T.\nfunc (v *freeVisitor) walkRecvFieldType(list *ast.FieldList) {\n\tif list == nil {\n\t\treturn\n\t}\n\tfor _, f := range list.List { // valid => len=1\n\t\ttyp := f.Type\n\t\tif ptr, ok := typ.(*ast.StarExpr); ok {\n\t\t\ttyp = ptr.X\n\t\t}\n\n\t\t// Analyze receiver type as Base[Index, ...]\n\t\tvar (\n\t\t\tbase    ast.Expr\n\t\t\tindices []ast.Expr\n\t\t)\n\t\tswitch typ := typ.(type) {\n\t\tcase *ast.IndexExpr: // B[T]\n\t\t\tbase, indices = typ.X, []ast.Expr{typ.Index}\n\t\tcase *ast.IndexListExpr: // B[K, V]\n\t\t\tbase, indices = typ.X, typ.Indices\n\t\tdefault: // B\n\t\t\tbase = typ\n\t\t}\n\t\tfor _, expr := range indices {\n\t\t\tif id, ok := expr.(*ast.Ident); ok {\n\t\t\t\tv.declare(id)\n\t\t\t}\n\t\t}\n\t\tv.walk(base)\n\t}\n}\n\n// walkTypeParams is like walkFieldList, but declares type parameters eagerly so\n// that they may be resolved in the constraint expressions held in the field\n// Type.\nfunc (v *freeVisitor) walkTypeParams(list *ast.FieldList) {\n\tv.declareFieldNames(list)\n\tv.walkFieldTypes(list) // constraints\n}\n\nfunc (v *freeVisitor) walkBody(body *ast.BlockStmt) {\n\tif body == nil {\n\t\treturn\n\t}\n\twalkSlice(v, body.List)\n}\n\nfunc (v *freeVisitor) walkFieldList(list *ast.FieldList) {\n\tif list == nil {\n\t\treturn\n\t}\n\tv.walkFieldTypes(list)    // .Type may contain references\n\tv.declareFieldNames(list) // .Names declares names\n}\n\nfunc (v *freeVisitor) shortVarDecl(lhs []ast.Expr) {\n\t// Go spec: A short variable declaration may redeclare variables provided\n\t// they were originally declared in the same block with the same type, and\n\t// at least one of the non-blank variables is new.\n\t//\n\t// However, it doesn't matter to free analysis whether a variable is declared\n\t// fresh or redeclared.\n\tfor _, x := range lhs {\n\t\t// In a well-formed program each expr must be an identifier,\n\t\t// but be forgiving.\n\t\tif id, ok := x.(*ast.Ident); ok {\n\t\t\tv.declare(id)\n\t\t}\n\t}\n}\n\nfunc walkSlice[S ~[]E, E ast.Node](r *freeVisitor, list S) {\n\tfor _, e := range list {\n\t\tr.walk(e)\n\t}\n}\n\n// walkFieldTypes resolves the types of the walkFieldTypes in list.\n// The companion method declareFieldList declares the names of the walkFieldTypes.\nfunc (v *freeVisitor) walkFieldTypes(list *ast.FieldList) {\n\tif list != nil {\n\t\tfor _, f := range list.List {\n\t\t\tv.walk(f.Type)\n\t\t}\n\t}\n}\n\n// declareFieldNames declares the names of the fields in list.\n// (Names in a FieldList always establish new bindings.)\n// The companion method resolveFieldList resolves the types of the fields.\nfunc (v *freeVisitor) declareFieldNames(list *ast.FieldList) {\n\tif list != nil {\n\t\tfor _, f := range list.List {\n\t\t\tv.declare(f.Names...)\n\t\t}\n\t}\n}\n\n// use marks ident as free if it is not in scope.\nfunc (v *freeVisitor) use(ident *ast.Ident) {\n\tif s := ident.Name; s != \"_\" && !v.scope.defined(s) {\n\t\tv.free[s] = true\n\t}\n}\n\n// declare adds each non-blank ident to the current scope.\nfunc (v *freeVisitor) declare(idents ...*ast.Ident) {\n\tfor _, id := range idents {\n\t\tif id.Name != \"_\" {\n\t\t\tv.scope.names[id.Name] = true\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/free/free_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage free_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"maps\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/astutil/free\"\n)\n\nfunc TestNames(t *testing.T) {\n\telems := func(m map[string]bool) string {\n\t\treturn strings.Join(slices.Sorted(maps.Keys(m)), \" \")\n\t}\n\n\ttype testcase struct {\n\t\tcode string // file content (without package decl)\n\t\twant string // space-separated list of expected free names of first decl\n\t}\n\n\tfor _, tc := range []struct {\n\t\tincludeComplitIdents bool\n\t\tcases                []testcase\n\t}{\n\t\t{true, []testcase{\n\t\t\t{\n\t\t\t\t`var _ = x`,\n\t\t\t\t\"x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = x.y.z`,\n\t\t\t\t\"x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = T{a: 1, b: 2, c.d: e}`,\n\t\t\t\t\"a b c e T\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = f(x)`,\n\t\t\t\t\"f x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = f.m(x)`,\n\t\t\t\t\"f x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = func(x int) int { return x + y }`,\n\t\t\t\t\"int y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { x = func(x int) int { return 2*x }() }`,\n\t\t\t\t\"int x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = func(x int) (y int) { return x + y }`,\n\t\t\t\t\"int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = struct{a **int; b map[int][]bool}`,\n\t\t\t\t\"bool int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = struct{f int}{f: 0}`,\n\t\t\t\t\"f int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var _ = interface{m1(int) bool; m2(x int) (y bool)}`,\n\t\t\t\t\"bool int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { x := 1; x++ }`,\n\t\t\t\t\"\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { x = 1 }`,\n\t\t\t\t\"x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { _ = 1 }`,\n\t\t\t\t\"\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { x, y := 1, 2; x = y + z }`,\n\t\t\t\t\"z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { x, y := y, x; x = y + z }`,\n\t\t\t\t\"x y z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { a, b := 0, 0; b, c := 0, 0; print(a, b, c, d) }`,\n\t\t\t\t\"d print\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { label: x++ }`,\n\t\t\t\t\"x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { if x == y {x} }`,\n\t\t\t\t\"x y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { if x := 1; x == y {x} }`,\n\t\t\t\t\"y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { if x := 1; x == y {x} else {z} }`,\n\t\t\t\t\"y z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { switch x { case 1: x; case y: z } }`,\n\t\t\t\t\"x y z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { switch x := 1; x { case 1: x; case y: z } }`,\n\t\t\t\t\"y z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { switch x.(type) { case int: x; case []int: y } }`,\n\t\t\t\t\"int x y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { switch x := 1; x.(type) { case int: x; case []int: y } }`,\n\t\t\t\t\"int y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { switch y := x.(type) { case int: x; case []int: y } }`,\n\t\t\t\t\"int x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { select { case c <- 1: x; case x := <-c: 2; default: y} }`,\n\t\t\t\t\"c x y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { for i := 0; i < 9; i++ { c <- j } }`,\n\t\t\t\t\"c j\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { for i = 0; i < 9; i++ { c <- j } }`,\n\t\t\t\t\"c i j\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { for i := range 9 { c <- j } }`,\n\t\t\t\t\"c j\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { for i = range 9 { c <- j } }`,\n\t\t\t\t\"c i j\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { for _, e := range []int{1, 2, x} {e} }`,\n\t\t\t\t\"int x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { var x, y int; f(x, y) }`,\n\t\t\t\t\"f int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { {var x, y int}; f(x, y) }`,\n\t\t\t\t\"f int x y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { const x = 1; { const y = iota; return x, y } }`,\n\t\t\t\t\"iota\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { type t int; t(0) }`,\n\t\t\t\t\"int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { type t[T ~int] struct { t T };  x = t{t: 1}.t }`, // field t shadowed by type decl\n\t\t\t\t\"int x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func _() { type t[S ~[]E, E any] S }`,\n\t\t\t\t\"any\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`var a [unsafe.Sizeof(func(x int) { x + y })]int`,\n\t\t\t\t\"int unsafe y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func f(x int) (int y)`,\n\t\t\t\t\"int y\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func f(int x) (y int)`,\n\t\t\t\t\"int x\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func f[T int](int [k]T) *T`,\n\t\t\t\t\"int k\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func f[T *T]([k]T)`,\n\t\t\t\t\"k\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func (recv T) method(x int) { print(recv) }`,\n\t\t\t\t\"T int print\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func (recv R[P]) method(x int) { var _ P }`,\n\t\t\t\t\"R int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func (recv R[P, P2]) method(x int) { var ( _ P; _ P2 ) }`,\n\t\t\t\t\"R int\",\n\t\t\t},\n\t\t\t{\n\t\t\t\t`func init() { print(init) }`,\n\t\t\t\t\"print init\",\n\t\t\t},\n\t\t}},\n\t\t{\n\t\t\tfalse,\n\t\t\t[]testcase{\n\t\t\t\t{\n\t\t\t\t\t`func _() { x }`,\n\t\t\t\t\t\"x\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t`func _() { x.y.z }`,\n\t\t\t\t\t\"x\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t`func _() { T{a: 1, b: 2, c.d: e} }`,\n\t\t\t\t\t\"c e T\", // omit a and b\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t`func _() { type t[T ~int] struct { t T };  x = t{t: 1}.t }`, // field t shadowed by type decl\n\t\t\t\t\t\"int x\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(fmt.Sprintf(\"includeComplitIdents=%t\", tc.includeComplitIdents), func(t *testing.T) {\n\t\t\tfor _, test := range tc.cases {\n\t\t\t\t_, f := mustParse(t, \"free.go\", `package p; `+test.code)\n\t\t\t\tdecl := f.Decls[0]\n\t\t\t\twant := map[string]bool{}\n\t\t\t\tfor name := range strings.FieldsSeq(test.want) {\n\t\t\t\t\twant[name] = true\n\t\t\t\t}\n\n\t\t\t\tgot := free.Names(decl, tc.includeComplitIdents)\n\n\t\t\t\tif !maps.Equal(got, want) {\n\t\t\t\t\tt.Errorf(\"\\ncode  %s\\ngot   %v\\nwant  %v\", test.code, elems(got), elems(want))\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFreeNames_scope(t *testing.T) {\n\t// Verify that inputs that don't start a scope don't crash.\n\t_, f := mustParse(t, \"free.go\", `package p; func _() { x := 1; _ = x }`)\n\t// Select the short var decl, not the entire function body.\n\tn := f.Decls[0].(*ast.FuncDecl).Body.List[0]\n\t_ = free.Names(n, false)\n}\n\nfunc mustParse(t *testing.T, filename string, content any) (*token.FileSet, *ast.File) {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, filename, content, parser.ParseComments|parser.SkipObjectResolution)\n\tif err != nil {\n\t\tt.Fatalf(\"ParseFile: %v\\ncode: %s\", err, content)\n\t}\n\treturn fset, f\n}\n"
  },
  {
    "path": "internal/astutil/purge.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package astutil provides various AST utility functions for gopls.\npackage astutil\n\nimport (\n\t\"bytes\"\n\t\"go/scanner\"\n\t\"go/token\"\n)\n\n// PurgeFuncBodies returns a copy of src in which the contents of each\n// outermost {...} region except struct and interface types have been\n// deleted. This reduces the amount of work required to parse the\n// top-level declarations.\n//\n// PurgeFuncBodies does not preserve newlines or position information.\n// Also, if the input is invalid, parsing the output of\n// PurgeFuncBodies may result in a different tree due to its effects\n// on parser error recovery.\nfunc PurgeFuncBodies(src []byte) []byte {\n\t// Destroy the content of any {...}-bracketed regions that are\n\t// not immediately preceded by a \"struct\" or \"interface\"\n\t// token.  That includes function bodies, composite literals,\n\t// switch/select bodies, and all blocks of statements.\n\t// This will lead to non-void functions that don't have return\n\t// statements, which of course is a type error, but that's ok.\n\n\tvar out bytes.Buffer\n\tfile := token.NewFileSet().AddFile(\"\", -1, len(src))\n\tvar sc scanner.Scanner\n\tsc.Init(file, src, nil, 0)\n\tvar prev token.Token\n\tvar cursor int         // last consumed src offset\n\tvar braces []token.Pos // stack of unclosed braces or -1 for struct/interface type\n\tfor {\n\t\tpos, tok, _ := sc.Scan()\n\t\tif tok == token.EOF {\n\t\t\tbreak\n\t\t}\n\t\tswitch tok {\n\t\tcase token.COMMENT:\n\t\t\t// TODO(adonovan): opt: skip, to save an estimated 20% of time.\n\n\t\tcase token.LBRACE:\n\t\t\tif prev == token.STRUCT || prev == token.INTERFACE {\n\t\t\t\tpos = -1\n\t\t\t}\n\t\t\tbraces = append(braces, pos)\n\n\t\tcase token.RBRACE:\n\t\t\tif last := len(braces) - 1; last >= 0 {\n\t\t\t\ttop := braces[last]\n\t\t\t\tbraces = braces[:last]\n\t\t\t\tif top < 0 {\n\t\t\t\t\t// struct/interface type: leave alone\n\t\t\t\t} else if len(braces) == 0 { // toplevel only\n\t\t\t\t\t// Delete {...} body.\n\t\t\t\t\tstart := file.Offset(top)\n\t\t\t\t\tend := file.Offset(pos)\n\t\t\t\t\tout.Write(src[cursor : start+len(\"{\")])\n\t\t\t\t\tcursor = end\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprev = tok\n\t}\n\tout.Write(src[cursor:])\n\treturn out.Bytes()\n}\n"
  },
  {
    "path": "internal/astutil/purge_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"os\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestPurgeFuncBodies tests PurgeFuncBodies by comparing it against a\n// (less efficient) reference implementation that purges after parsing.\nfunc TestPurgeFuncBodies(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // we need the source code for std\n\n\t// Load a few standard packages.\n\tconfig := packages.Config{Mode: packages.NeedCompiledGoFiles}\n\tpkgs, err := packages.Load(&config, \"encoding/...\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// preorder returns the nodes of tree f in preorder.\n\tpreorder := func(f *ast.File) (nodes []ast.Node) {\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif n != nil {\n\t\t\t\tnodes = append(nodes, n)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\treturn nodes\n\t}\n\n\tpackages.Visit(pkgs, nil, func(p *packages.Package) {\n\t\tfor _, filename := range p.CompiledGoFiles {\n\t\t\tcontent, err := os.ReadFile(filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tfset := token.NewFileSet()\n\n\t\t\t// Parse then purge (reference implementation).\n\t\t\tf1, _ := parser.ParseFile(fset, filename, content, parser.SkipObjectResolution)\n\t\t\tast.Inspect(f1, func(n ast.Node) bool {\n\t\t\t\tswitch n := n.(type) {\n\t\t\t\tcase *ast.FuncDecl:\n\t\t\t\t\tif n.Body != nil {\n\t\t\t\t\t\tn.Body.List = nil\n\t\t\t\t\t}\n\t\t\t\tcase *ast.FuncLit:\n\t\t\t\t\tn.Body.List = nil\n\t\t\t\tcase *ast.CompositeLit:\n\t\t\t\t\tn.Elts = nil\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\n\t\t\t// Purge before parse (logic under test).\n\t\t\tf2, _ := parser.ParseFile(fset, filename, astutil.PurgeFuncBodies(content), parser.SkipObjectResolution)\n\n\t\t\t// Compare sequence of node types.\n\t\t\tnodes1 := preorder(f1)\n\t\t\tnodes2 := preorder(f2)\n\t\t\tif len(nodes2) < len(nodes1) {\n\t\t\t\tt.Errorf(\"purged file has fewer nodes: %d vs  %d\",\n\t\t\t\t\tlen(nodes2), len(nodes1))\n\t\t\t\tnodes1 = nodes1[:len(nodes2)] // truncate\n\t\t\t}\n\t\t\tfor i := range nodes1 {\n\t\t\t\tx, y := nodes1[i], nodes2[i]\n\t\t\t\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\t\t\t\tt.Errorf(\"%s: got %T, want %T\",\n\t\t\t\t\t\tfset.Position(x.Pos()), y, x)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "internal/astutil/stringlit.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"strconv\"\n\t\"unicode/utf8\"\n)\n\n// RangeInStringLiteral calculates the positional range within a string literal\n// corresponding to the specified start and end byte offsets within the logical string.\nfunc RangeInStringLiteral(lit *ast.BasicLit, start, end int) (Range, error) {\n\tstartPos, err := PosInStringLiteral(lit, start)\n\tif err != nil {\n\t\treturn Range{}, fmt.Errorf(\"start: %v\", err)\n\t}\n\tendPos, err := PosInStringLiteral(lit, end)\n\tif err != nil {\n\t\treturn Range{}, fmt.Errorf(\"end: %v\", err)\n\t}\n\treturn Range{startPos, endPos}, nil\n}\n\n// PosInStringLiteral returns the position within a string literal\n// corresponding to the specified byte offset within the logical\n// string that it denotes.\nfunc PosInStringLiteral(lit *ast.BasicLit, offset int) (token.Pos, error) {\n\traw := lit.Value\n\n\tvalue, err := strconv.Unquote(raw)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif !(0 <= offset && offset <= len(value)) {\n\t\treturn 0, fmt.Errorf(\"invalid offset\")\n\t}\n\n\tpos, _ := walkStringLiteral(lit, lit.End(), offset)\n\treturn pos, nil\n}\n\n// OffsetInStringLiteral returns the byte offset within the logical (unquoted)\n// string corresponding to the specified source position.\nfunc OffsetInStringLiteral(lit *ast.BasicLit, pos token.Pos) (int, error) {\n\tif !NodeContainsPos(lit, pos) {\n\t\treturn 0, fmt.Errorf(\"invalid position\")\n\t}\n\n\traw := lit.Value\n\n\tvalue, err := strconv.Unquote(raw)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t_, offset := walkStringLiteral(lit, pos, len(value))\n\treturn offset, nil\n}\n\n// walkStringLiteral iterates through the raw string literal to map between\n// a file position and a logical byte offset. It stops when it reaches\n// either the targetPos or the targetOffset.\n//\n// TODO(hxjiang): consider making an iterator.\nfunc walkStringLiteral(lit *ast.BasicLit, targetPos token.Pos, targetOffset int) (token.Pos, int) {\n\traw := lit.Value\n\tnorm := int(lit.End()-lit.Pos()) > len(lit.Value)\n\n\t// remove quotes\n\tquote := raw[0] // '\"' or '`'\n\traw = raw[1 : len(raw)-1]\n\n\tvar (\n\t\ti   = 0             // byte index within logical value\n\t\tpos = lit.Pos() + 1 // position within literal\n\t)\n\n\tfor raw != \"\" {\n\t\tr, _, rest, _ := strconv.UnquoteChar(raw, quote) // can't fail\n\t\tsz := len(raw) - len(rest)                       // length of literal char in raw bytes\n\n\t\tnextPos := pos + token.Pos(sz)\n\t\tif norm && r == '\\n' {\n\t\t\tnextPos++\n\t\t}\n\t\tnextI := i + utf8.RuneLen(r) // length of logical char in \"cooked\" bytes\n\n\t\tif nextPos > targetPos || nextI > targetOffset {\n\t\t\tbreak\n\t\t}\n\n\t\traw = raw[sz:]\n\t\ti = nextI\n\t\tpos = nextPos\n\t}\n\n\treturn pos, i\n}\n"
  },
  {
    "path": "internal/astutil/stringlit_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestPosInStringLiteral(t *testing.T) {\n\t// Each string is Go source for a string literal with ^ marker at expected Pos.\n\ttests := []string{\n\t\t`\"^abc\"`,\n\t\t`\"a^bc\"`,\n\t\t`\"ab^c\"`,\n\t\t`\"abc^\"`,\n\t\t`\"a\\n^b\"`,\n\t\t`\"\\n^\"`,\n\t\t`\"a\\000^\"`,\n\t\t`\"\\x61^\"`,\n\t\t`\"\\u0061^\"`,\n\t\t`\"\\U00000061^\"`,\n\t\t`\"€^\"`,\n\t\t`\"a€^b\"`,\n\t\t\"`abc^`\",\n\t\t\"`a\\n^b`\",\n\t\t// normalization of \\r carriage returns:\n\t\t\"`a\\r\\n^b`\",\n\t\t\"`a\\r\\nb\\r\\nc\\r\\n^d`\",\n\t}\n\tfor _, test := range tests {\n\t\t// The workaround for \\r requires the go1.26 fix for https://go.dev/issue/76031.\n\t\tif strings.Contains(test, \"\\r\") && testenv.Go1Point() < 26 {\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Logf(\"input: %#q\", test)\n\n\t\t// Parse.\n\t\tconst prefix = \"package p; const _ = \"\n\t\tsrc := prefix + test\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Parse: %v\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Find literal.\n\t\tvar lit *ast.BasicLit\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif b, ok := n.(*ast.BasicLit); ok {\n\t\t\t\tlit = b\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tif lit == nil {\n\t\t\tt.Errorf(\"No literal\")\n\t\t\tcontinue\n\t\t}\n\n\t\t// Find index of marker within logical value.\n\t\tvalue, err := strconv.Unquote(lit.Value)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unquote: %v\", err)\n\t\t\tcontinue\n\t\t}\n\t\tindex := strings.Index(value, \"^\")\n\t\tif index < 0 {\n\t\t\tt.Errorf(\"Value %q contains no marker\", value)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Convert logical index to file position.\n\t\tpos, err := astutil.PosInStringLiteral(lit, index)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"PosInStringLiteral(%d): %v\", index, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check that cut offset in original src file is before marker.\n\t\toffset := fset.Position(pos).Offset\n\t\tbefore, after := src[:offset], src[offset:]\n\t\tt.Logf(\"\\t%q :: %q\", before, after)\n\t\tif !strings.HasPrefix(after, \"^\") {\n\t\t\tt.Errorf(\"no marker at cut point\")\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc TestOffsetInStringLiteral(t *testing.T) {\n\t// Each string is Go source for a string literal with | marker at expected\n\t// physical pos, and $ marker at the expected logical unquoted index.\n\ttests := []string{\n\t\t`\"$|abc\"`,\n\t\t`\"a$|bc\"`,\n\t\t`\"ab$|c\"`,\n\t\t`\"abc$|\"`,\n\t\t`\"a\\n$|b\"`,\n\t\t`\"\\n$|\"`,\n\t\t`\"a\\000$|\"`,\n\t\t`\"\\x61$|\"`,\n\t\t`\"\\u0061$|\"`,\n\t\t`\"\\U00000061$|\"`,\n\t\t`\"$\\U00|000061\"`,\n\t\t`\"€$|\"`,\n\t\t`\"a€$|b\"`,\n\t\t\"`abc$|`\",\n\t\t\"`a\\n$|b`\",\n\t\t// normalization of \\r carriage returns:\n\t\t\"`a\\r\\n$|b`\",\n\t\t\"`a\\r\\nb\\r\\nc\\r\\n$|d`\",\n\t}\n\tfor _, test := range tests {\n\t\t// The workaround for \\r requires the go1.26 fix for https://go.dev/issue/76031.\n\t\tif strings.Contains(test, \"\\r\") && testenv.Go1Point() < 26 {\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Logf(\"input: %#q\", test)\n\n\t\tconst prefix = \"package p; const _ = \"\n\t\tsrc := prefix + test\n\n\t\t// Remove the physical marker to produce valid Go source.\n\t\toffset := strings.Index(src, \"|\")\n\t\tif offset < 0 {\n\t\t\tt.Errorf(\"Source %q contains no marker\", src)\n\t\t\tcontinue\n\t\t}\n\t\tsrc = src[:offset] + src[offset+1:]\n\n\t\t// Parse.\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Parse: %v\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Find literal.\n\t\tvar lit *ast.BasicLit\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif b, ok := n.(*ast.BasicLit); ok {\n\t\t\t\tlit = b\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tif lit == nil {\n\t\t\tt.Errorf(\"No literal\")\n\t\t\tcontinue\n\t\t}\n\n\t\ttfile := fset.File(f.Pos())\n\t\tpos := tfile.Pos(offset)\n\n\t\t// Convert file position to logical index.\n\t\tindex, err := astutil.OffsetInStringLiteral(lit, pos)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"OffsetInStringLiteral(%d): %v\", pos, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tvalue, err := strconv.Unquote(lit.Value)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unquote: %v\", err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif index < 0 || index > len(value) {\n\t\t\tt.Errorf(\"Returned index %d is out of bounds for logical string of length %d\", index, len(value))\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check that cut offset in value is before marker.\n\t\tbefore, after := value[:index], value[index:]\n\t\tt.Logf(\"\\t%q :: %q\", before, after)\n\t\tif !strings.HasSuffix(before, \"$\") {\n\t\t\tt.Errorf(\"no marker at logical cut point, got before=%q\", before)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/astutil/unpack.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"go/ast\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// UnpackRecv unpacks a receiver type expression, reporting whether it is a\n// pointer receiver, along with the type name identifier and any receiver type\n// parameter identifiers.\n//\n// Copied (with modifications) from go/types.\nfunc UnpackRecv(rtyp ast.Expr) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) {\nL: // unpack receiver type\n\t// This accepts invalid receivers such as ***T and does not\n\t// work for other invalid receivers, but we don't care. The\n\t// validity of receiver expressions is checked elsewhere.\n\tfor {\n\t\tswitch t := rtyp.(type) {\n\t\tcase *ast.ParenExpr:\n\t\t\trtyp = t.X\n\t\tcase *ast.StarExpr:\n\t\t\tptr = true\n\t\t\trtyp = t.X\n\t\tdefault:\n\t\t\tbreak L\n\t\t}\n\t}\n\n\t// unpack type parameters, if any\n\tswitch rtyp.(type) {\n\tcase *ast.IndexExpr, *ast.IndexListExpr:\n\t\tvar indices []ast.Expr\n\t\trtyp, _, indices, _ = typeparams.UnpackIndexExpr(rtyp)\n\t\tfor _, arg := range indices {\n\t\t\tvar par *ast.Ident\n\t\t\tswitch arg := arg.(type) {\n\t\t\tcase *ast.Ident:\n\t\t\t\tpar = arg\n\t\t\tdefault:\n\t\t\t\t// ignore errors\n\t\t\t}\n\t\t\tif par == nil {\n\t\t\t\tpar = &ast.Ident{NamePos: arg.Pos(), Name: \"_\"}\n\t\t\t}\n\t\t\ttparams = append(tparams, par)\n\t\t}\n\t}\n\n\t// unpack receiver name\n\tif name, _ := rtyp.(*ast.Ident); name != nil {\n\t\trname = name\n\t}\n\n\treturn\n}\n"
  },
  {
    "path": "internal/astutil/util.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage astutil\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/moreiters\"\n)\n\n// NodeContains reports whether the Pos/End range of node n encloses\n// the given range.\n//\n// It is inclusive of both end points, to allow hovering (etc) when\n// the cursor is immediately after a node.\n//\n// Like [NodeRange], it treats the range of an [ast.File] as the\n// file's complete extent.\n//\n// Precondition: n must not be nil.\nfunc NodeContains(n ast.Node, rng Range) bool {\n\treturn NodeRange(n).Contains(rng)\n}\n\n// NodeContainsPos reports whether the Pos/End range of node n encloses\n// the given pos.\n//\n// Like [NodeRange], it treats the range of an [ast.File] as the\n// file's complete extent.\nfunc NodeContainsPos(n ast.Node, pos token.Pos) bool {\n\treturn NodeRange(n).ContainsPos(pos)\n}\n\n// EnclosingFile returns the syntax tree for the file enclosing c.\n//\n// TODO(adonovan): promote this to a method of Cursor.\nfunc EnclosingFile(c inspector.Cursor) *ast.File {\n\tc, _ = moreiters.First(c.Enclosing((*ast.File)(nil)))\n\treturn c.Node().(*ast.File)\n}\n\n// DocComment returns the doc comment for a node, if any.\nfunc DocComment(n ast.Node) *ast.CommentGroup {\n\tswitch n := n.(type) {\n\tcase *ast.FuncDecl:\n\t\treturn n.Doc\n\tcase *ast.GenDecl:\n\t\treturn n.Doc\n\tcase *ast.ValueSpec:\n\t\treturn n.Doc\n\tcase *ast.TypeSpec:\n\t\treturn n.Doc\n\tcase *ast.File:\n\t\treturn n.Doc\n\tcase *ast.ImportSpec:\n\t\treturn n.Doc\n\tcase *ast.Field:\n\t\treturn n.Doc\n\t}\n\treturn nil\n}\n\n// Format returns a string representation of the node n.\nfunc Format(fset *token.FileSet, n ast.Node) string {\n\tvar buf strings.Builder\n\tprinter.Fprint(&buf, fset, n) // ignore errors\n\treturn buf.String()\n}\n\n// -- Range --\n\n// Range is a Pos interval.\n// It implements [analysis.Range] and [ast.Node].\ntype Range struct{ Start, EndPos token.Pos }\n\n// RangeOf constructs a Range.\n//\n// RangeOf exists to pacify the \"unkeyed literal\" (composites) vet\n// check. It would be nice if there were a way for a type to add\n// itself to the allowlist.\nfunc RangeOf(start, end token.Pos) Range { return Range{start, end} }\n\n// NodeRange returns the extent of node n as a Range.\n//\n// For unfortunate historical reasons, the Pos/End extent of an\n// ast.File runs from the start of its package declaration---excluding\n// copyright comments, build tags, and package documentation---to the\n// end of its last declaration, excluding any trailing comments. So,\n// as a special case, if n is an [ast.File], NodeContains uses\n// n.FileStart <= pos && pos <= n.FileEnd to report whether the\n// position lies anywhere within the file.\nfunc NodeRange(n ast.Node) Range {\n\tif file, ok := n.(*ast.File); ok {\n\t\treturn Range{file.FileStart, file.FileEnd} // entire file\n\t}\n\treturn Range{n.Pos(), n.End()}\n}\n\nfunc (r Range) Pos() token.Pos { return r.Start }\nfunc (r Range) End() token.Pos { return r.EndPos }\n\n// ContainsPos reports whether the range (inclusive of both end points)\n// includes the specified position.\nfunc (r Range) ContainsPos(pos token.Pos) bool {\n\treturn r.Contains(RangeOf(pos, pos))\n}\n\n// Contains reports whether the range (inclusive of both end points)\n// includes the specified range.\nfunc (r Range) Contains(rng Range) bool {\n\treturn r.Start <= rng.Start && rng.EndPos <= r.EndPos\n}\n\n// IsValid reports whether the range is valid.\nfunc (r Range) IsValid() bool { return r.Start.IsValid() && r.Start <= r.EndPos }\n\n// --\n\n// Select returns the syntax nodes identified by a user's text\n// selection. It returns three nodes: the innermost node that wholly\n// encloses the selection; and the first and last nodes that are\n// wholly enclosed by the selection.\n//\n// For example, given this selection:\n//\n//\t{ f(); g(); /* comment */ }\n//\t  ~~~~~~~~~~~\n//\n// Select returns the enclosing BlockStmt, the f() CallExpr, and the g() CallExpr.\n//\n// If the selection does not wholly enclose any nodes, Select returns an error\n// and invalid start/end nodes, but it may return a valid enclosing node.\n//\n// Callers that require exactly one syntax tree (e.g. just f() or just\n// g()) should check that the returned start and end nodes are\n// identical.\n//\n// This function is intended to be called early in the handling of a\n// user's request, since it is tolerant of sloppy selection including\n// extraneous whitespace and comments. Use it in new code instead of\n// PathEnclosingInterval. When the exact extent of a node is known,\n// use [Cursor.FindByPos] instead.\nfunc Select(curFile inspector.Cursor, start, end token.Pos) (_enclosing, _start, _end inspector.Cursor, _ error) {\n\tcurEnclosing, ok := curFile.FindByPos(start, end)\n\tif !ok {\n\t\treturn noCursor, noCursor, noCursor, fmt.Errorf(\"invalid selection\")\n\t}\n\n\t// Find the first and last node wholly within the (start, end) range.\n\t// We'll narrow the effective selection to them, to exclude whitespace.\n\t// (This matches the functionality of PathEnclosingInterval.)\n\tvar curStart, curEnd inspector.Cursor\n\trng := RangeOf(start, end)\n\tfor cur := range curEnclosing.Preorder() {\n\t\tif rng.Contains(NodeRange(cur.Node())) {\n\t\t\t// The start node has the least Pos.\n\t\t\tif !curStart.Valid() {\n\t\t\t\tcurStart = cur\n\t\t\t}\n\t\t\t// The end node has the greatest End.\n\t\t\t// End positions do not change monotonically,\n\t\t\t// so we must compute the max.\n\t\t\tif !curEnd.Valid() ||\n\t\t\t\tcur.Node().End() > curEnd.Node().End() {\n\t\t\t\tcurEnd = cur\n\t\t\t}\n\t\t}\n\t}\n\tif !curStart.Valid() {\n\t\t// The selection is valid (inside curEnclosing) but contains no\n\t\t// complete nodes. This happens for point selections (start == end),\n\t\t// or selections covering only only spaces, comments, and punctuation\n\t\t// tokens.\n\t\t// Return the enclosing node so the caller can still use the context.\n\t\treturn curEnclosing, noCursor, noCursor, fmt.Errorf(\"invalid selection\")\n\t}\n\treturn curEnclosing, curStart, curEnd, nil\n}\n\nvar noCursor inspector.Cursor\n\n// MaybeParenthesize returns new, possibly wrapped in parens if needed\n// to preserve operator precedence when it replaces old, whose parent\n// is parentNode.\n//\n// (This would be more naturally written in terms of Cursor, but one of\n// the callers--the inliner--does not have cursors handy.)\nfunc MaybeParenthesize(parentNode ast.Node, old, new ast.Expr) ast.Expr {\n\tif needsParens(parentNode, old, new) {\n\t\tnew = &ast.ParenExpr{X: new}\n\t}\n\treturn new\n}\n\nfunc needsParens(parentNode ast.Node, old, new ast.Expr) bool {\n\t// An expression beneath a non-expression\n\t// has no precedence ambiguity.\n\tparent, ok := parentNode.(ast.Expr)\n\tif !ok {\n\t\treturn false\n\t}\n\n\tprecedence := func(n ast.Node) int {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.UnaryExpr, *ast.StarExpr:\n\t\t\treturn token.UnaryPrec\n\t\tcase *ast.BinaryExpr:\n\t\t\treturn n.Op.Precedence()\n\t\t}\n\t\treturn -1\n\t}\n\n\t// Parens are not required if the new node\n\t// is not unary or binary.\n\tnewprec := precedence(new)\n\tif newprec < 0 {\n\t\treturn false\n\t}\n\n\t// Parens are required if parent and child are both\n\t// unary or binary and the parent has higher precedence.\n\tif precedence(parent) > newprec {\n\t\treturn true\n\t}\n\n\t// Was the old node the operand of a postfix operator?\n\t//  f().sel\n\t//  f()[i:j]\n\t//  f()[i]\n\t//  f().(T)\n\t//  f()(x)\n\tswitch parent := parent.(type) {\n\tcase *ast.SelectorExpr:\n\t\treturn parent.X == old\n\tcase *ast.IndexExpr:\n\t\treturn parent.X == old\n\tcase *ast.SliceExpr:\n\t\treturn parent.X == old\n\tcase *ast.TypeAssertExpr:\n\t\treturn parent.X == old\n\tcase *ast.CallExpr:\n\t\treturn parent.Fun == old\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/bisect/bisect.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package bisect can be used by compilers and other programs\n// to serve as a target for the bisect debugging tool.\n// See [golang.org/x/tools/cmd/bisect] for details about using the tool.\n//\n// To be a bisect target, allowing bisect to help determine which of a set of independent\n// changes provokes a failure, a program needs to:\n//\n//  1. Define a way to accept a change pattern on its command line or in its environment.\n//     The most common mechanism is a command-line flag.\n//     The pattern can be passed to [New] to create a [Matcher], the compiled form of a pattern.\n//\n//  2. Assign each change a unique ID. One possibility is to use a sequence number,\n//     but the most common mechanism is to hash some kind of identifying information\n//     like the file and line number where the change might be applied.\n//     [Hash] hashes its arguments to compute an ID.\n//\n//  3. Enable each change that the pattern says should be enabled.\n//     The [Matcher.Enable] method answers this question for a given change ID.\n//\n//  4. Report each change that the pattern says should be reported.\n//     The [Matcher.Report] method answers this question for a given change ID.\n//     The report consists of one more lines on standard error or standard output\n//     that contain a “match marker”. [Marker] returns the match marker for a given ID.\n//     When bisect reports a change as causing the failure, it identifies the change\n//     by printing those report lines, with the match marker removed.\n//\n// # Example Usage\n//\n// A program starts by defining how it receives the pattern. In this example, we will assume a flag.\n// The next step is to compile the pattern:\n//\n//\tm, err := bisect.New(patternFlag)\n//\tif err != nil {\n//\t\tlog.Fatal(err)\n//\t}\n//\n// Then, each time a potential change is considered, the program computes\n// a change ID by hashing identifying information (source file and line, in this case)\n// and then calls m.ShouldEnable and m.ShouldReport to decide whether to\n// enable and report the change, respectively:\n//\n//\tfor each change {\n//\t\th := bisect.Hash(file, line)\n//\t\tif m.ShouldEnable(h) {\n//\t\t\tenableChange()\n//\t\t}\n//\t\tif m.ShouldReport(h) {\n//\t\t\tlog.Printf(\"%v %s:%d\", bisect.Marker(h), file, line)\n//\t\t}\n//\t}\n//\n// Note that the two return different values when bisect is searching for a\n// minimal set of changes to disable to provoke a failure.\n//\n// Finally, note that New returns a nil Matcher when there is no pattern,\n// meaning that the target is not running under bisect at all.\n// In that common case, the computation of the hash can be avoided entirely\n// by checking for m == nil first:\n//\n//\tfor each change {\n//\t\tif m == nil {\n//\t\t\tenableChange()\n//\t\t} else {\n//\t\t\th := bisect.Hash(file, line)\n//\t\t\tif m.ShouldEnable(h) {\n//\t\t\t\tenableChange()\n//\t\t\t}\n//\t\t\tif m.ShouldReport(h) {\n//\t\t\t\tlog.Printf(\"%v %s:%d\", bisect.Marker(h), file, line)\n//\t\t\t}\n//\t\t}\n//\t}\n//\n// # Pattern Syntax\n//\n// Patterns are generated by the bisect tool and interpreted by [New].\n// Users should not have to understand the patterns except when\n// debugging a target's bisect support or debugging the bisect tool itself.\n//\n// The pattern syntax selecting a change is a sequence of bit strings\n// separated by + and - operators. Each bit string denotes the set of\n// changes with IDs ending in those bits, + is set addition, - is set subtraction,\n// and the expression is evaluated in the usual left-to-right order.\n// The special binary number “y” denotes the set of all changes,\n// standing in for the empty bit string.\n// In the expression, all the + operators must appear before all the - operators.\n// A leading + adds to an empty set. A leading - subtracts from the set of all\n// possible suffixes.\n//\n// For example:\n//\n//   - “01+10” and “+01+10” both denote the set of changes\n//     with IDs ending with the bits 01 or 10.\n//\n//   - “01+10-1001” denotes the set of changes with IDs\n//     ending with the bits 01 or 10, but excluding those ending in 1001.\n//\n//   - “-01-1000” and “y-01-1000 both denote the set of all changes\n//     with IDs not ending in 01 nor 1000.\n//\n//   - “0+1-01+001” is not a valid pattern, because all the + operators do not\n//     appear before all the - operators.\n//\n// In the syntaxes described so far, the pattern specifies the changes to\n// enable and report. If a pattern is prefixed by a “!”, the meaning\n// changes: the pattern specifies the changes to DISABLE and report. This\n// mode of operation is needed when a program passes with all changes\n// enabled but fails with no changes enabled. In this case, bisect\n// searches for minimal sets of changes to disable.\n// Put another way, the leading “!” inverts the result from [Matcher.ShouldEnable]\n// but does not invert the result from [Matcher.ShouldReport].\n//\n// As a convenience for manual debugging, “n” is an alias for “!y”,\n// meaning to disable and report all changes.\n//\n// Finally, a leading “v” in the pattern indicates that the reports will be shown\n// to the user of bisect to describe the changes involved in a failure.\n// At the API level, the leading “v” causes [Matcher.Verbose] to return true.\n// See the next section for details.\n//\n// # Match Reports\n//\n// The target program must enable only those changed matched\n// by the pattern, and it must print a match report for each such change.\n// A match report consists of one or more lines of text that will be\n// printed by the bisect tool to describe a change implicated in causing\n// a failure. Each line in the report for a given change must contain a\n// match marker with that change ID, as returned by [Marker].\n// The markers are elided when displaying the lines to the user.\n//\n// A match marker has the form “[bisect-match 0x1234]” where\n// 0x1234 is the change ID in hexadecimal.\n// An alternate form is “[bisect-match 010101]”, giving the change ID in binary.\n//\n// When [Matcher.Verbose] returns false, the match reports are only\n// being processed by bisect to learn the set of enabled changes,\n// not shown to the user, meaning that each report can be a match\n// marker on a line by itself, eliding the usual textual description.\n// When the textual description is expensive to compute,\n// checking [Matcher.Verbose] can help the avoid that expense\n// in most runs.\npackage bisect\n\n// New creates and returns a new Matcher implementing the given pattern.\n// The pattern syntax is defined in the package doc comment.\n//\n// In addition to the pattern syntax syntax, New(\"\") returns nil, nil.\n// The nil *Matcher is valid for use: it returns true from ShouldEnable\n// and false from ShouldReport for all changes. Callers can avoid calling\n// [Hash], [Matcher.ShouldEnable], and [Matcher.ShouldPrint] entirely\n// when they recognize the nil Matcher.\nfunc New(pattern string) (*Matcher, error) {\n\tif pattern == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tm := new(Matcher)\n\n\t// Allow multiple v, so that “bisect cmd vPATTERN” can force verbose all the time.\n\tp := pattern\n\tfor len(p) > 0 && p[0] == 'v' {\n\t\tm.verbose = true\n\t\tp = p[1:]\n\t\tif p == \"\" {\n\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t}\n\t}\n\n\t// Allow multiple !, each negating the last, so that “bisect cmd !PATTERN” works\n\t// even when bisect chooses to add its own !.\n\tm.enable = true\n\tfor len(p) > 0 && p[0] == '!' {\n\t\tm.enable = !m.enable\n\t\tp = p[1:]\n\t\tif p == \"\" {\n\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t}\n\t}\n\n\tif p == \"n\" {\n\t\t// n is an alias for !y.\n\t\tm.enable = !m.enable\n\t\tp = \"y\"\n\t}\n\n\t// Parse actual pattern syntax.\n\tresult := true\n\tbits := uint64(0)\n\tstart := 0\n\twid := 1 // 1-bit (binary); sometimes 4-bit (hex)\n\tfor i := 0; i <= len(p); i++ {\n\t\t// Imagine a trailing - at the end of the pattern to flush final suffix\n\t\tc := byte('-')\n\t\tif i < len(p) {\n\t\t\tc = p[i]\n\t\t}\n\t\tif i == start && wid == 1 && c == 'x' { // leading x for hex\n\t\t\tstart = i + 1\n\t\t\twid = 4\n\t\t\tcontinue\n\t\t}\n\t\tswitch c {\n\t\tdefault:\n\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\tcase '2', '3', '4', '5', '6', '7', '8', '9':\n\t\t\tif wid != 4 {\n\t\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t\t}\n\t\t\tfallthrough\n\t\tcase '0', '1':\n\t\t\tbits <<= wid\n\t\t\tbits |= uint64(c - '0')\n\t\tcase 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F':\n\t\t\tif wid != 4 {\n\t\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t\t}\n\t\t\tbits <<= 4\n\t\t\tbits |= uint64(c&^0x20 - 'A' + 10)\n\t\tcase 'y':\n\t\t\tif i+1 < len(p) && (p[i+1] == '0' || p[i+1] == '1') {\n\t\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t\t}\n\t\t\tbits = 0\n\t\tcase '+', '-':\n\t\t\tif c == '+' && result == false {\n\t\t\t\t// Have already seen a -. Should be - from here on.\n\t\t\t\treturn nil, &parseError{\"invalid pattern syntax (+ after -): \" + pattern}\n\t\t\t}\n\t\t\tif i > 0 {\n\t\t\t\tn := (i - start) * wid\n\t\t\t\tif n > 64 {\n\t\t\t\t\treturn nil, &parseError{\"pattern bits too long: \" + pattern}\n\t\t\t\t}\n\t\t\t\tif n <= 0 {\n\t\t\t\t\treturn nil, &parseError{\"invalid pattern syntax: \" + pattern}\n\t\t\t\t}\n\t\t\t\tif p[start] == 'y' {\n\t\t\t\t\tn = 0\n\t\t\t\t}\n\t\t\t\tmask := uint64(1)<<n - 1\n\t\t\t\tm.list = append(m.list, cond{mask, bits, result})\n\t\t\t} else if c == '-' {\n\t\t\t\t// leading - subtracts from complete set\n\t\t\t\tm.list = append(m.list, cond{0, 0, true})\n\t\t\t}\n\t\t\tbits = 0\n\t\t\tresult = c == '+'\n\t\t\tstart = i + 1\n\t\t\twid = 1\n\t\t}\n\t}\n\treturn m, nil\n}\n\n// A Matcher is the parsed, compiled form of a PATTERN string.\n// The nil *Matcher is valid: it has all changes enabled but none reported.\ntype Matcher struct {\n\tverbose bool\n\tenable  bool   // when true, list is for “enable and report” (when false, “disable and report”)\n\tlist    []cond // conditions; later ones win over earlier ones\n}\n\n// A cond is a single condition in the matcher.\n// Given an input id, if id&mask == bits, return the result.\ntype cond struct {\n\tmask   uint64\n\tbits   uint64\n\tresult bool\n}\n\n// Verbose reports whether the reports will be shown to users\n// and need to include a human-readable change description.\n// If not, the target can print just the Marker on a line by itself\n// and perhaps save some computation.\nfunc (m *Matcher) Verbose() bool {\n\treturn m.verbose\n}\n\n// ShouldEnable reports whether the change with the given id should be enabled.\nfunc (m *Matcher) ShouldEnable(id uint64) bool {\n\tif m == nil {\n\t\treturn true\n\t}\n\tfor i := len(m.list) - 1; i >= 0; i-- {\n\t\tc := &m.list[i]\n\t\tif id&c.mask == c.bits {\n\t\t\treturn c.result == m.enable\n\t\t}\n\t}\n\treturn false == m.enable\n}\n\n// ShouldReport reports whether the change with the given id should be reported.\nfunc (m *Matcher) ShouldReport(id uint64) bool {\n\tif m == nil {\n\t\treturn false\n\t}\n\tfor i := len(m.list) - 1; i >= 0; i-- {\n\t\tc := &m.list[i]\n\t\tif id&c.mask == c.bits {\n\t\t\treturn c.result\n\t\t}\n\t}\n\treturn false\n}\n\n// Marker returns the match marker text to use on any line reporting details\n// about a match of the given ID.\n// It always returns the hexadecimal format.\nfunc Marker(id uint64) string {\n\treturn string(AppendMarker(nil, id))\n}\n\n// AppendMarker is like [Marker] but appends the marker to dst.\nfunc AppendMarker(dst []byte, id uint64) []byte {\n\tconst prefix = \"[bisect-match 0x\"\n\tvar buf [len(prefix) + 16 + 1]byte\n\tcopy(buf[:], prefix)\n\tfor i := range 16 {\n\t\tbuf[len(prefix)+i] = \"0123456789abcdef\"[id>>60]\n\t\tid <<= 4\n\t}\n\tbuf[len(prefix)+16] = ']'\n\treturn append(dst, buf[:]...)\n}\n\n// CutMarker finds the first match marker in line and removes it,\n// returning the shortened line (with the marker removed),\n// the ID from the match marker,\n// and whether a marker was found at all.\n// If there is no marker, CutMarker returns line, 0, false.\nfunc CutMarker(line string) (short string, id uint64, ok bool) {\n\t// Find first instance of prefix.\n\tprefix := \"[bisect-match \"\n\ti := 0\n\tfor ; ; i++ {\n\t\tif i >= len(line)-len(prefix) {\n\t\t\treturn line, 0, false\n\t\t}\n\t\tif line[i] == '[' && line[i:i+len(prefix)] == prefix {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Scan to ].\n\tj := i + len(prefix)\n\tfor j < len(line) && line[j] != ']' {\n\t\tj++\n\t}\n\tif j >= len(line) {\n\t\treturn line, 0, false\n\t}\n\n\t// Parse id.\n\tidstr := line[i+len(prefix) : j]\n\tif len(idstr) >= 3 && idstr[:2] == \"0x\" {\n\t\t// parse hex\n\t\tif len(idstr) > 2+16 { // max 0x + 16 digits\n\t\t\treturn line, 0, false\n\t\t}\n\t\tfor i := 2; i < len(idstr); i++ {\n\t\t\tid <<= 4\n\t\t\tswitch c := idstr[i]; {\n\t\t\tcase '0' <= c && c <= '9':\n\t\t\t\tid |= uint64(c - '0')\n\t\t\tcase 'a' <= c && c <= 'f':\n\t\t\t\tid |= uint64(c - 'a' + 10)\n\t\t\tcase 'A' <= c && c <= 'F':\n\t\t\t\tid |= uint64(c - 'A' + 10)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif idstr == \"\" || len(idstr) > 64 { // min 1 digit, max 64 digits\n\t\t\treturn line, 0, false\n\t\t}\n\t\t// parse binary\n\t\tfor i := 0; i < len(idstr); i++ {\n\t\t\tid <<= 1\n\t\t\tswitch c := idstr[i]; c {\n\t\t\tdefault:\n\t\t\t\treturn line, 0, false\n\t\t\tcase '0', '1':\n\t\t\t\tid |= uint64(c - '0')\n\t\t\t}\n\t\t}\n\t}\n\n\t// Construct shortened line.\n\t// Remove at most one space from around the marker,\n\t// so that \"foo [marker] bar\" shortens to \"foo bar\".\n\tj++ // skip ]\n\tif i > 0 && line[i-1] == ' ' {\n\t\ti--\n\t} else if j < len(line) && line[j] == ' ' {\n\t\tj++\n\t}\n\tshort = line[:i] + line[j:]\n\treturn short, id, true\n}\n\n// Hash computes a hash of the data arguments,\n// each of which must be of type string, byte, int, uint, int32, uint32, int64, uint64, uintptr, or a slice of one of those types.\nfunc Hash(data ...any) uint64 {\n\th := offset64\n\tfor _, v := range data {\n\t\tswitch v := v.(type) {\n\t\tdefault:\n\t\t\t// Note: Not printing the type, because reflect.ValueOf(v)\n\t\t\t// would make the interfaces prepared by the caller escape\n\t\t\t// and therefore allocate. This way, Hash(file, line) runs\n\t\t\t// without any allocation. It should be clear from the\n\t\t\t// source code calling Hash what the bad argument was.\n\t\t\tpanic(\"bisect.Hash: unexpected argument type\")\n\t\tcase string:\n\t\t\th = fnvString(h, v)\n\t\tcase byte:\n\t\t\th = fnv(h, v)\n\t\tcase int:\n\t\t\th = fnvUint64(h, uint64(v))\n\t\tcase uint:\n\t\t\th = fnvUint64(h, uint64(v))\n\t\tcase int32:\n\t\t\th = fnvUint32(h, uint32(v))\n\t\tcase uint32:\n\t\t\th = fnvUint32(h, v)\n\t\tcase int64:\n\t\t\th = fnvUint64(h, uint64(v))\n\t\tcase uint64:\n\t\t\th = fnvUint64(h, v)\n\t\tcase uintptr:\n\t\t\th = fnvUint64(h, uint64(v))\n\t\tcase []string:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvString(h, x)\n\t\t\t}\n\t\tcase []byte:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnv(h, x)\n\t\t\t}\n\t\tcase []int:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint64(h, uint64(x))\n\t\t\t}\n\t\tcase []uint:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint64(h, uint64(x))\n\t\t\t}\n\t\tcase []int32:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint32(h, uint32(x))\n\t\t\t}\n\t\tcase []uint32:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint32(h, x)\n\t\t\t}\n\t\tcase []int64:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint64(h, uint64(x))\n\t\t\t}\n\t\tcase []uint64:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint64(h, x)\n\t\t\t}\n\t\tcase []uintptr:\n\t\t\tfor _, x := range v {\n\t\t\t\th = fnvUint64(h, uint64(x))\n\t\t\t}\n\t\t}\n\t}\n\treturn h\n}\n\n// Trivial error implementation, here to avoid importing errors.\n\ntype parseError struct{ text string }\n\nfunc (e *parseError) Error() string { return e.text }\n\n// FNV-1a implementation. See Go's hash/fnv/fnv.go.\n// Copied here for simplicity (can handle uints directly)\n// and to avoid the dependency.\n\nconst (\n\toffset64 uint64 = 14695981039346656037\n\tprime64  uint64 = 1099511628211\n)\n\nfunc fnv(h uint64, x byte) uint64 {\n\th ^= uint64(x)\n\th *= prime64\n\treturn h\n}\n\nfunc fnvString(h uint64, x string) uint64 {\n\tfor i := 0; i < len(x); i++ {\n\t\th ^= uint64(x[i])\n\t\th *= prime64\n\t}\n\treturn h\n}\n\nfunc fnvUint64(h uint64, x uint64) uint64 {\n\tfor range 8 {\n\t\th ^= uint64(x & 0xFF)\n\t\tx >>= 8\n\t\th *= prime64\n\t}\n\treturn h\n}\n\nfunc fnvUint32(h uint64, x uint32) uint64 {\n\tfor range 4 {\n\t\th ^= uint64(x & 0xFF)\n\t\tx >>= 8\n\t\th *= prime64\n\t}\n\treturn h\n}\n"
  },
  {
    "path": "internal/bisect/bisect_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage bisect\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// In order for package bisect to be copied into the standard library\n// and used by very low-level packages such as internal/godebug,\n// it needs to have no imports at all.\nfunc TestNoImports(t *testing.T) {\n\tfiles, err := filepath.Glob(\"*.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, file := range files {\n\t\tif strings.HasSuffix(file, \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\t\tdata, err := os.ReadFile(file)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\tcontinue\n\t\t}\n\t\tif strings.Contains(string(data), \"\\nimport\") {\n\t\t\tt.Errorf(\"%s contains imports; package bisect must not import other packages\", file)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/diff/diff.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package diff computes differences between text files or strings.\npackage diff\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// An Edit describes the replacement of a portion of a text file.\ntype Edit struct {\n\tStart, End int    // byte offsets of the region to replace\n\tNew        string // the replacement\n}\n\nfunc (e Edit) String() string {\n\treturn fmt.Sprintf(\"{Start:%d,End:%d,New:%q}\", e.Start, e.End, e.New)\n}\n\n// Apply applies a sequence of edits to the src buffer and returns the\n// result. Edits are applied in order of start offset; edits with the\n// same start offset are applied in they order they were provided.\n//\n// Apply returns an error if any edit is out of bounds,\n// or if any pair of edits is overlapping.\nfunc Apply(src string, edits []Edit) (string, error) {\n\tedits, size, err := validate(src, edits)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Apply edits.\n\tout := make([]byte, 0, size)\n\tlastEnd := 0\n\tfor _, edit := range edits {\n\t\tif lastEnd < edit.Start {\n\t\t\tout = append(out, src[lastEnd:edit.Start]...)\n\t\t}\n\t\tout = append(out, edit.New...)\n\t\tlastEnd = edit.End\n\t}\n\tout = append(out, src[lastEnd:]...)\n\n\tif len(out) != size {\n\t\tpanic(\"wrong size\")\n\t}\n\n\treturn string(out), nil\n}\n\n// ApplyBytes is like Apply, but it accepts a byte slice.\n// The result is always a new array.\nfunc ApplyBytes(src []byte, edits []Edit) ([]byte, error) {\n\tres, err := Apply(string(src), edits)\n\treturn []byte(res), err\n}\n\n// validate checks that edits are consistent with src,\n// and returns the size of the patched output.\n// It may return a different slice.\nfunc validate(src string, edits []Edit) ([]Edit, int, error) {\n\tif !sort.IsSorted(editsSort(edits)) {\n\t\tedits = slices.Clone(edits)\n\t\tSortEdits(edits)\n\t}\n\n\t// Check validity of edits and compute final size.\n\tsize := len(src)\n\tlastEnd := 0\n\tfor _, edit := range edits {\n\t\tif !(0 <= edit.Start && edit.Start <= edit.End && edit.End <= len(src)) {\n\t\t\treturn nil, 0, fmt.Errorf(\"diff has out-of-bounds edits\")\n\t\t}\n\t\tif edit.Start < lastEnd {\n\t\t\treturn nil, 0, fmt.Errorf(\"diff has overlapping edits\")\n\t\t}\n\t\tsize += len(edit.New) + edit.Start - edit.End\n\t\tlastEnd = edit.End\n\t}\n\n\treturn edits, size, nil\n}\n\n// SortEdits orders a slice of Edits by (start, end) offset.\n// This ordering puts insertions (end = start) before deletions\n// (end > start) at the same point, but uses a stable sort to preserve\n// the order of multiple insertions at the same point.\n// (Apply detects multiple deletions at the same point as an error.)\nfunc SortEdits(edits []Edit) {\n\tsort.Stable(editsSort(edits))\n}\n\ntype editsSort []Edit\n\nfunc (a editsSort) Len() int { return len(a) }\nfunc (a editsSort) Less(i, j int) bool {\n\tif cmp := a[i].Start - a[j].Start; cmp != 0 {\n\t\treturn cmp < 0\n\t}\n\treturn a[i].End < a[j].End\n}\nfunc (a editsSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }\n\n// lineEdits expands and merges a sequence of edits so that each\n// resulting edit replaces one or more complete lines.\n// See ApplyEdits for preconditions.\nfunc lineEdits(src string, edits []Edit) ([]Edit, error) {\n\tedits, _, err := validate(src, edits)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Do all deletions begin and end at the start of a line,\n\t// and all insertions end with a newline?\n\t// (This is merely a fast path.)\n\tfor _, edit := range edits {\n\t\tif edit.Start >= len(src) || // insertion at EOF\n\t\t\tedit.Start > 0 && src[edit.Start-1] != '\\n' || // not at line start\n\t\t\tedit.End > 0 && src[edit.End-1] != '\\n' || // not at line start\n\t\t\tedit.New != \"\" && edit.New[len(edit.New)-1] != '\\n' { // partial insert\n\t\t\tgoto expand // slow path\n\t\t}\n\t}\n\treturn edits, nil // aligned\n\nexpand:\n\tif len(edits) == 0 {\n\t\treturn edits, nil // no edits (unreachable due to fast path)\n\t}\n\texpanded := make([]Edit, 0, len(edits)) // a guess\n\tprev := edits[0]\n\t// TODO(adonovan): opt: start from the first misaligned edit.\n\t// TODO(adonovan): opt: avoid quadratic cost of string += string.\n\tfor _, edit := range edits[1:] {\n\t\tbetween := src[prev.End:edit.Start]\n\t\tif !strings.Contains(between, \"\\n\") {\n\t\t\t// overlapping lines: combine with previous edit.\n\t\t\tprev.New += between + edit.New\n\t\t\tprev.End = edit.End\n\t\t} else {\n\t\t\t// non-overlapping lines: flush previous edit.\n\t\t\texpanded = append(expanded, expandEdit(prev, src))\n\t\t\tprev = edit\n\t\t}\n\t}\n\treturn append(expanded, expandEdit(prev, src)), nil // flush final edit\n}\n\n// expandEdit returns edit expanded to complete whole lines.\nfunc expandEdit(edit Edit, src string) Edit {\n\t// Expand start left to start of line.\n\t// (delta is the zero-based column number of start.)\n\tstart := edit.Start\n\tif delta := start - 1 - strings.LastIndex(src[:start], \"\\n\"); delta > 0 {\n\t\tedit.Start -= delta\n\t\tedit.New = src[start-delta:start] + edit.New\n\t}\n\n\t// Expand end right to end of line.\n\tend := edit.End\n\tif end > 0 && src[end-1] != '\\n' ||\n\t\tedit.New != \"\" && edit.New[len(edit.New)-1] != '\\n' {\n\t\tif nl := strings.IndexByte(src[end:], '\\n'); nl < 0 {\n\t\t\tedit.End = len(src) // extend to EOF\n\t\t} else {\n\t\t\tedit.End = end + nl + 1 // extend beyond \\n\n\t\t}\n\t}\n\tedit.New += src[end:edit.End]\n\n\treturn edit\n}\n"
  },
  {
    "path": "internal/diff/diff_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff_test\n\nimport (\n\t\"bytes\"\n\t\"math/rand\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/diff/difftest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestApply(t *testing.T) {\n\tfor _, tc := range difftest.TestCases {\n\t\tt.Run(tc.Name, func(t *testing.T) {\n\t\t\tgot, err := diff.Apply(tc.In, tc.Edits)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Apply(Edits) failed: %v\", err)\n\t\t\t}\n\t\t\tif got != tc.Out {\n\t\t\t\tt.Errorf(\"Apply(Edits): got %q, want %q\", got, tc.Out)\n\t\t\t}\n\t\t\tif tc.LineEdits != nil {\n\t\t\t\tgot, err := diff.Apply(tc.In, tc.LineEdits)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"Apply(LineEdits) failed: %v\", err)\n\t\t\t\t}\n\t\t\t\tif got != tc.Out {\n\t\t\t\t\tt.Errorf(\"Apply(LineEdits): got %q, want %q\", got, tc.Out)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestNEdits(t *testing.T) {\n\tfor _, tc := range difftest.TestCases {\n\t\tedits := diff.Strings(tc.In, tc.Out)\n\t\tgot, err := diff.Apply(tc.In, edits)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t\t}\n\t\tif got != tc.Out {\n\t\t\tt.Fatalf(\"%s: got %q wanted %q\", tc.Name, got, tc.Out)\n\t\t}\n\t\tif len(edits) < len(tc.Edits) { // should find subline edits\n\t\t\tt.Errorf(\"got %v, expected %v for %#v\", edits, tc.Edits, tc)\n\t\t}\n\t}\n}\n\nfunc TestNRandom(t *testing.T) {\n\trnd := rand.New(rand.NewSource(1))\n\tfor i := range 1000 {\n\t\ta := randstr(rnd, \"abω\", 16)\n\t\tb := randstr(rnd, \"abωc\", 16)\n\t\tedits := diff.Strings(a, b)\n\t\tgot, err := diff.Apply(a, edits)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t\t}\n\t\tif got != b {\n\t\t\tt.Fatalf(\"%d: got %q, wanted %q, starting with %q\", i, got, b, a)\n\t\t}\n\t}\n}\n\n// $ go test -fuzz=FuzzRoundTrip ./internal/diff\nfunc FuzzRoundTrip(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, a, b string) {\n\t\tif !utf8.ValidString(a) || !utf8.ValidString(b) {\n\t\t\treturn // inputs must be text\n\t\t}\n\t\tedits := diff.Strings(a, b)\n\t\tgot, err := diff.Apply(a, edits)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t\t}\n\t\tif got != b {\n\t\t\tt.Fatalf(\"applying diff(%q, %q) gives %q; edits=%v\", a, b, got, edits)\n\t\t}\n\t})\n}\n\nfunc TestLineEdits(t *testing.T) {\n\tfor _, tc := range difftest.TestCases {\n\t\tt.Run(tc.Name, func(t *testing.T) {\n\t\t\twant := tc.LineEdits\n\t\t\tif want == nil {\n\t\t\t\twant = tc.Edits // already line-aligned\n\t\t\t}\n\t\t\tgot, err := diff.LineEdits(tc.In, tc.Edits)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"LineEdits: %v\", err)\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, want) {\n\t\t\t\tt.Errorf(\"in=<<%s>>\\nout=<<%s>>\\nraw  edits=%s\\nline edits=%s\\nwant: %s\",\n\t\t\t\t\ttc.In, tc.Out, tc.Edits, got, want)\n\t\t\t}\n\t\t\t// make sure that applying the edits gives the expected result\n\t\t\tfixed, err := diff.Apply(tc.In, got)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t\tif fixed != tc.Out {\n\t\t\t\tt.Errorf(\"Apply(LineEdits): got %q, want %q\", fixed, tc.Out)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestToUnified(t *testing.T) {\n\ttestenv.NeedsTool(t, \"patch\")\n\tfor _, tc := range difftest.TestCases {\n\t\tt.Run(tc.Name, func(t *testing.T) {\n\t\t\tnedits := diff.Lines(tc.In, tc.Out)\n\t\t\txunified, err := diff.ToUnified(difftest.FileA, difftest.FileB, tc.In, nedits, diff.DefaultContextLines)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif xunified == \"\" {\n\t\t\t\treturn\n\t\t\t}\n\t\t\torig := filepath.Join(t.TempDir(), \"original\")\n\t\t\terr = os.WriteFile(orig, []byte(tc.In), 0644)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\ttemp := filepath.Join(t.TempDir(), \"patched\")\n\t\t\terr = os.WriteFile(temp, []byte(tc.In), 0644)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tcmd := exec.Command(\"patch\", \"-p0\", \"-u\", \"-s\", \"-o\", temp, orig)\n\t\t\tcmd.Stdin = strings.NewReader(xunified)\n\t\t\tcmd.Stdout = new(bytes.Buffer)\n\t\t\tcmd.Stderr = new(bytes.Buffer)\n\t\t\tif err = cmd.Run(); err != nil {\n\t\t\t\tt.Fatalf(\"%v: %q (%q) (%q)\", err, cmd.String(),\n\t\t\t\t\tcmd.Stderr, cmd.Stdout)\n\t\t\t}\n\t\t\tgot, err := os.ReadFile(temp)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif string(got) != tc.Out {\n\t\t\t\tt.Errorf(\"applying unified failed: got\\n%q, wanted\\n%q unified\\n%q\",\n\t\t\t\t\tgot, tc.Out, xunified)\n\t\t\t}\n\n\t\t})\n\t}\n}\n\nfunc TestRegressionOld001(t *testing.T) {\n\ta := \"// Copyright 2019 The Go Authors. All rights reserved.\\n// Use of this source code is governed by a BSD-style\\n// license that can be found in the LICENSE file.\\n\\npackage diff_test\\n\\nimport (\\n\\t\\\"fmt\\\"\\n\\t\\\"math/rand\\\"\\n\\t\\\"strings\\\"\\n\\t\\\"testing\\\"\\n\\n\\t\\\"golang.org/x/tools/gopls/internal/lsp/diff\\\"\\n\\t\\\"golang.org/x/tools/internal/diff/difftest\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/span\\\"\\n)\\n\"\n\n\tb := \"// Copyright 2019 The Go Authors. All rights reserved.\\n// Use of this source code is governed by a BSD-style\\n// license that can be found in the LICENSE file.\\n\\npackage diff_test\\n\\nimport (\\n\\t\\\"fmt\\\"\\n\\t\\\"math/rand\\\"\\n\\t\\\"strings\\\"\\n\\t\\\"testing\\\"\\n\\n\\t\\\"github.com/google/safehtml/template\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/lsp/diff\\\"\\n\\t\\\"golang.org/x/tools/internal/diff/difftest\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/span\\\"\\n)\\n\"\n\tdiffs := diff.Strings(a, b)\n\tgot, err := diff.Apply(a, diffs)\n\tif err != nil {\n\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t}\n\tif got != b {\n\t\ti := 0\n\t\tfor ; i < len(a) && i < len(b) && got[i] == b[i]; i++ {\n\t\t}\n\t\tt.Errorf(\"oops %vd\\n%q\\n%q\", diffs, got, b)\n\t\tt.Errorf(\"\\n%q\\n%q\", got[i:], b[i:])\n\t}\n}\n\nfunc TestRegressionOld002(t *testing.T) {\n\ta := \"n\\\"\\n)\\n\"\n\tb := \"n\\\"\\n\\t\\\"golang.org/x//nnal/stack\\\"\\n)\\n\"\n\tdiffs := diff.Strings(a, b)\n\tgot, err := diff.Apply(a, diffs)\n\tif err != nil {\n\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t}\n\tif got != b {\n\t\ti := 0\n\t\tfor ; i < len(a) && i < len(b) && got[i] == b[i]; i++ {\n\t\t}\n\t\tt.Errorf(\"oops %vd\\n%q\\n%q\", diffs, got, b)\n\t\tt.Errorf(\"\\n%q\\n%q\", got[i:], b[i:])\n\t}\n}\n\n// return a random string of length n made of characters from s\nfunc randstr(rnd *rand.Rand, s string, n int) string {\n\tsrc := []rune(s)\n\tx := make([]rune, n)\n\tfor i := range n {\n\t\tx[i] = src[rnd.Intn(len(src))]\n\t}\n\treturn string(x)\n}\n"
  },
  {
    "path": "internal/diff/difftest/difftest.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package difftest supplies a set of tests that will operate on any\n// implementation of a diff algorithm as exposed by\n// \"golang.org/x/tools/internal/diff\"\npackage difftest\n\n// There are two kinds of tests, semantic tests, and 'golden data' tests.\n// The semantic tests check that the computed diffs transform the input to\n// the output, and that 'patch' accepts the computed unified diffs.\n// The other tests just check that Edits and LineEdits haven't changed\n// unexpectedly. These fields may need to be changed when the diff algorithm\n// changes.\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/diff\"\n)\n\nconst (\n\tFileA         = \"from\"\n\tFileB         = \"to\"\n\tUnifiedPrefix = \"--- \" + FileA + \"\\n+++ \" + FileB + \"\\n\"\n)\n\nvar TestCases = []struct {\n\tName, In, Out, Unified string\n\tEdits, LineEdits       []diff.Edit // expectation (LineEdits=nil => already line-aligned)\n\tNoDiff                 bool\n}{{\n\tName: \"empty\",\n\tIn:   \"\",\n\tOut:  \"\",\n}, {\n\tName: \"no_diff\",\n\tIn:   \"gargantuan\\n\",\n\tOut:  \"gargantuan\\n\",\n}, {\n\tName: \"replace_all\",\n\tIn:   \"fruit\\n\",\n\tOut:  \"cheese\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-fruit\n+cheese\n`[1:],\n\tEdits:     []diff.Edit{{Start: 0, End: 5, New: \"cheese\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 6, New: \"cheese\\n\"}},\n}, {\n\tName: \"insert_rune\",\n\tIn:   \"gord\\n\",\n\tOut:  \"gourd\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-gord\n+gourd\n`[1:],\n\tEdits:     []diff.Edit{{Start: 2, End: 2, New: \"u\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 5, New: \"gourd\\n\"}},\n}, {\n\tName: \"delete_rune\",\n\tIn:   \"groat\\n\",\n\tOut:  \"goat\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-groat\n+goat\n`[1:],\n\tEdits:     []diff.Edit{{Start: 1, End: 2, New: \"\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 6, New: \"goat\\n\"}},\n}, {\n\tName: \"replace_rune\",\n\tIn:   \"loud\\n\",\n\tOut:  \"lord\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-loud\n+lord\n`[1:],\n\tEdits:     []diff.Edit{{Start: 2, End: 3, New: \"r\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 5, New: \"lord\\n\"}},\n}, {\n\tName: \"replace_partials\",\n\tIn:   \"blanket\\n\",\n\tOut:  \"bunker\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-blanket\n+bunker\n`[1:],\n\tEdits: []diff.Edit{\n\t\t{Start: 1, End: 3, New: \"u\"},\n\t\t{Start: 6, End: 7, New: \"r\"},\n\t},\n\tLineEdits: []diff.Edit{{Start: 0, End: 8, New: \"bunker\\n\"}},\n}, {\n\tName: \"insert_line\",\n\tIn:   \"1: one\\n3: three\\n\",\n\tOut:  \"1: one\\n2: two\\n3: three\\n\",\n\tUnified: UnifiedPrefix + `\n@@ -1,2 +1,3 @@\n 1: one\n+2: two\n 3: three\n`[1:],\n\tEdits: []diff.Edit{{Start: 7, End: 7, New: \"2: two\\n\"}},\n}, {\n\tName: \"replace_no_newline\",\n\tIn:   \"A\",\n\tOut:  \"B\",\n\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-A\n\\ No newline at end of file\n+B\n\\ No newline at end of file\n`[1:],\n\tEdits: []diff.Edit{{Start: 0, End: 1, New: \"B\"}},\n}, {\n\tName: \"delete_empty\",\n\tIn:   \"meow\",\n\tOut:  \"\", // GNU diff -u special case: +0,0\n\tUnified: UnifiedPrefix + `\n@@ -1 +0,0 @@\n-meow\n\\ No newline at end of file\n`[1:],\n\tEdits:     []diff.Edit{{Start: 0, End: 4, New: \"\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 4, New: \"\"}},\n}, {\n\tName: \"append_empty\",\n\tIn:   \"\", // GNU diff -u special case: -0,0\n\tOut:  \"AB\\nC\",\n\tUnified: UnifiedPrefix + `\n@@ -0,0 +1,2 @@\n+AB\n+C\n\\ No newline at end of file\n`[1:],\n\tEdits:     []diff.Edit{{Start: 0, End: 0, New: \"AB\\nC\"}},\n\tLineEdits: []diff.Edit{{Start: 0, End: 0, New: \"AB\\nC\"}},\n},\n\t// TODO(adonovan): fix this test: GNU diff -u prints \"+1,2\", Unifies prints \"+1,3\".\n\t// \t{\n\t// \t\tName: \"add_start\",\n\t// \t\tIn:   \"A\",\n\t// \t\tOut:  \"B\\nCA\",\n\t// \t\tUnified: UnifiedPrefix + `\n\t// @@ -1 +1,2 @@\n\t// -A\n\t// \\ No newline at end of file\n\t// +B\n\t// +CA\n\t// \\ No newline at end of file\n\t// `[1:],\n\t// \t\tEdits:     []diff.TextEdit{{Span: newSpan(0, 0), NewText: \"B\\nC\"}},\n\t// \t\tLineEdits: []diff.TextEdit{{Span: newSpan(0, 0), NewText: \"B\\nC\"}},\n\t// \t},\n\t{\n\t\tName: \"add_end\",\n\t\tIn:   \"A\",\n\t\tOut:  \"AB\",\n\t\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-A\n\\ No newline at end of file\n+AB\n\\ No newline at end of file\n`[1:],\n\t\tEdits:     []diff.Edit{{Start: 1, End: 1, New: \"B\"}},\n\t\tLineEdits: []diff.Edit{{Start: 0, End: 1, New: \"AB\"}},\n\t}, {\n\t\tName: \"add_empty\",\n\t\tIn:   \"\",\n\t\tOut:  \"AB\\nC\",\n\t\tUnified: UnifiedPrefix + `\n@@ -0,0 +1,2 @@\n+AB\n+C\n\\ No newline at end of file\n`[1:],\n\t\tEdits:     []diff.Edit{{Start: 0, End: 0, New: \"AB\\nC\"}},\n\t\tLineEdits: []diff.Edit{{Start: 0, End: 0, New: \"AB\\nC\"}},\n\t}, {\n\t\tName: \"add_newline\",\n\t\tIn:   \"A\",\n\t\tOut:  \"A\\n\",\n\t\tUnified: UnifiedPrefix + `\n@@ -1 +1 @@\n-A\n\\ No newline at end of file\n+A\n`[1:],\n\t\tEdits:     []diff.Edit{{Start: 1, End: 1, New: \"\\n\"}},\n\t\tLineEdits: []diff.Edit{{Start: 0, End: 1, New: \"A\\n\"}},\n\t}, {\n\t\tName: \"delete_front\",\n\t\tIn:   \"A\\nB\\nC\\nA\\nB\\nB\\nA\\n\",\n\t\tOut:  \"C\\nB\\nA\\nB\\nA\\nC\\n\",\n\t\tUnified: UnifiedPrefix + `\n@@ -1,7 +1,6 @@\n-A\n+C\nB\n-C\nA\n-B\nB\nA\n+C\n`[1:],\n\t\tNoDiff: true, // unified diff is different but valid\n\t\tEdits: []diff.Edit{\n\t\t\t{Start: 0, End: 2, New: \"C\\n\"},\n\t\t\t{Start: 4, End: 6, New: \"\"},\n\t\t\t{Start: 8, End: 10, New: \"\"},\n\t\t\t{Start: 14, End: 14, New: \"C\\n\"},\n\t\t},\n\t\tLineEdits: []diff.Edit{\n\t\t\t{Start: 0, End: 2, New: \"C\\n\"},\n\t\t\t{Start: 4, End: 6, New: \"\"},\n\t\t\t{Start: 8, End: 10, New: \"\"},\n\t\t\t{Start: 14, End: 14, New: \"C\\n\"},\n\t\t},\n\t}, {\n\t\tName: \"replace_last_line\",\n\t\tIn:   \"A\\nB\\n\",\n\t\tOut:  \"A\\nC\\n\\n\",\n\t\tUnified: UnifiedPrefix + `\n@@ -1,2 +1,3 @@\n A\n-B\n+C\n+\n`[1:],\n\t\tEdits:     []diff.Edit{{Start: 2, End: 3, New: \"C\\n\"}},\n\t\tLineEdits: []diff.Edit{{Start: 2, End: 4, New: \"C\\n\\n\"}},\n\t},\n\t{\n\t\tName: \"multiple_replace\",\n\t\tIn:   \"A\\nB\\nC\\nD\\nE\\nF\\nG\\n\",\n\t\tOut:  \"A\\nH\\nI\\nJ\\nE\\nF\\nK\\n\",\n\t\tUnified: UnifiedPrefix + `\n@@ -1,7 +1,7 @@\n A\n-B\n-C\n-D\n+H\n+I\n+J\n E\n F\n-G\n+K\n`[1:],\n\t\tEdits: []diff.Edit{\n\t\t\t{Start: 2, End: 8, New: \"H\\nI\\nJ\\n\"},\n\t\t\t{Start: 12, End: 14, New: \"K\\n\"},\n\t\t},\n\t\tNoDiff: true, // diff algorithm produces different delete/insert pattern\n\t},\n\t{\n\t\tName:  \"extra_newline\",\n\t\tIn:    \"\\nA\\n\",\n\t\tOut:   \"A\\n\",\n\t\tEdits: []diff.Edit{{Start: 0, End: 1, New: \"\"}},\n\t\tUnified: UnifiedPrefix + `@@ -1,2 +1 @@\n-\n A\n`,\n\t}, {\n\t\tName:      \"unified_lines\",\n\t\tIn:        \"aaa\\nccc\\n\",\n\t\tOut:       \"aaa\\nbbb\\nccc\\n\",\n\t\tEdits:     []diff.Edit{{Start: 4, End: 4, New: \"bbb\\n\"}},\n\t\tLineEdits: []diff.Edit{{Start: 4, End: 4, New: \"bbb\\n\"}},\n\t\tUnified:   UnifiedPrefix + \"@@ -1,2 +1,3 @@\\n aaa\\n+bbb\\n ccc\\n\",\n\t}, {\n\t\tName: \"60379\",\n\t\tIn: `package a\n\ntype S struct {\ns fmt.Stringer\n}\n`,\n\t\tOut: `package a\n\ntype S struct {\n\ts fmt.Stringer\n}\n`,\n\t\tEdits:     []diff.Edit{{Start: 27, End: 27, New: \"\\t\"}},\n\t\tLineEdits: []diff.Edit{{Start: 27, End: 42, New: \"\\ts fmt.Stringer\\n\"}},\n\t\tUnified:   UnifiedPrefix + \"@@ -1,5 +1,5 @@\\n package a\\n \\n type S struct {\\n-s fmt.Stringer\\n+\\ts fmt.Stringer\\n }\\n\",\n\t},\n}\n\nfunc DiffTest(t *testing.T, compute func(before, after string) []diff.Edit) {\n\tfor _, test := range TestCases {\n\t\tt.Run(test.Name, func(t *testing.T) {\n\t\t\tedits := compute(test.In, test.Out)\n\t\t\tgot, err := diff.Apply(test.In, edits)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Apply failed: %v\", err)\n\t\t\t}\n\t\t\tunified, err := diff.ToUnified(FileA, FileB, test.In, edits, diff.DefaultContextLines)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"ToUnified: %v\", err)\n\t\t\t}\n\t\t\tif got != test.Out {\n\t\t\t\tt.Errorf(\"Apply: got patched:\\n%v\\nfrom diff:\\n%v\\nexpected:\\n%v\",\n\t\t\t\t\tgot, unified, test.Out)\n\t\t\t}\n\t\t\tif !test.NoDiff && unified != test.Unified {\n\t\t\t\tt.Errorf(\"Unified: got diff:\\n%q\\nexpected:\\n%q diffs:%v\",\n\t\t\t\t\tunified, test.Unified, edits)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/diff/difftest/difftest_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package difftest supplies a set of tests that will operate on any\n// implementation of a diff algorithm as exposed by\n// \"golang.org/x/tools/internal/diff\"\npackage difftest_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/diff/difftest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// check that the TestCases match diff -u output\nfunc TestVerifyUnified(t *testing.T) {\n\ttestenv.NeedsTool(t, \"diff\")\n\tfor _, test := range difftest.TestCases {\n\t\tt.Run(test.Name, func(t *testing.T) {\n\t\t\tif test.NoDiff {\n\t\t\t\tt.Skip(\"diff tool produces expected different results\")\n\t\t\t}\n\t\t\tdiff, err := getDiffOutput(test.In, test.Out)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(diff) > 0 {\n\t\t\t\tdiff = difftest.UnifiedPrefix + diff\n\t\t\t}\n\t\t\tif diff != test.Unified {\n\t\t\t\tt.Errorf(\"unified:\\n%s\\ndiff -u:\\n%s\", test.Unified, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc getDiffOutput(a, b string) (string, error) {\n\tfileA, err := os.CreateTemp(\"\", \"myers.in\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer os.Remove(fileA.Name())\n\tif _, err := fileA.Write([]byte(a)); err != nil {\n\t\treturn \"\", err\n\t}\n\tif err := fileA.Close(); err != nil {\n\t\treturn \"\", err\n\t}\n\tfileB, err := os.CreateTemp(\"\", \"myers.in\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer os.Remove(fileB.Name())\n\tif _, err := fileB.Write([]byte(b)); err != nil {\n\t\treturn \"\", err\n\t}\n\tif err := fileB.Close(); err != nil {\n\t\treturn \"\", err\n\t}\n\tcmd := exec.Command(\"diff\", \"-u\", fileA.Name(), fileB.Name())\n\tcmd.Env = append(cmd.Env, \"LANG=en_US.UTF-8\")\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\texit, ok := err.(*exec.ExitError)\n\t\tif !ok {\n\t\t\treturn \"\", fmt.Errorf(\"can't exec %s: %v\", cmd, err)\n\t\t}\n\t\tif len(out) == 0 {\n\t\t\t// Nonzero exit with no output: terminated by signal?\n\t\t\treturn \"\", fmt.Errorf(\"%s failed: %v; stderr:\\n%s\", cmd, err, exit.Stderr)\n\t\t}\n\t\t// nonzero exit + output => files differ\n\t}\n\tdiff := string(out)\n\tif len(diff) <= 0 {\n\t\treturn diff, nil\n\t}\n\tbits := strings.SplitN(diff, \"\\n\", 3)\n\tif len(bits) != 3 {\n\t\treturn \"\", fmt.Errorf(\"diff output did not have file prefix:\\n%s\", diff)\n\t}\n\treturn bits[2], nil\n}\n"
  },
  {
    "path": "internal/diff/export_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff\n\n// This file exports some private declarations to tests.\n\nvar LineEdits = lineEdits\n"
  },
  {
    "path": "internal/diff/lcs/common.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\nimport (\n\t\"log\"\n\t\"sort\"\n)\n\n// lcs is a longest common sequence\ntype lcs []diag\n\n// A diag is a piece of the edit graph where A[X+i] == B[Y+i], for 0<=i<Len.\n// All computed diagonals are parts of a longest common subsequence.\ntype diag struct {\n\tX, Y int\n\tLen  int\n}\n\n// sort sorts in place, by lowest X, and if tied, inversely by Len\nfunc (l lcs) sort() lcs {\n\tsort.Slice(l, func(i, j int) bool {\n\t\tif l[i].X != l[j].X {\n\t\t\treturn l[i].X < l[j].X\n\t\t}\n\t\treturn l[i].Len > l[j].Len\n\t})\n\treturn l\n}\n\n// validate that the elements of the lcs do not overlap\n// (can only happen when the two-sided algorithm ends early)\n// expects the lcs to be sorted\nfunc (l lcs) valid() bool {\n\tfor i := 1; i < len(l); i++ {\n\t\tif l[i-1].X+l[i-1].Len > l[i].X {\n\t\t\treturn false\n\t\t}\n\t\tif l[i-1].Y+l[i-1].Len > l[i].Y {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// repair overlapping lcs\n// only called if two-sided stops early\nfunc (l lcs) fix() lcs {\n\t// from the set of diagonals in l, find a maximal non-conflicting set\n\t// this problem may be NP-complete, but we use a greedy heuristic,\n\t// which is quadratic, but with a better data structure, could be D log D.\n\t// independent is not enough: {0,3,1} and {3,0,2} can't both occur in an lcs\n\t// which has to have monotone x and y\n\tif len(l) == 0 {\n\t\treturn nil\n\t}\n\tsort.Slice(l, func(i, j int) bool { return l[i].Len > l[j].Len })\n\ttmp := make(lcs, 0, len(l))\n\ttmp = append(tmp, l[0])\n\tfor i := 1; i < len(l); i++ {\n\t\tvar dir direction\n\t\tnxt := l[i]\n\t\tfor _, in := range tmp {\n\t\t\tif dir, nxt = overlap(in, nxt); dir == empty || dir == bad {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif nxt.Len > 0 && dir != bad {\n\t\t\ttmp = append(tmp, nxt)\n\t\t}\n\t}\n\ttmp.sort()\n\tif false && !tmp.valid() { // debug checking\n\t\tlog.Fatalf(\"here %d\", len(tmp))\n\t}\n\treturn tmp\n}\n\ntype direction int\n\nconst (\n\tempty    direction = iota // diag is empty (so not in lcs)\n\tleftdown                  // proposed acceptably to the left and below\n\trightup                   // proposed diag is acceptably to the right and above\n\tbad                       // proposed diag is inconsistent with the lcs so far\n)\n\n// overlap trims the proposed diag prop  so it doesn't overlap with\n// the existing diag that has already been added to the lcs.\nfunc overlap(exist, prop diag) (direction, diag) {\n\tif prop.X <= exist.X && exist.X < prop.X+prop.Len {\n\t\t// remove the end of prop where it overlaps with the X end of exist\n\t\tdelta := prop.X + prop.Len - exist.X\n\t\tprop.Len -= delta\n\t\tif prop.Len <= 0 {\n\t\t\treturn empty, prop\n\t\t}\n\t}\n\tif exist.X <= prop.X && prop.X < exist.X+exist.Len {\n\t\t// remove the beginning of prop where overlaps with exist\n\t\tdelta := exist.X + exist.Len - prop.X\n\t\tprop.Len -= delta\n\t\tif prop.Len <= 0 {\n\t\t\treturn empty, prop\n\t\t}\n\t\tprop.X += delta\n\t\tprop.Y += delta\n\t}\n\tif prop.Y <= exist.Y && exist.Y < prop.Y+prop.Len {\n\t\t// remove the end of prop that overlaps (in Y) with exist\n\t\tdelta := prop.Y + prop.Len - exist.Y\n\t\tprop.Len -= delta\n\t\tif prop.Len <= 0 {\n\t\t\treturn empty, prop\n\t\t}\n\t}\n\tif exist.Y <= prop.Y && prop.Y < exist.Y+exist.Len {\n\t\t// remove the beginning of peop that overlaps with exist\n\t\tdelta := exist.Y + exist.Len - prop.Y\n\t\tprop.Len -= delta\n\t\tif prop.Len <= 0 {\n\t\t\treturn empty, prop\n\t\t}\n\t\tprop.X += delta // no test reaches this code\n\t\tprop.Y += delta\n\t}\n\tif prop.X+prop.Len <= exist.X && prop.Y+prop.Len <= exist.Y {\n\t\treturn leftdown, prop\n\t}\n\tif exist.X+exist.Len <= prop.X && exist.Y+exist.Len <= prop.Y {\n\t\treturn rightup, prop\n\t}\n\t// prop can't be in an lcs that contains exist\n\treturn bad, prop\n}\n\n// manipulating Diag and lcs\n\n// prepend a diagonal (x,y)-(x+1,y+1) segment either to an empty lcs\n// or to its first Diag. prepend is only called to extend diagonals\n// the backward direction.\nfunc (lcs lcs) prepend(x, y int) lcs {\n\tif len(lcs) > 0 {\n\t\td := &lcs[0]\n\t\tif int(d.X) == x+1 && int(d.Y) == y+1 {\n\t\t\t// extend the diagonal down and to the left\n\t\t\td.X, d.Y = int(x), int(y)\n\t\t\td.Len++\n\t\t\treturn lcs\n\t\t}\n\t}\n\n\tr := diag{X: int(x), Y: int(y), Len: 1}\n\tlcs = append([]diag{r}, lcs...)\n\treturn lcs\n}\n\n// append appends a diagonal, or extends the existing one.\n// by adding the edge (x,y)-(x+1.y+1). append is only called\n// to extend diagonals in the forward direction.\nfunc (lcs lcs) append(x, y int) lcs {\n\tif len(lcs) > 0 {\n\t\tlast := &lcs[len(lcs)-1]\n\t\t// Expand last element if adjoining.\n\t\tif last.X+last.Len == x && last.Y+last.Len == y {\n\t\t\tlast.Len++\n\t\t\treturn lcs\n\t\t}\n\t}\n\n\treturn append(lcs, diag{X: x, Y: y, Len: 1})\n}\n\n// enforce constraint on d, k\nfunc ok(d, k int) bool {\n\treturn d >= 0 && -d <= k && k <= d\n}\n"
  },
  {
    "path": "internal/diff/lcs/common_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\nimport (\n\t\"log\"\n\t\"math/rand/v2\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n)\n\ntype Btest struct {\n\ta, b string\n\tlcs  []string\n}\n\nvar Btests = []Btest{\n\t{\"aaabab\", \"abaab\", []string{\"abab\", \"aaab\"}},\n\t{\"aabbba\", \"baaba\", []string{\"aaba\"}},\n\t{\"cabbx\", \"cbabx\", []string{\"cabx\", \"cbbx\"}},\n\t{\"c\", \"cb\", []string{\"c\"}},\n\t{\"aaba\", \"bbb\", []string{\"b\"}},\n\t{\"bbaabb\", \"b\", []string{\"b\"}},\n\t{\"baaabb\", \"bbaba\", []string{\"bbb\", \"baa\", \"bab\"}},\n\t{\"baaabb\", \"abbab\", []string{\"abb\", \"bab\", \"aab\"}},\n\t{\"baaba\", \"aaabba\", []string{\"aaba\"}},\n\t{\"ca\", \"cba\", []string{\"ca\"}},\n\t{\"ccbcbc\", \"abba\", []string{\"bb\"}},\n\t{\"ccbcbc\", \"aabba\", []string{\"bb\"}},\n\t{\"ccb\", \"cba\", []string{\"cb\"}},\n\t{\"caef\", \"axe\", []string{\"ae\"}},\n\t{\"bbaabb\", \"baabb\", []string{\"baabb\"}},\n\t// Example from Myers:\n\t{\"abcabba\", \"cbabac\", []string{\"caba\", \"baba\", \"cbba\"}},\n\t{\"3456aaa\", \"aaa\", []string{\"aaa\"}},\n\t{\"aaa\", \"aaa123\", []string{\"aaa\"}},\n\t{\"aabaa\", \"aacaa\", []string{\"aaaa\"}},\n\t{\"1a\", \"a\", []string{\"a\"}},\n\t{\"abab\", \"bb\", []string{\"bb\"}},\n\t{\"123\", \"ab\", []string{\"\"}},\n\t{\"a\", \"b\", []string{\"\"}},\n\t{\"abc\", \"123\", []string{\"\"}},\n\t{\"aa\", \"aa\", []string{\"aa\"}},\n\t{\"abcde\", \"12345\", []string{\"\"}},\n\t{\"aaa3456\", \"aaa\", []string{\"aaa\"}},\n\t{\"abcde\", \"12345a\", []string{\"a\"}},\n\t{\"ab\", \"123\", []string{\"\"}},\n\t{\"1a2\", \"a\", []string{\"a\"}},\n\t// for two-sided\n\t{\"babaab\", \"cccaba\", []string{\"aba\"}},\n\t{\"aabbab\", \"cbcabc\", []string{\"bab\"}},\n\t{\"abaabb\", \"bcacab\", []string{\"baab\"}},\n\t{\"abaabb\", \"abaaaa\", []string{\"abaa\"}},\n\t{\"bababb\", \"baaabb\", []string{\"baabb\"}},\n\t{\"abbbaa\", \"cabacc\", []string{\"aba\"}},\n\t{\"aabbaa\", \"aacaba\", []string{\"aaaa\", \"aaba\"}},\n}\n\ntype stringSeqs struct{ a, b string }\n\nfunc (s stringSeqs) lengths() (int, int) { return len(s.a), len(s.b) }\nfunc (s stringSeqs) commonPrefixLen(ai, aj, bi, bj int) int {\n\treturn commonPrefixLenString(s.a[ai:aj], s.b[bi:bj])\n}\nfunc (s stringSeqs) commonSuffixLen(ai, aj, bi, bj int) int {\n\treturn commonSuffixLenString(s.a[ai:aj], s.b[bi:bj])\n}\n\nfunc commonPrefixLenString(a, b string) int {\n\tn := min(len(a), len(b))\n\ti := 0\n\tfor i < n && a[i] == b[i] {\n\t\ti++\n\t}\n\treturn i\n}\nfunc commonSuffixLenString(a, b string) int {\n\tn := min(len(a), len(b))\n\ti := 0\n\tfor i < n && a[len(a)-1-i] == b[len(b)-1-i] {\n\t\ti++\n\t}\n\treturn i\n}\n\nfunc init() {\n\tlog.SetFlags(log.Lshortfile)\n}\n\nfunc check(t *testing.T, str string, lcs lcs, want []string) {\n\tt.Helper()\n\tif !lcs.valid() {\n\t\tt.Errorf(\"bad lcs %v\", lcs)\n\t}\n\tvar got strings.Builder\n\tfor _, dd := range lcs {\n\t\tgot.WriteString(str[dd.X : dd.X+dd.Len])\n\t}\n\tans := got.String()\n\tif slices.Contains(want, ans) {\n\t\treturn\n\t}\n\tt.Fatalf(\"str=%q lcs=%v want=%q got=%q\", str, lcs, want, ans)\n}\n\nfunc checkDiffs(t *testing.T, before string, diffs []Diff, after string) {\n\tt.Helper()\n\tvar ans strings.Builder\n\tsofar := 0 // index of position in before\n\tfor _, d := range diffs {\n\t\tif sofar < d.Start {\n\t\t\tans.WriteString(before[sofar:d.Start])\n\t\t}\n\t\tans.WriteString(after[d.ReplStart:d.ReplEnd])\n\t\tsofar = d.End\n\t}\n\tans.WriteString(before[sofar:])\n\tif ans.String() != after {\n\t\tt.Fatalf(\"diff %v took %q to %q, not to %q\", diffs, before, ans.String(), after)\n\t}\n}\n\nfunc lcslen(l lcs) int {\n\tans := 0\n\tfor _, d := range l {\n\t\tans += int(d.Len)\n\t}\n\treturn ans\n}\n\n// return a random string of length n made of characters from s\nfunc randstr(rng *rand.Rand, s string, n int) string {\n\tsrc := []rune(s)\n\tx := make([]rune, n)\n\tfor i := range n {\n\t\tx[i] = src[rng.Int64N(int64(len(src)))]\n\t}\n\treturn string(x)\n}\n\nfunc TestLcsFix(t *testing.T) {\n\ttests := []struct{ before, after lcs }{\n\t\t{lcs{diag{0, 0, 3}, diag{2, 2, 5}, diag{3, 4, 5}, diag{8, 9, 4}}, lcs{diag{0, 0, 2}, diag{2, 2, 1}, diag{3, 4, 5}, diag{8, 9, 4}}},\n\t\t{lcs{diag{1, 1, 6}, diag{6, 12, 3}}, lcs{diag{1, 1, 5}, diag{6, 12, 3}}},\n\t\t{lcs{diag{0, 0, 4}, diag{3, 5, 4}}, lcs{diag{0, 0, 3}, diag{3, 5, 4}}},\n\t\t{lcs{diag{0, 20, 1}, diag{0, 0, 3}, diag{1, 20, 4}}, lcs{diag{0, 0, 3}, diag{3, 22, 2}}},\n\t\t{lcs{diag{0, 0, 4}, diag{1, 1, 2}}, lcs{diag{0, 0, 4}}},\n\t\t{lcs{diag{0, 0, 4}}, lcs{diag{0, 0, 4}}},\n\t\t{lcs{}, lcs{}},\n\t\t{lcs{diag{0, 0, 4}, diag{1, 1, 6}, diag{3, 3, 2}}, lcs{diag{0, 0, 1}, diag{1, 1, 6}}},\n\t}\n\tfor n, x := range tests {\n\t\tgot := x.before.fix()\n\t\tif len(got) != len(x.after) {\n\t\t\tt.Errorf(\"got %v, expected %v, for %v\", got, x.after, x.before)\n\t\t}\n\t\tolen := lcslen(x.after)\n\t\tglen := lcslen(got)\n\t\tif olen != glen {\n\t\t\tt.Errorf(\"%d: lens(%d,%d) differ, %v, %v, %v\", n, glen, olen, got, x.after, x.before)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/diff/lcs/doc.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// package lcs contains code to find longest-common-subsequences\n// (and diffs)\npackage lcs\n\n/*\nCompute longest-common-subsequences of two slices A, B using\nalgorithms from Myers' paper. A longest-common-subsequence\n(LCS from now on) of A and B is a maximal set of lexically increasing\npairs of subscripts (x,y) with A[x]==B[y]. There may be many LCS, but\nthey all have the same length. An LCS determines a sequence of edits\nthat changes A into B.\n\nThe key concept is the edit graph of A and B.\nIf A has length N and B has length M, then the edit graph has\nvertices v[i][j] for 0 <= i <= N, 0 <= j <= M. There is a\nhorizontal edge from v[i][j] to v[i+1][j] whenever both are in\nthe graph, and a vertical edge from v[i][j] to f[i][j+1] similarly.\nWhen A[i] == B[j] there is a diagonal edge from v[i][j] to v[i+1][j+1].\n\nA path between in the graph between (0,0) and (N,M) determines a sequence\nof edits converting A into B: each horizontal edge corresponds to removing\nan element of A, and each vertical edge corresponds to inserting an\nelement of B.\n\nA vertex (x,y) is on (forward) diagonal k if x-y=k. A path in the graph\nis of length D if it has D non-diagonal edges. The algorithms generate\nforward paths (in which at least one of x,y increases at each edge),\nor backward paths (in which at least one of x,y decreases at each edge),\nor a combination. (Note that the orientation is the traditional mathematical one,\nwith the origin in the lower-left corner.)\n\nHere is the edit graph for A:\"aabbaa\", B:\"aacaba\". (I know the diagonals look weird.)\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   b      |             |             |   ___/‾‾‾   |   ___/‾‾‾   |             |             |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   c      |             |             |             |             |             |             |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n                 a             a             b             b             a             a\n\n\nThe algorithm labels a vertex (x,y) with D,k if it is on diagonal k and at\nthe end of a maximal path of length D. (Because x-y=k it suffices to remember\nonly the x coordinate of the vertex.)\n\nThe forward algorithm: Find the longest diagonal starting at (0,0) and\nlabel its end with D=0,k=0. From that vertex take a vertical step and\nthen follow the longest diagonal (up and to the right), and label that vertex\nwith D=1,k=-1. From the D=0,k=0 point take a horizontal step and the follow\nthe longest diagonal (up and to the right) and label that vertex\nD=1,k=1. In the same way, having labelled all the D vertices,\nfrom a vertex labelled D,k find two vertices\ntentatively labelled D+1,k-1 and D+1,k+1. There may be two on the same\ndiagonal, in which case take the one with the larger x.\n\nEventually the path gets to (N,M), and the diagonals on it are the LCS.\n\nHere is the edit graph with the ends of D-paths labelled. (So, for instance,\n0/2,2 indicates that x=2,y=2 is labelled with 0, as it should be, since the first\nstep is to go up the longest diagonal from (0,0).)\nA:\"aabbaa\", B:\"aacaba\"\n          ⊙   -------   ⊙   -------   ⊙   -------(3/3,6)-------   ⊙   -------(3/5,6)-------(4/6,6)\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------(2/3,5)-------   ⊙   -------   ⊙   -------   ⊙\n   b      |             |             |   ___/‾‾‾   |   ___/‾‾‾   |             |             |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------(3/5,4)-------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------(1/2,3)-------(2/3,3)-------   ⊙   -------   ⊙   -------   ⊙\n   c      |             |             |             |             |             |             |\n          ⊙   -------   ⊙   -------(0/2,2)-------(1/3,2)-------(2/4,2)-------(3/5,2)-------(4/6,2)\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n   a      |   ___/‾‾‾   |   ___/‾‾‾   |             |             |   ___/‾‾‾   |   ___/‾‾‾   |\n          ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙   -------   ⊙\n                 a             a             b             b             a             a\n\nThe 4-path is reconstructed starting at (4/6,6), horizontal to (3/5,6), diagonal to (3,4), vertical\nto (2/3,3), horizontal to (1/2,3), vertical to (0/2,2), and diagonal to (0,0). As expected,\nthere are 4 non-diagonal steps, and the diagonals form an LCS.\n\nThere is a symmetric backward algorithm, which gives (backwards labels are prefixed with a colon):\nA:\"aabbaa\", B:\"aacaba\"\n            ⊙   --------    ⊙   --------    ⊙   --------    ⊙   --------    ⊙   --------    ⊙   --------    ⊙\n    a       |   ____/‾‾‾    |   ____/‾‾‾    |               |               |   ____/‾‾‾    |   ____/‾‾‾    |\n            ⊙   --------    ⊙   --------    ⊙   --------    ⊙   --------    ⊙   --------(:0/5,5)--------    ⊙\n    b       |               |               |   ____/‾‾‾    |   ____/‾‾‾    |               |               |\n            ⊙   --------    ⊙   --------    ⊙   --------(:1/3,4)--------    ⊙   --------    ⊙   --------    ⊙\n    a       |   ____/‾‾‾    |   ____/‾‾‾    |               |               |   ____/‾‾‾    |   ____/‾‾‾    |\n        (:3/0,3)--------(:2/1,3)--------    ⊙   --------(:2/3,3)--------(:1/4,3)--------    ⊙   --------    ⊙\n    c       |               |               |               |               |               |               |\n            ⊙   --------    ⊙   --------    ⊙   --------(:3/3,2)--------(:2/4,2)--------    ⊙   --------    ⊙\n    a       |   ____/‾‾‾    |   ____/‾‾‾    |               |               |   ____/‾‾‾    |   ____/‾‾‾    |\n        (:3/0,1)--------    ⊙   --------    ⊙   --------    ⊙   --------(:3/4,1)--------    ⊙   --------    ⊙\n    a       |   ____/‾‾‾    |   ____/‾‾‾    |               |               |   ____/‾‾‾    |   ____/‾‾‾    |\n        (:4/0,0)--------    ⊙   --------    ⊙   --------    ⊙   --------(:4/4,0)--------    ⊙   --------    ⊙\n                    a               a               b               b               a               a\n\nNeither of these is ideal for use in an editor, where it is undesirable to send very long diffs to the\nfront end. It's tricky to decide exactly what 'very long diffs' means, as \"replace A by B\" is very short.\nWe want to control how big D can be, by stopping when it gets too large. The forward algorithm then\nprivileges common prefixes, and the backward algorithm privileges common suffixes. Either is an undesirable\nasymmetry.\n\nFortunately there is a two-sided algorithm, implied by results in Myers' paper. Here's what the labels in\nthe edit graph look like.\nA:\"aabbaa\", B:\"aacaba\"\n             ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙\n    a        |    ____/‾‾‾‾    |    ____/‾‾‾‾    |                 |                 |    ____/‾‾‾‾    |    ____/‾‾‾‾    |\n             ⊙    ---------    ⊙    ---------    ⊙    --------- (2/3,5) ---------    ⊙    --------- (:0/5,5)---------    ⊙\n    b        |                 |                 |    ____/‾‾‾‾    |    ____/‾‾‾‾    |                 |                 |\n             ⊙    ---------    ⊙    ---------    ⊙    --------- (:1/3,4)---------    ⊙    ---------    ⊙    ---------    ⊙\n    a        |    ____/‾‾‾‾    |    ____/‾‾‾‾    |                 |                 |    ____/‾‾‾‾    |    ____/‾‾‾‾    |\n             ⊙    --------- (:2/1,3)--------- (1/2,3) ---------(2:2/3,3)--------- (:1/4,3)---------    ⊙    ---------    ⊙\n    c        |                 |                 |                 |                 |                 |                 |\n             ⊙    ---------    ⊙    --------- (0/2,2) --------- (1/3,2) ---------(2:2/4,2)---------    ⊙    ---------    ⊙\n    a        |    ____/‾‾‾‾    |    ____/‾‾‾‾    |                 |                 |    ____/‾‾‾‾    |    ____/‾‾‾‾    |\n             ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙\n    a        |    ____/‾‾‾‾    |    ____/‾‾‾‾    |                 |                 |    ____/‾‾‾‾    |    ____/‾‾‾‾    |\n             ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙    ---------    ⊙\n                      a                 a                 b                 b                 a                 a\n\nThe algorithm stopped when it saw the backwards 2-path ending at (1,3) and the forwards 2-path ending at (3,5). The criterion\nis a backwards path ending at (u,v) and a forward path ending at (x,y), where u <= x and the two points are on the same\ndiagonal. (Here the edgegraph has a diagonal, but the criterion is x-y=u-v.) Myers proves there is a forward\n2-path from (0,0) to (1,3), and that together with the backwards 2-path ending at (1,3) gives the expected 4-path.\nUnfortunately the forward path has to be constructed by another run of the forward algorithm; it can't be found from the\ncomputed labels. That is the worst case. Had the code noticed (x,y)=(u,v)=(3,3) the whole path could be reconstructed\nfrom the edgegraph. The implementation looks for a number of special cases to try to avoid computing an extra forward path.\n\nIf the two-sided algorithm has stop early (because D has become too large) it will have found a forward LCS and a\nbackwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointedness may fail and the two\ncomputed LCS may conflict. (An easy example is where A is a suffix of B, and shares a short prefix. The backwards LCS\nis all of A, and the forward LCS is a prefix of A.) The algorithm combines the two\nto form a best-effort LCS. In the worst case the forward partial LCS may have to\nbe recomputed.\n*/\n\n/* Eugene Myers paper is titled\n\"An O(ND) Difference Algorithm and Its Variations\"\nand can be found at\nhttp://www.xmailserver.org/diff2.pdf\n\n(There is a generic implementation of the algorithm the repository with git hash\nb9ad7e4ade3a686d608e44475390ad428e60e7fc)\n*/\n"
  },
  {
    "path": "internal/diff/lcs/git.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2022 The Go Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style\n# license that can be found in the LICENSE file.\n#\n# Creates a zip file containing all numbered versions\n# of the commit history of a large source file, for use\n# as input data for the tests of the diff algorithm.\n#\n# Run script from root of the x/tools repo.\n\nset -eu\n\n# WARNING: This script will install the latest version of $file\n# The largest real source file in the x/tools repo.\n# file=internal/golang/completion/completion.go\n# file=internal/golang/diagnostics.go\nfile=internal/protocol/tsprotocol.go\n\ntmp=$(mktemp -d)\ngit log $file |\n  awk '/^commit / {print $2}' |\n  nl -ba -nrz |\n  while read n hash; do\n    git checkout --quiet $hash $file\n    cp -f $file $tmp/$n\n  done\n(cd $tmp && zip -q - *) > testdata.zip\nrm -fr $tmp\ngit restore --staged $file\ngit restore $file\necho \"Created testdata.zip\"\n"
  },
  {
    "path": "internal/diff/lcs/labels.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\nimport (\n\t\"fmt\"\n)\n\n// For each D, vec[D] has length D+1,\n// and the label for (D, k) is stored in vec[D][(D+k)/2].\ntype label struct {\n\tvec [][]int\n}\n\n// Temporary checking DO NOT COMMIT true TO PRODUCTION CODE\nconst debug = false\n\n// debugging. check that the (d,k) pair is valid\n// (that is, -d<=k<=d and d+k even)\nfunc checkDK(D, k int) {\n\tif k >= -D && k <= D && (D+k)%2 == 0 {\n\t\treturn\n\t}\n\tpanic(fmt.Sprintf(\"out of range, d=%d,k=%d\", D, k))\n}\n\nfunc (t *label) set(D, k, x int) {\n\tif debug {\n\t\tcheckDK(D, k)\n\t}\n\tfor len(t.vec) <= D {\n\t\tt.vec = append(t.vec, nil)\n\t}\n\tif t.vec[D] == nil {\n\t\tt.vec[D] = make([]int, D+1)\n\t}\n\tt.vec[D][(D+k)/2] = x // known that D+k is even\n}\n\nfunc (t *label) get(d, k int) int {\n\tif debug {\n\t\tcheckDK(d, k)\n\t}\n\treturn int(t.vec[d][(d+k)/2])\n}\n\nfunc newtriang(limit int) label {\n\tif limit < 100 {\n\t\t// Preallocate if limit is not large.\n\t\treturn label{vec: make([][]int, limit)}\n\t}\n\treturn label{}\n}\n"
  },
  {
    "path": "internal/diff/lcs/old.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\n// TODO(adonovan): remove unclear references to \"old\" in this package.\n\nimport (\n\t\"fmt\"\n)\n\n// A Diff is a replacement of a portion of A by a portion of B.\ntype Diff struct {\n\tStart, End         int // offsets of portion to delete in A\n\tReplStart, ReplEnd int // offset of replacement text in B\n}\n\n// DiffBytes returns the differences between two byte sequences.\n// It does not respect rune boundaries.\nfunc DiffBytes(a, b []byte) []Diff { return diff(bytesSeqs{a, b}) }\n\n// DiffRunes returns the differences between two rune sequences.\nfunc DiffRunes(a, b []rune) []Diff { return diff(runesSeqs{a, b}) }\n\n// DiffLines returns the differences between two string sequences.\nfunc DiffLines(a, b []string) []Diff { return diff(linesSeqs{a, b}) }\n\n// A limit on how deeply the LCS algorithm should search. The value is just a guess.\nvar maxDiffs = 100\n\nfunc diff(seqs sequences) []Diff {\n\tdiff, _ := compute(seqs, twosided, maxDiffs/2)\n\treturn diff\n}\n\n// compute computes the list of differences between two sequences,\n// along with the LCS. It is exercised directly by tests.\n// The algorithm is one of {forward, backward, twosided}.\nfunc compute(seqs sequences, algo func(*editGraph) lcs, limit int) ([]Diff, lcs) {\n\tif limit <= 0 {\n\t\tlimit = 1 << 25 // effectively infinity\n\t}\n\talen, blen := seqs.lengths()\n\tg := &editGraph{\n\t\tseqs:  seqs,\n\t\tvf:    newtriang(limit),\n\t\tvb:    newtriang(limit),\n\t\tlimit: limit,\n\t\tux:    alen,\n\t\tuy:    blen,\n\t\tdelta: alen - blen,\n\t}\n\tlcs := algo(g)\n\tdiffs := lcs.toDiffs(alen, blen)\n\treturn diffs, lcs\n}\n\n// editGraph carries the information for computing the lcs of two sequences.\ntype editGraph struct {\n\tseqs   sequences\n\tvf, vb label // forward and backward labels\n\n\tlimit int // maximal value of D\n\t// the bounding rectangle of the current edit graph\n\tlx, ly, ux, uy int\n\tdelta          int // common subexpression: (ux-lx)-(uy-ly)\n}\n\n// toDiffs converts an LCS to a list of edits.\nfunc (lcs lcs) toDiffs(alen, blen int) []Diff {\n\tvar diffs []Diff\n\tvar pa, pb int // offsets in a, b\n\tfor _, l := range lcs {\n\t\tif pa < l.X || pb < l.Y {\n\t\t\tdiffs = append(diffs, Diff{pa, l.X, pb, l.Y})\n\t\t}\n\t\tpa = l.X + l.Len\n\t\tpb = l.Y + l.Len\n\t}\n\tif pa < alen || pb < blen {\n\t\tdiffs = append(diffs, Diff{pa, alen, pb, blen})\n\t}\n\treturn diffs\n}\n\n// --- FORWARD ---\n\n// fdone decides if the forward path has reached the upper right\n// corner of the rectangle. If so, it also returns the computed lcs.\nfunc (e *editGraph) fdone(D, k int) (bool, lcs) {\n\t// x, y, k are relative to the rectangle\n\tx := e.vf.get(D, k)\n\ty := x - k\n\tif x == e.ux && y == e.uy {\n\t\treturn true, e.forwardlcs(D, k)\n\t}\n\treturn false, nil\n}\n\n// run the forward algorithm, until success or up to the limit on D.\nfunc forward(e *editGraph) lcs {\n\te.setForward(0, 0, e.lx)\n\tif ok, ans := e.fdone(0, 0); ok {\n\t\treturn ans\n\t}\n\t// from D to D+1\n\tfor D := range e.limit {\n\t\te.setForward(D+1, -(D + 1), e.getForward(D, -D))\n\t\tif ok, ans := e.fdone(D+1, -(D + 1)); ok {\n\t\t\treturn ans\n\t\t}\n\t\te.setForward(D+1, D+1, e.getForward(D, D)+1)\n\t\tif ok, ans := e.fdone(D+1, D+1); ok {\n\t\t\treturn ans\n\t\t}\n\t\tfor k := -D + 1; k <= D-1; k += 2 {\n\t\t\t// these are tricky and easy to get backwards\n\t\t\tlookv := e.lookForward(k, e.getForward(D, k-1)+1)\n\t\t\tlookh := e.lookForward(k, e.getForward(D, k+1))\n\t\t\tif lookv > lookh {\n\t\t\t\te.setForward(D+1, k, lookv)\n\t\t\t} else {\n\t\t\t\te.setForward(D+1, k, lookh)\n\t\t\t}\n\t\t\tif ok, ans := e.fdone(D+1, k); ok {\n\t\t\t\treturn ans\n\t\t\t}\n\t\t}\n\t}\n\t// D is too large\n\t// find the D path with maximal x+y inside the rectangle and\n\t// use that to compute the found part of the lcs\n\tkmax := -e.limit - 1\n\tdiagmax := -1\n\tfor k := -e.limit; k <= e.limit; k += 2 {\n\t\tx := e.getForward(e.limit, k)\n\t\ty := x - k\n\t\tif x+y > diagmax && x <= e.ux && y <= e.uy {\n\t\t\tdiagmax, kmax = x+y, k\n\t\t}\n\t}\n\treturn e.forwardlcs(e.limit, kmax)\n}\n\n// recover the lcs by backtracking from the farthest point reached\nfunc (e *editGraph) forwardlcs(D, k int) lcs {\n\tvar ans lcs\n\tfor x := e.getForward(D, k); x != 0 || x-k != 0; {\n\t\tif ok(D-1, k-1) && x-1 == e.getForward(D-1, k-1) {\n\t\t\t// if (x-1,y) is labelled D-1, x--,D--,k--,continue\n\t\t\tD, k, x = D-1, k-1, x-1\n\t\t\tcontinue\n\t\t} else if ok(D-1, k+1) && x == e.getForward(D-1, k+1) {\n\t\t\t// if (x,y-1) is labelled D-1, x, D--,k++, continue\n\t\t\tD, k = D-1, k+1\n\t\t\tcontinue\n\t\t}\n\t\t// if (x-1,y-1)--(x,y) is a diagonal, prepend,x--,y--, continue\n\t\ty := x - k\n\t\tans = ans.prepend(x+e.lx-1, y+e.ly-1)\n\t\tx--\n\t}\n\treturn ans\n}\n\n// start at (x,y), go up the diagonal as far as possible,\n// and label the result with d\nfunc (e *editGraph) lookForward(k, relx int) int {\n\trely := relx - k\n\tx, y := relx+e.lx, rely+e.ly\n\tif x < e.ux && y < e.uy {\n\t\tx += e.seqs.commonPrefixLen(x, e.ux, y, e.uy)\n\t}\n\treturn x\n}\n\nfunc (e *editGraph) setForward(d, k, relx int) {\n\tx := e.lookForward(k, relx)\n\te.vf.set(d, k, x-e.lx)\n}\n\nfunc (e *editGraph) getForward(d, k int) int {\n\tx := e.vf.get(d, k)\n\treturn x\n}\n\n// --- BACKWARD ---\n\n// bdone decides if the backward path has reached the lower left corner\nfunc (e *editGraph) bdone(D, k int) (bool, lcs) {\n\t// x, y, k are relative to the rectangle\n\tx := e.vb.get(D, k)\n\ty := x - (k + e.delta)\n\tif x == 0 && y == 0 {\n\t\treturn true, e.backwardlcs(D, k)\n\t}\n\treturn false, nil\n}\n\n// run the backward algorithm, until success or up to the limit on D.\n// (used only by tests)\nfunc backward(e *editGraph) lcs {\n\te.setBackward(0, 0, e.ux)\n\tif ok, ans := e.bdone(0, 0); ok {\n\t\treturn ans\n\t}\n\t// from D to D+1\n\tfor D := range e.limit {\n\t\te.setBackward(D+1, -(D + 1), e.getBackward(D, -D)-1)\n\t\tif ok, ans := e.bdone(D+1, -(D + 1)); ok {\n\t\t\treturn ans\n\t\t}\n\t\te.setBackward(D+1, D+1, e.getBackward(D, D))\n\t\tif ok, ans := e.bdone(D+1, D+1); ok {\n\t\t\treturn ans\n\t\t}\n\t\tfor k := -D + 1; k <= D-1; k += 2 {\n\t\t\t// these are tricky and easy to get wrong\n\t\t\tlookv := e.lookBackward(k, e.getBackward(D, k-1))\n\t\t\tlookh := e.lookBackward(k, e.getBackward(D, k+1)-1)\n\t\t\tif lookv < lookh {\n\t\t\t\te.setBackward(D+1, k, lookv)\n\t\t\t} else {\n\t\t\t\te.setBackward(D+1, k, lookh)\n\t\t\t}\n\t\t\tif ok, ans := e.bdone(D+1, k); ok {\n\t\t\t\treturn ans\n\t\t\t}\n\t\t}\n\t}\n\n\t// D is too large\n\t// find the D path with minimal x+y inside the rectangle and\n\t// use that to compute the part of the lcs found\n\tkmax := -e.limit - 1\n\tdiagmin := 1 << 25\n\tfor k := -e.limit; k <= e.limit; k += 2 {\n\t\tx := e.getBackward(e.limit, k)\n\t\ty := x - (k + e.delta)\n\t\tif x+y < diagmin && x >= 0 && y >= 0 {\n\t\t\tdiagmin, kmax = x+y, k\n\t\t}\n\t}\n\tif kmax < -e.limit {\n\t\tpanic(fmt.Sprintf(\"no paths when limit=%d?\", e.limit))\n\t}\n\treturn e.backwardlcs(e.limit, kmax)\n}\n\n// recover the lcs by backtracking\nfunc (e *editGraph) backwardlcs(D, k int) lcs {\n\tvar ans lcs\n\tfor x := e.getBackward(D, k); x != e.ux || x-(k+e.delta) != e.uy; {\n\t\tif ok(D-1, k-1) && x == e.getBackward(D-1, k-1) {\n\t\t\t// D--, k--, x unchanged\n\t\t\tD, k = D-1, k-1\n\t\t\tcontinue\n\t\t} else if ok(D-1, k+1) && x+1 == e.getBackward(D-1, k+1) {\n\t\t\t// D--, k++, x++\n\t\t\tD, k, x = D-1, k+1, x+1\n\t\t\tcontinue\n\t\t}\n\t\ty := x - (k + e.delta)\n\t\tans = ans.append(x+e.lx, y+e.ly)\n\t\tx++\n\t}\n\treturn ans\n}\n\n// start at (x,y), go down the diagonal as far as possible,\nfunc (e *editGraph) lookBackward(k, relx int) int {\n\trely := relx - (k + e.delta) // forward k = k + e.delta\n\tx, y := relx+e.lx, rely+e.ly\n\tif x > 0 && y > 0 {\n\t\tx -= e.seqs.commonSuffixLen(0, x, 0, y)\n\t}\n\treturn x\n}\n\n// convert to rectangle, and label the result with d\nfunc (e *editGraph) setBackward(d, k, relx int) {\n\tx := e.lookBackward(k, relx)\n\te.vb.set(d, k, x-e.lx)\n}\n\nfunc (e *editGraph) getBackward(d, k int) int {\n\tx := e.vb.get(d, k)\n\treturn x\n}\n\n// -- TWOSIDED ---\n\nfunc twosided(e *editGraph) lcs {\n\t// The termination condition could be improved, as either the forward\n\t// or backward pass could succeed before Myers' Lemma applies.\n\t// Aside from questions of efficiency (is the extra testing cost-effective)\n\t// this is more likely to matter when e.limit is reached.\n\te.setForward(0, 0, e.lx)\n\te.setBackward(0, 0, e.ux)\n\n\t// from D to D+1\n\tfor D := range e.limit {\n\t\t// just finished a backwards pass, so check\n\t\tif got, ok := e.twoDone(D, D); ok {\n\t\t\treturn e.twolcs(D, D, got)\n\t\t}\n\t\t// do a forwards pass (D to D+1)\n\t\te.setForward(D+1, -(D + 1), e.getForward(D, -D))\n\t\te.setForward(D+1, D+1, e.getForward(D, D)+1)\n\t\tfor k := -D + 1; k <= D-1; k += 2 {\n\t\t\t// these are tricky and easy to get backwards\n\t\t\tlookv := e.lookForward(k, e.getForward(D, k-1)+1)\n\t\t\tlookh := e.lookForward(k, e.getForward(D, k+1))\n\t\t\tif lookv > lookh {\n\t\t\t\te.setForward(D+1, k, lookv)\n\t\t\t} else {\n\t\t\t\te.setForward(D+1, k, lookh)\n\t\t\t}\n\t\t}\n\t\t// just did a forward pass, so check\n\t\tif got, ok := e.twoDone(D+1, D); ok {\n\t\t\treturn e.twolcs(D+1, D, got)\n\t\t}\n\t\t// do a backward pass, D to D+1\n\t\te.setBackward(D+1, -(D + 1), e.getBackward(D, -D)-1)\n\t\te.setBackward(D+1, D+1, e.getBackward(D, D))\n\t\tfor k := -D + 1; k <= D-1; k += 2 {\n\t\t\t// these are tricky and easy to get wrong\n\t\t\tlookv := e.lookBackward(k, e.getBackward(D, k-1))\n\t\t\tlookh := e.lookBackward(k, e.getBackward(D, k+1)-1)\n\t\t\tif lookv < lookh {\n\t\t\t\te.setBackward(D+1, k, lookv)\n\t\t\t} else {\n\t\t\t\te.setBackward(D+1, k, lookh)\n\t\t\t}\n\t\t}\n\t}\n\n\t// D too large. combine a forward and backward partial lcs\n\t// first, a forward one\n\tkmax := -e.limit - 1\n\tdiagmax := -1\n\tfor k := -e.limit; k <= e.limit; k += 2 {\n\t\tx := e.getForward(e.limit, k)\n\t\ty := x - k\n\t\tif x+y > diagmax && x <= e.ux && y <= e.uy {\n\t\t\tdiagmax, kmax = x+y, k\n\t\t}\n\t}\n\tif kmax < -e.limit {\n\t\tpanic(fmt.Sprintf(\"no forward paths when limit=%d?\", e.limit))\n\t}\n\tlcs := e.forwardlcs(e.limit, kmax)\n\t// now a backward one\n\t// find the D path with minimal x+y inside the rectangle and\n\t// use that to compute the lcs\n\tdiagmin := 1 << 25 // infinity\n\tfor k := -e.limit; k <= e.limit; k += 2 {\n\t\tx := e.getBackward(e.limit, k)\n\t\ty := x - (k + e.delta)\n\t\tif x+y < diagmin && x >= 0 && y >= 0 {\n\t\t\tdiagmin, kmax = x+y, k\n\t\t}\n\t}\n\tif kmax < -e.limit {\n\t\tpanic(fmt.Sprintf(\"no backward paths when limit=%d?\", e.limit))\n\t}\n\tlcs = append(lcs, e.backwardlcs(e.limit, kmax)...)\n\t// These may overlap (e.forwardlcs and e.backwardlcs return sorted lcs)\n\tans := lcs.fix()\n\treturn ans\n}\n\n// Does Myers' Lemma apply?\nfunc (e *editGraph) twoDone(df, db int) (int, bool) {\n\tif (df+db+e.delta)%2 != 0 {\n\t\treturn 0, false // diagonals cannot overlap\n\t}\n\tkmin := max(-df, -db+e.delta)\n\tkmax := min(df, db+e.delta)\n\tfor k := kmin; k <= kmax; k += 2 {\n\t\tx := e.vf.get(df, k)\n\t\tu := e.vb.get(db, k-e.delta)\n\t\tif u <= x {\n\t\t\t// is it worth looking at all the other k?\n\t\t\tfor l := k; l <= kmax; l += 2 {\n\t\t\t\tx := e.vf.get(df, l)\n\t\t\t\ty := x - l\n\t\t\t\tu := e.vb.get(db, l-e.delta)\n\t\t\t\tv := u - l\n\t\t\t\tif x == u || u == 0 || v == 0 || y == e.uy || x == e.ux {\n\t\t\t\t\treturn l, true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn k, true\n\t\t}\n\t}\n\treturn 0, false\n}\n\nfunc (e *editGraph) twolcs(df, db, kf int) lcs {\n\t// db==df || db+1==df\n\tx := e.vf.get(df, kf)\n\ty := x - kf\n\tkb := kf - e.delta\n\tu := e.vb.get(db, kb)\n\tv := u - kf\n\n\t// Myers proved there is a df-path from (0,0) to (u,v)\n\t// and a db-path from (x,y) to (N,M).\n\t// In the first case the overall path is the forward path\n\t// to (u,v) followed by the backward path to (N,M).\n\t// In the second case the path is the backward path to (x,y)\n\t// followed by the forward path to (x,y) from (0,0).\n\n\t// Look for some special cases to avoid computing either of these paths.\n\tif x == u {\n\t\t// \"babaab\" \"cccaba\"\n\t\t// already patched together\n\t\tlcs := e.forwardlcs(df, kf)\n\t\tlcs = append(lcs, e.backwardlcs(db, kb)...)\n\t\treturn lcs.sort()\n\t}\n\n\t// is (u-1,v) or (u,v-1) labelled df-1?\n\t// if so, that forward df-1-path plus a horizontal or vertical edge\n\t// is the df-path to (u,v), then plus the db-path to (N,M)\n\tif u > 0 && ok(df-1, u-1-v) && e.vf.get(df-1, u-1-v) == u-1 {\n\t\t//  \"aabbab\" \"cbcabc\"\n\t\tlcs := e.forwardlcs(df-1, u-1-v)\n\t\tlcs = append(lcs, e.backwardlcs(db, kb)...)\n\t\treturn lcs.sort()\n\t}\n\tif v > 0 && ok(df-1, (u-(v-1))) && e.vf.get(df-1, u-(v-1)) == u {\n\t\t//  \"abaabb\" \"bcacab\"\n\t\tlcs := e.forwardlcs(df-1, u-(v-1))\n\t\tlcs = append(lcs, e.backwardlcs(db, kb)...)\n\t\treturn lcs.sort()\n\t}\n\n\t// The path can't possibly contribute to the lcs because it\n\t// is all horizontal or vertical edges\n\tif u == 0 || v == 0 || x == e.ux || y == e.uy {\n\t\t// \"abaabb\" \"abaaaa\"\n\t\tif u == 0 || v == 0 {\n\t\t\treturn e.backwardlcs(db, kb)\n\t\t}\n\t\treturn e.forwardlcs(df, kf)\n\t}\n\n\t// is (x+1,y) or (x,y+1) labelled db-1?\n\tif x+1 <= e.ux && ok(db-1, x+1-y-e.delta) && e.vb.get(db-1, x+1-y-e.delta) == x+1 {\n\t\t// \"bababb\" \"baaabb\"\n\t\tlcs := e.backwardlcs(db-1, kb+1)\n\t\tlcs = append(lcs, e.forwardlcs(df, kf)...)\n\t\treturn lcs.sort()\n\t}\n\tif y+1 <= e.uy && ok(db-1, x-(y+1)-e.delta) && e.vb.get(db-1, x-(y+1)-e.delta) == x {\n\t\t// \"abbbaa\" \"cabacc\"\n\t\tlcs := e.backwardlcs(db-1, kb-1)\n\t\tlcs = append(lcs, e.forwardlcs(df, kf)...)\n\t\treturn lcs.sort()\n\t}\n\n\t// need to compute another path\n\t// \"aabbaa\" \"aacaba\"\n\tlcs := e.backwardlcs(db, kb)\n\toldx, oldy := e.ux, e.uy\n\te.ux = u\n\te.uy = v\n\tlcs = append(lcs, forward(e)...)\n\te.ux, e.uy = oldx, oldy\n\treturn lcs.sort()\n}\n"
  },
  {
    "path": "internal/diff/lcs/old_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand/v2\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestAlgosOld(t *testing.T) {\n\tfor i, algo := range []func(*editGraph) lcs{forward, backward, twosided} {\n\t\tt.Run(strings.Fields(\"forward backward twosided\")[i], func(t *testing.T) {\n\t\t\tfor _, tx := range Btests {\n\t\t\t\tlim := len(tx.a) + len(tx.b)\n\n\t\t\t\tdiffs, lcs := compute(stringSeqs{tx.a, tx.b}, algo, lim)\n\t\t\t\tcheck(t, tx.a, lcs, tx.lcs)\n\t\t\t\tcheckDiffs(t, tx.a, diffs, tx.b)\n\n\t\t\t\tdiffs, lcs = compute(stringSeqs{tx.b, tx.a}, algo, lim)\n\t\t\t\tcheck(t, tx.b, lcs, tx.lcs)\n\t\t\t\tcheckDiffs(t, tx.b, diffs, tx.a)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIntOld(t *testing.T) {\n\t// need to avoid any characters in btests\n\tlfill, rfill := \"AAAAAAAAAAAA\", \"BBBBBBBBBBBB\"\n\tfor _, tx := range Btests {\n\t\tif len(tx.a) < 2 || len(tx.b) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\tleft := tx.a + lfill\n\t\tright := tx.b + rfill\n\t\tlim := len(tx.a) + len(tx.b)\n\t\tdiffs, lcs := compute(stringSeqs{left, right}, twosided, lim)\n\t\tcheck(t, left, lcs, tx.lcs)\n\t\tcheckDiffs(t, left, diffs, right)\n\t\tdiffs, lcs = compute(stringSeqs{right, left}, twosided, lim)\n\t\tcheck(t, right, lcs, tx.lcs)\n\t\tcheckDiffs(t, right, diffs, left)\n\n\t\tleft = lfill + tx.a\n\t\tright = rfill + tx.b\n\t\tdiffs, lcs = compute(stringSeqs{left, right}, twosided, lim)\n\t\tcheck(t, left, lcs, tx.lcs)\n\t\tcheckDiffs(t, left, diffs, right)\n\t\tdiffs, lcs = compute(stringSeqs{right, left}, twosided, lim)\n\t\tcheck(t, right, lcs, tx.lcs)\n\t\tcheckDiffs(t, right, diffs, left)\n\t}\n}\n\nfunc TestSpecialOld(t *testing.T) { // exercises lcs.fix\n\ta := \"golang.org/x/tools/intern\"\n\tb := \"github.com/google/safehtml/template\\\"\\n\\t\\\"golang.org/x/tools/intern\"\n\tdiffs, lcs := compute(stringSeqs{a, b}, twosided, 4)\n\tif !lcs.valid() {\n\t\tt.Errorf(\"%d,%v\", len(diffs), lcs)\n\t}\n}\n\nfunc TestRegressionOld001(t *testing.T) {\n\ta := \"// Copyright 2019 The Go Authors. All rights reserved.\\n// Use of this source code is governed by a BSD-style\\n// license that can be found in the LICENSE file.\\n\\npackage diff_test\\n\\nimport (\\n\\t\\\"fmt\\\"\\n\\t\\\"math/rand\\\"\\n\\t\\\"strings\\\"\\n\\t\\\"testing\\\"\\n\\n\\t\\\"golang.org/x/tools/gopls/internal/lsp/diff\\\"\\n\\t\\\"golang.org/x/tools/internal/diff/difftest\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/span\\\"\\n)\\n\"\n\n\tb := \"// Copyright 2019 The Go Authors. All rights reserved.\\n// Use of this source code is governed by a BSD-style\\n// license that can be found in the LICENSE file.\\n\\npackage diff_test\\n\\nimport (\\n\\t\\\"fmt\\\"\\n\\t\\\"math/rand\\\"\\n\\t\\\"strings\\\"\\n\\t\\\"testing\\\"\\n\\n\\t\\\"github.com/google/safehtml/template\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/lsp/diff\\\"\\n\\t\\\"golang.org/x/tools/internal/diff/difftest\\\"\\n\\t\\\"golang.org/x/tools/gopls/internal/span\\\"\\n)\\n\"\n\tfor i := 1; i < len(b); i++ {\n\t\tdiffs, lcs := compute(stringSeqs{a, b}, twosided, i) // 14 from gopls\n\t\tif !lcs.valid() {\n\t\t\tt.Errorf(\"%d,%v\", len(diffs), lcs)\n\t\t}\n\t\tcheckDiffs(t, a, diffs, b)\n\t}\n}\n\nfunc TestRegressionOld002(t *testing.T) {\n\ta := \"n\\\"\\n)\\n\"\n\tb := \"n\\\"\\n\\t\\\"golang.org/x//nnal/stack\\\"\\n)\\n\"\n\tfor i := 1; i <= len(b); i++ {\n\t\tdiffs, lcs := compute(stringSeqs{a, b}, twosided, i)\n\t\tif !lcs.valid() {\n\t\t\tt.Errorf(\"%d,%v\", len(diffs), lcs)\n\t\t}\n\t\tcheckDiffs(t, a, diffs, b)\n\t}\n}\n\nfunc TestRegressionOld003(t *testing.T) {\n\ta := \"golang.org/x/hello v1.0.0\\nrequire golang.org/x/unused v1\"\n\tb := \"golang.org/x/hello v1\"\n\tfor i := 1; i <= len(a); i++ {\n\t\tdiffs, lcs := compute(stringSeqs{a, b}, twosided, i)\n\t\tif !lcs.valid() {\n\t\t\tt.Errorf(\"%d,%v\", len(diffs), lcs)\n\t\t}\n\t\tcheckDiffs(t, a, diffs, b)\n\t}\n}\n\nfunc TestRandOld(t *testing.T) {\n\trng := rng(t)\n\n\tfor i := range 1000 {\n\t\t// TODO(adonovan): use ASCII and bytesSeqs here? The use of\n\t\t// non-ASCII isn't relevant to the property exercised by the test.\n\t\ta := []rune(randstr(rng, \"abω\", 16))\n\t\tb := []rune(randstr(rng, \"abωc\", 16))\n\t\tseq := runesSeqs{a, b}\n\n\t\tconst lim = 0 // make sure we get the lcs (24 was too small)\n\t\t_, forw := compute(seq, forward, lim)\n\t\t_, back := compute(seq, backward, lim)\n\t\t_, two := compute(seq, twosided, lim)\n\t\tif lcslen(two) != lcslen(forw) || lcslen(forw) != lcslen(back) {\n\t\t\tt.Logf(\"\\n%v\\n%v\\n%v\", forw, back, two)\n\t\t\tt.Fatalf(\"%d forw:%d back:%d two:%d\", i, lcslen(forw), lcslen(back), lcslen(two))\n\t\t}\n\t\tif !two.valid() || !forw.valid() || !back.valid() {\n\t\t\tt.Errorf(\"check failure\")\n\t\t}\n\t}\n}\n\n// TestDiffAPI tests the public API functions (Diff{Bytes,Strings,Runes})\n// to ensure at least minimal parity of the three representations.\nfunc TestDiffAPI(t *testing.T) {\n\tfor _, test := range []struct {\n\t\ta, b                 string\n\t\twantBytes, wantRunes string\n\t}{\n\t\t{\"abcXdef\", \"abcxdef\", \"[{3 4 3 4}]\", \"[{3 4 3 4}]\"}, // ASCII\n\t\t{\"abcωdef\", \"abcΩdef\", \"[{3 5 3 5}]\", \"[{3 4 3 4}]\"}, // non-ASCII\n\t} {\n\n\t\tgotBytes := fmt.Sprint(DiffBytes([]byte(test.a), []byte(test.b)))\n\t\tif gotBytes != test.wantBytes {\n\t\t\tt.Errorf(\"DiffBytes(%q, %q) = %v, want %v\",\n\t\t\t\ttest.a, test.b, gotBytes, test.wantBytes)\n\t\t}\n\t\tgotRunes := fmt.Sprint(DiffRunes([]rune(test.a), []rune(test.b)))\n\t\tif gotRunes != test.wantRunes {\n\t\t\tt.Errorf(\"DiffRunes(%q, %q) = %v, want %v\",\n\t\t\t\ttest.a, test.b, gotRunes, test.wantRunes)\n\t\t}\n\t}\n}\n\nfunc BenchmarkTwoOld(b *testing.B) {\n\ttests := genBench(rng(b), \"abc\", 96)\n\tfor b.Loop() {\n\t\tfor _, tt := range tests {\n\t\t\t_, two := compute(stringSeqs{tt.before, tt.after}, twosided, 100)\n\t\t\tif !two.valid() {\n\t\t\t\tb.Error(\"check failed\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc BenchmarkForwOld(b *testing.B) {\n\ttests := genBench(rng(b), \"abc\", 96)\n\tfor b.Loop() {\n\t\tfor _, tt := range tests {\n\t\t\t_, two := compute(stringSeqs{tt.before, tt.after}, forward, 100)\n\t\t\tif !two.valid() {\n\t\t\t\tb.Error(\"check failed\")\n\t\t\t}\n\t\t}\n\t}\n}\n\n// rng returns a randomly initialized PRNG whose seeds are logged so\n// that occasional test failures can be deterministically replayed.\nfunc rng(tb testing.TB) *rand.Rand {\n\tseed1, seed2 := rand.Uint64(), rand.Uint64()\n\ttb.Logf(\"PRNG seeds: %d, %d\", seed1, seed2)\n\treturn rand.New(rand.NewPCG(seed1, seed2))\n}\n\nfunc genBench(rng *rand.Rand, set string, n int) []struct{ before, after string } {\n\t// before and after for benchmarks. 24 strings of length n with\n\t// before and after differing at least once, and about 5%\n\tvar ans []struct{ before, after string }\n\tfor range 24 {\n\t\t// maybe b should have an approximately known number of diffs\n\t\ta := randstr(rng, set, n)\n\t\tcnt := 0\n\t\tbb := make([]rune, 0, n)\n\t\tfor _, r := range a {\n\t\t\tif rand.Float64() < .05 {\n\t\t\t\tcnt++\n\t\t\t\tr = 'N'\n\t\t\t}\n\t\t\tbb = append(bb, r)\n\t\t}\n\t\tif cnt == 0 {\n\t\t\t// avoid == shortcut\n\t\t\tbb[n/2] = 'N'\n\t\t}\n\t\tans = append(ans, struct{ before, after string }{a, string(bb)})\n\t}\n\treturn ans\n}\n\n// This benchmark represents a common case for a diff command:\n// large file with a single relatively small diff in the middle.\n// (It's not clear whether this is representative of gopls workloads\n// or whether it is important to gopls diff performance.)\n//\n// TODO(adonovan) opt: it could be much faster.  For example,\n// comparing a file against itself is about 10x faster than with the\n// small deletion in the middle. Strangely, comparing a file against\n// itself minus the last byte is faster still; I don't know why.\n// There is much low-hanging fruit here for further improvement.\nfunc BenchmarkLargeFileSmallDiff(b *testing.B) {\n\tdata, err := os.ReadFile(\"old.go\") // large file\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tn := len(data)\n\n\tsrc := string(data)\n\tdst := src[:n*49/100] + src[n*51/100:] // remove 2% from the middle\n\tb.Run(\"string\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcompute(stringSeqs{src, dst}, twosided, len(src)+len(dst))\n\t\t}\n\t})\n\n\tsrcBytes := []byte(src)\n\tdstBytes := []byte(dst)\n\tb.Run(\"bytes\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcompute(bytesSeqs{srcBytes, dstBytes}, twosided, len(srcBytes)+len(dstBytes))\n\t\t}\n\t})\n\n\tsrcRunes := []rune(src)\n\tdstRunes := []rune(dst)\n\tb.Run(\"runes\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcompute(runesSeqs{srcRunes, dstRunes}, twosided, len(srcRunes)+len(dstRunes))\n\t\t}\n\t})\n\tsrcLines := strings.Split(src, \"\\n\")\n\tdstLines := strings.Split(dst, \"\\n\")\n\tb.Run(\"lines\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcompute(linesSeqs{srcLines, dstLines}, twosided, len(srcLines)+len(dstLines))\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "internal/diff/lcs/sequence.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage lcs\n\n// This file defines the abstract sequence over which the LCS algorithm operates.\n\n// sequences abstracts a pair of sequences, A and B.\ntype sequences interface {\n\tlengths() (int, int)                    // len(A), len(B)\n\tcommonPrefixLen(ai, aj, bi, bj int) int // len(commonPrefix(A[ai:aj], B[bi:bj]))\n\tcommonSuffixLen(ai, aj, bi, bj int) int // len(commonSuffix(A[ai:aj], B[bi:bj]))\n}\n\n// The explicit capacity in s[i:j:j] leads to more efficient code.\n\ntype bytesSeqs struct{ a, b []byte }\n\nfunc (s bytesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }\nfunc (s bytesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {\n\treturn commonPrefixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])\n}\nfunc (s bytesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {\n\treturn commonSuffixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])\n}\n\ntype runesSeqs struct{ a, b []rune }\n\nfunc (s runesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }\nfunc (s runesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {\n\treturn commonPrefixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])\n}\nfunc (s runesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {\n\treturn commonSuffixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])\n}\n\ntype linesSeqs struct{ a, b []string }\n\nfunc (s linesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }\nfunc (s linesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {\n\treturn commonPrefixLen(s.a[ai:aj], s.b[bi:bj])\n}\nfunc (s linesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {\n\treturn commonSuffixLen(s.a[ai:aj], s.b[bi:bj])\n}\n\n// TODO(adonovan): optimize these functions using ideas from:\n// - https://go.dev/cl/408116 common.go\n// - https://go.dev/cl/421435 xor_generic.go\n\n// commonPrefixLen returns the length of the common prefix of a[ai:aj] and b[bi:bj].\nfunc commonPrefixLen[T comparable](a, b []T) int {\n\tn := min(len(a), len(b))\n\ti := 0\n\tfor i < n && a[i] == b[i] {\n\t\ti++\n\t}\n\treturn i\n}\n\n// commonSuffixLen returns the length of the common suffix of a[ai:aj] and b[bi:bj].\nfunc commonSuffixLen[T comparable](a, b []T) int {\n\tn := min(len(a), len(b))\n\ti := 0\n\tfor i < n && a[len(a)-1-i] == b[len(b)-1-i] {\n\t\ti++\n\t}\n\treturn i\n}\n"
  },
  {
    "path": "internal/diff/merge.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff\n\nimport (\n\t\"slices\"\n)\n\n// Merge merges two valid, ordered lists of edits.\n// It returns zero if there was a conflict.\n//\n// If corresponding edits in x and y are identical,\n// they are coalesced in the result.\n//\n// If x and y both provide different insertions at the same point,\n// the insertions from x will be first in the result.\n//\n// TODO(adonovan): this algorithm could be improved, for example by\n// working harder to coalesce non-identical edits that share a common\n// deletion or common prefix of insertion (see the tests).\n// Survey the academic literature for insights.\nfunc Merge(x, y []Edit) ([]Edit, bool) {\n\t// Make a defensive (premature) copy of the arrays.\n\tx = slices.Clone(x)\n\ty = slices.Clone(y)\n\n\tvar merged []Edit\n\tadd := func(edit Edit) {\n\t\tmerged = append(merged, edit)\n\t}\n\tvar xi, yi int\n\tfor xi < len(x) && yi < len(y) {\n\t\tpx := &x[xi]\n\t\tpy := &y[yi]\n\n\t\tif *px == *py {\n\t\t\t// x and y are identical: coalesce.\n\t\t\tadd(*px)\n\t\t\txi++\n\t\t\tyi++\n\n\t\t} else if px.End <= py.Start {\n\t\t\t// x is entirely before y,\n\t\t\t// or an insertion at start of y.\n\t\t\tadd(*px)\n\t\t\txi++\n\n\t\t} else if py.End <= px.Start {\n\t\t\t// y is entirely before x,\n\t\t\t// or an insertion at start of x.\n\t\t\tadd(*py)\n\t\t\tyi++\n\n\t\t} else if px.Start < py.Start {\n\t\t\t// x is partly before y:\n\t\t\t// split it into a deletion and an edit.\n\t\t\tadd(Edit{px.Start, py.Start, \"\"})\n\t\t\tpx.Start = py.Start\n\n\t\t} else if py.Start < px.Start {\n\t\t\t// y is partly before x:\n\t\t\t// split it into a deletion and an edit.\n\t\t\tadd(Edit{py.Start, px.Start, \"\"})\n\t\t\tpy.Start = px.Start\n\n\t\t} else {\n\t\t\t// x and y are unequal non-insertions\n\t\t\t// at the same point: conflict.\n\t\t\treturn nil, false\n\t\t}\n\t}\n\tfor ; xi < len(x); xi++ {\n\t\tadd(x[xi])\n\t}\n\tfor ; yi < len(y); yi++ {\n\t\tadd(y[yi])\n\t}\n\treturn merged, true\n}\n"
  },
  {
    "path": "internal/diff/merge_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff_test\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/diff\"\n)\n\nfunc TestMerge(t *testing.T) {\n\t// For convenience, we test Merge using strings, not sequences\n\t// of edits, though this does put us at the mercy of the diff\n\t// algorithm.\n\tfor _, test := range []struct {\n\t\tbase, x, y string\n\t\twant       string // \"!\" => conflict\n\t}{\n\t\t// independent insertions\n\t\t{\"abcdef\", \"abXcdef\", \"abcdeYf\", \"abXcdeYf\"},\n\t\t// independent deletions\n\t\t{\"abcdef\", \"acdef\", \"abcdf\", \"acdf\"},\n\t\t// colocated insertions (X first)\n\t\t{\"abcdef\", \"abcXdef\", \"abcYdef\", \"abcXYdef\"},\n\t\t// colocated identical insertions (coalesced)\n\t\t{\"abcdef\", \"abcXdef\", \"abcXdef\", \"abcXdef\"},\n\t\t// colocated insertions with common prefix (X first)\n\t\t// TODO(adonovan): would \"abcXYdef\" be better?\n\t\t// i.e. should we dissect the insertions?\n\t\t{\"abcdef\", \"abcXdef\", \"abcXYdef\", \"abcXXYdef\"},\n\t\t// mix of identical and independent insertions (X first)\n\t\t{\"abcdef\", \"aIbcdXef\", \"aIbcdYef\", \"aIbcdXYef\"},\n\t\t// independent deletions\n\t\t{\"abcdef\", \"def\", \"abc\", \"\"},\n\t\t// overlapping deletions: conflict\n\t\t{\"abcdef\", \"adef\", \"abef\", \"!\"},\n\t\t// overlapping deletions with distinct insertions, X first\n\t\t{\"abcdef\", \"abXef\", \"abcYf\", \"!\"},\n\t\t// overlapping deletions with distinct insertions, Y first\n\t\t{\"abcdef\", \"abcXf\", \"abYef\", \"!\"},\n\t\t// overlapping deletions with common insertions\n\t\t{\"abcdef\", \"abXef\", \"abcXf\", \"!\"},\n\t\t// trailing insertions in X (observe X bias)\n\t\t{\"abcdef\", \"aXbXcXdXeXfX\", \"aYbcdef\", \"aXYbXcXdXeXfX\"},\n\t\t// trailing insertions in Y (observe X bias)\n\t\t{\"abcdef\", \"aXbcdef\", \"aYbYcYdYeYfY\", \"aXYbYcYdYeYfY\"},\n\t} {\n\t\tdx := diff.Strings(test.base, test.x)\n\t\tdy := diff.Strings(test.base, test.y)\n\t\tgot := \"!\" // conflict\n\t\tif dz, ok := diff.Merge(dx, dy); ok {\n\t\t\tvar err error\n\t\t\tgot, err = diff.Apply(test.base, dz)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Merge(%q, %q, %q) produced invalid edits %v: %v\", test.base, test.x, test.y, dz, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif test.want != got {\n\t\t\tt.Errorf(\"base=%q x=%q y=%q: got %q, want %q\", test.base, test.x, test.y, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/diff/ndiff.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/internal/diff/lcs\"\n)\n\n// Lines computes differences between two strings. All edits are at line boundaries.\nfunc Lines(before, after string) []Edit {\n\tbeforeLines, bOffsets := splitLines(before)\n\tafterLines, _ := splitLines(after)\n\tdiffs := lcs.DiffLines(beforeLines, afterLines)\n\n\t// Convert from LCS diffs to Edits\n\tres := make([]Edit, len(diffs))\n\tfor i, d := range diffs {\n\t\tres[i] = Edit{\n\t\t\tStart: bOffsets[d.Start],\n\t\t\tEnd:   bOffsets[d.End],\n\t\t\tNew:   strings.Join(afterLines[d.ReplStart:d.ReplEnd], \"\"),\n\t\t}\n\t}\n\treturn res\n}\n\n// Strings computes the differences between two strings.\n// The resulting edits respect rune boundaries.\nfunc Strings(before, after string) []Edit {\n\tif before == after {\n\t\treturn nil // common case\n\t}\n\n\tif isASCII(before) && isASCII(after) {\n\t\t// TODO(adonovan): opt: specialize diffASCII for strings.\n\t\treturn diffASCII([]byte(before), []byte(after))\n\t}\n\treturn diffRunes([]rune(before), []rune(after))\n}\n\n// Bytes computes the differences between two byte slices.\n// The resulting edits respect rune boundaries.\nfunc Bytes(before, after []byte) []Edit {\n\tif bytes.Equal(before, after) {\n\t\treturn nil // common case\n\t}\n\n\tif isASCII(before) && isASCII(after) {\n\t\treturn diffASCII(before, after)\n\t}\n\treturn diffRunes(runes(before), runes(after))\n}\n\nfunc diffASCII(before, after []byte) []Edit {\n\tdiffs := lcs.DiffBytes(before, after)\n\n\t// Convert from LCS diffs.\n\tres := make([]Edit, len(diffs))\n\tfor i, d := range diffs {\n\t\tres[i] = Edit{d.Start, d.End, string(after[d.ReplStart:d.ReplEnd])}\n\t}\n\treturn res\n}\n\nfunc diffRunes(before, after []rune) []Edit {\n\tdiffs := lcs.DiffRunes(before, after)\n\n\t// The diffs returned by the lcs package use indexes\n\t// into whatever slice was passed in.\n\t// Convert rune offsets to byte offsets.\n\tres := make([]Edit, len(diffs))\n\tlastEnd := 0\n\tutf8Len := 0\n\tfor i, d := range diffs {\n\t\tutf8Len += runesLen(before[lastEnd:d.Start]) // text between edits\n\t\tstart := utf8Len\n\t\tutf8Len += runesLen(before[d.Start:d.End]) // text deleted by this edit\n\t\tres[i] = Edit{start, utf8Len, string(after[d.ReplStart:d.ReplEnd])}\n\t\tlastEnd = d.End\n\t}\n\treturn res\n}\n\n// runes is like []rune(string(bytes)) without the duplicate allocation.\nfunc runes(bytes []byte) []rune {\n\tn := utf8.RuneCount(bytes)\n\trunes := make([]rune, n)\n\tfor i := range n {\n\t\tr, sz := utf8.DecodeRune(bytes)\n\t\tbytes = bytes[sz:]\n\t\trunes[i] = r\n\t}\n\treturn runes\n}\n\n// runesLen returns the length in bytes of the UTF-8 encoding of runes.\nfunc runesLen(runes []rune) (len int) {\n\tfor _, r := range runes {\n\t\tlen += utf8.RuneLen(r)\n\t}\n\treturn len\n}\n\n// isASCII reports whether s contains only ASCII.\nfunc isASCII[S string | []byte](s S) bool {\n\tfor i := 0; i < len(s); i++ {\n\t\tif s[i] >= utf8.RuneSelf {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "internal/diff/unified.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diff\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// DefaultContextLines is the number of unchanged lines of surrounding\n// context displayed by Unified. Use ToUnified to specify a different value.\nconst DefaultContextLines = 3\n\n// Unified returns a unified diff of the old and new strings.\n// The old and new labels are the names of the old and new files.\n// If the strings are equal, it returns the empty string.\nfunc Unified(oldLabel, newLabel, old, new string) string {\n\tedits := Lines(old, new)\n\tunified, err := ToUnified(oldLabel, newLabel, old, edits, DefaultContextLines)\n\tif err != nil {\n\t\t// Can't happen: edits are consistent.\n\t\tlog.Fatalf(\"internal error in diff.Unified: %v\", err)\n\t}\n\treturn unified\n}\n\n// ToUnified applies the edits to content and returns a unified diff,\n// with contextLines lines of (unchanged) context around each diff hunk.\n// The old and new labels are the names of the content and result files.\n// It returns an error if the edits are inconsistent; see ApplyEdits.\nfunc ToUnified(oldLabel, newLabel, content string, edits []Edit, contextLines int) (string, error) {\n\tu, err := toUnified(oldLabel, newLabel, content, edits, contextLines)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn u.String(), nil\n}\n\n// unified represents a set of edits as a unified diff.\ntype unified struct {\n\t// from is the name of the original file.\n\tfrom string\n\t// to is the name of the modified file.\n\tto string\n\t// hunks is the set of edit hunks needed to transform the file content.\n\thunks []*hunk\n}\n\n// Hunk represents a contiguous set of line edits to apply.\ntype hunk struct {\n\t// The line in the original source where the hunk starts.\n\tfromLine int\n\t// The line in the original source where the hunk finishes.\n\ttoLine int\n\t// The set of line based edits to apply.\n\tlines []line\n}\n\n// Line represents a single line operation to apply as part of a Hunk.\ntype line struct {\n\t// kind is the type of line this represents, deletion, insertion or copy.\n\tkind opKind\n\t// content is the content of this line.\n\t// For deletion it is the line being removed, for all others it is the line\n\t// to put in the output.\n\tcontent string\n}\n\n// opKind is used to denote the type of operation a line represents.\ntype opKind int\n\nconst (\n\t// opDelete is the operation kind for a line that is present in the input\n\t// but not in the output.\n\topDelete opKind = iota\n\t// opInsert is the operation kind for a line that is new in the output.\n\topInsert\n\t// opEqual is the operation kind for a line that is the same in the input and\n\t// output, often used to provide context around edited lines.\n\topEqual\n)\n\n// String returns a human readable representation of an OpKind. It is not\n// intended for machine processing.\nfunc (k opKind) String() string {\n\tswitch k {\n\tcase opDelete:\n\t\treturn \"delete\"\n\tcase opInsert:\n\t\treturn \"insert\"\n\tcase opEqual:\n\t\treturn \"equal\"\n\tdefault:\n\t\tpanic(\"unknown operation kind\")\n\t}\n}\n\n// toUnified takes a file contents and a sequence of edits, and calculates\n// a unified diff that represents those edits.\nfunc toUnified(fromName, toName string, content string, edits []Edit, contextLines int) (unified, error) {\n\tgap := contextLines * 2\n\tu := unified{\n\t\tfrom: fromName,\n\t\tto:   toName,\n\t}\n\tif len(edits) == 0 {\n\t\treturn u, nil\n\t}\n\tvar err error\n\tedits, err = lineEdits(content, edits) // expand to whole lines\n\tif err != nil {\n\t\treturn u, err\n\t}\n\tlines, _ := splitLines(content)\n\tvar h *hunk\n\tlast := 0\n\ttoLine := 0\n\tfor _, edit := range edits {\n\t\t// Compute the zero-based line numbers of the edit start and end.\n\t\t// TODO(adonovan): opt: compute incrementally, avoid O(n^2).\n\t\tstart := strings.Count(content[:edit.Start], \"\\n\")\n\t\tend := strings.Count(content[:edit.End], \"\\n\")\n\t\tif edit.End == len(content) && len(content) > 0 && content[len(content)-1] != '\\n' {\n\t\t\tend++ // EOF counts as an implicit newline\n\t\t}\n\n\t\tswitch {\n\t\tcase h != nil && start == last:\n\t\t\t//direct extension\n\t\tcase h != nil && start <= last+gap:\n\t\t\t//within range of previous lines, add the joiners\n\t\t\taddEqualLines(h, lines, last, start)\n\t\tdefault:\n\t\t\t//need to start a new hunk\n\t\t\tif h != nil {\n\t\t\t\t// add the edge to the previous hunk\n\t\t\t\taddEqualLines(h, lines, last, last+contextLines)\n\t\t\t\tu.hunks = append(u.hunks, h)\n\t\t\t}\n\t\t\ttoLine += start - last\n\t\t\th = &hunk{\n\t\t\t\tfromLine: start + 1,\n\t\t\t\ttoLine:   toLine + 1,\n\t\t\t}\n\t\t\t// add the edge to the new hunk\n\t\t\tdelta := addEqualLines(h, lines, start-contextLines, start)\n\t\t\th.fromLine -= delta\n\t\t\th.toLine -= delta\n\t\t}\n\t\tlast = start\n\t\tfor i := start; i < end; i++ {\n\t\t\th.lines = append(h.lines, line{kind: opDelete, content: lines[i]})\n\t\t\tlast++\n\t\t}\n\t\tif edit.New != \"\" {\n\t\t\tv, _ := splitLines(edit.New)\n\t\t\tfor _, content := range v {\n\t\t\t\th.lines = append(h.lines, line{kind: opInsert, content: content})\n\t\t\t\ttoLine++\n\t\t\t}\n\t\t}\n\t}\n\tif h != nil {\n\t\t// add the edge to the final hunk\n\t\taddEqualLines(h, lines, last, last+contextLines)\n\t\tu.hunks = append(u.hunks, h)\n\t}\n\treturn u, nil\n}\n\n// split into lines removing a final empty line,\n// and also return the offsets of the line beginnings.\nfunc splitLines(text string) ([]string, []int) {\n\tvar lines []string\n\toffsets := []int{0}\n\tstart := 0\n\tfor i, r := range text {\n\t\tif r == '\\n' {\n\t\t\tlines = append(lines, text[start:i+1])\n\t\t\tstart = i + 1\n\t\t\toffsets = append(offsets, start)\n\t\t}\n\t}\n\tif start < len(text) {\n\t\tlines = append(lines, text[start:])\n\t\toffsets = append(offsets, len(text))\n\t}\n\treturn lines, offsets\n}\n\nfunc addEqualLines(h *hunk, lines []string, start, end int) int {\n\tdelta := 0\n\tfor i := start; i < end; i++ {\n\t\tif i < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif i >= len(lines) {\n\t\t\treturn delta\n\t\t}\n\t\th.lines = append(h.lines, line{kind: opEqual, content: lines[i]})\n\t\tdelta++\n\t}\n\treturn delta\n}\n\n// String converts a unified diff to the standard textual form for that diff.\n// The output of this function can be passed to tools like patch.\nfunc (u unified) String() string {\n\tif len(u.hunks) == 0 {\n\t\treturn \"\"\n\t}\n\tb := new(strings.Builder)\n\tfmt.Fprintf(b, \"--- %s\\n\", u.from)\n\tfmt.Fprintf(b, \"+++ %s\\n\", u.to)\n\tfor _, hunk := range u.hunks {\n\t\tfromCount, toCount := 0, 0\n\t\tfor _, l := range hunk.lines {\n\t\t\tswitch l.kind {\n\t\t\tcase opDelete:\n\t\t\t\tfromCount++\n\t\t\tcase opInsert:\n\t\t\t\ttoCount++\n\t\t\tdefault:\n\t\t\t\tfromCount++\n\t\t\t\ttoCount++\n\t\t\t}\n\t\t}\n\t\tfmt.Fprint(b, \"@@\")\n\t\tif fromCount > 1 {\n\t\t\tfmt.Fprintf(b, \" -%d,%d\", hunk.fromLine, fromCount)\n\t\t} else if hunk.fromLine == 1 && fromCount == 0 {\n\t\t\t// Match odd GNU diff -u behavior adding to empty file.\n\t\t\tfmt.Fprintf(b, \" -0,0\")\n\t\t} else {\n\t\t\tfmt.Fprintf(b, \" -%d\", hunk.fromLine)\n\t\t}\n\t\tif toCount > 1 {\n\t\t\tfmt.Fprintf(b, \" +%d,%d\", hunk.toLine, toCount)\n\t\t} else if hunk.toLine == 1 && toCount == 0 {\n\t\t\t// Match odd GNU diff -u behavior adding to empty file.\n\t\t\tfmt.Fprintf(b, \" +0,0\")\n\t\t} else {\n\t\t\tfmt.Fprintf(b, \" +%d\", hunk.toLine)\n\t\t}\n\t\tfmt.Fprint(b, \" @@\\n\")\n\t\tfor _, l := range hunk.lines {\n\t\t\tswitch l.kind {\n\t\t\tcase opDelete:\n\t\t\t\tfmt.Fprintf(b, \"-%s\", l.content)\n\t\t\tcase opInsert:\n\t\t\t\tfmt.Fprintf(b, \"+%s\", l.content)\n\t\t\tdefault:\n\t\t\t\tfmt.Fprintf(b, \" %s\", l.content)\n\t\t\t}\n\t\t\tif !strings.HasSuffix(l.content, \"\\n\") {\n\t\t\t\tfmt.Fprintf(b, \"\\n\\\\ No newline at end of file\\n\")\n\t\t\t}\n\t\t}\n\t}\n\treturn b.String()\n}\n\n// ApplyUnified applies the unified diffs.\nfunc ApplyUnified(udiffs, bef string) (string, error) {\n\tbefore := strings.Split(bef, \"\\n\")\n\tunif := strings.Split(udiffs, \"\\n\")\n\tvar got []string\n\tleft := 0\n\t// parse and apply the unified diffs\n\tfor _, l := range unif {\n\t\tif len(l) == 0 {\n\t\t\tcontinue // probably the last line (from Split)\n\t\t}\n\t\tswitch l[0] {\n\t\tcase '@': // The @@ line\n\t\t\tm := atregexp.FindStringSubmatch(l)\n\t\t\tfromLine, err := strconv.Atoi(m[1])\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"missing line number in %q\", l)\n\t\t\t}\n\t\t\t// before is a slice, so0-based; fromLine is 1-based\n\t\t\tfor ; left < fromLine-1; left++ {\n\t\t\t\tgot = append(got, before[left])\n\t\t\t}\n\t\tcase '+': // add this line\n\t\t\tif strings.HasPrefix(l, \"+++ \") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tgot = append(got, l[1:])\n\t\tcase '-': // delete this line\n\t\t\tif strings.HasPrefix(l, \"--- \") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tleft++\n\t\tcase ' ':\n\t\t\treturn \"\", fmt.Errorf(\"unexpected line %q\", l)\n\t\tdefault:\n\t\t\treturn \"\", fmt.Errorf(\"impossible unified %q\", udiffs)\n\t\t}\n\t}\n\t// copy any remaining lines\n\tfor ; left < len(before); left++ {\n\t\tgot = append(got, before[left])\n\t}\n\treturn strings.Join(got, \"\\n\"), nil\n}\n\n// The first number in the @@ lines is the line number in the 'before' data\nvar atregexp = regexp.MustCompile(`@@ -(\\d+).* @@`)\n"
  },
  {
    "path": "internal/diffp/diff.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package diffp implements a basic diff algorithm equivalent to patience diff.\n// It is a copy of internal/diff from the main Go repo, renamed to diffp to avoid\n// conflict with the existing golang.org/x/tools/internal/diff.\npackage diffp\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// A pair is a pair of values tracked for both the x and y side of a diff.\n// It is typically a pair of line indexes.\ntype pair struct{ x, y int }\n\n// Diff returns an anchored diff of the two texts old and new\n// in the “unified diff” format. If old and new are identical,\n// Diff returns a nil slice (no output).\n//\n// Unix diff implementations typically look for a diff with\n// the smallest number of lines inserted and removed,\n// which can in the worst case take time quadratic in the\n// number of lines in the texts. As a result, many implementations\n// either can be made to run for a long time or cut off the search\n// after a predetermined amount of work.\n//\n// In contrast, this implementation looks for a diff with the\n// smallest number of “unique” lines inserted and removed,\n// where unique means a line that appears just once in both old and new.\n// We call this an “anchored diff” because the unique lines anchor\n// the chosen matching regions. An anchored diff is usually clearer\n// than a standard diff, because the algorithm does not try to\n// reuse unrelated blank lines or closing braces.\n// The algorithm also guarantees to run in O(n log n) time\n// instead of the standard O(n²) time.\n//\n// Some systems call this approach a “patience diff,” named for\n// the “patience sorting” algorithm, itself named for a solitaire card game.\n// We avoid that name for two reasons. First, the name has been used\n// for a few different variants of the algorithm, so it is imprecise.\n// Second, the name is frequently interpreted as meaning that you have\n// to wait longer (to be patient) for the diff, meaning that it is a slower algorithm,\n// when in fact the algorithm is faster than the standard one.\nfunc Diff(oldName string, old []byte, newName string, new []byte) []byte {\n\tif bytes.Equal(old, new) {\n\t\treturn nil\n\t}\n\tx := lines(old)\n\ty := lines(new)\n\n\t// Print diff header.\n\tvar out bytes.Buffer\n\tfmt.Fprintf(&out, \"diff %s %s\\n\", oldName, newName)\n\tfmt.Fprintf(&out, \"--- %s\\n\", oldName)\n\tfmt.Fprintf(&out, \"+++ %s\\n\", newName)\n\n\t// Loop over matches to consider,\n\t// expanding each match to include surrounding lines,\n\t// and then printing diff chunks.\n\t// To avoid setup/teardown cases outside the loop,\n\t// tgs returns a leading {0,0} and trailing {len(x), len(y)} pair\n\t// in the sequence of matches.\n\tvar (\n\t\tdone  pair     // printed up to x[:done.x] and y[:done.y]\n\t\tchunk pair     // start lines of current chunk\n\t\tcount pair     // number of lines from each side in current chunk\n\t\tctext []string // lines for current chunk\n\t)\n\tfor _, m := range tgs(x, y) {\n\t\tif m.x < done.x {\n\t\t\t// Already handled scanning forward from earlier match.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Expand matching lines as far possible,\n\t\t// establishing that x[start.x:end.x] == y[start.y:end.y].\n\t\t// Note that on the first (or last) iteration we may (or definitey do)\n\t\t// have an empty match: start.x==end.x and start.y==end.y.\n\t\tstart := m\n\t\tfor start.x > done.x && start.y > done.y && x[start.x-1] == y[start.y-1] {\n\t\t\tstart.x--\n\t\t\tstart.y--\n\t\t}\n\t\tend := m\n\t\tfor end.x < len(x) && end.y < len(y) && x[end.x] == y[end.y] {\n\t\t\tend.x++\n\t\t\tend.y++\n\t\t}\n\n\t\t// Emit the mismatched lines before start into this chunk.\n\t\t// (No effect on first sentinel iteration, when start = {0,0}.)\n\t\tfor _, s := range x[done.x:start.x] {\n\t\t\tctext = append(ctext, \"-\"+s)\n\t\t\tcount.x++\n\t\t}\n\t\tfor _, s := range y[done.y:start.y] {\n\t\t\tctext = append(ctext, \"+\"+s)\n\t\t\tcount.y++\n\t\t}\n\n\t\t// If we're not at EOF and have too few common lines,\n\t\t// the chunk includes all the common lines and continues.\n\t\tconst C = 3 // number of context lines\n\t\tif (end.x < len(x) || end.y < len(y)) &&\n\t\t\t(end.x-start.x < C || (len(ctext) > 0 && end.x-start.x < 2*C)) {\n\t\t\tfor _, s := range x[start.x:end.x] {\n\t\t\t\tctext = append(ctext, \" \"+s)\n\t\t\t\tcount.x++\n\t\t\t\tcount.y++\n\t\t\t}\n\t\t\tdone = end\n\t\t\tcontinue\n\t\t}\n\n\t\t// End chunk with common lines for context.\n\t\tif len(ctext) > 0 {\n\t\t\tn := min(end.x-start.x, C)\n\t\t\tfor _, s := range x[start.x : start.x+n] {\n\t\t\t\tctext = append(ctext, \" \"+s)\n\t\t\t\tcount.x++\n\t\t\t\tcount.y++\n\t\t\t}\n\t\t\tdone = pair{start.x + n, start.y + n}\n\n\t\t\t// Format and emit chunk.\n\t\t\t// Convert line numbers to 1-indexed.\n\t\t\t// Special case: empty file shows up as 0,0 not 1,0.\n\t\t\tif count.x > 0 {\n\t\t\t\tchunk.x++\n\t\t\t}\n\t\t\tif count.y > 0 {\n\t\t\t\tchunk.y++\n\t\t\t}\n\t\t\tfmt.Fprintf(&out, \"@@ -%d,%d +%d,%d @@\\n\", chunk.x, count.x, chunk.y, count.y)\n\t\t\tfor _, s := range ctext {\n\t\t\t\tout.WriteString(s)\n\t\t\t}\n\t\t\tcount.x = 0\n\t\t\tcount.y = 0\n\t\t\tctext = ctext[:0]\n\t\t}\n\n\t\t// If we reached EOF, we're done.\n\t\tif end.x >= len(x) && end.y >= len(y) {\n\t\t\tbreak\n\t\t}\n\n\t\t// Otherwise start a new chunk.\n\t\tchunk = pair{end.x - C, end.y - C}\n\t\tfor _, s := range x[chunk.x:end.x] {\n\t\t\tctext = append(ctext, \" \"+s)\n\t\t\tcount.x++\n\t\t\tcount.y++\n\t\t}\n\t\tdone = end\n\t}\n\n\treturn out.Bytes()\n}\n\n// lines returns the lines in the file x, including newlines.\n// If the file does not end in a newline, one is supplied\n// along with a warning about the missing newline.\nfunc lines(x []byte) []string {\n\tl := strings.SplitAfter(string(x), \"\\n\")\n\tif l[len(l)-1] == \"\" {\n\t\tl = l[:len(l)-1]\n\t} else {\n\t\t// Treat last line as having a message about the missing newline attached,\n\t\t// using the same text as BSD/GNU diff (including the leading backslash).\n\t\tl[len(l)-1] += \"\\n\\\\ No newline at end of file\\n\"\n\t}\n\treturn l\n}\n\n// tgs returns the pairs of indexes of the longest common subsequence\n// of unique lines in x and y, where a unique line is one that appears\n// once in x and once in y.\n//\n// The longest common subsequence algorithm is as described in\n// Thomas G. Szymanski, “A Special Case of the Maximal Common\n// Subsequence Problem,” Princeton TR #170 (January 1975),\n// available at https://research.swtch.com/tgs170.pdf.\nfunc tgs(x, y []string) []pair {\n\t// Count the number of times each string appears in a and b.\n\t// We only care about 0, 1, many, counted as 0, -1, -2\n\t// for the x side and 0, -4, -8 for the y side.\n\t// Using negative numbers now lets us distinguish positive line numbers later.\n\tm := make(map[string]int)\n\tfor _, s := range x {\n\t\tif c := m[s]; c > -2 {\n\t\t\tm[s] = c - 1\n\t\t}\n\t}\n\tfor _, s := range y {\n\t\tif c := m[s]; c > -8 {\n\t\t\tm[s] = c - 4\n\t\t}\n\t}\n\n\t// Now unique strings can be identified by m[s] = -1+-4.\n\t//\n\t// Gather the indexes of those strings in x and y, building:\n\t//\txi[i] = increasing indexes of unique strings in x.\n\t//\tyi[i] = increasing indexes of unique strings in y.\n\t//\tinv[i] = index j such that x[xi[i]] = y[yi[j]].\n\tvar xi, yi, inv []int\n\tfor i, s := range y {\n\t\tif m[s] == -1+-4 {\n\t\t\tm[s] = len(yi)\n\t\t\tyi = append(yi, i)\n\t\t}\n\t}\n\tfor i, s := range x {\n\t\tif j, ok := m[s]; ok && j >= 0 {\n\t\t\txi = append(xi, i)\n\t\t\tinv = append(inv, j)\n\t\t}\n\t}\n\n\t// Apply Algorithm A from Szymanski's paper.\n\t// In those terms, A = J = inv and B = [0, n).\n\t// We add sentinel pairs {0,0}, and {len(x),len(y)}\n\t// to the returned sequence, to help the processing loop.\n\tJ := inv\n\tn := len(xi)\n\tT := make([]int, n)\n\tL := make([]int, n)\n\tfor i := range T {\n\t\tT[i] = n + 1\n\t}\n\tfor i := range n {\n\t\tk := sort.Search(n, func(k int) bool {\n\t\t\treturn T[k] >= J[i]\n\t\t})\n\t\tT[k] = J[i]\n\t\tL[i] = k + 1\n\t}\n\tk := 0\n\tfor _, v := range L {\n\t\tif k < v {\n\t\t\tk = v\n\t\t}\n\t}\n\tseq := make([]pair, 2+k)\n\tseq[1+k] = pair{len(x), len(y)} // sentinel at end\n\tlastj := n\n\tfor i := n - 1; i >= 0; i-- {\n\t\tif L[i] == k && J[i] < lastj {\n\t\t\tseq[k] = pair{xi[i], yi[J[i]]}\n\t\t\tk--\n\t\t}\n\t}\n\tseq[0] = pair{0, 0} // sentinel at start\n\treturn seq\n}\n"
  },
  {
    "path": "internal/diffp/diff_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage diffp\n\nimport (\n\t\"bytes\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc clean(text []byte) []byte {\n\ttext = bytes.ReplaceAll(text, []byte(\"$\\n\"), []byte(\"\\n\"))\n\ttext = bytes.TrimSuffix(text, []byte(\"^D\\n\"))\n\treturn text\n}\n\nfunc Test(t *testing.T) {\n\tfiles, _ := filepath.Glob(\"testdata/*.txt\")\n\tif len(files) == 0 {\n\t\tt.Fatalf(\"no testdata\")\n\t}\n\n\tfor _, file := range files {\n\t\tt.Run(filepath.Base(file), func(t *testing.T) {\n\t\t\ta, err := txtar.ParseFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(a.Files) != 3 || a.Files[2].Name != \"diff\" {\n\t\t\t\tt.Fatalf(\"%s: want three files, third named \\\"diff\\\"\", file)\n\t\t\t}\n\t\t\tdiffs := Diff(a.Files[0].Name, clean(a.Files[0].Data), a.Files[1].Name, clean(a.Files[1].Data))\n\t\t\twant := clean(a.Files[2].Data)\n\t\t\tif !bytes.Equal(diffs, want) {\n\t\t\t\tt.Fatalf(\"%s: have:\\n%s\\nwant:\\n%s\\n%s\", file,\n\t\t\t\t\tdiffs, want, Diff(\"have\", diffs, \"want\", want))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/diffp/testdata/allnew.txt",
    "content": "-- old --\n-- new --\na\nb\nc\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -0,0 +1,3 @@\n+a\n+b\n+c\n"
  },
  {
    "path": "internal/diffp/testdata/allold.txt",
    "content": "-- old --\na\nb\nc\n-- new --\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,3 +0,0 @@\n-a\n-b\n-c\n"
  },
  {
    "path": "internal/diffp/testdata/basic.txt",
    "content": "Example from Hunt and McIlroy, “An Algorithm for Differential File Comparison.”\nhttps://www.cs.dartmouth.edu/~doug/diff.pdf\n\n-- old --\na\nb\nc\nd\ne\nf\ng\n-- new --\nw\na\nb\nx\ny\nz\ne\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,7 +1,7 @@\n+w\n a\n b\n-c\n-d\n+x\n+y\n+z\n e\n-f\n-g\n"
  },
  {
    "path": "internal/diffp/testdata/dups.txt",
    "content": "-- old --\na\n\nb\n\nc\n\nd\n\ne\n\nf\n-- new --\na\n\nB\n\nC\n\nd\n\ne\n\nf\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,8 +1,8 @@\n a\n $\n-b\n-\n-c\n+B\n+\n+C\n $\n d\n $\n"
  },
  {
    "path": "internal/diffp/testdata/end.txt",
    "content": "-- old --\n1\n2\n3\n4\n5\n6\n7\neight\nnine\nten\neleven\n-- new --\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -5,7 +5,6 @@\n 5\n 6\n 7\n-eight\n-nine\n-ten\n-eleven\n+8\n+9\n+10\n"
  },
  {
    "path": "internal/diffp/testdata/eof.txt",
    "content": "-- old --\na\nb\nc^D\n-- new --\na\nb\nc^D\n-- diff --\n"
  },
  {
    "path": "internal/diffp/testdata/eof1.txt",
    "content": "-- old --\na\nb\nc\n-- new --\na\nb\nc^D\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,3 +1,3 @@\n a\n b\n-c\n+c\n\\ No newline at end of file\n"
  },
  {
    "path": "internal/diffp/testdata/eof2.txt",
    "content": "-- old --\na\nb\nc^D\n-- new --\na\nb\nc\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,3 +1,3 @@\n a\n b\n-c\n\\ No newline at end of file\n+c\n"
  },
  {
    "path": "internal/diffp/testdata/long.txt",
    "content": "-- old --\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n14½\n15\n16\n17\n18\n19\n20\n-- new --\n1\n2\n3\n4\n5\n6\n8\n9\n10\n11\n12\n13\n14\n17\n18\n19\n20\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -4,7 +4,6 @@\n 4\n 5\n 6\n-7\n 8\n 9\n 10\n@@ -12,9 +11,6 @@\n 12\n 13\n 14\n-14½\n-15\n-16\n 17\n 18\n 19\n"
  },
  {
    "path": "internal/diffp/testdata/same.txt",
    "content": "-- old --\nhello world\n-- new --\nhello world\n-- diff --\n"
  },
  {
    "path": "internal/diffp/testdata/start.txt",
    "content": "-- old --\ne\npi\n4\n5\n6\n7\n8\n9\n10\n-- new --\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,5 +1,6 @@\n-e\n-pi\n+1\n+2\n+3\n 4\n 5\n 6\n"
  },
  {
    "path": "internal/diffp/testdata/triv.txt",
    "content": "Another example from Hunt and McIlroy,\n“An Algorithm for Differential File Comparison.”\nhttps://www.cs.dartmouth.edu/~doug/diff.pdf\n\nAnchored diff gives up on finding anything,\nsince there are no unique lines.\n\n-- old --\na\nb\nc\na\nb\nb\na\n-- new --\nc\na\nb\na\nb\nc\n-- diff --\ndiff old new\n--- old\n+++ new\n@@ -1,7 +1,6 @@\n-a\n-b\n-c\n-a\n-b\n-b\n-a\n+c\n+a\n+b\n+a\n+b\n+c\n"
  },
  {
    "path": "internal/drivertest/driver.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The drivertest package provides a fake implementation of the go/packages\n// driver protocol that delegates to the go list driver. It may be used to test\n// programs such as gopls that specialize behavior when a go/packages driver is\n// in use.\n//\n// The driver is run as a child of the current process, by calling [RunIfChild]\n// at process start, and running go/packages with the environment variables set\n// by [Env].\npackage drivertest\n\nimport (\n\t\"encoding/json\"\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\nconst runAsDriverEnv = \"DRIVERTEST_RUN_AS_DRIVER\"\n\n// RunIfChild runs the current process as a go/packages driver, if configured\n// to do so by the current environment (see [Env]).\n//\n// Otherwise, RunIfChild is a no op.\nfunc RunIfChild() {\n\tif os.Getenv(runAsDriverEnv) != \"\" {\n\t\tmain()\n\t\tos.Exit(0)\n\t}\n}\n\n// Env returns additional environment variables for use in [packages.Config]\n// to enable the use of drivertest as the driver.\n//\n// t abstracts a *testing.T or log.Default().\nfunc Env(t interface{ Fatal(...any) }) []string {\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn []string{\"GOPACKAGESDRIVER=\" + exe, runAsDriverEnv + \"=1\"}\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tdec := json.NewDecoder(os.Stdin)\n\tvar request packages.DriverRequest\n\tif err := dec.Decode(&request); err != nil {\n\t\tlog.Fatalf(\"decoding request: %v\", err)\n\t}\n\n\tconfig := packages.Config{\n\t\tMode:       request.Mode,\n\t\tEnv:        append(request.Env, \"GOPACKAGESDRIVER=off\"), // avoid recursive invocation\n\t\tBuildFlags: request.BuildFlags,\n\t\tTests:      request.Tests,\n\t\tOverlay:    request.Overlay,\n\t}\n\tpkgs, err := packages.Load(&config, flag.Args()...)\n\tif err != nil {\n\t\tlog.Fatalf(\"load failed: %v\", err)\n\t}\n\n\tvar roots []string\n\tfor _, pkg := range pkgs {\n\t\troots = append(roots, pkg.ID)\n\t}\n\tvar allPackages []*packages.Package\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tnewImports := make(map[string]*packages.Package)\n\t\tfor path, imp := range pkg.Imports {\n\t\t\tnewImports[path] = &packages.Package{ID: imp.ID}\n\t\t}\n\t\tpkg.Imports = newImports\n\t\tallPackages = append(allPackages, pkg)\n\t})\n\n\tenc := json.NewEncoder(os.Stdout)\n\tresponse := packages.DriverResponse{\n\t\tRoots:    roots,\n\t\tPackages: allPackages,\n\t}\n\tif err := enc.Encode(response); err != nil {\n\t\tlog.Fatalf(\"encoding response: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "internal/drivertest/driver_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage drivertest_test\n\n// This file is both a test of drivertest and an example of how to use it in your own tests.\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/drivertest\"\n\t\"golang.org/x/tools/internal/packagesinternal\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestMain(m *testing.M) {\n\tdrivertest.RunIfChild()\n\n\tos.Exit(m.Run())\n}\n\nfunc TestDriverConformance(t *testing.T) {\n\ttestenv.NeedsExec(t)\n\n\tconst workspace = `\n-- go.mod --\nmodule example.com/m\n\ngo 1.20\n\n-- m.go --\npackage m\n\n-- lib/lib.go --\npackage lib\n`\n\n\tfs, err := txtar.FS(txtar.Parse([]byte(workspace)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdir := testfiles.CopyToTmp(t, fs)\n\n\t// TODO(rfindley): on mac, this is required to fix symlink path mismatches.\n\t// But why? Where is the symlink being evaluated in go/packages?\n\tdir, err = filepath.EvalSymlinks(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tbaseConfig := packages.Config{\n\t\tDir: dir,\n\t\tMode: packages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedCompiledGoFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedTypesSizes |\n\t\t\tpackages.NeedModule |\n\t\t\tpackages.NeedEmbedFiles |\n\t\t\tpackages.LoadMode(packagesinternal.DepsErrors) |\n\t\t\tpackages.NeedForTest,\n\t}\n\n\ttests := []struct {\n\t\tname    string\n\t\tquery   string\n\t\toverlay string\n\t}{\n\t\t{\n\t\t\tname:  \"load all\",\n\t\t\tquery: \"./...\",\n\t\t},\n\t\t{\n\t\t\tname:  \"overlays\",\n\t\t\tquery: \"./...\",\n\t\t\toverlay: `\n-- m.go --\npackage m\n\nimport . \"lib\"\n-- a/a.go --\npackage a\n`,\n\t\t},\n\t\t{\n\t\t\tname:  \"std\",\n\t\t\tquery: \"std\",\n\t\t},\n\t\t{\n\t\t\tname:  \"builtin\",\n\t\t\tquery: \"builtin\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tcfg := baseConfig\n\t\t\tif test.overlay != \"\" {\n\t\t\t\tcfg.Overlay = make(map[string][]byte)\n\t\t\t\tfor _, file := range txtar.Parse([]byte(test.overlay)).Files {\n\t\t\t\t\tname := filepath.Join(dir, filepath.FromSlash(file.Name))\n\t\t\t\t\tcfg.Overlay[name] = file.Data\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compare JSON-encoded packages with and without GOPACKAGESDRIVER.\n\t\t\t//\n\t\t\t// Note that this does not guarantee that the go/packages results\n\t\t\t// themselves are equivalent, only that their encoded JSON is equivalent.\n\t\t\t// Certain fields such as Module are intentionally omitted from external\n\t\t\t// drivers, because they don't make sense for an arbitrary build system.\n\t\t\tvar jsons []string\n\t\t\tfor _, env := range [][]string{\n\t\t\t\t{\"GOPACKAGESDRIVER=off\"},\n\t\t\t\tdrivertest.Env(t),\n\t\t\t} {\n\t\t\t\tcfg.Env = append(os.Environ(), env...)\n\t\t\t\tpkgs, err := packages.Load(&cfg, test.query)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"failed to load (env: %v): %v\", env, err)\n\t\t\t\t}\n\t\t\t\tdata, err := json.MarshalIndent(pkgs, \"\", \"\\t\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"failed to marshal (env: %v): %v\", env, err)\n\t\t\t\t}\n\t\t\t\tjsons = append(jsons, string(data))\n\t\t\t}\n\n\t\t\tlistJSON := jsons[0]\n\t\t\tdriverJSON := jsons[1]\n\n\t\t\tedits := diff.Lines(listJSON, driverJSON)\n\t\t\td, err := diff.ToUnified(\"go list\", \"driver\", listJSON, edits, 0)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif d != \"\" {\n\t\t\t\tt.Errorf(\"mismatching JSON:\\n%s\", d)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/edit/edit.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package edit implements buffered position-based editing of byte slices.\npackage edit\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\n// A Buffer is a queue of edits to apply to a given byte slice.\ntype Buffer struct {\n\told []byte\n\tq   edits\n}\n\n// An edit records a single text modification: change the bytes in [start,end) to new.\ntype edit struct {\n\tstart int\n\tend   int\n\tnew   string\n}\n\n// An edits is a list of edits that is sortable by start offset, breaking ties by end offset.\ntype edits []edit\n\nfunc (x edits) Len() int      { return len(x) }\nfunc (x edits) Swap(i, j int) { x[i], x[j] = x[j], x[i] }\nfunc (x edits) Less(i, j int) bool {\n\tif x[i].start != x[j].start {\n\t\treturn x[i].start < x[j].start\n\t}\n\treturn x[i].end < x[j].end\n}\n\n// NewBuffer returns a new buffer to accumulate changes to an initial data slice.\n// The returned buffer maintains a reference to the data, so the caller must ensure\n// the data is not modified until after the Buffer is done being used.\nfunc NewBuffer(old []byte) *Buffer {\n\treturn &Buffer{old: old}\n}\n\n// Insert inserts the new string at old[pos:pos].\nfunc (b *Buffer) Insert(pos int, new string) {\n\tif pos < 0 || pos > len(b.old) {\n\t\tpanic(\"invalid edit position\")\n\t}\n\tb.q = append(b.q, edit{pos, pos, new})\n}\n\n// Delete deletes the text old[start:end].\nfunc (b *Buffer) Delete(start, end int) {\n\tif end < start || start < 0 || end > len(b.old) {\n\t\tpanic(\"invalid edit position\")\n\t}\n\tb.q = append(b.q, edit{start, end, \"\"})\n}\n\n// Replace replaces old[start:end] with new.\nfunc (b *Buffer) Replace(start, end int, new string) {\n\tif end < start || start < 0 || end > len(b.old) {\n\t\tpanic(\"invalid edit position\")\n\t}\n\tb.q = append(b.q, edit{start, end, new})\n}\n\n// Bytes returns a new byte slice containing the original data\n// with the queued edits applied.\nfunc (b *Buffer) Bytes() []byte {\n\t// Sort edits by starting position and then by ending position.\n\t// Breaking ties by ending position allows insertions at point x\n\t// to be applied before a replacement of the text at [x, y).\n\tsort.Stable(b.q)\n\n\tvar new []byte\n\toffset := 0\n\tfor i, e := range b.q {\n\t\tif e.start < offset {\n\t\t\te0 := b.q[i-1]\n\t\t\tpanic(fmt.Sprintf(\"overlapping edits: [%d,%d)->%q, [%d,%d)->%q\", e0.start, e0.end, e0.new, e.start, e.end, e.new))\n\t\t}\n\t\tnew = append(new, b.old[offset:e.start]...)\n\t\toffset = e.end\n\t\tnew = append(new, e.new...)\n\t}\n\tnew = append(new, b.old[offset:]...)\n\treturn new\n}\n\n// String returns a string containing the original data\n// with the queued edits applied.\nfunc (b *Buffer) String() string {\n\treturn string(b.Bytes())\n}\n"
  },
  {
    "path": "internal/edit/edit_test.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage edit\n\nimport \"testing\"\n\nfunc TestEdit(t *testing.T) {\n\tb := NewBuffer([]byte(\"0123456789\"))\n\tb.Insert(8, \",7½,\")\n\tb.Replace(9, 10, \"the-end\")\n\tb.Insert(10, \"!\")\n\tb.Insert(4, \"3.14,\")\n\tb.Insert(4, \"π,\")\n\tb.Insert(4, \"3.15,\")\n\tb.Replace(3, 4, \"three,\")\n\twant := \"012three,3.14,π,3.15,4567,7½,8the-end!\"\n\n\ts := b.String()\n\tif s != want {\n\t\tt.Errorf(\"b.String() = %q, want %q\", s, want)\n\t}\n\tsb := b.Bytes()\n\tif string(sb) != want {\n\t\tt.Errorf(\"b.Bytes() = %q, want %q\", sb, want)\n\t}\n}\n"
  },
  {
    "path": "internal/event/bench_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage event_test\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"log\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\ntype Hooks struct {\n\tA func(ctx context.Context, a int) (context.Context, func())\n\tB func(ctx context.Context, b string) (context.Context, func())\n}\n\nvar (\n\taValue  = keys.NewInt(\"a\", \"\")\n\tbValue  = keys.NewString(\"b\", \"\")\n\taCount  = keys.NewInt(\"aCount\", \"Count of time A is called.\")\n\taStat   = keys.NewInt(\"aValue\", \"A value.\")\n\tbCount  = keys.NewInt(\"B\", \"Count of time B is called.\")\n\tbLength = keys.NewInt(\"BLen\", \"B length.\")\n\n\tBaseline = Hooks{\n\t\tA: func(ctx context.Context, a int) (context.Context, func()) {\n\t\t\treturn ctx, func() {}\n\t\t},\n\t\tB: func(ctx context.Context, b string) (context.Context, func()) {\n\t\t\treturn ctx, func() {}\n\t\t},\n\t}\n\n\tStdLog = Hooks{\n\t\tA: func(ctx context.Context, a int) (context.Context, func()) {\n\t\t\tlog.Printf(\"A where a=%d\", a)\n\t\t\treturn ctx, func() {}\n\t\t},\n\t\tB: func(ctx context.Context, b string) (context.Context, func()) {\n\t\t\tlog.Printf(\"B where b=%q\", b)\n\t\t\treturn ctx, func() {}\n\t\t},\n\t}\n\n\tLog = Hooks{\n\t\tA: func(ctx context.Context, a int) (context.Context, func()) {\n\t\t\tcore.Log1(ctx, \"A\", aValue.Of(a))\n\t\t\treturn ctx, func() {}\n\t\t},\n\t\tB: func(ctx context.Context, b string) (context.Context, func()) {\n\t\t\tcore.Log1(ctx, \"B\", bValue.Of(b))\n\t\t\treturn ctx, func() {}\n\t\t},\n\t}\n\n\tTrace = Hooks{\n\t\tA: func(ctx context.Context, a int) (context.Context, func()) {\n\t\t\treturn core.Start1(ctx, \"A\", aValue.Of(a))\n\t\t},\n\t\tB: func(ctx context.Context, b string) (context.Context, func()) {\n\t\t\treturn core.Start1(ctx, \"B\", bValue.Of(b))\n\t\t},\n\t}\n\n\tStats = Hooks{\n\t\tA: func(ctx context.Context, a int) (context.Context, func()) {\n\t\t\tcore.Metric1(ctx, aStat.Of(a))\n\t\t\tcore.Metric1(ctx, aCount.Of(1))\n\t\t\treturn ctx, func() {}\n\t\t},\n\t\tB: func(ctx context.Context, b string) (context.Context, func()) {\n\t\t\tcore.Metric1(ctx, bLength.Of(len(b)))\n\t\t\tcore.Metric1(ctx, bCount.Of(1))\n\t\t\treturn ctx, func() {}\n\t\t},\n\t}\n\n\tinitialList = []int{0, 1, 22, 333, 4444, 55555, 666666, 7777777}\n\tstringList  = []string{\n\t\t\"A value\",\n\t\t\"Some other value\",\n\t\t\"A nice longer value but not too long\",\n\t\t\"V\",\n\t\t\"\",\n\t\t\"ı\",\n\t\t\"prime count of values\",\n\t}\n)\n\ntype namedBenchmark struct {\n\tname string\n\ttest func(*testing.B)\n}\n\nfunc Benchmark(b *testing.B) {\n\tb.Run(\"Baseline\", Baseline.runBenchmark)\n\tb.Run(\"StdLog\", StdLog.runBenchmark)\n\tbenchmarks := []namedBenchmark{\n\t\t{\"Log\", Log.runBenchmark},\n\t\t{\"Trace\", Trace.runBenchmark},\n\t\t{\"Stats\", Stats.runBenchmark},\n\t}\n\n\tevent.SetExporter(nil)\n\tfor _, t := range benchmarks {\n\t\tb.Run(t.name+\"NoExporter\", t.test)\n\t}\n\n\tevent.SetExporter(noopExporter)\n\tfor _, t := range benchmarks {\n\t\tb.Run(t.name+\"Noop\", t.test)\n\t}\n\n\tevent.SetExporter(export.Spans(export.LogWriter(io.Discard, false)))\n\tfor _, t := range benchmarks {\n\t\tb.Run(t.name, t.test)\n\t}\n}\n\nfunc A(ctx context.Context, hooks Hooks, a int) int {\n\tctx, done := hooks.A(ctx, a)\n\tdefer done()\n\treturn B(ctx, hooks, a, stringList[a%len(stringList)])\n}\n\nfunc B(ctx context.Context, hooks Hooks, a int, b string) int {\n\t_, done := hooks.B(ctx, b)\n\tdefer done()\n\treturn a + len(b)\n}\n\nfunc (hooks Hooks) runBenchmark(b *testing.B) {\n\tctx := context.Background()\n\tb.ReportAllocs()\n\n\tvar acc int\n\tfor b.Loop() {\n\t\tfor _, value := range initialList {\n\t\t\tacc += A(ctx, hooks, value)\n\t\t}\n\t}\n}\n\nfunc init() {\n\tlog.SetOutput(io.Discard)\n}\n\nfunc noopExporter(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\treturn ctx\n}\n"
  },
  {
    "path": "internal/event/core/event.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package core provides support for event based telemetry.\npackage core\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Event holds the information about an event of note that occurred.\ntype Event struct {\n\tat time.Time\n\n\t// As events are often on the stack, storing the first few labels directly\n\t// in the event can avoid an allocation at all for the very common cases of\n\t// simple events.\n\t// The length needs to be large enough to cope with the majority of events\n\t// but no so large as to cause undue stack pressure.\n\t// A log message with two values will use 3 labels (one for each value and\n\t// one for the message itself).\n\n\tstatic  [3]label.Label // inline storage for the first few labels\n\tdynamic []label.Label  // dynamically sized storage for remaining labels\n}\n\nfunc (ev Event) At() time.Time { return ev.at }\n\nfunc (ev Event) Format(f fmt.State, r rune) {\n\tif !ev.at.IsZero() {\n\t\tfmt.Fprint(f, ev.at.Format(\"2006/01/02 15:04:05 \"))\n\t}\n\tfor l := range ev.Labels() {\n\t\tfmt.Fprintf(f, \"\\n\\t%v\", l)\n\t}\n}\n\nfunc (ev Event) Valid(index int) bool {\n\treturn index >= 0 && index < len(ev.static)+len(ev.dynamic)\n}\n\nfunc (ev Event) Label(index int) label.Label {\n\tif index < len(ev.static) {\n\t\treturn ev.static[index]\n\t}\n\treturn ev.dynamic[index-len(ev.static)]\n}\n\n// Labels returns an iterator over the event's valid labels.\nfunc (ev Event) Labels() iter.Seq[label.Label] {\n\treturn func(yield func(label.Label) bool) {\n\t\tfor _, l := range ev.static {\n\t\t\tif l.Valid() && !yield(l) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tfor _, l := range ev.dynamic {\n\t\t\tif l.Valid() && !yield(l) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (ev Event) Find(key label.Key) label.Label {\n\tfor _, l := range ev.static {\n\t\tif l.Key() == key {\n\t\t\treturn l\n\t\t}\n\t}\n\tfor _, l := range ev.dynamic {\n\t\tif l.Key() == key {\n\t\t\treturn l\n\t\t}\n\t}\n\treturn label.Label{}\n}\n\nfunc MakeEvent(static [3]label.Label, labels []label.Label) Event {\n\treturn Event{\n\t\tstatic:  static,\n\t\tdynamic: labels,\n\t}\n}\n\n// CloneEvent event returns a copy of the event with the time adjusted to at.\nfunc CloneEvent(ev Event, at time.Time) Event {\n\tev.at = at\n\treturn ev\n}\n"
  },
  {
    "path": "internal/event/core/export.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage core\n\nimport (\n\t\"context\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Exporter is a function that handles events.\n// It may return a modified context and event.\ntype Exporter func(context.Context, Event, label.Map) context.Context\n\nvar exporter atomic.Pointer[Exporter]\n\n// SetExporter sets the global exporter function that handles all events.\n// The exporter is called synchronously from the event call site, so it should\n// return quickly so as not to hold up user code.\nfunc SetExporter(e Exporter) {\n\tif e == nil {\n\t\t// &e is always valid, and so p is always valid, but for the early abort\n\t\t// of ProcessEvent to be efficient it needs to make the nil check on the\n\t\t// pointer without having to dereference it, so we make the nil function\n\t\t// also a nil pointer\n\t\texporter.Store(nil)\n\t} else {\n\t\texporter.Store(&e)\n\t}\n}\n\n// deliver is called to deliver an event to the supplied exporter.\n// it will fill in the time.\nfunc deliver(ctx context.Context, exporter Exporter, ev Event) context.Context {\n\t// add the current time to the event\n\tev.at = time.Now()\n\t// hand the event off to the current exporter\n\treturn exporter(ctx, ev, ev)\n}\n\n// Export is called to deliver an event to the global exporter if set.\nfunc Export(ctx context.Context, ev Event) context.Context {\n\t// get the global exporter and abort early if there is not one\n\texporterPtr := exporter.Load()\n\tif exporterPtr == nil {\n\t\treturn ctx\n\t}\n\treturn deliver(ctx, *exporterPtr, ev)\n}\n\n// ExportPair is called to deliver a start event to the supplied exporter.\n// It also returns a function that will deliver the end event to the same\n// exporter.\n// It will fill in the time.\nfunc ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) {\n\t// get the global exporter and abort early if there is not one\n\texporterPtr := exporter.Load()\n\tif exporterPtr == nil {\n\t\treturn ctx, func() {}\n\t}\n\tctx = deliver(ctx, *exporterPtr, begin)\n\treturn ctx, func() { deliver(ctx, *exporterPtr, end) }\n}\n"
  },
  {
    "path": "internal/event/core/fast.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage core\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Log1 takes a message and one label delivers a log event to the exporter.\n// It is a customized version of Print that is faster and does no allocation.\nfunc Log1(ctx context.Context, message string, t1 label.Label) {\n\tExport(ctx, MakeEvent([3]label.Label{\n\t\tkeys.Msg.Of(message),\n\t\tt1,\n\t}, nil))\n}\n\n// Log2 takes a message and two labels and delivers a log event to the exporter.\n// It is a customized version of Print that is faster and does no allocation.\nfunc Log2(ctx context.Context, message string, t1 label.Label, t2 label.Label) {\n\tExport(ctx, MakeEvent([3]label.Label{\n\t\tkeys.Msg.Of(message),\n\t\tt1,\n\t\tt2,\n\t}, nil))\n}\n\n// Metric1 sends a label event to the exporter with the supplied labels.\nfunc Metric1(ctx context.Context, t1 label.Label) context.Context {\n\treturn Export(ctx, MakeEvent([3]label.Label{\n\t\tkeys.Metric.New(),\n\t\tt1,\n\t}, nil))\n}\n\n// Metric2 sends a label event to the exporter with the supplied labels.\nfunc Metric2(ctx context.Context, t1, t2 label.Label) context.Context {\n\treturn Export(ctx, MakeEvent([3]label.Label{\n\t\tkeys.Metric.New(),\n\t\tt1,\n\t\tt2,\n\t}, nil))\n}\n\n// Start1 sends a span start event with the supplied label list to the exporter.\n// It also returns a function that will end the span, which should normally be\n// deferred.\nfunc Start1(ctx context.Context, name string, t1 label.Label) (context.Context, func()) {\n\treturn ExportPair(ctx,\n\t\tMakeEvent([3]label.Label{\n\t\t\tkeys.Start.Of(name),\n\t\t\tt1,\n\t\t}, nil),\n\t\tMakeEvent([3]label.Label{\n\t\t\tkeys.End.New(),\n\t\t}, nil))\n}\n\n// Start2 sends a span start event with the supplied label list to the exporter.\n// It also returns a function that will end the span, which should normally be\n// deferred.\nfunc Start2(ctx context.Context, name string, t1, t2 label.Label) (context.Context, func()) {\n\treturn ExportPair(ctx,\n\t\tMakeEvent([3]label.Label{\n\t\t\tkeys.Start.Of(name),\n\t\t\tt1,\n\t\t\tt2,\n\t\t}, nil),\n\t\tMakeEvent([3]label.Label{\n\t\t\tkeys.End.New(),\n\t\t}, nil))\n}\n"
  },
  {
    "path": "internal/event/doc.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package event provides a set of packages that cover the main\n// concepts of telemetry in an implementation agnostic way.\npackage event\n"
  },
  {
    "path": "internal/event/event.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage event\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Exporter is a function that handles events.\n// It may return a modified context and event.\ntype Exporter func(context.Context, core.Event, label.Map) context.Context\n\n// SetExporter sets the global exporter function that handles all events.\n// The exporter is called synchronously from the event call site, so it should\n// return quickly so as not to hold up user code.\nfunc SetExporter(e Exporter) {\n\tcore.SetExporter(core.Exporter(e))\n}\n\n// Log takes a message and a label list and combines them into a single event\n// before delivering them to the exporter.\nfunc Log(ctx context.Context, message string, labels ...label.Label) {\n\tcore.Export(ctx, core.MakeEvent([3]label.Label{\n\t\tkeys.Msg.Of(message),\n\t}, labels))\n}\n\n// IsLog returns true if the event was built by the Log function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsLog(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Msg\n}\n\n// Error takes a message and a label list and combines them into a single event\n// before delivering them to the exporter. It captures the error in the\n// delivered event.\nfunc Error(ctx context.Context, message string, err error, labels ...label.Label) {\n\tcore.Export(ctx, core.MakeEvent([3]label.Label{\n\t\tkeys.Msg.Of(message),\n\t\tkeys.Err.Of(err),\n\t}, labels))\n}\n\n// IsError returns true if the event was built by the Error function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsError(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Msg &&\n\t\tev.Label(1).Key() == keys.Err\n}\n\n// Metric sends a label event to the exporter with the supplied labels.\nfunc Metric(ctx context.Context, labels ...label.Label) {\n\tcore.Export(ctx, core.MakeEvent([3]label.Label{\n\t\tkeys.Metric.New(),\n\t}, labels))\n}\n\n// IsMetric returns true if the event was built by the Metric function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsMetric(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Metric\n}\n\n// Label sends a label event to the exporter with the supplied labels.\nfunc Label(ctx context.Context, labels ...label.Label) context.Context {\n\treturn core.Export(ctx, core.MakeEvent([3]label.Label{\n\t\tkeys.Label.New(),\n\t}, labels))\n}\n\n// IsLabel returns true if the event was built by the Label function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsLabel(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Label\n}\n\n// Start sends a span start event with the supplied label list to the exporter.\n// It also returns a function that will end the span, which should normally be\n// deferred.\nfunc Start(ctx context.Context, name string, labels ...label.Label) (context.Context, func()) {\n\treturn core.ExportPair(ctx,\n\t\tcore.MakeEvent([3]label.Label{\n\t\t\tkeys.Start.Of(name),\n\t\t}, labels),\n\t\tcore.MakeEvent([3]label.Label{\n\t\t\tkeys.End.New(),\n\t\t}, nil))\n}\n\n// IsStart returns true if the event was built by the Start function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsStart(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Start\n}\n\n// IsEnd returns true if the event was built by the End function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsEnd(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.End\n}\n\n// Detach returns a context without an associated span.\n// This allows the creation of spans that are not children of the current span.\nfunc Detach(ctx context.Context) context.Context {\n\treturn core.Export(ctx, core.MakeEvent([3]label.Label{\n\t\tkeys.Detach.New(),\n\t}, nil))\n}\n\n// IsDetach returns true if the event was built by the Detach function.\n// It is intended to be used in exporters to identify the semantics of the\n// event when deciding what to do with it.\nfunc IsDetach(ev core.Event) bool {\n\treturn ev.Label(0).Key() == keys.Detach\n}\n"
  },
  {
    "path": "internal/event/export/eventtest/eventtest.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package eventtest supports logging events to a test.\n// You can use NewContext to create a context that knows how to deliver\n// telemetry events back to the test.\n// You must use this context or a derived one anywhere you want telemetry to be\n// correctly routed back to the test it was constructed with.\n// Any events delivered to a background context will be dropped.\n//\n// Importing this package will cause it to register a new global telemetry\n// exporter that understands the special contexts returned by NewContext.\n// This means you should not import this package if you are not going to call\n// NewContext.\npackage eventtest\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nfunc init() {\n\te := &testExporter{buffer: &bytes.Buffer{}}\n\te.logger = export.LogWriter(e.buffer, false)\n\n\tevent.SetExporter(export.Spans(e.processEvent))\n}\n\ntype testingKeyType int\n\nconst testingKey = testingKeyType(0)\n\n// NewContext returns a context you should use for the active test.\nfunc NewContext(ctx context.Context, t testing.TB) context.Context {\n\treturn context.WithValue(ctx, testingKey, t)\n}\n\ntype testExporter struct {\n\tmu     sync.Mutex\n\tbuffer *bytes.Buffer\n\tlogger event.Exporter\n}\n\nfunc (w *testExporter) processEvent(ctx context.Context, ev core.Event, tm label.Map) context.Context {\n\tw.mu.Lock()\n\tdefer w.mu.Unlock()\n\t// build our log message in buffer\n\tresult := w.logger(ctx, ev, tm)\n\tv := ctx.Value(testingKey)\n\t// get the testing.TB\n\tif w.buffer.Len() > 0 && v != nil {\n\t\tv.(testing.TB).Log(w.buffer)\n\t}\n\tw.buffer.Truncate(0)\n\treturn result\n}\n"
  },
  {
    "path": "internal/event/export/id.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export\n\nimport (\n\tcrand \"crypto/rand\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\t\"sync/atomic\"\n)\n\ntype TraceID [16]byte\ntype SpanID [8]byte\n\nfunc (t TraceID) String() string {\n\treturn fmt.Sprintf(\"%02x\", t[:])\n}\n\nfunc (s SpanID) String() string {\n\treturn fmt.Sprintf(\"%02x\", s[:])\n}\n\nfunc (s SpanID) IsValid() bool {\n\treturn s != SpanID{}\n}\n\nvar (\n\tgenerationMu sync.Mutex\n\tnextSpanID   uint64\n\tspanIDInc    uint64\n\n\ttraceIDAdd  [2]uint64\n\ttraceIDRand *rand.Rand\n)\n\nfunc initGenerator() {\n\tvar rngSeed int64\n\tfor _, p := range []any{\n\t\t&rngSeed, &traceIDAdd, &nextSpanID, &spanIDInc,\n\t} {\n\t\tbinary.Read(crand.Reader, binary.LittleEndian, p)\n\t}\n\ttraceIDRand = rand.New(rand.NewSource(rngSeed))\n\tspanIDInc |= 1\n}\n\nfunc newTraceID() TraceID {\n\tgenerationMu.Lock()\n\tdefer generationMu.Unlock()\n\tif traceIDRand == nil {\n\t\tinitGenerator()\n\t}\n\tvar tid [16]byte\n\tbinary.LittleEndian.PutUint64(tid[0:8], traceIDRand.Uint64()+traceIDAdd[0])\n\tbinary.LittleEndian.PutUint64(tid[8:16], traceIDRand.Uint64()+traceIDAdd[1])\n\treturn tid\n}\n\nfunc newSpanID() SpanID {\n\tvar id uint64\n\tfor id == 0 {\n\t\tid = atomic.AddUint64(&nextSpanID, spanIDInc)\n\t}\n\tvar sid [8]byte\n\tbinary.LittleEndian.PutUint64(sid[:], id)\n\treturn sid\n}\n"
  },
  {
    "path": "internal/event/export/labels.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export\n\nimport (\n\t\"context\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Labels builds an exporter that manipulates the context using the event.\n// If the event is type IsLabel or IsStartSpan then it returns a context updated\n// with label values from the event.\n// For all other event types the event labels will be updated with values from the\n// context if they are missing.\nfunc Labels(output event.Exporter) event.Exporter {\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tstored, _ := ctx.Value(labelContextKey).(label.Map)\n\t\tif event.IsLabel(ev) || event.IsStart(ev) {\n\t\t\t// update the label map stored in the context\n\t\t\tfromEvent := label.Map(ev)\n\t\t\tif stored == nil {\n\t\t\t\tstored = fromEvent\n\t\t\t} else {\n\t\t\t\tstored = label.MergeMaps(fromEvent, stored)\n\t\t\t}\n\t\t\tctx = context.WithValue(ctx, labelContextKey, stored)\n\t\t}\n\t\t// add the stored label context to the label map\n\t\tlm = label.MergeMaps(lm, stored)\n\t\treturn output(ctx, ev, lm)\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/log.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// LogWriter returns an Exporter that logs events to the supplied writer.\n// If onlyErrors is true it does not log any event that did not have an\n// associated error.\n// It ignores all telemetry other than log events.\nfunc LogWriter(w io.Writer, onlyErrors bool) event.Exporter {\n\tlw := &logWriter{writer: w, onlyErrors: onlyErrors}\n\treturn lw.ProcessEvent\n}\n\ntype logWriter struct {\n\tmu         sync.Mutex\n\tprinter    Printer\n\twriter     io.Writer\n\tonlyErrors bool\n}\n\nfunc (w *logWriter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\tswitch {\n\tcase event.IsLog(ev):\n\t\tif w.onlyErrors && !event.IsError(ev) {\n\t\t\treturn ctx\n\t\t}\n\t\tw.mu.Lock()\n\t\tdefer w.mu.Unlock()\n\t\tw.printer.WriteEvent(w.writer, ev, lm)\n\n\tcase event.IsStart(ev):\n\t\tif span := GetSpan(ctx); span != nil {\n\t\t\tfmt.Fprintf(w.writer, \"start: %v %v\", span.Name, span.ID)\n\t\t\tif span.ParentID.IsValid() {\n\t\t\t\tfmt.Fprintf(w.writer, \"[%v]\", span.ParentID)\n\t\t\t}\n\t\t}\n\tcase event.IsEnd(ev):\n\t\tif span := GetSpan(ctx); span != nil {\n\t\t\tfmt.Fprintf(w.writer, \"finish: %v %v\", span.Name, span.ID)\n\t\t}\n\t}\n\treturn ctx\n}\n"
  },
  {
    "path": "internal/event/export/log_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nfunc ExampleLog() {\n\tctx := context.Background()\n\tevent.SetExporter(timeFixer(export.LogWriter(os.Stdout, false)))\n\tanInt := keys.NewInt(\"myInt\", \"an integer\")\n\taString := keys.NewString(\"myString\", \"a string\")\n\tevent.Log(ctx, \"my event\", anInt.Of(6))\n\tevent.Error(ctx, \"error event\", errors.New(\"an error\"), aString.Of(\"some string value\"))\n\t// Output:\n\t// 2020/03/05 14:27:48 my event\n\t// \tmyInt=6\n\t// 2020/03/05 14:27:48 error event: an error\n\t// \tmyString=\"some string value\"\n}\n\nfunc timeFixer(output event.Exporter) event.Exporter {\n\tat, _ := time.Parse(time.RFC3339Nano, \"2020-03-05T14:27:48Z\")\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tcopy := core.CloneEvent(ev, at)\n\t\treturn output(ctx, copy, lm)\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/metric/data.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage metric\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Data represents a single point in the time series of a metric.\n// This provides the common interface to all metrics no matter their data\n// format.\n// To get the actual values for the metric you must type assert to a concrete\n// metric type.\ntype Data interface {\n\t// Handle returns the metric handle this data is for.\n\t//TODO: rethink the concept of metric handles\n\tHandle() string\n\t// Groups reports the rows that currently exist for this metric.\n\tGroups() [][]label.Label\n}\n\n// Int64Data is a concrete implementation of Data for int64 scalar metrics.\ntype Int64Data struct {\n\t// Info holds the original construction information.\n\tInfo *Scalar\n\t// IsGauge is true for metrics that track values, rather than increasing over time.\n\tIsGauge bool\n\t// Rows holds the per group values for the metric.\n\tRows []int64\n\t// EndTime is the last time this metric was updated.\n\tEndTime time.Time\n\n\tgroups [][]label.Label\n\tkey    *keys.Int\n}\n\n// Float64Data is a concrete implementation of Data for float64 scalar metrics.\ntype Float64Data struct {\n\t// Info holds the original construction information.\n\tInfo *Scalar\n\t// IsGauge is true for metrics that track values, rather than increasing over time.\n\tIsGauge bool\n\t// Rows holds the per group values for the metric.\n\tRows []float64\n\t// EndTime is the last time this metric was updated.\n\tEndTime time.Time\n\n\tgroups [][]label.Label\n\tkey    *keys.Float\n}\n\n// HistogramInt64Data is a concrete implementation of Data for int64 histogram metrics.\ntype HistogramInt64Data struct {\n\t// Info holds the original construction information.\n\tInfo *HistogramInt64\n\t// Rows holds the per group values for the metric.\n\tRows []*HistogramInt64Row\n\t// EndTime is the last time this metric was updated.\n\tEndTime time.Time\n\n\tgroups [][]label.Label\n\tkey    *keys.Int\n}\n\n// HistogramInt64Row holds the values for a single row of a HistogramInt64Data.\ntype HistogramInt64Row struct {\n\t// Values is the counts per bucket.\n\tValues []int64\n\t// Count is the total count.\n\tCount int64\n\t// Sum is the sum of all the values recorded.\n\tSum int64\n\t// Min is the smallest recorded value.\n\tMin int64\n\t// Max is the largest recorded value.\n\tMax int64\n}\n\n// HistogramFloat64Data is a concrete implementation of Data for float64 histogram metrics.\ntype HistogramFloat64Data struct {\n\t// Info holds the original construction information.\n\tInfo *HistogramFloat64\n\t// Rows holds the per group values for the metric.\n\tRows []*HistogramFloat64Row\n\t// EndTime is the last time this metric was updated.\n\tEndTime time.Time\n\n\tgroups [][]label.Label\n\tkey    *keys.Float\n}\n\n// HistogramFloat64Row holds the values for a single row of a HistogramFloat64Data.\ntype HistogramFloat64Row struct {\n\t// Values is the counts per bucket.\n\tValues []int64\n\t// Count is the total count.\n\tCount int64\n\t// Sum is the sum of all the values recorded.\n\tSum float64\n\t// Min is the smallest recorded value.\n\tMin float64\n\t// Max is the largest recorded value.\n\tMax float64\n}\n\nfunc labelListEqual(a, b []label.Label) bool {\n\t//TODO: make this more efficient\n\treturn fmt.Sprint(a) == fmt.Sprint(b)\n}\n\nfunc labelListLess(a, b []label.Label) bool {\n\t//TODO: make this more efficient\n\treturn fmt.Sprint(a) < fmt.Sprint(b)\n}\n\nfunc getGroup(lm label.Map, g *[][]label.Label, keys []label.Key) (int, bool) {\n\tgroup := make([]label.Label, len(keys))\n\tfor i, key := range keys {\n\t\tl := lm.Find(key)\n\t\tif l.Valid() {\n\t\t\tgroup[i] = l\n\t\t}\n\t}\n\told := *g\n\tindex := sort.Search(len(old), func(i int) bool {\n\t\treturn !labelListLess(old[i], group)\n\t})\n\tif index < len(old) && labelListEqual(group, old[index]) {\n\t\t// not a new group\n\t\treturn index, false\n\t}\n\t*g = make([][]label.Label, len(old)+1)\n\tcopy(*g, old[:index])\n\tcopy((*g)[index+1:], old[index:])\n\t(*g)[index] = group\n\treturn index, true\n}\n\nfunc (data *Int64Data) Handle() string          { return data.Info.Name }\nfunc (data *Int64Data) Groups() [][]label.Label { return data.groups }\n\nfunc (data *Int64Data) modify(at time.Time, lm label.Map, f func(v int64) int64) Data {\n\tindex, insert := getGroup(lm, &data.groups, data.Info.Keys)\n\told := data.Rows\n\tif insert {\n\t\tdata.Rows = make([]int64, len(old)+1)\n\t\tcopy(data.Rows, old[:index])\n\t\tcopy(data.Rows[index+1:], old[index:])\n\t} else {\n\t\tdata.Rows = make([]int64, len(old))\n\t\tcopy(data.Rows, old)\n\t}\n\tdata.Rows[index] = f(data.Rows[index])\n\tdata.EndTime = at\n\tfrozen := *data\n\treturn &frozen\n}\n\nfunc (data *Int64Data) count(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v int64) int64 {\n\t\treturn v + 1\n\t})\n}\n\nfunc (data *Int64Data) sum(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v int64) int64 {\n\t\treturn v + data.key.From(l)\n\t})\n}\n\nfunc (data *Int64Data) latest(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v int64) int64 {\n\t\treturn data.key.From(l)\n\t})\n}\n\nfunc (data *Float64Data) Handle() string          { return data.Info.Name }\nfunc (data *Float64Data) Groups() [][]label.Label { return data.groups }\n\nfunc (data *Float64Data) modify(at time.Time, lm label.Map, f func(v float64) float64) Data {\n\tindex, insert := getGroup(lm, &data.groups, data.Info.Keys)\n\told := data.Rows\n\tif insert {\n\t\tdata.Rows = make([]float64, len(old)+1)\n\t\tcopy(data.Rows, old[:index])\n\t\tcopy(data.Rows[index+1:], old[index:])\n\t} else {\n\t\tdata.Rows = make([]float64, len(old))\n\t\tcopy(data.Rows, old)\n\t}\n\tdata.Rows[index] = f(data.Rows[index])\n\tdata.EndTime = at\n\tfrozen := *data\n\treturn &frozen\n}\n\nfunc (data *Float64Data) sum(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v float64) float64 {\n\t\treturn v + data.key.From(l)\n\t})\n}\n\nfunc (data *Float64Data) latest(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v float64) float64 {\n\t\treturn data.key.From(l)\n\t})\n}\n\nfunc (data *HistogramInt64Data) Handle() string          { return data.Info.Name }\nfunc (data *HistogramInt64Data) Groups() [][]label.Label { return data.groups }\n\nfunc (data *HistogramInt64Data) modify(at time.Time, lm label.Map, f func(v *HistogramInt64Row)) Data {\n\tindex, insert := getGroup(lm, &data.groups, data.Info.Keys)\n\told := data.Rows\n\tvar v HistogramInt64Row\n\tif insert {\n\t\tdata.Rows = make([]*HistogramInt64Row, len(old)+1)\n\t\tcopy(data.Rows, old[:index])\n\t\tcopy(data.Rows[index+1:], old[index:])\n\t} else {\n\t\tdata.Rows = make([]*HistogramInt64Row, len(old))\n\t\tcopy(data.Rows, old)\n\t\tv = *data.Rows[index]\n\t}\n\toldValues := v.Values\n\tv.Values = make([]int64, len(data.Info.Buckets))\n\tcopy(v.Values, oldValues)\n\tf(&v)\n\tdata.Rows[index] = &v\n\tdata.EndTime = at\n\tfrozen := *data\n\treturn &frozen\n}\n\nfunc (data *HistogramInt64Data) record(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v *HistogramInt64Row) {\n\t\tvalue := data.key.From(l)\n\t\tv.Sum += value\n\t\tif v.Min > value || v.Count == 0 {\n\t\t\tv.Min = value\n\t\t}\n\t\tif v.Max < value || v.Count == 0 {\n\t\t\tv.Max = value\n\t\t}\n\t\tv.Count++\n\t\tfor i, b := range data.Info.Buckets {\n\t\t\tif value <= b {\n\t\t\t\tv.Values[i]++\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc (data *HistogramFloat64Data) Handle() string          { return data.Info.Name }\nfunc (data *HistogramFloat64Data) Groups() [][]label.Label { return data.groups }\n\nfunc (data *HistogramFloat64Data) modify(at time.Time, lm label.Map, f func(v *HistogramFloat64Row)) Data {\n\tindex, insert := getGroup(lm, &data.groups, data.Info.Keys)\n\told := data.Rows\n\tvar v HistogramFloat64Row\n\tif insert {\n\t\tdata.Rows = make([]*HistogramFloat64Row, len(old)+1)\n\t\tcopy(data.Rows, old[:index])\n\t\tcopy(data.Rows[index+1:], old[index:])\n\t} else {\n\t\tdata.Rows = make([]*HistogramFloat64Row, len(old))\n\t\tcopy(data.Rows, old)\n\t\tv = *data.Rows[index]\n\t}\n\toldValues := v.Values\n\tv.Values = make([]int64, len(data.Info.Buckets))\n\tcopy(v.Values, oldValues)\n\tf(&v)\n\tdata.Rows[index] = &v\n\tdata.EndTime = at\n\tfrozen := *data\n\treturn &frozen\n}\n\nfunc (data *HistogramFloat64Data) record(at time.Time, lm label.Map, l label.Label) Data {\n\treturn data.modify(at, lm, func(v *HistogramFloat64Row) {\n\t\tvalue := data.key.From(l)\n\t\tv.Sum += value\n\t\tif v.Min > value || v.Count == 0 {\n\t\t\tv.Min = value\n\t\t}\n\t\tif v.Max < value || v.Count == 0 {\n\t\t\tv.Max = value\n\t\t}\n\t\tv.Count++\n\t\tfor i, b := range data.Info.Buckets {\n\t\t\tif value <= b {\n\t\t\t\tv.Values[i]++\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "internal/event/export/metric/exporter.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package metric aggregates events into metrics that can be exported.\npackage metric\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nvar Entries = keys.New(\"metric_entries\", \"The set of metrics calculated for an event\")\n\ntype Config struct {\n\tsubscribers map[any][]subscriber\n}\n\ntype subscriber func(time.Time, label.Map, label.Label) Data\n\nfunc (e *Config) subscribe(key label.Key, s subscriber) {\n\tif e.subscribers == nil {\n\t\te.subscribers = make(map[any][]subscriber)\n\t}\n\te.subscribers[key] = append(e.subscribers[key], s)\n}\n\nfunc (e *Config) Exporter(output event.Exporter) event.Exporter {\n\tvar mu sync.Mutex\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tif !event.IsMetric(ev) {\n\t\t\treturn output(ctx, ev, lm)\n\t\t}\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\tvar metrics []Data\n\t\tfor l := range ev.Labels() {\n\t\t\tid := l.Key()\n\t\t\tif list := e.subscribers[id]; len(list) > 0 {\n\t\t\t\tfor _, s := range list {\n\t\t\t\t\tmetrics = append(metrics, s(ev.At(), lm, l))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlm = label.MergeMaps(label.NewMap(Entries.Of(metrics)), lm)\n\t\treturn output(ctx, ev, lm)\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/metric/info.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage metric\n\nimport (\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Scalar represents the construction information for a scalar metric.\ntype Scalar struct {\n\t// Name is the unique name of this metric.\n\tName string\n\t// Description can be used by observers to describe the metric to users.\n\tDescription string\n\t// Keys is the set of labels that collectively describe rows of the metric.\n\tKeys []label.Key\n}\n\n// HistogramInt64 represents the construction information for an int64 histogram metric.\ntype HistogramInt64 struct {\n\t// Name is the unique name of this metric.\n\tName string\n\t// Description can be used by observers to describe the metric to users.\n\tDescription string\n\t// Keys is the set of labels that collectively describe rows of the metric.\n\tKeys []label.Key\n\t// Buckets holds the inclusive upper bound of each bucket in the histogram.\n\tBuckets []int64\n}\n\n// HistogramFloat64 represents the construction information for a float64 histogram metric.\ntype HistogramFloat64 struct {\n\t// Name is the unique name of this metric.\n\tName string\n\t// Description can be used by observers to describe the metric to users.\n\tDescription string\n\t// Keys is the set of labels that collectively describe rows of the metric.\n\tKeys []label.Key\n\t// Buckets holds the inclusive upper bound of each bucket in the histogram.\n\tBuckets []float64\n}\n\n// Count creates a new metric based on the Scalar information that counts\n// the number of times the supplied int64 measure is set.\n// Metrics of this type will use Int64Data.\nfunc (info Scalar) Count(e *Config, key label.Key) {\n\tdata := &Int64Data{Info: &info, key: nil}\n\te.subscribe(key, data.count)\n}\n\n// SumInt64 creates a new metric based on the Scalar information that sums all\n// the values recorded on the int64 measure.\n// Metrics of this type will use Int64Data.\nfunc (info Scalar) SumInt64(e *Config, key *keys.Int) {\n\tdata := &Int64Data{Info: &info, key: key}\n\te.subscribe(key, data.sum)\n}\n\n// LatestInt64 creates a new metric based on the Scalar information that tracks\n// the most recent value recorded on the int64 measure.\n// Metrics of this type will use Int64Data.\nfunc (info Scalar) LatestInt64(e *Config, key *keys.Int) {\n\tdata := &Int64Data{Info: &info, IsGauge: true, key: key}\n\te.subscribe(key, data.latest)\n}\n\n// SumFloat64 creates a new metric based on the Scalar information that sums all\n// the values recorded on the float64 measure.\n// Metrics of this type will use Float64Data.\nfunc (info Scalar) SumFloat64(e *Config, key *keys.Float) {\n\tdata := &Float64Data{Info: &info, key: key}\n\te.subscribe(key, data.sum)\n}\n\n// LatestFloat64 creates a new metric based on the Scalar information that tracks\n// the most recent value recorded on the float64 measure.\n// Metrics of this type will use Float64Data.\nfunc (info Scalar) LatestFloat64(e *Config, key *keys.Float) {\n\tdata := &Float64Data{Info: &info, IsGauge: true, key: key}\n\te.subscribe(key, data.latest)\n}\n\n// Record creates a new metric based on the HistogramInt64 information that\n// tracks the bucketized counts of values recorded on the int64 measure.\n// Metrics of this type will use HistogramInt64Data.\nfunc (info HistogramInt64) Record(e *Config, key *keys.Int) {\n\tdata := &HistogramInt64Data{Info: &info, key: key}\n\te.subscribe(key, data.record)\n}\n\n// Record creates a new metric based on the HistogramFloat64 information that\n// tracks the bucketized counts of values recorded on the float64 measure.\n// Metrics of this type will use HistogramFloat64Data.\nfunc (info HistogramFloat64) Record(e *Config, key *keys.Float) {\n\tdata := &HistogramFloat64Data{Info: &info, key: key}\n\te.subscribe(key, data.record)\n}\n"
  },
  {
    "path": "internal/event/export/otel/common.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// labelToAttribute converts a label to an OTLP attribute.\n// It returns false if the label has no value.\nfunc labelToAttribute(l label.Label) (otlpAttribute, bool) {\n\tkey := l.Key()\n\tvar v otlpAttributeValue\n\n\tswitch key := key.(type) {\n\tcase *keys.Int:\n\t\tv = otlpAttributeValue{IntValue: varOf(intAsString(key.From(l)))}\n\tcase *keys.Uint:\n\t\tv = otlpAttributeValue{IntValue: varOf(intAsString(key.From(l)))}\n\tcase *keys.Float:\n\t\tv = otlpAttributeValue{DoubleValue: varOf(key.From(l))}\n\tcase *keys.String:\n\t\tv = otlpAttributeValue{StringValue: varOf(key.From(l))}\n\tcase *keys.Error:\n\t\tif err := key.From(l); err != nil {\n\t\t\tv = otlpAttributeValue{StringValue: varOf(err.Error())}\n\t\t}\n\tcase *keys.Value:\n\t\tv = otlpAttributeValue{StringValue: varOf(fmt.Sprint(key.From(l)))}\n\tdefault:\n\t\tif l.Valid() {\n\t\t\tv = otlpAttributeValue{StringValue: varOf(fmt.Sprint(l))}\n\t\t}\n\t}\n\n\thasValue := v.StringValue != nil || v.IntValue != nil || v.DoubleValue != nil\n\treturn otlpAttribute{Key: key.Name(), Value: v}, hasValue\n}\n\n// TODO(adonovan): use go1.26 new(expr)\nfunc varOf[T any](x T) *T { return &x }\n"
  },
  {
    "path": "internal/event/export/otel/metrics.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// convertMetric converts internal metric.Data to an OTLP metric.\nfunc convertMetric(data metric.Data) otlpMetric {\n\tswitch data := data.(type) {\n\tcase *metric.Int64Data:\n\t\treturn convertInt64Data(data)\n\tcase *metric.Float64Data:\n\t\treturn convertFloat64Data(data)\n\tcase *metric.HistogramInt64Data:\n\t\treturn convertHistogramInt64Data(data)\n\tcase *metric.HistogramFloat64Data:\n\t\treturn convertHistogramFloat64Data(data)\n\tdefault:\n\t\treturn otlpMetric{Name: data.Handle()}\n\t}\n}\n\nfunc convertInt64Data(d *metric.Int64Data) otlpMetric {\n\tm := otlpMetric{\n\t\tName:        d.Info.Name,\n\t\tDescription: d.Info.Description,\n\t}\n\n\tgroups := d.Groups()\n\tdataPoints := make([]otlpNumberDataPoint, len(d.Rows))\n\tfor i, value := range d.Rows {\n\t\tv := intAsString(value)\n\t\tdp := otlpNumberDataPoint{\n\t\t\tTimeUnixNano: intAsString(d.EndTime.UnixNano()),\n\t\t\tAsInt:        &v, // TODO: use go1.26 new(value)\n\t\t\tAttributes:   labelsToAttributes(groups[i]),\n\t\t}\n\t\tdataPoints[i] = dp\n\t}\n\n\tif d.IsGauge {\n\t\tm.Gauge = &otlpGauge{DataPoints: dataPoints}\n\t} else {\n\t\tm.Sum = &otlpSum{\n\t\t\tDataPoints:             dataPoints,\n\t\t\tAggregationTemporality: 2, // cumulative\n\t\t\tIsMonotonic:            true,\n\t\t}\n\t}\n\n\treturn m\n}\n\nfunc convertFloat64Data(d *metric.Float64Data) otlpMetric {\n\tm := otlpMetric{\n\t\tName:        d.Info.Name,\n\t\tDescription: d.Info.Description,\n\t}\n\n\tgroups := d.Groups()\n\tdataPoints := make([]otlpNumberDataPoint, len(d.Rows))\n\tfor i, value := range d.Rows {\n\t\tv := value\n\t\tdp := otlpNumberDataPoint{\n\t\t\tTimeUnixNano: intAsString(d.EndTime.UnixNano()),\n\t\t\tAsDouble:     &v, // TODO: use go1.26 new(value)\n\t\t\tAttributes:   labelsToAttributes(groups[i]),\n\t\t}\n\t\tdataPoints[i] = dp\n\t}\n\n\tif d.IsGauge {\n\t\tm.Gauge = &otlpGauge{DataPoints: dataPoints}\n\t} else {\n\t\tm.Sum = &otlpSum{\n\t\t\tDataPoints:             dataPoints,\n\t\t\tAggregationTemporality: 2, // cumulative\n\t\t\tIsMonotonic:            true,\n\t\t}\n\t}\n\n\treturn m\n}\n\nfunc convertHistogramInt64Data(d *metric.HistogramInt64Data) otlpMetric {\n\tdataPoints := make([]otlpHistogramDataPoint, len(d.Rows))\n\n\t// Convert bucket boundaries to float64\n\tbounds := make([]float64, len(d.Info.Buckets))\n\tfor i, b := range d.Info.Buckets {\n\t\tbounds[i] = float64(b)\n\t}\n\n\tgroups := d.Groups()\n\tfor i, row := range d.Rows {\n\t\t// OTLP expects bucket counts, not cumulative counts\n\t\t// The internal format uses cumulative, so we need to convert\n\t\tbucketCounts := make([]intAsString, len(row.Values)+1)\n\t\tvar prev int64\n\t\tfor j, v := range row.Values {\n\t\t\tbucketCounts[j] = intAsString(v - prev)\n\t\t\tprev = v\n\t\t}\n\t\t// Last bucket is for values > last bound\n\t\tbucketCounts[len(row.Values)] = intAsString(row.Count - prev)\n\n\t\tsum := float64(row.Sum)\n\t\tmin := float64(row.Min)\n\t\tmax := float64(row.Max)\n\t\tdp := otlpHistogramDataPoint{\n\t\t\tTimeUnixNano:   intAsString(d.EndTime.UnixNano()),\n\t\t\tCount:          intAsString(row.Count),\n\t\t\tSum:            &sum, // TODO: use go1.26 new(value)\n\t\t\tBucketCounts:   bucketCounts,\n\t\t\tExplicitBounds: bounds,\n\t\t\tMin:            &min, // TODO: use go1.26 new(value)\n\t\t\tMax:            &max, // TODO: use go1.26 new(value)\n\t\t\tAttributes:     labelsToAttributes(groups[i]),\n\t\t}\n\t\tdataPoints[i] = dp\n\t}\n\n\treturn otlpMetric{\n\t\tName:        d.Info.Name,\n\t\tDescription: d.Info.Description,\n\t\tHistogram: &otlpHistogram{\n\t\t\tDataPoints:             dataPoints,\n\t\t\tAggregationTemporality: 2, // cumulative\n\t\t},\n\t}\n}\n\nfunc convertHistogramFloat64Data(d *metric.HistogramFloat64Data) otlpMetric {\n\tdataPoints := make([]otlpHistogramDataPoint, len(d.Rows))\n\n\tgroups := d.Groups()\n\tfor i, row := range d.Rows {\n\t\t// Convert cumulative to bucket counts\n\t\tbucketCounts := make([]intAsString, len(row.Values)+1)\n\t\tvar prev int64\n\t\tfor j, v := range row.Values {\n\t\t\tbucketCounts[j] = intAsString(v - prev)\n\t\t\tprev = v\n\t\t}\n\t\tbucketCounts[len(row.Values)] = intAsString(row.Count - prev)\n\n\t\tsum := row.Sum\n\t\tmin := row.Min\n\t\tmax := row.Max\n\t\tdp := otlpHistogramDataPoint{\n\t\t\tTimeUnixNano:   intAsString(d.EndTime.UnixNano()),\n\t\t\tCount:          intAsString(row.Count),\n\t\t\tSum:            &sum, // TODO: use go1.26 new(value)\n\t\t\tBucketCounts:   bucketCounts,\n\t\t\tExplicitBounds: d.Info.Buckets,\n\t\t\tMin:            &min, // TODO: use go1.26 new(value)\n\t\t\tMax:            &max, // TODO: use go1.26 new(value)\n\t\t\tAttributes:     labelsToAttributes(groups[i]),\n\t\t}\n\t\tdataPoints[i] = dp\n\t}\n\n\treturn otlpMetric{\n\t\tName:        d.Info.Name,\n\t\tDescription: d.Info.Description,\n\t\tHistogram: &otlpHistogram{\n\t\t\tDataPoints:             dataPoints,\n\t\t\tAggregationTemporality: 2, // cumulative\n\t\t},\n\t}\n}\n\n// labelsToAttributes converts a slice of labels to OTLP attributes.\nfunc labelsToAttributes(labels []label.Label) []otlpAttribute {\n\tattrs := make([]otlpAttribute, 0, len(labels))\n\tfor _, l := range labels {\n\t\tif attr, ok := labelToAttribute(l); ok {\n\t\t\tattrs = append(attrs, attr)\n\t\t}\n\t}\n\treturn attrs\n}\n\n// exportMetrics sends metrics to the OTLP endpoint.\nfunc (e *Exporter) exportMetrics(metrics []otlpMetric) error {\n\treq := otlpMetricsRequest{\n\t\tResourceMetrics: []otlpResourceMetrics{{\n\t\t\tResource: e.resource,\n\t\t\tScopeMetrics: []otlpScopeMetrics{{\n\t\t\t\tScope:   otlpScope{Name: \"golang.org/x/tools\"},\n\t\t\t\tMetrics: metrics,\n\t\t\t}},\n\t\t}},\n\t}\n\treturn e.post(\"/v1/metrics\", req)\n}\n"
  },
  {
    "path": "internal/event/export/otel/metrics_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// captureMetricData creates a metric using the production event system and returns the resulting data.\nfunc captureMetricData(name string, setup func(*metric.Config), record func(context.Context)) metric.Data {\n\tvar captured metric.Data\n\n\toutput := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tif event.IsMetric(ev) {\n\t\t\tif entries := metric.Entries.Get(lm); entries != nil {\n\t\t\t\tfor _, data := range entries.([]metric.Data) {\n\t\t\t\t\tif data.Handle() == name {\n\t\t\t\t\t\tcaptured = data\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ctx\n\t}\n\n\tcfg := metric.Config{}\n\tsetup(&cfg)\n\n\tevent.SetExporter(cfg.Exporter(output))\n\tdefer event.SetExporter(nil)\n\n\trecord(context.Background())\n\treturn captured\n}\n\nfunc TestConvertInt64Data_Counter(t *testing.T) {\n\tkey := keys.NewInt(\"value\", \"\")\n\n\tdata := captureMetricData(\"request_count\", func(cfg *metric.Config) {\n\t\tmetric.Scalar{\n\t\t\tName:        \"request_count\",\n\t\t\tDescription: \"Number of requests\",\n\t\t}.SumInt64(cfg, key)\n\t}, func(ctx context.Context) {\n\t\tevent.Metric(ctx, key.Of(42))\n\t}).(*metric.Int64Data)\n\n\tm := convertInt64Data(data)\n\n\tif m.Name != \"request_count\" {\n\t\tt.Errorf(\"expected name 'request_count', got %q\", m.Name)\n\t}\n\tif m.Description != \"Number of requests\" {\n\t\tt.Errorf(\"expected description 'Number of requests', got %q\", m.Description)\n\t}\n\tif m.Gauge != nil {\n\t\tt.Error(\"expected Gauge to be nil for counter\")\n\t}\n\tif m.Sum == nil {\n\t\tt.Fatal(\"expected Sum to be non-nil for counter\")\n\t}\n\tif len(m.Sum.DataPoints) != 1 {\n\t\tt.Fatalf(\"expected 1 data point, got %d\", len(m.Sum.DataPoints))\n\t}\n\tif m.Sum.DataPoints[0].AsInt == nil || *m.Sum.DataPoints[0].AsInt != 42 {\n\t\tt.Errorf(\"expected value 42, got %v\", m.Sum.DataPoints[0].AsInt)\n\t}\n\tif !m.Sum.IsMonotonic {\n\t\tt.Error(\"expected IsMonotonic to be true for counter\")\n\t}\n}\n\nfunc TestConvertInt64Data_Gauge(t *testing.T) {\n\tkey := keys.NewInt(\"value\", \"\")\n\n\tdata := captureMetricData(\"current_connections\", func(cfg *metric.Config) {\n\t\tmetric.Scalar{Name: \"current_connections\"}.LatestInt64(cfg, key)\n\t}, func(ctx context.Context) {\n\t\tevent.Metric(ctx, key.Of(100))\n\t}).(*metric.Int64Data)\n\n\tm := convertInt64Data(data)\n\n\tif m.Sum != nil {\n\t\tt.Error(\"expected Sum to be nil for gauge\")\n\t}\n\tif m.Gauge == nil {\n\t\tt.Fatal(\"expected Gauge to be non-nil\")\n\t}\n\tif len(m.Gauge.DataPoints) != 1 {\n\t\tt.Fatalf(\"expected 1 data point, got %d\", len(m.Gauge.DataPoints))\n\t}\n\tif m.Gauge.DataPoints[0].AsInt == nil || *m.Gauge.DataPoints[0].AsInt != 100 {\n\t\tt.Errorf(\"expected value 100, got %v\", m.Gauge.DataPoints[0].AsInt)\n\t}\n}\n\nfunc TestConvertFloat64Data(t *testing.T) {\n\tkey := keys.NewFloat(\"value\", \"\")\n\n\tdata := captureMetricData(\"cpu_usage\", func(cfg *metric.Config) {\n\t\tmetric.Scalar{Name: \"cpu_usage\"}.LatestFloat64(cfg, key)\n\t}, func(ctx context.Context) {\n\t\tevent.Metric(ctx, key.Of(0.75))\n\t}).(*metric.Float64Data)\n\n\tm := convertFloat64Data(data)\n\n\tif m.Gauge == nil {\n\t\tt.Fatal(\"expected Gauge to be non-nil\")\n\t}\n\tif len(m.Gauge.DataPoints) != 1 {\n\t\tt.Fatalf(\"expected 1 data point, got %d\", len(m.Gauge.DataPoints))\n\t}\n\tif m.Gauge.DataPoints[0].AsDouble == nil || *m.Gauge.DataPoints[0].AsDouble != 0.75 {\n\t\tt.Errorf(\"expected value 0.75, got %v\", m.Gauge.DataPoints[0].AsDouble)\n\t}\n}\n\nfunc TestConvertHistogramInt64Data(t *testing.T) {\n\tkey := keys.NewInt(\"value\", \"\")\n\tbuckets := []int64{10, 50, 100, 500}\n\n\t// Record multiple values across different buckets:\n\t// Bucket boundaries: <=10, <=50, <=100, <=500, >500\n\t// Values: 5, 8 (<=10), 20, 30, 40 (<=50), 75 (<=100), 200, 300 (<=500), 1000 (>500)\n\tvalues := []int{5, 8, 20, 30, 40, 75, 200, 300, 1000}\n\n\tdata := captureMetricData(\"response_time\", func(cfg *metric.Config) {\n\t\tmetric.HistogramInt64{\n\t\t\tName:        \"response_time\",\n\t\t\tDescription: \"Response time in ms\",\n\t\t\tBuckets:     buckets,\n\t\t}.Record(cfg, key)\n\t}, func(ctx context.Context) {\n\t\tfor _, v := range values {\n\t\t\tevent.Metric(ctx, key.Of(v))\n\t\t}\n\t}).(*metric.HistogramInt64Data)\n\n\tm := convertHistogramInt64Data(data)\n\n\tif m.Histogram == nil {\n\t\tt.Fatal(\"expected Histogram to be non-nil\")\n\t}\n\tdp := m.Histogram.DataPoints[0]\n\n\t// Verify count\n\tif dp.Count != 9 {\n\t\tt.Errorf(\"expected count 9, got %d\", dp.Count)\n\t}\n\n\t// Verify sum: 5+8+20+30+40+75+200+300+1000 = 1678\n\tif dp.Sum == nil || *dp.Sum != 1678 {\n\t\tt.Errorf(\"expected sum 1678, got %v\", dp.Sum)\n\t}\n\n\t// Verify min/max\n\tif dp.Min == nil || *dp.Min != 5 {\n\t\tt.Errorf(\"expected min 5, got %v\", dp.Min)\n\t}\n\tif dp.Max == nil || *dp.Max != 1000 {\n\t\tt.Errorf(\"expected max 1000, got %v\", dp.Max)\n\t}\n\n\t// Verify bucket counts (non-cumulative):\n\t// <=10: 2 (5, 8)\n\t// <=50: 3 (20, 30, 40)\n\t// <=100: 1 (75)\n\t// <=500: 2 (200, 300)\n\t// >500: 1 (1000)\n\texpectedBuckets := []intAsString{2, 3, 1, 2, 1}\n\tif len(dp.BucketCounts) != len(expectedBuckets) {\n\t\tt.Fatalf(\"expected %d buckets, got %d\", len(expectedBuckets), len(dp.BucketCounts))\n\t}\n\tfor i, expected := range expectedBuckets {\n\t\tif dp.BucketCounts[i] != expected {\n\t\t\tt.Errorf(\"bucket[%d]: expected %d, got %d\", i, expected, dp.BucketCounts[i])\n\t\t}\n\t}\n\n\t// Verify explicit bounds match configured buckets\n\texpectedBounds := []float64{10, 50, 100, 500}\n\tif len(dp.ExplicitBounds) != len(expectedBounds) {\n\t\tt.Fatalf(\"expected %d bounds, got %d\", len(expectedBounds), len(dp.ExplicitBounds))\n\t}\n\tfor i, expected := range expectedBounds {\n\t\tif dp.ExplicitBounds[i] != expected {\n\t\t\tt.Errorf(\"bound[%d]: expected %v, got %v\", i, expected, dp.ExplicitBounds[i])\n\t\t}\n\t}\n}\n\nfunc TestConvertInt64Data_WithAttributes(t *testing.T) {\n\tvalueKey := keys.NewInt(\"value\", \"\")\n\tmethodKey := keys.NewString(\"method\", \"\")\n\n\tdata := captureMetricData(\"requests_by_method\", func(cfg *metric.Config) {\n\t\tmetric.Scalar{\n\t\t\tName: \"requests_by_method\",\n\t\t\tKeys: []label.Key{methodKey}, // Group by method\n\t\t}.SumInt64(cfg, valueKey)\n\t}, func(ctx context.Context) {\n\t\tevent.Metric(ctx, valueKey.Of(10), methodKey.Of(\"GET\"))\n\t\tevent.Metric(ctx, valueKey.Of(5), methodKey.Of(\"POST\"))\n\t}).(*metric.Int64Data)\n\n\tm := convertInt64Data(data)\n\n\t// Should have 2 data points (one per method)\n\tif len(m.Sum.DataPoints) != 2 {\n\t\tt.Fatalf(\"expected 2 data points, got %d\", len(m.Sum.DataPoints))\n\t}\n\n\t// Verify attributes contain the method labels\n\tfor _, dp := range m.Sum.DataPoints {\n\t\tif len(dp.Attributes) != 1 {\n\t\t\tt.Errorf(\"expected 1 attribute, got %d\", len(dp.Attributes))\n\t\t}\n\t\tif dp.Attributes[0].Key != \"method\" {\n\t\t\tt.Errorf(\"expected attribute key 'method', got %q\", dp.Attributes[0].Key)\n\t\t}\n\t\t// Value should be \"GET\" or \"POST\"\n\t\tsv := dp.Attributes[0].Value.StringValue\n\t\tif sv == nil || (*sv != \"GET\" && *sv != \"POST\") {\n\t\t\tt.Errorf(\"unexpected method value: %v\", sv)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/otel/options.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"time\"\n)\n\n// Default configuration values.\nconst (\n\tDefaultEndpoint    = \"http://localhost:4318\"\n\tDefaultServiceName = \"unknown_service\"\n\tDefaultTimeout     = 10 * time.Second\n\tDefaultFlushPeriod = 2 * time.Second\n)\n\n// Option configures an OTelExporter.\ntype Option func(*Exporter)\n\n// WithEndpoint sets the OTLP HTTP endpoint.\nfunc WithEndpoint(endpoint string) Option {\n\treturn func(e *Exporter) {\n\t\te.endpoint = endpoint\n\t}\n}\n\n// WithServiceName sets the service name for exported spans.\nfunc WithServiceName(name string) Option {\n\treturn func(e *Exporter) {\n\t\te.serviceName = name\n\t}\n}\n\n// WithTimeout sets the HTTP client timeout.\nfunc WithTimeout(timeout time.Duration) Option {\n\treturn func(e *Exporter) {\n\t\te.client.Timeout = timeout\n\t}\n}\n\n// WithFlushPeriod sets the interval for automatic background flushing.\nfunc WithFlushPeriod(period time.Duration) Option {\n\treturn func(e *Exporter) {\n\t\te.flushPeriod = period\n\t}\n}\n\n// WithServiceVersion sets the service version for exported telemetry.\nfunc WithServiceVersion(version string) Option {\n\treturn func(e *Exporter) {\n\t\te.serviceVersion = version\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/otel/otel.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package otel exports spans and metrics to an OpenTelemetry\n// collector using the OTLP HTTP/JSON protocol.\n//\n// Use [NewExporter] to create an exporter, then chain its\n// [Exporter.ProcessEvent] method with other exporters:\n//\n//\totelExporter := otel.NewExporter(ctx,\n//\t\totel.WithEndpoint(\"http://localhost:4318\"),\n//\t\totel.WithServiceName(\"myservice\"),\n//\t)\n//\tevent.SetExporter(otelExporter.ProcessEvent)\n//\n// The exporter batches telemetry and flushes periodically in a\n// background goroutine. Call [Exporter.Flush] to force an\n// immediate export.\npackage otel\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Exporter exports spans and metrics to an OTLP HTTP endpoint.\ntype Exporter struct {\n\tmu             sync.Mutex\n\tendpoint       string\n\tserviceName    string\n\tserviceVersion string\n\tresource       otlpResource\n\tclient         *http.Client\n\tflushPeriod    time.Duration\n\tspans          []*export.Span\n\tmetrics        map[string]metric.Data\n}\n\n// NewExporter creates an exporter that sends spans to an OTLP endpoint.\n// Spans are collected and exported periodically in a background goroutine.\n// When the context is done, remaining spans are flushed.\nfunc NewExporter(ctx context.Context, opts ...Option) *Exporter {\n\te := &Exporter{\n\t\tendpoint:    DefaultEndpoint,\n\t\tserviceName: DefaultServiceName,\n\t\tclient:      &http.Client{Timeout: DefaultTimeout},\n\t\tflushPeriod: DefaultFlushPeriod,\n\t}\n\n\tfor _, opt := range opts {\n\t\topt(e)\n\t}\n\n\te.resource = e.buildResource()\n\n\tgo func() {\n\t\tticker := time.NewTicker(e.flushPeriod)\n\t\tdefer ticker.Stop()\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\te.Flush() // final flush before exiting\n\t\t\t\treturn\n\t\t\tcase <-ticker.C:\n\t\t\t\te.Flush()\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn e\n}\n\n// ProcessEvent handles events and collects completed spans and metrics.\nfunc (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\n\tif event.IsEnd(ev) {\n\t\tif span := export.GetSpan(ctx); span != nil {\n\t\t\te.spans = append(e.spans, span)\n\t\t}\n\t}\n\n\tif event.IsMetric(ev) {\n\t\tif e.metrics == nil {\n\t\t\te.metrics = make(map[string]metric.Data)\n\t\t}\n\t\tif entries := metric.Entries.Get(lm); entries != nil {\n\t\t\tfor _, data := range entries.([]metric.Data) {\n\t\t\t\te.metrics[data.Handle()] = data\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ctx\n}\n\n// Flush exports all collected spans and metrics to the OTLP endpoint.\nfunc (e *Exporter) Flush() {\n\te.mu.Lock()\n\tspans := e.spans\n\te.spans = nil\n\tmetrics := e.metrics\n\te.metrics = nil\n\te.mu.Unlock()\n\n\t// Export spans\n\tif len(spans) > 0 {\n\t\totlpSpans := make([]otlpSpan, 0, len(spans))\n\t\tfor _, span := range spans {\n\t\t\totlpSpans = append(otlpSpans, convertSpan(span))\n\t\t}\n\t\tif err := e.exportTraces(otlpSpans); err != nil {\n\t\t\tlog.Printf(\"post spans: %v\", err)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Export metrics\n\tif len(metrics) > 0 {\n\t\totlpMetrics := make([]otlpMetric, 0, len(metrics))\n\t\tfor _, data := range metrics {\n\t\t\totlpMetrics = append(otlpMetrics, convertMetric(data))\n\t\t}\n\t\tif err := e.exportMetrics(otlpMetrics); err != nil {\n\t\t\tlog.Printf(\"post metrics: %v\", err)\n\t\t}\n\t}\n}\n\n// post sends a JSON payload to the OTLP endpoint.\nfunc (e *Exporter) post(path string, payload any) error {\n\tdata, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// The background context is appropriate here since post is called only\n\t// from Flush, which is called only by the Exporter's background goroutine.\n\t// Notably it may be called after cancellation of the client's context.\n\treq, err := http.NewRequestWithContext(context.Background(), \"POST\", e.endpoint+path, bytes.NewReader(data))\n\tif err != nil {\n\t\treturn err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := e.client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode >= 400 {\n\t\treturn fmt.Errorf(\"OTLP export to %s failed with status %d\", path, resp.StatusCode)\n\t}\n\treturn nil\n}\n\nfunc (e *Exporter) buildResource() otlpResource {\n\tattrs := []otlpAttribute{\n\t\t{Key: \"service.name\", Value: otlpAttributeValue{StringValue: &e.serviceName}},\n\t\t{Key: \"process.runtime.version\", Value: otlpAttributeValue{StringValue: varOf(runtime.Version())}},\n\t\t{Key: \"process.pid\", Value: otlpAttributeValue{StringValue: varOf(strconv.Itoa(os.Getpid()))}},\n\t\t{Key: \"host.arch\", Value: otlpAttributeValue{StringValue: varOf(runtime.GOARCH)}},\n\t\t{Key: \"os.type\", Value: otlpAttributeValue{StringValue: varOf(runtime.GOOS)}},\n\t}\n\n\tif hostname, err := os.Hostname(); err == nil {\n\t\tattrs = append(attrs, otlpAttribute{\n\t\t\tKey:   \"host.name\",\n\t\t\tValue: otlpAttributeValue{StringValue: &hostname},\n\t\t})\n\t}\n\n\tif e.serviceVersion != \"\" {\n\t\tattrs = append(attrs, otlpAttribute{\n\t\t\tKey:   \"service.version\",\n\t\t\tValue: otlpAttributeValue{StringValue: &e.serviceVersion},\n\t\t})\n\t}\n\n\treturn otlpResource{Attributes: attrs}\n}\n"
  },
  {
    "path": "internal/event/export/otel/otel_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event/keys\"\n)\n\nfunc TestLabelToAttribute_String(t *testing.T) {\n\tkey := keys.NewString(\"mykey\", \"\")\n\tl := key.Of(\"myvalue\")\n\n\tattr, ok := labelToAttribute(l)\n\tif !ok {\n\t\tt.Fatal(\"expected ok=true\")\n\t}\n\tif attr.Key != \"mykey\" {\n\t\tt.Errorf(\"expected key 'mykey', got %q\", attr.Key)\n\t}\n\tif attr.Value.StringValue == nil || *attr.Value.StringValue != \"myvalue\" {\n\t\tt.Errorf(\"expected stringValue 'myvalue', got %v\", attr.Value.StringValue)\n\t}\n}\n\nfunc TestLabelToAttribute_Int(t *testing.T) {\n\tkey := keys.NewInt(\"count\", \"\")\n\tl := key.Of(42)\n\n\tattr, ok := labelToAttribute(l)\n\tif !ok {\n\t\tt.Fatal(\"expected ok=true\")\n\t}\n\tif attr.Key != \"count\" {\n\t\tt.Errorf(\"expected key 'count', got %q\", attr.Key)\n\t}\n\tif attr.Value.IntValue == nil || *attr.Value.IntValue != 42 {\n\t\tt.Errorf(\"expected intValue 42, got %v\", attr.Value.IntValue)\n\t}\n}\n\nfunc TestLabelToAttribute_Float(t *testing.T) {\n\tkey := keys.NewFloat(\"ratio\", \"\")\n\tl := key.Of(3.14)\n\n\tattr, ok := labelToAttribute(l)\n\tif !ok {\n\t\tt.Fatal(\"expected ok=true\")\n\t}\n\tif attr.Key != \"ratio\" {\n\t\tt.Errorf(\"expected key 'ratio', got %q\", attr.Key)\n\t}\n\tif attr.Value.DoubleValue == nil || *attr.Value.DoubleValue != 3.14 {\n\t\tt.Errorf(\"expected doubleValue 3.14, got %v\", attr.Value.DoubleValue)\n\t}\n}\n\nfunc TestLabelToAttribute_Error(t *testing.T) {\n\tkey := keys.NewError(\"err\", \"\")\n\tl := key.Of(errors.New(\"something failed\"))\n\n\tattr, ok := labelToAttribute(l)\n\tif !ok {\n\t\tt.Fatal(\"expected ok=true\")\n\t}\n\tif attr.Key != \"err\" {\n\t\tt.Errorf(\"expected key 'err', got %q\", attr.Key)\n\t}\n\tif attr.Value.StringValue == nil || *attr.Value.StringValue != \"something failed\" {\n\t\tt.Errorf(\"expected stringValue 'something failed', got %v\", attr.Value.StringValue)\n\t}\n}\n\nfunc TestLabelToAttribute_NilError(t *testing.T) {\n\tkey := keys.NewError(\"err\", \"\")\n\tl := key.Of(nil)\n\n\t_, ok := labelToAttribute(l)\n\tif ok {\n\t\tt.Error(\"expected ok=false for nil error\")\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/otel/otlp.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\n// OTLP JSON types for telemetry export.\n//\n// Specification\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/docs/specification.md\n\n// intAsString is an int64 that marshals to/from a JSON string.\n//\n// int64 values are encoded as strings because JSON numbers are IEEE 754\n// double-precision floats, which can only represent integers exactly up to\n// 2^53. Timestamps in nanoseconds and large counts would lose precision.\n// See: https://github.com/open-telemetry/opentelemetry-proto/issues/268\n// And: https://protobuf.dev/programming-guides/json/\ntype intAsString int64\n\nfunc (i intAsString) MarshalJSON() ([]byte, error) {\n\treturn fmt.Appendf(nil, `\"%d\"`, i), nil\n}\n\nfunc (i *intAsString) UnmarshalJSON(data []byte) error {\n\t// Strip quotes if present. Per the spec, both JSON strings (\"123\")\n\t// and JSON numbers (123) must be accepted for decoding int64 values.\n\tif len(data) >= 2 && data[0] == '\"' && data[len(data)-1] == '\"' {\n\t\tdata = data[1 : len(data)-1]\n\t}\n\tv, err := strconv.ParseInt(string(data), 10, 64)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*i = intAsString(v)\n\treturn nil\n}\n\n// Common oltp types\n\n// otlpResource corresponds to Resource.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/resource/v1/resource.proto#L28\ntype otlpResource struct {\n\tAttributes []otlpAttribute `json:\"attributes\"`\n}\n\n// otlpScope corresponds to InstrumentationScope.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L76\ntype otlpScope struct {\n\tName    string `json:\"name,omitempty\"`\n\tVersion string `json:\"version,omitempty\"`\n}\n\n// otlpAttribute corresponds to KeyValue.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L66\ntype otlpAttribute struct {\n\tKey   string             `json:\"key\"`\n\tValue otlpAttributeValue `json:\"value\"`\n}\n\n// otlpAttributeValue corresponds to AnyValue.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L28\ntype otlpAttributeValue struct {\n\tStringValue *string      `json:\"stringValue,omitempty\"`\n\tIntValue    *intAsString `json:\"intValue,omitempty\"`\n\tDoubleValue *float64     `json:\"doubleValue,omitempty\"`\n\tBoolValue   *bool        `json:\"boolValue,omitempty\"`\n}\n\n// Trace types\n\n// otlpTraceExportRequest is the payload for ExportTraceServiceRequest.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/collector/trace/v1/trace_service.proto#L34\ntype otlpTraceExportRequest struct {\n\tResourceSpans []otlpResourceSpans `json:\"resourceSpans\"`\n}\n\n// otlpResourceSpans corresponds to ResourceSpans.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L48\ntype otlpResourceSpans struct {\n\tResource   otlpResource     `json:\"resource\"`\n\tScopeSpans []otlpScopeSpans `json:\"scopeSpans\"`\n}\n\n// otlpScopeSpans corresponds to ScopeSpans.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L68\ntype otlpScopeSpans struct {\n\tScope otlpScope  `json:\"scope\"`\n\tSpans []otlpSpan `json:\"spans\"`\n}\n\n// otlpSpan corresponds to Span.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L89\ntype otlpSpan struct {\n\tTraceID           string          `json:\"traceId\"`\n\tSpanID            string          `json:\"spanId\"`\n\tParentSpanID      string          `json:\"parentSpanId,omitempty\"`\n\tName              string          `json:\"name\"`\n\tKind              int             `json:\"kind\"`\n\tStartTimeUnixNano intAsString     `json:\"startTimeUnixNano\"`\n\tEndTimeUnixNano   intAsString     `json:\"endTimeUnixNano\"`\n\tAttributes        []otlpAttribute `json:\"attributes,omitempty\"`\n\tStatus            otlpSpanStatus  `json:\"status\"`\n}\n\n// otlpSpanStatus corresponds to Status.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L308\ntype otlpSpanStatus struct {\n\tCode    int    `json:\"code\"`\n\tMessage string `json:\"message,omitempty\"`\n}\n\n// Metrics types\n\n// otlpMetricsRequest is the payload for ExportMetricsServiceRequest.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/collector/metrics/v1/metrics_service.proto#L34\ntype otlpMetricsRequest struct {\n\tResourceMetrics []otlpResourceMetrics `json:\"resourceMetrics\"`\n}\n\n// otlpResourceMetrics corresponds to ResourceMetrics.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L66\ntype otlpResourceMetrics struct {\n\tResource     otlpResource       `json:\"resource\"`\n\tScopeMetrics []otlpScopeMetrics `json:\"scopeMetrics\"`\n}\n\n// otlpScopeMetrics corresponds to ScopeMetrics.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L86\ntype otlpScopeMetrics struct {\n\tScope   otlpScope    `json:\"scope\"`\n\tMetrics []otlpMetric `json:\"metrics\"`\n}\n\n// otlpMetric corresponds to Metric.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L188\ntype otlpMetric struct {\n\tName        string         `json:\"name\"`\n\tDescription string         `json:\"description,omitempty\"`\n\tUnit        string         `json:\"unit,omitempty\"`\n\tGauge       *otlpGauge     `json:\"gauge,omitempty\"`\n\tSum         *otlpSum       `json:\"sum,omitempty\"`\n\tHistogram   *otlpHistogram `json:\"histogram,omitempty\"`\n}\n\n// otlpGauge corresponds to Gauge.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L232\ntype otlpGauge struct {\n\tDataPoints []otlpNumberDataPoint `json:\"dataPoints\"`\n}\n\n// otlpSum corresponds to Sum.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L240\ntype otlpSum struct {\n\tDataPoints             []otlpNumberDataPoint `json:\"dataPoints\"`\n\tAggregationTemporality int                   `json:\"aggregationTemporality\"` // 1=delta, 2=cumulative\n\tIsMonotonic            bool                  `json:\"isMonotonic\"`\n}\n\n// otlpHistogram corresponds to Histogram.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L255\ntype otlpHistogram struct {\n\tDataPoints             []otlpHistogramDataPoint `json:\"dataPoints\"`\n\tAggregationTemporality int                      `json:\"aggregationTemporality\"`\n}\n\n// otlpNumberDataPoint corresponds to NumberDataPoint.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L385\ntype otlpNumberDataPoint struct {\n\tAttributes   []otlpAttribute `json:\"attributes,omitempty\"`\n\tTimeUnixNano intAsString     `json:\"timeUnixNano\"`\n\tAsInt        *intAsString    `json:\"asInt,omitempty\"`\n\tAsDouble     *float64        `json:\"asDouble,omitempty\"`\n}\n\n// otlpHistogramDataPoint corresponds to HistogramDataPoint.\n// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L434\ntype otlpHistogramDataPoint struct {\n\tAttributes     []otlpAttribute `json:\"attributes,omitempty\"`\n\tTimeUnixNano   intAsString     `json:\"timeUnixNano\"`\n\tCount          intAsString     `json:\"count\"`\n\tSum            *float64        `json:\"sum,omitempty\"`\n\tBucketCounts   []intAsString   `json:\"bucketCounts\"`\n\tExplicitBounds []float64       `json:\"explicitBounds\"`\n\tMin            *float64        `json:\"min,omitempty\"`\n\tMax            *float64        `json:\"max,omitempty\"`\n}\n"
  },
  {
    "path": "internal/event/export/otel/traces.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/keys\"\n)\n\n// exportTraces sends traces to the OTLP endpoint.\nfunc (e *Exporter) exportTraces(spans []otlpSpan) error {\n\treq := otlpTraceExportRequest{\n\t\tResourceSpans: []otlpResourceSpans{{\n\t\t\tResource: e.resource,\n\t\t\tScopeSpans: []otlpScopeSpans{{\n\t\t\t\tScope: otlpScope{Name: \"golang.org/x/tools\"},\n\t\t\t\tSpans: spans,\n\t\t\t}},\n\t\t}},\n\t}\n\treturn e.post(\"/v1/traces\", req)\n}\n\n// convertSpan converts an internal Span to an OTLP span.\nfunc convertSpan(span *export.Span) otlpSpan {\n\ts := otlpSpan{\n\t\tTraceID: span.ID.TraceID.String(),\n\t\tSpanID:  span.ID.SpanID.String(),\n\t\tName:    span.Name,\n\t\tKind:    1,                       // SPAN_KIND_INTERNAL\n\t\tStatus:  otlpSpanStatus{Code: 0}, // STATUS_CODE_UNSET\n\t}\n\n\tif span.ParentID.IsValid() {\n\t\ts.ParentSpanID = span.ParentID.String()\n\t}\n\n\t// Get timestamps from start event\n\tstartEvent := span.Start()\n\tif !startEvent.At().IsZero() {\n\t\ts.StartTimeUnixNano = intAsString(startEvent.At().UnixNano())\n\t}\n\n\t// Get end timestamp from finish event\n\tfinishEvent := span.Finish()\n\tif !finishEvent.At().IsZero() {\n\t\ts.EndTimeUnixNano = intAsString(finishEvent.At().UnixNano())\n\t}\n\n\t// Check for errors in span events to set status\n\tif slices.ContainsFunc(span.Events(), event.IsError) {\n\t\ts.Status.Code = 2 // STATUS_CODE_ERROR\n\t}\n\n\t// Extract attributes from span events\n\ts.Attributes = extractAttributes(span)\n\n\treturn s\n}\n\n// extractAttributes extracts labels from span events as OTLP attributes.\nfunc extractAttributes(span *export.Span) []otlpAttribute {\n\tvar attrs []otlpAttribute\n\n\t// Extract from start event\n\tstartEvent := span.Start()\n\tattrs = appendEventAttributes(attrs, startEvent)\n\n\t// Extract from logged events\n\tfor _, ev := range span.Events() {\n\t\tattrs = appendEventAttributes(attrs, ev)\n\t}\n\n\treturn attrs\n}\n\n// appendEventAttributes appends labels from an event as attributes.\nfunc appendEventAttributes(attrs []otlpAttribute, ev core.Event) []otlpAttribute {\n\tfor l := range ev.Labels() {\n\t\tkey := l.Key()\n\t\t// Skip internal event type markers\n\t\tif key == keys.Start || key == keys.End || key == keys.Label ||\n\t\t\tkey == keys.Detach || key == keys.Metric {\n\t\t\tcontinue\n\t\t}\n\n\t\tif attr, ok := labelToAttribute(l); ok {\n\t\t\tattrs = append(attrs, attr)\n\t\t}\n\t}\n\treturn attrs\n}\n"
  },
  {
    "path": "internal/event/export/otel/traces_test.go",
    "content": "// Copyright 2026 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage otel\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nfunc TestConvertSpan(t *testing.T) {\n\tspan := &export.Span{\n\t\tName: \"test-operation\",\n\t\tID: export.SpanContext{\n\t\t\tTraceID: export.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},\n\t\t\tSpanID:  export.SpanID{1, 2, 3, 4, 5, 6, 7, 8},\n\t\t},\n\t\tParentID: export.SpanID{8, 7, 6, 5, 4, 3, 2, 1},\n\t}\n\n\tresult := convertSpan(span)\n\n\tif result.Name != \"test-operation\" {\n\t\tt.Errorf(\"expected name 'test-operation', got %q\", result.Name)\n\t}\n\tif result.TraceID != \"0102030405060708090a0b0c0d0e0f10\" {\n\t\tt.Errorf(\"unexpected traceId: %s\", result.TraceID)\n\t}\n\tif result.SpanID != \"0102030405060708\" {\n\t\tt.Errorf(\"unexpected spanId: %s\", result.SpanID)\n\t}\n\tif result.ParentSpanID != \"0807060504030201\" {\n\t\tt.Errorf(\"unexpected parentSpanId: %s\", result.ParentSpanID)\n\t}\n\tif result.Kind != 1 {\n\t\tt.Errorf(\"expected kind 1, got %d\", result.Kind)\n\t}\n\tif result.Status.Code != 0 {\n\t\tt.Errorf(\"expected status code 0, got %d\", result.Status.Code)\n\t}\n}\n\n// TestE2E_SpanExport is a minimal end-to-end test verifying the full pipeline.\nfunc TestE2E_SpanExport(t *testing.T) {\n\tvar received []byte\n\tvar mu sync.Mutex\n\n\tserver := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tmu.Lock()\n\t\treceived, _ = io.ReadAll(r.Body)\n\t\tmu.Unlock()\n\t\tw.WriteHeader(http.StatusOK)\n\t}))\n\tdefer server.Close()\n\n\tbaseExporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\treturn ctx\n\t}\n\tspansExporter := export.Spans(baseExporter)\n\totelExporter := NewExporter(context.Background(), WithEndpoint(server.URL))\n\n\tchainedExporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tctx = spansExporter(ctx, ev, lm)\n\t\treturn otelExporter.ProcessEvent(ctx, ev, lm)\n\t}\n\n\tevent.SetExporter(chainedExporter)\n\n\tctx := context.Background()\n\tctx, end := event.Start(ctx, \"e2e-span\")\n\tend()\n\n\totelExporter.Flush()\n\n\tmu.Lock()\n\tdata := received\n\tmu.Unlock()\n\n\tif len(data) == 0 {\n\t\tt.Fatal(\"no data received\")\n\t}\n\n\t// Just verify it's valid JSON with a span\n\tvar req otlpTraceExportRequest\n\tif err := json.Unmarshal(data, &req); err != nil {\n\t\tt.Fatalf(\"invalid JSON: %v\", err)\n\t}\n\tif len(req.ResourceSpans) == 0 ||\n\t\tlen(req.ResourceSpans[0].ScopeSpans) == 0 ||\n\t\tlen(req.ResourceSpans[0].ScopeSpans[0].Spans) == 0 {\n\t\tt.Fatal(\"expected at least one span\")\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/printer.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export\n\nimport (\n\t\"io\"\n\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\ntype Printer struct {\n\tbuffer [128]byte\n}\n\n// WriteEvent writes the formatted event to w. It is not concurrency-safe.\nfunc (p *Printer) WriteEvent(w io.Writer, ev core.Event, lm label.Map) {\n\t// TODO(adonovan): any function that accepts an arbitrary\n\t// io.Writer should really deal with errors. Use bytes.Buffer?\n\tbuf := p.buffer[:0]\n\tif !ev.At().IsZero() {\n\t\tw.Write(ev.At().AppendFormat(buf, \"2006/01/02 15:04:05 \")) // ignore error\n\t}\n\tmsg := keys.Msg.Get(lm)\n\tio.WriteString(w, msg)\n\tif err := keys.Err.Get(lm); err != nil {\n\t\tif msg != \"\" {\n\t\t\tio.WriteString(w, \": \")\n\t\t}\n\t\tio.WriteString(w, err.Error())\n\t}\n\tfor l := range ev.Labels() {\n\t\tif l.Key() == keys.Msg || l.Key() == keys.Err {\n\t\t\tcontinue\n\t\t}\n\t\tio.WriteString(w, \"\\n\\t\")\n\t\tio.WriteString(w, l.Key().Name())\n\t\tio.WriteString(w, \"=\")\n\t\tw.Write(l.Key().Append(buf, l)) // ignore error\n\t}\n\tio.WriteString(w, \"\\n\")\n}\n"
  },
  {
    "path": "internal/event/export/prometheus/prometheus.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage prometheus\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"sort\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/export/metric\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nfunc New() *Exporter {\n\treturn &Exporter{}\n}\n\ntype Exporter struct {\n\tmu      sync.Mutex\n\tmetrics []metric.Data\n}\n\nfunc (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\tif !event.IsMetric(ev) {\n\t\treturn ctx\n\t}\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tmetrics := metric.Entries.Get(lm).([]metric.Data)\n\tfor _, data := range metrics {\n\t\tname := data.Handle()\n\t\t// We keep the metrics in name sorted order so the page is stable and easy\n\t\t// to read. We do this with an insertion sort rather than sorting the list\n\t\t// each time\n\t\tindex := sort.Search(len(e.metrics), func(i int) bool {\n\t\t\treturn e.metrics[i].Handle() >= name\n\t\t})\n\t\tif index >= len(e.metrics) || e.metrics[index].Handle() != name {\n\t\t\t// we have a new metric, so we need to make a space for it\n\t\t\told := e.metrics\n\t\t\te.metrics = make([]metric.Data, len(old)+1)\n\t\t\tcopy(e.metrics, old[:index])\n\t\t\tcopy(e.metrics[index+1:], old[index:])\n\t\t}\n\t\te.metrics[index] = data\n\t}\n\treturn ctx\n}\n\nfunc (e *Exporter) header(w http.ResponseWriter, name, description string, isGauge, isHistogram bool) {\n\tkind := \"counter\"\n\tif isGauge {\n\t\tkind = \"gauge\"\n\t}\n\tif isHistogram {\n\t\tkind = \"histogram\"\n\t}\n\tfmt.Fprintf(w, \"# HELP %s %s\\n\", name, description)\n\tfmt.Fprintf(w, \"# TYPE %s %s\\n\", name, kind)\n}\n\nfunc (e *Exporter) row(w http.ResponseWriter, name string, group []label.Label, extra string, value any) {\n\tfmt.Fprint(w, name)\n\tbuf := &bytes.Buffer{}\n\tfmt.Fprint(buf, group)\n\tif extra != \"\" {\n\t\tif buf.Len() > 0 {\n\t\t\tfmt.Fprint(buf, \",\")\n\t\t}\n\t\tfmt.Fprint(buf, extra)\n\t}\n\tif buf.Len() > 0 {\n\t\tfmt.Fprint(w, \"{\")\n\t\tbuf.WriteTo(w)\n\t\tfmt.Fprint(w, \"}\")\n\t}\n\tfmt.Fprintf(w, \" %v\\n\", value)\n}\n\nfunc (e *Exporter) Serve(w http.ResponseWriter, r *http.Request) {\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\tfor _, data := range e.metrics {\n\t\tswitch data := data.(type) {\n\t\tcase *metric.Int64Data:\n\t\t\te.header(w, data.Info.Name, data.Info.Description, data.IsGauge, false)\n\t\t\tfor i, group := range data.Groups() {\n\t\t\t\te.row(w, data.Info.Name, group, \"\", data.Rows[i])\n\t\t\t}\n\n\t\tcase *metric.Float64Data:\n\t\t\te.header(w, data.Info.Name, data.Info.Description, data.IsGauge, false)\n\t\t\tfor i, group := range data.Groups() {\n\t\t\t\te.row(w, data.Info.Name, group, \"\", data.Rows[i])\n\t\t\t}\n\n\t\tcase *metric.HistogramInt64Data:\n\t\t\te.header(w, data.Info.Name, data.Info.Description, false, true)\n\t\t\tfor i, group := range data.Groups() {\n\t\t\t\trow := data.Rows[i]\n\t\t\t\tfor j, b := range data.Info.Buckets {\n\t\t\t\t\te.row(w, data.Info.Name+\"_bucket\", group, fmt.Sprintf(`le=\"%v\"`, b), row.Values[j])\n\t\t\t\t}\n\t\t\t\te.row(w, data.Info.Name+\"_bucket\", group, `le=\"+Inf\"`, row.Count)\n\t\t\t\te.row(w, data.Info.Name+\"_count\", group, \"\", row.Count)\n\t\t\t\te.row(w, data.Info.Name+\"_sum\", group, \"\", row.Sum)\n\t\t\t}\n\n\t\tcase *metric.HistogramFloat64Data:\n\t\t\te.header(w, data.Info.Name, data.Info.Description, false, true)\n\t\t\tfor i, group := range data.Groups() {\n\t\t\t\trow := data.Rows[i]\n\t\t\t\tfor j, b := range data.Info.Buckets {\n\t\t\t\t\te.row(w, data.Info.Name+\"_bucket\", group, fmt.Sprintf(`le=\"%v\"`, b), row.Values[j])\n\t\t\t\t}\n\t\t\t\te.row(w, data.Info.Name+\"_bucket\", group, `le=\"+Inf\"`, row.Count)\n\t\t\t\te.row(w, data.Info.Name+\"_count\", group, \"\", row.Count)\n\t\t\t\te.row(w, data.Info.Name+\"_sum\", group, \"\", row.Sum)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/event/export/trace.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage export\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/core\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\ntype SpanContext struct {\n\tTraceID TraceID\n\tSpanID  SpanID\n}\n\ntype Span struct {\n\tName     string\n\tID       SpanContext\n\tParentID SpanID\n\tmu       sync.Mutex\n\tstart    core.Event\n\tfinish   core.Event\n\tevents   []core.Event\n}\n\ntype contextKeyType int\n\nconst (\n\tspanContextKey = contextKeyType(iota)\n\tlabelContextKey\n)\n\nfunc GetSpan(ctx context.Context) *Span {\n\tv := ctx.Value(spanContextKey)\n\tif v == nil {\n\t\treturn nil\n\t}\n\treturn v.(*Span)\n}\n\n// Spans creates an exporter that maintains hierarchical span structure in the\n// context.\n// It creates new spans on start events, adds events to the current span on\n// log or label, and closes the span on end events.\n// The span structure can then be used by other exporters.\nfunc Spans(output event.Exporter) event.Exporter {\n\treturn func(ctx context.Context, ev core.Event, lm label.Map) context.Context {\n\t\tswitch {\n\t\tcase event.IsLog(ev), event.IsLabel(ev):\n\t\t\tif span := GetSpan(ctx); span != nil {\n\t\t\t\tspan.mu.Lock()\n\t\t\t\tspan.events = append(span.events, ev)\n\t\t\t\tspan.mu.Unlock()\n\t\t\t}\n\t\tcase event.IsStart(ev):\n\t\t\tspan := &Span{\n\t\t\t\tName:  keys.Start.Get(lm),\n\t\t\t\tstart: ev,\n\t\t\t}\n\t\t\tif parent := GetSpan(ctx); parent != nil {\n\t\t\t\tspan.ID.TraceID = parent.ID.TraceID\n\t\t\t\tspan.ParentID = parent.ID.SpanID\n\t\t\t} else {\n\t\t\t\tspan.ID.TraceID = newTraceID()\n\t\t\t}\n\t\t\tspan.ID.SpanID = newSpanID()\n\t\t\tctx = context.WithValue(ctx, spanContextKey, span)\n\t\tcase event.IsEnd(ev):\n\t\t\tif span := GetSpan(ctx); span != nil {\n\t\t\t\tspan.mu.Lock()\n\t\t\t\tspan.finish = ev\n\t\t\t\tspan.mu.Unlock()\n\t\t\t}\n\t\tcase event.IsDetach(ev):\n\t\t\tctx = context.WithValue(ctx, spanContextKey, nil)\n\t\t}\n\t\treturn output(ctx, ev, lm)\n\t}\n}\n\nfunc (s *SpanContext) Format(f fmt.State, r rune) {\n\tfmt.Fprintf(f, \"%v:%v\", s.TraceID, s.SpanID)\n}\n\nfunc (s *Span) Start() core.Event {\n\t// start never changes after construction, so we don't need to hold the mutex\n\treturn s.start\n}\n\nfunc (s *Span) Finish() core.Event {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.finish\n}\n\nfunc (s *Span) Events() []core.Event {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.events\n}\n\nfunc (s *Span) Format(f fmt.State, r rune) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tfmt.Fprintf(f, \"%v %v\", s.Name, s.ID)\n\tif s.ParentID.IsValid() {\n\t\tfmt.Fprintf(f, \"[%v]\", s.ParentID)\n\t}\n\tfmt.Fprintf(f, \" %v->%v\", s.start, s.finish)\n}\n"
  },
  {
    "path": "internal/event/keys/keys.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage keys\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Value is a [label.Key] for untyped values.\ntype Value struct {\n\tname        string\n\tdescription string\n}\n\n// New creates a new Key for untyped values.\nfunc New(name, description string) *Value {\n\treturn &Value{name: name, description: description}\n}\n\nfunc (k *Value) Name() string        { return k.name }\nfunc (k *Value) Description() string { return k.description }\n\nfunc (k *Value) Append(buf []byte, l label.Label) []byte {\n\treturn fmt.Append(buf, k.From(l))\n}\n\n// Get returns the label for the key of a label.Map.\nfunc (k *Value) Get(lm label.Map) any {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn nil\n}\n\n// From returns the value of a Label.\nfunc (k *Value) From(t label.Label) any { return t.UnpackValue() }\n\n// Of creates a new Label with this key and the supplied value.\nfunc (k *Value) Of(value any) label.Label { return label.OfValue(k, value) }\n\n// Tag represents a key for tagging labels that have no value.\n// These are used when the existence of the label is the entire information it\n// carries, such as marking events to be of a specific kind, or from a specific\n// package.\ntype Tag struct {\n\tname        string\n\tdescription string\n}\n\n// NewTag creates a new [label.Key] for tagging labels.\nfunc NewTag(name, description string) *Tag {\n\treturn &Tag{name: name, description: description}\n}\n\nfunc (k *Tag) Name() string        { return k.name }\nfunc (k *Tag) Description() string { return k.description }\n\nfunc (k *Tag) Append(buf []byte, l label.Label) []byte { return buf }\n\n// New creates a new Label with this key.\nfunc (k *Tag) New() label.Label { return label.OfValue(k, nil) }\n\n// Int is a [label.Key] for signed integers.\ntype Int struct {\n\tname        string\n\tdescription string\n}\n\n// NewInt returns a new [label.Key] for int64 values.\nfunc NewInt(name, description string) *Int {\n\treturn &Int{name: name, description: description}\n}\n\nfunc (k *Int) Name() string        { return k.name }\nfunc (k *Int) Description() string { return k.description }\n\nfunc (k *Int) Append(buf []byte, l label.Label) []byte {\n\treturn strconv.AppendInt(buf, k.From(l), 10)\n}\n\n// Of creates a new Label with this key and the supplied value.\nfunc (k *Int) Of(v int) label.Label { return k.Of64(int64(v)) }\n\n// Of64 creates a new Label with this key and the supplied value.\nfunc (k *Int) Of64(v int64) label.Label { return label.Of64(k, uint64(v)) }\n\n// Get returns the label for the key of a label.Map.\nfunc (k *Int) Get(lm label.Map) int64 {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn 0\n}\n\n// From returns the value of a Label.\nfunc (k *Int) From(t label.Label) int64 { return int64(t.Unpack64()) }\n\n// Uint is a [label.Key] for unsigned integers.\ntype Uint struct {\n\tname        string\n\tdescription string\n}\n\n// NewUint creates a new [label.Key] for unsigned values.\nfunc NewUint(name, description string) *Uint {\n\treturn &Uint{name: name, description: description}\n}\n\nfunc (k *Uint) Name() string        { return k.name }\nfunc (k *Uint) Description() string { return k.description }\n\nfunc (k *Uint) Append(buf []byte, l label.Label) []byte {\n\treturn strconv.AppendUint(buf, k.From(l), 10)\n}\n\n// Of creates a new Label with this key and the supplied value.\nfunc (k *Uint) Of(v uint64) label.Label { return label.Of64(k, v) }\n\n// Get returns the label for the key of a label.Map.\nfunc (k *Uint) Get(lm label.Map) uint64 {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn 0\n}\n\n// From returns the value of a Label.\nfunc (k *Uint) From(t label.Label) uint64 { return t.Unpack64() }\n\n// Float is a label.Key for floating-point values.\ntype Float struct {\n\tname        string\n\tdescription string\n}\n\n// NewFloat creates a new [label.Key] for floating-point values.\nfunc NewFloat(name, description string) *Float {\n\treturn &Float{name: name, description: description}\n}\n\nfunc (k *Float) Name() string        { return k.name }\nfunc (k *Float) Description() string { return k.description }\n\nfunc (k *Float) Append(buf []byte, l label.Label) []byte {\n\treturn strconv.AppendFloat(buf, k.From(l), 'E', -1, 64)\n}\n\n// Of creates a new Label with this key and the supplied value.\nfunc (k *Float) Of(v float64) label.Label {\n\treturn label.Of64(k, math.Float64bits(v))\n}\n\n// Get returns the label for the key of a label.Map.\nfunc (k *Float) Get(lm label.Map) float64 {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn 0\n}\n\n// From returns the value of a Label.\nfunc (k *Float) From(t label.Label) float64 {\n\treturn math.Float64frombits(t.Unpack64())\n}\n\n// String represents a key\ntype String struct {\n\tname        string\n\tdescription string\n}\n\n// NewString creates a new Key for int64 values.\nfunc NewString(name, description string) *String {\n\treturn &String{name: name, description: description}\n}\n\nfunc (k *String) Name() string        { return k.name }\nfunc (k *String) Description() string { return k.description }\n\nfunc (k *String) Append(buf []byte, l label.Label) []byte {\n\treturn strconv.AppendQuote(buf, k.From(l))\n}\n\n// Of creates a new Label with this key and the supplied value.\nfunc (k *String) Of(v string) label.Label { return label.OfString(k, v) }\n\n// Get returns the label for the key of a label.Map.\nfunc (k *String) Get(lm label.Map) string {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn \"\"\n}\n\n// From returns the value of a Label.\nfunc (k *String) From(t label.Label) string { return t.UnpackString() }\n\n// Error represents a key\ntype Error struct {\n\tname        string\n\tdescription string\n}\n\n// NewError returns a new [label.Key] for error values.\nfunc NewError(name, description string) *Error {\n\treturn &Error{name: name, description: description}\n}\n\nfunc (k *Error) Name() string        { return k.name }\nfunc (k *Error) Description() string { return k.description }\n\nfunc (k *Error) Append(buf []byte, l label.Label) []byte {\n\treturn append(buf, k.From(l).Error()...)\n}\n\n// Of returns a new Label with this key and the supplied value.\nfunc (k *Error) Of(v error) label.Label { return label.OfValue(k, v) }\n\n// Get returns the label for the key of a label.Map.\nfunc (k *Error) Get(lm label.Map) error {\n\tif t := lm.Find(k); t.Valid() {\n\t\treturn k.From(t)\n\t}\n\treturn nil\n}\n\n// From returns the value of a Label.\nfunc (k *Error) From(t label.Label) error {\n\terr, _ := t.UnpackValue().(error)\n\treturn err\n}\n"
  },
  {
    "path": "internal/event/keys/standard.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage keys\n\nvar (\n\t// Msg is a key used to add message strings to label lists.\n\tMsg = NewString(\"message\", \"a readable message\")\n\t// Label is a key used to indicate an event adds labels to the context.\n\tLabel = NewTag(\"label\", \"a label context marker\")\n\t// Start is used for things like traces that have a name.\n\tStart = NewString(\"start\", \"span start\")\n\t// Metric is a key used to indicate an event records metrics.\n\tEnd = NewTag(\"end\", \"a span end marker\")\n\t// Metric is a key used to indicate an event records metrics.\n\tDetach = NewTag(\"detach\", \"a span detach marker\")\n\t// Err is a key used to add error values to label lists.\n\tErr = NewError(\"error\", \"an error that occurred\")\n\t// Metric is a key used to indicate an event records metrics.\n\tMetric = NewTag(\"metric\", \"a metric event marker\")\n)\n"
  },
  {
    "path": "internal/event/keys/util.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage keys\n\nimport (\n\t\"sort\"\n\t\"strings\"\n)\n\n// Join returns a canonical join of the keys in S:\n// a sorted comma-separated string list.\nfunc Join[S ~[]T, T ~string](s S) string {\n\tstrs := make([]string, 0, len(s))\n\tfor _, v := range s {\n\t\tstrs = append(strs, string(v))\n\t}\n\tsort.Strings(strs)\n\treturn strings.Join(strs, \",\")\n}\n"
  },
  {
    "path": "internal/event/keys/util_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage keys\n\nimport \"testing\"\n\nfunc TestJoin(t *testing.T) {\n\ttype T string\n\ttype S []T\n\n\ttests := []struct {\n\t\tdata S\n\t\twant string\n\t}{\n\t\t{S{\"a\", \"b\", \"c\"}, \"a,b,c\"},\n\t\t{S{\"b\", \"a\", \"c\"}, \"a,b,c\"},\n\t\t{S{\"c\", \"a\", \"b\"}, \"a,b,c\"},\n\t\t{nil, \"\"},\n\t\t{S{}, \"\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tif got := Join(test.data); got != test.want {\n\t\t\tt.Errorf(\"Join(%v) = %q, want %q\", test.data, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/event/label/label.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage label\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"slices\"\n\t\"unsafe\"\n)\n\n// Key is used as the identity of a Label.\n// Keys are intended to be compared by pointer only, the name should be unique\n// for communicating with external systems, but it is not required or enforced.\ntype Key interface {\n\t// Name returns the key name.\n\tName() string\n\t// Description returns a string that can be used to describe the value.\n\tDescription() string\n\t// Append appends the formatted value of the label to the supplied buffer.\n\tAppend(buf []byte, l Label) []byte\n}\n\n// Label holds a key and value pair.\n// It is normally used when passing around lists of labels.\ntype Label struct {\n\tkey     Key\n\tpacked  uint64\n\tuntyped any\n}\n\n// Map is the interface to a collection of Labels indexed by key.\ntype Map interface {\n\t// Find returns the label that matches the supplied key.\n\tFind(key Key) Label\n}\n\n// List is the interface to something that provides an iterable\n// list of labels.\n// Iteration should start from 0 and continue until Valid returns false.\ntype List interface {\n\t// Valid returns true if the index is within range for the list.\n\t// It does not imply the label at that index will itself be valid.\n\tValid(index int) bool\n\t// Label returns the label at the given index.\n\tLabel(index int) Label\n}\n\n// list implements LabelList for a list of Labels.\ntype list struct {\n\tlabels []Label\n}\n\n// filter wraps a LabelList filtering out specific labels.\ntype filter struct {\n\tkeys       []Key\n\tunderlying List\n}\n\n// listMap implements LabelMap for a simple list of labels.\ntype listMap struct {\n\tlabels []Label\n}\n\n// mapChain implements LabelMap for a list of underlying LabelMap.\ntype mapChain struct {\n\tmaps []Map\n}\n\n// OfValue creates a new label from the key and value.\n// This method is for implementing new key types, label creation should\n// normally be done with the Of method of the key.\nfunc OfValue(k Key, value any) Label { return Label{key: k, untyped: value} }\n\n// UnpackValue assumes the label was built using LabelOfValue and returns the value\n// that was passed to that constructor.\n// This method is for implementing new key types, for type safety normal\n// access should be done with the From method of the key.\nfunc (t Label) UnpackValue() any { return t.untyped }\n\n// Of64 creates a new label from a key and a uint64. This is often\n// used for non uint64 values that can be packed into a uint64.\n// This method is for implementing new key types, label creation should\n// normally be done with the Of method of the key.\nfunc Of64(k Key, v uint64) Label { return Label{key: k, packed: v} }\n\n// Unpack64 assumes the label was built using LabelOf64 and returns the value that\n// was passed to that constructor.\n// This method is for implementing new key types, for type safety normal\n// access should be done with the From method of the key.\nfunc (t Label) Unpack64() uint64 { return t.packed }\n\ntype stringptr unsafe.Pointer\n\n// OfString creates a new label from a key and a string.\n// This method is for implementing new key types, label creation should\n// normally be done with the Of method of the key.\nfunc OfString(k Key, v string) Label {\n\treturn Label{\n\t\tkey:     k,\n\t\tpacked:  uint64(len(v)),\n\t\tuntyped: stringptr(unsafe.StringData(v)),\n\t}\n}\n\n// UnpackString assumes the label was built using LabelOfString and returns the\n// value that was passed to that constructor.\n// This method is for implementing new key types, for type safety normal\n// access should be done with the From method of the key.\nfunc (t Label) UnpackString() string {\n\treturn unsafe.String((*byte)(t.untyped.(stringptr)), int(t.packed))\n}\n\n// Valid returns true if the Label is a valid one (it has a key).\nfunc (t Label) Valid() bool { return t.key != nil }\n\n// Key returns the key of this Label.\nfunc (t Label) Key() Key { return t.key }\n\n// Format is used for debug printing of labels.\nfunc (t Label) Format(f fmt.State, r rune) {\n\tif !t.Valid() {\n\t\tio.WriteString(f, `nil`)\n\t\treturn\n\t}\n\tio.WriteString(f, t.Key().Name())\n\tio.WriteString(f, \"=\")\n\tf.Write(t.Key().Append(nil, t)) // ignore error\n}\n\nfunc (l *list) Valid(index int) bool {\n\treturn index >= 0 && index < len(l.labels)\n}\n\nfunc (l *list) Label(index int) Label {\n\treturn l.labels[index]\n}\n\nfunc (f *filter) Valid(index int) bool {\n\treturn f.underlying.Valid(index)\n}\n\nfunc (f *filter) Label(index int) Label {\n\tl := f.underlying.Label(index)\n\tif slices.Contains(f.keys, l.Key()) {\n\t\treturn Label{}\n\t}\n\treturn l\n}\n\nfunc (lm listMap) Find(key Key) Label {\n\tfor _, l := range lm.labels {\n\t\tif l.Key() == key {\n\t\t\treturn l\n\t\t}\n\t}\n\treturn Label{}\n}\n\nfunc (c mapChain) Find(key Key) Label {\n\tfor _, src := range c.maps {\n\t\tl := src.Find(key)\n\t\tif l.Valid() {\n\t\t\treturn l\n\t\t}\n\t}\n\treturn Label{}\n}\n\nvar emptyList = &list{}\n\nfunc NewList(labels ...Label) List {\n\tif len(labels) == 0 {\n\t\treturn emptyList\n\t}\n\treturn &list{labels: labels}\n}\n\nfunc Filter(l List, keys ...Key) List {\n\tif len(keys) == 0 {\n\t\treturn l\n\t}\n\treturn &filter{keys: keys, underlying: l}\n}\n\nfunc NewMap(labels ...Label) Map {\n\treturn listMap{labels: labels}\n}\n\nfunc MergeMaps(srcs ...Map) Map {\n\tvar nonNil []Map\n\tfor _, src := range srcs {\n\t\tif src != nil {\n\t\t\tnonNil = append(nonNil, src)\n\t\t}\n\t}\n\tif len(nonNil) == 1 {\n\t\treturn nonNil[0]\n\t}\n\treturn mapChain{maps: nonNil}\n}\n"
  },
  {
    "path": "internal/event/label/label_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage label_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"testing\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\nvar (\n\tAKey = keys.NewString(\"A\", \"\")\n\tBKey = keys.NewString(\"B\", \"\")\n\tCKey = keys.NewString(\"C\", \"\")\n\tA    = AKey.Of(\"a\")\n\tB    = BKey.Of(\"b\")\n\tC    = CKey.Of(\"c\")\n\tall  = []label.Label{A, B, C}\n)\n\nfunc TestList(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname   string\n\t\tlabels []label.Label\n\t\texpect string\n\t}{{\n\t\tname: \"empty\",\n\t}, {\n\t\tname:   \"single\",\n\t\tlabels: []label.Label{A},\n\t\texpect: `A=\"a\"`,\n\t}, {\n\t\tname:   \"invalid\",\n\t\tlabels: []label.Label{{}},\n\t\texpect: ``,\n\t}, {\n\t\tname:   \"two\",\n\t\tlabels: []label.Label{A, B},\n\t\texpect: `A=\"a\", B=\"b\"`,\n\t}, {\n\t\tname:   \"three\",\n\t\tlabels: []label.Label{A, B, C},\n\t\texpect: `A=\"a\", B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"missing A\",\n\t\tlabels: []label.Label{{}, B, C},\n\t\texpect: `B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"missing B\",\n\t\tlabels: []label.Label{A, {}, C},\n\t\texpect: `A=\"a\", C=\"c\"`,\n\t}, {\n\t\tname:   \"missing C\",\n\t\tlabels: []label.Label{A, B, {}},\n\t\texpect: `A=\"a\", B=\"b\"`,\n\t}, {\n\t\tname:   \"missing AB\",\n\t\tlabels: []label.Label{{}, {}, C},\n\t\texpect: `C=\"c\"`,\n\t}, {\n\t\tname:   \"missing AC\",\n\t\tlabels: []label.Label{{}, B, {}},\n\t\texpect: `B=\"b\"`,\n\t}, {\n\t\tname:   \"missing BC\",\n\t\tlabels: []label.Label{A, {}, {}},\n\t\texpect: `A=\"a\"`,\n\t}} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tgot := printList(label.NewList(test.labels...))\n\t\t\tif got != test.expect {\n\t\t\t\tt.Errorf(\"got %q want %q\", got, test.expect)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFilter(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname    string\n\t\tlabels  []label.Label\n\t\tfilters []label.Key\n\t\texpect  string\n\t}{{\n\t\tname:   \"no filters\",\n\t\tlabels: all,\n\t\texpect: `A=\"a\", B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:    \"no labels\",\n\t\tfilters: []label.Key{AKey},\n\t\texpect:  ``,\n\t}, {\n\t\tname:    \"filter A\",\n\t\tlabels:  all,\n\t\tfilters: []label.Key{AKey},\n\t\texpect:  `B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:    \"filter B\",\n\t\tlabels:  all,\n\t\tfilters: []label.Key{BKey},\n\t\texpect:  `A=\"a\", C=\"c\"`,\n\t}, {\n\t\tname:    \"filter C\",\n\t\tlabels:  all,\n\t\tfilters: []label.Key{CKey},\n\t\texpect:  `A=\"a\", B=\"b\"`,\n\t}, {\n\t\tname:    \"filter AC\",\n\t\tlabels:  all,\n\t\tfilters: []label.Key{AKey, CKey},\n\t\texpect:  `B=\"b\"`,\n\t}} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tlabels := label.NewList(test.labels...)\n\t\t\tgot := printList(label.Filter(labels, test.filters...))\n\t\t\tif got != test.expect {\n\t\t\t\tt.Errorf(\"got %q want %q\", got, test.expect)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMap(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname   string\n\t\tlabels []label.Label\n\t\tkeys   []label.Key\n\t\texpect string\n\t}{{\n\t\tname:   \"no labels\",\n\t\tkeys:   []label.Key{AKey},\n\t\texpect: `nil`,\n\t}, {\n\t\tname:   \"match A\",\n\t\tlabels: all,\n\t\tkeys:   []label.Key{AKey},\n\t\texpect: `A=\"a\"`,\n\t}, {\n\t\tname:   \"match B\",\n\t\tlabels: all,\n\t\tkeys:   []label.Key{BKey},\n\t\texpect: `B=\"b\"`,\n\t}, {\n\t\tname:   \"match C\",\n\t\tlabels: all,\n\t\tkeys:   []label.Key{CKey},\n\t\texpect: `C=\"c\"`,\n\t}, {\n\t\tname:   \"match ABC\",\n\t\tlabels: all,\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"missing A\",\n\t\tlabels: []label.Label{{}, B, C},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `nil, B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"missing B\",\n\t\tlabels: []label.Label{A, {}, C},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", nil, C=\"c\"`,\n\t}, {\n\t\tname:   \"missing C\",\n\t\tlabels: []label.Label{A, B, {}},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", nil`,\n\t}} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tlm := label.NewMap(test.labels...)\n\t\t\tgot := printMap(lm, test.keys)\n\t\t\tif got != test.expect {\n\t\t\t\tt.Errorf(\"got %q want %q\", got, test.expect)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMapMerge(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname   string\n\t\tmaps   []label.Map\n\t\tkeys   []label.Key\n\t\texpect string\n\t}{{\n\t\tname:   \"no maps\",\n\t\tkeys:   []label.Key{AKey},\n\t\texpect: `nil`,\n\t}, {\n\t\tname:   \"one map\",\n\t\tmaps:   []label.Map{label.NewMap(all...)},\n\t\tkeys:   []label.Key{AKey},\n\t\texpect: `A=\"a\"`,\n\t}, {\n\t\tname:   \"invalid map\",\n\t\tmaps:   []label.Map{label.NewMap()},\n\t\tkeys:   []label.Key{AKey},\n\t\texpect: `nil`,\n\t}, {\n\t\tname:   \"two maps\",\n\t\tmaps:   []label.Map{label.NewMap(B, C), label.NewMap(A)},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"invalid start map\",\n\t\tmaps:   []label.Map{label.NewMap(), label.NewMap(B, C)},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `nil, B=\"b\", C=\"c\"`,\n\t}, {\n\t\tname:   \"invalid mid map\",\n\t\tmaps:   []label.Map{label.NewMap(A), label.NewMap(), label.NewMap(C)},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", nil, C=\"c\"`,\n\t}, {\n\t\tname:   \"invalid end map\",\n\t\tmaps:   []label.Map{label.NewMap(A, B), label.NewMap()},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", nil`,\n\t}, {\n\t\tname:   \"three maps one nil\",\n\t\tmaps:   []label.Map{label.NewMap(A), label.NewMap(B), nil},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", nil`,\n\t}, {\n\t\tname:   \"two maps one nil\",\n\t\tmaps:   []label.Map{label.NewMap(A, B), nil},\n\t\tkeys:   []label.Key{AKey, BKey, CKey},\n\t\texpect: `A=\"a\", B=\"b\", nil`,\n\t}} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\ttagMap := label.MergeMaps(test.maps...)\n\t\t\tgot := printMap(tagMap, test.keys)\n\t\t\tif got != test.expect {\n\t\t\t\tt.Errorf(\"got %q want %q\", got, test.expect)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc printList(list label.List) string {\n\tbuf := &bytes.Buffer{}\n\tfor index := 0; list.Valid(index); index++ {\n\t\tl := list.Label(index)\n\t\tif !l.Valid() {\n\t\t\tcontinue\n\t\t}\n\t\tif buf.Len() > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tfmt.Fprint(buf, l)\n\t}\n\treturn buf.String()\n}\n\nfunc printMap(lm label.Map, keys []label.Key) string {\n\tbuf := &bytes.Buffer{}\n\tfor _, key := range keys {\n\t\tif buf.Len() > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tfmt.Fprint(buf, lm.Find(key))\n\t}\n\treturn buf.String()\n}\n\nfunc TestAttemptedStringCorruption(t *testing.T) {\n\tdefer func() {\n\t\tr := recover()\n\t\tif _, ok := r.(*runtime.TypeAssertionError); !ok {\n\t\t\tt.Fatalf(\"wanted to recover TypeAssertionError, got %T\", r)\n\t\t}\n\t}()\n\n\tvar x uint64 = 12390\n\tp := unsafe.Pointer(&x)\n\tl := label.OfValue(AKey, p)\n\t_ = l.UnpackString()\n}\n"
  },
  {
    "path": "internal/expect/expect.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage expect provides support for interpreting structured comments in Go\nsource code (including go.mod and go.work files) as test expectations.\n\nThis is primarily intended for writing tests of things that process Go source\nfiles, although it does not directly depend on the testing package.\n\nCollect notes with the Extract or Parse functions, and use the\nMatchBefore function to find matches within the lines the comments were on.\n\nThe interpretation of the notes depends on the application.\nFor example, the test suite for a static checking tool might\nuse a @diag note to indicate an expected diagnostic:\n\n\tfmt.Printf(\"%s\", 1) //@ diag(\"%s wants a string, got int\")\n\nBy contrast, the test suite for a source code navigation tool\nmight use notes to indicate the positions of features of\ninterest, the actions to be performed by the test,\nand their expected outcomes:\n\n\tvar x = 1 //@ x_decl\n\t...\n\tprint(x) //@ definition(\"x\", x_decl)\n\tprint(x) //@ typeof(\"x\", \"int\")\n\n# Note comment syntax\n\nNote comments always start with the special marker @, which must be the\nvery first character after the comment opening pair, so //@ or /*@ with no\nspaces.\n\nThis is followed by a comma separated list of notes.\n\nA note always starts with an identifier, which is optionally followed by an\nargument list. The argument list is surrounded with parentheses and contains a\ncomma-separated list of arguments.\nThe empty parameter list and the missing parameter list are distinguishable if\nneeded; they result in a nil or an empty list in the Args parameter respectively.\n\nArguments may be positional, such as f(value), or named, such as f(name=value).\nPositional arguments must appear before named arguments.\nNames may not be repeated.\n\nArgument values may be either identifiers or literals.\nThe literals supported are the basic value literals, of string, float, integer\ntrue, false or nil. All the literals match the standard go conventions, with\nall bases of integers, and both quote and backtick strings.\nThere is one extra literal type, which is a string literal preceded by the\nidentifier \"re\" which is compiled to a regular expression.\n*/\npackage expect\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"regexp\"\n)\n\n// Note is a parsed note from an expect comment.\n// It knows the position of the start of the comment, and the name and\n// arguments that make up the note.\ntype Note struct {\n\tPos       token.Pos      // The position at which the note identifier appears\n\tName      string         // the name associated with the note\n\tArgs      []any          // positional arguments (non-nil if parens were present)\n\tNamedArgs map[string]any // named arguments (or nil if none)\n}\n\n// ReadFile is the type of a function that can provide file contents for a\n// given filename.\n// This is used in MatchBefore to look up the content of the file in order to\n// find the line to match the pattern against.\ntype ReadFile func(filename string) ([]byte, error)\n\n// MatchBefore attempts to match a pattern in the line before the supplied pos.\n// It uses the token.File and the ReadFile to work out the contents of the line\n// that end is part of, and then matches the pattern against the content of the\n// start of that line up to the supplied position.\n// The pattern may be either a simple string, []byte or a *regexp.Regexp.\n// MatchBefore returns the range of the line that matched the pattern, and\n// invalid positions if there was no match, or an error if the line could not be\n// found.\nfunc MatchBefore(f *token.File, readFile ReadFile, end token.Pos, pattern any) (token.Pos, token.Pos, error) {\n\tcontent, err := readFile(f.Name())\n\tif err != nil {\n\t\treturn token.NoPos, token.NoPos, fmt.Errorf(\"invalid file: %v\", err)\n\t}\n\tposition := f.Position(end)\n\tstartOffset := f.Offset(f.LineStart(position.Line))\n\tendOffset := f.Offset(end)\n\tline := content[startOffset:endOffset]\n\tmatchStart, matchEnd := -1, -1\n\tswitch pattern := pattern.(type) {\n\tcase string:\n\t\tbytePattern := []byte(pattern)\n\t\tmatchStart = bytes.Index(line, bytePattern)\n\t\tif matchStart >= 0 {\n\t\t\tmatchEnd = matchStart + len(bytePattern)\n\t\t}\n\tcase []byte:\n\t\tmatchStart = bytes.Index(line, pattern)\n\t\tif matchStart >= 0 {\n\t\t\tmatchEnd = matchStart + len(pattern)\n\t\t}\n\tcase *regexp.Regexp:\n\t\tmatch := pattern.FindIndex(line)\n\t\tif len(match) > 0 {\n\t\t\tmatchStart = match[0]\n\t\t\tmatchEnd = match[1]\n\t\t}\n\t}\n\tif matchStart < 0 {\n\t\treturn token.NoPos, token.NoPos, nil\n\t}\n\treturn f.Pos(startOffset + matchStart), f.Pos(startOffset + matchEnd), nil\n}\n"
  },
  {
    "path": "internal/expect/expect_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage expect_test\n\nimport (\n\t\"bytes\"\n\t\"go/token\"\n\t\"os\"\n\t\"reflect\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/expect\"\n)\n\nfunc TestMarker(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tfilename      string\n\t\texpectNotes   int\n\t\texpectMarkers map[string]string\n\t\texpectChecks  map[string][]any\n\t\t// expectChecks holds {\"id\": values} for each call check(id, values...).\n\t\t// Any named k=v arguments become a final map[string]any argument.\n\t}{\n\t\t{\n\t\t\tfilename:    \"testdata/test.go\",\n\t\t\texpectNotes: 14,\n\t\t\texpectMarkers: map[string]string{\n\t\t\t\t\"αSimpleMarker\": \"α\",\n\t\t\t\t\"OffsetMarker\":  \"β\",\n\t\t\t\t\"RegexMarker\":   \"γ\",\n\t\t\t\t\"εMultiple\":     \"ε\",\n\t\t\t\t\"ζMarkers\":      \"ζ\",\n\t\t\t\t\"ηBlockMarker\":  \"η\",\n\t\t\t\t\"Declared\":      \"η\",\n\t\t\t\t\"Comment\":       \"ι\",\n\t\t\t\t\"LineComment\":   \"someFunc\",\n\t\t\t\t\"NonIdentifier\": \"+\",\n\t\t\t\t\"StringMarker\":  \"\\\"hello\\\"\",\n\t\t\t},\n\t\t\texpectChecks: map[string][]any{\n\t\t\t\t\"αSimpleMarker\": nil,\n\t\t\t\t\"StringAndInt\":  {\"Number %d\", int64(12)},\n\t\t\t\t\"Bool\":          {true},\n\t\t\t\t\"NamedArgs\": {int64(1), true, expect.Identifier(\"a\"), map[string]any{\n\t\t\t\t\t\"b\": int64(1),\n\t\t\t\t\t\"c\": \"3\",\n\t\t\t\t\t\"d\": true,\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tfilename:    \"testdata/go.fake.mod\",\n\t\t\texpectNotes: 2,\n\t\t\texpectMarkers: map[string]string{\n\t\t\t\t\"αMarker\": \"αfake1α\",\n\t\t\t\t\"βMarker\": \"require golang.org/modfile v0.0.0\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tfilename:    \"testdata/go.fake.work\",\n\t\t\texpectNotes: 2,\n\t\t\texpectMarkers: map[string]string{\n\t\t\t\t\"αMarker\": \"1.23.0\",\n\t\t\t\t\"βMarker\": \"αβ\",\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(tt.filename, func(t *testing.T) {\n\t\t\tcontent, err := os.ReadFile(tt.filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\treadFile := func(string) ([]byte, error) { return content, nil }\n\n\t\t\tmarkers := make(map[string]token.Pos)\n\t\t\tfor name, tok := range tt.expectMarkers {\n\t\t\t\toffset := bytes.Index(content, []byte(tok))\n\t\t\t\tmarkers[name] = token.Pos(offset + 1)\n\t\t\t\tend := bytes.Index(content[offset:], []byte(tok))\n\t\t\t\tif end > 0 {\n\t\t\t\t\tmarkers[name+\"@\"] = token.Pos(offset + end + 2)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfset := token.NewFileSet()\n\t\t\tnotes, err := expect.Parse(fset, tt.filename, content)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Failed to extract notes:\\n%v\", err)\n\t\t\t}\n\t\t\tif len(notes) != tt.expectNotes {\n\t\t\t\tt.Errorf(\"Expected %v notes, got %v\", tt.expectNotes, len(notes))\n\t\t\t}\n\t\t\tfor _, n := range notes {\n\t\t\t\tswitch {\n\t\t\t\tcase n.Args == nil:\n\t\t\t\t\t// A //@foo note associates the name foo with the position of the\n\t\t\t\t\t// first match of \"foo\" on the current line.\n\t\t\t\t\tcheckMarker(t, fset, readFile, markers, n.Pos, n.Name, n.Name)\n\t\t\t\tcase n.Name == \"mark\":\n\t\t\t\t\t// A //@mark(name, \"pattern\") note associates the specified name\n\t\t\t\t\t// with the position on the first match of pattern on the current line.\n\t\t\t\t\tif len(n.Args) != 2 {\n\t\t\t\t\t\tt.Errorf(\"%v: expected 2 args to mark, got %v\", fset.Position(n.Pos), len(n.Args))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tident, ok := n.Args[0].(expect.Identifier)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"%v: got %v (%T), want identifier\", fset.Position(n.Pos), n.Args[0], n.Args[0])\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tcheckMarker(t, fset, readFile, markers, n.Pos, string(ident), n.Args[1])\n\n\t\t\t\tcase n.Name == \"check\":\n\t\t\t\t\t// A //@check(args, ...) note specifies some hypothetical action to\n\t\t\t\t\t// be taken by the test driver and its expected outcome.\n\t\t\t\t\t// In this test, the action is to compare the arguments\n\t\t\t\t\t// against expectChecks.\n\t\t\t\t\tif len(n.Args) < 1 {\n\t\t\t\t\t\tt.Errorf(\"%v: expected 1 args to check, got %v\", fset.Position(n.Pos), len(n.Args))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tident, ok := n.Args[0].(expect.Identifier)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"%v: got %v (%T), want identifier\", fset.Position(n.Pos), n.Args[0], n.Args[0])\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\twantArgs, ok := tt.expectChecks[string(ident)]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"%v: unexpected check %v\", fset.Position(n.Pos), ident)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tgotArgs := n.Args[1:]\n\t\t\t\t\tif n.NamedArgs != nil {\n\t\t\t\t\t\t// Clip to avoid mutating Args' array.\n\t\t\t\t\t\tgotArgs = append(slices.Clip(gotArgs), n.NamedArgs)\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(gotArgs) != len(wantArgs) {\n\t\t\t\t\t\tt.Errorf(\"%v: expected %v args to check, got %v\", fset.Position(n.Pos), len(wantArgs), len(gotArgs))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tfor i := range gotArgs {\n\t\t\t\t\t\tif !reflect.DeepEqual(wantArgs[i], gotArgs[i]) {\n\t\t\t\t\t\t\tt.Errorf(\"%v: arg %d: expected %#v, got %#v\", fset.Position(n.Pos), i+1, wantArgs[i], gotArgs[i])\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tt.Errorf(\"Unexpected note %v at %v\", n.Name, fset.Position(n.Pos))\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc checkMarker(t *testing.T, fset *token.FileSet, readFile expect.ReadFile, markers map[string]token.Pos, pos token.Pos, name string, pattern any) {\n\tstart, end, err := expect.MatchBefore(fset.File(pos), readFile, pos, pattern)\n\tif err != nil {\n\t\tt.Errorf(\"%v: MatchBefore failed: %v\", fset.Position(pos), err)\n\t\treturn\n\t}\n\tif start == token.NoPos {\n\t\tt.Errorf(\"%v: Pattern %v did not match\", fset.Position(pos), pattern)\n\t\treturn\n\t}\n\texpectStart, ok := markers[name]\n\tif !ok {\n\t\tt.Errorf(\"%v: unexpected marker %v\", fset.Position(pos), name)\n\t\treturn\n\t}\n\tif start != expectStart {\n\t\tt.Errorf(\"%v: Expected %v got %v\", fset.Position(pos), fset.Position(expectStart), fset.Position(start))\n\t}\n\tif expectEnd, ok := markers[name+\"@\"]; ok && end != expectEnd {\n\t\tt.Errorf(\"%v: Expected end %v got %v\", fset.Position(pos), fset.Position(expectEnd), fset.Position(end))\n\t}\n}\n"
  },
  {
    "path": "internal/expect/extract.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage expect\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\tgoscanner \"go/scanner\"\n\t\"go/token\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/scanner\"\n\n\t\"golang.org/x/mod/modfile\"\n)\n\nconst commentStart = \"@\"\nconst commentStartLen = len(commentStart)\n\n// Identifier is the type for an identifier in a Note argument list.\ntype Identifier string\n\n// Parse collects all the notes present in a file.\n// If content is nil, the filename specified is read and parsed, otherwise the\n// content is used and the filename is used for positions and error messages.\n// Each comment whose text starts with @ is parsed as a comma-separated\n// sequence of notes.\n// See the package documentation for details about the syntax of those\n// notes.\nfunc Parse(fset *token.FileSet, filename string, content []byte) ([]*Note, error) {\n\tif content == nil {\n\t\tdata, err := os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcontent = data\n\t}\n\n\tswitch filepath.Ext(filename) {\n\tcase \".s\":\n\t\t// The assembler uses a custom scanner,\n\t\t// but the go/scanner package is close\n\t\t// enough: we only want the comments.\n\t\tfile := fset.AddFile(filename, -1, len(content))\n\t\tvar scan goscanner.Scanner\n\t\tscan.Init(file, content, nil, goscanner.ScanComments)\n\n\t\tvar notes []*Note\n\t\tfor {\n\t\t\tpos, tok, lit := scan.Scan()\n\t\t\tif tok == token.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif tok == token.COMMENT {\n\t\t\t\ttext, adjust := getAdjustedNote(lit)\n\t\t\t\tif text == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tparsed, err := parse(file, pos+token.Pos(adjust), text)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tnotes = append(notes, parsed...)\n\t\t\t}\n\t\t}\n\t\treturn notes, nil\n\n\tcase \".go\":\n\t\t// TODO: We should write this in terms of the scanner, like the .s case above.\n\t\t// there are ways you can break the parser such that it will not add all the\n\t\t// comments to the ast, which may result in files where the tests are silently\n\t\t// not run.\n\t\tfile, err := parser.ParseFile(fset, filename, content, parser.ParseComments|parser.AllErrors|parser.SkipObjectResolution)\n\t\tif file == nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn ExtractGo(fset.File(file.Pos()), file)\n\n\tcase \".mod\":\n\t\tfile, err := modfile.Parse(filename, content, nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tf := fset.AddFile(filename, -1, len(content))\n\t\tf.SetLinesForContent(content)\n\t\tnotes, err := extractModWork(fset, file.Syntax.Stmt)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Since modfile.Parse does not return an *ast, we need to add the offset\n\t\t// within the file's contents to the file's base relative to the fileset.\n\t\tfor _, note := range notes {\n\t\t\tnote.Pos += token.Pos(f.Base())\n\t\t}\n\t\treturn notes, nil\n\n\tcase \".work\":\n\t\tfile, err := modfile.ParseWork(filename, content, nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tf := fset.AddFile(filename, -1, len(content))\n\t\tf.SetLinesForContent(content)\n\t\tnotes, err := extractModWork(fset, file.Syntax.Stmt)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// As with go.mod files, we need to compute a synthetic token.Pos.\n\t\tfor _, note := range notes {\n\t\t\tnote.Pos += token.Pos(f.Base())\n\t\t}\n\t\treturn notes, nil\n\t}\n\treturn nil, nil\n}\n\n// extractModWork collects all the notes present in a go.mod file or go.work\n// file, by way of the shared modfile.Expr statement node.\n//\n// Each comment whose text starts with @ is parsed as a comma-separated\n// sequence of notes.\n// See the package documentation for details about the syntax of those\n// notes.\n// Only allow notes to appear with the following format: \"//@mark()\" or // @mark()\nfunc extractModWork(fset *token.FileSet, exprs []modfile.Expr) ([]*Note, error) {\n\tvar notes []*Note\n\tfor _, stmt := range exprs {\n\t\tcomment := stmt.Comment()\n\t\tif comment == nil {\n\t\t\tcontinue\n\t\t}\n\t\tvar allComments []modfile.Comment\n\t\tallComments = append(allComments, comment.Before...)\n\t\tallComments = append(allComments, comment.Suffix...)\n\t\tfor _, cmt := range allComments {\n\t\t\ttext, adjust := getAdjustedNote(cmt.Token)\n\t\t\tif text == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpos := token.Pos(int(cmt.Start.Byte) + adjust)\n\t\t\tparsed, err := parse(fset.File(pos), pos, text)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tnotes = append(notes, parsed...)\n\t\t}\n\t}\n\treturn notes, nil\n}\n\n// ExtractGo collects all the notes present in an AST.\n// Each comment whose text starts with @ is parsed as a comma-separated\n// sequence of notes.\n// See the package documentation for details about the syntax of those\n// notes.\nfunc ExtractGo(tokFile *token.File, file *ast.File) ([]*Note, error) {\n\tvar notes []*Note\n\tfor _, g := range file.Comments {\n\t\tfor _, c := range g.List {\n\t\t\ttext, adjust := getAdjustedNote(c.Text)\n\t\t\tif text == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparsed, err := parse(tokFile, token.Pos(int(c.Pos())+adjust), text)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tnotes = append(notes, parsed...)\n\t\t}\n\t}\n\treturn notes, nil\n}\n\nfunc getAdjustedNote(text string) (string, int) {\n\tif strings.HasPrefix(text, \"/*\") {\n\t\ttext = strings.TrimSuffix(text, \"*/\")\n\t}\n\ttext = text[2:] // remove \"//\" or \"/*\" prefix\n\n\t// Allow notes to appear within comments.\n\t// For example:\n\t// \"// //@mark()\" is valid.\n\t// \"// @mark()\" is not valid.\n\t// \"// /*@mark()*/\" is not valid.\n\tvar adjust int\n\tif i := strings.Index(text, commentStart); i > 2 {\n\t\t// Get the text before the commentStart.\n\t\tpre := text[i-2 : i]\n\t\tif pre != \"//\" {\n\t\t\treturn \"\", 0\n\t\t}\n\t\ttext = text[i:]\n\t\tadjust = i\n\t}\n\tif !strings.HasPrefix(text, commentStart) {\n\t\treturn \"\", 0\n\t}\n\ttext = text[commentStartLen:]\n\treturn text, commentStartLen + adjust + 1\n}\n\nconst invalidToken rune = 0\n\ntype tokens struct {\n\tscanner scanner.Scanner\n\tcurrent rune\n\terr     error\n\tbase    token.Pos\n}\n\nfunc (t *tokens) Init(base token.Pos, text string) *tokens {\n\tt.base = base\n\tt.scanner.Init(strings.NewReader(text))\n\tt.scanner.Mode = scanner.GoTokens\n\tt.scanner.Whitespace ^= 1 << '\\n' // don't skip new lines\n\tt.scanner.Error = func(s *scanner.Scanner, msg string) {\n\t\tt.Errorf(\"%v\", msg)\n\t}\n\treturn t\n}\n\nfunc (t *tokens) Consume() string {\n\tt.current = invalidToken\n\treturn t.scanner.TokenText()\n}\n\nfunc (t *tokens) Token() rune {\n\tif t.err != nil {\n\t\treturn scanner.EOF\n\t}\n\tif t.current == invalidToken {\n\t\tt.current = t.scanner.Scan()\n\t}\n\treturn t.current\n}\n\nfunc (t *tokens) Skip(r rune) int {\n\ti := 0\n\tfor t.Token() == '\\n' {\n\t\tt.Consume()\n\t\ti++\n\t}\n\treturn i\n}\n\nfunc (t *tokens) TokenString() string {\n\treturn scanner.TokenString(t.Token())\n}\n\nfunc (t *tokens) Pos() token.Pos {\n\treturn t.base + token.Pos(t.scanner.Position.Offset)\n}\n\nfunc (t *tokens) Errorf(msg string, args ...any) {\n\tif t.err != nil {\n\t\treturn\n\t}\n\tt.err = fmt.Errorf(msg, args...)\n}\n\nfunc parse(tokFile *token.File, base token.Pos, text string) ([]*Note, error) {\n\tt := new(tokens).Init(base, text)\n\tnotes := parseComment(t)\n\tif t.err != nil {\n\t\treturn nil, fmt.Errorf(\"%v: %s\", tokFile.Position(t.Pos()), t.err)\n\t}\n\treturn notes, nil\n}\n\nfunc parseComment(t *tokens) []*Note {\n\tvar notes []*Note\n\tfor {\n\t\tt.Skip('\\n')\n\t\tswitch t.Token() {\n\t\tcase scanner.EOF:\n\t\t\treturn notes\n\t\tcase scanner.Ident:\n\t\t\tnotes = append(notes, parseNote(t))\n\t\tdefault:\n\t\t\tt.Errorf(\"unexpected %s parsing comment, expect identifier\", t.TokenString())\n\t\t\treturn nil\n\t\t}\n\t\tswitch t.Token() {\n\t\tcase scanner.EOF:\n\t\t\treturn notes\n\t\tcase ',', '\\n':\n\t\t\tt.Consume()\n\t\tdefault:\n\t\t\tt.Errorf(\"unexpected %s parsing comment, expect separator\", t.TokenString())\n\t\t\treturn nil\n\t\t}\n\t}\n}\n\nfunc parseNote(t *tokens) *Note {\n\tn := &Note{\n\t\tPos:  t.Pos(),\n\t\tName: t.Consume(),\n\t}\n\n\tswitch t.Token() {\n\tcase ',', '\\n', scanner.EOF:\n\t\t// no argument list present\n\t\treturn n\n\tcase '(':\n\t\tn.Args, n.NamedArgs = parseArgumentList(t)\n\t\treturn n\n\tdefault:\n\t\tt.Errorf(\"unexpected %s parsing note\", t.TokenString())\n\t\treturn nil\n\t}\n}\n\nfunc parseArgumentList(t *tokens) (args []any, named map[string]any) {\n\targs = []any{} // @name() is represented by a non-nil empty slice.\n\tt.Consume()    // '('\n\tt.Skip('\\n')\n\tfor t.Token() != ')' {\n\t\tname, arg := parseArgument(t)\n\t\tif name != \"\" {\n\t\t\t// f(k=v)\n\t\t\tif named == nil {\n\t\t\t\tnamed = make(map[string]any)\n\t\t\t}\n\t\t\tif _, dup := named[name]; dup {\n\t\t\t\tt.Errorf(\"duplicate named argument %q\", name)\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tnamed[name] = arg\n\t\t} else {\n\t\t\t// f(v)\n\t\t\tif named != nil {\n\t\t\t\tt.Errorf(\"positional argument follows named argument\")\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\targs = append(args, arg)\n\t\t}\n\t\tif t.Token() != ',' {\n\t\t\tbreak\n\t\t}\n\t\tt.Consume()\n\t\tt.Skip('\\n')\n\t}\n\tif t.Token() != ')' {\n\t\tt.Errorf(\"unexpected %s parsing argument list\", t.TokenString())\n\t\treturn nil, nil\n\t}\n\tt.Consume() // ')'\n\treturn args, named\n}\n\n// parseArgument returns the value of the argument (\"f(value)\"),\n// and its name if named \"f(name=value)\".\nfunc parseArgument(t *tokens) (name string, value any) {\nagain:\n\tswitch t.Token() {\n\tcase scanner.Ident:\n\t\tv := t.Consume()\n\t\tswitch v {\n\t\tcase \"true\":\n\t\t\tvalue = true\n\t\tcase \"false\":\n\t\t\tvalue = false\n\t\tcase \"nil\":\n\t\t\tvalue = nil\n\t\tcase \"re\":\n\t\t\tif t.Token() != scanner.String && t.Token() != scanner.RawString {\n\t\t\t\tt.Errorf(\"re must be followed by string, got %s\", t.TokenString())\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpattern, _ := strconv.Unquote(t.Consume()) // can't fail\n\t\t\tre, err := regexp.Compile(pattern)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"invalid regular expression %s: %v\", pattern, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvalue = re\n\t\tdefault:\n\t\t\t// f(name=value)?\n\t\t\tif name == \"\" && t.Token() == '=' {\n\t\t\t\tt.Consume() // '='\n\t\t\t\tname = v\n\t\t\t\tgoto again\n\t\t\t}\n\t\t\tvalue = Identifier(v)\n\t\t}\n\n\tcase scanner.String, scanner.RawString:\n\t\tvalue, _ = strconv.Unquote(t.Consume()) // can't fail\n\n\tcase scanner.Int:\n\t\ts := t.Consume()\n\t\tv, err := strconv.ParseInt(s, 0, 0)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"cannot convert %v to int: %v\", s, err)\n\t\t}\n\t\tvalue = v\n\n\tcase scanner.Float:\n\t\ts := t.Consume()\n\t\tv, err := strconv.ParseFloat(s, 64)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"cannot convert %v to float: %v\", s, err)\n\t\t}\n\t\tvalue = v\n\n\tcase '-':\n\t\tt.Consume()\n\t\tswitch t.Token() {\n\t\tcase scanner.Int:\n\t\t\ts := \"-\" + t.Consume()\n\t\t\tv, err := strconv.ParseInt(s, 0, 0)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"cannot convert %v to int: %v\", s, err)\n\t\t\t}\n\t\t\tvalue = v\n\n\t\tcase scanner.Float:\n\t\t\ts := \"-\" + t.Consume()\n\t\t\tv, err := strconv.ParseFloat(s, 64)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"cannot convert %v to float: %v\", s, err)\n\t\t\t}\n\t\t\tvalue = v\n\n\t\tdefault:\n\t\t\tt.Errorf(\"unexpected '-' not followed by number, got %s\", t.TokenString())\n\t\t}\n\n\tcase scanner.Char:\n\t\tt.Errorf(\"unexpected char literal %s\", t.Consume())\n\n\tdefault:\n\t\tt.Errorf(\"unexpected %s parsing argument\", t.TokenString())\n\t}\n\treturn\n}\n"
  },
  {
    "path": "internal/expect/testdata/go.fake.mod",
    "content": "// This file is named go.fake.mod so it does not define a real module, which\n// would make the contents of this directory unavailable to the test when run\n// from outside the repository.\n\nmodule αfake1α //@mark(αMarker, \"αfake1α\")\n\ngo 1.14\n\nrequire golang.org/modfile v0.0.0 //@mark(βMarker, \"require golang.org/modfile v0.0.0\")\n"
  },
  {
    "path": "internal/expect/testdata/go.fake.work",
    "content": "// This file is named go.fake.mod so it does not define a real module, which\n// would make the contents of this directory unavailable to the test when run\n// from outside the repository.\n\ngo 1.23.0 //@mark(αMarker, \"1.23.0\")\n\nuse ./αβ //@mark(βMarker, \"αβ\")\n"
  },
  {
    "path": "internal/expect/testdata/test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fake1 is used to test the expect package.\npackage fake1\n\n// The greek letters in this file mark points we use for marker tests.\n// We use unique markers so we can make the tests stable against changes to\n// this file.\n\nconst (\n\t_                   int = iota\n\tαSimpleMarkerα          //@αSimpleMarker\n\toffsetββMarker          //@mark(OffsetMarker, \"β\")\n\tregexγMaγrker           //@mark(RegexMarker, re`\\p{Greek}Ma`)\n\tεMultipleεζMarkersζ     //@εMultiple,ζMarkers\n\tηBlockMarkerη           /*@ηBlockMarker*/\n)\n\n/*Marker ι inside ι a comment*/ //@mark(Comment,\"ι inside \")\nvar x = \"hello\"                 //@mark(StringMarker, `\"hello\"`)\n\n// someFunc is a function. //@mark(LineComment, \"someFunc\")\nfunc someFunc(a, b int) int {\n\t// The line below must be the first occurrence of the plus operator\n\treturn a + b + 1 //@mark(NonIdentifier, re`\\+[^\\+]*`)\n}\n\n// And some extra checks for interesting action parameters\n// Also checks for multi-line expectations\n/*@\ncheck(αSimpleMarker)\ncheck(StringAndInt,\n\t\"Number %d\",\n\t12,\n)\n\ncheck(Bool, true)\n\ncheck(NamedArgs, 1, true, a, b=1, c=\"3\", d=true)\n*/\n"
  },
  {
    "path": "internal/facts/facts.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package facts defines a serializable set of analysis.Fact.\n//\n// It provides a partial implementation of the Fact-related parts of the\n// analysis.Pass interface for use in analysis drivers such as \"go vet\"\n// and other build systems.\n//\n// The serial format is unspecified and may change, so the same version\n// of this package must be used for reading and writing serialized facts.\n//\n// The handling of facts in the analysis system parallels the handling\n// of type information in the compiler: during compilation of package P,\n// the compiler emits an export data file that describes the type of\n// every object (named thing) defined in package P, plus every object\n// indirectly reachable from one of those objects. Thus the downstream\n// compiler of package Q need only load one export data file per direct\n// import of Q, and it will learn everything about the API of package P\n// and everything it needs to know about the API of P's dependencies.\n//\n// Similarly, analysis of package P emits a fact set containing facts\n// about all objects exported from P, plus additional facts about only\n// those objects of P's dependencies that are reachable from the API of\n// package P; the downstream analysis of Q need only load one fact set\n// per direct import of Q.\n//\n// The notion of \"exportedness\" that matters here is that of the\n// compiler. According to the language spec, a method pkg.T.f is\n// unexported simply because its name starts with lowercase. But the\n// compiler must nonetheless export f so that downstream compilations can\n// accurately ascertain whether pkg.T implements an interface pkg.I\n// defined as interface{f()}. Exported thus means \"described in export\n// data\".\npackage facts\n\nimport (\n\t\"bytes\"\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"io\"\n\t\"log\"\n\t\"reflect\"\n\t\"sort\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/types/objectpath\"\n)\n\nconst debug = false\n\n// A Set is a set of analysis.Facts.\n//\n// Decode creates a Set of facts by reading from the imports of a given\n// package, and Encode writes out the set. Between these operation,\n// the Import and Export methods will query and update the set.\n//\n// All of Set's methods except String are safe to call concurrently.\ntype Set struct {\n\tpkg *types.Package\n\tmu  sync.Mutex\n\tm   map[key]analysis.Fact\n}\n\ntype key struct {\n\tpkg *types.Package\n\tobj types.Object // (object facts only)\n\tt   reflect.Type\n}\n\n// ImportObjectFact implements analysis.Pass.ImportObjectFact.\nfunc (s *Set) ImportObjectFact(obj types.Object, ptr analysis.Fact) bool {\n\tif obj == nil {\n\t\tpanic(\"nil object\")\n\t}\n\tkey := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(ptr)}\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif v, ok := s.m[key]; ok {\n\t\treflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())\n\t\treturn true\n\t}\n\treturn false\n}\n\n// ExportObjectFact implements analysis.Pass.ExportObjectFact.\nfunc (s *Set) ExportObjectFact(obj types.Object, fact analysis.Fact) {\n\tif obj.Pkg() != s.pkg {\n\t\tlog.Panicf(\"in package %s: ExportObjectFact(%s, %T): can't set fact on object belonging another package\",\n\t\t\ts.pkg, obj, fact)\n\t}\n\tkey := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(fact)}\n\ts.mu.Lock()\n\ts.m[key] = fact // clobber any existing entry\n\ts.mu.Unlock()\n}\n\nfunc (s *Set) AllObjectFacts(filter map[reflect.Type]bool) []analysis.ObjectFact {\n\tvar facts []analysis.ObjectFact\n\ts.mu.Lock()\n\tfor k, v := range s.m {\n\t\tif k.obj != nil && filter[k.t] {\n\t\t\tfacts = append(facts, analysis.ObjectFact{Object: k.obj, Fact: v})\n\t\t}\n\t}\n\ts.mu.Unlock()\n\treturn facts\n}\n\n// ImportPackageFact implements analysis.Pass.ImportPackageFact.\nfunc (s *Set) ImportPackageFact(pkg *types.Package, ptr analysis.Fact) bool {\n\tif pkg == nil {\n\t\tpanic(\"nil package\")\n\t}\n\tkey := key{pkg: pkg, t: reflect.TypeOf(ptr)}\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif v, ok := s.m[key]; ok {\n\t\treflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())\n\t\treturn true\n\t}\n\treturn false\n}\n\n// ExportPackageFact implements analysis.Pass.ExportPackageFact.\nfunc (s *Set) ExportPackageFact(fact analysis.Fact) {\n\tkey := key{pkg: s.pkg, t: reflect.TypeOf(fact)}\n\ts.mu.Lock()\n\ts.m[key] = fact // clobber any existing entry\n\ts.mu.Unlock()\n}\n\nfunc (s *Set) AllPackageFacts(filter map[reflect.Type]bool) []analysis.PackageFact {\n\tvar facts []analysis.PackageFact\n\ts.mu.Lock()\n\tfor k, v := range s.m {\n\t\tif k.obj == nil && filter[k.t] {\n\t\t\tfacts = append(facts, analysis.PackageFact{Package: k.pkg, Fact: v})\n\t\t}\n\t}\n\ts.mu.Unlock()\n\treturn facts\n}\n\n// gobFact is the Gob declaration of a serialized fact.\ntype gobFact struct {\n\tPkgPath string          // path of package\n\tObject  objectpath.Path // optional path of object relative to package itself\n\tFact    analysis.Fact   // type and value of user-defined Fact\n}\n\n// A Decoder decodes the facts from the direct imports of the package\n// provided to NewEncoder. A single decoder may be used to decode\n// multiple fact sets (e.g. each for a different set of fact types)\n// for the same package. Each call to Decode returns an independent\n// fact set.\ntype Decoder struct {\n\tpkg        *types.Package\n\tgetPackage GetPackageFunc\n}\n\n// NewDecoder returns a fact decoder for the specified package.\n//\n// It uses a brute-force recursive approach to enumerate all objects\n// defined by dependencies of pkg, so that it can learn the set of\n// package paths that may be mentioned in the fact encoding. This does\n// not scale well; use [NewDecoderFunc] where possible.\nfunc NewDecoder(pkg *types.Package) *Decoder {\n\t// Compute the import map for this package.\n\t// See the package doc comment.\n\tm := importMap(pkg.Imports())\n\tgetPackageFunc := func(path string) *types.Package { return m[path] }\n\treturn NewDecoderFunc(pkg, getPackageFunc)\n}\n\n// NewDecoderFunc returns a fact decoder for the specified package.\n//\n// It calls the getPackage function for the package path string of\n// each dependency (perhaps indirect) that it encounters in the\n// encoding. If the function returns nil, the fact is discarded.\n//\n// This function is preferred over [NewDecoder] when the client is\n// capable of efficient look-up of packages by package path.\nfunc NewDecoderFunc(pkg *types.Package, getPackage GetPackageFunc) *Decoder {\n\treturn &Decoder{\n\t\tpkg:        pkg,\n\t\tgetPackage: getPackage,\n\t}\n}\n\n// A GetPackageFunc function returns the package denoted by a package path.\ntype GetPackageFunc = func(pkgPath string) *types.Package\n\n// Decode decodes all the facts relevant to the analysis of package\n// pkgPath. The read function reads serialized fact data from an external\n// source for one of pkg's direct imports, identified by package path.\n// The empty file is a valid encoding of an empty fact set.\n//\n// It is the caller's responsibility to call gob.Register on all\n// necessary fact types.\n//\n// Concurrent calls to Decode are safe, so long as the\n// [GetPackageFunc] (if any) is also concurrency-safe.\nfunc (d *Decoder) Decode(read func(pkgPath string) ([]byte, error)) (*Set, error) {\n\t// Read facts from imported packages.\n\t// Facts may describe indirectly imported packages, or their objects.\n\tm := make(map[key]analysis.Fact) // one big bucket\n\tfor _, imp := range d.pkg.Imports() {\n\t\tlogf := func(format string, args ...any) {\n\t\t\tif debug {\n\t\t\t\tprefix := fmt.Sprintf(\"in %s, importing %s: \",\n\t\t\t\t\td.pkg.Path(), imp.Path())\n\t\t\t\tlog.Print(prefix, fmt.Sprintf(format, args...))\n\t\t\t}\n\t\t}\n\n\t\t// Read the gob-encoded facts.\n\t\tdata, err := read(imp.Path())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"in %s, can't import facts for package %q: %v\",\n\t\t\t\td.pkg.Path(), imp.Path(), err)\n\t\t}\n\t\tif len(data) == 0 {\n\t\t\tcontinue // no facts\n\t\t}\n\t\tvar gobFacts []gobFact\n\t\tif err := gob.NewDecoder(bytes.NewReader(data)).Decode(&gobFacts); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decoding facts for %q: %v\", imp.Path(), err)\n\t\t}\n\t\tlogf(\"decoded %d facts: %v\", len(gobFacts), gobFacts)\n\n\t\t// Parse each one into a key and a Fact.\n\t\tfor _, f := range gobFacts {\n\t\t\tfactPkg := d.getPackage(f.PkgPath) // possibly an indirect dependency\n\t\t\tif factPkg == nil {\n\t\t\t\t// Fact relates to a dependency that was\n\t\t\t\t// unused in this translation unit. Skip.\n\t\t\t\tlogf(\"no package %q; discarding %v\", f.PkgPath, f.Fact)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tkey := key{pkg: factPkg, t: reflect.TypeOf(f.Fact)}\n\t\t\tif f.Object != \"\" {\n\t\t\t\t// object fact\n\t\t\t\tobj, err := objectpath.Object(factPkg, f.Object)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// (most likely due to unexported object)\n\t\t\t\t\t// TODO(adonovan): audit for other possibilities.\n\t\t\t\t\tlogf(\"no object for path: %v; discarding %s\", err, f.Fact)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tkey.obj = obj\n\t\t\t\tlogf(\"read %T fact %s for %v\", f.Fact, f.Fact, key.obj)\n\t\t\t} else {\n\t\t\t\t// package fact\n\t\t\t\tlogf(\"read %T fact %s for %v\", f.Fact, f.Fact, factPkg)\n\t\t\t}\n\t\t\tm[key] = f.Fact\n\t\t}\n\t}\n\n\treturn &Set{pkg: d.pkg, m: m}, nil\n}\n\n// Encode encodes a set of facts to a memory buffer.\n//\n// It may fail if one of the Facts could not be gob-encoded, but this is\n// a sign of a bug in an Analyzer.\nfunc (s *Set) Encode() []byte {\n\tencoder := new(objectpath.Encoder)\n\n\t// TODO(adonovan): opt: use a more efficient encoding\n\t// that avoids repeating PkgPath for each fact.\n\n\t// Gather all facts, including those from imported packages.\n\tvar gobFacts []gobFact\n\n\ts.mu.Lock()\n\tfor k, fact := range s.m {\n\t\tif debug {\n\t\t\tlog.Printf(\"%v => %s\\n\", k, fact)\n\t\t}\n\n\t\t// Don't export facts that we imported from another\n\t\t// package, unless they represent fields or methods,\n\t\t// or package-level types.\n\t\t// (Facts about packages, and other package-level\n\t\t// objects, are only obtained from direct imports so\n\t\t// they needn't be reexported.)\n\t\t//\n\t\t// This is analogous to the pruning done by \"deep\"\n\t\t// export data for types, but not as precise because\n\t\t// we aren't careful about which structs or methods\n\t\t// we rexport: it should be only those referenced\n\t\t// from the API of s.pkg.\n\t\t// TODO(adonovan): opt: be more precise. e.g.\n\t\t// intersect with the set of objects computed by\n\t\t// importMap(s.pkg.Imports()).\n\t\t// TODO(adonovan): opt: implement \"shallow\" facts.\n\t\tif k.pkg != s.pkg {\n\t\t\tif k.obj == nil {\n\t\t\t\tcontinue // imported package fact\n\t\t\t}\n\t\t\tif _, isType := k.obj.(*types.TypeName); !isType &&\n\t\t\t\tk.obj.Parent() == k.obj.Pkg().Scope() {\n\t\t\t\tcontinue // imported fact about package-level non-type object\n\t\t\t}\n\t\t}\n\n\t\tvar object objectpath.Path\n\t\tif k.obj != nil {\n\t\t\tpath, err := encoder.For(k.obj)\n\t\t\tif err != nil {\n\t\t\t\tif debug {\n\t\t\t\t\tlog.Printf(\"discarding fact %s about %s\\n\", fact, k.obj)\n\t\t\t\t}\n\t\t\t\tcontinue // object not accessible from package API; discard fact\n\t\t\t}\n\t\t\tobject = path\n\t\t}\n\t\tgobFacts = append(gobFacts, gobFact{\n\t\t\tPkgPath: k.pkg.Path(),\n\t\t\tObject:  object,\n\t\t\tFact:    fact,\n\t\t})\n\t}\n\ts.mu.Unlock()\n\n\t// Sort facts by (package, object, type) for determinism.\n\tsort.Slice(gobFacts, func(i, j int) bool {\n\t\tx, y := gobFacts[i], gobFacts[j]\n\t\tif x.PkgPath != y.PkgPath {\n\t\t\treturn x.PkgPath < y.PkgPath\n\t\t}\n\t\tif x.Object != y.Object {\n\t\t\treturn x.Object < y.Object\n\t\t}\n\t\ttx := reflect.TypeOf(x.Fact)\n\t\tty := reflect.TypeOf(y.Fact)\n\t\tif tx != ty {\n\t\t\treturn tx.String() < ty.String()\n\t\t}\n\t\treturn false // equal\n\t})\n\n\tvar buf bytes.Buffer\n\tif len(gobFacts) > 0 {\n\t\tif err := gob.NewEncoder(&buf).Encode(gobFacts); err != nil {\n\t\t\t// Fact encoding should never fail. Identify the culprit.\n\t\t\tfor _, gf := range gobFacts {\n\t\t\t\tif err := gob.NewEncoder(io.Discard).Encode(gf); err != nil {\n\t\t\t\t\tfact := gf.Fact\n\t\t\t\t\tpkgpath := reflect.TypeOf(fact).Elem().PkgPath()\n\t\t\t\t\tlog.Panicf(\"internal error: gob encoding of analysis fact %s failed: %v; please report a bug against fact %T in package %q\",\n\t\t\t\t\t\tfact, err, fact, pkgpath)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif debug {\n\t\tlog.Printf(\"package %q: encode %d facts, %d bytes\\n\",\n\t\t\ts.pkg.Path(), len(gobFacts), buf.Len())\n\t}\n\n\treturn buf.Bytes()\n}\n\n// String is provided only for debugging, and must not be called\n// concurrent with any Import/Export method.\nfunc (s *Set) String() string {\n\tvar buf bytes.Buffer\n\tbuf.WriteString(\"{\")\n\tfor k, f := range s.m {\n\t\tif buf.Len() > 1 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tif k.obj != nil {\n\t\t\tbuf.WriteString(k.obj.String())\n\t\t} else {\n\t\t\tbuf.WriteString(k.pkg.Path())\n\t\t}\n\t\tfmt.Fprintf(&buf, \": %v\", f)\n\t}\n\tbuf.WriteString(\"}\")\n\treturn buf.String()\n}\n"
  },
  {
    "path": "internal/facts/facts_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage facts_test\n\nimport (\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/go/packages\"\n\n\t\"golang.org/x/tools/internal/facts\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\ntype myFact struct {\n\tS string\n}\n\nfunc (f *myFact) String() string { return fmt.Sprintf(\"myFact(%s)\", f.S) }\nfunc (f *myFact) AFact()         {}\n\nfunc init() {\n\tgob.Register(new(myFact))\n}\n\nfunc TestEncodeDecode(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tfiles    map[string]string\n\t\tplookups []pkgLookups // see testEncodeDecode for details\n\t}{\n\t\t{\n\t\t\tname: \"loading-order\",\n\t\t\t// c -> b -> a, a2\n\t\t\t// c does not directly depend on a, but it indirectly uses a.T.\n\t\t\t//\n\t\t\t// Package a2 is never loaded directly so it is incomplete.\n\t\t\t//\n\t\t\t// We use only types in this example because we rely on\n\t\t\t// types.Eval to resolve the lookup expressions, and it only\n\t\t\t// works for types. This is a definite gap in the typechecker API.\n\t\t\tfiles: map[string]string{\n\t\t\t\t\"a/a.go\":  `package a; type A int; type T int`,\n\t\t\t\t\"a2/a.go\": `package a2; type A2 int; type Unneeded int`,\n\t\t\t\t\"b/b.go\":  `package b; import (\"a\"; \"a2\"); type B chan a2.A2; type F func() a.T`,\n\t\t\t\t\"c/c.go\":  `package c; import \"b\"; type C []b.B`,\n\t\t\t},\n\t\t\t// In the following table, we analyze packages (a, b, c) in order,\n\t\t\t// look up various objects accessible within each package,\n\t\t\t// and see if they have a fact.  The \"analysis\" exports a fact\n\t\t\t// for every object at package level.\n\t\t\t//\n\t\t\t// Note: Loop iterations are not independent test cases;\n\t\t\t// order matters, as we populate factmap.\n\t\t\tplookups: []pkgLookups{\n\t\t\t\t{\"a\", []lookup{\n\t\t\t\t\t{\"A\", \"myFact(a.A)\"},\n\t\t\t\t}},\n\t\t\t\t{\"b\", []lookup{\n\t\t\t\t\t{\"a.A\", \"myFact(a.A)\"},\n\t\t\t\t\t{\"a.T\", \"myFact(a.T)\"},\n\t\t\t\t\t{\"B\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"F\", \"myFact(b.F)\"},\n\t\t\t\t\t{\"F(nil)()\", \"myFact(a.T)\"}, // (result type of b.F)\n\t\t\t\t}},\n\t\t\t\t{\"c\", []lookup{\n\t\t\t\t\t{\"b.B\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"b.F\", \"myFact(b.F)\"},\n\t\t\t\t\t{\"b.F(nil)()\", \"myFact(a.T)\"},\n\t\t\t\t\t{\"C\", \"myFact(c.C)\"},\n\t\t\t\t\t{\"C{}[0]\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"<-(C{}[0])\", \"no fact\"}, // object but no fact (we never \"analyze\" a2)\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"underlying\",\n\t\t\t// c->b->a\n\t\t\t// c does not import a directly or use any of its types, but it does use\n\t\t\t// the types within a indirectly. c.q has the type a.a so package a should\n\t\t\t// be included by importMap.\n\t\t\tfiles: map[string]string{\n\t\t\t\t\"a/a.go\": `package a; type a int; type T *a`,\n\t\t\t\t\"b/b.go\": `package b; import \"a\"; type B a.T`,\n\t\t\t\t\"c/c.go\": `package c; import \"b\"; type C b.B; var q = *C(nil)`,\n\t\t\t},\n\t\t\tplookups: []pkgLookups{\n\t\t\t\t{\"a\", []lookup{\n\t\t\t\t\t{\"a\", \"myFact(a.a)\"},\n\t\t\t\t\t{\"T\", \"myFact(a.T)\"},\n\t\t\t\t}},\n\t\t\t\t{\"b\", []lookup{\n\t\t\t\t\t{\"B\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"B(nil)\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"*(B(nil))\", \"myFact(a.a)\"},\n\t\t\t\t}},\n\t\t\t\t{\"c\", []lookup{\n\t\t\t\t\t{\"C\", \"myFact(c.C)\"},\n\t\t\t\t\t{\"C(nil)\", \"myFact(c.C)\"},\n\t\t\t\t\t{\"*C(nil)\", \"myFact(a.a)\"},\n\t\t\t\t\t{\"q\", \"myFact(a.a)\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"methods\",\n\t\t\t// c->b->a\n\t\t\t// c does not import a directly or use any of its types, but it does use\n\t\t\t// the types within a indirectly via a method.\n\t\t\tfiles: map[string]string{\n\t\t\t\t\"a/a.go\": `package a; type T int`,\n\t\t\t\t\"b/b.go\": `package b; import \"a\"; type B struct{}; func (_ B) M() a.T { return 0 }`,\n\t\t\t\t\"c/c.go\": `package c; import \"b\"; var C b.B`,\n\t\t\t},\n\t\t\tplookups: []pkgLookups{\n\t\t\t\t{\"a\", []lookup{\n\t\t\t\t\t{\"T\", \"myFact(a.T)\"},\n\t\t\t\t}},\n\t\t\t\t{\"b\", []lookup{\n\t\t\t\t\t{\"B{}\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"B{}.M()\", \"myFact(a.T)\"},\n\t\t\t\t}},\n\t\t\t\t{\"c\", []lookup{\n\t\t\t\t\t{\"C\", \"myFact(b.B)\"},\n\t\t\t\t\t{\"C.M()\", \"myFact(a.T)\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"globals\",\n\t\t\tfiles: map[string]string{\n\t\t\t\t\"a/a.go\": `package a;\n\t\t\t\ttype T1 int\n\t\t\t\ttype T2 int\n\t\t\t\ttype T3 int\n\t\t\t\ttype T4 int\n\t\t\t\ttype T5 int\n\t\t\t\ttype K int; type V string\n\t\t\t\t`,\n\t\t\t\t\"b/b.go\": `package b\n\t\t\t\timport \"a\"\n\t\t\t\tvar (\n\t\t\t\t\tG1 []a.T1\n\t\t\t\t\tG2 [7]a.T2\n\t\t\t\t\tG3 chan a.T3\n\t\t\t\t\tG4 *a.T4\n\t\t\t\t\tG5 struct{ F a.T5 }\n\t\t\t\t\tG6 map[a.K]a.V\n\t\t\t\t)\n\t\t\t\t`,\n\t\t\t\t\"c/c.go\": `package c; import \"b\";\n\t\t\t\tvar (\n\t\t\t\t\tv1 = b.G1\n\t\t\t\t\tv2 = b.G2\n\t\t\t\t\tv3 = b.G3\n\t\t\t\t\tv4 = b.G4\n\t\t\t\t\tv5 = b.G5\n\t\t\t\t\tv6 = b.G6\n\t\t\t\t)\n\t\t\t\t`,\n\t\t\t},\n\t\t\tplookups: []pkgLookups{\n\t\t\t\t{\"a\", []lookup{}},\n\t\t\t\t{\"b\", []lookup{}},\n\t\t\t\t{\"c\", []lookup{\n\t\t\t\t\t{\"v1[0]\", \"myFact(a.T1)\"},\n\t\t\t\t\t{\"v2[0]\", \"myFact(a.T2)\"},\n\t\t\t\t\t{\"<-v3\", \"myFact(a.T3)\"},\n\t\t\t\t\t{\"*v4\", \"myFact(a.T4)\"},\n\t\t\t\t\t{\"v5.F\", \"myFact(a.T5)\"},\n\t\t\t\t\t{\"v6[0]\", \"myFact(a.V)\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"typeparams\",\n\t\t\tfiles: map[string]string{\n\t\t\t\t\"a/a.go\": `package a\n\t\t\t\t  type T1 int\n\t\t\t\t  type T2 int\n\t\t\t\t  type T3 interface{Foo()}\n\t\t\t\t  type T4 int\n\t\t\t\t  type T5 int\n\t\t\t\t  type T6 interface{Foo()}\n\t\t\t\t`,\n\t\t\t\t\"b/b.go\": `package b\n\t\t\t\t  import \"a\"\n\t\t\t\t  type N1[T a.T1|int8] func() T\n\t\t\t\t  type N2[T any] struct{ F T }\n\t\t\t\t  type N3[T a.T3] func() T\n\t\t\t\t  type N4[T a.T4|int8] func() T\n\t\t\t\t  type N5[T interface{Bar() a.T5} ] func() T\n\n\t\t\t\t  type t5 struct{}; func (t5) Bar() a.T5 { return 0 }\n\n\t\t\t\t  var G1 N1[a.T1]\n\t\t\t\t  var G2 func() N2[a.T2]\n\t\t\t\t  var G3 N3[a.T3]\n\t\t\t\t  var G4 N4[a.T4]\n\t\t\t\t  var G5 N5[t5]\n\n\t\t\t\t  func F6[T a.T6]() T { var x T; return x }\n\t\t\t\t  `,\n\t\t\t\t\"c/c.go\": `package c; import \"b\";\n\t\t\t\t  var (\n\t\t\t\t\t  v1 = b.G1\n\t\t\t\t\t  v2 = b.G2\n\t\t\t\t\t  v3 = b.G3\n\t\t\t\t\t  v4 = b.G4\n\t\t\t\t\t  v5 = b.G5\n\t\t\t\t\t  v6 = b.F6[t6]\n\t\t\t\t  )\n\n\t\t\t\t  type t6 struct{}; func (t6) Foo() {}\n\t\t\t\t`,\n\t\t\t},\n\t\t\tplookups: []pkgLookups{\n\t\t\t\t{\"a\", []lookup{}},\n\t\t\t\t{\"b\", []lookup{}},\n\t\t\t\t{\"c\", []lookup{\n\t\t\t\t\t{\"v1\", \"myFact(b.N1)\"},\n\t\t\t\t\t{\"v1()\", \"myFact(a.T1)\"},\n\t\t\t\t\t{\"v2()\", \"myFact(b.N2)\"},\n\t\t\t\t\t{\"v2().F\", \"myFact(a.T2)\"},\n\t\t\t\t\t{\"v3\", \"myFact(b.N3)\"},\n\t\t\t\t\t{\"v4\", \"myFact(b.N4)\"},\n\t\t\t\t\t{\"v4()\", \"myFact(a.T4)\"},\n\t\t\t\t\t{\"v5\", \"myFact(b.N5)\"},\n\t\t\t\t\t{\"v5()\", \"myFact(b.t5)\"},\n\t\t\t\t\t{\"v6()\", \"myFact(c.t6)\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\ttestEncodeDecode(t, test.files, test.plookups)\n\t\t})\n\t}\n}\n\nfunc TestEncodeDecodeAliases(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 24)\n\n\tfiles := map[string]string{\n\t\t\"a/a.go\": `package a\n\t\t\t\t  type A = int\n\t\t\t\t`,\n\t\t\"b/b.go\": `package b\n\t\t\t\t  import \"a\"\n\t\t\t\t  type B = a.A\n\t\t\t\t`,\n\t\t\"c/c.go\": `package c\n\t\t\t\t  import \"b\";\n\t\t\t\t  type N1[T int|~string] = struct{}\n\n\t\t\t\t  var V1 = N1[b.B]{}\n\t\t\t\t`,\n\t}\n\tplookups := []pkgLookups{\n\t\t{\"a\", []lookup{}},\n\t\t{\"b\", []lookup{}},\n\t\t// fake objexpr for RHS of V1's type arg (see customFind hack)\n\t\t{\"c\", []lookup{{\"c.V1->c.N1->b.B->a.A\", \"myFact(a.A)\"}}},\n\t}\n\ttestEncodeDecode(t, files, plookups)\n}\n\ntype lookup struct {\n\tobjexpr string // expression whose type is a named type\n\twant    string // printed form of fact associated with that type (or \"no fact\")\n}\n\ntype pkgLookups struct {\n\tpath    string\n\tlookups []lookup\n}\n\n// testEncodeDecode tests fact encoding and decoding and simulates how package facts\n// are passed during analysis. It operates on a group of Go file contents. Then\n// for each <package, []lookup> in tests it does the following:\n//  1. loads and type checks the package,\n//  2. calls (*facts.Decoder).Decode to load the facts exported by its imports,\n//  3. exports a myFact Fact for all of package level objects,\n//  4. For each lookup for the current package:\n//     4.a) lookup the types.Object for a Go source expression in the current package\n//     (or confirms one is not expected want==\"no object\"),\n//     4.b) finds a Fact for the object (or confirms one is not expected want==\"no fact\"),\n//     4.c) compares the content of the Fact to want.\n//  5. encodes the Facts of the package.\n//\n// Note: tests are not independent test cases; order matters (as does a package being\n// skipped). It changes what Facts can be imported.\n//\n// Failures are reported on t.\nfunc testEncodeDecode(t *testing.T, files map[string]string, tests []pkgLookups) {\n\tdir, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\n\t// factmap represents the passing of encoded facts from one\n\t// package to another. In practice one would use the file system.\n\tfactmap := make(map[string][]byte)\n\tread := func(pkgPath string) ([]byte, error) { return factmap[pkgPath], nil }\n\n\t// Analyze packages in order, look up various objects accessible within\n\t// each package, and see if they have a fact.  The \"analysis\" exports a\n\t// fact for every object at package level.\n\t//\n\t// Note: Loop iterations are not independent test cases;\n\t// order matters, as we populate factmap.\n\tfor _, test := range tests {\n\t\t// load package\n\t\tpkg, err := load(t, dir, test.path)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// decode\n\t\tfacts, err := facts.NewDecoder(pkg).Decode(read)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Decode failed: %v\", err)\n\t\t}\n\t\tt.Logf(\"decode %s facts = %v\", pkg.Path(), facts) // show all facts\n\n\t\t// export\n\t\t// (one fact for each package-level object)\n\t\tfor _, name := range pkg.Scope().Names() {\n\t\t\tobj := pkg.Scope().Lookup(name)\n\t\t\tfact := &myFact{obj.Pkg().Name() + \".\" + obj.Name()}\n\t\t\tfacts.ExportObjectFact(obj, fact)\n\t\t}\n\t\tt.Logf(\"exported %s facts = %v\", pkg.Path(), facts) // show all facts\n\n\t\t// import\n\t\t// (after export, because an analyzer may import its own facts)\n\t\tfor _, lookup := range test.lookups {\n\t\t\tfact := new(myFact)\n\t\t\tvar got string\n\t\t\tif obj := find(pkg, lookup.objexpr); obj == nil {\n\t\t\t\tgot = \"no object\"\n\t\t\t} else if facts.ImportObjectFact(obj, fact) {\n\t\t\t\tgot = fact.String()\n\t\t\t} else {\n\t\t\t\tgot = \"no fact\"\n\t\t\t}\n\t\t\tif got != lookup.want {\n\t\t\t\tt.Errorf(\"in %s, ImportObjectFact(%s, %T) = %s, want %s\",\n\t\t\t\t\tpkg.Path(), lookup.objexpr, fact, got, lookup.want)\n\t\t\t}\n\t\t}\n\n\t\t// encode\n\t\tfactmap[pkg.Path()] = facts.Encode()\n\t}\n}\n\n// customFind allows for overriding how an object is looked up\n// by find. This is necessary for objects that are accessible through\n// the API but are not the type of any expression we can pass to types.CheckExpr.\nvar customFind = map[string]func(p *types.Package) types.Object{\n\t\"c.V1->c.N1->b.B->a.A\": func(p *types.Package) types.Object {\n\t\tcV1 := p.Scope().Lookup(\"V1\")\n\t\tcN1 := cV1.Type().(*types.Alias)\n\t\taT1 := cN1.TypeArgs().At(0).(*types.Alias)\n\t\tzZ1 := aT1.Rhs().(*types.Alias)\n\t\treturn zZ1.Obj()\n\t},\n}\n\nfunc find(p *types.Package, expr string) types.Object {\n\t// types.Eval only allows us to compute a TypeName object for an expression.\n\t// TODO(adonovan): support other expressions that denote an object:\n\t// - an identifier (or qualified ident) for a func, const, or var\n\t// - new(T).f for a field or method\n\t// I've added CheckExpr in https://go-review.googlesource.com/c/go/+/144677.\n\t// If that becomes available, use it.\n\tif f := customFind[expr]; f != nil {\n\t\treturn f(p)\n\t}\n\t// Choose an arbitrary position within the (single-file) package\n\t// so that we are within the scope of its import declarations.\n\tsomepos := p.Scope().Lookup(p.Scope().Names()[0]).Pos()\n\ttv, err := types.Eval(token.NewFileSet(), p, somepos, expr)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tif n, ok := tv.Type.(typesinternal.NamedOrAlias); ok {\n\t\treturn n.Obj()\n\t}\n\treturn nil\n}\n\nfunc load(t *testing.T, dir string, path string) (*types.Package, error) {\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadSyntax,\n\t\tDir:  dir,\n\t\tEnv:  append(os.Environ(), \"GOPATH=\"+dir, \"GO111MODULE=off\", \"GOPROXY=off\"),\n\t}\n\ttestenv.NeedsGoPackagesEnv(t, cfg.Env)\n\tpkgs, err := packages.Load(cfg, path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\treturn nil, fmt.Errorf(\"packages had errors\")\n\t}\n\tif len(pkgs) == 0 {\n\t\treturn nil, fmt.Errorf(\"no package matched %s\", path)\n\t}\n\treturn pkgs[0].Types, nil\n}\n\ntype otherFact struct {\n\tS string\n}\n\nfunc (f *otherFact) String() string { return fmt.Sprintf(\"otherFact(%s)\", f.S) }\nfunc (f *otherFact) AFact()         {}\n\nfunc TestFactFilter(t *testing.T) {\n\tfiles := map[string]string{\n\t\t\"a/a.go\": `package a; type A int`,\n\t}\n\tdir, cleanup, err := analysistest.WriteFiles(files)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cleanup()\n\n\tpkg, err := load(t, dir, \"a\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tobj := pkg.Scope().Lookup(\"A\")\n\ts, err := facts.NewDecoder(pkg).Decode(func(pkgPath string) ([]byte, error) { return nil, nil })\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ts.ExportObjectFact(obj, &myFact{\"good object fact\"})\n\ts.ExportPackageFact(&myFact{\"good package fact\"})\n\ts.ExportObjectFact(obj, &otherFact{\"bad object fact\"})\n\ts.ExportPackageFact(&otherFact{\"bad package fact\"})\n\n\tfilter := map[reflect.Type]bool{\n\t\treflect.TypeFor[*myFact](): true,\n\t}\n\n\tpkgFacts := s.AllPackageFacts(filter)\n\twantPkgFacts := `[{package a (\"a\") myFact(good package fact)}]`\n\tif got := fmt.Sprintf(\"%v\", pkgFacts); got != wantPkgFacts {\n\t\tt.Errorf(\"AllPackageFacts: got %v, want %v\", got, wantPkgFacts)\n\t}\n\n\tobjFacts := s.AllObjectFacts(filter)\n\twantObjFacts := \"[{type a.A int myFact(good object fact)}]\"\n\tif got := fmt.Sprintf(\"%v\", objFacts); got != wantObjFacts {\n\t\tt.Errorf(\"AllObjectFacts: got %v, want %v\", got, wantObjFacts)\n\t}\n}\n\n// TestMalformed checks that facts can be encoded and decoded *despite*\n// types.Config.Check returning an error. Importing facts is expected to\n// happen when Analyzers have RunDespiteErrors set to true. So this\n// needs to robust, e.g. no infinite loops.\nfunc TestMalformed(t *testing.T) {\n\tvar findPkg func(*types.Package, string) *types.Package\n\tfindPkg = func(p *types.Package, name string) *types.Package {\n\t\tif p.Name() == name {\n\t\t\treturn p\n\t\t}\n\t\tfor _, o := range p.Imports() {\n\t\t\tif f := findPkg(o, name); f != nil {\n\t\t\t\treturn f\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\ttype pkgTest struct {\n\t\tcontent string\n\t\terr     string            // if non-empty, expected substring of err.Error() from conf.Check().\n\t\twants   map[string]string // package path to expected name\n\t}\n\ttests := []struct {\n\t\tname string\n\t\tpkgs []pkgTest\n\t}{\n\t\t{\n\t\t\tname: \"initialization-cycle\",\n\t\t\tpkgs: []pkgTest{\n\t\t\t\t// Notation: myFact(a.[N]) means: package a has members {N}.\n\t\t\t\t{\n\t\t\t\t\tcontent: `package a; type N[T any] struct { F *N[N[T]] }`,\n\t\t\t\t\terr:     \"instantiation cycle:\",\n\t\t\t\t\twants:   map[string]string{\"a\": \"myFact(a.[N])\", \"b\": \"no package\", \"c\": \"no package\"},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcontent: `package b; import \"a\"; type B a.N[int]`,\n\t\t\t\t\twants:   map[string]string{\"a\": \"myFact(a.[N])\", \"b\": \"myFact(b.[B])\", \"c\": \"no package\"},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcontent: `package c; import \"b\"; var C b.B`,\n\t\t\t\t\twants:   map[string]string{\"a\": \"no fact\", \"b\": \"myFact(b.[B])\", \"c\": \"myFact(c.[C])\"},\n\t\t\t\t\t// package fact myFact(a.[N]) not reexported\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i := range tests {\n\t\ttest := tests[i]\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// setup for test wide variables.\n\t\t\tpackages := make(map[string]*types.Package)\n\t\t\tconf := types.Config{\n\t\t\t\tImporter: closure(packages),\n\t\t\t\tError:    func(err error) {}, // do not stop on first type checking error\n\t\t\t}\n\t\t\tfset := token.NewFileSet()\n\t\t\tfactmap := make(map[string][]byte)\n\t\t\tread := func(pkgPath string) ([]byte, error) { return factmap[pkgPath], nil }\n\n\t\t\t// Processes the pkgs in order. For package, export a package fact,\n\t\t\t// and use this fact to verify which package facts are reachable via Decode.\n\t\t\t// We allow for packages to have type checking errors.\n\t\t\tfor i, pkgTest := range test.pkgs {\n\t\t\t\t// parse\n\t\t\t\tf, err := parser.ParseFile(fset, fmt.Sprintf(\"%d.go\", i), pkgTest.content, 0)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\t// typecheck\n\t\t\t\tpkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)\n\t\t\t\tvar got string\n\t\t\t\tif err != nil {\n\t\t\t\t\tgot = err.Error()\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(got, pkgTest.err) {\n\t\t\t\t\tt.Fatalf(\"%s: type checking error %q did not match pattern %q\", pkg.Path(), err.Error(), pkgTest.err)\n\t\t\t\t}\n\t\t\t\tpackages[pkg.Path()] = pkg\n\n\t\t\t\t// decode facts\n\t\t\t\tfacts, err := facts.NewDecoder(pkg).Decode(read)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"Decode failed: %v\", err)\n\t\t\t\t}\n\n\t\t\t\t// export facts\n\t\t\t\tfact := &myFact{fmt.Sprintf(\"%s.%s\", pkg.Name(), pkg.Scope().Names())}\n\t\t\t\tfacts.ExportPackageFact(fact)\n\n\t\t\t\t// import facts\n\t\t\t\tfor other, want := range pkgTest.wants {\n\t\t\t\t\tfact := new(myFact)\n\t\t\t\t\tvar got string\n\t\t\t\t\tif found := findPkg(pkg, other); found == nil {\n\t\t\t\t\t\tgot = \"no package\"\n\t\t\t\t\t} else if facts.ImportPackageFact(found, fact) {\n\t\t\t\t\t\tgot = fact.String()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgot = \"no fact\"\n\t\t\t\t\t}\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"in %s, ImportPackageFact(%s, %T) = %s, want %s\",\n\t\t\t\t\t\t\tpkg.Path(), other, fact, got, want)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// encode facts\n\t\t\t\tfactmap[pkg.Path()] = facts.Encode()\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype closure map[string]*types.Package\n\nfunc (c closure) Import(path string) (*types.Package, error) { return c[path], nil }\n"
  },
  {
    "path": "internal/facts/imports.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage facts\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// importMap computes the import map for a package by traversing the\n// entire exported API each of its imports.\n//\n// This is a workaround for the fact that we cannot access the map used\n// internally by the types.Importer returned by go/importer. The entries\n// in this map are the packages and objects that may be relevant to the\n// current analysis unit.\n//\n// Packages in the map that are only indirectly imported may be\n// incomplete (!pkg.Complete()).\n//\n// This function scales very poorly with packages' transitive object\n// references, which can be more than a million for each package near\n// the top of a large project. (This was a significant contributor to\n// #60621.)\n// TODO(adonovan): opt: compute this information more efficiently\n// by obtaining it from the internals of the gcexportdata decoder.\nfunc importMap(imports []*types.Package) map[string]*types.Package {\n\tobjects := make(map[types.Object]bool)\n\ttyps := make(map[types.Type]bool) // Named and TypeParam\n\tpackages := make(map[string]*types.Package)\n\n\tvar addObj func(obj types.Object)\n\tvar addType func(T types.Type)\n\n\taddObj = func(obj types.Object) {\n\t\tif !objects[obj] {\n\t\t\tobjects[obj] = true\n\t\t\taddType(obj.Type())\n\t\t\tif pkg := obj.Pkg(); pkg != nil {\n\t\t\t\tpackages[pkg.Path()] = pkg\n\t\t\t}\n\t\t}\n\t}\n\n\taddType = func(T types.Type) {\n\t\tswitch T := T.(type) {\n\t\tcase *types.Basic:\n\t\t\t// nop\n\t\tcase typesinternal.NamedOrAlias: // *types.{Named,Alias}\n\t\t\t// Add the type arguments if this is an instance.\n\t\t\tif targs := T.TypeArgs(); targs.Len() > 0 {\n\t\t\t\tfor t := range targs.Types() {\n\t\t\t\t\taddType(t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove infinite expansions of *types.Named by always looking at the origin.\n\t\t\t// Some named types with type parameters [that will not type check] have\n\t\t\t// infinite expansions:\n\t\t\t//     type N[T any] struct { F *N[N[T]] }\n\t\t\t// importMap() is called on such types when Analyzer.RunDespiteErrors is true.\n\t\t\tT = typesinternal.Origin(T)\n\t\t\tif !typs[T] {\n\t\t\t\ttyps[T] = true\n\n\t\t\t\t// common aspects\n\t\t\t\taddObj(T.Obj())\n\t\t\t\tif tparams := T.TypeParams(); tparams.Len() > 0 {\n\t\t\t\t\tfor tparam := range tparams.TypeParams() {\n\t\t\t\t\t\taddType(tparam)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// variant aspects\n\t\t\t\tswitch T := T.(type) {\n\t\t\t\tcase *types.Alias:\n\t\t\t\t\taddType(T.Rhs())\n\t\t\t\tcase *types.Named:\n\t\t\t\t\taddType(T.Underlying())\n\t\t\t\t\tfor method := range T.Methods() {\n\t\t\t\t\t\taddObj(method)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tcase *types.Pointer:\n\t\t\taddType(T.Elem())\n\t\tcase *types.Slice:\n\t\t\taddType(T.Elem())\n\t\tcase *types.Array:\n\t\t\taddType(T.Elem())\n\t\tcase *types.Chan:\n\t\t\taddType(T.Elem())\n\t\tcase *types.Map:\n\t\t\taddType(T.Key())\n\t\t\taddType(T.Elem())\n\t\tcase *types.Signature:\n\t\t\taddType(T.Params())\n\t\t\taddType(T.Results())\n\t\t\tif tparams := T.TypeParams(); tparams != nil {\n\t\t\t\tfor tparam := range tparams.TypeParams() {\n\t\t\t\t\taddType(tparam)\n\t\t\t\t}\n\t\t\t}\n\t\tcase *types.Struct:\n\t\t\tfor field := range T.Fields() {\n\t\t\t\taddObj(field)\n\t\t\t}\n\t\tcase *types.Tuple:\n\t\t\tfor v := range T.Variables() {\n\t\t\t\taddObj(v)\n\t\t\t}\n\t\tcase *types.Interface:\n\t\t\tfor method := range T.Methods() {\n\t\t\t\taddObj(method)\n\t\t\t}\n\t\t\tfor etyp := range T.EmbeddedTypes() {\n\t\t\t\taddType(etyp) // walk Embedded for implicits\n\t\t\t}\n\t\tcase *types.Union:\n\t\t\tfor term := range T.Terms() {\n\t\t\t\taddType(term.Type())\n\t\t\t}\n\t\tcase *types.TypeParam:\n\t\t\tif !typs[T] {\n\t\t\t\ttyps[T] = true\n\t\t\t\taddObj(T.Obj())\n\t\t\t\taddType(T.Constraint())\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, imp := range imports {\n\t\tpackages[imp.Path()] = imp\n\n\t\tscope := imp.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\taddObj(scope.Lookup(name))\n\t\t}\n\t}\n\n\treturn packages\n}\n"
  },
  {
    "path": "internal/fmtstr/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The fmtstr command parses the format strings of calls to selected\n// printf-like functions in the specified source file, and prints the\n// formatting operations and their operands.\n//\n// It is intended only for debugging and is not a supported interface.\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"log\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/fmtstr\"\n)\n\nfunc main() {\n\tlog.SetPrefix(\"fmtstr: \")\n\tlog.SetFlags(0)\n\tflag.Parse()\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, flag.Args()[0], nil, 0)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfunctions := map[string]int{\n\t\t\"fmt.Errorf\":  0,\n\t\t\"fmt.Fprintf\": 1,\n\t\t\"fmt.Printf\":  0,\n\t\t\"fmt.Sprintf\": 0,\n\t\t\"log.Printf\":  0,\n\t}\n\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tif call, ok := n.(*ast.CallExpr); ok && !call.Ellipsis.IsValid() {\n\t\t\tif sel, ok := call.Fun.(*ast.SelectorExpr); ok && is[*ast.Ident](sel.X) {\n\t\t\t\tname := sel.X.(*ast.Ident).Name + \".\" + sel.Sel.Name // e.g. \"fmt.Printf\"\n\t\t\t\tif fmtstrIndex, ok := functions[name]; ok &&\n\t\t\t\t\tlen(call.Args) > fmtstrIndex {\n\t\t\t\t\t// Is it a string literal?\n\t\t\t\t\tif fmtstrArg, ok := call.Args[fmtstrIndex].(*ast.BasicLit); ok &&\n\t\t\t\t\t\tfmtstrArg.Kind == token.STRING {\n\t\t\t\t\t\t// Have fmt.Printf(\"format\", ...)\n\t\t\t\t\t\tformat, _ := strconv.Unquote(fmtstrArg.Value)\n\n\t\t\t\t\t\tops, err := fmtstr.Parse(format, 0)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlog.Printf(\"%s: %v\", fset.Position(fmtstrArg.Pos()), err)\n\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfmt.Printf(\"%s: %s(%s, ...)\\n\",\n\t\t\t\t\t\t\tfset.Position(fmtstrArg.Pos()),\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tfmtstrArg.Value)\n\t\t\t\t\t\tfor _, op := range ops {\n\t\t\t\t\t\t\t// TODO(adonovan): show more detail.\n\t\t\t\t\t\t\tfmt.Printf(\"\\t%q\\t%v\\n\",\n\t\t\t\t\t\t\t\top.Text,\n\t\t\t\t\t\t\t\tformatNode(fset, call.Args[op.Verb.ArgIndex]))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\nfunc formatNode(fset *token.FileSet, n ast.Node) string {\n\tvar buf strings.Builder\n\tif err := printer.Fprint(&buf, fset, n); err != nil {\n\t\treturn \"<error>\"\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "internal/fmtstr/parse.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package fmtstr defines a parser for format strings as used by [fmt.Printf].\npackage fmtstr\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// Operation holds the parsed representation of a printf operation such as \"%3.*[4]d\".\n// It is constructed by [Parse].\ntype Operation struct {\n\tText  string // full text of the operation, e.g. \"%[2]*.3d\"\n\tVerb  Verb   // verb specifier, guaranteed to exist, e.g., 'd' in '%[1]d'\n\tRange Range  // the range of Text within the overall format string\n\tFlags string // formatting flags, e.g. \"-0\"\n\tWidth Size   // width specifier, e.g., '3' in '%3d'\n\tPrec  Size   // precision specifier, e.g., '.4' in '%.4f'\n}\n\n// Size describes an optional width or precision in a format operation.\n// It may represent no value, a literal number, an asterisk, or an indexed asterisk.\ntype Size struct {\n\t// At most one of these two fields is non-negative.\n\tFixed   int // e.g. 4 from \"%4d\", otherwise -1\n\tDynamic int // index of argument providing dynamic size (e.g. %*d or %[3]*d), otherwise -1\n\n\tIndex int   // If the width or precision uses an indexed argument (e.g. 2 in %[2]*d), this is the index, otherwise -1\n\tRange Range // position of the size specifier within the operation\n}\n\n// Verb represents the verb character of a format operation (e.g., 'd', 's', 'f').\n// It also includes positional information and any explicit argument indexing.\ntype Verb struct {\n\tVerb     rune\n\tRange    Range // positional range of the verb in the format string\n\tIndex    int   // index of an indexed argument, (e.g. 2 in %[2]d), otherwise -1\n\tArgIndex int   // argument index (0-based) associated with this verb, relative to CallExpr\n}\n\n// byte offsets of format string\ntype Range struct {\n\tStart, End int\n}\n\n// Parse takes a format string and its index in the printf-like call,\n// parses out all format operations, returns a slice of parsed\n// [Operation] which describes flags, width, precision, verb, and argument indexing,\n// or an error if parsing fails.\n//\n// All error messages are in predicate form (\"call has a problem\")\n// so that they may be affixed into a subject (\"log.Printf \").\n//\n// The flags will only be a subset of ['#', '0', '+', '-', ' '].\n// It does not perform any validation of verbs, nor the\n// existence of corresponding arguments (obviously it can't). The provided format string may differ\n// from the one in CallExpr, such as a concatenated string or a string\n// referred to by the argument in the CallExpr.\nfunc Parse(format string, idx int) ([]*Operation, error) {\n\tif !strings.Contains(format, \"%\") {\n\t\treturn nil, fmt.Errorf(\"call has arguments but no formatting directives\")\n\t}\n\n\tfirstArg := idx + 1 // Arguments are immediately after format string.\n\targNum := firstArg\n\tvar operations []*Operation\n\tfor i, w := 0, 0; i < len(format); i += w {\n\t\tw = 1\n\t\tif format[i] != '%' {\n\t\t\tcontinue\n\t\t}\n\t\tstate, err := parseOperation(format[i:], firstArg, argNum)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tstate.operation.addOffset(i)\n\t\toperations = append(operations, state.operation)\n\n\t\tw = len(state.operation.Text)\n\t\t// Do not waste an argument for '%'.\n\t\tif state.operation.Verb.Verb != '%' {\n\t\t\targNum = state.argNum + 1\n\t\t}\n\t}\n\treturn operations, nil\n}\n\n// Internal parsing state to operation.\ntype state struct {\n\toperation    *Operation\n\tfirstArg     int  // index of the first argument after the format string\n\targNum       int  // which argument we're expecting to format now\n\thasIndex     bool // whether the argument is indexed\n\tindex        int  // the encountered index\n\tindexPos     int  // the encountered index's offset\n\tindexPending bool // whether we have an indexed argument that has not resolved\n\tnbytes       int  // number of bytes of the format string consumed\n}\n\n// parseOperation parses one format operation starting at the given substring `format`,\n// which should begin with '%'. It returns a fully populated state or an error\n// if the operation is malformed. The firstArg and argNum parameters help determine how\n// arguments map to this operation.\n//\n// Parse sequence: '%' -> flags -> {[N]* or width} -> .{[N]* or precision} -> [N] -> verb.\nfunc parseOperation(format string, firstArg, argNum int) (*state, error) {\n\tstate := &state{\n\t\toperation: &Operation{\n\t\t\tText: format,\n\t\t\tWidth: Size{\n\t\t\t\tFixed:   -1,\n\t\t\t\tDynamic: -1,\n\t\t\t\tIndex:   -1,\n\t\t\t},\n\t\t\tPrec: Size{\n\t\t\t\tFixed:   -1,\n\t\t\t\tDynamic: -1,\n\t\t\t\tIndex:   -1,\n\t\t\t},\n\t\t},\n\t\tfirstArg:     firstArg,\n\t\targNum:       argNum,\n\t\thasIndex:     false,\n\t\tindex:        0,\n\t\tindexPos:     0,\n\t\tindexPending: false,\n\t\tnbytes:       len(\"%\"), // There's guaranteed to be a percent sign.\n\t}\n\t// There may be flags.\n\tstate.parseFlags()\n\t// There may be an index.\n\tif err := state.parseIndex(); err != nil {\n\t\treturn nil, err\n\t}\n\t// There may be a width.\n\tstate.parseSize(Width)\n\t// There may be a precision.\n\tif err := state.parsePrecision(); err != nil {\n\t\treturn nil, err\n\t}\n\t// Now a verb, possibly prefixed by an index (which we may already have).\n\tif !state.indexPending {\n\t\tif err := state.parseIndex(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif state.nbytes == len(state.operation.Text) {\n\t\treturn nil, fmt.Errorf(\"format %s is missing verb at end of string\", state.operation.Text)\n\t}\n\tverb, w := utf8.DecodeRuneInString(state.operation.Text[state.nbytes:])\n\n\t// Ensure there must be a verb.\n\tif state.indexPending {\n\t\tstate.operation.Verb = Verb{\n\t\t\tVerb: verb,\n\t\t\tRange: Range{\n\t\t\t\tStart: state.indexPos,\n\t\t\t\tEnd:   state.nbytes + w,\n\t\t\t},\n\t\t\tIndex:    state.index,\n\t\t\tArgIndex: state.argNum,\n\t\t}\n\t} else {\n\t\tstate.operation.Verb = Verb{\n\t\t\tVerb: verb,\n\t\t\tRange: Range{\n\t\t\t\tStart: state.nbytes,\n\t\t\t\tEnd:   state.nbytes + w,\n\t\t\t},\n\t\t\tIndex:    -1,\n\t\t\tArgIndex: state.argNum,\n\t\t}\n\t}\n\n\tstate.nbytes += w\n\tstate.operation.Text = state.operation.Text[:state.nbytes]\n\treturn state, nil\n}\n\n// addOffset adjusts the recorded positions in Verb, Width, Prec, and the\n// operation's overall Range to be relative to the position in the full format string.\nfunc (s *Operation) addOffset(parsedLen int) {\n\ts.Verb.Range.Start += parsedLen\n\ts.Verb.Range.End += parsedLen\n\n\ts.Range.Start = parsedLen\n\ts.Range.End = s.Verb.Range.End\n\n\t// one of Fixed or Dynamic is non-negative means existence.\n\tif s.Prec.Fixed != -1 || s.Prec.Dynamic != -1 {\n\t\ts.Prec.Range.Start += parsedLen\n\t\ts.Prec.Range.End += parsedLen\n\t}\n\tif s.Width.Fixed != -1 || s.Width.Dynamic != -1 {\n\t\ts.Width.Range.Start += parsedLen\n\t\ts.Width.Range.End += parsedLen\n\t}\n}\n\n// parseFlags accepts any printf flags.\nfunc (s *state) parseFlags() {\n\ts.operation.Flags = prefixOf(s.operation.Text[s.nbytes:], \"#0+- \")\n\ts.nbytes += len(s.operation.Flags)\n}\n\n// prefixOf returns the prefix of s composed only of runes from the specified set.\nfunc prefixOf(s, set string) string {\n\trest := strings.TrimLeft(s, set)\n\treturn s[:len(s)-len(rest)]\n}\n\n// parseIndex parses an argument index of the form \"[n]\" that can appear\n// in a printf operation (e.g., \"%[2]d\"). Returns an error if syntax is\n// malformed or index is invalid.\nfunc (s *state) parseIndex() error {\n\tif s.nbytes == len(s.operation.Text) || s.operation.Text[s.nbytes] != '[' {\n\t\treturn nil\n\t}\n\t// Argument index present.\n\ts.nbytes++ // skip '['\n\tstart := s.nbytes\n\tif num, ok := s.scanNum(); ok {\n\t\t// Later consumed/stored by a '*' or verb.\n\t\ts.index = num\n\t\ts.indexPos = start - 1\n\t}\n\n\tok := true\n\tif s.nbytes == len(s.operation.Text) || s.nbytes == start || s.operation.Text[s.nbytes] != ']' {\n\t\tok = false // syntax error is either missing \"]\" or invalid index.\n\t\ts.nbytes = strings.Index(s.operation.Text[start:], \"]\")\n\t\tif s.nbytes < 0 {\n\t\t\treturn fmt.Errorf(\"format %s is missing closing ]\", s.operation.Text)\n\t\t}\n\t\ts.nbytes = s.nbytes + start\n\t}\n\targ32, err := strconv.ParseInt(s.operation.Text[start:s.nbytes], 10, 32)\n\tif err != nil || !ok || arg32 <= 0 {\n\t\treturn fmt.Errorf(\"format has invalid argument index [%s]\", s.operation.Text[start:s.nbytes])\n\t}\n\n\ts.nbytes++ // skip ']'\n\targ := int(arg32)\n\targ += s.firstArg - 1 // We want to zero-index the actual arguments.\n\ts.argNum = arg\n\ts.hasIndex = true\n\ts.indexPending = true\n\treturn nil\n}\n\n// scanNum advances through a decimal number if present, which represents a [Size] or [Index].\nfunc (s *state) scanNum() (int, bool) {\n\tstart := s.nbytes\n\tfor ; s.nbytes < len(s.operation.Text); s.nbytes++ {\n\t\tc := s.operation.Text[s.nbytes]\n\t\tif c < '0' || '9' < c {\n\t\t\tif start < s.nbytes {\n\t\t\t\tnum, _ := strconv.ParseInt(s.operation.Text[start:s.nbytes], 10, 32)\n\t\t\t\treturn int(num), true\n\t\t\t} else {\n\t\t\t\treturn 0, false\n\t\t\t}\n\t\t}\n\t}\n\treturn 0, false\n}\n\ntype sizeType int\n\nconst (\n\tWidth sizeType = iota\n\tPrecision\n)\n\n// parseSize parses a width or precision specifier. It handles literal numeric\n// values (e.g., \"%3d\"), asterisk values (e.g., \"%*d\"), or indexed asterisk values (e.g., \"%[2]*d\").\nfunc (s *state) parseSize(kind sizeType) {\n\tif s.nbytes < len(s.operation.Text) && s.operation.Text[s.nbytes] == '*' {\n\t\ts.nbytes++\n\t\tif s.indexPending {\n\t\t\t// Absorb it.\n\t\t\ts.indexPending = false\n\t\t\tsize := Size{\n\t\t\t\tFixed:   -1,\n\t\t\t\tDynamic: s.argNum,\n\t\t\t\tIndex:   s.index,\n\t\t\t\tRange: Range{\n\t\t\t\t\tStart: s.indexPos,\n\t\t\t\t\tEnd:   s.nbytes,\n\t\t\t\t},\n\t\t\t}\n\t\t\tswitch kind {\n\t\t\tcase Width:\n\t\t\t\ts.operation.Width = size\n\t\t\tcase Precision:\n\t\t\t\t// Include the leading '.'.\n\t\t\t\tsize.Range.Start -= len(\".\")\n\t\t\t\ts.operation.Prec = size\n\t\t\tdefault:\n\t\t\t\tpanic(kind)\n\t\t\t}\n\t\t} else {\n\t\t\t// Non-indexed asterisk: \"%*d\".\n\t\t\tsize := Size{\n\t\t\t\tDynamic: s.argNum,\n\t\t\t\tIndex:   -1,\n\t\t\t\tFixed:   -1,\n\t\t\t\tRange: Range{\n\t\t\t\t\tStart: s.nbytes - 1,\n\t\t\t\t\tEnd:   s.nbytes,\n\t\t\t\t},\n\t\t\t}\n\t\t\tswitch kind {\n\t\t\tcase Width:\n\t\t\t\ts.operation.Width = size\n\t\t\tcase Precision:\n\t\t\t\t// For precision, include the '.' in the range.\n\t\t\t\tsize.Range.Start -= 1\n\t\t\t\ts.operation.Prec = size\n\t\t\tdefault:\n\t\t\t\tpanic(kind)\n\t\t\t}\n\t\t}\n\t\ts.argNum++\n\t} else { // Literal number, e.g. \"%10d\"\n\t\tstart := s.nbytes\n\t\tif num, ok := s.scanNum(); ok {\n\t\t\tsize := Size{\n\t\t\t\tFixed:   num,\n\t\t\t\tIndex:   -1,\n\t\t\t\tDynamic: -1,\n\t\t\t\tRange: Range{\n\t\t\t\t\tStart: start,\n\t\t\t\t\tEnd:   s.nbytes,\n\t\t\t\t},\n\t\t\t}\n\t\t\tswitch kind {\n\t\t\tcase Width:\n\t\t\t\ts.operation.Width = size\n\t\t\tcase Precision:\n\t\t\t\t// Include the leading '.'.\n\t\t\t\tsize.Range.Start -= 1\n\t\t\t\ts.operation.Prec = size\n\t\t\tdefault:\n\t\t\t\tpanic(kind)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// parsePrecision checks if there's a precision specified after a '.' character.\n// If found, it may also parse an index or an asterisk. Returns an error if any index\n// parsing fails.\nfunc (s *state) parsePrecision() error {\n\t// If there's a period, there may be a precision.\n\tif s.nbytes < len(s.operation.Text) && s.operation.Text[s.nbytes] == '.' {\n\t\ts.nbytes++\n\t\tif err := s.parseIndex(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts.parseSize(Precision)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/gcimporter/bexport_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/gcimporter\"\n)\n\nvar isRace = false\n\nfunc fileLine(fset *token.FileSet, obj types.Object) string {\n\tposn := fset.Position(obj.Pos())\n\tfilename := filepath.Clean(strings.ReplaceAll(posn.Filename, \"$GOROOT\", runtime.GOROOT()))\n\treturn fmt.Sprintf(\"%s:%d\", filename, posn.Line)\n}\n\nfunc equalType(x, y types.Type) error {\n\tx = types.Unalias(x)\n\ty = types.Unalias(y)\n\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\treturn fmt.Errorf(\"unequal kinds: %T vs %T\", x, y)\n\t}\n\tswitch x := x.(type) {\n\tcase *types.Interface:\n\t\ty := y.(*types.Interface)\n\t\t// TODO(gri): enable separate emission of Embedded interfaces\n\t\t// and ExplicitMethods then use this logic.\n\t\t// if x.NumEmbeddeds() != y.NumEmbeddeds() {\n\t\t// \treturn fmt.Errorf(\"unequal number of embedded interfaces: %d vs %d\",\n\t\t// \t\tx.NumEmbeddeds(), y.NumEmbeddeds())\n\t\t// }\n\t\t// for i := 0; i < x.NumEmbeddeds(); i++ {\n\t\t// \txi := x.Embedded(i)\n\t\t// \tyi := y.Embedded(i)\n\t\t// \tif xi.String() != yi.String() {\n\t\t// \t\treturn fmt.Errorf(\"mismatched %th embedded interface: %s vs %s\",\n\t\t// \t\t\ti, xi, yi)\n\t\t// \t}\n\t\t// }\n\t\t// if x.NumExplicitMethods() != y.NumExplicitMethods() {\n\t\t// \treturn fmt.Errorf(\"unequal methods: %d vs %d\",\n\t\t// \t\tx.NumExplicitMethods(), y.NumExplicitMethods())\n\t\t// }\n\t\t// for i := 0; i < x.NumExplicitMethods(); i++ {\n\t\t// \txm := x.ExplicitMethod(i)\n\t\t// \tym := y.ExplicitMethod(i)\n\t\t// \tif xm.Name() != ym.Name() {\n\t\t// \t\treturn fmt.Errorf(\"mismatched %th method: %s vs %s\", i, xm, ym)\n\t\t// \t}\n\t\t// \tif err := equalType(xm.Type(), ym.Type()); err != nil {\n\t\t// \t\treturn fmt.Errorf(\"mismatched %s method: %s\", xm.Name(), err)\n\t\t// \t}\n\t\t// }\n\t\tif x.NumMethods() != y.NumMethods() {\n\t\t\treturn fmt.Errorf(\"unequal methods: %d vs %d\",\n\t\t\t\tx.NumMethods(), y.NumMethods())\n\t\t}\n\t\tfor i := 0; i < x.NumMethods(); i++ {\n\t\t\txm := x.Method(i)\n\t\t\tym := y.Method(i)\n\t\t\tif xm.Name() != ym.Name() {\n\t\t\t\treturn fmt.Errorf(\"mismatched %dth method: %s vs %s\", i, xm, ym)\n\t\t\t}\n\t\t\tif err := equalType(xm.Type(), ym.Type()); err != nil {\n\t\t\t\treturn fmt.Errorf(\"mismatched %s method: %s\", xm.Name(), err)\n\t\t\t}\n\t\t}\n\t\t// Constraints are handled explicitly in the *TypeParam case below, so we\n\t\t// don't yet need to consider embeddeds here.\n\t\t// TODO(rfindley): consider the type set here.\n\tcase *types.Array:\n\t\ty := y.(*types.Array)\n\t\tif x.Len() != y.Len() {\n\t\t\treturn fmt.Errorf(\"unequal array lengths: %d vs %d\", x.Len(), y.Len())\n\t\t}\n\t\tif err := equalType(x.Elem(), y.Elem()); err != nil {\n\t\t\treturn fmt.Errorf(\"array elements: %s\", err)\n\t\t}\n\tcase *types.Basic:\n\t\ty := y.(*types.Basic)\n\t\tif x.Kind() != y.Kind() {\n\t\t\treturn fmt.Errorf(\"unequal basic types: %s vs %s\", x, y)\n\t\t}\n\tcase *types.Chan:\n\t\ty := y.(*types.Chan)\n\t\tif x.Dir() != y.Dir() {\n\t\t\treturn fmt.Errorf(\"unequal channel directions: %d vs %d\", x.Dir(), y.Dir())\n\t\t}\n\t\tif err := equalType(x.Elem(), y.Elem()); err != nil {\n\t\t\treturn fmt.Errorf(\"channel elements: %s\", err)\n\t\t}\n\tcase *types.Map:\n\t\ty := y.(*types.Map)\n\t\tif err := equalType(x.Key(), y.Key()); err != nil {\n\t\t\treturn fmt.Errorf(\"map keys: %s\", err)\n\t\t}\n\t\tif err := equalType(x.Elem(), y.Elem()); err != nil {\n\t\t\treturn fmt.Errorf(\"map values: %s\", err)\n\t\t}\n\tcase *types.Named:\n\t\ty := y.(*types.Named)\n\t\treturn cmpNamed(x, y)\n\tcase *types.Pointer:\n\t\ty := y.(*types.Pointer)\n\t\tif err := equalType(x.Elem(), y.Elem()); err != nil {\n\t\t\treturn fmt.Errorf(\"pointer elements: %s\", err)\n\t\t}\n\tcase *types.Signature:\n\t\ty := y.(*types.Signature)\n\t\tif err := equalType(x.Params(), y.Params()); err != nil {\n\t\t\treturn fmt.Errorf(\"parameters: %s\", err)\n\t\t}\n\t\tif err := equalType(x.Results(), y.Results()); err != nil {\n\t\t\treturn fmt.Errorf(\"results: %s\", err)\n\t\t}\n\t\tif x.Variadic() != y.Variadic() {\n\t\t\treturn fmt.Errorf(\"unequal variadicity: %t vs %t\",\n\t\t\t\tx.Variadic(), y.Variadic())\n\t\t}\n\t\tif (x.Recv() != nil) != (y.Recv() != nil) {\n\t\t\treturn fmt.Errorf(\"unequal receivers: %s vs %s\", x.Recv(), y.Recv())\n\t\t}\n\t\tif x.Recv() != nil {\n\t\t\t// TODO(adonovan): fix: this assertion fires for interface methods.\n\t\t\t// The type of the receiver of an interface method is a named type\n\t\t\t// if the Package was loaded from export data, or an unnamed (interface)\n\t\t\t// type if the Package was produced by type-checking ASTs.\n\t\t\t// if err := equalType(x.Recv().Type(), y.Recv().Type()); err != nil {\n\t\t\t// \treturn fmt.Errorf(\"receiver: %s\", err)\n\t\t\t// }\n\t\t}\n\t\tif err := equalTypeParams(x.TypeParams(), y.TypeParams()); err != nil {\n\t\t\treturn fmt.Errorf(\"type params: %s\", err)\n\t\t}\n\t\tif err := equalTypeParams(x.RecvTypeParams(), y.RecvTypeParams()); err != nil {\n\t\t\treturn fmt.Errorf(\"recv type params: %s\", err)\n\t\t}\n\tcase *types.Slice:\n\t\ty := y.(*types.Slice)\n\t\tif err := equalType(x.Elem(), y.Elem()); err != nil {\n\t\t\treturn fmt.Errorf(\"slice elements: %s\", err)\n\t\t}\n\tcase *types.Struct:\n\t\ty := y.(*types.Struct)\n\t\tif x.NumFields() != y.NumFields() {\n\t\t\treturn fmt.Errorf(\"unequal struct fields: %d vs %d\",\n\t\t\t\tx.NumFields(), y.NumFields())\n\t\t}\n\t\tfor i := 0; i < x.NumFields(); i++ {\n\t\t\txf := x.Field(i)\n\t\t\tyf := y.Field(i)\n\t\t\tif xf.Name() != yf.Name() {\n\t\t\t\treturn fmt.Errorf(\"mismatched fields: %s vs %s\", xf, yf)\n\t\t\t}\n\t\t\tif err := equalType(xf.Type(), yf.Type()); err != nil {\n\t\t\t\treturn fmt.Errorf(\"struct field %s: %s\", xf.Name(), err)\n\t\t\t}\n\t\t\tif x.Tag(i) != y.Tag(i) {\n\t\t\t\treturn fmt.Errorf(\"struct field %s has unequal tags: %q vs %q\",\n\t\t\t\t\txf.Name(), x.Tag(i), y.Tag(i))\n\t\t\t}\n\t\t}\n\tcase *types.Tuple:\n\t\ty := y.(*types.Tuple)\n\t\tif x.Len() != y.Len() {\n\t\t\treturn fmt.Errorf(\"unequal tuple lengths: %d vs %d\", x.Len(), y.Len())\n\t\t}\n\t\tfor i := 0; i < x.Len(); i++ {\n\t\t\tif err := equalType(x.At(i).Type(), y.At(i).Type()); err != nil {\n\t\t\t\treturn fmt.Errorf(\"tuple element %d: %s\", i, err)\n\t\t\t}\n\t\t}\n\tcase *types.TypeParam:\n\t\ty := y.(*types.TypeParam)\n\t\tif x.String() != y.String() {\n\t\t\treturn fmt.Errorf(\"unequal named types: %s vs %s\", x, y)\n\t\t}\n\t\t// For now, just compare constraints by type string to short-circuit\n\t\t// cycles. We have to make interfaces explicit as export data currently\n\t\t// doesn't support marking interfaces as implicit.\n\t\t// TODO(rfindley): remove makeExplicit once export data contains an\n\t\t// implicit bit.\n\t\txc := makeExplicit(x.Constraint()).String()\n\t\tyc := makeExplicit(y.Constraint()).String()\n\t\tif xc != yc {\n\t\t\treturn fmt.Errorf(\"unequal constraints: %s vs %s\", xc, yc)\n\t\t}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unexpected %T type\", x))\n\t}\n\treturn nil\n}\n\n// cmpNamed compares two named types x and y, returning an error for any\n// discrepancies. It does not compare their underlying types.\nfunc cmpNamed(x, y *types.Named) error {\n\txOrig := x.Origin()\n\tyOrig := y.Origin()\n\tif xOrig.String() != yOrig.String() {\n\t\treturn fmt.Errorf(\"unequal named types: %s vs %s\", x, y)\n\t}\n\tif err := equalTypeParams(x.TypeParams(), y.TypeParams()); err != nil {\n\t\treturn fmt.Errorf(\"type parameters: %s\", err)\n\t}\n\tif err := equalTypeArgs(x.TypeArgs(), y.TypeArgs()); err != nil {\n\t\treturn fmt.Errorf(\"type arguments: %s\", err)\n\t}\n\tif x.NumMethods() != y.NumMethods() {\n\t\treturn fmt.Errorf(\"unequal methods: %d vs %d\",\n\t\t\tx.NumMethods(), y.NumMethods())\n\t}\n\t// Unfortunately method sorting is not canonical, so sort before comparing.\n\tvar xms, yms []*types.Func\n\tfor i := 0; i < x.NumMethods(); i++ {\n\t\txms = append(xms, x.Method(i))\n\t\tyms = append(yms, y.Method(i))\n\t}\n\tfor _, ms := range [][]*types.Func{xms, yms} {\n\t\tsort.Slice(ms, func(i, j int) bool {\n\t\t\treturn ms[i].Name() < ms[j].Name()\n\t\t})\n\t}\n\tfor i, xm := range xms {\n\t\tym := yms[i]\n\t\tif xm.Name() != ym.Name() {\n\t\t\treturn fmt.Errorf(\"mismatched %dth method: %s vs %s\", i, xm, ym)\n\t\t}\n\t\t// Calling equalType here leads to infinite recursion, so just compare\n\t\t// strings.\n\t\tif xm.String() != ym.String() {\n\t\t\treturn fmt.Errorf(\"unequal methods: %s vs %s\", x, y)\n\t\t}\n\t}\n\treturn nil\n}\n\n// makeExplicit returns an explicit version of typ, if typ is an implicit\n// interface. Otherwise it returns typ unmodified.\nfunc makeExplicit(typ types.Type) types.Type {\n\tif iface, _ := typ.(*types.Interface); iface != nil && iface.IsImplicit() {\n\t\tvar methods []*types.Func\n\t\tfor i := 0; i < iface.NumExplicitMethods(); i++ {\n\t\t\tmethods = append(methods, iface.Method(i))\n\t\t}\n\t\tvar embeddeds []types.Type\n\t\tfor etyp := range iface.EmbeddedTypes() {\n\t\t\tembeddeds = append(embeddeds, etyp)\n\t\t}\n\t\treturn types.NewInterfaceType(methods, embeddeds)\n\t}\n\treturn typ\n}\n\nfunc equalTypeArgs(x, y *types.TypeList) error {\n\tif x.Len() != y.Len() {\n\t\treturn fmt.Errorf(\"unequal lengths: %d vs %d\", x.Len(), y.Len())\n\t}\n\tfor i := 0; i < x.Len(); i++ {\n\t\tif err := equalType(x.At(i), y.At(i)); err != nil {\n\t\t\treturn fmt.Errorf(\"type %d: %s\", i, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc equalTypeParams(x, y *types.TypeParamList) error {\n\tif x.Len() != y.Len() {\n\t\treturn fmt.Errorf(\"unequal lengths: %d vs %d\", x.Len(), y.Len())\n\t}\n\tfor i := 0; i < x.Len(); i++ {\n\t\tif err := equalType(x.At(i), y.At(i)); err != nil {\n\t\t\treturn fmt.Errorf(\"type parameter %d: %s\", i, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// TestVeryLongFile tests the position of an import object declared in\n// a very long input file.  Line numbers greater than maxlines are\n// reported as line 1, not garbage or token.NoPos.\nfunc TestVeryLongFile(t *testing.T) {\n\t// parse and typecheck\n\tlongFile := \"package foo\" + strings.Repeat(\"\\n\", 123456) + \"var X int\"\n\tfset1 := token.NewFileSet()\n\tf, err := parser.ParseFile(fset1, \"foo.go\", longFile, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"foo\", fset1, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// export\n\tvar out bytes.Buffer\n\tif err := gcimporter.IExportData(&out, fset1, pkg); err != nil {\n\t\tt.Fatal(err)\n\t}\n\texportdata := out.Bytes()\n\n\t// import\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg.Path())\n\tif err != nil {\n\t\tt.Fatalf(\"BImportData(%s): %v\", pkg.Path(), err)\n\t}\n\n\t// compare\n\tposn1 := fset1.Position(pkg.Scope().Lookup(\"X\").Pos())\n\tposn2 := fset2.Position(pkg2.Scope().Lookup(\"X\").Pos())\n\tif want := \"foo.go:1:1\"; posn2.String() != want {\n\t\tt.Errorf(\"X position = %s, want %s (orig was %s)\",\n\t\t\tposn2, want, posn1)\n\t}\n}\n\nconst src = `\npackage p\n\ntype (\n\tT0 = int32\n\tT1 = struct{}\n\tT2 = struct{ T1 }\n\tInvalid = foo // foo is undeclared\n)\n`\n\nfunc checkPkg(t *testing.T, pkg *types.Package, label string) {\n\tT1 := types.NewStruct(nil, nil)\n\tT2 := types.NewStruct([]*types.Var{types.NewField(0, pkg, \"T1\", T1, true)}, nil)\n\n\tfor _, test := range []struct {\n\t\tname string\n\t\ttyp  types.Type\n\t}{\n\t\t{\"T0\", types.Typ[types.Int32]},\n\t\t{\"T1\", T1},\n\t\t{\"T2\", T2},\n\t\t{\"Invalid\", types.Typ[types.Invalid]},\n\t} {\n\t\tobj := pkg.Scope().Lookup(test.name)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"%s: %s not found\", label, test.name)\n\t\t\tcontinue\n\t\t}\n\t\ttname, _ := obj.(*types.TypeName)\n\t\tif tname == nil {\n\t\t\tt.Errorf(\"%s: %v not a type name\", label, obj)\n\t\t\tcontinue\n\t\t}\n\t\tif !tname.IsAlias() {\n\t\t\tt.Errorf(\"%s: %v: not marked as alias\", label, tname)\n\t\t\tcontinue\n\t\t}\n\t\tif got := tname.Type(); !types.Identical(got, test.typ) {\n\t\t\tt.Errorf(\"%s: %v: got %v; want %v\", label, tname, got, test.typ)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/gcimporter/bimport.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains the remaining vestiges of\n// $GOROOT/src/go/internal/gcimporter/bimport.go.\n\npackage gcimporter\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sync\"\n)\n\nfunc errorf(format string, args ...any) {\n\tpanic(fmt.Sprintf(format, args...))\n}\n\nconst deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go\n\n// Synthesize a token.Pos\ntype fakeFileSet struct {\n\tfset  *token.FileSet\n\tfiles map[string]*fileInfo\n}\n\ntype fileInfo struct {\n\tfile     *token.File\n\tlastline int\n}\n\nconst maxlines = 64 * 1024\n\nfunc (s *fakeFileSet) pos(file string, line, column int) token.Pos {\n\t_ = column // TODO(mdempsky): Make use of column.\n\n\t// Since we don't know the set of needed file positions, we reserve maxlines\n\t// positions per file. We delay calling token.File.SetLines until all\n\t// positions have been calculated (by way of fakeFileSet.setLines), so that\n\t// we can avoid setting unnecessary lines. See also golang/go#46586.\n\tf := s.files[file]\n\tif f == nil {\n\t\tf = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)}\n\t\ts.files[file] = f\n\t}\n\tif line > maxlines {\n\t\tline = 1\n\t}\n\tif line > f.lastline {\n\t\tf.lastline = line\n\t}\n\n\t// Return a fake position assuming that f.file consists only of newlines.\n\treturn token.Pos(f.file.Base() + line - 1)\n}\n\nfunc (s *fakeFileSet) setLines() {\n\tfakeLinesOnce.Do(func() {\n\t\tfakeLines = make([]int, maxlines)\n\t\tfor i := range fakeLines {\n\t\t\tfakeLines[i] = i\n\t\t}\n\t})\n\tfor _, f := range s.files {\n\t\tf.file.SetLines(fakeLines[:f.lastline])\n\t}\n}\n\nvar (\n\tfakeLines     []int\n\tfakeLinesOnce sync.Once\n)\n\nfunc chanDir(d int) types.ChanDir {\n\t// tag values must match the constants in cmd/compile/internal/gc/go.go\n\tswitch d {\n\tcase 1 /* Crecv */ :\n\t\treturn types.RecvOnly\n\tcase 2 /* Csend */ :\n\t\treturn types.SendOnly\n\tcase 3 /* Cboth */ :\n\t\treturn types.SendRecv\n\tdefault:\n\t\terrorf(\"unexpected channel dir %d\", d)\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "internal/gcimporter/exportdata.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file should be kept in sync with $GOROOT/src/internal/exportdata/exportdata.go.\n// This file also additionally implements FindExportData for gcexportdata.NewReader.\n\npackage gcimporter\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// FindExportData positions the reader r at the beginning of the\n// export data section of an underlying cmd/compile created archive\n// file by reading from it. The reader must be positioned at the\n// start of the file before calling this function.\n// This returns the length of the export data in bytes.\n//\n// This function is needed by [gcexportdata.Read], which must\n// accept inputs produced by the last two releases of cmd/compile,\n// plus tip.\nfunc FindExportData(r *bufio.Reader) (size int64, err error) {\n\tarsize, err := FindPackageDefinition(r)\n\tif err != nil {\n\t\treturn\n\t}\n\tsize = int64(arsize)\n\n\tobjapi, headers, err := ReadObjectHeaders(r)\n\tif err != nil {\n\t\treturn\n\t}\n\tsize -= int64(len(objapi))\n\tfor _, h := range headers {\n\t\tsize -= int64(len(h))\n\t}\n\n\t// Check for the binary export data section header \"$$B\\n\".\n\t// TODO(taking): Unify with ReadExportDataHeader so that it stops at the 'u' instead of reading\n\tline, err := r.ReadSlice('\\n')\n\tif err != nil {\n\t\treturn\n\t}\n\thdr := string(line)\n\tif hdr != \"$$B\\n\" {\n\t\terr = fmt.Errorf(\"unknown export data header: %q\", hdr)\n\t\treturn\n\t}\n\tsize -= int64(len(hdr))\n\n\t// For files with a binary export data header \"$$B\\n\",\n\t// these are always terminated by an end-of-section marker \"\\n$$\\n\".\n\t// So the last bytes must always be this constant.\n\t//\n\t// The end-of-section marker is not a part of the export data itself.\n\t// Do not include these in size.\n\t//\n\t// It would be nice to have sanity check that the final bytes after\n\t// the export data are indeed the end-of-section marker. The split\n\t// of gcexportdata.NewReader and gcexportdata.Read make checking this\n\t// ugly so gcimporter gives up enforcing this. The compiler and go/types\n\t// importer do enforce this, which seems good enough.\n\tconst endofsection = \"\\n$$\\n\"\n\tsize -= int64(len(endofsection))\n\n\tif size < 0 {\n\t\terr = fmt.Errorf(\"invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)\", arsize, size)\n\t\treturn\n\t}\n\n\treturn\n}\n\n// ReadUnified reads the contents of the unified export data from a reader r\n// that contains the contents of a GC-created archive file.\n//\n// On success, the reader will be positioned after the end-of-section marker \"\\n$$\\n\".\n//\n// Supported GC-created archive files have 4 layers of nesting:\n//   - An archive file containing a package definition file.\n//   - The package definition file contains headers followed by a data section.\n//     Headers are lines (≤ 4kb) that do not start with \"$$\".\n//   - The data section starts with \"$$B\\n\" followed by export data followed\n//     by an end of section marker \"\\n$$\\n\". (The section start \"$$\\n\" is no\n//     longer supported.)\n//   - The export data starts with a format byte ('u') followed by the <data> in\n//     the given format. (See ReadExportDataHeader for older formats.)\n//\n// Putting this together, the bytes in a GC-created archive files are expected\n// to look like the following.\n// See cmd/internal/archive for more details on ar file headers.\n//\n// | <!arch>\\n             | ar file signature\n// | __.PKGDEF...size...\\n | ar header for __.PKGDEF including size.\n// | go object <...>\\n     | objabi header\n// | <optional headers>\\n  | other headers such as build id\n// | $$B\\n                 | binary format marker\n// | u<data>\\n             | unified export <data>\n// | $$\\n                  | end-of-section marker\n// | [optional padding]    | padding byte (0x0A) if size is odd\n// | [ar file header]      | other ar files\n// | [ar file data]        |\nfunc ReadUnified(r *bufio.Reader) (data []byte, err error) {\n\t// We historically guaranteed headers at the default buffer size (4096) work.\n\t// This ensures we can use ReadSlice throughout.\n\tconst minBufferSize = 4096\n\tr = bufio.NewReaderSize(r, minBufferSize)\n\n\tsize, err := FindPackageDefinition(r)\n\tif err != nil {\n\t\treturn\n\t}\n\tn := size\n\n\tobjapi, headers, err := ReadObjectHeaders(r)\n\tif err != nil {\n\t\treturn\n\t}\n\tn -= len(objapi)\n\tfor _, h := range headers {\n\t\tn -= len(h)\n\t}\n\n\thdrlen, err := ReadExportDataHeader(r)\n\tif err != nil {\n\t\treturn\n\t}\n\tn -= hdrlen\n\n\t// size also includes the end of section marker. Remove that many bytes from the end.\n\tconst marker = \"\\n$$\\n\"\n\tn -= len(marker)\n\n\tif n < 0 {\n\t\terr = fmt.Errorf(\"invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)\", size, n)\n\t\treturn\n\t}\n\n\t// Read n bytes from buf.\n\tdata = make([]byte, n)\n\t_, err = io.ReadFull(r, data)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// Check for marker at the end.\n\tvar suffix [len(marker)]byte\n\t_, err = io.ReadFull(r, suffix[:])\n\tif err != nil {\n\t\treturn\n\t}\n\tif s := string(suffix[:]); s != marker {\n\t\terr = fmt.Errorf(\"read %q instead of end-of-section marker (%q)\", s, marker)\n\t\treturn\n\t}\n\n\treturn\n}\n\n// FindPackageDefinition positions the reader r at the beginning of a package\n// definition file (\"__.PKGDEF\") within a GC-created archive by reading\n// from it, and returns the size of the package definition file in the archive.\n//\n// The reader must be positioned at the start of the archive file before calling\n// this function, and \"__.PKGDEF\" is assumed to be the first file in the archive.\n//\n// See cmd/internal/archive for details on the archive format.\nfunc FindPackageDefinition(r *bufio.Reader) (size int, err error) {\n\t// Uses ReadSlice to limit risk of malformed inputs.\n\n\t// Read first line to make sure this is an object file.\n\tline, err := r.ReadSlice('\\n')\n\tif err != nil {\n\t\terr = fmt.Errorf(\"can't find export data (%v)\", err)\n\t\treturn\n\t}\n\n\t// Is the first line an archive file signature?\n\tif string(line) != \"!<arch>\\n\" {\n\t\terr = fmt.Errorf(\"not the start of an archive file (%q)\", line)\n\t\treturn\n\t}\n\n\t// package export block should be first\n\tsize = readArchiveHeader(r, \"__.PKGDEF\")\n\tif size <= 0 {\n\t\terr = fmt.Errorf(\"not a package file\")\n\t\treturn\n\t}\n\n\treturn\n}\n\n// ReadObjectHeaders reads object headers from the reader. Object headers are\n// lines that do not start with an end-of-section marker \"$$\". The first header\n// is the objabi header. On success, the reader will be positioned at the beginning\n// of the end-of-section marker.\n//\n// It returns an error if any header does not fit in r.Size() bytes.\nfunc ReadObjectHeaders(r *bufio.Reader) (objapi string, headers []string, err error) {\n\t// line is a temporary buffer for headers.\n\t// Use bounded reads (ReadSlice, Peek) to limit risk of malformed inputs.\n\tvar line []byte\n\n\t// objapi header should be the first line\n\tif line, err = r.ReadSlice('\\n'); err != nil {\n\t\terr = fmt.Errorf(\"can't find export data (%v)\", err)\n\t\treturn\n\t}\n\tobjapi = string(line)\n\n\t// objapi header begins with \"go object \".\n\tif !strings.HasPrefix(objapi, \"go object \") {\n\t\terr = fmt.Errorf(\"not a go object file: %s\", objapi)\n\t\treturn\n\t}\n\n\t// process remaining object header lines\n\tfor {\n\t\t// check for an end of section marker \"$$\"\n\t\tline, err = r.Peek(2)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif string(line) == \"$$\" {\n\t\t\treturn // stop\n\t\t}\n\n\t\t// read next header\n\t\tline, err = r.ReadSlice('\\n')\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\theaders = append(headers, string(line))\n\t}\n}\n\n// ReadExportDataHeader reads the export data header and format from r.\n// It returns the number of bytes read, or an error if the format is no longer\n// supported or it failed to read.\n//\n// The only currently supported format is binary export data in the\n// unified export format.\nfunc ReadExportDataHeader(r *bufio.Reader) (n int, err error) {\n\t// Read export data header.\n\tline, err := r.ReadSlice('\\n')\n\tif err != nil {\n\t\treturn\n\t}\n\n\thdr := string(line)\n\tswitch hdr {\n\tcase \"$$\\n\":\n\t\terr = fmt.Errorf(\"old textual export format no longer supported (recompile package)\")\n\t\treturn\n\n\tcase \"$$B\\n\":\n\t\tvar format byte\n\t\tformat, err = r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\t// The unified export format starts with a 'u'.\n\t\tswitch format {\n\t\tcase 'u':\n\t\tdefault:\n\t\t\t// Older no longer supported export formats include:\n\t\t\t// indexed export format which started with an 'i'; and\n\t\t\t// the older binary export format which started with a 'c',\n\t\t\t// 'd', or 'v' (from \"version\").\n\t\t\terr = fmt.Errorf(\"binary export format %q is no longer supported (recompile package)\", format)\n\t\t\treturn\n\t\t}\n\n\tdefault:\n\t\terr = fmt.Errorf(\"unknown export data header: %q\", hdr)\n\t\treturn\n\t}\n\n\tn = len(hdr) + 1 // + 1 is for 'u'\n\treturn\n}\n\n// FindPkg returns the filename and unique package id for an import\n// path based on package information provided by build.Import (using\n// the build.Default build.Context). A relative srcDir is interpreted\n// relative to the current working directory.\n//\n// FindPkg is only used in tests within x/tools.\nfunc FindPkg(path, srcDir string) (filename, id string, err error) {\n\t// TODO(taking): Move internal/exportdata.FindPkg into its own file,\n\t// and then this copy into a _test package.\n\tif path == \"\" {\n\t\treturn \"\", \"\", errors.New(\"path is empty\")\n\t}\n\n\tvar noext string\n\tswitch {\n\tdefault:\n\t\t// \"x\" -> \"$GOPATH/pkg/$GOOS_$GOARCH/x.ext\", \"x\"\n\t\t// Don't require the source files to be present.\n\t\tif abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282\n\t\t\tsrcDir = abs\n\t\t}\n\t\tvar bp *build.Package\n\t\tbp, err = build.Import(path, srcDir, build.FindOnly|build.AllowBinary)\n\t\tif bp.PkgObj == \"\" {\n\t\t\tif bp.Goroot && bp.Dir != \"\" {\n\t\t\t\tfilename, err = lookupGorootExport(bp.Dir)\n\t\t\t\tif err == nil {\n\t\t\t\t\t_, err = os.Stat(filename)\n\t\t\t\t}\n\t\t\t\tif err == nil {\n\t\t\t\t\treturn filename, bp.ImportPath, nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tgoto notfound\n\t\t} else {\n\t\t\tnoext = strings.TrimSuffix(bp.PkgObj, \".a\")\n\t\t}\n\t\tid = bp.ImportPath\n\n\tcase build.IsLocalImport(path):\n\t\t// \"./x\" -> \"/this/directory/x.ext\", \"/this/directory/x\"\n\t\tnoext = filepath.Join(srcDir, path)\n\t\tid = noext\n\n\tcase filepath.IsAbs(path):\n\t\t// for completeness only - go/build.Import\n\t\t// does not support absolute imports\n\t\t// \"/x\" -> \"/x.ext\", \"/x\"\n\t\tnoext = path\n\t\tid = path\n\t}\n\n\tif false { // for debugging\n\t\tif path != id {\n\t\t\tfmt.Printf(\"%s -> %s\\n\", path, id)\n\t\t}\n\t}\n\n\t// try extensions\n\tfor _, ext := range pkgExts {\n\t\tfilename = noext + ext\n\t\tf, statErr := os.Stat(filename)\n\t\tif statErr == nil && !f.IsDir() {\n\t\t\treturn filename, id, nil\n\t\t}\n\t\tif err == nil {\n\t\t\terr = statErr\n\t\t}\n\t}\n\nnotfound:\n\tif err == nil {\n\t\treturn \"\", path, fmt.Errorf(\"can't find import: %q\", path)\n\t}\n\treturn \"\", path, fmt.Errorf(\"can't find import: %q: %w\", path, err)\n}\n\nvar pkgExts = [...]string{\".a\", \".o\"} // a file from the build cache will have no extension\n\nvar exportMap sync.Map // package dir → func() (string, error)\n\n// lookupGorootExport returns the location of the export data\n// (normally found in the build cache, but located in GOROOT/pkg\n// in prior Go releases) for the package located in pkgDir.\n//\n// (We use the package's directory instead of its import path\n// mainly to simplify handling of the packages in src/vendor\n// and cmd/vendor.)\n//\n// lookupGorootExport is only used in tests within x/tools.\nfunc lookupGorootExport(pkgDir string) (string, error) {\n\tf, ok := exportMap.Load(pkgDir)\n\tif !ok {\n\t\tvar (\n\t\t\tlistOnce   sync.Once\n\t\t\texportPath string\n\t\t\terr        error\n\t\t)\n\t\tf, _ = exportMap.LoadOrStore(pkgDir, func() (string, error) {\n\t\t\tlistOnce.Do(func() {\n\t\t\t\tcmd := exec.Command(filepath.Join(build.Default.GOROOT, \"bin\", \"go\"), \"list\", \"-export\", \"-f\", \"{{.Export}}\", pkgDir)\n\t\t\t\tcmd.Dir = build.Default.GOROOT\n\t\t\t\tcmd.Env = append(os.Environ(), \"PWD=\"+cmd.Dir, \"GOROOT=\"+build.Default.GOROOT)\n\t\t\t\tvar output []byte\n\t\t\t\toutput, err = cmd.Output()\n\t\t\t\tif err != nil {\n\t\t\t\t\tif ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {\n\t\t\t\t\t\terr = errors.New(string(ee.Stderr))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\texports := strings.Split(string(bytes.TrimSpace(output)), \"\\n\")\n\t\t\t\tif len(exports) != 1 {\n\t\t\t\t\terr = fmt.Errorf(\"go list reported %d exports; expected 1\", len(exports))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\texportPath = exports[0]\n\t\t\t})\n\n\t\t\treturn exportPath, err\n\t\t})\n\t}\n\n\treturn f.(func() (string, error))()\n}\n"
  },
  {
    "path": "internal/gcimporter/gcimporter.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is a reduced copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go.\n\n// Package gcimporter provides various functions for reading\n// gc-generated object files that can be used to implement the\n// Importer interface defined by the Go 1.5 standard library package.\n//\n// The encoding is deterministic: if the encoder is applied twice to\n// the same types.Package data structure, both encodings are equal.\n// This property may be important to avoid spurious changes in\n// applications such as build systems.\n//\n// However, the encoder is not necessarily idempotent. Importing an\n// exported package may yield a types.Package that, while it\n// represents the same set of Go types as the original, may differ in\n// the details of its internal representation. Because of these\n// differences, re-encoding the imported package may yield a\n// different, but equally valid, encoding of the package.\npackage gcimporter // import \"golang.org/x/tools/internal/gcimporter\"\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n)\n\nconst (\n\t// Enable debug during development: it adds some additional checks, and\n\t// prevents errors from being recovered.\n\tdebug = false\n\n\t// If trace is set, debugging output is printed to std out.\n\ttrace = false\n)\n\n// Import imports a gc-generated package given its import path and srcDir, adds\n// the corresponding package object to the packages map, and returns the object.\n// The packages map must contain all packages already imported.\n//\n// Import is only used in tests.\nfunc Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) {\n\tvar rc io.ReadCloser\n\tvar id string\n\tif lookup != nil {\n\t\t// With custom lookup specified, assume that caller has\n\t\t// converted path to a canonical import path for use in the map.\n\t\tif path == \"unsafe\" {\n\t\t\treturn types.Unsafe, nil\n\t\t}\n\t\tid = path\n\n\t\t// No need to re-import if the package was imported completely before.\n\t\tif pkg = packages[id]; pkg != nil && pkg.Complete() {\n\t\t\treturn\n\t\t}\n\t\tf, err := lookup(path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trc = f\n\t} else {\n\t\tvar filename string\n\t\tfilename, id, err = FindPkg(path, srcDir)\n\t\tif filename == \"\" {\n\t\t\tif path == \"unsafe\" {\n\t\t\t\treturn types.Unsafe, nil\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// no need to re-import if the package was imported completely before\n\t\tif pkg = packages[id]; pkg != nil && pkg.Complete() {\n\t\t\treturn\n\t\t}\n\n\t\t// open file\n\t\tf, err := os.Open(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\t// add file name to error\n\t\t\t\terr = fmt.Errorf(\"%s: %v\", filename, err)\n\t\t\t}\n\t\t}()\n\t\trc = f\n\t}\n\tdefer rc.Close()\n\n\tbuf := bufio.NewReader(rc)\n\tdata, err := ReadUnified(buf)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"import %q: %v\", path, err)\n\t\treturn\n\t}\n\n\t// unified: emitted by cmd/compile since go1.20.\n\t_, pkg, err = UImportData(fset, packages, data, id)\n\n\treturn\n}\n"
  },
  {
    "path": "internal/gcimporter/gcimporter_test.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter_test.go,\n// adjusted to make it build with code from (std lib) internal/testenv copied.\n\npackage gcimporter_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\tgoimporter \"go/importer\"\n\tgoparser \"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/gcimporter\"\n\t\"golang.org/x/tools/internal/goroot\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\ttestenv.ExitIfSmallMachine()\n\tos.Exit(m.Run())\n}\n\n// ----------------------------------------------------------------------------\n\nfunc needsCompiler(t *testing.T, compiler string) {\n\tif runtime.Compiler == compiler {\n\t\treturn\n\t}\n\tswitch compiler {\n\tcase \"gc\":\n\t\tt.Skipf(\"gc-built packages not available (compiler = %s)\", runtime.Compiler)\n\t}\n}\n\n// compile runs the compiler on filename, with dirname as the working directory,\n// and writes the output file to outdirname.\n// compile gives the resulting package a packagepath of p.\nfunc compile(t *testing.T, dirname, filename, outdirname string, packagefiles map[string]string) string {\n\treturn compilePkg(t, dirname, filename, outdirname, packagefiles, \"p\")\n}\n\nfunc compilePkg(t *testing.T, dirname, filename, outdirname string, packagefiles map[string]string, pkg string) string {\n\ttestenv.NeedsGoBuild(t)\n\n\t// filename must end with \".go\"\n\tbasename := strings.TrimSuffix(filepath.Base(filename), \".go\")\n\tok := filename != basename\n\tif !ok {\n\t\tt.Fatalf(\"filename doesn't end in .go: %s\", filename)\n\t}\n\tobjname := basename + \".o\"\n\toutname := filepath.Join(outdirname, objname)\n\n\timportcfgfile := os.DevNull\n\tif len(packagefiles) > 0 {\n\t\timportcfgfile = filepath.Join(outdirname, basename) + \".importcfg\"\n\t\timportcfg := new(bytes.Buffer)\n\t\tfmt.Fprintf(importcfg, \"# import config\")\n\t\tfor k, v := range packagefiles {\n\t\t\tfmt.Fprintf(importcfg, \"\\npackagefile %s=%s\\n\", k, v)\n\t\t}\n\t\tif err := os.WriteFile(importcfgfile, importcfg.Bytes(), 0655); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\timportreldir := strings.ReplaceAll(outdirname, string(os.PathSeparator), \"/\")\n\tcmd := exec.Command(\"go\", \"tool\", \"compile\", \"-p\", pkg, \"-D\", importreldir, \"-importcfg\", importcfgfile, \"-o\", outname, filename)\n\tcmd.Dir = dirname\n\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\tt.Logf(\"%s\", out)\n\t\tt.Fatalf(\"go tool compile %s failed: %s\", filename, err)\n\t}\n\treturn outname\n}\n\nfunc testPath(t *testing.T, path, srcDir string) *types.Package {\n\tt0 := time.Now()\n\tpkg, err := gcimporter.Import(token.NewFileSet(), make(map[string]*types.Package), path, srcDir, nil)\n\tif err != nil {\n\t\tt.Errorf(\"testPath(%s): %s\", path, err)\n\t\treturn nil\n\t}\n\tt.Logf(\"testPath(%s): %v\", path, time.Since(t0))\n\treturn pkg\n}\n\nfunc mktmpdir(t *testing.T) string {\n\ttmpdir, err := os.MkdirTemp(\"\", \"gcimporter_test\")\n\tif err != nil {\n\t\tt.Fatal(\"mktmpdir:\", err)\n\t}\n\tif err := os.Mkdir(filepath.Join(tmpdir, \"testdata\"), 0700); err != nil {\n\t\tos.RemoveAll(tmpdir)\n\t\tt.Fatal(\"mktmpdir:\", err)\n\t}\n\treturn tmpdir\n}\n\nconst testfile = \"exports.go\"\n\nfunc TestImportTestdata(t *testing.T) {\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\n\tpackageFiles := map[string]string{}\n\tfor _, pkg := range []string{\"go/ast\", \"go/token\"} {\n\t\texport, _, err := gcimporter.FindPkg(pkg, \"testdata\")\n\t\tif export == \"\" {\n\t\t\tt.Fatalf(\"no export data found for %s: %s\", pkg, err)\n\t\t}\n\t\tpackageFiles[pkg] = export\n\t}\n\n\tcompile(t, \"testdata\", testfile, filepath.Join(tmpdir, \"testdata\"), packageFiles)\n\n\t// filename should end with \".go\"\n\tfilename := testfile[:len(testfile)-3]\n\tif pkg := testPath(t, \"./testdata/\"+filename, tmpdir); pkg != nil {\n\t\t// The package's Imports list must include all packages\n\t\t// explicitly imported by testfile, plus all packages\n\t\t// referenced indirectly via exported objects in testfile.\n\t\t// With the textual export format (when run against Go1.6),\n\t\t// the list may also include additional packages that are\n\t\t// not strictly required for import processing alone (they\n\t\t// are exported to err \"on the safe side\").\n\t\t// For now, we just test the presence of a few packages\n\t\t// that we know are there for sure.\n\t\tgot := fmt.Sprint(pkg.Imports())\n\t\twants := []string{\"go/ast\", \"go/token\", \"go/ast\"}\n\t\tfor _, want := range wants {\n\t\t\tif !strings.Contains(got, want) {\n\t\t\t\tt.Errorf(`Package(\"exports\").Imports() = %s, does not contain %s`, got, want)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestImportTypeparamTests(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skipf(\"in short mode, skipping test that requires export data for all of std\")\n\t}\n\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\ttestenv.NeedsGOROOTDir(t, \"test\")\n\n\t// This package only handles gc export data.\n\tif runtime.Compiler != \"gc\" {\n\t\tt.Skipf(\"gc-built packages not available (compiler = %s)\", runtime.Compiler)\n\t}\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\n\t// Check go files in test/typeparam, except those that fail for a known\n\t// reason.\n\trootDir := filepath.Join(runtime.GOROOT(), \"test\", \"typeparam\")\n\tlist, err := os.ReadDir(rootDir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, entry := range list {\n\t\tif entry.IsDir() || !strings.HasSuffix(entry.Name(), \".go\") {\n\t\t\t// For now, only consider standalone go files.\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Run(entry.Name(), func(t *testing.T) {\n\t\t\tfilename := filepath.Join(rootDir, entry.Name())\n\t\t\tsrc, err := os.ReadFile(filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif !bytes.HasPrefix(src, []byte(\"// run\")) && !bytes.HasPrefix(src, []byte(\"// compile\")) {\n\t\t\t\t// We're bypassing the logic of run.go here, so be conservative about\n\t\t\t\t// the files we consider in an attempt to make this test more robust to\n\t\t\t\t// changes in test/typeparams.\n\t\t\t\tt.Skipf(\"not detected as a run test\")\n\t\t\t}\n\n\t\t\t// Compile and import, and compare the resulting package with the package\n\t\t\t// that was type-checked directly.\n\t\t\tpkgFiles, err := goroot.PkgfileMap()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tcompile(t, rootDir, entry.Name(), filepath.Join(tmpdir, \"testdata\"), pkgFiles)\n\t\t\tpkgName := strings.TrimSuffix(entry.Name(), \".go\")\n\t\t\timported := importPkg(t, \"./testdata/\"+pkgName, tmpdir)\n\t\t\tchecked := checkFile(t, filename, src)\n\n\t\t\tseen := make(map[string]bool)\n\t\t\tfor _, name := range imported.Scope().Names() {\n\t\t\t\tif !token.IsExported(name) {\n\t\t\t\t\tcontinue // ignore synthetic names like .inittask and .dict.*\n\t\t\t\t}\n\t\t\t\tseen[name] = true\n\n\t\t\t\timportedObj := imported.Scope().Lookup(name)\n\t\t\t\tgot := types.ObjectString(importedObj, types.RelativeTo(imported))\n\n\t\t\t\tcheckedObj := checked.Scope().Lookup(name)\n\t\t\t\tif checkedObj == nil {\n\t\t\t\t\tt.Fatalf(\"imported object %q was not type-checked\", name)\n\t\t\t\t}\n\t\t\t\twant := types.ObjectString(checkedObj, types.RelativeTo(checked))\n\n\t\t\t\tif got != want {\n\t\t\t\t\tt.Errorf(\"imported %q as %q, want %q\", name, got, want)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, name := range checked.Scope().Names() {\n\t\t\t\tif !token.IsExported(name) || seen[name] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tt.Errorf(\"did not import object %q\", name)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc checkFile(t *testing.T, filename string, src []byte) *types.Package {\n\tfset := token.NewFileSet()\n\tf, err := goparser.ParseFile(fset, filename, src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tconfig := types.Config{\n\t\tImporter: goimporter.Default(),\n\t}\n\tpkg, err := config.Check(\"\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn pkg\n}\n\nfunc TestVersionHandling(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\n\tconst dir = \"./testdata/versions\"\n\tlist, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\tcorruptdir := filepath.Join(tmpdir, \"testdata\", \"versions\")\n\tif err := os.Mkdir(corruptdir, 0700); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, f := range list {\n\t\tname := f.Name()\n\t\tif !strings.HasSuffix(name, \".a\") {\n\t\t\tcontinue // not a package file\n\t\t}\n\t\tif strings.Contains(name, \"corrupted\") {\n\t\t\tcontinue // don't process a leftover corrupted file\n\t\t}\n\t\tpkgpath := \"./\" + name[:len(name)-2]\n\n\t\tif testing.Verbose() {\n\t\t\tt.Logf(\"importing %s\", name)\n\t\t}\n\n\t\t// test that export data can be imported\n\t\t_, err := gcimporter.Import(token.NewFileSet(), make(map[string]*types.Package), pkgpath, dir, nil)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"import %q failed: %v\", pkgpath, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// create file with corrupted export data\n\t\t// 1) read file\n\t\tdata, err := os.ReadFile(filepath.Join(dir, name))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// 2) find export data\n\t\t// Index is an incorrect but 'good enough for tests' way to find the end of the export data.\n\t\ti := bytes.Index(data, []byte(\"\\n$$B\\n\")) + 5\n\t\tj := bytes.Index(data[i:], []byte(\"\\n$$\\n\")) + i\n\t\tif i < 0 || j < 0 || i > j {\n\t\t\tt.Fatalf(\"export data section not found (i = %d, j = %d)\", i, j)\n\t\t}\n\t\t// 3) corrupt the data (increment every 7th byte)\n\t\tfor k := j - 13; k >= i; k -= 7 {\n\t\t\tdata[k]++\n\t\t}\n\t\t// 4) write the file\n\t\tpkgpath += \"_corrupted\"\n\t\tfilename := filepath.Join(corruptdir, pkgpath) + \".a\"\n\t\tos.WriteFile(filename, data, 0666)\n\n\t\t// test that importing the corrupted file results in an error\n\t\t_, err = gcimporter.Import(token.NewFileSet(), make(map[string]*types.Package), pkgpath, corruptdir, nil)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"import corrupted %q succeeded\", pkgpath)\n\t\t} else if msg := err.Error(); !strings.Contains(msg, \"internal error\") {\n\t\t\tt.Errorf(\"import %q error incorrect (%s)\", pkgpath, msg)\n\t\t}\n\t}\n}\n\nfunc TestImportStdLib(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"the imports can be expensive, and this test is especially slow when the build cache is empty\")\n\t}\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\t// Get list of packages in stdlib. Filter out test-only packages with {{if .GoFiles}} check.\n\tvar stderr bytes.Buffer\n\tcmd := exec.Command(\"go\", \"list\", \"-f\", \"{{if .GoFiles}}{{.ImportPath}}{{end}}\", \"std\")\n\tcmd.Stderr = &stderr\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\tt.Fatalf(\"failed to run go list to determine stdlib packages: %v\\nstderr:\\n%v\", err, stderr.String())\n\t}\n\tpkgs := strings.Fields(string(out))\n\n\tvar nimports int\n\tfor _, pkg := range pkgs {\n\t\tt.Run(pkg, func(t *testing.T) {\n\t\t\tif testPath(t, pkg, filepath.Join(testenv.GOROOT(t), \"src\", path.Dir(pkg))) != nil {\n\t\t\t\tnimports++\n\t\t\t}\n\t\t})\n\t}\n\tconst minPkgs = 225 // 'GOOS=plan9 go1.18 list std | wc -l' reports 228; most other platforms have more.\n\tif len(pkgs) < minPkgs {\n\t\tt.Fatalf(\"too few packages (%d) were imported\", nimports)\n\t}\n\n\tt.Logf(\"tested %d imports\", nimports)\n}\n\nvar importedObjectTests = []struct {\n\tname string\n\twant string\n}{\n\t// non-interfaces\n\t{\"crypto.Hash\", \"type Hash uint\"},\n\t{\"go/ast.ObjKind\", \"type ObjKind int\"},\n\t{\"go/types.Qualifier\", \"type Qualifier func(*Package) string\"},\n\t{\"go/types.Comparable\", \"func Comparable(T Type) bool\"},\n\t{\"math.Pi\", \"const Pi untyped float\"},\n\t{\"math.Sin\", \"func Sin(x float64) float64\"},\n\t{\"go/ast.NotNilFilter\", \"func NotNilFilter(_ string, v reflect.Value) bool\"},\n\n\t// interfaces\n\t{\"context.Context\", \"type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}\"},\n\t{\"crypto.Decrypter\", \"type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}\"},\n\t{\"encoding.BinaryMarshaler\", \"type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}\"},\n\t{\"io.Reader\", \"type Reader interface{Read(p []byte) (n int, err error)}\"},\n\t{\"io.ReadWriter\", \"type ReadWriter interface{Reader; Writer}\"},\n\t{\"go/ast.Node\", \"type Node interface{End() go/token.Pos; Pos() go/token.Pos}\"},\n\t{\"go/types.Type\", \"type Type interface{String() string; Underlying() Type}\"},\n}\n\nfunc TestImportedTypes(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\tfor _, test := range importedObjectTests {\n\t\tobj := importObject(t, test.name)\n\t\tif obj == nil {\n\t\t\tcontinue // error reported elsewhere\n\t\t}\n\t\tgot := types.ObjectString(obj, types.RelativeTo(obj.Pkg()))\n\n\t\t// TODO(rsc): Delete this block once go.dev/cl/368254 lands.\n\t\tif got != test.want && test.want == strings.ReplaceAll(got, \"interface{}\", \"any\") {\n\t\t\tgot = test.want\n\t\t}\n\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"%s: got %q; want %q\", test.name, got, test.want)\n\t\t}\n\n\t\tif named, _ := types.Unalias(obj.Type()).(*types.Named); named != nil {\n\t\t\tverifyInterfaceMethodRecvs(t, named, 0)\n\t\t}\n\t}\n}\n\nfunc TestImportedConsts(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\ttests := []struct {\n\t\tname string\n\t\twant constant.Kind\n\t}{\n\t\t{\"math.Pi\", constant.Float},\n\t\t{\"math.MaxFloat64\", constant.Float},\n\t\t{\"math.MaxInt64\", constant.Int},\n\t}\n\n\tfor _, test := range tests {\n\t\tobj := importObject(t, test.name)\n\t\tif got := obj.(*types.Const).Val().Kind(); got != test.want {\n\t\t\tt.Errorf(\"%s: imported as constant.Kind(%v), want constant.Kind(%v)\", test.name, got, test.want)\n\t\t}\n\t}\n}\n\n// importObject imports the object specified by a name of the form\n// <import path>.<object name>, e.g. go/types.Type.\n//\n// If any errors occur they are reported via t and the resulting object will\n// be nil.\nfunc importObject(t *testing.T, name string) types.Object {\n\ts := strings.Split(name, \".\")\n\tif len(s) != 2 {\n\t\tt.Fatal(\"inconsistent test data\")\n\t}\n\timportPath := s[0]\n\tobjName := s[1]\n\n\tpkg, err := gcimporter.Import(token.NewFileSet(), make(map[string]*types.Package), importPath, \".\", nil)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn nil\n\t}\n\n\tobj := pkg.Scope().Lookup(objName)\n\tif obj == nil {\n\t\tt.Errorf(\"%s: object not found\", name)\n\t\treturn nil\n\t}\n\treturn obj\n}\n\n// verifyInterfaceMethodRecvs verifies that method receiver types\n// are named if the methods belong to a named interface type.\nfunc verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) {\n\t// avoid endless recursion in case of an embedding bug that lead to a cycle\n\tif level > 10 {\n\t\tt.Errorf(\"%s: embeds itself\", named)\n\t\treturn\n\t}\n\n\tiface, _ := named.Underlying().(*types.Interface)\n\tif iface == nil {\n\t\treturn // not an interface\n\t}\n\n\t// check explicitly declared methods\n\tfor m := range iface.ExplicitMethods() {\n\t\trecv := m.Type().(*types.Signature).Recv()\n\t\tif recv == nil {\n\t\t\tt.Errorf(\"%s: missing receiver type\", m)\n\t\t\tcontinue\n\t\t}\n\t\tif recv.Type() != named {\n\t\t\tt.Errorf(\"%s: got recv type %s; want %s\", m, recv.Type(), named)\n\t\t}\n\t}\n\n\t// check embedded interfaces (if they are named, too)\n\tfor etyp := range iface.EmbeddedTypes() {\n\t\t// embedding of interfaces cannot have cycles; recursion will terminate\n\t\tif etype, _ := types.Unalias(etyp).(*types.Named); etype != nil {\n\t\t\tverifyInterfaceMethodRecvs(t, etype, level+1)\n\t\t}\n\t}\n}\n\nfunc TestIssue5815(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\tpkg := importPkg(t, \"strings\", \".\")\n\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif obj.Pkg() == nil {\n\t\t\tt.Errorf(\"no pkg for %s\", obj)\n\t\t}\n\t\tif tname, _ := obj.(*types.TypeName); tname != nil {\n\t\t\tnamed := types.Unalias(tname.Type()).(*types.Named)\n\t\t\tfor m := range named.Methods() {\n\t\t\t\tif m.Pkg() == nil {\n\t\t\t\t\tt.Errorf(\"no pkg for %s\", m)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Smoke test to ensure that imported methods get the correct package.\nfunc TestCorrectMethodPackage(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\timports := make(map[string]*types.Package)\n\t_, err := gcimporter.Import(token.NewFileSet(), imports, \"net/http\", \".\", nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tmutex := imports[\"sync\"].Scope().Lookup(\"Mutex\").(*types.TypeName).Type()\n\tmset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex\n\tsel := mset.Lookup(nil, \"Lock\")\n\tlock := sel.Obj().(*types.Func)\n\tif got, want := lock.Pkg().Path(), \"sync\"; got != want {\n\t\tt.Errorf(\"got package path %q; want %q\", got, want)\n\t}\n}\n\nfunc TestIssue13566(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\tskipWindows(t)\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\ttestoutdir := filepath.Join(tmpdir, \"testdata\")\n\n\t// b.go needs to be compiled from the output directory so that the compiler can\n\t// find the compiled package a. We pass the full path to compile() so that we\n\t// don't have to copy the file to that directory.\n\tbpath, err := filepath.Abs(filepath.Join(\"testdata\", \"b.go\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tjsonExport, _, err := gcimporter.FindPkg(\"encoding/json\", \"testdata\")\n\tif jsonExport == \"\" {\n\t\tt.Fatalf(\"no export data found for encoding/json: %s\", err)\n\t}\n\n\tcompilePkg(t, \"testdata\", \"a.go\", testoutdir, map[string]string{\"encoding/json\": jsonExport}, apkg(testoutdir))\n\tcompile(t, testoutdir, bpath, testoutdir, map[string]string{apkg(testoutdir): filepath.Join(testoutdir, \"a.o\")})\n\n\t// import must succeed (test for issue at hand)\n\tpkg := importPkg(t, \"./testdata/b\", tmpdir)\n\n\t// make sure all indirectly imported packages have names\n\tfor _, imp := range pkg.Imports() {\n\t\tif imp.Name() == \"\" {\n\t\t\tt.Errorf(\"no name for %s package\", imp.Path())\n\t\t}\n\t}\n}\n\nfunc TestIssue13898(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\n\t// import go/internal/gcimporter which imports go/types partially\n\timports := make(map[string]*types.Package)\n\t_, err := gcimporter.Import(token.NewFileSet(), imports, \"go/internal/gcimporter\", \".\", nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// look for go/types package\n\tvar goTypesPkg *types.Package\n\tfor path, pkg := range imports {\n\t\tif path == \"go/types\" {\n\t\t\tgoTypesPkg = pkg\n\t\t\tbreak\n\t\t}\n\t}\n\tif goTypesPkg == nil {\n\t\tt.Fatal(\"go/types not found\")\n\t}\n\n\t// look for go/types.Object type\n\tobj := lookupObj(t, goTypesPkg.Scope(), \"Object\")\n\ttyp, ok := types.Unalias(obj.Type()).(*types.Named)\n\tif !ok {\n\t\tt.Fatalf(\"go/types.Object type is %v; wanted named type\", typ)\n\t}\n\n\t// lookup go/types.Object.Pkg method\n\tm, index, indirect := types.LookupFieldOrMethod(typ, false, nil, \"Pkg\")\n\tif m == nil {\n\t\tt.Fatalf(\"go/types.Object.Pkg not found (index = %v, indirect = %v)\", index, indirect)\n\t}\n\n\t// the method must belong to go/types\n\tif m.Pkg().Path() != \"go/types\" {\n\t\tt.Fatalf(\"found %v; want go/types\", m.Pkg())\n\t}\n}\n\nfunc TestIssue15517(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\n\tcompile(t, \"testdata\", \"p.go\", filepath.Join(tmpdir, \"testdata\"), nil)\n\n\t// Multiple imports of p must succeed without redeclaration errors.\n\t// We use an import path that's not cleaned up so that the eventual\n\t// file path for the package is different from the package path; this\n\t// will expose the error if it is present.\n\t//\n\t// (Issue: Both the textual and the binary importer used the file path\n\t// of the package to be imported as key into the shared packages map.\n\t// However, the binary importer then used the package path to identify\n\t// the imported package to mark it as complete; effectively marking the\n\t// wrong package as complete. By using an \"unclean\" package path, the\n\t// file and package path are different, exposing the problem if present.\n\t// The same issue occurs with vendoring.)\n\timports := make(map[string]*types.Package)\n\tfor range 3 {\n\t\tif _, err := gcimporter.Import(token.NewFileSet(), imports, \"./././testdata/p\", tmpdir, nil); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestIssue15920(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\tcompileAndImportPkg(t, \"issue15920\")\n}\n\nfunc TestIssue20046(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\t// \"./issue20046\".V.M must exist\n\tpkg := compileAndImportPkg(t, \"issue20046\")\n\tobj := lookupObj(t, pkg.Scope(), \"V\")\n\tif m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, \"M\"); m == nil {\n\t\tt.Fatalf(\"V.M not found (index = %v, indirect = %v)\", index, indirect)\n\t}\n}\n\nfunc TestIssue25301(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\tcompileAndImportPkg(t, \"issue25301\")\n}\n\nfunc TestIssue51836(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\ttestoutdir := filepath.Join(tmpdir, \"testdata\")\n\n\tdir := filepath.Join(\"testdata\", \"issue51836\")\n\t// Following the pattern of TestIssue13898, aa.go needs to be compiled from\n\t// the output directory. We pass the full path to compile() so that we don't\n\t// have to copy the file to that directory.\n\tbpath, err := filepath.Abs(filepath.Join(dir, \"aa.go\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcompilePkg(t, dir, \"a.go\", testoutdir, nil, apkg(testoutdir))\n\tcompile(t, testoutdir, bpath, testoutdir, map[string]string{apkg(testoutdir): filepath.Join(testoutdir, \"a.o\")})\n\n\t// import must succeed (test for issue at hand)\n\t_ = importPkg(t, \"./testdata/aa\", tmpdir)\n}\n\nfunc TestIssue61561(t *testing.T) {\n\tconst src = `package p\n\ntype I[P any] interface {\n\tm(P)\n\tn() P\n}\n\ntype J = I[int]\n\ntype StillBad[P any] *interface{b(P)}\n\ntype K = StillBad[string]\n`\n\tfset := token.NewFileSet()\n\tf, err := goparser.ParseFile(fset, \"p.go\", src, 0)\n\tif f == nil {\n\t\t// Some test cases may have parse errors, but we must always have a\n\t\t// file.\n\t\tt.Fatalf(\"ParseFile returned nil file. Err: %v\", err)\n\t}\n\n\tconfig := &types.Config{}\n\tpkg1, err := config.Check(\"p\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Export it. (Shallowness isn't important here.)\n\tdata, err := gcimporter.IExportShallow(fset, pkg1, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"export: %v\", err) // any failure to export is a bug\n\t}\n\n\t// Re-import it.\n\timports := make(map[string]*types.Package)\n\tpkg2, err := gcimporter.IImportShallow(fset, gcimporter.GetPackagesFromMap(imports), data, \"p\", nil)\n\tif err != nil {\n\t\tt.Fatalf(\"import: %v\", err) // any failure of IExport+IImport is a bug.\n\t}\n\n\tinsts := []types.Type{\n\t\tpkg2.Scope().Lookup(\"J\").Type(),\n\t\t// This test is still racy, because the incomplete interface is contained\n\t\t// within a nested type expression.\n\t\t//\n\t\t// Uncomment this once golang/go#61561 is fixed.\n\t\t// pkg2.Scope().Lookup(\"K\").Type().Underlying().(*types.Pointer).Elem(),\n\t}\n\n\t// Use the interface instances concurrently.\n\tfor _, inst := range insts {\n\t\tvar wg sync.WaitGroup\n\t\tfor range 2 {\n\t\t\twg.Add(1)\n\t\t\tgo func() {\n\t\t\t\tdefer wg.Done()\n\t\t\t\t_ = types.NewMethodSet(inst)\n\t\t\t}()\n\t\t}\n\t\twg.Wait()\n\t}\n}\n\nfunc TestIssue57015(t *testing.T) {\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\tskipWindows(t)\n\n\tcompileAndImportPkg(t, \"issue57015\")\n}\n\n// This is a regression test for a failure to export a package\n// containing type errors.\n//\n// Though the issues and tests are specific, they may be representatives of a\n// class of exporter bugs on ill-typed code that we have yet to flush out.\n//\n// TODO(adonovan): systematize our search for similar problems using\n// fuzz testing.\nfunc TestExportInvalid(t *testing.T) {\n\n\ttests := []struct {\n\t\tname    string\n\t\tsrc     string\n\t\tobjName string\n\t}{\n\t\t// The lack of a receiver causes Recv.Type=Invalid.\n\t\t// (The type checker then treats Foo as a package-level\n\t\t// function, inserting it into the package scope.)\n\t\t// The exporter needs to apply the same treatment.\n\t\t{\"issue 57729\", `package p; func () Foo() {}`, \"Foo\"},\n\n\t\t// It must be possible to export a constant with unknown kind, even if its\n\t\t// type is known.\n\t\t{\"issue 60605\", `package p; const EPSILON float64 = 1e-`, \"EPSILON\"},\n\n\t\t// We must not crash when exporting a struct with unknown package.\n\t\t{\"issue 60891\", `package p; type I[P any] int; const C I[struct{}] = 42`, \"C\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\t// Parse the ill-typed input.\n\t\t\tfset := token.NewFileSet()\n\n\t\t\tf, err := goparser.ParseFile(fset, \"p.go\", test.src, 0)\n\t\t\tif f == nil {\n\t\t\t\t// Some test cases may have parse errors, but we must always have a\n\t\t\t\t// file.\n\t\t\t\tt.Fatalf(\"ParseFile returned nil file. Err: %v\", err)\n\t\t\t}\n\n\t\t\t// Type check it, expecting errors.\n\t\t\tconfig := &types.Config{\n\t\t\t\tError: func(err error) { t.Log(err) }, // don't abort at first error\n\t\t\t}\n\t\t\tpkg1, _ := config.Check(\"p\", fset, []*ast.File{f}, nil)\n\n\t\t\t// Export it.\n\t\t\t// (Shallowness isn't important here.)\n\t\t\tdata, err := gcimporter.IExportShallow(fset, pkg1, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"export: %v\", err) // any failure to export is a bug\n\t\t\t}\n\n\t\t\t// Re-import it.\n\t\t\timports := make(map[string]*types.Package)\n\t\t\tpkg2, err := gcimporter.IImportShallow(fset, gcimporter.GetPackagesFromMap(imports), data, \"p\", nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"import: %v\", err) // any failure of IExport+IImport is a bug.\n\t\t\t}\n\n\t\t\t// Check that the expected object is present in both packages.\n\t\t\t// We can't assert the type hasn't changed: it may have, in some cases.\n\t\t\thasObj1 := pkg1.Scope().Lookup(test.objName) != nil\n\t\t\thasObj2 := pkg2.Scope().Lookup(test.objName) != nil\n\t\t\tif hasObj1 != hasObj2 {\n\t\t\t\tt.Errorf(\"export+import changed Lookup(%q)!=nil: was %t, became %t\", test.objName, hasObj1, hasObj2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIssue58296(t *testing.T) {\n\t// Compiles packages c, b, and a where c imports b and b imports a,\n\t// then imports c with stub *types.Packages for b and a, and checks that\n\t// both a and b are in the Imports() of c.\n\t//\n\t// This is how go/packages can read the exportdata when NeedDeps is off.\n\n\t// This package only handles gc export data.\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\tskipWindows(t)\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\ttestoutdir := filepath.Join(tmpdir, \"testdata\")\n\n\tapkg := filepath.Join(testoutdir, \"a\")\n\tbpkg := filepath.Join(testoutdir, \"b\")\n\tcpkg := filepath.Join(testoutdir, \"c\")\n\n\tsrcdir := filepath.Join(\"testdata\", \"issue58296\")\n\tcompilePkg(t, filepath.Join(srcdir, \"a\"), \"a.go\", testoutdir, nil, apkg)\n\tcompilePkg(t, filepath.Join(srcdir, \"b\"), \"b.go\", testoutdir, map[string]string{apkg: filepath.Join(testoutdir, \"a.o\")}, bpkg)\n\tcompilePkg(t, filepath.Join(srcdir, \"c\"), \"c.go\", testoutdir, map[string]string{bpkg: filepath.Join(testoutdir, \"b.o\")}, cpkg)\n\n\t// The export data reader for c cannot rely on Package.Imports\n\t// being populated for a or b. (For the imports {a,b} it is unset.)\n\timports := map[string]*types.Package{\n\t\tapkg: types.NewPackage(apkg, \"a\"),\n\t\tbpkg: types.NewPackage(bpkg, \"b\"),\n\t}\n\n\t// make sure a and b are both imported by c.\n\tpkg, err := gcimporter.Import(token.NewFileSet(), imports, \"./c\", testoutdir, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar names []string\n\tfor _, imp := range pkg.Imports() {\n\t\tnames = append(names, imp.Name())\n\t}\n\tsort.Strings(names)\n\n\tif got, want := strings.Join(names, \",\"), \"a,b\"; got != want {\n\t\tt.Errorf(\"got imports %v for package c. wanted %v\", names, want)\n\t}\n}\n\nfunc TestIssueAliases(t *testing.T) {\n\t// This package only handles gc export data.\n\ttestenv.NeedsGo1Point(t, 24)\n\tneedsCompiler(t, \"gc\")\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\tskipWindows(t)\n\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\ttestoutdir := filepath.Join(tmpdir, \"testdata\")\n\n\tapkg := filepath.Join(testoutdir, \"a\")\n\tbpkg := filepath.Join(testoutdir, \"b\")\n\tcpkg := filepath.Join(testoutdir, \"c\")\n\n\t// compile a, b and c into gc export data.\n\tsrcdir := filepath.Join(\"testdata\", \"aliases\")\n\tcompilePkg(t, filepath.Join(srcdir, \"a\"), \"a.go\", testoutdir, nil, apkg)\n\tcompilePkg(t, filepath.Join(srcdir, \"b\"), \"b.go\", testoutdir, map[string]string{apkg: filepath.Join(testoutdir, \"a.o\")}, bpkg)\n\tcompilePkg(t, filepath.Join(srcdir, \"c\"), \"c.go\", testoutdir,\n\t\tmap[string]string{apkg: filepath.Join(testoutdir, \"a.o\"), bpkg: filepath.Join(testoutdir, \"b.o\")},\n\t\tcpkg,\n\t)\n\n\t// import c from gc export data using a and b.\n\tpkg, err := gcimporter.Import(token.NewFileSet(), map[string]*types.Package{\n\t\tapkg: types.NewPackage(apkg, \"a\"),\n\t\tbpkg: types.NewPackage(bpkg, \"b\"),\n\t}, \"./c\", testoutdir, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check c's objects and types.\n\tvar objs []string\n\tfor _, imp := range pkg.Scope().Names() {\n\t\tobj := pkg.Scope().Lookup(imp)\n\t\ts := fmt.Sprintf(\"%s : %s\", obj.Name(), obj.Type())\n\t\ts = strings.ReplaceAll(s, testoutdir, \"testdata\")\n\t\tobjs = append(objs, s)\n\t}\n\tsort.Strings(objs)\n\n\twant := strings.Join([]string{\n\t\t\"S : struct{F int}\",\n\t\t\"T : struct{F int}\",\n\t\t\"U : testdata/a.A[string]\",\n\t\t\"V : testdata/a.A[int]\",\n\t\t\"W : testdata/b.B[string]\",\n\t\t\"X : testdata/b.B[int]\",\n\t\t\"Y : testdata/c.c[string]\",\n\t\t\"Z : testdata/c.c[int]\",\n\t\t\"c : testdata/c.c[V any]\",\n\t}, \",\")\n\tif got := strings.Join(objs, \",\"); got != want {\n\t\tt.Errorf(\"got imports %v for package c. wanted %v\", objs, want)\n\t}\n}\n\n// apkg returns the package \"a\" prefixed by (as a package) testoutdir\nfunc apkg(testoutdir string) string {\n\tapkg := testoutdir + \"/a\"\n\tif os.PathSeparator != '/' {\n\t\tapkg = strings.ReplaceAll(apkg, string(os.PathSeparator), \"/\")\n\t}\n\treturn apkg\n}\n\nfunc importPkg(t *testing.T, path, srcDir string) *types.Package {\n\tpkg, err := gcimporter.Import(token.NewFileSet(), make(map[string]*types.Package), path, srcDir, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn pkg\n}\n\nfunc compileAndImportPkg(t *testing.T, name string) *types.Package {\n\ttmpdir := mktmpdir(t)\n\tdefer os.RemoveAll(tmpdir)\n\tcompile(t, \"testdata\", name+\".go\", filepath.Join(tmpdir, \"testdata\"), nil)\n\treturn importPkg(t, \"./testdata/\"+name, tmpdir)\n}\n\nfunc lookupObj(t *testing.T, scope *types.Scope, name string) types.Object {\n\tif obj := scope.Lookup(name); obj != nil {\n\t\treturn obj\n\t}\n\tt.Fatalf(\"%s not found\", name)\n\treturn nil\n}\n\n// skipWindows skips the test on windows.\n//\n// On windows, we have to set the -D option for the compiler to avoid having a drive\n// letter and an illegal ':' in the import path - just skip it (see also issue #3483).\nfunc skipWindows(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"avoid dealing with relative paths/drive letters on windows\")\n\t}\n}\n\ntype importMap map[string]*types.Package\n\nfunc (m importMap) Import(path string) (*types.Package, error) { return m[path], nil }\n\nfunc TestIssue69912(t *testing.T) {\n\tfset := token.NewFileSet()\n\n\tcheck := func(pkgname, src string, imports importMap) (*types.Package, error) {\n\t\tf, err := goparser.ParseFile(fset, \"a.go\", src, 0)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tconfig := &types.Config{\n\t\t\tImporter: imports,\n\t\t}\n\t\treturn config.Check(pkgname, fset, []*ast.File{f}, nil)\n\t}\n\n\tconst libSrc = `package lib\n\ntype T int\n`\n\n\tlib, err := check(\"lib\", libSrc, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"Checking lib: %v\", err)\n\t}\n\n\t// Export it.\n\tvar out bytes.Buffer\n\tif err := gcimporter.IExportData(&out, fset, lib); err != nil {\n\t\tt.Fatalf(\"export: %v\", err) // any failure to export is a bug\n\t}\n\n\t// Re-import it.\n\timports := make(map[string]*types.Package)\n\t_, lib2, err := gcimporter.IImportData(fset, imports, out.Bytes(), \"lib\")\n\tif err != nil {\n\t\tt.Fatalf(\"import: %v\", err) // any failure of export+import is a bug.\n\t}\n\n\t// Use the resulting package concurrently, via dot-imports.\n\n\tconst pSrc = `package p\n\nimport . \"lib\"\n\ntype S struct {\n\tf T\n}\n`\n\timporter := importMap{\n\t\t\"lib\": lib2,\n\t}\n\tvar wg sync.WaitGroup\n\tfor range 10 {\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\t_, err := check(\"p\", pSrc, importer)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"check failed: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\twg.Wait()\n}\n"
  },
  {
    "path": "internal/gcimporter/iexport.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Indexed package export.\n//\n// The indexed export data format is an evolution of the previous\n// binary export data format. Its chief contribution is introducing an\n// index table, which allows efficient random access of individual\n// declarations and inline function bodies. In turn, this allows\n// avoiding unnecessary work for compilation units that import large\n// packages.\n//\n//\n// The top-level data format is structured as:\n//\n//     Header struct {\n//         Tag        byte   // 'i'\n//         Version    uvarint\n//         StringSize uvarint\n//         DataSize   uvarint\n//     }\n//\n//     Strings [StringSize]byte\n//     Data    [DataSize]byte\n//\n//     MainIndex []struct{\n//         PkgPath   stringOff\n//         PkgName   stringOff\n//         PkgHeight uvarint\n//\n//         Decls []struct{\n//             Name   stringOff\n//             Offset declOff\n//         }\n//     }\n//\n//     Fingerprint [8]byte\n//\n// uvarint means a uint64 written out using uvarint encoding.\n//\n// []T means a uvarint followed by that many T objects. In other\n// words:\n//\n//     Len   uvarint\n//     Elems [Len]T\n//\n// stringOff means a uvarint that indicates an offset within the\n// Strings section. At that offset is another uvarint, followed by\n// that many bytes, which form the string value.\n//\n// declOff means a uvarint that indicates an offset within the Data\n// section where the associated declaration can be found.\n//\n//\n// There are five kinds of declarations, distinguished by their first\n// byte:\n//\n//     type Var struct {\n//         Tag  byte // 'V'\n//         Pos  Pos\n//         Type typeOff\n//     }\n//\n//     type Func struct {\n//         Tag       byte // 'F' or 'G'\n//         Pos       Pos\n//         TypeParams []typeOff  // only present if Tag == 'G'\n//         Signature Signature\n//     }\n//\n//     type Const struct {\n//         Tag   byte // 'C'\n//         Pos   Pos\n//         Value Value\n//     }\n//\n//     type Type struct {\n//         Tag        byte // 'T' or 'U'\n//         Pos        Pos\n//         TypeParams []typeOff  // only present if Tag == 'U'\n//         Underlying typeOff\n//\n//         Methods []struct{  // omitted if Underlying is an interface type\n//             Pos       Pos\n//             Name      stringOff\n//             Recv      Param\n//             Signature Signature\n//         }\n//     }\n//\n//     type Alias struct {\n//         Tag  byte // 'A' or 'B'\n//         Pos  Pos\n//         TypeParams []typeOff  // only present if Tag == 'B'\n//         Type typeOff\n//     }\n//\n//     // \"Automatic\" declaration of each typeparam\n//     type TypeParam struct {\n//         Tag        byte // 'P'\n//         Pos        Pos\n//         Implicit   bool\n//         Constraint typeOff\n//     }\n//\n// typeOff means a uvarint that either indicates a predeclared type,\n// or an offset into the Data section. If the uvarint is less than\n// predeclReserved, then it indicates the index into the predeclared\n// types list (see predeclared in bexport.go for order). Otherwise,\n// subtracting predeclReserved yields the offset of a type descriptor.\n//\n// Value means a type, kind, and type-specific value. See\n// (*exportWriter).value for details.\n//\n//\n// There are twelve kinds of type descriptors, distinguished by an itag:\n//\n//     type DefinedType struct {\n//         Tag     itag // definedType\n//         Name    stringOff\n//         PkgPath stringOff\n//     }\n//\n//     type PointerType struct {\n//         Tag  itag // pointerType\n//         Elem typeOff\n//     }\n//\n//     type SliceType struct {\n//         Tag  itag // sliceType\n//         Elem typeOff\n//     }\n//\n//     type ArrayType struct {\n//         Tag  itag // arrayType\n//         Len  uint64\n//         Elem typeOff\n//     }\n//\n//     type ChanType struct {\n//         Tag  itag   // chanType\n//         Dir  uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv\n//         Elem typeOff\n//     }\n//\n//     type MapType struct {\n//         Tag  itag // mapType\n//         Key  typeOff\n//         Elem typeOff\n//     }\n//\n//     type FuncType struct {\n//         Tag       itag // signatureType\n//         PkgPath   stringOff\n//         Signature Signature\n//     }\n//\n//     type StructType struct {\n//         Tag     itag // structType\n//         PkgPath stringOff\n//         Fields []struct {\n//             Pos      Pos\n//             Name     stringOff\n//             Type     typeOff\n//             Embedded bool\n//             Note     stringOff\n//         }\n//     }\n//\n//     type InterfaceType struct {\n//         Tag     itag // interfaceType\n//         PkgPath stringOff\n//         Embeddeds []struct {\n//             Pos  Pos\n//             Type typeOff\n//         }\n//         Methods []struct {\n//             Pos       Pos\n//             Name      stringOff\n//             Signature Signature\n//         }\n//     }\n//\n//     // Reference to a type param declaration\n//     type TypeParamType struct {\n//         Tag     itag // typeParamType\n//         Name    stringOff\n//         PkgPath stringOff\n//     }\n//\n//     // Instantiation of a generic type (like List[T2] or List[int])\n//     type InstanceType struct {\n//         Tag     itag // instanceType\n//         Pos     pos\n//         TypeArgs []typeOff\n//         BaseType typeOff\n//     }\n//\n//     type UnionType struct {\n//         Tag     itag // interfaceType\n//         Terms   []struct {\n//             tilde bool\n//             Type  typeOff\n//         }\n//     }\n//\n//\n//\n//     type Signature struct {\n//         Params   []Param\n//         Results  []Param\n//         Variadic bool  // omitted if Results is empty\n//     }\n//\n//     type Param struct {\n//         Pos  Pos\n//         Name stringOff\n//         Type typOff\n//     }\n//\n//\n// Pos encodes a file:line:column triple, incorporating a simple delta\n// encoding scheme within a data object. See exportWriter.pos for\n// details.\n\npackage gcimporter\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n)\n\n// IExportShallow encodes \"shallow\" export data for the specified package.\n//\n// For types, we use \"shallow\" export data. Historically, the Go\n// compiler always produced a summary of the types for a given package\n// that included types from other packages that it indirectly\n// referenced: \"deep\" export data. This had the advantage that the\n// compiler (and analogous tools such as gopls) need only load one\n// file per direct import.  However, it meant that the files tended to\n// get larger based on the level of the package in the import\n// graph. For example, higher-level packages in the kubernetes module\n// have over 1MB of \"deep\" export data, even when they have almost no\n// content of their own, merely because they mention a major type that\n// references many others. In pathological cases the export data was\n// 300x larger than the source for a package due to this quadratic\n// growth.\n//\n// \"Shallow\" export data means that the serialized types describe only\n// a single package. If those types mention types from other packages,\n// the type checker may need to request additional packages beyond\n// just the direct imports. Type information for the entire transitive\n// closure of imports is provided (lazily) by the DAG.\n//\n// No promises are made about the encoding other than that it can be decoded by\n// the same version of IIExportShallow. If you plan to save export data in the\n// file system, be sure to include a cryptographic digest of the executable in\n// the key to avoid version skew.\n//\n// If the provided reportf func is non-nil, it is used for reporting\n// bugs (e.g. recovered panics) encountered during export, enabling us\n// to obtain via telemetry the stack that would otherwise be lost by\n// merely returning an error.\nfunc IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) ([]byte, error) {\n\t// In principle this operation can only fail if out.Write fails,\n\t// but that's impossible for bytes.Buffer---and as a matter of\n\t// fact iexportCommon doesn't even check for I/O errors.\n\t// TODO(adonovan): handle I/O errors properly.\n\t// TODO(adonovan): use byte slices throughout, avoiding copying.\n\tconst bundle, shallow = false, true\n\tvar out bytes.Buffer\n\terr := iexportCommon(&out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg}, reportf)\n\treturn out.Bytes(), err\n}\n\n// IImportShallow decodes \"shallow\" types.Package data encoded by\n// [IExportShallow] in the same executable. This function cannot import data\n// from cmd/compile or gcexportdata.Write.\n//\n// The importer calls getPackages to obtain package symbols for all\n// packages mentioned in the export data, including the one being\n// decoded.\n//\n// If the provided reportf func is non-nil, it will be used for reporting bugs\n// encountered during import.\n// TODO(rfindley): remove reportf when we are confident enough in the new\n// objectpath encoding.\nfunc IImportShallow(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, path string, reportf ReportFunc) (*types.Package, error) {\n\tconst bundle = false\n\tconst shallow = true\n\tpkgs, err := iimportCommon(fset, getPackages, data, bundle, path, shallow, reportf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pkgs[0], nil\n}\n\n// ReportFunc is the type of a function used to report formatted bugs.\ntype ReportFunc = func(string, ...any)\n\n// Current bundled export format version. Increase with each format change.\n// 0: initial implementation\nconst bundleVersion = 0\n\n// IExportData writes indexed export data for pkg to out.\n//\n// If no file set is provided, position info will be missing.\n// The package path of the top-level package will not be recorded,\n// so that calls to IImportData can override with a provided package path.\nfunc IExportData(out io.Writer, fset *token.FileSet, pkg *types.Package) error {\n\tconst bundle, shallow = false, false\n\treturn iexportCommon(out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg}, nil)\n}\n\n// IExportBundle writes an indexed export bundle for pkgs to out.\nfunc IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {\n\tconst bundle, shallow = true, false\n\treturn iexportCommon(out, fset, bundle, shallow, iexportVersion, pkgs, nil)\n}\n\nfunc iexportCommon(out io.Writer, fset *token.FileSet, bundle, shallow bool, version int, pkgs []*types.Package, reportf ReportFunc) (err error) {\n\tif !debug {\n\t\tdefer func() {\n\t\t\tif e := recover(); e != nil {\n\t\t\t\t// Report the stack via telemetry (see #71067).\n\t\t\t\tif reportf != nil {\n\t\t\t\t\treportf(\"panic in exporter\")\n\t\t\t\t}\n\t\t\t\tif ierr, ok := e.(internalError); ok {\n\t\t\t\t\t// internalError usually means we exported a\n\t\t\t\t\t// bad go/types data structure: a violation\n\t\t\t\t\t// of an implicit precondition of Export.\n\t\t\t\t\terr = ierr\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Not an internal error; panic again.\n\t\t\t\tpanic(e)\n\t\t\t}\n\t\t}()\n\t}\n\n\tp := iexporter{\n\t\tfset:        fset,\n\t\tversion:     version,\n\t\tshallow:     shallow,\n\t\tallPkgs:     map[*types.Package]bool{},\n\t\tstringIndex: map[string]uint64{},\n\t\tdeclIndex:   map[types.Object]uint64{},\n\t\ttparamNames: map[types.Object]string{},\n\t\ttypIndex:    map[types.Type]uint64{},\n\t}\n\tif !bundle {\n\t\tp.localpkg = pkgs[0]\n\t}\n\n\tfor i, pt := range predeclared() {\n\t\tp.typIndex[pt] = uint64(i)\n\t}\n\tif len(p.typIndex) > predeclReserved {\n\t\tpanic(internalErrorf(\"too many predeclared types: %d > %d\", len(p.typIndex), predeclReserved))\n\t}\n\n\t// Initialize work queue with exported declarations.\n\tfor _, pkg := range pkgs {\n\t\tscope := pkg.Scope()\n\t\tfor _, name := range scope.Names() {\n\t\t\tif token.IsExported(name) {\n\t\t\t\tp.pushDecl(scope.Lookup(name))\n\t\t\t}\n\t\t}\n\n\t\tif bundle {\n\t\t\t// Ensure pkg and its imports are included in the index.\n\t\t\tp.allPkgs[pkg] = true\n\t\t\tfor _, imp := range pkg.Imports() {\n\t\t\t\tp.allPkgs[imp] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Loop until no more work.\n\tfor !p.declTodo.empty() {\n\t\tp.doDecl(p.declTodo.popHead())\n\t}\n\n\t// Produce index of offset of each file record in files.\n\tvar files intWriter\n\tvar fileOffset []uint64 // fileOffset[i] is offset in files of file encoded as i\n\tif p.shallow {\n\t\tfileOffset = make([]uint64, len(p.fileInfos))\n\t\tfor i, info := range p.fileInfos {\n\t\t\tfileOffset[i] = uint64(files.Len())\n\t\t\tp.encodeFile(&files, info.file, info.needed)\n\t\t}\n\t}\n\n\t// Append indices to data0 section.\n\tdataLen := uint64(p.data0.Len())\n\tw := p.newWriter()\n\tw.writeIndex(p.declIndex)\n\n\tif bundle {\n\t\tw.uint64(uint64(len(pkgs)))\n\t\tfor _, pkg := range pkgs {\n\t\t\tw.pkg(pkg)\n\t\t\timps := pkg.Imports()\n\t\t\tw.uint64(uint64(len(imps)))\n\t\t\tfor _, imp := range imps {\n\t\t\t\tw.pkg(imp)\n\t\t\t}\n\t\t}\n\t}\n\tw.flush()\n\n\t// Assemble header.\n\tvar hdr intWriter\n\tif bundle {\n\t\thdr.uint64(bundleVersion)\n\t}\n\thdr.uint64(uint64(p.version))\n\thdr.uint64(uint64(p.strings.Len()))\n\tif p.shallow {\n\t\thdr.uint64(uint64(files.Len()))\n\t\thdr.uint64(uint64(len(fileOffset)))\n\t\tfor _, offset := range fileOffset {\n\t\t\thdr.uint64(offset)\n\t\t}\n\t}\n\thdr.uint64(dataLen)\n\n\t// Flush output.\n\tio.Copy(out, &hdr)\n\tio.Copy(out, &p.strings)\n\tif p.shallow {\n\t\tio.Copy(out, &files)\n\t}\n\tio.Copy(out, &p.data0)\n\n\treturn nil\n}\n\n// encodeFile writes to w a representation of the file sufficient to\n// faithfully restore position information about all needed offsets.\n// Mutates the needed array.\nfunc (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) {\n\t_ = needed[0] // precondition: needed is non-empty\n\n\tw.uint64(p.stringOff(file.Name()))\n\n\tsize := uint64(file.Size())\n\tw.uint64(size)\n\n\t// Sort the set of needed offsets. Duplicates are harmless.\n\tslices.Sort(needed)\n\n\tlines := file.Lines() // byte offset of each line start\n\tw.uint64(uint64(len(lines)))\n\n\t// Rather than record the entire array of line start offsets,\n\t// we save only a sparse list of (index, offset) pairs for\n\t// the start of each line that contains a needed position.\n\tvar sparse [][2]int // (index, offset) pairs\nouter:\n\tfor i, lineStart := range lines {\n\t\tlineEnd := size\n\t\tif i < len(lines)-1 {\n\t\t\tlineEnd = uint64(lines[i+1])\n\t\t}\n\t\t// Does this line contains a needed offset?\n\t\tif needed[0] < lineEnd {\n\t\t\tsparse = append(sparse, [2]int{i, lineStart})\n\t\t\tfor needed[0] < lineEnd {\n\t\t\t\tneeded = needed[1:]\n\t\t\t\tif len(needed) == 0 {\n\t\t\t\t\tbreak outer\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Delta-encode the columns.\n\tw.uint64(uint64(len(sparse)))\n\tvar prev [2]int\n\tfor _, pair := range sparse {\n\t\tw.uint64(uint64(pair[0] - prev[0]))\n\t\tw.uint64(uint64(pair[1] - prev[1]))\n\t\tprev = pair\n\t}\n}\n\n// writeIndex writes out an object index. mainIndex indicates whether\n// we're writing out the main index, which is also read by\n// non-compiler tools and includes a complete package description\n// (i.e., name and height).\nfunc (w *exportWriter) writeIndex(index map[types.Object]uint64) {\n\ttype pkgObj struct {\n\t\tobj  types.Object\n\t\tname string // qualified name; differs from obj.Name for type params\n\t}\n\t// Build a map from packages to objects from that package.\n\tpkgObjs := map[*types.Package][]pkgObj{}\n\n\t// For the main index, make sure to include every package that\n\t// we reference, even if we're not exporting (or reexporting)\n\t// any symbols from it.\n\tif w.p.localpkg != nil {\n\t\tpkgObjs[w.p.localpkg] = nil\n\t}\n\tfor pkg := range w.p.allPkgs {\n\t\tpkgObjs[pkg] = nil\n\t}\n\n\tfor obj := range index {\n\t\tname := w.p.exportName(obj)\n\t\tpkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], pkgObj{obj, name})\n\t}\n\n\tvar pkgs []*types.Package\n\tfor pkg, objs := range pkgObjs {\n\t\tpkgs = append(pkgs, pkg)\n\n\t\tsort.Slice(objs, func(i, j int) bool {\n\t\t\treturn objs[i].name < objs[j].name\n\t\t})\n\t}\n\n\tsort.Slice(pkgs, func(i, j int) bool {\n\t\treturn w.exportPath(pkgs[i]) < w.exportPath(pkgs[j])\n\t})\n\n\tw.uint64(uint64(len(pkgs)))\n\tfor _, pkg := range pkgs {\n\t\tw.string(w.exportPath(pkg))\n\t\tw.string(pkg.Name())\n\t\tw.uint64(uint64(0)) // package height is not needed for go/types\n\n\t\tobjs := pkgObjs[pkg]\n\t\tw.uint64(uint64(len(objs)))\n\t\tfor _, obj := range objs {\n\t\t\tw.string(obj.name)\n\t\t\tw.uint64(index[obj.obj])\n\t\t}\n\t}\n}\n\n// exportName returns the 'exported' name of an object. It differs from\n// obj.Name() only for type parameters (see tparamExportName for details).\nfunc (p *iexporter) exportName(obj types.Object) (res string) {\n\tif name := p.tparamNames[obj]; name != \"\" {\n\t\treturn name\n\t}\n\treturn obj.Name()\n}\n\ntype iexporter struct {\n\tfset    *token.FileSet\n\tversion int\n\n\tshallow    bool                // don't put types from other packages in the index\n\tobjEncoder *objectpath.Encoder // encodes objects from other packages in shallow mode; lazily allocated\n\tlocalpkg   *types.Package      // (nil in bundle mode)\n\n\t// allPkgs tracks all packages that have been referenced by\n\t// the export data, so we can ensure to include them in the\n\t// main index.\n\tallPkgs map[*types.Package]bool\n\n\tdeclTodo objQueue\n\n\tstrings     intWriter\n\tstringIndex map[string]uint64\n\n\t// In shallow mode, object positions are encoded as (file, offset).\n\t// Each file is recorded as a line-number table.\n\t// Only the lines of needed positions are saved faithfully.\n\tfileInfo  map[*token.File]uint64 // value is index in fileInfos\n\tfileInfos []*filePositions\n\n\tdata0       intWriter\n\tdeclIndex   map[types.Object]uint64\n\ttparamNames map[types.Object]string // typeparam->exported name\n\ttypIndex    map[types.Type]uint64\n\n\tindent int // for tracing support\n}\n\ntype filePositions struct {\n\tfile   *token.File\n\tneeded []uint64 // unordered list of needed file offsets\n}\n\nfunc (p *iexporter) trace(format string, args ...any) {\n\tif !trace {\n\t\t// Call sites should also be guarded, but having this check here allows\n\t\t// easily enabling/disabling debug trace statements.\n\t\treturn\n\t}\n\tfmt.Printf(strings.Repeat(\"..\", p.indent)+format+\"\\n\", args...)\n}\n\n// objectpathEncoder returns the lazily allocated objectpath.Encoder to use\n// when encoding objects in other packages during shallow export.\n//\n// Using a shared Encoder amortizes some of cost of objectpath search.\nfunc (p *iexporter) objectpathEncoder() *objectpath.Encoder {\n\tif p.objEncoder == nil {\n\t\tp.objEncoder = new(objectpath.Encoder)\n\t}\n\treturn p.objEncoder\n}\n\n// stringOff returns the offset of s within the string section.\n// If not already present, it's added to the end.\nfunc (p *iexporter) stringOff(s string) uint64 {\n\toff, ok := p.stringIndex[s]\n\tif !ok {\n\t\toff = uint64(p.strings.Len())\n\t\tp.stringIndex[s] = off\n\n\t\tp.strings.uint64(uint64(len(s)))\n\t\tp.strings.WriteString(s)\n\t}\n\treturn off\n}\n\n// fileIndexAndOffset returns the index of the token.File and the byte offset of pos within it.\nfunc (p *iexporter) fileIndexAndOffset(file *token.File, pos token.Pos) (uint64, uint64) {\n\tindex, ok := p.fileInfo[file]\n\tif !ok {\n\t\tindex = uint64(len(p.fileInfo))\n\t\tp.fileInfos = append(p.fileInfos, &filePositions{file: file})\n\t\tif p.fileInfo == nil {\n\t\t\tp.fileInfo = make(map[*token.File]uint64)\n\t\t}\n\t\tp.fileInfo[file] = index\n\t}\n\t// Record each needed offset.\n\tinfo := p.fileInfos[index]\n\toffset := uint64(file.Offset(pos))\n\tinfo.needed = append(info.needed, offset)\n\n\treturn index, offset\n}\n\n// pushDecl adds n to the declaration work queue, if not already present.\nfunc (p *iexporter) pushDecl(obj types.Object) {\n\t// Package unsafe is known to the compiler and predeclared.\n\t// Caller should not ask us to do export it.\n\tif obj.Pkg() == types.Unsafe {\n\t\tpanic(\"cannot export package unsafe\")\n\t}\n\n\t// Shallow export data: don't index decls from other packages.\n\tif p.shallow && obj.Pkg() != p.localpkg {\n\t\treturn\n\t}\n\n\tif _, ok := p.declIndex[obj]; ok {\n\t\treturn\n\t}\n\n\tp.declIndex[obj] = ^uint64(0) // mark obj present in work queue\n\tp.declTodo.pushTail(obj)\n}\n\n// exportWriter handles writing out individual data section chunks.\ntype exportWriter struct {\n\tp *iexporter\n\n\tdata       intWriter\n\tprevFile   string\n\tprevLine   int64\n\tprevColumn int64\n}\n\nfunc (w *exportWriter) exportPath(pkg *types.Package) string {\n\tif pkg == w.p.localpkg {\n\t\treturn \"\"\n\t}\n\treturn pkg.Path()\n}\n\nfunc (p *iexporter) doDecl(obj types.Object) {\n\tif trace {\n\t\tp.trace(\"exporting decl %v (%T)\", obj, obj)\n\t\tp.indent++\n\t\tdefer func() {\n\t\t\tp.indent--\n\t\t\tp.trace(\"=> %s\", obj)\n\t\t}()\n\t}\n\tw := p.newWriter()\n\n\tswitch obj := obj.(type) {\n\tcase *types.Var:\n\t\tw.tag(varTag)\n\t\tw.pos(obj.Pos())\n\t\tw.typ(obj.Type(), obj.Pkg())\n\n\tcase *types.Func:\n\t\tsig, _ := obj.Type().(*types.Signature)\n\t\tif sig.Recv() != nil {\n\t\t\t// We shouldn't see methods in the package scope,\n\t\t\t// but the type checker may repair \"func () F() {}\"\n\t\t\t// to \"func (Invalid) F()\" and then treat it like \"func F()\",\n\t\t\t// so allow that. See golang/go#57729.\n\t\t\tif sig.Recv().Type() != types.Typ[types.Invalid] {\n\t\t\t\tpanic(internalErrorf(\"unexpected method: %v\", sig))\n\t\t\t}\n\t\t}\n\n\t\t// Function.\n\t\tif sig.TypeParams().Len() == 0 {\n\t\t\tw.tag(funcTag)\n\t\t} else {\n\t\t\tw.tag(genericFuncTag)\n\t\t}\n\t\tw.pos(obj.Pos())\n\t\t// The tparam list of the function type is the declaration of the type\n\t\t// params. So, write out the type params right now. Then those type params\n\t\t// will be referenced via their type offset (via typOff) in all other\n\t\t// places in the signature and function where they are used.\n\t\t//\n\t\t// While importing the type parameters, tparamList computes and records\n\t\t// their export name, so that it can be later used when writing the index.\n\t\tif tparams := sig.TypeParams(); tparams.Len() > 0 {\n\t\t\tw.tparamList(obj.Name(), tparams, obj.Pkg())\n\t\t}\n\t\tw.signature(sig)\n\n\tcase *types.Const:\n\t\tw.tag(constTag)\n\t\tw.pos(obj.Pos())\n\t\tw.value(obj.Type(), obj.Val())\n\n\tcase *types.TypeName:\n\t\tt := obj.Type()\n\n\t\tif tparam, ok := types.Unalias(t).(*types.TypeParam); ok {\n\t\t\tw.tag(typeParamTag)\n\t\t\tw.pos(obj.Pos())\n\t\t\tconstraint := tparam.Constraint()\n\t\t\tif p.version >= iexportVersionGo1_18 {\n\t\t\t\timplicit := false\n\t\t\t\tif iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil {\n\t\t\t\t\timplicit = iface.IsImplicit()\n\t\t\t\t}\n\t\t\t\tw.bool(implicit)\n\t\t\t}\n\t\t\tw.typ(constraint, obj.Pkg())\n\t\t\tbreak\n\t\t}\n\n\t\tif obj.IsAlias() {\n\t\t\talias, materialized := t.(*types.Alias) // perhaps false for certain built-ins?\n\n\t\t\tvar tparams *types.TypeParamList\n\t\t\tif materialized {\n\t\t\t\ttparams = alias.TypeParams()\n\t\t\t}\n\t\t\tif tparams.Len() == 0 {\n\t\t\t\tw.tag(aliasTag)\n\t\t\t} else {\n\t\t\t\tw.tag(genericAliasTag)\n\t\t\t}\n\t\t\tw.pos(obj.Pos())\n\t\t\tif tparams.Len() > 0 {\n\t\t\t\tw.tparamList(obj.Name(), tparams, obj.Pkg())\n\t\t\t}\n\t\t\tif materialized {\n\t\t\t\t// Preserve materialized aliases,\n\t\t\t\t// even of non-exported types.\n\t\t\t\tt = alias.Rhs()\n\t\t\t}\n\t\t\tw.typ(t, obj.Pkg())\n\t\t\tbreak\n\t\t}\n\n\t\t// Defined type.\n\t\tnamed, ok := t.(*types.Named)\n\t\tif !ok {\n\t\t\tpanic(internalErrorf(\"%s is not a defined type\", t))\n\t\t}\n\n\t\tif named.TypeParams().Len() == 0 {\n\t\t\tw.tag(typeTag)\n\t\t} else {\n\t\t\tw.tag(genericTypeTag)\n\t\t}\n\t\tw.pos(obj.Pos())\n\n\t\tif named.TypeParams().Len() > 0 {\n\t\t\t// While importing the type parameters, tparamList computes and records\n\t\t\t// their export name, so that it can be later used when writing the index.\n\t\t\tw.tparamList(obj.Name(), named.TypeParams(), obj.Pkg())\n\t\t}\n\n\t\tunderlying := named.Underlying()\n\t\tw.typ(underlying, obj.Pkg())\n\n\t\tif types.IsInterface(t) {\n\t\t\tbreak\n\t\t}\n\n\t\tn := named.NumMethods()\n\t\tw.uint64(uint64(n))\n\t\tfor i := range n {\n\t\t\tm := named.Method(i)\n\t\t\tw.pos(m.Pos())\n\t\t\tw.string(m.Name())\n\t\t\tsig, _ := m.Type().(*types.Signature)\n\n\t\t\t// Receiver type parameters are type arguments of the receiver type, so\n\t\t\t// their name must be qualified before exporting recv.\n\t\t\tif rparams := sig.RecvTypeParams(); rparams.Len() > 0 {\n\t\t\t\tprefix := obj.Name() + \".\" + m.Name()\n\t\t\t\tfor rparam := range rparams.TypeParams() {\n\t\t\t\t\tname := tparamExportName(prefix, rparam)\n\t\t\t\t\tw.p.tparamNames[rparam.Obj()] = name\n\t\t\t\t}\n\t\t\t}\n\t\t\tw.param(sig.Recv())\n\t\t\tw.signature(sig)\n\t\t}\n\n\tdefault:\n\t\tpanic(internalErrorf(\"unexpected object: %v\", obj))\n\t}\n\n\tp.declIndex[obj] = w.flush()\n}\n\nfunc (w *exportWriter) tag(tag byte) {\n\tw.data.WriteByte(tag)\n}\n\nfunc (w *exportWriter) pos(pos token.Pos) {\n\tif w.p.shallow {\n\t\tw.posV2(pos)\n\t} else if w.p.version >= iexportVersionPosCol {\n\t\tw.posV1(pos)\n\t} else {\n\t\tw.posV0(pos)\n\t}\n}\n\n// posV2 encoding (used only in shallow mode) records positions as\n// (file, offset), where file is the index in the token.File table\n// (which records the file name and newline offsets) and offset is a\n// byte offset. It effectively ignores //line directives.\nfunc (w *exportWriter) posV2(pos token.Pos) {\n\tif pos == token.NoPos {\n\t\tw.uint64(0)\n\t\treturn\n\t}\n\tfile := w.p.fset.File(pos) // fset must be non-nil\n\tindex, offset := w.p.fileIndexAndOffset(file, pos)\n\tw.uint64(1 + index)\n\tw.uint64(offset)\n}\n\nfunc (w *exportWriter) posV1(pos token.Pos) {\n\tif w.p.fset == nil {\n\t\tw.int64(0)\n\t\treturn\n\t}\n\n\tp := w.p.fset.Position(pos)\n\tfile := p.Filename\n\tline := int64(p.Line)\n\tcolumn := int64(p.Column)\n\n\tdeltaColumn := (column - w.prevColumn) << 1\n\tdeltaLine := (line - w.prevLine) << 1\n\n\tif file != w.prevFile {\n\t\tdeltaLine |= 1\n\t}\n\tif deltaLine != 0 {\n\t\tdeltaColumn |= 1\n\t}\n\n\tw.int64(deltaColumn)\n\tif deltaColumn&1 != 0 {\n\t\tw.int64(deltaLine)\n\t\tif deltaLine&1 != 0 {\n\t\t\tw.string(file)\n\t\t}\n\t}\n\n\tw.prevFile = file\n\tw.prevLine = line\n\tw.prevColumn = column\n}\n\nfunc (w *exportWriter) posV0(pos token.Pos) {\n\tif w.p.fset == nil {\n\t\tw.int64(0)\n\t\treturn\n\t}\n\n\tp := w.p.fset.Position(pos)\n\tfile := p.Filename\n\tline := int64(p.Line)\n\n\t// When file is the same as the last position (common case),\n\t// we can save a few bytes by delta encoding just the line\n\t// number.\n\t//\n\t// Note: Because data objects may be read out of order (or not\n\t// at all), we can only apply delta encoding within a single\n\t// object. This is handled implicitly by tracking prevFile and\n\t// prevLine as fields of exportWriter.\n\n\tif file == w.prevFile {\n\t\tdelta := line - w.prevLine\n\t\tw.int64(delta)\n\t\tif delta == deltaNewFile {\n\t\t\tw.int64(-1)\n\t\t}\n\t} else {\n\t\tw.int64(deltaNewFile)\n\t\tw.int64(line) // line >= 0\n\t\tw.string(file)\n\t\tw.prevFile = file\n\t}\n\tw.prevLine = line\n}\n\nfunc (w *exportWriter) pkg(pkg *types.Package) {\n\tif pkg == nil {\n\t\t// [exportWriter.typ] accepts a nil pkg only for types\n\t\t// of constants, which cannot contain named objects\n\t\t// such as fields or methods and thus should never\n\t\t// reach this method (#76222).\n\t\tpanic(\"nil package\")\n\t}\n\t// Ensure any referenced packages are declared in the main index.\n\tw.p.allPkgs[pkg] = true\n\n\tw.string(w.exportPath(pkg))\n}\n\nfunc (w *exportWriter) qualifiedType(obj *types.TypeName) {\n\tname := w.p.exportName(obj)\n\n\t// Ensure any referenced declarations are written out too.\n\tw.p.pushDecl(obj)\n\tw.string(name)\n\tw.pkg(obj.Pkg())\n}\n\n// typ emits the specified type.\n//\n// Objects within the type (struct fields and interface methods) are\n// qualified by pkg. It may be nil if the type cannot contain objects,\n// such as the type of a constant.\nfunc (w *exportWriter) typ(t types.Type, pkg *types.Package) {\n\tw.data.uint64(w.p.typOff(t, pkg))\n}\n\nfunc (p *iexporter) newWriter() *exportWriter {\n\treturn &exportWriter{p: p}\n}\n\nfunc (w *exportWriter) flush() uint64 {\n\toff := uint64(w.p.data0.Len())\n\tio.Copy(&w.p.data0, &w.data)\n\treturn off\n}\n\nfunc (p *iexporter) typOff(t types.Type, pkg *types.Package) uint64 {\n\toff, ok := p.typIndex[t]\n\tif !ok {\n\t\tw := p.newWriter()\n\t\tw.doTyp(t, pkg)\n\t\toff = predeclReserved + w.flush()\n\t\tp.typIndex[t] = off\n\t}\n\treturn off\n}\n\nfunc (w *exportWriter) startType(k itag) {\n\tw.data.uint64(uint64(k))\n}\n\n// doTyp is the implementation of [exportWriter.typ].\nfunc (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {\n\tif trace {\n\t\tw.p.trace(\"exporting type %s (%T)\", t, t)\n\t\tw.p.indent++\n\t\tdefer func() {\n\t\t\tw.p.indent--\n\t\t\tw.p.trace(\"=> %s\", t)\n\t\t}()\n\t}\n\tswitch t := t.(type) {\n\tcase *types.Alias:\n\t\tif targs := t.TypeArgs(); targs.Len() > 0 {\n\t\t\tw.startType(instanceType)\n\t\t\tw.pos(t.Obj().Pos())\n\t\t\tw.typeList(targs, pkg)\n\t\t\tw.typ(t.Origin(), pkg)\n\t\t\treturn\n\t\t}\n\t\tw.startType(aliasType)\n\t\tw.qualifiedType(t.Obj())\n\n\tcase *types.Named:\n\t\tif targs := t.TypeArgs(); targs.Len() > 0 {\n\t\t\tw.startType(instanceType)\n\t\t\t// TODO(rfindley): investigate if this position is correct, and if it\n\t\t\t// matters.\n\t\t\tw.pos(t.Obj().Pos())\n\t\t\tw.typeList(targs, pkg)\n\t\t\tw.typ(t.Origin(), pkg)\n\t\t\treturn\n\t\t}\n\t\tw.startType(definedType)\n\t\tw.qualifiedType(t.Obj())\n\n\tcase *types.TypeParam:\n\t\tw.startType(typeParamType)\n\t\tw.qualifiedType(t.Obj())\n\n\tcase *types.Pointer:\n\t\tw.startType(pointerType)\n\t\tw.typ(t.Elem(), pkg)\n\n\tcase *types.Slice:\n\t\tw.startType(sliceType)\n\t\tw.typ(t.Elem(), pkg)\n\n\tcase *types.Array:\n\t\tw.startType(arrayType)\n\t\tw.uint64(uint64(t.Len()))\n\t\tw.typ(t.Elem(), pkg)\n\n\tcase *types.Chan:\n\t\tw.startType(chanType)\n\t\t// 1 RecvOnly; 2 SendOnly; 3 SendRecv\n\t\tvar dir uint64\n\t\tswitch t.Dir() {\n\t\tcase types.RecvOnly:\n\t\t\tdir = 1\n\t\tcase types.SendOnly:\n\t\t\tdir = 2\n\t\tcase types.SendRecv:\n\t\t\tdir = 3\n\t\t}\n\t\tw.uint64(dir)\n\t\tw.typ(t.Elem(), pkg)\n\n\tcase *types.Map:\n\t\tw.startType(mapType)\n\t\tw.typ(t.Key(), pkg)\n\t\tw.typ(t.Elem(), pkg)\n\n\tcase *types.Signature:\n\t\tw.startType(signatureType)\n\t\tw.pkg(pkg) // qualifies param/result vars\n\t\tw.signature(t)\n\n\tcase *types.Struct:\n\t\tw.startType(structType)\n\t\tn := t.NumFields()\n\t\t// Even for struct{} we must emit some qualifying package, because that's\n\t\t// what the compiler does, and thus that's what the importer expects.\n\t\tfieldPkg := pkg\n\t\tif n > 0 {\n\t\t\tfieldPkg = t.Field(0).Pkg()\n\t\t}\n\t\tif fieldPkg == nil {\n\t\t\t// TODO(rfindley): improve this very hacky logic.\n\t\t\t//\n\t\t\t// The importer expects a package to be set for all struct types, even\n\t\t\t// those with no fields. A better encoding might be to set NumFields\n\t\t\t// before pkg. setPkg panics with a nil package, which may be possible\n\t\t\t// to reach with invalid packages (and perhaps valid packages, too?), so\n\t\t\t// (arbitrarily) set the localpkg if available.\n\t\t\t//\n\t\t\t// Alternatively, we may be able to simply guarantee that pkg != nil, by\n\t\t\t// reconsidering the encoding of constant values.\n\t\t\tif w.p.shallow {\n\t\t\t\tfieldPkg = w.p.localpkg\n\t\t\t} else {\n\t\t\t\tpanic(internalErrorf(\"no package to set for empty struct\"))\n\t\t\t}\n\t\t}\n\t\tw.pkg(fieldPkg)\n\t\tw.uint64(uint64(n))\n\n\t\tfor i := range n {\n\t\t\tf := t.Field(i)\n\t\t\tif w.p.shallow {\n\t\t\t\tw.objectPath(f)\n\t\t\t}\n\t\t\tw.pos(f.Pos())\n\t\t\tw.string(f.Name()) // unexported fields implicitly qualified by prior setPkg\n\t\t\tw.typ(f.Type(), fieldPkg)\n\t\t\tw.bool(f.Anonymous())\n\t\t\tw.string(t.Tag(i)) // note (or tag)\n\t\t}\n\n\tcase *types.Interface:\n\t\tw.startType(interfaceType)\n\t\tw.pkg(pkg) // qualifies unexported method funcs\n\n\t\tn := t.NumEmbeddeds()\n\t\tw.uint64(uint64(n))\n\t\tfor i := 0; i < n; i++ {\n\t\t\tft := t.EmbeddedType(i)\n\t\t\tif named, _ := types.Unalias(ft).(*types.Named); named != nil {\n\t\t\t\tw.pos(named.Obj().Pos())\n\t\t\t} else {\n\t\t\t\t// e.g. ~int\n\t\t\t\tw.pos(token.NoPos)\n\t\t\t}\n\t\t\tw.typ(ft, pkg)\n\t\t}\n\n\t\t// See comment for struct fields. In shallow mode we change the encoding\n\t\t// for interface methods that are promoted from other packages.\n\n\t\tn = t.NumExplicitMethods()\n\t\tw.uint64(uint64(n))\n\t\tfor i := 0; i < n; i++ {\n\t\t\tm := t.ExplicitMethod(i)\n\t\t\tif w.p.shallow {\n\t\t\t\tw.objectPath(m)\n\t\t\t}\n\t\t\tw.pos(m.Pos())\n\t\t\tw.string(m.Name())\n\t\t\tsig, _ := m.Type().(*types.Signature)\n\t\t\tw.signature(sig)\n\t\t}\n\n\tcase *types.Union:\n\t\tw.startType(unionType)\n\t\tnt := t.Len()\n\t\tw.uint64(uint64(nt))\n\t\tfor i := range nt {\n\t\t\tterm := t.Term(i)\n\t\t\tw.bool(term.Tilde())\n\t\t\tw.typ(term.Type(), pkg)\n\t\t}\n\n\tdefault:\n\t\tpanic(internalErrorf(\"unexpected type: %v, %v\", t, reflect.TypeOf(t)))\n\t}\n}\n\n// objectPath writes the package and objectPath to use to look up obj in a\n// different package, when encoding in \"shallow\" mode.\n//\n// When doing a shallow import, the importer creates only the local package,\n// and requests package symbols for dependencies from the client.\n// However, certain types defined in the local package may hold objects defined\n// (perhaps deeply) within another package.\n//\n// For example, consider the following:\n//\n//\tpackage a\n//\tfunc F() chan * map[string] struct { X int }\n//\n//\tpackage b\n//\timport \"a\"\n//\tvar B = a.F()\n//\n// In this example, the type of b.B holds fields defined in package a.\n// In order to have the correct canonical objects for the field defined in the\n// type of B, they are encoded as objectPaths and later looked up in the\n// importer. The same problem applies to interface methods.\nfunc (w *exportWriter) objectPath(obj types.Object) {\n\tif obj.Pkg() == nil || obj.Pkg() == w.p.localpkg {\n\t\t// obj.Pkg() may be nil for the builtin error.Error.\n\t\t// In this case, or if obj is declared in the local package, no need to\n\t\t// encode.\n\t\tw.string(\"\")\n\t\treturn\n\t}\n\tobjectPath, err := w.p.objectpathEncoder().For(obj)\n\tif err != nil {\n\t\t// Fall back to the empty string, which will cause the importer to create a\n\t\t// new object, which matches earlier behavior. Creating a new object is\n\t\t// sufficient for many purposes (such as type checking), but causes certain\n\t\t// references algorithms to fail (golang/go#60819). However, we didn't\n\t\t// notice this problem during months of gopls@v0.12.0 testing.\n\t\t//\n\t\t// TODO(golang/go#61674): this workaround is insufficient, as in the case\n\t\t// where the field forwarded from an instantiated type that may not appear\n\t\t// in the export data of the original package:\n\t\t//\n\t\t//  // package a\n\t\t//  type A[P any] struct{ F P }\n\t\t//\n\t\t//  // package b\n\t\t//  type B a.A[int]\n\t\t//\n\t\t// We need to update references algorithms not to depend on this\n\t\t// de-duplication, at which point we may want to simply remove the\n\t\t// workaround here.\n\t\tw.string(\"\")\n\t\treturn\n\t}\n\tw.string(string(objectPath))\n\tw.pkg(obj.Pkg())\n}\n\nfunc (w *exportWriter) signature(sig *types.Signature) {\n\tw.paramList(sig.Params())\n\tw.paramList(sig.Results())\n\tif sig.Params().Len() > 0 {\n\t\tw.bool(sig.Variadic())\n\t}\n}\n\nfunc (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) {\n\tw.uint64(uint64(ts.Len()))\n\tfor t := range ts.Types() {\n\t\tw.typ(t, pkg)\n\t}\n}\n\nfunc (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) {\n\tll := uint64(list.Len())\n\tw.uint64(ll)\n\tfor tparam := range list.TypeParams() {\n\t\t// Set the type parameter exportName before exporting its type.\n\t\texportName := tparamExportName(prefix, tparam)\n\t\tw.p.tparamNames[tparam.Obj()] = exportName\n\t\tw.typ(tparam, pkg)\n\t}\n}\n\nconst blankMarker = \"$\"\n\n// tparamExportName returns the 'exported' name of a type parameter, which\n// differs from its actual object name: it is prefixed with a qualifier, and\n// blank type parameter names are disambiguated by their index in the type\n// parameter list.\nfunc tparamExportName(prefix string, tparam *types.TypeParam) string {\n\tassert(prefix != \"\")\n\tname := tparam.Obj().Name()\n\tif name == \"_\" {\n\t\tname = blankMarker + strconv.Itoa(tparam.Index())\n\t}\n\treturn prefix + \".\" + name\n}\n\n// tparamName returns the real name of a type parameter, after stripping its\n// qualifying prefix and reverting blank-name encoding. See tparamExportName\n// for details.\nfunc tparamName(exportName string) string {\n\t// Remove the \"path\" from the type param name that makes it unique.\n\tix := strings.LastIndex(exportName, \".\")\n\tif ix < 0 {\n\t\terrorf(\"malformed type parameter export name %s: missing prefix\", exportName)\n\t}\n\tname := exportName[ix+1:]\n\tif strings.HasPrefix(name, blankMarker) {\n\t\treturn \"_\"\n\t}\n\treturn name\n}\n\nfunc (w *exportWriter) paramList(tup *types.Tuple) {\n\tn := tup.Len()\n\tw.uint64(uint64(n))\n\tfor i := range n {\n\t\tw.param(tup.At(i))\n\t}\n}\n\nfunc (w *exportWriter) param(obj types.Object) {\n\tw.pos(obj.Pos())\n\tw.localIdent(obj)\n\tw.typ(obj.Type(), obj.Pkg())\n}\n\nfunc (w *exportWriter) value(typ types.Type, v constant.Value) {\n\tw.typ(typ, nil)\n\tif w.p.version >= iexportVersionGo1_18 {\n\t\tw.int64(int64(v.Kind()))\n\t}\n\n\tif v.Kind() == constant.Unknown {\n\t\t// golang/go#60605: treat unknown constant values as if they have invalid type\n\t\t//\n\t\t// This loses some fidelity over the package type-checked from source, but that\n\t\t// is acceptable.\n\t\t//\n\t\t// TODO(rfindley): we should switch on the recorded constant kind rather\n\t\t// than the constant type\n\t\treturn\n\t}\n\n\tswitch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {\n\tcase types.IsBoolean:\n\t\tw.bool(constant.BoolVal(v))\n\tcase types.IsInteger:\n\t\tvar i big.Int\n\t\tif i64, exact := constant.Int64Val(v); exact {\n\t\t\ti.SetInt64(i64)\n\t\t} else if ui64, exact := constant.Uint64Val(v); exact {\n\t\t\ti.SetUint64(ui64)\n\t\t} else {\n\t\t\ti.SetString(v.ExactString(), 10)\n\t\t}\n\t\tw.mpint(&i, typ)\n\tcase types.IsFloat:\n\t\tf := constantToFloat(v)\n\t\tw.mpfloat(f, typ)\n\tcase types.IsComplex:\n\t\tw.mpfloat(constantToFloat(constant.Real(v)), typ)\n\t\tw.mpfloat(constantToFloat(constant.Imag(v)), typ)\n\tcase types.IsString:\n\t\tw.string(constant.StringVal(v))\n\tdefault:\n\t\tif b.Kind() == types.Invalid {\n\t\t\t// package contains type errors\n\t\t\tbreak\n\t\t}\n\t\tpanic(internalErrorf(\"unexpected type %v (%v)\", typ, typ.Underlying()))\n\t}\n}\n\n// constantToFloat converts a constant.Value with kind constant.Float to a\n// big.Float.\nfunc constantToFloat(x constant.Value) *big.Float {\n\tx = constant.ToFloat(x)\n\t// Use the same floating-point precision (512) as cmd/compile\n\t// (see Mpprec in cmd/compile/internal/gc/mpfloat.go).\n\tconst mpprec = 512\n\tvar f big.Float\n\tf.SetPrec(mpprec)\n\tif v, exact := constant.Float64Val(x); exact {\n\t\t// float64\n\t\tf.SetFloat64(v)\n\t} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {\n\t\t// TODO(gri): add big.Rat accessor to constant.Value.\n\t\tn := valueToRat(num)\n\t\td := valueToRat(denom)\n\t\tf.SetRat(n.Quo(n, d))\n\t} else {\n\t\t// Value too large to represent as a fraction => inaccessible.\n\t\t// TODO(gri): add big.Float accessor to constant.Value.\n\t\t_, ok := f.SetString(x.ExactString())\n\t\tassert(ok)\n\t}\n\treturn &f\n}\n\nfunc valueToRat(x constant.Value) *big.Rat {\n\t// Convert little-endian to big-endian.\n\t// I can't believe this is necessary.\n\tbytes := constant.Bytes(x)\n\tfor i := 0; i < len(bytes)/2; i++ {\n\t\tbytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]\n\t}\n\treturn new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))\n}\n\n// mpint exports a multi-precision integer.\n//\n// For unsigned types, small values are written out as a single\n// byte. Larger values are written out as a length-prefixed big-endian\n// byte string, where the length prefix is encoded as its complement.\n// For example, bytes 0, 1, and 2 directly represent the integer\n// values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,\n// 2-, and 3-byte big-endian string follow.\n//\n// Encoding for signed types use the same general approach as for\n// unsigned types, except small values use zig-zag encoding and the\n// bottom bit of length prefix byte for large values is reserved as a\n// sign bit.\n//\n// The exact boundary between small and large encodings varies\n// according to the maximum number of bytes needed to encode a value\n// of type typ. As a special case, 8-bit types are always encoded as a\n// single byte.\n//\n// TODO(mdempsky): Is this level of complexity really worthwhile?\nfunc (w *exportWriter) mpint(x *big.Int, typ types.Type) {\n\tbasic, ok := typ.Underlying().(*types.Basic)\n\tif !ok {\n\t\tpanic(internalErrorf(\"unexpected type %v (%T)\", typ.Underlying(), typ.Underlying()))\n\t}\n\n\tsigned, maxBytes := intSize(basic)\n\n\tnegative := x.Sign() < 0\n\tif !signed && negative {\n\t\tpanic(internalErrorf(\"negative unsigned integer; type %v, value %v\", typ, x))\n\t}\n\n\tb := x.Bytes()\n\tif len(b) > 0 && b[0] == 0 {\n\t\tpanic(internalErrorf(\"leading zeros\"))\n\t}\n\tif uint(len(b)) > maxBytes {\n\t\tpanic(internalErrorf(\"bad mpint length: %d > %d (type %v, value %v)\", len(b), maxBytes, typ, x))\n\t}\n\n\tmaxSmall := 256 - maxBytes\n\tif signed {\n\t\tmaxSmall = 256 - 2*maxBytes\n\t}\n\tif maxBytes == 1 {\n\t\tmaxSmall = 256\n\t}\n\n\t// Check if x can use small value encoding.\n\tif len(b) <= 1 {\n\t\tvar ux uint\n\t\tif len(b) == 1 {\n\t\t\tux = uint(b[0])\n\t\t}\n\t\tif signed {\n\t\t\tux <<= 1\n\t\t\tif negative {\n\t\t\t\tux--\n\t\t\t}\n\t\t}\n\t\tif ux < maxSmall {\n\t\t\tw.data.WriteByte(byte(ux))\n\t\t\treturn\n\t\t}\n\t}\n\n\tn := 256 - uint(len(b))\n\tif signed {\n\t\tn = 256 - 2*uint(len(b))\n\t\tif negative {\n\t\t\tn |= 1\n\t\t}\n\t}\n\tif n < maxSmall || n >= 256 {\n\t\tpanic(internalErrorf(\"encoding mistake: %d, %v, %v => %d\", len(b), signed, negative, n))\n\t}\n\n\tw.data.WriteByte(byte(n))\n\tw.data.Write(b)\n}\n\n// mpfloat exports a multi-precision floating point number.\n//\n// The number's value is decomposed into mantissa × 2**exponent, where\n// mantissa is an integer. The value is written out as mantissa (as a\n// multi-precision integer) and then the exponent, except exponent is\n// omitted if mantissa is zero.\nfunc (w *exportWriter) mpfloat(f *big.Float, typ types.Type) {\n\tif f.IsInf() {\n\t\tpanic(\"infinite constant\")\n\t}\n\n\t// Break into f = mant × 2**exp, with 0.5 <= mant < 1.\n\tvar mant big.Float\n\texp := int64(f.MantExp(&mant))\n\n\t// Scale so that mant is an integer.\n\tprec := mant.MinPrec()\n\tmant.SetMantExp(&mant, int(prec))\n\texp -= int64(prec)\n\n\tmanti, acc := mant.Int(nil)\n\tif acc != big.Exact {\n\t\tpanic(internalErrorf(\"mantissa scaling failed for %f (%s)\", f, acc))\n\t}\n\tw.mpint(manti, typ)\n\tif manti.Sign() != 0 {\n\t\tw.int64(exp)\n\t}\n}\n\nfunc (w *exportWriter) bool(b bool) bool {\n\tvar x uint64\n\tif b {\n\t\tx = 1\n\t}\n\tw.uint64(x)\n\treturn b\n}\n\nfunc (w *exportWriter) int64(x int64)   { w.data.int64(x) }\nfunc (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }\nfunc (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }\n\nfunc (w *exportWriter) localIdent(obj types.Object) {\n\t// Anonymous parameters.\n\tif obj == nil {\n\t\tw.string(\"\")\n\t\treturn\n\t}\n\n\tname := obj.Name()\n\tif name == \"_\" {\n\t\tw.string(\"_\")\n\t\treturn\n\t}\n\n\tw.string(name)\n}\n\ntype intWriter struct {\n\tbytes.Buffer\n}\n\nfunc (w *intWriter) int64(x int64) {\n\tvar buf [binary.MaxVarintLen64]byte\n\tn := binary.PutVarint(buf[:], x)\n\tw.Write(buf[:n])\n}\n\nfunc (w *intWriter) uint64(x uint64) {\n\tvar buf [binary.MaxVarintLen64]byte\n\tn := binary.PutUvarint(buf[:], x)\n\tw.Write(buf[:n])\n}\n\nfunc assert(cond bool) {\n\tif !cond {\n\t\tpanic(\"internal error: assertion failed\")\n\t}\n}\n\n// The below is copied from go/src/cmd/compile/internal/gc/syntax.go.\n\n// objQueue is a FIFO queue of types.Object. The zero value of objQueue is\n// a ready-to-use empty queue.\ntype objQueue struct {\n\tring       []types.Object\n\thead, tail int\n}\n\n// empty returns true if q contains no Nodes.\nfunc (q *objQueue) empty() bool {\n\treturn q.head == q.tail\n}\n\n// pushTail appends n to the tail of the queue.\nfunc (q *objQueue) pushTail(obj types.Object) {\n\tif len(q.ring) == 0 {\n\t\tq.ring = make([]types.Object, 16)\n\t} else if q.head+len(q.ring) == q.tail {\n\t\t// Grow the ring.\n\t\tnring := make([]types.Object, len(q.ring)*2)\n\t\t// Copy the old elements.\n\t\tpart := q.ring[q.head%len(q.ring):]\n\t\tif q.tail-q.head <= len(part) {\n\t\t\tpart = part[:q.tail-q.head]\n\t\t\tcopy(nring, part)\n\t\t} else {\n\t\t\tpos := copy(nring, part)\n\t\t\tcopy(nring[pos:], q.ring[:q.tail%len(q.ring)])\n\t\t}\n\t\tq.ring, q.head, q.tail = nring, 0, q.tail-q.head\n\t}\n\n\tq.ring[q.tail%len(q.ring)] = obj\n\tq.tail++\n}\n\n// popHead pops a node from the head of the queue. It panics if q is empty.\nfunc (q *objQueue) popHead() types.Object {\n\tif q.empty() {\n\t\tpanic(\"dequeue empty\")\n\t}\n\tobj := q.ring[q.head%len(q.ring)]\n\tq.head++\n\treturn obj\n}\n\n// internalError represents an error generated inside this package.\ntype internalError string\n\nfunc (e internalError) Error() string { return \"gcimporter: \" + string(e) }\n\n// TODO(adonovan): make this call panic, so that it's symmetric with errorf.\n// Otherwise it's easy to forget to do anything with the error.\n//\n// TODO(adonovan): also, consider switching the names \"errorf\" and\n// \"internalErrorf\" as the former is used for bugs, whose cause is\n// internal inconsistency, whereas the latter is used for ordinary\n// situations like bad input, whose cause is external.\nfunc internalErrorf(format string, args ...any) error {\n\treturn internalError(fmt.Sprintf(format, args...))\n}\n"
  },
  {
    "path": "internal/gcimporter/iexport_common_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter\n\n// Temporarily expose version-related functionality so that we can test at\n// specific export data versions.\n\nvar IExportCommon = iexportCommon\n\nconst IExportVersion = iexportVersionGenerics\n"
  },
  {
    "path": "internal/gcimporter/iexport_go118_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter_test\n\n// This file defines test of generics features introduce in go1.18.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/gcimporter\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TODO(rfindley): migrate this to testdata, as has been done in the standard library.\nfunc TestGenericExport(t *testing.T) {\n\tconst src = `\npackage generic\n\ntype Any any\n\ntype T[A, B any] struct { Left A; Right B }\n\nfunc (T[P, Q]) m() {}\n\nvar X T[int, string] = T[int, string]{1, \"hi\"}\n\nfunc ToInt[P interface{ ~int }](p P) int { return int(p) }\n\nvar IntID = ToInt[int]\n\ntype G[C comparable] int\n\nfunc ImplicitFunc[T ~int]() {}\n\ntype ImplicitType[T ~int] int\n\n// Exercise constant import/export\nconst C1 = 42\nconst C2 int = 42\nconst C3 float64 = 42\n\ntype Constraint[T any] interface {\n       m(T)\n}\n\n// TODO(rfindley): revert to multiple blanks once the restriction on multiple\n// blanks is removed from the type checker.\n// type Blanks[_ any, _ Constraint[int]] int\n// func (Blanks[_, _]) m() {}\ntype Blanks[_ any] int\nfunc (Blanks[_]) m() {}\n`\n\ttestExportSrc(t, []byte(src))\n}\n\nfunc testExportSrc(t *testing.T, src []byte) {\n\t// This package only handles gc export data.\n\tif runtime.Compiler != \"gc\" {\n\t\tt.Skipf(\"gc-built packages not available (compiler = %s)\", runtime.Compiler)\n\t}\n\ttestenv.NeedsGoBuild(t)\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"g.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tconf := types.Config{\n\t\tImporter: importer.Default(),\n\t}\n\tpkg, err := conf.Check(\"\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// export\n\tversion := gcimporter.IExportVersion\n\tdata, err := iexport(fset, version, pkg)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttestPkgData(t, fset, version, pkg, data)\n}\n\nfunc TestIndexedImportTypeparamTests(t *testing.T) {\n\ttestenv.NeedsGoBuild(t) // to find stdlib export data in the build cache\n\ttestenv.NeedsGOROOTDir(t, \"test\")\n\n\t// Check go files in test/typeparam.\n\trootDir := filepath.Join(runtime.GOROOT(), \"test\", \"typeparam\")\n\tlist, err := os.ReadDir(rootDir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, entry := range list {\n\t\tif entry.IsDir() || !strings.HasSuffix(entry.Name(), \".go\") {\n\t\t\t// For now, only consider standalone go files.\n\t\t\tcontinue\n\t\t}\n\n\t\tt.Run(entry.Name(), func(t *testing.T) {\n\t\t\tfilename := filepath.Join(rootDir, entry.Name())\n\t\t\tsrc, err := os.ReadFile(filename)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif !bytes.HasPrefix(src, []byte(\"// run\")) && !bytes.HasPrefix(src, []byte(\"// compile\")) {\n\t\t\t\t// We're bypassing the logic of run.go here, so be conservative about\n\t\t\t\t// the files we consider in an attempt to make this test more robust to\n\t\t\t\t// changes in test/typeparams.\n\t\t\t\tt.Skipf(\"not detected as a run test\")\n\t\t\t}\n\n\t\t\ttestExportSrc(t, src)\n\t\t})\n\t}\n}\n\nfunc TestRecursiveExport_Issue51219(t *testing.T) {\n\tconst srca = `\npackage a\n\ntype Interaction[DataT InteractionDataConstraint] struct {\n}\n\ntype InteractionDataConstraint interface {\n\t[]byte |\n\t\tUserCommandInteractionData\n}\n\ntype UserCommandInteractionData struct {\n\tresolvedInteractionWithOptions\n}\n\ntype resolvedInteractionWithOptions struct {\n\tResolved Resolved\n}\n\ntype Resolved struct {\n\tUsers ResolvedData[User]\n}\n\ntype ResolvedData[T ResolvedDataConstraint] map[uint64]T\n\ntype ResolvedDataConstraint interface {\n\tUser | Message\n}\n\ntype User struct{}\n\ntype Message struct {\n\tInteraction *Interaction[[]byte]\n}\n`\n\n\tconst srcb = `\npackage b\n\nimport (\n\t\"a\"\n)\n\n// InteractionRequest is an incoming request Interaction\ntype InteractionRequest[T a.InteractionDataConstraint] struct {\n\ta.Interaction[T]\n}\n`\n\n\tconst srcp = `\npackage p\n\nimport (\n\t\"b\"\n)\n\n// ResponseWriterMock mocks corde's ResponseWriter interface\ntype ResponseWriterMock struct {\n\tx b.InteractionRequest[[]byte]\n}\n`\n\n\timporter := &testImporter{\n\t\tsrc: map[string][]byte{\n\t\t\t\"a\": []byte(srca),\n\t\t\t\"b\": []byte(srcb),\n\t\t\t\"p\": []byte(srcp),\n\t\t},\n\t\tpkgs: make(map[string]*types.Package),\n\t}\n\t_, err := importer.Import(\"p\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\n// testImporter is a helper to test chains of imports using export data.\ntype testImporter struct {\n\tsrc  map[string][]byte         // original source\n\tpkgs map[string]*types.Package // memoized imported packages\n}\n\nfunc (t *testImporter) Import(path string) (*types.Package, error) {\n\tif pkg, ok := t.pkgs[path]; ok {\n\t\treturn pkg, nil\n\t}\n\tsrc, ok := t.src[path]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unknown path %v\", path)\n\t}\n\n\t// Type-check, but don't return this package directly.\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, path+\".go\", src, 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tconf := types.Config{\n\t\tImporter: t,\n\t}\n\tpkg, err := conf.Check(path, fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Export and import to get the package imported from export data.\n\texportdata, err := iexport(fset, gcimporter.IExportVersion, pkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg.Path())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tt.pkgs[path] = pkg2\n\treturn pkg2, nil\n}\n"
  },
  {
    "path": "internal/gcimporter/iexport_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is a copy of bexport_test.go for iexport.go.\n\npackage gcimporter_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math/big\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/gcimporter\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc iexport(fset *token.FileSet, version int, pkg *types.Package) ([]byte, error) {\n\tvar buf bytes.Buffer\n\tconst bundle, shallow = false, false\n\tif err := gcimporter.IExportCommon(&buf, fset, bundle, shallow, version, []*types.Package{pkg}, nil); err != nil {\n\t\treturn nil, err\n\t}\n\treturn buf.Bytes(), nil\n}\n\nfunc TestIExportData_stdlib(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tif isRace {\n\t\tt.Skipf(\"stdlib tests take too long in race mode and flake on builders\")\n\t}\n\tif testing.Short() {\n\t\tt.Skip(\"skipping RAM hungry test in -short mode\")\n\t}\n\n\tvar errorsDir string // GOROOT/src/errors directory\n\t{\n\t\tcfg := packages.Config{\n\t\t\tMode: packages.NeedName | packages.NeedFiles,\n\t\t}\n\t\tpkgs, err := packages.Load(&cfg, \"errors\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terrorsDir = filepath.Dir(pkgs[0].GoFiles[0])\n\t}\n\n\t// Load types from syntax for all std packages.\n\t//\n\t// Append a file to package errors containing type and\n\t// value errors to ensure they are properly encoded/decoded.\n\tconst bad = `package errors\nconst UnknownValue = \"\" + 0\ntype UnknownType undefined\n`\n\tcfg := packages.Config{\n\t\tMode:    packages.LoadAllSyntax | packages.NeedDeps,\n\t\tOverlay: map[string][]byte{filepath.Join(errorsDir, \"bad.go\"): []byte(bad)},\n\t}\n\tpkgs, err := packages.Load(&cfg, \"std\") // ~800ms\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfset := pkgs[0].Fset\n\n\tversion := gcimporter.IExportVersion\n\n\t// Export and reimport each package, and check that they match.\n\tvar allPkgs []*types.Package\n\tvar errorsPkg *types.Package                             // reimported errors package\n\tpackages.Visit(pkgs, nil, func(ppkg *packages.Package) { // ~300ms\n\t\tpkg := ppkg.Types\n\t\tpath := pkg.Path()\n\t\tif path == \"unsafe\" ||\n\t\t\tstrings.HasPrefix(path, \"cmd/\") ||\n\t\t\tstrings.HasPrefix(path, \"vendor/\") {\n\t\t\treturn\n\t\t}\n\t\tallPkgs = append(allPkgs, pkg)\n\n\t\t// Export and reimport the package, and compare.\n\t\texportdata, err := iexport(fset, version, pkg)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t\treturn\n\t\t}\n\t\tpkg2 := testPkgData(t, fset, version, pkg, exportdata)\n\t\tif path == \"errors\" {\n\t\t\terrorsPkg = pkg2\n\t\t}\n\t})\n\n\t// Assert that we saw a plausible sized library.\n\tconst minStdlibPackages = 248\n\tif n := len(allPkgs); n < minStdlibPackages {\n\t\tt.Errorf(\"Loaded only %d packages, want at least %d\", n, minStdlibPackages)\n\t}\n\n\t// Check that reimported errors package has bad decls.\n\tif errorsPkg == nil {\n\t\tt.Fatalf(\"'errors' package not found\")\n\t}\n\tfor _, name := range []string{\"UnknownType\", \"UnknownValue\"} {\n\t\tobj := errorsPkg.Scope().Lookup(name)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"errors.%s not found\", name)\n\t\t}\n\t\tif typ := obj.Type().Underlying(); typ.String() != \"invalid type\" {\n\t\t\tt.Errorf(\"errors.%s has underlying type %s, want invalid type\", name, typ)\n\t\t}\n\t}\n\n\t// (Sole) test of bundle functionality (250ms).\n\tvar bundle bytes.Buffer\n\tif err := gcimporter.IExportBundle(&bundle, fset, allPkgs); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfset2 := token.NewFileSet()\n\timports := make(map[string]*types.Package)\n\tpkgs2, err := gcimporter.IImportBundle(fset2, imports, bundle.Bytes())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor i, pkg := range allPkgs {\n\t\ttestPkg(t, fset, version, pkg, fset2, pkgs2[i])\n\t}\n}\n\n// testPkgData imports a package from export data and compares it with pkg.\nfunc testPkgData(t *testing.T, fset *token.FileSet, version int, pkg *types.Package, exportdata []byte) *types.Package {\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg.Path())\n\tif err != nil {\n\t\tt.Errorf(\"IImportData(%s): %v\", pkg.Path(), err)\n\t}\n\n\ttestPkg(t, fset, version, pkg, fset2, pkg2)\n\treturn pkg2\n}\n\nfunc testPkg(t *testing.T, fset *token.FileSet, version int, pkg *types.Package, fset2 *token.FileSet, pkg2 *types.Package) {\n\tif _, err := iexport(fset2, version, pkg2); err != nil {\n\t\tt.Errorf(\"reexport %q: %v\", pkg.Path(), err)\n\t}\n\n\t// Compare the packages' corresponding members.\n\tfor _, name := range pkg.Scope().Names() {\n\t\tif !token.IsExported(name) {\n\t\t\tcontinue\n\t\t}\n\t\tobj1 := pkg.Scope().Lookup(name)\n\t\tobj2 := pkg2.Scope().Lookup(name)\n\t\tif obj2 == nil {\n\t\t\tt.Errorf(\"%s.%s not found, want %s\", pkg.Path(), name, obj1)\n\t\t\tcontinue\n\t\t}\n\n\t\tfl1 := fileLine(fset, obj1)\n\t\tfl2 := fileLine(fset2, obj2)\n\t\tif fl1 != fl2 {\n\t\t\tt.Errorf(\"%s.%s: got posn %s, want %s\",\n\t\t\t\tpkg.Path(), name, fl2, fl1)\n\t\t}\n\n\t\tif err := cmpObj(obj1, obj2); err != nil {\n\t\t\tt.Errorf(\"%s.%s: %s\\ngot:  %s\\nwant: %s\",\n\t\t\t\tpkg.Path(), name, err, obj2, obj1)\n\t\t}\n\t}\n}\n\n// TestIExportData_long tests the position of an import object declared in\n// a very long input file.  Line numbers greater than maxlines are\n// reported as line 1, not garbage or token.NoPos.\nfunc TestIExportData_long(t *testing.T) {\n\t// parse and typecheck\n\tlongFile := \"package foo\" + strings.Repeat(\"\\n\", 123456) + \"var X int\"\n\tfset1 := token.NewFileSet()\n\tf, err := parser.ParseFile(fset1, \"foo.go\", longFile, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"foo\", fset1, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// export\n\texportdata, err := iexport(fset1, gcimporter.IExportVersion, pkg)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// import\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg.Path())\n\tif err != nil {\n\t\tt.Fatalf(\"IImportData(%s): %v\", pkg.Path(), err)\n\t}\n\n\t// compare\n\tposn1 := fset1.Position(pkg.Scope().Lookup(\"X\").Pos())\n\tposn2 := fset2.Position(pkg2.Scope().Lookup(\"X\").Pos())\n\tif want := \"foo.go:1:1\"; posn2.String() != want {\n\t\tt.Errorf(\"X position = %s, want %s (orig was %s)\",\n\t\t\tposn2, want, posn1)\n\t}\n}\n\nfunc TestIExportData_typealiases(t *testing.T) {\n\t// parse and typecheck\n\tfset1 := token.NewFileSet()\n\tf, err := parser.ParseFile(fset1, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar conf types.Config\n\tpkg1, err := conf.Check(\"p\", fset1, []*ast.File{f}, nil)\n\tif err == nil {\n\t\t// foo in undeclared in src; we should see an error\n\t\tt.Fatal(\"invalid source type-checked without error\")\n\t}\n\tif pkg1 == nil {\n\t\t// despite incorrect src we should see a (partially) type-checked package\n\t\tt.Fatal(\"nil package returned\")\n\t}\n\tcheckPkg(t, pkg1, \"export\")\n\n\t// export\n\t// use a nil fileset here to confirm that it doesn't panic\n\texportdata, err := iexport(nil, gcimporter.IExportVersion, pkg1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// import\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg1.Path())\n\tif err != nil {\n\t\tt.Fatalf(\"IImportData(%s): %v\", pkg1.Path(), err)\n\t}\n\tcheckPkg(t, pkg2, \"import\")\n}\n\n// cmpObj reports how x and y differ. They are assumed to belong to different\n// universes so cannot be compared directly. It is an adapted version of\n// equalObj in bexport_test.go.\nfunc cmpObj(x, y types.Object) error {\n\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\treturn fmt.Errorf(\"%T vs %T\", x, y)\n\t}\n\txt := x.Type()\n\tyt := y.Type()\n\tswitch x := x.(type) {\n\tcase *types.Var, *types.Func:\n\t\t// ok\n\tcase *types.Const:\n\t\txval := x.Val()\n\t\tyval := y.(*types.Const).Val()\n\t\tequal := constant.Compare(xval, token.EQL, yval)\n\t\tif !equal {\n\t\t\t// try approx. comparison\n\t\t\txkind := xval.Kind()\n\t\t\tykind := yval.Kind()\n\t\t\tif xkind == constant.Complex || ykind == constant.Complex {\n\t\t\t\tequal = same(constant.Real(xval), constant.Real(yval)) &&\n\t\t\t\t\tsame(constant.Imag(xval), constant.Imag(yval))\n\t\t\t} else if xkind == constant.Float || ykind == constant.Float {\n\t\t\t\tequal = same(xval, yval)\n\t\t\t} else if xkind == constant.Unknown && ykind == constant.Unknown {\n\t\t\t\tequal = true\n\t\t\t}\n\t\t}\n\t\tif !equal {\n\t\t\treturn fmt.Errorf(\"unequal constants %s vs %s\", xval, yval)\n\t\t}\n\tcase *types.TypeName:\n\t\tif xalias, yalias := x.IsAlias(), y.(*types.TypeName).IsAlias(); xalias != yalias {\n\t\t\treturn fmt.Errorf(\"mismatching IsAlias(): %s vs %s\", x, y)\n\t\t}\n\n\t\t// equalType does not recurse into the underlying types of named types, so\n\t\t// we must pass the underlying type explicitly here. However, in doing this\n\t\t// we may skip checking the features of the named types themselves, in\n\t\t// situations where the type name is not referenced by the underlying or\n\t\t// any other top-level declarations. Therefore, we must explicitly compare\n\t\t// named types here, before passing their underlying types into equalType.\n\t\txn, _ := types.Unalias(xt).(*types.Named)\n\t\tyn, _ := types.Unalias(yt).(*types.Named)\n\t\tif (xn == nil) != (yn == nil) {\n\t\t\treturn fmt.Errorf(\"mismatching types: %T vs %T\", xt, yt)\n\t\t}\n\t\tif xn != nil {\n\t\t\tif err := cmpNamed(xn, yn); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\txt = xt.Underlying()\n\t\tyt = yt.Underlying()\n\tdefault:\n\t\treturn fmt.Errorf(\"unexpected %T\", x)\n\t}\n\treturn equalType(xt, yt)\n}\n\n// Use the same floating-point precision (512) as cmd/compile\n// (see Mpprec in cmd/compile/internal/gc/mpfloat.go).\nconst mpprec = 512\n\n// same compares non-complex numeric values and reports if they are approximately equal.\nfunc same(x, y constant.Value) bool {\n\txf := constantToFloat(x)\n\tyf := constantToFloat(y)\n\td := new(big.Float).Sub(xf, yf)\n\td.Abs(d)\n\teps := big.NewFloat(1.0 / (1 << (mpprec - 1))) // allow for 1 bit of error\n\treturn d.Cmp(eps) < 0\n}\n\n// copy of the function with the same name in iexport.go.\nfunc constantToFloat(x constant.Value) *big.Float {\n\tvar f big.Float\n\tf.SetPrec(mpprec)\n\tif v, exact := constant.Float64Val(x); exact {\n\t\t// float64\n\t\tf.SetFloat64(v)\n\t} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {\n\t\t// TODO(gri): add big.Rat accessor to constant.Value.\n\t\tn := valueToRat(num)\n\t\td := valueToRat(denom)\n\t\tf.SetRat(n.Quo(n, d))\n\t} else {\n\t\t// Value too large to represent as a fraction => inaccessible.\n\t\t// TODO(gri): add big.Float accessor to constant.Value.\n\t\t_, ok := f.SetString(x.ExactString())\n\t\tif !ok {\n\t\t\tpanic(\"should not reach here\")\n\t\t}\n\t}\n\treturn &f\n}\n\n// copy of the function with the same name in iexport.go.\nfunc valueToRat(x constant.Value) *big.Rat {\n\t// Convert little-endian to big-endian.\n\t// I can't believe this is necessary.\n\tbytes := constant.Bytes(x)\n\tfor i := 0; i < len(bytes)/2; i++ {\n\t\tbytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]\n\t}\n\treturn new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))\n}\n\n// This is a regression test for a bug in iexport of types.Struct:\n// unexported fields were losing their implicit package qualifier.\nfunc TestUnexportedStructFields(t *testing.T) {\n\tfset := token.NewFileSet()\n\texport := make(map[string][]byte)\n\n\t// process parses and type-checks a single-file\n\t// package and saves its export data.\n\tprocess := func(path, content string) {\n\t\tsyntax, err := parser.ParseFile(fset, path+\"/x.go\", content, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tpackages := make(map[string]*types.Package) // keys are package paths\n\t\tcfg := &types.Config{\n\t\t\tImporter: importerFunc(func(path string) (*types.Package, error) {\n\t\t\t\tdata, ok := export[path]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"missing export data for %s\", path)\n\t\t\t\t}\n\t\t\t\treturn gcexportdata.Read(bytes.NewReader(data), fset, packages, path)\n\t\t\t}),\n\t\t}\n\t\tpkg := types.NewPackage(path, syntax.Name.Name)\n\t\tcheck := types.NewChecker(cfg, fset, pkg, nil)\n\t\tif err := check.Files([]*ast.File{syntax}); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tvar out bytes.Buffer\n\t\tif err := gcexportdata.Write(&out, fset, pkg); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\texport[path] = out.Bytes()\n\t}\n\n\t// Historically this led to a spurious error:\n\t// \"cannot convert a.M (variable of type a.MyTime) to type time.Time\"\n\t// because the private fields of Time and MyTime were not identical.\n\tprocess(\"time\", `package time; type Time struct { x, y int }`)\n\tprocess(\"a\", `package a; import \"time\"; type MyTime time.Time; var M MyTime`)\n\tprocess(\"b\", `package b; import (\"a\"; \"time\"); var _ = time.Time(a.M)`)\n}\n\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }\n\n// TestIExportDataTypeParameterizedAliases tests IExportData\n// on both declarations and uses of type parameterized aliases.\nfunc TestIExportDataTypeParameterizedAliases(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\tskipWindows(t)\n\tif testenv.Go1Point() == 23 {\n\t\ttestenv.NeedsGoExperiment(t, \"aliastypeparams\") // testenv.Go1Point() >= 24 implies aliastypeparams=1\n\t}\n\n\t// High level steps:\n\t// * parse  and typecheck\n\t// * export the data for the importer (via IExportData),\n\t// * import the data (via either x/tools or GOROOT's gcimporter), and\n\t// * check the imported types.\n\n\tconst src = `package pkg\n\ntype A[T any] = *T\ntype B[R any, S *R] = []S\ntype C[U any] = B[U, A[U]]\n\ntype Named int\ntype Chained = C[Named] // B[Named, A[Named]] = B[Named, *Named] = []*Named\n`\n\n\t// parse and typecheck\n\tfset1 := token.NewFileSet()\n\tf, err := parser.ParseFile(fset1, \"pkg\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar conf types.Config\n\tpkg1, err := conf.Check(\"pkg\", fset1, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Read the result of IExportData through x/tools/internal/gcimporter.IImportData.\n\t// export\n\texportdata, err := iexport(fset1, gcimporter.IExportVersion, pkg1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// import\n\timports := make(map[string]*types.Package)\n\tfset2 := token.NewFileSet()\n\t_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg1.Path())\n\tif err != nil {\n\t\tt.Fatalf(\"IImportData(%s): %v\", pkg1.Path(), err)\n\t}\n\n\tpkg := pkg2\n\tfor name, want := range map[string]string{\n\t\t\"A\":       \"type pkg.A[T any] = *T\",\n\t\t\"B\":       \"type pkg.B[R any, S *R] = []S\",\n\t\t\"C\":       \"type pkg.C[U any] = pkg.B[U, pkg.A[U]]\",\n\t\t\"Named\":   \"type pkg.Named int\",\n\t\t\"Chained\": \"type pkg.Chained = pkg.C[pkg.Named]\",\n\t} {\n\t\tobj := pkg.Scope().Lookup(name)\n\t\tif obj == nil {\n\t\t\tt.Errorf(\"failed to find %q in package %s\", name, pkg)\n\t\t\tcontinue\n\t\t}\n\n\t\tgot := strings.ReplaceAll(obj.String(), pkg.Path(), \"pkg\")\n\t\tif got != want {\n\t\t\tt.Errorf(\"(%q).String()=%q. wanted %q\", name, got, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/gcimporter/iimport.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Indexed package import.\n// See iexport.go for the export data format.\n\npackage gcimporter\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"math/big\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/types/objectpath\"\n\t\"golang.org/x/tools/internal/aliases\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\ntype intReader struct {\n\t*bytes.Reader\n\tpath string\n}\n\nfunc (r *intReader) int64() int64 {\n\ti, err := binary.ReadVarint(r.Reader)\n\tif err != nil {\n\t\terrorf(\"import %q: read varint error: %v\", r.path, err)\n\t}\n\treturn i\n}\n\nfunc (r *intReader) uint64() uint64 {\n\ti, err := binary.ReadUvarint(r.Reader)\n\tif err != nil {\n\t\terrorf(\"import %q: read varint error: %v\", r.path, err)\n\t}\n\treturn i\n}\n\n// Keep this in sync with constants in iexport.go.\nconst (\n\tiexportVersionGo1_11   = 0\n\tiexportVersionPosCol   = 1\n\tiexportVersionGo1_18   = 2\n\tiexportVersionGenerics = 2\n\tiexportVersion         = iexportVersionGenerics\n\n\tiexportVersionCurrent = 2\n)\n\ntype ident struct {\n\tpkg  *types.Package\n\tname string\n}\n\nconst predeclReserved = 32\n\ntype itag uint64\n\nconst (\n\t// Types\n\tdefinedType itag = iota\n\tpointerType\n\tsliceType\n\tarrayType\n\tchanType\n\tmapType\n\tsignatureType\n\tstructType\n\tinterfaceType\n\ttypeParamType\n\tinstanceType\n\tunionType\n\taliasType\n)\n\n// Object tags\nconst (\n\tvarTag          = 'V'\n\tfuncTag         = 'F'\n\tgenericFuncTag  = 'G'\n\tconstTag        = 'C'\n\taliasTag        = 'A'\n\tgenericAliasTag = 'B'\n\ttypeParamTag    = 'P'\n\ttypeTag         = 'T'\n\tgenericTypeTag  = 'U'\n)\n\n// IImportData imports a package from the serialized package data\n// and returns 0 and a reference to the package.\n// If the export data version is not recognized or the format is otherwise\n// compromised, an error is returned.\nfunc IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {\n\tpkgs, err := iimportCommon(fset, GetPackagesFromMap(imports), data, false, path, false, nil)\n\tif err != nil {\n\t\treturn 0, nil, err\n\t}\n\treturn 0, pkgs[0], nil\n}\n\n// IImportBundle imports a set of packages from the serialized package bundle.\nfunc IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {\n\treturn iimportCommon(fset, GetPackagesFromMap(imports), data, true, \"\", false, nil)\n}\n\n// A GetPackagesFunc function obtains the non-nil symbols for a set of\n// packages, creating and recursively importing them as needed. An\n// implementation should store each package symbol is in the Pkg\n// field of the items array.\n//\n// Any error causes importing to fail. This can be used to quickly read\n// the import manifest of an export data file without fully decoding it.\ntype GetPackagesFunc = func(items []GetPackagesItem) error\n\n// A GetPackagesItem is a request from the importer for the package\n// symbol of the specified name and path.\ntype GetPackagesItem struct {\n\tName, Path string\n\tPkg        *types.Package // to be filled in by GetPackagesFunc call\n\n\t// private importer state\n\tpathOffset uint64\n\tnameIndex  map[string]uint64\n}\n\n// GetPackagesFromMap returns a GetPackagesFunc that retrieves\n// packages from the given map of package path to package.\n//\n// The returned function may mutate m: each requested package that is not\n// found is created with types.NewPackage and inserted into m.\nfunc GetPackagesFromMap(m map[string]*types.Package) GetPackagesFunc {\n\treturn func(items []GetPackagesItem) error {\n\t\tfor i, item := range items {\n\t\t\tpkg, ok := m[item.Path]\n\t\t\tif !ok {\n\t\t\t\tpkg = types.NewPackage(item.Path, item.Name)\n\t\t\t\tm[item.Path] = pkg\n\t\t\t}\n\t\t\titems[i].Pkg = pkg\n\t\t}\n\t\treturn nil\n\t}\n}\n\nfunc iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, bundle bool, path string, shallow bool, reportf ReportFunc) (pkgs []*types.Package, err error) {\n\tconst currentVersion = iexportVersionCurrent\n\tversion := int64(-1)\n\tif !debug {\n\t\tdefer func() {\n\t\t\tif e := recover(); e != nil {\n\t\t\t\tif bundle {\n\t\t\t\t\terr = fmt.Errorf(\"%v\", e)\n\t\t\t\t} else if version > currentVersion {\n\t\t\t\t\terr = fmt.Errorf(\"cannot import %q (%v), export data is newer version - update tool\", path, e)\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"internal error while importing %q (%v); please report an issue\", path, e)\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\t}\n\n\tr := &intReader{bytes.NewReader(data), path}\n\n\tif bundle {\n\t\tif v := r.uint64(); v != bundleVersion {\n\t\t\terrorf(\"unknown bundle format version %d\", v)\n\t\t}\n\t}\n\n\tversion = int64(r.uint64())\n\tswitch version {\n\tcase iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:\n\tdefault:\n\t\tif version > iexportVersionGo1_18 {\n\t\t\terrorf(\"unstable iexport format version %d, just rebuild compiler and std library\", version)\n\t\t} else {\n\t\t\terrorf(\"unknown iexport format version %d\", version)\n\t\t}\n\t}\n\n\tsLen := int64(r.uint64())\n\tvar fLen int64\n\tvar fileOffset []uint64\n\tif shallow {\n\t\t// Shallow mode uses a different position encoding.\n\t\tfLen = int64(r.uint64())\n\t\tfileOffset = make([]uint64, r.uint64())\n\t\tfor i := range fileOffset {\n\t\t\tfileOffset[i] = r.uint64()\n\t\t}\n\t}\n\tdLen := int64(r.uint64())\n\n\twhence, _ := r.Seek(0, io.SeekCurrent)\n\tstringData := data[whence : whence+sLen]\n\tfileData := data[whence+sLen : whence+sLen+fLen]\n\tdeclData := data[whence+sLen+fLen : whence+sLen+fLen+dLen]\n\tr.Seek(sLen+fLen+dLen, io.SeekCurrent)\n\n\tp := iimporter{\n\t\tversion: int(version),\n\t\tipath:   path,\n\t\tshallow: shallow,\n\t\treportf: reportf,\n\n\t\tstringData:  stringData,\n\t\tstringCache: make(map[uint64]string),\n\t\tfileOffset:  fileOffset,\n\t\tfileData:    fileData,\n\t\tfileCache:   make([]*token.File, len(fileOffset)),\n\t\tpkgCache:    make(map[uint64]*types.Package),\n\n\t\tdeclData: declData,\n\t\tpkgIndex: make(map[*types.Package]map[string]uint64),\n\t\ttypCache: make(map[uint64]types.Type),\n\t\t// Separate map for typeparams, keyed by their package and unique\n\t\t// name.\n\t\ttparamIndex: make(map[ident]types.Type),\n\n\t\tfake: fakeFileSet{\n\t\t\tfset:  fset,\n\t\t\tfiles: make(map[string]*fileInfo),\n\t\t},\n\t}\n\tdefer p.fake.setLines() // set lines for files in fset\n\n\tfor i, pt := range predeclared() {\n\t\tp.typCache[uint64(i)] = pt\n\t}\n\n\t// Gather the relevant packages from the manifest.\n\titems := make([]GetPackagesItem, r.uint64())\n\tuniquePkgPaths := make(map[string]bool)\n\tfor i := range items {\n\t\tpkgPathOff := r.uint64()\n\t\tpkgPath := p.stringAt(pkgPathOff)\n\t\tpkgName := p.stringAt(r.uint64())\n\t\t_ = r.uint64() // package height; unused by go/types\n\n\t\tif pkgPath == \"\" {\n\t\t\tpkgPath = path\n\t\t}\n\t\titems[i].Name = pkgName\n\t\titems[i].Path = pkgPath\n\t\titems[i].pathOffset = pkgPathOff\n\n\t\t// Read index for package.\n\t\tnameIndex := make(map[string]uint64)\n\t\tnSyms := r.uint64()\n\t\t// In shallow mode, only the current package (i=0) has an index.\n\t\tassert(!(shallow && i > 0 && nSyms != 0))\n\t\tfor ; nSyms > 0; nSyms-- {\n\t\t\tname := p.stringAt(r.uint64())\n\t\t\tnameIndex[name] = r.uint64()\n\t\t}\n\n\t\titems[i].nameIndex = nameIndex\n\n\t\tuniquePkgPaths[pkgPath] = true\n\t}\n\t// Debugging #63822; hypothesis: there are duplicate PkgPaths.\n\tif len(uniquePkgPaths) != len(items) {\n\t\treportf(\"found duplicate PkgPaths while reading export data manifest: %v\", items)\n\t}\n\n\t// Request packages all at once from the client,\n\t// enabling a parallel implementation.\n\tif err := getPackages(items); err != nil {\n\t\treturn nil, err // don't wrap this error\n\t}\n\n\t// Check the results and complete the index.\n\tpkgList := make([]*types.Package, len(items))\n\tfor i, item := range items {\n\t\tpkg := item.Pkg\n\t\tif pkg == nil {\n\t\t\terrorf(\"internal error: getPackages returned nil package for %q\", item.Path)\n\t\t} else if pkg.Path() != item.Path {\n\t\t\terrorf(\"internal error: getPackages returned wrong path %q, want %q\", pkg.Path(), item.Path)\n\t\t} else if pkg.Name() != item.Name {\n\t\t\terrorf(\"internal error: getPackages returned wrong name %s for package %q, want %s\", pkg.Name(), item.Path, item.Name)\n\t\t}\n\t\tp.pkgCache[item.pathOffset] = pkg\n\t\tp.pkgIndex[pkg] = item.nameIndex\n\t\tpkgList[i] = pkg\n\t}\n\n\tif bundle {\n\t\tpkgs = make([]*types.Package, r.uint64())\n\t\tfor i := range pkgs {\n\t\t\tpkg := p.pkgAt(r.uint64())\n\t\t\timps := make([]*types.Package, r.uint64())\n\t\t\tfor j := range imps {\n\t\t\t\timps[j] = p.pkgAt(r.uint64())\n\t\t\t}\n\t\t\tpkg.SetImports(imps)\n\t\t\tpkgs[i] = pkg\n\t\t}\n\t} else {\n\t\tif len(pkgList) == 0 {\n\t\t\terrorf(\"no packages found for %s\", path)\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t\tpkgs = pkgList[:1]\n\n\t\t// record all referenced packages as imports\n\t\tlist := slices.Clone(pkgList[1:])\n\t\tsort.Sort(byPath(list))\n\t\tpkgs[0].SetImports(list)\n\t}\n\n\tfor _, pkg := range pkgs {\n\t\tif pkg.Complete() {\n\t\t\tcontinue\n\t\t}\n\n\t\tnames := make([]string, 0, len(p.pkgIndex[pkg]))\n\t\tfor name := range p.pkgIndex[pkg] {\n\t\t\tnames = append(names, name)\n\t\t}\n\t\tsort.Strings(names)\n\t\tfor _, name := range names {\n\t\t\tp.doDecl(pkg, name)\n\t\t}\n\n\t\t// package was imported completely and without errors\n\t\tpkg.MarkComplete()\n\t}\n\n\t// SetConstraint can't be called if the constraint type is not yet complete.\n\t// When type params are created in the typeParamTag case of (*importReader).obj(),\n\t// the associated constraint type may not be complete due to recursion.\n\t// Therefore, we defer calling SetConstraint there, and call it here instead\n\t// after all types are complete.\n\tfor _, d := range p.later {\n\t\td.t.SetConstraint(d.constraint)\n\t}\n\n\tfor _, typ := range p.interfaceList {\n\t\ttyp.Complete()\n\t}\n\n\t// Workaround for golang/go#61561. See the doc for instanceList for details.\n\tfor _, typ := range p.instanceList {\n\t\tif iface, _ := typ.Underlying().(*types.Interface); iface != nil {\n\t\t\tiface.Complete()\n\t\t}\n\t}\n\n\treturn pkgs, nil\n}\n\ntype setConstraintArgs struct {\n\tt          *types.TypeParam\n\tconstraint types.Type\n}\n\ntype iimporter struct {\n\tversion int\n\tipath   string\n\n\tshallow bool\n\treportf ReportFunc // if non-nil, used to report bugs\n\n\tstringData  []byte\n\tstringCache map[uint64]string\n\tfileOffset  []uint64 // fileOffset[i] is offset in fileData for info about file encoded as i\n\tfileData    []byte\n\tfileCache   []*token.File // memoized decoding of file encoded as i\n\tpkgCache    map[uint64]*types.Package\n\n\tdeclData    []byte\n\tpkgIndex    map[*types.Package]map[string]uint64\n\ttypCache    map[uint64]types.Type\n\ttparamIndex map[ident]types.Type\n\n\tfake          fakeFileSet\n\tinterfaceList []*types.Interface\n\n\t// Workaround for the go/types bug golang/go#61561: instances produced during\n\t// instantiation may contain incomplete interfaces. Here we only complete the\n\t// underlying type of the instance, which is the most common case but doesn't\n\t// handle parameterized interface literals defined deeper in the type.\n\tinstanceList []types.Type // instances for later completion (see golang/go#61561)\n\n\t// Arguments for calls to SetConstraint that are deferred due to recursive types\n\tlater []setConstraintArgs\n\n\tindent int // for tracing support\n}\n\nfunc (p *iimporter) trace(format string, args ...any) {\n\tif !trace {\n\t\t// Call sites should also be guarded, but having this check here allows\n\t\t// easily enabling/disabling debug trace statements.\n\t\treturn\n\t}\n\tfmt.Printf(strings.Repeat(\"..\", p.indent)+format+\"\\n\", args...)\n}\n\nfunc (p *iimporter) doDecl(pkg *types.Package, name string) {\n\tif debug {\n\t\tp.trace(\"import decl %s\", name)\n\t\tp.indent++\n\t\tdefer func() {\n\t\t\tp.indent--\n\t\t\tp.trace(\"=> %s\", name)\n\t\t}()\n\t}\n\t// See if we've already imported this declaration.\n\tif obj := pkg.Scope().Lookup(name); obj != nil {\n\t\treturn\n\t}\n\n\toff, ok := p.pkgIndex[pkg][name]\n\tif !ok {\n\t\t// In deep mode, the index should be complete. In shallow\n\t\t// mode, we should have already recursively loaded necessary\n\t\t// dependencies so the above Lookup succeeds.\n\t\terrorf(\"%v.%v not in index\", pkg, name)\n\t}\n\n\tr := &importReader{p: p}\n\tr.declReader.Reset(p.declData[off:])\n\n\tr.obj(pkg, name)\n}\n\nfunc (p *iimporter) stringAt(off uint64) string {\n\tif s, ok := p.stringCache[off]; ok {\n\t\treturn s\n\t}\n\n\tslen, n := binary.Uvarint(p.stringData[off:])\n\tif n <= 0 {\n\t\terrorf(\"varint failed\")\n\t}\n\tspos := off + uint64(n)\n\ts := string(p.stringData[spos : spos+slen])\n\tp.stringCache[off] = s\n\treturn s\n}\n\nfunc (p *iimporter) fileAt(index uint64) *token.File {\n\tfile := p.fileCache[index]\n\tif file == nil {\n\t\toff := p.fileOffset[index]\n\t\tfile = p.decodeFile(intReader{bytes.NewReader(p.fileData[off:]), p.ipath})\n\t\tp.fileCache[index] = file\n\t}\n\treturn file\n}\n\nfunc (p *iimporter) decodeFile(rd intReader) *token.File {\n\tfilename := p.stringAt(rd.uint64())\n\tsize := int(rd.uint64())\n\tfile := p.fake.fset.AddFile(filename, -1, size)\n\n\t// SetLines requires a nondecreasing sequence.\n\t// Because it is common for clients to derive the interval\n\t// [start, start+len(name)] from a start position, and we\n\t// want to ensure that the end offset is on the same line,\n\t// we fill in the gaps of the sparse encoding with values\n\t// that strictly increase by the largest possible amount.\n\t// This allows us to avoid having to record the actual end\n\t// offset of each needed line.\n\n\tlines := make([]int, int(rd.uint64()))\n\tvar index, offset int\n\tfor i, n := 0, int(rd.uint64()); i < n; i++ {\n\t\tindex += int(rd.uint64())\n\t\toffset += int(rd.uint64())\n\t\tlines[index] = offset\n\n\t\t// Ensure monotonicity between points.\n\t\tfor j := index - 1; j > 0 && lines[j] == 0; j-- {\n\t\t\tlines[j] = lines[j+1] - 1\n\t\t}\n\t}\n\n\t// Ensure monotonicity after last point.\n\tfor j := len(lines) - 1; j > 0 && lines[j] == 0; j-- {\n\t\tsize--\n\t\tlines[j] = size\n\t}\n\n\tif !file.SetLines(lines) {\n\t\terrorf(\"SetLines failed: %d\", lines) // can't happen\n\t}\n\treturn file\n}\n\nfunc (p *iimporter) pkgAt(off uint64) *types.Package {\n\tif pkg, ok := p.pkgCache[off]; ok {\n\t\treturn pkg\n\t}\n\tpath := p.stringAt(off)\n\terrorf(\"missing package %q in %q\", path, p.ipath)\n\treturn nil\n}\n\nfunc (p *iimporter) typAt(off uint64, base *types.Named) types.Type {\n\tif t, ok := p.typCache[off]; ok && canReuse(base, t) {\n\t\treturn t\n\t}\n\n\tif off < predeclReserved {\n\t\terrorf(\"predeclared type missing from cache: %v\", off)\n\t}\n\n\tr := &importReader{p: p}\n\tr.declReader.Reset(p.declData[off-predeclReserved:])\n\tt := r.doType(base)\n\n\tif canReuse(base, t) {\n\t\tp.typCache[off] = t\n\t}\n\treturn t\n}\n\n// canReuse reports whether the type rhs on the RHS of the declaration for def\n// may be re-used.\n//\n// Specifically, if def is non-nil and rhs is an interface type with methods, it\n// may not be re-used because we have a convention of setting the receiver type\n// for interface methods to def.\nfunc canReuse(def *types.Named, rhs types.Type) bool {\n\tif def == nil {\n\t\treturn true\n\t}\n\tiface, _ := types.Unalias(rhs).(*types.Interface)\n\tif iface == nil {\n\t\treturn true\n\t}\n\t// Don't use iface.Empty() here as iface may not be complete.\n\treturn iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0\n}\n\ntype importReader struct {\n\tp          *iimporter\n\tdeclReader bytes.Reader\n\tprevFile   string\n\tprevLine   int64\n\tprevColumn int64\n}\n\n// markBlack is redefined in iimport_go123.go, to work around golang/go#69912.\n//\n// If TypeNames are not marked black (in the sense of go/types cycle\n// detection), they may be mutated when dot-imported. Fix this by punching a\n// hole through the type, when compiling with Go 1.23. (The bug has been fixed\n// for 1.24, but the fix was not worth back-porting).\nvar markBlack = func(name *types.TypeName) {}\n\n// obj decodes and declares the package-level object denoted by (pkg, name).\nfunc (r *importReader) obj(pkg *types.Package, name string) {\n\ttag := r.byte()\n\tpos := r.pos()\n\n\tswitch tag {\n\tcase aliasTag, genericAliasTag:\n\t\tvar tparams []*types.TypeParam\n\t\tif tag == genericAliasTag {\n\t\t\ttparams = r.tparamList()\n\t\t}\n\t\ttyp := r.typ()\n\t\tobj := aliases.New(pos, pkg, name, typ, tparams)\n\t\tmarkBlack(obj) // workaround for golang/go#69912\n\t\tr.declare(obj)\n\n\tcase constTag:\n\t\ttyp, val := r.value()\n\n\t\tr.declare(types.NewConst(pos, pkg, name, typ, val))\n\n\tcase funcTag, genericFuncTag:\n\t\tvar tparams []*types.TypeParam\n\t\tif tag == genericFuncTag {\n\t\t\ttparams = r.tparamList()\n\t\t}\n\t\tsig := r.signature(pkg, nil, nil, tparams)\n\t\tr.declare(types.NewFunc(pos, pkg, name, sig))\n\n\tcase typeTag, genericTypeTag:\n\t\t// Types can be recursive. We need to setup a stub\n\t\t// declaration before recursing.\n\t\tobj := types.NewTypeName(pos, pkg, name, nil)\n\t\tnamed := types.NewNamed(obj, nil, nil)\n\n\t\tmarkBlack(obj) // workaround for golang/go#69912\n\n\t\t// Declare obj before calling r.tparamList, so the new type name is recognized\n\t\t// if used in the constraint of one of its own typeparams (see #48280).\n\t\tr.declare(obj)\n\t\tif tag == genericTypeTag {\n\t\t\ttparams := r.tparamList()\n\t\t\tnamed.SetTypeParams(tparams)\n\t\t}\n\n\t\tunderlying := r.p.typAt(r.uint64(), named).Underlying()\n\t\tnamed.SetUnderlying(underlying)\n\n\t\tif !isInterface(underlying) {\n\t\t\tfor n := r.uint64(); n > 0; n-- {\n\t\t\t\tmpos := r.pos()\n\t\t\t\tmname := r.ident()\n\t\t\t\trecv := r.param(pkg)\n\n\t\t\t\t// If the receiver has any targs, set those as the\n\t\t\t\t// rparams of the method (since those are the\n\t\t\t\t// typeparams being used in the method sig/body).\n\t\t\t\t_, recvNamed := typesinternal.ReceiverNamed(recv)\n\t\t\t\ttargs := recvNamed.TypeArgs()\n\t\t\t\tvar rparams []*types.TypeParam\n\t\t\t\tif targs.Len() > 0 {\n\t\t\t\t\trparams = make([]*types.TypeParam, targs.Len())\n\t\t\t\t\tfor i := range rparams {\n\t\t\t\t\t\trparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmsig := r.signature(pkg, recv, rparams, nil)\n\n\t\t\t\tnamed.AddMethod(types.NewFunc(mpos, pkg, mname, msig))\n\t\t\t}\n\t\t}\n\n\tcase typeParamTag:\n\t\t// We need to \"declare\" a typeparam in order to have a name that\n\t\t// can be referenced recursively (if needed) in the type param's\n\t\t// bound.\n\t\tif r.p.version < iexportVersionGenerics {\n\t\t\terrorf(\"unexpected type param type\")\n\t\t}\n\t\tname0 := tparamName(name)\n\t\ttn := types.NewTypeName(pos, pkg, name0, nil)\n\t\tt := types.NewTypeParam(tn, nil)\n\n\t\t// To handle recursive references to the typeparam within its\n\t\t// bound, save the partial type in tparamIndex before reading the bounds.\n\t\tid := ident{pkg, name}\n\t\tr.p.tparamIndex[id] = t\n\t\tvar implicit bool\n\t\tif r.p.version >= iexportVersionGo1_18 {\n\t\t\timplicit = r.bool()\n\t\t}\n\t\tconstraint := r.typ()\n\t\tif implicit {\n\t\t\tiface, _ := types.Unalias(constraint).(*types.Interface)\n\t\t\tif iface == nil {\n\t\t\t\terrorf(\"non-interface constraint marked implicit\")\n\t\t\t}\n\t\t\tiface.MarkImplicit()\n\t\t}\n\t\t// The constraint type may not be complete, if we\n\t\t// are in the middle of a type recursion involving type\n\t\t// constraints. So, we defer SetConstraint until we have\n\t\t// completely set up all types in ImportData.\n\t\tr.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})\n\n\tcase varTag:\n\t\ttyp := r.typ()\n\n\t\tv := types.NewVar(pos, pkg, name, typ)\n\t\ttypesinternal.SetVarKind(v, typesinternal.PackageVar)\n\t\tr.declare(v)\n\n\tdefault:\n\t\terrorf(\"unexpected tag: %v\", tag)\n\t}\n}\n\nfunc (r *importReader) declare(obj types.Object) {\n\tobj.Pkg().Scope().Insert(obj)\n}\n\nfunc (r *importReader) value() (typ types.Type, val constant.Value) {\n\ttyp = r.typ()\n\tif r.p.version >= iexportVersionGo1_18 {\n\t\t// TODO: add support for using the kind.\n\t\t_ = constant.Kind(r.int64())\n\t}\n\n\tswitch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {\n\tcase types.IsBoolean:\n\t\tval = constant.MakeBool(r.bool())\n\n\tcase types.IsString:\n\t\tval = constant.MakeString(r.string())\n\n\tcase types.IsInteger:\n\t\tvar x big.Int\n\t\tr.mpint(&x, b)\n\t\tval = constant.Make(&x)\n\n\tcase types.IsFloat:\n\t\tval = r.mpfloat(b)\n\n\tcase types.IsComplex:\n\t\tre := r.mpfloat(b)\n\t\tim := r.mpfloat(b)\n\t\tval = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))\n\n\tdefault:\n\t\tif b.Kind() == types.Invalid {\n\t\t\tval = constant.MakeUnknown()\n\t\t\treturn\n\t\t}\n\t\terrorf(\"unexpected type %v\", typ) // panics\n\t\tpanic(\"unreachable\")\n\t}\n\n\treturn\n}\n\nfunc intSize(b *types.Basic) (signed bool, maxBytes uint) {\n\tif (b.Info() & types.IsUntyped) != 0 {\n\t\treturn true, 64\n\t}\n\n\tswitch b.Kind() {\n\tcase types.Float32, types.Complex64:\n\t\treturn true, 3\n\tcase types.Float64, types.Complex128:\n\t\treturn true, 7\n\t}\n\n\tsigned = (b.Info() & types.IsUnsigned) == 0\n\tswitch b.Kind() {\n\tcase types.Int8, types.Uint8:\n\t\tmaxBytes = 1\n\tcase types.Int16, types.Uint16:\n\t\tmaxBytes = 2\n\tcase types.Int32, types.Uint32:\n\t\tmaxBytes = 4\n\tdefault:\n\t\tmaxBytes = 8\n\t}\n\n\treturn\n}\n\nfunc (r *importReader) mpint(x *big.Int, typ *types.Basic) {\n\tsigned, maxBytes := intSize(typ)\n\n\tmaxSmall := 256 - maxBytes\n\tif signed {\n\t\tmaxSmall = 256 - 2*maxBytes\n\t}\n\tif maxBytes == 1 {\n\t\tmaxSmall = 256\n\t}\n\n\tn, _ := r.declReader.ReadByte()\n\tif uint(n) < maxSmall {\n\t\tv := int64(n)\n\t\tif signed {\n\t\t\tv >>= 1\n\t\t\tif n&1 != 0 {\n\t\t\t\tv = ^v\n\t\t\t}\n\t\t}\n\t\tx.SetInt64(v)\n\t\treturn\n\t}\n\n\tv := -n\n\tif signed {\n\t\tv = -(n &^ 1) >> 1\n\t}\n\tif v < 1 || uint(v) > maxBytes {\n\t\terrorf(\"weird decoding: %v, %v => %v\", n, signed, v)\n\t}\n\tb := make([]byte, v)\n\tio.ReadFull(&r.declReader, b)\n\tx.SetBytes(b)\n\tif signed && n&1 != 0 {\n\t\tx.Neg(x)\n\t}\n}\n\nfunc (r *importReader) mpfloat(typ *types.Basic) constant.Value {\n\tvar mant big.Int\n\tr.mpint(&mant, typ)\n\tvar f big.Float\n\tf.SetInt(&mant)\n\tif f.Sign() != 0 {\n\t\tf.SetMantExp(&f, int(r.int64()))\n\t}\n\treturn constant.Make(&f)\n}\n\nfunc (r *importReader) ident() string {\n\treturn r.string()\n}\n\nfunc (r *importReader) qualifiedIdent() (*types.Package, string) {\n\tname := r.string()\n\tpkg := r.pkg()\n\treturn pkg, name\n}\n\nfunc (r *importReader) pos() token.Pos {\n\tif r.p.shallow {\n\t\t// precise offsets are encoded only in shallow mode\n\t\treturn r.posv2()\n\t}\n\tif r.p.version >= iexportVersionPosCol {\n\t\tr.posv1()\n\t} else {\n\t\tr.posv0()\n\t}\n\n\tif r.prevFile == \"\" && r.prevLine == 0 && r.prevColumn == 0 {\n\t\treturn token.NoPos\n\t}\n\treturn r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))\n}\n\nfunc (r *importReader) posv0() {\n\tdelta := r.int64()\n\tif delta != deltaNewFile {\n\t\tr.prevLine += delta\n\t} else if l := r.int64(); l == -1 {\n\t\tr.prevLine += deltaNewFile\n\t} else {\n\t\tr.prevFile = r.string()\n\t\tr.prevLine = l\n\t}\n}\n\nfunc (r *importReader) posv1() {\n\tdelta := r.int64()\n\tr.prevColumn += delta >> 1\n\tif delta&1 != 0 {\n\t\tdelta = r.int64()\n\t\tr.prevLine += delta >> 1\n\t\tif delta&1 != 0 {\n\t\t\tr.prevFile = r.string()\n\t\t}\n\t}\n}\n\nfunc (r *importReader) posv2() token.Pos {\n\tfile := r.uint64()\n\tif file == 0 {\n\t\treturn token.NoPos\n\t}\n\ttf := r.p.fileAt(file - 1)\n\treturn tf.Pos(int(r.uint64()))\n}\n\nfunc (r *importReader) typ() types.Type {\n\treturn r.p.typAt(r.uint64(), nil)\n}\n\nfunc isInterface(t types.Type) bool {\n\t_, ok := types.Unalias(t).(*types.Interface)\n\treturn ok\n}\n\nfunc (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }\nfunc (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }\n\nfunc (r *importReader) doType(base *types.Named) (res types.Type) {\n\tk := r.kind()\n\tif debug {\n\t\tr.p.trace(\"importing type %d (base: %v)\", k, base)\n\t\tr.p.indent++\n\t\tdefer func() {\n\t\t\tr.p.indent--\n\t\t\tr.p.trace(\"=> %s\", res)\n\t\t}()\n\t}\n\tswitch k {\n\tdefault:\n\t\terrorf(\"unexpected kind tag in %q: %v\", r.p.ipath, k)\n\t\treturn nil\n\n\tcase aliasType, definedType:\n\t\tpkg, name := r.qualifiedIdent()\n\t\tr.p.doDecl(pkg, name)\n\t\treturn pkg.Scope().Lookup(name).(*types.TypeName).Type()\n\tcase pointerType:\n\t\treturn types.NewPointer(r.typ())\n\tcase sliceType:\n\t\treturn types.NewSlice(r.typ())\n\tcase arrayType:\n\t\tn := r.uint64()\n\t\treturn types.NewArray(r.typ(), int64(n))\n\tcase chanType:\n\t\tdir := chanDir(int(r.uint64()))\n\t\treturn types.NewChan(dir, r.typ())\n\tcase mapType:\n\t\treturn types.NewMap(r.typ(), r.typ())\n\tcase signatureType:\n\t\tparamPkg := r.pkg()\n\t\treturn r.signature(paramPkg, nil, nil, nil)\n\n\tcase structType:\n\t\tfieldPkg := r.pkg()\n\n\t\tfields := make([]*types.Var, r.uint64())\n\t\ttags := make([]string, len(fields))\n\t\tfor i := range fields {\n\t\t\tvar field *types.Var\n\t\t\tif r.p.shallow {\n\t\t\t\tfield, _ = r.objectPathObject().(*types.Var)\n\t\t\t}\n\n\t\t\tfpos := r.pos()\n\t\t\tfname := r.ident()\n\t\t\tftyp := r.typ()\n\t\t\temb := r.bool()\n\t\t\ttag := r.string()\n\n\t\t\t// Either this is not a shallow import, the field is local, or the\n\t\t\t// encoded objectPath failed to produce an object (a bug).\n\t\t\t//\n\t\t\t// Even in this last, buggy case, fall back on creating a new field. As\n\t\t\t// discussed in iexport.go, this is not correct, but mostly works and is\n\t\t\t// preferable to failing (for now at least).\n\t\t\tif field == nil {\n\t\t\t\tfield = types.NewField(fpos, fieldPkg, fname, ftyp, emb)\n\t\t\t}\n\n\t\t\tfields[i] = field\n\t\t\ttags[i] = tag\n\t\t}\n\t\treturn types.NewStruct(fields, tags)\n\n\tcase interfaceType:\n\t\tmethodPkg := r.pkg() // qualifies methods and their param/result vars\n\n\t\tembeddeds := make([]types.Type, r.uint64())\n\t\tfor i := range embeddeds {\n\t\t\t_ = r.pos()\n\t\t\tembeddeds[i] = r.typ()\n\t\t}\n\n\t\tmethods := make([]*types.Func, r.uint64())\n\t\tfor i := range methods {\n\t\t\tvar method *types.Func\n\t\t\tif r.p.shallow {\n\t\t\t\tmethod, _ = r.objectPathObject().(*types.Func)\n\t\t\t}\n\n\t\t\tmpos := r.pos()\n\t\t\tmname := r.ident()\n\n\t\t\t// TODO(mdempsky): Matches bimport.go, but I\n\t\t\t// don't agree with this.\n\t\t\tvar recv *types.Var\n\t\t\tif base != nil {\n\t\t\t\trecv = types.NewVar(token.NoPos, methodPkg, \"\", base)\n\t\t\t}\n\t\t\tmsig := r.signature(methodPkg, recv, nil, nil)\n\n\t\t\tif method == nil {\n\t\t\t\tmethod = types.NewFunc(mpos, methodPkg, mname, msig)\n\t\t\t}\n\t\t\tmethods[i] = method\n\t\t}\n\n\t\ttyp := types.NewInterfaceType(methods, embeddeds)\n\t\tr.p.interfaceList = append(r.p.interfaceList, typ)\n\t\treturn typ\n\n\tcase typeParamType:\n\t\tif r.p.version < iexportVersionGenerics {\n\t\t\terrorf(\"unexpected type param type\")\n\t\t}\n\t\tpkg, name := r.qualifiedIdent()\n\t\tid := ident{pkg, name}\n\t\tif t, ok := r.p.tparamIndex[id]; ok {\n\t\t\t// We're already in the process of importing this typeparam.\n\t\t\treturn t\n\t\t}\n\t\t// Otherwise, import the definition of the typeparam now.\n\t\tr.p.doDecl(pkg, name)\n\t\treturn r.p.tparamIndex[id]\n\n\tcase instanceType:\n\t\tif r.p.version < iexportVersionGenerics {\n\t\t\terrorf(\"unexpected instantiation type\")\n\t\t}\n\t\t// pos does not matter for instances: they are positioned on the original\n\t\t// type.\n\t\t_ = r.pos()\n\t\tlen := r.uint64()\n\t\ttargs := make([]types.Type, len)\n\t\tfor i := range targs {\n\t\t\ttargs[i] = r.typ()\n\t\t}\n\t\tbaseType := r.typ()\n\t\t// The imported instantiated type doesn't include any methods, so\n\t\t// we must always use the methods of the base (orig) type.\n\t\t// TODO provide a non-nil *Environment\n\t\tt, _ := types.Instantiate(nil, baseType, targs, false)\n\n\t\t// Workaround for golang/go#61561. See the doc for instanceList for details.\n\t\tr.p.instanceList = append(r.p.instanceList, t)\n\t\treturn t\n\n\tcase unionType:\n\t\tif r.p.version < iexportVersionGenerics {\n\t\t\terrorf(\"unexpected instantiation type\")\n\t\t}\n\t\tterms := make([]*types.Term, r.uint64())\n\t\tfor i := range terms {\n\t\t\tterms[i] = types.NewTerm(r.bool(), r.typ())\n\t\t}\n\t\treturn types.NewUnion(terms)\n\t}\n}\n\nfunc (r *importReader) kind() itag {\n\treturn itag(r.uint64())\n}\n\n// objectPathObject is the inverse of exportWriter.objectPath.\n//\n// In shallow mode, certain fields and methods may need to be looked up in an\n// imported package. See the doc for exportWriter.objectPath for a full\n// explanation.\nfunc (r *importReader) objectPathObject() types.Object {\n\tobjPath := objectpath.Path(r.string())\n\tif objPath == \"\" {\n\t\treturn nil\n\t}\n\tpkg := r.pkg()\n\tobj, err := objectpath.Object(pkg, objPath)\n\tif err != nil {\n\t\tif r.p.reportf != nil {\n\t\t\tr.p.reportf(\"failed to find object for objectPath %q: %v\", objPath, err)\n\t\t}\n\t}\n\treturn obj\n}\n\nfunc (r *importReader) signature(paramPkg *types.Package, recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {\n\tparams := r.paramList(paramPkg)\n\tresults := r.paramList(paramPkg)\n\tvariadic := params.Len() > 0 && r.bool()\n\treturn types.NewSignatureType(recv, rparams, tparams, params, results, variadic)\n}\n\nfunc (r *importReader) tparamList() []*types.TypeParam {\n\tn := r.uint64()\n\tif n == 0 {\n\t\treturn nil\n\t}\n\txs := make([]*types.TypeParam, n)\n\tfor i := range xs {\n\t\t// Note: the standard library importer is tolerant of nil types here,\n\t\t// though would panic in SetTypeParams.\n\t\txs[i] = types.Unalias(r.typ()).(*types.TypeParam)\n\t}\n\treturn xs\n}\n\nfunc (r *importReader) paramList(pkg *types.Package) *types.Tuple {\n\txs := make([]*types.Var, r.uint64())\n\tfor i := range xs {\n\t\txs[i] = r.param(pkg)\n\t}\n\treturn types.NewTuple(xs...)\n}\n\nfunc (r *importReader) param(pkg *types.Package) *types.Var {\n\tpos := r.pos()\n\tname := r.ident()\n\ttyp := r.typ()\n\treturn types.NewParam(pos, pkg, name, typ)\n}\n\nfunc (r *importReader) bool() bool {\n\treturn r.uint64() != 0\n}\n\nfunc (r *importReader) int64() int64 {\n\tn, err := binary.ReadVarint(&r.declReader)\n\tif err != nil {\n\t\terrorf(\"readVarint: %v\", err)\n\t}\n\treturn n\n}\n\nfunc (r *importReader) uint64() uint64 {\n\tn, err := binary.ReadUvarint(&r.declReader)\n\tif err != nil {\n\t\terrorf(\"readUvarint: %v\", err)\n\t}\n\treturn n\n}\n\nfunc (r *importReader) byte() byte {\n\tx, err := r.declReader.ReadByte()\n\tif err != nil {\n\t\terrorf(\"declReader.ReadByte: %v\", err)\n\t}\n\treturn x\n}\n\ntype byPath []*types.Package\n\nfunc (a byPath) Len() int           { return len(a) }\nfunc (a byPath) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }\nfunc (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }\n"
  },
  {
    "path": "internal/gcimporter/israce_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build race\n\npackage gcimporter_test\n\nfunc init() {\n\tisRace = true\n}\n"
  },
  {
    "path": "internal/gcimporter/main.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The gcimporter command reads the compiler's export data for the\n// named packages and prints the decoded type information.\n//\n// It is provided for debugging export data problems.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/gcimporter\"\n)\n\nfunc main() {\n\tflag.Parse()\n\tcfg := &packages.Config{\n\t\tFset: token.NewFileSet(),\n\t\t// Don't request NeedTypes: we want to be certain that\n\t\t// we loaded the types ourselves, from export data.\n\t\tMode: packages.NeedName | packages.NeedExportFile,\n\t}\n\tpkgs, err := packages.Load(cfg, flag.Args()...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tos.Exit(1)\n\t}\n\n\tfor _, pkg := range pkgs {\n\t\t// Read types from compiler's unified export data file.\n\t\t// This Package may included non-exported functions if they\n\t\t// are called by inlinable exported functions.\n\t\tvar tpkg1 *types.Package\n\t\t{\n\t\t\texport, err := os.ReadFile(pkg.ExportFile)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"can't read %q export data: %v\", pkg.PkgPath, err)\n\t\t\t}\n\t\t\tr, err := gcexportdata.NewReader(bytes.NewReader(export))\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"reading export data %s: %v\", pkg.ExportFile, err)\n\t\t\t}\n\t\t\ttpkg1, err = gcexportdata.Read(r, cfg.Fset, make(map[string]*types.Package), pkg.PkgPath)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"decoding export data: %v\", err)\n\t\t\t}\n\t\t}\n\t\tfmt.Println(\"# Read from compiler's unified export data:\")\n\t\tprintPackage(tpkg1)\n\n\t\t// Now reexport as indexed (deep) export data, and reimport.\n\t\t// The Package will contain only exported symbols.\n\t\tvar tpkg2 *types.Package\n\t\t{\n\t\t\tvar out bytes.Buffer\n\t\t\tif err := gcimporter.IExportData(&out, cfg.Fset, tpkg1); err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t\tvar err error\n\t\t\t_, tpkg2, err = gcimporter.IImportData(cfg.Fset, make(map[string]*types.Package), out.Bytes(), tpkg1.Path())\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t}\n\t\tfmt.Println(\"# After round-tripping through indexed export data:\")\n\t\tprintPackage(tpkg2)\n\t}\n}\n\nfunc printPackage(pkg *types.Package) {\n\tfmt.Printf(\"package %s %q\\n\", pkg.Name(), pkg.Path())\n\n\tif !pkg.Complete() {\n\t\tfmt.Printf(\"\\thas incomplete exported type info\\n\")\n\t}\n\n\t// imports\n\tvar lines []string\n\tfor _, imp := range pkg.Imports() {\n\t\tlines = append(lines, fmt.Sprintf(\"\\timport %q\", imp.Path()))\n\t}\n\tsort.Strings(lines)\n\tfor _, line := range lines {\n\t\tfmt.Println(line)\n\t}\n\n\t// types of package members\n\tqual := types.RelativeTo(pkg)\n\tscope := pkg.Scope()\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tfmt.Printf(\"\\t%s\\n\", types.ObjectString(obj, qual))\n\t\tif _, ok := obj.(*types.TypeName); ok {\n\t\t\tfor _, meth := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {\n\t\t\t\tfmt.Printf(\"\\t%s\\n\", types.SelectionString(meth, qual))\n\t\t\t}\n\t\t}\n\t}\n\n\tfmt.Println()\n}\n"
  },
  {
    "path": "internal/gcimporter/predeclared.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter\n\nimport (\n\t\"go/types\"\n\t\"sync\"\n)\n\n// predecl is a cache for the predeclared types in types.Universe.\n//\n// Cache a distinct result based on the runtime value of any.\n// The pointer value of the any type varies based on GODEBUG settings.\nvar predeclMu sync.Mutex\nvar predecl map[types.Type][]types.Type\n\nfunc predeclared() []types.Type {\n\tanyt := types.Universe.Lookup(\"any\").Type()\n\n\tpredeclMu.Lock()\n\tdefer predeclMu.Unlock()\n\n\tif pre, ok := predecl[anyt]; ok {\n\t\treturn pre\n\t}\n\n\tif predecl == nil {\n\t\tpredecl = make(map[types.Type][]types.Type)\n\t}\n\n\tdecls := []types.Type{ // basic types\n\t\ttypes.Typ[types.Bool],\n\t\ttypes.Typ[types.Int],\n\t\ttypes.Typ[types.Int8],\n\t\ttypes.Typ[types.Int16],\n\t\ttypes.Typ[types.Int32],\n\t\ttypes.Typ[types.Int64],\n\t\ttypes.Typ[types.Uint],\n\t\ttypes.Typ[types.Uint8],\n\t\ttypes.Typ[types.Uint16],\n\t\ttypes.Typ[types.Uint32],\n\t\ttypes.Typ[types.Uint64],\n\t\ttypes.Typ[types.Uintptr],\n\t\ttypes.Typ[types.Float32],\n\t\ttypes.Typ[types.Float64],\n\t\ttypes.Typ[types.Complex64],\n\t\ttypes.Typ[types.Complex128],\n\t\ttypes.Typ[types.String],\n\n\t\t// basic type aliases\n\t\ttypes.Universe.Lookup(\"byte\").Type(),\n\t\ttypes.Universe.Lookup(\"rune\").Type(),\n\n\t\t// error\n\t\ttypes.Universe.Lookup(\"error\").Type(),\n\n\t\t// untyped types\n\t\ttypes.Typ[types.UntypedBool],\n\t\ttypes.Typ[types.UntypedInt],\n\t\ttypes.Typ[types.UntypedRune],\n\t\ttypes.Typ[types.UntypedFloat],\n\t\ttypes.Typ[types.UntypedComplex],\n\t\ttypes.Typ[types.UntypedString],\n\t\ttypes.Typ[types.UntypedNil],\n\n\t\t// package unsafe\n\t\ttypes.Typ[types.UnsafePointer],\n\n\t\t// invalid type\n\t\ttypes.Typ[types.Invalid], // only appears in packages with errors\n\n\t\t// used internally by gc; never used by this package or in .a files\n\t\tanyType{},\n\n\t\t// comparable\n\t\ttypes.Universe.Lookup(\"comparable\").Type(),\n\n\t\t// any\n\t\tanyt,\n\t}\n\n\tpredecl[anyt] = decls\n\treturn decls\n}\n\ntype anyType struct{}\n\nfunc (t anyType) Underlying() types.Type { return t }\nfunc (t anyType) String() string         { return \"any\" }\n"
  },
  {
    "path": "internal/gcimporter/shallow_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/gcimporter\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestShallowStd type-checks the standard library using shallow export data.\nfunc TestShallowStd(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode; too slow (https://golang.org/issue/14113)\")\n\t}\n\ttestenv.NeedsTool(t, \"go\")\n\n\t// Load import graph of the standard library.\n\t// (No parsing or type-checking.)\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedImports |\n\t\t\tpackages.NeedName |\n\t\t\tpackages.NeedFiles | // see https://github.com/golang/go/issues/56632\n\t\t\tpackages.NeedCompiledGoFiles,\n\t\tTests: false,\n\t}\n\tpkgs, err := packages.Load(cfg, \"std\")\n\tif err != nil {\n\t\tt.Fatalf(\"load: %v\", err)\n\t}\n\tif len(pkgs) < 200 {\n\t\tt.Fatalf(\"too few packages: %d\", len(pkgs))\n\t}\n\n\t// Type check the packages in parallel postorder.\n\tdone := make(map[*packages.Package]chan struct{})\n\tpackages.Visit(pkgs, nil, func(p *packages.Package) {\n\t\tdone[p] = make(chan struct{})\n\t})\n\tpackages.Visit(pkgs, nil,\n\t\tfunc(pkg *packages.Package) {\n\t\t\tgo func() {\n\t\t\t\t// Wait for all deps to be done.\n\t\t\t\tfor _, imp := range pkg.Imports {\n\t\t\t\t\t<-done[imp]\n\t\t\t\t}\n\t\t\t\ttypecheck(t, pkg)\n\t\t\t\tclose(done[pkg])\n\t\t\t}()\n\t\t})\n\tfor _, root := range pkgs {\n\t\t<-done[root]\n\t}\n}\n\n// typecheck reads, parses, and type-checks a package.\n// It squirrels the export data in the ppkg.ExportFile field.\nfunc typecheck(t *testing.T, ppkg *packages.Package) {\n\tif ppkg.PkgPath == \"unsafe\" {\n\t\treturn // unsafe is special\n\t}\n\n\t// Create a local FileSet just for this package.\n\tfset := token.NewFileSet()\n\n\t// Parse files in parallel.\n\tsyntax := make([]*ast.File, len(ppkg.CompiledGoFiles))\n\tvar group errgroup.Group\n\tfor i, filename := range ppkg.CompiledGoFiles {\n\t\tgroup.Go(func() error {\n\t\t\tf, err := parser.ParseFile(fset, filename, nil, parser.SkipObjectResolution)\n\t\t\tif err != nil {\n\t\t\t\treturn err // e.g. missing file\n\t\t\t}\n\t\t\tsyntax[i] = f\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := group.Wait(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Inv: all files were successfully parsed.\n\n\t// Build map of dependencies by package path.\n\t// (We don't compute this mapping for the entire\n\t// packages graph because it is not globally consistent.)\n\tdepsByPkgPath := make(map[string]*packages.Package)\n\t{\n\t\tvar visit func(*packages.Package)\n\t\tvisit = func(pkg *packages.Package) {\n\t\t\tif depsByPkgPath[pkg.PkgPath] == nil {\n\t\t\t\tdepsByPkgPath[pkg.PkgPath] = pkg\n\t\t\t\tfor path := range pkg.Imports {\n\t\t\t\t\tvisit(pkg.Imports[path])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvisit(ppkg)\n\t}\n\n\t// importer state\n\tvar (\n\t\tloadFromExportData func(*packages.Package) (*types.Package, error)\n\t\timportMap          = map[string]*types.Package{ // keys are PackagePaths\n\t\t\tppkg.PkgPath: types.NewPackage(ppkg.PkgPath, ppkg.Name),\n\t\t}\n\t)\n\tloadFromExportData = func(imp *packages.Package) (*types.Package, error) {\n\t\texport := []byte(imp.ExportFile)\n\t\tgetPackages := func(items []gcimporter.GetPackagesItem) error {\n\t\t\tfor i, item := range items {\n\t\t\t\tpkg, ok := importMap[item.Path]\n\t\t\t\tif !ok {\n\t\t\t\t\tdep, ok := depsByPkgPath[item.Path]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn fmt.Errorf(\"can't find dependency: %q\", item.Path)\n\t\t\t\t\t}\n\t\t\t\t\tpkg = types.NewPackage(item.Path, dep.Name)\n\t\t\t\t\timportMap[item.Path] = pkg\n\t\t\t\t\tloadFromExportData(dep) // side effect: populate package scope\n\t\t\t\t}\n\t\t\t\titems[i].Pkg = pkg\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\treturn gcimporter.IImportShallow(fset, getPackages, export, imp.PkgPath, nil)\n\t}\n\n\t// Type-check the syntax trees.\n\tcfg := &types.Config{\n\t\tError: func(e error) {\n\t\t\tt.Error(e)\n\t\t},\n\t\tImporter: importerFunc(func(importPath string) (*types.Package, error) {\n\t\t\tif importPath == \"unsafe\" {\n\t\t\t\treturn types.Unsafe, nil // unsafe has no exportdata\n\t\t\t}\n\t\t\timp, ok := ppkg.Imports[importPath]\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"missing import %q\", importPath)\n\t\t\t}\n\t\t\treturn loadFromExportData(imp)\n\t\t}),\n\t}\n\n\t// (Use NewChecker+Files to ensure Package.Name is set explicitly.)\n\ttpkg := types.NewPackage(ppkg.PkgPath, ppkg.Name)\n\t_ = types.NewChecker(cfg, fset, tpkg, nil).Files(syntax) // ignore error\n\t// Check sanity.\n\tpostTypeCheck(t, fset, tpkg)\n\n\t// Save the export data.\n\tdata, err := gcimporter.IExportShallow(fset, tpkg, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"internal error marshalling export data: %v\", err)\n\t}\n\tppkg.ExportFile = string(data)\n}\n\n// postTypeCheck is called after a package is type checked.\n// We use it to assert additional correctness properties,\n// for example, that the apparent location of \"fmt.Println\"\n// corresponds to its source location: in other words,\n// export+import preserves high-fidelity positions.\nfunc postTypeCheck(t *testing.T, fset *token.FileSet, pkg *types.Package) {\n\t// We hard-code a few interesting test-case objects.\n\tvar obj types.Object\n\tswitch pkg.Path() {\n\tcase \"fmt\":\n\t\t// func fmt.Println\n\t\tobj = pkg.Scope().Lookup(\"Println\")\n\tcase \"net/http\":\n\t\t// method (*http.Request).ParseForm\n\t\treq := pkg.Scope().Lookup(\"Request\")\n\t\tobj, _, _ = types.LookupFieldOrMethod(req.Type(), true, pkg, \"ParseForm\")\n\tdefault:\n\t\treturn\n\t}\n\tif obj == nil {\n\t\tt.Errorf(\"object not found in package %s\", pkg.Path())\n\t\treturn\n\t}\n\n\t// Now check the source fidelity of the object's position.\n\tposn := fset.Position(obj.Pos())\n\tdata, err := os.ReadFile(posn.Filename)\n\tif err != nil {\n\t\tt.Errorf(\"can't read source file declaring %v: %v\", obj, err)\n\t\treturn\n\t}\n\n\t// Check line and column denote a source interval containing the object's identifier.\n\tline := strings.Split(string(data), \"\\n\")[posn.Line-1]\n\n\tif id := line[posn.Column-1 : posn.Column-1+len(obj.Name())]; id != obj.Name() {\n\t\tt.Errorf(\"%+v: expected declaration of %v at this line, column; got %q\", posn, obj, line)\n\t}\n\n\t// Check offset.\n\tif id := string(data[posn.Offset : posn.Offset+len(obj.Name())]); id != obj.Name() {\n\t\tt.Errorf(\"%+v: expected declaration of %v at this offset; got %q\", posn, obj, id)\n\t}\n\n\t// Check commutativity of Position() and start+len(name) operations:\n\t// Position(startPos+len(name)) == Position(startPos) + len(name).\n\t// This important property is a consequence of the way in which the\n\t// decoder fills the gaps in the sparse line-start offset table.\n\tendPosn := fset.Position(obj.Pos() + token.Pos(len(obj.Name())))\n\twantEndPosn := token.Position{\n\t\tFilename: posn.Filename,\n\t\tOffset:   posn.Offset + len(obj.Name()),\n\t\tLine:     posn.Line,\n\t\tColumn:   posn.Column + len(obj.Name()),\n\t}\n\tif endPosn != wantEndPosn {\n\t\tt.Errorf(\"%+v: expected end Position of %v here; was at %+v\", wantEndPosn, obj, endPosn)\n\t}\n}\n"
  },
  {
    "path": "internal/gcimporter/stdlib_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"runtime\"\n\t\"testing\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/gcexportdata\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TestStdlib ensures that all packages in std and x/tools can be\n// type-checked using export data.\nfunc TestStdlib(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\t// gcexportdata.Read rapidly consumes FileSet address space,\n\t// so disable the test on 32-bit machines.\n\t// (We could use a fresh FileSet per type-check, but that\n\t// would require us to re-parse the source using it.)\n\tif unsafe.Sizeof(token.NoPos) < 8 {\n\t\tt.Skip(\"skipping test on 32-bit machine\")\n\t}\n\n\t// Load, parse and type-check the standard library.\n\t// If we have the full source code for x/tools, also load and type-check that.\n\tcfg := &packages.Config{Mode: packages.LoadAllSyntax}\n\tpatterns := []string{\"std\"}\n\tminPkgs := 225 // 'GOOS=plan9 go1.18 list std | wc -l' reports 228; most other platforms have more.\n\tswitch runtime.GOOS {\n\tcase \"android\", \"ios\":\n\t\t// The go_.*_exec script for mobile builders only copies over the source tree\n\t\t// for the package under test.\n\tdefault:\n\t\tpatterns = append(patterns, \"golang.org/x/tools/...\")\n\t\tminPkgs += 160 // At the time of writing, 'GOOS=plan9 go list ./... | wc -l' reports 188.\n\t}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to load/parse/type-check: %v\", err)\n\t}\n\tif packages.PrintErrors(pkgs) > 0 {\n\t\tt.Fatal(\"there were errors during loading\")\n\t}\n\tif len(pkgs) < minPkgs {\n\t\tt.Errorf(\"too few packages (%d) were loaded\", len(pkgs))\n\t}\n\n\texport := make(map[string][]byte) // keys are package IDs\n\n\t// Re-type check them all in post-order, using export data.\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tpackages := make(map[string]*types.Package) // keys are package paths\n\t\tcfg := &types.Config{\n\t\t\tError: func(e error) {\n\t\t\t\tt.Errorf(\"type error: %v\", e)\n\t\t\t},\n\t\t\tImporter: importerFunc(func(importPath string) (*types.Package, error) {\n\t\t\t\t// Resolve import path to (vendored?) package path.\n\t\t\t\timported := pkg.Imports[importPath]\n\n\t\t\t\tif imported.PkgPath == \"unsafe\" {\n\t\t\t\t\treturn types.Unsafe, nil // unsafe has no exportdata\n\t\t\t\t}\n\n\t\t\t\tdata, ok := export[imported.ID]\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"missing export data for %s\", importPath)\n\t\t\t\t}\n\t\t\t\treturn gcexportdata.Read(bytes.NewReader(data), pkg.Fset, packages, imported.PkgPath)\n\t\t\t}),\n\t\t}\n\n\t\t// Re-typecheck the syntax and save the export data in the map.\n\t\tnewPkg := types.NewPackage(pkg.PkgPath, pkg.Name)\n\t\tcheck := types.NewChecker(cfg, pkg.Fset, newPkg, nil)\n\t\tcheck.Files(pkg.Syntax)\n\n\t\tvar out bytes.Buffer\n\t\tif err := gcexportdata.Write(&out, pkg.Fset, newPkg); err != nil {\n\t\t\tt.Fatalf(\"internal error writing export data: %v\", err)\n\t\t}\n\t\texport[pkg.ID] = out.Bytes()\n\t})\n}\n"
  },
  {
    "path": "internal/gcimporter/support.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gcimporter\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Copy of $GOROOT/src/cmd/internal/archive.ReadHeader.\nfunc readArchiveHeader(b *bufio.Reader, name string) int {\n\t// architecture-independent object file output\n\tconst HeaderSize = 60\n\n\tvar buf [HeaderSize]byte\n\tif _, err := io.ReadFull(b, buf[:]); err != nil {\n\t\treturn -1\n\t}\n\taname := strings.Trim(string(buf[0:16]), \" \")\n\tif !strings.HasPrefix(aname, name) {\n\t\treturn -1\n\t}\n\tasize := strings.Trim(string(buf[48:58]), \" \")\n\ti, _ := strconv.Atoi(asize)\n\treturn i\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/a/a.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Input for TestIssue13566\n\npackage a\n\nimport \"encoding/json\"\n\ntype A struct {\n\ta    *A\n\tjson json.RawMessage\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/a.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Input for TestIssue13566\n\npackage a\n\nimport \"encoding/json\"\n\ntype A struct {\n\ta    *A\n\tjson json.RawMessage\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/aliases/a/a.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\ntype A[T any] = *T\n\ntype B = struct{ F int }\n\nfunc F() B {\n\ttype a[T any] = struct{ F T }\n\treturn a[int]{}\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/aliases/b/b.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage b\n\nimport \"./a\"\n\ntype B[S any] = struct {\n\tF a.A[[]S]\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/aliases/c/c.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage c\n\nimport (\n\t\"./a\"\n\t\"./b\"\n)\n\ntype c[V any] = struct {\n\tG b.B[[3]V]\n}\n\nvar S struct{ F int } = a.B{}\nvar T struct{ F int } = a.F()\n\nvar U a.A[string] = (*string)(nil)\nvar V a.A[int] = (*int)(nil)\n\nvar W b.B[string] = struct{ F *[]string }{}\nvar X b.B[int] = struct{ F *[]int }{}\n\nvar Y c[string] = struct{ G struct{ F *[][3]string } }{}\nvar Z c[int] = struct{ G struct{ F *[][3]int } }{}\n"
  },
  {
    "path": "internal/gcimporter/testdata/b.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Input for TestIssue13566\n\npackage b\n\nimport \"./a\"\n\ntype A a.A\n"
  },
  {
    "path": "internal/gcimporter/testdata/exports.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is used to generate an object file which\n// serves as test file for gcimporter_test.go.\n\npackage exports\n\nimport (\n\t\"go/ast\"\n)\n\n// Issue 3682: Correctly read dotted identifiers from export data.\nconst init1 = 0\n\nfunc init() {}\n\nconst (\n\tC0 int = 0\n\tC1     = 3.14159265\n\tC2     = 2.718281828i\n\tC3     = -123.456e-789\n\tC4     = +123.456E+789\n\tC5     = 1234i\n\tC6     = \"foo\\n\"\n\tC7     = `bar\\n`\n)\n\ntype (\n\tT1  int\n\tT2  [10]int\n\tT3  []int\n\tT4  *int\n\tT5  chan int\n\tT6a chan<- int\n\tT6b chan (<-chan int)\n\tT6c chan<- (chan int)\n\tT7  <-chan *ast.File\n\tT8  struct{}\n\tT9  struct {\n\t\ta    int\n\t\tb, c float32\n\t\td    []string `go:\"tag\"`\n\t}\n\tT10 struct {\n\t\tT8\n\t\tT9\n\t\t_ *T10\n\t}\n\tT11 map[int]string\n\tT12 interface{}\n\tT13 interface {\n\t\tm1()\n\t\tm2(int) float32\n\t}\n\tT14 interface {\n\t\tT12\n\t\tT13\n\t\tm3(x ...struct{}) []T9\n\t}\n\tT15 func()\n\tT16 func(int)\n\tT17 func(x int)\n\tT18 func() float32\n\tT19 func() (x float32)\n\tT20 func(...interface{})\n\tT21 struct{ next *T21 }\n\tT22 struct{ link *T23 }\n\tT23 struct{ link *T22 }\n\tT24 *T24\n\tT25 *T26\n\tT26 *T27\n\tT27 *T25\n\tT28 func(T28) T28\n)\n\nvar (\n\tV0 int\n\tV1 = -991.0\n)\n\nfunc F1()         {}\nfunc F2(x int)    {}\nfunc F3() int     { return 0 }\nfunc F4() float32 { return 0 }\nfunc F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)\n\nfunc (p *T1) M1()\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue15920.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage p\n\n// The underlying type of Error is the underlying type of error.\n// Make sure we can import this again without problems.\ntype Error error\n\nfunc F() Error { return nil }\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue20046.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage p\n\nvar V interface {\n\tM()\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue25301.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage issue25301\n\ntype (\n\tA = interface {\n\t\tM()\n\t}\n\tT interface {\n\t\tA\n\t}\n\tS struct{}\n)\n\nfunc (S) M() { println(\"m\") }\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue51836/a/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\ntype T[K any] struct {\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue51836/a.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\ntype T[K any] struct {\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue51836/aa.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\nimport (\n\t\"./a\"\n)\n\ntype T[K any] struct {\n\tt a.T[K]\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue57015.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage issue57015\n\ntype E error\n\ntype X[T any] struct {}\n\nfunc F() X[interface {\n\tE\n}] {\n\tpanic(0)\n}\n\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue58296/a/a.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage a\n\ntype A int\n\nfunc (A) f() {}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue58296/b/b.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage b\n\nimport \"./a\"\n\ntype B struct {\n\ta a.A\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/issue58296/c/c.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage c\n\nimport \"./b\"\n\ntype C struct {\n\tb b.B\n}\n"
  },
  {
    "path": "internal/gcimporter/testdata/p.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Input for TestIssue15517\n\npackage p\n\nconst C = 0\n\nvar V int\n\nfunc F() {}\n"
  },
  {
    "path": "internal/gcimporter/testdata/versions/test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is a copy of $GOROOT/src/go/internal/gcimporter/testdata/versions.test.go.\n\n// To create a test case for a new export format version,\n// build this package with the latest compiler and store\n// the resulting .a file appropriately named in the versions\n// directory. The VersionHandling test will pick it up.\n//\n// In the testdata/versions:\n//\n// go build -o test_go1.$X_$Y.a test.go\n//\n// with $X = Go version and $Y = export format version (e.g. 'i', 'u').\n//\n// Make sure this source is extended such that it exercises\n// whatever export format change has taken place.\n\npackage test\n\n// Any release before and including Go 1.7 didn't encode\n// the package for a blank struct field.\ntype BlankField struct {\n\t_ int\n}\n"
  },
  {
    "path": "internal/gcimporter/ureader_yes.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Derived from go/internal/gcimporter/ureader.go\n\npackage gcimporter\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"sort\"\n\n\t\"golang.org/x/tools/internal/aliases\"\n\t\"golang.org/x/tools/internal/pkgbits\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// A pkgReader holds the shared state for reading a unified IR package\n// description.\ntype pkgReader struct {\n\tpkgbits.PkgDecoder\n\n\tfake fakeFileSet\n\n\tctxt    *types.Context\n\timports map[string]*types.Package // previously imported packages, indexed by path\n\n\t// lazily initialized arrays corresponding to the unified IR\n\t// PosBase, Pkg, and Type sections, respectively.\n\tposBases []string // position bases (i.e., file names)\n\tpkgs     []*types.Package\n\ttyps     []types.Type\n\n\t// laterFns holds functions that need to be invoked at the end of\n\t// import reading.\n\tlaterFns []func()\n\t// laterFors is used in case of 'type A B' to ensure that B is processed before A.\n\tlaterFors map[types.Type]int\n\n\t// ifaces holds a list of constructed Interfaces, which need to have\n\t// Complete called after importing is done.\n\tifaces []*types.Interface\n}\n\n// later adds a function to be invoked at the end of import reading.\nfunc (pr *pkgReader) later(fn func()) {\n\tpr.laterFns = append(pr.laterFns, fn)\n}\n\n// See cmd/compile/internal/noder.derivedInfo.\ntype derivedInfo struct {\n\tidx pkgbits.Index\n}\n\n// See cmd/compile/internal/noder.typeInfo.\ntype typeInfo struct {\n\tidx     pkgbits.Index\n\tderived bool\n}\n\nfunc UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {\n\tif !debug {\n\t\tdefer func() {\n\t\t\tif x := recover(); x != nil {\n\t\t\t\terr = fmt.Errorf(\"internal error in importing %q (%v); please report an issue\", path, x)\n\t\t\t}\n\t\t}()\n\t}\n\n\ts := string(data)\n\tinput := pkgbits.NewPkgDecoder(path, s)\n\tpkg = readUnifiedPackage(fset, nil, imports, input)\n\treturn\n}\n\n// laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing.\nfunc (pr *pkgReader) laterFor(t types.Type, fn func()) {\n\tif pr.laterFors == nil {\n\t\tpr.laterFors = make(map[types.Type]int)\n\t}\n\tpr.laterFors[t] = len(pr.laterFns)\n\tpr.laterFns = append(pr.laterFns, fn)\n}\n\n// readUnifiedPackage reads a package description from the given\n// unified IR export data decoder.\nfunc readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {\n\tpr := pkgReader{\n\t\tPkgDecoder: input,\n\n\t\tfake: fakeFileSet{\n\t\t\tfset:  fset,\n\t\t\tfiles: make(map[string]*fileInfo),\n\t\t},\n\n\t\tctxt:    ctxt,\n\t\timports: imports,\n\n\t\tposBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),\n\t\tpkgs:     make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),\n\t\ttyps:     make([]types.Type, input.NumElems(pkgbits.RelocType)),\n\t}\n\tdefer pr.fake.setLines()\n\n\tr := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)\n\tpkg := r.pkg()\n\tif r.Version().Has(pkgbits.HasInit) {\n\t\tr.Bool()\n\t}\n\n\tfor i, n := 0, r.Len(); i < n; i++ {\n\t\t// As if r.obj(), but avoiding the Scope.Lookup call,\n\t\t// to avoid eager loading of imports.\n\t\tr.Sync(pkgbits.SyncObject)\n\t\tif r.Version().Has(pkgbits.DerivedFuncInstance) {\n\t\t\tassert(!r.Bool())\n\t\t}\n\t\tr.p.objIdx(r.Reloc(pkgbits.RelocObj))\n\t\tassert(r.Len() == 0)\n\t}\n\n\tr.Sync(pkgbits.SyncEOF)\n\n\tfor _, fn := range pr.laterFns {\n\t\tfn()\n\t}\n\n\tfor _, iface := range pr.ifaces {\n\t\tiface.Complete()\n\t}\n\n\t// Imports() of pkg are all of the transitive packages that were loaded.\n\tvar imps []*types.Package\n\tfor _, imp := range pr.pkgs {\n\t\tif imp != nil && imp != pkg {\n\t\t\timps = append(imps, imp)\n\t\t}\n\t}\n\tsort.Sort(byPath(imps))\n\tpkg.SetImports(imps)\n\n\tpkg.MarkComplete()\n\treturn pkg\n}\n\n// A reader holds the state for reading a single unified IR element\n// within a package.\ntype reader struct {\n\tpkgbits.Decoder\n\n\tp *pkgReader\n\n\tdict *readerDict\n}\n\n// A readerDict holds the state for type parameters that parameterize\n// the current unified IR element.\ntype readerDict struct {\n\t// bounds is a slice of typeInfos corresponding to the underlying\n\t// bounds of the element's type parameters.\n\tbounds []typeInfo\n\n\t// tparams is a slice of the constructed TypeParams for the element.\n\ttparams []*types.TypeParam\n\n\t// derived is a slice of types derived from tparams, which may be\n\t// instantiated while reading the current element.\n\tderived      []derivedInfo\n\tderivedTypes []types.Type // lazily instantiated from derived\n}\n\nfunc (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {\n\treturn &reader{\n\t\tDecoder: pr.NewDecoder(k, idx, marker),\n\t\tp:       pr,\n\t}\n}\n\nfunc (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {\n\treturn &reader{\n\t\tDecoder: pr.TempDecoder(k, idx, marker),\n\t\tp:       pr,\n\t}\n}\n\nfunc (pr *pkgReader) retireReader(r *reader) {\n\tpr.RetireDecoder(&r.Decoder)\n}\n\n// @@@ Positions\n\nfunc (r *reader) pos() token.Pos {\n\tr.Sync(pkgbits.SyncPos)\n\tif !r.Bool() {\n\t\treturn token.NoPos\n\t}\n\n\t// TODO(mdempsky): Delta encoding.\n\tposBase := r.posBase()\n\tline := r.Uint()\n\tcol := r.Uint()\n\treturn r.p.fake.pos(posBase, int(line), int(col))\n}\n\nfunc (r *reader) posBase() string {\n\treturn r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))\n}\n\nfunc (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {\n\tif b := pr.posBases[idx]; b != \"\" {\n\t\treturn b\n\t}\n\n\tvar filename string\n\t{\n\t\tr := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)\n\n\t\t// Within types2, position bases have a lot more details (e.g.,\n\t\t// keeping track of where //line directives appeared exactly).\n\t\t//\n\t\t// For go/types, we just track the file name.\n\n\t\tfilename = r.String()\n\n\t\tif r.Bool() { // file base\n\t\t\t// Was: \"b = token.NewTrimmedFileBase(filename, true)\"\n\t\t} else { // line base\n\t\t\tpos := r.pos()\n\t\t\tline := r.Uint()\n\t\t\tcol := r.Uint()\n\n\t\t\t// Was: \"b = token.NewLineBase(pos, filename, true, line, col)\"\n\t\t\t_, _, _ = pos, line, col\n\t\t}\n\t\tpr.retireReader(r)\n\t}\n\tb := filename\n\tpr.posBases[idx] = b\n\treturn b\n}\n\n// @@@ Packages\n\nfunc (r *reader) pkg() *types.Package {\n\tr.Sync(pkgbits.SyncPkg)\n\treturn r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))\n}\n\nfunc (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {\n\t// TODO(mdempsky): Consider using some non-nil pointer to indicate\n\t// the universe scope, so we don't need to keep re-reading it.\n\tif pkg := pr.pkgs[idx]; pkg != nil {\n\t\treturn pkg\n\t}\n\n\tpkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()\n\tpr.pkgs[idx] = pkg\n\treturn pkg\n}\n\nfunc (r *reader) doPkg() *types.Package {\n\tpath := r.String()\n\tswitch path {\n\t// cmd/compile emits path=\"main\" for main packages because\n\t// that's the linker symbol prefix it used; but we need\n\t// the package's path as it would be reported by go list,\n\t// hence \"main\" below.\n\t// See test at go/packages.TestMainPackagePathInModeTypes.\n\tcase \"\", \"main\":\n\t\tpath = r.p.PkgPath()\n\tcase \"builtin\":\n\t\treturn nil // universe\n\tcase \"unsafe\":\n\t\treturn types.Unsafe\n\t}\n\n\tif pkg := r.p.imports[path]; pkg != nil {\n\t\treturn pkg\n\t}\n\n\tname := r.String()\n\n\tpkg := types.NewPackage(path, name)\n\tr.p.imports[path] = pkg\n\n\treturn pkg\n}\n\n// @@@ Types\n\nfunc (r *reader) typ() types.Type {\n\treturn r.p.typIdx(r.typInfo(), r.dict)\n}\n\nfunc (r *reader) typInfo() typeInfo {\n\tr.Sync(pkgbits.SyncType)\n\tif r.Bool() {\n\t\treturn typeInfo{idx: pkgbits.Index(r.Len()), derived: true}\n\t}\n\treturn typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}\n}\n\nfunc (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {\n\tidx := info.idx\n\tvar where *types.Type\n\tif info.derived {\n\t\twhere = &dict.derivedTypes[idx]\n\t\tidx = dict.derived[idx].idx\n\t} else {\n\t\twhere = &pr.typs[idx]\n\t}\n\n\tif typ := *where; typ != nil {\n\t\treturn typ\n\t}\n\n\tvar typ types.Type\n\t{\n\t\tr := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)\n\t\tr.dict = dict\n\n\t\ttyp = r.doTyp()\n\t\tassert(typ != nil)\n\t\tpr.retireReader(r)\n\t}\n\t// See comment in pkgReader.typIdx explaining how this happens.\n\tif prev := *where; prev != nil {\n\t\treturn prev\n\t}\n\n\t*where = typ\n\treturn typ\n}\n\nfunc (r *reader) doTyp() (res types.Type) {\n\tswitch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {\n\tdefault:\n\t\terrorf(\"unhandled type tag: %v\", tag)\n\t\tpanic(\"unreachable\")\n\n\tcase pkgbits.TypeBasic:\n\t\treturn types.Typ[r.Len()]\n\n\tcase pkgbits.TypeNamed:\n\t\tobj, targs := r.obj()\n\t\tname := obj.(*types.TypeName)\n\t\tif len(targs) != 0 {\n\t\t\tt, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false)\n\t\t\treturn t\n\t\t}\n\t\treturn name.Type()\n\n\tcase pkgbits.TypeTypeParam:\n\t\treturn r.dict.tparams[r.Len()]\n\n\tcase pkgbits.TypeArray:\n\t\tlen := int64(r.Uint64())\n\t\treturn types.NewArray(r.typ(), len)\n\tcase pkgbits.TypeChan:\n\t\tdir := types.ChanDir(r.Len())\n\t\treturn types.NewChan(dir, r.typ())\n\tcase pkgbits.TypeMap:\n\t\treturn types.NewMap(r.typ(), r.typ())\n\tcase pkgbits.TypePointer:\n\t\treturn types.NewPointer(r.typ())\n\tcase pkgbits.TypeSignature:\n\t\treturn r.signature(nil, nil, nil)\n\tcase pkgbits.TypeSlice:\n\t\treturn types.NewSlice(r.typ())\n\tcase pkgbits.TypeStruct:\n\t\treturn r.structType()\n\tcase pkgbits.TypeInterface:\n\t\treturn r.interfaceType()\n\tcase pkgbits.TypeUnion:\n\t\treturn r.unionType()\n\t}\n}\n\nfunc (r *reader) structType() *types.Struct {\n\tfields := make([]*types.Var, r.Len())\n\tvar tags []string\n\tfor i := range fields {\n\t\tpos := r.pos()\n\t\tpkg, name := r.selector()\n\t\tftyp := r.typ()\n\t\ttag := r.String()\n\t\tembedded := r.Bool()\n\n\t\tfields[i] = types.NewField(pos, pkg, name, ftyp, embedded)\n\t\tif tag != \"\" {\n\t\t\tfor len(tags) < i {\n\t\t\t\ttags = append(tags, \"\")\n\t\t\t}\n\t\t\ttags = append(tags, tag)\n\t\t}\n\t}\n\treturn types.NewStruct(fields, tags)\n}\n\nfunc (r *reader) unionType() *types.Union {\n\tterms := make([]*types.Term, r.Len())\n\tfor i := range terms {\n\t\tterms[i] = types.NewTerm(r.Bool(), r.typ())\n\t}\n\treturn types.NewUnion(terms)\n}\n\nfunc (r *reader) interfaceType() *types.Interface {\n\tmethods := make([]*types.Func, r.Len())\n\tembeddeds := make([]types.Type, r.Len())\n\timplicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()\n\n\tfor i := range methods {\n\t\tpos := r.pos()\n\t\tpkg, name := r.selector()\n\t\tmtyp := r.signature(nil, nil, nil)\n\t\tmethods[i] = types.NewFunc(pos, pkg, name, mtyp)\n\t}\n\n\tfor i := range embeddeds {\n\t\tembeddeds[i] = r.typ()\n\t}\n\n\tiface := types.NewInterfaceType(methods, embeddeds)\n\tif implicit {\n\t\tiface.MarkImplicit()\n\t}\n\n\t// We need to call iface.Complete(), but if there are any embedded\n\t// defined types, then we may not have set their underlying\n\t// interface type yet. So we need to defer calling Complete until\n\t// after we've called SetUnderlying everywhere.\n\t//\n\t// TODO(mdempsky): After CL 424876 lands, it should be safe to call\n\t// iface.Complete() immediately.\n\tr.p.ifaces = append(r.p.ifaces, iface)\n\n\treturn iface\n}\n\nfunc (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature {\n\tr.Sync(pkgbits.SyncSignature)\n\n\tparams := r.params()\n\tresults := r.params()\n\tvariadic := r.Bool()\n\n\treturn types.NewSignatureType(recv, rtparams, tparams, params, results, variadic)\n}\n\nfunc (r *reader) params() *types.Tuple {\n\tr.Sync(pkgbits.SyncParams)\n\n\tparams := make([]*types.Var, r.Len())\n\tfor i := range params {\n\t\tparams[i] = r.param()\n\t}\n\n\treturn types.NewTuple(params...)\n}\n\nfunc (r *reader) param() *types.Var {\n\tr.Sync(pkgbits.SyncParam)\n\n\tpos := r.pos()\n\tpkg, name := r.localIdent()\n\ttyp := r.typ()\n\n\treturn types.NewParam(pos, pkg, name, typ)\n}\n\n// @@@ Objects\n\nfunc (r *reader) obj() (types.Object, []types.Type) {\n\tr.Sync(pkgbits.SyncObject)\n\n\tif r.Version().Has(pkgbits.DerivedFuncInstance) {\n\t\tassert(!r.Bool())\n\t}\n\n\tpkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))\n\tobj := pkgScope(pkg).Lookup(name)\n\n\ttargs := make([]types.Type, r.Len())\n\tfor i := range targs {\n\t\ttargs[i] = r.typ()\n\t}\n\n\treturn obj, targs\n}\n\nfunc (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {\n\n\tvar objPkg *types.Package\n\tvar objName string\n\tvar tag pkgbits.CodeObj\n\t{\n\t\trname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)\n\n\t\tobjPkg, objName = rname.qualifiedIdent()\n\t\tassert(objName != \"\")\n\n\t\ttag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))\n\t\tpr.retireReader(rname)\n\t}\n\n\tif tag == pkgbits.ObjStub {\n\t\tassert(objPkg == nil || objPkg == types.Unsafe)\n\t\treturn objPkg, objName\n\t}\n\n\t// Ignore local types promoted to global scope (#55110).\n\tif _, suffix := splitVargenSuffix(objName); suffix != \"\" {\n\t\treturn objPkg, objName\n\t}\n\n\tif objPkg.Scope().Lookup(objName) == nil {\n\t\tdict := pr.objDictIdx(idx)\n\n\t\tr := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)\n\t\tr.dict = dict\n\n\t\tdeclare := func(obj types.Object) {\n\t\t\tobjPkg.Scope().Insert(obj)\n\t\t}\n\n\t\tswitch tag {\n\t\tdefault:\n\t\t\tpanic(\"weird\")\n\n\t\tcase pkgbits.ObjAlias:\n\t\t\tpos := r.pos()\n\t\t\tvar tparams []*types.TypeParam\n\t\t\tif r.Version().Has(pkgbits.AliasTypeParamNames) {\n\t\t\t\ttparams = r.typeParamNames()\n\t\t\t}\n\t\t\ttyp := r.typ()\n\t\t\tdeclare(aliases.New(pos, objPkg, objName, typ, tparams))\n\n\t\tcase pkgbits.ObjConst:\n\t\t\tpos := r.pos()\n\t\t\ttyp := r.typ()\n\t\t\tval := r.Value()\n\t\t\tdeclare(types.NewConst(pos, objPkg, objName, typ, val))\n\n\t\tcase pkgbits.ObjFunc:\n\t\t\tpos := r.pos()\n\t\t\ttparams := r.typeParamNames()\n\t\t\tsig := r.signature(nil, nil, tparams)\n\t\t\tdeclare(types.NewFunc(pos, objPkg, objName, sig))\n\n\t\tcase pkgbits.ObjType:\n\t\t\tpos := r.pos()\n\n\t\t\tobj := types.NewTypeName(pos, objPkg, objName, nil)\n\t\t\tnamed := types.NewNamed(obj, nil, nil)\n\t\t\tdeclare(obj)\n\n\t\t\tnamed.SetTypeParams(r.typeParamNames())\n\n\t\t\tsetUnderlying := func(underlying types.Type) {\n\t\t\t\t// If the underlying type is an interface, we need to\n\t\t\t\t// duplicate its methods so we can replace the receiver\n\t\t\t\t// parameter's type (#49906).\n\t\t\t\tif iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {\n\t\t\t\t\tmethods := make([]*types.Func, iface.NumExplicitMethods())\n\t\t\t\t\tfor i := range methods {\n\t\t\t\t\t\tfn := iface.ExplicitMethod(i)\n\t\t\t\t\t\tsig := fn.Type().(*types.Signature)\n\n\t\t\t\t\t\trecv := types.NewVar(fn.Pos(), fn.Pkg(), \"\", named)\n\t\t\t\t\t\ttypesinternal.SetVarKind(recv, typesinternal.RecvVar)\n\t\t\t\t\t\tmethods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignatureType(recv, nil, nil, sig.Params(), sig.Results(), sig.Variadic()))\n\t\t\t\t\t}\n\n\t\t\t\t\tembeds := make([]types.Type, iface.NumEmbeddeds())\n\t\t\t\t\tfor i := range embeds {\n\t\t\t\t\t\tembeds[i] = iface.EmbeddedType(i)\n\t\t\t\t\t}\n\n\t\t\t\t\tnewIface := types.NewInterfaceType(methods, embeds)\n\t\t\t\t\tr.p.ifaces = append(r.p.ifaces, newIface)\n\t\t\t\t\tunderlying = newIface\n\t\t\t\t}\n\n\t\t\t\tnamed.SetUnderlying(underlying)\n\t\t\t}\n\n\t\t\t// Since go.dev/cl/455279, we can assume rhs.Underlying() will\n\t\t\t// always be non-nil. However, to temporarily support users of\n\t\t\t// older snapshot releases, we continue to fallback to the old\n\t\t\t// behavior for now.\n\t\t\t//\n\t\t\t// TODO(mdempsky): Remove fallback code and simplify after\n\t\t\t// allowing time for snapshot users to upgrade.\n\t\t\trhs := r.typ()\n\t\t\tif underlying := rhs.Underlying(); underlying != nil {\n\t\t\t\tsetUnderlying(underlying)\n\t\t\t} else {\n\t\t\t\tpk := r.p\n\t\t\t\tpk.laterFor(named, func() {\n\t\t\t\t\t// First be sure that the rhs is initialized, if it needs to be initialized.\n\t\t\t\t\tdelete(pk.laterFors, named) // prevent cycles\n\t\t\t\t\tif i, ok := pk.laterFors[rhs]; ok {\n\t\t\t\t\t\tf := pk.laterFns[i]\n\t\t\t\t\t\tpk.laterFns[i] = func() {} // function is running now, so replace it with a no-op\n\t\t\t\t\t\tf()                        // initialize RHS\n\t\t\t\t\t}\n\t\t\t\t\tsetUnderlying(rhs.Underlying())\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfor i, n := 0, r.Len(); i < n; i++ {\n\t\t\t\tnamed.AddMethod(r.method())\n\t\t\t}\n\n\t\tcase pkgbits.ObjVar:\n\t\t\tpos := r.pos()\n\t\t\ttyp := r.typ()\n\t\t\tv := types.NewVar(pos, objPkg, objName, typ)\n\t\t\ttypesinternal.SetVarKind(v, typesinternal.PackageVar)\n\t\t\tdeclare(v)\n\t\t}\n\t}\n\n\treturn objPkg, objName\n}\n\nfunc (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {\n\n\tvar dict readerDict\n\n\t{\n\t\tr := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)\n\t\tif implicits := r.Len(); implicits != 0 {\n\t\t\terrorf(\"unexpected object with %v implicit type parameter(s)\", implicits)\n\t\t}\n\n\t\tdict.bounds = make([]typeInfo, r.Len())\n\t\tfor i := range dict.bounds {\n\t\t\tdict.bounds[i] = r.typInfo()\n\t\t}\n\n\t\tdict.derived = make([]derivedInfo, r.Len())\n\t\tdict.derivedTypes = make([]types.Type, len(dict.derived))\n\t\tfor i := range dict.derived {\n\t\t\tdict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)}\n\t\t\tif r.Version().Has(pkgbits.DerivedInfoNeeded) {\n\t\t\t\tassert(!r.Bool())\n\t\t\t}\n\t\t}\n\n\t\tpr.retireReader(r)\n\t}\n\t// function references follow, but reader doesn't need those\n\n\treturn &dict\n}\n\nfunc (r *reader) typeParamNames() []*types.TypeParam {\n\tr.Sync(pkgbits.SyncTypeParamNames)\n\n\t// Note: This code assumes it only processes objects without\n\t// implement type parameters. This is currently fine, because\n\t// reader is only used to read in exported declarations, which are\n\t// always package scoped.\n\n\tif len(r.dict.bounds) == 0 {\n\t\treturn nil\n\t}\n\n\t// Careful: Type parameter lists may have cycles. To allow for this,\n\t// we construct the type parameter list in two passes: first we\n\t// create all the TypeNames and TypeParams, then we construct and\n\t// set the bound type.\n\n\tr.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds))\n\tfor i := range r.dict.bounds {\n\t\tpos := r.pos()\n\t\tpkg, name := r.localIdent()\n\n\t\ttname := types.NewTypeName(pos, pkg, name, nil)\n\t\tr.dict.tparams[i] = types.NewTypeParam(tname, nil)\n\t}\n\n\ttyps := make([]types.Type, len(r.dict.bounds))\n\tfor i, bound := range r.dict.bounds {\n\t\ttyps[i] = r.p.typIdx(bound, r.dict)\n\t}\n\n\t// TODO(mdempsky): This is subtle, elaborate further.\n\t//\n\t// We have to save tparams outside of the closure, because\n\t// typeParamNames() can be called multiple times with the same\n\t// dictionary instance.\n\t//\n\t// Also, this needs to happen later to make sure SetUnderlying has\n\t// been called.\n\t//\n\t// TODO(mdempsky): Is it safe to have a single \"later\" slice or do\n\t// we need to have multiple passes? See comments on CL 386002 and\n\t// go.dev/issue/52104.\n\ttparams := r.dict.tparams\n\tr.p.later(func() {\n\t\tfor i, typ := range typs {\n\t\t\ttparams[i].SetConstraint(typ)\n\t\t}\n\t})\n\n\treturn r.dict.tparams\n}\n\nfunc (r *reader) method() *types.Func {\n\tr.Sync(pkgbits.SyncMethod)\n\tpos := r.pos()\n\tpkg, name := r.selector()\n\n\trparams := r.typeParamNames()\n\tsig := r.signature(r.param(), rparams, nil)\n\n\t_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.\n\treturn types.NewFunc(pos, pkg, name, sig)\n}\n\nfunc (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) }\nfunc (r *reader) localIdent() (*types.Package, string)     { return r.ident(pkgbits.SyncLocalIdent) }\nfunc (r *reader) selector() (*types.Package, string)       { return r.ident(pkgbits.SyncSelector) }\n\nfunc (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) {\n\tr.Sync(marker)\n\treturn r.pkg(), r.String()\n}\n\n// pkgScope returns pkg.Scope().\n// If pkg is nil, it returns types.Universe instead.\n//\n// TODO(mdempsky): Remove after x/tools can depend on Go 1.19.\nfunc pkgScope(pkg *types.Package) *types.Scope {\n\tif pkg != nil {\n\t\treturn pkg.Scope()\n\t}\n\treturn types.Universe\n}\n\n// See cmd/compile/internal/types.SplitVargenSuffix.\nfunc splitVargenSuffix(name string) (base, suffix string) {\n\ti := len(name)\n\tfor i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {\n\t\ti--\n\t}\n\tconst dot = \"·\"\n\tif i >= len(dot) && name[i-len(dot):i] == dot {\n\t\ti -= len(dot)\n\t\treturn name[:i], name[i:]\n\t}\n\treturn name, \"\"\n}\n"
  },
  {
    "path": "internal/gocommand/invoke.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gocommand is a helper for calling the go command.\npackage gocommand\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/keys\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// A Runner will run go command invocations and serialize\n// them if it sees a concurrency error.\ntype Runner struct {\n\t// once guards the runner initialization.\n\tonce sync.Once\n\n\t// inFlight tracks available workers.\n\tinFlight chan struct{}\n\n\t// serialized guards the ability to run a go command serially,\n\t// to avoid deadlocks when claiming workers.\n\tserialized chan struct{}\n}\n\nconst maxInFlight = 10\n\nfunc (runner *Runner) initialize() {\n\trunner.once.Do(func() {\n\t\trunner.inFlight = make(chan struct{}, maxInFlight)\n\t\trunner.serialized = make(chan struct{}, 1)\n\t})\n}\n\n// 1.13: go: updates to go.mod needed, but contents have changed\n// 1.14: go: updating go.mod: existing contents have changed since last read\nvar modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)\n\n// event keys for go command invocations\nvar (\n\tverb      = keys.NewString(\"verb\", \"go command verb\")\n\tdirectory = keys.NewString(\"directory\", \"\")\n)\n\nfunc invLabels(inv Invocation) []label.Label {\n\treturn []label.Label{verb.Of(inv.Verb), directory.Of(inv.WorkingDir)}\n}\n\n// Run is a convenience wrapper around RunRaw.\n// It returns only stdout and a \"friendly\" error.\nfunc (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, error) {\n\tctx, done := event.Start(ctx, \"gocommand.Runner.Run\", invLabels(inv)...)\n\tdefer done()\n\n\tstdout, _, friendly, _ := runner.RunRaw(ctx, inv)\n\treturn stdout, friendly\n}\n\n// RunPiped runs the invocation serially, always waiting for any concurrent\n// invocations to complete first.\nfunc (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) error {\n\tctx, done := event.Start(ctx, \"gocommand.Runner.RunPiped\", invLabels(inv)...)\n\tdefer done()\n\n\t_, err := runner.runPiped(ctx, inv, stdout, stderr)\n\treturn err\n}\n\n// RunRaw runs the invocation, serializing requests only if they fight over\n// go.mod changes.\n// Postcondition: both error results have same nilness.\nfunc (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {\n\tctx, done := event.Start(ctx, \"gocommand.Runner.RunRaw\", invLabels(inv)...)\n\tdefer done()\n\t// Make sure the runner is always initialized.\n\trunner.initialize()\n\n\t// First, try to run the go command concurrently.\n\tstdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv)\n\n\t// If we encounter a load concurrency error, we need to retry serially.\n\tif friendlyErr != nil && modConcurrencyError.MatchString(friendlyErr.Error()) {\n\t\tevent.Error(ctx, \"Load concurrency error, will retry serially\", err)\n\n\t\t// Run serially by calling runPiped.\n\t\tstdout.Reset()\n\t\tstderr.Reset()\n\t\tfriendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr)\n\t}\n\n\treturn stdout, stderr, friendlyErr, err\n}\n\n// Postcondition: both error results have same nilness.\nfunc (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {\n\t// Wait for 1 worker to become available.\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, nil, ctx.Err(), ctx.Err()\n\tcase runner.inFlight <- struct{}{}:\n\t\tdefer func() { <-runner.inFlight }()\n\t}\n\n\tstdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}\n\tfriendlyErr, err := inv.runWithFriendlyError(ctx, stdout, stderr)\n\treturn stdout, stderr, friendlyErr, err\n}\n\n// Postcondition: both error results have same nilness.\nfunc (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) {\n\t// Make sure the runner is always initialized.\n\trunner.initialize()\n\n\t// Acquire the serialization lock. This avoids deadlocks between two\n\t// runPiped commands.\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err(), ctx.Err()\n\tcase runner.serialized <- struct{}{}:\n\t\tdefer func() { <-runner.serialized }()\n\t}\n\n\t// Wait for all in-progress go commands to return before proceeding,\n\t// to avoid load concurrency errors.\n\tfor range maxInFlight {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err(), ctx.Err()\n\t\tcase runner.inFlight <- struct{}{}:\n\t\t\t// Make sure we always \"return\" any workers we took.\n\t\t\tdefer func() { <-runner.inFlight }()\n\t\t}\n\t}\n\n\treturn inv.runWithFriendlyError(ctx, stdout, stderr)\n}\n\n// An Invocation represents a call to the go command.\ntype Invocation struct {\n\tVerb       string\n\tArgs       []string\n\tBuildFlags []string\n\n\t// If ModFlag is set, the go command is invoked with -mod=ModFlag.\n\t// TODO(rfindley): remove, in favor of Args.\n\tModFlag string\n\n\t// If ModFile is set, the go command is invoked with -modfile=ModFile.\n\t// TODO(rfindley): remove, in favor of Args.\n\tModFile string\n\n\t// Overlay is the name of the JSON overlay file that describes\n\t// unsaved editor buffers; see [WriteOverlays].\n\t// If set, the go command is invoked with -overlay=Overlay.\n\t// TODO(rfindley): remove, in favor of Args.\n\tOverlay string\n\n\t// If CleanEnv is set, the invocation will run only with the environment\n\t// in Env, not starting with os.Environ.\n\tCleanEnv   bool\n\tEnv        []string\n\tWorkingDir string\n\tLogf       func(format string, args ...any)\n}\n\n// Postcondition: both error results have same nilness.\nfunc (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) {\n\trawError = i.run(ctx, stdout, stderr)\n\tif rawError != nil {\n\t\tfriendlyError = rawError\n\t\t// Check for 'go' executable not being found.\n\t\tif ee, ok := rawError.(*exec.Error); ok && ee.Err == exec.ErrNotFound {\n\t\t\tfriendlyError = fmt.Errorf(\"go command required, not found: %v\", ee)\n\t\t}\n\t\tif ctx.Err() != nil {\n\t\t\tfriendlyError = ctx.Err()\n\t\t}\n\t\tfriendlyError = fmt.Errorf(\"err: %v: stderr: %s\", friendlyError, stderr)\n\t}\n\treturn\n}\n\n// logf logs if i.Logf is non-nil.\nfunc (i *Invocation) logf(format string, args ...any) {\n\tif i.Logf != nil {\n\t\ti.Logf(format, args...)\n\t}\n}\n\nfunc (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {\n\tgoArgs := []string{i.Verb}\n\n\tappendModFile := func() {\n\t\tif i.ModFile != \"\" {\n\t\t\tgoArgs = append(goArgs, \"-modfile=\"+i.ModFile)\n\t\t}\n\t}\n\tappendModFlag := func() {\n\t\tif i.ModFlag != \"\" {\n\t\t\tgoArgs = append(goArgs, \"-mod=\"+i.ModFlag)\n\t\t}\n\t}\n\tappendOverlayFlag := func() {\n\t\tif i.Overlay != \"\" {\n\t\t\tgoArgs = append(goArgs, \"-overlay=\"+i.Overlay)\n\t\t}\n\t}\n\n\tswitch i.Verb {\n\tcase \"env\", \"version\":\n\t\tgoArgs = append(goArgs, i.Args...)\n\tcase \"mod\":\n\t\t// mod needs the sub-verb before flags.\n\t\tgoArgs = append(goArgs, i.Args[0])\n\t\tappendModFile()\n\t\tgoArgs = append(goArgs, i.Args[1:]...)\n\tcase \"get\":\n\t\tgoArgs = append(goArgs, i.BuildFlags...)\n\t\tappendModFile()\n\t\tgoArgs = append(goArgs, i.Args...)\n\n\tdefault: // notably list and build.\n\t\tgoArgs = append(goArgs, i.BuildFlags...)\n\t\tappendModFile()\n\t\tappendModFlag()\n\t\tappendOverlayFlag()\n\t\tgoArgs = append(goArgs, i.Args...)\n\t}\n\tcmd := exec.Command(\"go\", goArgs...)\n\tcmd.Stdout = stdout\n\tcmd.Stderr = stderr\n\n\t// https://go.dev/issue/59541: don't wait forever copying stderr\n\t// after the command has exited.\n\t// After CL 484741 we copy stdout manually, so we we'll stop reading that as\n\t// soon as ctx is done. However, we also don't want to wait around forever\n\t// for stderr. Give a much-longer-than-reasonable delay and then assume that\n\t// something has wedged in the kernel or runtime.\n\tcmd.WaitDelay = 30 * time.Second\n\n\t// The cwd gets resolved to the real path. On Darwin, where\n\t// /tmp is a symlink, this breaks anything that expects the\n\t// working directory to keep the original path, including the\n\t// go command when dealing with modules.\n\t//\n\t// os.Getwd has a special feature where if the cwd and the PWD\n\t// are the same node then it trusts the PWD, so by setting it\n\t// in the env for the child process we fix up all the paths\n\t// returned by the go command.\n\tif !i.CleanEnv {\n\t\tcmd.Env = os.Environ()\n\t}\n\tcmd.Env = append(cmd.Env, i.Env...)\n\tif i.WorkingDir != \"\" {\n\t\tcmd.Env = append(cmd.Env, \"PWD=\"+i.WorkingDir)\n\t\tcmd.Dir = i.WorkingDir\n\t}\n\n\tdebugStr := cmdDebugStr(cmd)\n\ti.logf(\"starting %v\", debugStr)\n\tstart := time.Now()\n\tdefer func() {\n\t\ti.logf(\"%s for %v\", time.Since(start), debugStr)\n\t}()\n\n\treturn runCmdContext(ctx, cmd)\n}\n\n// DebugHangingGoCommands may be set by tests to enable additional\n// instrumentation (including panics) for debugging hanging Go commands.\n//\n// See golang/go#54461 for details.\nvar DebugHangingGoCommands = false\n\n// runCmdContext is like exec.CommandContext except it sends os.Interrupt\n// before os.Kill.\nfunc runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {\n\t// If cmd.Stdout is not an *os.File, the exec package will create a pipe and\n\t// copy it to the Writer in a goroutine until the process has finished and\n\t// either the pipe reaches EOF or command's WaitDelay expires.\n\t//\n\t// However, the output from 'go list' can be quite large, and we don't want to\n\t// keep reading (and allocating buffers) if we've already decided we don't\n\t// care about the output. We don't want to wait for the process to finish, and\n\t// we don't wait to wait for the WaitDelay to expire either.\n\t//\n\t// Instead, if cmd.Stdout requires a copying goroutine we explicitly replace\n\t// it with a pipe (which is an *os.File), which we can close in order to stop\n\t// copying output as soon as we realize we don't care about it.\n\tvar stdoutW *os.File\n\tif cmd.Stdout != nil {\n\t\tif _, ok := cmd.Stdout.(*os.File); !ok {\n\t\t\tvar stdoutR *os.File\n\t\t\tstdoutR, stdoutW, err = os.Pipe()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tprevStdout := cmd.Stdout\n\t\t\tcmd.Stdout = stdoutW\n\n\t\t\tstdoutErr := make(chan error, 1)\n\t\t\tgo func() {\n\t\t\t\t_, err := io.Copy(prevStdout, stdoutR)\n\t\t\t\tif err != nil {\n\t\t\t\t\terr = fmt.Errorf(\"copying stdout: %w\", err)\n\t\t\t\t}\n\t\t\t\tstdoutErr <- err\n\t\t\t}()\n\t\t\tdefer func() {\n\t\t\t\t// We started a goroutine to copy a stdout pipe.\n\t\t\t\t// Wait for it to finish, or terminate it if need be.\n\t\t\t\tvar err2 error\n\t\t\t\tselect {\n\t\t\t\tcase err2 = <-stdoutErr:\n\t\t\t\t\tstdoutR.Close()\n\t\t\t\tcase <-ctx.Done():\n\t\t\t\t\tstdoutR.Close()\n\t\t\t\t\t// Per https://pkg.go.dev/os#File.Close, the call to stdoutR.Close\n\t\t\t\t\t// should cause the Read call in io.Copy to unblock and return\n\t\t\t\t\t// immediately, but we still need to receive from stdoutErr to confirm\n\t\t\t\t\t// that it has happened.\n\t\t\t\t\t<-stdoutErr\n\t\t\t\t\terr2 = ctx.Err()\n\t\t\t\t}\n\t\t\t\tif err == nil {\n\t\t\t\t\terr = err2\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\t// Per https://pkg.go.dev/os/exec#Cmd, “If Stdout and Stderr are the\n\t\t\t// same writer, and have a type that can be compared with ==, at most\n\t\t\t// one goroutine at a time will call Write.”\n\t\t\t//\n\t\t\t// Since we're starting a goroutine that writes to cmd.Stdout, we must\n\t\t\t// also update cmd.Stderr so that it still holds.\n\t\t\tfunc() {\n\t\t\t\tdefer func() { recover() }()\n\t\t\t\tif cmd.Stderr == prevStdout {\n\t\t\t\t\tcmd.Stderr = cmd.Stdout\n\t\t\t\t}\n\t\t\t}()\n\t\t}\n\t}\n\n\tstartTime := time.Now()\n\terr = cmd.Start()\n\tif stdoutW != nil {\n\t\t// The child process has inherited the pipe file,\n\t\t// so close the copy held in this process.\n\t\tstdoutW.Close()\n\t\tstdoutW = nil\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tresChan := make(chan error, 1)\n\tgo func() {\n\t\tresChan <- cmd.Wait()\n\t}()\n\n\t// If we're interested in debugging hanging Go commands, stop waiting after a\n\t// minute and panic with interesting information.\n\tdebug := DebugHangingGoCommands\n\tif debug {\n\t\ttimer := time.NewTimer(1 * time.Minute)\n\t\tdefer timer.Stop()\n\t\tselect {\n\t\tcase err := <-resChan:\n\t\t\treturn err\n\t\tcase <-timer.C:\n\t\t\t// HandleHangingGoCommand terminates this process.\n\t\t\t// Pass off resChan in case we can collect the command error.\n\t\t\thandleHangingGoCommand(startTime, cmd, resChan)\n\t\tcase <-ctx.Done():\n\t\t}\n\t} else {\n\t\tselect {\n\t\tcase err := <-resChan:\n\t\t\treturn err\n\t\tcase <-ctx.Done():\n\t\t}\n\t}\n\n\t// Cancelled. Interrupt and see if it ends voluntarily.\n\tif err := cmd.Process.Signal(os.Interrupt); err == nil {\n\t\t// (We used to wait only 1s but this proved\n\t\t// fragile on loaded builder machines.)\n\t\ttimer := time.NewTimer(5 * time.Second)\n\t\tdefer timer.Stop()\n\t\tselect {\n\t\tcase err := <-resChan:\n\t\t\treturn err\n\t\tcase <-timer.C:\n\t\t}\n\t}\n\n\t// Didn't shut down in response to interrupt. Kill it hard.\n\tif err := cmd.Process.Kill(); err != nil && !errors.Is(err, os.ErrProcessDone) && debug {\n\t\tlog.Printf(\"error killing the Go command: %v\", err)\n\t}\n\n\treturn <-resChan\n}\n\n// handleHangingGoCommand outputs debugging information to help diagnose the\n// cause of a hanging Go command, and then exits with log.Fatalf.\nfunc handleHangingGoCommand(start time.Time, cmd *exec.Cmd, resChan chan error) {\n\tswitch runtime.GOOS {\n\tcase \"linux\", \"darwin\", \"freebsd\", \"netbsd\", \"openbsd\":\n\t\tfmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND\n\n\t\t\tThe gopls test runner has detected a hanging go command. In order to debug\n\t\t\tthis, the output of ps and lsof/fstat is printed below.\n\n\t\t\tSee golang/go#54461 for more details.`)\n\n\t\tfmt.Fprintln(os.Stderr, \"\\nps axo ppid,pid,command:\")\n\t\tfmt.Fprintln(os.Stderr, \"-------------------------\")\n\t\tpsCmd := exec.Command(\"ps\", \"axo\", \"ppid,pid,command\")\n\t\tpsCmd.Stdout = os.Stderr\n\t\tpsCmd.Stderr = os.Stderr\n\t\tif err := psCmd.Run(); err != nil {\n\t\t\tlog.Printf(\"Handling hanging Go command: running ps: %v\", err)\n\t\t}\n\n\t\tlistFiles := \"lsof\"\n\t\tif runtime.GOOS == \"freebsd\" || runtime.GOOS == \"netbsd\" {\n\t\t\tlistFiles = \"fstat\"\n\t\t}\n\n\t\tfmt.Fprintln(os.Stderr, \"\\n\"+listFiles+\":\")\n\t\tfmt.Fprintln(os.Stderr, \"-----\")\n\t\tlistFilesCmd := exec.Command(listFiles)\n\t\tlistFilesCmd.Stdout = os.Stderr\n\t\tlistFilesCmd.Stderr = os.Stderr\n\t\tif err := listFilesCmd.Run(); err != nil {\n\t\t\tlog.Printf(\"Handling hanging Go command: running %s: %v\", listFiles, err)\n\t\t}\n\t\t// Try to extract information about the slow go process by issuing a SIGQUIT.\n\t\tif err := cmd.Process.Signal(sigStuckProcess); err == nil {\n\t\t\tselect {\n\t\t\tcase err := <-resChan:\n\t\t\t\tstderr := \"not a bytes.Buffer\"\n\t\t\t\tif buf, _ := cmd.Stderr.(*bytes.Buffer); buf != nil {\n\t\t\t\t\tstderr = buf.String()\n\t\t\t\t}\n\t\t\t\tlog.Printf(\"Quit hanging go command:\\n\\terr:%v\\n\\tstderr:\\n%v\\n\\n\", err, stderr)\n\t\t\tcase <-time.After(5 * time.Second):\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Printf(\"Sending signal %d to hanging go command: %v\", sigStuckProcess, err)\n\t\t}\n\t}\n\tlog.Fatalf(\"detected hanging go command (golang/go#54461); waited %s\\n\\tcommand:%s\\n\\tpid:%d\", time.Since(start), cmd, cmd.Process.Pid)\n}\n\nfunc cmdDebugStr(cmd *exec.Cmd) string {\n\tenv := make(map[string]string)\n\tfor _, kv := range cmd.Env {\n\t\tsplit := strings.SplitN(kv, \"=\", 2)\n\t\tif len(split) == 2 {\n\t\t\tk, v := split[0], split[1]\n\t\t\tenv[k] = v\n\t\t}\n\t}\n\n\tvar args []string\n\tfor _, arg := range cmd.Args {\n\t\tquoted := strconv.Quote(arg)\n\t\tif quoted[1:len(quoted)-1] != arg || strings.Contains(arg, \" \") {\n\t\t\targs = append(args, quoted)\n\t\t} else {\n\t\t\targs = append(args, arg)\n\t\t}\n\t}\n\treturn fmt.Sprintf(\"GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v\", env[\"GOROOT\"], env[\"GOPATH\"], env[\"GO111MODULE\"], env[\"GOPROXY\"], env[\"PWD\"], strings.Join(args, \" \"))\n}\n\n// WriteOverlays writes each value in the overlay (see the Overlay\n// field of go/packages.Config) to a temporary file and returns the name\n// of a JSON file describing the mapping that is suitable for the \"go\n// list -overlay\" flag.\n//\n// On success, the caller must call the cleanup function exactly once\n// when the files are no longer needed.\nfunc WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) {\n\t// Do nothing if there are no overlays in the config.\n\tif len(overlay) == 0 {\n\t\treturn \"\", func() {}, nil\n\t}\n\n\tdir, err := os.MkdirTemp(\"\", \"gocommand-*\")\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\n\t// The caller must clean up this directory,\n\t// unless this function returns an error.\n\t// (The cleanup operand of each return\n\t// statement below is ignored.)\n\tdefer func() {\n\t\tcleanup = func() {\n\t\t\tos.RemoveAll(dir)\n\t\t}\n\t\tif err != nil {\n\t\t\tcleanup()\n\t\t\tcleanup = nil\n\t\t}\n\t}()\n\n\t// Write each map entry to a temporary file.\n\toverlays := make(map[string]string)\n\tfor k, v := range overlay {\n\t\t// Use a unique basename for each file (001-foo.go),\n\t\t// to avoid creating nested directories.\n\t\tbase := fmt.Sprintf(\"%d-%s\", 1+len(overlays), filepath.Base(k))\n\t\tfilename := filepath.Join(dir, base)\n\t\terr := os.WriteFile(filename, v, 0666)\n\t\tif err != nil {\n\t\t\treturn \"\", nil, err\n\t\t}\n\t\toverlays[k] = filename\n\t}\n\n\t// Write the JSON overlay file that maps logical file names to temp files.\n\t//\n\t// OverlayJSON is the format overlay files are expected to be in.\n\t// The Replace map maps from overlaid paths to replacement paths:\n\t// the Go command will forward all reads trying to open\n\t// each overlaid path to its replacement path, or consider the overlaid\n\t// path not to exist if the replacement path is empty.\n\t//\n\t// From golang/go#39958.\n\ttype OverlayJSON struct {\n\t\tReplace map[string]string `json:\"replace,omitempty\"`\n\t}\n\tb, err := json.Marshal(OverlayJSON{Replace: overlays})\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tfilename = filepath.Join(dir, \"overlay.json\")\n\tif err := os.WriteFile(filename, b, 0666); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\n\treturn filename, nil, nil\n}\n"
  },
  {
    "path": "internal/gocommand/invoke_notunix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !unix\n\npackage gocommand\n\nimport \"os\"\n\n// sigStuckProcess is the signal to send to kill a hanging subprocess.\n// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill.\nvar sigStuckProcess = os.Kill\n"
  },
  {
    "path": "internal/gocommand/invoke_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocommand_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestGoVersion(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tinv := gocommand.Invocation{\n\t\tVerb: \"version\",\n\t}\n\tgocmdRunner := &gocommand.Runner{}\n\tif _, err := gocmdRunner.Run(context.Background(), inv); err != nil {\n\t\tt.Error(err)\n\t}\n}\n\n// This is not a test of go/packages at all: it's a test of whether it\n// is possible to delete the directory used by go list once it has\n// finished. It is intended to evaluate the hypothesis (to explain\n// issue #71544) that the go command, on Windows, occasionally fails\n// to release all its handles to the temporary directory even when it\n// should have finished.\n//\n// If this test ever fails, the combination of the gocommand package\n// and the go command itself has a bug; this has been observed (#73503).\nfunc TestRmdirAfterGoList_Runner(t *testing.T) {\n\tt.Skip(\"flaky; see https://github.com/golang/go/issues/73736#issuecomment-2885407104\")\n\n\ttestRmdirAfterGoList(t, func(ctx context.Context, dir string) {\n\t\tvar runner gocommand.Runner\n\t\tstdout, stderr, friendlyErr, err := runner.RunRaw(ctx, gocommand.Invocation{\n\t\t\tVerb:       \"list\",\n\t\t\tArgs:       []string{\"-json\", \"example.com/p\"},\n\t\t\tWorkingDir: dir,\n\t\t})\n\t\tif ctx.Err() != nil {\n\t\t\treturn // don't report error if canceled\n\t\t}\n\t\tif err != nil || friendlyErr != nil {\n\t\t\tt.Fatalf(\"go list failed: %v, %v (stdout=%s stderr=%s)\",\n\t\t\t\terr, friendlyErr, stdout, stderr)\n\t\t}\n\t})\n}\n\n// TestRmdirAfterGoList_Direct is a variant of\n// TestRmdirAfterGoList_Runner that executes go list directly, to\n// control for the substantial logic of the gocommand package.\n//\n// It has two variants: the first does not set WaitDelay; the second\n// sets it to 30s. If the first variant ever fails, the go command\n// itself has a bug; as of May 2025 this has never been observed.\n//\n// If the second variant fails, it indicates that the WaitDelay\n// mechanism is responsible for causing Wait to return before the\n// child process has naturally finished. This is to confirm the\n// hypothesis at https://github.com/golang/go/issues/73736#issuecomment-2885407104.\nfunc TestRmdirAfterGoList_Direct(t *testing.T) {\n\tfor _, delay := range []time.Duration{0, 30 * time.Second} {\n\t\tt.Run(delay.String(), func(t *testing.T) {\n\t\t\ttestRmdirAfterGoList(t, func(ctx context.Context, dir string) {\n\t\t\t\tcmd := exec.Command(\"go\", \"list\", \"-json\", \"example.com/p\")\n\t\t\t\tcmd.Dir = dir\n\t\t\t\tcmd.Stdout = new(strings.Builder)\n\t\t\t\tcmd.Stderr = new(strings.Builder)\n\t\t\t\tcmd.WaitDelay = delay\n\t\t\t\terr := cmd.Run()\n\t\t\t\tif ctx.Err() != nil {\n\t\t\t\t\treturn // don't report error if canceled\n\t\t\t\t}\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"go list failed: %v (stdout=%s stderr=%s)\",\n\t\t\t\t\t\terr, cmd.Stdout, cmd.Stderr)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc testRmdirAfterGoList(t *testing.T, f func(ctx context.Context, dir string)) {\n\ttestenv.NeedsExec(t)\n\n\tdir := t.TempDir()\n\tif err := os.Mkdir(filepath.Join(dir, \"p\"), 0777); err != nil {\n\t\tt.Fatalf(\"mkdir p: %v\", err)\n\t}\n\n\t// Create a go.mod file and 100 trivial Go files for the go command to read.\n\tif err := os.WriteFile(filepath.Join(dir, \"go.mod\"), []byte(\"module example.com\"), 0666); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor i := range 100 {\n\t\tfilename := filepath.Join(dir, fmt.Sprintf(\"p/%d.go\", i))\n\t\tif err := os.WriteFile(filename, []byte(\"package p\"), 0666); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tt0 := time.Now()\n\tg, ctx := errgroup.WithContext(context.Background())\n\tfor range 10 {\n\t\tg.Go(func() error {\n\t\t\tf(ctx, dir)\n\t\t\t// Return an error so that concurrent invocations are canceled.\n\t\t\treturn fmt.Errorf(\"oops\")\n\t\t})\n\t}\n\tg.Wait() // ignore error (expected)\n\n\tt.Logf(\"10 concurrent executions (9 canceled) took %v\", time.Since(t0))\n\n\t// This is the critical operation.\n\tif err := os.RemoveAll(dir); err != nil {\n\t\tt.Errorf(\"failed to remove temp dir: %v\", err)\n\t\t// List the contents of the directory, for clues.\n\t\tfilepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {\n\t\t\tt.Log(path, d, err)\n\t\t\treturn nil\n\t\t}) // ignore error\n\t}\n}\n"
  },
  {
    "path": "internal/gocommand/invoke_unix.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build unix\n\npackage gocommand\n\nimport \"syscall\"\n\n// Sigstuckprocess is the signal to send to kill a hanging subprocess.\n// Send SIGQUIT to get a stack trace.\nvar sigStuckProcess = syscall.SIGQUIT\n"
  },
  {
    "path": "internal/gocommand/vendor.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocommand\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/mod/semver\"\n)\n\n// ModuleJSON holds information about a module.\ntype ModuleJSON struct {\n\tPath      string      // module path\n\tVersion   string      // module version\n\tVersions  []string    // available module versions (with -versions)\n\tReplace   *ModuleJSON // replaced by this module\n\tTime      *time.Time  // time version was created\n\tUpdate    *ModuleJSON // available update, if any (with -u)\n\tMain      bool        // is this the main module?\n\tIndirect  bool        // is this module only an indirect dependency of main module?\n\tDir       string      // directory holding files for this module, if any\n\tGoMod     string      // path to go.mod file used when loading this module, if any\n\tGoVersion string      // go version used in module\n}\n\nvar modFlagRegexp = regexp.MustCompile(`-mod[ =](\\w+)`)\n\n// VendorEnabled reports whether vendoring is enabled. It takes a *Runner to execute Go commands\n// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,\n// of which only Verb and Args are modified to run the appropriate Go command.\n// Inspired by setDefaultBuildMod in modload/init.go\nfunc VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, *ModuleJSON, error) {\n\tmainMod, go114, err := getMainModuleAnd114(ctx, inv, r)\n\tif err != nil {\n\t\treturn false, nil, err\n\t}\n\n\t// We check the GOFLAGS to see if there is anything overridden or not.\n\tinv.Verb = \"env\"\n\tinv.Args = []string{\"GOFLAGS\"}\n\tstdout, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn false, nil, err\n\t}\n\tgoflags := string(bytes.TrimSpace(stdout.Bytes()))\n\tmatches := modFlagRegexp.FindStringSubmatch(goflags)\n\tvar modFlag string\n\tif len(matches) != 0 {\n\t\tmodFlag = matches[1]\n\t}\n\t// Don't override an explicit '-mod=' argument.\n\tif modFlag == \"vendor\" {\n\t\treturn true, mainMod, nil\n\t} else if modFlag != \"\" {\n\t\treturn false, nil, nil\n\t}\n\tif mainMod == nil || !go114 {\n\t\treturn false, nil, nil\n\t}\n\t// Check 1.14's automatic vendor mode.\n\tif fi, err := os.Stat(filepath.Join(mainMod.Dir, \"vendor\")); err == nil && fi.IsDir() {\n\t\tif mainMod.GoVersion != \"\" && semver.Compare(\"v\"+mainMod.GoVersion, \"v1.14\") >= 0 {\n\t\t\t// The Go version is at least 1.14, and a vendor directory exists.\n\t\t\t// Set -mod=vendor by default.\n\t\t\treturn true, mainMod, nil\n\t\t}\n\t}\n\treturn false, nil, nil\n}\n\n// getMainModuleAnd114 gets one of the main modules' information and whether the\n// go command in use is 1.14+. This is the information needed to figure out\n// if vendoring should be enabled.\nfunc getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {\n\tconst format = `{{.Path}}\n{{.Dir}}\n{{.GoMod}}\n{{.GoVersion}}\n{{range context.ReleaseTags}}{{if eq . \"go1.14\"}}{{.}}{{end}}{{end}}\n`\n\tinv.Verb = \"list\"\n\tinv.Args = []string{\"-m\", \"-f\", format}\n\tstdout, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\n\tlines := strings.Split(stdout.String(), \"\\n\")\n\tif len(lines) < 5 {\n\t\treturn nil, false, fmt.Errorf(\"unexpected stdout: %q\", stdout.String())\n\t}\n\tmod := &ModuleJSON{\n\t\tPath:      lines[0],\n\t\tDir:       lines[1],\n\t\tGoMod:     lines[2],\n\t\tGoVersion: lines[3],\n\t\tMain:      true,\n\t}\n\treturn mod, lines[4] == \"go1.14\", nil\n}\n\n// WorkspaceVendorEnabled reports whether workspace vendoring is enabled. It takes a *Runner to execute Go commands\n// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,\n// of which only Verb and Args are modified to run the appropriate Go command.\n// Inspired by setDefaultBuildMod in modload/init.go\nfunc WorkspaceVendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, []*ModuleJSON, error) {\n\tinv.Verb = \"env\"\n\tinv.Args = []string{\"GOWORK\"}\n\tstdout, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn false, nil, err\n\t}\n\tgoWork := string(bytes.TrimSpace(stdout.Bytes()))\n\tif fi, err := os.Stat(filepath.Join(filepath.Dir(goWork), \"vendor\")); err == nil && fi.IsDir() {\n\t\tmainMods, err := getWorkspaceMainModules(ctx, inv, r)\n\t\tif err != nil {\n\t\t\treturn false, nil, err\n\t\t}\n\t\treturn true, mainMods, nil\n\t}\n\treturn false, nil, nil\n}\n\n// getWorkspaceMainModules gets the main modules' information.\n// This is the information needed to figure out if vendoring should be enabled.\nfunc getWorkspaceMainModules(ctx context.Context, inv Invocation, r *Runner) ([]*ModuleJSON, error) {\n\tconst format = `{{.Path}}\n{{.Dir}}\n{{.GoMod}}\n{{.GoVersion}}\n`\n\tinv.Verb = \"list\"\n\tinv.Args = []string{\"-m\", \"-f\", format}\n\tstdout, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines := strings.Split(strings.TrimSuffix(stdout.String(), \"\\n\"), \"\\n\")\n\tif len(lines) < 4 {\n\t\treturn nil, fmt.Errorf(\"unexpected stdout: %q\", stdout.String())\n\t}\n\tmods := make([]*ModuleJSON, 0, len(lines)/4)\n\tfor i := 0; i < len(lines); i += 4 {\n\t\tmods = append(mods, &ModuleJSON{\n\t\t\tPath:      lines[i],\n\t\t\tDir:       lines[i+1],\n\t\t\tGoMod:     lines[i+2],\n\t\t\tGoVersion: lines[i+3],\n\t\t\tMain:      true,\n\t\t})\n\t}\n\treturn mods, nil\n}\n"
  },
  {
    "path": "internal/gocommand/version.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocommand\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// GoVersion reports the minor version number of the highest release\n// tag built into the go command on the PATH.\n//\n// Note that this may be higher than the version of the go tool used\n// to build this application, and thus the versions of the standard\n// go/{scanner,parser,ast,types} packages that are linked into it.\n// In that case, callers should either downgrade to the version of\n// go used to build the application, or report an error that the\n// application is too old to use the go command on the PATH.\nfunc GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {\n\tinv.Verb = \"list\"\n\tinv.Args = []string{\"-e\", \"-f\", `{{context.ReleaseTags}}`, `--`, `unsafe`}\n\tinv.BuildFlags = nil // This is not a build command.\n\tinv.ModFlag = \"\"\n\tinv.ModFile = \"\"\n\t// Set GO111MODULE=off so that we are immune to errors in go.{work,mod}.\n\t// Unfortunately, this breaks the Go 1.21+ toolchain directive and\n\t// may affect the set of ReleaseTags; see #68495.\n\tinv.Env = append(inv.Env[:len(inv.Env):len(inv.Env)], \"GO111MODULE=off\")\n\n\tstdoutBytes, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tstdout := stdoutBytes.String()\n\tif len(stdout) < 3 {\n\t\treturn 0, fmt.Errorf(\"bad ReleaseTags output: %q\", stdout)\n\t}\n\t// Split up \"[go1.1 go1.15]\" and return highest go1.X value.\n\ttags := strings.Fields(stdout[1 : len(stdout)-2])\n\tfor i := len(tags) - 1; i >= 0; i-- {\n\t\tvar version int\n\t\tif _, err := fmt.Sscanf(tags[i], \"go1.%d\", &version); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treturn version, nil\n\t}\n\treturn 0, fmt.Errorf(\"no parseable ReleaseTags in %v\", tags)\n}\n\n// GoVersionOutput returns the complete output of the go version command.\nfunc GoVersionOutput(ctx context.Context, inv Invocation, r *Runner) (string, error) {\n\tinv.Verb = \"version\"\n\tgoVersion, err := r.Run(ctx, inv)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn goVersion.String(), nil\n}\n\n// ParseGoVersionOutput extracts the Go version string\n// from the output of the \"go version\" command.\n// Given an unrecognized form, it returns an empty string.\nfunc ParseGoVersionOutput(data string) string {\n\tre := regexp.MustCompile(`^go version (go\\S+|devel \\S+)`)\n\tm := re.FindStringSubmatch(data)\n\tif len(m) != 2 {\n\t\treturn \"\" // unrecognized version\n\t}\n\treturn m[1]\n}\n"
  },
  {
    "path": "internal/gocommand/version_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocommand\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n)\n\nfunc TestParseGoVersionOutput(t *testing.T) {\n\ttests := []struct {\n\t\targs string\n\t\twant string\n\t}{\n\t\t{\"go version go1.12 linux/amd64\", \"go1.12\"},\n\t\t{\"go version go1.18.1 darwin/amd64\", \"go1.18.1\"},\n\t\t{\"go version go1.19.rc1 windows/arm64\", \"go1.19.rc1\"},\n\t\t{\"go version devel d5de62df152baf4de6e9fe81933319b86fd95ae4 linux/386\", \"devel d5de62df152baf4de6e9fe81933319b86fd95ae4\"},\n\t\t{\"go version devel go1.20-1f068f0dc7 Tue Oct 18 20:58:37 2022 +0000 darwin/amd64\", \"devel go1.20-1f068f0dc7\"},\n\t\t{\"v1.19.1 foo/bar\", \"\"},\n\t}\n\tfor i, tt := range tests {\n\t\tt.Run(strconv.Itoa(i), func(t *testing.T) {\n\t\t\tif got := ParseGoVersionOutput(tt.args); got != tt.want {\n\t\t\t\tt.Errorf(\"parseGoVersionOutput() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/gopathwalk/walk.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gopathwalk is like filepath.Walk but specialized for finding Go\n// packages, particularly in $GOPATH and $GOROOT.\npackage gopathwalk\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Options controls the behavior of a Walk call.\ntype Options struct {\n\t// If Logf is non-nil, debug logging is enabled through this function.\n\tLogf func(format string, args ...any)\n\n\t// Search module caches. Also disables legacy goimports ignore rules.\n\tModulesEnabled bool\n\n\t// Maximum number of concurrent calls to user-provided callbacks,\n\t// or 0 for GOMAXPROCS.\n\tConcurrency int\n}\n\n// RootType indicates the type of a Root.\ntype RootType int\n\nconst (\n\tRootUnknown RootType = iota\n\tRootGOROOT\n\tRootGOPATH\n\tRootCurrentModule\n\tRootModuleCache\n\tRootOther\n)\n\n// A Root is a starting point for a Walk.\ntype Root struct {\n\tPath string\n\tType RootType\n}\n\n// Walk concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.\n//\n// For each package found, add will be called with the absolute\n// paths of the containing source directory and the package directory.\n//\n// Unlike filepath.WalkDir, Walk follows symbolic links\n// (while guarding against cycles).\nfunc Walk(roots []Root, add func(root Root, dir string), opts Options) {\n\tWalkSkip(roots, add, func(Root, string) bool { return false }, opts)\n}\n\n// WalkSkip concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to\n// find packages.\n//\n// For each package found, add will be called with the absolute\n// paths of the containing source directory and the package directory.\n// For each directory that will be scanned, skip will be called\n// with the absolute paths of the containing source directory and the directory.\n// If skip returns false on a directory it will be processed.\n//\n// Unlike filepath.WalkDir, WalkSkip follows symbolic links\n// (while guarding against cycles).\nfunc WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) {\n\tfor _, root := range roots {\n\t\twalkDir(root, add, skip, opts)\n\t}\n}\n\n// walkDir creates a walker and starts fastwalk with this walker.\nfunc walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) {\n\tif opts.Logf == nil {\n\t\topts.Logf = func(format string, args ...any) {}\n\t}\n\tif _, err := os.Stat(root.Path); os.IsNotExist(err) {\n\t\topts.Logf(\"skipping nonexistent directory: %v\", root.Path)\n\t\treturn\n\t}\n\tstart := time.Now()\n\topts.Logf(\"scanning %s\", root.Path)\n\n\tconcurrency := opts.Concurrency\n\tif concurrency == 0 {\n\t\t// The walk be either CPU-bound or I/O-bound, depending on what the\n\t\t// caller-supplied add function does and the details of the user's platform\n\t\t// and machine. Rather than trying to fine-tune the concurrency level for a\n\t\t// specific environment, we default to GOMAXPROCS: it is likely to be a good\n\t\t// choice for a CPU-bound add function, and if it is instead I/O-bound, then\n\t\t// dealing with I/O saturation is arguably the job of the kernel and/or\n\t\t// runtime. (Oversaturating I/O seems unlikely to harm performance as badly\n\t\t// as failing to saturate would.)\n\t\tconcurrency = runtime.GOMAXPROCS(0)\n\t}\n\tw := &walker{\n\t\troot: root,\n\t\tadd:  add,\n\t\tskip: skip,\n\t\topts: opts,\n\t\tsem:  make(chan struct{}, concurrency),\n\t}\n\tw.init()\n\n\tw.sem <- struct{}{}\n\tpath := root.Path\n\tif path == \"\" {\n\t\tpath = \".\"\n\t}\n\tif fi, err := os.Lstat(path); err == nil {\n\t\tw.walk(path, nil, fs.FileInfoToDirEntry(fi))\n\t} else {\n\t\tw.opts.Logf(\"scanning directory %v: %v\", root.Path, err)\n\t}\n\t<-w.sem\n\tw.walking.Wait()\n\n\topts.Logf(\"scanned %s in %v\", root.Path, time.Since(start))\n}\n\n// walker is the callback for fastwalk.Walk.\ntype walker struct {\n\troot Root                    // The source directory to scan.\n\tadd  func(Root, string)      // The callback that will be invoked for every possible Go package dir.\n\tskip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true.\n\topts Options                 // Options passed to Walk by the user.\n\n\twalking     sync.WaitGroup\n\tsem         chan struct{} // Channel of semaphore tokens; send to acquire, receive to release.\n\tignoredDirs []string\n\n\tadded sync.Map // map[string]bool\n}\n\n// A symlinkList is a linked list of os.FileInfos for parent directories\n// reached via symlinks.\ntype symlinkList struct {\n\tinfo os.FileInfo\n\tprev *symlinkList\n}\n\n// init initializes the walker based on its Options\nfunc (w *walker) init() {\n\tvar ignoredPaths []string\n\tif w.root.Type == RootModuleCache {\n\t\tignoredPaths = []string{\"cache\"}\n\t}\n\tif !w.opts.ModulesEnabled && w.root.Type == RootGOPATH {\n\t\tignoredPaths = w.getIgnoredDirs(w.root.Path)\n\t\tignoredPaths = append(ignoredPaths, \"v\", \"mod\")\n\t}\n\n\tfor _, p := range ignoredPaths {\n\t\tfull := filepath.Join(w.root.Path, p)\n\t\tw.ignoredDirs = append(w.ignoredDirs, full)\n\t\tw.opts.Logf(\"Directory added to ignore list: %s\", full)\n\t}\n}\n\n// getIgnoredDirs reads an optional config file at <path>/.goimportsignore\n// of relative directories to ignore when scanning for go files.\n// The provided path is one of the $GOPATH entries with \"src\" appended.\nfunc (w *walker) getIgnoredDirs(path string) []string {\n\tfile := filepath.Join(path, \".goimportsignore\")\n\tslurp, err := os.ReadFile(file)\n\tif err != nil {\n\t\tw.opts.Logf(\"%v\", err)\n\t} else {\n\t\tw.opts.Logf(\"Read %s\", file)\n\t}\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tvar ignoredDirs []string\n\tbs := bufio.NewScanner(bytes.NewReader(slurp))\n\tfor bs.Scan() {\n\t\tline := strings.TrimSpace(bs.Text())\n\t\tif line == \"\" || strings.HasPrefix(line, \"#\") {\n\t\t\tcontinue\n\t\t}\n\t\tignoredDirs = append(ignoredDirs, line)\n\t}\n\treturn ignoredDirs\n}\n\n// shouldSkipDir reports whether the file should be skipped or not.\nfunc (w *walker) shouldSkipDir(dir string) bool {\n\tif slices.Contains(w.ignoredDirs, dir) {\n\t\treturn true\n\t}\n\tif w.skip != nil {\n\t\t// Check with the user specified callback.\n\t\treturn w.skip(w.root, dir)\n\t}\n\treturn false\n}\n\n// walk walks through the given path.\n//\n// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored.\nfunc (w *walker) walk(path string, pathSymlinks *symlinkList, d fs.DirEntry) {\n\tif d.Type()&os.ModeSymlink != 0 {\n\t\t// Walk the symlink's target rather than the symlink itself.\n\t\t//\n\t\t// (Note that os.Stat, unlike the lower-lever os.Readlink,\n\t\t// follows arbitrarily many layers of symlinks, so it will eventually\n\t\t// reach either a non-symlink or a nonexistent target.)\n\t\t//\n\t\t// TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src\n\t\t// and GOPATH/src. Do we really need to traverse them here? If so, why?\n\n\t\tfi, err := os.Stat(path)\n\t\tif err != nil {\n\t\t\tw.opts.Logf(\"%v\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Avoid walking symlink cycles: if we have already followed a symlink to\n\t\t// this directory as a parent of itself, don't follow it again.\n\t\t//\n\t\t// This doesn't catch the first time through a cycle, but it also minimizes\n\t\t// the number of extra stat calls we make if we *don't* encounter a cycle.\n\t\t// Since we don't actually expect to encounter symlink cycles in practice,\n\t\t// this seems like the right tradeoff.\n\t\tfor parent := pathSymlinks; parent != nil; parent = parent.prev {\n\t\t\tif os.SameFile(fi, parent.info) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tpathSymlinks = &symlinkList{\n\t\t\tinfo: fi,\n\t\t\tprev: pathSymlinks,\n\t\t}\n\t\td = fs.FileInfoToDirEntry(fi)\n\t}\n\n\tif d.Type().IsRegular() {\n\t\tif !strings.HasSuffix(path, \".go\") {\n\t\t\treturn\n\t\t}\n\n\t\tdir := filepath.Dir(path)\n\t\tif dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {\n\t\t\t// Doesn't make sense to have regular files\n\t\t\t// directly in your $GOPATH/src or $GOROOT/src.\n\t\t\t//\n\t\t\t// TODO(bcmills): there are many levels of directory within\n\t\t\t// RootModuleCache where this also wouldn't make sense,\n\t\t\t// Can we generalize this to any directory without a corresponding\n\t\t\t// import path?\n\t\t\treturn\n\t\t}\n\n\t\tif _, dup := w.added.LoadOrStore(dir, true); !dup {\n\t\t\tw.add(w.root, dir)\n\t\t}\n\t}\n\n\tif !d.IsDir() {\n\t\treturn\n\t}\n\n\tbase := filepath.Base(path)\n\tif base == \"\" || base[0] == '.' || base[0] == '_' ||\n\t\tbase == \"testdata\" ||\n\t\t(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == \"vendor\") ||\n\t\t(!w.opts.ModulesEnabled && base == \"node_modules\") ||\n\t\tw.shouldSkipDir(path) {\n\t\treturn\n\t}\n\n\t// Read the directory and walk its entries.\n\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\tw.opts.Logf(\"%v\", err)\n\t\treturn\n\t}\n\tdefer f.Close()\n\n\tfor {\n\t\t// We impose an arbitrary limit on the number of ReadDir results per\n\t\t// directory to limit the amount of memory consumed for stale or upcoming\n\t\t// directory entries. The limit trades off CPU (number of syscalls to read\n\t\t// the whole directory) against RAM (reachable directory entries other than\n\t\t// the one currently being processed).\n\t\t//\n\t\t// Since we process the directories recursively, we will end up maintaining\n\t\t// a slice of entries for each level of the directory tree.\n\t\t// (Compare https://go.dev/issue/36197.)\n\t\tents, err := f.ReadDir(1024)\n\t\tif err != nil {\n\t\t\tif err != io.EOF {\n\t\t\t\tw.opts.Logf(\"%v\", err)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tfor _, d := range ents {\n\t\t\tnextPath := filepath.Join(path, d.Name())\n\t\t\tif d.IsDir() {\n\t\t\t\tselect {\n\t\t\t\tcase w.sem <- struct{}{}:\n\t\t\t\t\t// Got a new semaphore token, so we can traverse the directory concurrently.\n\t\t\t\t\td := d\n\t\t\t\t\tw.walking.Add(1)\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tdefer func() {\n\t\t\t\t\t\t\t<-w.sem\n\t\t\t\t\t\t\tw.walking.Done()\n\t\t\t\t\t\t}()\n\t\t\t\t\t\tw.walk(nextPath, pathSymlinks, d)\n\t\t\t\t\t}()\n\t\t\t\t\tcontinue\n\n\t\t\t\tdefault:\n\t\t\t\t\t// No tokens available, so traverse serially.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tw.walk(nextPath, pathSymlinks, d)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/gopathwalk/walk_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gopathwalk\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc TestSymlinkTraversal(t *testing.T) {\n\tt.Parallel()\n\n\tgopath := t.TempDir()\n\n\tif err := mapToDir(gopath, map[string]string{\n\t\t\"a/b/c\":          \"LINK:../../a/d\",\n\t\t\"a/b/pkg/pkg.go\": \"package pkg\",\n\t\t\"a/d/e\":          \"LINK:../../a/b\",\n\t\t\"a/d/pkg/pkg.go\": \"package pkg\",\n\t\t\"a/f/loop\":       \"LINK:../f\",\n\t\t\"a/f/pkg/pkg.go\": \"package pkg\",\n\t\t\"a/g/pkg/pkg.go\": \"LINK:../../f/pkg/pkg.go\",\n\t\t\"a/self\":         \"LINK:.\",\n\t}); err != nil {\n\t\tswitch runtime.GOOS {\n\t\tcase \"windows\", \"plan9\":\n\t\t\tt.Skipf(\"skipping symlink-requiring test on %s\", runtime.GOOS)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\tpkgc := make(chan []string, 1)\n\tpkgc <- nil\n\tadd := func(root Root, dir string) {\n\t\trel, err := filepath.Rel(filepath.Join(root.Path, \"src\"), dir)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t\tpkgc <- append(<-pkgc, filepath.ToSlash(rel))\n\t}\n\n\tWalk([]Root{{Path: gopath, Type: RootGOPATH}}, add, Options{Logf: t.Logf})\n\n\tpkgs := <-pkgc\n\tsort.Strings(pkgs)\n\tt.Logf(\"Found packages:\\n\\t%s\", strings.Join(pkgs, \"\\n\\t\"))\n\n\tgot := make(map[string]bool, len(pkgs))\n\tfor _, pkg := range pkgs {\n\t\tgot[pkg] = true\n\t}\n\ttests := []struct {\n\t\tpath string\n\t\twant bool\n\t\twhy  string\n\t}{\n\t\t{\n\t\t\tpath: \"a/b/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"found via regular directories\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/b/c/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"found via non-cyclic dir link\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/b/c/e/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"found via two non-cyclic dir links\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/d/e/c/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"found via two non-cyclic dir links\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/f/loop/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"found via a single parent-dir link\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/f/loop/loop/pkg\",\n\t\t\twant: false,\n\t\t\twhy:  \"would follow loop symlink twice\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/self/b/pkg\",\n\t\t\twant: true,\n\t\t\twhy:  \"follows self-link once\",\n\t\t},\n\t\t{\n\t\t\tpath: \"a/self/self/b/pkg\",\n\t\t\twant: false,\n\t\t\twhy:  \"would follow self-link twice\",\n\t\t},\n\t}\n\tfor _, tc := range tests {\n\t\tif got[tc.path] != tc.want {\n\t\t\tif tc.want {\n\t\t\t\tt.Errorf(\"MISSING: %s (%s)\", tc.path, tc.why)\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"UNEXPECTED: %s (%s)\", tc.path, tc.why)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TestSkip tests that various goimports rules are followed in non-modules mode.\nfunc TestSkip(t *testing.T) {\n\tt.Parallel()\n\n\tdir := t.TempDir()\n\n\tif err := mapToDir(dir, map[string]string{\n\t\t\"ignoreme/f.go\":     \"package ignoreme\",     // ignored by .goimportsignore\n\t\t\"node_modules/f.go\": \"package nodemodules;\", // ignored by hardcoded node_modules filter\n\t\t\"v/f.go\":            \"package v;\",           // ignored by hardcoded vgo cache rule\n\t\t\"mod/f.go\":          \"package mod;\",         // ignored by hardcoded vgo cache rule\n\t\t\"shouldfind/f.go\":   \"package shouldfind;\",  // not ignored\n\n\t\t\".goimportsignore\": \"ignoreme\\n\",\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar found []string\n\tvar mu sync.Mutex\n\twalkDir(Root{filepath.Join(dir, \"src\"), RootGOPATH},\n\t\tfunc(root Root, dir string) {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfound = append(found, dir[len(root.Path)+1:])\n\t\t}, func(root Root, dir string) bool {\n\t\t\treturn false\n\t\t}, Options{\n\t\t\tModulesEnabled: false,\n\t\t\tLogf:           t.Logf,\n\t\t})\n\tif want := []string{\"shouldfind\"}; !reflect.DeepEqual(found, want) {\n\t\tt.Errorf(\"expected to find only %v, got %v\", want, found)\n\t}\n}\n\n// TestSkipFunction tests that scan successfully skips directories from user callback.\nfunc TestSkipFunction(t *testing.T) {\n\tt.Parallel()\n\n\tdir := t.TempDir()\n\n\tif err := mapToDir(dir, map[string]string{\n\t\t\"ignoreme/f.go\":           \"package ignoreme\",    // ignored by skip\n\t\t\"ignoreme/subignore/f.go\": \"package subignore\",   // also ignored by skip\n\t\t\"shouldfind/f.go\":         \"package shouldfind;\", // not ignored\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar found []string\n\tvar mu sync.Mutex\n\twalkDir(Root{filepath.Join(dir, \"src\"), RootGOPATH},\n\t\tfunc(root Root, dir string) {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfound = append(found, dir[len(root.Path)+1:])\n\t\t}, func(root Root, dir string) bool {\n\t\t\treturn strings.HasSuffix(dir, \"ignoreme\")\n\t\t},\n\t\tOptions{\n\t\t\tModulesEnabled: false,\n\t\t\tLogf:           t.Logf,\n\t\t})\n\tif want := []string{\"shouldfind\"}; !reflect.DeepEqual(found, want) {\n\t\tt.Errorf(\"expected to find only %v, got %v\", want, found)\n\t}\n}\n\n// TestWalkSymlinkConcurrentDeletion is a regression test for the panic reported\n// in https://go.dev/issue/58054#issuecomment-1791513726.\nfunc TestWalkSymlinkConcurrentDeletion(t *testing.T) {\n\tt.Parallel()\n\n\tsrc := t.TempDir()\n\n\tm := map[string]string{\n\t\t\"dir/readme.txt\": \"dir is not a go package\",\n\t\t\"dirlink\":        \"LINK:dir\",\n\t}\n\tif err := mapToDir(src, m); err != nil {\n\t\tswitch runtime.GOOS {\n\t\tcase \"windows\", \"plan9\":\n\t\t\tt.Skipf(\"skipping symlink-requiring test on %s\", runtime.GOOS)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\tdone := make(chan struct{})\n\tgo func() {\n\t\tif err := os.RemoveAll(src); err != nil {\n\t\t\tt.Log(err)\n\t\t}\n\t\tclose(done)\n\t}()\n\tdefer func() {\n\t\t<-done\n\t}()\n\n\tadd := func(root Root, dir string) {\n\t\tt.Errorf(\"unexpected call to add(%q, %q)\", root.Path, dir)\n\t}\n\tWalk([]Root{{Path: src, Type: RootGOPATH}}, add, Options{Logf: t.Logf})\n}\n\nfunc mapToDir(destDir string, files map[string]string) error {\n\tvar symlinkPaths []string\n\tfor path, contents := range files {\n\t\tfile := filepath.Join(destDir, \"src\", path)\n\t\tif err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar err error\n\t\tif strings.HasPrefix(contents, \"LINK:\") {\n\t\t\t// To work around https://go.dev/issue/39183, wait to create symlinks\n\t\t\t// until we have created all non-symlink paths.\n\t\t\tsymlinkPaths = append(symlinkPaths, path)\n\t\t} else {\n\t\t\terr = os.WriteFile(file, []byte(contents), 0644)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor _, path := range symlinkPaths {\n\t\tfile := filepath.Join(destDir, \"src\", path)\n\t\ttarget := filepath.FromSlash(strings.TrimPrefix(files[path], \"LINK:\"))\n\t\terr := os.Symlink(target, file)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/goplsexport/export.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package goplsexport provides various backdoors to not-yet-published\n// parts of x/tools that are needed by gopls.\npackage goplsexport\n\nimport \"golang.org/x/tools/go/analysis\"\n\nvar (\n\tErrorsAsTypeModernizer *analysis.Analyzer // = modernize.errorsastypeAnalyzer\n\tStdIteratorsModernizer *analysis.Analyzer // = modernize.stditeratorsAnalyzer\n\tPlusBuildModernizer    *analysis.Analyzer // = modernize.plusbuildAnalyzer\n\tStringsCutModernizer   *analysis.Analyzer // = modernize.stringscutAnalyzer\n\tUnsafeFuncsModernizer  *analysis.Analyzer // = modernize.unsafeFuncsAnalyzer\n\tAtomicTypesModernizer  *analysis.Analyzer // = modernize.atomicTypesAnalyzer\n)\n"
  },
  {
    "path": "internal/goroot/importcfg.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package goroot is a copy of package internal/goroot\n// in the main GO repot. It provides a utility to produce\n// an import path to package file map mapping\n// standard library packages to the locations of their export\n// data files.\npackage goroot\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// PkgfileMap returns a map of package paths to the location on disk\n// of the .a file for the package.\n// The caller must not modify the map.\nfunc PkgfileMap() (map[string]string, error) {\n\treturn pkgFileMapOnce()\n}\n\nvar pkgFileMapOnce = sync.OnceValues(func() (map[string]string, error) {\n\tm := make(map[string]string)\n\toutput, err := exec.Command(\"go\", \"list\", \"-export\", \"-e\", \"-f\", \"{{.ImportPath}} {{.Export}}\", \"std\", \"cmd\").Output()\n\tif err != nil {\n\t\treturn m, err\n\t}\n\tfor line := range strings.SplitSeq(string(output), \"\\n\") {\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tsp := strings.SplitN(line, \" \", 2)\n\t\tif len(sp) != 2 {\n\t\t\treturn m, fmt.Errorf(\"determining pkgfile map: invalid line in go list output: %q\", line)\n\t\t}\n\t\timportPath, export := sp[0], sp[1]\n\t\tif export != \"\" {\n\t\t\tm[importPath] = export\n\t\t}\n\t}\n\treturn m, nil\n})\n"
  },
  {
    "path": "internal/imports/fix.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io/fs\"\n\t\"io/ioutil\"\n\t\"maps\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n\t\"golang.org/x/tools/internal/stdlib\"\n)\n\n// importToGroup is a list of functions which map from an import path to\n// a group number.\nvar importToGroup = []func(localPrefix, importPath string) (num int, ok bool){\n\tfunc(localPrefix, importPath string) (num int, ok bool) {\n\t\tif localPrefix == \"\" {\n\t\t\treturn\n\t\t}\n\t\tfor p := range strings.SplitSeq(localPrefix, \",\") {\n\t\t\tif strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, \"/\") == importPath {\n\t\t\t\treturn 3, true\n\t\t\t}\n\t\t}\n\t\treturn\n\t},\n\tfunc(_, importPath string) (num int, ok bool) {\n\t\tif strings.HasPrefix(importPath, \"appengine\") {\n\t\t\treturn 2, true\n\t\t}\n\t\treturn\n\t},\n\tfunc(_, importPath string) (num int, ok bool) {\n\t\tfirstComponent := strings.Split(importPath, \"/\")[0]\n\t\tif strings.Contains(firstComponent, \".\") {\n\t\t\treturn 1, true\n\t\t}\n\t\treturn\n\t},\n}\n\nfunc importGroup(localPrefix, importPath string) int {\n\tfor _, fn := range importToGroup {\n\t\tif n, ok := fn(localPrefix, importPath); ok {\n\t\t\treturn n\n\t\t}\n\t}\n\treturn 0\n}\n\ntype ImportFixType int\n\nconst (\n\tAddImport ImportFixType = iota\n\tDeleteImport\n\tSetImportName\n)\n\ntype ImportFix struct {\n\t// StmtInfo represents the import statement this fix will add, remove, or change.\n\tStmtInfo ImportInfo\n\t// IdentName is the identifier that this fix will add or remove.\n\tIdentName string\n\t// FixType is the type of fix this is (AddImport, DeleteImport, SetImportName).\n\tFixType   ImportFixType\n\tRelevance float64 // see pkg\n}\n\n// parseOtherFiles parses all the Go files in srcDir except filename, including\n// test files if filename looks like a test.\n//\n// It returns an error only if ctx is cancelled. Files with parse errors are\n// ignored.\nfunc parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename string) ([]*ast.File, error) {\n\t// This could use go/packages but it doesn't buy much, and it fails\n\t// with https://golang.org/issue/26296 in LoadFiles mode in some cases.\n\tconsiderTests := strings.HasSuffix(filename, \"_test.go\")\n\n\tfileBase := filepath.Base(filename)\n\tpackageFileInfos, err := os.ReadDir(srcDir)\n\tif err != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\tvar files []*ast.File\n\tfor _, fi := range packageFileInfos {\n\t\tif ctx.Err() != nil {\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t\tif fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), \".go\") {\n\t\t\tcontinue\n\t\t}\n\t\tif !considerTests && strings.HasSuffix(fi.Name(), \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\n\t\tf, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, parser.SkipObjectResolution)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tfiles = append(files, f)\n\t}\n\n\treturn files, ctx.Err()\n}\n\n// addGlobals puts the names of package vars into the provided map.\nfunc addGlobals(f *ast.File, globals map[string]bool) {\n\tfor _, decl := range f.Decls {\n\t\tgenDecl, ok := decl.(*ast.GenDecl)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, spec := range genDecl.Specs {\n\t\t\tvalueSpec, ok := spec.(*ast.ValueSpec)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tglobals[valueSpec.Names[0].Name] = true\n\t\t}\n\t}\n}\n\n// collectReferences builds a map of selector expressions, from\n// left hand side (X) to a set of right hand sides (Sel).\nfunc collectReferences(f *ast.File) References {\n\trefs := References{}\n\n\tvar visitor visitFn\n\tvisitor = func(node ast.Node) ast.Visitor {\n\t\tif node == nil {\n\t\t\treturn visitor\n\t\t}\n\t\tswitch v := node.(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\txident, ok := v.X.(*ast.Ident)\n\t\t\tif !ok {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif xident.Obj != nil {\n\t\t\t\t// If the parser can resolve it, it's not a package ref.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif !ast.IsExported(v.Sel.Name) {\n\t\t\t\t// Whatever this is, it's not exported from a package.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpkgName := xident.Name\n\t\t\tr := refs[pkgName]\n\t\t\tif r == nil {\n\t\t\t\tr = make(map[string]bool)\n\t\t\t\trefs[pkgName] = r\n\t\t\t}\n\t\t\tr[v.Sel.Name] = true\n\t\t}\n\t\treturn visitor\n\t}\n\tast.Walk(visitor, f)\n\treturn refs\n}\n\n// collectImports returns all the imports in f.\n// Unnamed imports (., _) and \"C\" are ignored.\nfunc collectImports(f *ast.File) []*ImportInfo {\n\tvar imports []*ImportInfo\n\tfor _, imp := range f.Imports {\n\t\tvar name string\n\t\tif imp.Name != nil {\n\t\t\tname = imp.Name.Name\n\t\t}\n\t\tif imp.Path.Value == `\"C\"` || name == \"_\" || name == \".\" {\n\t\t\tcontinue\n\t\t}\n\t\tpath := strings.Trim(imp.Path.Value, `\"`)\n\t\timports = append(imports, &ImportInfo{\n\t\t\tName:       name,\n\t\t\tImportPath: path,\n\t\t})\n\t}\n\treturn imports\n}\n\n// findMissingImport searches pass's candidates for an import that provides\n// pkg, containing all of syms.\nfunc (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo {\n\tfor _, candidate := range p.candidates {\n\t\tpkgInfo, ok := p.knownPackages[candidate.ImportPath]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif p.importIdentifier(candidate) != pkg {\n\t\t\tcontinue\n\t\t}\n\n\t\tallFound := true\n\t\tfor right := range syms {\n\t\t\tif !pkgInfo.Exports[right] {\n\t\t\t\tallFound = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif allFound {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn nil\n}\n\n// A pass contains all the inputs and state necessary to fix a file's imports.\n// It can be modified in some ways during use; see comments below.\ntype pass struct {\n\t// Inputs. These must be set before a call to load, and not modified after.\n\tfset                 *token.FileSet // fset used to parse f and its siblings.\n\tf                    *ast.File      // the file being fixed.\n\tsrcDir               string         // the directory containing f.\n\tlogf                 func(string, ...any)\n\tsource               Source      // the environment to use for go commands, etc.\n\tloadRealPackageNames bool        // if true, load package names from disk rather than guessing them.\n\totherFiles           []*ast.File // sibling files.\n\tgoroot               string\n\n\t// Intermediate state, generated by load.\n\texistingImports map[string][]*ImportInfo\n\tallRefs         References\n\tmissingRefs     References\n\n\t// Inputs to fix. These can be augmented between successive fix calls.\n\tlastTry       bool                    // indicates that this is the last call and fix should clean up as best it can.\n\tcandidates    []*ImportInfo           // candidate imports in priority order.\n\tknownPackages map[string]*PackageInfo // information about all known packages.\n}\n\n// loadPackageNames saves the package names for everything referenced by imports.\nfunc (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) error {\n\tif p.logf != nil {\n\t\tp.logf(\"loading package names for %v packages\", len(imports))\n\t\tdefer func() {\n\t\t\tp.logf(\"done loading package names for %v packages\", len(imports))\n\t\t}()\n\t}\n\tvar unknown []string\n\tfor _, imp := range imports {\n\t\tif _, ok := p.knownPackages[imp.ImportPath]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tunknown = append(unknown, imp.ImportPath)\n\t}\n\n\tnames, err := p.source.LoadPackageNames(ctx, p.srcDir, unknown)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// TODO(rfindley): revisit this. Why do we need to store known packages with\n\t// no exports? The inconsistent data is confusing.\n\tfor path, name := range names {\n\t\tp.knownPackages[path] = &PackageInfo{\n\t\t\tName:    name,\n\t\t\tExports: map[string]bool{},\n\t\t}\n\t}\n\treturn nil\n}\n\n// WithoutVersion removes a trailing major version, if there is one.\nfunc WithoutVersion(nm string) string {\n\tif v := path.Base(nm); len(v) > 0 && v[0] == 'v' {\n\t\tif _, err := strconv.Atoi(v[1:]); err == nil {\n\t\t\t// this is, for instance, called with rand/v2 and returns rand\n\t\t\tif len(v) < len(nm) {\n\t\t\t\txnm := nm[:len(nm)-len(v)-1]\n\t\t\t\treturn path.Base(xnm)\n\t\t\t}\n\t\t}\n\t}\n\treturn nm\n}\n\n// importIdentifier returns the identifier that imp will introduce. It will\n// guess if the package name has not been loaded, e.g. because the source\n// is not available.\nfunc (p *pass) importIdentifier(imp *ImportInfo) string {\n\tif imp.Name != \"\" {\n\t\treturn imp.Name\n\t}\n\tknown := p.knownPackages[imp.ImportPath]\n\tif known != nil && known.Name != \"\" {\n\t\treturn WithoutVersion(known.Name)\n\t}\n\treturn ImportPathToAssumedName(imp.ImportPath)\n}\n\n// load reads in everything necessary to run a pass, and reports whether the\n// file already has all the imports it needs. It fills in p.missingRefs with the\n// file's missing symbols, if any, or removes unused imports if not.\nfunc (p *pass) load(ctx context.Context) ([]*ImportFix, bool) {\n\tp.knownPackages = map[string]*PackageInfo{}\n\tp.missingRefs = References{}\n\tp.existingImports = map[string][]*ImportInfo{}\n\n\t// Load basic information about the file in question.\n\tp.allRefs = collectReferences(p.f)\n\n\t// Load stuff from other files in the same package:\n\t// global variables so we know they don't need resolving, and imports\n\t// that we might want to mimic.\n\tglobals := map[string]bool{}\n\tfor _, otherFile := range p.otherFiles {\n\t\t// Don't load globals from files that are in the same directory\n\t\t// but a different package. Using them to suggest imports is OK.\n\t\tif p.f.Name.Name == otherFile.Name.Name {\n\t\t\taddGlobals(otherFile, globals)\n\t\t}\n\t\tp.candidates = append(p.candidates, collectImports(otherFile)...)\n\t}\n\n\t// Resolve all the import paths we've seen to package names, and store\n\t// f's imports by the identifier they introduce.\n\timports := collectImports(p.f)\n\tif p.loadRealPackageNames {\n\t\terr := p.loadPackageNames(ctx, append(imports, p.candidates...))\n\t\tif err != nil {\n\t\t\tif p.logf != nil {\n\t\t\t\tp.logf(\"loading package names: %v\", err)\n\t\t\t}\n\t\t\treturn nil, false\n\t\t}\n\t}\n\tfor _, imp := range imports {\n\t\tp.existingImports[p.importIdentifier(imp)] = append(p.existingImports[p.importIdentifier(imp)], imp)\n\t}\n\n\t// Find missing references.\n\tfor left, rights := range p.allRefs {\n\t\tif globals[left] {\n\t\t\tcontinue\n\t\t}\n\t\t_, ok := p.existingImports[left]\n\t\tif !ok {\n\t\t\tp.missingRefs[left] = rights\n\t\t\tcontinue\n\t\t}\n\t}\n\tif len(p.missingRefs) != 0 {\n\t\treturn nil, false\n\t}\n\n\treturn p.fix()\n}\n\n// fix attempts to satisfy missing imports using p.candidates. If it finds\n// everything, or if p.lastTry is true, it updates fixes to add the imports it found,\n// delete anything unused, and update import names, and returns true.\nfunc (p *pass) fix() ([]*ImportFix, bool) {\n\t// Find missing imports.\n\tvar selected []*ImportInfo\n\tfor left, rights := range p.missingRefs {\n\t\tif imp := p.findMissingImport(left, rights); imp != nil {\n\t\t\tselected = append(selected, imp)\n\t\t}\n\t}\n\n\tif !p.lastTry && len(selected) != len(p.missingRefs) {\n\t\treturn nil, false\n\t}\n\n\t// Found everything, or giving up. Add the new imports and remove any unused.\n\tvar fixes []*ImportFix\n\tfor _, identifierImports := range p.existingImports {\n\t\tfor _, imp := range identifierImports {\n\t\t\t// We deliberately ignore globals here, because we can't be sure\n\t\t\t// they're in the same package. People do things like put multiple\n\t\t\t// main packages in the same directory, and we don't want to\n\t\t\t// remove imports if they happen to have the same name as a var in\n\t\t\t// a different package.\n\t\t\tif _, ok := p.allRefs[p.importIdentifier(imp)]; !ok {\n\t\t\t\tfixes = append(fixes, &ImportFix{\n\t\t\t\t\tStmtInfo:  *imp,\n\t\t\t\t\tIdentName: p.importIdentifier(imp),\n\t\t\t\t\tFixType:   DeleteImport,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// An existing import may need to update its import name to be correct.\n\t\t\tif name := p.importSpecName(imp); name != imp.Name {\n\t\t\t\tfixes = append(fixes, &ImportFix{\n\t\t\t\t\tStmtInfo: ImportInfo{\n\t\t\t\t\t\tName:       name,\n\t\t\t\t\t\tImportPath: imp.ImportPath,\n\t\t\t\t\t},\n\t\t\t\t\tIdentName: p.importIdentifier(imp),\n\t\t\t\t\tFixType:   SetImportName,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\t// Collecting fixes involved map iteration, so sort for stability. See\n\t// golang/go#59976.\n\tsortFixes(fixes)\n\n\t// collect selected fixes in a separate slice, so that it can be sorted\n\t// separately. Note that these fixes must occur after fixes to existing\n\t// imports. TODO(rfindley): figure out why.\n\tvar selectedFixes []*ImportFix\n\tfor _, imp := range selected {\n\t\tselectedFixes = append(selectedFixes, &ImportFix{\n\t\t\tStmtInfo: ImportInfo{\n\t\t\t\tName:       p.importSpecName(imp),\n\t\t\t\tImportPath: imp.ImportPath,\n\t\t\t},\n\t\t\tIdentName: p.importIdentifier(imp),\n\t\t\tFixType:   AddImport,\n\t\t})\n\t}\n\tsortFixes(selectedFixes)\n\n\treturn append(fixes, selectedFixes...), true\n}\n\nfunc sortFixes(fixes []*ImportFix) {\n\tsort.Slice(fixes, func(i, j int) bool {\n\t\tfi, fj := fixes[i], fixes[j]\n\t\tif fi.StmtInfo.ImportPath != fj.StmtInfo.ImportPath {\n\t\t\treturn fi.StmtInfo.ImportPath < fj.StmtInfo.ImportPath\n\t\t}\n\t\tif fi.StmtInfo.Name != fj.StmtInfo.Name {\n\t\t\treturn fi.StmtInfo.Name < fj.StmtInfo.Name\n\t\t}\n\t\tif fi.IdentName != fj.IdentName {\n\t\t\treturn fi.IdentName < fj.IdentName\n\t\t}\n\t\treturn fi.FixType < fj.FixType\n\t})\n}\n\n// importSpecName gets the import name of imp in the import spec.\n//\n// When the import identifier matches the assumed import name, the import name does\n// not appear in the import spec.\nfunc (p *pass) importSpecName(imp *ImportInfo) string {\n\t// If we did not load the real package names, or the name is already set,\n\t// we just return the existing name.\n\tif !p.loadRealPackageNames || imp.Name != \"\" {\n\t\treturn imp.Name\n\t}\n\n\tident := p.importIdentifier(imp)\n\tif ident == ImportPathToAssumedName(imp.ImportPath) {\n\t\treturn \"\" // ident not needed since the assumed and real names are the same.\n\t}\n\treturn ident\n}\n\n// apply will perform the fixes on f in order.\nfunc apply(fset *token.FileSet, f *ast.File, fixes []*ImportFix) {\n\tfor _, fix := range fixes {\n\t\tswitch fix.FixType {\n\t\tcase DeleteImport:\n\t\t\tastutil.DeleteNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)\n\t\tcase AddImport:\n\t\t\tastutil.AddNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)\n\t\tcase SetImportName:\n\t\t\t// Find the matching import path and change the name.\n\t\t\tfor _, spec := range f.Imports {\n\t\t\t\tpath := strings.Trim(spec.Path.Value, `\"`)\n\t\t\t\tif path == fix.StmtInfo.ImportPath {\n\t\t\t\t\tspec.Name = &ast.Ident{\n\t\t\t\t\t\tName:    fix.StmtInfo.Name,\n\t\t\t\t\t\tNamePos: spec.Pos(),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// assumeSiblingImportsValid assumes that siblings' use of packages is valid,\n// adding the exports they use.\nfunc (p *pass) assumeSiblingImportsValid() {\n\tfor _, f := range p.otherFiles {\n\t\trefs := collectReferences(f)\n\t\timports := collectImports(f)\n\t\timportsByName := map[string]*ImportInfo{}\n\t\tfor _, imp := range imports {\n\t\t\timportsByName[p.importIdentifier(imp)] = imp\n\t\t}\n\t\tfor left, rights := range refs {\n\t\t\tif imp, ok := importsByName[left]; ok {\n\t\t\t\tif m, ok := stdlib.PackageSymbols[imp.ImportPath]; ok {\n\t\t\t\t\t// We have the stdlib in memory; no need to guess.\n\t\t\t\t\trights = symbolNameSet(m)\n\t\t\t\t}\n\t\t\t\t// TODO(rfindley): we should set package name here, for consistency.\n\t\t\t\tp.addCandidate(imp, &PackageInfo{\n\t\t\t\t\t// no name; we already know it.\n\t\t\t\t\tExports: rights,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\n// addCandidate adds a candidate import to p, and merges in the information\n// in pkg.\nfunc (p *pass) addCandidate(imp *ImportInfo, pkg *PackageInfo) {\n\tp.candidates = append(p.candidates, imp)\n\tif existing, ok := p.knownPackages[imp.ImportPath]; ok {\n\t\tif existing.Name == \"\" {\n\t\t\texisting.Name = pkg.Name\n\t\t}\n\t\tfor export := range pkg.Exports {\n\t\t\texisting.Exports[export] = true\n\t\t}\n\t} else {\n\t\tp.knownPackages[imp.ImportPath] = pkg\n\t}\n}\n\n// fixImports adds and removes imports from f so that all its references are\n// satisfied and there are no unused imports.\n//\n// This is declared as a variable rather than a function so goimports can\n// easily be extended by adding a file with an init function.\n//\n// DO NOT REMOVE: used internally at Google.\nvar fixImports = fixImportsDefault\n\nfunc fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {\n\tfixes, err := getFixes(context.Background(), fset, f, filename, env)\n\tif err != nil {\n\t\treturn err\n\t}\n\tapply(fset, f, fixes)\n\treturn nil\n}\n\n// getFixes gets the import fixes that need to be made to f in order to fix the imports.\n// It does not modify the ast.\nfunc getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) {\n\tsource, err := NewProcessEnvSource(env, filename, f.Name.Name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tgoEnv, err := env.goEnv()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn getFixesWithSource(ctx, fset, f, filename, goEnv[\"GOROOT\"], env.logf, source)\n}\n\nfunc getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, goroot string, logf func(string, ...any), source Source) ([]*ImportFix, error) {\n\t// This logic is defensively duplicated from getFixes.\n\tabs, err := filepath.Abs(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsrcDir := filepath.Dir(abs)\n\n\tif logf != nil {\n\t\tlogf(\"fixImports(filename=%q), srcDir=%q ...\", filename, srcDir)\n\t}\n\n\t// First pass: looking only at f, and using the naive algorithm to\n\t// derive package names from import paths, see if the file is already\n\t// complete. We can't add any imports yet, because we don't know\n\t// if missing references are actually package vars.\n\tp := &pass{\n\t\tfset:   fset,\n\t\tf:      f,\n\t\tsrcDir: srcDir,\n\t\tlogf:   logf,\n\t\tgoroot: goroot,\n\t\tsource: source,\n\t}\n\tif fixes, done := p.load(ctx); done {\n\t\treturn fixes, nil\n\t}\n\n\totherFiles, err := parseOtherFiles(ctx, fset, srcDir, filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Second pass: add information from other files in the same package,\n\t// like their package vars and imports.\n\tp.otherFiles = otherFiles\n\tif fixes, done := p.load(ctx); done {\n\t\treturn fixes, nil\n\t}\n\n\t// Now we can try adding imports from the stdlib.\n\tp.assumeSiblingImportsValid()\n\taddStdlibCandidates(p, p.missingRefs)\n\tif fixes, done := p.fix(); done {\n\t\treturn fixes, nil\n\t}\n\n\t// Third pass: get real package names where we had previously used\n\t// the naive algorithm.\n\tp = &pass{\n\t\tfset:   fset,\n\t\tf:      f,\n\t\tsrcDir: srcDir,\n\t\tlogf:   logf,\n\t\tgoroot: goroot,\n\t\tsource: p.source, // safe to reuse, as it's just a wrapper around env\n\t}\n\tp.loadRealPackageNames = true\n\tp.otherFiles = otherFiles\n\tif fixes, done := p.load(ctx); done {\n\t\treturn fixes, nil\n\t}\n\n\tif err := addStdlibCandidates(p, p.missingRefs); err != nil {\n\t\treturn nil, err\n\t}\n\tp.assumeSiblingImportsValid()\n\tif fixes, done := p.fix(); done {\n\t\treturn fixes, nil\n\t}\n\n\t// Go look for candidates in $GOPATH, etc. We don't necessarily load\n\t// the real exports of sibling imports, so keep assuming their contents.\n\tif err := addExternalCandidates(ctx, p, p.missingRefs, filename); err != nil {\n\t\treturn nil, err\n\t}\n\n\tp.lastTry = true\n\tfixes, _ := p.fix()\n\treturn fixes, nil\n}\n\n// MaxRelevance is the highest relevance, used for the standard library.\n// Chosen arbitrarily to match pre-existing gopls code.\nconst MaxRelevance = 7.0\n\n// getCandidatePkgs works with the passed callback to find all acceptable packages.\n// It deduplicates by import path, and uses a cached stdlib rather than reading\n// from disk.\nfunc getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filename, filePkg string, env *ProcessEnv) error {\n\tnotSelf := func(p *pkg) bool {\n\t\treturn p.packageName != filePkg || p.dir != filepath.Dir(filename)\n\t}\n\tgoenv, err := env.goEnv()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar mu sync.Mutex // to guard asynchronous access to dupCheck\n\tdupCheck := map[string]struct{}{}\n\n\t// Start off with the standard library.\n\tfor importPath, symbols := range stdlib.PackageSymbols {\n\t\tp := &pkg{\n\t\t\tdir:             filepath.Join(goenv[\"GOROOT\"], \"src\", importPath),\n\t\t\timportPathShort: importPath,\n\t\t\tpackageName:     path.Base(importPath),\n\t\t\trelevance:       MaxRelevance,\n\t\t}\n\t\tdupCheck[importPath] = struct{}{}\n\t\tif notSelf(p) && wrappedCallback.dirFound(p) && wrappedCallback.packageNameLoaded(p) {\n\t\t\tvar exports []stdlib.Symbol\n\t\t\tfor _, sym := range symbols {\n\t\t\t\tswitch sym.Kind {\n\t\t\t\tcase stdlib.Func, stdlib.Type, stdlib.Var, stdlib.Const:\n\t\t\t\t\texports = append(exports, sym)\n\t\t\t\t}\n\t\t\t}\n\t\t\twrappedCallback.exportsLoaded(p, exports)\n\t\t}\n\t}\n\n\tscanFilter := &scanCallback{\n\t\trootFound: func(root gopathwalk.Root) bool {\n\t\t\t// Exclude goroot results -- getting them is relatively expensive, not cached,\n\t\t\t// and generally redundant with the in-memory version.\n\t\t\treturn root.Type != gopathwalk.RootGOROOT && wrappedCallback.rootFound(root)\n\t\t},\n\t\tdirFound: wrappedCallback.dirFound,\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tif _, ok := dupCheck[pkg.importPathShort]; ok {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdupCheck[pkg.importPathShort] = struct{}{}\n\t\t\treturn notSelf(pkg) && wrappedCallback.packageNameLoaded(pkg)\n\t\t},\n\t\texportsLoaded: func(pkg *pkg, exports []stdlib.Symbol) {\n\t\t\t// If we're an x_test, load the package under test's test variant.\n\t\t\tif strings.HasSuffix(filePkg, \"_test\") && pkg.dir == filepath.Dir(filename) {\n\t\t\t\tvar err error\n\t\t\t\t_, exports, err = loadExportsFromFiles(ctx, env, pkg.dir, true)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\twrappedCallback.exportsLoaded(pkg, exports)\n\t\t},\n\t}\n\tresolver, err := env.GetResolver()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn resolver.scan(ctx, scanFilter)\n}\n\nfunc ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) (map[string]float64, error) {\n\tresult := make(map[string]float64)\n\tresolver, err := env.GetResolver()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, path := range paths {\n\t\tresult[path] = resolver.scoreImportPath(ctx, path)\n\t}\n\treturn result, nil\n}\n\nfunc PrimeCache(ctx context.Context, resolver Resolver) error {\n\t// Fully scan the disk for directories, but don't actually read any Go files.\n\tcallback := &scanCallback{\n\t\trootFound: func(root gopathwalk.Root) bool {\n\t\t\t// See getCandidatePkgs: walking GOROOT is apparently expensive and\n\t\t\t// unnecessary.\n\t\t\treturn root.Type != gopathwalk.RootGOROOT\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\treturn false\n\t\t},\n\t\t// packageNameLoaded and exportsLoaded must never be called.\n\t}\n\n\treturn resolver.scan(ctx, callback)\n}\n\nfunc candidateImportName(pkg *pkg) string {\n\tif ImportPathToAssumedName(pkg.importPathShort) != pkg.packageName {\n\t\treturn pkg.packageName\n\t}\n\treturn \"\"\n}\n\n// GetAllCandidates calls wrapped for each package whose name starts with\n// searchPrefix, and can be imported from filename with the package name filePkg.\n//\n// Beware that the wrapped function may be called multiple times concurrently.\n// TODO(adonovan): encapsulate the concurrency.\nfunc GetAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error {\n\tcallback := &scanCallback{\n\t\trootFound: func(gopathwalk.Root) bool {\n\t\t\treturn true\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\tif !CanUse(filename, pkg.dir) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Try the assumed package name first, then a simpler path match\n\t\t\t// in case of packages named vN, which are not uncommon.\n\t\t\treturn strings.HasPrefix(ImportPathToAssumedName(pkg.importPathShort), searchPrefix) ||\n\t\t\t\tstrings.HasPrefix(path.Base(pkg.importPathShort), searchPrefix)\n\t\t},\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\tif !strings.HasPrefix(pkg.packageName, searchPrefix) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\twrapped(ImportFix{\n\t\t\t\tStmtInfo: ImportInfo{\n\t\t\t\t\tImportPath: pkg.importPathShort,\n\t\t\t\t\tName:       candidateImportName(pkg),\n\t\t\t\t},\n\t\t\t\tIdentName: pkg.packageName,\n\t\t\t\tFixType:   AddImport,\n\t\t\t\tRelevance: pkg.relevance,\n\t\t\t})\n\t\t\treturn false\n\t\t},\n\t}\n\treturn getCandidatePkgs(ctx, callback, filename, filePkg, env)\n}\n\n// GetImportPaths calls wrapped for each package whose import path starts with\n// searchPrefix, and can be imported from filename with the package name filePkg.\nfunc GetImportPaths(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error {\n\tcallback := &scanCallback{\n\t\trootFound: func(gopathwalk.Root) bool {\n\t\t\treturn true\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\tif !CanUse(filename, pkg.dir) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn strings.HasPrefix(pkg.importPathShort, searchPrefix)\n\t\t},\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\twrapped(ImportFix{\n\t\t\t\tStmtInfo: ImportInfo{\n\t\t\t\t\tImportPath: pkg.importPathShort,\n\t\t\t\t\tName:       candidateImportName(pkg),\n\t\t\t\t},\n\t\t\t\tIdentName: pkg.packageName,\n\t\t\t\tFixType:   AddImport,\n\t\t\t\tRelevance: pkg.relevance,\n\t\t\t})\n\t\t\treturn false\n\t\t},\n\t}\n\treturn getCandidatePkgs(ctx, callback, filename, filePkg, env)\n}\n\n// A PackageExport is a package and its exports.\ntype PackageExport struct {\n\tFix     *ImportFix\n\tExports []stdlib.Symbol\n}\n\n// GetPackageExports returns all known packages with name pkg and their exports.\nfunc GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error {\n\tcallback := &scanCallback{\n\t\trootFound: func(gopathwalk.Root) bool {\n\t\t\treturn true\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\treturn pkgIsCandidate(filename, References{searchPkg: nil}, pkg)\n\t\t},\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\treturn pkg.packageName == searchPkg\n\t\t},\n\t\texportsLoaded: func(pkg *pkg, exports []stdlib.Symbol) {\n\t\t\tsortSymbols(exports)\n\t\t\twrapped(PackageExport{\n\t\t\t\tFix: &ImportFix{\n\t\t\t\t\tStmtInfo: ImportInfo{\n\t\t\t\t\t\tImportPath: pkg.importPathShort,\n\t\t\t\t\t\tName:       candidateImportName(pkg),\n\t\t\t\t\t},\n\t\t\t\t\tIdentName: pkg.packageName,\n\t\t\t\t\tFixType:   AddImport,\n\t\t\t\t\tRelevance: pkg.relevance,\n\t\t\t\t},\n\t\t\t\tExports: exports,\n\t\t\t})\n\t\t},\n\t}\n\treturn getCandidatePkgs(ctx, callback, filename, filePkg, env)\n}\n\n// TODO(rfindley): we should depend on GOOS and GOARCH, to provide accurate\n// imports when doing cross-platform development.\nvar requiredGoEnvVars = []string{\n\t\"GO111MODULE\",\n\t\"GOFLAGS\",\n\t\"GOINSECURE\",\n\t\"GOMOD\",\n\t\"GOMODCACHE\",\n\t\"GONOPROXY\",\n\t\"GONOSUMDB\",\n\t\"GOPATH\",\n\t\"GOPROXY\",\n\t\"GOROOT\",\n\t\"GOSUMDB\",\n\t\"GOWORK\",\n}\n\n// ProcessEnv contains environment variables and settings that affect the use of\n// the go command, the go/build package, etc.\n//\n// ...a ProcessEnv *also* overwrites its Env along with derived state in the\n// form of the resolver. And because it is lazily initialized, an env may just\n// be broken and unusable, but there is no way for the caller to detect that:\n// all queries will just fail.\n//\n// TODO(rfindley): refactor this package so that this type (perhaps renamed to\n// just Env or Config) is an immutable configuration struct, to be exchanged\n// for an initialized object via a constructor that returns an error. Perhaps\n// the signature should be `func NewResolver(*Env) (*Resolver, error)`, where\n// resolver is a concrete type used for resolving imports. Via this\n// refactoring, we can avoid the need to call ProcessEnv.init and\n// ProcessEnv.GoEnv everywhere, and implicitly fix all the places where this\n// these are misused. Also, we'd delegate the caller the decision of how to\n// handle a broken environment.\ntype ProcessEnv struct {\n\tGocmdRunner *gocommand.Runner\n\n\tBuildFlags []string\n\tModFlag    string\n\n\t// SkipPathInScan returns true if the path should be skipped from scans of\n\t// the RootCurrentModule root type. The function argument is a clean,\n\t// absolute path.\n\tSkipPathInScan func(string) bool\n\n\t// Env overrides the OS environment, and can be used to specify\n\t// GOPROXY, GO111MODULE, etc. PATH cannot be set here, because\n\t// exec.Command will not honor it.\n\t// Specifying all of requiredGoEnvVars avoids a call to `go env`.\n\tEnv map[string]string\n\n\tWorkingDir string\n\n\t// If Logf is non-nil, debug logging is enabled through this function.\n\tLogf func(format string, args ...any)\n\n\t// If set, ModCache holds a shared cache of directory info to use across\n\t// multiple ProcessEnvs.\n\tModCache *DirInfoCache\n\n\tinitialized bool // see TODO above\n\n\t// resolver and resolverErr are lazily evaluated (see GetResolver).\n\t// This is unclean, but see the big TODO in the docstring for ProcessEnv\n\t// above: for now, we can't be sure that the ProcessEnv is fully initialized.\n\tresolver    Resolver\n\tresolverErr error\n}\n\nfunc (e *ProcessEnv) goEnv() (map[string]string, error) {\n\tif err := e.init(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e.Env, nil\n}\n\nfunc (e *ProcessEnv) matchFile(dir, name string) (bool, error) {\n\tbctx, err := e.buildContext()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn bctx.MatchFile(dir, name)\n}\n\n// CopyConfig copies the env's configuration into a new env.\nfunc (e *ProcessEnv) CopyConfig() *ProcessEnv {\n\tcopy := &ProcessEnv{\n\t\tGocmdRunner: e.GocmdRunner,\n\t\tinitialized: e.initialized,\n\t\tBuildFlags:  e.BuildFlags,\n\t\tLogf:        e.Logf,\n\t\tWorkingDir:  e.WorkingDir,\n\t\tresolver:    nil,\n\t\tEnv:         map[string]string{},\n\t}\n\tmaps.Copy(copy.Env, e.Env)\n\treturn copy\n}\n\nfunc (e *ProcessEnv) init() error {\n\tif e.initialized {\n\t\treturn nil\n\t}\n\n\tfoundAllRequired := true\n\tfor _, k := range requiredGoEnvVars {\n\t\tif _, ok := e.Env[k]; !ok {\n\t\t\tfoundAllRequired = false\n\t\t\tbreak\n\t\t}\n\t}\n\tif foundAllRequired {\n\t\te.initialized = true\n\t\treturn nil\n\t}\n\n\tif e.Env == nil {\n\t\te.Env = map[string]string{}\n\t}\n\n\tgoEnv := map[string]string{}\n\tstdout, err := e.invokeGo(context.TODO(), \"env\", append([]string{\"-json\"}, requiredGoEnvVars...)...)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := json.Unmarshal(stdout.Bytes(), &goEnv); err != nil {\n\t\treturn err\n\t}\n\tmaps.Copy(e.Env, goEnv)\n\te.initialized = true\n\treturn nil\n}\n\nfunc (e *ProcessEnv) env() []string {\n\tvar env []string // the gocommand package will prepend os.Environ.\n\tfor k, v := range e.Env {\n\t\tenv = append(env, k+\"=\"+v)\n\t}\n\treturn env\n}\n\nfunc (e *ProcessEnv) GetResolver() (Resolver, error) {\n\tif err := e.init(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif e.resolver == nil && e.resolverErr == nil {\n\t\t// TODO(rfindley): we should only use a gopathResolver here if the working\n\t\t// directory is actually *in* GOPATH. (I seem to recall an open gopls issue\n\t\t// for this behavior, but I can't find it).\n\t\t//\n\t\t// For gopls, we can optionally explicitly choose a resolver type, since we\n\t\t// already know the view type.\n\t\tif e.Env[\"GOMOD\"] == \"\" && (e.Env[\"GOWORK\"] == \"\" || e.Env[\"GOWORK\"] == \"off\") {\n\t\t\te.resolver = newGopathResolver(e)\n\t\t\te.logf(\"created gopath resolver\")\n\t\t} else if r, err := newModuleResolver(e, e.ModCache); err != nil {\n\t\t\te.resolverErr = err\n\t\t\te.logf(\"failed to create module resolver: %v\", err)\n\t\t} else {\n\t\t\te.resolver = Resolver(r)\n\t\t\te.logf(\"created module resolver\")\n\t\t}\n\t}\n\n\treturn e.resolver, e.resolverErr\n}\n\n// logf logs if e.Logf is non-nil.\nfunc (e *ProcessEnv) logf(format string, args ...any) {\n\tif e.Logf != nil {\n\t\te.Logf(format, args...)\n\t}\n}\n\n// buildContext returns the build.Context to use for matching files.\n//\n// TODO(rfindley): support dynamic GOOS, GOARCH here, when doing cross-platform\n// development.\nfunc (e *ProcessEnv) buildContext() (*build.Context, error) {\n\tctx := build.Default\n\tgoenv, err := e.goEnv()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tctx.GOROOT = goenv[\"GOROOT\"]\n\tctx.GOPATH = goenv[\"GOPATH\"]\n\n\t// As of Go 1.14, build.Context has a Dir field\n\t// (see golang.org/issue/34860).\n\t// Populate it only if present.\n\trc := reflect.ValueOf(&ctx).Elem()\n\tdir := rc.FieldByName(\"Dir\")\n\tif dir.IsValid() && dir.Kind() == reflect.String {\n\t\tdir.SetString(e.WorkingDir)\n\t}\n\n\t// Since Go 1.11, go/build.Context.Import may invoke 'go list' depending on\n\t// the value in GO111MODULE in the process's environment. We always want to\n\t// run in GOPATH mode when calling Import, so we need to prevent this from\n\t// happening. In Go 1.16, GO111MODULE defaults to \"on\", so this problem comes\n\t// up more frequently.\n\t//\n\t// HACK: setting any of the Context I/O hooks prevents Import from invoking\n\t// 'go list', regardless of GO111MODULE. This is undocumented, but it's\n\t// unlikely to change before GOPATH support is removed.\n\tctx.ReadDir = ioutil.ReadDir\n\n\treturn &ctx, nil\n}\n\nfunc (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) (*bytes.Buffer, error) {\n\tinv := gocommand.Invocation{\n\t\tVerb:       verb,\n\t\tArgs:       args,\n\t\tBuildFlags: e.BuildFlags,\n\t\tEnv:        e.env(),\n\t\tLogf:       e.Logf,\n\t\tWorkingDir: e.WorkingDir,\n\t}\n\treturn e.GocmdRunner.Run(ctx, inv)\n}\n\nfunc addStdlibCandidates(pass *pass, refs References) error {\n\tlocalbase := func(nm string) string {\n\t\tans := path.Base(nm)\n\t\tif ans[0] == 'v' {\n\t\t\t// this is called, for instance, with math/rand/v2 and returns rand/v2\n\t\t\tif _, err := strconv.Atoi(ans[1:]); err == nil {\n\t\t\t\tix := strings.LastIndex(nm, ans)\n\t\t\t\tmore := path.Base(nm[:ix])\n\t\t\t\tans = path.Join(more, ans)\n\t\t\t}\n\t\t}\n\t\treturn ans\n\t}\n\tadd := func(pkg string) {\n\t\t// Prevent self-imports.\n\t\tif path.Base(pkg) == pass.f.Name.Name && filepath.Join(pass.goroot, \"src\", pkg) == pass.srcDir {\n\t\t\treturn\n\t\t}\n\t\texports := symbolNameSet(stdlib.PackageSymbols[pkg])\n\t\tpass.addCandidate(\n\t\t\t&ImportInfo{ImportPath: pkg},\n\t\t\t&PackageInfo{Name: localbase(pkg), Exports: exports})\n\t}\n\tfor left := range refs {\n\t\tif left == \"rand\" {\n\t\t\t// Make sure we try crypto/rand before any version of math/rand as both have Int()\n\t\t\t// and our policy is to recommend crypto\n\t\t\tadd(\"crypto/rand\")\n\t\t\t// if the user's no later than go1.21, this should be \"math/rand\"\n\t\t\t// but we have no way of figuring out what the user is using\n\t\t\t// TODO: investigate using the toolchain version to disambiguate in the stdlib\n\t\t\tadd(\"math/rand/v2\")\n\t\t\t// math/rand has an overlapping API\n\t\t\t// TestIssue66407 fails without this\n\t\t\tadd(\"math/rand\")\n\t\t\tcontinue\n\t\t}\n\t\tfor importPath := range stdlib.PackageSymbols {\n\t\t\tif path.Base(importPath) == left {\n\t\t\t\tadd(importPath)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// A Resolver does the build-system-specific parts of goimports.\ntype Resolver interface {\n\t// loadPackageNames loads the package names in importPaths.\n\tloadPackageNames(importPaths []string, srcDir string) (map[string]string, error)\n\n\t// scan works with callback to search for packages. See scanCallback for details.\n\tscan(ctx context.Context, callback *scanCallback) error\n\n\t// loadExports returns the package name and set of exported symbols in the\n\t// package at dir. loadExports may be called concurrently.\n\tloadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error)\n\n\t// scoreImportPath returns the relevance for an import path.\n\tscoreImportPath(ctx context.Context, path string) float64\n\n\t// ClearForNewScan returns a new Resolver based on the receiver that has\n\t// cleared its internal caches of directory contents.\n\t//\n\t// The new resolver should be primed and then set via\n\t// [ProcessEnv.UpdateResolver].\n\tClearForNewScan() Resolver\n}\n\n// A scanCallback controls a call to scan and receives its results.\n// In general, minor errors will be silently discarded; a user should not\n// expect to receive a full series of calls for everything.\ntype scanCallback struct {\n\t// rootFound is called before scanning a new root dir. If it returns true,\n\t// the root will be scanned. Returning false will not necessarily prevent\n\t// directories from that root making it to dirFound.\n\trootFound func(gopathwalk.Root) bool\n\t// dirFound is called when a directory is found that is possibly a Go package.\n\t// pkg will be populated with everything except packageName.\n\t// If it returns true, the package's name will be loaded.\n\tdirFound func(pkg *pkg) bool\n\t// packageNameLoaded is called when a package is found and its name is loaded.\n\t// If it returns true, the package's exports will be loaded.\n\tpackageNameLoaded func(pkg *pkg) bool\n\t// exportsLoaded is called when a package's exports have been loaded.\n\texportsLoaded func(pkg *pkg, exports []stdlib.Symbol)\n}\n\nfunc addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string) error {\n\tctx, done := event.Start(ctx, \"imports.addExternalCandidates\")\n\tdefer done()\n\n\tresults, err := pass.source.ResolveReferences(ctx, filename, refs)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, result := range results {\n\t\tif result == nil {\n\t\t\tcontinue\n\t\t}\n\t\t// Don't offer completions that would shadow predeclared\n\t\t// names, such as github.com/coreos/etcd/error.\n\t\tif types.Universe.Lookup(result.Package.Name) != nil { // predeclared\n\t\t\t// Ideally we would skip this candidate only\n\t\t\t// if the predeclared name is actually\n\t\t\t// referenced by the file, but that's a lot\n\t\t\t// trickier to compute and would still create\n\t\t\t// an import that is likely to surprise the\n\t\t\t// user before long.\n\t\t\tcontinue\n\t\t}\n\t\tpass.addCandidate(result.Import, result.Package)\n\t}\n\treturn nil\n}\n\n// notIdentifier reports whether ch is an invalid identifier character.\nfunc notIdentifier(ch rune) bool {\n\treturn !('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' ||\n\t\t'0' <= ch && ch <= '9' ||\n\t\tch == '_' ||\n\t\tch >= utf8.RuneSelf && (unicode.IsLetter(ch) || unicode.IsDigit(ch)))\n}\n\n// ImportPathToAssumedName returns the assumed package name of an import path.\n// It does this using only string parsing of the import path.\n// It picks the last element of the path that does not look like a major\n// version, and then picks the valid identifier off the start of that element.\n// It is used to determine if a local rename should be added to an import for\n// clarity.\n// This function could be moved to a standard package and exported if we want\n// for use in other tools.\nfunc ImportPathToAssumedName(importPath string) string {\n\tbase := path.Base(importPath)\n\tif strings.HasPrefix(base, \"v\") {\n\t\tif _, err := strconv.Atoi(base[1:]); err == nil {\n\t\t\tdir := path.Dir(importPath)\n\t\t\tif dir != \".\" {\n\t\t\t\tbase = path.Base(dir)\n\t\t\t}\n\t\t}\n\t}\n\tbase = strings.TrimPrefix(base, \"go-\")\n\tif i := strings.IndexFunc(base, notIdentifier); i >= 0 {\n\t\tbase = base[:i]\n\t}\n\treturn base\n}\n\n// gopathResolver implements resolver for GOPATH workspaces.\ntype gopathResolver struct {\n\tenv      *ProcessEnv\n\tcache    *DirInfoCache\n\tscanSema chan struct{} // scanSema prevents concurrent scans.\n}\n\nfunc newGopathResolver(env *ProcessEnv) *gopathResolver {\n\tr := &gopathResolver{\n\t\tenv:      env,\n\t\tcache:    NewDirInfoCache(),\n\t\tscanSema: make(chan struct{}, 1),\n\t}\n\tr.scanSema <- struct{}{}\n\treturn r\n}\n\nfunc (r *gopathResolver) ClearForNewScan() Resolver {\n\treturn newGopathResolver(r.env)\n}\n\nfunc (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {\n\tnames := map[string]string{}\n\tbctx, err := r.env.buildContext()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, path := range importPaths {\n\t\tnames[path] = importPathToName(bctx, path, srcDir)\n\t}\n\treturn names, nil\n}\n\n// importPathToName finds out the actual package name, as declared in its .go files.\nfunc importPathToName(bctx *build.Context, importPath, srcDir string) string {\n\t// Fast path for standard library without going to disk.\n\tif stdlib.HasPackage(importPath) {\n\t\treturn path.Base(importPath) // stdlib packages always match their paths.\n\t}\n\n\tbuildPkg, err := bctx.Import(importPath, srcDir, build.FindOnly)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\tpkgName, err := packageDirToName(buildPkg.Dir)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn pkgName\n}\n\n// packageDirToName is a faster version of build.Import if\n// the only thing desired is the package name. Given a directory,\n// packageDirToName then only parses one file in the package,\n// trusting that the files in the directory are consistent.\nfunc packageDirToName(dir string) (packageName string, err error) {\n\td, err := os.Open(dir)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tnames, err := d.Readdirnames(-1)\n\td.Close()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tsort.Strings(names) // to have predictable behavior\n\tvar lastErr error\n\tvar nfile int\n\tfor _, name := range names {\n\t\tif !strings.HasSuffix(name, \".go\") {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasSuffix(name, \"_test.go\") {\n\t\t\tcontinue\n\t\t}\n\t\tnfile++\n\t\tfullFile := filepath.Join(dir, name)\n\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, fullFile, nil, parser.PackageClauseOnly)\n\t\tif err != nil {\n\t\t\tlastErr = err\n\t\t\tcontinue\n\t\t}\n\t\tpkgName := f.Name.Name\n\t\tif pkgName == \"documentation\" {\n\t\t\t// Special case from go/build.ImportDir, not\n\t\t\t// handled by ctx.MatchFile.\n\t\t\tcontinue\n\t\t}\n\t\tif pkgName == \"main\" {\n\t\t\t// Also skip package main, assuming it's a +build ignore generator or example.\n\t\t\t// Since you can't import a package main anyway, there's no harm here.\n\t\t\tcontinue\n\t\t}\n\t\treturn pkgName, nil\n\t}\n\tif lastErr != nil {\n\t\treturn \"\", lastErr\n\t}\n\treturn \"\", fmt.Errorf(\"no importable package found in %d Go files\", nfile)\n}\n\ntype pkg struct {\n\tdir             string  // absolute file path to pkg directory (\"/usr/lib/go/src/net/http\")\n\timportPathShort string  // vendorless import path (\"net/http\", \"a/b\")\n\tpackageName     string  // package name loaded from source if requested\n\trelevance       float64 // a weakly-defined score of how relevant a package is. 0 is most relevant.\n}\n\ntype pkgDistance struct {\n\tpkg      *pkg\n\tdistance int // relative distance to target\n}\n\n// byDistanceOrImportPathShortLength sorts by relative distance breaking ties\n// on the short import path length and then the import string itself.\ntype byDistanceOrImportPathShortLength []pkgDistance\n\nfunc (s byDistanceOrImportPathShortLength) Len() int { return len(s) }\nfunc (s byDistanceOrImportPathShortLength) Less(i, j int) bool {\n\tdi, dj := s[i].distance, s[j].distance\n\tif di == -1 {\n\t\treturn false\n\t}\n\tif dj == -1 {\n\t\treturn true\n\t}\n\tif di != dj {\n\t\treturn di < dj\n\t}\n\n\tvi, vj := s[i].pkg.importPathShort, s[j].pkg.importPathShort\n\tif len(vi) != len(vj) {\n\t\treturn len(vi) < len(vj)\n\t}\n\treturn vi < vj\n}\nfunc (s byDistanceOrImportPathShortLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }\n\nfunc distance(basepath, targetpath string) int {\n\tp, err := filepath.Rel(basepath, targetpath)\n\tif err != nil {\n\t\treturn -1\n\t}\n\tif p == \".\" {\n\t\treturn 0\n\t}\n\treturn strings.Count(p, string(filepath.Separator)) + 1\n}\n\nfunc (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error {\n\tadd := func(root gopathwalk.Root, dir string) {\n\t\t// We assume cached directories have not changed. We can skip them and their\n\t\t// children.\n\t\tif _, ok := r.cache.Load(dir); ok {\n\t\t\treturn\n\t\t}\n\n\t\timportpath := filepath.ToSlash(dir[len(root.Path)+len(\"/\"):])\n\t\tinfo := directoryPackageInfo{\n\t\t\tstatus:                 directoryScanned,\n\t\t\tdir:                    dir,\n\t\t\trootType:               root.Type,\n\t\t\tnonCanonicalImportPath: VendorlessPath(importpath),\n\t\t}\n\t\tr.cache.Store(dir, info)\n\t}\n\tprocessDir := func(info directoryPackageInfo) {\n\t\t// Skip this directory if we were not able to get the package information successfully.\n\t\tif scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tp := &pkg{\n\t\t\timportPathShort: info.nonCanonicalImportPath,\n\t\t\tdir:             info.dir,\n\t\t\trelevance:       MaxRelevance - 1,\n\t\t}\n\t\tif info.rootType == gopathwalk.RootGOROOT {\n\t\t\tp.relevance = MaxRelevance\n\t\t}\n\n\t\tif !callback.dirFound(p) {\n\t\t\treturn\n\t\t}\n\t\tvar err error\n\t\tp.packageName, err = r.cache.CachePackageName(info)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tif !callback.packageNameLoaded(p) {\n\t\t\treturn\n\t\t}\n\t\tif _, exports, err := r.loadExports(ctx, p, false); err == nil {\n\t\t\tcallback.exportsLoaded(p, exports)\n\t\t}\n\t}\n\tstop := r.cache.ScanAndListen(ctx, processDir)\n\tdefer stop()\n\n\tgoenv, err := r.env.goEnv()\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar roots []gopathwalk.Root\n\troots = append(roots, gopathwalk.Root{Path: filepath.Join(goenv[\"GOROOT\"], \"src\"), Type: gopathwalk.RootGOROOT})\n\tfor _, p := range filepath.SplitList(goenv[\"GOPATH\"]) {\n\t\troots = append(roots, gopathwalk.Root{Path: filepath.Join(p, \"src\"), Type: gopathwalk.RootGOPATH})\n\t}\n\t// The callback is not necessarily safe to use in the goroutine below. Process roots eagerly.\n\troots = filterRoots(roots, callback.rootFound)\n\t// We can't cancel walks, because we need them to finish to have a usable\n\t// cache. Instead, run them in a separate goroutine and detach.\n\tscanDone := make(chan struct{})\n\tgo func() {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tcase <-r.scanSema:\n\t\t}\n\t\tdefer func() { r.scanSema <- struct{}{} }()\n\t\tgopathwalk.Walk(roots, add, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: false})\n\t\tclose(scanDone)\n\t}()\n\tselect {\n\tcase <-ctx.Done():\n\tcase <-scanDone:\n\t}\n\treturn nil\n}\n\nfunc (r *gopathResolver) scoreImportPath(ctx context.Context, path string) float64 {\n\tif stdlib.HasPackage(path) {\n\t\treturn MaxRelevance\n\t}\n\treturn MaxRelevance - 1\n}\n\nfunc filterRoots(roots []gopathwalk.Root, include func(gopathwalk.Root) bool) []gopathwalk.Root {\n\tvar result []gopathwalk.Root\n\tfor _, root := range roots {\n\t\tif !include(root) {\n\t\t\tcontinue\n\t\t}\n\t\tresult = append(result, root)\n\t}\n\treturn result\n}\n\nfunc (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) {\n\tif info, ok := r.cache.Load(pkg.dir); ok && !includeTest {\n\t\treturn r.cache.CacheExports(ctx, r.env, info)\n\t}\n\treturn loadExportsFromFiles(ctx, r.env, pkg.dir, includeTest)\n}\n\n// VendorlessPath returns the devendorized version of the import path ipath.\n// For example, VendorlessPath(\"foo/bar/vendor/a/b\") returns \"a/b\".\nfunc VendorlessPath(ipath string) string {\n\t// Devendorize for use in import statement.\n\tif i := strings.LastIndex(ipath, \"/vendor/\"); i >= 0 {\n\t\treturn ipath[i+len(\"/vendor/\"):]\n\t}\n\tif strings.HasPrefix(ipath, \"vendor/\") {\n\t\treturn ipath[len(\"vendor/\"):]\n\t}\n\treturn ipath\n}\n\nfunc loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []stdlib.Symbol, error) {\n\t// Look for non-test, buildable .go files which could provide exports.\n\tall, err := os.ReadDir(dir)\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tvar files []fs.DirEntry\n\tfor _, fi := range all {\n\t\tname := fi.Name()\n\t\tif !strings.HasSuffix(name, \".go\") || (!includeTest && strings.HasSuffix(name, \"_test.go\")) {\n\t\t\tcontinue\n\t\t}\n\t\tmatch, err := env.matchFile(dir, fi.Name())\n\t\tif err != nil || !match {\n\t\t\tcontinue\n\t\t}\n\t\tfiles = append(files, fi)\n\t}\n\n\tif len(files) == 0 {\n\t\treturn \"\", nil, fmt.Errorf(\"dir %v contains no buildable, non-test .go files\", dir)\n\t}\n\n\tvar pkgName string\n\tvar exports []stdlib.Symbol\n\tfset := token.NewFileSet()\n\tfor _, fi := range files {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn \"\", nil, ctx.Err()\n\t\tdefault:\n\t\t}\n\n\t\tfullFile := filepath.Join(dir, fi.Name())\n\t\t// Legacy ast.Object resolution is needed here.\n\t\tf, err := parser.ParseFile(fset, fullFile, nil, 0)\n\t\tif err != nil {\n\t\t\tenv.logf(\"error parsing %v: %v\", fullFile, err)\n\t\t\tcontinue\n\t\t}\n\t\tif f.Name.Name == \"documentation\" {\n\t\t\t// Special case from go/build.ImportDir, not\n\t\t\t// handled by MatchFile above.\n\t\t\tcontinue\n\t\t}\n\t\tif includeTest && strings.HasSuffix(f.Name.Name, \"_test\") {\n\t\t\t// x_test package. We want internal test files only.\n\t\t\tcontinue\n\t\t}\n\t\tpkgName = f.Name.Name\n\t\tfor name, obj := range f.Scope.Objects {\n\t\t\tif ast.IsExported(name) {\n\t\t\t\tvar kind stdlib.Kind\n\t\t\t\tswitch obj.Kind {\n\t\t\t\tcase ast.Con:\n\t\t\t\t\tkind = stdlib.Const\n\t\t\t\tcase ast.Typ:\n\t\t\t\t\tkind = stdlib.Type\n\t\t\t\tcase ast.Var:\n\t\t\t\t\tkind = stdlib.Var\n\t\t\t\tcase ast.Fun:\n\t\t\t\t\tkind = stdlib.Func\n\t\t\t\t}\n\t\t\t\texports = append(exports, stdlib.Symbol{\n\t\t\t\t\tName:    name,\n\t\t\t\t\tKind:    kind,\n\t\t\t\t\tVersion: 0, // unknown; be permissive\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\tsortSymbols(exports)\n\n\tenv.logf(\"loaded exports in dir %v (package %v): %v\", dir, pkgName, exports)\n\treturn pkgName, exports, nil\n}\n\nfunc sortSymbols(syms []stdlib.Symbol) {\n\tsort.Slice(syms, func(i, j int) bool {\n\t\treturn syms[i].Name < syms[j].Name\n\t})\n}\n\n// A symbolSearcher searches for a package with a set of symbols, among a set\n// of candidates. See [symbolSearcher.search].\n//\n// The search occurs within the scope of a single file, with context captured\n// in srcDir and xtest.\ntype symbolSearcher struct {\n\tlogf        func(string, ...any)\n\tsrcDir      string // directory containing the file\n\txtest       bool   // if set, the file containing is an x_test file\n\tloadExports func(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error)\n}\n\n// search searches the provided candidates for a package containing all\n// exported symbols.\n//\n// If successful, returns the resulting package.\nfunc (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, pkgName string, symbols map[string]bool) (*pkg, error) {\n\t// Sort the candidates by their import package length,\n\t// assuming that shorter package names are better than long\n\t// ones.  Note that this sorts by the de-vendored name, so\n\t// there's no \"penalty\" for vendoring.\n\tsort.Sort(byDistanceOrImportPathShortLength(candidates))\n\tif s.logf != nil {\n\t\tfor i, c := range candidates {\n\t\t\ts.logf(\"%s candidate %d/%d: %v in %v\", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir)\n\t\t}\n\t}\n\n\t// Arrange rescv so that we can we can await results in order of relevance\n\t// and exit as soon as we find the first match.\n\t//\n\t// Search with bounded concurrency, returning as soon as the first result\n\t// among rescv is non-nil.\n\trescv := make([]chan *pkg, len(candidates))\n\tfor i := range candidates {\n\t\trescv[i] = make(chan *pkg, 1)\n\t}\n\tconst maxConcurrentPackageImport = 4\n\tloadExportsSem := make(chan struct{}, maxConcurrentPackageImport)\n\n\t// Ensure that all work is completed at exit.\n\tctx, cancel := context.WithCancel(ctx)\n\tvar wg sync.WaitGroup\n\tdefer func() {\n\t\tcancel()\n\t\twg.Wait()\n\t}()\n\n\t// Start the search.\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor i, c := range candidates {\n\t\t\tselect {\n\t\t\tcase loadExportsSem <- struct{}{}:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ti := i\n\t\t\tc := c\n\t\t\twg.Add(1)\n\t\t\tgo func() {\n\t\t\t\tdefer func() {\n\t\t\t\t\t<-loadExportsSem\n\t\t\t\t\twg.Done()\n\t\t\t\t}()\n\t\t\t\tif s.logf != nil {\n\t\t\t\t\ts.logf(\"loading exports in dir %s (seeking package %s)\", c.pkg.dir, pkgName)\n\t\t\t\t}\n\t\t\t\tpkg, err := s.searchOne(ctx, c, symbols)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif s.logf != nil && ctx.Err() == nil {\n\t\t\t\t\t\ts.logf(\"loading exports in dir %s (seeking package %s): %v\", c.pkg.dir, pkgName, err)\n\t\t\t\t\t}\n\t\t\t\t\tpkg = nil\n\t\t\t\t}\n\t\t\t\trescv[i] <- pkg // may be nil\n\t\t\t}()\n\t\t}\n\t}()\n\n\t// Await the first (best) result.\n\tfor _, resc := range rescv {\n\t\tselect {\n\t\tcase r := <-resc:\n\t\t\tif r != nil {\n\t\t\t\treturn r, nil\n\t\t\t}\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc (s *symbolSearcher) searchOne(ctx context.Context, c pkgDistance, symbols map[string]bool) (*pkg, error) {\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\t// If we're considering the package under test from an x_test, load the\n\t// test variant.\n\tincludeTest := s.xtest && c.pkg.dir == s.srcDir\n\t_, exports, err := s.loadExports(ctx, c.pkg, includeTest)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\texportsMap := make(map[string]bool, len(exports))\n\tfor _, sym := range exports {\n\t\texportsMap[sym.Name] = true\n\t}\n\tfor symbol := range symbols {\n\t\tif !exportsMap[symbol] {\n\t\t\treturn nil, nil // no match\n\t\t}\n\t}\n\treturn c.pkg, nil\n}\n\n// pkgIsCandidate reports whether pkg is a candidate for satisfying the\n// finding which package pkgIdent in the file named by filename is trying\n// to refer to.\n//\n// This check is purely lexical and is meant to be as fast as possible\n// because it's run over all $GOPATH directories to filter out poor\n// candidates in order to limit the CPU and I/O later parsing the\n// exports in candidate packages.\n//\n// filename is the file being formatted.\n// pkgIdent is the package being searched for, like \"client\" (if\n// searching for \"client.New\")\nfunc pkgIsCandidate(filename string, refs References, pkg *pkg) bool {\n\t// Check \"internal\" and \"vendor\" visibility:\n\tif !CanUse(filename, pkg.dir) {\n\t\treturn false\n\t}\n\n\t// Speed optimization to minimize disk I/O:\n\t//\n\t// Use the matchesPath heuristic to filter to package paths that could\n\t// reasonably match a dangling reference.\n\t//\n\t// This permits mismatch naming like directory \"go-foo\" being package \"foo\",\n\t// or \"pkg.v3\" being \"pkg\", or directory\n\t// \"google.golang.org/api/cloudbilling/v1\" being package \"cloudbilling\", but\n\t// doesn't permit a directory \"foo\" to be package \"bar\", which is strongly\n\t// discouraged anyway. There's no reason goimports needs to be slow just to\n\t// accommodate that.\n\tfor pkgIdent := range refs {\n\t\tif matchesPath(pkgIdent, pkg.importPathShort) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// CanUse reports whether the package in dir is usable from filename,\n// respecting the Go \"internal\" and \"vendor\" visibility rules.\nfunc CanUse(filename, dir string) bool {\n\t// Fast path check, before any allocations. If it doesn't contain vendor\n\t// or internal, it's not tricky:\n\t// Note that this can false-negative on directories like \"notinternal\",\n\t// but we check it correctly below. This is just a fast path.\n\tif !strings.Contains(dir, \"vendor\") && !strings.Contains(dir, \"internal\") {\n\t\treturn true\n\t}\n\n\tdirSlash := filepath.ToSlash(dir)\n\tif !strings.Contains(dirSlash, \"/vendor/\") && !strings.Contains(dirSlash, \"/internal/\") && !strings.HasSuffix(dirSlash, \"/internal\") {\n\t\treturn true\n\t}\n\t// Vendor or internal directory only visible from children of parent.\n\t// That means the path from the current directory to the target directory\n\t// can contain ../vendor or ../internal but not ../foo/vendor or ../foo/internal\n\t// or bar/vendor or bar/internal.\n\t// After stripping all the leading ../, the only okay place to see vendor or internal\n\t// is at the very beginning of the path.\n\tabsfile, err := filepath.Abs(filename)\n\tif err != nil {\n\t\treturn false\n\t}\n\tabsdir, err := filepath.Abs(dir)\n\tif err != nil {\n\t\treturn false\n\t}\n\trel, err := filepath.Rel(absfile, absdir)\n\tif err != nil {\n\t\treturn false\n\t}\n\trelSlash := filepath.ToSlash(rel)\n\tif i := strings.LastIndex(relSlash, \"../\"); i >= 0 {\n\t\trelSlash = relSlash[i+len(\"../\"):]\n\t}\n\treturn !strings.Contains(relSlash, \"/vendor/\") && !strings.Contains(relSlash, \"/internal/\") && !strings.HasSuffix(relSlash, \"/internal\")\n}\n\n// matchesPath reports whether ident may match a potential package name\n// referred to by path, using heuristics to filter out unidiomatic package\n// names.\n//\n// Specifically, it checks whether either of the last two '/'- or '\\'-delimited\n// path segments matches the identifier. The segment-matching heuristic must\n// allow for various conventions around segment naming, including go-foo,\n// foo-go, and foo.v3. To handle all of these, matching considers both (1) the\n// entire segment, ignoring '-' and '.', as well as (2) the last subsegment\n// separated by '-' or '.'. So the segment foo-go matches all of the following\n// identifiers: foo, go, and foogo. All matches are case insensitive (for ASCII\n// identifiers).\n//\n// See the docstring for [pkgIsCandidate] for an explanation of how this\n// heuristic filters potential candidate packages.\nfunc matchesPath(ident, path string) bool {\n\t// Ignore case, for ASCII.\n\tlowerIfASCII := func(b byte) byte {\n\t\tif 'A' <= b && b <= 'Z' {\n\t\t\treturn b + ('a' - 'A')\n\t\t}\n\t\treturn b\n\t}\n\n\t// match reports whether path[start:end] matches ident, ignoring [.-].\n\tmatch := func(start, end int) bool {\n\t\tii := len(ident) - 1 // current byte in ident\n\t\tpi := end - 1        // current byte in path\n\t\tfor ; pi >= start && ii >= 0; pi-- {\n\t\t\tpb := path[pi]\n\t\t\tif pb == '-' || pb == '.' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpb = lowerIfASCII(pb)\n\t\t\tib := lowerIfASCII(ident[ii])\n\t\t\tif pb != ib {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tii--\n\t\t}\n\t\treturn ii < 0 && pi < start // all bytes matched\n\t}\n\n\t// segmentEnd and subsegmentEnd hold the end points of the current segment\n\t// and subsegment intervals.\n\tsegmentEnd := len(path)\n\tsubsegmentEnd := len(path)\n\n\t// Count slashes; we only care about the last two segments.\n\tnslash := 0\n\n\tfor i := len(path) - 1; i >= 0; i-- {\n\t\tswitch b := path[i]; b {\n\t\t// TODO(rfindley): we handle backlashes here only because the previous\n\t\t// heuristic handled backslashes. This is perhaps overly defensive, but is\n\t\t// the result of many lessons regarding Chesterton's fence and the\n\t\t// goimports codebase.\n\t\t//\n\t\t// However, this function is only ever called with something called an\n\t\t// 'importPath'. Is it possible that this is a real import path, and\n\t\t// therefore we need only consider forward slashes?\n\t\tcase '/', '\\\\':\n\t\t\tif match(i+1, segmentEnd) || match(i+1, subsegmentEnd) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tnslash++\n\t\t\tif nslash == 2 {\n\t\t\t\treturn false // did not match above\n\t\t\t}\n\t\t\tsegmentEnd, subsegmentEnd = i, i // reset\n\t\tcase '-', '.':\n\t\t\tif match(i+1, subsegmentEnd) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tsubsegmentEnd = i\n\t\t}\n\t}\n\treturn match(0, segmentEnd) || match(0, subsegmentEnd)\n}\n\ntype visitFn func(node ast.Node) ast.Visitor\n\nfunc (fn visitFn) Visit(node ast.Node) ast.Visitor {\n\treturn fn(node)\n}\n\nfunc symbolNameSet(symbols []stdlib.Symbol) map[string]bool {\n\tnames := make(map[string]bool)\n\tfor _, sym := range symbols {\n\t\tswitch sym.Kind {\n\t\tcase stdlib.Const, stdlib.Var, stdlib.Type, stdlib.Func:\n\t\t\tnames[sym.Name] = true\n\t\t}\n\t}\n\treturn names\n}\n"
  },
  {
    "path": "internal/imports/fix_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"log\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/packagestest\"\n\t\"golang.org/x/tools/internal/stdlib\"\n)\n\nvar testDebug = flag.Bool(\"debug\", false, \"enable debug output\")\n\nvar tests = []struct {\n\tname       string\n\tformatOnly bool\n\tin, out    string\n}{\n\t// Adding an import to an existing parenthesized import\n\t{\n\t\tname: \"factored_imports_add\",\n\t\tin: `package foo\nimport (\n  \"fmt\"\n)\nfunc bar() {\nvar b bytes.Buffer\nfmt.Println(b.String())\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nfunc bar() {\n\tvar b bytes.Buffer\n\tfmt.Println(b.String())\n}\n`,\n\t},\n\n\t// Adding an import to an existing parenthesized import,\n\t// verifying it goes into the first section.\n\t{\n\t\tname: \"factored_imports_add_first_sec\",\n\t\tin: `package foo\nimport (\n  \"fmt\"\n\n  \"github.com/golang/snappy\"\n)\nfunc bar() {\nvar b bytes.Buffer\n_ = snappy.ErrCorrupt\nfmt.Println(b.String())\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\n\t\"github.com/golang/snappy\"\n)\n\nfunc bar() {\n\tvar b bytes.Buffer\n\t_ = snappy.ErrCorrupt\n\tfmt.Println(b.String())\n}\n`,\n\t},\n\n\t// Adding an import to an existing parenthesized import,\n\t// verifying it goes into the first section. (test 2)\n\t{\n\t\tname: \"factored_imports_add_first_sec_2\",\n\t\tin: `package foo\nimport (\n  \"fmt\"\n\n  \"github.com/golang/snappy\"\n)\nfunc bar() {\n_ = math.NaN\n_ = fmt.Sprintf\n_ = snappy.ErrCorrupt\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\n\t\"github.com/golang/snappy\"\n)\n\nfunc bar() {\n\t_ = math.NaN\n\t_ = fmt.Sprintf\n\t_ = snappy.ErrCorrupt\n}\n`,\n\t},\n\n\t// Adding a new import line, without parens\n\t{\n\t\tname: \"add_import_section\",\n\t\tin: `package foo\nfunc bar() {\nvar b bytes.Buffer\n}\n`,\n\t\tout: `package foo\n\nimport \"bytes\"\n\nfunc bar() {\n\tvar b bytes.Buffer\n}\n`,\n\t},\n\n\t// Adding two new imports, which should make a parenthesized import decl.\n\t{\n\t\tname: \"add_import_paren_section\",\n\t\tin: `package foo\nfunc bar() {\n_, _ := bytes.Buffer, zip.NewReader\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n)\n\nfunc bar() {\n\t_, _ := bytes.Buffer, zip.NewReader\n}\n`,\n\t},\n\n\t// Make sure we don't add things twice\n\t{\n\t\tname: \"no_double_add\",\n\t\tin: `package foo\nfunc bar() {\n_, _ := bytes.Buffer, bytes.NewReader\n}\n`,\n\t\tout: `package foo\n\nimport \"bytes\"\n\nfunc bar() {\n\t_, _ := bytes.Buffer, bytes.NewReader\n}\n`,\n\t},\n\n\t// Make sure we don't add packages that don't have the right exports\n\t{\n\t\tname: \"no_mismatched_add\",\n\t\tin: `package foo\n\nfunc bar() {\n\t_ := bytes.NonexistentSymbol\n}\n`,\n\t\tout: `package foo\n\nfunc bar() {\n\t_ := bytes.NonexistentSymbol\n}\n`,\n\t},\n\n\t// Remove unused imports, 1 of a factored block\n\t{\n\t\tname: \"remove_unused_1_of_2\",\n\t\tin: `package foo\nimport (\n\"bytes\"\n\"fmt\"\n)\n\nfunc bar() {\n_, _ := bytes.Buffer, bytes.NewReader\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"bytes\"\n)\n\nfunc bar() {\n\t_, _ := bytes.Buffer, bytes.NewReader\n}\n`,\n\t},\n\n\t// Remove unused imports, 2 of 2\n\t{\n\t\tname: \"remove_unused_2_of_2\",\n\t\tin: `package foo\nimport (\n\"bytes\"\n\"fmt\"\n)\n\nfunc bar() {\n}\n`,\n\t\tout: `package foo\n\nfunc bar() {\n}\n`,\n\t},\n\n\t// Remove unused imports, 1 of 1\n\t{\n\t\tname: \"remove_unused_1_of_1\",\n\t\tin: `package foo\n\nimport \"fmt\"\n\nfunc bar() {\n}\n`,\n\t\tout: `package foo\n\nfunc bar() {\n}\n`,\n\t},\n\n\t// Don't remove empty imports.\n\t{\n\t\tname: \"dont_remove_empty_imports\",\n\t\tin: `package foo\nimport (\n_ \"image/png\"\n_ \"image/jpeg\"\n)\n`,\n\t\tout: `package foo\n\nimport (\n\t_ \"image/jpeg\"\n\t_ \"image/png\"\n)\n`,\n\t},\n\n\t// Don't remove dot imports.\n\t{\n\t\tname: \"dont_remove_dot_imports\",\n\t\tin: `package foo\nimport (\n. \"foo\"\n. \"bar\"\n)\n`,\n\t\tout: `package foo\n\nimport (\n\t. \"bar\"\n\t. \"foo\"\n)\n`,\n\t},\n\n\t// Skip refs the parser can resolve.\n\t{\n\t\tname: \"skip_resolved_refs\",\n\t\tin: `package foo\n\nfunc f() {\n\ttype t struct{ Println func(string) }\n\tfmt := t{Println: func(string) {}}\n\tfmt.Println(\"foo\")\n}\n`,\n\t\tout: `package foo\n\nfunc f() {\n\ttype t struct{ Println func(string) }\n\tfmt := t{Println: func(string) {}}\n\tfmt.Println(\"foo\")\n}\n`,\n\t},\n\n\t// Do not add a package we already have a resolution for.\n\t{\n\t\tname: \"skip_template\",\n\t\tin: `package foo\n\nimport \"html/template\"\n\nfunc f() { t = template.New(\"sometemplate\") }\n`,\n\t\tout: `package foo\n\nimport \"html/template\"\n\nfunc f() { t = template.New(\"sometemplate\") }\n`,\n\t},\n\n\t// Don't touch cgo\n\t{\n\t\tname: \"cgo\",\n\t\tin: `package foo\n\n/*\n#include <foo.h>\n*/\nimport \"C\"\n`,\n\t\tout: `package foo\n\n/*\n#include <foo.h>\n*/\nimport \"C\"\n`,\n\t},\n\n\t// Put some things in their own section\n\t{\n\t\tname: \"make_sections\",\n\t\tin: `package foo\n\nimport (\n\"os\"\n)\n\nfunc foo () {\n_, _ = os.Args, fmt.Println\n_, _ = snappy.ErrCorrupt, p.P\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/golang/snappy\"\n\t\"rsc.io/p\"\n)\n\nfunc foo() {\n\t_, _ = os.Args, fmt.Println\n\t_, _ = snappy.ErrCorrupt, p.P\n}\n`,\n\t},\n\t// Merge import blocks, even when no additions are required.\n\t{\n\t\tname: \"merge_import_blocks_no_fix\",\n\t\tin: `package foo\n\nimport (\n\t\"fmt\"\n)\nimport \"os\"\n\nimport (\n\t\"rsc.io/p\"\n)\n\nvar _, _ = os.Args, fmt.Println\nvar _, _ = snappy.ErrCorrupt, p.P\n`,\n\t\tout: `package foo\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/golang/snappy\"\n\t\"rsc.io/p\"\n)\n\nvar _, _ = os.Args, fmt.Println\nvar _, _ = snappy.ErrCorrupt, p.P\n`,\n\t},\n\t// Delete existing empty import block\n\t{\n\t\tname: \"delete_empty_import_block\",\n\t\tin: `package foo\n\nimport ()\n`,\n\t\tout: `package foo\n`,\n\t},\n\n\t// Use existing empty import block\n\t{\n\t\tname: \"use_empty_import_block\",\n\t\tin: `package foo\n\nimport ()\n\nfunc f() {\n\t_ = fmt.Println\n}\n`,\n\t\tout: `package foo\n\nimport \"fmt\"\n\nfunc f() {\n\t_ = fmt.Println\n}\n`,\n\t},\n\n\t// Blank line before adding new section.\n\t{\n\t\tname: \"blank_line_before_new_group\",\n\t\tin: `package foo\n\nimport (\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc f() {\n\t_ = net.Dial\n\t_ = fmt.Printf\n\t_ = snappy.ErrCorrupt\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/golang/snappy\"\n)\n\nfunc f() {\n\t_ = net.Dial\n\t_ = fmt.Printf\n\t_ = snappy.ErrCorrupt\n}\n`,\n\t},\n\n\t// Blank line between standard library and third-party stuff.\n\t{\n\t\tname: \"blank_line_separating_std_and_third_party\",\n\t\tin: `package foo\n\nimport (\n\t\"github.com/golang/snappy\"\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc f() {\n\t_ = net.Dial\n\t_ = fmt.Printf\n\t_ = snappy.Foo\n}\n`,\n\t\tout: `package foo\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/golang/snappy\"\n)\n\nfunc f() {\n\t_ = net.Dial\n\t_ = fmt.Printf\n\t_ = snappy.Foo\n}\n`,\n\t},\n\n\t// golang.org/issue/6884\n\t{\n\t\tname: \"new_imports_before_comment\",\n\t\tin: `package main\n\n// A comment\nfunc main() {\n\tfmt.Println(\"Hello, world\")\n}\n`,\n\t\tout: `package main\n\nimport \"fmt\"\n\n// A comment\nfunc main() {\n\tfmt.Println(\"Hello, world\")\n}\n`,\n\t},\n\n\t// golang.org/issue/7132\n\t{\n\t\tname: \"new_section_for_dotless_import\",\n\t\tin: `package main\n\nimport (\n\"fmt\"\n\n\"gu\"\n\"manypackages.com/packagea\"\n)\n\nvar (\na = packagea.A\nb = gu.A\nc = fmt.Printf\n)\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"gu\"\n\n\t\"manypackages.com/packagea\"\n)\n\nvar (\n\ta = packagea.A\n\tb = gu.A\n\tc = fmt.Printf\n)\n`,\n\t},\n\n\t{\n\t\tname: \"fragment_with_main\",\n\t\tin:   `func main(){fmt.Println(\"Hello, world\")}`,\n\t\tout: `package main\n\nimport \"fmt\"\n\nfunc main() { fmt.Println(\"Hello, world\") }\n`,\n\t},\n\n\t{\n\t\tname: \"fragment_without_main\",\n\t\tin:   `func notmain(){fmt.Println(\"Hello, world\")}`,\n\t\tout: `import \"fmt\"\n\nfunc notmain() { fmt.Println(\"Hello, world\") }`,\n\t},\n\n\t// Remove first import within in a 2nd/3rd/4th/etc. section.\n\t// golang.org/issue/7679\n\t{\n\t\tname: \"remove_first_import_in_section\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"manypackages.com/packagea\"\n\t\"manypackages.com/packageb\"\n)\n\nfunc main() {\n\tvar _ = fmt.Println\n\t//var _ = packagea.A\n\tvar _ = packageb.B\n}\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"manypackages.com/packageb\"\n)\n\nfunc main() {\n\tvar _ = fmt.Println\n\t//var _ = packagea.A\n\tvar _ = packageb.B\n}\n`,\n\t},\n\n\t// Blank line can be added before all types of import declarations.\n\t// golang.org/issue/7866\n\t{\n\t\tname: \"new_section_for_all_kinds_of_imports\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\trenamed_packagea \"manypackages.com/packagea\"\n\n\t. \"manypackages.com/packageb\"\n\t\"io\"\n\n\t_ \"manypackages.com/packagec\"\n\t\"strings\"\n)\n\nvar _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\n\trenamed_packagea \"manypackages.com/packagea\"\n\n\t\"io\"\n\n\t. \"manypackages.com/packageb\"\n\n\t\"strings\"\n\n\t_ \"manypackages.com/packagec\"\n)\n\nvar _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B\n`,\n\t},\n\n\t// Blank line can be added even when first import of group has comment with quote\n\t{\n\t\tname: \"new_section_where_trailing_comment_has_quote\",\n\t\tin: `package main\n\nimport (\n\t\"context\"\n\tbar \"local.com/bar\"\n\tbaz \"local.com/baz\"\n\tbuzz \"local.com/buzz\"\n\t\"github.com/golang/snappy\" // this is a \"typical\" import\n)\n\nvar _, _, _, _, _ = context.Background, bar.B, baz.B, buzz.B, snappy.ErrCorrupt\n`,\n\t\tout: `package main\n\nimport (\n\t\"context\"\n\n\t\"github.com/golang/snappy\" // this is a \"typical\" import\n\n\tbar \"local.com/bar\"\n\tbaz \"local.com/baz\"\n\tbuzz \"local.com/buzz\"\n)\n\nvar _, _, _, _, _ = context.Background, bar.B, baz.B, buzz.B, snappy.ErrCorrupt\n`,\n\t},\n\n\t// Non-idempotent comment formatting\n\t// golang.org/issue/8035\n\t{\n\t\tname: \"comments_formatted\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"                     // A\n\t\"go/ast\"                  // B\n\t_ \"manypackages.com/packagec\"    // C\n)\n\nfunc main() { _, _ = fmt.Print, ast.Walk }\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"    // A\n\t\"go/ast\" // B\n\n\t_ \"manypackages.com/packagec\" // C\n)\n\nfunc main() { _, _ = fmt.Print, ast.Walk }\n`,\n\t},\n\n\t// Failure to delete all duplicate imports\n\t// golang.org/issue/8459\n\t{\n\t\tname: \"remove_duplicates\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"log\"\n\t\"math\"\n)\n\nfunc main() { fmt.Println(\"pi:\", math.Pi) }\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc main() { fmt.Println(\"pi:\", math.Pi) }\n`,\n\t},\n\n\t// Too aggressive prefix matching\n\t// golang.org/issue/9961\n\t{\n\t\tname: \"no_extra_groups\",\n\t\tin: `package p\n\nimport (\n\t\"zip\"\n\n\t\"rsc.io/p\"\n)\n\nvar (\n\t_ = fmt.Print\n\t_ = zip.Store\n\t_ p.P\n\t_ = regexp.Compile\n)\n`,\n\t\tout: `package p\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"zip\"\n\n\t\"rsc.io/p\"\n)\n\nvar (\n\t_ = fmt.Print\n\t_ = zip.Store\n\t_ p.P\n\t_ = regexp.Compile\n)\n`,\n\t},\n\n\t// Unused named import is mistaken for unnamed import\n\t// golang.org/issue/8149\n\t{\n\t\tname: \"named_import_doesnt_provide_package_name\",\n\t\tin: `package main\n\nimport foo \"fmt\"\n\nfunc main() { fmt.Println() }\n`,\n\t\tout: `package main\n\nimport \"fmt\"\n\nfunc main() { fmt.Println() }\n`,\n\t},\n\n\t// Unused named import is mistaken for unnamed import\n\t// golang.org/issue/8149\n\t{\n\t\tname: \"unused_named_import_removed\",\n\t\tin: `package main\n\nimport (\n\t\"fmt\"\n\tx \"fmt\"\n)\n\nfunc main() { fmt.Println() }\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() { fmt.Println() }\n`,\n\t},\n\n\t{\n\t\tname: \"ignore_unexported_identifier\",\n\t\tin: `package main\nvar _ = fmt.unexported`,\n\t\tout: `package main\n\nvar _ = fmt.unexported\n`,\n\t},\n\n\t// FormatOnly\n\t{\n\t\tname:       \"formatonly_works\",\n\t\tformatOnly: true,\n\t\tin: `package main\n\nimport (\n\"fmt\"\n\"manypackages.com/packagea\"\n)\n\nfunc main() {}\n`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\n\t\"manypackages.com/packagea\"\n)\n\nfunc main() {}\n`,\n\t},\n\n\t{\n\t\tname: \"preserve_import_group\",\n\t\tin: `package p\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nvar _ = fmt.Sprintf\n`,\n\t\tout: `package p\n\nimport (\n\t\"fmt\"\n)\n\nvar _ = fmt.Sprintf\n`,\n\t},\n\t{\n\t\tname: \"import_grouping_not_path_dependent_no_groups\",\n\t\tin: `package main\n\nimport (\n\t\"time\"\n)\n\nfunc main() {\n\t_ = snappy.ErrCorrupt\n\t_ = p.P\n\t_ = time.Parse\n}\n`,\n\t\tout: `package main\n\nimport (\n\t\"time\"\n\n\t\"github.com/golang/snappy\"\n\t\"rsc.io/p\"\n)\n\nfunc main() {\n\t_ = snappy.ErrCorrupt\n\t_ = p.P\n\t_ = time.Parse\n}\n`,\n\t},\n\n\t{\n\t\tname: \"import_grouping_not_path_dependent_existing_group\",\n\t\tin: `package main\n\nimport (\n\t\"time\"\n\n\t\"github.com/golang/snappy\"\n)\n\nfunc main() {\n\t_ = snappy.ErrCorrupt\n\t_ = p.P\n\t_ = time.Parse\n}\n`,\n\t\tout: `package main\n\nimport (\n\t\"time\"\n\n\t\"github.com/golang/snappy\"\n\t\"rsc.io/p\"\n)\n\nfunc main() {\n\t_ = snappy.ErrCorrupt\n\t_ = p.P\n\t_ = time.Parse\n}\n`,\n\t},\n\n\t// golang.org/issue/12097\n\t{\n\t\tname: \"package_statement_insertion_preserves_comments\",\n\t\tin: `// a\n// b\n// c\n\nfunc main() {\n    _ = fmt.Println\n}`,\n\t\tout: `package main\n\nimport \"fmt\"\n\n// a\n// b\n// c\n\nfunc main() {\n\t_ = fmt.Println\n}\n`,\n\t},\n\n\t{\n\t\tname: \"import_comment_stays_on_import\",\n\t\tin: `package main\n\nimport (\n\t\"math\" // fun\n)\n\nfunc main() {\n\tx := math.MaxInt64\n\tfmt.Println(strings.Join(\",\", []string{\"hi\"}), x)\n}`,\n\t\tout: `package main\n\nimport (\n\t\"fmt\"\n\t\"math\" // fun\n\t\"strings\"\n)\n\nfunc main() {\n\tx := math.MaxInt64\n\tfmt.Println(strings.Join(\",\", []string{\"hi\"}), x)\n}\n`,\n\t},\n\n\t{\n\t\tname: \"no_blank_after_comment\",\n\t\tin: `package main\n\nimport (\n\t_ \"io\"\n\t_ \"net/http\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t_ \"strings\"\n)\n\nfunc main() {\n}\n`,\n\t\tout: `package main\n\nimport (\n\t_ \"io\"\n\t_ \"net/http\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t_ \"strings\"\n)\n\nfunc main() {\n}\n`,\n\t},\n\n\t{\n\t\tname: \"no_blank_after_comment_reordered\",\n\t\tin: `package main\n\nimport (\n\t_ \"io\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t_ \"net/http\"\n\t_ \"strings\"\n)\n\nfunc main() {\n}\n`,\n\t\tout: `package main\n\nimport (\n\t_ \"io\"\n\t_ \"net/http\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t_ \"strings\"\n)\n\nfunc main() {\n}\n`,\n\t},\n\n\t{\n\t\tname: \"no_blank_after_comment_unnamed\",\n\t\tin: `package main\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t\"strings\"\n\n\t\"manypackages.com/packagea\"\n)\n\nfunc main() {\n\t_ = strings.ToUpper(\"hello\")\n\t_ = io.EOF\n\tvar (\n\t\t_ json.Number\n\t\t_ *http.Request\n\t\t_ packagea.A\n\t)\n}\n`,\n\t\tout: `package main\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t_ \"net/http/pprof\" // install the pprof http handlers\n\t\"strings\"\n\n\t\"manypackages.com/packagea\"\n)\n\nfunc main() {\n\t_ = strings.ToUpper(\"hello\")\n\t_ = io.EOF\n\tvar (\n\t\t_ json.Number\n\t\t_ *http.Request\n\t\t_ packagea.A\n\t)\n}\n`,\n\t},\n\n\t{\n\t\tname: \"blank_after_package_statement_with_comment\",\n\t\tin: `package p // comment\n\nimport \"math\"\n\nvar _ = fmt.Printf\n`,\n\t\tout: `package p // comment\n\nimport \"fmt\"\n\nvar _ = fmt.Printf\n`,\n\t},\n\n\t{\n\t\tname: \"blank_after_package_statement_no_comment\",\n\t\tin: `package p\n\nimport \"math\"\n\nvar _ = fmt.Printf\n`,\n\t\tout: `package p\n\nimport \"fmt\"\n\nvar _ = fmt.Printf\n`,\n\t},\n\n\t{\n\t\tname: \"cryptorand_preferred_easy_possible\",\n\t\tin: `package p\n\nvar _ = rand.Read\n`,\n\t\tout: `package p\n\nimport \"crypto/rand\"\n\nvar _ = rand.Read\n`,\n\t},\n\n\t{\n\t\tname: \"cryptorand_preferred_easy_impossible\",\n\t\tin: `package p\n\nvar _ = rand.NewZipf\n`,\n\t\tout: `package p\n\nimport \"math/rand/v2\"\n\nvar _ = rand.NewZipf\n`,\n\t},\n\n\t{\n\t\tname: \"cryptorand_preferred_complex_possible\",\n\t\tin: `package p\n\nvar _, _ = rand.Read, rand.Prime\n`,\n\t\tout: `package p\n\nimport \"crypto/rand\"\n\nvar _, _ = rand.Read, rand.Prime\n`,\n\t},\n\n\t{\n\t\tname: \"cryptorand_preferred_complex_impossible\",\n\t\tin: `package p\n\nvar _, _ = rand.Read, rand.NewZipf\n`,\n\t\tout: `package p\n\nimport \"math/rand\"\n\nvar _, _ = rand.Read, rand.NewZipf\n`,\n\t},\n\t{\n\t\tname: \"unused_duplicate_imports_remove\",\n\t\tin: `package main\n\nimport (\n\t\"errors\"\n\n\t\"github.com/pkg/errors\"\n)\n`,\n\t\tout: `package main\n`,\n\t},\n}\n\nfunc TestSimpleCases(t *testing.T) {\n\tconst localPrefix = \"local.com,github.com/local\"\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ttestConfig{\n\t\t\t\tmodules: []packagestest.Module{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"golang.org/fake\",\n\t\t\t\t\t\tFiles: fm{\"x.go\": tt.in},\n\t\t\t\t\t},\n\t\t\t\t\t// Skeleton non-stdlib packages for use during testing.\n\t\t\t\t\t// Each includes one arbitrary symbol, e.g. the first declaration in the first file.\n\t\t\t\t\t// Try not to add more without a good reason.\n\t\t\t\t\t// DO NOT USE PACKAGES NOT LISTED HERE -- they will be downloaded!\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"rsc.io\",\n\t\t\t\t\t\tFiles: fm{\"p/x.go\": \"package p\\nfunc P(){}\\n\"},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"github.com/golang/snappy\",\n\t\t\t\t\t\tFiles: fm{\"x.go\": \"package snappy\\nvar ErrCorrupt error\\n\"},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"manypackages.com\",\n\t\t\t\t\t\tFiles: fm{\n\t\t\t\t\t\t\t\"packagea/x.go\": \"package packagea\\nfunc A(){}\\n\",\n\t\t\t\t\t\t\t\"packageb/x.go\": \"package packageb\\nfunc B(){}\\n\",\n\t\t\t\t\t\t\t\"packagec/x.go\": \"package packagec\\nfunc C(){}\\n\",\n\t\t\t\t\t\t\t\"packaged/x.go\": \"package packaged\\nfunc D(){}\\n\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"local.com\",\n\t\t\t\t\t\tFiles: fm{\"foo/x.go\": \"package foo\\nfunc Foo(){}\\n\"},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"github.com/local\",\n\t\t\t\t\t\tFiles: fm{\"bar/x.go\": \"package bar\\nfunc Bar(){}\\n\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}.test(t, func(t *goimportTest) {\n\t\t\t\toptions := &Options{\n\t\t\t\t\tLocalPrefix: localPrefix,\n\t\t\t\t\tTabWidth:    8,\n\t\t\t\t\tTabIndent:   true,\n\t\t\t\t\tComments:    true,\n\t\t\t\t\tFragment:    true,\n\t\t\t\t\tFormatOnly:  tt.formatOnly,\n\t\t\t\t}\n\t\t\t\tt.assertProcessEquals(\"golang.org/fake\", \"x.go\", nil, options, tt.out)\n\t\t\t})\n\n\t\t})\n\t}\n}\n\nfunc TestAppengine(t *testing.T) {\n\tconst input = `package p\n\nvar _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType\n`\n\n\tconst want = `package p\n\nimport (\n\t\"fmt\"\n\n\t\"appengine\"\n\t\"appengine/datastore\"\n)\n\nvar _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType\n`\n\n\ttestConfig{\n\t\tgopathOnly: true, // can't create a module named appengine, so no module tests.\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"golang.org/fake\",\n\t\t\t\tFiles: fm{\"x.go\": input},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"appengine\",\n\t\t\t\tFiles: fm{\n\t\t\t\t\t\"x.go\":           \"package appengine\\nfunc Main(){}\\n\",\n\t\t\t\t\t\"datastore/x.go\": \"package datastore\\nvar ErrInvalidEntityType error\\n\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"golang.org/fake\", \"x.go\", nil, nil, want)\n}\n\nfunc TestReadFromFilesystem(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tin, out string\n\t}{\n\t\t{\n\t\t\tname: \"works\",\n\t\t\tin: `package foo\nfunc bar() {\nfmt.Println(\"hi\")\n}\n`,\n\t\t\tout: `package foo\n\nimport \"fmt\"\n\nfunc bar() {\n\tfmt.Println(\"hi\")\n}\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"missing_package\",\n\t\t\tin: `\nfunc bar() {\nfmt.Println(\"hi\")\n}\n`,\n\t\t\tout: `\nimport \"fmt\"\n\nfunc bar() {\n\tfmt.Println(\"hi\")\n}\n`,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toptions := &Options{\n\t\t\t\tTabWidth:  8,\n\t\t\t\tTabIndent: true,\n\t\t\t\tComments:  true,\n\t\t\t\tFragment:  true,\n\t\t\t}\n\t\t\ttestConfig{\n\t\t\t\tmodule: packagestest.Module{\n\t\t\t\t\tName:  \"golang.org/fake\",\n\t\t\t\t\tFiles: fm{\"x.go\": tt.in},\n\t\t\t\t},\n\t\t\t}.processTest(t, \"golang.org/fake\", \"x.go\", nil, options, tt.out)\n\t\t})\n\t}\n\n}\n\n// Test support for packages in GOPATH that are actually symlinks.\n// Also test that a symlink loop does not block the process.\nfunc TestImportSymlinks(t *testing.T) {\n\tconst input = `package p\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\tconst want = `package p\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/fake/x/y/mypkg\"\n)\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: fm{\n\t\t\t\t\"target/f.go\":                \"package mypkg\\nvar Foo = 123\\n\",\n\t\t\t\t\"x/y/mypkg\":                  packagestest.Symlink(\"../../target\"), // valid symlink\n\t\t\t\t\"x/y/apkg\":                   packagestest.Symlink(\"..\"),           // symlink loop\n\t\t\t\t\"myotherpackage/toformat.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"golang.org/fake\", \"myotherpackage/toformat.go\", nil, nil, want)\n}\n\n// Test support for packages in GOPATH whose files are symlinks.\nfunc TestImportSymlinkFiles(t *testing.T) {\n\tconst input = `package p\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\tconst want = `package p\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/fake/x/y/mypkg\"\n)\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: fm{\n\t\t\t\t\"target/f.go\":                \"package mypkg\\nvar Foo = 123\\n\",\n\t\t\t\t\"x/y/mypkg/f.go\":             packagestest.Symlink(\"../../../target/f.go\"),\n\t\t\t\t\"myotherpackage/toformat.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"golang.org/fake\", \"myotherpackage/toformat.go\", nil, nil, want)\n}\n\nfunc TestImportSymlinksWithIgnore(t *testing.T) {\n\tconst input = `package p\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\tconst want = `package p\n\nimport \"fmt\"\n\nvar (\n\t_ = fmt.Print\n\t_ = mypkg.Foo\n)\n`\n\n\ttestConfig{\n\t\tgopathOnly: true,\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"golang.org/fake\",\n\t\t\tFiles: fm{\n\t\t\t\t\"target/f.go\":            \"package mypkg\\nvar Foo = 123\\n\",\n\t\t\t\t\"x/y/mypkg\":              packagestest.Symlink(\"../../target\"), // valid symlink\n\t\t\t\t\"x/y/apkg\":               packagestest.Symlink(\"..\"),           // symlink loop\n\t\t\t\t\"myotherpkg/toformat.go\": input,\n\t\t\t\t\"../../.goimportsignore\": \"golang.org/fake/x/y/mypkg\\n\" +\n\t\t\t\t\t\"golang.org/fake/x/y/apkg\\n\",\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"golang.org/fake\", \"myotherpkg/toformat.go\", nil, nil, want)\n}\n\n// Test for x/y/v2 convention for package y.\nfunc TestModuleVersion(t *testing.T) {\n\tconst input = `package p\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/foo/v2\"\n)\n\nvar (\n\t_ = fmt.Print\n\t_ = foo.Foo\n)\n`\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"mypkg.com/outpkg\",\n\t\t\t\tFiles: fm{\"toformat.go\": input},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:  \"github.com/foo/v2\",\n\t\t\t\tFiles: fm{\"x.go\": \"package foo\\n func Foo(){}\\n\"},\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"mypkg.com/outpkg\", \"toformat.go\", nil, nil, input)\n}\n\n// Test for correctly identifying the name of a vendored package when it\n// differs from its directory name. In this test, the import line\n// \"mypkg.com/mypkg_v1\" would be removed if goimports wasn't able to detect\n// that the package name is \"mypkg\".\nfunc TestVendorPackage(t *testing.T) {\n\tconst input = `package p\nimport (\n\t\"fmt\"\n\t\"mypkg.com/mypkg_v1\"\n)\nvar _, _ = fmt.Print, mypkg.Foo\n`\n\n\tconst want = `package p\n\nimport (\n\t\"fmt\"\n\n\tmypkg \"mypkg.com/mypkg_v1\"\n)\n\nvar _, _ = fmt.Print, mypkg.Foo\n`\n\n\ttestConfig{\n\t\tgopathOnly: true,\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"mypkg.com/outpkg\",\n\t\t\tFiles: fm{\n\t\t\t\t\"vendor/mypkg.com/mypkg_v1/f.go\": \"package mypkg\\nvar Foo = 123\\n\",\n\t\t\t\t\"toformat.go\":                    input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"mypkg.com/outpkg\", \"toformat.go\", nil, nil, want)\n}\n\nfunc TestInternal(t *testing.T) {\n\tconst input = `package bar\n\nvar _ = race.Acquire\n`\n\tconst importAdded = `package bar\n\nimport \"foo.com/internal/race\"\n\nvar _ = race.Acquire\n`\n\n\t// Packages under the same directory should be able to use internal packages.\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"internal/race/x.go\": \"package race\\n func Acquire(){}\\n\",\n\t\t\t\t\"bar/x.go\":           input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"bar/x.go\", nil, nil, importAdded)\n\n\t// Packages outside the same directory should not.\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"foo.com\",\n\t\t\t\tFiles: fm{\"internal/race/x.go\": \"package race\\n func Acquire(){}\\n\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:  \"bar.com\",\n\t\t\t\tFiles: fm{\"x.go\": input},\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"bar.com\", \"x.go\", nil, nil, input)\n}\n\nfunc TestProcessVendor(t *testing.T) {\n\tconst input = `package p\n\nvar _ = hpack.HuffmanDecode\n`\n\tconst want = `package p\n\nimport \"golang.org/x/net/http2/hpack\"\n\nvar _ = hpack.HuffmanDecode\n`\n\ttestConfig{\n\t\tgopathOnly: true,\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"vendor/golang.org/x/net/http2/hpack/huffman.go\": \"package hpack\\nfunc HuffmanDecode() { }\\n\",\n\t\t\t\t\"bar/x.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"bar/x.go\", nil, nil, want)\n}\n\nfunc TestFindStdlib(t *testing.T) {\n\ttests := []struct {\n\t\tpkg     string\n\t\tsymbols []string\n\t\twant    string\n\t}{\n\t\t{\"http\", []string{\"Get\"}, \"net/http\"},\n\t\t{\"http\", []string{\"Get\", \"Post\"}, \"net/http\"},\n\t\t{\"http\", []string{\"Get\", \"Foo\"}, \"\"},\n\t\t{\"bytes\", []string{\"Buffer\"}, \"bytes\"},\n\t\t{\"ioutil\", []string{\"Discard\"}, \"io/ioutil\"},\n\t}\n\tfor _, tt := range tests {\n\t\tinput := \"package p\\n\"\n\t\tfor _, sym := range tt.symbols {\n\t\t\tinput += fmt.Sprintf(\"var _ = %s.%s\\n\", tt.pkg, sym)\n\t\t}\n\t\ttestConfig{\n\t\t\tmodule: packagestest.Module{\n\t\t\t\tName:  \"foo.com\",\n\t\t\t\tFiles: fm{\"x.go\": input},\n\t\t\t},\n\t\t}.test(t, func(t *goimportTest) {\n\t\t\tbuf, err := t.process(\"foo.com\", \"x.go\", nil, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif got := string(buf); !strings.Contains(got, tt.want) {\n\t\t\t\tt.Errorf(\"Process(%q) = %q, wanted it to contain %q\", input, buf, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// https://golang.org/issue/31814\nfunc TestStdlibNotPrefixed(t *testing.T) {\n\tconst input = `package p\nvar _ = bytes.Buffer\n`\n\tconst want = `package p\n\nimport \"bytes\"\n\nvar _ = bytes.Buffer\n`\n\t// Force a scan of the stdlib.\n\tsavedStdlib := stdlib.PackageSymbols\n\tdefer func() { stdlib.PackageSymbols = savedStdlib }()\n\tstdlib.PackageSymbols = nil\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName:  \"ignored.com\",\n\t\t\tFiles: fm{\"x.go\": \"package x\"},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\t// Run in GOROOT/src so that the std module shows up in go list -m all.\n\t\tt.env.WorkingDir = filepath.Join(t.goroot, \"src\")\n\t\tgot, err := t.processNonModule(filepath.Join(t.goroot, \"src/x.go\"), []byte(input), nil)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Process() = %v\", err)\n\t\t}\n\t\tif string(got) != want {\n\t\t\tt.Errorf(\"Got:\\n%s\\nWant:\\n%s\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestStdlibSelfImports(t *testing.T) {\n\tconst input = `package rc4\n\nvar _ = rc4.NewCipher\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName:  \"ignored.com\",\n\t\t\tFiles: fm{\"x.go\": \"package x\"},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tgot, err := t.processNonModule(filepath.Join(t.goroot, \"src/crypto/rc4/foo.go\"), []byte(input), nil)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Process() = %v\", err)\n\t\t}\n\t\tif string(got) != input {\n\t\t\tt.Errorf(\"Got:\\n%s\\nWant:\\n%s\", got, input)\n\t\t}\n\t})\n}\n\ntype testConfig struct {\n\tgopathOnly bool\n\tmodule     packagestest.Module\n\tmodules    []packagestest.Module\n}\n\n// fm is the type for a packagestest.Module's Files, abbreviated for shorter lines.\ntype fm map[string]any\n\nfunc (c testConfig) test(t *testing.T, fn func(*goimportTest)) {\n\tt.Helper()\n\n\tif c.module.Name != \"\" {\n\t\tc.modules = []packagestest.Module{c.module}\n\t}\n\n\tfor _, exporter := range packagestest.All {\n\t\tt.Run(exporter.Name(), func(t *testing.T) {\n\t\t\tt.Helper()\n\t\t\tif c.gopathOnly && exporter.Name() == \"Modules\" {\n\t\t\t\tt.Skip(\"test marked GOPATH-only\")\n\t\t\t}\n\t\t\texported := packagestest.Export(t, exporter, c.modules)\n\t\t\tdefer exported.Cleanup()\n\n\t\t\tenv := map[string]string{}\n\t\t\tfor _, kv := range exported.Config.Env {\n\t\t\t\tsplit := strings.SplitN(kv, \"=\", 2)\n\t\t\t\tenv[split[0]] = split[1]\n\t\t\t}\n\t\t\tit := &goimportTest{\n\t\t\t\tT: t,\n\t\t\t\tenv: &ProcessEnv{\n\t\t\t\t\tEnv:         env,\n\t\t\t\t\tWorkingDir:  exported.Config.Dir,\n\t\t\t\t\tGocmdRunner: &gocommand.Runner{},\n\t\t\t\t},\n\t\t\t\texported: exported,\n\t\t\t}\n\t\t\tif *testDebug {\n\t\t\t\tit.env.Logf = log.Printf\n\t\t\t}\n\t\t\t// packagestest clears out GOROOT to work around golang/go#32849,\n\t\t\t// which isn't relevant here. Fill it back in so we can find the standard library.\n\t\t\tit.env.Env[\"GOROOT\"] = build.Default.GOROOT\n\t\t\tit.goroot = build.Default.GOROOT\n\n\t\t\tfn(it)\n\t\t})\n\t}\n}\n\nfunc (c testConfig) processTest(t *testing.T, module, file string, contents []byte, opts *Options, want string) {\n\tt.Helper()\n\tc.test(t, func(t *goimportTest) {\n\t\tt.Helper()\n\t\tt.assertProcessEquals(module, file, contents, opts, want)\n\t})\n}\n\ntype goimportTest struct {\n\t*testing.T\n\tgoroot   string\n\tenv      *ProcessEnv\n\texported *packagestest.Exported\n}\n\nfunc (t *goimportTest) process(module, file string, contents []byte, opts *Options) ([]byte, error) {\n\tt.Helper()\n\tf := t.exported.File(module, file)\n\tif f == \"\" {\n\t\tt.Fatalf(\"%v not found in exported files (typo in filename?)\", file)\n\t}\n\treturn t.processNonModule(f, contents, opts)\n}\n\nfunc (t *goimportTest) processNonModule(file string, contents []byte, opts *Options) ([]byte, error) {\n\tif contents == nil {\n\t\tvar err error\n\t\tcontents, err = os.ReadFile(file)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif opts == nil {\n\t\topts = &Options{Comments: true, TabIndent: true, TabWidth: 8}\n\t}\n\t// ProcessEnv is not safe for concurrent use. Make a copy.\n\topts.Env = t.env.CopyConfig()\n\treturn Process(file, contents, opts)\n}\n\nfunc (t *goimportTest) assertProcessEquals(module, file string, contents []byte, opts *Options, want string) {\n\tbuf, err := t.process(module, file, contents, opts)\n\tif err != nil {\n\t\tt.Fatalf(\"Process() = %v\", err)\n\t}\n\tif string(buf) != want {\n\t\tt.Errorf(\"Got:\\n'%s'\\nWant:\\n'%s'\", buf, want) // 's show empty lines\n\t}\n}\n\n// Tests that added imports are renamed when the import path's base doesn't\n// match its package name.\nfunc TestRenameWhenPackageNameMismatch(t *testing.T) {\n\tconst input = `package main\n const Y = bar.X`\n\n\tconst want = `package main\n\nimport bar \"foo.com/foo/bar/baz\"\n\nconst Y = bar.X\n`\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"foo/bar/baz/x.go\": \"package bar \\n const X = 1\",\n\t\t\t\t\"test/t.go\":        input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"test/t.go\", nil, nil, want)\n}\n\nfunc TestPanicAstutils(t *testing.T) {\n\tt.Skip(\"panic in ast/astutil/imports.go, should be PostionFor(,false) at lines 273, 274, at least\")\n\tconst input = `package main\n//line mah.go:600\n\nimport (\n\"foo.com/a.thing\"\n\"foo.com/surprise\"\n\"foo.com/v1\"\n\"foo.com/other/v2\"\n\"foo.com/other/v3\"\n)\n`\n\n\tconst want = `package main\n\n//line mah.go:600\n\nimport (\n\t\"foo.com/a.thing\"\n\t\"foo.com/go-thing\"\n\tgow \"foo.com/go-wrong\"\n\tv2 \"foo.com/other/v2\"\n\t\"foo.com/other/v3\"\n\tbar \"foo.com/surprise\"\n\tv1 \"foo.com/v1\"\n)\n\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"test/t.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"test/t.go\", nil, nil, want)\n}\n\n// without PositionFor in sortImports this test panics\nfunc TestPanic51916(t *testing.T) {\n\tconst input = `package main\n//line mah.go:600\n\nimport (\n\"foo.com/a.thing\"\n\"foo.com/surprise\"\n\"foo.com/v1\"\n\"foo.com/other/v2\"\n\"foo.com/other/v3\"\n\"foo.com/go-thing\"\n\"foo.com/go-wrong\"\n)\n\nvar _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}`\n\n\tconst want = `package main\n\n//line mah.go:600\n\nimport (\n\t\"foo.com/a.thing\"\n\t\"foo.com/go-thing\"\n\tgow \"foo.com/go-wrong\"\n\tv2 \"foo.com/other/v2\"\n\t\"foo.com/other/v3\"\n\tbar \"foo.com/surprise\"\n\tv1 \"foo.com/v1\"\n)\n\nvar _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"a.thing/a.go\":  \"package a \\n const A = 1\",\n\t\t\t\t\"surprise/x.go\": \"package bar \\n const X = 1\",\n\t\t\t\t\"v1/x.go\":       \"package v1 \\n const Y = 1\",\n\t\t\t\t\"other/v2/y.go\": \"package v2 \\n const V2 = 1\",\n\t\t\t\t\"other/v3/z.go\": \"package other \\n const V3 = 1\",\n\t\t\t\t\"go-thing/b.go\": \"package thing \\n const Thing = 1\",\n\t\t\t\t\"go-wrong/b.go\": \"package gow \\n const Wrong = 1\",\n\t\t\t\t\"test/t.go\":     input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"test/t.go\", nil, nil, want)\n}\n\n// Tests that an existing import with badly mismatched path/name has its name\n// correctly added. See #28645 and #29041.\n// and check that //line directives are ignored (#51916)\nfunc TestAddNameToMismatchedImport(t *testing.T) {\n\tconst input = `package main\n\nimport (\n\"foo.com/a.thing\"\n\"foo.com/surprise\"\n\"foo.com/v1\"\n\"foo.com/other/v2\"\n\"foo.com/other/v3\"\n\"foo.com/go-thing\"\n\"foo.com/go-wrong\"\n)\n\nvar _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}`\n\n\tconst want = `package main\n\nimport (\n\t\"foo.com/a.thing\"\n\t\"foo.com/go-thing\"\n\tgow \"foo.com/go-wrong\"\n\tv2 \"foo.com/other/v2\"\n\t\"foo.com/other/v3\"\n\tbar \"foo.com/surprise\"\n\tv1 \"foo.com/v1\"\n)\n\nvar _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"a.thing/a.go\":  \"package a \\n const A = 1\",\n\t\t\t\t\"surprise/x.go\": \"package bar \\n const X = 1\",\n\t\t\t\t\"v1/x.go\":       \"package v1 \\n const Y = 1\",\n\t\t\t\t\"other/v2/y.go\": \"package v2 \\n const V2 = 1\",\n\t\t\t\t\"other/v3/z.go\": \"package other \\n const V3 = 1\",\n\t\t\t\t\"go-thing/b.go\": \"package thing \\n const Thing = 1\",\n\t\t\t\t\"go-wrong/b.go\": \"package gow \\n const Wrong = 1\",\n\t\t\t\t\"test/t.go\":     input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"test/t.go\", nil, nil, want)\n}\n\n// Tests that the LocalPrefix option causes imports\n// to be added into a later group (num=3).\nfunc TestLocalPrefix(t *testing.T) {\n\ttests := []struct {\n\t\tname        string\n\t\tmodules     []packagestest.Module\n\t\tlocalPrefix string\n\t\tsrc         string\n\t\twant        string\n\t}{\n\t\t{\n\t\t\tname: \"one_local\",\n\t\t\tmodules: []packagestest.Module{\n\t\t\t\t{\n\t\t\t\t\tName: \"foo.com\",\n\t\t\t\t\tFiles: fm{\n\t\t\t\t\t\t\"bar/bar.go\": \"package bar \\n const X = 1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tlocalPrefix: \"foo.com/\",\n\t\t\tsrc:         \"package main \\n const Y = bar.X \\n const _ = runtime.GOOS\",\n\t\t\twant: `package main\n\nimport (\n\t\"runtime\"\n\n\t\"foo.com/bar\"\n)\n\nconst Y = bar.X\nconst _ = runtime.GOOS\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"two_local\",\n\t\t\tmodules: []packagestest.Module{\n\t\t\t\t{\n\t\t\t\t\tName: \"foo.com\",\n\t\t\t\t\tFiles: fm{\n\t\t\t\t\t\t\"foo/foo.go\":     \"package foo \\n const X = 1\",\n\t\t\t\t\t\t\"foo/bar/bar.go\": \"package bar \\n const X = 1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tlocalPrefix: \"foo.com/foo\",\n\t\t\tsrc:         \"package main \\n const Y = bar.X \\n const Z = foo.X \\n const _ = runtime.GOOS\",\n\t\t\twant: `package main\n\nimport (\n\t\"runtime\"\n\n\t\"foo.com/foo\"\n\t\"foo.com/foo/bar\"\n)\n\nconst Y = bar.X\nconst Z = foo.X\nconst _ = runtime.GOOS\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"three_prefixes\",\n\t\t\tmodules: []packagestest.Module{\n\t\t\t\t{\n\t\t\t\t\tName:  \"example.org/pkg\",\n\t\t\t\t\tFiles: fm{\"pkg.go\": \"package pkg \\n const A = 1\"},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName:  \"foo.com\",\n\t\t\t\t\tFiles: fm{\"bar/bar.go\": \"package bar \\n const B = 1\"},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName:  \"code.org/r/p\",\n\t\t\t\t\tFiles: fm{\"expproj/expproj.go\": \"package expproj \\n const C = 1\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\tlocalPrefix: \"example.org/pkg,foo.com/,code.org\",\n\t\t\tsrc:         \"package main \\n const X = pkg.A \\n const Y = bar.B \\n const Z = expproj.C \\n const _ = runtime.GOOS\",\n\t\t\twant: `package main\n\nimport (\n\t\"runtime\"\n\n\t\"code.org/r/p/expproj\"\n\t\"example.org/pkg\"\n\t\"foo.com/bar\"\n)\n\nconst X = pkg.A\nconst Y = bar.B\nconst Z = expproj.C\nconst _ = runtime.GOOS\n`,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ttestConfig{\n\t\t\t\t// The module being processed has to be first so it's the primary module.\n\t\t\t\tmodules: append([]packagestest.Module{{\n\t\t\t\t\tName:  \"test.com\",\n\t\t\t\t\tFiles: fm{\"t.go\": tt.src},\n\t\t\t\t}}, tt.modules...),\n\t\t\t}.test(t, func(t *goimportTest) {\n\t\t\t\toptions := &Options{\n\t\t\t\t\tLocalPrefix: tt.localPrefix,\n\t\t\t\t\tTabWidth:    8,\n\t\t\t\t\tTabIndent:   true,\n\t\t\t\t\tComments:    true,\n\t\t\t\t\tFragment:    true,\n\t\t\t\t}\n\t\t\t\tt.assertProcessEquals(\"test.com\", \"t.go\", nil, options, tt.want)\n\t\t\t})\n\t\t})\n\t}\n}\n\n// Tests that \"package documentation\" files are ignored.\nfunc TestIgnoreDocumentationPackage(t *testing.T) {\n\tconst input = `package x\n\nconst Y = foo.X\n`\n\tconst want = `package x\n\nimport \"foo.com/foo\"\n\nconst Y = foo.X\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"foo/foo.go\": \"package foo\\nconst X = 1\\n\",\n\t\t\t\t\"foo/doc.go\": \"package documentation \\n // just to confuse things\\n\",\n\t\t\t\t\"x/x.go\":     input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"x/x.go\", nil, nil, want)\n}\n\n// Tests importPathToNameGoPathParse and in particular that it stops\n// after finding the first non-documentation package name, not\n// reporting an error on inconsistent package names (since it should\n// never make it that far).\nfunc TestImportPathToNameGoPathParse(t *testing.T) {\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"example.net/pkg\",\n\t\t\tFiles: fm{\n\t\t\t\t\"doc.go\": \"package documentation\\n\", // ignored\n\t\t\t\t\"gen.go\": \"package main\\n\",          // also ignored\n\t\t\t\t\"pkg.go\": \"package the_pkg_name_to_find\\n  and this syntax error is ignored because of parser.PackageClauseOnly\",\n\t\t\t\t\"z.go\":   \"package inconsistent\\n\", // inconsistent but ignored\n\t\t\t},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tif strings.Contains(t.Name(), \"GoPackages\") {\n\t\t\tt.Skip(\"go/packages does not ignore package main\")\n\t\t}\n\t\tr, err := t.env.GetResolver()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tsrcDir := filepath.Dir(t.exported.File(\"example.net/pkg\", \"z.go\"))\n\t\tnames, err := r.loadPackageNames([]string{\"example.net/pkg\"}, srcDir)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tconst want = \"the_pkg_name_to_find\"\n\t\tif got := names[\"example.net/pkg\"]; got != want {\n\t\t\tt.Errorf(\"loadPackageNames(..) = %q; want %q\", got, want)\n\t\t}\n\t})\n}\n\nfunc TestIgnoreConfiguration(t *testing.T) {\n\tconst input = `package x\n\nconst _ = pkg.X\n`\n\tconst want = `package x\n\nimport \"foo.com/otherwise-longer-so-worse-example/foo/pkg\"\n\nconst _ = pkg.X\n`\n\n\ttestConfig{\n\t\tgopathOnly: true,\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"../.goimportsignore\":                              \"# comment line\\n\\n foo.com/example\", // tests comment, blank line, whitespace trimming\n\t\t\t\t\"example/pkg/pkg.go\":                               \"package pkg\\nconst X = 1\",\n\t\t\t\t\"otherwise-longer-so-worse-example/foo/pkg/pkg.go\": \"package pkg\\nconst X = 1\",\n\t\t\t\t\"x/x.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"x/x.go\", nil, nil, want)\n}\n\n// Skip \"node_modules\" directory.\nfunc TestSkipNodeModules(t *testing.T) {\n\tconst input = `package x\n\nconst _ = pkg.X\n`\n\tconst want = `package x\n\nimport \"foo.com/otherwise-longer/not_modules/pkg\"\n\nconst _ = pkg.X\n`\n\n\ttestConfig{\n\t\tgopathOnly: true,\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"example/node_modules/pkg/a.go\":         \"package pkg\\nconst X = 1\",\n\t\t\t\t\"otherwise-longer/not_modules/pkg/a.go\": \"package pkg\\nconst X = 1\",\n\t\t\t\t\"x/x.go\":                                input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"x/x.go\", nil, nil, want)\n}\n\n// Tests that package global variables with the same name and function name as\n// a function in a separate package do not result in an import which masks\n// the global variable\nfunc TestGlobalImports(t *testing.T) {\n\tconst usesGlobal = `package pkg\n\nfunc doSomething() {\n\tt := time.Now()\n}\n`\n\n\tconst declaresGlobal = `package pkg\n\ntype Time struct{}\n\nfunc (t Time) Now() Time {\n\treturn Time{}\n}\n\nvar time Time\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/uses.go\":   usesGlobal,\n\t\t\t\t\"pkg/global.go\": declaresGlobal,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/uses.go\", nil, nil, usesGlobal)\n}\n\n// Some people put multiple packages' files in the same directory. Globals\n// declared in other packages should be ignored.\nfunc TestGlobalImports_DifferentPackage(t *testing.T) {\n\tconst declaresGlobal = `package main\nvar fmt int\n`\n\tconst input = `package pkg\nvar _ = fmt.Printf\n`\n\tconst want = `package pkg\n\nimport \"fmt\"\n\nvar _ = fmt.Printf\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/main.go\": declaresGlobal,\n\t\t\t\t\"pkg/uses.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/uses.go\", nil, nil, want)\n}\n\nfunc TestGlobalImports_MultipleMains(t *testing.T) {\n\tconst declaresGlobal = `package main\nvar fmt int\n`\n\tconst input = `package main\nimport \"fmt\"\nvar _, _ = fmt.Printf, bytes.Equal\n`\n\tconst want = `package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nvar _, _ = fmt.Printf, bytes.Equal\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/main.go\": declaresGlobal,\n\t\t\t\t\"pkg/uses.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/uses.go\", nil, nil, want)\n}\n\n// Tests that sibling files - other files in the same package - can provide an\n// import that may not be the default one otherwise.\nfunc TestSiblingImports(t *testing.T) {\n\n\t// provide is the sibling file that provides the desired import.\n\tconst provide = `package siblingimporttest\n\nimport \"local/log\"\nimport \"my/bytes\"\nimport renamed \"fmt\"\n\nfunc LogSomething() {\n\tlog.Print(\"Something\")\n\tbytes.SomeFunc()\n\trenamed.Println(\"Something\")\n}\n`\n\n\t// need is the file being tested that needs the import.\n\tconst need = `package siblingimporttest\n\nvar _ = bytes.Buffer{}\n\nfunc LogSomethingElse() {\n\tlog.Print(\"Something else\")\n\trenamed.Println(\"Yet another\")\n}\n`\n\n\t// want is the expected result file\n\tconst want = `package siblingimporttest\n\nimport (\n\t\"bytes\"\n\trenamed \"fmt\"\n\t\"local/log\"\n)\n\nvar _ = bytes.Buffer{}\n\nfunc LogSomethingElse() {\n\tlog.Print(\"Something else\")\n\trenamed.Println(\"Yet another\")\n}\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"p/needs_import.go\":    need,\n\t\t\t\t\"p/provides_import.go\": provide,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"p/needs_import.go\", nil, nil, want)\n}\n\n// Tests #29180: a sibling import of the right package with the wrong name is used.\nfunc TestSiblingImport_Misnamed(t *testing.T) {\n\tconst sibling = `package main\nimport renamed \"fmt\"\nvar _ = renamed.Printf\n`\n\tconst input = `package pkg\nvar _ = fmt.Printf\n`\n\tconst want = `package pkg\n\nimport \"fmt\"\n\nvar _ = fmt.Printf\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/main.go\": sibling,\n\t\t\t\t\"pkg/uses.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/uses.go\", nil, nil, want)\n\n}\n\n// Tests that an input file's own package is ignored.\nfunc TestIgnoreOwnPackage(t *testing.T) {\n\tconst input = `package pkg\n\nconst _ = pkg.X\n`\n\tconst want = `package pkg\n\nconst _ = pkg.X\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/a.go\": \"package pkg\\nconst X = 1\",\n\t\t\t\t\"pkg/b.go\": input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/b.go\", nil, nil, want)\n}\n\nfunc TestExternalTestImportsPackageUnderTest(t *testing.T) {\n\tconst provide = `package pkg\nfunc DoIt(){}\n`\n\tconst input = `package pkg_test\n\nvar _ = pkg.DoIt`\n\n\tconst want = `package pkg_test\n\nimport \"foo.com/pkg\"\n\nvar _ = pkg.DoIt\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"pkg/provide.go\": provide,\n\t\t\t\t\"pkg/x_test.go\":  input,\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"pkg/x_test.go\", nil, nil, want)\n}\n\nfunc TestPkgIsCandidate(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tfilename string\n\t\tpkgIdent string\n\t\tpkg      *pkg\n\t\twant     bool\n\t}{\n\t\t{\n\t\t\tname:     \"normal_match\",\n\t\t\tfilename: \"/gopath/src/my/pkg/pkg.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/client\",\n\t\t\t\timportPathShort: \"client\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"no_match\",\n\t\t\tfilename: \"/gopath/src/my/pkg/pkg.go\",\n\t\t\tpkgIdent: \"zzz\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/client\",\n\t\t\t\timportPathShort: \"client\",\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"match_too_early\",\n\t\t\tfilename: \"/gopath/src/my/pkg/pkg.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/client/foo/foo/foo\",\n\t\t\t\timportPathShort: \"client/foo/foo\",\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"substring_match\",\n\t\t\tfilename: \"/gopath/src/my/pkg/pkg.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/go-client\",\n\t\t\t\timportPathShort: \"foo/go-client\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"hidden_internal\",\n\t\t\tfilename: \"/gopath/src/my/pkg/pkg.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/internal/client\",\n\t\t\t\timportPathShort: \"foo/internal/client\",\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"visible_internal\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/internal/client\",\n\t\t\t\timportPathShort: \"foo/internal/client\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"invisible_vendor\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/other/vendor/client\",\n\t\t\t\timportPathShort: \"client\",\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"visible_vendor\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"client\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/vendor/client\",\n\t\t\t\timportPathShort: \"client\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"match_with_hyphens\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"socketio\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/socket-io\",\n\t\t\t\timportPathShort: \"foo/socket-io\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"match_with_mixed_case\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"fooprod\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/FooPROD\",\n\t\t\t\timportPathShort: \"foo/FooPROD\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"matches_with_hyphen_and_caps\",\n\t\t\tfilename: \"/gopath/src/foo/bar.go\",\n\t\t\tpkgIdent: \"fooprod\",\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             \"/gopath/src/foo/Foo-PROD\",\n\t\t\t\timportPathShort: \"foo/Foo-PROD\",\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t}\n\tfor i, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trefs := References{tt.pkgIdent: nil}\n\t\t\tgot := pkgIsCandidate(tt.filename, refs, tt.pkg)\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"test %d. pkgIsCandidate(%q, %q, %+v) = %v; want %v\",\n\t\t\t\t\ti, tt.filename, tt.pkgIdent, *tt.pkg, got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Issue 20941: this used to panic on Windows.\nfunc TestProcessStdin(t *testing.T) {\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tgot, err := t.processNonModule(\"<standard input>\", []byte(\"package main\\nfunc main() {\\n\\tfmt.Println(123)\\n}\\n\"), nil)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !strings.Contains(string(got), `\"fmt\"`) {\n\t\t\tt.Errorf(\"expected fmt import; got: %s\", got)\n\t\t}\n\t})\n}\n\n// Tests LocalPackagePromotion when there is a local package that matches, it\n// should be the closest match.\n// https://golang.org/issues/17557\nfunc TestLocalPackagePromotion(t *testing.T) {\n\tconst input = `package main\nvar c = &config.SystemConfig{}\n`\n\tconst want = `package main\n\nimport \"mycompany.net/tool/config\"\n\nvar c = &config.SystemConfig{}\n`\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"config.net/config\",\n\t\t\t\tFiles: fm{\"config.go\": \"package config\\n type SystemConfig struct {}\"}, // Will match but should not be first choice\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:  \"mycompany.net/config\",\n\t\t\t\tFiles: fm{\"config.go\": \"package config\\n type SystemConfig struct {}\"}, // Will match but should not be first choice\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"mycompany.net/tool\",\n\t\t\t\tFiles: fm{\n\t\t\t\t\t\"config/config.go\": \"package config\\n type SystemConfig struct {}\", // Local package should be promoted over shorter package\n\t\t\t\t\t\"main.go\":          input,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"mycompany.net/tool\", \"main.go\", nil, nil, want)\n}\n\n// Tests FindImportInLocalGoFiles looks at the import lines for other Go files in the\n// local directory, since the user is likely to import the same packages in the current\n// Go file.  If an import is found that satisfies the need, it should be used over the\n// standard library.\n// https://golang.org/issues/17557\nfunc TestFindImportInLocalGoFiles(t *testing.T) {\n\tconst input = `package main\n var _ = &bytes.Buffer{}`\n\n\tconst want = `package main\n\nimport \"bytes.net/bytes\"\n\nvar _ = &bytes.Buffer{}\n`\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName: \"mycompany.net/tool\",\n\t\t\t\tFiles: fm{\n\t\t\t\t\t\"io.go\":   \"package main\\n import \\\"bytes.net/bytes\\\"\\n var _ = &bytes.Buffer{}\", // Contains package import that will cause stdlib to be ignored\n\t\t\t\t\t\"main.go\": input,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:  \"bytes.net/bytes\",\n\t\t\t\tFiles: fm{\"bytes.go\": \"package bytes\\n type Buffer struct {}\"}, // Should be selected over standard library\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"mycompany.net/tool\", \"main.go\", nil, nil, want)\n}\n\nfunc TestInMemoryFile(t *testing.T) {\n\tconst input = `package main\n var _ = &bytes.Buffer{}`\n\n\tconst want = `package main\n\nimport \"bytes\"\n\nvar _ = &bytes.Buffer{}\n`\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName:  \"foo.com\",\n\t\t\tFiles: fm{\"x.go\": \"package x\\n\"},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"x.go\", []byte(input), nil, want)\n}\n\nfunc TestImportNoGoFiles(t *testing.T) {\n\tconst input = `package main\n var _ = &bytes.Buffer{}`\n\n\tconst want = `package main\n\nimport \"bytes\"\n\nvar _ = &bytes.Buffer{}\n`\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"mycompany.net\",\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tbuf, err := t.processNonModule(\"mycompany.net/tool/main.go\", []byte(input), nil)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Process() = %v\", err)\n\t\t}\n\t\tif string(buf) != want {\n\t\t\tt.Errorf(\"Got:\\n%s\\nWant:\\n%s\", buf, want)\n\t\t}\n\t})\n\n}\n\n// Ensures a token as large as 500000 bytes can be handled\n// https://golang.org/issues/18201\nfunc TestProcessLargeToken(t *testing.T) {\n\tlargeString := strings.Repeat(\"x\", 500000)\n\n\tinput := `package testimports\n\nimport (\n\t\"bytes\"\n)\n\nconst s = fmt.Sprintf(\"%s\", \"` + largeString + `\")\nvar _ = bytes.Buffer{}\n\n// end\n`\n\n\twant := `package testimports\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nconst s = fmt.Sprintf(\"%s\", \"` + largeString + `\")\n\nvar _ = bytes.Buffer{}\n\n// end\n`\n\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName:  \"foo.com\",\n\t\t\tFiles: fm{\"foo.go\": input},\n\t\t},\n\t}.processTest(t, \"foo.com\", \"foo.go\", nil, nil, want)\n}\n\n// Tests that an external test package will import the package under test if it\n// also uses symbols exported only in test files.\n// https://golang.org/issues/29979\nfunc TestExternalTest(t *testing.T) {\n\tconst input = `package a_test\nfunc TestX() {\n\ta.X()\n\ta.Y()\n}\n`\n\tconst want = `package a_test\n\nimport \"foo.com/a\"\n\nfunc TestX() {\n\ta.X()\n\ta.Y()\n}\n`\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName: \"foo.com/a\",\n\t\t\t\tFiles: fm{\n\t\t\t\t\t\"a.go\":           \"package a\\n func X() {}\",\n\t\t\t\t\t\"export_test.go\": \"package a\\n func Y() {}\",\n\t\t\t\t\t\"a_test.go\":      input,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}.processTest(t, \"foo.com/a\", \"a_test.go\", nil, nil, want)\n}\n\n// TestGetCandidates tests that get packages finds packages\n// with correct priorities.\nfunc TestGetCandidates(t *testing.T) {\n\ttype res struct {\n\t\trelevance  float64\n\t\tname, path string\n\t}\n\twant := []res{\n\t\t{0, \"bytes\", \"bytes\"},\n\t\t{0, \"http\", \"net/http\"},\n\t\t{0, \"rand\", \"crypto/rand\"},\n\t\t{0, \"bar\", \"bar.com/bar\"},\n\t\t{0, \"foo\", \"foo.com/foo\"},\n\t}\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"bar.com\",\n\t\t\t\tFiles: fm{\"bar/bar.go\": \"package bar\\n\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:  \"foo.com\",\n\t\t\t\tFiles: fm{\"foo/foo.go\": \"package foo\\n\"},\n\t\t\t},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tvar mu sync.Mutex\n\t\tvar got []res\n\t\tadd := func(c ImportFix) {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfor _, w := range want {\n\t\t\t\tif c.StmtInfo.ImportPath == w.path {\n\t\t\t\t\tgot = append(got, res{c.Relevance, c.IdentName, c.StmtInfo.ImportPath})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := GetAllCandidates(context.Background(), add, \"\", \"x.go\", \"x\", t.env); err != nil {\n\t\t\tt.Fatalf(\"GetAllCandidates() = %v\", err)\n\t\t}\n\t\t// Sort, then clear out relevance so it doesn't mess up the DeepEqual.\n\t\tsort.Slice(got, func(i, j int) bool {\n\t\t\tri, rj := got[i], got[j]\n\t\t\tif ri.relevance != rj.relevance {\n\t\t\t\treturn ri.relevance > rj.relevance // Highest first.\n\t\t\t}\n\t\t\treturn ri.name < rj.name\n\t\t})\n\t\tfor i := range got {\n\t\t\tgot[i].relevance = 0\n\t\t}\n\t\tif !reflect.DeepEqual(want, got) {\n\t\t\tt.Errorf(\"wanted results in order %v, got %v\", want, got)\n\t\t}\n\t})\n}\n\nfunc TestGetImportPaths(t *testing.T) {\n\ttype res struct {\n\t\trelevance  float64\n\t\tname, path string\n\t}\n\twant := []res{\n\t\t{0, \"http\", \"net/http\"},\n\t\t{0, \"net\", \"net\"},\n\t\t{0, \"neta\", \"neta.com/neta\"},\n\t}\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"neta.com\",\n\t\t\t\tFiles: fm{\"neta/neta.go\": \"package neta\\n\"},\n\t\t\t},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tvar mu sync.Mutex\n\t\tvar got []res\n\t\tadd := func(c ImportFix) {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfor _, w := range want {\n\t\t\t\tif c.StmtInfo.ImportPath == w.path {\n\t\t\t\t\tgot = append(got, res{c.Relevance, c.IdentName, c.StmtInfo.ImportPath})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := GetImportPaths(context.Background(), add, \"ne\", \"x.go\", \"x\", t.env); err != nil {\n\t\t\tt.Fatalf(\"GetImportPaths() = %v\", err)\n\t\t}\n\t\t// Sort, then clear out relevance so it doesn't mess up the DeepEqual.\n\t\tsort.Slice(got, func(i, j int) bool {\n\t\t\tri, rj := got[i], got[j]\n\t\t\tif ri.relevance != rj.relevance {\n\t\t\t\treturn ri.relevance > rj.relevance // Highest first.\n\t\t\t}\n\t\t\treturn ri.name < rj.name\n\t\t})\n\t\tfor i := range got {\n\t\t\tgot[i].relevance = 0\n\t\t}\n\t\tif !reflect.DeepEqual(want, got) {\n\t\t\tt.Errorf(\"wanted results in order %v, got %v\", want, got)\n\t\t}\n\t})\n}\n\nfunc TestGetPackageCompletions(t *testing.T) {\n\ttype res struct {\n\t\trelevance          float64\n\t\tname, path, symbol string\n\t}\n\twant := []res{\n\t\t{0, \"rand\", \"math/rand\", \"Seed\"},\n\t\t{0, \"rand\", \"bar.com/rand\", \"Bar\"},\n\t}\n\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"bar.com\",\n\t\t\t\tFiles: fm{\"rand/bar.go\": \"package rand\\nvar Bar int\\n\"},\n\t\t\t},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tvar mu sync.Mutex\n\t\tvar got []res\n\t\tadd := func(c PackageExport) {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfor _, csym := range c.Exports {\n\t\t\t\tfor _, w := range want {\n\t\t\t\t\tif c.Fix.StmtInfo.ImportPath == w.path && csym.Name == w.symbol {\n\t\t\t\t\t\tgot = append(got, res{c.Fix.Relevance, c.Fix.IdentName, c.Fix.StmtInfo.ImportPath, csym.Name})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := GetPackageExports(context.Background(), add, \"rand\", \"x.go\", \"x\", t.env); err != nil {\n\t\t\tt.Fatalf(\"getPackageCompletions() = %v\", err)\n\t\t}\n\t\t// Sort, then clear out relevance so it doesn't mess up the DeepEqual.\n\t\tsort.Slice(got, func(i, j int) bool {\n\t\t\tri, rj := got[i], got[j]\n\t\t\tif ri.relevance != rj.relevance {\n\t\t\t\treturn ri.relevance > rj.relevance // Highest first.\n\t\t\t}\n\t\t\treturn ri.name < rj.name\n\t\t})\n\t\tfor i := range got {\n\t\t\tgot[i].relevance = 0\n\t\t}\n\t\tif !reflect.DeepEqual(want, got) {\n\t\t\tt.Errorf(\"wanted results in order %v, got %v\", want, got)\n\t\t}\n\t})\n}\n\n// Tests #34895: process should not panic on concurrent calls.\nfunc TestConcurrentProcess(t *testing.T) {\n\ttestConfig{\n\t\tmodule: packagestest.Module{\n\t\t\tName: \"foo.com\",\n\t\t\tFiles: fm{\n\t\t\t\t\"p/first.go\": `package foo\n\nfunc _() {\n\tfmt.Println()\n}\n`,\n\t\t\t\t\"p/second.go\": `package foo\n\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Println()\n\timports.Bar() // not imported.\n}\n`,\n\t\t\t},\n\t\t},\n\t}.test(t, func(t *goimportTest) {\n\t\tvar (\n\t\t\tn  = 10\n\t\t\twg sync.WaitGroup\n\t\t)\n\t\twg.Add(n)\n\t\tfor range n {\n\t\t\tgo func() {\n\t\t\t\tdefer wg.Done()\n\t\t\t\t_, err := t.process(\"foo.com\", \"p/first.go\", nil, nil)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Error(err)\n\t\t\t\t}\n\t\t\t}()\n\t\t}\n\t\twg.Wait()\n\t})\n}\n\nfunc TestNonlocalDot(t *testing.T) {\n\tconst input = `package main\nimport (\n\t\"fmt\"\n)\nvar _, _ = fmt.Sprintf, dot.Dot\n`\n\tconst want = `package main\n\nimport (\n\t\"fmt\"\n\t\"noninternet/dot.v1/dot\"\n)\n\nvar _, _ = fmt.Sprintf, dot.Dot\n`\n\ttestConfig{\n\t\tmodules: []packagestest.Module{\n\t\t\t{\n\t\t\t\tName:  \"golang.org/fake\",\n\t\t\t\tFiles: fm{\"x.go\": input},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"noninternet/dot.v1\",\n\t\t\t\tFiles: fm{\n\t\t\t\t\t\"dot/dot.go\": \"package dot\\nfunc Dot(){}\\n\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tgopathOnly: true, // our modules testing setup doesn't allow modules without dots.\n\t}.processTest(t, \"golang.org/fake\", \"x.go\", nil, nil, want)\n}\n\nfunc TestSymbolSearchStarvation(t *testing.T) {\n\t// This test verifies the fix for golang/go#67923: searching through\n\t// candidates should not starve when the context is cancelled.\n\t//\n\t// To reproduce the conditions that led to starvation, cancel the context\n\t// half way through the search, by leveraging the loadExports callback.\n\tconst candCount = 100\n\tvar loaded atomic.Int32\n\tctx, cancel := context.WithCancel(context.Background())\n\tsearcher := symbolSearcher{\n\t\tlogf:   t.Logf,\n\t\tsrcDir: \"/path/to/foo\",\n\t\tloadExports: func(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) {\n\t\t\tif loaded.Add(1) > candCount/2 {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\treturn \"bar\", []stdlib.Symbol{\n\t\t\t\t{Name: \"A\", Kind: stdlib.Var},\n\t\t\t\t{Name: \"B\", Kind: stdlib.Var},\n\t\t\t\t// Missing: \"C\", so that none of these packages match.\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tvar candidates []pkgDistance\n\tfor i := range candCount {\n\t\tname := fmt.Sprintf(\"bar%d\", i)\n\t\tcandidates = append(candidates, pkgDistance{\n\t\t\tpkg: &pkg{\n\t\t\t\tdir:             path.Join(searcher.srcDir, name),\n\t\t\t\timportPathShort: \"foo/\" + name,\n\t\t\t\tpackageName:     name,\n\t\t\t\trelevance:       1,\n\t\t\t},\n\t\t\tdistance: 1,\n\t\t})\n\t}\n\n\t// We don't actually care what happens, as long as it doesn't deadlock!\n\t_, err := searcher.search(ctx, candidates, \"bar\", map[string]bool{\"A\": true, \"B\": true, \"C\": true})\n\tt.Logf(\"search completed with err: %v\", err)\n}\n\nfunc TestMatchesPath(t *testing.T) {\n\ttests := []struct {\n\t\tident string\n\t\tpath  string\n\t\twant  bool\n\t}{\n\t\t// degenerate cases\n\t\t{\"\", \"\", true},\n\t\t{\"\", \"x\", false},\n\t\t{\"x\", \"\", false},\n\n\t\t// full segment matching\n\t\t{\"x\", \"x\", true},\n\t\t{\"x\", \"y\", false},\n\t\t{\"x\", \"wx\", false},\n\t\t{\"x\", \"path/to/x\", true},\n\t\t{\"mypkg\", \"path/to/mypkg\", true},\n\t\t{\"x\", \"path/to/xy\", false},\n\t\t{\"x\", \"path/to/x/y\", true},\n\t\t{\"mypkg\", \"path/to/mypkg/y\", true},\n\t\t{\"x\", \"path/to/x/v3\", true},\n\n\t\t// subsegment matching\n\t\t{\"x\", \"path/to/x-go\", true},\n\t\t{\"foo\", \"path/to/go-foo\", true},\n\t\t{\"go\", \"path/to/go-foo\", true},\n\t\t{\"gofoo\", \"path/to/go-foo\", true},\n\t\t{\"gofoo\", \"path/to/go-foo-bar\", false},\n\t\t{\"foo\", \"path/to/go-foo-bar\", true},\n\t\t{\"bar\", \"path/to/go-foo-bar\", true},\n\t\t{\"gofoobar\", \"path/to/go-foo-bar\", true},\n\t\t{\"x\", \"path/to/x.v3\", true},\n\t\t{\"x\", \"path/to/xy.v3\", false},\n\t\t{\"x\", \"path/to/wx.v3\", false},\n\n\t\t// case insensitivity\n\t\t{\"MyPkg\", \"path/to/mypkg\", true},\n\t\t{\"myPkg\", \"path/to/MyPkg\", true},\n\n\t\t// multi-byte runes\n\t\t{\"世界\", \"path/to/世界\", true},\n\t\t{\"世界\", \"path/to/世界/foo\", true},\n\t\t{\"世界\", \"path/to/go-世界/foo\", true},\n\t\t{\"世界\", \"path/to/世/foo\", false},\n\t}\n\n\tfor _, test := range tests {\n\t\tif got := matchesPath(test.ident, test.path); got != test.want {\n\t\t\tt.Errorf(\"matchesPath(%q, %q) = %v, want %v\", test.ident, test.path, got, test.want)\n\t\t}\n\t}\n}\n\nfunc BenchmarkMatchesPath(b *testing.B) {\n\t// A collection of calls that exercise different kinds of matching.\n\ttests := map[string][]struct {\n\t\tident string\n\t\tpath  string\n\t\twant  bool\n\t}{\n\t\t\"easy\": { // lower case ascii\n\t\t\t{\"mypkg\", \"path/to/mypkg/y\", true},\n\t\t\t{\"foo\", \"path/to/go-foo-bar\", true},\n\t\t\t{\"gofoo\", \"path/to/go-foo-bar-baz\", false},\n\t\t},\n\t\t\"hard\": {\n\t\t\t{\"MyPkg\", \"path/to/mypkg\", true},\n\t\t\t{\"世界\", \"path/to/go-世界-pkg/foo\", true},\n\t\t\t{\"longpkgname\", \"cloud.google.com/Go/Spanner/Admin/Database/longpkgname\", true},\n\t\t},\n\t}\n\n\tfor name, tests := range tests {\n\t\tb.Run(name, func(b *testing.B) {\n\t\t\tfor b.Loop() {\n\t\t\t\tfor _, test := range tests {\n\t\t\t\t\tif got := matchesPath(test.ident, test.path); got != test.want {\n\t\t\t\t\t\tb.Errorf(\"matchesPath(%q, %q) = %v, want %v\", test.ident, test.path, got, test.want)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/imports/imports.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package imports implements a Go pretty-printer (like package \"go/format\")\n// that also adds or removes import statements as necessary.\npackage imports\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"io\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Options is golang.org/x/tools/imports.Options with extra internal-only options.\ntype Options struct {\n\tEnv *ProcessEnv // The environment to use. Note: this contains the cached module and filesystem state.\n\n\t// LocalPrefix is a comma-separated string of import path prefixes, which, if\n\t// set, instructs Process to sort the import paths with the given prefixes\n\t// into another group after 3rd-party packages.\n\tLocalPrefix string\n\n\tFragment  bool // Accept fragment of a source file (no package statement)\n\tAllErrors bool // Report all errors (not just the first 10 on different lines)\n\n\tComments  bool // Print comments (true if nil *Options provided)\n\tTabIndent bool // Use tabs for indent (true if nil *Options provided)\n\tTabWidth  int  // Tab width (8 if nil *Options provided)\n\n\tFormatOnly bool // Disable the insertion and deletion of imports\n}\n\n// Process implements golang.org/x/tools/imports.Process with explicit context in opt.Env.\nfunc Process(filename string, src []byte, opt *Options) (formatted []byte, err error) {\n\tfileSet := token.NewFileSet()\n\tvar parserMode parser.Mode\n\tif opt.Comments {\n\t\tparserMode |= parser.ParseComments\n\t}\n\tif opt.AllErrors {\n\t\tparserMode |= parser.AllErrors\n\t}\n\tfile, adjust, err := parse(fileSet, filename, src, parserMode, opt.Fragment)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !opt.FormatOnly {\n\t\tif err := fixImports(fileSet, file, filename, opt.Env); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn formatFile(fileSet, file, src, adjust, opt)\n}\n\n// FixImports returns a list of fixes to the imports that, when applied,\n// will leave the imports in the same state as Process. src and opt must\n// be specified.\n//\n// Note that filename's directory influences which imports can be chosen,\n// so it is important that filename be accurate.\nfunc FixImports(ctx context.Context, filename string, src []byte, goroot string, logf func(string, ...any), source Source) (fixes []*ImportFix, err error) {\n\tctx, done := event.Start(ctx, \"imports.FixImports\")\n\tdefer done()\n\n\tfileSet := token.NewFileSet()\n\t// TODO(rfindley): these default values for ParseComments and AllErrors were\n\t// extracted from gopls, but are they even needed?\n\tfile, _, err := parse(fileSet, filename, src, parser.ParseComments|parser.AllErrors, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn getFixesWithSource(ctx, fileSet, file, filename, goroot, logf, source)\n}\n\n// ApplyFixes applies all of the fixes to the file and formats it. extraMode\n// is added in when parsing the file. src and opts must be specified, but no\n// env is needed.\nfunc ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) {\n\t// Don't use parse() -- we don't care about fragments or statement lists\n\t// here, and we need to work with unparsable files.\n\tfileSet := token.NewFileSet()\n\tparserMode := parser.SkipObjectResolution\n\tif opt.Comments {\n\t\tparserMode |= parser.ParseComments\n\t}\n\tif opt.AllErrors {\n\t\tparserMode |= parser.AllErrors\n\t}\n\tparserMode |= extraMode\n\n\tfile, err := parser.ParseFile(fileSet, filename, src, parserMode)\n\tif file == nil {\n\t\treturn nil, err\n\t}\n\n\t// Apply the fixes to the file.\n\tapply(fileSet, file, fixes)\n\n\treturn formatFile(fileSet, file, src, nil, opt)\n}\n\n// formatFile formats the file syntax tree.\n// It may mutate the token.FileSet and the ast.File.\n//\n// If an adjust function is provided, it is called after formatting\n// with the original source (formatFile's src parameter) and the\n// formatted file, and returns the postpocessed result.\nfunc formatFile(fset *token.FileSet, file *ast.File, src []byte, adjust func(orig []byte, src []byte) []byte, opt *Options) ([]byte, error) {\n\tmergeImports(file)\n\tsortImports(opt.LocalPrefix, fset.File(file.FileStart), file)\n\tvar spacesBefore []string // import paths we need spaces before\n\tfor _, impSection := range astutil.Imports(fset, file) {\n\t\t// Within each block of contiguous imports, see if any\n\t\t// import lines are in different group numbers. If so,\n\t\t// we'll need to put a space between them so it's\n\t\t// compatible with gofmt.\n\t\tlastGroup := -1\n\t\tfor _, importSpec := range impSection {\n\t\t\timportPath, _ := strconv.Unquote(importSpec.Path.Value)\n\t\t\tgroupNum := importGroup(opt.LocalPrefix, importPath)\n\t\t\tif groupNum != lastGroup && lastGroup != -1 {\n\t\t\t\tspacesBefore = append(spacesBefore, importPath)\n\t\t\t}\n\t\t\tlastGroup = groupNum\n\t\t}\n\n\t}\n\n\tprinterMode := printer.UseSpaces\n\tif opt.TabIndent {\n\t\tprinterMode |= printer.TabIndent\n\t}\n\tprintConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth}\n\n\tvar buf bytes.Buffer\n\terr := printConfig.Fprint(&buf, fset, file)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tout := buf.Bytes()\n\tif adjust != nil {\n\t\tout = adjust(src, out)\n\t}\n\tif len(spacesBefore) > 0 {\n\t\tout, err = addImportSpaces(bytes.NewReader(out), spacesBefore)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tout, err = format.Source(out)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// parse parses src, which was read from filename,\n// as a Go source file or statement list.\nfunc parse(fset *token.FileSet, filename string, src []byte, parserMode parser.Mode, fragment bool) (*ast.File, func(orig, src []byte) []byte, error) {\n\tif parserMode&parser.SkipObjectResolution != 0 {\n\t\tpanic(\"legacy ast.Object resolution is required\")\n\t}\n\n\t// Try as whole source file.\n\tfile, err := parser.ParseFile(fset, filename, src, parserMode)\n\tif err == nil {\n\t\treturn file, nil, nil\n\t}\n\t// If the error is that the source file didn't begin with a\n\t// package line and we accept fragmented input, fall through to\n\t// try as a source fragment.  Stop and return on any other error.\n\tif !fragment || !strings.Contains(err.Error(), \"expected 'package'\") {\n\t\treturn nil, nil, err\n\t}\n\n\t// If this is a declaration list, make it a source file\n\t// by inserting a package clause.\n\t// Insert using a ;, not a newline, so that parse errors are on\n\t// the correct line.\n\tconst prefix = \"package main;\"\n\tpsrc := append([]byte(prefix), src...)\n\tfile, err = parser.ParseFile(fset, filename, psrc, parserMode)\n\tif err == nil {\n\t\t// Gofmt will turn the ; into a \\n.\n\t\t// Do that ourselves now and update the file contents,\n\t\t// so that positions and line numbers are correct going forward.\n\t\tpsrc[len(prefix)-1] = '\\n'\n\t\tfset.File(file.Package).SetLinesForContent(psrc)\n\n\t\t// If a main function exists, we will assume this is a main\n\t\t// package and leave the file.\n\t\tif containsMainFunc(file) {\n\t\t\treturn file, nil, nil\n\t\t}\n\n\t\tadjust := func(orig, src []byte) []byte {\n\t\t\t// Remove the package clause.\n\t\t\tsrc = src[len(prefix):]\n\t\t\treturn matchSpace(orig, src)\n\t\t}\n\t\treturn file, adjust, nil\n\t}\n\t// If the error is that the source file didn't begin with a\n\t// declaration, fall through to try as a statement list.\n\t// Stop and return on any other error.\n\tif !strings.Contains(err.Error(), \"expected declaration\") {\n\t\treturn nil, nil, err\n\t}\n\n\t// If this is a statement list, make it a source file\n\t// by inserting a package clause and turning the list\n\t// into a function body.  This handles expressions too.\n\t// Insert using a ;, not a newline, so that the line numbers\n\t// in fsrc match the ones in src.\n\tfsrc := append(append([]byte(\"package p; func _() {\"), src...), '}')\n\tfile, err = parser.ParseFile(fset, filename, fsrc, parserMode)\n\tif err == nil {\n\t\tadjust := func(orig, src []byte) []byte {\n\t\t\t// Remove the wrapping.\n\t\t\t// Gofmt has turned the ; into a \\n\\n.\n\t\t\tsrc = src[len(\"package p\\n\\nfunc _() {\"):]\n\t\t\tsrc = src[:len(src)-len(\"}\\n\")]\n\t\t\t// Gofmt has also indented the function body one level.\n\t\t\t// Remove that indent.\n\t\t\tsrc = bytes.ReplaceAll(src, []byte(\"\\n\\t\"), []byte(\"\\n\"))\n\t\t\treturn matchSpace(orig, src)\n\t\t}\n\t\treturn file, adjust, nil\n\t}\n\n\t// Failed, and out of options.\n\treturn nil, nil, err\n}\n\n// containsMainFunc checks if a file contains a function declaration with the\n// function signature 'func main()'\nfunc containsMainFunc(file *ast.File) bool {\n\tfor _, decl := range file.Decls {\n\t\tif f, ok := decl.(*ast.FuncDecl); ok {\n\t\t\tif f.Name.Name != \"main\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif len(f.Type.Params.List) != 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif f.Type.Results != nil && len(f.Type.Results.List) != 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc cutSpace(b []byte) (before, middle, after []byte) {\n\ti := 0\n\tfor i < len(b) && (b[i] == ' ' || b[i] == '\\t' || b[i] == '\\n') {\n\t\ti++\n\t}\n\tj := len(b)\n\tfor j > 0 && (b[j-1] == ' ' || b[j-1] == '\\t' || b[j-1] == '\\n') {\n\t\tj--\n\t}\n\tif i <= j {\n\t\treturn b[:i], b[i:j], b[j:]\n\t}\n\treturn nil, nil, b[j:]\n}\n\n// matchSpace reformats src to use the same space context as orig.\n//  1. If orig begins with blank lines, matchSpace inserts them at the beginning of src.\n//  2. matchSpace copies the indentation of the first non-blank line in orig\n//     to every non-blank line in src.\n//  3. matchSpace copies the trailing space from orig and uses it in place\n//     of src's trailing space.\nfunc matchSpace(orig []byte, src []byte) []byte {\n\tbefore, _, after := cutSpace(orig)\n\ti := bytes.LastIndex(before, []byte{'\\n'})\n\tbefore, indent := before[:i+1], before[i+1:]\n\n\t_, src, _ = cutSpace(src)\n\n\tvar b bytes.Buffer\n\tb.Write(before)\n\tfor len(src) > 0 {\n\t\tline := src\n\t\tif i := bytes.IndexByte(line, '\\n'); i >= 0 {\n\t\t\tline, src = line[:i+1], line[i+1:]\n\t\t} else {\n\t\t\tsrc = nil\n\t\t}\n\t\tif len(line) > 0 && line[0] != '\\n' { // not blank\n\t\t\tb.Write(indent)\n\t\t}\n\t\tb.Write(line)\n\t}\n\tb.Write(after)\n\treturn b.Bytes()\n}\n\nvar impLine = regexp.MustCompile(`^\\s+(?:[\\w\\.]+\\s+)?\"(.+?)\"`)\n\nfunc addImportSpaces(r io.Reader, breaks []string) ([]byte, error) {\n\tvar out bytes.Buffer\n\tin := bufio.NewReader(r)\n\tinImports := false\n\tdone := false\n\tfor {\n\t\ts, err := in.ReadString('\\n')\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t} else if err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif !inImports && !done && strings.HasPrefix(s, \"import\") {\n\t\t\tinImports = true\n\t\t}\n\t\tif inImports && (strings.HasPrefix(s, \"var\") ||\n\t\t\tstrings.HasPrefix(s, \"func\") ||\n\t\t\tstrings.HasPrefix(s, \"const\") ||\n\t\t\tstrings.HasPrefix(s, \"type\")) {\n\t\t\tdone = true\n\t\t\tinImports = false\n\t\t}\n\t\tif inImports && len(breaks) > 0 {\n\t\t\tif m := impLine.FindStringSubmatch(s); m != nil {\n\t\t\t\tif m[1] == breaks[0] {\n\t\t\t\t\tout.WriteByte('\\n')\n\t\t\t\t\tbreaks = breaks[1:]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfmt.Fprint(&out, s)\n\t}\n\treturn out.Bytes(), nil\n}\n"
  },
  {
    "path": "internal/imports/imports_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestMain(m *testing.M) {\n\ttestenv.ExitIfSmallMachine()\n\tos.Exit(m.Run())\n}\n"
  },
  {
    "path": "internal/imports/mkindex.go",
    "content": "//go:build ignore\n\n// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Command mkindex creates the file \"pkgindex.go\" containing an index of the Go\n// standard library. The file is intended to be built as part of the imports\n// package, so that the package may be used in environments where a GOROOT is\n// not available (such as App Engine).\npackage imports\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nvar (\n\tpkgIndex = make(map[string][]pkg)\n\texports  = make(map[string]map[string]bool)\n)\n\nfunc main() {\n\t// Don't use GOPATH.\n\tctx := build.Default\n\tctx.GOPATH = \"\"\n\n\t// Populate pkgIndex global from GOROOT.\n\tfor _, path := range ctx.SrcDirs() {\n\t\tf, err := os.Open(path)\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t\tcontinue\n\t\t}\n\t\tchildren, err := f.Readdir(-1)\n\t\tf.Close()\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t\tcontinue\n\t\t}\n\t\tfor _, child := range children {\n\t\t\tif child.IsDir() {\n\t\t\t\tloadPkg(path, child.Name())\n\t\t\t}\n\t\t}\n\t}\n\t// Populate exports global.\n\tfor _, ps := range pkgIndex {\n\t\tfor _, p := range ps {\n\t\t\te := loadExports(p.dir)\n\t\t\tif e != nil {\n\t\t\t\texports[p.dir] = e\n\t\t\t}\n\t\t}\n\t}\n\n\t// Construct source file.\n\tvar buf bytes.Buffer\n\tfmt.Fprint(&buf, pkgIndexHead)\n\tfmt.Fprintf(&buf, \"var pkgIndexMaster = %#v\\n\", pkgIndex)\n\tfmt.Fprintf(&buf, \"var exportsMaster = %#v\\n\", exports)\n\tsrc := buf.Bytes()\n\n\t// Replace main.pkg type name with pkg.\n\tsrc = bytes.Replace(src, []byte(\"main.pkg\"), []byte(\"pkg\"), -1)\n\t// Replace actual GOROOT with \"/go\".\n\tsrc = bytes.Replace(src, []byte(ctx.GOROOT), []byte(\"/go\"), -1)\n\t// Add some line wrapping.\n\tsrc = bytes.Replace(src, []byte(\"}, \"), []byte(\"},\\n\"), -1)\n\tsrc = bytes.Replace(src, []byte(\"true, \"), []byte(\"true,\\n\"), -1)\n\n\tvar err error\n\tsrc, err = format.Source(src)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Write out source file.\n\terr = os.WriteFile(\"pkgindex.go\", src, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nconst pkgIndexHead = `package imports\n\nfunc init() {\n\tpkgIndexOnce.Do(func() {\n\t\tpkgIndex.m = pkgIndexMaster\n\t})\n\tloadExports = func(dir string) map[string]bool {\n\t\treturn exportsMaster[dir]\n\t}\n}\n`\n\ntype pkg struct {\n\timportpath string // full pkg import path, e.g. \"net/http\"\n\tdir        string // absolute file path to pkg directory e.g. \"/usr/lib/go/src/fmt\"\n}\n\nvar fset = token.NewFileSet()\n\nfunc loadPkg(root, importpath string) {\n\tshortName := path.Base(importpath)\n\tif shortName == \"testdata\" {\n\t\treturn\n\t}\n\n\tdir := filepath.Join(root, importpath)\n\tpkgIndex[shortName] = append(pkgIndex[shortName], pkg{\n\t\timportpath: importpath,\n\t\tdir:        dir,\n\t})\n\n\tpkgDir, err := os.Open(dir)\n\tif err != nil {\n\t\treturn\n\t}\n\tchildren, err := pkgDir.Readdir(-1)\n\tpkgDir.Close()\n\tif err != nil {\n\t\treturn\n\t}\n\tfor _, child := range children {\n\t\tname := child.Name()\n\t\tif name == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif c := name[0]; c == '.' || ('0' <= c && c <= '9') {\n\t\t\tcontinue\n\t\t}\n\t\tif child.IsDir() {\n\t\t\tloadPkg(root, filepath.Join(importpath, name))\n\t\t}\n\t}\n}\n\nfunc loadExports(dir string) map[string]bool {\n\texports := make(map[string]bool)\n\tbuildPkg, err := build.ImportDir(dir, 0)\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"no buildable Go source files in\") {\n\t\t\treturn nil\n\t\t}\n\t\tlog.Printf(\"could not import %q: %v\", dir, err)\n\t\treturn nil\n\t}\n\tfor _, file := range buildPkg.GoFiles {\n\t\t// Legacy ast.Object resolution is needed here.\n\t\tf, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"could not parse %q: %v\", file, err)\n\t\t\tcontinue\n\t\t}\n\t\tfor name := range f.Scope.Objects {\n\t\t\tif ast.IsExported(name) {\n\t\t\t\texports[name] = true\n\t\t\t}\n\t\t}\n\t}\n\treturn exports\n}\n"
  },
  {
    "path": "internal/imports/mod.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n\t\"golang.org/x/tools/internal/stdlib\"\n)\n\n// Notes(rfindley): ModuleResolver appears to be heavily optimized for scanning\n// as fast as possible, which is desirable for a call to goimports from the\n// command line, but it doesn't work as well for gopls, where it suffers from\n// slow startup (golang/go#44863) and intermittent hanging (golang/go#59216),\n// both caused by populating the cache, albeit in slightly different ways.\n//\n// A high level list of TODOs:\n//  - Optimize the scan itself, as there is some redundancy statting and\n//    reading go.mod files.\n//  - Invert the relationship between ProcessEnv and Resolver (see the\n//    docstring of ProcessEnv).\n//  - Make it easier to use an external resolver implementation.\n//\n// Smaller TODOs are annotated in the code below.\n\n// ModuleResolver implements the Resolver interface for a workspace using\n// modules.\n//\n// A goal of the ModuleResolver is to invoke the Go command as little as\n// possible. To this end, it runs the Go command only for listing module\n// information (i.e. `go list -m -e -json ...`). Package scanning, the process\n// of loading package information for the modules, is implemented internally\n// via the scan method.\n//\n// It has two types of state: the state derived from the go command, which\n// is populated by init, and the state derived from scans, which is populated\n// via scan. A root is considered scanned if it has been walked to discover\n// directories. However, if the scan did not require additional information\n// from the directory (such as package name or exports), the directory\n// information itself may be partially populated. It will be lazily filled in\n// as needed by scans, using the scanCallback.\ntype ModuleResolver struct {\n\tenv *ProcessEnv\n\n\t// Module state, populated during construction\n\tdummyVendorMod *gocommand.ModuleJSON            // if vendoring is enabled, a pseudo-module to represent the /vendor directory\n\tmoduleCacheDir string                           // GOMODCACHE, inferred from GOPATH if unset\n\troots          []gopathwalk.Root                // roots to scan, in approximate order of importance\n\tmains          []*gocommand.ModuleJSON          // main modules\n\tmainByDir      map[string]*gocommand.ModuleJSON // module information by dir, to join with roots\n\tmodsByModPath  []*gocommand.ModuleJSON          // all modules, ordered by # of path components in their module path\n\tmodsByDir      []*gocommand.ModuleJSON          // ...or by the number of path components in their Dir.\n\n\t// Scanning state, populated by scan\n\n\t// scanSema prevents concurrent scans, and guards scannedRoots and the cache\n\t// fields below (though the caches themselves are concurrency safe).\n\t// Receive to acquire, send to release.\n\tscanSema     chan struct{}\n\tscannedRoots map[gopathwalk.Root]bool // if true, root has been walked\n\n\t// Caches of directory info, populated by scans and scan callbacks\n\t//\n\t// moduleCacheCache stores cached information about roots in the module\n\t// cache, which are immutable and therefore do not need to be invalidated.\n\t//\n\t// otherCache stores information about all other roots (even GOROOT), which\n\t// may change.\n\tmoduleCacheCache *DirInfoCache\n\totherCache       *DirInfoCache\n}\n\n// newModuleResolver returns a new module-aware goimports resolver.\n//\n// Note: use caution when modifying this constructor: changes must also be\n// reflected in ModuleResolver.ClearForNewScan.\nfunc newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleResolver, error) {\n\tr := &ModuleResolver{\n\t\tenv:      e,\n\t\tscanSema: make(chan struct{}, 1),\n\t}\n\tr.scanSema <- struct{}{} // release\n\n\tgoenv, err := r.env.goEnv()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// TODO(rfindley): can we refactor to share logic with r.env.invokeGo?\n\tinv := gocommand.Invocation{\n\t\tBuildFlags: r.env.BuildFlags,\n\t\tModFlag:    r.env.ModFlag,\n\t\tEnv:        r.env.env(),\n\t\tLogf:       r.env.Logf,\n\t\tWorkingDir: r.env.WorkingDir,\n\t}\n\n\tvendorEnabled := false\n\tvar mainModVendor *gocommand.ModuleJSON    // for module vendoring\n\tvar mainModsVendor []*gocommand.ModuleJSON // for workspace vendoring\n\n\tgoWork := r.env.Env[\"GOWORK\"]\n\tif len(goWork) == 0 {\n\t\t// TODO(rfindley): VendorEnabled runs the go command to get GOFLAGS, but\n\t\t// they should be available from the ProcessEnv. Can we avoid the redundant\n\t\t// invocation?\n\t\tvendorEnabled, mainModVendor, err = gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\tvendorEnabled, mainModsVendor, err = gocommand.WorkspaceVendorEnabled(context.Background(), inv, r.env.GocmdRunner)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif vendorEnabled {\n\t\tif mainModVendor != nil {\n\t\t\t// Module vendor mode is on, so all the non-Main modules are irrelevant,\n\t\t\t// and we need to search /vendor for everything.\n\t\t\tr.mains = []*gocommand.ModuleJSON{mainModVendor}\n\t\t\tr.dummyVendorMod = &gocommand.ModuleJSON{\n\t\t\t\tPath: \"\",\n\t\t\t\tDir:  filepath.Join(mainModVendor.Dir, \"vendor\"),\n\t\t\t}\n\t\t\tr.modsByModPath = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod}\n\t\t\tr.modsByDir = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod}\n\t\t} else {\n\t\t\t// Workspace vendor mode is on, so all the non-Main modules are irrelevant,\n\t\t\t// and we need to search /vendor for everything.\n\t\t\tr.mains = mainModsVendor\n\t\t\tr.dummyVendorMod = &gocommand.ModuleJSON{\n\t\t\t\tPath: \"\",\n\t\t\t\tDir:  filepath.Join(filepath.Dir(goWork), \"vendor\"),\n\t\t\t}\n\t\t\tr.modsByModPath = append(slices.Clone(mainModsVendor), r.dummyVendorMod)\n\t\t\tr.modsByDir = append(slices.Clone(mainModsVendor), r.dummyVendorMod)\n\t\t}\n\t} else {\n\t\t// Vendor mode is off, so run go list -m ... to find everything.\n\t\terr := r.initAllMods()\n\t\t// We expect an error when running outside of a module with\n\t\t// GO111MODULE=on. Other errors are fatal.\n\t\tif err != nil {\n\t\t\tif errMsg := err.Error(); !strings.Contains(errMsg, \"working directory is not part of a module\") && !strings.Contains(errMsg, \"go.mod file not found\") {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\tr.moduleCacheDir = gomodcacheForEnv(goenv)\n\tif r.moduleCacheDir == \"\" {\n\t\treturn nil, fmt.Errorf(\"cannot resolve GOMODCACHE\")\n\t}\n\n\tsort.Slice(r.modsByModPath, func(i, j int) bool {\n\t\tcount := func(x int) int {\n\t\t\treturn strings.Count(r.modsByModPath[x].Path, \"/\")\n\t\t}\n\t\treturn count(j) < count(i) // descending order\n\t})\n\tsort.Slice(r.modsByDir, func(i, j int) bool {\n\t\tcount := func(x int) int {\n\t\t\treturn strings.Count(r.modsByDir[x].Dir, string(filepath.Separator))\n\t\t}\n\t\treturn count(j) < count(i) // descending order\n\t})\n\n\tr.roots = []gopathwalk.Root{}\n\tif goenv[\"GOROOT\"] != \"\" { // \"\" happens in tests\n\t\tr.roots = append(r.roots, gopathwalk.Root{Path: filepath.Join(goenv[\"GOROOT\"], \"/src\"), Type: gopathwalk.RootGOROOT})\n\t}\n\tr.mainByDir = make(map[string]*gocommand.ModuleJSON)\n\tfor _, main := range r.mains {\n\t\tr.roots = append(r.roots, gopathwalk.Root{Path: main.Dir, Type: gopathwalk.RootCurrentModule})\n\t\tr.mainByDir[main.Dir] = main\n\t}\n\tif vendorEnabled {\n\t\tr.roots = append(r.roots, gopathwalk.Root{Path: r.dummyVendorMod.Dir, Type: gopathwalk.RootOther})\n\t} else {\n\t\taddDep := func(mod *gocommand.ModuleJSON) {\n\t\t\tif mod.Replace == nil {\n\t\t\t\t// This is redundant with the cache, but we'll skip it cheaply enough\n\t\t\t\t// when we encounter it in the module cache scan.\n\t\t\t\t//\n\t\t\t\t// Including it at a lower index in r.roots than the module cache dir\n\t\t\t\t// helps prioritize matches from within existing dependencies.\n\t\t\t\tr.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootModuleCache})\n\t\t\t} else {\n\t\t\t\tr.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootOther})\n\t\t\t}\n\t\t}\n\t\t// Walk dependent modules before scanning the full mod cache, direct deps first.\n\t\tfor _, mod := range r.modsByModPath {\n\t\t\tif !mod.Indirect && !mod.Main {\n\t\t\t\taddDep(mod)\n\t\t\t}\n\t\t}\n\t\tfor _, mod := range r.modsByModPath {\n\t\t\tif mod.Indirect && !mod.Main {\n\t\t\t\taddDep(mod)\n\t\t\t}\n\t\t}\n\t\t// If provided, share the moduleCacheCache.\n\t\t//\n\t\t// TODO(rfindley): The module cache is immutable. However, the loaded\n\t\t// exports do depend on GOOS and GOARCH. Fortunately, the\n\t\t// ProcessEnv.buildContext does not adjust these from build.DefaultContext\n\t\t// (even though it should). So for now, this is OK to share, but we need to\n\t\t// add logic for handling GOOS/GOARCH.\n\t\tr.moduleCacheCache = moduleCacheCache\n\t\tr.roots = append(r.roots, gopathwalk.Root{Path: r.moduleCacheDir, Type: gopathwalk.RootModuleCache})\n\t}\n\n\tr.scannedRoots = map[gopathwalk.Root]bool{}\n\tif r.moduleCacheCache == nil {\n\t\tr.moduleCacheCache = NewDirInfoCache()\n\t}\n\tr.otherCache = NewDirInfoCache()\n\treturn r, nil\n}\n\n// gomodcacheForEnv returns the GOMODCACHE value to use based on the given env\n// map, which must have GOMODCACHE and GOPATH populated.\n//\n// TODO(rfindley): this is defensive refactoring.\n//  1. Is this even relevant anymore? Can't we just read GOMODCACHE.\n//  2. Use this to separate module cache scanning from other scanning.\nfunc gomodcacheForEnv(goenv map[string]string) string {\n\tif gmc := goenv[\"GOMODCACHE\"]; gmc != \"\" {\n\t\t// golang/go#67156: ensure that the module cache is clean, since it is\n\t\t// assumed as a prefix to directories scanned by gopathwalk, which are\n\t\t// themselves clean.\n\t\treturn filepath.Clean(gmc)\n\t}\n\tgopaths := filepath.SplitList(goenv[\"GOPATH\"])\n\tif len(gopaths) == 0 {\n\t\treturn \"\"\n\t}\n\treturn filepath.Join(gopaths[0], \"/pkg/mod\")\n}\n\nfunc (r *ModuleResolver) initAllMods() error {\n\tstdout, err := r.env.invokeGo(context.TODO(), \"list\", \"-m\", \"-e\", \"-json\", \"...\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor dec := json.NewDecoder(stdout); dec.More(); {\n\t\tmod := &gocommand.ModuleJSON{}\n\t\tif err := dec.Decode(mod); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif mod.Dir == \"\" {\n\t\t\tr.env.logf(\"module %v has not been downloaded and will be ignored\", mod.Path)\n\t\t\t// Can't do anything with a module that's not downloaded.\n\t\t\tcontinue\n\t\t}\n\t\t// golang/go#36193: the go command doesn't always clean paths.\n\t\tmod.Dir = filepath.Clean(mod.Dir)\n\t\tr.modsByModPath = append(r.modsByModPath, mod)\n\t\tr.modsByDir = append(r.modsByDir, mod)\n\t\tif mod.Main {\n\t\t\tr.mains = append(r.mains, mod)\n\t\t}\n\t}\n\treturn nil\n}\n\n// ClearForNewScan invalidates the last scan.\n//\n// It preserves the set of roots, but forgets about the set of directories.\n// Though it forgets the set of module cache directories, it remembers their\n// contents, since they are assumed to be immutable.\nfunc (r *ModuleResolver) ClearForNewScan() Resolver {\n\t<-r.scanSema // acquire r, to guard scannedRoots\n\tr2 := &ModuleResolver{\n\t\tenv:            r.env,\n\t\tdummyVendorMod: r.dummyVendorMod,\n\t\tmoduleCacheDir: r.moduleCacheDir,\n\t\troots:          r.roots,\n\t\tmains:          r.mains,\n\t\tmainByDir:      r.mainByDir,\n\t\tmodsByModPath:  r.modsByModPath,\n\n\t\tscanSema:         make(chan struct{}, 1),\n\t\tscannedRoots:     make(map[gopathwalk.Root]bool),\n\t\totherCache:       NewDirInfoCache(),\n\t\tmoduleCacheCache: r.moduleCacheCache,\n\t}\n\tr2.scanSema <- struct{}{} // r2 must start released\n\t// Invalidate root scans. We don't need to invalidate module cache roots,\n\t// because they are immutable.\n\t// (We don't support a use case where GOMODCACHE is cleaned in the middle of\n\t// e.g. a gopls session: the user must restart gopls to get accurate\n\t// imports.)\n\t//\n\t// Scanning for new directories in GOMODCACHE should be handled elsewhere,\n\t// via a call to ScanModuleCache.\n\tfor _, root := range r.roots {\n\t\tif root.Type == gopathwalk.RootModuleCache && r.scannedRoots[root] {\n\t\t\tr2.scannedRoots[root] = true\n\t\t}\n\t}\n\tr.scanSema <- struct{}{} // release r\n\treturn r2\n}\n\n// ClearModuleInfo invalidates resolver state that depends on go.mod file\n// contents (essentially, the output of go list -m -json ...).\n//\n// Notably, it does not forget directory contents, which are reset\n// asynchronously via ClearForNewScan.\n//\n// If the ProcessEnv is a GOPATH environment, ClearModuleInfo is a no op.\n//\n// TODO(rfindley): move this to a new env.go, consolidating ProcessEnv methods.\nfunc (e *ProcessEnv) ClearModuleInfo() {\n\tif r, ok := e.resolver.(*ModuleResolver); ok {\n\t\tresolver, err := newModuleResolver(e, e.ModCache)\n\t\tif err != nil {\n\t\t\te.resolver = nil\n\t\t\te.resolverErr = err\n\t\t\treturn\n\t\t}\n\n\t\t<-r.scanSema // acquire (guards caches)\n\t\tresolver.moduleCacheCache = r.moduleCacheCache\n\t\tresolver.otherCache = r.otherCache\n\t\tr.scanSema <- struct{}{} // release\n\n\t\te.UpdateResolver(resolver)\n\t}\n}\n\n// UpdateResolver sets the resolver for the ProcessEnv to use in imports\n// operations. Only for use with the result of [Resolver.ClearForNewScan].\n//\n// TODO(rfindley): this awkward API is a result of the (arguably) inverted\n// relationship between configuration and state described in the doc comment\n// for [ProcessEnv].\nfunc (e *ProcessEnv) UpdateResolver(r Resolver) {\n\te.resolver = r\n\te.resolverErr = nil\n}\n\n// findPackage returns the module and directory from within the main modules\n// and their dependencies that contains the package at the given import path,\n// or returns nil, \"\" if no module is in scope.\nfunc (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) {\n\t// This can't find packages in the stdlib, but that's harmless for all\n\t// the existing code paths.\n\tfor _, m := range r.modsByModPath {\n\t\tif !strings.HasPrefix(importPath, m.Path) {\n\t\t\tcontinue\n\t\t}\n\t\tpathInModule := importPath[len(m.Path):]\n\t\tpkgDir := filepath.Join(m.Dir, pathInModule)\n\t\tif r.dirIsNestedModule(pkgDir, m) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif info, ok := r.cacheLoad(pkgDir); ok {\n\t\t\tif loaded, err := info.reachedStatus(nameLoaded); loaded {\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue // No package in this dir.\n\t\t\t\t}\n\t\t\t\treturn m, pkgDir\n\t\t\t}\n\t\t\tif scanned, err := info.reachedStatus(directoryScanned); scanned && err != nil {\n\t\t\t\tcontinue // Dir is unreadable, etc.\n\t\t\t}\n\t\t\t// This is slightly wrong: a directory doesn't have to have an\n\t\t\t// importable package to count as a package for package-to-module\n\t\t\t// resolution. package main or _test files should count but\n\t\t\t// don't.\n\t\t\t// TODO(heschi): fix this.\n\t\t\tif _, err := r.cachePackageName(info); err == nil {\n\t\t\t\treturn m, pkgDir\n\t\t\t}\n\t\t}\n\n\t\t// Not cached. Read the filesystem.\n\t\tpkgFiles, err := os.ReadDir(pkgDir)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\t// A module only contains a package if it has buildable go\n\t\t// files in that directory. If not, it could be provided by an\n\t\t// outer module. See #29736.\n\t\tfor _, fi := range pkgFiles {\n\t\t\tif ok, _ := r.env.matchFile(pkgDir, fi.Name()); ok {\n\t\t\t\treturn m, pkgDir\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, \"\"\n}\n\nfunc (r *ModuleResolver) cacheLoad(dir string) (directoryPackageInfo, bool) {\n\tif info, ok := r.moduleCacheCache.Load(dir); ok {\n\t\treturn info, ok\n\t}\n\treturn r.otherCache.Load(dir)\n}\n\nfunc (r *ModuleResolver) cacheStore(info directoryPackageInfo) {\n\tif info.rootType == gopathwalk.RootModuleCache {\n\t\tr.moduleCacheCache.Store(info.dir, info)\n\t} else {\n\t\tr.otherCache.Store(info.dir, info)\n\t}\n}\n\n// cachePackageName caches the package name for a dir already in the cache.\nfunc (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) {\n\tif info.rootType == gopathwalk.RootModuleCache {\n\t\treturn r.moduleCacheCache.CachePackageName(info)\n\t}\n\treturn r.otherCache.CachePackageName(info)\n}\n\nfunc (r *ModuleResolver) cacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []stdlib.Symbol, error) {\n\tif info.rootType == gopathwalk.RootModuleCache {\n\t\treturn r.moduleCacheCache.CacheExports(ctx, env, info)\n\t}\n\treturn r.otherCache.CacheExports(ctx, env, info)\n}\n\n// findModuleByDir returns the module that contains dir, or nil if no such\n// module is in scope.\nfunc (r *ModuleResolver) findModuleByDir(dir string) *gocommand.ModuleJSON {\n\t// This is quite tricky and may not be correct. dir could be:\n\t// - a package in the main module.\n\t// - a replace target underneath the main module's directory.\n\t//    - a nested module in the above.\n\t// - a replace target somewhere totally random.\n\t//    - a nested module in the above.\n\t// - in the mod cache.\n\t// - in /vendor/ in -mod=vendor mode.\n\t//    - nested module? Dunno.\n\t// Rumor has it that replace targets cannot contain other replace targets.\n\t//\n\t// Note that it is critical here that modsByDir is sorted to have deeper dirs\n\t// first. This ensures that findModuleByDir finds the innermost module.\n\t// See also golang/go#56291.\n\tfor _, m := range r.modsByDir {\n\t\tif !strings.HasPrefix(dir, m.Dir) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif r.dirIsNestedModule(dir, m) {\n\t\t\tcontinue\n\t\t}\n\n\t\treturn m\n\t}\n\treturn nil\n}\n\n// dirIsNestedModule reports if dir is contained in a nested module underneath\n// mod, not actually in mod.\nfunc (r *ModuleResolver) dirIsNestedModule(dir string, mod *gocommand.ModuleJSON) bool {\n\tif !strings.HasPrefix(dir, mod.Dir) {\n\t\treturn false\n\t}\n\tif r.dirInModuleCache(dir) {\n\t\t// Nested modules in the module cache are pruned,\n\t\t// so it cannot be a nested module.\n\t\treturn false\n\t}\n\tif mod != nil && mod == r.dummyVendorMod {\n\t\t// The /vendor pseudomodule is flattened and doesn't actually count.\n\t\treturn false\n\t}\n\tmodDir, _ := r.modInfo(dir)\n\tif modDir == \"\" {\n\t\treturn false\n\t}\n\treturn modDir != mod.Dir\n}\n\nfunc readModName(modFile string) string {\n\tmodBytes, err := os.ReadFile(modFile)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn modulePath(modBytes)\n}\n\nfunc (r *ModuleResolver) modInfo(dir string) (modDir, modName string) {\n\tif r.dirInModuleCache(dir) {\n\t\tif matches := modCacheRegexp.FindStringSubmatch(dir); len(matches) == 3 {\n\t\t\tindex := strings.Index(dir, matches[1]+\"@\"+matches[2])\n\t\t\tmodDir := filepath.Join(dir[:index], matches[1]+\"@\"+matches[2])\n\t\t\treturn modDir, readModName(filepath.Join(modDir, \"go.mod\"))\n\t\t}\n\t}\n\tfor {\n\t\tif info, ok := r.cacheLoad(dir); ok {\n\t\t\treturn info.moduleDir, info.moduleName\n\t\t}\n\t\tf := filepath.Join(dir, \"go.mod\")\n\t\tinfo, err := os.Stat(f)\n\t\tif err == nil && !info.IsDir() {\n\t\t\treturn dir, readModName(f)\n\t\t}\n\n\t\td := filepath.Dir(dir)\n\t\tif len(d) >= len(dir) {\n\t\t\treturn \"\", \"\" // reached top of file system, no go.mod\n\t\t}\n\t\tdir = d\n\t}\n}\n\nfunc (r *ModuleResolver) dirInModuleCache(dir string) bool {\n\tif r.moduleCacheDir == \"\" {\n\t\treturn false\n\t}\n\treturn strings.HasPrefix(dir, r.moduleCacheDir)\n}\n\nfunc (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {\n\tnames := map[string]string{}\n\tfor _, path := range importPaths {\n\t\t// TODO(rfindley): shouldn't this use the dirInfoCache?\n\t\t_, packageDir := r.findPackage(path)\n\t\tif packageDir == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tname, err := packageDirToName(packageDir)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tnames[path] = name\n\t}\n\treturn names, nil\n}\n\nfunc (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error {\n\tctx, done := event.Start(ctx, \"imports.ModuleResolver.scan\")\n\tdefer done()\n\n\tprocessDir := func(info directoryPackageInfo) {\n\t\t// Skip this directory if we were not able to get the package information successfully.\n\t\tif scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {\n\t\t\treturn\n\t\t}\n\t\tpkg, err := r.canonicalize(info)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif !callback.dirFound(pkg) {\n\t\t\treturn\n\t\t}\n\n\t\tpkg.packageName, err = r.cachePackageName(info)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif !callback.packageNameLoaded(pkg) {\n\t\t\treturn\n\t\t}\n\n\t\t_, exports, err := r.loadExports(ctx, pkg, false)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tcallback.exportsLoaded(pkg, exports)\n\t}\n\n\t// Start processing everything in the cache, and listen for the new stuff\n\t// we discover in the walk below.\n\tstop1 := r.moduleCacheCache.ScanAndListen(ctx, processDir)\n\tdefer stop1()\n\tstop2 := r.otherCache.ScanAndListen(ctx, processDir)\n\tdefer stop2()\n\n\t// We assume cached directories are fully cached, including all their\n\t// children, and have not changed. We can skip them.\n\tskip := func(root gopathwalk.Root, dir string) bool {\n\t\tif r.env.SkipPathInScan != nil && root.Type == gopathwalk.RootCurrentModule {\n\t\t\tif root.Path == dir {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif r.env.SkipPathInScan(filepath.Clean(dir)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\tinfo, ok := r.cacheLoad(dir)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\t// This directory can be skipped as long as we have already scanned it.\n\t\t// Packages with errors will continue to have errors, so there is no need\n\t\t// to rescan them.\n\t\tpackageScanned, _ := info.reachedStatus(directoryScanned)\n\t\treturn packageScanned\n\t}\n\n\tadd := func(root gopathwalk.Root, dir string) {\n\t\tr.cacheStore(r.scanDirForPackage(root, dir))\n\t}\n\n\t// r.roots and the callback are not necessarily safe to use in the\n\t// goroutine below. Process them eagerly.\n\troots := filterRoots(r.roots, callback.rootFound)\n\t// We can't cancel walks, because we need them to finish to have a usable\n\t// cache. Instead, run them in a separate goroutine and detach.\n\tscanDone := make(chan struct{})\n\tgo func() {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tcase <-r.scanSema: // acquire\n\t\t}\n\t\tdefer func() { r.scanSema <- struct{}{} }() // release\n\t\t// We have the lock on r.scannedRoots, and no other scans can run.\n\t\tfor _, root := range roots {\n\t\t\tif ctx.Err() != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif r.scannedRoots[root] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tgopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: true})\n\t\t\tr.scannedRoots[root] = true\n\t\t}\n\t\tclose(scanDone)\n\t}()\n\tselect {\n\tcase <-ctx.Done():\n\tcase <-scanDone:\n\t}\n\treturn nil\n}\n\nfunc (r *ModuleResolver) scoreImportPath(ctx context.Context, path string) float64 {\n\tif stdlib.HasPackage(path) {\n\t\treturn MaxRelevance\n\t}\n\tmod, _ := r.findPackage(path)\n\treturn modRelevance(mod)\n}\n\nfunc modRelevance(mod *gocommand.ModuleJSON) float64 {\n\tvar relevance float64\n\tswitch {\n\tcase mod == nil: // out of scope\n\t\treturn MaxRelevance - 4\n\tcase mod.Indirect:\n\t\trelevance = MaxRelevance - 3\n\tcase !mod.Main:\n\t\trelevance = MaxRelevance - 2\n\tdefault:\n\t\trelevance = MaxRelevance - 1 // main module ties with stdlib\n\t}\n\n\t_, versionString, ok := module.SplitPathVersion(mod.Path)\n\tif ok {\n\t\tindex := strings.Index(versionString, \"v\")\n\t\tif index == -1 {\n\t\t\treturn relevance\n\t\t}\n\t\tif versionNumber, err := strconv.ParseFloat(versionString[index+1:], 64); err == nil {\n\t\t\trelevance += versionNumber / 1000\n\t\t}\n\t}\n\n\treturn relevance\n}\n\n// canonicalize gets the result of canonicalizing the packages using the results\n// of initializing the resolver from 'go list -m'.\nfunc (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) {\n\t// Packages in GOROOT are already canonical, regardless of the std/cmd modules.\n\tif info.rootType == gopathwalk.RootGOROOT {\n\t\treturn &pkg{\n\t\t\timportPathShort: info.nonCanonicalImportPath,\n\t\t\tdir:             info.dir,\n\t\t\tpackageName:     path.Base(info.nonCanonicalImportPath),\n\t\t\trelevance:       MaxRelevance,\n\t\t}, nil\n\t}\n\n\timportPath := info.nonCanonicalImportPath\n\tmod := r.findModuleByDir(info.dir)\n\t// Check if the directory is underneath a module that's in scope.\n\tif mod != nil {\n\t\t// It is. If dir is the target of a replace directive,\n\t\t// our guessed import path is wrong. Use the real one.\n\t\tif mod.Dir == info.dir {\n\t\t\timportPath = mod.Path\n\t\t} else {\n\t\t\tdirInMod := info.dir[len(mod.Dir)+len(\"/\"):]\n\t\t\timportPath = path.Join(mod.Path, filepath.ToSlash(dirInMod))\n\t\t}\n\t} else if !strings.HasPrefix(importPath, info.moduleName) {\n\t\t// The module's name doesn't match the package's import path. It\n\t\t// probably needs a replace directive we don't have.\n\t\treturn nil, fmt.Errorf(\"package in %q is not valid without a replace statement\", info.dir)\n\t}\n\n\tres := &pkg{\n\t\timportPathShort: importPath,\n\t\tdir:             info.dir,\n\t\trelevance:       modRelevance(mod),\n\t}\n\t// We may have discovered a package that has a different version\n\t// in scope already. Canonicalize to that one if possible.\n\tif _, canonicalDir := r.findPackage(importPath); canonicalDir != \"\" {\n\t\tres.dir = canonicalDir\n\t}\n\treturn res, nil\n}\n\nfunc (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) {\n\tif info, ok := r.cacheLoad(pkg.dir); ok && !includeTest {\n\t\treturn r.cacheExports(ctx, r.env, info)\n\t}\n\treturn loadExportsFromFiles(ctx, r.env, pkg.dir, includeTest)\n}\n\nfunc (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) directoryPackageInfo {\n\tsubdir := \"\"\n\tif prefix := root.Path + string(filepath.Separator); strings.HasPrefix(dir, prefix) {\n\t\tsubdir = dir[len(prefix):]\n\t}\n\timportPath := filepath.ToSlash(subdir)\n\tif strings.HasPrefix(importPath, \"vendor/\") {\n\t\t// Only enter vendor directories if they're explicitly requested as a root.\n\t\treturn directoryPackageInfo{\n\t\t\tstatus: directoryScanned,\n\t\t\terr:    fmt.Errorf(\"unwanted vendor directory\"),\n\t\t}\n\t}\n\tswitch root.Type {\n\tcase gopathwalk.RootCurrentModule:\n\t\timportPath = path.Join(r.mainByDir[root.Path].Path, filepath.ToSlash(subdir))\n\tcase gopathwalk.RootModuleCache:\n\t\tmatches := modCacheRegexp.FindStringSubmatch(subdir)\n\t\tif len(matches) == 0 {\n\t\t\treturn directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"invalid module cache path: %v\", subdir),\n\t\t\t}\n\t\t}\n\t\tmodPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))\n\t\tif err != nil {\n\t\t\tr.env.logf(\"decoding module cache path %q: %v\", subdir, err)\n\t\t\treturn directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"decoding module cache path %q: %v\", subdir, err),\n\t\t\t}\n\t\t}\n\t\timportPath = path.Join(modPath, filepath.ToSlash(matches[3]))\n\t}\n\n\tmodDir, modName := r.modInfo(dir)\n\tresult := directoryPackageInfo{\n\t\tstatus:                 directoryScanned,\n\t\tdir:                    dir,\n\t\trootType:               root.Type,\n\t\tnonCanonicalImportPath: importPath,\n\t\tmoduleDir:              modDir,\n\t\tmoduleName:             modName,\n\t}\n\tif root.Type == gopathwalk.RootGOROOT {\n\t\t// stdlib packages are always in scope, despite the confusing go.mod\n\t\treturn result\n\t}\n\treturn result\n}\n\n// modCacheRegexp splits a path in a module cache into module, module version, and package.\nvar modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\\\]*)(.*)`)\n\nvar (\n\tslashSlash = []byte(\"//\")\n\tmoduleStr  = []byte(\"module\")\n)\n\n// modulePath returns the module path from the gomod file text.\n// If it cannot find a module path, it returns an empty string.\n// It is tolerant of unrelated problems in the go.mod file.\n//\n// Copied from cmd/go/internal/modfile.\nfunc modulePath(mod []byte) string {\n\tfor len(mod) > 0 {\n\t\tline := mod\n\t\tmod = nil\n\t\tif i := bytes.IndexByte(line, '\\n'); i >= 0 {\n\t\t\tline, mod = line[:i], line[i+1:]\n\t\t}\n\t\tif i := bytes.Index(line, slashSlash); i >= 0 {\n\t\t\tline = line[:i]\n\t\t}\n\t\tline = bytes.TrimSpace(line)\n\t\tif !bytes.HasPrefix(line, moduleStr) {\n\t\t\tcontinue\n\t\t}\n\t\tline = line[len(moduleStr):]\n\t\tn := len(line)\n\t\tline = bytes.TrimSpace(line)\n\t\tif len(line) == n || len(line) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif line[0] == '\"' || line[0] == '`' {\n\t\t\tp, err := strconv.Unquote(string(line))\n\t\t\tif err != nil {\n\t\t\t\treturn \"\" // malformed quoted string or multiline module path\n\t\t\t}\n\t\t\treturn p\n\t\t}\n\n\t\treturn string(line)\n\t}\n\treturn \"\" // missing module path\n}\n"
  },
  {
    "path": "internal/imports/mod_cache.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n\t\"golang.org/x/tools/internal/stdlib\"\n)\n\n// To find packages to import, the resolver needs to know about all of\n// the packages that could be imported. This includes packages that are\n// already in modules that are in (1) the current module, (2) replace targets,\n// and (3) packages in the module cache. Packages in (1) and (2) may change over\n// time, as the client may edit the current module and locally replaced modules.\n// The module cache (which includes all of the packages in (3)) can only\n// ever be added to.\n//\n// The resolver can thus save state about packages in the module cache\n// and guarantee that this will not change over time. To obtain information\n// about new modules added to the module cache, the module cache should be\n// rescanned.\n//\n// It is OK to serve information about modules that have been deleted,\n// as they do still exist.\n// TODO(suzmue): can we share information with the caller about\n// what module needs to be downloaded to import this package?\n\ntype directoryPackageStatus int\n\nconst (\n\t_ directoryPackageStatus = iota\n\tdirectoryScanned\n\tnameLoaded\n\texportsLoaded\n)\n\n// directoryPackageInfo holds (possibly incomplete) information about packages\n// contained in a given directory.\ntype directoryPackageInfo struct {\n\t// status indicates the extent to which this struct has been filled in.\n\tstatus directoryPackageStatus\n\t// err is non-nil when there was an error trying to reach status.\n\terr error\n\n\t// Set when status >= directoryScanned.\n\n\t// dir is the absolute directory of this package.\n\tdir      string\n\trootType gopathwalk.RootType\n\t// nonCanonicalImportPath is the package's expected import path. It may\n\t// not actually be importable at that path.\n\tnonCanonicalImportPath string\n\n\t// Module-related information.\n\tmoduleDir  string // The directory that is the module root of this dir.\n\tmoduleName string // The module name that contains this dir.\n\n\t// Set when status >= nameLoaded.\n\n\tpackageName string // the package name, as declared in the source.\n\n\t// Set when status >= exportsLoaded.\n\t// TODO(rfindley): it's hard to see this, but exports depend implicitly on\n\t// the default build context GOOS and GOARCH.\n\t//\n\t// We can make this explicit, and key exports by GOOS, GOARCH.\n\texports []stdlib.Symbol\n}\n\n// reachedStatus returns true when info has a status at least target and any error associated with\n// an attempt to reach target.\nfunc (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) (bool, error) {\n\tif info.err == nil {\n\t\treturn info.status >= target, nil\n\t}\n\tif info.status == target {\n\t\treturn true, info.err\n\t}\n\treturn true, nil\n}\n\n// DirInfoCache is a concurrency-safe map for storing information about\n// directories that may contain packages.\n//\n// The information in this cache is built incrementally. Entries are initialized in scan.\n// No new keys should be added in any other functions, as all directories containing\n// packages are identified in scan.\n//\n// Other functions, including loadExports and findPackage, may update entries in this cache\n// as they discover new things about the directory.\n//\n// The information in the cache is not expected to change for the cache's\n// lifetime, so there is no protection against competing writes. Users should\n// take care not to hold the cache across changes to the underlying files.\ntype DirInfoCache struct {\n\tmu sync.Mutex\n\t// dirs stores information about packages in directories, keyed by absolute path.\n\tdirs      map[string]*directoryPackageInfo\n\tlisteners map[*int]cacheListener\n}\n\nfunc NewDirInfoCache() *DirInfoCache {\n\treturn &DirInfoCache{\n\t\tdirs:      make(map[string]*directoryPackageInfo),\n\t\tlisteners: make(map[*int]cacheListener),\n\t}\n}\n\ntype cacheListener func(directoryPackageInfo)\n\n// ScanAndListen calls listener on all the items in the cache, and on anything\n// newly added. The returned stop function waits for all in-flight callbacks to\n// finish and blocks new ones.\nfunc (d *DirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() {\n\tctx, cancel := context.WithCancel(ctx)\n\n\t// Flushing out all the callbacks is tricky without knowing how many there\n\t// are going to be. Setting an arbitrary limit makes it much easier.\n\tconst maxInFlight = 10\n\tsema := make(chan struct{}, maxInFlight)\n\tfor range maxInFlight {\n\t\tsema <- struct{}{}\n\t}\n\n\tcookie := new(int) // A unique ID we can use for the listener.\n\n\t// We can't hold mu while calling the listener.\n\td.mu.Lock()\n\tvar keys []string\n\tfor key := range d.dirs {\n\t\tkeys = append(keys, key)\n\t}\n\td.listeners[cookie] = func(info directoryPackageInfo) {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tcase <-sema:\n\t\t}\n\t\tlistener(info)\n\t\tsema <- struct{}{}\n\t}\n\td.mu.Unlock()\n\n\tstop := func() {\n\t\tcancel()\n\t\td.mu.Lock()\n\t\tdelete(d.listeners, cookie)\n\t\td.mu.Unlock()\n\t\tfor range maxInFlight {\n\t\t\t<-sema\n\t\t}\n\t}\n\n\t// Process the pre-existing keys.\n\tfor _, k := range keys {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn stop\n\t\tdefault:\n\t\t}\n\t\tif v, ok := d.Load(k); ok {\n\t\t\tlistener(v)\n\t\t}\n\t}\n\n\treturn stop\n}\n\n// Store stores the package info for dir.\nfunc (d *DirInfoCache) Store(dir string, info directoryPackageInfo) {\n\td.mu.Lock()\n\t// TODO(rfindley, golang/go#59216): should we overwrite an existing entry?\n\t// That seems incorrect as the cache should be idempotent.\n\t_, old := d.dirs[dir]\n\td.dirs[dir] = &info\n\tvar listeners []cacheListener\n\tfor _, l := range d.listeners {\n\t\tlisteners = append(listeners, l)\n\t}\n\td.mu.Unlock()\n\n\tif !old {\n\t\tfor _, l := range listeners {\n\t\t\tl(info)\n\t\t}\n\t}\n}\n\n// Load returns a copy of the directoryPackageInfo for absolute directory dir.\nfunc (d *DirInfoCache) Load(dir string) (directoryPackageInfo, bool) {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\tinfo, ok := d.dirs[dir]\n\tif !ok {\n\t\treturn directoryPackageInfo{}, false\n\t}\n\treturn *info, true\n}\n\n// Keys returns the keys currently present in d.\nfunc (d *DirInfoCache) Keys() (keys []string) {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\tfor key := range d.dirs {\n\t\tkeys = append(keys, key)\n\t}\n\treturn keys\n}\n\nfunc (d *DirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) {\n\tif loaded, err := info.reachedStatus(nameLoaded); loaded {\n\t\treturn info.packageName, err\n\t}\n\tif scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {\n\t\treturn \"\", fmt.Errorf(\"cannot read package name, scan error: %v\", err)\n\t}\n\tinfo.packageName, info.err = packageDirToName(info.dir)\n\tinfo.status = nameLoaded\n\td.Store(info.dir, info)\n\treturn info.packageName, info.err\n}\n\nfunc (d *DirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []stdlib.Symbol, error) {\n\tif reached, _ := info.reachedStatus(exportsLoaded); reached {\n\t\treturn info.packageName, info.exports, info.err\n\t}\n\tif reached, err := info.reachedStatus(nameLoaded); reached && err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tinfo.packageName, info.exports, info.err = loadExportsFromFiles(ctx, env, info.dir, false)\n\tif info.err == context.Canceled || info.err == context.DeadlineExceeded {\n\t\treturn info.packageName, info.exports, info.err\n\t}\n\t// The cache structure wants things to proceed linearly. We can skip a\n\t// step here, but only if we succeed.\n\tif info.status == nameLoaded || info.err == nil {\n\t\tinfo.status = exportsLoaded\n\t} else {\n\t\tinfo.status = nameLoaded\n\t}\n\td.Store(info.dir, info)\n\treturn info.packageName, info.exports, info.err\n}\n\n// ScanModuleCache walks the given directory, which must be a GOMODCACHE value,\n// for directory package information, storing the results in cache.\nfunc ScanModuleCache(dir string, cache *DirInfoCache, logf func(string, ...any)) {\n\t// Note(rfindley): it's hard to see, but this function attempts to implement\n\t// just the side effects on cache of calling PrimeCache with a ProcessEnv\n\t// that has the given dir as its GOMODCACHE.\n\t//\n\t// Teasing out the control flow, we see that we can avoid any handling of\n\t// vendor/ and can infer module info entirely from the path, simplifying the\n\t// logic here.\n\n\troot := gopathwalk.Root{\n\t\tPath: filepath.Clean(dir),\n\t\tType: gopathwalk.RootModuleCache,\n\t}\n\n\tdirectoryInfo := func(root gopathwalk.Root, dir string) directoryPackageInfo {\n\t\t// This is a copy of ModuleResolver.scanDirForPackage, trimmed down to\n\t\t// logic that applies to a module cache directory.\n\n\t\tsubdir := \"\"\n\t\tif dir != root.Path {\n\t\t\tsubdir = dir[len(root.Path)+len(\"/\"):]\n\t\t}\n\n\t\tmatches := modCacheRegexp.FindStringSubmatch(subdir)\n\t\tif len(matches) == 0 {\n\t\t\treturn directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"invalid module cache path: %v\", subdir),\n\t\t\t}\n\t\t}\n\t\tmodPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))\n\t\tif err != nil {\n\t\t\tif logf != nil {\n\t\t\t\tlogf(\"decoding module cache path %q: %v\", subdir, err)\n\t\t\t}\n\t\t\treturn directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"decoding module cache path %q: %v\", subdir, err),\n\t\t\t}\n\t\t}\n\t\timportPath := path.Join(modPath, filepath.ToSlash(matches[3]))\n\t\tindex := strings.Index(dir, matches[1]+\"@\"+matches[2])\n\t\tmodDir := filepath.Join(dir[:index], matches[1]+\"@\"+matches[2])\n\t\tmodName := readModName(filepath.Join(modDir, \"go.mod\"))\n\t\treturn directoryPackageInfo{\n\t\t\tstatus:                 directoryScanned,\n\t\t\tdir:                    dir,\n\t\t\trootType:               root.Type,\n\t\t\tnonCanonicalImportPath: importPath,\n\t\t\tmoduleDir:              modDir,\n\t\t\tmoduleName:             modName,\n\t\t}\n\t}\n\n\tadd := func(root gopathwalk.Root, dir string) {\n\t\tinfo := directoryInfo(root, dir)\n\t\tcache.Store(info.dir, info)\n\t}\n\n\tskip := func(_ gopathwalk.Root, dir string) bool {\n\t\t// Skip directories that have already been scanned.\n\t\t//\n\t\t// Note that gopathwalk only adds \"package\" directories, which must contain\n\t\t// a .go file, and all such package directories in the module cache are\n\t\t// immutable. So if we can load a dir, it can be skipped.\n\t\tinfo, ok := cache.Load(dir)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tpackageScanned, _ := info.reachedStatus(directoryScanned)\n\t\treturn packageScanned\n\t}\n\n\tgopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: logf, ModulesEnabled: true})\n}\n"
  },
  {
    "path": "internal/imports/mod_cache_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestDirectoryPackageInfoReachedStatus(t *testing.T) {\n\ttests := []struct {\n\t\tinfo       directoryPackageInfo\n\t\ttarget     directoryPackageStatus\n\t\twantStatus bool\n\t\twantError  bool\n\t}{\n\t\t{\n\t\t\tinfo: directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    nil,\n\t\t\t},\n\t\t\ttarget:     directoryScanned,\n\t\t\twantStatus: true,\n\t\t},\n\t\t{\n\t\t\tinfo: directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"error getting to directory scanned\"),\n\t\t\t},\n\t\t\ttarget:     directoryScanned,\n\t\t\twantStatus: true,\n\t\t\twantError:  true,\n\t\t},\n\t\t{\n\t\t\tinfo:       directoryPackageInfo{},\n\t\t\ttarget:     directoryScanned,\n\t\t\twantStatus: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tgotStatus, gotErr := tt.info.reachedStatus(tt.target)\n\t\tif gotErr != nil {\n\t\t\tif !tt.wantError {\n\t\t\t\tt.Errorf(\"unexpected error: %s\", gotErr)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif tt.wantStatus != gotStatus {\n\t\t\tt.Errorf(\"reached status expected: %v, got: %v\", tt.wantStatus, gotStatus)\n\t\t}\n\t}\n}\n\nfunc TestModCacheInfo(t *testing.T) {\n\tm := NewDirInfoCache()\n\n\tdirInfo := []struct {\n\t\tdir  string\n\t\tinfo directoryPackageInfo\n\t}{\n\t\t{\n\t\t\tdir: \"mypackage\",\n\t\t\tinfo: directoryPackageInfo{\n\t\t\t\tstatus:                 directoryScanned,\n\t\t\t\tdir:                    \"mypackage\",\n\t\t\t\tnonCanonicalImportPath: \"example.com/mypackage\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdir: \"bad package\",\n\t\t\tinfo: directoryPackageInfo{\n\t\t\t\tstatus: directoryScanned,\n\t\t\t\terr:    fmt.Errorf(\"bad package\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdir: \"mypackage/other\",\n\t\t\tinfo: directoryPackageInfo{\n\t\t\t\tdir:                    \"mypackage/other\",\n\t\t\t\tnonCanonicalImportPath: \"example.com/mypackage/other\",\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, d := range dirInfo {\n\t\tm.Store(d.dir, d.info)\n\t}\n\n\tfor _, d := range dirInfo {\n\t\tval, ok := m.Load(d.dir)\n\t\tif !ok {\n\t\t\tt.Errorf(\"directory not loaded: %s\", d.dir)\n\t\t}\n\n\t\tif !reflect.DeepEqual(d.info, val) {\n\t\t\tt.Errorf(\"expected: %v, got: %v\", d.info, val)\n\t\t}\n\t}\n\n\tvar wantKeys []string\n\tfor _, d := range dirInfo {\n\t\twantKeys = append(wantKeys, d.dir)\n\t}\n\tsort.Strings(wantKeys)\n\n\tgotKeys := m.Keys()\n\tsort.Strings(gotKeys)\n\n\tif len(gotKeys) != len(wantKeys) {\n\t\tt.Errorf(\"different length of keys. expected: %d, got: %d\", len(wantKeys), len(gotKeys))\n\t}\n\n\tfor i, want := range wantKeys {\n\t\tif want != gotKeys[i] {\n\t\t\tt.Errorf(\"%d: expected %s, got %s\", i, want, gotKeys[i])\n\t\t}\n\t}\n}\n\nfunc BenchmarkScanModuleCache(b *testing.B) {\n\toutput, err := exec.Command(\"go\", \"env\", \"GOMODCACHE\").Output()\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tgomodcache := strings.TrimSpace(string(output))\n\tcache := NewDirInfoCache()\n\tstart := time.Now()\n\tScanModuleCache(gomodcache, cache, nil)\n\tb.Logf(\"initial scan took %v\", time.Since(start))\n\n\tfor b.Loop() {\n\t\tScanModuleCache(gomodcache, cache, nil)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/mod_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"archive/zip\"\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/mod/module\"\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n\t\"golang.org/x/tools/internal/proxydir\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n\t\"maps\"\n\t\"slices\"\n)\n\n// Tests that we can find packages in the stdlib.\nfunc TestScanStdlib(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertScanFinds(\"fmt\", \"fmt\")\n}\n\n// Tests that we handle a nested module. This is different from other tests\n// where the module is in scope -- here we have to figure out the import path\n// without any help from go list.\nfunc TestScanOutOfScopeNestedModule(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\n-- x.go --\npackage x\n\n-- v2/go.mod --\nmodule x\n\n-- v2/x.go --\npackage x`, \"\")\n\tdefer mt.cleanup()\n\n\tpkg := mt.assertScanFinds(\"x/v2\", \"x\")\n\tif pkg != nil && !strings.HasSuffix(filepath.ToSlash(pkg.dir), \"main/v2\") {\n\t\tt.Errorf(\"x/v2 was found in %v, wanted .../main/v2\", pkg.dir)\n\t}\n\t// We can't load the package name from the import path, but that should\n\t// be okay -- if we end up adding this result, we'll add it with a name\n\t// if necessary.\n}\n\n// Tests that we don't find a nested module contained in a local replace target.\n// The code for this case is too annoying to write, so it's just ignored.\nfunc TestScanNestedModuleInLocalReplace(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire y v0.0.0\nreplace y => ./y\n\n-- x.go --\npackage x\n\n-- y/go.mod --\nmodule y\n\n-- y/y.go --\npackage y\n\n-- y/z/go.mod --\nmodule y/z\n\n-- y/z/z.go --\npackage z\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertFound(\"y\", \"y\")\n\n\tscan, err := scanToSlice(mt.env.resolver, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, pkg := range scan {\n\t\tif strings.HasSuffix(filepath.ToSlash(pkg.dir), \"main/y/z\") {\n\t\t\tt.Errorf(\"scan found a package %v in dir main/y/z, wanted none\", pkg.importPathShort)\n\t\t}\n\t}\n}\n\n// Tests that path encoding is handled correctly. Adapted from mod_case.txt.\nfunc TestModCase(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire rsc.io/QUOTE v1.5.2\n\n-- x.go --\npackage x\n\nimport _ \"rsc.io/QUOTE/QUOTE\"\n`, \"\")\n\tdefer mt.cleanup()\n\tmt.assertFound(\"rsc.io/QUOTE/QUOTE\", \"QUOTE\")\n}\n\n// Not obviously relevant to goimports. Adapted from mod_domain_root.txt anyway.\nfunc TestModDomainRoot(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire example.com v1.0.0\n\n-- x.go --\npackage x\nimport _ \"example.com\"\n`, \"\")\n\tdefer mt.cleanup()\n\tmt.assertFound(\"example.com\", \"x\")\n}\n\n// Tests that scanning the module cache > 1 time is able to find the same module.\nfunc TestModMultipleScans(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire example.com v1.0.0\n\n-- x.go --\npackage x\nimport _ \"example.com\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertScanFinds(\"example.com\", \"x\")\n\tmt.assertScanFinds(\"example.com\", \"x\")\n}\n\n// Tests that scanning the module cache > 1 time is able to find the same module\n// in the module cache.\nfunc TestModMultipleScansWithSubdirs(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire rsc.io/quote v1.5.2\n\n-- x.go --\npackage x\nimport _ \"rsc.io/quote\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n\tmt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n}\n\n// Tests that scanning the module cache > 1 after changing a package in module cache to make it unimportable\n// is able to find the same module.\nfunc TestModCacheEditModFile(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire rsc.io/quote v1.5.2\n-- x.go --\npackage x\nimport _ \"rsc.io/quote\"\n`, \"\")\n\tdefer mt.cleanup()\n\tfound := mt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n\tif found == nil {\n\t\tt.Fatal(\"rsc.io/quote not found in initial scan.\")\n\t}\n\n\t// Update the go.mod file of example.com so that it changes its module path (not allowed).\n\tif err := os.Chmod(filepath.Join(found.dir, \"go.mod\"), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(found.dir, \"go.mod\"), []byte(\"module bad.com\\n\"), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Test that with its cache of module packages it still finds the package.\n\tmt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n\n\t// Rewrite the main package so that rsc.io/quote is not in scope.\n\tif err := os.WriteFile(filepath.Join(mt.env.WorkingDir, \"go.mod\"), []byte(\"module x\\n\"), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(mt.env.WorkingDir, \"x.go\"), []byte(\"package x\\n\"), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Uninitialize the go.mod dependent cached information and make sure it still finds the package.\n\tmt.env.ClearModuleInfo()\n\tmt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n}\n\n// Tests that -mod=vendor works. Adapted from mod_vendor_build.txt.\nfunc TestModVendorBuild(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule m\ngo 1.12\nrequire rsc.io/sampler v1.3.1\n-- x.go --\npackage x\nimport _ \"rsc.io/sampler\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\t// Sanity-check the setup.\n\tmt.assertModuleFoundInDir(\"rsc.io/sampler\", \"sampler\", `pkg.*mod.*/sampler@.*$`)\n\n\t// Populate vendor/ and clear out the mod cache so we can't cheat.\n\tif _, err := mt.env.invokeGo(context.Background(), \"mod\", \"vendor\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := mt.env.invokeGo(context.Background(), \"clean\", \"-modcache\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Clear out the resolver's cache, since we've changed the environment.\n\tmt.env.Env[\"GOFLAGS\"] = \"-mod=vendor\"\n\tmt.env.ClearModuleInfo()\n\tmt.env.UpdateResolver(mt.env.resolver.ClearForNewScan())\n\tmt.assertModuleFoundInDir(\"rsc.io/sampler\", \"sampler\", `/vendor/`)\n}\n\n// Tests that -mod=vendor is auto-enabled only for go1.14 and higher.\n// Vaguely inspired by mod_vendor_auto.txt.\nfunc TestModVendorAuto(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule m\ngo 1.14\nrequire rsc.io/sampler v1.3.1\n-- x.go --\npackage x\nimport _ \"rsc.io/sampler\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\t// Populate vendor/.\n\tif _, err := mt.env.invokeGo(context.Background(), \"mod\", \"vendor\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twantDir := `/vendor/`\n\n\t// Clear out the resolver's module info, since we've changed the environment.\n\t// (the presence of a /vendor directory affects `go list -m`).\n\tmt.env.ClearModuleInfo()\n\tmt.assertModuleFoundInDir(\"rsc.io/sampler\", \"sampler\", wantDir)\n}\n\n// Tests that a module replace works. Adapted from mod_list.txt. We start with\n// go.mod2; the first part of the test is irrelevant.\nfunc TestModList(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\nrequire rsc.io/quote v1.5.1\nreplace rsc.io/sampler v1.3.0 => rsc.io/sampler v1.3.1\n\n-- x.go --\npackage x\nimport _ \"rsc.io/quote\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"rsc.io/sampler\", \"sampler\", `pkg.mod.*/sampler@v1.3.1$`)\n}\n\n// Tests that a local replace works. Adapted from mod_local_replace.txt.\nfunc TestModLocalReplace(t *testing.T) {\n\tmt := setup(t, nil, `\n-- x/y/go.mod --\nmodule x/y\nrequire zz v1.0.0\nreplace zz v1.0.0 => ../z\n\n-- x/y/y.go --\npackage y\nimport _ \"zz\"\n\n-- x/z/go.mod --\nmodule x/z\n\n-- x/z/z.go --\npackage z\n`, \"x/y\")\n\tdefer mt.cleanup()\n\n\tmt.assertFound(\"zz\", \"z\")\n}\n\n// Tests that the package at the root of the main module can be found.\n// Adapted from the first part of mod_multirepo.txt.\nfunc TestModMultirepo1(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule rsc.io/quote\n\n-- x.go --\npackage quote\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"rsc.io/quote\", \"quote\", `/main`)\n}\n\n// Tests that a simple module dependency is found. Adapted from the third part\n// of mod_multirepo.txt (We skip the case where it doesn't have a go.mod\n// entry -- we just don't work in that case.)\nfunc TestModMultirepo3(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule rsc.io/quote\n\nrequire rsc.io/quote/v2 v2.0.1\n-- x.go --\npackage quote\n\nimport _ \"rsc.io/quote/v2\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"rsc.io/quote\", \"quote\", `/main`)\n\tmt.assertModuleFoundInDir(\"rsc.io/quote/v2\", \"quote\", `pkg.mod.*/v2@v2.0.1$`)\n}\n\n// Tests that a nested module is found in the module cache, even though\n// it's checked out. Adapted from the fourth part of mod_multirepo.txt.\nfunc TestModMultirepo4(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule rsc.io/quote\nrequire rsc.io/quote/v2 v2.0.1\n\n-- x.go --\npackage quote\nimport _ \"rsc.io/quote/v2\"\n\n-- v2/go.mod --\npackage rsc.io/quote/v2\n\n-- v2/x.go --\npackage quote\nimport _ \"rsc.io/quote/v2\"\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"rsc.io/quote\", \"quote\", `/main`)\n\tmt.assertModuleFoundInDir(\"rsc.io/quote/v2\", \"quote\", `pkg.mod.*/v2@v2.0.1$`)\n}\n\n// Tests a simple module dependency. Adapted from the first part of mod_replace.txt.\nfunc TestModReplace1(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule quoter\n\nrequire rsc.io/quote/v3 v3.0.0\n\n-- main.go --\n\npackage main\n`, \"\")\n\tdefer mt.cleanup()\n\tmt.assertFound(\"rsc.io/quote/v3\", \"quote\")\n}\n\n// Tests a local replace. Adapted from the second part of mod_replace.txt.\nfunc TestModReplace2(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule quoter\n\nrequire rsc.io/quote/v3 v3.0.0\nreplace rsc.io/quote/v3 => ./local/rsc.io/quote/v3\n-- main.go --\npackage main\n\n-- local/rsc.io/quote/v3/go.mod --\nmodule rsc.io/quote/v3\n\nrequire rsc.io/sampler v1.3.0\n\n-- local/rsc.io/quote/v3/quote.go --\npackage quote\n\nimport \"rsc.io/sampler\"\n`, \"\")\n\tdefer mt.cleanup()\n\tmt.assertModuleFoundInDir(\"rsc.io/quote/v3\", \"quote\", `/local/rsc.io/quote/v3`)\n}\n\n// Tests that a module can be replaced by a different module path. Adapted\n// from the third part of mod_replace.txt.\nfunc TestModReplace3(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule quoter\n\nrequire not-rsc.io/quote/v3 v3.1.0\nreplace not-rsc.io/quote/v3 v3.1.0 => ./local/rsc.io/quote/v3\n\n-- usenewmodule/main.go --\npackage main\n\n-- local/rsc.io/quote/v3/go.mod --\nmodule rsc.io/quote/v3\n\nrequire rsc.io/sampler v1.3.0\n\n-- local/rsc.io/quote/v3/quote.go --\npackage quote\n\n-- local/not-rsc.io/quote/v3/go.mod --\nmodule not-rsc.io/quote/v3\n\n-- local/not-rsc.io/quote/v3/quote.go --\npackage quote\n`, \"\")\n\tdefer mt.cleanup()\n\tmt.assertModuleFoundInDir(\"not-rsc.io/quote/v3\", \"quote\", \"local/rsc.io/quote/v3\")\n}\n\n// Tests more local replaces, notably the case where an outer module provides\n// a package that could also be provided by an inner module. Adapted from\n// mod_replace_import.txt, with example.com/v changed to /vv because Go 1.11\n// thinks /v is an invalid major version.\nfunc TestModReplaceImport(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule example.com/m\n\nreplace (\n\texample.com/a => ./a\n\texample.com/a/b => ./b\n)\n\nreplace (\n\texample.com/x => ./x\n\texample.com/x/v3 => ./v3\n)\n\nreplace (\n\texample.com/y/z/w => ./w\n\texample.com/y => ./y\n)\n\nreplace (\n\texample.com/vv v1.11.0 => ./v11\n\texample.com/vv v1.12.0 => ./v12\n\texample.com/vv => ./vv\n)\n\nrequire (\n\texample.com/a/b v0.0.0\n\texample.com/x/v3 v3.0.0\n\texample.com/y v0.0.0\n\texample.com/y/z/w v0.0.0\n\texample.com/vv v1.12.0\n)\n-- m.go --\npackage main\nimport (\n\t_ \"example.com/a/b\"\n\t_ \"example.com/x/v3\"\n\t_ \"example.com/y/z/w\"\n\t_ \"example.com/vv\"\n)\nfunc main() {}\n\n-- a/go.mod --\nmodule a.localhost\n-- a/a.go --\npackage a\n-- a/b/b.go--\npackage b\n\n-- b/go.mod --\nmodule a.localhost/b\n-- b/b.go --\npackage b\n\n-- x/go.mod --\nmodule x.localhost\n-- x/x.go --\npackage x\n-- x/v3.go --\npackage v3\nimport _ \"x.localhost/v3\"\n\n-- v3/go.mod --\nmodule x.localhost/v3\n-- v3/x.go --\npackage x\n\n-- w/go.mod --\nmodule w.localhost\n-- w/skip/skip.go --\n// Package skip is nested below nonexistent package w.\npackage skip\n\n-- y/go.mod --\nmodule y.localhost\n-- y/z/w/w.go --\npackage w\n\n-- v12/go.mod --\nmodule v.localhost\n-- v12/v.go --\npackage v\n\n-- v11/go.mod --\nmodule v.localhost\n-- v11/v.go --\npackage v\n\n-- vv/go.mod --\nmodule v.localhost\n-- vv/v.go --\npackage v\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"example.com/a/b\", \"b\", `main/b$`)\n\tmt.assertModuleFoundInDir(\"example.com/x/v3\", \"x\", `main/v3$`)\n\tmt.assertModuleFoundInDir(\"example.com/y/z/w\", \"w\", `main/y/z/w$`)\n\tmt.assertModuleFoundInDir(\"example.com/vv\", \"v\", `main/v12$`)\n}\n\n// Tests that go.work files are respected.\nfunc TestModWorkspace(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.work --\ngo 1.18\n\nuse (\n\t./a\n\t./b\n)\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.18\n-- a/a.go --\npackage a\n-- b/go.mod --\nmodule example.com/b\n\ngo 1.18\n-- b/b.go --\npackage b\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertModuleFoundInDir(\"example.com/a\", \"a\", `main/a$`)\n\tmt.assertModuleFoundInDir(\"example.com/b\", \"b\", `main/b$`)\n\tmt.assertScanFinds(\"example.com/a\", \"a\")\n\tmt.assertScanFinds(\"example.com/b\", \"b\")\n}\n\n// Tests replaces in workspaces. Uses the directory layout in the cmd/go\n// work_replace test. It tests both that replaces in go.work files are\n// respected and that a wildcard replace in go.work overrides a versioned replace\n// in go.mod.\nfunc TestModWorkspaceReplace(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.work --\nuse m\n\nreplace example.com/dep => ./dep\nreplace example.com/other => ./other2\n\n-- m/go.mod --\nmodule example.com/m\n\nrequire example.com/dep v1.0.0\nrequire example.com/other v1.0.0\n\nreplace example.com/other v1.0.0 => ./other\n-- m/m.go --\npackage m\n\nimport \"example.com/dep\"\nimport \"example.com/other\"\n\nfunc F() {\n\tdep.G()\n\tother.H()\n}\n-- dep/go.mod --\nmodule example.com/dep\n-- dep/dep.go --\npackage dep\n\nfunc G() {\n}\n-- other/go.mod --\nmodule example.com/other\n-- other/dep.go --\npackage other\n\nfunc G() {\n}\n-- other2/go.mod --\nmodule example.com/other\n-- other2/dep.go --\npackage other2\n\nfunc G() {\n}\n`, \"\")\n\tdefer mt.cleanup()\n\n\tmt.assertScanFinds(\"example.com/m\", \"m\")\n\tmt.assertScanFinds(\"example.com/dep\", \"dep\")\n\tmt.assertModuleFoundInDir(\"example.com/other\", \"other2\", \"main/other2$\")\n\tmt.assertScanFinds(\"example.com/other\", \"other2\")\n}\n\n// Tests a case where conflicting replaces are overridden by a replace\n// in the go.work file.\nfunc TestModWorkspaceReplaceOverride(t *testing.T) {\n\tmt := setup(t, nil, `-- go.work --\nuse m\nuse n\nreplace example.com/dep => ./dep3\n-- m/go.mod --\nmodule example.com/m\n\nrequire example.com/dep v1.0.0\nreplace example.com/dep => ./dep1\n-- m/m.go --\npackage m\n\nimport \"example.com/dep\"\n\nfunc F() {\n\tdep.G()\n}\n-- n/go.mod --\nmodule example.com/n\n\nrequire example.com/dep v1.0.0\nreplace example.com/dep => ./dep2\n-- n/n.go --\npackage n\n\nimport \"example.com/dep\"\n\nfunc F() {\n\tdep.G()\n}\n-- dep1/go.mod --\nmodule example.com/dep\n-- dep1/dep.go --\npackage dep\n\nfunc G() {\n}\n-- dep2/go.mod --\nmodule example.com/dep\n-- dep2/dep.go --\npackage dep\n\nfunc G() {\n}\n-- dep3/go.mod --\nmodule example.com/dep\n-- dep3/dep.go --\npackage dep\n\nfunc G() {\n}\n`, \"\")\n\n\tmt.assertScanFinds(\"example.com/m\", \"m\")\n\tmt.assertScanFinds(\"example.com/n\", \"n\")\n\tmt.assertScanFinds(\"example.com/dep\", \"dep\")\n\tmt.assertModuleFoundInDir(\"example.com/dep\", \"dep\", \"main/dep3$\")\n}\n\n// Tests that the correct versions of modules are found in\n// workspaces with module pruning. This is based on the\n// cmd/go mod_prune_all script test.\nfunc TestModWorkspacePrune(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.work --\ngo 1.18\n\nuse (\n\t./a\n\t./p\n)\n\nreplace example.com/b v1.0.0 => ./b\nreplace example.com/q v1.0.0 => ./q1_0_0\nreplace example.com/q v1.0.5 => ./q1_0_5\nreplace example.com/q v1.1.0 => ./q1_1_0\nreplace example.com/r v1.0.0 => ./r\nreplace example.com/w v1.0.0 => ./w\nreplace example.com/x v1.0.0 => ./x\nreplace example.com/y v1.0.0 => ./y\nreplace example.com/z v1.0.0 => ./z1_0_0\nreplace example.com/z v1.1.0 => ./z1_1_0\n\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.18\n\nrequire example.com/b v1.0.0\nrequire example.com/z v1.0.0\n-- a/foo.go --\npackage main\n\nimport \"example.com/b\"\n\nfunc main() {\n\tb.B()\n}\n-- b/go.mod --\nmodule example.com/b\n\ngo 1.18\n\nrequire example.com/q v1.1.0\n-- b/b.go --\npackage b\n\nfunc B() {\n}\n-- p/go.mod --\nmodule example.com/p\n\ngo 1.18\n\nrequire example.com/q v1.0.0\n\nreplace example.com/q v1.0.0 => ../q1_0_0\nreplace example.com/q v1.1.0 => ../q1_1_0\n-- p/main.go --\npackage main\n\nimport \"example.com/q\"\n\nfunc main() {\n\tq.PrintVersion()\n}\n-- q1_0_0/go.mod --\nmodule example.com/q\n\ngo 1.18\n-- q1_0_0/q.go --\npackage q\n\nimport \"fmt\"\n\nfunc PrintVersion() {\n\tfmt.Println(\"version 1.0.0\")\n}\n-- q1_0_5/go.mod --\nmodule example.com/q\n\ngo 1.18\n\nrequire example.com/r v1.0.0\n-- q1_0_5/q.go --\npackage q\n\nimport _ \"example.com/r\"\n-- q1_1_0/go.mod --\nmodule example.com/q\n\nrequire example.com/w v1.0.0\nrequire example.com/z v1.1.0\n\ngo 1.18\n-- q1_1_0/q.go --\npackage q\n\nimport _ \"example.com/w\"\nimport _ \"example.com/z\"\n\nimport \"fmt\"\n\nfunc PrintVersion() {\n\tfmt.Println(\"version 1.1.0\")\n}\n-- r/go.mod --\nmodule example.com/r\n\ngo 1.18\n\nrequire example.com/r v1.0.0\n-- r/r.go --\npackage r\n-- w/go.mod --\nmodule example.com/w\n\ngo 1.18\n\nrequire example.com/x v1.0.0\n-- w/w.go --\npackage w\n-- w/w_test.go --\npackage w\n\nimport _ \"example.com/x\"\n-- x/go.mod --\nmodule example.com/x\n\ngo 1.18\n-- x/x.go --\npackage x\n-- x/x_test.go --\npackage x\nimport _ \"example.com/y\"\n-- y/go.mod --\nmodule example.com/y\n\ngo 1.18\n-- y/y.go --\npackage y\n-- z1_0_0/go.mod --\nmodule example.com/z\n\ngo 1.18\n\nrequire example.com/q v1.0.5\n-- z1_0_0/z.go --\npackage z\n\nimport _ \"example.com/q\"\n-- z1_1_0/go.mod --\nmodule example.com/z\n\ngo 1.18\n-- z1_1_0/z.go --\npackage z\n`, \"\")\n\n\tmt.assertScanFinds(\"example.com/w\", \"w\")\n\tmt.assertScanFinds(\"example.com/q\", \"q\")\n\tmt.assertScanFinds(\"example.com/x\", \"x\")\n\tmt.assertScanFinds(\"example.com/z\", \"z\")\n\tmt.assertModuleFoundInDir(\"example.com/w\", \"w\", \"main/w$\")\n\tmt.assertModuleFoundInDir(\"example.com/q\", \"q\", \"main/q1_1_0$\")\n\tmt.assertModuleFoundInDir(\"example.com/x\", \"x\", \"main/x$\")\n\tmt.assertModuleFoundInDir(\"example.com/z\", \"z\", \"main/z1_1_0$\")\n}\n\n// Tests that we handle GO111MODULE=on with no go.mod file. See #30855.\nfunc TestNoMainModule(t *testing.T) {\n\tmt := setup(t, map[string]string{\"GO111MODULE\": \"on\"}, `\n-- x.go --\npackage x\n`, \"\")\n\tdefer mt.cleanup()\n\tif _, err := mt.env.invokeGo(context.Background(), \"mod\", \"download\", \"rsc.io/quote@v1.5.1\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tmt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n}\n\n// assertFound asserts that the package at importPath is found to have pkgName,\n// and that scanning for pkgName finds it at importPath.\nfunc (t *modTest) assertFound(importPath, pkgName string) (string, *pkg) {\n\tt.Helper()\n\n\tnames, err := t.env.resolver.loadPackageNames([]string{importPath}, t.env.WorkingDir)\n\tif err != nil {\n\t\tt.Errorf(\"loading package name for %v: %v\", importPath, err)\n\t}\n\tif names[importPath] != pkgName {\n\t\tt.Errorf(\"package name for %v = %v, want %v\", importPath, names[importPath], pkgName)\n\t}\n\tpkg := t.assertScanFinds(importPath, pkgName)\n\n\t_, foundDir := t.env.resolver.(*ModuleResolver).findPackage(importPath)\n\treturn foundDir, pkg\n}\n\nfunc (t *modTest) assertScanFinds(importPath, pkgName string) *pkg {\n\tt.Helper()\n\tscan, err := scanToSlice(t.env.resolver, nil)\n\tif err != nil {\n\t\tt.Errorf(\"scan failed: %v\", err)\n\t}\n\tfor _, pkg := range scan {\n\t\tif pkg.importPathShort == importPath {\n\t\t\treturn pkg\n\t\t}\n\t}\n\tt.Errorf(\"scanning for %v did not find %v\", pkgName, importPath)\n\treturn nil\n}\n\nfunc scanToSlice(resolver Resolver, exclude []gopathwalk.RootType) ([]*pkg, error) {\n\tvar mu sync.Mutex\n\tvar result []*pkg\n\tfilter := &scanCallback{\n\t\trootFound: func(root gopathwalk.Root) bool {\n\t\t\treturn !slices.Contains(exclude, root.Type)\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\treturn true\n\t\t},\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tresult = append(result, pkg)\n\t\t\treturn false\n\t\t},\n\t}\n\terr := resolver.scan(context.Background(), filter)\n\treturn result, err\n}\n\n// assertModuleFoundInDir is the same as assertFound, but also checks that the\n// package was found in an active module whose Dir matches dirRE.\nfunc (t *modTest) assertModuleFoundInDir(importPath, pkgName, dirRE string) {\n\tt.Helper()\n\tdir, pkg := t.assertFound(importPath, pkgName)\n\tre, err := regexp.Compile(dirRE)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif dir == \"\" {\n\t\tt.Errorf(\"import path %v not found in active modules\", importPath)\n\t} else {\n\t\tif !re.MatchString(filepath.ToSlash(dir)) {\n\t\t\tt.Errorf(\"finding dir for %s: dir = %q did not match regex %q\", importPath, dir, dirRE)\n\t\t}\n\t}\n\tif pkg != nil {\n\t\tif !re.MatchString(filepath.ToSlash(pkg.dir)) {\n\t\t\tt.Errorf(\"scanning for %s: dir = %q did not match regex %q\", pkgName, pkg.dir, dirRE)\n\t\t}\n\t}\n}\n\nvar proxyOnce sync.Once\nvar proxyDir string\n\ntype modTest struct {\n\t*testing.T\n\tenv     *ProcessEnv\n\tgopath  string\n\tcleanup func()\n}\n\n// setup builds a test environment from a txtar and supporting modules\n// in testdata/mod, along the lines of TestScript in cmd/go.\n//\n// extraEnv is applied on top of the default test env.\nfunc setup(t *testing.T, extraEnv map[string]string, main, wd string) *modTest {\n\tt.Helper()\n\ttestenv.NeedsTool(t, \"go\")\n\n\tproxyOnce.Do(func() {\n\t\tvar err error\n\t\tproxyDir, err = os.MkdirTemp(\"\", \"proxy-\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := writeProxy(proxyDir, \"testdata/mod\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t})\n\n\tdir, err := os.MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tmainDir := filepath.Join(dir, \"main\")\n\tif err := writeModule(mainDir, main); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tenv := &ProcessEnv{\n\t\tEnv: map[string]string{\n\t\t\t\"GOPATH\":      filepath.Join(dir, \"gopath\"),\n\t\t\t\"GOMODCACHE\":  \"\",\n\t\t\t\"GO111MODULE\": \"auto\",\n\t\t\t\"GOSUMDB\":     \"off\",\n\t\t\t\"GOPROXY\":     proxydir.ToURL(proxyDir),\n\t\t},\n\t\tWorkingDir:  filepath.Join(mainDir, wd),\n\t\tGocmdRunner: &gocommand.Runner{},\n\t}\n\tmaps.Copy(env.Env, extraEnv)\n\tif *testDebug {\n\t\tenv.Logf = log.Printf\n\t}\n\t// go mod download gets mad if we don't have a go.mod, so make sure we do.\n\t_, err = os.Stat(filepath.Join(mainDir, \"go.mod\"))\n\tif err != nil && !os.IsNotExist(err) {\n\t\tt.Fatalf(\"checking if go.mod exists: %v\", err)\n\t}\n\tif err == nil {\n\t\tif _, err := env.invokeGo(context.Background(), \"mod\", \"download\", \"all\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\t// Ensure the resolver is set for tests that (unsafely) access env.resolver\n\t// directly.\n\t//\n\t// TODO(rfindley): fix this after addressing the TODO in the ProcessEnv\n\t// docstring.\n\tif _, err := env.GetResolver(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\treturn &modTest{\n\t\tT:       t,\n\t\tgopath:  env.Env[\"GOPATH\"],\n\t\tenv:     env,\n\t\tcleanup: func() { removeDir(dir) },\n\t}\n}\n\n// writeModule writes the module in the ar, a txtar, to dir.\nfunc writeModule(dir, ar string) error {\n\ta := txtar.Parse([]byte(ar))\n\n\tfor _, f := range a.Files {\n\t\tfpath := filepath.Join(dir, f.Name)\n\t\tif err := os.MkdirAll(filepath.Dir(fpath), 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif err := os.WriteFile(fpath, f.Data, 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// writeProxy writes all the txtar-formatted modules in arDir to a proxy\n// directory in dir.\nfunc writeProxy(dir, arDir string) error {\n\tfiles, err := os.ReadDir(arDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, fi := range files {\n\t\tif err := writeProxyModule(dir, filepath.Join(arDir, fi.Name())); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// writeProxyModule writes a txtar-formatted module at arPath to the module\n// proxy in base.\nfunc writeProxyModule(base, arPath string) error {\n\tarName := filepath.Base(arPath)\n\ti := strings.LastIndex(arName, \"_v\")\n\tver := strings.TrimSuffix(arName[i+1:], \".txt\")\n\tmodDir := strings.ReplaceAll(arName[:i], \"_\", \"/\")\n\tmodPath, err := module.UnescapePath(modDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdir := filepath.Join(base, modDir, \"@v\")\n\ta, err := txtar.ParseFile(arPath)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := os.MkdirAll(dir, 0755); err != nil {\n\t\treturn err\n\t}\n\n\tf, err := os.OpenFile(filepath.Join(dir, ver+\".zip\"), os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tz := zip.NewWriter(f)\n\tfor _, f := range a.Files {\n\t\tif f.Name[0] == '.' {\n\t\t\tif err := os.WriteFile(filepath.Join(dir, ver+f.Name), f.Data, 0644); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\tzf, err := z.Create(modPath + \"@\" + ver + \"/\" + f.Name)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif _, err := zf.Write(f.Data); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tif err := z.Close(); err != nil {\n\t\treturn err\n\t}\n\tif err := f.Close(); err != nil {\n\t\treturn err\n\t}\n\n\tlist, err := os.OpenFile(filepath.Join(dir, \"list\"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(list, \"%s\\n\", ver); err != nil {\n\t\treturn err\n\t}\n\tif err := list.Close(); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc removeDir(dir string) {\n\t_ = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tif info.IsDir() {\n\t\t\t_ = os.Chmod(path, 0777)\n\t\t}\n\t\treturn nil\n\t})\n\t_ = os.RemoveAll(dir) // ignore errors\n}\n\n// Tests that findModFile can find the mod files from a path in the module cache.\nfunc TestFindModFileModCache(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule x\n\nrequire rsc.io/quote v1.5.2\n-- x.go --\npackage x\nimport _ \"rsc.io/quote\"\n`, \"\")\n\tdefer mt.cleanup()\n\twant := filepath.Join(mt.gopath, \"pkg/mod\", \"rsc.io/quote@v1.5.2\")\n\n\tfound := mt.assertScanFinds(\"rsc.io/quote\", \"quote\")\n\tmodDir, _ := mt.env.resolver.(*ModuleResolver).modInfo(found.dir)\n\tif modDir != want {\n\t\tt.Errorf(\"expected: %s, got: %s\", want, modDir)\n\t}\n}\n\n// Tests that crud in the module cache is ignored.\nfunc TestInvalidModCache(t *testing.T) {\n\ttestenv.NeedsTool(t, \"go\")\n\n\tdir, err := os.MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer removeDir(dir)\n\n\t// This doesn't have module@version like it should.\n\tif err := os.MkdirAll(filepath.Join(dir, \"gopath/pkg/mod/sabotage\"), 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.WriteFile(filepath.Join(dir, \"gopath/pkg/mod/sabotage/x.go\"), []byte(\"package foo\\n\"), 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tenv := &ProcessEnv{\n\t\tEnv: map[string]string{\n\t\t\t\"GOPATH\":      filepath.Join(dir, \"gopath\"),\n\t\t\t\"GO111MODULE\": \"on\",\n\t\t\t\"GOSUMDB\":     \"off\",\n\t\t},\n\t\tGocmdRunner: &gocommand.Runner{},\n\t\tWorkingDir:  dir,\n\t}\n\tresolver, err := env.GetResolver()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tscanToSlice(resolver, nil)\n}\n\nfunc TestGetCandidatesRanking(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.mod --\nmodule example.com\n\nrequire rsc.io/quote v1.5.1\nrequire rsc.io/quote/v3 v3.0.0\n\n-- rpackage/x.go --\npackage rpackage\nimport (\n\t_ \"rsc.io/quote\"\n\t_ \"rsc.io/quote/v3\"\n)\n`, \"\")\n\tdefer mt.cleanup()\n\n\tif _, err := mt.env.invokeGo(context.Background(), \"mod\", \"download\", \"rsc.io/quote/v2@v2.0.1\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttype res struct {\n\t\trelevance  float64\n\t\tname, path string\n\t}\n\twant := []res{\n\t\t// Stdlib\n\t\t{7, \"bytes\", \"bytes\"},\n\t\t{7, \"http\", \"net/http\"},\n\t\t// Main module\n\t\t{6, \"rpackage\", \"example.com/rpackage\"},\n\t\t// Direct module deps with v2+ major version\n\t\t{5.003, \"quote\", \"rsc.io/quote/v3\"},\n\t\t// Direct module deps\n\t\t{5, \"quote\", \"rsc.io/quote\"},\n\t\t// Indirect deps\n\t\t{4, \"language\", \"golang.org/x/text/language\"},\n\t\t// Out of scope modules\n\t\t{3, \"quote\", \"rsc.io/quote/v2\"},\n\t}\n\tvar mu sync.Mutex\n\tvar got []res\n\tadd := func(c ImportFix) {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\tfor _, w := range want {\n\t\t\tif c.StmtInfo.ImportPath == w.path {\n\t\t\t\tgot = append(got, res{c.Relevance, c.IdentName, c.StmtInfo.ImportPath})\n\t\t\t}\n\t\t}\n\t}\n\tif err := GetAllCandidates(context.Background(), add, \"\", \"foo.go\", \"foo\", mt.env); err != nil {\n\t\tt.Fatalf(\"getAllCandidates() = %v\", err)\n\t}\n\tsort.Slice(got, func(i, j int) bool {\n\t\tri, rj := got[i], got[j]\n\t\tif ri.relevance != rj.relevance {\n\t\t\treturn ri.relevance > rj.relevance // Highest first.\n\t\t}\n\t\treturn ri.name < rj.name\n\t})\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"wanted candidates in order %v, got %v\", want, got)\n\t}\n}\n\nfunc BenchmarkModuleResolver_RescanModCache(b *testing.B) {\n\tenv := &ProcessEnv{\n\t\tGocmdRunner: &gocommand.Runner{},\n\t\t// Uncomment for verbose logging (too verbose to enable by default).\n\t\t// Logf:        b.Logf,\n\t}\n\texclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}\n\tresolver, err := env.GetResolver()\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tstart := time.Now()\n\tscanToSlice(resolver, exclude)\n\tb.Logf(\"warming the mod cache took %v\", time.Since(start))\n\n\tfor b.Loop() {\n\t\tscanToSlice(resolver, exclude)\n\t\tresolver = resolver.ClearForNewScan()\n\t}\n}\n\nfunc BenchmarkModuleResolver_InitialScan(b *testing.B) {\n\tfor b.Loop() {\n\t\tenv := &ProcessEnv{\n\t\t\tGocmdRunner: &gocommand.Runner{},\n\t\t}\n\t\texclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}\n\t\tresolver, err := env.GetResolver()\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t\tscanToSlice(resolver, exclude)\n\t}\n}\n\n// Tests that go.work files and vendor directory are respected.\nfunc TestModWorkspaceVendoring(t *testing.T) {\n\tmt := setup(t, nil, `\n-- go.work --\ngo 1.22\n\nuse (\n\t./a\n\t./b\n)\n-- a/go.mod --\nmodule example.com/a\n\ngo 1.22\n\nrequire rsc.io/sampler v1.3.1\n-- a/a.go --\npackage a\n\nimport _ \"rsc.io/sampler\"\n-- b/go.mod --\nmodule example.com/b\n\ngo 1.22\n-- b/b.go --\npackage b\n`, \"\")\n\tdefer mt.cleanup()\n\n\t// generate vendor directory\n\tif _, err := mt.env.invokeGo(context.Background(), \"work\", \"vendor\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// update module resolver\n\tmt.env.ClearModuleInfo()\n\tmt.env.UpdateResolver(mt.env.resolver.ClearForNewScan())\n\n\tmt.assertModuleFoundInDir(\"example.com/a\", \"a\", `main/a$`)\n\tmt.assertScanFinds(\"example.com/a\", \"a\")\n\tmt.assertModuleFoundInDir(\"example.com/b\", \"b\", `main/b$`)\n\tmt.assertScanFinds(\"example.com/b\", \"b\")\n\tmt.assertModuleFoundInDir(\"rsc.io/sampler\", \"sampler\", `/vendor/`)\n}\n"
  },
  {
    "path": "internal/imports/sortimports.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Hacked up copy of go/ast/import.go\n// Modified to use a single token.File in preference to a FileSet.\n\npackage imports\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"log\"\n\t\"reflect\"\n\t\"slices\"\n\t\"sort\"\n\t\"strconv\"\n)\n\n// sortImports sorts runs of consecutive import lines in import blocks in f.\n// It also removes duplicate imports when it is possible to do so without data loss.\n//\n// It may mutate the token.File and the ast.File.\nfunc sortImports(localPrefix string, tokFile *token.File, f *ast.File) {\n\tfor i, d := range f.Decls {\n\t\td, ok := d.(*ast.GenDecl)\n\t\tif !ok || d.Tok != token.IMPORT {\n\t\t\t// Not an import declaration, so we're done.\n\t\t\t// Imports are always first.\n\t\t\tbreak\n\t\t}\n\n\t\tif len(d.Specs) == 0 {\n\t\t\t// Empty import block, remove it.\n\t\t\tf.Decls = slices.Delete(f.Decls, i, i+1)\n\t\t}\n\n\t\tif !d.Lparen.IsValid() {\n\t\t\t// Not a block: sorted by default.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Identify and sort runs of specs on successive lines.\n\t\ti := 0\n\t\tspecs := d.Specs[:0]\n\t\tfor j, s := range d.Specs {\n\t\t\tif j > i && tokFile.Line(s.Pos()) > 1+tokFile.Line(d.Specs[j-1].End()) {\n\t\t\t\t// j begins a new run.  End this one.\n\t\t\t\tspecs = append(specs, sortSpecs(localPrefix, tokFile, f, d.Specs[i:j])...)\n\t\t\t\ti = j\n\t\t\t}\n\t\t}\n\t\tspecs = append(specs, sortSpecs(localPrefix, tokFile, f, d.Specs[i:])...)\n\t\td.Specs = specs\n\n\t\t// Deduping can leave a blank line before the rparen; clean that up.\n\t\t// Ignore line directives.\n\t\tif len(d.Specs) > 0 {\n\t\t\tlastSpec := d.Specs[len(d.Specs)-1]\n\t\t\tlastLine := tokFile.PositionFor(lastSpec.Pos(), false).Line\n\t\t\tif rParenLine := tokFile.PositionFor(d.Rparen, false).Line; rParenLine > lastLine+1 {\n\t\t\t\ttokFile.MergeLine(rParenLine - 1) // has side effects!\n\t\t\t}\n\t\t}\n\t}\n}\n\n// mergeImports merges all the import declarations into the first one.\n// Taken from golang.org/x/tools/go/ast/astutil.\n// This does not adjust line numbers properly\nfunc mergeImports(f *ast.File) {\n\tif len(f.Decls) <= 1 {\n\t\treturn\n\t}\n\n\t// Merge all the import declarations into the first one.\n\tvar first *ast.GenDecl\n\tfor i := 0; i < len(f.Decls); i++ {\n\t\tdecl := f.Decls[i]\n\t\tgen, ok := decl.(*ast.GenDecl)\n\t\tif !ok || gen.Tok != token.IMPORT || declImports(gen, \"C\") {\n\t\t\tcontinue\n\t\t}\n\t\tif first == nil {\n\t\t\tfirst = gen\n\t\t\tcontinue // Don't touch the first one.\n\t\t}\n\t\t// We now know there is more than one package in this import\n\t\t// declaration. Ensure that it ends up parenthesized.\n\t\tfirst.Lparen = first.Pos()\n\t\t// Move the imports of the other import declaration to the first one.\n\t\tfor _, spec := range gen.Specs {\n\t\t\tupdateBasicLitPos(spec.(*ast.ImportSpec).Path, first.Pos())\n\t\t\tfirst.Specs = append(first.Specs, spec)\n\t\t}\n\t\tf.Decls = slices.Delete(f.Decls, i, i+1)\n\t\ti--\n\t}\n}\n\n// declImports reports whether gen contains an import of path.\n// Taken from golang.org/x/tools/go/ast/astutil.\nfunc declImports(gen *ast.GenDecl, path string) bool {\n\tif gen.Tok != token.IMPORT {\n\t\treturn false\n\t}\n\tfor _, spec := range gen.Specs {\n\t\timpspec := spec.(*ast.ImportSpec)\n\t\tif importPath(impspec) == path {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc importPath(s ast.Spec) string {\n\tt, err := strconv.Unquote(s.(*ast.ImportSpec).Path.Value)\n\tif err == nil {\n\t\treturn t\n\t}\n\treturn \"\"\n}\n\nfunc importName(s ast.Spec) string {\n\tn := s.(*ast.ImportSpec).Name\n\tif n == nil {\n\t\treturn \"\"\n\t}\n\treturn n.Name\n}\n\nfunc importComment(s ast.Spec) string {\n\tc := s.(*ast.ImportSpec).Comment\n\tif c == nil {\n\t\treturn \"\"\n\t}\n\treturn c.Text()\n}\n\n// collapse indicates whether prev may be removed, leaving only next.\nfunc collapse(prev, next ast.Spec) bool {\n\tif importPath(next) != importPath(prev) || importName(next) != importName(prev) {\n\t\treturn false\n\t}\n\treturn prev.(*ast.ImportSpec).Comment == nil\n}\n\ntype posSpan struct {\n\tStart token.Pos\n\tEnd   token.Pos\n}\n\n// sortSpecs sorts the import specs within each import decl.\n// It may mutate the token.File.\nfunc sortSpecs(localPrefix string, tokFile *token.File, f *ast.File, specs []ast.Spec) []ast.Spec {\n\t// Can't short-circuit here even if specs are already sorted,\n\t// since they might yet need deduplication.\n\t// A lone import, however, may be safely ignored.\n\tif len(specs) <= 1 {\n\t\treturn specs\n\t}\n\n\t// Record positions for specs.\n\tpos := make([]posSpan, len(specs))\n\tfor i, s := range specs {\n\t\tpos[i] = posSpan{s.Pos(), s.End()}\n\t}\n\n\t// Identify comments in this range.\n\t// Any comment from pos[0].Start to the final line counts.\n\tlastLine := tokFile.Line(pos[len(pos)-1].End)\n\tcstart := len(f.Comments)\n\tcend := len(f.Comments)\n\tfor i, g := range f.Comments {\n\t\tif g.Pos() < pos[0].Start {\n\t\t\tcontinue\n\t\t}\n\t\tif i < cstart {\n\t\t\tcstart = i\n\t\t}\n\t\tif tokFile.Line(g.End()) > lastLine {\n\t\t\tcend = i\n\t\t\tbreak\n\t\t}\n\t}\n\tcomments := f.Comments[cstart:cend]\n\n\t// Assign each comment to the import spec preceding it.\n\timportComment := map[*ast.ImportSpec][]*ast.CommentGroup{}\n\tspecIndex := 0\n\tfor _, g := range comments {\n\t\tfor specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {\n\t\t\tspecIndex++\n\t\t}\n\t\ts := specs[specIndex].(*ast.ImportSpec)\n\t\timportComment[s] = append(importComment[s], g)\n\t}\n\n\t// Sort the import specs by import path.\n\t// Remove duplicates, when possible without data loss.\n\t// Reassign the import paths to have the same position sequence.\n\t// Reassign each comment to abut the end of its spec.\n\t// Sort the comments by new position.\n\tsort.Sort(byImportSpec{localPrefix, specs})\n\n\t// Dedup. Thanks to our sorting, we can just consider\n\t// adjacent pairs of imports.\n\tdeduped := specs[:0]\n\tfor i, s := range specs {\n\t\tif i == len(specs)-1 || !collapse(s, specs[i+1]) {\n\t\t\tdeduped = append(deduped, s)\n\t\t} else {\n\t\t\tp := s.Pos()\n\t\t\ttokFile.MergeLine(tokFile.Line(p)) // has side effects!\n\t\t}\n\t}\n\tspecs = deduped\n\n\t// Fix up comment positions\n\tfor i, s := range specs {\n\t\ts := s.(*ast.ImportSpec)\n\t\tif s.Name != nil {\n\t\t\ts.Name.NamePos = pos[i].Start\n\t\t}\n\t\tupdateBasicLitPos(s.Path, pos[i].Start)\n\t\ts.EndPos = pos[i].End\n\t\tnextSpecPos := pos[i].End\n\n\t\tfor _, g := range importComment[s] {\n\t\t\tfor _, c := range g.List {\n\t\t\t\tc.Slash = pos[i].End\n\t\t\t\tnextSpecPos = c.End()\n\t\t\t}\n\t\t}\n\t\tif i < len(specs)-1 {\n\t\t\tpos[i+1].Start = nextSpecPos\n\t\t\tpos[i+1].End = nextSpecPos\n\t\t}\n\t}\n\n\tsort.Sort(byCommentPos(comments))\n\n\t// Fixup comments can insert blank lines, because import specs are on different lines.\n\t// We remove those blank lines here by merging import spec to the first import spec line.\n\tfirstSpecLine := tokFile.Line(specs[0].Pos())\n\tfor _, s := range specs[1:] {\n\t\tp := s.Pos()\n\t\tline := tokFile.Line(p)\n\t\tfor previousLine := line - 1; previousLine >= firstSpecLine; {\n\t\t\t// MergeLine can panic. Avoid the panic at the cost of not removing the blank line\n\t\t\t// golang/go#50329\n\t\t\tif previousLine > 0 && previousLine < tokFile.LineCount() {\n\t\t\t\ttokFile.MergeLine(previousLine) // has side effects!\n\t\t\t\tpreviousLine--\n\t\t\t} else {\n\t\t\t\t// try to gather some data to diagnose how this could happen\n\t\t\t\treq := \"Please report what the imports section of your go file looked like.\"\n\t\t\t\tlog.Printf(\"panic avoided: first:%d line:%d previous:%d max:%d. %s\",\n\t\t\t\t\tfirstSpecLine, line, previousLine, tokFile.LineCount(), req)\n\t\t\t}\n\t\t}\n\t}\n\treturn specs\n}\n\ntype byImportSpec struct {\n\tlocalPrefix string\n\tspecs       []ast.Spec // slice of *ast.ImportSpec\n}\n\nfunc (x byImportSpec) Len() int      { return len(x.specs) }\nfunc (x byImportSpec) Swap(i, j int) { x.specs[i], x.specs[j] = x.specs[j], x.specs[i] }\nfunc (x byImportSpec) Less(i, j int) bool {\n\tipath := importPath(x.specs[i])\n\tjpath := importPath(x.specs[j])\n\n\tigroup := importGroup(x.localPrefix, ipath)\n\tjgroup := importGroup(x.localPrefix, jpath)\n\tif igroup != jgroup {\n\t\treturn igroup < jgroup\n\t}\n\n\tif ipath != jpath {\n\t\treturn ipath < jpath\n\t}\n\tiname := importName(x.specs[i])\n\tjname := importName(x.specs[j])\n\n\tif iname != jname {\n\t\treturn iname < jname\n\t}\n\treturn importComment(x.specs[i]) < importComment(x.specs[j])\n}\n\ntype byCommentPos []*ast.CommentGroup\n\nfunc (x byCommentPos) Len() int           { return len(x) }\nfunc (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\nfunc (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }\n\n// updateBasicLitPos updates lit.Pos,\n// ensuring that lit.End (if set) is displaced by the same amount.\n// (See https://go.dev/issue/76395.)\nfunc updateBasicLitPos(lit *ast.BasicLit, pos token.Pos) {\n\tlen := lit.End() - lit.Pos()\n\tlit.ValuePos = pos\n\t// TODO(adonovan): after go1.26, simplify to:\n\t//   lit.ValueEnd = pos + len\n\tv := reflect.ValueOf(lit).Elem().FieldByName(\"ValueEnd\")\n\tif v.IsValid() && v.Int() != 0 {\n\t\tv.SetInt(int64(pos + len))\n\t}\n}\n"
  },
  {
    "path": "internal/imports/source.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport \"context\"\n\n// These types document the APIs below.\n//\n// TODO(rfindley): consider making these defined types rather than aliases.\ntype (\n\tImportPath  = string\n\tPackageName = string\n\tSymbol      = string\n\n\t// References is set of References found in a Go file. The first map key is the\n\t// left hand side of a selector expression, the second key is the right hand\n\t// side, and the value should always be true.\n\tReferences = map[PackageName]map[Symbol]bool\n)\n\n// A Result satisfies a missing import.\n//\n// The Import field describes the missing import spec, and the Package field\n// summarizes the package exports.\ntype Result struct {\n\tImport  *ImportInfo\n\tPackage *PackageInfo\n}\n\n// An ImportInfo represents a single import statement.\ntype ImportInfo struct {\n\tImportPath string // import path, e.g. \"crypto/rand\".\n\tName       string // import name, e.g. \"crand\", or \"\" if none.\n}\n\n// A PackageInfo represents what's known about a package.\ntype PackageInfo struct {\n\tName    string          // package name in the package declaration, if known\n\tExports map[string]bool // set of names of known package level sortSymbols\n}\n\n// A Source provides imports to satisfy unresolved references in the file being\n// fixed.\ntype Source interface {\n\t// LoadPackageNames queries PackageName information for the requested import\n\t// paths, when operating from the provided srcDir.\n\t//\n\t// TODO(rfindley): try to refactor to remove this operation.\n\tLoadPackageNames(ctx context.Context, srcDir string, paths []ImportPath) (map[ImportPath]PackageName, error)\n\n\t// ResolveReferences asks the Source for the best package name to satisfy\n\t// each of the missing references, in the context of fixing the given\n\t// filename.\n\t//\n\t// Returns a map from package name to a [Result] for that package name that\n\t// provides the required symbols. Keys may be omitted in the map if no\n\t// candidates satisfy all missing references for that package name. It is up\n\t// to each data source to select the best result for each entry in the\n\t// missing map.\n\tResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error)\n}\n"
  },
  {
    "path": "internal/imports/source_env.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"context\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n)\n\n// ProcessEnvSource implements the [Source] interface using the legacy\n// [ProcessEnv] abstraction.\ntype ProcessEnvSource struct {\n\tenv      *ProcessEnv\n\tsrcDir   string\n\tfilename string\n\tpkgName  string\n}\n\n// NewProcessEnvSource returns a [ProcessEnvSource] wrapping the given\n// env, to be used for fixing imports in the file with name filename in package\n// named pkgName.\nfunc NewProcessEnvSource(env *ProcessEnv, filename, pkgName string) (*ProcessEnvSource, error) {\n\tabs, err := filepath.Abs(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsrcDir := filepath.Dir(abs)\n\treturn &ProcessEnvSource{\n\t\tenv:      env,\n\t\tsrcDir:   srcDir,\n\t\tfilename: filename,\n\t\tpkgName:  pkgName,\n\t}, nil\n}\n\nfunc (s *ProcessEnvSource) LoadPackageNames(ctx context.Context, srcDir string, unknown []string) (map[string]string, error) {\n\tr, err := s.env.GetResolver()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn r.loadPackageNames(unknown, srcDir)\n}\n\nfunc (s *ProcessEnvSource) ResolveReferences(ctx context.Context, filename string, refs map[string]map[string]bool) ([]*Result, error) {\n\tvar mu sync.Mutex\n\tfound := make(map[string][]pkgDistance)\n\tcallback := &scanCallback{\n\t\trootFound: func(gopathwalk.Root) bool {\n\t\t\treturn true // We want everything.\n\t\t},\n\t\tdirFound: func(pkg *pkg) bool {\n\t\t\treturn pkgIsCandidate(filename, refs, pkg)\n\t\t},\n\t\tpackageNameLoaded: func(pkg *pkg) bool {\n\t\t\tif _, want := refs[pkg.packageName]; !want {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif pkg.dir == s.srcDir && s.pkgName == pkg.packageName {\n\t\t\t\t// The candidate is in the same directory and has the\n\t\t\t\t// same package name. Don't try to import ourselves.\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif !CanUse(filename, pkg.dir) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tmu.Lock()\n\t\t\tdefer mu.Unlock()\n\t\t\tfound[pkg.packageName] = append(found[pkg.packageName], pkgDistance{pkg, distance(s.srcDir, pkg.dir)})\n\t\t\treturn false // We'll do our own loading after we sort.\n\t\t},\n\t}\n\tresolver, err := s.env.GetResolver()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := resolver.scan(ctx, callback); err != nil {\n\t\treturn nil, err\n\t}\n\n\tg, ctx := errgroup.WithContext(ctx)\n\n\tsearcher := symbolSearcher{\n\t\tlogf:        s.env.logf,\n\t\tsrcDir:      s.srcDir,\n\t\txtest:       strings.HasSuffix(s.pkgName, \"_test\"),\n\t\tloadExports: resolver.loadExports,\n\t}\n\n\tvar resultMu sync.Mutex\n\tresults := make(map[string]*Result, len(refs))\n\tfor pkgName, symbols := range refs {\n\t\tg.Go(func() error {\n\t\t\tfound, err := searcher.search(ctx, found[pkgName], pkgName, symbols)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif found == nil {\n\t\t\t\treturn nil // No matching package.\n\t\t\t}\n\n\t\t\timp := &ImportInfo{\n\t\t\t\tImportPath: found.importPathShort,\n\t\t\t}\n\t\t\tpkg := &PackageInfo{\n\t\t\t\tName:    pkgName,\n\t\t\t\tExports: symbols,\n\t\t\t}\n\t\t\tresultMu.Lock()\n\t\t\tresults[pkgName] = &Result{Import: imp, Package: pkg}\n\t\t\tresultMu.Unlock()\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := g.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\tvar ans []*Result\n\tfor _, x := range results {\n\t\tans = append(ans, x)\n\t}\n\treturn ans, nil\n}\n"
  },
  {
    "path": "internal/imports/source_modindex.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/modindex\"\n)\n\n// This code is here rather than in the modindex package\n// to avoid import loops\n\n// TODO(adonovan): this code is only used by a test in this package.\n// Can we delete it? Or is there a plan to call NewIndexSource from\n// cmd/goimports?\n\n// implements Source using modindex, so only for module cache.\n//\n// this is perhaps over-engineered. A new Index is read at first use.\n// And then Update is called after every 15 minutes, and a new Index\n// is read if the index changed. It is not clear the Mutex is needed.\ntype IndexSource struct {\n\tmodcachedir string\n\tmu          sync.Mutex\n\tindex       *modindex.Index // (access via getIndex)\n\texpires     time.Time\n}\n\n// create a new Source. Called from NewView in cache/session.go.\nfunc NewIndexSource(cachedir string) *IndexSource {\n\treturn &IndexSource{modcachedir: cachedir}\n}\n\nfunc (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths []ImportPath) (map[ImportPath]PackageName, error) {\n\t/// This is used by goimports to resolve the package names of imports of the\n\t// current package, which is irrelevant for the module cache.\n\treturn nil, nil\n}\n\nfunc (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) {\n\tindex, err := s.getIndex()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar cs []modindex.Candidate\n\tfor pkg, nms := range missing {\n\t\tfor nm := range nms {\n\t\t\tx := index.Lookup(pkg, nm, false)\n\t\t\tcs = append(cs, x...)\n\t\t}\n\t}\n\tfound := make(map[string]*Result)\n\tfor _, c := range cs {\n\t\tvar x *Result\n\t\tif x = found[c.ImportPath]; x == nil {\n\t\t\tx = &Result{\n\t\t\t\tImport: &ImportInfo{\n\t\t\t\t\tImportPath: c.ImportPath,\n\t\t\t\t\tName:       \"\",\n\t\t\t\t},\n\t\t\t\tPackage: &PackageInfo{\n\t\t\t\t\tName:    c.PkgName,\n\t\t\t\t\tExports: make(map[string]bool),\n\t\t\t\t},\n\t\t\t}\n\t\t\tfound[c.ImportPath] = x\n\t\t}\n\t\tx.Package.Exports[c.Name] = true\n\t}\n\tvar ans []*Result\n\tfor _, x := range found {\n\t\tans = append(ans, x)\n\t}\n\treturn ans, nil\n}\n\nfunc (s *IndexSource) getIndex() (*modindex.Index, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\t// (s.index = nil => s.expires is zero,\n\t// so the first condition is strictly redundant.\n\t// But it makes the postcondition very clear.)\n\tif s.index == nil || time.Now().After(s.expires) {\n\t\tindex, err := modindex.Update(s.modcachedir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ts.index = index\n\t\ts.expires = index.ValidAt.Add(15 * time.Minute) // (refresh period)\n\t}\n\t// Inv: s.index != nil\n\n\treturn s.index, nil\n}\n"
  },
  {
    "path": "internal/imports/sourcex_test.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage imports_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/internal/imports\"\n\t\"golang.org/x/tools/internal/modindex\"\n)\n\n// There are two cached packages, both resolving foo.Foo,\n// but only one resolving foo.Bar\nvar (\n\tfoo = tpkg{\n\t\trepo: \"foo.com\",\n\t\tdir:  \"foo@v1.0.0\",\n\t\tsyms: []string{\"Foo\"},\n\t}\n\tfoobar = tpkg{\n\t\trepo: \"bar.com\",\n\t\tdir:  \"foo@v1.0.0\",\n\t\tsyms: []string{\"Foo\", \"Bar\"},\n\t}\n\n\tfx = `package main\n\t\tvar _ = foo.Foo\n\t\tvar _ = foo.Bar\n\t`\n)\n\ntype tpkg struct {\n\t// all packages are named foo\n\trepo string   // e.g. foo.com\n\tdir  string   // e.g., foo@v1.0.0\n\tsyms []string // exported syms\n}\n\nfunc newpkgs(cachedir string, pks ...*tpkg) error {\n\tfor _, p := range pks {\n\t\tfname := filepath.Join(cachedir, p.repo, p.dir, \"foo.go\")\n\t\tif err := os.MkdirAll(filepath.Dir(fname), 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfd, err := os.Create(fname)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Fprintf(fd, \"package foo\\n\")\n\t\tfor _, s := range p.syms {\n\t\t\tfmt.Fprintf(fd, \"func %s() {}\\n\", s)\n\t\t}\n\t\tif err := fd.Close(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc TestSource(t *testing.T) {\n\tdirs := testDirs(t)\n\tif err := newpkgs(dirs.cachedir, &foo, &foobar); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tsource := imports.NewIndexSource(dirs.cachedir)\n\tctx := context.Background()\n\tfixes, err := imports.FixImports(ctx, \"tfile.go\", []byte(fx), \"unused\", nil, source)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\topts := imports.Options{}\n\t// ApplyFixes needs a non-nil opts\n\tgot, err := imports.ApplyFixes(fixes, \"tfile.go\", []byte(fx), &opts, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfxwant := \"package main\\n\\nimport \\\"bar.com/foo\\\"\\n\\nvar _ = foo.Foo\\nvar _ = foo.Bar\\n\"\n\tif diff := cmp.Diff(string(got), fxwant); diff != \"\" {\n\t\tt.Errorf(\"FixImports got\\n%q, wanted\\n%q\\ndiff is\\n%s\", string(got), fxwant, diff)\n\t}\n}\n\ntype dirs struct {\n\ttmpdir   string\n\tcachedir string\n\trootdir  string // goroot if we need it, which we don't\n}\n\nfunc testDirs(t *testing.T) dirs {\n\tt.Helper()\n\tdir := t.TempDir()\n\tmodindex.IndexDir = dir\n\tx := dirs{\n\t\ttmpdir:   dir,\n\t\tcachedir: filepath.Join(dir, \"pkg\", \"mod\"),\n\t\trootdir:  filepath.Join(dir, \"root\"),\n\t}\n\tif err := os.MkdirAll(x.cachedir, 0755); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.MkdirAll(x.rootdir, 0755); err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn x\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/example.com_v1.0.0.txt",
    "content": "Written by hand.\nTest case for module at root of domain.\n\n-- .mod --\nmodule example.com\n-- .info --\n{\"Version\": \"v1.0.0\"}\n-- x.go --\npackage x\n"
  },
  {
    "path": "internal/imports/testdata/mod/golang.org_x_text_v0.0.0-20170915032832-14c0d48ead0c.txt",
    "content": "written by hand - just enough to compile rsc.io/sampler, rsc.io/quote\n\n-- .mod --\nmodule golang.org/x/text\n-- .info --\n{\"Version\":\"v0.0.0-20170915032832-14c0d48ead0c\",\"Name\":\"v0.0.0-20170915032832-14c0d48ead0c\",\"Short\":\"14c0d48ead0c\",\"Time\":\"2017-09-15T03:28:32Z\"}\n-- go.mod --\nmodule golang.org/x/text\n-- unused/unused.go --\npackage unused\n-- language/lang.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is a tiny version of golang.org/x/text.\n\npackage language\n\nimport \"strings\"\n\ntype Tag string\n\nfunc Make(s string) Tag { return Tag(s) }\n\nfunc (t Tag) String() string { return string(t) }\n\nfunc NewMatcher(tags []Tag) Matcher { return &matcher{tags} }\n\ntype Matcher interface {\n\tMatch(...Tag) (Tag, int, int)\n}\n\ntype matcher struct {\n\ttags []Tag\n}\n\nfunc (m *matcher) Match(prefs ...Tag) (Tag, int, int) {\n\tfor _, pref := range prefs {\n\t\tfor _, tag := range m.tags {\n\t\t\tif tag == pref || strings.HasPrefix(string(pref), string(tag+\"-\")) || strings.HasPrefix(string(tag), string(pref+\"-\")) {\n\t\t\t\treturn tag, 0, 0\n\t\t\t}\n\t\t}\n\t}\n\treturn m.tags[0], 0, 0\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.2.txt",
    "content": "rsc.io/QUOTE v1.5.2\n\n-- .mod --\nmodule rsc.io/QUOTE\n\nrequire rsc.io/quote v1.5.2\n-- .info --\n{\"Version\":\"v1.5.2\",\"Name\":\"\",\"Short\":\"\",\"Time\":\"2018-07-15T16:25:34Z\"}\n-- go.mod --\nmodule rsc.io/QUOTE\n\nrequire rsc.io/quote v1.5.2\n-- QUOTE/quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// PACKAGE QUOTE COLLECTS LOUD SAYINGS.\npackage QUOTE\n\nimport (\n\t\"strings\"\n\n\t\"rsc.io/quote\"\n)\n\n// HELLO RETURNS A GREETING.\nfunc HELLO() string {\n\treturn strings.ToUpper(quote.Hello())\n}\n\n// GLASS RETURNS A USEFUL PHRASE FOR WORLD TRAVELERS.\nfunc GLASS() string {\n\treturn strings.ToUpper(quote.GLASS())\n}\n\n// GO RETURNS A GO PROVERB.\nfunc GO() string {\n\treturn strings.ToUpper(quote.GO())\n}\n\n// OPT RETURNS AN OPTIMIZATION TRUTH.\nfunc OPT() string {\n\treturn strings.ToUpper(quote.OPT())\n}\n-- QUOTE/quote_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage QUOTE\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc init() {\n\tos.Setenv(\"LC_ALL\", \"en\")\n}\n\nfunc TestHELLO(t *testing.T) {\n\thello := \"HELLO, WORLD\"\n\tif out := HELLO(); out != hello {\n\t\tt.Errorf(\"HELLO() = %q, want %q\", out, hello)\n\t}\n}\n\nfunc TestGLASS(t *testing.T) {\n\tglass := \"I CAN EAT GLASS AND IT DOESN'T HURT ME.\"\n\tif out := GLASS(); out != glass {\n\t\tt.Errorf(\"GLASS() = %q, want %q\", out, glass)\n\t}\n}\n\nfunc TestGO(t *testing.T) {\n\tgo1 := \"DON'T COMMUNICATE BY SHARING MEMORY, SHARE MEMORY BY COMMUNICATING.\"\n\tif out := GO(); out != go1 {\n\t\tt.Errorf(\"GO() = %q, want %q\", out, go1)\n\t}\n}\n\nfunc TestOPT(t *testing.T) {\n\topt := \"IF A PROGRAM IS TOO SLOW, IT MUST HAVE A LOOP.\"\n\tif out := OPT(); out != opt {\n\t\tt.Errorf(\"OPT() = %q, want %q\", out, opt)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.3-!p!r!e.txt",
    "content": "rsc.io/QUOTE v1.5.3-PRE (sigh)\n\n-- .mod --\nmodule rsc.io/QUOTE\n\nrequire rsc.io/quote v1.5.2\n-- .info --\n{\"Version\":\"v1.5.3-PRE\",\"Name\":\"\",\"Short\":\"\",\"Time\":\"2018-07-15T16:25:34Z\"}\n-- go.mod --\nmodule rsc.io/QUOTE\n\nrequire rsc.io/quote v1.5.2\n-- QUOTE/quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// PACKAGE QUOTE COLLECTS LOUD SAYINGS.\npackage QUOTE\n\nimport (\n\t\"strings\"\n\n\t\"rsc.io/quote\"\n)\n\n// HELLO RETURNS A GREETING.\nfunc HELLO() string {\n\treturn strings.ToUpper(quote.Hello())\n}\n\n// GLASS RETURNS A USEFUL PHRASE FOR WORLD TRAVELERS.\nfunc GLASS() string {\n\treturn strings.ToUpper(quote.GLASS())\n}\n\n// GO RETURNS A GO PROVERB.\nfunc GO() string {\n\treturn strings.ToUpper(quote.GO())\n}\n\n// OPT RETURNS AN OPTIMIZATION TRUTH.\nfunc OPT() string {\n\treturn strings.ToUpper(quote.OPT())\n}\n-- QUOTE/quote_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage QUOTE\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc init() {\n\tos.Setenv(\"LC_ALL\", \"en\")\n}\n\nfunc TestHELLO(t *testing.T) {\n\thello := \"HELLO, WORLD\"\n\tif out := HELLO(); out != hello {\n\t\tt.Errorf(\"HELLO() = %q, want %q\", out, hello)\n\t}\n}\n\nfunc TestGLASS(t *testing.T) {\n\tglass := \"I CAN EAT GLASS AND IT DOESN'T HURT ME.\"\n\tif out := GLASS(); out != glass {\n\t\tt.Errorf(\"GLASS() = %q, want %q\", out, glass)\n\t}\n}\n\nfunc TestGO(t *testing.T) {\n\tgo1 := \"DON'T COMMUNICATE BY SHARING MEMORY, SHARE MEMORY BY COMMUNICATING.\"\n\tif out := GO(); out != go1 {\n\t\tt.Errorf(\"GO() = %q, want %q\", out, go1)\n\t}\n}\n\nfunc TestOPT(t *testing.T) {\n\topt := \"IF A PROGRAM IS TOO SLOW, IT MUST HAVE A LOOP.\"\n\tif out := OPT(); out != opt {\n\t\tt.Errorf(\"OPT() = %q, want %q\", out, opt)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_quote_v1.5.1.txt",
    "content": "rsc.io/quote@23179ee8a569\n\n-- .mod --\nmodule \"rsc.io/quote\"\n\nrequire \"rsc.io/sampler\" v1.3.0\n-- .info --\n{\"Version\":\"v1.5.1\",\"Name\":\"23179ee8a569bb05d896ae05c6503ec69a19f99f\",\"Short\":\"23179ee8a569\",\"Time\":\"2018-02-14T00:58:40Z\"}\n-- go.mod --\nmodule \"rsc.io/quote\"\n\nrequire \"rsc.io/sampler\" v1.3.0\n-- quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package quote collects pithy sayings.\npackage quote // import \"rsc.io/quote\"\n\nimport \"rsc.io/sampler\"\n\n// Hello returns a greeting.\nfunc Hello() string {\n\treturn sampler.Hello()\n}\n\n// Glass returns a useful phrase for world travelers.\nfunc Glass() string {\n\t// See http://www.oocities.org/nodotus/hbglass.html.\n\treturn \"I can eat glass and it doesn't hurt me.\"\n}\n\n// Go returns a Go proverb.\nfunc Go() string {\n\treturn \"Don't communicate by sharing memory, share memory by communicating.\"\n}\n\n// Opt returns an optimization truth.\nfunc Opt() string {\n\t// Wisdom from ken.\n\treturn \"If a program is too slow, it must have a loop.\"\n}\n-- quote_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage quote\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc init() {\n\tos.Setenv(\"LC_ALL\", \"en\")\n}\n\nfunc TestHello(t *testing.T) {\n\thello := \"Hello, world.\"\n\tif out := Hello(); out != hello {\n\t\tt.Errorf(\"Hello() = %q, want %q\", out, hello)\n\t}\n}\n\nfunc TestGlass(t *testing.T) {\n\tglass := \"I can eat glass and it doesn't hurt me.\"\n\tif out := Glass(); out != glass {\n\t\tt.Errorf(\"Glass() = %q, want %q\", out, glass)\n\t}\n}\n\nfunc TestGo(t *testing.T) {\n\tgo1 := \"Don't communicate by sharing memory, share memory by communicating.\"\n\tif out := Go(); out != go1 {\n\t\tt.Errorf(\"Go() = %q, want %q\", out, go1)\n\t}\n}\n\nfunc TestOpt(t *testing.T) {\n\topt := \"If a program is too slow, it must have a loop.\"\n\tif out := Opt(); out != opt {\n\t\tt.Errorf(\"Opt() = %q, want %q\", out, opt)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_quote_v1.5.2.txt",
    "content": "rsc.io/quote@v1.5.2\n\n-- .mod --\nmodule \"rsc.io/quote\"\n\nrequire \"rsc.io/sampler\" v1.3.0\n-- .info --\n{\"Version\":\"v1.5.2\",\"Name\":\"c4d4236f92427c64bfbcf1cc3f8142ab18f30b22\",\"Short\":\"c4d4236f9242\",\"Time\":\"2018-02-14T15:44:20Z\"}\n-- buggy/buggy_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage buggy\n\nimport \"testing\"\n\nfunc Test(t *testing.T) {\n\tt.Fatal(\"buggy!\")\n}\n-- go.mod --\nmodule \"rsc.io/quote\"\n\nrequire \"rsc.io/sampler\" v1.3.0\n-- quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package quote collects pithy sayings.\npackage quote // import \"rsc.io/quote\"\n\nimport \"rsc.io/sampler\"\n\n// Hello returns a greeting.\nfunc Hello() string {\n\treturn sampler.Hello()\n}\n\n// Glass returns a useful phrase for world travelers.\nfunc Glass() string {\n\t// See http://www.oocities.org/nodotus/hbglass.html.\n\treturn \"I can eat glass and it doesn't hurt me.\"\n}\n\n// Go returns a Go proverb.\nfunc Go() string {\n\treturn \"Don't communicate by sharing memory, share memory by communicating.\"\n}\n\n// Opt returns an optimization truth.\nfunc Opt() string {\n\t// Wisdom from ken.\n\treturn \"If a program is too slow, it must have a loop.\"\n}\n-- quote_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage quote\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc init() {\n\tos.Setenv(\"LC_ALL\", \"en\")\n}\n\nfunc TestHello(t *testing.T) {\n\thello := \"Hello, world.\"\n\tif out := Hello(); out != hello {\n\t\tt.Errorf(\"Hello() = %q, want %q\", out, hello)\n\t}\n}\n\nfunc TestGlass(t *testing.T) {\n\tglass := \"I can eat glass and it doesn't hurt me.\"\n\tif out := Glass(); out != glass {\n\t\tt.Errorf(\"Glass() = %q, want %q\", out, glass)\n\t}\n}\n\nfunc TestGo(t *testing.T) {\n\tgo1 := \"Don't communicate by sharing memory, share memory by communicating.\"\n\tif out := Go(); out != go1 {\n\t\tt.Errorf(\"Go() = %q, want %q\", out, go1)\n\t}\n}\n\nfunc TestOpt(t *testing.T) {\n\topt := \"If a program is too slow, it must have a loop.\"\n\tif out := Opt(); out != opt {\n\t\tt.Errorf(\"Opt() = %q, want %q\", out, opt)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_quote_v2_v2.0.1.txt",
    "content": "rsc.io/quote/v2@v2.0.1\n\n-- .mod --\nmodule rsc.io/quote/v2\n\nrequire rsc.io/sampler v1.3.0\n-- .info --\n{\"Version\":\"v2.0.1\",\"Name\":\"754f68430672776c84704e2d10209a6ec700cd64\",\"Short\":\"754f68430672\",\"Time\":\"2018-07-09T16:25:34Z\"}\n-- go.mod --\nmodule rsc.io/quote/v2\n\nrequire rsc.io/sampler v1.3.0\n-- quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package quote collects pithy sayings.\npackage quote // import \"rsc.io/quote\"\n\nimport \"rsc.io/sampler\"\n\n// Hello returns a greeting.\nfunc HelloV2() string {\n\treturn sampler.Hello()\n}\n\n// Glass returns a useful phrase for world travelers.\nfunc GlassV2() string {\n\t// See http://www.oocities.org/nodotus/hbglass.html.\n\treturn \"I can eat glass and it doesn't hurt me.\"\n}\n\n// Go returns a Go proverb.\nfunc GoV2() string {\n\treturn \"Don't communicate by sharing memory, share memory by communicating.\"\n}\n\n// Opt returns an optimization truth.\nfunc OptV2() string {\n\t// Wisdom from ken.\n\treturn \"If a program is too slow, it must have a loop.\"\n}\n-- quote_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage quote\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc init() {\n\tos.Setenv(\"LC_ALL\", \"en\")\n}\n\nfunc TestHello(t *testing.T) {\n\thello := \"Hello, world.\"\n\tif out := Hello(); out != hello {\n\t\tt.Errorf(\"Hello() = %q, want %q\", out, hello)\n\t}\n}\n\nfunc TestGlass(t *testing.T) {\n\tglass := \"I can eat glass and it doesn't hurt me.\"\n\tif out := Glass(); out != glass {\n\t\tt.Errorf(\"Glass() = %q, want %q\", out, glass)\n\t}\n}\n\nfunc TestGo(t *testing.T) {\n\tgo1 := \"Don't communicate by sharing memory, share memory by communicating.\"\n\tif out := Go(); out != go1 {\n\t\tt.Errorf(\"Go() = %q, want %q\", out, go1)\n\t}\n}\n\nfunc TestOpt(t *testing.T) {\n\topt := \"If a program is too slow, it must have a loop.\"\n\tif out := Opt(); out != opt {\n\t\tt.Errorf(\"Opt() = %q, want %q\", out, opt)\n\t}\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_quote_v3_v3.0.0.txt",
    "content": "rsc.io/quote/v3@v3.0.0\n\n-- .mod --\nmodule rsc.io/quote/v3\n\nrequire rsc.io/sampler v1.3.0\n\n-- .info --\n{\"Version\":\"v3.0.0\",\"Name\":\"d88915d7e77ed0fd35d0a022a2f244e2202fd8c8\",\"Short\":\"d88915d7e77e\",\"Time\":\"2018-07-09T15:34:46Z\"}\n-- go.mod --\nmodule rsc.io/quote/v3\n\nrequire rsc.io/sampler v1.3.0\n\n-- quote.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package quote collects pithy sayings.\npackage quote // import \"rsc.io/quote\"\n\nimport \"rsc.io/sampler\"\n\n// Hello returns a greeting.\nfunc HelloV3() string {\n\treturn sampler.Hello()\n}\n\n// Glass returns a useful phrase for world travelers.\nfunc GlassV3() string {\n\t// See http://www.oocities.org/nodotus/hbglass.html.\n\treturn \"I can eat glass and it doesn't hurt me.\"\n}\n\n// Go returns a Go proverb.\nfunc GoV3() string {\n\treturn \"Don't communicate by sharing memory, share memory by communicating.\"\n}\n\n// Opt returns an optimization truth.\nfunc OptV3() string {\n\t// Wisdom from ken.\n\treturn \"If a program is too slow, it must have a loop.\"\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_sampler_v1.3.0.txt",
    "content": "rsc.io/sampler@v1.3.0\n\n-- .mod --\nmodule \"rsc.io/sampler\"\n\nrequire \"golang.org/x/text\" v0.0.0-20170915032832-14c0d48ead0c\n-- .info --\n{\"Version\":\"v1.3.0\",\"Name\":\"0cc034b51e57ed7832d4c67d526f75a900996e5c\",\"Short\":\"0cc034b51e57\",\"Time\":\"2018-02-13T19:05:03Z\"}\n-- glass.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Translations from Frank da Cruz, Ethan Mollick, and many others.\n// See http://kermitproject.org/utf8.html.\n// http://www.oocities.org/nodotus/hbglass.html\n// https://en.wikipedia.org/wiki/I_Can_Eat_Glass\n\npackage sampler\n\nvar glass = newText(`\n\nEnglish: en: I can eat glass and it doesn't hurt me.\nFrench: fr: Je peux manger du verre, ça ne me fait pas mal.\nSpanish: es: Puedo comer vidrio, no me hace daño.\n\n`)\n-- glass_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sampler\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/text/language\"\n\t_ \"rsc.io/testonly\"\n)\n\nvar glassTests = []struct {\n\tprefs []language.Tag\n\ttext  string\n}{\n\t{\n\t\t[]language.Tag{language.Make(\"en-US\"), language.Make(\"fr\")},\n\t\t\"I can eat glass and it doesn't hurt me.\",\n\t},\n\t{\n\t\t[]language.Tag{language.Make(\"fr\"), language.Make(\"en-US\")},\n\t\t\"Je peux manger du verre, ça ne me fait pas mal.\",\n\t},\n}\n\nfunc TestGlass(t *testing.T) {\n\tfor _, tt := range glassTests {\n\t\ttext := Glass(tt.prefs...)\n\t\tif text != tt.text {\n\t\t\tt.Errorf(\"Glass(%v) = %q, want %q\", tt.prefs, text, tt.text)\n\t\t}\n\t}\n}\n-- go.mod --\nmodule \"rsc.io/sampler\"\n\nrequire \"golang.org/x/text\" v0.0.0-20170915032832-14c0d48ead0c\n-- hello.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Translations by Google Translate.\n\npackage sampler\n\nvar hello = newText(`\n\nEnglish: en: Hello, world.\nFrench: fr: Bonjour le monde.\nSpanish: es: Hola Mundo.\n\n`)\n-- hello_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sampler\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/text/language\"\n)\n\nvar helloTests = []struct {\n\tprefs []language.Tag\n\ttext  string\n}{\n\t{\n\t\t[]language.Tag{language.Make(\"en-US\"), language.Make(\"fr\")},\n\t\t\"Hello, world.\",\n\t},\n\t{\n\t\t[]language.Tag{language.Make(\"fr\"), language.Make(\"en-US\")},\n\t\t\"Bonjour le monde.\",\n\t},\n}\n\nfunc TestHello(t *testing.T) {\n\tfor _, tt := range helloTests {\n\t\ttext := Hello(tt.prefs...)\n\t\tif text != tt.text {\n\t\t\tt.Errorf(\"Hello(%v) = %q, want %q\", tt.prefs, text, tt.text)\n\t\t}\n\t}\n}\n-- sampler.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sampler shows simple texts.\npackage sampler // import \"rsc.io/sampler\"\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/text/language\"\n)\n\n// DefaultUserPrefs returns the default user language preferences.\n// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment\n// variables, in that order.\nfunc DefaultUserPrefs() []language.Tag {\n\tvar prefs []language.Tag\n\tfor _, k := range []string{\"LC_ALL\", \"LC_MESSAGES\", \"LANG\"} {\n\t\tif env := os.Getenv(k); env != \"\" {\n\t\t\tprefs = append(prefs, language.Make(env))\n\t\t}\n\t}\n\treturn prefs\n}\n\n// Hello returns a localized greeting.\n// If no prefs are given, Hello uses DefaultUserPrefs.\nfunc Hello(prefs ...language.Tag) string {\n\tif len(prefs) == 0 {\n\t\tprefs = DefaultUserPrefs()\n\t}\n\treturn hello.find(prefs)\n}\n\n// Glass returns a localized silly phrase.\n// If no prefs are given, Glass uses DefaultUserPrefs.\nfunc Glass(prefs ...language.Tag) string {\n\tif len(prefs) == 0 {\n\t\tprefs = DefaultUserPrefs()\n\t}\n\treturn glass.find(prefs)\n}\n\n// A text is a localized text.\ntype text struct {\n\tbyTag   map[string]string\n\tmatcher language.Matcher\n}\n\n// newText creates a new localized text, given a list of translations.\nfunc newText(s string) *text {\n\tt := &text{\n\t\tbyTag: make(map[string]string),\n\t}\n\tvar tags []language.Tag\n\tfor _, line := range strings.Split(s, \"\\n\") {\n\t\tline = strings.TrimSpace(line)\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tf := strings.Split(line, \": \")\n\t\tif len(f) != 3 {\n\t\t\tcontinue\n\t\t}\n\t\ttag := language.Make(f[1])\n\t\ttags = append(tags, tag)\n\t\tt.byTag[tag.String()] = f[2]\n\t}\n\tt.matcher = language.NewMatcher(tags)\n\treturn t\n}\n\n// find finds the text to use for the given language tag preferences.\nfunc (t *text) find(prefs []language.Tag) string {\n\ttag, _, _ := t.matcher.Match(prefs...)\n\ts := t.byTag[tag.String()]\n\tif strings.HasPrefix(s, \"RTL \") {\n\t\ts = \"\\u200F\" + strings.TrimPrefix(s, \"RTL \") + \"\\u200E\"\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "internal/imports/testdata/mod/rsc.io_sampler_v1.3.1.txt",
    "content": "rsc.io/sampler@v1.3.1\n\n-- .mod --\nmodule \"rsc.io/sampler\"\n\nrequire \"golang.org/x/text\" v0.0.0-20170915032832-14c0d48ead0c\n-- .info --\n{\"Version\":\"v1.3.1\",\"Name\":\"f545d0289d06e2add4556ea6a15fc4938014bf87\",\"Short\":\"f545d0289d06\",\"Time\":\"2018-02-14T16:34:12Z\"}\n-- glass.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Translations from Frank da Cruz, Ethan Mollick, and many others.\n// See http://kermitproject.org/utf8.html.\n// http://www.oocities.org/nodotus/hbglass.html\n// https://en.wikipedia.org/wiki/I_Can_Eat_Glass\n\npackage sampler\n\nvar glass = newText(`\n\nEnglish: en: I can eat glass and it doesn't hurt me.\nFrench: fr: Je peux manger du verre, ça ne me fait pas mal.\nSpanish: es: Puedo comer vidrio, no me hace daño.\n\n`)\n-- glass_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sampler\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/text/language\"\n)\n\nvar glassTests = []struct {\n\tprefs []language.Tag\n\ttext  string\n}{\n\t{\n\t\t[]language.Tag{language.Make(\"en-US\"), language.Make(\"fr\")},\n\t\t\"I can eat glass and it doesn't hurt me.\",\n\t},\n\t{\n\t\t[]language.Tag{language.Make(\"fr\"), language.Make(\"en-US\")},\n\t\t\"Je peux manger du verre, ça ne me fait pas mal.\",\n\t},\n}\n\nfunc TestGlass(t *testing.T) {\n\tfor _, tt := range glassTests {\n\t\ttext := Glass(tt.prefs...)\n\t\tif text != tt.text {\n\t\t\tt.Errorf(\"Glass(%v) = %q, want %q\", tt.prefs, text, tt.text)\n\t\t}\n\t}\n}\n-- go.mod --\nmodule \"rsc.io/sampler\"\n\nrequire \"golang.org/x/text\" v0.0.0-20170915032832-14c0d48ead0c\n-- hello.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Translations by Google Translate.\n\npackage sampler\n\nvar hello = newText(`\n\nEnglish: en: Hello, world.\nFrench: fr: Bonjour le monde.\nSpanish: es: Hola Mundo.\n\n`)\n-- hello_test.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sampler\n\nimport (\n\t\"testing\"\n\n\t\"golang.org/x/text/language\"\n)\n\nvar helloTests = []struct {\n\tprefs []language.Tag\n\ttext  string\n}{\n\t{\n\t\t[]language.Tag{language.Make(\"en-US\"), language.Make(\"fr\")},\n\t\t\"Hello, world.\",\n\t},\n\t{\n\t\t[]language.Tag{language.Make(\"fr\"), language.Make(\"en-US\")},\n\t\t\"Bonjour le monde.\",\n\t},\n}\n\nfunc TestHello(t *testing.T) {\n\tfor _, tt := range helloTests {\n\t\ttext := Hello(tt.prefs...)\n\t\tif text != tt.text {\n\t\t\tt.Errorf(\"Hello(%v) = %q, want %q\", tt.prefs, text, tt.text)\n\t\t}\n\t}\n}\n-- sampler.go --\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sampler shows simple texts in a variety of languages.\npackage sampler // import \"rsc.io/sampler\"\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"golang.org/x/text/language\"\n)\n\n// DefaultUserPrefs returns the default user language preferences.\n// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment\n// variables, in that order.\nfunc DefaultUserPrefs() []language.Tag {\n\tvar prefs []language.Tag\n\tfor _, k := range []string{\"LC_ALL\", \"LC_MESSAGES\", \"LANG\"} {\n\t\tif env := os.Getenv(k); env != \"\" {\n\t\t\tprefs = append(prefs, language.Make(env))\n\t\t}\n\t}\n\treturn prefs\n}\n\n// Hello returns a localized greeting.\n// If no prefs are given, Hello uses DefaultUserPrefs.\nfunc Hello(prefs ...language.Tag) string {\n\tif len(prefs) == 0 {\n\t\tprefs = DefaultUserPrefs()\n\t}\n\treturn hello.find(prefs)\n}\n\n// Glass returns a localized silly phrase.\n// If no prefs are given, Glass uses DefaultUserPrefs.\nfunc Glass(prefs ...language.Tag) string {\n\tif len(prefs) == 0 {\n\t\tprefs = DefaultUserPrefs()\n\t}\n\treturn glass.find(prefs)\n}\n\n// A text is a localized text.\ntype text struct {\n\tbyTag   map[string]string\n\tmatcher language.Matcher\n}\n\n// newText creates a new localized text, given a list of translations.\nfunc newText(s string) *text {\n\tt := &text{\n\t\tbyTag: make(map[string]string),\n\t}\n\tvar tags []language.Tag\n\tfor _, line := range strings.Split(s, \"\\n\") {\n\t\tline = strings.TrimSpace(line)\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tf := strings.Split(line, \": \")\n\t\tif len(f) != 3 {\n\t\t\tcontinue\n\t\t}\n\t\ttag := language.Make(f[1])\n\t\ttags = append(tags, tag)\n\t\tt.byTag[tag.String()] = f[2]\n\t}\n\tt.matcher = language.NewMatcher(tags)\n\treturn t\n}\n\n// find finds the text to use for the given language tag preferences.\nfunc (t *text) find(prefs []language.Tag) string {\n\ttag, _, _ := t.matcher.Match(prefs...)\n\ts := t.byTag[tag.String()]\n\tif strings.HasPrefix(s, \"RTL \") {\n\t\ts = \"\\u200F\" + strings.TrimPrefix(s, \"RTL \") + \"\\u200E\"\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "internal/jsonrpc2/conn.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n\t\"golang.org/x/tools/internal/event/label\"\n)\n\n// Conn is the common interface to jsonrpc clients and servers.\n// Conn is bidirectional; it does not have a designated server or client end.\n// It manages the jsonrpc2 protocol, connecting responses back to their calls.\ntype Conn interface {\n\t// Call invokes the target method and waits for a response.\n\t// The params will be marshaled to JSON before sending over the wire, and will\n\t// be handed to the method invoked.\n\t// The response will be unmarshaled from JSON into the result.\n\t// The id returned will be unique from this connection, and can be used for\n\t// logging or tracking.\n\tCall(ctx context.Context, method string, params, result any) (ID, error)\n\n\t// Notify invokes the target method but does not wait for a response.\n\t// The params will be marshaled to JSON before sending over the wire, and will\n\t// be handed to the method invoked.\n\tNotify(ctx context.Context, method string, params any) error\n\n\t// Go starts a goroutine to handle the connection.\n\t// It must be called exactly once for each Conn.\n\t// It returns immediately.\n\t// You must block on Done() to wait for the connection to shut down.\n\t// This is a temporary measure, this should be started automatically in the\n\t// future.\n\tGo(ctx context.Context, handler Handler)\n\n\t// Close closes the connection and it's underlying stream.\n\t// It does not wait for the close to complete, use the Done() channel for\n\t// that.\n\tClose() error\n\n\t// Done returns a channel that will be closed when the processing goroutine\n\t// has terminated, which will happen if Close() is called or an underlying\n\t// stream is closed.\n\tDone() <-chan struct{}\n\n\t// Err returns an error if there was one from within the processing goroutine.\n\t// If err returns non nil, the connection will be already closed or closing.\n\tErr() error\n}\n\ntype conn struct {\n\tseq       int64      // must only be accessed using atomic operations\n\twriteMu   sync.Mutex // protects writes to the stream\n\tstream    Stream\n\tpendingMu sync.Mutex // protects the pending map\n\tpending   map[ID]chan *Response\n\n\tdone chan struct{}\n\terr  atomic.Value\n}\n\n// NewConn creates a new connection object around the supplied stream.\nfunc NewConn(s Stream) Conn {\n\tconn := &conn{\n\t\tstream:  s,\n\t\tpending: make(map[ID]chan *Response),\n\t\tdone:    make(chan struct{}),\n\t}\n\treturn conn\n}\n\nfunc (c *conn) Notify(ctx context.Context, method string, params any) (err error) {\n\tnotify, err := NewNotification(method, params)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling notify parameters: %v\", err)\n\t}\n\tctx, done := event.Start(ctx, method,\n\t\tMethod.Of(method),\n\t\tRPCDirection.Of(Outbound),\n\t)\n\tstart := time.Now()\n\tdefer func() {\n\t\tctx = recordStatus(ctx, err)\n\t\tevent.Metric(ctx, Latency.Of(time.Since(start).Seconds()))\n\t\tdone()\n\t}()\n\n\tevent.Metric(ctx, Started.Of(1))\n\tn, err := c.write(ctx, notify)\n\tevent.Metric(ctx, SentBytes.Of64(n))\n\treturn err\n}\n\nfunc (c *conn) Call(ctx context.Context, method string, params, result any) (_ ID, err error) {\n\t// generate a new request identifier\n\tid := ID{number: atomic.AddInt64(&c.seq, 1)}\n\tcall, err := NewCall(id, method, params)\n\tif err != nil {\n\t\treturn id, fmt.Errorf(\"marshaling call parameters: %v\", err)\n\t}\n\tctx, done := event.Start(ctx, method,\n\t\tMethod.Of(method),\n\t\tRPCDirection.Of(Outbound),\n\t\tRPCID.Of(fmt.Sprintf(\"%q\", id)),\n\t)\n\tstart := time.Now()\n\tvar rpcErr error\n\tdefer func() {\n\t\tctx = recordStatus(ctx, rpcErr)\n\t\tevent.Metric(ctx, Latency.Of(time.Since(start).Seconds()))\n\t\tdone()\n\t}()\n\tevent.Metric(ctx, Started.Of(1))\n\t// We have to add ourselves to the pending map before we send, otherwise we\n\t// are racing the response. Also add a buffer to rchan, so that if we get a\n\t// wire response between the time this call is cancelled and id is deleted\n\t// from c.pending, the send to rchan will not block.\n\trchan := make(chan *Response, 1)\n\tc.pendingMu.Lock()\n\tc.pending[id] = rchan\n\tc.pendingMu.Unlock()\n\tdefer func() {\n\t\tc.pendingMu.Lock()\n\t\tdelete(c.pending, id)\n\t\tc.pendingMu.Unlock()\n\t}()\n\t// now we are ready to send\n\tn, err := c.write(ctx, call)\n\tevent.Metric(ctx, SentBytes.Of64(n))\n\tif err != nil {\n\t\t// sending failed, we will never get a response, so don't leave it pending\n\t\treturn id, err\n\t}\n\t// now wait for the response\n\tselect {\n\tcase response := <-rchan:\n\t\t// is it an error response?\n\t\tif response.err != nil {\n\t\t\trpcErr = response.err\n\t\t\treturn id, response.err\n\t\t}\n\t\tif result == nil || len(response.result) == 0 {\n\t\t\treturn id, nil\n\t\t}\n\t\tif err := json.Unmarshal(response.result, result); err != nil {\n\t\t\treturn id, fmt.Errorf(\"unmarshaling result: %v\", err)\n\t\t}\n\t\treturn id, nil\n\tcase <-ctx.Done():\n\t\trpcErr = ctx.Err()\n\t\treturn id, ctx.Err()\n\t}\n}\n\nfunc (c *conn) replier(req Request, start time.Time, spanDone func()) Replier {\n\treturn func(ctx context.Context, result any, err error) error {\n\t\t// Save the RPC error before err gets reassigned by NewResponse/write below.\n\t\trpcErr := err\n\t\tdefer func() {\n\t\t\tctx = recordStatus(ctx, rpcErr)\n\t\t\tevent.Metric(ctx, Latency.Of(time.Since(start).Seconds()))\n\t\t\tspanDone()\n\t\t}()\n\t\tcall, ok := req.(*Call)\n\t\tif !ok {\n\t\t\t// request was a notify, no need to respond\n\t\t\treturn nil\n\t\t}\n\t\tresponse, err := NewResponse(call.id, result, err)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tn, err := c.write(ctx, response)\n\t\tevent.Metric(ctx, SentBytes.Of64(n))\n\t\tif err != nil {\n\t\t\t// TODO(iancottrell): if a stream write fails, we really need to shut down\n\t\t\t// the whole stream\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n}\n\nfunc (c *conn) write(ctx context.Context, msg Message) (int64, error) {\n\tc.writeMu.Lock()\n\tdefer c.writeMu.Unlock()\n\treturn c.stream.Write(ctx, msg)\n}\n\nfunc (c *conn) Go(ctx context.Context, handler Handler) {\n\tgo c.run(ctx, handler)\n}\n\nfunc (c *conn) run(ctx context.Context, handler Handler) {\n\tdefer close(c.done)\n\tfor {\n\t\t// get the next message\n\t\tmsg, n, err := c.stream.Read(ctx)\n\t\tif err != nil {\n\t\t\t// The stream failed, we cannot continue.\n\t\t\tc.fail(err)\n\t\t\treturn\n\t\t}\n\t\tswitch msg := msg.(type) {\n\t\tcase Request:\n\t\t\tlabels := []label.Label{\n\t\t\t\tMethod.Of(msg.Method()),\n\t\t\t\tRPCDirection.Of(Inbound),\n\t\t\t\t{}, // reserved for ID if present\n\t\t\t}\n\t\t\tif call, ok := msg.(*Call); ok {\n\t\t\t\tlabels[len(labels)-1] = RPCID.Of(fmt.Sprintf(\"%q\", call.ID()))\n\t\t\t} else {\n\t\t\t\tlabels = labels[:len(labels)-1]\n\t\t\t}\n\t\t\treqCtx, spanDone := event.Start(ctx, msg.Method(), labels...)\n\t\t\tstart := time.Now()\n\t\t\tevent.Metric(reqCtx,\n\t\t\t\tStarted.Of(1),\n\t\t\t\tReceivedBytes.Of64(n))\n\t\t\tif err := handler(reqCtx, c.replier(msg, start, spanDone), msg); err != nil {\n\t\t\t\t// delivery failed, not much we can do\n\t\t\t\tevent.Error(reqCtx, \"jsonrpc2 message delivery failed\", err)\n\t\t\t}\n\t\tcase *Response:\n\t\t\t// If method is not set, this should be a response, in which case we must\n\t\t\t// have an id to send the response back to the caller.\n\t\t\tc.pendingMu.Lock()\n\t\t\trchan, ok := c.pending[msg.id]\n\t\t\tc.pendingMu.Unlock()\n\t\t\tif ok {\n\t\t\t\trchan <- msg\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (c *conn) Close() error {\n\treturn c.stream.Close()\n}\n\nfunc (c *conn) Done() <-chan struct{} {\n\treturn c.done\n}\n\nfunc (c *conn) Err() error {\n\tif err := c.err.Load(); err != nil {\n\t\treturn err.(error)\n\t}\n\treturn nil\n}\n\n// fail sets a failure condition on the stream and closes it.\nfunc (c *conn) fail(err error) {\n\tc.err.Store(err)\n\tc.stream.Close()\n}\n\nfunc recordStatus(ctx context.Context, err error) context.Context {\n\tvar status string\n\tvar wireError *WireError\n\tswitch {\n\tcase err == nil:\n\t\tstatus = \"OK\"\n\tcase errors.Is(err, context.Canceled):\n\t\tstatus = \"CANCELED\"\n\tcase errors.As(err, &wireError) && wireError.Code == -32800: // JSON RPC request canceled\n\t\tstatus = \"CANCELED\"\n\tcase errors.Is(err, context.DeadlineExceeded):\n\t\tstatus = \"DEADLINE_EXCEEDED\"\n\tcase errors.Is(err, ErrMethodNotFound):\n\t\tstatus = \"METHOD_NOT_FOUND\"\n\tdefault:\n\t\tstatus = \"ERROR\"\n\t}\n\treturn event.Label(ctx, StatusCode.Of(status))\n}\n"
  },
  {
    "path": "internal/jsonrpc2/handler.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// Handler is invoked to handle incoming requests.\n// The Replier sends a reply to the request and must be called exactly once.\ntype Handler func(ctx context.Context, reply Replier, req Request) error\n\n// Replier is passed to handlers to allow them to reply to the request.\n// If err is set then result will be ignored.\ntype Replier func(ctx context.Context, result any, err error) error\n\n// MethodNotFound is a Handler that replies to all call requests with the\n// standard method not found response.\n// This should normally be the final handler in a chain.\nfunc MethodNotFound(ctx context.Context, reply Replier, req Request) error {\n\treturn reply(ctx, nil, fmt.Errorf(\"%w: %q\", ErrMethodNotFound, req.Method()))\n}\n\n// MustReplyHandler is a middleware that creates a Handler that panics if the\n// wrapped handler does not call Reply for every request that it is passed.\nfunc MustReplyHandler(handler Handler) Handler {\n\treturn func(ctx context.Context, reply Replier, req Request) error {\n\t\tcalled := false\n\t\terr := handler(ctx, func(ctx context.Context, result any, err error) error {\n\t\t\tif called {\n\t\t\t\tpanic(fmt.Errorf(\"request %q replied to more than once\", req.Method()))\n\t\t\t}\n\t\t\tcalled = true\n\t\t\treturn reply(ctx, result, err)\n\t\t}, req)\n\t\tif !called {\n\t\t\tpanic(fmt.Errorf(\"request %q was never replied to\", req.Method()))\n\t\t}\n\t\treturn err\n\t}\n}\n\n// CancelHandler returns a handler that supports cancellation, and a function\n// that can be used to trigger canceling in progress requests.\nfunc CancelHandler(handler Handler) (Handler, func(id ID)) {\n\tvar mu sync.Mutex\n\thandling := make(map[ID]context.CancelFunc)\n\twrapped := func(ctx context.Context, reply Replier, req Request) error {\n\t\tif call, ok := req.(*Call); ok {\n\t\t\tcancelCtx, cancel := context.WithCancel(ctx)\n\t\t\tctx = cancelCtx\n\t\t\tmu.Lock()\n\t\t\thandling[call.ID()] = cancel\n\t\t\tmu.Unlock()\n\t\t\tinnerReply := reply\n\t\t\treply = func(ctx context.Context, result any, err error) error {\n\t\t\t\tmu.Lock()\n\t\t\t\tdelete(handling, call.ID())\n\t\t\t\tmu.Unlock()\n\t\t\t\treturn innerReply(ctx, result, err)\n\t\t\t}\n\t\t}\n\t\treturn handler(ctx, reply, req)\n\t}\n\treturn wrapped, func(id ID) {\n\t\tmu.Lock()\n\t\tcancel, found := handling[id]\n\t\tmu.Unlock()\n\t\tif found {\n\t\t\tcancel()\n\t\t}\n\t}\n}\n\n// AsyncHandler is a middleware that returns a handler that processes each\n// request goes in its own goroutine.\n// The handler returns immediately, without the request being processed.\n// Each request then waits for the previous request to finish before it starts.\n// This allows the stream to unblock at the cost of unbounded goroutines\n// all stalled on the previous one.\nfunc AsyncHandler(handler Handler) Handler {\n\tnextRequest := make(chan struct{})\n\tclose(nextRequest)\n\treturn func(ctx context.Context, reply Replier, req Request) error {\n\t\twaitForPrevious := nextRequest\n\t\tnextRequest = make(chan struct{})\n\t\treleaser := &releaser{ch: nextRequest}\n\t\tinnerReply := reply\n\t\treply = func(ctx context.Context, result any, err error) error {\n\t\t\treleaser.release(true)\n\t\t\treturn innerReply(ctx, result, err)\n\t\t}\n\t\t_, queueDone := event.Start(ctx, \"queued\")\n\t\tctx = context.WithValue(ctx, asyncKey, releaser)\n\t\tgo func() {\n\t\t\t<-waitForPrevious\n\t\t\tqueueDone()\n\t\t\tif err := handler(ctx, reply, req); err != nil {\n\t\t\t\tevent.Error(ctx, \"jsonrpc2 async message delivery failed\", err)\n\t\t\t}\n\t\t}()\n\t\treturn nil\n\t}\n}\n\n// Async, when used with the [AsyncHandler] middleware, indicates that the\n// current jsonrpc2 request may be handled asynchronously to subsequent\n// requests.\n//\n// When not used with an AsyncHandler, Async is a no-op.\n//\n// Async must be called at most once on each request's context (and its\n// descendants).\nfunc Async(ctx context.Context) {\n\tif r, ok := ctx.Value(asyncKey).(*releaser); ok {\n\t\tr.release(false)\n\t}\n}\n\ntype asyncKeyType struct{}\n\nvar asyncKey = asyncKeyType{}\n\n// A releaser implements concurrency safe 'releasing' of async requests. (A\n// request is released when it is allowed to run concurrent with other\n// requests, via a call to [Async].)\ntype releaser struct {\n\tmu       sync.Mutex\n\tch       chan struct{}\n\treleased bool\n}\n\n// release closes the associated channel. If soft is set, multiple calls to\n// release are allowed.\nfunc (r *releaser) release(soft bool) {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\n\tif r.released {\n\t\tif !soft {\n\t\t\tpanic(\"jsonrpc2.Async called multiple times\")\n\t\t}\n\t} else {\n\t\tclose(r.ch)\n\t\tr.released = true\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2/jsonrpc2.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.\n// https://www.jsonrpc.org/specification\n// It is intended to be compatible with other implementations at the wire level.\npackage jsonrpc2\n\nconst (\n\t// ErrIdleTimeout is returned when serving timed out waiting for new connections.\n\tErrIdleTimeout = constError(\"timed out waiting for new connections\")\n)\n\ntype constError string\n\nfunc (e constError) Error() string { return string(e) }\n"
  },
  {
    "path": "internal/jsonrpc2/jsonrpc2_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"net\"\n\t\"path\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/event/export/eventtest\"\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n\t\"golang.org/x/tools/internal/jsonrpc2/stack/stacktest\"\n)\n\nvar logRPC = flag.Bool(\"logrpc\", false, \"Enable jsonrpc2 communication logging\")\n\ntype callTest struct {\n\tmethod string\n\tparams any\n\texpect any\n}\n\nvar callTests = []callTest{\n\t{\"no_args\", nil, true},\n\t{\"one_string\", \"fish\", \"got:fish\"},\n\t{\"one_number\", 10, \"got:10\"},\n\t{\"join\", []string{\"a\", \"b\", \"c\"}, \"a/b/c\"},\n\t//TODO: expand the test cases\n}\n\nfunc (test *callTest) newResults() any {\n\tswitch e := test.expect.(type) {\n\tcase []any:\n\t\tvar r []any\n\t\tfor _, v := range e {\n\t\t\tr = append(r, reflect.New(reflect.TypeOf(v)).Interface())\n\t\t}\n\t\treturn r\n\tcase nil:\n\t\treturn nil\n\tdefault:\n\t\treturn reflect.New(reflect.TypeOf(test.expect)).Interface()\n\t}\n}\n\nfunc (test *callTest) verifyResults(t *testing.T, results any) {\n\tif results == nil {\n\t\treturn\n\t}\n\tval := reflect.Indirect(reflect.ValueOf(results)).Interface()\n\tif !reflect.DeepEqual(val, test.expect) {\n\t\tt.Errorf(\"%v:Results are incorrect, got %+v expect %+v\", test.method, val, test.expect)\n\t}\n}\n\nfunc TestCall(t *testing.T) {\n\tstacktest.NoLeak(t)\n\tctx := eventtest.NewContext(context.Background(), t)\n\tfor _, headers := range []bool{false, true} {\n\t\tname := \"Plain\"\n\t\tif headers {\n\t\t\tname = \"Headers\"\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tctx := eventtest.NewContext(ctx, t)\n\t\t\ta, b, done := prepare(ctx, headers)\n\t\t\tdefer done()\n\t\t\tfor _, test := range callTests {\n\t\t\t\tt.Run(test.method, func(t *testing.T) {\n\t\t\t\t\tctx := eventtest.NewContext(ctx, t)\n\t\t\t\t\tresults := test.newResults()\n\t\t\t\t\tif _, err := a.Call(ctx, test.method, test.params, results); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"%v:Call failed: %v\", test.method, err)\n\t\t\t\t\t}\n\t\t\t\t\ttest.verifyResults(t, results)\n\t\t\t\t\tif _, err := b.Call(ctx, test.method, test.params, results); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"%v:Call failed: %v\", test.method, err)\n\t\t\t\t\t}\n\t\t\t\t\ttest.verifyResults(t, results)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc prepare(ctx context.Context, withHeaders bool) (jsonrpc2.Conn, jsonrpc2.Conn, func()) {\n\t// make a wait group that can be used to wait for the system to shut down\n\taPipe, bPipe := net.Pipe()\n\ta := run(ctx, withHeaders, aPipe)\n\tb := run(ctx, withHeaders, bPipe)\n\treturn a, b, func() {\n\t\ta.Close()\n\t\tb.Close()\n\t\t<-a.Done()\n\t\t<-b.Done()\n\t}\n}\n\nfunc run(ctx context.Context, withHeaders bool, nc net.Conn) jsonrpc2.Conn {\n\tvar stream jsonrpc2.Stream\n\tif withHeaders {\n\t\tstream = jsonrpc2.NewHeaderStream(nc)\n\t} else {\n\t\tstream = jsonrpc2.NewRawStream(nc)\n\t}\n\tconn := jsonrpc2.NewConn(stream)\n\tconn.Go(ctx, testHandler())\n\treturn conn\n}\n\nfunc testHandler() jsonrpc2.Handler {\n\treturn func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\t\tswitch req.Method() {\n\t\tcase \"no_args\":\n\t\t\tif len(req.Params()) > 0 {\n\t\t\t\treturn reply(ctx, nil, fmt.Errorf(\"%w: expected no params\", jsonrpc2.ErrInvalidParams))\n\t\t\t}\n\t\t\treturn reply(ctx, true, nil)\n\t\tcase \"one_string\":\n\t\t\tvar v string\n\t\t\tif err := json.Unmarshal(req.Params(), &v); err != nil {\n\t\t\t\treturn reply(ctx, nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err))\n\t\t\t}\n\t\t\treturn reply(ctx, \"got:\"+v, nil)\n\t\tcase \"one_number\":\n\t\t\tvar v int\n\t\t\tif err := json.Unmarshal(req.Params(), &v); err != nil {\n\t\t\t\treturn reply(ctx, nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err))\n\t\t\t}\n\t\t\treturn reply(ctx, fmt.Sprintf(\"got:%d\", v), nil)\n\t\tcase \"join\":\n\t\t\tvar v []string\n\t\t\tif err := json.Unmarshal(req.Params(), &v); err != nil {\n\t\t\t\treturn reply(ctx, nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err))\n\t\t\t}\n\t\t\treturn reply(ctx, path.Join(v...), nil)\n\t\tdefault:\n\t\t\treturn jsonrpc2.MethodNotFound(ctx, reply, req)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2/labels.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport \"golang.org/x/tools/internal/event/keys\"\n\n// These keys are used for creating labels to instrument jsonrpc2 events.\nvar (\n\tMethod        = keys.NewString(\"method\", \"\")\n\tRPCID         = keys.NewString(\"id\", \"\")\n\tRPCDirection  = keys.NewString(\"direction\", \"\")\n\tStarted       = keys.NewInt(\"started\", \"count of started RPCs\")\n\tSentBytes     = keys.NewInt(\"sent_bytes\", \"bytes sent\")\n\tReceivedBytes = keys.NewInt(\"received_bytes\", \"bytes received\")\n\tStatusCode    = keys.NewString(\"status.code\", \"\")\n\tLatency       = keys.NewFloat(\"latency\", \"elapsed time in seconds\")\n)\n\nconst (\n\tInbound  = \"in\"\n\tOutbound = \"out\"\n)\n"
  },
  {
    "path": "internal/jsonrpc2/messages.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Message is the interface to all jsonrpc2 message types.\n// They share no common functionality, but are a closed set of concrete types\n// that are allowed to implement this interface. The message types are *Call,\n// *Notification and *Response.\ntype Message interface {\n\t// isJSONRPC2Message is used to make the set of message implementations a\n\t// closed set.\n\tisJSONRPC2Message()\n}\n\n// Request is the shared interface to jsonrpc2 messages that request\n// a method be invoked.\n// The request types are a closed set of *Call and *Notification.\ntype Request interface {\n\tMessage\n\t// Method is a string containing the method name to invoke.\n\tMethod() string\n\t// Params is a JSON value (object, array, null, or \"\") with the parameters of the method.\n\tParams() json.RawMessage\n\t// isJSONRPC2Request is used to make the set of request implementations closed.\n\tisJSONRPC2Request()\n}\n\n// Notification is a request for which a response cannot occur, and as such\n// it has not ID.\ntype Notification struct {\n\t// Method is a string containing the method name to invoke.\n\tmethod string\n\tparams json.RawMessage\n}\n\n// Call is a request that expects a response.\n// The response will have a matching ID.\ntype Call struct {\n\t// Method is a string containing the method name to invoke.\n\tmethod string\n\t// Params is a JSON value (object, array, null, or \"\") with the parameters of the method.\n\tparams json.RawMessage\n\t// id of this request, used to tie the Response back to the request.\n\tid ID\n}\n\n// Response is a reply to a Call.\n// It will have the same ID as the call it is a response to.\ntype Response struct {\n\t// result is the content of the response.\n\tresult json.RawMessage\n\t// err is set only if the call failed.\n\terr error\n\t// ID of the request this is a response to.\n\tid ID\n}\n\n// NewNotification constructs a new Notification message for the supplied\n// method and parameters.\nfunc NewNotification(method string, params any) (*Notification, error) {\n\tp, merr := marshalToRaw(params)\n\treturn &Notification{method: method, params: p}, merr\n}\n\nfunc (msg *Notification) Method() string          { return msg.method }\nfunc (msg *Notification) Params() json.RawMessage { return msg.params }\nfunc (msg *Notification) isJSONRPC2Message()      {}\nfunc (msg *Notification) isJSONRPC2Request()      {}\n\nfunc (n *Notification) MarshalJSON() ([]byte, error) {\n\tmsg := wireRequest{Method: n.method, Params: &n.params}\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn data, fmt.Errorf(\"marshaling notification: %w\", err)\n\t}\n\treturn data, nil\n}\n\nfunc (n *Notification) UnmarshalJSON(data []byte) error {\n\tmsg := wireRequest{}\n\tif err := json.Unmarshal(data, &msg); err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling notification: %w\", err)\n\t}\n\tn.method = msg.Method\n\tif msg.Params != nil {\n\t\tn.params = *msg.Params\n\t}\n\treturn nil\n}\n\n// NewCall constructs a new Call message for the supplied ID, method and\n// parameters.\nfunc NewCall(id ID, method string, params any) (*Call, error) {\n\tp, merr := marshalToRaw(params)\n\treturn &Call{id: id, method: method, params: p}, merr\n}\n\nfunc (msg *Call) Method() string          { return msg.method }\nfunc (msg *Call) Params() json.RawMessage { return msg.params }\nfunc (msg *Call) ID() ID                  { return msg.id }\nfunc (msg *Call) isJSONRPC2Message()      {}\nfunc (msg *Call) isJSONRPC2Request()      {}\n\nfunc (c *Call) MarshalJSON() ([]byte, error) {\n\tmsg := wireRequest{Method: c.method, Params: &c.params, ID: &c.id}\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn data, fmt.Errorf(\"marshaling call: %w\", err)\n\t}\n\treturn data, nil\n}\n\nfunc (c *Call) UnmarshalJSON(data []byte) error {\n\tmsg := wireRequest{}\n\tif err := json.Unmarshal(data, &msg); err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling call: %w\", err)\n\t}\n\tc.method = msg.Method\n\tif msg.Params != nil {\n\t\tc.params = *msg.Params\n\t}\n\tif msg.ID != nil {\n\t\tc.id = *msg.ID\n\t}\n\treturn nil\n}\n\n// NewResponse constructs a new Response message that is a reply to the\n// supplied. If err is set result may be ignored.\nfunc NewResponse(id ID, result any, err error) (*Response, error) {\n\tr, merr := marshalToRaw(result)\n\treturn &Response{id: id, result: r, err: err}, merr\n}\n\nfunc (msg *Response) ID() ID                  { return msg.id }\nfunc (msg *Response) Result() json.RawMessage { return msg.result }\nfunc (msg *Response) Err() error              { return msg.err }\nfunc (msg *Response) isJSONRPC2Message()      {}\n\nfunc (r *Response) MarshalJSON() ([]byte, error) {\n\tmsg := &wireResponse{Error: toWireError(r.err), ID: &r.id}\n\tif msg.Error == nil {\n\t\tmsg.Result = &r.result\n\t}\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn data, fmt.Errorf(\"marshaling notification: %w\", err)\n\t}\n\treturn data, nil\n}\n\nfunc toWireError(err error) *WireError {\n\tif err == nil {\n\t\t// no error, the response is complete\n\t\treturn nil\n\t}\n\tif err, ok := err.(*WireError); ok {\n\t\t// already a wire error, just use it\n\t\treturn err\n\t}\n\tresult := &WireError{Message: err.Error()}\n\tvar wrapped *WireError\n\tif errors.As(err, &wrapped) {\n\t\t// if we wrapped a wire error, keep the code from the wrapped error\n\t\t// but the message from the outer error\n\t\tresult.Code = wrapped.Code\n\t}\n\treturn result\n}\n\nfunc (r *Response) UnmarshalJSON(data []byte) error {\n\tmsg := wireResponse{}\n\tif err := json.Unmarshal(data, &msg); err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling jsonrpc response: %w\", err)\n\t}\n\tif msg.Result != nil {\n\t\tr.result = *msg.Result\n\t}\n\tif msg.Error != nil {\n\t\tr.err = msg.Error\n\t}\n\tif msg.ID != nil {\n\t\tr.id = *msg.ID\n\t}\n\treturn nil\n}\n\nfunc DecodeMessage(data []byte) (Message, error) {\n\tmsg := wireCombined{}\n\tif err := json.Unmarshal(data, &msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshaling jsonrpc message: %w\", err)\n\t}\n\tif msg.Method == \"\" {\n\t\t// no method, should be a response\n\t\tif msg.ID == nil {\n\t\t\treturn nil, ErrInvalidRequest\n\t\t}\n\t\tresponse := &Response{id: *msg.ID}\n\t\tif msg.Error != nil {\n\t\t\tresponse.err = msg.Error\n\t\t}\n\t\tif msg.Result != nil {\n\t\t\tresponse.result = *msg.Result\n\t\t}\n\t\treturn response, nil\n\t}\n\t// has a method, must be a request\n\tif msg.ID == nil {\n\t\t// request with no ID is a notify\n\t\tnotify := &Notification{method: msg.Method}\n\t\tif msg.Params != nil {\n\t\t\tnotify.params = *msg.Params\n\t\t}\n\t\treturn notify, nil\n\t}\n\t// request with an ID, must be a call\n\tcall := &Call{method: msg.Method, id: *msg.ID}\n\tif msg.Params != nil {\n\t\tcall.params = *msg.Params\n\t}\n\treturn call, nil\n}\n\nfunc marshalToRaw(obj any) (json.RawMessage, error) {\n\tdata, err := json.Marshal(obj)\n\tif err != nil {\n\t\treturn json.RawMessage{}, err\n\t}\n\treturn json.RawMessage(data), nil\n}\n"
  },
  {
    "path": "internal/jsonrpc2/serve.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"math\"\n\t\"net\"\n\t\"os\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/event\"\n)\n\n// NOTE: This file provides an experimental API for serving multiple remote\n// jsonrpc2 clients over the network. For now, it is intentionally similar to\n// net/http, but that may change in the future as we figure out the correct\n// semantics.\n\n// A StreamServer is used to serve incoming jsonrpc2 clients communicating over\n// a newly created connection.\ntype StreamServer interface {\n\tServeStream(context.Context, Conn) error\n}\n\n// The ServerFunc type is an adapter that implements the StreamServer interface\n// using an ordinary function.\ntype ServerFunc func(context.Context, Conn) error\n\n// ServeStream calls f(ctx, s).\nfunc (f ServerFunc) ServeStream(ctx context.Context, c Conn) error {\n\treturn f(ctx, c)\n}\n\n// HandlerServer returns a StreamServer that handles incoming streams using the\n// provided handler.\nfunc HandlerServer(h Handler) StreamServer {\n\treturn ServerFunc(func(ctx context.Context, conn Conn) error {\n\t\tconn.Go(ctx, h)\n\t\t<-conn.Done()\n\t\treturn conn.Err()\n\t})\n}\n\n// ListenAndServe starts a jsonrpc2 server on the given address.  If\n// idleTimeout is non-zero, ListenAndServe exits after there are no clients for\n// this duration, otherwise it exits only on error.\nfunc ListenAndServe(ctx context.Context, network, addr string, server StreamServer, idleTimeout time.Duration) error {\n\tln, err := net.Listen(network, addr)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer ln.Close()\n\tif network == \"unix\" {\n\t\tdefer os.Remove(addr)\n\t}\n\treturn Serve(ctx, ln, server, idleTimeout)\n}\n\n// Serve accepts incoming connections from the network, and handles them using\n// the provided server. If idleTimeout is non-zero, ListenAndServe exits after\n// there are no clients for this duration, otherwise it exits only on error.\nfunc Serve(ctx context.Context, ln net.Listener, server StreamServer, idleTimeout time.Duration) error {\n\tnewConns := make(chan net.Conn)\n\tclosedConns := make(chan error)\n\tactiveConns := 0\n\tvar acceptErr error\n\tgo func() {\n\t\tdefer close(newConns)\n\t\tfor {\n\t\t\tvar nc net.Conn\n\t\t\tnc, acceptErr = ln.Accept()\n\t\t\tif acceptErr != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tnewConns <- nc\n\t\t}\n\t}()\n\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer func() {\n\t\t// Signal the Accept goroutine to stop immediately\n\t\t// and terminate all newly-accepted connections until it returns.\n\t\tln.Close()\n\t\tfor nc := range newConns {\n\t\t\tnc.Close()\n\t\t}\n\t\t// Cancel pending ServeStream callbacks and wait for them to finish.\n\t\tcancel()\n\t\tfor activeConns > 0 {\n\t\t\terr := <-closedConns\n\t\t\tif !isClosingError(err) {\n\t\t\t\tevent.Error(ctx, \"closed a connection\", err)\n\t\t\t}\n\t\t\tactiveConns--\n\t\t}\n\t}()\n\n\t// Max duration: ~290 years; surely that's long enough.\n\tconst forever = math.MaxInt64\n\tif idleTimeout <= 0 {\n\t\tidleTimeout = forever\n\t}\n\tconnTimer := time.NewTimer(idleTimeout)\n\tdefer connTimer.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase netConn, ok := <-newConns:\n\t\t\tif !ok {\n\t\t\t\treturn acceptErr\n\t\t\t}\n\t\t\tif activeConns == 0 && !connTimer.Stop() {\n\t\t\t\t// connTimer.C may receive a value even after Stop returns.\n\t\t\t\t// (See https://golang.org/issue/37196.)\n\t\t\t\t<-connTimer.C\n\t\t\t}\n\t\t\tactiveConns++\n\t\t\tstream := NewHeaderStream(netConn)\n\t\t\tgo func() {\n\t\t\t\tconn := NewConn(stream)\n\t\t\t\terr := server.ServeStream(ctx, conn)\n\t\t\t\tstream.Close()\n\t\t\t\tclosedConns <- err\n\t\t\t}()\n\n\t\tcase err := <-closedConns:\n\t\t\tif !isClosingError(err) {\n\t\t\t\tevent.Error(ctx, \"closed a connection\", err)\n\t\t\t}\n\t\t\tactiveConns--\n\t\t\tif activeConns == 0 {\n\t\t\t\tconnTimer.Reset(idleTimeout)\n\t\t\t}\n\n\t\tcase <-connTimer.C:\n\t\t\treturn ErrIdleTimeout\n\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\t}\n\t}\n}\n\n// isClosingError reports if the error occurs normally during the process of\n// closing a network connection. It uses imperfect heuristics that err on the\n// side of false negatives, and should not be used for anything critical.\nfunc isClosingError(err error) bool {\n\tif errors.Is(err, io.EOF) {\n\t\treturn true\n\t}\n\t// Per https://github.com/golang/go/issues/4373, this error string should not\n\t// change. This is not ideal, but since the worst that could happen here is\n\t// some superfluous logging, it is acceptable.\n\tif err.Error() == \"use of closed network connection\" {\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/jsonrpc2/serve_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2/stack/stacktest\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestIdleTimeout(t *testing.T) {\n\ttestenv.NeedsLocalhostNet(t)\n\n\tstacktest.NoLeak(t)\n\tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n\tdefer cancel()\n\n\tln, err := net.Listen(\"tcp\", \"localhost:0\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer ln.Close()\n\n\tconnect := func() net.Conn {\n\t\tconn, err := net.DialTimeout(\"tcp\", ln.Addr().String(), 5*time.Second)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn conn\n\t}\n\n\tserver := HandlerServer(MethodNotFound)\n\t// connTimer := &fakeTimer{c: make(chan time.Time, 1)}\n\tvar (\n\t\trunErr error\n\t\twg     sync.WaitGroup\n\t)\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\trunErr = Serve(ctx, ln, server, 100*time.Millisecond)\n\t}()\n\n\t// Exercise some connection/disconnection patterns, and then assert that when\n\t// our timer fires, the server exits.\n\tconn1 := connect()\n\tconn2 := connect()\n\tconn1.Close()\n\tconn2.Close()\n\tconn3 := connect()\n\tconn3.Close()\n\n\twg.Wait()\n\n\tif runErr != ErrIdleTimeout {\n\t\tt.Errorf(\"run() returned error %v, want %v\", runErr, ErrIdleTimeout)\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2/servertest/servertest.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package servertest provides utilities for running tests against a remote LSP\n// server.\npackage servertest\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\n// Connector is the interface used to connect to a server.\ntype Connector interface {\n\tConnect(context.Context) jsonrpc2.Conn\n}\n\n// TCPServer is a helper for executing tests against a remote jsonrpc2\n// connection. Once initialized, its Addr field may be used to connect a\n// jsonrpc2 client.\ntype TCPServer struct {\n\t*connList\n\n\tAddr string\n\n\tln     net.Listener\n\tframer jsonrpc2.Framer\n}\n\n// NewTCPServer returns a new test server listening on local tcp port and\n// serving incoming jsonrpc2 streams using the provided stream server. It\n// panics on any error.\nfunc NewTCPServer(ctx context.Context, server jsonrpc2.StreamServer, framer jsonrpc2.Framer) *TCPServer {\n\tln, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"servertest: failed to listen: %v\", err))\n\t}\n\tif framer == nil {\n\t\tframer = jsonrpc2.NewHeaderStream\n\t}\n\tgo jsonrpc2.Serve(ctx, ln, server, 0)\n\treturn &TCPServer{Addr: ln.Addr().String(), ln: ln, framer: framer, connList: &connList{}}\n}\n\n// Connect dials the test server and returns a jsonrpc2 Connection that is\n// ready for use.\nfunc (s *TCPServer) Connect(_ context.Context) jsonrpc2.Conn {\n\tnetConn, err := net.Dial(\"tcp\", s.Addr)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"servertest: failed to connect to test instance: %v\", err))\n\t}\n\tconn := jsonrpc2.NewConn(s.framer(netConn))\n\ts.add(conn)\n\treturn conn\n}\n\n// PipeServer is a test server that handles connections over io.Pipes.\ntype PipeServer struct {\n\t*connList\n\tserver jsonrpc2.StreamServer\n\tframer jsonrpc2.Framer\n}\n\n// NewPipeServer returns a test server that can be connected to via io.Pipes.\nfunc NewPipeServer(server jsonrpc2.StreamServer, framer jsonrpc2.Framer) *PipeServer {\n\tif framer == nil {\n\t\tframer = jsonrpc2.NewRawStream\n\t}\n\treturn &PipeServer{server: server, framer: framer, connList: &connList{}}\n}\n\n// Connect creates new io.Pipes and binds them to the underlying StreamServer.\nfunc (s *PipeServer) Connect(ctx context.Context) jsonrpc2.Conn {\n\tsPipe, cPipe := net.Pipe()\n\tserverStream := s.framer(sPipe)\n\tserverConn := jsonrpc2.NewConn(serverStream)\n\ts.add(serverConn)\n\tgo s.server.ServeStream(ctx, serverConn)\n\n\tclientStream := s.framer(cPipe)\n\tclientConn := jsonrpc2.NewConn(clientStream)\n\ts.add(clientConn)\n\treturn clientConn\n}\n\n// connList tracks closers to run when a testserver is closed.  This is a\n// convenience, so that callers don't have to worry about closing each\n// connection.\ntype connList struct {\n\tmu    sync.Mutex\n\tconns []jsonrpc2.Conn\n}\n\nfunc (l *connList) add(conn jsonrpc2.Conn) {\n\tl.mu.Lock()\n\tdefer l.mu.Unlock()\n\tl.conns = append(l.conns, conn)\n}\n\nfunc (l *connList) Close() error {\n\tl.mu.Lock()\n\tdefer l.mu.Unlock()\n\tvar errmsgs []string\n\tfor _, conn := range l.conns {\n\t\tif err := conn.Close(); err != nil {\n\t\t\terrmsgs = append(errmsgs, err.Error())\n\t\t}\n\t}\n\tif len(errmsgs) > 0 {\n\t\treturn fmt.Errorf(\"closing errors:\\n%s\", strings.Join(errmsgs, \"\\n\"))\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/jsonrpc2/servertest/servertest_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage servertest\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\ntype msg struct {\n\tMsg string\n}\n\nfunc fakeHandler(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {\n\treturn reply(ctx, &msg{\"pong\"}, nil)\n}\n\nfunc TestTestServer(t *testing.T) {\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\tserver := jsonrpc2.HandlerServer(fakeHandler)\n\ttcpTS := NewTCPServer(ctx, server, nil)\n\tdefer tcpTS.Close()\n\tpipeTS := NewPipeServer(server, nil)\n\tdefer pipeTS.Close()\n\n\ttests := []struct {\n\t\tname      string\n\t\tconnector Connector\n\t}{\n\t\t{\"tcp\", tcpTS},\n\t\t{\"pipe\", pipeTS},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tconn := test.connector.Connect(ctx)\n\t\t\tconn.Go(ctx, jsonrpc2.MethodNotFound)\n\t\t\tvar got msg\n\t\t\tif _, err := conn.Call(ctx, \"ping\", &msg{\"ping\"}, &got); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif want := \"pong\"; got.Msg != want {\n\t\t\t\tt.Errorf(\"conn.Call(...): returned %q, want %q\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stack/parse.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stack\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"regexp\"\n\t\"strconv\"\n)\n\nvar (\n\treBlank     = regexp.MustCompile(`^\\s*$`)\n\treGoroutine = regexp.MustCompile(`^\\s*goroutine (\\d+) \\[([^\\]]*)\\]:\\s*$`)\n\treCall      = regexp.MustCompile(`^\\s*` +\n\t\t`(created by )?` + //marker\n\t\t`(([\\w/.]+/)?[\\w]+)\\.` + //package\n\t\t`(\\(([^:.)]*)\\)\\.)?` + //optional type\n\t\t`([\\w\\.]+)` + //function\n\t\t`(\\(.*\\))?` + // args\n\t\t`\\s*$`)\n\trePos = regexp.MustCompile(`^\\s*(.*):(\\d+)( .*)?$`)\n)\n\n// Scanner splits an input stream into lines in a way that is consumable by\n// the parser.\ntype Scanner struct {\n\tlines *bufio.Scanner\n\tdone  bool\n}\n\n// NewScanner creates a scanner on top of a reader.\nfunc NewScanner(r io.Reader) *Scanner {\n\ts := &Scanner{\n\t\tlines: bufio.NewScanner(r),\n\t}\n\ts.Skip() // prefill\n\treturn s\n}\n\n// Peek returns the next line without consuming it.\nfunc (s *Scanner) Peek() string {\n\tif s.done {\n\t\treturn \"\"\n\t}\n\treturn s.lines.Text()\n}\n\n// Skip consumes the next line without looking at it.\n// Normally used after it has already been looked at using Peek.\nfunc (s *Scanner) Skip() {\n\tif !s.lines.Scan() {\n\t\ts.done = true\n\t}\n}\n\n// Next consumes and returns the next line.\nfunc (s *Scanner) Next() string {\n\tline := s.Peek()\n\ts.Skip()\n\treturn line\n}\n\n// Done returns true if the scanner has reached the end of the underlying\n// stream.\nfunc (s *Scanner) Done() bool {\n\treturn s.done\n}\n\n// Err returns true if the scanner has reached the end of the underlying\n// stream.\nfunc (s *Scanner) Err() error {\n\treturn s.lines.Err()\n}\n\n// Match returns the submatchs of the regular expression against the next line.\n// If it matched the line is also consumed.\nfunc (s *Scanner) Match(re *regexp.Regexp) []string {\n\tif s.done {\n\t\treturn nil\n\t}\n\tmatch := re.FindStringSubmatch(s.Peek())\n\tif match != nil {\n\t\ts.Skip()\n\t}\n\treturn match\n}\n\n// SkipBlank skips any number of pure whitespace lines.\nfunc (s *Scanner) SkipBlank() {\n\tfor !s.done {\n\t\tline := s.Peek()\n\t\tif len(line) != 0 && !reBlank.MatchString(line) {\n\t\t\treturn\n\t\t}\n\t\ts.Skip()\n\t}\n}\n\n// Parse the current contiguous block of goroutine stack traces until the\n// scanned content no longer matches.\nfunc Parse(scanner *Scanner) (Dump, error) {\n\tdump := Dump{}\n\tfor {\n\t\tgr, ok := parseGoroutine(scanner)\n\t\tif !ok {\n\t\t\treturn dump, nil\n\t\t}\n\t\tdump = append(dump, gr)\n\t}\n}\n\nfunc parseGoroutine(scanner *Scanner) (Goroutine, bool) {\n\tmatch := scanner.Match(reGoroutine)\n\tif match == nil {\n\t\treturn Goroutine{}, false\n\t}\n\tid, _ := strconv.ParseInt(match[1], 0, 32)\n\tgr := Goroutine{\n\t\tID:    int(id),\n\t\tState: match[2],\n\t}\n\tfor {\n\t\tframe, ok := parseFrame(scanner)\n\t\tif !ok {\n\t\t\tscanner.SkipBlank()\n\t\t\treturn gr, true\n\t\t}\n\t\tif frame.Position.Filename != \"\" {\n\t\t\tgr.Stack = append(gr.Stack, frame)\n\t\t}\n\t}\n}\n\nfunc parseFrame(scanner *Scanner) (Frame, bool) {\n\tfun, ok := parseFunction(scanner)\n\tif !ok {\n\t\treturn Frame{}, false\n\t}\n\tframe := Frame{\n\t\tFunction: fun,\n\t}\n\tframe.Position, ok = parsePosition(scanner)\n\t// if ok is false, then this is a broken state.\n\t// we got the func but not the file that must follow\n\t// the consumed line can be recovered from the frame\n\t//TODO: push back the fun raw\n\treturn frame, ok\n}\n\nfunc parseFunction(scanner *Scanner) (Function, bool) {\n\tmatch := scanner.Match(reCall)\n\tif match == nil {\n\t\treturn Function{}, false\n\t}\n\treturn Function{\n\t\tPackage: match[2],\n\t\tType:    match[5],\n\t\tName:    match[6],\n\t}, true\n}\n\nfunc parsePosition(scanner *Scanner) (Position, bool) {\n\tmatch := scanner.Match(rePos)\n\tif match == nil {\n\t\treturn Position{}, false\n\t}\n\tline, _ := strconv.ParseInt(match[2], 0, 32)\n\treturn Position{Filename: match[1], Line: int(line)}, true\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stack/process.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stack\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"runtime\"\n\t\"sort\"\n)\n\n// Capture get the current stack traces from the runtime.\nfunc Capture() Dump {\n\tbuf := make([]byte, 2<<20)\n\tbuf = buf[:runtime.Stack(buf, true)]\n\tscanner := NewScanner(bytes.NewReader(buf))\n\tdump, _ := Parse(scanner)\n\treturn dump\n}\n\n// Summarize a dump for easier consumption.\n// This collates goroutines with equivalent stacks.\nfunc Summarize(dump Dump) Summary {\n\ts := Summary{\n\t\tTotal: len(dump),\n\t}\n\tfor _, gr := range dump {\n\t\ts.addGoroutine(gr)\n\t}\n\treturn s\n}\n\n// Process and input stream to an output stream, summarizing any stacks that\n// are detected in place.\nfunc Process(out io.Writer, in io.Reader) error {\n\tscanner := NewScanner(in)\n\tfor {\n\t\tdump, err := Parse(scanner)\n\t\tsummary := Summarize(dump)\n\t\tswitch {\n\t\tcase len(dump) > 0:\n\t\t\tfmt.Fprintf(out, \"%+v\\n\\n\", summary)\n\t\tcase err != nil:\n\t\t\treturn err\n\t\tcase scanner.Done():\n\t\t\treturn scanner.Err()\n\t\tdefault:\n\t\t\t// must have been a line that is not part of a dump\n\t\t\tfmt.Fprintln(out, scanner.Next())\n\t\t}\n\t}\n}\n\n// Diff calculates the delta between two dumps.\nfunc Diff(before, after Dump) Delta {\n\tresult := Delta{}\n\tprocessed := make(map[int]bool)\n\tfor _, gr := range before {\n\t\tprocessed[gr.ID] = false\n\t}\n\tfor _, gr := range after {\n\t\tif _, found := processed[gr.ID]; found {\n\t\t\tresult.Shared = append(result.Shared, gr)\n\t\t} else {\n\t\t\tresult.After = append(result.After, gr)\n\t\t}\n\t\tprocessed[gr.ID] = true\n\t}\n\tfor _, gr := range before {\n\t\tif done := processed[gr.ID]; !done {\n\t\t\tresult.Before = append(result.Before, gr)\n\t\t}\n\t}\n\treturn result\n}\n\n// TODO: do we want to allow contraction of stacks before comparison?\nfunc (s *Summary) addGoroutine(gr Goroutine) {\n\tindex := sort.Search(len(s.Calls), func(i int) bool {\n\t\treturn !s.Calls[i].Stack.less(gr.Stack)\n\t})\n\tif index >= len(s.Calls) || !s.Calls[index].Stack.equal(gr.Stack) {\n\t\t// insert new stack, first increase the length\n\t\ts.Calls = append(s.Calls, Call{})\n\t\t// move the top part upward to make space\n\t\tcopy(s.Calls[index+1:], s.Calls[index:])\n\t\t// insert the new call\n\t\ts.Calls[index] = Call{\n\t\t\tStack: gr.Stack,\n\t\t}\n\t}\n\t// merge the goroutine into the matched call\n\ts.Calls[index].merge(gr)\n}\n\n// TODO: do we want other grouping strategies?\nfunc (c *Call) merge(gr Goroutine) {\n\tfor i := range c.Groups {\n\t\tcanditate := &c.Groups[i]\n\t\tif canditate.State == gr.State {\n\t\t\tcanditate.Goroutines = append(canditate.Goroutines, gr)\n\t\t\treturn\n\t\t}\n\t}\n\tc.Groups = append(c.Groups, Group{\n\t\tState:      gr.State,\n\t\tGoroutines: []Goroutine{gr},\n\t})\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stack/stack.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package stack provides support for parsing standard goroutine stack traces.\npackage stack\n\nimport (\n\t\"fmt\"\n\t\"text/tabwriter\"\n)\n\n// Dump is a raw set of goroutines and their stacks.\ntype Dump []Goroutine\n\n// Goroutine is a single parsed goroutine dump.\ntype Goroutine struct {\n\tState string // state that the goroutine is in.\n\tID    int    // id of the goroutine.\n\tStack Stack  // call frames that make up the stack\n}\n\n// Stack is a set of frames in a callstack.\ntype Stack []Frame\n\n// Frame is a point in a call stack.\ntype Frame struct {\n\tFunction Function\n\tPosition Position\n}\n\n// Function is the function called at a frame.\ntype Function struct {\n\tPackage string // package name of function if known\n\tType    string // if set function is a method of this type\n\tName    string // function name of the frame\n}\n\n// Position is the file position for a frame.\ntype Position struct {\n\tFilename string // source filename\n\tLine     int    // line number within file\n}\n\n// Summary is a set of stacks processed and collated into Calls.\ntype Summary struct {\n\tTotal int    // the total count of goroutines in the summary\n\tCalls []Call // the collated stack traces\n}\n\n// Call is set of goroutines that all share the same callstack.\n// They will be grouped by state.\ntype Call struct {\n\tStack  Stack   // the shared callstack information\n\tGroups []Group // the sets of goroutines with the same state\n}\n\n// Group is a set of goroutines with the same stack that are in the same state.\ntype Group struct {\n\tState      string      // the shared state of the goroutines\n\tGoroutines []Goroutine // the set of goroutines in this group\n}\n\n// Delta represents the difference between two stack dumps.\ntype Delta struct {\n\tBefore Dump // The goroutines that were only in the before set.\n\tShared Dump // The goroutines that were in both sets.\n\tAfter  Dump // The goroutines that were only in the after set.\n}\n\nfunc (s Stack) equal(other Stack) bool {\n\tif len(s) != len(other) {\n\t\treturn false\n\t}\n\tfor i, frame := range s {\n\t\tif !frame.equal(other[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (s Stack) less(other Stack) bool {\n\tfor i, frame := range s {\n\t\tif i >= len(other) {\n\t\t\treturn false\n\t\t}\n\t\tif frame.less(other[i]) {\n\t\t\treturn true\n\t\t}\n\t\tif !frame.equal(other[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn len(s) < len(other)\n}\n\nfunc (f Frame) equal(other Frame) bool {\n\treturn f.Position.equal(other.Position)\n}\n\nfunc (f Frame) less(other Frame) bool {\n\treturn f.Position.less(other.Position)\n}\n\nfunc (p Position) equal(other Position) bool {\n\treturn p.Filename == other.Filename && p.Line == other.Line\n}\n\nfunc (p Position) less(other Position) bool {\n\tif p.Filename < other.Filename {\n\t\treturn true\n\t}\n\tif p.Filename > other.Filename {\n\t\treturn false\n\t}\n\treturn p.Line < other.Line\n}\n\nfunc (s Summary) Format(w fmt.State, r rune) {\n\ttw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)\n\tfor i, c := range s.Calls {\n\t\tif i > 0 {\n\t\t\tfmt.Fprintf(tw, \"\\n\\n\")\n\t\t\ttw.Flush()\n\t\t}\n\t\tfmt.Fprint(tw, c)\n\t}\n\ttw.Flush()\n\tif s.Total > 0 && w.Flag('+') {\n\t\tfmt.Fprintf(w, \"\\n\\n%d goroutines, %d unique\", s.Total, len(s.Calls))\n\t}\n}\n\nfunc (c Call) Format(w fmt.State, r rune) {\n\tfor i, g := range c.Groups {\n\t\tif i > 0 {\n\t\t\tfmt.Fprint(w, \" \")\n\t\t}\n\t\tfmt.Fprint(w, g)\n\t}\n\tfor _, f := range c.Stack {\n\t\tfmt.Fprintf(w, \"\\n%v\", f)\n\t}\n}\n\nfunc (g Group) Format(w fmt.State, r rune) {\n\tfmt.Fprintf(w, \"[%v]: \", g.State)\n\tfor i, gr := range g.Goroutines {\n\t\tif i > 0 {\n\t\t\tfmt.Fprint(w, \", \")\n\t\t}\n\t\tfmt.Fprintf(w, \"$%d\", gr.ID)\n\t}\n}\n\nfunc (f Frame) Format(w fmt.State, c rune) {\n\tfmt.Fprintf(w, \"%v:\\t%v\", f.Position, f.Function)\n}\n\nfunc (f Function) Format(w fmt.State, c rune) {\n\tif f.Type != \"\" {\n\t\tfmt.Fprintf(w, \"(%v).\", f.Type)\n\t}\n\tfmt.Fprintf(w, \"%v\", f.Name)\n}\n\nfunc (p Position) Format(w fmt.State, c rune) {\n\tfmt.Fprintf(w, \"%v:%v\", p.Filename, p.Line)\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stack/stack_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stack_test\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2/stack\"\n)\n\nfunc TestProcess(t *testing.T) {\n\tfor _, test := range []struct{ name, input, expect string }{{\n\t\tname:   `empty`,\n\t\tinput:  ``,\n\t\texpect: ``,\n\t}, {\n\t\tname:  `no_frame`,\n\t\tinput: `goroutine 1 [running]:`,\n\t\texpect: `\n[running]: $1\n\n1 goroutines, 1 unique\n`,\n\t}, {\n\t\tname: `one_frame`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage.function(args)\n\tfile.go:10\n`,\n\t\texpect: `\n[running]: $1\nfile.go:10: function\n\n1 goroutines, 1 unique\n`,\n\t}, {\n\t\tname: `one_call`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage1.functionA(args)\n\tfile1.go:10\npackage2.functionB(args)\n\tfile2.go:20\npackage3.functionC(args)\n\tfile3.go:30\n`,\n\t\texpect: `\n[running]: $1\nfile1.go:10: functionA\nfile2.go:20: functionB\nfile3.go:30: functionC\n\n1 goroutines, 1 unique\n`,\n\t}, {\n\t\tname: `two_call`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage1.functionA(args)\n\tfile1.go:10\ngoroutine 2 [running]:\npackage2.functionB(args)\n\tfile2.go:20\n`,\n\t\texpect: `\n[running]: $1\nfile1.go:10: functionA\n\n[running]: $2\nfile2.go:20: functionB\n\n2 goroutines, 2 unique\n`,\n\t}, {\n\t\tname: `merge_call`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage1.functionA(args)\n\tfile1.go:10\ngoroutine 2 [running]:\npackage1.functionA(args)\n\tfile1.go:10\n`,\n\t\texpect: `\n[running]: $1, $2\nfile1.go:10: functionA\n\n2 goroutines, 1 unique\n`,\n\t}, {\n\t\tname: `alternating_call`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage1.functionA(args)\n\tfile1.go:10\ngoroutine 2 [running]:\npackage2.functionB(args)\n\tfile2.go:20\ngoroutine 3 [running]:\npackage1.functionA(args)\n\tfile1.go:10\ngoroutine 4 [running]:\npackage2.functionB(args)\n\tfile2.go:20\ngoroutine 5 [running]:\npackage1.functionA(args)\n\tfile1.go:10\ngoroutine 6 [running]:\npackage2.functionB(args)\n\tfile2.go:20\n`,\n\t\texpect: `\n[running]: $1, $3, $5\nfile1.go:10: functionA\n\n[running]: $2, $4, $6\nfile2.go:20: functionB\n\n6 goroutines, 2 unique\n`,\n\t}, {\n\t\tname: `sort_calls`,\n\t\tinput: `\ngoroutine 1 [running]:\npackage3.functionC(args)\n\tfile3.go:30\ngoroutine 2 [running]:\npackage2.functionB(args)\n\tfile2.go:20\ngoroutine 3 [running]:\npackage1.functionA(args)\n\tfile1.go:10\n`,\n\t\texpect: `\n[running]: $3\nfile1.go:10: functionA\n\n[running]: $2\nfile2.go:20: functionB\n\n[running]: $1\nfile3.go:30: functionC\n\n3 goroutines, 3 unique\n`,\n\t}, {\n\t\tname: `real_single`,\n\t\tinput: `\npanic: oops\n\ngoroutine 53 [running]:\ngolang.org/x/tools/internal/jsonrpc2_test.testHandler.func1(0x1240c20, 0xc000013350, 0xc0000133b0, 0x1240ca0, 0xc00002ab00, 0x3, 0x3)\n\t/work/tools/internal/jsonrpc2/jsonrpc2_test.go:160 +0x74c\ngolang.org/x/tools/internal/jsonrpc2.(*Conn).Run(0xc000204330, 0x1240c20, 0xc000204270, 0x1209570, 0xc000212120, 0x1242700)\n\t/work/tools/internal/jsonrpc2/jsonrpc2.go:187 +0x777\ngolang.org/x/tools/internal/jsonrpc2_test.run.func1(0x123ebe0, 0xc000206018, 0x123ec20, 0xc000206010, 0xc0002080a0, 0xc000204330, 0x1240c20, 0xc000204270, 0xc000212120)\n\t/work/tools/internal/jsonrpc2/jsonrpc2_test.go:131 +0xe2\ncreated by golang.org/x/tools/internal/jsonrpc2_test.run\n\t/work/tools/internal/jsonrpc2/jsonrpc2_test.go:121 +0x263\nFAIL    golang.org/x/tools/internal/jsonrpc2    0.252s\nFAIL\n`,\n\t\texpect: `\npanic: oops\n\n[running]: $53\n/work/tools/internal/jsonrpc2/jsonrpc2_test.go:160: testHandler.func1\n/work/tools/internal/jsonrpc2/jsonrpc2.go:187:      (*Conn).Run\n/work/tools/internal/jsonrpc2/jsonrpc2_test.go:131: run.func1\n/work/tools/internal/jsonrpc2/jsonrpc2_test.go:121: run\n\n1 goroutines, 1 unique\n\nFAIL    golang.org/x/tools/internal/jsonrpc2    0.252s\nFAIL\n`,\n\t}} {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tbuf := &bytes.Buffer{}\n\t\t\tstack.Process(buf, strings.NewReader(test.input))\n\t\t\texpect := strings.TrimSpace(test.expect)\n\t\t\tgot := strings.TrimSpace(buf.String())\n\t\t\tif got != expect {\n\t\t\t\tt.Errorf(\"got:\\n%s\\nexpect:\\n%s\", got, expect)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stack/stacktest/stacktest.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stacktest\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2/stack\"\n)\n\n// this is only needed to support pre 1.14 when testing.TB did not have Cleanup\ntype withCleanup interface {\n\tCleanup(func())\n}\n\n// the maximum amount of time to wait for goroutines to clean themselves up.\nconst maxWait = time.Second\n\n// NoLeak checks that a test (or benchmark) does not leak any goroutines.\nfunc NoLeak(t testing.TB) {\n\tc, ok := t.(withCleanup)\n\tif !ok {\n\t\treturn\n\t}\n\tbefore := stack.Capture()\n\tc.Cleanup(func() {\n\t\tvar delta stack.Delta\n\t\tstart := time.Now()\n\t\tdelay := time.Millisecond\n\t\tfor {\n\t\t\tafter := stack.Capture()\n\t\t\tdelta = stack.Diff(before, after)\n\t\t\tif len(delta.After) == 0 {\n\t\t\t\t// no leaks\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif time.Since(start) > maxWait {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttime.Sleep(delay)\n\t\t\tdelay *= 2\n\t\t}\n\t\t// it's been long enough, and leaks are still present\n\t\tsummary := stack.Summarize(delta.After)\n\t\tt.Errorf(\"goroutine leak detected:\\n%+v\", summary)\n\t})\n}\n"
  },
  {
    "path": "internal/jsonrpc2/stream.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Stream abstracts the transport mechanics from the JSON RPC protocol.\n// A Conn reads and writes messages using the stream it was provided on\n// construction, and assumes that each call to Read or Write fully transfers\n// a single message, or returns an error.\n// A stream is not safe for concurrent use, it is expected it will be used by\n// a single Conn in a safe manner.\ntype Stream interface {\n\t// Read gets the next message from the stream.\n\tRead(context.Context) (Message, int64, error)\n\t// Write sends a message to the stream.\n\tWrite(context.Context, Message) (int64, error)\n\t// Close closes the connection.\n\t// Any blocked Read or Write operations will be unblocked and return errors.\n\tClose() error\n}\n\n// Framer wraps a network connection up into a Stream.\n// It is responsible for the framing and encoding of messages into wire form.\n// NewRawStream and NewHeaderStream are implementations of a Framer.\ntype Framer func(conn net.Conn) Stream\n\n// NewRawStream returns a Stream built on top of a net.Conn.\n// The messages are sent with no wrapping, and rely on json decode consistency\n// to determine message boundaries.\nfunc NewRawStream(conn net.Conn) Stream {\n\treturn &rawStream{\n\t\tconn: conn,\n\t\tin:   json.NewDecoder(conn),\n\t}\n}\n\ntype rawStream struct {\n\tconn net.Conn\n\tin   *json.Decoder\n}\n\nfunc (s *rawStream) Read(ctx context.Context) (Message, int64, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, 0, ctx.Err()\n\tdefault:\n\t}\n\tvar raw json.RawMessage\n\tif err := s.in.Decode(&raw); err != nil {\n\t\treturn nil, 0, err\n\t}\n\tmsg, err := DecodeMessage(raw)\n\treturn msg, int64(len(raw)), err\n}\n\nfunc (s *rawStream) Write(ctx context.Context, msg Message) (int64, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn 0, ctx.Err()\n\tdefault:\n\t}\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"marshaling message: %v\", err)\n\t}\n\tn, err := s.conn.Write(data)\n\treturn int64(n), err\n}\n\nfunc (s *rawStream) Close() error {\n\treturn s.conn.Close()\n}\n\n// NewHeaderStream returns a Stream built on top of a net.Conn.\n// The messages are sent with HTTP content length and MIME type headers.\n// This is the format used by LSP and others.\nfunc NewHeaderStream(conn net.Conn) Stream {\n\treturn &headerStream{\n\t\tconn: conn,\n\t\tin:   bufio.NewReader(conn),\n\t}\n}\n\ntype headerStream struct {\n\tconn net.Conn\n\tin   *bufio.Reader\n}\n\nfunc (s *headerStream) Read(ctx context.Context) (Message, int64, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, 0, ctx.Err()\n\tdefault:\n\t}\n\tvar total, length int64\n\t// read the header, stop on the first empty line\n\tfor {\n\t\tline, err := s.in.ReadString('\\n')\n\t\ttotal += int64(len(line))\n\t\tif err != nil {\n\t\t\treturn nil, total, fmt.Errorf(\"failed reading header line: %w\", err)\n\t\t}\n\t\tline = strings.TrimSpace(line)\n\t\t// check we have a header line\n\t\tif line == \"\" {\n\t\t\tbreak\n\t\t}\n\t\tcolon := strings.IndexRune(line, ':')\n\t\tif colon < 0 {\n\t\t\treturn nil, total, fmt.Errorf(\"invalid header line %q\", line)\n\t\t}\n\t\tname, value := line[:colon], strings.TrimSpace(line[colon+1:])\n\t\tswitch name {\n\t\tcase \"Content-Length\":\n\t\t\tif length, err = strconv.ParseInt(value, 10, 32); err != nil {\n\t\t\t\treturn nil, total, fmt.Errorf(\"failed parsing Content-Length: %v\", value)\n\t\t\t}\n\t\t\tif length <= 0 {\n\t\t\t\treturn nil, total, fmt.Errorf(\"invalid Content-Length: %v\", length)\n\t\t\t}\n\t\tdefault:\n\t\t\t// ignoring unknown headers\n\t\t}\n\t}\n\tif length == 0 {\n\t\treturn nil, total, fmt.Errorf(\"missing Content-Length header\")\n\t}\n\tdata := make([]byte, length)\n\tif _, err := io.ReadFull(s.in, data); err != nil {\n\t\treturn nil, total, err\n\t}\n\ttotal += length\n\tmsg, err := DecodeMessage(data)\n\treturn msg, total, err\n}\n\nfunc (s *headerStream) Write(ctx context.Context, msg Message) (int64, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn 0, ctx.Err()\n\tdefault:\n\t}\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"marshaling message: %v\", err)\n\t}\n\tn, err := fmt.Fprintf(s.conn, \"Content-Length: %v\\r\\n\\r\\n\", len(data))\n\ttotal := int64(n)\n\tif err == nil {\n\t\tn, err = s.conn.Write(data)\n\t\ttotal += int64(n)\n\t}\n\treturn total, err\n}\n\nfunc (s *headerStream) Close() error {\n\treturn s.conn.Close()\n}\n"
  },
  {
    "path": "internal/jsonrpc2/wire.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// this file contains the go forms of the wire specification\n// see http://www.jsonrpc.org/specification for details\n\nvar (\n\t// ErrUnknown should be used for all non coded errors.\n\tErrUnknown = NewError(-32001, \"JSON RPC unknown error\")\n\t// ErrParse is used when invalid JSON was received by the server.\n\tErrParse = NewError(-32700, \"JSON RPC parse error\")\n\t//ErrInvalidRequest is used when the JSON sent is not a valid Request object.\n\tErrInvalidRequest = NewError(-32600, \"JSON RPC invalid request\")\n\t// ErrMethodNotFound should be returned by the handler when the method does\n\t// not exist / is not available.\n\tErrMethodNotFound = NewError(-32601, \"JSON RPC method not found\")\n\t// ErrInvalidParams should be returned by the handler when method\n\t// parameter(s) were invalid.\n\tErrInvalidParams = NewError(-32602, \"JSON RPC invalid params\")\n\t// ErrInternal is not currently returned but defined for completeness.\n\tErrInternal = NewError(-32603, \"JSON RPC internal error\")\n\n\t//ErrServerOverloaded is returned when a message was refused due to a\n\t//server being temporarily unable to accept any new messages.\n\tErrServerOverloaded = NewError(-32000, \"JSON RPC overloaded\")\n)\n\n// wireRequest is sent to a server to represent a Call or Notify operation.\ntype wireRequest struct {\n\t// VersionTag is always encoded as the string \"2.0\"\n\tVersionTag wireVersionTag `json:\"jsonrpc\"`\n\t// Method is a string containing the method name to invoke.\n\tMethod string `json:\"method\"`\n\t// Params is either a struct or an array with the parameters of the method.\n\tParams *json.RawMessage `json:\"params,omitempty\"`\n\t// The id of this request, used to tie the Response back to the request.\n\t// Will be either a string or a number. If not set, the Request is a notify,\n\t// and no response is possible.\n\tID *ID `json:\"id,omitempty\"`\n}\n\n// wireResponse is a reply to a Request.\n// It will always have the ID field set to tie it back to a request, and will\n// have either the Result or Error fields set depending on whether it is a\n// success or failure response.\ntype wireResponse struct {\n\t// VersionTag is always encoded as the string \"2.0\"\n\tVersionTag wireVersionTag `json:\"jsonrpc\"`\n\t// Result is the response value, and is required on success.\n\tResult *json.RawMessage `json:\"result,omitempty\"`\n\t// Error is a structured error response if the call fails.\n\tError *WireError `json:\"error,omitempty\"`\n\t// ID must be set and is the identifier of the Request this is a response to.\n\tID *ID `json:\"id,omitempty\"`\n}\n\n// wireCombined has all the fields of both Request and Response.\n// We can decode this and then work out which it is.\ntype wireCombined struct {\n\tVersionTag wireVersionTag   `json:\"jsonrpc\"`\n\tID         *ID              `json:\"id,omitempty\"`\n\tMethod     string           `json:\"method\"`\n\tParams     *json.RawMessage `json:\"params,omitempty\"`\n\tResult     *json.RawMessage `json:\"result,omitempty\"`\n\tError      *WireError       `json:\"error,omitempty\"`\n}\n\n// WireError represents a structured error in a Response.\ntype WireError struct {\n\t// Code is an error code indicating the type of failure.\n\tCode int64 `json:\"code\"`\n\t// Message is a short description of the error.\n\tMessage string `json:\"message\"`\n\t// Data is optional structured data containing additional information about the error.\n\tData *json.RawMessage `json:\"data,omitempty\"`\n}\n\n// wireVersionTag is a special 0 sized struct that encodes as the jsonrpc version\n// tag.\n// It will fail during decode if it is not the correct version tag in the\n// stream.\ntype wireVersionTag struct{}\n\n// ID is a Request identifier.\ntype ID struct {\n\tname   string\n\tnumber int64\n}\n\nfunc NewError(code int64, message string) error {\n\treturn &WireError{\n\t\tCode:    code,\n\t\tMessage: message,\n\t}\n}\n\nfunc (err *WireError) Error() string {\n\treturn err.Message\n}\n\nfunc (wireVersionTag) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(\"2.0\")\n}\n\nfunc (wireVersionTag) UnmarshalJSON(data []byte) error {\n\tversion := \"\"\n\tif err := json.Unmarshal(data, &version); err != nil {\n\t\treturn err\n\t}\n\tif version != \"2.0\" {\n\t\treturn fmt.Errorf(\"invalid RPC version %v\", version)\n\t}\n\treturn nil\n}\n\n// NewIntID returns a new numerical request ID.\nfunc NewIntID(v int64) ID { return ID{number: v} }\n\n// NewStringID returns a new string request ID.\nfunc NewStringID(v string) ID { return ID{name: v} }\n\n// Format writes the ID to the formatter.\n// If the rune is q the representation is non ambiguous,\n// string forms are quoted, number forms are preceded by a #\nfunc (id ID) Format(f fmt.State, r rune) {\n\tnumF, strF := `%d`, `%s`\n\tif r == 'q' {\n\t\tnumF, strF = `#%d`, `%q`\n\t}\n\tswitch {\n\tcase id.name != \"\":\n\t\tfmt.Fprintf(f, strF, id.name)\n\tdefault:\n\t\tfmt.Fprintf(f, numF, id.number)\n\t}\n}\n\nfunc (id *ID) MarshalJSON() ([]byte, error) {\n\tif id.name != \"\" {\n\t\treturn json.Marshal(id.name)\n\t}\n\treturn json.Marshal(id.number)\n}\n\nfunc (id *ID) UnmarshalJSON(data []byte) error {\n\t*id = ID{}\n\tif err := json.Unmarshal(data, &id.number); err == nil {\n\t\treturn nil\n\t}\n\treturn json.Unmarshal(data, &id.name)\n}\n"
  },
  {
    "path": "internal/jsonrpc2/wire_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/jsonrpc2\"\n)\n\nvar wireIDTestData = []struct {\n\tname    string\n\tid      jsonrpc2.ID\n\tencoded []byte\n\tplain   string\n\tquoted  string\n}{\n\t{\n\t\tname:    `empty`,\n\t\tencoded: []byte(`0`),\n\t\tplain:   `0`,\n\t\tquoted:  `#0`,\n\t}, {\n\t\tname:    `number`,\n\t\tid:      jsonrpc2.NewIntID(43),\n\t\tencoded: []byte(`43`),\n\t\tplain:   `43`,\n\t\tquoted:  `#43`,\n\t}, {\n\t\tname:    `string`,\n\t\tid:      jsonrpc2.NewStringID(\"life\"),\n\t\tencoded: []byte(`\"life\"`),\n\t\tplain:   `life`,\n\t\tquoted:  `\"life\"`,\n\t},\n}\n\nfunc TestIDFormat(t *testing.T) {\n\tfor _, test := range wireIDTestData {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tif got := fmt.Sprint(test.id); got != test.plain {\n\t\t\t\tt.Errorf(\"got %s expected %s\", got, test.plain)\n\t\t\t}\n\t\t\tif got := fmt.Sprintf(\"%q\", test.id); got != test.quoted {\n\t\t\t\tt.Errorf(\"got %s want %s\", got, test.quoted)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIDEncode(t *testing.T) {\n\tfor _, test := range wireIDTestData {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tdata, err := json.Marshal(&test.id)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tcheckJSON(t, data, test.encoded)\n\t\t})\n\t}\n}\n\nfunc TestIDDecode(t *testing.T) {\n\tfor _, test := range wireIDTestData {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tvar got *jsonrpc2.ID\n\t\t\tif err := json.Unmarshal(test.encoded, &got); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif got == nil {\n\t\t\t\tt.Errorf(\"got nil want %s\", test.id)\n\t\t\t} else if *got != test.id {\n\t\t\t\tt.Errorf(\"got %s want %s\", got, test.id)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestErrorEncode(t *testing.T) {\n\tb, err := json.Marshal(jsonrpc2.NewError(0, \"\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcheckJSON(t, b, []byte(`{\n\t\t\"code\": 0,\n\t\t\"message\": \"\"\n\t}`))\n}\n\nfunc TestErrorResponse(t *testing.T) {\n\t// originally reported in #39719, this checks that result is not present if\n\t// it is an error response\n\tr, _ := jsonrpc2.NewResponse(jsonrpc2.NewIntID(3), nil, fmt.Errorf(\"computing fix edits\"))\n\tdata, err := json.Marshal(r)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcheckJSON(t, data, []byte(`{\n\t\t\"jsonrpc\":\"2.0\",\n\t\t\"error\":{\n\t\t\t\"code\":0,\n\t\t\t\"message\":\"computing fix edits\"\n\t\t},\n\t\t\"id\":3\n\t}`))\n}\n\nfunc checkJSON(t *testing.T, got, want []byte) {\n\t// compare the compact form, to allow for formatting differences\n\tg := &bytes.Buffer{}\n\tif err := json.Compact(g, []byte(got)); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tw := &bytes.Buffer{}\n\tif err := json.Compact(w, []byte(want)); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif g.String() != w.String() {\n\t\tt.Fatalf(\"Got:\\n%s\\nWant:\\n%s\", g, w)\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/conn.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\n// Binder builds a connection configuration.\n// This may be used in servers to generate a new configuration per connection.\n// ConnectionOptions itself implements Binder returning itself unmodified, to\n// allow for the simple cases where no per connection information is needed.\ntype Binder interface {\n\t// Bind returns the ConnectionOptions to use when establishing the passed-in\n\t// Connection.\n\t//\n\t// The connection is not ready to use when Bind is called,\n\t// but Bind may close it without reading or writing to it.\n\tBind(context.Context, *Connection) ConnectionOptions\n}\n\n// A BinderFunc implements the Binder interface for a standalone Bind function.\ntype BinderFunc func(context.Context, *Connection) ConnectionOptions\n\nfunc (f BinderFunc) Bind(ctx context.Context, c *Connection) ConnectionOptions {\n\treturn f(ctx, c)\n}\n\nvar _ Binder = BinderFunc(nil)\n\n// ConnectionOptions holds the options for new connections.\ntype ConnectionOptions struct {\n\t// Framer allows control over the message framing and encoding.\n\t// If nil, HeaderFramer will be used.\n\tFramer Framer\n\t// Preempter allows registration of a pre-queue message handler.\n\t// If nil, no messages will be preempted.\n\tPreempter Preempter\n\t// Handler is used as the queued message handler for inbound messages.\n\t// If nil, all responses will be ErrNotHandled.\n\tHandler Handler\n\t// OnInternalError, if non-nil, is called with any internal errors that occur\n\t// while serving the connection, such as protocol errors or invariant\n\t// violations. (If nil, internal errors result in panics.)\n\tOnInternalError func(error)\n}\n\n// Connection manages the jsonrpc2 protocol, connecting responses back to their\n// calls.\n// Connection is bidirectional; it does not have a designated server or client\n// end.\ntype Connection struct {\n\tseq int64 // must only be accessed using atomic operations\n\n\tstateMu sync.Mutex\n\tstate   inFlightState // accessed only in updateInFlight\n\tdone    chan struct{} // closed (under stateMu) when state.closed is true and all goroutines have completed\n\n\twriter chan Writer // 1-buffered; stores the writer when not in use\n\n\thandler Handler\n\n\tonInternalError func(error)\n\tonDone          func()\n}\n\n// inFlightState records the state of the incoming and outgoing calls on a\n// Connection.\ntype inFlightState struct {\n\tconnClosing bool  // true when the Connection's Close method has been called\n\treading     bool  // true while the readIncoming goroutine is running\n\treadErr     error // non-nil when the readIncoming goroutine exits (typically io.EOF)\n\twriteErr    error // non-nil if a call to the Writer has failed with a non-canceled Context\n\n\t// closer shuts down and cleans up the Reader and Writer state, ideally\n\t// interrupting any Read or Write call that is currently blocked. It is closed\n\t// when the state is idle and one of: connClosing is true, readErr is non-nil,\n\t// or writeErr is non-nil.\n\t//\n\t// After the closer has been invoked, the closer field is set to nil\n\t// and the closeErr field is simultaneously set to its result.\n\tcloser   io.Closer\n\tcloseErr error // error returned from closer.Close\n\n\toutgoingCalls         map[ID]*AsyncCall // calls only\n\toutgoingNotifications int               // # of notifications awaiting \"write\"\n\n\t// incoming stores the total number of incoming calls and notifications\n\t// that have not yet written or processed a result.\n\tincoming int\n\n\tincomingByID map[ID]*incomingRequest // calls only\n\n\t// handlerQueue stores the backlog of calls and notifications that were not\n\t// already handled by a preempter.\n\t// The queue does not include the request currently being handled (if any).\n\thandlerQueue   []*incomingRequest\n\thandlerRunning bool\n}\n\n// updateInFlight locks the state of the connection's in-flight requests, allows\n// f to mutate that state, and closes the connection if it is idle and either\n// is closing or has a read or write error.\nfunc (c *Connection) updateInFlight(f func(*inFlightState)) {\n\tc.stateMu.Lock()\n\tdefer c.stateMu.Unlock()\n\n\ts := &c.state\n\n\tf(s)\n\n\tselect {\n\tcase <-c.done:\n\t\t// The connection was already completely done at the start of this call to\n\t\t// updateInFlight, so it must remain so. (The call to f should have noticed\n\t\t// that and avoided making any updates that would cause the state to be\n\t\t// non-idle.)\n\t\tif !s.idle() {\n\t\t\tpanic(\"jsonrpc2_v2: updateInFlight transitioned to non-idle when already done\")\n\t\t}\n\t\treturn\n\tdefault:\n\t}\n\n\tif s.idle() && s.shuttingDown(ErrUnknown) != nil {\n\t\tif s.closer != nil {\n\t\t\ts.closeErr = s.closer.Close()\n\t\t\ts.closer = nil // prevent duplicate Close calls\n\t\t}\n\t\tif s.reading {\n\t\t\t// The readIncoming goroutine is still running. Our call to Close should\n\t\t\t// cause it to exit soon, at which point it will make another call to\n\t\t\t// updateInFlight, set s.reading to false, and mark the Connection done.\n\t\t} else {\n\t\t\t// The readIncoming goroutine has exited, or never started to begin with.\n\t\t\t// Since everything else is idle, we're completely done.\n\t\t\tif c.onDone != nil {\n\t\t\t\tc.onDone()\n\t\t\t}\n\t\t\tclose(c.done)\n\t\t}\n\t}\n}\n\n// idle reports whether the connection is in a state with no pending calls or\n// notifications.\n//\n// If idle returns true, the readIncoming goroutine may still be running,\n// but no other goroutines are doing work on behalf of the connection.\nfunc (s *inFlightState) idle() bool {\n\treturn len(s.outgoingCalls) == 0 && s.outgoingNotifications == 0 && s.incoming == 0 && !s.handlerRunning\n}\n\n// shuttingDown reports whether the connection is in a state that should\n// disallow new (incoming and outgoing) calls. It returns either nil or\n// an error that is or wraps the provided errClosing.\nfunc (s *inFlightState) shuttingDown(errClosing error) error {\n\tif s.connClosing {\n\t\t// If Close has been called explicitly, it doesn't matter what state the\n\t\t// Reader and Writer are in: we shouldn't be starting new work because the\n\t\t// caller told us not to start new work.\n\t\treturn errClosing\n\t}\n\tif s.readErr != nil {\n\t\t// If the read side of the connection is broken, we cannot read new call\n\t\t// requests, and cannot read responses to our outgoing calls.\n\t\treturn fmt.Errorf(\"%w: %v\", errClosing, s.readErr)\n\t}\n\tif s.writeErr != nil {\n\t\t// If the write side of the connection is broken, we cannot write responses\n\t\t// for incoming calls, and cannot write requests for outgoing calls.\n\t\treturn fmt.Errorf(\"%w: %v\", errClosing, s.writeErr)\n\t}\n\treturn nil\n}\n\n// incomingRequest is used to track an incoming request as it is being handled\ntype incomingRequest struct {\n\t*Request // the request being processed\n\tctx      context.Context\n\tcancel   context.CancelFunc\n}\n\n// Bind returns the options unmodified.\nfunc (o ConnectionOptions) Bind(context.Context, *Connection) ConnectionOptions {\n\treturn o\n}\n\n// A ConnectionConfig configures a bidirectional jsonrpc2 connection.\ntype ConnectionConfig struct {\n\tReader          Reader                    // required\n\tWriter          Writer                    // required\n\tCloser          io.Closer                 // required\n\tPreempter       Preempter                 // optional\n\tBind            func(*Connection) Handler // required\n\tOnDone          func()                    // optional\n\tOnInternalError func(error)               // optional\n}\n\n// NewConnection creates a new [Connection] object and starts processing\n// incoming messages.\nfunc NewConnection(ctx context.Context, cfg ConnectionConfig) *Connection {\n\tctx = notDone{ctx}\n\n\tc := &Connection{\n\t\tstate:           inFlightState{closer: cfg.Closer},\n\t\tdone:            make(chan struct{}),\n\t\twriter:          make(chan Writer, 1),\n\t\tonDone:          cfg.OnDone,\n\t\tonInternalError: cfg.OnInternalError,\n\t}\n\tc.handler = cfg.Bind(c)\n\tc.writer <- cfg.Writer\n\tc.start(ctx, cfg.Reader, cfg.Preempter)\n\treturn c\n}\n\n// bindConnection creates a new connection and runs it.\n//\n// This is used by the Dial and Serve functions to build the actual connection.\n//\n// The connection is closed automatically (and its resources cleaned up) when\n// the last request has completed after the underlying ReadWriteCloser breaks,\n// but it may be stopped earlier by calling Close (for a clean shutdown).\nfunc bindConnection(bindCtx context.Context, rwc io.ReadWriteCloser, binder Binder, onDone func()) *Connection {\n\t// TODO: Should we create a new event span here?\n\t// This will propagate cancellation from ctx; should it?\n\tctx := notDone{bindCtx}\n\n\tc := &Connection{\n\t\tstate:  inFlightState{closer: rwc},\n\t\tdone:   make(chan struct{}),\n\t\twriter: make(chan Writer, 1),\n\t\tonDone: onDone,\n\t}\n\t// It's tempting to set a finalizer on c to verify that the state has gone\n\t// idle when the connection becomes unreachable. Unfortunately, the Binder\n\t// interface makes that unsafe: it allows the Handler to close over the\n\t// Connection, which could create a reference cycle that would cause the\n\t// Connection to become uncollectable.\n\n\toptions := binder.Bind(bindCtx, c)\n\tframer := options.Framer\n\tif framer == nil {\n\t\tframer = HeaderFramer()\n\t}\n\tc.handler = options.Handler\n\tif c.handler == nil {\n\t\tc.handler = defaultHandler{}\n\t}\n\tc.onInternalError = options.OnInternalError\n\n\tc.writer <- framer.Writer(rwc)\n\treader := framer.Reader(rwc)\n\tc.start(ctx, reader, options.Preempter)\n\treturn c\n}\n\nfunc (c *Connection) start(ctx context.Context, reader Reader, preempter Preempter) {\n\tc.updateInFlight(func(s *inFlightState) {\n\t\tselect {\n\t\tcase <-c.done:\n\t\t\t// Bind already closed the connection; don't start a goroutine to read it.\n\t\t\treturn\n\t\tdefault:\n\t\t}\n\n\t\t// The goroutine started here will continue until the underlying stream is closed.\n\t\t//\n\t\t// (If the Binder closed the Connection already, this should error out and\n\t\t// return almost immediately.)\n\t\ts.reading = true\n\t\tgo c.readIncoming(ctx, reader, preempter)\n\t})\n}\n\n// Notify invokes the target method but does not wait for a response.\n// The params will be marshaled to JSON before sending over the wire, and will\n// be handed to the method invoked.\nfunc (c *Connection) Notify(ctx context.Context, method string, params any) (err error) {\n\tattempted := false\n\n\tdefer func() {\n\t\tif attempted {\n\t\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\t\ts.outgoingNotifications--\n\t\t\t})\n\t\t}\n\t}()\n\n\tc.updateInFlight(func(s *inFlightState) {\n\t\t// If the connection is shutting down, allow outgoing notifications only if\n\t\t// there is at least one call still in flight. The number of calls in flight\n\t\t// cannot increase once shutdown begins, and allowing outgoing notifications\n\t\t// may permit notifications that will cancel in-flight calls.\n\t\tif len(s.outgoingCalls) == 0 && len(s.incomingByID) == 0 {\n\t\t\terr = s.shuttingDown(ErrClientClosing)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\ts.outgoingNotifications++\n\t\tattempted = true\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tnotify, err := NewNotification(method, params)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling notify parameters: %v\", err)\n\t}\n\n\treturn c.write(ctx, notify)\n}\n\n// Call invokes the target method and returns an object that can be used to await the response.\n// The params will be marshaled to JSON before sending over the wire, and will\n// be handed to the method invoked.\n// You do not have to wait for the response, it can just be ignored if not needed.\n// If sending the call failed, the response will be ready and have the error in it.\nfunc (c *Connection) Call(ctx context.Context, method string, params any) *AsyncCall {\n\t// Generate a new request identifier.\n\tid := Int64ID(atomic.AddInt64(&c.seq, 1))\n\n\tac := &AsyncCall{\n\t\tid:    id,\n\t\tready: make(chan struct{}),\n\t}\n\t// When this method returns, either ac is retired, or the request has been\n\t// written successfully and the call is awaiting a response (to be provided by\n\t// the readIncoming goroutine).\n\n\tcall, err := NewCall(ac.id, method, params)\n\tif err != nil {\n\t\tac.retire(&Response{ID: id, Error: fmt.Errorf(\"marshaling call parameters: %w\", err)})\n\t\treturn ac\n\t}\n\n\tc.updateInFlight(func(s *inFlightState) {\n\t\terr = s.shuttingDown(ErrClientClosing)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif s.outgoingCalls == nil {\n\t\t\ts.outgoingCalls = make(map[ID]*AsyncCall)\n\t\t}\n\t\ts.outgoingCalls[ac.id] = ac\n\t})\n\tif err != nil {\n\t\tac.retire(&Response{ID: id, Error: err})\n\t\treturn ac\n\t}\n\n\tif err := c.write(ctx, call); err != nil {\n\t\t// Sending failed. We will never get a response, so deliver a fake one if it\n\t\t// wasn't already retired by the connection breaking.\n\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\tif s.outgoingCalls[ac.id] == ac {\n\t\t\t\tdelete(s.outgoingCalls, ac.id)\n\t\t\t\tac.retire(&Response{ID: id, Error: err})\n\t\t\t} else {\n\t\t\t\t// ac was already retired by the readIncoming goroutine:\n\t\t\t\t// perhaps our write raced with the Read side of the connection breaking.\n\t\t\t}\n\t\t})\n\t}\n\treturn ac\n}\n\ntype AsyncCall struct {\n\tid       ID\n\tready    chan struct{} // closed after response has been set\n\tresponse *Response\n}\n\n// ID used for this call.\n// This can be used to cancel the call if needed.\nfunc (ac *AsyncCall) ID() ID { return ac.id }\n\n// IsReady can be used to check if the result is already prepared.\n// This is guaranteed to return true on a result for which Await has already\n// returned, or a call that failed to send in the first place.\nfunc (ac *AsyncCall) IsReady() bool {\n\tselect {\n\tcase <-ac.ready:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// retire processes the response to the call.\nfunc (ac *AsyncCall) retire(response *Response) {\n\tselect {\n\tcase <-ac.ready:\n\t\tpanic(fmt.Sprintf(\"jsonrpc2: retire called twice for ID %v\", ac.id))\n\tdefault:\n\t}\n\n\tac.response = response\n\tclose(ac.ready)\n}\n\n// Await waits for (and decodes) the results of a Call.\n// The response will be unmarshaled from JSON into the result.\nfunc (ac *AsyncCall) Await(ctx context.Context, result any) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tcase <-ac.ready:\n\t}\n\tif ac.response.Error != nil {\n\t\treturn ac.response.Error\n\t}\n\tif result == nil {\n\t\treturn nil\n\t}\n\treturn json.Unmarshal(ac.response.Result, result)\n}\n\n// Respond delivers a response to an incoming Call.\n//\n// Respond must be called exactly once for any message for which a handler\n// returns ErrAsyncResponse. It must not be called for any other message.\nfunc (c *Connection) Respond(id ID, result any, err error) error {\n\tvar req *incomingRequest\n\tc.updateInFlight(func(s *inFlightState) {\n\t\treq = s.incomingByID[id]\n\t})\n\tif req == nil {\n\t\treturn c.internalErrorf(\"Request not found for ID %v\", id)\n\t}\n\n\tif err == ErrAsyncResponse {\n\t\t// Respond is supposed to supply the asynchronous response, so it would be\n\t\t// confusing to call Respond with an error that promises to call Respond\n\t\t// again.\n\t\terr = c.internalErrorf(\"Respond called with ErrAsyncResponse for %q\", req.Method)\n\t}\n\treturn c.processResult(\"Respond\", req, result, err)\n}\n\n// Cancel cancels the Context passed to the Handle call for the inbound message\n// with the given ID.\n//\n// Cancel will not complain if the ID is not a currently active message, and it\n// will not cause any messages that have not arrived yet with that ID to be\n// cancelled.\nfunc (c *Connection) Cancel(id ID) {\n\tvar req *incomingRequest\n\tc.updateInFlight(func(s *inFlightState) {\n\t\treq = s.incomingByID[id]\n\t})\n\tif req != nil {\n\t\treq.cancel()\n\t}\n}\n\n// Wait blocks until the connection is fully closed, but does not close it.\nfunc (c *Connection) Wait() error {\n\tvar err error\n\t<-c.done\n\tc.updateInFlight(func(s *inFlightState) {\n\t\terr = s.closeErr\n\t})\n\treturn err\n}\n\n// Close stops accepting new requests, waits for in-flight requests and enqueued\n// Handle calls to complete, and then closes the underlying stream.\n//\n// After the start of a Close, notification requests (that lack IDs and do not\n// receive responses) will continue to be passed to the Preempter, but calls\n// with IDs will receive immediate responses with ErrServerClosing, and no new\n// requests (not even notifications!) will be enqueued to the Handler.\nfunc (c *Connection) Close() error {\n\t// Stop handling new requests, and interrupt the reader (by closing the\n\t// connection) as soon as the active requests finish.\n\tc.updateInFlight(func(s *inFlightState) { s.connClosing = true })\n\n\treturn c.Wait()\n}\n\n// readIncoming collects inbound messages from the reader and delivers them, either responding\n// to outgoing calls or feeding requests to the queue.\nfunc (c *Connection) readIncoming(ctx context.Context, reader Reader, preempter Preempter) {\n\tvar err error\n\tfor {\n\t\tvar msg Message\n\t\tmsg, err = reader.Read(ctx)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\n\t\tswitch msg := msg.(type) {\n\t\tcase *Request:\n\t\t\tc.acceptRequest(ctx, msg, preempter)\n\n\t\tcase *Response:\n\t\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\t\tif ac, ok := s.outgoingCalls[msg.ID]; ok {\n\t\t\t\t\tdelete(s.outgoingCalls, msg.ID)\n\t\t\t\t\tac.retire(msg)\n\t\t\t\t} else {\n\t\t\t\t\t// TODO: How should we report unexpected responses?\n\t\t\t\t}\n\t\t\t})\n\n\t\tdefault:\n\t\t\tc.internalErrorf(\"Read returned an unexpected message of type %T\", msg)\n\t\t}\n\t}\n\n\tc.updateInFlight(func(s *inFlightState) {\n\t\ts.reading = false\n\t\ts.readErr = err\n\n\t\t// Retire any outgoing requests that were still in flight: with the Reader no\n\t\t// longer being processed, they necessarily cannot receive a response.\n\t\tfor id, ac := range s.outgoingCalls {\n\t\t\tac.retire(&Response{ID: id, Error: err})\n\t\t}\n\t\ts.outgoingCalls = nil\n\t})\n}\n\n// acceptRequest either handles msg synchronously or enqueues it to be handled\n// asynchronously.\nfunc (c *Connection) acceptRequest(ctx context.Context, msg *Request, preempter Preempter) {\n\t// In theory notifications cannot be cancelled, but we build them a cancel\n\t// context anyway.\n\treqCtx, cancel := context.WithCancel(ctx)\n\treq := &incomingRequest{\n\t\tRequest: msg,\n\t\tctx:     reqCtx,\n\t\tcancel:  cancel,\n\t}\n\n\t// If the request is a call, add it to the incoming map so it can be\n\t// cancelled (or responded) by ID.\n\tvar err error\n\tc.updateInFlight(func(s *inFlightState) {\n\t\ts.incoming++\n\n\t\tif req.IsCall() {\n\t\t\tif s.incomingByID[req.ID] != nil {\n\t\t\t\terr = fmt.Errorf(\"%w: request ID %v already in use\", ErrInvalidRequest, req.ID)\n\t\t\t\treq.ID = ID{} // Don't misattribute this error to the existing request.\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif s.incomingByID == nil {\n\t\t\t\ts.incomingByID = make(map[ID]*incomingRequest)\n\t\t\t}\n\t\t\ts.incomingByID[req.ID] = req\n\n\t\t\t// When shutting down, reject all new Call requests, even if they could\n\t\t\t// theoretically be handled by the preempter. The preempter could return\n\t\t\t// ErrAsyncResponse, which would increase the amount of work in flight\n\t\t\t// when we're trying to ensure that it strictly decreases.\n\t\t\terr = s.shuttingDown(ErrServerClosing)\n\t\t}\n\t})\n\tif err != nil {\n\t\tc.processResult(\"acceptRequest\", req, nil, err)\n\t\treturn\n\t}\n\n\tif preempter != nil {\n\t\tresult, err := preempter.Preempt(req.ctx, req.Request)\n\n\t\tif req.IsCall() && errors.Is(err, ErrAsyncResponse) {\n\t\t\t// This request will remain in flight until Respond is called for it.\n\t\t\treturn\n\t\t}\n\n\t\tif !errors.Is(err, ErrNotHandled) {\n\t\t\tc.processResult(\"Preempt\", req, result, err)\n\t\t\treturn\n\t\t}\n\t}\n\n\tc.updateInFlight(func(s *inFlightState) {\n\t\t// If the connection is shutting down, don't enqueue anything to the\n\t\t// handler — not even notifications. That ensures that if the handler\n\t\t// continues to make progress, it will eventually become idle and\n\t\t// close the connection.\n\t\terr = s.shuttingDown(ErrServerClosing)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\n\t\t// We enqueue requests that have not been preempted to an unbounded slice.\n\t\t// Unfortunately, we cannot in general limit the size of the handler\n\t\t// queue: we have to read every response that comes in on the wire\n\t\t// (because it may be responding to a request issued by, say, an\n\t\t// asynchronous handler), and in order to get to that response we have\n\t\t// to read all of the requests that came in ahead of it.\n\t\ts.handlerQueue = append(s.handlerQueue, req)\n\t\tif !s.handlerRunning {\n\t\t\t// We start the handleAsync goroutine when it has work to do, and let it\n\t\t\t// exit when the queue empties.\n\t\t\t//\n\t\t\t// Otherwise, in order to synchronize the handler we would need some other\n\t\t\t// goroutine (probably readIncoming?) to explicitly wait for handleAsync\n\t\t\t// to finish, and that would complicate error reporting: either the error\n\t\t\t// report from the goroutine would be blocked on the handler emptying its\n\t\t\t// queue (which was tried, and introduced a deadlock detected by\n\t\t\t// TestCloseCallRace), or the error would need to be reported separately\n\t\t\t// from synchronizing completion. Allowing the handler goroutine to exit\n\t\t\t// when idle seems simpler than trying to implement either of those\n\t\t\t// alternatives correctly.\n\t\t\ts.handlerRunning = true\n\t\t\tgo c.handleAsync()\n\t\t}\n\t})\n\tif err != nil {\n\t\tc.processResult(\"acceptRequest\", req, nil, err)\n\t}\n}\n\n// handleAsync invokes the handler on the requests in the handler queue\n// sequentially until the queue is empty.\nfunc (c *Connection) handleAsync() {\n\tfor {\n\t\tvar req *incomingRequest\n\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\tif len(s.handlerQueue) > 0 {\n\t\t\t\treq, s.handlerQueue = s.handlerQueue[0], s.handlerQueue[1:]\n\t\t\t} else {\n\t\t\t\ts.handlerRunning = false\n\t\t\t}\n\t\t})\n\t\tif req == nil {\n\t\t\treturn\n\t\t}\n\n\t\t// Only deliver to the Handler if not already canceled.\n\t\tif err := req.ctx.Err(); err != nil {\n\t\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\t\tif s.writeErr != nil {\n\t\t\t\t\t// Assume that req.ctx was canceled due to s.writeErr.\n\t\t\t\t\t// TODO(#51365): use a Context API to plumb this through req.ctx.\n\t\t\t\t\terr = fmt.Errorf(\"%w: %v\", ErrServerClosing, s.writeErr)\n\t\t\t\t}\n\t\t\t})\n\t\t\tc.processResult(\"handleAsync\", req, nil, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tresult, err := c.handler.Handle(req.ctx, req.Request)\n\t\tc.processResult(c.handler, req, result, err)\n\t}\n}\n\n// processResult processes the result of a request and, if appropriate, sends a response.\nfunc (c *Connection) processResult(from any, req *incomingRequest, result any, err error) error {\n\tswitch err {\n\tcase ErrAsyncResponse:\n\t\tif !req.IsCall() {\n\t\t\treturn c.internalErrorf(\"%#v returned ErrAsyncResponse for a %q Request without an ID\", from, req.Method)\n\t\t}\n\t\treturn nil // This request is still in flight, so don't record the result yet.\n\tcase ErrNotHandled, ErrMethodNotFound:\n\t\t// Add detail describing the unhandled method.\n\t\terr = fmt.Errorf(\"%w: %q\", ErrMethodNotFound, req.Method)\n\t}\n\n\tif result != nil && err != nil {\n\t\tc.internalErrorf(\"%#v returned a non-nil result with a non-nil error for %s:\\n%v\\n%#v\", from, req.Method, err, result)\n\t\tresult = nil // Discard the spurious result and respond with err.\n\t}\n\n\tif req.IsCall() {\n\t\tif result == nil && err == nil {\n\t\t\terr = c.internalErrorf(\"%#v returned a nil result and nil error for a %q Request that requires a Response\", from, req.Method)\n\t\t}\n\n\t\tresponse, respErr := NewResponse(req.ID, result, err)\n\n\t\t// The caller could theoretically reuse the request's ID as soon as we've\n\t\t// sent the response, so ensure that it is removed from the incoming map\n\t\t// before sending.\n\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\tdelete(s.incomingByID, req.ID)\n\t\t})\n\t\tif respErr == nil {\n\t\t\twriteErr := c.write(notDone{req.ctx}, response)\n\t\t\tif err == nil {\n\t\t\t\terr = writeErr\n\t\t\t}\n\t\t} else {\n\t\t\terr = c.internalErrorf(\"%#v returned a malformed result for %q: %w\", from, req.Method, respErr)\n\t\t}\n\t} else { // req is a notification\n\t\tif result != nil {\n\t\t\terr = c.internalErrorf(\"%#v returned a non-nil result for a %q Request without an ID\", from, req.Method)\n\t\t} else if err != nil {\n\t\t\terr = fmt.Errorf(\"%w: %q notification failed: %v\", ErrInternal, req.Method, err)\n\t\t}\n\t\tif err != nil {\n\t\t\t// TODO: can/should we do anything with this error beyond writing it to the event log?\n\t\t\t// (Is this the right label to attach to the log?)\n\t\t}\n\t}\n\n\t// Cancel the request to free any associated resources.\n\treq.cancel()\n\tc.updateInFlight(func(s *inFlightState) {\n\t\tif s.incoming == 0 {\n\t\t\tpanic(\"jsonrpc2_v2: processResult called when incoming count is already zero\")\n\t\t}\n\t\ts.incoming--\n\t})\n\treturn nil\n}\n\n// write is used by all things that write outgoing messages, including replies.\n// it makes sure that writes are atomic\nfunc (c *Connection) write(ctx context.Context, msg Message) error {\n\twriter := <-c.writer\n\tdefer func() { c.writer <- writer }()\n\terr := writer.Write(ctx, msg)\n\n\tif err != nil && ctx.Err() == nil {\n\t\t// The call to Write failed, and since ctx.Err() is nil we can't attribute\n\t\t// the failure (even indirectly) to Context cancellation. The writer appears\n\t\t// to be broken, and future writes are likely to also fail.\n\t\t//\n\t\t// If the read side of the connection is also broken, we might not even be\n\t\t// able to receive cancellation notifications. Since we can't reliably write\n\t\t// the results of incoming calls and can't receive explicit cancellations,\n\t\t// cancel the calls now.\n\t\tc.updateInFlight(func(s *inFlightState) {\n\t\t\tif s.writeErr == nil {\n\t\t\t\ts.writeErr = err\n\t\t\t\tfor _, r := range s.incomingByID {\n\t\t\t\t\tr.cancel()\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\treturn err\n}\n\n// internalErrorf reports an internal error. By default it panics, but if\n// c.onInternalError is non-nil it instead calls that and returns an error\n// wrapping ErrInternal.\nfunc (c *Connection) internalErrorf(format string, args ...any) error {\n\terr := fmt.Errorf(format, args...)\n\tif c.onInternalError == nil {\n\t\tpanic(\"jsonrpc2: \" + err.Error())\n\t}\n\tc.onInternalError(err)\n\n\treturn fmt.Errorf(\"%w: %v\", ErrInternal, err)\n}\n\n// notDone is a context.Context wrapper that returns a nil Done channel.\ntype notDone struct{ ctx context.Context }\n\nfunc (ic notDone) Value(key any) any {\n\treturn ic.ctx.Value(key)\n}\n\nfunc (notDone) Done() <-chan struct{}       { return nil }\nfunc (notDone) Err() error                  { return nil }\nfunc (notDone) Deadline() (time.Time, bool) { return time.Time{}, false }\n"
  },
  {
    "path": "internal/jsonrpc2_v2/frame.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Reader abstracts the transport mechanics from the JSON RPC protocol.\n// A Conn reads messages from the reader it was provided on construction,\n// and assumes that each call to Read fully transfers a single message,\n// or returns an error.\n// A reader is not safe for concurrent use, it is expected it will be used by\n// a single Conn in a safe manner.\ntype Reader interface {\n\t// Read gets the next message from the stream.\n\tRead(context.Context) (Message, error)\n}\n\n// Writer abstracts the transport mechanics from the JSON RPC protocol.\n// A Conn writes messages using the writer it was provided on construction,\n// and assumes that each call to Write fully transfers a single message,\n// or returns an error.\n// A writer is not safe for concurrent use, it is expected it will be used by\n// a single Conn in a safe manner.\ntype Writer interface {\n\t// Write sends a message to the stream.\n\tWrite(context.Context, Message) error\n}\n\n// Framer wraps low level byte readers and writers into jsonrpc2 message\n// readers and writers.\n// It is responsible for the framing and encoding of messages into wire form.\n//\n// TODO(rfindley): rethink the framer interface, as with JSONRPC2 batching\n// there is a need for Reader and Writer to be correlated, and while the\n// implementation of framing here allows that, it is not made explicit by the\n// interface.\n//\n// Perhaps a better interface would be\n//\n//\tFrame(io.ReadWriteCloser) (Reader, Writer).\ntype Framer interface {\n\t// Reader wraps a byte reader into a message reader.\n\tReader(io.Reader) Reader\n\t// Writer wraps a byte writer into a message writer.\n\tWriter(io.Writer) Writer\n}\n\n// RawFramer returns a new Framer.\n// The messages are sent with no wrapping, and rely on json decode consistency\n// to determine message boundaries.\nfunc RawFramer() Framer { return rawFramer{} }\n\ntype rawFramer struct{}\ntype rawReader struct{ in *json.Decoder }\ntype rawWriter struct{ out io.Writer }\n\nfunc (rawFramer) Reader(rw io.Reader) Reader {\n\treturn &rawReader{in: json.NewDecoder(rw)}\n}\n\nfunc (rawFramer) Writer(rw io.Writer) Writer {\n\treturn &rawWriter{out: rw}\n}\n\nfunc (r *rawReader) Read(ctx context.Context) (Message, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tdefault:\n\t}\n\tvar raw json.RawMessage\n\tif err := r.in.Decode(&raw); err != nil {\n\t\treturn nil, err\n\t}\n\tmsg, err := DecodeMessage(raw)\n\treturn msg, err\n}\n\nfunc (w *rawWriter) Write(ctx context.Context, msg Message) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tdefault:\n\t}\n\tdata, err := EncodeMessage(msg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling message: %v\", err)\n\t}\n\t_, err = w.out.Write(data)\n\treturn err\n}\n\n// HeaderFramer returns a new Framer.\n// The messages are sent with HTTP content length and MIME type headers.\n// This is the format used by LSP and others.\nfunc HeaderFramer() Framer { return headerFramer{} }\n\ntype headerFramer struct{}\ntype headerReader struct{ in *bufio.Reader }\ntype headerWriter struct{ out io.Writer }\n\nfunc (headerFramer) Reader(rw io.Reader) Reader {\n\treturn &headerReader{in: bufio.NewReader(rw)}\n}\n\nfunc (headerFramer) Writer(rw io.Writer) Writer {\n\treturn &headerWriter{out: rw}\n}\n\nfunc (r *headerReader) Read(ctx context.Context) (Message, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tdefault:\n\t}\n\n\tfirstRead := true // to detect a clean EOF below\n\tvar contentLength int64\n\t// read the header, stop on the first empty line\n\tfor {\n\t\tline, err := r.in.ReadString('\\n')\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tif firstRead && line == \"\" {\n\t\t\t\t\treturn nil, io.EOF // clean EOF\n\t\t\t\t}\n\t\t\t\terr = io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"failed reading header line: %w\", err)\n\t\t}\n\t\tfirstRead = false\n\n\t\tline = strings.TrimSpace(line)\n\t\t// check we have a header line\n\t\tif line == \"\" {\n\t\t\tbreak\n\t\t}\n\t\tcolon := strings.IndexRune(line, ':')\n\t\tif colon < 0 {\n\t\t\treturn nil, fmt.Errorf(\"invalid header line %q\", line)\n\t\t}\n\t\tname, value := line[:colon], strings.TrimSpace(line[colon+1:])\n\t\tswitch name {\n\t\tcase \"Content-Length\":\n\t\t\tif contentLength, err = strconv.ParseInt(value, 10, 32); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed parsing Content-Length: %v\", value)\n\t\t\t}\n\t\t\tif contentLength <= 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid Content-Length: %v\", contentLength)\n\t\t\t}\n\t\tdefault:\n\t\t\t// ignoring unknown headers\n\t\t}\n\t}\n\tif contentLength == 0 {\n\t\treturn nil, fmt.Errorf(\"missing Content-Length header\")\n\t}\n\tdata := make([]byte, contentLength)\n\t_, err := io.ReadFull(r.in, data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tmsg, err := DecodeMessage(data)\n\treturn msg, err\n}\n\nfunc (w *headerWriter) Write(ctx context.Context, msg Message) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tdefault:\n\t}\n\tdata, err := EncodeMessage(msg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling message: %v\", err)\n\t}\n\t_, err = fmt.Fprintf(w.out, \"Content-Length: %v\\r\\n\\r\\n\", len(data))\n\tif err == nil {\n\t\t_, err = w.out.Write(data)\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/jsonrpc2.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.\n// https://www.jsonrpc.org/specification\n// It is intended to be compatible with other implementations at the wire level.\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"errors\"\n)\n\nvar (\n\t// ErrIdleTimeout is returned when serving timed out waiting for new connections.\n\tErrIdleTimeout = errors.New(\"timed out waiting for new connections\")\n\n\t// ErrNotHandled is returned from a Handler or Preempter to indicate it did\n\t// not handle the request.\n\t//\n\t// If a Handler returns ErrNotHandled, the server replies with\n\t// ErrMethodNotFound.\n\tErrNotHandled = errors.New(\"JSON RPC not handled\")\n\n\t// ErrAsyncResponse is returned from a handler to indicate it will generate a\n\t// response asynchronously.\n\t//\n\t// ErrAsyncResponse must not be returned for notifications,\n\t// which do not receive responses.\n\tErrAsyncResponse = errors.New(\"JSON RPC asynchronous response\")\n)\n\n// Preempter handles messages on a connection before they are queued to the main\n// handler.\n// Primarily this is used for cancel handlers or notifications for which out of\n// order processing is not an issue.\ntype Preempter interface {\n\t// Preempt is invoked for each incoming request before it is queued for handling.\n\t//\n\t// If Preempt returns ErrNotHandled, the request will be queued,\n\t// and eventually passed to a Handle call.\n\t//\n\t// Otherwise, the result and error are processed as if returned by Handle.\n\t//\n\t// Preempt must not block. (The Context passed to it is for Values only.)\n\tPreempt(ctx context.Context, req *Request) (result any, err error)\n}\n\n// A PreempterFunc implements the Preempter interface for a standalone Preempt function.\ntype PreempterFunc func(ctx context.Context, req *Request) (any, error)\n\nfunc (f PreempterFunc) Preempt(ctx context.Context, req *Request) (any, error) {\n\treturn f(ctx, req)\n}\n\nvar _ Preempter = PreempterFunc(nil)\n\n// Handler handles messages on a connection.\ntype Handler interface {\n\t// Handle is invoked sequentially for each incoming request that has not\n\t// already been handled by a Preempter.\n\t//\n\t// If the Request has a nil ID, Handle must return a nil result,\n\t// and any error may be logged but will not be reported to the caller.\n\t//\n\t// If the Request has a non-nil ID, Handle must return either a\n\t// non-nil, JSON-marshalable result, or a non-nil error.\n\t//\n\t// The Context passed to Handle will be canceled if the\n\t// connection is broken or the request is canceled or completed.\n\t// (If Handle returns ErrAsyncResponse, ctx will remain uncanceled\n\t// until either Cancel or Respond is called for the request's ID.)\n\tHandle(ctx context.Context, req *Request) (result any, err error)\n}\n\ntype defaultHandler struct{}\n\nfunc (defaultHandler) Preempt(context.Context, *Request) (any, error) {\n\treturn nil, ErrNotHandled\n}\n\nfunc (defaultHandler) Handle(context.Context, *Request) (any, error) {\n\treturn nil, ErrNotHandled\n}\n\n// A HandlerFunc implements the Handler interface for a standalone Handle function.\ntype HandlerFunc func(ctx context.Context, req *Request) (any, error)\n\nfunc (f HandlerFunc) Handle(ctx context.Context, req *Request) (any, error) {\n\treturn f(ctx, req)\n}\n\nvar _ Handler = HandlerFunc(nil)\n\n// async is a small helper for operations with an asynchronous result that you\n// can wait for.\ntype async struct {\n\tready    chan struct{} // closed when done\n\tfirstErr chan error    // 1-buffered; contains either nil or the first non-nil error\n}\n\nfunc newAsync() *async {\n\tvar a async\n\ta.ready = make(chan struct{})\n\ta.firstErr = make(chan error, 1)\n\ta.firstErr <- nil\n\treturn &a\n}\n\nfunc (a *async) done() {\n\tclose(a.ready)\n}\n\nfunc (a *async) wait() error {\n\t<-a.ready\n\terr := <-a.firstErr\n\ta.firstErr <- err\n\treturn err\n}\n\nfunc (a *async) setError(err error) {\n\tstoredErr := <-a.firstErr\n\tif storedErr == nil {\n\t\tstoredErr = err\n\t}\n\ta.firstErr <- storedErr\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/jsonrpc2_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"path\"\n\t\"reflect\"\n\t\"testing\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\nvar callTests = []invoker{\n\tcall{\"no_args\", nil, true},\n\tcall{\"one_string\", \"fish\", \"got:fish\"},\n\tcall{\"one_number\", 10, \"got:10\"},\n\tcall{\"join\", []string{\"a\", \"b\", \"c\"}, \"a/b/c\"},\n\tsequence{\"notify\", []invoker{\n\t\tnotify{\"set\", 3},\n\t\tnotify{\"add\", 5},\n\t\tcall{\"get\", nil, 8},\n\t}},\n\tsequence{\"preempt\", []invoker{\n\t\tasync{\"a\", \"wait\", \"a\"},\n\t\tnotify{\"unblock\", \"a\"},\n\t\tcollect{\"a\", true, false},\n\t}},\n\tsequence{\"basic cancel\", []invoker{\n\t\tasync{\"b\", \"wait\", \"b\"},\n\t\tcancel{\"b\"},\n\t\tcollect{\"b\", nil, true},\n\t}},\n\tsequence{\"queue\", []invoker{\n\t\tasync{\"a\", \"wait\", \"a\"},\n\t\tnotify{\"set\", 1},\n\t\tnotify{\"add\", 2},\n\t\tnotify{\"add\", 3},\n\t\tnotify{\"add\", 4},\n\t\tcall{\"peek\", nil, 0}, // accumulator will not have any adds yet\n\t\tnotify{\"unblock\", \"a\"},\n\t\tcollect{\"a\", true, false},\n\t\tcall{\"get\", nil, 10}, // accumulator now has all the adds\n\t}},\n\tsequence{\"fork\", []invoker{\n\t\tasync{\"a\", \"fork\", \"a\"},\n\t\tnotify{\"set\", 1},\n\t\tnotify{\"add\", 2},\n\t\tnotify{\"add\", 3},\n\t\tnotify{\"add\", 4},\n\t\tcall{\"get\", nil, 10}, // fork will not have blocked the adds\n\t\tnotify{\"unblock\", \"a\"},\n\t\tcollect{\"a\", true, false},\n\t}},\n\tsequence{\"concurrent\", []invoker{\n\t\tasync{\"a\", \"fork\", \"a\"},\n\t\tnotify{\"unblock\", \"a\"},\n\t\tasync{\"b\", \"fork\", \"b\"},\n\t\tnotify{\"unblock\", \"b\"},\n\t\tcollect{\"a\", true, false},\n\t\tcollect{\"b\", true, false},\n\t}},\n}\n\ntype binder struct {\n\tframer  jsonrpc2.Framer\n\trunTest func(*handler)\n}\n\ntype handler struct {\n\tconn        *jsonrpc2.Connection\n\taccumulator int\n\twaiters     chan map[string]chan struct{}\n\tcalls       map[string]*jsonrpc2.AsyncCall\n}\n\ntype invoker interface {\n\tName() string\n\tInvoke(t *testing.T, ctx context.Context, h *handler)\n}\n\ntype notify struct {\n\tmethod string\n\tparams any\n}\n\ntype call struct {\n\tmethod string\n\tparams any\n\texpect any\n}\n\ntype async struct {\n\tname   string\n\tmethod string\n\tparams any\n}\n\ntype collect struct {\n\tname   string\n\texpect any\n\tfails  bool\n}\n\ntype cancel struct {\n\tname string\n}\n\ntype sequence struct {\n\tname  string\n\ttests []invoker\n}\n\ntype echo call\n\ntype cancelParams struct{ ID int64 }\n\nfunc TestConnectionRaw(t *testing.T) {\n\ttestConnection(t, jsonrpc2.RawFramer())\n}\n\nfunc TestConnectionHeader(t *testing.T) {\n\ttestConnection(t, jsonrpc2.HeaderFramer())\n}\n\nfunc testConnection(t *testing.T, framer jsonrpc2.Framer) {\n\tctx := context.Background()\n\tlistener, err := jsonrpc2.NetPipeListener(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tserver := jsonrpc2.NewServer(ctx, listener, binder{framer, nil})\n\tdefer func() {\n\t\tlistener.Close()\n\t\tserver.Wait()\n\t}()\n\n\tfor _, test := range callTests {\n\t\tt.Run(test.Name(), func(t *testing.T) {\n\t\t\tclient, err := jsonrpc2.Dial(ctx,\n\t\t\t\tlistener.Dialer(), binder{framer, func(h *handler) {\n\t\t\t\t\tdefer h.conn.Close()\n\t\t\t\t\ttest.Invoke(t, ctx, h)\n\t\t\t\t\tif call, ok := test.(*call); ok {\n\t\t\t\t\t\t// also run all simple call tests in echo mode\n\t\t\t\t\t\t(*echo)(call).Invoke(t, ctx, h)\n\t\t\t\t\t}\n\t\t\t\t}}, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tclient.Wait()\n\t\t})\n\t}\n}\n\nfunc (test notify) Name() string { return test.method }\nfunc (test notify) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\tif err := h.conn.Notify(ctx, test.method, test.params); err != nil {\n\t\tt.Fatalf(\"%v:Notify failed: %v\", test.method, err)\n\t}\n}\n\nfunc (test call) Name() string { return test.method }\nfunc (test call) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\tresults := newResults(test.expect)\n\tif err := h.conn.Call(ctx, test.method, test.params).Await(ctx, results); err != nil {\n\t\tt.Fatalf(\"%v:Call failed: %v\", test.method, err)\n\t}\n\tverifyResults(t, test.method, results, test.expect)\n}\n\nfunc (test echo) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\tresults := newResults(test.expect)\n\tif err := h.conn.Call(ctx, \"echo\", []any{test.method, test.params}).Await(ctx, results); err != nil {\n\t\tt.Fatalf(\"%v:Echo failed: %v\", test.method, err)\n\t}\n\tverifyResults(t, test.method, results, test.expect)\n}\n\nfunc (test async) Name() string { return test.name }\nfunc (test async) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\th.calls[test.name] = h.conn.Call(ctx, test.method, test.params)\n}\n\nfunc (test collect) Name() string { return test.name }\nfunc (test collect) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\to := h.calls[test.name]\n\tresults := newResults(test.expect)\n\terr := o.Await(ctx, results)\n\tswitch {\n\tcase test.fails && err == nil:\n\t\tt.Fatalf(\"%v:Collect was supposed to fail\", test.name)\n\tcase !test.fails && err != nil:\n\t\tt.Fatalf(\"%v:Collect failed: %v\", test.name, err)\n\t}\n\tverifyResults(t, test.name, results, test.expect)\n}\n\nfunc (test cancel) Name() string { return test.name }\nfunc (test cancel) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\to := h.calls[test.name]\n\tif err := h.conn.Notify(ctx, \"cancel\", &cancelParams{o.ID().Raw().(int64)}); err != nil {\n\t\tt.Fatalf(\"%v:Collect failed: %v\", test.name, err)\n\t}\n}\n\nfunc (test sequence) Name() string { return test.name }\nfunc (test sequence) Invoke(t *testing.T, ctx context.Context, h *handler) {\n\tfor _, child := range test.tests {\n\t\tchild.Invoke(t, ctx, h)\n\t}\n}\n\n// newResults makes a new empty copy of the expected type to put the results into\nfunc newResults(expect any) any {\n\tswitch e := expect.(type) {\n\tcase []any:\n\t\tvar r []any\n\t\tfor _, v := range e {\n\t\t\tr = append(r, reflect.New(reflect.TypeOf(v)).Interface())\n\t\t}\n\t\treturn r\n\tcase nil:\n\t\treturn nil\n\tdefault:\n\t\treturn reflect.New(reflect.TypeOf(expect)).Interface()\n\t}\n}\n\n// verifyResults compares the results to the expected values\nfunc verifyResults(t *testing.T, method string, results any, expect any) {\n\tif expect == nil {\n\t\tif results != nil {\n\t\t\tt.Errorf(\"%v:Got results %+v where none expected\", method, expect)\n\t\t}\n\t\treturn\n\t}\n\tval := reflect.Indirect(reflect.ValueOf(results)).Interface()\n\tif !reflect.DeepEqual(val, expect) {\n\t\tt.Errorf(\"%v:Results are incorrect, got %+v expect %+v\", method, val, expect)\n\t}\n}\n\nfunc (b binder) Bind(ctx context.Context, conn *jsonrpc2.Connection) jsonrpc2.ConnectionOptions {\n\th := &handler{\n\t\tconn:    conn,\n\t\twaiters: make(chan map[string]chan struct{}, 1),\n\t\tcalls:   make(map[string]*jsonrpc2.AsyncCall),\n\t}\n\th.waiters <- make(map[string]chan struct{})\n\tif b.runTest != nil {\n\t\tgo b.runTest(h)\n\t}\n\treturn jsonrpc2.ConnectionOptions{\n\t\tFramer:    b.framer,\n\t\tPreempter: h,\n\t\tHandler:   h,\n\t}\n}\n\nfunc (h *handler) waiter(name string) chan struct{} {\n\twaiters := <-h.waiters\n\tdefer func() { h.waiters <- waiters }()\n\twaiter, found := waiters[name]\n\tif !found {\n\t\twaiter = make(chan struct{})\n\t\twaiters[name] = waiter\n\t}\n\treturn waiter\n}\n\nfunc (h *handler) Preempt(ctx context.Context, req *jsonrpc2.Request) (any, error) {\n\tswitch req.Method {\n\tcase \"unblock\":\n\t\tvar name string\n\t\tif err := json.Unmarshal(req.Params, &name); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tclose(h.waiter(name))\n\t\treturn nil, nil\n\tcase \"peek\":\n\t\tif len(req.Params) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"%w: expected no params\", jsonrpc2.ErrInvalidParams)\n\t\t}\n\t\treturn h.accumulator, nil\n\tcase \"cancel\":\n\t\tvar params cancelParams\n\t\tif err := json.Unmarshal(req.Params, &params); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\th.conn.Cancel(jsonrpc2.Int64ID(params.ID))\n\t\treturn nil, nil\n\tdefault:\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n}\n\nfunc (h *handler) Handle(ctx context.Context, req *jsonrpc2.Request) (any, error) {\n\tswitch req.Method {\n\tcase \"no_args\":\n\t\tif len(req.Params) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"%w: expected no params\", jsonrpc2.ErrInvalidParams)\n\t\t}\n\t\treturn true, nil\n\tcase \"one_string\":\n\t\tvar v string\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\treturn \"got:\" + v, nil\n\tcase \"one_number\":\n\t\tvar v int\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\treturn fmt.Sprintf(\"got:%d\", v), nil\n\tcase \"set\":\n\t\tvar v int\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\th.accumulator = v\n\t\treturn nil, nil\n\tcase \"add\":\n\t\tvar v int\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\th.accumulator += v\n\t\treturn nil, nil\n\tcase \"get\":\n\t\tif len(req.Params) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"%w: expected no params\", jsonrpc2.ErrInvalidParams)\n\t\t}\n\t\treturn h.accumulator, nil\n\tcase \"join\":\n\t\tvar v []string\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\treturn path.Join(v...), nil\n\tcase \"echo\":\n\t\tvar v []any\n\t\tif err := json.Unmarshal(req.Params, &v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tvar result any\n\t\terr := h.conn.Call(ctx, v[0].(string), v[1]).Await(ctx, &result)\n\t\treturn result, err\n\tcase \"wait\":\n\t\tvar name string\n\t\tif err := json.Unmarshal(req.Params, &name); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\tselect {\n\t\tcase <-h.waiter(name):\n\t\t\treturn true, nil\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\tcase \"fork\":\n\t\tvar name string\n\t\tif err := json.Unmarshal(req.Params, &name); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", jsonrpc2.ErrParse, err)\n\t\t}\n\t\twaitFor := h.waiter(name)\n\t\tgo func() {\n\t\t\tselect {\n\t\t\tcase <-waitFor:\n\t\t\t\th.conn.Respond(req.ID, true, nil)\n\t\t\tcase <-ctx.Done():\n\t\t\t\th.conn.Respond(req.ID, nil, ctx.Err())\n\t\t\t}\n\t\t}()\n\t\treturn nil, jsonrpc2.ErrAsyncResponse\n\tdefault:\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/messages.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n)\n\n// ID is a Request identifier, which is defined by the spec to be a string, integer, or null.\n// https://www.jsonrpc.org/specification#request_object\ntype ID struct {\n\tvalue any\n}\n\n// MakeID coerces the given Go value to an ID. The value is assumed to be the\n// default JSON marshaling of a Request identifier -- nil, float64, or string.\n//\n// Returns an error if the value type was a valid Request ID type.\n//\n// TODO: ID can't be a json.Marshaler/Unmarshaler, because we want to omitzero.\n// Simplify this package by making ID json serializable once we can rely on\n// omitzero.\nfunc MakeID(v any) (ID, error) {\n\tswitch v := v.(type) {\n\tcase nil:\n\t\treturn ID{}, nil\n\tcase float64:\n\t\treturn Int64ID(int64(v)), nil\n\tcase string:\n\t\treturn StringID(v), nil\n\t}\n\treturn ID{}, fmt.Errorf(\"%w: invalid ID type %T\", ErrParse, v)\n}\n\n// Message is the interface to all jsonrpc2 message types.\n// They share no common functionality, but are a closed set of concrete types\n// that are allowed to implement this interface. The message types are *Request\n// and *Response.\ntype Message interface {\n\t// marshal builds the wire form from the API form.\n\t// It is private, which makes the set of Message implementations closed.\n\tmarshal(to *wireCombined)\n}\n\n// Request is a Message sent to a peer to request behavior.\n// If it has an ID it is a call, otherwise it is a notification.\ntype Request struct {\n\t// ID of this request, used to tie the Response back to the request.\n\t// This will be nil for notifications.\n\tID ID\n\t// Method is a string containing the method name to invoke.\n\tMethod string\n\t// Params is either a struct or an array with the parameters of the method.\n\tParams json.RawMessage\n}\n\n// Response is a Message used as a reply to a call Request.\n// It will have the same ID as the call it is a response to.\ntype Response struct {\n\t// result is the content of the response.\n\tResult json.RawMessage\n\t// err is set only if the call failed.\n\tError error\n\t// id of the request this is a response to.\n\tID ID\n}\n\n// StringID creates a new string request identifier.\nfunc StringID(s string) ID { return ID{value: s} }\n\n// Int64ID creates a new integer request identifier.\nfunc Int64ID(i int64) ID { return ID{value: i} }\n\n// IsValid returns true if the ID is a valid identifier.\n// The default value for ID will return false.\nfunc (id ID) IsValid() bool { return id.value != nil }\n\n// Raw returns the underlying value of the ID.\nfunc (id ID) Raw() any { return id.value }\n\n// NewNotification constructs a new Notification message for the supplied\n// method and parameters.\nfunc NewNotification(method string, params any) (*Request, error) {\n\tp, merr := marshalToRaw(params)\n\treturn &Request{Method: method, Params: p}, merr\n}\n\n// NewCall constructs a new Call message for the supplied ID, method and\n// parameters.\nfunc NewCall(id ID, method string, params any) (*Request, error) {\n\tp, merr := marshalToRaw(params)\n\treturn &Request{ID: id, Method: method, Params: p}, merr\n}\n\nfunc (msg *Request) IsCall() bool { return msg.ID.IsValid() }\n\nfunc (msg *Request) marshal(to *wireCombined) {\n\tto.ID = msg.ID.value\n\tto.Method = msg.Method\n\tto.Params = msg.Params\n}\n\n// NewResponse constructs a new Response message that is a reply to the\n// supplied. If err is set result may be ignored.\nfunc NewResponse(id ID, result any, rerr error) (*Response, error) {\n\tr, merr := marshalToRaw(result)\n\treturn &Response{ID: id, Result: r, Error: rerr}, merr\n}\n\nfunc (msg *Response) marshal(to *wireCombined) {\n\tto.ID = msg.ID.value\n\tto.Error = toWireError(msg.Error)\n\tto.Result = msg.Result\n}\n\nfunc toWireError(err error) *WireError {\n\tif err == nil {\n\t\t// no error, the response is complete\n\t\treturn nil\n\t}\n\tif err, ok := err.(*WireError); ok {\n\t\t// already a wire error, just use it\n\t\treturn err\n\t}\n\tresult := &WireError{Message: err.Error()}\n\tvar wrapped *WireError\n\tif errors.As(err, &wrapped) {\n\t\t// if we wrapped a wire error, keep the code from the wrapped error\n\t\t// but the message from the outer error\n\t\tresult.Code = wrapped.Code\n\t}\n\treturn result\n}\n\nfunc EncodeMessage(msg Message) ([]byte, error) {\n\twire := wireCombined{VersionTag: wireVersion}\n\tmsg.marshal(&wire)\n\tdata, err := json.Marshal(&wire)\n\tif err != nil {\n\t\treturn data, fmt.Errorf(\"marshaling jsonrpc message: %w\", err)\n\t}\n\treturn data, nil\n}\n\n// EncodeIndent is like EncodeMessage, but honors indents.\n// TODO(rfindley): refactor so that this concern is handled independently.\n// Perhaps we should pass in a json.Encoder?\nfunc EncodeIndent(msg Message, prefix, indent string) ([]byte, error) {\n\twire := wireCombined{VersionTag: wireVersion}\n\tmsg.marshal(&wire)\n\tdata, err := json.MarshalIndent(&wire, prefix, indent)\n\tif err != nil {\n\t\treturn data, fmt.Errorf(\"marshaling jsonrpc message: %w\", err)\n\t}\n\treturn data, nil\n}\n\nfunc DecodeMessage(data []byte) (Message, error) {\n\tmsg := wireCombined{}\n\tif err := json.Unmarshal(data, &msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshaling jsonrpc message: %w\", err)\n\t}\n\tif msg.VersionTag != wireVersion {\n\t\treturn nil, fmt.Errorf(\"invalid message version tag %q; expected %q\", msg.VersionTag, wireVersion)\n\t}\n\tid, err := MakeID(msg.ID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif msg.Method != \"\" {\n\t\t// has a method, must be a call\n\t\treturn &Request{\n\t\t\tMethod: msg.Method,\n\t\t\tID:     id,\n\t\t\tParams: msg.Params,\n\t\t}, nil\n\t}\n\t// no method, should be a response\n\tif !id.IsValid() {\n\t\treturn nil, ErrInvalidRequest\n\t}\n\tresp := &Response{\n\t\tID:     id,\n\t\tResult: msg.Result,\n\t}\n\t// we have to check if msg.Error is nil to avoid a typed error\n\tif msg.Error != nil {\n\t\tresp.Error = msg.Error\n\t}\n\treturn resp, nil\n}\n\nfunc marshalToRaw(obj any) (json.RawMessage, error) {\n\tif obj == nil {\n\t\treturn nil, nil\n\t}\n\tdata, err := json.Marshal(obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn json.RawMessage(data), nil\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/net.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n)\n\n// This file contains implementations of the transport primitives that use the standard network\n// package.\n\n// NetListenOptions is the optional arguments to the NetListen function.\ntype NetListenOptions struct {\n\tNetListenConfig net.ListenConfig\n\tNetDialer       net.Dialer\n}\n\n// NetListener returns a new Listener that listens on a socket using the net package.\nfunc NetListener(ctx context.Context, network, address string, options NetListenOptions) (Listener, error) {\n\tln, err := options.NetListenConfig.Listen(ctx, network, address)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &netListener{net: ln}, nil\n}\n\n// netListener is the implementation of Listener for connections made using the net package.\ntype netListener struct {\n\tnet net.Listener\n}\n\n// Accept blocks waiting for an incoming connection to the listener.\nfunc (l *netListener) Accept(context.Context) (io.ReadWriteCloser, error) {\n\treturn l.net.Accept()\n}\n\n// Close will cause the listener to stop listening. It will not close any connections that have\n// already been accepted.\nfunc (l *netListener) Close() error {\n\taddr := l.net.Addr()\n\terr := l.net.Close()\n\tif addr.Network() == \"unix\" {\n\t\trerr := os.Remove(addr.String())\n\t\tif rerr != nil && err == nil {\n\t\t\terr = rerr\n\t\t}\n\t}\n\treturn err\n}\n\n// Dialer returns a dialer that can be used to connect to the listener.\nfunc (l *netListener) Dialer() Dialer {\n\treturn NetDialer(l.net.Addr().Network(), l.net.Addr().String(), net.Dialer{})\n}\n\n// NetDialer returns a Dialer using the supplied standard network dialer.\nfunc NetDialer(network, address string, nd net.Dialer) Dialer {\n\treturn &netDialer{\n\t\tnetwork: network,\n\t\taddress: address,\n\t\tdialer:  nd,\n\t}\n}\n\ntype netDialer struct {\n\tnetwork string\n\taddress string\n\tdialer  net.Dialer\n}\n\nfunc (n *netDialer) Dial(ctx context.Context) (io.ReadWriteCloser, error) {\n\treturn n.dialer.DialContext(ctx, n.network, n.address)\n}\n\n// NetPipeListener returns a new Listener that listens using net.Pipe.\n// It is only possibly to connect to it using the Dialer returned by the\n// Dialer method, each call to that method will generate a new pipe the other\n// side of which will be returned from the Accept call.\nfunc NetPipeListener(ctx context.Context) (Listener, error) {\n\treturn &netPiper{\n\t\tdone:   make(chan struct{}),\n\t\tdialed: make(chan io.ReadWriteCloser),\n\t}, nil\n}\n\n// netPiper is the implementation of Listener build on top of net.Pipes.\ntype netPiper struct {\n\tdone   chan struct{}\n\tdialed chan io.ReadWriteCloser\n}\n\n// Accept blocks waiting for an incoming connection to the listener.\nfunc (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) {\n\t// Block until the pipe is dialed or the listener is closed,\n\t// preferring the latter if already closed at the start of Accept.\n\tselect {\n\tcase <-l.done:\n\t\treturn nil, net.ErrClosed\n\tdefault:\n\t}\n\tselect {\n\tcase rwc := <-l.dialed:\n\t\treturn rwc, nil\n\tcase <-l.done:\n\t\treturn nil, net.ErrClosed\n\t}\n}\n\n// Close will cause the listener to stop listening. It will not close any connections that have\n// already been accepted.\nfunc (l *netPiper) Close() error {\n\t// unblock any accept calls that are pending\n\tclose(l.done)\n\treturn nil\n}\n\nfunc (l *netPiper) Dialer() Dialer {\n\treturn l\n}\n\nfunc (l *netPiper) Dial(ctx context.Context) (io.ReadWriteCloser, error) {\n\tclient, server := net.Pipe()\n\n\tselect {\n\tcase l.dialed <- server:\n\t\treturn client, nil\n\n\tcase <-l.done:\n\t\tclient.Close()\n\t\tserver.Close()\n\t\treturn nil, net.ErrClosed\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/serve.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"runtime\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\n// Listener is implemented by protocols to accept new inbound connections.\ntype Listener interface {\n\t// Accept accepts an inbound connection to a server.\n\t// It blocks until either an inbound connection is made, or the listener is closed.\n\tAccept(context.Context) (io.ReadWriteCloser, error)\n\n\t// Close closes the listener.\n\t// Any blocked Accept or Dial operations will unblock and return errors.\n\tClose() error\n\n\t// Dialer returns a dialer that can be used to connect to this listener\n\t// locally.\n\t// If a listener does not implement this it will return nil.\n\tDialer() Dialer\n}\n\n// Dialer is used by clients to dial a server.\ntype Dialer interface {\n\t// Dial returns a new communication byte stream to a listening server.\n\tDial(ctx context.Context) (io.ReadWriteCloser, error)\n}\n\n// Server is a running server that is accepting incoming connections.\ntype Server struct {\n\tlistener Listener\n\tbinder   Binder\n\tasync    *async\n\n\tshutdownOnce sync.Once\n\tclosing      int32 // atomic: set to nonzero when Shutdown is called\n}\n\n// Dial uses the dialer to make a new connection, wraps the returned\n// reader and writer using the framer to make a stream, and then builds\n// a connection on top of that stream using the binder.\n//\n// The returned Connection will operate independently using the Preempter and/or\n// Handler provided by the Binder, and will release its own resources when the\n// connection is broken, but the caller may Close it earlier to stop accepting\n// (or sending) new requests.\n//\n// If non-nil, the onDone function is called when the connection is closed.\nfunc Dial(ctx context.Context, dialer Dialer, binder Binder, onDone func()) (*Connection, error) {\n\t// dial a server\n\trwc, err := dialer.Dial(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn bindConnection(ctx, rwc, binder, onDone), nil\n}\n\n// NewServer starts a new server listening for incoming connections and returns\n// it.\n// This returns a fully running and connected server, it does not block on\n// the listener.\n// You can call Wait to block on the server, or Shutdown to get the sever to\n// terminate gracefully.\n// To notice incoming connections, use an intercepting Binder.\nfunc NewServer(ctx context.Context, listener Listener, binder Binder) *Server {\n\tserver := &Server{\n\t\tlistener: listener,\n\t\tbinder:   binder,\n\t\tasync:    newAsync(),\n\t}\n\tgo server.run(ctx)\n\treturn server\n}\n\n// Wait returns only when the server has shut down.\nfunc (s *Server) Wait() error {\n\treturn s.async.wait()\n}\n\n// Shutdown informs the server to stop accepting new connections.\nfunc (s *Server) Shutdown() {\n\ts.shutdownOnce.Do(func() {\n\t\tatomic.StoreInt32(&s.closing, 1)\n\t\ts.listener.Close()\n\t})\n}\n\n// run accepts incoming connections from the listener,\n// If IdleTimeout is non-zero, run exits after there are no clients for this\n// duration, otherwise it exits only on error.\nfunc (s *Server) run(ctx context.Context) {\n\tdefer s.async.done()\n\n\tvar activeConns sync.WaitGroup\n\tfor {\n\t\trwc, err := s.listener.Accept(ctx)\n\t\tif err != nil {\n\t\t\t// Only Shutdown closes the listener. If we get an error after Shutdown is\n\t\t\t// called, assume that was the cause and don't report the error;\n\t\t\t// otherwise, report the error in case it is unexpected.\n\t\t\tif atomic.LoadInt32(&s.closing) == 0 {\n\t\t\t\ts.async.setError(err)\n\t\t\t}\n\t\t\t// We are done generating new connections for good.\n\t\t\tbreak\n\t\t}\n\n\t\t// A new inbound connection.\n\t\tactiveConns.Add(1)\n\t\t_ = bindConnection(ctx, rwc, s.binder, activeConns.Done) // unregisters itself when done\n\t}\n\tactiveConns.Wait()\n}\n\n// NewIdleListener wraps a listener with an idle timeout.\n//\n// When there are no active connections for at least the timeout duration,\n// calls to Accept will fail with ErrIdleTimeout.\n//\n// A connection is considered inactive as soon as its Close method is called.\nfunc NewIdleListener(timeout time.Duration, wrap Listener) Listener {\n\tl := &idleListener{\n\t\twrapped:   wrap,\n\t\ttimeout:   timeout,\n\t\tactive:    make(chan int, 1),\n\t\ttimedOut:  make(chan struct{}),\n\t\tidleTimer: make(chan *time.Timer, 1),\n\t}\n\tl.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired)\n\treturn l\n}\n\ntype idleListener struct {\n\twrapped Listener\n\ttimeout time.Duration\n\n\t// Only one of these channels is receivable at any given time.\n\tactive    chan int         // count of active connections; closed when Close is called if not timed out\n\ttimedOut  chan struct{}    // closed when the idle timer expires\n\tidleTimer chan *time.Timer // holds the timer only when idle\n}\n\n// Accept accepts an incoming connection.\n//\n// If an incoming connection is accepted concurrent to the listener being closed\n// due to idleness, the new connection is immediately closed.\nfunc (l *idleListener) Accept(ctx context.Context) (io.ReadWriteCloser, error) {\n\trwc, err := l.wrapped.Accept(ctx)\n\n\tselect {\n\tcase n, ok := <-l.active:\n\t\tif err != nil {\n\t\t\tif ok {\n\t\t\t\tl.active <- n\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tl.active <- n + 1\n\t\t} else {\n\t\t\t// l.wrapped.Close Close has been called, but Accept returned a\n\t\t\t// connection. This race can occur with concurrent Accept and Close calls\n\t\t\t// with any net.Listener, and it is benign: since the listener was closed\n\t\t\t// explicitly, it can't have also timed out.\n\t\t}\n\t\treturn l.newConn(rwc), nil\n\n\tcase <-l.timedOut:\n\t\tif err == nil {\n\t\t\t// Keeping the connection open would leave the listener simultaneously\n\t\t\t// active and closed due to idleness, which would be contradictory and\n\t\t\t// confusing. Close the connection and pretend that it never happened.\n\t\t\trwc.Close()\n\t\t} else {\n\t\t\t// In theory the timeout could have raced with an unrelated error return\n\t\t\t// from Accept. However, ErrIdleTimeout is arguably still valid (since we\n\t\t\t// would have closed due to the timeout independent of the error), and the\n\t\t\t// harm from returning a spurious ErrIdleTimeout is negligible anyway.\n\t\t}\n\t\treturn nil, ErrIdleTimeout\n\n\tcase timer := <-l.idleTimer:\n\t\tif err != nil {\n\t\t\t// The idle timer doesn't run until it receives itself from the idleTimer\n\t\t\t// channel, so it can't have called l.wrapped.Close yet and thus err can't\n\t\t\t// be ErrIdleTimeout. Leave the idle timer as it was and return whatever\n\t\t\t// error we got.\n\t\t\tl.idleTimer <- timer\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif !timer.Stop() {\n\t\t\t// Failed to stop the timer — the timer goroutine is in the process of\n\t\t\t// firing. Send the timer back to the timer goroutine so that it can\n\t\t\t// safely close the timedOut channel, and then wait for the listener to\n\t\t\t// actually be closed before we return ErrIdleTimeout.\n\t\t\tl.idleTimer <- timer\n\t\t\trwc.Close()\n\t\t\t<-l.timedOut\n\t\t\treturn nil, ErrIdleTimeout\n\t\t}\n\n\t\tl.active <- 1\n\t\treturn l.newConn(rwc), nil\n\t}\n}\n\nfunc (l *idleListener) Close() error {\n\tselect {\n\tcase _, ok := <-l.active:\n\t\tif ok {\n\t\t\tclose(l.active)\n\t\t}\n\n\tcase <-l.timedOut:\n\t\t// Already closed by the timer; take care not to double-close if the caller\n\t\t// only explicitly invokes this Close method once, since the io.Closer\n\t\t// interface explicitly leaves doubled Close calls undefined.\n\t\treturn ErrIdleTimeout\n\n\tcase timer := <-l.idleTimer:\n\t\tif !timer.Stop() {\n\t\t\t// Couldn't stop the timer. It shouldn't take long to run, so just wait\n\t\t\t// (so that the Listener is guaranteed to be closed before we return)\n\t\t\t// and pretend that this call happened afterward.\n\t\t\t// That way we won't leak any timers or goroutines when Close returns.\n\t\t\tl.idleTimer <- timer\n\t\t\t<-l.timedOut\n\t\t\treturn ErrIdleTimeout\n\t\t}\n\t\tclose(l.active)\n\t}\n\n\treturn l.wrapped.Close()\n}\n\nfunc (l *idleListener) Dialer() Dialer {\n\treturn l.wrapped.Dialer()\n}\n\nfunc (l *idleListener) timerExpired() {\n\tselect {\n\tcase n, ok := <-l.active:\n\t\tif ok {\n\t\t\tpanic(fmt.Sprintf(\"jsonrpc2: idleListener idle timer fired with %d connections still active\", n))\n\t\t} else {\n\t\t\tpanic(\"jsonrpc2: Close finished with idle timer still running\")\n\t\t}\n\n\tcase <-l.timedOut:\n\t\tpanic(\"jsonrpc2: idleListener idle timer fired more than once\")\n\n\tcase <-l.idleTimer:\n\t\t// The timer for this very call!\n\t}\n\n\t// Close the Listener with all channels still blocked to ensure that this call\n\t// to l.wrapped.Close doesn't race with the one in l.Close.\n\tdefer close(l.timedOut)\n\tl.wrapped.Close()\n}\n\nfunc (l *idleListener) connClosed() {\n\tselect {\n\tcase n, ok := <-l.active:\n\t\tif !ok {\n\t\t\t// l is already closed, so it can't close due to idleness,\n\t\t\t// and we don't need to track the number of active connections any more.\n\t\t\treturn\n\t\t}\n\t\tn--\n\t\tif n == 0 {\n\t\t\tl.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired)\n\t\t} else {\n\t\t\tl.active <- n\n\t\t}\n\n\tcase <-l.timedOut:\n\t\tpanic(\"jsonrpc2: idleListener idle timer fired before last active connection was closed\")\n\n\tcase <-l.idleTimer:\n\t\tpanic(\"jsonrpc2: idleListener idle timer active before last active connection was closed\")\n\t}\n}\n\ntype idleListenerConn struct {\n\twrapped   io.ReadWriteCloser\n\tl         *idleListener\n\tcloseOnce sync.Once\n}\n\nfunc (l *idleListener) newConn(rwc io.ReadWriteCloser) *idleListenerConn {\n\tc := &idleListenerConn{\n\t\twrapped: rwc,\n\t\tl:       l,\n\t}\n\n\t// A caller that forgets to call Close may disrupt the idleListener's\n\t// accounting, even though the file descriptor for the underlying connection\n\t// may eventually be garbage-collected anyway.\n\t//\n\t// Set a (best-effort) finalizer to verify that a Close call always occurs.\n\t// (We will clear the finalizer explicitly in Close.)\n\truntime.SetFinalizer(c, func(c *idleListenerConn) {\n\t\tpanic(\"jsonrpc2: IdleListener connection became unreachable without a call to Close\")\n\t})\n\n\treturn c\n}\n\nfunc (c *idleListenerConn) Read(p []byte) (int, error)  { return c.wrapped.Read(p) }\nfunc (c *idleListenerConn) Write(p []byte) (int, error) { return c.wrapped.Write(p) }\n\nfunc (c *idleListenerConn) Close() error {\n\tdefer c.closeOnce.Do(func() {\n\t\tc.l.connClosed()\n\t\truntime.SetFinalizer(c, nil)\n\t})\n\treturn c.wrapped.Close()\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/serve_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"testing\"\n\t\"time\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\n// needsLocalhostNet skips t if networking does not work for ports opened\n// with \"localhost\".\n// forked from golang.org/x/tools/internal/testenv.\nfunc needsLocalhostNet(t testing.TB) {\n\tswitch runtime.GOOS {\n\tcase \"js\", \"wasip1\":\n\t\tt.Skipf(`Listening on \"localhost\" fails on %s; see https://go.dev/issue/59718`, runtime.GOOS)\n\t}\n}\n\nfunc TestIdleTimeout(t *testing.T) {\n\tneedsLocalhostNet(t)\n\n\t// Use a panicking time.AfterFunc instead of context.WithTimeout so that we\n\t// get a goroutine dump on failure. We expect the test to take on the order of\n\t// a few tens of milliseconds at most, so 10s should be several orders of\n\t// magnitude of headroom.\n\ttimer := time.AfterFunc(10*time.Second, func() {\n\t\tdebug.SetTraceback(\"all\")\n\t\tpanic(\"TestIdleTimeout deadlocked\")\n\t})\n\tdefer timer.Stop()\n\n\tctx := context.Background()\n\n\ttry := func(d time.Duration) (longEnough bool) {\n\t\tlistener, err := jsonrpc2.NetListener(ctx, \"tcp\", \"localhost:0\", jsonrpc2.NetListenOptions{})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tidleStart := time.Now()\n\t\tlistener = jsonrpc2.NewIdleListener(d, listener)\n\t\tdefer listener.Close()\n\n\t\tserver := jsonrpc2.NewServer(ctx, listener, jsonrpc2.ConnectionOptions{})\n\n\t\t// Exercise some connection/disconnection patterns, and then assert that when\n\t\t// our timer fires, the server exits.\n\t\tconn1, err := jsonrpc2.Dial(ctx, listener.Dialer(), jsonrpc2.ConnectionOptions{}, nil)\n\t\tif err != nil {\n\t\t\tif since := time.Since(idleStart); since < d {\n\t\t\t\tt.Fatalf(\"conn1 failed to connect after %v: %v\", since, err)\n\t\t\t}\n\t\t\tt.Log(\"jsonrpc2.Dial:\", err)\n\t\t\treturn false // Took to long to dial, so the failure could have been due to the idle timeout.\n\t\t}\n\t\t// On the server side, Accept can race with the connection timing out.\n\t\t// Send a call and wait for the response to ensure that the connection was\n\t\t// actually fully accepted.\n\t\tac := conn1.Call(ctx, \"ping\", nil)\n\t\tif err := ac.Await(ctx, nil); !errors.Is(err, jsonrpc2.ErrMethodNotFound) {\n\t\t\tif since := time.Since(idleStart); since < d {\n\t\t\t\tt.Fatalf(\"conn1 broken after %v: %v\", since, err)\n\t\t\t}\n\t\t\tt.Log(`conn1.Call(ctx, \"ping\", nil):`, err)\n\t\t\tconn1.Close()\n\t\t\treturn false\n\t\t}\n\n\t\t// Since conn1 was successfully accepted and remains open, the server is\n\t\t// definitely non-idle. Dialing another simultaneous connection should\n\t\t// succeed.\n\t\tconn2, err := jsonrpc2.Dial(ctx, listener.Dialer(), jsonrpc2.ConnectionOptions{}, nil)\n\t\tif err != nil {\n\t\t\tconn1.Close()\n\t\t\tt.Fatalf(\"conn2 failed to connect while non-idle after %v: %v\", time.Since(idleStart), err)\n\t\t\treturn false\n\t\t}\n\t\t// Ensure that conn2 is also accepted on the server side before we close\n\t\t// conn1. Otherwise, the connection can appear idle if the server processes\n\t\t// the closure of conn1 and the idle timeout before it finally notices conn2\n\t\t// in the accept queue.\n\t\t// (That failure mode may explain the failure noted in\n\t\t// https://go.dev/issue/49387#issuecomment-1303979877.)\n\t\tac = conn2.Call(ctx, \"ping\", nil)\n\t\tif err := ac.Await(ctx, nil); !errors.Is(err, jsonrpc2.ErrMethodNotFound) {\n\t\t\tt.Fatalf(\"conn2 broken while non-idle after %v: %v\", time.Since(idleStart), err)\n\t\t}\n\n\t\tif err := conn1.Close(); err != nil {\n\t\t\tt.Fatalf(\"conn1.Close failed with error: %v\", err)\n\t\t}\n\t\tidleStart = time.Now()\n\t\tif err := conn2.Close(); err != nil {\n\t\t\tt.Fatalf(\"conn2.Close failed with error: %v\", err)\n\t\t}\n\n\t\tconn3, err := jsonrpc2.Dial(ctx, listener.Dialer(), jsonrpc2.ConnectionOptions{}, nil)\n\t\tif err != nil {\n\t\t\tif since := time.Since(idleStart); since < d {\n\t\t\t\tt.Fatalf(\"conn3 failed to connect after %v: %v\", since, err)\n\t\t\t}\n\t\t\tt.Log(\"jsonrpc2.Dial:\", err)\n\t\t\treturn false // Took to long to dial, so the failure could have been due to the idle timeout.\n\t\t}\n\n\t\tac = conn3.Call(ctx, \"ping\", nil)\n\t\tif err := ac.Await(ctx, nil); !errors.Is(err, jsonrpc2.ErrMethodNotFound) {\n\t\t\tif since := time.Since(idleStart); since < d {\n\t\t\t\tt.Fatalf(\"conn3 broken after %v: %v\", since, err)\n\t\t\t}\n\t\t\tt.Log(`conn3.Call(ctx, \"ping\", nil):`, err)\n\t\t\tconn3.Close()\n\t\t\treturn false\n\t\t}\n\n\t\tidleStart = time.Now()\n\t\tif err := conn3.Close(); err != nil {\n\t\t\tt.Fatalf(\"conn3.Close failed with error: %v\", err)\n\t\t}\n\n\t\tserverError := server.Wait()\n\n\t\tif !errors.Is(serverError, jsonrpc2.ErrIdleTimeout) {\n\t\t\tt.Errorf(\"run() returned error %v, want %v\", serverError, jsonrpc2.ErrIdleTimeout)\n\t\t}\n\t\tif since := time.Since(idleStart); since < d {\n\t\t\tt.Errorf(\"server shut down after %v idle; want at least %v\", since, d)\n\t\t}\n\t\treturn true\n\t}\n\n\td := 1 * time.Millisecond\n\tfor {\n\t\tt.Logf(\"testing with idle timeout %v\", d)\n\t\tif !try(d) {\n\t\t\td *= 2\n\t\t\tcontinue\n\t\t}\n\t\tbreak\n\t}\n}\n\ntype msg struct {\n\tMsg string\n}\n\ntype fakeHandler struct{}\n\nfunc (fakeHandler) Handle(ctx context.Context, req *jsonrpc2.Request) (any, error) {\n\tswitch req.Method {\n\tcase \"ping\":\n\t\treturn &msg{\"pong\"}, nil\n\tdefault:\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n}\n\nfunc TestServe(t *testing.T) {\n\tctx := context.Background()\n\n\ttests := []struct {\n\t\tname    string\n\t\tfactory func(context.Context, testing.TB) (jsonrpc2.Listener, error)\n\t}{\n\t\t{\"tcp\", func(ctx context.Context, t testing.TB) (jsonrpc2.Listener, error) {\n\t\t\tneedsLocalhostNet(t)\n\t\t\treturn jsonrpc2.NetListener(ctx, \"tcp\", \"localhost:0\", jsonrpc2.NetListenOptions{})\n\t\t}},\n\t\t{\"pipe\", func(ctx context.Context, t testing.TB) (jsonrpc2.Listener, error) {\n\t\t\treturn jsonrpc2.NetPipeListener(ctx)\n\t\t}},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tfake, err := test.factory(ctx, t)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tconn, shutdown, err := newFake(t, ctx, fake)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer shutdown()\n\t\t\tvar got msg\n\t\t\tif err := conn.Call(ctx, \"ping\", &msg{\"ting\"}).Await(ctx, &got); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif want := \"pong\"; got.Msg != want {\n\t\t\t\tt.Errorf(\"conn.Call(...): returned %q, want %q\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc newFake(t *testing.T, ctx context.Context, l jsonrpc2.Listener) (*jsonrpc2.Connection, func(), error) {\n\tserver := jsonrpc2.NewServer(ctx, l, jsonrpc2.ConnectionOptions{\n\t\tHandler: fakeHandler{},\n\t})\n\n\tclient, err := jsonrpc2.Dial(ctx,\n\t\tl.Dialer(),\n\t\tjsonrpc2.ConnectionOptions{\n\t\t\tHandler: fakeHandler{},\n\t\t}, nil)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn client, func() {\n\t\tif err := l.Close(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := client.Close(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tserver.Wait()\n\t}, nil\n}\n\n// TestIdleListenerAcceptCloseRace checks for the Accept/Close race fixed in CL 388597.\n//\n// (A bug in the idleListener implementation caused a successful Accept to block\n// on sending to a background goroutine that could have already exited.)\nfunc TestIdleListenerAcceptCloseRace(t *testing.T) {\n\tctx := context.Background()\n\n\tn := 10\n\n\t// Each iteration of the loop appears to take around a millisecond, so to\n\t// avoid spurious failures we'll set the watchdog for three orders of\n\t// magnitude longer. When the bug was present, this reproduced the deadlock\n\t// reliably on a Linux workstation when run with -count=100, which should be\n\t// frequent enough to show up on the Go build dashboard if it regresses.\n\twatchdog := time.Duration(n) * 1000 * time.Millisecond\n\ttimer := time.AfterFunc(watchdog, func() {\n\t\tdebug.SetTraceback(\"all\")\n\t\tpanic(fmt.Sprintf(\"%s deadlocked after %v\", t.Name(), watchdog))\n\t})\n\tdefer timer.Stop()\n\n\tfor ; n > 0; n-- {\n\t\tlistener, err := jsonrpc2.NetPipeListener(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tlistener = jsonrpc2.NewIdleListener(24*time.Hour, listener)\n\n\t\tdone := make(chan struct{})\n\t\tgo func() {\n\t\t\tconn, err := jsonrpc2.Dial(ctx, listener.Dialer(), jsonrpc2.ConnectionOptions{}, nil)\n\t\t\tlistener.Close()\n\t\t\tif err == nil {\n\t\t\t\tconn.Close()\n\t\t\t}\n\t\t\tclose(done)\n\t\t}()\n\n\t\t// Accept may return a non-nil error if Close closes the underlying network\n\t\t// connection before the wrapped Accept call unblocks. However, it must not\n\t\t// deadlock!\n\t\tc, err := listener.Accept(ctx)\n\t\tif err == nil {\n\t\t\tc.Close()\n\t\t}\n\t\t<-done\n\t}\n}\n\n// TestCloseCallRace checks for a race resulting in a deadlock when a Call on\n// one side of the connection races with a Close (or otherwise broken\n// connection) initiated from the other side.\n//\n// (The Call method was waiting for a result from the Read goroutine to\n// determine which error value to return, but the Read goroutine was waiting for\n// in-flight calls to complete before reporting that result.)\nfunc TestCloseCallRace(t *testing.T) {\n\tctx := context.Background()\n\tn := 10\n\n\twatchdog := time.Duration(n) * 1000 * time.Millisecond\n\ttimer := time.AfterFunc(watchdog, func() {\n\t\tdebug.SetTraceback(\"all\")\n\t\tpanic(fmt.Sprintf(\"%s deadlocked after %v\", t.Name(), watchdog))\n\t})\n\tdefer timer.Stop()\n\n\tfor ; n > 0; n-- {\n\t\tlistener, err := jsonrpc2.NetPipeListener(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tpokec := make(chan *jsonrpc2.AsyncCall, 1)\n\n\t\ts := jsonrpc2.NewServer(ctx, listener, jsonrpc2.BinderFunc(func(_ context.Context, srvConn *jsonrpc2.Connection) jsonrpc2.ConnectionOptions {\n\t\t\th := jsonrpc2.HandlerFunc(func(ctx context.Context, _ *jsonrpc2.Request) (any, error) {\n\t\t\t\t// Start a concurrent call from the server to the client.\n\t\t\t\t// The point of this test is to ensure this doesn't deadlock\n\t\t\t\t// if the client shuts down the connection concurrently.\n\t\t\t\t//\n\t\t\t\t// The racing Call may or may not receive a response: it should get a\n\t\t\t\t// response if it is sent before the client closes the connection, and\n\t\t\t\t// it should fail with some kind of \"connection closed\" error otherwise.\n\t\t\t\tgo func() {\n\t\t\t\t\tpokec <- srvConn.Call(ctx, \"poke\", nil)\n\t\t\t\t}()\n\n\t\t\t\treturn &msg{\"pong\"}, nil\n\t\t\t})\n\t\t\treturn jsonrpc2.ConnectionOptions{Handler: h}\n\t\t}))\n\n\t\tdialConn, err := jsonrpc2.Dial(ctx, listener.Dialer(), jsonrpc2.ConnectionOptions{}, nil)\n\t\tif err != nil {\n\t\t\tlistener.Close()\n\t\t\ts.Wait()\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Calling any method on the server should provoke it to asynchronously call\n\t\t// us back. While it is starting that call, we will close the connection.\n\t\tif err := dialConn.Call(ctx, \"ping\", nil).Await(ctx, nil); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t\tif err := dialConn.Close(); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\n\t\t// Ensure that the Call on the server side did not block forever when the\n\t\t// connection closed.\n\t\tpokeCall := <-pokec\n\t\tif err := pokeCall.Await(ctx, nil); err == nil {\n\t\t\tt.Errorf(\"unexpected nil error from server-initited call\")\n\t\t} else if errors.Is(err, jsonrpc2.ErrMethodNotFound) {\n\t\t\t// The call completed before the Close reached the handler.\n\t\t} else {\n\t\t\t// The error was something else.\n\t\t\tt.Logf(\"server-initiated call completed with expected error: %v\", err)\n\t\t}\n\n\t\tlistener.Close()\n\t\ts.Wait()\n\t}\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/wire.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2\n\nimport (\n\t\"encoding/json\"\n)\n\n// This file contains the go forms of the wire specification.\n// see http://www.jsonrpc.org/specification for details\n\nvar (\n\t// ErrParse is used when invalid JSON was received by the server.\n\tErrParse = NewError(-32700, \"JSON RPC parse error\")\n\t// ErrInvalidRequest is used when the JSON sent is not a valid Request object.\n\tErrInvalidRequest = NewError(-32600, \"JSON RPC invalid request\")\n\t// ErrMethodNotFound should be returned by the handler when the method does\n\t// not exist / is not available.\n\tErrMethodNotFound = NewError(-32601, \"JSON RPC method not found\")\n\t// ErrInvalidParams should be returned by the handler when method\n\t// parameter(s) were invalid.\n\tErrInvalidParams = NewError(-32602, \"JSON RPC invalid params\")\n\t// ErrInternal indicates a failure to process a call correctly\n\tErrInternal = NewError(-32603, \"JSON RPC internal error\")\n\n\t// The following errors are not part of the json specification, but\n\t// compliant extensions specific to this implementation.\n\n\t// ErrServerOverloaded is returned when a message was refused due to a\n\t// server being temporarily unable to accept any new messages.\n\tErrServerOverloaded = NewError(-32000, \"JSON RPC overloaded\")\n\t// ErrUnknown should be used for all non coded errors.\n\tErrUnknown = NewError(-32001, \"JSON RPC unknown error\")\n\t// ErrServerClosing is returned for calls that arrive while the server is closing.\n\tErrServerClosing = NewError(-32002, \"JSON RPC server is closing\")\n\t// ErrClientClosing is a dummy error returned for calls initiated while the client is closing.\n\tErrClientClosing = NewError(-32003, \"JSON RPC client is closing\")\n)\n\nconst wireVersion = \"2.0\"\n\n// wireCombined has all the fields of both Request and Response.\n// We can decode this and then work out which it is.\ntype wireCombined struct {\n\tVersionTag string          `json:\"jsonrpc\"`\n\tID         any             `json:\"id,omitempty\"`\n\tMethod     string          `json:\"method,omitempty\"`\n\tParams     json.RawMessage `json:\"params,omitempty\"`\n\tResult     json.RawMessage `json:\"result,omitempty\"`\n\tError      *WireError      `json:\"error,omitempty\"`\n}\n\n// WireError represents a structured error in a Response.\ntype WireError struct {\n\t// Code is an error code indicating the type of failure.\n\tCode int64 `json:\"code\"`\n\t// Message is a short description of the error.\n\tMessage string `json:\"message\"`\n\t// Data is optional structured data containing additional information about the error.\n\tData json.RawMessage `json:\"data,omitempty\"`\n}\n\n// NewError returns an error that will encode on the wire correctly.\n// The standard codes are made available from this package, this function should\n// only be used to build errors for application specific codes as allowed by the\n// specification.\nfunc NewError(code int64, message string) error {\n\treturn &WireError{\n\t\tCode:    code,\n\t\tMessage: message,\n\t}\n}\n\nfunc (err *WireError) Error() string {\n\treturn err.Message\n}\n\nfunc (err *WireError) Is(other error) bool {\n\tw, ok := other.(*WireError)\n\tif !ok {\n\t\treturn false\n\t}\n\treturn err.Code == w.Code\n}\n"
  },
  {
    "path": "internal/jsonrpc2_v2/wire_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonrpc2_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"testing\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\nfunc TestWireMessage(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tname    string\n\t\tmsg     jsonrpc2.Message\n\t\tencoded []byte\n\t}{{\n\t\tname:    \"notification\",\n\t\tmsg:     newNotification(\"alive\", nil),\n\t\tencoded: []byte(`{\"jsonrpc\":\"2.0\",\"method\":\"alive\"}`),\n\t}, {\n\t\tname:    \"call\",\n\t\tmsg:     newCall(\"msg1\", \"ping\", nil),\n\t\tencoded: []byte(`{\"jsonrpc\":\"2.0\",\"id\":\"msg1\",\"method\":\"ping\"}`),\n\t}, {\n\t\tname:    \"response\",\n\t\tmsg:     newResponse(\"msg2\", \"pong\", nil),\n\t\tencoded: []byte(`{\"jsonrpc\":\"2.0\",\"id\":\"msg2\",\"result\":\"pong\"}`),\n\t}, {\n\t\tname:    \"numerical id\",\n\t\tmsg:     newCall(1, \"poke\", nil),\n\t\tencoded: []byte(`{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"poke\"}`),\n\t}, {\n\t\t// originally reported in #39719, this checks that result is not present if\n\t\t// it is an error response\n\t\tname: \"computing fix edits\",\n\t\tmsg:  newResponse(3, nil, jsonrpc2.NewError(0, \"computing fix edits\")),\n\t\tencoded: []byte(`{\n\t\t\"jsonrpc\":\"2.0\",\n\t\t\"id\":3,\n\t\t\"error\":{\n\t\t\t\"code\":0,\n\t\t\t\"message\":\"computing fix edits\"\n\t\t}\n\t}`),\n\t}} {\n\t\tb, err := jsonrpc2.EncodeMessage(test.msg)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tcheckJSON(t, b, test.encoded)\n\t\tmsg, err := jsonrpc2.DecodeMessage(test.encoded)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !reflect.DeepEqual(msg, test.msg) {\n\t\t\tt.Errorf(\"decoded message does not match\\nGot:\\n%+#v\\nWant:\\n%+#v\", msg, test.msg)\n\t\t}\n\t}\n}\n\nfunc newNotification(method string, params any) jsonrpc2.Message {\n\tmsg, err := jsonrpc2.NewNotification(method, params)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn msg\n}\n\nfunc newID(id any) jsonrpc2.ID {\n\tswitch v := id.(type) {\n\tcase nil:\n\t\treturn jsonrpc2.ID{}\n\tcase string:\n\t\treturn jsonrpc2.StringID(v)\n\tcase int:\n\t\treturn jsonrpc2.Int64ID(int64(v))\n\tcase int64:\n\t\treturn jsonrpc2.Int64ID(v)\n\tdefault:\n\t\tpanic(\"invalid ID type\")\n\t}\n}\n\nfunc newCall(id any, method string, params any) jsonrpc2.Message {\n\tmsg, err := jsonrpc2.NewCall(newID(id), method, params)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn msg\n}\n\nfunc newResponse(id any, result any, rerr error) jsonrpc2.Message {\n\tmsg, err := jsonrpc2.NewResponse(newID(id), result, rerr)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn msg\n}\n\nfunc checkJSON(t *testing.T, got, want []byte) {\n\t// compare the compact form, to allow for formatting differences\n\tg := &bytes.Buffer{}\n\tif err := json.Compact(g, []byte(got)); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tw := &bytes.Buffer{}\n\tif err := json.Compact(w, []byte(want)); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif g.String() != w.String() {\n\t\tt.Errorf(\"encoded message does not match\\nGot:\\n%s\\nWant:\\n%s\", g, w)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/CONTRIBUTING.md",
    "content": "# Contributing to the Go MCP SDK\n\nThank you for your interest in contributing! The Go SDK needs active\ncontributions to keep up with changes in the MCP spec, fix bugs, and accommodate\nnew and emerging use-cases. We welcome all forms of contribution, from filing\nand reviewing issues, to contributing fixes, to proposing and implementing new\nfeatures.\n\nAs described in the [design document](./design/design.md), it is important for\nthe MCP SDK to remain idiomatic, future-proof, and extensible. The process\ndescribed here is intended to ensure that the SDK evolves safely and\ntransparently, while adhering to these goals.\n\n## Development setup\n\nThis module can be built and tested using the standard Go toolchain. Run `go\ntest ./...` to run all its tests.\n\nTo test changes to this module against another module that uses the SDK, we\nrecommend using a [`go.work` file](https://go.dev/doc/tutorial/workspaces) to\ndefine a multi-module workspace. For example, if your directory contains a\n`project` directory containing your project, and a `go-sdk` directory\ncontaining the SDK, run:\n\n```sh\ngo work init ./project ./go-sdk\n```\n\n## Filing issues\n\nThis project uses the [GitHub issue\ntracker](https://github.com/modelcontextprotocol/go-sdk/issues) for issues. The\nprocess for filing bugs and proposals is described below.\n\nTODO(rfindley): describe a process for asking general questions in the public\nMCP discord server.\n\n### Bugs\n\nPlease [report\nbugs](https://github.com/modelcontextprotocol/go-sdk/issues/new). If the SDK is\nnot working as you expected, it is likely due to a bug or inadequate\ndocumentation, and reporting an issue will help us address this shortcoming.\n\nWhen reporting a bug, make sure to answer these five questions:\n\n1. What did you do?\n2. What did you see?\n3. What did you expect to see?\n4. What version of the Go MCP SDK are you using?\n5. What version of Go are you using (`go version`)?\n\n### Proposals\n\nA proposal is an issue that proposes a new API for the SDK, or a change to the\nsignature or behavior of an existing API. Proposals are be labeled with the\n'Proposal' label, and require an explicit approval from a maintainer before\nbeing accepted (indicated by the 'Proposal-Accepted' label). Proposals must\nremain open for at least a week to allow discussion before being accepted or\ndeclined by a maintainer.\n\nProposals that are straightforward and uncontroversial may be approved based on\nGitHub discussion. However, proposals that are deemed to be sufficiently\nunclear or complicated may be deferred to a regular steering meeting (see\n'Governance' below).\n\nThis process is similar to the [Go proposal\nprocess](https://github.com/golang/proposal), but is necessarily lighter weight\nto accommodate the greater rate of change expected for the SDK.\n\n## Contributing code\n\nThe project uses GitHub pull requests (PRs) to review changes.\n\nAny significant change should be associated with a GitHub issue. Issues that\nare deemed to be good opportunities for contribution are be labeled ['Help\nWanted'](https://github.com/modelcontextprotocol/go-sdk/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22).\nIf you want to work on such an issue, please first comment on the issue to say\nthat you're interested in contributing. For issues _not_ labeled 'Help Wanted',\nit is recommended that you ask (and wait for confirmation) on the issue before\ncontributing, to avoid duplication of effort or wasted work. For nontrivial\nchanges that _don't_ relate to an existing issue, please file an issue first.\n\nChanges should be high quality and well tested, and should generally follow the\n[Google Go style guide](https://google.github.io/styleguide/go/). Commit\nmessages should follow the [format used by the Go\nproject](https://go.dev/wiki/CommitMessage).\n\nUnless otherwise noted, the Go source files are distributed under the MIT-style\nlicense found in the LICENSE file. All Go files in the SDK should have a\ncopyright header following the format below:\n\n```go\n// Copyright 2025 The Go MCP SDK Authors. All rights reserved.\n// Use of this source code is governed by an MIT-style\n// license that can be found in the LICENSE file.\n```\n\n## Code of conduct\n\nThis project follows the [Go Community Code of Conduct](https://go.dev/conduct).\nIf you encounter a conduct-related issue, please mail conduct@golang.org.\n\n## Governance\n\nInitially, the Go SDK repository will be administered by the Go team and\nAnthropic, and they will be the Approvers (the set of people able to merge PRs\nto the SDK). The policies here are also intended to satisfy necessary\nconstraints of the Go team's participation in the project. This may change in\nthe future: see 'Ongoing Evaluation' below.\n\n### Steering meetings\n\nOn a regular basis, the maintainers will host a virtual steering meeting to\ndiscuss outstanding proposals and other changes to the SDK. These meetings and\ntheir agendas will be announced in advance, and open to all to join. The\nmeetings will be recorded, and recordings and meeting notes will be made\navailable afterward. (TODO: decide on a mechanism for tracking these\nmeetings--likely a GitHub issue.)\n\nThis process is similar to the [Go Tools\ncall](https://go.dev/wiki/golang-tools), though it is expected that meetings\nwill at least initially occur on a more frequent basis.\n\n### Discord\n\nDiscord (either the public or private Anthropic discord servers) should only be\nused for logistical coordination or answering questions. For transparency and\ndurability, design discussion and decisions should occur in GitHub issues or\npublic steering meetings.\n\n### Antitrust considerations\n\nIt is important that the SDK avoids bias toward specific integration paths or\nproviders. The antitrust policy below details precise terms that should be\navoided to ensure that the evolution and governance of the SDK remain\nprocompetitive.\n\nA note to readers: this policy was drafted in consultation with counsel, and so\nuses terms like 'Steering Committee', which may be confusing in the context of\nother 'steering committees' for model context protocol. In the context here,\n'Steering Committee' means the set of Approvers, who are able to approve pull\nrequests and/or make administrative changes to the project.\n\n### Antitrust policy\n\nNote: all changes to the policy in this section must be approved by legal\ncounsel.\n\nThe Go+Anthropic MCP SDK Steering Committee (the “Committee”) is established to\nguide and review technical contributions to an open-source Go software\ndevelopment kit (“SDK”) for the Model Context Protocol (“MCP”). The Committee\nand its members are committed to operating for procompetitive purposes that\naccelerate AI development and benefit businesses and consumers. This\ncollaboration is focused on technical and infrastructure objectives – namely,\ndeveloping and maintaining a neutral, open-source, and MIT-licensed tool.\nGoogle and Anthropic, as well as other stakeholders, participate with the\nunderstanding that the Committee’s sole purpose is to improve interoperability\nand innovation in the MCP ecosystem.\n\nAntitrust law recognizes that when competitors collaborate for valid reasons\n(e.g., joint R&D or standard-setting), such collaborations can be\nprocompetitive. This Antitrust Compliance Policy (the “Policy”) therefore\noutlines guidelines and safeguards to ensure the collaboration remains focused\non its technical mission.\n\nThe Policy applies to all Committee activities and communications, including\nofficial meetings, subcommittee discussions, emails, shared documents, and any\nother interactions under the Committee’s auspices (e.g., group chats, version\ncontrol systems). It applies to all participants from Google, Anthropic, and\nany other member organizations or independent contributors involved. Each\nparticipating entity should ensure its representatives understand and uphold\nthese rules. By participating, members agree to follow the Policy in both\nletter and spirit.\n\n#### Governance Procedures and Principles\n\n- **Participant Guidelines.** Participants should generally be limited to\n  individuals in technical roles who are directly involved in the MCP SDK\n  project. These participants should not be key decision-makers in their\n  company’s AI commercial strategy, sales, marketing, pricing, or other\n  competitively or strategically sensitive business planning.\n- **Agenda Preparation.** A written agenda should be circulated before each\n  Committee meeting. Agenda items should focus on the SDK’s technical\n  development, maintenance, or documentation. Where appropriate, counsel should\n  review the agenda prior to circulation to ensure compliance with the Policy.\n- **Policy Reminder at Start.** Meetings should begin with a brief antitrust\n  compliance reminder with reference to the Policy.\n- **Minutes.** Meetings will be minuted by a designated participant, and\n  neutrally record attendees, roles, topics discussed, action items, and\n  outcomes. Draft minutes will be circulated to all participants.\n- **Documentation and Transparency.** Steering Committee outputs are intended\n  for public release. Significant design decisions and discussion outcomes\n  should be documented publicly. If a topic cannot be safely disclosed\n  publicly, it likely does not belong in this forum.\n- **Independence of Decision-Making.** All participants and their companies\n  retain complete independence in their own business decisions and competitive\n  strategies outside of the MCP SDK project. Nothing in this collaboration\n  restricts or influences how each company operates its commercial business.\n\n### Information Exchange Guidelines\n\n**Appropriate Topics.** Committee members are anticipated to remain within the\nproject’s technical scope. In general, discussions should focus on improving\nthe Go SDK for MCP in a transparent, collaborative, and non-exclusive manner.\nThe following topics are appropriate and expected:\n\n- **Software Design and Architecture:** Implementation of MCP features in Go,\n  API design, code structure, testing frameworks, performance considerations,\n  compatibility issues, and security concerns.\n- **Technical Contributions and Bug Fixes:** Review of code contributions,\n  debugging problems, and handling feature requests.\n- **Documentation and Open-Source Logistics:** Discussions of project\n  documentation, changelogs, versioning strategy, and managing contributions.\n- **Standards and Interoperability:** Ensuring SDK compliance with MCP or other\n  open technical standards. Any standardization effort should be open,\n  voluntary, and tailored to promote interoperability.\n- **Public Information:** Any public information relevant to the Committee’s\n  technical work (e.g., published research, open-source code from outside\n  projects, publicly documented API specs).\n\n**Inappropriate Topics.** To ensure compliance with antitrust law and maintain\nthe open character of the collaboration, the following subjects should not be\ndiscussed in Committee meetings, side conversations, or related communications:\n\n- **Pricing and Commercial Terms:** Do not discuss prices, pricing strategy,\n  discounting, or future pricing plans for Claude, Gemini, or any other AI\n  product or service provided by Committee members.\n- **Sales or Output:** Avoid sharing sales volumes, revenue, customer counts,\n  market shares, production plans, or any business performance metrics.\n- **Product Roadmaps (beyond SDK):** Do not disclose internal plans for AI\n  model development, feature rollouts, or future commercialization strategies.\n- **Customers or Markets:** No discussions of which customers, industries, or\n  geographies the parties will pursue or avoid.\n- **Customer or Supplier Details:** Do not share specifics of contracts,\n  negotiations, or relationships with commercial partners.\n- **Non-SDK Proprietary Tech:** Keep discussions focused on the open SDK.\n  Sharing of information should be limited to what is needed to achieve the\n  Committee’s goals. Each party’s internal model architectures, fine-tuning\n  approaches, or training methods unrelated to the project should not be\n  disclosed.\n- **HR or Labor Matters:** No discussions about wages, hiring plans, or\n  policies toward employees.\n\n#### Enforcement and Support\n\n- **Shared Responsibility.** All Committee participants share responsibility\n  for upholding the Policy. While legal counsel can provide support, day-to-day\n  compliance is a function of culture and practice.\n- **Designated Legal Contacts.** Each participating entity should designate a\n  legal point of contact responsible for reviewing meeting materials (e.g.,\n  agendas, minutes) and fielding questions about compliance. These contacts\n  should be included in the Committee distribution list for all official\n  materials and should be consulted in advance of any meetings where sensitive\n  topics may arise.\n- **Final Note.** The Policy is not meant to chill legitimate technical\n  collaboration. It is meant to ensure that the Committee can focus on its\n  mission without creating unnecessary legal risk or attracting regulator\n  scrutiny. Participants who follow the Policy and avoid Inappropriate Topics\n  will remain squarely within the procompetitive zone.\n\n### Ongoing evaluation\n\nOn an ongoing basis, the administrators of the SDK will evaluate whether it is\nkeeping pace with changes to the MCP spec and meeting its goals of openness and\ntransparency. If it is not meeting these goals, either because it exceeds the\nbandwidth of its current Approvers, or because the processes here are\ninadequate, these processes will be re-evaluated by the Approvers. At this\ntime, the Approvers set may be expanded to include additional community\nmembers, based on their history of strong contribution.\n"
  },
  {
    "path": "internal/mcp/README.md",
    "content": "<!-- Autogenerated by weave; DO NOT EDIT -->\n# MCP Go SDK\n\n<!-- TODO: update pkgsite links here to point to the modelcontextprotocol\nmodule, once it exists. -->\n\n[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk)\n\nThis repository contains an implementation of the official Go software\ndevelopment kit (SDK) for the Model Context Protocol (MCP).\n\n**WARNING**: The SDK is currently unstable and subject to breaking changes.\nPlease test it out and file bug reports or API proposals. The [TODO](#todo)\nsection below outlines outstanding release blockers. We aim to release a stable\nversion of the SDK in mid July, 2025.\n\n\t1. [Package documentation](#package-documentation)\n\t1. [Example](#example)\n\t1. [TODO](#todo)\n\t1. [Design](#design)\n\t1. [Acknowledgements](#acknowledgements)\n\t1. [License](#license)\n\n## Package documentation\n\nThe SDK consists of two importable packages:\n\n- The\n  [`github.com/modelcontextprotocol/go-sdk/mcp`](https://pkg.go.dev/golang.org/x/tools/internal/mcp)\n  package defines the primary APIs for constructing and using MCP clients and\n  servers.\n- The\n  [`github.com/modelcontextprotocol/go-sdk/jsonschema`](https://pkg.go.dev/golang.org/x/tools/internal/mcp/jsonschema)\n  package provides an implementation of [JSON\n  Schema](https://json-schema.org/), used for MCP tool input and output schema.\n\n## Example\n\nIn this example, an MCP client communicates with an MCP server running in a\nsidecar process:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os/exec\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\t// Create a new client, with no features.\n\tclient := mcp.NewClient(\"mcp-client\", \"v1.0.0\", nil)\n\n\t// Connect to a server over stdin/stdout\n\ttransport := mcp.NewCommandTransport(exec.Command(\"myserver\"))\n\tsession, err := client.Connect(ctx, transport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer session.Close()\n\n\t// Call a tool on the server.\n\tparams := &mcp.CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"you\"},\n\t}\n\tres, err := session.CallTool(ctx, params)\n\tif err != nil {\n\t\tlog.Fatalf(\"CallTool failed: %v\", err)\n\t}\n\tif res.IsError {\n\t\tlog.Fatal(\"tool failed\")\n\t}\n\tfor _, c := range res.Content {\n\t\tlog.Print(c.Text)\n\t}\n}\n```\n\nHere's an example of the corresponding server component, which communicates\nwith its client over stdin/stdout:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\ntype HiParams struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {\n\treturn &mcp.CallToolResultFor[any]{\n\t\tContent: []*mcp.Content{mcp.NewTextContent(\"Hi \" + params.Name)},\n\t}, nil\n}\n\nfunc main() {\n\t// Create a server with a single tool.\n\tserver := mcp.NewServer(\"greeter\", \"v1.0.0\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi))\n\t// Run the server over stdin/stdout, until the client disconnects\n\tif err := server.Run(context.Background(), mcp.NewStdioTransport()); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\n\nThe `examples/` directory contains more example clients and servers.\n\n## TODO\n\nThe following TODOs block the release of this SDK:\n\n- Better support for resumability in the Streamable HTTP transport: a\n  server-side event store and client-side retry configuration.\n- OAuth support (or examples of implementing OAuth using middleware).\n- Support for the changes in the\n  [2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/changelog)\n  version of the MCP spec.\n- More examples and documentation.\n\n## Design\n\nThe design doc for this SDK is at [design.md](./design/design.md), which was\ninitially reviewed at\n[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).\n\nFurther design discussion should occur in GitHub issues. See CONTRIBUTING.md\nfor details.\n\n## Acknowledgements\n\nSeveral existing Go MCP SDKs inspired the development and design of this\nofficial SDK, notably [mcp-go](https://github.com/mark3labs/mcp-go), authored\nby Ed Zynda. We are grateful to Ed as well as the other contributors to mcp-go,\nand to authors and contributors of other SDKs such as\n[mcp-golang](https://github.com/metoro-io/mcp-golang) and\n[go-mcp](https://github.com/ThinkInAIXYZ/go-mcp). Thanks to their work, there\nis a thriving ecosystem of Go MCP clients and servers.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](./LICENSE)\nfile for details.\n"
  },
  {
    "path": "internal/mcp/client.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"iter\"\n\t\"slices\"\n\t\"sync\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\n// A Client is an MCP client, which may be connected to an MCP server\n// using the [Client.Connect] method.\ntype Client struct {\n\tname                    string\n\tversion                 string\n\topts                    ClientOptions\n\tmu                      sync.Mutex\n\troots                   *featureSet[*Root]\n\tsessions                []*ClientSession\n\tsendingMethodHandler_   MethodHandler[*ClientSession]\n\treceivingMethodHandler_ MethodHandler[*ClientSession]\n}\n\n// NewClient creates a new Client.\n//\n// Use [Client.Connect] to connect it to an MCP server.\n//\n// If non-nil, the provided options configure the Client.\nfunc NewClient(name, version string, opts *ClientOptions) *Client {\n\tc := &Client{\n\t\tname:                    name,\n\t\tversion:                 version,\n\t\troots:                   newFeatureSet(func(r *Root) string { return r.URI }),\n\t\tsendingMethodHandler_:   defaultSendingMethodHandler[*ClientSession],\n\t\treceivingMethodHandler_: defaultReceivingMethodHandler[*ClientSession],\n\t}\n\tif opts != nil {\n\t\tc.opts = *opts\n\t}\n\treturn c\n}\n\n// ClientOptions configures the behavior of the client.\ntype ClientOptions struct {\n\t// Handler for sampling.\n\t// Called when a server calls CreateMessage.\n\tCreateMessageHandler func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error)\n\t// Handlers for notifications from the server.\n\tToolListChangedHandler      func(context.Context, *ClientSession, *ToolListChangedParams)\n\tPromptListChangedHandler    func(context.Context, *ClientSession, *PromptListChangedParams)\n\tResourceListChangedHandler  func(context.Context, *ClientSession, *ResourceListChangedParams)\n\tLoggingMessageHandler       func(context.Context, *ClientSession, *LoggingMessageParams)\n\tProgressNotificationHandler func(context.Context, *ClientSession, *ProgressNotificationParams)\n}\n\n// bind implements the binder[*ClientSession] interface, so that Clients can\n// be connected using [connect].\nfunc (c *Client) bind(conn *jsonrpc2.Connection) *ClientSession {\n\tcs := &ClientSession{\n\t\tconn:   conn,\n\t\tclient: c,\n\t}\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.sessions = append(c.sessions, cs)\n\treturn cs\n}\n\n// disconnect implements the binder[*Client] interface, so that\n// Clients can be connected using [connect].\nfunc (c *Client) disconnect(cs *ClientSession) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.sessions = slices.DeleteFunc(c.sessions, func(cs2 *ClientSession) bool {\n\t\treturn cs2 == cs\n\t})\n}\n\n// Connect begins an MCP session by connecting to a server over the given\n// transport, and initializing the session.\n//\n// Typically, it is the responsibility of the client to close the connection\n// when it is no longer needed. However, if the connection is closed by the\n// server, calls or notifications will return an error wrapping\n// [ErrConnectionClosed].\nfunc (c *Client) Connect(ctx context.Context, t Transport) (cs *ClientSession, err error) {\n\tcs, err = connect(ctx, t, c)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcaps := &ClientCapabilities{}\n\tcaps.Roots.ListChanged = true\n\tif c.opts.CreateMessageHandler != nil {\n\t\tcaps.Sampling = &SamplingCapabilities{}\n\t}\n\n\tparams := &InitializeParams{\n\t\tClientInfo:      &implementation{Name: c.name, Version: c.version},\n\t\tCapabilities:    caps,\n\t\tProtocolVersion: \"2025-03-26\",\n\t}\n\t// TODO(rfindley): handle protocol negotiation gracefully. If the server\n\t// responds with 2024-11-05, surface that failure to the caller of connect,\n\t// so that they can choose a different transport.\n\tres, err := handleSend[*InitializeResult](ctx, cs, methodInitialize, params)\n\tif err != nil {\n\t\t_ = cs.Close()\n\t\treturn nil, err\n\t}\n\tcs.initializeResult = res\n\tif err := handleNotify(ctx, cs, notificationInitialized, &InitializedParams{}); err != nil {\n\t\t_ = cs.Close()\n\t\treturn nil, err\n\t}\n\treturn cs, nil\n}\n\n// A ClientSession is a logical connection with an MCP server. Its\n// methods can be used to send requests or notifications to the server. Create\n// a session by calling [Client.Connect].\n//\n// Call [ClientSession.Close] to close the connection, or await client\n// termination with [ServerSession.Wait].\ntype ClientSession struct {\n\tconn             *jsonrpc2.Connection\n\tclient           *Client\n\tinitializeResult *InitializeResult\n}\n\n// Close performs a graceful close of the connection, preventing new requests\n// from being handled, and waiting for ongoing requests to return. Close then\n// terminates the connection.\nfunc (cs *ClientSession) Close() error {\n\treturn cs.conn.Close()\n}\n\n// Wait waits for the connection to be closed by the server.\n// Generally, clients should be responsible for closing the connection.\nfunc (cs *ClientSession) Wait() error {\n\treturn cs.conn.Wait()\n}\n\n// AddRoots adds the given roots to the client,\n// replacing any with the same URIs,\n// and notifies any connected servers.\nfunc (c *Client) AddRoots(roots ...*Root) {\n\t// Only notify if something could change.\n\tif len(roots) == 0 {\n\t\treturn\n\t}\n\tc.changeAndNotify(notificationRootsListChanged, &RootsListChangedParams{},\n\t\tfunc() bool { c.roots.add(roots...); return true })\n}\n\n// RemoveRoots removes the roots with the given URIs,\n// and notifies any connected servers if the list has changed.\n// It is not an error to remove a nonexistent root.\n// TODO: notification\nfunc (c *Client) RemoveRoots(uris ...string) {\n\tc.changeAndNotify(notificationRootsListChanged, &RootsListChangedParams{},\n\t\tfunc() bool { return c.roots.remove(uris...) })\n}\n\n// changeAndNotify is called when a feature is added or removed.\n// It calls change, which should do the work and report whether a change actually occurred.\n// If there was a change, it notifies a snapshot of the sessions.\nfunc (c *Client) changeAndNotify(notification string, params Params, change func() bool) {\n\tvar sessions []*ClientSession\n\t// Lock for the change, but not for the notification.\n\tc.mu.Lock()\n\tif change() {\n\t\tsessions = slices.Clone(c.sessions)\n\t}\n\tc.mu.Unlock()\n\tnotifySessions(sessions, notification, params)\n}\n\nfunc (c *Client) listRoots(_ context.Context, _ *ClientSession, _ *ListRootsParams) (*ListRootsResult, error) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\troots := slices.Collect(c.roots.all())\n\tif roots == nil {\n\t\troots = []*Root{} // avoid JSON null\n\t}\n\treturn &ListRootsResult{\n\t\tRoots: roots,\n\t}, nil\n}\n\nfunc (c *Client) createMessage(ctx context.Context, cs *ClientSession, params *CreateMessageParams) (*CreateMessageResult, error) {\n\tif c.opts.CreateMessageHandler == nil {\n\t\t// TODO: wrap or annotate this error? Pick a standard code?\n\t\treturn nil, &jsonrpc2.WireError{Code: CodeUnsupportedMethod, Message: \"client does not support CreateMessage\"}\n\t}\n\treturn c.opts.CreateMessageHandler(ctx, cs, params)\n}\n\n// AddSendingMiddleware wraps the current sending method handler using the provided\n// middleware. Middleware is applied from right to left, so that the first one is\n// executed first.\n//\n// For example, AddSendingMiddleware(m1, m2, m3) augments the method handler as\n// m1(m2(m3(handler))).\n//\n// Sending middleware is called when a request is sent. It is useful for tasks\n// such as tracing, metrics, and adding progress tokens.\nfunc (c *Client) AddSendingMiddleware(middleware ...Middleware[*ClientSession]) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\taddMiddleware(&c.sendingMethodHandler_, middleware)\n}\n\n// AddReceivingMiddleware wraps the current receiving method handler using\n// the provided middleware. Middleware is applied from right to left, so that the\n// first one is executed first.\n//\n// For example, AddReceivingMiddleware(m1, m2, m3) augments the method handler as\n// m1(m2(m3(handler))).\n//\n// Receiving middleware is called when a request is received. It is useful for tasks\n// such as authentication, request logging and metrics.\nfunc (c *Client) AddReceivingMiddleware(middleware ...Middleware[*ClientSession]) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\taddMiddleware(&c.receivingMethodHandler_, middleware)\n}\n\n// clientMethodInfos maps from the RPC method name to serverMethodInfos.\nvar clientMethodInfos = map[string]methodInfo{\n\tmethodPing:                      newMethodInfo(sessionMethod((*ClientSession).ping)),\n\tmethodListRoots:                 newMethodInfo(clientMethod((*Client).listRoots)),\n\tmethodCreateMessage:             newMethodInfo(clientMethod((*Client).createMessage)),\n\tnotificationToolListChanged:     newMethodInfo(clientMethod((*Client).callToolChangedHandler)),\n\tnotificationPromptListChanged:   newMethodInfo(clientMethod((*Client).callPromptChangedHandler)),\n\tnotificationResourceListChanged: newMethodInfo(clientMethod((*Client).callResourceChangedHandler)),\n\tnotificationLoggingMessage:      newMethodInfo(clientMethod((*Client).callLoggingHandler)),\n\tnotificationProgress:            newMethodInfo(sessionMethod((*ClientSession).callProgressNotificationHandler)),\n}\n\nfunc (cs *ClientSession) sendingMethodInfos() map[string]methodInfo {\n\treturn serverMethodInfos\n}\n\nfunc (cs *ClientSession) receivingMethodInfos() map[string]methodInfo {\n\treturn clientMethodInfos\n}\n\nfunc (cs *ClientSession) handle(ctx context.Context, req *JSONRPCRequest) (any, error) {\n\treturn handleReceive(ctx, cs, req)\n}\n\nfunc (cs *ClientSession) sendingMethodHandler() methodHandler {\n\tcs.client.mu.Lock()\n\tdefer cs.client.mu.Unlock()\n\treturn cs.client.sendingMethodHandler_\n}\n\nfunc (cs *ClientSession) receivingMethodHandler() methodHandler {\n\tcs.client.mu.Lock()\n\tdefer cs.client.mu.Unlock()\n\treturn cs.client.receivingMethodHandler_\n}\n\n// getConn implements [session.getConn].\nfunc (cs *ClientSession) getConn() *jsonrpc2.Connection { return cs.conn }\n\nfunc (*ClientSession) ping(context.Context, *PingParams) (*emptyResult, error) {\n\treturn &emptyResult{}, nil\n}\n\n// Ping makes an MCP \"ping\" request to the server.\nfunc (cs *ClientSession) Ping(ctx context.Context, params *PingParams) error {\n\t_, err := handleSend[*emptyResult](ctx, cs, methodPing, orZero[Params](params))\n\treturn err\n}\n\n// ListPrompts lists prompts that are currently available on the server.\nfunc (cs *ClientSession) ListPrompts(ctx context.Context, params *ListPromptsParams) (*ListPromptsResult, error) {\n\treturn handleSend[*ListPromptsResult](ctx, cs, methodListPrompts, orZero[Params](params))\n}\n\n// GetPrompt gets a prompt from the server.\nfunc (cs *ClientSession) GetPrompt(ctx context.Context, params *GetPromptParams) (*GetPromptResult, error) {\n\treturn handleSend[*GetPromptResult](ctx, cs, methodGetPrompt, orZero[Params](params))\n}\n\n// ListTools lists tools that are currently available on the server.\nfunc (cs *ClientSession) ListTools(ctx context.Context, params *ListToolsParams) (*ListToolsResult, error) {\n\treturn handleSend[*ListToolsResult](ctx, cs, methodListTools, orZero[Params](params))\n}\n\n// CallTool calls the tool with the given name and arguments.\n// The arguments can be any value that marshals into a JSON object.\nfunc (cs *ClientSession) CallTool(ctx context.Context, params *CallToolParams) (*CallToolResult, error) {\n\tif params == nil {\n\t\tparams = new(CallToolParams)\n\t}\n\tif params.Arguments == nil {\n\t\t// Avoid sending nil over the wire.\n\t\tparams.Arguments = map[string]any{}\n\t}\n\treturn handleSend[*CallToolResult](ctx, cs, methodCallTool, params)\n}\n\nfunc (cs *ClientSession) SetLevel(ctx context.Context, params *SetLevelParams) error {\n\t_, err := handleSend[*emptyResult](ctx, cs, methodSetLevel, orZero[Params](params))\n\treturn err\n}\n\n// ListResources lists the resources that are currently available on the server.\nfunc (cs *ClientSession) ListResources(ctx context.Context, params *ListResourcesParams) (*ListResourcesResult, error) {\n\treturn handleSend[*ListResourcesResult](ctx, cs, methodListResources, orZero[Params](params))\n}\n\n// ListResourceTemplates lists the resource templates that are currently available on the server.\nfunc (cs *ClientSession) ListResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) (*ListResourceTemplatesResult, error) {\n\treturn handleSend[*ListResourceTemplatesResult](ctx, cs, methodListResourceTemplates, orZero[Params](params))\n}\n\n// ReadResource ask the server to read a resource and return its contents.\nfunc (cs *ClientSession) ReadResource(ctx context.Context, params *ReadResourceParams) (*ReadResourceResult, error) {\n\treturn handleSend[*ReadResourceResult](ctx, cs, methodReadResource, orZero[Params](params))\n}\n\nfunc (c *Client) callToolChangedHandler(ctx context.Context, s *ClientSession, params *ToolListChangedParams) (Result, error) {\n\treturn callNotificationHandler(ctx, c.opts.ToolListChangedHandler, s, params)\n}\n\nfunc (c *Client) callPromptChangedHandler(ctx context.Context, s *ClientSession, params *PromptListChangedParams) (Result, error) {\n\treturn callNotificationHandler(ctx, c.opts.PromptListChangedHandler, s, params)\n}\n\nfunc (c *Client) callResourceChangedHandler(ctx context.Context, s *ClientSession, params *ResourceListChangedParams) (Result, error) {\n\treturn callNotificationHandler(ctx, c.opts.ResourceListChangedHandler, s, params)\n}\n\nfunc (c *Client) callLoggingHandler(ctx context.Context, cs *ClientSession, params *LoggingMessageParams) (Result, error) {\n\tif h := c.opts.LoggingMessageHandler; h != nil {\n\t\th(ctx, cs, params)\n\t}\n\treturn nil, nil\n}\n\nfunc (cs *ClientSession) callProgressNotificationHandler(ctx context.Context, params *ProgressNotificationParams) (Result, error) {\n\treturn callNotificationHandler(ctx, cs.client.opts.ProgressNotificationHandler, cs, params)\n}\n\n// NotifyProgress sends a progress notification from the client to the server\n// associated with this session.\n// This can be used if the client is performing a long-running task that was\n// initiated by the server\nfunc (cs *ClientSession) NotifyProgress(ctx context.Context, params *ProgressNotificationParams) error {\n\treturn handleNotify(ctx, cs, notificationProgress, params)\n}\n\n// Tools provides an iterator for all tools available on the server,\n// automatically fetching pages and managing cursors.\n// The params argument can set the initial cursor.\n// Iteration stops at the first encountered error, which will be yielded.\nfunc (cs *ClientSession) Tools(ctx context.Context, params *ListToolsParams) iter.Seq2[*Tool, error] {\n\tif params == nil {\n\t\tparams = &ListToolsParams{}\n\t}\n\treturn paginate(ctx, params, cs.ListTools, func(res *ListToolsResult) []*Tool {\n\t\treturn res.Tools\n\t})\n}\n\n// Resources provides an iterator for all resources available on the server,\n// automatically fetching pages and managing cursors.\n// The params argument can set the initial cursor.\n// Iteration stops at the first encountered error, which will be yielded.\nfunc (cs *ClientSession) Resources(ctx context.Context, params *ListResourcesParams) iter.Seq2[*Resource, error] {\n\tif params == nil {\n\t\tparams = &ListResourcesParams{}\n\t}\n\treturn paginate(ctx, params, cs.ListResources, func(res *ListResourcesResult) []*Resource {\n\t\treturn res.Resources\n\t})\n}\n\n// ResourceTemplates provides an iterator for all resource templates available on the server,\n// automatically fetching pages and managing cursors.\n// The `params` argument can set the initial cursor.\n// Iteration stops at the first encountered error, which will be yielded.\nfunc (cs *ClientSession) ResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) iter.Seq2[*ResourceTemplate, error] {\n\tif params == nil {\n\t\tparams = &ListResourceTemplatesParams{}\n\t}\n\treturn paginate(ctx, params, cs.ListResourceTemplates, func(res *ListResourceTemplatesResult) []*ResourceTemplate {\n\t\treturn res.ResourceTemplates\n\t})\n}\n\n// Prompts provides an iterator for all prompts available on the server,\n// automatically fetching pages and managing cursors.\n// The params argument can set the initial cursor.\n// Iteration stops at the first encountered error, which will be yielded.\nfunc (cs *ClientSession) Prompts(ctx context.Context, params *ListPromptsParams) iter.Seq2[*Prompt, error] {\n\tif params == nil {\n\t\tparams = &ListPromptsParams{}\n\t}\n\treturn paginate(ctx, params, cs.ListPrompts, func(res *ListPromptsResult) []*Prompt {\n\t\treturn res.Prompts\n\t})\n}\n\n// paginate is a generic helper function to provide a paginated iterator.\nfunc paginate[P listParams, R listResult[T], T any](ctx context.Context, params P, listFunc func(context.Context, P) (R, error), items func(R) []*T) iter.Seq2[*T, error] {\n\treturn func(yield func(*T, error) bool) {\n\t\tfor {\n\t\t\tres, err := listFunc(ctx, params)\n\t\t\tif err != nil {\n\t\t\t\tyield(nil, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor _, r := range items(res) {\n\t\t\t\tif !yield(r, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tnextCursorVal := res.nextCursorPtr()\n\t\t\tif nextCursorVal == nil || *nextCursorVal == \"\" {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t*params.cursorPtr() = *nextCursorVal\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/client_list_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"iter\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/internal/mcp\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\nfunc TestList(t *testing.T) {\n\tctx := context.Background()\n\tclientSession, serverSession, server := createSessions(ctx)\n\tdefer clientSession.Close()\n\tdefer serverSession.Close()\n\n\tt.Run(\"tools\", func(t *testing.T) {\n\t\ttoolA := mcp.NewServerTool(\"apple\", \"apple tool\", SayHi)\n\t\ttoolB := mcp.NewServerTool(\"banana\", \"banana tool\", SayHi)\n\t\ttoolC := mcp.NewServerTool(\"cherry\", \"cherry tool\", SayHi)\n\t\ttools := []*mcp.ServerTool{toolA, toolB, toolC}\n\t\twantTools := []*mcp.Tool{toolA.Tool, toolB.Tool, toolC.Tool}\n\t\tserver.AddTools(tools...)\n\t\tt.Run(\"list\", func(t *testing.T) {\n\t\t\tres, err := clientSession.ListTools(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"ListTools() failed:\", err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantTools, res.Tools, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"ListTools() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t\tt.Run(\"iterator\", func(t *testing.T) {\n\t\t\ttestIterator(t, clientSession.Tools(ctx, nil), wantTools)\n\t\t})\n\t})\n\n\tt.Run(\"resources\", func(t *testing.T) {\n\t\tresourceA := &mcp.ServerResource{Resource: &mcp.Resource{URI: \"http://apple\"}}\n\t\tresourceB := &mcp.ServerResource{Resource: &mcp.Resource{URI: \"http://banana\"}}\n\t\tresourceC := &mcp.ServerResource{Resource: &mcp.Resource{URI: \"http://cherry\"}}\n\t\twantResources := []*mcp.Resource{resourceA.Resource, resourceB.Resource, resourceC.Resource}\n\t\tresources := []*mcp.ServerResource{resourceA, resourceB, resourceC}\n\t\tserver.AddResources(resources...)\n\t\tt.Run(\"list\", func(t *testing.T) {\n\t\t\tres, err := clientSession.ListResources(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"ListResources() failed:\", err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantResources, res.Resources, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"ListResources() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t\tt.Run(\"iterator\", func(t *testing.T) {\n\t\t\ttestIterator(t, clientSession.Resources(ctx, nil), wantResources)\n\t\t})\n\t})\n\n\tt.Run(\"templates\", func(t *testing.T) {\n\t\tresourceTmplA := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: \"http://apple/{x}\"}}\n\t\tresourceTmplB := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: \"http://banana/{x}\"}}\n\t\tresourceTmplC := &mcp.ServerResourceTemplate{ResourceTemplate: &mcp.ResourceTemplate{URITemplate: \"http://cherry/{x}\"}}\n\t\twantResourceTemplates := []*mcp.ResourceTemplate{\n\t\t\tresourceTmplA.ResourceTemplate, resourceTmplB.ResourceTemplate,\n\t\t\tresourceTmplC.ResourceTemplate,\n\t\t}\n\t\tresourceTemplates := []*mcp.ServerResourceTemplate{resourceTmplA, resourceTmplB, resourceTmplC}\n\t\tserver.AddResourceTemplates(resourceTemplates...)\n\t\tt.Run(\"list\", func(t *testing.T) {\n\t\t\tres, err := clientSession.ListResourceTemplates(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"ListResourceTemplates() failed:\", err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantResourceTemplates, res.ResourceTemplates, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"ListResourceTemplates() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t\tt.Run(\"ResourceTemplatesIterator\", func(t *testing.T) {\n\t\t\ttestIterator(t, clientSession.ResourceTemplates(ctx, nil), wantResourceTemplates)\n\t\t})\n\t})\n\n\tt.Run(\"prompts\", func(t *testing.T) {\n\t\tpromptA := newServerPrompt(\"apple\", \"apple prompt\")\n\t\tpromptB := newServerPrompt(\"banana\", \"banana prompt\")\n\t\tpromptC := newServerPrompt(\"cherry\", \"cherry prompt\")\n\t\twantPrompts := []*mcp.Prompt{promptA.Prompt, promptB.Prompt, promptC.Prompt}\n\t\tprompts := []*mcp.ServerPrompt{promptA, promptB, promptC}\n\t\tserver.AddPrompts(prompts...)\n\t\tt.Run(\"list\", func(t *testing.T) {\n\t\t\tres, err := clientSession.ListPrompts(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"ListPrompts() failed:\", err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantPrompts, res.Prompts, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"ListPrompts() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t\tt.Run(\"iterator\", func(t *testing.T) {\n\t\t\ttestIterator(t, clientSession.Prompts(ctx, nil), wantPrompts)\n\t\t})\n\t})\n}\n\nfunc testIterator[T any](t *testing.T, seq iter.Seq2[*T, error], want []*T) {\n\tt.Helper()\n\tvar got []*T\n\tfor x, err := range seq {\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"iteration failed: %v\", err)\n\t\t}\n\t\tgot = append(got, x)\n\t}\n\tif diff := cmp.Diff(want, got, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\tt.Fatalf(\"mismatch (-want +got):\\n%s\", diff)\n\t}\n}\n\n// testPromptHandler is used for type inference newServerPrompt.\nfunc testPromptHandler(context.Context, *mcp.ServerSession, *mcp.GetPromptParams) (*mcp.GetPromptResult, error) {\n\tpanic(\"not implemented\")\n}\n\nfunc newServerPrompt(name, desc string) *mcp.ServerPrompt {\n\treturn &mcp.ServerPrompt{\n\t\tPrompt:  &mcp.Prompt{Name: name, Description: desc},\n\t\tHandler: testPromptHandler,\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/client_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\ntype Item struct {\n\tName  string\n\tValue string\n}\n\ntype ListTestParams struct {\n\tCursor string\n}\n\nfunc (p *ListTestParams) cursorPtr() *string {\n\treturn &p.Cursor\n}\n\ntype ListTestResult struct {\n\tItems      []*Item\n\tNextCursor string\n}\n\nfunc (r *ListTestResult) nextCursorPtr() *string {\n\treturn &r.NextCursor\n}\n\nvar allItems = []*Item{\n\t{\"alpha\", \"val-A\"},\n\t{\"bravo\", \"val-B\"},\n\t{\"charlie\", \"val-C\"},\n\t{\"delta\", \"val-D\"},\n\t{\"echo\", \"val-E\"},\n\t{\"foxtrot\", \"val-F\"},\n\t{\"golf\", \"val-G\"},\n\t{\"hotel\", \"val-H\"},\n\t{\"india\", \"val-I\"},\n\t{\"juliet\", \"val-J\"},\n\t{\"kilo\", \"val-K\"},\n}\n\n// generatePaginatedResults is a helper to create a sequence of mock responses for pagination.\n// It simulates a server returning items in pages based on a given page size.\nfunc generatePaginatedResults(all []*Item, pageSize int) []*ListTestResult {\n\tif len(all) == 0 {\n\t\treturn []*ListTestResult{{Items: []*Item{}, NextCursor: \"\"}}\n\t}\n\tif pageSize <= 0 {\n\t\tpanic(\"pageSize must be greater than 0\")\n\t}\n\tnumPages := (len(all) + pageSize - 1) / pageSize // Ceiling division\n\tvar results []*ListTestResult\n\tfor i := range numPages {\n\t\tstartIndex := i * pageSize\n\t\tendIndex := min(startIndex+pageSize, len(all)) // Use min to prevent out of bounds\n\t\tnextCursor := \"\"\n\t\tif endIndex < len(all) { // If there are more items after this page\n\t\t\tnextCursor = fmt.Sprintf(\"cursor_%d\", endIndex)\n\t\t}\n\t\tresults = append(results, &ListTestResult{Items: all[startIndex:endIndex], NextCursor: nextCursor})\n\t}\n\treturn results\n}\n\nfunc TestClientPaginateBasic(t *testing.T) {\n\tctx := context.Background()\n\ttestCases := []struct {\n\t\tname          string\n\t\tresults       []*ListTestResult\n\t\tmockError     error\n\t\tinitialParams *ListTestParams\n\t\texpected      []*Item\n\t\texpectError   bool\n\t}{\n\t\t{\n\t\t\tname:     \"SinglePageAllItems\",\n\t\t\tresults:  generatePaginatedResults(allItems, len(allItems)),\n\t\t\texpected: allItems,\n\t\t},\n\t\t{\n\t\t\tname:     \"MultiplePages\",\n\t\t\tresults:  generatePaginatedResults(allItems, 3),\n\t\t\texpected: allItems,\n\t\t},\n\t\t{\n\t\t\tname:     \"EmptyResults\",\n\t\t\tresults:  generatePaginatedResults([]*Item{}, 10),\n\t\t\texpected: nil,\n\t\t},\n\t\t{\n\t\t\tname:        \"ListFuncReturnsErrorImmediately\",\n\t\t\tresults:     []*ListTestResult{{}},\n\t\t\tmockError:   fmt.Errorf(\"API error on first call\"),\n\t\t\texpected:    nil,\n\t\t\texpectError: true,\n\t\t},\n\t\t{\n\t\t\tname:          \"InitialCursorProvided\",\n\t\t\tinitialParams: &ListTestParams{Cursor: \"cursor_2\"},\n\t\t\tresults:       generatePaginatedResults(allItems[2:], 3),\n\t\t\texpected:      allItems[2:],\n\t\t},\n\t\t{\n\t\t\tname:          \"CursorBeyondAllItems\",\n\t\t\tinitialParams: &ListTestParams{Cursor: \"cursor_999\"},\n\t\t\tresults:       []*ListTestResult{{Items: []*Item{}, NextCursor: \"\"}},\n\t\t\texpected:      nil,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tlistFunc := func(ctx context.Context, params *ListTestParams) (*ListTestResult, error) {\n\t\t\t\tif len(tc.results) == 0 {\n\t\t\t\t\tt.Fatalf(\"listFunc called but no more results defined for test case %q\", tc.name)\n\t\t\t\t}\n\t\t\t\tres := tc.results[0]\n\t\t\t\ttc.results = tc.results[1:]\n\t\t\t\tvar err error\n\t\t\t\tif tc.mockError != nil {\n\t\t\t\t\terr = tc.mockError\n\t\t\t\t}\n\t\t\t\treturn res, err\n\t\t\t}\n\n\t\t\tparams := tc.initialParams\n\t\t\tif tc.initialParams == nil {\n\t\t\t\tparams = &ListTestParams{}\n\t\t\t}\n\n\t\t\tvar gotItems []*Item\n\t\t\tvar iterationErr error\n\t\t\tseq := paginate(ctx, params, listFunc, func(r *ListTestResult) []*Item { return r.Items })\n\t\t\tfor item, err := range seq {\n\t\t\t\tif err != nil {\n\t\t\t\t\titerationErr = err\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tgotItems = append(gotItems, item)\n\t\t\t}\n\t\t\tif tc.expectError {\n\t\t\t\tif iterationErr == nil {\n\t\t\t\t\tt.Errorf(\"paginate() expected an error during iteration, but got none\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif iterationErr != nil {\n\t\t\t\t\tt.Errorf(\"paginate() got: %v, want: nil\", iterationErr)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif diff := cmp.Diff(tc.expected, gotItems, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"paginate() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClientPaginateVariousPageSizes(t *testing.T) {\n\tctx := context.Background()\n\tfor i := 1; i < len(allItems)+1; i++ {\n\t\ttestname := fmt.Sprintf(\"PageSize=%d\", i)\n\t\tt.Run(testname, func(t *testing.T) {\n\t\t\tresults := generatePaginatedResults(allItems, i)\n\t\t\tlistFunc := func(ctx context.Context, params *ListTestParams) (*ListTestResult, error) {\n\t\t\t\tres := results[0]\n\t\t\t\tresults = results[1:]\n\t\t\t\treturn res, nil\n\t\t\t}\n\t\t\tvar gotItems []*Item\n\t\t\tseq := paginate(ctx, &ListTestParams{}, listFunc, func(r *ListTestResult) []*Item { return r.Items })\n\t\t\tfor item, err := range seq {\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"paginate() unexpected error during iteration: %v\", err)\n\t\t\t\t}\n\t\t\t\tgotItems = append(gotItems, item)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(allItems, gotItems, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"paginate() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/cmd.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os/exec\"\n\t\"syscall\"\n\t\"time\"\n)\n\n// A CommandTransport is a [Transport] that runs a command and communicates\n// with it over stdin/stdout, using newline-delimited JSON.\ntype CommandTransport struct {\n\tcmd *exec.Cmd\n}\n\n// NewCommandTransport returns a [CommandTransport] that runs the given command\n// and communicates with it over stdin/stdout.\n//\n// The resulting transport takes ownership of the command, starting it during\n// [CommandTransport.Connect], and stopping it when the connection is closed.\nfunc NewCommandTransport(cmd *exec.Cmd) *CommandTransport {\n\treturn &CommandTransport{cmd}\n}\n\n// Connect starts the command, and connects to it over stdin/stdout.\nfunc (t *CommandTransport) Connect(ctx context.Context) (Connection, error) {\n\tstdout, err := t.cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstdout = io.NopCloser(stdout) // close the connection by closing stdin, not stdout\n\tstdin, err := t.cmd.StdinPipe()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := t.cmd.Start(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn newIOConn(&pipeRWC{t.cmd, stdout, stdin}), nil\n}\n\n// A pipeRWC is an io.ReadWriteCloser that communicates with a subprocess over\n// stdin/stdout pipes.\ntype pipeRWC struct {\n\tcmd    *exec.Cmd\n\tstdout io.ReadCloser\n\tstdin  io.WriteCloser\n}\n\nfunc (s *pipeRWC) Read(p []byte) (n int, err error) {\n\treturn s.stdout.Read(p)\n}\n\nfunc (s *pipeRWC) Write(p []byte) (n int, err error) {\n\treturn s.stdin.Write(p)\n}\n\n// Close closes the input stream to the child process, and awaits normal\n// termination of the command. If the command does not exit, it is signalled to\n// terminate, and then eventually killed.\nfunc (s *pipeRWC) Close() error {\n\t// Spec:\n\t// \"For the stdio transport, the client SHOULD initiate shutdown by:...\n\n\t// \"...First, closing the input stream to the child process (the server)\"\n\tif err := s.stdin.Close(); err != nil {\n\t\treturn fmt.Errorf(\"closing stdin: %v\", err)\n\t}\n\tresChan := make(chan error, 1)\n\tgo func() {\n\t\tresChan <- s.cmd.Wait()\n\t}()\n\t// \"...Waiting for the server to exit, or sending SIGTERM if the server does not exit within a reasonable time\"\n\twait := func() (error, bool) {\n\t\tselect {\n\t\tcase err := <-resChan:\n\t\t\treturn err, true\n\t\tcase <-time.After(5 * time.Second):\n\t\t}\n\t\treturn nil, false\n\t}\n\tif err, ok := wait(); ok {\n\t\treturn err\n\t}\n\t// Note the condition here: if sending SIGTERM fails, don't wait and just\n\t// move on to SIGKILL.\n\tif err := s.cmd.Process.Signal(syscall.SIGTERM); err == nil {\n\t\tif err, ok := wait(); ok {\n\t\t\treturn err\n\t\t}\n\t}\n\t// \"...Sending SIGKILL if the server does not exit within a reasonable time after SIGTERM\"\n\tif err := s.cmd.Process.Kill(); err != nil {\n\t\treturn err\n\t}\n\tif err, ok := wait(); ok {\n\t\treturn err\n\t}\n\treturn fmt.Errorf(\"unresponsive subprocess\")\n}\n"
  },
  {
    "path": "internal/mcp/cmd_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nconst runAsServer = \"_MCP_RUN_AS_SERVER\"\n\nfunc TestMain(m *testing.M) {\n\tif os.Getenv(runAsServer) != \"\" {\n\t\tos.Unsetenv(runAsServer)\n\t\trunServer()\n\t\treturn\n\t}\n\tos.Exit(m.Run())\n}\n\nfunc runServer() {\n\tctx := context.Background()\n\n\tserver := mcp.NewServer(\"greeter\", \"v0.0.1\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi))\n\n\tif err := server.Run(ctx, mcp.NewStdioTransport()); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc TestCmdTransport(t *testing.T) {\n\t// Conservatively, limit to major OS where we know that os.Exec is\n\t// supported.\n\tswitch runtime.GOOS {\n\tcase \"darwin\", \"linux\", \"windows\":\n\tdefault:\n\t\tt.Skip(\"unsupported OS\")\n\t}\n\n\tctx := t.Context()\n\n\texe, err := os.Executable()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcmd := exec.Command(exe)\n\tcmd.Env = append(os.Environ(), runAsServer+\"=true\")\n\n\tclient := mcp.NewClient(\"client\", \"v0.0.1\", nil)\n\tsession, err := client.Connect(ctx, mcp.NewCommandTransport(cmd))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tgot, err := session.CallTool(ctx, &mcp.CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"user\"},\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\twant := &mcp.CallToolResult{\n\t\tContent: []*mcp.Content{{Type: \"text\", Text: \"Hi user\"}},\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"greet returned unexpected content (-want +got):\\n%s\", diff)\n\t}\n\tif err := session.Close(); err != nil {\n\t\tt.Fatalf(\"closing server: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/conformance_go124_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build goexperiment.synctest\n\npackage mcp\n\nimport (\n\t\"testing\"\n\t\"testing/synctest\"\n)\n\nfunc runSyncTest(t *testing.T, f func(t *testing.T)) {\n\tsynctest.Run(func() { f(t) })\n}\n"
  },
  {
    "path": "internal/mcp/conformance_go125_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.25\n\npackage mcp\n\nimport (\n\t\"testing\"\n\t\"testing/synctest\"\n)\n\nfunc runSyncTest(t *testing.T, f func(t *testing.T)) {\n\tsynctest.Test(t, f)\n}\n"
  },
  {
    "path": "internal/mcp/conformance_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build goexperiment.synctest || go1.25\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/synctest\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nvar update = flag.Bool(\"update\", false, \"if set, update conformance test data\")\n\n// A conformance test checks JSON-level conformance of a test server or client.\n// This allows us to confirm that we can handle the input or output of other\n// SDKs, even if they behave differently at the JSON level (for example, have\n// different behavior with respect to optional fields).\n//\n// The client and server fields hold an encoded sequence of JSON-RPC messages.\n//\n// For server tests, the client messages are a sequence of messages to be sent\n// from the (synthetic) client and the server messages are the expected\n// messages to be received from the real server.\n//\n// For client tests, it's the other way around: server messages are synthetic,\n// and client messages are expected from the real client.\n//\n// Conformance tests are loaded from txtar-encoded testdata files. Run the test\n// with -update to have the test runner update the expected output, which may\n// be client or server depending on the perspective of the test.\ntype conformanceTest struct {\n\tname                      string           // test name\n\tpath                      string           // path to test file\n\tarchive                   *txtar.Archive   // raw archive, for updating\n\ttools, prompts, resources []string         // named features to include\n\tclient                    []JSONRPCMessage // client messages\n\tserver                    []JSONRPCMessage // server messages\n}\n\n// TODO(rfindley): add client conformance tests.\n\nfunc TestServerConformance(t *testing.T) {\n\tvar tests []*conformanceTest\n\tdir := filepath.Join(\"testdata\", \"conformance\", \"server\")\n\tif err := filepath.WalkDir(dir, func(path string, _ fs.DirEntry, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif strings.HasSuffix(path, \".txtar\") {\n\t\t\ttest, err := loadConformanceTest(dir, path)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%s: %v\", path, err)\n\t\t\t}\n\t\t\ttests = append(tests, test)\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\t// We use synctest here because in general, there is no way to know when the\n\t\t\t// server is done processing any notifications. As long as our server doesn't\n\t\t\t// do background work, synctest provides an easy way for us to detect when the\n\t\t\t// server is done processing.\n\t\t\t//\n\t\t\t// By comparison, gopls has a complicated framework based on progress\n\t\t\t// reporting and careful accounting to detect when all 'expected' work\n\t\t\t// on the server is complete.\n\t\t\trunSyncTest(t, func(t *testing.T) { runServerTest(t, test) })\n\n\t\t\t// TODO: in 1.25, use the following instead:\n\t\t\t// synctest.Test(t, func(t *testing.T) {\n\t\t\t// \trunServerTest(t, test)\n\t\t\t// })\n\t\t})\n\t}\n}\n\n// runServerTest runs the server conformance test.\n// It must be executed in a synctest bubble.\nfunc runServerTest(t *testing.T, test *conformanceTest) {\n\tctx := t.Context()\n\t// Construct the server based on features listed in the test.\n\ts := NewServer(\"testServer\", \"v1.0.0\", nil)\n\tadd(tools, s.AddTools, test.tools...)\n\tadd(prompts, s.AddPrompts, test.prompts...)\n\tadd(resources, s.AddResources, test.resources...)\n\n\t// Connect the server, and connect the client stream,\n\t// but don't connect an actual client.\n\tcTransport, sTransport := NewInMemoryTransports()\n\tss, err := s.Connect(ctx, sTransport)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcStream, err := cTransport.Connect(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twriteMsg := func(msg JSONRPCMessage) {\n\t\tif err := cStream.Write(ctx, msg); err != nil {\n\t\t\tt.Fatalf(\"Write failed: %v\", err)\n\t\t}\n\t}\n\n\tvar (\n\t\tserverMessages []JSONRPCMessage\n\t\toutRequests    []*JSONRPCRequest\n\t\toutResponses   []*JSONRPCResponse\n\t)\n\n\t// Separate client requests and responses; we use them differently.\n\tfor _, msg := range test.client {\n\t\tswitch msg := msg.(type) {\n\t\tcase *JSONRPCRequest:\n\t\t\toutRequests = append(outRequests, msg)\n\t\tcase *JSONRPCResponse:\n\t\t\toutResponses = append(outResponses, msg)\n\t\tdefault:\n\t\t\tt.Fatalf(\"bad message type %T\", msg)\n\t\t}\n\t}\n\n\t// nextResponse handles incoming requests and notifications, and returns the\n\t// next incoming response.\n\tnextResponse := func() (*JSONRPCResponse, error, bool) {\n\t\tfor {\n\t\t\tmsg, err := cStream.Read(ctx)\n\t\t\tif err != nil {\n\t\t\t\t// TODO(rfindley): we don't document (or want to document) that the in\n\t\t\t\t// memory transports use a net.Pipe. How can users detect this failure?\n\t\t\t\t// Should we promote it to EOF?\n\t\t\t\tif errors.Is(err, io.ErrClosedPipe) {\n\t\t\t\t\terr = nil\n\t\t\t\t}\n\t\t\t\treturn nil, err, false\n\t\t\t}\n\t\t\tserverMessages = append(serverMessages, msg)\n\t\t\tif req, ok := msg.(*JSONRPCRequest); ok && req.ID.IsValid() {\n\t\t\t\t// Pair up the next outgoing response with this request.\n\t\t\t\t// We assume requests arrive in the same order every time.\n\t\t\t\tif len(outResponses) == 0 {\n\t\t\t\t\tt.Fatalf(\"no outgoing response for request %v\", req)\n\t\t\t\t}\n\t\t\t\toutResponses[0].ID = req.ID\n\t\t\t\twriteMsg(outResponses[0])\n\t\t\t\toutResponses = outResponses[1:]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn msg.(*JSONRPCResponse), nil, true\n\t\t}\n\t}\n\n\t// Synthetic peer interacts with real peer.\n\tfor _, req := range outRequests {\n\t\twriteMsg(req)\n\t\tif req.ID.IsValid() {\n\t\t\t// A request (as opposed to a notification). Wait for the response.\n\t\t\tres, err, ok := nextResponse()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"reading server messages failed: %v\", err)\n\t\t\t}\n\t\t\tif !ok {\n\t\t\t\tt.Fatalf(\"missing response for request %v\", req)\n\t\t\t}\n\t\t\tif res.ID != req.ID {\n\t\t\t\tt.Fatalf(\"out-of-order response %v to request %v\", req, res)\n\t\t\t}\n\t\t}\n\t}\n\t// There might be more notifications or requests, but there shouldn't be more\n\t// responses.\n\t// Run this in a goroutine so the current thread can wait for it.\n\tvar extra *JSONRPCResponse\n\tgo func() {\n\t\textra, err, _ = nextResponse()\n\t}()\n\t// Before closing the stream, wait for all messages to be processed.\n\tsynctest.Wait()\n\tif err != nil {\n\t\tt.Fatalf(\"reading server messages failedd: %v\", err)\n\t}\n\tif extra != nil {\n\t\tt.Fatalf(\"got extra response: %v\", extra)\n\t}\n\tif err := cStream.Close(); err != nil {\n\t\tt.Fatalf(\"Stream.Close failed: %v\", err)\n\t}\n\tss.Wait() // ignore error\n\n\t// Handle server output. If -update is set, write the 'server' file.\n\t// Otherwise, compare with expected.\n\tif *update {\n\t\tarch := &txtar.Archive{\n\t\t\tComment: test.archive.Comment,\n\t\t}\n\t\tvar buf bytes.Buffer\n\t\tfor _, msg := range serverMessages {\n\t\t\tdata, err := jsonrpc2.EncodeIndent(msg, \"\", \"\\t\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"jsonrpc2.EncodeIndent failed: %v\", err)\n\t\t\t}\n\t\t\tbuf.Write(data)\n\t\t\tbuf.WriteByte('\\n')\n\t\t}\n\t\tserverFile := txtar.File{Name: \"server\", Data: buf.Bytes()}\n\t\tseenServer := false // replace or append the 'server' file\n\t\tfor _, f := range test.archive.Files {\n\t\t\tif f.Name == \"server\" {\n\t\t\t\tseenServer = true\n\t\t\t\tarch.Files = append(arch.Files, serverFile)\n\t\t\t} else {\n\t\t\t\tarch.Files = append(arch.Files, f)\n\t\t\t}\n\t\t}\n\t\tif !seenServer {\n\t\t\tarch.Files = append(arch.Files, serverFile)\n\t\t}\n\t\tif err := os.WriteFile(test.path, txtar.Format(arch), 0o666); err != nil {\n\t\t\tt.Fatalf(\"os.WriteFile(%q) failed: %v\", test.path, err)\n\t\t}\n\t} else {\n\t\t// JSONRPCMessages are not comparable, so we instead compare lines of JSON.\n\t\ttransform := cmpopts.AcyclicTransformer(\"toJSON\", func(msg JSONRPCMessage) []string {\n\t\t\tencoded, err := jsonrpc2.EncodeIndent(msg, \"\", \"\\t\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\treturn strings.Split(string(encoded), \"\\n\")\n\t\t})\n\t\tif diff := cmp.Diff(test.server, serverMessages, transform); diff != \"\" {\n\t\t\tt.Errorf(\"Mismatching server messages (-want +got):\\n%s\", diff)\n\t\t}\n\t}\n}\n\n// loadConformanceTest loads one conformance test from the given path contained\n// in the root dir.\nfunc loadConformanceTest(dir, path string) (*conformanceTest, error) {\n\tcontent, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttest := &conformanceTest{\n\t\tname:    strings.TrimPrefix(path, dir+string(filepath.Separator)),\n\t\tpath:    path,\n\t\tarchive: txtar.Parse(content),\n\t}\n\tif len(test.archive.Files) == 0 {\n\t\treturn nil, fmt.Errorf(\"txtar archive %q has no '-- filename --' sections\", path)\n\t}\n\n\t// decodeMessages loads JSON-RPC messages from the archive file.\n\tdecodeMessages := func(data []byte) ([]JSONRPCMessage, error) {\n\t\tdec := json.NewDecoder(bytes.NewReader(data))\n\t\tvar res []JSONRPCMessage\n\t\tfor dec.More() {\n\t\t\tvar raw json.RawMessage\n\t\t\tif err := dec.Decode(&raw); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tm, err := jsonrpc2.DecodeMessage(raw)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres = append(res, m)\n\t\t}\n\t\treturn res, nil\n\t}\n\t// loadFeatures loads lists of named features from the archive file.\n\tloadFeatures := func(data []byte) []string {\n\t\tvar feats []string\n\t\tfor line := range strings.Lines(string(data)) {\n\t\t\tif f := strings.TrimSpace(line); f != \"\" {\n\t\t\t\tfeats = append(feats, f)\n\t\t\t}\n\t\t}\n\t\treturn feats\n\t}\n\n\tseen := make(map[string]bool) // catch accidentally duplicate files\n\tfor _, f := range test.archive.Files {\n\t\tif seen[f.Name] {\n\t\t\treturn nil, fmt.Errorf(\"duplicate file name %q\", f.Name)\n\t\t}\n\t\tseen[f.Name] = true\n\t\tswitch f.Name {\n\t\tcase \"tools\":\n\t\t\ttest.tools = loadFeatures(f.Data)\n\t\tcase \"prompts\":\n\t\t\ttest.prompts = loadFeatures(f.Data)\n\t\tcase \"resources\":\n\t\t\ttest.resources = loadFeatures(f.Data)\n\t\tcase \"client\":\n\t\t\ttest.client, err = decodeMessages(f.Data)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"txtar archive %q contains bad -- client -- section: %v\", path, err)\n\t\t\t}\n\t\tcase \"server\":\n\t\t\ttest.server, err = decodeMessages(f.Data)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"txtar archive %q contains bad -- server -- section: %v\", path, err)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"txtar archive %q contains unexpected file %q\", path, f.Name)\n\t\t}\n\t}\n\n\treturn test, nil\n}\n"
  },
  {
    "path": "internal/mcp/content.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Content is the wire format for content.\n// It represents the protocol types TextContent, ImageContent, AudioContent\n// and EmbeddedResource.\n// Use [NewTextContent], [NewImageContent], [NewAudioContent] or [NewResourceContent]\n// to create one.\n//\n// The Type field must be one of \"text\", \"image\", \"audio\" or \"resource\". The\n// constructors above populate this field appropriately.\n// Although at most one of Text, Data, and Resource should be non-zero, consumers of Content\n// use the Type field to determine which value to use; values in the other fields are ignored.\ntype Content struct {\n\tType        string            `json:\"type\"`\n\tText        string            `json:\"text,omitempty\"`\n\tMIMEType    string            `json:\"mimeType,omitempty\"`\n\tData        []byte            `json:\"data,omitempty\"`\n\tResource    *ResourceContents `json:\"resource,omitempty\"`\n\tAnnotations *Annotations      `json:\"annotations,omitempty\"`\n}\n\nfunc (c *Content) UnmarshalJSON(data []byte) error {\n\ttype wireContent Content // for naive unmarshaling\n\tvar c2 wireContent\n\tif err := json.Unmarshal(data, &c2); err != nil {\n\t\treturn err\n\t}\n\tswitch c2.Type {\n\tcase \"text\", \"image\", \"audio\", \"resource\":\n\tdefault:\n\t\treturn fmt.Errorf(\"unrecognized content type %s\", c.Type)\n\t}\n\t*c = Content(c2)\n\treturn nil\n}\n\n// NewTextContent creates a [Content] with text.\nfunc NewTextContent(text string) *Content {\n\treturn &Content{Type: \"text\", Text: text}\n}\n\n// NewImageContent creates a [Content] with image data.\nfunc NewImageContent(data []byte, mimeType string) *Content {\n\treturn &Content{Type: \"image\", Data: data, MIMEType: mimeType}\n}\n\n// NewAudioContent creates a [Content] with audio data.\nfunc NewAudioContent(data []byte, mimeType string) *Content {\n\treturn &Content{Type: \"audio\", Data: data, MIMEType: mimeType}\n}\n\n// NewResourceContent creates a [Content] with an embedded resource.\nfunc NewResourceContent(resource *ResourceContents) *Content {\n\treturn &Content{Type: \"resource\", Resource: resource}\n}\n\n// ResourceContents represents the union of the spec's {Text,Blob}ResourceContents types.\n// See https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-03-26/schema.ts#L524-L551\n// for the inheritance structure.\n\n// A ResourceContents is either a TextResourceContents or a BlobResourceContents.\n// Use [NewTextResourceContents] or [NextBlobResourceContents] to create one.\ntype ResourceContents struct {\n\tURI      string `json:\"uri\"` // resource location; must not be empty\n\tMIMEType string `json:\"mimeType,omitempty\"`\n\tText     string `json:\"text\"`\n\tBlob     []byte `json:\"blob,omitempty\"` // if nil, then text; else blob\n}\n\nfunc (r ResourceContents) MarshalJSON() ([]byte, error) {\n\t// TODO(adonovan): now we can assume Go 1.24, use omitzero for Blob and avoid this method.\n\tif r.URI == \"\" {\n\t\treturn nil, errors.New(\"ResourceContents missing URI\")\n\t}\n\tif r.Blob == nil {\n\t\t// Text. Marshal normally.\n\t\ttype wireResourceContents ResourceContents // (lacks MarshalJSON method)\n\t\treturn json.Marshal((wireResourceContents)(r))\n\t}\n\t// Blob.\n\tif r.Text != \"\" {\n\t\treturn nil, errors.New(\"ResourceContents has non-zero Text and Blob fields\")\n\t}\n\t// r.Blob may be the empty slice, so marshal with an alternative definition.\n\tbr := struct {\n\t\tURI      string `json:\"uri,omitempty\"`\n\t\tMIMEType string `json:\"mimeType,omitempty\"`\n\t\tBlob     []byte `json:\"blob\"`\n\t}{\n\t\tURI:      r.URI,\n\t\tMIMEType: r.MIMEType,\n\t\tBlob:     r.Blob,\n\t}\n\treturn json.Marshal(br)\n}\n\n// NewTextResourceContents returns a [ResourceContents] containing text.\nfunc NewTextResourceContents(uri, mimeType, text string) *ResourceContents {\n\treturn &ResourceContents{\n\t\tURI:      uri,\n\t\tMIMEType: mimeType,\n\t\tText:     text,\n\t\t// Blob is nil, indicating this is a TextResourceContents.\n\t}\n}\n\n// NewBlobResourceContents returns a [ResourceContents] containing a byte slice.\nfunc NewBlobResourceContents(uri, mimeType string, blob []byte) *ResourceContents {\n\t// The only way to distinguish text from blob is a non-nil Blob field.\n\tif blob == nil {\n\t\tblob = []byte{}\n\t}\n\treturn &ResourceContents{\n\t\tURI:      uri,\n\t\tMIMEType: mimeType,\n\t\tBlob:     blob,\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/content_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nfunc TestContent(t *testing.T) {\n\ttests := []struct {\n\t\tin   *mcp.Content\n\t\twant string // json serialization\n\t}{\n\t\t{mcp.NewTextContent(\"hello\"), `{\"type\":\"text\",\"text\":\"hello\"}`},\n\t\t{\n\t\t\tmcp.NewImageContent([]byte(\"a1b2c3\"), \"image/png\"),\n\t\t\t`{\"type\":\"image\",\"mimeType\":\"image/png\",\"data\":\"YTFiMmMz\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.NewAudioContent([]byte(\"a1b2c3\"), \"audio/wav\"),\n\t\t\t`{\"type\":\"audio\",\"mimeType\":\"audio/wav\",\"data\":\"YTFiMmMz\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.NewResourceContent(\n\t\t\t\tmcp.NewTextResourceContents(\"file://foo\", \"text\", \"abc\"),\n\t\t\t),\n\t\t\t`{\"type\":\"resource\",\"resource\":{\"uri\":\"file://foo\",\"mimeType\":\"text\",\"text\":\"abc\"}}`,\n\t\t},\n\t\t{\n\t\t\tmcp.NewResourceContent(\n\t\t\t\tmcp.NewBlobResourceContents(\"file://foo\", \"image/png\", []byte(\"a1b2c3\")),\n\t\t\t),\n\t\t\t`{\"type\":\"resource\",\"resource\":{\"uri\":\"file://foo\",\"mimeType\":\"image/png\",\"blob\":\"YTFiMmMz\"}}`,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tgot, err := json.Marshal(test.in)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff(test.want, string(got)); diff != \"\" {\n\t\t\tt.Errorf(\"json.Marshal(%v) mismatch (-want +got):\\n%s\", test.in, diff)\n\t\t}\n\t\tvar out *mcp.Content\n\t\tif err := json.Unmarshal(got, &out); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff(test.in, out); diff != \"\" {\n\t\t\tt.Errorf(\"json.Unmarshal(%q) mismatch (-want +got):\\n%s\", string(got), diff)\n\t\t}\n\t}\n}\n\nfunc TestResourceContents(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\trc   mcp.ResourceContents\n\t\twant string // marshaled JSON\n\t}{\n\t\t{\n\t\t\tmcp.ResourceContents{URI: \"u\", Text: \"t\"},\n\t\t\t`{\"uri\":\"u\",\"text\":\"t\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.ResourceContents{URI: \"u\", MIMEType: \"m\", Text: \"t\"},\n\t\t\t`{\"uri\":\"u\",\"mimeType\":\"m\",\"text\":\"t\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.ResourceContents{URI: \"u\", Text: \"\", Blob: nil},\n\t\t\t`{\"uri\":\"u\",\"text\":\"\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.ResourceContents{URI: \"u\", Blob: []byte{}},\n\t\t\t`{\"uri\":\"u\",\"blob\":\"\"}`,\n\t\t},\n\t\t{\n\t\t\tmcp.ResourceContents{URI: \"u\", Blob: []byte{1}},\n\t\t\t`{\"uri\":\"u\",\"blob\":\"AQ==\"}`,\n\t\t},\n\t} {\n\t\tdata, err := json.Marshal(tt.rc)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif got := string(data); got != tt.want {\n\t\t\tt.Errorf(\"%#v:\\ngot  %s\\nwant %s\", tt.rc, got, tt.want)\n\t\t}\n\t\tvar urc mcp.ResourceContents\n\t\tif err := json.Unmarshal(data, &urc); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff(tt.rc, urc); diff != \"\" {\n\t\t\tt.Errorf(\"mismatch (-want, +got):\\n%s\", diff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/create-repo.sh",
    "content": "#!/bin/bash\n\n# This script creates an MCP SDK repo from x/tools/internal/mcp (and friends).\n# It will be used as a one-off to create github.com/modelcontextprotocol/go-sdk.\n#\n# Requires https://github.com/newren/git-filter-repo.\n\nset -eu\n\n# Check if exactly one argument is provided\nif [ \"$#\" -ne 1 ]; then\n  echo \"create-repo.sh: create a standalone mcp SDK repo from x/tools\"\n  echo \"Usage: $0 <mcp repo destination>\"\n  exit 1\nfi >&2\n\nsrc=$(go list -m -f {{.Dir}} golang.org/x/tools)\ndest=\"$1\"\n\necho \"Filtering MCP commits from ${src} to ${dest}...\" >&2\n\nstartdir=$(pwd)\ntempdir=$(mktemp -d)\nfunction cleanup {\n  echo \"cleaning up ${tempdir}\"\n  rm -rf \"$tempdir\"\n} >&2\ntrap cleanup EXIT SIGINT\n\necho \"Checking out to ${tempdir}\"\n\ngit clone --bare \"${src}\" \"${tempdir}\"\ngit -C \"${tempdir}\" --git-dir=. filter-repo \\\n  --path internal/mcp/jsonschema --path-rename internal/mcp/jsonschema:jsonschema \\\n  --path internal/mcp/design --path-rename internal/mcp/design:design \\\n  --path internal/mcp/examples --path-rename internal/mcp/examples:examples \\\n  --path internal/mcp/internal --path-rename internal/mcp/internal:internal \\\n  --path internal/mcp/README.md --path-rename internal/mcp/README.md:README.md \\\n  --path internal/mcp/CONTRIBUTING.md --path-rename internal/mcp/CONTRIBUTING.md:CONTRIBUTING.md \\\n  --path internal/mcp --path-rename internal/mcp:mcp \\\n  --path internal/jsonrpc2_v2 --path-rename internal/jsonrpc2_v2:internal/jsonrpc2 \\\n  --path internal/xcontext \\\n  --replace-text \"${startdir}/mcp-repo-replace.txt\" \\\n  --force\nmkdir ${dest}\ncd \"${dest}\"\ngit init\n\ncat << EOF > LICENSE\nMIT License\n\nCopyright (c) 2025 Go MCP SDK Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\nEOF\n\ngit add LICENSE && git commit -m \"Initial commit: add LICENSE\"\ngit remote add filtered_source \"${tempdir}\"\ngit pull filtered_source master --allow-unrelated-histories\ngit remote remove filtered_source\ngo mod init github.com/modelcontextprotocol/go-sdk && go get go@1.23.0\ngo mod tidy\ngit add go.mod go.sum\ngit commit -m \"all: add go.mod and go.sum file\"\n"
  },
  {
    "path": "internal/mcp/design/design.md",
    "content": "# Go SDK Design\n\nThis document discusses the design of a Go SDK for the [model context protocol](https://modelcontextprotocol.io/specification/2025-03-26). The [golang.org/x/tools/internal/mcp](https://pkg.go.dev/golang.org/x/tools/internal/mcp@master) package contains a prototype that we built to explore the MCP design space. Many of the ideas there are present in this document. However, we have diverged from and expanded on the APIs of that prototype, and this document should be considered canonical.\n\n## Similarities and differences with mark3labs/mcp-go (and others)\n\nThe most popular unofficial MCP SDK for Go is [mark3labs/mcp-go](https://pkg.go.dev/github.com/mark3labs/mcp-go). As of this writing, it is imported by over 400 packages that span over 200 modules.\n\nWe admire mcp-go, and where possible tried to align with its design. However, the APIs here diverge in a number of ways in order to keep the official SDK minimal, allow for future spec evolution, and support additional features. We have noted significant differences from mcp-go in the sections below. Although the API here is not compatible with mcp-go, translating between them should be straightforward in most cases. (Later, we will provide a detailed translation guide.)\n\nThank you to everyone who contributes to mcp-go and other Go SDKs. We hope that we can collaborate to leverage all that we've learned about MCP and Go in an official SDK.\n\n# Requirements\n\nThese may be obvious, but it's worthwhile to define goals for an official MCP SDK. An official SDK should aim to be:\n\n- **complete**: it should be possible to implement every feature of the MCP spec, and these features should conform to all of the semantics described by the spec.\n- **idiomatic**: as much as possible, MCP features should be modeled using features of the Go language and its standard library. Additionally, the SDK should repeat idioms from similar domains.\n- **robust**: the SDK itself should be well tested and reliable, and should enable easy testability for its users.\n- **future-proof**: the SDK should allow for future evolution of the MCP spec, in such a way that we can (as much as possible) avoid incompatible changes to the SDK API.\n- **extensible**: to best serve the previous four concerns, the SDK should be minimal. However, it should admit extensibility using (for example) simple interfaces, middleware, or hooks.\n\n# Design\n\nIn the sections below, we visit each aspect of the MCP spec, in approximately the order they are presented by the [official spec](https://modelcontextprotocol.io/specification/2025-03-26) For each, we discuss considerations for the Go implementation, and propose a Go API.\n\n## Foundations\n\n### Package layout\n\nIn the sections that follow, it is assumed that most of the MCP API lives in a single shared package, the `mcp` package. This is inconsistent with other MCP SDKs, but is consistent with Go packages like `net/http`, `net/rpc`, or `google.golang.org/grpc`. We believe that having a single package aids discoverability in package documentation and in the IDE. Furthermore, it avoids arbitrary decisions about package structure that may be rendered inaccurate by future evolution of the spec.\n\nFunctionality that is not directly related to MCP (like jsonschema or jsonrpc2) belongs in a separate package.\n\nTherefore, this is the core package layout, assuming github.com/modelcontextprotocol/go-sdk as the module path.\n\n- `github.com/modelcontextprotocol/go-sdk/mcp`: the bulk of the user facing API\n- `github.com/modelcontextprotocol/go-sdk/jsonschema`: a jsonschema implementation, with validation\n- `github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2`: a fork of x/tools/internal/jsonrpc2_v2\n\nThe JSON-RPC implementation is hidden, to avoid tight coupling. As described in the next section, the only aspects of JSON-RPC that need to be exposed in the SDK are the message types, for the purposes of defining custom transports. We can expose these types by promoting them from the `mcp` package using aliases or wrappers.\n\n**Difference from mcp-go**: Our `mcp` package includes all the functionality of mcp-go's `mcp`, `client`, `server` and `transport` packages.\n\n### JSON-RPC and Transports\n\nThe MCP is defined in terms of client-server communication over bidirectional JSON-RPC message connections. Specifically, version `2025-03-26` of the spec defines two transports:\n\n- **stdio**: communication with a subprocess over stdin/stdout.\n- **streamable http**: communication over a relatively complicated series of text/event-stream GET and HTTP POST requests.\n\nAdditionally, version `2024-11-05` of the spec defined a simpler (yet stateful) HTTP transport:\n\n- **sse**: client issues a hanging GET request and receives messages via `text/event-stream`, and sends messages via POST to a session endpoint.\n\nFurthermore, the spec [states](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#custom-transports) that it must be possible for users to define their own custom transports.\n\nGiven the diversity of the transport implementations, they can be challenging to abstract. However, since JSON-RPC requires a bidirectional connection, we can use this to model the MCP transport abstraction:\n\n```go\ntype (\n\tJSONRPCID       = jsonrpc2.ID\n\tJSONRPCMessage  = jsonrpc2.Message\n\tJSONRPCRequest  = jsonrpc2.Request\n\tJSONRPCResponse = jsonrpc2.Response\n)\n\n// A Transport is used to create a bidirectional connection between MCP client\n// and server.\ntype Transport interface {\n    Connect(ctx context.Context) (Connection, error)\n}\n\n// A Connection is a bidirectional jsonrpc2 connection.\ntype Connection interface {\n    Read(ctx context.Context) (JSONRPCMessage, error)\n    Write(ctx context.Context, JSONRPCMessage) error\n    Close() error\n}\n```\n\nMethods accept a Go `Context` and return an `error`, as is idiomatic for APIs that do I/O.\n\nA `Transport` is something that connects a logical JSON-RPC connection, and nothing more. Connections must be closeable in order to implement client and server shutdown, and therefore conform to the `io.Closer` interface.\n\nOther SDKs define higher-level transports, with, for example, methods to send a notification or make a call. Those are jsonrpc2 operations on top of the logical connection, and the lower-level interface is easier to implement in most cases, which means it is easier to implement custom transports.\n\nFor our prototype, we've used an internal `jsonrpc2` package based on the Go language server `gopls`, which we propose to fork for the MCP SDK. It already handles concerns like client/server connection, request lifecycle, cancellation, and shutdown.\n\n**Differences from mcp-go**: The Go team has a battle-tested JSON-RPC implementation that we use for gopls, our Go LSP server. We are using the new version of this library as part of our MCP SDK. It handles all JSON-RPC 2.0 features, including cancellation.\n\nThe `Transport` interface here is lower-level than that of mcp-go, but serves a similar purpose. We believe the lower-level interface is easier to implement.\n\n#### stdio transports\n\nIn the MCP Spec, the **stdio** transport uses newline-delimited JSON to communicate over stdin/stdout. It's possible to model both client side and server side of this communication with a shared type that communicates over an `io.ReadWriteCloser`. However, for the purposes of future-proofing, we should use a different types for client and server stdio transport.\n\nThe `CommandTransport` is the client side of the stdio transport, and connects by starting a command and streaming JSON-RPC messages over stdin/stdout.\n\n```go\n// A CommandTransport is a [Transport] that runs a command and communicates\n// with it over stdin/stdout, using newline-delimited JSON.\ntype CommandTransport struct { /* unexported fields */ }\n\n// NewCommandTransport returns a [CommandTransport] that runs the given command\n// and communicates with it over stdin/stdout.\nfunc NewCommandTransport(cmd *exec.Command) *CommandTransport\n\n// Connect starts the command, and connects to it over stdin/stdout.\nfunc (*CommandTransport) Connect(ctx context.Context) (Connection, error) {\n```\n\nThe `StdioTransport` is the server side of the stdio transport, and connects by binding to `os.Stdin` and `os.Stdout`.\n\n```go\n// A StdioTransport is a [Transport] that communicates using newline-delimited\n// JSON over stdin/stdout.\ntype StdioTransport struct { /* unexported fields */ }\n\nfunc NewStdioTransport() *StdioTransport\n\nfunc (t *StdioTransport) Connect(context.Context) (Connection, error)\n```\n\n#### HTTP transports\n\nThe HTTP transport APIs are even more asymmetrical. Since connections are initiated via HTTP requests, the client developer will create a transport, but the server developer will typically install an HTTP handler. Internally, the HTTP handler will create a logical transport for each new client connection.\n\nImportantly, since they serve many connections, the HTTP handlers must accept a callback to get an MCP server for each new session. As described below, MCP servers can optionally connect to multiple clients. This allows customization of per-session servers: if the MCP server is stateless, the user can return the same MCP server for each connection. On the other hand, if any per-session customization is required, it is possible by returning a different `Server` instance for each connection.\n\n```go\n// SSEHTTPHandler is an http.Handler that serves SSE-based MCP sessions as defined by\n// the 2024-11-05 version of the MCP protocol.\ntype SSEHTTPHandler struct { /* unexported fields */ }\n\n// NewSSEHTTPHandler returns a new [SSEHTTPHandler] that is ready to serve HTTP.\n//\n// The getServer function is used to bind created servers for new sessions. It\n// is OK for getServer to return the same server multiple times.\nfunc NewSSEHTTPHandler(getServer func(request *http.Request) *Server) *SSEHTTPHandler\n\nfunc (*SSEHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)\n\n// Close prevents the SSEHTTPHandler from accepting new sessions, closes active\n// sessions, and awaits their graceful termination.\nfunc (*SSEHTTPHandler) Close() error\n```\n\nNotably absent are options to hook into low-level request handling for the purposes of authentication or context injection. These concerns are instead handled using standard HTTP middleware patterns. For middleware at the level of the MCP protocol, see [Middleware](#Middleware) below.\n\nBy default, the SSE handler creates messages endpoints with the `?sessionId=...` query parameter. Users that want more control over the management of sessions and session endpoints may write their own handler, and create `SSEServerTransport` instances themselves for incoming GET requests.\n\n```go\n// A SSEServerTransport is a logical SSE session created through a hanging GET\n// request.\n//\n// When connected, it returns the following [Connection] implementation:\n//   - Writes are SSE 'message' events to the GET response.\n//   - Reads are received from POSTs to the session endpoint, via\n//     [SSEServerTransport.ServeHTTP].\n//   - Close terminates the hanging GET.\ntype SSEServerTransport struct { /* ... */ }\n\n// NewSSEServerTransport creates a new SSE transport for the given messages\n// endpoint, and hanging GET response.\n//\n// Use [SSEServerTransport.Connect] to initiate the flow of messages.\n//\n// The transport is itself an [http.Handler]. It is the caller's responsibility\n// to ensure that the resulting transport serves HTTP requests on the given\n// session endpoint.\n//\n// Most callers should instead use an [SSEHandler], which transparently handles\n// the delegation to SSEServerTransports.\nfunc NewSSEServerTransport(endpoint string, w http.ResponseWriter) *SSEServerTransport\n\n// ServeHTTP handles POST requests to the transport endpoint.\nfunc (*SSEServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request)\n\n// Connect sends the 'endpoint' event to the client.\n// See [SSEServerTransport] for more details on the [Connection] implementation.\nfunc (*SSEServerTransport) Connect(context.Context) (Connection, error)\n```\n\nThe SSE client transport is simpler, and hopefully self-explanatory.\n\n```go\ntype SSEClientTransport struct { /* ... */ }\n\n// SSEClientTransportOptions provides options for the [NewSSEClientTransport]\n// constructor.\ntype SSEClientTransportOptions struct {\n\t// HTTPClient is the client to use for making HTTP requests. If nil,\n\t// http.DefaultClient is used.\n\tHTTPClient *http.Client\n}\n\n// NewSSEClientTransport returns a new client transport that connects to the\n// SSE server at the provided URL.\nfunc NewSSEClientTransport(url string, opts *SSEClientTransportOptions) (*SSEClientTransport, error)\n\n// Connect connects through the client endpoint.\nfunc (*SSEClientTransport) Connect(ctx context.Context) (Connection, error)\n```\n\nThe Streamable HTTP transports are similar to the SSE transport, albeit with a\nmore complicated implementation. For brevity, we summarize only the differences\nfrom the equivalent SSE types:\n\n```go\n// The StreamableHTTPHandler interface is symmetrical to the SSEHTTPHandler.\ntype StreamableHTTPHandler struct { /* unexported fields */ }\nfunc NewStreamableHTTPHandler(getServer func(request *http.Request) *Server) *StreamableHTTPHandler\nfunc (*StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)\nfunc (*StreamableHTTPHandler) Close() error\n\n// Unlike the SSE transport, the streamable transport constructor accepts a\n// session ID, not an endpoint, along with the HTTP response for the request\n// that created the session. It is the caller's responsibility to delegate\n// requests to this session.\ntype StreamableServerTransport struct { /* ... */ }\nfunc NewStreamableServerTransport(sessionID string) *StreamableServerTransport\nfunc (*StreamableServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request)\nfunc (*StreamableServerTransport) Connect(context.Context) (Connection, error)\n\n// The streamable client handles reconnection transparently to the user.\ntype StreamableClientTransport struct { /* ... */ }\n\n// StreamableClientTransportOptions provides options for the\n// [NewStreamableClientTransport] constructor.\ntype StreamableClientTransportOptions struct {\n\t// HTTPClient is the client to use for making HTTP requests. If nil,\n\t// http.DefaultClient is used.\n\tHTTPClient *http.Client\n}\n\nfunc NewStreamableClientTransport(url string, opts *StreamableClientTransportOptions) *StreamableClientTransport\nfunc (*StreamableClientTransport) Connect(context.Context) (Connection, error)\n```\n\n**Differences from mcp-go**: In mcp-go, server authors create an `MCPServer`, populate it with tools, resources and so on, and then wrap it in an `SSEServer` or `StdioServer`. Users can manage their own sessions with `RegisterSession` and `UnregisterSession`. Rather than use a server constructor to get a distinct server for each connection, there is a concept of a \"session tool\" that overlays tools for a specific session.\n\nHere, we tried to differentiate the concept of a `Server`, `HTTPHandler`, and `Transport`, and provide per-session customization through either the `getServer` constructor or middleware. Additionally, individual handlers and transports here have a minimal API, and do not expose internal details. (Open question: are we oversimplifying?)\n\n#### Other transports\n\nWe also provide a couple of transport implementations for special scenarios. An InMemoryTransport can be used when the client and server reside in the same process. A LoggingTransport is a middleware layer that logs RPC logs to a desired location, specified as an io.Writer.\n\n```go\n// An InMemoryTransport is a [Transport] that communicates over an in-memory\n// network connection, using newline-delimited JSON.\ntype InMemoryTransport struct { /* ... */ }\n\n// NewInMemoryTransports returns two InMemoryTransports that connect to each\n// other.\nfunc NewInMemoryTransports() (*InMemoryTransport, *InMemoryTransport)\n\n// A LoggingTransport is a [Transport] that delegates to another transport,\n// writing RPC logs to an io.Writer.\ntype LoggingTransport struct { /* ... */ }\nfunc NewLoggingTransport(delegate Transport, w io.Writer) *LoggingTransport\n```\n\n### Protocol types\n\nTypes needed for the protocol are generated from the [JSON schema of the MCP spec](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-03-26/schema.json).\n\nThese types will be included in the `mcp` package, but will be unexported unless they are needed for the user-facing API. Notably, JSON-RPC request types are elided, since they are handled by the `jsonrpc2` package and should not be observed by the user.\n\nFor user-provided data, we use `json.RawMessage` or `map[string]any`, depending on the use case.\n\nFor union types, which can't be represented in Go (specifically `Content` and `ResourceContents`), we prefer distinguished unions: struct types with fields corresponding to the union of all properties for union elements.\n\nFor brevity, only a few examples are shown here:\n\n```go\ntype ReadResourceParams struct {\n\tURI string `json:\"uri\"`\n}\n\ntype CallToolResult struct {\n\tMeta    Meta      `json:\"_meta,omitempty\"`\n\tContent []Content `json:\"content\"`\n\tIsError bool      `json:\"isError,omitempty\"`\n}\n\n// Content is the wire format for content.\n//\n// The Type field distinguishes the type of the content.\n// At most one of Text, MIMEType, Data, and Resource is non-zero.\ntype Content struct {\n\tType     string            `json:\"type\"`\n\tText     string            `json:\"text,omitempty\"`\n\tMIMEType string            `json:\"mimeType,omitempty\"`\n\tData     []byte            `json:\"data,omitempty\"`\n\tResource *ResourceContents `json:\"resource,omitempty\"`\n}\n\n// NewTextContent creates a [Content] with text.\nfunc NewTextContent(text string) *Content\n// etc.\n```\n\nThe `Meta` type includes a `map[string]any` for arbitrary data, and a `ProgressToken` field.\n\n**Differences from mcp-go**: these types are largely similar, but our type generator flattens types rather than using struct embedding.\n\n### Clients and Servers\n\nGenerally speaking, the SDK is used by creating a `Client` or `Server` instance, adding features to it, and connecting it to a peer.\n\nHowever, the SDK must make a non-obvious choice in these APIs: are clients 1:1 with their logical connections? What about servers? Both clients and servers are stateful: users may add or remove roots from clients, and tools, prompts, and resources from servers. Additionally, handlers for these features may themselves be stateful, for example if a tool handler caches state from earlier requests in the session.\n\nWe believe that in the common case, any change to a client or server, such as adding a tool, is intended for all its peers. It is therefore more useful to allow multiple connections from a client, and to a server. This is similar to the `net/http` packages, in which an `http.Client` and `http.Server` each may handle multiple unrelated connections. When users add features to a client or server, all connected peers are notified of the change.\n\nSupporting multiple connections to servers (and from clients) still allows for stateful components, as it is up to the user to decide whether or not to create distinct servers/clients for each connection. For example, if the user wants to create a distinct server for each new connection, they can do so in the `getServer` factory passed to transport handlers.\n\nFollowing the terminology of the [spec](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#session-management), we call the logical connection between a client and server a \"session.\" There must necessarily be a `ClientSession` and a `ServerSession`, corresponding to the APIs available from the client and server perspective, respectively.\n\n```\nClient                                                   Server\n  ⇅                          (jsonrpc2)                     ⇅\nClientSession ⇄ Client Transport ⇄ Server Transport ⇄ ServerSession\n```\n\nSessions are created from either `Client` or `Server` using the `Connect` method.\n\n```go\ntype Client struct { /* ... */ }\nfunc NewClient(name, version string, opts *ClientOptions) *Client\nfunc (*Client) Connect(context.Context, Transport) (*ClientSession, error)\nfunc (*Client) Sessions() iter.Seq[*ClientSession]\n// Methods for adding/removing client features are described below.\n\ntype ClientOptions struct { /* ... */ } // described below\n\ntype ClientSession struct { /* ... */ }\nfunc (*ClientSession) Client() *Client\nfunc (*ClientSession) Close() error\nfunc (*ClientSession) Wait() error\n// Methods for calling through the ClientSession are described below.\n// For example: ClientSession.ListTools.\n\ntype Server struct { /* ... */ }\nfunc NewServer(name, version string, opts *ServerOptions) *Server\nfunc (*Server) Connect(context.Context, Transport) (*ServerSession, error)\nfunc (*Server) Sessions() iter.Seq[*ServerSession]\n// Methods for adding/removing server features are described below.\n\ntype ServerOptions struct { /* ... */ } // described below\n\ntype ServerSession struct { /* ... */ }\nfunc (*ServerSession) Server() *Server\nfunc (*ServerSession) Close() error\nfunc (*ServerSession) Wait() error\n// Methods for calling through the ServerSession are described below.\n// For example: ServerSession.ListRoots.\n```\n\nHere's an example of these APIs from the client side:\n\n```go\nclient := mcp.NewClient(\"mcp-client\", \"v1.0.0\", nil)\n// Connect to a server over stdin/stdout\ntransport := mcp.NewCommandTransport(exec.Command(\"myserver\"))\nsession, err := client.Connect(ctx, transport)\nif err != nil { ... }\n// Call a tool on the server.\ncontent, err := session.CallTool(ctx, \"greet\", map[string]any{\"name\": \"you\"}, nil)\n...\nreturn session.Close()\n```\n\nA server that can handle that client call would look like this:\n\n```go\n// Create a server with a single tool.\nserver := mcp.NewServer(\"greeter\", \"v1.0.0\", nil)\nserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi))\n// Run the server over stdin/stdout, until the client disconnects.\ntransport := mcp.NewStdioTransport()\nsession, err := server.Connect(ctx, transport)\n...\nreturn session.Wait()\n```\n\nFor convenience, we provide `Server.Run` to handle the common case of running a session until the client disconnects:\n\n```go\nfunc (*Server) Run(context.Context, Transport)\n```\n\n**Differences from mcp-go**: the Server APIs are similar to mcp-go, though the association between servers and transports is different. In mcp-go, a single server is bound to what we would call an `SSEHTTPHandler`, and reused for all sessions. Per-session behavior is implemented though a 'session tool' overlay. As discussed above, the transport abstraction here is differentiated from HTTP serving, and the `Server.Connect` method provides a consistent API for binding to an arbitrary transport. Servers here do not have methods for sending notifications or calls, because they are logically distinct from the `ServerSession`. In mcp-go, servers are `n:1`, but there is no abstraction of a server session: sessions are addressed in Server APIs through their `sessionID`: `SendNotificationToAllClients`, `SendNotificationToClient`, `SendNotificationToSpecificClient`.\n\nThe client API here is different, since clients and client sessions are conceptually distinct. The `ClientSession` is closer to mcp-go's notion of Client.\n\nFor both clients and servers, mcp-go uses variadic options to customize behavior, whereas an options struct is used here. We felt that in this case, an options struct would be more readable, and result in simpler package documentation.\n\n### Spec Methods\n\nIn our SDK, RPC methods that are defined in the specification take a context and a params pointer as arguments, and return a result pointer and error:\n\n```go\nfunc (*ClientSession) ListTools(context.Context, *ListToolsParams) (*ListToolsResult, error)\n```\n\nOur SDK has a method for every RPC in the spec, their signatures all share this form. We do this, rather than providing more convenient shortcut signatures, to maintain backward compatibility if the spec makes backward-compatible changes such as adding a new property to the request parameters (as in [this commit](https://github.com/modelcontextprotocol/modelcontextprotocol/commit/2fce8a077688bf8011e80af06348b8fe1dae08ac), for example). To avoid boilerplate, we don't repeat this signature for RPCs defined in the spec; readers may assume it when we mention a \"spec method.\"\n\n`CallTool` is the only exception: for convenience when binding to Go argument types, `*CallToolParams[TArgs]` is generic, with a type parameter providing the Go type of the tool arguments. The spec method accepts a `*CallToolParams[json.RawMessage]`, but we provide a generic helper function. See the section on Tools below for details.\n\nWhy do we use params instead of the full JSON-RPC request? As much as possible, we endeavor to hide JSON-RPC details when they are not relevant to the business logic of your client or server. In this case, the additional information in the JSON-RPC request is just the request ID and method name; the request ID is irrelevant, and the method name is implied by the name of the Go method providing the API.\n\nWe believe that any change to the spec that would require callers to pass a new a parameter is not backward compatible. Therefore, it will always work to pass `nil` for any `XXXParams` argument that isn't currently necessary. For example, it is okay to call `Ping` like so:\n\n```go\nerr := session.Ping(ctx, nil)\n```\n\n#### Iterator Methods\n\nFor convenience, iterator methods handle pagination for the `List` spec methods automatically, traversing all pages. If Params are supplied, iteration begins from the provided cursor (if present).\n\n```go\nfunc (*ClientSession) Tools(context.Context, *ListToolsParams) iter.Seq2[Tool, error]\n\nfunc (*ClientSession) Prompts(context.Context, *ListPromptsParams) iter.Seq2[Prompt, error]\n\nfunc (*ClientSession) Resources(context.Context, *ListResourceParams) iter.Seq2[Resource, error]\n\nfunc (*ClientSession) ResourceTemplates(context.Context, *ListResourceTemplatesParams) iter.Seq2[ResourceTemplate, error]\n```\n\n### Middleware\n\nWe provide a mechanism to add MCP-level middleware on the both the client and server side. Receiving middleware runs after the request has been parsed but before any normal handling. It is analogous to traditional HTTP server middleware. Sending middleware runs after a call to a method but before the request is sent. It is an alternative to transport middleware that exposes MCP types instead of raw JSON-RPC 2.0 messages. It is useful for tracing and setting progress tokens, for example.\n\n```go\n// A MethodHandler handles MCP messages.\n// The params argument is an XXXParams struct pointer, such as *GetPromptParams.\n// For methods, a MethodHandler must return either an XXResult struct pointer and a nil error, or\n// nil with a non-nil error.\n// For notifications, a MethodHandler must return nil, nil.\ntype MethodHandler[S Session] func(\n\tctx context.Context, _ *S, method string, params Params) (result Result, err error)\n\n// Middleware is a function from MethodHandlers to MethodHandlers.\ntype Middleware[S Session] func(MethodHandler[S]) MethodHandler[S]\n\n// AddMiddleware wraps the client/server's current method handler using the provided\n// middleware. Middleware is applied from right to left, so that the first one\n// is executed first.\n//\n// For example, AddMiddleware(m1, m2, m3) augments the server method handler as\n// m1(m2(m3(handler))).\nfunc (c *Client) AddSendingMiddleware(middleware ...Middleware[*ClientSession])\nfunc (c *Client) AddReceivingMiddleware(middleware ...Middleware[*ClientSession])\nfunc (s *Server) AddSendingMiddleware(middleware ...Middleware[*ServerSession])\nfunc (s *Server) AddReceivingMiddleware(middleware ...Middleware[*ServerSession])\n```\n\nAs an example, this code adds server-side logging:\n\n```go\nfunc withLogging(h mcp.MethodHandler[*ServerSession]) mcp.MethodHandler[*ServerSession]{\n    return func(ctx context.Context, s *mcp.ServerSession, method string, params any) (res any, err error) {\n        log.Printf(\"request: %s %v\", method, params)\n        defer func() { log.Printf(\"response: %v, %v\", res, err) }()\n        return h(ctx, s , method, params)\n    }\n}\n\nserver.AddReceivingMiddleware(withLogging)\n```\n\n**Differences from mcp-go**: Version 0.26.0 of mcp-go defines 24 server hooks. Each hook consists of a field in the `Hooks` struct, a `Hooks.Add` method, and a type for the hook function. These are rarely used. The most common is `OnError`, which occurs fewer than ten times in open-source code.\n\n### Errors\n\nWith the exception of tool handler errors, protocol errors are handled transparently as Go errors: errors in server-side feature handlers are propagated as errors from calls from the `ClientSession`, and vice-versa.\n\nProtocol errors wrap a `JSONRPCError` type which exposes its underlying error code.\n\n```go\ntype JSONRPCError struct {\n\tCode    int64           `json:\"code\"`\n\tMessage string          `json:\"message\"`\n\tData    json.RawMessage `json:\"data,omitempty\"`\n}\n```\n\nAs described by the [spec](https://modelcontextprotocol.io/specification/2025-03-26/server/tools#error-handling), tool execution errors are reported in tool results.\n\n**Differences from mcp-go**: the `JSONRPCError` type here does not include ID and Method, which can be inferred from the caller. Otherwise, this behavior is similar.\n\n### Cancellation\n\nCancellation is implemented transparently using context cancellation. The user can cancel an operation by cancelling the associated context:\n\n```go\nctx, cancel := context.WithCancel(ctx)\ngo session.CallTool(ctx, \"slow\", map[string]any{}, nil)\ncancel()\n```\n\nWhen this client call is cancelled, a `\"notifications/cancelled\"` notification is sent to the server. However, the client call returns immediately with `ctx.Err()`: it does not wait for the result from the server.\n\nThe server observes a client cancellation as a cancelled context.\n\n### Progress handling\n\nA caller can request progress notifications by setting the `Meta.ProgressToken` field on any request.\n\n```go\ntype XXXParams struct { // where XXX is each type of call\n  Meta Meta\n  ...\n}\n\ntype Meta struct {\n  Data          map[string]any\n  ProgressToken any // string or int\n}\n```\n\nHandlers can notify their peer about progress by calling the `NotifyProgress` method. The notification is only sent if the peer requested it by providing a progress token.\n\n```go\nfunc (*ClientSession) NotifyProgress(context.Context, *ProgressNotification)\nfunc (*ServerSession) NotifyProgress(context.Context, *ProgressNotification)\n```\n\n### Ping / KeepAlive\n\nBoth `ClientSession` and `ServerSession` expose a `Ping` method to call \"ping\" on their peer.\n\n```go\nfunc (c *ClientSession) Ping(ctx context.Context, *PingParams) error\nfunc (c *ServerSession) Ping(ctx context.Context, *PingParams) error\n```\n\nAdditionally, client and server sessions can be configured with automatic keepalive behavior. If the `KeepAlive` option is set to a non-zero duration, it defines an interval for regular \"ping\" requests. If the peer fails to respond to pings originating from the keepalive check, the session is automatically closed.\n\n```go\ntype ClientOptions struct {\n  ...\n  KeepAlive time.Duration\n}\n\ntype ServerOptions struct {\n  ...\n  KeepAlive time.Duration\n}\n```\n\n**Differences from mcp-go**: in mcp-go the `Ping` method is only provided for client, not server, and the keepalive option is only provided for SSE servers (as a variadic option).\n\n## Client Features\n\n### Roots\n\nClients support the MCP Roots feature, including roots-changed notifications. Roots can be added and removed from a `Client` with `AddRoots` and `RemoveRoots`:\n\n```go\n// AddRoots adds the given roots to the client,\n// replacing any with the same URIs,\n// and notifies any connected servers.\nfunc (*Client) AddRoots(roots ...*Root)\n\n// RemoveRoots removes the roots with the given URIs.\n// and notifies any connected servers if the list has changed.\n// It is not an error to remove a nonexistent root.\nfunc (*Client) RemoveRoots(uris ...string)\n```\n\nServer sessions can call the spec method `ListRoots` to get the roots. If a server installs a `RootsChangedHandler`, it will be called when the client sends a roots-changed notification, which happens whenever the list of roots changes after a connection has been established.\n\n```go\ntype ServerOptions {\n  ...\n  // If non-nil, called when a client sends a roots-changed notification.\n  RootsChangedHandler func(context.Context, *ServerSession, *RootsChangedParams)\n}\n```\n\nThe `Roots` method provides a [cached](https://modelcontextprotocol.io/specification/2025-03-26/client/roots#implementation-guidelines) iterator of the root set, invalidated when roots change.\n\n```go\nfunc (*ServerSession) Roots(context.Context) (iter.Seq[*Root, error])\n```\n\n### Sampling\n\nClients that support sampling are created with a `CreateMessageHandler` option for handling server calls. To perform sampling, a server session calls the spec method `CreateMessage`.\n\n```go\ntype ClientOptions struct {\n  ...\n  CreateMessageHandler func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error)\n}\n```\n\n## Server Features\n\n### Tools\n\nA `Tool` is a logical MCP tool, generated from the MCP spec, and a `ServerTool` is a tool bound to a tool handler.\n\nA tool handler accepts `CallToolParams` and returns a `CallToolResult`. However, since we want to bind tools to Go input types, it is convenient in associated APIs to make `CallToolParams` generic, with a type parameter `TArgs` for the tool argument type. This allows tool APIs to manage the marshalling and unmarshalling of tool inputs for their caller. The bound `ServerTool` type expects a `json.RawMessage` for its tool arguments, but the `NewServerTool` constructor described below provides a mechanism to bind a typed handler.\n\n```go\ntype CallToolParams[TArgs any] struct {\n\tMeta      Meta   `json:\"_meta,omitempty\"`\n\tArguments TArgs  `json:\"arguments,omitempty\"`\n\tName      string `json:\"name\"`\n}\n\ntype Tool struct {\n\tAnnotations *ToolAnnotations   `json:\"annotations,omitempty\"`\n\tDescription string             `json:\"description,omitempty\"`\n\tInputSchema *jsonschema.Schema `json:\"inputSchema\"`\n\tName string                    `json:\"name\"`\n}\n\ntype ToolHandler[TArgs] func(context.Context, *ServerSession, *CallToolParams[TArgs]) (*CallToolResult, error)\n\ntype ServerTool struct {\n\tTool    Tool\n\tHandler ToolHandler[json.RawMessage]\n}\n```\n\nAdd tools to a server with `AddTools`:\n\n```go\nserver.AddTools(\n  mcp.NewServerTool(\"add\", \"add numbers\", addHandler),\n  mcp.NewServerTool(\"subtract, subtract numbers\", subHandler))\n```\n\nRemove them by name with `RemoveTools`:\n\n```go\nserver.RemoveTools(\"add\", \"subtract\")\n```\n\nA tool's input schema, expressed as a [JSON Schema](https://json-schema.org), provides a way to validate the tool's input. One of the challenges in defining tools is the need to associate them with a Go function, yet support the arbitrary complexity of JSON Schema. To achieve this, we have seen two primary approaches:\n\n1. Use reflection to generate the tool's input schema from a Go type (à la `metoro-io/mcp-golang`)\n2. Explicitly build the input schema (à la `mark3labs/mcp-go`).\n\nBoth of these have their advantages and disadvantages. Reflection is nice, because it allows you to bind directly to a Go API, and means that the JSON schema of your API is compatible with your Go types by construction. It also means that concerns like parsing and validation can be handled automatically. However, it can become cumbersome to express the full breadth of JSON schema using Go types or struct tags, and sometimes you want to express things that aren’t naturally modeled by Go types, like unions. Explicit schemas are simple and readable, and give the caller full control over their tool definition, but involve significant boilerplate.\n\nWe have found that a hybrid model works well, where the _initial_ schema is derived using reflection, but any customization on top of that schema is applied using variadic options. We achieve this using a `NewServerTool` helper, which generates the schema from the input type, and wraps the handler to provide parsing and validation. The schema (and potentially other features) can be customized using ToolOptions.\n\n```go\n// NewServerTool creates a Tool using reflection on the given handler.\nfunc NewServerTool[TArgs any](name, description string, handler ToolHandler[TArgs], opts …ToolOption) *ServerTool\n\ntype ToolOption interface { /* ... */ }\n```\n\n`NewServerTool` determines the input schema for a Tool from the `TArgs` type. Each struct field that would be marshaled by `encoding/json.Marshal` becomes a property of the schema. The property is required unless the field's `json` tag specifies \"omitempty\" or \"omitzero\" (new in Go 1.24). For example, given this struct:\n\n```go\nstruct {\n  Name     string `json:\"name\"`\n  Count    int    `json:\"count,omitempty\"`\n  Choices  []string\n  Password []byte `json:\"-\"`\n}\n```\n\n\"name\" and \"Choices\" are required, while \"count\" is optional.\n\nAs of this writing, the only `ToolOption` is `Input`, which allows customizing the input schema of the tool using schema options. These schema options are recursive, in the sense that they may also be applied to properties.\n\n```go\nfunc Input(...SchemaOption) ToolOption\n\ntype Property(name string, opts ...SchemaOption) SchemaOption\ntype Description(desc string) SchemaOption\n// etc.\n```\n\nFor example:\n\n```go\nNewServerTool(name, description, handler,\n    Input(Property(\"count\", Description(\"size of the inventory\"))))\n```\n\nThe most recent JSON Schema spec defines over 40 keywords. Providing them all as options would bloat the API despite the fact that most would be very rarely used. For less common keywords, use the `Schema` option to set the schema explicitly:\n\n```go\nNewServerTool(name, description, handler,\n    Input(Property(\"Choices\", Schema(&jsonschema.Schema{UniqueItems: true}))))\n```\n\nSchemas are validated on the server before the tool handler is called.\n\nSince all the fields of the Tool struct are exported, a Tool can also be created directly with assignment or a struct literal.\n\nClient sessions can call the spec method `ListTools` or an iterator method `Tools` to list the available tools, and use spec method `CallTool` to call tools. Similar to `ServerTool.Handler`, `CallTool` expects `*CallToolParams[json.RawMessage]`, but we provide a generic `CallTool` helper to operate on typed arguments.\n\n```go\nfunc (cs *ClientSession) CallTool(context.Context, *CallToolParams[json.RawMessage]) (*CallToolResult, error)\n\nfunc CallTool[TArgs any](context.Context, *ClientSession, *CallToolParams[TArgs]) (*CallToolResult, error)\n```\n\n**Differences from mcp-go**: using variadic options to configure tools was significantly inspired by mcp-go. However, the distinction between `ToolOption` and `SchemaOption` allows for recursive application of schema options. For example, that limitation is visible in [this code](https://github.com/DCjanus/dida365-mcp-server/blob/master/cmd/mcp/tools.go#L315), which must resort to untyped maps to express a nested schema.\n\nAdditionally, the `NewServerTool` helper provides a means for building a tool from a Go function using reflection, that automatically handles parsing and validation of inputs.\n\nWe provide a full JSON Schema implementation for validating tool input schemas against incoming arguments. The `jsonschema.Schema` type provides exported features for all keywords in the JSON Schema draft2020-12 spec. Tool definers can use it to construct any schema they want, so there is no need to provide options for all of them. When combined with schema inference from input structs, we found that we needed only three options to cover the common cases, instead of mcp-go's 23. For example, we will provide `Enum`, which occurs 125 times in open source code, but not MinItems, MinLength or MinProperties, which each occur only once (and in an SDK that wraps mcp-go).\n\nFor registering tools, we provide only `AddTools`; mcp-go's `SetTools`, `AddTool`, `AddSessionTool`, and `AddSessionTools` are deemed unnecessary. (Similarly for Delete/Remove).\n\n### Prompts\n\nUse `NewServerPrompt` to create a prompt. As with tools, prompt argument schemas can be inferred from a struct, or obtained from options.\n\n```go\nfunc NewServerPrompt[TReq any](name, description string,\n  handler func(context.Context, *ServerSession, TReq) (*GetPromptResult, error),\n  opts ...PromptOption) *ServerPrompt\n```\n\nUse `AddPrompts` to add prompts to the server, and `RemovePrompts`\nto remove them by name.\n\n```go\ntype codeReviewArgs struct {\n  Code string `json:\"code\"`\n}\n\nfunc codeReviewHandler(context.Context, *ServerSession, codeReviewArgs) {...}\n\nserver.AddPrompts(\n  NewServerPrompt(\"code_review\", \"review code\", codeReviewHandler,\n    Argument(\"code\", Description(\"the code to review\"))))\n\nserver.RemovePrompts(\"code_review\")\n```\n\nClient sessions can call the spec method `ListPrompts` or the iterator method `Prompts` to list the available prompts, and the spec method `GetPrompt` to get one.\n\n**Differences from mcp-go**: We provide a `NewServerPrompt` helper to bind a prompt handler to a Go function using reflection to derive its arguments. We provide `RemovePrompts` to remove prompts from the server.\n\n### Resources and resource templates\n\nIn our design, each resource and resource template is associated with a function that reads it, with this signature:\n\n```go\ntype ResourceHandler func(context.Context, *ServerSession, *ReadResourceParams) (*ReadResourceResult, error)\n```\n\nThe arguments include the `ServerSession` so the handler can observe the client's roots. The handler should return the resource contents in a `ReadResourceResult`, calling either `NewTextResourceContents` or `NewBlobResourceContents`. If the handler omits the URI or MIME type, the server will populate them from the resource.\n\nThe `ServerResource` and `ServerResourceTemplate` types hold the association between the resource and its handler:\n\n```go\ntype ServerResource struct {\n  Resource Resource\n  Handler  ResourceHandler\n}\n\ntype ServerResourceTemplate struct {\n  Template ResourceTemplate\n  Handler  ResourceHandler\n}\n```\n\nTo add a resource or resource template to a server, users call the `AddResources` and `AddResourceTemplates` methods with one or more `ServerResource`s or `ServerResourceTemplate`s. We also provide methods to remove them.\n\n```go\nfunc (*Server) AddResources(...*ServerResource)\nfunc (*Server) AddResourceTemplates(...*ServerResourceTemplate)\n\nfunc (s *Server) RemoveResources(uris ...string)\nfunc (s *Server) RemoveResourceTemplates(uriTemplates ...string)\n```\n\nThe `ReadResource` method finds a resource or resource template matching the argument URI and calls its associated handler.\n\nTo read files from the local filesystem, we recommend using `FileResourceHandler` to construct a handler:\n\n```go\n// FileResourceHandler returns a ResourceHandler that reads paths using dir as a root directory.\n// It protects against path traversal attacks.\n// It will not read any file that is not in the root set of the client requesting the resource.\nfunc (*Server) FileResourceHandler(dir string) ResourceHandler\n```\n\nHere is an example:\n\n```go\n// Safely read \"/public/puppies.txt\".\ns.AddResources(&mcp.ServerResource{\n  Resource: mcp.Resource{URI: \"file:///puppies.txt\"},\n  Handler: s.FileReadResourceHandler(\"/public\")})\n```\n\nServer sessions also support the spec methods `ListResources` and `ListResourceTemplates`, and the corresponding iterator methods `Resources` and `ResourceTemplates`.\n\n**Differences from mcp-go**: for symmetry with tools and prompts, we use `AddResources` rather than `AddResource`. Additionally, the `ResourceHandler` returns a `ReadResourceResult`, rather than just its content, for compatibility with future evolution of the spec.\n\n#### Subscriptions\n\nClientSessions can manage change notifications on particular resources:\n\n```go\nfunc (*ClientSession) Subscribe(context.Context, *SubscribeParams) error\nfunc (*ClientSession) Unsubscribe(context.Context, *UnsubscribeParams) error\n```\n\nThe server does not implement resource subscriptions. It passes along subscription requests to the user, and supplies a method to notify clients of changes. It tracks which sessions have subscribed to which resources so the user doesn't have to.\n\nIf a server author wants to support resource subscriptions, they must provide handlers to be called when clients subscribe and unsubscribe. It is an error to provide only one of these handlers.\n\n```go\ntype ServerOptions struct {\n  ...\n  // Function called when a client session subscribes to a resource.\n  SubscribeHandler func(context.Context, *SubscribeParams) error\n  // Function called when a client session unsubscribes from a resource.\n  UnsubscribeHandler func(context.Context, *UnsubscribeParams) error\n}\n```\n\nUser code should call `ResourceUpdated` when a subscribed resource changes.\n\n```go\nfunc (*Server) ResourceUpdated(context.Context, *ResourceUpdatedNotification) error\n```\n\nThe server routes these notifications to the server sessions that subscribed to the resource.\n\n### ListChanged notifications\n\nWhen a list of tools, prompts or resources changes as the result of an AddXXX or RemoveXXX call, the server informs all its connected clients by sending the corresponding type of notification. A client will receive these notifications if it was created with the corresponding option:\n\n```go\ntype ClientOptions struct {\n  ...\n  ToolListChangedHandler func(context.Context, *ClientSession, *ToolListChangedParams)\n  PromptListChangedHandler func(context.Context, *ClientSession, *PromptListChangedParams)\n  // For both resources and resource templates.\n  ResourceListChangedHandler func(context.Context, *ClientSession, *ResourceListChangedParams)\n}\n```\n\n**Differences from mcp-go**: mcp-go instead provides a general `OnNotification` handler. For type-safety, and to hide JSON RPC details, we provide feature-specific handlers here.\n\n### Completion\n\nClients call the spec method `Complete` to request completions. Servers automatically handle these requests based on their collections of prompts and resources.\n\n**Differences from mcp-go**: the client API is similar. mcp-go has not yet defined its server-side behavior.\n\n### Logging\n\nMCP specifies a notification for servers to log to clients. Server sessions implement this with the `LoggingMessage` method. It honors the minimum log level established by the client session's `SetLevel` call.\n\nAs a convenience, we also provide a `slog.Handler` that allows server authors to write logs with the `log/slog` package::\n\n```go\n// A LoggingHandler is a [slog.Handler] for MCP.\ntype LoggingHandler struct {...}\n\n// LoggingHandlerOptions are options for a LoggingHandler.\ntype LoggingHandlerOptions struct {\n\t// The value for the \"logger\" field of logging notifications.\n\tLoggerName string\n\t// Limits the rate at which log messages are sent.\n\t// If zero, there is no rate limiting.\n\tMinInterval time.Duration\n}\n\n// NewLoggingHandler creates a [LoggingHandler] that logs to the given [ServerSession] using a\n// [slog.JSONHandler].\nfunc NewLoggingHandler(ss *ServerSession, opts *LoggingHandlerOptions) *LoggingHandler\n```\n\nServer-to-client logging is configured with `ServerOptions`:\n\n```go\ntype ServerOptions {\n  ...\n  // The value for the \"logger\" field of the notification.\n  LoggerName string\n  // Log notifications to a single ClientSession will not be\n  // sent more frequently than this duration.\n  LoggingInterval time.Duration\n}\n```\n\nA call to a log method like `Info` is translated to a `LoggingMessageNotification` as follows:\n\n- The attributes and the message populate the \"data\" property with the output of a `slog.JSONHandler`: The result is always a JSON object, with the key \"msg\" for the message.\n\n- If the `LoggerName` server option is set, it populates the \"logger\" property.\n\n- The standard slog levels `Info`, `Debug`, `Warn` and `Error` map to the corresponding levels in the MCP spec. The other spec levels map to integers between the slog levels. For example, \"notice\" is level 2 because it is between \"warning\" (slog value 4) and \"info\" (slog value 0). The `mcp` package defines consts for these levels. To log at the \"notice\" level, a handler would call `Log(ctx, mcp.LevelNotice, \"message\")`.\n\nA client that wishes to receive log messages must provide a handler:\n\n```go\ntype ClientOptions struct {\n  ...\n  LoggingMessageHandler func(context.Context, *ClientSession, *LoggingMessageParams)\n}\n```\n\n### Pagination\n\nServers initiate pagination for `ListTools`, `ListPrompts`, `ListResources`, and `ListResourceTemplates`, dictating the page size and providing a `NextCursor` field in the Result if more pages exist. The SDK implements keyset pagination, using the unique ID of the feature as the key for a stable sort order and encoding the cursor as an opaque string.\n\nFor server implementations, the page size for the list operation may be configured via the `ServerOptions.PageSize` field. PageSize must be a non-negative integer. If zero, a sensible default is used.\n\n```go\ntype ServerOptions {\n  ...\n  PageSize int\n}\n```\n\nClient requests for List methods include an optional Cursor field for pagination. Server responses for List methods include a `NextCursor` field if more pages exist.\n\nIn addition to the `List` methods, the SDK provides an iterator method for each list operation. This simplifies pagination for clients by automatically handling the underlying pagination logic. See [Iterator Methods](#iterator-methods) above.\n\n**Differences with mcp-go**: the PageSize configuration is set with a configuration field rather than a variadic option. Additionally, this design proposes pagination by default, as this is likely desirable for most servers\n\n# Governance and Community\n\nWhile the sections above propose an initial implementation of the Go SDK, MCP is evolving rapidly. SDKs need to keep pace, by implementing changes to the spec, fixing bugs, and accommodating new and emerging use-cases. This section proposes how the SDK project can be managed so that it can change safely and transparently.\n\nInitially, the Go SDK repository will be administered by the Go team and Anthropic, and they will be the Approvers (the set of people able to merge PRs to the SDK). The policies here are also intended to satisfy necessary constraints of the Go team's participation in the project.\n\nThe content in this section will also be included in a CONTRIBUTING.md file in the repo root.\n\n## Hosting, copyright, and license\n\nThe SDK will be hosted under github.com/modelcontextprotocol/go-sdk, MIT license, copyright \"Go SDK Authors\". Each Go file in the repository will have a standard copyright header. For example:\n\n```go\n// Copyright 2025 The Go MCP SDK Authors. All rights reserved.\n// Use of this source code is governed by an MIT-style\n// license that can be found in the LICENSE file.\n```\n\n## Issues and Contributing\n\nThe SDK will use its GitHub issue tracker for bug tracking, and pull requests for contributions.\n\nContributions to the SDK will be welcomed, and will be accepted provided they are high quality and consistent with the direction and philosophy of the SDK outlined above. An official SDK must be conservative in the changes it accepts, to defend against compatibility problems, security vulnerabilities, and churn. To avoid being declined, PRs should be associated with open issues, and those issues should either be labeled 'Help Wanted', or the PR author should ask on the issue before contributing.\n\n### Proposals\n\nA proposal is an issue that proposes a new API for the SDK, or a change to the signature or behavior of an existing API. Proposals will be labeled with the 'Proposal' label, and require an explicit approval before being accepted (applied through the 'Proposal-Accepted' label). Proposals will remain open for at least a week to allow discussion before being accepted or declined by an Approver.\n\nProposals that are straightforward and uncontroversial may be approved based on GitHub discussion. However, proposals that are deemed to be sufficiently unclear or complicated will be deferred to a regular steering meeting (see below).\n\nThis process is similar to the [Go proposal process](https://github.com/golang/proposal), but is necessarily lighter weight to accommodate the greater rate of change expected for the SDK.\n\n### Steering meetings\n\nOn a regular basis, we will host a virtual steering meeting to discuss outstanding proposals and other changes to the SDK. These 1hr meetings and their agenda will be announced in advance, and open to all to join. The meetings will be recorded, and recordings and meeting notes will be made available afterward.\n\nThis process is similar to the [Go Tools call](https://go.dev/wiki/golang-tools), though it is expected that meetings will at least initially occur on a more frequent basis (likely biweekly).\n\n### Discord\n\nDiscord (either the public or private Anthropic discord servers) should only be used for logistical coordination or answering questions. Design discussion and decisions should occur in GitHub issues or public steering meetings.\n\n### Antitrust considerations\n\nIt is important that the SDK avoids bias toward specific integration paths or providers. Therefore, the CONTRIBUTING.md file will include an antitrust policy that outlines terms and practices intended to avoid such bias, or the appearance thereof. (The details of this policy will be determined by Google and Anthropic lawyers).\n\n## Releases and Versioning\n\nThe SDK will consist of a single Go module, and will be released through versioned Git tags. Accordingly, it will follow semantic versioning.\n\nUp until the v1.0.0 release, the SDK may be unstable and may change in breaking ways. An initial v1.0.0 release will occur when the SDK is deemed by Approvers to be stable, production ready, and sufficiently complete (though some unimplemented features may remain). Subsequent to that release, new APIs will be added in minor versions, and breaking changes will require a v2 release of the module (and therefore should be avoided). All releases will have corresponding release notes in GitHub.\n\nIt is desirable that releases occur frequently, and that a v1.0.0 release is achieved as quickly as possible.\n\nIf feasible, the SDK will support all versions of the MCP spec. However, if breaking changes to the spec make this infeasible, preference will be given to the most recent version of the MCP spec.\n\n## Ongoing evaluation\n\nOn an ongoing basis, the administrators of the SDK will evaluate whether it is keeping pace with changes to the MCP spec and meeting its goals of openness and transparency. If it is not meeting these goals, either because it exceeds the bandwidth of its current Approvers, or because the processes here are inadequate, these processes will be re-evaluated. At this time, the Approvers set may be expanded to include additional community members, based on their history of strong contribution.\n"
  },
  {
    "path": "internal/mcp/example_progress_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"sync/atomic\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nvar nextProgressToken atomic.Int64\n\n// This middleware function adds a progress token to every outgoing request\n// from the client.\nfunc Example_progressMiddleware() {\n\tc := mcp.NewClient(\"test\", \"v1\", nil)\n\tc.AddSendingMiddleware(addProgressToken[*mcp.ClientSession])\n\t_ = c\n}\n\nfunc addProgressToken[S mcp.Session](h mcp.MethodHandler[S]) mcp.MethodHandler[S] {\n\treturn func(ctx context.Context, s S, method string, params mcp.Params) (result mcp.Result, err error) {\n\t\tparams.GetMeta().ProgressToken = nextProgressToken.Add(1)\n\t\treturn h(ctx, s, method, params)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/examples/hello/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nvar httpAddr = flag.String(\"http\", \"\", \"if set, use streamable HTTP at this address, instead of stdin/stdout\")\n\ntype HiArgs struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[HiArgs]) (*mcp.CallToolResultFor[struct{}], error) {\n\treturn &mcp.CallToolResultFor[struct{}]{\n\t\tContent: []*mcp.Content{\n\t\t\tmcp.NewTextContent(\"Hi \" + params.Name),\n\t\t},\n\t}, nil\n}\n\n// TODO(jba): it should be OK for args to be a pointer, but this fails in\n// jsonschema. Needs investigation.\nfunc PromptHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.GetPromptParams) (*mcp.GetPromptResult, error) {\n\treturn &mcp.GetPromptResult{\n\t\tDescription: \"Code review prompt\",\n\t\tMessages: []*mcp.PromptMessage{\n\t\t\t{Role: \"user\", Content: mcp.NewTextContent(\"Say hi to \" + params.Arguments[\"name\"])},\n\t\t},\n\t}, nil\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tserver := mcp.NewServer(\"greeter\", \"v0.0.1\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi, mcp.Input(\n\t\tmcp.Property(\"name\", mcp.Description(\"the name to say hi to\")),\n\t)))\n\tserver.AddPrompts(&mcp.ServerPrompt{\n\t\tPrompt:  &mcp.Prompt{Name: \"greet\"},\n\t\tHandler: PromptHi,\n\t})\n\tserver.AddResources(&mcp.ServerResource{\n\t\tResource: &mcp.Resource{\n\t\t\tName:     \"info\",\n\t\t\tMIMEType: \"text/plain\",\n\t\t\tURI:      \"embedded:info\",\n\t\t},\n\t\tHandler: handleEmbeddedResource,\n\t})\n\n\tif *httpAddr != \"\" {\n\t\thandler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server {\n\t\t\treturn server\n\t\t}, nil)\n\t\tlog.Printf(\"MCP handler listening at %s\", *httpAddr)\n\t\thttp.ListenAndServe(*httpAddr, handler)\n\t} else {\n\t\tt := mcp.NewLoggingTransport(mcp.NewStdioTransport(), os.Stderr)\n\t\tif err := server.Run(context.Background(), t); err != nil {\n\t\t\tlog.Printf(\"Server failed: %v\", err)\n\t\t}\n\t}\n}\n\nvar embeddedResources = map[string]string{\n\t\"info\": \"This is the hello example server.\",\n}\n\nfunc handleEmbeddedResource(_ context.Context, _ *mcp.ServerSession, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error) {\n\tu, err := url.Parse(params.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif u.Scheme != \"embedded\" {\n\t\treturn nil, fmt.Errorf(\"wrong scheme: %q\", u.Scheme)\n\t}\n\tkey := u.Opaque\n\ttext, ok := embeddedResources[key]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no embedded resource named %q\", key)\n\t}\n\treturn &mcp.ReadResourceResult{\n\t\tContents: []*mcp.ResourceContents{mcp.NewTextResourceContents(params.URI, \"text/plain\", text)},\n\t}, nil\n}\n"
  },
  {
    "path": "internal/mcp/examples/sse/main.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nvar httpAddr = flag.String(\"http\", \"\", \"use SSE HTTP at this address\")\n\ntype SayHiParams struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {\n\treturn &mcp.CallToolResultFor[any]{\n\t\tContent: []*mcp.Content{\n\t\t\tmcp.NewTextContent(\"Hi \" + params.Name),\n\t\t},\n\t}, nil\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tif httpAddr == nil || *httpAddr == \"\" {\n\t\tlog.Fatal(\"http address not set\")\n\t}\n\n\tserver1 := mcp.NewServer(\"greeter1\", \"v0.0.1\", nil)\n\tserver1.AddTools(mcp.NewServerTool(\"greet1\", \"say hi\", SayHi))\n\n\tserver2 := mcp.NewServer(\"greeter2\", \"v0.0.1\", nil)\n\tserver2.AddTools(mcp.NewServerTool(\"greet2\", \"say hello\", SayHi))\n\n\tlog.Printf(\"MCP servers serving at %s\\n\", *httpAddr)\n\thandler := mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {\n\t\turl := request.URL.Path\n\t\tlog.Printf(\"Handling request for URL %s\\n\", url)\n\t\tswitch url {\n\t\tcase \"/greeter1\":\n\t\t\treturn server1\n\t\tcase \"/greeter2\":\n\t\t\treturn server2\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t})\n\thttp.ListenAndServe(*httpAddr, handler)\n}\n"
  },
  {
    "path": "internal/mcp/features.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"iter\"\n\t\"maps\"\n\t\"slices\"\n)\n\n// This file contains implementations that are common to all features.\n// A feature is an item provided to a peer. In the 2025-03-26 spec,\n// the features are prompt, tool, resource and root.\n\n// A featureSet is a collection of features of type T.\n// Every feature has a unique ID, and the spec never mentions\n// an ordering for the List calls, so what it calls a \"list\" is actually a set.\n// TODO: switch to an ordered map\ntype featureSet[T any] struct {\n\tuniqueID   func(T) string\n\tfeatures   map[string]T\n\tsortedKeys []string // lazily computed; nil after add or remove\n}\n\n// newFeatureSet creates a new featureSet for features of type T.\n// The argument function should return the unique ID for a single feature.\nfunc newFeatureSet[T any](uniqueIDFunc func(T) string) *featureSet[T] {\n\treturn &featureSet[T]{\n\t\tuniqueID: uniqueIDFunc,\n\t\tfeatures: make(map[string]T),\n\t}\n}\n\n// add adds each feature to the set if it is not present,\n// or replaces an existing feature.\nfunc (s *featureSet[T]) add(fs ...T) {\n\tfor _, f := range fs {\n\t\ts.features[s.uniqueID(f)] = f\n\t}\n\ts.sortedKeys = nil\n}\n\n// remove removes all features with the given uids from the set if present,\n// and returns whether any were removed.\n// It is not an error to remove a nonexistent feature.\nfunc (s *featureSet[T]) remove(uids ...string) bool {\n\tchanged := false\n\tfor _, uid := range uids {\n\t\tif _, ok := s.features[uid]; ok {\n\t\t\tchanged = true\n\t\t\tdelete(s.features, uid)\n\t\t}\n\t}\n\tif changed {\n\t\ts.sortedKeys = nil\n\t}\n\treturn changed\n}\n\n// get returns the feature with the given uid.\n// If there is none, it returns zero, false.\nfunc (s *featureSet[T]) get(uid string) (T, bool) {\n\tt, ok := s.features[uid]\n\treturn t, ok\n}\n\n// all returns an iterator over of all the features in the set\n// sorted by unique ID.\nfunc (s *featureSet[T]) all() iter.Seq[T] {\n\ts.sortKeys()\n\treturn func(yield func(T) bool) {\n\t\ts.yieldFrom(0, yield)\n\t}\n}\n\n// above returns an iterator over features in the set whose unique IDs are\n// greater than `uid`, in ascending ID order.\nfunc (s *featureSet[T]) above(uid string) iter.Seq[T] {\n\ts.sortKeys()\n\tindex, found := slices.BinarySearch(s.sortedKeys, uid)\n\tif found {\n\t\tindex++\n\t}\n\treturn func(yield func(T) bool) {\n\t\ts.yieldFrom(index, yield)\n\t}\n}\n\n// sortKeys is a helper that maintains a sorted list of feature IDs. It\n// computes this list lazily upon its first call after a modification, or\n// if it's nil.\nfunc (s *featureSet[T]) sortKeys() {\n\tif s.sortedKeys != nil {\n\t\treturn\n\t}\n\ts.sortedKeys = slices.Sorted(maps.Keys(s.features))\n}\n\n// yieldFrom is a helper that iterates over the features in the set,\n// starting at the given index, and calls the yield function for each one.\nfunc (s *featureSet[T]) yieldFrom(index int, yield func(T) bool) {\n\tfor i := index; i < len(s.sortedKeys); i++ {\n\t\tif !yield(s.features[s.sortedKeys[i]]) {\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/features_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\ntype SayHiParams struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[SayHiParams]) (*CallToolResultFor[any], error) {\n\treturn &CallToolResultFor[any]{\n\t\tContent: []*Content{\n\t\t\tNewTextContent(\"Hi \" + params.Name),\n\t\t},\n\t}, nil\n}\n\nfunc TestFeatureSetOrder(t *testing.T) {\n\ttoolA := NewServerTool(\"apple\", \"apple tool\", SayHi).Tool\n\ttoolB := NewServerTool(\"banana\", \"banana tool\", SayHi).Tool\n\ttoolC := NewServerTool(\"cherry\", \"cherry tool\", SayHi).Tool\n\n\ttestCases := []struct {\n\t\ttools []*Tool\n\t\twant  []*Tool\n\t}{\n\t\t{[]*Tool{toolA, toolB, toolC}, []*Tool{toolA, toolB, toolC}},\n\t\t{[]*Tool{toolB, toolC, toolA}, []*Tool{toolA, toolB, toolC}},\n\t\t{[]*Tool{toolA, toolC}, []*Tool{toolA, toolC}},\n\t\t{[]*Tool{toolA, toolA, toolA}, []*Tool{toolA}},\n\t\t{[]*Tool{}, nil},\n\t}\n\tfor _, tc := range testCases {\n\t\tfs := newFeatureSet(func(t *Tool) string { return t.Name })\n\t\tfs.add(tc.tools...)\n\t\tgot := slices.Collect(fs.all())\n\t\tif diff := cmp.Diff(got, tc.want, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\tt.Errorf(\"expected %v, got %v, (-want +got):\\n%s\", tc.want, got, diff)\n\t\t}\n\t}\n}\n\nfunc TestFeatureSetAbove(t *testing.T) {\n\ttoolA := NewServerTool(\"apple\", \"apple tool\", SayHi).Tool\n\ttoolB := NewServerTool(\"banana\", \"banana tool\", SayHi).Tool\n\ttoolC := NewServerTool(\"cherry\", \"cherry tool\", SayHi).Tool\n\n\ttestCases := []struct {\n\t\ttools []*Tool\n\t\tabove string\n\t\twant  []*Tool\n\t}{\n\t\t{[]*Tool{toolA, toolB, toolC}, \"apple\", []*Tool{toolB, toolC}},\n\t\t{[]*Tool{toolA, toolB, toolC}, \"banana\", []*Tool{toolC}},\n\t\t{[]*Tool{toolA, toolB, toolC}, \"cherry\", nil},\n\t}\n\tfor _, tc := range testCases {\n\t\tfs := newFeatureSet(func(t *Tool) string { return t.Name })\n\t\tfs.add(tc.tools...)\n\t\tgot := slices.Collect(fs.above(tc.above))\n\t\tif diff := cmp.Diff(got, tc.want, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\tt.Errorf(\"expected %v, got %v, (-want +got):\\n%s\", tc.want, got, diff)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/generate.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// This script generates protocol definitions in protocol.go from the MCP spec.\n//\n// Only the set of declarations configured by the [declarations] value are\n// generated.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/format\"\n\t\"io\"\n\t\"log\"\n\t\"maps\"\n\t\"net/http\"\n\t\"os\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\nvar schemaFile = flag.String(\"schema_file\", \"\", \"if set, use this file as the persistent schema file\")\n\n// A typeConfig defines a rewrite to perform to a (possibly nested) struct\n// field. In some cases, we may want to use an external type for the nested\n// struct field. In others, we may want to extract the type definition to a\n// name.\ntype typeConfig struct {\n\tName       string      // declaration name for the type\n\tTypeParams [][2]string // formatted type parameter list ({name, constraint}), if any\n\tSubstitute string      // type definition to substitute\n\tFields     config      // individual field configuration, or nil\n}\n\ntype config map[string]*typeConfig\n\n// declarations configures the set of declarations to write.\n//\n// Top level declarations are created unless configured with Name==\"-\",\n// in which case they are discarded, though their fields may be\n// extracted to types if they have a nested field configuration.\n// If Name == \"\", the map key is used as the type name.\nvar declarations = config{\n\t\"Annotations\": {},\n\t\"CallToolRequest\": {\n\t\tName: \"-\",\n\t\tFields: config{\n\t\t\t\"Params\": {\n\t\t\t\tName: \"CallToolParams\",\n\t\t\t\tFields: config{\n\t\t\t\t\t\"Arguments\": {Substitute: \"any\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t\"CallToolResult\": {},\n\t\"CancelledNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"CancelledParams\"}},\n\t},\n\t\"ClientCapabilities\": {\n\t\tFields: config{\"Sampling\": {Name: \"SamplingCapabilities\"}},\n\t},\n\t\"CreateMessageRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"CreateMessageParams\"}},\n\t},\n\t\"CreateMessageResult\": {},\n\t\"GetPromptRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"GetPromptParams\"}},\n\t},\n\t\"GetPromptResult\": {},\n\t\"Implementation\":  {Name: \"implementation\"},\n\t\"InitializeRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"InitializeParams\"}},\n\t},\n\t\"InitializeResult\": {Name: \"InitializeResult\"},\n\t\"InitializedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"InitializedParams\"}},\n\t},\n\t\"ListPromptsRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ListPromptsParams\"}},\n\t},\n\t\"ListPromptsResult\": {},\n\t\"ListResourcesRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ListResourcesParams\"}},\n\t},\n\t\"ListResourcesResult\": {},\n\t\"ListResourceTemplatesRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ListResourceTemplatesParams\"}},\n\t},\n\t\"ListResourceTemplatesResult\": {},\n\t\"ListRootsRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ListRootsParams\"}},\n\t},\n\t\"ListRootsResult\": {},\n\t\"ListToolsRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ListToolsParams\"}},\n\t},\n\t\"ListToolsResult\":     {},\n\t\"loggingCapabilities\": {Substitute: \"struct{}\"},\n\t\"LoggingLevel\":        {},\n\t\"LoggingMessageNotification\": {\n\t\tName: \"-\",\n\t\tFields: config{\n\t\t\t\"Params\": {\n\t\t\t\tName:   \"LoggingMessageParams\",\n\t\t\t\tFields: config{\"Data\": {Substitute: \"any\"}},\n\t\t\t},\n\t\t},\n\t},\n\t\"ModelHint\":        {},\n\t\"ModelPreferences\": {},\n\t\"PingRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"PingParams\"}},\n\t},\n\t\"Prompt\":         {},\n\t\"PromptMessage\":  {},\n\t\"PromptArgument\": {},\n\t\"PromptListChangedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"PromptListChangedParams\"}},\n\t},\n\t\"ProgressNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ProgressNotificationParams\"}},\n\t},\n\t\"ProgressToken\": {Name: \"-\", Substitute: \"any\"}, // null|number|string\n\t\"RequestId\":     {Name: \"-\", Substitute: \"any\"}, // null|number|string\n\t\"ReadResourceRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ReadResourceParams\"}},\n\t},\n\t\"ReadResourceResult\": {\n\t\tFields: config{\"Contents\": {Substitute: \"[]*ResourceContents\"}},\n\t},\n\t\"Resource\": {},\n\t\"ResourceListChangedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ResourceListChangedParams\"}},\n\t},\n\t\"ResourceTemplate\": {},\n\t\"ResourceTemplateListChangedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ResourceTemplateListChangedParams\"}},\n\t},\n\t\"Role\": {},\n\t\"Root\": {},\n\t\"RootsListChangedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"RootsListChangedParams\"}},\n\t},\n\n\t\"SamplingCapabilities\": {Substitute: \"struct{}\"},\n\t\"SamplingMessage\":      {},\n\t\"ServerCapabilities\": {\n\t\tName: \"serverCapabilities\",\n\t\tFields: config{\n\t\t\t\"Prompts\":   {Name: \"promptCapabilities\"},\n\t\t\t\"Resources\": {Name: \"resourceCapabilities\"},\n\t\t\t\"Tools\":     {Name: \"toolCapabilities\"},\n\t\t\t\"Logging\":   {Name: \"loggingCapabilities\"},\n\t\t},\n\t},\n\t\"SetLevelRequest\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"SetLevelParams\"}},\n\t},\n\t\"Tool\": {\n\t\tFields: config{\"InputSchema\": {Substitute: \"*jsonschema.Schema\"}},\n\t},\n\t\"ToolAnnotations\": {},\n\t\"ToolListChangedNotification\": {\n\t\tName:   \"-\",\n\t\tFields: config{\"Params\": {Name: \"ToolListChangedParams\"}},\n\t},\n}\n\nfunc main() {\n\tflag.Parse()\n\n\t// Load and unmarshal the schema.\n\tdata, err := loadSchema(*schemaFile)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tschema := new(jsonschema.Schema)\n\tif err := json.Unmarshal(data, &schema); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// Resolve the schema so we have the referents of all the Refs.\n\tif _, err := schema.Resolve(nil); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Collect named types. Since we may create new type definitions while\n\t// writing types, we collect definitions and concatenate them later. This\n\t// also allows us to sort.\n\tnamed := make(map[string]*bytes.Buffer)\n\tfor name, def := range util.Sorted(schema.Definitions) {\n\t\tconfig := declarations[name]\n\t\tif config == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := writeDecl(name, *config, def, named); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\tbuf := new(bytes.Buffer)\n\tfmt.Fprintf(buf, `\n// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage mcp\n\nimport (\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n`)\n\n\t// Write out types.\n\tfor _, b := range util.Sorted(named) {\n\t\tfmt.Fprintln(buf)\n\t\tfmt.Fprint(buf, b.String())\n\t}\n\t// Write out method names.\n\tfmt.Fprintln(buf, `const (`)\n\tfor _, name := range slices.Sorted(maps.Keys(schema.Definitions)) {\n\t\tprefix := \"method\"\n\t\tmethod, found := strings.CutSuffix(name, \"Request\")\n\t\tif !found {\n\t\t\tprefix = \"notification\"\n\t\t\tmethod, found = strings.CutSuffix(name, \"Notification\")\n\t\t}\n\t\tif found {\n\t\t\tif ms, ok := schema.Definitions[name].Properties[\"method\"]; ok {\n\t\t\t\tif c := ms.Const; c != nil {\n\t\t\t\t\tfmt.Fprintf(buf, \"%s%s = %q\\n\", prefix, method, *c)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfmt.Fprintln(buf, `)`)\n\n\tformatted, err := format.Source(buf.Bytes())\n\tif err != nil {\n\t\tlog.Println(buf.String())\n\t\tlog.Fatalf(\"failed to format: %v\", err)\n\t}\n\tif err := os.WriteFile(\"protocol.go\", formatted, 0666); err != nil {\n\t\tlog.Fatalf(\"failed to write protocol.go: %v\", err)\n\t}\n}\n\nfunc loadSchema(schemaFile string) (data []byte, err error) {\n\tconst schemaURL = \"https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/refs/heads/main/schema/2025-03-26/schema.json\"\n\n\tif schemaFile != \"\" {\n\t\tdata, err = os.ReadFile(schemaFile)\n\t\tif os.IsNotExist(err) {\n\t\t\tdata = nil\n\t\t} else if err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading schema file %q: %v\", schemaFile, err)\n\t\t}\n\t}\n\tif data == nil {\n\t\tresp, err := http.Get(schemaURL)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"downloading schema: %v\", err)\n\t\t}\n\t\tdefer resp.Body.Close()\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\treturn nil, fmt.Errorf(\"downloading schema: %v\", resp.Status)\n\t\t}\n\t\tdata, err = io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading schema body: %v\", err)\n\t\t}\n\t\tif schemaFile != \"\" {\n\t\t\tif err := os.WriteFile(schemaFile, data, 0666); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"persisting schema: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\treturn data, nil\n}\n\n// Suffixes of type names with a meta field.\nvar metaSuffixes = []string{\"Params\", \"ParamsFor\", \"Result\", \"ResultFor\"}\n\nfunc writeDecl(configName string, config typeConfig, def *jsonschema.Schema, named map[string]*bytes.Buffer) error {\n\tvar w io.Writer = io.Discard\n\tvar typeName string\n\tif typeName = config.Name; typeName != \"-\" {\n\t\tif typeName == \"\" {\n\t\t\ttypeName = configName\n\t\t}\n\t\tif _, ok := named[typeName]; ok {\n\t\t\treturn nil\n\t\t}\n\t\t// The JSON schema does not accurately represent the source of truth, which is typescript.\n\t\t// Every Params and Result type should have a _meta property.\n\t\t// Also, those with a progress token will turn into a struct; we want the progress token to\n\t\t// be a map item. So replace all metas.\n\t\tfor _, s := range metaSuffixes {\n\t\t\tif strings.HasSuffix(typeName, s) {\n\t\t\t\tdef.Properties[\"_meta\"] = metaSchema\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tbuf := new(bytes.Buffer)\n\t\tw = buf\n\t\tnamed[typeName] = buf\n\t\tif def.Description != \"\" {\n\t\t\tfmt.Fprintf(buf, \"%s\\n\", toComment(def.Description))\n\t\t}\n\t\ttypeParams := new(strings.Builder)\n\t\tif len(config.TypeParams) > 0 {\n\t\t\ttypeParams.WriteByte('[')\n\t\t\tfor i, p := range config.TypeParams {\n\t\t\t\tif i > 0 {\n\t\t\t\t\ttypeParams.WriteString(\", \")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(typeParams, \"%s %s\", p[0], p[1])\n\t\t\t}\n\t\t\ttypeParams.WriteByte(']')\n\t\t}\n\t\tfmt.Fprintf(buf, \"type %s%s \", typeName, typeParams)\n\t}\n\tif err := writeType(w, &config, def, named); err != nil {\n\t\treturn err // Better error here?\n\t}\n\tfmt.Fprintf(w, \"\\n\")\n\n\t// Any decl with a _meta field gets a GetMeta method.\n\tif _, ok := def.Properties[\"_meta\"]; ok {\n\t\ttargs := new(strings.Builder)\n\t\tif len(config.TypeParams) > 0 {\n\t\t\ttargs.WriteByte('[')\n\t\t\tfor i, p := range config.TypeParams {\n\t\t\t\tif i > 0 {\n\t\t\t\t\ttargs.WriteString(\", \")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(targs, \"%s\", p[0])\n\t\t\t}\n\t\t\ttargs.WriteByte(']')\n\t\t}\n\t\tfmt.Fprintf(w, \"\\nfunc (x *%s%s) GetMeta() *Meta { return &x.Meta }\", typeName, targs)\n\t}\n\n\tif _, ok := def.Properties[\"cursor\"]; ok {\n\t\tfmt.Fprintf(w, \"\\nfunc (x *%s) cursorPtr() *string { return &x.Cursor }\", typeName)\n\t}\n\tif _, ok := def.Properties[\"nextCursor\"]; ok {\n\t\tfmt.Fprintf(w, \"\\nfunc (x *%s) nextCursorPtr() *string { return &x.NextCursor }\", typeName)\n\t}\n\n\t// Some types have generic counterparts.\n\tvar typeArg, substField string\n\tswitch typeName {\n\tcase \"CallToolParams\":\n\t\ttypeName = \"CallToolParamsFor\"\n\t\ttypeArg = \"In\"\n\t\tsubstField = \"Arguments\"\n\tcase \"CallToolResult\":\n\t\ttypeName = \"CallToolResultFor\"\n\t\ttypeArg = \"Out\"\n\t\tsubstField = \"StructuredContent\"\n\t}\n\tif typeArg != \"\" {\n\t\tfmt.Fprintf(w, \"\\n\\ntype %s[%s any]\", typeName, typeArg)\n\t\tif config.Fields != nil {\n\t\t\tconfig.Fields[substField].Substitute = typeArg\n\t\t}\n\t\tif err := writeType(w, &config, def, named); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Fprintf(w, \"\\nfunc (x *%s[%s]) GetMeta() *Meta {return &x.Meta}\", typeName, typeArg)\n\t}\n\treturn nil\n}\n\n// writeType writes the type definition to the given writer.\n//\n// If path is non-empty, it is the path to the field using this type, for the\n// purpose of detecting field rewrites (see [fieldRewrite]).\n//\n// named is the in-progress collection of type definitions. New named types may\n// be added during writeType, if they are extracted from inner fields.\nfunc writeType(w io.Writer, config *typeConfig, def *jsonschema.Schema, named map[string]*bytes.Buffer) error {\n\t// Use type names for Named types.\n\tname, resolved := deref(def)\n\tif name != \"\" {\n\t\t// TODO: this check is not quite right: we should really panic if the\n\t\t// definition is missing, *but only if w is not io.Discard*. That's not a\n\t\t// great API: see if we can do something more explicit than io.Discard.\n\t\tif cfg, ok := declarations[name]; ok {\n\t\t\tif cfg.Name == \"-\" && cfg.Substitute == \"\" {\n\t\t\t\tpanic(fmt.Sprintf(\"referenced type %q cannot be referred to (no name or substitution)\", name))\n\t\t\t}\n\t\t\tif cfg.Substitute != \"\" {\n\t\t\t\tname = cfg.Substitute\n\t\t\t} else if cfg.Name != \"\" {\n\t\t\t\tname = cfg.Name\n\t\t\t}\n\t\t\tif isStruct(resolved) {\n\t\t\t\tw.Write([]byte{'*'})\n\t\t\t}\n\t\t}\n\t\tw.Write([]byte(name))\n\t\treturn nil\n\t}\n\n\t// For types that explicitly allow additional properties, we can either\n\t// unmarshal them into a map[string]any, or delay unmarshalling with\n\t// json.RawMessage. We use any.\n\tif def.Type == \"object\" && canHaveAdditionalProperties(def) && def.Properties == nil {\n\t\tw.Write([]byte(\"map[string]\"))\n\t\treturn writeType(w, nil, def.AdditionalProperties, named)\n\t}\n\n\tif def.Type == \"\" {\n\t\t// special case: recognize Content\n\t\tif slices.ContainsFunc(def.AnyOf, func(s *jsonschema.Schema) bool {\n\t\t\treturn s.Ref == \"#/definitions/TextContent\"\n\t\t}) {\n\t\t\tfmt.Fprintf(w, \"*Content\")\n\t\t} else {\n\t\t\t// E.g. union types.\n\t\t\tfmt.Fprintf(w, \"any\")\n\t\t}\n\t} else {\n\t\tswitch def.Type {\n\t\tcase \"array\":\n\t\t\tfmt.Fprintf(w, \"[]\")\n\t\t\treturn writeType(w, nil, def.Items, named)\n\n\t\tcase \"boolean\":\n\t\t\tfmt.Fprintf(w, \"bool\")\n\n\t\tcase \"integer\":\n\t\t\tfmt.Fprintf(w, \"int64\")\n\n\t\t// not handled: \"null\"\n\n\t\tcase \"number\":\n\t\t\t// We could use json.Number here; use float64 for simplicity.\n\t\t\tfmt.Fprintf(w, \"float64\")\n\n\t\tcase \"object\":\n\t\t\tfmt.Fprintf(w, \"struct {\\n\")\n\t\t\tfor name, fieldDef := range util.Sorted(def.Properties) {\n\t\t\t\tif fieldDef.Description != \"\" {\n\t\t\t\t\tfmt.Fprintf(w, \"%s\\n\", toComment(fieldDef.Description))\n\t\t\t\t}\n\t\t\t\tif name == \"_meta\" {\n\t\t\t\t\tfmt.Fprintln(w, \"\\tMeta Meta `json:\\\"_meta,omitempty\\\"`\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\texport := exportName(name)\n\t\t\t\tfmt.Fprintf(w, \"\\t%s \", export)\n\n\t\t\t\trequired := slices.Contains(def.Required, name)\n\n\t\t\t\t// If the field is a struct type, indirect with a\n\t\t\t\t// pointer so that it can be empty as defined by encoding/json.\n\t\t\t\t// This also future-proofs against the struct getting large.\n\t\t\t\tfieldTypeSchema := fieldDef\n\t\t\t\t// If the schema is a reference, dereference it.\n\t\t\t\tif _, rs := deref(fieldDef); rs != nil {\n\t\t\t\t\tfieldTypeSchema = rs\n\t\t\t\t}\n\t\t\t\tneedPointer := isStruct(fieldTypeSchema)\n\t\t\t\t// Special case: there are no sampling or logging capabilities defined,\n\t\t\t\t// but we want them to be structs for future expansion.\n\t\t\t\tif !needPointer && (name == \"sampling\" || name == \"logging\") {\n\t\t\t\t\tneedPointer = true\n\t\t\t\t}\n\t\t\t\tif config != nil && config.Fields[export] != nil {\n\t\t\t\t\tr := config.Fields[export]\n\t\t\t\t\tif r.Substitute != \"\" {\n\t\t\t\t\t\tfmt.Fprintf(w, r.Substitute)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tassert(r.Name != \"-\", \"missing ExtractTo\")\n\t\t\t\t\t\ttypename := export\n\t\t\t\t\t\tif r.Name != \"\" {\n\t\t\t\t\t\t\ttypename = r.Name\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif err := writeDecl(typename, *r, fieldDef, named); err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif needPointer {\n\t\t\t\t\t\t\tfmt.Fprintf(w, \"*\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfmt.Fprintf(w, typename)\n\t\t\t\t\t}\n\t\t\t\t} else if err := writeType(w, nil, fieldDef, named); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to write type for field %s: %v\", export, err)\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(w, \" `json:\\\"%s\", name)\n\t\t\t\tif !required {\n\t\t\t\t\tfmt.Fprint(w, \",omitempty\")\n\t\t\t\t}\n\t\t\t\tfmt.Fprint(w, \"\\\"`\\n\")\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"}\")\n\n\t\tcase \"string\":\n\t\t\tfmt.Fprintf(w, \"string\")\n\n\t\tdefault:\n\t\t\tfmt.Fprintf(w, \"any\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// toComment converts a JSON schema description to a Go comment.\nfunc toComment(description string) string {\n\tvar (\n\t\tbuf     strings.Builder\n\t\tlineBuf strings.Builder\n\t)\n\tconst wrapAt = 80\n\tfor line := range strings.SplitSeq(description, \"\\n\") {\n\t\t// Start a new paragraph, if the current is nonempty.\n\t\tif len(line) == 0 && lineBuf.Len() > 0 {\n\t\t\tbuf.WriteString(lineBuf.String())\n\t\t\tlineBuf.Reset()\n\t\t\tbuf.WriteString(\"\\n//\\n\")\n\t\t\tcontinue\n\t\t}\n\t\t// Otherwise, fill in the current paragraph.\n\t\tfor field := range strings.FieldsSeq(line) {\n\t\t\tif lineBuf.Len() > 0 && lineBuf.Len()+len(\" \")+len(field) > wrapAt {\n\t\t\t\tbuf.WriteString(lineBuf.String())\n\t\t\t\tbuf.WriteRune('\\n')\n\t\t\t\tlineBuf.Reset()\n\t\t\t}\n\t\t\tif lineBuf.Len() == 0 {\n\t\t\t\tlineBuf.WriteString(\"//\")\n\t\t\t}\n\t\t\tlineBuf.WriteString(\" \")\n\t\t\tlineBuf.WriteString(field)\n\t\t}\n\t}\n\tif lineBuf.Len() > 0 {\n\t\tbuf.WriteString(lineBuf.String())\n\t}\n\treturn strings.TrimRight(buf.String(), \"\\n\")\n}\n\n// The MCP spec improperly uses the absence of the additionalProperties keyword to\n// mean that additional properties are not allowed. In fact, it means just the opposite\n// (https://json-schema.org/draft-07/draft-handrews-json-schema-validation-01#rfc.section.6.5.6).\n// If the MCP spec wants to allow additional properties, it will write \"true\" or\n// an object explicitly.\nfunc canHaveAdditionalProperties(s *jsonschema.Schema) bool {\n\tap := s.AdditionalProperties\n\treturn ap != nil && !reflect.DeepEqual(ap, &jsonschema.Schema{Not: &jsonschema.Schema{}})\n}\n\n// exportName returns an exported name for a Go symbol, based on the given name\n// in the JSON schema, removing leading underscores and capitalizing.\n// It also rewrites initialisms.\nfunc exportName(s string) string {\n\tif strings.HasPrefix(s, \"_\") {\n\t\ts = s[1:]\n\t}\n\ts = strings.ToUpper(s[:1]) + s[1:]\n\t// Replace an initialism if it is its own \"word\": see the init function below for\n\t// a definition.\n\t// There is probably a clever way to write this whole thing with one regexp and\n\t// a Replace method, but it would be quite obscure.\n\t// This doesn't have to be fast, because the first match will rarely succeed.\n\tfor ism, re := range initialisms {\n\t\treplacement := strings.ToUpper(ism)\n\t\t// Find the index of one match at a time, and replace. (We can't find all\n\t\t// at once, because the replacement will change the indices.)\n\t\tfor {\n\t\t\tif loc := re.FindStringIndex(s); loc != nil {\n\t\t\t\t// Don't replace the rune after the initialism, if any.\n\t\t\t\tend := loc[1]\n\t\t\t\tif end < len(s) {\n\t\t\t\t\tend--\n\t\t\t\t}\n\t\t\t\ts = s[:loc[0]] + replacement + s[end:]\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn s\n}\n\n// deref dereferences s.Ref.\n// If s.Ref refers to a schema in the Definitions section, deref\n// returns the definition name and the associated schema.\n// Otherwise, deref returns \"\", nil.\nfunc deref(s *jsonschema.Schema) (name string, _ *jsonschema.Schema) {\n\tname, ok := strings.CutPrefix(s.Ref, \"#/definitions/\")\n\tif !ok {\n\t\treturn \"\", nil\n\t}\n\treturn name, s.ResolvedRef()\n}\n\n// isStruct reports whether s should be translated to a struct.\nfunc isStruct(s *jsonschema.Schema) bool {\n\treturn s.Type == \"object\" && s.Properties != nil && !canHaveAdditionalProperties(s)\n}\n\n// The schema for \"_meta\".\n// We only need the description: the rest is a special case.\nvar metaSchema = &jsonschema.Schema{\n\tDescription: \"This property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.\",\n}\n\n// schemaJSON returns the JSON for s.\n// For debugging.\nfunc schemaJSON(s *jsonschema.Schema) string {\n\tdata, err := json.Marshal(s)\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"<jsonschema.Schema:%v>\", err)\n\t}\n\treturn string(data)\n}\n\n// Map from initialism to the regexp that matches it.\nvar initialisms = map[string]*regexp.Regexp{\n\t\"Id\":   nil,\n\t\"Url\":  nil,\n\t\"Uri\":  nil,\n\t\"Mime\": nil,\n}\n\nfunc init() {\n\tfor ism := range initialisms {\n\t\t// Match ism if it is at the end, or followed by an uppercase letter or a number.\n\t\tinitialisms[ism] = regexp.MustCompile(ism + `($|[A-Z0-9])`)\n\t}\n}\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/internal/oauthex/oauth2.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package oauthex implements extensions to OAuth2.\npackage oauthex\n"
  },
  {
    "path": "internal/mcp/internal/oauthex/oauth2_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage oauthex\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSplitChallenges(t *testing.T) {\n\ttests := []struct {\n\t\tname  string\n\t\tinput string\n\t\twant  []string\n\t}{\n\t\t{\n\t\t\tname:  \"single challenge no params\",\n\t\t\tinput: `Basic`,\n\t\t\twant:  []string{`Basic`},\n\t\t},\n\t\t{\n\t\t\tname:  \"single challenge with params\",\n\t\t\tinput: `Bearer realm=\"example.com\", error=\"invalid_token\"`,\n\t\t\twant:  []string{`Bearer realm=\"example.com\", error=\"invalid_token\"`},\n\t\t},\n\t\t{\n\t\t\tname:  \"single challenge with comma in quoted string\",\n\t\t\tinput: `Bearer realm=\"example, with comma\"`,\n\t\t\twant:  []string{`Bearer realm=\"example, with comma\"`},\n\t\t},\n\t\t{\n\t\t\tname:  \"two challenges\",\n\t\t\tinput: `Basic, Bearer realm=\"example\"`,\n\t\t\twant:  []string{`Basic`, ` Bearer realm=\"example\"`},\n\t\t},\n\t\t{\n\t\t\tname:  \"multiple challenges complex\",\n\t\t\tinput: `Newauth realm=\"apps\", Basic, Bearer realm=\"example.com\", error=\"invalid_token\"`,\n\t\t\twant:  []string{`Newauth realm=\"apps\"`, ` Basic`, ` Bearer realm=\"example.com\", error=\"invalid_token\"`},\n\t\t},\n\t\t{\n\t\t\tname:  \"challenge with escaped quote\",\n\t\t\tinput: `Bearer realm=\"example \\\"quoted\\\"\"`,\n\t\t\twant:  []string{`Bearer realm=\"example \\\"quoted\\\"\"`},\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input\",\n\t\t\tinput: \"\",\n\t\t\twant:  []string{\"\"},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := splitChallenges(tt.input)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"splitChallenges() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSplitChallengesError(t *testing.T) {\n\tif _, err := splitChallenges(`\"Bearer\"`); err == nil {\n\t\tt.Fatal(\"got nil, want error\")\n\t}\n}\n\nfunc TestParseSingleChallenge(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tinput   string\n\t\twant    challenge\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname:  \"scheme only\",\n\t\t\tinput: \"Basic\",\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"basic\",\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"scheme with one quoted param\",\n\t\t\tinput: `Bearer realm=\"example.com\"`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\"realm\": \"example.com\"},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"scheme with one unquoted param\",\n\t\t\tinput: `Bearer realm=example.com`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\"realm\": \"example.com\"},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"scheme with multiple params\",\n\t\t\tinput: `Bearer realm=\"example\", error=\"invalid_token\", error_description=\"The token expired\"`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\n\t\t\t\t\t\"realm\":             \"example\",\n\t\t\t\t\t\"error\":             \"invalid_token\",\n\t\t\t\t\t\"error_description\": \"The token expired\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"scheme with multiple unquoted params\",\n\t\t\tinput: `Bearer realm=example, error=invalid_token, error_description=The token expired`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\n\t\t\t\t\t\"realm\":             \"example\",\n\t\t\t\t\t\"error\":             \"invalid_token\",\n\t\t\t\t\t\"error_description\": \"The token expired\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"case-insensitive scheme and keys\",\n\t\t\tinput: `BEARER ReAlM=\"example\"`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\"realm\": \"example\"},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"param with escaped quote\",\n\t\t\tinput: `Bearer realm=\"example \\\"foo\\\" bar\"`,\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\"realm\": `example \"foo\" bar`},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:  \"param without quotes (token)\",\n\t\t\tinput: \"Bearer realm=example.com\",\n\t\t\twant: challenge{\n\t\t\t\tScheme: \"bearer\",\n\t\t\t\tParams: map[string]string{\"realm\": \"example.com\"},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"malformed param - no value\",\n\t\t\tinput:   \"Bearer realm=\",\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:    \"malformed param - unterminated quote\",\n\t\t\tinput:   `Bearer realm=\"example`,\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:    \"malformed param - missing comma\",\n\t\t\tinput:   `Bearer realm=\"a\" error=\"b\"`,\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:    \"malformed param - initial equal\",\n\t\t\tinput:   `Bearer =\"a\"`,\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:    \"empty input\",\n\t\t\tinput:   \"\",\n\t\t\twantErr: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := parseSingleChallenge(tt.input)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"parseSingleChallenge() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"parseSingleChallenge() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestGetProtectedResourceMetadata(t *testing.T) {\n\tctx := context.Background()\n\tt.Run(\"FromHeader\", func(t *testing.T) {\n\t\th := &fakeResourceHandler{serveWWWAuthenticate: true}\n\t\tserver := httptest.NewTLSServer(h)\n\t\th.installHandlers(server.URL)\n\t\tclient := server.Client()\n\t\tres, err := client.Get(server.URL + \"/resource\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res.StatusCode != http.StatusUnauthorized {\n\t\t\tt.Fatal(\"want unauth\")\n\t\t}\n\t\tprm, err := GetProtectedResourceMetadataFromHeader(ctx, res.Header, client)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif prm == nil {\n\t\t\tt.Fatal(\"nil prm\")\n\t\t}\n\t})\n\tt.Run(\"FromID\", func(t *testing.T) {\n\t\th := &fakeResourceHandler{serveWWWAuthenticate: false}\n\t\tserver := httptest.NewTLSServer(h)\n\t\th.installHandlers(server.URL)\n\t\tclient := server.Client()\n\t\tprm, err := GetProtectedResourceMetadataFromID(ctx, server.URL, client)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif prm == nil {\n\t\t\tt.Fatal(\"nil prm\")\n\t\t}\n\t})\n}\n\ntype fakeResourceHandler struct {\n\thttp.ServeMux\n\tserverURL            string\n\tserveWWWAuthenticate bool\n}\n\nfunc (h *fakeResourceHandler) installHandlers(serverURL string) {\n\tpath := \"/.well-known/oauth-protected-resource\"\n\turl := serverURL + path\n\th.Handle(\"GET /resource\", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tif h.serveWWWAuthenticate {\n\t\t\tw.Header().Set(\"WWW-Authenticate\", fmt.Sprintf(`Bearer resource_metadata=\"%s\"`, url))\n\t\t}\n\t\tw.WriteHeader(http.StatusUnauthorized)\n\t}))\n\th.Handle(\"GET \"+path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\t// If there is a WWW-Authenticate header, the resource field is the value of that header.\n\t\t// If not, it's the server URL without the \"/.well-known/...\" part.\n\t\tresource := serverURL\n\t\tif h.serveWWWAuthenticate {\n\t\t\tresource = url\n\t\t}\n\t\tprm := &ProtectedResourceMetadata{Resource: resource}\n\t\tif err := json.NewEncoder(w).Encode(prm); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}))\n}\n"
  },
  {
    "path": "internal/mcp/internal/oauthex/resource_meta.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements Protected Resource Metadata.\n// See https://www.rfc-editor.org/rfc/rfc9728.html.\n\npackage oauthex\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\nconst defaultProtectedResourceMetadataURI = \"/.well-known/oauth-protected-resource\"\n\n// ProtectedResourceMetadata is the metadata for an OAuth 2.0 protected resource,\n// as defined in section 2 of https://www.rfc-editor.org/rfc/rfc9728.html.\n//\n// The following features are not supported:\n// - additional keys (§2, last sentence)\n// - human-readable metadata (§2.1)\n// - signed metadata (§2.2)\ntype ProtectedResourceMetadata struct {\n\t// GENERATED BY GEMINI 2.5.\n\n\t// Resource (resource) is the protected resource's resource identifier.\n\t// Required.\n\tResource string `json:\"resource\"`\n\n\t// AuthorizationServers (authorization_servers) is an optional slice containing a list of\n\t// OAuth authorization server issuer identifiers (as defined in RFC 8414) that can be\n\t// used with this protected resource.\n\tAuthorizationServers []string `json:\"authorization_servers,omitempty\"`\n\n\t// JWKSURI (jwks_uri) is an optional URL of the protected resource's JSON Web Key (JWK) Set\n\t// document. This contains public keys belonging to the protected resource, such as\n\t// signing key(s) that the resource server uses to sign resource responses.\n\tJWKSURI string `json:\"jwks_uri,omitempty\"`\n\n\t// ScopesSupported (scopes_supported) is a recommended slice containing a list of scope\n\t// values (as defined in RFC 6749) used in authorization requests to request access\n\t// to this protected resource.\n\tScopesSupported []string `json:\"scopes_supported,omitempty\"`\n\n\t// BearerMethodsSupported (bearer_methods_supported) is an optional slice containing\n\t// a list of the supported methods of sending an OAuth 2.0 bearer token to the\n\t// protected resource. Defined values are \"header\", \"body\", and \"query\".\n\tBearerMethodsSupported []string `json:\"bearer_methods_supported,omitempty\"`\n\n\t// ResourceSigningAlgValuesSupported (resource_signing_alg_values_supported) is an optional\n\t// slice of JWS signing algorithms (alg values) supported by the protected\n\t// resource for signing resource responses.\n\tResourceSigningAlgValuesSupported []string `json:\"resource_signing_alg_values_supported,omitempty\"`\n\n\t// ResourceName (resource_name) is a human-readable name of the protected resource\n\t// intended for display to the end user. It is RECOMMENDED that this field be included.\n\t// This value may be internationalized.\n\tResourceName string `json:\"resource_name,omitempty\"`\n\n\t// ResourceDocumentation (resource_documentation) is an optional URL of a page containing\n\t// human-readable information for developers using the protected resource.\n\t// This value may be internationalized.\n\tResourceDocumentation string `json:\"resource_documentation,omitempty\"`\n\n\t// ResourcePolicyURI (resource_policy_uri) is an optional URL of a page containing\n\t// human-readable policy information on how a client can use the data provided.\n\t// This value may be internationalized.\n\tResourcePolicyURI string `json:\"resource_policy_uri,omitempty\"`\n\n\t// ResourceTOSURI (resource_tos_uri) is an optional URL of a page containing the protected\n\t// resource's human-readable terms of service. This value may be internationalized.\n\tResourceTOSURI string `json:\"resource_tos_uri,omitempty\"`\n\n\t// TLSClientCertificateBoundAccessTokens (tls_client_certificate_bound_access_tokens) is an\n\t// optional boolean indicating support for mutual-TLS client certificate-bound\n\t// access tokens (RFC 8705). Defaults to false if omitted.\n\tTLSClientCertificateBoundAccessTokens bool `json:\"tls_client_certificate_bound_access_tokens,omitempty\"`\n\n\t// AuthorizationDetailsTypesSupported (authorization_details_types_supported) is an optional\n\t// slice of 'type' values supported by the resource server for the\n\t// 'authorization_details' parameter (RFC 9396).\n\tAuthorizationDetailsTypesSupported []string `json:\"authorization_details_types_supported,omitempty\"`\n\n\t// DPOPSigningAlgValuesSupported (dpop_signing_alg_values_supported) is an optional\n\t// slice of JWS signing algorithms supported by the resource server for validating\n\t// DPoP proof JWTs (RFC 9449).\n\tDPOPSigningAlgValuesSupported []string `json:\"dpop_signing_alg_values_supported,omitempty\"`\n\n\t// DPOPBoundAccessTokensRequired (dpop_bound_access_tokens_required) is an optional boolean\n\t// specifying whether the protected resource always requires the use of DPoP-bound\n\t// access tokens (RFC 9449). Defaults to false if omitted.\n\tDPOPBoundAccessTokensRequired bool `json:\"dpop_bound_access_tokens_required,omitempty\"`\n\n\t// SignedMetadata (signed_metadata) is an optional JWT containing metadata parameters\n\t// about the protected resource as claims. If present, these values take precedence\n\t// over values conveyed in plain JSON.\n\t// TODO:implement.\n\t// Note that §2.2 says it's okay to ignore this.\n\t// SignedMetadata string `json:\"signed_metadata,omitempty\"`\n}\n\n// GetProtectedResourceMetadataFromID issues a GET request to retrieve protected resource\n// metadata from a resource server by its ID.\n// The resource ID is an HTTPS URL, typically with a host:port and possibly a path.\n// For example:\n//\n//\thttps://example.com/server\n//\n// This function, following the spec (§3), inserts the default well-known path into the\n// URL. In our example, the result would be\n//\n//\thttps://example.com/.well-known/oauth-protected-resource/server\n//\n// It then retrieves the metadata at that location using the given client (or the\n// default client if nil) and validates its resource field against resourceID.\nfunc GetProtectedResourceMetadataFromID(ctx context.Context, resourceID string, c *http.Client) (_ *ProtectedResourceMetadata, err error) {\n\tdefer util.Wrapf(&err, \"GetProtectedResourceMetadataFromID(%q)\", resourceID)\n\n\tu, err := url.Parse(resourceID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Insert well-known URI into URL.\n\tu.Path = path.Join(defaultProtectedResourceMetadataURI, u.Path)\n\treturn getPRM(ctx, u.String(), c, resourceID)\n}\n\n// GetProtectedResourceMetadataFromHeader retrieves protected resource metadata\n// using information in the given header, using the given client (or the default\n// client if nil).\n// It issues a GET request to a URL discovered by parsing the WWW-Authenticate headers in the given request,\n// It then validates the resource field of the resulting metadata against the given URL.\n// If there is no URL in the request, it returns nil, nil.\nfunc GetProtectedResourceMetadataFromHeader(ctx context.Context, header http.Header, c *http.Client) (_ *ProtectedResourceMetadata, err error) {\n\tdefer util.Wrapf(&err, \"GetProtectedResourceMetadataFromHeader\")\n\theaders := header[http.CanonicalHeaderKey(\"WWW-Authenticate\")]\n\tif len(headers) == 0 {\n\t\treturn nil, nil\n\t}\n\tcs, err := parseWWWAuthenticate(headers)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\turl := resourceMetadataURL(cs)\n\tif url == \"\" {\n\t\treturn nil, nil\n\t}\n\treturn getPRM(ctx, url, c, url)\n}\n\n// getPRM makes a GET request to the given URL, and validates the response.\n// As part of the validation, it compares the returned resource field to wantResource.\nfunc getPRM(ctx context.Context, url string, c *http.Client, wantResource string) (*ProtectedResourceMetadata, error) {\n\tif !strings.HasPrefix(strings.ToUpper(url), \"HTTPS://\") {\n\t\treturn nil, fmt.Errorf(\"resource URL %q does not use HTTPS\", url)\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif c == nil {\n\t\tc = http.DefaultClient\n\t}\n\tres, err := c.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\n\t// Spec §3.2 requires a 200.\n\tif res.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"bad status %s\", res.Status)\n\t}\n\t// Spec §3.2 requires application/json.\n\tif ct := res.Header.Get(\"Content-Type\"); ct != \"application/json\" {\n\t\treturn nil, fmt.Errorf(\"bad content type %q\", ct)\n\t}\n\n\tvar prm ProtectedResourceMetadata\n\tdec := json.NewDecoder(res.Body)\n\tif err := dec.Decode(&prm); err != nil {\n\t\treturn nil, err\n\t}\n\t// Validate the Resource field to thwart impersonation attacks (section 3.3).\n\tif prm.Resource != wantResource {\n\t\treturn nil, fmt.Errorf(\"got metadata resource %q, want %q\", prm.Resource, wantResource)\n\t}\n\treturn &prm, nil\n}\n\n// challenge represents a single authentication challenge from a WWW-Authenticate header.\n// As per RFC 9110, Section 11.6.1, a challenge consists of a scheme and optional parameters.\ntype challenge struct {\n\t// GENERATED BY GEMINI 2.5.\n\t//\n\t// Scheme is the authentication scheme (e.g., \"Bearer\", \"Basic\").\n\t// It is case-insensitive. A parsed value will always be lower-case.\n\tScheme string\n\t// Params is a map of authentication parameters.\n\t// Keys are case-insensitive. Parsed keys are always lower-case.\n\tParams map[string]string\n}\n\n// resourceMetadataURL returns a resource metadata URL from the given challenges,\n// or the empty string if there is none.\nfunc resourceMetadataURL(cs []challenge) string {\n\tfor _, c := range cs {\n\t\tif u := c.Params[\"resource_metadata\"]; u != \"\" {\n\t\t\treturn u\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// parseWWWAuthenticate parses a WWW-Authenticate header string.\n// The header format is defined in RFC 9110, Section 11.6.1, and can contain\n// one or more challenges, separated by commas.\n// It returns a slice of challenges or an error if one of the headers is malformed.\nfunc parseWWWAuthenticate(headers []string) ([]challenge, error) {\n\t// GENERATED BY GEMINI 2.5 (human-tweaked)\n\tvar challenges []challenge\n\tfor _, h := range headers {\n\t\tchallengeStrings, err := splitChallenges(h)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, cs := range challengeStrings {\n\t\t\tif strings.TrimSpace(cs) == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tchallenge, err := parseSingleChallenge(cs)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to parse challenge %q: %w\", cs, err)\n\t\t\t}\n\t\t\tchallenges = append(challenges, challenge)\n\t\t}\n\t}\n\treturn challenges, nil\n}\n\n// splitChallenges splits a header value containing one or more challenges.\n// It correctly handles commas within quoted strings and distinguishes between\n// commas separating auth-params and commas separating challenges.\nfunc splitChallenges(header string) ([]string, error) {\n\t// GENERATED BY GEMINI 2.5.\n\tvar challenges []string\n\tinQuotes := false\n\tstart := 0\n\tfor i, r := range header {\n\t\tif r == '\"' {\n\t\t\tif i > 0 && header[i-1] != '\\\\' {\n\t\t\t\tinQuotes = !inQuotes\n\t\t\t} else if i == 0 {\n\t\t\t\t// A challenge begins with an auth-scheme, which is a token, which cannot contain\n\t\t\t\t// a quote.\n\t\t\t\treturn nil, errors.New(`challenge begins with '\"'`)\n\t\t\t}\n\t\t} else if r == ',' && !inQuotes {\n\t\t\t// This is a potential challenge separator.\n\t\t\t// A new challenge does not start with `key=value`.\n\t\t\t// We check if the part after the comma looks like a parameter.\n\t\t\tlookahead := strings.TrimSpace(header[i+1:])\n\t\t\teqPos := strings.Index(lookahead, \"=\")\n\n\t\t\tisParam := false\n\t\t\tif eqPos > 0 {\n\t\t\t\t// Check if the part before '=' is a single token (no spaces).\n\t\t\t\ttoken := lookahead[:eqPos]\n\t\t\t\tif strings.IndexFunc(token, unicode.IsSpace) == -1 {\n\t\t\t\t\tisParam = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !isParam {\n\t\t\t\t// The part after the comma does not look like a parameter,\n\t\t\t\t// so this comma separates challenges.\n\t\t\t\tchallenges = append(challenges, header[start:i])\n\t\t\t\tstart = i + 1\n\t\t\t}\n\t\t}\n\t}\n\t// Add the last (or only) challenge to the list.\n\tchallenges = append(challenges, header[start:])\n\treturn challenges, nil\n}\n\n// parseSingleChallenge parses a string containing exactly one challenge.\n// challenge   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]\nfunc parseSingleChallenge(s string) (challenge, error) {\n\t// GENERATED BY GEMINI 2.5, human-tweaked.\n\ts = strings.TrimSpace(s)\n\tif s == \"\" {\n\t\treturn challenge{}, errors.New(\"empty challenge string\")\n\t}\n\n\tscheme, paramsStr, found := strings.Cut(s, \" \")\n\tc := challenge{Scheme: strings.ToLower(scheme)}\n\tif !found {\n\t\treturn c, nil\n\t}\n\n\tparams := make(map[string]string)\n\n\t// Parse the key-value parameters.\n\tfor paramsStr != \"\" {\n\t\t// Find the end of the parameter key.\n\t\tkeyEnd := strings.Index(paramsStr, \"=\")\n\t\tif keyEnd <= 0 {\n\t\t\treturn challenge{}, fmt.Errorf(\"malformed auth parameter: expected key=value, but got %q\", paramsStr)\n\t\t}\n\t\tkey := strings.TrimSpace(paramsStr[:keyEnd])\n\n\t\t// Move the string past the key and the '='.\n\t\tparamsStr = strings.TrimSpace(paramsStr[keyEnd+1:])\n\n\t\tvar value string\n\t\tif strings.HasPrefix(paramsStr, \"\\\"\") {\n\t\t\t// The value is a quoted string.\n\t\t\tparamsStr = paramsStr[1:] // Consume the opening quote.\n\t\t\tvar valBuilder strings.Builder\n\t\t\ti := 0\n\t\t\tfor ; i < len(paramsStr); i++ {\n\t\t\t\t// Handle escaped characters.\n\t\t\t\tif paramsStr[i] == '\\\\' && i+1 < len(paramsStr) {\n\t\t\t\t\tvalBuilder.WriteByte(paramsStr[i+1])\n\t\t\t\t\ti++ // We've consumed two characters.\n\t\t\t\t} else if paramsStr[i] == '\"' {\n\t\t\t\t\t// End of the quoted string.\n\t\t\t\t\tbreak\n\t\t\t\t} else {\n\t\t\t\t\tvalBuilder.WriteByte(paramsStr[i])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// A quoted string must be terminated.\n\t\t\tif i == len(paramsStr) {\n\t\t\t\treturn challenge{}, fmt.Errorf(\"unterminated quoted string in auth parameter\")\n\t\t\t}\n\n\t\t\tvalue = valBuilder.String()\n\t\t\t// Move the string past the value and the closing quote.\n\t\t\tparamsStr = strings.TrimSpace(paramsStr[i+1:])\n\t\t} else {\n\t\t\t// The value is a token. It ends at the next comma or the end of the string.\n\t\t\tcommaPos := strings.Index(paramsStr, \",\")\n\t\t\tif commaPos == -1 {\n\t\t\t\tvalue = paramsStr\n\t\t\t\tparamsStr = \"\"\n\t\t\t} else {\n\t\t\t\tvalue = strings.TrimSpace(paramsStr[:commaPos])\n\t\t\t\tparamsStr = strings.TrimSpace(paramsStr[commaPos:]) // Keep comma for next check\n\t\t\t}\n\t\t}\n\t\tif value == \"\" {\n\t\t\treturn challenge{}, fmt.Errorf(\"no value for auth param %q\", key)\n\t\t}\n\n\t\t// Per RFC 9110, parameter keys are case-insensitive.\n\t\tparams[strings.ToLower(key)] = value\n\n\t\t// If there is a comma, consume it and continue to the next parameter.\n\t\tif strings.HasPrefix(paramsStr, \",\") {\n\t\t\tparamsStr = strings.TrimSpace(paramsStr[1:])\n\t\t} else if paramsStr != \"\" {\n\t\t\t// If there's content but it's not a new parameter, the format is wrong.\n\t\t\treturn challenge{}, fmt.Errorf(\"malformed auth parameter: expected comma after value, but got %q\", paramsStr)\n\t\t}\n\t}\n\n\t// Per RFC 9110, the scheme is case-insensitive.\n\treturn challenge{Scheme: strings.ToLower(scheme), Params: params}, nil\n}\n"
  },
  {
    "path": "internal/mcp/internal/readme/Makefile",
    "content": "# This makefile builds ../README.md from the files in this directory.\n\nOUTFILE=../../README.md\n\n$(OUTFILE): build README.src.md\n\tgo run golang.org/x/example/internal/cmd/weave@latest README.src.md > $(OUTFILE)\n\n# Compile all the code used in the README.\nbuild: $(wildcard */*.go)\n\tgo build -o /tmp/mcp-readme/ ./...\n\n# Preview the README on GitHub.\n# $HOME/markdown must be a github repo.\n# Visit https://github.com/$HOME/markdown to see the result.\npreview: $(OUTFILE)\n\tcp $(OUTFILE) $$HOME/markdown/\n\t(cd $$HOME/markdown/ && git commit -m . README.md && git push)\n\n.PHONY: build preview\n"
  },
  {
    "path": "internal/mcp/internal/readme/README.src.md",
    "content": "# MCP Go SDK\n\n<!-- TODO: update pkgsite links here to point to the modelcontextprotocol\nmodule, once it exists. -->\n\n[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk)\n\nThis repository contains an implementation of the official Go software\ndevelopment kit (SDK) for the Model Context Protocol (MCP).\n\n**WARNING**: The SDK is currently unstable and subject to breaking changes.\nPlease test it out and file bug reports or API proposals. The [TODO](#todo)\nsection below outlines outstanding release blockers. We aim to release a stable\nversion of the SDK in mid July, 2025.\n\n%toc\n\n## Package documentation\n\nThe SDK consists of two importable packages:\n\n- The\n  [`github.com/modelcontextprotocol/go-sdk/mcp`](https://pkg.go.dev/golang.org/x/tools/internal/mcp)\n  package defines the primary APIs for constructing and using MCP clients and\n  servers.\n- The\n  [`github.com/modelcontextprotocol/go-sdk/jsonschema`](https://pkg.go.dev/golang.org/x/tools/internal/mcp/jsonschema)\n  package provides an implementation of [JSON\n  Schema](https://json-schema.org/), used for MCP tool input and output schema.\n\n## Example\n\nIn this example, an MCP client communicates with an MCP server running in a\nsidecar process:\n\n%include client/client.go -\n\nHere's an example of the corresponding server component, which communicates\nwith its client over stdin/stdout:\n\n%include server/server.go -\n\nThe `examples/` directory contains more example clients and servers.\n\n## TODO\n\nThe following TODOs block the release of this SDK:\n\n- Better support for resumability in the Streamable HTTP transport: a\n  server-side event store and client-side retry configuration.\n- OAuth support (or examples of implementing OAuth using middleware).\n- Support for the changes in the\n  [2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/changelog)\n  version of the MCP spec.\n- More examples and documentation.\n\n## Design\n\nThe design doc for this SDK is at [design.md](./design/design.md), which was\ninitially reviewed at\n[modelcontextprotocol/discussions/364](https://github.com/orgs/modelcontextprotocol/discussions/364).\n\nFurther design discussion should occur in GitHub issues. See CONTRIBUTING.md\nfor details.\n\n## Acknowledgements\n\nSeveral existing Go MCP SDKs inspired the development and design of this\nofficial SDK, notably [mcp-go](https://github.com/mark3labs/mcp-go), authored\nby Ed Zynda. We are grateful to Ed as well as the other contributors to mcp-go,\nand to authors and contributors of other SDKs such as\n[mcp-golang](https://github.com/metoro-io/mcp-golang) and\n[go-mcp](https://github.com/ThinkInAIXYZ/go-mcp). Thanks to their work, there\nis a thriving ecosystem of Go MCP clients and servers.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](./LICENSE)\nfile for details.\n"
  },
  {
    "path": "internal/mcp/internal/readme/build.sh",
    "content": "#!/bin/sh\n\n# Build README.md from the files in this directory.\n# Must be invoked from the internal/cmp directory.\n\ncd internal/readme\n\noutfile=../../README.md\n\n# Compile all the code used in the README.\ngo build -o /tmp/mcp-readme/ ./...\n# Combine the code with the text in README.src.md.\n# TODO: when at Go 1.24, use a tool directive for weave.\ngo run golang.org/x/example/internal/cmd/weave@latest README.src.md > $outfile\n\nif [[ $1 = '-preview' ]]; then\n\t# Preview the README on GitHub.\n\t# $HOME/markdown must be a github repo.\n\t# Visit https://github.com/$HOME/markdown to see the result.\n\tcp $outfile $HOME/markdown/\n\t(cd $HOME/markdown/ && git commit -m . README.md && git push)\nfi\n"
  },
  {
    "path": "internal/mcp/internal/readme/client/client.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// !+\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os/exec\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\t// Create a new client, with no features.\n\tclient := mcp.NewClient(\"mcp-client\", \"v1.0.0\", nil)\n\n\t// Connect to a server over stdin/stdout\n\ttransport := mcp.NewCommandTransport(exec.Command(\"myserver\"))\n\tsession, err := client.Connect(ctx, transport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer session.Close()\n\n\t// Call a tool on the server.\n\tparams := &mcp.CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"you\"},\n\t}\n\tres, err := session.CallTool(ctx, params)\n\tif err != nil {\n\t\tlog.Fatalf(\"CallTool failed: %v\", err)\n\t}\n\tif res.IsError {\n\t\tlog.Fatal(\"tool failed\")\n\t}\n\tfor _, c := range res.Content {\n\t\tlog.Print(c.Text)\n\t}\n}\n\n//!-\n"
  },
  {
    "path": "internal/mcp/internal/readme/server/server.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// !+\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\ntype HiParams struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {\n\treturn &mcp.CallToolResultFor[any]{\n\t\tContent: []*mcp.Content{mcp.NewTextContent(\"Hi \" + params.Name)},\n\t}, nil\n}\n\nfunc main() {\n\t// Create a server with a single tool.\n\tserver := mcp.NewServer(\"greeter\", \"v1.0.0\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi))\n\t// Run the server over stdin/stdout, until the client disconnects\n\tif err := server.Run(context.Background(), mcp.NewStdioTransport()); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\n// !-\n"
  },
  {
    "path": "internal/mcp/internal/util/util.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage util\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n)\n\ntype JSONInfo struct {\n\tOmit     bool            // unexported or first tag element is \"-\"\n\tName     string          // Go field name or first tag element. Empty if Omit is true.\n\tSettings map[string]bool // \"omitempty\", \"omitzero\", etc.\n}\n\n// FieldJSONInfo reports information about how encoding/json\n// handles the given struct field.\n// If the field is unexported, JSONInfo.Omit is true and no other JSONInfo field\n// is populated.\n// If the field is exported and has no tag, then Name is the field's name and all\n// other fields are false.\n// Otherwise, the information is obtained from the tag.\nfunc FieldJSONInfo(f reflect.StructField) JSONInfo {\n\tif !f.IsExported() {\n\t\treturn JSONInfo{Omit: true}\n\t}\n\tinfo := JSONInfo{Name: f.Name}\n\tif tag, ok := f.Tag.Lookup(\"json\"); ok {\n\t\tname, rest, found := strings.Cut(tag, \",\")\n\t\t// \"-\" means omit, but \"-,\" means the name is \"-\"\n\t\tif name == \"-\" && !found {\n\t\t\treturn JSONInfo{Omit: true}\n\t\t}\n\t\tif name != \"\" {\n\t\t\tinfo.Name = name\n\t\t}\n\t\tif len(rest) > 0 {\n\t\t\tinfo.Settings = map[string]bool{}\n\t\t\tfor s := range strings.SplitSeq(rest, \",\") {\n\t\t\t\tinfo.Settings[s] = true\n\t\t\t}\n\t\t}\n\t}\n\treturn info\n}\n\n// Wrapf wraps *errp with the given formatted message if *errp is not nil.\nfunc Wrapf(errp *error, format string, args ...any) {\n\tif *errp != nil {\n\t\t*errp = fmt.Errorf(\"%s: %w\", fmt.Sprintf(format, args...), *errp)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/internal/util/util_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage util\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestJSONInfo(t *testing.T) {\n\ttype S struct {\n\t\tA int\n\t\tB int `json:\",\"`\n\t\tC int `json:\"-\"`\n\t\tD int `json:\"-,\"`\n\t\tE int `json:\"echo\"`\n\t\tF int `json:\"foxtrot,omitempty\"`\n\t\tg int `json:\"golf\"` // vet reports \"struct field g has json tag but is not exported\"\n\t}\n\twant := []JSONInfo{\n\t\t{Name: \"A\"},\n\t\t{Name: \"B\"},\n\t\t{Omit: true},\n\t\t{Name: \"-\"},\n\t\t{Name: \"echo\"},\n\t\t{Name: \"foxtrot\", Settings: map[string]bool{\"omitempty\": true}},\n\t\t{Omit: true},\n\t}\n\ttt := reflect.TypeFor[S]()\n\tfor i := range tt.NumField() {\n\t\tgot := FieldJSONInfo(tt.Field(i))\n\t\tif !reflect.DeepEqual(got, want[i]) {\n\t\t\tt.Errorf(\"got %+v, want %+v\", got, want[i])\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/annotations.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport \"maps\"\n\n// An annotations tracks certain properties computed by keywords that are used by validation.\n// (\"Annotation\" is the spec's term.)\n// In particular, the unevaluatedItems and unevaluatedProperties keywords need to know which\n// items and properties were evaluated (validated successfully).\ntype annotations struct {\n\tallItems            bool            // all items were evaluated\n\tendIndex            int             // 1+largest index evaluated by prefixItems\n\tevaluatedIndexes    map[int]bool    // set of indexes evaluated by contains\n\tallProperties       bool            // all properties were evaluated\n\tevaluatedProperties map[string]bool // set of properties evaluated by various keywords\n}\n\n// noteIndex marks i as evaluated.\nfunc (a *annotations) noteIndex(i int) {\n\tif a.evaluatedIndexes == nil {\n\t\ta.evaluatedIndexes = map[int]bool{}\n\t}\n\ta.evaluatedIndexes[i] = true\n}\n\n// noteEndIndex marks items with index less than end as evaluated.\nfunc (a *annotations) noteEndIndex(end int) {\n\tif end > a.endIndex {\n\t\ta.endIndex = end\n\t}\n}\n\n// noteProperty marks prop as evaluated.\nfunc (a *annotations) noteProperty(prop string) {\n\tif a.evaluatedProperties == nil {\n\t\ta.evaluatedProperties = map[string]bool{}\n\t}\n\ta.evaluatedProperties[prop] = true\n}\n\n// noteProperties marks all the properties in props as evaluated.\nfunc (a *annotations) noteProperties(props map[string]bool) {\n\ta.evaluatedProperties = merge(a.evaluatedProperties, props)\n}\n\n// merge adds b's annotations to a.\n// a must not be nil.\nfunc (a *annotations) merge(b *annotations) {\n\tif b == nil {\n\t\treturn\n\t}\n\tif b.allItems {\n\t\ta.allItems = true\n\t}\n\tif b.endIndex > a.endIndex {\n\t\ta.endIndex = b.endIndex\n\t}\n\ta.evaluatedIndexes = merge(a.evaluatedIndexes, b.evaluatedIndexes)\n\tif b.allProperties {\n\t\ta.allProperties = true\n\t}\n\ta.evaluatedProperties = merge(a.evaluatedProperties, b.evaluatedProperties)\n}\n\n// merge adds t's keys to s and returns s.\n// If s is nil, it returns a copy of t.\nfunc merge[K comparable](s, t map[K]bool) map[K]bool {\n\tif s == nil {\n\t\treturn maps.Clone(t)\n\t}\n\tmaps.Copy(s, t)\n\treturn s\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/doc.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage jsonschema is an implementation of the [JSON Schema specification],\na JSON-based format for describing the structure of JSON data.\nThe package can be used to read schemas for code generation, and to validate data using the\ndraft 2020-12 specification. Validation with other drafts or custom meta-schemas\nis not supported.\n\nConstruct a [Schema] as you would any Go struct (for example, by writing a struct\nliteral), or unmarshal a JSON schema into a [Schema] in the usual way (with [encoding/json],\nfor instance). It can then be used for code generation or other purposes without\nfurther processing.\n\n# Validation\n\nBefore using a Schema to validate a JSON value, you must first resolve it by calling\n[Schema.Resolve].\nThe call [Resolved.Validate] on the result to validate a JSON value.\nThe value must be a Go value that looks like the result of unmarshaling a JSON\nvalue into an [any] or a struct. For example, the JSON value\n\n\t{\"name\": \"Al\", \"scores\": [90, 80, 100]}\n\ncould be represented as the Go value\n\n\tmap[string]any{\n\t\t\"name\": \"Al\",\n\t\t\"scores\": []any{90, 80, 100},\n\t}\n\nor as a value of this type:\n\n\ttype Player struct {\n\t\tName   string `json:\"name\"`\n\t\tScores []int  `json:\"scores\"`\n\t}\n\n# Inference\n\nThe [For] and [ForType] functions return a [Schema] describing the given Go type.\nThe type cannot contain any function or channel types, and any map types must have a string key.\nFor example, calling For on the above Player type results in this schema:\n\n\t{\n\t    \"properties\": {\n\t        \"name\": {\n\t            \"type\": \"string\"\n\t        },\n\t        \"scores\": {\n\t            \"type\": \"array\",\n\t            \"items\": {\"type\": \"integer\"}\n\t        }\n\t        \"required\": [\"name\", \"scores\"],\n\t        \"additionalProperties\": {\"not\": {}}\n\t    }\n\t}\n\n# Deviations from the specification\n\nRegular expressions are processed with Go's regexp package, which differs from ECMA 262,\nmost significantly in not supporting back-references.\nSee [this table of differences] for more.\n\nThe value of the \"format\" keyword is recorded in the Schema, but is ignored during validation.\nIt does not even produce [annotations].\n\n[JSON Schema specification]: https://json-schema.org\n[this table of differences] https://github.com/dlclark/regexp2?tab=readme-ov-file#compare-regexp-and-regexp2\n[annotations]: https://json-schema.org/draft/2020-12/json-schema-core#name-annotations\n*/\npackage jsonschema\n"
  },
  {
    "path": "internal/mcp/jsonschema/infer.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains functions that infer a schema from a Go type.\n\npackage jsonschema\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\n// For constructs a JSON schema object for the given type argument.\n//\n// It is a convenience for ForType.\nfunc For[T any]() (*Schema, error) {\n\treturn ForType(reflect.TypeFor[T]())\n}\n\n// ForType constructs a JSON schema object for the given type.\n// It translates Go types into compatible JSON schema types, as follows:\n//   - strings have schema type \"string\"\n//   - bools have schema type \"boolean\"\n//   - signed and unsigned integer types have schema type \"integer\"\n//   - floating point types have schema type \"number\"\n//   - slices and arrays have schema type \"array\", and a corresponding schema\n//     for items\n//   - maps with string key have schema type \"object\", and corresponding\n//     schema for additionalProperties\n//   - structs have schema type \"object\", and disallow additionalProperties.\n//     Their properties are derived from exported struct fields, using the\n//     struct field json name. Fields that are marked \"omitempty\" are\n//     considered optional; all other fields become required properties.\n//\n// It returns an error if t contains (possibly recursively) any of the following Go\n// types, as they are incompatible with the JSON schema spec.\n//   - maps with key other than 'string'\n//   - function types\n//   - complex numbers\n//   - unsafe pointers\n//\n// The cannot be any cycles in the types.\n// TODO(rfindley): we could perhaps just skip these incompatible fields.\nfunc ForType(t reflect.Type) (*Schema, error) {\n\treturn typeSchema(t)\n}\n\nfunc typeSchema(t reflect.Type) (*Schema, error) {\n\t// Follow pointers: the schema for *T is almost the same as for T, except that\n\t// an explicit JSON \"null\" is allowed for the pointer.\n\tallowNull := false\n\tfor t.Kind() == reflect.Pointer {\n\t\tallowNull = true\n\t\tt = t.Elem()\n\t}\n\n\tvar (\n\t\ts   = new(Schema)\n\t\terr error\n\t)\n\n\tswitch t.Kind() {\n\tcase reflect.Bool:\n\t\ts.Type = \"boolean\"\n\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,\n\t\treflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,\n\t\treflect.Uintptr:\n\t\ts.Type = \"integer\"\n\n\tcase reflect.Float32, reflect.Float64:\n\t\ts.Type = \"number\"\n\n\tcase reflect.Interface:\n\t\t// Unrestricted\n\n\tcase reflect.Map:\n\t\tif t.Key().Kind() != reflect.String {\n\t\t\treturn nil, fmt.Errorf(\"unsupported map key type %v\", t.Key().Kind())\n\t\t}\n\t\ts.Type = \"object\"\n\t\ts.AdditionalProperties, err = typeSchema(t.Elem())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"computing map value schema: %v\", err)\n\t\t}\n\n\tcase reflect.Slice, reflect.Array:\n\t\ts.Type = \"array\"\n\t\ts.Items, err = typeSchema(t.Elem())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"computing element schema: %v\", err)\n\t\t}\n\t\tif t.Kind() == reflect.Array {\n\t\t\ts.MinItems = Ptr(t.Len())\n\t\t\ts.MaxItems = Ptr(t.Len())\n\t\t}\n\n\tcase reflect.String:\n\t\ts.Type = \"string\"\n\n\tcase reflect.Struct:\n\t\ts.Type = \"object\"\n\t\t// no additional properties are allowed\n\t\ts.AdditionalProperties = falseSchema()\n\n\t\tfor i := range t.NumField() {\n\t\t\tfield := t.Field(i)\n\t\t\tinfo := util.FieldJSONInfo(field)\n\t\t\tif info.Omit {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif s.Properties == nil {\n\t\t\t\ts.Properties = make(map[string]*Schema)\n\t\t\t}\n\t\t\ts.Properties[info.Name], err = typeSchema(field.Type)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif !info.Settings[\"omitempty\"] && !info.Settings[\"omitzero\"] {\n\t\t\t\ts.Required = append(s.Required, info.Name)\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"type %v is unsupported by jsonschema\", t)\n\t}\n\tif allowNull && s.Type != \"\" {\n\t\ts.Types = []string{\"null\", s.Type}\n\t\ts.Type = \"\"\n\t}\n\treturn s, nil\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/infer_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\nfunc forType[T any]() *jsonschema.Schema {\n\ts, err := jsonschema.For[T]()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn s\n}\n\nfunc TestForType(t *testing.T) {\n\ttype schema = jsonschema.Schema\n\ttests := []struct {\n\t\tname string\n\t\tgot  *jsonschema.Schema\n\t\twant *jsonschema.Schema\n\t}{\n\t\t{\"string\", forType[string](), &schema{Type: \"string\"}},\n\t\t{\"int\", forType[int](), &schema{Type: \"integer\"}},\n\t\t{\"int16\", forType[int16](), &schema{Type: \"integer\"}},\n\t\t{\"uint32\", forType[int16](), &schema{Type: \"integer\"}},\n\t\t{\"float64\", forType[float64](), &schema{Type: \"number\"}},\n\t\t{\"bool\", forType[bool](), &schema{Type: \"boolean\"}},\n\t\t{\"intmap\", forType[map[string]int](), &schema{\n\t\t\tType:                 \"object\",\n\t\t\tAdditionalProperties: &schema{Type: \"integer\"},\n\t\t}},\n\t\t{\"anymap\", forType[map[string]any](), &schema{\n\t\t\tType:                 \"object\",\n\t\t\tAdditionalProperties: &schema{},\n\t\t}},\n\t\t{\n\t\t\t\"struct\",\n\t\t\tforType[struct {\n\t\t\t\tF           int `json:\"f\"`\n\t\t\t\tG           []float64\n\t\t\t\tP           *bool\n\t\t\t\tSkip        string `json:\"-\"`\n\t\t\t\tNoSkip      string `json:\",omitempty\"`\n\t\t\t\tunexported  float64\n\t\t\t\tunexported2 int `json:\"No\"` // vet reports \"struct field unexported2 has json tag but is not exported\"\n\t\t\t}](),\n\t\t\t&schema{\n\t\t\t\tType: \"object\",\n\t\t\t\tProperties: map[string]*schema{\n\t\t\t\t\t\"f\":      {Type: \"integer\"},\n\t\t\t\t\t\"G\":      {Type: \"array\", Items: &schema{Type: \"number\"}},\n\t\t\t\t\t\"P\":      {Types: []string{\"null\", \"boolean\"}},\n\t\t\t\t\t\"NoSkip\": {Type: \"string\"},\n\t\t\t\t},\n\t\t\t\tRequired:             []string{\"f\", \"G\", \"P\"},\n\t\t\t\tAdditionalProperties: &jsonschema.Schema{Not: &jsonschema.Schema{}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"no sharing\",\n\t\t\tforType[struct{ X, Y int }](),\n\t\t\t&schema{\n\t\t\t\tType: \"object\",\n\t\t\t\tProperties: map[string]*schema{\n\t\t\t\t\t\"X\": {Type: \"integer\"},\n\t\t\t\t\t\"Y\": {Type: \"integer\"},\n\t\t\t\t},\n\t\t\t\tRequired:             []string{\"X\", \"Y\"},\n\t\t\t\tAdditionalProperties: &jsonschema.Schema{Not: &jsonschema.Schema{}},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tif diff := cmp.Diff(test.want, test.got, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\t\tt.Fatalf(\"ForType mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t\t// These schemas should all resolve.\n\t\t\tif _, err := test.got.Resolve(nil); err != nil {\n\t\t\t\tt.Fatalf(\"Resolving: %v\", err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/json_pointer.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file implements JSON Pointers.\n// A JSON Pointer is a path that refers to one JSON value within another.\n// If the path is empty, it refers to the root value.\n// Otherwise, it is a sequence of slash-prefixed strings, like \"/points/1/x\",\n// selecting successive properties (for JSON objects) or items (for JSON arrays).\n// For example, when applied to this JSON value:\n//    {\n// \t     \"points\": [\n// \t \t    {\"x\": 1, \"y\": 2},\n// \t \t    {\"x\": 3, \"y\": 4}\n// \t\t ]\n//    }\n//\n// the JSON Pointer \"/points/1/x\" refers to the number 3.\n// See the spec at https://datatracker.ietf.org/doc/html/rfc6901.\n\npackage jsonschema\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\nvar (\n\tjsonPointerEscaper   = strings.NewReplacer(\"~\", \"~0\", \"/\", \"~1\")\n\tjsonPointerUnescaper = strings.NewReplacer(\"~0\", \"~\", \"~1\", \"/\")\n)\n\nfunc escapeJSONPointerSegment(s string) string {\n\treturn jsonPointerEscaper.Replace(s)\n}\n\nfunc unescapeJSONPointerSegment(s string) string {\n\treturn jsonPointerUnescaper.Replace(s)\n}\n\n// parseJSONPointer splits a JSON Pointer into a sequence of segments. It doesn't\n// convert strings to numbers, because that depends on the traversal: a segment\n// is treated as a number when applied to an array, but a string when applied to\n// an object. See section 4 of the spec.\nfunc parseJSONPointer(ptr string) (segments []string, err error) {\n\tif ptr == \"\" {\n\t\treturn nil, nil\n\t}\n\tif ptr[0] != '/' {\n\t\treturn nil, fmt.Errorf(\"JSON Pointer %q does not begin with '/'\", ptr)\n\t}\n\t// Unlike file paths, consecutive slashes are not coalesced.\n\t// Split is nicer than Cut here, because it gets a final \"/\" right.\n\tsegments = strings.Split(ptr[1:], \"/\")\n\tif strings.Contains(ptr, \"~\") {\n\t\t// Undo the simple escaping rules that allow one to include a slash in a segment.\n\t\tfor i := range segments {\n\t\t\tsegments[i] = unescapeJSONPointerSegment(segments[i])\n\t\t}\n\t}\n\treturn segments, nil\n}\n\n// dereferenceJSONPointer returns the Schema that sptr points to within s,\n// or an error if none.\n// This implementation suffices for JSON Schema: pointers are applied only to Schemas,\n// and refer only to Schemas.\nfunc dereferenceJSONPointer(s *Schema, sptr string) (_ *Schema, err error) {\n\tdefer util.Wrapf(&err, \"JSON Pointer %q\", sptr)\n\n\tsegments, err := parseJSONPointer(sptr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tv := reflect.ValueOf(s)\n\tfor _, seg := range segments {\n\t\tswitch v.Kind() {\n\t\tcase reflect.Pointer:\n\t\t\tv = v.Elem()\n\t\t\tif !v.IsValid() {\n\t\t\t\treturn nil, errors.New(\"navigated to nil reference\")\n\t\t\t}\n\t\t\tfallthrough // if valid, can only be a pointer to a Schema\n\n\t\tcase reflect.Struct:\n\t\t\t// The segment must refer to a field in a Schema.\n\t\t\tif v.Type() != reflect.TypeFor[Schema]() {\n\t\t\t\treturn nil, fmt.Errorf(\"navigated to non-Schema %s\", v.Type())\n\t\t\t}\n\t\t\tv = lookupSchemaField(v, seg)\n\t\t\tif !v.IsValid() {\n\t\t\t\treturn nil, fmt.Errorf(\"no schema field %q\", seg)\n\t\t\t}\n\t\tcase reflect.Slice, reflect.Array:\n\t\t\t// The segment must be an integer without leading zeroes that refers to an item in the\n\t\t\t// slice or array.\n\t\t\tif seg == \"-\" {\n\t\t\t\treturn nil, errors.New(\"the JSON Pointer array segment '-' is not supported\")\n\t\t\t}\n\t\t\tif len(seg) > 1 && seg[0] == '0' {\n\t\t\t\treturn nil, fmt.Errorf(\"segment %q has leading zeroes\", seg)\n\t\t\t}\n\t\t\tn, err := strconv.Atoi(seg)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid int: %q\", seg)\n\t\t\t}\n\t\t\tif n < 0 || n >= v.Len() {\n\t\t\t\treturn nil, fmt.Errorf(\"index %d is out of bounds for array of length %d\", n, v.Len())\n\t\t\t}\n\t\t\tv = v.Index(n)\n\t\t\t// Cannot be invalid.\n\t\tcase reflect.Map:\n\t\t\t// The segment must be a key in the map.\n\t\t\tv = v.MapIndex(reflect.ValueOf(seg))\n\t\t\tif !v.IsValid() {\n\t\t\t\treturn nil, fmt.Errorf(\"no key %q in map\", seg)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"value %s (%s) is not a schema, slice or map\", v, v.Type())\n\t\t}\n\t}\n\tif s, ok := v.Interface().(*Schema); ok {\n\t\treturn s, nil\n\t}\n\treturn nil, fmt.Errorf(\"does not refer to a schema, but to a %s\", v.Type())\n}\n\n// lookupSchemaField returns the value of the field with the given name in v,\n// or the zero value if there is no such field or it is not of type Schema or *Schema.\nfunc lookupSchemaField(v reflect.Value, name string) reflect.Value {\n\tif name == \"type\" {\n\t\t// The \"type\" keyword may refer to Type or Types.\n\t\t// At most one will be non-zero.\n\t\tif t := v.FieldByName(\"Type\"); !t.IsZero() {\n\t\t\treturn t\n\t\t}\n\t\treturn v.FieldByName(\"Types\")\n\t}\n\tif sf, ok := schemaFieldMap[name]; ok {\n\t\treturn v.FieldByIndex(sf.Index)\n\t}\n\treturn reflect.Value{}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/json_pointer_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestDereferenceJSONPointer(t *testing.T) {\n\ts := &Schema{\n\t\tAllOf: []*Schema{{}, {}},\n\t\tDefs: map[string]*Schema{\n\t\t\t\"\":  {Properties: map[string]*Schema{\"\": {}}},\n\t\t\t\"A\": {},\n\t\t\t\"B\": {\n\t\t\t\tDefs: map[string]*Schema{\n\t\t\t\t\t\"X\": {},\n\t\t\t\t\t\"Y\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"/~\": {},\n\t\t\t\"~1\": {},\n\t\t},\n\t}\n\n\tfor _, tt := range []struct {\n\t\tptr  string\n\t\twant any\n\t}{\n\t\t{\"\", s},\n\t\t{\"/$defs/A\", s.Defs[\"A\"]},\n\t\t{\"/$defs/B\", s.Defs[\"B\"]},\n\t\t{\"/$defs/B/$defs/X\", s.Defs[\"B\"].Defs[\"X\"]},\n\t\t{\"/$defs//properties/\", s.Defs[\"\"].Properties[\"\"]},\n\t\t{\"/allOf/1\", s.AllOf[1]},\n\t\t{\"/$defs/~1~0\", s.Defs[\"/~\"]},\n\t\t{\"/$defs/~01\", s.Defs[\"~1\"]},\n\t} {\n\t\tgot, err := dereferenceJSONPointer(s, tt.ptr)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif got != tt.want {\n\t\t\tt.Errorf(\"%s:\\ngot  %+v\\nwant %+v\", tt.ptr, got, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestDerefernceJSONPointerErrors(t *testing.T) {\n\ts := &Schema{\n\t\tType:     \"t\",\n\t\tItems:    &Schema{},\n\t\tRequired: []string{\"a\"},\n\t}\n\tfor _, tt := range []struct {\n\t\tptr  string\n\t\twant string // error must contain this string\n\t}{\n\t\t{\"x\", \"does not begin\"}, // parse error: no initial '/'\n\t\t{\"/minItems\", \"does not refer to a schema\"},\n\t\t{\"/minItems/x\", \"navigated to nil\"},\n\t\t{\"/required/-\", \"not supported\"},\n\t\t{\"/required/01\", \"leading zeroes\"},\n\t\t{\"/required/x\", \"invalid int\"},\n\t\t{\"/required/1\", \"out of bounds\"},\n\t\t{\"/properties/x\", \"no key\"},\n\t} {\n\t\t_, err := dereferenceJSONPointer(s, tt.ptr)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"%q: succeeded, want failure\", tt.ptr)\n\t\t} else if !strings.Contains(err.Error(), tt.want) {\n\t\t\tt.Errorf(\"%q: error is %q, which does not contain %q\", tt.ptr, err, tt.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/applicator.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/applicator\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Applicator vocabulary meta-schema\",\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"prefixItems\": { \"$ref\": \"#/$defs/schemaArray\" },\n        \"items\": { \"$dynamicRef\": \"#meta\" },\n        \"contains\": { \"$dynamicRef\": \"#meta\" },\n        \"additionalProperties\": { \"$dynamicRef\": \"#meta\" },\n        \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$dynamicRef\": \"#meta\" },\n            \"default\": {}\n        },\n        \"patternProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$dynamicRef\": \"#meta\" },\n            \"propertyNames\": { \"format\": \"regex\" },\n            \"default\": {}\n        },\n        \"dependentSchemas\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$dynamicRef\": \"#meta\" },\n            \"default\": {}\n        },\n        \"propertyNames\": { \"$dynamicRef\": \"#meta\" },\n        \"if\": { \"$dynamicRef\": \"#meta\" },\n        \"then\": { \"$dynamicRef\": \"#meta\" },\n        \"else\": { \"$dynamicRef\": \"#meta\" },\n        \"allOf\": { \"$ref\": \"#/$defs/schemaArray\" },\n        \"anyOf\": { \"$ref\": \"#/$defs/schemaArray\" },\n        \"oneOf\": { \"$ref\": \"#/$defs/schemaArray\" },\n        \"not\": { \"$dynamicRef\": \"#meta\" }\n    },\n    \"$defs\": {\n        \"schemaArray\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"items\": { \"$dynamicRef\": \"#meta\" }\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/content.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/content\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Content vocabulary meta-schema\",\n\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"contentEncoding\": { \"type\": \"string\" },\n        \"contentMediaType\": { \"type\": \"string\" },\n        \"contentSchema\": { \"$dynamicRef\": \"#meta\" }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/core.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/core\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Core vocabulary meta-schema\",\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"$id\": {\n            \"$ref\": \"#/$defs/uriReferenceString\",\n            \"$comment\": \"Non-empty fragments not allowed.\",\n            \"pattern\": \"^[^#]*#?$\"\n        },\n        \"$schema\": { \"$ref\": \"#/$defs/uriString\" },\n        \"$ref\": { \"$ref\": \"#/$defs/uriReferenceString\" },\n        \"$anchor\": { \"$ref\": \"#/$defs/anchorString\" },\n        \"$dynamicRef\": { \"$ref\": \"#/$defs/uriReferenceString\" },\n        \"$dynamicAnchor\": { \"$ref\": \"#/$defs/anchorString\" },\n        \"$vocabulary\": {\n            \"type\": \"object\",\n            \"propertyNames\": { \"$ref\": \"#/$defs/uriString\" },\n            \"additionalProperties\": {\n                \"type\": \"boolean\"\n            }\n        },\n        \"$comment\": {\n            \"type\": \"string\"\n        },\n        \"$defs\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$dynamicRef\": \"#meta\" }\n        }\n    },\n    \"$defs\": {\n        \"anchorString\": {\n            \"type\": \"string\",\n            \"pattern\": \"^[A-Za-z_][-A-Za-z0-9._]*$\"\n        },\n        \"uriString\": {\n            \"type\": \"string\",\n            \"format\": \"uri\"\n        },\n        \"uriReferenceString\": {\n            \"type\": \"string\",\n            \"format\": \"uri-reference\"\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/format-annotation.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/format-annotation\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Format vocabulary meta-schema for annotation results\",\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"format\": { \"type\": \"string\" }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/meta-data.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/meta-data\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Meta-data vocabulary meta-schema\",\n\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"description\": {\n            \"type\": \"string\"\n        },\n        \"default\": true,\n        \"deprecated\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"readOnly\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"writeOnly\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"examples\": {\n            \"type\": \"array\",\n            \"items\": true\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/unevaluated.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/unevaluated\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Unevaluated applicator vocabulary meta-schema\",\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"unevaluatedItems\": { \"$dynamicRef\": \"#meta\" },\n        \"unevaluatedProperties\": { \"$dynamicRef\": \"#meta\" }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/meta/validation.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/meta/validation\",\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Validation vocabulary meta-schema\",\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"type\": {\n            \"anyOf\": [\n                { \"$ref\": \"#/$defs/simpleTypes\" },\n                {\n                    \"type\": \"array\",\n                    \"items\": { \"$ref\": \"#/$defs/simpleTypes\" },\n                    \"minItems\": 1,\n                    \"uniqueItems\": true\n                }\n            ]\n        },\n        \"const\": true,\n        \"enum\": {\n            \"type\": \"array\",\n            \"items\": true\n        },\n        \"multipleOf\": {\n            \"type\": \"number\",\n            \"exclusiveMinimum\": 0\n        },\n        \"maximum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMaximum\": {\n            \"type\": \"number\"\n        },\n        \"minimum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMinimum\": {\n            \"type\": \"number\"\n        },\n        \"maxLength\": { \"$ref\": \"#/$defs/nonNegativeInteger\" },\n        \"minLength\": { \"$ref\": \"#/$defs/nonNegativeIntegerDefault0\" },\n        \"pattern\": {\n            \"type\": \"string\",\n            \"format\": \"regex\"\n        },\n        \"maxItems\": { \"$ref\": \"#/$defs/nonNegativeInteger\" },\n        \"minItems\": { \"$ref\": \"#/$defs/nonNegativeIntegerDefault0\" },\n        \"uniqueItems\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"maxContains\": { \"$ref\": \"#/$defs/nonNegativeInteger\" },\n        \"minContains\": {\n            \"$ref\": \"#/$defs/nonNegativeInteger\",\n            \"default\": 1\n        },\n        \"maxProperties\": { \"$ref\": \"#/$defs/nonNegativeInteger\" },\n        \"minProperties\": { \"$ref\": \"#/$defs/nonNegativeIntegerDefault0\" },\n        \"required\": { \"$ref\": \"#/$defs/stringArray\" },\n        \"dependentRequired\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"$ref\": \"#/$defs/stringArray\"\n            }\n        }\n    },\n    \"$defs\": {\n        \"nonNegativeInteger\": {\n            \"type\": \"integer\",\n            \"minimum\": 0\n        },\n        \"nonNegativeIntegerDefault0\": {\n            \"$ref\": \"#/$defs/nonNegativeInteger\",\n            \"default\": 0\n        },\n        \"simpleTypes\": {\n            \"enum\": [\n                \"array\",\n                \"boolean\",\n                \"integer\",\n                \"null\",\n                \"number\",\n                \"object\",\n                \"string\"\n            ]\n        },\n        \"stringArray\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" },\n            \"uniqueItems\": true,\n            \"default\": []\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/meta-schemas/draft2020-12/schema.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$vocabulary\": {\n        \"https://json-schema.org/draft/2020-12/vocab/core\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/applicator\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/unevaluated\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/validation\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/meta-data\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/format-annotation\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/content\": true\n    },\n    \"$dynamicAnchor\": \"meta\",\n\n    \"title\": \"Core and Validation specifications meta-schema\",\n    \"allOf\": [\n        {\"$ref\": \"meta/core\"},\n        {\"$ref\": \"meta/applicator\"},\n        {\"$ref\": \"meta/unevaluated\"},\n        {\"$ref\": \"meta/validation\"},\n        {\"$ref\": \"meta/meta-data\"},\n        {\"$ref\": \"meta/format-annotation\"},\n        {\"$ref\": \"meta/content\"}\n    ],\n    \"type\": [\"object\", \"boolean\"],\n    \"$comment\": \"This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.\",\n    \"properties\": {\n        \"definitions\": {\n            \"$comment\": \"\\\"definitions\\\" has been replaced by \\\"$defs\\\".\",\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$dynamicRef\": \"#meta\" },\n            \"deprecated\": true,\n            \"default\": {}\n        },\n        \"dependencies\": {\n            \"$comment\": \"\\\"dependencies\\\" has been split and replaced by \\\"dependentSchemas\\\" and \\\"dependentRequired\\\" in order to serve their differing semantics.\",\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    { \"$dynamicRef\": \"#meta\" },\n                    { \"$ref\": \"meta/validation#/$defs/stringArray\" }\n                ]\n            },\n            \"deprecated\": true,\n            \"default\": {}\n        },\n        \"$recursiveAnchor\": {\n            \"$comment\": \"\\\"$recursiveAnchor\\\" has been replaced by \\\"$dynamicAnchor\\\".\",\n            \"$ref\": \"meta/core#/$defs/anchorString\",\n            \"deprecated\": true\n        },\n        \"$recursiveRef\": {\n            \"$comment\": \"\\\"$recursiveRef\\\" has been replaced by \\\"$dynamicRef\\\".\",\n            \"$ref\": \"meta/core#/$defs/uriReferenceString\",\n            \"deprecated\": true\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/resolve.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file deals with preparing a schema for validation, including various checks,\n// optimizations, and the resolution of cross-schema references.\n\npackage jsonschema\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// A Resolved consists of a [Schema] along with associated information needed to\n// validate documents against it.\n// A Resolved has been validated against its meta-schema, and all its references\n// (the $ref and $dynamicRef keywords) have been resolved to their referenced Schemas.\n// Call [Schema.Resolve] to obtain a Resolved from a Schema.\ntype Resolved struct {\n\troot *Schema\n\t// map from $ids to their schemas\n\tresolvedURIs map[string]*Schema\n}\n\n// Schema returns the schema that was resolved.\n// It must not be modified.\nfunc (r *Resolved) Schema() *Schema { return r.root }\n\n// A Loader reads and unmarshals the schema at uri, if any.\ntype Loader func(uri *url.URL) (*Schema, error)\n\n// ResolveOptions are options for [Schema.Resolve].\ntype ResolveOptions struct {\n\t// BaseURI is the URI relative to which the root schema should be resolved.\n\t// If non-empty, must be an absolute URI (one that starts with a scheme).\n\t// It is resolved (in the URI sense; see [url.ResolveReference]) with root's\n\t// $id property.\n\t// If the resulting URI is not absolute, then the schema cannot contain\n\t// relative URI references.\n\tBaseURI string\n\t// Loader loads schemas that are referred to by a $ref but are not under the\n\t// root schema (remote references).\n\t// If nil, resolving a remote reference will return an error.\n\tLoader Loader\n\t// ValidateDefaults determines whether to validate values of \"default\" keywords\n\t// against their schemas.\n\t// The [JSON Schema specification] does not require this, but it is\n\t// recommended if defaults will be used.\n\t//\n\t// [JSON Schema specification]: https://json-schema.org/understanding-json-schema/reference/annotations\n\tValidateDefaults bool\n}\n\n// Resolve resolves all references within the schema and performs other tasks that\n// prepare the schema for validation.\n// If opts is nil, the default values are used.\nfunc (root *Schema) Resolve(opts *ResolveOptions) (*Resolved, error) {\n\t// There are up to five steps required to prepare a schema to validate.\n\t// 1. Load: read the schema from somewhere and unmarshal it.\n\t//    This schema (root) may have been loaded or created in memory, but other schemas that\n\t//    come into the picture in step 4 will be loaded by the given loader.\n\t// 2. Check: validate the schema against a meta-schema, and perform other well-formedness checks.\n\t//    Precompute some values along the way.\n\t// 3. Resolve URIs: determine the base URI of the root and all its subschemas, and\n\t//    resolve (in the URI sense) all identifiers and anchors with their bases. This step results\n\t//    in a map from URIs to schemas within root.\n\t// 4. Resolve references: all refs in the schemas are replaced with the schema they refer to.\n\t// 5. (Optional.) If opts.ValidateDefaults is true, validate the defaults.\n\tif root.path != \"\" {\n\t\treturn nil, fmt.Errorf(\"jsonschema: Resolve: %s already resolved\", root)\n\t}\n\tr := &resolver{loaded: map[string]*Resolved{}}\n\tif opts != nil {\n\t\tr.opts = *opts\n\t}\n\tvar base *url.URL\n\tif r.opts.BaseURI == \"\" {\n\t\tbase = &url.URL{} // so we can call ResolveReference on it\n\t} else {\n\t\tvar err error\n\t\tbase, err = url.Parse(r.opts.BaseURI)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parsing base URI: %w\", err)\n\t\t}\n\t}\n\n\tif r.opts.Loader == nil {\n\t\tr.opts.Loader = func(uri *url.URL) (*Schema, error) {\n\t\t\treturn nil, errors.New(\"cannot resolve remote schemas: no loader passed to Schema.Resolve\")\n\t\t}\n\t}\n\n\tresolved, err := r.resolve(root, base)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif r.opts.ValidateDefaults {\n\t\tif err := resolved.validateDefaults(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\t// TODO: before we return, throw away anything we don't need for validation.\n\treturn resolved, nil\n}\n\n// A resolver holds the state for resolution.\ntype resolver struct {\n\topts ResolveOptions\n\t// A cache of loaded and partly resolved schemas. (They may not have had their\n\t// refs resolved.) The cache ensures that the loader will never be called more\n\t// than once with the same URI, and that reference cycles are handled properly.\n\tloaded map[string]*Resolved\n}\n\nfunc (r *resolver) resolve(s *Schema, baseURI *url.URL) (*Resolved, error) {\n\tif baseURI.Fragment != \"\" {\n\t\treturn nil, fmt.Errorf(\"base URI %s must not have a fragment\", baseURI)\n\t}\n\tif err := s.check(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tm, err := resolveURIs(s, baseURI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\trs := &Resolved{root: s, resolvedURIs: m}\n\t// Remember the schema by both the URI we loaded it from and its canonical name,\n\t// which may differ if the schema has an $id.\n\t// We must set the map before calling resolveRefs, or ref cycles will cause unbounded recursion.\n\tr.loaded[baseURI.String()] = rs\n\tr.loaded[s.uri.String()] = rs\n\n\tif err := r.resolveRefs(rs); err != nil {\n\t\treturn nil, err\n\t}\n\treturn rs, nil\n}\n\nfunc (root *Schema) check() error {\n\t// Check for structural validity. Do this first and fail fast:\n\t// bad structure will cause other code to panic.\n\tif err := root.checkStructure(); err != nil {\n\t\treturn err\n\t}\n\n\tvar errs []error\n\treport := func(err error) { errs = append(errs, err) }\n\n\tfor ss := range root.all() {\n\t\tss.checkLocal(report)\n\t}\n\treturn errors.Join(errs...)\n}\n\n// checkStructure verifies that root and its subschemas form a tree.\n// It also assigns each schema a unique path, to improve error messages.\nfunc (root *Schema) checkStructure() error {\n\tvar check func(reflect.Value, []byte) error\n\tcheck = func(v reflect.Value, path []byte) error {\n\t\t// For the purpose of error messages, the root schema has path \"root\"\n\t\t// and other schemas' paths are their JSON Pointer from the root.\n\t\tp := \"root\"\n\t\tif len(path) > 0 {\n\t\t\tp = string(path)\n\t\t}\n\t\ts := v.Interface().(*Schema)\n\t\tif s == nil {\n\t\t\treturn fmt.Errorf(\"jsonschema: schema at %s is nil\", p)\n\t\t}\n\t\tif s.path != \"\" {\n\t\t\t// We've seen s before.\n\t\t\t// The schema graph at root is not a tree, but it needs to\n\t\t\t// be because we assume a unique parent when we store a schema's base\n\t\t\t// in the Schema. A cycle would also put Schema.all into an infinite\n\t\t\t// recursion.\n\t\t\treturn fmt.Errorf(\"jsonschema: schemas at %s do not form a tree; %s appears more than once (also at %s)\",\n\t\t\t\troot, s.path, p)\n\t\t}\n\t\ts.path = p\n\n\t\tfor _, info := range schemaFieldInfos {\n\t\t\tfv := v.Elem().FieldByIndex(info.sf.Index)\n\t\t\tswitch info.sf.Type {\n\t\t\tcase schemaType:\n\t\t\t\t// A field that contains an individual schema.\n\t\t\t\t// A nil is valid: it just means the field isn't present.\n\t\t\t\tif !fv.IsNil() {\n\t\t\t\t\tif err := check(fv, fmt.Appendf(path, \"/%s\", info.jsonName)); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase schemaSliceType:\n\t\t\t\tfor i := range fv.Len() {\n\t\t\t\t\tif err := check(fv.Index(i), fmt.Appendf(path, \"/%s/%d\", info.jsonName, i)); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase schemaMapType:\n\t\t\t\titer := fv.MapRange()\n\t\t\t\tfor iter.Next() {\n\t\t\t\t\tkey := escapeJSONPointerSegment(iter.Key().String())\n\t\t\t\t\tif err := check(iter.Value(), fmt.Appendf(path, \"/%s/%s\", info.jsonName, key)); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn check(reflect.ValueOf(root), make([]byte, 0, 256))\n}\n\n// checkLocal checks s for validity, independently of other schemas it may refer to.\n// Since checking a regexp involves compiling it, checkLocal saves those compiled regexps\n// in the schema for later use.\n// It appends the errors it finds to errs.\nfunc (s *Schema) checkLocal(report func(error)) {\n\taddf := func(format string, args ...any) {\n\t\tmsg := fmt.Sprintf(format, args...)\n\t\treport(fmt.Errorf(\"jsonschema.Schema: %s: %s\", s, msg))\n\t}\n\n\tif s == nil {\n\t\taddf(\"nil subschema\")\n\t\treturn\n\t}\n\tif err := s.basicChecks(); err != nil {\n\t\treport(err)\n\t\treturn\n\t}\n\n\t// TODO: validate the schema's properties,\n\t// ideally by jsonschema-validating it against the meta-schema.\n\n\t// Some properties are present so that Schemas can round-trip, but we do not\n\t// validate them.\n\t// Currently, it's just the $vocabulary property.\n\t// As a special case, we can validate the 2020-12 meta-schema.\n\tif s.Vocabulary != nil && s.Schema != draft202012 {\n\t\taddf(\"cannot validate a schema with $vocabulary\")\n\t}\n\n\t// Check and compile regexps.\n\tif s.Pattern != \"\" {\n\t\tre, err := regexp.Compile(s.Pattern)\n\t\tif err != nil {\n\t\t\taddf(\"pattern: %v\", err)\n\t\t} else {\n\t\t\ts.pattern = re\n\t\t}\n\t}\n\tif len(s.PatternProperties) > 0 {\n\t\ts.patternProperties = map[*regexp.Regexp]*Schema{}\n\t\tfor reString, subschema := range s.PatternProperties {\n\t\t\tre, err := regexp.Compile(reString)\n\t\t\tif err != nil {\n\t\t\t\taddf(\"patternProperties[%q]: %v\", reString, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ts.patternProperties[re] = subschema\n\t\t}\n\t}\n\n\t// Build a set of required properties, to avoid quadratic behavior when validating\n\t// a struct.\n\tif len(s.Required) > 0 {\n\t\ts.isRequired = map[string]bool{}\n\t\tfor _, r := range s.Required {\n\t\t\ts.isRequired[r] = true\n\t\t}\n\t}\n}\n\n// resolveURIs resolves the ids and anchors in all the schemas of root, relative\n// to baseURI.\n// See https://json-schema.org/draft/2020-12/json-schema-core#section-8.2, section\n// 8.2.1.\n\n// TODO(jba): dynamicAnchors (§8.2.2)\n//\n// Every schema has a base URI and a parent base URI.\n//\n// The parent base URI is the base URI of the lexically enclosing schema, or for\n// a root schema, the URI it was loaded from or the one supplied to [Schema.Resolve].\n//\n// If the schema has no $id property, the base URI of a schema is that of its parent.\n// If the schema does have an $id, it must be a URI, possibly relative. The schema's\n// base URI is the $id resolved (in the sense of [url.URL.ResolveReference]) against\n// the parent base.\n//\n// As an example, consider this schema loaded from http://a.com/root.json (quotes omitted):\n//\n//\t{\n//\t    allOf: [\n//\t        {$id: \"sub1.json\", minLength: 5},\n//\t        {$id: \"http://b.com\", minimum: 10},\n//\t        {not: {maximum: 20}}\n//\t    ]\n//\t}\n//\n// The base URIs are as follows. Schema locations are expressed in the JSON Pointer notation.\n//\n//\tschema         base URI\n//\troot           http://a.com/root.json\n//\tallOf/0        http://a.com/sub1.json\n//\tallOf/1        http://b.com (absolute $id; doesn't matter that it's not under the loaded URI)\n//\tallOf/2        http://a.com/root.json (inherited from parent)\n//\tallOf/2/not    http://a.com/root.json (inherited from parent)\nfunc resolveURIs(root *Schema, baseURI *url.URL) (map[string]*Schema, error) {\n\tresolvedURIs := map[string]*Schema{}\n\n\tvar resolve func(s, base *Schema) error\n\tresolve = func(s, base *Schema) error {\n\t\t// ids are scoped to the root.\n\t\tif s.ID != \"\" {\n\t\t\t// A non-empty ID establishes a new base.\n\t\t\tidURI, err := url.Parse(s.ID)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif idURI.Fragment != \"\" {\n\t\t\t\treturn fmt.Errorf(\"$id %s must not have a fragment\", s.ID)\n\t\t\t}\n\t\t\t// The base URI for this schema is its $id resolved against the parent base.\n\t\t\ts.uri = base.uri.ResolveReference(idURI)\n\t\t\tif !s.uri.IsAbs() {\n\t\t\t\treturn fmt.Errorf(\"$id %s does not resolve to an absolute URI (base is %s)\", s.ID, base.uri)\n\t\t\t}\n\t\t\tresolvedURIs[s.uri.String()] = s\n\t\t\tbase = s // needed for anchors\n\t\t}\n\t\ts.base = base\n\n\t\t// Anchors and dynamic anchors are URI fragments that are scoped to their base.\n\t\t// We treat them as keys in a map stored within the schema.\n\t\tsetAnchor := func(anchor string, dynamic bool) error {\n\t\t\tif anchor != \"\" {\n\t\t\t\tif _, ok := base.anchors[anchor]; ok {\n\t\t\t\t\treturn fmt.Errorf(\"duplicate anchor %q in %s\", anchor, base.uri)\n\t\t\t\t}\n\t\t\t\tif base.anchors == nil {\n\t\t\t\t\tbase.anchors = map[string]anchorInfo{}\n\t\t\t\t}\n\t\t\t\tbase.anchors[anchor] = anchorInfo{s, dynamic}\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\tsetAnchor(s.Anchor, false)\n\t\tsetAnchor(s.DynamicAnchor, true)\n\n\t\tfor c := range s.children() {\n\t\t\tif err := resolve(c, base); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Set the root URI to the base for now. If the root has an $id, this will change.\n\troot.uri = baseURI\n\t// The original base, even if changed, is still a valid way to refer to the root.\n\tresolvedURIs[baseURI.String()] = root\n\tif err := resolve(root, root); err != nil {\n\t\treturn nil, err\n\t}\n\treturn resolvedURIs, nil\n}\n\n// resolveRefs replaces every ref in the schemas with the schema it refers to.\n// A reference that doesn't resolve within the schema may refer to some other schema\n// that needs to be loaded.\nfunc (r *resolver) resolveRefs(rs *Resolved) error {\n\tfor s := range rs.root.all() {\n\t\tif s.Ref != \"\" {\n\t\t\trefSchema, _, err := r.resolveRef(rs, s, s.Ref)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// Whether or not the anchor referred to by $ref fragment is dynamic,\n\t\t\t// the ref still treats it lexically.\n\t\t\ts.resolvedRef = refSchema\n\t\t}\n\t\tif s.DynamicRef != \"\" {\n\t\t\trefSchema, frag, err := r.resolveRef(rs, s, s.DynamicRef)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif frag != \"\" {\n\t\t\t\t// The dynamic ref's fragment points to a dynamic anchor.\n\t\t\t\t// We must resolve the fragment at validation time.\n\t\t\t\ts.dynamicRefAnchor = frag\n\t\t\t} else {\n\t\t\t\t// There is no dynamic anchor in the lexically referenced schema,\n\t\t\t\t// so the dynamic ref behaves like a lexical ref.\n\t\t\t\ts.resolvedDynamicRef = refSchema\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// resolveRef resolves the reference ref, which is either s.Ref or s.DynamicRef.\nfunc (r *resolver) resolveRef(rs *Resolved, s *Schema, ref string) (_ *Schema, dynamicFragment string, err error) {\n\trefURI, err := url.Parse(ref)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\t// URI-resolve the ref against the current base URI to get a complete URI.\n\trefURI = s.base.uri.ResolveReference(refURI)\n\t// The non-fragment part of a ref URI refers to the base URI of some schema.\n\t// This part is the same for dynamic refs too: their non-fragment part resolves\n\t// lexically.\n\tu := *refURI\n\tu.Fragment = \"\"\n\tfraglessRefURI := &u\n\t// Look it up locally.\n\treferencedSchema := rs.resolvedURIs[fraglessRefURI.String()]\n\tif referencedSchema == nil {\n\t\t// The schema is remote. Maybe we've already loaded it.\n\t\t// We assume that the non-fragment part of refURI refers to a top-level schema\n\t\t// document. That is, we don't support the case exemplified by\n\t\t// http://foo.com/bar.json/baz, where the document is in bar.json and\n\t\t// the reference points to a subschema within it.\n\t\t// TODO: support that case.\n\t\tif lrs := r.loaded[fraglessRefURI.String()]; lrs != nil {\n\t\t\treferencedSchema = lrs.root\n\t\t} else {\n\t\t\t// Try to load the schema.\n\t\t\tls, err := r.opts.Loader(fraglessRefURI)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", fmt.Errorf(\"loading %s: %w\", fraglessRefURI, err)\n\t\t\t}\n\t\t\tlrs, err := r.resolve(ls, fraglessRefURI)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", err\n\t\t\t}\n\t\t\treferencedSchema = lrs.root\n\t\t\tassert(referencedSchema != nil, \"nil referenced schema\")\n\t\t}\n\t}\n\n\tfrag := refURI.Fragment\n\t// Look up frag in refSchema.\n\t// frag is either a JSON Pointer or the name of an anchor.\n\t// A JSON Pointer is either the empty string or begins with a '/',\n\t// whereas anchors are always non-empty strings that don't contain slashes.\n\tif frag != \"\" && !strings.HasPrefix(frag, \"/\") {\n\t\tinfo, found := referencedSchema.anchors[frag]\n\t\tif !found {\n\t\t\treturn nil, \"\", fmt.Errorf(\"no anchor %q in %s\", frag, s)\n\t\t}\n\t\tif info.dynamic {\n\t\t\tdynamicFragment = frag\n\t\t}\n\t\treturn info.schema, dynamicFragment, nil\n\t}\n\t// frag is a JSON Pointer.\n\ts, err = dereferenceJSONPointer(referencedSchema, frag)\n\treturn s, \"\", err\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/resolve_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"errors\"\n\t\"maps\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestSchemaStructure(t *testing.T) {\n\tcheck := func(s *Schema, want string) {\n\t\tt.Helper()\n\t\terr := s.checkStructure()\n\t\tif err == nil || !strings.Contains(err.Error(), want) {\n\t\t\tt.Errorf(\"checkStructure returned error %q, want %q\", err, want)\n\t\t}\n\t}\n\n\tdag := &Schema{Type: \"number\"}\n\tdag = &Schema{Items: dag, Contains: dag}\n\tcheck(dag, \"do not form a tree\")\n\n\ttree := &Schema{Type: \"number\"}\n\ttree.Items = tree\n\tcheck(tree, \"do not form a tree\")\n\n\tsliceNil := &Schema{PrefixItems: []*Schema{nil}}\n\tcheck(sliceNil, \"is nil\")\n\n\tsliceMap := &Schema{Properties: map[string]*Schema{\"a\": nil}}\n\tcheck(sliceMap, \"is nil\")\n}\n\nfunc TestCheckLocal(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\ts    *Schema\n\t\twant string // error must be non-nil and match this regexp\n\t}{\n\t\t{\n\t\t\t&Schema{Pattern: \"][\"},\n\t\t\t\"regexp\",\n\t\t},\n\t\t{\n\t\t\t&Schema{PatternProperties: map[string]*Schema{\"*\": {}}},\n\t\t\t\"regexp\",\n\t\t},\n\t} {\n\t\t_, err := tt.s.Resolve(nil)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"%s: unexpectedly passed\", tt.s.json())\n\t\t\tcontinue\n\t\t}\n\t\tif !regexp.MustCompile(tt.want).MatchString(err.Error()) {\n\t\t\tt.Errorf(\"checkLocal returned error\\n%q\\nwanted it to match\\n%s\\nregexp: %s\",\n\t\t\t\ttt.s.json(), err, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestPaths(t *testing.T) {\n\t// CheckStructure should assign paths to schemas.\n\t// This test also verifies that Schema.all visits maps in sorted order.\n\troot := &Schema{\n\t\tType:        \"string\",\n\t\tPrefixItems: []*Schema{{Type: \"int\"}, {Items: &Schema{Type: \"null\"}}},\n\t\tContains: &Schema{Properties: map[string]*Schema{\n\t\t\t\"~1\": {Type: \"boolean\"},\n\t\t\t\"p\":  {},\n\t\t}},\n\t}\n\n\ttype item struct {\n\t\ts *Schema\n\t\tp string\n\t}\n\twant := []item{\n\t\t{root, \"root\"},\n\t\t{root.Contains, \"/contains\"},\n\t\t{root.Contains.Properties[\"p\"], \"/contains/properties/p\"},\n\t\t{root.Contains.Properties[\"~1\"], \"/contains/properties/~01\"},\n\t\t{root.PrefixItems[0], \"/prefixItems/0\"},\n\t\t{root.PrefixItems[1], \"/prefixItems/1\"},\n\t\t{root.PrefixItems[1].Items, \"/prefixItems/1/items\"},\n\t}\n\tif err := root.checkStructure(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar got []item\n\tfor s := range root.all() {\n\t\tgot = append(got, item{s, s.path})\n\t}\n\tif !slices.Equal(got, want) {\n\t\tt.Errorf(\"\\ngot  %v\\nwant %v\", got, want)\n\t}\n}\n\nfunc TestResolveURIs(t *testing.T) {\n\tfor _, baseURI := range []string{\"\", \"http://a.com\"} {\n\t\tt.Run(baseURI, func(t *testing.T) {\n\t\t\troot := &Schema{\n\t\t\t\tID: \"http://b.com\",\n\t\t\t\tItems: &Schema{\n\t\t\t\t\tID: \"/foo.json\",\n\t\t\t\t},\n\t\t\t\tContains: &Schema{\n\t\t\t\t\tID:            \"/bar.json\",\n\t\t\t\t\tAnchor:        \"a\",\n\t\t\t\t\tDynamicAnchor: \"da\",\n\t\t\t\t\tItems: &Schema{\n\t\t\t\t\t\tAnchor: \"b\",\n\t\t\t\t\t\tItems: &Schema{\n\t\t\t\t\t\t\t// An ID shouldn't be a query param, but this tests\n\t\t\t\t\t\t\t// resolving an ID with its parent.\n\t\t\t\t\t\t\tID:     \"?items\",\n\t\t\t\t\t\t\tAnchor: \"c\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tbase, err := url.Parse(baseURI)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tgot, err := resolveURIs(root, base)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\twantIDs := map[string]*Schema{\n\t\t\t\tbaseURI:                       root,\n\t\t\t\t\"http://b.com/foo.json\":       root.Items,\n\t\t\t\t\"http://b.com/bar.json\":       root.Contains,\n\t\t\t\t\"http://b.com/bar.json?items\": root.Contains.Items.Items,\n\t\t\t}\n\t\t\tif baseURI != root.ID {\n\t\t\t\twantIDs[root.ID] = root\n\t\t\t}\n\t\t\twantAnchors := map[*Schema]map[string]anchorInfo{\n\t\t\t\troot.Contains: {\n\t\t\t\t\t\"a\":  anchorInfo{root.Contains, false},\n\t\t\t\t\t\"da\": anchorInfo{root.Contains, true},\n\t\t\t\t\t\"b\":  anchorInfo{root.Contains.Items, false},\n\t\t\t\t},\n\t\t\t\troot.Contains.Items.Items: {\n\t\t\t\t\t\"c\": anchorInfo{root.Contains.Items.Items, false},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tgotKeys := slices.Sorted(maps.Keys(got))\n\t\t\twantKeys := slices.Sorted(maps.Keys(wantIDs))\n\t\t\tif !slices.Equal(gotKeys, wantKeys) {\n\t\t\t\tt.Errorf(\"ID keys:\\ngot  %q\\nwant %q\", gotKeys, wantKeys)\n\t\t\t}\n\t\t\tif !maps.Equal(got, wantIDs) {\n\t\t\t\tt.Errorf(\"IDs:\\ngot  %+v\\n\\nwant %+v\", got, wantIDs)\n\t\t\t}\n\t\t\tfor s := range root.all() {\n\t\t\t\tif want := wantAnchors[s]; want != nil {\n\t\t\t\t\tif got := s.anchors; !maps.Equal(got, want) {\n\t\t\t\t\t\tt.Errorf(\"anchors:\\ngot  %+v\\n\\nwant %+v\", got, want)\n\t\t\t\t\t}\n\t\t\t\t} else if s.anchors != nil {\n\t\t\t\t\tt.Errorf(\"non-nil anchors for %s\", s)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestRefCycle(t *testing.T) {\n\t// Verify that cycles of refs are OK.\n\t// The test suite doesn't check this, surprisingly.\n\tschemas := map[string]*Schema{\n\t\t\"root\": {Ref: \"a\"},\n\t\t\"a\":    {Ref: \"b\"},\n\t\t\"b\":    {Ref: \"a\"},\n\t}\n\n\tloader := func(uri *url.URL) (*Schema, error) {\n\t\ts, ok := schemas[uri.Path[1:]]\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"not found\")\n\t\t}\n\t\treturn s, nil\n\t}\n\n\trs, err := schemas[\"root\"].Resolve(&ResolveOptions{Loader: loader})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcheck := func(s *Schema, key string) {\n\t\tt.Helper()\n\t\tif s.resolvedRef != schemas[key] {\n\t\t\tt.Errorf(\"%s resolvedRef != schemas[%q]\", s.json(), key)\n\t\t}\n\t}\n\n\tcheck(rs.root, \"a\")\n\tcheck(schemas[\"a\"], \"b\")\n\tcheck(schemas[\"b\"], \"a\")\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/schema.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"iter\"\n\t\"maps\"\n\t\"math\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\n// A Schema is a JSON schema object.\n// It corresponds to the 2020-12 draft, as described in https://json-schema.org/draft/2020-12,\n// specifically:\n// - https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01\n// - https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01\n//\n// A Schema value may have non-zero values for more than one field:\n// all relevant non-zero fields are used for validation.\n// There is one exception to provide more Go type-safety: the Type and Types fields\n// are mutually exclusive.\n//\n// Since this struct is a Go representation of a JSON value, it inherits JSON's\n// distinction between nil and empty. Nil slices and maps are considered absent,\n// but empty ones are present and affect validation. For example,\n//\n//\tSchema{Enum: nil}\n//\n// is equivalent to an empty schema, so it validates every instance. But\n//\n//\tSchema{Enum: []any{}}\n//\n// requires equality to some slice element, so it vacuously rejects every instance.\ntype Schema struct {\n\t// core\n\tID      string             `json:\"$id,omitempty\"`\n\tSchema  string             `json:\"$schema,omitempty\"`\n\tRef     string             `json:\"$ref,omitempty\"`\n\tComment string             `json:\"$comment,omitempty\"`\n\tDefs    map[string]*Schema `json:\"$defs,omitempty\"`\n\t// definitions is deprecated but still allowed. It is a synonym for $defs.\n\tDefinitions map[string]*Schema `json:\"definitions,omitempty\"`\n\n\tAnchor        string          `json:\"$anchor,omitempty\"`\n\tDynamicAnchor string          `json:\"$dynamicAnchor,omitempty\"`\n\tDynamicRef    string          `json:\"$dynamicRef,omitempty\"`\n\tVocabulary    map[string]bool `json:\"$vocabulary,omitempty\"`\n\n\t// metadata\n\tTitle       string          `json:\"title,omitempty\"`\n\tDescription string          `json:\"description,omitempty\"`\n\tDefault     json.RawMessage `json:\"default,omitempty\"`\n\tDeprecated  bool            `json:\"deprecated,omitempty\"`\n\tReadOnly    bool            `json:\"readOnly,omitempty\"`\n\tWriteOnly   bool            `json:\"writeOnly,omitempty\"`\n\tExamples    []any           `json:\"examples,omitempty\"`\n\n\t// validation\n\t// Use Type for a single type, or Types for multiple types; never both.\n\tType  string   `json:\"-\"`\n\tTypes []string `json:\"-\"`\n\tEnum  []any    `json:\"enum,omitempty\"`\n\t// Const is *any because a JSON null (Go nil) is a valid value.\n\tConst            *any     `json:\"const,omitempty\"`\n\tMultipleOf       *float64 `json:\"multipleOf,omitempty\"`\n\tMinimum          *float64 `json:\"minimum,omitempty\"`\n\tMaximum          *float64 `json:\"maximum,omitempty\"`\n\tExclusiveMinimum *float64 `json:\"exclusiveMinimum,omitempty\"`\n\tExclusiveMaximum *float64 `json:\"exclusiveMaximum,omitempty\"`\n\tMinLength        *int     `json:\"minLength,omitempty\"`\n\tMaxLength        *int     `json:\"maxLength,omitempty\"`\n\tPattern          string   `json:\"pattern,omitempty\"`\n\n\t// arrays\n\tPrefixItems      []*Schema `json:\"prefixItems,omitempty\"`\n\tItems            *Schema   `json:\"items,omitempty\"`\n\tMinItems         *int      `json:\"minItems,omitempty\"`\n\tMaxItems         *int      `json:\"maxItems,omitempty\"`\n\tAdditionalItems  *Schema   `json:\"additionalItems,omitempty\"`\n\tUniqueItems      bool      `json:\"uniqueItems,omitempty\"`\n\tContains         *Schema   `json:\"contains,omitempty\"`\n\tMinContains      *int      `json:\"minContains,omitempty\"` // *int, not int: default is 1, not 0\n\tMaxContains      *int      `json:\"maxContains,omitempty\"`\n\tUnevaluatedItems *Schema   `json:\"unevaluatedItems,omitempty\"`\n\n\t// objects\n\tMinProperties         *int                `json:\"minProperties,omitempty\"`\n\tMaxProperties         *int                `json:\"maxProperties,omitempty\"`\n\tRequired              []string            `json:\"required,omitempty\"`\n\tDependentRequired     map[string][]string `json:\"dependentRequired,omitempty\"`\n\tProperties            map[string]*Schema  `json:\"properties,omitempty\"`\n\tPatternProperties     map[string]*Schema  `json:\"patternProperties,omitempty\"`\n\tAdditionalProperties  *Schema             `json:\"additionalProperties,omitempty\"`\n\tPropertyNames         *Schema             `json:\"propertyNames,omitempty\"`\n\tUnevaluatedProperties *Schema             `json:\"unevaluatedProperties,omitempty\"`\n\n\t// logic\n\tAllOf []*Schema `json:\"allOf,omitempty\"`\n\tAnyOf []*Schema `json:\"anyOf,omitempty\"`\n\tOneOf []*Schema `json:\"oneOf,omitempty\"`\n\tNot   *Schema   `json:\"not,omitempty\"`\n\n\t// conditional\n\tIf               *Schema            `json:\"if,omitempty\"`\n\tThen             *Schema            `json:\"then,omitempty\"`\n\tElse             *Schema            `json:\"else,omitempty\"`\n\tDependentSchemas map[string]*Schema `json:\"dependentSchemas,omitempty\"`\n\n\t// other\n\t// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.8\n\tContentEncoding  string  `json:\"contentEncoding,omitempty\"`\n\tContentMediaType string  `json:\"contentMediaType,omitempty\"`\n\tContentSchema    *Schema `json:\"contentSchema,omitempty\"`\n\n\t// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7\n\tFormat string `json:\"format,omitempty\"`\n\n\t// computed fields\n\n\t// This schema's base schema.\n\t// If the schema is the root or has an ID, its base is itself.\n\t// Otherwise, its base is the innermost enclosing schema whose base\n\t// is itself.\n\t// Intuitively, a base schema is one that can be referred to with a\n\t// fragmentless URI.\n\tbase *Schema\n\n\t// The URI for the schema, if it is the root or has an ID.\n\t// Otherwise nil.\n\t// Invariants:\n\t//   s.base.uri != nil.\n\t//   s.base == s <=> s.uri != nil\n\turi *url.URL\n\n\t// The JSON Pointer path from the root schema to here.\n\t// Used in errors.\n\tpath string\n\n\t// The schema to which Ref refers.\n\tresolvedRef *Schema\n\n\t// If the schema has a dynamic ref, exactly one of the next two fields\n\t// will be non-zero after successful resolution.\n\t// The schema to which the dynamic ref refers when it acts lexically.\n\tresolvedDynamicRef *Schema\n\t// The anchor to look up on the stack when the dynamic ref acts dynamically.\n\tdynamicRefAnchor string\n\n\t// Map from anchors to subschemas.\n\tanchors map[string]anchorInfo\n\n\t// compiled regexps\n\tpattern           *regexp.Regexp\n\tpatternProperties map[*regexp.Regexp]*Schema\n\n\t// the set of required properties\n\tisRequired map[string]bool\n}\n\n// falseSchema returns a new Schema tree that fails to validate any value.\nfunc falseSchema() *Schema {\n\treturn &Schema{Not: &Schema{}}\n}\n\n// anchorInfo records the subschema to which an anchor refers, and whether\n// the anchor keyword is $anchor or $dynamicAnchor.\ntype anchorInfo struct {\n\tschema  *Schema\n\tdynamic bool\n}\n\n// String returns a short description of the schema.\nfunc (s *Schema) String() string {\n\tif s.uri != nil {\n\t\tif u := s.uri.String(); u != \"\" {\n\t\t\treturn u\n\t\t}\n\t}\n\tif a := cmp.Or(s.Anchor, s.DynamicAnchor); a != \"\" {\n\t\treturn fmt.Sprintf(\"%q, anchor %s\", s.base.uri.String(), a)\n\t}\n\tif s.path != \"\" {\n\t\treturn s.path\n\t}\n\treturn \"<anonymous schema>\"\n}\n\n// ResolvedRef returns the Schema to which this schema's $ref keyword\n// refers, or nil if it doesn't have a $ref.\n// It returns nil if this schema has not been resolved, meaning that\n// [Schema.Resolve] was called on it or one of its ancestors.\nfunc (s *Schema) ResolvedRef() *Schema {\n\treturn s.resolvedRef\n}\n\nfunc (s *Schema) basicChecks() error {\n\tif s.Type != \"\" && s.Types != nil {\n\t\treturn errors.New(\"both Type and Types are set; at most one should be\")\n\t}\n\tif s.Defs != nil && s.Definitions != nil {\n\t\treturn errors.New(\"both Defs and Definitions are set; at most one should be\")\n\t}\n\treturn nil\n}\n\ntype schemaWithoutMethods Schema // doesn't implement json.{Unm,M}arshaler\n\nfunc (s *Schema) MarshalJSON() ([]byte, error) {\n\tif err := s.basicChecks(); err != nil {\n\t\treturn nil, err\n\t}\n\t// Marshal either Type or Types as \"type\".\n\tvar typ any\n\tswitch {\n\tcase s.Type != \"\":\n\t\ttyp = s.Type\n\tcase s.Types != nil:\n\t\ttyp = s.Types\n\t}\n\tms := struct {\n\t\tType any `json:\"type,omitempty\"`\n\t\t*schemaWithoutMethods\n\t}{\n\t\tType:                 typ,\n\t\tschemaWithoutMethods: (*schemaWithoutMethods)(s),\n\t}\n\treturn json.Marshal(ms)\n}\n\nfunc (s *Schema) UnmarshalJSON(data []byte) error {\n\t// A JSON boolean is a valid schema.\n\tvar b bool\n\tif err := json.Unmarshal(data, &b); err == nil {\n\t\tif b {\n\t\t\t// true is the empty schema, which validates everything.\n\t\t\t*s = Schema{}\n\t\t} else {\n\t\t\t// false is the schema that validates nothing.\n\t\t\t*s = *falseSchema()\n\t\t}\n\t\treturn nil\n\t}\n\n\tms := struct {\n\t\tType          json.RawMessage `json:\"type,omitempty\"`\n\t\tConst         json.RawMessage `json:\"const,omitempty\"`\n\t\tMinLength     *integer        `json:\"minLength,omitempty\"`\n\t\tMaxLength     *integer        `json:\"maxLength,omitempty\"`\n\t\tMinItems      *integer        `json:\"minItems,omitempty\"`\n\t\tMaxItems      *integer        `json:\"maxItems,omitempty\"`\n\t\tMinProperties *integer        `json:\"minProperties,omitempty\"`\n\t\tMaxProperties *integer        `json:\"maxProperties,omitempty\"`\n\t\tMinContains   *integer        `json:\"minContains,omitempty\"`\n\t\tMaxContains   *integer        `json:\"maxContains,omitempty\"`\n\n\t\t*schemaWithoutMethods\n\t}{\n\t\tschemaWithoutMethods: (*schemaWithoutMethods)(s),\n\t}\n\tif err := json.Unmarshal(data, &ms); err != nil {\n\t\treturn err\n\t}\n\t// Unmarshal \"type\" as either Type or Types.\n\tvar err error\n\tif len(ms.Type) > 0 {\n\t\tswitch ms.Type[0] {\n\t\tcase '\"':\n\t\t\terr = json.Unmarshal(ms.Type, &s.Type)\n\t\tcase '[':\n\t\t\terr = json.Unmarshal(ms.Type, &s.Types)\n\t\tdefault:\n\t\t\terr = fmt.Errorf(`invalid value for \"type\": %q`, ms.Type)\n\t\t}\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tunmarshalAnyPtr := func(p **any, raw json.RawMessage) error {\n\t\tif len(raw) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\tif bytes.Equal(raw, []byte(\"null\")) {\n\t\t\t*p = new(any)\n\t\t\treturn nil\n\t\t}\n\t\treturn json.Unmarshal(raw, p)\n\t}\n\n\t// Setting Const to a pointer to null will marshal properly, but won't\n\t// unmarshal: the *any is set to nil, not a pointer to nil.\n\tif err := unmarshalAnyPtr(&s.Const, ms.Const); err != nil {\n\t\treturn err\n\t}\n\n\tset := func(dst **int, src *integer) {\n\t\tif src != nil {\n\t\t\t*dst = Ptr(int(*src))\n\t\t}\n\t}\n\n\tset(&s.MinLength, ms.MinLength)\n\tset(&s.MaxLength, ms.MaxLength)\n\tset(&s.MinItems, ms.MinItems)\n\tset(&s.MaxItems, ms.MaxItems)\n\tset(&s.MinProperties, ms.MinProperties)\n\tset(&s.MaxProperties, ms.MaxProperties)\n\tset(&s.MinContains, ms.MinContains)\n\tset(&s.MaxContains, ms.MaxContains)\n\n\treturn nil\n}\n\ntype integer int32 // for the integer-valued fields of Schema\n\nfunc (ip *integer) UnmarshalJSON(data []byte) error {\n\tif len(data) == 0 {\n\t\t// nothing to do\n\t\treturn nil\n\t}\n\t// If there is a decimal point, src is a floating-point number.\n\tvar i int64\n\tif bytes.ContainsRune(data, '.') {\n\t\tvar f float64\n\t\tif err := json.Unmarshal(data, &f); err != nil {\n\t\t\treturn errors.New(\"not a number\")\n\t\t}\n\t\ti = int64(f)\n\t\tif float64(i) != f {\n\t\t\treturn errors.New(\"not an integer value\")\n\t\t}\n\t} else {\n\t\tif err := json.Unmarshal(data, &i); err != nil {\n\t\t\treturn errors.New(\"cannot be unmarshaled into an int\")\n\t\t}\n\t}\n\t// Ensure behavior is the same on both 32-bit and 64-bit systems.\n\tif i < math.MinInt32 || i > math.MaxInt32 {\n\t\treturn errors.New(\"integer is out of range\")\n\t}\n\t*ip = integer(i)\n\treturn nil\n}\n\n// Ptr returns a pointer to a new variable whose value is x.\nfunc Ptr[T any](x T) *T { return &x }\n\n// every applies f preorder to every schema under s including s.\n// The second argument to f is the path to the schema appended to the argument path.\n// It stops when f returns false.\nfunc (s *Schema) every(f func(*Schema) bool) bool {\n\treturn f(s) && s.everyChild(func(s *Schema) bool { return s.every(f) })\n}\n\n// everyChild reports whether f is true for every immediate child schema of s.\nfunc (s *Schema) everyChild(f func(*Schema) bool) bool {\n\tv := reflect.ValueOf(s)\n\tfor _, info := range schemaFieldInfos {\n\t\tfv := v.Elem().FieldByIndex(info.sf.Index)\n\t\tswitch info.sf.Type {\n\t\tcase schemaType:\n\t\t\t// A field that contains an individual schema. A nil is valid: it just means the field isn't present.\n\t\t\tc := fv.Interface().(*Schema)\n\t\t\tif c != nil && !f(c) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\tcase schemaSliceType:\n\t\t\tslice := fv.Interface().([]*Schema)\n\t\t\tfor _, c := range slice {\n\t\t\t\tif !f(c) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase schemaMapType:\n\t\t\t// Sort keys for determinism.\n\t\t\tm := fv.Interface().(map[string]*Schema)\n\t\t\tfor _, k := range slices.Sorted(maps.Keys(m)) {\n\t\t\t\tif !f(m[k]) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n// all wraps every in an iterator.\nfunc (s *Schema) all() iter.Seq[*Schema] {\n\treturn func(yield func(*Schema) bool) { s.every(yield) }\n}\n\n// children wraps everyChild in an iterator.\nfunc (s *Schema) children() iter.Seq[*Schema] {\n\treturn func(yield func(*Schema) bool) { s.everyChild(yield) }\n}\n\nvar (\n\tschemaType      = reflect.TypeFor[*Schema]()\n\tschemaSliceType = reflect.TypeFor[[]*Schema]()\n\tschemaMapType   = reflect.TypeFor[map[string]*Schema]()\n)\n\ntype structFieldInfo struct {\n\tsf       reflect.StructField\n\tjsonName string\n}\n\nvar (\n\t// the visible fields of Schema that have a JSON name, sorted by that name\n\tschemaFieldInfos []structFieldInfo\n\t// map from JSON name to field\n\tschemaFieldMap = map[string]reflect.StructField{}\n)\n\nfunc init() {\n\tfor _, sf := range reflect.VisibleFields(reflect.TypeFor[Schema]()) {\n\t\tinfo := util.FieldJSONInfo(sf)\n\t\tif !info.Omit {\n\t\t\tschemaFieldInfos = append(schemaFieldInfos, structFieldInfo{sf, info.Name})\n\t\t}\n\t}\n\tslices.SortFunc(schemaFieldInfos, func(i1, i2 structFieldInfo) int {\n\t\treturn cmp.Compare(i1.jsonName, i2.jsonName)\n\t})\n\tfor _, info := range schemaFieldInfos {\n\t\tschemaFieldMap[info.jsonName] = info.sf\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/schema_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"regexp\"\n\t\"testing\"\n)\n\nfunc TestGoRoundTrip(t *testing.T) {\n\t// Verify that Go representations round-trip.\n\tfor _, s := range []*Schema{\n\t\t{Type: \"null\"},\n\t\t{Types: []string{\"null\", \"number\"}},\n\t\t{Type: \"string\", MinLength: Ptr(20)},\n\t\t{Minimum: Ptr(20.0)},\n\t\t{Items: &Schema{Type: \"integer\"}},\n\t\t{Const: Ptr(any(0))},\n\t\t{Const: Ptr(any(nil))},\n\t\t{Const: Ptr(any([]int{}))},\n\t\t{Const: Ptr(any(map[string]any{}))},\n\t\t{Default: mustMarshal(1)},\n\t\t{Default: mustMarshal(nil)},\n\t} {\n\t\tdata, err := json.Marshal(s)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tvar got *Schema\n\t\tmustUnmarshal(t, data, &got)\n\t\tif !Equal(got, s) {\n\t\t\tt.Errorf(\"got %s, want %s\", got.json(), s.json())\n\t\t\tif got.Const != nil && s.Const != nil {\n\t\t\t\tt.Logf(\"Consts: got %#v (%[1]T), want %#v (%[2]T)\", *got.Const, *s.Const)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestJSONRoundTrip(t *testing.T) {\n\t// Verify that JSON texts for schemas marshal into equivalent forms.\n\t// We don't expect everything to round-trip perfectly. For example, \"true\" and \"false\"\n\t// will turn into their object equivalents.\n\t// But most things should.\n\t// Some of these cases test Schema.{UnM,M}arshalJSON.\n\t// Most of others follow from the behavior of encoding/json, but they are still\n\t// valuable as regression tests of this package's behavior.\n\tfor _, tt := range []struct {\n\t\tin, want string\n\t}{\n\t\t{`true`, `{}`}, // boolean schemas become object schemas\n\t\t{`false`, `{\"not\":{}}`},\n\t\t{`{\"type\":\"\", \"enum\":null}`, `{}`}, // empty fields are omitted\n\t\t{`{\"minimum\":1}`, `{\"minimum\":1}`},\n\t\t{`{\"minimum\":1.0}`, `{\"minimum\":1}`},     // floating-point integers lose their fractional part\n\t\t{`{\"minLength\":1.0}`, `{\"minLength\":1}`}, // some floats are unmarshaled into ints, but you can't tell\n\t\t{\n\t\t\t// map keys are sorted\n\t\t\t`{\"$vocabulary\":{\"b\":true, \"a\":false}}`,\n\t\t\t`{\"$vocabulary\":{\"a\":false,\"b\":true}}`,\n\t\t},\n\t\t{`{\"unk\":0}`, `{}`}, // unknown fields are dropped, unfortunately\n\t} {\n\t\tvar s Schema\n\t\tmustUnmarshal(t, []byte(tt.in), &s)\n\t\tdata, err := json.Marshal(s)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif got := string(data); got != tt.want {\n\t\t\tt.Errorf(\"%s:\\ngot  %s\\nwant %s\", tt.in, got, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestUnmarshalErrors(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tin   string\n\t\twant string // error must match this regexp\n\t}{\n\t\t{`1`, \"cannot unmarshal number\"},\n\t\t{`{\"type\":1}`, `invalid value for \"type\"`},\n\t\t{`{\"minLength\":1.5}`, `not an integer value`},\n\t\t{`{\"maxLength\":1.5}`, `not an integer value`},\n\t\t{`{\"minItems\":1.5}`, `not an integer value`},\n\t\t{`{\"maxItems\":1.5}`, `not an integer value`},\n\t\t{`{\"minProperties\":1.5}`, `not an integer value`},\n\t\t{`{\"maxProperties\":1.5}`, `not an integer value`},\n\t\t{`{\"minContains\":1.5}`, `not an integer value`},\n\t\t{`{\"maxContains\":1.5}`, `not an integer value`},\n\t\t{fmt.Sprintf(`{\"maxContains\":%d}`, int64(math.MaxInt32+1)), `out of range`},\n\t\t{`{\"minLength\":9e99}`, `cannot be unmarshaled`},\n\t\t{`{\"minLength\":\"1.5\"}`, `not a number`},\n\t} {\n\t\tvar s Schema\n\t\terr := json.Unmarshal([]byte(tt.in), &s)\n\t\tif err == nil {\n\t\t\tt.Fatalf(\"%s: no error but expected one\", tt.in)\n\t\t}\n\t\tif !regexp.MustCompile(tt.want).MatchString(err.Error()) {\n\t\t\tt.Errorf(\"%s: error %q does not match %q\", tt.in, err, tt.want)\n\t\t}\n\n\t}\n}\n\nfunc mustUnmarshal(t *testing.T, data []byte, ptr any) {\n\tt.Helper()\n\tif err := json.Unmarshal(data, ptr); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\n// json returns the schema in json format.\nfunc (s *Schema) json() string {\n\tdata, err := json.Marshal(s)\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"<jsonschema.Schema:%v>\", err)\n\t}\n\treturn string(data)\n}\n\n// json returns the schema in json format, indented.\nfunc (s *Schema) jsonIndent() string {\n\tdata, err := json.MarshalIndent(s, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"<jsonschema.Schema:%v>\", err)\n\t}\n\treturn string(data)\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/README.md",
    "content": "# JSON Schema test suite for 2020-12\n\nThese files were copied from\nhttps://github.com/json-schema-org/JSON-Schema-Test-Suite/tree/83e866b46c9f9e7082fd51e83a61c5f2145a1ab7/tests/draft2020-12.\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/additionalProperties.json",
    "content": "[\n    {\n        \"description\":\n            \"additionalProperties being false does not allow other properties\",\n        \"specification\": [ { \"core\":\"10.3.2.3\", \"quote\": \"The value of \\\"additionalProperties\\\" MUST be a valid JSON Schema. Boolean \\\"false\\\" forbids everything.\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"foo\": {}, \"bar\": {}},\n            \"patternProperties\": { \"^v\": {} },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"no additional properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional property is invalid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : \"boom\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobarbaz\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"patternProperties are not additional properties\",\n                \"data\": {\"foo\":1, \"vroom\": 2},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"non-ASCII pattern with additionalProperties\",\n        \"specification\": [ { \"core\":\"10.3.2.3\"} ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\"^á\": {}},\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"matching the pattern is valid\",\n                \"data\": {\"ármányos\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"not matching the pattern is invalid\",\n                \"data\": {\"élmény\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties with schema\",\n        \"specification\": [ { \"core\":\"10.3.2.3\", \"quote\": \"The value of \\\"additionalProperties\\\" MUST be a valid JSON Schema.\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"foo\": {}, \"bar\": {}},\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"no additional properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional valid property is valid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional invalid property is invalid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties can exist by itself\",\n        \"specification\": [ { \"core\":\"10.3.2.3\", \"quote\": \"With no other applicator applying to object instances. This validates all the instance values irrespective of their property names\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"an additional valid property is valid\",\n                \"data\": {\"foo\" : true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional invalid property is invalid\",\n                \"data\": {\"foo\" : 1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties are allowed by default\",\n        \"specification\": [ { \"core\":\"10.3.2.3\", \"quote\": \"Omitting this keyword has the same assertion behavior as an empty schema.\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"foo\": {}, \"bar\": {}}\n        },\n        \"tests\": [\n            {\n                \"description\": \"additional properties are allowed\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"quux\": true},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties does not look in applicators\",\n        \"specification\":[ { \"core\": \"10.2\", \"quote\": \"Subschemas of applicator keywords evaluate the instance completely independently such that the results of one such subschema MUST NOT impact the results of sibling subschemas.\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\"properties\": {\"foo\": {}}}\n            ],\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"properties defined in allOf are not examined\",\n                \"data\": {\"foo\": 1, \"bar\": true},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties with null valued instance properties\",\n        \"specification\": [ { \"core\":\"10.3.2.3\" } ],\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"additionalProperties\": {\n                \"type\": \"null\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null values\",\n                \"data\": {\"foo\": null},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties with propertyNames\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": {\n                \"maxLength\": 5\n            },\n            \"additionalProperties\": {\n                \"type\": \"number\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"Valid against both keywords\",\n                \"data\": { \"apple\": 4 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"Valid against propertyNames, but not additionalProperties\",\n                \"data\": { \"fig\": 2, \"pear\": \"available\" },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dependentSchemas with additionalProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"foo2\": {}},\n            \"dependentSchemas\": {\n                \"foo\" : {},\n                \"foo2\": {\n                    \"properties\": {\n                        \"bar\": {}\n                    }\n                }\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"additionalProperties doesn't consider dependentSchemas\",\n                \"data\": {\"foo\": \"\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"additionalProperties can't see bar\",\n                \"data\": {\"bar\": \"\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"additionalProperties can't see bar even when foo2 is present\",\n                \"data\": {\"foo2\": \"\", \"bar\": \"\"},\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/allOf.json",
    "content": "[\n    {\n        \"description\": \"allOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"allOf\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch second\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch first\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type\",\n                \"data\": {\"foo\": \"baz\", \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with base schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"bar\": {\"type\": \"integer\"}},\n            \"required\": [\"bar\"],\n            \"allOf\" : [\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                },\n                {\n                    \"properties\": {\n                        \"baz\": {\"type\": \"null\"}\n                    },\n                    \"required\": [\"baz\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2, \"baz\": null},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": {\"foo\": \"quux\", \"baz\": null},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch first allOf\",\n                \"data\": {\"bar\": 2, \"baz\": null},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch second allOf\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch both\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf simple types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\"maximum\": 30},\n                {\"minimum\": 20}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": 25,\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch one\",\n                \"data\": 35,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, all true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [true, true]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, some false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [true, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, all false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [false, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with one empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any data is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with two empty schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {},\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any data is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with the first empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {},\n                { \"type\": \"number\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with the last empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested allOf, to check validation semantics\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"allOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf combined with anyOf, oneOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [ { \"multipleOf\": 2 } ],\n            \"anyOf\": [ { \"multipleOf\": 3 } ],\n            \"oneOf\": [ { \"multipleOf\": 5 } ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"allOf: false, anyOf: false, oneOf: false\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: false, oneOf: true\",\n                \"data\": 5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: true, oneOf: false\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: true, oneOf: true\",\n                \"data\": 15,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: false, oneOf: false\",\n                \"data\": 2,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: false, oneOf: true\",\n                \"data\": 10,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: true, oneOf: false\",\n                \"data\": 6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: true, oneOf: true\",\n                \"data\": 30,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/anchor.json",
    "content": "[\n    {\n        \"description\": \"Location-independent identifier\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"#foo\",\n            \"$defs\": {\n                \"A\": {\n                    \"$anchor\": \"foo\",\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"data\": 1,\n                \"description\": \"match\",\n                \"valid\": true\n            },\n            {\n                \"data\": \"a\",\n                \"description\": \"mismatch\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Location-independent identifier with absolute URI\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/bar#foo\",\n            \"$defs\": {\n                \"A\": {\n                    \"$id\": \"http://localhost:1234/draft2020-12/bar\",\n                    \"$anchor\": \"foo\",\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"data\": 1,\n                \"description\": \"match\",\n                \"valid\": true\n            },\n            {\n                \"data\": \"a\",\n                \"description\": \"mismatch\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Location-independent identifier with base URI change in subschema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/root\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/nested.json#foo\",\n            \"$defs\": {\n                \"A\": {\n                    \"$id\": \"nested.json\",\n                    \"$defs\": {\n                        \"B\": {\n                            \"$anchor\": \"foo\",\n                            \"type\": \"integer\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"data\": 1,\n                \"description\": \"match\",\n                \"valid\": true\n            },\n            {\n                \"data\": \"a\",\n                \"description\": \"mismatch\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"same $anchor with different base uri\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/foobar\",\n            \"$defs\": {\n                \"A\": {\n                    \"$id\": \"child1\",\n                    \"allOf\": [\n                        {\n                            \"$id\": \"child2\",\n                            \"$anchor\": \"my_anchor\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$anchor\": \"my_anchor\",\n                            \"type\": \"string\"\n                        }\n                    ]\n                }\n            },\n            \"$ref\": \"child1#my_anchor\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"$ref resolves to /$defs/A/allOf/1\",\n                \"data\": \"a\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"$ref does not resolve to /$defs/A/allOf/0\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/anyOf.json",
    "content": "[\n    {\n        \"description\": \"anyOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [\n                {\n                    \"type\": \"integer\"\n                },\n                {\n                    \"minimum\": 2\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first anyOf valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"second anyOf valid\",\n                \"data\": 2.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf valid\",\n                \"data\": 3,\n                \"valid\": true\n            },\n            {\n                \"description\": \"neither anyOf valid\",\n                \"data\": 1.5,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with base schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"string\",\n            \"anyOf\" : [\n                {\n                    \"maxLength\": 2\n                },\n                {\n                    \"minLength\": 4\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"one anyOf valid\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, all true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [true, true]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, some true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [true, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, all false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [false, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf complex types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first anyOf valid (complex)\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second anyOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"neither anyOf valid (complex)\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with one empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is valid\",\n                \"data\": 123,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested anyOf, to check validation semantics\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"anyOf\": [\n                {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/boolean_schema.json",
    "content": "[\n    {\n        \"description\": \"boolean schema 'true'\",\n        \"schema\": true,\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"boolean schema 'false'\",\n        \"schema\": false,\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/const.json",
    "content": "[\n    {\n        \"description\": \"const validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"same value is valid\",\n                \"data\": 2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"another value is invalid\",\n                \"data\": 5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"another type is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with object\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": {\"foo\": \"bar\", \"baz\": \"bax\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"same object is valid\",\n                \"data\": {\"foo\": \"bar\", \"baz\": \"bax\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"same object with different property order is valid\",\n                \"data\": {\"baz\": \"bax\", \"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"another object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"another type is invalid\",\n                \"data\": [1, 2],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with array\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": [{ \"foo\": \"bar\" }]\n        },\n        \"tests\": [\n            {\n                \"description\": \"same array is valid\",\n                \"data\": [{\"foo\": \"bar\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"another array item is invalid\",\n                \"data\": [2],\n                \"valid\": false\n            },\n            {\n                \"description\": \"array with additional items is invalid\",\n                \"data\": [1, 2, 3],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with null\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": null\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"not null is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with false does not match 0\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer zero is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float zero is invalid\",\n                \"data\": 0.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with true does not match 1\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer one is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float one is invalid\",\n                \"data\": 1.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with [false] does not match [0]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": [false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false] is valid\",\n                \"data\": [false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0] is invalid\",\n                \"data\": [0],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[0.0] is invalid\",\n                \"data\": [0.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with [true] does not match [1]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": [true]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[true] is valid\",\n                \"data\": [true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1] is invalid\",\n                \"data\": [1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[1.0] is invalid\",\n                \"data\": [1.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with {\\\"a\\\": false} does not match {\\\"a\\\": 0}\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": {\"a\": false}\n        },\n        \"tests\": [\n            {\n                \"description\": \"{\\\"a\\\": false} is valid\",\n                \"data\": {\"a\": false},\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": 0} is invalid\",\n                \"data\": {\"a\": 0},\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": 0.0} is invalid\",\n                \"data\": {\"a\": 0.0},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with {\\\"a\\\": true} does not match {\\\"a\\\": 1}\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": {\"a\": true}\n        },\n        \"tests\": [\n            {\n                \"description\": \"{\\\"a\\\": true} is valid\",\n                \"data\": {\"a\": true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": 1} is invalid\",\n                \"data\": {\"a\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": 1.0} is invalid\",\n                \"data\": {\"a\": 1.0},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with 0 does not match other zero-like types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": 0\n        },\n        \"tests\": [\n            {\n                \"description\": \"false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer zero is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float zero is valid\",\n                \"data\": 0.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty string is invalid\",\n                \"data\": \"\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with 1 does not match true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer one is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float one is valid\",\n                \"data\": 1.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"const with -2.0 matches integer and float types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": -2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"integer -2 is valid\",\n                \"data\": -2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer 2 is invalid\",\n                \"data\": 2,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float -2.0 is valid\",\n                \"data\": -2.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float 2.0 is invalid\",\n                \"data\": 2.0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float -2.00001 is invalid\",\n                \"data\": -2.00001,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"float and integers are equal up to 64-bit representation limits\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": 9007199254740992\n        },\n        \"tests\": [\n            {\n                \"description\": \"integer is valid\",\n                \"data\": 9007199254740992,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer minus one is invalid\",\n                \"data\": 9007199254740991,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float is valid\",\n                \"data\": 9007199254740992.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float minus one is invalid\",\n                \"data\": 9007199254740991.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nul characters in strings\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"const\": \"hello\\u0000there\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"match string with nul\",\n                \"data\": \"hello\\u0000there\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"do not match string lacking nul\",\n                \"data\": \"hellothere\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/contains.json",
    "content": "[\n    {\n        \"description\": \"contains keyword validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"minimum\": 5}\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with item matching schema (5) is valid\",\n                \"data\": [3, 4, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with item matching schema (6) is valid\",\n                \"data\": [3, 4, 6],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items matching schema (5, 6) is valid\",\n                \"data\": [3, 4, 5, 6],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array without items matching schema is invalid\",\n                \"data\": [2, 3, 4],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"not array is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with const keyword\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": { \"const\": 5 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with item 5 is valid\",\n                \"data\": [3, 4, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items 5 is valid\",\n                \"data\": [3, 4, 5, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array without item 5 is invalid\",\n                \"data\": [1, 2, 3, 4],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with boolean schema true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with boolean schema false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-arrays are valid\",\n                \"data\": \"contains does not apply to strings\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items + contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": { \"multipleOf\": 2 },\n            \"contains\": { \"multipleOf\": 3 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches items, does not match contains\",\n                \"data\": [ 2, 4, 8 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"does not match items, matches contains\",\n                \"data\": [ 3, 6, 9 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches both items and contains\",\n                \"data\": [ 6, 12 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches neither items nor contains\",\n                \"data\": [ 1, 5 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains with false if subschema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\n                \"if\": false,\n                \"else\": true\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains with null instance elements\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\n                \"type\": \"null\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null items\",\n                \"data\": [ null ],\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/default.json",
    "content": "[\n    {\n        \"description\": \"invalid type for default\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\n                    \"type\": \"integer\",\n                    \"default\": []\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when property is specified\",\n                \"data\": {\"foo\": 13},\n                \"valid\": true\n            },\n            {\n                \"description\": \"still valid when the invalid default is used\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"invalid string value for default\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"bar\": {\n                    \"type\": \"string\",\n                    \"minLength\": 4,\n                    \"default\": \"bad\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when property is specified\",\n                \"data\": {\"bar\": \"good\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"still valid when the invalid default is used\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"the default keyword does not do anything if the property is missing\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"alpha\": {\n                    \"type\": \"number\",\n                    \"maximum\": 3,\n                    \"default\": 5\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"an explicit property value is checked against maximum (passing)\",\n                \"data\": { \"alpha\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"an explicit property value is checked against maximum (failing)\",\n                \"data\": { \"alpha\": 5 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing properties are not filled in with the default\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/defs.json",
    "content": "[\n    {\n        \"description\": \"validate definition against metaschema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"https://json-schema.org/draft/2020-12/schema\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid definition schema\",\n                \"data\": {\"$defs\": {\"foo\": {\"type\": \"integer\"}}},\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid definition schema\",\n                \"data\": {\"$defs\": {\"foo\": {\"type\": 1}}},\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/dependentRequired.json",
    "content": "[\n    {\n        \"description\": \"single dependency\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentRequired\": {\"bar\": [\"foo\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"neither\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"nondependant\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with dependency\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing dependency\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [\"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"empty dependents\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentRequired\": {\"bar\": []}\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty object\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with one property\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-object is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple dependents required\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentRequired\": {\"quux\": [\"foo\", \"bar\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"neither\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"nondependants\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with dependencies\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"quux\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing dependency\",\n                \"data\": {\"foo\": 1, \"quux\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing other dependency\",\n                \"data\": {\"bar\": 1, \"quux\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing both dependencies\",\n                \"data\": {\"quux\": 1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dependencies with escaped characters\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentRequired\": {\n                \"foo\\nbar\": [\"foo\\rbar\"],\n                \"foo\\\"bar\": [\"foo'bar\"]\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"CRLF\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\rbar\": 2\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"quoted quotes\",\n                \"data\": {\n                    \"foo'bar\": 1,\n                    \"foo\\\"bar\": 2\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"CRLF missing dependent\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\": 2\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"quoted quotes missing dependent\",\n                \"data\": {\n                    \"foo\\\"bar\": 2\n                },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/dependentSchemas.json",
    "content": "[\n    {\n        \"description\": \"single dependency\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentSchemas\": {\n                \"bar\": {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"integer\"},\n                        \"bar\": {\"type\": \"integer\"}\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"no dependency\",\n                \"data\": {\"foo\": \"quux\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type other\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type both\",\n                \"data\": {\"foo\": \"quux\", \"bar\": \"quux\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [\"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"boolean subschemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentSchemas\": {\n                \"foo\": true,\n                \"bar\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property having schema true is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with property having schema false is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with both properties is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"dependencies with escaped characters\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"dependentSchemas\": {\n                \"foo\\tbar\": {\"minProperties\": 4},\n                \"foo'bar\": {\"required\": [\"foo\\\"bar\"]}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"quoted tab\",\n                \"data\": {\n                    \"foo\\tbar\": 1,\n                    \"a\": 2,\n                    \"b\": 3,\n                    \"c\": 4\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"quoted quote\",\n                \"data\": {\n                    \"foo'bar\": {\"foo\\\"bar\": 1}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"quoted tab invalid under dependent schema\",\n                \"data\": {\n                    \"foo\\tbar\": 1,\n                    \"a\": 2\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"quoted quote invalid under dependent schema\",\n                \"data\": {\"foo'bar\": 1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dependent subschema incompatible with root\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {}\n            },\n            \"dependentSchemas\": {\n                \"foo\": {\n                    \"properties\": {\n                        \"bar\": {}\n                    },\n                    \"additionalProperties\": false\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches root\",\n                \"data\": {\"foo\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches dependency\",\n                \"data\": {\"bar\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches both\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"no dependency\",\n                \"data\": {\"baz\": 1},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/dynamicRef.json",
    "content": "[\n    {\n        \"description\": \"A $dynamicRef to a $dynamicAnchor in the same schema resource behaves like a normal $ref to an $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamicRef-dynamicAnchor-same-schema/root\",\n            \"type\": \"array\",\n            \"items\": { \"$dynamicRef\": \"#items\" },\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is valid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"An array containing non-strings is invalid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef to an $anchor in the same schema resource behaves like a normal $ref to an $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamicRef-anchor-same-schema/root\",\n            \"type\": \"array\",\n            \"items\": { \"$dynamicRef\": \"#items\" },\n            \"$defs\": {\n                \"foo\": {\n                    \"$anchor\": \"items\",\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is valid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"An array containing non-strings is invalid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"A $ref to a $dynamicAnchor in the same schema resource behaves like a normal $ref to an $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/ref-dynamicAnchor-same-schema/root\",\n            \"type\": \"array\",\n            \"items\": { \"$ref\": \"#items\" },\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is valid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"An array containing non-strings is invalid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef resolves to the first $dynamicAnchor still in scope that is encountered when the schema is evaluated\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/typical-dynamic-resolution/root\",\n            \"$ref\": \"list\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#items\" },\n                    \"$defs\": {\n                      \"items\": {\n                          \"$comment\": \"This is only needed to satisfy the bookending requirement\",\n                          \"$dynamicAnchor\": \"items\"\n                      }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is valid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"An array containing non-strings is invalid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef without anchor in fragment behaves identical to $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamicRef-without-anchor/root\",\n            \"$ref\": \"list\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#/$defs/items\" },\n                    \"$defs\": {\n                      \"items\": {\n                          \"$comment\": \"This is only needed to satisfy the bookending requirement\",\n                          \"$dynamicAnchor\": \"items\",\n                          \"type\": \"number\"\n                      }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is invalid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"An array of numbers is valid\",\n                \"data\": [24, 42],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef with intermediate scopes that don't include a matching $dynamicAnchor does not affect dynamic scope resolution\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-resolution-with-intermediate-scopes/root\",\n            \"$ref\": \"intermediate-scope\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"intermediate-scope\": {\n                    \"$id\": \"intermediate-scope\",\n                    \"$ref\": \"list\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#items\" },\n                    \"$defs\": {\n                      \"items\": {\n                          \"$comment\": \"This is only needed to satisfy the bookending requirement\",\n                          \"$dynamicAnchor\": \"items\"\n                      }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"An array of strings is valid\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"An array containing non-strings is invalid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"An $anchor with the same name as a $dynamicAnchor is not used for dynamic scope resolution\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-resolution-ignores-anchors/root\",\n            \"$ref\": \"list\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$anchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#items\" },\n                    \"$defs\": {\n                      \"items\": {\n                          \"$comment\": \"This is only needed to satisfy the bookending requirement\",\n                          \"$dynamicAnchor\": \"items\"\n                      }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"Any array is valid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef without a matching $dynamicAnchor in the same schema resource behaves like a normal $ref to $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-resolution-without-bookend/root\",\n            \"$ref\": \"list\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#items\" },\n                    \"$defs\": {\n                        \"items\": {\n                            \"$comment\": \"This is only needed to give the reference somewhere to resolve to when it behaves like $ref\",\n                            \"$anchor\": \"items\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"Any array is valid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef with a non-matching $dynamicAnchor in the same schema resource behaves like a normal $ref to $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/unmatched-dynamic-anchor/root\",\n            \"$ref\": \"list\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$dynamicAnchor\": \"items\",\n                    \"type\": \"string\"\n                },\n                \"list\": {\n                    \"$id\": \"list\",\n                    \"type\": \"array\",\n                    \"items\": { \"$dynamicRef\": \"#items\" },\n                    \"$defs\": {\n                        \"items\": {\n                            \"$comment\": \"This is only needed to give the reference somewhere to resolve to when it behaves like $ref\",\n                            \"$anchor\": \"items\",\n                            \"$dynamicAnchor\": \"foo\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"Any array is valid\",\n                \"data\": [\"foo\", 42],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef that initially resolves to a schema with a matching $dynamicAnchor resolves to the first $dynamicAnchor in the dynamic scope\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/relative-dynamic-reference/root\",\n            \"$dynamicAnchor\": \"meta\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"const\": \"pass\" }\n            },\n            \"$ref\": \"extended\",\n            \"$defs\": {\n                \"extended\": {\n                    \"$id\": \"extended\",\n                    \"$dynamicAnchor\": \"meta\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"bar\": { \"$ref\": \"bar\" }\n                    }\n                },\n                \"bar\": {\n                    \"$id\": \"bar\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"baz\": { \"$dynamicRef\": \"extended#meta\" }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"The recursive part is valid against the root\",\n                \"data\": {\n                    \"foo\": \"pass\",\n                    \"bar\": {\n                        \"baz\": { \"foo\": \"pass\" }\n                    }\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"The recursive part is not valid against the root\",\n                \"data\": {\n                    \"foo\": \"pass\",\n                    \"bar\": {\n                        \"baz\": { \"foo\": \"fail\" }\n                    }\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"A $dynamicRef that initially resolves to a schema without a matching $dynamicAnchor behaves like a normal $ref to $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/relative-dynamic-reference-without-bookend/root\",\n            \"$dynamicAnchor\": \"meta\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"const\": \"pass\" }\n            },\n            \"$ref\": \"extended\",\n            \"$defs\": {\n                \"extended\": {\n                    \"$id\": \"extended\",\n                    \"$anchor\": \"meta\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"bar\": { \"$ref\": \"bar\" }\n                    }\n                },\n                \"bar\": {\n                    \"$id\": \"bar\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"baz\": { \"$dynamicRef\": \"extended#meta\" }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"The recursive part doesn't need to validate against the root\",\n                \"data\": {\n                    \"foo\": \"pass\",\n                    \"bar\": {\n                        \"baz\": { \"foo\": \"fail\" }\n                    }\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple dynamic paths to the $dynamicRef keyword\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-ref-with-multiple-paths/main\",\n            \"if\": {\n                \"properties\": {\n                    \"kindOfList\": { \"const\": \"numbers\" }\n                },\n                \"required\": [\"kindOfList\"]\n            },\n            \"then\": { \"$ref\": \"numberList\" },\n            \"else\": { \"$ref\": \"stringList\" },\n\n            \"$defs\": {\n                \"genericList\": {\n                    \"$id\": \"genericList\",\n                    \"properties\": {\n                        \"list\": {\n                            \"items\": { \"$dynamicRef\": \"#itemType\" }\n                        }\n                    },\n                    \"$defs\": {\n                        \"defaultItemType\": {\n                            \"$comment\": \"Only needed to satisfy bookending requirement\",\n                            \"$dynamicAnchor\": \"itemType\"\n                        }\n                    }\n                },\n                \"numberList\": {\n                    \"$id\": \"numberList\",\n                    \"$defs\": {\n                        \"itemType\": {\n                            \"$dynamicAnchor\": \"itemType\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"$ref\": \"genericList\"\n                },\n                \"stringList\": {\n                    \"$id\": \"stringList\",\n                    \"$defs\": {\n                        \"itemType\": {\n                            \"$dynamicAnchor\": \"itemType\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"$ref\": \"genericList\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number list with number values\",\n                \"data\": {\n                    \"kindOfList\": \"numbers\",\n                    \"list\": [1.1]\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"number list with string values\",\n                \"data\": {\n                    \"kindOfList\": \"numbers\",\n                    \"list\": [\"foo\"]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"string list with number values\",\n                \"data\": {\n                    \"kindOfList\": \"strings\",\n                    \"list\": [1.1]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"string list with string values\",\n                \"data\": {\n                    \"kindOfList\": \"strings\",\n                    \"list\": [\"foo\"]\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"after leaving a dynamic scope, it is not used by a $dynamicRef\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-ref-leaving-dynamic-scope/main\",\n            \"if\": {\n                \"$id\": \"first_scope\",\n                \"$defs\": {\n                    \"thingy\": {\n                        \"$comment\": \"this is first_scope#thingy\",\n                        \"$dynamicAnchor\": \"thingy\",\n                        \"type\": \"number\"\n                    }\n                }\n            },\n            \"then\": {\n                \"$id\": \"second_scope\",\n                \"$ref\": \"start\",\n                \"$defs\": {\n                    \"thingy\": {\n                        \"$comment\": \"this is second_scope#thingy, the final destination of the $dynamicRef\",\n                        \"$dynamicAnchor\": \"thingy\",\n                        \"type\": \"null\"\n                    }\n                }\n            },\n            \"$defs\": {\n                \"start\": {\n                    \"$comment\": \"this is the landing spot from $ref\",\n                    \"$id\": \"start\",\n                    \"$dynamicRef\": \"inner_scope#thingy\"\n                },\n                \"thingy\": {\n                    \"$comment\": \"this is the first stop for the $dynamicRef\",\n                    \"$id\": \"inner_scope\",\n                    \"$dynamicAnchor\": \"thingy\",\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"string matches /$defs/thingy, but the $dynamicRef does not stop here\",\n                \"data\": \"a string\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"first_scope is not in dynamic scope for the $dynamicRef\",\n                \"data\": 42,\n                \"valid\": false\n            },\n            {\n                \"description\": \"/then/$defs/thingy is the final stop for the $dynamicRef\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"strict-tree schema, guards against misspelled properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/strict-tree.json\",\n            \"$dynamicAnchor\": \"node\",\n\n            \"$ref\": \"tree.json\",\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"instance with misspelled field\",\n                \"data\": {\n                    \"children\": [{\n                            \"daat\": 1\n                        }]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"instance with correct field\",\n                \"data\": {\n                    \"children\": [{\n                            \"data\": 1\n                        }]\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"tests for implementation dynamic anchor and reference link\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/strict-extendible.json\",\n            \"$ref\": \"extendible-dynamic-ref.json\",\n            \"$defs\": {\n                \"elements\": {\n                    \"$dynamicAnchor\": \"elements\",\n                    \"properties\": {\n                        \"a\": true\n                    },\n                    \"required\": [\"a\"],\n                    \"additionalProperties\": false\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"incorrect parent schema\",\n                \"data\": {\n                    \"a\": true\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"incorrect extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"b\": 1 }\n                    ]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"correct extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"a\": 1 }\n                    ]\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref and $dynamicAnchor are independent of order - $defs first\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/strict-extendible-allof-defs-first.json\",\n            \"allOf\": [\n                {\n                    \"$ref\": \"extendible-dynamic-ref.json\"\n                },\n                {\n                    \"$defs\": {\n                        \"elements\": {\n                            \"$dynamicAnchor\": \"elements\",\n                            \"properties\": {\n                                \"a\": true\n                            },\n                            \"required\": [\"a\"],\n                            \"additionalProperties\": false\n                        }\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"incorrect parent schema\",\n                \"data\": {\n                    \"a\": true\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"incorrect extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"b\": 1 }\n                    ]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"correct extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"a\": 1 }\n                    ]\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref and $dynamicAnchor are independent of order - $ref first\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/strict-extendible-allof-ref-first.json\",\n            \"allOf\": [\n                {\n                    \"$defs\": {\n                        \"elements\": {\n                            \"$dynamicAnchor\": \"elements\",\n                            \"properties\": {\n                                \"a\": true\n                            },\n                            \"required\": [\"a\"],\n                            \"additionalProperties\": false\n                        }\n                    }\n                },\n                {\n                    \"$ref\": \"extendible-dynamic-ref.json\"\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"incorrect parent schema\",\n                \"data\": {\n                    \"a\": true\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"incorrect extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"b\": 1 }\n                    ]\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"correct extended schema\",\n                \"data\": {\n                    \"elements\": [\n                        { \"a\": 1 }\n                    ]\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to $dynamicRef finds detached $dynamicAnchor\",\n        \"schema\": {\n            \"$ref\": \"http://localhost:1234/draft2020-12/detached-dynamicref.json#/$defs/foo\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$dynamicRef points to a boolean schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"true\": true,\n                \"false\": false\n            },\n            \"properties\": {\n                \"true\": {\n                    \"$dynamicRef\": \"#/$defs/true\"\n                },\n                \"false\": {\n                    \"$dynamicRef\": \"#/$defs/false\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"follow $dynamicRef to a true schema\",\n                \"data\": { \"true\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"follow $dynamicRef to a false schema\",\n                \"data\": { \"false\": 1 },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$dynamicRef skips over intermediate resources - direct reference\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://test.json-schema.org/dynamic-ref-skips-intermediate-resource/main\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"bar-item\": {\n                    \"$ref\": \"item\"\n                }\n            },\n            \"$defs\": {\n                \"bar\": {\n                    \"$id\": \"bar\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"item\"\n                    },\n                    \"$defs\": {\n                        \"item\": {\n                            \"$id\": \"item\",\n                            \"type\": \"object\",\n                            \"properties\": {\n                                \"content\": {\n                                    \"$dynamicRef\": \"#content\"\n                                }\n                            },\n                            \"$defs\": {\n                                \"defaultContent\": {\n                                    \"$dynamicAnchor\": \"content\",\n                                    \"type\": \"integer\"\n                                }\n                            }\n                        },\n                        \"content\": {\n                            \"$dynamicAnchor\": \"content\",\n                            \"type\": \"string\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"integer property passes\",\n                \"data\": { \"bar-item\": { \"content\": 42 } },\n                \"valid\": true\n            },\n            {\n                \"description\": \"string property fails\",\n                \"data\": { \"bar-item\": { \"content\": \"value\" } },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/enum.json",
    "content": "[\n    {\n        \"description\": \"simple enum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [1, 2, 3]\n        },\n        \"tests\": [\n            {\n                \"description\": \"one of the enum is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": 4,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"heterogeneous enum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [6, \"foo\", [], true, {\"foo\": 12}]\n        },\n        \"tests\": [\n            {\n                \"description\": \"one of the enum is valid\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"objects are deep compared\",\n                \"data\": {\"foo\": false},\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid object matches\",\n                \"data\": {\"foo\": 12},\n                \"valid\": true\n            },\n            {\n                \"description\": \"extra properties in object is invalid\",\n                \"data\": {\"foo\": 12, \"boo\": 42},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"heterogeneous enum-with-null validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [6, null]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is valid\",\n                \"data\": 6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": \"test\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enums in properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\":\"object\",\n            \"properties\": {\n                \"foo\": {\"enum\":[\"foo\"]},\n                \"bar\": {\"enum\":[\"bar\"]}\n            },\n            \"required\": [\"bar\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"both properties are valid\",\n                \"data\": {\"foo\":\"foo\", \"bar\":\"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong foo value\",\n                \"data\": {\"foo\":\"foot\", \"bar\":\"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong bar value\",\n                \"data\": {\"foo\":\"foo\", \"bar\":\"bart\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing optional property is valid\",\n                \"data\": {\"bar\":\"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing required property is invalid\",\n                \"data\": {\"foo\":\"foo\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing all properties is invalid\",\n                \"data\": {},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with escaped characters\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [\"foo\\nbar\", \"foo\\rbar\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"member 1 is valid\",\n                \"data\": \"foo\\nbar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"member 2 is valid\",\n                \"data\": \"foo\\rbar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"another string is invalid\",\n                \"data\": \"abc\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with false does not match 0\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer zero is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float zero is invalid\",\n                \"data\": 0.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with [false] does not match [0]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [[false]]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false] is valid\",\n                \"data\": [false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0] is invalid\",\n                \"data\": [0],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[0.0] is invalid\",\n                \"data\": [0.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with true does not match 1\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [true]\n        },\n        \"tests\": [\n            {\n                \"description\": \"true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer one is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float one is invalid\",\n                \"data\": 1.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with [true] does not match [1]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [[true]]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[true] is valid\",\n                \"data\": [true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1] is invalid\",\n                \"data\": [1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[1.0] is invalid\",\n                \"data\": [1.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with 0 does not match false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [0]\n        },\n        \"tests\": [\n            {\n                \"description\": \"false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer zero is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float zero is valid\",\n                \"data\": 0.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with [0] does not match [false]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [[0]]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false] is invalid\",\n                \"data\": [false],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[0] is valid\",\n                \"data\": [0],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0.0] is valid\",\n                \"data\": [0.0],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with 1 does not match true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [1]\n        },\n        \"tests\": [\n            {\n                \"description\": \"true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer one is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float one is valid\",\n                \"data\": 1.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with [1] does not match [true]\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [[1]]\n        },\n        \"tests\": [\n            {\n                \"description\": \"[true] is invalid\",\n                \"data\": [true],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[1] is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1.0] is valid\",\n                \"data\": [1.0],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nul characters in strings\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"enum\": [ \"hello\\u0000there\" ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"match string with nul\",\n                \"data\": \"hello\\u0000there\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"do not match string lacking nul\",\n                \"data\": \"hellothere\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/exclusiveMaximum.json",
    "content": "[\n    {\n        \"description\": \"exclusiveMaximum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"exclusiveMaximum\": 3.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"below the exclusiveMaximum is valid\",\n                \"data\": 2.2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is invalid\",\n                \"data\": 3.0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"above the exclusiveMaximum is invalid\",\n                \"data\": 3.5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/exclusiveMinimum.json",
    "content": "[\n    {\n        \"description\": \"exclusiveMinimum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"exclusiveMinimum\": 1.1\n        },\n        \"tests\": [\n            {\n                \"description\": \"above the exclusiveMinimum is valid\",\n                \"data\": 1.2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is invalid\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"below the exclusiveMinimum is invalid\",\n                \"data\": 0.6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/if-then-else.json",
    "content": "[\n    {\n        \"description\": \"ignore if without then or else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone if\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone if\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ignore then without if\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"then\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone then\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone then\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ignore else without if\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"else\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone else\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone else\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if and then without else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"then\": {\n                \"minimum\": -10\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid through then\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through then\",\n                \"data\": -100,\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid when if test fails\",\n                \"data\": 3,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if and else without then\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"else\": {\n                \"multipleOf\": 2\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when if test passes\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid through else\",\n                \"data\": 4,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through else\",\n                \"data\": 3,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"validate against correct branch, then vs else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"then\": {\n                \"minimum\": -10\n            },\n            \"else\": {\n                \"multipleOf\": 2\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid through then\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through then\",\n                \"data\": -100,\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid through else\",\n                \"data\": 4,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through else\",\n                \"data\": 3,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"non-interference across combined schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"if\": {\n                        \"exclusiveMaximum\": 0\n                    }\n                },\n                {\n                    \"then\": {\n                        \"minimum\": -10\n                    }\n                },\n                {\n                    \"else\": {\n                        \"multipleOf\": 2\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid, but would have been invalid through then\",\n                \"data\": -100,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid, but would have been invalid through else\",\n                \"data\": 3,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if with boolean schema true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": true,\n            \"then\": { \"const\": \"then\" },\n            \"else\": { \"const\": \"else\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"boolean schema true in if always chooses the then path (valid)\",\n                \"data\": \"then\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean schema true in if always chooses the then path (invalid)\",\n                \"data\": \"else\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"if with boolean schema false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": false,\n            \"then\": { \"const\": \"then\" },\n            \"else\": { \"const\": \"else\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"boolean schema false in if always chooses the else path (invalid)\",\n                \"data\": \"then\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean schema false in if always chooses the else path (valid)\",\n                \"data\": \"else\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if appears at the end when serialized (keyword processing sequence)\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"then\": { \"const\": \"yes\" },\n            \"else\": { \"const\": \"other\" },\n            \"if\": { \"maxLength\": 4 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"yes redirects to then and passes\",\n                \"data\": \"yes\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"other redirects to else and passes\",\n                \"data\": \"other\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"no redirects to then and fails\",\n                \"data\": \"no\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid redirects to else and fails\",\n                \"data\": \"invalid\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/infinite-loop-detection.json",
    "content": "[\n    {\n        \"description\": \"evaluating the same schema location against the same data location twice is not a sign of an infinite loop\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"int\": { \"type\": \"integer\" }\n            },\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": {\n                            \"$ref\": \"#/$defs/int\"\n                        }\n                    }\n                },\n                {\n                    \"additionalProperties\": {\n                        \"$ref\": \"#/$defs/int\"\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"passing case\",\n                \"data\": { \"foo\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"failing case\",\n                \"data\": { \"foo\": \"a string\" },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/items.json",
    "content": "[\n    {\n        \"description\": \"a schema given for items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [ 1, 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type of items\",\n                \"data\": [1, \"x\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": {\"foo\" : \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"JavaScript pseudo-array is valid\",\n                \"data\": {\n                    \"0\": \"invalid\",\n                    \"length\": 1\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with boolean schema (true)\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"any array is valid\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with boolean schema (false)\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is invalid\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items and subitems\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"item\": {\n                    \"type\": \"array\",\n                    \"items\": false,\n                    \"prefixItems\": [\n                        { \"$ref\": \"#/$defs/sub-item\" },\n                        { \"$ref\": \"#/$defs/sub-item\" }\n                    ]\n                },\n                \"sub-item\": {\n                    \"type\": \"object\",\n                    \"required\": [\"foo\"]\n                }\n            },\n            \"type\": \"array\",\n            \"items\": false,\n            \"prefixItems\": [\n                { \"$ref\": \"#/$defs/item\" },\n                { \"$ref\": \"#/$defs/item\" },\n                { \"$ref\": \"#/$defs/item\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too many items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"too many sub-items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong item\",\n                \"data\": [\n                    {\"foo\": null},\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong sub-item\",\n                \"data\": [\n                    [ {}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"fewer items is valid\",\n                \"data\": [\n                    [ {\"foo\": null} ],\n                    [ {\"foo\": null} ]\n                ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"array\",\n            \"items\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"type\": \"array\",\n                        \"items\": {\n                            \"type\": \"number\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid nested array\",\n                \"data\": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested array with invalid type\",\n                \"data\": [[[[\"1\"]], [[2],[3]]], [[[4], [5], [6]]]],\n                \"valid\": false\n            },\n            {\n                \"description\": \"not deep enough\",\n                \"data\": [[[1], [2],[3]], [[4], [5], [6]]],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"prefixItems with no additional items allowed\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{}, {}, {}],\n            \"items\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty array\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"fewer number of items present (1)\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"fewer number of items present (2)\",\n                \"data\": [ 1, 2 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"equal number of items present\",\n                \"data\": [ 1, 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"additional items are not permitted\",\n                \"data\": [ 1, 2, 3, 4 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"items does not look in applicators, valid case\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                { \"prefixItems\": [ { \"minimum\": 3 } ] }\n            ],\n            \"items\": { \"minimum\": 5 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"prefixItems in allOf does not constrain items, invalid case\",\n                \"data\": [ 3, 5 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"prefixItems in allOf does not constrain items, valid case\",\n                \"data\": [ 5, 5 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"prefixItems validation adjusts the starting index for items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [ { \"type\": \"string\" } ],\n            \"items\": { \"type\": \"integer\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [ \"x\", 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type of second item\",\n                \"data\": [ \"x\", \"y\" ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"items with heterogeneous array\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{}],\n            \"items\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"heterogeneous invalid instance\",\n                \"data\": [ \"foo\", \"bar\", 37 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid instance\",\n                \"data\": [ null ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with null instance elements\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": {\n                \"type\": \"null\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null elements\",\n                \"data\": [ null ],\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/maxContains.json",
    "content": "[\n    {\n        \"description\": \"maxContains without contains is ignored\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxContains\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"one item valid against lone maxContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"two items still valid against lone maxContains\",\n                \"data\": [ 1, 2 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxContains with contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"maxContains\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, valid maxContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all elements match, invalid maxContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"some elements match, valid maxContains\",\n                \"data\": [ 1, 2 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"some elements match, invalid maxContains\",\n                \"data\": [ 1, 2, 1 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"maxContains with contains, value with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"maxContains\": 1.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"one element matches, valid maxContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too many elements match, invalid maxContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains < maxContains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 1,\n            \"maxContains\": 3\n        },\n        \"tests\": [\n            {\n                \"description\": \"actual < minContains < maxContains\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"minContains < actual < maxContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"minContains < maxContains < actual\",\n                \"data\": [ 1, 1, 1, 1 ],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/maxItems.json",
    "content": "[\n    {\n        \"description\": \"maxItems validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxItems\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": [1, 2, 3],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxItems validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxItems\": 2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": [1, 2, 3],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/maxLength.json",
    "content": "[\n    {\n        \"description\": \"maxLength validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxLength\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": \"f\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": \"fo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 100,\n                \"valid\": true\n            },\n            {\n                \"description\": \"two graphemes is long enough\",\n                \"data\": \"\\uD83D\\uDCA9\\uD83D\\uDCA9\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxLength validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxLength\": 2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": \"f\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/maxProperties.json",
    "content": "[\n    {\n        \"description\": \"maxProperties validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxProperties\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"baz\": 3},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxProperties validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxProperties\": 2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"baz\": 3},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"maxProperties = 0 means the object is empty\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maxProperties\": 0\n        },\n        \"tests\": [\n            {\n                \"description\": \"no properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"one property is invalid\",\n                \"data\": { \"foo\": 1 },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/maximum.json",
    "content": "[\n    {\n        \"description\": \"maximum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maximum\": 3.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"below the maximum is valid\",\n                \"data\": 2.6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": 3.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"above the maximum is invalid\",\n                \"data\": 3.5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maximum validation with unsigned integer\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"maximum\": 300\n        },\n        \"tests\":  [\n            {\n                \"description\": \"below the maximum is invalid\",\n                \"data\": 299.97,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point integer is valid\",\n                \"data\": 300,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point float is valid\",\n                \"data\": 300.00,\n                \"valid\": true\n            },\n            {\n                \"description\": \"above the maximum is invalid\",\n                \"data\": 300.5,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/minContains.json",
    "content": "[\n    {\n        \"description\": \"minContains without contains is ignored\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minContains\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"one item valid against lone minContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"zero items still valid against lone minContains\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains=1 with contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"no elements match\",\n                \"data\": [ 2 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"single element matches, valid minContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"some elements match, valid minContains\",\n                \"data\": [ 1, 2 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all elements match, valid minContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains=2 with contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, invalid minContains\",\n                \"data\": [ 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"some elements match, invalid minContains\",\n                \"data\": [ 1, 2 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, valid minContains (exactly as needed)\",\n                \"data\": [ 1, 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all elements match, valid minContains (more than needed)\",\n                \"data\": [ 1, 1, 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"some elements match, valid minContains\",\n                \"data\": [ 1, 2, 1 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains=2 with contains with a decimal value\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"one element matches, invalid minContains\",\n                \"data\": [ 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"both elements match, valid minContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxContains = minContains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"maxContains\": 2,\n            \"minContains\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, invalid minContains\",\n                \"data\": [ 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, invalid maxContains\",\n                \"data\": [ 1, 1, 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"all elements match, valid maxContains and minContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxContains < minContains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"maxContains\": 1,\n            \"minContains\": 3\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid minContains\",\n                \"data\": [ 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid maxContains\",\n                \"data\": [ 1, 1, 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid maxContains and minContains\",\n                \"data\": [ 1, 1 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains = 0\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 0\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"minContains = 0 makes contains always pass\",\n                \"data\": [ 2 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minContains = 0 with maxContains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"contains\": {\"const\": 1},\n            \"minContains\": 0,\n            \"maxContains\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty data\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"not more than maxContains\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too many\",\n                \"data\": [ 1, 1 ],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/minItems.json",
    "content": "[\n    {\n        \"description\": \"minItems validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minItems\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": \"\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minItems validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minItems\": 1.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/minLength.json",
    "content": "[\n    {\n        \"description\": \"minLength validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minLength\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": \"fo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": \"f\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"one grapheme is not long enough\",\n                \"data\": \"\\uD83D\\uDCA9\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"minLength validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minLength\": 2.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": \"f\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/minProperties.json",
    "content": "[\n    {\n        \"description\": \"minProperties validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minProperties\": 1\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minProperties validation with a decimal\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minProperties\": 1.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": {},\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/minimum.json",
    "content": "[\n    {\n        \"description\": \"minimum validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minimum\": 1.1\n        },\n        \"tests\": [\n            {\n                \"description\": \"above the minimum is valid\",\n                \"data\": 2.6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": 1.1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"below the minimum is invalid\",\n                \"data\": 0.6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minimum validation with signed integer\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"minimum\": -2\n        },\n        \"tests\": [\n            {\n                \"description\": \"negative above the minimum is valid\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"positive above the minimum is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": -2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point with float is valid\",\n                \"data\": -2.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float below the minimum is invalid\",\n                \"data\": -2.0001,\n                \"valid\": false\n            },\n            {\n                \"description\": \"int below the minimum is invalid\",\n                \"data\": -3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/multipleOf.json",
    "content": "[\n    {\n        \"description\": \"by int\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"multipleOf\": 2\n        },\n        \"tests\": [\n            {\n                \"description\": \"int by int\",\n                \"data\": 10,\n                \"valid\": true\n            },\n            {\n                \"description\": \"int by int fail\",\n                \"data\": 7,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"by number\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"multipleOf\": 1.5\n        },\n        \"tests\": [\n            {\n                \"description\": \"zero is multiple of anything\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"4.5 is multiple of 1.5\",\n                \"data\": 4.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"35 is not multiple of 1.5\",\n                \"data\": 35,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"by small number\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"multipleOf\": 0.0001\n        },\n        \"tests\": [\n            {\n                \"description\": \"0.0075 is multiple of 0.0001\",\n                \"data\": 0.0075,\n                \"valid\": true\n            },\n            {\n                \"description\": \"0.00751 is not multiple of 0.0001\",\n                \"data\": 0.00751,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"float division = inf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"integer\", \"multipleOf\": 0.123456789\n        },\n        \"tests\": [\n            {\n                \"description\": \"always invalid, but naive implementations may raise an overflow error\",\n                \"data\": 1e308,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"small multiple of large integer\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"integer\", \"multipleOf\": 1e-8\n        },\n        \"tests\": [\n            {\n                \"description\": \"any integer is a multiple of 1e-8\",\n                \"data\": 12391239123,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/not.json",
    "content": "[\n    {\n        \"description\": \"not\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"allowed\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"disallowed\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"not multiple types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": {\"type\": [\"integer\", \"boolean\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"other mismatch\",\n                \"data\": true,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"not more complex schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"foo\": {\n                        \"type\": \"string\"\n                    }\n                }\n             }\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"other match\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"forbidden property\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\n                    \"not\": {}\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property present\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"property absent\",\n                \"data\": {\"bar\": 1, \"baz\": 2},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"forbid everything with empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": {}\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"forbid everything with boolean schema true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allow everything with boolean schema false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"double negation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": { \"not\": {} }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"collect annotations inside a 'not', even if collection is disabled\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"not\": {\n                \"$comment\": \"this subschema must still produce annotations internally, even though the 'not' will ultimately discard them\",\n                \"anyOf\": [\n                    true,\n                    { \"properties\": { \"foo\": true } }\n                ],\n                \"unevaluatedProperties\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"unevaluated property\",\n                \"data\": { \"bar\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"annotations are still collected inside a 'not'\",\n                \"data\": { \"foo\": 1 },\n                \"valid\": false\n            }\n        ]\n     }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/oneOf.json",
    "content": "[\n    {\n        \"description\": \"oneOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [\n                {\n                    \"type\": \"integer\"\n                },\n                {\n                    \"minimum\": 2\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid\",\n                \"data\": 2.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid\",\n                \"data\": 1.5,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with base schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"string\",\n            \"oneOf\" : [\n                {\n                    \"minLength\": 2\n                },\n                {\n                    \"maxLength\": 4\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"one oneOf valid\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, all true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [true, true, true]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, one true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [true, false, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, more than one true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [true, true, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, all false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [false, false, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf complex types\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid (complex)\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid (complex)\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with empty schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"one valid - valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both valid - invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with required\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"oneOf\": [\n                { \"required\": [\"foo\", \"bar\"] },\n                { \"required\": [\"foo\", \"baz\"] }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"both invalid - invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"first valid - valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second valid - valid\",\n                \"data\": {\"foo\": 1, \"baz\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both valid - invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"baz\" : 3},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with missing optional property\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": true,\n                        \"baz\": true\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid\",\n                \"data\": {\"bar\": 8},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid\",\n                \"data\": {\"foo\": \"foo\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": {\"foo\": \"foo\", \"bar\": 8},\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid\",\n                \"data\": {\"baz\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested oneOf, to check validation semantics\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"oneOf\": [\n                {\n                    \"oneOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/pattern.json",
    "content": "[\n    {\n        \"description\": \"pattern validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"pattern\": \"^a*$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"a matching pattern is valid\",\n                \"data\": \"aaa\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-matching pattern is invalid\",\n                \"data\": \"abc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores booleans\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores integers\",\n                \"data\": 123,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores floats\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"pattern is not anchored\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"pattern\": \"a+\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches a substring\",\n                \"data\": \"xxaayy\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/patternProperties.json",
    "content": "[\n    {\n        \"description\":\n            \"patternProperties validates properties matching a regex\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\n                \"f.*o\": {\"type\": \"integer\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a single valid match is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"multiple valid matches is valid\",\n                \"data\": {\"foo\": 1, \"foooooo\" : 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a single invalid match is invalid\",\n                \"data\": {\"foo\": \"bar\", \"fooooo\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"multiple invalid matches is invalid\",\n                \"data\": {\"foo\": \"bar\", \"foooooo\" : \"baz\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple simultaneous patternProperties are validated\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\n                \"a*\": {\"type\": \"integer\"},\n                \"aaa*\": {\"maximum\": 20}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a single valid match is valid\",\n                \"data\": {\"a\": 21},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a simultaneous match is valid\",\n                \"data\": {\"aaaa\": 18},\n                \"valid\": true\n            },\n            {\n                \"description\": \"multiple matches is valid\",\n                \"data\": {\"a\": 21, \"aaaa\": 18},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid due to one is invalid\",\n                \"data\": {\"a\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid due to the other is invalid\",\n                \"data\": {\"aaaa\": 31},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid due to both is invalid\",\n                \"data\": {\"aaa\": \"foo\", \"aaaa\": 31},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"regexes are not anchored by default and are case sensitive\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\n                \"[0-9]{2,}\": { \"type\": \"boolean\" },\n                \"X_\": { \"type\": \"string\" }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"non recognized members are ignored\",\n                \"data\": { \"answer 1\": \"42\" },\n                \"valid\": true\n            },\n            {\n                \"description\": \"recognized members are accounted for\",\n                \"data\": { \"a31b\": null },\n                \"valid\": false\n            },\n            {\n                \"description\": \"regexes are case sensitive\",\n                \"data\": { \"a_x_3\": 3 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"regexes are case sensitive, 2\",\n                \"data\": { \"a_X_3\": 3 },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"patternProperties with boolean schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\n                \"f.*\": true,\n                \"b.*\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property matching schema true is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with property matching schema false is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with both properties is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with a property matching both true and false is invalid\",\n                \"data\": {\"foobar\":1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"patternProperties with null valued instance properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"patternProperties\": {\n                \"^.*bar$\": {\"type\": \"null\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null values\",\n                \"data\": {\"foobar\": null},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/prefixItems.json",
    "content": "[\n    {\n        \"description\": \"a schema given for prefixItems\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                {\"type\": \"integer\"},\n                {\"type\": \"string\"}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"correct types\",\n                \"data\": [ 1, \"foo\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong types\",\n                \"data\": [ \"foo\", 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"incomplete array of items\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with additional items\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"JavaScript pseudo-array is valid\",\n                \"data\": {\n                    \"0\": \"invalid\",\n                    \"1\": \"valid\",\n                    \"length\": 2\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"prefixItems with boolean schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [true, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with one item is valid\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items is invalid\",\n                \"data\": [ 1, \"foo\" ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additional items are allowed by default\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{\"type\": \"integer\"}]\n        },\n        \"tests\": [\n            {\n                \"description\": \"only the first item is validated\",\n                \"data\": [1, \"foo\", false],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"prefixItems with null instance elements\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                {\n                    \"type\": \"null\"\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null elements\",\n                \"data\": [ null ],\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/properties.json",
    "content": "[\n    {\n        \"description\": \"object properties validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\"type\": \"integer\"},\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"both properties present and valid is valid\",\n                \"data\": {\"foo\": 1, \"bar\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"one property invalid is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": {}},\n                \"valid\": false\n            },\n            {\n                \"description\": \"both properties invalid is invalid\",\n                \"data\": {\"foo\": [], \"bar\": {}},\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't invalidate other properties\",\n                \"data\": {\"quux\": []},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\":\n            \"properties, patternProperties, additionalProperties interaction\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\"type\": \"array\", \"maxItems\": 3},\n                \"bar\": {\"type\": \"array\"}\n            },\n            \"patternProperties\": {\"f.o\": {\"minItems\": 2}},\n            \"additionalProperties\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"property validates property\",\n                \"data\": {\"foo\": [1, 2]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property invalidates property\",\n                \"data\": {\"foo\": [1, 2, 3, 4]},\n                \"valid\": false\n            },\n            {\n                \"description\": \"patternProperty invalidates property\",\n                \"data\": {\"foo\": []},\n                \"valid\": false\n            },\n            {\n                \"description\": \"patternProperty validates nonproperty\",\n                \"data\": {\"fxo\": [1, 2]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"patternProperty invalidates nonproperty\",\n                \"data\": {\"fxo\": []},\n                \"valid\": false\n            },\n            {\n                \"description\": \"additionalProperty ignores property\",\n                \"data\": {\"bar\": []},\n                \"valid\": true\n            },\n            {\n                \"description\": \"additionalProperty validates others\",\n                \"data\": {\"quux\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"additionalProperty invalidates others\",\n                \"data\": {\"quux\": \"foo\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"properties with boolean schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": true,\n                \"bar\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"no property present is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"only 'true' property present is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"only 'false' property present is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"both properties present is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"properties with escaped characters\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\\nbar\": {\"type\": \"number\"},\n                \"foo\\\"bar\": {\"type\": \"number\"},\n                \"foo\\\\bar\": {\"type\": \"number\"},\n                \"foo\\rbar\": {\"type\": \"number\"},\n                \"foo\\tbar\": {\"type\": \"number\"},\n                \"foo\\fbar\": {\"type\": \"number\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with all numbers is valid\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\\"bar\": 1,\n                    \"foo\\\\bar\": 1,\n                    \"foo\\rbar\": 1,\n                    \"foo\\tbar\": 1,\n                    \"foo\\fbar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with strings is invalid\",\n                \"data\": {\n                    \"foo\\nbar\": \"1\",\n                    \"foo\\\"bar\": \"1\",\n                    \"foo\\\\bar\": \"1\",\n                    \"foo\\rbar\": \"1\",\n                    \"foo\\tbar\": \"1\",\n                    \"foo\\fbar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"properties with null valued instance properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\"type\": \"null\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null values\",\n                \"data\": {\"foo\": null},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"properties whose names are Javascript object property names\",\n        \"comment\": \"Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"__proto__\": {\"type\": \"number\"},\n                \"toString\": {\n                    \"properties\": { \"length\": { \"type\": \"string\" } }\n                },\n                \"constructor\": {\"type\": \"number\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"none of the properties mentioned\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"__proto__ not valid\",\n                \"data\": { \"__proto__\": \"foo\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"toString not valid\",\n                \"data\": { \"toString\": { \"length\": 37 } },\n                \"valid\": false\n            },\n            {\n                \"description\": \"constructor not valid\",\n                \"data\": { \"constructor\": { \"length\": 37 } },\n                \"valid\": false\n            },\n            {\n                \"description\": \"all present and valid\",\n                \"data\": {\n                    \"__proto__\": 12,\n                    \"toString\": { \"length\": \"foo\" },\n                    \"constructor\": 37\n                },\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/propertyNames.json",
    "content": "[\n    {\n        \"description\": \"propertyNames validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": {\"maxLength\": 3}\n        },\n        \"tests\": [\n            {\n                \"description\": \"all property names valid\",\n                \"data\": {\n                    \"f\": {},\n                    \"foo\": {}\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"some property names invalid\",\n                \"data\": {\n                    \"foo\": {},\n                    \"foobar\": {}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"object without properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3, 4],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames validation with pattern\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": { \"pattern\": \"^a+$\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matching property names valid\",\n                \"data\": {\n                    \"a\": {},\n                    \"aa\": {},\n                    \"aaa\": {}\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-matching property name is invalid\",\n                \"data\": {\n                    \"aaA\": {}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"object without properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with boolean schema true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with any properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with boolean schema false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with any properties is invalid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with const\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": {\"const\": \"foo\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property foo is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with any other property is invalid\",\n                \"data\": {\"bar\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with enum\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": {\"enum\": [\"foo\", \"bar\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property foo is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with property foo and bar is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with any other property is invalid\",\n                \"data\": {\"baz\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/ref.json",
    "content": "[\n    {\n        \"description\": \"root pointer ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#\"}\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": {\"foo\": false},\n                \"valid\": true\n            },\n            {\n                \"description\": \"recursive match\",\n                \"data\": {\"foo\": {\"foo\": false}},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"bar\": false},\n                \"valid\": false\n            },\n            {\n                \"description\": \"recursive mismatch\",\n                \"data\": {\"foo\": {\"bar\": false}},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"relative pointer ref to object\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\"type\": \"integer\"},\n                \"bar\": {\"$ref\": \"#/properties/foo\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": {\"bar\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"bar\": true},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"relative pointer ref to array\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                {\"type\": \"integer\"},\n                {\"$ref\": \"#/prefixItems/0\"}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"match array\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch array\",\n                \"data\": [1, \"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"escaped pointer ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"tilde~field\": {\"type\": \"integer\"},\n                \"slash/field\": {\"type\": \"integer\"},\n                \"percent%field\": {\"type\": \"integer\"}\n            },\n            \"properties\": {\n                \"tilde\": {\"$ref\": \"#/$defs/tilde~0field\"},\n                \"slash\": {\"$ref\": \"#/$defs/slash~1field\"},\n                \"percent\": {\"$ref\": \"#/$defs/percent%25field\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"slash invalid\",\n                \"data\": {\"slash\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"tilde invalid\",\n                \"data\": {\"tilde\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"percent invalid\",\n                \"data\": {\"percent\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"slash valid\",\n                \"data\": {\"slash\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"tilde valid\",\n                \"data\": {\"tilde\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"percent valid\",\n                \"data\": {\"percent\": 123},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested refs\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"a\": {\"type\": \"integer\"},\n                \"b\": {\"$ref\": \"#/$defs/a\"},\n                \"c\": {\"$ref\": \"#/$defs/b\"}\n            },\n            \"$ref\": \"#/$defs/c\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"nested ref valid\",\n                \"data\": 5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref applies alongside sibling keywords\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"reffed\": {\n                    \"type\": \"array\"\n                }\n            },\n            \"properties\": {\n                \"foo\": {\n                    \"$ref\": \"#/$defs/reffed\",\n                    \"maxItems\": 2\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"ref valid, maxItems valid\",\n                \"data\": { \"foo\": [] },\n                \"valid\": true\n            },\n            {\n                \"description\": \"ref valid, maxItems invalid\",\n                \"data\": { \"foo\": [1, 2, 3] },\n                \"valid\": false\n            },\n            {\n                \"description\": \"ref invalid\",\n                \"data\": { \"foo\": \"string\" },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"remote ref, containing refs itself\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"https://json-schema.org/draft/2020-12/schema\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"remote ref valid\",\n                \"data\": {\"minLength\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote ref invalid\",\n                \"data\": {\"minLength\": -1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"property named $ref that is not a reference\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"$ref\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property named $ref valid\",\n                \"data\": {\"$ref\": \"a\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property named $ref invalid\",\n                \"data\": {\"$ref\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"property named $ref, containing an actual $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"$ref\": {\"$ref\": \"#/$defs/is-string\"}\n            },\n            \"$defs\": {\n                \"is-string\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property named $ref valid\",\n                \"data\": {\"$ref\": \"a\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property named $ref invalid\",\n                \"data\": {\"$ref\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to boolean schema true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"#/$defs/bool\",\n            \"$defs\": {\n                \"bool\": true\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to boolean schema false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"#/$defs/bool\",\n            \"$defs\": {\n                \"bool\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Recursive references between schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/tree\",\n            \"description\": \"tree of nodes\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"meta\": {\"type\": \"string\"},\n                \"nodes\": {\n                    \"type\": \"array\",\n                    \"items\": {\"$ref\": \"node\"}\n                }\n            },\n            \"required\": [\"meta\", \"nodes\"],\n            \"$defs\": {\n                \"node\": {\n                    \"$id\": \"http://localhost:1234/draft2020-12/node\",\n                    \"description\": \"node\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"value\": {\"type\": \"number\"},\n                        \"subtree\": {\"$ref\": \"tree\"}\n                    },\n                    \"required\": [\"value\"]\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid tree\",\n                \"data\": {\n                    \"meta\": \"root\",\n                    \"nodes\": [\n                        {\n                            \"value\": 1,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 1.1},\n                                    {\"value\": 1.2}\n                                ]\n                            }\n                        },\n                        {\n                            \"value\": 2,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 2.1},\n                                    {\"value\": 2.2}\n                                ]\n                            }\n                        }\n                    ]\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid tree\",\n                \"data\": {\n                    \"meta\": \"root\",\n                    \"nodes\": [\n                        {\n                            \"value\": 1,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": \"string is invalid\"},\n                                    {\"value\": 1.2}\n                                ]\n                            }\n                        },\n                        {\n                            \"value\": 2,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 2.1},\n                                    {\"value\": 2.2}\n                                ]\n                            }\n                        }\n                    ]\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"refs with quote\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\\\"bar\": {\"$ref\": \"#/$defs/foo%22bar\"}\n            },\n            \"$defs\": {\n                \"foo\\\"bar\": {\"type\": \"number\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with numbers is valid\",\n                \"data\": {\n                    \"foo\\\"bar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with strings is invalid\",\n                \"data\": {\n                    \"foo\\\"bar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref creates new scope when adjacent to keywords\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"A\": {\n                    \"unevaluatedProperties\": false\n                }\n            },\n            \"properties\": {\n                \"prop1\": {\n                    \"type\": \"string\"\n                }\n            },\n            \"$ref\": \"#/$defs/A\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"referenced subschema doesn't see annotations from properties\",\n                \"data\": {\n                    \"prop1\": \"match\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"naive replacement of $ref with its destination is not correct\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"a_string\": { \"type\": \"string\" }\n            },\n            \"enum\": [\n                { \"$ref\": \"#/$defs/a_string\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"do not evaluate the $ref inside the enum, matching any string\",\n                \"data\": \"this is a string\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"do not evaluate the $ref inside the enum, definition exact match\",\n                \"data\": { \"type\": \"string\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"match the enum exactly\",\n                \"data\": { \"$ref\": \"#/$defs/a_string\" },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"refs with relative uris and defs\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://example.com/schema-relative-uri-defs1.json\",\n            \"properties\": {\n                \"foo\": {\n                    \"$id\": \"schema-relative-uri-defs2.json\",\n                    \"$defs\": {\n                        \"inner\": {\n                            \"properties\": {\n                                \"bar\": { \"type\": \"string\" }\n                            }\n                        }\n                    },\n                    \"$ref\": \"#/$defs/inner\"\n                }\n            },\n            \"$ref\": \"schema-relative-uri-defs2.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid on inner field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": 1\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid on outer field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid on both fields\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"relative refs with absolute uris and defs\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://example.com/schema-refs-absolute-uris-defs1.json\",\n            \"properties\": {\n                \"foo\": {\n                    \"$id\": \"http://example.com/schema-refs-absolute-uris-defs2.json\",\n                    \"$defs\": {\n                        \"inner\": {\n                            \"properties\": {\n                                \"bar\": { \"type\": \"string\" }\n                            }\n                        }\n                    },\n                    \"$ref\": \"#/$defs/inner\"\n                }\n            },\n            \"$ref\": \"schema-refs-absolute-uris-defs2.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid on inner field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": 1\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid on outer field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid on both fields\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$id must be resolved against nearest parent, not just immediate parent\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://example.com/a.json\",\n            \"$defs\": {\n                \"x\": {\n                    \"$id\": \"http://example.com/b/c.json\",\n                    \"not\": {\n                        \"$defs\": {\n                            \"y\": {\n                                \"$id\": \"d.json\",\n                                \"type\": \"number\"\n                            }\n                        }\n                    }\n                }\n            },\n            \"allOf\": [\n                {\n                    \"$ref\": \"http://example.com/b/d.json\"\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"order of evaluation: $id and $ref\",\n        \"schema\": {\n            \"$comment\": \"$id must be evaluated before $ref to get the proper $ref destination\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://example.com/draft2020-12/ref-and-id1/base.json\",\n            \"$ref\": \"int.json\",\n            \"$defs\": {\n                \"bigint\": {\n                    \"$comment\": \"canonical uri: https://example.com/ref-and-id1/int.json\",\n                    \"$id\": \"int.json\",\n                    \"maximum\": 10\n                },\n                \"smallint\": {\n                    \"$comment\": \"canonical uri: https://example.com/ref-and-id1-int.json\",\n                    \"$id\": \"/draft2020-12/ref-and-id1-int.json\",\n                    \"maximum\": 2\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"data is valid against first definition\",\n                \"data\": 5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"data is invalid against first definition\",\n                \"data\": 50,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"order of evaluation: $id and $anchor and $ref\",\n        \"schema\": {\n            \"$comment\": \"$id must be evaluated before $ref to get the proper $ref destination\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://example.com/draft2020-12/ref-and-id2/base.json\",\n            \"$ref\": \"#bigint\",\n            \"$defs\": {\n                \"bigint\": {\n                    \"$comment\": \"canonical uri: /ref-and-id2/base.json#/$defs/bigint; another valid uri for this location: /ref-and-id2/base.json#bigint\",\n                    \"$anchor\": \"bigint\",\n                    \"maximum\": 10\n                },\n                \"smallint\": {\n                    \"$comment\": \"canonical uri: https://example.com/ref-and-id2#/$defs/smallint; another valid uri for this location: https://example.com/ref-and-id2/#bigint\",\n                    \"$id\": \"https://example.com/draft2020-12/ref-and-id2/\",\n                    \"$anchor\": \"bigint\",\n                    \"maximum\": 2\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"data is valid against first definition\",\n                \"data\": 5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"data is invalid against first definition\",\n                \"data\": 50,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"simple URN base URI with $ref via the URN\",\n        \"schema\": {\n            \"$comment\": \"URIs do not have to have HTTP(s) schemes\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed\",\n            \"minimum\": 30,\n            \"properties\": {\n                \"foo\": {\"$ref\": \"urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid under the URN IDed schema\",\n                \"data\": {\"foo\": 37},\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid under the URN IDed schema\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"simple URN base URI with JSON pointer\",\n        \"schema\": {\n            \"$comment\": \"URIs do not have to have HTTP(s) schemes\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:uuid:deadbeef-1234-00ff-ff00-4321feebdaed\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#/$defs/bar\"}\n            },\n            \"$defs\": {\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN base URI with NSS\",\n        \"schema\": {\n            \"$comment\": \"RFC 8141 §2.2\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:example:1/406/47452/2\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#/$defs/bar\"}\n            },\n            \"$defs\": {\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN base URI with r-component\",\n        \"schema\": {\n            \"$comment\": \"RFC 8141 §2.3.1\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:example:foo-bar-baz-qux?+CCResolve:cc=uk\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#/$defs/bar\"}\n            },\n            \"$defs\": {\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN base URI with q-component\",\n        \"schema\": {\n            \"$comment\": \"RFC 8141 §2.3.2\",\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:example:weather?=op=map&lat=39.56&lon=-104.85&datetime=1969-07-21T02:56:15Z\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#/$defs/bar\"}\n            },\n            \"$defs\": {\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN base URI with URN and JSON pointer ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:uuid:deadbeef-1234-0000-0000-4321feebdaed\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"urn:uuid:deadbeef-1234-0000-0000-4321feebdaed#/$defs/bar\"}\n            },\n            \"$defs\": {\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN base URI with URN and anchor ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed\",\n            \"properties\": {\n                \"foo\": {\"$ref\": \"urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed#something\"}\n            },\n            \"$defs\": {\n                \"bar\": {\n                    \"$anchor\": \"something\",\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": {\"foo\": 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"URN ref with nested pointer ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"urn:uuid:deadbeef-4321-ffff-ffff-1234feebdaed\",\n            \"$defs\": {\n                \"foo\": {\n                    \"$id\": \"urn:uuid:deadbeef-4321-ffff-ffff-1234feebdaed\",\n                    \"$defs\": {\"bar\": {\"type\": \"string\"}},\n                    \"$ref\": \"#/$defs/bar\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": \"bar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-string is invalid\",\n                \"data\": 12,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref to if\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://example.com/ref/if\",\n            \"if\": {\n                \"$id\": \"http://example.com/ref/if\",\n                \"type\": \"integer\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a non-integer is invalid due to the $ref\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an integer is valid\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ref to then\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://example.com/ref/then\",\n            \"then\": {\n                \"$id\": \"http://example.com/ref/then\",\n                \"type\": \"integer\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a non-integer is invalid due to the $ref\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an integer is valid\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ref to else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://example.com/ref/else\",\n            \"else\": {\n                \"$id\": \"http://example.com/ref/else\",\n                \"type\": \"integer\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a non-integer is invalid due to the $ref\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an integer is valid\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ref with absolute-path-reference\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://example.com/ref/absref.json\",\n            \"$defs\": {\n                \"a\": {\n                    \"$id\": \"http://example.com/ref/absref/foobar.json\",\n                    \"type\": \"number\"\n                },\n                \"b\": {\n                    \"$id\": \"http://example.com/absref/foobar.json\",\n                    \"type\": \"string\"\n                }\n            },\n            \"$ref\": \"/absref/foobar.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"a string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an integer is invalid\",\n                \"data\": 12,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$id with file URI still resolves pointers - *nix\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"file:///folder/file.json\",\n            \"$defs\": {\n                \"foo\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"$ref\": \"#/$defs/foo\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$id with file URI still resolves pointers - windows\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"file:///c:/folder/file.json\",\n            \"$defs\": {\n                \"foo\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"$ref\": \"#/$defs/foo\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"empty tokens in $ref json-pointer\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"\": {\n                    \"$defs\": {\n                        \"\": { \"type\": \"number\" }\n                    }\n                }\n            },\n            \"allOf\": [\n                {\n                    \"$ref\": \"#/$defs//$defs/\"\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/refRemote.json",
    "content": "[\n    {\n        \"description\": \"remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/integer.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"remote ref valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"fragment within remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/subSchemas.json#/$defs/integer\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"remote fragment valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote fragment invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anchor within remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/locationIndependentIdentifier.json#foo\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"remote anchor valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote anchor invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref within remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/subSchemas.json#/$defs/refToInteger\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ref within ref valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ref within ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/\",\n            \"items\": {\n                \"$id\": \"baseUriChange/\",\n                \"items\": {\"$ref\": \"folderInteger.json\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"base URI change ref valid\",\n                \"data\": [[1]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"base URI change ref invalid\",\n                \"data\": [[\"a\"]],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change - change folder\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/scope_change_defs1.json\",\n            \"type\" : \"object\",\n            \"properties\": {\"list\": {\"$ref\": \"baseUriChangeFolder/\"}},\n            \"$defs\": {\n                \"baz\": {\n                    \"$id\": \"baseUriChangeFolder/\",\n                    \"type\": \"array\",\n                    \"items\": {\"$ref\": \"folderInteger.json\"}\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": {\"list\": [1]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": {\"list\": [\"a\"]},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change - change folder in subschema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/scope_change_defs2.json\",\n            \"type\" : \"object\",\n            \"properties\": {\"list\": {\"$ref\": \"baseUriChangeFolderInSubschema/#/$defs/bar\"}},\n            \"$defs\": {\n                \"baz\": {\n                    \"$id\": \"baseUriChangeFolderInSubschema/\",\n                    \"$defs\": {\n                        \"bar\": {\n                            \"type\": \"array\",\n                            \"items\": {\"$ref\": \"folderInteger.json\"}\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": {\"list\": [1]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": {\"list\": [\"a\"]},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"root ref in remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/object\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\"$ref\": \"name-defs.json#/$defs/orNull\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": {\n                    \"name\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": {\n                    \"name\": null\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\n                    \"name\": {\n                        \"name\": null\n                    }\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"remote ref with ref to defs\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/schema-remote-ref-ref-defs1.json\",\n            \"$ref\": \"ref-and-defs.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid\",\n                \"data\": {\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid\",\n                \"data\": {\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"Location-independent identifier in remote ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/locationIndependentIdentifier.json#/$defs/refToInteger\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"integer is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"retrieved nested refs resolve relative to their URI not $id\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"http://localhost:1234/draft2020-12/some-id\",\n            \"properties\": {\n                \"name\": {\"$ref\": \"nested/foo-ref-string.json\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": {\n                    \"name\": {\"foo\":  1}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": {\n                    \"name\": {\"foo\":  \"a\"}\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"remote HTTP ref with different $id\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/different-id-ref-string.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"remote HTTP ref with different URN $id\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/urn-ref-string.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"remote HTTP ref with nested absolute ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/nested-absolute-ref-to-string.json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to $ref finds detached $anchor\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"http://localhost:1234/draft2020-12/detached-ref.json#/$defs/foo\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-number is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/required.json",
    "content": "[\n    {\n        \"description\": \"required validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {},\n                \"bar\": {}\n            },\n            \"required\": [\"foo\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"present required property is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-present required property is invalid\",\n                \"data\": {\"bar\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required default validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"not required by default\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required with empty array\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {}\n            },\n            \"required\": []\n        },\n        \"tests\": [\n            {\n                \"description\": \"property not required\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required with escaped characters\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"required\": [\n                \"foo\\nbar\",\n                \"foo\\\"bar\",\n                \"foo\\\\bar\",\n                \"foo\\rbar\",\n                \"foo\\tbar\",\n                \"foo\\fbar\"\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with all properties present is valid\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\\"bar\": 1,\n                    \"foo\\\\bar\": 1,\n                    \"foo\\rbar\": 1,\n                    \"foo\\tbar\": 1,\n                    \"foo\\fbar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with some properties missing is invalid\",\n                \"data\": {\n                    \"foo\\nbar\": \"1\",\n                    \"foo\\\"bar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"required properties whose names are Javascript object property names\",\n        \"comment\": \"Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"required\": [\"__proto__\", \"toString\", \"constructor\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"none of the properties mentioned\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"__proto__ present\",\n                \"data\": { \"__proto__\": \"foo\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"toString present\",\n                \"data\": { \"toString\": { \"length\": 37 } },\n                \"valid\": false\n            },\n            {\n                \"description\": \"constructor present\",\n                \"data\": { \"constructor\": { \"length\": 37 } },\n                \"valid\": false\n            },\n            {\n                \"description\": \"all present\",\n                \"data\": {\n                    \"__proto__\": 12,\n                    \"toString\": { \"length\": \"foo\" },\n                    \"constructor\": 37\n                },\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/type.json",
    "content": "[\n    {\n        \"description\": \"integer type matches integers\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"integer\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is an integer\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float with zero fractional part is an integer\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is not an integer\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an integer\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is still not an integer, even if it looks like one\",\n                \"data\": \"1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not an integer\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not an integer\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not an integer\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an integer\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"number type matches numbers\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"number\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is a number\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float with zero fractional part is a number (and an integer)\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is a number\",\n                \"data\": 1.1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is not a number\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is still not a number, even if it looks like one\",\n                \"data\": \"1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not a number\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a number\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not a number\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not a number\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"string type matches strings\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"string\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"1 is not a string\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not a string\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is a string\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is still a string, even if it looks like a number\",\n                \"data\": \"1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an empty string is still a string\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an object is not a string\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a string\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not a string\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not a string\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"object type matches objects\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is not an object\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not an object\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an object\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is an object\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an array is not an object\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not an object\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an object\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"array type matches arrays\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"array\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is not an array\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not an array\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an array\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not an array\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is an array\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"a boolean is not an array\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an array\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"boolean type matches booleans\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"boolean\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is not a boolean\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero is not a boolean\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not a boolean\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not a boolean\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an empty string is not a boolean\",\n                \"data\": \"\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not a boolean\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a boolean\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"true is a boolean\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"false is a boolean\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is not a boolean\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"null type matches only the null object\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"null\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is not null\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not null\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero is not null\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not null\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an empty string is not null\",\n                \"data\": \"\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not null\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not null\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"true is not null\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"false is not null\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple types can be specified in an array\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": [\"integer\", \"string\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"an integer is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is invalid\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type as array with one item\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": [\"string\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type: array or object\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": [\"array\", \"object\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array is valid\",\n                \"data\": [1,2,3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type: array, object or null\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": [\"array\", \"object\", \"null\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array is valid\",\n                \"data\": [1,2,3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/unevaluatedItems.json",
    "content": "[\n    {\n        \"description\": \"unevaluatedItems true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems as schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": { \"type\": \"string\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with valid unevaluated items\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with invalid unevaluated items\",\n                \"data\": [42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with uniform items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": { \"type\": \"string\" },\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"unevaluatedItems doesn't apply\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with tuple\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"type\": \"string\" }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with items and prefixItems\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"type\": \"string\" }\n            ],\n            \"items\": true,\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"unevaluatedItems doesn't apply\",\n                \"data\": [\"foo\", 42],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"items\": {\"type\": \"number\"},\n            \"unevaluatedItems\": {\"type\": \"string\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid under items\",\n                \"comment\": \"no elements are considered by unevaluatedItems\",\n                \"data\": [5, 6, 7, 8],\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid under items\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with nested tuple\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"type\": \"string\" }\n            ],\n            \"allOf\": [\n                {\n                    \"prefixItems\": [\n                        true,\n                        { \"type\": \"number\" }\n                    ]\n                }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\", 42],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", 42, true],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with nested items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": {\"type\": \"boolean\"},\n            \"anyOf\": [\n                { \"items\": {\"type\": \"string\"} },\n                true\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"with only (valid) additional items\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with no additional items\",\n                \"data\": [\"yes\", \"no\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with invalid additional item\",\n                \"data\": [\"yes\", false],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with nested prefixItems and items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"prefixItems\": [\n                        { \"type\": \"string\" }\n                    ],\n                    \"items\": true\n                }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional items\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional items\",\n                \"data\": [\"foo\", 42, true],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with nested unevaluatedItems\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"prefixItems\": [\n                        { \"type\": \"string\" }\n                    ]\n                },\n                { \"unevaluatedItems\": true }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional items\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional items\",\n                \"data\": [\"foo\", 42, true],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with anyOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"const\": \"foo\" }\n            ],\n            \"anyOf\": [\n                {\n                    \"prefixItems\": [\n                        true,\n                        { \"const\": \"bar\" }\n                    ]\n                },\n                {\n                    \"prefixItems\": [\n                        true,\n                        true,\n                        { \"const\": \"baz\" }\n                    ]\n                }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when one schema matches and has no unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"when one schema matches and has unevaluated items\",\n                \"data\": [\"foo\", \"bar\", 42],\n                \"valid\": false\n            },\n            {\n                \"description\": \"when two schemas match and has no unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"when two schemas match and has unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"baz\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with oneOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"const\": \"foo\" }\n            ],\n            \"oneOf\": [\n                {\n                    \"prefixItems\": [\n                        true,\n                        { \"const\": \"bar\" }\n                    ]\n                },\n                {\n                    \"prefixItems\": [\n                        true,\n                        { \"const\": \"baz\" }\n                    ]\n                }\n            ],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with not\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"const\": \"foo\" }\n            ],\n            \"not\": {\n                \"not\": {\n                    \"prefixItems\": [\n                        true,\n                        { \"const\": \"bar\" }\n                    ]\n                }\n            },\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with if/then/else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [\n                { \"const\": \"foo\" }\n            ],\n            \"if\": {\n                \"prefixItems\": [\n                    true,\n                    { \"const\": \"bar\" }\n                ]\n            },\n            \"then\": {\n                \"prefixItems\": [\n                    true,\n                    true,\n                    { \"const\": \"then\" }\n                ]\n            },\n            \"else\": {\n                \"prefixItems\": [\n                    true,\n                    true,\n                    true,\n                    { \"const\": \"else\" }\n                ]\n            },\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when if matches and it has no unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"then\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if matches and it has unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"then\", \"else\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if doesn't match and it has no unevaluated items\",\n                \"data\": [\"foo\", 42, 42, \"else\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if doesn't match and it has unevaluated items\",\n                \"data\": [\"foo\", 42, 42, \"else\", 42],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with boolean schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [true],\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$ref\": \"#/$defs/bar\",\n            \"prefixItems\": [\n                { \"type\": \"string\" }\n            ],\n            \"unevaluatedItems\": false,\n            \"$defs\": {\n              \"bar\": {\n                  \"prefixItems\": [\n                      true,\n                      { \"type\": \"string\" }\n                  ]\n              }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems before $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": false,\n            \"prefixItems\": [\n                { \"type\": \"string\" }\n            ],\n            \"$ref\": \"#/$defs/bar\",\n            \"$defs\": {\n              \"bar\": {\n                  \"prefixItems\": [\n                      true,\n                      { \"type\": \"string\" }\n                  ]\n              }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with $dynamicRef\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://example.com/unevaluated-items-with-dynamic-ref/derived\",\n\n            \"$ref\": \"./baseSchema\",\n\n            \"$defs\": {\n                \"derived\": {\n                    \"$dynamicAnchor\": \"addons\",\n                    \"prefixItems\": [\n                        true,\n                        { \"type\": \"string\" }\n                    ]\n                },\n                \"baseSchema\": {\n                    \"$id\": \"./baseSchema\",\n\n                    \"$comment\": \"unevaluatedItems comes first so it's more likely to catch bugs with implementations that are sensitive to keyword ordering\",\n                    \"unevaluatedItems\": false,\n                    \"type\": \"array\",\n                    \"prefixItems\": [\n                        { \"type\": \"string\" }\n                    ],\n                    \"$dynamicRef\": \"#addons\",\n\n                    \"$defs\": {\n                        \"defaultAddons\": {\n                            \"$comment\": \"Needed to satisfy the bookending requirement\",\n                            \"$dynamicAnchor\": \"addons\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated items\",\n                \"data\": [\"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated items\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems can't see inside cousins\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"prefixItems\": [ true ]\n                },\n                { \"unevaluatedItems\": false }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"always fails\",\n                \"data\": [ 1 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"item is evaluated in an uncle schema to unevaluatedItems\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\n                \"foo\": {\n                    \"prefixItems\": [\n                        { \"type\": \"string\" }\n                    ],\n                    \"unevaluatedItems\": false\n                  }\n            },\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": {\n                            \"prefixItems\": [\n                                true,\n                                { \"type\": \"string\" }\n                            ]\n                        }\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"no extra items\",\n                \"data\": {\n                    \"foo\": [\n                        \"test\"\n                    ]\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"uncle keyword evaluation is not significant\",\n                \"data\": {\n                    \"foo\": [\n                        \"test\",\n                        \"test\"\n                    ]\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems depends on adjacent contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [true],\n            \"contains\": {\"type\": \"string\"},\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"second item is evaluated by contains\",\n                \"data\": [ 1, \"foo\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"contains fails, second item is not evaluated\",\n                \"data\": [ 1, 2 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"contains passes, second item is not evaluated\",\n                \"data\": [ 1, 2, \"foo\" ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems depends on multiple nested contains\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                { \"contains\": { \"multipleOf\": 2 } },\n                { \"contains\": { \"multipleOf\": 3 } }\n            ],\n            \"unevaluatedItems\": { \"multipleOf\": 5 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"5 not evaluated, passes unevaluatedItems\",\n                \"data\": [ 2, 3, 4, 5, 6 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"7 not evaluated, fails unevaluatedItems\",\n                \"data\": [ 2, 3, 4, 7, 8 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems and contains interact to control item dependency relationship\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"contains\": {\"const\": \"a\"}\n            },\n            \"then\": {\n                \"if\": {\n                    \"contains\": {\"const\": \"b\"}\n                },\n                \"then\": {\n                    \"if\": {\n                        \"contains\": {\"const\": \"c\"}\n                    }\n                }\n            },\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"only a's are valid\",\n                \"data\": [ \"a\", \"a\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"a's and b's are valid\",\n                \"data\": [ \"a\", \"b\", \"a\", \"b\", \"a\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"a's, b's and c's are valid\",\n                \"data\": [ \"c\", \"a\", \"c\", \"c\", \"b\", \"a\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"only b's are invalid\",\n                \"data\": [ \"b\", \"b\" ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"only c's are invalid\",\n                \"data\": [ \"c\", \"c\" ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"only b's and c's are invalid\",\n                \"data\": [ \"c\", \"b\", \"c\", \"b\", \"c\" ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"only a's and c's are invalid\",\n                \"data\": [ \"c\", \"a\", \"c\", \"a\", \"c\" ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"non-array instances are valid\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"ignores booleans\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores integers\",\n                \"data\": 123,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores floats\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems with null instance elements\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedItems\": {\n                \"type\": \"null\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null elements\",\n                \"data\": [ null ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedItems can see annotations from if without then and else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"prefixItems\": [{\"const\": \"a\"}]\n            },\n            \"unevaluatedItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid in case if is evaluated\",\n                \"data\": [ \"a\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid in case if is evaluated\",\n                \"data\": [ \"b\" ],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/unevaluatedProperties.json",
    "content": "[\n    {\n        \"description\": \"unevaluatedProperties true\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"unevaluatedProperties\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties schema\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"unevaluatedProperties\": {\n                \"type\": \"string\",\n                \"minLength\": 3\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with valid unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with invalid unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"fo\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with adjacent properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with adjacent patternProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"patternProperties\": {\n                \"^foo\": { \"type\": \"string\" }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with adjacent additionalProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"additionalProperties\": true,\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with nested properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": { \"type\": \"string\" }\n                    }\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with nested patternProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n              {\n                  \"patternProperties\": {\n                      \"^bar\": { \"type\": \"string\" }\n                  }\n              }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with nested additionalProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n                {\n                    \"additionalProperties\": true\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with additional properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with nested unevaluatedProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n                {\n                    \"unevaluatedProperties\": true\n                }\n            ],\n            \"unevaluatedProperties\": {\n                \"type\": \"string\",\n                \"maxLength\": 2\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with anyOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": { \"const\": \"bar\" }\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"baz\": { \"const\": \"baz\" }\n                    },\n                    \"required\": [\"baz\"]\n                },\n                {\n                    \"properties\": {\n                        \"quux\": { \"const\": \"quux\" }\n                    },\n                    \"required\": [\"quux\"]\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when one matches and has no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when one matches and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"not-baz\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when two match and has no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when two match and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\",\n                    \"quux\": \"not-quux\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with oneOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"oneOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": { \"const\": \"bar\" }\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"baz\": { \"const\": \"baz\" }\n                    },\n                    \"required\": [\"baz\"]\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"quux\": \"quux\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with not\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"not\": {\n                \"not\": {\n                    \"properties\": {\n                        \"bar\": { \"const\": \"bar\" }\n                    },\n                    \"required\": [\"bar\"]\n                }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with if/then/else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"if\": {\n                \"properties\": {\n                    \"foo\": { \"const\": \"then\" }\n                },\n                \"required\": [\"foo\"]\n            },\n            \"then\": {\n                \"properties\": {\n                    \"bar\": { \"type\": \"string\" }\n                },\n                \"required\": [\"bar\"]\n            },\n            \"else\": {\n                \"properties\": {\n                    \"baz\": { \"type\": \"string\" }\n                },\n                \"required\": [\"baz\"]\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when if is true and has no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if is true and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if is false and has no unevaluated properties\",\n                \"data\": {\n                    \"baz\": \"baz\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if is false and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"else\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with if/then/else, then not defined\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"if\": {\n                \"properties\": {\n                    \"foo\": { \"const\": \"then\" }\n                },\n                \"required\": [\"foo\"]\n            },\n            \"else\": {\n                \"properties\": {\n                    \"baz\": { \"type\": \"string\" }\n                },\n                \"required\": [\"baz\"]\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when if is true and has no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if is true and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if is false and has no unevaluated properties\",\n                \"data\": {\n                    \"baz\": \"baz\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if is false and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"else\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with if/then/else, else not defined\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"if\": {\n                \"properties\": {\n                    \"foo\": { \"const\": \"then\" }\n                },\n                \"required\": [\"foo\"]\n            },\n            \"then\": {\n                \"properties\": {\n                    \"bar\": { \"type\": \"string\" }\n                },\n                \"required\": [\"bar\"]\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"when if is true and has no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"when if is true and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"then\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if is false and has no unevaluated properties\",\n                \"data\": {\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"when if is false and has unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"else\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with dependentSchemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"dependentSchemas\": {\n                \"foo\": {\n                    \"properties\": {\n                        \"bar\": { \"const\": \"bar\" }\n                    },\n                    \"required\": [\"bar\"]\n                }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with boolean schemas\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [true],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"$ref\": \"#/$defs/bar\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"unevaluatedProperties\": false,\n            \"$defs\": {\n                \"bar\": {\n                    \"properties\": {\n                        \"bar\": { \"type\": \"string\" }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties before $ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"unevaluatedProperties\": false,\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"$ref\": \"#/$defs/bar\",\n            \"$defs\": {\n                \"bar\": {\n                    \"properties\": {\n                        \"bar\": { \"type\": \"string\" }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with $dynamicRef\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$id\": \"https://example.com/unevaluated-properties-with-dynamic-ref/derived\",\n\n            \"$ref\": \"./baseSchema\",\n\n            \"$defs\": {\n                \"derived\": {\n                    \"$dynamicAnchor\": \"addons\",\n                    \"properties\": {\n                        \"bar\": { \"type\": \"string\" }\n                    }\n                },\n                \"baseSchema\": {\n                    \"$id\": \"./baseSchema\",\n\n                    \"$comment\": \"unevaluatedProperties comes first so it's more likely to catch bugs with implementations that are sensitive to keyword ordering\",\n                    \"unevaluatedProperties\": false,\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"foo\": { \"type\": \"string\" }\n                    },\n                    \"$dynamicRef\": \"#addons\",\n\n                    \"$defs\": {\n                        \"defaultAddons\": {\n                            \"$comment\": \"Needed to satisfy the bookending requirement\",\n                            \"$dynamicAnchor\": \"addons\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\",\n                    \"baz\": \"baz\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties can't see inside cousins\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    }\n                },\n                {\n                    \"unevaluatedProperties\": false\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"always fails\",\n                \"data\": {\n                    \"foo\": 1\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties can't see inside cousins (reverse order)\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"allOf\": [\n                {\n                    \"unevaluatedProperties\": false\n                },\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"always fails\",\n                \"data\": {\n                    \"foo\": 1\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested unevaluatedProperties, outer false, inner true, properties outside\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n                {\n                    \"unevaluatedProperties\": true\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested unevaluatedProperties, outer false, inner true, properties inside\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": { \"type\": \"string\" }\n                    },\n                    \"unevaluatedProperties\": true\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested unevaluatedProperties, outer true, inner false, properties outside\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": { \"type\": \"string\" }\n            },\n            \"allOf\": [\n                {\n                    \"unevaluatedProperties\": false\n                }\n            ],\n            \"unevaluatedProperties\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested unevaluatedProperties, outer true, inner false, properties inside\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": { \"type\": \"string\" }\n                    },\n                    \"unevaluatedProperties\": false\n                }\n            ],\n            \"unevaluatedProperties\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"cousin unevaluatedProperties, true and false, true with properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": { \"type\": \"string\" }\n                    },\n                    \"unevaluatedProperties\": true\n                },\n                {\n                    \"unevaluatedProperties\": false\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"cousin unevaluatedProperties, true and false, false with properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"unevaluatedProperties\": true\n                },\n                {\n                    \"properties\": {\n                        \"foo\": { \"type\": \"string\" }\n                    },\n                    \"unevaluatedProperties\": false\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"with no nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"with nested unevaluated properties\",\n                \"data\": {\n                    \"foo\": \"foo\",\n                    \"bar\": \"bar\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"property is evaluated in an uncle schema to unevaluatedProperties\",\n        \"comment\": \"see https://stackoverflow.com/questions/66936884/deeply-nested-unevaluatedproperties-and-their-expectations\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"foo\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"bar\": {\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"unevaluatedProperties\": false\n                  }\n            },\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": {\n                            \"properties\": {\n                                \"faz\": {\n                                    \"type\": \"string\"\n                                }\n                            }\n                        }\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"no extra properties\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"test\"\n                    }\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"uncle keyword evaluation is not significant\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"test\",\n                        \"faz\": \"test\"\n                    }\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"in-place applicator siblings, allOf has unevaluated\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    },\n                    \"unevaluatedProperties\": false\n                }\n            ],\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": true\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"base case: both properties present\",\n                \"data\": {\n                    \"foo\": 1,\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"in place applicator siblings, bar is missing\",\n                \"data\": {\n                    \"foo\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"in place applicator siblings, foo is missing\",\n                \"data\": {\n                    \"bar\": 1\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"in-place applicator siblings, anyOf has unevaluated\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    }\n                }\n            ],\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": true\n                    },\n                    \"unevaluatedProperties\": false\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"base case: both properties present\",\n                \"data\": {\n                    \"foo\": 1,\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"in place applicator siblings, bar is missing\",\n                \"data\": {\n                    \"foo\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"in place applicator siblings, foo is missing\",\n                \"data\": {\n                    \"bar\": 1\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties + single cyclic ref\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"x\": { \"$ref\": \"#\" }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"Empty is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"Single is valid\",\n                \"data\": { \"x\": {} },\n                \"valid\": true\n            },\n            {\n                \"description\": \"Unevaluated on 1st level is invalid\",\n                \"data\": { \"x\": {}, \"y\": {} },\n                \"valid\": false\n            },\n            {\n                \"description\": \"Nested is valid\",\n                \"data\": { \"x\": { \"x\": {} } },\n                \"valid\": true\n            },\n            {\n                \"description\": \"Unevaluated on 2nd level is invalid\",\n                \"data\": { \"x\": { \"x\": {}, \"y\": {} } },\n                \"valid\": false\n            },\n            {\n                \"description\": \"Deep nested is valid\",\n                \"data\": { \"x\": { \"x\": { \"x\": {} } } },\n                \"valid\": true\n            },\n            {\n                \"description\": \"Unevaluated on 3rd level is invalid\",\n                \"data\": { \"x\": { \"x\": { \"x\": {}, \"y\": {} } } },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties + ref inside allOf / oneOf\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"one\": {\n                    \"properties\": { \"a\": true }\n                },\n                \"two\": {\n                    \"required\": [\"x\"],\n                    \"properties\": { \"x\": true }\n                }\n            },\n            \"allOf\": [\n                { \"$ref\": \"#/$defs/one\" },\n                { \"properties\": { \"b\": true } },\n                {\n                    \"oneOf\": [\n                        { \"$ref\": \"#/$defs/two\" },\n                        {\n                            \"required\": [\"y\"],\n                            \"properties\": { \"y\": true }\n                        }\n                    ]\n                }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"Empty is invalid (no x or y)\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"a and b are invalid (no x or y)\",\n                \"data\": { \"a\": 1, \"b\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"x and y are invalid\",\n                \"data\": { \"x\": 1, \"y\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"a and x are valid\",\n                \"data\": { \"a\": 1, \"x\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"a and y are valid\",\n                \"data\": { \"a\": 1, \"y\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"a and b and x are valid\",\n                \"data\": { \"a\": 1, \"b\": 1, \"x\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"a and b and y are valid\",\n                \"data\": { \"a\": 1, \"b\": 1, \"y\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"a and b and x and y are invalid\",\n                \"data\": { \"a\": 1, \"b\": 1, \"x\": 1, \"y\": 1 },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dynamic evalation inside nested refs\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"$defs\": {\n                \"one\": {\n                    \"oneOf\": [\n                        { \"$ref\": \"#/$defs/two\" },\n                        { \"required\": [\"b\"], \"properties\": { \"b\": true } },\n                        { \"required\": [\"xx\"], \"patternProperties\": { \"x\": true } },\n                        { \"required\": [\"all\"], \"unevaluatedProperties\": true }\n                    ]\n                },\n                \"two\": {\n                    \"oneOf\": [\n                        { \"required\": [\"c\"], \"properties\": { \"c\": true } },\n                        { \"required\": [\"d\"], \"properties\": { \"d\": true } }\n                    ]\n                }\n            },\n            \"oneOf\": [\n                { \"$ref\": \"#/$defs/one\" },\n                { \"required\": [\"a\"], \"properties\": { \"a\": true } }\n            ],\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"Empty is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"a is valid\",\n                \"data\": { \"a\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"b is valid\",\n                \"data\": { \"b\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"c is valid\",\n                \"data\": { \"c\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"d is valid\",\n                \"data\": { \"d\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"a + b is invalid\",\n                \"data\": { \"a\": 1, \"b\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"a + c is invalid\",\n                \"data\": { \"a\": 1, \"c\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"a + d is invalid\",\n                \"data\": { \"a\": 1, \"d\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"b + c is invalid\",\n                \"data\": { \"b\": 1, \"c\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"b + d is invalid\",\n                \"data\": { \"b\": 1, \"d\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"c + d is invalid\",\n                \"data\": { \"c\": 1, \"d\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"xx is valid\",\n                \"data\": { \"xx\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"xx + foox is valid\",\n                \"data\": { \"xx\": 1, \"foox\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"xx + foo is invalid\",\n                \"data\": { \"xx\": 1, \"foo\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"xx + a is invalid\",\n                \"data\": { \"xx\": 1, \"a\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"xx + b is invalid\",\n                \"data\": { \"xx\": 1, \"b\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"xx + c is invalid\",\n                \"data\": { \"xx\": 1, \"c\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"xx + d is invalid\",\n                \"data\": { \"xx\": 1, \"d\": 1 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"all is valid\",\n                \"data\": { \"all\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"all + foo is valid\",\n                \"data\": { \"all\": 1, \"foo\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"all + a is invalid\",\n                \"data\": { \"all\": 1, \"a\": 1 },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"non-object instances are valid\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"ignores booleans\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores integers\",\n                \"data\": 123,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores floats\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties with null valued instance properties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"unevaluatedProperties\": {\n                \"type\": \"null\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows null valued properties\",\n                \"data\": {\"foo\": null},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties not affected by propertyNames\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"propertyNames\": {\"maxLength\": 1},\n            \"unevaluatedProperties\": {\n                \"type\": \"number\"\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"allows only number properties\",\n                \"data\": {\"a\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"string property is invalid\",\n                \"data\": {\"a\": \"b\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unevaluatedProperties can see annotations from if without then and else\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"if\": {\n                \"patternProperties\": {\n                    \"foo\": {\n                        \"type\": \"string\"\n                    }\n                }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid in case if is evaluated\",\n                \"data\": {\n                    \"foo\": \"a\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid in case if is evaluated\",\n                \"data\": {\n                    \"bar\": \"a\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dependentSchemas with unevaluatedProperties\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"properties\": {\"foo2\": {}},\n            \"dependentSchemas\": {\n                \"foo\" : {},\n                \"foo2\": {\n                    \"properties\": {\n                        \"bar\":{}\n                    }\n                }\n            },\n            \"unevaluatedProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"unevaluatedProperties doesn't consider dependentSchemas\",\n                \"data\": {\"foo\": \"\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"unevaluatedProperties doesn't see bar when foo2 is absent\",\n                \"data\": {\"bar\": \"\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"unevaluatedProperties sees bar when foo2 is present\",\n                \"data\": { \"foo2\": \"\", \"bar\": \"\"},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/draft2020-12/uniqueItems.json",
    "content": "[\n    {\n        \"description\": \"uniqueItems validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"uniqueItems\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"unique array of integers is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of integers is invalid\",\n                \"data\": [1, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-unique array of more than two integers is invalid\",\n                \"data\": [1, 2, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"numbers are unique if mathematically unequal\",\n                \"data\": [1.0, 1.00, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"false is not equal to zero\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"true is not equal to one\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of strings is valid\",\n                \"data\": [\"foo\", \"bar\", \"baz\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of strings is invalid\",\n                \"data\": [\"foo\", \"bar\", \"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"baz\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of objects is invalid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"bar\"}],\n                \"valid\": false\n            },\n            {\n                \"description\": \"property order of array of objects is ignored\",\n                \"data\": [{\"foo\": \"bar\", \"bar\": \"foo\"}, {\"bar\": \"foo\", \"foo\": \"bar\"}],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : false}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of nested objects is invalid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}}\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"bar\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of arrays is invalid\",\n                \"data\": [[\"foo\"], [\"foo\"]],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-unique array of more than two arrays is invalid\",\n                \"data\": [[\"foo\"], [\"bar\"], [\"foo\"]],\n                \"valid\": false\n            },\n            {\n                \"description\": \"1 and true are unique\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"0 and false are unique\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1] and [true] are unique\",\n                \"data\": [[1], [true]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0] and [false] are unique\",\n                \"data\": [[0], [false]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested [1] and [true] are unique\",\n                \"data\": [[[1], \"foo\"], [[true], \"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested [0] and [false] are unique\",\n                \"data\": [[[0], \"foo\"], [[false], \"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, 1, \"{}\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique heterogeneous types are invalid\",\n                \"data\": [{}, [1], true, null, {}, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"different objects are unique\",\n                \"data\": [{\"a\": 1, \"b\": 2}, {\"a\": 2, \"b\": 1}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"objects are non-unique despite key order\",\n                \"data\": [{\"a\": 1, \"b\": 2}, {\"b\": 2, \"a\": 1}],\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": false} and {\\\"a\\\": 0} are unique\",\n                \"data\": [{\"a\": false}, {\"a\": 0}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": true} and {\\\"a\\\": 1} are unique\",\n                \"data\": [{\"a\": true}, {\"a\": 1}],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems with an array of items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is not valid\",\n                \"data\": [false, false],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[true, true] from items array is not valid\",\n                \"data\": [true, true],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [false, true] is not valid\",\n                \"data\": [false, true, \"foo\", \"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-unique array extended from [true, false] is not valid\",\n                \"data\": [true, false, \"foo\", \"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems with an array of items and additionalItems=false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": true,\n            \"items\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is not valid\",\n                \"data\": [false, false],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[true, true] from items array is not valid\",\n                \"data\": [true, true],\n                \"valid\": false\n            },\n            {\n                \"description\": \"extra items are invalid even if unique\",\n                \"data\": [false, true, null],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false validation\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"uniqueItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"unique array of integers is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of integers is valid\",\n                \"data\": [1, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"numbers are unique if mathematically unequal\",\n                \"data\": [1.0, 1.00, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"false is not equal to zero\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"true is not equal to one\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"baz\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"bar\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : false}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"bar\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"1 and true are unique\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"0 and false are unique\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, {}, 1],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false with an array of items\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is valid\",\n                \"data\": [false, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, true] from items array is valid\",\n                \"data\": [true, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"foo\"],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false with an array of items and additionalItems=false\",\n        \"schema\": {\n            \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n            \"prefixItems\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": false,\n            \"items\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is valid\",\n                \"data\": [false, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, true] from items array is valid\",\n                \"data\": [true, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"extra items are invalid even if unique\",\n                \"data\": [false, true, null],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/README.md",
    "content": "# JSON Schema test suite: remote references\n\nThese files were copied from\nhttps://github.com/json-schema-org/JSON-Schema-Test-Suite/tree/83e866b46c9f9e7082fd51e83a61c5f2145a1ab7/remotes.\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/different-id-ref-string.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/real-id-ref-string.json\",\n    \"$defs\": {\"bar\": {\"type\": \"string\"}},\n    \"$ref\": \"#/$defs/bar\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/baseUriChange/folderInteger.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/baseUriChangeFolder/folderInteger.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/baseUriChangeFolderInSubschema/folderInteger.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/detached-dynamicref.json",
    "content": "{\n  \"$id\": \"http://localhost:1234/draft2020-12/detached-dynamicref.json\",\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$defs\": {\n    \"foo\": {\n      \"$dynamicRef\": \"#detached\"\n    },\n    \"detached\": {\n      \"$dynamicAnchor\": \"detached\",\n      \"type\": \"integer\"\n    }\n  }\n}"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/detached-ref.json",
    "content": "{\n  \"$id\": \"http://localhost:1234/draft2020-12/detached-ref.json\",\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$defs\": {\n    \"foo\": {\n      \"$ref\": \"#detached\"\n    },\n    \"detached\": {\n      \"$anchor\": \"detached\",\n      \"type\": \"integer\"\n    }\n  }\n}"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/extendible-dynamic-ref.json",
    "content": "{\n    \"description\": \"extendible array\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"http://localhost:1234/draft2020-12/extendible-dynamic-ref.json\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"elements\": {\n            \"type\": \"array\",\n            \"items\": {\n                \"$dynamicRef\": \"#elements\"\n            }\n        }\n    },\n    \"required\": [\"elements\"],\n    \"additionalProperties\": false,\n    \"$defs\": {\n        \"elements\": {\n            \"$dynamicAnchor\": \"elements\"\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/format-assertion-false.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/draft2020-12/format-assertion-false.json\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$vocabulary\": {\n        \"https://json-schema.org/draft/2020-12/vocab/core\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/format-assertion\": false\n    },\n    \"$dynamicAnchor\": \"meta\",\n    \"allOf\": [\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/core\" },\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/format-assertion\" }\n    ]\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/format-assertion-true.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/draft2020-12/format-assertion-true.json\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$vocabulary\": {\n        \"https://json-schema.org/draft/2020-12/vocab/core\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/format-assertion\": true\n    },\n    \"$dynamicAnchor\": \"meta\",\n    \"allOf\": [\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/core\" },\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/format-assertion\" }\n    ]\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/integer.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/locationIndependentIdentifier.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$defs\": {\n        \"refToInteger\": {\n            \"$ref\": \"#foo\"\n        },\n        \"A\": {\n            \"$anchor\": \"foo\",\n            \"type\": \"integer\"\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/metaschema-no-validation.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"http://localhost:1234/draft2020-12/metaschema-no-validation.json\",\n    \"$vocabulary\": {\n        \"https://json-schema.org/draft/2020-12/vocab/applicator\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/core\": true\n    },\n    \"$dynamicAnchor\": \"meta\",\n    \"allOf\": [\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/applicator\" },\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/core\" }\n    ]\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/metaschema-optional-vocabulary.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"http://localhost:1234/draft2020-12/metaschema-optional-vocabulary.json\",\n    \"$vocabulary\": {\n        \"https://json-schema.org/draft/2020-12/vocab/validation\": true,\n        \"https://json-schema.org/draft/2020-12/vocab/core\": true,\n        \"http://localhost:1234/draft/2020-12/vocab/custom\": false\n    },\n    \"$dynamicAnchor\": \"meta\",\n    \"allOf\": [\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/validation\" },\n        { \"$ref\": \"https://json-schema.org/draft/2020-12/meta/core\" }\n    ]\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/name-defs.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$defs\": {\n        \"orNull\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"null\"\n                },\n                {\n                    \"$ref\": \"#\"\n                }\n            ]\n        }\n    },\n    \"type\": \"string\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/nested/foo-ref-string.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"foo\": {\"$ref\": \"string.json\"}\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/nested/string.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"type\": \"string\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/prefixItems.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/draft2020-12/prefixItems.json\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"prefixItems\": [\n        {\"type\": \"string\"}\n    ]\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/ref-and-defs.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"http://localhost:1234/draft2020-12/ref-and-defs.json\",\n    \"$defs\": {\n        \"inner\": {\n            \"properties\": {\n                \"bar\": { \"type\": \"string\" }\n            }\n        }\n    },\n    \"$ref\": \"#/$defs/inner\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/subSchemas.json",
    "content": "{\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$defs\": {\n        \"integer\": {\n            \"type\": \"integer\"\n        },\n        \"refToInteger\": {\n            \"$ref\": \"#/$defs/integer\"\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/draft2020-12/tree.json",
    "content": "{\n    \"description\": \"tree schema, extensible\",\n    \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n    \"$id\": \"http://localhost:1234/draft2020-12/tree.json\",\n    \"$dynamicAnchor\": \"node\",\n\n    \"type\": \"object\",\n    \"properties\": {\n        \"data\": true,\n        \"children\": {\n            \"type\": \"array\",\n            \"items\": {\n                \"$dynamicRef\": \"#node\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/nested-absolute-ref-to-string.json",
    "content": "{\n    \"$defs\": {\n        \"bar\": {\n            \"$id\": \"http://localhost:1234/the-nested-id.json\",\n            \"type\": \"string\"\n        }\n    },\n    \"$ref\": \"http://localhost:1234/the-nested-id.json\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/testdata/remotes/urn-ref-string.json",
    "content": "{\n    \"$id\": \"urn:uuid:feebdaed-ffff-0000-ffff-0000deadbeef\",\n    \"$defs\": {\"bar\": {\"type\": \"string\"}},\n    \"$ref\": \"#/$defs/bar\"\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/util.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"encoding/binary\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"hash/maphash\"\n\t\"math\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"slices\"\n)\n\n// Equal reports whether two Go values representing JSON values are equal according\n// to the JSON Schema spec.\n// The values must not contain cycles.\n// See https://json-schema.org/draft/2020-12/json-schema-core#section-4.2.2.\n// It behaves like reflect.DeepEqual, except that numbers are compared according\n// to mathematical equality.\nfunc Equal(x, y any) bool {\n\treturn equalValue(reflect.ValueOf(x), reflect.ValueOf(y))\n}\n\nfunc equalValue(x, y reflect.Value) bool {\n\t// Copied from src/reflect/deepequal.go, omitting the visited check (because JSON\n\t// values are trees).\n\tif !x.IsValid() || !y.IsValid() {\n\t\treturn x.IsValid() == y.IsValid()\n\t}\n\n\t// Treat numbers specially.\n\trx, ok1 := jsonNumber(x)\n\try, ok2 := jsonNumber(y)\n\tif ok1 && ok2 {\n\t\treturn rx.Cmp(ry) == 0\n\t}\n\tif x.Kind() != y.Kind() {\n\t\treturn false\n\t}\n\tswitch x.Kind() {\n\tcase reflect.Array:\n\t\tif x.Len() != y.Len() {\n\t\t\treturn false\n\t\t}\n\t\tfor i := range x.Len() {\n\t\t\tif !equalValue(x.Index(i), y.Index(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflect.Slice:\n\t\tif x.IsNil() != y.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif x.Len() != y.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif x.UnsafePointer() == y.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\t// Special case for []byte, which is common.\n\t\tif x.Type().Elem().Kind() == reflect.Uint8 && x.Type() == y.Type() {\n\t\t\treturn bytes.Equal(x.Bytes(), y.Bytes())\n\t\t}\n\t\tfor i := range x.Len() {\n\t\t\tif !equalValue(x.Index(i), y.Index(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflect.Interface:\n\t\tif x.IsNil() || y.IsNil() {\n\t\t\treturn x.IsNil() == y.IsNil()\n\t\t}\n\t\treturn equalValue(x.Elem(), y.Elem())\n\tcase reflect.Pointer:\n\t\tif x.UnsafePointer() == y.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\treturn equalValue(x.Elem(), y.Elem())\n\tcase reflect.Struct:\n\t\tt := x.Type()\n\t\tif t != y.Type() {\n\t\t\treturn false\n\t\t}\n\t\tfor i := range t.NumField() {\n\t\t\tsf := t.Field(i)\n\t\t\tif !sf.IsExported() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !equalValue(x.FieldByIndex(sf.Index), y.FieldByIndex(sf.Index)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflect.Map:\n\t\tif x.IsNil() != y.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif x.Len() != y.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif x.UnsafePointer() == y.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\titer := x.MapRange()\n\t\tfor iter.Next() {\n\t\t\tvx := iter.Value()\n\t\t\tvy := y.MapIndex(iter.Key())\n\t\t\tif !vy.IsValid() || !equalValue(vx, vy) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflect.Func:\n\t\tif x.Type() != y.Type() {\n\t\t\treturn false\n\t\t}\n\t\tif x.IsNil() && y.IsNil() {\n\t\t\treturn true\n\t\t}\n\t\tpanic(\"cannot compare functions\")\n\tcase reflect.String:\n\t\treturn x.String() == y.String()\n\tcase reflect.Bool:\n\t\treturn x.Bool() == y.Bool()\n\t// Ints, uints and floats handled in jsonNumber, at top of function.\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unsupported kind: %s\", x.Kind()))\n\t}\n}\n\n// hashValue adds v to the data hashed by h. v must not have cycles.\n// hashValue panics if the value contains functions or channels, or maps whose\n// key type is not string.\n// It ignores unexported fields of structs.\n// Calls to hashValue with the equal values (in the sense\n// of [Equal]) result in the same sequence of values written to the hash.\nfunc hashValue(h *maphash.Hash, v reflect.Value) {\n\t// TODO: replace writes of basic types with WriteComparable in 1.24.\n\n\twriteUint := func(u uint64) {\n\t\tvar buf [8]byte\n\t\tbinary.BigEndian.PutUint64(buf[:], u)\n\t\th.Write(buf[:])\n\t}\n\n\tvar write func(reflect.Value)\n\twrite = func(v reflect.Value) {\n\t\tif r, ok := jsonNumber(v); ok {\n\t\t\t// We want 1.0 and 1 to hash the same.\n\t\t\t// big.Rats are always normalized, so they will be.\n\t\t\t// We could do this more efficiently by handling the int and float cases\n\t\t\t// separately, but that's premature.\n\t\t\twriteUint(uint64(r.Sign() + 1))\n\t\t\th.Write(r.Num().Bytes())\n\t\t\th.Write(r.Denom().Bytes())\n\t\t\treturn\n\t\t}\n\t\tswitch v.Kind() {\n\t\tcase reflect.Invalid:\n\t\t\th.WriteByte(0)\n\t\tcase reflect.String:\n\t\t\th.WriteString(v.String())\n\t\tcase reflect.Bool:\n\t\t\tif v.Bool() {\n\t\t\t\th.WriteByte(1)\n\t\t\t} else {\n\t\t\t\th.WriteByte(0)\n\t\t\t}\n\t\tcase reflect.Complex64, reflect.Complex128:\n\t\t\tc := v.Complex()\n\t\t\twriteUint(math.Float64bits(real(c)))\n\t\t\twriteUint(math.Float64bits(imag(c)))\n\t\tcase reflect.Array, reflect.Slice:\n\t\t\t// Although we could treat []byte more efficiently,\n\t\t\t// JSON values are unlikely to contain them.\n\t\t\twriteUint(uint64(v.Len()))\n\t\t\tfor i := range v.Len() {\n\t\t\t\twrite(v.Index(i))\n\t\t\t}\n\t\tcase reflect.Interface, reflect.Pointer:\n\t\t\twrite(v.Elem())\n\t\tcase reflect.Struct:\n\t\t\tt := v.Type()\n\t\t\tfor i := range t.NumField() {\n\t\t\t\tif sf := t.Field(i); sf.IsExported() {\n\t\t\t\t\twrite(v.FieldByIndex(sf.Index))\n\t\t\t\t}\n\t\t\t}\n\t\tcase reflect.Map:\n\t\t\tif v.Type().Key().Kind() != reflect.String {\n\t\t\t\tpanic(\"map with non-string key\")\n\t\t\t}\n\t\t\t// Sort the keys so the hash is deterministic.\n\t\t\tkeys := v.MapKeys()\n\t\t\t// Write the length. That distinguishes between, say, two consecutive\n\t\t\t// maps with disjoint keys from one map that has the items of both.\n\t\t\twriteUint(uint64(len(keys)))\n\t\t\tslices.SortFunc(keys, func(x, y reflect.Value) int { return cmp.Compare(x.String(), y.String()) })\n\t\t\tfor _, k := range keys {\n\t\t\t\twrite(k)\n\t\t\t\twrite(v.MapIndex(k))\n\t\t\t}\n\t\t// Ints, uints and floats handled in jsonNumber, at top of function.\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unsupported kind: %s\", v.Kind()))\n\t\t}\n\t}\n\n\twrite(v)\n}\n\n// jsonNumber converts a numeric value or a json.Number to a [big.Rat].\n// If v is not a number, it returns nil, false.\nfunc jsonNumber(v reflect.Value) (*big.Rat, bool) {\n\tr := new(big.Rat)\n\tswitch {\n\tcase !v.IsValid():\n\t\treturn nil, false\n\tcase v.CanInt():\n\t\tr.SetInt64(v.Int())\n\tcase v.CanUint():\n\t\tr.SetUint64(v.Uint())\n\tcase v.CanFloat():\n\t\tr.SetFloat64(v.Float())\n\tdefault:\n\t\tjn, ok := v.Interface().(json.Number)\n\t\tif !ok {\n\t\t\treturn nil, false\n\t\t}\n\t\tif _, ok := r.SetString(jn.String()); !ok {\n\t\t\t// This can fail in rare cases; for example, \"1e9999999\".\n\t\t\t// That is a valid JSON number, since the spec puts no limit on the size\n\t\t\t// of the exponent.\n\t\t\treturn nil, false\n\t\t}\n\t}\n\treturn r, true\n}\n\n// jsonType returns a string describing the type of the JSON value,\n// as described in the JSON Schema specification:\n// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.1.\n// It returns \"\", false if the value is not valid JSON.\nfunc jsonType(v reflect.Value) (string, bool) {\n\tif !v.IsValid() {\n\t\t// Not v.IsNil(): a nil []any is still a JSON array.\n\t\treturn \"null\", true\n\t}\n\tif v.CanInt() || v.CanUint() {\n\t\treturn \"integer\", true\n\t}\n\tif v.CanFloat() {\n\t\tif _, f := math.Modf(v.Float()); f == 0 {\n\t\t\treturn \"integer\", true\n\t\t}\n\t\treturn \"number\", true\n\t}\n\tswitch v.Kind() {\n\tcase reflect.Bool:\n\t\treturn \"boolean\", true\n\tcase reflect.String:\n\t\treturn \"string\", true\n\tcase reflect.Slice, reflect.Array:\n\t\treturn \"array\", true\n\tcase reflect.Map, reflect.Struct:\n\t\treturn \"object\", true\n\tdefault:\n\t\treturn \"\", false\n\t}\n}\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(\"assertion failed: \" + msg)\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/util_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"encoding/json\"\n\t\"hash/maphash\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestEqual(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tx1, x2 any\n\t\twant   bool\n\t}{\n\t\t{0, 1, false},\n\t\t{1, 1.0, true},\n\t\t{nil, 0, false},\n\t\t{\"0\", 0, false},\n\t\t{2.5, 2.5, true},\n\t\t{[]int{1, 2}, []float64{1.0, 2.0}, true},\n\t\t{[]int(nil), []int{}, false},\n\t\t{[]map[string]any(nil), []map[string]any{}, false},\n\t\t{\n\t\t\tmap[string]any{\"a\": 1, \"b\": 2.0},\n\t\t\tmap[string]any{\"a\": 1.0, \"b\": 2},\n\t\t\ttrue,\n\t\t},\n\t} {\n\t\tcheck := func(x1, x2 any, want bool) {\n\t\t\tt.Helper()\n\t\t\tif got := Equal(x1, x2); got != want {\n\t\t\t\tt.Errorf(\"jsonEqual(%#v, %#v) = %t, want %t\", x1, x2, got, want)\n\t\t\t}\n\t\t}\n\t\tcheck(tt.x1, tt.x1, true)\n\t\tcheck(tt.x2, tt.x2, true)\n\t\tcheck(tt.x1, tt.x2, tt.want)\n\t\tcheck(tt.x2, tt.x1, tt.want)\n\t}\n}\n\nfunc TestJSONType(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tval  string\n\t\twant string\n\t}{\n\t\t{`null`, \"null\"},\n\t\t{`0`, \"integer\"},\n\t\t{`0.0`, \"integer\"},\n\t\t{`1e2`, \"integer\"},\n\t\t{`0.1`, \"number\"},\n\t\t{`\"\"`, \"string\"},\n\t\t{`true`, \"boolean\"},\n\t\t{`[]`, \"array\"},\n\t\t{`{}`, \"object\"},\n\t} {\n\t\tvar val any\n\t\tif err := json.Unmarshal([]byte(tt.val), &val); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgot, ok := jsonType(reflect.ValueOf(val))\n\t\tif !ok {\n\t\t\tt.Fatalf(\"jsonType failed on %q\", tt.val)\n\t\t}\n\t\tif got != tt.want {\n\t\t\tt.Errorf(\"%s: got %q, want %q\", tt.val, got, tt.want)\n\t\t}\n\n\t}\n}\n\nfunc TestHash(t *testing.T) {\n\tx := map[string]any{\n\t\t\"s\": []any{1, \"foo\", nil, true},\n\t\t\"f\": 2.5,\n\t\t\"m\": map[string]any{\n\t\t\t\"n\":      json.Number(\"123.456\"),\n\t\t\t\"schema\": &Schema{Type: \"integer\", UniqueItems: true},\n\t\t},\n\t\t\"c\": 1.2 + 3.4i,\n\t\t\"n\": nil,\n\t}\n\n\tseed := maphash.MakeSeed()\n\n\thash := func(x any) uint64 {\n\t\tvar h maphash.Hash\n\t\th.SetSeed(seed)\n\t\thashValue(&h, reflect.ValueOf(x))\n\t\treturn h.Sum64()\n\t}\n\n\twant := hash(x)\n\t// Run several times to verify consistency.\n\tfor range 10 {\n\t\tif got := hash(x); got != want {\n\t\t\tt.Errorf(\"hash values differ: %d vs. %d\", got, want)\n\t\t}\n\t}\n\n\t// Check mathematically equal values.\n\tnums := []any{\n\t\t5,\n\t\tuint(5),\n\t\t5.0,\n\t\tjson.Number(\"5\"),\n\t\tjson.Number(\"5.00\"),\n\t}\n\tfor i, n := range nums {\n\t\tif i == 0 {\n\t\t\twant = hash(n)\n\t\t} else if got := hash(n); got != want {\n\t\t\tt.Errorf(\"hashes differ between %v (%[1]T) and %v (%[2]T)\", nums[0], n)\n\t\t}\n\t}\n\n\t// Check that a bare JSON `null` is OK.\n\tvar null any\n\tif err := json.Unmarshal([]byte(`null`), &null); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_ = hash(null)\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/validate.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"hash/maphash\"\n\t\"iter\"\n\t\"math\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\n// The value of the \"$schema\" keyword for the version that we can validate.\nconst draft202012 = \"https://json-schema.org/draft/2020-12/schema\"\n\n// Validate validates the instance, which must be a JSON value, against the schema.\n// It returns nil if validation is successful or an error if it is not.\nfunc (rs *Resolved) Validate(instance any) error {\n\tif s := rs.root.Schema; s != \"\" && s != draft202012 {\n\t\treturn fmt.Errorf(\"cannot validate version %s, only %s\", s, draft202012)\n\t}\n\tst := &state{rs: rs}\n\treturn st.validate(reflect.ValueOf(instance), st.rs.root, nil)\n}\n\n// validateDefaults walks the schema tree. If it finds a default, it validates it\n// against the schema containing it.\n//\n// TODO(jba): account for dynamic refs. This algorithm simple-mindedly\n// treats each schema with a default as its own root.\nfunc (rs *Resolved) validateDefaults() error {\n\tif s := rs.root.Schema; s != \"\" && s != draft202012 {\n\t\treturn fmt.Errorf(\"cannot validate version %s, only %s\", s, draft202012)\n\t}\n\tst := &state{rs: rs}\n\tfor s := range rs.root.all() {\n\t\t// We checked for nil schemas in [Schema.Resolve].\n\t\tassert(s != nil, \"nil schema\")\n\t\tif s.DynamicRef != \"\" {\n\t\t\treturn fmt.Errorf(\"jsonschema: %s: validateDefaults does not support dynamic refs\", s)\n\t\t}\n\t\tif s.Default != nil {\n\t\t\tvar d any\n\t\t\tif err := json.Unmarshal(s.Default, &d); err != nil {\n\t\t\t\treturn fmt.Errorf(\"unmarshaling default value of schema %s: %w\", s, err)\n\t\t\t}\n\t\t\tif err := st.validate(reflect.ValueOf(d), s, nil); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// state is the state of single call to ResolvedSchema.Validate.\ntype state struct {\n\trs *Resolved\n\t// stack holds the schemas from recursive calls to validate.\n\t// These are the \"dynamic scopes\" used to resolve dynamic references.\n\t// https://json-schema.org/draft/2020-12/json-schema-core#scopes\n\tstack []*Schema\n}\n\n// validate validates the reflected value of the instance.\nfunc (st *state) validate(instance reflect.Value, schema *Schema, callerAnns *annotations) (err error) {\n\tdefer util.Wrapf(&err, \"validating %s\", schema)\n\n\t// Maintain a stack for dynamic schema resolution.\n\tst.stack = append(st.stack, schema) // push\n\tdefer func() {\n\t\tst.stack = st.stack[:len(st.stack)-1] // pop\n\t}()\n\n\t// We checked for nil schemas in [Schema.Resolve].\n\tassert(schema != nil, \"nil schema\")\n\n\t// Step through interfaces and pointers.\n\tfor instance.Kind() == reflect.Pointer || instance.Kind() == reflect.Interface {\n\t\tinstance = instance.Elem()\n\t}\n\n\t// type: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.1\n\tif schema.Type != \"\" || schema.Types != nil {\n\t\tgotType, ok := jsonType(instance)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"type: %v of type %[1]T is not a valid JSON value\", instance)\n\t\t}\n\t\tif schema.Type != \"\" {\n\t\t\t// \"number\" subsumes integers\n\t\t\tif !(gotType == schema.Type ||\n\t\t\t\tgotType == \"integer\" && schema.Type == \"number\") {\n\t\t\t\treturn fmt.Errorf(\"type: %v has type %q, want %q\", instance, gotType, schema.Type)\n\t\t\t}\n\t\t} else {\n\t\t\tif !(slices.Contains(schema.Types, gotType) || (gotType == \"integer\" && slices.Contains(schema.Types, \"number\"))) {\n\t\t\t\treturn fmt.Errorf(\"type: %v has type %q, want one of %q\",\n\t\t\t\t\tinstance, gotType, strings.Join(schema.Types, \", \"))\n\t\t\t}\n\t\t}\n\t}\n\t// enum: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.2\n\tif schema.Enum != nil {\n\t\tok := false\n\t\tfor _, e := range schema.Enum {\n\t\t\tif equalValue(reflect.ValueOf(e), instance) {\n\t\t\t\tok = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"enum: %v does not equal any of: %v\", instance, schema.Enum)\n\t\t}\n\t}\n\n\t// const: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.3\n\tif schema.Const != nil {\n\t\tif !equalValue(reflect.ValueOf(*schema.Const), instance) {\n\t\t\treturn fmt.Errorf(\"const: %v does not equal %v\", instance, *schema.Const)\n\t\t}\n\t}\n\n\t// numbers: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.2\n\tif schema.MultipleOf != nil || schema.Minimum != nil || schema.Maximum != nil || schema.ExclusiveMinimum != nil || schema.ExclusiveMaximum != nil {\n\t\tn, ok := jsonNumber(instance)\n\t\tif ok { // these keywords don't apply to non-numbers\n\t\t\tif schema.MultipleOf != nil {\n\t\t\t\t// TODO: validate MultipleOf as non-zero.\n\t\t\t\t// The test suite assumes floats.\n\t\t\t\tnf, _ := n.Float64() // don't care if it's exact or not\n\t\t\t\tif _, f := math.Modf(nf / *schema.MultipleOf); f != 0 {\n\t\t\t\t\treturn fmt.Errorf(\"multipleOf: %s is not a multiple of %f\", n, *schema.MultipleOf)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm := new(big.Rat) // reuse for all of the following\n\t\t\tcmp := func(f float64) int { return n.Cmp(m.SetFloat64(f)) }\n\n\t\t\tif schema.Minimum != nil && cmp(*schema.Minimum) < 0 {\n\t\t\t\treturn fmt.Errorf(\"minimum: %s is less than %f\", n, *schema.Minimum)\n\t\t\t}\n\t\t\tif schema.Maximum != nil && cmp(*schema.Maximum) > 0 {\n\t\t\t\treturn fmt.Errorf(\"maximum: %s is greater than %f\", n, *schema.Maximum)\n\t\t\t}\n\t\t\tif schema.ExclusiveMinimum != nil && cmp(*schema.ExclusiveMinimum) <= 0 {\n\t\t\t\treturn fmt.Errorf(\"exclusiveMinimum: %s is less than or equal to %f\", n, *schema.ExclusiveMinimum)\n\t\t\t}\n\t\t\tif schema.ExclusiveMaximum != nil && cmp(*schema.ExclusiveMaximum) >= 0 {\n\t\t\t\treturn fmt.Errorf(\"exclusiveMaximum: %s is greater than or equal to %f\", n, *schema.ExclusiveMaximum)\n\t\t\t}\n\t\t}\n\t}\n\n\t// strings: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.3\n\tif instance.Kind() == reflect.String && (schema.MinLength != nil || schema.MaxLength != nil || schema.Pattern != \"\") {\n\t\tstr := instance.String()\n\t\tn := utf8.RuneCountInString(str)\n\t\tif schema.MinLength != nil {\n\t\t\tif m := *schema.MinLength; n < m {\n\t\t\t\treturn fmt.Errorf(\"minLength: %q contains %d Unicode code points, fewer than %d\", str, n, m)\n\t\t\t}\n\t\t}\n\t\tif schema.MaxLength != nil {\n\t\t\tif m := *schema.MaxLength; n > m {\n\t\t\t\treturn fmt.Errorf(\"maxLength: %q contains %d Unicode code points, more than %d\", str, n, m)\n\t\t\t}\n\t\t}\n\n\t\tif schema.Pattern != \"\" && !schema.pattern.MatchString(str) {\n\t\t\treturn fmt.Errorf(\"pattern: %q does not match regular expression %q\", str, schema.Pattern)\n\t\t}\n\t}\n\n\tvar anns annotations // all the annotations for this call and child calls\n\n\t// $ref: https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.1\n\tif schema.Ref != \"\" {\n\t\tif err := st.validate(instance, schema.resolvedRef, &anns); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// $dynamicRef: https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.2\n\tif schema.DynamicRef != \"\" {\n\t\t// The ref behaves lexically or dynamically, but not both.\n\t\tassert((schema.resolvedDynamicRef == nil) != (schema.dynamicRefAnchor == \"\"),\n\t\t\t\"DynamicRef not resolved properly\")\n\t\tif schema.resolvedDynamicRef != nil {\n\t\t\t// Same as $ref.\n\t\t\tif err := st.validate(instance, schema.resolvedDynamicRef, &anns); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\t// Dynamic behavior.\n\t\t\t// Look for the base of the outermost schema on the stack with this dynamic\n\t\t\t// anchor. (Yes, outermost: the one farthest from here. This the opposite\n\t\t\t// of how ordinary dynamic variables behave.)\n\t\t\t// Why the base of the schema being validated and not the schema itself?\n\t\t\t// Because the base is the scope for anchors. In fact it's possible to\n\t\t\t// refer to a schema that is not on the stack, but a child of some base\n\t\t\t// on the stack.\n\t\t\t// For an example, search for \"detached\" in testdata/draft2020-12/dynamicRef.json.\n\t\t\tvar dynamicSchema *Schema\n\t\t\tfor _, s := range st.stack {\n\t\t\t\tinfo, ok := s.base.anchors[schema.dynamicRefAnchor]\n\t\t\t\tif ok && info.dynamic {\n\t\t\t\t\tdynamicSchema = info.schema\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif dynamicSchema == nil {\n\t\t\t\treturn fmt.Errorf(\"missing dynamic anchor %q\", schema.dynamicRefAnchor)\n\t\t\t}\n\t\t\tif err := st.validate(instance, dynamicSchema, &anns); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\t// logic\n\t// https://json-schema.org/draft/2020-12/json-schema-core#section-10.2\n\t// These must happen before arrays and objects because if they evaluate an item or property,\n\t// then the unevaluatedItems/Properties schemas don't apply to it.\n\t// See https://json-schema.org/draft/2020-12/json-schema-core#section-11.2, paragraph 4.\n\t//\n\t// If any of these fail, then validation fails, even if there is an unevaluatedXXX\n\t// keyword in the schema. The spec is unclear about this, but that is the intention.\n\n\tvalid := func(s *Schema, anns *annotations) bool { return st.validate(instance, s, anns) == nil }\n\n\tif schema.AllOf != nil {\n\t\tfor _, ss := range schema.AllOf {\n\t\t\tif err := st.validate(instance, ss, &anns); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tif schema.AnyOf != nil {\n\t\t// We must visit them all, to collect annotations.\n\t\tok := false\n\t\tfor _, ss := range schema.AnyOf {\n\t\t\tif valid(ss, &anns) {\n\t\t\t\tok = true\n\t\t\t}\n\t\t}\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"anyOf: did not validate against any of %v\", schema.AnyOf)\n\t\t}\n\t}\n\tif schema.OneOf != nil {\n\t\t// Exactly one.\n\t\tvar okSchema *Schema\n\t\tfor _, ss := range schema.OneOf {\n\t\t\tif valid(ss, &anns) {\n\t\t\t\tif okSchema != nil {\n\t\t\t\t\treturn fmt.Errorf(\"oneOf: validated against both %v and %v\", okSchema, ss)\n\t\t\t\t}\n\t\t\t\tokSchema = ss\n\t\t\t}\n\t\t}\n\t\tif okSchema == nil {\n\t\t\treturn fmt.Errorf(\"oneOf: did not validate against any of %v\", schema.OneOf)\n\t\t}\n\t}\n\tif schema.Not != nil {\n\t\t// Ignore annotations from \"not\".\n\t\tif valid(schema.Not, nil) {\n\t\t\treturn fmt.Errorf(\"not: validated against %v\", schema.Not)\n\t\t}\n\t}\n\tif schema.If != nil {\n\t\tvar ss *Schema\n\t\tif valid(schema.If, &anns) {\n\t\t\tss = schema.Then\n\t\t} else {\n\t\t\tss = schema.Else\n\t\t}\n\t\tif ss != nil {\n\t\t\tif err := st.validate(instance, ss, &anns); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\t// arrays\n\t// TODO(jba): consider arrays of structs.\n\tif instance.Kind() == reflect.Array || instance.Kind() == reflect.Slice {\n\t\t// https://json-schema.org/draft/2020-12/json-schema-core#section-10.3.1\n\t\t// This validate call doesn't collect annotations for the items of the instance; they are separate\n\t\t// instances in their own right.\n\t\t// TODO(jba): if the test suite doesn't cover this case, add a test. For example, nested arrays.\n\t\tfor i, ischema := range schema.PrefixItems {\n\t\t\tif i >= instance.Len() {\n\t\t\t\tbreak // shorter is OK\n\t\t\t}\n\t\t\tif err := st.validate(instance.Index(i), ischema, nil); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tanns.noteEndIndex(min(len(schema.PrefixItems), instance.Len()))\n\n\t\tif schema.Items != nil {\n\t\t\tfor i := len(schema.PrefixItems); i < instance.Len(); i++ {\n\t\t\t\tif err := st.validate(instance.Index(i), schema.Items, nil); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Note that all the items in this array have been validated.\n\t\t\tanns.allItems = true\n\t\t}\n\n\t\tnContains := 0\n\t\tif schema.Contains != nil {\n\t\t\tfor i := range instance.Len() {\n\t\t\t\tif err := st.validate(instance.Index(i), schema.Contains, nil); err == nil {\n\t\t\t\t\tnContains++\n\t\t\t\t\tanns.noteIndex(i)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif nContains == 0 && (schema.MinContains == nil || *schema.MinContains > 0) {\n\t\t\t\treturn fmt.Errorf(\"contains: %s does not have an item matching %s\", instance, schema.Contains)\n\t\t\t}\n\t\t}\n\n\t\t// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.4\n\t\t// TODO(jba): check that these next four keywords' values are integers.\n\t\tif schema.MinContains != nil && schema.Contains != nil {\n\t\t\tif m := *schema.MinContains; nContains < m {\n\t\t\t\treturn fmt.Errorf(\"minContains: contains validated %d items, less than %d\", nContains, m)\n\t\t\t}\n\t\t}\n\t\tif schema.MaxContains != nil && schema.Contains != nil {\n\t\t\tif m := *schema.MaxContains; nContains > m {\n\t\t\t\treturn fmt.Errorf(\"maxContains: contains validated %d items, greater than %d\", nContains, m)\n\t\t\t}\n\t\t}\n\t\tif schema.MinItems != nil {\n\t\t\tif m := *schema.MinItems; instance.Len() < m {\n\t\t\t\treturn fmt.Errorf(\"minItems: array length %d is less than %d\", instance.Len(), m)\n\t\t\t}\n\t\t}\n\t\tif schema.MaxItems != nil {\n\t\t\tif m := *schema.MaxItems; instance.Len() > m {\n\t\t\t\treturn fmt.Errorf(\"maxItems: array length %d is greater than %d\", instance.Len(), m)\n\t\t\t}\n\t\t}\n\t\tif schema.UniqueItems {\n\t\t\tif instance.Len() > 1 {\n\t\t\t\t// Hash each item and compare the hashes.\n\t\t\t\t// If two hashes differ, the items differ.\n\t\t\t\t// If two hashes are the same, compare the collisions for equality.\n\t\t\t\t// (The same logic as hash table lookup.)\n\t\t\t\t// TODO(jba): Use container/hash.Map when it becomes available (https://go.dev/issue/69559),\n\t\t\t\thashes := map[uint64][]int{} // from hash to indices\n\t\t\t\tseed := maphash.MakeSeed()\n\t\t\t\tfor i := range instance.Len() {\n\t\t\t\t\titem := instance.Index(i)\n\t\t\t\t\tvar h maphash.Hash\n\t\t\t\t\th.SetSeed(seed)\n\t\t\t\t\thashValue(&h, item)\n\t\t\t\t\thv := h.Sum64()\n\t\t\t\t\tif sames := hashes[hv]; len(sames) > 0 {\n\t\t\t\t\t\tfor _, j := range sames {\n\t\t\t\t\t\t\tif equalValue(item, instance.Index(j)) {\n\t\t\t\t\t\t\t\treturn fmt.Errorf(\"uniqueItems: array items %d and %d are equal\", i, j)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thashes[hv] = append(hashes[hv], i)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// https://json-schema.org/draft/2020-12/json-schema-core#section-11.2\n\t\tif schema.UnevaluatedItems != nil && !anns.allItems {\n\t\t\t// Apply this subschema to all items in the array that haven't been successfully validated.\n\t\t\t// That includes validations by subschemas on the same instance, like allOf.\n\t\t\tfor i := anns.endIndex; i < instance.Len(); i++ {\n\t\t\t\tif !anns.evaluatedIndexes[i] {\n\t\t\t\t\tif err := st.validate(instance.Index(i), schema.UnevaluatedItems, nil); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tanns.allItems = true\n\t\t}\n\t}\n\n\t// objects\n\t// https://json-schema.org/draft/2020-12/json-schema-core#section-10.3.2\n\tif instance.Kind() == reflect.Map || instance.Kind() == reflect.Struct {\n\t\tif instance.Kind() == reflect.Map {\n\t\t\tif kt := instance.Type().Key(); kt.Kind() != reflect.String {\n\t\t\t\treturn fmt.Errorf(\"map key type %s is not a string\", kt)\n\t\t\t}\n\t\t}\n\t\t// Track the evaluated properties for just this schema, to support additionalProperties.\n\t\t// If we used anns here, then we'd be including properties evaluated in subschemas\n\t\t// from allOf, etc., which additionalProperties shouldn't observe.\n\t\tevalProps := map[string]bool{}\n\t\tfor prop, subschema := range schema.Properties {\n\t\t\tval := property(instance, prop)\n\t\t\tif !val.IsValid() {\n\t\t\t\t// It's OK if the instance doesn't have the property.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// If the instance is a struct and an optional property has the zero\n\t\t\t// value, then we could interpret it as present or missing. Be generous:\n\t\t\t// assume it's missing, and thus always validates successfully.\n\t\t\tif instance.Kind() == reflect.Struct && val.IsZero() && !schema.isRequired[prop] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := st.validate(val, subschema, nil); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tevalProps[prop] = true\n\t\t}\n\t\tif len(schema.PatternProperties) > 0 {\n\t\t\tfor prop, val := range properties(instance) {\n\t\t\t\t// Check every matching pattern.\n\t\t\t\tfor re, schema := range schema.patternProperties {\n\t\t\t\t\tif re.MatchString(prop) {\n\t\t\t\t\t\tif err := st.validate(val, schema, nil); err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tevalProps[prop] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif schema.AdditionalProperties != nil {\n\t\t\t// Apply to all properties not handled above.\n\t\t\tfor prop, val := range properties(instance) {\n\t\t\t\tif !evalProps[prop] {\n\t\t\t\t\tif err := st.validate(val, schema.AdditionalProperties, nil); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tevalProps[prop] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tanns.noteProperties(evalProps)\n\t\tif schema.PropertyNames != nil {\n\t\t\t// Note: properties unnecessarily fetches each value. We could define a propertyNames function\n\t\t\t// if performance ever matters.\n\t\t\tfor prop := range properties(instance) {\n\t\t\t\tif err := st.validate(reflect.ValueOf(prop), schema.PropertyNames, nil); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.5\n\t\tvar min, max int\n\t\tif schema.MinProperties != nil || schema.MaxProperties != nil {\n\t\t\tmin, max = numPropertiesBounds(instance, schema.isRequired)\n\t\t}\n\t\tif schema.MinProperties != nil {\n\t\t\tif n, m := max, *schema.MinProperties; n < m {\n\t\t\t\treturn fmt.Errorf(\"minProperties: object has %d properties, less than %d\", n, m)\n\t\t\t}\n\t\t}\n\t\tif schema.MaxProperties != nil {\n\t\t\tif n, m := min, *schema.MaxProperties; n > m {\n\t\t\t\treturn fmt.Errorf(\"maxProperties: object has %d properties, greater than %d\", n, m)\n\t\t\t}\n\t\t}\n\n\t\thasProperty := func(prop string) bool {\n\t\t\treturn property(instance, prop).IsValid()\n\t\t}\n\n\t\tmissingProperties := func(props []string) []string {\n\t\t\tvar missing []string\n\t\t\tfor _, p := range props {\n\t\t\t\tif !hasProperty(p) {\n\t\t\t\t\tmissing = append(missing, p)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn missing\n\t\t}\n\n\t\tif schema.Required != nil {\n\t\t\tif m := missingProperties(schema.Required); len(m) > 0 {\n\t\t\t\treturn fmt.Errorf(\"required: missing properties: %q\", m)\n\t\t\t}\n\t\t}\n\t\tif schema.DependentRequired != nil {\n\t\t\t// \"Validation succeeds if, for each name that appears in both the instance\n\t\t\t// and as a name within this keyword's value, every item in the corresponding\n\t\t\t// array is also the name of a property in the instance.\" §6.5.4\n\t\t\tfor dprop, reqs := range schema.DependentRequired {\n\t\t\t\tif hasProperty(dprop) {\n\t\t\t\t\tif m := missingProperties(reqs); len(m) > 0 {\n\t\t\t\t\t\treturn fmt.Errorf(\"dependentRequired[%q]: missing properties %q\", dprop, m)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// https://json-schema.org/draft/2020-12/json-schema-core#section-10.2.2.4\n\t\tif schema.DependentSchemas != nil {\n\t\t\t// This does not collect annotations, although it seems like it should.\n\t\t\tfor dprop, ss := range schema.DependentSchemas {\n\t\t\t\tif hasProperty(dprop) {\n\t\t\t\t\t// TODO: include dependentSchemas[dprop] in the errors.\n\t\t\t\t\terr := st.validate(instance, ss, &anns)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif schema.UnevaluatedProperties != nil && !anns.allProperties {\n\t\t\t// This looks a lot like AdditionalProperties, but depends on in-place keywords like allOf\n\t\t\t// in addition to sibling keywords.\n\t\t\tfor prop, val := range properties(instance) {\n\t\t\t\tif !anns.evaluatedProperties[prop] {\n\t\t\t\t\tif err := st.validate(val, schema.UnevaluatedProperties, nil); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The spec says the annotation should be the set of evaluated properties, but we can optimize\n\t\t\t// by setting a single boolean, since after this succeeds all properties will be validated.\n\t\t\t// See https://json-schema.slack.com/archives/CT7FF623C/p1745592564381459.\n\t\t\tanns.allProperties = true\n\t\t}\n\t}\n\n\tif callerAnns != nil {\n\t\t// Our caller wants to know what we've validated.\n\t\tcallerAnns.merge(&anns)\n\t}\n\treturn nil\n}\n\n// resolveDynamicRef returns the schema referred to by the argument schema's\n// $dynamicRef value.\n// It returns an error if the dynamic reference has no referent.\n// If there is no $dynamicRef, resolveDynamicRef returns nil, nil.\n// See https://json-schema.org/draft/2020-12/json-schema-core#section-8.2.3.2.\nfunc (st *state) resolveDynamicRef(schema *Schema) (*Schema, error) {\n\tif schema.DynamicRef == \"\" {\n\t\treturn nil, nil\n\t}\n\t// The ref behaves lexically or dynamically, but not both.\n\tassert((schema.resolvedDynamicRef == nil) != (schema.dynamicRefAnchor == \"\"),\n\t\t\"DynamicRef not statically resolved properly\")\n\tif r := schema.resolvedDynamicRef; r != nil {\n\t\t// Same as $ref.\n\t\treturn r, nil\n\t}\n\t// Dynamic behavior.\n\t// Look for the base of the outermost schema on the stack with this dynamic\n\t// anchor. (Yes, outermost: the one farthest from here. This the opposite\n\t// of how ordinary dynamic variables behave.)\n\t// Why the base of the schema being validated and not the schema itself?\n\t// Because the base is the scope for anchors. In fact it's possible to\n\t// refer to a schema that is not on the stack, but a child of some base\n\t// on the stack.\n\t// For an example, search for \"detached\" in testdata/draft2020-12/dynamicRef.json.\n\tfor _, s := range st.stack {\n\t\tinfo, ok := s.base.anchors[schema.dynamicRefAnchor]\n\t\tif ok && info.dynamic {\n\t\t\treturn info.schema, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"missing dynamic anchor %q\", schema.dynamicRefAnchor)\n}\n\n// ApplyDefaults modifies an instance by applying the schema's defaults to it. If\n// a schema or sub-schema has a default, then a corresponding zero instance value\n// is set to the default.\n//\n// The JSON Schema specification does not describe how defaults should be interpreted.\n// This method honors defaults only on properties, and only those that are not required.\n// If the instance is a map and the property is missing, the property is added to\n// the map with the default.\n// If the instance is a struct, the field corresponding to the property exists, and\n// its value is zero, the field is set to the default.\n// ApplyDefaults can panic if a default cannot be assigned to a field.\n//\n// The argument must be a pointer to the instance.\n// (In case we decide that top-level defaults are meaningful.)\n//\n// It is recommended to first call Resolve with a ValidateDefaults option of true,\n// then call this method, and lastly call Validate.\n//\n// TODO(jba): consider what defaults on top-level or array instances might mean.\n// TODO(jba): follow $ref and $dynamicRef\n// TODO(jba): apply defaults on sub-schemas to corresponding sub-instances.\nfunc (rs *Resolved) ApplyDefaults(instancep any) error {\n\tst := &state{rs: rs}\n\treturn st.applyDefaults(reflect.ValueOf(instancep), rs.root)\n}\n\n// Leave this as a potentially recursive helper function, because we'll surely want\n// to apply defaults on sub-schemas someday.\nfunc (st *state) applyDefaults(instancep reflect.Value, schema *Schema) (err error) {\n\tdefer util.Wrapf(&err, \"applyDefaults: schema %s, instance %v\", schema, instancep)\n\n\tinstance := instancep.Elem()\n\tif instance.Kind() == reflect.Map || instance.Kind() == reflect.Struct {\n\t\tif instance.Kind() == reflect.Map {\n\t\t\tif kt := instance.Type().Key(); kt.Kind() != reflect.String {\n\t\t\t\treturn fmt.Errorf(\"map key type %s is not a string\", kt)\n\t\t\t}\n\t\t}\n\t\tfor prop, subschema := range schema.Properties {\n\t\t\t// Ignore defaults on required properties. (A required property shouldn't have a default.)\n\t\t\tif schema.isRequired[prop] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tval := property(instance, prop)\n\t\t\tswitch instance.Kind() {\n\t\t\tcase reflect.Map:\n\t\t\t\t// If there is a default for this property, and the map key is missing,\n\t\t\t\t// set the map value to the default.\n\t\t\t\tif subschema.Default != nil && !val.IsValid() {\n\t\t\t\t\t// Create an lvalue, since map values aren't addressable.\n\t\t\t\t\tlvalue := reflect.New(instance.Type().Elem())\n\t\t\t\t\tif err := json.Unmarshal(subschema.Default, lvalue.Interface()); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tinstance.SetMapIndex(reflect.ValueOf(prop), lvalue.Elem())\n\t\t\t\t}\n\t\t\tcase reflect.Struct:\n\t\t\t\t// If there is a default for this property, and the field exists but is zero,\n\t\t\t\t// set the field to the default.\n\t\t\t\tif subschema.Default != nil && val.IsValid() && val.IsZero() {\n\t\t\t\t\tif err := json.Unmarshal(subschema.Default, val.Addr().Interface()); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"applyDefaults: property %s: bad value %s of kind %s\",\n\t\t\t\t\tprop, instance, instance.Kind()))\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// property returns the value of the property of v with the given name, or the invalid\n// reflect.Value if there is none.\n// If v is a map, the property is the value of the map whose key is name.\n// If v is a struct, the property is the value of the field with the given name according\n// to the encoding/json package (see [jsonName]).\n// If v is anything else, property panics.\nfunc property(v reflect.Value, name string) reflect.Value {\n\tswitch v.Kind() {\n\tcase reflect.Map:\n\t\treturn v.MapIndex(reflect.ValueOf(name))\n\tcase reflect.Struct:\n\t\tprops := structPropertiesOf(v.Type())\n\t\t// Ignore nonexistent properties.\n\t\tif sf, ok := props[name]; ok {\n\t\t\treturn v.FieldByIndex(sf.Index)\n\t\t}\n\t\treturn reflect.Value{}\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"property(%q): bad value %s of kind %s\", name, v, v.Kind()))\n\t}\n}\n\n// properties returns an iterator over the names and values of all properties\n// in v, which must be a map or a struct.\n// If a struct, zero-valued properties that are marked omitempty or omitzero\n// are excluded.\nfunc properties(v reflect.Value) iter.Seq2[string, reflect.Value] {\n\treturn func(yield func(string, reflect.Value) bool) {\n\t\tswitch v.Kind() {\n\t\tcase reflect.Map:\n\t\t\tfor k, e := range v.Seq2() {\n\t\t\t\tif !yield(k.String(), e) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\tcase reflect.Struct:\n\t\t\tfor name, sf := range structPropertiesOf(v.Type()) {\n\t\t\t\tval := v.FieldByIndex(sf.Index)\n\t\t\t\tif val.IsZero() {\n\t\t\t\t\tinfo := util.FieldJSONInfo(sf)\n\t\t\t\t\tif info.Settings[\"omitempty\"] || info.Settings[\"omitzero\"] {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(name, val) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"bad value %s of kind %s\", v, v.Kind()))\n\t\t}\n\t}\n}\n\n// numPropertiesBounds returns bounds on the number of v's properties.\n// v must be a map or a struct.\n// If v is a map, both bounds are the map's size.\n// If v is a struct, the max is the number of struct properties.\n// But since we don't know whether a zero value indicates a missing optional property\n// or not, be generous and use the number of non-zero properties as the min.\nfunc numPropertiesBounds(v reflect.Value, isRequired map[string]bool) (int, int) {\n\tswitch v.Kind() {\n\tcase reflect.Map:\n\t\treturn v.Len(), v.Len()\n\tcase reflect.Struct:\n\t\tsp := structPropertiesOf(v.Type())\n\t\tmin := 0\n\t\tfor prop, sf := range sp {\n\t\t\tif !v.FieldByIndex(sf.Index).IsZero() || isRequired[prop] {\n\t\t\t\tmin++\n\t\t\t}\n\t\t}\n\t\treturn min, len(sp)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"properties: bad value: %s of kind %s\", v, v.Kind()))\n\t}\n}\n\n// A propertyMap is a map from property name to struct field index.\ntype propertyMap = map[string]reflect.StructField\n\nvar structProperties sync.Map // from reflect.Type to propertyMap\n\n// structPropertiesOf returns the JSON Schema properties for the struct type t.\n// The caller must not mutate the result.\nfunc structPropertiesOf(t reflect.Type) propertyMap {\n\t// Mutex not necessary: at worst we'll recompute the same value.\n\tif props, ok := structProperties.Load(t); ok {\n\t\treturn props.(propertyMap)\n\t}\n\tprops := map[string]reflect.StructField{}\n\tfor _, sf := range reflect.VisibleFields(t) {\n\t\tinfo := util.FieldJSONInfo(sf)\n\t\tif !info.Omit {\n\t\t\tprops[info.Name] = sf\n\t\t}\n\t}\n\tstructProperties.Store(t, props)\n\treturn props\n}\n"
  },
  {
    "path": "internal/mcp/jsonschema/validate_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage jsonschema\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// The test for validation uses the official test suite, expressed as a set of JSON files.\n// Each file is an array of group objects.\n\n// A testGroup consists of a schema and some tests on it.\ntype testGroup struct {\n\tDescription string\n\tSchema      *Schema\n\tTests       []test\n}\n\n// A test consists of a JSON instance to be validated and the expected result.\ntype test struct {\n\tDescription string\n\tData        any\n\tValid       bool\n}\n\nfunc TestValidate(t *testing.T) {\n\tfiles, err := filepath.Glob(filepath.FromSlash(\"testdata/draft2020-12/*.json\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(files) == 0 {\n\t\tt.Fatal(\"no files\")\n\t}\n\tfor _, file := range files {\n\t\tbase := filepath.Base(file)\n\t\tt.Run(base, func(t *testing.T) {\n\t\t\tdata, err := os.ReadFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar groups []testGroup\n\t\t\tif err := json.Unmarshal(data, &groups); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfor _, g := range groups {\n\t\t\t\tt.Run(g.Description, func(t *testing.T) {\n\t\t\t\t\trs, err := g.Schema.Resolve(&ResolveOptions{Loader: loadRemote})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Fatal(err)\n\t\t\t\t\t}\n\t\t\t\t\tfor _, test := range g.Tests {\n\t\t\t\t\t\tt.Run(test.Description, func(t *testing.T) {\n\t\t\t\t\t\t\terr = rs.Validate(test.Data)\n\t\t\t\t\t\t\tif err != nil && test.Valid {\n\t\t\t\t\t\t\t\tt.Errorf(\"wanted success, but failed with: %v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif err == nil && !test.Valid {\n\t\t\t\t\t\t\t\tt.Error(\"succeeded but wanted failure\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif t.Failed() {\n\t\t\t\t\t\t\t\tt.Errorf(\"schema: %s\", g.Schema.json())\n\t\t\t\t\t\t\t\tt.Fatalf(\"instance: %v (%[1]T)\", test.Data)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestValidateErrors(t *testing.T) {\n\tschema := &Schema{\n\t\tPrefixItems: []*Schema{{Contains: &Schema{Type: \"integer\"}}},\n\t}\n\trs, err := schema.Resolve(nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = rs.Validate([]any{[]any{\"1\"}})\n\twant := \"prefixItems/0\"\n\tif err == nil || !strings.Contains(err.Error(), want) {\n\t\tt.Errorf(\"error:\\n%s\\ndoes not contain %q\", err, want)\n\t}\n}\n\nfunc TestValidateDefaults(t *testing.T) {\n\ts := &Schema{\n\t\tProperties: map[string]*Schema{\n\t\t\t\"a\": {Type: \"integer\", Default: mustMarshal(1)},\n\t\t\t\"b\": {Type: \"string\", Default: mustMarshal(\"s\")},\n\t\t},\n\t\tDefault: mustMarshal(map[string]any{\"a\": 1, \"b\": \"two\"}),\n\t}\n\tif _, err := s.Resolve(&ResolveOptions{ValidateDefaults: true}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ts = &Schema{\n\t\tProperties: map[string]*Schema{\n\t\t\t\"a\": {Type: \"integer\", Default: mustMarshal(3)},\n\t\t\t\"b\": {Type: \"string\", Default: mustMarshal(\"s\")},\n\t\t},\n\t\tDefault: mustMarshal(map[string]any{\"a\": 1, \"b\": 2}),\n\t}\n\t_, err := s.Resolve(&ResolveOptions{ValidateDefaults: true})\n\twant := `has type \"integer\", want \"string\"`\n\tif err == nil || !strings.Contains(err.Error(), want) {\n\t\tt.Errorf(\"Resolve returned error %q, want %q\", err, want)\n\t}\n}\n\nfunc TestApplyDefaults(t *testing.T) {\n\tschema := &Schema{\n\t\tProperties: map[string]*Schema{\n\t\t\t\"A\": {Default: mustMarshal(1)},\n\t\t\t\"B\": {Default: mustMarshal(2)},\n\t\t\t\"C\": {Default: mustMarshal(3)},\n\t\t},\n\t\tRequired: []string{\"C\"},\n\t}\n\trs, err := schema.Resolve(&ResolveOptions{ValidateDefaults: true})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttype S struct{ A, B, C int }\n\tfor _, tt := range []struct {\n\t\tinstancep any // pointer to instance value\n\t\twant      any // desired value (not a pointer)\n\t}{\n\t\t{\n\t\t\t&map[string]any{\"B\": 0},\n\t\t\tmap[string]any{\n\t\t\t\t\"A\": float64(1), // filled from default\n\t\t\t\t\"B\": 0,          // untouched: it was already there\n\t\t\t\t// \"C\" not added: it is required (Validate will catch that)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t&S{B: 1},\n\t\t\tS{\n\t\t\t\tA: 1, // filled from default\n\t\t\t\tB: 1, // untouched: non-zero\n\t\t\t\tC: 0, // untouched: required\n\t\t\t},\n\t\t},\n\t} {\n\t\tif err := rs.ApplyDefaults(tt.instancep); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgot := reflect.ValueOf(tt.instancep).Elem().Interface() // dereference the pointer\n\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\tt.Errorf(\"\\ngot  %#v\\nwant %#v\", got, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestStructInstance(t *testing.T) {\n\tinstance := struct {\n\t\tI int\n\t\tB bool `json:\"b\"`\n\t\tP *int // either missing or nil\n\t\tu int  // unexported: not a property\n\t}{1, true, nil, 0}\n\n\tfor _, tt := range []struct {\n\t\ts    Schema\n\t\twant bool\n\t}{\n\t\t{\n\t\t\tSchema{MinProperties: Ptr(4)},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{MinProperties: Ptr(3)},\n\t\t\ttrue, // P interpreted as present\n\t\t},\n\t\t{\n\t\t\tSchema{MaxProperties: Ptr(1)},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{MaxProperties: Ptr(2)},\n\t\t\ttrue, // P interpreted as absent\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"i\"}}, // the name is \"I\"\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"B\"}}, // the name is \"b\"\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{PropertyNames: &Schema{MinLength: Ptr(2)}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{Properties: map[string]*Schema{\"b\": {Type: \"boolean\"}}},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\tSchema{Properties: map[string]*Schema{\"b\": {Type: \"number\"}}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"I\"}},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"I\", \"P\"}},\n\t\t\ttrue, // P interpreted as present\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"I\", \"P\"}, Properties: map[string]*Schema{\"P\": {Type: \"number\"}}},\n\t\t\tfalse, // P interpreted as present, but not a number\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"I\"}, Properties: map[string]*Schema{\"P\": {Type: \"number\"}}},\n\t\t\ttrue, // P not required, so interpreted as absent\n\t\t},\n\t\t{\n\t\t\tSchema{Required: []string{\"I\"}, AdditionalProperties: falseSchema()},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{DependentRequired: map[string][]string{\"b\": {\"u\"}}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{DependentSchemas: map[string]*Schema{\"b\": falseSchema()}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tSchema{UnevaluatedProperties: falseSchema()},\n\t\t\tfalse,\n\t\t},\n\t} {\n\t\tres, err := tt.s.Resolve(nil)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = res.Validate(instance)\n\t\tif err == nil && !tt.want {\n\t\t\tt.Errorf(\"succeeded unexpectedly\\nschema = %s\", tt.s.json())\n\t\t} else if err != nil && tt.want {\n\t\t\tt.Errorf(\"Validate: %v\\nschema = %s\", err, tt.s.json())\n\t\t}\n\t}\n}\n\nfunc mustMarshal(x any) json.RawMessage {\n\tdata, err := json.Marshal(x)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn json.RawMessage(data)\n}\n\n// loadRemote loads a remote reference used in the test suite.\nfunc loadRemote(uri *url.URL) (*Schema, error) {\n\t// Anything with localhost:1234 refers to the remotes directory in the test suite repo.\n\tif uri.Host == \"localhost:1234\" {\n\t\treturn loadSchemaFromFile(filepath.FromSlash(filepath.Join(\"testdata/remotes\", uri.Path)))\n\t}\n\t// One test needs the meta-schema files.\n\tconst metaPrefix = \"https://json-schema.org/draft/2020-12/\"\n\tif after, ok := strings.CutPrefix(uri.String(), metaPrefix); ok {\n\t\treturn loadSchemaFromFile(filepath.FromSlash(\"meta-schemas/draft2020-12/\" + after + \".json\"))\n\t}\n\treturn nil, fmt.Errorf(\"don't know how to load %s\", uri)\n}\n\nfunc loadSchemaFromFile(filename string) (*Schema, error) {\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar s Schema\n\tif err := json.Unmarshal(data, &s); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshaling JSON at %s: %w\", filename, err)\n\t}\n\treturn &s, nil\n}\n"
  },
  {
    "path": "internal/mcp/logging.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"log/slog\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Logging levels.\nconst (\n\tLevelDebug     = slog.LevelDebug\n\tLevelInfo      = slog.LevelInfo\n\tLevelNotice    = (slog.LevelInfo + slog.LevelWarn) / 2\n\tLevelWarning   = slog.LevelWarn\n\tLevelError     = slog.LevelError\n\tLevelCritical  = slog.LevelError + 4\n\tLevelAlert     = slog.LevelError + 8\n\tLevelEmergency = slog.LevelError + 12\n)\n\nvar slogToMCP = map[slog.Level]LoggingLevel{\n\tLevelDebug:     \"debug\",\n\tLevelInfo:      \"info\",\n\tLevelNotice:    \"notice\",\n\tLevelWarning:   \"warning\",\n\tLevelError:     \"error\",\n\tLevelCritical:  \"critical\",\n\tLevelAlert:     \"alert\",\n\tLevelEmergency: \"emergency\",\n}\n\nvar mcpToSlog = make(map[LoggingLevel]slog.Level)\n\nfunc init() {\n\tfor sl, ml := range slogToMCP {\n\t\tmcpToSlog[ml] = sl\n\t}\n}\n\nfunc slogLevelToMCP(sl slog.Level) LoggingLevel {\n\tif ml, ok := slogToMCP[sl]; ok {\n\t\treturn ml\n\t}\n\treturn \"debug\" // for lack of a better idea\n}\n\nfunc mcpLevelToSlog(ll LoggingLevel) slog.Level {\n\tif sl, ok := mcpToSlog[ll]; ok {\n\t\treturn sl\n\t}\n\t// TODO: is there a better default?\n\treturn LevelDebug\n}\n\n// compareLevels behaves like [cmp.Compare] for [LoggingLevel]s.\nfunc compareLevels(l1, l2 LoggingLevel) int {\n\treturn cmp.Compare(mcpLevelToSlog(l1), mcpLevelToSlog(l2))\n}\n\n// LoggingHandlerOptions are options for a LoggingHandler.\ntype LoggingHandlerOptions struct {\n\t// The value for the \"logger\" field of logging notifications.\n\tLoggerName string\n\t// Limits the rate at which log messages are sent.\n\t// If zero, there is no rate limiting.\n\tMinInterval time.Duration\n}\n\n// A LoggingHandler is a [slog.Handler] for MCP.\ntype LoggingHandler struct {\n\topts LoggingHandlerOptions\n\tss   *ServerSession\n\t// Ensures that the buffer reset is atomic with the write (see Handle).\n\t// A pointer so that clones share the mutex. See\n\t// https://github.com/golang/example/blob/master/slog-handler-guide/README.md#getting-the-mutex-right.\n\tmu              *sync.Mutex\n\tlastMessageSent time.Time // for rate-limiting\n\tbuf             *bytes.Buffer\n\thandler         slog.Handler\n}\n\n// NewLoggingHandler creates a [LoggingHandler] that logs to the given [ServerSession] using a\n// [slog.JSONHandler].\nfunc NewLoggingHandler(ss *ServerSession, opts *LoggingHandlerOptions) *LoggingHandler {\n\tvar buf bytes.Buffer\n\tjsonHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{\n\t\tReplaceAttr: func(_ []string, a slog.Attr) slog.Attr {\n\t\t\t// Remove level: it appears in LoggingMessageParams.\n\t\t\tif a.Key == slog.LevelKey {\n\t\t\t\treturn slog.Attr{}\n\t\t\t}\n\t\t\treturn a\n\t\t},\n\t})\n\tlh := &LoggingHandler{\n\t\tss:      ss,\n\t\tmu:      new(sync.Mutex),\n\t\tbuf:     &buf,\n\t\thandler: jsonHandler,\n\t}\n\tif opts != nil {\n\t\tlh.opts = *opts\n\t}\n\treturn lh\n}\n\n// Enabled implements [slog.Handler.Enabled] by comparing level to the [ServerSession]'s level.\nfunc (h *LoggingHandler) Enabled(ctx context.Context, level slog.Level) bool {\n\t// This is also checked in ServerSession.LoggingMessage, so checking it here\n\t// is just an optimization that skips building the JSON.\n\th.ss.mu.Lock()\n\tmcpLevel := h.ss.logLevel\n\th.ss.mu.Unlock()\n\treturn level >= mcpLevelToSlog(mcpLevel)\n}\n\n// WithAttrs implements [slog.Handler.WithAttrs].\nfunc (h *LoggingHandler) WithAttrs(as []slog.Attr) slog.Handler {\n\th2 := *h\n\th2.handler = h.handler.WithAttrs(as)\n\treturn &h2\n}\n\n// WithGroup implements [slog.Handler.WithGroup].\nfunc (h *LoggingHandler) WithGroup(name string) slog.Handler {\n\th2 := *h\n\th2.handler = h.handler.WithGroup(name)\n\treturn &h2\n}\n\n// Handle implements [slog.Handler.Handle] by writing the Record to a JSONHandler,\n// then calling [ServerSession.LoggingMesssage] with the result.\nfunc (h *LoggingHandler) Handle(ctx context.Context, r slog.Record) error {\n\terr := h.handle(ctx, r)\n\t// TODO(jba): find a way to surface the error.\n\t// The return value will probably be ignored.\n\treturn err\n}\n\nfunc (h *LoggingHandler) handle(ctx context.Context, r slog.Record) error {\n\t// Observe the rate limit.\n\t// TODO(jba): use golang.org/x/time/rate. (We can't here because it would require adding\n\t// golang.org/x/time to the go.mod file.)\n\th.mu.Lock()\n\tskip := time.Since(h.lastMessageSent) < h.opts.MinInterval\n\th.mu.Unlock()\n\tif skip {\n\t\treturn nil\n\t}\n\n\tvar err error\n\t// Make the buffer reset atomic with the record write.\n\t// We are careful here in the unlikely event that the handler panics.\n\t// We don't want to hold the lock for the entire function, because Notify is\n\t// an I/O operation.\n\t// This can result in out-of-order delivery.\n\tfunc() {\n\t\th.mu.Lock()\n\t\tdefer h.mu.Unlock()\n\t\th.buf.Reset()\n\t\terr = h.handler.Handle(ctx, r)\n\t}()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\th.mu.Lock()\n\th.lastMessageSent = time.Now()\n\th.mu.Unlock()\n\n\tparams := &LoggingMessageParams{\n\t\tLogger: h.opts.LoggerName,\n\t\tLevel:  slogLevelToMCP(r.Level),\n\t\tData:   json.RawMessage(h.buf.Bytes()),\n\t}\n\t// We pass the argument context to Notify, even though slog.Handler.Handle's\n\t// documentation says not to.\n\t// In this case logging is a service to clients, not a means for debugging the\n\t// server, so we want to cancel the log message.\n\treturn h.ss.LoggingMessage(ctx, params)\n}\n"
  },
  {
    "path": "internal/mcp/mcp-repo-replace.txt",
    "content": "jsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"==>\"github.com/modelcontextprotocol/go-sdk/internal/jsonrpc2\"\ngolang.org/x/tools/internal/xcontext==>github.com/modelcontextprotocol/go-sdk/internal/xcontext\ngolang.org/x/tools/internal/mcp/internal==>github.com/modelcontextprotocol/go-sdk/internal\ngolang.org/x/tools/internal/mcp/jsonschema==>github.com/modelcontextprotocol/go-sdk/jsonschema\ngolang.org/x/tools/internal/mcp/examples==>github.com/modelcontextprotocol/go-sdk/examples\ngolang.org/x/tools/internal/mcp/design==>github.com/modelcontextprotocol/go-sdk/design\ngolang.org/x/tools/internal/mcp==>github.com/modelcontextprotocol/go-sdk/mcp\ngoverned by a BSD-style==>governed by an MIT-style\nregex:Copyright (20\\d\\d) The Go Authors==>Copyright \\1 The Go MCP SDK Authors\n"
  },
  {
    "path": "internal/mcp/mcp.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run generate.go\n//go:generate ./internal/readme/build.sh\n\n// The mcp package provides an SDK for writing model context protocol clients\n// and servers.\n//\n// To get started, create either a [Client] or [Server], and connect it to a\n// peer using a [Transport]. The diagram below illustrates how this works:\n//\n//\tClient                                                   Server\n//\t ⇅                          (jsonrpc2)                     ⇅\n//\tClientSession ⇄ Client Transport ⇄ Server Transport ⇄ ServerSession\n//\n// A [Client] is an MCP client, which can be configured with various client\n// capabilities. Clients may be connected to a [Server] instance\n// using the [Client.Connect] method.\n//\n// Similarly, a [Server] is an MCP server, which can be configured with various\n// server capabilities. Servers may be connected to one or more [Client]\n// instances using the [Server.Connect] method, which creates a\n// [ServerSession].\n//\n// A [Transport] connects a bidirectional [Connection] of jsonrpc2 messages. In\n// practice, transports in the MCP spec are either client transports or\n// server transports. For example, the [StdioTransport] is a server transport\n// that communicates over stdin/stdout, and its counterpart is a\n// [CommandTransport] that communicates with a subprocess over its\n// stdin/stdout.\n//\n// Some transports may hide more complicated details, such as an\n// [SSEClientTransport], which reads messages via server-sent events on a\n// hanging GET request, and writes them to a POST endpoint. Users of this SDK\n// may define their own custom Transports by implementing the [Transport]\n// interface.\npackage mcp\n"
  },
  {
    "path": "internal/mcp/mcp_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"net/url\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\ntype hiParams struct {\n\tName string\n}\n\nfunc sayHi(ctx context.Context, ss *ServerSession, params *CallToolParamsFor[hiParams]) (*CallToolResultFor[any], error) {\n\tif err := ss.Ping(ctx, nil); err != nil {\n\t\treturn nil, fmt.Errorf(\"ping failed: %v\", err)\n\t}\n\treturn &CallToolResultFor[any]{Content: []*Content{NewTextContent(\"hi \" + params.Arguments.Name)}}, nil\n}\n\nfunc TestEndToEnd(t *testing.T) {\n\tctx := context.Background()\n\tvar ct, st Transport = NewInMemoryTransports()\n\n\t// Channels to check if notification callbacks happened.\n\tnotificationChans := map[string]chan int{}\n\tfor _, name := range []string{\"initialized\", \"roots\", \"tools\", \"prompts\", \"resources\", \"progress_server\", \"progress_client\"} {\n\t\tnotificationChans[name] = make(chan int, 1)\n\t}\n\twaitForNotification := func(t *testing.T, name string) {\n\t\tt.Helper()\n\t\tselect {\n\t\tcase <-notificationChans[name]:\n\t\tcase <-time.After(time.Second):\n\t\t\tt.Fatalf(\"%s handler never called\", name)\n\t\t}\n\t}\n\n\tsopts := &ServerOptions{\n\t\tInitializedHandler:      func(context.Context, *ServerSession, *InitializedParams) { notificationChans[\"initialized\"] <- 0 },\n\t\tRootsListChangedHandler: func(context.Context, *ServerSession, *RootsListChangedParams) { notificationChans[\"roots\"] <- 0 },\n\t\tProgressNotificationHandler: func(context.Context, *ServerSession, *ProgressNotificationParams) {\n\t\t\tnotificationChans[\"progress_server\"] <- 0\n\t\t},\n\t}\n\ts := NewServer(\"testServer\", \"v1.0.0\", sopts)\n\tadd(tools, s.AddTools, \"greet\", \"fail\")\n\tadd(prompts, s.AddPrompts, \"code_review\", \"fail\")\n\tadd(resources, s.AddResources, \"info.txt\", \"fail.txt\")\n\n\t// Connect the server.\n\tss, err := s.Connect(ctx, st)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := slices.Collect(s.Sessions()); len(got) != 1 {\n\t\tt.Errorf(\"after connection, Clients() has length %d, want 1\", len(got))\n\t}\n\n\t// Wait for the server to exit after the client closes its connection.\n\tvar clientWG sync.WaitGroup\n\tclientWG.Add(1)\n\tgo func() {\n\t\tif err := ss.Wait(); err != nil {\n\t\t\tt.Errorf(\"server failed: %v\", err)\n\t\t}\n\t\tclientWG.Done()\n\t}()\n\n\tloggingMessages := make(chan *LoggingMessageParams, 100) // big enough for all logging\n\topts := &ClientOptions{\n\t\tCreateMessageHandler: func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error) {\n\t\t\treturn &CreateMessageResult{Model: \"aModel\"}, nil\n\t\t},\n\t\tToolListChangedHandler:     func(context.Context, *ClientSession, *ToolListChangedParams) { notificationChans[\"tools\"] <- 0 },\n\t\tPromptListChangedHandler:   func(context.Context, *ClientSession, *PromptListChangedParams) { notificationChans[\"prompts\"] <- 0 },\n\t\tResourceListChangedHandler: func(context.Context, *ClientSession, *ResourceListChangedParams) { notificationChans[\"resources\"] <- 0 },\n\t\tLoggingMessageHandler: func(_ context.Context, _ *ClientSession, lm *LoggingMessageParams) {\n\t\t\tloggingMessages <- lm\n\t\t},\n\t\tProgressNotificationHandler: func(context.Context, *ClientSession, *ProgressNotificationParams) {\n\t\t\tnotificationChans[\"progress_client\"] <- 0\n\t\t},\n\t}\n\tc := NewClient(\"testClient\", \"v1.0.0\", opts)\n\trootAbs, err := filepath.Abs(filepath.FromSlash(\"testdata/files\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tc.AddRoots(&Root{URI: \"file://\" + rootAbs})\n\n\t// Connect the client.\n\tcs, err := c.Connect(ctx, ct)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twaitForNotification(t, \"initialized\")\n\tif err := cs.Ping(ctx, nil); err != nil {\n\t\tt.Fatalf(\"ping failed: %v\", err)\n\t}\n\tt.Run(\"prompts\", func(t *testing.T) {\n\t\tres, err := cs.ListPrompts(ctx, nil)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"prompts/list failed: %v\", err)\n\t\t}\n\t\twantPrompts := []*Prompt{\n\t\t\t{\n\t\t\t\tName:        \"code_review\",\n\t\t\t\tDescription: \"do a code review\",\n\t\t\t\tArguments:   []*PromptArgument{{Name: \"Code\", Required: true}},\n\t\t\t},\n\t\t\t{Name: \"fail\"},\n\t\t}\n\t\tif diff := cmp.Diff(wantPrompts, res.Prompts); diff != \"\" {\n\t\t\tt.Fatalf(\"prompts/list mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tgotReview, err := cs.GetPrompt(ctx, &GetPromptParams{Name: \"code_review\", Arguments: map[string]string{\"Code\": \"1+1\"}})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twantReview := &GetPromptResult{\n\t\t\tDescription: \"Code review prompt\",\n\t\t\tMessages: []*PromptMessage{{\n\t\t\t\tContent: NewTextContent(\"Please review the following code: 1+1\"),\n\t\t\t\tRole:    \"user\",\n\t\t\t}},\n\t\t}\n\t\tif diff := cmp.Diff(wantReview, gotReview); diff != \"\" {\n\t\t\tt.Errorf(\"prompts/get 'code_review' mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tif _, err := cs.GetPrompt(ctx, &GetPromptParams{Name: \"fail\"}); err == nil || !strings.Contains(err.Error(), errTestFailure.Error()) {\n\t\t\tt.Errorf(\"fail returned unexpected error: got %v, want containing %v\", err, errTestFailure)\n\t\t}\n\n\t\ts.AddPrompts(&ServerPrompt{Prompt: &Prompt{Name: \"T\"}})\n\t\twaitForNotification(t, \"prompts\")\n\t\ts.RemovePrompts(\"T\")\n\t\twaitForNotification(t, \"prompts\")\n\t})\n\n\tt.Run(\"tools\", func(t *testing.T) {\n\t\tres, err := cs.ListTools(ctx, nil)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"tools/list failed: %v\", err)\n\t\t}\n\t\twantTools := []*Tool{\n\t\t\t{\n\t\t\t\tName:        \"fail\",\n\t\t\t\tInputSchema: nil,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:        \"greet\",\n\t\t\t\tDescription: \"say hi\",\n\t\t\t\tInputSchema: &jsonschema.Schema{\n\t\t\t\t\tType:     \"object\",\n\t\t\t\t\tRequired: []string{\"Name\"},\n\t\t\t\t\tProperties: map[string]*jsonschema.Schema{\n\t\t\t\t\t\t\"Name\": {Type: \"string\"},\n\t\t\t\t\t},\n\t\t\t\t\tAdditionalProperties: falseSchema(),\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tif diff := cmp.Diff(wantTools, res.Tools, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\tt.Fatalf(\"tools/list mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tgotHi, err := cs.CallTool(ctx, &CallToolParams{\n\t\t\tName:      \"greet\",\n\t\t\tArguments: map[string]any{\"name\": \"user\"},\n\t\t})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twantHi := &CallToolResult{\n\t\t\tContent: []*Content{{Type: \"text\", Text: \"hi user\"}},\n\t\t}\n\t\tif diff := cmp.Diff(wantHi, gotHi); diff != \"\" {\n\t\t\tt.Errorf(\"tools/call 'greet' mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tgotFail, err := cs.CallTool(ctx, &CallToolParams{\n\t\t\tName:      \"fail\",\n\t\t\tArguments: map[string]any{},\n\t\t})\n\t\t// Counter-intuitively, when a tool fails, we don't expect an RPC error for\n\t\t// call tool: instead, the failure is embedded in the result.\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twantFail := &CallToolResult{\n\t\t\tIsError: true,\n\t\t\tContent: []*Content{{Type: \"text\", Text: errTestFailure.Error()}},\n\t\t}\n\t\tif diff := cmp.Diff(wantFail, gotFail); diff != \"\" {\n\t\t\tt.Errorf(\"tools/call 'fail' mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\ts.AddTools(&ServerTool{Tool: &Tool{Name: \"T\"}, Handler: nopHandler})\n\t\twaitForNotification(t, \"tools\")\n\t\ts.RemoveTools(\"T\")\n\t\twaitForNotification(t, \"tools\")\n\t})\n\n\tt.Run(\"resources\", func(t *testing.T) {\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\tt.Skip(\"TODO: fix for Windows\")\n\t\t}\n\t\twantResources := []*Resource{resource2, resource1}\n\t\tlrres, err := cs.ListResources(ctx, nil)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff(wantResources, lrres.Resources); diff != \"\" {\n\t\t\tt.Errorf(\"resources/list mismatch (-want, +got):\\n%s\", diff)\n\t\t}\n\n\t\ttemplate := &ResourceTemplate{\n\t\t\tName:        \"rt\",\n\t\t\tMIMEType:    \"text/template\",\n\t\t\tURITemplate: \"file:///{+filename}\", // the '+' means that filename can contain '/'\n\t\t}\n\t\tst := &ServerResourceTemplate{ResourceTemplate: template, Handler: readHandler}\n\t\ts.AddResourceTemplates(st)\n\t\ttres, err := cs.ListResourceTemplates(ctx, nil)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff([]*ResourceTemplate{template}, tres.ResourceTemplates); diff != \"\" {\n\t\t\tt.Errorf(\"resources/list mismatch (-want, +got):\\n%s\", diff)\n\t\t}\n\n\t\tfor _, tt := range []struct {\n\t\t\turi      string\n\t\t\tmimeType string // \"\": not found; \"text/plain\": resource; \"text/template\": template\n\t\t\tfail     bool   // non-nil error returned\n\t\t}{\n\t\t\t{\"file:///info.txt\", \"text/plain\", false},\n\t\t\t{\"file:///fail.txt\", \"\", false},\n\t\t\t{\"file:///template.txt\", \"text/template\", false},\n\t\t\t{\"file:///../private.txt\", \"\", true}, // not found: escaping disallowed\n\t\t} {\n\t\t\trres, err := cs.ReadResource(ctx, &ReadResourceParams{URI: tt.uri})\n\t\t\tif err != nil {\n\t\t\t\tif code := errorCode(err); code == CodeResourceNotFound {\n\t\t\t\t\tif tt.mimeType != \"\" {\n\t\t\t\t\t\tt.Errorf(\"%s: not found but expected it to be\", tt.uri)\n\t\t\t\t\t}\n\t\t\t\t} else if !tt.fail {\n\t\t\t\t\tt.Errorf(\"%s: unexpected error %v\", tt.uri, err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif tt.fail {\n\t\t\t\t\tt.Errorf(\"%s: unexpected success\", tt.uri)\n\t\t\t\t} else if g, w := len(rres.Contents), 1; g != w {\n\t\t\t\t\tt.Errorf(\"got %d contents, wanted %d\", g, w)\n\t\t\t\t} else {\n\t\t\t\t\tc := rres.Contents[0]\n\t\t\t\t\tif got := c.URI; got != tt.uri {\n\t\t\t\t\t\tt.Errorf(\"got uri %q, want %q\", got, tt.uri)\n\t\t\t\t\t}\n\t\t\t\t\tif got := c.MIMEType; got != tt.mimeType {\n\t\t\t\t\t\tt.Errorf(\"%s: got MIME type %q, want %q\", tt.uri, got, tt.mimeType)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.AddResources(&ServerResource{Resource: &Resource{URI: \"http://U\"}})\n\t\twaitForNotification(t, \"resources\")\n\t\ts.RemoveResources(\"http://U\")\n\t\twaitForNotification(t, \"resources\")\n\t})\n\tt.Run(\"roots\", func(t *testing.T) {\n\t\trootRes, err := ss.ListRoots(ctx, &ListRootsParams{})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tgotRoots := rootRes.Roots\n\t\twantRoots := slices.Collect(c.roots.all())\n\t\tif diff := cmp.Diff(wantRoots, gotRoots); diff != \"\" {\n\t\t\tt.Errorf(\"roots/list mismatch (-want +got):\\n%s\", diff)\n\t\t}\n\n\t\tc.AddRoots(&Root{URI: \"U\"})\n\t\twaitForNotification(t, \"roots\")\n\t\tc.RemoveRoots(\"U\")\n\t\twaitForNotification(t, \"roots\")\n\t})\n\tt.Run(\"sampling\", func(t *testing.T) {\n\t\t// TODO: test that a client that doesn't have the handler returns CodeUnsupportedMethod.\n\t\tres, err := ss.CreateMessage(ctx, &CreateMessageParams{})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif g, w := res.Model, \"aModel\"; g != w {\n\t\t\tt.Errorf(\"got %q, want %q\", g, w)\n\t\t}\n\t})\n\tt.Run(\"logging\", func(t *testing.T) {\n\t\twant := []*LoggingMessageParams{\n\t\t\t{\n\t\t\t\tLogger: \"test\",\n\t\t\t\tLevel:  \"warning\",\n\t\t\t\tData: map[string]any{\n\t\t\t\t\t\"msg\":     \"first\",\n\t\t\t\t\t\"name\":    \"Pat\",\n\t\t\t\t\t\"logtest\": true,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tLogger: \"test\",\n\t\t\t\tLevel:  \"alert\",\n\t\t\t\tData: map[string]any{\n\t\t\t\t\t\"msg\":     \"second\",\n\t\t\t\t\t\"count\":   2.0,\n\t\t\t\t\t\"logtest\": true,\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tcheck := func(t *testing.T) {\n\t\t\tt.Helper()\n\t\t\tvar got []*LoggingMessageParams\n\t\t\t// Read messages from this test until we've seen all we expect.\n\t\t\tfor len(got) < len(want) {\n\t\t\t\tselect {\n\t\t\t\tcase p := <-loggingMessages:\n\t\t\t\t\t// Ignore logging from other tests.\n\t\t\t\t\tif m, ok := p.Data.(map[string]any); ok && m[\"logtest\"] != nil {\n\t\t\t\t\t\tdelete(m, \"time\") // remove time because it changes\n\t\t\t\t\t\tgot = append(got, p)\n\t\t\t\t\t}\n\t\t\t\tcase <-time.After(time.Second):\n\t\t\t\t\tt.Fatal(\"timed out waiting for log messages\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"mismatch (-want, +got):\\n%s\", diff)\n\t\t\t}\n\t\t}\n\n\t\tt.Run(\"direct\", func(t *testing.T) { // Use the LoggingMessage method directly.\n\n\t\t\tmustLog := func(level LoggingLevel, data any) {\n\t\t\t\tt.Helper()\n\t\t\t\tif err := ss.LoggingMessage(ctx, &LoggingMessageParams{\n\t\t\t\t\tLogger: \"test\",\n\t\t\t\t\tLevel:  level,\n\t\t\t\t\tData:   data,\n\t\t\t\t}); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Nothing should be logged until the client sets a level.\n\t\t\tmustLog(\"info\", \"before\")\n\t\t\tif err := cs.SetLevel(ctx, &SetLevelParams{Level: \"warning\"}); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tmustLog(\"warning\", want[0].Data)\n\t\t\tmustLog(\"debug\", \"nope\")    // below the level\n\t\t\tmustLog(\"info\", \"negative\") // below the level\n\t\t\tmustLog(\"alert\", want[1].Data)\n\t\t\tcheck(t)\n\t\t})\n\n\t\tt.Run(\"handler\", func(t *testing.T) { // Use the slog handler.\n\t\t\t// We can't check the \"before SetLevel\" behavior because it's already been set.\n\t\t\t// Not a big deal: that check is in LoggingMessage anyway.\n\t\t\tlogger := slog.New(NewLoggingHandler(ss, &LoggingHandlerOptions{LoggerName: \"test\"}))\n\t\t\tlogger.Warn(\"first\", \"name\", \"Pat\", \"logtest\", true)\n\t\t\tlogger.Debug(\"nope\")    // below the level\n\t\t\tlogger.Info(\"negative\") // below the level\n\t\t\tlogger.Log(ctx, LevelAlert, \"second\", \"count\", 2, \"logtest\", true)\n\t\t\tcheck(t)\n\t\t})\n\t})\n\tt.Run(\"progress\", func(t *testing.T) {\n\t\tss.NotifyProgress(ctx, &ProgressNotificationParams{\n\t\t\tProgressToken: \"token-xyz\",\n\t\t\tMessage:       \"progress update\",\n\t\t\tProgress:      0.5,\n\t\t\tTotal:         2,\n\t\t})\n\t\twaitForNotification(t, \"progress_client\")\n\t\tcs.NotifyProgress(ctx, &ProgressNotificationParams{\n\t\t\tProgressToken: \"token-abc\",\n\t\t\tMessage:       \"progress update\",\n\t\t\tProgress:      1,\n\t\t\tTotal:         2,\n\t\t})\n\t\twaitForNotification(t, \"progress_server\")\n\t})\n\n\t// Disconnect.\n\tcs.Close()\n\tclientWG.Wait()\n\n\t// After disconnecting, neither client nor server should have any\n\t// connections.\n\tfor range s.Sessions() {\n\t\tt.Errorf(\"unexpected client after disconnection\")\n\t}\n}\n\n// Registry of values to be referenced in tests.\nvar (\n\terrTestFailure = errors.New(\"mcp failure\")\n\n\ttools = map[string]*ServerTool{\n\t\t\"greet\": NewServerTool(\"greet\", \"say hi\", sayHi),\n\t\t\"fail\": {\n\t\t\tTool: &Tool{Name: \"fail\"},\n\t\t\tHandler: func(context.Context, *ServerSession, *CallToolParamsFor[map[string]any]) (*CallToolResult, error) {\n\t\t\t\treturn nil, errTestFailure\n\t\t\t},\n\t\t},\n\t}\n\n\tprompts = map[string]*ServerPrompt{\n\t\t\"code_review\": {\n\t\t\tPrompt: &Prompt{\n\t\t\t\tName:        \"code_review\",\n\t\t\t\tDescription: \"do a code review\",\n\t\t\t\tArguments:   []*PromptArgument{{Name: \"Code\", Required: true}},\n\t\t\t},\n\t\t\tHandler: func(_ context.Context, _ *ServerSession, params *GetPromptParams) (*GetPromptResult, error) {\n\t\t\t\treturn &GetPromptResult{\n\t\t\t\t\tDescription: \"Code review prompt\",\n\t\t\t\t\tMessages: []*PromptMessage{\n\t\t\t\t\t\t{Role: \"user\", Content: NewTextContent(\"Please review the following code: \" + params.Arguments[\"Code\"])},\n\t\t\t\t\t},\n\t\t\t\t}, nil\n\t\t\t},\n\t\t},\n\t\t\"fail\": {\n\t\t\tPrompt: &Prompt{Name: \"fail\"},\n\t\t\tHandler: func(_ context.Context, _ *ServerSession, _ *GetPromptParams) (*GetPromptResult, error) {\n\t\t\t\treturn nil, errTestFailure\n\t\t\t},\n\t\t},\n\t}\n\n\tresource1 = &Resource{\n\t\tName:     \"public\",\n\t\tMIMEType: \"text/plain\",\n\t\tURI:      \"file:///info.txt\",\n\t}\n\tresource2 = &Resource{\n\t\tName:     \"public\", // names are not unique IDs\n\t\tMIMEType: \"text/plain\",\n\t\tURI:      \"file:///fail.txt\",\n\t}\n\tresource3 = &Resource{\n\t\tName:     \"info\",\n\t\tMIMEType: \"text/plain\",\n\t\tURI:      \"embedded:info\",\n\t}\n\treadHandler = fileResourceHandler(\"testdata/files\")\n\tresources   = map[string]*ServerResource{\n\t\t\"info.txt\": {resource1, readHandler},\n\t\t\"fail.txt\": {resource2, readHandler},\n\t\t\"info\":     {resource3, handleEmbeddedResource},\n\t}\n)\n\nvar embeddedResources = map[string]string{\n\t\"info\": \"This is the MCP test server.\",\n}\n\nfunc handleEmbeddedResource(_ context.Context, _ *ServerSession, params *ReadResourceParams) (*ReadResourceResult, error) {\n\tu, err := url.Parse(params.URI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif u.Scheme != \"embedded\" {\n\t\treturn nil, fmt.Errorf(\"wrong scheme: %q\", u.Scheme)\n\t}\n\tkey := u.Opaque\n\ttext, ok := embeddedResources[key]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no embedded resource named %q\", key)\n\t}\n\treturn &ReadResourceResult{\n\t\tContents: []*ResourceContents{NewTextResourceContents(params.URI, \"text/plain\", text)},\n\t}, nil\n}\n\n// Add calls the given function to add the named features.\nfunc add[T any](m map[string]T, add func(...T), names ...string) {\n\tfor _, name := range names {\n\t\tfeat, ok := m[name]\n\t\tif !ok {\n\t\t\tpanic(\"missing feature \" + name)\n\t\t}\n\t\tadd(feat)\n\t}\n}\n\n// errorCode returns the code associated with err.\n// If err is nil, it returns 0.\n// If there is no code, it returns -1.\nfunc errorCode(err error) int64 {\n\tif err == nil {\n\t\treturn 0\n\t}\n\tvar werr *jsonrpc2.WireError\n\tif errors.As(err, &werr) {\n\t\treturn werr.Code\n\t}\n\treturn -1\n}\n\n// basicConnection returns a new basic client-server connection configured with\n// the provided tools.\n//\n// The caller should cancel either the client connection or server connection\n// when the connections are no longer needed.\nfunc basicConnection(t *testing.T, tools ...*ServerTool) (*ServerSession, *ClientSession) {\n\tt.Helper()\n\n\tctx := context.Background()\n\tct, st := NewInMemoryTransports()\n\n\ts := NewServer(\"testServer\", \"v1.0.0\", nil)\n\n\t// The 'greet' tool says hi.\n\ts.AddTools(tools...)\n\tss, err := s.Connect(ctx, st)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tc := NewClient(\"testClient\", \"v1.0.0\", nil)\n\tcs, err := c.Connect(ctx, ct)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn ss, cs\n}\n\nfunc TestServerClosing(t *testing.T) {\n\tcc, cs := basicConnection(t, NewServerTool(\"greet\", \"say hi\", sayHi))\n\tdefer cs.Close()\n\n\tctx := context.Background()\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tif err := cs.Wait(); err != nil {\n\t\t\tt.Errorf(\"server connection failed: %v\", err)\n\t\t}\n\t\twg.Done()\n\t}()\n\tif _, err := cs.CallTool(ctx, &CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"user\"},\n\t}); err != nil {\n\t\tt.Fatalf(\"after connecting: %v\", err)\n\t}\n\tcc.Close()\n\twg.Wait()\n\tif _, err := cs.CallTool(ctx, &CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"user\"},\n\t}); !errors.Is(err, ErrConnectionClosed) {\n\t\tt.Errorf(\"after disconnection, got error %v, want EOF\", err)\n\t}\n}\n\nfunc TestBatching(t *testing.T) {\n\tctx := context.Background()\n\tct, st := NewInMemoryTransports()\n\n\ts := NewServer(\"testServer\", \"v1.0.0\", nil)\n\t_, err := s.Connect(ctx, st)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tc := NewClient(\"testClient\", \"v1.0.0\", nil)\n\t// TODO: this test is broken, because increasing the batch size here causes\n\t// 'initialize' to block. Therefore, we can only test with a size of 1.\n\t// Since batching is being removed, we can probably just delete this.\n\tconst batchSize = 1\n\tcs, err := c.Connect(ctx, ct)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer cs.Close()\n\n\terrs := make(chan error, batchSize)\n\tfor i := range batchSize {\n\t\tgo func() {\n\t\t\t_, err := cs.ListTools(ctx, nil)\n\t\t\terrs <- err\n\t\t}()\n\t\ttime.Sleep(2 * time.Millisecond)\n\t\tif i < batchSize-1 {\n\t\t\tselect {\n\t\t\tcase <-errs:\n\t\t\t\tt.Errorf(\"ListTools: unexpected result for incomplete batch: %v\", err)\n\t\t\tdefault:\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCancellation(t *testing.T) {\n\tvar (\n\t\tstart     = make(chan struct{})\n\t\tcancelled = make(chan struct{}, 1) // don't block the request\n\t)\n\n\tslowRequest := func(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[map[string]any]) (*CallToolResult, error) {\n\t\tstart <- struct{}{}\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tcancelled <- struct{}{}\n\t\tcase <-time.After(5 * time.Second):\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, nil\n\t}\n\tst := &ServerTool{\n\t\tTool:    &Tool{Name: \"slow\"},\n\t\tHandler: slowRequest,\n\t}\n\t_, cs := basicConnection(t, st)\n\tdefer cs.Close()\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tgo cs.CallTool(ctx, &CallToolParams{Name: \"slow\"})\n\t<-start\n\tcancel()\n\tselect {\n\tcase <-cancelled:\n\tcase <-time.After(5 * time.Second):\n\t\tt.Fatal(\"timeout waiting for cancellation\")\n\t}\n}\n\nfunc TestMiddleware(t *testing.T) {\n\tctx := context.Background()\n\tct, st := NewInMemoryTransports()\n\n\ts := NewServer(\"testServer\", \"v1.0.0\", nil)\n\tss, err := s.Connect(ctx, st)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Wait for the server to exit after the client closes its connection.\n\tvar clientWG sync.WaitGroup\n\tclientWG.Add(1)\n\tgo func() {\n\t\tif err := ss.Wait(); err != nil {\n\t\t\tt.Errorf(\"server failed: %v\", err)\n\t\t}\n\t\tclientWG.Done()\n\t}()\n\n\tvar sbuf, cbuf bytes.Buffer\n\tsbuf.WriteByte('\\n')\n\tcbuf.WriteByte('\\n')\n\n\t// \"1\" is the outer middleware layer, called first; then \"2\" is called, and finally\n\t// the default dispatcher.\n\ts.AddSendingMiddleware(traceCalls[*ServerSession](&sbuf, \"S1\"), traceCalls[*ServerSession](&sbuf, \"S2\"))\n\ts.AddReceivingMiddleware(traceCalls[*ServerSession](&sbuf, \"R1\"), traceCalls[*ServerSession](&sbuf, \"R2\"))\n\n\tc := NewClient(\"testClient\", \"v1.0.0\", nil)\n\tc.AddSendingMiddleware(traceCalls[*ClientSession](&cbuf, \"S1\"), traceCalls[*ClientSession](&cbuf, \"S2\"))\n\tc.AddReceivingMiddleware(traceCalls[*ClientSession](&cbuf, \"R1\"), traceCalls[*ClientSession](&cbuf, \"R2\"))\n\n\tcs, err := c.Connect(ctx, ct)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := cs.ListTools(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := ss.ListRoots(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twantServer := `\nR1 >initialize\nR2 >initialize\nR2 <initialize\nR1 <initialize\nR1 >notifications/initialized\nR2 >notifications/initialized\nR2 <notifications/initialized\nR1 <notifications/initialized\nR1 >tools/list\nR2 >tools/list\nR2 <tools/list\nR1 <tools/list\nS1 >roots/list\nS2 >roots/list\nS2 <roots/list\nS1 <roots/list\n`\n\tif diff := cmp.Diff(wantServer, sbuf.String()); diff != \"\" {\n\t\tt.Errorf(\"server mismatch (-want, +got):\\n%s\", diff)\n\t}\n\n\twantClient := `\nS1 >initialize\nS2 >initialize\nS2 <initialize\nS1 <initialize\nS1 >notifications/initialized\nS2 >notifications/initialized\nS2 <notifications/initialized\nS1 <notifications/initialized\nS1 >tools/list\nS2 >tools/list\nS2 <tools/list\nS1 <tools/list\nR1 >roots/list\nR2 >roots/list\nR2 <roots/list\nR1 <roots/list\n`\n\tif diff := cmp.Diff(wantClient, cbuf.String()); diff != \"\" {\n\t\tt.Errorf(\"client mismatch (-want, +got):\\n%s\", diff)\n\t}\n}\n\ntype safeBuffer struct {\n\tmu  sync.Mutex\n\tbuf bytes.Buffer\n}\n\nfunc (b *safeBuffer) Write(data []byte) (int, error) {\n\tb.mu.Lock()\n\tdefer b.mu.Unlock()\n\treturn b.buf.Write(data)\n}\n\nfunc (b *safeBuffer) Bytes() []byte {\n\tb.mu.Lock()\n\tdefer b.mu.Unlock()\n\treturn b.buf.Bytes()\n}\n\nfunc TestNoJSONNull(t *testing.T) {\n\tctx := context.Background()\n\tvar ct, st Transport = NewInMemoryTransports()\n\n\t// Collect logs, to sanity check that we don't write JSON null anywhere.\n\tvar logbuf safeBuffer\n\tct = NewLoggingTransport(ct, &logbuf)\n\n\ts := NewServer(\"testServer\", \"v1.0.0\", nil)\n\tss, err := s.Connect(ctx, st)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tc := NewClient(\"testClient\", \"v1.0.0\", nil)\n\tcs, err := c.Connect(ctx, ct)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := cs.ListTools(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := cs.ListPrompts(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := cs.ListResources(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := cs.ListResourceTemplates(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := ss.ListRoots(ctx, nil); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcs.Close()\n\tss.Wait()\n\n\tlogs := logbuf.Bytes()\n\tif i := bytes.Index(logs, []byte(\"null\")); i >= 0 {\n\t\tstart := max(i-20, 0)\n\t\tend := min(i+20, len(logs))\n\t\tt.Errorf(\"conformance violation: MCP logs contain JSON null: %s\", \"...\"+string(logs[start:end])+\"...\")\n\t}\n}\n\n// traceCalls creates a middleware function that prints the method before and after each call\n// with the given prefix.\nfunc traceCalls[S Session](w io.Writer, prefix string) Middleware[S] {\n\treturn func(h MethodHandler[S]) MethodHandler[S] {\n\t\treturn func(ctx context.Context, sess S, method string, params Params) (Result, error) {\n\t\t\tfmt.Fprintf(w, \"%s >%s\\n\", prefix, method)\n\t\t\tdefer fmt.Fprintf(w, \"%s <%s\\n\", prefix, method)\n\t\t\treturn h(ctx, sess, method, params)\n\t\t}\n\t}\n}\n\n// A function, because schemas must form a tree (they have hidden state).\nfunc falseSchema() *jsonschema.Schema { return &jsonschema.Schema{Not: &jsonschema.Schema{}} }\n\nfunc nopHandler(context.Context, *ServerSession, *CallToolParamsFor[map[string]any]) (*CallToolResult, error) {\n\treturn nil, nil\n}\n"
  },
  {
    "path": "internal/mcp/prompt.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n)\n\n// A PromptHandler handles a call to prompts/get.\ntype PromptHandler func(context.Context, *ServerSession, *GetPromptParams) (*GetPromptResult, error)\n\n// A Prompt is a prompt definition bound to a prompt handler.\ntype ServerPrompt struct {\n\tPrompt  *Prompt\n\tHandler PromptHandler\n}\n"
  },
  {
    "path": "internal/mcp/protocol.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage mcp\n\nimport (\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\n// Optional annotations for the client. The client can use annotations to inform\n// how objects are used or displayed\ntype Annotations struct {\n\t// Describes who the intended customer of this object or data is.\n\t//\n\t// It can include multiple entries to indicate content useful for multiple\n\t// audiences (e.g., `[\"user\", \"assistant\"]`).\n\tAudience []Role `json:\"audience,omitempty\"`\n\t// Describes how important this data is for operating the server.\n\t//\n\t// A value of 1 means \"most important,\" and indicates that the data is\n\t// effectively required, while 0 means \"least important,\" and indicates that the\n\t// data is entirely optional.\n\tPriority float64 `json:\"priority,omitempty\"`\n}\n\ntype CallToolParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta      Meta   `json:\"_meta,omitempty\"`\n\tArguments any    `json:\"arguments,omitempty\"`\n\tName      string `json:\"name\"`\n}\n\nfunc (x *CallToolParams) GetMeta() *Meta { return &x.Meta }\n\ntype CallToolParamsFor[In any] struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta      Meta   `json:\"_meta,omitempty\"`\n\tArguments In     `json:\"arguments,omitempty\"`\n\tName      string `json:\"name\"`\n}\n\nfunc (x *CallToolParamsFor[In]) GetMeta() *Meta { return &x.Meta }\n\n// The server's response to a tool call.\n//\n// Any errors that originate from the tool SHOULD be reported inside the result\n// object, with `isError` set to true, _not_ as an MCP protocol-level error\n// response. Otherwise, the LLM would not be able to see that an error occurred\n// and self-correct.\n//\n// However, any errors in _finding_ the tool, an error indicating that the\n// server does not support tool calls, or any other exceptional conditions,\n// should be reported as an MCP error response.\ntype CallToolResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta    Meta       `json:\"_meta,omitempty\"`\n\tContent []*Content `json:\"content\"`\n\t// Whether the tool call ended in an error.\n\t//\n\t// If not set, this is assumed to be false (the call was successful).\n\tIsError bool `json:\"isError,omitempty\"`\n}\n\nfunc (x *CallToolResult) GetMeta() *Meta { return &x.Meta }\n\ntype CallToolResultFor[Out any] struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta    Meta       `json:\"_meta,omitempty\"`\n\tContent []*Content `json:\"content\"`\n\t// Whether the tool call ended in an error.\n\t//\n\t// If not set, this is assumed to be false (the call was successful).\n\tIsError bool `json:\"isError,omitempty\"`\n}\n\nfunc (x *CallToolResultFor[Out]) GetMeta() *Meta { return &x.Meta }\n\ntype CancelledParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An optional string describing the reason for the cancellation. This MAY be\n\t// logged or presented to the user.\n\tReason string `json:\"reason,omitempty\"`\n\t// The ID of the request to cancel.\n\t//\n\t// This MUST correspond to the ID of a request previously issued in the same\n\t// direction.\n\tRequestID any `json:\"requestId\"`\n}\n\nfunc (x *CancelledParams) GetMeta() *Meta { return &x.Meta }\n\n// Capabilities a client may support. Known capabilities are defined here, in\n// this schema, but this is not a closed set: any client can define its own,\n// additional capabilities.\ntype ClientCapabilities struct {\n\t// Experimental, non-standard capabilities that the client supports.\n\tExperimental map[string]struct {\n\t} `json:\"experimental,omitempty\"`\n\t// Present if the client supports listing roots.\n\tRoots struct {\n\t\t// Whether the client supports notifications for changes to the roots list.\n\t\tListChanged bool `json:\"listChanged,omitempty\"`\n\t} `json:\"roots,omitempty\"`\n\t// Present if the client supports sampling from an LLM.\n\tSampling *SamplingCapabilities `json:\"sampling,omitempty\"`\n}\n\ntype CreateMessageParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// A request to include context from one or more MCP servers (including the\n\t// caller), to be attached to the prompt. The client MAY ignore this request.\n\tIncludeContext string `json:\"includeContext,omitempty\"`\n\t// The maximum number of tokens to sample, as requested by the server. The\n\t// client MAY choose to sample fewer tokens than requested.\n\tMaxTokens int64              `json:\"maxTokens\"`\n\tMessages  []*SamplingMessage `json:\"messages\"`\n\t// Optional metadata to pass through to the LLM provider. The format of this\n\t// metadata is provider-specific.\n\tMetadata struct {\n\t} `json:\"metadata,omitempty\"`\n\t// The server's preferences for which model to select. The client MAY ignore\n\t// these preferences.\n\tModelPreferences *ModelPreferences `json:\"modelPreferences,omitempty\"`\n\tStopSequences    []string          `json:\"stopSequences,omitempty\"`\n\t// An optional system prompt the server wants to use for sampling. The client\n\t// MAY modify or omit this prompt.\n\tSystemPrompt string  `json:\"systemPrompt,omitempty\"`\n\tTemperature  float64 `json:\"temperature,omitempty\"`\n}\n\nfunc (x *CreateMessageParams) GetMeta() *Meta { return &x.Meta }\n\n// The client's response to a sampling/create_message request from the server.\n// The client should inform the user before returning the sampled message, to\n// allow them to inspect the response (human in the loop) and decide whether to\n// allow the server to see it.\ntype CreateMessageResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta    Meta     `json:\"_meta,omitempty\"`\n\tContent *Content `json:\"content\"`\n\t// The name of the model that generated the message.\n\tModel string `json:\"model\"`\n\tRole  Role   `json:\"role\"`\n\t// The reason why sampling stopped, if known.\n\tStopReason string `json:\"stopReason,omitempty\"`\n}\n\nfunc (x *CreateMessageResult) GetMeta() *Meta { return &x.Meta }\n\ntype GetPromptParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// Arguments to use for templating the prompt.\n\tArguments map[string]string `json:\"arguments,omitempty\"`\n\t// The name of the prompt or prompt template.\n\tName string `json:\"name\"`\n}\n\nfunc (x *GetPromptParams) GetMeta() *Meta { return &x.Meta }\n\n// The server's response to a prompts/get request from the client.\ntype GetPromptResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An optional description for the prompt.\n\tDescription string           `json:\"description,omitempty\"`\n\tMessages    []*PromptMessage `json:\"messages\"`\n}\n\nfunc (x *GetPromptResult) GetMeta() *Meta { return &x.Meta }\n\ntype InitializeParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta         Meta                `json:\"_meta,omitempty\"`\n\tCapabilities *ClientCapabilities `json:\"capabilities\"`\n\tClientInfo   *implementation     `json:\"clientInfo\"`\n\t// The latest version of the Model Context Protocol that the client supports.\n\t// The client MAY decide to support older versions as well.\n\tProtocolVersion string `json:\"protocolVersion\"`\n}\n\nfunc (x *InitializeParams) GetMeta() *Meta { return &x.Meta }\n\n// After receiving an initialize request from the client, the server sends this\n// response.\ntype InitializeResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta         Meta                `json:\"_meta,omitempty\"`\n\tCapabilities *serverCapabilities `json:\"capabilities\"`\n\t// Instructions describing how to use the server and its features.\n\t//\n\t// This can be used by clients to improve the LLM's understanding of available\n\t// tools, resources, etc. It can be thought of like a \"hint\" to the model. For\n\t// example, this information MAY be added to the system prompt.\n\tInstructions string `json:\"instructions,omitempty\"`\n\t// The version of the Model Context Protocol that the server wants to use. This\n\t// may not match the version that the client requested. If the client cannot\n\t// support this version, it MUST disconnect.\n\tProtocolVersion string          `json:\"protocolVersion\"`\n\tServerInfo      *implementation `json:\"serverInfo\"`\n}\n\nfunc (x *InitializeResult) GetMeta() *Meta { return &x.Meta }\n\ntype InitializedParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *InitializedParams) GetMeta() *Meta { return &x.Meta }\n\ntype ListPromptsParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the current pagination position. If provided,\n\t// the server should return results starting after this cursor.\n\tCursor string `json:\"cursor,omitempty\"`\n}\n\nfunc (x *ListPromptsParams) GetMeta() *Meta     { return &x.Meta }\nfunc (x *ListPromptsParams) cursorPtr() *string { return &x.Cursor }\n\n// The server's response to a prompts/list request from the client.\ntype ListPromptsResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the pagination position after the last returned\n\t// result. If present, there may be more results available.\n\tNextCursor string    `json:\"nextCursor,omitempty\"`\n\tPrompts    []*Prompt `json:\"prompts\"`\n}\n\nfunc (x *ListPromptsResult) GetMeta() *Meta         { return &x.Meta }\nfunc (x *ListPromptsResult) nextCursorPtr() *string { return &x.NextCursor }\n\ntype ListResourceTemplatesParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the current pagination position. If provided,\n\t// the server should return results starting after this cursor.\n\tCursor string `json:\"cursor,omitempty\"`\n}\n\nfunc (x *ListResourceTemplatesParams) GetMeta() *Meta     { return &x.Meta }\nfunc (x *ListResourceTemplatesParams) cursorPtr() *string { return &x.Cursor }\n\n// The server's response to a resources/templates/list request from the client.\ntype ListResourceTemplatesResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the pagination position after the last returned\n\t// result. If present, there may be more results available.\n\tNextCursor        string              `json:\"nextCursor,omitempty\"`\n\tResourceTemplates []*ResourceTemplate `json:\"resourceTemplates\"`\n}\n\nfunc (x *ListResourceTemplatesResult) GetMeta() *Meta         { return &x.Meta }\nfunc (x *ListResourceTemplatesResult) nextCursorPtr() *string { return &x.NextCursor }\n\ntype ListResourcesParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the current pagination position. If provided,\n\t// the server should return results starting after this cursor.\n\tCursor string `json:\"cursor,omitempty\"`\n}\n\nfunc (x *ListResourcesParams) GetMeta() *Meta     { return &x.Meta }\nfunc (x *ListResourcesParams) cursorPtr() *string { return &x.Cursor }\n\n// The server's response to a resources/list request from the client.\ntype ListResourcesResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the pagination position after the last returned\n\t// result. If present, there may be more results available.\n\tNextCursor string      `json:\"nextCursor,omitempty\"`\n\tResources  []*Resource `json:\"resources\"`\n}\n\nfunc (x *ListResourcesResult) GetMeta() *Meta         { return &x.Meta }\nfunc (x *ListResourcesResult) nextCursorPtr() *string { return &x.NextCursor }\n\ntype ListRootsParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *ListRootsParams) GetMeta() *Meta { return &x.Meta }\n\n// The client's response to a roots/list request from the server. This result\n// contains an array of Root objects, each representing a root directory or file\n// that the server can operate on.\ntype ListRootsResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta  Meta    `json:\"_meta,omitempty\"`\n\tRoots []*Root `json:\"roots\"`\n}\n\nfunc (x *ListRootsResult) GetMeta() *Meta { return &x.Meta }\n\ntype ListToolsParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the current pagination position. If provided,\n\t// the server should return results starting after this cursor.\n\tCursor string `json:\"cursor,omitempty\"`\n}\n\nfunc (x *ListToolsParams) GetMeta() *Meta     { return &x.Meta }\nfunc (x *ListToolsParams) cursorPtr() *string { return &x.Cursor }\n\n// The server's response to a tools/list request from the client.\ntype ListToolsResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An opaque token representing the pagination position after the last returned\n\t// result. If present, there may be more results available.\n\tNextCursor string  `json:\"nextCursor,omitempty\"`\n\tTools      []*Tool `json:\"tools\"`\n}\n\nfunc (x *ListToolsResult) GetMeta() *Meta         { return &x.Meta }\nfunc (x *ListToolsResult) nextCursorPtr() *string { return &x.NextCursor }\n\n// The severity of a log message.\n//\n// These map to syslog message severities, as specified in RFC-5424:\n// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1\ntype LoggingLevel string\n\ntype LoggingMessageParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// The data to be logged, such as a string message or an object. Any JSON\n\t// serializable type is allowed here.\n\tData any `json:\"data\"`\n\t// The severity of this log message.\n\tLevel LoggingLevel `json:\"level\"`\n\t// An optional name of the logger issuing this message.\n\tLogger string `json:\"logger,omitempty\"`\n}\n\nfunc (x *LoggingMessageParams) GetMeta() *Meta { return &x.Meta }\n\n// Hints to use for model selection.\n//\n// Keys not declared here are currently left unspecified by the spec and are up\n// to the client to interpret.\ntype ModelHint struct {\n\t// A hint for a model name.\n\t//\n\t// The client SHOULD treat this as a substring of a model name; for example: -\n\t// `claude-3-5-sonnet` should match `claude-3-5-sonnet-20241022` - `sonnet`\n\t// should match `claude-3-5-sonnet-20241022`, `claude-3-sonnet-20240229`, etc. -\n\t// `claude` should match any Claude model\n\t//\n\t// The client MAY also map the string to a different provider's model name or a\n\t// different model family, as long as it fills a similar niche; for example: -\n\t// `gemini-1.5-flash` could match `claude-3-haiku-20240307`\n\tName string `json:\"name,omitempty\"`\n}\n\n// The server's preferences for model selection, requested of the client during\n// sampling.\n//\n// Because LLMs can vary along multiple dimensions, choosing the \"best\" model is\n// rarely straightforward. Different models excel in different areas—some are\n// faster but less capable, others are more capable but more expensive, and so\n// on. This interface allows servers to express their priorities across multiple\n// dimensions to help clients make an appropriate selection for their use case.\n//\n// These preferences are always advisory. The client MAY ignore them. It is also\n// up to the client to decide how to interpret these preferences and how to\n// balance them against other considerations.\ntype ModelPreferences struct {\n\t// How much to prioritize cost when selecting a model. A value of 0 means cost\n\t// is not important, while a value of 1 means cost is the most important factor.\n\tCostPriority float64 `json:\"costPriority,omitempty\"`\n\t// Optional hints to use for model selection.\n\t//\n\t// If multiple hints are specified, the client MUST evaluate them in order (such\n\t// that the first match is taken).\n\t//\n\t// The client SHOULD prioritize these hints over the numeric priorities, but MAY\n\t// still use the priorities to select from ambiguous matches.\n\tHints []*ModelHint `json:\"hints,omitempty\"`\n\t// How much to prioritize intelligence and capabilities when selecting a model.\n\t// A value of 0 means intelligence is not important, while a value of 1 means\n\t// intelligence is the most important factor.\n\tIntelligencePriority float64 `json:\"intelligencePriority,omitempty\"`\n\t// How much to prioritize sampling speed (latency) when selecting a model. A\n\t// value of 0 means speed is not important, while a value of 1 means speed is\n\t// the most important factor.\n\tSpeedPriority float64 `json:\"speedPriority,omitempty\"`\n}\n\ntype PingParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *PingParams) GetMeta() *Meta { return &x.Meta }\n\ntype ProgressNotificationParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// An optional message describing the current progress.\n\tMessage string `json:\"message,omitempty\"`\n\t// The progress thus far. This should increase every time progress is made, even\n\t// if the total is unknown.\n\tProgress float64 `json:\"progress\"`\n\t// The progress token which was given in the initial request, used to associate\n\t// this notification with the request that is proceeding.\n\tProgressToken any `json:\"progressToken\"`\n\t// Total number of items to process (or total progress required), if known.\n\tTotal float64 `json:\"total,omitempty\"`\n}\n\nfunc (x *ProgressNotificationParams) GetMeta() *Meta { return &x.Meta }\n\n// A prompt or prompt template that the server offers.\ntype Prompt struct {\n\t// A list of arguments to use for templating the prompt.\n\tArguments []*PromptArgument `json:\"arguments,omitempty\"`\n\t// An optional description of what this prompt provides\n\tDescription string `json:\"description,omitempty\"`\n\t// The name of the prompt or prompt template.\n\tName string `json:\"name\"`\n}\n\n// Describes an argument that a prompt can accept.\ntype PromptArgument struct {\n\t// A human-readable description of the argument.\n\tDescription string `json:\"description,omitempty\"`\n\t// The name of the argument.\n\tName string `json:\"name\"`\n\t// Whether this argument must be provided.\n\tRequired bool `json:\"required,omitempty\"`\n}\n\ntype PromptListChangedParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *PromptListChangedParams) GetMeta() *Meta { return &x.Meta }\n\n// Describes a message returned as part of a prompt.\n//\n// This is similar to `SamplingMessage`, but also supports the embedding of\n// resources from the MCP server.\ntype PromptMessage struct {\n\tContent *Content `json:\"content\"`\n\tRole    Role     `json:\"role\"`\n}\n\ntype ReadResourceParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// The URI of the resource to read. The URI can use any protocol; it is up to\n\t// the server how to interpret it.\n\tURI string `json:\"uri\"`\n}\n\nfunc (x *ReadResourceParams) GetMeta() *Meta { return &x.Meta }\n\n// The server's response to a resources/read request from the client.\ntype ReadResourceResult struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta     Meta                `json:\"_meta,omitempty\"`\n\tContents []*ResourceContents `json:\"contents\"`\n}\n\nfunc (x *ReadResourceResult) GetMeta() *Meta { return &x.Meta }\n\n// A known resource that the server is capable of reading.\ntype Resource struct {\n\t// Optional annotations for the client.\n\tAnnotations *Annotations `json:\"annotations,omitempty\"`\n\t// A description of what this resource represents.\n\t//\n\t// This can be used by clients to improve the LLM's understanding of available\n\t// resources. It can be thought of like a \"hint\" to the model.\n\tDescription string `json:\"description,omitempty\"`\n\t// The MIME type of this resource, if known.\n\tMIMEType string `json:\"mimeType,omitempty\"`\n\t// A human-readable name for this resource.\n\t//\n\t// This can be used by clients to populate UI elements.\n\tName string `json:\"name\"`\n\t// The size of the raw resource content, in bytes (i.e., before base64 encoding\n\t// or any tokenization), if known.\n\t//\n\t// This can be used by Hosts to display file sizes and estimate context window\n\t// usage.\n\tSize int64 `json:\"size,omitempty\"`\n\t// The URI of this resource.\n\tURI string `json:\"uri\"`\n}\n\ntype ResourceListChangedParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *ResourceListChangedParams) GetMeta() *Meta { return &x.Meta }\n\n// A template description for resources available on the server.\ntype ResourceTemplate struct {\n\t// Optional annotations for the client.\n\tAnnotations *Annotations `json:\"annotations,omitempty\"`\n\t// A description of what this template is for.\n\t//\n\t// This can be used by clients to improve the LLM's understanding of available\n\t// resources. It can be thought of like a \"hint\" to the model.\n\tDescription string `json:\"description,omitempty\"`\n\t// The MIME type for all resources that match this template. This should only be\n\t// included if all resources matching this template have the same type.\n\tMIMEType string `json:\"mimeType,omitempty\"`\n\t// A human-readable name for the type of resource this template refers to.\n\t//\n\t// This can be used by clients to populate UI elements.\n\tName string `json:\"name\"`\n\t// A URI template (according to RFC 6570) that can be used to construct resource\n\t// URIs.\n\tURITemplate string `json:\"uriTemplate\"`\n}\n\n// The sender or recipient of messages and data in a conversation.\ntype Role string\n\n// Represents a root directory or file that the server can operate on.\ntype Root struct {\n\t// An optional name for the root. This can be used to provide a human-readable\n\t// identifier for the root, which may be useful for display purposes or for\n\t// referencing the root in other parts of the application.\n\tName string `json:\"name,omitempty\"`\n\t// The URI identifying the root. This *must* start with file:// for now. This\n\t// restriction may be relaxed in future versions of the protocol to allow other\n\t// URI schemes.\n\tURI string `json:\"uri\"`\n}\n\ntype RootsListChangedParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *RootsListChangedParams) GetMeta() *Meta { return &x.Meta }\n\n// Present if the client supports sampling from an LLM.\ntype SamplingCapabilities struct {\n}\n\n// Describes a message issued to or received from an LLM API.\ntype SamplingMessage struct {\n\tContent *Content `json:\"content\"`\n\tRole    Role     `json:\"role\"`\n}\n\ntype SetLevelParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n\t// The level of logging that the client wants to receive from the server. The\n\t// server should send all logs at this level and higher (i.e., more severe) to\n\t// the client as notifications/message.\n\tLevel LoggingLevel `json:\"level\"`\n}\n\nfunc (x *SetLevelParams) GetMeta() *Meta { return &x.Meta }\n\n// Definition for a tool the client can call.\ntype Tool struct {\n\t// Optional additional tool information.\n\tAnnotations *ToolAnnotations `json:\"annotations,omitempty\"`\n\t// A human-readable description of the tool.\n\t//\n\t// This can be used by clients to improve the LLM's understanding of available\n\t// tools. It can be thought of like a \"hint\" to the model.\n\tDescription string `json:\"description,omitempty\"`\n\t// A JSON Schema object defining the expected parameters for the tool.\n\tInputSchema *jsonschema.Schema `json:\"inputSchema\"`\n\t// The name of the tool.\n\tName string `json:\"name\"`\n}\n\n// Additional properties describing a Tool to clients.\n//\n// NOTE: all properties in ToolAnnotations are **hints**. They are not\n// guaranteed to provide a faithful description of tool behavior (including\n// descriptive properties like `title`).\n//\n// Clients should never make tool use decisions based on ToolAnnotations\n// received from untrusted servers.\ntype ToolAnnotations struct {\n\t// If true, the tool may perform destructive updates to its environment. If\n\t// false, the tool performs only additive updates.\n\t//\n\t// (This property is meaningful only when `readOnlyHint == false`)\n\t//\n\t// Default: true\n\tDestructiveHint bool `json:\"destructiveHint,omitempty\"`\n\t// If true, calling the tool repeatedly with the same arguments will have no\n\t// additional effect on the its environment.\n\t//\n\t// (This property is meaningful only when `readOnlyHint == false`)\n\t//\n\t// Default: false\n\tIdempotentHint bool `json:\"idempotentHint,omitempty\"`\n\t// If true, this tool may interact with an \"open world\" of external entities. If\n\t// false, the tool's domain of interaction is closed. For example, the world of\n\t// a web search tool is open, whereas that of a memory tool is not.\n\t//\n\t// Default: true\n\tOpenWorldHint bool `json:\"openWorldHint,omitempty\"`\n\t// If true, the tool does not modify its environment.\n\t//\n\t// Default: false\n\tReadOnlyHint bool `json:\"readOnlyHint,omitempty\"`\n\t// A human-readable title for the tool.\n\tTitle string `json:\"title,omitempty\"`\n}\n\ntype ToolListChangedParams struct {\n\t// This property is reserved by the protocol to allow clients and servers to\n\t// attach additional metadata to their responses.\n\tMeta Meta `json:\"_meta,omitempty\"`\n}\n\nfunc (x *ToolListChangedParams) GetMeta() *Meta { return &x.Meta }\n\n// Describes the name and version of an MCP implementation.\ntype implementation struct {\n\tName    string `json:\"name\"`\n\tVersion string `json:\"version\"`\n}\n\n// Present if the server supports sending log messages to the client.\ntype loggingCapabilities struct {\n}\n\n// Present if the server offers any prompt templates.\ntype promptCapabilities struct {\n\t// Whether this server supports notifications for changes to the prompt list.\n\tListChanged bool `json:\"listChanged,omitempty\"`\n}\n\n// Present if the server offers any resources to read.\ntype resourceCapabilities struct {\n\t// Whether this server supports notifications for changes to the resource list.\n\tListChanged bool `json:\"listChanged,omitempty\"`\n\t// Whether this server supports subscribing to resource updates.\n\tSubscribe bool `json:\"subscribe,omitempty\"`\n}\n\n// Capabilities that a server may support. Known capabilities are defined here,\n// in this schema, but this is not a closed set: any server can define its own,\n// additional capabilities.\ntype serverCapabilities struct {\n\t// Present if the server supports argument autocompletion suggestions.\n\tCompletions struct {\n\t} `json:\"completions,omitempty\"`\n\t// Experimental, non-standard capabilities that the server supports.\n\tExperimental map[string]struct {\n\t} `json:\"experimental,omitempty\"`\n\t// Present if the server supports sending log messages to the client.\n\tLogging *loggingCapabilities `json:\"logging,omitempty\"`\n\t// Present if the server offers any prompt templates.\n\tPrompts *promptCapabilities `json:\"prompts,omitempty\"`\n\t// Present if the server offers any resources to read.\n\tResources *resourceCapabilities `json:\"resources,omitempty\"`\n\t// Present if the server offers any tools to call.\n\tTools *toolCapabilities `json:\"tools,omitempty\"`\n}\n\n// Present if the server offers any tools to call.\ntype toolCapabilities struct {\n\t// Whether this server supports notifications for changes to the tool list.\n\tListChanged bool `json:\"listChanged,omitempty\"`\n}\n\nconst (\n\tmethodCallTool                  = \"tools/call\"\n\tnotificationCancelled           = \"notifications/cancelled\"\n\tmethodComplete                  = \"completion/complete\"\n\tmethodCreateMessage             = \"sampling/createMessage\"\n\tmethodGetPrompt                 = \"prompts/get\"\n\tmethodInitialize                = \"initialize\"\n\tnotificationInitialized         = \"notifications/initialized\"\n\tmethodListPrompts               = \"prompts/list\"\n\tmethodListResourceTemplates     = \"resources/templates/list\"\n\tmethodListResources             = \"resources/list\"\n\tmethodListRoots                 = \"roots/list\"\n\tmethodListTools                 = \"tools/list\"\n\tnotificationLoggingMessage      = \"notifications/message\"\n\tmethodPing                      = \"ping\"\n\tnotificationProgress            = \"notifications/progress\"\n\tnotificationPromptListChanged   = \"notifications/prompts/list_changed\"\n\tmethodReadResource              = \"resources/read\"\n\tnotificationResourceListChanged = \"notifications/resources/list_changed\"\n\tnotificationResourceUpdated     = \"notifications/resources/updated\"\n\tnotificationRootsListChanged    = \"notifications/roots/list_changed\"\n\tmethodSetLevel                  = \"logging/setLevel\"\n\tmethodSubscribe                 = \"resources/subscribe\"\n\tnotificationToolListChanged     = \"notifications/tools/list_changed\"\n\tmethodUnsubscribe               = \"resources/unsubscribe\"\n)\n"
  },
  {
    "path": "internal/mcp/resource.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/url\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\n// A ServerResource associates a Resource with its handler.\ntype ServerResource struct {\n\tResource *Resource\n\tHandler  ResourceHandler\n}\n\n// A ServerResourceTemplate associates a ResourceTemplate with its handler.\ntype ServerResourceTemplate struct {\n\tResourceTemplate *ResourceTemplate\n\tHandler          ResourceHandler\n}\n\n// A ResourceHandler is a function that reads a resource.\n// It will be called when the client calls [ClientSession.ReadResource].\n// If it cannot find the resource, it should return the result of calling [ResourceNotFoundError].\ntype ResourceHandler func(context.Context, *ServerSession, *ReadResourceParams) (*ReadResourceResult, error)\n\n// ResourceNotFoundError returns an error indicating that a resource being read could\n// not be found.\nfunc ResourceNotFoundError(uri string) error {\n\treturn &jsonrpc2.WireError{\n\t\tCode:    CodeResourceNotFound,\n\t\tMessage: \"Resource not found\",\n\t\tData:    json.RawMessage(fmt.Sprintf(`{\"uri\":%q}`, uri)),\n\t}\n}\n\n// readFileResource reads from the filesystem at a URI relative to dirFilepath, respecting\n// the roots.\n// dirFilepath and rootFilepaths are absolute filesystem paths.\nfunc readFileResource(rawURI, dirFilepath string, rootFilepaths []string) ([]byte, error) {\n\turiFilepath, err := computeURIFilepath(rawURI, dirFilepath, rootFilepaths)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar data []byte\n\terr = withFile(dirFilepath, uriFilepath, func(f *os.File) error {\n\t\tvar err error\n\t\tdata, err = io.ReadAll(f)\n\t\treturn err\n\t})\n\tif os.IsNotExist(err) {\n\t\terr = ResourceNotFoundError(rawURI)\n\t}\n\treturn data, err\n}\n\n// withFile calls f on the file at join(dir, rel),\n// protecting against path traversal attacks.\nfunc withFile(dir, rel string, f func(*os.File) error) (err error) {\n\tr, err := os.OpenRoot(dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer r.Close()\n\tfile, err := r.Open(rel)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Record error, in case f writes.\n\tdefer func() { err = errors.Join(err, file.Close()) }()\n\treturn f(file)\n}\n\n// computeURIFilepath returns a path relative to dirFilepath.\n// The dirFilepath and rootFilepaths are absolute file paths.\nfunc computeURIFilepath(rawURI, dirFilepath string, rootFilepaths []string) (string, error) {\n\t// We use \"file path\" to mean a filesystem path.\n\turi, err := url.Parse(rawURI)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif uri.Scheme != \"file\" {\n\t\treturn \"\", fmt.Errorf(\"URI is not a file: %s\", uri)\n\t}\n\tif uri.Path == \"\" {\n\t\t// A more specific error than the one below, to catch the\n\t\t// common mistake \"file://foo\".\n\t\treturn \"\", errors.New(\"empty path\")\n\t}\n\t// The URI's path is interpreted relative to dirFilepath, and in the local filesystem.\n\t// It must not try to escape its directory.\n\turiFilepathRel, err := filepath.Localize(strings.TrimPrefix(uri.Path, \"/\"))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%q cannot be localized: %w\", uriFilepathRel, err)\n\t}\n\n\t// Check roots, if there are any.\n\tif len(rootFilepaths) > 0 {\n\t\t// To check against the roots, we need an absolute file path, not relative to the directory.\n\t\t// uriFilepath is local, so the joined path is under dirFilepath.\n\t\turiFilepathAbs := filepath.Join(dirFilepath, uriFilepathRel)\n\t\trootOK := false\n\t\t// Check that the requested file path is under some root.\n\t\t// Since both paths are absolute, that's equivalent to filepath.Rel constructing\n\t\t// a local path.\n\t\tfor _, rootFilepathAbs := range rootFilepaths {\n\t\t\tif rel, err := filepath.Rel(rootFilepathAbs, uriFilepathAbs); err == nil && filepath.IsLocal(rel) {\n\t\t\t\trootOK = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !rootOK {\n\t\t\treturn \"\", fmt.Errorf(\"URI path %q is not under any root\", uriFilepathAbs)\n\t\t}\n\t}\n\treturn uriFilepathRel, nil\n}\n\n// fileRoots transforms the Roots obtained from the client into absolute paths on\n// the local filesystem.\n// TODO(jba): expose this functionality to user ResourceHandlers,\n// so they don't have to repeat it.\nfunc fileRoots(rawRoots []*Root) ([]string, error) {\n\tvar fileRoots []string\n\tfor _, r := range rawRoots {\n\t\tfr, err := fileRoot(r)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfileRoots = append(fileRoots, fr)\n\t}\n\treturn fileRoots, nil\n}\n\n// fileRoot returns the absolute path for Root.\nfunc fileRoot(root *Root) (_ string, err error) {\n\tdefer util.Wrapf(&err, \"root %q\", root.URI)\n\n\t// Convert to absolute file path.\n\trurl, err := url.Parse(root.URI)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif rurl.Scheme != \"file\" {\n\t\treturn \"\", errors.New(\"not a file URI\")\n\t}\n\tif rurl.Path == \"\" {\n\t\t// A more specific error than the one below, to catch the\n\t\t// common mistake \"file://foo\".\n\t\treturn \"\", errors.New(\"empty path\")\n\t}\n\t// We don't want Localize here: we want an absolute path, which is not local.\n\tfileRoot := filepath.Clean(filepath.FromSlash(rurl.Path))\n\tif !filepath.IsAbs(fileRoot) {\n\t\treturn \"\", errors.New(\"not an absolute path\")\n\t}\n\treturn fileRoot, nil\n}\n\n// Matches reports whether the receiver's uri template matches the uri.\n// TODO: use \"github.com/yosida95/uritemplate/v3\"\nfunc (sr *ServerResourceTemplate) Matches(uri string) bool {\n\tre, err := uriTemplateToRegexp(sr.ResourceTemplate.URITemplate)\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn re.MatchString(uri)\n}\n\nfunc uriTemplateToRegexp(uriTemplate string) (*regexp.Regexp, error) {\n\tpat := uriTemplate\n\tvar b strings.Builder\n\tb.WriteByte('^')\n\tseen := map[string]bool{}\n\tfor len(pat) > 0 {\n\t\tliteral, rest, ok := strings.Cut(pat, \"{\")\n\t\tb.WriteString(regexp.QuoteMeta(literal))\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\texpr, rest, ok := strings.Cut(rest, \"}\")\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"missing '}'\")\n\t\t}\n\t\tpat = rest\n\t\tif strings.ContainsRune(expr, ',') {\n\t\t\treturn nil, errors.New(\"can't handle commas in expressions\")\n\t\t}\n\t\tif strings.ContainsRune(expr, ':') {\n\t\t\treturn nil, errors.New(\"can't handle prefix modifiers in expressions\")\n\t\t}\n\t\tif len(expr) > 0 && expr[len(expr)-1] == '*' {\n\t\t\treturn nil, errors.New(\"can't handle explode modifiers in expressions\")\n\t\t}\n\n\t\t// These sets of valid characters aren't accurate.\n\t\t// See https://datatracker.ietf.org/doc/html/rfc6570.\n\t\tvar re, name string\n\t\tfirst := byte(0)\n\t\tif len(expr) > 0 {\n\t\t\tfirst = expr[0]\n\t\t}\n\t\tswitch first {\n\t\tdefault:\n\t\t\t// {var} doesn't match slashes. (It should also fail to match other characters,\n\t\t\t// but this simplified implementation doesn't handle that.)\n\t\t\tre = `[^/]*`\n\t\t\tname = expr\n\t\tcase '+':\n\t\t\t// {+var} matches anything, even slashes\n\t\t\tre = `.*`\n\t\t\tname = expr[1:]\n\t\tcase '#', '.', '/', ';', '?', '&':\n\t\t\treturn nil, fmt.Errorf(\"prefix character %c unsupported\", first)\n\t\t}\n\t\tif seen[name] {\n\t\t\treturn nil, fmt.Errorf(\"can't handle duplicate name %q\", name)\n\t\t}\n\t\tseen[name] = true\n\t\tb.WriteString(re)\n\t}\n\tb.WriteByte('$')\n\treturn regexp.Compile(b.String())\n}\n"
  },
  {
    "path": "internal/mcp/resource_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestFileRoot(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"TODO: fix for Windows\")\n\t}\n\n\tfor _, tt := range []struct {\n\t\turi     string\n\t\twant    string\n\t\twantErr string // error must contain this string\n\t}{\n\t\t{uri: \"file:///foo\", want: \"/foo\"},\n\t\t{uri: \"file:///foo/bar\", want: \"/foo/bar\"},\n\t\t{uri: \"file:///foo/../bar\", want: \"/bar\"},\n\t\t{uri: \"file:/foo\", want: \"/foo\"},\n\t\t{uri: \"http:///foo\", wantErr: \"not a file\"},\n\t\t{uri: \"file://foo\", wantErr: \"empty path\"},\n\t\t{uri: \":\", wantErr: \"missing protocol scheme\"},\n\t} {\n\t\tgot, err := fileRoot(&Root{URI: tt.uri})\n\t\tif err != nil {\n\t\t\tif tt.wantErr == \"\" {\n\t\t\t\tt.Errorf(\"%s: got %v, want success\", tt.uri, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !strings.Contains(err.Error(), tt.wantErr) {\n\t\t\t\tt.Errorf(\"%s: got %v, does not contain %q\", tt.uri, err, tt.wantErr)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else if tt.wantErr != \"\" {\n\t\t\tt.Errorf(\"%s: succeeded, but wanted error with %q\", tt.uri, tt.wantErr)\n\t\t} else if got != tt.want {\n\t\t\tt.Errorf(\"%s: got %q, want %q\", tt.uri, got, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestComputeURIFilepath(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"TODO: fix for Windows\")\n\t}\n\t// TODO(jba): test with Windows \\\\host paths and C: paths\n\tdirFilepath := filepath.FromSlash(\"/files\")\n\trootFilepaths := []string{\n\t\tfilepath.FromSlash(\"/files/public\"),\n\t\tfilepath.FromSlash(\"/files/shared\"),\n\t}\n\tfor _, tt := range []struct {\n\t\turi     string\n\t\twant    string\n\t\twantErr string // error must contain this\n\t}{\n\t\t{\"file:///public\", \"public\", \"\"},\n\t\t{\"file:///public/file\", \"public/file\", \"\"},\n\t\t{\"file:///shared/file\", \"shared/file\", \"\"},\n\t\t{\"http:///foo\", \"\", \"not a file\"},\n\t\t{\"file://foo\", \"\", \"empty\"},\n\t\t{\"file://foo/../bar\", \"\", \"localized\"},\n\t\t{\"file:///secret\", \"\", \"root\"},\n\t\t{\"file:///secret/file\", \"\", \"root\"},\n\t\t{\"file:///private/file\", \"\", \"root\"},\n\t} {\n\t\tt.Run(tt.uri, func(t *testing.T) {\n\t\t\ttt.want = filepath.FromSlash(tt.want) // handle Windows\n\t\t\tgot, gotErr := computeURIFilepath(tt.uri, dirFilepath, rootFilepaths)\n\t\t\tif gotErr != nil {\n\t\t\t\tif tt.wantErr == \"\" {\n\t\t\t\t\tt.Fatalf(\"got %v, wanted success\", gotErr)\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(gotErr.Error(), tt.wantErr) {\n\t\t\t\t\tt.Fatalf(\"got error %v, does not contain %q\", gotErr, tt.wantErr)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tt.Fatal(\"succeeded unexpectedly\")\n\t\t\t}\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"got %q, want %q\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestReadFileResource(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Skip(\"TODO: fix for Windows\")\n\t}\n\tabs, err := filepath.Abs(\"testdata\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdirFilepath := filepath.Join(abs, \"files\")\n\tgot, err := readFileResource(\"file:///info.txt\", dirFilepath, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := \"Contents\\n\"\n\tif g := string(got); g != want {\n\t\tt.Errorf(\"got %q, want %q\", g, want)\n\t}\n}\n\nfunc TestTemplateMatch(t *testing.T) {\n\turi := \"file:///path/to/file\"\n\tfor _, tt := range []struct {\n\t\ttemplate string\n\t\twant     bool\n\t}{\n\t\t{\"file:///{}/{a}/{b}\", true},\n\t\t{\"file:///{a}/{b}\", false},\n\t\t{\"file:///{+path}\", true},\n\t\t{\"file:///{a}/{+path}\", true},\n\t} {\n\t\tre, err := uriTemplateToRegexp(tt.template)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"%s: %v\", tt.template, err)\n\t\t}\n\t\tgot := re.MatchString(uri)\n\t\tif got != tt.want {\n\t\t\tt.Errorf(\"%s: got %t, want %t\", tt.template, got, tt.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/root.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n"
  },
  {
    "path": "internal/mcp/server.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"iter\"\n\t\"net/url\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sync\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\nconst DefaultPageSize = 1000\n\n// A Server is an instance of an MCP server.\n//\n// Servers expose server-side MCP features, which can serve one or more MCP\n// sessions by using [Server.Start] or [Server.Run].\ntype Server struct {\n\t// fixed at creation\n\tname    string\n\tversion string\n\topts    ServerOptions\n\n\tmu                      sync.Mutex\n\tprompts                 *featureSet[*ServerPrompt]\n\ttools                   *featureSet[*ServerTool]\n\tresources               *featureSet[*ServerResource]\n\tresourceTemplates       *featureSet[*ServerResourceTemplate]\n\tsessions                []*ServerSession\n\tsendingMethodHandler_   MethodHandler[*ServerSession]\n\treceivingMethodHandler_ MethodHandler[*ServerSession]\n}\n\n// ServerOptions is used to configure behavior of the server.\ntype ServerOptions struct {\n\t// Optional instructions for connected clients.\n\tInstructions string\n\t// If non-nil, called when \"notifications/initialized\" is received.\n\tInitializedHandler func(context.Context, *ServerSession, *InitializedParams)\n\t// PageSize is the maximum number of items to return in a single page for\n\t// list methods (e.g. ListTools).\n\tPageSize int\n\t// If non-nil, called when \"notifications/roots/list_changed\" is received.\n\tRootsListChangedHandler func(context.Context, *ServerSession, *RootsListChangedParams)\n\t// If non-nil, called when \"notifications/progress\" is received.\n\tProgressNotificationHandler func(context.Context, *ServerSession, *ProgressNotificationParams)\n}\n\n// NewServer creates a new MCP server. The resulting server has no features:\n// add features using [Server.AddTools], [Server.AddPrompts] and [Server.AddResources].\n//\n// The server can be connected to one or more MCP clients using [Server.Start]\n// or [Server.Run].\n//\n// If non-nil, the provided options is used to configure the server.\nfunc NewServer(name, version string, opts *ServerOptions) *Server {\n\tif opts == nil {\n\t\topts = new(ServerOptions)\n\t}\n\tif opts.PageSize < 0 {\n\t\tpanic(fmt.Errorf(\"invalid page size %d\", opts.PageSize))\n\t}\n\tif opts.PageSize == 0 {\n\t\topts.PageSize = DefaultPageSize\n\t}\n\treturn &Server{\n\t\tname:                    name,\n\t\tversion:                 version,\n\t\topts:                    *opts,\n\t\tprompts:                 newFeatureSet(func(p *ServerPrompt) string { return p.Prompt.Name }),\n\t\ttools:                   newFeatureSet(func(t *ServerTool) string { return t.Tool.Name }),\n\t\tresources:               newFeatureSet(func(r *ServerResource) string { return r.Resource.URI }),\n\t\tresourceTemplates:       newFeatureSet(func(t *ServerResourceTemplate) string { return t.ResourceTemplate.URITemplate }),\n\t\tsendingMethodHandler_:   defaultSendingMethodHandler[*ServerSession],\n\t\treceivingMethodHandler_: defaultReceivingMethodHandler[*ServerSession],\n\t}\n}\n\n// AddPrompts adds the given prompts to the server,\n// replacing any with the same names.\nfunc (s *Server) AddPrompts(prompts ...*ServerPrompt) {\n\t// Only notify if something could change.\n\tif len(prompts) == 0 {\n\t\treturn\n\t}\n\t// Assume there was a change, since add replaces existing roots.\n\t// (It's possible a root was replaced with an identical one, but not worth checking.)\n\ts.changeAndNotify(\n\t\tnotificationPromptListChanged,\n\t\t&PromptListChangedParams{},\n\t\tfunc() bool { s.prompts.add(prompts...); return true })\n}\n\n// RemovePrompts removes the prompts with the given names.\n// It is not an error to remove a nonexistent prompt.\nfunc (s *Server) RemovePrompts(names ...string) {\n\ts.changeAndNotify(notificationPromptListChanged, &PromptListChangedParams{},\n\t\tfunc() bool { return s.prompts.remove(names...) })\n}\n\n// AddTools adds the given tools to the server,\n// replacing any with the same names.\n// The arguments must not be modified after this call.\n//\n// AddTools panics if errors are detected.\nfunc (s *Server) AddTools(tools ...*ServerTool) {\n\tif err := s.addToolsErr(tools...); err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// addToolsErr is like [AddTools], but returns an error instead of panicking.\nfunc (s *Server) addToolsErr(tools ...*ServerTool) error {\n\t// Only notify if something could change.\n\tif len(tools) == 0 {\n\t\treturn nil\n\t}\n\t// Wrap the user's Handlers with rawHandlers that take a json.RawMessage.\n\tfor _, st := range tools {\n\t\tif st.rawHandler == nil {\n\t\t\t// This ServerTool was not created with NewServerTool.\n\t\t\tif st.Handler == nil {\n\t\t\t\treturn fmt.Errorf(\"AddTools: tool %q has no handler\", st.Tool.Name)\n\t\t\t}\n\t\t\tst.rawHandler = newRawHandler(st)\n\t\t\t// Resolve the schemas, with no base URI. We don't expect tool schemas to\n\t\t\t// refer outside of themselves.\n\t\t\t// TODO(rfindley): re-enable schema validation. See note in [ServerTool].\n\t\t\t// if st.Tool.InputSchema != nil {\n\t\t\t// \tr, err := st.Tool.InputSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})\n\t\t\t// \tif err != nil {\n\t\t\t// \t\treturn err\n\t\t\t// \t}\n\t\t\t// \tst.inputResolved = r\n\t\t\t// }\n\n\t\t\t// TODO: uncomment when output schemas drop.\n\t\t\t// if st.Tool.OutputSchema != nil {\n\t\t\t// \tst.outputResolved, err := st.Tool.OutputSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})\n\t\t\t// \tif err != nil {\n\t\t\t// \t\treturn err\n\t\t\t// \t}\n\t\t\t// }\n\t\t}\n\t}\n\n\t// Assume there was a change, since add replaces existing tools.\n\t// (It's possible a tool was replaced with an identical one, but not worth checking.)\n\t// TODO: surface notify error here?\n\ts.changeAndNotify(notificationToolListChanged, &ToolListChangedParams{},\n\t\tfunc() bool { s.tools.add(tools...); return true })\n\treturn nil\n}\n\n// RemoveTools removes the tools with the given names.\n// It is not an error to remove a nonexistent tool.\nfunc (s *Server) RemoveTools(names ...string) {\n\ts.changeAndNotify(notificationToolListChanged, &ToolListChangedParams{},\n\t\tfunc() bool { return s.tools.remove(names...) })\n}\n\n// AddResources adds the given resources to the server.\n// If a resource with the same URI already exists, it is replaced.\n// AddResources panics if a resource URI is invalid or not absolute (has an empty scheme).\nfunc (s *Server) AddResources(resources ...*ServerResource) {\n\t// Only notify if something could change.\n\tif len(resources) == 0 {\n\t\treturn\n\t}\n\ts.changeAndNotify(notificationResourceListChanged, &ResourceListChangedParams{},\n\t\tfunc() bool {\n\t\t\tfor _, r := range resources {\n\t\t\t\tu, err := url.Parse(r.Resource.URI)\n\t\t\t\tif err != nil {\n\t\t\t\t\tpanic(err) // url.Parse includes the URI in the error\n\t\t\t\t}\n\t\t\t\tif !u.IsAbs() {\n\t\t\t\t\tpanic(fmt.Errorf(\"URI %s needs a scheme\", r.Resource.URI))\n\t\t\t\t}\n\t\t\t\ts.resources.add(r)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n}\n\n// RemoveResources removes the resources with the given URIs.\n// It is not an error to remove a nonexistent resource.\nfunc (s *Server) RemoveResources(uris ...string) {\n\ts.changeAndNotify(notificationResourceListChanged, &ResourceListChangedParams{},\n\t\tfunc() bool { return s.resources.remove(uris...) })\n}\n\n// AddResourceTemplates adds the given resource templates to the server.\n// If a resource template with the same URI template already exists, it will be replaced.\n// AddResourceTemplates panics if a URI template is invalid or not absolute (has an empty scheme).\nfunc (s *Server) AddResourceTemplates(templates ...*ServerResourceTemplate) {\n\t// Only notify if something could change.\n\tif len(templates) == 0 {\n\t\treturn\n\t}\n\ts.changeAndNotify(notificationResourceListChanged, &ResourceListChangedParams{},\n\t\tfunc() bool {\n\t\t\tfor _, t := range templates {\n\t\t\t\t// TODO: check template validity.\n\t\t\t\ts.resourceTemplates.add(t)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n}\n\n// RemoveResourceTemplates removes the resource templates with the given URI templates.\n// It is not an error to remove a nonexistent resource.\nfunc (s *Server) RemoveResourceTemplates(uriTemplates ...string) {\n\ts.changeAndNotify(notificationResourceListChanged, &ResourceListChangedParams{},\n\t\tfunc() bool { return s.resourceTemplates.remove(uriTemplates...) })\n}\n\n// changeAndNotify is called when a feature is added or removed.\n// It calls change, which should do the work and report whether a change actually occurred.\n// If there was a change, it notifies a snapshot of the sessions.\nfunc (s *Server) changeAndNotify(notification string, params Params, change func() bool) {\n\tvar sessions []*ServerSession\n\t// Lock for the change, but not for the notification.\n\ts.mu.Lock()\n\tif change() {\n\t\tsessions = slices.Clone(s.sessions)\n\t}\n\ts.mu.Unlock()\n\tnotifySessions(sessions, notification, params)\n}\n\n// Sessions returns an iterator that yields the current set of server sessions.\nfunc (s *Server) Sessions() iter.Seq[*ServerSession] {\n\ts.mu.Lock()\n\tclients := slices.Clone(s.sessions)\n\ts.mu.Unlock()\n\treturn slices.Values(clients)\n}\n\nfunc (s *Server) listPrompts(_ context.Context, _ *ServerSession, params *ListPromptsParams) (*ListPromptsResult, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif params == nil {\n\t\tparams = &ListPromptsParams{}\n\t}\n\treturn paginateList(s.prompts, s.opts.PageSize, params, &ListPromptsResult{}, func(res *ListPromptsResult, prompts []*ServerPrompt) {\n\t\tres.Prompts = []*Prompt{} // avoid JSON null\n\t\tfor _, p := range prompts {\n\t\t\tres.Prompts = append(res.Prompts, p.Prompt)\n\t\t}\n\t})\n}\n\nfunc (s *Server) getPrompt(ctx context.Context, cc *ServerSession, params *GetPromptParams) (*GetPromptResult, error) {\n\ts.mu.Lock()\n\tprompt, ok := s.prompts.get(params.Name)\n\ts.mu.Unlock()\n\tif !ok {\n\t\t// TODO: surface the error code over the wire, instead of flattening it into the string.\n\t\treturn nil, fmt.Errorf(\"%s: unknown prompt %q\", jsonrpc2.ErrInvalidParams, params.Name)\n\t}\n\treturn prompt.Handler(ctx, cc, params)\n}\n\nfunc (s *Server) listTools(_ context.Context, _ *ServerSession, params *ListToolsParams) (*ListToolsResult, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif params == nil {\n\t\tparams = &ListToolsParams{}\n\t}\n\treturn paginateList(s.tools, s.opts.PageSize, params, &ListToolsResult{}, func(res *ListToolsResult, tools []*ServerTool) {\n\t\tres.Tools = []*Tool{} // avoid JSON null\n\t\tfor _, t := range tools {\n\t\t\tres.Tools = append(res.Tools, t.Tool)\n\t\t}\n\t})\n}\n\nfunc (s *Server) callTool(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[json.RawMessage]) (*CallToolResult, error) {\n\ts.mu.Lock()\n\ttool, ok := s.tools.get(params.Name)\n\ts.mu.Unlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%s: unknown tool %q\", jsonrpc2.ErrInvalidParams, params.Name)\n\t}\n\treturn tool.rawHandler(ctx, cc, params)\n}\n\nfunc (s *Server) listResources(_ context.Context, _ *ServerSession, params *ListResourcesParams) (*ListResourcesResult, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif params == nil {\n\t\tparams = &ListResourcesParams{}\n\t}\n\treturn paginateList(s.resources, s.opts.PageSize, params, &ListResourcesResult{}, func(res *ListResourcesResult, resources []*ServerResource) {\n\t\tres.Resources = []*Resource{} // avoid JSON null\n\t\tfor _, r := range resources {\n\t\t\tres.Resources = append(res.Resources, r.Resource)\n\t\t}\n\t})\n}\n\nfunc (s *Server) listResourceTemplates(_ context.Context, _ *ServerSession, params *ListResourceTemplatesParams) (*ListResourceTemplatesResult, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tif params == nil {\n\t\tparams = &ListResourceTemplatesParams{}\n\t}\n\treturn paginateList(s.resourceTemplates, s.opts.PageSize, params, &ListResourceTemplatesResult{},\n\t\tfunc(res *ListResourceTemplatesResult, rts []*ServerResourceTemplate) {\n\t\t\tres.ResourceTemplates = []*ResourceTemplate{} // avoid JSON null\n\t\t\tfor _, rt := range rts {\n\t\t\t\tres.ResourceTemplates = append(res.ResourceTemplates, rt.ResourceTemplate)\n\t\t\t}\n\t\t})\n}\n\nfunc (s *Server) readResource(ctx context.Context, ss *ServerSession, params *ReadResourceParams) (*ReadResourceResult, error) {\n\turi := params.URI\n\t// Look up the resource URI in the lists of resources and resource templates.\n\t// This is a security check as well as an information lookup.\n\thandler, mimeType, ok := s.lookupResourceHandler(uri)\n\tif !ok {\n\t\t// Don't expose the server configuration to the client.\n\t\t// Treat an unregistered resource the same as a registered one that couldn't be found.\n\t\treturn nil, ResourceNotFoundError(uri)\n\t}\n\tres, err := handler(ctx, ss, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif res == nil || res.Contents == nil {\n\t\treturn nil, fmt.Errorf(\"reading resource %s: read handler returned nil information\", uri)\n\t}\n\t// As a convenience, populate some fields.\n\tfor _, c := range res.Contents {\n\t\tif c.URI == \"\" {\n\t\t\tc.URI = uri\n\t\t}\n\t\tif c.MIMEType == \"\" {\n\t\t\tc.MIMEType = mimeType\n\t\t}\n\t}\n\treturn res, nil\n}\n\n// lookupResourceHandler returns the resource handler and MIME type for the resource or\n// resource template matching uri. If none, the last return value is false.\nfunc (s *Server) lookupResourceHandler(uri string) (ResourceHandler, string, bool) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\t// Try resources first.\n\tif r, ok := s.resources.get(uri); ok {\n\t\treturn r.Handler, r.Resource.MIMEType, true\n\t}\n\t// Look for matching template.\n\tfor rt := range s.resourceTemplates.all() {\n\t\tif rt.Matches(uri) {\n\t\t\treturn rt.Handler, rt.ResourceTemplate.MIMEType, true\n\t\t}\n\t}\n\treturn nil, \"\", false\n}\n\n// fileResourceHandler returns a ReadResourceHandler that reads paths using dir as\n// a base directory.\n// It honors client roots and protects against path traversal attacks.\n//\n// The dir argument should be a filesystem path. It need not be absolute, but\n// that is recommended to avoid a dependency on the current working directory (the\n// check against client roots is done with an absolute path). If dir is not absolute\n// and the current working directory is unavailable, FileResourceHandler panics.\n//\n// Lexical path traversal attacks, where the path has \"..\" elements that escape dir,\n// are always caught. Go 1.24 and above also protects against symlink-based attacks,\n// where symlinks under dir lead out of the tree.\nfunc (s *Server) fileResourceHandler(dir string) ResourceHandler {\n\treturn fileResourceHandler(dir)\n}\n\nfunc fileResourceHandler(dir string) ResourceHandler {\n\t// Convert dir to an absolute path.\n\tdirFilepath, err := filepath.Abs(dir)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn func(ctx context.Context, ss *ServerSession, params *ReadResourceParams) (_ *ReadResourceResult, err error) {\n\t\tdefer util.Wrapf(&err, \"reading resource %s\", params.URI)\n\n\t\t// TODO: use a memoizing API here.\n\t\trootRes, err := ss.ListRoots(ctx, nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"listing roots: %w\", err)\n\t\t}\n\t\troots, err := fileRoots(rootRes.Roots)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdata, err := readFileResource(params.URI, dirFilepath, roots)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// TODO(jba): figure out mime type. Omit for now: Server.readResource will fill it in.\n\t\treturn &ReadResourceResult{Contents: []*ResourceContents{NewBlobResourceContents(params.URI, \"\", data)}}, nil\n\t}\n}\n\n// Run runs the server over the given transport, which must be persistent.\n//\n// Run blocks until the client terminates the connection.\nfunc (s *Server) Run(ctx context.Context, t Transport) error {\n\tss, err := s.Connect(ctx, t)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn ss.Wait()\n}\n\n// bind implements the binder[*ServerSession] interface, so that Servers can\n// be connected using [connect].\nfunc (s *Server) bind(conn *jsonrpc2.Connection) *ServerSession {\n\tss := &ServerSession{conn: conn, server: s}\n\ts.mu.Lock()\n\ts.sessions = append(s.sessions, ss)\n\ts.mu.Unlock()\n\treturn ss\n}\n\n// disconnect implements the binder[*ServerSession] interface, so that\n// Servers can be connected using [connect].\nfunc (s *Server) disconnect(cc *ServerSession) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\ts.sessions = slices.DeleteFunc(s.sessions, func(cc2 *ServerSession) bool {\n\t\treturn cc2 == cc\n\t})\n}\n\n// Connect connects the MCP server over the given transport and starts handling\n// messages.\n//\n// It returns a connection object that may be used to terminate the connection\n// (with [Connection.Close]), or await client termination (with\n// [Connection.Wait]).\nfunc (s *Server) Connect(ctx context.Context, t Transport) (*ServerSession, error) {\n\treturn connect(ctx, t, s)\n}\n\nfunc (s *Server) callInitializedHandler(ctx context.Context, ss *ServerSession, params *InitializedParams) (Result, error) {\n\treturn callNotificationHandler(ctx, s.opts.InitializedHandler, ss, params)\n}\n\nfunc (s *Server) callRootsListChangedHandler(ctx context.Context, ss *ServerSession, params *RootsListChangedParams) (Result, error) {\n\treturn callNotificationHandler(ctx, s.opts.RootsListChangedHandler, ss, params)\n}\n\nfunc (ss *ServerSession) callProgressNotificationHandler(ctx context.Context, params *ProgressNotificationParams) (Result, error) {\n\treturn callNotificationHandler(ctx, ss.server.opts.ProgressNotificationHandler, ss, params)\n}\n\n// NotifyProgress sends a progress notification from the server to the client\n// associated with this session.\n// This is typically used to report on the status of a long-running request\n// that was initiated by the client.\nfunc (ss *ServerSession) NotifyProgress(ctx context.Context, params *ProgressNotificationParams) error {\n\treturn handleNotify(ctx, ss, notificationProgress, params)\n}\n\n// A ServerSession is a logical connection from a single MCP client. Its\n// methods can be used to send requests or notifications to the client. Create\n// a session by calling [Server.Connect].\n//\n// Call [ServerSession.Close] to close the connection, or await client\n// termination with [ServerSession.Wait].\ntype ServerSession struct {\n\tserver           *Server\n\tconn             *jsonrpc2.Connection\n\tmu               sync.Mutex\n\tlogLevel         LoggingLevel\n\tinitializeParams *InitializeParams\n\tinitialized      bool\n}\n\n// Ping pings the client.\nfunc (ss *ServerSession) Ping(ctx context.Context, params *PingParams) error {\n\t_, err := handleSend[*emptyResult](ctx, ss, methodPing, params)\n\treturn err\n}\n\n// ListRoots lists the client roots.\nfunc (ss *ServerSession) ListRoots(ctx context.Context, params *ListRootsParams) (*ListRootsResult, error) {\n\treturn handleSend[*ListRootsResult](ctx, ss, methodListRoots, orZero[Params](params))\n}\n\n// CreateMessage sends a sampling request to the client.\nfunc (ss *ServerSession) CreateMessage(ctx context.Context, params *CreateMessageParams) (*CreateMessageResult, error) {\n\treturn handleSend[*CreateMessageResult](ctx, ss, methodCreateMessage, orZero[Params](params))\n}\n\n// LoggingMessage sends a logging message to the client.\n// The message is not sent if the client has not called SetLevel, or if its level\n// is below that of the last SetLevel.\n//\n// TODO(jba): rename to Log or LogMessage. A logging message is the thing that is sent to logging.\nfunc (ss *ServerSession) LoggingMessage(ctx context.Context, params *LoggingMessageParams) error {\n\tss.mu.Lock()\n\tlogLevel := ss.logLevel\n\tss.mu.Unlock()\n\tif logLevel == \"\" {\n\t\t// The spec is unclear, but seems to imply that no log messages are sent until the client\n\t\t// sets the level.\n\t\t// TODO(jba): read other SDKs, possibly file an issue.\n\t\treturn nil\n\t}\n\tif compareLevels(params.Level, logLevel) < 0 {\n\t\treturn nil\n\t}\n\treturn handleNotify(ctx, ss, notificationLoggingMessage, params)\n}\n\n// AddSendingMiddleware wraps the current sending method handler using the provided\n// middleware. Middleware is applied from right to left, so that the first one is\n// executed first.\n//\n// For example, AddSendingMiddleware(m1, m2, m3) augments the method handler as\n// m1(m2(m3(handler))).\n//\n// Sending middleware is called when a request is sent. It is useful for tasks\n// such as tracing, metrics, and adding progress tokens.\nfunc (s *Server) AddSendingMiddleware(middleware ...Middleware[*ServerSession]) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\taddMiddleware(&s.sendingMethodHandler_, middleware)\n}\n\n// AddReceivingMiddleware wraps the current receiving method handler using\n// the provided middleware. Middleware is applied from right to left, so that the\n// first one is executed first.\n//\n// For example, AddReceivingMiddleware(m1, m2, m3) augments the method handler as\n// m1(m2(m3(handler))).\n//\n// Receiving middleware is called when a request is received. It is useful for tasks\n// such as authentication, request logging and metrics.\nfunc (s *Server) AddReceivingMiddleware(middleware ...Middleware[*ServerSession]) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\taddMiddleware(&s.receivingMethodHandler_, middleware)\n}\n\n// serverMethodInfos maps from the RPC method name to serverMethodInfos.\nvar serverMethodInfos = map[string]methodInfo{\n\tmethodInitialize:             newMethodInfo(sessionMethod((*ServerSession).initialize)),\n\tmethodPing:                   newMethodInfo(sessionMethod((*ServerSession).ping)),\n\tmethodListPrompts:            newMethodInfo(serverMethod((*Server).listPrompts)),\n\tmethodGetPrompt:              newMethodInfo(serverMethod((*Server).getPrompt)),\n\tmethodListTools:              newMethodInfo(serverMethod((*Server).listTools)),\n\tmethodCallTool:               newMethodInfo(serverMethod((*Server).callTool)),\n\tmethodListResources:          newMethodInfo(serverMethod((*Server).listResources)),\n\tmethodListResourceTemplates:  newMethodInfo(serverMethod((*Server).listResourceTemplates)),\n\tmethodReadResource:           newMethodInfo(serverMethod((*Server).readResource)),\n\tmethodSetLevel:               newMethodInfo(sessionMethod((*ServerSession).setLevel)),\n\tnotificationInitialized:      newMethodInfo(serverMethod((*Server).callInitializedHandler)),\n\tnotificationRootsListChanged: newMethodInfo(serverMethod((*Server).callRootsListChangedHandler)),\n\tnotificationProgress:         newMethodInfo(sessionMethod((*ServerSession).callProgressNotificationHandler)),\n}\n\nfunc (ss *ServerSession) sendingMethodInfos() map[string]methodInfo { return clientMethodInfos }\n\nfunc (ss *ServerSession) receivingMethodInfos() map[string]methodInfo { return serverMethodInfos }\n\nfunc (ss *ServerSession) sendingMethodHandler() methodHandler {\n\tss.server.mu.Lock()\n\tdefer ss.server.mu.Unlock()\n\treturn ss.server.sendingMethodHandler_\n}\n\nfunc (ss *ServerSession) receivingMethodHandler() methodHandler {\n\tss.server.mu.Lock()\n\tdefer ss.server.mu.Unlock()\n\treturn ss.server.receivingMethodHandler_\n}\n\n// getConn implements [session.getConn].\nfunc (ss *ServerSession) getConn() *jsonrpc2.Connection { return ss.conn }\n\n// handle invokes the method described by the given JSON RPC request.\nfunc (ss *ServerSession) handle(ctx context.Context, req *JSONRPCRequest) (any, error) {\n\tss.mu.Lock()\n\tinitialized := ss.initialized\n\tss.mu.Unlock()\n\t// From the spec:\n\t// \"The client SHOULD NOT send requests other than pings before the server\n\t// has responded to the initialize request.\"\n\tswitch req.Method {\n\tcase \"initialize\", \"ping\":\n\tdefault:\n\t\tif !initialized {\n\t\t\treturn nil, fmt.Errorf(\"method %q is invalid during session initialization\", req.Method)\n\t\t}\n\t}\n\t// For the streamable transport, we need the request ID to correlate\n\t// server->client calls and notifications to the incoming request from which\n\t// they originated. See [idContext] for details.\n\tctx = context.WithValue(ctx, idContextKey{}, req.ID)\n\treturn handleReceive(ctx, ss, req)\n}\n\nfunc (ss *ServerSession) initialize(ctx context.Context, params *InitializeParams) (*InitializeResult, error) {\n\tss.mu.Lock()\n\tss.initializeParams = params\n\tss.mu.Unlock()\n\n\t// Mark the connection as initialized when this method exits.\n\t// TODO: Technically, the server should not be considered initialized until it has\n\t// *responded*, but we don't have adequate visibility into the jsonrpc2\n\t// connection to implement that easily. In any case, once we've initialized\n\t// here, we can handle requests.\n\tdefer func() {\n\t\tss.mu.Lock()\n\t\tss.initialized = true\n\t\tss.mu.Unlock()\n\t}()\n\n\tversion := \"2025-03-26\" // preferred version\n\tswitch v := params.ProtocolVersion; v {\n\tcase \"2024-11-05\", \"2025-03-26\":\n\t\tversion = v\n\t}\n\n\treturn &InitializeResult{\n\t\t// TODO(rfindley): alter behavior when falling back to an older version:\n\t\t// reject unsupported features.\n\t\tProtocolVersion: version,\n\t\tCapabilities: &serverCapabilities{\n\t\t\tPrompts: &promptCapabilities{\n\t\t\t\tListChanged: true,\n\t\t\t},\n\t\t\tTools: &toolCapabilities{\n\t\t\t\tListChanged: true,\n\t\t\t},\n\t\t\tResources: &resourceCapabilities{\n\t\t\t\tListChanged: true,\n\t\t\t},\n\t\t\tLogging: &loggingCapabilities{},\n\t\t},\n\t\tInstructions: ss.server.opts.Instructions,\n\t\tServerInfo: &implementation{\n\t\t\tName:    ss.server.name,\n\t\t\tVersion: ss.server.version,\n\t\t},\n\t}, nil\n}\n\nfunc (ss *ServerSession) ping(context.Context, *PingParams) (*emptyResult, error) {\n\treturn &emptyResult{}, nil\n}\n\nfunc (ss *ServerSession) setLevel(_ context.Context, params *SetLevelParams) (*emptyResult, error) {\n\tss.mu.Lock()\n\tdefer ss.mu.Unlock()\n\tss.logLevel = params.Level\n\treturn &emptyResult{}, nil\n}\n\n// Close performs a graceful shutdown of the connection, preventing new\n// requests from being handled, and waiting for ongoing requests to return.\n// Close then terminates the connection.\nfunc (ss *ServerSession) Close() error {\n\treturn ss.conn.Close()\n}\n\n// Wait waits for the connection to be closed by the client.\nfunc (ss *ServerSession) Wait() error {\n\treturn ss.conn.Wait()\n}\n\n// pageToken is the internal structure for the opaque pagination cursor.\n// It will be Gob-encoded and then Base64-encoded for use as a string token.\ntype pageToken struct {\n\tLastUID string // The unique ID of the last resource seen.\n}\n\n// encodeCursor encodes a unique identifier (UID) into a opaque pagination cursor\n// by serializing a pageToken struct.\nfunc encodeCursor(uid string) (string, error) {\n\tvar buf bytes.Buffer\n\ttoken := pageToken{LastUID: uid}\n\tencoder := gob.NewEncoder(&buf)\n\tif err := encoder.Encode(token); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to encode page token: %w\", err)\n\t}\n\treturn base64.URLEncoding.EncodeToString(buf.Bytes()), nil\n}\n\n// decodeCursor decodes an opaque pagination cursor into the original pageToken struct.\nfunc decodeCursor(cursor string) (*pageToken, error) {\n\tdecodedBytes, err := base64.URLEncoding.DecodeString(cursor)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode cursor: %w\", err)\n\t}\n\n\tvar token pageToken\n\tbuf := bytes.NewBuffer(decodedBytes)\n\tdecoder := gob.NewDecoder(buf)\n\tif err := decoder.Decode(&token); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode page token: %w, cursor: %v\", err, cursor)\n\t}\n\treturn &token, nil\n}\n\n// paginateList is a generic helper that returns a paginated slice of items\n// from a featureSet. It populates the provided result res with the items\n// and sets its next cursor for subsequent pages.\n// If there are no more pages, the next cursor within the result will be an empty string.\nfunc paginateList[P listParams, R listResult[T], T any](fs *featureSet[T], pageSize int, params P, res R, setFunc func(R, []T)) (R, error) {\n\tvar seq iter.Seq[T]\n\tif params.cursorPtr() == nil || *params.cursorPtr() == \"\" {\n\t\tseq = fs.all()\n\t} else {\n\t\tpageToken, err := decodeCursor(*params.cursorPtr())\n\t\t// According to the spec, invalid cursors should return Invalid params.\n\t\tif err != nil {\n\t\t\tvar zero R\n\t\t\treturn zero, jsonrpc2.ErrInvalidParams\n\t\t}\n\t\tseq = fs.above(pageToken.LastUID)\n\t}\n\tvar count int\n\tvar features []T\n\tfor f := range seq {\n\t\tcount++\n\t\t// If we've seen pageSize + 1 elements, we've gathered enough info to determine\n\t\t// if there's a next page. Stop processing the sequence.\n\t\tif count == pageSize+1 {\n\t\t\tbreak\n\t\t}\n\t\tfeatures = append(features, f)\n\t}\n\tsetFunc(res, features)\n\t// No remaining pages.\n\tif count < pageSize+1 {\n\t\treturn res, nil\n\t}\n\tnextCursor, err := encodeCursor(fs.uniqueID(features[len(features)-1]))\n\tif err != nil {\n\t\tvar zero R\n\t\treturn zero, err\n\t}\n\t*res.nextCursorPtr() = nextCursor\n\treturn res, nil\n}\n"
  },
  {
    "path": "internal/mcp/server_example_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\ntype SayHiParams struct {\n\tName string `json:\"name\"`\n}\n\nfunc SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {\n\treturn &mcp.CallToolResultFor[any]{\n\t\tContent: []*mcp.Content{\n\t\t\tmcp.NewTextContent(\"Hi \" + params.Arguments.Name),\n\t\t},\n\t}, nil\n}\n\nfunc ExampleServer() {\n\tctx := context.Background()\n\tclientTransport, serverTransport := mcp.NewInMemoryTransports()\n\n\tserver := mcp.NewServer(\"greeter\", \"v0.0.1\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"greet\", \"say hi\", SayHi))\n\n\tserverSession, err := server.Connect(ctx, serverTransport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tclient := mcp.NewClient(\"client\", \"v0.0.1\", nil)\n\tclientSession, err := client.Connect(ctx, clientTransport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tres, err := clientSession.CallTool(ctx, &mcp.CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"user\"},\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(res.Content[0].Text)\n\n\tclientSession.Close()\n\tserverSession.Wait()\n\n\t// Output: Hi user\n}\n\n// createSessions creates and connects an in-memory client and server session for testing purposes.\nfunc createSessions(ctx context.Context) (*mcp.ClientSession, *mcp.ServerSession, *mcp.Server) {\n\tserver := mcp.NewServer(\"server\", \"v0.0.1\", nil)\n\tclient := mcp.NewClient(\"client\", \"v0.0.1\", nil)\n\tserverTransport, clientTransport := mcp.NewInMemoryTransports()\n\tserverSession, err := server.Connect(ctx, serverTransport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tclientSession, err := client.Connect(ctx, clientTransport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn clientSession, serverSession, server\n}\n"
  },
  {
    "path": "internal/mcp/server_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"log\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\ntype testItem struct {\n\tName  string\n\tValue string\n}\n\ntype testListParams struct {\n\tCursor string\n}\n\nfunc (p *testListParams) cursorPtr() *string {\n\treturn &p.Cursor\n}\n\ntype testListResult struct {\n\tItems      []*testItem\n\tNextCursor string\n}\n\nfunc (r *testListResult) nextCursorPtr() *string {\n\treturn &r.NextCursor\n}\n\nvar allTestItems = []*testItem{\n\t{\"alpha\", \"val-A\"},\n\t{\"bravo\", \"val-B\"},\n\t{\"charlie\", \"val-C\"},\n\t{\"delta\", \"val-D\"},\n\t{\"echo\", \"val-E\"},\n\t{\"foxtrot\", \"val-F\"},\n\t{\"golf\", \"val-G\"},\n\t{\"hotel\", \"val-H\"},\n\t{\"india\", \"val-I\"},\n\t{\"juliet\", \"val-J\"},\n\t{\"kilo\", \"val-K\"},\n}\n\n// getCursor encodes a string input into a URL-safe base64 cursor,\n// fatally logging any encoding errors.\nfunc getCursor(input string) string {\n\tcursor, err := encodeCursor(input)\n\tif err != nil {\n\t\tlog.Fatalf(\"encodeCursor(%s) error = %v\", input, err)\n\t}\n\treturn cursor\n}\n\nfunc TestServerPaginateBasic(t *testing.T) {\n\ttestCases := []struct {\n\t\tname           string\n\t\tinitialItems   []*testItem\n\t\tinputCursor    string\n\t\tinputPageSize  int\n\t\twantFeatures   []*testItem\n\t\twantNextCursor string\n\t\twantErr        bool\n\t}{\n\t\t{\n\t\t\tname:           \"FirstPage_DefaultSize_Full\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    \"\",\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[0:5],\n\t\t\twantNextCursor: getCursor(\"echo\"), // Based on last item of first page\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"SecondPage_DefaultSize_Full\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    getCursor(\"echo\"),\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[5:10],\n\t\t\twantNextCursor: getCursor(\"juliet\"), // Based on last item of second page\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"SecondPage_DefaultSize_Full_OutOfOrder\",\n\t\t\tinitialItems:   append(allTestItems[5:], allTestItems[0:5]...),\n\t\t\tinputCursor:    getCursor(\"echo\"),\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[5:10],\n\t\t\twantNextCursor: getCursor(\"juliet\"), // Based on last item of second page\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"SecondPage_DefaultSize_Full_Duplicates\",\n\t\t\tinitialItems:   append(allTestItems, allTestItems[0:5]...),\n\t\t\tinputCursor:    getCursor(\"echo\"),\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[5:10],\n\t\t\twantNextCursor: getCursor(\"juliet\"), // Based on last item of second page\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"LastPage_Remaining\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    getCursor(\"juliet\"),\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[10:11], // Only 1 item left\n\t\t\twantNextCursor: \"\",                  // No more pages\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"PageSize_1\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    \"\",\n\t\t\tinputPageSize:  1,\n\t\t\twantFeatures:   allTestItems[0:1],\n\t\t\twantNextCursor: getCursor(\"alpha\"),\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"PageSize_All\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    \"\",\n\t\t\tinputPageSize:  len(allTestItems), // Page size equals total\n\t\t\twantFeatures:   allTestItems,\n\t\t\twantNextCursor: \"\", // No more pages\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"PageSize_LargerThanAll\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    \"\",\n\t\t\tinputPageSize:  len(allTestItems) + 5, // Page size larger than total\n\t\t\twantFeatures:   allTestItems,\n\t\t\twantNextCursor: \"\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"EmptySet\",\n\t\t\tinitialItems:   nil,\n\t\t\tinputCursor:    \"\",\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   nil,\n\t\t\twantNextCursor: \"\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tname:           \"InvalidCursor\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    \"not-a-valid-gob-base64-cursor\",\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   nil, // Should be nil for error cases\n\t\t\twantNextCursor: \"\",\n\t\t\twantErr:        true,\n\t\t},\n\t\t{\n\t\t\tname:           \"AboveNonExistentID\",\n\t\t\tinitialItems:   allTestItems,\n\t\t\tinputCursor:    getCursor(\"dne\"), // A UID that doesn't exist\n\t\t\tinputPageSize:  5,\n\t\t\twantFeatures:   allTestItems[4:9], // Should return elements above UID.\n\t\t\twantNextCursor: getCursor(\"india\"),\n\t\t\twantErr:        false,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tfs := newFeatureSet(func(t *testItem) string { return t.Name })\n\t\t\tfs.add(tc.initialItems...)\n\t\t\tparams := &testListParams{Cursor: tc.inputCursor}\n\t\t\tgotResult, err := paginateList(fs, tc.inputPageSize, params, &testListResult{}, func(res *testListResult, items []*testItem) {\n\t\t\t\tres.Items = items\n\t\t\t})\n\t\t\tif (err != nil) != tc.wantErr {\n\t\t\t\tt.Errorf(\"paginateList(%s) error, got %v, wantErr %v\", tc.name, err, tc.wantErr)\n\t\t\t}\n\t\t\tif tc.wantErr {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif diff := cmp.Diff(tc.wantFeatures, gotResult.Items); diff != \"\" {\n\t\t\t\tt.Errorf(\"paginateList(%s) mismatch (-want +got):\\n%s\", tc.name, diff)\n\t\t\t}\n\t\t\tif tc.wantNextCursor != gotResult.NextCursor {\n\t\t\t\tt.Errorf(\"paginateList(%s) nextCursor, got %v, want %v\", tc.name, gotResult.NextCursor, tc.wantNextCursor)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestServerPaginateVariousPageSizes(t *testing.T) {\n\tfs := newFeatureSet(func(t *testItem) string { return t.Name })\n\tfs.add(allTestItems...)\n\t// Try all possible page sizes, ensuring we get the correct list of items.\n\tfor pageSize := 1; pageSize < len(allTestItems)+1; pageSize++ {\n\t\tvar gotItems []*testItem\n\t\tvar nextCursor string\n\t\twantChunks := slices.Collect(slices.Chunk(allTestItems, pageSize))\n\t\tindex := 0\n\t\t// Iterate through all pages, comparing sub-slices to the paginated list.\n\t\tfor {\n\t\t\tparams := &testListParams{Cursor: nextCursor}\n\t\t\tgotResult, err := paginateList(fs, pageSize, params, &testListResult{}, func(res *testListResult, items []*testItem) {\n\t\t\t\tres.Items = items\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"paginateList() unexpected error for pageSize %d, cursor %q: %v\", pageSize, nextCursor, err)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantChunks[index], gotResult.Items); diff != \"\" {\n\t\t\t\tt.Errorf(\"paginateList mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t\tgotItems = append(gotItems, gotResult.Items...)\n\t\t\tnextCursor = gotResult.NextCursor\n\t\t\tif nextCursor == \"\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tindex++\n\t\t}\n\n\t\tif len(gotItems) != len(allTestItems) {\n\t\t\tt.Fatalf(\"paginateList() returned %d items, want %d\", len(allTestItems), len(gotItems))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/shared.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains code shared between client and server, including\n// method handler and middleware definitions.\n// TODO: much of this is here so that we can factor out commonalities using\n// generics. Perhaps it can be simplified with reflection.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\n// A MethodHandler handles MCP messages.\n// For methods, exactly one of the return values must be nil.\n// For notifications, both must be nil.\ntype MethodHandler[S Session] func(ctx context.Context, _ S, method string, params Params) (result Result, err error)\n\n// A methodHandler is a MethodHandler[Session] for some session.\n// We need to give up type safety here, or we will end up with a type cycle somewhere\n// else. For example, if Session.methodHandler returned a MethodHandler[Session],\n// the compiler would complain.\ntype methodHandler any // MethodHandler[*ClientSession] | MethodHandler[*ServerSession]\n\n// A Session is either a ClientSession or a ServerSession.\ntype Session interface {\n\t*ClientSession | *ServerSession\n\tsendingMethodInfos() map[string]methodInfo\n\treceivingMethodInfos() map[string]methodInfo\n\tsendingMethodHandler() methodHandler\n\treceivingMethodHandler() methodHandler\n\tgetConn() *jsonrpc2.Connection\n}\n\n// Middleware is a function from MethodHandlers to MethodHandlers.\ntype Middleware[S Session] func(MethodHandler[S]) MethodHandler[S]\n\n// addMiddleware wraps the handler in the middleware functions.\nfunc addMiddleware[S Session](handlerp *MethodHandler[S], middleware []Middleware[S]) {\n\tfor _, m := range slices.Backward(middleware) {\n\t\t*handlerp = m(*handlerp)\n\t}\n}\n\nfunc defaultSendingMethodHandler[S Session](ctx context.Context, session S, method string, params Params) (Result, error) {\n\tinfo, ok := session.sendingMethodInfos()[method]\n\tif !ok {\n\t\t// This can be called from user code, with an arbitrary value for method.\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n\t// Notifications don't have results.\n\tif strings.HasPrefix(method, \"notifications/\") {\n\t\treturn nil, session.getConn().Notify(ctx, method, params)\n\t}\n\t// Create the result to unmarshal into.\n\t// The concrete type of the result is the return type of the receiving function.\n\tres := info.newResult()\n\tif err := call(ctx, session.getConn(), method, params, res); err != nil {\n\t\treturn nil, err\n\t}\n\treturn res, nil\n}\n\n// Helper methods to avoid typed nil.\nfunc orZero[T any, P *U, U any](p P) T {\n\tif p == nil {\n\t\tvar zero T\n\t\treturn zero\n\t}\n\treturn any(p).(T)\n}\n\nfunc handleNotify[S Session](ctx context.Context, session S, method string, params Params) error {\n\tmh := session.sendingMethodHandler().(MethodHandler[S])\n\t_, err := mh(ctx, session, method, params)\n\treturn err\n}\n\nfunc handleSend[R Result, S Session](ctx context.Context, s S, method string, params Params) (R, error) {\n\tmh := s.sendingMethodHandler().(MethodHandler[S])\n\t// mh might be user code, so ensure that it returns the right values for the jsonrpc2 protocol.\n\tres, err := mh(ctx, s, method, params)\n\tif err != nil {\n\t\tvar z R\n\t\treturn z, err\n\t}\n\treturn res.(R), nil\n}\n\n// defaultReceivingMethodHandler is the initial MethodHandler for servers and clients, before being wrapped by middleware.\nfunc defaultReceivingMethodHandler[S Session](ctx context.Context, session S, method string, params Params) (Result, error) {\n\tinfo, ok := session.receivingMethodInfos()[method]\n\tif !ok {\n\t\t// This can be called from user code, with an arbitrary value for method.\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n\treturn info.handleMethod.(MethodHandler[S])(ctx, session, method, params)\n}\n\nfunc handleReceive[S Session](ctx context.Context, session S, req *JSONRPCRequest) (Result, error) {\n\tinfo, ok := session.receivingMethodInfos()[req.Method]\n\tif !ok {\n\t\treturn nil, jsonrpc2.ErrNotHandled\n\t}\n\tparams, err := info.unmarshalParams(req.Params)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"handleRequest %q: %w\", req.Method, err)\n\t}\n\n\tmh := session.receivingMethodHandler().(MethodHandler[S])\n\t// mh might be user code, so ensure that it returns the right values for the jsonrpc2 protocol.\n\tres, err := mh(ctx, session, req.Method, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn res, nil\n}\n\n// methodInfo is information about sending and receiving a method.\ntype methodInfo struct {\n\t// Unmarshal params from the wire into a Params struct.\n\t// Used on the receive side.\n\tunmarshalParams func(json.RawMessage) (Params, error)\n\t// Run the code when a call to the method is received.\n\t// Used on the receive side.\n\thandleMethod methodHandler\n\t// Create a pointer to a Result struct.\n\t// Used on the send side.\n\tnewResult func() Result\n}\n\n// The following definitions support converting from typed to untyped method handlers.\n// Type parameter meanings:\n// - S: sessions\n// - P: params\n// - R: results\n\n// A typedMethodHandler is like a MethodHandler, but with type information.\ntype typedMethodHandler[S Session, P Params, R Result] func(context.Context, S, P) (R, error)\n\ntype paramsPtr[T any] interface {\n\t*T\n\tParams\n}\n\n// newMethodInfo creates a methodInfo from a typedMethodHandler.\nfunc newMethodInfo[S Session, P paramsPtr[T], R Result, T any](d typedMethodHandler[S, P, R]) methodInfo {\n\treturn methodInfo{\n\t\tunmarshalParams: func(m json.RawMessage) (Params, error) {\n\t\t\tvar p P\n\t\t\tif m != nil {\n\t\t\t\tif err := json.Unmarshal(m, &p); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"unmarshaling %q into a %T: %w\", m, p, err)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn orZero[Params](p), nil\n\t\t},\n\t\thandleMethod: MethodHandler[S](func(ctx context.Context, session S, _ string, params Params) (Result, error) {\n\t\t\tif params == nil {\n\t\t\t\treturn d(ctx, session, nil)\n\t\t\t}\n\t\t\treturn d(ctx, session, params.(P))\n\t\t}),\n\t\t// newResult is used on the send side, to construct the value to unmarshal the result into.\n\t\t// R is a pointer to a result struct. There is no way to \"unpointer\" it without reflection.\n\t\t// TODO(jba): explore generic approaches to this, perhaps by treating R in\n\t\t// the signature as the unpointered type.\n\t\tnewResult: func() Result { return reflect.New(reflect.TypeFor[R]().Elem()).Interface().(R) },\n\t}\n}\n\n// serverMethod is glue for creating a typedMethodHandler from a method on Server.\nfunc serverMethod[P Params, R Result](\n\tf func(*Server, context.Context, *ServerSession, P) (R, error),\n) typedMethodHandler[*ServerSession, P, R] {\n\treturn func(ctx context.Context, ss *ServerSession, p P) (R, error) {\n\t\treturn f(ss.server, ctx, ss, p)\n\t}\n}\n\n// clientMethod is glue for creating a typedMethodHandler from a method on Server.\nfunc clientMethod[P Params, R Result](\n\tf func(*Client, context.Context, *ClientSession, P) (R, error),\n) typedMethodHandler[*ClientSession, P, R] {\n\treturn func(ctx context.Context, cs *ClientSession, p P) (R, error) {\n\t\treturn f(cs.client, ctx, cs, p)\n\t}\n}\n\n// sessionMethod is glue for creating a typedMethodHandler from a method on ServerSession.\nfunc sessionMethod[S Session, P Params, R Result](f func(S, context.Context, P) (R, error)) typedMethodHandler[S, P, R] {\n\treturn func(ctx context.Context, sess S, p P) (R, error) {\n\t\treturn f(sess, ctx, p)\n\t}\n}\n\n// Error codes\nconst (\n\t// The error code to return when a resource isn't found.\n\t// See https://modelcontextprotocol.io/specification/2025-03-26/server/resources#error-handling\n\t// However, the code they chose is in the wrong space\n\t// (see https://github.com/modelcontextprotocol/modelcontextprotocol/issues/509).\n\t// so we pick a different one, arbitrarily for now (until they fix it).\n\t// The immediate problem is that jsonprc2 defines -32002 as \"server closing\".\n\tCodeResourceNotFound = -31002\n\t// The error code if the method exists and was called properly, but the peer does not support it.\n\tCodeUnsupportedMethod = -31001\n)\n\nfunc callNotificationHandler[S Session, P any](ctx context.Context, h func(context.Context, S, *P), sess S, params *P) (Result, error) {\n\tif h != nil {\n\t\th(ctx, sess, params)\n\t}\n\treturn nil, nil\n}\n\n// notifySessions calls Notify on all the sessions.\n// Should be called on a copy of the peer sessions.\nfunc notifySessions[S Session](sessions []S, method string, params Params) {\n\tif sessions == nil {\n\t\treturn\n\t}\n\t// TODO: make this timeout configurable, or call Notify asynchronously.\n\tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n\tdefer cancel()\n\tfor _, s := range sessions {\n\t\tif err := handleNotify(ctx, s, method, params); err != nil {\n\t\t\t// TODO(jba): surface this error better\n\t\t\tlog.Printf(\"calling %s: %v\", method, err)\n\t\t}\n\t}\n}\n\ntype Meta struct {\n\tData map[string]any `json:\",omitempty\"`\n\t// For params, the progress token can be nil, a string or an integer.\n\t// It should be nil for results.\n\tProgressToken any `json:\"progressToken,omitempty\"`\n}\n\ntype metaSansMethods Meta // avoid infinite recursion during marshaling\n\nfunc (m Meta) MarshalJSON() ([]byte, error) {\n\tif p := m.ProgressToken; p != nil {\n\t\tif k := reflect.ValueOf(p).Kind(); k != reflect.Int && k != reflect.String {\n\t\t\treturn nil, fmt.Errorf(\"bad type %T for Meta.ProgressToken: must be int or string\", p)\n\t\t}\n\t}\n\t// If ProgressToken is nil, accept Data[\"progressToken\"]. We can't call marshalStructWithMap\n\t// in that case because it will complain about duplicate fields. (We'd have to\n\t// make it much smarter to avoid that; not worth it.)\n\tif m.ProgressToken == nil && len(m.Data) > 0 {\n\t\treturn json.Marshal(m.Data)\n\t}\n\treturn marshalStructWithMap((*metaSansMethods)(&m), \"Data\")\n}\n\nfunc (m *Meta) UnmarshalJSON(data []byte) error {\n\treturn unmarshalStructWithMap(data, (*metaSansMethods)(m), \"Data\")\n}\n\n// Params is a parameter (input) type for an MCP call or notification.\ntype Params interface {\n\t// Returns a pointer to the params's Meta field.\n\tGetMeta() *Meta\n}\n\n// Result is a result of an MCP call.\ntype Result interface {\n\t// Returns a pointer to the result's Meta field.\n\tGetMeta() *Meta\n}\n\n// emptyResult is returned by methods that have no result, like ping.\n// Those methods cannot return nil, because jsonrpc2 cannot handle nils.\ntype emptyResult struct{}\n\nfunc (*emptyResult) GetMeta() *Meta { panic(\"should never be called\") }\n\ntype listParams interface {\n\t// Returns a pointer to the param's Cursor field.\n\tcursorPtr() *string\n}\n\ntype listResult[T any] interface {\n\t// Returns a pointer to the param's NextCursor field.\n\tnextCursorPtr() *string\n}\n"
  },
  {
    "path": "internal/mcp/shared_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestMetaMarshal(t *testing.T) {\n\t// Verify that Meta values round-trip.\n\tfor _, meta := range []Meta{\n\t\t{Data: nil, ProgressToken: nil},\n\t\t{Data: nil, ProgressToken: \"p\"},\n\t\t{Data: map[string]any{\"d\": true}, ProgressToken: nil},\n\t\t{Data: map[string]any{\"d\": true}, ProgressToken: \"p\"},\n\t} {\n\t\tgot := roundTrip(t, meta)\n\t\tif !cmp.Equal(got, meta) {\n\t\t\tt.Errorf(\"\\ngot  %#v\\nwant %#v\", got, meta)\n\t\t}\n\t}\n\n\t// Check errors.\n\tfor _, tt := range []struct {\n\t\tmeta Meta\n\t\twant string\n\t}{\n\t\t{\n\t\t\tMeta{Data: map[string]any{\"progressToken\": \"p\"}, ProgressToken: 1},\n\t\t\t\"duplicate\",\n\t\t},\n\t\t{\n\t\t\tMeta{ProgressToken: true},\n\t\t\t\"bad type\",\n\t\t},\n\t} {\n\t\t_, err := json.Marshal(tt.meta)\n\t\tif err == nil || !strings.Contains(err.Error(), tt.want) {\n\t\t\tt.Errorf(\"%+v: got %v, want error containing %q\", tt.meta, err, tt.want)\n\t\t}\n\t}\n\n\t// Accept progressToken in map if the field is nil.\n\t// It will unmarshal by populating ProgressToken.\n\tmeta := Meta{Data: map[string]any{\"progressToken\": \"p\"}}\n\tgot := roundTrip(t, meta)\n\twant := Meta{ProgressToken: \"p\"}\n\tif !cmp.Equal(got, want) {\n\t\tt.Errorf(\"got %+v, want %+v\", got, want)\n\t}\n}\n\nfunc roundTrip[T any](t *testing.T, v T) T {\n\tt.Helper()\n\tbytes, err := json.Marshal(v)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar res T\n\tif err := json.Unmarshal(bytes, &res); err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn res\n}\n\n// TODO(jba): this shouldn't be in this file, but tool_test.go doesn't have access to unexported symbols.\nfunc TestNewServerToolValidate(t *testing.T) {\n\t// Check that the tool returned from NewServerTool properly validates its input schema.\n\n\ttype req struct {\n\t\tI int\n\t\tB bool\n\t\tS string `json:\",omitempty\"`\n\t\tP *int   `json:\",omitempty\"`\n\t}\n\n\tdummyHandler := func(context.Context, *ServerSession, *CallToolParamsFor[req]) (*CallToolResultFor[any], error) {\n\t\treturn nil, nil\n\t}\n\n\ttool := NewServerTool(\"test\", \"test\", dummyHandler)\n\t// Need to add the tool to a server to get resolved schemas.\n\t// s := NewServer(\"\", \"\", nil)\n\n\tfor _, tt := range []struct {\n\t\tdesc string\n\t\targs map[string]any\n\t\twant string // error should contain this string; empty for success\n\t}{\n\t\t{\n\t\t\t\"both required\",\n\t\t\tmap[string]any{\"I\": 1, \"B\": true},\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"optional\",\n\t\t\tmap[string]any{\"I\": 1, \"B\": true, \"S\": \"foo\"},\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"wrong type\",\n\t\t\tmap[string]any{\"I\": 1.5, \"B\": true},\n\t\t\t\"cannot unmarshal\",\n\t\t},\n\t\t{\n\t\t\t\"extra property\",\n\t\t\tmap[string]any{\"I\": 1, \"B\": true, \"C\": 2},\n\t\t\t\"unknown field\",\n\t\t},\n\t\t{\n\t\t\t\"value for pointer\",\n\t\t\tmap[string]any{\"I\": 1, \"B\": true, \"P\": 3},\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"null for pointer\",\n\t\t\tmap[string]any{\"I\": 1, \"B\": true, \"P\": nil},\n\t\t\t\"\",\n\t\t},\n\t} {\n\t\tt.Run(tt.desc, func(t *testing.T) {\n\t\t\traw, err := json.Marshal(tt.args)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\t_, err = tool.rawHandler(context.Background(), nil,\n\t\t\t\t&CallToolParamsFor[json.RawMessage]{Arguments: json.RawMessage(raw)})\n\t\t\tif err == nil && tt.want != \"\" {\n\t\t\t\tt.Error(\"got success, wanted failure\")\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tif tt.want == \"\" {\n\t\t\t\t\tt.Fatalf(\"failed with:\\n%s\\nwanted success\", err)\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(err.Error(), tt.want) {\n\t\t\t\t\tt.Fatalf(\"got:\\n%s\\nwanted to contain %q\", err, tt.want)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/sse.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"iter\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"sync\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\n// This file implements support for SSE (HTTP with server-sent events)\n// transport server and client.\n// https://modelcontextprotocol.io/specification/2024-11-05/basic/transports\n//\n// The transport is simple, at least relative to the new streamable transport\n// introduced in the 2025-03-26 version of the spec. In short:\n//\n//  1. Sessions are initiated via a hanging GET request, which streams\n//     server->client messages as SSE 'message' events.\n//  2. The first event in the SSE stream must be an 'endpoint' event that\n//     informs the client of the session endpoint.\n//  3. The client POSTs client->server messages to the session endpoint.\n//\n// Therefore, the each new GET request hands off its responsewriter to an\n// [SSEServerTransport] type that abstracts the transport as follows:\n//  - Write writes a new event to the responseWriter, or fails if the GET has\n//  exited.\n//  - Read reads off a message queue that is pushed to via POST requests.\n//  - Close causes the hanging GET to exit.\n\n// An event is a server-sent event.\ntype event struct {\n\tname string\n\tid   string\n\tdata []byte\n}\n\nfunc (e event) empty() bool {\n\treturn e.name == \"\" && e.id == \"\" && len(e.data) == 0\n}\n\n// writeEvent writes the event to w, and flushes.\nfunc writeEvent(w io.Writer, evt event) (int, error) {\n\tvar b bytes.Buffer\n\tif evt.name != \"\" {\n\t\tfmt.Fprintf(&b, \"event: %s\\n\", evt.name)\n\t}\n\tif evt.id != \"\" {\n\t\tfmt.Fprintf(&b, \"id: %s\\n\", evt.id)\n\t}\n\tfmt.Fprintf(&b, \"data: %s\\n\\n\", string(evt.data))\n\tn, err := w.Write(b.Bytes())\n\tif f, ok := w.(http.Flusher); ok {\n\t\tf.Flush()\n\t}\n\treturn n, err\n}\n\n// SSEHandler is an http.Handler that serves SSE-based MCP sessions as defined by\n// the [2024-11-05 version] of the MCP spec.\n//\n// [2024-11-05 version]: https://modelcontextprotocol.io/specification/2024-11-05/basic/transports\ntype SSEHandler struct {\n\tgetServer    func(request *http.Request) *Server\n\tonConnection func(*ServerSession) // for testing; must not block\n\n\tmu       sync.Mutex\n\tsessions map[string]*SSEServerTransport\n}\n\n// NewSSEHandler returns a new [SSEHandler] that creates and manages MCP\n// sessions created via incoming HTTP requests.\n//\n// Sessions are created when the client issues a GET request to the server,\n// which must accept text/event-stream responses (server-sent events).\n// For each such request, a new [SSEServerTransport] is created with a distinct\n// messages endpoint, and connected to the server returned by getServer. It is\n// up to the user whether getServer returns a distinct [Server] for each new\n// request, or reuses an existing server.\n//\n// The SSEHandler also handles requests to the message endpoints, by\n// delegating them to the relevant server transport.\n//\n// TODO(rfindley): add options.\nfunc NewSSEHandler(getServer func(request *http.Request) *Server) *SSEHandler {\n\treturn &SSEHandler{\n\t\tgetServer: getServer,\n\t\tsessions:  make(map[string]*SSEServerTransport),\n\t}\n}\n\n// A SSEServerTransport is a logical SSE session created through a hanging GET\n// request.\n//\n// When connected, it returns the following [Connection] implementation:\n//   - Writes are SSE 'message' events to the GET response.\n//   - Reads are received from POSTs to the session endpoint, via\n//     [SSEServerTransport.ServeHTTP].\n//   - Close terminates the hanging GET.\ntype SSEServerTransport struct {\n\tendpoint string\n\tincoming chan JSONRPCMessage // queue of incoming messages; never closed\n\n\t// We must guard both pushes to the incoming queue and writes to the response\n\t// writer, because incoming POST requests are arbitrarily concurrent and we\n\t// need to ensure we don't write push to the queue, or write to the\n\t// ResponseWriter, after the session GET request exits.\n\tmu     sync.Mutex\n\tw      http.ResponseWriter // the hanging response body\n\tclosed bool                // set when the stream is closed\n\tdone   chan struct{}       // closed when the connection is closed\n}\n\n// NewSSEServerTransport creates a new SSE transport for the given messages\n// endpoint, and hanging GET response.\n//\n// Use [SSEServerTransport.Connect] to initiate the flow of messages.\n//\n// The transport is itself an [http.Handler]. It is the caller's responsibility\n// to ensure that the resulting transport serves HTTP requests on the given\n// session endpoint.\n//\n// Most callers should instead use an [SSEHandler], which transparently handles\n// the delegation to SSEServerTransports.\nfunc NewSSEServerTransport(endpoint string, w http.ResponseWriter) *SSEServerTransport {\n\treturn &SSEServerTransport{\n\t\tendpoint: endpoint,\n\t\tw:        w,\n\t\tincoming: make(chan JSONRPCMessage, 100),\n\t\tdone:     make(chan struct{}),\n\t}\n}\n\n// ServeHTTP handles POST requests to the transport endpoint.\nfunc (t *SSEServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\t// Read and parse the message.\n\tdata, err := io.ReadAll(req.Body)\n\tif err != nil {\n\t\thttp.Error(w, \"failed to read body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\t// Optionally, we could just push the data onto a channel, and let the\n\t// message fail to parse when it is read. This failure seems a bit more\n\t// useful\n\tmsg, err := jsonrpc2.DecodeMessage(data)\n\tif err != nil {\n\t\thttp.Error(w, \"failed to parse body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tselect {\n\tcase t.incoming <- msg:\n\t\tw.WriteHeader(http.StatusAccepted)\n\tcase <-t.done:\n\t\thttp.Error(w, \"session closed\", http.StatusBadRequest)\n\t}\n}\n\n// Connect sends the 'endpoint' event to the client.\n// See [SSEServerTransport] for more details on the [Connection] implementation.\nfunc (t *SSEServerTransport) Connect(context.Context) (Connection, error) {\n\tt.mu.Lock()\n\t_, err := writeEvent(t.w, event{\n\t\tname: \"endpoint\",\n\t\tdata: []byte(t.endpoint),\n\t})\n\tt.mu.Unlock()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn sseServerConn{t}, nil\n}\n\nfunc (h *SSEHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\tsessionID := req.URL.Query().Get(\"sessionid\")\n\n\t// TODO: consider checking Content-Type here. For now, we are lax.\n\n\t// For POST requests, the message body is a message to send to a session.\n\tif req.Method == http.MethodPost {\n\t\t// Look up the session.\n\t\tif sessionID == \"\" {\n\t\t\thttp.Error(w, \"sessionid must be provided\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\th.mu.Lock()\n\t\tsession := h.sessions[sessionID]\n\t\th.mu.Unlock()\n\t\tif session == nil {\n\t\t\thttp.Error(w, \"session not found\", http.StatusNotFound)\n\t\t\treturn\n\t\t}\n\n\t\tsession.ServeHTTP(w, req)\n\t\treturn\n\t}\n\n\tif req.Method != http.MethodGet {\n\t\thttp.Error(w, \"invalid method\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}\n\n\t// GET requests create a new session, and serve messages over SSE.\n\n\t// TODO: it's not entirely documented whether we should check Accept here.\n\t// Let's again be lax and assume the client will accept SSE.\n\n\tw.Header().Set(\"Content-Type\", \"text/event-stream\")\n\tw.Header().Set(\"Cache-Control\", \"no-cache\")\n\tw.Header().Set(\"Connection\", \"keep-alive\")\n\n\tsessionID = rand.Text()\n\tendpoint, err := req.URL.Parse(\"?sessionid=\" + sessionID)\n\tif err != nil {\n\t\thttp.Error(w, \"internal error: failed to create endpoint\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\ttransport := NewSSEServerTransport(endpoint.RequestURI(), w)\n\n\t// The session is terminated when the request exits.\n\th.mu.Lock()\n\th.sessions[sessionID] = transport\n\th.mu.Unlock()\n\tdefer func() {\n\t\th.mu.Lock()\n\t\tdelete(h.sessions, sessionID)\n\t\th.mu.Unlock()\n\t}()\n\n\t// TODO(hxjiang): getServer returns nil will panic.\n\tserver := h.getServer(req)\n\tss, err := server.Connect(req.Context(), transport)\n\tif err != nil {\n\t\thttp.Error(w, \"connection failed\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif h.onConnection != nil {\n\t\th.onConnection(ss)\n\t}\n\tdefer ss.Close() // close the transport when the GET exits\n\n\tselect {\n\tcase <-req.Context().Done():\n\tcase <-transport.done:\n\t}\n}\n\n// sseServerConn implements the [Connection] interface for a single [SSEServerTransport].\n// It hides the Connection interface from the SSEServerTransport API.\ntype sseServerConn struct {\n\tt *SSEServerTransport\n}\n\n// Read implements jsonrpc2.Reader.\nfunc (s sseServerConn) Read(ctx context.Context) (JSONRPCMessage, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tcase msg := <-s.t.incoming:\n\t\treturn msg, nil\n\tcase <-s.t.done:\n\t\treturn nil, io.EOF\n\t}\n}\n\n// Write implements jsonrpc2.Writer.\nfunc (s sseServerConn) Write(ctx context.Context, msg JSONRPCMessage) error {\n\tif ctx.Err() != nil {\n\t\treturn ctx.Err()\n\t}\n\n\tdata, err := jsonrpc2.EncodeMessage(msg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts.t.mu.Lock()\n\tdefer s.t.mu.Unlock()\n\n\t// Note that it is invalid to write to a ResponseWriter after ServeHTTP has\n\t// exited, and so we must lock around this write and check isDone, which is\n\t// set before the hanging GET exits.\n\tif s.t.closed {\n\t\treturn io.EOF\n\t}\n\n\t_, err = writeEvent(s.t.w, event{name: \"message\", data: data})\n\treturn err\n}\n\n// Close implements io.Closer, and closes the session.\n//\n// It must be safe to call Close more than once, as the close may\n// asynchronously be initiated by either the server closing its connection, or\n// by the hanging GET exiting.\nfunc (s sseServerConn) Close() error {\n\ts.t.mu.Lock()\n\tdefer s.t.mu.Unlock()\n\tif !s.t.closed {\n\t\ts.t.closed = true\n\t\tclose(s.t.done)\n\t}\n\treturn nil\n}\n\n// An SSEClientTransport is a [Transport] that can communicate with an MCP\n// endpoint serving the SSE transport defined by the 2024-11-05 version of the\n// spec.\n//\n// https://modelcontextprotocol.io/specification/2024-11-05/basic/transports\ntype SSEClientTransport struct {\n\tsseEndpoint *url.URL\n\topts        SSEClientTransportOptions\n}\n\n// SSEClientTransportOptions provides options for the [NewSSEClientTransport]\n// constructor.\ntype SSEClientTransportOptions struct {\n\t// HTTPClient is the client to use for making HTTP requests. If nil,\n\t// http.DefaultClient is used.\n\tHTTPClient *http.Client\n}\n\n// NewSSEClientTransport returns a new client transport that connects to the\n// SSE server at the provided URL.\n//\n// NewSSEClientTransport panics if the given URL is invalid.\nfunc NewSSEClientTransport(baseURL string, opts *SSEClientTransportOptions) *SSEClientTransport {\n\turl, err := url.Parse(baseURL)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"invalid base url: %v\", err))\n\t}\n\tt := &SSEClientTransport{\n\t\tsseEndpoint: url,\n\t}\n\tif opts != nil {\n\t\tt.opts = *opts\n\t}\n\treturn t\n}\n\n// Connect connects through the client endpoint.\nfunc (c *SSEClientTransport) Connect(ctx context.Context) (Connection, error) {\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", c.sseEndpoint.String(), nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thttpClient := c.opts.HTTPClient\n\tif httpClient == nil {\n\t\thttpClient = http.DefaultClient\n\t}\n\treq.Header.Set(\"Accept\", \"text/event-stream\")\n\tresp, err := httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tmsgEndpoint, err := func() (*url.URL, error) {\n\t\tvar evt event\n\t\tfor evt, err = range scanEvents(resp.Body) {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif evt.name != \"endpoint\" {\n\t\t\treturn nil, fmt.Errorf(\"first event is %q, want %q\", evt.name, \"endpoint\")\n\t\t}\n\t\traw := string(evt.data)\n\t\treturn c.sseEndpoint.Parse(raw)\n\t}()\n\tif err != nil {\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"missing endpoint: %v\", err)\n\t}\n\n\t// From here on, the stream takes ownership of resp.Body.\n\ts := &sseClientConn{\n\t\tsseEndpoint: c.sseEndpoint,\n\t\tmsgEndpoint: msgEndpoint,\n\t\tincoming:    make(chan []byte, 100),\n\t\tbody:        resp.Body,\n\t\tdone:        make(chan struct{}),\n\t}\n\n\tgo func() {\n\t\tdefer s.Close() // close the transport when the GET exits\n\n\t\tfor evt, err := range scanEvents(resp.Body) {\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase s.incoming <- evt.data:\n\t\t\tcase <-s.done:\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn s, nil\n}\n\n// scanEvents iterates SSE events in the given scanner. The iterated error is\n// terminal: if encountered, the stream is corrupt or broken and should no\n// longer be used.\n//\n// TODO(rfindley): consider a different API here that makes failure modes more\n// apparent.\nfunc scanEvents(r io.Reader) iter.Seq2[event, error] {\n\tscanner := bufio.NewScanner(r)\n\tconst maxTokenSize = 1 * 1024 * 1024 // 1 MiB max line size\n\tscanner.Buffer(nil, maxTokenSize)\n\n\t// TODO: investigate proper behavior when events are out of order, or have\n\t// non-standard names.\n\tvar (\n\t\teventKey = []byte(\"event\")\n\t\tidKey    = []byte(\"id\")\n\t\tdataKey  = []byte(\"data\")\n\t)\n\n\treturn func(yield func(event, error) bool) {\n\t\t// iterate event from the wire.\n\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#examples\n\t\t//\n\t\t//  - `key: value` line records.\n\t\t//  - Consecutive `data: ...` fields are joined with newlines.\n\t\t//  - Unrecognized fields are ignored. Since we only care about 'event', 'id', and\n\t\t//   'data', these are the only three we consider.\n\t\t//  - Lines starting with \":\" are ignored.\n\t\t//  - Records are terminated with two consecutive newlines.\n\t\tvar (\n\t\t\tevt     event\n\t\t\tdataBuf *bytes.Buffer // if non-nil, preceding field was also data\n\t\t)\n\t\tflushData := func() {\n\t\t\tif dataBuf != nil {\n\t\t\t\tevt.data = dataBuf.Bytes()\n\t\t\t\tdataBuf = nil\n\t\t\t}\n\t\t}\n\t\tfor scanner.Scan() {\n\t\t\tline := scanner.Bytes()\n\t\t\tif len(line) == 0 {\n\t\t\t\tflushData()\n\t\t\t\t// \\n\\n is the record delimiter\n\t\t\t\tif !evt.empty() && !yield(evt, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tevt = event{}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbefore, after, found := bytes.Cut(line, []byte{':'})\n\t\t\tif !found {\n\t\t\t\tyield(event{}, fmt.Errorf(\"malformed line in SSE stream: %q\", string(line)))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !bytes.Equal(before, dataKey) {\n\t\t\t\tflushData()\n\t\t\t}\n\t\t\tswitch {\n\t\t\tcase bytes.Equal(before, eventKey):\n\t\t\t\tevt.name = strings.TrimSpace(string(after))\n\t\t\tcase bytes.Equal(before, idKey):\n\t\t\t\tevt.id = strings.TrimSpace(string(after))\n\t\t\tcase bytes.Equal(before, dataKey):\n\t\t\t\tdata := bytes.TrimSpace(after)\n\t\t\t\tif dataBuf != nil {\n\t\t\t\t\tdataBuf.WriteByte('\\n')\n\t\t\t\t\tdataBuf.Write(data)\n\t\t\t\t} else {\n\t\t\t\t\tdataBuf = new(bytes.Buffer)\n\t\t\t\t\tdataBuf.Write(data)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := scanner.Err(); err != nil {\n\t\t\tif errors.Is(err, bufio.ErrTooLong) {\n\t\t\t\terr = fmt.Errorf(\"event exceeded max line length of %d\", maxTokenSize)\n\t\t\t}\n\t\t\tif !yield(event{}, err) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tflushData()\n\t\tif !evt.empty() {\n\t\t\tyield(evt, nil)\n\t\t}\n\t}\n}\n\n// An sseClientConn is a logical jsonrpc2 connection that implements the client\n// half of the SSE protocol:\n//   - Writes are POSTS to the session endpoint.\n//   - Reads are SSE 'message' events, and pushes them onto a buffered channel.\n//   - Close terminates the GET request.\ntype sseClientConn struct {\n\tsseEndpoint *url.URL    // SSE endpoint for the GET\n\tmsgEndpoint *url.URL    // session endpoint for POSTs\n\tincoming    chan []byte // queue of incoming messages\n\n\tmu     sync.Mutex\n\tbody   io.ReadCloser // body of the hanging GET\n\tclosed bool          // set when the stream is closed\n\tdone   chan struct{} // closed when the stream is closed\n}\n\nfunc (c *sseClientConn) isDone() bool {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\treturn c.closed\n}\n\nfunc (c *sseClientConn) Read(ctx context.Context) (JSONRPCMessage, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\n\tcase <-c.done:\n\t\treturn nil, io.EOF\n\n\tcase data := <-c.incoming:\n\t\t// TODO(rfindley): do we really need to check this? We receive from c.done above.\n\t\tif c.isDone() {\n\t\t\treturn nil, io.EOF\n\t\t}\n\t\tmsg, err := jsonrpc2.DecodeMessage(data)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn msg, nil\n\t}\n}\n\nfunc (c *sseClientConn) Write(ctx context.Context, msg JSONRPCMessage) error {\n\tdata, err := jsonrpc2.EncodeMessage(msg)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif c.isDone() {\n\t\treturn io.EOF\n\t}\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", c.msgEndpoint.String(), bytes.NewReader(data))\n\tif err != nil {\n\t\treturn err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\treturn fmt.Errorf(\"failed to write: %s\", resp.Status)\n\t}\n\treturn nil\n}\n\nfunc (c *sseClientConn) Close() error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tif !c.closed {\n\t\tc.closed = true\n\t\t_ = c.body.Close()\n\t\tclose(c.done)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/mcp/sse_example_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\n\t\"golang.org/x/tools/internal/mcp\"\n)\n\ntype AddParams struct {\n\tX, Y int\n}\n\nfunc Add(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[AddParams]) (*mcp.CallToolResultFor[any], error) {\n\treturn &mcp.CallToolResultFor[any]{\n\t\tContent: []*mcp.Content{mcp.NewTextContent(fmt.Sprintf(\"%d\", params.Arguments.X+params.Arguments.Y))},\n\t}, nil\n}\n\nfunc ExampleSSEHandler() {\n\tserver := mcp.NewServer(\"adder\", \"v0.0.1\", nil)\n\tserver.AddTools(mcp.NewServerTool(\"add\", \"add two numbers\", Add))\n\n\thandler := mcp.NewSSEHandler(func(*http.Request) *mcp.Server { return server })\n\thttpServer := httptest.NewServer(handler)\n\tdefer httpServer.Close()\n\n\tctx := context.Background()\n\ttransport := mcp.NewSSEClientTransport(httpServer.URL, nil)\n\tclient := mcp.NewClient(\"test\", \"v1.0.0\", nil)\n\tcs, err := client.Connect(ctx, transport)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer cs.Close()\n\n\tres, err := cs.CallTool(ctx, &mcp.CallToolParams{\n\t\tName:      \"add\",\n\t\tArguments: map[string]any{\"x\": 1, \"y\": 2},\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(res.Content[0].Text)\n\n\t// Output: 3\n}\n"
  },
  {
    "path": "internal/mcp/sse_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestSSEServer(t *testing.T) {\n\tfor _, closeServerFirst := range []bool{false, true} {\n\t\tt.Run(fmt.Sprintf(\"closeServerFirst=%t\", closeServerFirst), func(t *testing.T) {\n\t\t\tctx := context.Background()\n\t\t\tserver := NewServer(\"testServer\", \"v1.0.0\", nil)\n\t\t\tserver.AddTools(NewServerTool(\"greet\", \"say hi\", sayHi))\n\n\t\t\tsseHandler := NewSSEHandler(func(*http.Request) *Server { return server })\n\n\t\t\tconns := make(chan *ServerSession, 1)\n\t\t\tsseHandler.onConnection = func(cc *ServerSession) {\n\t\t\t\tselect {\n\t\t\t\tcase conns <- cc:\n\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t}\n\t\t\thttpServer := httptest.NewServer(sseHandler)\n\t\t\tdefer httpServer.Close()\n\n\t\t\tclientTransport := NewSSEClientTransport(httpServer.URL, nil)\n\n\t\t\tc := NewClient(\"testClient\", \"v1.0.0\", nil)\n\t\t\tcs, err := c.Connect(ctx, clientTransport)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif err := cs.Ping(ctx, nil); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tss := <-conns\n\t\t\tgotHi, err := cs.CallTool(ctx, &CallToolParams{\n\t\t\t\tName:      \"greet\",\n\t\t\t\tArguments: map[string]any{\"Name\": \"user\"},\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\twantHi := &CallToolResult{\n\t\t\t\tContent: []*Content{{Type: \"text\", Text: \"hi user\"}},\n\t\t\t}\n\t\t\tif diff := cmp.Diff(wantHi, gotHi); diff != \"\" {\n\t\t\t\tt.Errorf(\"tools/call 'greet' mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\n\t\t\t// Test that closing either end of the connection terminates the other\n\t\t\t// end.\n\t\t\tif closeServerFirst {\n\t\t\t\tcs.Close()\n\t\t\t\tss.Wait()\n\t\t\t} else {\n\t\t\t\tss.Close()\n\t\t\t\tcs.Wait()\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestScanEvents(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tinput   string\n\t\twant    []event\n\t\twantErr string\n\t}{\n\t\t{\n\t\t\tname:  \"simple event\",\n\t\t\tinput: \"event: message\\nid: 1\\ndata: hello\\n\\n\",\n\t\t\twant: []event{\n\t\t\t\t{name: \"message\", id: \"1\", data: []byte(\"hello\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"multiple data lines\",\n\t\t\tinput: \"data: line 1\\ndata: line 2\\n\\n\",\n\t\t\twant: []event{\n\t\t\t\t{data: []byte(\"line 1\\nline 2\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"multiple events\",\n\t\t\tinput: \"data: first\\n\\nevent: second\\ndata: second\\n\\n\",\n\t\t\twant: []event{\n\t\t\t\t{data: []byte(\"first\")},\n\t\t\t\t{name: \"second\", data: []byte(\"second\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:  \"no trailing newline\",\n\t\t\tinput: \"data: hello\",\n\t\t\twant: []event{\n\t\t\t\t{data: []byte(\"hello\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"malformed line\",\n\t\t\tinput:   \"invalid line\\n\\n\",\n\t\t\twantErr: \"malformed line\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tr := strings.NewReader(tt.input)\n\t\t\tvar got []event\n\t\t\tvar err error\n\t\t\tfor e, err2 := range scanEvents(r) {\n\t\t\t\tif err2 != nil {\n\t\t\t\t\terr = err2\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tgot = append(got, e)\n\t\t\t}\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatalf(\"scanEvents() got nil error, want error containing %q\", tt.wantErr)\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(err.Error(), tt.wantErr) {\n\t\t\t\t\tt.Fatalf(\"scanEvents() error = %q, want containing %q\", err, tt.wantErr)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"scanEvents() returned unexpected error: %v\", err)\n\t\t\t}\n\n\t\t\tif len(got) != len(tt.want) {\n\t\t\t\tt.Fatalf(\"scanEvents() got %d events, want %d\", len(got), len(tt.want))\n\t\t\t}\n\n\t\t\tfor i := range got {\n\t\t\t\tif g, w := got[i].name, tt.want[i].name; g != w {\n\t\t\t\t\tt.Errorf(\"event %d: name = %q, want %q\", i, g, w)\n\t\t\t\t}\n\t\t\t\tif g, w := got[i].id, tt.want[i].id; g != w {\n\t\t\t\t\tt.Errorf(\"event %d: id = %q, want %q\", i, g, w)\n\t\t\t\t}\n\t\t\t\tif g, w := string(got[i].data), string(tt.want[i].data); g != w {\n\t\t\t\t\tt.Errorf(\"event %d: data = %q, want %q\", i, g, w)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/streamable.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/rand\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\n// A StreamableHTTPHandler is an http.Handler that serves streamable MCP\n// sessions, as defined by the [MCP spec].\n//\n// [MCP spec]: https://modelcontextprotocol.io/2025/03/26/streamable-http-transport.html\ntype StreamableHTTPHandler struct {\n\tgetServer func(*http.Request) *Server\n\n\tsessionsMu sync.Mutex\n\tsessions   map[string]*StreamableServerTransport // keyed by IDs (from Mcp-Session-Id header)\n}\n\n// StreamableHTTPOptions is a placeholder options struct for future\n// configuration of the StreamableHTTP handler.\ntype StreamableHTTPOptions struct {\n\t// TODO(rfindley): support configurable session ID generation and event\n\t// store, session retention, and event retention.\n}\n\n// NewStreamableHTTPHandler returns a new [StreamableHTTPHandler].\n//\n// The getServer function is used to create or look up servers for new\n// sessions. It is OK for getServer to return the same server multiple times.\nfunc NewStreamableHTTPHandler(getServer func(*http.Request) *Server, opts *StreamableHTTPOptions) *StreamableHTTPHandler {\n\treturn &StreamableHTTPHandler{\n\t\tgetServer: getServer,\n\t\tsessions:  make(map[string]*StreamableServerTransport),\n\t}\n}\n\n// closeAll closes all ongoing sessions.\n//\n// TODO(rfindley): investigate the best API for callers to configure their\n// session lifecycle.\n//\n// Should we allow passing in a session store? That would allow the handler to\n// be stateless.\nfunc (h *StreamableHTTPHandler) closeAll() {\n\th.sessionsMu.Lock()\n\tdefer h.sessionsMu.Unlock()\n\tfor _, s := range h.sessions {\n\t\ts.Close()\n\t}\n\th.sessions = nil\n}\n\nfunc (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\t// Allow multiple 'Accept' headers.\n\t// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept#syntax\n\taccept := strings.Split(strings.Join(req.Header.Values(\"Accept\"), \",\"), \",\")\n\tvar jsonOK, streamOK bool\n\tfor _, c := range accept {\n\t\tswitch strings.TrimSpace(c) {\n\t\tcase \"application/json\":\n\t\t\tjsonOK = true\n\t\tcase \"text/event-stream\":\n\t\t\tstreamOK = true\n\t\t}\n\t}\n\n\tif req.Method == http.MethodGet {\n\t\tif !streamOK {\n\t\t\thttp.Error(w, \"Accept must contain 'text/event-stream' for GET requests\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t} else if !jsonOK || !streamOK {\n\t\thttp.Error(w, \"Accept must contain both 'application/json' and 'text/event-stream'\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tvar session *StreamableServerTransport\n\tif id := req.Header.Get(\"Mcp-Session-Id\"); id != \"\" {\n\t\th.sessionsMu.Lock()\n\t\tsession, _ = h.sessions[id]\n\t\th.sessionsMu.Unlock()\n\t\tif session == nil {\n\t\t\thttp.Error(w, \"session not found\", http.StatusNotFound)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// TODO(rfindley): simplify the locking so that each request has only one\n\t// critical section.\n\tif req.Method == http.MethodDelete {\n\t\tif session == nil {\n\t\t\t// => Mcp-Session-Id was not set; else we'd have returned NotFound above.\n\t\t\thttp.Error(w, \"DELETE requires an Mcp-Session-Id header\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\th.sessionsMu.Lock()\n\t\tdelete(h.sessions, session.id)\n\t\th.sessionsMu.Unlock()\n\t\tsession.Close()\n\t\tw.WriteHeader(http.StatusNoContent)\n\t\treturn\n\t}\n\n\tswitch req.Method {\n\tcase http.MethodPost, http.MethodGet:\n\tdefault:\n\t\tw.Header().Set(\"Allow\", \"GET, POST\")\n\t\thttp.Error(w, \"unsupported method\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}\n\n\tif session == nil {\n\t\ts := NewStreamableServerTransport(rand.Text())\n\t\tserver := h.getServer(req)\n\t\t// Pass req.Context() here, to allow middleware to add context values.\n\t\t// The context is detached in the jsonrpc2 library when handling the\n\t\t// long-running stream.\n\t\tif _, err := server.Connect(req.Context(), s); err != nil {\n\t\t\thttp.Error(w, \"failed connection\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\th.sessionsMu.Lock()\n\t\th.sessions[s.id] = s\n\t\th.sessionsMu.Unlock()\n\t\tsession = s\n\t}\n\n\tsession.ServeHTTP(w, req)\n}\n\n// NewStreamableServerTransport returns a new [StreamableServerTransport] with\n// the given session ID.\n//\n// A StreamableServerTransport implements the server-side of the streamable\n// transport.\n//\n// TODO(rfindley): consider adding options here, to configure event storage\n// policy.\nfunc NewStreamableServerTransport(sessionID string) *StreamableServerTransport {\n\treturn &StreamableServerTransport{\n\t\tid:               sessionID,\n\t\tincoming:         make(chan JSONRPCMessage, 10),\n\t\tdone:             make(chan struct{}),\n\t\toutgoingMessages: make(map[streamID][]*streamableMsg),\n\t\tsignals:          make(map[streamID]chan struct{}),\n\t\trequestStreams:   make(map[JSONRPCID]streamID),\n\t\tstreamRequests:   make(map[streamID]map[JSONRPCID]struct{}),\n\t}\n}\n\n// A StreamableServerTransport implements the [Transport] interface for a\n// single session.\ntype StreamableServerTransport struct {\n\tnextStreamID atomic.Int64 // incrementing next stream ID\n\n\tid       string\n\tincoming chan JSONRPCMessage // messages from the client to the server\n\n\tmu sync.Mutex\n\n\t// Sessions are closed exactly once.\n\tisDone bool\n\tdone   chan struct{}\n\n\t// Sessions can have multiple logical connections, corresponding to HTTP\n\t// requests. Additionally, logical sessions may be resumed by subsequent HTTP\n\t// requests, when the session is terminated unexpectedly.\n\t//\n\t// Therefore, we use a logical connection ID to key the connection state, and\n\t// perform the accounting described below when incoming HTTP requests are\n\t// handled.\n\t//\n\t// The accounting is complicated. It is tempting to merge some of the maps\n\t// below, but they each have different lifecycles, as indicated by Lifecycle:\n\t// comments.\n\t//\n\t// TODO(rfindley): simplify.\n\n\t// outgoingMessages is the collection of outgoingMessages messages, keyed by the logical\n\t// stream ID where they should be delivered.\n\t//\n\t// streamID 0 is used for messages that don't correlate with an incoming\n\t// request.\n\t//\n\t// Lifecycle: outgoingMessages persists for the duration of the session.\n\t//\n\t// TODO(rfindley): garbage collect this data. For now, we save all outgoingMessages\n\t// messages for the lifespan of the transport.\n\toutgoingMessages map[streamID][]*streamableMsg\n\n\t// signals maps a logical stream ID to a 1-buffered channel, owned by an\n\t// incoming HTTP request, that signals that there are messages available to\n\t// write into the HTTP response. Signals guarantees that at most one HTTP\n\t// response can receive messages for a logical stream. After claiming\n\t// the stream, incoming requests should read from outgoing, to ensure\n\t// that no new messages are missed.\n\t//\n\t// Lifecycle: signals persists for the duration of an HTTP POST or GET\n\t// request for the given streamID.\n\tsignals map[streamID]chan struct{}\n\n\t// requestStreams maps incoming requests to their logical stream ID.\n\t//\n\t// Lifecycle: requestStreams persists for the duration of the session.\n\t//\n\t// TODO(rfindley): clean up once requests are handled.\n\trequestStreams map[JSONRPCID]streamID\n\n\t// outstandingRequests tracks the set of unanswered incoming RPCs for each logical\n\t// stream.\n\t//\n\t// When the server has responded to each request, the stream should be\n\t// closed.\n\t//\n\t// Lifecycle: outstandingRequests values persist as until the requests have been\n\t// replied to by the server. Notably, NOT until they are sent to an HTTP\n\t// response, as delivery is not guaranteed.\n\tstreamRequests map[streamID]map[JSONRPCID]struct{}\n}\n\ntype streamID int64\n\n// a streamableMsg is an SSE event with an index into its logical stream.\ntype streamableMsg struct {\n\tidx   int\n\tevent event\n}\n\n// Connect implements the [Transport] interface.\n//\n// TODO(rfindley): Connect should return a new object.\nfunc (s *StreamableServerTransport) Connect(context.Context) (Connection, error) {\n\treturn s, nil\n}\n\n// We track the incoming request ID inside the handler context using\n// idContextValue, so that notifications and server->client calls that occur in\n// the course of handling incoming requests are correlated with the incoming\n// request that caused them, and can be dispatched as server-sent events to the\n// correct HTTP request.\n//\n// Currently, this is implemented in [ServerSession.handle]. This is not ideal,\n// because it means that a user of the MCP package couldn't implement the\n// streamable transport, as they'd lack this priviledged access.\n//\n// If we ever wanted to expose this mechanism, we have a few options:\n//  1. Make ServerSession an interface, and provide an implementation of\n//     ServerSession to handlers that closes over the incoming request ID.\n//  2. Expose a 'HandlerTransport' interface that allows transports to provide\n//     a handler middleware, so that we don't hard-code this behavior in\n//     ServerSession.handle.\n//  3. Add a `func ForRequest(context.Context) JSONRPCID` accessor that lets\n//     any transport access the incoming request ID.\n//\n// For now, by giving only the StreamableServerTransport access to the request\n// ID, we avoid having to make this API decision.\ntype idContextKey struct{}\n\n// ServeHTTP handles a single HTTP request for the session.\nfunc (t *StreamableServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\tswitch req.Method {\n\tcase http.MethodGet:\n\t\tt.serveGET(w, req)\n\tcase http.MethodPost:\n\t\tt.servePOST(w, req)\n\tdefault:\n\t\t// Should not be reached, as this is checked in StreamableHTTPHandler.ServeHTTP.\n\t\tw.Header().Set(\"Allow\", \"GET, POST\")\n\t\thttp.Error(w, \"unsupported method\", http.StatusMethodNotAllowed)\n\t}\n}\n\nfunc (t *StreamableServerTransport) serveGET(w http.ResponseWriter, req *http.Request) {\n\t// connID 0 corresponds to the default GET request.\n\tid, nextIdx := streamID(0), 0\n\tif len(req.Header.Values(\"Last-Event-ID\")) > 0 {\n\t\teid := req.Header.Get(\"Last-Event-ID\")\n\t\tvar ok bool\n\t\tid, nextIdx, ok = parseEventID(eid)\n\t\tif !ok {\n\t\t\thttp.Error(w, fmt.Sprintf(\"malformed Last-Event-ID %q\", eid), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tnextIdx++\n\t}\n\n\tt.mu.Lock()\n\tif _, ok := t.signals[id]; ok {\n\t\thttp.Error(w, \"stream ID conflicts with ongoing stream\", http.StatusBadRequest)\n\t\tt.mu.Unlock()\n\t\treturn\n\t}\n\tsignal := make(chan struct{}, 1)\n\tt.signals[id] = signal\n\tt.mu.Unlock()\n\n\tt.streamResponse(w, req, id, nextIdx, signal)\n}\n\nfunc (t *StreamableServerTransport) servePOST(w http.ResponseWriter, req *http.Request) {\n\tif len(req.Header.Values(\"Last-Event-ID\")) > 0 {\n\t\thttp.Error(w, \"can't send Last-Event-ID for POST request\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Read incoming messages.\n\tbody, err := io.ReadAll(req.Body)\n\tif err != nil {\n\t\thttp.Error(w, \"failed to read body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tif len(body) == 0 {\n\t\thttp.Error(w, \"POST requires a non-empty body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tincoming, _, err := readBatch(body)\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"malformed payload: %v\", err), http.StatusBadRequest)\n\t\treturn\n\t}\n\tvar requests = make(map[JSONRPCID]struct{})\n\tfor _, msg := range incoming {\n\t\tif req, ok := msg.(*JSONRPCRequest); ok && req.ID.IsValid() {\n\t\t\trequests[req.ID] = struct{}{}\n\t\t}\n\t}\n\n\t// Update accounting for this request.\n\tid := streamID(t.nextStreamID.Add(1))\n\tsignal := make(chan struct{}, 1)\n\tt.mu.Lock()\n\tif len(requests) > 0 {\n\t\tt.streamRequests[id] = make(map[JSONRPCID]struct{})\n\t}\n\tfor reqID := range requests {\n\t\tt.requestStreams[reqID] = id\n\t\tt.streamRequests[id][reqID] = struct{}{}\n\t}\n\tt.signals[id] = signal\n\tt.mu.Unlock()\n\n\t// Publish incoming messages.\n\tfor _, msg := range incoming {\n\t\tt.incoming <- msg\n\t}\n\n\t// TODO(rfindley): consider optimizing for a single incoming request, by\n\t// responding with application/json when there is only a single message in\n\t// the response.\n\tt.streamResponse(w, req, id, 0, signal)\n}\n\nfunc (t *StreamableServerTransport) streamResponse(w http.ResponseWriter, req *http.Request, id streamID, nextIndex int, signal chan struct{}) {\n\tdefer func() {\n\t\tt.mu.Lock()\n\t\tdelete(t.signals, id)\n\t\tt.mu.Unlock()\n\t}()\n\n\t// Stream resumption: adjust outgoing index based on what the user says\n\t// they've received.\n\tif nextIndex > 0 {\n\t\tt.mu.Lock()\n\t\t// Clamp nextIndex to outgoing messages.\n\t\toutgoing := t.outgoingMessages[id]\n\t\tif nextIndex > len(outgoing) {\n\t\t\tnextIndex = len(outgoing)\n\t\t}\n\t\tt.mu.Unlock()\n\t}\n\n\tw.Header().Set(\"Mcp-Session-Id\", t.id)\n\tw.Header().Set(\"Content-Type\", \"text/event-stream\") // Accept checked in [StreamableHTTPHandler]\n\tw.Header().Set(\"Cache-Control\", \"no-cache, no-transform\")\n\tw.Header().Set(\"Connection\", \"keep-alive\")\n\n\twrites := 0\nstream:\n\tfor {\n\t\t// Send outgoing messages\n\t\tt.mu.Lock()\n\t\toutgoing := t.outgoingMessages[id][nextIndex:]\n\t\tt.mu.Unlock()\n\n\t\tfor _, msg := range outgoing {\n\t\t\tif _, err := writeEvent(w, msg.event); err != nil {\n\t\t\t\t// Connection closed or broken.\n\t\t\t\treturn\n\t\t\t}\n\t\t\twrites++\n\t\t\tnextIndex++\n\t\t}\n\n\t\tt.mu.Lock()\n\t\tnOutstanding := len(t.streamRequests[id])\n\t\tnOutgoing := len(t.outgoingMessages[id])\n\t\tt.mu.Unlock()\n\t\t// If all requests have been handled and replied to, we can terminate this\n\t\t// connection. However, in the case of a sequencing violation from the server\n\t\t// (a send on the request context after the request has been handled), we\n\t\t// loop until we've written all messages.\n\t\t//\n\t\t// TODO(rfindley): should we instead refuse to send messages after the last\n\t\t// response? Decide, write a test, and change the behavior.\n\t\tif nextIndex < nOutgoing {\n\t\t\tcontinue // more to send\n\t\t}\n\t\tif req.Method == http.MethodPost && nOutstanding == 0 {\n\t\t\tif writes == 0 {\n\t\t\t\t// Spec: If the server accepts the input, the server MUST return HTTP\n\t\t\t\t// status code 202 Accepted with no body.\n\t\t\t\tw.WriteHeader(http.StatusAccepted)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tselect {\n\t\tcase <-signal:\n\t\tcase <-t.done:\n\t\t\tif writes == 0 {\n\t\t\t\thttp.Error(w, \"session terminated\", http.StatusGone)\n\t\t\t}\n\t\t\tbreak stream\n\t\tcase <-req.Context().Done():\n\t\t\tif writes == 0 {\n\t\t\t\tw.WriteHeader(http.StatusNoContent)\n\t\t\t}\n\t\t\tbreak stream\n\t\t}\n\t}\n}\n\n// Event IDs: encode both the logical connection ID and the index, as\n// <streamID>_<idx>, to be consistent with the typescript implementation.\n\n// formatEventID returns the event ID to use for the logical connection ID\n// streamID and message index idx.\n//\n// See also [parseEventID].\nfunc formatEventID(sid streamID, idx int) string {\n\treturn fmt.Sprintf(\"%d_%d\", sid, idx)\n}\n\n// parseEventID parses a Last-Event-ID value into a logical stream id and\n// index.\n//\n// See also [formatEventID].\nfunc parseEventID(eventID string) (sid streamID, idx int, ok bool) {\n\tparts := strings.Split(eventID, \"_\")\n\tif len(parts) != 2 {\n\t\treturn 0, 0, false\n\t}\n\tstream, err := strconv.ParseInt(parts[0], 10, 64)\n\tif err != nil || stream < 0 {\n\t\treturn 0, 0, false\n\t}\n\tidx, err = strconv.Atoi(parts[1])\n\tif err != nil || idx < 0 {\n\t\treturn 0, 0, false\n\t}\n\treturn streamID(stream), idx, true\n}\n\n// Read implements the [Connection] interface.\nfunc (t *StreamableServerTransport) Read(ctx context.Context) (JSONRPCMessage, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tcase msg, ok := <-t.incoming:\n\t\tif !ok {\n\t\t\treturn nil, io.EOF\n\t\t}\n\t\treturn msg, nil\n\tcase <-t.done:\n\t\treturn nil, io.EOF\n\t}\n}\n\n// Write implements the [Connection] interface.\nfunc (t *StreamableServerTransport) Write(ctx context.Context, msg JSONRPCMessage) error {\n\t// Find the incoming request that this write relates to, if any.\n\tvar forRequest, replyTo JSONRPCID\n\tif resp, ok := msg.(*JSONRPCResponse); ok {\n\t\t// If the message is a response, it relates to its request (of course).\n\t\tforRequest = resp.ID\n\t\treplyTo = resp.ID\n\t} else {\n\t\t// Otherwise, we check to see if it request was made in the context of an\n\t\t// ongoing request. This may not be the case if the request way made with\n\t\t// an unrelated context.\n\t\tif v := ctx.Value(idContextKey{}); v != nil {\n\t\t\tforRequest = v.(JSONRPCID)\n\t\t}\n\t}\n\n\t// Find the logical connection corresponding to this request.\n\t//\n\t// For messages sent outside of a request context, this is the default\n\t// connection 0.\n\tvar forConn streamID\n\tif forRequest.IsValid() {\n\t\tt.mu.Lock()\n\t\tforConn = t.requestStreams[forRequest]\n\t\tt.mu.Unlock()\n\t}\n\n\tdata, err := jsonrpc2.EncodeMessage(msg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tt.mu.Lock()\n\tdefer t.mu.Unlock()\n\tif t.isDone {\n\t\treturn fmt.Errorf(\"session is closed\") // TODO: should this be EOF?\n\t}\n\n\tif _, ok := t.streamRequests[forConn]; !ok && forConn != 0 {\n\t\t// No outstanding requests for this connection, which means it is logically\n\t\t// done. This is a sequencing violation from the server, so we should report\n\t\t// a side-channel error here. Put the message on the general queue to avoid\n\t\t// dropping messages.\n\t\tforConn = 0\n\t}\n\n\tidx := len(t.outgoingMessages[forConn])\n\tt.outgoingMessages[forConn] = append(t.outgoingMessages[forConn], &streamableMsg{\n\t\tidx: idx,\n\t\tevent: event{\n\t\t\tname: \"message\",\n\t\t\tid:   formatEventID(forConn, idx),\n\t\t\tdata: data,\n\t\t},\n\t})\n\tif replyTo.IsValid() {\n\t\t// Once we've put the reply on the queue, it's no longer outstanding.\n\t\tdelete(t.streamRequests[forConn], replyTo)\n\t\tif len(t.streamRequests[forConn]) == 0 {\n\t\t\tdelete(t.streamRequests, forConn)\n\t\t}\n\t}\n\n\t// Signal work.\n\tif c, ok := t.signals[forConn]; ok {\n\t\tselect {\n\t\tcase c <- struct{}{}:\n\t\tdefault:\n\t\t}\n\t}\n\treturn nil\n}\n\n// Close implements the [Connection] interface.\nfunc (t *StreamableServerTransport) Close() error {\n\tt.mu.Lock()\n\tdefer t.mu.Unlock()\n\tif !t.isDone {\n\t\tt.isDone = true\n\t\tclose(t.done)\n\t}\n\treturn nil\n}\n\n// A StreamableClientTransport is a [Transport] that can communicate with an MCP\n// endpoint serving the streamable HTTP transport defined by the 2025-03-26\n// version of the spec.\n//\n// TODO(rfindley): support retries and resumption tokens.\ntype StreamableClientTransport struct {\n\turl  string\n\topts StreamableClientTransportOptions\n}\n\n// StreamableClientTransportOptions provides options for the\n// [NewStreamableClientTransport] constructor.\ntype StreamableClientTransportOptions struct {\n\t// HTTPClient is the client to use for making HTTP requests. If nil,\n\t// http.DefaultClient is used.\n\tHTTPClient *http.Client\n}\n\n// NewStreamableClientTransport returns a new client transport that connects to\n// the streamable HTTP server at the provided URL.\nfunc NewStreamableClientTransport(url string, opts *StreamableClientTransportOptions) *StreamableClientTransport {\n\tt := &StreamableClientTransport{url: url}\n\tif opts != nil {\n\t\tt.opts = *opts\n\t}\n\treturn t\n}\n\n// Connect implements the [Transport] interface.\n//\n// The resulting [Connection] writes messages via POST requests to the\n// transport URL with the Mcp-Session-Id header set, and reads messages from\n// hanging requests.\n//\n// When closed, the connection issues a DELETE request to terminate the logical\n// session.\nfunc (t *StreamableClientTransport) Connect(ctx context.Context) (Connection, error) {\n\tclient := t.opts.HTTPClient\n\tif client == nil {\n\t\tclient = http.DefaultClient\n\t}\n\treturn &streamableClientConn{\n\t\turl:      t.url,\n\t\tclient:   client,\n\t\tincoming: make(chan []byte, 100),\n\t\tdone:     make(chan struct{}),\n\t}, nil\n}\n\ntype streamableClientConn struct {\n\turl       string\n\tsessionID string\n\tclient    *http.Client\n\tincoming  chan []byte\n\tdone      chan struct{}\n\n\tcloseOnce sync.Once\n\tcloseErr  error\n\n\tmu sync.Mutex\n\t// bodies map[*http.Response]io.Closer\n\terr error\n}\n\n// Read implements the [Connection] interface.\nfunc (s *streamableClientConn) Read(ctx context.Context) (JSONRPCMessage, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tcase <-s.done:\n\t\treturn nil, io.EOF\n\tcase data := <-s.incoming:\n\t\treturn jsonrpc2.DecodeMessage(data)\n\t}\n}\n\n// Write implements the [Connection] interface.\nfunc (s *streamableClientConn) Write(ctx context.Context, msg JSONRPCMessage) error {\n\ts.mu.Lock()\n\tif s.err != nil {\n\t\ts.mu.Unlock()\n\t\treturn s.err\n\t}\n\n\tsessionID := s.sessionID\n\tif sessionID == \"\" {\n\t\t// Hold lock for the first request.\n\t\tdefer s.mu.Unlock()\n\t} else {\n\t\ts.mu.Unlock()\n\t}\n\n\tgotSessionID, err := s.postMessage(ctx, sessionID, msg)\n\tif err != nil {\n\t\tif sessionID != \"\" {\n\t\t\t// unlocked; lock to set err\n\t\t\ts.mu.Lock()\n\t\t\tdefer s.mu.Unlock()\n\t\t}\n\t\tif s.err != nil {\n\t\t\ts.err = err\n\t\t}\n\t\treturn err\n\t}\n\n\tif sessionID == \"\" {\n\t\t// locked\n\t\ts.sessionID = gotSessionID\n\t}\n\n\treturn nil\n}\n\nfunc (s *streamableClientConn) postMessage(ctx context.Context, sessionID string, msg JSONRPCMessage) (string, error) {\n\tdata, err := jsonrpc2.EncodeMessage(msg)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, s.url, bytes.NewReader(data))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif sessionID != \"\" {\n\t\treq.Header.Set(\"Mcp-Session-Id\", sessionID)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Accept\", \"application/json, text/event-stream\")\n\n\tresp, err := s.client.Do(req)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\t// TODO: do a best effort read of the body here, and format it in the error.\n\t\tresp.Body.Close()\n\t\treturn \"\", fmt.Errorf(\"broken session: %v\", resp.Status)\n\t}\n\n\tsessionID = resp.Header.Get(\"Mcp-Session-Id\")\n\tif resp.Header.Get(\"Content-Type\") == \"text/event-stream\" {\n\t\tgo s.handleSSE(resp)\n\t} else {\n\t\tresp.Body.Close()\n\t}\n\treturn sessionID, nil\n}\n\nfunc (s *streamableClientConn) handleSSE(resp *http.Response) {\n\tdefer resp.Body.Close()\n\n\tdone := make(chan struct{})\n\tgo func() {\n\t\tdefer close(done)\n\t\tfor evt, err := range scanEvents(resp.Body) {\n\t\t\tif err != nil {\n\t\t\t\t// TODO: surface this error; possibly break the stream\n\t\t\t\treturn\n\t\t\t}\n\t\t\ts.incoming <- evt.data\n\t\t}\n\t}()\n\n\tselect {\n\tcase <-s.done:\n\tcase <-done:\n\t}\n}\n\n// Close implements the [Connection] interface.\nfunc (s *streamableClientConn) Close() error {\n\ts.closeOnce.Do(func() {\n\t\tclose(s.done)\n\n\t\treq, err := http.NewRequest(http.MethodDelete, s.url, nil)\n\t\tif err != nil {\n\t\t\ts.closeErr = err\n\t\t} else {\n\t\t\treq.Header.Set(\"Mcp-Session-Id\", s.sessionID)\n\t\t\tif _, err := s.client.Do(req); err != nil {\n\t\t\t\ts.closeErr = err\n\t\t\t}\n\t\t}\n\t})\n\treturn s.closeErr\n}\n"
  },
  {
    "path": "internal/mcp/streamable_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/cookiejar\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\nfunc TestStreamableTransports(t *testing.T) {\n\t// This test checks that the streamable server and client transports can\n\t// communicate.\n\n\tctx := context.Background()\n\n\t// 1. Create a server with a simple \"greet\" tool.\n\tserver := NewServer(\"testServer\", \"v1.0.0\", nil)\n\tserver.AddTools(NewServerTool(\"greet\", \"say hi\", sayHi))\n\n\t// 2. Start an httptest.Server with the StreamableHTTPHandler, wrapped in a\n\t// cookie-checking middleware.\n\thandler := NewStreamableHTTPHandler(func(req *http.Request) *Server { return server }, nil)\n\thttpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tcookie, err := r.Cookie(\"test-cookie\")\n\t\tif err != nil {\n\t\t\tt.Errorf(\"missing cookie: %v\", err)\n\t\t} else if cookie.Value != \"test-value\" {\n\t\t\tt.Errorf(\"got cookie %q, want %q\", cookie.Value, \"test-value\")\n\t\t}\n\t\thandler.ServeHTTP(w, r)\n\t}))\n\tdefer httpServer.Close()\n\n\t// 3. Create a client and connect it to the server using our StreamableClientTransport.\n\t// Check that all requests honor a custom client.\n\tjar, err := cookiejar.New(nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tu, err := url.Parse(httpServer.URL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tjar.SetCookies(u, []*http.Cookie{{Name: \"test-cookie\", Value: \"test-value\"}})\n\thttpClient := &http.Client{Jar: jar}\n\ttransport := NewStreamableClientTransport(httpServer.URL, &StreamableClientTransportOptions{\n\t\tHTTPClient: httpClient,\n\t})\n\tclient := NewClient(\"testClient\", \"v1.0.0\", nil)\n\tsession, err := client.Connect(ctx, transport)\n\tif err != nil {\n\t\tt.Fatalf(\"client.Connect() failed: %v\", err)\n\t}\n\tdefer session.Close()\n\n\t// 4. The client calls the \"greet\" tool.\n\tparams := &CallToolParams{\n\t\tName:      \"greet\",\n\t\tArguments: map[string]any{\"name\": \"streamy\"},\n\t}\n\tgot, err := session.CallTool(ctx, params)\n\tif err != nil {\n\t\tt.Fatalf(\"CallTool() failed: %v\", err)\n\t}\n\n\t// 5. Verify that the correct response is received.\n\twant := &CallToolResult{\n\t\tContent: []*Content{{Type: \"text\", Text: \"hi streamy\"}},\n\t}\n\tif diff := cmp.Diff(want, got); diff != \"\" {\n\t\tt.Errorf(\"CallTool() returned unexpected content (-want +got):\\n%s\", diff)\n\t}\n}\n\nfunc TestStreamableServerTransport(t *testing.T) {\n\t// This test checks detailed behavior of the streamable server transport, by\n\t// faking the behavior of a streamable client using a sequence of HTTP\n\t// requests.\n\n\t// A step is a single step in the tests below, consisting of a request payload\n\t// and expected response.\n\ttype step struct {\n\t\t// If OnRequest is > 0, this step only executes after a request with the\n\t\t// given ID is received.\n\t\t//\n\t\t// All OnRequest steps must occur before the step that creates the request.\n\t\t//\n\t\t// To avoid tests hanging when there's a bug, it's expected that this\n\t\t// request is received in the course of a *synchronous* request to the\n\t\t// server (otherwise, we wouldn't be able to terminate the test without\n\t\t// analyzing a dependency graph).\n\t\tOnRequest int64\n\t\t// If set, Async causes the step to run asynchronously to other steps.\n\t\t// Redundant with OnRequest: all OnRequest steps are asynchronous.\n\t\tAsync bool\n\n\t\tMethod     string           // HTTP request method\n\t\tSend       []JSONRPCMessage // messages to send\n\t\tCloseAfter int              // if nonzero, close after receiving this many messages\n\t\tStatusCode int              // expected status code\n\t\tRecv       []JSONRPCMessage // expected messages to receive\n\t}\n\n\t// JSON-RPC message constructors.\n\treq := func(id int64, method string, params any) *JSONRPCRequest {\n\t\tr := &JSONRPCRequest{\n\t\t\tMethod: method,\n\t\t\tParams: mustMarshal(t, params),\n\t\t}\n\t\tif id > 0 {\n\t\t\tr.ID = jsonrpc2.Int64ID(id)\n\t\t}\n\t\treturn r\n\t}\n\tresp := func(id int64, result any, err error) *JSONRPCResponse {\n\t\treturn &JSONRPCResponse{\n\t\t\tID:     jsonrpc2.Int64ID(id),\n\t\t\tResult: mustMarshal(t, result),\n\t\t\tError:  err,\n\t\t}\n\t}\n\n\t// Predefined steps, to avoid repetition below.\n\tinitReq := req(1, \"initialize\", &InitializeParams{})\n\tinitResp := resp(1, &InitializeResult{\n\t\tCapabilities: &serverCapabilities{\n\t\t\tLogging:   &loggingCapabilities{},\n\t\t\tPrompts:   &promptCapabilities{ListChanged: true},\n\t\t\tResources: &resourceCapabilities{ListChanged: true},\n\t\t\tTools:     &toolCapabilities{ListChanged: true},\n\t\t},\n\t\tProtocolVersion: \"2025-03-26\",\n\t\tServerInfo:      &implementation{Name: \"testServer\", Version: \"v1.0.0\"},\n\t}, nil)\n\tinitializedMsg := req(0, \"initialized\", &InitializedParams{})\n\tinitialize := step{\n\t\tMethod:     \"POST\",\n\t\tSend:       []JSONRPCMessage{initReq},\n\t\tStatusCode: http.StatusOK,\n\t\tRecv:       []JSONRPCMessage{initResp},\n\t}\n\tinitialized := step{\n\t\tMethod:     \"POST\",\n\t\tSend:       []JSONRPCMessage{initializedMsg},\n\t\tStatusCode: http.StatusAccepted,\n\t}\n\n\ttests := []struct {\n\t\tname  string\n\t\ttool  func(*testing.T, context.Context, *ServerSession)\n\t\tsteps []step\n\t}{\n\t\t{\n\t\t\tname: \"basic\",\n\t\t\tsteps: []step{\n\t\t\t\tinitialize,\n\t\t\t\tinitialized,\n\t\t\t\t{\n\t\t\t\t\tMethod:     \"POST\",\n\t\t\t\t\tSend:       []JSONRPCMessage{req(2, \"tools/call\", &CallToolParams{Name: \"tool\"})},\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tRecv:       []JSONRPCMessage{resp(2, &CallToolResult{}, nil)},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"tool notification\",\n\t\t\ttool: func(t *testing.T, ctx context.Context, ss *ServerSession) {\n\t\t\t\t// Send an arbitrary notification.\n\t\t\t\tif err := ss.NotifyProgress(ctx, &ProgressNotificationParams{}); err != nil {\n\t\t\t\t\tt.Errorf(\"Notify failed: %v\", err)\n\t\t\t\t}\n\t\t\t},\n\t\t\tsteps: []step{\n\t\t\t\tinitialize,\n\t\t\t\tinitialized,\n\t\t\t\t{\n\t\t\t\t\tMethod: \"POST\",\n\t\t\t\t\tSend: []JSONRPCMessage{\n\t\t\t\t\t\treq(2, \"tools/call\", &CallToolParams{Name: \"tool\"}),\n\t\t\t\t\t},\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tRecv: []JSONRPCMessage{\n\t\t\t\t\t\treq(0, \"notifications/progress\", &ProgressNotificationParams{}),\n\t\t\t\t\t\tresp(2, &CallToolResult{}, nil),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"tool upcall\",\n\t\t\ttool: func(t *testing.T, ctx context.Context, ss *ServerSession) {\n\t\t\t\t// Make an arbitrary call.\n\t\t\t\tif _, err := ss.ListRoots(ctx, &ListRootsParams{}); err != nil {\n\t\t\t\t\tt.Errorf(\"Call failed: %v\", err)\n\t\t\t\t}\n\t\t\t},\n\t\t\tsteps: []step{\n\t\t\t\tinitialize,\n\t\t\t\tinitialized,\n\t\t\t\t{\n\t\t\t\t\tMethod:    \"POST\",\n\t\t\t\t\tOnRequest: 1,\n\t\t\t\t\tSend: []JSONRPCMessage{\n\t\t\t\t\t\tresp(1, &ListRootsResult{}, nil),\n\t\t\t\t\t},\n\t\t\t\t\tStatusCode: http.StatusAccepted,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMethod: \"POST\",\n\t\t\t\t\tSend: []JSONRPCMessage{\n\t\t\t\t\t\treq(2, \"tools/call\", &CallToolParams{Name: \"tool\"}),\n\t\t\t\t\t},\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tRecv: []JSONRPCMessage{\n\t\t\t\t\t\treq(1, \"roots/list\", &ListRootsParams{}),\n\t\t\t\t\t\tresp(2, &CallToolResult{}, nil),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"background\",\n\t\t\ttool: func(t *testing.T, ctx context.Context, ss *ServerSession) {\n\t\t\t\t// Perform operations on a background context, and ensure the client\n\t\t\t\t// receives it.\n\t\t\t\tctx = context.Background()\n\t\t\t\tif err := ss.NotifyProgress(ctx, &ProgressNotificationParams{}); err != nil {\n\t\t\t\t\tt.Errorf(\"Notify failed: %v\", err)\n\t\t\t\t}\n\t\t\t\t// TODO(rfindley): finish implementing logging.\n\t\t\t\t// if err := ss.LoggingMessage(ctx, &LoggingMessageParams{}); err != nil {\n\t\t\t\t// \tt.Errorf(\"Logging failed: %v\", err)\n\t\t\t\t// }\n\t\t\t\tif _, err := ss.ListRoots(ctx, &ListRootsParams{}); err != nil {\n\t\t\t\t\tt.Errorf(\"Notify failed: %v\", err)\n\t\t\t\t}\n\t\t\t},\n\t\t\tsteps: []step{\n\t\t\t\tinitialize,\n\t\t\t\tinitialized,\n\t\t\t\t{\n\t\t\t\t\tMethod:    \"POST\",\n\t\t\t\t\tOnRequest: 1,\n\t\t\t\t\tSend: []JSONRPCMessage{\n\t\t\t\t\t\tresp(1, &ListRootsResult{}, nil),\n\t\t\t\t\t},\n\t\t\t\t\tStatusCode: http.StatusAccepted,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMethod:     \"GET\",\n\t\t\t\t\tAsync:      true,\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tCloseAfter: 2,\n\t\t\t\t\tRecv: []JSONRPCMessage{\n\t\t\t\t\t\treq(0, \"notifications/progress\", &ProgressNotificationParams{}),\n\t\t\t\t\t\treq(1, \"roots/list\", &ListRootsParams{}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMethod: \"POST\",\n\t\t\t\t\tSend: []JSONRPCMessage{\n\t\t\t\t\t\treq(2, \"tools/call\", &CallToolParams{Name: \"tool\"}),\n\t\t\t\t\t},\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tRecv: []JSONRPCMessage{\n\t\t\t\t\t\tresp(2, &CallToolResult{}, nil),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"errors\",\n\t\t\tsteps: []step{\n\t\t\t\t{\n\t\t\t\t\tMethod:     \"PUT\",\n\t\t\t\t\tStatusCode: http.StatusMethodNotAllowed,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMethod:     \"DELETE\",\n\t\t\t\t\tStatusCode: http.StatusBadRequest,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMethod:     \"POST\",\n\t\t\t\t\tSend:       []JSONRPCMessage{req(2, \"tools/call\", &CallToolParams{Name: \"tool\"})},\n\t\t\t\t\tStatusCode: http.StatusOK,\n\t\t\t\t\tRecv: []JSONRPCMessage{resp(2, nil, &jsonrpc2.WireError{\n\t\t\t\t\t\tMessage: `method \"tools/call\" is invalid during session initialization`,\n\t\t\t\t\t})},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\t// Create a server containing a single tool, which runs the test tool\n\t\t\t// behavior, if any.\n\t\t\tserver := NewServer(\"testServer\", \"v1.0.0\", nil)\n\t\t\ttool := NewServerTool(\"tool\", \"test tool\", func(ctx context.Context, ss *ServerSession, params *CallToolParamsFor[any]) (*CallToolResultFor[any], error) {\n\t\t\t\tif test.tool != nil {\n\t\t\t\t\ttest.tool(t, ctx, ss)\n\t\t\t\t}\n\t\t\t\treturn &CallToolResultFor[any]{}, nil\n\t\t\t})\n\t\t\tserver.AddTools(tool)\n\n\t\t\t// Start the streamable handler.\n\t\t\thandler := NewStreamableHTTPHandler(func(req *http.Request) *Server { return server }, nil)\n\t\t\tdefer handler.closeAll()\n\n\t\t\thttpServer := httptest.NewServer(handler)\n\t\t\tdefer httpServer.Close()\n\n\t\t\t// blocks records request blocks by JSONRPC ID.\n\t\t\t//\n\t\t\t// When an OnRequest step is encountered, it waits on the corresponding\n\t\t\t// block. When a request with that ID is received, the block is closed.\n\t\t\tvar mu sync.Mutex\n\t\t\tblocks := make(map[int64]chan struct{})\n\t\t\tfor _, step := range test.steps {\n\t\t\t\tif step.OnRequest > 0 {\n\t\t\t\t\tblocks[step.OnRequest] = make(chan struct{})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// signal when all synchronous requests have executed, so we can fail\n\t\t\t// async requests that are blocked.\n\t\t\tsyncRequestsDone := make(chan struct{})\n\n\t\t\t// To avoid complicated accounting for session ID, just set the first\n\t\t\t// non-empty session ID from a response.\n\t\t\tvar sessionID atomic.Value\n\t\t\tsessionID.Store(\"\")\n\n\t\t\t// doStep executes a single step.\n\t\t\tdoStep := func(t *testing.T, step step) {\n\t\t\t\tif step.OnRequest > 0 {\n\t\t\t\t\t// Block the step until we've received the server->client request.\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tblock := blocks[step.OnRequest]\n\t\t\t\t\tmu.Unlock()\n\t\t\t\t\tselect {\n\t\t\t\t\tcase <-block:\n\t\t\t\t\tcase <-syncRequestsDone:\n\t\t\t\t\t\tt.Errorf(\"after all sync requests are complete, request still blocked on %d\", step.OnRequest)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Collect messages received during this request, unblock other steps\n\t\t\t\t// when requests are received.\n\t\t\t\tvar got []JSONRPCMessage\n\t\t\t\tout := make(chan JSONRPCMessage)\n\t\t\t\t// Cancel the step if we encounter a request that isn't going to be\n\t\t\t\t// handled.\n\t\t\t\tctx, cancel := context.WithCancel(context.Background())\n\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\twg.Add(1)\n\t\t\t\tgo func() {\n\t\t\t\t\tdefer wg.Done()\n\n\t\t\t\t\tfor m := range out {\n\t\t\t\t\t\tif req, ok := m.(*JSONRPCRequest); ok && req.ID.IsValid() {\n\t\t\t\t\t\t\t// Encountered a server->client request. We should have a\n\t\t\t\t\t\t\t// response queued. Otherwise, we may deadlock.\n\t\t\t\t\t\t\tmu.Lock()\n\t\t\t\t\t\t\tif block, ok := blocks[req.ID.Raw().(int64)]; ok {\n\t\t\t\t\t\t\t\tclose(block)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt.Errorf(\"no queued response for %v\", req.ID)\n\t\t\t\t\t\t\t\tcancel()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmu.Unlock()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgot = append(got, m)\n\t\t\t\t\t\tif step.CloseAfter > 0 && len(got) == step.CloseAfter {\n\t\t\t\t\t\t\tcancel()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}()\n\n\t\t\t\tgotSessionID, gotStatusCode, err := streamingRequest(ctx,\n\t\t\t\t\thttpServer.URL, sessionID.Load().(string), step.Method, step.Send, out)\n\n\t\t\t\t// Don't fail on cancelled requests: error (if any) is handled\n\t\t\t\t// elsewhere.\n\t\t\t\tif err != nil && ctx.Err() == nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif gotStatusCode != step.StatusCode {\n\t\t\t\t\tt.Errorf(\"got status %d, want %d\", gotStatusCode, step.StatusCode)\n\t\t\t\t}\n\t\t\t\twg.Wait()\n\n\t\t\t\ttransform := cmpopts.AcyclicTransformer(\"jsonrpcid\", func(id JSONRPCID) any { return id.Raw() })\n\t\t\t\tif diff := cmp.Diff(step.Recv, got, transform); diff != \"\" {\n\t\t\t\t\tt.Errorf(\"received unexpected messages (-want +got):\\n%s\", diff)\n\t\t\t\t}\n\t\t\t\tsessionID.CompareAndSwap(\"\", gotSessionID)\n\t\t\t}\n\n\t\t\tvar wg sync.WaitGroup\n\t\t\tfor _, step := range test.steps {\n\t\t\t\tif step.Async || step.OnRequest > 0 {\n\t\t\t\t\twg.Add(1)\n\t\t\t\t\tgo func() {\n\t\t\t\t\t\tdefer wg.Done()\n\t\t\t\t\t\tdoStep(t, step)\n\t\t\t\t\t}()\n\t\t\t\t} else {\n\t\t\t\t\tdoStep(t, step)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fail any blocked responses if they weren't needed by a synchronous\n\t\t\t// request.\n\t\t\tclose(syncRequestsDone)\n\n\t\t\twg.Wait()\n\t\t})\n\t}\n}\n\n// streamingRequest makes a request to the given streamable server with the\n// given url, sessionID, and method.\n//\n// If provided, the in messages are encoded in the request body. A single\n// message is encoded as a JSON object. Multiple messages are batched as a JSON\n// array.\n//\n// Any received messages are sent to the out channel, which is closed when the\n// request completes.\n//\n// Returns the sessionID and http status code from the response. If an error is\n// returned, sessionID and status code may still be set if the error occurs\n// after the response headers have been received.\nfunc streamingRequest(ctx context.Context, serverURL, sessionID, method string, in []JSONRPCMessage, out chan<- JSONRPCMessage) (string, int, error) {\n\tdefer close(out)\n\n\tvar body []byte\n\tif len(in) == 1 {\n\t\tdata, err := jsonrpc2.EncodeMessage(in[0])\n\t\tif err != nil {\n\t\t\treturn \"\", 0, fmt.Errorf(\"encoding message: %w\", err)\n\t\t}\n\t\tbody = data\n\t} else {\n\t\tvar rawMsgs []json.RawMessage\n\t\tfor _, msg := range in {\n\t\t\tdata, err := jsonrpc2.EncodeMessage(msg)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", 0, fmt.Errorf(\"encoding message: %w\", err)\n\t\t\t}\n\t\t\trawMsgs = append(rawMsgs, data)\n\t\t}\n\t\tdata, err := json.Marshal(rawMsgs)\n\t\tif err != nil {\n\t\t\treturn \"\", 0, fmt.Errorf(\"marshaling batch: %w\", err)\n\t\t}\n\t\tbody = data\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, method, serverURL, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn \"\", 0, fmt.Errorf(\"creating request: %w\", err)\n\t}\n\tif sessionID != \"\" {\n\t\treq.Header.Set(\"Mcp-Session-Id\", sessionID)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Add(\"Accept\", \"text/plain\") // ensure multiple accept headers are allowed\n\treq.Header.Add(\"Accept\", \"application/json, text/event-stream\")\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn \"\", 0, fmt.Errorf(\"request failed: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tnewSessionID := resp.Header.Get(\"Mcp-Session-Id\")\n\n\tif strings.HasPrefix(resp.Header.Get(\"Content-Type\"), \"text/event-stream\") {\n\t\tfor evt, err := range scanEvents(resp.Body) {\n\t\t\tif err != nil {\n\t\t\t\treturn newSessionID, resp.StatusCode, fmt.Errorf(\"reading events: %v\", err)\n\t\t\t}\n\t\t\t// TODO(rfindley): do we need to check evt.name?\n\t\t\t// Does the MCP spec say anything about this?\n\t\t\tmsg, err := jsonrpc2.DecodeMessage(evt.data)\n\t\t\tif err != nil {\n\t\t\t\treturn newSessionID, resp.StatusCode, fmt.Errorf(\"decoding message: %w\", err)\n\t\t\t}\n\t\t\tout <- msg\n\t\t}\n\t} else if strings.HasPrefix(resp.Header.Get(\"Content-Type\"), \"application/json\") {\n\t\tdata, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\treturn newSessionID, resp.StatusCode, fmt.Errorf(\"reading json body: %w\", err)\n\t\t}\n\t\tmsg, err := jsonrpc2.DecodeMessage(data)\n\t\tif err != nil {\n\t\t\treturn newSessionID, resp.StatusCode, fmt.Errorf(\"decoding message: %w\", err)\n\t\t}\n\t\tout <- msg\n\t}\n\n\treturn newSessionID, resp.StatusCode, nil\n}\n\nfunc mustMarshal(t *testing.T, v any) json.RawMessage {\n\tif v == nil {\n\t\treturn nil\n\t}\n\tt.Helper()\n\tdata, err := json.Marshal(v)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn data\n}\n\nfunc TestEventID(t *testing.T) {\n\ttests := []struct {\n\t\tsid streamID\n\t\tidx int\n\t}{\n\t\t{0, 0},\n\t\t{0, 1},\n\t\t{1, 0},\n\t\t{1, 1},\n\t\t{1234, 5678},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"%d_%d\", test.sid, test.idx), func(t *testing.T) {\n\t\t\teventID := formatEventID(test.sid, test.idx)\n\t\t\tgotSID, gotIdx, ok := parseEventID(eventID)\n\t\t\tif !ok {\n\t\t\t\tt.Fatalf(\"parseEventID(%q) failed, want ok\", eventID)\n\t\t\t}\n\t\t\tif gotSID != test.sid || gotIdx != test.idx {\n\t\t\t\tt.Errorf(\"parseEventID(%q) = %d, %d, want %d, %d\", eventID, gotSID, gotIdx, test.sid, test.idx)\n\t\t\t}\n\t\t})\n\t}\n\n\tinvalid := []string{\n\t\t\"\",\n\t\t\"_\",\n\t\t\"1_\",\n\t\t\"_1\",\n\t\t\"a_1\",\n\t\t\"1_a\",\n\t\t\"-1_1\",\n\t\t\"1_-1\",\n\t}\n\n\tfor _, eventID := range invalid {\n\t\tt.Run(fmt.Sprintf(\"invalid_%q\", eventID), func(t *testing.T) {\n\t\t\tif _, _, ok := parseEventID(eventID); ok {\n\t\t\t\tt.Errorf(\"parseEventID(%q) succeeded, want failure\", eventID)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/conformance/server/prompts.txtar",
    "content": "Check behavior of a server with just prompts.\n\nFixed bugs:\n- empty tools lists should not be returned as 'null'\n\n-- prompts --\ncode_review\n\n-- client --\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2024-11-05\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"ExampleClient\", \"version\": \"1.0.0\" }\n  }\n}\n{ \"jsonrpc\": \"2.0\", \"id\": 2, \"method\": \"tools/list\" }\n{ \"jsonrpc\": \"2.0\", \"id\": 4, \"method\": \"prompts/list\" }\n-- server --\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"capabilities\": {\n\t\t\t\"completions\": {},\n\t\t\t\"logging\": {},\n\t\t\t\"prompts\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"resources\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"tools\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t}\n\t\t},\n\t\t\"protocolVersion\": \"2024-11-05\",\n\t\t\"serverInfo\": {\n\t\t\t\"name\": \"testServer\",\n\t\t\t\"version\": \"v1.0.0\"\n\t\t}\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 2,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"tools\": []\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 4,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"prompts\": [\n\t\t\t{\n\t\t\t\t\"arguments\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"name\": \"Code\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"description\": \"do a code review\",\n\t\t\t\t\"name\": \"code_review\"\n\t\t\t}\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/conformance/server/resources.txtar",
    "content": "Check behavior of a server with just resources.\n\nFixed bugs:\n- A resource result holds a slice of contents, not just one.\n\n-- resources --\ninfo\ninfo.txt\n\n-- client --\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2024-11-05\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"ExampleClient\", \"version\": \"1.0.0\" }\n  }\n}\n{ \"jsonrpc\": \"2.0\", \"id\": 2, \"method\": \"resources/list\" }\n{\n  \"jsonrpc\": \"2.0\", \"id\": 3,\n  \"method\": \"resources/read\",\n  \"params\": {\n    \"uri\": \"embedded:info\"\n  }\n}\n{\n  \"jsonrpc\": \"2.0\", \"id\": 3,\n  \"method\": \"resources/read\",\n  \"params\": {\n    \"uri\": \"file:///info.txt\"\n  }\n}\n{\n  \"jsonrpc\": \"2.0\", \"id\": 0,\n  \"result\": {\n\t\"roots\": []\n  }\n}\n-- server --\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"capabilities\": {\n\t\t\t\"completions\": {},\n\t\t\t\"logging\": {},\n\t\t\t\"prompts\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"resources\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"tools\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t}\n\t\t},\n\t\t\"protocolVersion\": \"2024-11-05\",\n\t\t\"serverInfo\": {\n\t\t\t\"name\": \"testServer\",\n\t\t\t\"version\": \"v1.0.0\"\n\t\t}\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 2,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"resources\": [\n\t\t\t{\n\t\t\t\t\"mimeType\": \"text/plain\",\n\t\t\t\t\"name\": \"info\",\n\t\t\t\t\"uri\": \"embedded:info\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"mimeType\": \"text/plain\",\n\t\t\t\t\"name\": \"public\",\n\t\t\t\t\"uri\": \"file:///info.txt\"\n\t\t\t}\n\t\t]\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 3,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"contents\": [\n\t\t\t{\n\t\t\t\t\"uri\": \"embedded:info\",\n\t\t\t\t\"mimeType\": \"text/plain\",\n\t\t\t\t\"text\": \"This is the MCP test server.\"\n\t\t\t}\n\t\t]\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"method\": \"roots/list\"\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 3,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"contents\": [\n\t\t\t{\n\t\t\t\t\"uri\": \"file:///info.txt\",\n\t\t\t\t\"mimeType\": \"text/plain\",\n\t\t\t\t\"blob\": \"Q29udGVudHMK\"\n\t\t\t}\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/conformance/server/tools.txtar",
    "content": "Check behavior of a server with just tools.\n\nFixed bugs:\n- \"tools/list\" can have missing params\n- \"_meta\" should not be nil\n- empty resource or prompts should not be returned as 'null'\n\n-- tools --\ngreet\n\n-- client --\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2024-11-05\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"ExampleClient\", \"version\": \"1.0.0\" }\n  }\n}\n{ \"jsonrpc\": \"2.0\", \"id\": 2, \"method\": \"tools/list\" }\n{ \"jsonrpc\": \"2.0\", \"id\": 3, \"method\": \"resources/list\" }\n{ \"jsonrpc\": \"2.0\", \"id\": 4, \"method\": \"prompts/list\" }\n-- server --\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"capabilities\": {\n\t\t\t\"completions\": {},\n\t\t\t\"logging\": {},\n\t\t\t\"prompts\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"resources\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"tools\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t}\n\t\t},\n\t\t\"protocolVersion\": \"2024-11-05\",\n\t\t\"serverInfo\": {\n\t\t\t\"name\": \"testServer\",\n\t\t\t\"version\": \"v1.0.0\"\n\t\t}\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 2,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"tools\": [\n\t\t\t{\n\t\t\t\t\"description\": \"say hi\",\n\t\t\t\t\"inputSchema\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"required\": [\n\t\t\t\t\t\t\"Name\"\n\t\t\t\t\t],\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"Name\": {\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"not\": {}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"name\": \"greet\"\n\t\t\t}\n\t\t]\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 3,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"resources\": []\n\t}\n}\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 4,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"prompts\": []\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/conformance/server/version-latest.txtar",
    "content": "Check that when the client sends an arbitrary later version, the server\nresponse with its latest supported version.\n\n-- client --\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2029-01-01\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"ExampleClient\", \"version\": \"1.0.0\" }\n  }\n}\n-- server --\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"capabilities\": {\n\t\t\t\"completions\": {},\n\t\t\t\"logging\": {},\n\t\t\t\"prompts\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"resources\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"tools\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t}\n\t\t},\n\t\t\"protocolVersion\": \"2025-03-26\",\n\t\t\"serverInfo\": {\n\t\t\t\"name\": \"testServer\",\n\t\t\t\"version\": \"v1.0.0\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/conformance/server/version-older.txtar",
    "content": "Check that when the client sends an older version, the server indicates\nsupport.\n\n-- client --\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2024-11-05\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"ExampleClient\", \"version\": \"1.0.0\" }\n  }\n}\n-- server --\n{\n\t\"jsonrpc\": \"2.0\",\n\t\"id\": 1,\n\t\"result\": {\n\t\t\"_meta\": {},\n\t\t\"capabilities\": {\n\t\t\t\"completions\": {},\n\t\t\t\"logging\": {},\n\t\t\t\"prompts\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"resources\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t},\n\t\t\t\"tools\": {\n\t\t\t\t\"listChanged\": true\n\t\t\t}\n\t\t},\n\t\t\"protocolVersion\": \"2024-11-05\",\n\t\t\"serverInfo\": {\n\t\t\t\"name\": \"testServer\",\n\t\t\t\"version\": \"v1.0.0\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/testdata/files/info.txt",
    "content": "Contents\n"
  },
  {
    "path": "internal/mcp/testdata/files/template.txt",
    "content": ""
  },
  {
    "path": "internal/mcp/testdata/private.txt",
    "content": ""
  },
  {
    "path": "internal/mcp/testdata/public/dir/file3.txt",
    "content": ""
  },
  {
    "path": "internal/mcp/testdata/public/file1.txt",
    "content": ""
  },
  {
    "path": "internal/mcp/testdata/public/file2.txt",
    "content": ""
  },
  {
    "path": "internal/mcp/tool.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\n// A ToolHandler handles a call to tools/call.\n// [CallToolParams.Arguments] will contain a map[string]any that has been validated\n// against the input schema.\n// Perhaps this should be an alias for ToolHandlerFor[map[string]any, map[string]any].\ntype ToolHandler func(context.Context, *ServerSession, *CallToolParamsFor[map[string]any]) (*CallToolResult, error)\n\n// A ToolHandlerFor handles a call to tools/call with typed arguments and results.\ntype ToolHandlerFor[In, Out any] func(context.Context, *ServerSession, *CallToolParamsFor[In]) (*CallToolResultFor[Out], error)\n\n// A rawToolHandler is like a ToolHandler, but takes the arguments as json.RawMessage.\ntype rawToolHandler = func(context.Context, *ServerSession, *CallToolParamsFor[json.RawMessage]) (*CallToolResult, error)\n\n// A Tool is a tool definition that is bound to a tool handler.\ntype ServerTool struct {\n\tTool    *Tool\n\tHandler ToolHandler\n\t// Set in NewServerTool or Server.AddToolsErr.\n\trawHandler rawToolHandler\n\t// Resolved tool schemas. Set in Server.AddToolsErr.\n\t// TODO(rfindley): re-enable schema validation. For now, it is causing breakage in Google.\n\t// inputResolved, outputResolved *jsonschema.Resolved\n}\n\n// NewServerTool is a helper to make a tool using reflection on the given type parameters.\n// When the tool is called, CallToolParams.Arguments will be of type In.\n//\n// If provided, variadic [ToolOption] values may be used to customize the tool.\n//\n// The input schema for the tool is extracted from the request type for the\n// handler, and used to unmmarshal and validate requests to the handler. This\n// schema may be customized using the [Input] option.\nfunc NewServerTool[In, Out any](name, description string, handler ToolHandlerFor[In, Out], opts ...ToolOption) *ServerTool {\n\tst, err := newServerToolErr[In, Out](name, description, handler, opts...)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"NewServerTool(%q): %w\", name, err))\n\t}\n\treturn st\n}\n\nfunc newServerToolErr[In, Out any](name, description string, handler ToolHandlerFor[In, Out], opts ...ToolOption) (*ServerTool, error) {\n\t// TODO: check that In is a struct.\n\tischema, err := jsonschema.For[In]()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// TODO: uncomment when output schemas drop.\n\t// oschema, err := jsonschema.For[TRes]()\n\t// if err != nil {\n\t// \treturn nil, err\n\t// }\n\n\tt := &ServerTool{\n\t\tTool: &Tool{\n\t\t\tName:        name,\n\t\t\tDescription: description,\n\t\t\tInputSchema: ischema,\n\t\t\t// OutputSchema: oschema,\n\t\t},\n\t}\n\tfor _, opt := range opts {\n\t\topt.set(t)\n\t}\n\n\tt.rawHandler = func(ctx context.Context, ss *ServerSession, rparams *CallToolParamsFor[json.RawMessage]) (*CallToolResult, error) {\n\t\tvar args In\n\t\tif rparams.Arguments != nil {\n\t\t\t// TODO(rfindley): re-enable schema validation. See note in [ServerTool].\n\t\t\tif err := unmarshalSchema(rparams.Arguments, nil, &args); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\t// TODO(jba): future-proof this copy.\n\t\tparams := &CallToolParamsFor[In]{\n\t\t\tMeta:      rparams.Meta,\n\t\t\tName:      rparams.Name,\n\t\t\tArguments: args,\n\t\t}\n\t\tres, err := handler(ctx, ss, params)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tvar ctr CallToolResult\n\t\tif res != nil {\n\t\t\t// TODO(jba): future-proof this copy.\n\t\t\tctr.Meta = res.Meta\n\t\t\tctr.Content = res.Content\n\t\t\tctr.IsError = res.IsError\n\t\t}\n\t\treturn &ctr, nil\n\t}\n\treturn t, nil\n}\n\n// newRawHandler creates a rawToolHandler for tools not created through NewServerTool.\n// It unmarshals the arguments into a map[string]any and validates them against the\n// schema, then calls the ServerTool's handler.\nfunc newRawHandler(st *ServerTool) rawToolHandler {\n\tif st.Handler == nil {\n\t\tpanic(\"st.Handler is nil\")\n\t}\n\treturn func(ctx context.Context, ss *ServerSession, rparams *CallToolParamsFor[json.RawMessage]) (*CallToolResult, error) {\n\t\t// Unmarshal the args into what should be a map.\n\t\tvar args map[string]any\n\t\tif rparams.Arguments != nil {\n\t\t\t// TODO(rfindley): re-enable schema validation. See note in [ServerTool].\n\t\t\tif err := unmarshalSchema(rparams.Arguments, nil, &args); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\t// TODO: generate copy\n\t\tparams := &CallToolParamsFor[map[string]any]{\n\t\t\tMeta:      rparams.Meta,\n\t\t\tName:      rparams.Name,\n\t\t\tArguments: args,\n\t\t}\n\t\tres, err := st.Handler(ctx, ss, params)\n\t\t// TODO(rfindley): investigate why server errors are embedded in this strange way,\n\t\t// rather than returned as jsonrpc2 server errors.\n\t\tif err != nil {\n\t\t\treturn &CallToolResult{\n\t\t\t\tContent: []*Content{NewTextContent(err.Error())},\n\t\t\t\tIsError: true,\n\t\t\t}, nil\n\t\t}\n\t\treturn res, nil\n\t}\n}\n\n// unmarshalSchema unmarshals data into v and validates the result according to\n// the given resolved schema.\nfunc unmarshalSchema(data json.RawMessage, resolved *jsonschema.Resolved, v any) error {\n\t// TODO: use reflection to create the struct type to unmarshal into.\n\t// Separate validation from assignment.\n\n\t// Disallow unknown fields.\n\t// Otherwise, if the tool was built with a struct, the client could send extra\n\t// fields and json.Unmarshal would ignore them, so the schema would never get\n\t// a chance to declare the extra args invalid.\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.DisallowUnknownFields()\n\tif err := dec.Decode(v); err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling: %w\", err)\n\t}\n\t// TODO: test with nil args.\n\tif resolved != nil {\n\t\tif err := resolved.ApplyDefaults(v); err != nil {\n\t\t\treturn fmt.Errorf(\"applying defaults from \\n\\t%s\\nto\\n\\t%s:\\n%w\", schemaJSON(resolved.Schema()), data, err)\n\t\t}\n\t\tif err := resolved.Validate(v); err != nil {\n\t\t\treturn fmt.Errorf(\"validating\\n\\t%s\\nagainst\\n\\t %s:\\n %w\", data, schemaJSON(resolved.Schema()), err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// A ToolOption configures the behavior of a Tool.\ntype ToolOption interface {\n\tset(*ServerTool)\n}\n\ntype toolSetter func(*ServerTool)\n\nfunc (s toolSetter) set(t *ServerTool) { s(t) }\n\n// Input applies the provided [SchemaOption] configuration to the tool's input\n// schema.\nfunc Input(opts ...SchemaOption) ToolOption {\n\treturn toolSetter(func(t *ServerTool) {\n\t\tfor _, opt := range opts {\n\t\t\topt.set(t.Tool.InputSchema)\n\t\t}\n\t})\n}\n\n// A SchemaOption configures a jsonschema.Schema.\ntype SchemaOption interface {\n\tset(s *jsonschema.Schema)\n}\n\ntype schemaSetter func(*jsonschema.Schema)\n\nfunc (s schemaSetter) set(schema *jsonschema.Schema) { s(schema) }\n\n// Property configures the schema for the property of the given name.\n// If there is no such property in the schema, it is created.\nfunc Property(name string, opts ...SchemaOption) SchemaOption {\n\treturn schemaSetter(func(schema *jsonschema.Schema) {\n\t\tpropSchema, ok := schema.Properties[name]\n\t\tif !ok {\n\t\t\tpropSchema = new(jsonschema.Schema)\n\t\t\tschema.Properties[name] = propSchema\n\t\t}\n\t\t// Apply the options, with special handling for Required, as it needs to be\n\t\t// set on the parent schema.\n\t\tfor _, opt := range opts {\n\t\t\tif req, ok := opt.(required); ok {\n\t\t\t\tif req {\n\t\t\t\t\tif !slices.Contains(schema.Required, name) {\n\t\t\t\t\t\tschema.Required = append(schema.Required, name)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tschema.Required = slices.DeleteFunc(schema.Required, func(s string) bool {\n\t\t\t\t\t\treturn s == name\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\topt.set(propSchema)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// Required sets whether the associated property is required. It is only valid\n// when used in a [Property] option: using Required outside of Property panics.\nfunc Required(v bool) SchemaOption {\n\treturn required(v)\n}\n\n// required must be a distinguished type as it needs special handling to mutate\n// the parent schema, and to mutate prompt arguments.\ntype required bool\n\nfunc (required) set(s *jsonschema.Schema) {\n\tpanic(\"use of required outside of Property\")\n}\n\n// Enum sets the provided values as the \"enum\" value of the schema.\nfunc Enum(values ...any) SchemaOption {\n\treturn schemaSetter(func(s *jsonschema.Schema) {\n\t\ts.Enum = values\n\t})\n}\n\n// Description sets the provided schema description.\nfunc Description(desc string) SchemaOption {\n\treturn description(desc)\n}\n\n// description must be a distinguished type so that it can be handled by prompt\n// options.\ntype description string\n\nfunc (d description) set(s *jsonschema.Schema) {\n\ts.Description = string(d)\n}\n\n// Schema overrides the inferred schema with a shallow copy of the given\n// schema.\nfunc Schema(schema *jsonschema.Schema) SchemaOption {\n\treturn schemaSetter(func(s *jsonschema.Schema) {\n\t\t*s = *schema\n\t})\n}\n\n// schemaJSON returns the JSON value for s as a string, or a string indicating an error.\nfunc schemaJSON(s *jsonschema.Schema) string {\n\tm, err := json.Marshal(s)\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"<!%s>\", err)\n\t}\n\treturn string(m)\n}\n"
  },
  {
    "path": "internal/mcp/tool_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n\t\"golang.org/x/tools/internal/mcp/jsonschema\"\n)\n\n// testToolHandler is used for type inference in TestNewServerTool.\nfunc testToolHandler[T any](context.Context, *ServerSession, *CallToolParamsFor[T]) (*CallToolResultFor[any], error) {\n\tpanic(\"not implemented\")\n}\n\nfunc TestNewServerTool(t *testing.T) {\n\ttests := []struct {\n\t\ttool *ServerTool\n\t\twant *jsonschema.Schema\n\t}{\n\t\t{\n\t\t\tNewServerTool(\"basic\", \"\", testToolHandler[struct {\n\t\t\t\tName string `json:\"name\"`\n\t\t\t}]),\n\t\t\t&jsonschema.Schema{\n\t\t\t\tType:     \"object\",\n\t\t\t\tRequired: []string{\"name\"},\n\t\t\t\tProperties: map[string]*jsonschema.Schema{\n\t\t\t\t\t\"name\": {Type: \"string\"},\n\t\t\t\t},\n\t\t\t\tAdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tNewServerTool(\"enum\", \"\", testToolHandler[struct{ Name string }], Input(\n\t\t\t\tProperty(\"Name\", Enum(\"x\", \"y\", \"z\")),\n\t\t\t)),\n\t\t\t&jsonschema.Schema{\n\t\t\t\tType:     \"object\",\n\t\t\t\tRequired: []string{\"Name\"},\n\t\t\t\tProperties: map[string]*jsonschema.Schema{\n\t\t\t\t\t\"Name\": {Type: \"string\", Enum: []any{\"x\", \"y\", \"z\"}},\n\t\t\t\t},\n\t\t\t\tAdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tNewServerTool(\"required\", \"\", testToolHandler[struct {\n\t\t\t\tName     string `json:\"name\"`\n\t\t\t\tLanguage string `json:\"language\"`\n\t\t\t\tX        int    `json:\"x,omitempty\"`\n\t\t\t\tY        int    `json:\"y,omitempty\"`\n\t\t\t}], Input(\n\t\t\t\tProperty(\"x\", Required(true)))),\n\t\t\t&jsonschema.Schema{\n\t\t\t\tType:     \"object\",\n\t\t\t\tRequired: []string{\"name\", \"language\", \"x\"},\n\t\t\t\tProperties: map[string]*jsonschema.Schema{\n\t\t\t\t\t\"language\": {Type: \"string\"},\n\t\t\t\t\t\"name\":     {Type: \"string\"},\n\t\t\t\t\t\"x\":        {Type: \"integer\"},\n\t\t\t\t\t\"y\":        {Type: \"integer\"},\n\t\t\t\t},\n\t\t\t\tAdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tNewServerTool(\"set_schema\", \"\", testToolHandler[struct {\n\t\t\t\tX int `json:\"x,omitempty\"`\n\t\t\t\tY int `json:\"y,omitempty\"`\n\t\t\t}], Input(\n\t\t\t\tSchema(&jsonschema.Schema{Type: \"object\"})),\n\t\t\t),\n\t\t\t&jsonschema.Schema{\n\t\t\t\tType: \"object\",\n\t\t\t},\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tif diff := cmp.Diff(test.want, test.tool.Tool.InputSchema, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != \"\" {\n\t\t\tt.Errorf(\"NewServerTool(%v) mismatch (-want +got):\\n%s\", test.tool.Tool.Name, diff)\n\t\t}\n\t}\n}\n\nfunc TestUnmarshalSchema(t *testing.T) {\n\tschema := &jsonschema.Schema{\n\t\tType: \"object\",\n\t\tProperties: map[string]*jsonschema.Schema{\n\t\t\t\"x\": {Type: \"integer\", Default: json.RawMessage(\"3\")},\n\t\t},\n\t}\n\tresolved, err := schema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttype S struct {\n\t\tX int `json:\"x\"`\n\t}\n\n\tfor _, tt := range []struct {\n\t\tdata string\n\t\tv    any\n\t\twant any\n\t}{\n\t\t{`{\"x\": 1}`, new(S), &S{X: 1}},\n\t\t{`{}`, new(S), &S{X: 3}},       // default applied\n\t\t{`{\"x\": 0}`, new(S), &S{X: 3}}, // FAIL: should be 0. (requires double unmarshal)\n\t\t{`{\"x\": 1}`, new(map[string]any), &map[string]any{\"x\": 1.0}},\n\t\t{`{}`, new(map[string]any), &map[string]any{\"x\": 3.0}}, // default applied\n\t\t{`{\"x\": 0}`, new(map[string]any), &map[string]any{\"x\": 0.0}},\n\t} {\n\t\traw := json.RawMessage(tt.data)\n\t\tif err := unmarshalSchema(raw, resolved, tt.v); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !reflect.DeepEqual(tt.v, tt.want) {\n\t\t\tt.Errorf(\"got %#v, want %#v\", tt.v, tt.want)\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/transport.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"sync\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n\t\"golang.org/x/tools/internal/xcontext\"\n)\n\n// ErrConnectionClosed is returned when sending a message to a connection that\n// is closed or in the process of closing.\nvar ErrConnectionClosed = errors.New(\"connection closed\")\n\n// A Transport is used to create a bidirectional connection between MCP client\n// and server.\n//\n// Transports should be used for at most one call to [Server.Connect] or\n// [Client.Start].\ntype Transport interface {\n\t// Connect returns the logical JSON-RPC connection..\n\t//\n\t// It is called exactly once by [Server.Connect] or [Client.Connect].\n\tConnect(ctx context.Context) (Connection, error)\n}\n\ntype (\n\t// JSONRPCID is a JSON-RPC request ID.\n\tJSONRPCID = jsonrpc2.ID\n\t// JSONRPCMessage is a JSON-RPC message.\n\tJSONRPCMessage = jsonrpc2.Message\n\t// JSONRPCRequest is a JSON-RPC request.\n\tJSONRPCRequest = jsonrpc2.Request\n\t// JSONRPCResponse is a JSON-RPC response.\n\tJSONRPCResponse = jsonrpc2.Response\n)\n\n// A Connection is a logical bidirectional JSON-RPC connection.\ntype Connection interface {\n\tRead(context.Context) (JSONRPCMessage, error)\n\tWrite(context.Context, JSONRPCMessage) error\n\tClose() error // may be called concurrently by both peers\n}\n\n// A StdioTransport is a [Transport] that communicates over stdin/stdout using\n// newline-delimited JSON.\ntype StdioTransport struct {\n\tioTransport\n}\n\n// An ioTransport is a [Transport] that communicates using newline-delimited\n// JSON over an io.ReadWriteCloser.\ntype ioTransport struct {\n\trwc io.ReadWriteCloser\n}\n\nfunc (t *ioTransport) Connect(context.Context) (Connection, error) {\n\treturn newIOConn(t.rwc), nil\n}\n\n// NewStdioTransport constructs a transport that communicates over\n// stdin/stdout.\nfunc NewStdioTransport() *StdioTransport {\n\treturn &StdioTransport{ioTransport{rwc{os.Stdin, os.Stdout}}}\n}\n\n// An InMemoryTransport is a [Transport] that communicates over an in-memory\n// network connection, using newline-delimited JSON.\ntype InMemoryTransport struct {\n\tioTransport\n}\n\n// NewInMemoryTransports returns two InMemoryTransports that connect to each\n// other.\nfunc NewInMemoryTransports() (*InMemoryTransport, *InMemoryTransport) {\n\tc1, c2 := net.Pipe()\n\treturn &InMemoryTransport{ioTransport{c1}}, &InMemoryTransport{ioTransport{c2}}\n}\n\ntype binder[T handler] interface {\n\tbind(*jsonrpc2.Connection) T\n\tdisconnect(T)\n}\n\ntype handler interface {\n\thandle(ctx context.Context, req *JSONRPCRequest) (any, error)\n}\n\nfunc connect[H handler](ctx context.Context, t Transport, b binder[H]) (H, error) {\n\tvar zero H\n\tconn, err := t.Connect(ctx)\n\tif err != nil {\n\t\treturn zero, err\n\t}\n\t// If logging is configured, write message logs.\n\treader, writer := jsonrpc2.Reader(conn), jsonrpc2.Writer(conn)\n\tvar (\n\t\th         H\n\t\tpreempter canceller\n\t)\n\tbind := func(conn *jsonrpc2.Connection) jsonrpc2.Handler {\n\t\th = b.bind(conn)\n\t\tpreempter.conn = conn\n\t\treturn jsonrpc2.HandlerFunc(h.handle)\n\t}\n\t_ = jsonrpc2.NewConnection(ctx, jsonrpc2.ConnectionConfig{\n\t\tReader:    reader,\n\t\tWriter:    writer,\n\t\tCloser:    conn,\n\t\tBind:      bind,\n\t\tPreempter: &preempter,\n\t\tOnDone: func() {\n\t\t\tb.disconnect(h)\n\t\t},\n\t})\n\tassert(preempter.conn != nil, \"unbound preempter\")\n\treturn h, nil\n}\n\n// A canceller is a jsonrpc2.Preempter that cancels in-flight requests on MCP\n// cancelled notifications.\ntype canceller struct {\n\tconn *jsonrpc2.Connection\n}\n\n// Preempt implements jsonrpc2.Preempter.\nfunc (c *canceller) Preempt(ctx context.Context, req *JSONRPCRequest) (result any, err error) {\n\tif req.Method == \"notifications/cancelled\" {\n\t\tvar params CancelledParams\n\t\tif err := json.Unmarshal(req.Params, &params); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tid, err := jsonrpc2.MakeID(params.RequestID)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tgo c.conn.Cancel(id)\n\t}\n\treturn nil, jsonrpc2.ErrNotHandled\n}\n\n// call executes and awaits a jsonrpc2 call on the given connection,\n// translating errors into the mcp domain.\nfunc call(ctx context.Context, conn *jsonrpc2.Connection, method string, params Params, result Result) error {\n\t// TODO: the \"%w\"s in this function effectively make jsonrpc2.WireError part of the API.\n\t// Consider alternatives.\n\tcall := conn.Call(ctx, method, params)\n\terr := call.Await(ctx, result)\n\tswitch {\n\tcase errors.Is(err, jsonrpc2.ErrClientClosing), errors.Is(err, jsonrpc2.ErrServerClosing):\n\t\treturn fmt.Errorf(\"calling %q: %w\", method, ErrConnectionClosed)\n\tcase ctx.Err() != nil:\n\t\t// Notify the peer of cancellation.\n\t\terr := conn.Notify(xcontext.Detach(ctx), notificationCancelled, &CancelledParams{\n\t\t\tReason:    ctx.Err().Error(),\n\t\t\tRequestID: call.ID().Raw(),\n\t\t})\n\t\treturn errors.Join(ctx.Err(), err)\n\tcase err != nil:\n\t\treturn fmt.Errorf(\"calling %q: %w\", method, err)\n\t}\n\treturn nil\n}\n\n// A LoggingTransport is a [Transport] that delegates to another transport,\n// writing RPC logs to an io.Writer.\ntype LoggingTransport struct {\n\tdelegate Transport\n\tw        io.Writer\n}\n\n// NewLoggingTransport creates a new LoggingTransport that delegates to the\n// provided transport, writing RPC logs to the provided io.Writer.\nfunc NewLoggingTransport(delegate Transport, w io.Writer) *LoggingTransport {\n\treturn &LoggingTransport{delegate, w}\n}\n\n// Connect connects the underlying transport, returning a [Connection] that writes\n// logs to the configured destination.\nfunc (t *LoggingTransport) Connect(ctx context.Context) (Connection, error) {\n\tdelegate, err := t.delegate.Connect(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &loggingConn{delegate, t.w}, nil\n}\n\ntype loggingConn struct {\n\tdelegate Connection\n\tw        io.Writer\n}\n\n// loggingReader is a stream middleware that logs incoming messages.\nfunc (s *loggingConn) Read(ctx context.Context) (JSONRPCMessage, error) {\n\tmsg, err := s.delegate.Read(ctx)\n\tif err != nil {\n\t\tfmt.Fprintf(s.w, \"read error: %v\", err)\n\t} else {\n\t\tdata, err := jsonrpc2.EncodeMessage(msg)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(s.w, \"LoggingTransport: failed to marshal: %v\", err)\n\t\t}\n\t\tfmt.Fprintf(s.w, \"read: %s\\n\", string(data))\n\t}\n\treturn msg, err\n}\n\n// loggingWriter is a stream middleware that logs outgoing messages.\nfunc (s *loggingConn) Write(ctx context.Context, msg JSONRPCMessage) error {\n\terr := s.delegate.Write(ctx, msg)\n\tif err != nil {\n\t\tfmt.Fprintf(s.w, \"write error: %v\", err)\n\t} else {\n\t\tdata, err := jsonrpc2.EncodeMessage(msg)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(s.w, \"LoggingTransport: failed to marshal: %v\", err)\n\t\t}\n\t\tfmt.Fprintf(s.w, \"write: %s\\n\", string(data))\n\t}\n\treturn err\n}\n\nfunc (s *loggingConn) Close() error {\n\treturn s.delegate.Close()\n}\n\n// A rwc binds an io.ReadCloser and io.WriteCloser together to create an\n// io.ReadWriteCloser.\ntype rwc struct {\n\trc io.ReadCloser\n\twc io.WriteCloser\n}\n\nfunc (r rwc) Read(p []byte) (n int, err error) {\n\treturn r.rc.Read(p)\n}\n\nfunc (r rwc) Write(p []byte) (n int, err error) {\n\treturn r.wc.Write(p)\n}\n\nfunc (r rwc) Close() error {\n\treturn errors.Join(r.rc.Close(), r.wc.Close())\n}\n\n// An ioConn is a transport that delimits messages with newlines across\n// a bidirectional stream, and supports JSONRPC2 message batching.\n//\n// See https://github.com/ndjson/ndjson-spec for discussion of newline\n// delimited JSON.\n//\n// See [msgBatch] for more discussion of message batching.\ntype ioConn struct {\n\trwc io.ReadWriteCloser // the underlying stream\n\tin  *json.Decoder      // a decoder bound to rwc\n\n\t// If outgoiBatch has a positive capacity, it will be used to batch requests\n\t// and notifications before sending.\n\toutgoingBatch []JSONRPCMessage\n\n\t// Unread messages in the last batch. Since reads are serialized, there is no\n\t// need to guard here.\n\tqueue []JSONRPCMessage\n\n\t// batches correlate incoming requests to the batch in which they arrived.\n\t// Since writes may be concurrent to reads, we need to guard this with a mutex.\n\tbatchMu sync.Mutex\n\tbatches map[jsonrpc2.ID]*msgBatch // lazily allocated\n}\n\nfunc newIOConn(rwc io.ReadWriteCloser) *ioConn {\n\treturn &ioConn{\n\t\trwc: rwc,\n\t\tin:  json.NewDecoder(rwc),\n\t}\n}\n\n// addBatch records a msgBatch for an incoming batch payload.\n// It returns an error if batch is malformed, containing previously seen IDs.\n//\n// See [msgBatch] for more.\nfunc (t *ioConn) addBatch(batch *msgBatch) error {\n\tt.batchMu.Lock()\n\tdefer t.batchMu.Unlock()\n\tfor id := range batch.unresolved {\n\t\tif _, ok := t.batches[id]; ok {\n\t\t\treturn fmt.Errorf(\"%w: batch contains previously seen request %v\", jsonrpc2.ErrInvalidRequest, id.Raw())\n\t\t}\n\t}\n\tfor id := range batch.unresolved {\n\t\tif t.batches == nil {\n\t\t\tt.batches = make(map[jsonrpc2.ID]*msgBatch)\n\t\t}\n\t\tt.batches[id] = batch\n\t}\n\treturn nil\n}\n\n// updateBatch records a response in the message batch tracking the\n// corresponding incoming call, if any.\n//\n// The second result reports whether resp was part of a batch. If this is true,\n// the first result is nil if the batch is still incomplete, or the full set of\n// batch responses if resp completed the batch.\nfunc (t *ioConn) updateBatch(resp *JSONRPCResponse) ([]*JSONRPCResponse, bool) {\n\tt.batchMu.Lock()\n\tdefer t.batchMu.Unlock()\n\n\tif batch, ok := t.batches[resp.ID]; ok {\n\t\tidx, ok := batch.unresolved[resp.ID]\n\t\tif !ok {\n\t\t\tpanic(\"internal error: inconsistent batches\")\n\t\t}\n\t\tbatch.responses[idx] = resp\n\t\tdelete(batch.unresolved, resp.ID)\n\t\tdelete(t.batches, resp.ID)\n\t\tif len(batch.unresolved) == 0 {\n\t\t\treturn batch.responses, true\n\t\t}\n\t\treturn nil, true\n\t}\n\treturn nil, false\n}\n\n// A msgBatch records information about an incoming batch of JSONRPC2 calls.\n//\n// The JSONRPC2 spec (https://www.jsonrpc.org/specification#batch) says:\n//\n// \"The Server should respond with an Array containing the corresponding\n// Response objects, after all of the batch Request objects have been\n// processed. A Response object SHOULD exist for each Request object, except\n// that there SHOULD NOT be any Response objects for notifications. The Server\n// MAY process a batch rpc call as a set of concurrent tasks, processing them\n// in any order and with any width of parallelism.\"\n//\n// Therefore, a msgBatch keeps track of outstanding calls and their responses.\n// When there are no unresolved calls, the response payload is sent.\ntype msgBatch struct {\n\tunresolved map[jsonrpc2.ID]int\n\tresponses  []*JSONRPCResponse\n}\n\nfunc (t *ioConn) Read(ctx context.Context) (JSONRPCMessage, error) {\n\treturn t.read(ctx, t.in)\n}\n\nfunc (t *ioConn) read(ctx context.Context, in *json.Decoder) (JSONRPCMessage, error) {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tdefault:\n\t}\n\tif len(t.queue) > 0 {\n\t\tnext := t.queue[0]\n\t\tt.queue = t.queue[1:]\n\t\treturn next, nil\n\t}\n\n\tvar raw json.RawMessage\n\tif err := in.Decode(&raw); err != nil {\n\t\treturn nil, err\n\t}\n\tmsgs, batch, err := readBatch(raw)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tt.queue = msgs[1:]\n\n\tif batch {\n\t\tvar respBatch *msgBatch // track incoming requests in the batch\n\t\tfor _, msg := range msgs {\n\t\t\tif req, ok := msg.(*JSONRPCRequest); ok {\n\t\t\t\tif respBatch == nil {\n\t\t\t\t\trespBatch = &msgBatch{\n\t\t\t\t\t\tunresolved: make(map[jsonrpc2.ID]int),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif _, ok := respBatch.unresolved[req.ID]; ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"duplicate message ID %q\", req.ID)\n\t\t\t\t}\n\t\t\t\trespBatch.unresolved[req.ID] = len(respBatch.responses)\n\t\t\t\trespBatch.responses = append(respBatch.responses, nil)\n\t\t\t}\n\t\t}\n\t\tif respBatch != nil {\n\t\t\t// The batch contains one or more incoming requests to track.\n\t\t\tif err := t.addBatch(respBatch); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\treturn msgs[0], err\n}\n\n// readBatch reads batch data, which may be either a single JSON-RPC message,\n// or an array of JSON-RPC messages.\nfunc readBatch(data []byte) (msgs []JSONRPCMessage, isBatch bool, _ error) {\n\t// Try to read an array of messages first.\n\tvar rawBatch []json.RawMessage\n\tif err := json.Unmarshal(data, &rawBatch); err == nil {\n\t\tif len(rawBatch) == 0 {\n\t\t\treturn nil, true, fmt.Errorf(\"empty batch\")\n\t\t}\n\t\tfor _, raw := range rawBatch {\n\t\t\tmsg, err := jsonrpc2.DecodeMessage(raw)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, true, err\n\t\t\t}\n\t\t\tmsgs = append(msgs, msg)\n\t\t}\n\t\treturn msgs, true, nil\n\t}\n\t// Try again with a single message.\n\tmsg, err := jsonrpc2.DecodeMessage(data)\n\treturn []JSONRPCMessage{msg}, false, err\n}\n\nfunc (t *ioConn) Write(ctx context.Context, msg JSONRPCMessage) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tdefault:\n\t}\n\n\t// Batching support: if msg is a Response, it may have completed a batch, so\n\t// check that first. Otherwise, it is a request or notification, and we may\n\t// want to collect it into a batch before sending, if we're configured to use\n\t// outgoing batches.\n\tif resp, ok := msg.(*JSONRPCResponse); ok {\n\t\tif batch, ok := t.updateBatch(resp); ok {\n\t\t\tif len(batch) > 0 {\n\t\t\t\tdata, err := marshalMessages(batch)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdata = append(data, '\\n')\n\t\t\t\t_, err = t.rwc.Write(data)\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t} else if len(t.outgoingBatch) < cap(t.outgoingBatch) {\n\t\tt.outgoingBatch = append(t.outgoingBatch, msg)\n\t\tif len(t.outgoingBatch) == cap(t.outgoingBatch) {\n\t\t\tdata, err := marshalMessages(t.outgoingBatch)\n\t\t\tt.outgoingBatch = t.outgoingBatch[:0]\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdata = append(data, '\\n')\n\t\t\t_, err = t.rwc.Write(data)\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n\tdata, err := jsonrpc2.EncodeMessage(msg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling message: %v\", err)\n\t}\n\tdata = append(data, '\\n') // newline delimited\n\t_, err = t.rwc.Write(data)\n\treturn err\n}\n\nfunc (t *ioConn) Close() error {\n\treturn t.rwc.Close()\n}\n\nfunc marshalMessages[T JSONRPCMessage](msgs []T) ([]byte, error) {\n\tvar rawMsgs []json.RawMessage\n\tfor _, msg := range msgs {\n\t\traw, err := jsonrpc2.EncodeMessage(msg)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"encoding batch message: %w\", err)\n\t\t}\n\t\trawMsgs = append(rawMsgs, raw)\n\t}\n\treturn json.Marshal(rawMsgs)\n}\n"
  },
  {
    "path": "internal/mcp/transport_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"testing\"\n\n\tjsonrpc2 \"golang.org/x/tools/internal/jsonrpc2_v2\"\n)\n\nfunc TestBatchFraming(t *testing.T) {\n\t// This test checks that the ndjsonFramer can read and write JSON batches.\n\t//\n\t// The framer is configured to write a batch size of 2, and we confirm that\n\t// nothing is sent over the wire until the second write, at which point both\n\t// messages become available.\n\tctx := context.Background()\n\n\tr, w := io.Pipe()\n\ttport := newIOConn(rwc{r, w})\n\ttport.outgoingBatch = make([]JSONRPCMessage, 0, 2)\n\n\t// Read the two messages into a channel, for easy testing later.\n\tread := make(chan JSONRPCMessage)\n\tgo func() {\n\t\tfor range 2 {\n\t\t\tmsg, _ := tport.Read(ctx)\n\t\t\tread <- msg\n\t\t}\n\t}()\n\n\t// The first write should not yet be observed by the reader.\n\ttport.Write(ctx, &JSONRPCRequest{ID: jsonrpc2.Int64ID(1), Method: \"test\"})\n\tselect {\n\tcase got := <-read:\n\t\tt.Fatalf(\"after one write, got message %v\", got)\n\tdefault:\n\t}\n\n\t// ...but the second write causes both messages to be observed.\n\ttport.Write(ctx, &JSONRPCRequest{ID: jsonrpc2.Int64ID(2), Method: \"test\"})\n\tfor _, want := range []int64{1, 2} {\n\t\tgot := <-read\n\t\tif got := got.(*JSONRPCRequest).ID.Raw(); got != want {\n\t\t\tt.Errorf(\"got message #%d, want #%d\", got, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/mcp/util.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/internal/mcp/internal/util\"\n)\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n\n// marshalStructWithMap marshals its first argument to JSON, treating the field named\n// mapField as an embedded map. The first argument must be a pointer to\n// a struct. The underlying type of mapField must be a map[string]any, and it must have\n// an \"omitempty\" json tag.\n//\n// For example, given this struct:\n//\n//\ttype S struct {\n//\t   A int\n//\t   Extra map[string] any `json:,omitempty`\n//\t}\n//\n// and this value:\n//\n//\ts := S{A: 1, Extra: map[string]any{\"B\": 2}}\n//\n// the call marshalJSONWithMap(s, \"Extra\") would return\n//\n//\t{\"A\": 1, \"B\": 2}\n//\n// It is an error if the map contains the same key as another struct field's\n// JSON name.\n//\n// marshalStructWithMap calls json.Marshal on a value of type T, so T must not\n// have a MarshalJSON method that calls this function, on pain of infinite regress.\n//\n// TODO: avoid this restriction on T by forcing it to marshal in a default way.\n// See https://go.dev/play/p/EgXKJHxEx_R.\nfunc marshalStructWithMap[T any](s *T, mapField string) ([]byte, error) {\n\t// Marshal the struct and the map separately, and concatenate the bytes.\n\t// This strategy is dramatically less complicated than\n\t// constructing a synthetic struct or map with the combined keys.\n\tif s == nil {\n\t\treturn []byte(\"null\"), nil\n\t}\n\ts2 := *s\n\tvMapField := reflect.ValueOf(&s2).Elem().FieldByName(mapField)\n\tmapVal := vMapField.Interface().(map[string]any)\n\n\t// Check for duplicates.\n\tnames := jsonNames(reflect.TypeFor[T]())\n\tfor key := range mapVal {\n\t\tif names[key] {\n\t\t\treturn nil, fmt.Errorf(\"map key %q duplicates struct field\", key)\n\t\t}\n\t}\n\n\t// Clear the map field, relying on the omitempty tag to omit it.\n\tvMapField.Set(reflect.Zero(vMapField.Type()))\n\tstructBytes, err := json.Marshal(s2)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshalStructWithMap(%+v): %w\", s, err)\n\t}\n\tif len(mapVal) == 0 {\n\t\treturn structBytes, nil\n\t}\n\tmapBytes, err := json.Marshal(mapVal)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(structBytes) == 2 { // must be \"{}\"\n\t\treturn mapBytes, nil\n\t}\n\t// \"{X}\" + \"{Y}\" => \"{X,Y}\"\n\tres := append(structBytes[:len(structBytes)-1], ',')\n\tres = append(res, mapBytes[1:]...)\n\treturn res, nil\n}\n\n// unmarshalStructWithMap is the inverse of marshalStructWithMap.\n// T has the same restrictions as in that function.\nfunc unmarshalStructWithMap[T any](data []byte, v *T, mapField string) error {\n\t// Unmarshal into the struct, ignoring unknown fields.\n\tif err := json.Unmarshal(data, v); err != nil {\n\t\treturn err\n\t}\n\t// Unmarshal into the map.\n\tm := map[string]any{}\n\tif err := json.Unmarshal(data, &m); err != nil {\n\t\treturn err\n\t}\n\t// Delete from the map the fields of the struct.\n\tfor n := range jsonNames(reflect.TypeFor[T]()) {\n\t\tdelete(m, n)\n\t}\n\tif len(m) != 0 {\n\t\treflect.ValueOf(v).Elem().FieldByName(mapField).Set(reflect.ValueOf(m))\n\t}\n\treturn nil\n}\n\nvar jsonNamesMap sync.Map // from reflect.Type to map[string]bool\n\n// jsonNames returns the set of JSON object keys that t will marshal into.\n// t must be a struct type.\nfunc jsonNames(t reflect.Type) map[string]bool {\n\t// Lock not necessary: at worst we'll duplicate work.\n\tif val, ok := jsonNamesMap.Load(t); ok {\n\t\treturn val.(map[string]bool)\n\t}\n\tm := map[string]bool{}\n\tfor i := range t.NumField() {\n\t\tinfo := util.FieldJSONInfo(t.Field(i))\n\t\tif !info.Omit {\n\t\t\tm[info.Name] = true\n\t\t}\n\t}\n\tjsonNamesMap.Store(t, m)\n\treturn m\n}\n"
  },
  {
    "path": "internal/mcp/util_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mcp\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmpopts\"\n)\n\nfunc TestMarshalStructWithMap(t *testing.T) {\n\ttype S struct {\n\t\tA int\n\t\tB string `json:\"b,omitempty\"`\n\t\tu bool\n\t\tM map[string]any `json:\",omitempty\"`\n\t}\n\tt.Run(\"basic\", func(t *testing.T) {\n\t\ts := S{A: 1, B: \"two\", M: map[string]any{\"!@#\": true}}\n\t\tgot, err := marshalStructWithMap(&s, \"M\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twant := `{\"A\":1,\"b\":\"two\",\"!@#\":true}`\n\t\tif g := string(got); g != want {\n\t\t\tt.Errorf(\"\\ngot  %s\\nwant %s\", g, want)\n\t\t}\n\n\t\tvar un S\n\t\tif err := unmarshalStructWithMap(got, &un, \"M\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif diff := cmp.Diff(s, un, cmpopts.IgnoreUnexported(S{})); diff != \"\" {\n\t\t\tt.Errorf(\"mismatch (-want, +got):\\n%s\", diff)\n\t\t}\n\t})\n\tt.Run(\"duplicate\", func(t *testing.T) {\n\t\ts := S{A: 1, B: \"two\", M: map[string]any{\"b\": \"dup\"}}\n\t\t_, err := marshalStructWithMap(&s, \"M\")\n\t\tif err == nil || !strings.Contains(err.Error(), \"duplicate\") {\n\t\t\tt.Errorf(\"got %v, want error with 'duplicate'\", err)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "internal/modindex/dir_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\n\t. \"golang.org/x/tools/internal/modindex\"\n)\n\ntype id struct {\n\timportPath string\n\tbest       int // which of the dirs is the one that should have been chosen\n\tdirs       []string\n}\n\nvar idtests = []id{\n\t{ // get one right\n\t\timportPath: \"cloud.google.com/go/longrunning\",\n\t\tbest:       2,\n\t\tdirs: []string{\n\t\t\t\"cloud.google.com/go/longrunning@v0.3.0\",\n\t\t\t\"cloud.google.com/go/longrunning@v0.4.1\",\n\t\t\t\"cloud.google.com/go@v0.104.0/longrunning\",\n\t\t\t\"cloud.google.com/go@v0.94.0/longrunning\",\n\t\t},\n\t},\n\t{ // make sure we can run more than one test\n\t\timportPath: \"cloud.google.com/go/compute/metadata\",\n\t\tbest:       2,\n\t\tdirs: []string{\n\t\t\t\"cloud.google.com/go/compute/metadata@v0.2.1\",\n\t\t\t\"cloud.google.com/go/compute/metadata@v0.2.3\",\n\t\t\t\"cloud.google.com/go/compute@v1.7.0/metadata\",\n\t\t\t\"cloud.google.com/go@v0.94.0/compute/metadata\",\n\t\t},\n\t},\n\t{ // test bizarre characters in directory name\n\t\timportPath: \"bad,guy.com/go\",\n\t\tbest:       0,\n\t\tdirs:       []string{\"bad,guy.com/go@v0.1.0\"},\n\t},\n}\n\nfunc testModCache(t *testing.T) string {\n\tIndexDir = t.TempDir()\n\treturn IndexDir\n}\n\n// add a trivial package to the test module cache\nfunc addPkg(gomodcache, dir string) error {\n\tif err := os.MkdirAll(filepath.Join(gomodcache, dir), 0755); err != nil {\n\t\treturn err\n\t}\n\treturn os.WriteFile(filepath.Join(gomodcache, dir, \"foo.go\"),\n\t\t[]byte(\"package foo\\nfunc Foo() {}\"), 0644)\n}\n\n// update, where new stuff is semantically better than old stuff\nfunc TestIncremental(t *testing.T) {\n\tdir := testModCache(t)\n\t// build old index\n\tfor _, it := range idtests {\n\t\tfor i, d := range it.dirs {\n\t\t\tif it.best == i {\n\t\t\t\tcontinue // wait for second pass\n\t\t\t}\n\t\t\tif err := addPkg(dir, d); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t}\n\t}\n\tindex0, err := Create(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// add new stuff to the module cache\n\tfor _, it := range idtests {\n\t\tfor i, d := range it.dirs {\n\t\t\tif it.best != i {\n\t\t\t\tcontinue // only add the new stuff\n\t\t\t}\n\t\t\tif err := addPkg(dir, d); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t}\n\t}\n\tif index1, err := Update(dir); err != nil {\n\t\tt.Fatalf(\"failed to update index: %v\", err)\n\t} else if len(index1.Entries) <= len(index0.Entries) {\n\t\tt.Fatalf(\"updated index is not larger: %v\", err)\n\t}\n\tindex2, err := Read(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// build a fresh index\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tindex1, err := Read(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// they should be the same except maybe for the time\n\tindex1.ValidAt = index2.ValidAt\n\tif diff := cmp.Diff(index1, index2); diff != \"\" {\n\t\tt.Errorf(\"mismatching indexes (-updated +cleared):\\n%s\", diff)\n\t}\n}\n\n// update, where new stuff is semantically worse than some old stuff\nfunc TestIncrementalNope(t *testing.T) {\n\tdir := testModCache(t)\n\t// build old index\n\tfor _, it := range idtests {\n\t\tfor i, d := range it.dirs {\n\t\t\tif i == 0 {\n\t\t\t\tcontinue // wait for second pass\n\t\t\t}\n\t\t\tif err := addPkg(dir, d); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t}\n\t}\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// add new stuff to the module cache\n\tfor _, it := range idtests {\n\t\tfor i, d := range it.dirs {\n\t\t\tif i > 0 {\n\t\t\t\tbreak // only add the new one\n\t\t\t}\n\t\t\tif err := addPkg(dir, d); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t}\n\t}\n\tindex2, err := Update(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// build a fresh index\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tindex1, err := Read(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// they should be the same except maybe for the time\n\tindex1.ValidAt = index2.ValidAt\n\tif diff := cmp.Diff(index1, index2); diff != \"\" {\n\t\tt.Errorf(\"mismatching indexes (-updated +cleared):\\n%s\", diff)\n\t}\n}\n\n// choose the semantically-latest version, with a single symbol\nfunc TestDirsSinglePath(t *testing.T) {\n\tfor _, itest := range idtests {\n\t\tt.Run(itest.importPath, func(t *testing.T) {\n\t\t\t// create a new test GOMODCACHE\n\t\t\tdir := testModCache(t)\n\t\t\tfor _, d := range itest.dirs {\n\t\t\t\tif err := addPkg(dir, d); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// build and check the index\n\t\t\tif _, err := Create(dir); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tix, err := Read(dir)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(ix.Entries) != 1 {\n\t\t\t\tt.Fatalf(\"got %d entries, wanted 1\", len(ix.Entries))\n\t\t\t}\n\t\t\tif ix.Entries[0].ImportPath != itest.importPath {\n\t\t\t\tt.Fatalf(\"got %s import path, wanted %s\", ix.Entries[0].ImportPath, itest.importPath)\n\t\t\t}\n\t\t\tgotDir := filepath.ToSlash(ix.Entries[0].Dir)\n\t\t\tif gotDir != itest.dirs[itest.best] {\n\t\t\t\tt.Fatalf(\"got dir %s, wanted %s\", gotDir, itest.dirs[itest.best])\n\t\t\t}\n\t\t\tnms := ix.Entries[0].Names\n\t\t\tif len(nms) != 1 {\n\t\t\t\tt.Fatalf(\"got %d names, expected 1\", len(nms))\n\t\t\t}\n\t\t\tif nms[0] != \"Foo F 0\" {\n\t\t\t\tt.Fatalf(\"got %q, expected Foo F 0\", nms[0])\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMissingGOMODCACHE(t *testing.T) {\n\t// behave properly if the cached dir is empty\n\tdir := testModCache(t)\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdes, err := os.ReadDir(IndexDir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(des) != 2 {\n\t\tt.Errorf(\"got %d, but expected two entries in index dir\", len(des))\n\t}\n}\n\nfunc TestMissingIndex(t *testing.T) {\n\t// behave properly if there is no existing index\n\tdir := testModCache(t)\n\tif _, err := Update(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdes, err := os.ReadDir(IndexDir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(des) != 2 {\n\t\tt.Errorf(\"got %d, but expected two entries in index dir\", len(des))\n\t}\n}\n"
  },
  {
    "path": "internal/modindex/directories.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/mod/semver\"\n\t\"golang.org/x/tools/internal/gopathwalk\"\n)\n\ntype directory struct {\n\tpath       string // relative to GOMODCACHE\n\timportPath string\n\tversion    string // semantic version\n}\n\n// bestDirByImportPath returns the best directory for each import\n// path, where \"best\" means most recent semantic version. These import\n// paths are inferred from the GOMODCACHE-relative dir names in dirs.\nfunc bestDirByImportPath(dirs []string) (map[string]directory, error) {\n\tdirsByPath := make(map[string]directory)\n\tfor _, dir := range dirs {\n\t\timportPath, version, err := dirToImportPathVersion(dir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tnew := directory{\n\t\t\tpath:       dir,\n\t\t\timportPath: importPath,\n\t\t\tversion:    version,\n\t\t}\n\t\tif old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 {\n\t\t\tdirsByPath[importPath] = new\n\t\t}\n\t}\n\treturn dirsByPath, nil\n}\n\n// compareDirectory defines an ordering of path@version directories,\n// by descending version, then by ascending path.\nfunc compareDirectory(x, y directory) int {\n\tif sign := -semver.Compare(x.version, y.version); sign != 0 {\n\t\treturn sign // latest first\n\t}\n\treturn strings.Compare(string(x.path), string(y.path))\n}\n\n// modCacheRegexp splits a relpathpath into module, module version, and package.\nvar modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\\\]*)(.*)`)\n\n// dirToImportPathVersion computes import path and semantic version\n// from a GOMODCACHE-relative directory name.\nfunc dirToImportPathVersion(dir string) (string, string, error) {\n\tm := modCacheRegexp.FindStringSubmatch(string(dir))\n\t// m[1] is the module path\n\t// m[2] is the version major.minor.patch(-<pre release identifier)\n\t// m[3] is the rest of the package path\n\tif len(m) != 4 {\n\t\treturn \"\", \"\", fmt.Errorf(\"bad dir %s\", dir)\n\t}\n\tif !semver.IsValid(m[2]) {\n\t\treturn \"\", \"\", fmt.Errorf(\"bad semantic version %s\", m[2])\n\t}\n\t// ToSlash is required to convert Windows file paths\n\t// into Go package import paths.\n\treturn filepath.ToSlash(m[1] + m[3]), m[2], nil\n}\n\n// findDirs returns an unordered list of relevant package directories,\n// relative to the specified module cache root. The result includes only\n// module dirs whose mtime is within (start, end).\nfunc findDirs(root string, start, end time.Time) []string {\n\tvar (\n\t\tresMu sync.Mutex\n\t\tres   []string\n\t)\n\n\taddDir := func(root gopathwalk.Root, dir string) {\n\t\t// TODO(pjw): do we need to check times?\n\t\tresMu.Lock()\n\t\tdefer resMu.Unlock()\n\t\tres = append(res, relative(root.Path, dir))\n\t}\n\n\tskipDir := func(_ gopathwalk.Root, dir string) bool {\n\t\t// The cache directory is already ignored in gopathwalk.\n\t\tif filepath.Base(dir) == \"internal\" {\n\t\t\treturn true\n\t\t}\n\n\t\t// Skip toolchains.\n\t\tif strings.Contains(dir, \"toolchain@\") {\n\t\t\treturn true\n\t\t}\n\n\t\t// Don't look inside @ directories that are too old/new.\n\t\tif strings.Contains(filepath.Base(dir), \"@\") {\n\t\t\tst, err := os.Stat(dir)\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"can't stat dir %s %v\", dir, err)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tmtime := st.ModTime()\n\t\t\treturn mtime.Before(start) || mtime.After(end)\n\t\t}\n\n\t\treturn false\n\t}\n\n\t// TODO(adonovan): parallelize this. Even with a hot buffer cache,\n\t//   find $(go env GOMODCACHE) -type d\n\t// can easily take up a minute.\n\troots := []gopathwalk.Root{{Path: root, Type: gopathwalk.RootModuleCache}}\n\tgopathwalk.WalkSkip(roots, addDir, skipDir, gopathwalk.Options{\n\t\tModulesEnabled: true,\n\t\tConcurrency:    1, // TODO(pjw): adjust concurrency\n\t\t// Logf: log.Printf,\n\t})\n\n\treturn res\n}\n"
  },
  {
    "path": "internal/modindex/export_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex\n\n// backdoors for tests\n\nvar Uniquify = uniquify\n\n// Create always creates a new index for the\n// specified Go module cache directory.\n// On success it returns the current index.\nfunc Create(gomodcache string) (*Index, error) {\n\treturn update(gomodcache, nil)\n}\n"
  },
  {
    "path": "internal/modindex/gomodindex/cmd.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// A command for building and maintaining the module cache\n// a.out <flags> <command> <args>\n// The commands are:\n// 'update', which attempts to update an existing index,\n// 'query', which looks up things in the index.\n// 'clean', which remove obsolete index files.\n// If the command is invoked with no arguments, it defaults to 'update'.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/modindex\"\n)\n\nvar verbose = flag.Int(\"v\", 0, \"how much information to print\")\n\ntype cmd struct {\n\tname string\n\tf    func(string)\n\tdoc  string\n}\n\nvar cmds = []cmd{\n\t{\"update\", update, \"if there is an existing index of GOMODCACHE, update it. Otherwise create one.\"},\n\t{\"clean\", clean, \"removed unreferenced indexes more than an hour old\"},\n\t{\"query\", query, \"not yet implemented\"},\n}\n\nfunc goEnv(s string) string {\n\tout, err := exec.Command(\"go\", \"env\", s).Output()\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\tout = bytes.TrimSpace(out)\n\treturn string(out)\n}\n\nfunc main() {\n\tflag.Parse()\n\tlog.SetFlags(log.Lshortfile)\n\tgomodcache := goEnv(\"GOMODCACHE\")\n\tif gomodcache == \"\" {\n\t\tlog.Fatal(\"can't find GOMODCACHE\")\n\t}\n\tif flag.NArg() == 0 {\n\t\tupdate(gomodcache)\n\t\treturn\n\t}\n\tfor _, c := range cmds {\n\t\tif flag.Arg(0) == c.name {\n\t\t\tc.f(gomodcache)\n\t\t\treturn\n\t\t}\n\t}\n\tflag.Usage()\n}\n\nfunc init() {\n\tvar sb strings.Builder\n\tfmt.Fprintf(&sb, \"usage:\\n\")\n\tfor _, c := range cmds {\n\t\tfmt.Fprintf(&sb, \"'%s': %s\\n\", c.name, c.doc)\n\t}\n\tmsg := sb.String()\n\tflag.Usage = func() {\n\t\tfmt.Fprint(os.Stderr, msg)\n\t}\n}\n\nfunc update(dir string) {\n\tif _, err := modindex.Update(dir); err != nil {\n\t\tlog.Print(err)\n\t}\n}\n\nfunc query(dir string) {\n\tpanic(\"implement\")\n}\n\nfunc clean(_ string) {\n\tdes := modindex.IndexDir\n\t// look at the files starting with 'index'\n\t// the current ones of each version are pointed to by\n\t// index-name-%d files. Any others more than an hour old\n\t// are deleted.\n\tdis, err := os.ReadDir(des)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tcutoff := time.Now().Add(-time.Hour)\n\tvar inames []string               // older files named index*\n\tcurnames := make(map[string]bool) // current versions of index (different CurrentVersion)\n\tfor _, de := range dis {\n\t\tif !strings.HasPrefix(de.Name(), \"index\") {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(de.Name(), \"index-name-\") {\n\t\t\tbuf, err := os.ReadFile(filepath.Join(des, de.Name()))\n\t\t\tif err != nil {\n\t\t\t\tlog.Print(err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcurnames[string(buf)] = true\n\t\t\tif *verbose > 1 {\n\t\t\t\tlog.Printf(\"latest index is %s\", string(buf))\n\t\t\t}\n\t\t}\n\t\tinfo, err := de.Info()\n\t\tif err != nil {\n\t\t\tlog.Print(err)\n\t\t\tcontinue\n\t\t}\n\t\tif info.ModTime().Before(cutoff) && !strings.HasPrefix(de.Name(), \"index-name-\") {\n\t\t\t// add to the list of files to be removed. index-name-%d files are never removed\n\t\t\tinames = append(inames, de.Name())\n\t\t\tif *verbose > 0 {\n\t\t\t\tlog.Printf(\"%s:%s\", de.Name(), cutoff.Sub(info.ModTime()))\n\t\t\t}\n\t\t}\n\t}\n\tfor _, nm := range inames {\n\t\tif curnames[nm] {\n\t\t\tcontinue\n\t\t}\n\t\terr := os.Remove(filepath.Join(des, nm))\n\t\tif err != nil && *verbose > 0 {\n\t\t\tlog.Printf(\"%s not removed (%v)\", nm, err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/modindex/index.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex\n\nimport (\n\t\"bufio\"\n\t\"crypto/sha256\"\n\t\"encoding/csv\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\n/*\nThe on-disk index (\"payload\") is a text file.\nThe first 3 lines are header information containing CurrentVersion,\nthe value of GOMODCACHE, and the validity date of the index.\n(This is when the code started building the index.)\nFollowing the header are sections of lines, one section for each\nimport path. These sections are sorted by package name.\nThe first line of each section, marked by a leading :, contains\nthe package name, the import path, the name of the directory relative\nto GOMODCACHE, and its semantic version.\nThe rest of each section consists of one line per exported symbol.\nThe lines are sorted by the symbol's name and contain the name,\nan indication of its lexical type (C, T, V, F), and if it is the\nname of a function, information about the signature.\n\nThe fields in the section header lines are separated by commas, and\nin the unlikely event this would be confusing, the csv package is used\nto write (and read) them.\n\nIn the lines containing exported names, C=const, V=var, T=type, F=func.\nIf it is a func, the next field is the number of returned values,\nfollowed by pairs consisting of formal parameter names and types.\nAll these fields are separated by spaces. Any spaces in a type\n(e.g., chan struct{}) are replaced by $s on the disk. The $s are\nturned back into spaces when read.\n\nHere is an index header (the comments are not part of the index):\n0                                      // version (of the index format)\n/usr/local/google/home/pjw/go/pkg/mod  // GOMODCACHE\n2024-09-11 18:55:09                    // validity date of the index\n\nHere is an index section:\n:yaml,gopkg.in/yaml.v1,gopkg.in/yaml.v1@v1.0.0-20140924161607-9f9df34309c0,v1.0.0-20140924161607-9f9df34309c0\nGetter T\nMarshal F 2 in interface{}\nSetter T\nUnmarshal F 1 in []byte out interface{}\n\nThe package name is yaml, the import path is gopkg.in/yaml.v1.\nGetter and Setter are types, and Marshal and Unmarshal are functions.\nThe latter returns one value and has two arguments, 'in' and 'out'\nwhose types are []byte and interface{}.\n*/\n\n// CurrentVersion tells readers about the format of the index.\nconst CurrentVersion int = 0\n\n// Index is returned by [Read].\ntype Index struct {\n\tVersion    int\n\tGOMODCACHE string    // absolute path of Go module cache dir\n\tValidAt    time.Time // moment at which the index was up to date\n\tEntries    []Entry\n}\n\nfunc (ix *Index) String() string {\n\treturn fmt.Sprintf(\"Index(%s v%d has %d entries at %v)\",\n\t\tix.GOMODCACHE, ix.Version, len(ix.Entries), ix.ValidAt)\n}\n\n// An Entry contains information for an import path.\ntype Entry struct {\n\tDir        string // package directory relative to GOMODCACHE; uses OS path separator\n\tImportPath string\n\tPkgName    string\n\tVersion    string\n\tNames      []string // exported names and information\n}\n\n// IndexDir is where the module index is stored.\n// Each logical index entry consists of a pair of files:\n//\n//   - the \"payload\" (index-VERSION-XXX), whose name is\n//     randomized, holds the actual index; and\n//   - the \"link\" (index-name-VERSION-HASH),\n//     whose name is predictable, contains the\n//     name of the payload file.\n//\n// Since the link file is small (<512B),\n// reads and writes to it may be assumed atomic.\nvar IndexDir string = func() string {\n\tvar dir string\n\tif testing.Testing() {\n\t\tdir = os.TempDir()\n\t} else {\n\t\tvar err error\n\t\tdir, err = os.UserCacheDir()\n\t\t// shouldn't happen, but TempDir is better than\n\t\t// creating ./goimports\n\t\tif err != nil {\n\t\t\tdir = os.TempDir()\n\t\t}\n\t}\n\tdir = filepath.Join(dir, \"goimports\")\n\tif err := os.MkdirAll(dir, 0777); err != nil {\n\t\tdir = \"\" // #75505, people complain about the error message\n\t}\n\treturn dir\n}()\n\n// Read reads the latest version of the on-disk index\n// for the specified Go module cache directory.\n// If there is no index, it returns a nil Index and an fs.ErrNotExist error.\nfunc Read(gomodcache string) (*Index, error) {\n\tgomodcache, err := filepath.Abs(gomodcache)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif IndexDir == \"\" {\n\t\treturn nil, os.ErrNotExist\n\t}\n\n\t// Read the \"link\" file for the specified gomodcache directory.\n\t// It names the payload file.\n\tcontent, err := os.ReadFile(filepath.Join(IndexDir, linkFileBasename(gomodcache)))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpayloadFile := filepath.Join(IndexDir, string(content))\n\n\t// Read the index out of the payload file.\n\tf, err := os.Open(payloadFile)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\treturn readIndexFrom(gomodcache, bufio.NewReader(f))\n}\n\nfunc readIndexFrom(gomodcache string, r io.Reader) (*Index, error) {\n\tscan := bufio.NewScanner(r)\n\n\t// version\n\tif !scan.Scan() {\n\t\treturn nil, fmt.Errorf(\"unexpected scan error: %v\", scan.Err())\n\t}\n\tversion, err := strconv.Atoi(scan.Text())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif version != CurrentVersion {\n\t\treturn nil, fmt.Errorf(\"got version %d, expected %d\", version, CurrentVersion)\n\t}\n\n\t// gomodcache\n\tif !scan.Scan() {\n\t\treturn nil, fmt.Errorf(\"scanner error reading module cache dir: %v\", scan.Err())\n\t}\n\t// TODO(pjw): need to check that this is the expected cache dir\n\t// so the tag should be passed in to this function\n\tif dir := string(scan.Text()); dir != gomodcache {\n\t\treturn nil, fmt.Errorf(\"index file GOMODCACHE mismatch: got %q, want %q\", dir, gomodcache)\n\t}\n\n\t// changed\n\tif !scan.Scan() {\n\t\treturn nil, fmt.Errorf(\"scanner error reading index creation time: %v\", scan.Err())\n\t}\n\tchanged, err := time.ParseInLocation(time.DateTime, scan.Text(), time.Local)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// entries\n\tvar (\n\t\tcurEntry *Entry\n\t\tentries  []Entry\n\t)\n\tfor scan.Scan() {\n\t\tv := scan.Text()\n\t\tif v[0] == ':' {\n\t\t\tif curEntry != nil {\n\t\t\t\tentries = append(entries, *curEntry)\n\t\t\t}\n\t\t\t// as directories may contain commas and quotes, they need to be read as csv.\n\t\t\trdr := strings.NewReader(v[1:])\n\t\t\tcs := csv.NewReader(rdr)\n\t\t\tflds, err := cs.Read()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif len(flds) != 4 {\n\t\t\t\treturn nil, fmt.Errorf(\"header contains %d fields, not 4: %q\", len(v), v)\n\t\t\t}\n\t\t\tcurEntry = &Entry{\n\t\t\t\tPkgName:    flds[0],\n\t\t\t\tImportPath: flds[1],\n\t\t\t\tDir:        relative(gomodcache, flds[2]),\n\t\t\t\tVersion:    flds[3],\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tcurEntry.Names = append(curEntry.Names, v)\n\t}\n\tif err := scan.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"scanner failed while reading modindex entry: %v\", err)\n\t}\n\tif curEntry != nil {\n\t\tentries = append(entries, *curEntry)\n\t}\n\n\treturn &Index{\n\t\tVersion:    version,\n\t\tGOMODCACHE: gomodcache,\n\t\tValidAt:    changed,\n\t\tEntries:    entries,\n\t}, nil\n}\n\n// write writes the index file and updates the index directory to refer to it.\nfunc write(gomodcache string, ix *Index) error {\n\tif IndexDir == \"\" {\n\t\treturn os.ErrNotExist\n\t}\n\t// Write the index into a payload file with a fresh name.\n\tf, err := os.CreateTemp(IndexDir, fmt.Sprintf(\"index-%d-*\", CurrentVersion))\n\tif err != nil {\n\t\treturn err // e.g. disk full, or index dir deleted\n\t}\n\tif err := writeIndexToFile(ix, bufio.NewWriter(f)); err != nil {\n\t\t_ = f.Close() // ignore error\n\t\treturn err\n\t}\n\tif err := f.Close(); err != nil {\n\t\treturn err\n\t}\n\n\t// Write the name of the payload file into a link file.\n\tindexDirFile := filepath.Join(IndexDir, linkFileBasename(gomodcache))\n\tcontent := []byte(filepath.Base(f.Name()))\n\treturn os.WriteFile(indexDirFile, content, 0666)\n}\n\nfunc writeIndexToFile(x *Index, w *bufio.Writer) error {\n\tfmt.Fprintf(w, \"%d\\n\", x.Version)\n\tfmt.Fprintf(w, \"%s\\n\", x.GOMODCACHE)\n\ttm := x.ValidAt.Truncate(time.Second) // round the time down\n\tfmt.Fprintf(w, \"%s\\n\", tm.Format(time.DateTime))\n\tfor _, e := range x.Entries {\n\t\tif e.ImportPath == \"\" {\n\t\t\tcontinue // shouldn't happen\n\t\t}\n\t\t// PJW: maybe always write these headers as csv?\n\t\tif strings.ContainsAny(string(e.Dir), \",\\\"\") {\n\t\t\tcw := csv.NewWriter(w)\n\t\t\tcw.Write([]string{\":\" + e.PkgName, e.ImportPath, string(e.Dir), e.Version})\n\t\t\tcw.Flush()\n\t\t} else {\n\t\t\tfmt.Fprintf(w, \":%s,%s,%s,%s\\n\", e.PkgName, e.ImportPath, e.Dir, e.Version)\n\t\t}\n\t\tfor _, x := range e.Names {\n\t\t\tfmt.Fprintf(w, \"%s\\n\", x)\n\t\t}\n\t}\n\treturn w.Flush()\n}\n\n// linkFileBasename returns the base name of the link file in the\n// index directory that holds the name of the payload file for the\n// specified (absolute) Go module cache dir.\nfunc linkFileBasename(gomodcache string) string {\n\t// Note: coupled to logic in ./gomodindex/cmd.go. TODO: factor.\n\th := sha256.Sum256([]byte(gomodcache)) // collision-resistant hash\n\treturn fmt.Sprintf(\"index-name-%d-%032x\", CurrentVersion, h)\n}\n\nfunc relative(base, file string) string {\n\tif rel, err := filepath.Rel(base, file); err == nil {\n\t\treturn rel\n\t}\n\treturn file\n}\n"
  },
  {
    "path": "internal/modindex/lookup.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex\n\nimport (\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/mod/module\"\n)\n\ntype Candidate struct {\n\tPkgName    string\n\tName       string\n\tDir        string\n\tImportPath string\n\tType       LexType\n\tDeprecated bool\n\t// information for Funcs\n\tResults int16   // how many results\n\tSig     []Field // arg names and types\n}\n\ntype Field struct {\n\tArg, Type string\n}\n\ntype LexType int8\n\nconst (\n\tConst LexType = iota\n\tVar\n\tType\n\tFunc\n)\n\n// LookupAll only returns those Candidates whose import path\n// finds all the names.\nfunc (ix *Index) LookupAll(pkgName string, names ...string) map[string][]Candidate {\n\t// this can be made faster when benchmarks show that it needs to be\n\tnames = uniquify(names)\n\tbyImpPath := make(map[string][]Candidate)\n\tfor _, nm := range names {\n\t\tcands := ix.Lookup(pkgName, nm, false)\n\t\tfor _, c := range cands {\n\t\t\tbyImpPath[c.ImportPath] = append(byImpPath[c.ImportPath], c)\n\t\t}\n\t}\n\tfor k, v := range byImpPath {\n\t\tif len(v) != len(names) {\n\t\t\tdelete(byImpPath, k)\n\t\t}\n\t}\n\treturn byImpPath\n}\n\n// remove duplicates\nfunc uniquify(in []string) []string {\n\tif len(in) == 0 {\n\t\treturn in\n\t}\n\tin = slices.Clone(in)\n\tslices.Sort(in)\n\treturn slices.Compact(in)\n}\n\n// Lookup finds all the symbols in the index with the given PkgName and name.\n// If prefix is true, it finds all of these with name as a prefix.\nfunc (ix *Index) Lookup(pkgName, name string, prefix bool) []Candidate {\n\tloc, ok := slices.BinarySearchFunc(ix.Entries, pkgName, func(e Entry, pkg string) int {\n\t\treturn strings.Compare(e.PkgName, pkgName)\n\t})\n\tif !ok {\n\t\treturn nil // didn't find the package\n\t}\n\tvar ans []Candidate\n\t// loc is the first entry for this package name, but there may be several\n\tfor i := loc; i < len(ix.Entries); i++ {\n\t\te := ix.Entries[i]\n\t\tif e.PkgName != pkgName {\n\t\t\tbreak // end of sorted package names\n\t\t}\n\t\tnloc, ok := slices.BinarySearchFunc(e.Names, name, func(s string, name string) int {\n\t\t\tif strings.HasPrefix(s, name) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\tif s < name {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\treturn 1\n\t\t})\n\t\tif !ok {\n\t\t\tcontinue // didn't find the name, nor any symbols with name as a prefix\n\t\t}\n\t\tfor j := nloc; j < len(e.Names); j++ {\n\t\t\tnstr := e.Names[j]\n\t\t\t// benchmarks show this makes a difference when there are a lot of Possibilities\n\t\t\tflds := fastSplit(nstr)\n\t\t\tif !(flds[0] == name || prefix && strings.HasPrefix(flds[0], name)) {\n\t\t\t\t// past range of matching Names\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif len(flds) < 2 {\n\t\t\t\tcontinue // should never happen\n\t\t\t}\n\t\t\timpPath, err := module.UnescapePath(e.ImportPath)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpx := Candidate{\n\t\t\t\tPkgName:    pkgName,\n\t\t\t\tName:       flds[0],\n\t\t\t\tDir:        string(e.Dir),\n\t\t\t\tImportPath: impPath,\n\t\t\t\tType:       asLexType(flds[1][0]),\n\t\t\t\tDeprecated: len(flds[1]) > 1 && flds[1][1] == 'D',\n\t\t\t}\n\t\t\tif px.Type == Func {\n\t\t\t\tn, err := strconv.Atoi(flds[2])\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue // should never happen\n\t\t\t\t}\n\t\t\t\tpx.Results = int16(n)\n\t\t\t\tif len(flds) >= 4 {\n\t\t\t\t\tsig := strings.Split(flds[3], \" \")\n\t\t\t\t\tfor i := range sig {\n\t\t\t\t\t\t// $ cannot otherwise occur. removing the spaces\n\t\t\t\t\t\t// almost works, but for chan struct{}, e.g.\n\t\t\t\t\t\tsig[i] = strings.Replace(sig[i], \"$\", \" \", -1)\n\t\t\t\t\t}\n\t\t\t\t\tpx.Sig = toFields(sig)\n\t\t\t\t}\n\t\t\t}\n\t\t\tans = append(ans, px)\n\t\t}\n\t}\n\treturn ans\n}\n\nfunc toFields(sig []string) []Field {\n\tans := make([]Field, len(sig)/2)\n\tfor i := range ans {\n\t\tans[i] = Field{Arg: sig[2*i], Type: sig[2*i+1]}\n\t}\n\treturn ans\n}\n\n// benchmarks show this is measurably better than strings.Split\n// split into first 4 fields separated by single space\nfunc fastSplit(x string) []string {\n\tans := make([]string, 0, 4)\n\tnxt := 0\n\tstart := 0\n\tfor i := 0; i < len(x); i++ {\n\t\tif x[i] != ' ' {\n\t\t\tcontinue\n\t\t}\n\t\tans = append(ans, x[start:i])\n\t\tnxt++\n\t\tstart = i + 1\n\t\tif nxt >= 3 {\n\t\t\tbreak\n\t\t}\n\t}\n\tans = append(ans, x[start:])\n\treturn ans\n}\n\nfunc asLexType(c byte) LexType {\n\tswitch c {\n\tcase 'C':\n\t\treturn Const\n\tcase 'V':\n\t\treturn Var\n\tcase 'T':\n\t\treturn Type\n\tcase 'F':\n\t\treturn Func\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "internal/modindex/lookup_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex_test\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/internal/modindex\"\n)\n\ntype tdata struct {\n\tfname string\n\tpkg   string\n\titems []titem\n}\n\ntype titem struct {\n\tcode   string\n\tresult result\n}\n\nvar thedata = tdata{\n\tfname: \"cloud.google.com/go/!longrunning@v0.4.1/foo.go\",\n\tpkg:   \"foo\",\n\titems: []titem{\n\t\t// these need to be in alphabetical order\n\t\t{\"func Foo() {}\", result{\"Foo\", Func, false, 0, nil}},\n\t\t{\"const FooC = 23\", result{\"FooC\", Const, false, 0, nil}},\n\t\t{\"func FooF(int, float) error {return nil}\", result{\"FooF\", Func, false, 1,\n\t\t\t[]Field{{\"_\", \"int\"}, {\"_\", \"float\"}}}},\n\t\t{\"type FooT struct{}\", result{\"FooT\", Type, false, 0, nil}},\n\t\t{\"var FooV int\", result{\"FooV\", Var, false, 0, nil}},\n\t\t{\"func Goo() {}\", result{\"Goo\", Func, false, 0, nil}},\n\t\t{\"/*Deprecated: too weird\\n*/\\n// Another Goo\\nvar GooVV int\", result{\"GooVV\", Var, true, 0, nil}},\n\t\t{\"func Ⱋoox(x int) {}\", result{\"Ⱋoox\", Func, false, 0, []Field{{\"x\", \"int\"}}}},\n\t},\n}\n\ntype result struct {\n\tname       string\n\ttyp        LexType\n\tdeprecated bool\n\tresult     int\n\tsig        []Field\n}\n\nfunc okresult(r result, p Candidate) bool {\n\tif r.name != p.Name || r.typ != p.Type || r.result != int(p.Results) {\n\t\treturn false\n\t}\n\tif r.deprecated != p.Deprecated {\n\t\treturn false\n\t}\n\tif len(r.sig) != len(p.Sig) {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.sig); i++ {\n\t\tif r.sig[i] != p.Sig[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc TestLookup(t *testing.T) {\n\tdir := testModCache(t)\n\twrtData(t, dir, thedata)\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tix, err := Read(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(ix.Entries) != 1 {\n\t\tt.Fatalf(\"got %d Entries, expected 1\", len(ix.Entries))\n\t}\n\t// get all the symbols\n\tp := ix.Lookup(\"foo\", \"\", true)\n\tif len(p) > 0 && !strings.Contains(p[0].ImportPath, \"Longrunning\") {\n\t\tt.Errorf(\"Failed to convert escaped path: %s\", p[0].ImportPath)\n\t}\n\tif len(p) != len(thedata.items) {\n\t\tt.Errorf(\"got %d possibilities for pkg foo, expected %d\", len(p), len(thedata.items))\n\t}\n\tfor i, r := range thedata.items {\n\t\tif !okresult(r.result, p[i]) {\n\t\t\tt.Errorf(\"got %#v, expected %#v\", p[i], r.result)\n\t\t}\n\t}\n\t// look for the Foo... and check that each is a Foo...\n\tp = ix.Lookup(\"foo\", \"Foo\", true)\n\tif len(p) != 5 {\n\t\tt.Errorf(\"got %d possibilities for foo.Foo*, expected 5\", len(p))\n\t}\n\tfor _, r := range p {\n\t\tif !strings.HasPrefix(r.Name, \"Foo\") {\n\t\t\tt.Errorf(\"got %s, expected Foo...\", r.Name)\n\t\t}\n\t}\n\t// fail to find something\n\tp = ix.Lookup(\"foo\", \"FooVal\", false)\n\tif len(p) != 0 {\n\t\tt.Errorf(\"got %d possibilities for foo.FooVal, expected 0\", len(p))\n\t}\n\t// find an exact match\n\tp = ix.Lookup(\"foo\", \"Foo\", false)\n\tif len(p) != 1 {\n\t\tt.Errorf(\"got %d possibilities for foo.Foo, expected 1\", len(p))\n\t}\n\t// \"Foo\" is the first test datum\n\tif !okresult(thedata.items[0].result, p[0]) {\n\t\tt.Errorf(\"got %#v, expected %#v\", p[0], thedata.items[0].result)\n\t}\n}\n\nfunc wrtData(t *testing.T, dir string, data tdata) {\n\tt.Helper()\n\tlocname := filepath.FromSlash(data.fname)\n\tif err := os.MkdirAll(filepath.Join(dir, filepath.Dir(locname)), 0755); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfd, err := os.Create(filepath.Join(dir, locname))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer fd.Close()\n\tfmt.Fprintf(fd, \"package %s\\n\", data.pkg)\n\tfor _, item := range data.items {\n\t\tfd.WriteString(item.code + \"\\n\")\n\t}\n}\n\nfunc TestLookupAll(t *testing.T) {\n\tlog.SetFlags(log.Lshortfile)\n\tdir := testModCache(t)\n\twrtModule := func(mod string, nms ...string) {\n\t\tdname := filepath.Join(dir, mod)\n\t\tif err := os.MkdirAll(dname, 0755); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfname := filepath.Join(dname, \"foo.go\")\n\t\tfd, err := os.Create(fname)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdefer fd.Close()\n\t\tif _, err := fmt.Fprintf(fd, \"package foo\\n\"); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfor _, nm := range nms {\n\t\t\tfmt.Fprintf(fd, \"func %s() {}\\n\", nm)\n\t\t}\n\t}\n\twrtModule(\"a.com/go/x4@v1.1.1\", \"A\", \"B\", \"C\", \"D\")\n\twrtModule(\"b.com/go/x3@v1.2.1\", \"A\", \"B\", \"C\")\n\twrtModule(\"c.com/go/x5@v1.3.1\", \"A\", \"B\", \"C\", \"D\", \"E\")\n\n\tif _, err := Create(dir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tix, err := Read(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcands := ix.Lookup(\"foo\", \"A\", false)\n\tif len(cands) != 3 {\n\t\tt.Errorf(\"got %d candidates for A, expected 3\", len(cands))\n\t}\n\tgot := ix.LookupAll(\"foo\", \"A\", \"B\", \"C\", \"D\")\n\tif len(got) != 2 {\n\t\tt.Errorf(\"got %d candidates for A,B,C,D, expected 2\", len(got))\n\t}\n\tgot = ix.LookupAll(\"foo\", []string{\"A\", \"B\", \"C\", \"D\", \"E\"}...)\n\tif len(got) != 1 {\n\t\tt.Errorf(\"got %d candidates for A,B,C,D,E, expected 1\", len(got))\n\t}\n}\n\nfunc TestUniquify(t *testing.T) {\n\tvar v []string\n\tfor i := 1; i < 4; i++ {\n\t\tv = append(v, \"A\")\n\t\tw := Uniquify(v)\n\t\tif len(w) != 1 {\n\t\t\tt.Errorf(\"got %d, expected 1\", len(w))\n\t\t}\n\t}\n\tfor i := 1; i < 3; i++ {\n\t\tv = append(v, \"B\", \"C\")\n\t\tw := Uniquify(v)\n\t\tif len(w) != 3 {\n\t\t\tt.Errorf(\"got %d, expected 3\", len(w))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/modindex/modindex.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package modindex contains code for building and searching an\n// [Index] of the Go module cache.\npackage modindex\n\n// The directory containing the index, returned by\n// [IndexDir], contains a file index-name-<ver> that contains the name\n// of the current index. We believe writing that short file is atomic.\n// [Read] reads that file to get the file name of the index.\n// WriteIndex writes an index with a unique name and then\n// writes that name into a new version of index-name-<ver>.\n// (<ver> stands for the CurrentVersion of the index format.)\n\nimport (\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/mod/semver\"\n)\n\n// Update updates the index for the specified Go\n// module cache directory, creating it as needed.\n// On success it returns the current index.\nfunc Update(gomodcache string) (*Index, error) {\n\tprev, err := Read(gomodcache)\n\tif err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn nil, err\n\t\t}\n\t\tprev = nil\n\t}\n\treturn update(gomodcache, prev)\n}\n\n// update builds, writes, and returns the current index.\n//\n// If old is nil, the new index is built from all of GOMODCACHE;\n// otherwise it is built from the old index plus cache updates\n// since the previous index's time.\nfunc update(gomodcache string, old *Index) (*Index, error) {\n\tgomodcache, err := filepath.Abs(gomodcache)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnew, changed, err := build(gomodcache, old)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif old == nil || changed {\n\t\tif err := write(gomodcache, new); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn new, nil\n}\n\n// build returns a new index for the specified Go module cache (an\n// absolute path).\n//\n// If an old index is provided, only directories more recent than it\n// that it are scanned; older directories are provided by the old\n// Index.\n//\n// The boolean result indicates whether new entries were found.\nfunc build(gomodcache string, old *Index) (*Index, bool, error) {\n\t// Set the time window.\n\tvar start time.Time // = dawn of time\n\tif old != nil {\n\t\tstart = old.ValidAt\n\t}\n\tnow := time.Now()\n\tend := now.Add(24 * time.Hour) // safely in the future\n\n\t// Enumerate GOMODCACHE package directories.\n\t// Choose the best (latest) package for each import path.\n\tpkgDirs := findDirs(gomodcache, start, end)\n\tdirByPath, err := bestDirByImportPath(pkgDirs)\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\n\t// For each import path it might occur only in\n\t// dirByPath, only in old, or in both.\n\t// If both, use the semantically later one.\n\tvar entries []Entry\n\tif old != nil {\n\t\tfor _, entry := range old.Entries {\n\t\t\tdir, ok := dirByPath[entry.ImportPath]\n\t\t\tif !ok || semver.Compare(dir.version, entry.Version) <= 0 {\n\t\t\t\t// New dir is missing or not more recent; use old entry.\n\t\t\t\tentries = append(entries, entry)\n\t\t\t\tdelete(dirByPath, entry.ImportPath)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract symbol information for all the new directories.\n\tnewEntries := extractSymbols(gomodcache, maps.Values(dirByPath))\n\tentries = append(entries, newEntries...)\n\tslices.SortFunc(entries, func(x, y Entry) int {\n\t\tif n := strings.Compare(x.PkgName, y.PkgName); n != 0 {\n\t\t\treturn n\n\t\t}\n\t\treturn strings.Compare(x.ImportPath, y.ImportPath)\n\t})\n\n\treturn &Index{\n\t\tGOMODCACHE: gomodcache,\n\t\tValidAt:    now, // time before the directories were scanned\n\t\tEntries:    entries,\n\t}, len(newEntries) > 0, nil\n}\n"
  },
  {
    "path": "internal/modindex/symbols.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage modindex\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"iter\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n)\n\n// The name of a symbol contains information about the symbol:\n// <name> T for types, TD if the type is deprecated\n// <name> C for consts, CD if the const is deprecated\n// <name> V for vars, VD if the var is deprecated\n// and for funcs: <name> F <num of return values> (<arg-name> <arg-type>)*\n// any spaces in <arg-type> are replaced by $s so that the fields\n// of the name are space separated. F is replaced by FD if the func\n// is deprecated.\ntype symbol struct {\n\tpkg  string // name of the symbols's package\n\tname string // declared name\n\tkind string // T, C, V, or F, followed by D if deprecated\n\tsig  string // signature information, for F\n}\n\n// extractSymbols returns a (new, unordered) array of Entries, one for\n// each provided package directory, describing its exported symbols.\nfunc extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {\n\tvar (\n\t\tmu      sync.Mutex\n\t\tentries []Entry\n\t)\n\n\tvar g errgroup.Group\n\tg.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))\n\tfor dir := range dirs {\n\t\tg.Go(func() error {\n\t\t\tthedir := filepath.Join(cwd, string(dir.path))\n\t\t\tmode := parser.SkipObjectResolution | parser.ParseComments\n\n\t\t\t// Parse all Go files in dir and extract symbols.\n\t\t\tdirents, err := os.ReadDir(thedir)\n\t\t\tif err != nil {\n\t\t\t\treturn nil // log this someday?\n\t\t\t}\n\t\t\tvar syms []symbol\n\t\t\tfor _, dirent := range dirents {\n\t\t\t\tif !strings.HasSuffix(dirent.Name(), \".go\") ||\n\t\t\t\t\tstrings.HasSuffix(dirent.Name(), \"_test.go\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfname := filepath.Join(thedir, dirent.Name())\n\t\t\t\ttr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue // ignore errors, someday log them?\n\t\t\t\t}\n\t\t\t\tsyms = append(syms, getFileExports(tr)...)\n\t\t\t}\n\n\t\t\t// Create an entry for the package.\n\t\t\tpkg, names := processSyms(syms)\n\t\t\tif pkg != \"\" {\n\t\t\t\tmu.Lock()\n\t\t\t\tdefer mu.Unlock()\n\t\t\t\tentries = append(entries, Entry{\n\t\t\t\t\tPkgName:    pkg,\n\t\t\t\t\tDir:        dir.path,\n\t\t\t\t\tImportPath: dir.importPath,\n\t\t\t\t\tVersion:    dir.version,\n\t\t\t\t\tNames:      names,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn nil\n\t\t})\n\t}\n\tg.Wait() // ignore error\n\n\treturn entries\n}\n\nfunc getFileExports(f *ast.File) []symbol {\n\tpkg := f.Name.Name\n\tif pkg == \"main\" || pkg == \"\" {\n\t\treturn nil\n\t}\n\tvar ans []symbol\n\t// should we look for //go:build ignore?\n\tfor _, decl := range f.Decls {\n\t\tswitch decl := decl.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tif decl.Recv != nil {\n\t\t\t\t// ignore methods, as we are completing package selections\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tname := decl.Name.Name\n\t\t\tdtype := decl.Type\n\t\t\t// not looking at dtype.TypeParams. That is, treating\n\t\t\t// generic functions just like non-generic ones.\n\t\t\tsig := dtype.Params\n\t\t\tkind := \"F\"\n\t\t\tif isDeprecated(decl.Doc) {\n\t\t\t\tkind += \"D\"\n\t\t\t}\n\t\t\tresult := []string{fmt.Sprintf(\"%d\", dtype.Results.NumFields())}\n\t\t\tfor _, x := range sig.List {\n\t\t\t\t// This code creates a string representing the type.\n\t\t\t\t// TODO(pjw): it may be fragile:\n\t\t\t\t// 1. x.Type could be nil, perhaps in ill-formed code\n\t\t\t\t// 2. ExprString might someday change incompatibly to\n\t\t\t\t//    include struct tags, which can be arbitrary strings\n\t\t\t\tif x.Type == nil {\n\t\t\t\t\t// Can this happen without a parse error? (Files with parse\n\t\t\t\t\t// errors are ignored in getSymbols)\n\t\t\t\t\tcontinue // maybe report this someday\n\t\t\t\t}\n\t\t\t\ttp := types.ExprString(x.Type)\n\t\t\t\tif len(tp) == 0 {\n\t\t\t\t\t// Can this happen?\n\t\t\t\t\tcontinue // maybe report this someday\n\t\t\t\t}\n\t\t\t\t// This is only safe if ExprString never returns anything with a $\n\t\t\t\t// The only place a $ can occur seems to be in a struct tag, which\n\t\t\t\t// can be an arbitrary string literal, and ExprString does not presently\n\t\t\t\t// print struct tags. So for this to happen the type of a formal parameter\n\t\t\t\t// has to be a explicit struct, e.g. foo(x struct{a int \"$\"}) and ExprString\n\t\t\t\t// would have to show the struct tag. Even testing for this case seems\n\t\t\t\t// a waste of effort, but let's remember the possibility\n\t\t\t\tif strings.Contains(tp, \"$\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\ttp = strings.Replace(tp, \" \", \"$\", -1)\n\t\t\t\tif len(x.Names) == 0 {\n\t\t\t\t\tresult = append(result, \"_\")\n\t\t\t\t\tresult = append(result, tp)\n\t\t\t\t} else {\n\t\t\t\t\tfor _, y := range x.Names {\n\t\t\t\t\t\tresult = append(result, y.Name)\n\t\t\t\t\t\tresult = append(result, tp)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsigs := strings.Join(result, \" \")\n\t\t\tif s := newsym(pkg, name, kind, sigs); s != nil {\n\t\t\t\tans = append(ans, *s)\n\t\t\t}\n\t\tcase *ast.GenDecl:\n\t\t\tdepr := isDeprecated(decl.Doc)\n\t\t\tswitch decl.Tok {\n\t\t\tcase token.CONST, token.VAR:\n\t\t\t\ttp := \"V\"\n\t\t\t\tif decl.Tok == token.CONST {\n\t\t\t\t\ttp = \"C\"\n\t\t\t\t}\n\t\t\t\tif depr {\n\t\t\t\t\ttp += \"D\"\n\t\t\t\t}\n\t\t\t\tfor _, sp := range decl.Specs {\n\t\t\t\t\tfor _, x := range sp.(*ast.ValueSpec).Names {\n\t\t\t\t\t\tif s := newsym(pkg, x.Name, tp, \"\"); s != nil {\n\t\t\t\t\t\t\tans = append(ans, *s)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase token.TYPE:\n\t\t\t\ttp := \"T\"\n\t\t\t\tif depr {\n\t\t\t\t\ttp += \"D\"\n\t\t\t\t}\n\t\t\t\tfor _, sp := range decl.Specs {\n\t\t\t\t\tif s := newsym(pkg, sp.(*ast.TypeSpec).Name.Name, tp, \"\"); s != nil {\n\t\t\t\t\t\tans = append(ans, *s)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn ans\n}\n\nfunc newsym(pkg, name, kind, sig string) *symbol {\n\tif len(name) == 0 || !ast.IsExported(name) {\n\t\treturn nil\n\t}\n\tsym := symbol{pkg: pkg, name: name, kind: kind, sig: sig}\n\treturn &sym\n}\n\nfunc isDeprecated(doc *ast.CommentGroup) bool {\n\tif doc == nil {\n\t\treturn false\n\t}\n\t// go.dev/wiki/Deprecated Paragraph starting 'Deprecated:'\n\t// This code fails for /* Deprecated: */, but it's the code from\n\t// gopls/internal/analysis/deprecated\n\tfor line := range strings.SplitSeq(doc.Text(), \"\\n\\n\") {\n\t\tif strings.HasPrefix(line, \"Deprecated:\") {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// return the package name and the value for the symbols.\n// if there are multiple packages, choose one arbitrarily\n// the returned slice is sorted lexicographically\nfunc processSyms(syms []symbol) (string, []string) {\n\tif len(syms) == 0 {\n\t\treturn \"\", nil\n\t}\n\tslices.SortFunc(syms, func(l, r symbol) int {\n\t\treturn strings.Compare(l.name, r.name)\n\t})\n\tpkg := syms[0].pkg\n\tvar names []string\n\tfor _, s := range syms {\n\t\tif s.pkg != pkg {\n\t\t\t// Symbols came from two files in same dir\n\t\t\t// with different package declarations.\n\t\t\tcontinue\n\t\t}\n\t\tvar nx string\n\t\tif s.sig != \"\" {\n\t\t\tnx = fmt.Sprintf(\"%s %s %s\", s.name, s.kind, s.sig)\n\t\t} else {\n\t\t\tnx = fmt.Sprintf(\"%s %s\", s.name, s.kind)\n\t\t}\n\t\tnames = append(names, nx)\n\t}\n\treturn pkg, names\n}\n"
  },
  {
    "path": "internal/moreiters/iters.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage moreiters\n\nimport \"iter\"\n\n// First returns the first value of seq and true.\n// If seq is empty, it returns the zero value of T and false.\nfunc First[T any](seq iter.Seq[T]) (z T, ok bool) {\n\tfor t := range seq {\n\t\treturn t, true\n\t}\n\treturn z, false\n}\n\n// Contains reports whether x is an element of the sequence seq.\nfunc Contains[T comparable](seq iter.Seq[T], x T) bool {\n\tfor cand := range seq {\n\t\tif cand == x {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Every reports whether every pred(t) for t in seq returns true,\n// stopping at the first false element.\nfunc Every[T any](seq iter.Seq[T], pred func(T) bool) bool {\n\tfor t := range seq {\n\t\tif !pred(t) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Any reports whether any pred(t) for t in seq returns true.\nfunc Any[T any](seq iter.Seq[T], pred func(T) bool) bool {\n\tfor t := range seq {\n\t\tif pred(t) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Len returns the number of elements in the sequence (by iterating).\nfunc Len[T any](seq iter.Seq[T]) (n int) {\n\tfor range seq {\n\t\tn++\n\t}\n\treturn\n}\n"
  },
  {
    "path": "internal/packagepath/packagepath.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package packagepath provides metadata operations on package path\n// strings.\npackage packagepath\n\n// (This package should not depend on go/ast.)\nimport \"strings\"\n\n// CanImport reports whether one package is allowed to import another.\n//\n// TODO(adonovan): allow customization of the accessibility relation\n// (e.g. for Bazel).\nfunc CanImport(from, to string) bool {\n\t// TODO(adonovan): better segment hygiene.\n\tif to == \"internal\" || strings.HasPrefix(to, \"internal/\") {\n\t\t// Special case: only std packages may import internal/...\n\t\t// We can't reliably know whether we're in std, so we\n\t\t// use a heuristic on the first segment.\n\t\tfirst, _, _ := strings.Cut(from, \"/\")\n\t\tif strings.Contains(first, \".\") {\n\t\t\treturn false // example.com/foo ∉ std\n\t\t}\n\t\tif first == \"testdata\" {\n\t\t\treturn false // testdata/foo ∉ std\n\t\t}\n\t}\n\tif strings.HasSuffix(to, \"/internal\") {\n\t\treturn strings.HasPrefix(from, to[:len(to)-len(\"/internal\")])\n\t}\n\tif i := strings.LastIndex(to, \"/internal/\"); i >= 0 {\n\t\treturn strings.HasPrefix(from, to[:i])\n\t}\n\treturn true\n}\n\n// IsStdPackage reports whether the specified package path belongs to a\n// package in the standard library (including internal dependencies).\nfunc IsStdPackage(path string) bool {\n\t// A standard package has no dot in its first segment.\n\t// (It may yet have a dot, e.g. \"vendor/golang.org/x/foo\".)\n\tslash := strings.IndexByte(path, '/')\n\tif slash < 0 {\n\t\tslash = len(path)\n\t}\n\treturn !strings.Contains(path[:slash], \".\") && path != \"testdata\"\n}\n"
  },
  {
    "path": "internal/packagepath/packagepath_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagepath_test\n\nimport (\n\t\"testing\"\n\n\t. \"golang.org/x/tools/internal/packagepath\"\n)\n\nfunc TestCanImport(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tfrom string\n\t\tto   string\n\t\twant bool\n\t}{\n\t\t{\"fmt\", \"internal\", true},\n\t\t{\"fmt\", \"internal/foo\", true},\n\t\t{\"fmt\", \"fmt/internal/foo\", true},\n\t\t{\"fmt\", \"cmd/internal/archive\", false},\n\t\t{\"a.com/b\", \"internal\", false},\n\t\t{\"a.com/b\", \"xinternal\", true},\n\t\t{\"a.com/b\", \"internal/foo\", false},\n\t\t{\"a.com/b\", \"xinternal/foo\", true},\n\t\t{\"a.com/b\", \"a.com/internal\", true},\n\t\t{\"a.com/b\", \"a.com/b/internal\", true},\n\t\t{\"a.com/b\", \"a.com/b/internal/foo\", true},\n\t\t{\"a.com/b\", \"a.com/c/internal\", false},\n\t\t{\"a.com/b\", \"a.com/c/xinternal\", true},\n\t\t{\"a.com/b\", \"a.com/c/internal/foo\", false},\n\t\t{\"a.com/b\", \"a.com/c/xinternal/foo\", true},\n\t} {\n\t\tgot := CanImport(tt.from, tt.to)\n\t\tif got != tt.want {\n\t\t\tt.Errorf(\"CanImport(%q, %q) = %v, want %v\", tt.from, tt.to, got, tt.want)\n\t\t}\n\t}\n}\n\nfunc TestIsStdPackage(t *testing.T) {\n\ttestCases := []struct {\n\t\tpkgpath string\n\t\tisStd   bool\n\t}{\n\t\t{pkgpath: \"os\", isStd: true},\n\t\t{pkgpath: \"net/http\", isStd: true},\n\t\t{pkgpath: \"vendor/golang.org/x/net/dns/dnsmessage\", isStd: true},\n\t\t{pkgpath: \"golang.org/x/net/dns/dnsmessage\", isStd: false},\n\t\t{pkgpath: \"testdata\", isStd: false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.pkgpath, func(t *testing.T) {\n\t\t\tgot := IsStdPackage(tc.pkgpath)\n\t\t\tif got != tc.isStd {\n\t\t\t\tt.Fatalf(\"got %t want %t\", got, tc.isStd)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/packagesinternal/packages.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package packagesinternal exposes internal-only fields from go/packages.\npackage packagesinternal\n\nimport \"fmt\"\n\nvar GetDepsErrors = func(p any) []*PackageError { return nil }\n\ntype PackageError struct {\n\tImportStack []string // shortest path from package named on command line to this one\n\tPos         string   // position of error (if present, file:line:col)\n\tErr         string   // the error itself\n}\n\nfunc (err PackageError) String() string {\n\treturn fmt.Sprintf(\"%s: %s (import stack: %s)\", err.Pos, err.Err, err.ImportStack)\n}\n\nvar TypecheckCgo int\nvar DepsErrors int // must be set as a LoadMode to call GetDepsErrors\n"
  },
  {
    "path": "internal/packagestest/expect.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/expect\"\n)\n\nconst (\n\tmarkMethod    = \"mark\"\n\teofIdentifier = \"EOF\"\n)\n\n// Expect invokes the supplied methods for all expectation notes found in\n// the exported source files.\n//\n// All exported go source files are parsed to collect the expectation\n// notes.\n// See the documentation for expect.Parse for how the notes are collected\n// and parsed.\n//\n// The methods are supplied as a map of name to function, and those functions\n// will be matched against the expectations by name.\n// Notes with no matching function will be skipped, and functions with no\n// matching notes will not be invoked.\n// If there are no registered markers yet, a special pass will be run first\n// which adds any markers declared with @mark(Name, pattern) or @name. These\n// call the Mark method to add the marker to the global set.\n// You can register the \"mark\" method to override these in your own call to\n// Expect. The bound Mark function is usable directly in your method map, so\n//\n//\texported.Expect(map[string]interface{}{\"mark\": exported.Mark})\n//\n// replicates the built in behavior.\n//\n// # Method invocation\n//\n// When invoking a method the expressions in the parameter list need to be\n// converted to values to be passed to the method.\n// There are a very limited set of types the arguments are allowed to be.\n//\n//\texpect.Note : passed the Note instance being evaluated.\n//\tstring : can be supplied either a string literal or an identifier.\n//\tint : can only be supplied an integer literal.\n//\t*regexp.Regexp : can only be supplied a regular expression literal\n//\ttoken.Pos : has a file position calculated as described below.\n//\ttoken.Position : has a file position calculated as described below.\n//\texpect.Range: has a start and end position as described below.\n//\tinterface{} : will be passed any value\n//\n// # Position calculation\n//\n// There is some extra handling when a parameter is being coerced into a\n// token.Pos, token.Position or Range type argument.\n//\n// If the parameter is an identifier, it will be treated as the name of an\n// marker to look up (as if markers were global variables).\n//\n// If it is a string or regular expression, then it will be passed to\n// expect.MatchBefore to look up a match in the line at which it was declared.\n//\n// It is safe to call this repeatedly with different method sets, but it is\n// not safe to call it concurrently.\nfunc (e *Exported) Expect(methods map[string]any) error {\n\tif err := e.getNotes(); err != nil {\n\t\treturn err\n\t}\n\tif err := e.getMarkers(); err != nil {\n\t\treturn err\n\t}\n\tvar err error\n\tms := make(map[string]method, len(methods))\n\tfor name, f := range methods {\n\t\tmi := method{f: reflect.ValueOf(f)}\n\t\tmi.converters = make([]converter, mi.f.Type().NumIn())\n\t\tfor i := 0; i < len(mi.converters); i++ {\n\t\t\tmi.converters[i], err = e.buildConverter(mi.f.Type().In(i))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid method %v: %v\", name, err)\n\t\t\t}\n\t\t}\n\t\tms[name] = mi\n\t}\n\tfor _, n := range e.notes {\n\t\tif n.Args == nil {\n\t\t\t// simple identifier form, convert to a call to mark\n\t\t\tn = &expect.Note{\n\t\t\t\tPos:  n.Pos,\n\t\t\t\tName: markMethod,\n\t\t\t\tArgs: []any{n.Name, n.Name},\n\t\t\t}\n\t\t}\n\t\tmi, ok := ms[n.Name]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tparams := make([]reflect.Value, len(mi.converters))\n\t\targs := n.Args\n\t\tfor i, convert := range mi.converters {\n\t\t\tparams[i], args, err = convert(n, args)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%v: %v\", e.ExpectFileSet.Position(n.Pos), err)\n\t\t\t}\n\t\t}\n\t\tif len(args) > 0 {\n\t\t\treturn fmt.Errorf(\"%v: unwanted args got %+v extra\", e.ExpectFileSet.Position(n.Pos), args)\n\t\t}\n\t\t//TODO: catch the error returned from the method\n\t\tmi.f.Call(params)\n\t}\n\treturn nil\n}\n\n// Mark adds a new marker to the known set.\nfunc (e *Exported) Mark(name string, r astutil.Range) {\n\tif e.markers == nil {\n\t\te.markers = make(map[string]astutil.Range)\n\t}\n\te.markers[name] = r\n}\n\nfunc (e *Exported) getNotes() error {\n\tif e.notes != nil {\n\t\treturn nil\n\t}\n\tnotes := []*expect.Note{}\n\tvar dirs []string\n\tfor _, module := range e.written {\n\t\tfor _, filename := range module {\n\t\t\tdirs = append(dirs, filepath.Dir(filename))\n\t\t}\n\t}\n\tfor filename := range e.Config.Overlay {\n\t\tdirs = append(dirs, filepath.Dir(filename))\n\t}\n\tpkgs, err := packages.Load(e.Config, dirs...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to load packages for directories %s: %v\", dirs, err)\n\t}\n\tseen := make(map[token.Position]struct{})\n\tfor _, pkg := range pkgs {\n\t\tfor _, filename := range pkg.GoFiles {\n\t\t\tcontent, err := e.FileContents(filename)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tl, err := expect.Parse(e.ExpectFileSet, filename, content)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to extract expectations: %v\", err)\n\t\t\t}\n\t\t\tfor _, note := range l {\n\t\t\t\tpos := e.ExpectFileSet.Position(note.Pos)\n\t\t\t\tif _, ok := seen[pos]; ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tnotes = append(notes, note)\n\t\t\t\tseen[pos] = struct{}{}\n\t\t\t}\n\t\t}\n\t}\n\tif _, ok := e.written[e.primary]; !ok {\n\t\te.notes = notes\n\t\treturn nil\n\t}\n\t// Check go.mod markers regardless of mode, we need to do this so that our marker count\n\t// matches the counts in the summary.txt.golden file for the test directory.\n\tif gomod, found := e.written[e.primary][\"go.mod\"]; found {\n\t\t// If we are in Modules mode, then we need to check the contents of the go.mod.temp.\n\t\tif e.Exporter == Modules {\n\t\t\tgomod += \".temp\"\n\t\t}\n\t\tl, err := goModMarkers(e, gomod)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to extract expectations for go.mod: %v\", err)\n\t\t}\n\t\tnotes = append(notes, l...)\n\t}\n\te.notes = notes\n\treturn nil\n}\n\nfunc goModMarkers(e *Exported, gomod string) ([]*expect.Note, error) {\n\tif _, err := os.Stat(gomod); os.IsNotExist(err) {\n\t\t// If there is no go.mod file, we want to be able to continue.\n\t\treturn nil, nil\n\t}\n\tcontent, err := e.FileContents(gomod)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif e.Exporter == GOPATH {\n\t\treturn expect.Parse(e.ExpectFileSet, gomod, content)\n\t}\n\tgomod = strings.TrimSuffix(gomod, \".temp\")\n\t// If we are in Modules mode, copy the original contents file back into go.mod\n\tif err := os.WriteFile(gomod, content, 0644); err != nil {\n\t\treturn nil, nil\n\t}\n\treturn expect.Parse(e.ExpectFileSet, gomod, content)\n}\n\nfunc (e *Exported) getMarkers() error {\n\tif e.markers != nil {\n\t\treturn nil\n\t}\n\t// set markers early so that we don't call getMarkers again from Expect\n\te.markers = make(map[string]astutil.Range)\n\treturn e.Expect(map[string]any{\n\t\tmarkMethod: e.Mark,\n\t})\n}\n\nvar (\n\tnoteType       = reflect.TypeFor[*expect.Note]()\n\tidentifierType = reflect.TypeFor[expect.Identifier]()\n\tposType        = reflect.TypeFor[token.Pos]()\n\tpositionType   = reflect.TypeFor[token.Position]()\n\trangeType      = reflect.TypeFor[astutil.Range]()\n\tfsetType       = reflect.TypeFor[*token.FileSet]()\n\tregexType      = reflect.TypeFor[*regexp.Regexp]()\n\texportedType   = reflect.TypeFor[*Exported]()\n)\n\n// converter converts from a marker's argument parsed from the comment to\n// reflect values passed to the method during Invoke.\n// It takes the args remaining, and returns the args it did not consume.\n// This allows a converter to consume 0 args for well known types, or multiple\n// args for compound types.\ntype converter func(*expect.Note, []any) (reflect.Value, []any, error)\n\n// method is used to track information about Invoke methods that is expensive to\n// calculate so that we can work it out once rather than per marker.\ntype method struct {\n\tf          reflect.Value // the reflect value of the passed in method\n\tconverters []converter   // the parameter converters for the method\n}\n\n// buildConverter works out what function should be used to go from an ast expressions to a reflect\n// value of the type expected by a method.\n// It is called when only the target type is know, it returns converters that are flexible across\n// all supported expression types for that target type.\nfunc (e *Exported) buildConverter(pt reflect.Type) (converter, error) {\n\tswitch {\n\tcase pt == noteType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\treturn reflect.ValueOf(n), args, nil\n\t\t}, nil\n\tcase pt == fsetType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\treturn reflect.ValueOf(e.ExpectFileSet), args, nil\n\t\t}, nil\n\tcase pt == exportedType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\treturn reflect.ValueOf(e), args, nil\n\t\t}, nil\n\tcase pt == posType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tr, remains, err := e.rangeConverter(n, args)\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Value{}, nil, err\n\t\t\t}\n\t\t\treturn reflect.ValueOf(r.Start), remains, nil\n\t\t}, nil\n\tcase pt == positionType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tr, remains, err := e.rangeConverter(n, args)\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Value{}, nil, err\n\t\t\t}\n\t\t\treturn reflect.ValueOf(e.ExpectFileSet.Position(r.Start)), remains, nil\n\t\t}, nil\n\tcase pt == rangeType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tr, remains, err := e.rangeConverter(n, args)\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Value{}, nil, err\n\t\t\t}\n\t\t\treturn reflect.ValueOf(r), remains, nil\n\t\t}, nil\n\tcase pt == identifierType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tif len(args) < 1 {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t}\n\t\t\targ := args[0]\n\t\t\targs = args[1:]\n\t\t\tswitch arg := arg.(type) {\n\t\t\tcase expect.Identifier:\n\t\t\t\treturn reflect.ValueOf(arg), args, nil\n\t\t\tdefault:\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"cannot convert %v to string\", arg)\n\t\t\t}\n\t\t}, nil\n\n\tcase pt == regexType:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tif len(args) < 1 {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t}\n\t\t\targ := args[0]\n\t\t\targs = args[1:]\n\t\t\tif _, ok := arg.(*regexp.Regexp); !ok {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"cannot convert %v to *regexp.Regexp\", arg)\n\t\t\t}\n\t\t\treturn reflect.ValueOf(arg), args, nil\n\t\t}, nil\n\n\tcase pt.Kind() == reflect.String:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tif len(args) < 1 {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t}\n\t\t\targ := args[0]\n\t\t\targs = args[1:]\n\t\t\tswitch arg := arg.(type) {\n\t\t\tcase expect.Identifier:\n\t\t\t\treturn reflect.ValueOf(string(arg)), args, nil\n\t\t\tcase string:\n\t\t\t\treturn reflect.ValueOf(arg), args, nil\n\t\t\tdefault:\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"cannot convert %v to string\", arg)\n\t\t\t}\n\t\t}, nil\n\tcase pt.Kind() == reflect.Int64:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tif len(args) < 1 {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t}\n\t\t\targ := args[0]\n\t\t\targs = args[1:]\n\t\t\tswitch arg := arg.(type) {\n\t\t\tcase int64:\n\t\t\t\treturn reflect.ValueOf(arg), args, nil\n\t\t\tdefault:\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"cannot convert %v to int\", arg)\n\t\t\t}\n\t\t}, nil\n\tcase pt.Kind() == reflect.Bool:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tif len(args) < 1 {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t}\n\t\t\targ := args[0]\n\t\t\targs = args[1:]\n\t\t\tb, ok := arg.(bool)\n\t\t\tif !ok {\n\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"cannot convert %v to bool\", arg)\n\t\t\t}\n\t\t\treturn reflect.ValueOf(b), args, nil\n\t\t}, nil\n\tcase pt.Kind() == reflect.Slice:\n\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\tconverter, err := e.buildConverter(pt.Elem())\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Value{}, nil, err\n\t\t\t}\n\t\t\tresult := reflect.MakeSlice(reflect.SliceOf(pt.Elem()), 0, len(args))\n\t\t\tfor range args {\n\t\t\t\tvalue, remains, err := converter(n, args)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn reflect.Value{}, nil, err\n\t\t\t\t}\n\t\t\t\tresult = reflect.Append(result, value)\n\t\t\t\targs = remains\n\t\t\t}\n\t\t\treturn result, args, nil\n\t\t}, nil\n\tdefault:\n\t\tif pt.Kind() == reflect.Interface && pt.NumMethod() == 0 {\n\t\t\treturn func(n *expect.Note, args []any) (reflect.Value, []any, error) {\n\t\t\t\tif len(args) < 1 {\n\t\t\t\t\treturn reflect.Value{}, nil, fmt.Errorf(\"missing argument\")\n\t\t\t\t}\n\t\t\t\treturn reflect.ValueOf(args[0]), args[1:], nil\n\t\t\t}, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"param has unexpected type %v (kind %v)\", pt, pt.Kind())\n\t}\n}\n\nfunc (e *Exported) rangeConverter(n *expect.Note, args []any) (astutil.Range, []any, error) {\n\ttokFile := e.ExpectFileSet.File(n.Pos)\n\tif len(args) < 1 {\n\t\treturn astutil.Range{}, nil, fmt.Errorf(\"missing argument\")\n\t}\n\targ := args[0]\n\targs = args[1:]\n\tswitch arg := arg.(type) {\n\tcase expect.Identifier:\n\t\t// handle the special identifiers\n\t\tswitch arg {\n\t\tcase eofIdentifier:\n\t\t\t// end of file identifier\n\t\t\teof := tokFile.Pos(tokFile.Size())\n\t\t\treturn newRange(tokFile, eof, eof), args, nil\n\t\tdefault:\n\t\t\t// look up a marker by name\n\t\t\tmark, ok := e.markers[string(arg)]\n\t\t\tif !ok {\n\t\t\t\treturn astutil.Range{}, nil, fmt.Errorf(\"cannot find marker %v\", arg)\n\t\t\t}\n\t\t\treturn mark, args, nil\n\t\t}\n\tcase string:\n\t\tstart, end, err := expect.MatchBefore(tokFile, e.FileContents, n.Pos, arg)\n\t\tif err != nil {\n\t\t\treturn astutil.Range{}, nil, err\n\t\t}\n\t\tif !start.IsValid() {\n\t\t\treturn astutil.Range{}, nil, fmt.Errorf(\"%v: pattern %s did not match\", tokFile.Position(n.Pos), arg)\n\t\t}\n\t\treturn newRange(tokFile, start, end), args, nil\n\tcase *regexp.Regexp:\n\t\tstart, end, err := expect.MatchBefore(tokFile, e.FileContents, n.Pos, arg)\n\t\tif err != nil {\n\t\t\treturn astutil.Range{}, nil, err\n\t\t}\n\t\tif !start.IsValid() {\n\t\t\treturn astutil.Range{}, nil, fmt.Errorf(\"%v: pattern %s did not match\", tokFile.Position(n.Pos), arg)\n\t\t}\n\t\treturn newRange(tokFile, start, end), args, nil\n\tdefault:\n\t\treturn astutil.Range{}, nil, fmt.Errorf(\"cannot convert %v to pos\", arg)\n\t}\n}\n\n// newRange creates a new Range from two valid positions within the specified token.File.\nfunc newRange(file *token.File, start, end token.Pos) astutil.Range {\n\tfileBase := file.Base()\n\tfileEnd := fileBase + file.Size()\n\tif !start.IsValid() {\n\t\tpanic(\"invalid start token.Pos\")\n\t}\n\tif !end.IsValid() {\n\t\tpanic(\"invalid end token.Pos\")\n\t}\n\tif int(start) < fileBase || int(start) > fileEnd {\n\t\tpanic(fmt.Sprintf(\"invalid start: %d not in [%d, %d]\", start, fileBase, fileEnd))\n\t}\n\tif int(end) < fileBase || int(end) > fileEnd {\n\t\tpanic(fmt.Sprintf(\"invalid end: %d not in [%d, %d]\", end, fileBase, fileEnd))\n\t}\n\tif start > end {\n\t\tpanic(\"invalid start: greater than end\")\n\t}\n\treturn astutil.RangeOf(start, end)\n}\n"
  },
  {
    "path": "internal/packagestest/expect_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest_test\n\nimport (\n\t\"go/token\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestExpect(t *testing.T) {\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{\n\t\tName:  \"golang.org/fake\",\n\t\tFiles: packagestest.MustCopyFileTree(\"testdata\"),\n\t}})\n\tdefer exported.Cleanup()\n\tcheckCount := 0\n\tif err := exported.Expect(map[string]any{\n\t\t\"check\": func(src, target token.Position) {\n\t\t\tcheckCount++\n\t\t},\n\t\t\"boolArg\": func(n *expect.Note, yes, no bool) {\n\t\t\tif !yes {\n\t\t\t\tt.Errorf(\"Expected boolArg first param to be true\")\n\t\t\t}\n\t\t\tif no {\n\t\t\t\tt.Errorf(\"Expected boolArg second param to be false\")\n\t\t\t}\n\t\t},\n\t\t\"intArg\": func(n *expect.Note, i int64) {\n\t\t\tif i != 42 {\n\t\t\t\tt.Errorf(\"Expected intarg to be 42\")\n\t\t\t}\n\t\t},\n\t\t\"stringArg\": func(n *expect.Note, name expect.Identifier, value string) {\n\t\t\tif string(name) != value {\n\t\t\t\tt.Errorf(\"Got string arg %v expected %v\", value, name)\n\t\t\t}\n\t\t},\n\t\t\"directNote\": func(n *expect.Note) {},\n\t\t\"range\": func(r astutil.Range) {\n\t\t\tif r.Start == token.NoPos {\n\t\t\t\tt.Errorf(\"Range had no valid starting position\")\n\t\t\t}\n\t\t\tif r.EndPos == token.NoPos {\n\t\t\t\tt.Errorf(\"Range had no valid ending position\")\n\t\t\t} else if r.EndPos <= r.Start {\n\t\t\t\tt.Errorf(\"Range ending was not greater than start\")\n\t\t\t}\n\t\t},\n\t\t\"checkEOF\": func(n *expect.Note, p token.Pos) {\n\t\t\tif p <= n.Pos {\n\t\t\t\tt.Errorf(\"EOF was before the checkEOF note\")\n\t\t\t}\n\t\t},\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// We expect to have walked the @check annotations in all .go files,\n\t// including _test.go files (XTest or otherwise). But to have walked the\n\t// non-_test.go files only once. Hence wantCheck = 3 (testdata/test.go) + 1\n\t// (testdata/test_test.go) + 1 (testdata/x_test.go)\n\twantCheck := 7\n\tif wantCheck != checkCount {\n\t\tt.Fatalf(\"Expected @check count of %v; got %v\", wantCheck, checkCount)\n\t}\n}\n"
  },
  {
    "path": "internal/packagestest/export.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage packagestest creates temporary projects on disk for testing go tools on.\n\nBy changing the exporter used, you can create projects for multiple build\nsystems from the same description, and run the same tests on them in many\ncases.\n\n# Example\n\nAs an example of packagestest use, consider the following test that runs\nthe 'go list' command on the specified modules:\n\n\t// TestGoList exercises the 'go list' command in module mode and in GOPATH mode.\n\tfunc TestGoList(t *testing.T) { packagestest.TestAll(t, testGoList) }\n\tfunc testGoList(t *testing.T, x packagestest.Exporter) {\n\t\te := packagestest.Export(t, x, []packagestest.Module{\n\t\t\t{\n\t\t\t\tName: \"gopher.example/repoa\",\n\t\t\t\tFiles: map[string]interface{}{\n\t\t\t\t\t\"a/a.go\": \"package a\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"gopher.example/repob\",\n\t\t\t\tFiles: map[string]interface{}{\n\t\t\t\t\t\"b/b.go\": \"package b\",\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tdefer e.Cleanup()\n\n\t\tcmd := exec.Command(\"go\", \"list\", \"gopher.example/...\")\n\t\tcmd.Dir = e.Config.Dir\n\t\tcmd.Env = e.Config.Env\n\t\tout, err := cmd.Output()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tt.Logf(\"'go list gopher.example/...' with %s mode layout:\\n%s\", x.Name(), out)\n\t}\n\nTestGoList uses TestAll to exercise the 'go list' command with all\nexporters known to packagestest. Currently, packagestest includes\nexporters that produce module mode layouts and GOPATH mode layouts.\nRunning the test with verbose output will print:\n\n\t=== RUN   TestGoList\n\t=== RUN   TestGoList/GOPATH\n\t=== RUN   TestGoList/Modules\n\t--- PASS: TestGoList (0.21s)\n\t    --- PASS: TestGoList/GOPATH (0.03s)\n\t        main_test.go:36: 'go list gopher.example/...' with GOPATH mode layout:\n\t            gopher.example/repoa/a\n\t            gopher.example/repob/b\n\t    --- PASS: TestGoList/Modules (0.18s)\n\t        main_test.go:36: 'go list gopher.example/...' with Modules mode layout:\n\t            gopher.example/repoa/a\n\t            gopher.example/repob/b\n*/\npackage packagestest\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar (\n\tskipCleanup = flag.Bool(\"skip-cleanup\", false, \"Do not delete the temporary export folders\") // for debugging\n)\n\n// ErrUnsupported indicates an error due to an operation not supported on the\n// current platform.\nvar ErrUnsupported = errors.New(\"operation is not supported\")\n\n// Module is a representation of a go module.\ntype Module struct {\n\t// Name is the base name of the module as it would be in the go.mod file.\n\tName string\n\t// Files is the set of source files for all packages that make up the module.\n\t// The keys are the file fragment that follows the module name, the value can\n\t// be a string or byte slice, in which case it is the contents of the\n\t// file, otherwise it must be a Writer function.\n\tFiles map[string]any\n\n\t// Overlay is the set of source file overlays for the module.\n\t// The keys are the file fragment as in the Files configuration.\n\t// The values are the in memory overlay content for the file.\n\tOverlay map[string][]byte\n}\n\n// A Writer is a function that writes out a test file.\n// It is provided the name of the file to write, and may return an error if it\n// cannot write the file.\n// These are used as the content of the Files map in a Module.\ntype Writer func(filename string) error\n\n// Exported is returned by the Export function to report the structure that was produced on disk.\ntype Exported struct {\n\t// Config is a correctly configured packages.Config ready to be passed to packages.Load.\n\t// Exactly what it will contain varies depending on the Exporter being used.\n\tConfig *packages.Config\n\n\t// Modules is the module description that was used to produce this exported data set.\n\tModules []Module\n\n\tExpectFileSet *token.FileSet // The file set used when parsing expectations\n\n\tExporter Exporter                     // the exporter used\n\ttemp     string                       // the temporary directory that was exported to\n\tprimary  string                       // the first non GOROOT module that was exported\n\twritten  map[string]map[string]string // the full set of exported files\n\tnotes    []*expect.Note               // The list of expectations extracted from go source files\n\tmarkers  map[string]astutil.Range     // The set of markers extracted from go source files\n}\n\n// Exporter implementations are responsible for converting from the generic description of some\n// test data to a driver specific file layout.\ntype Exporter interface {\n\t// Name reports the name of the exporter, used in logging and sub-test generation.\n\tName() string\n\t// Filename reports the system filename for test data source file.\n\t// It is given the base directory, the module the file is part of and the filename fragment to\n\t// work from.\n\tFilename(exported *Exported, module, fragment string) string\n\t// Finalize is called once all files have been written to write any extra data needed and modify\n\t// the Config to match. It is handed the full list of modules that were encountered while writing\n\t// files.\n\tFinalize(exported *Exported) error\n}\n\n// All is the list of known exporters.\n// This is used by TestAll to run tests with all the exporters.\nvar All = []Exporter{GOPATH, Modules}\n\n// TestAll invokes the testing function once for each exporter registered in\n// the All global.\n// Each exporter will be run as a sub-test named after the exporter being used.\nfunc TestAll(t *testing.T, f func(*testing.T, Exporter)) {\n\tt.Helper()\n\tfor _, e := range All {\n\t\tt.Run(e.Name(), func(t *testing.T) {\n\t\t\tt.Helper()\n\t\t\tf(t, e)\n\t\t})\n\t}\n}\n\n// BenchmarkAll invokes the testing function once for each exporter registered in\n// the All global.\n// Each exporter will be run as a sub-test named after the exporter being used.\nfunc BenchmarkAll(b *testing.B, f func(*testing.B, Exporter)) {\n\tb.Helper()\n\tfor _, e := range All {\n\t\tb.Run(e.Name(), func(b *testing.B) {\n\t\t\tb.Helper()\n\t\t\tf(b, e)\n\t\t})\n\t}\n}\n\n// Export is called to write out a test directory from within a test function.\n// It takes the exporter and the build system agnostic module descriptions, and\n// uses them to build a temporary directory.\n// It returns an Exported with the results of the export.\n// The Exported.Config is prepared for loading from the exported data.\n// You must invoke Exported.Cleanup on the returned value to clean up.\n// The file deletion in the cleanup can be skipped by setting the skip-cleanup\n// flag when invoking the test, allowing the temporary directory to be left for\n// debugging tests.\n//\n// If the Writer for any file within any module returns an error equivalent to\n// ErrUnspported, Export skips the test.\nfunc Export(t testing.TB, exporter Exporter, modules []Module) *Exported {\n\tt.Helper()\n\tif exporter == Modules {\n\t\ttestenv.NeedsTool(t, \"go\")\n\t}\n\n\tdirname := strings.Replace(t.Name(), \"/\", \"_\", -1)\n\tdirname = strings.Replace(dirname, \"#\", \"_\", -1) // duplicate subtests get a #NNN suffix.\n\ttemp, err := os.MkdirTemp(\"\", dirname)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\texported := &Exported{\n\t\tConfig: &packages.Config{\n\t\t\tDir:     temp,\n\t\t\tEnv:     append(os.Environ(), \"GOPACKAGESDRIVER=off\", \"GOROOT=\"), // Clear GOROOT to work around #32849.\n\t\t\tOverlay: make(map[string][]byte),\n\t\t\tTests:   true,\n\t\t\tMode:    packages.LoadImports,\n\t\t},\n\t\tModules:       modules,\n\t\tExporter:      exporter,\n\t\ttemp:          temp,\n\t\tprimary:       modules[0].Name,\n\t\twritten:       map[string]map[string]string{},\n\t\tExpectFileSet: token.NewFileSet(),\n\t}\n\tif testing.Verbose() {\n\t\texported.Config.Logf = t.Logf\n\t}\n\tdefer func() {\n\t\tif t.Failed() || t.Skipped() {\n\t\t\texported.Cleanup()\n\t\t}\n\t}()\n\tfor _, module := range modules {\n\t\t// Create all parent directories before individual files. If any file is a\n\t\t// symlink to a directory, that directory must exist before the symlink is\n\t\t// created or else it may be created with the wrong type on Windows.\n\t\t// (See https://golang.org/issue/39183.)\n\t\tfor fragment := range module.Files {\n\t\t\tfullpath := exporter.Filename(exported, module.Name, filepath.FromSlash(fragment))\n\t\t\tif err := os.MkdirAll(filepath.Dir(fullpath), 0755); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t}\n\n\t\tfor fragment, value := range module.Files {\n\t\t\tfullpath := exporter.Filename(exported, module.Name, filepath.FromSlash(fragment))\n\t\t\twritten, ok := exported.written[module.Name]\n\t\t\tif !ok {\n\t\t\t\twritten = map[string]string{}\n\t\t\t\texported.written[module.Name] = written\n\t\t\t}\n\t\t\twritten[fragment] = fullpath\n\t\t\tswitch value := value.(type) {\n\t\t\tcase Writer:\n\t\t\t\tif err := value(fullpath); err != nil {\n\t\t\t\t\tif errors.Is(err, ErrUnsupported) {\n\t\t\t\t\t\tt.Skip(err)\n\t\t\t\t\t}\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\tcase string:\n\t\t\t\tif err := os.WriteFile(fullpath, []byte(value), 0644); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tt.Fatalf(\"Invalid type %T in files, must be string or Writer\", value)\n\t\t\t}\n\t\t}\n\t\tfor fragment, value := range module.Overlay {\n\t\t\tfullpath := exporter.Filename(exported, module.Name, filepath.FromSlash(fragment))\n\t\t\texported.Config.Overlay[fullpath] = value\n\t\t}\n\t}\n\tif err := exporter.Finalize(exported); err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttestenv.NeedsGoPackagesEnv(t, exported.Config.Env)\n\treturn exported\n}\n\n// Script returns a Writer that writes out contents to the file and sets the\n// executable bit on the created file.\n// It is intended for source files that are shell scripts.\nfunc Script(contents string) Writer {\n\treturn func(filename string) error {\n\t\treturn os.WriteFile(filename, []byte(contents), 0755)\n\t}\n}\n\n// Link returns a Writer that creates a hard link from the specified source to\n// the required file.\n// This is used to link testdata files into the generated testing tree.\n//\n// If hard links to source are not supported on the destination filesystem, the\n// returned Writer returns an error for which errors.Is(_, ErrUnsupported)\n// returns true.\nfunc Link(source string) Writer {\n\treturn func(filename string) error {\n\t\tlinkErr := os.Link(source, filename)\n\n\t\tif linkErr != nil && !builderMustSupportLinks() {\n\t\t\t// Probe to figure out whether Link failed because the Link operation\n\t\t\t// isn't supported.\n\t\t\tif stat, err := openAndStat(source); err == nil {\n\t\t\t\tif err := createEmpty(filename, stat.Mode()); err == nil {\n\t\t\t\t\t// Successfully opened the source and created the destination,\n\t\t\t\t\t// but the result is empty and not a hard-link.\n\t\t\t\t\treturn &os.PathError{Op: \"Link\", Path: filename, Err: ErrUnsupported}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn linkErr\n\t}\n}\n\n// Symlink returns a Writer that creates a symlink from the specified source to the\n// required file.\n// This is used to link testdata files into the generated testing tree.\n//\n// If symlinks to source are not supported on the destination filesystem, the\n// returned Writer returns an error for which errors.Is(_, ErrUnsupported)\n// returns true.\nfunc Symlink(source string) Writer {\n\tif !strings.HasPrefix(source, \".\") {\n\t\tif absSource, err := filepath.Abs(source); err == nil {\n\t\t\tif _, err := os.Stat(source); !os.IsNotExist(err) {\n\t\t\t\tsource = absSource\n\t\t\t}\n\t\t}\n\t}\n\treturn func(filename string) error {\n\t\tsymlinkErr := os.Symlink(source, filename)\n\n\t\tif symlinkErr != nil && !builderMustSupportLinks() {\n\t\t\t// Probe to figure out whether Symlink failed because the Symlink\n\t\t\t// operation isn't supported.\n\t\t\tfullSource := source\n\t\t\tif !filepath.IsAbs(source) {\n\t\t\t\t// Compute the target path relative to the parent of filename, not the\n\t\t\t\t// current working directory.\n\t\t\t\tfullSource = filepath.Join(filename, \"..\", source)\n\t\t\t}\n\t\t\tstat, err := openAndStat(fullSource)\n\t\t\tmode := os.ModePerm\n\t\t\tif err == nil {\n\t\t\t\tmode = stat.Mode()\n\t\t\t} else if !errors.Is(err, os.ErrNotExist) {\n\t\t\t\t// We couldn't open the source, but it might exist. We don't expect to be\n\t\t\t\t// able to portably create a symlink to a file we can't see.\n\t\t\t\treturn symlinkErr\n\t\t\t}\n\n\t\t\tif err := createEmpty(filename, mode|0644); err == nil {\n\t\t\t\t// Successfully opened the source (or verified that it does not exist) and\n\t\t\t\t// created the destination, but we couldn't create it as a symlink.\n\t\t\t\t// Probably the OS just doesn't support symlinks in this context.\n\t\t\t\treturn &os.PathError{Op: \"Symlink\", Path: filename, Err: ErrUnsupported}\n\t\t\t}\n\t\t}\n\n\t\treturn symlinkErr\n\t}\n}\n\n// builderMustSupportLinks reports whether we are running on a Go builder\n// that is known to support hard and symbolic links.\nfunc builderMustSupportLinks() bool {\n\tif os.Getenv(\"GO_BUILDER_NAME\") == \"\" {\n\t\t// Any OS can be configured to mount an exotic filesystem.\n\t\t// Don't make assumptions about what users are running.\n\t\treturn false\n\t}\n\n\tswitch runtime.GOOS {\n\tcase \"windows\", \"plan9\":\n\t\t// Some versions of Windows and all versions of plan9 do not support\n\t\t// symlinks by default.\n\t\treturn false\n\n\tdefault:\n\t\t// All other platforms should support symlinks by default, and our builders\n\t\t// should not do anything unusual that would violate that.\n\t\treturn true\n\t}\n}\n\n// openAndStat attempts to open source for reading.\nfunc openAndStat(source string) (os.FileInfo, error) {\n\tsrc, err := os.Open(source)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstat, err := src.Stat()\n\tsrc.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn stat, nil\n}\n\n// createEmpty creates an empty file or directory (depending on mode)\n// at dst, with the same permissions as mode.\nfunc createEmpty(dst string, mode os.FileMode) error {\n\tif mode.IsDir() {\n\t\treturn os.Mkdir(dst, mode.Perm())\n\t}\n\n\tf, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode.Perm())\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := f.Close(); err != nil {\n\t\tos.Remove(dst) // best-effort\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// Copy returns a Writer that copies a file from the specified source to the\n// required file.\n// This is used to copy testdata files into the generated testing tree.\nfunc Copy(source string) Writer {\n\treturn func(filename string) error {\n\t\tstat, err := os.Stat(source)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !stat.Mode().IsRegular() {\n\t\t\t// cannot copy non-regular files (e.g., directories,\n\t\t\t// symlinks, devices, etc.)\n\t\t\treturn fmt.Errorf(\"cannot copy non regular file %s\", source)\n\t\t}\n\t\treturn copyFile(filename, source, stat.Mode().Perm())\n\t}\n}\n\nfunc copyFile(dest, source string, perm os.FileMode) error {\n\tsrc, err := os.Open(source)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer src.Close()\n\n\tdst, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = io.Copy(dst, src)\n\tif closeErr := dst.Close(); err == nil {\n\t\terr = closeErr\n\t}\n\treturn err\n}\n\n// GroupFilesByModules attempts to map directories to the modules within each directory.\n// This function assumes that the folder is structured in the following way:\n//\n//\tdir/\n//\t\tprimarymod/\n//\t\t\t*.go files\n//\t\t\tpackages\n//\t\t\tgo.mod (optional)\n//\t\tmodules/\n//\t\t\trepoa/\n//\t\t\t\tmod1/\n//\t\t\t\t\t*.go files\n//\t\t\t\t\tpackages\n//\t\t\t\t\tgo.mod (optional)\n//\n// It scans the directory tree anchored at root and adds a Copy writer to the\n// map for every file found.\n// This is to enable the common case in tests where you have a full copy of the\n// package in your testdata.\nfunc GroupFilesByModules(root string) ([]Module, error) {\n\troot = filepath.FromSlash(root)\n\tprimarymodPath := filepath.Join(root, \"primarymod\")\n\n\t_, err := os.Stat(primarymodPath)\n\tif os.IsNotExist(err) {\n\t\treturn nil, fmt.Errorf(\"could not find primarymod folder within %s\", root)\n\t}\n\n\tprimarymod := &Module{\n\t\tName:    root,\n\t\tFiles:   make(map[string]any),\n\t\tOverlay: make(map[string][]byte),\n\t}\n\tmods := map[string]*Module{\n\t\troot: primarymod,\n\t}\n\tmodules := []Module{*primarymod}\n\n\tif err := filepath.Walk(primarymodPath, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif info.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\tfragment, err := filepath.Rel(primarymodPath, path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tprimarymod.Files[filepath.ToSlash(fragment)] = Copy(path)\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\tmodulesPath := filepath.Join(root, \"modules\")\n\tif _, err := os.Stat(modulesPath); os.IsNotExist(err) {\n\t\treturn modules, nil\n\t}\n\n\tvar currentRepo, currentModule string\n\tupdateCurrentModule := func(dir string) {\n\t\tif dir == currentModule {\n\t\t\treturn\n\t\t}\n\t\t// Handle the case where we step into a nested directory that is a module\n\t\t// and then step out into the parent which is also a module.\n\t\t// Example:\n\t\t// - repoa\n\t\t//   - moda\n\t\t//     - go.mod\n\t\t//     - v2\n\t\t//       - go.mod\n\t\t//     - what.go\n\t\t//   - modb\n\t\tfor dir != root {\n\t\t\tif mods[dir] != nil {\n\t\t\t\tcurrentModule = dir\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdir = filepath.Dir(dir)\n\t\t}\n\t}\n\n\tif err := filepath.Walk(modulesPath, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tenclosingDir := filepath.Dir(path)\n\t\t// If the path is not a directory, then we want to add the path to\n\t\t// the files map of the currentModule.\n\t\tif !info.IsDir() {\n\t\t\tupdateCurrentModule(enclosingDir)\n\t\t\tfragment, err := filepath.Rel(currentModule, path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tmods[currentModule].Files[filepath.ToSlash(fragment)] = Copy(path)\n\t\t\treturn nil\n\t\t}\n\t\t// If the path is a directory and it's enclosing folder is equal to\n\t\t// the modules folder, then the path is a new repo.\n\t\tif enclosingDir == modulesPath {\n\t\t\tcurrentRepo = path\n\t\t\treturn nil\n\t\t}\n\t\t// If the path is a directory and it's enclosing folder is not the same\n\t\t// as the current repo and it is not of the form `v1`,`v2`,...\n\t\t// then the path is a folder/package of the current module.\n\t\tif enclosingDir != currentRepo && !versionSuffixRE.MatchString(filepath.Base(path)) {\n\t\t\treturn nil\n\t\t}\n\t\t// If the path is a directory and it's enclosing folder is the current repo\n\t\t// then the path is a new module.\n\t\tmodule, err := filepath.Rel(modulesPath, path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tmods[path] = &Module{\n\t\t\tName:    filepath.ToSlash(module),\n\t\t\tFiles:   make(map[string]any),\n\t\t\tOverlay: make(map[string][]byte),\n\t\t}\n\t\tcurrentModule = path\n\t\tmodules = append(modules, *mods[path])\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\treturn modules, nil\n}\n\n// MustCopyFileTree returns a file set for a module based on a real directory tree.\n// It scans the directory tree anchored at root and adds a Copy writer to the\n// map for every file found. It skips copying files in nested modules.\n// This is to enable the common case in tests where you have a full copy of the\n// package in your testdata.\n// This will panic if there is any kind of error trying to walk the file tree.\nfunc MustCopyFileTree(root string) map[string]any {\n\tresult := map[string]any{}\n\tif err := filepath.Walk(filepath.FromSlash(root), func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif info.IsDir() {\n\t\t\t// skip nested modules.\n\t\t\tif path != root {\n\t\t\t\tif fi, err := os.Stat(filepath.Join(path, \"go.mod\")); err == nil && !fi.IsDir() {\n\t\t\t\t\treturn filepath.SkipDir\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\tfragment, err := filepath.Rel(root, path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresult[filepath.ToSlash(fragment)] = Copy(path)\n\t\treturn nil\n\t}); err != nil {\n\t\tlog.Panic(fmt.Sprintf(\"MustCopyFileTree failed: %v\", err))\n\t}\n\treturn result\n}\n\n// Cleanup removes the temporary directory (unless the --skip-cleanup flag was set)\n// It is safe to call cleanup multiple times.\nfunc (e *Exported) Cleanup() {\n\tif e.temp == \"\" {\n\t\treturn\n\t}\n\tif *skipCleanup {\n\t\tlog.Printf(\"Skipping cleanup of temp dir: %s\", e.temp)\n\t\treturn\n\t}\n\t// Make everything read-write so that the Module exporter's module cache can be deleted.\n\tfilepath.Walk(e.temp, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tif info.IsDir() {\n\t\t\tos.Chmod(path, 0777)\n\t\t}\n\t\treturn nil\n\t})\n\tos.RemoveAll(e.temp) // ignore errors\n\te.temp = \"\"\n}\n\n// Temp returns the temporary directory that was generated.\nfunc (e *Exported) Temp() string {\n\treturn e.temp\n}\n\n// File returns the full path for the given module and file fragment.\nfunc (e *Exported) File(module, fragment string) string {\n\tif m := e.written[module]; m != nil {\n\t\treturn m[fragment]\n\t}\n\treturn \"\"\n}\n\n// FileContents returns the contents of the specified file.\n// It will use the overlay if the file is present, otherwise it will read it\n// from disk.\nfunc (e *Exported) FileContents(filename string) ([]byte, error) {\n\tif content, found := e.Config.Overlay[filename]; found {\n\t\treturn content, nil\n\t}\n\tcontent, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn content, nil\n}\n"
  },
  {
    "path": "internal/packagestest/export_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nvar testdata = []packagestest.Module{{\n\tName: \"golang.org/fake1\",\n\tFiles: map[string]any{\n\t\t\"a.go\": packagestest.Symlink(\"testdata/a.go\"), // broken symlink\n\t\t\"b.go\": \"invalid file contents\",\n\t},\n\tOverlay: map[string][]byte{\n\t\t\"b.go\": []byte(\"package fake1\"),\n\t\t\"c.go\": []byte(\"package fake1\"),\n\t},\n}, {\n\tName: \"golang.org/fake2\",\n\tFiles: map[string]any{\n\t\t\"other/a.go\": \"package fake2\",\n\t},\n}, {\n\tName: \"golang.org/fake2/v2\",\n\tFiles: map[string]any{\n\t\t\"other/a.go\": \"package fake2\",\n\t},\n}, {\n\tName: \"golang.org/fake3@v1.0.0\",\n\tFiles: map[string]any{\n\t\t\"other/a.go\": \"package fake3\",\n\t},\n}, {\n\tName: \"golang.org/fake3@v1.1.0\",\n\tFiles: map[string]any{\n\t\t\"other/a.go\": \"package fake3\",\n\t},\n}}\n\ntype fileTest struct {\n\tmodule, fragment, expect string\n\tcheck                    func(t *testing.T, exported *packagestest.Exported, filename string)\n}\n\nfunc checkFiles(t *testing.T, exported *packagestest.Exported, tests []fileTest) {\n\tfor _, test := range tests {\n\t\texpect := filepath.Join(exported.Temp(), filepath.FromSlash(test.expect))\n\t\tgot := exported.File(test.module, test.fragment)\n\t\tif got == \"\" {\n\t\t\tt.Errorf(\"File %v missing from the output\", expect)\n\t\t} else if got != expect {\n\t\t\tt.Errorf(\"Got file %v, expected %v\", got, expect)\n\t\t}\n\t\tif test.check != nil {\n\t\t\ttest.check(t, exported, got)\n\t\t}\n\t}\n}\n\nfunc checkLink(expect string) func(t *testing.T, exported *packagestest.Exported, filename string) {\n\texpect = filepath.FromSlash(expect)\n\treturn func(t *testing.T, exported *packagestest.Exported, filename string) {\n\t\tif target, err := os.Readlink(filename); err != nil {\n\t\t\tt.Errorf(\"Error checking link %v: %v\", filename, err)\n\t\t} else if target != expect {\n\t\t\tt.Errorf(\"Link %v does not match, got %v expected %v\", filename, target, expect)\n\t\t}\n\t}\n}\n\nfunc checkContent(expect string) func(t *testing.T, exported *packagestest.Exported, filename string) {\n\treturn func(t *testing.T, exported *packagestest.Exported, filename string) {\n\t\tif content, err := exported.FileContents(filename); err != nil {\n\t\t\tt.Errorf(\"Error reading %v: %v\", filename, err)\n\t\t} else if string(content) != expect {\n\t\t\tt.Errorf(\"Content of %v does not match, got %v expected %v\", filename, string(content), expect)\n\t\t}\n\t}\n}\n\nfunc TestGroupFilesByModules(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\ttestdir string\n\t\twant    []packagestest.Module\n\t}{\n\t\t{\n\t\t\ttestdir: \"testdata/groups/one\",\n\t\t\twant: []packagestest.Module{\n\t\t\t\t{\n\t\t\t\t\tName: \"testdata/groups/one\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"main.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/extra\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"help.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ttestdir: \"testdata/groups/two\",\n\t\t\twant: []packagestest.Module{\n\t\t\t\t{\n\t\t\t\t\tName: \"testdata/groups/two\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"main.go\":           true,\n\t\t\t\t\t\t\"expect/yo.go\":      true,\n\t\t\t\t\t\t\"expect/yo_test.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/extra\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"yo.go\":        true,\n\t\t\t\t\t\t\"geez/help.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/extra/v2\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"me.go\":        true,\n\t\t\t\t\t\t\"geez/help.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/tempmod\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"main.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/what@v1.0.0\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"main.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"example.com/what@v1.1.0\",\n\t\t\t\t\tFiles: map[string]any{\n\t\t\t\t\t\t\"main.go\": true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(tt.testdir, func(t *testing.T) {\n\t\t\tgot, err := packagestest.GroupFilesByModules(tt.testdir)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"could not group files %v\", err)\n\t\t\t}\n\t\t\tif len(got) != len(tt.want) {\n\t\t\t\tt.Fatalf(\"%s: wanted %d modules but got %d\", tt.testdir, len(tt.want), len(got))\n\t\t\t}\n\t\t\tfor i, w := range tt.want {\n\t\t\t\tg := got[i]\n\t\t\t\tif filepath.FromSlash(g.Name) != filepath.FromSlash(w.Name) {\n\t\t\t\t\tt.Fatalf(\"%s: wanted module[%d].Name to be %s but got %s\", tt.testdir, i, filepath.FromSlash(w.Name), filepath.FromSlash(g.Name))\n\t\t\t\t}\n\t\t\t\tfor fh := range w.Files {\n\t\t\t\t\tif _, ok := g.Files[fh]; !ok {\n\t\t\t\t\t\tt.Fatalf(\"%s, module[%d]: wanted %s but could not find\", tt.testdir, i, fh)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor fh := range g.Files {\n\t\t\t\t\tif _, ok := w.Files[fh]; !ok {\n\t\t\t\t\t\tt.Fatalf(\"%s, module[%d]: found unexpected file %s\", tt.testdir, i, fh)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMustCopyFiles(t *testing.T) {\n\t// Create the following test directory structure in a temporary directory.\n\tsrc := map[string]string{\n\t\t// copies all files under the specified directory.\n\t\t\"go.mod\": \"module example.com\",\n\t\t\"m.go\":   \"package m\",\n\t\t\"a/a.go\": \"package a\",\n\t\t// contents from a nested module shouldn't be copied.\n\t\t\"nested/go.mod\": \"module example.com/nested\",\n\t\t\"nested/m.go\":   \"package nested\",\n\t\t\"nested/b/b.go\": \"package b\",\n\t}\n\n\ttmpDir, err := os.MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create a temporary directory: %v\", err)\n\t}\n\tdefer os.RemoveAll(tmpDir)\n\n\tfor fragment, contents := range src {\n\t\tfullpath := filepath.Join(tmpDir, filepath.FromSlash(fragment))\n\t\tif err := os.MkdirAll(filepath.Dir(fullpath), 0755); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(fullpath, []byte(contents), 0644); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tcopied := packagestest.MustCopyFileTree(tmpDir)\n\tvar got []string\n\tfor fragment := range copied {\n\t\tgot = append(got, filepath.ToSlash(fragment))\n\t}\n\twant := []string{\"go.mod\", \"m.go\", \"a/a.go\"}\n\n\tsort.Strings(got)\n\tsort.Strings(want)\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"packagestest.MustCopyFileTree = %v, want %v\", got, want)\n\t}\n\n\t// packagestest.Export is happy.\n\texported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{{\n\t\tName:  \"example.com\",\n\t\tFiles: packagestest.MustCopyFileTree(tmpDir),\n\t}})\n\tdefer exported.Cleanup()\n}\n"
  },
  {
    "path": "internal/packagestest/gopath.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest\n\nimport (\n\t\"path\"\n\t\"path/filepath\"\n)\n\n// GOPATH is the exporter that produces GOPATH layouts.\n// Each \"module\" is put in it's own GOPATH entry to help test complex cases.\n// Given the two files\n//\n//\tgolang.org/repoa#a/a.go\n//\tgolang.org/repob#b/b.go\n//\n// You would get the directory layout\n//\n//\t/sometemporarydirectory\n//\t├── repoa\n//\t│   └── src\n//\t│       └── golang.org\n//\t│           └── repoa\n//\t│               └── a\n//\t│                   └── a.go\n//\t└── repob\n//\t    └── src\n//\t        └── golang.org\n//\t            └── repob\n//\t                └── b\n//\t                    └── b.go\n//\n// GOPATH would be set to\n//\n//\t/sometemporarydirectory/repoa;/sometemporarydirectory/repob\n//\n// and the working directory would be\n//\n//\t/sometemporarydirectory/repoa/src\nvar GOPATH = gopath{}\n\ntype gopath struct{}\n\nfunc (gopath) Name() string {\n\treturn \"GOPATH\"\n}\n\nfunc (gopath) Filename(exported *Exported, module, fragment string) string {\n\treturn filepath.Join(gopathDir(exported, module), \"src\", module, fragment)\n}\n\nfunc (gopath) Finalize(exported *Exported) error {\n\texported.Config.Env = append(exported.Config.Env, \"GO111MODULE=off\")\n\tgopath := \"\"\n\tfor module := range exported.written {\n\t\tif gopath != \"\" {\n\t\t\tgopath += string(filepath.ListSeparator)\n\t\t}\n\t\tdir := gopathDir(exported, module)\n\t\tgopath += dir\n\t\tif module == exported.primary {\n\t\t\texported.Config.Dir = filepath.Join(dir, \"src\")\n\t\t}\n\t}\n\texported.Config.Env = append(exported.Config.Env, \"GOPATH=\"+gopath)\n\treturn nil\n}\n\nfunc gopathDir(exported *Exported, module string) string {\n\tdir := path.Base(module)\n\tif versionSuffixRE.MatchString(dir) {\n\t\tdir = path.Base(path.Dir(module)) + \"_\" + dir\n\t}\n\treturn filepath.Join(exported.temp, dir)\n}\n"
  },
  {
    "path": "internal/packagestest/gopath_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestGOPATHExport(t *testing.T) {\n\texported := packagestest.Export(t, packagestest.GOPATH, testdata)\n\tdefer exported.Cleanup()\n\t// Check that the cfg contains all the right bits\n\tvar expectDir = filepath.Join(exported.Temp(), \"fake1\", \"src\")\n\tif exported.Config.Dir != expectDir {\n\t\tt.Errorf(\"Got working directory %v expected %v\", exported.Config.Dir, expectDir)\n\t}\n\tcheckFiles(t, exported, []fileTest{\n\t\t{\"golang.org/fake1\", \"a.go\", \"fake1/src/golang.org/fake1/a.go\", checkLink(\"testdata/a.go\")},\n\t\t{\"golang.org/fake1\", \"b.go\", \"fake1/src/golang.org/fake1/b.go\", checkContent(\"package fake1\")},\n\t\t{\"golang.org/fake2\", \"other/a.go\", \"fake2/src/golang.org/fake2/other/a.go\", checkContent(\"package fake2\")},\n\t\t{\"golang.org/fake2/v2\", \"other/a.go\", \"fake2_v2/src/golang.org/fake2/v2/other/a.go\", checkContent(\"package fake2\")},\n\t})\n}\n"
  },
  {
    "path": "internal/packagestest/modules.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/gocommand\"\n\t\"golang.org/x/tools/internal/proxydir\"\n)\n\n// Modules is the exporter that produces module layouts.\n// Each \"repository\" is put in its own module, and the module file generated\n// will have replace directives for all other modules.\n// Given the two files\n//\n//\tgolang.org/repoa#a/a.go\n//\tgolang.org/repob#b/b.go\n//\n// You would get the directory layout\n//\n//\t/sometemporarydirectory\n//\t├── repoa\n//\t│   ├── a\n//\t│   │   └── a.go\n//\t│   └── go.mod\n//\t└── repob\n//\t    ├── b\n//\t    │   └── b.go\n//\t    └── go.mod\n//\n// and the working directory would be\n//\n//\t/sometemporarydirectory/repoa\nvar Modules = modules{}\n\ntype modules struct{}\n\ntype moduleAtVersion struct {\n\tmodule  string\n\tversion string\n}\n\nfunc (modules) Name() string {\n\treturn \"Modules\"\n}\n\nfunc (modules) Filename(exported *Exported, module, fragment string) string {\n\tif module == exported.primary {\n\t\treturn filepath.Join(primaryDir(exported), fragment)\n\t}\n\treturn filepath.Join(moduleDir(exported, module), fragment)\n}\n\nfunc (modules) Finalize(exported *Exported) error {\n\t// Write out the primary module. This module can use symlinks and\n\t// other weird stuff, and will be the working dir for the go command.\n\t// It depends on all the other modules.\n\tprimaryDir := primaryDir(exported)\n\tif err := os.MkdirAll(primaryDir, 0755); err != nil {\n\t\treturn err\n\t}\n\texported.Config.Dir = primaryDir\n\tif exported.written[exported.primary] == nil {\n\t\texported.written[exported.primary] = make(map[string]string)\n\t}\n\n\t// Create a map of modulepath -> {module, version} for modulepaths\n\t// that are of the form `repoa/mod1@v1.1.0`.\n\tversions := make(map[string]moduleAtVersion)\n\tfor module := range exported.written {\n\t\tif splt := strings.Split(module, \"@\"); len(splt) > 1 {\n\t\t\tversions[module] = moduleAtVersion{\n\t\t\t\tmodule:  splt[0],\n\t\t\t\tversion: splt[1],\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the primary module already has a go.mod, write the contents to a temp\n\t// go.mod for now and then we will reset it when we are getting all the markers.\n\tif gomod := exported.written[exported.primary][\"go.mod\"]; gomod != \"\" {\n\t\tcontents, err := os.ReadFile(gomod)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := os.WriteFile(gomod+\".temp\", contents, 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\texported.written[exported.primary][\"go.mod\"] = filepath.Join(primaryDir, \"go.mod\")\n\tvar primaryGomod bytes.Buffer\n\tfmt.Fprintf(&primaryGomod, \"module %s\\nrequire (\\n\", exported.primary)\n\tfor other := range exported.written {\n\t\tif other == exported.primary {\n\t\t\tcontinue\n\t\t}\n\t\tversion := moduleVersion(other)\n\t\t// If other is of the form `repo1/mod1@v1.1.0`,\n\t\t// then we need to extract the module and the version.\n\t\tif v, ok := versions[other]; ok {\n\t\t\tother = v.module\n\t\t\tversion = v.version\n\t\t}\n\t\tfmt.Fprintf(&primaryGomod, \"\\t%v %v\\n\", other, version)\n\t}\n\tfmt.Fprintf(&primaryGomod, \")\\n\")\n\tif err := os.WriteFile(filepath.Join(primaryDir, \"go.mod\"), primaryGomod.Bytes(), 0644); err != nil {\n\t\treturn err\n\t}\n\n\t// Create the mod cache so we can rename it later, even if we don't need it.\n\tif err := os.MkdirAll(modCache(exported), 0755); err != nil {\n\t\treturn err\n\t}\n\n\t// Write out the go.mod files for the other modules.\n\tfor module, files := range exported.written {\n\t\tif module == exported.primary {\n\t\t\tcontinue\n\t\t}\n\t\tdir := moduleDir(exported, module)\n\t\tmodfile := filepath.Join(dir, \"go.mod\")\n\t\t// If other is of the form `repo1/mod1@v1.1.0`,\n\t\t// then we need to extract the module name without the version.\n\t\tif v, ok := versions[module]; ok {\n\t\t\tmodule = v.module\n\t\t}\n\t\tif err := os.WriteFile(modfile, []byte(\"module \"+module+\"\\n\"), 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfiles[\"go.mod\"] = modfile\n\t}\n\n\t// Zip up all the secondary modules into the proxy dir.\n\tmodProxyDir := filepath.Join(exported.temp, \"modproxy\")\n\tfor module, files := range exported.written {\n\t\tif module == exported.primary {\n\t\t\tcontinue\n\t\t}\n\t\tversion := moduleVersion(module)\n\t\t// If other is of the form `repo1/mod1@v1.1.0`,\n\t\t// then we need to extract the module and the version.\n\t\tif v, ok := versions[module]; ok {\n\t\t\tmodule = v.module\n\t\t\tversion = v.version\n\t\t}\n\t\tif err := writeModuleFiles(modProxyDir, module, version, files); err != nil {\n\t\t\treturn fmt.Errorf(\"creating module proxy dir for %v: %v\", module, err)\n\t\t}\n\t}\n\n\t// Discard the original mod cache dir, which contained the files written\n\t// for us by Export.\n\tif err := os.Rename(modCache(exported), modCache(exported)+\".orig\"); err != nil {\n\t\treturn err\n\t}\n\texported.Config.Env = append(exported.Config.Env,\n\t\t\"GO111MODULE=on\",\n\t\t\"GOPATH=\"+filepath.Join(exported.temp, \"modcache\"),\n\t\t\"GOMODCACHE=\",\n\t\t\"GOPROXY=\"+proxydir.ToURL(modProxyDir),\n\t\t\"GOSUMDB=off\",\n\t)\n\n\t// Run go mod download to recreate the mod cache dir with all the extra\n\t// stuff in cache. All the files created by Export should be recreated.\n\tinv := gocommand.Invocation{\n\t\tVerb:       \"mod\",\n\t\tArgs:       []string{\"download\", \"all\"},\n\t\tEnv:        exported.Config.Env,\n\t\tBuildFlags: exported.Config.BuildFlags,\n\t\tWorkingDir: exported.Config.Dir,\n\t}\n\t_, err := new(gocommand.Runner).Run(context.Background(), inv)\n\treturn err\n}\n\nfunc writeModuleFiles(rootDir, module, ver string, filePaths map[string]string) error {\n\tfileData := make(map[string][]byte)\n\tfor name, path := range filePaths {\n\t\tcontents, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfileData[name] = contents\n\t}\n\treturn proxydir.WriteModuleVersion(rootDir, module, ver, fileData)\n}\n\nfunc modCache(exported *Exported) string {\n\treturn filepath.Join(exported.temp, \"modcache/pkg/mod\")\n}\n\nfunc primaryDir(exported *Exported) string {\n\treturn filepath.Join(exported.temp, path.Base(exported.primary))\n}\n\nfunc moduleDir(exported *Exported, module string) string {\n\tif strings.Contains(module, \"@\") {\n\t\treturn filepath.Join(modCache(exported), module)\n\t}\n\treturn filepath.Join(modCache(exported), path.Dir(module), path.Base(module)+\"@\"+moduleVersion(module))\n}\n\nvar versionSuffixRE = regexp.MustCompile(`v\\d+`)\n\nfunc moduleVersion(module string) string {\n\tif versionSuffixRE.MatchString(path.Base(module)) {\n\t\treturn path.Base(module) + \".0.0\"\n\t}\n\treturn \"v1.0.0\"\n}\n"
  },
  {
    "path": "internal/packagestest/modules_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage packagestest_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/packagestest\"\n)\n\nfunc TestModulesExport(t *testing.T) {\n\texported := packagestest.Export(t, packagestest.Modules, testdata)\n\tdefer exported.Cleanup()\n\t// Check that the cfg contains all the right bits\n\tvar expectDir = filepath.Join(exported.Temp(), \"fake1\")\n\tif exported.Config.Dir != expectDir {\n\t\tt.Errorf(\"Got working directory %v expected %v\", exported.Config.Dir, expectDir)\n\t}\n\tcheckFiles(t, exported, []fileTest{\n\t\t{\"golang.org/fake1\", \"go.mod\", \"fake1/go.mod\", nil},\n\t\t{\"golang.org/fake1\", \"a.go\", \"fake1/a.go\", checkLink(\"testdata/a.go\")},\n\t\t{\"golang.org/fake1\", \"b.go\", \"fake1/b.go\", checkContent(\"package fake1\")},\n\t\t{\"golang.org/fake2\", \"go.mod\", \"modcache/pkg/mod/golang.org/fake2@v1.0.0/go.mod\", nil},\n\t\t{\"golang.org/fake2\", \"other/a.go\", \"modcache/pkg/mod/golang.org/fake2@v1.0.0/other/a.go\", checkContent(\"package fake2\")},\n\t\t{\"golang.org/fake2/v2\", \"other/a.go\", \"modcache/pkg/mod/golang.org/fake2/v2@v2.0.0/other/a.go\", checkContent(\"package fake2\")},\n\t\t{\"golang.org/fake3@v1.1.0\", \"other/a.go\", \"modcache/pkg/mod/golang.org/fake3@v1.1.0/other/a.go\", checkContent(\"package fake3\")},\n\t\t{\"golang.org/fake3@v1.0.0\", \"other/a.go\", \"modcache/pkg/mod/golang.org/fake3@v1.0.0/other/a.go\", nil},\n\t})\n}\n"
  },
  {
    "path": "internal/packagestest/testdata/groups/one/modules/example.com/extra/help.go",
    "content": "package extra"
  },
  {
    "path": "internal/packagestest/testdata/groups/one/primarymod/main.go",
    "content": "package one"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/extra/geez/help.go",
    "content": "package example.com/extra/geez"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/extra/v2/geez/help.go",
    "content": "package example.com/extra/geez"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/extra/v2/me.go",
    "content": "package example.com/extra"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/extra/yo.go",
    "content": "package example.com/extra"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/tempmod/main.go",
    "content": "package example.com/tempmod"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/what@v1.0.0/main.go",
    "content": "package example.com/what"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/modules/example.com/what@v1.1.0/main.go",
    "content": "package example.com/what"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/primarymod/expect/yo.go",
    "content": "package expect\n\nvar X int //@check(\"X\", \"X\")\n"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/primarymod/expect/yo_test.go",
    "content": "package expect_test\n\nimport (\n\t\"testdata/groups/two/expect\"\n\t\"testing\"\n)\n\nfunc TestX(t *testing.T) {\n\t_ = expect.X //@check(\"X\", \"X\")\n}\n"
  },
  {
    "path": "internal/packagestest/testdata/groups/two/primarymod/main.go",
    "content": "package two"
  },
  {
    "path": "internal/packagestest/testdata/test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage fake1\n\n// This is a test file for the behaviors in Exported.Expect.\n\ntype AThing string //@AThing,mark(StringThing, \"AThing\"),mark(REThing,re`.T.*g`)\n\ntype Match string //@check(\"Match\",re`[[:upper:]]`)\n\n//@check(AThing, StringThing)\n//@check(AThing, REThing)\n\n//@boolArg(true, false)\n//@intArg(42)\n//@stringArg(PlainString, \"PlainString\")\n//@stringArg(IdentAsString,IdentAsString)\n//@directNote()\n//@range(AThing)\n\n// The following test should remain at the bottom of the file\n//@checkEOF(EOF)\n"
  },
  {
    "path": "internal/packagestest/testdata/test_test.go",
    "content": "package fake1\n\ntype ATestType string //@check(\"ATestType\",\"ATestType\")\n"
  },
  {
    "path": "internal/packagestest/testdata/x_test.go",
    "content": "package fake1_test\n\ntype AnXTestType string //@check(\"AnXTestType\",\"AnXTestType\")\n"
  },
  {
    "path": "internal/pkgbits/codes.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\n// A Code is an enum value that can be encoded into bitstreams.\n//\n// Code types are preferable for enum types, because they allow\n// Decoder to detect desyncs.\ntype Code interface {\n\t// Marker returns the SyncMarker for the Code's dynamic type.\n\tMarker() SyncMarker\n\n\t// Value returns the Code's ordinal value.\n\tValue() int\n}\n\n// A CodeVal distinguishes among go/constant.Value encodings.\ntype CodeVal int\n\nfunc (c CodeVal) Marker() SyncMarker { return SyncVal }\nfunc (c CodeVal) Value() int         { return int(c) }\n\n// Note: These values are public and cannot be changed without\n// updating the go/types importers.\n\nconst (\n\tValBool CodeVal = iota\n\tValString\n\tValInt64\n\tValBigInt\n\tValBigRat\n\tValBigFloat\n)\n\n// A CodeType distinguishes among go/types.Type encodings.\ntype CodeType int\n\nfunc (c CodeType) Marker() SyncMarker { return SyncType }\nfunc (c CodeType) Value() int         { return int(c) }\n\n// Note: These values are public and cannot be changed without\n// updating the go/types importers.\n\nconst (\n\tTypeBasic CodeType = iota\n\tTypeNamed\n\tTypePointer\n\tTypeSlice\n\tTypeArray\n\tTypeChan\n\tTypeMap\n\tTypeSignature\n\tTypeStruct\n\tTypeInterface\n\tTypeUnion\n\tTypeTypeParam\n)\n\n// A CodeObj distinguishes among go/types.Object encodings.\ntype CodeObj int\n\nfunc (c CodeObj) Marker() SyncMarker { return SyncCodeObj }\nfunc (c CodeObj) Value() int         { return int(c) }\n\n// Note: These values are public and cannot be changed without\n// updating the go/types importers.\n\nconst (\n\tObjAlias CodeObj = iota\n\tObjConst\n\tObjType\n\tObjFunc\n\tObjVar\n\tObjStub\n)\n"
  },
  {
    "path": "internal/pkgbits/decoder.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"io\"\n\t\"math/big\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n)\n\n// A PkgDecoder provides methods for decoding a package's Unified IR\n// export data.\ntype PkgDecoder struct {\n\t// version is the file format version.\n\tversion Version\n\n\t// sync indicates whether the file uses sync markers.\n\tsync bool\n\n\t// pkgPath is the package path for the package to be decoded.\n\t//\n\t// TODO(mdempsky): Remove; unneeded since CL 391014.\n\tpkgPath string\n\n\t// elemData is the full data payload of the encoded package.\n\t// Elements are densely and contiguously packed together.\n\t//\n\t// The last 8 bytes of elemData are the package fingerprint.\n\telemData string\n\n\t// elemEnds stores the byte-offset end positions of element\n\t// bitstreams within elemData.\n\t//\n\t// For example, element I's bitstream data starts at elemEnds[I-1]\n\t// (or 0, if I==0) and ends at elemEnds[I].\n\t//\n\t// Note: elemEnds is indexed by absolute indices, not\n\t// section-relative indices.\n\telemEnds []uint32\n\n\t// elemEndsEnds stores the index-offset end positions of relocation\n\t// sections within elemEnds.\n\t//\n\t// For example, section K's end positions start at elemEndsEnds[K-1]\n\t// (or 0, if K==0) and end at elemEndsEnds[K].\n\telemEndsEnds [numRelocs]uint32\n\n\tscratchRelocEnt []RelocEnt\n}\n\n// PkgPath returns the package path for the package\n//\n// TODO(mdempsky): Remove; unneeded since CL 391014.\nfunc (pr *PkgDecoder) PkgPath() string { return pr.pkgPath }\n\n// SyncMarkers reports whether pr uses sync markers.\nfunc (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }\n\n// NewPkgDecoder returns a PkgDecoder initialized to read the Unified\n// IR export data from input. pkgPath is the package path for the\n// compilation unit that produced the export data.\nfunc NewPkgDecoder(pkgPath, input string) PkgDecoder {\n\tpr := PkgDecoder{\n\t\tpkgPath: pkgPath,\n\t}\n\n\t// TODO(mdempsky): Implement direct indexing of input string to\n\t// avoid copying the position information.\n\n\tr := strings.NewReader(input)\n\n\tvar ver uint32\n\tassert(binary.Read(r, binary.LittleEndian, &ver) == nil)\n\tpr.version = Version(ver)\n\n\tif pr.version >= numVersions {\n\t\tpanic(fmt.Errorf(\"cannot decode %q, export data version %d is greater than maximum supported version %d\", pkgPath, pr.version, numVersions-1))\n\t}\n\n\tif pr.version.Has(Flags) {\n\t\tvar flags uint32\n\t\tassert(binary.Read(r, binary.LittleEndian, &flags) == nil)\n\t\tpr.sync = flags&flagSyncMarkers != 0\n\t}\n\n\tassert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)\n\n\tpr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1])\n\tassert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil)\n\n\tpos, err := r.Seek(0, io.SeekCurrent)\n\tassert(err == nil)\n\n\tpr.elemData = input[pos:]\n\n\tconst fingerprintSize = 8\n\tassert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))\n\n\treturn pr\n}\n\n// NumElems returns the number of elements in section k.\nfunc (pr *PkgDecoder) NumElems(k RelocKind) int {\n\tcount := int(pr.elemEndsEnds[k])\n\tif k > 0 {\n\t\tcount -= int(pr.elemEndsEnds[k-1])\n\t}\n\treturn count\n}\n\n// TotalElems returns the total number of elements across all sections.\nfunc (pr *PkgDecoder) TotalElems() int {\n\treturn len(pr.elemEnds)\n}\n\n// Fingerprint returns the package fingerprint.\nfunc (pr *PkgDecoder) Fingerprint() [8]byte {\n\tvar fp [8]byte\n\tcopy(fp[:], pr.elemData[len(pr.elemData)-8:])\n\treturn fp\n}\n\n// AbsIdx returns the absolute index for the given (section, index)\n// pair.\nfunc (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {\n\tabsIdx := int(idx)\n\tif k > 0 {\n\t\tabsIdx += int(pr.elemEndsEnds[k-1])\n\t}\n\tif absIdx >= int(pr.elemEndsEnds[k]) {\n\t\tpanicf(\"%v:%v is out of bounds; %v\", k, idx, pr.elemEndsEnds)\n\t}\n\treturn absIdx\n}\n\n// DataIdx returns the raw element bitstream for the given (section,\n// index) pair.\nfunc (pr *PkgDecoder) DataIdx(k RelocKind, idx Index) string {\n\tabsIdx := pr.AbsIdx(k, idx)\n\n\tvar start uint32\n\tif absIdx > 0 {\n\t\tstart = pr.elemEnds[absIdx-1]\n\t}\n\tend := pr.elemEnds[absIdx]\n\n\treturn pr.elemData[start:end]\n}\n\n// StringIdx returns the string value for the given string index.\nfunc (pr *PkgDecoder) StringIdx(idx Index) string {\n\treturn pr.DataIdx(RelocString, idx)\n}\n\n// NewDecoder returns a Decoder for the given (section, index) pair,\n// and decodes the given SyncMarker from the element bitstream.\nfunc (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {\n\tr := pr.NewDecoderRaw(k, idx)\n\tr.Sync(marker)\n\treturn r\n}\n\n// TempDecoder returns a Decoder for the given (section, index) pair,\n// and decodes the given SyncMarker from the element bitstream.\n// If possible the Decoder should be RetireDecoder'd when it is no longer\n// needed, this will avoid heap allocations.\nfunc (pr *PkgDecoder) TempDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {\n\tr := pr.TempDecoderRaw(k, idx)\n\tr.Sync(marker)\n\treturn r\n}\n\nfunc (pr *PkgDecoder) RetireDecoder(d *Decoder) {\n\tpr.scratchRelocEnt = d.Relocs\n\td.Relocs = nil\n}\n\n// NewDecoderRaw returns a Decoder for the given (section, index) pair.\n//\n// Most callers should use NewDecoder instead.\nfunc (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {\n\tr := Decoder{\n\t\tcommon: pr,\n\t\tk:      k,\n\t\tIdx:    idx,\n\t}\n\n\tr.Data.Reset(pr.DataIdx(k, idx))\n\tr.Sync(SyncRelocs)\n\tr.Relocs = make([]RelocEnt, r.Len())\n\tfor i := range r.Relocs {\n\t\tr.Sync(SyncReloc)\n\t\tr.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}\n\t}\n\n\treturn r\n}\n\nfunc (pr *PkgDecoder) TempDecoderRaw(k RelocKind, idx Index) Decoder {\n\tr := Decoder{\n\t\tcommon: pr,\n\t\tk:      k,\n\t\tIdx:    idx,\n\t}\n\n\tr.Data.Reset(pr.DataIdx(k, idx))\n\tr.Sync(SyncRelocs)\n\tl := r.Len()\n\tif cap(pr.scratchRelocEnt) >= l {\n\t\tr.Relocs = pr.scratchRelocEnt[:l]\n\t\tpr.scratchRelocEnt = nil\n\t} else {\n\t\tr.Relocs = make([]RelocEnt, l)\n\t}\n\tfor i := range r.Relocs {\n\t\tr.Sync(SyncReloc)\n\t\tr.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}\n\t}\n\n\treturn r\n}\n\n// A Decoder provides methods for decoding an individual element's\n// bitstream data.\ntype Decoder struct {\n\tcommon *PkgDecoder\n\n\tRelocs []RelocEnt\n\tData   strings.Reader\n\n\tk   RelocKind\n\tIdx Index\n}\n\nfunc (r *Decoder) checkErr(err error) {\n\tif err != nil {\n\t\tpanicf(\"unexpected decoding error: %w\", err)\n\t}\n}\n\nfunc (r *Decoder) rawUvarint() uint64 {\n\tx, err := readUvarint(&r.Data)\n\tr.checkErr(err)\n\treturn x\n}\n\n// readUvarint is a type-specialized copy of encoding/binary.ReadUvarint.\n// This avoids the interface conversion and thus has better escape properties,\n// which flows up the stack.\nfunc readUvarint(r *strings.Reader) (uint64, error) {\n\tvar x uint64\n\tvar s uint\n\tfor i := range binary.MaxVarintLen64 {\n\t\tb, err := r.ReadByte()\n\t\tif err != nil {\n\t\t\tif i > 0 && err == io.EOF {\n\t\t\t\terr = io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn x, err\n\t\t}\n\t\tif b < 0x80 {\n\t\t\tif i == binary.MaxVarintLen64-1 && b > 1 {\n\t\t\t\treturn x, overflow\n\t\t\t}\n\t\t\treturn x | uint64(b)<<s, nil\n\t\t}\n\t\tx |= uint64(b&0x7f) << s\n\t\ts += 7\n\t}\n\treturn x, overflow\n}\n\nvar overflow = errors.New(\"pkgbits: readUvarint overflows a 64-bit integer\")\n\nfunc (r *Decoder) rawVarint() int64 {\n\tux := r.rawUvarint()\n\n\t// Zig-zag decode.\n\tx := int64(ux >> 1)\n\tif ux&1 != 0 {\n\t\tx = ^x\n\t}\n\treturn x\n}\n\nfunc (r *Decoder) rawReloc(k RelocKind, idx int) Index {\n\te := r.Relocs[idx]\n\tassert(e.Kind == k)\n\treturn e.Idx\n}\n\n// Sync decodes a sync marker from the element bitstream and asserts\n// that it matches the expected marker.\n//\n// If r.common.sync is false, then Sync is a no-op.\nfunc (r *Decoder) Sync(mWant SyncMarker) {\n\tif !r.common.sync {\n\t\treturn\n\t}\n\n\tpos, _ := r.Data.Seek(0, io.SeekCurrent)\n\tmHave := SyncMarker(r.rawUvarint())\n\twriterPCs := make([]int, r.rawUvarint())\n\tfor i := range writerPCs {\n\t\twriterPCs[i] = int(r.rawUvarint())\n\t}\n\n\tif mHave == mWant {\n\t\treturn\n\t}\n\n\t// There's some tension here between printing:\n\t//\n\t// (1) full file paths that tools can recognize (e.g., so emacs\n\t//     hyperlinks the \"file:line\" text for easy navigation), or\n\t//\n\t// (2) short file paths that are easier for humans to read (e.g., by\n\t//     omitting redundant or irrelevant details, so it's easier to\n\t//     focus on the useful bits that remain).\n\t//\n\t// The current formatting favors the former, as it seems more\n\t// helpful in practice. But perhaps the formatting could be improved\n\t// to better address both concerns. For example, use relative file\n\t// paths if they would be shorter, or rewrite file paths to contain\n\t// \"$GOROOT\" (like objabi.AbsFile does) if tools can be taught how\n\t// to reliably expand that again.\n\n\tfmt.Printf(\"export data desync: package %q, section %v, index %v, offset %v\\n\", r.common.pkgPath, r.k, r.Idx, pos)\n\n\tfmt.Printf(\"\\nfound %v, written at:\\n\", mHave)\n\tif len(writerPCs) == 0 {\n\t\tfmt.Printf(\"\\t[stack trace unavailable; recompile package %q with -d=syncframes]\\n\", r.common.pkgPath)\n\t}\n\tfor _, pc := range writerPCs {\n\t\tfmt.Printf(\"\\t%s\\n\", r.common.StringIdx(r.rawReloc(RelocString, pc)))\n\t}\n\n\tfmt.Printf(\"\\nexpected %v, reading at:\\n\", mWant)\n\tvar readerPCs [32]uintptr // TODO(mdempsky): Dynamically size?\n\tn := runtime.Callers(2, readerPCs[:])\n\tfor _, pc := range fmtFrames(readerPCs[:n]...) {\n\t\tfmt.Printf(\"\\t%s\\n\", pc)\n\t}\n\n\t// We already printed a stack trace for the reader, so now we can\n\t// simply exit. Printing a second one with panic or base.Fatalf\n\t// would just be noise.\n\tos.Exit(1)\n}\n\n// Bool decodes and returns a bool value from the element bitstream.\nfunc (r *Decoder) Bool() bool {\n\tr.Sync(SyncBool)\n\tx, err := r.Data.ReadByte()\n\tr.checkErr(err)\n\tassert(x < 2)\n\treturn x != 0\n}\n\n// Int64 decodes and returns an int64 value from the element bitstream.\nfunc (r *Decoder) Int64() int64 {\n\tr.Sync(SyncInt64)\n\treturn r.rawVarint()\n}\n\n// Uint64 decodes and returns a uint64 value from the element bitstream.\nfunc (r *Decoder) Uint64() uint64 {\n\tr.Sync(SyncUint64)\n\treturn r.rawUvarint()\n}\n\n// Len decodes and returns a non-negative int value from the element bitstream.\nfunc (r *Decoder) Len() int { x := r.Uint64(); v := int(x); assert(uint64(v) == x); return v }\n\n// Int decodes and returns an int value from the element bitstream.\nfunc (r *Decoder) Int() int { x := r.Int64(); v := int(x); assert(int64(v) == x); return v }\n\n// Uint decodes and returns a uint value from the element bitstream.\nfunc (r *Decoder) Uint() uint { x := r.Uint64(); v := uint(x); assert(uint64(v) == x); return v }\n\n// Code decodes a Code value from the element bitstream and returns\n// its ordinal value. It's the caller's responsibility to convert the\n// result to an appropriate Code type.\n//\n// TODO(mdempsky): Ideally this method would have signature \"Code[T\n// Code] T\" instead, but we don't allow generic methods and the\n// compiler can't depend on generics yet anyway.\nfunc (r *Decoder) Code(mark SyncMarker) int {\n\tr.Sync(mark)\n\treturn r.Len()\n}\n\n// Reloc decodes a relocation of expected section k from the element\n// bitstream and returns an index to the referenced element.\nfunc (r *Decoder) Reloc(k RelocKind) Index {\n\tr.Sync(SyncUseReloc)\n\treturn r.rawReloc(k, r.Len())\n}\n\n// String decodes and returns a string value from the element\n// bitstream.\nfunc (r *Decoder) String() string {\n\tr.Sync(SyncString)\n\treturn r.common.StringIdx(r.Reloc(RelocString))\n}\n\n// Strings decodes and returns a variable-length slice of strings from\n// the element bitstream.\nfunc (r *Decoder) Strings() []string {\n\tres := make([]string, r.Len())\n\tfor i := range res {\n\t\tres[i] = r.String()\n\t}\n\treturn res\n}\n\n// Value decodes and returns a constant.Value from the element\n// bitstream.\nfunc (r *Decoder) Value() constant.Value {\n\tr.Sync(SyncValue)\n\tisComplex := r.Bool()\n\tval := r.scalar()\n\tif isComplex {\n\t\tval = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))\n\t}\n\treturn val\n}\n\nfunc (r *Decoder) scalar() constant.Value {\n\tswitch tag := CodeVal(r.Code(SyncVal)); tag {\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unexpected scalar tag: %v\", tag))\n\n\tcase ValBool:\n\t\treturn constant.MakeBool(r.Bool())\n\tcase ValString:\n\t\treturn constant.MakeString(r.String())\n\tcase ValInt64:\n\t\treturn constant.MakeInt64(r.Int64())\n\tcase ValBigInt:\n\t\treturn constant.Make(r.bigInt())\n\tcase ValBigRat:\n\t\tnum := r.bigInt()\n\t\tdenom := r.bigInt()\n\t\treturn constant.Make(new(big.Rat).SetFrac(num, denom))\n\tcase ValBigFloat:\n\t\treturn constant.Make(r.bigFloat())\n\t}\n}\n\nfunc (r *Decoder) bigInt() *big.Int {\n\tv := new(big.Int).SetBytes([]byte(r.String()))\n\tif r.Bool() {\n\t\tv.Neg(v)\n\t}\n\treturn v\n}\n\nfunc (r *Decoder) bigFloat() *big.Float {\n\tv := new(big.Float).SetPrec(512)\n\tassert(v.UnmarshalText([]byte(r.String())) == nil)\n\treturn v\n}\n\n// @@@ Helpers\n\n// TODO(mdempsky): These should probably be removed. I think they're a\n// smell that the export data format is not yet quite right.\n\n// PeekPkgPath returns the package path for the specified package\n// index.\nfunc (pr *PkgDecoder) PeekPkgPath(idx Index) string {\n\tvar path string\n\t{\n\t\tr := pr.TempDecoder(RelocPkg, idx, SyncPkgDef)\n\t\tpath = r.String()\n\t\tpr.RetireDecoder(&r)\n\t}\n\tif path == \"\" {\n\t\tpath = pr.pkgPath\n\t}\n\treturn path\n}\n\n// PeekObj returns the package path, object name, and CodeObj for the\n// specified object index.\nfunc (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {\n\tvar ridx Index\n\tvar name string\n\tvar rcode int\n\t{\n\t\tr := pr.TempDecoder(RelocName, idx, SyncObject1)\n\t\tr.Sync(SyncSym)\n\t\tr.Sync(SyncPkg)\n\t\tridx = r.Reloc(RelocPkg)\n\t\tname = r.String()\n\t\trcode = r.Code(SyncCodeObj)\n\t\tpr.RetireDecoder(&r)\n\t}\n\n\tpath := pr.PeekPkgPath(ridx)\n\tassert(name != \"\")\n\n\ttag := CodeObj(rcode)\n\n\treturn path, name, tag\n}\n\n// Version reports the version of the bitstream.\nfunc (w *Decoder) Version() Version { return w.common.version }\n"
  },
  {
    "path": "internal/pkgbits/doc.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package pkgbits implements low-level coding abstractions for\n// Unified IR's export data format.\n//\n// At a low-level, a package is a collection of bitstream elements.\n// Each element has a \"kind\" and a dense, non-negative index.\n// Elements can be randomly accessed given their kind and index.\n//\n// Individual elements are sequences of variable-length values (e.g.,\n// integers, booleans, strings, go/constant values, cross-references\n// to other elements). Package pkgbits provides APIs for encoding and\n// decoding these low-level values, but the details of mapping\n// higher-level Go constructs into elements is left to higher-level\n// abstractions.\n//\n// Elements may cross-reference each other with \"relocations.\" For\n// example, an element representing a pointer type has a relocation\n// referring to the element type.\n//\n// Go constructs may be composed as a constellation of multiple\n// elements. For example, a declared function may have one element to\n// describe the object (e.g., its name, type, position), and a\n// separate element to describe its function body. This allows readers\n// some flexibility in efficiently seeking or re-reading data (e.g.,\n// inlining requires re-reading the function body for each inlined\n// call, without needing to re-read the object-level details).\n//\n// This is a copy of internal/pkgbits in the Go implementation.\npackage pkgbits\n"
  },
  {
    "path": "internal/pkgbits/encoder.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"encoding/binary\"\n\t\"go/constant\"\n\t\"io\"\n\t\"math/big\"\n\t\"runtime\"\n\t\"strings\"\n)\n\n// A PkgEncoder provides methods for encoding a package's Unified IR\n// export data.\ntype PkgEncoder struct {\n\t// version of the bitstream.\n\tversion Version\n\n\t// elems holds the bitstream for previously encoded elements.\n\telems [numRelocs][]string\n\n\t// stringsIdx maps previously encoded strings to their index within\n\t// the RelocString section, to allow deduplication. That is,\n\t// elems[RelocString][stringsIdx[s]] == s (if present).\n\tstringsIdx map[string]Index\n\n\t// syncFrames is the number of frames to write at each sync\n\t// marker. A negative value means sync markers are omitted.\n\tsyncFrames int\n}\n\n// SyncMarkers reports whether pw uses sync markers.\nfunc (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }\n\n// NewPkgEncoder returns an initialized PkgEncoder.\n//\n// syncFrames is the number of caller frames that should be serialized\n// at Sync points. Serializing additional frames results in larger\n// export data files, but can help diagnosing desync errors in\n// higher-level Unified IR reader/writer code. If syncFrames is\n// negative, then sync markers are omitted entirely.\nfunc NewPkgEncoder(version Version, syncFrames int) PkgEncoder {\n\treturn PkgEncoder{\n\t\tversion:    version,\n\t\tstringsIdx: make(map[string]Index),\n\t\tsyncFrames: syncFrames,\n\t}\n}\n\n// DumpTo writes the package's encoded data to out0 and returns the\n// package fingerprint.\nfunc (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {\n\th := md5.New()\n\tout := io.MultiWriter(out0, h)\n\n\twriteUint32 := func(x uint32) {\n\t\tassert(binary.Write(out, binary.LittleEndian, x) == nil)\n\t}\n\n\twriteUint32(uint32(pw.version))\n\n\tif pw.version.Has(Flags) {\n\t\tvar flags uint32\n\t\tif pw.SyncMarkers() {\n\t\t\tflags |= flagSyncMarkers\n\t\t}\n\t\twriteUint32(flags)\n\t}\n\n\t// Write elemEndsEnds.\n\tvar sum uint32\n\tfor _, elems := range &pw.elems {\n\t\tsum += uint32(len(elems))\n\t\twriteUint32(sum)\n\t}\n\n\t// Write elemEnds.\n\tsum = 0\n\tfor _, elems := range &pw.elems {\n\t\tfor _, elem := range elems {\n\t\t\tsum += uint32(len(elem))\n\t\t\twriteUint32(sum)\n\t\t}\n\t}\n\n\t// Write elemData.\n\tfor _, elems := range &pw.elems {\n\t\tfor _, elem := range elems {\n\t\t\t_, err := io.WriteString(out, elem)\n\t\t\tassert(err == nil)\n\t\t}\n\t}\n\n\t// Write fingerprint.\n\tcopy(fingerprint[:], h.Sum(nil))\n\t_, err := out0.Write(fingerprint[:])\n\tassert(err == nil)\n\n\treturn\n}\n\n// StringIdx adds a string value to the strings section, if not\n// already present, and returns its index.\nfunc (pw *PkgEncoder) StringIdx(s string) Index {\n\tif idx, ok := pw.stringsIdx[s]; ok {\n\t\tassert(pw.elems[RelocString][idx] == s)\n\t\treturn idx\n\t}\n\n\tidx := Index(len(pw.elems[RelocString]))\n\tpw.elems[RelocString] = append(pw.elems[RelocString], s)\n\tpw.stringsIdx[s] = idx\n\treturn idx\n}\n\n// NewEncoder returns an Encoder for a new element within the given\n// section, and encodes the given SyncMarker as the start of the\n// element bitstream.\nfunc (pw *PkgEncoder) NewEncoder(k RelocKind, marker SyncMarker) Encoder {\n\te := pw.NewEncoderRaw(k)\n\te.Sync(marker)\n\treturn e\n}\n\n// NewEncoderRaw returns an Encoder for a new element within the given\n// section.\n//\n// Most callers should use NewEncoder instead.\nfunc (pw *PkgEncoder) NewEncoderRaw(k RelocKind) Encoder {\n\tidx := Index(len(pw.elems[k]))\n\tpw.elems[k] = append(pw.elems[k], \"\") // placeholder\n\n\treturn Encoder{\n\t\tp:   pw,\n\t\tk:   k,\n\t\tIdx: idx,\n\t}\n}\n\n// An Encoder provides methods for encoding an individual element's\n// bitstream data.\ntype Encoder struct {\n\tp *PkgEncoder\n\n\tRelocs   []RelocEnt\n\tRelocMap map[RelocEnt]uint32\n\tData     bytes.Buffer // accumulated element bitstream data\n\n\tencodingRelocHeader bool\n\n\tk   RelocKind\n\tIdx Index // index within relocation section\n}\n\n// Flush finalizes the element's bitstream and returns its Index.\nfunc (w *Encoder) Flush() Index {\n\tvar sb strings.Builder\n\n\t// Backup the data so we write the relocations at the front.\n\tvar tmp bytes.Buffer\n\tio.Copy(&tmp, &w.Data)\n\n\t// TODO(mdempsky): Consider writing these out separately so they're\n\t// easier to strip, along with function bodies, so that we can prune\n\t// down to just the data that's relevant to go/types.\n\tif w.encodingRelocHeader {\n\t\tpanic(\"encodingRelocHeader already true; recursive flush?\")\n\t}\n\tw.encodingRelocHeader = true\n\tw.Sync(SyncRelocs)\n\tw.Len(len(w.Relocs))\n\tfor _, rEnt := range w.Relocs {\n\t\tw.Sync(SyncReloc)\n\t\tw.Len(int(rEnt.Kind))\n\t\tw.Len(int(rEnt.Idx))\n\t}\n\n\tio.Copy(&sb, &w.Data)\n\tio.Copy(&sb, &tmp)\n\tw.p.elems[w.k][w.Idx] = sb.String()\n\n\treturn w.Idx\n}\n\nfunc (w *Encoder) checkErr(err error) {\n\tif err != nil {\n\t\tpanicf(\"unexpected encoding error: %v\", err)\n\t}\n}\n\nfunc (w *Encoder) rawUvarint(x uint64) {\n\tvar buf [binary.MaxVarintLen64]byte\n\tn := binary.PutUvarint(buf[:], x)\n\t_, err := w.Data.Write(buf[:n])\n\tw.checkErr(err)\n}\n\nfunc (w *Encoder) rawVarint(x int64) {\n\t// Zig-zag encode.\n\tux := uint64(x) << 1\n\tif x < 0 {\n\t\tux = ^ux\n\t}\n\n\tw.rawUvarint(ux)\n}\n\nfunc (w *Encoder) rawReloc(r RelocKind, idx Index) int {\n\te := RelocEnt{r, idx}\n\tif w.RelocMap != nil {\n\t\tif i, ok := w.RelocMap[e]; ok {\n\t\t\treturn int(i)\n\t\t}\n\t} else {\n\t\tw.RelocMap = make(map[RelocEnt]uint32)\n\t}\n\n\ti := len(w.Relocs)\n\tw.RelocMap[e] = uint32(i)\n\tw.Relocs = append(w.Relocs, e)\n\treturn i\n}\n\nfunc (w *Encoder) Sync(m SyncMarker) {\n\tif !w.p.SyncMarkers() {\n\t\treturn\n\t}\n\n\t// Writing out stack frame string references requires working\n\t// relocations, but writing out the relocations themselves involves\n\t// sync markers. To prevent infinite recursion, we simply trim the\n\t// stack frame for sync markers within the relocation header.\n\tvar frames []string\n\tif !w.encodingRelocHeader && w.p.syncFrames > 0 {\n\t\tpcs := make([]uintptr, w.p.syncFrames)\n\t\tn := runtime.Callers(2, pcs)\n\t\tframes = fmtFrames(pcs[:n]...)\n\t}\n\n\t// TODO(mdempsky): Save space by writing out stack frames as a\n\t// linked list so we can share common stack frames.\n\tw.rawUvarint(uint64(m))\n\tw.rawUvarint(uint64(len(frames)))\n\tfor _, frame := range frames {\n\t\tw.rawUvarint(uint64(w.rawReloc(RelocString, w.p.StringIdx(frame))))\n\t}\n}\n\n// Bool encodes and writes a bool value into the element bitstream,\n// and then returns the bool value.\n//\n// For simple, 2-alternative encodings, the idiomatic way to call Bool\n// is something like:\n//\n//\tif w.Bool(x != 0) {\n//\t\t// alternative #1\n//\t} else {\n//\t\t// alternative #2\n//\t}\n//\n// For multi-alternative encodings, use Code instead.\nfunc (w *Encoder) Bool(b bool) bool {\n\tw.Sync(SyncBool)\n\tvar x byte\n\tif b {\n\t\tx = 1\n\t}\n\terr := w.Data.WriteByte(x)\n\tw.checkErr(err)\n\treturn b\n}\n\n// Int64 encodes and writes an int64 value into the element bitstream.\nfunc (w *Encoder) Int64(x int64) {\n\tw.Sync(SyncInt64)\n\tw.rawVarint(x)\n}\n\n// Uint64 encodes and writes a uint64 value into the element bitstream.\nfunc (w *Encoder) Uint64(x uint64) {\n\tw.Sync(SyncUint64)\n\tw.rawUvarint(x)\n}\n\n// Len encodes and writes a non-negative int value into the element bitstream.\nfunc (w *Encoder) Len(x int) { assert(x >= 0); w.Uint64(uint64(x)) }\n\n// Int encodes and writes an int value into the element bitstream.\nfunc (w *Encoder) Int(x int) { w.Int64(int64(x)) }\n\n// Uint encodes and writes a uint value into the element bitstream.\nfunc (w *Encoder) Uint(x uint) { w.Uint64(uint64(x)) }\n\n// Reloc encodes and writes a relocation for the given (section,\n// index) pair into the element bitstream.\n//\n// Note: Only the index is formally written into the element\n// bitstream, so bitstream decoders must know from context which\n// section an encoded relocation refers to.\nfunc (w *Encoder) Reloc(r RelocKind, idx Index) {\n\tw.Sync(SyncUseReloc)\n\tw.Len(w.rawReloc(r, idx))\n}\n\n// Code encodes and writes a Code value into the element bitstream.\nfunc (w *Encoder) Code(c Code) {\n\tw.Sync(c.Marker())\n\tw.Len(c.Value())\n}\n\n// String encodes and writes a string value into the element\n// bitstream.\n//\n// Internally, strings are deduplicated by adding them to the strings\n// section (if not already present), and then writing a relocation\n// into the element bitstream.\nfunc (w *Encoder) String(s string) {\n\tw.StringRef(w.p.StringIdx(s))\n}\n\n// StringRef writes a reference to the given index, which must be a\n// previously encoded string value.\nfunc (w *Encoder) StringRef(idx Index) {\n\tw.Sync(SyncString)\n\tw.Reloc(RelocString, idx)\n}\n\n// Strings encodes and writes a variable-length slice of strings into\n// the element bitstream.\nfunc (w *Encoder) Strings(ss []string) {\n\tw.Len(len(ss))\n\tfor _, s := range ss {\n\t\tw.String(s)\n\t}\n}\n\n// Value encodes and writes a constant.Value into the element\n// bitstream.\nfunc (w *Encoder) Value(val constant.Value) {\n\tw.Sync(SyncValue)\n\tif w.Bool(val.Kind() == constant.Complex) {\n\t\tw.scalar(constant.Real(val))\n\t\tw.scalar(constant.Imag(val))\n\t} else {\n\t\tw.scalar(val)\n\t}\n}\n\nfunc (w *Encoder) scalar(val constant.Value) {\n\tswitch v := constant.Val(val).(type) {\n\tdefault:\n\t\tpanicf(\"unhandled %v (%v)\", val, val.Kind())\n\tcase bool:\n\t\tw.Code(ValBool)\n\t\tw.Bool(v)\n\tcase string:\n\t\tw.Code(ValString)\n\t\tw.String(v)\n\tcase int64:\n\t\tw.Code(ValInt64)\n\t\tw.Int64(v)\n\tcase *big.Int:\n\t\tw.Code(ValBigInt)\n\t\tw.bigInt(v)\n\tcase *big.Rat:\n\t\tw.Code(ValBigRat)\n\t\tw.bigInt(v.Num())\n\t\tw.bigInt(v.Denom())\n\tcase *big.Float:\n\t\tw.Code(ValBigFloat)\n\t\tw.bigFloat(v)\n\t}\n}\n\nfunc (w *Encoder) bigInt(v *big.Int) {\n\tb := v.Bytes()\n\tw.String(string(b)) // TODO: More efficient encoding.\n\tw.Bool(v.Sign() < 0)\n}\n\nfunc (w *Encoder) bigFloat(v *big.Float) {\n\tb := v.Append(nil, 'p', -1)\n\tw.String(string(b)) // TODO: More efficient encoding.\n}\n\n// Version reports the version of the bitstream.\nfunc (w *Encoder) Version() Version { return w.p.version }\n"
  },
  {
    "path": "internal/pkgbits/flags.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\nconst (\n\tflagSyncMarkers = 1 << iota // file format contains sync markers\n)\n"
  },
  {
    "path": "internal/pkgbits/pkgbits_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits_test\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/pkgbits\"\n)\n\nfunc TestRoundTrip(t *testing.T) {\n\tfor _, version := range []pkgbits.Version{\n\t\tpkgbits.V0,\n\t\tpkgbits.V1,\n\t\tpkgbits.V2,\n\t} {\n\t\tpw := pkgbits.NewPkgEncoder(version, -1)\n\t\tw := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)\n\t\tw.Flush()\n\n\t\tvar b strings.Builder\n\t\t_ = pw.DumpTo(&b)\n\t\tinput := b.String()\n\n\t\tpr := pkgbits.NewPkgDecoder(\"package_id\", input)\n\t\tr := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)\n\n\t\tif r.Version() != w.Version() {\n\t\t\tt.Errorf(\"Expected reader version %d to be the writer version %d\", r.Version(), w.Version())\n\t\t}\n\t}\n}\n\n// Type checker to enforce that know V* have the constant values they must have.\nvar _ [0]bool = [pkgbits.V0]bool{}\nvar _ [1]bool = [pkgbits.V1]bool{}\n\nfunc TestVersions(t *testing.T) {\n\ttype vfpair struct {\n\t\tv pkgbits.Version\n\t\tf pkgbits.Field\n\t}\n\n\t// has field tests\n\tfor _, c := range []vfpair{\n\t\t{pkgbits.V1, pkgbits.Flags},\n\t\t{pkgbits.V2, pkgbits.Flags},\n\t\t{pkgbits.V0, pkgbits.HasInit},\n\t\t{pkgbits.V1, pkgbits.HasInit},\n\t\t{pkgbits.V0, pkgbits.DerivedFuncInstance},\n\t\t{pkgbits.V1, pkgbits.DerivedFuncInstance},\n\t\t{pkgbits.V0, pkgbits.DerivedInfoNeeded},\n\t\t{pkgbits.V1, pkgbits.DerivedInfoNeeded},\n\t\t{pkgbits.V2, pkgbits.AliasTypeParamNames},\n\t} {\n\t\tif !c.v.Has(c.f) {\n\t\t\tt.Errorf(\"Expected version %v to have field %v\", c.v, c.f)\n\t\t}\n\t}\n\n\t// does not have field tests\n\tfor _, c := range []vfpair{\n\t\t{pkgbits.V0, pkgbits.Flags},\n\t\t{pkgbits.V2, pkgbits.HasInit},\n\t\t{pkgbits.V2, pkgbits.DerivedFuncInstance},\n\t\t{pkgbits.V2, pkgbits.DerivedInfoNeeded},\n\t\t{pkgbits.V0, pkgbits.AliasTypeParamNames},\n\t\t{pkgbits.V1, pkgbits.AliasTypeParamNames},\n\t} {\n\t\tif c.v.Has(c.f) {\n\t\t\tt.Errorf(\"Expected version %v to not have field %v\", c.v, c.f)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/pkgbits/reloc.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\n// A RelocKind indicates a particular section within a unified IR export.\ntype RelocKind int32\n\n// An Index represents a bitstream element index within a particular\n// section.\ntype Index int32\n\n// A relocEnt (relocation entry) is an entry in an element's local\n// reference table.\n//\n// TODO(mdempsky): Rename this too.\ntype RelocEnt struct {\n\tKind RelocKind\n\tIdx  Index\n}\n\n// Reserved indices within the meta relocation section.\nconst (\n\tPublicRootIdx  Index = 0\n\tPrivateRootIdx Index = 1\n)\n\nconst (\n\tRelocString RelocKind = iota\n\tRelocMeta\n\tRelocPosBase\n\tRelocPkg\n\tRelocName\n\tRelocType\n\tRelocObj\n\tRelocObjExt\n\tRelocObjDict\n\tRelocBody\n\n\tnumRelocs = iota\n)\n"
  },
  {
    "path": "internal/pkgbits/support.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\nimport \"fmt\"\n\nfunc assert(b bool) {\n\tif !b {\n\t\tpanic(\"assertion failed\")\n\t}\n}\n\nfunc panicf(format string, args ...any) {\n\tpanic(fmt.Errorf(format, args...))\n}\n"
  },
  {
    "path": "internal/pkgbits/sync.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"strings\"\n)\n\n// fmtFrames formats a backtrace for reporting reader/writer desyncs.\nfunc fmtFrames(pcs ...uintptr) []string {\n\tres := make([]string, 0, len(pcs))\n\twalkFrames(pcs, func(file string, line int, name string, offset uintptr) {\n\t\t// Trim package from function name. It's just redundant noise.\n\t\tname = strings.TrimPrefix(name, \"cmd/compile/internal/noder.\")\n\n\t\tres = append(res, fmt.Sprintf(\"%s:%v: %s +0x%v\", file, line, name, offset))\n\t})\n\treturn res\n}\n\ntype frameVisitor func(file string, line int, name string, offset uintptr)\n\n// walkFrames calls visit for each call frame represented by pcs.\n//\n// pcs should be a slice of PCs, as returned by runtime.Callers.\nfunc walkFrames(pcs []uintptr, visit frameVisitor) {\n\tif len(pcs) == 0 {\n\t\treturn\n\t}\n\n\tframes := runtime.CallersFrames(pcs)\n\tfor {\n\t\tframe, more := frames.Next()\n\t\tvisit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)\n\t\tif !more {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// SyncMarker is an enum type that represents markers that may be\n// written to export data to ensure the reader and writer stay\n// synchronized.\ntype SyncMarker int\n\n//go:generate stringer -type=SyncMarker -trimprefix=Sync\n\nconst (\n\t_ SyncMarker = iota\n\n\t// Public markers (known to go/types importers).\n\n\t// Low-level coding markers.\n\tSyncEOF\n\tSyncBool\n\tSyncInt64\n\tSyncUint64\n\tSyncString\n\tSyncValue\n\tSyncVal\n\tSyncRelocs\n\tSyncReloc\n\tSyncUseReloc\n\n\t// Higher-level object and type markers.\n\tSyncPublic\n\tSyncPos\n\tSyncPosBase\n\tSyncObject\n\tSyncObject1\n\tSyncPkg\n\tSyncPkgDef\n\tSyncMethod\n\tSyncType\n\tSyncTypeIdx\n\tSyncTypeParamNames\n\tSyncSignature\n\tSyncParams\n\tSyncParam\n\tSyncCodeObj\n\tSyncSym\n\tSyncLocalIdent\n\tSyncSelector\n\n\t// Private markers (only known to cmd/compile).\n\tSyncPrivate\n\n\tSyncFuncExt\n\tSyncVarExt\n\tSyncTypeExt\n\tSyncPragma\n\n\tSyncExprList\n\tSyncExprs\n\tSyncExpr\n\tSyncExprType\n\tSyncAssign\n\tSyncOp\n\tSyncFuncLit\n\tSyncCompLit\n\n\tSyncDecl\n\tSyncFuncBody\n\tSyncOpenScope\n\tSyncCloseScope\n\tSyncCloseAnotherScope\n\tSyncDeclNames\n\tSyncDeclName\n\n\tSyncStmts\n\tSyncBlockStmt\n\tSyncIfStmt\n\tSyncForStmt\n\tSyncSwitchStmt\n\tSyncRangeStmt\n\tSyncCaseClause\n\tSyncCommClause\n\tSyncSelectStmt\n\tSyncDecls\n\tSyncLabeledStmt\n\tSyncUseObjLocal\n\tSyncAddLocal\n\tSyncLinkname\n\tSyncStmt1\n\tSyncStmtsEnd\n\tSyncLabel\n\tSyncOptLabel\n\n\tSyncMultiExpr\n\tSyncRType\n\tSyncConvRTTI\n)\n"
  },
  {
    "path": "internal/pkgbits/syncmarker_string.go",
    "content": "// Code generated by \"stringer -type=SyncMarker -trimprefix=Sync\"; DO NOT EDIT.\n\npackage pkgbits\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[SyncEOF-1]\n\t_ = x[SyncBool-2]\n\t_ = x[SyncInt64-3]\n\t_ = x[SyncUint64-4]\n\t_ = x[SyncString-5]\n\t_ = x[SyncValue-6]\n\t_ = x[SyncVal-7]\n\t_ = x[SyncRelocs-8]\n\t_ = x[SyncReloc-9]\n\t_ = x[SyncUseReloc-10]\n\t_ = x[SyncPublic-11]\n\t_ = x[SyncPos-12]\n\t_ = x[SyncPosBase-13]\n\t_ = x[SyncObject-14]\n\t_ = x[SyncObject1-15]\n\t_ = x[SyncPkg-16]\n\t_ = x[SyncPkgDef-17]\n\t_ = x[SyncMethod-18]\n\t_ = x[SyncType-19]\n\t_ = x[SyncTypeIdx-20]\n\t_ = x[SyncTypeParamNames-21]\n\t_ = x[SyncSignature-22]\n\t_ = x[SyncParams-23]\n\t_ = x[SyncParam-24]\n\t_ = x[SyncCodeObj-25]\n\t_ = x[SyncSym-26]\n\t_ = x[SyncLocalIdent-27]\n\t_ = x[SyncSelector-28]\n\t_ = x[SyncPrivate-29]\n\t_ = x[SyncFuncExt-30]\n\t_ = x[SyncVarExt-31]\n\t_ = x[SyncTypeExt-32]\n\t_ = x[SyncPragma-33]\n\t_ = x[SyncExprList-34]\n\t_ = x[SyncExprs-35]\n\t_ = x[SyncExpr-36]\n\t_ = x[SyncExprType-37]\n\t_ = x[SyncAssign-38]\n\t_ = x[SyncOp-39]\n\t_ = x[SyncFuncLit-40]\n\t_ = x[SyncCompLit-41]\n\t_ = x[SyncDecl-42]\n\t_ = x[SyncFuncBody-43]\n\t_ = x[SyncOpenScope-44]\n\t_ = x[SyncCloseScope-45]\n\t_ = x[SyncCloseAnotherScope-46]\n\t_ = x[SyncDeclNames-47]\n\t_ = x[SyncDeclName-48]\n\t_ = x[SyncStmts-49]\n\t_ = x[SyncBlockStmt-50]\n\t_ = x[SyncIfStmt-51]\n\t_ = x[SyncForStmt-52]\n\t_ = x[SyncSwitchStmt-53]\n\t_ = x[SyncRangeStmt-54]\n\t_ = x[SyncCaseClause-55]\n\t_ = x[SyncCommClause-56]\n\t_ = x[SyncSelectStmt-57]\n\t_ = x[SyncDecls-58]\n\t_ = x[SyncLabeledStmt-59]\n\t_ = x[SyncUseObjLocal-60]\n\t_ = x[SyncAddLocal-61]\n\t_ = x[SyncLinkname-62]\n\t_ = x[SyncStmt1-63]\n\t_ = x[SyncStmtsEnd-64]\n\t_ = x[SyncLabel-65]\n\t_ = x[SyncOptLabel-66]\n\t_ = x[SyncMultiExpr-67]\n\t_ = x[SyncRType-68]\n\t_ = x[SyncConvRTTI-69]\n}\n\nconst _SyncMarker_name = \"EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabelMultiExprRTypeConvRTTI\"\n\nvar _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458, 467, 472, 480}\n\nfunc (i SyncMarker) String() string {\n\ti -= 1\n\tif i < 0 || i >= SyncMarker(len(_SyncMarker_index)-1) {\n\t\treturn \"SyncMarker(\" + strconv.FormatInt(int64(i+1), 10) + \")\"\n\t}\n\treturn _SyncMarker_name[_SyncMarker_index[i]:_SyncMarker_index[i+1]]\n}\n"
  },
  {
    "path": "internal/pkgbits/version.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pkgbits\n\n// Version indicates a version of a unified IR bitstream.\n// Each Version indicates the addition, removal, or change of\n// new data in the bitstream.\n//\n// These are serialized to disk and the interpretation remains fixed.\ntype Version uint32\n\nconst (\n\t// V0: initial prototype.\n\t//\n\t// All data that is not assigned a Field is in version V0\n\t// and has not been deprecated.\n\tV0 Version = iota\n\n\t// V1: adds the Flags uint32 word\n\tV1\n\n\t// V2: removes unused legacy fields and supports type parameters for aliases.\n\t// - remove the legacy \"has init\" bool from the public root\n\t// - remove obj's \"derived func instance\" bool\n\t// - add a TypeParamNames field to ObjAlias\n\t// - remove derived info \"needed\" bool\n\tV2\n\n\t// V3: introduces a more compact format for composite literal element lists\n\t// - negative lengths indicate that (some) elements may have keys\n\t// - positive lengths indicate that no element has a key\n\t// - a negative struct field index indicates an embedded field\n\tV3\n\n\tnumVersions = iota\n)\n\n// Field denotes a unit of data in the serialized unified IR bitstream.\n// It is conceptually a like field in a structure.\n//\n// We only really need Fields when the data may or may not be present\n// in a stream based on the Version of the bitstream.\n//\n// Unlike much of pkgbits, Fields are not serialized and\n// can change values as needed.\ntype Field int\n\nconst (\n\t// Flags in a uint32 in the header of a bitstream\n\t// that is used to indicate whether optional features are enabled.\n\tFlags Field = iota\n\n\t// Deprecated: HasInit was a bool indicating whether a package\n\t// has any init functions.\n\tHasInit\n\n\t// Deprecated: DerivedFuncInstance was a bool indicating\n\t// whether an object was a function instance.\n\tDerivedFuncInstance\n\n\t// ObjAlias has a list of TypeParamNames.\n\tAliasTypeParamNames\n\n\t// Deprecated: DerivedInfoNeeded was a bool indicating\n\t// whether a type was a derived type.\n\tDerivedInfoNeeded\n\n\t// Composite literals use a more compact format for element lists.\n\tCompactCompLiterals\n\n\tnumFields = iota\n)\n\n// introduced is the version a field was added.\nvar introduced = [numFields]Version{\n\tFlags:               V1,\n\tAliasTypeParamNames: V2,\n\tCompactCompLiterals: V3,\n}\n\n// removed is the version a field was removed in or 0 for fields\n// that have not yet been deprecated.\n// (So removed[f]-1 is the last version it is included in.)\nvar removed = [numFields]Version{\n\tHasInit:             V2,\n\tDerivedFuncInstance: V2,\n\tDerivedInfoNeeded:   V2,\n}\n\n// Has reports whether field f is present in a bitstream at version v.\nfunc (v Version) Has(f Field) bool {\n\treturn introduced[f] <= v && (v < removed[f] || removed[f] == V0)\n}\n"
  },
  {
    "path": "internal/pprof/main.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The pprof command prints the total time in a pprof profile provided\n// through the standard input.\npackage main\n\nimport (\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/tools/internal/pprof\"\n)\n\nfunc main() {\n\trd, err := gzip.NewReader(os.Stdin)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tpayload, err := io.ReadAll(rd)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\ttotal, err := pprof.TotalTime(payload)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(total)\n}\n"
  },
  {
    "path": "internal/pprof/pprof.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package pprof provides minimalistic routines for extracting\n// information from profiles.\npackage pprof\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\n// TotalTime parses the profile data and returns the accumulated time.\n// The input should not be gzipped.\nfunc TotalTime(data []byte) (total time.Duration, err error) {\n\tdefer func() {\n\t\tif x := recover(); x != nil {\n\t\t\terr = fmt.Errorf(\"error parsing pprof profile: %v\", x)\n\t\t}\n\t}()\n\tdecode(&total, data, msgProfile)\n\treturn\n}\n\n// All errors are handled by panicking.\n// Constants are copied below to avoid dependency on protobufs or pprof.\n\n// protobuf wire types, from https://developers.google.com/protocol-buffers/docs/encoding\nconst (\n\twireVarint = 0\n\twireBytes  = 2\n)\n\n// pprof field numbers, from https://github.com/google/pprof/blob/master/proto/profile.proto\nconst (\n\tfldProfileSample = 2 // repeated Sample\n\tfldSampleValue   = 2 // repeated int64\n)\n\n// arbitrary numbering of message types\nconst (\n\tmsgProfile = 0\n\tmsgSample  = 1\n)\n\nfunc decode(total *time.Duration, data []byte, msg int) {\n\tfor len(data) > 0 {\n\t\t// Read tag (wire type and field number).\n\t\ttag := varint(&data)\n\n\t\t// Read wire value (int or bytes).\n\t\twire := tag & 7\n\t\tvar ival uint64\n\t\tvar sval []byte\n\t\tswitch wire {\n\t\tcase wireVarint:\n\t\t\tival = varint(&data)\n\n\t\tcase wireBytes:\n\t\t\tn := varint(&data)\n\t\t\tsval, data = data[:n], data[n:]\n\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected wire type: %d\", wire))\n\t\t}\n\n\t\t// Process field of msg.\n\t\tfld := tag >> 3\n\t\tswitch {\n\t\tcase msg == msgProfile && fld == fldProfileSample:\n\t\t\tdecode(total, sval, msgSample) // recursively decode Sample message\n\n\t\tcase msg == msgSample, fld == fldSampleValue:\n\t\t\t*total += time.Duration(ival) // accumulate time\n\t\t}\n\t}\n}\n\nfunc varint(data *[]byte) (v uint64) {\n\tfor i := 0; ; i++ {\n\t\tb := uint64((*data)[i])\n\t\tv += (b & 0x7f) << (7 * i)\n\t\tif b < 0x80 {\n\t\t\t*data = (*data)[i+1:]\n\t\t\treturn v\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/pprof/pprof_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pprof_test\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/pprof\"\n)\n\nfunc TestTotalTime(t *testing.T) {\n\t// $ go tool pprof testdata/sample.pprof <&- 2>&1 | grep Total\n\t// Duration: 11.10s, Total samples = 27.59s (248.65%)\n\tconst (\n\t\tfilename = \"testdata/sample.pprof\"\n\t\twant     = time.Duration(27590003550)\n\t)\n\n\tprofGz, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\trd, err := gzip.NewReader(bytes.NewReader(profGz))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tpayload, err := io.ReadAll(rd)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot, err := pprof.TotalTime(payload)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif got != want {\n\t\tt.Fatalf(\"TotalTime(%q): got %v (%d), want %v (%d)\", filename, got, got, want, want)\n\t}\n}\n"
  },
  {
    "path": "internal/proxydir/proxydir.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package proxydir provides functions for writing module data to a directory\n// in proxy format, so that it can be used as a module proxy by setting\n// GOPROXY=\"file://<dir>\".\npackage proxydir\n\nimport (\n\t\"archive/zip\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// WriteModuleVersion creates a directory in the proxy dir for a module.\nfunc WriteModuleVersion(rootDir, module, ver string, files map[string][]byte) (rerr error) {\n\tdir := filepath.Join(rootDir, module, \"@v\")\n\tif err := os.MkdirAll(dir, 0755); err != nil {\n\t\treturn err\n\t}\n\n\t// The go command checks for versions by looking at the \"list\" file.  Since\n\t// we are supporting multiple versions, create this file if it does not exist\n\t// or append the version number to the preexisting file.\n\tf, err := os.OpenFile(filepath.Join(dir, \"list\"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer checkClose(\"list file\", f, &rerr)\n\tif _, err := f.WriteString(ver + \"\\n\"); err != nil {\n\t\treturn err\n\t}\n\n\t// Serve the go.mod file on the <version>.mod url, if it exists. Otherwise,\n\t// serve a stub.\n\tmodContents, ok := files[\"go.mod\"]\n\tif !ok {\n\t\tmodContents = []byte(\"module \" + module)\n\t}\n\tif err := os.WriteFile(filepath.Join(dir, ver+\".mod\"), modContents, 0644); err != nil {\n\t\treturn err\n\t}\n\n\t// info file, just the bare bones.\n\tinfoContents := fmt.Appendf(nil, `{\"Version\": \"%v\", \"Time\":\"2017-12-14T13:08:43Z\"}`, ver)\n\tif err := os.WriteFile(filepath.Join(dir, ver+\".info\"), infoContents, 0644); err != nil {\n\t\treturn err\n\t}\n\n\t// zip of all the source files.\n\tf, err = os.OpenFile(filepath.Join(dir, ver+\".zip\"), os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer checkClose(\"zip file\", f, &rerr)\n\tz := zip.NewWriter(f)\n\tdefer checkClose(\"zip writer\", z, &rerr)\n\tfor name, contents := range files {\n\t\tzf, err := z.Create(module + \"@\" + ver + \"/\" + name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := zf.Write(contents); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc checkClose(name string, closer io.Closer, err *error) {\n\tif cerr := closer.Close(); cerr != nil && *err == nil {\n\t\t*err = fmt.Errorf(\"closing %s: %v\", name, cerr)\n\t}\n}\n\n// ToURL returns the file uri for a proxy directory.\nfunc ToURL(dir string) string {\n\t// file URLs on Windows must start with file:///. See golang.org/issue/6027.\n\tpath := filepath.ToSlash(dir)\n\tif !strings.HasPrefix(path, \"/\") {\n\t\tpath = \"/\" + path\n\t}\n\treturn \"file://\" + path\n}\n"
  },
  {
    "path": "internal/proxydir/proxydir_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage proxydir\n\nimport (\n\t\"archive/zip\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestWriteModuleVersion(t *testing.T) {\n\ttests := []struct {\n\t\tmodulePath, version string\n\t\tfiles               map[string][]byte\n\t}{\n\t\t{\n\t\t\tmodulePath: \"mod.test/module\",\n\t\t\tversion:    \"v1.2.3\",\n\t\t\tfiles: map[string][]byte{\n\t\t\t\t\"go.mod\":   []byte(\"module mod.com\\n\\ngo 1.12\"),\n\t\t\t\t\"const.go\": []byte(\"package module\\n\\nconst Answer = 42\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tmodulePath: \"mod.test/module\",\n\t\t\tversion:    \"v1.2.4\",\n\t\t\tfiles: map[string][]byte{\n\t\t\t\t\"go.mod\":   []byte(\"module mod.com\\n\\ngo 1.12\"),\n\t\t\t\t\"const.go\": []byte(\"package module\\n\\nconst Answer = 43\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tmodulePath: \"mod.test/nogomod\",\n\t\t\tversion:    \"v0.9.0\",\n\t\t\tfiles: map[string][]byte{\n\t\t\t\t\"const.go\": []byte(\"package module\\n\\nconst Other = \\\"Other\\\"\"),\n\t\t\t},\n\t\t},\n\t}\n\tdir, err := os.MkdirTemp(\"\", \"proxydirtest-\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(dir)\n\tfor _, test := range tests {\n\t\t// Since we later assert on the contents of /list, don't use subtests.\n\t\tif err := WriteModuleVersion(dir, test.modulePath, test.version, test.files); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\trootDir := filepath.Join(dir, filepath.FromSlash(test.modulePath), \"@v\")\n\t\tgomod, err := os.ReadFile(filepath.Join(rootDir, test.version+\".mod\"))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\twantMod, ok := test.files[\"go.mod\"]\n\t\tif !ok {\n\t\t\twantMod = []byte(\"module \" + test.modulePath)\n\t\t}\n\t\tif got, want := string(gomod), string(wantMod); got != want {\n\t\t\tt.Errorf(\"reading %s/@v/%s.mod: got %q, want %q\", test.modulePath, test.version, got, want)\n\t\t}\n\t\tzr, err := zip.OpenReader(filepath.Join(rootDir, test.version+\".zip\"))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdefer zr.Close()\n\n\t\tfor _, zf := range zr.File {\n\t\t\tr, err := zf.Open()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer r.Close()\n\t\t\tcontent, err := io.ReadAll(r)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tname := strings.TrimPrefix(zf.Name, fmt.Sprintf(\"%s@%s/\", test.modulePath, test.version))\n\t\t\tif got, want := string(content), string(test.files[name]); got != want {\n\t\t\t\tt.Errorf(\"unzipping %q: got %q, want %q\", zf.Name, got, want)\n\t\t\t}\n\t\t\tdelete(test.files, name)\n\t\t}\n\t\tfor name := range test.files {\n\t\t\tt.Errorf(\"file %q not present in the module zip\", name)\n\t\t}\n\t}\n\n\tlists := []struct {\n\t\tmodulePath, want string\n\t}{\n\t\t{\"mod.test/module\", \"v1.2.3\\nv1.2.4\\n\"},\n\t\t{\"mod.test/nogomod\", \"v0.9.0\\n\"},\n\t}\n\n\tfor _, test := range lists {\n\t\tfp := filepath.Join(dir, filepath.FromSlash(test.modulePath), \"@v\", \"list\")\n\t\tlist, err := os.ReadFile(fp)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif got := string(list); got != test.want {\n\t\t\tt.Errorf(\"%q/@v/list: got %q, want %q\", test.modulePath, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/refactor/delete.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage refactor\n\n// This file defines operations for computing deletion edits.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\n// DeleteVar returns edits to delete the declaration of a variable or\n// constant whose defining identifier is curId.\n//\n// It handles variants including:\n// - GenDecl > ValueSpec versus AssignStmt;\n// - RHS expression has effects, or not;\n// - entire statement/declaration may be eliminated;\n// and removes associated comments.\n//\n// If it cannot make the necessary edits, such as for a function\n// parameter or result, it returns nil.\nfunc DeleteVar(tokFile *token.File, info *types.Info, curId inspector.Cursor) []Edit {\n\tswitch curId.ParentEdgeKind() {\n\tcase edge.ValueSpec_Names:\n\t\treturn deleteVarFromValueSpec(tokFile, info, curId)\n\n\tcase edge.AssignStmt_Lhs:\n\t\treturn deleteVarFromAssignStmt(tokFile, info, curId)\n\t}\n\n\t// e.g. function receiver, parameter, or result,\n\t// or \"switch v := expr.(T) {}\" (which has no object).\n\treturn nil\n}\n\n// deleteVarFromValueSpec returns edits to delete the declaration of a\n// variable or constant within a ValueSpec.\n//\n// Precondition: curId is Ident beneath ValueSpec.Names beneath GenDecl.\n//\n// See also [deleteVarFromAssignStmt], which has parallel structure.\nfunc deleteVarFromValueSpec(tokFile *token.File, info *types.Info, curIdent inspector.Cursor) []Edit {\n\tvar (\n\t\tid      = curIdent.Node().(*ast.Ident)\n\t\tcurSpec = curIdent.Parent()\n\t\tspec    = curSpec.Node().(*ast.ValueSpec)\n\t)\n\n\tdeclaresOtherNames := slices.ContainsFunc(spec.Names, func(name *ast.Ident) bool {\n\t\treturn name != id && name.Name != \"_\"\n\t})\n\tnoRHSEffects := !slices.ContainsFunc(spec.Values, func(rhs ast.Expr) bool {\n\t\treturn !typesinternal.NoEffects(info, rhs)\n\t})\n\tif !declaresOtherNames && noRHSEffects {\n\t\t// The spec is no longer needed, either to declare\n\t\t// other variables, or for its side effects.\n\t\treturn DeleteSpec(tokFile, curSpec)\n\t}\n\n\t// The spec is still needed, either for\n\t// at least one LHS, or for effects on RHS.\n\t// Blank out or delete just one LHS.\n\n\tindex := curIdent.ParentEdgeIndex() // index of LHS within ValueSpec.Names\n\n\t// If there is no RHS, we can delete the LHS.\n\tif len(spec.Values) == 0 {\n\t\tvar pos, end token.Pos\n\t\tif index == len(spec.Names)-1 {\n\t\t\t// Delete final name.\n\t\t\t//\n\t\t\t// var _, lhs1 T\n\t\t\t//      ------\n\t\t\tpos = spec.Names[index-1].End()\n\t\t\tend = spec.Names[index].End()\n\t\t} else {\n\t\t\t// Delete non-final name.\n\t\t\t//\n\t\t\t// var lhs0, _ T\n\t\t\t//     ------\n\t\t\tpos = spec.Names[index].Pos()\n\t\t\tend = spec.Names[index+1].Pos()\n\t\t}\n\t\treturn []Edit{{\n\t\t\tPos: pos,\n\t\t\tEnd: end,\n\t\t}}\n\t}\n\n\t// If the assignment is n:n and the RHS has no effects,\n\t// we can delete the LHS and its corresponding RHS.\n\tif len(spec.Names) == len(spec.Values) &&\n\t\ttypesinternal.NoEffects(info, spec.Values[index]) {\n\n\t\tif index == len(spec.Names)-1 {\n\t\t\t// Delete final items.\n\t\t\t//\n\t\t\t// var _, lhs1 = rhs0, rhs1\n\t\t\t//      ------       ------\n\t\t\treturn []Edit{\n\t\t\t\t{\n\t\t\t\t\tPos: spec.Names[index-1].End(),\n\t\t\t\t\tEnd: spec.Names[index].End(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos: spec.Values[index-1].End(),\n\t\t\t\t\tEnd: spec.Values[index].End(),\n\t\t\t\t},\n\t\t\t}\n\t\t} else {\n\t\t\t// Delete non-final items.\n\t\t\t//\n\t\t\t// var lhs0, _ = rhs0, rhs1\n\t\t\t//     ------    ------\n\t\t\treturn []Edit{\n\t\t\t\t{\n\t\t\t\t\tPos: spec.Names[index].Pos(),\n\t\t\t\t\tEnd: spec.Names[index+1].Pos(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos: spec.Values[index].Pos(),\n\t\t\t\t\tEnd: spec.Values[index+1].Pos(),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\t// We cannot delete the RHS.\n\t// Blank out the LHS.\n\treturn []Edit{{\n\t\tPos:     id.Pos(),\n\t\tEnd:     id.End(),\n\t\tNewText: []byte(\"_\"),\n\t}}\n}\n\n// Precondition: curId is Ident beneath AssignStmt.Lhs.\n//\n// See also [deleteVarFromValueSpec], which has parallel structure.\nfunc deleteVarFromAssignStmt(tokFile *token.File, info *types.Info, curIdent inspector.Cursor) []Edit {\n\tvar (\n\t\tid      = curIdent.Node().(*ast.Ident)\n\t\tcurStmt = curIdent.Parent()\n\t\tassign  = curStmt.Node().(*ast.AssignStmt)\n\t)\n\n\tdeclaresOtherNames := slices.ContainsFunc(assign.Lhs, func(lhs ast.Expr) bool {\n\t\tlhsId, ok := lhs.(*ast.Ident)\n\t\treturn ok && lhsId != id && lhsId.Name != \"_\"\n\t})\n\tnoRHSEffects := !slices.ContainsFunc(assign.Rhs, func(rhs ast.Expr) bool {\n\t\treturn !typesinternal.NoEffects(info, rhs)\n\t})\n\tif !declaresOtherNames && noRHSEffects {\n\t\t// The assignment is no longer needed, either to\n\t\t// declare other variables, or for its side effects.\n\t\tif edits := DeleteStmt(tokFile, curStmt); edits != nil {\n\t\t\treturn edits\n\t\t}\n\t\t// Statement could not not be deleted in this context.\n\t\t// Fall back to conservative deletion.\n\t}\n\n\t// The assign is still needed, either for\n\t// at least one LHS, or for effects on RHS,\n\t// or because it cannot deleted because of its context.\n\t// Blank out or delete just one LHS.\n\n\t// If the assignment is 1:1 and the RHS has no effects,\n\t// we can delete the LHS and its corresponding RHS.\n\tindex := curIdent.ParentEdgeIndex()\n\tif len(assign.Lhs) > 1 &&\n\t\tlen(assign.Lhs) == len(assign.Rhs) &&\n\t\ttypesinternal.NoEffects(info, assign.Rhs[index]) {\n\n\t\tif index == len(assign.Lhs)-1 {\n\t\t\t// Delete final items.\n\t\t\t//\n\t\t\t// _, lhs1 := rhs0, rhs1\n\t\t\t//  ------        ------\n\t\t\treturn []Edit{\n\t\t\t\t{\n\t\t\t\t\tPos: assign.Lhs[index-1].End(),\n\t\t\t\t\tEnd: assign.Lhs[index].End(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos: assign.Rhs[index-1].End(),\n\t\t\t\t\tEnd: assign.Rhs[index].End(),\n\t\t\t\t},\n\t\t\t}\n\t\t} else {\n\t\t\t// Delete non-final items.\n\t\t\t//\n\t\t\t// lhs0, _ := rhs0, rhs1\n\t\t\t// ------     ------\n\t\t\treturn []Edit{\n\t\t\t\t{\n\t\t\t\t\tPos: assign.Lhs[index].Pos(),\n\t\t\t\t\tEnd: assign.Lhs[index+1].Pos(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPos: assign.Rhs[index].Pos(),\n\t\t\t\t\tEnd: assign.Rhs[index+1].Pos(),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\t// We cannot delete the RHS.\n\t// Blank out the LHS.\n\tedits := []Edit{{\n\t\tPos:     id.Pos(),\n\t\tEnd:     id.End(),\n\t\tNewText: []byte(\"_\"),\n\t}}\n\n\t// If this eliminates the final variable declared by\n\t// an := statement, we need to turn it into an =\n\t// assignment to avoid a \"no new variables on left\n\t// side of :=\" error.\n\tif !declaresOtherNames {\n\t\tedits = append(edits, Edit{\n\t\t\tPos:     assign.TokPos,\n\t\t\tEnd:     assign.TokPos + token.Pos(len(\":=\")),\n\t\t\tNewText: []byte(\"=\"),\n\t\t})\n\t}\n\n\treturn edits\n}\n\n// DeleteSpec returns edits to delete the {Type,Value}Spec identified by curSpec.\n//\n// TODO(adonovan): add test suite. Test for consts as well.\nfunc DeleteSpec(tokFile *token.File, curSpec inspector.Cursor) []Edit {\n\tvar (\n\t\tspec    = curSpec.Node().(ast.Spec)\n\t\tcurDecl = curSpec.Parent()\n\t\tdecl    = curDecl.Node().(*ast.GenDecl)\n\t)\n\n\t// If it is the sole spec in the decl,\n\t// delete the entire decl.\n\tif len(decl.Specs) == 1 {\n\t\treturn DeleteDecl(tokFile, curDecl)\n\t}\n\n\t// Delete the spec and its comments.\n\tindex := curSpec.ParentEdgeIndex() // index of ValueSpec within GenDecl.Specs\n\tpos, end := spec.Pos(), spec.End()\n\tif doc := astutil.DocComment(spec); doc != nil {\n\t\tpos = doc.Pos() // leading comment\n\t}\n\tif index == len(decl.Specs)-1 {\n\t\t// Delete final spec.\n\t\tif c := eolComment(spec); c != nil {\n\t\t\t//  var (v int // comment \\n)\n\t\t\tend = c.End()\n\t\t}\n\t} else {\n\t\t// Delete non-final spec.\n\t\t//   var ( a T; b T )\n\t\t//         -----\n\t\tend = decl.Specs[index+1].Pos()\n\t}\n\treturn []Edit{{\n\t\tPos: pos,\n\t\tEnd: end,\n\t}}\n}\n\n// DeleteDecl returns edits to delete the ast.Decl identified by curDecl.\n//\n// TODO(adonovan): add test suite.\nfunc DeleteDecl(tokFile *token.File, curDecl inspector.Cursor) []Edit {\n\tdecl := curDecl.Node().(ast.Decl)\n\n\tek := curDecl.ParentEdgeKind()\n\tswitch ek {\n\tcase edge.DeclStmt_Decl:\n\t\treturn DeleteStmt(tokFile, curDecl.Parent())\n\n\tcase edge.File_Decls:\n\t\tpos, end := decl.Pos(), decl.End()\n\t\tif doc := astutil.DocComment(decl); doc != nil {\n\t\t\tpos = doc.Pos()\n\t\t}\n\n\t\t// Delete free-floating comments on same line as rparen.\n\t\t//    var (...) // comment\n\t\tvar (\n\t\t\tfile        = curDecl.Parent().Node().(*ast.File)\n\t\t\tlineOf      = tokFile.Line\n\t\t\tdeclEndLine = lineOf(decl.End())\n\t\t)\n\t\tfor _, cg := range file.Comments {\n\t\t\tfor _, c := range cg.List {\n\t\t\t\tif c.Pos() < end {\n\t\t\t\t\tcontinue // too early\n\t\t\t\t}\n\t\t\t\tcommentEndLine := lineOf(c.End())\n\t\t\t\tif commentEndLine > declEndLine {\n\t\t\t\t\tbreak // too late\n\t\t\t\t} else if lineOf(c.Pos()) == declEndLine && commentEndLine == declEndLine {\n\t\t\t\t\tend = c.End()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn []Edit{{\n\t\t\tPos: pos,\n\t\t\tEnd: end,\n\t\t}}\n\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"Decl parent is %v, want DeclStmt or File\", ek))\n\t}\n}\n\n// find leftmost Pos bigger than start and rightmost less than end\nfunc filterPos(nds []*ast.Comment, start, end token.Pos) (token.Pos, token.Pos, bool) {\n\tl, r := end, token.NoPos\n\tok := false\n\tfor _, n := range nds {\n\t\tif n.Pos() > start && n.Pos() < l {\n\t\t\tl = n.Pos()\n\t\t\tok = true\n\t\t}\n\t\tif n.End() <= end && n.End() > r {\n\t\t\tr = n.End()\n\t\t\tok = true\n\t\t}\n\t}\n\treturn l, r, ok\n}\n\n// DeleteStmt returns the edits to remove the [ast.Stmt] identified by\n// curStmt if it recognizes the context. It returns nil otherwise.\n// TODO(pjw, adonovan): it should not return nil, it should return an error\n//\n// DeleteStmt is called with just the AST so it has trouble deciding if\n// a comment is associated with the statement to be deleted. For instance,\n//\n//\tfor /*A*/ init()/*B*/;/*C/cond()/*D/;/*E*/post() /*F*/ { /*G*/}\n//\n// comment B and C are indistinguishable, as are D and E. That is, as the\n// AST does not say where the semicolons are, B and C could go either\n// with the init() or the cond(), so cannot be removed safely. The same\n// is true for D, E, and the post(). (And there are other similar cases.)\n// But the other comments can be removed as they are unambiguously\n// associated with the statement being deleted. In particular,\n// it removes whole lines like\n//\n//\tstmt // comment\nfunc DeleteStmt(file *token.File, curStmt inspector.Cursor) []Edit {\n\t// if the stmt is on a line by itself, or a range of lines, delete the whole thing\n\t// including comments. Except for the heads of switches, type\n\t// switches, and for-statements that's the usual case. Complexity occurs where\n\t// there are multiple statements on the same line, and adjacent comments.\n\n\t// In that case we remove some adjacent comments:\n\t// In me()/*A*/;b(), comment A cannot be removed, because the ast\n\t// is indistinguishable from me();/*A*/b()\n\t// and the same for cases like switch me()/*A*/; x.(type) {\n\n\t// this would be more precise with the file contents, or if the ast\n\t// contained the location of semicolons\n\tvar (\n\t\tstmt          = curStmt.Node().(ast.Stmt)\n\t\ttokFile       = file\n\t\tlineOf        = tokFile.Line\n\t\tstmtStartLine = lineOf(stmt.Pos())\n\t\tstmtEndLine   = lineOf(stmt.End())\n\n\t\tleftSyntax, rightSyntax     token.Pos      // pieces of parent node on stmt{Start,End}Line\n\t\tleftComments, rightComments []*ast.Comment // comments before/after stmt on the same line\n\t)\n\n\t// remember the Pos that are on the same line as stmt\n\tuse := func(left, right token.Pos) {\n\t\tif lineOf(left) == stmtStartLine {\n\t\t\tleftSyntax = left\n\t\t}\n\t\tif lineOf(right) == stmtEndLine {\n\t\t\trightSyntax = right\n\t\t}\n\t}\n\n\t// find the comments, if any, on the same line\nBig:\n\tfor _, cg := range astutil.EnclosingFile(curStmt).Comments {\n\t\tfor _, co := range cg.List {\n\t\t\tif lineOf(co.End()) < stmtStartLine {\n\t\t\t\tcontinue\n\t\t\t} else if lineOf(co.Pos()) > stmtEndLine {\n\t\t\t\tbreak Big // no more are possible\n\t\t\t}\n\t\t\tif lineOf(co.End()) == stmtStartLine && co.End() <= stmt.Pos() {\n\t\t\t\t// comment is before the statement\n\t\t\t\tleftComments = append(leftComments, co)\n\t\t\t} else if lineOf(co.Pos()) == stmtEndLine && co.Pos() >= stmt.End() {\n\t\t\t\t// comment is after the statement\n\t\t\t\trightComments = append(rightComments, co)\n\t\t\t}\n\t\t}\n\t}\n\n\t// find any other syntax on the same line\n\tvar (\n\t\tleftStmt, rightStmt token.Pos // end/start positions of sibling statements in a []Stmt list\n\t\tinStmtList          = false\n\t\tcurParent           = curStmt.Parent()\n\t)\n\tswitch parent := curParent.Node().(type) {\n\tcase *ast.BlockStmt:\n\t\tuse(parent.Lbrace, parent.Rbrace)\n\t\tinStmtList = true\n\tcase *ast.CaseClause:\n\t\tuse(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)\n\t\tinStmtList = true\n\tcase *ast.CommClause:\n\t\tif parent.Comm == stmt {\n\t\t\treturn nil // maybe the user meant to remove the entire CommClause?\n\t\t}\n\t\tuse(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)\n\t\tinStmtList = true\n\tcase *ast.ForStmt:\n\t\tuse(parent.For, parent.Body.Lbrace)\n\t\t// special handling, as init;cond;post BlockStmt is not a statment list\n\t\tif parent.Init != nil && parent.Cond != nil && stmt == parent.Init && lineOf(parent.Cond.Pos()) == lineOf(stmt.End()) {\n\t\t\trightStmt = parent.Cond.Pos()\n\t\t} else if parent.Post != nil && parent.Cond != nil && stmt == parent.Post && lineOf(parent.Cond.End()) == lineOf(stmt.Pos()) {\n\t\t\tleftStmt = parent.Cond.End()\n\t\t}\n\tcase *ast.IfStmt:\n\t\tswitch stmt {\n\t\tcase parent.Init:\n\t\t\tuse(parent.If, parent.Body.Lbrace)\n\t\tcase parent.Else:\n\t\t\t// stmt is the {...} in \"if cond {} else {...}\" and removing\n\t\t\t// it would require removing the 'else' keyword, but the ast\n\t\t\t// does not contain its position.\n\t\t\treturn nil\n\t\t}\n\tcase *ast.SwitchStmt:\n\t\tuse(parent.Switch, parent.Body.Lbrace)\n\tcase *ast.TypeSwitchStmt:\n\t\tif stmt == parent.Assign {\n\t\t\treturn nil // don't remove .(type)\n\t\t}\n\t\tuse(parent.Switch, parent.Body.Lbrace)\n\tdefault:\n\t\treturn nil // not one of ours\n\t}\n\n\tif inStmtList {\n\t\t// find the siblings, if any, on the same line\n\t\tif prev, found := curStmt.PrevSibling(); found && lineOf(prev.Node().End()) == stmtStartLine {\n\t\t\tif _, ok := prev.Node().(ast.Stmt); ok {\n\t\t\t\tleftStmt = prev.Node().End() // preceding statement ends on same line\n\t\t\t}\n\t\t}\n\t\tif next, found := curStmt.NextSibling(); found && lineOf(next.Node().Pos()) == stmtEndLine {\n\t\t\trightStmt = next.Node().Pos() // following statement begins on same line\n\t\t}\n\t}\n\n\t// compute the left and right limits of the edit\n\tvar leftEdit, rightEdit token.Pos\n\tif leftStmt.IsValid() {\n\t\tleftEdit = stmt.Pos() // can't remove preceding comments: a()/*A*/; me()\n\t} else if leftSyntax.IsValid() {\n\t\t// remove intervening leftComments\n\t\tif a, _, ok := filterPos(leftComments, leftSyntax, stmt.Pos()); ok {\n\t\t\tleftEdit = a\n\t\t} else {\n\t\t\tleftEdit = stmt.Pos()\n\t\t}\n\t} else { // remove whole line\n\t\tfor leftEdit = stmt.Pos(); lineOf(leftEdit) == stmtStartLine; leftEdit-- {\n\t\t}\n\t\tif leftEdit < stmt.Pos() {\n\t\t\tleftEdit++ // beginning of line\n\t\t}\n\t}\n\tif rightStmt.IsValid() {\n\t\trightEdit = stmt.End() // can't remove following comments\n\t} else if rightSyntax.IsValid() {\n\t\t// remove intervening rightComments\n\t\tif _, b, ok := filterPos(rightComments, stmt.End(), rightSyntax); ok {\n\t\t\trightEdit = b\n\t\t} else {\n\t\t\trightEdit = stmt.End()\n\t\t}\n\t} else { // remove whole line\n\t\tfend := token.Pos(file.Base()) + token.Pos(file.Size())\n\t\tfor rightEdit = stmt.End(); fend >= rightEdit && lineOf(rightEdit) == stmtEndLine; rightEdit++ {\n\t\t}\n\t\t// don't remove \\n if there was other stuff earlier\n\t\tif leftSyntax.IsValid() || leftStmt.IsValid() {\n\t\t\trightEdit--\n\t\t}\n\t}\n\n\treturn []Edit{{Pos: leftEdit, End: rightEdit}}\n}\n\n// DeleteUnusedVars computes the edits required to delete the\n// declarations of any local variables whose last uses are in the\n// curDelend subtree, which is about to be deleted.\nfunc DeleteUnusedVars(index *typeindex.Index, info *types.Info, tokFile *token.File, curDelend inspector.Cursor) []Edit {\n\t// TODO(adonovan): we might want to generalize this by\n\t// splitting the two phases below, so that we can gather\n\t// across a whole sequence of deletions then finally compute the\n\t// set of variables that are no longer wanted.\n\n\t// Count number of deletions of each var.\n\tdelcount := make(map[*types.Var]int)\n\tfor curId := range curDelend.Preorder((*ast.Ident)(nil)) {\n\t\tid := curId.Node().(*ast.Ident)\n\t\tif v, ok := info.Uses[id].(*types.Var); ok &&\n\t\t\ttypesinternal.GetVarKind(v) == typesinternal.LocalVar { // always false before go1.25\n\t\t\tdelcount[v]++\n\t\t}\n\t}\n\n\t// Delete declaration of each var that became unused.\n\tvar edits []Edit\n\tfor v, count := range delcount {\n\t\tif len(slices.Collect(index.Uses(v))) == count {\n\t\t\tif curDefId, ok := index.Def(v); ok {\n\t\t\t\tedits = append(edits, DeleteVar(tokFile, info, curDefId)...)\n\t\t\t}\n\t\t}\n\t}\n\treturn edits\n}\n\nfunc eolComment(n ast.Node) *ast.CommentGroup {\n\t// TODO(adonovan): support:\n\t//    func f() {...} // comment\n\tswitch n := n.(type) {\n\tcase *ast.GenDecl:\n\t\tif !n.TokPos.IsValid() && len(n.Specs) == 1 {\n\t\t\treturn eolComment(n.Specs[0])\n\t\t}\n\tcase *ast.ValueSpec:\n\t\treturn n.Comment\n\tcase *ast.TypeSpec:\n\t\treturn n.Comment\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/refactor/delete_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage refactor_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/refactor\"\n)\n\nfunc TestDeleteStmt(t *testing.T) {\n\ttype testCase struct {\n\t\tin    string\n\t\twhich int // count of ast.Stmt in ast.Inspect traversal to remove\n\t\twant  string\n\t\tname  string // should contain exactly one of [block,switch,case,comm,for,type]\n\t}\n\ttests := []testCase{\n\t\t{\n\t\t\tin:    \"package p; func f() {/*a*/x := 12/*b*/}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() {}\",\n\t\t\tname:  \"var0\",\n\t\t},\n\t\t{\n\t\t\tin:    \"package p; func f() {\\n/*a*/x := 12 //foo\\n//keep\\n}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() {\\n//keep\\n}\",\n\t\t\tname:  \"var1\",\n\t\t},\n\t\t{ // for code coverage\n\t\t\tin:    \"package p; func f() {/*a*/x:=12/*b*/; y:=11}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() {/*b*/; y:=11}\",\n\t\t\tname:  \"var2\",\n\t\t},\n\t\t{ // do nothing when asked to remove a function body\n\t\t\tin:    \"package p; func f() {  }\",\n\t\t\twhich: 0,\n\t\t\twant:  \"package p; func f() {  }\",\n\t\t\tname:  \"block0\",\n\t\t},\n\t\t{\n\t\t\tin:    \"package p; func f() { abcd()}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() { }\",\n\t\t\tname:  \"block1\",\n\t\t},\n\t\t{ // keep white space\n\t\t\tin:    \"package p; func f() { a() }\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() {  }\",\n\t\t\tname:  \"block2\",\n\t\t},\n\t\t{ // keep semicolon\n\t\t\tin:    \"package p; func f() { a();}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() { ;}\",\n\t\t\tname:  \"block3\",\n\t\t},\n\t\t{ // remove whole line\n\t\t\tin:    \"package p; func f() {\\n a() \\n\\n}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() {\\n\\n}\",\n\t\t\tname:  \"block4\",\n\t\t},\n\t\t{ // preserve whitespace and remove comment\n\t\t\tin:    \"package p; func f() { a()// comment\\n}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() { \\n}\",\n\t\t\tname:  \"block5\",\n\t\t},\n\t\t{ // preserve whitespace, remove preceding comment\n\t\t\tin:    \"package p; func f() { /*c*/a() \\n}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p; func f() { \\n}\",\n\t\t\tname:  \"block6\",\n\t\t},\n\t\t{\n\t\t\tin:    \"package p; func f() { a();b();}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() { a();;}\",\n\t\t\tname:  \"block7\",\n\t\t},\n\t\t{ // remove whole line\n\t\t\tin:    \"package p; func f() {\\n\\ta()\\n\\tb()\\n}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {\\n\\ta()\\n}\",\n\t\t\tname:  \"block8\",\n\t\t},\n\t\t{ // remove whole line\n\t\t\tin:    \"package p; func f() {\\n\\ta()\\n\\tb()\\n\\tc()\\n}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {\\n\\ta()\\n\\tc()\\n}\",\n\t\t\tname:  \"block9\",\n\t\t},\n\t\t{ // remove expression statement\n\t\t\tin:    \"package p\\nfunc f() {a()+b()}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p\\nfunc f() {}\",\n\t\t\tname:  \"block10\",\n\t\t},\n\t\t{ // even in parentheses\n\t\t\tin:    \"package p\\nfunc f() {(a()+b())}\",\n\t\t\twhich: 1,\n\t\t\twant:  \"package p\\nfunc f() {}\",\n\t\t\tname:  \"block11\",\n\t\t},\n\t\t{ // should it also remove the semicolon? No, can't find it.\n\t\t\tin:    \"package p; func f() { switch a(); b() {}}\",\n\t\t\twhich: 2, // 0 is the func body, 1 is the switch statement\n\t\t\twant:  \"package p; func f() { switch ; b() {}}\",\n\t\t\tname:  \"switch0\",\n\t\t},\n\t\t{ // remove preceding comment too\n\t\t\tin:    \"package p; func f() { switch /*c*/a(); {}}\",\n\t\t\twhich: 2, // 0 is the func body, 1 is the switch statement\n\t\t\twant:  \"package p; func f() { switch ; {}}\",\n\t\t\tname:  \"switch1\",\n\t\t},\n\t\t{ // remove subsequent comment too\n\t\t\tin:    \"package p; func f() { switch a()/*c*/; {}}\",\n\t\t\twhich: 2, // 0 is the func body, 1 is the switch statement\n\t\t\twant:  \"package p; func f() { switch ; {}}\",\n\t\t\tname:  \"switch2\",\n\t\t},\n\t\t{ // statement inside a case\n\t\t\tin:    \"package p; func f() { select {default: a()}}\",\n\t\t\twhich: 4, // 0 is the func body, 1 is the select statement, 2 is its body, 3 is the comm clause\n\t\t\twant:  \"package p; func f() { select {default: }}\",\n\t\t\tname:  \"comm0\",\n\t\t},\n\t\t{ // statement in comm clause\n\t\t\tin:    \"package p; func f(x chan any) { select {case x <- a: a(x)}}\",\n\t\t\twhich: 5, // 0 is the func body, 1 is the select statement, 2 is its body, 3 is the comm clause\n\t\t\twant:  \"package p; func f(x chan any) { select {case x <- a: }}\",\n\t\t\tname:  \"comm1\",\n\t\t},\n\t\t{ // don't remove whole clause\n\t\t\tin:    \"package p; func f(x chan any) { select {case x <- a: a(x)}}\",\n\t\t\twhich: 4, // 0 is the func body, 1 is the select statement, 2 is its body, 3 is the comm clause\n\t\t\twant:  \"package p; func f(x chan any) { select {case x <- a: a(x)}}\",\n\t\t\tname:  \"comm2\",\n\t\t},\n\t\t{\n\t\t\tin:    \"package p; func f() { switch {default: a()}}\",\n\t\t\twhich: 4, // 0 is the func body, 1 is the select statement, 2 is its body\n\t\t\twant:  \"package p; func f() { switch {default: }}\",\n\t\t\tname:  \"case0\",\n\t\t},\n\t\t{\n\t\t\tin:    \"package p; func f() { switch {case 3: /*A*/ a() /*B*/}}\",\n\t\t\twhich: 4, // 0 is the func body, 1 is the select statement, 2 is its body\n\t\t\twant:  \"package p; func f() { switch {case 3: }}\",\n\t\t\tname:  \"case1\",\n\t\t},\n\t\t{ // init in for statement\n\t\t\tin:    \"package p; func f() {for /*a*/ a();;b() {}}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {for ;;b() {}}\",\n\t\t\tname:  \"for0\",\n\t\t},\n\t\t{ // step in for statement\n\t\t\tin:    \"package p; func f() {for a();c();b() /*B*/ {}}\",\n\t\t\twhich: 3,\n\t\t\twant:  \"package p; func f() {for a();c(); {}}\",\n\t\t\tname:  \"for1\",\n\t\t},\n\t\t{ // one of two func calls on. line\n\t\t\tin:    \"package p; func f() {for\\na();c()\\nb() {}}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {for\\n;c()\\nb() {}}\",\n\t\t\tname:  \"for2\",\n\t\t},\n\t\t{ // step in for, with strange \\n\n\t\t\tin:    \"package p; func f() {for a();\\nc();b() {}}\",\n\t\t\twhich: 3,\n\t\t\twant:  \"package p; func f() {for a();\\nc(); {}}\",\n\t\t\tname:  \"for3\",\n\t\t},\n\t\t{ // in type switch\n\t\t\tin:    \"package p; func f() {switch a();b().(type){}}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {switch ;b().(type){}}\",\n\t\t\tname:  \"type0\",\n\t\t},\n\t\t{ // but not the type cast\n\t\t\tin:    \"package p; func f() {switch a();b().(type){}}\",\n\t\t\twhich: 3,\n\t\t\twant:  \"package p; func f() {switch a();b().(type){}}\",\n\t\t\tname:  \"type1\",\n\t\t},\n\t\t{ // if\n\t\t\tin:    \"package p; func f() {if a();b() {}}\",\n\t\t\twhich: 2,\n\t\t\twant:  \"package p; func f() {if ;b() {}}\",\n\t\t\tname:  \"if0\",\n\t\t},\n\t\t{ // cannot remove the else\n\t\t\tin:    \"package p\\nfunc _() { if a() {}  else {b()}}\",\n\t\t\twhich: 3,\n\t\t\twant:  \"package p\\nfunc _() { if a() {}  else {b()}}\",\n\t\t\tname:  \"else0\",\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, tt.name, tt.in, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"%s: %v\", tt.name, err)\n\t\t\t}\n\t\t\tinsp := inspector.New([]*ast.File{f})\n\t\t\troot := insp.Root()\n\t\t\tvar stmt inspector.Cursor\n\t\t\tcnt := 0\n\t\t\tfor cn := range root.Preorder() { // Preorder(ast.Stmt(nil)) doesn't work\n\t\t\t\tif _, ok := cn.Node().(ast.Stmt); !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif cnt == tt.which {\n\t\t\t\t\tstmt = cn\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcnt++\n\t\t\t}\n\t\t\tif cnt != tt.which {\n\t\t\t\tt.Fatalf(\"test %s does not contain desired statement %d\", tt.name, tt.which)\n\t\t\t}\n\t\t\ttokFile := fset.File(f.Pos())\n\t\t\tedits := refactor.DeleteStmt(tokFile, stmt)\n\t\t\tif tt.want == tt.in {\n\t\t\t\tif len(edits) != 0 {\n\t\t\t\t\tt.Fatalf(\"%s: got %d edits, expected 0\", tt.name, len(edits))\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif len(edits) != 1 {\n\t\t\t\tt.Fatalf(\"%s: got %d edits, expected 1\", tt.name, len(edits))\n\t\t\t}\n\n\t\t\tleft := tokFile.Offset(edits[0].Pos)\n\t\t\tright := tokFile.Offset(edits[0].End)\n\n\t\t\tgot := tt.in[:left] + tt.in[right:]\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"%s: got\\n%q, want\\n%q\", tt.name, got, tt.want)\n\t\t\t}\n\t\t})\n\n\t}\n}\n\nfunc TestDeleteVar(t *testing.T) {\n\t// Each example deletes var v.\n\tfor i, test := range []struct {\n\t\tsrc  string\n\t\twant string\n\t}{\n\t\t// package-level GenDecl > ValueSpec\n\t\t{\n\t\t\t\"package p; var v int\",\n\t\t\t\"package p; \",\n\t\t},\n\t\t{\n\t\t\t\"package p; var x, v int\",\n\t\t\t\"package p; var x int\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var v, x int\",\n\t\t\t\"package p; var x int\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v int )\",\n\t\t\t\"package p;\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( x, v int )\",\n\t\t\t\"package p; var ( x int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v, x int )\",\n\t\t\t\"package p; var ( x int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var v, x = 1, 2\",\n\t\t\t\"package p; var x = 2\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var x, v = 1, 2\",\n\t\t\t\"package p; var x = 1\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var v, x = fx(), fx()\",\n\t\t\t\"package p; var _, x = fx(), fx()\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var v, _ = fx(), fx()\",\n\t\t\t\"package p; var _, _ = fx(), fx()\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var _, v = fx(), fx()\",\n\t\t\t\"package p; var _, _ = fx(), fx()\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var v = fx()\",\n\t\t\t\"package p; var _ = fx()\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( a int; v int; c int )\",\n\t\t\t\"package p; var ( a int; c int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( a int; v int = 2; c int )\",\n\t\t\t\"package p; var ( a int; c int )\",\n\t\t},\n\t\t// GenDecl doc comments are not deleted unless decl is deleted.\n\t\t{\n\t\t\t\"package p\\n// comment\\nvar ( v int )\",\n\t\t\t\"package p\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\n// comment\\nvar v int\",\n\t\t\t\"package p\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\n/* comment */\\nvar v int\",\n\t\t\t\"package p\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\n// comment\\nvar ( v, x int )\",\n\t\t\t\"package p\\n// comment\\nvar ( x int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\n// comment\\nvar v, x int\",\n\t\t\t\"package p\\n// comment\\nvar x int\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\n/* comment */\\nvar x, v int\",\n\t\t\t\"package p\\n/* comment */\\nvar x int\",\n\t\t},\n\t\t// ValueSpec leading doc comments\n\t\t{\n\t\t\t\"package p\\nvar (\\n// comment\\nv int; x int )\",\n\t\t\t\"package p\\nvar (\\nx int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p\\nvar (\\n// comment\\nx int; v int )\",\n\t\t\t\"package p\\nvar (\\n// comment\\nx int )\",\n\t\t},\n\t\t// ValueSpec trailing line comments\n\t\t{\n\t\t\t\"package p; var ( v int // comment\\nx int )\",\n\t\t\t\"package p; var ( x int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( x int // comment\\nv int )\",\n\t\t\t\"package p; var ( x int // comment\\n )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v int /* comment */)\",\n\t\t\t\"package p;\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v int // comment\\n)\",\n\t\t\t\"package p;\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v int ) // comment\",\n\t\t\t\"package p;\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( x, v int /* comment */ )\",\n\t\t\t\"package p; var ( x int /* comment */ )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v, x int /* comment */ )\",\n\t\t\t\"package p; var ( x int /* comment */ )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( x, v int // comment\\n)\",\n\t\t\t\"package p; var ( x int // comment\\n)\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v, x int // comment\\n)\",\n\t\t\t\"package p; var ( x int // comment\\n)\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v, x int ) // comment\",\n\t\t\t\"package p; var ( x int ) // comment\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( x int; v int // comment\\n)\",\n\t\t\t\"package p; var ( x int )\",\n\t\t},\n\t\t{\n\t\t\t\"package p; var ( v int // comment\\n x int )\",\n\t\t\t\"package p; var ( x int )\",\n\t\t},\n\t\t// local DeclStmt > GenDecl > ValueSpec\n\t\t// (The only interesting cases\n\t\t// here are the total deletions.)\n\t\t{\n\t\t\t\"package p; func _() { var v int }\",\n\t\t\t\"package p; func _() {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { var ( v int ) }\",\n\t\t\t\"package p; func _() {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { var ( v int // comment\\n) }\",\n\t\t\t\"package p; func _() {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { var ( v int ) // comment\\n }\",\n\t\t\t\"package p; func _() { \\n}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { var v int // comment\\n }\",\n\t\t\t\"package p; func _() { \\n}\",\n\t\t},\n\t\t// AssignStmt\n\t\t{\n\t\t\t\"package p; func _() { v := 0 }\",\n\t\t\t\"package p; func _() {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { x, v := 0, 1 }\",\n\t\t\t\"package p; func _() { x := 0 }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v, x := 0, 1 }\",\n\t\t\t\"package p; func _() { x := 1 }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v, x := f() }\",\n\t\t\t\"package p; func _() { _, x := f() }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v, x := fx(), fx() }\",\n\t\t\t\"package p; func _() { _, x := fx(), fx() }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v, _ := fx(), fx() }\",\n\t\t\t\"package p; func _() { _, _ = fx(), fx() }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { _, v := fx(), fx() }\",\n\t\t\t\"package p; func _() { _, _ = fx(), fx() }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v := fx() }\",\n\t\t\t\"package p; func _() { _ = fx() }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v := 1 // comment\\n }\",\n\t\t\t\"package p; func _() { \\n}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { v, x := 0, 1 // comment\\n }\",\n\t\t\t\"package p; func _() { x := 1 // comment\\n }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { if v := 1; cond {} }\",\n\t\t\t\"package p; func _() { if ; cond {} }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { if v, x := 1, 2; cond {} }\",\n\t\t\t\"package p; func _() { if x := 2; cond {} }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { switch v := 0; cond {} }\",\n\t\t\t\"package p; func _() { switch cond {} }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { switch v := fx(); cond {} }\",\n\t\t\t\"package p; func _() { switch _ = fx(); cond {} }\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() { for v := 0; ; {} }\",\n\t\t\t\"package p; func _() { for {} }\",\n\t\t},\n\t\t// unhandled cases\n\t\t{\n\t\t\t\"package p; func _(v int) {}\", // parameter\n\t\t\t\"package p; func _(v int) {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; func _() (v int) {}\", // result\n\t\t\t\"package p; func _() (v int) {}\",\n\t\t},\n\t\t{\n\t\t\t\"package p; type T int; func _(v T) {}\", // receiver\n\t\t\t\"package p; type T int; func _(v T) {}\",\n\t\t},\n\t\t// There is no defining Ident in this case.\n\t\t// {\n\t\t// \t\"package p; func _() { switch v := any(nil).(type) {} }\",\n\t\t// \t\"package p; func _() { switch v := any(nil).(type) {} }\",\n\t\t// },\n\t} {\n\t\tt.Run(fmt.Sprint(i), func(t *testing.T) {\n\t\t\tt.Logf(\"src: %s\", test.src)\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, _ := parser.ParseFile(fset, \"p\", test.src, parser.ParseComments) // allow errors\n\t\t\tconf := types.Config{\n\t\t\t\tError: func(err error) {}, // allow errors\n\t\t\t}\n\t\t\tinfo := &types.Info{\n\t\t\t\tTypes: make(map[ast.Expr]types.TypeAndValue),\n\t\t\t\tDefs:  make(map[*ast.Ident]types.Object),\n\t\t\t}\n\t\t\tfiles := []*ast.File{f}\n\t\t\tconf.Check(\"p\", fset, files, info) // ignore error\n\n\t\t\tcurId := func() inspector.Cursor {\n\t\t\t\tfor curId := range inspector.New(files).Root().Preorder((*ast.Ident)(nil)) {\n\t\t\t\t\tid := curId.Node().(*ast.Ident)\n\t\t\t\t\tif id.Name == \"v\" && info.Defs[id] != nil {\n\t\t\t\t\t\treturn curId\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tt.Fatalf(\"can't find Defs[v]\")\n\t\t\t\tpanic(\"unreachable\")\n\t\t\t}()\n\t\t\ttokFile := fset.File(f.Pos())\n\t\t\tedits := refactor.DeleteVar(tokFile, info, curId)\n\n\t\t\t// TODO(adonovan): extract this helper for\n\t\t\t// applying TextEdits and comparing against\n\t\t\t// expectations. (This code was mostly copied\n\t\t\t// from analysistest.)\n\t\t\tvar dedits []diff.Edit\n\t\t\tfor _, edit := range edits {\n\t\t\t\tfile := fset.File(edit.Pos)\n\t\t\t\tdedits = append(dedits, diff.Edit{\n\t\t\t\t\tStart: file.Offset(edit.Pos),\n\t\t\t\t\tEnd:   file.Offset(edit.End),\n\t\t\t\t\tNew:   string(edit.NewText),\n\t\t\t\t})\n\t\t\t}\n\t\t\tfixed, err := diff.ApplyBytes([]byte(test.src), dedits)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"diff.Apply: %v\", err)\n\t\t\t}\n\t\t\tt.Logf(\"fixed: %s\", fixed)\n\t\t\tfixed, err = format.Source(fixed)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"format: %v\", err)\n\t\t\t}\n\t\t\twant, err := format.Source([]byte(test.want))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"formatting want: %v\", err)\n\t\t\t}\n\t\t\tt.Logf(\"want: %s\", want)\n\t\t\tunified := func(xlabel, ylabel string, x, y []byte) string {\n\t\t\t\tx = append(slices.Clip(bytes.TrimSpace(x)), '\\n')\n\t\t\t\ty = append(slices.Clip(bytes.TrimSpace(y)), '\\n')\n\t\t\t\treturn diff.Unified(xlabel, ylabel, string(x), string(y))\n\t\t\t}\n\t\t\tif diff := unified(\"fixed\", \"want\", fixed, want); diff != \"\" {\n\t\t\t\tt.Errorf(\"-- diff original fixed --\\n%s\\n\"+\n\t\t\t\t\t\"-- diff fixed want --\\n%s\",\n\t\t\t\t\tunified(\"original\", \"fixed\", []byte(test.src), fixed),\n\t\t\t\t\tdiff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/refactor/edit.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.p\n\npackage refactor\n\n// This is the only file in this package that should import analysis.\n//\n// TODO(adonovan): consider unaliasing the type to break the\n// dependency. (The ergonomics of slice append are unfortunate.)\n\nimport \"golang.org/x/tools/go/analysis\"\n\n// An Edit describes a deletion and/or an insertion.\ntype Edit = analysis.TextEdit\n"
  },
  {
    "path": "internal/refactor/imports.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage refactor\n\n// This file defines operations for computing edits to imports.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\tpathpkg \"path\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/internal/packagepath\"\n)\n\n// AddImport returns the prefix (either \"pkg.\" or \"\") that should be\n// used to qualify references to the desired symbol (member) imported\n// from the specified package, plus any necessary edits to the file's\n// import declaration to add a new import.\n//\n// If the import already exists, and is accessible at pos, AddImport\n// returns the existing name and no edits. (If the existing import is\n// a dot import, the prefix is \"\".)\n//\n// Otherwise, it adds a new import, using a local name derived from\n// the preferred name. To request a blank import, use a preferredName\n// of \"_\", and discard the prefix result; member is ignored in this\n// case.\n//\n// AddImport accepts the caller's implicit claim that the imported\n// package declares member.\n//\n// AddImport does not mutate its arguments.\nfunc AddImport(info *types.Info, file *ast.File, preferredName, pkgpath, member string, pos token.Pos) (prefix string, edits []Edit) {\n\t// Find innermost enclosing lexical block.\n\tscope := info.Scopes[file].Innermost(pos)\n\tif scope == nil {\n\t\tpanic(\"no enclosing lexical block\")\n\t}\n\n\t// Is there an existing import of this package?\n\t// If so, are we in its scope? (not shadowed)\n\tfor _, spec := range file.Imports {\n\t\tpkgname := info.PkgNameOf(spec)\n\t\tif pkgname != nil && pkgname.Imported().Path() == pkgpath {\n\t\t\tname := pkgname.Name()\n\t\t\tif preferredName == \"_\" {\n\t\t\t\t// Request for blank import; any existing import will do.\n\t\t\t\treturn \"\", nil\n\t\t\t}\n\t\t\tif name == \".\" {\n\t\t\t\t// The scope of ident must be the file scope.\n\t\t\t\tif s, _ := scope.LookupParent(member, pos); s == info.Scopes[file] {\n\t\t\t\t\treturn \"\", nil\n\t\t\t\t}\n\t\t\t} else if _, obj := scope.LookupParent(name, pos); obj == pkgname {\n\t\t\t\treturn name + \".\", nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// We must add a new import.\n\n\t// Ensure we have a fresh name.\n\tnewName := preferredName\n\tif preferredName != \"_\" {\n\t\tnewName = FreshName(scope, pos, preferredName)\n\t\tprefix = newName + \".\"\n\t}\n\n\t// Use a renaming import whenever the preferred name is not\n\t// available, or the chosen name does not match the last\n\t// segment of its path.\n\tif newName == preferredName && newName == pathpkg.Base(pkgpath) {\n\t\tnewName = \"\"\n\t}\n\n\treturn prefix, AddImportEdits(file, newName, pkgpath)\n}\n\n// AddImportEdits returns the edits to add an import of the specified\n// package, without any analysis of whether this is necessary or safe.\n// If name is nonempty, it is used as an explicit [ImportSpec.Name].\n//\n// A sequence of calls to AddImportEdits that each add the file's\n// first import (or in a file that does not have a grouped import) may\n// result in multiple import declarations, rather than a single one\n// with multiple ImportSpecs. However, a subsequent run of\n// x/tools/cmd/goimports ([imports.Process]) will combine them.\n//\n// AddImportEdits does not mutate the AST.\nfunc AddImportEdits(file *ast.File, name, pkgpath string) []Edit {\n\tnewText := strconv.Quote(pkgpath)\n\tif name != \"\" {\n\t\tnewText = name + \" \" + newText\n\t}\n\n\t// Create a new import declaration either before the first existing\n\t// declaration (which must exist), including its comments; or\n\t// inside the declaration, if it is an import group.\n\tdecl0 := file.Decls[0]\n\tbefore := decl0.Pos()\n\tswitch decl0 := decl0.(type) {\n\tcase *ast.GenDecl:\n\t\tif decl0.Doc != nil {\n\t\t\tbefore = decl0.Doc.Pos()\n\t\t}\n\tcase *ast.FuncDecl:\n\t\tif decl0.Doc != nil {\n\t\t\tbefore = decl0.Doc.Pos()\n\t\t}\n\t}\n\tvar pos token.Pos\n\tif gd, ok := decl0.(*ast.GenDecl); ok && gd.Tok == token.IMPORT && gd.Rparen.IsValid() {\n\t\t// Have existing grouped import ( ... ) decl.\n\t\tif packagepath.IsStdPackage(pkgpath) && len(gd.Specs) > 0 {\n\t\t\t// Add spec for a std package before\n\t\t\t// first existing spec, followed by\n\t\t\t// a blank line if the next one is non-std.\n\t\t\tfirst := gd.Specs[0].(*ast.ImportSpec)\n\t\t\tpos = first.Pos()\n\t\t\tif !packagepath.IsStdPackage(first.Path.Value) {\n\t\t\t\tnewText += \"\\n\"\n\t\t\t}\n\t\t\tnewText += \"\\n\\t\"\n\t\t} else {\n\t\t\t// Add spec at end of group.\n\t\t\tpos = gd.Rparen\n\t\t\tnewText = \"\\t\" + newText + \"\\n\"\n\t\t}\n\t} else {\n\t\t// No import decl, or non-grouped import.\n\t\t// Add a new import decl before first decl.\n\t\t// (gofmt will merge multiple import decls.)\n\t\t//\n\t\t// TODO(adonovan): do better here; plunder the\n\t\t// mergeImports logic from [imports.Process].\n\t\tpos = before\n\t\tnewText = \"import \" + newText + \"\\n\\n\"\n\t}\n\treturn []Edit{{\n\t\tPos:     pos,\n\t\tEnd:     pos,\n\t\tNewText: []byte(newText),\n\t}}\n}\n"
  },
  {
    "path": "internal/refactor/imports_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage refactor_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestAddImport(t *testing.T) {\n\ttestenv.NeedsDefaultImporter(t)\n\n\tdescr := func(s string) string {\n\t\tif _, _, line, ok := runtime.Caller(1); ok {\n\t\t\treturn fmt.Sprintf(\"L%d %s\", line, s)\n\t\t}\n\t\tpanic(\"runtime.Caller failed\")\n\t}\n\n\t// Each test case contains a «name pkgpath member»\n\t// triple to be replaced with a valid qualified identifier\n\t// to pkgpath.member, ideally of the specified name.\n\tfor _, test := range []struct {\n\t\tdescr, src, want string\n\t}{\n\t\t{\n\t\t\tdescr: descr(\"simple add import\"),\n\t\t\tsrc: `package a\nfunc _() {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\nimport \"fmt\"\n\nfunc _() {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"existing import\"),\n\t\t\tsrc: `package a\n\nimport \"fmt\"\n\nfunc _(fmt.Stringer) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport \"fmt\"\n\nfunc _(fmt.Stringer) {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"existing blank import\"),\n\t\t\tsrc: `package a\n\nimport _ \"fmt\"\n\nfunc _() {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport \"fmt\"\n\nimport _ \"fmt\"\n\nfunc _() {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"existing renaming import\"),\n\t\t\tsrc: `package a\n\nimport fmtpkg \"fmt\"\n\nvar fmt int\n\nfunc _(fmtpkg.Stringer) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport fmtpkg \"fmt\"\n\nvar fmt int\n\nfunc _(fmtpkg.Stringer) {\n\tfmtpkg.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"existing import is shadowed\"),\n\t\t\tsrc: `package a\n\nimport \"fmt\"\n\nvar _ fmt.Stringer\n\nfunc _(fmt int) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport fmt0 \"fmt\"\n\nimport \"fmt\"\n\nvar _ fmt.Stringer\n\nfunc _(fmt int) {\n\tfmt0.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"preferred name is shadowed\"),\n\t\t\tsrc: `package a\n\nimport \"fmt\"\n\nfunc _(fmt fmt.Stringer) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport fmt0 \"fmt\"\n\nimport \"fmt\"\n\nfunc _(fmt fmt.Stringer) {\n\tfmt0.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"import inserted before doc comments\"),\n\t\t\tsrc: `package a\n\n// hello\nimport \"os\"\n\n// world\nfunc _() {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport \"fmt\"\n\n// hello\nimport \"os\"\n\n// world\nfunc _() {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"arbitrary preferred name => renaming import\"),\n\t\t\tsrc: `package a\n\nfunc _() {\n\t«foo encoding/json Marshal»\n}`,\n\t\t\twant: `package a\n\nimport foo \"encoding/json\"\n\nfunc _() {\n\tfoo.Marshal\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"dot import unshadowed\"),\n\t\t\tsrc: `package a\n\nimport . \"fmt\"\n\nfunc _() {\n\t«. fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport . \"fmt\"\n\nfunc _() {\n\tPrint\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"dot import shadowed\"),\n\t\t\tsrc: `package a\n\nimport . \"fmt\"\n\nfunc _(Print fmt.Stringer) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport \"fmt\"\n\nimport . \"fmt\"\n\nfunc _(Print fmt.Stringer) {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"add import to group\"),\n\t\t\tsrc: `package a\n\nimport (\n\t\"io\"\n)\n\nfunc _(io.Reader) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nfunc _(io.Reader) {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"add import to group which imports std and a 3rd module\"),\n\t\t\tsrc: `package a\n\nimport (\n\t\"io\"\n\n\t\"vendor/golang.org/x/net/dns/dnsmessage\"\n)\n\nfunc _(io.Reader) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"vendor/golang.org/x/net/dns/dnsmessage\"\n)\n\nfunc _(io.Reader) {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"add import to group which imports std and a 3rd module without parens\"),\n\t\t\tsrc: `package a\n\nimport \"io\"\n\nimport \"vendor/golang.org/x/net/dns/dnsmessage\"\n\nfunc _(io.Reader) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport \"fmt\"\n\nimport \"io\"\n\nimport \"vendor/golang.org/x/net/dns/dnsmessage\"\n\nfunc _(io.Reader) {\n\tfmt.Print\n}`,\n\t\t},\n\t\t{\n\t\t\tdescr: descr(\"add import to group without std import\"),\n\t\t\tsrc: `package a\n\nimport (\n\t\"golang.org/x/tools/go/packages\"\n\tgossa \"golang.org/x/tools/go/ssa\"\n)\n\nfunc _(io.Reader) {\n\t«fmt fmt Print»\n}`,\n\t\t\twant: `package a\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/x/tools/go/packages\"\n\tgossa \"golang.org/x/tools/go/ssa\"\n)\n\nfunc _(io.Reader) {\n\tfmt.Print\n}`,\n\t\t},\n\t} {\n\t\tt.Run(test.descr, func(t *testing.T) {\n\t\t\t// splice marker (name pkgpath member)\n\t\t\tbefore, mid, ok1 := strings.Cut(test.src, \"«\")\n\t\t\tmid, after, ok2 := strings.Cut(mid, \"»\")\n\t\t\tif !ok1 || !ok2 {\n\t\t\t\tt.Fatal(\"no «name path member» marker\")\n\t\t\t}\n\t\t\tsrc := before + \"/*!*/\" + after\n\t\t\tfields := strings.Fields(mid)\n\t\t\tif len(fields) != 3 {\n\t\t\t\tt.Fatalf(\"splice marker needs 3 fields (got %q)\", mid)\n\t\t\t}\n\t\t\tname, path, member := fields[0], fields[1], fields[2]\n\n\t\t\t// parse\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, \"a.go\", src, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\tt.Log(err)\n\t\t\t}\n\t\t\tpos := fset.File(f.FileStart).Pos(len(before))\n\n\t\t\t// type-check\n\t\t\tinfo := &types.Info{\n\t\t\t\tTypes:     make(map[ast.Expr]types.TypeAndValue),\n\t\t\t\tScopes:    make(map[ast.Node]*types.Scope),\n\t\t\t\tDefs:      make(map[*ast.Ident]types.Object),\n\t\t\t\tImplicits: make(map[ast.Node]types.Object),\n\t\t\t}\n\t\t\tconf := &types.Config{\n\t\t\t\t// We don't want to fail if there is an error during type checking:\n\t\t\t\t// the error may be because we're missing an import, and adding imports\n\t\t\t\t// is the whole point of AddImport.\n\t\t\t\tError:    func(err error) { t.Log(err) },\n\t\t\t\tImporter: importer.Default(),\n\t\t\t}\n\t\t\tconf.Check(f.Name.Name, fset, []*ast.File{f}, info)\n\n\t\t\tprefix, edits := refactor.AddImport(info, f, name, path, member, pos)\n\n\t\t\tvar edit refactor.Edit\n\t\t\tswitch len(edits) {\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\tedit = edits[0]\n\t\t\tdefault:\n\t\t\t\tt.Fatalf(\"expected at most one edit, got %d\", len(edits))\n\t\t\t}\n\n\t\t\t// apply patch\n\t\t\tstart := fset.Position(edit.Pos)\n\t\t\tend := fset.Position(edit.End)\n\t\t\toutput := src[:start.Offset] + string(edit.NewText) + src[end.Offset:]\n\t\t\toutput = strings.ReplaceAll(output, \"/*!*/\", prefix+member)\n\t\t\tif output != test.want {\n\t\t\t\tt.Errorf(\"\\n--got--\\n%s\\n--want--\\n%s\\n--diff--\\n%s\",\n\t\t\t\t\toutput, test.want, cmp.Diff(test.want, output))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/refactor/inline/callee.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\n// This file defines the analysis of the callee function.\n\nimport (\n\t\"bytes\"\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// A Callee holds information about an inlinable function. Gob-serializable.\ntype Callee struct {\n\timpl gobCallee\n}\n\nfunc (callee *Callee) String() string { return callee.impl.Name }\n\ntype gobCallee struct {\n\tContent []byte // file content, compacted to a single func decl\n\n\t// results of type analysis (does not reach go/types data structures)\n\tPkgPath          string                 // package path of declaring package\n\tName             string                 // user-friendly name for error messages\n\tGoVersion        string                 // version of Go effective in callee file\n\tUnexported       []string               // names of free objects that are unexported\n\tFreeRefs         []freeRef              // locations of references to free objects\n\tFreeObjs         []object               // descriptions of free objects\n\tValidForCallStmt bool                   // function body is \"return expr\" where expr is f() or <-ch\n\tNumResults       int                    // number of results (according to type, not ast.FieldList)\n\tParams           []*paramInfo           // information about parameters (incl. receiver)\n\tTypeParams       []*paramInfo           // information about type parameters\n\tResults          []*paramInfo           // information about result variables\n\tEffects          []int                  // order in which parameters are evaluated (see calleefx)\n\tHasDefer         bool                   // uses defer\n\tHasBareReturn    bool                   // uses bare return in non-void function\n\tReturns          [][]returnOperandFlags // metadata about result expressions for each return\n\tLabels           []string               // names of all control labels\n\tFalcon           falconResult           // falcon constraint system\n}\n\n// returnOperandFlags records metadata about a single result expression in a return\n// statement.\ntype returnOperandFlags int\n\nconst (\n\tnonTrivialResult returnOperandFlags = 1 << iota // return operand has non-trivial conversion to result type\n\tuntypedNilResult                                // return operand is nil literal\n)\n\n// A freeRef records a reference to a free object. Gob-serializable.\n// (This means free relative to the FuncDecl as a whole, i.e. excluding parameters.)\ntype freeRef struct {\n\tOffset int // byte offset of the reference relative to the FuncDecl\n\tObject int // index into Callee.freeObjs\n}\n\n// An object abstracts a free types.Object referenced by the callee. Gob-serializable.\ntype object struct {\n\tName    string // Object.Name()\n\tKind    string // one of {var,func,const,type,pkgname,nil,builtin}\n\tPkgPath string // path of object's package (or imported package if kind=\"pkgname\")\n\tPkgName string // name of object's package (or imported package if kind=\"pkgname\")\n\t// TODO(rfindley): should we also track LocalPkgName here? Do we want to\n\t// preserve the local package name?\n\tValidPos bool      // Object.Pos().IsValid()\n\tShadow   shadowMap // shadowing info for the object's refs\n}\n\n// AnalyzeCallee analyzes a function that is a candidate for inlining\n// and returns a Callee that describes it. The Callee object, which is\n// serializable, can be passed to one or more subsequent calls to\n// Inline, each with a different Caller.\n//\n// This design allows separate analysis of callers and callees in the\n// golang.org/x/tools/go/analysis framework: the inlining information\n// about a callee can be recorded as a \"fact\".\n//\n// The content should be the actual input to the compiler, not the\n// apparent source file according to any //line directives that\n// may be present within it.\nfunc AnalyzeCallee(logf func(string, ...any), fset *token.FileSet, pkg *types.Package, info *types.Info, decl *ast.FuncDecl, content []byte) (*Callee, error) {\n\tcheckInfoFields(info)\n\n\t// The client is expected to have determined that the callee\n\t// is a function with a declaration (not a built-in or var).\n\tfn := info.Defs[decl.Name].(*types.Func)\n\tsig := fn.Type().(*types.Signature)\n\n\tlogf(\"analyzeCallee %v @ %v\", fn, fset.PositionFor(decl.Pos(), false))\n\n\t// Create user-friendly name (\"pkg.Func\" or \"(pkg.T).Method\")\n\tvar name string\n\tif sig.Recv() == nil {\n\t\tname = fmt.Sprintf(\"%s.%s\", fn.Pkg().Name(), fn.Name())\n\t} else {\n\t\tname = fmt.Sprintf(\"(%s).%s\", types.TypeString(sig.Recv().Type(), (*types.Package).Name), fn.Name())\n\t}\n\n\tif decl.Body == nil {\n\t\treturn nil, fmt.Errorf(\"cannot inline function %s as it has no body\", name)\n\t}\n\n\t// Record the file's Go goVersion so that we don't\n\t// inline newer code into file using an older dialect.\n\t//\n\t// Using the file version is overly conservative.\n\t// A more precise solution would be for the type checker to\n\t// record which language features the callee actually needs;\n\t// see https://go.dev/issue/75726.\n\t//\n\t// We don't have the ast.File handy, so instead of a\n\t// lookup we must scan the entire FileVersions map.\n\tvar goVersion string\n\tfor file, v := range info.FileVersions {\n\t\tif file.Pos() < decl.Pos() && decl.Pos() < file.End() {\n\t\t\tgoVersion = v\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Record the location of all free references in the FuncDecl.\n\t// (Parameters are not free by this definition.)\n\tvar (\n\t\tfieldObjs    = fieldObjs(sig)\n\t\tfreeObjIndex = make(map[types.Object]int)\n\t\tfreeObjs     []object\n\t\tfreeRefs     []freeRef // free refs that may need renaming\n\t\tunexported   []string  // free refs to unexported objects, for later error checks\n\t)\n\tvar f func(n ast.Node, stack []ast.Node) bool\n\tvar stack []ast.Node\n\tstack = append(stack, decl.Type) // for scope of function itself\n\tvisit := func(n ast.Node, stack []ast.Node) { ast.PreorderStack(n, stack, f) }\n\tf = func(n ast.Node, stack []ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.SelectorExpr:\n\t\t\t// Check selections of free fields/methods.\n\t\t\tif sel, ok := info.Selections[n]; ok &&\n\t\t\t\t!within(sel.Obj().Pos(), decl) &&\n\t\t\t\t!n.Sel.IsExported() {\n\t\t\t\tsym := fmt.Sprintf(\"(%s).%s\", info.TypeOf(n.X), n.Sel.Name)\n\t\t\t\tunexported = append(unexported, sym)\n\t\t\t}\n\n\t\t\t// Don't recur into SelectorExpr.Sel.\n\t\t\tvisit(n.X, stack)\n\t\t\treturn false\n\n\t\tcase *ast.CompositeLit:\n\t\t\t// Check for struct literals that refer to unexported fields,\n\t\t\t// whether keyed or unkeyed. (Logic assumes well-typedness.)\n\t\t\tlitType := typeparams.Deref(info.TypeOf(n))\n\t\t\tif s, ok := typeparams.CoreType(litType).(*types.Struct); ok {\n\t\t\t\tif n.Type != nil {\n\t\t\t\t\tvisit(n.Type, stack)\n\t\t\t\t}\n\t\t\t\tfor i, elt := range n.Elts {\n\t\t\t\t\tvar field *types.Var\n\t\t\t\t\tvar value ast.Expr\n\t\t\t\t\tif kv, ok := elt.(*ast.KeyValueExpr); ok {\n\t\t\t\t\t\tfield = info.Uses[kv.Key.(*ast.Ident)].(*types.Var)\n\t\t\t\t\t\tvalue = kv.Value\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfield = s.Field(i)\n\t\t\t\t\t\tvalue = elt\n\t\t\t\t\t}\n\t\t\t\t\tif !within(field.Pos(), decl) && !field.Exported() {\n\t\t\t\t\t\tsym := fmt.Sprintf(\"(%s).%s\", litType, field.Name())\n\t\t\t\t\t\tunexported = append(unexported, sym)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Don't recur into KeyValueExpr.Key.\n\t\t\t\t\tvisit(value, stack)\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\n\t\tcase *ast.Ident:\n\t\t\tif obj, ok := info.Uses[n]; ok {\n\t\t\t\t// Methods and fields are handled by SelectorExpr and CompositeLit.\n\t\t\t\tif isField(obj) || isMethod(obj) {\n\t\t\t\t\tpanic(obj)\n\t\t\t\t}\n\t\t\t\t// Inv: id is a lexical reference.\n\n\t\t\t\t// A reference to an unexported package-level declaration\n\t\t\t\t// cannot be inlined into another package.\n\t\t\t\tif !n.IsExported() &&\n\t\t\t\t\tobj.Pkg() != nil && obj.Parent() == obj.Pkg().Scope() {\n\t\t\t\t\tunexported = append(unexported, n.Name)\n\t\t\t\t}\n\n\t\t\t\t// Record free reference (incl. self-reference).\n\t\t\t\tif obj == fn || !within(obj.Pos(), decl) {\n\t\t\t\t\tobjidx, ok := freeObjIndex[obj]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tobjidx = len(freeObjIndex)\n\t\t\t\t\t\tvar pkgPath, pkgName string\n\t\t\t\t\t\tif pn, ok := obj.(*types.PkgName); ok {\n\t\t\t\t\t\t\tpkgPath = pn.Imported().Path()\n\t\t\t\t\t\t\tpkgName = pn.Imported().Name()\n\t\t\t\t\t\t} else if obj.Pkg() != nil {\n\t\t\t\t\t\t\tpkgPath = obj.Pkg().Path()\n\t\t\t\t\t\t\tpkgName = obj.Pkg().Name()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfreeObjs = append(freeObjs, object{\n\t\t\t\t\t\t\tName:     obj.Name(),\n\t\t\t\t\t\t\tKind:     objectKind(obj),\n\t\t\t\t\t\t\tPkgName:  pkgName,\n\t\t\t\t\t\t\tPkgPath:  pkgPath,\n\t\t\t\t\t\t\tValidPos: obj.Pos().IsValid(),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tfreeObjIndex[obj] = objidx\n\t\t\t\t\t}\n\n\t\t\t\t\tfreeObjs[objidx].Shadow = freeObjs[objidx].Shadow.add(info, fieldObjs, obj.Name(), stack)\n\n\t\t\t\t\tfreeRefs = append(freeRefs, freeRef{\n\t\t\t\t\t\tOffset: int(n.Pos() - decl.Pos()),\n\t\t\t\t\t\tObject: objidx,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\tvisit(decl, stack)\n\n\t// Analyze callee body for \"return expr\" form,\n\t// where expr is f() or <-ch. These forms are\n\t// safe to inline as a standalone statement.\n\tvalidForCallStmt := false\n\tif len(decl.Body.List) != 1 {\n\t\t// not just a return statement\n\t} else if ret, ok := decl.Body.List[0].(*ast.ReturnStmt); ok && len(ret.Results) == 1 {\n\t\tvalidForCallStmt = func() bool {\n\t\t\tswitch expr := ast.Unparen(ret.Results[0]).(type) {\n\t\t\tcase *ast.CallExpr: // f(x)\n\t\t\t\tcallee := typeutil.Callee(info, expr)\n\t\t\t\tif callee == nil {\n\t\t\t\t\treturn false // conversion T(x)\n\t\t\t\t}\n\n\t\t\t\t// The only non-void built-in functions that may be\n\t\t\t\t// called as a statement are copy and recover\n\t\t\t\t// (though arguably a call to recover should never\n\t\t\t\t// be inlined as that changes its behavior).\n\t\t\t\tif builtin, ok := callee.(*types.Builtin); ok {\n\t\t\t\t\treturn builtin.Name() == \"copy\" ||\n\t\t\t\t\t\tbuiltin.Name() == \"recover\"\n\t\t\t\t}\n\n\t\t\t\treturn true // ordinary call f()\n\n\t\t\tcase *ast.UnaryExpr: // <-x\n\t\t\t\treturn expr.Op == token.ARROW // channel receive <-ch\n\t\t\t}\n\n\t\t\t// No other expressions are valid statements.\n\t\t\treturn false\n\t\t}()\n\t}\n\n\t// Record information about control flow in the callee\n\t// (but not any nested functions).\n\tvar (\n\t\thasDefer      = false\n\t\thasBareReturn = false\n\t\treturnInfo    [][]returnOperandFlags\n\t\tlabels        []string\n\t)\n\tast.Inspect(decl.Body, func(n ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncLit:\n\t\t\treturn false // prune traversal\n\t\tcase *ast.DeferStmt:\n\t\t\thasDefer = true\n\t\tcase *ast.LabeledStmt:\n\t\t\tlabels = append(labels, n.Label.Name)\n\t\tcase *ast.ReturnStmt:\n\n\t\t\t// Are implicit assignment conversions\n\t\t\t// to result variables all trivial?\n\t\t\tvar resultInfo []returnOperandFlags\n\t\t\tif len(n.Results) > 0 {\n\t\t\t\targInfo := func(i int) (ast.Expr, types.Type) {\n\t\t\t\t\texpr := n.Results[i]\n\t\t\t\t\treturn expr, info.TypeOf(expr)\n\t\t\t\t}\n\t\t\t\tif len(n.Results) == 1 && sig.Results().Len() > 1 {\n\t\t\t\t\t// Spread return: return f() where f.Results > 1.\n\t\t\t\t\ttuple := info.TypeOf(n.Results[0]).(*types.Tuple)\n\t\t\t\t\targInfo = func(i int) (ast.Expr, types.Type) {\n\t\t\t\t\t\treturn nil, tuple.At(i).Type()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor i := range sig.Results().Len() {\n\t\t\t\t\texpr, typ := argInfo(i)\n\t\t\t\t\tvar flags returnOperandFlags\n\t\t\t\t\tif typ == types.Typ[types.UntypedNil] { // untyped nil is preserved by go/types\n\t\t\t\t\t\tflags |= untypedNilResult\n\t\t\t\t\t}\n\t\t\t\t\tif !trivialConversion(info.Types[expr].Value, typ, sig.Results().At(i).Type()) {\n\t\t\t\t\t\tflags |= nonTrivialResult\n\t\t\t\t\t}\n\t\t\t\t\tresultInfo = append(resultInfo, flags)\n\t\t\t\t}\n\t\t\t} else if sig.Results().Len() > 0 {\n\t\t\t\thasBareReturn = true\n\t\t\t}\n\t\t\treturnInfo = append(returnInfo, resultInfo)\n\t\t}\n\t\treturn true\n\t})\n\n\t// Reject attempts to inline cgo-generated functions.\n\tfor _, obj := range freeObjs {\n\t\t// There are others (iconst fconst sconst fpvar macro)\n\t\t// but this is probably sufficient.\n\t\tif strings.HasPrefix(obj.Name, \"_Cfunc_\") ||\n\t\t\tstrings.HasPrefix(obj.Name, \"_Ctype_\") ||\n\t\t\tstrings.HasPrefix(obj.Name, \"_Cvar_\") {\n\t\t\treturn nil, fmt.Errorf(\"cannot inline cgo-generated functions\")\n\t\t}\n\t}\n\n\t// Compact content to just the FuncDecl.\n\t//\n\t// As a space optimization, we don't retain the complete\n\t// callee file content; all we need is \"package _; func f() { ... }\".\n\t// This reduces the size of analysis facts.\n\t//\n\t// Offsets in the callee information are \"relocatable\"\n\t// since they are all relative to the FuncDecl.\n\n\tcontent = append([]byte(\"package _\\n\"),\n\t\tcontent[offsetOf(fset, decl.Pos()):offsetOf(fset, decl.End())]...)\n\t// Sanity check: re-parse the compacted content.\n\tif _, _, err := parseCompact(content); err != nil {\n\t\treturn nil, err\n\t}\n\n\tparams, results, effects, falcon := analyzeParams(logf, fset, info, decl)\n\ttparams := analyzeTypeParams(logf, fset, info, decl)\n\treturn &Callee{gobCallee{\n\t\tContent:          content,\n\t\tPkgPath:          pkg.Path(),\n\t\tName:             name,\n\t\tGoVersion:        goVersion,\n\t\tUnexported:       unexported,\n\t\tFreeObjs:         freeObjs,\n\t\tFreeRefs:         freeRefs,\n\t\tValidForCallStmt: validForCallStmt,\n\t\tNumResults:       sig.Results().Len(),\n\t\tParams:           params,\n\t\tTypeParams:       tparams,\n\t\tResults:          results,\n\t\tEffects:          effects,\n\t\tHasDefer:         hasDefer,\n\t\tHasBareReturn:    hasBareReturn,\n\t\tReturns:          returnInfo,\n\t\tLabels:           labels,\n\t\tFalcon:           falcon,\n\t}}, nil\n}\n\n// parseCompact parses a Go source file of the form \"package _\\n func f() { ... }\"\n// and returns the sole function declaration.\nfunc parseCompact(content []byte) (*token.FileSet, *ast.FuncDecl, error) {\n\tfset := token.NewFileSet()\n\tconst mode = parser.ParseComments | parser.SkipObjectResolution | parser.AllErrors\n\tf, err := parser.ParseFile(fset, \"callee.go\", content, mode)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"internal error: cannot compact file: %v\", err)\n\t}\n\treturn fset, f.Decls[0].(*ast.FuncDecl), nil\n}\n\n// A paramInfo records information about a callee receiver, parameter, or result variable.\ntype paramInfo struct {\n\tName        string    // parameter name (may be blank, or even \"\")\n\tIndex       int       // index within signature\n\tIsResult    bool      // false for receiver or parameter, true for result variable\n\tIsInterface bool      // parameter has a (non-type parameter) interface type\n\tAssigned    bool      // parameter appears on left side of an assignment statement\n\tEscapes     bool      // parameter has its address taken\n\tRefs        []refInfo // information about references to parameter within body\n\tShadow      shadowMap // shadowing info for the above refs; see [shadowMap]\n\tFalconType  string    // name of this parameter's type (if basic) in the falcon system\n}\n\ntype refInfo struct {\n\tOffset           int  // FuncDecl-relative byte offset of parameter ref within body\n\tAssignable       bool // ref appears in context of assignment to known type\n\tIfaceAssignment  bool // ref is being assigned to an interface\n\tAffectsInference bool // ref type may affect type inference\n\t// IsSelectionOperand indicates whether the parameter reference is the\n\t// operand of a selection (param.f). If so, and param's argument is itself\n\t// a receiver parameter (a common case), we don't need to desugar (&v or *ptr)\n\t// the selection: if param.Method is a valid selection, then so is param.fieldOrMethod.\n\tIsSelectionOperand bool\n}\n\n// analyzeParams computes information about parameters of the function declared by decl,\n// including a simple \"address taken\" escape analysis.\n//\n// It returns two new arrays, one of the receiver and parameters, and\n// the other of the result variables of the function.\n//\n// The input must be well-typed.\nfunc analyzeParams(logf func(string, ...any), fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) (params, results []*paramInfo, effects []int, _ falconResult) {\n\tsig := signature(fset, info, decl)\n\n\tparamInfos := make(map[*types.Var]*paramInfo)\n\t{\n\t\tnewParamInfo := func(param *types.Var, isResult bool) *paramInfo {\n\t\t\tinfo := &paramInfo{\n\t\t\t\tName:        param.Name(),\n\t\t\t\tIsResult:    isResult,\n\t\t\t\tIndex:       len(paramInfos),\n\t\t\t\tIsInterface: isNonTypeParamInterface(param.Type()),\n\t\t\t}\n\t\t\tparamInfos[param] = info\n\t\t\treturn info\n\t\t}\n\t\tif sig.Recv() != nil {\n\t\t\tparams = append(params, newParamInfo(sig.Recv(), false))\n\t\t}\n\t\tfor v := range sig.Params().Variables() {\n\t\t\tparams = append(params, newParamInfo(v, false))\n\t\t}\n\t\tfor v := range sig.Results().Variables() {\n\t\t\tresults = append(results, newParamInfo(v, true))\n\t\t}\n\t}\n\n\t// Search function body for operations &x, x.f(), and x = y\n\t// where x is a parameter, and record it.\n\tescape(info, decl, func(v *types.Var, escapes bool) {\n\t\tif info := paramInfos[v]; info != nil {\n\t\t\tif escapes {\n\t\t\t\tinfo.Escapes = true\n\t\t\t} else {\n\t\t\t\tinfo.Assigned = true\n\t\t\t}\n\t\t}\n\t})\n\n\t// Record locations of all references to parameters.\n\t// And record the set of intervening definitions for each parameter.\n\t//\n\t// TODO(adonovan): combine this traversal with the one that computes\n\t// FreeRefs. The tricky part is that calleefx needs this one first.\n\tfieldObjs := fieldObjs(sig)\n\tvar stack []ast.Node\n\tstack = append(stack, decl.Type) // for scope of function itself\n\tast.PreorderStack(decl.Body, stack, func(n ast.Node, stack []ast.Node) bool {\n\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\tif v, ok := info.Uses[id].(*types.Var); ok {\n\t\t\t\tif pinfo, ok := paramInfos[v]; ok {\n\t\t\t\t\t// Record ref information, and any intervening (shadowing) names.\n\t\t\t\t\t//\n\t\t\t\t\t// If the parameter v has an interface type, and the reference id\n\t\t\t\t\t// appears in a context where assignability rules apply, there may be\n\t\t\t\t\t// an implicit interface-to-interface widening. In that case it is\n\t\t\t\t\t// not necessary to insert an explicit conversion from the argument\n\t\t\t\t\t// to the parameter's type.\n\t\t\t\t\t//\n\t\t\t\t\t// Contrapositively, if param is not an interface type, then the\n\t\t\t\t\t// assignment may lose type information, for example in the case that\n\t\t\t\t\t// the substituted expression is an untyped constant or unnamed type.\n\t\t\t\t\tstack = append(stack, n) // (the two calls below want n)\n\t\t\t\t\tassignable, ifaceAssign, affectsInference := analyzeAssignment(info, stack)\n\t\t\t\t\tref := refInfo{\n\t\t\t\t\t\tOffset:             int(n.Pos() - decl.Pos()),\n\t\t\t\t\t\tAssignable:         assignable,\n\t\t\t\t\t\tIfaceAssignment:    ifaceAssign,\n\t\t\t\t\t\tAffectsInference:   affectsInference,\n\t\t\t\t\t\tIsSelectionOperand: isSelectionOperand(stack),\n\t\t\t\t\t}\n\t\t\t\t\tpinfo.Refs = append(pinfo.Refs, ref)\n\t\t\t\t\tpinfo.Shadow = pinfo.Shadow.add(info, fieldObjs, pinfo.Name, stack)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\t// Compute subset and order of parameters that are strictly evaluated.\n\t// (Depends on Refs computed above.)\n\teffects = calleefx(info, decl.Body, paramInfos)\n\tlogf(\"effects list = %v\", effects)\n\n\tfalcon := falcon(logf, fset, paramInfos, info, decl)\n\n\treturn params, results, effects, falcon\n}\n\n// analyzeTypeParams computes information about the type parameters of the function declared by decl.\nfunc analyzeTypeParams(_ logger, fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) []*paramInfo {\n\tsig := signature(fset, info, decl)\n\tparamInfos := make(map[*types.TypeName]*paramInfo)\n\tvar params []*paramInfo\n\tcollect := func(tpl *types.TypeParamList) {\n\t\tfor tparam := range tpl.TypeParams() {\n\t\t\ttypeName := tparam.Obj()\n\t\t\tinfo := &paramInfo{Name: typeName.Name()}\n\t\t\tparams = append(params, info)\n\t\t\tparamInfos[typeName] = info\n\t\t}\n\t}\n\tcollect(sig.RecvTypeParams())\n\tcollect(sig.TypeParams())\n\n\t// Find references.\n\t// We don't care about most of the properties that matter for parameter references:\n\t// a type is immutable, cannot have its address taken, and does not undergo conversions.\n\t// TODO(jba): can we nevertheless combine this with the traversal in analyzeParams?\n\tvar stack []ast.Node\n\tstack = append(stack, decl.Type) // for scope of function itself\n\tast.PreorderStack(decl.Body, stack, func(n ast.Node, stack []ast.Node) bool {\n\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\tif v, ok := info.Uses[id].(*types.TypeName); ok {\n\t\t\t\tif pinfo, ok := paramInfos[v]; ok {\n\t\t\t\t\tref := refInfo{Offset: int(n.Pos() - decl.Pos())}\n\t\t\t\t\tpinfo.Refs = append(pinfo.Refs, ref)\n\t\t\t\t\tpinfo.Shadow = pinfo.Shadow.add(info, nil, pinfo.Name, stack)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\treturn params\n}\n\nfunc signature(fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) *types.Signature {\n\tfnobj, ok := info.Defs[decl.Name]\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"%s: no func object for %q\",\n\t\t\tfset.PositionFor(decl.Name.Pos(), false), decl.Name)) // ill-typed?\n\t}\n\treturn fnobj.Type().(*types.Signature)\n}\n\n// -- callee helpers --\n\n// analyzeAssignment looks at the given stack, and analyzes certain\n// attributes of the innermost expression.\n//\n// In all cases we 'fail closed' when we cannot detect (or for simplicity\n// choose not to detect) the condition in question, meaning we err on the side\n// of the more restrictive rule. This is noted for each result below.\n//\n//   - assignable reports whether the expression is used in a position where\n//     assignability rules apply, such as in an actual assignment, as call\n//     argument, or in a send to a channel. Defaults to 'false'. If assignable\n//     is false, the other two results are irrelevant.\n//   - ifaceAssign reports whether that assignment is to an interface type.\n//     This is important as we want to preserve the concrete type in that\n//     assignment. Defaults to 'true'. Notably, if the assigned type is a type\n//     parameter, we assume that it could have interface type.\n//   - affectsInference is (somewhat vaguely) defined as whether or not the\n//     type of the operand may affect the type of the surrounding syntax,\n//     through type inference. It is infeasible to completely reverse engineer\n//     type inference, so we over approximate: if the expression is an argument\n//     to a call to a generic function (but not method!) that uses type\n//     parameters, assume that unification of that argument may affect the\n//     inferred types.\nfunc analyzeAssignment(info *types.Info, stack []ast.Node) (assignable, ifaceAssign, affectsInference bool) {\n\tremaining, parent, expr := exprContext(stack)\n\tif parent == nil {\n\t\treturn false, false, false\n\t}\n\n\t// TODO(golang/go#70638): simplify when types.Info records implicit conversions.\n\n\t// Types do not need to match for assignment to a variable.\n\tif assign, ok := parent.(*ast.AssignStmt); ok {\n\t\tfor i, v := range assign.Rhs {\n\t\t\tif v == expr {\n\t\t\t\tif i >= len(assign.Lhs) {\n\t\t\t\t\treturn false, false, false // ill typed\n\t\t\t\t}\n\t\t\t\t// Check to see if the assignment is to an interface type.\n\t\t\t\tif i < len(assign.Lhs) {\n\t\t\t\t\t// TODO: We could handle spread calls here, but in current usage expr\n\t\t\t\t\t// is an ident.\n\t\t\t\t\tif id, _ := assign.Lhs[i].(*ast.Ident); id != nil && info.Defs[id] != nil {\n\t\t\t\t\t\t// Types must match for a defining identifier in a short variable\n\t\t\t\t\t\t// declaration.\n\t\t\t\t\t\treturn false, false, false\n\t\t\t\t\t}\n\t\t\t\t\t// In all other cases, types should be known.\n\t\t\t\t\ttyp := info.TypeOf(assign.Lhs[i])\n\t\t\t\t\treturn true, typ == nil || types.IsInterface(typ), false\n\t\t\t\t}\n\t\t\t\t// Default:\n\t\t\t\treturn assign.Tok == token.ASSIGN, true, false\n\t\t\t}\n\t\t}\n\t}\n\n\t// Types do not need to match for an initializer with known type.\n\tif spec, ok := parent.(*ast.ValueSpec); ok && spec.Type != nil {\n\t\tif slices.Contains(spec.Values, expr) {\n\t\t\ttyp := info.TypeOf(spec.Type)\n\t\t\treturn true, typ == nil || types.IsInterface(typ), false\n\t\t}\n\t}\n\n\t// Types do not need to match for index expressions.\n\tif ix, ok := parent.(*ast.IndexExpr); ok {\n\t\tif ix.Index == expr {\n\t\t\ttyp := info.TypeOf(ix.X)\n\t\t\tif typ == nil {\n\t\t\t\treturn true, true, false\n\t\t\t}\n\t\t\tm, _ := typeparams.CoreType(typ).(*types.Map)\n\t\t\treturn true, m == nil || types.IsInterface(m.Key()), false\n\t\t}\n\t}\n\n\t// Types do not need to match for composite literal keys, values, or\n\t// fields.\n\tif kv, ok := parent.(*ast.KeyValueExpr); ok {\n\t\tvar under types.Type\n\t\tif len(remaining) > 0 {\n\t\t\tif complit, ok := remaining[len(remaining)-1].(*ast.CompositeLit); ok {\n\t\t\t\tif typ := info.TypeOf(complit); typ != nil {\n\t\t\t\t\t// Unpointer to allow for pointers to slices or arrays, which are\n\t\t\t\t\t// permitted as the types of nested composite literals without a type\n\t\t\t\t\t// name.\n\t\t\t\t\tunder = typesinternal.Unpointer(typeparams.CoreType(typ))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif kv.Key == expr { // M{expr: ...}: assign to map key\n\t\t\tm, _ := under.(*types.Map)\n\t\t\treturn true, m == nil || types.IsInterface(m.Key()), false\n\t\t}\n\t\tif kv.Value == expr {\n\t\t\tswitch under := under.(type) {\n\t\t\tcase interface{ Elem() types.Type }: // T{...: expr}: assign to map/array/slice element\n\t\t\t\treturn true, types.IsInterface(under.Elem()), false\n\t\t\tcase *types.Struct: // Struct{k: expr}\n\t\t\t\tif id, _ := kv.Key.(*ast.Ident); id != nil {\n\t\t\t\t\tfor field := range under.Fields() {\n\t\t\t\t\t\tif info.Uses[id] == field {\n\t\t\t\t\t\t\treturn true, types.IsInterface(field.Type()), false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn true, true, false\n\t\t\t}\n\t\t}\n\t}\n\tif lit, ok := parent.(*ast.CompositeLit); ok {\n\t\tfor i, v := range lit.Elts {\n\t\t\tif v == expr {\n\t\t\t\ttyp := info.TypeOf(lit)\n\t\t\t\tif typ == nil {\n\t\t\t\t\treturn true, true, false\n\t\t\t\t}\n\t\t\t\t// As in the KeyValueExpr case above, unpointer to handle pointers to\n\t\t\t\t// array/slice literals.\n\t\t\t\tunder := typesinternal.Unpointer(typeparams.CoreType(typ))\n\t\t\t\tswitch under := under.(type) {\n\t\t\t\tcase interface{ Elem() types.Type }: // T{expr}: assign to map/array/slice element\n\t\t\t\t\treturn true, types.IsInterface(under.Elem()), false\n\t\t\t\tcase *types.Struct: // Struct{expr}: assign to unkeyed struct field\n\t\t\t\t\tif i < under.NumFields() {\n\t\t\t\t\t\treturn true, types.IsInterface(under.Field(i).Type()), false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true, true, false\n\t\t\t}\n\t\t}\n\t}\n\n\t// Types do not need to match for values sent to a channel.\n\tif send, ok := parent.(*ast.SendStmt); ok {\n\t\tif send.Value == expr {\n\t\t\ttyp := info.TypeOf(send.Chan)\n\t\t\tif typ == nil {\n\t\t\t\treturn true, true, false\n\t\t\t}\n\t\t\tch, _ := typeparams.CoreType(typ).(*types.Chan)\n\t\t\treturn true, ch == nil || types.IsInterface(ch.Elem()), false\n\t\t}\n\t}\n\n\t// Types do not need to match for an argument to a call, unless the\n\t// corresponding parameter has type parameters, as in that case the\n\t// argument type may affect inference.\n\tif call, ok := parent.(*ast.CallExpr); ok {\n\t\tif _, ok := isConversion(info, call); ok {\n\t\t\treturn false, false, false // redundant conversions are handled at the call site\n\t\t}\n\t\t// Ordinary call. Could be a call of a func, builtin, or function value.\n\t\tfor i, arg := range call.Args {\n\t\t\tif arg == expr {\n\t\t\t\ttyp := info.TypeOf(call.Fun)\n\t\t\t\tif typ == nil {\n\t\t\t\t\treturn true, true, false\n\t\t\t\t}\n\t\t\t\tsig, _ := typeparams.CoreType(typ).(*types.Signature)\n\t\t\t\tif sig != nil {\n\t\t\t\t\t// Find the relevant parameter type, accounting for variadics.\n\t\t\t\t\tparamType := paramTypeAtIndex(sig, call, i)\n\t\t\t\t\tifaceAssign := paramType == nil || types.IsInterface(paramType)\n\t\t\t\t\taffectsInference := false\n\t\t\t\t\tswitch callee := typeutil.Callee(info, call).(type) {\n\t\t\t\t\tcase *types.Builtin:\n\t\t\t\t\t\t// Consider this litmus test:\n\t\t\t\t\t\t//\n\t\t\t\t\t\t//   func f(x int64) any { return max(x) }\n\t\t\t\t\t\t//   func main() { fmt.Printf(\"%T\", f(42)) }\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// If we lose the implicit conversion from untyped int\n\t\t\t\t\t\t// to int64, the type inferred for the max(x) call changes,\n\t\t\t\t\t\t// resulting in a different dynamic behavior: it prints\n\t\t\t\t\t\t// int, not int64.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Inferred result type affected:\n\t\t\t\t\t\t//    new\n\t\t\t\t\t\t//    complex, real, imag\n\t\t\t\t\t\t//    min, max\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Dynamic behavior change:\n\t\t\t\t\t\t//    append         -- dynamic type of append([]any(nil), x)[0]\n\t\t\t\t\t\t//    delete(m, x)   -- dynamic key type where m is map[any]unit\n\t\t\t\t\t\t//    panic          -- dynamic type of panic value\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Unaffected:\n\t\t\t\t\t\t//    recover\n\t\t\t\t\t\t//    make\n\t\t\t\t\t\t//    len, cap\n\t\t\t\t\t\t//    clear\n\t\t\t\t\t\t//    close\n\t\t\t\t\t\t//    copy\n\t\t\t\t\t\t//    print, println  -- only uses underlying types (?)\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// The dynamic type cases are all covered by\n\t\t\t\t\t\t// the ifaceAssign logic.\n\t\t\t\t\t\tswitch callee.Name() {\n\t\t\t\t\t\tcase \"new\", \"complex\", \"real\", \"imag\", \"min\", \"max\":\n\t\t\t\t\t\t\taffectsInference = true\n\t\t\t\t\t\t}\n\n\t\t\t\t\tcase *types.Func:\n\t\t\t\t\t\t// Only standalone (non-method) functions have type\n\t\t\t\t\t\t// parameters affected by the call arguments.\n\t\t\t\t\t\tif sig2 := callee.Signature(); sig2.Recv() == nil {\n\t\t\t\t\t\t\toriginParamType := paramTypeAtIndex(sig2, call, i)\n\t\t\t\t\t\t\taffectsInference = originParamType == nil || new(typeparams.Free).Has(originParamType)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true, ifaceAssign, affectsInference\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false, false, false\n}\n\n// paramTypeAtIndex returns the effective parameter type at the given argument\n// index in call, if valid.\nfunc paramTypeAtIndex(sig *types.Signature, call *ast.CallExpr, index int) types.Type {\n\tif plen := sig.Params().Len(); sig.Variadic() && index >= plen-1 && !call.Ellipsis.IsValid() {\n\t\tif s, ok := sig.Params().At(plen - 1).Type().(*types.Slice); ok {\n\t\t\treturn s.Elem()\n\t\t}\n\t} else if index < plen {\n\t\treturn sig.Params().At(index).Type()\n\t}\n\treturn nil // ill typed\n}\n\n// exprContext returns the innermost parent->child expression nodes for the\n// given outer-to-inner stack, after stripping parentheses, along with the\n// remaining stack up to the parent node.\n//\n// If no such context exists, returns (nil, nil, nil).\nfunc exprContext(stack []ast.Node) (remaining []ast.Node, parent ast.Node, expr ast.Expr) {\n\texpr, _ = stack[len(stack)-1].(ast.Expr)\n\tif expr == nil {\n\t\treturn nil, nil, nil\n\t}\n\ti := len(stack) - 2\n\tfor ; i >= 0; i-- {\n\t\tif pexpr, ok := stack[i].(*ast.ParenExpr); ok {\n\t\t\texpr = pexpr\n\t\t} else {\n\t\t\tparent = stack[i]\n\t\t\tbreak\n\t\t}\n\t}\n\tif parent == nil {\n\t\treturn nil, nil, nil\n\t}\n\t// inv: i is the index of parent in the stack.\n\treturn stack[:i], parent, expr\n}\n\n// isSelectionOperand reports whether the innermost node of stack is operand\n// (x) of a selection x.f.\nfunc isSelectionOperand(stack []ast.Node) bool {\n\t_, parent, expr := exprContext(stack)\n\tif parent == nil {\n\t\treturn false\n\t}\n\tsel, ok := parent.(*ast.SelectorExpr)\n\treturn ok && sel.X == expr\n}\n\n// A shadowMap records information about shadowing at any of the parameter's\n// references within the callee decl.\n//\n// For each name shadowed at a reference to the parameter within the callee\n// body, shadow map records the 1-based index of the callee decl parameter\n// causing the shadowing, or -1, if the shadowing is not due to a callee decl.\n// A value of zero (or missing) indicates no shadowing. By convention,\n// self-shadowing is excluded from the map.\n//\n// For example, in the following callee\n//\n//\tfunc f(a, b int) int {\n//\t\tc := 2 + b\n//\t\treturn a + c\n//\t}\n//\n// the shadow map of a is {b: 2, c: -1}, because b is shadowed by the 2nd\n// parameter. The shadow map of b is {a: 1}, because c is not shadowed at the\n// use of b.\ntype shadowMap map[string]int\n\n// add returns the [shadowMap] augmented by the set of names\n// locally shadowed at the location of the reference in the callee\n// (identified by the stack). The name of the reference itself is\n// excluded.\n//\n// These shadowed names may not be used in a replacement expression\n// for the reference.\nfunc (s shadowMap) add(info *types.Info, paramIndexes map[types.Object]int, exclude string, stack []ast.Node) shadowMap {\n\tfor _, n := range stack {\n\t\tif scope := scopeFor(info, n); scope != nil {\n\t\t\tfor _, name := range scope.Names() {\n\t\t\t\tif name != exclude {\n\t\t\t\t\tif s == nil {\n\t\t\t\t\t\ts = make(shadowMap)\n\t\t\t\t\t}\n\t\t\t\t\tobj := scope.Lookup(name)\n\t\t\t\t\tif idx, ok := paramIndexes[obj]; ok {\n\t\t\t\t\t\ts[name] = idx + 1\n\t\t\t\t\t} else {\n\t\t\t\t\t\ts[name] = -1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn s\n}\n\n// fieldObjs returns a map of each types.Object defined by the given signature\n// to its index in the parameter list. Parameters with missing or blank name\n// are skipped.\nfunc fieldObjs(sig *types.Signature) map[types.Object]int {\n\tm := make(map[types.Object]int)\n\tfor i := range sig.Params().Len() {\n\t\tif p := sig.Params().At(i); p.Name() != \"\" && p.Name() != \"_\" {\n\t\t\tm[p] = i\n\t\t}\n\t}\n\treturn m\n}\n\nfunc isField(obj types.Object) bool {\n\tif v, ok := obj.(*types.Var); ok && v.IsField() {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc isMethod(obj types.Object) bool {\n\tif f, ok := obj.(*types.Func); ok && f.Type().(*types.Signature).Recv() != nil {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// -- serialization --\n\nvar (\n\t_ gob.GobEncoder = (*Callee)(nil)\n\t_ gob.GobDecoder = (*Callee)(nil)\n)\n\nfunc (callee *Callee) GobEncode() ([]byte, error) {\n\tvar out bytes.Buffer\n\tif err := gob.NewEncoder(&out).Encode(callee.impl); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out.Bytes(), nil\n}\n\nfunc (callee *Callee) GobDecode(data []byte) error {\n\treturn gob.NewDecoder(bytes.NewReader(data)).Decode(&callee.impl)\n}\n"
  },
  {
    "path": "internal/refactor/inline/calleefx.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\n// This file defines the analysis of callee effects.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst (\n\trinf = -1 //  R∞: arbitrary read from memory\n\twinf = -2 //  W∞: arbitrary write to memory (or unknown control)\n)\n\n// calleefx returns a list of parameter indices indicating the order\n// in which parameters are first referenced during evaluation of the\n// callee, relative both to each other and to other effects of the\n// callee (if any), such as arbitrary reads (rinf) and arbitrary\n// effects (winf), including unknown control flow. Each parameter\n// that is referenced appears once in the list.\n//\n// For example, the effects list of this function:\n//\n//\tfunc f(x, y, z int) int {\n//\t    return y + x + g() + z\n//\t}\n//\n// is [1 0 -2 2], indicating reads of y and x, followed by the unknown\n// effects of the g() call, and finally the read of parameter z. This\n// information is used during inlining to ascertain when it is safe\n// for parameter references to be replaced by their corresponding\n// argument expressions. Such substitutions are permitted only when\n// they do not cause \"write\" operations (those with effects) to\n// commute with \"read\" operations (those that have no effect but are\n// not pure). Impure operations may be reordered with other impure\n// operations, and pure operations may be reordered arbitrarily.\n//\n// The analysis ignores the effects of runtime panics, on the\n// assumption that well-behaved programs shouldn't encounter them.\nfunc calleefx(info *types.Info, body *ast.BlockStmt, paramInfos map[*types.Var]*paramInfo) []int {\n\t// This traversal analyzes the callee's statements (in syntax\n\t// form, though one could do better with SSA) to compute the\n\t// sequence of events of the following kinds:\n\t//\n\t// 1  read of a parameter variable.\n\t// 2. reads from other memory.\n\t// 3. writes to memory\n\n\tvar effects []int // indices of parameters, or rinf/winf (-ve)\n\tseen := make(map[int]bool)\n\teffect := func(i int) {\n\t\tif !seen[i] {\n\t\t\tseen[i] = true\n\t\t\teffects = append(effects, i)\n\t\t}\n\t}\n\n\t// unknown is called for statements of unknown effects (or control).\n\tunknown := func() {\n\t\teffect(winf)\n\n\t\t// Ensure that all remaining parameters are \"seen\"\n\t\t// after we go into the unknown (unless they are\n\t\t// unreferenced by the function body). This lets us\n\t\t// not bother implementing the complete traversal into\n\t\t// control structures.\n\t\t//\n\t\t// TODO(adonovan): add them in a deterministic order.\n\t\t// (This is not a bug but determinism is good.)\n\t\tfor _, pinfo := range paramInfos {\n\t\t\tif !pinfo.IsResult && len(pinfo.Refs) > 0 {\n\t\t\t\teffect(pinfo.Index)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar visitExpr func(n ast.Expr)\n\tvar visitStmt func(n ast.Stmt) bool\n\tvisitExpr = func(n ast.Expr) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Ident:\n\t\t\tif v, ok := info.Uses[n].(*types.Var); ok && !v.IsField() {\n\t\t\t\t// Use of global?\n\t\t\t\tif v.Parent() == v.Pkg().Scope() {\n\t\t\t\t\teffect(rinf) // read global var\n\t\t\t\t}\n\n\t\t\t\t// Use of parameter?\n\t\t\t\tif pinfo, ok := paramInfos[v]; ok && !pinfo.IsResult {\n\t\t\t\t\teffect(pinfo.Index) // read parameter var\n\t\t\t\t}\n\n\t\t\t\t// Use of local variables is ok.\n\t\t\t}\n\n\t\tcase *ast.BasicLit:\n\t\t\t// no effect\n\n\t\tcase *ast.FuncLit:\n\t\t\t// A func literal has no read or write effect\n\t\t\t// until called, and (most) function calls are\n\t\t\t// considered to have arbitrary effects.\n\t\t\t// So, no effect.\n\n\t\tcase *ast.CompositeLit:\n\t\t\tfor _, elt := range n.Elts {\n\t\t\t\tvisitExpr(elt) // note: visits KeyValueExpr\n\t\t\t}\n\n\t\tcase *ast.ParenExpr:\n\t\t\tvisitExpr(n.X)\n\n\t\tcase *ast.SelectorExpr:\n\t\t\tif seln, ok := info.Selections[n]; ok {\n\t\t\t\tvisitExpr(n.X)\n\n\t\t\t\t// See types.SelectionKind for background.\n\t\t\t\tswitch seln.Kind() {\n\t\t\t\tcase types.MethodExpr:\n\t\t\t\t\t// A method expression T.f acts like a\n\t\t\t\t\t// reference to a func decl,\n\t\t\t\t\t// so it doesn't read x until called.\n\n\t\t\t\tcase types.MethodVal, types.FieldVal:\n\t\t\t\t\t// A field or method value selection x.f\n\t\t\t\t\t// reads x if the selection indirects a pointer.\n\n\t\t\t\t\tif indirectSelection(seln) {\n\t\t\t\t\t\teffect(rinf)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// qualified identifier: treat like unqualified\n\t\t\t\tvisitExpr(n.Sel)\n\t\t\t}\n\n\t\tcase *ast.IndexExpr:\n\t\t\tif tv := info.Types[n.Index]; tv.IsType() {\n\t\t\t\t// no effect (G[T] instantiation)\n\t\t\t} else {\n\t\t\t\tvisitExpr(n.X)\n\t\t\t\tvisitExpr(n.Index)\n\t\t\t\tswitch tv.Type.Underlying().(type) {\n\t\t\t\tcase *types.Slice, *types.Pointer: // []T, *[n]T (not string, [n]T)\n\t\t\t\t\teffect(rinf) // indirect read of slice/array element\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.IndexListExpr:\n\t\t\t// no effect (M[K,V] instantiation)\n\n\t\tcase *ast.SliceExpr:\n\t\t\tvisitExpr(n.X)\n\t\t\tvisitExpr(n.Low)\n\t\t\tvisitExpr(n.High)\n\t\t\tvisitExpr(n.Max)\n\n\t\tcase *ast.TypeAssertExpr:\n\t\t\tvisitExpr(n.X)\n\n\t\tcase *ast.CallExpr:\n\t\t\tif info.Types[n.Fun].IsType() {\n\t\t\t\t// conversion T(x)\n\t\t\t\tvisitExpr(n.Args[0])\n\t\t\t} else {\n\t\t\t\t// call f(args)\n\t\t\t\tvisitExpr(n.Fun)\n\t\t\t\tfor i, arg := range n.Args {\n\t\t\t\t\tif i == 0 && info.Types[arg].IsType() {\n\t\t\t\t\t\tcontinue // new(T), make(T, n)\n\t\t\t\t\t}\n\t\t\t\t\tvisitExpr(arg)\n\t\t\t\t}\n\n\t\t\t\t// The pure built-ins have no effects beyond\n\t\t\t\t// those of their operands (not even memory reads).\n\t\t\t\t// All other calls have unknown effects.\n\t\t\t\tif !typesinternal.CallsPureBuiltin(info, n) {\n\t\t\t\t\tunknown() // arbitrary effects\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.StarExpr:\n\t\t\tvisitExpr(n.X)\n\t\t\teffect(rinf) // *ptr load or store depends on state of heap\n\n\t\tcase *ast.UnaryExpr: // + - ! ^ & ~ <-\n\t\t\tvisitExpr(n.X)\n\t\t\tif n.Op == token.ARROW {\n\t\t\t\tunknown() // effect: channel receive\n\t\t\t}\n\n\t\tcase *ast.BinaryExpr:\n\t\t\tvisitExpr(n.X)\n\t\t\tvisitExpr(n.Y)\n\n\t\tcase *ast.KeyValueExpr:\n\t\t\tvisitExpr(n.Key) // may be a struct field\n\t\t\tvisitExpr(n.Value)\n\n\t\tcase *ast.BadExpr:\n\t\t\t// no effect\n\n\t\tcase nil:\n\t\t\t// optional subtree\n\n\t\tdefault:\n\t\t\t// type syntax: unreachable given traversal\n\t\t\tpanic(n)\n\t\t}\n\t}\n\n\t// visitStmt's result indicates the continuation:\n\t// false for return, true for the next statement.\n\t//\n\t// We could treat return as an unknown, but this way\n\t// yields definite effects for simple sequences like\n\t// {S1; S2; return}, so unreferenced parameters are\n\t// not spuriously added to the effects list, and thus\n\t// not spuriously disqualified from elimination.\n\tvisitStmt = func(n ast.Stmt) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.DeclStmt:\n\t\t\tdecl := n.Decl.(*ast.GenDecl)\n\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, v := range spec.Values {\n\t\t\t\t\t\tvisitExpr(v)\n\t\t\t\t\t}\n\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\t// no effect\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.LabeledStmt:\n\t\t\treturn visitStmt(n.Stmt)\n\n\t\tcase *ast.ExprStmt:\n\t\t\tvisitExpr(n.X)\n\n\t\tcase *ast.SendStmt:\n\t\t\tvisitExpr(n.Chan)\n\t\t\tvisitExpr(n.Value)\n\t\t\tunknown() // effect: channel send\n\n\t\tcase *ast.IncDecStmt:\n\t\t\tvisitExpr(n.X)\n\t\t\tunknown() // effect: variable increment\n\n\t\tcase *ast.AssignStmt:\n\t\t\tfor _, lhs := range n.Lhs {\n\t\t\t\tvisitExpr(lhs)\n\t\t\t}\n\t\t\tfor _, rhs := range n.Rhs {\n\t\t\t\tvisitExpr(rhs)\n\t\t\t}\n\t\t\tfor _, lhs := range n.Lhs {\n\t\t\t\tid, _ := lhs.(*ast.Ident)\n\t\t\t\tif id != nil && id.Name == \"_\" {\n\t\t\t\t\tcontinue // blank assign has no effect\n\t\t\t\t}\n\t\t\t\tif n.Tok == token.DEFINE && id != nil && info.Defs[id] != nil {\n\t\t\t\t\tcontinue // new var declared by := has no effect\n\t\t\t\t}\n\t\t\t\tunknown() // assignment to existing var\n\t\t\t\tbreak\n\t\t\t}\n\n\t\tcase *ast.GoStmt:\n\t\t\tvisitExpr(n.Call.Fun)\n\t\t\tfor _, arg := range n.Call.Args {\n\t\t\t\tvisitExpr(arg)\n\t\t\t}\n\t\t\tunknown() // effect: create goroutine\n\n\t\tcase *ast.DeferStmt:\n\t\t\tvisitExpr(n.Call.Fun)\n\t\t\tfor _, arg := range n.Call.Args {\n\t\t\t\tvisitExpr(arg)\n\t\t\t}\n\t\t\tunknown() // effect: push defer\n\n\t\tcase *ast.ReturnStmt:\n\t\t\tfor _, res := range n.Results {\n\t\t\t\tvisitExpr(res)\n\t\t\t}\n\t\t\treturn false\n\n\t\tcase *ast.BlockStmt:\n\t\t\tfor _, stmt := range n.List {\n\t\t\t\tif !visitStmt(stmt) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.BranchStmt:\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.IfStmt:\n\t\t\tvisitStmt(n.Init)\n\t\t\tvisitExpr(n.Cond)\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.SwitchStmt:\n\t\t\tvisitStmt(n.Init)\n\t\t\tvisitExpr(n.Tag)\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.TypeSwitchStmt:\n\t\t\tvisitStmt(n.Init)\n\t\t\tvisitStmt(n.Assign)\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.SelectStmt:\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.ForStmt:\n\t\t\tvisitStmt(n.Init)\n\t\t\tvisitExpr(n.Cond)\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.RangeStmt:\n\t\t\tvisitExpr(n.X)\n\t\t\tunknown() // control flow\n\n\t\tcase *ast.EmptyStmt, *ast.BadStmt:\n\t\t\t// no effect\n\n\t\tcase nil:\n\t\t\t// optional subtree\n\n\t\tdefault:\n\t\t\tpanic(n)\n\t\t}\n\t\treturn true\n\t}\n\tvisitStmt(body)\n\n\treturn effects\n}\n"
  },
  {
    "path": "internal/refactor/inline/calleefx_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/refactor/inline\"\n)\n\n// TestCalleeEffects is a unit test of the calleefx analysis.\nfunc TestCalleeEffects(t *testing.T) {\n\t// Each callee must declare a function or method named f.\n\tconst funcName = \"f\"\n\n\tvar tests = []struct {\n\t\tdescr  string\n\t\tcallee string // Go source file (sans package decl) containing callee decl\n\t\twant   string // expected effects string (-1=R∞ -2=W∞)\n\t}{\n\t\t{\n\t\t\t\"Assignments have unknown effects.\",\n\t\t\t`func f(x, y int) { x = y }`,\n\t\t\t`[0 1 -2]`,\n\t\t},\n\t\t{\n\t\t\t\"Reads from globals are impure.\",\n\t\t\t`func f() { _ = g }; var g int`,\n\t\t\t`[-1]`,\n\t\t},\n\t\t{\n\t\t\t\"Writes to globals have effects.\",\n\t\t\t`func f() { g = 0 }; var g int`,\n\t\t\t`[-1 -2]`, // the -1 is spurious but benign\n\t\t},\n\t\t{\n\t\t\t\"Blank assign has no effect.\",\n\t\t\t`func f(x int) { _ = x }`,\n\t\t\t`[0]`,\n\t\t},\n\t\t{\n\t\t\t\"Short decl of new var has has no effect.\",\n\t\t\t`func f(x int) { y := x; _ = y }`,\n\t\t\t`[0]`,\n\t\t},\n\t\t{\n\t\t\t\"Short decl of existing var (y) is an assignment.\",\n\t\t\t`func f(x int) { y := x; y, z := 1, 2; _, _ = y, z }`,\n\t\t\t`[0 -2]`,\n\t\t},\n\t\t{\n\t\t\t\"Unreferenced parameters are excluded.\",\n\t\t\t`func f(x, y, z int) { _ = z + x }`,\n\t\t\t`[2 0]`,\n\t\t},\n\t\t{\n\t\t\t\"Built-in len has no effect.\",\n\t\t\t`func f(x, y string) { _ = len(y) + len(x) }`,\n\t\t\t`[1 0]`,\n\t\t},\n\t\t{\n\t\t\t\"Built-in println has effects.\",\n\t\t\t`func f(x, y int) { println(y, x) }`,\n\t\t\t`[1 0 -2]`,\n\t\t},\n\t\t{\n\t\t\t\"Return has no effect, and no control successor.\",\n\t\t\t`func f(x, y int) int { return x + y; panic(1) }`,\n\t\t\t`[0 1]`,\n\t\t},\n\t\t{\n\t\t\t\"Loops (etc) have unknown effects.\",\n\t\t\t`func f(x, y bool) { for x { _ = y } }`,\n\t\t\t`[0 -2 1]`,\n\t\t},\n\t\t{\n\t\t\t\"Calls have unknown effects.\",\n\t\t\t`func f(x, y int) { _, _, _ = x, g(), y }; func g() int`,\n\t\t\t`[0 -2 1]`,\n\t\t},\n\t\t{\n\t\t\t\"Calls to some built-ins are pure.\",\n\t\t\t`func f(x, y int) { _, _, _ = x, len(\"hi\"), y }`,\n\t\t\t`[0 1]`,\n\t\t},\n\t\t{\n\t\t\t\"Calls to some built-ins are pure (variant).\",\n\t\t\t`func f(x, y int) { s := \"hi\"; _, _, _ = x, len(s), y; s = \"bye\" }`,\n\t\t\t`[0 1 -2]`,\n\t\t},\n\t\t{\n\t\t\t\"Calls to some built-ins are pure (another variants).\",\n\t\t\t`func f(x, y int) { s := \"hi\"; _, _, _ = x, len(s), y }`,\n\t\t\t`[0 1]`,\n\t\t},\n\t\t{\n\t\t\t\"Reading a local var is impure but does not have effects.\",\n\t\t\t`func f(x, y bool) { for x { _ = y } }`,\n\t\t\t`[0 -2 1]`,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.descr, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tmustParse := func(filename string, content any) *ast.File {\n\t\t\t\tf, err := parser.ParseFile(fset, filename, content, parser.ParseComments|parser.SkipObjectResolution)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"ParseFile: %v\", err)\n\t\t\t\t}\n\t\t\t\treturn f\n\t\t\t}\n\n\t\t\t// Parse callee file and find first func decl named f.\n\t\t\tcalleeContent := \"package p\\n\" + test.callee\n\t\t\tcalleeFile := mustParse(\"callee.go\", calleeContent)\n\t\t\tvar decl *ast.FuncDecl\n\t\t\tfor _, d := range calleeFile.Decls {\n\t\t\t\tif d, ok := d.(*ast.FuncDecl); ok && d.Name.Name == funcName {\n\t\t\t\t\tdecl = d\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif decl == nil {\n\t\t\t\tt.Fatalf(\"declaration of func %s not found: %s\", funcName, test.callee)\n\t\t\t}\n\n\t\t\tinfo := &types.Info{\n\t\t\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\t\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\t\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\t\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\t\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\t\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t\t}\n\t\t\tconf := &types.Config{Error: func(err error) { t.Error(err) }}\n\t\t\tpkg, err := conf.Check(\"p\", fset, []*ast.File{calleeFile}, info)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tcallee, err := inline.AnalyzeCallee(t.Logf, fset, pkg, info, decl, []byte(calleeContent))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif got := fmt.Sprint(callee.Effects()); got != test.want {\n\t\t\t\tt.Errorf(\"for effects of %s, got %s want %s\",\n\t\t\t\t\ttest.callee, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/refactor/inline/doc.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage inline implements inlining of Go function calls.\n\nThe client provides information about the caller and callee,\nincluding the source text, syntax tree, and type information, and\nthe inliner returns the modified source file for the caller, or an\nerror if the inlining operation is invalid (for example because the\nfunction body refers to names that are inaccessible to the caller).\n\nAlthough this interface demands more information from the client\nthan might seem necessary, it enables smoother integration with\nexisting batch and interactive tools that have their own ways of\nmanaging the processes of reading, parsing, and type-checking\npackages. In particular, this package does not assume that the\ncaller and callee belong to the same token.FileSet or\ntypes.Importer realms.\n\nThere are many aspects to a function call. It is the only construct\nthat can simultaneously bind multiple variables of different\nexplicit types, with implicit assignment conversions. (Neither var\nnor := declarations can do that.) It defines the scope of control\nlabels, of return statements, and of defer statements. Arguments\nand results of function calls may be tuples even though tuples are\nnot first-class values in Go, and a tuple-valued call expression\nmay be \"spread\" across the argument list of a call or the operands\nof a return statement. All these unique features mean that in the\ngeneral case, not everything that can be expressed by a function\ncall can be expressed without one.\n\nSo, in general, inlining consists of modifying a function or method\ncall expression f(a1, ..., an) so that the name of the function f\nis replaced (\"literalized\") by a literal copy of the function\ndeclaration, with free identifiers suitably modified to use the\nlocally appropriate identifiers or perhaps constant argument\nvalues.\n\nInlining must not change the semantics of the call. Semantics\npreservation is crucial for clients such as codebase maintenance\ntools that automatically inline all calls to designated functions\non a large scale. Such tools must not introduce subtle behavior\nchanges. (Fully inlining a call is dynamically observable using\nreflection over the call stack, but this exception to the rule is\nexplicitly allowed.)\n\nIn many cases it is possible to entirely replace (\"reduce\") the\ncall by a copy of the function's body in which parameters have been\nreplaced by arguments. The inliner supports a number of reduction\nstrategies, and we expect this set to grow. Nonetheless, sound\nreduction is surprisingly tricky.\n\nThe inliner is in some ways like an optimizing compiler. A compiler\nis considered correct if it doesn't change the meaning of the\nprogram in translation from source language to target language. An\noptimizing compiler exploits the particulars of the input to\ngenerate better code, where \"better\" usually means more efficient.\nWhen a case is found in which it emits suboptimal code, the\ncompiler is improved to recognize more cases, or more rules, and\nmore exceptions to rules; this process has no end. Inlining is\nsimilar except that \"better\" code means tidier code. The baseline\ntranslation (literalization) is correct, but there are endless\nrules--and exceptions to rules--by which the output can be\nimproved.\n\nThe following section lists some of the challenges, and ways in\nwhich they can be addressed.\n\n  - All effects of the call argument expressions must be preserved,\n    both in their number (they must not be eliminated or repeated),\n    and in their order (both with respect to other arguments, and any\n    effects in the callee function).\n\n    This must be the case even if the corresponding parameters are\n    never referenced, are referenced multiple times, referenced in\n    a different order from the arguments, or referenced within a\n    nested function that may be executed an arbitrary number of\n    times.\n\n    Currently, parameter replacement is not applied to arguments\n    with effects, but with further analysis of the sequence of\n    strict effects within the callee we could relax this constraint.\n\n  - When not all parameters can be substituted by their arguments\n    (e.g. due to possible effects), if the call appears in a\n    statement context, the inliner may introduce a var declaration\n    that declares the parameter variables (with the correct types)\n    and assigns them to their corresponding argument values.\n    The rest of the function body may then follow.\n    For example, the call\n\n    f(1, 2)\n\n    to the function\n\n    func f(x, y int32) { stmts }\n\n    may be reduced to\n\n    { var x, y int32 = 1, 2; stmts }.\n\n    There are many reasons why this is not always possible. For\n    example, true parameters are statically resolved in the same\n    scope, and are dynamically assigned their arguments in\n    parallel; but each spec in a var declaration is statically\n    resolved in sequence and dynamically executed in sequence, so\n    earlier parameters may shadow references in later ones.\n\n  - Even an argument expression as simple as ptr.x may not be\n    referentially transparent, because another argument may have the\n    effect of changing the value of ptr.\n\n    This constraint could be relaxed by some kind of alias or\n    escape analysis that proves that ptr cannot be mutated during\n    the call.\n\n  - Although constants are referentially transparent, as a matter of\n    style we do not wish to duplicate literals that are referenced\n    multiple times in the body because this undoes proper factoring.\n    Also, string literals may be arbitrarily large.\n\n  - If the function body consists of statements other than just\n    \"return expr\", in some contexts it may be syntactically\n    impossible to reduce the call. Consider:\n\n    if x := f(); cond { ... }\n\n    Go has no equivalent to Lisp's progn or Rust's blocks,\n    nor ML's let expressions (let param = arg in body);\n    its closest equivalent is func(param){body}(arg).\n    Reduction strategies must therefore consider the syntactic\n    context of the call.\n\n    In such situations we could work harder to extract a statement\n    context for the call, by transforming it to:\n\n    { x := f(); if cond { ... } }\n\n  - Similarly, without the equivalent of Rust-style blocks and\n    first-class tuples, there is no general way to reduce a call\n    to a function such as\n\n    func(params)(args)(results) { stmts; return expr }\n\n    to an expression such as\n\n    { var params = args; stmts; expr }\n\n    or even a statement such as\n\n    results = { var params = args; stmts; expr }\n\n    Consequently the declaration and scope of the result variables,\n    and the assignment and control-flow implications of the return\n    statement, must be dealt with by cases.\n\n  - A standalone call statement that calls a function whose body is\n    \"return expr\" cannot be simply replaced by the body expression\n    if it is not itself a call or channel receive expression; it is\n    necessary to explicitly discard the result using \"_ = expr\".\n\n    Similarly, if the body is a call expression, only calls to some\n    built-in functions with no result (such as copy or panic) are\n    permitted as statements, whereas others (such as append) return\n    a result that must be used, even if just by discarding.\n\n  - If a parameter or result variable is updated by an assignment\n    within the function body, it cannot always be safely replaced\n    by a variable in the caller. For example, given\n\n    func f(a int) int { a++; return a }\n\n    The call y = f(x) cannot be replaced by { x++; y = x } because\n    this would change the value of the caller's variable x.\n    Only if the caller is finished with x is this safe.\n\n    A similar argument applies to parameter or result variables\n    that escape: by eliminating a variable, inlining would change\n    the identity of the variable that escapes.\n\n  - If the function body uses 'defer' and the inlined call is not a\n    tail-call, inlining may delay the deferred effects.\n\n  - Because the scope of a control label is the entire function, a\n    call cannot be reduced if the caller and callee have intersecting\n    sets of control labels. (It is possible to α-rename any\n    conflicting ones, but our colleagues building C++ refactoring\n    tools report that, when tools must choose new identifiers, they\n    generally do a poor job.)\n\n  - Given\n\n    func f() uint8 { return 0 }\n\n    var x any = f()\n\n    reducing the call to var x any = 0 is unsound because it\n    discards the implicit conversion to uint8. We may need to make\n    each argument-to-parameter conversion explicit if the types\n    differ. Assignments to variadic parameters may need to\n    explicitly construct a slice.\n\n    An analogous problem applies to the implicit assignments in\n    return statements:\n\n    func g() any { return f() }\n\n    Replacing the call f() with 0 would silently lose a\n    conversion to uint8 and change the behavior of the program.\n\n  - When inlining a call f(1, x, g()) where those parameters are\n    unreferenced, we should be able to avoid evaluating 1 and x\n    since they are pure and thus have no effect. But x may be the\n    last reference to a local variable in the caller, so removing\n    it would cause a compilation error. Parameter substitution must\n    avoid making the caller's local variables unreferenced (or must\n    be prepared to eliminate the declaration too---this is where an\n    iterative framework for simplification would really help).\n\n  - An expression such as s[i] may be valid if s and i are\n    variables but invalid if either or both of them are constants.\n    For example, a negative constant index s[-1] is always out of\n    bounds, and even a non-negative constant index may be out of\n    bounds depending on the particular string constant (e.g.\n    \"abc\"[4]).\n\n    So, if a parameter participates in any expression that is\n    subject to additional compile-time checks when its operands are\n    constant, it may be unsafe to substitute that parameter by a\n    constant argument value (#62664).\n\nMore complex callee functions are inlinable with more elaborate and\ninvasive changes to the statements surrounding the call expression.\n\nTODO(adonovan): future work:\n\n  - Handle more of the above special cases by careful analysis,\n    thoughtful factoring of the large design space, and thorough\n    test coverage.\n\n  - Compute precisely (not conservatively) when parameter\n    substitution would remove the last reference to a caller local\n    variable, and blank out the local instead of retreating from\n    the substitution.\n\n  - Afford the client more control such as a limit on the total\n    increase in line count, or a refusal to inline using the\n    general approach (replacing name by function literal). This\n    could be achieved by returning metadata alongside the result\n    and having the client conditionally discard the change.\n\n  - Support inlining of generic functions, replacing type parameters\n    by their instantiations.\n\n  - Support inlining of calls to function literals (\"closures\").\n    But note that the existing algorithm makes widespread assumptions\n    that the callee is a package-level function or method.\n\n  - Eliminate explicit conversions of \"untyped\" literals inserted\n    conservatively when they are redundant. For example, the\n    conversion int32(1) is redundant when this value is used only as a\n    slice index; but it may be crucial if it is used in x := int32(1)\n    as it changes the type of x, which may have further implications.\n    The conversions may also be important to the falcon analysis.\n\n  - Allow non-'go' build systems such as Bazel/Blaze a chance to\n    decide whether an import is accessible using logic other than\n    \"/internal/\" path segments. This could be achieved by returning\n    the list of added import paths instead of a text diff.\n\n  - Inlining a function from another module may change the\n    effective version of the Go language spec that governs it. We\n    should probably make the client responsible for rejecting\n    attempts to inline from newer callees to older callers, since\n    there's no way for this package to access module versions.\n\n  - Use an alternative implementation of the import-organizing\n    operation that doesn't require operating on a complete file\n    (and reformatting). Then return the results in a higher-level\n    form as a set of import additions and deletions plus a single\n    diff that encloses the call expression. This interface could\n    perhaps be implemented atop imports.Process by post-processing\n    its result to obtain the abstract import changes and discarding\n    its formatted output.\n*/\npackage inline\n"
  },
  {
    "path": "internal/refactor/inline/escape.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// escape implements a simple \"address-taken\" escape analysis. It\n// calls f for each local variable that appears on the left side of an\n// assignment (escapes=false) or has its address taken (escapes=true).\n// The initialization of a variable by its declaration does not count\n// as an assignment.\nfunc escape(info *types.Info, root ast.Node, f func(v *types.Var, escapes bool)) {\n\n\t// lvalue is called for each address-taken expression or LHS of assignment.\n\t// Supported forms are: x, (x), x[i], x.f, *x, T{}.\n\tvar lvalue func(e ast.Expr, escapes bool)\n\tlvalue = func(e ast.Expr, escapes bool) {\n\t\tswitch e := e.(type) {\n\t\tcase *ast.Ident:\n\t\t\tif v, ok := info.Uses[e].(*types.Var); ok {\n\t\t\t\tif !isPkgLevel(v) {\n\t\t\t\t\tf(v, escapes)\n\t\t\t\t}\n\t\t\t}\n\t\tcase *ast.ParenExpr:\n\t\t\tlvalue(e.X, escapes)\n\t\tcase *ast.IndexExpr:\n\t\t\t// TODO(adonovan): support generics without assuming e.X has a core type.\n\t\t\t// Consider:\n\t\t\t//\n\t\t\t// func Index[T interface{ [3]int | []int }](t T, i int) *int {\n\t\t\t//     return &t[i]\n\t\t\t// }\n\t\t\t//\n\t\t\t// We must traverse the normal terms and check\n\t\t\t// whether any of them is an array.\n\t\t\t//\n\t\t\t// We assume TypeOf returns non-nil.\n\t\t\tif _, ok := info.TypeOf(e.X).Underlying().(*types.Array); ok {\n\t\t\t\tlvalue(e.X, escapes) // &a[i] on array\n\t\t\t}\n\t\tcase *ast.SelectorExpr:\n\t\t\t// We assume TypeOf returns non-nil.\n\t\t\tif _, ok := info.TypeOf(e.X).Underlying().(*types.Struct); ok {\n\t\t\t\tlvalue(e.X, escapes) // &s.f on struct\n\t\t\t}\n\t\tcase *ast.StarExpr:\n\t\t\t// *ptr indirects an existing pointer\n\t\tcase *ast.CompositeLit:\n\t\t\t// &T{...} creates a new variable\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"&x on %T\", e)) // unreachable in well-typed code\n\t\t}\n\t}\n\n\t// Search function body for operations &x, x.f(), x++, and x = y\n\t// where x is a parameter. Each of these treats x as an address.\n\tast.Inspect(root, func(n ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.UnaryExpr:\n\t\t\tif n.Op == token.AND {\n\t\t\t\tlvalue(n.X, true) // &x\n\t\t\t}\n\n\t\tcase *ast.CallExpr:\n\t\t\t// implicit &x in method call x.f(),\n\t\t\t// where x has type T and method is (*T).f\n\t\t\tif sel, ok := n.Fun.(*ast.SelectorExpr); ok {\n\t\t\t\tif seln, ok := info.Selections[sel]; ok &&\n\t\t\t\t\tseln.Kind() == types.MethodVal &&\n\t\t\t\t\tisPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type()) {\n\t\t\t\t\ttArg, indirect := effectiveReceiver(seln)\n\t\t\t\t\tif !indirect && !isPointer(tArg) {\n\t\t\t\t\t\tlvalue(sel.X, true) // &x.f\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.AssignStmt:\n\t\t\tfor _, lhs := range n.Lhs {\n\t\t\t\tif id, ok := lhs.(*ast.Ident); ok &&\n\t\t\t\t\tinfo.Defs[id] != nil &&\n\t\t\t\t\tn.Tok == token.DEFINE {\n\t\t\t\t\t// declaration: doesn't count\n\t\t\t\t} else {\n\t\t\t\t\tlvalue(lhs, false)\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.IncDecStmt:\n\t\t\tlvalue(n.X, false)\n\t\t}\n\t\treturn true\n\t})\n}\n"
  },
  {
    "path": "internal/refactor/inline/everything_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline_test\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nvar packagesFlag = flag.String(\"packages\", \"\", \"set of packages for TestEverything\")\n\n// TestEverything invokes the inliner on every single call site in a\n// given package. and checks that it produces either a reasonable\n// error, or output that parses and type-checks.\n//\n// It does nothing during ordinary testing, but may be used to find\n// inlining bugs in large corpora.\n//\n// Use this command to inline everything in golang.org/x/tools:\n//\n// $ go test ./internal/refactor/inline/ -run=Everything -packages=../../../\n//\n// And these commands to inline everything in the kubernetes repository:\n//\n// $ go test -c -o /tmp/everything ./internal/refactor/inline/\n// $ (cd kubernetes && /tmp/everything -test.run=Everything -packages=./...)\n//\n// TODO(adonovan):\n//   - report counters (number of attempts, failed AnalyzeCallee, failed\n//     Inline, etc.)\n//   - Make a pretty log of the entire output so that we can peruse it\n//     for opportunities for systematic improvement.\nfunc TestEverything(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tif testing.Short() {\n\t\tt.Skipf(\"skipping slow test in -short mode\")\n\t}\n\tif *packagesFlag == \"\" {\n\t\treturn\n\t}\n\n\t// Load this package plus dependencies from typed syntax.\n\tcfg := &packages.Config{\n\t\tMode: packages.LoadAllSyntax,\n\t\tEnv: append(os.Environ(),\n\t\t\t\"GO111MODULES=on\",\n\t\t\t\"GOPATH=\",\n\t\t\t\"GOWORK=off\",\n\t\t\t\"GOPROXY=off\"),\n\t}\n\tpkgs, err := packages.Load(cfg, *packagesFlag)\n\tif err != nil {\n\t\tt.Errorf(\"Load: %v\", err)\n\t}\n\t// Report parse/type errors.\n\t// Also, build transitive dependency mapping.\n\tdeps := make(map[string]*packages.Package) // key is PkgPath\n\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\tdeps[pkg.Types.Path()] = pkg\n\t\tfor _, err := range pkg.Errors {\n\t\t\tt.Fatal(err)\n\t\t}\n\t})\n\n\t// Memoize repeated calls for same file.\n\tfileContent := make(map[string][]byte)\n\treadFile := func(filename string) ([]byte, error) {\n\t\tcontent, ok := fileContent[filename]\n\t\tif !ok {\n\t\t\tvar err error\n\t\t\tcontent, err = os.ReadFile(filename)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tfileContent[filename] = content\n\t\t}\n\t\treturn content, nil\n\t}\n\n\tfor _, callerPkg := range pkgs {\n\t\t// Find all static function calls in the package.\n\t\tfor _, callerFile := range callerPkg.Syntax {\n\t\t\tnoMutCheck := checkNoMutation(callerFile)\n\t\t\tast.Inspect(callerFile, func(n ast.Node) bool {\n\t\t\t\tcall, ok := n.(*ast.CallExpr)\n\t\t\t\tif !ok {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tfn := typeutil.StaticCallee(callerPkg.TypesInfo, call)\n\t\t\t\tif fn == nil {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\t// Prepare caller info.\n\t\t\t\tcallPosn := callerPkg.Fset.PositionFor(call.Lparen, false)\n\t\t\t\tcallerContent, err := readFile(callPosn.Filename)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tcaller := &inline.Caller{\n\t\t\t\t\tFset:  callerPkg.Fset,\n\t\t\t\t\tTypes: callerPkg.Types,\n\t\t\t\t\tInfo:  callerPkg.TypesInfo,\n\t\t\t\t\tFile:  callerFile,\n\t\t\t\t\tCall:  call,\n\t\t\t\t}\n\n\t\t\t\t// Analyze callee.\n\t\t\t\tcalleePkg, ok := deps[fn.Pkg().Path()]\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Fatalf(\"missing package for callee %v\", fn)\n\t\t\t\t}\n\t\t\t\tcalleePosn := callerPkg.Fset.PositionFor(fn.Pos(), false)\n\t\t\t\tcalleeDecl, err := findFuncByPosition(calleePkg, calleePosn)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tcalleeContent, err := readFile(calleePosn.Filename)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\t// Create a subtest for each inlining operation.\n\t\t\t\tname := fmt.Sprintf(\"%s@%v\", fn.Name(), filepath.Base(callPosn.String()))\n\t\t\t\tt.Run(name, func(t *testing.T) {\n\t\t\t\t\t// TODO(adonovan): add a panic handler.\n\n\t\t\t\t\tt.Logf(\"callee declared at %v\",\n\t\t\t\t\t\tfilepath.Base(calleePosn.String()))\n\n\t\t\t\t\tt.Logf(\"run this command to reproduce locally:\\n$ gopls codeaction -kind=refactor.inline -exec -diff %s:#%d\",\n\t\t\t\t\t\tcallPosn.Filename, callPosn.Offset)\n\n\t\t\t\t\tcallee, err := inline.AnalyzeCallee(\n\t\t\t\t\t\tt.Logf,\n\t\t\t\t\t\tcalleePkg.Fset,\n\t\t\t\t\t\tcalleePkg.Types,\n\t\t\t\t\t\tcalleePkg.TypesInfo,\n\t\t\t\t\t\tcalleeDecl,\n\t\t\t\t\t\tcalleeContent)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t// Ignore the expected kinds of errors.\n\t\t\t\t\t\tfor _, ignore := range []string{\n\t\t\t\t\t\t\t\"has no body\",\n\t\t\t\t\t\t\t\"type parameters are not yet\",\n\t\t\t\t\t\t\t\"line directives\",\n\t\t\t\t\t\t\t\"cgo-generated\",\n\t\t\t\t\t\t} {\n\t\t\t\t\t\t\tif strings.Contains(err.Error(), ignore) {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tt.Fatalf(\"AnalyzeCallee: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := checkTranscode(callee); err != nil {\n\t\t\t\t\t\tt.Fatal(err)\n\t\t\t\t\t}\n\n\t\t\t\t\tres, err := inline.Inline(caller, callee, &inline.Options{\n\t\t\t\t\t\tLogf: t.Logf,\n\t\t\t\t\t})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t// Write error to a log, but this ok.\n\t\t\t\t\t\tt.Log(err)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tgot, err := applyEdits(caller.Types, caller.File.FileStart, callerContent, res.Edits)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Fatalf(\"can't apply inliner edits: %v\", err)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Print the diff.\n\t\t\t\t\tt.Logf(\"Got diff:\\n%s\",\n\t\t\t\t\t\tdiff.Unified(\"old\", \"new\", string(callerContent), string(got)))\n\n\t\t\t\t\t// Parse and type-check the transformed source.\n\t\t\t\t\tf, err := parser.ParseFile(caller.Fset, callPosn.Filename, got, parser.SkipObjectResolution)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Fatalf(\"transformed source does not parse: %v\", err)\n\t\t\t\t\t}\n\t\t\t\t\t// Splice into original file list.\n\t\t\t\t\tsyntax := slices.Clone(callerPkg.Syntax)\n\t\t\t\t\tfor i := range callerPkg.Syntax {\n\t\t\t\t\t\tif syntax[i] == callerFile {\n\t\t\t\t\t\t\tsyntax[i] = f\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar typeErrors []string\n\t\t\t\t\tconf := &types.Config{\n\t\t\t\t\t\tError: func(err error) {\n\t\t\t\t\t\t\ttypeErrors = append(typeErrors, err.Error())\n\t\t\t\t\t\t},\n\t\t\t\t\t\tImporter: importerFunc(func(importPath string) (*types.Package, error) {\n\t\t\t\t\t\t\t// Note: deps is properly keyed by package path,\n\t\t\t\t\t\t\t// not import path, but we can't assume\n\t\t\t\t\t\t\t// Package.Imports[importPath] exists in the\n\t\t\t\t\t\t\t// case of newly added imports of indirect\n\t\t\t\t\t\t\t// dependencies. Seems not to matter to this test.\n\t\t\t\t\t\t\tdep, ok := deps[importPath]\n\t\t\t\t\t\t\tif ok {\n\t\t\t\t\t\t\t\treturn dep.Types, nil\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"missing package: %q\", importPath)\n\t\t\t\t\t\t}),\n\t\t\t\t\t}\n\t\t\t\t\tif _, err := conf.Check(\"p\", caller.Fset, syntax, nil); err != nil {\n\t\t\t\t\t\tt.Fatalf(\"transformed package has type errors:\\n\\n%s\\n\\nTransformed file:\\n\\n%s\",\n\t\t\t\t\t\t\tstrings.Join(typeErrors, \"\\n\"),\n\t\t\t\t\t\t\tgot)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\treturn true\n\t\t\t})\n\t\t\tnoMutCheck()\n\t\t}\n\t}\n\tlog.Printf(\"Analyzed %d packages\", len(pkgs))\n}\n\ntype importerFunc func(path string) (*types.Package, error)\n\nfunc (f importerFunc) Import(path string) (*types.Package, error) {\n\treturn f(path)\n}\n"
  },
  {
    "path": "internal/refactor/inline/export_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\n// This file opens back doors for testing.\n\nfunc (callee *Callee) Effects() []int { return callee.impl.Effects }\n"
  },
  {
    "path": "internal/refactor/inline/falcon.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\n// This file defines the callee side of the \"fallible constant\" analysis.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// falconResult is the result of the analysis of the callee.\ntype falconResult struct {\n\tTypes       []falconType // types for falcon constraint environment\n\tConstraints []string     // constraints (Go expressions) on values of fallible constants\n}\n\n// A falconType specifies the name and underlying type of a synthetic\n// defined type for use in falcon constraints.\n//\n// Unique types from callee code are bijectively mapped onto falcon\n// types so that constraints are independent of callee type\n// information but preserve type equivalence classes.\n//\n// Fresh names are deliberately obscure to avoid shadowing even if a\n// callee parameter has a name like \"int\" or \"any\".\ntype falconType struct {\n\tName string\n\tKind types.BasicKind // string/number/bool\n}\n\n// falcon identifies \"fallible constant\" expressions, which are\n// expressions that may fail to compile if one or more of their\n// operands is changed from non-constant to constant.\n//\n// Consider:\n//\n//\tfunc sub(s string, i, j int) string { return s[i:j] }\n//\n// If parameters are replaced by constants, the compiler is\n// required to perform these additional checks:\n//\n//   - if i is constant, 0 <= i.\n//   - if s and i are constant, i <= len(s).\n//   - ditto for j.\n//   - if i and j are constant, i <= j.\n//\n// s[i:j] is thus a \"fallible constant\" expression dependent on {s, i,\n// j}. Each falcon creates a set of conditional constraints across one\n// or more parameter variables.\n//\n//   - When inlining a call such as sub(\"abc\", -1, 2), the parameter i\n//     cannot be eliminated by substitution as its argument value is\n//     negative.\n//\n//   - When inlining sub(\"\", 2, 1), all three parameters cannot be\n//     simultaneously eliminated by substitution without violating i\n//     <= len(s) and j <= len(s), but the parameters i and j could be\n//     safely eliminated without s.\n//\n// Parameters that cannot be eliminated must remain non-constant,\n// either in the form of a binding declaration:\n//\n//\t{ var i int = -1; return \"abc\"[i:2] }\n//\n// or a parameter of a literalization:\n//\n//\tfunc (i int) string { return \"abc\"[i:2] }(-1)\n//\n// These example expressions are obviously doomed to fail at run\n// time, but in realistic cases such expressions are dominated by\n// appropriate conditions that make them reachable only when safe:\n//\n//\tif 0 <= i && i <= j && j <= len(s) { _ = s[i:j] }\n//\n// (In principle a more sophisticated inliner could entirely eliminate\n// such unreachable blocks based on the condition being always-false\n// for the given parameter substitution, but this is tricky to do safely\n// because the type-checker considers only a single configuration.\n// Consider: if runtime.GOOS == \"linux\" { ... }.)\n//\n// We believe this is an exhaustive list of \"fallible constant\" operations:\n//\n//   - switch z { case x: case y } \t// duplicate case values\n//   - s[i], s[i:j], s[i:j:k]\t\t// index out of bounds (0 <= i <= j <= k <= len(s))\n//   - T{x: 0}\t\t\t\t// index out of bounds, duplicate index\n//   - x/y, x%y, x/=y, x%=y\t\t// integer division by zero; minint/-1 overflow\n//   - x+y, x-y, x*y\t\t\t// arithmetic overflow\n//   - x<<y\t\t\t\t// shift out of range\n//   - -x\t\t\t\t// negation of minint\n//   - T(x)\t\t\t\t// value out of range\n//\n// The fundamental reason for this elaborate algorithm is that the\n// \"separate analysis\" of callee and caller, as required when running\n// in an environment such as unitchecker, means that there is no way\n// for us to simply invoke the type checker on the combination of\n// caller and callee code, as by the time we analyze the caller, we no\n// longer have access to type information for the callee (and, in\n// particular, any of its direct dependencies that are not direct\n// dependencies of the caller). So, in effect, we are forced to map\n// the problem in a neutral (callee-type-independent) constraint\n// system that can be verified later.\nfunc falcon(logf func(string, ...any), fset *token.FileSet, params map[*types.Var]*paramInfo, info *types.Info, decl *ast.FuncDecl) falconResult {\n\n\tst := &falconState{\n\t\tlogf:   logf,\n\t\tfset:   fset,\n\t\tparams: params,\n\t\tinfo:   info,\n\t\tdecl:   decl,\n\t}\n\n\t// type mapping\n\tst.int = st.typename(types.Typ[types.Int])\n\tst.any = \"interface{}\" // don't use \"any\" as it may be shadowed\n\tfor obj, info := range st.params {\n\t\tif isBasic(obj.Type(), types.IsConstType) {\n\t\t\tinfo.FalconType = st.typename(obj.Type())\n\t\t}\n\t}\n\n\tst.stmt(st.decl.Body)\n\n\treturn st.result\n}\n\ntype falconState struct {\n\t// inputs\n\tlogf   func(string, ...any)\n\tfset   *token.FileSet\n\tparams map[*types.Var]*paramInfo\n\tinfo   *types.Info\n\tdecl   *ast.FuncDecl\n\n\t// working state\n\tint       string\n\tany       string\n\ttypenames typeutil.Map\n\n\tresult falconResult\n}\n\n// typename returns the name in the falcon constraint system\n// of a given string/number/bool type t. Falcon types are\n// specified directly in go/types data structures rather than\n// by name, avoiding potential shadowing conflicts with\n// confusing parameter names such as \"int\".\n//\n// Also, each distinct type (as determined by types.Identical)\n// is mapped to a fresh type in the falcon system so that we\n// can map the types in the callee code into a neutral form\n// that does not depend on imports, allowing us to detect\n// potential conflicts such as\n//\n//\tmap[any]{T1(1): 0, T2(1): 0}\n//\n// where T1=T2.\nfunc (st *falconState) typename(t types.Type) string {\n\tname, ok := st.typenames.At(t).(string)\n\tif !ok {\n\t\tbasic := t.Underlying().(*types.Basic)\n\n\t\t// That dot ۰ is an Arabic zero numeral U+06F0.\n\t\t// It is very unlikely to appear in a real program.\n\t\t// TODO(adonovan): use a non-heuristic solution.\n\t\tname = fmt.Sprintf(\"%s۰%d\", basic, st.typenames.Len())\n\t\tst.typenames.Set(t, name)\n\t\tst.logf(\"falcon: emit type %s %s // %q\", name, basic, t)\n\t\tst.result.Types = append(st.result.Types, falconType{\n\t\t\tName: name,\n\t\t\tKind: basic.Kind(),\n\t\t})\n\t}\n\treturn name\n}\n\n// -- constraint emission --\n\n// emit emits a Go expression that must have a legal type.\n// In effect, we let the go/types constant folding algorithm\n// do most of the heavy lifting (though it may be hard to\n// believe from the complexity of this algorithm!).\nfunc (st *falconState) emit(constraint ast.Expr) {\n\tvar out strings.Builder\n\tif err := format.Node(&out, st.fset, constraint); err != nil {\n\t\tpanic(err) // can't happen\n\t}\n\tsyntax := out.String()\n\tst.logf(\"falcon: emit constraint %s\", syntax)\n\tst.result.Constraints = append(st.result.Constraints, syntax)\n}\n\n// emitNonNegative emits an []T{}[index] constraint,\n// which ensures index is non-negative if constant.\nfunc (st *falconState) emitNonNegative(index ast.Expr) {\n\tst.emit(&ast.IndexExpr{\n\t\tX: &ast.CompositeLit{\n\t\t\tType: &ast.ArrayType{\n\t\t\t\tElt: makeIdent(st.int),\n\t\t\t},\n\t\t},\n\t\tIndex: index,\n\t})\n}\n\n// emitMonotonic emits an []T{}[i:j] constraint,\n// which ensures i <= j if both are constant.\nfunc (st *falconState) emitMonotonic(i, j ast.Expr) {\n\tst.emit(&ast.SliceExpr{\n\t\tX: &ast.CompositeLit{\n\t\t\tType: &ast.ArrayType{\n\t\t\t\tElt: makeIdent(st.int),\n\t\t\t},\n\t\t},\n\t\tLow:  i,\n\t\tHigh: j,\n\t})\n}\n\n// emitUnique emits a T{elem1: 0, ... elemN: 0} constraint,\n// which ensures that all constant elems are unique.\n// T may be a map, slice, or array depending\n// on the desired check semantics.\nfunc (st *falconState) emitUnique(typ ast.Expr, elems []ast.Expr) {\n\tif len(elems) > 1 {\n\t\tvar elts []ast.Expr\n\t\tfor _, elem := range elems {\n\t\t\telts = append(elts, &ast.KeyValueExpr{\n\t\t\t\tKey:   elem,\n\t\t\t\tValue: makeIntLit(0),\n\t\t\t})\n\t\t}\n\t\tst.emit(&ast.CompositeLit{\n\t\t\tType: typ,\n\t\t\tElts: elts,\n\t\t})\n\t}\n}\n\n// -- traversal --\n\n// The traversal functions scan the callee body for expressions that\n// are not constant but would become constant if the parameter vars\n// were redeclared as constants, and emits for each one a constraint\n// (a Go expression) with the property that it will not type-check\n// (using types.CheckExpr) if the particular argument values are\n// unsuitable.\n//\n// These constraints are checked by Inline with the actual\n// constant argument values. Violations cause it to reject\n// parameters as candidates for substitution.\n\nfunc (st *falconState) stmt(s ast.Stmt) {\n\tast.Inspect(s, func(n ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase ast.Expr:\n\t\t\t_ = st.expr(n)\n\t\t\treturn false // skip usual traversal\n\n\t\tcase *ast.AssignStmt:\n\t\t\tswitch n.Tok {\n\t\t\tcase token.QUO_ASSIGN, token.REM_ASSIGN:\n\t\t\t\t// x /= y\n\t\t\t\t// Possible \"integer division by zero\"\n\t\t\t\t// Emit constraint: 1/y.\n\t\t\t\t_ = st.expr(n.Lhs[0])\n\t\t\t\tkY := st.expr(n.Rhs[0])\n\t\t\t\tif kY, ok := kY.(ast.Expr); ok {\n\t\t\t\t\top := token.QUO\n\t\t\t\t\tif n.Tok == token.REM_ASSIGN {\n\t\t\t\t\t\top = token.REM\n\t\t\t\t\t}\n\t\t\t\t\tst.emit(&ast.BinaryExpr{\n\t\t\t\t\t\tOp: op,\n\t\t\t\t\t\tX:  makeIntLit(1),\n\t\t\t\t\t\tY:  kY,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn false // skip usual traversal\n\t\t\t}\n\n\t\tcase *ast.SwitchStmt:\n\t\t\tif n.Init != nil {\n\t\t\t\tst.stmt(n.Init)\n\t\t\t}\n\t\t\ttBool := types.Type(types.Typ[types.Bool])\n\t\t\ttagType := tBool // default: true\n\t\t\tif n.Tag != nil {\n\t\t\t\tst.expr(n.Tag)\n\t\t\t\ttagType = st.info.TypeOf(n.Tag)\n\t\t\t}\n\n\t\t\t// Possible \"duplicate case value\".\n\t\t\t// Emit constraint map[T]int{v1: 0, ..., vN:0}\n\t\t\t// to ensure all maybe-constant case values are unique\n\t\t\t// (unless switch tag is boolean, which is relaxed).\n\t\t\tvar unique []ast.Expr\n\t\t\tfor _, clause := range n.Body.List {\n\t\t\t\tclause := clause.(*ast.CaseClause)\n\t\t\t\tfor _, caseval := range clause.List {\n\t\t\t\t\tif k := st.expr(caseval); k != nil {\n\t\t\t\t\t\tunique = append(unique, st.toExpr(k))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor _, stmt := range clause.Body {\n\t\t\t\t\tst.stmt(stmt)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif unique != nil && !types.Identical(tagType.Underlying(), tBool) {\n\t\t\t\ttname := st.any\n\t\t\t\tif !types.IsInterface(tagType) {\n\t\t\t\t\ttname = st.typename(tagType)\n\t\t\t\t}\n\t\t\t\tt := &ast.MapType{\n\t\t\t\t\tKey:   makeIdent(tname),\n\t\t\t\t\tValue: makeIdent(st.int),\n\t\t\t\t}\n\t\t\t\tst.emitUnique(t, unique)\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// fieldTypes visits the .Type of each field in the list.\nfunc (st *falconState) fieldTypes(fields *ast.FieldList) {\n\tif fields != nil {\n\t\tfor _, field := range fields.List {\n\t\t\t_ = st.expr(field.Type)\n\t\t}\n\t}\n}\n\n// expr visits the expression (or type) and returns a\n// non-nil result if the expression is constant or would\n// become constant if all suitable function parameters were\n// redeclared as constants.\n//\n// If the expression is constant, st.expr returns its type\n// and value (types.TypeAndValue). If the expression would\n// become constant, st.expr returns an ast.Expr tree whose\n// leaves are literals and parameter references, and whose\n// interior nodes are operations that may become constant,\n// such as -x, x+y, f(x), and T(x). We call these would-be\n// constant expressions \"fallible constants\", since they may\n// fail to type-check for some values of x, i, and j. (We\n// refer to the non-nil cases collectively as \"maybe\n// constant\", and the nil case as \"definitely non-constant\".)\n//\n// As a side effect, st.expr emits constraints for each\n// fallible constant expression; this is its main purpose.\n//\n// Consequently, st.expr must visit the entire subtree so\n// that all necessary constraints are emitted. It may not\n// short-circuit the traversal when it encounters a constant\n// subexpression as constants may contain arbitrary other\n// syntax that may impose constraints. Consider (as always)\n// this contrived but legal example of a type parameter (!)\n// that contains statement syntax:\n//\n//\tfunc f[T [unsafe.Sizeof(func() { stmts })]int]()\n//\n// There is no need to emit constraints for (e.g.) s[i] when s\n// and i are already constants, because we know the expression\n// is sound, but it is sometimes easier to emit these\n// redundant constraints than to avoid them.\nfunc (st *falconState) expr(e ast.Expr) (res any) { // = types.TypeAndValue | ast.Expr\n\ttv := st.info.Types[e]\n\tif tv.Value != nil {\n\t\t// A constant value overrides any other result.\n\t\tdefer func() { res = tv }()\n\t}\n\n\tswitch e := e.(type) {\n\tcase *ast.Ident:\n\t\tif v, ok := st.info.Uses[e].(*types.Var); ok {\n\t\t\tif _, ok := st.params[v]; ok && isBasic(v.Type(), types.IsConstType) {\n\t\t\t\treturn e // reference to constable parameter\n\t\t\t}\n\t\t}\n\t\t// (References to *types.Const are handled by the defer.)\n\n\tcase *ast.BasicLit:\n\t\t// constant\n\n\tcase *ast.ParenExpr:\n\t\treturn st.expr(e.X)\n\n\tcase *ast.FuncLit:\n\t\t_ = st.expr(e.Type)\n\t\tst.stmt(e.Body)\n\t\t// definitely non-constant\n\n\tcase *ast.CompositeLit:\n\t\t// T{k: v, ...}, where T ∈ {array,*array,slice,map},\n\t\t// imposes a constraint that all constant k are\n\t\t// distinct and, for arrays [n]T, within range 0-n.\n\t\t//\n\t\t// Types matter, not just values. For example,\n\t\t// an interface-keyed map may contain keys\n\t\t// that are numerically equal so long as they\n\t\t// are of distinct types. For example:\n\t\t//\n\t\t//   type myint int\n\t\t//   map[any]bool{1: true, 1:        true} // error: duplicate key\n\t\t//   map[any]bool{1: true, int16(1): true} // ok\n\t\t//   map[any]bool{1: true, myint(1): true} // ok\n\t\t//\n\t\t// This can be asserted by emitting a\n\t\t// constraint of the form T{k1: 0, ..., kN: 0}.\n\t\tif e.Type != nil {\n\t\t\t_ = st.expr(e.Type)\n\t\t}\n\t\tt := types.Unalias(typeparams.Deref(tv.Type))\n\t\tct := typeparams.CoreType(t)\n\t\tvar mapKeys []ast.Expr // map key expressions; must be distinct if constant\n\t\tfor _, elt := range e.Elts {\n\t\t\tif kv, ok := elt.(*ast.KeyValueExpr); ok {\n\t\t\t\tif is[*types.Map](ct) {\n\t\t\t\t\tif k := st.expr(kv.Key); k != nil {\n\t\t\t\t\t\tmapKeys = append(mapKeys, st.toExpr(k))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_ = st.expr(kv.Value)\n\t\t\t} else {\n\t\t\t\t_ = st.expr(elt)\n\t\t\t}\n\t\t}\n\t\tif len(mapKeys) > 0 {\n\t\t\t// Inlining a map literal may replace variable key expressions by constants.\n\t\t\t// All such constants must have distinct values.\n\t\t\t// (Array and slice literals do not permit non-constant keys.)\n\t\t\tt := ct.(*types.Map)\n\t\t\tvar typ ast.Expr\n\t\t\tif types.IsInterface(t.Key()) {\n\t\t\t\ttyp = &ast.MapType{\n\t\t\t\t\tKey:   makeIdent(st.any),\n\t\t\t\t\tValue: makeIdent(st.int),\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttyp = &ast.MapType{\n\t\t\t\t\tKey:   makeIdent(st.typename(t.Key())),\n\t\t\t\t\tValue: makeIdent(st.int),\n\t\t\t\t}\n\t\t\t}\n\t\t\tst.emitUnique(typ, mapKeys)\n\t\t}\n\t\t// definitely non-constant\n\n\tcase *ast.SelectorExpr:\n\t\t_ = st.expr(e.X)\n\t\t_ = st.expr(e.Sel)\n\t\t// The defer is sufficient to handle\n\t\t// qualified identifiers (pkg.Const).\n\t\t// All other cases are definitely non-constant.\n\n\tcase *ast.IndexExpr:\n\t\tif tv.IsType() {\n\t\t\t// type C[T]\n\t\t\t_ = st.expr(e.X)\n\t\t\t_ = st.expr(e.Index)\n\t\t} else {\n\t\t\t// term x[i]\n\t\t\t//\n\t\t\t// Constraints (if x is slice/string/array/*array, not map):\n\t\t\t// - i >= 0\n\t\t\t//     if i is a fallible constant\n\t\t\t// - i < len(x)\n\t\t\t//     if x is array/*array and\n\t\t\t//     i is a fallible constant;\n\t\t\t//  or if s is a string and both i,\n\t\t\t//     s are maybe-constants,\n\t\t\t//     but not both are constants.\n\t\t\tkX := st.expr(e.X)\n\t\t\tkI := st.expr(e.Index)\n\t\t\tif kI != nil && !is[*types.Map](st.info.TypeOf(e.X).Underlying()) {\n\t\t\t\tif kI, ok := kI.(ast.Expr); ok {\n\t\t\t\t\tst.emitNonNegative(kI)\n\t\t\t\t}\n\t\t\t\t// Emit constraint to check indices against known length.\n\t\t\t\t// TODO(adonovan): factor with SliceExpr logic.\n\t\t\t\tvar x ast.Expr\n\t\t\t\tif kX != nil {\n\t\t\t\t\t// string\n\t\t\t\t\tx = st.toExpr(kX)\n\t\t\t\t} else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {\n\t\t\t\t\t// array, *array\n\t\t\t\t\tx = &ast.CompositeLit{\n\t\t\t\t\t\tType: &ast.ArrayType{\n\t\t\t\t\t\t\tLen: makeIntLit(arr.Len()),\n\t\t\t\t\t\t\tElt: makeIdent(st.int),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif x != nil {\n\t\t\t\t\tst.emit(&ast.IndexExpr{\n\t\t\t\t\t\tX:     x,\n\t\t\t\t\t\tIndex: st.toExpr(kI),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// definitely non-constant\n\n\tcase *ast.SliceExpr:\n\t\t// x[low:high:max]\n\t\t//\n\t\t// Emit non-negative constraints for each index,\n\t\t// plus low <= high <= max <= len(x)\n\t\t// for each pair that are maybe-constant\n\t\t// but not definitely constant.\n\n\t\tkX := st.expr(e.X)\n\t\tvar kLow, kHigh, kMax any\n\t\tif e.Low != nil {\n\t\t\tkLow = st.expr(e.Low)\n\t\t\tif kLow != nil {\n\t\t\t\tif kLow, ok := kLow.(ast.Expr); ok {\n\t\t\t\t\tst.emitNonNegative(kLow)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif e.High != nil {\n\t\t\tkHigh = st.expr(e.High)\n\t\t\tif kHigh != nil {\n\t\t\t\tif kHigh, ok := kHigh.(ast.Expr); ok {\n\t\t\t\t\tst.emitNonNegative(kHigh)\n\t\t\t\t}\n\t\t\t\tif kLow != nil {\n\t\t\t\t\tst.emitMonotonic(st.toExpr(kLow), st.toExpr(kHigh))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif e.Max != nil {\n\t\t\tkMax = st.expr(e.Max)\n\t\t\tif kMax != nil {\n\t\t\t\tif kMax, ok := kMax.(ast.Expr); ok {\n\t\t\t\t\tst.emitNonNegative(kMax)\n\t\t\t\t}\n\t\t\t\tif kHigh != nil {\n\t\t\t\t\tst.emitMonotonic(st.toExpr(kHigh), st.toExpr(kMax))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Emit constraint to check indices against known length.\n\t\tvar x ast.Expr\n\t\tif kX != nil {\n\t\t\t// string\n\t\t\tx = st.toExpr(kX)\n\t\t} else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {\n\t\t\t// array, *array\n\t\t\tx = &ast.CompositeLit{\n\t\t\t\tType: &ast.ArrayType{\n\t\t\t\t\tLen: makeIntLit(arr.Len()),\n\t\t\t\t\tElt: makeIdent(st.int),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tif x != nil {\n\t\t\t// Avoid slice[::max] if kHigh is nonconstant (nil).\n\t\t\thigh, max := st.toExpr(kHigh), st.toExpr(kMax)\n\t\t\tif high == nil {\n\t\t\t\thigh = max // => slice[:max:max]\n\t\t\t}\n\t\t\tst.emit(&ast.SliceExpr{\n\t\t\t\tX:    x,\n\t\t\t\tLow:  st.toExpr(kLow),\n\t\t\t\tHigh: high,\n\t\t\t\tMax:  max,\n\t\t\t})\n\t\t}\n\t\t// definitely non-constant\n\n\tcase *ast.TypeAssertExpr:\n\t\t_ = st.expr(e.X)\n\t\tif e.Type != nil {\n\t\t\t_ = st.expr(e.Type)\n\t\t}\n\n\tcase *ast.CallExpr:\n\t\t_ = st.expr(e.Fun)\n\t\tif tv, ok := st.info.Types[e.Fun]; ok && tv.IsType() {\n\t\t\t// conversion T(x)\n\t\t\t//\n\t\t\t// Possible \"value out of range\".\n\t\t\tkX := st.expr(e.Args[0])\n\t\t\tif kX != nil && isBasic(tv.Type, types.IsConstType) {\n\t\t\t\tconv := convert(makeIdent(st.typename(tv.Type)), st.toExpr(kX))\n\t\t\t\tif is[ast.Expr](kX) {\n\t\t\t\t\tst.emit(conv)\n\t\t\t\t}\n\t\t\t\treturn conv\n\t\t\t}\n\t\t\treturn nil // definitely non-constant\n\t\t}\n\n\t\t// call f(x)\n\n\t\tall := true // all args are possibly-constant\n\t\tkArgs := make([]ast.Expr, len(e.Args))\n\t\tfor i, arg := range e.Args {\n\t\t\tif kArg := st.expr(arg); kArg != nil {\n\t\t\t\tkArgs[i] = st.toExpr(kArg)\n\t\t\t} else {\n\t\t\t\tall = false\n\t\t\t}\n\t\t}\n\n\t\t// Calls to built-ins with fallibly constant arguments\n\t\t// may become constant. All other calls are either\n\t\t// constant or non-constant\n\t\tif id, ok := e.Fun.(*ast.Ident); ok && all && tv.Value == nil {\n\t\t\tif builtin, ok := st.info.Uses[id].(*types.Builtin); ok {\n\t\t\t\tswitch builtin.Name() {\n\t\t\t\tcase \"len\", \"imag\", \"real\", \"complex\", \"min\", \"max\":\n\t\t\t\t\treturn &ast.CallExpr{\n\t\t\t\t\t\tFun:      id,\n\t\t\t\t\t\tArgs:     kArgs,\n\t\t\t\t\t\tEllipsis: e.Ellipsis,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase *ast.StarExpr: // *T, *ptr\n\t\t_ = st.expr(e.X)\n\n\tcase *ast.UnaryExpr:\n\t\t// + - ! ^ & <- ~\n\t\t//\n\t\t// Possible \"negation of minint\".\n\t\t// Emit constraint: -x\n\t\tkX := st.expr(e.X)\n\t\tif kX != nil && !is[types.TypeAndValue](kX) {\n\t\t\tif e.Op == token.SUB {\n\t\t\t\tst.emit(&ast.UnaryExpr{\n\t\t\t\t\tOp: e.Op,\n\t\t\t\t\tX:  st.toExpr(kX),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn &ast.UnaryExpr{\n\t\t\t\tOp: e.Op,\n\t\t\t\tX:  st.toExpr(kX),\n\t\t\t}\n\t\t}\n\n\tcase *ast.BinaryExpr:\n\t\tkX := st.expr(e.X)\n\t\tkY := st.expr(e.Y)\n\t\tswitch e.Op {\n\t\tcase token.QUO, token.REM:\n\t\t\t// x/y, x%y\n\t\t\t//\n\t\t\t// Possible \"integer division by zero\" or\n\t\t\t// \"minint / -1\" overflow.\n\t\t\t// Emit constraint: x/y or 1/y\n\t\t\tif kY != nil {\n\t\t\t\tif kX == nil {\n\t\t\t\t\tkX = makeIntLit(1)\n\t\t\t\t}\n\t\t\t\tst.emit(&ast.BinaryExpr{\n\t\t\t\t\tOp: e.Op,\n\t\t\t\t\tX:  st.toExpr(kX),\n\t\t\t\t\tY:  st.toExpr(kY),\n\t\t\t\t})\n\t\t\t}\n\n\t\tcase token.ADD, token.SUB, token.MUL:\n\t\t\t// x+y, x-y, x*y\n\t\t\t//\n\t\t\t// Possible \"arithmetic overflow\".\n\t\t\t// Emit constraint: x+y\n\t\t\tif kX != nil && kY != nil {\n\t\t\t\tst.emit(&ast.BinaryExpr{\n\t\t\t\t\tOp: e.Op,\n\t\t\t\t\tX:  st.toExpr(kX),\n\t\t\t\t\tY:  st.toExpr(kY),\n\t\t\t\t})\n\t\t\t}\n\n\t\tcase token.SHL, token.SHR:\n\t\t\t// x << y, x >> y\n\t\t\t//\n\t\t\t// Possible \"constant shift too large\".\n\t\t\t// Either operand may be too large individually,\n\t\t\t// and they may be too large together.\n\t\t\t// Emit constraint:\n\t\t\t//    x << y (if both maybe-constant)\n\t\t\t//    x << 0 (if y is non-constant)\n\t\t\t//    1 << y (if x is non-constant)\n\t\t\tif kX != nil || kY != nil {\n\t\t\t\tx := st.toExpr(kX)\n\t\t\t\tif x == nil {\n\t\t\t\t\tx = makeIntLit(1)\n\t\t\t\t}\n\t\t\t\ty := st.toExpr(kY)\n\t\t\t\tif y == nil {\n\t\t\t\t\ty = makeIntLit(0)\n\t\t\t\t}\n\t\t\t\tst.emit(&ast.BinaryExpr{\n\t\t\t\t\tOp: e.Op,\n\t\t\t\t\tX:  x,\n\t\t\t\t\tY:  y,\n\t\t\t\t})\n\t\t\t}\n\n\t\tcase token.LSS, token.GTR, token.EQL, token.NEQ, token.LEQ, token.GEQ:\n\t\t\t// < > == != <= <=\n\t\t\t//\n\t\t\t// A \"x cmp y\" expression with constant operands x, y is\n\t\t\t// itself constant, but I can't see how a constant bool\n\t\t\t// could be fallible: the compiler doesn't reject duplicate\n\t\t\t// boolean cases in a switch, presumably because boolean\n\t\t\t// switches are less like n-way branches and more like\n\t\t\t// sequential if-else chains with possibly overlapping\n\t\t\t// conditions; and there is (sadly) no way to convert a\n\t\t\t// boolean constant to an int constant.\n\t\t}\n\t\tif kX != nil && kY != nil {\n\t\t\treturn &ast.BinaryExpr{\n\t\t\t\tOp: e.Op,\n\t\t\t\tX:  st.toExpr(kX),\n\t\t\t\tY:  st.toExpr(kY),\n\t\t\t}\n\t\t}\n\n\t// types\n\t//\n\t// We need to visit types (and even type parameters)\n\t// in order to reach all the places where things could go wrong:\n\t//\n\t// \tconst (\n\t// \t\ts = \"\"\n\t// \t\ti = 0\n\t// \t)\n\t// \ttype C[T [unsafe.Sizeof(func() { _ = s[i] })]int] bool\n\n\tcase *ast.IndexListExpr:\n\t\t_ = st.expr(e.X)\n\t\tfor _, expr := range e.Indices {\n\t\t\t_ = st.expr(expr)\n\t\t}\n\n\tcase *ast.Ellipsis:\n\t\tif e.Elt != nil {\n\t\t\t_ = st.expr(e.Elt)\n\t\t}\n\n\tcase *ast.ArrayType:\n\t\tif e.Len != nil {\n\t\t\t_ = st.expr(e.Len)\n\t\t}\n\t\t_ = st.expr(e.Elt)\n\n\tcase *ast.StructType:\n\t\tst.fieldTypes(e.Fields)\n\n\tcase *ast.FuncType:\n\t\tst.fieldTypes(e.TypeParams)\n\t\tst.fieldTypes(e.Params)\n\t\tst.fieldTypes(e.Results)\n\n\tcase *ast.InterfaceType:\n\t\tst.fieldTypes(e.Methods)\n\n\tcase *ast.MapType:\n\t\t_ = st.expr(e.Key)\n\t\t_ = st.expr(e.Value)\n\n\tcase *ast.ChanType:\n\t\t_ = st.expr(e.Value)\n\t}\n\treturn\n}\n\n// toExpr converts the result of visitExpr to a falcon expression.\n// (We don't do this in visitExpr as we first need to discriminate\n// constants from maybe-constants.)\nfunc (st *falconState) toExpr(x any) ast.Expr {\n\tswitch x := x.(type) {\n\tcase nil:\n\t\treturn nil\n\n\tcase types.TypeAndValue:\n\t\tlit := makeLiteral(x.Value)\n\t\tif !isBasic(x.Type, types.IsUntyped) {\n\t\t\t// convert to \"typed\" type\n\t\t\tlit = &ast.CallExpr{\n\t\t\t\tFun:  makeIdent(st.typename(x.Type)),\n\t\t\t\tArgs: []ast.Expr{lit},\n\t\t\t}\n\t\t}\n\t\treturn lit\n\n\tcase ast.Expr:\n\t\treturn x\n\n\tdefault:\n\t\tpanic(x)\n\t}\n}\n\nfunc makeLiteral(v constant.Value) ast.Expr {\n\tswitch v.Kind() {\n\tcase constant.Bool:\n\t\t// Rather than refer to the true or false built-ins,\n\t\t// which could be shadowed by poorly chosen parameter\n\t\t// names, we use 0 == 0 for true and 0 != 0 for false.\n\t\top := token.EQL\n\t\tif !constant.BoolVal(v) {\n\t\t\top = token.NEQ\n\t\t}\n\t\treturn &ast.BinaryExpr{\n\t\t\tOp: op,\n\t\t\tX:  makeIntLit(0),\n\t\t\tY:  makeIntLit(0),\n\t\t}\n\n\tcase constant.String:\n\t\treturn &ast.BasicLit{\n\t\t\tKind:  token.STRING,\n\t\t\tValue: v.ExactString(),\n\t\t}\n\n\tcase constant.Int:\n\t\treturn &ast.BasicLit{\n\t\t\tKind:  token.INT,\n\t\t\tValue: v.ExactString(),\n\t\t}\n\n\tcase constant.Float:\n\t\treturn &ast.BasicLit{\n\t\t\tKind:  token.FLOAT,\n\t\t\tValue: v.ExactString(),\n\t\t}\n\n\tcase constant.Complex:\n\t\t// The components could be float or int.\n\t\ty := makeLiteral(constant.Imag(v))\n\t\ty.(*ast.BasicLit).Value += \"i\" // ugh\n\t\tif re := constant.Real(v); !consteq(re, kZeroInt) {\n\t\t\t// complex: x + yi\n\t\t\ty = &ast.BinaryExpr{\n\t\t\t\tOp: token.ADD,\n\t\t\t\tX:  makeLiteral(re),\n\t\t\t\tY:  y,\n\t\t\t}\n\t\t}\n\t\treturn y\n\n\tdefault:\n\t\tpanic(v.Kind())\n\t}\n}\n\nfunc makeIntLit(x int64) *ast.BasicLit {\n\treturn &ast.BasicLit{\n\t\tKind:  token.INT,\n\t\tValue: strconv.FormatInt(x, 10),\n\t}\n}\n\nfunc isBasic(t types.Type, info types.BasicInfo) bool {\n\tbasic, ok := t.Underlying().(*types.Basic)\n\treturn ok && basic.Info()&info != 0\n}\n"
  },
  {
    "path": "internal/refactor/inline/falcon_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline_test\n\nimport \"testing\"\n\n// Testcases mostly come in pairs, of a success and a failure\n// to substitute based on specific constant argument values.\n\nfunc TestFalconStringIndex(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Non-negative string index.\",\n\t\t\t`func f(i int) byte { return s[i] }; var s string`,\n\t\t\t`func _() { f(0) }`,\n\t\t\t`func _() { _ = s[0] }`,\n\t\t},\n\t\t{\n\t\t\t\"Negative string index.\",\n\t\t\t`func f(i int) byte { return s[i] }; var s string`,\n\t\t\t`func _() { f(-1) }`,\n\t\t\t`func _() {\n\tvar i int = -1\n\t_ = s[i]\n}`,\n\t\t},\n\t\t{\n\t\t\t\"String index in range.\",\n\t\t\t`func f(s string, i int) byte { return s[i] }`,\n\t\t\t`func _() { f(\"-\", 0) }`,\n\t\t\t`func _() { _ = \"-\"[0] }`,\n\t\t},\n\t\t{\n\t\t\t\"String index out of range.\",\n\t\t\t`func f(s string, i int) byte { return s[i] }`,\n\t\t\t`func _() { f(\"-\", 1) }`,\n\t\t\t`func _() {\n\tvar (\n\t\ts string = \"-\"\n\t\ti int    = 1\n\t)\n\t_ = s[i]\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Remove known prefix (OK)\",\n\t\t\t`func f(s, prefix string) string { return s[:len(prefix)] }`,\n\t\t\t`func _() { f(\"\", \"\") }`,\n\t\t\t`func _() { _ = \"\"[:len(\"\")] }`,\n\t\t},\n\t\t{\n\t\t\t\"Remove not-a-prefix (out of range)\",\n\t\t\t`func f(s, prefix string) string { return s[:len(prefix)] }`,\n\t\t\t`func _() { f(\"\", \"pre\") }`,\n\t\t\t`func _() {\n\tvar s, prefix string = \"\", \"pre\"\n\t_ = s[:len(prefix)]\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconSliceIndices(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Monotonic (0<=i<=j) slice indices (len unknown).\",\n\t\t\t`func f(i, j int) []int { return s[i:j] }; var s []int`,\n\t\t\t`func _() { f(0, 1) }`,\n\t\t\t`func _() { _ = s[0:1] }`,\n\t\t},\n\t\t{\n\t\t\t\"Non-monotonic slice indices (len unknown).\",\n\t\t\t`func f(i, j int) []int { return s[i:j] }; var s []int`,\n\t\t\t`func _() { f(1, 0) }`,\n\t\t\t`func _() {\n\tvar i, j int = 1, 0\n\t_ = s[i:j]\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Negative slice index.\",\n\t\t\t`func f(i, j int) []int { return s[i:j] }; var s []int`,\n\t\t\t`func _() { f(-1, 1) }`,\n\t\t\t`func _() {\n\tvar i, j int = -1, 1\n\t_ = s[i:j]\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconMapKeys(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Unique map keys (int)\",\n\t\t\t`func f(x int) { _ = map[int]bool{1: true, x: true} }`,\n\t\t\t`func _() { f(2) }`,\n\t\t\t`func _() { _ = map[int]bool{1: true, 2: true} }`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate map keys (int)\",\n\t\t\t`func f(x int) { _ = map[int]bool{1: true, x: true} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\t_ = map[int]bool{1: true, x: true}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Generic map keys\",\n\t\t\t// We have to use a named map type here, because the substituter tries to\n\t\t\t// wrap the type expr in parens, which are not allowed around the type in\n\t\t\t// composite literal expressions.\n\t\t\t`type Map map[int]bool; func f[M Map](x int) { _ = M{1: true, x: true} }`,\n\t\t\t`func _() { f[Map](1) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\t_ = Map{1: true, x: true}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Array keys\", // not a map; shouldn't crash (golang/go$74393)\n\t\t\t`func f(x int) { _ = [2]int{1: 0} }`,\n\t\t\t`func _() { f(0) }`,\n\t\t\t`func _() { _ = [2]int{1: 0} }`,\n\t\t},\n\t\t{\n\t\t\t\"Slice keys\", // not a map; shouldn't crash (golang/go$74393)\n\t\t\t`func f(x int) { _ = []int{1: 0} }`,\n\t\t\t`func _() { f(0) }`,\n\t\t\t`func _() { _ = []int{1: 0} }`,\n\t\t},\n\t\t{\n\t\t\t\"Unique map keys (varied built-in types)\",\n\t\t\t`func f(x int16) { _ = map[any]bool{1: true, x: true} }`,\n\t\t\t`func _() { f(2) }`,\n\t\t\t`func _() { _ = map[any]bool{1: true, int16(2): true} }`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate map keys (varied built-in types)\",\n\t\t\t`func f(x int16) { _ = map[any]bool{1: true, x: true} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = map[any]bool{1: true, int16(1): true} }`,\n\t\t},\n\t\t{\n\t\t\t\"Unique map keys (varied user-defined types)\",\n\t\t\t`func f(x myint) { _ = map[any]bool{1: true, x: true} }; type myint int`,\n\t\t\t`func _() { f(2) }`,\n\t\t\t`func _() { _ = map[any]bool{1: true, myint(2): true} }`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate map keys (varied user-defined types)\",\n\t\t\t`func f(x myint, y myint2) { _ = map[any]bool{x: true, y: true} }; type (myint int; myint2 int)`,\n\t\t\t`func _() { f(1, 1) }`,\n\t\t\t`func _() {\n\tvar (\n\t\tx myint  = 1\n\t\ty myint2 = 1\n\t)\n\t_ = map[any]bool{x: true, y: true}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate map keys (user-defined alias to built-in)\",\n\t\t\t`func f(x myint, y int) { _ = map[any]bool{x: true, y: true} }; type myint = int`,\n\t\t\t`func _() { f(1, 1) }`,\n\t\t\t`func _() {\n\tvar (\n\t\tx myint = 1\n\t\ty int   = 1\n\t)\n\t_ = map[any]bool{x: true, y: true}\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconSwitchCases(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Unique switch cases (int).\",\n\t\t\t`func f(x int) { switch 0 { case x: case 1: } }`,\n\t\t\t`func _() { f(2) }`,\n\t\t\t`func _() {\n\tswitch 0 {\n\tcase 2:\n\tcase 1:\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate switch cases (int).\",\n\t\t\t`func f(x int) { switch 0 { case x: case 1: } }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\tswitch 0 {\n\tcase x:\n\tcase 1:\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Unique switch cases (varied built-in types).\",\n\t\t\t`func f(x int) { switch any(nil) { case x: case int16(1): } }`,\n\t\t\t`func _() { f(2) }`,\n\t\t\t`func _() {\n\tswitch any(nil) {\n\tcase 2:\n\tcase int16(1):\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Duplicate switch cases (varied built-in types).\",\n\t\t\t`func f(x int) { switch any(nil) { case x: case int16(1): } }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\tswitch any(nil) {\n\tcase 1:\n\tcase int16(1):\n\t}\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconDivision(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Division by two.\",\n\t\t\t`func f(x, y int) int { return x / y }`,\n\t\t\t`func _() { f(1, 2) }`,\n\t\t\t`func _() { _ = 1 / 2 }`,\n\t\t},\n\t\t{\n\t\t\t\"Division by zero.\",\n\t\t\t`func f(x, y int) int { return x / y }`,\n\t\t\t`func _() { f(1, 0) }`,\n\t\t\t`func _() {\n\tvar x, y int = 1, 0\n\t_ = x / y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Division by two (statement).\",\n\t\t\t`func f(x, y int) { x /= y }`,\n\t\t\t`func _() { f(1, 2) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\tx /= 2\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Division by zero (statement).\",\n\t\t\t`func f(x, y int) { x /= y }`,\n\t\t\t`func _() { f(1, 0) }`,\n\t\t\t`func _() {\n\tvar x, y int = 1, 0\n\tx /= y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Division of minint by two (ok).\",\n\t\t\t`func f(x, y int32) { _ = x / y }`,\n\t\t\t`func _() { f(-0x80000000, 2) }`,\n\t\t\t`func _() { _ = int32(-0x80000000) / int32(2) }`,\n\t\t},\n\t\t{\n\t\t\t\"Division of minint by -1 (overflow).\",\n\t\t\t`func f(x, y int32) { _ = x / y }`,\n\t\t\t`func _() { f(-0x80000000, -1) }`,\n\t\t\t`func _() {\n\tvar x, y int32 = -0x80000000, -1\n\t_ = x / y\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconMinusMinInt(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Negation of maxint.\",\n\t\t\t`func f(x int32) int32 { return -x }`,\n\t\t\t`func _() { f(0x7fffffff) }`,\n\t\t\t`func _() { _ = -int32(0x7fffffff) }`,\n\t\t},\n\t\t{\n\t\t\t\"Negation of minint.\",\n\t\t\t`func f(x int32) int32 { return -x }`,\n\t\t\t`func _() { f(-0x80000000) }`,\n\t\t\t`func _() {\n\tvar x int32 = -0x80000000\n\t_ = -x\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconArithmeticOverflow(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Addition without overflow.\",\n\t\t\t`func f(x, y int32) int32 { return x + y }`,\n\t\t\t`func _() { f(100, 200) }`,\n\t\t\t`func _() { _ = int32(100) + int32(200) }`,\n\t\t},\n\t\t{\n\t\t\t\"Addition with overflow.\",\n\t\t\t`func f(x, y int32) int32 { return x + y }`,\n\t\t\t`func _() { f(1<<30, 1<<30) }`,\n\t\t\t`func _() {\n\tvar x, y int32 = 1 << 30, 1 << 30\n\t_ = x + y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Conversion in range.\",\n\t\t\t`func f(x int) int8 { return int8(x) }`,\n\t\t\t`func _() { f(123) }`,\n\t\t\t`func _() { _ = int8(123) }`,\n\t\t},\n\t\t{\n\t\t\t\"Conversion out of range.\",\n\t\t\t`func f(x int) int8 { return int8(x) }`,\n\t\t\t`func _() { f(456) }`,\n\t\t\t`func _() {\n\tvar x int = 456\n\t_ = int8(x)\n}`,\n\t\t},\n\t})\n}\n\nfunc TestFalconComplex(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Complex arithmetic (good).\",\n\t\t\t`func f(re, im float64, z complex128) byte { return \"x\"[int(real(complex(re, im)*complex(re, -im)-z))] }`,\n\t\t\t`func _() { f(1, 2, 5+0i) }`,\n\t\t\t// The float64 conversions are excessively conservative here\n\t\t\t// but in general may affect the type of complex produced.\n\t\t\t`func _() { _ = \"x\"[int(real(complex(float64(1), float64(2))*complex(float64(1), -2)-(5+0i)))] }`,\n\t\t},\n\t\t{\n\t\t\t\"Complex arithmetic (bad).\",\n\t\t\t`func f(re, im float64, z complex128) byte { return \"x\"[int(real(complex(re, im)*complex(re, -im)-z))] }`,\n\t\t\t`func _() { f(1, 3, 5+0i) }`,\n\t\t\t`func _() {\n\tvar (\n\t\tre, im float64    = 1, 3\n\t\tz      complex128 = 5 + 0i\n\t)\n\t_ = \"x\"[int(real(complex(re, im)*complex(re, -im)-z))]\n}`,\n\t\t},\n\t})\n}\nfunc TestFalconMisc(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Compound constant expression (good).\",\n\t\t\t`func f(x, y string, i, j int) byte { return x[i*len(y)+j] }`,\n\t\t\t`func _() { f(\"abc\", \"xy\", 2, -3) }`,\n\t\t\t`func _() { _ = \"abc\"[2*len(\"xy\")+-3] }`,\n\t\t},\n\t\t{\n\t\t\t\"Compound constant expression (index out of range).\",\n\t\t\t`func f(x, y string, i, j int) byte { return x[i*len(y)+j] }`,\n\t\t\t`func _() { f(\"abc\", \"xy\", 4, -3) }`,\n\t\t\t`func _() {\n\tvar (\n\t\tx, y string = \"abc\", \"xy\"\n\t\ti, j int    = 4, -3\n\t)\n\t_ = x[i*len(y)+j]\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Constraints within nested functions (good).\",\n\t\t\t`func f(x int) { _ = func() { _ = [1]int{}[x] } }`,\n\t\t\t`func _() { f(0) }`,\n\t\t\t`func _() { _ = func() { _ = [1]int{}[0] } }`,\n\t\t},\n\t\t{\n\t\t\t\"Constraints within nested functions (bad).\",\n\t\t\t`func f(x int) { _ = func() { _ = [1]int{}[x] } }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\t_ = func() { _ = [1]int{}[x] }\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Falcon violation rejects only the constant arguments (x, z).\",\n\t\t\t`func f(x, y, z string) string { return x[:2] + y + z[:2] }; var b string`,\n\t\t\t`func _() { f(\"a\", b, \"c\") }`,\n\t\t\t`func _() {\n\tvar x, z string = \"a\", \"c\"\n\t_ = x[:2] + b + z[:2]\n}`,\n\t\t},\n\t})\n}\n"
  },
  {
    "path": "internal/refactor/inline/inline.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\tpathpkg \"path\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\tinternalastutil \"golang.org/x/tools/internal/astutil\"\n\t\"golang.org/x/tools/internal/astutil/free\"\n\t\"golang.org/x/tools/internal/packagepath\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// A Caller describes the function call and its enclosing context.\n//\n// The client is responsible for populating this struct and passing it to Inline.\ntype Caller struct {\n\tFset  *token.FileSet\n\tTypes *types.Package\n\tInfo  *types.Info\n\tFile  *ast.File\n\tCall  *ast.CallExpr\n\n\t// CountUses is an optional optimized computation of\n\t// the number of times pkgname appears in Info.Uses.\n\tCountUses func(pkgname *types.PkgName) int\n\n\tpath          []ast.Node    // path from call to root of file syntax tree\n\tenclosingFunc *ast.FuncDecl // top-level function/method enclosing the call, if any\n}\n\ntype logger = func(string, ...any)\n\n// Options specifies parameters affecting the inliner algorithm.\n// All fields are optional.\ntype Options struct {\n\tLogf          logger // log output function, records decision-making process\n\tIgnoreEffects bool   // ignore potential side effects of arguments (unsound)\n}\n\n// Result holds the result of code transformation.\ntype Result struct {\n\tEdits       []refactor.Edit // edits around CallExpr and imports\n\tLiteralized bool            // chosen strategy replaced callee() with func(){...}()\n\tBindingDecl bool            // transformation added \"var params = args\" declaration\n}\n\n// Inline inlines the called function (callee) into the function call (caller)\n// and returns the updated, formatted content of the caller source file.\n//\n// Inline does not mutate any public fields of Caller or Callee.\nfunc Inline(caller *Caller, callee *Callee, opts *Options) (*Result, error) {\n\tcopy := *opts // shallow copy\n\topts = &copy\n\t// Set default options.\n\tif opts.Logf == nil {\n\t\topts.Logf = func(string, ...any) {}\n\t}\n\n\tst := &state{\n\t\tcaller: caller,\n\t\tcallee: callee,\n\t\topts:   opts,\n\t}\n\treturn st.inline()\n}\n\n// state holds the working state of the inliner.\ntype state struct {\n\tcaller *Caller\n\tcallee *Callee\n\topts   *Options\n}\n\nfunc (st *state) inline() (*Result, error) {\n\tlogf, caller, callee := st.opts.Logf, st.caller, st.callee\n\n\tlogf(\"inline %s @ %v\",\n\t\tdebugFormatNode(caller.Fset, caller.Call),\n\t\tcaller.Fset.PositionFor(caller.Call.Lparen, false))\n\n\tif ast.IsGenerated(caller.File) {\n\t\treturn nil, fmt.Errorf(\"cannot inline calls from generated files\")\n\t}\n\n\tres, err := st.inlineCall()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Replace the call (or some node that encloses it) by new syntax.\n\tassert(res.old != nil, \"old is nil\")\n\tassert(res.new != nil, \"new is nil\")\n\n\t// A single return operand inlined to a unary\n\t// expression context may need parens. Otherwise:\n\t//    func two() int { return 1+1 }\n\t//    print(-two())  =>  print(-1+1) // oops!\n\t//\n\t// Usually it is not necessary to insert ParenExprs\n\t// as the formatter is smart enough to insert them as\n\t// needed by the context. But the res.{old,new}\n\t// substitution is done by formatting res.new in isolation\n\t// and then splicing its text over res.old, so the\n\t// formatter doesn't see the parent node and cannot do\n\t// the right thing. (One solution would be to always\n\t// format the enclosing node of old, but that requires\n\t// non-lossy comment handling, #20744.)\n\t//\n\t// So, we must analyze the call's context\n\t// to see whether ambiguity is possible.\n\t// For example, if the context is x[y:z], then\n\t// the x subtree is subject to precedence ambiguity\n\t// (replacing x by p+q would give p+q[y:z] which is wrong)\n\t// but the y and z subtrees are safe.\n\tif new, ok := res.new.(ast.Expr); ok {\n\t\tparent := caller.path[slices.Index(caller.path, res.old)+1]\n\t\tres.new = internalastutil.MaybeParenthesize(parent, res.old.(ast.Expr), new)\n\t}\n\n\t// Some reduction strategies return a new block holding the\n\t// callee's statements. The block's braces may be elided when\n\t// there is no conflict between names declared in the block\n\t// with those declared by the parent block, and no risk of\n\t// a caller's goto jumping forward across a declaration.\n\t//\n\t// This elision is only safe when the ExprStmt is beneath a\n\t// BlockStmt, CaseClause.Body, or CommClause.Body;\n\t// (see \"statement theory\").\n\t//\n\t// The inlining analysis may have already determined that eliding braces is\n\t// safe. Otherwise, we analyze its safety here.\n\telideBraces := res.elideBraces\n\tif !elideBraces {\n\t\tif newBlock, ok := res.new.(*ast.BlockStmt); ok {\n\t\t\ti := slices.Index(caller.path, res.old)\n\t\t\tparent := caller.path[i+1]\n\t\t\tvar body []ast.Stmt\n\t\t\tswitch parent := parent.(type) {\n\t\t\tcase *ast.BlockStmt:\n\t\t\t\tbody = parent.List\n\t\t\tcase *ast.CommClause:\n\t\t\t\tbody = parent.Body\n\t\t\tcase *ast.CaseClause:\n\t\t\t\tbody = parent.Body\n\t\t\t}\n\t\t\tif body != nil {\n\t\t\t\tcallerNames := declares(body)\n\n\t\t\t\t// If BlockStmt is a function body,\n\t\t\t\t// include its receiver, params, and results.\n\t\t\t\taddFieldNames := func(fields *ast.FieldList) {\n\t\t\t\t\tif fields != nil {\n\t\t\t\t\t\tfor _, field := range fields.List {\n\t\t\t\t\t\t\tfor _, id := range field.Names {\n\t\t\t\t\t\t\t\tcallerNames[id.Name] = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch f := caller.path[i+2].(type) {\n\t\t\t\tcase *ast.FuncDecl:\n\t\t\t\t\taddFieldNames(f.Recv)\n\t\t\t\t\taddFieldNames(f.Type.Params)\n\t\t\t\t\taddFieldNames(f.Type.Results)\n\t\t\t\tcase *ast.FuncLit:\n\t\t\t\t\taddFieldNames(f.Type.Params)\n\t\t\t\t\taddFieldNames(f.Type.Results)\n\t\t\t\t}\n\n\t\t\t\tif len(callerLabels(caller.path)) > 0 {\n\t\t\t\t\t// TODO(adonovan): be more precise and reject\n\t\t\t\t\t// only forward gotos across the inlined block.\n\t\t\t\t\tlogf(\"keeping block braces: caller uses control labels\")\n\t\t\t\t} else if intersects(declares(newBlock.List), callerNames) {\n\t\t\t\t\tlogf(\"keeping block braces: avoids name conflict\")\n\t\t\t\t} else {\n\t\t\t\t\telideBraces = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar edits []refactor.Edit\n\n\t// Format the cloned callee.\n\t{\n\t\t// TODO(adonovan): might it make more sense to use\n\t\t// callee.Fset when formatting res.new?\n\t\t// The new tree is a mix of (cloned) caller nodes for\n\t\t// the argument expressions and callee nodes for the\n\t\t// function body. In essence the question is: which\n\t\t// is more likely to have comments?\n\t\t// Usually the callee body will be larger and more\n\t\t// statement-heavy than the arguments, but a\n\t\t// strategy may widen the scope of the replacement\n\t\t// (res.old) from CallExpr to, say, its enclosing\n\t\t// block, so the caller nodes dominate.\n\t\t// Precise comment handling would make this a\n\t\t// non-issue. Formatting wouldn't really need a\n\t\t// FileSet at all.\n\n\t\tvar out bytes.Buffer\n\t\tif elideBraces {\n\t\t\tfor i, stmt := range res.new.(*ast.BlockStmt).List {\n\t\t\t\tif i > 0 {\n\t\t\t\t\tout.WriteByte('\\n')\n\t\t\t\t}\n\t\t\t\tif err := format.Node(&out, caller.Fset, stmt); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif err := format.Node(&out, caller.Fset, res.new); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\tedits = append(edits, refactor.Edit{\n\t\t\tPos:     res.old.Pos(),\n\t\t\tEnd:     res.old.End(),\n\t\t\tNewText: out.Bytes(),\n\t\t})\n\t}\n\n\t// Add new imports.\n\t//\n\t// It's possible that not all are needed (e.g. for type names\n\t// that melted away), but we'll let the client (such as an\n\t// analysis driver) clean it up since it must remove unused\n\t// imports anyway.\n\tfor _, imp := range res.newImports {\n\t\t// Check that the new imports are accessible.\n\t\tif !packagepath.CanImport(caller.Types.Path(), imp.path) {\n\t\t\treturn nil, fmt.Errorf(\"can't inline function %v as its body refers to inaccessible package %q\", callee, imp.path)\n\t\t}\n\n\t\t// We've already validated the import, so we call\n\t\t// AddImportEdits directly to compute the edit.\n\t\tname := \"\"\n\t\tif imp.explicit {\n\t\t\tname = imp.name\n\t\t}\n\t\tedits = append(edits, refactor.AddImportEdits(caller.File, name, imp.path)...)\n\t}\n\n\tliteralized := false\n\tif call, ok := res.new.(*ast.CallExpr); ok && is[*ast.FuncLit](call.Fun) {\n\t\tliteralized = true\n\t}\n\n\t// Delete imports referenced only by caller.Call.Fun.\n\t//\n\t// It's ambiguous to let the client (e.g. analysis driver)\n\t// remove unneeded imports in this case because it is common\n\t// to inlining a call from \"dir1/a\".F to \"dir2/a\".F, which\n\t// leaves two imports of packages named 'a', both providing a.F.\n\t//\n\t// However, the only two import deletion tools at our disposal\n\t// are astutil.DeleteNamedImport, which mutates the AST, and\n\t// refactor.Delete{Spec,Decl}, which need a Cursor. So we need\n\t// to reinvent the wheel here.\n\tfor _, oldImport := range res.oldImports {\n\t\tspec := oldImport.spec\n\n\t\t// Include adjacent comments.\n\t\tpos := spec.Pos()\n\t\tif doc := spec.Doc; doc != nil {\n\t\t\tpos = doc.Pos()\n\t\t}\n\t\tend := spec.End()\n\t\tif doc := spec.Comment; doc != nil {\n\t\t\tend = doc.End()\n\t\t}\n\n\t\t// Find the enclosing import decl.\n\t\t// If it's paren-less, we must delete it too.\n\t\tfor _, decl := range caller.File.Decls {\n\t\t\tdecl, ok := decl.(*ast.GenDecl)\n\t\t\tif !(ok && decl.Tok == token.IMPORT) {\n\t\t\t\tbreak // stop at first non-import decl\n\t\t\t}\n\t\t\tif internalastutil.NodeContainsPos(decl, spec.Pos()) && !decl.Rparen.IsValid() {\n\t\t\t\t// Include adjacent comments.\n\t\t\t\tpos = decl.Pos()\n\t\t\t\tif doc := decl.Doc; doc != nil {\n\t\t\t\t\tpos = doc.Pos()\n\t\t\t\t}\n\t\t\t\tend = decl.End()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tedits = append(edits, refactor.Edit{\n\t\t\tPos: pos,\n\t\t\tEnd: end,\n\t\t})\n\t}\n\n\treturn &Result{\n\t\tEdits:       edits,\n\t\tLiteralized: literalized,\n\t\tBindingDecl: res.bindingDecl,\n\t}, nil\n}\n\n// An oldImport is an import that will be deleted from the caller file.\ntype oldImport struct {\n\tpkgName *types.PkgName\n\tspec    *ast.ImportSpec\n}\n\n// A newImport is an import that will be added to the caller file.\ntype newImport struct {\n\tname     string\n\tpath     string\n\texplicit bool // use name as ImportSpec.Name\n}\n\n// importState tracks information about imports.\ntype importState struct {\n\tlogf       func(string, ...any)\n\tcaller     *Caller\n\timportMap  map[string][]string // from package paths in the caller's file to local names\n\tnewImports []newImport         // for references to free names in callee; to be added to the file\n\toldImports []oldImport         // referenced only by caller.Call.Fun; to be removed from the file\n}\n\n// newImportState returns an importState with initial information about the caller's imports.\nfunc newImportState(logf func(string, ...any), caller *Caller, callee *gobCallee) *importState {\n\t// For simplicity we ignore existing dot imports, so that a qualified\n\t// identifier (QI) in the callee is always represented by a QI in the caller,\n\t// allowing us to treat a QI like a selection on a package name.\n\tist := &importState{\n\t\tlogf:      logf,\n\t\tcaller:    caller,\n\t\timportMap: make(map[string][]string),\n\t}\n\n\t// Provide an inefficient default implementation of CountUses.\n\t// (Ideally clients amortize this for the entire package.)\n\tcountUses := caller.CountUses\n\tif countUses == nil {\n\t\tuses := make(map[*types.PkgName]int)\n\t\tfor _, obj := range caller.Info.Uses {\n\t\t\tif pkgname, ok := obj.(*types.PkgName); ok {\n\t\t\t\tuses[pkgname]++\n\t\t\t}\n\t\t}\n\t\tcountUses = func(pkgname *types.PkgName) int {\n\t\t\treturn uses[pkgname]\n\t\t}\n\t}\n\n\tfor _, imp := range caller.File.Imports {\n\t\tif pkgName, ok := importedPkgName(caller.Info, imp); ok &&\n\t\t\tpkgName.Name() != \".\" &&\n\t\t\tpkgName.Name() != \"_\" {\n\n\t\t\t// If the import's sole use is in caller.Call.Fun of the form p.F(...),\n\t\t\t// where p.F is a qualified identifier, the p import may not be\n\t\t\t// necessary.\n\t\t\t//\n\t\t\t// Only the qualified identifier case matters, as other references to\n\t\t\t// imported package names in the Call.Fun expression (e.g.\n\t\t\t// x.after(3*time.Second).f() or time.Second.String()) will remain after\n\t\t\t// inlining, as arguments.\n\t\t\t//\n\t\t\t// If that is the case, proactively check if any of the callee FreeObjs\n\t\t\t// need this import. Doing so eagerly simplifies the resulting logic.\n\t\t\tneeded := true\n\t\t\tif sel, ok := ast.Unparen(caller.Call.Fun).(*ast.SelectorExpr); ok &&\n\t\t\t\tis[*ast.Ident](sel.X) &&\n\t\t\t\tcaller.Info.Uses[sel.X.(*ast.Ident)] == pkgName &&\n\t\t\t\tcountUses(pkgName) == 1 {\n\t\t\t\tneeded = false // no longer needed by caller\n\t\t\t\t// Check to see if any of the inlined free objects need this package.\n\t\t\t\tfor _, obj := range callee.FreeObjs {\n\t\t\t\t\tif obj.PkgPath == pkgName.Imported().Path() && obj.Shadow[pkgName.Name()] == 0 {\n\t\t\t\t\t\tneeded = true // needed by callee\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Exclude imports not needed by the caller or callee after inlining; the second\n\t\t\t// return value holds these.\n\t\t\tif needed {\n\t\t\t\tpath := pkgName.Imported().Path()\n\t\t\t\tist.importMap[path] = append(ist.importMap[path], pkgName.Name())\n\t\t\t} else {\n\t\t\t\tist.oldImports = append(ist.oldImports, oldImport{pkgName: pkgName, spec: imp})\n\t\t\t}\n\t\t}\n\t}\n\treturn ist\n}\n\n// importName finds an existing import name to use in a particular shadowing\n// context. It is used to determine the set of new imports in\n// localName, and is also used for writing out names in inlining\n// strategies below.\nfunc (i *importState) importName(pkgPath string, shadow shadowMap) string {\n\tfor _, name := range i.importMap[pkgPath] {\n\t\t// Check that either the import preexisted, or that it was newly added\n\t\t// (no PkgName) but is not shadowed, either in the callee (shadows) or\n\t\t// caller (caller.lookup).\n\t\tif shadow[name] == 0 {\n\t\t\tfound := i.caller.lookup(name)\n\t\t\tif is[*types.PkgName](found) || found == nil {\n\t\t\t\treturn name\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// findNewLocalName returns a new local package name to use in a particular shadowing context.\n// It considers the existing local name used by the callee, or construct a new local name\n// based on the package name.\nfunc (i *importState) findNewLocalName(pkgName, calleePkgName string, shadow shadowMap) string {\n\tnewlyAdded := func(name string) bool {\n\t\treturn slices.ContainsFunc(i.newImports, func(n newImport) bool { return n.name == name })\n\t}\n\n\t// shadowedInCaller reports whether a candidate package name\n\t// already refers to a declaration in the caller.\n\tshadowedInCaller := func(name string) bool {\n\t\tobj := i.caller.lookup(name)\n\t\tif obj == nil {\n\t\t\treturn false\n\t\t}\n\t\t// If obj will be removed, the name is available.\n\t\treturn !slices.ContainsFunc(i.oldImports, func(o oldImport) bool { return o.pkgName == obj })\n\t}\n\n\t// import added by callee\n\t//\n\t// Try to preserve the local package name used by the callee first.\n\t//\n\t// If that is shadowed, choose a local package name based on last segment of\n\t// package path plus, if needed, a numeric suffix to ensure uniqueness.\n\t//\n\t// \"init\" is not a legal PkgName.\n\tif shadow[calleePkgName] == 0 && !shadowedInCaller(calleePkgName) && !newlyAdded(calleePkgName) && calleePkgName != \"init\" {\n\t\treturn calleePkgName\n\t}\n\n\tbase := pkgName\n\tname := base\n\tfor n := 0; shadow[name] != 0 || shadowedInCaller(name) || newlyAdded(name) || name == \"init\"; n++ {\n\t\tname = fmt.Sprintf(\"%s%d\", base, n)\n\t}\n\n\treturn name\n}\n\n// localName returns the local name for a given imported package path,\n// adding one if it doesn't exists.\nfunc (i *importState) localName(pkgPath, pkgName, calleePkgName string, shadow shadowMap) string {\n\t// Does an import already exist that works in this shadowing context?\n\tif name := i.importName(pkgPath, shadow); name != \"\" {\n\t\treturn name\n\t}\n\n\tname := i.findNewLocalName(pkgName, calleePkgName, shadow)\n\ti.logf(\"adding import %s %q\", name, pkgPath)\n\t// Use explicit pkgname (out of necessity) when it differs from the declared name,\n\t// or (for good style) when it differs from base(pkgpath).\n\ti.newImports = append(i.newImports, newImport{\n\t\tname:     name,\n\t\tpath:     pkgPath,\n\t\texplicit: name != pkgName || name != pathpkg.Base(pkgPath),\n\t})\n\ti.importMap[pkgPath] = append(i.importMap[pkgPath], name)\n\treturn name\n}\n\ntype inlineCallResult struct {\n\tnewImports []newImport // to add\n\toldImports []oldImport // to remove\n\n\t// If elideBraces is set, old is an ast.Stmt and new is an ast.BlockStmt to\n\t// be spliced in. This allows the inlining analysis to assert that inlining\n\t// the block is OK; if elideBraces is unset and old is an ast.Stmt and new is\n\t// an ast.BlockStmt, braces may still be elided if the post-processing\n\t// analysis determines that it is safe to do so.\n\t//\n\t// Ideally, it would not be necessary for the inlining analysis to \"reach\n\t// through\" to the post-processing pass in this way. Instead, inlining could\n\t// just set old to be an ast.BlockStmt and rewrite the entire BlockStmt, but\n\t// unfortunately in order to preserve comments, it is important that inlining\n\t// replace as little syntax as possible.\n\telideBraces bool\n\tbindingDecl bool     // transformation inserted \"var params = args\" declaration\n\told, new    ast.Node // e.g. replace call expr by callee function body expression\n}\n\n// inlineCall returns a pair of an old node (the call, or something\n// enclosing it) and a new node (its replacement, which may be a\n// combination of caller, callee, and new nodes), along with the set\n// of new imports needed.\n//\n// TODO(adonovan): rethink the 'result' interface. The assumption of a\n// one-to-one replacement seems fragile. One can easily imagine the\n// transformation replacing the call and adding new variable\n// declarations, for example, or replacing a call statement by zero or\n// many statements.)\n// NOTE(rfindley): we've sort-of done this, with the 'elideBraces' flag that\n// allows inlining a statement list. However, due to loss of comments, more\n// sophisticated rewrites are challenging.\n//\n// TODO(rfindley): see if we can reduce the amount of comment lossiness by\n// using printer.CommentedNode, which has been useful elsewhere.\n//\n// TODO(rfindley): inlineCall is getting very long, and very stateful, making\n// it very hard to read. The following refactoring may improve readability and\n// maintainability:\n//   - Rename 'state' to 'callsite', since that is what it encapsulates.\n//   - Add results of pre-processing analysis into the callsite struct, such as\n//     the effective importMap, new/old imports, arguments, etc. Essentially\n//     anything that resulted from initial analysis of the call site, and which\n//     may be useful to inlining strategies.\n//   - Delegate this call site analysis to a constructor or initializer, such\n//     as 'analyzeCallsite', so that it does not consume bandwidth in the\n//     'inlineCall' logical flow.\n//   - Once analyzeCallsite returns, the callsite is immutable, much in the\n//     same way as the Callee and Caller are immutable.\n//   - Decide on a standard interface for strategies (and substrategies), such\n//     that they may be delegated to a separate method on callsite.\n//\n// In this way, the logical flow of inline call will clearly follow the\n// following structure:\n//  1. Analyze the call site.\n//  2. Try strategies, in order, until one succeeds.\n//  3. Process the results.\n//\n// If any expensive analysis may be avoided by earlier strategies, it can be\n// encapsulated in its own type and passed to subsequent strategies.\nfunc (st *state) inlineCall() (*inlineCallResult, error) {\n\tlogf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl\n\n\tcheckInfoFields(caller.Info)\n\n\t// Inlining of dynamic calls is not currently supported,\n\t// even for local closure calls. (This would be a lot of work.)\n\tcalleeSymbol := typeutil.StaticCallee(caller.Info, caller.Call)\n\tif calleeSymbol == nil {\n\t\t// e.g. interface method\n\t\treturn nil, fmt.Errorf(\"cannot inline: not a static function call\")\n\t}\n\n\t// Reject cross-package inlining if callee has\n\t// free references to unexported symbols.\n\tsamePkg := caller.Types.Path() == callee.PkgPath\n\tif !samePkg && len(callee.Unexported) > 0 {\n\t\treturn nil, fmt.Errorf(\"cannot inline call to %s because body refers to non-exported %s\",\n\t\t\tcallee.Name, callee.Unexported[0])\n\t}\n\n\t// Reject cross-file inlining if callee requires a newer dialect of Go (#75726).\n\t// (Versions default to types.Config.GoVersion, which is unset in many tests,\n\t// though should be populated by an analysis driver.)\n\tcallerGoVersion := caller.Info.FileVersions[caller.File]\n\tif callerGoVersion != \"\" && callee.GoVersion != \"\" && versions.Before(callerGoVersion, callee.GoVersion) {\n\t\treturn nil, fmt.Errorf(\"cannot inline call to %s (declared using %s) into a file using %s\",\n\t\t\tcallee.Name, callee.GoVersion, callerGoVersion)\n\t}\n\n\t// -- analyze callee's free references in caller context --\n\n\t// Compute syntax path enclosing Call, innermost first (Path[0]=Call),\n\t// and outermost enclosing function, if any.\n\tcaller.path, _ = astutil.PathEnclosingInterval(caller.File, caller.Call.Pos(), caller.Call.End())\n\tfor _, n := range caller.path {\n\t\tif decl, ok := n.(*ast.FuncDecl); ok {\n\t\t\tcaller.enclosingFunc = decl\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// If call is within a function, analyze all its\n\t// local vars for the \"single assignment\" property.\n\t// (Taking the address &v counts as a potential assignment.)\n\tvar assign1 func(v *types.Var) bool // reports whether v a single-assignment local var\n\t{\n\t\tupdatedLocals := make(map[*types.Var]bool)\n\t\tif caller.enclosingFunc != nil {\n\t\t\tescape(caller.Info, caller.enclosingFunc, func(v *types.Var, _ bool) {\n\t\t\t\tupdatedLocals[v] = true\n\t\t\t})\n\t\t\tlogf(\"multiple-assignment vars: %v\", updatedLocals)\n\t\t}\n\t\tassign1 = func(v *types.Var) bool { return !updatedLocals[v] }\n\t}\n\n\t// Extract information about the caller's imports.\n\tistate := newImportState(logf, caller, callee)\n\n\t// Compute the renaming of the callee's free identifiers.\n\tobjRenames, err := st.renameFreeObjs(istate)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tres := &inlineCallResult{\n\t\tnewImports: istate.newImports,\n\t\toldImports: istate.oldImports,\n\t}\n\n\t// Parse callee function declaration.\n\tcalleeFset, calleeDecl, err := parseCompact(callee.Content)\n\tif err != nil {\n\t\treturn nil, err // \"can't happen\"\n\t}\n\n\t// replaceCalleeID replaces an identifier in the callee. See [replacer] for\n\t// more detailed semantics.\n\treplaceCalleeID := func(offset int, repl ast.Expr, unpackVariadic bool) {\n\t\tpath, id := findIdent(calleeDecl, calleeDecl.Pos()+token.Pos(offset))\n\t\tlogf(\"- replace id %q @ #%d to %q\", id.Name, offset, debugFormatNode(calleeFset, repl))\n\t\t// Replace f([]T{a, b, c}...) with f(a, b, c).\n\t\tif lit, ok := repl.(*ast.CompositeLit); ok && unpackVariadic && len(path) > 0 {\n\t\t\tif call, ok := last(path).(*ast.CallExpr); ok &&\n\t\t\t\tcall.Ellipsis.IsValid() &&\n\t\t\t\tid == last(call.Args) {\n\n\t\t\t\tcall.Args = append(call.Args[:len(call.Args)-1], lit.Elts...)\n\t\t\t\tcall.Ellipsis = token.NoPos\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\treplaceNode(calleeDecl, id, repl)\n\t}\n\n\t// Generate replacements for each free identifier.\n\t// (The same tree may be spliced in multiple times, resulting in a DAG.)\n\tfor _, ref := range callee.FreeRefs {\n\t\tif repl := objRenames[ref.Object]; repl != nil {\n\t\t\treplaceCalleeID(ref.Offset, repl, false)\n\t\t}\n\t}\n\n\t// Gather the effective call arguments, including the receiver.\n\t// Later, elements will be eliminated (=> nil) by parameter substitution.\n\targs, err := st.arguments(caller, calleeDecl, assign1)\n\tif err != nil {\n\t\treturn nil, err // e.g. implicit field selection cannot be made explicit\n\t}\n\n\t// Gather effective parameter tuple, including the receiver if any.\n\t// Simplify variadic parameters to slices (in all cases but one).\n\tvar params []*parameter // including receiver; nil => parameter substituted\n\t{\n\t\tsig := calleeSymbol.Type().(*types.Signature)\n\t\tif sig.Recv() != nil {\n\t\t\tparams = append(params, &parameter{\n\t\t\t\tobj:       sig.Recv(),\n\t\t\t\tfieldType: calleeDecl.Recv.List[0].Type,\n\t\t\t\tinfo:      callee.Params[0],\n\t\t\t})\n\t\t}\n\n\t\t// Flatten the list of syntactic types.\n\t\tvar types []ast.Expr\n\t\tfor _, field := range calleeDecl.Type.Params.List {\n\t\t\tif field.Names == nil {\n\t\t\t\ttypes = append(types, field.Type)\n\t\t\t} else {\n\t\t\t\tfor range field.Names {\n\t\t\t\t\ttypes = append(types, field.Type)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\t\tparams = append(params, &parameter{\n\t\t\t\tobj:       sig.Params().At(i),\n\t\t\t\tfieldType: types[i],\n\t\t\t\tinfo:      callee.Params[len(params)],\n\t\t\t})\n\t\t}\n\n\t\t// Variadic function?\n\t\t//\n\t\t// There are three possible types of call:\n\t\t// - ordinary f(a1, ..., aN)\n\t\t// - ellipsis f(a1, ..., slice...)\n\t\t// - spread   f(recv?, g()) where g() is a tuple.\n\t\t// The first two are desugared to non-variadic calls\n\t\t// with an ordinary slice parameter;\n\t\t// the third is tricky and cannot be reduced, and (if\n\t\t// a receiver is present) cannot even be literalized.\n\t\t// Fortunately it is vanishingly rare.\n\t\t//\n\t\t// TODO(adonovan): extract this to a function.\n\t\tif sig.Variadic() {\n\t\t\tlastParam := last(params)\n\t\t\tif len(args) > 0 && last(args).spread {\n\t\t\t\t// spread call to variadic: tricky\n\t\t\t\tlastParam.variadic = true\n\t\t\t} else {\n\t\t\t\t// ordinary/ellipsis call to variadic\n\n\t\t\t\t// simplify decl: func(T...) -> func([]T)\n\t\t\t\tlastParamField := last(calleeDecl.Type.Params.List)\n\t\t\t\tlastParamField.Type = &ast.ArrayType{\n\t\t\t\t\tElt: lastParamField.Type.(*ast.Ellipsis).Elt,\n\t\t\t\t}\n\n\t\t\t\tif caller.Call.Ellipsis.IsValid() {\n\t\t\t\t\t// ellipsis call: f(slice...) -> f(slice)\n\t\t\t\t\t// nop\n\t\t\t\t} else {\n\t\t\t\t\t// ordinary call: f(a1, ... aN) -> f([]T{a1, ..., aN})\n\t\t\t\t\t//\n\t\t\t\t\t// Substitution of []T{...} in the callee body may lead to\n\t\t\t\t\t// g([]T{a1, ..., aN}...), which we simplify to g(a1, ..., an)\n\t\t\t\t\t// later; see replaceCalleeID.\n\t\t\t\t\tn := len(params) - 1\n\t\t\t\t\tordinary, extra := args[:n], args[n:]\n\t\t\t\t\tvar elts []ast.Expr\n\t\t\t\t\tfreevars := make(map[string]bool)\n\t\t\t\t\tpure, effects := true, false\n\t\t\t\t\tfor _, arg := range extra {\n\t\t\t\t\t\telts = append(elts, arg.expr)\n\t\t\t\t\t\tpure = pure && arg.pure\n\t\t\t\t\t\teffects = effects || arg.effects\n\t\t\t\t\t\tmaps.Copy(freevars, arg.freevars)\n\t\t\t\t\t}\n\t\t\t\t\targs = append(ordinary, &argument{\n\t\t\t\t\t\texpr: &ast.CompositeLit{\n\t\t\t\t\t\t\tType: lastParamField.Type,\n\t\t\t\t\t\t\tElts: elts,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttyp:        lastParam.obj.Type(),\n\t\t\t\t\t\tconstant:   nil,\n\t\t\t\t\t\tpure:       pure,\n\t\t\t\t\t\teffects:    effects,\n\t\t\t\t\t\tduplicable: false,\n\t\t\t\t\t\tfreevars:   freevars,\n\t\t\t\t\t\tvariadic:   true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttypeArgs := st.typeArguments(caller.Call)\n\tif len(typeArgs) != len(callee.TypeParams) {\n\t\treturn nil, fmt.Errorf(\"cannot inline: type parameter inference is not yet supported\")\n\t}\n\tif err := substituteTypeParams(logf, callee.TypeParams, typeArgs, params, replaceCalleeID); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Log effective arguments.\n\tfor i, arg := range args {\n\t\tlogf(\"arg #%d: %s pure=%t effects=%t duplicable=%t free=%v type=%v\",\n\t\t\ti, debugFormatNode(caller.Fset, arg.expr),\n\t\t\targ.pure, arg.effects, arg.duplicable, arg.freevars, arg.typ)\n\t}\n\n\t// Note: computation below should be expressed in terms of\n\t// the args and params slices, not the raw material.\n\n\t// Perform parameter substitution.\n\t// May eliminate some elements of params/args.\n\tsubstitute(logf, caller, params, args, callee.Effects, callee.Falcon, replaceCalleeID)\n\n\t// Update the callee's signature syntax.\n\tupdateCalleeParams(calleeDecl, params)\n\n\t// Create a var (param = arg; ...) decl for use by some strategies.\n\tbindingDecl := createBindingDecl(logf, caller, args, calleeDecl, callee.Results)\n\n\tvar remainingArgs []ast.Expr\n\tfor _, arg := range args {\n\t\tif arg != nil {\n\t\t\tremainingArgs = append(remainingArgs, arg.expr)\n\t\t}\n\t}\n\n\t// -- let the inlining strategies begin --\n\t//\n\t// When we commit to a strategy, we log a message of the form:\n\t//\n\t//   \"strategy: reduce expr-context call to { return expr }\"\n\t//\n\t// This is a terse way of saying:\n\t//\n\t//    we plan to reduce a call\n\t//    that appears in expression context\n\t//    to a function whose body is of the form { return expr }\n\n\t// TODO(adonovan): split this huge function into a sequence of\n\t// function calls with an error sentinel that means \"try the\n\t// next strategy\", and make sure each strategy writes to the\n\t// log the reason it didn't match.\n\n\t// Special case: eliminate a call to a function whose body is empty.\n\t// (=> callee has no results and caller is a statement.)\n\t//\n\t//    func f(params) {}\n\t//    f(args)\n\t//    => _, _ = args\n\t//\n\tif len(calleeDecl.Body.List) == 0 {\n\t\tlogf(\"strategy: reduce call to empty body\")\n\n\t\t// Evaluate the arguments for effects and delete the call entirely.\n\t\t// Note(golang/go#71486): stmt can be nil if the call is in a go or defer\n\t\t// statement.\n\t\t// TODO: discard go or defer statements as well.\n\t\tif stmt := callStmt(caller.path, false); stmt != nil {\n\t\t\tres.old = stmt\n\t\t\tif nargs := len(remainingArgs); nargs > 0 {\n\t\t\t\t// Emit \"_, _ = args\" to discard results.\n\n\t\t\t\t// TODO(adonovan): if args is the []T{a1, ..., an}\n\t\t\t\t// literal synthesized during variadic simplification,\n\t\t\t\t// consider unwrapping it to its (pure) elements.\n\t\t\t\t// Perhaps there's no harm doing this for any slice literal.\n\n\t\t\t\t// Make correction for spread calls\n\t\t\t\t// f(g()) or recv.f(g()) where g() is a tuple.\n\t\t\t\tif last := last(args); last != nil && last.spread {\n\t\t\t\t\tnspread := last.typ.(*types.Tuple).Len()\n\t\t\t\t\tif len(args) > 1 { // [recv, g()]\n\t\t\t\t\t\t// A single AssignStmt cannot discard both, so use a 2-spec var decl.\n\t\t\t\t\t\tres.new = &ast.GenDecl{\n\t\t\t\t\t\t\tTok: token.VAR,\n\t\t\t\t\t\t\tSpecs: []ast.Spec{\n\t\t\t\t\t\t\t\t&ast.ValueSpec{\n\t\t\t\t\t\t\t\t\tNames:  []*ast.Ident{makeIdent(\"_\")},\n\t\t\t\t\t\t\t\t\tValues: []ast.Expr{args[0].expr},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t&ast.ValueSpec{\n\t\t\t\t\t\t\t\t\tNames:  blanks[*ast.Ident](nspread),\n\t\t\t\t\t\t\t\t\tValues: []ast.Expr{args[1].expr},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn res, nil\n\t\t\t\t\t}\n\n\t\t\t\t\t// Sole argument is spread call.\n\t\t\t\t\tnargs = nspread\n\t\t\t\t}\n\n\t\t\t\tres.new = &ast.AssignStmt{\n\t\t\t\t\tLhs: blanks[ast.Expr](nargs),\n\t\t\t\t\tTok: token.ASSIGN,\n\t\t\t\t\tRhs: remainingArgs,\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// No remaining arguments: delete call statement entirely\n\t\t\t\tres.new = &ast.EmptyStmt{}\n\t\t\t}\n\t\t\treturn res, nil\n\t\t}\n\t}\n\n\t// If all parameters have been substituted and no result\n\t// variable is referenced, we don't need a binding decl.\n\t// This may enable better reduction strategies.\n\tallResultsUnreferenced := forall(callee.Results, func(i int, r *paramInfo) bool { return len(r.Refs) == 0 })\n\tneedBindingDecl := !allResultsUnreferenced ||\n\t\texists(params, func(i int, p *parameter) bool { return p != nil })\n\n\t// The two strategies below overlap for a tail call of {return exprs}:\n\t// The expr-context reduction is nice because it keeps the\n\t// caller's return stmt and merely switches its operand,\n\t// without introducing a new block, but it doesn't work with\n\t// implicit return conversions.\n\t//\n\t// TODO(adonovan): unify these cases more cleanly, allowing return-\n\t// operand replacement and implicit conversions, by adding\n\t// conversions around each return operand (if not a spread return).\n\n\t// Special case: call to { return exprs }.\n\t//\n\t// Reduces to:\n\t//\t    { var (bindings); _, _ = exprs }\n\t//     or   _, _ = exprs\n\t//     or   expr\n\t//\n\t// If:\n\t// - the body is just \"return expr\" with trivial implicit conversions,\n\t//   or the caller's return type matches the callee's,\n\t// - all parameters and result vars can be eliminated\n\t//   or replaced by a binding decl,\n\t// then the call expression can be replaced by the\n\t// callee's body expression, suitably substituted.\n\tif len(calleeDecl.Body.List) == 1 &&\n\t\tis[*ast.ReturnStmt](calleeDecl.Body.List[0]) &&\n\t\tlen(calleeDecl.Body.List[0].(*ast.ReturnStmt).Results) > 0 { // not a bare return\n\t\tresults := calleeDecl.Body.List[0].(*ast.ReturnStmt).Results\n\n\t\tparent, grandparent := callContext(caller.path)\n\n\t\t// statement context\n\t\tif stmt, ok := parent.(*ast.ExprStmt); ok &&\n\t\t\t(!needBindingDecl || bindingDecl != nil) {\n\t\t\tlogf(\"strategy: reduce stmt-context call to { return exprs }\")\n\t\t\tclearPositions(calleeDecl.Body)\n\n\t\t\tif callee.ValidForCallStmt {\n\t\t\t\tlogf(\"callee body is valid as statement\")\n\t\t\t\t// Inv: len(results) == 1\n\t\t\t\tif !needBindingDecl {\n\t\t\t\t\t// Reduces to: expr\n\t\t\t\t\tres.old = caller.Call\n\t\t\t\t\tres.new = results[0]\n\t\t\t\t} else {\n\t\t\t\t\t// Reduces to: { var (bindings); expr }\n\t\t\t\t\tres.bindingDecl = true\n\t\t\t\t\tres.old = stmt\n\t\t\t\t\tres.new = &ast.BlockStmt{\n\t\t\t\t\t\tList: []ast.Stmt{\n\t\t\t\t\t\t\tbindingDecl.stmt,\n\t\t\t\t\t\t\t&ast.ExprStmt{X: results[0]},\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogf(\"callee body is not valid as statement\")\n\t\t\t\t// The call is a standalone statement, but the\n\t\t\t\t// callee body is not suitable as a standalone statement\n\t\t\t\t// (f() or <-ch), explicitly discard the results:\n\t\t\t\t// Reduces to: _, _ = exprs\n\t\t\t\tdiscard := &ast.AssignStmt{\n\t\t\t\t\tLhs: blanks[ast.Expr](callee.NumResults),\n\t\t\t\t\tTok: token.ASSIGN,\n\t\t\t\t\tRhs: results,\n\t\t\t\t}\n\t\t\t\tres.old = stmt\n\t\t\t\tif !needBindingDecl {\n\t\t\t\t\t// Reduces to: _, _ = exprs\n\t\t\t\t\tres.new = discard\n\t\t\t\t} else {\n\t\t\t\t\t// Reduces to: { var (bindings); _, _ = exprs }\n\t\t\t\t\tres.bindingDecl = true\n\t\t\t\t\tres.new = &ast.BlockStmt{\n\t\t\t\t\t\tList: []ast.Stmt{\n\t\t\t\t\t\t\tbindingDecl.stmt,\n\t\t\t\t\t\t\tdiscard,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res, nil\n\t\t}\n\n\t\t// Assignment context.\n\t\t//\n\t\t// If there is no binding decl, or if the binding decl declares no names,\n\t\t// an assignment a, b := f() can be reduced to a, b := x, y.\n\t\tif stmt, ok := parent.(*ast.AssignStmt); ok &&\n\t\t\tis[*ast.BlockStmt](grandparent) &&\n\t\t\t(!needBindingDecl || (bindingDecl != nil && len(bindingDecl.names) == 0)) {\n\n\t\t\t// Reduces to: { var (bindings); lhs... := rhs... }\n\t\t\tif newStmts, ok := st.assignStmts(stmt, results, istate.importName); ok {\n\t\t\t\tlogf(\"strategy: reduce assign-context call to { return exprs }\")\n\n\t\t\t\tclearPositions(calleeDecl.Body)\n\n\t\t\t\tblock := &ast.BlockStmt{\n\t\t\t\t\tList: newStmts,\n\t\t\t\t}\n\t\t\t\tif needBindingDecl {\n\t\t\t\t\tres.bindingDecl = true\n\t\t\t\t\tblock.List = prepend(bindingDecl.stmt, block.List...)\n\t\t\t\t}\n\n\t\t\t\t// assignStmts does not introduce new bindings, and replacing an\n\t\t\t\t// assignment only works if the replacement occurs in the same scope.\n\t\t\t\t// Therefore, we must ensure that braces are elided.\n\t\t\t\tres.elideBraces = true\n\t\t\t\tres.old = stmt\n\t\t\t\tres.new = block\n\t\t\t\treturn res, nil\n\t\t\t}\n\t\t}\n\n\t\t// expression context\n\t\tif !needBindingDecl {\n\t\t\tclearPositions(calleeDecl.Body)\n\n\t\t\tanyNonTrivialReturns := hasNonTrivialReturn(callee.Returns)\n\n\t\t\tif callee.NumResults == 1 {\n\t\t\t\tlogf(\"strategy: reduce expr-context call to { return expr }\")\n\t\t\t\t// (includes some simple tail-calls)\n\n\t\t\t\t// Make implicit return conversion explicit.\n\t\t\t\tif anyNonTrivialReturns {\n\t\t\t\t\tresults[0] = convert(calleeDecl.Type.Results.List[0].Type, results[0])\n\t\t\t\t}\n\n\t\t\t\tres.old = caller.Call\n\t\t\t\tres.new = results[0]\n\t\t\t\treturn res, nil\n\n\t\t\t} else if !anyNonTrivialReturns {\n\t\t\t\tlogf(\"strategy: reduce spread-context call to { return expr }\")\n\t\t\t\t// There is no general way to reify conversions in a spread\n\t\t\t\t// return, hence the requirement above.\n\t\t\t\t//\n\t\t\t\t// TODO(adonovan): allow this reduction when no\n\t\t\t\t// conversion is required by the context.\n\n\t\t\t\t// The call returns multiple results but is\n\t\t\t\t// not a standalone call statement. It must\n\t\t\t\t// be the RHS of a spread assignment:\n\t\t\t\t//   var x, y  = f()\n\t\t\t\t//       x, y := f()\n\t\t\t\t//       x, y  = f()\n\t\t\t\t// or the sole argument to a spread call:\n\t\t\t\t//        printf(f())\n\t\t\t\t// or spread return statement:\n\t\t\t\t//        return f()\n\t\t\t\tres.old = parent\n\t\t\t\tswitch context := parent.(type) {\n\t\t\t\tcase *ast.AssignStmt:\n\t\t\t\t\t// Inv: the call must be in Rhs[0], not Lhs.\n\t\t\t\t\tassign := shallowCopy(context)\n\t\t\t\t\tassign.Rhs = results\n\t\t\t\t\tres.new = assign\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\t// Inv: the call must be in Values[0], not Names.\n\t\t\t\t\tspec := shallowCopy(context)\n\t\t\t\t\tspec.Values = results\n\t\t\t\t\tres.new = spec\n\t\t\t\tcase *ast.CallExpr:\n\t\t\t\t\t// Inv: the call must be in Args[0], not Fun.\n\t\t\t\t\tcall := shallowCopy(context)\n\t\t\t\t\tcall.Args = results\n\t\t\t\t\tres.new = call\n\t\t\t\tcase *ast.ReturnStmt:\n\t\t\t\t\t// Inv: the call must be Results[0].\n\t\t\t\t\tret := shallowCopy(context)\n\t\t\t\t\tret.Results = results\n\t\t\t\t\tres.new = ret\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, fmt.Errorf(\"internal error: unexpected context %T for spread call\", context)\n\t\t\t\t}\n\t\t\t\treturn res, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Special case: tail-call.\n\t//\n\t// Inlining:\n\t//         return f(args)\n\t// where:\n\t//         func f(params) (results) { body }\n\t// reduces to:\n\t//         { var (bindings); body }\n\t//         { body }\n\t// so long as:\n\t// - all parameters can be eliminated or replaced by a binding decl,\n\t// - call is a tail-call;\n\t// - all returns in body have trivial result conversions,\n\t//   or the caller's return type matches the callee's,\n\t// - there is no label conflict;\n\t// - no result variable is referenced by name,\n\t//   or implicitly by a bare return.\n\t//\n\t// The body may use defer, arbitrary control flow, and\n\t// multiple returns.\n\t//\n\t// TODO(adonovan): add a strategy for a 'void tail\n\t// call', i.e. a call statement prior to an (explicit\n\t// or implicit) return.\n\tparent, _ := callContext(caller.path)\n\tif ret, ok := parent.(*ast.ReturnStmt); ok &&\n\t\tlen(ret.Results) == 1 &&\n\t\ttailCallSafeReturn(caller, calleeSymbol, callee) &&\n\t\t!callee.HasBareReturn &&\n\t\t(!needBindingDecl || bindingDecl != nil) &&\n\t\t!hasLabelConflict(caller.path, callee.Labels) &&\n\t\tallResultsUnreferenced {\n\t\tlogf(\"strategy: reduce tail-call\")\n\t\tbody := calleeDecl.Body\n\t\tclearPositions(body)\n\t\tif needBindingDecl {\n\t\t\tres.bindingDecl = true\n\t\t\tbody.List = prepend(bindingDecl.stmt, body.List...)\n\t\t}\n\t\tres.old = ret\n\t\tres.new = body\n\t\treturn res, nil\n\t}\n\n\t// Special case: call to void function\n\t//\n\t// Inlining:\n\t//         f(args)\n\t// where:\n\t//\t   func f(params) { stmts }\n\t// reduces to:\n\t//         { var (bindings); stmts }\n\t//         { stmts }\n\t// so long as:\n\t// - callee is a void function (no returns)\n\t// - callee does not use defer\n\t// - there is no label conflict between caller and callee\n\t// - all parameters and result vars can be eliminated\n\t//   or replaced by a binding decl,\n\t// - caller ExprStmt is in unrestricted statement context.\n\tif stmt := callStmt(caller.path, true); stmt != nil &&\n\t\t(!needBindingDecl || bindingDecl != nil) &&\n\t\t!callee.HasDefer &&\n\t\t!hasLabelConflict(caller.path, callee.Labels) &&\n\t\tlen(callee.Returns) == 0 {\n\t\tlogf(\"strategy: reduce stmt-context call to { stmts }\")\n\t\tbody := calleeDecl.Body\n\t\tvar repl ast.Stmt = body\n\t\tclearPositions(repl)\n\t\tif needBindingDecl {\n\t\t\tbody.List = prepend(bindingDecl.stmt, body.List...)\n\t\t}\n\t\tres.old = stmt\n\t\tres.new = repl\n\t\treturn res, nil\n\t}\n\n\t// TODO(adonovan): parameterless call to { stmts; return expr }\n\t// from one of these contexts:\n\t//    x, y     = f()\n\t//    x, y    := f()\n\t//    var x, y = f()\n\t// =>\n\t//    var (x T1, y T2); { stmts; x, y = expr }\n\t//\n\t// Because the params are no longer declared simultaneously\n\t// we need to check that (for example) x ∉ freevars(T2),\n\t// in addition to the usual checks for arg/result conversions,\n\t// complex control, etc.\n\t// Also test cases where expr is an n-ary call (spread returns).\n\n\t// Literalization isn't quite infallible.\n\t// Consider a spread call to a method in which\n\t// no parameters are eliminated, e.g.\n\t// \tnew(T).f(g())\n\t// where\n\t//  \tfunc (recv *T) f(x, y int) { body }\n\t//  \tfunc g() (int, int)\n\t// This would be literalized to:\n\t// \tfunc (recv *T, x, y int) { body }(new(T), g()),\n\t// which is not a valid argument list because g() must appear alone.\n\t// Reject this case for now.\n\tif len(args) == 2 && args[0] != nil && args[1] != nil && is[*types.Tuple](args[1].typ) {\n\t\treturn nil, fmt.Errorf(\"can't yet inline spread call to method\")\n\t}\n\n\t// Infallible general case: literalization.\n\t//\n\t//    func(params) { body }(args)\n\t//\n\tlogf(\"strategy: literalization\")\n\tfuncLit := &ast.FuncLit{\n\t\tType: calleeDecl.Type,\n\t\tBody: calleeDecl.Body,\n\t}\n\t// clear positions before prepending the binding decl below, since the\n\t// binding decl contains syntax from the caller and we must not mutate the\n\t// caller. (This was a prior bug.)\n\tclearPositions(funcLit)\n\n\t// Literalization can still make use of a binding\n\t// decl as it gives a more natural reading order:\n\t//\n\t//    func() { var params = args; body }()\n\t//\n\t// TODO(adonovan): relax the allResultsUnreferenced requirement\n\t// by adding a parameter-only (no named results) binding decl.\n\tif bindingDecl != nil && allResultsUnreferenced {\n\t\tfuncLit.Type.Params.List = nil\n\t\tremainingArgs = nil\n\t\tres.bindingDecl = true\n\t\tfuncLit.Body.List = prepend(bindingDecl.stmt, funcLit.Body.List...)\n\t}\n\n\t// Emit a new call to a function literal in place of\n\t// the callee name, with appropriate replacements.\n\tnewCall := &ast.CallExpr{\n\t\tFun:      funcLit,\n\t\tEllipsis: token.NoPos, // f(slice...) is always simplified\n\t\tArgs:     remainingArgs,\n\t}\n\tres.old = caller.Call\n\tres.new = newCall\n\treturn res, nil\n}\n\n// renameFreeObjs computes the renaming of the callee's free identifiers.\n// It returns a slice of names (identifiers or selector expressions) corresponding\n// to the callee's free objects (gobCallee.FreeObjs).\nfunc (st *state) renameFreeObjs(istate *importState) ([]ast.Expr, error) {\n\tcaller, callee := st.caller, &st.callee.impl\n\tobjRenames := make([]ast.Expr, len(callee.FreeObjs)) // nil => no change\n\tfor i, obj := range callee.FreeObjs {\n\t\t// obj is a free object of the callee.\n\t\t//\n\t\t// Possible cases are:\n\t\t// - builtin function, type, or value (e.g. nil, zero)\n\t\t//   => check not shadowed in caller.\n\t\t// - package-level var/func/const/types\n\t\t//   => same package: check not shadowed in caller.\n\t\t//   => otherwise: import other package, form a qualified identifier.\n\t\t//      (Unexported cross-package references were rejected already.)\n\t\t// - type parameter\n\t\t//   => not yet supported\n\t\t// - pkgname\n\t\t//   => import other package and use its local name.\n\t\t//\n\t\t// There can be no free references to labels, fields, or methods.\n\n\t\t// Note that we must consider potential shadowing both\n\t\t// at the caller side (caller.lookup) and, when\n\t\t// choosing new PkgNames, within the callee (obj.shadow).\n\n\t\tvar newName ast.Expr\n\t\tif obj.Kind == \"pkgname\" {\n\t\t\t// Use locally appropriate import, creating as needed.\n\t\t\tn := istate.localName(obj.PkgPath, obj.PkgName, obj.Name, obj.Shadow)\n\t\t\tnewName = makeIdent(n) // imported package\n\t\t} else if !obj.ValidPos {\n\t\t\t// Built-in function, type, or value (e.g. nil, zero):\n\t\t\t// check not shadowed at caller.\n\t\t\tfound := caller.lookup(obj.Name) // always finds something\n\t\t\tif found.Pos().IsValid() {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot inline, because the callee refers to built-in %q, which in the caller is shadowed by a %s (declared at line %d)\",\n\t\t\t\t\tobj.Name, objectKind(found),\n\t\t\t\t\tcaller.Fset.PositionFor(found.Pos(), false).Line)\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Must be reference to package-level var/func/const/type,\n\t\t\t// since type parameters are not yet supported.\n\t\t\tqualify := false\n\t\t\tif obj.PkgPath == callee.PkgPath {\n\t\t\t\t// reference within callee package\n\t\t\t\tif caller.Types.Path() == callee.PkgPath {\n\t\t\t\t\t// Caller and callee are in same package.\n\t\t\t\t\t// Check caller has not shadowed the decl.\n\t\t\t\t\t//\n\t\t\t\t\t// This may fail if the callee is \"fake\", such as for signature\n\t\t\t\t\t// refactoring where the callee is modified to be a trivial wrapper\n\t\t\t\t\t// around the refactored signature.\n\t\t\t\t\tfound := caller.lookup(obj.Name)\n\t\t\t\t\tif found != nil && !isPkgLevel(found) {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"cannot inline, because the callee refers to %s %q, which in the caller is shadowed by a %s (declared at line %d)\",\n\t\t\t\t\t\t\tobj.Kind, obj.Name,\n\t\t\t\t\t\t\tobjectKind(found),\n\t\t\t\t\t\t\tcaller.Fset.PositionFor(found.Pos(), false).Line)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Cross-package reference.\n\t\t\t\t\tqualify = true\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Reference to a package-level declaration\n\t\t\t\t// in another package, without a qualified identifier:\n\t\t\t\t// it must be a dot import.\n\t\t\t\tqualify = true\n\t\t\t}\n\n\t\t\t// Form a qualified identifier, pkg.Name.\n\t\t\tif qualify {\n\t\t\t\tpkgName := istate.localName(obj.PkgPath, obj.PkgName, obj.PkgName, obj.Shadow)\n\t\t\t\tnewName = &ast.SelectorExpr{\n\t\t\t\t\tX:   makeIdent(pkgName),\n\t\t\t\t\tSel: makeIdent(obj.Name),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tobjRenames[i] = newName\n\t}\n\treturn objRenames, nil\n}\n\ntype argument struct {\n\texpr          ast.Expr\n\ttyp           types.Type      // may be tuple for sole non-receiver arg in spread call\n\tconstant      constant.Value  // value of argument if constant\n\tspread        bool            // final arg is call() assigned to multiple params\n\tpure          bool            // expr is pure (doesn't read variables)\n\teffects       bool            // expr has effects (updates variables)\n\tduplicable    bool            // expr may be duplicated\n\tfreevars      map[string]bool // free names of expr\n\tvariadic      bool            // is explicit []T{...} for eliminated variadic\n\tdesugaredRecv bool            // is *recv or &recv, where operator was elided\n}\n\n// typeArguments returns the type arguments of the call.\n// It only collects the arguments that are explicitly provided; it does\n// not attempt type inference.\nfunc (st *state) typeArguments(call *ast.CallExpr) []*argument {\n\tvar exprs []ast.Expr\n\tswitch d := ast.Unparen(call.Fun).(type) {\n\tcase *ast.IndexExpr:\n\t\texprs = []ast.Expr{d.Index}\n\tcase *ast.IndexListExpr:\n\t\texprs = d.Indices\n\tdefault:\n\t\t// No type  arguments\n\t\treturn nil\n\t}\n\tvar args []*argument\n\tfor _, e := range exprs {\n\t\targ := &argument{expr: e, freevars: freeVars(st.caller.Info, e)}\n\t\t// Wrap the instantiating type in parens when it's not an\n\t\t// ident or qualified ident to prevent \"if x == struct{}\"\n\t\t// parsing ambiguity, or \"T(x)\" where T = \"*int\" or \"func()\"\n\t\t// from misparsing.\n\t\t// TODO(adonovan): this fails in cases where parens are disallowed, such as\n\t\t// in the composite literal expression T{k: v}.\n\t\tif _, ok := arg.expr.(*ast.Ident); !ok {\n\t\t\targ.expr = &ast.ParenExpr{X: arg.expr}\n\t\t}\n\t\targs = append(args, arg)\n\t}\n\treturn args\n}\n\n// arguments returns the effective arguments of the call.\n//\n// If the receiver argument and parameter have\n// different pointerness, make the \"&\" or \"*\" explicit.\n//\n// Also, if x.f() is shorthand for promoted method x.y.f(),\n// make the .y explicit in T.f(x.y, ...).\n//\n// Beware that:\n//\n//   - a method can only be called through a selection, but only\n//     the first of these two forms needs special treatment:\n//\n//     expr.f(args)     -> ([&*]expr, args)\tMethodVal\n//     T.f(recv, args)  -> (    expr, args)\tMethodExpr\n//\n//   - the presence of a value in receiver-position in the call\n//     is a property of the caller, not the callee. A method\n//     (calleeDecl.Recv != nil) may be called like an ordinary\n//     function.\n//\n//   - the types.Signatures seen by the caller (from\n//     StaticCallee) and by the callee (from decl type)\n//     differ in this case.\n//\n// In a spread call f(g()), the sole ordinary argument g(),\n// always last in args, has a tuple type.\n//\n// We compute type-based predicates like pure, duplicable,\n// freevars, etc, now, before we start modifying syntax.\nfunc (st *state) arguments(caller *Caller, calleeDecl *ast.FuncDecl, assign1 func(*types.Var) bool) ([]*argument, error) {\n\tvar args []*argument\n\n\tcallArgs := caller.Call.Args\n\tif calleeDecl.Recv != nil {\n\t\tif len(st.callee.impl.TypeParams) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"cannot inline: generic methods not yet supported\")\n\t\t}\n\t\tsel := ast.Unparen(caller.Call.Fun).(*ast.SelectorExpr)\n\t\tseln := caller.Info.Selections[sel]\n\t\tvar recvArg ast.Expr\n\t\tswitch seln.Kind() {\n\t\tcase types.MethodVal: // recv.f(callArgs)\n\t\t\trecvArg = sel.X\n\t\tcase types.MethodExpr: // T.f(recv, callArgs)\n\t\t\trecvArg = callArgs[0]\n\t\t\tcallArgs = callArgs[1:]\n\t\t}\n\t\tif recvArg != nil {\n\t\t\t// Compute all the type-based predicates now,\n\t\t\t// before we start meddling with the syntax;\n\t\t\t// the meddling will update them.\n\t\t\targ := &argument{\n\t\t\t\texpr:       recvArg,\n\t\t\t\ttyp:        caller.Info.TypeOf(recvArg),\n\t\t\t\tconstant:   caller.Info.Types[recvArg].Value,\n\t\t\t\tpure:       pure(caller.Info, assign1, recvArg),\n\t\t\t\teffects:    st.effects(caller.Info, recvArg),\n\t\t\t\tduplicable: duplicable(caller.Info, recvArg),\n\t\t\t\tfreevars:   freeVars(caller.Info, recvArg),\n\t\t\t}\n\t\t\trecvArg = nil // prevent accidental use\n\n\t\t\t// Move receiver argument recv.f(args) to argument list f(&recv, args).\n\t\t\targs = append(args, arg)\n\n\t\t\t// Make field selections explicit (recv.f -> recv.y.f),\n\t\t\t// updating arg.{expr,typ}.\n\t\t\tindices := seln.Index()\n\t\t\tfor _, index := range indices[:len(indices)-1] {\n\t\t\t\tfld := typeparams.CoreType(typeparams.Deref(arg.typ)).(*types.Struct).Field(index)\n\t\t\t\tif fld.Pkg() != caller.Types && !fld.Exported() {\n\t\t\t\t\treturn nil, fmt.Errorf(\"in %s, implicit reference to unexported field .%s cannot be made explicit\",\n\t\t\t\t\t\tdebugFormatNode(caller.Fset, caller.Call.Fun),\n\t\t\t\t\t\tfld.Name())\n\t\t\t\t}\n\t\t\t\tif isPointer(arg.typ) {\n\t\t\t\t\targ.pure = false // implicit *ptr operation => impure\n\t\t\t\t}\n\t\t\t\targ.expr = &ast.SelectorExpr{\n\t\t\t\t\tX:   arg.expr,\n\t\t\t\t\tSel: makeIdent(fld.Name()),\n\t\t\t\t}\n\t\t\t\targ.typ = fld.Type()\n\t\t\t\targ.duplicable = false\n\t\t\t}\n\n\t\t\t// Make * or & explicit.\n\t\t\targIsPtr := isPointer(arg.typ)\n\t\t\tparamIsPtr := isPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type())\n\t\t\tif !argIsPtr && paramIsPtr {\n\t\t\t\t// &recv\n\t\t\t\targ.expr = &ast.UnaryExpr{Op: token.AND, X: arg.expr}\n\t\t\t\targ.typ = types.NewPointer(arg.typ)\n\t\t\t\targ.desugaredRecv = true\n\t\t\t} else if argIsPtr && !paramIsPtr {\n\t\t\t\t// *recv\n\t\t\t\targ.expr = &ast.StarExpr{X: arg.expr}\n\t\t\t\targ.typ = typeparams.Deref(arg.typ)\n\t\t\t\targ.duplicable = false\n\t\t\t\targ.pure = false\n\t\t\t\targ.desugaredRecv = true\n\t\t\t}\n\t\t}\n\t}\n\tfor _, expr := range callArgs {\n\t\ttv := caller.Info.Types[expr]\n\t\targs = append(args, &argument{\n\t\t\texpr:       expr,\n\t\t\ttyp:        tv.Type,\n\t\t\tconstant:   tv.Value,\n\t\t\tspread:     is[*types.Tuple](tv.Type), // => last\n\t\t\tpure:       pure(caller.Info, assign1, expr),\n\t\t\teffects:    st.effects(caller.Info, expr),\n\t\t\tduplicable: duplicable(caller.Info, expr),\n\t\t\tfreevars:   freeVars(caller.Info, expr),\n\t\t})\n\t}\n\n\t// Re-typecheck each constant argument expression in a neutral context.\n\t//\n\t// In a call such as func(int16){}(1), the type checker infers\n\t// the type \"int16\", not \"untyped int\", for the argument 1,\n\t// because it has incorporated information from the left-hand\n\t// side of the assignment implicit in parameter passing, but\n\t// of course in a different context, the expression 1 may have\n\t// a different type.\n\t//\n\t// So, we must use CheckExpr to recompute the type of the\n\t// argument in a neutral context to find its inherent type.\n\t// (This is arguably a bug in go/types, but I'm pretty certain\n\t// I requested it be this way long ago... -adonovan)\n\t//\n\t// This is only needed for constants. Other implicit\n\t// assignment conversions, such as unnamed-to-named struct or\n\t// chan to <-chan, do not result in the type-checker imposing\n\t// the LHS type on the RHS value.\n\tfor _, arg := range args {\n\t\tif arg.constant == nil {\n\t\t\tcontinue\n\t\t}\n\t\tinfo := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}\n\t\tif err := types.CheckExpr(caller.Fset, caller.Types, caller.Call.Pos(), arg.expr, info); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\targ.typ = info.TypeOf(arg.expr)\n\t}\n\n\treturn args, nil\n}\n\ntype parameter struct {\n\tobj       *types.Var // parameter var from caller's signature\n\tfieldType ast.Expr   // syntax of type, from calleeDecl.Type.{Recv,Params}\n\tinfo      *paramInfo // information from AnalyzeCallee\n\tvariadic  bool       // (final) parameter is unsimplified ...T\n}\n\n// A replacer replaces an identifier at the given offset in the callee.\n// The replacement tree must not belong to the caller; use cloneNode as needed.\n// If unpackVariadic is set, the replacement is a composite resulting from\n// variadic elimination, and may be unpacked into variadic calls.\ntype replacer = func(offset int, repl ast.Expr, unpackVariadic bool)\n\n// substituteTypeParams replaces type parameters in the callee with the corresponding type arguments\n// from the call.\nfunc substituteTypeParams(logf logger, typeParams []*paramInfo, typeArgs []*argument, params []*parameter, replace replacer) error {\n\tassert(len(typeParams) == len(typeArgs), \"mismatched number of type params/args\")\n\tfor i, paramInfo := range typeParams {\n\t\targ := typeArgs[i]\n\t\t// Perform a simplified, conservative shadow analysis: fail if there is any shadowing.\n\t\tfor free := range arg.freevars {\n\t\t\tif paramInfo.Shadow[free] != 0 {\n\t\t\t\treturn fmt.Errorf(\"cannot inline: type argument #%d (type parameter %s) is shadowed\", i, paramInfo.Name)\n\t\t\t}\n\t\t}\n\t\tlogf(\"replacing type param %s with %s\", paramInfo.Name, debugFormatNode(token.NewFileSet(), arg.expr))\n\t\tfor _, ref := range paramInfo.Refs {\n\t\t\treplace(ref.Offset, internalastutil.CloneNode(arg.expr), false)\n\t\t}\n\t\t// Also replace parameter field types.\n\t\t// TODO(jba): find a way to do this that is not so slow and clumsy.\n\t\t// Ideally, we'd walk each p.fieldType once, replacing all type params together.\n\t\tfor _, p := range params {\n\t\t\tif id, ok := p.fieldType.(*ast.Ident); ok && id.Name == paramInfo.Name {\n\t\t\t\tp.fieldType = arg.expr\n\t\t\t} else {\n\t\t\t\tfor _, id := range identsNamed(p.fieldType, paramInfo.Name) {\n\t\t\t\t\treplaceNode(p.fieldType, id, arg.expr)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc identsNamed(n ast.Node, name string) []*ast.Ident {\n\tvar ids []*ast.Ident\n\tast.Inspect(n, func(n ast.Node) bool {\n\t\tif id, ok := n.(*ast.Ident); ok && id.Name == name {\n\t\t\tids = append(ids, id)\n\t\t}\n\t\treturn true\n\t})\n\treturn ids\n}\n\n// substitute implements parameter elimination by substitution.\n//\n// It considers each parameter and its corresponding argument in turn\n// and evaluate these conditions:\n//\n//   - the parameter is neither address-taken nor assigned;\n//   - the argument is pure;\n//   - if the parameter refcount is zero, the argument must\n//     not contain the last use of a local var;\n//   - if the parameter refcount is > 1, the argument must be duplicable;\n//   - the argument (or types.Default(argument) if it's untyped) has\n//     the same type as the parameter.\n//\n// If all conditions are met then the parameter can be substituted and\n// each reference to it replaced by the argument. In that case, the\n// replaceCalleeID function is called for each reference to the\n// parameter, and is provided with its relative offset and replacement\n// expression (argument), and the corresponding elements of params and\n// args are replaced by nil.\nfunc substitute(logf logger, caller *Caller, params []*parameter, args []*argument, effects []int, falcon falconResult, replace replacer) {\n\t// Inv:\n\t//  in        calls to     variadic, len(args) >= len(params)-1\n\t//  in spread calls to non-variadic, len(args) <  len(params)\n\t//  in spread calls to     variadic, len(args) <= len(params)\n\t// (In spread calls len(args) = 1, or 2 if call has receiver.)\n\t// Non-spread variadics have been simplified away already,\n\t// so the args[i] lookup is safe if we stop after the spread arg.\n\tassert(len(args) <= len(params), \"too many arguments\")\n\n\t// Collect candidates for substitution.\n\t//\n\t// An argument is a candidate if it is not otherwise rejected, and any free\n\t// variables that are shadowed only by other parameters.\n\t//\n\t// Therefore, substitution candidates are represented by a graph, where edges\n\t// lead from each argument to the other arguments that, if substituted, would\n\t// allow the argument to be substituted. We collect these edges in the\n\t// [substGraph]. Any node that is known not to be elided from the graph.\n\t// Arguments in this graph with no edges are substitutable independent of\n\t// other nodes, though they may be removed due to falcon or effects analysis.\n\tsg := make(substGraph)\nnext:\n\tfor i, param := range params {\n\t\targ := args[i]\n\n\t\t// Check argument against parameter.\n\t\t//\n\t\t// Beware: don't use types.Info on arg since\n\t\t// the syntax may be synthetic (not created by parser)\n\t\t// and thus lacking positions and types;\n\t\t// do it earlier (see pure/duplicable/freevars).\n\n\t\tif arg.spread {\n\t\t\t// spread => last argument, but not always last parameter\n\t\t\tlogf(\"keeping param %q and following ones: argument %s is spread\",\n\t\t\t\tparam.info.Name, debugFormatNode(caller.Fset, arg.expr))\n\t\t\treturn // give up\n\t\t}\n\t\tassert(!param.variadic, \"unsimplified variadic parameter\")\n\t\tif param.info.Escapes {\n\t\t\tlogf(\"keeping param %q: escapes from callee\", param.info.Name)\n\t\t\tcontinue\n\t\t}\n\t\tif param.info.Assigned {\n\t\t\tlogf(\"keeping param %q: assigned by callee\", param.info.Name)\n\t\t\tcontinue // callee needs the parameter variable\n\t\t}\n\t\tif len(param.info.Refs) > 1 && !arg.duplicable {\n\t\t\tlogf(\"keeping param %q: argument is not duplicable\", param.info.Name)\n\t\t\tcontinue // incorrect or poor style to duplicate an expression\n\t\t}\n\t\tif len(param.info.Refs) == 0 {\n\t\t\tif arg.effects {\n\t\t\t\tlogf(\"keeping param %q: though unreferenced, it has effects\", param.info.Name)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If the caller is within a function body,\n\t\t\t// eliminating an unreferenced parameter might\n\t\t\t// remove the last reference to a caller local var.\n\t\t\tif caller.enclosingFunc != nil {\n\t\t\t\tfor free := range arg.freevars {\n\t\t\t\t\t// TODO(rfindley): we can get this 100% right by looking for\n\t\t\t\t\t// references among other arguments which have non-zero references\n\t\t\t\t\t// within the callee.\n\t\t\t\t\tif v, ok := caller.lookup(free).(*types.Var); ok && within(v.Pos(), caller.enclosingFunc.Body) && !isUsedOutsideCall(caller, v) {\n\n\t\t\t\t\t\t// Check to see if the substituted var is used within other args\n\t\t\t\t\t\t// whose corresponding params ARE used in the callee\n\t\t\t\t\t\tusedElsewhere := func() bool {\n\t\t\t\t\t\t\tfor i, param := range params {\n\t\t\t\t\t\t\t\tif i < len(args) && len(param.info.Refs) > 0 { // excludes original param\n\t\t\t\t\t\t\t\t\tfor name := range args[i].freevars {\n\t\t\t\t\t\t\t\t\t\tif caller.lookup(name) == v {\n\t\t\t\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !usedElsewhere() {\n\t\t\t\t\t\t\tlogf(\"keeping param %q: arg contains perhaps the last reference to caller local %v @ %v\",\n\t\t\t\t\t\t\t\tparam.info.Name, v, caller.Fset.PositionFor(v.Pos(), false))\n\t\t\t\t\t\t\tcontinue next\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Arg is a potential substitution candidate: analyze its shadowing.\n\t\t//\n\t\t// Consider inlining a call f(z, 1) to\n\t\t//\n\t\t// \tfunc f(x, y int) int { z := y; return x + y + z }\n\t\t//\n\t\t// we can't replace x in the body by z (or any\n\t\t// expression that has z as a free identifier) because there's an\n\t\t// intervening declaration of z that would shadow the caller's one.\n\t\t//\n\t\t// However, we *could* replace x in the body by y, as long as the y\n\t\t// parameter is also removed by substitution.\n\n\t\tsg[arg] = nil // Absent shadowing, the arg is substitutable.\n\t\tfor free := range arg.freevars {\n\t\t\tswitch s := param.info.Shadow[free]; {\n\t\t\tcase s < 0:\n\t\t\t\t// Shadowed by a non-parameter symbol, so arg is not substitutable.\n\t\t\t\tdelete(sg, arg)\n\t\t\tcase s > 0:\n\t\t\t\t// Shadowed by a parameter; arg may be substitutable, if only shadowed\n\t\t\t\t// by other substitutable parameters.\n\t\t\t\tif s > len(args) {\n\t\t\t\t\t// Defensive: this should not happen in the current factoring, since\n\t\t\t\t\t// spread arguments are already handled.\n\t\t\t\t\tdelete(sg, arg)\n\t\t\t\t}\n\t\t\t\tif edges, ok := sg[arg]; ok {\n\t\t\t\t\tsg[arg] = append(edges, args[s-1])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Process the initial state of the substitution graph.\n\tsg.prune()\n\n\t// Now we check various conditions on the substituted argument set as a\n\t// whole. These conditions reject substitution candidates, but since their\n\t// analysis depends on the full set of candidates, we do not process side\n\t// effects of their candidate rejection until after the analysis completes,\n\t// in a call to prune. After pruning, we must re-run the analysis to check\n\t// for additional rejections.\n\t//\n\t// Here's an example of that in practice:\n\t//\n\t// \tvar a [3]int\n\t//\n\t// \tfunc falcon(x, y, z int) {\n\t// \t\t_ = x + a[y+z]\n\t// \t}\n\t//\n\t// \tfunc _() {\n\t// \t\tvar y int\n\t// \t\tconst x, z = 1, 2\n\t// \t\tfalcon(y, x, z)\n\t// \t}\n\t//\n\t// In this example, arguments 0 and 1 are shadowed by each other's\n\t// corresponding parameter, and so each can be substituted only if they are\n\t// both substituted. But the fallible constant analysis finds a violated\n\t// constraint: x + z = 3, and so the constant array index would cause a\n\t// compile-time error if argument 1 (x) were substituted. Therefore,\n\t// following the falcon analysis, we must also prune argument 0.\n\t//\n\t// As far as I (rfindley) can tell, the falcon analysis should always succeed\n\t// after the first pass, as it's not possible for additional bindings to\n\t// cause new constraint failures. Nevertheless, we re-run it to be sure.\n\t//\n\t// However, the same cannot be said of the effects analysis, as demonstrated\n\t// by this example:\n\t//\n\t// \tfunc effects(w, x, y, z int) {\n\t// \t\t_ = x + w + y + z\n\t// \t}\n\n\t// \tfunc _() {\n\t// \t\tv := 0\n\t// \t\tw := func() int { v++; return 0 }\n\t// \t\tx := func() int { v++; return 0 }\n\t// \t\ty := func() int { v++; return 0 }\n\t// \t\teffects(x(), w(), y(), x()) //@ inline(re\"effects\", effects)\n\t// \t}\n\t//\n\t// In this example, arguments 0, 1, and 3 are related by the substitution\n\t// graph. The first effects analysis implies that arguments 0 and 1 must be\n\t// bound, and therefore argument 3 must be bound. But then a subsequent\n\t// effects analysis forces argument 2 to also be bound.\n\n\t// Reject constant arguments as substitution candidates if they cause\n\t// violation of falcon constraints.\n\t//\n\t// Keep redoing the analysis until we no longer reject additional arguments,\n\t// as the set of substituted parameters affects the falcon package.\n\tfor checkFalconConstraints(logf, params, args, falcon, sg) {\n\t\tsg.prune()\n\t}\n\n\t// As a final step, introduce bindings to resolve any\n\t// evaluation order hazards. This must be done last, as\n\t// additional subsequent bindings could introduce new hazards.\n\t//\n\t// As with the falcon analysis, keep redoing the analysis until the no more\n\t// arguments are rejected.\n\tfor resolveEffects(logf, args, effects, sg) {\n\t\tsg.prune()\n\t}\n\n\t// The remaining candidates are safe to substitute.\n\tfor i, param := range params {\n\t\tif arg := args[i]; sg.has(arg) {\n\n\t\t\t// It is safe to substitute param and replace it with arg.\n\t\t\t// The formatter introduces parens as needed for precedence.\n\t\t\t//\n\t\t\t// Because arg.expr belongs to the caller,\n\t\t\t// we clone it before splicing it into the callee tree.\n\t\t\tlogf(\"replacing parameter %q by argument %q\",\n\t\t\t\tparam.info.Name, debugFormatNode(caller.Fset, arg.expr))\n\t\t\tfor _, ref := range param.info.Refs {\n\t\t\t\t// Apply any transformations necessary for this reference.\n\t\t\t\targExpr := arg.expr\n\n\t\t\t\t// If the reference itself is being selected, and we applied desugaring\n\t\t\t\t// (an explicit &x or *x), we can undo that desugaring here as it is\n\t\t\t\t// not necessary for a selector. We don't need to check addressability\n\t\t\t\t// here because if we desugared, the receiver must have been\n\t\t\t\t// addressable.\n\t\t\t\tif ref.IsSelectionOperand && arg.desugaredRecv {\n\t\t\t\t\tswitch e := argExpr.(type) {\n\t\t\t\t\tcase *ast.UnaryExpr:\n\t\t\t\t\t\targExpr = e.X\n\t\t\t\t\tcase *ast.StarExpr:\n\t\t\t\t\t\targExpr = e.X\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If the reference requires exact type agreement between parameter and\n\t\t\t\t// argument, wrap the argument in an explicit conversion if\n\t\t\t\t// substitution might materially change its type. (We already did the\n\t\t\t\t// necessary shadowing check on the parameter type syntax.)\n\t\t\t\t//\n\t\t\t\t// The types must agree in any of these cases:\n\t\t\t\t// - the argument affects type inference;\n\t\t\t\t// - the reference's concrete type is assigned to an interface type;\n\t\t\t\t// - the reference is not an assignment, nor a trivial conversion of an untyped constant.\n\t\t\t\t//\n\t\t\t\t// In all other cases, no explicit conversion is necessary as either\n\t\t\t\t// the type does not matter, or must have already agreed for well-typed\n\t\t\t\t// code.\n\t\t\t\t//\n\t\t\t\t// This is only needed for substituted arguments. All other arguments\n\t\t\t\t// are given explicit types in either a binding decl or when using the\n\t\t\t\t// literalization strategy.\n\t\t\t\t//\n\t\t\t\t// If the types are identical, we can eliminate\n\t\t\t\t// redundant type conversions such as this:\n\t\t\t\t//\n\t\t\t\t// Callee:\n\t\t\t\t//    func f(i int32) { fmt.Println(i) }\n\t\t\t\t// Caller:\n\t\t\t\t//    func g() { f(int32(1)) }\n\t\t\t\t// Inlined as:\n\t\t\t\t//    func g() { fmt.Println(int32(int32(1)))\n\t\t\t\t//\n\t\t\t\t// Recall that non-trivial does not imply non-identical for constant\n\t\t\t\t// conversions; however, at this point state.arguments has already\n\t\t\t\t// re-typechecked the constant and set arg.type to its (possibly\n\t\t\t\t// \"untyped\") inherent type, so the conversion from untyped 1 to int32\n\t\t\t\t// is non-trivial even though both arg and param have identical types\n\t\t\t\t// (int32).\n\t\t\t\tneedType := ref.AffectsInference ||\n\t\t\t\t\t(ref.Assignable && ref.IfaceAssignment && !param.info.IsInterface) ||\n\t\t\t\t\t(!ref.Assignable && !trivialConversion(arg.constant, arg.typ, param.obj.Type()))\n\n\t\t\t\tif needType &&\n\t\t\t\t\t!types.Identical(types.Default(arg.typ), param.obj.Type()) {\n\n\t\t\t\t\t// If arg.expr is already an interface call, strip it.\n\t\t\t\t\tif call, ok := argExpr.(*ast.CallExpr); ok && len(call.Args) == 1 {\n\t\t\t\t\t\tif typ, ok := isConversion(caller.Info, call); ok && isNonTypeParamInterface(typ) {\n\t\t\t\t\t\t\targExpr = call.Args[0]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\targExpr = convert(param.fieldType, argExpr)\n\t\t\t\t\tlogf(\"param %q (offset %d): adding explicit %s -> %s conversion around argument\",\n\t\t\t\t\t\tparam.info.Name, ref.Offset, arg.typ, param.obj.Type())\n\t\t\t\t}\n\t\t\t\treplace(ref.Offset, internalastutil.CloneNode(argExpr).(ast.Expr), arg.variadic)\n\t\t\t}\n\t\t\tparams[i] = nil // substituted\n\t\t\targs[i] = nil   // substituted\n\t\t}\n\t}\n}\n\n// isConversion reports whether the given call is a type conversion, returning\n// (operand, true) if so.\n//\n// If the call is not a conversion, it returns (nil, false).\nfunc isConversion(info *types.Info, call *ast.CallExpr) (types.Type, bool) {\n\tif tv, ok := info.Types[call.Fun]; ok && tv.IsType() {\n\t\treturn tv.Type, true\n\t}\n\treturn nil, false\n}\n\n// isNonTypeParamInterface reports whether t is a non-type parameter interface\n// type.\nfunc isNonTypeParamInterface(t types.Type) bool {\n\treturn !typeparams.IsTypeParam(t) && types.IsInterface(t)\n}\n\n// isUsedOutsideCall reports whether v is used outside of caller.Call, within\n// the body of caller.enclosingFunc.\nfunc isUsedOutsideCall(caller *Caller, v *types.Var) bool {\n\tused := false\n\tast.Inspect(caller.enclosingFunc.Body, func(n ast.Node) bool {\n\t\tif n == caller.Call {\n\t\t\treturn false\n\t\t}\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Ident:\n\t\t\tif use := caller.Info.Uses[n]; use == v {\n\t\t\t\tused = true\n\t\t\t}\n\t\tcase *ast.FuncType:\n\t\t\t// All params are used.\n\t\t\tfor _, fld := range n.Params.List {\n\t\t\t\tfor _, n := range fld.Names {\n\t\t\t\t\tif def := caller.Info.Defs[n]; def == v {\n\t\t\t\t\t\tused = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn !used // keep going until we find a use\n\t})\n\treturn used\n}\n\n// checkFalconConstraints checks whether constant arguments\n// are safe to substitute (e.g. s[i] -> \"\"[0] is not safe.)\n//\n// Any failed constraint causes us to reject all constant arguments as\n// substitution candidates (by clearing args[i].substitution=false).\n//\n// TODO(adonovan): we could obtain a finer result rejecting only the\n// freevars of each failed constraint, and processing constraints in\n// order of increasing arity, but failures are quite rare.\nfunc checkFalconConstraints(logf logger, params []*parameter, args []*argument, falcon falconResult, sg substGraph) bool {\n\t// Create a dummy package, as this is the only\n\t// way to create an environment for CheckExpr.\n\tpkg := types.NewPackage(\"falcon\", \"falcon\")\n\n\t// Declare types used by constraints.\n\tfor _, typ := range falcon.Types {\n\t\tlogf(\"falcon env: type %s %s\", typ.Name, types.Typ[typ.Kind])\n\t\tpkg.Scope().Insert(types.NewTypeName(token.NoPos, pkg, typ.Name, types.Typ[typ.Kind]))\n\t}\n\n\t// Declared constants and variables for parameters.\n\tnconst := 0\n\tfor i, param := range params {\n\t\tname := param.info.Name\n\t\tif name == \"\" {\n\t\t\tcontinue // unreferenced\n\t\t}\n\t\targ := args[i]\n\t\tif arg.constant != nil && sg.has(arg) && param.info.FalconType != \"\" {\n\t\t\tt := pkg.Scope().Lookup(param.info.FalconType).Type()\n\t\t\tpkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, t, arg.constant))\n\t\t\tlogf(\"falcon env: const %s %s = %v\", name, param.info.FalconType, arg.constant)\n\t\t\tnconst++\n\t\t} else {\n\t\t\tv := types.NewVar(token.NoPos, pkg, name, arg.typ)\n\t\t\ttypesinternal.SetVarKind(v, typesinternal.PackageVar)\n\t\t\tpkg.Scope().Insert(v)\n\t\t\tlogf(\"falcon env: var %s %s\", name, arg.typ)\n\t\t}\n\t}\n\tif nconst == 0 {\n\t\treturn false // nothing to do\n\t}\n\n\t// Parse and evaluate the constraints in the environment.\n\tfset := token.NewFileSet()\n\tremoved := false\n\tfor _, falcon := range falcon.Constraints {\n\t\texpr, err := parser.ParseExprFrom(fset, \"falcon\", falcon, 0)\n\t\tif err != nil {\n\t\t\tpanic(fmt.Sprintf(\"failed to parse falcon constraint %s: %v\", falcon, err))\n\t\t}\n\t\tif err := types.CheckExpr(fset, pkg, token.NoPos, expr, nil); err != nil {\n\t\t\tlogf(\"falcon: constraint %s violated: %v\", falcon, err)\n\t\t\tfor j, arg := range args {\n\t\t\t\tif arg.constant != nil && sg.has(arg) {\n\t\t\t\t\tlogf(\"keeping param %q due falcon violation\", params[j].info.Name)\n\t\t\t\t\tremoved = sg.remove(arg) || removed\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tlogf(\"falcon: constraint %s satisfied\", falcon)\n\t}\n\treturn removed\n}\n\n// resolveEffects marks arguments as non-substitutable to resolve\n// hazards resulting from the callee evaluation order described by the\n// effects list.\n//\n// To do this, each argument is categorized as a read (R), write (W),\n// or pure. A hazard occurs when the order of evaluation of a W\n// changes with respect to any R or W. Pure arguments can be\n// effectively ignored, as they can be safely evaluated in any order.\n//\n// The callee effects list contains the index of each parameter in the\n// order it is first evaluated during execution of the callee. In\n// addition, the two special values R∞ and W∞ indicate the relative\n// position of the callee's first non-parameter read and its first\n// effects (or other unknown behavior).\n// For example, the list [0 2 1 R∞ 3 W∞] for func(a, b, c, d)\n// indicates that the callee referenced parameters a, c, and b,\n// followed by an arbitrary read, then parameter d, and finally\n// unknown behavior.\n//\n// When an argument is marked as not substitutable, we say that it is\n// 'bound', in the sense that its evaluation occurs in a binding decl\n// or literalized call. Such bindings always occur in the original\n// callee parameter order.\n//\n// In this context, \"resolving hazards\" means binding arguments so\n// that they are evaluated in a valid, hazard-free order. A trivial\n// solution to this problem would be to bind all arguments, but of\n// course that's not useful. The goal is to bind as few arguments as\n// possible.\n//\n// The algorithm proceeds by inspecting arguments in reverse parameter\n// order (right to left), preserving the invariant that every\n// higher-ordered argument is either already substituted or does not\n// need to be substituted. At each iteration, if there is an\n// evaluation hazard in the callee effects relative to the current\n// argument, the argument must be bound. Subsequently, if the argument\n// is bound for any reason, each lower-ordered argument must also be\n// bound if either the argument or lower-order argument is a\n// W---otherwise the binding itself would introduce a hazard.\n//\n// Thus, after each iteration, there are no hazards relative to the\n// current argument. Subsequent iterations cannot introduce hazards\n// with that argument because they can result only in additional\n// binding of lower-ordered arguments.\nfunc resolveEffects(logf logger, args []*argument, effects []int, sg substGraph) bool {\n\teffectStr := func(effects bool, idx int) string {\n\t\ti := fmt.Sprint(idx)\n\t\tif idx == len(args) {\n\t\t\ti = \"∞\"\n\t\t}\n\t\treturn string(\"RW\"[btoi(effects)]) + i\n\t}\n\tremoved := false\n\tfor i := len(args) - 1; i >= 0; i-- {\n\t\targi := args[i]\n\t\tif sg.has(argi) && !argi.pure {\n\t\t\t// i is not bound: check whether it must be bound due to hazards.\n\t\t\tidx := slices.Index(effects, i)\n\t\t\tif idx >= 0 {\n\t\t\t\tfor _, j := range effects[:idx] {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tji int  // effective param index\n\t\t\t\t\t\tjw bool // j is a write\n\t\t\t\t\t)\n\t\t\t\t\tif j == winf || j == rinf {\n\t\t\t\t\t\tjw = j == winf\n\t\t\t\t\t\tji = len(args)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjw = args[j].effects\n\t\t\t\t\t\tji = j\n\t\t\t\t\t}\n\t\t\t\t\tif ji > i && (jw || argi.effects) { // out of order evaluation\n\t\t\t\t\t\tlogf(\"binding argument %s: preceded by %s\",\n\t\t\t\t\t\t\teffectStr(argi.effects, i), effectStr(jw, ji))\n\n\t\t\t\t\t\tremoved = sg.remove(argi) || removed\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif !sg.has(argi) {\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\targj := args[j]\n\t\t\t\tif argj.pure {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (argi.effects || argj.effects) && sg.has(argj) {\n\t\t\t\t\tlogf(\"binding argument %s: %s is bound\",\n\t\t\t\t\t\teffectStr(argj.effects, j), effectStr(argi.effects, i))\n\n\t\t\t\t\tremoved = sg.remove(argj) || removed\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn removed\n}\n\n// A substGraph is a directed graph representing arguments that may be\n// substituted, provided all of their related arguments (or \"dependencies\") are\n// also substituted. The candidates arguments for substitution are the keys in\n// this graph, and the edges represent shadowing of free variables of the key\n// by parameters corresponding to the dependency arguments.\n//\n// Any argument not present as a map key is known not to be substitutable. Some\n// arguments may have edges leading to other arguments that are not present in\n// the graph. In this case, those arguments also cannot be substituted, because\n// they have free variables that are shadowed by parameters that cannot be\n// substituted. Calling [substGraph.prune] removes these arguments from the\n// graph.\n//\n// The 'prune' operation is not built into the 'remove' step both because\n// analyses (falcon, effects) need local information about each argument\n// independent of dependencies, and for the efficiency of pruning once en masse\n// after each analysis.\ntype substGraph map[*argument][]*argument\n\n// has reports whether arg is a candidate for substitution.\nfunc (g substGraph) has(arg *argument) bool {\n\t_, ok := g[arg]\n\treturn ok\n}\n\n// remove marks arg as not substitutable, reporting whether the arg was\n// previously substitutable.\n//\n// remove does not have side effects on other arguments that may be\n// unsubstitutable as a result of their dependency being removed.\n// Call [substGraph.prune] to propagate these side effects, removing dependent\n// arguments.\nfunc (g substGraph) remove(arg *argument) bool {\n\tpre := len(g)\n\tdelete(g, arg)\n\treturn len(g) < pre\n}\n\n// prune updates the graph to remove any keys that reach other arguments not\n// present in the graph.\nfunc (g substGraph) prune() {\n\t// visit visits the forward transitive closure of arg and reports whether any\n\t// missing argument was encountered, removing all nodes on the path to it\n\t// from arg.\n\t//\n\t// The seen map is used for cycle breaking. In the presence of cycles, visit\n\t// may report a false positive for an intermediate argument. For example,\n\t// consider the following graph, where only a and b are candidates for\n\t// substitution (meaning, only a and b are present in the graph).\n\t//\n\t//   a ↔ b\n\t//   ↓\n\t//  [c]\n\t//\n\t// In this case, starting a visit from a, visit(b, seen) may report 'true',\n\t// because c has not yet been considered. For this reason, we must guarantee\n\t// that visit is called with an empty seen map at least once for each node.\n\tvar visit func(*argument, map[*argument]unit) bool\n\tvisit = func(arg *argument, seen map[*argument]unit) bool {\n\t\tdeps, ok := g[arg]\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif _, ok := seen[arg]; !ok {\n\t\t\tseen[arg] = unit{}\n\t\t\tfor _, dep := range deps {\n\t\t\t\tif !visit(dep, seen) {\n\t\t\t\t\tdelete(g, arg)\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\tfor arg := range g {\n\t\t// Remove any argument that is, or transitively depends upon,\n\t\t// an unsubstitutable argument.\n\t\t//\n\t\t// Each visitation gets a fresh cycle-breaking set.\n\t\tvisit(arg, make(map[*argument]unit))\n\t}\n}\n\n// updateCalleeParams updates the calleeDecl syntax to remove\n// substituted parameters and move the receiver (if any) to the head\n// of the ordinary parameters.\nfunc updateCalleeParams(calleeDecl *ast.FuncDecl, params []*parameter) {\n\t// The logic is fiddly because of the three forms of ast.Field:\n\t//\n\t//\tfunc(int), func(x int), func(x, y int)\n\t//\n\t// Also, ensure that all remaining parameters are named\n\t// to avoid a mix of named/unnamed when joining (recv, params...).\n\t// func (T) f(int, bool) -> (_ T, _ int, _ bool)\n\t// (Strictly, we need do this only for methods and only when\n\t// the namednesses of Recv and Params differ; that might be tidier.)\n\n\tparamIdx := 0 // index in original parameter list (incl. receiver)\n\tvar newParams []*ast.Field\n\tfilterParams := func(field *ast.Field) {\n\t\tvar names []*ast.Ident\n\t\tif field.Names == nil {\n\t\t\t// Unnamed parameter field (e.g. func f(int)\n\t\t\tif params[paramIdx] != nil {\n\t\t\t\t// Give it an explicit name \"_\" since we will\n\t\t\t\t// make the receiver (if any) a regular parameter\n\t\t\t\t// and one cannot mix named and unnamed parameters.\n\t\t\t\tnames = append(names, makeIdent(\"_\"))\n\t\t\t}\n\t\t\tparamIdx++\n\t\t} else {\n\t\t\t// Named parameter field e.g. func f(x, y int)\n\t\t\t// Remove substituted parameters in place.\n\t\t\t// If all were substituted, delete field.\n\t\t\tfor _, id := range field.Names {\n\t\t\t\tif pinfo := params[paramIdx]; pinfo != nil {\n\t\t\t\t\t// Rename unreferenced parameters with \"_\".\n\t\t\t\t\t// This is crucial for binding decls, since\n\t\t\t\t\t// unlike parameters, they are subject to\n\t\t\t\t\t// \"unreferenced var\" checks.\n\t\t\t\t\tif len(pinfo.info.Refs) == 0 {\n\t\t\t\t\t\tid = makeIdent(\"_\")\n\t\t\t\t\t}\n\t\t\t\t\tnames = append(names, id)\n\t\t\t\t}\n\t\t\t\tparamIdx++\n\t\t\t}\n\t\t}\n\t\tif names != nil {\n\t\t\tnewParams = append(newParams, &ast.Field{\n\t\t\t\tNames: names,\n\t\t\t\tType:  field.Type,\n\t\t\t})\n\t\t}\n\t}\n\tif calleeDecl.Recv != nil {\n\t\tfilterParams(calleeDecl.Recv.List[0])\n\t\tcalleeDecl.Recv = nil\n\t}\n\tfor _, field := range calleeDecl.Type.Params.List {\n\t\tfilterParams(field)\n\t}\n\tcalleeDecl.Type.Params.List = newParams\n}\n\n// bindingDeclInfo records information about the binding decl produced by\n// createBindingDecl.\ntype bindingDeclInfo struct {\n\tnames map[string]bool // names bound by the binding decl; possibly empty\n\tstmt  ast.Stmt        // the binding decl itself\n}\n\n// createBindingDecl constructs a \"binding decl\" that implements\n// parameter assignment and declares any named result variables\n// referenced by the callee. It returns nil if there were no\n// unsubstituted parameters.\n//\n// It may not always be possible to create the decl (e.g. due to\n// shadowing), in which case it also returns nil; but if it succeeds,\n// the declaration may be used by reduction strategies to relax the\n// requirement that all parameters have been substituted.\n//\n// For example, a call:\n//\n//\tf(a0, a1, a2)\n//\n// where:\n//\n//\tfunc f(p0, p1 T0, p2 T1) { body }\n//\n// reduces to:\n//\n//\t{\n//\t  var (\n//\t    p0, p1 T0 = a0, a1\n//\t    p2     T1 = a2\n//\t  )\n//\t  body\n//\t}\n//\n// so long as p0, p1 ∉ freevars(T1) or freevars(a2), and so on,\n// because each spec is statically resolved in sequence and\n// dynamically assigned in sequence. By contrast, all\n// parameters are resolved simultaneously and assigned\n// simultaneously.\n//\n// The pX names should already be blank (\"_\") if the parameter\n// is unreferenced; this avoids \"unreferenced local var\" checks.\n//\n// Strategies may impose additional checks on return\n// conversions, labels, defer, etc.\nfunc createBindingDecl(logf logger, caller *Caller, args []*argument, calleeDecl *ast.FuncDecl, results []*paramInfo) *bindingDeclInfo {\n\t// Spread calls are tricky as they may not align with the\n\t// parameters' field groupings nor types.\n\t// For example, given\n\t//   func g() (int, string)\n\t// the call\n\t//   f(g())\n\t// is legal with these decls of f:\n\t//   func f(int, string)\n\t//   func f(x, y any)\n\t//   func f(x, y ...any)\n\t// TODO(adonovan): support binding decls for spread calls by\n\t// splitting parameter groupings as needed.\n\tif lastArg := last(args); lastArg != nil && lastArg.spread {\n\t\tlogf(\"binding decls not yet supported for spread calls\")\n\t\treturn nil\n\t}\n\n\tvar (\n\t\tspecs []ast.Spec\n\t\tnames = make(map[string]bool) // names defined by previous specs\n\t)\n\t// shadow reports whether any name referenced by spec is\n\t// shadowed by a name declared by a previous spec (since,\n\t// unlike parameters, each spec of a var decl is within the\n\t// scope of the previous specs).\n\tshadow := func(spec *ast.ValueSpec) bool {\n\t\t// Compute union of free names of type and values\n\t\t// and detect shadowing. Values is the arguments\n\t\t// (caller syntax), so we can use type info.\n\t\t// But Type is the untyped callee syntax,\n\t\t// so we have to use a syntax-only algorithm.\n\t\tconst includeComplitIdents = true\n\t\tfree := free.Names(spec.Type, includeComplitIdents)\n\t\tfor _, value := range spec.Values {\n\t\t\tfor name := range freeVars(caller.Info, value) {\n\t\t\t\tfree[name] = true\n\t\t\t}\n\t\t}\n\t\tfor name := range free {\n\t\t\tif names[name] {\n\t\t\t\tlogf(\"binding decl would shadow free name %q\", name)\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\tfor _, id := range spec.Names {\n\t\t\tif id.Name != \"_\" {\n\t\t\t\tnames[id.Name] = true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// parameters\n\t//\n\t// Bind parameters that were not eliminated through\n\t// substitution. (Non-nil arguments correspond to the\n\t// remaining parameters in calleeDecl.)\n\tvar values []ast.Expr\n\tfor _, arg := range args {\n\t\tif arg != nil {\n\t\t\tvalues = append(values, arg.expr)\n\t\t}\n\t}\n\tfor _, field := range calleeDecl.Type.Params.List {\n\t\t// Each field (param group) becomes a ValueSpec.\n\t\tspec := &ast.ValueSpec{\n\t\t\tNames:  cleanNodes(field.Names),\n\t\t\tType:   cleanNode(field.Type),\n\t\t\tValues: values[:len(field.Names)],\n\t\t}\n\t\tvalues = values[len(field.Names):]\n\t\tif shadow(spec) {\n\t\t\treturn nil\n\t\t}\n\t\tspecs = append(specs, spec)\n\t}\n\tassert(len(values) == 0, \"args/params mismatch\")\n\n\t// results\n\t//\n\t// Add specs to declare any named result\n\t// variables that are referenced by the body.\n\tif calleeDecl.Type.Results != nil {\n\t\tresultIdx := 0\n\t\tfor _, field := range calleeDecl.Type.Results.List {\n\t\t\tif field.Names == nil {\n\t\t\t\tresultIdx++\n\t\t\t\tcontinue // unnamed field\n\t\t\t}\n\t\t\tvar names []*ast.Ident\n\t\t\tfor _, id := range field.Names {\n\t\t\t\tif len(results[resultIdx].Refs) > 0 {\n\t\t\t\t\tnames = append(names, id)\n\t\t\t\t}\n\t\t\t\tresultIdx++\n\t\t\t}\n\t\t\tif len(names) > 0 {\n\t\t\t\tspec := &ast.ValueSpec{\n\t\t\t\t\tNames: cleanNodes(names),\n\t\t\t\t\tType:  cleanNode(field.Type),\n\t\t\t\t}\n\t\t\t\tif shadow(spec) {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tspecs = append(specs, spec)\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(specs) == 0 {\n\t\tlogf(\"binding decl not needed: all parameters substituted\")\n\t\treturn nil\n\t}\n\n\tstmt := &ast.DeclStmt{\n\t\tDecl: &ast.GenDecl{\n\t\t\tTok:   token.VAR,\n\t\t\tSpecs: specs,\n\t\t},\n\t}\n\tlogf(\"binding decl: %s\", debugFormatNode(caller.Fset, stmt))\n\treturn &bindingDeclInfo{names: names, stmt: stmt}\n}\n\n// lookup does a symbol lookup in the lexical environment of the caller.\nfunc (caller *Caller) lookup(name string) types.Object {\n\tpos := caller.Call.Pos()\n\tfor _, n := range caller.path {\n\t\tif scope := scopeFor(caller.Info, n); scope != nil {\n\t\t\tif _, obj := scope.LookupParent(name, pos); obj != nil {\n\t\t\t\treturn obj\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc scopeFor(info *types.Info, n ast.Node) *types.Scope {\n\t// The function body scope (containing not just params)\n\t// is associated with the function's type, not body.\n\tswitch fn := n.(type) {\n\tcase *ast.FuncDecl:\n\t\tn = fn.Type\n\tcase *ast.FuncLit:\n\t\tn = fn.Type\n\t}\n\treturn info.Scopes[n]\n}\n\n// -- predicates over expressions --\n\n// freeVars returns the names of all free identifiers of e:\n// those lexically referenced by it but not defined within it.\n// (Fields and methods are not included.)\nfunc freeVars(info *types.Info, e ast.Expr) map[string]bool {\n\tfree := make(map[string]bool)\n\tast.Inspect(e, func(n ast.Node) bool {\n\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\t// The isField check is so that we don't treat T{f: 0} as a ref to f.\n\t\t\tif obj, ok := info.Uses[id]; ok && !within(obj.Pos(), e) && !isField(obj) {\n\t\t\t\tfree[obj.Name()] = true\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\treturn free\n}\n\n// effects reports whether an expression might change the state of the\n// program (through function calls and channel receives) and affect\n// the evaluation of subsequent expressions.\nfunc (st *state) effects(info *types.Info, expr ast.Expr) bool {\n\teffects := false\n\tast.Inspect(expr, func(n ast.Node) bool {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.FuncLit:\n\t\t\treturn false // prune descent\n\n\t\tcase *ast.CallExpr:\n\t\t\tif info.Types[n.Fun].IsType() {\n\t\t\t\t// A conversion T(x) has only the effect of its operand.\n\t\t\t} else if !typesinternal.CallsPureBuiltin(info, n) {\n\t\t\t\t// A handful of built-ins have no effect\n\t\t\t\t// beyond those of their arguments.\n\t\t\t\t// All other calls (including append, copy, recover)\n\t\t\t\t// have unknown effects.\n\t\t\t\t//\n\t\t\t\t// As with 'pure', there is room for\n\t\t\t\t// improvement by inspecting the callee.\n\t\t\t\teffects = true\n\t\t\t}\n\n\t\tcase *ast.UnaryExpr:\n\t\t\tif n.Op == token.ARROW { // <-ch\n\t\t\t\teffects = true\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\t// Even if consideration of effects is not desired,\n\t// we continue to compute, log, and discard them.\n\tif st.opts.IgnoreEffects && effects {\n\t\teffects = false\n\t\tst.opts.Logf(\"ignoring potential effects of argument %s\",\n\t\t\tdebugFormatNode(st.caller.Fset, expr))\n\t}\n\n\treturn effects\n}\n\n// pure reports whether an expression has the same result no matter\n// when it is executed relative to other expressions, so it can be\n// commuted with any other expression or statement without changing\n// its meaning.\n//\n// An expression is considered impure if it reads the contents of any\n// variable, with the exception of \"single assignment\" local variables\n// (as classified by the provided callback), which are never updated\n// after their initialization.\n//\n// Pure does not imply duplicable: for example, new(T) and T{} are\n// pure expressions but both return a different value each time they\n// are evaluated, so they are not safe to duplicate.\n//\n// Purity does not imply freedom from run-time panics. We assume that\n// target programs do not encounter run-time panics nor depend on them\n// for correct operation.\n//\n// TODO(adonovan): add unit tests of this function.\nfunc pure(info *types.Info, assign1 func(*types.Var) bool, e ast.Expr) bool {\n\tvar pure func(e ast.Expr) bool\n\tpure = func(e ast.Expr) bool {\n\t\tswitch e := e.(type) {\n\t\tcase *ast.ParenExpr:\n\t\t\treturn pure(e.X)\n\n\t\tcase *ast.Ident:\n\t\t\tif v, ok := info.Uses[e].(*types.Var); ok {\n\t\t\t\t// In general variables are impure\n\t\t\t\t// as they may be updated, but\n\t\t\t\t// single-assignment local variables\n\t\t\t\t// never change value.\n\t\t\t\t//\n\t\t\t\t// We assume all package-level variables\n\t\t\t\t// may be updated, but for non-exported\n\t\t\t\t// ones we could do better by analyzing\n\t\t\t\t// the complete package.\n\t\t\t\treturn !isPkgLevel(v) && assign1(v)\n\t\t\t}\n\n\t\t\t// All other kinds of reference are pure.\n\t\t\treturn true\n\n\t\tcase *ast.FuncLit:\n\t\t\t// A function literal may allocate a closure that\n\t\t\t// references mutable variables, but mutation\n\t\t\t// cannot be observed without calling the function,\n\t\t\t// and calls are considered impure.\n\t\t\treturn true\n\n\t\tcase *ast.BasicLit:\n\t\t\treturn true\n\n\t\tcase *ast.UnaryExpr: // + - ! ^ & but not <-\n\t\t\treturn e.Op != token.ARROW && pure(e.X)\n\n\t\tcase *ast.BinaryExpr: // arithmetic, shifts, comparisons, &&/||\n\t\t\treturn pure(e.X) && pure(e.Y)\n\n\t\tcase *ast.CallExpr:\n\t\t\t// A conversion is as pure as its operand.\n\t\t\tif info.Types[e.Fun].IsType() {\n\t\t\t\treturn pure(e.Args[0])\n\t\t\t}\n\n\t\t\t// Calls to some built-ins are as pure as their arguments.\n\t\t\tif typesinternal.CallsPureBuiltin(info, e) {\n\t\t\t\tfor _, arg := range e.Args {\n\t\t\t\t\tif !pure(arg) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// All other calls are impure, so we can\n\t\t\t// reject them without even looking at e.Fun.\n\t\t\t//\n\t\t\t// More sophisticated analysis could infer purity in\n\t\t\t// commonly used functions such as strings.Contains;\n\t\t\t// perhaps we could offer the client a hook so that\n\t\t\t// go/analysis-based implementation could exploit the\n\t\t\t// results of a purity analysis. But that would make\n\t\t\t// the inliner's choices harder to explain.\n\t\t\treturn false\n\n\t\tcase *ast.CompositeLit:\n\t\t\t// T{...} is as pure as its elements.\n\t\t\tfor _, elt := range e.Elts {\n\t\t\t\tif kv, ok := elt.(*ast.KeyValueExpr); ok {\n\t\t\t\t\tif !pure(kv.Value) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif id, ok := kv.Key.(*ast.Ident); ok {\n\t\t\t\t\t\tif v, ok := info.Uses[id].(*types.Var); ok && v.IsField() {\n\t\t\t\t\t\t\tcontinue // struct {field: value}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// map/slice/array {key: value}\n\t\t\t\t\tif !pure(kv.Key) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\n\t\t\t\t} else if !pure(elt) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\n\t\tcase *ast.SelectorExpr:\n\t\t\tif seln, ok := info.Selections[e]; ok {\n\t\t\t\t// See types.SelectionKind for background.\n\t\t\t\tswitch seln.Kind() {\n\t\t\t\tcase types.MethodExpr:\n\t\t\t\t\t// A method expression T.f acts like a\n\t\t\t\t\t// reference to a func decl, so it is pure.\n\t\t\t\t\treturn true\n\n\t\t\t\tcase types.MethodVal, types.FieldVal:\n\t\t\t\t\t// A field or method selection x.f is pure\n\t\t\t\t\t// if x is pure and the selection does\n\t\t\t\t\t// not indirect a pointer.\n\t\t\t\t\treturn !indirectSelection(seln) && pure(e.X)\n\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(seln)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// A qualified identifier is\n\t\t\t\t// treated like an unqualified one.\n\t\t\t\treturn pure(e.Sel)\n\t\t\t}\n\n\t\tcase *ast.StarExpr:\n\t\t\treturn false // *ptr depends on the state of the heap\n\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t}\n\treturn pure(e)\n}\n\n// duplicable reports whether it is appropriate for the expression to\n// be freely duplicated.\n//\n// Given the declaration\n//\n//\tfunc f(x T) T { return x + g() + x }\n//\n// an argument y is considered duplicable if we would wish to see a\n// call f(y) simplified to y+g()+y. This is true for identifiers,\n// integer literals, unary negation, and selectors x.f where x is not\n// a pointer. But we would not wish to duplicate expressions that:\n// - have side effects (e.g. nearly all calls),\n// - are not referentially transparent (e.g. &T{}, ptr.field, *ptr), or\n// - are long (e.g. \"huge string literal\").\nfunc duplicable(info *types.Info, e ast.Expr) bool {\n\tswitch e := e.(type) {\n\tcase *ast.ParenExpr:\n\t\treturn duplicable(info, e.X)\n\n\tcase *ast.Ident:\n\t\treturn true\n\n\tcase *ast.BasicLit:\n\t\tv := info.Types[e].Value\n\t\tswitch e.Kind {\n\t\tcase token.INT:\n\t\t\treturn true // any int\n\t\tcase token.STRING:\n\t\t\treturn consteq(v, kZeroString) // only \"\"\n\t\tcase token.FLOAT:\n\t\t\treturn consteq(v, kZeroFloat) || consteq(v, kOneFloat) // only 0.0 or 1.0\n\t\t}\n\n\tcase *ast.UnaryExpr: // e.g. +1, -1\n\t\treturn (e.Op == token.ADD || e.Op == token.SUB) && duplicable(info, e.X)\n\n\tcase *ast.CompositeLit:\n\t\t// Empty struct or array literals T{} are duplicable.\n\t\t// (Non-empty literals are too verbose, and slice/map\n\t\t// literals allocate indirect variables.)\n\t\tif len(e.Elts) == 0 {\n\t\t\tswitch info.TypeOf(e).Underlying().(type) {\n\t\t\tcase *types.Struct, *types.Array:\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\n\tcase *ast.CallExpr:\n\t\t// Treat type conversions as duplicable if they do not observably allocate.\n\t\t// The only cases of observable allocations are\n\t\t// the `[]byte(string)` and `[]rune(string)` conversions.\n\t\t//\n\t\t// Duplicating string([]byte) conversions increases\n\t\t// allocation but doesn't change behavior, but the\n\t\t// reverse, []byte(string), allocates a distinct array,\n\t\t// which is observable.\n\n\t\tif !info.Types[e.Fun].IsType() { // check whether e.Fun is a type conversion\n\t\t\treturn false\n\t\t}\n\n\t\tfun := info.TypeOf(e.Fun)\n\t\targ := info.TypeOf(e.Args[0])\n\n\t\tswitch fun := fun.Underlying().(type) {\n\t\tcase *types.Slice:\n\t\t\t// Do not mark []byte(string) and []rune(string) as duplicable.\n\t\t\telem, ok := fun.Elem().Underlying().(*types.Basic)\n\t\t\tif ok && (elem.Kind() == types.Rune || elem.Kind() == types.Byte) {\n\t\t\t\tfrom, ok := arg.Underlying().(*types.Basic)\n\t\t\t\tisString := ok && from.Info()&types.IsString != 0\n\t\t\t\treturn !isString\n\t\t\t}\n\t\tcase *types.TypeParam:\n\t\t\treturn false // be conservative\n\t\t}\n\t\treturn true\n\n\tcase *ast.SelectorExpr:\n\t\tif seln, ok := info.Selections[e]; ok {\n\t\t\t// A field or method selection x.f is referentially\n\t\t\t// transparent if it does not indirect a pointer.\n\t\t\treturn !indirectSelection(seln)\n\t\t}\n\t\t// A qualified identifier pkg.Name is referentially transparent.\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc consteq(x, y constant.Value) bool {\n\treturn constant.Compare(x, token.EQL, y)\n}\n\nvar (\n\tkZeroInt    = constant.MakeInt64(0)\n\tkZeroString = constant.MakeString(\"\")\n\tkZeroFloat  = constant.MakeFloat64(0.0)\n\tkOneFloat   = constant.MakeFloat64(1.0)\n)\n\n// -- inline helpers --\n\nfunc assert(cond bool, msg string) {\n\tif !cond {\n\t\tpanic(msg)\n\t}\n}\n\n// blanks returns a slice of n > 0 blank identifiers.\nfunc blanks[E ast.Expr](n int) []E {\n\tif n == 0 {\n\t\tpanic(\"blanks(0)\")\n\t}\n\tres := make([]E, n)\n\tfor i := range res {\n\t\tres[i] = ast.Expr(makeIdent(\"_\")).(E) // ugh\n\t}\n\treturn res\n}\n\nfunc makeIdent(name string) *ast.Ident {\n\treturn &ast.Ident{Name: name}\n}\n\n// importedPkgName returns the PkgName object declared by an ImportSpec.\n// TODO(adonovan): make this a method of types.Info (#62037).\nfunc importedPkgName(info *types.Info, imp *ast.ImportSpec) (*types.PkgName, bool) {\n\tvar obj types.Object\n\tif imp.Name != nil {\n\t\tobj = info.Defs[imp.Name]\n\t} else {\n\t\tobj = info.Implicits[imp]\n\t}\n\tpkgname, ok := obj.(*types.PkgName)\n\treturn pkgname, ok\n}\n\nfunc isPkgLevel(obj types.Object) bool {\n\t// TODO(adonovan): consider using the simpler obj.Parent() ==\n\t// obj.Pkg().Scope() instead. But be sure to test carefully\n\t// with instantiations of generics.\n\treturn obj.Pkg().Scope().Lookup(obj.Name()) == obj\n}\n\n// callContext returns the two nodes immediately enclosing the call\n// (specified as a PathEnclosingInterval), ignoring parens.\nfunc callContext(callPath []ast.Node) (parent, grandparent ast.Node) {\n\t_ = callPath[0].(*ast.CallExpr) // sanity check\n\tfor _, n := range callPath[1:] {\n\t\tif !is[*ast.ParenExpr](n) {\n\t\t\tif parent == nil {\n\t\t\t\tparent = n\n\t\t\t} else {\n\t\t\t\treturn parent, n\n\t\t\t}\n\t\t}\n\t}\n\treturn parent, nil\n}\n\n// hasLabelConflict reports whether the set of labels of the function\n// enclosing the call (specified as a PathEnclosingInterval)\n// intersects with the set of callee labels.\nfunc hasLabelConflict(callPath []ast.Node, calleeLabels []string) bool {\n\tlabels := callerLabels(callPath)\n\tfor _, label := range calleeLabels {\n\t\tif labels[label] {\n\t\t\treturn true // conflict\n\t\t}\n\t}\n\treturn false\n}\n\n// callerLabels returns the set of control labels in the function (if\n// any) enclosing the call (specified as a PathEnclosingInterval).\nfunc callerLabels(callPath []ast.Node) map[string]bool {\n\tvar callerBody *ast.BlockStmt\n\tswitch f := callerFunc(callPath).(type) {\n\tcase *ast.FuncDecl:\n\t\tcallerBody = f.Body\n\tcase *ast.FuncLit:\n\t\tcallerBody = f.Body\n\t}\n\tvar labels map[string]bool\n\tif callerBody != nil {\n\t\tast.Inspect(callerBody, func(n ast.Node) bool {\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.FuncLit:\n\t\t\t\treturn false // prune traversal\n\t\t\tcase *ast.LabeledStmt:\n\t\t\t\tif labels == nil {\n\t\t\t\t\tlabels = make(map[string]bool)\n\t\t\t\t}\n\t\t\t\tlabels[n.Label.Name] = true\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n\treturn labels\n}\n\n// callerFunc returns the innermost Func{Decl,Lit} node enclosing the\n// call (specified as a PathEnclosingInterval).\nfunc callerFunc(callPath []ast.Node) ast.Node {\n\t_ = callPath[0].(*ast.CallExpr) // sanity check\n\tfor _, n := range callPath[1:] {\n\t\tif is[*ast.FuncDecl](n) || is[*ast.FuncLit](n) {\n\t\t\treturn n\n\t\t}\n\t}\n\treturn nil\n}\n\n// callStmt reports whether the function call (specified\n// as a PathEnclosingInterval) appears within an ExprStmt,\n// and returns it if so.\n//\n// If unrestricted, callStmt returns nil if the ExprStmt f() appears\n// in a restricted context (such as \"if f(); cond {\") where it cannot\n// be replaced by an arbitrary statement. (See \"statement theory\".)\nfunc callStmt(callPath []ast.Node, unrestricted bool) *ast.ExprStmt {\n\tparent, _ := callContext(callPath)\n\tstmt, ok := parent.(*ast.ExprStmt)\n\tif ok && unrestricted {\n\t\tswitch callPath[slices.Index(callPath, ast.Node(stmt))+1].(type) {\n\t\tcase *ast.LabeledStmt,\n\t\t\t*ast.BlockStmt,\n\t\t\t*ast.CaseClause,\n\t\t\t*ast.CommClause:\n\t\t\t// unrestricted\n\t\tdefault:\n\t\t\t// TODO(adonovan): handle restricted\n\t\t\t// XYZStmt.Init contexts (but not ForStmt.Post)\n\t\t\t// by creating a block around the if/for/switch:\n\t\t\t// \"if f(); cond {\"  ->  \"{ stmts; if cond {\"\n\n\t\t\treturn nil // restricted\n\t\t}\n\t}\n\treturn stmt\n}\n\n// Statement theory\n//\n// These are all the places a statement may appear in the AST:\n//\n// LabeledStmt.Stmt       Stmt      -- any\n// BlockStmt.List       []Stmt      -- any (but see switch/select)\n// IfStmt.Init            Stmt?     -- simple\n// IfStmt.Body            BlockStmt\n// IfStmt.Else            Stmt?     -- IfStmt or BlockStmt\n// CaseClause.Body      []Stmt      -- any\n// SwitchStmt.Init        Stmt?     -- simple\n// SwitchStmt.Body        BlockStmt -- CaseClauses only\n// TypeSwitchStmt.Init    Stmt?     -- simple\n// TypeSwitchStmt.Assign  Stmt      -- AssignStmt(TypeAssertExpr) or ExprStmt(TypeAssertExpr)\n// TypeSwitchStmt.Body    BlockStmt -- CaseClauses only\n// CommClause.Comm        Stmt?     -- SendStmt or ExprStmt(UnaryExpr) or AssignStmt(UnaryExpr)\n// CommClause.Body      []Stmt      -- any\n// SelectStmt.Body        BlockStmt -- CommClauses only\n// ForStmt.Init           Stmt?     -- simple\n// ForStmt.Post           Stmt?     -- simple\n// ForStmt.Body           BlockStmt\n// RangeStmt.Body         BlockStmt\n//\n// simple = AssignStmt | SendStmt | IncDecStmt | ExprStmt.\n//\n// A BlockStmt cannot replace an ExprStmt in\n// {If,Switch,TypeSwitch}Stmt.Init or ForStmt.Post.\n// That is allowed only within:\n//   LabeledStmt.Stmt       Stmt\n//   BlockStmt.List       []Stmt\n//   CaseClause.Body      []Stmt\n//   CommClause.Body      []Stmt\n\n// replaceNode performs a destructive update of the tree rooted at\n// root, replacing each occurrence of \"from\" with \"to\". If to is nil and\n// the element is within a slice, the slice element is removed.\n//\n// The root itself cannot be replaced; an attempt will panic.\n//\n// This function must not be called on the caller's syntax tree.\n//\n// TODO(adonovan): polish this up and move it to astutil package.\n// TODO(adonovan): needs a unit test.\nfunc replaceNode(root ast.Node, from, to ast.Node) {\n\tif from == nil {\n\t\tpanic(\"from == nil\")\n\t}\n\tif reflect.ValueOf(from).IsNil() {\n\t\tpanic(fmt.Sprintf(\"from == (%T)(nil)\", from))\n\t}\n\tif from == root {\n\t\tpanic(\"from == root\")\n\t}\n\tfound := false\n\tvar parent reflect.Value // parent variable of interface type, containing a pointer\n\tvar visit func(reflect.Value)\n\tvisit = func(v reflect.Value) {\n\t\tswitch v.Kind() {\n\t\tcase reflect.Pointer:\n\t\t\tif v.Interface() == from {\n\t\t\t\tfound = true\n\n\t\t\t\t// If v is a struct field or array element\n\t\t\t\t// (e.g. Field.Comment or Field.Names[i])\n\t\t\t\t// then it is addressable (a pointer variable).\n\t\t\t\t//\n\t\t\t\t// But if it was the value an interface\n\t\t\t\t// (e.g. *ast.Ident within ast.Node)\n\t\t\t\t// then it is non-addressable, and we need\n\t\t\t\t// to set the enclosing interface (parent).\n\t\t\t\tif !v.CanAddr() {\n\t\t\t\t\tv = parent\n\t\t\t\t}\n\n\t\t\t\t// to=nil => use zero value\n\t\t\t\tvar toV reflect.Value\n\t\t\t\tif to != nil {\n\t\t\t\t\ttoV = reflect.ValueOf(to)\n\t\t\t\t} else {\n\t\t\t\t\ttoV = reflect.Zero(v.Type()) // e.g. ast.Expr(nil)\n\t\t\t\t}\n\t\t\t\tv.Set(toV)\n\n\t\t\t} else if !v.IsNil() {\n\t\t\t\tswitch v.Interface().(type) {\n\t\t\t\tcase *ast.Object, *ast.Scope:\n\t\t\t\t\t// Skip fields of types potentially involved in cycles.\n\t\t\t\tdefault:\n\t\t\t\t\tvisit(v.Elem())\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase reflect.Struct:\n\t\t\tfor i := range v.Type().NumField() {\n\t\t\t\tvisit(v.Field(i))\n\t\t\t}\n\n\t\tcase reflect.Slice:\n\t\t\tcompact := false\n\t\t\tfor i := range v.Len() {\n\t\t\t\tvisit(v.Index(i))\n\t\t\t\tif v.Index(i).IsNil() {\n\t\t\t\t\tcompact = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif compact {\n\t\t\t\t// Elements were deleted. Eliminate nils.\n\t\t\t\t// (Do this is a second pass to avoid\n\t\t\t\t// unnecessary writes in the common case.)\n\t\t\t\tj := 0\n\t\t\t\tfor i := range v.Len() {\n\t\t\t\t\tif !v.Index(i).IsNil() {\n\t\t\t\t\t\tv.Index(j).Set(v.Index(i))\n\t\t\t\t\t\tj++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tv.SetLen(j)\n\t\t\t}\n\t\tcase reflect.Interface:\n\t\t\tparent = v\n\t\t\tvisit(v.Elem())\n\n\t\tcase reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer:\n\t\t\tpanic(v) // unreachable in AST\n\t\tdefault:\n\t\t\t// bool, string, number: nop\n\t\t}\n\t\tparent = reflect.Value{}\n\t}\n\tvisit(reflect.ValueOf(root))\n\tif !found {\n\t\tpanic(fmt.Sprintf(\"%T not found\", from))\n\t}\n}\n\n// cleanNode returns a clone of node with positions cleared.\n//\n// It should be used for any callee nodes that are formatted using the caller\n// file set.\nfunc cleanNode[T ast.Node](node T) T {\n\tclone := internalastutil.CloneNode(node)\n\tclearPositions(clone)\n\treturn clone\n}\n\nfunc cleanNodes[T ast.Node](nodes []T) []T {\n\tvar clean []T\n\tfor _, node := range nodes {\n\t\tclean = append(clean, cleanNode(node))\n\t}\n\treturn clean\n}\n\n// clearPositions destroys token.Pos information within the tree rooted at root,\n// as positions in callee trees may cause caller comments to be emitted prematurely.\n//\n// In general it isn't safe to clear a valid Pos because some of them\n// (e.g. CallExpr.Ellipsis, TypeSpec.Assign) are significant to\n// go/printer, so this function sets each non-zero Pos to 1, which\n// suffices to avoid advancing the printer's comment cursor.\n//\n// This function mutates its argument; do not invoke on caller syntax.\n//\n// TODO(adonovan): remove this horrendous workaround when #20744 is finally fixed.\nfunc clearPositions(root ast.Node) {\n\tposType := reflect.TypeFor[token.Pos]()\n\tast.Inspect(root, func(n ast.Node) bool {\n\t\tif n != nil {\n\t\t\tv := reflect.ValueOf(n).Elem() // deref the pointer to struct\n\t\t\tfields := v.Type().NumField()\n\t\t\tfor i := range fields {\n\t\t\t\tf := v.Field(i)\n\t\t\t\t// Clearing Pos arbitrarily is destructive,\n\t\t\t\t// as its presence may be semantically significant\n\t\t\t\t// (e.g. CallExpr.Ellipsis, TypeSpec.Assign)\n\t\t\t\t// or affect formatting preferences (e.g. GenDecl.Lparen).\n\t\t\t\t//\n\t\t\t\t// Note: for proper formatting, it may be necessary to be selective\n\t\t\t\t// about which positions we set to 1 vs which we set to token.NoPos.\n\t\t\t\t// (e.g. we can set most to token.NoPos, save the few that are\n\t\t\t\t// significant).\n\t\t\t\tif f.Type() == posType {\n\t\t\t\t\tif f.Interface() != token.NoPos {\n\t\t\t\t\t\tf.Set(reflect.ValueOf(token.Pos(1)))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\n// findIdent finds the Ident beneath root that has the given pos.\n// It returns the path to the ident (excluding the ident), and the ident\n// itself, where the path is the sequence of ast.Nodes encountered in a\n// depth-first search to find ident.\nfunc findIdent(root ast.Node, pos token.Pos) ([]ast.Node, *ast.Ident) {\n\t// TODO(adonovan): opt: skip subtrees that don't contain pos.\n\tvar (\n\t\tpath  []ast.Node\n\t\tfound *ast.Ident\n\t)\n\tast.Inspect(root, func(n ast.Node) bool {\n\t\tif found != nil {\n\t\t\treturn false\n\t\t}\n\t\tif n == nil {\n\t\t\tpath = path[:len(path)-1]\n\t\t\treturn false\n\t\t}\n\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\tif id.Pos() == pos {\n\t\t\t\tfound = id\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\tpath = append(path, n)\n\t\treturn true\n\t})\n\tif found == nil {\n\t\tpanic(fmt.Sprintf(\"findIdent %d not found in %s\",\n\t\t\tpos, debugFormatNode(token.NewFileSet(), root)))\n\t}\n\treturn path, found\n}\n\nfunc prepend[T any](elem T, slice ...T) []T {\n\treturn append([]T{elem}, slice...)\n}\n\n// debugFormatNode formats a node or returns a formatting error.\n// Its sloppy treatment of errors is appropriate only for logging.\nfunc debugFormatNode(fset *token.FileSet, n ast.Node) string {\n\tvar out strings.Builder\n\tif err := format.Node(&out, fset, n); err != nil {\n\t\tout.WriteString(err.Error())\n\t}\n\treturn out.String()\n}\n\nfunc shallowCopy[T any](ptr *T) *T {\n\tcopy := *ptr\n\treturn &copy\n}\n\n// ∀\nfunc forall[T any](list []T, f func(i int, x T) bool) bool {\n\tfor i, x := range list {\n\t\tif !f(i, x) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// ∃\nfunc exists[T any](list []T, f func(i int, x T) bool) bool {\n\tfor i, x := range list {\n\t\tif f(i, x) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// last returns the last element of a slice, or zero if empty.\nfunc last[T any](slice []T) T {\n\tn := len(slice)\n\tif n > 0 {\n\t\treturn slice[n-1]\n\t}\n\treturn *new(T)\n}\n\n// declares returns the set of lexical names declared by a\n// sequence of statements from the same block, excluding sub-blocks.\n// (Lexical names do not include control labels.)\nfunc declares(stmts []ast.Stmt) map[string]bool {\n\tnames := make(map[string]bool)\n\tfor _, stmt := range stmts {\n\t\tswitch stmt := stmt.(type) {\n\t\tcase *ast.DeclStmt:\n\t\t\tfor _, spec := range stmt.Decl.(*ast.GenDecl).Specs {\n\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\tcase *ast.ValueSpec:\n\t\t\t\t\tfor _, id := range spec.Names {\n\t\t\t\t\t\tnames[id.Name] = true\n\t\t\t\t\t}\n\t\t\t\tcase *ast.TypeSpec:\n\t\t\t\t\tnames[spec.Name.Name] = true\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.AssignStmt:\n\t\t\tif stmt.Tok == token.DEFINE {\n\t\t\t\tfor _, lhs := range stmt.Lhs {\n\t\t\t\t\tnames[lhs.(*ast.Ident).Name] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tdelete(names, \"_\")\n\treturn names\n}\n\n// A importNameFunc is used to query local import names in the caller, in a\n// particular shadowing context.\n//\n// The shadow map contains additional names shadowed in the inlined code, at\n// the position the local import name is to be used. The shadow map only needs\n// to contain newly introduced names in the inlined code; names shadowed at the\n// caller are handled automatically.\ntype importNameFunc = func(pkgPath string, shadow shadowMap) string\n\n// assignStmts rewrites a statement assigning the results of a call into zero\n// or more statements that assign its return operands, or (nil, false) if no\n// such rewrite is possible. The set of bindings created by the result of\n// assignStmts is the same as the set of bindings created by the callerStmt.\n//\n// The callee must contain exactly one return statement.\n//\n// This is (once again) a surprisingly complex task. For example, depending on\n// types and existing bindings, the assignment\n//\n//\ta, b := f()\n//\n// could be rewritten as:\n//\n//\ta, b := 1, 2\n//\n// but may need to be written as:\n//\n//\ta, b := int8(1), int32(2)\n//\n// In the case where the return statement within f is a spread call to another\n// function g(), we cannot explicitly convert the return values inline, and so\n// it may be necessary to split the declaration and assignment of variables\n// into separate statements:\n//\n//\ta, b := g()\n//\n// or\n//\n//\tvar a int32\n//\ta, b = g()\n//\n// or\n//\n//\tvar (\n//\t\ta int8\n//\t\tb int32\n//\t)\n//\ta, b = g()\n//\n// Note: assignStmts may return (nil, true) if it determines that the rewritten\n// assignment consists only of _ = nil assignments.\nfunc (st *state) assignStmts(callerStmt *ast.AssignStmt, returnOperands []ast.Expr, importName importNameFunc) ([]ast.Stmt, bool) {\n\tlogf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl\n\n\tassert(len(callee.Returns) == 1, \"unexpected multiple returns\")\n\tresultInfo := callee.Returns[0]\n\n\t// When constructing assign statements, we need to make sure that we don't\n\t// modify types on the left-hand side, such as would happen if the type of a\n\t// RHS expression does not match the corresponding LHS type at the caller\n\t// (due to untyped conversion or interface widening).\n\t//\n\t// This turns out to be remarkably tricky to handle correctly.\n\t//\n\t// Substrategies below are labeled as `Substrategy <name>:`.\n\n\t// Collect LHS information.\n\tvar (\n\t\tlhs    []ast.Expr                                // shallow copy of the LHS slice, for mutation\n\t\tdefs   = make([]*ast.Ident, len(callerStmt.Lhs)) // indexes in lhs of defining identifiers\n\t\tblanks = make([]bool, len(callerStmt.Lhs))       // indexes in lhs of blank identifiers\n\t\tbyType typeutil.Map                              // map of distinct types -> indexes, for writing specs later\n\t)\n\tfor i, expr := range callerStmt.Lhs {\n\t\tlhs = append(lhs, expr)\n\t\tif name, ok := expr.(*ast.Ident); ok {\n\t\t\tif name.Name == \"_\" {\n\t\t\t\tblanks[i] = true\n\t\t\t\tcontinue // no type\n\t\t\t}\n\n\t\t\tif obj, isDef := caller.Info.Defs[name]; isDef {\n\t\t\t\tdefs[i] = name\n\t\t\t\ttyp := obj.Type()\n\t\t\t\tidxs, _ := byType.At(typ).([]int)\n\t\t\t\tidxs = append(idxs, i)\n\t\t\t\tbyType.Set(typ, idxs)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect RHS information\n\t//\n\t// The RHS is either a parallel assignment or spread assignment, but by\n\t// looping over both callerStmt.Rhs and returnOperands we handle both.\n\tvar (\n\t\trhs             []ast.Expr              // new RHS of assignment, owned by the inliner\n\t\tcallIdx         = -1                    // index of the call among the original RHS\n\t\tnilBlankAssigns = make(map[int]unit)    // indexes in rhs of _ = nil assignments, which can be deleted\n\t\tfreeNames       = make(map[string]bool) // free(ish) names among rhs expressions\n\t\tnonTrivial      = make(map[int]bool)    // indexes in rhs of nontrivial result conversions\n\t)\n\tconst includeComplitIdents = true\n\n\tfor i, expr := range callerStmt.Rhs {\n\t\tif expr == caller.Call {\n\t\t\tassert(callIdx == -1, \"malformed (duplicative) AST\")\n\t\t\tcallIdx = i\n\t\t\tfor j, returnOperand := range returnOperands {\n\t\t\t\tmaps.Copy(freeNames, free.Names(returnOperand, includeComplitIdents))\n\t\t\t\trhs = append(rhs, returnOperand)\n\t\t\t\tif resultInfo[j]&nonTrivialResult != 0 {\n\t\t\t\t\tnonTrivial[i+j] = true\n\t\t\t\t}\n\t\t\t\tif blanks[i+j] && resultInfo[j]&untypedNilResult != 0 {\n\t\t\t\t\tnilBlankAssigns[i+j] = unit{}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// We must clone before clearing positions, since e came from the caller.\n\t\t\texpr = internalastutil.CloneNode(expr)\n\t\t\tclearPositions(expr)\n\t\t\tmaps.Copy(freeNames, free.Names(expr, includeComplitIdents))\n\t\t\trhs = append(rhs, expr)\n\t\t}\n\t}\n\tassert(callIdx >= 0, \"failed to find call in RHS\")\n\n\t// Substrategy \"splice\": Check to see if we can simply splice in the result\n\t// expressions from the callee, such as simplifying\n\t//\n\t//  x, y := f()\n\t//\n\t// to\n\t//\n\t//  x, y := e1, e2\n\t//\n\t// where the types of x and y match the types of e1 and e2.\n\t//\n\t// This works as long as we don't need to write any additional type\n\t// information.\n\tif len(nonTrivial) == 0 { // no non-trivial conversions to worry about\n\n\t\tlogf(\"substrategy: splice assignment\")\n\t\treturn []ast.Stmt{&ast.AssignStmt{\n\t\t\tLhs:    lhs,\n\t\t\tTok:    callerStmt.Tok,\n\t\t\tTokPos: callerStmt.TokPos,\n\t\t\tRhs:    rhs,\n\t\t}}, true\n\t}\n\n\t// Inlining techniques below will need to write type information in order to\n\t// preserve the correct types of LHS identifiers.\n\t//\n\t// typeExpr is a simple helper to write out type expressions. It currently\n\t// handles (possibly qualified) type names.\n\t//\n\t// TODO(rfindley):\n\t//   1. expand this to handle more type expressions.\n\t//   2. refactor to share logic with callee rewriting.\n\tuniverseAny := types.Universe.Lookup(\"any\")\n\ttypeExpr := func(typ types.Type, shadow shadowMap) ast.Expr {\n\t\tvar (\n\t\t\ttypeName string\n\t\t\tobj      *types.TypeName // nil for basic types\n\t\t)\n\t\tif tname := typesinternal.TypeNameFor(typ); tname != nil {\n\t\t\tobj = tname\n\t\t\ttypeName = tname.Name()\n\t\t}\n\n\t\t// Special case: check for universe \"any\".\n\t\t// TODO(golang/go#66921): this may become unnecessary if any becomes a proper alias.\n\t\tif typ == universeAny.Type() {\n\t\t\ttypeName = \"any\"\n\t\t}\n\n\t\tif typeName == \"\" {\n\t\t\treturn nil\n\t\t}\n\n\t\tif obj == nil || obj.Pkg() == nil || obj.Pkg() == caller.Types { // local type or builtin\n\t\t\tif shadow[typeName] != 0 {\n\t\t\t\tlogf(\"cannot write shadowed type name %q\", typeName)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tobj, _ := caller.lookup(typeName).(*types.TypeName)\n\t\t\tif obj != nil && types.Identical(obj.Type(), typ) {\n\t\t\t\treturn ast.NewIdent(typeName)\n\t\t\t}\n\t\t} else if pkgName := importName(obj.Pkg().Path(), shadow); pkgName != \"\" {\n\t\t\treturn &ast.SelectorExpr{\n\t\t\t\tX:   ast.NewIdent(pkgName),\n\t\t\t\tSel: ast.NewIdent(typeName),\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Substrategy \"spread\": in the case of a spread call (func f() (T1, T2) return\n\t// g()), since we didn't hit the 'splice' substrategy, there must be some\n\t// non-declaring expression on the LHS. Simplify this by pre-declaring\n\t// variables, rewriting\n\t//\n\t//   x, y := f()\n\t//\n\t// to\n\t//\n\t//  var x int\n\t//  x, y = g()\n\t//\n\t// Which works as long as the predeclared variables do not overlap with free\n\t// names on the RHS.\n\tif len(rhs) != len(lhs) {\n\t\tassert(len(rhs) == 1 && len(returnOperands) == 1, \"expected spread call\")\n\n\t\tfor _, id := range defs {\n\t\t\tif id != nil && freeNames[id.Name] {\n\t\t\t\t// By predeclaring variables, we're changing them to be in scope of the\n\t\t\t\t// RHS. We can't do this if their names are free on the RHS.\n\t\t\t\treturn nil, false\n\t\t\t}\n\t\t}\n\n\t\t// Write out the specs, being careful to avoid shadowing free names in\n\t\t// their type expressions.\n\t\tvar (\n\t\t\tspecs    []ast.Spec\n\t\t\tspecIdxs []int\n\t\t\tshadow   = make(shadowMap)\n\t\t)\n\t\tfailed := false\n\t\tbyType.Iterate(func(typ types.Type, v any) {\n\t\t\tif failed {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tidxs := v.([]int)\n\t\t\tspecIdxs = append(specIdxs, idxs[0])\n\t\t\ttexpr := typeExpr(typ, shadow)\n\t\t\tif texpr == nil {\n\t\t\t\tfailed = true\n\t\t\t\treturn\n\t\t\t}\n\t\t\tspec := &ast.ValueSpec{\n\t\t\t\tType: texpr,\n\t\t\t}\n\t\t\tfor _, idx := range idxs {\n\t\t\t\tspec.Names = append(spec.Names, ast.NewIdent(defs[idx].Name))\n\t\t\t}\n\t\t\tspecs = append(specs, spec)\n\t\t})\n\t\tif failed {\n\t\t\treturn nil, false\n\t\t}\n\t\tlogf(\"substrategy: spread assignment\")\n\t\treturn []ast.Stmt{\n\t\t\t&ast.DeclStmt{\n\t\t\t\tDecl: &ast.GenDecl{\n\t\t\t\t\tTok:   token.VAR,\n\t\t\t\t\tSpecs: specs,\n\t\t\t\t},\n\t\t\t},\n\t\t\t&ast.AssignStmt{\n\t\t\t\tLhs: callerStmt.Lhs,\n\t\t\t\tTok: token.ASSIGN,\n\t\t\t\tRhs: returnOperands,\n\t\t\t},\n\t\t}, true\n\t}\n\n\tassert(len(lhs) == len(rhs), \"mismatching LHS and RHS\")\n\n\t// Substrategy \"convert\": write out RHS expressions with explicit type conversions\n\t// as necessary, rewriting\n\t//\n\t//  x, y := f()\n\t//\n\t// to\n\t//\n\t//  x, y := 1, int32(2)\n\t//\n\t// As required to preserve types.\n\t//\n\t// In the special case of _ = nil, which is disallowed by the type checker\n\t// (since nil has no default type), we delete the assignment.\n\tvar origIdxs []int // maps back to original indexes after lhs and rhs are pruned\n\ti := 0\n\tfor j := range lhs {\n\t\tif _, ok := nilBlankAssigns[j]; !ok {\n\t\t\tlhs[i] = lhs[j]\n\t\t\trhs[i] = rhs[j]\n\t\t\torigIdxs = append(origIdxs, j)\n\t\t\ti++\n\t\t}\n\t}\n\tlhs = lhs[:i]\n\trhs = rhs[:i]\n\n\tif len(lhs) == 0 {\n\t\tlogf(\"trivial assignment after pruning nil blanks assigns\")\n\t\t// After pruning, we have no remaining assignments.\n\t\t// Signal this by returning a non-nil slice of statements.\n\t\treturn nil, true\n\t}\n\n\t// Write out explicit conversions as necessary.\n\t//\n\t// A conversion is necessary if the LHS is being defined, and the RHS return\n\t// involved a nontrivial implicit conversion.\n\tfor i, expr := range rhs {\n\t\tidx := origIdxs[i]\n\t\tif nonTrivial[idx] && defs[idx] != nil {\n\t\t\ttyp := caller.Info.TypeOf(lhs[i])\n\t\t\ttexpr := typeExpr(typ, nil)\n\t\t\tif texpr == nil {\n\t\t\t\treturn nil, false\n\t\t\t}\n\t\t\tif _, ok := texpr.(*ast.StarExpr); ok {\n\t\t\t\t// TODO(rfindley): is this necessary? Doesn't the formatter add these parens?\n\t\t\t\ttexpr = &ast.ParenExpr{X: texpr} // *T -> (*T)   so that (*T)(x) is valid\n\t\t\t}\n\t\t\trhs[i] = &ast.CallExpr{\n\t\t\t\tFun:  texpr,\n\t\t\t\tArgs: []ast.Expr{expr},\n\t\t\t}\n\t\t}\n\t}\n\tlogf(\"substrategy: convert assignment\")\n\treturn []ast.Stmt{&ast.AssignStmt{\n\t\tLhs: lhs,\n\t\tTok: callerStmt.Tok,\n\t\tRhs: rhs,\n\t}}, true\n}\n\n// tailCallSafeReturn reports whether the callee's return statements may be safely\n// used to return from the function enclosing the caller (which must exist).\nfunc tailCallSafeReturn(caller *Caller, calleeSymbol *types.Func, callee *gobCallee) bool {\n\t// It is safe if all callee returns involve only trivial conversions.\n\tif !hasNonTrivialReturn(callee.Returns) {\n\t\treturn true\n\t}\n\n\tvar callerType types.Type\n\t// Find type of innermost function enclosing call.\n\t// (Beware: Caller.enclosingFunc is the outermost.)\nloop:\n\tfor _, n := range caller.path {\n\t\tswitch f := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tcallerType = caller.Info.ObjectOf(f.Name).Type()\n\t\t\tbreak loop\n\t\tcase *ast.FuncLit:\n\t\t\tcallerType = caller.Info.TypeOf(f)\n\t\t\tbreak loop\n\t\t}\n\t}\n\n\t// Non-trivial return conversions in the callee are permitted\n\t// if the same non-trivial conversion would occur after inlining,\n\t// i.e. if the caller and callee results tuples are identical.\n\tcallerResults := callerType.(*types.Signature).Results()\n\tcalleeResults := calleeSymbol.Type().(*types.Signature).Results()\n\treturn types.Identical(callerResults, calleeResults)\n}\n\n// hasNonTrivialReturn reports whether any of the returns involve a nontrivial\n// implicit conversion of a result expression.\nfunc hasNonTrivialReturn(returnInfo [][]returnOperandFlags) bool {\n\tfor _, resultInfo := range returnInfo {\n\t\tfor _, r := range resultInfo {\n\t\t\tif r&nonTrivialResult != 0 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\ntype unit struct{} // for representing sets as maps\n"
  },
  {
    "path": "internal/refactor/inline/inline_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline_test\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/binary\"\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"unsafe\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/analysis/driverutil\"\n\t\"golang.org/x/tools/internal/diff\"\n\t\"golang.org/x/tools/internal/expect\"\n\t\"golang.org/x/tools/internal/refactor\"\n\t\"golang.org/x/tools/internal/refactor/inline\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TestData executes test scenarios specified by files in testdata/*.txtar.\n// Each txtar file describes two sets of files, some containing Go source\n// and others expected results.\n//\n// The Go source files and go.mod are parsed and type-checked as a Go module.\n// Some of these files contain marker comments (in a form described below) describing\n// the inlinings to perform and whether they should succeed or fail. A marker\n// indicating success refers to another file in the txtar, not a .go\n// file, that should contain the contents of the first file after inlining.\n//\n// The marker format for success is\n//\n//\t@inline(re\"pat\", wantfile)\n//\n// The first call in the marker's line that matches pat is inlined, and the contents\n// of the resulting file must match the contents of wantfile.\n//\n// The marker format for failure is\n//\n//\t@inline(re\"pat\", re\"errpat\")\n//\n// The first argument selects the call for inlining as before, and the second\n// is a regular expression that must match the text of resulting error.\nfunc TestData(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tfiles, err := filepath.Glob(\"testdata/*.txtar\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, file := range files {\n\t\tt.Run(filepath.Base(file), func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// The few tests that use cgo should be in\n\t\t\t// files whose name includes \"cgo\".\n\t\t\tif strings.Contains(t.Name(), \"cgo\") {\n\t\t\t\ttestenv.NeedsTool(t, \"cgo\")\n\t\t\t}\n\n\t\t\t// Some tests need specific Go versions.\n\t\t\t// TODO(adonovan): remove when go1.26 is assured.\n\t\t\tif strings.HasSuffix(t.Name(), \"newexpr.txtar\") {\n\t\t\t\ttestenv.NeedsGo1Point(t, 26)\n\t\t\t}\n\n\t\t\t// Extract archive to temporary tree.\n\t\t\tar, err := txtar.ParseFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfs, err := txtar.FS(ar)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdir := testfiles.CopyToTmp(t, fs)\n\n\t\t\t// Load packages.\n\t\t\tcfg := &packages.Config{\n\t\t\t\tDir:  dir,\n\t\t\t\tMode: packages.LoadAllSyntax,\n\t\t\t\tEnv: append(os.Environ(),\n\t\t\t\t\t\"GO111MODULES=on\",\n\t\t\t\t\t\"GOPATH=\",\n\t\t\t\t\t\"GOWORK=off\",\n\t\t\t\t\t\"GOPROXY=off\"),\n\t\t\t}\n\t\t\tpkgs, err := packages.Load(cfg, \"./...\")\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Load: %v\", err)\n\t\t\t}\n\t\t\t// Report parse/type errors; they may be benign.\n\t\t\tpackages.Visit(pkgs, nil, func(pkg *packages.Package) {\n\t\t\t\tfor _, err := range pkg.Errors {\n\t\t\t\t\tt.Logf(\"warning: %v\", err)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// Process @inline notes in comments in initial packages.\n\t\t\tfor _, pkg := range pkgs {\n\t\t\t\tfor _, file := range pkg.Syntax {\n\t\t\t\t\ttokFile := pkg.Fset.File(file.FileStart)\n\t\t\t\t\t// Read file content (for @inline regexp, and inliner).\n\t\t\t\t\tcontent, err := os.ReadFile(tokFile.Name())\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Error(err)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\t// Read and process @inline notes.\n\t\t\t\t\tnotes, err := expect.ExtractGo(tokFile, file)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Errorf(\"parsing notes in %q: %v\", tokFile.Name(), err)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tfor _, note := range notes {\n\t\t\t\t\t\tposn := tokFile.PositionFor(note.Pos, false)\n\t\t\t\t\t\tif note.Name != \"inline\" {\n\t\t\t\t\t\t\tt.Errorf(\"%s: invalid marker @%s\", posn, note.Name)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif nargs := len(note.Args); nargs != 2 {\n\t\t\t\t\t\t\tt.Errorf(\"@inline: want 2 args, got %d\", nargs)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpattern, ok := note.Args[0].(*regexp.Regexp)\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tt.Errorf(\"%s: @inline(rx, want): want regular expression rx\", posn)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// want is a []byte (success) or *Regexp (failure)\n\t\t\t\t\t\tvar want any\n\t\t\t\t\t\tswitch x := note.Args[1].(type) {\n\t\t\t\t\t\tcase string, expect.Identifier:\n\t\t\t\t\t\t\tname := fmt.Sprint(x)\n\t\t\t\t\t\t\tfor _, file := range ar.Files {\n\t\t\t\t\t\t\t\tif file.Name == name {\n\t\t\t\t\t\t\t\t\twant = file.Data\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif want == nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%s: @inline(rx, want): archive entry %q not found\", posn, x)\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tcase *regexp.Regexp:\n\t\t\t\t\t\t\twant = x\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tt.Errorf(\"%s: @inline(rx, want): want file name (to assert success) or error message regexp (to assert failure)\", posn)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif err := doInlineNote(t.Logf, pkg, file, content, pattern, posn, want); err != nil {\n\t\t\t\t\t\t\tt.Errorf(\"%s: @inline(%v, %v): %v\", posn, note.Args[0], note.Args[1], err)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// doInlineNote executes an assertion specified by a single\n// @inline(re\"pattern\", want) note in a comment. It finds the first\n// match of regular expression 'pattern' on the same line, finds the\n// innermost enclosing CallExpr, and inlines it.\n//\n// Finally it checks that, on success, the transformed file is equal\n// to want (a []byte), or on failure that the error message matches\n// want (a *Regexp).\nfunc doInlineNote(logf func(string, ...any), pkg *packages.Package, file *ast.File, content []byte, pattern *regexp.Regexp, posn token.Position, want any) error {\n\t// Find extent of pattern match within commented line.\n\tvar startPos, endPos token.Pos\n\t{\n\t\ttokFile := pkg.Fset.File(file.FileStart)\n\t\tlineStartOffset := int(tokFile.LineStart(posn.Line)) - tokFile.Base()\n\t\tline := content[lineStartOffset:]\n\t\tif i := bytes.IndexByte(line, '\\n'); i >= 0 {\n\t\t\tline = line[:i]\n\t\t}\n\t\tmatches := pattern.FindSubmatchIndex(line)\n\t\tvar start, end int // offsets\n\t\tswitch len(matches) {\n\t\tcase 2:\n\t\t\t// no subgroups: return the range of the regexp expression\n\t\t\tstart, end = matches[0], matches[1]\n\t\tcase 4:\n\t\t\t// one subgroup: return its range\n\t\t\tstart, end = matches[2], matches[3]\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid location regexp %q: expect either 0 or 1 subgroups, got %d\",\n\t\t\t\tpattern, len(matches)/2-1)\n\t\t}\n\t\tstartPos = tokFile.Pos(lineStartOffset + start)\n\t\tendPos = tokFile.Pos(lineStartOffset + end)\n\t}\n\n\t// Find innermost call enclosing the pattern match.\n\tvar caller *inline.Caller\n\t{\n\t\tpath, _ := astutil.PathEnclosingInterval(file, startPos, endPos)\n\t\tfor _, n := range path {\n\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\tcaller = &inline.Caller{\n\t\t\t\t\tFset:  pkg.Fset,\n\t\t\t\t\tTypes: pkg.Types,\n\t\t\t\t\tInfo:  pkg.TypesInfo,\n\t\t\t\t\tFile:  file,\n\t\t\t\t\tCall:  call,\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif caller == nil {\n\t\t\treturn fmt.Errorf(\"no enclosing call\")\n\t\t}\n\t}\n\n\t// Is it a static function call?\n\tfn := typeutil.StaticCallee(caller.Info, caller.Call)\n\tif fn == nil {\n\t\treturn fmt.Errorf(\"cannot inline: not a static call\")\n\t}\n\n\t// Find callee function.\n\tvar calleePkg *packages.Package\n\t{\n\t\t// Is the call within the package?\n\t\tif fn.Pkg() == caller.Types {\n\t\t\tcalleePkg = pkg // same as caller\n\t\t} else {\n\t\t\t// Different package. Load it now.\n\t\t\t// (The primary load loaded all dependencies,\n\t\t\t// but we choose to load it again, with\n\t\t\t// a distinct token.FileSet and types.Importer,\n\t\t\t// to keep the implementation honest.)\n\t\t\tcfg := &packages.Config{\n\t\t\t\t// TODO(adonovan): get the original module root more cleanly\n\t\t\t\tDir:  filepath.Dir(filepath.Dir(pkg.GoFiles[0])),\n\t\t\t\tFset: token.NewFileSet(),\n\t\t\t\tMode: packages.LoadSyntax,\n\t\t\t}\n\t\t\troots, err := packages.Load(cfg, fn.Pkg().Path())\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading callee package: %v\", err)\n\t\t\t}\n\t\t\tif packages.PrintErrors(roots) > 0 {\n\t\t\t\treturn fmt.Errorf(\"callee package had errors\") // (see log)\n\t\t\t}\n\t\t\tcalleePkg = roots[0]\n\t\t}\n\t}\n\n\tcalleeDecl, err := findFuncByPosition(calleePkg, caller.Fset.PositionFor(fn.Pos(), false))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Do the inlining. For the purposes of the test,\n\t// AnalyzeCallee and Inline are a single operation.\n\tres, err := func() (*inline.Result, error) {\n\t\tfilename := calleePkg.Fset.File(calleeDecl.Pos()).Name()\n\t\tcontent, err := os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcallee, err := inline.AnalyzeCallee(\n\t\t\tlogf,\n\t\t\tcalleePkg.Fset,\n\t\t\tcalleePkg.Types,\n\t\t\tcalleePkg.TypesInfo,\n\t\t\tcalleeDecl,\n\t\t\tcontent)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif err := checkTranscode(callee); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tcheck := checkNoMutation(caller.File)\n\t\tdefer check()\n\t\treturn inline.Inline(caller, callee, &inline.Options{Logf: logf})\n\t}()\n\tif err != nil {\n\t\tif wantRE, ok := want.(*regexp.Regexp); ok {\n\t\t\tif !wantRE.MatchString(err.Error()) {\n\t\t\t\treturn fmt.Errorf(\"Inline failed with wrong error: %v (want error matching %q)\", err, want)\n\t\t\t}\n\t\t\treturn nil // expected error\n\t\t}\n\t\treturn fmt.Errorf(\"Inline failed: %v\", err) // success was expected\n\t}\n\n\t// Inline succeeded.\n\tgot, err := applyEdits(caller.Types, caller.File.FileStart, content, res.Edits)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif want, ok := want.([]byte); ok {\n\t\tgot = append(bytes.TrimSpace(got), '\\n')\n\t\twant = append(bytes.TrimSpace(want), '\\n')\n\t\t// If the \"want\" file begins \"...\", it need only be a substring of the \"got\" result,\n\t\t// rather than an exact match.\n\t\tif rest, ok := bytes.CutPrefix(want, []byte(\"...\\n\")); ok {\n\t\t\twant = rest\n\t\t\tif !bytes.Contains(got, want) {\n\t\t\t\treturn fmt.Errorf(\"Inline returned wrong output:\\n%s\\nWant substring:\\n%s\", got, want)\n\t\t\t}\n\t\t} else {\n\t\t\tif diff := diff.Unified(\"want\", \"got\", string(want), string(got)); diff != \"\" {\n\t\t\t\treturn fmt.Errorf(\"Inline returned wrong output:\\n-- got --\\n%s\\n-- want --\\n%s\\n-- diff --\\n%s\",\n\t\t\t\t\tgot, want, diff)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"Inline succeeded unexpectedly: want error matching %q, got <<%s>>\", want, got)\n}\n\n// findFuncByPosition returns the FuncDecl at the specified (package-agnostic) position.\nfunc findFuncByPosition(pkg *packages.Package, posn token.Position) (*ast.FuncDecl, error) {\n\tsame := func(decl *ast.FuncDecl) bool {\n\t\t// We can't rely on columns in export data:\n\t\t// some variants replace it with 1.\n\t\t// We can't expect file names to have the same prefix.\n\t\t// export data for go1.20 std packages have  $GOROOT written in\n\t\t// them, so how are we supposed to find the source? Yuck!\n\t\t// Ugh. need to samefile? Nope $GOROOT just won't work\n\t\t// This is highly client specific anyway.\n\t\tposn2 := pkg.Fset.PositionFor(decl.Name.Pos(), false)\n\t\treturn posn.Filename == posn2.Filename &&\n\t\t\tposn.Line == posn2.Line\n\t}\n\tfor _, file := range pkg.Syntax {\n\t\tfor _, decl := range file.Decls {\n\t\t\tif decl, ok := decl.(*ast.FuncDecl); ok && same(decl) {\n\t\t\t\treturn decl, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"can't find FuncDecl at %v in package %q\", posn, pkg.PkgPath)\n}\n\n// Each callee must declare a function or method named f,\n// and each caller must call it.\nconst funcName = \"f\"\n\n// A testcase is an item in a table-driven test.\n//\n// The table-driven tests are less flexible, but enable more compact\n// expression of single-package test cases than is possible with the\n// txtar notation.\n//\n// TODO(adonovan): improve coverage of the cross product of each\n// strategy with the checklist of concerns enumerated in the package\n// doc comment.\ntype testcase struct {\n\tdescr          string // description; substrings enable test or inliner options (e.g. \"IgnoreEffects\", \"NoPackageClause\")\n\tcallee, caller string // Go source files (sans package decl) of caller, callee\n\twant           string // expected new portion of caller file, or \"error: regexp\"\n}\n\nfunc TestErrors(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Inference of type parameters is not yet supported.\",\n\t\t\t`func f[T any](x T) T { return x }`,\n\t\t\t`var _ = f(0)`,\n\t\t\t`error: type parameter inference is not yet supported`,\n\t\t},\n\t\t{\n\t\t\t\"Methods on generic types are not yet supported.\",\n\t\t\t`type G[T any] struct{}; func (G[T]) f(x T) T { return x }`,\n\t\t\t`var _ = G[int]{}.f(0)`,\n\t\t\t`error: generic methods not yet supported`,\n\t\t},\n\t\t{\n\t\t\t\"[NoPackageClause] Can't inline a callee using newer Go to a caller using older Go (#75726).\",\n\t\t\t\"//go:build go1.23\\n\\npackage p\\nfunc f() int { return 0 }\",\n\t\t\t\"//go:build go1.22\\n\\npackage p\\nvar _ = f()\",\n\t\t\t`error: cannot inline call to p.f \\(declared using go1.23\\) into a file using go1.22`,\n\t\t},\n\t})\n}\n\nfunc TestBasics(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Basic\",\n\t\t\t`func f(x int) int { return x }`,\n\t\t\t`var _ = f(0)`,\n\t\t\t`var _ = 0`,\n\t\t},\n\t\t{\n\t\t\t\"Empty body, no arg effects.\",\n\t\t\t`func f(x, y int) {}`,\n\t\t\t`func _() { f(1, 2) }`,\n\t\t\t`func _() {}`,\n\t\t},\n\t\t{\n\t\t\t\"Empty body, some arg effects.\",\n\t\t\t`func f(x, y, z int) {}`,\n\t\t\t`func _() { f(1, recover().(int), 3) }`,\n\t\t\t`func _() { _ = recover().(int) }`,\n\t\t},\n\t\t{\n\t\t\t\"Non-duplicable arguments are not substituted even if pure.\",\n\t\t\t`func f(s string, i int) { print(s, s, i, i) }`,\n\t\t\t`func _() { f(\"hi\", 0)  }`,\n\t\t\t`func _() {\n\tvar s string = \"hi\"\n\tprint(s, s, 0, 0)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Workaround for T(x) misformatting (#63362).\",\n\t\t\t`func f(ch <-chan int) { <-ch }`,\n\t\t\t`func _(ch chan int) { f(ch) }`,\n\t\t\t`func _(ch chan int) { <-(<-chan int)(ch) }`,\n\t\t},\n\t\t{\n\t\t\t// (a regression test for unnecessary braces)\n\t\t\t\"In block elision, blank decls don't count when computing name conflicts.\",\n\t\t\t`func f(x int) { var _ = x; var _ = 3 }`,\n\t\t\t`func _() { var _ = 1; f(2) }`,\n\t\t\t`func _() {\n\tvar _ = 1\n\tvar _ = 2\n\tvar _ = 3\n}`,\n\t\t},\n\t\t{\n\t\t\t// (a regression test for a missing conversion)\n\t\t\t\"Implicit return conversions are inserted in expr-context reduction.\",\n\t\t\t`func f(x int) error { return nil }`,\n\t\t\t`func _() { if err := f(0); err != nil {} }`,\n\t\t\t`func _() {\n\tif err := error(nil); err != nil {\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Explicit type parameters.\",\n\t\t\t`func f[T any](x T) T { return x }`,\n\t\t\t`var _ = f[int](0)`,\n\t\t\t// TODO(jba): remove the unnecessary conversion.\n\t\t\t`var _ = int(0)`,\n\t\t},\n\t})\n}\n\nfunc TestDuplicable(t *testing.T) {\n\tt.Run(\"basic\", func(t *testing.T) {\n\t\trunTests(t, []testcase{\n\t\t\t{\n\t\t\t\t\"Empty strings are duplicable.\",\n\t\t\t\t`func f(s string) { print(s, s) }`,\n\t\t\t\t`func _() { f(\"\")  }`,\n\t\t\t\t`func _() { print(\"\", \"\") }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Non-empty string literals are not duplicable.\",\n\t\t\t\t`func f(s string) { print(s, s) }`,\n\t\t\t\t`func _() { f(\"hi\")  }`,\n\t\t\t\t`func _() {\n\tvar s string = \"hi\"\n\tprint(s, s)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Empty array literals are duplicable.\",\n\t\t\t\t`func f(a [2]int) { print(a, a) }`,\n\t\t\t\t`func _() { f([2]int{})  }`,\n\t\t\t\t`func _() { print([2]int{}, [2]int{}) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Non-empty array literals are not duplicable.\",\n\t\t\t\t`func f(a [2]int) { print(a, a) }`,\n\t\t\t\t`func _() { f([2]int{1, 2})  }`,\n\t\t\t\t`func _() {\n\tvar a [2]int = [2]int{1, 2}\n\tprint(a, a)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Empty struct literals are duplicable.\",\n\t\t\t\t`func f(s S) { print(s, s) }; type S struct { x int }`,\n\t\t\t\t`func _() { f(S{})  }`,\n\t\t\t\t`func _() { print(S{}, S{}) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Non-empty struct literals are not duplicable.\",\n\t\t\t\t`func f(s S) { print(s, s) }; type S struct { x int }`,\n\t\t\t\t`func _() { f(S{x: 1})  }`,\n\t\t\t\t`func _() {\n\tvar s S = S{x: 1}\n\tprint(s, s)\n}`,\n\t\t\t},\n\t\t})\n\t})\n\n\tt.Run(\"conversions\", func(t *testing.T) {\n\t\trunTests(t, []testcase{\n\t\t\t{\n\t\t\t\t\"Conversions to integer are duplicable.\",\n\t\t\t\t`func f(i int) { print(i, i) }`,\n\t\t\t\t`func _() { var i int8 = 1; f(int(i))  }`,\n\t\t\t\t`func _() { var i int8 = 1; print(int(i), int(i)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Implicit conversions from underlying types are duplicable.\",\n\t\t\t\t`func f(i I) { print(i, i) }; type I int; func print(args ...any) {}`,\n\t\t\t\t`func _() { f(1)  }`,\n\t\t\t\t`func _() { print(I(1), I(1)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions to array are duplicable.\",\n\t\t\t\t`func f(a [2]int) { print(a, a) }; type A [2]int`,\n\t\t\t\t`func _() { var a A; f([2]int(a)) }`,\n\t\t\t\t`func _() { var a A; print([2]int(a), [2]int(a)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from array are duplicable.\",\n\t\t\t\t`func f(a A) { print(a, a) }; type A [2]int`,\n\t\t\t\t`func _() { var a [2]int; f(A(a)) }`,\n\t\t\t\t`func _() { var a [2]int; print(A(a), A(a)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from byte slice to string are duplicable.\",\n\t\t\t\t`func f(s string) { print(s, s) }`,\n\t\t\t\t`func _() { var b []byte; f(string(b)) }`,\n\t\t\t\t`func _() { var b []byte; print(string(b), string(b)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from string to byte slice are not duplicable.\",\n\t\t\t\t`func f(b []byte) { print(b, b) }`,\n\t\t\t\t`func _() { var s string; f([]byte(s)) }`,\n\t\t\t\t`func _() {\n\tvar s string\n\tvar b []byte = []byte(s)\n\tprint(b, b)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from string to uint8 slice are not duplicable.\",\n\t\t\t\t`func f(b []uint8) { print(b, b) }`,\n\t\t\t\t`func _() { var s string; f([]uint8(s)) }`,\n\t\t\t\t`func _() {\n\tvar s string\n\tvar b []uint8 = []uint8(s)\n\tprint(b, b)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from string to rune slice are not duplicable.\",\n\t\t\t\t`func f(r []rune) { print(r, r) }`,\n\t\t\t\t`func _() { var s string; f([]rune(s)) }`,\n\t\t\t\t`func _() {\n\tvar s string\n\tvar r []rune = []rune(s)\n\tprint(r, r)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from string to named type with underlying byte slice are not duplicable.\",\n\t\t\t\t`func f(b B) { print(b, b) }; type B []byte`,\n\t\t\t\t`func _() { var s string; f(B(s)) }`,\n\t\t\t\t`func _() {\n\tvar s string\n\tvar b B = B(s)\n\tprint(b, b)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions from string to named type of string are duplicable.\",\n\t\t\t\t`func f(s S) { print(s, s) }; type S string`,\n\t\t\t\t`func _() { var s string; f(S(s)) }`,\n\t\t\t\t`func _() { var s string; print(S(s), S(s)) }`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Built-in function calls are not duplicable.\",\n\t\t\t\t`func f(i int) { print(i, i) }`,\n\t\t\t\t`func _() { f(len(\"\"))  }`,\n\t\t\t\t`func _() {\n\tvar i int = len(\"\")\n\tprint(i, i)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Built-in function calls are not duplicable.\",\n\t\t\t\t`func f(c complex128) { print(c, c) }`,\n\t\t\t\t`func _() { f(complex(1.0, 2.0)) }`,\n\t\t\t\t`func _() {\n\tvar c complex128 = complex(1.0, 2.0)\n\tprint(c, c)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Non built-in function calls are not duplicable.\",\n\t\t\t\t`func f(i int) { print(i, i) }\n//go:noinline\nfunc f1(i int) int { return i + 1 }`,\n\t\t\t\t`func _() { f(f1(1))  }`,\n\t\t\t\t`func _() {\n\tvar i int = f1(1)\n\tprint(i, i)\n}`,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Conversions between function types are duplicable.\",\n\t\t\t\t`func f(f F) { print(f, f) }; type F func(); func f1() {}`,\n\t\t\t\t`func _() { f(F(f1))  }`,\n\t\t\t\t`func _() { print(F(f1), F(f1)) }`,\n\t\t\t},\n\t\t})\n\t})\n}\n\nfunc TestExprStmtReduction(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"A call in an unrestricted ExprStmt may be replaced by the body stmts.\",\n\t\t\t`func f() { var _ = len(\"\") }`,\n\t\t\t`func _() { f() }`,\n\t\t\t`func _() { var _ = len(\"\") }`,\n\t\t},\n\t\t{\n\t\t\t\"ExprStmts in the body of a switch case are unrestricted.\",\n\t\t\t`func f() { x := 1; print(x) }`,\n\t\t\t`func _() { switch { case true: f() } }`,\n\t\t\t`func _() {\n\tswitch {\n\tcase true:\n\t\tx := 1\n\t\tprint(x)\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"ExprStmts in the body of a select case are unrestricted.\",\n\t\t\t`func f() { x := 1; print(x) }`,\n\t\t\t`func _() { select { default: f() } }`,\n\t\t\t`func _() {\n\tselect {\n\tdefault:\n\t\tx := 1\n\t\tprint(x)\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Some ExprStmt contexts are restricted to simple statements.\",\n\t\t\t`func f() { var _ = len(\"\") }`,\n\t\t\t`func _(cond bool) { if f(); cond {} }`,\n\t\t\t`func _(cond bool) {\n\tif func() { var _ = len(\"\") }(); cond {\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Braces must be preserved to avoid a name conflict (decl before).\",\n\t\t\t`func f() { x := 1; print(x) }`,\n\t\t\t`func _() { x := 2; print(x); f() }`,\n\t\t\t`func _() {\n\tx := 2\n\tprint(x)\n\t{\n\t\tx := 1\n\t\tprint(x)\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Braces must be preserved to avoid a name conflict (decl after).\",\n\t\t\t`func f() { x := 1; print(x) }`,\n\t\t\t`func _() { f(); x := 2; print(x) }`,\n\t\t\t`func _() {\n\t{\n\t\tx := 1\n\t\tprint(x)\n\t}\n\tx := 2\n\tprint(x)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Braces must be preserved to avoid a forward jump across a decl.\",\n\t\t\t`func f() { x := 1; print(x) }`,\n\t\t\t`func _() { goto label; f(); label: }`,\n\t\t\t`func _() {\n\tgoto label\n\t{\n\t\tx := 1\n\t\tprint(x)\n\t}\nlabel:\n}`,\n\t\t},\n\t})\n}\n\nfunc TestPrecedenceParens(t *testing.T) {\n\t// Ensure that parens are inserted when (and only when) necessary\n\t// around the replacement for the call expression. (This is a special\n\t// case in the way the inliner uses a combination of AST formatting\n\t// for the call and text splicing for the rest of the file.)\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Multiplication in addition context (no parens).\",\n\t\t\t`func f(x, y int) int { return x * y }`,\n\t\t\t`func _() { _ = 1 + f(2, 3) }`,\n\t\t\t`func _() { _ = 1 + 2*3 }`,\n\t\t},\n\t\t{\n\t\t\t\"Addition in multiplication context (parens).\",\n\t\t\t`func f(x, y int) int { return x + y }`,\n\t\t\t`func _() { _ = 1 * f(2, 3) }`,\n\t\t\t`func _() { _ = 1 * (2 + 3) }`,\n\t\t},\n\t\t{\n\t\t\t\"Addition in negation context (parens).\",\n\t\t\t`func f(x, y int) int { return x + y }`,\n\t\t\t`func _() { _ = -f(1, 2) }`,\n\t\t\t`func _() { _ = -(1 + 2) }`,\n\t\t},\n\t\t{\n\t\t\t\"Addition in call context (no parens).\",\n\t\t\t`func f(x, y int) int { return x + y }`,\n\t\t\t`func _() { println(f(1, 2)) }`,\n\t\t\t`func _() { println(1 + 2) }`,\n\t\t},\n\t\t{\n\t\t\t\"Addition in slice operand context (parens).\",\n\t\t\t`func f(x, y string) string { return x + y }`,\n\t\t\t`func _() { _ = f(\"x\",  \"y\")[1:2] }`,\n\t\t\t`func _() { _ = (\"x\" + \"y\")[1:2] }`,\n\t\t},\n\t\t{\n\t\t\t\"String literal in slice operand context (no parens).\",\n\t\t\t`func f(x string) string { return x }`,\n\t\t\t`func _() { _ = f(\"xy\")[1:2] }`,\n\t\t\t`func _() { _ = \"xy\"[1:2] }`,\n\t\t},\n\t})\n}\n\nfunc TestSubstitution(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Arg to unref'd param can be eliminated if has no effects.\",\n\t\t\t`func f(x, y int) {}; var global int`,\n\t\t\t`func _() { f(0, global) }`,\n\t\t\t`func _() {}`,\n\t\t},\n\t\t{\n\t\t\t\"But not if it may contain last reference to a caller local var.\",\n\t\t\t`func f(int) {}`,\n\t\t\t`func _() { var local int; f(local) }`,\n\t\t\t`func _() { var local int; _ = local }`,\n\t\t},\n\t\t{\n\t\t\t\"Arguments that are used are detected\",\n\t\t\t`func f(int) {}`,\n\t\t\t`func _() { var local int; _ = local; f(local) }`,\n\t\t\t`func _() { var local int; _ = local }`,\n\t\t},\n\t\t{\n\t\t\t\"Arguments that are used by other arguments are detected\",\n\t\t\t`func f(x, y int) { print(x) }`,\n\t\t\t`func _() { var z int; f(z, z) }`,\n\t\t\t`func _() { var z int; print(z) }`,\n\t\t},\n\t\t{\n\t\t\t\"Arguments that are used by other variadic arguments are detected\",\n\t\t\t`func f(x int, ys ...int) { print(ys) }`,\n\t\t\t`func _() { var z int; f(z, 1, 2, 3, z) }`,\n\t\t\t`func _() { var z int; print([]int{1, 2, 3, z}) }`,\n\t\t},\n\t\t{\n\t\t\t\"Arguments that are used by other variadic arguments are detected, 2\",\n\t\t\t`func f(x int, ys ...int) { print(ys) }`,\n\t\t\t`func _() { var z int; f(z) }`,\n\t\t\t`func _() {\n\tvar z int\n\tvar _ int = z\n\tprint([]int{})\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Function parameters are always used\",\n\t\t\t`func f(int) {}`,\n\t\t\t`func _() {\n\tfunc(local int) {\n\t\tf(local)\n\t}(1)\n}`,\n\t\t\t`func _() {\n\tfunc(local int) {\n\n\t}(1)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Regression test for detection of shadowing in nested functions.\",\n\t\t\t`func f(x int) { _ = func() { y := 1; print(y); print(x) } }`,\n\t\t\t`func _(y int) { f(y) } `,\n\t\t\t`func _(y int) {\n\tvar x int = y\n\t_ = func() { y := 1; print(y); print(x) }\n}`,\n\t\t},\n\t})\n}\n\nfunc TestTailCallStrategy(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"simple\",\n\t\t\t`func f() int { return 1 }`,\n\t\t\t`func _() int { return f() }`,\n\t\t\t`func _() int { return 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"void\",\n\t\t\t`func f() { println() }`,\n\t\t\t`func _() { f() }`,\n\t\t\t`func _() { println() }`,\n\t\t},\n\t\t{\n\t\t\t\"void with defer\", // => literalized\n\t\t\t`func f() { defer f(); println() }`,\n\t\t\t`func _() { f() }`,\n\t\t\t`func _() { func() { defer f(); println() }() }`,\n\t\t},\n\t\t// Tests for issue #63336:\n\t\t{\n\t\t\t\"non-trivial return conversion (caller.sig = callee.sig)\",\n\t\t\t`func f() error { if true { return nil } else { return e } }; var e struct{error}`,\n\t\t\t`func _() error { return f() }`,\n\t\t\t`func _() error {\n\tif true {\n\t\treturn nil\n\t} else {\n\t\treturn e\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"non-trivial return conversion (caller.sig != callee.sig)\",\n\t\t\t`func f() error { return E{} }; type E struct{error}`,\n\t\t\t`func _() any { return f() }`,\n\t\t\t`func _() any { return error(E{}) }`,\n\t\t},\n\t})\n}\n\nfunc TestSpreadCalls(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Edge case: cannot literalize spread method call.\",\n\t\t\t`type I int\n \t\t\tfunc g() (I, I)\n\t\t\tfunc (r I) f(x, y I) I {\n\t\t\t\tdefer g() // force literalization\n\t\t\t\treturn x + y + r\n\t\t\t}`,\n\t\t\t`func _() I { return recover().(I).f(g()) }`,\n\t\t\t`error: can't yet inline spread call to method`,\n\t\t},\n\t\t{\n\t\t\t\"Spread argument evaluated for effect.\",\n\t\t\t`func f(int, int) {}; func g() (int, int)`,\n\t\t\t`func _() { f(g())  }`,\n\t\t\t`func _() { _, _ = g() }`,\n\t\t},\n\t\t{\n\t\t\t\"Edge case: receiver and spread argument, both evaluated for effect.\",\n\t\t\t`type T int; func (T) f(int, int) {}; func g() (int, int)`,\n\t\t\t`func _() { T(0).f(g())  }`,\n\t\t\t`func _() {\n\tvar (\n\t\t_    = T(0)\n\t\t_, _ = g()\n\t)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Spread call in return (#63398).\",\n\t\t\t`func f() (int, error) { return 0, nil }`,\n\t\t\t`func _() (int, error) { return f() }`,\n\t\t\t`func _() (int, error) { return 0, nil }`,\n\t\t},\n\t})\n}\n\nfunc TestAssignmentCallStrategy(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"splice: basic\",\n\t\t\t`func f(x int) (int, int) { return x, 2 }`,\n\t\t\t`func _() { x, y := f(1); _, _ = x, y }`,\n\t\t\t`func _() { x, y := 1, 2; _, _ = x, y }`,\n\t\t},\n\t\t{\n\t\t\t\"spread: basic\",\n\t\t\t`func f(x int) (any, any) { return g() }; func g() (error, error) { return nil, nil }`,\n\t\t\t`func _() {\n\tvar x any\n\tx, y := f(0)\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tvar x any\n\tvar y any\n\tx, y = g()\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"spread: free var conflict\",\n\t\t\t`func f(x int) (any, any) { return g(x) }; func g(x int) (int, int) { return x, x }`,\n\t\t\t`func _() {\n\ty := 2\n\t{\n\t\tvar x any\n\t\tx, y := f(y)\n\t\t_, _ = x, y\n\t}\n}`,\n\t\t\t`func _() {\n\ty := 2\n\t{\n\t\tvar x any\n\t\tx, y := func() (any, any) { return g(y) }()\n\t\t_, _ = x, y\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: basic\",\n\t\t\t`func f(x int) (int32, int8) { return 1, 2 }`,\n\t\t\t`func _() {\n\tvar x int32\n  x, y := f(0)\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tvar x int32\n\tx, y := 1, int8(2)\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: rune and byte\",\n\t\t\t`func f(x int) (rune, byte) { return 0, 0 }`,\n\t\t\t`func _() {\n\tx, y := f(0)\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tx, y := rune(0), byte(0)\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: interface conversions\",\n\t\t\t`func f(x int) (_, _ error) { return nil, nil }`,\n\t\t\t`func _() {\n  x, y := f(0)\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tx, y := error(nil), error(nil)\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: implicit nil conversions\",\n\t\t\t`func f(x int) (_, _ error) { return nil, nil }`,\n\t\t\t`func _() { x, y := f(0); _, _ = x, y }`,\n\t\t\t`func _() { x, y := error(nil), error(nil); _, _ = x, y }`,\n\t\t},\n\t\t{\n\t\t\t\"convert: pruning nil assignments left\",\n\t\t\t`func f(x int) (_, _ error) { return nil, nil }`,\n\t\t\t`func _() { _, y := f(0); _ = y }`,\n\t\t\t`func _() { y := error(nil); _ = y }`,\n\t\t},\n\t\t{\n\t\t\t\"convert: pruning nil assignments right\",\n\t\t\t`func f(x int) (_, _ error) { return nil, nil }`,\n\t\t\t`func _() { x, _ := f(0); _ = x }`,\n\t\t\t`func _() { x := error(nil); _ = x }`,\n\t\t},\n\t\t{\n\t\t\t\"convert: partial assign\",\n\t\t\t`func f(x int) (_, _ error) { return nil, nil }`,\n\t\t\t`func _() {\n\tvar x error\n  x, y := f(0)\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tvar x error\n\tx, y := nil, error(nil)\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: single assignment left\",\n\t\t\t`func f() int { return 0 }`,\n\t\t\t`func _() {\n\tx, y := f(), \"hello\"\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tx, y := 0, \"hello\"\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: single assignment left with conversion\",\n\t\t\t`func f() int32 { return 0 }`,\n\t\t\t`func _() {\n\tx, y := f(), \"hello\"\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tx, y := int32(0), \"hello\"\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: single assignment right\",\n\t\t\t`func f() int32 { return 0 }`,\n\t\t\t`func _() {\n\tx, y := \"hello\", f()\n\t_, _ = x, y\n}`,\n\t\t\t`func _() {\n\tx, y := \"hello\", int32(0)\n\t_, _ = x, y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"convert: single assignment middle\",\n\t\t\t`func f() int32 { return 0 }`,\n\t\t\t`func _() {\n\tx, y, z := \"hello\", f(), 1.56\n\t_, _, _ = x, y, z\n}`,\n\t\t\t`func _() {\n\tx, y, z := \"hello\", int32(0), 1.56\n\t_, _, _ = x, y, z\n}`,\n\t\t},\n\t})\n}\n\nfunc TestVariadic(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Variadic cancellation (basic).\",\n\t\t\t`func f(args ...any) { defer f(&args); println(args) }`,\n\t\t\t`func _(slice []any) { f(slice...) }`,\n\t\t\t`func _(slice []any) { func() { var args []any = slice; defer f(&args); println(args) }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Variadic cancellation (literalization with parameter elimination).\",\n\t\t\t`func f(args ...any) { defer f(); println(args) }`,\n\t\t\t`func _(slice []any) { f(slice...) }`,\n\t\t\t`func _(slice []any) { func() { defer f(); println(slice) }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Variadic cancellation (reduction).\",\n\t\t\t`func f(args ...any) { println(args) }`,\n\t\t\t`func _(slice []any) { f(slice...) }`,\n\t\t\t`func _(slice []any) { println(slice) }`,\n\t\t},\n\t\t{\n\t\t\t\"Undo variadic elimination\",\n\t\t\t`func f(args ...int) []int { return append([]int{1}, args...) }`,\n\t\t\t`func _(a, b int) { f(a, b) }`,\n\t\t\t`func _(a, b int) { _ = append([]int{1}, a, b) }`,\n\t\t},\n\t\t{\n\t\t\t\"Variadic elimination (literalization).\",\n\t\t\t`func f(x any, rest ...any) { defer println(x, rest) }`, // defer => literalization\n\t\t\t`func _() { f(1, 2, 3) }`,\n\t\t\t`func _() { func() { defer println(1, []any{2, 3}) }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Variadic elimination (reduction).\",\n\t\t\t`func f(x int, rest ...int) { println(x, rest) }`,\n\t\t\t`func _() { f(1, 2, 3) }`,\n\t\t\t`func _() { println(1, []int{2, 3}) }`,\n\t\t},\n\t\t{\n\t\t\t\"Spread call to variadic (1 arg, 1 param).\",\n\t\t\t`func f(rest ...int) { println(rest) }; func g() (a, b int)`,\n\t\t\t`func _() { f(g()) }`,\n\t\t\t`func _() { func(rest ...int) { println(rest) }(g()) }`,\n\t\t},\n\t\t{\n\t\t\t\"Spread call to variadic (1 arg, 2 params).\",\n\t\t\t`func f(x int, rest ...int) { println(x, rest) }; func g() (a, b int)`,\n\t\t\t`func _() { f(g()) }`,\n\t\t\t`func _() { func(x int, rest ...int) { println(x, rest) }(g()) }`,\n\t\t},\n\t\t{\n\t\t\t\"Spread call to variadic (1 arg, 3 params).\",\n\t\t\t`func f(x, y int, rest ...int) { println(x, y, rest) }; func g() (a, b, c int)`,\n\t\t\t`func _() { f(g()) }`,\n\t\t\t`func _() { func(x, y int, rest ...int) { println(x, y, rest) }(g()) }`,\n\t\t},\n\t})\n}\n\nfunc TestParameterBindingDecl(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"IncDec counts as assignment.\",\n\t\t\t`func f(x int) { x++ }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\tvar x int = 1\n\tx++\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Binding declaration (x, y, z eliminated).\",\n\t\t\t`func f(w, x, y any, z int) { println(w, y, z) }; func g(int) int`,\n\t\t\t`func _() { f(g(0), g(1), g(2), g(3)) }`,\n\t\t\t`func _() {\n\tvar w, _ any = g(0), g(1)\n\tprintln(w, g(2), g(3))\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Reduction of stmt-context call to { return exprs }, with substitution\",\n\t\t\t`func f(ch chan int) int { return <-ch }; func g() chan int`,\n\t\t\t`func _() { f(g()) }`,\n\t\t\t`func _() { <-g() }`,\n\t\t},\n\t\t{\n\t\t\t// Same again, with callee effects:\n\t\t\t\"Binding decl in reduction of stmt-context call to { return exprs }\",\n\t\t\t`func f(x int) int { return <-h(g(2), x) }; func g(int) int; func h(int, int) chan int`,\n\t\t\t`func _() { f(g(1)) }`,\n\t\t\t`func _() {\n\tvar x int = g(1)\n\t<-h(g(2), x)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"No binding decl due to shadowing of int\",\n\t\t\t`func f(int, y any, z int) { defer g(0); println(int, y, z) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2), g(3)) }`,\n\t\t\t`func _() { func(int, y any, z int) { defer g(0); println(int, y, z) }(g(1), g(2), g(3)) }`,\n\t\t},\n\t\t{\n\t\t\t\"An indirect method selection (*x).g acts as a read.\",\n\t\t\t`func f(x *T, y any) any { return x.g(y) }; type T struct{}; func (T) g(x any) any { return x }`,\n\t\t\t`func _(x *T) { f(x, recover()) }`,\n\t\t\t`func _(x *T) {\n\tvar y any = recover()\n\tx.g(y)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"A direct method selection x.g is pure.\",\n\t\t\t`func f(x *T, y any) any { return x.g(y) }; type T struct{}; func (*T) g(x any) any { return x }`,\n\t\t\t`func _(x *T) { f(x, recover()) }`,\n\t\t\t`func _(x *T) { x.g(recover()) }`,\n\t\t},\n\t\t{\n\t\t\t\"Literalization can make use of a binding decl (all params).\",\n\t\t\t`func f(x, y int) int { defer println(); return y + x }; func g(int) int`,\n\t\t\t`func _() { println(f(g(1), g(2))) }`,\n\t\t\t`func _() { println(func() int { var x, y int = g(1), g(2); defer println(); return y + x }()) }`,\n\t\t},\n\t\t{\n\t\t\t\"Literalization can make use of a binding decl (some params).\",\n\t\t\t`func f(x, y int) int { z := y + x; defer println(); return z }; func g(int) int`,\n\t\t\t`func _() { println(f(g(1), g(2))) }`,\n\t\t\t`func _() { println(func() int { var x int = g(1); z := g(2) + x; defer println(); return z }()) }`,\n\t\t},\n\t\t{\n\t\t\t\"Literalization can't yet use of a binding decl if named results.\",\n\t\t\t`func f(x, y int) (z int) { z = y + x; defer println(); return }; func g(int) int`,\n\t\t\t`func _() { println(f(g(1), g(2))) }`,\n\t\t\t`func _() { println(func(x int) (z int) { z = g(2) + x; defer println(); return }(g(1))) }`,\n\t\t},\n\t})\n}\n\nfunc TestEmbeddedFields(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Embedded fields in x.f method selection (direct).\",\n\t\t\t`type T int; func (t T) f() { print(t) }; type U struct{ T }`,\n\t\t\t`func _(u U) { u.f() }`,\n\t\t\t`func _(u U) { print(u.T) }`,\n\t\t},\n\t\t{\n\t\t\t\"Embedded fields in x.f method selection (implicit *).\",\n\t\t\t`type ( T int; U struct{*T}; V struct {U} ); func (t T) f() { print(t) }`,\n\t\t\t`func _(v V) { v.f() }`,\n\t\t\t`func _(v V) { print(*v.U.T) }`,\n\t\t},\n\t\t{\n\t\t\t\"Embedded fields in x.f method selection (implicit &).\",\n\t\t\t`type ( T int; U struct{T}; V struct {U} ); func (t *T) f() { print(t) }`,\n\t\t\t`func _(v V) { v.f() }`,\n\t\t\t`func _(v V) { print(&v.U.T) }`,\n\t\t},\n\t\t// Now the same tests again with T.f(recv).\n\t\t{\n\t\t\t\"Embedded fields in T.f method selection.\",\n\t\t\t`type T int; func (t T) f() { print(t) }; type U struct{ T }`,\n\t\t\t`func _(u U) { U.f(u) }`,\n\t\t\t`func _(u U) { print(u.T) }`,\n\t\t},\n\t\t{\n\t\t\t\"Embedded fields in T.f method selection (implicit *).\",\n\t\t\t`type ( T int; U struct{*T}; V struct {U} ); func (t T) f() { print(t) }`,\n\t\t\t`func _(v V) { V.f(v) }`,\n\t\t\t`func _(v V) { print(*v.U.T) }`,\n\t\t},\n\t\t{\n\t\t\t\"Embedded fields in (*T).f method selection.\",\n\t\t\t`type ( T int; U struct{T}; V struct {U} ); func (t *T) f() { print(t) }`,\n\t\t\t`func _(v V) { (*V).f(&v) }`,\n\t\t\t`func _(v V) { print(&(&v).U.T) }`,\n\t\t},\n\t\t{\n\t\t\t// x is a single-assign var, and x.f does not load through a pointer\n\t\t\t// (despite types.Selection.Indirect=true), so x is pure.\n\t\t\t\"No binding decl is required for recv in method-to-method calls.\",\n\t\t\t`type T struct{}; func (x *T) f() { g(); print(*x) }; func g()`,\n\t\t\t`func (x *T) _() { x.f() }`,\n\t\t\t`func (x *T) _() {\n\tg()\n\tprint(*x)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Same, with implicit &recv.\",\n\t\t\t`type T struct{}; func (x *T) f() { g(); print(*x) }; func g()`,\n\t\t\t`func (x T) _() { x.f() }`,\n\t\t\t`func (x T) _() {\n\t{\n\t\tvar x *T = &x\n\t\tg()\n\t\tprint(*x)\n\t}\n}`,\n\t\t},\n\t})\n}\n\nfunc TestSubstitutionGroups(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t// b -> a\n\t\t\t\"Basic\",\n\t\t\t`func f(a, b int) { print(a, b) }`,\n\t\t\t`func _() { var a int; f(a, a) }`,\n\t\t\t`func _() { var a int; print(a, a) }`,\n\t\t},\n\t\t{\n\t\t\t// a <-> b\n\t\t\t\"Cocycle\",\n\t\t\t`func f(a, b int) { print(a, b) }`,\n\t\t\t`func _() { var a, b int; f(a+b, a+b) }`,\n\t\t\t`func _() { var a, b int; print(a+b, a+b) }`,\n\t\t},\n\t\t{\n\t\t\t// a <-> b\n\t\t\t// a -> c\n\t\t\t// Don't compute b as substitutable due to bad cycle traversal.\n\t\t\t\"Middle cycle\",\n\t\t\t`func f(a, b, c int) { var d int; print(a, b, c, d) }`,\n\t\t\t`func _() { var a, b, c, d int; f(a+b+c, a+b, d) }`,\n\t\t\t`func _() {\n\tvar a, b, c, d int\n\t{\n\t\tvar a, b, c int = a + b + c, a + b, d\n\t\tvar d int\n\t\tprint(a, b, c, d)\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t// a -> b\n\t\t\t// b -> c\n\t\t\t// b -> d\n\t\t\t// c\n\t\t\t//\n\t\t\t// Only c should be substitutable.\n\t\t\t\"Singleton\",\n\t\t\t`func f(a, b, c, d int) { var e int; print(a, b, c, d, e) }`,\n\t\t\t`func _() { var a, b, c, d, e int; f(a+b, c+d, c, e) }`,\n\t\t\t`func _() {\n\tvar a, b, c, d, e int\n\t{\n\t\tvar a, b, d int = a + b, c + d, e\n\t\tvar e int\n\t\tprint(a, b, c, d, e)\n\t}\n}`,\n\t\t},\n\t})\n}\n\nfunc TestSubstitutionPreservesArgumentEffectOrder(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Arguments have effects, but parameters are evaluated in order.\",\n\t\t\t`func f(a, b, c int) { print(a, b, c) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2), g(3)) }`,\n\t\t\t`func _() { print(g(1), g(2), g(3)) }`,\n\t\t},\n\t\t{\n\t\t\t\"Arguments have effects, and parameters are evaluated out of order.\",\n\t\t\t`func f(a, b, c int) { print(a, c, b) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2), g(3)) }`,\n\t\t\t`func _() {\n\tvar a, b int = g(1), g(2)\n\tprint(a, g(3), b)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Pure arguments may commute with argument that have effects.\",\n\t\t\t`func f(a, b, c int) { print(a, c, b) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), 2, g(3)) }`,\n\t\t\t`func _() { print(g(1), g(3), 2) }`,\n\t\t},\n\t\t{\n\t\t\t\"Impure arguments may commute with each other.\",\n\t\t\t`func f(a, b, c, d int) { print(a, c, b, d) }; func g(int) int; var x, y int`,\n\t\t\t`func _() { f(g(1), x, y, g(2)) }`,\n\t\t\t`func _() { print(g(1), y, x, g(2)) }`,\n\t\t},\n\t\t{\n\t\t\t\"Impure arguments do not commute with arguments that have effects (1)\",\n\t\t\t`func f(a, b, c, d int) { print(a, c, b, d) }; func g(int) int; var x, y int`,\n\t\t\t`func _() { f(g(1), g(2), y, g(3)) }`,\n\t\t\t`func _() {\n\tvar a, b int = g(1), g(2)\n\tprint(a, y, b, g(3))\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Impure arguments do not commute with those that have effects (2).\",\n\t\t\t`func f(a, b, c, d int) { print(a, c, b, d) }; func g(int) int; var x, y int`,\n\t\t\t`func _() { f(g(1), y, g(2), g(3)) }`,\n\t\t\t`func _() {\n\tvar a, b int = g(1), y\n\tprint(a, g(2), b, g(3))\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Callee effects commute with pure arguments.\",\n\t\t\t`func f(a, b, c int) { print(a, c, recover().(int), b) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), 2, g(3)) }`,\n\t\t\t`func _() { print(g(1), g(3), recover().(int), 2) }`,\n\t\t},\n\t\t{\n\t\t\t\"Callee reads may commute with impure arguments.\",\n\t\t\t`func f(a, b int) { print(a, x, b) }; func g(int) int; var x, y int`,\n\t\t\t`func _() { f(g(1), y) }`,\n\t\t\t`func _() { print(g(1), x, y) }`,\n\t\t},\n\t\t{\n\t\t\t\"All impure parameters preceding a read hazard must be kept.\",\n\t\t\t`func f(a, b, c int) { print(a, b, recover().(int), c) }; var x, y, z int`,\n\t\t\t`func _() { f(x, y, z) }`,\n\t\t\t`func _() {\n\tvar c int = z\n\tprint(x, y, recover().(int), c)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"All parameters preceding a write hazard must be kept.\",\n\t\t\t`func f(a, b, c int) { print(a, b, recover().(int), c) }; func g(int) int; var x, y, z int`,\n\t\t\t`func _() { f(x, y, g(0))  }`,\n\t\t\t`func _() {\n\tvar a, b, c int = x, y, g(0)\n\tprint(a, b, recover().(int), c)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"[W1 R0 W2 W4 R3] -- test case for second iteration of effect loop\",\n\t\t\t`func f(a, b, c, d, e int) { print(b, a, c, e, d) }; func g(int) int; var x, y int`,\n\t\t\t`func _() { f(x, g(1), g(2), y, g(3))  }`,\n\t\t\t`func _() {\n\tvar a, b, c, d int = x, g(1), g(2), y\n\tprint(b, a, c, g(3), d)\n}`,\n\t\t},\n\t\t{\n\t\t\t// In this example, the set() call is rejected as a substitution\n\t\t\t// candidate due to a shadowing conflict (z). This must entail that the\n\t\t\t// selection x.y (R) is also rejected, because it is lower numbered.\n\t\t\t//\n\t\t\t// Incidentally this program (which panics when executed) illustrates\n\t\t\t// that although effects occur left-to-right, read operations such\n\t\t\t// as x.y are not ordered wrt writes, depending on the compiler.\n\t\t\t// Changing x.y to identity(x).y forces the ordering and avoids the panic.\n\t\t\t\"Hazards with args already rejected (e.g. due to shadowing) are detected too.\",\n\t\t\t`func f(x, y int) (z int) { return x + y }; func set[T any](ptr *T, old, new T) int { println(old); *ptr = new; return 0; }`,\n\t\t\t`func _() { x := new(struct{ y int }); z := x; f(x.y, set(&x, z, nil)) }`,\n\t\t\t`func _() {\n\tx := new(struct{ y int })\n\tz := x\n\t{\n\t\tvar x, y int = x.y, set(&x, z, nil)\n\t\t_ = x + y\n\t}\n}`,\n\t\t},\n\t\t{\n\t\t\t// Rejection of a later parameter for reasons other than callee\n\t\t\t// effects (e.g. escape) may create hazards with lower-numbered\n\t\t\t// parameters that require them to be rejected too.\n\t\t\t\"Hazards with already eliminated parameters (variant)\",\n\t\t\t`func f(x, y int) { _ = &y }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2)) }`,\n\t\t\t`func _() {\n\tvar _, y int = g(1), g(2)\n\t_ = &y\n}`,\n\t\t},\n\t\t{\n\t\t\t// In this case g(2) is rejected for substitution because it is\n\t\t\t// unreferenced but has effects, so parameter x must also be rejected\n\t\t\t// so that its argument v can be evaluated earlier in the binding decl.\n\t\t\t\"Hazards with already eliminated parameters (unreferenced fx variant)\",\n\t\t\t`func f(x, y int) { _ = x }; func g(int) int; var v int`,\n\t\t\t`func _() { f(v, g(2)) }`,\n\t\t\t`func _() {\n\tvar x, _ int = v, g(2)\n\t_ = x\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Defer f() evaluates f() before unknown effects\",\n\t\t\t`func f(int, y any, z int) { defer println(int, y, z) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2), g(3)) }`,\n\t\t\t`func _() { func() { defer println(g(1), g(2), g(3)) }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Effects are ignored when IgnoreEffects\",\n\t\t\t`func f(x, y int) { println(y, x) }; func g(int) int`,\n\t\t\t`func _() { f(g(1), g(2)) }`,\n\t\t\t`func _() { println(g(2), g(1)) }`,\n\t\t},\n\t})\n}\n\nfunc TestNamedResultVars(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Stmt-context call to {return g()} that mentions named result.\",\n\t\t\t`func f() (x int) { return g(x) }; func g(int) int`,\n\t\t\t`func _() { f() }`,\n\t\t\t`func _() {\n\tvar x int\n\tg(x)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Ditto, with binding decl again.\",\n\t\t\t`func f(y string) (x int) { return x+x+len(y+y) }`,\n\t\t\t`func _() { f(\".\") }`,\n\t\t\t`func _() {\n\tvar (\n\t\ty string = \".\"\n\t\tx int\n\t)\n\t_ = x + x + len(y+y)\n}`,\n\t\t},\n\n\t\t{\n\t\t\t\"Ditto, with binding decl (due to repeated y refs).\",\n\t\t\t`func f(y string) (x string) { return x+y+y }`,\n\t\t\t`func _() { f(\".\") }`,\n\t\t\t`func _() {\n\tvar (\n\t\ty string = \".\"\n\t\tx string\n\t)\n\t_ = x + y + y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Stmt-context call to {return binary} that mentions named result.\",\n\t\t\t`func f() (x int) { return x+x }`,\n\t\t\t`func _() { f() }`,\n\t\t\t`func _() {\n\tvar x int\n\t_ = x + x\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Tail call to {return expr} that mentions named result.\",\n\t\t\t`func f() (x int) { return x }`,\n\t\t\t`func _() int { return f() }`,\n\t\t\t`func _() int { return func() (x int) { return x }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Tail call to {return} that implicitly reads named result.\",\n\t\t\t`func f() (x int) { return }`,\n\t\t\t`func _() int { return f() }`,\n\t\t\t`func _() int { return func() (x int) { return }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Spread-context call to {return expr} that mentions named result.\",\n\t\t\t`func f() (x, y int) { return x, y }`,\n\t\t\t`func _() { var _, _ = f() }`,\n\t\t\t`func _() { var _, _ = func() (x, y int) { return x, y }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Shadowing in binding decl for named results => literalization.\",\n\t\t\t`func f(y string) (x y) { return x+x+len(y+y) }; type y = int`,\n\t\t\t`func _() { f(\".\") }`,\n\t\t\t`func _() { func(y string) (x y) { return x + x + len(y+y) }(\".\") }`,\n\t\t},\n\t})\n}\n\nfunc TestSubstitutionPreservesParameterType(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Substitution preserves argument type (#63193).\",\n\t\t\t`func f(x int16) { y := x; _ = (*int16)(&y) }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() {\n\ty := int16(1)\n\t_ = (*int16)(&y)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Same, with non-constant (unnamed to named struct) conversion.\",\n\t\t\t`func f(x T) { y := x; _ = (*T)(&y) }; type T struct{}`,\n\t\t\t`func _() { f(struct{}{}) }`,\n\t\t\t`func _() {\n\ty := T(struct{}{})\n\t_ = (*T)(&y)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Same, with non-constant (chan to <-chan) conversion.\",\n\t\t\t`func f(x T) { y := x; _ = (*T)(&y) }; type T = <-chan int; var ch chan int`,\n\t\t\t`func _() { f(ch) }`,\n\t\t\t`func _() {\n\ty := T(ch)\n\t_ = (*T)(&y)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Same, with untyped nil to typed nil conversion.\",\n\t\t\t`func f(x *int) { y := x; _ = (**int)(&y) }`,\n\t\t\t`func _() { f(nil) }`,\n\t\t\t`func _() {\n\ty := (*int)(nil)\n\t_ = (**int)(&y)\n}`,\n\t\t},\n\t\t{\n\t\t\t\"Conversion of untyped int to named type is made explicit.\",\n\t\t\t`type T int; func (x T) f() { x.g() }; func (T) g() {}`,\n\t\t\t`func _() { T.f(1) }`,\n\t\t\t`func _() { T(1).g() }`,\n\t\t},\n\t\t{\n\t\t\t\"Implicit reference is made explicit outside of selector\",\n\t\t\t`type T int; func (x *T) f() bool { return x == x.id() }; func (x *T) id() *T { return x }`,\n\t\t\t`func _() { var t T; _ = t.f() }`,\n\t\t\t`func _() { var t T; _ = &t == t.id() }`,\n\t\t},\n\t\t{\n\t\t\t\"Implicit parenthesized reference is not made explicit in selector\",\n\t\t\t`type T int; func (x *T) f() bool { return x == (x).id() }; func (x *T) id() *T { return x }`,\n\t\t\t`func _() { var t T; _ = t.f() }`,\n\t\t\t`func _() { var t T; _ = &t == (t).id() }`,\n\t\t},\n\t\t{\n\t\t\t\"Implicit dereference is made explicit outside of selector\", // TODO(rfindley): avoid unnecessary literalization here\n\t\t\t`type T int; func (x T) f() bool { return x == x.id() }; func (x T) id() T { return x }`,\n\t\t\t`func _() { var t *T; _ = t.f() }`,\n\t\t\t`func _() { var t *T; _ = func() bool { var x T = *t; return x == x.id() }() }`,\n\t\t},\n\t\t{\n\t\t\t\"Check for shadowing error on type used in the conversion.\",\n\t\t\t`func f(x T) { _ = &x == (*T)(nil) }; type T int16`,\n\t\t\t`func _() { type T bool; f(1) }`,\n\t\t\t`error: T.*shadowed.*by.*type`,\n\t\t},\n\t})\n}\n\nfunc TestRedundantConversions(t *testing.T) {\n\trunTests(t, []testcase{\n\t\t{\n\t\t\t\"Type conversion must be added if the constant is untyped.\",\n\t\t\t`func f(i int32) { print(i) }; func print(x any) {}`,\n\t\t\t`func _() { f(1)  }`,\n\t\t\t`func _() { print(int32(1)) }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion must not be added if the constant is typed.\",\n\t\t\t`func f(i int32) { print(i) }; func print(x any) {}`,\n\t\t\t`func _() { f(int32(1))  }`,\n\t\t\t`func _() { print(int32(1)) }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for argument to interface parameter\",\n\t\t\t`type T int; func f(x any) { g(x) }; func g(any) {}`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { g(T(1)) }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for parenthesized argument to interface parameter\",\n\t\t\t`type T int; func f(x any) { g((x)) }; func g(any) {}`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { g((T(1))) }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for argument to type parameter\",\n\t\t\t`type T int; func f(x any) { g(x) }; func g[P any](P) {}`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { g(any(T(1))) }`,\n\t\t},\n\t\t{\n\t\t\t\"Strip redundant interface conversions\",\n\t\t\t`type T interface{ M() }; func f(x any) { g(x) }; func g[P any](P) {}`,\n\t\t\t`func _() { f(T(nil)) }`,\n\t\t\t`func _() { g(any(nil)) }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for argument to variadic interface parameter\",\n\t\t\t`type T int; func f(x ...any) { g(x...) }; func g(...any) {}`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { g(T(1)) }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for variadic argument\",\n\t\t\t`type T int; func f(x ...any) { g(x...) }; func g(...any) {}`,\n\t\t\t`func _() { f([]any{T(1)}...) }`,\n\t\t\t`func _() { g([]any{T(1)}...) }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for argument to interface channel\",\n\t\t\t`type T int; var c chan any; func f(x T) { c <- x }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { c <- T(1) }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for argument to concrete channel\",\n\t\t\t`type T int32; var c chan T; func f(x T) { c <- x }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { c <- 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for interface map key\",\n\t\t\t`type T int; var m map[any]any; func f(x T) { m[x] = 1 }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { m[T(1)] = 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for interface to interface map key\",\n\t\t\t`type T int; var m map[any]any; func f(x any) { m[x] = 1 }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { m[T(1)] = 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for concrete map key\",\n\t\t\t`type T int; var m map[T]any; func f(x T) { m[x] = 1 }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { m[1] = 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for interface literal key/value\",\n\t\t\t`type T int; type m map[any]any; func f(x, y T) { _ = m{x: y} }`,\n\t\t\t`func _() { f(1, 2) }`,\n\t\t\t`func _() { _ = m{T(1): T(2)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for concrete literal key/value\",\n\t\t\t`type T int; type m map[T]T; func f(x, y T) { _ = m{x: y} }`,\n\t\t\t`func _() { f(1, 2) }`,\n\t\t\t`func _() { _ = m{1: 2} }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for interface literal element\",\n\t\t\t`type T int; type s []any; func f(x T) { _ = s{x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = s{T(1)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for concrete literal element\",\n\t\t\t`type T int; type s []T; func f(x T) { _ = s{x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = s{1} }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for interface unkeyed struct field\",\n\t\t\t`type T int; type s struct{any}; func f(x T) { _ = s{x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = s{T(1)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for concrete unkeyed struct field\",\n\t\t\t`type T int; type s struct{T}; func f(x T) { _ = s{x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = s{1} }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for interface field value\",\n\t\t\t`type T int; type S struct{ F any }; func f(x T) { _ = S{F: x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = S{F: T(1)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for concrete field value\",\n\t\t\t`type T int; type S struct{ F T }; func f(x T) { _ = S{F: x} }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { _ = S{F: 1} }`,\n\t\t},\n\t\t{\n\t\t\t\"Type conversion for argument to interface channel\",\n\t\t\t`type T int; var c chan any; func f(x any) { c <- x }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { c <- T(1) }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for argument to concrete channel\",\n\t\t\t`type T int32; var c chan T; func f(x T) { c <- x }`,\n\t\t\t`func _() { f(1) }`,\n\t\t\t`func _() { c <- 1 }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for assignment to an explicit interface type\",\n\t\t\t`type T int; func f(x any) { var y any; y = x; _ = y }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() {\n\tvar y any\n\ty = T(1)\n\t_ = y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for short variable assignment to an explicit interface type\",\n\t\t\t`type T int; func f(e error) { var err any; i, err := 1, e; _, _ = i, err }`,\n\t\t\t`func _() { f(nil) }`,\n\t\t\t`func _() {\n\tvar err any\n\ti, err := 1, nil\n\t_, _ = i, err\n}`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for initializer of an explicit interface type\",\n\t\t\t`type T int; func f(x any) { var y any = x; _ = y }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() {\n\tvar y any = T(1)\n\t_ = y\n}`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for use as a composite literal key\",\n\t\t\t`type T int; func f(x any) { _ = map[any]any{x: 1} }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { _ = map[any]any{T(1): 1} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for use as a composite literal value\",\n\t\t\t`type T int; func f(x any) { _ = []any{x} }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { _ = []any{T(1)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for use as a composite literal field\",\n\t\t\t`type T int; func f(x any) { _ = struct{ F any }{F: x} }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() { _ = struct{ F any }{F: T(1)} }`,\n\t\t},\n\t\t{\n\t\t\t\"No type conversion for use in a send statement\",\n\t\t\t`type T int; func f(x any) { var c chan any; c <- x }`,\n\t\t\t`func _() { f(T(1)) }`,\n\t\t\t`func _() {\n\tvar c chan any\n\tc <- T(1)\n}`,\n\t\t},\n\t})\n}\n\nfunc runTests(t *testing.T, tests []testcase) {\n\tfor _, test := range tests {\n\t\tt.Run(test.descr, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tmustParse := func(filename string, content any) *ast.File {\n\t\t\t\tf, err := parser.ParseFile(fset, filename, content, parser.ParseComments|parser.SkipObjectResolution)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"ParseFile: %v\", err)\n\t\t\t\t}\n\t\t\t\treturn f\n\t\t\t}\n\n\t\t\taddPackageClause := func(src string) string {\n\t\t\t\tif !strings.Contains(test.descr, \"NoPackageClause\") {\n\t\t\t\t\tsrc = \"package p\\n\" + src\n\t\t\t\t}\n\t\t\t\treturn src\n\t\t\t}\n\n\t\t\t// Parse callee file and find first func decl named f.\n\t\t\tcalleeContent := addPackageClause(test.callee)\n\t\t\tcalleeFile := mustParse(\"callee.go\", calleeContent)\n\t\t\tvar decl *ast.FuncDecl\n\t\t\tfor _, d := range calleeFile.Decls {\n\t\t\t\tif d, ok := d.(*ast.FuncDecl); ok && d.Name.Name == funcName {\n\t\t\t\t\tdecl = d\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif decl == nil {\n\t\t\t\tt.Fatalf(\"declaration of func %s not found: %s\", funcName, test.callee)\n\t\t\t}\n\n\t\t\t// Parse caller file and find first call to f().\n\t\t\tcallerContent := addPackageClause(test.caller)\n\t\t\tcallerFile := mustParse(\"caller.go\", callerContent)\n\t\t\tvar call *ast.CallExpr\n\t\t\tast.Inspect(callerFile, func(n ast.Node) bool {\n\t\t\t\tif n, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\tswitch fun := n.Fun.(type) {\n\t\t\t\t\tcase *ast.SelectorExpr:\n\t\t\t\t\t\tif fun.Sel.Name == funcName {\n\t\t\t\t\t\t\tcall = n\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ast.Ident:\n\t\t\t\t\t\tif fun.Name == funcName {\n\t\t\t\t\t\t\tcall = n\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ast.IndexExpr:\n\t\t\t\t\t\tif id, ok := fun.X.(*ast.Ident); ok && id.Name == funcName {\n\t\t\t\t\t\t\tcall = n\n\t\t\t\t\t\t}\n\t\t\t\t\tcase *ast.IndexListExpr:\n\t\t\t\t\t\tif id, ok := fun.X.(*ast.Ident); ok && id.Name == funcName {\n\t\t\t\t\t\t\tcall = n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn call == nil\n\t\t\t})\n\t\t\tif call == nil {\n\t\t\t\tt.Fatalf(\"call to %s not found: %s\", funcName, test.caller)\n\t\t\t}\n\n\t\t\t// Type check both files as one package.\n\t\t\tinfo := &types.Info{\n\t\t\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\t\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\t\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\t\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\t\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\t\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t\t}\n\t\t\tconf := &types.Config{Error: func(err error) { t.Error(err) }}\n\t\t\tpkg, err := conf.Check(\"p\", fset, []*ast.File{callerFile, calleeFile}, info)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"transformation introduced type errors\")\n\t\t\t}\n\n\t\t\t// Analyze callee and inline call.\n\t\t\tdoIt := func() (*inline.Result, error) {\n\t\t\t\tcallee, err := inline.AnalyzeCallee(t.Logf, fset, pkg, info, decl, []byte(calleeContent))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tif err := checkTranscode(callee); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tcaller := &inline.Caller{\n\t\t\t\t\tFset:  fset,\n\t\t\t\t\tTypes: pkg,\n\t\t\t\t\tInfo:  info,\n\t\t\t\t\tFile:  callerFile,\n\t\t\t\t\tCall:  call,\n\t\t\t\t}\n\t\t\t\tcheck := checkNoMutation(caller.File)\n\t\t\t\tdefer check()\n\t\t\t\treturn inline.Inline(caller, callee, &inline.Options{\n\t\t\t\t\tLogf:          t.Logf,\n\t\t\t\t\tIgnoreEffects: strings.Contains(test.descr, \"IgnoreEffects\"),\n\t\t\t\t})\n\t\t\t}\n\t\t\tres, err := doIt()\n\n\t\t\t// Want error?\n\t\t\tif rest, ok := strings.CutPrefix(test.want, \"error: \"); ok {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatalf(\"unexpected success: want error matching %q\", rest)\n\t\t\t\t}\n\t\t\t\tmsg := err.Error()\n\t\t\t\tif ok, err := regexp.MatchString(rest, msg); err != nil {\n\t\t\t\t\tt.Fatalf(\"invalid regexp: %v\", err)\n\t\t\t\t} else if !ok {\n\t\t\t\t\tt.Fatalf(\"wrong error: %s (want match for %q)\", msg, rest)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Want success.\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tgotContent, err := applyEdits(pkg, callerFile.FileStart, []byte(callerContent), res.Edits)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Compute a single-hunk line-based diff.\n\t\t\tsrcLines := strings.Split(callerContent, \"\\n\")\n\t\t\tgotLines := strings.Split(string(gotContent), \"\\n\")\n\t\t\tfor len(srcLines) > 0 && len(gotLines) > 0 &&\n\t\t\t\tsrcLines[0] == gotLines[0] {\n\t\t\t\tsrcLines = srcLines[1:]\n\t\t\t\tgotLines = gotLines[1:]\n\t\t\t}\n\t\t\tfor len(srcLines) > 0 && len(gotLines) > 0 &&\n\t\t\t\tsrcLines[len(srcLines)-1] == gotLines[len(gotLines)-1] {\n\t\t\t\tsrcLines = srcLines[:len(srcLines)-1]\n\t\t\t\tgotLines = gotLines[:len(gotLines)-1]\n\t\t\t}\n\t\t\tgot := strings.Join(gotLines, \"\\n\")\n\n\t\t\tif strings.TrimSpace(got) != strings.TrimSpace(test.want) {\n\t\t\t\tt.Fatalf(\"\\nInlining this call:\\t%s\\nof this callee:    \\t%s\\nproduced:\\n%s\\nWant:\\n\\n%s\",\n\t\t\t\t\ttest.caller,\n\t\t\t\t\ttest.callee,\n\t\t\t\t\tgot,\n\t\t\t\t\ttest.want)\n\t\t\t}\n\n\t\t\t// Check that resulting code type-checks.\n\t\t\tnewCallerFile := mustParse(\"newcaller.go\", gotContent)\n\t\t\tif _, err := conf.Check(\"p\", fset, []*ast.File{newCallerFile, calleeFile}, nil); err != nil {\n\t\t\t\tt.Fatalf(\"modified source failed to typecheck: <<%s>>\", gotContent)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// -- helpers --\n\n// checkNoMutation returns a function that, when called,\n// asserts that file was not modified since the checkNoMutation call.\nfunc checkNoMutation(file *ast.File) func() {\n\tpre := deepHash(file)\n\treturn func() {\n\t\tpost := deepHash(file)\n\t\tif pre != post {\n\t\t\tpanic(\"Inline mutated caller.File\")\n\t\t}\n\t}\n}\n\n// checkTranscode replaces *callee by the results of gob-encoding and\n// then decoding it, to test that these operations are lossless.\nfunc checkTranscode(callee *inline.Callee) error {\n\t// Perform Gob transcoding so that it is exercised by the test.\n\tvar enc bytes.Buffer\n\tif err := gob.NewEncoder(&enc).Encode(callee); err != nil {\n\t\treturn fmt.Errorf(\"internal error: gob encoding failed: %v\", err)\n\t}\n\t*callee = inline.Callee{}\n\tif err := gob.NewDecoder(&enc).Decode(callee); err != nil {\n\t\treturn fmt.Errorf(\"internal error: gob decoding failed: %v\", err)\n\t}\n\treturn nil\n}\n\n// deepHash computes a cryptographic hash of an ast.Node so that\n// if the data structure is mutated, the hash changes.\n// It assumes Go variables do not change address.\n//\n// TODO(adonovan): consider publishing this in the astutil package.\n//\n// TODO(adonovan): consider a variant that reports where in the tree\n// the mutation occurred (obviously at a cost in space).\nfunc deepHash(n ast.Node) any {\n\tseen := make(map[unsafe.Pointer]bool) // to break cycles\n\n\thasher := sha256.New()\n\tle := binary.LittleEndian\n\twriteUint64 := func(v uint64) {\n\t\tvar bs [8]byte\n\t\tle.PutUint64(bs[:], v)\n\t\thasher.Write(bs[:])\n\t}\n\n\tvar visit func(reflect.Value)\n\tvisit = func(v reflect.Value) {\n\t\tswitch v.Kind() {\n\t\tcase reflect.Pointer:\n\t\t\tptr := v.UnsafePointer()\n\t\t\twriteUint64(uint64(uintptr(ptr)))\n\t\t\tif !v.IsNil() {\n\t\t\t\tif !seen[ptr] {\n\t\t\t\t\tseen[ptr] = true\n\t\t\t\t\t// Skip types we don't handle yet, but don't care about.\n\t\t\t\t\tswitch v.Interface().(type) {\n\t\t\t\t\tcase *ast.Scope:\n\t\t\t\t\t\treturn // involves a map\n\t\t\t\t\t}\n\n\t\t\t\t\tvisit(v.Elem())\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase reflect.Struct:\n\t\t\tfor i := 0; i < v.Type().NumField(); i++ {\n\t\t\t\tvisit(v.Field(i))\n\t\t\t}\n\n\t\tcase reflect.Slice:\n\t\t\tptr := v.UnsafePointer()\n\t\t\t// We may encounter different slices at the same address,\n\t\t\t// so don't mark ptr as \"seen\".\n\t\t\twriteUint64(uint64(uintptr(ptr)))\n\t\t\twriteUint64(uint64(v.Len()))\n\t\t\twriteUint64(uint64(v.Cap()))\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\tvisit(v.Index(i))\n\t\t\t}\n\n\t\tcase reflect.Interface:\n\t\t\tif v.IsNil() {\n\t\t\t\twriteUint64(0)\n\t\t\t} else {\n\t\t\t\trtype := reflect.ValueOf(v.Type()).UnsafePointer()\n\t\t\t\twriteUint64(uint64(uintptr(rtype)))\n\t\t\t\tvisit(v.Elem())\n\t\t\t}\n\n\t\tcase reflect.String:\n\t\t\twriteUint64(uint64(v.Len()))\n\t\t\thasher.Write([]byte(v.String()))\n\n\t\tcase reflect.Int:\n\t\t\twriteUint64(uint64(v.Int()))\n\n\t\tcase reflect.Uint:\n\t\t\twriteUint64(uint64(v.Uint()))\n\n\t\tcase reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\t// Bools and fixed width numbers can be handled by binary.Write.\n\t\t\tbinary.Write(hasher, le, v.Interface())\n\n\t\tdefault: // reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer, reflect.Uintptr\n\t\t\tpanic(v) // unreachable in AST\n\t\t}\n\t}\n\tvisit(reflect.ValueOf(n))\n\n\tvar hash [sha256.Size]byte\n\thasher.Sum(hash[:0])\n\treturn hash\n}\n\nfunc TestDeepHash(t *testing.T) {\n\t// This test reproduces a bug in DeepHash that was encountered during work on\n\t// the inliner.\n\t//\n\t// TODO(rfindley): consider replacing this with a fuzz test.\n\tid := &ast.Ident{\n\t\tNamePos: 2,\n\t\tName:    \"t\",\n\t}\n\tc := &ast.CallExpr{\n\t\tFun: id,\n\t}\n\th1 := deepHash(c)\n\tid.NamePos = 1\n\th2 := deepHash(c)\n\tif h1 == h2 {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n\n// applyEdits transforms content by applying the specified edits\n// to the file whose positions are defined by fset), reformatting the file, and\n// removing unused imports (using pkg for names of imported packages).\nfunc applyEdits(pkg *types.Package, fileStart token.Pos, content []byte, edits []refactor.Edit) ([]byte, error) {\n\tdedits := make([]diff.Edit, len(edits))\n\tfor i, edit := range edits {\n\t\tdedits[i] = diff.Edit{\n\t\t\tStart: int(edit.Pos - fileStart),\n\t\t\tEnd:   int(edit.End - fileStart),\n\t\t\tNew:   string(edit.NewText),\n\t\t}\n\t}\n\tgot, err := diff.ApplyBytes(content, dedits)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tgot, err = driverutil.FormatSourceRemoveImports(pkg, got)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn []byte(got), nil\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/assignment-splice.txtar",
    "content": "This test checks the splice assignment substrategy.\n\n-- go.mod --\nmodule testdata\n\ngo 1.20\n\n-- a.go --\npackage a\n\nfunc a() (int32, string) {\n\treturn b()\n}\n\nfunc b() (int32, string) {\n\treturn 0, \"a\"\n}\n\nfunc c() (int, chan<- int) {\n\treturn 0, make(chan int) // nontrivial conversion\n}\n\n-- a1.go --\npackage a\n\nfunc _() {\n\tx, y := a() //@ inline(re\"a\", a1)\n}\n-- a1 --\npackage a\n\nfunc _() {\n\tx, y := b() //@ inline(re\"a\", a1)\n}\n-- a2.go --\npackage a\n\nfunc _() {\n\tvar x, y any\n\tx, y = a() //@ inline(re\"a\", a2)\n}\n-- a2 --\npackage a\n\nfunc _() {\n\tvar x, y any\n\tx, y = b() //@ inline(re\"a\", a2)\n}\n-- a3.go --\npackage a\n\nfunc _() {\n\tvar y chan<- int\n\tx, y := c() //@ inline(re\"c\", a3)\n}\n-- a3 --\npackage a\n\nfunc _() {\n\tvar y chan<- int\n\tx, y := 0, make(chan int) //@ inline(re\"c\", a3)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/assignment.txtar",
    "content": "Basic tests of inlining a call on the RHS of an assignment.\n\n-- go.mod --\nmodule testdata\n\ngo 1.20\n\n-- a/a1.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tvar y int\n\tx, y := b.B1() //@ inline(re\"B\", b1)\n\t_, _ = x, y\n}\n\n-- a/a2.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tvar y int\n\tx, y := b.B2() //@ inline(re\"B\", b2)\n\t_, _ = x, y\n}\n\n-- a/a3.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tx, y := b.B3() //@ inline(re\"B\", b3)\n\t_, _ = x, y\n}\n\n-- a/a4.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tx, y := b.B4() //@ inline(re\"B\", b4)\n\t_, _ = x, y\n}\n\n-- b/b.go --\npackage b\n\nimport (\n\t\"testdata/c\"\n)\n\nfunc B1() (c.C, int) {\n\treturn 0, 1\n}\n\nfunc B2() (c.C, int) {\n\treturn B1()\n}\n\nfunc B3() (c.C, c.C) {\n\treturn 0, 1\n}\n\n-- b/b4.go --\npackage b\n\nimport (\n\tc1 \"testdata/c\"\n\tc2 \"testdata/c2\"\n)\n\nfunc B4() (c1.C, c2.C) {\n\treturn 0, 1\n}\n\n-- c/c.go --\npackage c\n\ntype C int\n\n-- c2/c.go --\npackage c\n\ntype C int\n\n-- b1 --\npackage a\n\nimport \"testdata/c\"\n\nfunc _() {\n\tvar y int\n\tx, y := c.C(0), 1 //@ inline(re\"B\", b1)\n\t_, _ = x, y\n}\n-- b2 --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tvar y int\n\tx, y := b.B1() //@ inline(re\"B\", b2)\n\t_, _ = x, y\n}\n-- b3 --\npackage a\n\nimport \"testdata/c\"\n\nfunc _() {\n\tx, y := c.C(0), c.C(1) //@ inline(re\"B\", b3)\n\t_, _ = x, y\n}\n\n-- b4 --\npackage a\n\nimport c1 \"testdata/c\"\n\nimport c2 \"testdata/c2\"\n\nfunc _() {\n\tx, y := c1.C(0), c2.C(1) //@ inline(re\"B\", b4)\n\t_, _ = x, y\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/basic-err.txtar",
    "content": "Test of inlining a function that references err.Error,\nwhich is often a special case because it has no position.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"io\"\n\nvar _ = getError(io.EOF) //@ inline(re\"getError\", getError)\n\nfunc getError(err error) string { return err.Error() }\n\n-- getError --\npackage a\n\nimport \"io\"\n\nvar _ = io.EOF.Error() //@ inline(re\"getError\", getError)\n\nfunc getError(err error) string { return err.Error() }\n"
  },
  {
    "path": "internal/refactor/inline/testdata/basic-literal.txtar",
    "content": "Basic tests of inlining by literalization.\n\nThe use of defer forces literalization.\n\nrecover() is an example of a function with effects,\ndefeating elimination of parameter x; but parameter\ny is eliminated by substitution.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a1.go --\npackage a\n\nfunc _() {\n\tadd(recover().(int), 2) //@ inline(re\"add\", add1)\n}\n\nfunc add(x, y int) int { defer print(); return x + y }\n\n-- add1 --\npackage a\n\nfunc _() {\n\tfunc() int { var x int = recover().(int); defer print(); return x + 2 }() //@ inline(re\"add\", add1)\n}\n\nfunc add(x, y int) int { defer print(); return x + y }\n"
  },
  {
    "path": "internal/refactor/inline/testdata/basic-reduce.txtar",
    "content": "Most basic test of inlining by reduction.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a0.go --\npackage a\n\nvar _ = zero() //@ inline(re\"zero\", zero)\n\nfunc zero() int { return 0 }\n\n-- zero --\npackage a\n\nvar _ = 0 //@ inline(re\"zero\", zero)\n\nfunc zero() int { return 0 }\n\n-- a/a1.go --\npackage a\n\nfunc _() {\n\tone := 1\n\tadd(one, 2) //@ inline(re\"add\", add1)\n}\n\nfunc add(x, y int) int { return x + y }\n\n-- add1 --\npackage a\n\nfunc _() {\n\tone := 1\n\t_ = one + 2 //@ inline(re\"add\", add1)\n}\n\nfunc add(x, y int) int { return x + y }\n\n-- a/a2.go --\npackage a\n\nvar _ = add(len(\"\"), 2) //@ inline(re\"add\", add2)\n\n-- add2 --\npackage a\n\nvar _ = len(\"\") + 2 //@ inline(re\"add\", add2)\n\n"
  },
  {
    "path": "internal/refactor/inline/testdata/cgo.txtar",
    "content": "Test that attempts to inline with caller or callee in a cgo-generated\nfile are rejected. (This is just a special case of rejecting generated files.)\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\n/*\nstatic void f() {}\n*/\nimport \"C\"\n\nfunc a() {\n\tC.f() //@ inline(re\"f\", re\"cannot inline cgo-generated functions\")\n\tg()   //@ inline(re\"g\", re`cannot inline calls from generated files`)\n}\n\nfunc g() {\n\tprintln()\n}\n\n-- a/a2.go --\npackage a\n\nfunc b() {\n\ta() //@ inline(re\"a\", re\"cannot inline cgo-generated functions\")\n}\n\nfunc c() {\n\tb() //@ inline(re\"b\", result)\n}\n\n-- result --\npackage a\n\nfunc b() {\n\ta() //@ inline(re\"a\", re\"cannot inline cgo-generated functions\")\n}\n\nfunc c() {\n\ta() //@ inline(re\"b\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/comments.txtar",
    "content": "Test of (lack of) comment preservation by inlining,\nwhether by literalization or reduction.\n\nComment handling was better in an earlier implementation\nbased on byte-oriented file surgery; switching to AST\nmanipulation (though better in all other respects) was\na regression. The underlying problem of AST comment fidelity\nis Go issue #20744.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/f.go --\npackage a\n\nfunc _() {\n\tf() //@ inline(re\"f\", f)\n}\n\nfunc f() {\n\t// a\n\t/* b */ g() /* c */\n\t// d\n}\n\n-- f --\npackage a\n\nfunc _() {\n\tg() //@ inline(re\"f\", f)\n}\n\nfunc f() {\n\t// a\n\t/* b */\n\tg() /* c */\n\t// d\n}\n\n-- a/g.go --\npackage a\n\nfunc _() {\n\tprintln(g()) //@ inline(re\"g\", g)\n}\n\nfunc g() int { return 1 /*hello*/ + /*there*/ 1 }\n\n-- g --\npackage a\n\nfunc _() {\n\tprintln(1 + 1) //@ inline(re\"g\", g)\n}\n\nfunc g() int { return 1 /*hello*/ + /*there*/ 1 }\n"
  },
  {
    "path": "internal/refactor/inline/testdata/crosspkg-selfref.txtar",
    "content": "A self-reference counts as a free reference,\nso that it gets properly package-qualified as needed.\n(Regression test for a bug.)\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tb.F(1) //@ inline(re\"F\", output)\n}\n\n-- b/b.go --\npackage b\n\nfunc F(x int) {\n\tF(x + 2)\n}\n\n-- output --\npackage a\n\nimport \"testdata/b\"\n\nfunc _() {\n\tb.F(1 + 2) //@ inline(re\"F\", output)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/crosspkg.txtar",
    "content": "Test of cross-package inlining.\nThe first case creates a new import,\nthe second reuses an existing one.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\n// This comment does not migrate.\n\nimport (\n\t\"fmt\"\n\t\"testdata/b\"\n)\n\n// Nor this one.\n\nfunc A() {\n\tfmt.Println()\n\tb.B1() //@ inline(re\"B1\", b1result)\n\tb.B2() //@ inline(re\"B2\", b2result)\n\tb.B3() //@ inline(re\"B3\", b3result)\n}\n\n-- b/b.go --\npackage b\n\nimport \"testdata/c\"\nimport \"testdata/d\"\nimport \"fmt\"\n\nfunc B1() { c.C() }\nfunc B2() { fmt.Println() }\nfunc B3() { e.E() } // (note that \"testdata/d\" points to package e)\n\n-- c/c.go --\npackage c\n\nfunc C() {}\n\n-- d/d.go --\npackage e // <- this package name intentionally mismatches the path\n\nfunc E() {}\n\n-- b1result --\npackage a\n\n// This comment does not migrate.\n\nimport (\n\t\"fmt\"\n\t\"testdata/b\"\n\t\"testdata/c\"\n)\n\n// Nor this one.\n\nfunc A() {\n\tfmt.Println()\n\tc.C()  //@ inline(re\"B1\", b1result)\n\tb.B2() //@ inline(re\"B2\", b2result)\n\tb.B3() //@ inline(re\"B3\", b3result)\n}\n\n-- b2result --\npackage a\n\n// This comment does not migrate.\n\nimport (\n\t\"fmt\"\n\t\"testdata/b\"\n)\n\n// Nor this one.\n\nfunc A() {\n\tfmt.Println()\n\tb.B1()        //@ inline(re\"B1\", b1result)\n\tfmt.Println() //@ inline(re\"B2\", b2result)\n\tb.B3()        //@ inline(re\"B3\", b3result)\n}\n-- b3result --\npackage a\n\n// This comment does not migrate.\n\nimport (\n\t\"fmt\"\n\t\"testdata/b\"\n\te \"testdata/d\"\n)\n\n// Nor this one.\n\nfunc A() {\n\tfmt.Println()\n\tb.B1() //@ inline(re\"B1\", b1result)\n\tb.B2() //@ inline(re\"B2\", b2result)\n\te.E()  //@ inline(re\"B3\", b3result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/dotimport.txtar",
    "content": "Test of inlining a function that uses a dot import.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc A() {}\n\n-- b/b.go --\npackage b\n\nimport . \"testdata/a\"\n\nfunc B() { A() }\n\n-- c/c.go --\npackage c\n\nimport \"testdata/b\"\n\nfunc _() {\n\tb.B() //@ inline(re\"B\", result)\n}\n\n-- result --\npackage c\n\nimport \"testdata/a\"\n\nfunc _() {\n\ta.A() //@ inline(re\"B\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/embed.txtar",
    "content": "Test of implicit field selections in method calls.\n\nThe two level wrapping T -> unexported -> U is required\nto exercise the implicit selections exportedness check;\nwith only a single level, the receiver declaration in\n\"func (unexported) F()\" would fail the earlier\nunexportedness check.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc _(x b.T) {\n\tx.F() //@ inline(re\"F\", re\"in x.F, implicit reference to unexported field .unexported cannot be made explicit\")\n}\n\n-- b/b.go --\npackage b\n\ntype T struct { unexported }\ntype unexported struct { U }\ntype U struct{}\nfunc (U) F() {}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/empty-body.txtar",
    "content": "Test of elimination of calls to functions with completely empty bodies.\nThe arguments must still be evaluated and their results discarded.\nThe number of discard blanks must match the type, not the syntax (see 2-ary f).\nIf there are no arguments, the entire call is eliminated.\n\nWe cannot eliminate some pure argument expressions because they\nmay contain the last reference to a local variable.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a0.go --\npackage a\n\nfunc _() {\n\tempty() //@ inline(re\"empty\", empty0)\n}\n\nfunc empty(...any) {}\n\n-- empty0 --\npackage a\n\nfunc _() {\n\t//@ inline(re\"empty\", empty0)\n}\n\nfunc empty(...any) {}\n\n-- a/a1.go --\npackage a\n\nfunc _(ch chan int) {\n\tempty(f()) //@ inline(re\"empty\", empty1)\n}\n\nfunc f() (int, int)\n\n-- empty1 --\npackage a\n\nfunc _(ch chan int) {\n\t_, _ = f() //@ inline(re\"empty\", empty1)\n}\n\nfunc f() (int, int)\n\n-- a/a2.go --\npackage a\n\nfunc _(ch chan int) {\n\tempty(-1, ch, len(\"\"), g(), <-ch) //@ inline(re\"empty\", empty2)\n}\n\nfunc g() int\n\n-- empty2 --\npackage a\n\nfunc _(ch chan int) {\n\t_ = []any{-1, ch, len(\"\"), g(), <-ch} //@ inline(re\"empty\", empty2)\n}\n\nfunc g() int\n\n-- a/a3.go --\npackage a\n\nfunc _() {\n\tnew(T).empty() //@ inline(re\"empty\", empty3)\n}\n\ntype T int\n\nfunc (T) empty() int {}\n\n-- empty3 --\npackage a\n\nfunc _() {\n\t//@ inline(re\"empty\", empty3)\n}\n\ntype T int\n\nfunc (T) empty() int {}\n\n-- a/a4.go --\npackage a\n\nfunc _() {\n\tvar x T\n\tx.empty() //@ inline(re\"empty\", empty4)\n}\n\n-- empty4 --\npackage a\n\nfunc _() {\n\tvar x T\n\t_ = x //@ inline(re\"empty\", empty4)\n}\n\n-- a/a5.go --\npackage a\n\nfunc _() {\n\tgo empty() //@ inline(re\"empty\", empty5)\n}\n\nfunc empty() {}\n-- empty5 --\npackage a\n\nfunc _() {\n\tgo func() {}() //@ inline(re\"empty\", empty5)\n}\n\nfunc empty() {}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/err-basic.txtar",
    "content": "Basic errors:\n- Inlining of generic functions is not yet supported.\n\nWe can't express tests for the error resulting from inlining a\nconversion T(x), a call to a literal func(){}(), a call to a\nfunc-typed var, or a call to an interface method, since all of these\ncause the test driver to fail to locate the callee, so\nit doesn't even reach the Indent function.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/nobody.go --\npackage a\n\nfunc _() {\n\tg() //@ inline(re\"g\", re\"has no body\")\n}\n\nfunc g()\n"
  },
  {
    "path": "internal/refactor/inline/testdata/err-shadow-builtin.txtar",
    "content": "Failures to inline because callee references a builtin that\nis shadowed by caller.\n\n-- go.mod --\nmodule testdata\ngo 1.18\n\n-- a/nil.go --\npackage a\n\nfunc _() {\n\tconst nil = 1\n\t_ = f() //@ inline(re\"f\", re\"nil.*shadowed.*by.*const.*line 4\")\n}\n\nfunc f() *int { return nil }\n-- a/nil-type-param.go --\npackage a\n\nfunc _[nil any]() {\n\t_ = f() //@ inline(re\"f\", re\"nil.*shadowed.*by.*typename.*line 3\")\n}\n\n-- a/nil-typename.go --\npackage a\n\nfunc _[nil any]() {\n\t_ = f() //@ inline(re\"f\", re\"nil.*shadowed.*by.*typename.*line 3\")\n}\n\n-- a/append.go --\npackage a\n\nfunc _() {\n\ttype append int\n\tg(nil) //@ inline(re\"g\", re\"append.*shadowed.*by.*typename.*line 4\")\n}\n\nfunc g(x []int) { _ = append(x, x...) }\n\n-- a/type.go --\npackage a\n\nfunc _() {\n\ttype int uint8\n\t_ = h(0) //@ inline(re\"h\", re\"int.*shadowed.*by.*typename.*line 4\")\n}\n\nfunc h(x int) int { return x + 1 }\n"
  },
  {
    "path": "internal/refactor/inline/testdata/err-shadow-pkg.txtar",
    "content": "Test of failure to inline because callee references a\npackage-level decl that is shadowed by caller.\n\nObserve that the first call to f can be inlined because\nthe shadowing has not yet occurred; but the second call\nto f is within the scope of the local constant v.\n\n-- go.mod --\nmodule testdata\ngo 1.18\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tf() //@ inline(re\"f\", result)\n\tconst v = 1\n\tf() //@ inline(re\"f\", re\"v.*shadowed.*by.*const.*line 5\")\n}\n\nfunc _[v any]() {\n\tf() //@ inline(re\"f\", re\"v.*shadowed.*by.*typename.*line 9\")\n}\n\nfunc f() int { return v }\n\nvar v int\n\n-- result --\npackage a\n\nfunc _() {\n\t_ = v //@ inline(re\"f\", result)\n\tconst v = 1\n\tf() //@ inline(re\"f\", re\"v.*shadowed.*by.*const.*line 5\")\n}\n\nfunc _[v any]() {\n\tf() //@ inline(re\"f\", re\"v.*shadowed.*by.*typename.*line 9\")\n}\n\nfunc f() int { return v }\n\nvar v int\n"
  },
  {
    "path": "internal/refactor/inline/testdata/err-unexported.txtar",
    "content": "Errors from attempting to import a function from another\npackage whose body refers to unexported declarations.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc A1() { b() }\nfunc b() {}\n\nfunc A2() { var x T; print(x.f) }\ntype T struct { f int }\n\nfunc A3() { _ = &T{f: 0} }\n\nfunc A4() { _ = &T{0} }\n\n-- b/b.go --\npackage b\n\nimport \"testdata/a\"\n\nfunc _() {\n\ta.A1() //@ inline(re\"A1\", re`body refers to non-exported b`)\n\ta.A2() //@ inline(re\"A2\", re`body refers to non-exported \\(testdata/a.T\\).f`)\n\ta.A3() //@ inline(re\"A3\", re`body refers to non-exported \\(testdata/a.T\\).f`)\n\ta.A4() //@ inline(re\"A4\", re`body refers to non-exported \\(testdata/a.T\\).f`)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/exprstmt.txtar",
    "content": "Inlining an expression into an ExprStmt.\nCall and receive expressions can be inlined directly\n(though calls to only some builtins can be reduced).\nAll other expressions are inlined as \"_ = expr\".\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/call.go --\npackage a\n\nfunc _() {\n\tcall() //@ inline(re\"call\", call)\n}\n\nfunc call() int { return recv() }\n\n-- call --\npackage a\n\nfunc _() {\n\trecv() //@ inline(re\"call\", call)\n}\n\nfunc call() int { return recv() }\n\n-- a/recv.go --\npackage a\n\nfunc _() {\n\trecv() //@ inline(re\"recv\", recv)\n}\n\nfunc recv() int { return <-(chan int)(nil) }\n\n-- recv --\npackage a\n\nfunc _() {\n\t<-(chan int)(nil) //@ inline(re\"recv\", recv)\n}\n\nfunc recv() int { return <-(chan int)(nil) }\n\n-- a/constant.go --\npackage a\n\nfunc _() {\n\tconstant() //@ inline(re\"constant\", constant)\n}\n\nfunc constant() int { return 0 }\n\n-- constant --\npackage a\n\nfunc _() {\n\t_ = 0 //@ inline(re\"constant\", constant)\n}\n\nfunc constant() int { return 0 }\n\n-- a/builtin.go --\npackage a\n\nfunc _() {\n\tbuiltin() //@ inline(re\"builtin\", builtin)\n}\n\nfunc builtin() int { return len(\"\") }\n\n-- builtin --\npackage a\n\nfunc _() {\n\t_ = len(\"\") //@ inline(re\"builtin\", builtin)\n}\n\nfunc builtin() int { return len(\"\") }\n\n-- a/copy.go --\npackage a\n\nfunc _() {\n\t_copy() //@ inline(re\"copy\", copy)\n}\n\nfunc _copy() int { return copy([]int(nil), []int(nil)) }\n\n-- copy --\npackage a\n\nfunc _() {\n\tcopy([]int(nil), []int(nil)) //@ inline(re\"copy\", copy)\n}\n\nfunc _copy() int { return copy([]int(nil), []int(nil)) }\n\n"
  },
  {
    "path": "internal/refactor/inline/testdata/generic.txtar",
    "content": "Inlining a call to a generic function.\n\na1: explicit type args, no shadowing\na2: the call uses type inference\na3: the type argument is shadowed in the callee\na4: ditto, with a more complicated arg\na5: a free identifier in the callee is captured by a global\n    in the caller's scope (covered elsewhere; verifying for generics)\n-- go.mod --\nmodule testdata\ngo 1.18\n\n-- a/a1.go --\npackage a\n\nfunc _() {\n\tf[int](1) //@ inline(re\"f\", a1)\n}\n\nfunc f[T any](x T) { print(x) }\n-- a1 --\n...\nfunc _() {\n\tprint(int(1)) //@ inline(re\"f\", a1)\n}\n\n-- a/a1a.go --\npackage a\n\nfunc _() {\n\tf[([]int)]([]int{1}) //@ inline(re\"f\", a1a)\n}\n\nfunc f[T any](x T) { print(x) }\n-- a1a --\n...\nfunc _() {\n\tprint(([]int)([]int{1})) //@ inline(re\"f\", a1a)\n}\n\n-- a/a2.go --\npackage a\n\nfunc _() {\n\tf(1) //@ inline(re\"f\", re\"cannot inline.*type.*inference\")\n}\n\n-- a/a3.go --\npackage a\n\nfunc _() {\n\tg[int]() //@ inline(re\"g\", re\"cannot inline:.*shadow\")\n}\n\nfunc g[T any]() {\n\ttype int bool\n\tvar x T\n\tprint(x)\n}\n\n-- a/a4.go --\npackage a\n\nfunc _() {\n\tg[map[int]string]()  //@ inline(re\"g\", re\"cannot inline:.*shadow\")\n}\n\n-- a/a5.go --\npackage a\n\nimport \"testdata/b\"\n\ntype bool int\n\nfunc _() {\n\tb.H[int]() //@ inline(re\"H\", re\"cannot inline.*shadowed\")\n}\n-- b/b.go --\npackage b\n\nfunc H[T comparable]() {\n\tvar x map[T]bool\n\tprint(x)\n}\n\n-- a/a6.go --\npackage a\n\ntype G[T any] struct{}\n\nfunc (G[T]) f(x T) { print(x) }\n\nfunc _() {\n\tG[int]{}.f[bool]() //@ inline(re\"f\", re\"generic methods not yet supported\")\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-comments.txtar",
    "content": "This file checks various handling of comments when adding imports.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/empty.go --\npackage a // This is package a.\n\nfunc _() {\n\ta() //@ inline(re\"a\", empty)\n}\n\n-- empty --\npackage a // This is package a.\n\nimport \"testdata/b\"\n\nfunc _() {\n\tb.B() //@ inline(re\"a\", empty)\n}\n-- a/existing.go --\npackage a // This is package a.\n\n// This is an import block.\nimport (\n\t// This is an import of io.\n\t\"io\"\n\n\t// This is an import of c.\n\t\"testdata/c\" // yes, of c\n)\n\nvar (\n\t// This is an io.Writer.\n\t_ io.Writer\n\t// This is c.C\n\t_ c.C\n)\n\nfunc _() {\n\ta() //@ inline(re\"a\", existing)\n}\n\n-- existing --\npackage a // This is package a.\n\n// This is an import block.\nimport (\n\t// This is an import of io.\n\t\"io\"\n\t\"testdata/b\"\n\n\t// This is an import of c.\n\t\"testdata/c\" // yes, of c\n)\n\nvar (\n\t// This is an io.Writer.\n\t_ io.Writer\n\t// This is c.C\n\t_ c.C\n)\n\nfunc _() {\n\tb.B() //@ inline(re\"a\", existing)\n}\n\n-- a/noparens.go --\npackage a // This is package a.\n\n// This is an import of c.\nimport \"testdata/c\"\n\nfunc _() {\n\tvar _ c.C\n\ta() //@ inline(re\"a\", noparens)\n}\n\n-- noparens --\npackage a // This is package a.\n\nimport \"testdata/b\"\n\n// This is an import of c.\nimport \"testdata/c\"\n\nfunc _() {\n\tvar _ c.C\n\tb.B() //@ inline(re\"a\", noparens)\n}\n\n-- a/a.go --\npackage a\n\n// This is an import of b.\nimport \"testdata/b\"\n\nfunc a() {\n\t// This is a call to B.\n\tb.B()\n}\n\n-- b/b.go --\npackage b\n\nfunc B() {}\n\n-- c/c.go --\npackage c\n\ntype C int\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-comments2.txtar",
    "content": "Regression test for migration of comments in deleted imports (#67336).\n\n-- go.mod --\nmodule testdata\ngo 1.20\n\n-- define/my/typ/foo.go --\npackage typ\ntype T int\n\n-- some/other/pkg/foo.go --\npackage pkg\nimport \"context\"\nimport \"testdata/define/my/typ\"\nfunc Foo(typ.T) context.Context{ return nil }\n\n-- one/more/pkg/foo.go --\npackage pkg\nfunc Bar() {}\n\n-- to/be/inlined/foo.go --\npackage inlined\n\nimport \"context\"\nimport \"testdata/some/other/pkg\"\nimport \"testdata/define/my/typ\"\n\n// inlineme\nfunc Baz(ctx context.Context) context.Context {\n\treturn pkg.Foo(typ.T(5))\n}\n\n-- b/c/foo.go --\npackage c\nimport (\n\t\"context\"\n\t\"testdata/to/be/inlined\"\n\t\"testdata/one/more/pkg\"\n)\n\nconst (\n\t// This is a constant\n\tsomeConst = 5\n)\n\nfunc foo() {\n\tinlined.Baz(context.TODO()) //@inline(re\"Baz\", out)\n\tpkg.Bar()\n}\n\n-- out --\npackage c\n\nimport (\n\t\"context\"\n\t\"testdata/define/my/typ\"\n\tpkg0 \"testdata/some/other/pkg\"\n\n\t\"testdata/one/more/pkg\"\n)\n\nconst (\n\t// This is a constant\n\tsomeConst = 5\n)\n\nfunc foo() {\n\tvar _ context.Context = context.TODO()\n\tpkg0.Foo(typ.T(5)) //@inline(re\"Baz\", out)\n\tpkg.Bar()\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-preserve-local-pkgname.txtar",
    "content": "Test that when choosing local package names, we prefer the\nname used by the callee over a disambiguating numeric suffix.\n\n-- go.mod --\nmodule example.com\ngo 1.19\n\n-- main/main.go --\npackage main\n\nimport stringutil \"example.com/string/util\"\nimport \"example.com/util\"\n\nfunc main() {\n\tutil.A() //@ inline(re\"A\", result)\n\tstringutil.B()\n}\n\n-- util/util.go --\npackage util\n\nimport stringutil \"example.com/string/util\"\nimport urlutil \"example.com/url/util\"\n\nfunc A() {\n\tstringutil.A()\n\turlutil.A()\n}\n\n-- string/util/util.go --\npackage util\n\nfunc A() {\n}\n\nfunc B() {\n}\n\n-- url/util/util.go --\npackage util\n\nfunc A() {\n}\n\n-- result --\npackage main\n\nimport urlutil \"example.com/url/util\"\n\nimport stringutil \"example.com/string/util\"\n\nfunc main() {\n\tstringutil.A()\n\turlutil.A() //@ inline(re\"A\", result)\n\tstringutil.B()\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-rename.txtar",
    "content": "Regtest for https://github.com/golang/go/issues/67281\n\n-- go.mod --\nmodule example.com\ngo 1.19\n\n-- main/main.go --\npackage main\n\nimport \"example.com/a\"\n\nfunc main() {\n\ta.A() //@ inline(re\"A\", result)\n}\n\n-- a/a.go --\npackage a\n\nimport \"example.com/other/a\"\n\nfunc A() {\n\ta.A()\n}\n\n-- other/a/a.go --\npackage a\n\nfunc A() {\n}\n\n-- result --\npackage main\n\nimport \"example.com/other/a\"\n\nfunc main() {\n\ta.A() //@ inline(re\"A\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-shadow-1.txtar",
    "content": "This file is identical to import-shadow.txtar except\nthat the imports in a/a.go are not grouped.\nThat is unusual, since goimports and related tools\nform groups.\n\nThe result of inlining (bresult) also looks strange,\nbut again, goimports would fix it up.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\nimport \"log\"\n\nfunc A() {\n\tconst log = \"shadow\"\n\tb.B() //@ inline(re\"B\", bresult)\n}\n\nvar _ log.Logger\n\n-- b/b.go --\npackage b\n\nimport \"log\"\n\nfunc B() {\n\tlog.Printf(\"\")\n}\n\n-- bresult --\npackage a\n\nimport log0 \"log\"\n\nimport \"log\"\n\nfunc A() {\n\tconst log = \"shadow\"\n\tlog0.Printf(\"\") //@ inline(re\"B\", bresult)\n}\n\nvar _ log.Logger\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-shadow-2.txtar",
    "content": "See import-shadow.txtar for a description.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\n\nvar x b.T\n\nfunc A(b int) {\n\tx.F() //@ inline(re\"F\", fresult)\n}\n\n-- b/b.go --\npackage b\n\ntype T struct{}\n\nfunc (T) F() {\n\tOne()\n\tTwo()\n}\n\nfunc One() {}\nfunc Two() {}\n\n-- fresult --\npackage a\n\nimport b0 \"testdata/b\"\n\nimport \"testdata/b\"\n\nvar x b.T\n\nfunc A(b int) {\n\tb0.One()\n\tb0.Two() //@ inline(re\"F\", fresult)\n}\n\n-- d/d.go --\npackage d\n\nimport \"testdata/e\"\n\nfunc D() {\n\tconst log = \"shadow\"\n\te.E() //@ inline(re\"E\", eresult)\n}\n\n-- e/e.go --\npackage e\n\nimport \"log\"\n\nfunc E() {\n\tlog.Printf(\"\")\n}\n\n-- eresult --\npackage d\n\nimport log0 \"log\"\n\nfunc D() {\n\tconst log = \"shadow\"\n\tlog0.Printf(\"\") //@ inline(re\"E\", eresult)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/import-shadow.txtar",
    "content": "Just because a package (e.g. log) is imported by the caller,\nand the name log is in scope, doesn't mean the name in scope\nrefers to the package: it could be locally shadowed.\n\nIn all three scenarios in this file and import-shadow-2.txtar, a renaming\nimport with a fresh name is added because the usual name is locally\nshadowed: in cases 1, 2 an existing import is shadowed by (respectively)\na local constant, parameter; in case 3 there is no existing import.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport (\n\t\"testdata/b\"\n\t\"log\"\n)\n\nfunc A() {\n\tconst log = \"shadow\"\n\tb.B() //@ inline(re\"B\", bresult)\n}\n\nvar _ log.Logger\n\n-- b/b.go --\npackage b\n\nimport \"log\"\n\nfunc B() {\n\tlog.Printf(\"\")\n}\n\n-- bresult --\npackage a\n\nimport (\n\tlog0 \"log\"\n\n\t\"log\"\n)\n\nfunc A() {\n\tconst log = \"shadow\"\n\tlog0.Printf(\"\") //@ inline(re\"B\", bresult)\n}\n\nvar _ log.Logger\n"
  },
  {
    "path": "internal/refactor/inline/testdata/internal.txtar",
    "content": "Test of inlining a function that references an\ninternal package that is not accessible to the caller.\n\n(c -> b -> b/internal/a)\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- b/internal/a/a.go --\npackage a\n\nfunc A() {}\n\n-- b/b.go --\npackage b\n\nimport \"testdata/b/internal/a\"\n\nfunc B() { a.A() }\n\n-- c/c.go --\npackage c\n\nimport \"testdata/b\"\n\nfunc _() {\n\tb.B() //@ inline(re\"B\", re`body refers to inaccessible package \"testdata/b/internal/a\"`)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/issue62667.txtar",
    "content": "Regression test for #62667: the callee's reference to Split\nwas blindly qualified to path.Split even though the imported\nPkgName path is shadowed by the parameter of the same name.\n\nThe defer is to defeat reduction of the call and\nsubstitution of the path parameter by g().\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/path\"\n\nfunc A() {\n\tpath.Dir(g()) //@ inline(re\"Dir\", result)\n}\n\nfunc g() string\n\n-- path/path.go --\npackage path\n\nfunc Dir(path string) {\n\tdefer func(){}()\n\tSplit(path)\n}\n\nfunc Split(string) {}\n\n-- result --\npackage a\n\nimport path0 \"testdata/path\"\n\nfunc A() {\n\tfunc() { var path string = g(); defer func() {}(); path0.Split(path) }() //@ inline(re\"Dir\", result)\n}\n\nfunc g() string"
  },
  {
    "path": "internal/refactor/inline/testdata/issue63298.txtar",
    "content": "Regression test for #63298: inlining a function that\ndepends on two packages with the same name leads\nto duplicate PkgNames.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\ta2() //@ inline(re\"a2\", result)\n}\n\n-- a/a2.go --\npackage a\n\nimport \"testdata/b\"\nimport anotherb \"testdata/another/b\"\n\nfunc a2() {\n\tb.B()\n\tanotherb.B()\n}\n\n-- b/b.go --\npackage b\n\nfunc B() {}\n\n-- b/another/b.go --\npackage b\n\nfunc B() {}\n\n-- result --\npackage a\n\nimport \"testdata/b\"\n\nimport anotherb \"testdata/another/b\"\n\nfunc _() {\n\tb.B()\n\tanotherb.B() //@ inline(re\"a2\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/issue69441.txtar",
    "content": "This test checks that variadic elimination does not cause a semantic change due\nto creation of a non-nil empty slice instead of a nil slice due to missing\nvariadic arguments.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- foo/foo.go --\npackage foo\nimport \"fmt\"\n\nfunc F(is ...int) {\n\tif is == nil {\n\t\tfmt.Println(\"is is nil\")\n\t} else {\n\t\tfmt.Println(\"is is not nil\")\n\t}\n}\n\nfunc G(is ...int) { F(is...) }\n\nfunc main() {\n\tG() //@ inline(re\"G\", G)\n}\n\n-- G --\npackage foo\n\nimport \"fmt\"\n\nfunc F(is ...int) {\n\tif is == nil {\n\t\tfmt.Println(\"is is nil\")\n\t} else {\n\t\tfmt.Println(\"is is not nil\")\n\t}\n}\n\nfunc G(is ...int) { F(is...) }\n\nfunc main() {\n\tF() //@ inline(re\"G\", G)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/issue69442.txtar",
    "content": "This test checks that we don't introduce unnecessary (&v) or (*ptr) operations\nwhen calling a method on an addressable receiver.\n\n-- go.mod --\nmodule testdata\n\ngo 1.20\n\n-- main.go --\npackage foo\ntype T int\n\nfunc (*T) F() {}\n\nfunc (t *T) G() { t.F() }\n\nfunc main() {\n\tvar t T\n\tt.G() //@ inline(re\"G\", inline)\n}\n\n-- inline --\npackage foo\n\ntype T int\n\nfunc (*T) F() {}\n\nfunc (t *T) G() { t.F() }\n\nfunc main() {\n\tvar t T\n\tt.F() //@ inline(re\"G\", inline)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/line-directives.txtar",
    "content": "Test of line directives in caller and caller.\nNeither should have any effect on inlining.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"testdata/b\"\n\nfunc A() {\n//line b2.go:3:3\n\tb.F() //@ inline(re\"F\", result)\n}\n\n-- b/b.go --\npackage b\n\n//line b2.go:1:1\nfunc F() { println(\"hi\") }\n\n-- b/b2.go --\npackage b\n\nfunc NotWhatYouWereLookingFor() {}\n\n-- result --\npackage a\n\nfunc A() {\n//line b2.go:3:3\n\tprintln(\"hi\") //@ inline(re\"F\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/method.txtar",
    "content": "Test of inlining a method call.\n\nThe call to (*T).g0 implicitly takes the address &x, and\nthe call to T.h implicitly dereferences the argument *ptr.\n\nThe f1/g1 methods have parameters, exercising the\nsplicing of the receiver into the parameter list.\nNotice that the unnamed parameters become named.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/f0.go --\npackage a\n\ntype T int\n\nfunc (recv T) f0() { println(recv) }\n\nfunc _(x T) {\n\tx.f0() //@ inline(re\"f0\", f0)\n}\n\n-- f0 --\npackage a\n\ntype T int\n\nfunc (recv T) f0() { println(recv) }\n\nfunc _(x T) {\n\tprintln(x) //@ inline(re\"f0\", f0)\n}\n\n-- a/g0.go --\npackage a\n\nfunc (recv *T) g0() { println(recv) }\n\nfunc _(x T) {\n\tx.g0() //@ inline(re\"g0\", g0)\n}\n\n-- g0 --\npackage a\n\nfunc (recv *T) g0() { println(recv) }\n\nfunc _(x T) {\n\tprintln(&x) //@ inline(re\"g0\", g0)\n}\n\n-- a/f1.go --\npackage a\n\nfunc (recv T) f1(int, int) { println(recv) }\n\nfunc _(x T) {\n\tx.f1(1, 2) //@ inline(re\"f1\", f1)\n}\n\n-- f1 --\npackage a\n\nfunc (recv T) f1(int, int) { println(recv) }\n\nfunc _(x T) {\n\tprintln(x) //@ inline(re\"f1\", f1)\n}\n\n-- a/g1.go --\npackage a\n\nfunc (recv *T) g1(int, int) { println(recv) }\n\nfunc _(x T) {\n\tx.g1(1, 2) //@ inline(re\"g1\", g1)\n}\n\n-- g1 --\npackage a\n\nfunc (recv *T) g1(int, int) { println(recv) }\n\nfunc _(x T) {\n\tprintln(&x) //@ inline(re\"g1\", g1)\n}\n\n-- a/h.go --\npackage a\n\nfunc (T) h() int { return 1 }\n\nfunc _() {\n\tvar ptr *T\n\tptr.h() //@ inline(re\"h\", h)\n}\n\n-- h --\npackage a\n\nfunc (T) h() int { return 1 }\n\nfunc _() {\n\tvar ptr *T\n\tvar _ T = *ptr\n\t_ = 1 //@ inline(re\"h\", h)\n}\n\n-- a/i.go --\npackage a\n\nfunc (T) i() int { return 1 }\n\nfunc _() {\n\t(*T).i(nil) //@ inline(re\"i\", i)\n}\n\n-- i --\npackage a\n\nfunc (T) i() int { return 1 }\n\nfunc _() {\n\t_ = 1 //@ inline(re\"i\", i)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/multistmt-body.txtar",
    "content": "Tests of reduction of calls to multi-statement bodies.\n\na1: reduced to a block with a parameter binding decl.\n   (Parameter x can't be substituted by z without a shadowing conflict.)\n\na2: reduced with parameter substitution (no shadowing).\n\na3: literalized, because of the return statement.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a1.go --\npackage a\n\nfunc _() {\n\tz := 1\n\tf(z, 2) //@ inline(re\"f\", out1)\n}\n\nfunc f(x, y int) {\n\tz := 1\n\tprint(x + y + z)\n}\n\n-- out1 --\npackage a\n\nfunc _() {\n\tz := 1\n\t{\n\t\tvar x int = z\n\t\tz := 1\n\t\tprint(x + 2 + z)\n\t} //@ inline(re\"f\", out1)\n}\n\nfunc f(x, y int) {\n\tz := 1\n\tprint(x + y + z)\n}\n\n-- a/a2.go --\npackage a\n\nfunc _() {\n\ta := 1\n\tf(a, 2) //@ inline(re\"f\", out2)\n}\n\n-- out2 --\npackage a\n\nfunc _() {\n\ta := 1\n\tz := 1\n\tprint(a + 2 + z) //@ inline(re\"f\", out2)\n}\n\n-- a/a3.go --\npackage a\n\nfunc _() {\n\ta := 1\n\tg(a, 2) //@ inline(re\"g\", out3)\n}\n\nfunc g(x, y int) int {\n\tz := 1\n\treturn x + y + z\n}\n\n-- out3 --\npackage a\n\nfunc _() {\n\ta := 1\n\tfunc() int { z := 1; return a + 2 + z }() //@ inline(re\"g\", out3)\n}\n\nfunc g(x, y int) int {\n\tz := 1\n\treturn x + y + z\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/n-ary.txtar",
    "content": "Tests of various n-ary result function cases.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc _() {\n\tprintln(f1()) //@ inline(re\"f1\", f1)\n}\n\nfunc f1() (int, int) { return 1, 1 }\n\n-- f1 --\npackage a\n\nfunc _() {\n\tprintln(1, 1) //@ inline(re\"f1\", f1)\n}\n\nfunc f1() (int, int) { return 1, 1 }\n\n-- b/b.go --\npackage b\n\nfunc _() {\n\tf2() //@ inline(re\"f2\", f2)\n}\n\nfunc f2() (int, int) { return 2, 2 }\n\n-- f2 --\npackage b\n\nfunc _() {\n\t_, _ = 2, 2 //@ inline(re\"f2\", f2)\n}\n\nfunc f2() (int, int) { return 2, 2 }\n\n-- c/c.go --\npackage c\n\nfunc _() {\n\t_, _ = f3() //@ inline(re\"f3\", f3)\n}\n\nfunc f3() (int, int) { return f3A() }\nfunc f3A() (x, y int)\n\n-- f3 --\npackage c\n\nfunc _() {\n\t_, _ = f3A() //@ inline(re\"f3\", f3)\n}\n\nfunc f3() (int, int) { return f3A() }\nfunc f3A() (x, y int)\n\n-- d/d.go --\npackage d\n\nfunc _() {\n\tprintln(-f4()) //@ inline(re\"f4\", f4)\n}\n\nfunc f4() int { return 2 + 2 }\n\n-- f4 --\npackage d\n\nfunc _() {\n\tprintln(-(2 + 2)) //@ inline(re\"f4\", f4)\n}\n\nfunc f4() int { return 2 + 2 }\n-- e/e.go --\npackage e\n\nfunc _() {\n\tswitch {\n\tcase true:\n\t\ta, b := f5() //@ inline(re\"f5\", f5)\n\t\t_, _ = a, b\n\t}\n}\n\nfunc f5() (int, int) { return 2, 2}\n\n-- f5 --\npackage e\n\nfunc _() {\n\tswitch {\n\tcase true:\n\t\ta, b := 2, 2 //@ inline(re\"f5\", f5)\n\t\t_, _ = a, b\n\t}\n}\n\nfunc f5() (int, int) { return 2, 2 }\n"
  },
  {
    "path": "internal/refactor/inline/testdata/newexpr.txtar",
    "content": "Regression test for https://go.dev/issue/76287:\nensure that inlining a function that wraps go1.26's new(expr)\ncorrectly inserts a conversion as needed, just as it would for a\ndeclared generic function equivalent to 'new'.\n\n- f uses a declared _new(expr) function.\n- g uses the built-in new(expr) function.\n\n-- go.mod --\nmodule testdata\ngo 1.26\n\n-- common.go --\npackage p\n\nfunc _new[T any](x T) *T { return &x }\n\n-- f.go --\npackage p\n\nfunc f(x int64) *int64 { return _new(x) }\n\nvar _ *int64 = f(42) //@ inline(re\"f\", f)\n\n-- g.go --\npackage p\n\nfunc g(x int64) *int64 { return new(x) }\n\nvar _ *int64 = g(42) //@ inline(re\"g\", g)\n\n-- f --\npackage p\n\nfunc f(x int64) *int64 { return _new(x) }\n\nvar _ *int64 = _new(int64(42)) //@ inline(re\"f\", f)\n\n-- g --\npackage p\n\nfunc g(x int64) *int64 { return new(x) }\n\nvar _ *int64 = new(int64(42)) //@ inline(re\"g\", g)\n"
  },
  {
    "path": "internal/refactor/inline/testdata/param-subst.txtar",
    "content": "Test of parameter substitution.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a0.go --\npackage a\n\nvar _ = add(2, 1+1) //@ inline(re\"add\", add)\n\nfunc add(x, y int) int { return x + 2*y }\n\n-- add --\npackage a\n\nvar _ = 2 + 2*(1+1) //@ inline(re\"add\", add)\n\nfunc add(x, y int) int { return x + 2*y }"
  },
  {
    "path": "internal/refactor/inline/testdata/revdotimport.txtar",
    "content": "Test of inlining a function into a context that already\ndot-imports the necessary additional import.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nfunc A() {}\n\n-- b/b.go --\npackage b\n\nimport \"testdata/a\"\n\nfunc B() { a.A() }\n\n-- c/c.go --\npackage c\n\nimport . \"testdata/a\"\nimport \"testdata/b\"\n\nfunc _() {\n\tA()\n\tb.B() //@ inline(re\"B\", result)\n}\n\n-- result --\npackage c\n\nimport \"testdata/a\"\n\nimport . \"testdata/a\"\n\nfunc _() {\n\tA()\n\ta.A() //@ inline(re\"B\", result)\n}\n"
  },
  {
    "path": "internal/refactor/inline/testdata/std-internal.txtar",
    "content": "\nstd packages are a special case of the internal package check.\n\nThis test assumes that syscall.ByteSliceFromString refers to internal/bytealg.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a.go --\npackage a\n\nimport \"syscall\"\n\nvar _, _ = syscall.ByteSliceFromString(\"\") //@ inline(re\"ByteSliceFromString\", re`inaccessible package \"internal/bytealg\"`)\n"
  },
  {
    "path": "internal/refactor/inline/testdata/substgroups.txtar",
    "content": "This test checks that parameter shadowing is avoided for substitution groups,\nas well as the examples of recursive pruning of these groups based on falcon\nand effects analysis.\n\n-- go.mod --\nmodule testdata\n\ngo 1.20\n\n-- falcon.go --\npackage a\n\nvar a [3]int\n\nfunc falcon(x, y, z int) {\n\t_ = x + a[y+z]\n}\n\nfunc _() {\n\tvar y int\n\tconst x, z = 1, 2\n\tfalcon(y, x, z) //@ inline(re\"falcon\", falcon)\n}\n\n-- falcon --\npackage a\n\nvar a [3]int\n\nfunc falcon(x, y, z int) {\n\t_ = x + a[y+z]\n}\n\nfunc _() {\n\tvar y int\n\tconst x, z = 1, 2\n\t{\n\t\tvar x, y, z int = y, x, z\n\t\t_ = x + a[y+z]\n\t} //@ inline(re\"falcon\", falcon)\n}\n\n-- effects.go --\npackage a\n\nfunc effects(w, x, y, z int) {\n\t_ = x + w + y + z\n}\n\nfunc _() {\n  v := 0\n  w := func() int { v++; return 0 }\n  x := func() int { v++; return 0 }\n  y := func() int { v++; return 0 }\n\teffects(x(), w(), y(), x()) //@ inline(re\"effects\", effects)\n}\n\n-- effects --\npackage a\n\nfunc effects(w, x, y, z int) {\n\t_ = x + w + y + z\n}\n\nfunc _() {\n\tv := 0\n\tw := func() int { v++; return 0 }\n\tx := func() int { v++; return 0 }\n\ty := func() int { v++; return 0 }\n\t{\n\t\tvar w, x, y, z int = x(), w(), y(), x()\n\t\t_ = x + w + y + z\n\t} //@ inline(re\"effects\", effects)\n}\n\n-- negative.go --\npackage a\n\nfunc _() {\n\ti := -1\n\tif negative1(i, i) { //@ inline(re\"negative1\", negative1)\n\t\ti := 0\n\t\t_ = i\n\t}\n}\n\nfunc negative1(i, j int) bool {\n\treturn negative2(j, i)\n}\n\nfunc negative2(i, j int) bool {\n\treturn i < 0\n}\n\n-- negative1 --\npackage a\n\nfunc _() {\n\ti := -1\n\tif negative2(i, i) { //@ inline(re\"negative1\", negative1)\n\t\ti := 0\n\t\t_ = i\n\t}\n}\n\nfunc negative1(i, j int) bool {\n\treturn negative2(j, i)\n}\n\nfunc negative2(i, j int) bool {\n\treturn i < 0\n}\n\n"
  },
  {
    "path": "internal/refactor/inline/testdata/tailcall.txtar",
    "content": "Reduction of parameterless tail-call to functions.\n\n1. a0 (sum) is reduced, despite the complexity of the callee.\n\n2. a1 (conflict) is not reduced, because the caller and callee have\n   intersecting sets of labels.\n\n3. a2 (usesResult) is not reduced, because it refers to a result variable.\n\n-- go.mod --\nmodule testdata\ngo 1.12\n\n-- a/a0.go --\npackage a\n\nfunc _() int {\n\treturn sum(1, 2) //@ inline(re\"sum\", sum)\n}\n\nfunc sum(lo, hi int) int {\n\ttotal := 0\nstart:\n\tfor i := lo; i <= hi; i++ {\n\t\ttotal += i\n\t\tif i == 6 {\n\t\t\tgoto start\n\t\t} else if i == 7 {\n\t\t\treturn -1\n\t\t}\n\t}\n\treturn total\n}\n\n-- sum --\npackage a\n\nfunc _() int {\n\ttotal := 0\nstart:\n\tfor i := 1; i <= 2; i++ {\n\t\ttotal += i\n\t\tif i == 6 {\n\t\t\tgoto start\n\t\t} else if i == 7 {\n\t\t\treturn -1\n\t\t}\n\t}\n\treturn total //@ inline(re\"sum\", sum)\n}\n\nfunc sum(lo, hi int) int {\n\ttotal := 0\nstart:\n\tfor i := lo; i <= hi; i++ {\n\t\ttotal += i\n\t\tif i == 6 {\n\t\t\tgoto start\n\t\t} else if i == 7 {\n\t\t\treturn -1\n\t\t}\n\t}\n\treturn total\n}\n\n-- a/a1.go --\npackage a\n\nfunc _() int {\n\thello:\n\treturn conflict(1, 2) //@ inline(re\"conflict\", conflict)\n\tgoto hello\n}\n\nfunc conflict(lo, hi int) int {\nhello:\n\treturn lo + hi\n}\n\n-- conflict --\npackage a\n\nfunc _() int {\nhello:\n\treturn func() int {\n\thello:\n\t\treturn 1 + 2\n\t}() //@ inline(re\"conflict\", conflict)\n\tgoto hello\n}\n\nfunc conflict(lo, hi int) int {\nhello:\n\treturn lo + hi\n}\n\n-- a/a2.go --\npackage a\n\nfunc _() int {\n\treturn usesResult(1, 2) //@ inline(re\"usesResult\", usesResult)\n}\n\nfunc usesResult(lo, hi int) (z int) {\n\tz = y + x\n\treturn\n}\n\n-- usesResult --\npackage a\n\nfunc _() int {\n\treturn func() (z int) { z = y + x; return }() //@ inline(re\"usesResult\", usesResult)\n}\n\nfunc usesResult(lo, hi int) (z int) {\n\tz = y + x\n\treturn\n}\n\n"
  },
  {
    "path": "internal/refactor/inline/util.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage inline\n\n// This file defines various common helpers.\n\nimport (\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n\nfunc btoi(b bool) int {\n\tif b {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfunc offsetOf(fset *token.FileSet, pos token.Pos) int {\n\treturn fset.PositionFor(pos, false).Offset\n}\n\n// objectKind returns an object's kind (e.g. var, func, const, typename).\nfunc objectKind(obj types.Object) string {\n\treturn strings.TrimPrefix(strings.ToLower(reflect.TypeOf(obj).String()), \"*types.\")\n}\n\n// within reports whether pos is within the half-open interval [n.Pos, n.End).\nfunc within(pos token.Pos, n ast.Node) bool {\n\treturn n.Pos() <= pos && pos < n.End()\n}\n\n// trivialConversion reports whether it is safe to omit the implicit\n// value-to-variable conversion that occurs in argument passing or\n// result return. The only case currently allowed is converting from\n// untyped constant to its default type (e.g. 0 to int).\n//\n// The reason for this check is that converting from A to B to C may\n// yield a different result than converting A directly to C: consider\n// 0 to int32 to any.\n//\n// trivialConversion under-approximates trivial conversions, as unfortunately\n// go/types does not record the type of an expression *before* it is implicitly\n// converted, and therefore it cannot distinguish typed constant\n// expressions from untyped constant expressions. For example, in the\n// expression `c + 2`, where c is a uint32 constant, trivialConversion does not\n// detect that the default type of this expression is actually uint32, not untyped\n// int.\n//\n// We could, of course, do better here by reverse engineering some of go/types'\n// constant handling. That may or may not be worthwhile.\n//\n// Example: in func f() int32 { return 0 },\n// the type recorded for 0 is int32, not untyped int;\n// although it is Identical to the result var,\n// the conversion is non-trivial.\nfunc trivialConversion(fromValue constant.Value, from, to types.Type) bool {\n\tif fromValue != nil {\n\t\tvar defaultType types.Type\n\t\tswitch fromValue.Kind() {\n\t\tcase constant.Bool:\n\t\t\tdefaultType = types.Typ[types.Bool]\n\t\tcase constant.String:\n\t\t\tdefaultType = types.Typ[types.String]\n\t\tcase constant.Int:\n\t\t\tdefaultType = types.Typ[types.Int]\n\t\tcase constant.Float:\n\t\t\tdefaultType = types.Typ[types.Float64]\n\t\tcase constant.Complex:\n\t\t\tdefaultType = types.Typ[types.Complex128]\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t\treturn types.Identical(defaultType, to)\n\t}\n\treturn types.Identical(from, to)\n}\n\nfunc checkInfoFields(info *types.Info) {\n\tassert(info.Defs != nil, \"types.Info.Defs is nil\")\n\tassert(info.Implicits != nil, \"types.Info.Implicits is nil\")\n\tassert(info.Scopes != nil, \"types.Info.Scopes is nil\")\n\tassert(info.Selections != nil, \"types.Info.Selections is nil\")\n\tassert(info.Types != nil, \"types.Info.Types is nil\")\n\tassert(info.Uses != nil, \"types.Info.Uses is nil\")\n\tassert(info.FileVersions != nil, \"types.Info.FileVersions is nil\")\n}\n\n// intersects reports whether the maps' key sets intersect.\nfunc intersects[K comparable, T1, T2 any](x map[K]T1, y map[K]T2) bool {\n\tif len(x) > len(y) {\n\t\treturn intersects(y, x)\n\t}\n\tfor k := range x {\n\t\tif _, ok := y[k]; ok {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// convert returns syntax for the conversion T(x).\nfunc convert(T, x ast.Expr) *ast.CallExpr {\n\t// The formatter generally adds parens as needed,\n\t// but before go1.22 it had a bug (#63362) for\n\t// channel types that requires this workaround.\n\tif ch, ok := T.(*ast.ChanType); ok && ch.Dir == ast.RECV {\n\t\tT = &ast.ParenExpr{X: T}\n\t}\n\treturn &ast.CallExpr{\n\t\tFun:  T,\n\t\tArgs: []ast.Expr{x},\n\t}\n}\n\n// isPointer reports whether t's core type is a pointer.\nfunc isPointer(t types.Type) bool {\n\treturn is[*types.Pointer](typeparams.CoreType(t))\n}\n\n// indirectSelection is like seln.Indirect() without bug #8353.\nfunc indirectSelection(seln *types.Selection) bool {\n\t// Work around bug #8353 in Selection.Indirect when Kind=MethodVal.\n\tif seln.Kind() == types.MethodVal {\n\t\ttArg, indirect := effectiveReceiver(seln)\n\t\tif indirect {\n\t\t\treturn true\n\t\t}\n\n\t\ttParam := seln.Obj().Type().Underlying().(*types.Signature).Recv().Type()\n\t\treturn isPointer(tArg) && !isPointer(tParam) // implicit *\n\t}\n\n\treturn seln.Indirect()\n}\n\n// effectiveReceiver returns the effective type of the method\n// receiver after all implicit field selections (but not implicit * or\n// & operations) have been applied.\n//\n// The boolean indicates whether any implicit field selection was indirect.\nfunc effectiveReceiver(seln *types.Selection) (types.Type, bool) {\n\tassert(seln.Kind() == types.MethodVal, \"not MethodVal\")\n\tt := seln.Recv()\n\tindices := seln.Index()\n\tindirect := false\n\tfor _, index := range indices[:len(indices)-1] {\n\t\tif isPointer(t) {\n\t\t\tindirect = true\n\t\t\tt = typeparams.MustDeref(t)\n\t\t}\n\t\tt = typeparams.CoreType(t).(*types.Struct).Field(index).Type()\n\t}\n\treturn t, indirect\n}\n"
  },
  {
    "path": "internal/refactor/refactor.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package refactor provides operators to compute common textual edits\n// for refactoring tools.\n//\n// This package should not use features of the analysis API other than [Edit].\npackage refactor\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// FreshName returns the name of an identifier that is undefined\n// at the specified position, based on the preferred name.\n//\n// export/use freshName in go/analysis/passes/modernize/modernize.go if you want\n// to generate a fresh name only when necessary (i.e., there is both an existing\n// declaration and some free reference to the name within a narrower scope)\nfunc FreshName(scope *types.Scope, pos token.Pos, preferred string) string {\n\tnewName := preferred\n\tfor i := 0; ; i++ {\n\t\tif _, obj := scope.LookupParent(newName, pos); obj == nil {\n\t\t\tbreak // fresh\n\t\t}\n\t\tnewName = fmt.Sprintf(\"%s%d\", preferred, i)\n\t}\n\treturn newName\n}\n"
  },
  {
    "path": "internal/robustio/copyfiles.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The copyfiles script copies the contents of the internal cmd/go robustio\n// package to the current directory, with adjustments to make it build.\n//\n// NOTE: In retrospect this script got out of hand, as we have to perform\n// various operations on the package to get it to build at old Go versions. If\n// in the future it proves to be flaky, delete it and just copy code manually.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"go/build/constraint\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n)\n\nfunc main() {\n\tdir := filepath.Join(runtime.GOROOT(), \"src\", \"cmd\", \"go\", \"internal\", \"robustio\")\n\n\tentries, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tlog.Fatalf(\"reading the robustio dir: %v\", err)\n\t}\n\n\t// Collect file content so that we can validate before copying.\n\tfileContent := make(map[string][]byte)\n\twindowsImport := []byte(\"\\t\\\"internal/syscall/windows\\\"\\n\")\n\tfoundWindowsImport := false\n\tfor _, entry := range entries {\n\t\tif strings.HasSuffix(entry.Name(), \".go\") {\n\t\t\tpth := filepath.Join(dir, entry.Name())\n\t\t\tcontent, err := os.ReadFile(pth)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"reading %q: %v\", entry.Name(), err)\n\t\t\t}\n\n\t\t\t// Replace the use of internal/syscall/windows.ERROR_SHARING_VIOLATION\n\t\t\t// with a local constant.\n\t\t\tif entry.Name() == \"robustio_windows.go\" && bytes.Contains(content, windowsImport) {\n\t\t\t\tfoundWindowsImport = true\n\t\t\t\tcontent = bytes.Replace(content, windowsImport, nil, 1)\n\t\t\t\tcontent = bytes.Replace(content, []byte(\"windows.ERROR_SHARING_VIOLATION\"), []byte(\"ERROR_SHARING_VIOLATION\"), -1)\n\t\t\t}\n\n\t\t\t// Replace os.ReadFile with os.ReadFile (for 1.15 and older). We\n\t\t\t// attempt to match calls (via the '('), to avoid matching mentions of\n\t\t\t// os.ReadFile in comments.\n\t\t\t//\n\t\t\t// TODO(rfindley): once we (shortly!) no longer support 1.15, remove\n\t\t\t// this and break the build.\n\t\t\tif bytes.Contains(content, []byte(\"os.ReadFile(\")) {\n\t\t\t\tcontent = bytes.Replace(content, []byte(\"\\\"os\\\"\"), []byte(\"\\\"io/ioutil\\\"\\n\\t\\\"os\\\"\"), 1)\n\t\t\t\tcontent = bytes.Replace(content, []byte(\"os.ReadFile(\"), []byte(\"os.ReadFile(\"), -1)\n\t\t\t}\n\n\t\t\t// Add +build constraints, for 1.16.\n\t\t\tcontent = addPlusBuildConstraints(content)\n\n\t\t\tfileContent[entry.Name()] = content\n\t\t}\n\t}\n\n\tif !foundWindowsImport {\n\t\tlog.Fatal(\"missing expected import of internal/syscall/windows in robustio_windows.go\")\n\t}\n\n\tfor name, content := range fileContent {\n\t\tif err := os.WriteFile(name, content, 0644); err != nil {\n\t\t\tlog.Fatalf(\"writing %q: %v\", name, err)\n\t\t}\n\t}\n}\n\n// addPlusBuildConstraints splices in +build constraints for go:build\n// constraints encountered in the source.\n//\n// Gopls still builds at Go 1.16, which requires +build constraints.\nfunc addPlusBuildConstraints(src []byte) []byte {\n\tvar s scanner.Scanner\n\tfset := token.NewFileSet()\n\tfile := fset.AddFile(\"\", fset.Base(), len(src))\n\ts.Init(file, src, nil /* no error handler */, scanner.ScanComments)\n\n\tresult := make([]byte, 0, len(src))\n\tlastInsertion := 0\n\tfor {\n\t\tpos, tok, lit := s.Scan()\n\t\tif tok == token.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif tok == token.COMMENT {\n\t\t\tif c, err := constraint.Parse(lit); err == nil {\n\t\t\t\tplusBuild, err := constraint.PlusBuildLines(c)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Fatalf(\"computing +build constraint for %q: %v\", lit, err)\n\t\t\t\t}\n\t\t\t\tinsertAt := file.Offset(pos) + len(lit)\n\t\t\t\tresult = append(result, src[lastInsertion:insertAt]...)\n\t\t\t\tresult = append(result, []byte(\"\\n\"+strings.Join(plusBuild, \"\\n\"))...)\n\t\t\t\tlastInsertion = insertAt\n\t\t\t}\n\t\t}\n\t}\n\tresult = append(result, src[lastInsertion:]...)\n\treturn result\n}\n"
  },
  {
    "path": "internal/robustio/gopls_windows.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage robustio\n\nimport \"syscall\"\n\n// The robustio package is copied from cmd/go/internal/robustio, a package used\n// by the go command to retry known flaky operations on certain operating systems.\n\n//go:generate go run copyfiles.go\n\n// Since the gopls module cannot access internal/syscall/windows, copy a\n// necessary constant.\nconst ERROR_SHARING_VIOLATION syscall.Errno = 32\n"
  },
  {
    "path": "internal/robustio/robustio.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package robustio wraps I/O functions that are prone to failure on Windows,\n// transparently retrying errors up to an arbitrary timeout.\n//\n// Errors are classified heuristically and retries are bounded, so the functions\n// in this package do not completely eliminate spurious errors. However, they do\n// significantly reduce the rate of failure in practice.\n//\n// If so, the error will likely wrap one of:\n// The functions in this package do not completely eliminate spurious errors,\n// but substantially reduce their rate of occurrence in practice.\npackage robustio\n\nimport \"time\"\n\n// Rename is like os.Rename, but on Windows retries errors that may occur if the\n// file is concurrently read or overwritten.\n//\n// (See golang.org/issue/31247 and golang.org/issue/32188.)\nfunc Rename(oldpath, newpath string) error {\n\treturn rename(oldpath, newpath)\n}\n\n// ReadFile is like os.ReadFile, but on Windows retries errors that may\n// occur if the file is concurrently replaced.\n//\n// (See golang.org/issue/31247 and golang.org/issue/32188.)\nfunc ReadFile(filename string) ([]byte, error) {\n\treturn readFile(filename)\n}\n\n// RemoveAll is like os.RemoveAll, but on Windows retries errors that may occur\n// if an executable file in the directory has recently been executed.\n//\n// (See golang.org/issue/19491.)\nfunc RemoveAll(path string) error {\n\treturn removeAll(path)\n}\n\n// IsEphemeralError reports whether err is one of the errors that the functions\n// in this package attempt to mitigate.\n//\n// Errors considered ephemeral include:\n//   - syscall.ERROR_ACCESS_DENIED\n//   - syscall.ERROR_FILE_NOT_FOUND\n//   - internal/syscall/windows.ERROR_SHARING_VIOLATION\n//\n// This set may be expanded in the future; programs must not rely on the\n// non-ephemerality of any given error.\nfunc IsEphemeralError(err error) bool {\n\treturn isEphemeralError(err)\n}\n\n// A FileID uniquely identifies a file in the file system.\n//\n// If GetFileID(name1) returns the same ID as GetFileID(name2), the two file\n// names denote the same file.\n// A FileID is comparable, and thus suitable for use as a map key.\ntype FileID struct {\n\tdevice, inode uint64\n}\n\n// GetFileID returns the file system's identifier for the file, and its\n// modification time.\n// Like os.Stat, it reads through symbolic links.\nfunc GetFileID(filename string) (FileID, time.Time, error) { return getFileID(filename) }\n"
  },
  {
    "path": "internal/robustio/robustio_darwin.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage robustio\n\nimport (\n\t\"errors\"\n\t\"syscall\"\n)\n\nconst errFileNotFound = syscall.ENOENT\n\n// isEphemeralError returns true if err may be resolved by waiting.\nfunc isEphemeralError(err error) bool {\n\tvar errno syscall.Errno\n\tif errors.As(err, &errno) {\n\t\treturn errno == errFileNotFound\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/robustio/robustio_flaky.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build windows || darwin\n\npackage robustio\n\nimport (\n\t\"errors\"\n\t\"math/rand\"\n\t\"os\"\n\t\"syscall\"\n\t\"time\"\n)\n\nconst arbitraryTimeout = 2000 * time.Millisecond\n\n// retry retries ephemeral errors from f up to an arbitrary timeout\n// to work around filesystem flakiness on Windows and Darwin.\nfunc retry(f func() (err error, mayRetry bool)) error {\n\tvar (\n\t\tbestErr     error\n\t\tlowestErrno syscall.Errno\n\t\tstart       time.Time\n\t\tnextSleep   time.Duration = 1 * time.Millisecond\n\t)\n\tfor {\n\t\terr, mayRetry := f()\n\t\tif err == nil || !mayRetry {\n\t\t\treturn err\n\t\t}\n\n\t\tvar errno syscall.Errno\n\t\tif errors.As(err, &errno) && (lowestErrno == 0 || errno < lowestErrno) {\n\t\t\tbestErr = err\n\t\t\tlowestErrno = errno\n\t\t} else if bestErr == nil {\n\t\t\tbestErr = err\n\t\t}\n\n\t\tif start.IsZero() {\n\t\t\tstart = time.Now()\n\t\t} else if d := time.Since(start) + nextSleep; d >= arbitraryTimeout {\n\t\t\tbreak\n\t\t}\n\t\ttime.Sleep(nextSleep)\n\t\tnextSleep += time.Duration(rand.Int63n(int64(nextSleep)))\n\t}\n\n\treturn bestErr\n}\n\n// rename is like os.Rename, but retries ephemeral errors.\n//\n// On Windows it wraps os.Rename, which (as of 2019-06-04) uses MoveFileEx with\n// MOVEFILE_REPLACE_EXISTING.\n//\n// Windows also provides a different system call, ReplaceFile,\n// that provides similar semantics, but perhaps preserves more metadata. (The\n// documentation on the differences between the two is very sparse.)\n//\n// Empirical error rates with MoveFileEx are lower under modest concurrency, so\n// for now we're sticking with what the os package already provides.\nfunc rename(oldpath, newpath string) (err error) {\n\treturn retry(func() (err error, mayRetry bool) {\n\t\terr = os.Rename(oldpath, newpath)\n\t\treturn err, isEphemeralError(err)\n\t})\n}\n\n// readFile is like os.ReadFile, but retries ephemeral errors.\nfunc readFile(filename string) ([]byte, error) {\n\tvar b []byte\n\terr := retry(func() (err error, mayRetry bool) {\n\t\tb, err = os.ReadFile(filename)\n\n\t\t// Unlike in rename, we do not retry errFileNotFound here: it can occur\n\t\t// as a spurious error, but the file may also genuinely not exist, so the\n\t\t// increase in robustness is probably not worth the extra latency.\n\t\treturn err, isEphemeralError(err) && !errors.Is(err, errFileNotFound)\n\t})\n\treturn b, err\n}\n\nfunc removeAll(path string) error {\n\treturn retry(func() (err error, mayRetry bool) {\n\t\terr = os.RemoveAll(path)\n\t\treturn err, isEphemeralError(err)\n\t})\n}\n"
  },
  {
    "path": "internal/robustio/robustio_other.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !windows && !darwin\n\npackage robustio\n\nimport (\n\t\"os\"\n)\n\nfunc rename(oldpath, newpath string) error {\n\treturn os.Rename(oldpath, newpath)\n}\n\nfunc readFile(filename string) ([]byte, error) {\n\treturn os.ReadFile(filename)\n}\n\nfunc removeAll(path string) error {\n\treturn os.RemoveAll(path)\n}\n\nfunc isEphemeralError(err error) bool {\n\treturn false\n}\n"
  },
  {
    "path": "internal/robustio/robustio_plan9.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build plan9\n\npackage robustio\n\nimport (\n\t\"os\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc getFileID(filename string) (FileID, time.Time, error) {\n\tfi, err := os.Stat(filename)\n\tif err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\tdir := fi.Sys().(*syscall.Dir)\n\treturn FileID{\n\t\tdevice: uint64(dir.Type)<<32 | uint64(dir.Dev),\n\t\tinode:  dir.Qid.Path,\n\t}, fi.ModTime(), nil\n}\n"
  },
  {
    "path": "internal/robustio/robustio_posix.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !windows && !plan9\n\npackage robustio\n\nimport (\n\t\"os\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc getFileID(filename string) (FileID, time.Time, error) {\n\tfi, err := os.Stat(filename)\n\tif err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\tstat := fi.Sys().(*syscall.Stat_t)\n\treturn FileID{\n\t\tdevice: uint64(stat.Dev), // (int32 on darwin, uint64 on linux)\n\t\tinode:  stat.Ino,\n\t}, fi.ModTime(), nil\n}\n"
  },
  {
    "path": "internal/robustio/robustio_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage robustio_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/tools/internal/robustio\"\n)\n\nfunc checkOSLink(t *testing.T, err error) {\n\tif err == nil {\n\t\treturn\n\t}\n\n\tt.Helper()\n\tswitch runtime.GOOS {\n\tcase \"aix\", \"darwin\", \"dragonfly\", \"freebsd\", \"illumos\", \"linux\", \"netbsd\", \"openbsd\", \"solaris\":\n\t\t// Non-mobile OS known to always support os.Symlink and os.Link.\n\t\tt.Fatal(err)\n\tdefault:\n\t\tt.Skipf(\"skipping due to error on %v: %v\", runtime.GOOS, err)\n\t}\n}\n\nfunc TestFileInfo(t *testing.T) {\n\t// A nonexistent file has no ID.\n\tnonexistent := filepath.Join(t.TempDir(), \"nonexistent\")\n\tif _, _, err := robustio.GetFileID(nonexistent); err == nil {\n\t\tt.Fatalf(\"GetFileID(nonexistent) succeeded unexpectedly\")\n\t}\n\n\t// A regular file has an ID.\n\treal := filepath.Join(t.TempDir(), \"real\")\n\tif err := os.WriteFile(real, nil, 0644); err != nil {\n\t\tt.Fatalf(\"can't create regular file: %v\", err)\n\t}\n\trealID, realMtime, err := robustio.GetFileID(real)\n\tif err != nil {\n\t\tt.Fatalf(\"can't get ID of regular file: %v\", err)\n\t}\n\n\t// Sleep so that we get a new mtime for subsequent writes.\n\ttime.Sleep(2 * time.Second)\n\n\t// A second regular file has a different ID.\n\treal2 := filepath.Join(t.TempDir(), \"real2\")\n\tif err := os.WriteFile(real2, nil, 0644); err != nil {\n\t\tt.Fatalf(\"can't create second regular file: %v\", err)\n\t}\n\treal2ID, real2Mtime, err := robustio.GetFileID(real2)\n\tif err != nil {\n\t\tt.Fatalf(\"can't get ID of second regular file: %v\", err)\n\t}\n\tif realID == real2ID {\n\t\tt.Errorf(\"realID %+v == real2ID %+v\", realID, real2ID)\n\t}\n\tif realMtime.Equal(real2Mtime) {\n\t\tt.Errorf(\"realMtime %v == real2Mtime %v\", realMtime, real2Mtime)\n\t}\n\n\t// A symbolic link has the same ID as its target.\n\tt.Run(\"symlink\", func(t *testing.T) {\n\t\tsymlink := filepath.Join(t.TempDir(), \"symlink\")\n\t\tcheckOSLink(t, os.Symlink(real, symlink))\n\n\t\tsymlinkID, symlinkMtime, err := robustio.GetFileID(symlink)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"can't get ID of symbolic link: %v\", err)\n\t\t}\n\t\tif realID != symlinkID {\n\t\t\tt.Errorf(\"realID %+v != symlinkID %+v\", realID, symlinkID)\n\t\t}\n\t\tif !realMtime.Equal(symlinkMtime) {\n\t\t\tt.Errorf(\"realMtime %v != symlinkMtime %v\", realMtime, symlinkMtime)\n\t\t}\n\t})\n\n\t// Two hard-linked files have the same ID.\n\tt.Run(\"hardlink\", func(t *testing.T) {\n\t\thardlink := filepath.Join(t.TempDir(), \"hardlink\")\n\t\tcheckOSLink(t, os.Link(real, hardlink))\n\n\t\thardlinkID, hardlinkMtime, err := robustio.GetFileID(hardlink)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"can't get ID of hard link: %v\", err)\n\t\t}\n\t\tif realID != hardlinkID {\n\t\t\tt.Errorf(\"realID %+v != hardlinkID %+v\", realID, hardlinkID)\n\t\t}\n\t\tif !realMtime.Equal(hardlinkMtime) {\n\t\t\tt.Errorf(\"realMtime %v != hardlinkMtime %v\", realMtime, hardlinkMtime)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "internal/robustio/robustio_windows.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage robustio\n\nimport (\n\t\"errors\"\n\t\"syscall\"\n\t\"time\"\n)\n\nconst errFileNotFound = syscall.ERROR_FILE_NOT_FOUND\n\n// isEphemeralError returns true if err may be resolved by waiting.\nfunc isEphemeralError(err error) bool {\n\tvar errno syscall.Errno\n\tif errors.As(err, &errno) {\n\t\tswitch errno {\n\t\tcase syscall.ERROR_ACCESS_DENIED,\n\t\t\tsyscall.ERROR_FILE_NOT_FOUND,\n\t\t\tERROR_SHARING_VIOLATION:\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Note: it may be convenient to have this helper return fs.FileInfo, but\n// implementing this is actually quite involved on Windows. Since we only\n// currently use mtime, keep it simple.\nfunc getFileID(filename string) (FileID, time.Time, error) {\n\tfilename16, err := syscall.UTF16PtrFromString(filename)\n\tif err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\th, err := syscall.CreateFile(filename16, 0, 0, nil, syscall.OPEN_EXISTING, uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS), 0)\n\tif err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\tdefer syscall.CloseHandle(h)\n\tvar i syscall.ByHandleFileInformation\n\tif err := syscall.GetFileInformationByHandle(h, &i); err != nil {\n\t\treturn FileID{}, time.Time{}, err\n\t}\n\tmtime := time.Unix(0, i.LastWriteTime.Nanoseconds())\n\treturn FileID{\n\t\tdevice: uint64(i.VolumeSerialNumber),\n\t\tinode:  uint64(i.FileIndexHigh)<<32 | uint64(i.FileIndexLow),\n\t}, mtime, nil\n}\n"
  },
  {
    "path": "internal/stdlib/deps.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage stdlib\n\ntype pkginfo struct {\n\tname string\n\tdeps string // list of indices of dependencies, as varint-encoded deltas\n}\n\nvar deps = [...]pkginfo{\n\t{\"archive/tar\", \"\\x03q\\x03F=\\x01\\n\\x01$\\x01\\x01\\x02\\x05\\b\\x02\\x01\\x02\\x02\\r\"},\n\t{\"archive/zip\", \"\\x02\\x04g\\a\\x03\\x13\\x021=\\x01+\\x05\\x01\\x0f\\x03\\x02\\x0f\\x04\"},\n\t{\"bufio\", \"\\x03q\\x86\\x01D\\x15\"},\n\t{\"bytes\", \"t+[\\x03\\fH\\x02\\x02\"},\n\t{\"cmp\", \"\"},\n\t{\"compress/bzip2\", \"\\x02\\x02\\xf6\\x01A\"},\n\t{\"compress/flate\", \"\\x02r\\x03\\x83\\x01\\f\\x033\\x01\\x03\"},\n\t{\"compress/gzip\", \"\\x02\\x04g\\a\\x03\\x15nU\"},\n\t{\"compress/lzw\", \"\\x02r\\x03\\x83\\x01\"},\n\t{\"compress/zlib\", \"\\x02\\x04g\\a\\x03\\x13\\x01o\"},\n\t{\"container/heap\", \"\\xbc\\x02\"},\n\t{\"container/list\", \"\"},\n\t{\"container/ring\", \"\"},\n\t{\"context\", \"t\\\\p\\x01\\x0e\"},\n\t{\"crypto\", \"\\x8a\\x01pC\"},\n\t{\"crypto/aes\", \"\\x10\\v\\t\\x99\\x02\"},\n\t{\"crypto/cipher\", \"\\x03!\\x01\\x01 \\x12\\x1c,Z\"},\n\t{\"crypto/des\", \"\\x10\\x16 .,\\x9d\\x01\\x03\"},\n\t{\"crypto/dsa\", \"F\\x03+\\x86\\x01\\r\"},\n\t{\"crypto/ecdh\", \"\\x03\\v\\r\\x10\\x04\\x17\\x03\\x0f\\x1c\\x86\\x01\"},\n\t{\"crypto/ecdsa\", \"\\x0e\\x05\\x03\\x05\\x01\\x10\\b\\v\\x06\\x01\\x03\\x0e\\x01\\x1c\\x86\\x01\\r\\x05L\\x01\"},\n\t{\"crypto/ed25519\", \"\\x0e\\x1f\\x12\\a\\x03\\b\\a\\x1cI=C\"},\n\t{\"crypto/elliptic\", \"4@\\x86\\x01\\r9\"},\n\t{\"crypto/fips140\", \"#\\x05\\x95\\x01\\x98\\x01\"},\n\t{\"crypto/hkdf\", \"0\\x15\\x01.\\x16\"},\n\t{\"crypto/hmac\", \"\\x1b\\x16\\x14\\x01\\x122\"},\n\t{\"crypto/hpke\", \"\\x03\\v\\x02\\x03\\x04\\x01\\f\\x01\\x05\\x1f\\x05\\a\\x01\\x01\\x1d\\x03\\x13\\x16\\x9b\\x01\\x1c\"},\n\t{\"crypto/internal/boring\", \"\\x0e\\x02\\x0el\"},\n\t{\"crypto/internal/boring/bbig\", \"\\x1b\\xec\\x01N\"},\n\t{\"crypto/internal/boring/bcache\", \"\\xc1\\x02\\x14\"},\n\t{\"crypto/internal/boring/sig\", \"\"},\n\t{\"crypto/internal/constanttime\", \"\"},\n\t{\"crypto/internal/cryptotest\", \"\\x03\\r\\v\\b%\\x10\\x19\\x06\\x13\\x12 \\x04\\x06\\t\\x19\\x01\\x11\\x11\\x1b\\x01\\a\\x05\\b\\x03\\x05\\f\"},\n\t{\"crypto/internal/entropy\", \"K\"},\n\t{\"crypto/internal/entropy/v1.0.0\", \"D0\\x95\\x018\\x14\"},\n\t{\"crypto/internal/fips140\", \"C1\\xbf\\x01\\v\\x17\"},\n\t{\"crypto/internal/fips140/aes\", \"\\x03 \\x03\\x02\\x14\\x05\\x01\\x01\\x05,\\x95\\x014\"},\n\t{\"crypto/internal/fips140/aes/gcm\", \"#\\x01\\x02\\x02\\x02\\x12\\x05\\x01\\x06,\\x92\\x01\"},\n\t{\"crypto/internal/fips140/alias\", \"\\xd5\\x02\"},\n\t{\"crypto/internal/fips140/bigmod\", \"(\\x19\\x01\\x06,\\x95\\x01\"},\n\t{\"crypto/internal/fips140/check\", \"#\\x0e\\a\\t\\x02\\xb7\\x01[\"},\n\t{\"crypto/internal/fips140/check/checktest\", \"(\\x8b\\x02\\\"\"},\n\t{\"crypto/internal/fips140/drbg\", \"\\x03\\x1f\\x01\\x01\\x04\\x14\\x05\\n)\\x86\\x01\\x0f7\\x01\"},\n\t{\"crypto/internal/fips140/ecdh\", \"\\x03 \\x05\\x02\\n\\r3\\x86\\x01\\x0f7\"},\n\t{\"crypto/internal/fips140/ecdsa\", \"\\x03 \\x04\\x01\\x02\\a\\x03\\x06:\\x16pF\"},\n\t{\"crypto/internal/fips140/ed25519\", \"\\x03 \\x05\\x02\\x04\\f:\\xc9\\x01\\x03\"},\n\t{\"crypto/internal/fips140/edwards25519\", \"\\x1f\\t\\a\\x123\\x95\\x017\"},\n\t{\"crypto/internal/fips140/edwards25519/field\", \"(\\x14\\x053\\x95\\x01\"},\n\t{\"crypto/internal/fips140/hkdf\", \"\\x03 \\x05\\t\\a<\\x16\"},\n\t{\"crypto/internal/fips140/hmac\", \"\\x03 \\x15\\x01\\x01:\\x16\"},\n\t{\"crypto/internal/fips140/mldsa\", \"\\x03\\x1c\\x04\\x05\\x02\\x0e\\x01\\x03\\x053\\x95\\x017\"},\n\t{\"crypto/internal/fips140/mlkem\", \"\\x03 \\x05\\x02\\x0f\\x03\\x053\\xcc\\x01\"},\n\t{\"crypto/internal/fips140/nistec\", \"\\x1f\\t\\r\\f3\\x95\\x01*\\r\\x15\"},\n\t{\"crypto/internal/fips140/nistec/fiat\", \"(\\x148\\x95\\x01\"},\n\t{\"crypto/internal/fips140/pbkdf2\", \"\\x03 \\x05\\t\\a<\\x16\"},\n\t{\"crypto/internal/fips140/rsa\", \"\\x03\\x1c\\x04\\x04\\x01\\x02\\x0e\\x01\\x01\\x028\\x16pF\"},\n\t{\"crypto/internal/fips140/sha256\", \"\\x03 \\x1e\\x01\\x06,\\x16\\x7f\"},\n\t{\"crypto/internal/fips140/sha3\", \"\\x03 \\x19\\x05\\x012\\x95\\x01L\"},\n\t{\"crypto/internal/fips140/sha512\", \"\\x03 \\x1e\\x01\\x06,\\x16\\x7f\"},\n\t{\"crypto/internal/fips140/ssh\", \"(b\"},\n\t{\"crypto/internal/fips140/subtle\", \"\\x1f\\a\\x1b\\xc8\\x01\"},\n\t{\"crypto/internal/fips140/tls12\", \"\\x03 \\x05\\t\\a\\x02:\\x16\"},\n\t{\"crypto/internal/fips140/tls13\", \"\\x03 \\x05\\b\\b\\t3\\x16\"},\n\t{\"crypto/internal/fips140cache\", \"\\xb3\\x02\\r'\"},\n\t{\"crypto/internal/fips140deps\", \"\"},\n\t{\"crypto/internal/fips140deps/byteorder\", \"\\xa0\\x01\"},\n\t{\"crypto/internal/fips140deps/cpu\", \"\\xb5\\x01\\a\"},\n\t{\"crypto/internal/fips140deps/godebug\", \"\\xbd\\x01\"},\n\t{\"crypto/internal/fips140deps/time\", \"\\xcf\\x02\"},\n\t{\"crypto/internal/fips140hash\", \"9\\x1d4\\xcb\\x01\"},\n\t{\"crypto/internal/fips140only\", \"\\x17\\x13\\x0e\\x01\\x01Pp\"},\n\t{\"crypto/internal/fips140test\", \"\"},\n\t{\"crypto/internal/impl\", \"\\xbe\\x02\"},\n\t{\"crypto/internal/rand\", \"\\x1b\\x0f s=[\"},\n\t{\"crypto/internal/randutil\", \"\\xfa\\x01\\x12\"},\n\t{\"crypto/internal/sysrand\", \"tq! \\r\\r\\x01\\x01\\r\\x06\"},\n\t{\"crypto/internal/sysrand/internal/seccomp\", \"t\"},\n\t{\"crypto/md5\", \"\\x0e8.\\x16\\x16i\"},\n\t{\"crypto/mlkem\", \"\\x0e%\"},\n\t{\"crypto/mlkem/mlkemtest\", \"3\\x13\\b&\"},\n\t{\"crypto/pbkdf2\", \"6\\x0f\\x01.\\x16\"},\n\t{\"crypto/rand\", \"\\x1b\\x0f\\x1c\\x03+\\x86\\x01\\rN\"},\n\t{\"crypto/rc4\", \"& .\\xc9\\x01\"},\n\t{\"crypto/rsa\", \"\\x0e\\r\\x01\\v\\x10\\x0e\\x01\\x03\\b\\a\\x1c\\x03\\x133=\\f\\x01\"},\n\t{\"crypto/sha1\", \"\\x0e\\r+\\x02,\\x16\\x16\\x15T\"},\n\t{\"crypto/sha256\", \"\\x0e\\r\\x1dR\"},\n\t{\"crypto/sha3\", \"\\x0e+Q\\xcb\\x01\"},\n\t{\"crypto/sha512\", \"\\x0e\\r\\x1fP\"},\n\t{\"crypto/subtle\", \"\\x1f\\x1d\\x9f\\x01z\"},\n\t{\"crypto/tls\", \"\\x03\\b\\x02\\x01\\x01\\x01\\x01\\x02\\x01\\x01\\x01\\x02\\x01\\x01\\x01\\t\\x01\\x18\\x01\\x0f\\x01\\x03\\x01\\x01\\x01\\x01\\x02\\x01\\x02\\x01\\x17\\x02\\x03\\x13\\x16\\x15\\b=\\x16\\x16\\r\\b\\x01\\x01\\x01\\x02\\x01\\x0e\\x06\\x02\\x01\\x0f\"},\n\t{\"crypto/tls/internal/fips140tls\", \"\\x17\\xaa\\x02\"},\n\t{\"crypto/x509\", \"\\x03\\v\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x017\\x06\\x01\\x01\\x02\\x05\\x0e\\x06\\x02\\x02\\x03F\\x03:\\x01\\x02\\b\\x01\\x01\\x02\\a\\x10\\x05\\x01\\x06\\a\\b\\x02\\x01\\x02\\x0f\\x02\\x01\\x01\\x02\\x03\\x01\"},\n\t{\"crypto/x509/pkix\", \"j\\x06\\a\\x90\\x01H\"},\n\t{\"database/sql\", \"\\x03\\nQ\\x16\\x03\\x83\\x01\\v\\a\\\"\\x05\\b\\x02\\x03\\x01\\x0e\\x02\\x02\\x02\"},\n\t{\"database/sql/driver\", \"\\rg\\x03\\xb7\\x01\\x0f\\x12\"},\n\t{\"debug/buildinfo\", \"\\x03^\\x02\\x01\\x01\\b\\a\\x03g\\x1a\\x02\\x01+\\x0f \"},\n\t{\"debug/dwarf\", \"\\x03j\\a\\x03\\x83\\x011\\x11\\x01\\x01\"},\n\t{\"debug/elf\", \"\\x03\\x06W\\r\\a\\x03g\\x1b\\x01\\f \\x17\\x01\\x17\"},\n\t{\"debug/gosym\", \"\\x03j\\n$\\xa1\\x01\\x01\\x01\\x02\"},\n\t{\"debug/macho\", \"\\x03\\x06W\\r\\ng\\x1c,\\x17\\x01\"},\n\t{\"debug/pe\", \"\\x03\\x06W\\r\\a\\x03g\\x1c,\\x17\\x01\\x17\"},\n\t{\"debug/plan9obj\", \"m\\a\\x03g\\x1c,\"},\n\t{\"embed\", \"t+B\\x19\\x01T\"},\n\t{\"embed/internal/embedtest\", \"\"},\n\t{\"encoding\", \"\"},\n\t{\"encoding/ascii85\", \"\\xfa\\x01C\"},\n\t{\"encoding/asn1\", \"\\x03q\\x03g(\\x01'\\r\\x02\\x01\\x11\\x03\\x01\"},\n\t{\"encoding/base32\", \"\\xfa\\x01A\\x02\"},\n\t{\"encoding/base64\", \"\\xa0\\x01ZA\\x02\"},\n\t{\"encoding/binary\", \"t\\x86\\x01\\f(\\r\\x05\"},\n\t{\"encoding/csv\", \"\\x02\\x01q\\x03\\x83\\x01D\\x13\\x02\"},\n\t{\"encoding/gob\", \"\\x02f\\x05\\a\\x03g\\x1c\\v\\x01\\x03\\x1d\\b\\x12\\x01\\x10\\x02\"},\n\t{\"encoding/hex\", \"t\\x03\\x83\\x01A\\x03\"},\n\t{\"encoding/json\", \"\\x03\\x01d\\x04\\b\\x03\\x83\\x01\\f(\\r\\x02\\x01\\x02\\x11\\x01\\x01\\x02\"},\n\t{\"encoding/pem\", \"\\x03i\\b\\x86\\x01A\\x03\"},\n\t{\"encoding/xml\", \"\\x02\\x01e\\f\\x03\\x83\\x014\\x05\\n\\x01\\x02\\x11\\x02\"},\n\t{\"errors\", \"\\xd0\\x01\\x85\\x01\"},\n\t{\"expvar\", \"qLA\\b\\v\\x15\\r\\b\\x02\\x03\\x01\\x12\"},\n\t{\"flag\", \"h\\f\\x03\\x83\\x01,\\b\\x05\\b\\x02\\x01\\x11\"},\n\t{\"fmt\", \"tF'\\x19\\f \\b\\r\\x02\\x03\\x13\"},\n\t{\"go/ast\", \"\\x03\\x01s\\x0f\\x01s\\x03)\\b\\r\\x02\\x01\\x13\\x02\"},\n\t{\"go/build\", \"\\x02\\x01q\\x03\\x01\\x02\\x02\\b\\x02\\x01\\x17\\x1f\\x04\\x02\\b\\x1c\\x13\\x01+\\x01\\x04\\x01\\a\\b\\x02\\x01\\x13\\x02\\x02\"},\n\t{\"go/build/constraint\", \"t\\xc9\\x01\\x01\\x13\\x02\"},\n\t{\"go/constant\", \"w\\x10\\x7f\\x01\\x024\\x01\\x02\\x13\"},\n\t{\"go/doc\", \"\\x04s\\x01\\x05\\n=61\\x10\\x02\\x01\\x13\\x02\"},\n\t{\"go/doc/comment\", \"\\x03t\\xc4\\x01\\x01\\x01\\x01\\x13\\x02\"},\n\t{\"go/format\", \"\\x03t\\x01\\f\\x01\\x02sD\"},\n\t{\"go/importer\", \"y\\a\\x01\\x02\\x04\\x01r9\"},\n\t{\"go/internal/gccgoimporter\", \"\\x02\\x01^\\x13\\x03\\x04\\f\\x01p\\x02,\\x01\\x05\\x11\\x01\\r\\b\"},\n\t{\"go/internal/gcimporter\", \"\\x02u\\x10\\x010\\x05\\r0,\\x15\\x03\\x02\"},\n\t{\"go/internal/scannerhooks\", \"\\x87\\x01\"},\n\t{\"go/internal/srcimporter\", \"w\\x01\\x01\\v\\x03\\x01r,\\x01\\x05\\x12\\x02\\x15\"},\n\t{\"go/parser\", \"\\x03q\\x03\\x01\\x02\\b\\x04\\x01s\\x01+\\x06\\x12\"},\n\t{\"go/printer\", \"w\\x01\\x02\\x03\\ns\\f \\x15\\x02\\x01\\x02\\f\\x05\\x02\"},\n\t{\"go/scanner\", \"\\x03t\\v\\x05s2\\x10\\x01\\x14\\x02\"},\n\t{\"go/token\", \"\\x04s\\x86\\x01>\\x02\\x03\\x01\\x10\\x02\"},\n\t{\"go/types\", \"\\x03\\x01\\x06j\\x03\\x01\\x03\\t\\x03\\x024\\x063\\x04\\x03\\t \\x06\\a\\b\\x01\\x01\\x01\\x02\\x01\\x10\\x02\\x02\"},\n\t{\"go/version\", \"\\xc2\\x01|\"},\n\t{\"hash\", \"\\xfa\\x01\"},\n\t{\"hash/adler32\", \"t\\x16\\x16\"},\n\t{\"hash/crc32\", \"t\\x16\\x16\\x15\\x8b\\x01\\x01\\x14\"},\n\t{\"hash/crc64\", \"t\\x16\\x16\\xa0\\x01\"},\n\t{\"hash/fnv\", \"t\\x16\\x16i\"},\n\t{\"hash/maphash\", \"\\x8a\\x01\\x11<~\"},\n\t{\"html\", \"\\xbe\\x02\\x02\\x13\"},\n\t{\"html/template\", \"\\x03n\\x06\\x19-=\\x01\\n!\\x05\\x01\\x02\\x03\\f\\x01\\x02\\r\\x01\\x03\\x02\"},\n\t{\"image\", \"\\x02r\\x1fg\\x0f4\\x03\\x01\"},\n\t{\"image/color\", \"\"},\n\t{\"image/color/palette\", \"\\x93\\x01\"},\n\t{\"image/draw\", \"\\x92\\x01\\x01\\x04\"},\n\t{\"image/gif\", \"\\x02\\x01\\x05l\\x03\\x1b\\x01\\x01\\x01\\vZ\\x0f\"},\n\t{\"image/internal/imageutil\", \"\\x92\\x01\"},\n\t{\"image/jpeg\", \"\\x02r\\x1e\\x01\\x04c\"},\n\t{\"image/png\", \"\\x02\\ad\\n\\x13\\x02\\x06\\x01gC\"},\n\t{\"index/suffixarray\", \"\\x03j\\a\\x86\\x01\\f+\\n\\x01\"},\n\t{\"internal/abi\", \"\\xbc\\x01\\x99\\x01\"},\n\t{\"internal/asan\", \"\\xd5\\x02\"},\n\t{\"internal/bisect\", \"\\xb3\\x02\\r\\x01\"},\n\t{\"internal/buildcfg\", \"wHg\\x06\\x02\\x05\\n\\x01\"},\n\t{\"internal/bytealg\", \"\\xb5\\x01\\xa0\\x01\"},\n\t{\"internal/byteorder\", \"\"},\n\t{\"internal/cfg\", \"\"},\n\t{\"internal/cgrouptest\", \"w[T\\x06\\x0f\\x02\\x01\\x04\\x01\"},\n\t{\"internal/chacha8rand\", \"\\xa0\\x01\\x15\\a\\x99\\x01\"},\n\t{\"internal/copyright\", \"\"},\n\t{\"internal/coverage\", \"\"},\n\t{\"internal/coverage/calloc\", \"\"},\n\t{\"internal/coverage/cfile\", \"q\\x06\\x17\\x17\\x01\\x02\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\\"\\x02',\\x06\\a\\n\\x01\\x03\\x0e\\x06\"},\n\t{\"internal/coverage/cformat\", \"\\x04s.\\x04Q\\v6\\x01\\x02\\x0e\"},\n\t{\"internal/coverage/cmerge\", \"w.a\"},\n\t{\"internal/coverage/decodecounter\", \"m\\n.\\v\\x02H,\\x17\\x18\"},\n\t{\"internal/coverage/decodemeta\", \"\\x02k\\n\\x17\\x17\\v\\x02H,\"},\n\t{\"internal/coverage/encodecounter\", \"\\x02k\\n.\\f\\x01\\x02F\\v!\\x15\"},\n\t{\"internal/coverage/encodemeta\", \"\\x02\\x01j\\n\\x13\\x04\\x17\\r\\x02F,/\"},\n\t{\"internal/coverage/pods\", \"\\x04s.\\x81\\x01\\x06\\x05\\n\\x02\\x01\"},\n\t{\"internal/coverage/rtcov\", \"\\xd5\\x02\"},\n\t{\"internal/coverage/slicereader\", \"m\\n\\x83\\x01[\"},\n\t{\"internal/coverage/slicewriter\", \"w\\x83\\x01\"},\n\t{\"internal/coverage/stringtab\", \"w9\\x04F\"},\n\t{\"internal/coverage/test\", \"\"},\n\t{\"internal/coverage/uleb128\", \"\"},\n\t{\"internal/cpu\", \"\\xd5\\x02\"},\n\t{\"internal/dag\", \"\\x04s\\xc4\\x01\\x03\"},\n\t{\"internal/diff\", \"\\x03t\\xc5\\x01\\x02\"},\n\t{\"internal/exportdata\", \"\\x02\\x01q\\x03\\x02e\\x1c,\\x01\\x05\\x11\\x01\\x02\"},\n\t{\"internal/filepathlite\", \"t+B\\x1a@\"},\n\t{\"internal/fmtsort\", \"\\x04\\xaa\\x02\\r\"},\n\t{\"internal/fuzz\", \"\\x03\\nH\\x18\\x04\\x03\\x03\\x01\\f\\x036=\\f\\x03\\x1d\\x01\\x05\\x02\\x05\\n\\x01\\x02\\x01\\x01\\r\\x04\\x02\"},\n\t{\"internal/goarch\", \"\"},\n\t{\"internal/godebug\", \"\\x9d\\x01!\\x82\\x01\\x01\\x14\"},\n\t{\"internal/godebugs\", \"\"},\n\t{\"internal/goexperiment\", \"\"},\n\t{\"internal/goos\", \"\"},\n\t{\"internal/goroot\", \"\\xa6\\x02\\x01\\x05\\x12\\x02\"},\n\t{\"internal/gover\", \"\\x04\"},\n\t{\"internal/goversion\", \"\"},\n\t{\"internal/lazyregexp\", \"\\xa6\\x02\\v\\r\\x02\"},\n\t{\"internal/lazytemplate\", \"\\xfa\\x01,\\x18\\x02\\r\"},\n\t{\"internal/msan\", \"\\xd5\\x02\"},\n\t{\"internal/nettrace\", \"\"},\n\t{\"internal/obscuretestdata\", \"l\\x8e\\x01,\"},\n\t{\"internal/oserror\", \"t\"},\n\t{\"internal/pkgbits\", \"\\x03R\\x18\\a\\x03\\x04\\fs\\r\\x1f\\r\\n\\x01\"},\n\t{\"internal/platform\", \"\"},\n\t{\"internal/poll\", \"tl\\x05\\x159\\r\\x01\\x01\\r\\x06\"},\n\t{\"internal/profile\", \"\\x03\\x04m\\x03\\x83\\x017\\n\\x01\\x01\\x01\\x11\"},\n\t{\"internal/profilerecord\", \"\"},\n\t{\"internal/race\", \"\\x9b\\x01\\xba\\x01\"},\n\t{\"internal/reflectlite\", \"\\x9b\\x01!;<\\\"\"},\n\t{\"internal/runtime/atomic\", \"\\xbc\\x01\\x99\\x01\"},\n\t{\"internal/runtime/cgroup\", \"\\x9f\\x01=\\x04u\"},\n\t{\"internal/runtime/exithook\", \"\\xd1\\x01\\x84\\x01\"},\n\t{\"internal/runtime/gc\", \"\\xbc\\x01\"},\n\t{\"internal/runtime/gc/internal/gen\", \"\\nc\\n\\x18k\\x04\\v\\x1d\\b\\x10\\x02\"},\n\t{\"internal/runtime/gc/scan\", \"\\xb5\\x01\\a\\x18\\az\"},\n\t{\"internal/runtime/maps\", \"\\x9b\\x01\\x01 \\n\\t\\t\\x03z\"},\n\t{\"internal/runtime/math\", \"\\xbc\\x01\"},\n\t{\"internal/runtime/pprof/label\", \"\"},\n\t{\"internal/runtime/startlinetest\", \"\"},\n\t{\"internal/runtime/sys\", \"\\xbc\\x01\\x04\"},\n\t{\"internal/runtime/syscall/linux\", \"\\xbc\\x01\\x99\\x01\"},\n\t{\"internal/runtime/wasitest\", \"\"},\n\t{\"internal/saferio\", \"\\xfa\\x01[\"},\n\t{\"internal/singleflight\", \"\\xc0\\x02\"},\n\t{\"internal/strconv\", \"\\x89\\x02L\"},\n\t{\"internal/stringslite\", \"\\x9f\\x01\\xb6\\x01\"},\n\t{\"internal/sync\", \"\\x9b\\x01!\\x13r\\x14\"},\n\t{\"internal/synctest\", \"\\x9b\\x01\\xba\\x01\"},\n\t{\"internal/syscall/execenv\", \"\\xc2\\x02\"},\n\t{\"internal/syscall/unix\", \"\\xb3\\x02\\x0e\\x01\\x13\"},\n\t{\"internal/sysinfo\", \"\\x02\\x01\\xb2\\x01E,\\x18\\x02\"},\n\t{\"internal/syslist\", \"\"},\n\t{\"internal/testenv\", \"\\x03\\ng\\x02\\x01*\\x1b\\x0f0+\\x01\\x05\\a\\n\\x01\\x02\\x02\\x01\\f\"},\n\t{\"internal/testhash\", \"\\x03\\x87\\x01p\\x118\\f\"},\n\t{\"internal/testlog\", \"\\xc0\\x02\\x01\\x14\"},\n\t{\"internal/testpty\", \"t\\x03\\xaf\\x01\"},\n\t{\"internal/trace\", \"\\x02\\x01\\x01\\x06c\\a\\x03w\\x03\\x03\\x06\\x03\\t+\\n\\x01\\x01\\x01\\x11\\x06\"},\n\t{\"internal/trace/internal/testgen\", \"\\x03j\\nu\\x03\\x02\\x03\\x011\\v\\r\\x11\"},\n\t{\"internal/trace/internal/tracev1\", \"\\x03\\x01i\\a\\x03}\\x06\\f5\\x01\"},\n\t{\"internal/trace/raw\", \"\\x02k\\nz\\x03\\x06C\\x01\\x13\"},\n\t{\"internal/trace/testtrace\", \"\\x02\\x01q\\x03q\\x04\\x03\\x05\\x01\\x05,\\v\\x02\\b\\x02\\x01\\x05\"},\n\t{\"internal/trace/tracev2\", \"\"},\n\t{\"internal/trace/traceviewer\", \"\\x02d\\v\\x06\\x1a<\\x1f\\a\\a\\x04\\b\\v\\x15\\x01\\x05\\a\\n\\x01\\x02\\x0f\"},\n\t{\"internal/trace/traceviewer/format\", \"\"},\n\t{\"internal/trace/version\", \"wz\\t\"},\n\t{\"internal/txtar\", \"\\x03t\\xaf\\x01\\x18\"},\n\t{\"internal/types/errors\", \"\\xbd\\x02\"},\n\t{\"internal/unsafeheader\", \"\\xd5\\x02\"},\n\t{\"internal/xcoff\", \"`\\r\\a\\x03g\\x1c,\\x17\\x01\"},\n\t{\"internal/zstd\", \"m\\a\\x03\\x83\\x01\\x0f\"},\n\t{\"io\", \"t\\xcc\\x01\"},\n\t{\"io/fs\", \"t+*11\\x10\\x14\\x04\"},\n\t{\"io/ioutil\", \"\\xfa\\x01\\x01+\\x15\\x03\"},\n\t{\"iter\", \"\\xcf\\x01d\\\"\"},\n\t{\"log\", \"w\\x83\\x01\\x05'\\r\\r\\x01\\x0e\"},\n\t{\"log/internal\", \"\"},\n\t{\"log/slog\", \"\\x03\\n[\\t\\x03\\x03\\x83\\x01\\x04\\x01\\x02\\x02\\x03(\\x05\\b\\x02\\x01\\x02\\x01\\x0e\\x02\\x02\\x02\"},\n\t{\"log/slog/internal\", \"\"},\n\t{\"log/slog/internal/benchmarks\", \"\\rg\\x03\\x83\\x01\\x06\\x03:\\x12\"},\n\t{\"log/slog/internal/buffer\", \"\\xc0\\x02\"},\n\t{\"log/syslog\", \"t\\x03\\x87\\x01\\x12\\x16\\x18\\x02\\x0f\"},\n\t{\"maps\", \"\\xfd\\x01X\"},\n\t{\"math\", \"\\xb5\\x01TL\"},\n\t{\"math/big\", \"\\x03q\\x03)\\x15E\\f\\x03\\x020\\x02\\x01\\x02\\x15\"},\n\t{\"math/big/internal/asmgen\", \"\\x03\\x01s\\x92\\x012\\x03\"},\n\t{\"math/bits\", \"\\xd5\\x02\"},\n\t{\"math/cmplx\", \"\\x86\\x02\\x03\"},\n\t{\"math/rand\", \"\\xbd\\x01I:\\x01\\x14\"},\n\t{\"math/rand/v2\", \"t,\\x03c\\x03L\"},\n\t{\"mime\", \"\\x02\\x01i\\b\\x03\\x83\\x01\\v!\\x15\\x03\\x02\\x11\\x02\"},\n\t{\"mime/multipart\", \"\\x02\\x01N#\\x03F=\\v\\x01\\a\\x02\\x15\\x02\\x06\\x0f\\x02\\x01\\x17\"},\n\t{\"mime/quotedprintable\", \"\\x02\\x01t\\x83\\x01\"},\n\t{\"net\", \"\\x04\\tg+\\x1e\\n\\x05\\x13\\x01\\x01\\x04\\x15\\x01%\\x06\\r\\b\\x05\\x01\\x01\\r\\x06\\a\"},\n\t{\"net/http\", \"\\x02\\x01\\x03\\x01\\x04\\x02D\\b\\x13\\x01\\a\\x03F=\\x01\\x03\\a\\x01\\x03\\x02\\x02\\x01\\x02\\x06\\x02\\x01\\x01\\n\\x01\\x01\\x05\\x01\\x02\\x05\\b\\x01\\x01\\x01\\x02\\x01\\x0e\\x02\\x02\\x02\\b\\x01\\x01\\x01\"},\n\t{\"net/http/cgi\", \"\\x02W\\x1b\\x03\\x83\\x01\\x04\\a\\v\\x01\\x13\\x01\\x01\\x01\\x04\\x01\\x05\\x02\\b\\x02\\x01\\x11\\x0e\"},\n\t{\"net/http/cookiejar\", \"\\x04p\\x03\\x99\\x01\\x01\\b\\a\\x05\\x16\\x03\\x02\\x0f\\x04\"},\n\t{\"net/http/fcgi\", \"\\x02\\x01\\n`\\a\\x03\\x83\\x01\\x16\\x01\\x01\\x14\\x18\\x02\\x0f\"},\n\t{\"net/http/httptest\", \"\\x02\\x01\\nL\\x02\\x1b\\x01\\x83\\x01\\x04\\x12\\x01\\n\\t\\x02\\x17\\x01\\x02\\x0f\\x0e\"},\n\t{\"net/http/httptrace\", \"\\rLnI\\x14\\n!\"},\n\t{\"net/http/httputil\", \"\\x02\\x01\\ng\\x03\\x83\\x01\\x04\\x0f\\x03\\x01\\x05\\x02\\x01\\v\\x01\\x19\\x02\\x01\\x0e\\x0e\"},\n\t{\"net/http/internal\", \"\\x02\\x01q\\x03\\x83\\x01\"},\n\t{\"net/http/internal/ascii\", \"\\xbe\\x02\\x13\"},\n\t{\"net/http/internal/httpcommon\", \"\\rg\\x03\\x9f\\x01\\x0e\\x01\\x17\\x01\\x01\\x02\\x1d\\x02\"},\n\t{\"net/http/internal/testcert\", \"\\xbe\\x02\"},\n\t{\"net/http/pprof\", \"\\x02\\x01\\nj\\x19-\\x02\\x0e-\\x04\\x13\\x14\\x01\\r\\x04\\x03\\x01\\x02\\x01\\x11\"},\n\t{\"net/internal/cgotest\", \"\"},\n\t{\"net/internal/socktest\", \"w\\xc9\\x01\\x02\"},\n\t{\"net/mail\", \"\\x02r\\x03\\x83\\x01\\x04\\x0f\\x03\\x14\\x1a\\x02\\x0f\\x04\"},\n\t{\"net/netip\", \"\\x04p+\\x01f\\x034\\x17\"},\n\t{\"net/rpc\", \"\\x02m\\x05\\x03\\x10\\ni\\x04\\x12\\x01\\x1d\\r\\x03\\x02\"},\n\t{\"net/rpc/jsonrpc\", \"q\\x03\\x03\\x83\\x01\\x16\\x11\\x1f\"},\n\t{\"net/smtp\", \"\\x194\\f\\x13\\b\\x03\\x83\\x01\\x16\\x14\\x1a\"},\n\t{\"net/textproto\", \"\\x02\\x01q\\x03\\x83\\x01\\f\\n-\\x01\\x02\\x15\"},\n\t{\"net/url\", \"t\\x03Fc\\v\\x10\\x02\\x01\\x17\"},\n\t{\"os\", \"t+\\x01\\x19\\x03\\x10\\x14\\x01\\x03\\x01\\x05\\x10\\x018\\b\\x05\\x01\\x01\\r\\x06\"},\n\t{\"os/exec\", \"\\x03\\ngI'\\x01\\x15\\x01+\\x06\\a\\n\\x01\\x03\\x01\\r\"},\n\t{\"os/exec/internal/fdtest\", \"\\xc2\\x02\"},\n\t{\"os/signal\", \"\\r\\x99\\x02\\x15\\x05\\x02\"},\n\t{\"os/user\", \"\\x02\\x01q\\x03\\x83\\x01,\\r\\n\\x01\\x02\"},\n\t{\"path\", \"t+\\xb4\\x01\"},\n\t{\"path/filepath\", \"t+\\x1aB+\\r\\b\\x03\\x04\\x11\"},\n\t{\"plugin\", \"t\"},\n\t{\"reflect\", \"t'\\x04\\x1d\\x13\\b\\x04\\x05\\x17\\x06\\t-\\n\\x03\\x11\\x02\\x02\"},\n\t{\"reflect/internal/example1\", \"\"},\n\t{\"reflect/internal/example2\", \"\"},\n\t{\"regexp\", \"\\x03\\xf7\\x018\\t\\x02\\x01\\x02\\x11\\x02\"},\n\t{\"regexp/syntax\", \"\\xbb\\x02\\x01\\x01\\x01\\x02\\x11\\x02\"},\n\t{\"runtime\", \"\\x9b\\x01\\x04\\x01\\x03\\f\\x06\\a\\x02\\x01\\x01\\x0e\\x03\\x01\\x01\\x01\\x02\\x01\\x01\\x01\\x02\\x01\\x04\\x01\\x10\\x18L\"},\n\t{\"runtime/coverage\", \"\\xa7\\x01S\"},\n\t{\"runtime/debug\", \"wUZ\\r\\b\\x02\\x01\\x11\\x06\"},\n\t{\"runtime/metrics\", \"\\xbe\\x01H-\\\"\"},\n\t{\"runtime/pprof\", \"\\x02\\x01\\x01\\x03\\x06`\\a\\x03$$\\x0f\\v!\\f \\r\\b\\x01\\x01\\x01\\x02\\x02\\n\\x03\\x06\"},\n\t{\"runtime/race\", \"\\xb9\\x02\"},\n\t{\"runtime/race/internal/amd64v1\", \"\"},\n\t{\"runtime/trace\", \"\\rg\\x03z\\t9\\b\\x05\\x01\\x0e\\x06\"},\n\t{\"slices\", \"\\x04\\xf9\\x01\\fL\"},\n\t{\"sort\", \"\\xd0\\x0192\"},\n\t{\"strconv\", \"t+A\\x01r\"},\n\t{\"strings\", \"t'\\x04B\\x19\\x03\\f7\\x11\\x02\\x02\"},\n\t{\"structs\", \"\"},\n\t{\"sync\", \"\\xcf\\x01\\x13\\x01P\\x0e\\x14\"},\n\t{\"sync/atomic\", \"\\xd5\\x02\"},\n\t{\"syscall\", \"t(\\x03\\x01\\x1c\\n\\x03\\x06\\r\\x04S\\b\\x05\\x01\\x14\"},\n\t{\"testing\", \"\\x03\\ng\\x02\\x01X\\x17\\x14\\f\\x05\\x1b\\x06\\x02\\x05\\x02\\x05\\x01\\x02\\x01\\x02\\x01\\x0e\\x02\\x04\"},\n\t{\"testing/cryptotest\", \"QOZ\\x124\\x03\\x12\"},\n\t{\"testing/fstest\", \"t\\x03\\x83\\x01\\x01\\n&\\x10\\x03\\t\\b\"},\n\t{\"testing/internal/testdeps\", \"\\x02\\v\\xae\\x01/\\x10,\\x03\\x05\\x03\\x06\\a\\x02\\x0f\"},\n\t{\"testing/iotest\", \"\\x03q\\x03\\x83\\x01\\x04\"},\n\t{\"testing/quick\", \"v\\x01\\x8f\\x01\\x05#\\x10\\x11\"},\n\t{\"testing/slogtest\", \"\\rg\\x03\\x89\\x01.\\x05\\x10\\f\"},\n\t{\"testing/synctest\", \"\\xe3\\x01`\\x12\"},\n\t{\"text/scanner\", \"\\x03t\\x83\\x01,+\\x02\"},\n\t{\"text/tabwriter\", \"w\\x83\\x01Y\"},\n\t{\"text/template\", \"t\\x03C@\\x01\\n \\x01\\x05\\x01\\x02\\x05\\v\\x02\\x0e\\x03\\x02\"},\n\t{\"text/template/parse\", \"\\x03t\\xbc\\x01\\n\\x01\\x13\\x02\"},\n\t{\"time\", \"t+\\x1e$(*\\r\\x02\\x13\"},\n\t{\"time/tzdata\", \"t\\xce\\x01\\x13\"},\n\t{\"unicode\", \"\"},\n\t{\"unicode/utf16\", \"\"},\n\t{\"unicode/utf8\", \"\"},\n\t{\"unique\", \"\\x9b\\x01!%\\x01Q\\r\\x01\\x14\\x12\"},\n\t{\"unsafe\", \"\"},\n\t{\"vendor/golang.org/x/crypto/chacha20\", \"\\x10]\\a\\x95\\x01*'\"},\n\t{\"vendor/golang.org/x/crypto/chacha20poly1305\", \"\\x10\\aV\\a\\xe2\\x01\\x04\\x01\\a\"},\n\t{\"vendor/golang.org/x/crypto/cryptobyte\", \"j\\n\\x03\\x90\\x01'!\\n\"},\n\t{\"vendor/golang.org/x/crypto/cryptobyte/asn1\", \"\"},\n\t{\"vendor/golang.org/x/crypto/internal/alias\", \"\\xd5\\x02\"},\n\t{\"vendor/golang.org/x/crypto/internal/poly1305\", \"X\\x15\\x9c\\x01\"},\n\t{\"vendor/golang.org/x/net/dns/dnsmessage\", \"t\\xc7\\x01\"},\n\t{\"vendor/golang.org/x/net/http/httpguts\", \"\\x90\\x02\\x14\\x1a\\x15\\r\"},\n\t{\"vendor/golang.org/x/net/http/httpproxy\", \"t\\x03\\x99\\x01\\x10\\x05\\x01\\x18\\x15\\r\"},\n\t{\"vendor/golang.org/x/net/http2/hpack\", \"\\x03q\\x03\\x83\\x01F\"},\n\t{\"vendor/golang.org/x/net/idna\", \"w\\x8f\\x018\\x15\\x10\\x02\\x01\"},\n\t{\"vendor/golang.org/x/net/nettest\", \"\\x03j\\a\\x03\\x83\\x01\\x11\\x05\\x16\\x01\\f\\n\\x01\\x02\\x02\\x01\\f\"},\n\t{\"vendor/golang.org/x/sys/cpu\", \"\\xa6\\x02\\r\\n\\x01\\x17\"},\n\t{\"vendor/golang.org/x/text/secure/bidirule\", \"t\\xdf\\x01\\x11\\x01\"},\n\t{\"vendor/golang.org/x/text/transform\", \"\\x03q\\x86\\x01Y\"},\n\t{\"vendor/golang.org/x/text/unicode/bidi\", \"\\x03\\bl\\x87\\x01>\\x17\"},\n\t{\"vendor/golang.org/x/text/unicode/norm\", \"m\\n\\x83\\x01F\\x13\\x11\"},\n\t{\"weak\", \"\\x9b\\x01\\x98\\x01\\\"\"},\n}\n\n// bootstrap is the list of bootstrap packages extracted from cmd/dist.\nvar bootstrap = map[string]bool{\n\t\"cmp\":                                     true,\n\t\"cmd/asm\":                                 true,\n\t\"cmd/asm/internal/arch\":                   true,\n\t\"cmd/asm/internal/asm\":                    true,\n\t\"cmd/asm/internal/flags\":                  true,\n\t\"cmd/asm/internal/lex\":                    true,\n\t\"cmd/cgo\":                                 true,\n\t\"cmd/compile\":                             true,\n\t\"cmd/compile/internal/abi\":                true,\n\t\"cmd/compile/internal/abt\":                true,\n\t\"cmd/compile/internal/amd64\":              true,\n\t\"cmd/compile/internal/arm\":                true,\n\t\"cmd/compile/internal/arm64\":              true,\n\t\"cmd/compile/internal/base\":               true,\n\t\"cmd/compile/internal/bitvec\":             true,\n\t\"cmd/compile/internal/bloop\":              true,\n\t\"cmd/compile/internal/compare\":            true,\n\t\"cmd/compile/internal/coverage\":           true,\n\t\"cmd/compile/internal/deadlocals\":         true,\n\t\"cmd/compile/internal/devirtualize\":       true,\n\t\"cmd/compile/internal/dwarfgen\":           true,\n\t\"cmd/compile/internal/escape\":             true,\n\t\"cmd/compile/internal/gc\":                 true,\n\t\"cmd/compile/internal/importer\":           true,\n\t\"cmd/compile/internal/inline\":             true,\n\t\"cmd/compile/internal/inline/inlheur\":     true,\n\t\"cmd/compile/internal/inline/interleaved\": true,\n\t\"cmd/compile/internal/ir\":                 true,\n\t\"cmd/compile/internal/liveness\":           true,\n\t\"cmd/compile/internal/logopt\":             true,\n\t\"cmd/compile/internal/loong64\":            true,\n\t\"cmd/compile/internal/loopvar\":            true,\n\t\"cmd/compile/internal/mips\":               true,\n\t\"cmd/compile/internal/mips64\":             true,\n\t\"cmd/compile/internal/noder\":              true,\n\t\"cmd/compile/internal/objw\":               true,\n\t\"cmd/compile/internal/pgoir\":              true,\n\t\"cmd/compile/internal/pkginit\":            true,\n\t\"cmd/compile/internal/ppc64\":              true,\n\t\"cmd/compile/internal/rangefunc\":          true,\n\t\"cmd/compile/internal/reflectdata\":        true,\n\t\"cmd/compile/internal/riscv64\":            true,\n\t\"cmd/compile/internal/rttype\":             true,\n\t\"cmd/compile/internal/s390x\":              true,\n\t\"cmd/compile/internal/slice\":              true,\n\t\"cmd/compile/internal/ssa\":                true,\n\t\"cmd/compile/internal/ssagen\":             true,\n\t\"cmd/compile/internal/staticdata\":         true,\n\t\"cmd/compile/internal/staticinit\":         true,\n\t\"cmd/compile/internal/syntax\":             true,\n\t\"cmd/compile/internal/test\":               true,\n\t\"cmd/compile/internal/typebits\":           true,\n\t\"cmd/compile/internal/typecheck\":          true,\n\t\"cmd/compile/internal/types\":              true,\n\t\"cmd/compile/internal/types2\":             true,\n\t\"cmd/compile/internal/walk\":               true,\n\t\"cmd/compile/internal/wasm\":               true,\n\t\"cmd/compile/internal/x86\":                true,\n\t\"cmd/internal/archive\":                    true,\n\t\"cmd/internal/bio\":                        true,\n\t\"cmd/internal/codesign\":                   true,\n\t\"cmd/internal/dwarf\":                      true,\n\t\"cmd/internal/edit\":                       true,\n\t\"cmd/internal/gcprog\":                     true,\n\t\"cmd/internal/goobj\":                      true,\n\t\"cmd/internal/hash\":                       true,\n\t\"cmd/internal/macho\":                      true,\n\t\"cmd/internal/obj\":                        true,\n\t\"cmd/internal/obj/arm\":                    true,\n\t\"cmd/internal/obj/arm64\":                  true,\n\t\"cmd/internal/obj/loong64\":                true,\n\t\"cmd/internal/obj/mips\":                   true,\n\t\"cmd/internal/obj/ppc64\":                  true,\n\t\"cmd/internal/obj/riscv\":                  true,\n\t\"cmd/internal/obj/s390x\":                  true,\n\t\"cmd/internal/obj/wasm\":                   true,\n\t\"cmd/internal/obj/x86\":                    true,\n\t\"cmd/internal/objabi\":                     true,\n\t\"cmd/internal/par\":                        true,\n\t\"cmd/internal/pgo\":                        true,\n\t\"cmd/internal/pkgpath\":                    true,\n\t\"cmd/internal/quoted\":                     true,\n\t\"cmd/internal/src\":                        true,\n\t\"cmd/internal/sys\":                        true,\n\t\"cmd/internal/telemetry\":                  true,\n\t\"cmd/internal/telemetry/counter\":          true,\n\t\"cmd/link\":                                true,\n\t\"cmd/link/internal/amd64\":                 true,\n\t\"cmd/link/internal/arm\":                   true,\n\t\"cmd/link/internal/arm64\":                 true,\n\t\"cmd/link/internal/benchmark\":             true,\n\t\"cmd/link/internal/dwtest\":                true,\n\t\"cmd/link/internal/ld\":                    true,\n\t\"cmd/link/internal/loadelf\":               true,\n\t\"cmd/link/internal/loader\":                true,\n\t\"cmd/link/internal/loadmacho\":             true,\n\t\"cmd/link/internal/loadpe\":                true,\n\t\"cmd/link/internal/loadxcoff\":             true,\n\t\"cmd/link/internal/loong64\":               true,\n\t\"cmd/link/internal/mips\":                  true,\n\t\"cmd/link/internal/mips64\":                true,\n\t\"cmd/link/internal/ppc64\":                 true,\n\t\"cmd/link/internal/riscv64\":               true,\n\t\"cmd/link/internal/s390x\":                 true,\n\t\"cmd/link/internal/sym\":                   true,\n\t\"cmd/link/internal/wasm\":                  true,\n\t\"cmd/link/internal/x86\":                   true,\n\t\"compress/flate\":                          true,\n\t\"compress/zlib\":                           true,\n\t\"container/heap\":                          true,\n\t\"debug/dwarf\":                             true,\n\t\"debug/elf\":                               true,\n\t\"debug/macho\":                             true,\n\t\"debug/pe\":                                true,\n\t\"go/build/constraint\":                     true,\n\t\"go/constant\":                             true,\n\t\"go/version\":                              true,\n\t\"internal/abi\":                            true,\n\t\"internal/coverage\":                       true,\n\t\"cmd/internal/cov/covcmd\":                 true,\n\t\"internal/bisect\":                         true,\n\t\"internal/buildcfg\":                       true,\n\t\"internal/exportdata\":                     true,\n\t\"internal/goarch\":                         true,\n\t\"internal/godebugs\":                       true,\n\t\"internal/goexperiment\":                   true,\n\t\"internal/goroot\":                         true,\n\t\"internal/gover\":                          true,\n\t\"internal/goversion\":                      true,\n\t\"internal/lazyregexp\":                     true,\n\t\"internal/pkgbits\":                        true,\n\t\"internal/platform\":                       true,\n\t\"internal/profile\":                        true,\n\t\"internal/race\":                           true,\n\t\"internal/runtime/gc\":                     true,\n\t\"internal/saferio\":                        true,\n\t\"internal/syscall/unix\":                   true,\n\t\"internal/types/errors\":                   true,\n\t\"internal/unsafeheader\":                   true,\n\t\"internal/xcoff\":                          true,\n\t\"internal/zstd\":                           true,\n\t\"math/bits\":                               true,\n\t\"sort\":                                    true,\n}\n\n// BootstrapVersion is the minor version of Go used during toolchain\n// bootstrapping. Packages for which [IsBootstrapPackage] must not use\n// features of Go newer than this version.\nconst BootstrapVersion = Version(24) // go1.24.6\n"
  },
  {
    "path": "internal/stdlib/deps_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stdlib_test\n\nimport (\n\t\"iter\"\n\t\"os\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/internal/stdlib\"\n)\n\nfunc TestImports(t *testing.T) { testDepsFunc(t, \"testdata/nethttp.imports\", stdlib.Imports) }\nfunc TestDeps(t *testing.T)    { testDepsFunc(t, \"testdata/nethttp.deps\", stdlib.Dependencies) }\n\n// testDepsFunc checks that the specified dependency function applied\n// to net/http returns the set of dependencies in the named file.\nfunc testDepsFunc(t *testing.T, filename string, depsFunc func(pkgs ...string) iter.Seq[string]) {\n\tdata, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := strings.Split(strings.TrimSpace(string(data)), \"\\n\")\n\tgot := slices.Collect(depsFunc(\"net/http\"))\n\tsort.Strings(want)\n\tsort.Strings(got)\n\tif diff := cmp.Diff(got, want); diff != \"\" {\n\t\tt.Fatalf(\"Deps mismatch (-want +got):\\n%s\", diff)\n\t}\n}\n\nfunc TestIsBootstrapPackage(t *testing.T) {\n\tfor pkg, want := range map[string]bool{\n\t\t\"cmd/internal/obj/arm64\":             true,\n\t\t\"sort\":                               true,\n\t\t\"encoding/json\":                      false,\n\t\t\"golang.org/x/tools/internal/stdlib\": false,\n\t\t\"\":                                   false,\n\t} {\n\t\tgot := stdlib.IsBootstrapPackage(pkg)\n\t\tif got != want {\n\t\t\tt.Errorf(\"IsBootstrapPackage(%q) = %t\", pkg, got)\n\t\t}\n\t}\n\n\tif stdlib.BootstrapVersion < 24 {\n\t\tt.Errorf(\"BootstrapVersion = %v, want at least go1.24\", stdlib.BootstrapVersion)\n\t}\n}\n"
  },
  {
    "path": "internal/stdlib/generate.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// The generate command reads all the GOROOT/api/go1.*.txt files and\n// generates a single combined manifest.go file containing the Go\n// standard library API symbols along with versions.\n//\n// It also runs \"go list -deps std\" and records the import graph. This\n// information may be used, for example, to ensure that tools don't\n// suggest fixes that import package P when analyzing one of P's\n// dependencies.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"encoding/binary\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io/fs\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/packages\"\n)\n\nfunc main() {\n\tlog.SetFlags(log.Lshortfile) // to identify the source of the log messages\n\n\tdir := apidir()\n\tmanifest(dir)\n\tdeps()\n}\n\n// -- generate std manifest --\n\nfunc manifest(apidir string) {\n\t// find the signatures\n\tcfg := packages.Config{\n\t\tMode: packages.LoadTypes,\n\t\tEnv:  append(os.Environ(), \"CGO_ENABLED=0\", \"GOOS=linux\", \"GOARCH=amd64\"),\n\t}\n\t// find the source. This is not totally reliable: different\n\t// systems may get different versions of unreleased APIs.\n\t// The result depends on the toolchain.\n\t// The x/tools release process regenerates the table\n\t// with the canonical toolchain.\n\tstdpkgs, err := packages.Load(&cfg, \"std\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tsignatures := make(map[string]map[string]string) // PkgPath->FuncName->signature\n\t// signatures start with func and may contain type parameters\n\t// \"func[T comparable](value T) unique.Handle[T]\"\n\tfor _, pkg := range stdpkgs {\n\t\tif strings.HasPrefix(pkg.PkgPath, \"vendor/\") ||\n\t\t\tstrings.HasPrefix(pkg.PkgPath, \"internal/\") ||\n\t\t\tstrings.Contains(pkg.PkgPath, \"/internal/\") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, name := range pkg.Types.Scope().Names() {\n\t\t\tfixer := func(p *types.Package) string {\n\t\t\t\t// fn.Signature() would have produced\n\t\t\t\t// \"func(fi io/fs.FileInfo, link string) (*archive/tar.Header, error)\"},\n\t\t\t\t// This produces\n\t\t\t\t// \"func FileInfoHeader(fi fs.FileInfo, link string) (*Header, error)\"\"\n\t\t\t\t// Note that the function name is superfluous, so it is removed below\n\t\t\t\tif p != pkg.Types {\n\t\t\t\t\treturn p.Name()\n\t\t\t\t}\n\t\t\t\treturn \"\"\n\t\t\t}\n\t\t\tobj := pkg.Types.Scope().Lookup(name)\n\t\t\tif fn, ok := obj.(*types.Func); ok {\n\t\t\t\tmp, ok := signatures[pkg.PkgPath]\n\t\t\t\tif !ok {\n\t\t\t\t\tmp = make(map[string]string)\n\t\t\t\t\tsignatures[pkg.PkgPath] = mp\n\t\t\t\t}\n\t\t\t\tsig := types.ObjectString(fn, fixer)\n\t\t\t\t// remove the space and function name introduced by fixer\n\t\t\t\tsig = strings.Replace(sig, \" \"+name, \"\", 1)\n\t\t\t\tmp[name] = sig\n\t\t\t}\n\t\t}\n\t}\n\n\t// read the api data\n\tpkgs := make(map[string]map[string]symInfo) // package -> symbol -> info\n\tsymRE := regexp.MustCompile(`^pkg (\\S+).*?, (var|func|type|const|method \\([^)]*\\)) ([\\pL\\p{Nd}_]+)(.*)`)\n\n\t// parse parses symbols out of GOROOT/api/*.txt data, with the specified minor version.\n\t// Errors are reported against filename.\n\tparse := func(filename string, data []byte, minor int) {\n\t\tfor linenum, line := range strings.Split(string(data), \"\\n\") {\n\t\t\tif line == \"\" || strings.HasPrefix(line, \"#\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tm := symRE.FindStringSubmatch(line)\n\t\t\tif m == nil {\n\t\t\t\tlog.Fatalf(\"invalid input: %s:%d: %s\", filename, linenum+1, line)\n\t\t\t}\n\t\t\tpath, kind, sym, rest := m[1], m[2], m[3], m[4]\n\n\t\t\tif _, recv, ok := strings.Cut(kind, \"method \"); ok {\n\t\t\t\t// e.g. \"method (*Func) Pos() token.Pos\"\n\t\t\t\tkind = \"method\" // (concrete)\n\n\t\t\t\trecv := removeTypeParam(recv) // (*Foo[T]) -> (*Foo)\n\n\t\t\t\tsym = recv + \".\" + sym // (*T).m\n\n\t\t\t} else if method, ok := strings.CutPrefix(rest, \" interface, \"); ok && kind == \"type\" {\n\t\t\t\t// e.g. \"pkg reflect, type Type interface, Comparable() bool\"\n\t\t\t\t// or   \"pkg net, type Error interface, Temporary //deprecated\"\n\n\t\t\t\tkind = \"method\" // (abstract)\n\n\t\t\t\tif strings.HasPrefix(method, \"unexported methods\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif strings.Contains(method, \" //deprecated\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tname, _, ok := strings.Cut(method, \"(\")\n\t\t\t\tif !ok {\n\t\t\t\t\tlog.Printf(\"unexpected: %s\", line)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsym = fmt.Sprintf(\"(%s).%s\", sym, name) // (T).m\n\n\t\t\t} else if field, ok := strings.CutPrefix(rest, \" struct, \"); ok && kind == \"type\" {\n\t\t\t\t// e.g. \"type ParenExpr struct, Lparen token.Pos\"\n\t\t\t\tkind = \"field\"\n\t\t\t\tname, typ, _ := strings.Cut(field, \" \")\n\n\t\t\t\t// The api script uses the name\n\t\t\t\t// \"embedded\" (ambiguously) for\n\t\t\t\t// the name of an anonymous field.\n\t\t\t\tif name == \"embedded\" {\n\t\t\t\t\t// Strip \"*pkg.T\" down to \"T\".\n\t\t\t\t\ttyp = strings.TrimPrefix(typ, \"*\")\n\t\t\t\t\tif _, after, ok := strings.Cut(typ, \".\"); ok {\n\t\t\t\t\t\ttyp = after\n\t\t\t\t\t}\n\t\t\t\t\ttyp = removeTypeParam(typ) // embedded Foo[T] -> Foo\n\t\t\t\t\tname = typ\n\t\t\t\t}\n\n\t\t\t\tsym += \".\" + name // T.f\n\t\t\t}\n\n\t\t\tsymbols, ok := pkgs[path]\n\t\t\tif !ok {\n\t\t\t\tsymbols = make(map[string]symInfo)\n\t\t\t\tpkgs[path] = symbols\n\t\t\t}\n\n\t\t\t// Don't overwrite earlier entries:\n\t\t\t// enums are redeclared in later versions\n\t\t\t// as their encoding changes;\n\t\t\t// deprecations count as updates too.\n\t\t\t// TODO(adonovan): it would be better to mark\n\t\t\t// deprecated as a boolean without changing the\n\t\t\t// version.\n\t\t\tif _, ok := symbols[sym]; !ok {\n\t\t\t\tvar sig string\n\t\t\t\tif kind == \"func\" {\n\t\t\t\t\tsig = signatures[path][sym]\n\t\t\t\t}\n\t\t\t\tsymbols[sym] = symInfo{\n\t\t\t\t\tkind:      kind,\n\t\t\t\t\tminor:     minor,\n\t\t\t\t\tsignature: sig,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Read and parse the GOROOT/api manifests.\n\tfor minor := 0; ; minor++ {\n\t\tbase := \"go1.txt\"\n\t\tif minor > 0 {\n\t\t\tbase = fmt.Sprintf(\"go1.%d.txt\", minor)\n\t\t}\n\t\tfilename := filepath.Join(apidir, base)\n\t\tdata, err := os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\t\t// All caught up.\n\t\t\t\t// Synthesize one final file from any api/next/*.txt fragments.\n\t\t\t\t// (They are consolidated into a go1.%d file some time between\n\t\t\t\t// the freeze and the first release candidate.)\n\t\t\t\tfilenames, err := filepath.Glob(filepath.Join(apidir, \"next\", \"*.txt\"))\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t}\n\t\t\t\tvar next bytes.Buffer\n\t\t\t\tfor _, filename := range filenames {\n\t\t\t\t\tdata, err := os.ReadFile(filename)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t\t}\n\t\t\t\t\tnext.Write(data)\n\t\t\t\t}\n\t\t\t\tparse(filename, next.Bytes(), minor) // (filename is a lie)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tparse(filename, data, minor)\n\t}\n\n\t// The APIs of the syscall/js and unsafe packages need to be computed explicitly,\n\t// because they're not included in the GOROOT/api/go1.*.txt files at this time.\n\tpkgs[\"syscall/js\"] = loadSymbols(\"syscall/js\", \"GOOS=js\", \"GOARCH=wasm\")\n\tpkgs[\"unsafe\"] = exportedSymbols(types.Unsafe) // TODO(adonovan): set correct versions\n\n\t// Write the combined manifest.\n\tvar buf bytes.Buffer\n\tbuf.WriteString(`// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage stdlib\n\nvar PackageSymbols = map[string][]Symbol{\n`)\n\n\tfor _, path := range sortedKeys(pkgs) {\n\t\tpkg := pkgs[path]\n\t\tfmt.Fprintf(&buf, \"\\t%q: {\\n\", path)\n\t\tfor _, name := range sortedKeys(pkg) {\n\t\t\tinfo := pkg[name]\n\t\t\tfmt.Fprintf(&buf, \"\\t\\t{%q, %s, %d, %q},\\n\",\n\t\t\t\tname, strings.Title(info.kind), info.minor, info.signature)\n\t\t}\n\t\tfmt.Fprintln(&buf, \"},\")\n\t}\n\tfmt.Fprintln(&buf, \"}\")\n\tfmtbuf, err := format.Source(buf.Bytes())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.WriteFile(\"manifest.go\", fmtbuf, 0o666); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\n// find the api directory, In most situations it is in GOROOT/api, but not always.\n// TODO(pjw): understand where it might be, and if there could be newer and older versions\nfunc apidir() string {\n\tstdout := new(bytes.Buffer)\n\tcmd := exec.Command(\"go\", \"env\", \"GOROOT\", \"GOPATH\")\n\tcmd.Stdout = stdout\n\tcmd.Stderr = os.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// Prefer GOROOT/api over GOPATH/api.\n\tfor line := range strings.SplitSeq(stdout.String(), \"\\n\") {\n\t\tapidir := filepath.Join(line, \"api\")\n\t\tinfo, err := os.Stat(apidir)\n\t\tif err == nil && info.IsDir() {\n\t\t\treturn apidir\n\t\t}\n\t}\n\tlog.Fatal(\"could not find api dir\")\n\treturn \"\"\n}\n\ntype symInfo struct {\n\tkind  string // e.g. \"func\"\n\tminor int    // go1.%d\n\t// for completion snippets\n\tsignature string // for Kind == stdlib.Func\n}\n\n// loadSymbols computes the exported symbols in the specified package\n// by parsing and type-checking the current source.\nfunc loadSymbols(pkg string, extraEnv ...string) map[string]symInfo {\n\tpkgs, err := packages.Load(&packages.Config{\n\t\tMode: packages.NeedTypes,\n\t\tEnv:  append(os.Environ(), extraEnv...),\n\t}, pkg)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t} else if len(pkgs) != 1 {\n\t\tlog.Fatalf(\"got %d packages, want one package %q\", len(pkgs), pkg)\n\t}\n\treturn exportedSymbols(pkgs[0].Types)\n}\n\nfunc exportedSymbols(pkg *types.Package) map[string]symInfo {\n\tsymbols := make(map[string]symInfo)\n\tfor _, name := range pkg.Scope().Names() {\n\t\tif obj := pkg.Scope().Lookup(name); obj.Exported() {\n\t\t\tvar kind string\n\t\t\tswitch obj.(type) {\n\t\t\tcase *types.Func, *types.Builtin:\n\t\t\t\tkind = \"func\"\n\t\t\tcase *types.Const:\n\t\t\t\tkind = \"const\"\n\t\t\tcase *types.Var:\n\t\t\t\tkind = \"var\"\n\t\t\tcase *types.TypeName:\n\t\t\t\tkind = \"type\"\n\t\t\t\t// TODO(adonovan): expand fields and methods of syscall/js.*\n\t\t\tdefault:\n\t\t\t\tlog.Fatalf(\"unexpected object type: %v\", obj)\n\t\t\t}\n\t\t\tsymbols[name] = symInfo{kind: kind, minor: 0} // pretend go1.0\n\t\t}\n\t}\n\treturn symbols\n}\n\nfunc sortedKeys[M ~map[K]V, K cmp.Ordered, V any](m M) []K {\n\tr := make([]K, 0, len(m))\n\tfor k := range m {\n\t\tr = append(r, k)\n\t}\n\tslices.Sort(r)\n\treturn r\n}\n\nfunc removeTypeParam(s string) string {\n\ti := strings.IndexByte(s, '[')\n\tj := strings.LastIndexByte(s, ']')\n\tif i > 0 && j > i {\n\t\ts = s[:i] + s[j+len(\"[\"):]\n\t}\n\treturn s\n}\n\n// -- generate dependency graph --\n\nfunc deps() {\n\ttype Package struct {\n\t\t// go list JSON output\n\t\tImportPath string   // import path of package in dir\n\t\tImports    []string // import paths used by this package\n\n\t\t// encoding\n\t\tindex int\n\t\tdeps  []int // indices of direct imports, sorted\n\t}\n\tpkgs := make(map[string]*Package)\n\tvar keys []string\n\tfor dec := json.NewDecoder(runGo(\"list\", \"-deps\", \"-json\", \"std\")); dec.More(); {\n\t\tvar pkg Package\n\t\tif err := dec.Decode(&pkg); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tpkgs[pkg.ImportPath] = &pkg\n\t\tkeys = append(keys, pkg.ImportPath)\n\t}\n\n\t// Sort and number the packages.\n\t// There are 344 as of Mar 2025.\n\tslices.Sort(keys)\n\tfor i, name := range keys {\n\t\tpkgs[name].index = i\n\t}\n\n\t// Encode the dependencies.\n\tfor _, pkg := range pkgs {\n\t\tfor _, imp := range pkg.Imports {\n\t\t\tif imp == \"C\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpkg.deps = append(pkg.deps, pkgs[imp].index)\n\t\t}\n\t\tslices.Sort(pkg.deps)\n\t}\n\n\t// Emit the table.\n\tvar buf bytes.Buffer\n\tbuf.WriteString(`// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage stdlib\n\ntype pkginfo struct {\n\tname string\n\tdeps string // list of indices of dependencies, as varint-encoded deltas\n}\nvar deps = [...]pkginfo{\n`)\n\tfor _, name := range keys {\n\t\tprev := 0\n\t\tvar deps []int\n\t\tfor _, v := range pkgs[name].deps {\n\t\t\tdeps = append(deps, v-prev) // delta\n\t\t\tprev = v\n\t\t}\n\t\tvar data []byte\n\t\tfor _, v := range deps {\n\t\t\tdata = binary.AppendUvarint(data, uint64(v))\n\t\t}\n\t\tfmt.Fprintf(&buf, \"\\t{%q, %q},\\n\", name, data)\n\t}\n\tfmt.Fprintln(&buf, \"}\")\n\n\t// Also write the list of bootstrap packages.\n\t// (We can't use indices because it is not a subset of std.)\n\tbootstrap, version := bootstrap()\n\tminor := strings.Split(version, \".\")[1] // \"go1.2.3\" -> \"2\"\n\tbuf.WriteString(`\n// bootstrap is the list of bootstrap packages extracted from cmd/dist.\nvar bootstrap = map[string]bool{\n`)\n\tfor _, pkg := range bootstrap {\n\t\tfmt.Fprintf(&buf, \"\\t%q: true,\\n\", pkg)\n\t}\n\tfmt.Fprintf(&buf, `}\n\n// BootstrapVersion is the minor version of Go used during toolchain\n// bootstrapping. Packages for which [IsBootstrapPackage] must not use\n// features of Go newer than this version.\nconst BootstrapVersion = Version(%s) // %s\n`, minor, version)\n\n\t// Format and update the dependencies file.\n\tfmtbuf, err := format.Source(buf.Bytes())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := os.WriteFile(\"deps.go\", fmtbuf, 0o666); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Also generate the data for the test.\n\tfor _, t := range [...]struct{ flag, filename string }{\n\t\t{\"-deps=true\", \"testdata/nethttp.deps\"},\n\t\t{`-f={{join .Imports \"\\n\"}}`, \"testdata/nethttp.imports\"},\n\t} {\n\t\tstdout := new(bytes.Buffer)\n\t\tcmd := exec.Command(\"go\", \"list\", t.flag, \"net/http\")\n\t\tcmd.Stdout = stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Env = append(os.Environ(), \"CGO_ENABLED=0\", \"GOOS=linux\", \"GOARCH=amd64\")\n\t\tif err := cmd.Run(); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(t.filename, stdout.Bytes(), 0666); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n\n// bootstrap returns the list of bootstrap packages out of the\n// source of the dist command, along with the minimum toolchain\n// version.\n//\n// We assume it is \"var bootstrapDirs []string\" in buildtool.go, and\n// is a list of string literals, either package names or \"dir/...\".\n// TODO(adonovan): find a more robust solution.\nfunc bootstrap() ([]string, string) {\n\tfset := token.NewFileSet()\n\tfilename := strings.TrimSpace(runGo(\"list\", \"-f={{.Dir}}/buildtool.go\", \"cmd/dist\").String())\n\tf, err := parser.ParseFile(fset, filename, nil, 0)\n\tif err != nil {\n\t\tlog.Fatalf(\"can't parse buildtool.go file in cmd/dist package: %v\", err)\n\t}\n\n\tconst bootstrapVarName = \"bootstrapDirs\"\n\tvar (\n\t\targs    = []string{\"list\"} // go list command to expand bootstrap packages\n\t\tversion string\n\t)\n\tfor _, decl := range f.Decls {\n\t\tdecl, ok := decl.(*ast.GenDecl)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, spec := range decl.Specs {\n\t\t\tspec, ok := spec.(*ast.ValueSpec)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(spec.Names) != 1 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch spec.Names[0].Name {\n\t\t\tcase bootstrapVarName:\n\t\t\t\t// var bootstrapDirs = []string{ ... }\n\t\t\t\tif len(spec.Values) != 1 {\n\t\t\t\t\tlog.Fatalf(\"%s: %s var spec has %d values, want 1\",\n\t\t\t\t\t\tfset.Position(spec.Pos()), len(spec.Values))\n\t\t\t\t}\n\t\t\t\tvalue0 := spec.Values[0]\n\t\t\t\tlit, ok := value0.(*ast.CompositeLit)\n\t\t\t\tif !ok {\n\t\t\t\t\tlog.Fatalf(\"%s: %s assigned from %T, want slice literal\",\n\t\t\t\t\t\tfset.Position(value0.Pos()), value0)\n\t\t\t\t}\n\t\t\t\t// Construct a go list command from the package patterns.\n\t\t\t\tfor _, elt := range lit.Elts {\n\t\t\t\t\tlit, ok := elt.(*ast.BasicLit)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tlog.Fatalf(\"%s: element is %T, want string literal\",\n\t\t\t\t\t\t\tfset.Position(elt.Pos()), elt)\n\t\t\t\t\t}\n\t\t\t\t\tpattern, err := strconv.Unquote(lit.Value)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlog.Fatalf(\"%s: %v\", fset.Position(elt.Pos()), err)\n\t\t\t\t\t}\n\t\t\t\t\targs = append(args, pattern)\n\t\t\t\t}\n\n\t\t\tcase \"minBootstrap\":\n\t\t\t\t// const minBootstrap = \"go1.2.3\"\n\t\t\t\tlit := spec.Values[0].(*ast.BasicLit)\n\t\t\t\tversion, _ = strconv.Unquote(lit.Value)\n\t\t\t}\n\t\t}\n\t}\n\tif len(args) < 2 {\n\t\tlog.Fatalf(\"can't find var %s in buildtool.go file in cmd/dist package: %v\",\n\t\t\tbootstrapVarName, err)\n\t}\n\tif version == \"\" {\n\t\tlog.Fatalf(\"can't find const minBootstrap version in buildtool.go file in cmd/dist package: %v\",\n\t\t\terr)\n\t}\n\n\treturn strings.Split(strings.TrimSpace(runGo(args...).String()), \"\\n\"), version\n}\n\nfunc runGo(args ...string) *bytes.Buffer {\n\tcmd := exec.Command(\"go\", args...)\n\tcmd.Env = append(os.Environ(), \"CGO_ENABLED=0\", \"GOOS=linux\", \"GOARCH=amd64\")\n\tstdout, err := cmd.Output()\n\tif err != nil {\n\t\tlog.Fatalf(\"%s: failed: %v\", cmd, err)\n\t}\n\treturn bytes.NewBuffer(stdout)\n}\n"
  },
  {
    "path": "internal/stdlib/import.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage stdlib\n\n// This file provides the API for the import graph of the standard library.\n//\n// Be aware that the compiler-generated code for every package\n// implicitly depends on package \"runtime\" and a handful of others\n// (see runtimePkgs in GOROOT/src/cmd/internal/objabi/pkgspecial.go).\n\nimport (\n\t\"encoding/binary\"\n\t\"iter\"\n\t\"slices\"\n\t\"strings\"\n)\n\n// Imports returns the sequence of packages directly imported by the\n// named standard packages, in name order.\n// The imports of an unknown package are the empty set.\n//\n// The graph is built into the application and may differ from the\n// graph in the Go source tree being analyzed by the application.\nfunc Imports(pkgs ...string) iter.Seq[string] {\n\treturn func(yield func(string) bool) {\n\t\tfor _, pkg := range pkgs {\n\t\t\tif i, ok := find(pkg); ok {\n\t\t\t\tvar depIndex uint64\n\t\t\t\tfor data := []byte(deps[i].deps); len(data) > 0; {\n\t\t\t\t\tdelta, n := binary.Uvarint(data)\n\t\t\t\t\tdepIndex += delta\n\t\t\t\t\tif !yield(deps[depIndex].name) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tdata = data[n:]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Dependencies returns the set of all dependencies of the named\n// standard packages, including the initial package,\n// in a deterministic topological order.\n// The dependencies of an unknown package are the empty set.\n//\n// The graph is built into the application and may differ from the\n// graph in the Go source tree being analyzed by the application.\nfunc Dependencies(pkgs ...string) iter.Seq[string] {\n\treturn func(yield func(string) bool) {\n\t\tfor _, pkg := range pkgs {\n\t\t\tif i, ok := find(pkg); ok {\n\t\t\t\tvar seen [1 + len(deps)/8]byte // bit set of seen packages\n\t\t\t\tvar visit func(i int) bool\n\t\t\t\tvisit = func(i int) bool {\n\t\t\t\t\tbit := byte(1) << (i % 8)\n\t\t\t\t\tif seen[i/8]&bit == 0 {\n\t\t\t\t\t\tseen[i/8] |= bit\n\t\t\t\t\t\tvar depIndex uint64\n\t\t\t\t\t\tfor data := []byte(deps[i].deps); len(data) > 0; {\n\t\t\t\t\t\t\tdelta, n := binary.Uvarint(data)\n\t\t\t\t\t\t\tdepIndex += delta\n\t\t\t\t\t\t\tif !visit(int(depIndex)) {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdata = data[n:]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !yield(deps[i].name) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tif !visit(i) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// find returns the index of pkg in the deps table.\nfunc find(pkg string) (int, bool) {\n\treturn slices.BinarySearchFunc(deps[:], pkg, func(p pkginfo, n string) int {\n\t\treturn strings.Compare(p.name, n)\n\t})\n}\n\n// IsBootstrapPackage reports whether pkg is one of the low-level\n// packages in the Go distribution that must compile with the older\n// language version specified by [BootstrapVersion] during toolchain\n// bootstrapping; see golang.org/s/go15bootstrap.\nfunc IsBootstrapPackage(pkg string) bool {\n\treturn bootstrap[pkg]\n}\n"
  },
  {
    "path": "internal/stdlib/manifest.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by generate.go. DO NOT EDIT.\n\npackage stdlib\n\nvar PackageSymbols = map[string][]Symbol{\n\t\"archive/tar\": {\n\t\t{\"(*Header).FileInfo\", Method, 1, \"\"},\n\t\t{\"(*Reader).Next\", Method, 0, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Writer).AddFS\", Method, 22, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"(*Writer).WriteHeader\", Method, 0, \"\"},\n\t\t{\"(FileInfoNames).Gname\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).IsDir\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).ModTime\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).Mode\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).Name\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).Size\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).Sys\", Method, 23, \"\"},\n\t\t{\"(FileInfoNames).Uname\", Method, 23, \"\"},\n\t\t{\"(Format).String\", Method, 10, \"\"},\n\t\t{\"ErrFieldTooLong\", Var, 0, \"\"},\n\t\t{\"ErrHeader\", Var, 0, \"\"},\n\t\t{\"ErrInsecurePath\", Var, 20, \"\"},\n\t\t{\"ErrWriteAfterClose\", Var, 0, \"\"},\n\t\t{\"ErrWriteTooLong\", Var, 0, \"\"},\n\t\t{\"FileInfoHeader\", Func, 1, \"func(fi fs.FileInfo, link string) (*Header, error)\"},\n\t\t{\"FileInfoNames\", Type, 23, \"\"},\n\t\t{\"Format\", Type, 10, \"\"},\n\t\t{\"FormatGNU\", Const, 10, \"\"},\n\t\t{\"FormatPAX\", Const, 10, \"\"},\n\t\t{\"FormatUSTAR\", Const, 10, \"\"},\n\t\t{\"FormatUnknown\", Const, 10, \"\"},\n\t\t{\"Header\", Type, 0, \"\"},\n\t\t{\"Header.AccessTime\", Field, 0, \"\"},\n\t\t{\"Header.ChangeTime\", Field, 0, \"\"},\n\t\t{\"Header.Devmajor\", Field, 0, \"\"},\n\t\t{\"Header.Devminor\", Field, 0, \"\"},\n\t\t{\"Header.Format\", Field, 10, \"\"},\n\t\t{\"Header.Gid\", Field, 0, \"\"},\n\t\t{\"Header.Gname\", Field, 0, \"\"},\n\t\t{\"Header.Linkname\", Field, 0, \"\"},\n\t\t{\"Header.ModTime\", Field, 0, \"\"},\n\t\t{\"Header.Mode\", Field, 0, \"\"},\n\t\t{\"Header.Name\", Field, 0, \"\"},\n\t\t{\"Header.PAXRecords\", Field, 10, \"\"},\n\t\t{\"Header.Size\", Field, 0, \"\"},\n\t\t{\"Header.Typeflag\", Field, 0, \"\"},\n\t\t{\"Header.Uid\", Field, 0, \"\"},\n\t\t{\"Header.Uname\", Field, 0, \"\"},\n\t\t{\"Header.Xattrs\", Field, 3, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) *Reader\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"TypeBlock\", Const, 0, \"\"},\n\t\t{\"TypeChar\", Const, 0, \"\"},\n\t\t{\"TypeCont\", Const, 0, \"\"},\n\t\t{\"TypeDir\", Const, 0, \"\"},\n\t\t{\"TypeFifo\", Const, 0, \"\"},\n\t\t{\"TypeGNULongLink\", Const, 1, \"\"},\n\t\t{\"TypeGNULongName\", Const, 1, \"\"},\n\t\t{\"TypeGNUSparse\", Const, 3, \"\"},\n\t\t{\"TypeLink\", Const, 0, \"\"},\n\t\t{\"TypeReg\", Const, 0, \"\"},\n\t\t{\"TypeRegA\", Const, 0, \"\"},\n\t\t{\"TypeSymlink\", Const, 0, \"\"},\n\t\t{\"TypeXGlobalHeader\", Const, 0, \"\"},\n\t\t{\"TypeXHeader\", Const, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"archive/zip\": {\n\t\t{\"(*File).DataOffset\", Method, 2, \"\"},\n\t\t{\"(*File).FileInfo\", Method, 0, \"\"},\n\t\t{\"(*File).ModTime\", Method, 0, \"\"},\n\t\t{\"(*File).Mode\", Method, 0, \"\"},\n\t\t{\"(*File).Open\", Method, 0, \"\"},\n\t\t{\"(*File).OpenRaw\", Method, 17, \"\"},\n\t\t{\"(*File).SetModTime\", Method, 0, \"\"},\n\t\t{\"(*File).SetMode\", Method, 0, \"\"},\n\t\t{\"(*FileHeader).FileInfo\", Method, 0, \"\"},\n\t\t{\"(*FileHeader).ModTime\", Method, 0, \"\"},\n\t\t{\"(*FileHeader).Mode\", Method, 0, \"\"},\n\t\t{\"(*FileHeader).SetModTime\", Method, 0, \"\"},\n\t\t{\"(*FileHeader).SetMode\", Method, 0, \"\"},\n\t\t{\"(*ReadCloser).Close\", Method, 0, \"\"},\n\t\t{\"(*ReadCloser).Open\", Method, 16, \"\"},\n\t\t{\"(*ReadCloser).RegisterDecompressor\", Method, 6, \"\"},\n\t\t{\"(*Reader).Open\", Method, 16, \"\"},\n\t\t{\"(*Reader).RegisterDecompressor\", Method, 6, \"\"},\n\t\t{\"(*Writer).AddFS\", Method, 22, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Copy\", Method, 17, \"\"},\n\t\t{\"(*Writer).Create\", Method, 0, \"\"},\n\t\t{\"(*Writer).CreateHeader\", Method, 0, \"\"},\n\t\t{\"(*Writer).CreateRaw\", Method, 17, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 4, \"\"},\n\t\t{\"(*Writer).RegisterCompressor\", Method, 6, \"\"},\n\t\t{\"(*Writer).SetComment\", Method, 10, \"\"},\n\t\t{\"(*Writer).SetOffset\", Method, 5, \"\"},\n\t\t{\"Compressor\", Type, 2, \"\"},\n\t\t{\"Decompressor\", Type, 2, \"\"},\n\t\t{\"Deflate\", Const, 0, \"\"},\n\t\t{\"ErrAlgorithm\", Var, 0, \"\"},\n\t\t{\"ErrChecksum\", Var, 0, \"\"},\n\t\t{\"ErrFormat\", Var, 0, \"\"},\n\t\t{\"ErrInsecurePath\", Var, 20, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"File.FileHeader\", Field, 0, \"\"},\n\t\t{\"FileHeader\", Type, 0, \"\"},\n\t\t{\"FileHeader.CRC32\", Field, 0, \"\"},\n\t\t{\"FileHeader.Comment\", Field, 0, \"\"},\n\t\t{\"FileHeader.CompressedSize\", Field, 0, \"\"},\n\t\t{\"FileHeader.CompressedSize64\", Field, 1, \"\"},\n\t\t{\"FileHeader.CreatorVersion\", Field, 0, \"\"},\n\t\t{\"FileHeader.ExternalAttrs\", Field, 0, \"\"},\n\t\t{\"FileHeader.Extra\", Field, 0, \"\"},\n\t\t{\"FileHeader.Flags\", Field, 0, \"\"},\n\t\t{\"FileHeader.Method\", Field, 0, \"\"},\n\t\t{\"FileHeader.Modified\", Field, 10, \"\"},\n\t\t{\"FileHeader.ModifiedDate\", Field, 0, \"\"},\n\t\t{\"FileHeader.ModifiedTime\", Field, 0, \"\"},\n\t\t{\"FileHeader.Name\", Field, 0, \"\"},\n\t\t{\"FileHeader.NonUTF8\", Field, 10, \"\"},\n\t\t{\"FileHeader.ReaderVersion\", Field, 0, \"\"},\n\t\t{\"FileHeader.UncompressedSize\", Field, 0, \"\"},\n\t\t{\"FileHeader.UncompressedSize64\", Field, 1, \"\"},\n\t\t{\"FileInfoHeader\", Func, 0, \"func(fi fs.FileInfo) (*FileHeader, error)\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.ReaderAt, size int64) (*Reader, error)\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"OpenReader\", Func, 0, \"func(name string) (*ReadCloser, error)\"},\n\t\t{\"ReadCloser\", Type, 0, \"\"},\n\t\t{\"ReadCloser.Reader\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Reader.Comment\", Field, 0, \"\"},\n\t\t{\"Reader.File\", Field, 0, \"\"},\n\t\t{\"RegisterCompressor\", Func, 2, \"func(method uint16, comp Compressor)\"},\n\t\t{\"RegisterDecompressor\", Func, 2, \"func(method uint16, dcomp Decompressor)\"},\n\t\t{\"Store\", Const, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"bufio\": {\n\t\t{\"(*Reader).Buffered\", Method, 0, \"\"},\n\t\t{\"(*Reader).Discard\", Method, 5, \"\"},\n\t\t{\"(*Reader).Peek\", Method, 0, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadBytes\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadLine\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadSlice\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadString\", Method, 0, \"\"},\n\t\t{\"(*Reader).Reset\", Method, 2, \"\"},\n\t\t{\"(*Reader).Size\", Method, 10, \"\"},\n\t\t{\"(*Reader).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).WriteTo\", Method, 1, \"\"},\n\t\t{\"(*Scanner).Buffer\", Method, 6, \"\"},\n\t\t{\"(*Scanner).Bytes\", Method, 1, \"\"},\n\t\t{\"(*Scanner).Err\", Method, 1, \"\"},\n\t\t{\"(*Scanner).Scan\", Method, 1, \"\"},\n\t\t{\"(*Scanner).Split\", Method, 1, \"\"},\n\t\t{\"(*Scanner).Text\", Method, 1, \"\"},\n\t\t{\"(*Writer).Available\", Method, 0, \"\"},\n\t\t{\"(*Writer).AvailableBuffer\", Method, 18, \"\"},\n\t\t{\"(*Writer).Buffered\", Method, 0, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).ReadFrom\", Method, 1, \"\"},\n\t\t{\"(*Writer).Reset\", Method, 2, \"\"},\n\t\t{\"(*Writer).Size\", Method, 10, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"(*Writer).WriteByte\", Method, 0, \"\"},\n\t\t{\"(*Writer).WriteRune\", Method, 0, \"\"},\n\t\t{\"(*Writer).WriteString\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Available\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).AvailableBuffer\", Method, 18, \"\"},\n\t\t{\"(ReadWriter).Discard\", Method, 5, \"\"},\n\t\t{\"(ReadWriter).Flush\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Peek\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Read\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadByte\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadBytes\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadFrom\", Method, 1, \"\"},\n\t\t{\"(ReadWriter).ReadLine\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadRune\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadSlice\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).ReadString\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Write\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).WriteByte\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).WriteRune\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).WriteString\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).WriteTo\", Method, 1, \"\"},\n\t\t{\"ErrAdvanceTooFar\", Var, 1, \"\"},\n\t\t{\"ErrBadReadCount\", Var, 15, \"\"},\n\t\t{\"ErrBufferFull\", Var, 0, \"\"},\n\t\t{\"ErrFinalToken\", Var, 6, \"\"},\n\t\t{\"ErrInvalidUnreadByte\", Var, 0, \"\"},\n\t\t{\"ErrInvalidUnreadRune\", Var, 0, \"\"},\n\t\t{\"ErrNegativeAdvance\", Var, 1, \"\"},\n\t\t{\"ErrNegativeCount\", Var, 0, \"\"},\n\t\t{\"ErrTooLong\", Var, 1, \"\"},\n\t\t{\"MaxScanTokenSize\", Const, 1, \"\"},\n\t\t{\"NewReadWriter\", Func, 0, \"func(r *Reader, w *Writer) *ReadWriter\"},\n\t\t{\"NewReader\", Func, 0, \"func(rd io.Reader) *Reader\"},\n\t\t{\"NewReaderSize\", Func, 0, \"func(rd io.Reader, size int) *Reader\"},\n\t\t{\"NewScanner\", Func, 1, \"func(r io.Reader) *Scanner\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"NewWriterSize\", Func, 0, \"func(w io.Writer, size int) *Writer\"},\n\t\t{\"ReadWriter\", Type, 0, \"\"},\n\t\t{\"ReadWriter.Reader\", Field, 0, \"\"},\n\t\t{\"ReadWriter.Writer\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"ScanBytes\", Func, 1, \"func(data []byte, atEOF bool) (advance int, token []byte, err error)\"},\n\t\t{\"ScanLines\", Func, 1, \"func(data []byte, atEOF bool) (advance int, token []byte, err error)\"},\n\t\t{\"ScanRunes\", Func, 1, \"func(data []byte, atEOF bool) (advance int, token []byte, err error)\"},\n\t\t{\"ScanWords\", Func, 1, \"func(data []byte, atEOF bool) (advance int, token []byte, err error)\"},\n\t\t{\"Scanner\", Type, 1, \"\"},\n\t\t{\"SplitFunc\", Type, 1, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"bytes\": {\n\t\t{\"(*Buffer).Available\", Method, 21, \"\"},\n\t\t{\"(*Buffer).AvailableBuffer\", Method, 21, \"\"},\n\t\t{\"(*Buffer).Bytes\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Cap\", Method, 5, \"\"},\n\t\t{\"(*Buffer).Grow\", Method, 1, \"\"},\n\t\t{\"(*Buffer).Len\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Next\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Peek\", Method, 26, \"\"},\n\t\t{\"(*Buffer).Read\", Method, 0, \"\"},\n\t\t{\"(*Buffer).ReadByte\", Method, 0, \"\"},\n\t\t{\"(*Buffer).ReadBytes\", Method, 0, \"\"},\n\t\t{\"(*Buffer).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(*Buffer).ReadRune\", Method, 0, \"\"},\n\t\t{\"(*Buffer).ReadString\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Reset\", Method, 0, \"\"},\n\t\t{\"(*Buffer).String\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Truncate\", Method, 0, \"\"},\n\t\t{\"(*Buffer).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(*Buffer).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(*Buffer).Write\", Method, 0, \"\"},\n\t\t{\"(*Buffer).WriteByte\", Method, 0, \"\"},\n\t\t{\"(*Buffer).WriteRune\", Method, 0, \"\"},\n\t\t{\"(*Buffer).WriteString\", Method, 0, \"\"},\n\t\t{\"(*Buffer).WriteTo\", Method, 0, \"\"},\n\t\t{\"(*Reader).Len\", Method, 0, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadAt\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).Reset\", Method, 7, \"\"},\n\t\t{\"(*Reader).Seek\", Method, 0, \"\"},\n\t\t{\"(*Reader).Size\", Method, 5, \"\"},\n\t\t{\"(*Reader).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).WriteTo\", Method, 1, \"\"},\n\t\t{\"Buffer\", Type, 0, \"\"},\n\t\t{\"Clone\", Func, 20, \"func(b []byte) []byte\"},\n\t\t{\"Compare\", Func, 0, \"func(a []byte, b []byte) int\"},\n\t\t{\"Contains\", Func, 0, \"func(b []byte, subslice []byte) bool\"},\n\t\t{\"ContainsAny\", Func, 7, \"func(b []byte, chars string) bool\"},\n\t\t{\"ContainsFunc\", Func, 21, \"func(b []byte, f func(rune) bool) bool\"},\n\t\t{\"ContainsRune\", Func, 7, \"func(b []byte, r rune) bool\"},\n\t\t{\"Count\", Func, 0, \"func(s []byte, sep []byte) int\"},\n\t\t{\"Cut\", Func, 18, \"func(s []byte, sep []byte) (before []byte, after []byte, found bool)\"},\n\t\t{\"CutPrefix\", Func, 20, \"func(s []byte, prefix []byte) (after []byte, found bool)\"},\n\t\t{\"CutSuffix\", Func, 20, \"func(s []byte, suffix []byte) (before []byte, found bool)\"},\n\t\t{\"Equal\", Func, 0, \"func(a []byte, b []byte) bool\"},\n\t\t{\"EqualFold\", Func, 0, \"func(s []byte, t []byte) bool\"},\n\t\t{\"ErrTooLarge\", Var, 0, \"\"},\n\t\t{\"Fields\", Func, 0, \"func(s []byte) [][]byte\"},\n\t\t{\"FieldsFunc\", Func, 0, \"func(s []byte, f func(rune) bool) [][]byte\"},\n\t\t{\"FieldsFuncSeq\", Func, 24, \"func(s []byte, f func(rune) bool) iter.Seq[[]byte]\"},\n\t\t{\"FieldsSeq\", Func, 24, \"func(s []byte) iter.Seq[[]byte]\"},\n\t\t{\"HasPrefix\", Func, 0, \"func(s []byte, prefix []byte) bool\"},\n\t\t{\"HasSuffix\", Func, 0, \"func(s []byte, suffix []byte) bool\"},\n\t\t{\"Index\", Func, 0, \"func(s []byte, sep []byte) int\"},\n\t\t{\"IndexAny\", Func, 0, \"func(s []byte, chars string) int\"},\n\t\t{\"IndexByte\", Func, 0, \"func(b []byte, c byte) int\"},\n\t\t{\"IndexFunc\", Func, 0, \"func(s []byte, f func(r rune) bool) int\"},\n\t\t{\"IndexRune\", Func, 0, \"func(s []byte, r rune) int\"},\n\t\t{\"Join\", Func, 0, \"func(s [][]byte, sep []byte) []byte\"},\n\t\t{\"LastIndex\", Func, 0, \"func(s []byte, sep []byte) int\"},\n\t\t{\"LastIndexAny\", Func, 0, \"func(s []byte, chars string) int\"},\n\t\t{\"LastIndexByte\", Func, 5, \"func(s []byte, c byte) int\"},\n\t\t{\"LastIndexFunc\", Func, 0, \"func(s []byte, f func(r rune) bool) int\"},\n\t\t{\"Lines\", Func, 24, \"func(s []byte) iter.Seq[[]byte]\"},\n\t\t{\"Map\", Func, 0, \"func(mapping func(r rune) rune, s []byte) []byte\"},\n\t\t{\"MinRead\", Const, 0, \"\"},\n\t\t{\"NewBuffer\", Func, 0, \"func(buf []byte) *Buffer\"},\n\t\t{\"NewBufferString\", Func, 0, \"func(s string) *Buffer\"},\n\t\t{\"NewReader\", Func, 0, \"func(b []byte) *Reader\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Repeat\", Func, 0, \"func(b []byte, count int) []byte\"},\n\t\t{\"Replace\", Func, 0, \"func(s []byte, old []byte, new []byte, n int) []byte\"},\n\t\t{\"ReplaceAll\", Func, 12, \"func(s []byte, old []byte, new []byte) []byte\"},\n\t\t{\"Runes\", Func, 0, \"func(s []byte) []rune\"},\n\t\t{\"Split\", Func, 0, \"func(s []byte, sep []byte) [][]byte\"},\n\t\t{\"SplitAfter\", Func, 0, \"func(s []byte, sep []byte) [][]byte\"},\n\t\t{\"SplitAfterN\", Func, 0, \"func(s []byte, sep []byte, n int) [][]byte\"},\n\t\t{\"SplitAfterSeq\", Func, 24, \"func(s []byte, sep []byte) iter.Seq[[]byte]\"},\n\t\t{\"SplitN\", Func, 0, \"func(s []byte, sep []byte, n int) [][]byte\"},\n\t\t{\"SplitSeq\", Func, 24, \"func(s []byte, sep []byte) iter.Seq[[]byte]\"},\n\t\t{\"Title\", Func, 0, \"func(s []byte) []byte\"},\n\t\t{\"ToLower\", Func, 0, \"func(s []byte) []byte\"},\n\t\t{\"ToLowerSpecial\", Func, 0, \"func(c unicode.SpecialCase, s []byte) []byte\"},\n\t\t{\"ToTitle\", Func, 0, \"func(s []byte) []byte\"},\n\t\t{\"ToTitleSpecial\", Func, 0, \"func(c unicode.SpecialCase, s []byte) []byte\"},\n\t\t{\"ToUpper\", Func, 0, \"func(s []byte) []byte\"},\n\t\t{\"ToUpperSpecial\", Func, 0, \"func(c unicode.SpecialCase, s []byte) []byte\"},\n\t\t{\"ToValidUTF8\", Func, 13, \"func(s []byte, replacement []byte) []byte\"},\n\t\t{\"Trim\", Func, 0, \"func(s []byte, cutset string) []byte\"},\n\t\t{\"TrimFunc\", Func, 0, \"func(s []byte, f func(r rune) bool) []byte\"},\n\t\t{\"TrimLeft\", Func, 0, \"func(s []byte, cutset string) []byte\"},\n\t\t{\"TrimLeftFunc\", Func, 0, \"func(s []byte, f func(r rune) bool) []byte\"},\n\t\t{\"TrimPrefix\", Func, 1, \"func(s []byte, prefix []byte) []byte\"},\n\t\t{\"TrimRight\", Func, 0, \"func(s []byte, cutset string) []byte\"},\n\t\t{\"TrimRightFunc\", Func, 0, \"func(s []byte, f func(r rune) bool) []byte\"},\n\t\t{\"TrimSpace\", Func, 0, \"func(s []byte) []byte\"},\n\t\t{\"TrimSuffix\", Func, 1, \"func(s []byte, suffix []byte) []byte\"},\n\t},\n\t\"cmp\": {\n\t\t{\"Compare\", Func, 21, \"func[T Ordered](x T, y T) int\"},\n\t\t{\"Less\", Func, 21, \"func[T Ordered](x T, y T) bool\"},\n\t\t{\"Or\", Func, 22, \"func[T comparable](vals ...T) T\"},\n\t\t{\"Ordered\", Type, 21, \"\"},\n\t},\n\t\"compress/bzip2\": {\n\t\t{\"(StructuralError).Error\", Method, 0, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"StructuralError\", Type, 0, \"\"},\n\t},\n\t\"compress/flate\": {\n\t\t{\"(*ReadError).Error\", Method, 0, \"\"},\n\t\t{\"(*WriteError).Error\", Method, 0, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).Reset\", Method, 2, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"(CorruptInputError).Error\", Method, 0, \"\"},\n\t\t{\"(InternalError).Error\", Method, 0, \"\"},\n\t\t{\"(Reader).Read\", Method, 0, \"\"},\n\t\t{\"(Reader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(Resetter).Reset\", Method, 4, \"\"},\n\t\t{\"BestCompression\", Const, 0, \"\"},\n\t\t{\"BestSpeed\", Const, 0, \"\"},\n\t\t{\"CorruptInputError\", Type, 0, \"\"},\n\t\t{\"DefaultCompression\", Const, 0, \"\"},\n\t\t{\"HuffmanOnly\", Const, 7, \"\"},\n\t\t{\"InternalError\", Type, 0, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) io.ReadCloser\"},\n\t\t{\"NewReaderDict\", Func, 0, \"func(r io.Reader, dict []byte) io.ReadCloser\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer, level int) (*Writer, error)\"},\n\t\t{\"NewWriterDict\", Func, 0, \"func(w io.Writer, level int, dict []byte) (*Writer, error)\"},\n\t\t{\"NoCompression\", Const, 0, \"\"},\n\t\t{\"ReadError\", Type, 0, \"\"},\n\t\t{\"ReadError.Err\", Field, 0, \"\"},\n\t\t{\"ReadError.Offset\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Resetter\", Type, 4, \"\"},\n\t\t{\"WriteError\", Type, 0, \"\"},\n\t\t{\"WriteError.Err\", Field, 0, \"\"},\n\t\t{\"WriteError.Offset\", Field, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"compress/gzip\": {\n\t\t{\"(*Reader).Close\", Method, 0, \"\"},\n\t\t{\"(*Reader).Multistream\", Method, 4, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).Reset\", Method, 3, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 1, \"\"},\n\t\t{\"(*Writer).Reset\", Method, 2, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"BestCompression\", Const, 0, \"\"},\n\t\t{\"BestSpeed\", Const, 0, \"\"},\n\t\t{\"DefaultCompression\", Const, 0, \"\"},\n\t\t{\"ErrChecksum\", Var, 0, \"\"},\n\t\t{\"ErrHeader\", Var, 0, \"\"},\n\t\t{\"Header\", Type, 0, \"\"},\n\t\t{\"Header.Comment\", Field, 0, \"\"},\n\t\t{\"Header.Extra\", Field, 0, \"\"},\n\t\t{\"Header.ModTime\", Field, 0, \"\"},\n\t\t{\"Header.Name\", Field, 0, \"\"},\n\t\t{\"Header.OS\", Field, 0, \"\"},\n\t\t{\"HuffmanOnly\", Const, 8, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) (*Reader, error)\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"NewWriterLevel\", Func, 0, \"func(w io.Writer, level int) (*Writer, error)\"},\n\t\t{\"NoCompression\", Const, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Reader.Header\", Field, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t\t{\"Writer.Header\", Field, 0, \"\"},\n\t},\n\t\"compress/lzw\": {\n\t\t{\"(*Reader).Close\", Method, 17, \"\"},\n\t\t{\"(*Reader).Read\", Method, 17, \"\"},\n\t\t{\"(*Reader).Reset\", Method, 17, \"\"},\n\t\t{\"(*Writer).Close\", Method, 17, \"\"},\n\t\t{\"(*Writer).Reset\", Method, 17, \"\"},\n\t\t{\"(*Writer).Write\", Method, 17, \"\"},\n\t\t{\"LSB\", Const, 0, \"\"},\n\t\t{\"MSB\", Const, 0, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader, order Order, litWidth int) io.ReadCloser\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer, order Order, litWidth int) io.WriteCloser\"},\n\t\t{\"Order\", Type, 0, \"\"},\n\t\t{\"Reader\", Type, 17, \"\"},\n\t\t{\"Writer\", Type, 17, \"\"},\n\t},\n\t\"compress/zlib\": {\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).Reset\", Method, 2, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"(Resetter).Reset\", Method, 4, \"\"},\n\t\t{\"BestCompression\", Const, 0, \"\"},\n\t\t{\"BestSpeed\", Const, 0, \"\"},\n\t\t{\"DefaultCompression\", Const, 0, \"\"},\n\t\t{\"ErrChecksum\", Var, 0, \"\"},\n\t\t{\"ErrDictionary\", Var, 0, \"\"},\n\t\t{\"ErrHeader\", Var, 0, \"\"},\n\t\t{\"HuffmanOnly\", Const, 8, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) (io.ReadCloser, error)\"},\n\t\t{\"NewReaderDict\", Func, 0, \"func(r io.Reader, dict []byte) (io.ReadCloser, error)\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"NewWriterLevel\", Func, 0, \"func(w io.Writer, level int) (*Writer, error)\"},\n\t\t{\"NewWriterLevelDict\", Func, 0, \"func(w io.Writer, level int, dict []byte) (*Writer, error)\"},\n\t\t{\"NoCompression\", Const, 0, \"\"},\n\t\t{\"Resetter\", Type, 4, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"container/heap\": {\n\t\t{\"(Interface).Len\", Method, 0, \"\"},\n\t\t{\"(Interface).Less\", Method, 0, \"\"},\n\t\t{\"(Interface).Pop\", Method, 0, \"\"},\n\t\t{\"(Interface).Push\", Method, 0, \"\"},\n\t\t{\"(Interface).Swap\", Method, 0, \"\"},\n\t\t{\"Fix\", Func, 2, \"func(h Interface, i int)\"},\n\t\t{\"Init\", Func, 0, \"func(h Interface)\"},\n\t\t{\"Interface\", Type, 0, \"\"},\n\t\t{\"Pop\", Func, 0, \"func(h Interface) any\"},\n\t\t{\"Push\", Func, 0, \"func(h Interface, x any)\"},\n\t\t{\"Remove\", Func, 0, \"func(h Interface, i int) any\"},\n\t},\n\t\"container/list\": {\n\t\t{\"(*Element).Next\", Method, 0, \"\"},\n\t\t{\"(*Element).Prev\", Method, 0, \"\"},\n\t\t{\"(*List).Back\", Method, 0, \"\"},\n\t\t{\"(*List).Front\", Method, 0, \"\"},\n\t\t{\"(*List).Init\", Method, 0, \"\"},\n\t\t{\"(*List).InsertAfter\", Method, 0, \"\"},\n\t\t{\"(*List).InsertBefore\", Method, 0, \"\"},\n\t\t{\"(*List).Len\", Method, 0, \"\"},\n\t\t{\"(*List).MoveAfter\", Method, 2, \"\"},\n\t\t{\"(*List).MoveBefore\", Method, 2, \"\"},\n\t\t{\"(*List).MoveToBack\", Method, 0, \"\"},\n\t\t{\"(*List).MoveToFront\", Method, 0, \"\"},\n\t\t{\"(*List).PushBack\", Method, 0, \"\"},\n\t\t{\"(*List).PushBackList\", Method, 0, \"\"},\n\t\t{\"(*List).PushFront\", Method, 0, \"\"},\n\t\t{\"(*List).PushFrontList\", Method, 0, \"\"},\n\t\t{\"(*List).Remove\", Method, 0, \"\"},\n\t\t{\"Element\", Type, 0, \"\"},\n\t\t{\"Element.Value\", Field, 0, \"\"},\n\t\t{\"List\", Type, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func() *List\"},\n\t},\n\t\"container/ring\": {\n\t\t{\"(*Ring).Do\", Method, 0, \"\"},\n\t\t{\"(*Ring).Len\", Method, 0, \"\"},\n\t\t{\"(*Ring).Link\", Method, 0, \"\"},\n\t\t{\"(*Ring).Move\", Method, 0, \"\"},\n\t\t{\"(*Ring).Next\", Method, 0, \"\"},\n\t\t{\"(*Ring).Prev\", Method, 0, \"\"},\n\t\t{\"(*Ring).Unlink\", Method, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(n int) *Ring\"},\n\t\t{\"Ring\", Type, 0, \"\"},\n\t\t{\"Ring.Value\", Field, 0, \"\"},\n\t},\n\t\"context\": {\n\t\t{\"(Context).Deadline\", Method, 7, \"\"},\n\t\t{\"(Context).Done\", Method, 7, \"\"},\n\t\t{\"(Context).Err\", Method, 7, \"\"},\n\t\t{\"(Context).Value\", Method, 7, \"\"},\n\t\t{\"AfterFunc\", Func, 21, \"func(ctx Context, f func()) (stop func() bool)\"},\n\t\t{\"Background\", Func, 7, \"func() Context\"},\n\t\t{\"CancelCauseFunc\", Type, 20, \"\"},\n\t\t{\"CancelFunc\", Type, 7, \"\"},\n\t\t{\"Canceled\", Var, 7, \"\"},\n\t\t{\"Cause\", Func, 20, \"func(c Context) error\"},\n\t\t{\"Context\", Type, 7, \"\"},\n\t\t{\"DeadlineExceeded\", Var, 7, \"\"},\n\t\t{\"TODO\", Func, 7, \"func() Context\"},\n\t\t{\"WithCancel\", Func, 7, \"func(parent Context) (ctx Context, cancel CancelFunc)\"},\n\t\t{\"WithCancelCause\", Func, 20, \"func(parent Context) (ctx Context, cancel CancelCauseFunc)\"},\n\t\t{\"WithDeadline\", Func, 7, \"func(parent Context, d time.Time) (Context, CancelFunc)\"},\n\t\t{\"WithDeadlineCause\", Func, 21, \"func(parent Context, d time.Time, cause error) (Context, CancelFunc)\"},\n\t\t{\"WithTimeout\", Func, 7, \"func(parent Context, timeout time.Duration) (Context, CancelFunc)\"},\n\t\t{\"WithTimeoutCause\", Func, 21, \"func(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)\"},\n\t\t{\"WithValue\", Func, 7, \"func(parent Context, key any, val any) Context\"},\n\t\t{\"WithoutCancel\", Func, 21, \"func(parent Context) Context\"},\n\t},\n\t\"crypto\": {\n\t\t{\"(Decapsulator).Decapsulate\", Method, 26, \"\"},\n\t\t{\"(Decapsulator).Encapsulator\", Method, 26, \"\"},\n\t\t{\"(Decrypter).Decrypt\", Method, 5, \"\"},\n\t\t{\"(Decrypter).Public\", Method, 5, \"\"},\n\t\t{\"(Encapsulator).Bytes\", Method, 26, \"\"},\n\t\t{\"(Encapsulator).Encapsulate\", Method, 26, \"\"},\n\t\t{\"(Hash).Available\", Method, 0, \"\"},\n\t\t{\"(Hash).HashFunc\", Method, 4, \"\"},\n\t\t{\"(Hash).New\", Method, 0, \"\"},\n\t\t{\"(Hash).Size\", Method, 0, \"\"},\n\t\t{\"(Hash).String\", Method, 15, \"\"},\n\t\t{\"(MessageSigner).Public\", Method, 25, \"\"},\n\t\t{\"(MessageSigner).Sign\", Method, 25, \"\"},\n\t\t{\"(MessageSigner).SignMessage\", Method, 25, \"\"},\n\t\t{\"(Signer).Public\", Method, 4, \"\"},\n\t\t{\"(Signer).Sign\", Method, 4, \"\"},\n\t\t{\"(SignerOpts).HashFunc\", Method, 4, \"\"},\n\t\t{\"BLAKE2b_256\", Const, 9, \"\"},\n\t\t{\"BLAKE2b_384\", Const, 9, \"\"},\n\t\t{\"BLAKE2b_512\", Const, 9, \"\"},\n\t\t{\"BLAKE2s_256\", Const, 9, \"\"},\n\t\t{\"Decapsulator\", Type, 26, \"\"},\n\t\t{\"Decrypter\", Type, 5, \"\"},\n\t\t{\"DecrypterOpts\", Type, 5, \"\"},\n\t\t{\"Encapsulator\", Type, 26, \"\"},\n\t\t{\"Hash\", Type, 0, \"\"},\n\t\t{\"MD4\", Const, 0, \"\"},\n\t\t{\"MD5\", Const, 0, \"\"},\n\t\t{\"MD5SHA1\", Const, 0, \"\"},\n\t\t{\"MessageSigner\", Type, 25, \"\"},\n\t\t{\"PrivateKey\", Type, 0, \"\"},\n\t\t{\"PublicKey\", Type, 2, \"\"},\n\t\t{\"RIPEMD160\", Const, 0, \"\"},\n\t\t{\"RegisterHash\", Func, 0, \"func(h Hash, f func() hash.Hash)\"},\n\t\t{\"SHA1\", Const, 0, \"\"},\n\t\t{\"SHA224\", Const, 0, \"\"},\n\t\t{\"SHA256\", Const, 0, \"\"},\n\t\t{\"SHA384\", Const, 0, \"\"},\n\t\t{\"SHA3_224\", Const, 4, \"\"},\n\t\t{\"SHA3_256\", Const, 4, \"\"},\n\t\t{\"SHA3_384\", Const, 4, \"\"},\n\t\t{\"SHA3_512\", Const, 4, \"\"},\n\t\t{\"SHA512\", Const, 0, \"\"},\n\t\t{\"SHA512_224\", Const, 5, \"\"},\n\t\t{\"SHA512_256\", Const, 5, \"\"},\n\t\t{\"SignMessage\", Func, 25, \"func(signer Signer, rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error)\"},\n\t\t{\"Signer\", Type, 4, \"\"},\n\t\t{\"SignerOpts\", Type, 4, \"\"},\n\t},\n\t\"crypto/aes\": {\n\t\t{\"(KeySizeError).Error\", Method, 0, \"\"},\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"KeySizeError\", Type, 0, \"\"},\n\t\t{\"NewCipher\", Func, 0, \"func(key []byte) (cipher.Block, error)\"},\n\t},\n\t\"crypto/cipher\": {\n\t\t{\"(AEAD).NonceSize\", Method, 2, \"\"},\n\t\t{\"(AEAD).Open\", Method, 2, \"\"},\n\t\t{\"(AEAD).Overhead\", Method, 2, \"\"},\n\t\t{\"(AEAD).Seal\", Method, 2, \"\"},\n\t\t{\"(Block).BlockSize\", Method, 0, \"\"},\n\t\t{\"(Block).Decrypt\", Method, 0, \"\"},\n\t\t{\"(Block).Encrypt\", Method, 0, \"\"},\n\t\t{\"(BlockMode).BlockSize\", Method, 0, \"\"},\n\t\t{\"(BlockMode).CryptBlocks\", Method, 0, \"\"},\n\t\t{\"(Stream).XORKeyStream\", Method, 0, \"\"},\n\t\t{\"(StreamReader).Read\", Method, 0, \"\"},\n\t\t{\"(StreamWriter).Close\", Method, 0, \"\"},\n\t\t{\"(StreamWriter).Write\", Method, 0, \"\"},\n\t\t{\"AEAD\", Type, 2, \"\"},\n\t\t{\"Block\", Type, 0, \"\"},\n\t\t{\"BlockMode\", Type, 0, \"\"},\n\t\t{\"NewCBCDecrypter\", Func, 0, \"func(b Block, iv []byte) BlockMode\"},\n\t\t{\"NewCBCEncrypter\", Func, 0, \"func(b Block, iv []byte) BlockMode\"},\n\t\t{\"NewCFBDecrypter\", Func, 0, \"func(block Block, iv []byte) Stream\"},\n\t\t{\"NewCFBEncrypter\", Func, 0, \"func(block Block, iv []byte) Stream\"},\n\t\t{\"NewCTR\", Func, 0, \"func(block Block, iv []byte) Stream\"},\n\t\t{\"NewGCM\", Func, 2, \"func(cipher Block) (AEAD, error)\"},\n\t\t{\"NewGCMWithNonceSize\", Func, 5, \"func(cipher Block, size int) (AEAD, error)\"},\n\t\t{\"NewGCMWithRandomNonce\", Func, 24, \"func(cipher Block) (AEAD, error)\"},\n\t\t{\"NewGCMWithTagSize\", Func, 11, \"func(cipher Block, tagSize int) (AEAD, error)\"},\n\t\t{\"NewOFB\", Func, 0, \"func(b Block, iv []byte) Stream\"},\n\t\t{\"Stream\", Type, 0, \"\"},\n\t\t{\"StreamReader\", Type, 0, \"\"},\n\t\t{\"StreamReader.R\", Field, 0, \"\"},\n\t\t{\"StreamReader.S\", Field, 0, \"\"},\n\t\t{\"StreamWriter\", Type, 0, \"\"},\n\t\t{\"StreamWriter.Err\", Field, 0, \"\"},\n\t\t{\"StreamWriter.S\", Field, 0, \"\"},\n\t\t{\"StreamWriter.W\", Field, 0, \"\"},\n\t},\n\t\"crypto/des\": {\n\t\t{\"(KeySizeError).Error\", Method, 0, \"\"},\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"KeySizeError\", Type, 0, \"\"},\n\t\t{\"NewCipher\", Func, 0, \"func(key []byte) (cipher.Block, error)\"},\n\t\t{\"NewTripleDESCipher\", Func, 0, \"func(key []byte) (cipher.Block, error)\"},\n\t},\n\t\"crypto/dsa\": {\n\t\t{\"ErrInvalidPublicKey\", Var, 0, \"\"},\n\t\t{\"GenerateKey\", Func, 0, \"func(priv *PrivateKey, rand io.Reader) error\"},\n\t\t{\"GenerateParameters\", Func, 0, \"func(params *Parameters, rand io.Reader, sizes ParameterSizes) error\"},\n\t\t{\"L1024N160\", Const, 0, \"\"},\n\t\t{\"L2048N224\", Const, 0, \"\"},\n\t\t{\"L2048N256\", Const, 0, \"\"},\n\t\t{\"L3072N256\", Const, 0, \"\"},\n\t\t{\"ParameterSizes\", Type, 0, \"\"},\n\t\t{\"Parameters\", Type, 0, \"\"},\n\t\t{\"Parameters.G\", Field, 0, \"\"},\n\t\t{\"Parameters.P\", Field, 0, \"\"},\n\t\t{\"Parameters.Q\", Field, 0, \"\"},\n\t\t{\"PrivateKey\", Type, 0, \"\"},\n\t\t{\"PrivateKey.PublicKey\", Field, 0, \"\"},\n\t\t{\"PrivateKey.X\", Field, 0, \"\"},\n\t\t{\"PublicKey\", Type, 0, \"\"},\n\t\t{\"PublicKey.Parameters\", Field, 0, \"\"},\n\t\t{\"PublicKey.Y\", Field, 0, \"\"},\n\t\t{\"Sign\", Func, 0, \"func(random io.Reader, priv *PrivateKey, hash []byte) (r *big.Int, s *big.Int, err error)\"},\n\t\t{\"Verify\", Func, 0, \"func(pub *PublicKey, hash []byte, r *big.Int, s *big.Int) bool\"},\n\t},\n\t\"crypto/ecdh\": {\n\t\t{\"(*PrivateKey).Bytes\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).Curve\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).ECDH\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).Equal\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).Public\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).PublicKey\", Method, 20, \"\"},\n\t\t{\"(*PublicKey).Bytes\", Method, 20, \"\"},\n\t\t{\"(*PublicKey).Curve\", Method, 20, \"\"},\n\t\t{\"(*PublicKey).Equal\", Method, 20, \"\"},\n\t\t{\"(Curve).GenerateKey\", Method, 20, \"\"},\n\t\t{\"(Curve).NewPrivateKey\", Method, 20, \"\"},\n\t\t{\"(Curve).NewPublicKey\", Method, 20, \"\"},\n\t\t{\"(KeyExchanger).Curve\", Method, 26, \"\"},\n\t\t{\"(KeyExchanger).ECDH\", Method, 26, \"\"},\n\t\t{\"(KeyExchanger).PublicKey\", Method, 26, \"\"},\n\t\t{\"KeyExchanger\", Type, 26, \"\"},\n\t\t{\"P256\", Func, 20, \"func() Curve\"},\n\t\t{\"P384\", Func, 20, \"func() Curve\"},\n\t\t{\"P521\", Func, 20, \"func() Curve\"},\n\t\t{\"PrivateKey\", Type, 20, \"\"},\n\t\t{\"PublicKey\", Type, 20, \"\"},\n\t\t{\"X25519\", Func, 20, \"func() Curve\"},\n\t},\n\t\"crypto/ecdsa\": {\n\t\t{\"(*PrivateKey).Bytes\", Method, 25, \"\"},\n\t\t{\"(*PrivateKey).ECDH\", Method, 20, \"\"},\n\t\t{\"(*PrivateKey).Equal\", Method, 15, \"\"},\n\t\t{\"(*PrivateKey).Public\", Method, 4, \"\"},\n\t\t{\"(*PrivateKey).Sign\", Method, 4, \"\"},\n\t\t{\"(*PublicKey).Bytes\", Method, 25, \"\"},\n\t\t{\"(*PublicKey).ECDH\", Method, 20, \"\"},\n\t\t{\"(*PublicKey).Equal\", Method, 15, \"\"},\n\t\t{\"(PrivateKey).Add\", Method, 0, \"\"},\n\t\t{\"(PrivateKey).Double\", Method, 0, \"\"},\n\t\t{\"(PrivateKey).IsOnCurve\", Method, 0, \"\"},\n\t\t{\"(PrivateKey).Params\", Method, 0, \"\"},\n\t\t{\"(PrivateKey).ScalarBaseMult\", Method, 0, \"\"},\n\t\t{\"(PrivateKey).ScalarMult\", Method, 0, \"\"},\n\t\t{\"(PublicKey).Add\", Method, 0, \"\"},\n\t\t{\"(PublicKey).Double\", Method, 0, \"\"},\n\t\t{\"(PublicKey).IsOnCurve\", Method, 0, \"\"},\n\t\t{\"(PublicKey).Params\", Method, 0, \"\"},\n\t\t{\"(PublicKey).ScalarBaseMult\", Method, 0, \"\"},\n\t\t{\"(PublicKey).ScalarMult\", Method, 0, \"\"},\n\t\t{\"GenerateKey\", Func, 0, \"func(c elliptic.Curve, r io.Reader) (*PrivateKey, error)\"},\n\t\t{\"ParseRawPrivateKey\", Func, 25, \"func(curve elliptic.Curve, data []byte) (*PrivateKey, error)\"},\n\t\t{\"ParseUncompressedPublicKey\", Func, 25, \"func(curve elliptic.Curve, data []byte) (*PublicKey, error)\"},\n\t\t{\"PrivateKey\", Type, 0, \"\"},\n\t\t{\"PrivateKey.D\", Field, 0, \"\"},\n\t\t{\"PrivateKey.PublicKey\", Field, 0, \"\"},\n\t\t{\"PublicKey\", Type, 0, \"\"},\n\t\t{\"PublicKey.Curve\", Field, 0, \"\"},\n\t\t{\"PublicKey.X\", Field, 0, \"\"},\n\t\t{\"PublicKey.Y\", Field, 0, \"\"},\n\t\t{\"Sign\", Func, 0, \"func(rand io.Reader, priv *PrivateKey, hash []byte) (r *big.Int, s *big.Int, err error)\"},\n\t\t{\"SignASN1\", Func, 15, \"func(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error)\"},\n\t\t{\"Verify\", Func, 0, \"func(pub *PublicKey, hash []byte, r *big.Int, s *big.Int) bool\"},\n\t\t{\"VerifyASN1\", Func, 15, \"func(pub *PublicKey, hash []byte, sig []byte) bool\"},\n\t},\n\t\"crypto/ed25519\": {\n\t\t{\"(*Options).HashFunc\", Method, 20, \"\"},\n\t\t{\"(PrivateKey).Equal\", Method, 15, \"\"},\n\t\t{\"(PrivateKey).Public\", Method, 13, \"\"},\n\t\t{\"(PrivateKey).Seed\", Method, 13, \"\"},\n\t\t{\"(PrivateKey).Sign\", Method, 13, \"\"},\n\t\t{\"(PublicKey).Equal\", Method, 15, \"\"},\n\t\t{\"GenerateKey\", Func, 13, \"func(random io.Reader) (PublicKey, PrivateKey, error)\"},\n\t\t{\"NewKeyFromSeed\", Func, 13, \"func(seed []byte) PrivateKey\"},\n\t\t{\"Options\", Type, 20, \"\"},\n\t\t{\"Options.Context\", Field, 20, \"\"},\n\t\t{\"Options.Hash\", Field, 20, \"\"},\n\t\t{\"PrivateKey\", Type, 13, \"\"},\n\t\t{\"PrivateKeySize\", Const, 13, \"\"},\n\t\t{\"PublicKey\", Type, 13, \"\"},\n\t\t{\"PublicKeySize\", Const, 13, \"\"},\n\t\t{\"SeedSize\", Const, 13, \"\"},\n\t\t{\"Sign\", Func, 13, \"func(privateKey PrivateKey, message []byte) []byte\"},\n\t\t{\"SignatureSize\", Const, 13, \"\"},\n\t\t{\"Verify\", Func, 13, \"func(publicKey PublicKey, message []byte, sig []byte) bool\"},\n\t\t{\"VerifyWithOptions\", Func, 20, \"func(publicKey PublicKey, message []byte, sig []byte, opts *Options) error\"},\n\t},\n\t\"crypto/elliptic\": {\n\t\t{\"(*CurveParams).Add\", Method, 0, \"\"},\n\t\t{\"(*CurveParams).Double\", Method, 0, \"\"},\n\t\t{\"(*CurveParams).IsOnCurve\", Method, 0, \"\"},\n\t\t{\"(*CurveParams).Params\", Method, 0, \"\"},\n\t\t{\"(*CurveParams).ScalarBaseMult\", Method, 0, \"\"},\n\t\t{\"(*CurveParams).ScalarMult\", Method, 0, \"\"},\n\t\t{\"(Curve).Add\", Method, 0, \"\"},\n\t\t{\"(Curve).Double\", Method, 0, \"\"},\n\t\t{\"(Curve).IsOnCurve\", Method, 0, \"\"},\n\t\t{\"(Curve).Params\", Method, 0, \"\"},\n\t\t{\"(Curve).ScalarBaseMult\", Method, 0, \"\"},\n\t\t{\"(Curve).ScalarMult\", Method, 0, \"\"},\n\t\t{\"Curve\", Type, 0, \"\"},\n\t\t{\"CurveParams\", Type, 0, \"\"},\n\t\t{\"CurveParams.B\", Field, 0, \"\"},\n\t\t{\"CurveParams.BitSize\", Field, 0, \"\"},\n\t\t{\"CurveParams.Gx\", Field, 0, \"\"},\n\t\t{\"CurveParams.Gy\", Field, 0, \"\"},\n\t\t{\"CurveParams.N\", Field, 0, \"\"},\n\t\t{\"CurveParams.Name\", Field, 5, \"\"},\n\t\t{\"CurveParams.P\", Field, 0, \"\"},\n\t\t{\"GenerateKey\", Func, 0, \"func(curve Curve, rand io.Reader) (priv []byte, x *big.Int, y *big.Int, err error)\"},\n\t\t{\"Marshal\", Func, 0, \"func(curve Curve, x *big.Int, y *big.Int) []byte\"},\n\t\t{\"MarshalCompressed\", Func, 15, \"func(curve Curve, x *big.Int, y *big.Int) []byte\"},\n\t\t{\"P224\", Func, 0, \"func() Curve\"},\n\t\t{\"P256\", Func, 0, \"func() Curve\"},\n\t\t{\"P384\", Func, 0, \"func() Curve\"},\n\t\t{\"P521\", Func, 0, \"func() Curve\"},\n\t\t{\"Unmarshal\", Func, 0, \"func(curve Curve, data []byte) (x *big.Int, y *big.Int)\"},\n\t\t{\"UnmarshalCompressed\", Func, 15, \"func(curve Curve, data []byte) (x *big.Int, y *big.Int)\"},\n\t},\n\t\"crypto/fips140\": {\n\t\t{\"Enabled\", Func, 24, \"func() bool\"},\n\t\t{\"Enforced\", Func, 26, \"func() bool\"},\n\t\t{\"Version\", Func, 26, \"func() string\"},\n\t\t{\"WithoutEnforcement\", Func, 26, \"func(f func())\"},\n\t},\n\t\"crypto/hkdf\": {\n\t\t{\"Expand\", Func, 24, \"func[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLength int) ([]byte, error)\"},\n\t\t{\"Extract\", Func, 24, \"func[H hash.Hash](h func() H, secret []byte, salt []byte) ([]byte, error)\"},\n\t\t{\"Key\", Func, 24, \"func[Hash hash.Hash](h func() Hash, secret []byte, salt []byte, info string, keyLength int) ([]byte, error)\"},\n\t},\n\t\"crypto/hmac\": {\n\t\t{\"Equal\", Func, 1, \"func(mac1 []byte, mac2 []byte) bool\"},\n\t\t{\"New\", Func, 0, \"func(h func() hash.Hash, key []byte) hash.Hash\"},\n\t},\n\t\"crypto/hpke\": {\n\t\t{\"(*Recipient).Export\", Method, 26, \"\"},\n\t\t{\"(*Recipient).Open\", Method, 26, \"\"},\n\t\t{\"(*Sender).Export\", Method, 26, \"\"},\n\t\t{\"(*Sender).Seal\", Method, 26, \"\"},\n\t\t{\"(AEAD).ID\", Method, 26, \"\"},\n\t\t{\"(KDF).ID\", Method, 26, \"\"},\n\t\t{\"(KEM).DeriveKeyPair\", Method, 26, \"\"},\n\t\t{\"(KEM).GenerateKey\", Method, 26, \"\"},\n\t\t{\"(KEM).ID\", Method, 26, \"\"},\n\t\t{\"(KEM).NewPrivateKey\", Method, 26, \"\"},\n\t\t{\"(KEM).NewPublicKey\", Method, 26, \"\"},\n\t\t{\"(PrivateKey).Bytes\", Method, 26, \"\"},\n\t\t{\"(PrivateKey).KEM\", Method, 26, \"\"},\n\t\t{\"(PrivateKey).PublicKey\", Method, 26, \"\"},\n\t\t{\"(PublicKey).Bytes\", Method, 26, \"\"},\n\t\t{\"(PublicKey).KEM\", Method, 26, \"\"},\n\t\t{\"AES128GCM\", Func, 26, \"func() AEAD\"},\n\t\t{\"AES256GCM\", Func, 26, \"func() AEAD\"},\n\t\t{\"ChaCha20Poly1305\", Func, 26, \"func() AEAD\"},\n\t\t{\"DHKEM\", Func, 26, \"func(curve ecdh.Curve) KEM\"},\n\t\t{\"ExportOnly\", Func, 26, \"func() AEAD\"},\n\t\t{\"HKDFSHA256\", Func, 26, \"func() KDF\"},\n\t\t{\"HKDFSHA384\", Func, 26, \"func() KDF\"},\n\t\t{\"HKDFSHA512\", Func, 26, \"func() KDF\"},\n\t\t{\"MLKEM1024\", Func, 26, \"func() KEM\"},\n\t\t{\"MLKEM1024P384\", Func, 26, \"func() KEM\"},\n\t\t{\"MLKEM768\", Func, 26, \"func() KEM\"},\n\t\t{\"MLKEM768P256\", Func, 26, \"func() KEM\"},\n\t\t{\"MLKEM768X25519\", Func, 26, \"func() KEM\"},\n\t\t{\"NewAEAD\", Func, 26, \"func(id uint16) (AEAD, error)\"},\n\t\t{\"NewDHKEMPrivateKey\", Func, 26, \"func(priv ecdh.KeyExchanger) (PrivateKey, error)\"},\n\t\t{\"NewDHKEMPublicKey\", Func, 26, \"func(pub *ecdh.PublicKey) (PublicKey, error)\"},\n\t\t{\"NewHybridPrivateKey\", Func, 26, \"func(pq crypto.Decapsulator, t ecdh.KeyExchanger) (PrivateKey, error)\"},\n\t\t{\"NewHybridPublicKey\", Func, 26, \"func(pq crypto.Encapsulator, t *ecdh.PublicKey) (PublicKey, error)\"},\n\t\t{\"NewKDF\", Func, 26, \"func(id uint16) (KDF, error)\"},\n\t\t{\"NewKEM\", Func, 26, \"func(id uint16) (KEM, error)\"},\n\t\t{\"NewMLKEMPrivateKey\", Func, 26, \"func(priv crypto.Decapsulator) (PrivateKey, error)\"},\n\t\t{\"NewMLKEMPublicKey\", Func, 26, \"func(pub crypto.Encapsulator) (PublicKey, error)\"},\n\t\t{\"NewRecipient\", Func, 26, \"func(enc []byte, k PrivateKey, kdf KDF, aead AEAD, info []byte) (*Recipient, error)\"},\n\t\t{\"NewSender\", Func, 26, \"func(pk PublicKey, kdf KDF, aead AEAD, info []byte) (enc []byte, s *Sender, err error)\"},\n\t\t{\"Open\", Func, 26, \"func(k PrivateKey, kdf KDF, aead AEAD, info []byte, ciphertext []byte) ([]byte, error)\"},\n\t\t{\"Recipient\", Type, 26, \"\"},\n\t\t{\"SHAKE128\", Func, 26, \"func() KDF\"},\n\t\t{\"SHAKE256\", Func, 26, \"func() KDF\"},\n\t\t{\"Seal\", Func, 26, \"func(pk PublicKey, kdf KDF, aead AEAD, info []byte, plaintext []byte) ([]byte, error)\"},\n\t\t{\"Sender\", Type, 26, \"\"},\n\t},\n\t\"crypto/md5\": {\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Sum\", Func, 2, \"func(data []byte) [16]byte\"},\n\t},\n\t\"crypto/mlkem\": {\n\t\t{\"(*DecapsulationKey1024).Bytes\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey1024).Decapsulate\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey1024).EncapsulationKey\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey1024).Encapsulator\", Method, 26, \"\"},\n\t\t{\"(*DecapsulationKey768).Bytes\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey768).Decapsulate\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey768).EncapsulationKey\", Method, 24, \"\"},\n\t\t{\"(*DecapsulationKey768).Encapsulator\", Method, 26, \"\"},\n\t\t{\"(*EncapsulationKey1024).Bytes\", Method, 24, \"\"},\n\t\t{\"(*EncapsulationKey1024).Encapsulate\", Method, 24, \"\"},\n\t\t{\"(*EncapsulationKey768).Bytes\", Method, 24, \"\"},\n\t\t{\"(*EncapsulationKey768).Encapsulate\", Method, 24, \"\"},\n\t\t{\"CiphertextSize1024\", Const, 24, \"\"},\n\t\t{\"CiphertextSize768\", Const, 24, \"\"},\n\t\t{\"DecapsulationKey1024\", Type, 24, \"\"},\n\t\t{\"DecapsulationKey768\", Type, 24, \"\"},\n\t\t{\"EncapsulationKey1024\", Type, 24, \"\"},\n\t\t{\"EncapsulationKey768\", Type, 24, \"\"},\n\t\t{\"EncapsulationKeySize1024\", Const, 24, \"\"},\n\t\t{\"EncapsulationKeySize768\", Const, 24, \"\"},\n\t\t{\"GenerateKey1024\", Func, 24, \"func() (*DecapsulationKey1024, error)\"},\n\t\t{\"GenerateKey768\", Func, 24, \"func() (*DecapsulationKey768, error)\"},\n\t\t{\"NewDecapsulationKey1024\", Func, 24, \"func(seed []byte) (*DecapsulationKey1024, error)\"},\n\t\t{\"NewDecapsulationKey768\", Func, 24, \"func(seed []byte) (*DecapsulationKey768, error)\"},\n\t\t{\"NewEncapsulationKey1024\", Func, 24, \"func(encapsulationKey []byte) (*EncapsulationKey1024, error)\"},\n\t\t{\"NewEncapsulationKey768\", Func, 24, \"func(encapsulationKey []byte) (*EncapsulationKey768, error)\"},\n\t\t{\"SeedSize\", Const, 24, \"\"},\n\t\t{\"SharedKeySize\", Const, 24, \"\"},\n\t},\n\t\"crypto/mlkem/mlkemtest\": {\n\t\t{\"Encapsulate1024\", Func, 26, \"func(ek *mlkem.EncapsulationKey1024, random []byte) (sharedKey []byte, ciphertext []byte, err error)\"},\n\t\t{\"Encapsulate768\", Func, 26, \"func(ek *mlkem.EncapsulationKey768, random []byte) (sharedKey []byte, ciphertext []byte, err error)\"},\n\t},\n\t\"crypto/pbkdf2\": {\n\t\t{\"Key\", Func, 24, \"func[Hash hash.Hash](h func() Hash, password string, salt []byte, iter int, keyLength int) ([]byte, error)\"},\n\t},\n\t\"crypto/rand\": {\n\t\t{\"Int\", Func, 0, \"func(rand io.Reader, max *big.Int) (n *big.Int, err error)\"},\n\t\t{\"Prime\", Func, 0, \"func(r io.Reader, bits int) (*big.Int, error)\"},\n\t\t{\"Read\", Func, 0, \"func(b []byte) (n int, err error)\"},\n\t\t{\"Reader\", Var, 0, \"\"},\n\t\t{\"Text\", Func, 24, \"func() string\"},\n\t},\n\t\"crypto/rc4\": {\n\t\t{\"(*Cipher).Reset\", Method, 0, \"\"},\n\t\t{\"(*Cipher).XORKeyStream\", Method, 0, \"\"},\n\t\t{\"(KeySizeError).Error\", Method, 0, \"\"},\n\t\t{\"Cipher\", Type, 0, \"\"},\n\t\t{\"KeySizeError\", Type, 0, \"\"},\n\t\t{\"NewCipher\", Func, 0, \"func(key []byte) (*Cipher, error)\"},\n\t},\n\t\"crypto/rsa\": {\n\t\t{\"(*PSSOptions).HashFunc\", Method, 4, \"\"},\n\t\t{\"(*PrivateKey).Decrypt\", Method, 5, \"\"},\n\t\t{\"(*PrivateKey).Equal\", Method, 15, \"\"},\n\t\t{\"(*PrivateKey).Precompute\", Method, 0, \"\"},\n\t\t{\"(*PrivateKey).Public\", Method, 4, \"\"},\n\t\t{\"(*PrivateKey).Sign\", Method, 4, \"\"},\n\t\t{\"(*PrivateKey).Size\", Method, 11, \"\"},\n\t\t{\"(*PrivateKey).Validate\", Method, 0, \"\"},\n\t\t{\"(*PublicKey).Equal\", Method, 15, \"\"},\n\t\t{\"(*PublicKey).Size\", Method, 11, \"\"},\n\t\t{\"CRTValue\", Type, 0, \"\"},\n\t\t{\"CRTValue.Coeff\", Field, 0, \"\"},\n\t\t{\"CRTValue.Exp\", Field, 0, \"\"},\n\t\t{\"CRTValue.R\", Field, 0, \"\"},\n\t\t{\"DecryptOAEP\", Func, 0, \"func(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)\"},\n\t\t{\"DecryptPKCS1v15\", Func, 0, \"func(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)\"},\n\t\t{\"DecryptPKCS1v15SessionKey\", Func, 0, \"func(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error\"},\n\t\t{\"EncryptOAEP\", Func, 0, \"func(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error)\"},\n\t\t{\"EncryptOAEPWithOptions\", Func, 26, \"func(random io.Reader, pub *PublicKey, msg []byte, opts *OAEPOptions) ([]byte, error)\"},\n\t\t{\"EncryptPKCS1v15\", Func, 0, \"func(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error)\"},\n\t\t{\"ErrDecryption\", Var, 0, \"\"},\n\t\t{\"ErrMessageTooLong\", Var, 0, \"\"},\n\t\t{\"ErrVerification\", Var, 0, \"\"},\n\t\t{\"GenerateKey\", Func, 0, \"func(random io.Reader, bits int) (*PrivateKey, error)\"},\n\t\t{\"GenerateMultiPrimeKey\", Func, 0, \"func(random io.Reader, nprimes int, bits int) (*PrivateKey, error)\"},\n\t\t{\"OAEPOptions\", Type, 5, \"\"},\n\t\t{\"OAEPOptions.Hash\", Field, 5, \"\"},\n\t\t{\"OAEPOptions.Label\", Field, 5, \"\"},\n\t\t{\"OAEPOptions.MGFHash\", Field, 20, \"\"},\n\t\t{\"PKCS1v15DecryptOptions\", Type, 5, \"\"},\n\t\t{\"PKCS1v15DecryptOptions.SessionKeyLen\", Field, 5, \"\"},\n\t\t{\"PSSOptions\", Type, 2, \"\"},\n\t\t{\"PSSOptions.Hash\", Field, 4, \"\"},\n\t\t{\"PSSOptions.SaltLength\", Field, 2, \"\"},\n\t\t{\"PSSSaltLengthAuto\", Const, 2, \"\"},\n\t\t{\"PSSSaltLengthEqualsHash\", Const, 2, \"\"},\n\t\t{\"PrecomputedValues\", Type, 0, \"\"},\n\t\t{\"PrecomputedValues.CRTValues\", Field, 0, \"\"},\n\t\t{\"PrecomputedValues.Dp\", Field, 0, \"\"},\n\t\t{\"PrecomputedValues.Dq\", Field, 0, \"\"},\n\t\t{\"PrecomputedValues.Qinv\", Field, 0, \"\"},\n\t\t{\"PrivateKey\", Type, 0, \"\"},\n\t\t{\"PrivateKey.D\", Field, 0, \"\"},\n\t\t{\"PrivateKey.Precomputed\", Field, 0, \"\"},\n\t\t{\"PrivateKey.Primes\", Field, 0, \"\"},\n\t\t{\"PrivateKey.PublicKey\", Field, 0, \"\"},\n\t\t{\"PublicKey\", Type, 0, \"\"},\n\t\t{\"PublicKey.E\", Field, 0, \"\"},\n\t\t{\"PublicKey.N\", Field, 0, \"\"},\n\t\t{\"SignPKCS1v15\", Func, 0, \"func(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)\"},\n\t\t{\"SignPSS\", Func, 2, \"func(random io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error)\"},\n\t\t{\"VerifyPKCS1v15\", Func, 0, \"func(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error\"},\n\t\t{\"VerifyPSS\", Func, 2, \"func(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error\"},\n\t},\n\t\"crypto/sha1\": {\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Sum\", Func, 2, \"func(data []byte) [20]byte\"},\n\t},\n\t\"crypto/sha256\": {\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"New224\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Size224\", Const, 0, \"\"},\n\t\t{\"Sum224\", Func, 2, \"func(data []byte) [28]byte\"},\n\t\t{\"Sum256\", Func, 2, \"func(data []byte) [32]byte\"},\n\t},\n\t\"crypto/sha3\": {\n\t\t{\"(*SHA3).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(*SHA3).BlockSize\", Method, 24, \"\"},\n\t\t{\"(*SHA3).Clone\", Method, 25, \"\"},\n\t\t{\"(*SHA3).MarshalBinary\", Method, 24, \"\"},\n\t\t{\"(*SHA3).Reset\", Method, 24, \"\"},\n\t\t{\"(*SHA3).Size\", Method, 24, \"\"},\n\t\t{\"(*SHA3).Sum\", Method, 24, \"\"},\n\t\t{\"(*SHA3).UnmarshalBinary\", Method, 24, \"\"},\n\t\t{\"(*SHA3).Write\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).BlockSize\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).MarshalBinary\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).Read\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).Reset\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).UnmarshalBinary\", Method, 24, \"\"},\n\t\t{\"(*SHAKE).Write\", Method, 24, \"\"},\n\t\t{\"New224\", Func, 24, \"func() *SHA3\"},\n\t\t{\"New256\", Func, 24, \"func() *SHA3\"},\n\t\t{\"New384\", Func, 24, \"func() *SHA3\"},\n\t\t{\"New512\", Func, 24, \"func() *SHA3\"},\n\t\t{\"NewCSHAKE128\", Func, 24, \"func(N []byte, S []byte) *SHAKE\"},\n\t\t{\"NewCSHAKE256\", Func, 24, \"func(N []byte, S []byte) *SHAKE\"},\n\t\t{\"NewSHAKE128\", Func, 24, \"func() *SHAKE\"},\n\t\t{\"NewSHAKE256\", Func, 24, \"func() *SHAKE\"},\n\t\t{\"SHA3\", Type, 24, \"\"},\n\t\t{\"SHAKE\", Type, 24, \"\"},\n\t\t{\"Sum224\", Func, 24, \"func(data []byte) [28]byte\"},\n\t\t{\"Sum256\", Func, 24, \"func(data []byte) [32]byte\"},\n\t\t{\"Sum384\", Func, 24, \"func(data []byte) [48]byte\"},\n\t\t{\"Sum512\", Func, 24, \"func(data []byte) [64]byte\"},\n\t\t{\"SumSHAKE128\", Func, 24, \"func(data []byte, length int) []byte\"},\n\t\t{\"SumSHAKE256\", Func, 24, \"func(data []byte, length int) []byte\"},\n\t},\n\t\"crypto/sha512\": {\n\t\t{\"BlockSize\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"New384\", Func, 0, \"func() hash.Hash\"},\n\t\t{\"New512_224\", Func, 5, \"func() hash.Hash\"},\n\t\t{\"New512_256\", Func, 5, \"func() hash.Hash\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Size224\", Const, 5, \"\"},\n\t\t{\"Size256\", Const, 5, \"\"},\n\t\t{\"Size384\", Const, 0, \"\"},\n\t\t{\"Sum384\", Func, 2, \"func(data []byte) [48]byte\"},\n\t\t{\"Sum512\", Func, 2, \"func(data []byte) [64]byte\"},\n\t\t{\"Sum512_224\", Func, 5, \"func(data []byte) [28]byte\"},\n\t\t{\"Sum512_256\", Func, 5, \"func(data []byte) [32]byte\"},\n\t},\n\t\"crypto/subtle\": {\n\t\t{\"ConstantTimeByteEq\", Func, 0, \"func(x uint8, y uint8) int\"},\n\t\t{\"ConstantTimeCompare\", Func, 0, \"func(x []byte, y []byte) int\"},\n\t\t{\"ConstantTimeCopy\", Func, 0, \"func(v int, x []byte, y []byte)\"},\n\t\t{\"ConstantTimeEq\", Func, 0, \"func(x int32, y int32) int\"},\n\t\t{\"ConstantTimeLessOrEq\", Func, 2, \"func(x int, y int) int\"},\n\t\t{\"ConstantTimeSelect\", Func, 0, \"func(v int, x int, y int) int\"},\n\t\t{\"WithDataIndependentTiming\", Func, 24, \"func(f func())\"},\n\t\t{\"XORBytes\", Func, 20, \"func(dst []byte, x []byte, y []byte) int\"},\n\t},\n\t\"crypto/tls\": {\n\t\t{\"(*CertificateRequestInfo).Context\", Method, 17, \"\"},\n\t\t{\"(*CertificateRequestInfo).SupportsCertificate\", Method, 14, \"\"},\n\t\t{\"(*CertificateVerificationError).Error\", Method, 20, \"\"},\n\t\t{\"(*CertificateVerificationError).Unwrap\", Method, 20, \"\"},\n\t\t{\"(*ClientHelloInfo).Context\", Method, 17, \"\"},\n\t\t{\"(*ClientHelloInfo).SupportsCertificate\", Method, 14, \"\"},\n\t\t{\"(*ClientSessionState).ResumptionState\", Method, 21, \"\"},\n\t\t{\"(*Config).BuildNameToCertificate\", Method, 0, \"\"},\n\t\t{\"(*Config).Clone\", Method, 8, \"\"},\n\t\t{\"(*Config).DecryptTicket\", Method, 21, \"\"},\n\t\t{\"(*Config).EncryptTicket\", Method, 21, \"\"},\n\t\t{\"(*Config).SetSessionTicketKeys\", Method, 5, \"\"},\n\t\t{\"(*Conn).Close\", Method, 0, \"\"},\n\t\t{\"(*Conn).CloseWrite\", Method, 8, \"\"},\n\t\t{\"(*Conn).ConnectionState\", Method, 0, \"\"},\n\t\t{\"(*Conn).Handshake\", Method, 0, \"\"},\n\t\t{\"(*Conn).HandshakeContext\", Method, 17, \"\"},\n\t\t{\"(*Conn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(*Conn).NetConn\", Method, 18, \"\"},\n\t\t{\"(*Conn).OCSPResponse\", Method, 0, \"\"},\n\t\t{\"(*Conn).Read\", Method, 0, \"\"},\n\t\t{\"(*Conn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(*Conn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*Conn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(*Conn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(*Conn).VerifyHostname\", Method, 0, \"\"},\n\t\t{\"(*Conn).Write\", Method, 0, \"\"},\n\t\t{\"(*ConnectionState).ExportKeyingMaterial\", Method, 11, \"\"},\n\t\t{\"(*Dialer).Dial\", Method, 15, \"\"},\n\t\t{\"(*Dialer).DialContext\", Method, 15, \"\"},\n\t\t{\"(*ECHRejectionError).Error\", Method, 23, \"\"},\n\t\t{\"(*QUICConn).Close\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).ConnectionState\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).HandleData\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).NextEvent\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).SendSessionTicket\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).SetTransportParameters\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).Start\", Method, 21, \"\"},\n\t\t{\"(*QUICConn).StoreSession\", Method, 23, \"\"},\n\t\t{\"(*SessionState).Bytes\", Method, 21, \"\"},\n\t\t{\"(AlertError).Error\", Method, 21, \"\"},\n\t\t{\"(ClientAuthType).String\", Method, 15, \"\"},\n\t\t{\"(ClientSessionCache).Get\", Method, 3, \"\"},\n\t\t{\"(ClientSessionCache).Put\", Method, 3, \"\"},\n\t\t{\"(CurveID).String\", Method, 15, \"\"},\n\t\t{\"(QUICEncryptionLevel).String\", Method, 21, \"\"},\n\t\t{\"(RecordHeaderError).Error\", Method, 6, \"\"},\n\t\t{\"(SignatureScheme).String\", Method, 15, \"\"},\n\t\t{\"AlertError\", Type, 21, \"\"},\n\t\t{\"Certificate\", Type, 0, \"\"},\n\t\t{\"Certificate.Certificate\", Field, 0, \"\"},\n\t\t{\"Certificate.Leaf\", Field, 0, \"\"},\n\t\t{\"Certificate.OCSPStaple\", Field, 0, \"\"},\n\t\t{\"Certificate.PrivateKey\", Field, 0, \"\"},\n\t\t{\"Certificate.SignedCertificateTimestamps\", Field, 5, \"\"},\n\t\t{\"Certificate.SupportedSignatureAlgorithms\", Field, 14, \"\"},\n\t\t{\"CertificateRequestInfo\", Type, 8, \"\"},\n\t\t{\"CertificateRequestInfo.AcceptableCAs\", Field, 8, \"\"},\n\t\t{\"CertificateRequestInfo.SignatureSchemes\", Field, 8, \"\"},\n\t\t{\"CertificateRequestInfo.Version\", Field, 14, \"\"},\n\t\t{\"CertificateVerificationError\", Type, 20, \"\"},\n\t\t{\"CertificateVerificationError.Err\", Field, 20, \"\"},\n\t\t{\"CertificateVerificationError.UnverifiedCertificates\", Field, 20, \"\"},\n\t\t{\"CipherSuite\", Type, 14, \"\"},\n\t\t{\"CipherSuite.ID\", Field, 14, \"\"},\n\t\t{\"CipherSuite.Insecure\", Field, 14, \"\"},\n\t\t{\"CipherSuite.Name\", Field, 14, \"\"},\n\t\t{\"CipherSuite.SupportedVersions\", Field, 14, \"\"},\n\t\t{\"CipherSuiteName\", Func, 14, \"func(id uint16) string\"},\n\t\t{\"CipherSuites\", Func, 14, \"func() []*CipherSuite\"},\n\t\t{\"Client\", Func, 0, \"func(conn net.Conn, config *Config) *Conn\"},\n\t\t{\"ClientAuthType\", Type, 0, \"\"},\n\t\t{\"ClientHelloInfo\", Type, 4, \"\"},\n\t\t{\"ClientHelloInfo.CipherSuites\", Field, 4, \"\"},\n\t\t{\"ClientHelloInfo.Conn\", Field, 8, \"\"},\n\t\t{\"ClientHelloInfo.Extensions\", Field, 24, \"\"},\n\t\t{\"ClientHelloInfo.HelloRetryRequest\", Field, 26, \"\"},\n\t\t{\"ClientHelloInfo.ServerName\", Field, 4, \"\"},\n\t\t{\"ClientHelloInfo.SignatureSchemes\", Field, 8, \"\"},\n\t\t{\"ClientHelloInfo.SupportedCurves\", Field, 4, \"\"},\n\t\t{\"ClientHelloInfo.SupportedPoints\", Field, 4, \"\"},\n\t\t{\"ClientHelloInfo.SupportedProtos\", Field, 8, \"\"},\n\t\t{\"ClientHelloInfo.SupportedVersions\", Field, 8, \"\"},\n\t\t{\"ClientSessionCache\", Type, 3, \"\"},\n\t\t{\"ClientSessionState\", Type, 3, \"\"},\n\t\t{\"Config\", Type, 0, \"\"},\n\t\t{\"Config.Certificates\", Field, 0, \"\"},\n\t\t{\"Config.CipherSuites\", Field, 0, \"\"},\n\t\t{\"Config.ClientAuth\", Field, 0, \"\"},\n\t\t{\"Config.ClientCAs\", Field, 0, \"\"},\n\t\t{\"Config.ClientSessionCache\", Field, 3, \"\"},\n\t\t{\"Config.CurvePreferences\", Field, 3, \"\"},\n\t\t{\"Config.DynamicRecordSizingDisabled\", Field, 7, \"\"},\n\t\t{\"Config.EncryptedClientHelloConfigList\", Field, 23, \"\"},\n\t\t{\"Config.EncryptedClientHelloKeys\", Field, 24, \"\"},\n\t\t{\"Config.EncryptedClientHelloRejectionVerify\", Field, 23, \"\"},\n\t\t{\"Config.GetCertificate\", Field, 4, \"\"},\n\t\t{\"Config.GetClientCertificate\", Field, 8, \"\"},\n\t\t{\"Config.GetConfigForClient\", Field, 8, \"\"},\n\t\t{\"Config.GetEncryptedClientHelloKeys\", Field, 25, \"\"},\n\t\t{\"Config.InsecureSkipVerify\", Field, 0, \"\"},\n\t\t{\"Config.KeyLogWriter\", Field, 8, \"\"},\n\t\t{\"Config.MaxVersion\", Field, 2, \"\"},\n\t\t{\"Config.MinVersion\", Field, 2, \"\"},\n\t\t{\"Config.NameToCertificate\", Field, 0, \"\"},\n\t\t{\"Config.NextProtos\", Field, 0, \"\"},\n\t\t{\"Config.PreferServerCipherSuites\", Field, 1, \"\"},\n\t\t{\"Config.Rand\", Field, 0, \"\"},\n\t\t{\"Config.Renegotiation\", Field, 7, \"\"},\n\t\t{\"Config.RootCAs\", Field, 0, \"\"},\n\t\t{\"Config.ServerName\", Field, 0, \"\"},\n\t\t{\"Config.SessionTicketKey\", Field, 1, \"\"},\n\t\t{\"Config.SessionTicketsDisabled\", Field, 1, \"\"},\n\t\t{\"Config.Time\", Field, 0, \"\"},\n\t\t{\"Config.UnwrapSession\", Field, 21, \"\"},\n\t\t{\"Config.VerifyConnection\", Field, 15, \"\"},\n\t\t{\"Config.VerifyPeerCertificate\", Field, 8, \"\"},\n\t\t{\"Config.WrapSession\", Field, 21, \"\"},\n\t\t{\"Conn\", Type, 0, \"\"},\n\t\t{\"ConnectionState\", Type, 0, \"\"},\n\t\t{\"ConnectionState.CipherSuite\", Field, 0, \"\"},\n\t\t{\"ConnectionState.CurveID\", Field, 25, \"\"},\n\t\t{\"ConnectionState.DidResume\", Field, 1, \"\"},\n\t\t{\"ConnectionState.ECHAccepted\", Field, 23, \"\"},\n\t\t{\"ConnectionState.HandshakeComplete\", Field, 0, \"\"},\n\t\t{\"ConnectionState.HelloRetryRequest\", Field, 26, \"\"},\n\t\t{\"ConnectionState.NegotiatedProtocol\", Field, 0, \"\"},\n\t\t{\"ConnectionState.NegotiatedProtocolIsMutual\", Field, 0, \"\"},\n\t\t{\"ConnectionState.OCSPResponse\", Field, 5, \"\"},\n\t\t{\"ConnectionState.PeerCertificates\", Field, 0, \"\"},\n\t\t{\"ConnectionState.ServerName\", Field, 0, \"\"},\n\t\t{\"ConnectionState.SignedCertificateTimestamps\", Field, 5, \"\"},\n\t\t{\"ConnectionState.TLSUnique\", Field, 4, \"\"},\n\t\t{\"ConnectionState.VerifiedChains\", Field, 0, \"\"},\n\t\t{\"ConnectionState.Version\", Field, 3, \"\"},\n\t\t{\"CurveID\", Type, 3, \"\"},\n\t\t{\"CurveP256\", Const, 3, \"\"},\n\t\t{\"CurveP384\", Const, 3, \"\"},\n\t\t{\"CurveP521\", Const, 3, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(network string, addr string, config *Config) (*Conn, error)\"},\n\t\t{\"DialWithDialer\", Func, 3, \"func(dialer *net.Dialer, network string, addr string, config *Config) (*Conn, error)\"},\n\t\t{\"Dialer\", Type, 15, \"\"},\n\t\t{\"Dialer.Config\", Field, 15, \"\"},\n\t\t{\"Dialer.NetDialer\", Field, 15, \"\"},\n\t\t{\"ECDSAWithP256AndSHA256\", Const, 8, \"\"},\n\t\t{\"ECDSAWithP384AndSHA384\", Const, 8, \"\"},\n\t\t{\"ECDSAWithP521AndSHA512\", Const, 8, \"\"},\n\t\t{\"ECDSAWithSHA1\", Const, 10, \"\"},\n\t\t{\"ECHRejectionError\", Type, 23, \"\"},\n\t\t{\"ECHRejectionError.RetryConfigList\", Field, 23, \"\"},\n\t\t{\"Ed25519\", Const, 13, \"\"},\n\t\t{\"EncryptedClientHelloKey\", Type, 24, \"\"},\n\t\t{\"EncryptedClientHelloKey.Config\", Field, 24, \"\"},\n\t\t{\"EncryptedClientHelloKey.PrivateKey\", Field, 24, \"\"},\n\t\t{\"EncryptedClientHelloKey.SendAsRetry\", Field, 24, \"\"},\n\t\t{\"InsecureCipherSuites\", Func, 14, \"func() []*CipherSuite\"},\n\t\t{\"Listen\", Func, 0, \"func(network string, laddr string, config *Config) (net.Listener, error)\"},\n\t\t{\"LoadX509KeyPair\", Func, 0, \"func(certFile string, keyFile string) (Certificate, error)\"},\n\t\t{\"NewLRUClientSessionCache\", Func, 3, \"func(capacity int) ClientSessionCache\"},\n\t\t{\"NewListener\", Func, 0, \"func(inner net.Listener, config *Config) net.Listener\"},\n\t\t{\"NewResumptionState\", Func, 21, \"func(ticket []byte, state *SessionState) (*ClientSessionState, error)\"},\n\t\t{\"NoClientCert\", Const, 0, \"\"},\n\t\t{\"PKCS1WithSHA1\", Const, 8, \"\"},\n\t\t{\"PKCS1WithSHA256\", Const, 8, \"\"},\n\t\t{\"PKCS1WithSHA384\", Const, 8, \"\"},\n\t\t{\"PKCS1WithSHA512\", Const, 8, \"\"},\n\t\t{\"PSSWithSHA256\", Const, 8, \"\"},\n\t\t{\"PSSWithSHA384\", Const, 8, \"\"},\n\t\t{\"PSSWithSHA512\", Const, 8, \"\"},\n\t\t{\"ParseSessionState\", Func, 21, \"func(data []byte) (*SessionState, error)\"},\n\t\t{\"QUICClient\", Func, 21, \"func(config *QUICConfig) *QUICConn\"},\n\t\t{\"QUICConfig\", Type, 21, \"\"},\n\t\t{\"QUICConfig.EnableSessionEvents\", Field, 23, \"\"},\n\t\t{\"QUICConfig.TLSConfig\", Field, 21, \"\"},\n\t\t{\"QUICConn\", Type, 21, \"\"},\n\t\t{\"QUICEncryptionLevel\", Type, 21, \"\"},\n\t\t{\"QUICEncryptionLevelApplication\", Const, 21, \"\"},\n\t\t{\"QUICEncryptionLevelEarly\", Const, 21, \"\"},\n\t\t{\"QUICEncryptionLevelHandshake\", Const, 21, \"\"},\n\t\t{\"QUICEncryptionLevelInitial\", Const, 21, \"\"},\n\t\t{\"QUICErrorEvent\", Const, 26, \"\"},\n\t\t{\"QUICEvent\", Type, 21, \"\"},\n\t\t{\"QUICEvent.Data\", Field, 21, \"\"},\n\t\t{\"QUICEvent.Err\", Field, 26, \"\"},\n\t\t{\"QUICEvent.Kind\", Field, 21, \"\"},\n\t\t{\"QUICEvent.Level\", Field, 21, \"\"},\n\t\t{\"QUICEvent.SessionState\", Field, 23, \"\"},\n\t\t{\"QUICEvent.Suite\", Field, 21, \"\"},\n\t\t{\"QUICEventKind\", Type, 21, \"\"},\n\t\t{\"QUICHandshakeDone\", Const, 21, \"\"},\n\t\t{\"QUICNoEvent\", Const, 21, \"\"},\n\t\t{\"QUICRejectedEarlyData\", Const, 21, \"\"},\n\t\t{\"QUICResumeSession\", Const, 23, \"\"},\n\t\t{\"QUICServer\", Func, 21, \"func(config *QUICConfig) *QUICConn\"},\n\t\t{\"QUICSessionTicketOptions\", Type, 21, \"\"},\n\t\t{\"QUICSessionTicketOptions.EarlyData\", Field, 21, \"\"},\n\t\t{\"QUICSessionTicketOptions.Extra\", Field, 23, \"\"},\n\t\t{\"QUICSetReadSecret\", Const, 21, \"\"},\n\t\t{\"QUICSetWriteSecret\", Const, 21, \"\"},\n\t\t{\"QUICStoreSession\", Const, 23, \"\"},\n\t\t{\"QUICTransportParameters\", Const, 21, \"\"},\n\t\t{\"QUICTransportParametersRequired\", Const, 21, \"\"},\n\t\t{\"QUICWriteData\", Const, 21, \"\"},\n\t\t{\"RecordHeaderError\", Type, 6, \"\"},\n\t\t{\"RecordHeaderError.Conn\", Field, 12, \"\"},\n\t\t{\"RecordHeaderError.Msg\", Field, 6, \"\"},\n\t\t{\"RecordHeaderError.RecordHeader\", Field, 6, \"\"},\n\t\t{\"RenegotiateFreelyAsClient\", Const, 7, \"\"},\n\t\t{\"RenegotiateNever\", Const, 7, \"\"},\n\t\t{\"RenegotiateOnceAsClient\", Const, 7, \"\"},\n\t\t{\"RenegotiationSupport\", Type, 7, \"\"},\n\t\t{\"RequestClientCert\", Const, 0, \"\"},\n\t\t{\"RequireAndVerifyClientCert\", Const, 0, \"\"},\n\t\t{\"RequireAnyClientCert\", Const, 0, \"\"},\n\t\t{\"SecP256r1MLKEM768\", Const, 26, \"\"},\n\t\t{\"SecP384r1MLKEM1024\", Const, 26, \"\"},\n\t\t{\"Server\", Func, 0, \"func(conn net.Conn, config *Config) *Conn\"},\n\t\t{\"SessionState\", Type, 21, \"\"},\n\t\t{\"SessionState.EarlyData\", Field, 21, \"\"},\n\t\t{\"SessionState.Extra\", Field, 21, \"\"},\n\t\t{\"SignatureScheme\", Type, 8, \"\"},\n\t\t{\"TLS_AES_128_GCM_SHA256\", Const, 12, \"\"},\n\t\t{\"TLS_AES_256_GCM_SHA384\", Const, 12, \"\"},\n\t\t{\"TLS_CHACHA20_POLY1305_SHA256\", Const, 12, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\", Const, 2, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\", Const, 8, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\", Const, 2, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\", Const, 2, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\", Const, 5, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305\", Const, 8, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\", Const, 14, \"\"},\n\t\t{\"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA\", Const, 2, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\", Const, 0, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\", Const, 0, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\", Const, 8, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\", Const, 2, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\", Const, 1, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\", Const, 5, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305\", Const, 8, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\", Const, 14, \"\"},\n\t\t{\"TLS_ECDHE_RSA_WITH_RC4_128_SHA\", Const, 0, \"\"},\n\t\t{\"TLS_FALLBACK_SCSV\", Const, 4, \"\"},\n\t\t{\"TLS_RSA_WITH_3DES_EDE_CBC_SHA\", Const, 0, \"\"},\n\t\t{\"TLS_RSA_WITH_AES_128_CBC_SHA\", Const, 0, \"\"},\n\t\t{\"TLS_RSA_WITH_AES_128_CBC_SHA256\", Const, 8, \"\"},\n\t\t{\"TLS_RSA_WITH_AES_128_GCM_SHA256\", Const, 6, \"\"},\n\t\t{\"TLS_RSA_WITH_AES_256_CBC_SHA\", Const, 1, \"\"},\n\t\t{\"TLS_RSA_WITH_AES_256_GCM_SHA384\", Const, 6, \"\"},\n\t\t{\"TLS_RSA_WITH_RC4_128_SHA\", Const, 0, \"\"},\n\t\t{\"VerifyClientCertIfGiven\", Const, 0, \"\"},\n\t\t{\"VersionName\", Func, 21, \"func(version uint16) string\"},\n\t\t{\"VersionSSL30\", Const, 2, \"\"},\n\t\t{\"VersionTLS10\", Const, 2, \"\"},\n\t\t{\"VersionTLS11\", Const, 2, \"\"},\n\t\t{\"VersionTLS12\", Const, 2, \"\"},\n\t\t{\"VersionTLS13\", Const, 12, \"\"},\n\t\t{\"X25519\", Const, 8, \"\"},\n\t\t{\"X25519MLKEM768\", Const, 24, \"\"},\n\t\t{\"X509KeyPair\", Func, 0, \"func(certPEMBlock []byte, keyPEMBlock []byte) (Certificate, error)\"},\n\t},\n\t\"crypto/x509\": {\n\t\t{\"(*CertPool).AddCert\", Method, 0, \"\"},\n\t\t{\"(*CertPool).AddCertWithConstraint\", Method, 22, \"\"},\n\t\t{\"(*CertPool).AppendCertsFromPEM\", Method, 0, \"\"},\n\t\t{\"(*CertPool).Clone\", Method, 19, \"\"},\n\t\t{\"(*CertPool).Equal\", Method, 19, \"\"},\n\t\t{\"(*CertPool).Subjects\", Method, 0, \"\"},\n\t\t{\"(*Certificate).CheckCRLSignature\", Method, 0, \"\"},\n\t\t{\"(*Certificate).CheckSignature\", Method, 0, \"\"},\n\t\t{\"(*Certificate).CheckSignatureFrom\", Method, 0, \"\"},\n\t\t{\"(*Certificate).CreateCRL\", Method, 0, \"\"},\n\t\t{\"(*Certificate).Equal\", Method, 0, \"\"},\n\t\t{\"(*Certificate).Verify\", Method, 0, \"\"},\n\t\t{\"(*Certificate).VerifyHostname\", Method, 0, \"\"},\n\t\t{\"(*CertificateRequest).CheckSignature\", Method, 5, \"\"},\n\t\t{\"(*OID).UnmarshalBinary\", Method, 23, \"\"},\n\t\t{\"(*OID).UnmarshalText\", Method, 23, \"\"},\n\t\t{\"(*RevocationList).CheckSignatureFrom\", Method, 19, \"\"},\n\t\t{\"(CertificateInvalidError).Error\", Method, 0, \"\"},\n\t\t{\"(ConstraintViolationError).Error\", Method, 0, \"\"},\n\t\t{\"(ExtKeyUsage).OID\", Method, 26, \"\"},\n\t\t{\"(ExtKeyUsage).String\", Method, 26, \"\"},\n\t\t{\"(HostnameError).Error\", Method, 0, \"\"},\n\t\t{\"(InsecureAlgorithmError).Error\", Method, 6, \"\"},\n\t\t{\"(KeyUsage).String\", Method, 26, \"\"},\n\t\t{\"(OID).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(OID).AppendText\", Method, 24, \"\"},\n\t\t{\"(OID).Equal\", Method, 22, \"\"},\n\t\t{\"(OID).EqualASN1OID\", Method, 22, \"\"},\n\t\t{\"(OID).MarshalBinary\", Method, 23, \"\"},\n\t\t{\"(OID).MarshalText\", Method, 23, \"\"},\n\t\t{\"(OID).String\", Method, 22, \"\"},\n\t\t{\"(PublicKeyAlgorithm).String\", Method, 10, \"\"},\n\t\t{\"(SignatureAlgorithm).String\", Method, 6, \"\"},\n\t\t{\"(SystemRootsError).Error\", Method, 1, \"\"},\n\t\t{\"(SystemRootsError).Unwrap\", Method, 16, \"\"},\n\t\t{\"(UnhandledCriticalExtension).Error\", Method, 0, \"\"},\n\t\t{\"(UnknownAuthorityError).Error\", Method, 0, \"\"},\n\t\t{\"CANotAuthorizedForExtKeyUsage\", Const, 10, \"\"},\n\t\t{\"CANotAuthorizedForThisName\", Const, 0, \"\"},\n\t\t{\"CertPool\", Type, 0, \"\"},\n\t\t{\"Certificate\", Type, 0, \"\"},\n\t\t{\"Certificate.AuthorityKeyId\", Field, 0, \"\"},\n\t\t{\"Certificate.BasicConstraintsValid\", Field, 0, \"\"},\n\t\t{\"Certificate.CRLDistributionPoints\", Field, 2, \"\"},\n\t\t{\"Certificate.DNSNames\", Field, 0, \"\"},\n\t\t{\"Certificate.EmailAddresses\", Field, 0, \"\"},\n\t\t{\"Certificate.ExcludedDNSDomains\", Field, 9, \"\"},\n\t\t{\"Certificate.ExcludedEmailAddresses\", Field, 10, \"\"},\n\t\t{\"Certificate.ExcludedIPRanges\", Field, 10, \"\"},\n\t\t{\"Certificate.ExcludedURIDomains\", Field, 10, \"\"},\n\t\t{\"Certificate.ExtKeyUsage\", Field, 0, \"\"},\n\t\t{\"Certificate.Extensions\", Field, 2, \"\"},\n\t\t{\"Certificate.ExtraExtensions\", Field, 2, \"\"},\n\t\t{\"Certificate.IPAddresses\", Field, 1, \"\"},\n\t\t{\"Certificate.InhibitAnyPolicy\", Field, 24, \"\"},\n\t\t{\"Certificate.InhibitAnyPolicyZero\", Field, 24, \"\"},\n\t\t{\"Certificate.InhibitPolicyMapping\", Field, 24, \"\"},\n\t\t{\"Certificate.InhibitPolicyMappingZero\", Field, 24, \"\"},\n\t\t{\"Certificate.IsCA\", Field, 0, \"\"},\n\t\t{\"Certificate.Issuer\", Field, 0, \"\"},\n\t\t{\"Certificate.IssuingCertificateURL\", Field, 2, \"\"},\n\t\t{\"Certificate.KeyUsage\", Field, 0, \"\"},\n\t\t{\"Certificate.MaxPathLen\", Field, 0, \"\"},\n\t\t{\"Certificate.MaxPathLenZero\", Field, 4, \"\"},\n\t\t{\"Certificate.NotAfter\", Field, 0, \"\"},\n\t\t{\"Certificate.NotBefore\", Field, 0, \"\"},\n\t\t{\"Certificate.OCSPServer\", Field, 2, \"\"},\n\t\t{\"Certificate.PermittedDNSDomains\", Field, 0, \"\"},\n\t\t{\"Certificate.PermittedDNSDomainsCritical\", Field, 0, \"\"},\n\t\t{\"Certificate.PermittedEmailAddresses\", Field, 10, \"\"},\n\t\t{\"Certificate.PermittedIPRanges\", Field, 10, \"\"},\n\t\t{\"Certificate.PermittedURIDomains\", Field, 10, \"\"},\n\t\t{\"Certificate.Policies\", Field, 22, \"\"},\n\t\t{\"Certificate.PolicyIdentifiers\", Field, 0, \"\"},\n\t\t{\"Certificate.PolicyMappings\", Field, 24, \"\"},\n\t\t{\"Certificate.PublicKey\", Field, 0, \"\"},\n\t\t{\"Certificate.PublicKeyAlgorithm\", Field, 0, \"\"},\n\t\t{\"Certificate.Raw\", Field, 0, \"\"},\n\t\t{\"Certificate.RawIssuer\", Field, 0, \"\"},\n\t\t{\"Certificate.RawSubject\", Field, 0, \"\"},\n\t\t{\"Certificate.RawSubjectPublicKeyInfo\", Field, 0, \"\"},\n\t\t{\"Certificate.RawTBSCertificate\", Field, 0, \"\"},\n\t\t{\"Certificate.RequireExplicitPolicy\", Field, 24, \"\"},\n\t\t{\"Certificate.RequireExplicitPolicyZero\", Field, 24, \"\"},\n\t\t{\"Certificate.SerialNumber\", Field, 0, \"\"},\n\t\t{\"Certificate.Signature\", Field, 0, \"\"},\n\t\t{\"Certificate.SignatureAlgorithm\", Field, 0, \"\"},\n\t\t{\"Certificate.Subject\", Field, 0, \"\"},\n\t\t{\"Certificate.SubjectKeyId\", Field, 0, \"\"},\n\t\t{\"Certificate.URIs\", Field, 10, \"\"},\n\t\t{\"Certificate.UnhandledCriticalExtensions\", Field, 5, \"\"},\n\t\t{\"Certificate.UnknownExtKeyUsage\", Field, 0, \"\"},\n\t\t{\"Certificate.Version\", Field, 0, \"\"},\n\t\t{\"CertificateInvalidError\", Type, 0, \"\"},\n\t\t{\"CertificateInvalidError.Cert\", Field, 0, \"\"},\n\t\t{\"CertificateInvalidError.Detail\", Field, 10, \"\"},\n\t\t{\"CertificateInvalidError.Reason\", Field, 0, \"\"},\n\t\t{\"CertificateRequest\", Type, 3, \"\"},\n\t\t{\"CertificateRequest.Attributes\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.DNSNames\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.EmailAddresses\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.Extensions\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.ExtraExtensions\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.IPAddresses\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.PublicKey\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.PublicKeyAlgorithm\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.Raw\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.RawSubject\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.RawSubjectPublicKeyInfo\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.RawTBSCertificateRequest\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.Signature\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.SignatureAlgorithm\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.Subject\", Field, 3, \"\"},\n\t\t{\"CertificateRequest.URIs\", Field, 10, \"\"},\n\t\t{\"CertificateRequest.Version\", Field, 3, \"\"},\n\t\t{\"ConstraintViolationError\", Type, 0, \"\"},\n\t\t{\"CreateCertificate\", Func, 0, \"func(rand io.Reader, template *Certificate, parent *Certificate, pub any, priv any) ([]byte, error)\"},\n\t\t{\"CreateCertificateRequest\", Func, 3, \"func(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error)\"},\n\t\t{\"CreateRevocationList\", Func, 15, \"func(rand io.Reader, template *RevocationList, issuer *Certificate, priv crypto.Signer) ([]byte, error)\"},\n\t\t{\"DSA\", Const, 0, \"\"},\n\t\t{\"DSAWithSHA1\", Const, 0, \"\"},\n\t\t{\"DSAWithSHA256\", Const, 0, \"\"},\n\t\t{\"DecryptPEMBlock\", Func, 1, \"func(b *pem.Block, password []byte) ([]byte, error)\"},\n\t\t{\"ECDSA\", Const, 1, \"\"},\n\t\t{\"ECDSAWithSHA1\", Const, 1, \"\"},\n\t\t{\"ECDSAWithSHA256\", Const, 1, \"\"},\n\t\t{\"ECDSAWithSHA384\", Const, 1, \"\"},\n\t\t{\"ECDSAWithSHA512\", Const, 1, \"\"},\n\t\t{\"Ed25519\", Const, 13, \"\"},\n\t\t{\"EncryptPEMBlock\", Func, 1, \"func(rand io.Reader, blockType string, data []byte, password []byte, alg PEMCipher) (*pem.Block, error)\"},\n\t\t{\"ErrUnsupportedAlgorithm\", Var, 0, \"\"},\n\t\t{\"Expired\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsage\", Type, 0, \"\"},\n\t\t{\"ExtKeyUsageAny\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageClientAuth\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageCodeSigning\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageEmailProtection\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageIPSECEndSystem\", Const, 1, \"\"},\n\t\t{\"ExtKeyUsageIPSECTunnel\", Const, 1, \"\"},\n\t\t{\"ExtKeyUsageIPSECUser\", Const, 1, \"\"},\n\t\t{\"ExtKeyUsageMicrosoftCommercialCodeSigning\", Const, 10, \"\"},\n\t\t{\"ExtKeyUsageMicrosoftKernelCodeSigning\", Const, 10, \"\"},\n\t\t{\"ExtKeyUsageMicrosoftServerGatedCrypto\", Const, 1, \"\"},\n\t\t{\"ExtKeyUsageNetscapeServerGatedCrypto\", Const, 1, \"\"},\n\t\t{\"ExtKeyUsageOCSPSigning\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageServerAuth\", Const, 0, \"\"},\n\t\t{\"ExtKeyUsageTimeStamping\", Const, 0, \"\"},\n\t\t{\"HostnameError\", Type, 0, \"\"},\n\t\t{\"HostnameError.Certificate\", Field, 0, \"\"},\n\t\t{\"HostnameError.Host\", Field, 0, \"\"},\n\t\t{\"IncompatibleUsage\", Const, 1, \"\"},\n\t\t{\"IncorrectPasswordError\", Var, 1, \"\"},\n\t\t{\"InsecureAlgorithmError\", Type, 6, \"\"},\n\t\t{\"InvalidReason\", Type, 0, \"\"},\n\t\t{\"IsEncryptedPEMBlock\", Func, 1, \"func(b *pem.Block) bool\"},\n\t\t{\"KeyUsage\", Type, 0, \"\"},\n\t\t{\"KeyUsageCRLSign\", Const, 0, \"\"},\n\t\t{\"KeyUsageCertSign\", Const, 0, \"\"},\n\t\t{\"KeyUsageContentCommitment\", Const, 0, \"\"},\n\t\t{\"KeyUsageDataEncipherment\", Const, 0, \"\"},\n\t\t{\"KeyUsageDecipherOnly\", Const, 0, \"\"},\n\t\t{\"KeyUsageDigitalSignature\", Const, 0, \"\"},\n\t\t{\"KeyUsageEncipherOnly\", Const, 0, \"\"},\n\t\t{\"KeyUsageKeyAgreement\", Const, 0, \"\"},\n\t\t{\"KeyUsageKeyEncipherment\", Const, 0, \"\"},\n\t\t{\"MD2WithRSA\", Const, 0, \"\"},\n\t\t{\"MD5WithRSA\", Const, 0, \"\"},\n\t\t{\"MarshalECPrivateKey\", Func, 2, \"func(key *ecdsa.PrivateKey) ([]byte, error)\"},\n\t\t{\"MarshalPKCS1PrivateKey\", Func, 0, \"func(key *rsa.PrivateKey) []byte\"},\n\t\t{\"MarshalPKCS1PublicKey\", Func, 10, \"func(key *rsa.PublicKey) []byte\"},\n\t\t{\"MarshalPKCS8PrivateKey\", Func, 10, \"func(key any) ([]byte, error)\"},\n\t\t{\"MarshalPKIXPublicKey\", Func, 0, \"func(pub any) ([]byte, error)\"},\n\t\t{\"NameConstraintsWithoutSANs\", Const, 10, \"\"},\n\t\t{\"NameMismatch\", Const, 8, \"\"},\n\t\t{\"NewCertPool\", Func, 0, \"func() *CertPool\"},\n\t\t{\"NoValidChains\", Const, 24, \"\"},\n\t\t{\"NotAuthorizedToSign\", Const, 0, \"\"},\n\t\t{\"OID\", Type, 22, \"\"},\n\t\t{\"OIDFromASN1OID\", Func, 26, \"func(asn1OID asn1.ObjectIdentifier) (OID, error)\"},\n\t\t{\"OIDFromInts\", Func, 22, \"func(oid []uint64) (OID, error)\"},\n\t\t{\"PEMCipher\", Type, 1, \"\"},\n\t\t{\"PEMCipher3DES\", Const, 1, \"\"},\n\t\t{\"PEMCipherAES128\", Const, 1, \"\"},\n\t\t{\"PEMCipherAES192\", Const, 1, \"\"},\n\t\t{\"PEMCipherAES256\", Const, 1, \"\"},\n\t\t{\"PEMCipherDES\", Const, 1, \"\"},\n\t\t{\"ParseCRL\", Func, 0, \"func(crlBytes []byte) (*pkix.CertificateList, error)\"},\n\t\t{\"ParseCertificate\", Func, 0, \"func(der []byte) (*Certificate, error)\"},\n\t\t{\"ParseCertificateRequest\", Func, 3, \"func(asn1Data []byte) (*CertificateRequest, error)\"},\n\t\t{\"ParseCertificates\", Func, 0, \"func(der []byte) ([]*Certificate, error)\"},\n\t\t{\"ParseDERCRL\", Func, 0, \"func(derBytes []byte) (*pkix.CertificateList, error)\"},\n\t\t{\"ParseECPrivateKey\", Func, 1, \"func(der []byte) (*ecdsa.PrivateKey, error)\"},\n\t\t{\"ParseOID\", Func, 23, \"func(oid string) (OID, error)\"},\n\t\t{\"ParsePKCS1PrivateKey\", Func, 0, \"func(der []byte) (*rsa.PrivateKey, error)\"},\n\t\t{\"ParsePKCS1PublicKey\", Func, 10, \"func(der []byte) (*rsa.PublicKey, error)\"},\n\t\t{\"ParsePKCS8PrivateKey\", Func, 0, \"func(der []byte) (key any, err error)\"},\n\t\t{\"ParsePKIXPublicKey\", Func, 0, \"func(derBytes []byte) (pub any, err error)\"},\n\t\t{\"ParseRevocationList\", Func, 19, \"func(der []byte) (*RevocationList, error)\"},\n\t\t{\"PolicyMapping\", Type, 24, \"\"},\n\t\t{\"PolicyMapping.IssuerDomainPolicy\", Field, 24, \"\"},\n\t\t{\"PolicyMapping.SubjectDomainPolicy\", Field, 24, \"\"},\n\t\t{\"PublicKeyAlgorithm\", Type, 0, \"\"},\n\t\t{\"PureEd25519\", Const, 13, \"\"},\n\t\t{\"RSA\", Const, 0, \"\"},\n\t\t{\"RevocationList\", Type, 15, \"\"},\n\t\t{\"RevocationList.AuthorityKeyId\", Field, 19, \"\"},\n\t\t{\"RevocationList.Extensions\", Field, 19, \"\"},\n\t\t{\"RevocationList.ExtraExtensions\", Field, 15, \"\"},\n\t\t{\"RevocationList.Issuer\", Field, 19, \"\"},\n\t\t{\"RevocationList.NextUpdate\", Field, 15, \"\"},\n\t\t{\"RevocationList.Number\", Field, 15, \"\"},\n\t\t{\"RevocationList.Raw\", Field, 19, \"\"},\n\t\t{\"RevocationList.RawIssuer\", Field, 19, \"\"},\n\t\t{\"RevocationList.RawTBSRevocationList\", Field, 19, \"\"},\n\t\t{\"RevocationList.RevokedCertificateEntries\", Field, 21, \"\"},\n\t\t{\"RevocationList.RevokedCertificates\", Field, 15, \"\"},\n\t\t{\"RevocationList.Signature\", Field, 19, \"\"},\n\t\t{\"RevocationList.SignatureAlgorithm\", Field, 15, \"\"},\n\t\t{\"RevocationList.ThisUpdate\", Field, 15, \"\"},\n\t\t{\"RevocationListEntry\", Type, 21, \"\"},\n\t\t{\"RevocationListEntry.Extensions\", Field, 21, \"\"},\n\t\t{\"RevocationListEntry.ExtraExtensions\", Field, 21, \"\"},\n\t\t{\"RevocationListEntry.Raw\", Field, 21, \"\"},\n\t\t{\"RevocationListEntry.ReasonCode\", Field, 21, \"\"},\n\t\t{\"RevocationListEntry.RevocationTime\", Field, 21, \"\"},\n\t\t{\"RevocationListEntry.SerialNumber\", Field, 21, \"\"},\n\t\t{\"SHA1WithRSA\", Const, 0, \"\"},\n\t\t{\"SHA256WithRSA\", Const, 0, \"\"},\n\t\t{\"SHA256WithRSAPSS\", Const, 8, \"\"},\n\t\t{\"SHA384WithRSA\", Const, 0, \"\"},\n\t\t{\"SHA384WithRSAPSS\", Const, 8, \"\"},\n\t\t{\"SHA512WithRSA\", Const, 0, \"\"},\n\t\t{\"SHA512WithRSAPSS\", Const, 8, \"\"},\n\t\t{\"SetFallbackRoots\", Func, 20, \"func(roots *CertPool)\"},\n\t\t{\"SignatureAlgorithm\", Type, 0, \"\"},\n\t\t{\"SystemCertPool\", Func, 7, \"func() (*CertPool, error)\"},\n\t\t{\"SystemRootsError\", Type, 1, \"\"},\n\t\t{\"SystemRootsError.Err\", Field, 7, \"\"},\n\t\t{\"TooManyConstraints\", Const, 10, \"\"},\n\t\t{\"TooManyIntermediates\", Const, 0, \"\"},\n\t\t{\"UnconstrainedName\", Const, 10, \"\"},\n\t\t{\"UnhandledCriticalExtension\", Type, 0, \"\"},\n\t\t{\"UnknownAuthorityError\", Type, 0, \"\"},\n\t\t{\"UnknownAuthorityError.Cert\", Field, 8, \"\"},\n\t\t{\"UnknownPublicKeyAlgorithm\", Const, 0, \"\"},\n\t\t{\"UnknownSignatureAlgorithm\", Const, 0, \"\"},\n\t\t{\"VerifyOptions\", Type, 0, \"\"},\n\t\t{\"VerifyOptions.CertificatePolicies\", Field, 24, \"\"},\n\t\t{\"VerifyOptions.CurrentTime\", Field, 0, \"\"},\n\t\t{\"VerifyOptions.DNSName\", Field, 0, \"\"},\n\t\t{\"VerifyOptions.Intermediates\", Field, 0, \"\"},\n\t\t{\"VerifyOptions.KeyUsages\", Field, 1, \"\"},\n\t\t{\"VerifyOptions.MaxConstraintComparisions\", Field, 10, \"\"},\n\t\t{\"VerifyOptions.Roots\", Field, 0, \"\"},\n\t},\n\t\"crypto/x509/pkix\": {\n\t\t{\"(*CertificateList).HasExpired\", Method, 0, \"\"},\n\t\t{\"(*Name).FillFromRDNSequence\", Method, 0, \"\"},\n\t\t{\"(Name).String\", Method, 10, \"\"},\n\t\t{\"(Name).ToRDNSequence\", Method, 0, \"\"},\n\t\t{\"(RDNSequence).String\", Method, 10, \"\"},\n\t\t{\"AlgorithmIdentifier\", Type, 0, \"\"},\n\t\t{\"AlgorithmIdentifier.Algorithm\", Field, 0, \"\"},\n\t\t{\"AlgorithmIdentifier.Parameters\", Field, 0, \"\"},\n\t\t{\"AttributeTypeAndValue\", Type, 0, \"\"},\n\t\t{\"AttributeTypeAndValue.Type\", Field, 0, \"\"},\n\t\t{\"AttributeTypeAndValue.Value\", Field, 0, \"\"},\n\t\t{\"AttributeTypeAndValueSET\", Type, 3, \"\"},\n\t\t{\"AttributeTypeAndValueSET.Type\", Field, 3, \"\"},\n\t\t{\"AttributeTypeAndValueSET.Value\", Field, 3, \"\"},\n\t\t{\"CertificateList\", Type, 0, \"\"},\n\t\t{\"CertificateList.SignatureAlgorithm\", Field, 0, \"\"},\n\t\t{\"CertificateList.SignatureValue\", Field, 0, \"\"},\n\t\t{\"CertificateList.TBSCertList\", Field, 0, \"\"},\n\t\t{\"Extension\", Type, 0, \"\"},\n\t\t{\"Extension.Critical\", Field, 0, \"\"},\n\t\t{\"Extension.Id\", Field, 0, \"\"},\n\t\t{\"Extension.Value\", Field, 0, \"\"},\n\t\t{\"Name\", Type, 0, \"\"},\n\t\t{\"Name.CommonName\", Field, 0, \"\"},\n\t\t{\"Name.Country\", Field, 0, \"\"},\n\t\t{\"Name.ExtraNames\", Field, 5, \"\"},\n\t\t{\"Name.Locality\", Field, 0, \"\"},\n\t\t{\"Name.Names\", Field, 0, \"\"},\n\t\t{\"Name.Organization\", Field, 0, \"\"},\n\t\t{\"Name.OrganizationalUnit\", Field, 0, \"\"},\n\t\t{\"Name.PostalCode\", Field, 0, \"\"},\n\t\t{\"Name.Province\", Field, 0, \"\"},\n\t\t{\"Name.SerialNumber\", Field, 0, \"\"},\n\t\t{\"Name.StreetAddress\", Field, 0, \"\"},\n\t\t{\"RDNSequence\", Type, 0, \"\"},\n\t\t{\"RelativeDistinguishedNameSET\", Type, 0, \"\"},\n\t\t{\"RevokedCertificate\", Type, 0, \"\"},\n\t\t{\"RevokedCertificate.Extensions\", Field, 0, \"\"},\n\t\t{\"RevokedCertificate.RevocationTime\", Field, 0, \"\"},\n\t\t{\"RevokedCertificate.SerialNumber\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList\", Type, 0, \"\"},\n\t\t{\"TBSCertificateList.Extensions\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.Issuer\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.NextUpdate\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.Raw\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.RevokedCertificates\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.Signature\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.ThisUpdate\", Field, 0, \"\"},\n\t\t{\"TBSCertificateList.Version\", Field, 0, \"\"},\n\t},\n\t\"database/sql\": {\n\t\t{\"(*ColumnType).DatabaseTypeName\", Method, 8, \"\"},\n\t\t{\"(*ColumnType).DecimalSize\", Method, 8, \"\"},\n\t\t{\"(*ColumnType).Length\", Method, 8, \"\"},\n\t\t{\"(*ColumnType).Name\", Method, 8, \"\"},\n\t\t{\"(*ColumnType).Nullable\", Method, 8, \"\"},\n\t\t{\"(*ColumnType).ScanType\", Method, 8, \"\"},\n\t\t{\"(*Conn).BeginTx\", Method, 9, \"\"},\n\t\t{\"(*Conn).Close\", Method, 9, \"\"},\n\t\t{\"(*Conn).ExecContext\", Method, 9, \"\"},\n\t\t{\"(*Conn).PingContext\", Method, 9, \"\"},\n\t\t{\"(*Conn).PrepareContext\", Method, 9, \"\"},\n\t\t{\"(*Conn).QueryContext\", Method, 9, \"\"},\n\t\t{\"(*Conn).QueryRowContext\", Method, 9, \"\"},\n\t\t{\"(*Conn).Raw\", Method, 13, \"\"},\n\t\t{\"(*DB).Begin\", Method, 0, \"\"},\n\t\t{\"(*DB).BeginTx\", Method, 8, \"\"},\n\t\t{\"(*DB).Close\", Method, 0, \"\"},\n\t\t{\"(*DB).Conn\", Method, 9, \"\"},\n\t\t{\"(*DB).Driver\", Method, 0, \"\"},\n\t\t{\"(*DB).Exec\", Method, 0, \"\"},\n\t\t{\"(*DB).ExecContext\", Method, 8, \"\"},\n\t\t{\"(*DB).Ping\", Method, 1, \"\"},\n\t\t{\"(*DB).PingContext\", Method, 8, \"\"},\n\t\t{\"(*DB).Prepare\", Method, 0, \"\"},\n\t\t{\"(*DB).PrepareContext\", Method, 8, \"\"},\n\t\t{\"(*DB).Query\", Method, 0, \"\"},\n\t\t{\"(*DB).QueryContext\", Method, 8, \"\"},\n\t\t{\"(*DB).QueryRow\", Method, 0, \"\"},\n\t\t{\"(*DB).QueryRowContext\", Method, 8, \"\"},\n\t\t{\"(*DB).SetConnMaxIdleTime\", Method, 15, \"\"},\n\t\t{\"(*DB).SetConnMaxLifetime\", Method, 6, \"\"},\n\t\t{\"(*DB).SetMaxIdleConns\", Method, 1, \"\"},\n\t\t{\"(*DB).SetMaxOpenConns\", Method, 2, \"\"},\n\t\t{\"(*DB).Stats\", Method, 5, \"\"},\n\t\t{\"(*Null).Scan\", Method, 22, \"\"},\n\t\t{\"(*NullBool).Scan\", Method, 0, \"\"},\n\t\t{\"(*NullByte).Scan\", Method, 17, \"\"},\n\t\t{\"(*NullFloat64).Scan\", Method, 0, \"\"},\n\t\t{\"(*NullInt16).Scan\", Method, 17, \"\"},\n\t\t{\"(*NullInt32).Scan\", Method, 13, \"\"},\n\t\t{\"(*NullInt64).Scan\", Method, 0, \"\"},\n\t\t{\"(*NullString).Scan\", Method, 0, \"\"},\n\t\t{\"(*NullTime).Scan\", Method, 13, \"\"},\n\t\t{\"(*Row).Err\", Method, 15, \"\"},\n\t\t{\"(*Row).Scan\", Method, 0, \"\"},\n\t\t{\"(*Rows).Close\", Method, 0, \"\"},\n\t\t{\"(*Rows).ColumnTypes\", Method, 8, \"\"},\n\t\t{\"(*Rows).Columns\", Method, 0, \"\"},\n\t\t{\"(*Rows).Err\", Method, 0, \"\"},\n\t\t{\"(*Rows).Next\", Method, 0, \"\"},\n\t\t{\"(*Rows).NextResultSet\", Method, 8, \"\"},\n\t\t{\"(*Rows).Scan\", Method, 0, \"\"},\n\t\t{\"(*Stmt).Close\", Method, 0, \"\"},\n\t\t{\"(*Stmt).Exec\", Method, 0, \"\"},\n\t\t{\"(*Stmt).ExecContext\", Method, 8, \"\"},\n\t\t{\"(*Stmt).Query\", Method, 0, \"\"},\n\t\t{\"(*Stmt).QueryContext\", Method, 8, \"\"},\n\t\t{\"(*Stmt).QueryRow\", Method, 0, \"\"},\n\t\t{\"(*Stmt).QueryRowContext\", Method, 8, \"\"},\n\t\t{\"(*Tx).Commit\", Method, 0, \"\"},\n\t\t{\"(*Tx).Exec\", Method, 0, \"\"},\n\t\t{\"(*Tx).ExecContext\", Method, 8, \"\"},\n\t\t{\"(*Tx).Prepare\", Method, 0, \"\"},\n\t\t{\"(*Tx).PrepareContext\", Method, 8, \"\"},\n\t\t{\"(*Tx).Query\", Method, 0, \"\"},\n\t\t{\"(*Tx).QueryContext\", Method, 8, \"\"},\n\t\t{\"(*Tx).QueryRow\", Method, 0, \"\"},\n\t\t{\"(*Tx).QueryRowContext\", Method, 8, \"\"},\n\t\t{\"(*Tx).Rollback\", Method, 0, \"\"},\n\t\t{\"(*Tx).Stmt\", Method, 0, \"\"},\n\t\t{\"(*Tx).StmtContext\", Method, 8, \"\"},\n\t\t{\"(IsolationLevel).String\", Method, 11, \"\"},\n\t\t{\"(Null).Value\", Method, 22, \"\"},\n\t\t{\"(NullBool).Value\", Method, 0, \"\"},\n\t\t{\"(NullByte).Value\", Method, 17, \"\"},\n\t\t{\"(NullFloat64).Value\", Method, 0, \"\"},\n\t\t{\"(NullInt16).Value\", Method, 17, \"\"},\n\t\t{\"(NullInt32).Value\", Method, 13, \"\"},\n\t\t{\"(NullInt64).Value\", Method, 0, \"\"},\n\t\t{\"(NullString).Value\", Method, 0, \"\"},\n\t\t{\"(NullTime).Value\", Method, 13, \"\"},\n\t\t{\"(Result).LastInsertId\", Method, 0, \"\"},\n\t\t{\"(Result).RowsAffected\", Method, 0, \"\"},\n\t\t{\"(Scanner).Scan\", Method, 0, \"\"},\n\t\t{\"ColumnType\", Type, 8, \"\"},\n\t\t{\"Conn\", Type, 9, \"\"},\n\t\t{\"DB\", Type, 0, \"\"},\n\t\t{\"DBStats\", Type, 5, \"\"},\n\t\t{\"DBStats.Idle\", Field, 11, \"\"},\n\t\t{\"DBStats.InUse\", Field, 11, \"\"},\n\t\t{\"DBStats.MaxIdleClosed\", Field, 11, \"\"},\n\t\t{\"DBStats.MaxIdleTimeClosed\", Field, 15, \"\"},\n\t\t{\"DBStats.MaxLifetimeClosed\", Field, 11, \"\"},\n\t\t{\"DBStats.MaxOpenConnections\", Field, 11, \"\"},\n\t\t{\"DBStats.OpenConnections\", Field, 5, \"\"},\n\t\t{\"DBStats.WaitCount\", Field, 11, \"\"},\n\t\t{\"DBStats.WaitDuration\", Field, 11, \"\"},\n\t\t{\"Drivers\", Func, 4, \"func() []string\"},\n\t\t{\"ErrConnDone\", Var, 9, \"\"},\n\t\t{\"ErrNoRows\", Var, 0, \"\"},\n\t\t{\"ErrTxDone\", Var, 0, \"\"},\n\t\t{\"IsolationLevel\", Type, 8, \"\"},\n\t\t{\"LevelDefault\", Const, 8, \"\"},\n\t\t{\"LevelLinearizable\", Const, 8, \"\"},\n\t\t{\"LevelReadCommitted\", Const, 8, \"\"},\n\t\t{\"LevelReadUncommitted\", Const, 8, \"\"},\n\t\t{\"LevelRepeatableRead\", Const, 8, \"\"},\n\t\t{\"LevelSerializable\", Const, 8, \"\"},\n\t\t{\"LevelSnapshot\", Const, 8, \"\"},\n\t\t{\"LevelWriteCommitted\", Const, 8, \"\"},\n\t\t{\"Named\", Func, 8, \"func(name string, value any) NamedArg\"},\n\t\t{\"NamedArg\", Type, 8, \"\"},\n\t\t{\"NamedArg.Name\", Field, 8, \"\"},\n\t\t{\"NamedArg.Value\", Field, 8, \"\"},\n\t\t{\"Null\", Type, 22, \"\"},\n\t\t{\"NullBool\", Type, 0, \"\"},\n\t\t{\"NullBool.Bool\", Field, 0, \"\"},\n\t\t{\"NullBool.Valid\", Field, 0, \"\"},\n\t\t{\"NullByte\", Type, 17, \"\"},\n\t\t{\"NullByte.Byte\", Field, 17, \"\"},\n\t\t{\"NullByte.Valid\", Field, 17, \"\"},\n\t\t{\"NullFloat64\", Type, 0, \"\"},\n\t\t{\"NullFloat64.Float64\", Field, 0, \"\"},\n\t\t{\"NullFloat64.Valid\", Field, 0, \"\"},\n\t\t{\"NullInt16\", Type, 17, \"\"},\n\t\t{\"NullInt16.Int16\", Field, 17, \"\"},\n\t\t{\"NullInt16.Valid\", Field, 17, \"\"},\n\t\t{\"NullInt32\", Type, 13, \"\"},\n\t\t{\"NullInt32.Int32\", Field, 13, \"\"},\n\t\t{\"NullInt32.Valid\", Field, 13, \"\"},\n\t\t{\"NullInt64\", Type, 0, \"\"},\n\t\t{\"NullInt64.Int64\", Field, 0, \"\"},\n\t\t{\"NullInt64.Valid\", Field, 0, \"\"},\n\t\t{\"NullString\", Type, 0, \"\"},\n\t\t{\"NullString.String\", Field, 0, \"\"},\n\t\t{\"NullString.Valid\", Field, 0, \"\"},\n\t\t{\"NullTime\", Type, 13, \"\"},\n\t\t{\"NullTime.Time\", Field, 13, \"\"},\n\t\t{\"NullTime.Valid\", Field, 13, \"\"},\n\t\t{\"Open\", Func, 0, \"func(driverName string, dataSourceName string) (*DB, error)\"},\n\t\t{\"OpenDB\", Func, 10, \"func(c driver.Connector) *DB\"},\n\t\t{\"Out\", Type, 9, \"\"},\n\t\t{\"Out.Dest\", Field, 9, \"\"},\n\t\t{\"Out.In\", Field, 9, \"\"},\n\t\t{\"RawBytes\", Type, 0, \"\"},\n\t\t{\"Register\", Func, 0, \"func(name string, driver driver.Driver)\"},\n\t\t{\"Result\", Type, 0, \"\"},\n\t\t{\"Row\", Type, 0, \"\"},\n\t\t{\"Rows\", Type, 0, \"\"},\n\t\t{\"Scanner\", Type, 0, \"\"},\n\t\t{\"Stmt\", Type, 0, \"\"},\n\t\t{\"Tx\", Type, 0, \"\"},\n\t\t{\"TxOptions\", Type, 8, \"\"},\n\t\t{\"TxOptions.Isolation\", Field, 8, \"\"},\n\t\t{\"TxOptions.ReadOnly\", Field, 8, \"\"},\n\t},\n\t\"database/sql/driver\": {\n\t\t{\"(ColumnConverter).ColumnConverter\", Method, 0, \"\"},\n\t\t{\"(Conn).Begin\", Method, 0, \"\"},\n\t\t{\"(Conn).Close\", Method, 0, \"\"},\n\t\t{\"(Conn).Prepare\", Method, 0, \"\"},\n\t\t{\"(ConnBeginTx).BeginTx\", Method, 8, \"\"},\n\t\t{\"(ConnPrepareContext).PrepareContext\", Method, 8, \"\"},\n\t\t{\"(Connector).Connect\", Method, 10, \"\"},\n\t\t{\"(Connector).Driver\", Method, 10, \"\"},\n\t\t{\"(Driver).Open\", Method, 0, \"\"},\n\t\t{\"(DriverContext).OpenConnector\", Method, 10, \"\"},\n\t\t{\"(Execer).Exec\", Method, 0, \"\"},\n\t\t{\"(ExecerContext).ExecContext\", Method, 8, \"\"},\n\t\t{\"(NamedValueChecker).CheckNamedValue\", Method, 9, \"\"},\n\t\t{\"(NotNull).ConvertValue\", Method, 0, \"\"},\n\t\t{\"(Null).ConvertValue\", Method, 0, \"\"},\n\t\t{\"(Pinger).Ping\", Method, 8, \"\"},\n\t\t{\"(Queryer).Query\", Method, 1, \"\"},\n\t\t{\"(QueryerContext).QueryContext\", Method, 8, \"\"},\n\t\t{\"(Result).LastInsertId\", Method, 0, \"\"},\n\t\t{\"(Result).RowsAffected\", Method, 0, \"\"},\n\t\t{\"(Rows).Close\", Method, 0, \"\"},\n\t\t{\"(Rows).Columns\", Method, 0, \"\"},\n\t\t{\"(Rows).Next\", Method, 0, \"\"},\n\t\t{\"(RowsAffected).LastInsertId\", Method, 0, \"\"},\n\t\t{\"(RowsAffected).RowsAffected\", Method, 0, \"\"},\n\t\t{\"(RowsColumnTypeDatabaseTypeName).Close\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeDatabaseTypeName).ColumnTypeDatabaseTypeName\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeDatabaseTypeName).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeDatabaseTypeName).Next\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeLength).Close\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeLength).ColumnTypeLength\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeLength).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeLength).Next\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeNullable).Close\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeNullable).ColumnTypeNullable\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeNullable).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeNullable).Next\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypePrecisionScale).Close\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypePrecisionScale).ColumnTypePrecisionScale\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypePrecisionScale).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypePrecisionScale).Next\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeScanType).Close\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeScanType).ColumnTypeScanType\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeScanType).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsColumnTypeScanType).Next\", Method, 8, \"\"},\n\t\t{\"(RowsNextResultSet).Close\", Method, 8, \"\"},\n\t\t{\"(RowsNextResultSet).Columns\", Method, 8, \"\"},\n\t\t{\"(RowsNextResultSet).HasNextResultSet\", Method, 8, \"\"},\n\t\t{\"(RowsNextResultSet).Next\", Method, 8, \"\"},\n\t\t{\"(RowsNextResultSet).NextResultSet\", Method, 8, \"\"},\n\t\t{\"(SessionResetter).ResetSession\", Method, 10, \"\"},\n\t\t{\"(Stmt).Close\", Method, 0, \"\"},\n\t\t{\"(Stmt).Exec\", Method, 0, \"\"},\n\t\t{\"(Stmt).NumInput\", Method, 0, \"\"},\n\t\t{\"(Stmt).Query\", Method, 0, \"\"},\n\t\t{\"(StmtExecContext).ExecContext\", Method, 8, \"\"},\n\t\t{\"(StmtQueryContext).QueryContext\", Method, 8, \"\"},\n\t\t{\"(Tx).Commit\", Method, 0, \"\"},\n\t\t{\"(Tx).Rollback\", Method, 0, \"\"},\n\t\t{\"(Validator).IsValid\", Method, 15, \"\"},\n\t\t{\"(ValueConverter).ConvertValue\", Method, 0, \"\"},\n\t\t{\"(Valuer).Value\", Method, 0, \"\"},\n\t\t{\"Bool\", Var, 0, \"\"},\n\t\t{\"ColumnConverter\", Type, 0, \"\"},\n\t\t{\"Conn\", Type, 0, \"\"},\n\t\t{\"ConnBeginTx\", Type, 8, \"\"},\n\t\t{\"ConnPrepareContext\", Type, 8, \"\"},\n\t\t{\"Connector\", Type, 10, \"\"},\n\t\t{\"DefaultParameterConverter\", Var, 0, \"\"},\n\t\t{\"Driver\", Type, 0, \"\"},\n\t\t{\"DriverContext\", Type, 10, \"\"},\n\t\t{\"ErrBadConn\", Var, 0, \"\"},\n\t\t{\"ErrRemoveArgument\", Var, 9, \"\"},\n\t\t{\"ErrSkip\", Var, 0, \"\"},\n\t\t{\"Execer\", Type, 0, \"\"},\n\t\t{\"ExecerContext\", Type, 8, \"\"},\n\t\t{\"Int32\", Var, 0, \"\"},\n\t\t{\"IsScanValue\", Func, 0, \"func(v any) bool\"},\n\t\t{\"IsValue\", Func, 0, \"func(v any) bool\"},\n\t\t{\"IsolationLevel\", Type, 8, \"\"},\n\t\t{\"NamedValue\", Type, 8, \"\"},\n\t\t{\"NamedValue.Name\", Field, 8, \"\"},\n\t\t{\"NamedValue.Ordinal\", Field, 8, \"\"},\n\t\t{\"NamedValue.Value\", Field, 8, \"\"},\n\t\t{\"NamedValueChecker\", Type, 9, \"\"},\n\t\t{\"NotNull\", Type, 0, \"\"},\n\t\t{\"NotNull.Converter\", Field, 0, \"\"},\n\t\t{\"Null\", Type, 0, \"\"},\n\t\t{\"Null.Converter\", Field, 0, \"\"},\n\t\t{\"Pinger\", Type, 8, \"\"},\n\t\t{\"Queryer\", Type, 1, \"\"},\n\t\t{\"QueryerContext\", Type, 8, \"\"},\n\t\t{\"Result\", Type, 0, \"\"},\n\t\t{\"ResultNoRows\", Var, 0, \"\"},\n\t\t{\"Rows\", Type, 0, \"\"},\n\t\t{\"RowsAffected\", Type, 0, \"\"},\n\t\t{\"RowsColumnTypeDatabaseTypeName\", Type, 8, \"\"},\n\t\t{\"RowsColumnTypeLength\", Type, 8, \"\"},\n\t\t{\"RowsColumnTypeNullable\", Type, 8, \"\"},\n\t\t{\"RowsColumnTypePrecisionScale\", Type, 8, \"\"},\n\t\t{\"RowsColumnTypeScanType\", Type, 8, \"\"},\n\t\t{\"RowsNextResultSet\", Type, 8, \"\"},\n\t\t{\"SessionResetter\", Type, 10, \"\"},\n\t\t{\"Stmt\", Type, 0, \"\"},\n\t\t{\"StmtExecContext\", Type, 8, \"\"},\n\t\t{\"StmtQueryContext\", Type, 8, \"\"},\n\t\t{\"String\", Var, 0, \"\"},\n\t\t{\"Tx\", Type, 0, \"\"},\n\t\t{\"TxOptions\", Type, 8, \"\"},\n\t\t{\"TxOptions.Isolation\", Field, 8, \"\"},\n\t\t{\"TxOptions.ReadOnly\", Field, 8, \"\"},\n\t\t{\"Validator\", Type, 15, \"\"},\n\t\t{\"Value\", Type, 0, \"\"},\n\t\t{\"ValueConverter\", Type, 0, \"\"},\n\t\t{\"Valuer\", Type, 0, \"\"},\n\t},\n\t\"debug/buildinfo\": {\n\t\t{\"BuildInfo\", Type, 18, \"\"},\n\t\t{\"Read\", Func, 18, \"func(r io.ReaderAt) (*BuildInfo, error)\"},\n\t\t{\"ReadFile\", Func, 18, \"func(name string) (info *BuildInfo, err error)\"},\n\t},\n\t\"debug/dwarf\": {\n\t\t{\"(*AddrType).Basic\", Method, 0, \"\"},\n\t\t{\"(*AddrType).Common\", Method, 0, \"\"},\n\t\t{\"(*AddrType).Size\", Method, 0, \"\"},\n\t\t{\"(*AddrType).String\", Method, 0, \"\"},\n\t\t{\"(*ArrayType).Common\", Method, 0, \"\"},\n\t\t{\"(*ArrayType).Size\", Method, 0, \"\"},\n\t\t{\"(*ArrayType).String\", Method, 0, \"\"},\n\t\t{\"(*BasicType).Basic\", Method, 0, \"\"},\n\t\t{\"(*BasicType).Common\", Method, 0, \"\"},\n\t\t{\"(*BasicType).Size\", Method, 0, \"\"},\n\t\t{\"(*BasicType).String\", Method, 0, \"\"},\n\t\t{\"(*BoolType).Basic\", Method, 0, \"\"},\n\t\t{\"(*BoolType).Common\", Method, 0, \"\"},\n\t\t{\"(*BoolType).Size\", Method, 0, \"\"},\n\t\t{\"(*BoolType).String\", Method, 0, \"\"},\n\t\t{\"(*CharType).Basic\", Method, 0, \"\"},\n\t\t{\"(*CharType).Common\", Method, 0, \"\"},\n\t\t{\"(*CharType).Size\", Method, 0, \"\"},\n\t\t{\"(*CharType).String\", Method, 0, \"\"},\n\t\t{\"(*CommonType).Common\", Method, 0, \"\"},\n\t\t{\"(*CommonType).Size\", Method, 0, \"\"},\n\t\t{\"(*ComplexType).Basic\", Method, 0, \"\"},\n\t\t{\"(*ComplexType).Common\", Method, 0, \"\"},\n\t\t{\"(*ComplexType).Size\", Method, 0, \"\"},\n\t\t{\"(*ComplexType).String\", Method, 0, \"\"},\n\t\t{\"(*Data).AddSection\", Method, 14, \"\"},\n\t\t{\"(*Data).AddTypes\", Method, 3, \"\"},\n\t\t{\"(*Data).LineReader\", Method, 5, \"\"},\n\t\t{\"(*Data).Ranges\", Method, 7, \"\"},\n\t\t{\"(*Data).Reader\", Method, 0, \"\"},\n\t\t{\"(*Data).Type\", Method, 0, \"\"},\n\t\t{\"(*DotDotDotType).Common\", Method, 0, \"\"},\n\t\t{\"(*DotDotDotType).Size\", Method, 0, \"\"},\n\t\t{\"(*DotDotDotType).String\", Method, 0, \"\"},\n\t\t{\"(*Entry).AttrField\", Method, 5, \"\"},\n\t\t{\"(*Entry).Val\", Method, 0, \"\"},\n\t\t{\"(*EnumType).Common\", Method, 0, \"\"},\n\t\t{\"(*EnumType).Size\", Method, 0, \"\"},\n\t\t{\"(*EnumType).String\", Method, 0, \"\"},\n\t\t{\"(*FloatType).Basic\", Method, 0, \"\"},\n\t\t{\"(*FloatType).Common\", Method, 0, \"\"},\n\t\t{\"(*FloatType).Size\", Method, 0, \"\"},\n\t\t{\"(*FloatType).String\", Method, 0, \"\"},\n\t\t{\"(*FuncType).Common\", Method, 0, \"\"},\n\t\t{\"(*FuncType).Size\", Method, 0, \"\"},\n\t\t{\"(*FuncType).String\", Method, 0, \"\"},\n\t\t{\"(*IntType).Basic\", Method, 0, \"\"},\n\t\t{\"(*IntType).Common\", Method, 0, \"\"},\n\t\t{\"(*IntType).Size\", Method, 0, \"\"},\n\t\t{\"(*IntType).String\", Method, 0, \"\"},\n\t\t{\"(*LineReader).Files\", Method, 14, \"\"},\n\t\t{\"(*LineReader).Next\", Method, 5, \"\"},\n\t\t{\"(*LineReader).Reset\", Method, 5, \"\"},\n\t\t{\"(*LineReader).Seek\", Method, 5, \"\"},\n\t\t{\"(*LineReader).SeekPC\", Method, 5, \"\"},\n\t\t{\"(*LineReader).Tell\", Method, 5, \"\"},\n\t\t{\"(*PtrType).Common\", Method, 0, \"\"},\n\t\t{\"(*PtrType).Size\", Method, 0, \"\"},\n\t\t{\"(*PtrType).String\", Method, 0, \"\"},\n\t\t{\"(*QualType).Common\", Method, 0, \"\"},\n\t\t{\"(*QualType).Size\", Method, 0, \"\"},\n\t\t{\"(*QualType).String\", Method, 0, \"\"},\n\t\t{\"(*Reader).AddressSize\", Method, 5, \"\"},\n\t\t{\"(*Reader).ByteOrder\", Method, 14, \"\"},\n\t\t{\"(*Reader).Next\", Method, 0, \"\"},\n\t\t{\"(*Reader).Seek\", Method, 0, \"\"},\n\t\t{\"(*Reader).SeekPC\", Method, 7, \"\"},\n\t\t{\"(*Reader).SkipChildren\", Method, 0, \"\"},\n\t\t{\"(*StructType).Common\", Method, 0, \"\"},\n\t\t{\"(*StructType).Defn\", Method, 0, \"\"},\n\t\t{\"(*StructType).Size\", Method, 0, \"\"},\n\t\t{\"(*StructType).String\", Method, 0, \"\"},\n\t\t{\"(*TypedefType).Common\", Method, 0, \"\"},\n\t\t{\"(*TypedefType).Size\", Method, 0, \"\"},\n\t\t{\"(*TypedefType).String\", Method, 0, \"\"},\n\t\t{\"(*UcharType).Basic\", Method, 0, \"\"},\n\t\t{\"(*UcharType).Common\", Method, 0, \"\"},\n\t\t{\"(*UcharType).Size\", Method, 0, \"\"},\n\t\t{\"(*UcharType).String\", Method, 0, \"\"},\n\t\t{\"(*UintType).Basic\", Method, 0, \"\"},\n\t\t{\"(*UintType).Common\", Method, 0, \"\"},\n\t\t{\"(*UintType).Size\", Method, 0, \"\"},\n\t\t{\"(*UintType).String\", Method, 0, \"\"},\n\t\t{\"(*UnspecifiedType).Basic\", Method, 4, \"\"},\n\t\t{\"(*UnspecifiedType).Common\", Method, 4, \"\"},\n\t\t{\"(*UnspecifiedType).Size\", Method, 4, \"\"},\n\t\t{\"(*UnspecifiedType).String\", Method, 4, \"\"},\n\t\t{\"(*UnsupportedType).Common\", Method, 13, \"\"},\n\t\t{\"(*UnsupportedType).Size\", Method, 13, \"\"},\n\t\t{\"(*UnsupportedType).String\", Method, 13, \"\"},\n\t\t{\"(*VoidType).Common\", Method, 0, \"\"},\n\t\t{\"(*VoidType).Size\", Method, 0, \"\"},\n\t\t{\"(*VoidType).String\", Method, 0, \"\"},\n\t\t{\"(Attr).GoString\", Method, 0, \"\"},\n\t\t{\"(Attr).String\", Method, 0, \"\"},\n\t\t{\"(Class).GoString\", Method, 5, \"\"},\n\t\t{\"(Class).String\", Method, 5, \"\"},\n\t\t{\"(DecodeError).Error\", Method, 0, \"\"},\n\t\t{\"(Tag).GoString\", Method, 0, \"\"},\n\t\t{\"(Tag).String\", Method, 0, \"\"},\n\t\t{\"(Type).Common\", Method, 0, \"\"},\n\t\t{\"(Type).Size\", Method, 0, \"\"},\n\t\t{\"(Type).String\", Method, 0, \"\"},\n\t\t{\"AddrType\", Type, 0, \"\"},\n\t\t{\"AddrType.BasicType\", Field, 0, \"\"},\n\t\t{\"ArrayType\", Type, 0, \"\"},\n\t\t{\"ArrayType.CommonType\", Field, 0, \"\"},\n\t\t{\"ArrayType.Count\", Field, 0, \"\"},\n\t\t{\"ArrayType.StrideBitSize\", Field, 0, \"\"},\n\t\t{\"ArrayType.Type\", Field, 0, \"\"},\n\t\t{\"Attr\", Type, 0, \"\"},\n\t\t{\"AttrAbstractOrigin\", Const, 0, \"\"},\n\t\t{\"AttrAccessibility\", Const, 0, \"\"},\n\t\t{\"AttrAddrBase\", Const, 14, \"\"},\n\t\t{\"AttrAddrClass\", Const, 0, \"\"},\n\t\t{\"AttrAlignment\", Const, 14, \"\"},\n\t\t{\"AttrAllocated\", Const, 0, \"\"},\n\t\t{\"AttrArtificial\", Const, 0, \"\"},\n\t\t{\"AttrAssociated\", Const, 0, \"\"},\n\t\t{\"AttrBaseTypes\", Const, 0, \"\"},\n\t\t{\"AttrBinaryScale\", Const, 14, \"\"},\n\t\t{\"AttrBitOffset\", Const, 0, \"\"},\n\t\t{\"AttrBitSize\", Const, 0, \"\"},\n\t\t{\"AttrByteSize\", Const, 0, \"\"},\n\t\t{\"AttrCallAllCalls\", Const, 14, \"\"},\n\t\t{\"AttrCallAllSourceCalls\", Const, 14, \"\"},\n\t\t{\"AttrCallAllTailCalls\", Const, 14, \"\"},\n\t\t{\"AttrCallColumn\", Const, 0, \"\"},\n\t\t{\"AttrCallDataLocation\", Const, 14, \"\"},\n\t\t{\"AttrCallDataValue\", Const, 14, \"\"},\n\t\t{\"AttrCallFile\", Const, 0, \"\"},\n\t\t{\"AttrCallLine\", Const, 0, \"\"},\n\t\t{\"AttrCallOrigin\", Const, 14, \"\"},\n\t\t{\"AttrCallPC\", Const, 14, \"\"},\n\t\t{\"AttrCallParameter\", Const, 14, \"\"},\n\t\t{\"AttrCallReturnPC\", Const, 14, \"\"},\n\t\t{\"AttrCallTailCall\", Const, 14, \"\"},\n\t\t{\"AttrCallTarget\", Const, 14, \"\"},\n\t\t{\"AttrCallTargetClobbered\", Const, 14, \"\"},\n\t\t{\"AttrCallValue\", Const, 14, \"\"},\n\t\t{\"AttrCalling\", Const, 0, \"\"},\n\t\t{\"AttrCommonRef\", Const, 0, \"\"},\n\t\t{\"AttrCompDir\", Const, 0, \"\"},\n\t\t{\"AttrConstExpr\", Const, 14, \"\"},\n\t\t{\"AttrConstValue\", Const, 0, \"\"},\n\t\t{\"AttrContainingType\", Const, 0, \"\"},\n\t\t{\"AttrCount\", Const, 0, \"\"},\n\t\t{\"AttrDataBitOffset\", Const, 14, \"\"},\n\t\t{\"AttrDataLocation\", Const, 0, \"\"},\n\t\t{\"AttrDataMemberLoc\", Const, 0, \"\"},\n\t\t{\"AttrDecimalScale\", Const, 14, \"\"},\n\t\t{\"AttrDecimalSign\", Const, 14, \"\"},\n\t\t{\"AttrDeclColumn\", Const, 0, \"\"},\n\t\t{\"AttrDeclFile\", Const, 0, \"\"},\n\t\t{\"AttrDeclLine\", Const, 0, \"\"},\n\t\t{\"AttrDeclaration\", Const, 0, \"\"},\n\t\t{\"AttrDefaultValue\", Const, 0, \"\"},\n\t\t{\"AttrDefaulted\", Const, 14, \"\"},\n\t\t{\"AttrDeleted\", Const, 14, \"\"},\n\t\t{\"AttrDescription\", Const, 0, \"\"},\n\t\t{\"AttrDigitCount\", Const, 14, \"\"},\n\t\t{\"AttrDiscr\", Const, 0, \"\"},\n\t\t{\"AttrDiscrList\", Const, 0, \"\"},\n\t\t{\"AttrDiscrValue\", Const, 0, \"\"},\n\t\t{\"AttrDwoName\", Const, 14, \"\"},\n\t\t{\"AttrElemental\", Const, 14, \"\"},\n\t\t{\"AttrEncoding\", Const, 0, \"\"},\n\t\t{\"AttrEndianity\", Const, 14, \"\"},\n\t\t{\"AttrEntrypc\", Const, 0, \"\"},\n\t\t{\"AttrEnumClass\", Const, 14, \"\"},\n\t\t{\"AttrExplicit\", Const, 14, \"\"},\n\t\t{\"AttrExportSymbols\", Const, 14, \"\"},\n\t\t{\"AttrExtension\", Const, 0, \"\"},\n\t\t{\"AttrExternal\", Const, 0, \"\"},\n\t\t{\"AttrFrameBase\", Const, 0, \"\"},\n\t\t{\"AttrFriend\", Const, 0, \"\"},\n\t\t{\"AttrHighpc\", Const, 0, \"\"},\n\t\t{\"AttrIdentifierCase\", Const, 0, \"\"},\n\t\t{\"AttrImport\", Const, 0, \"\"},\n\t\t{\"AttrInline\", Const, 0, \"\"},\n\t\t{\"AttrIsOptional\", Const, 0, \"\"},\n\t\t{\"AttrLanguage\", Const, 0, \"\"},\n\t\t{\"AttrLinkageName\", Const, 14, \"\"},\n\t\t{\"AttrLocation\", Const, 0, \"\"},\n\t\t{\"AttrLoclistsBase\", Const, 14, \"\"},\n\t\t{\"AttrLowerBound\", Const, 0, \"\"},\n\t\t{\"AttrLowpc\", Const, 0, \"\"},\n\t\t{\"AttrMacroInfo\", Const, 0, \"\"},\n\t\t{\"AttrMacros\", Const, 14, \"\"},\n\t\t{\"AttrMainSubprogram\", Const, 14, \"\"},\n\t\t{\"AttrMutable\", Const, 14, \"\"},\n\t\t{\"AttrName\", Const, 0, \"\"},\n\t\t{\"AttrNamelistItem\", Const, 0, \"\"},\n\t\t{\"AttrNoreturn\", Const, 14, \"\"},\n\t\t{\"AttrObjectPointer\", Const, 14, \"\"},\n\t\t{\"AttrOrdering\", Const, 0, \"\"},\n\t\t{\"AttrPictureString\", Const, 14, \"\"},\n\t\t{\"AttrPriority\", Const, 0, \"\"},\n\t\t{\"AttrProducer\", Const, 0, \"\"},\n\t\t{\"AttrPrototyped\", Const, 0, \"\"},\n\t\t{\"AttrPure\", Const, 14, \"\"},\n\t\t{\"AttrRanges\", Const, 0, \"\"},\n\t\t{\"AttrRank\", Const, 14, \"\"},\n\t\t{\"AttrRecursive\", Const, 14, \"\"},\n\t\t{\"AttrReference\", Const, 14, \"\"},\n\t\t{\"AttrReturnAddr\", Const, 0, \"\"},\n\t\t{\"AttrRnglistsBase\", Const, 14, \"\"},\n\t\t{\"AttrRvalueReference\", Const, 14, \"\"},\n\t\t{\"AttrSegment\", Const, 0, \"\"},\n\t\t{\"AttrSibling\", Const, 0, \"\"},\n\t\t{\"AttrSignature\", Const, 14, \"\"},\n\t\t{\"AttrSmall\", Const, 14, \"\"},\n\t\t{\"AttrSpecification\", Const, 0, \"\"},\n\t\t{\"AttrStartScope\", Const, 0, \"\"},\n\t\t{\"AttrStaticLink\", Const, 0, \"\"},\n\t\t{\"AttrStmtList\", Const, 0, \"\"},\n\t\t{\"AttrStrOffsetsBase\", Const, 14, \"\"},\n\t\t{\"AttrStride\", Const, 0, \"\"},\n\t\t{\"AttrStrideSize\", Const, 0, \"\"},\n\t\t{\"AttrStringLength\", Const, 0, \"\"},\n\t\t{\"AttrStringLengthBitSize\", Const, 14, \"\"},\n\t\t{\"AttrStringLengthByteSize\", Const, 14, \"\"},\n\t\t{\"AttrThreadsScaled\", Const, 14, \"\"},\n\t\t{\"AttrTrampoline\", Const, 0, \"\"},\n\t\t{\"AttrType\", Const, 0, \"\"},\n\t\t{\"AttrUpperBound\", Const, 0, \"\"},\n\t\t{\"AttrUseLocation\", Const, 0, \"\"},\n\t\t{\"AttrUseUTF8\", Const, 0, \"\"},\n\t\t{\"AttrVarParam\", Const, 0, \"\"},\n\t\t{\"AttrVirtuality\", Const, 0, \"\"},\n\t\t{\"AttrVisibility\", Const, 0, \"\"},\n\t\t{\"AttrVtableElemLoc\", Const, 0, \"\"},\n\t\t{\"BasicType\", Type, 0, \"\"},\n\t\t{\"BasicType.BitOffset\", Field, 0, \"\"},\n\t\t{\"BasicType.BitSize\", Field, 0, \"\"},\n\t\t{\"BasicType.CommonType\", Field, 0, \"\"},\n\t\t{\"BasicType.DataBitOffset\", Field, 18, \"\"},\n\t\t{\"BoolType\", Type, 0, \"\"},\n\t\t{\"BoolType.BasicType\", Field, 0, \"\"},\n\t\t{\"CharType\", Type, 0, \"\"},\n\t\t{\"CharType.BasicType\", Field, 0, \"\"},\n\t\t{\"Class\", Type, 5, \"\"},\n\t\t{\"ClassAddrPtr\", Const, 14, \"\"},\n\t\t{\"ClassAddress\", Const, 5, \"\"},\n\t\t{\"ClassBlock\", Const, 5, \"\"},\n\t\t{\"ClassConstant\", Const, 5, \"\"},\n\t\t{\"ClassExprLoc\", Const, 5, \"\"},\n\t\t{\"ClassFlag\", Const, 5, \"\"},\n\t\t{\"ClassLinePtr\", Const, 5, \"\"},\n\t\t{\"ClassLocList\", Const, 14, \"\"},\n\t\t{\"ClassLocListPtr\", Const, 5, \"\"},\n\t\t{\"ClassMacPtr\", Const, 5, \"\"},\n\t\t{\"ClassRangeListPtr\", Const, 5, \"\"},\n\t\t{\"ClassReference\", Const, 5, \"\"},\n\t\t{\"ClassReferenceAlt\", Const, 5, \"\"},\n\t\t{\"ClassReferenceSig\", Const, 5, \"\"},\n\t\t{\"ClassRngList\", Const, 14, \"\"},\n\t\t{\"ClassRngListsPtr\", Const, 14, \"\"},\n\t\t{\"ClassStrOffsetsPtr\", Const, 14, \"\"},\n\t\t{\"ClassString\", Const, 5, \"\"},\n\t\t{\"ClassStringAlt\", Const, 5, \"\"},\n\t\t{\"ClassUnknown\", Const, 6, \"\"},\n\t\t{\"CommonType\", Type, 0, \"\"},\n\t\t{\"CommonType.ByteSize\", Field, 0, \"\"},\n\t\t{\"CommonType.Name\", Field, 0, \"\"},\n\t\t{\"ComplexType\", Type, 0, \"\"},\n\t\t{\"ComplexType.BasicType\", Field, 0, \"\"},\n\t\t{\"Data\", Type, 0, \"\"},\n\t\t{\"DecodeError\", Type, 0, \"\"},\n\t\t{\"DecodeError.Err\", Field, 0, \"\"},\n\t\t{\"DecodeError.Name\", Field, 0, \"\"},\n\t\t{\"DecodeError.Offset\", Field, 0, \"\"},\n\t\t{\"DotDotDotType\", Type, 0, \"\"},\n\t\t{\"DotDotDotType.CommonType\", Field, 0, \"\"},\n\t\t{\"Entry\", Type, 0, \"\"},\n\t\t{\"Entry.Children\", Field, 0, \"\"},\n\t\t{\"Entry.Field\", Field, 0, \"\"},\n\t\t{\"Entry.Offset\", Field, 0, \"\"},\n\t\t{\"Entry.Tag\", Field, 0, \"\"},\n\t\t{\"EnumType\", Type, 0, \"\"},\n\t\t{\"EnumType.CommonType\", Field, 0, \"\"},\n\t\t{\"EnumType.EnumName\", Field, 0, \"\"},\n\t\t{\"EnumType.Val\", Field, 0, \"\"},\n\t\t{\"EnumValue\", Type, 0, \"\"},\n\t\t{\"EnumValue.Name\", Field, 0, \"\"},\n\t\t{\"EnumValue.Val\", Field, 0, \"\"},\n\t\t{\"ErrUnknownPC\", Var, 5, \"\"},\n\t\t{\"Field\", Type, 0, \"\"},\n\t\t{\"Field.Attr\", Field, 0, \"\"},\n\t\t{\"Field.Class\", Field, 5, \"\"},\n\t\t{\"Field.Val\", Field, 0, \"\"},\n\t\t{\"FloatType\", Type, 0, \"\"},\n\t\t{\"FloatType.BasicType\", Field, 0, \"\"},\n\t\t{\"FuncType\", Type, 0, \"\"},\n\t\t{\"FuncType.CommonType\", Field, 0, \"\"},\n\t\t{\"FuncType.ParamType\", Field, 0, \"\"},\n\t\t{\"FuncType.ReturnType\", Field, 0, \"\"},\n\t\t{\"IntType\", Type, 0, \"\"},\n\t\t{\"IntType.BasicType\", Field, 0, \"\"},\n\t\t{\"LineEntry\", Type, 5, \"\"},\n\t\t{\"LineEntry.Address\", Field, 5, \"\"},\n\t\t{\"LineEntry.BasicBlock\", Field, 5, \"\"},\n\t\t{\"LineEntry.Column\", Field, 5, \"\"},\n\t\t{\"LineEntry.Discriminator\", Field, 5, \"\"},\n\t\t{\"LineEntry.EndSequence\", Field, 5, \"\"},\n\t\t{\"LineEntry.EpilogueBegin\", Field, 5, \"\"},\n\t\t{\"LineEntry.File\", Field, 5, \"\"},\n\t\t{\"LineEntry.ISA\", Field, 5, \"\"},\n\t\t{\"LineEntry.IsStmt\", Field, 5, \"\"},\n\t\t{\"LineEntry.Line\", Field, 5, \"\"},\n\t\t{\"LineEntry.OpIndex\", Field, 5, \"\"},\n\t\t{\"LineEntry.PrologueEnd\", Field, 5, \"\"},\n\t\t{\"LineFile\", Type, 5, \"\"},\n\t\t{\"LineFile.Length\", Field, 5, \"\"},\n\t\t{\"LineFile.Mtime\", Field, 5, \"\"},\n\t\t{\"LineFile.Name\", Field, 5, \"\"},\n\t\t{\"LineReader\", Type, 5, \"\"},\n\t\t{\"LineReaderPos\", Type, 5, \"\"},\n\t\t{\"New\", Func, 0, \"func(abbrev []byte, aranges []byte, frame []byte, info []byte, line []byte, pubnames []byte, ranges []byte, str []byte) (*Data, error)\"},\n\t\t{\"Offset\", Type, 0, \"\"},\n\t\t{\"PtrType\", Type, 0, \"\"},\n\t\t{\"PtrType.CommonType\", Field, 0, \"\"},\n\t\t{\"PtrType.Type\", Field, 0, \"\"},\n\t\t{\"QualType\", Type, 0, \"\"},\n\t\t{\"QualType.CommonType\", Field, 0, \"\"},\n\t\t{\"QualType.Qual\", Field, 0, \"\"},\n\t\t{\"QualType.Type\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"StructField\", Type, 0, \"\"},\n\t\t{\"StructField.BitOffset\", Field, 0, \"\"},\n\t\t{\"StructField.BitSize\", Field, 0, \"\"},\n\t\t{\"StructField.ByteOffset\", Field, 0, \"\"},\n\t\t{\"StructField.ByteSize\", Field, 0, \"\"},\n\t\t{\"StructField.DataBitOffset\", Field, 18, \"\"},\n\t\t{\"StructField.Name\", Field, 0, \"\"},\n\t\t{\"StructField.Type\", Field, 0, \"\"},\n\t\t{\"StructType\", Type, 0, \"\"},\n\t\t{\"StructType.CommonType\", Field, 0, \"\"},\n\t\t{\"StructType.Field\", Field, 0, \"\"},\n\t\t{\"StructType.Incomplete\", Field, 0, \"\"},\n\t\t{\"StructType.Kind\", Field, 0, \"\"},\n\t\t{\"StructType.StructName\", Field, 0, \"\"},\n\t\t{\"Tag\", Type, 0, \"\"},\n\t\t{\"TagAccessDeclaration\", Const, 0, \"\"},\n\t\t{\"TagArrayType\", Const, 0, \"\"},\n\t\t{\"TagAtomicType\", Const, 14, \"\"},\n\t\t{\"TagBaseType\", Const, 0, \"\"},\n\t\t{\"TagCallSite\", Const, 14, \"\"},\n\t\t{\"TagCallSiteParameter\", Const, 14, \"\"},\n\t\t{\"TagCatchDwarfBlock\", Const, 0, \"\"},\n\t\t{\"TagClassType\", Const, 0, \"\"},\n\t\t{\"TagCoarrayType\", Const, 14, \"\"},\n\t\t{\"TagCommonDwarfBlock\", Const, 0, \"\"},\n\t\t{\"TagCommonInclusion\", Const, 0, \"\"},\n\t\t{\"TagCompileUnit\", Const, 0, \"\"},\n\t\t{\"TagCondition\", Const, 3, \"\"},\n\t\t{\"TagConstType\", Const, 0, \"\"},\n\t\t{\"TagConstant\", Const, 0, \"\"},\n\t\t{\"TagDwarfProcedure\", Const, 0, \"\"},\n\t\t{\"TagDynamicType\", Const, 14, \"\"},\n\t\t{\"TagEntryPoint\", Const, 0, \"\"},\n\t\t{\"TagEnumerationType\", Const, 0, \"\"},\n\t\t{\"TagEnumerator\", Const, 0, \"\"},\n\t\t{\"TagFileType\", Const, 0, \"\"},\n\t\t{\"TagFormalParameter\", Const, 0, \"\"},\n\t\t{\"TagFriend\", Const, 0, \"\"},\n\t\t{\"TagGenericSubrange\", Const, 14, \"\"},\n\t\t{\"TagImmutableType\", Const, 14, \"\"},\n\t\t{\"TagImportedDeclaration\", Const, 0, \"\"},\n\t\t{\"TagImportedModule\", Const, 0, \"\"},\n\t\t{\"TagImportedUnit\", Const, 0, \"\"},\n\t\t{\"TagInheritance\", Const, 0, \"\"},\n\t\t{\"TagInlinedSubroutine\", Const, 0, \"\"},\n\t\t{\"TagInterfaceType\", Const, 0, \"\"},\n\t\t{\"TagLabel\", Const, 0, \"\"},\n\t\t{\"TagLexDwarfBlock\", Const, 0, \"\"},\n\t\t{\"TagMember\", Const, 0, \"\"},\n\t\t{\"TagModule\", Const, 0, \"\"},\n\t\t{\"TagMutableType\", Const, 0, \"\"},\n\t\t{\"TagNamelist\", Const, 0, \"\"},\n\t\t{\"TagNamelistItem\", Const, 0, \"\"},\n\t\t{\"TagNamespace\", Const, 0, \"\"},\n\t\t{\"TagPackedType\", Const, 0, \"\"},\n\t\t{\"TagPartialUnit\", Const, 0, \"\"},\n\t\t{\"TagPointerType\", Const, 0, \"\"},\n\t\t{\"TagPtrToMemberType\", Const, 0, \"\"},\n\t\t{\"TagReferenceType\", Const, 0, \"\"},\n\t\t{\"TagRestrictType\", Const, 0, \"\"},\n\t\t{\"TagRvalueReferenceType\", Const, 3, \"\"},\n\t\t{\"TagSetType\", Const, 0, \"\"},\n\t\t{\"TagSharedType\", Const, 3, \"\"},\n\t\t{\"TagSkeletonUnit\", Const, 14, \"\"},\n\t\t{\"TagStringType\", Const, 0, \"\"},\n\t\t{\"TagStructType\", Const, 0, \"\"},\n\t\t{\"TagSubprogram\", Const, 0, \"\"},\n\t\t{\"TagSubrangeType\", Const, 0, \"\"},\n\t\t{\"TagSubroutineType\", Const, 0, \"\"},\n\t\t{\"TagTemplateAlias\", Const, 3, \"\"},\n\t\t{\"TagTemplateTypeParameter\", Const, 0, \"\"},\n\t\t{\"TagTemplateValueParameter\", Const, 0, \"\"},\n\t\t{\"TagThrownType\", Const, 0, \"\"},\n\t\t{\"TagTryDwarfBlock\", Const, 0, \"\"},\n\t\t{\"TagTypeUnit\", Const, 3, \"\"},\n\t\t{\"TagTypedef\", Const, 0, \"\"},\n\t\t{\"TagUnionType\", Const, 0, \"\"},\n\t\t{\"TagUnspecifiedParameters\", Const, 0, \"\"},\n\t\t{\"TagUnspecifiedType\", Const, 0, \"\"},\n\t\t{\"TagVariable\", Const, 0, \"\"},\n\t\t{\"TagVariant\", Const, 0, \"\"},\n\t\t{\"TagVariantPart\", Const, 0, \"\"},\n\t\t{\"TagVolatileType\", Const, 0, \"\"},\n\t\t{\"TagWithStmt\", Const, 0, \"\"},\n\t\t{\"Type\", Type, 0, \"\"},\n\t\t{\"TypedefType\", Type, 0, \"\"},\n\t\t{\"TypedefType.CommonType\", Field, 0, \"\"},\n\t\t{\"TypedefType.Type\", Field, 0, \"\"},\n\t\t{\"UcharType\", Type, 0, \"\"},\n\t\t{\"UcharType.BasicType\", Field, 0, \"\"},\n\t\t{\"UintType\", Type, 0, \"\"},\n\t\t{\"UintType.BasicType\", Field, 0, \"\"},\n\t\t{\"UnspecifiedType\", Type, 4, \"\"},\n\t\t{\"UnspecifiedType.BasicType\", Field, 4, \"\"},\n\t\t{\"UnsupportedType\", Type, 13, \"\"},\n\t\t{\"UnsupportedType.CommonType\", Field, 13, \"\"},\n\t\t{\"UnsupportedType.Tag\", Field, 13, \"\"},\n\t\t{\"VoidType\", Type, 0, \"\"},\n\t\t{\"VoidType.CommonType\", Field, 0, \"\"},\n\t},\n\t\"debug/elf\": {\n\t\t{\"(*File).Close\", Method, 0, \"\"},\n\t\t{\"(*File).DWARF\", Method, 0, \"\"},\n\t\t{\"(*File).DynString\", Method, 1, \"\"},\n\t\t{\"(*File).DynValue\", Method, 21, \"\"},\n\t\t{\"(*File).DynamicSymbols\", Method, 4, \"\"},\n\t\t{\"(*File).DynamicVersionNeeds\", Method, 24, \"\"},\n\t\t{\"(*File).DynamicVersions\", Method, 24, \"\"},\n\t\t{\"(*File).ImportedLibraries\", Method, 0, \"\"},\n\t\t{\"(*File).ImportedSymbols\", Method, 0, \"\"},\n\t\t{\"(*File).Section\", Method, 0, \"\"},\n\t\t{\"(*File).SectionByType\", Method, 0, \"\"},\n\t\t{\"(*File).Symbols\", Method, 0, \"\"},\n\t\t{\"(*FormatError).Error\", Method, 0, \"\"},\n\t\t{\"(*Prog).Open\", Method, 0, \"\"},\n\t\t{\"(*Section).Data\", Method, 0, \"\"},\n\t\t{\"(*Section).Open\", Method, 0, \"\"},\n\t\t{\"(Class).GoString\", Method, 0, \"\"},\n\t\t{\"(Class).String\", Method, 0, \"\"},\n\t\t{\"(CompressionType).GoString\", Method, 6, \"\"},\n\t\t{\"(CompressionType).String\", Method, 6, \"\"},\n\t\t{\"(Data).GoString\", Method, 0, \"\"},\n\t\t{\"(Data).String\", Method, 0, \"\"},\n\t\t{\"(DynFlag).GoString\", Method, 0, \"\"},\n\t\t{\"(DynFlag).String\", Method, 0, \"\"},\n\t\t{\"(DynFlag1).GoString\", Method, 21, \"\"},\n\t\t{\"(DynFlag1).String\", Method, 21, \"\"},\n\t\t{\"(DynTag).GoString\", Method, 0, \"\"},\n\t\t{\"(DynTag).String\", Method, 0, \"\"},\n\t\t{\"(Machine).GoString\", Method, 0, \"\"},\n\t\t{\"(Machine).String\", Method, 0, \"\"},\n\t\t{\"(NType).GoString\", Method, 0, \"\"},\n\t\t{\"(NType).String\", Method, 0, \"\"},\n\t\t{\"(OSABI).GoString\", Method, 0, \"\"},\n\t\t{\"(OSABI).String\", Method, 0, \"\"},\n\t\t{\"(Prog).ReadAt\", Method, 0, \"\"},\n\t\t{\"(ProgFlag).GoString\", Method, 0, \"\"},\n\t\t{\"(ProgFlag).String\", Method, 0, \"\"},\n\t\t{\"(ProgType).GoString\", Method, 0, \"\"},\n\t\t{\"(ProgType).String\", Method, 0, \"\"},\n\t\t{\"(R_386).GoString\", Method, 0, \"\"},\n\t\t{\"(R_386).String\", Method, 0, \"\"},\n\t\t{\"(R_390).GoString\", Method, 7, \"\"},\n\t\t{\"(R_390).String\", Method, 7, \"\"},\n\t\t{\"(R_AARCH64).GoString\", Method, 4, \"\"},\n\t\t{\"(R_AARCH64).String\", Method, 4, \"\"},\n\t\t{\"(R_ALPHA).GoString\", Method, 0, \"\"},\n\t\t{\"(R_ALPHA).String\", Method, 0, \"\"},\n\t\t{\"(R_ARM).GoString\", Method, 0, \"\"},\n\t\t{\"(R_ARM).String\", Method, 0, \"\"},\n\t\t{\"(R_LARCH).GoString\", Method, 19, \"\"},\n\t\t{\"(R_LARCH).String\", Method, 19, \"\"},\n\t\t{\"(R_MIPS).GoString\", Method, 6, \"\"},\n\t\t{\"(R_MIPS).String\", Method, 6, \"\"},\n\t\t{\"(R_PPC).GoString\", Method, 0, \"\"},\n\t\t{\"(R_PPC).String\", Method, 0, \"\"},\n\t\t{\"(R_PPC64).GoString\", Method, 5, \"\"},\n\t\t{\"(R_PPC64).String\", Method, 5, \"\"},\n\t\t{\"(R_RISCV).GoString\", Method, 11, \"\"},\n\t\t{\"(R_RISCV).String\", Method, 11, \"\"},\n\t\t{\"(R_SPARC).GoString\", Method, 0, \"\"},\n\t\t{\"(R_SPARC).String\", Method, 0, \"\"},\n\t\t{\"(R_X86_64).GoString\", Method, 0, \"\"},\n\t\t{\"(R_X86_64).String\", Method, 0, \"\"},\n\t\t{\"(Section).ReadAt\", Method, 0, \"\"},\n\t\t{\"(SectionFlag).GoString\", Method, 0, \"\"},\n\t\t{\"(SectionFlag).String\", Method, 0, \"\"},\n\t\t{\"(SectionIndex).GoString\", Method, 0, \"\"},\n\t\t{\"(SectionIndex).String\", Method, 0, \"\"},\n\t\t{\"(SectionType).GoString\", Method, 0, \"\"},\n\t\t{\"(SectionType).String\", Method, 0, \"\"},\n\t\t{\"(SymBind).GoString\", Method, 0, \"\"},\n\t\t{\"(SymBind).String\", Method, 0, \"\"},\n\t\t{\"(SymType).GoString\", Method, 0, \"\"},\n\t\t{\"(SymType).String\", Method, 0, \"\"},\n\t\t{\"(SymVis).GoString\", Method, 0, \"\"},\n\t\t{\"(SymVis).String\", Method, 0, \"\"},\n\t\t{\"(Type).GoString\", Method, 0, \"\"},\n\t\t{\"(Type).String\", Method, 0, \"\"},\n\t\t{\"(Version).GoString\", Method, 0, \"\"},\n\t\t{\"(Version).String\", Method, 0, \"\"},\n\t\t{\"(VersionIndex).Index\", Method, 24, \"\"},\n\t\t{\"(VersionIndex).IsHidden\", Method, 24, \"\"},\n\t\t{\"ARM_MAGIC_TRAMP_NUMBER\", Const, 0, \"\"},\n\t\t{\"COMPRESS_HIOS\", Const, 6, \"\"},\n\t\t{\"COMPRESS_HIPROC\", Const, 6, \"\"},\n\t\t{\"COMPRESS_LOOS\", Const, 6, \"\"},\n\t\t{\"COMPRESS_LOPROC\", Const, 6, \"\"},\n\t\t{\"COMPRESS_ZLIB\", Const, 6, \"\"},\n\t\t{\"COMPRESS_ZSTD\", Const, 21, \"\"},\n\t\t{\"Chdr32\", Type, 6, \"\"},\n\t\t{\"Chdr32.Addralign\", Field, 6, \"\"},\n\t\t{\"Chdr32.Size\", Field, 6, \"\"},\n\t\t{\"Chdr32.Type\", Field, 6, \"\"},\n\t\t{\"Chdr64\", Type, 6, \"\"},\n\t\t{\"Chdr64.Addralign\", Field, 6, \"\"},\n\t\t{\"Chdr64.Size\", Field, 6, \"\"},\n\t\t{\"Chdr64.Type\", Field, 6, \"\"},\n\t\t{\"Class\", Type, 0, \"\"},\n\t\t{\"CompressionType\", Type, 6, \"\"},\n\t\t{\"DF_1_CONFALT\", Const, 21, \"\"},\n\t\t{\"DF_1_DIRECT\", Const, 21, \"\"},\n\t\t{\"DF_1_DISPRELDNE\", Const, 21, \"\"},\n\t\t{\"DF_1_DISPRELPND\", Const, 21, \"\"},\n\t\t{\"DF_1_EDITED\", Const, 21, \"\"},\n\t\t{\"DF_1_ENDFILTEE\", Const, 21, \"\"},\n\t\t{\"DF_1_GLOBAL\", Const, 21, \"\"},\n\t\t{\"DF_1_GLOBAUDIT\", Const, 21, \"\"},\n\t\t{\"DF_1_GROUP\", Const, 21, \"\"},\n\t\t{\"DF_1_IGNMULDEF\", Const, 21, \"\"},\n\t\t{\"DF_1_INITFIRST\", Const, 21, \"\"},\n\t\t{\"DF_1_INTERPOSE\", Const, 21, \"\"},\n\t\t{\"DF_1_KMOD\", Const, 21, \"\"},\n\t\t{\"DF_1_LOADFLTR\", Const, 21, \"\"},\n\t\t{\"DF_1_NOCOMMON\", Const, 21, \"\"},\n\t\t{\"DF_1_NODEFLIB\", Const, 21, \"\"},\n\t\t{\"DF_1_NODELETE\", Const, 21, \"\"},\n\t\t{\"DF_1_NODIRECT\", Const, 21, \"\"},\n\t\t{\"DF_1_NODUMP\", Const, 21, \"\"},\n\t\t{\"DF_1_NOHDR\", Const, 21, \"\"},\n\t\t{\"DF_1_NOKSYMS\", Const, 21, \"\"},\n\t\t{\"DF_1_NOOPEN\", Const, 21, \"\"},\n\t\t{\"DF_1_NORELOC\", Const, 21, \"\"},\n\t\t{\"DF_1_NOW\", Const, 21, \"\"},\n\t\t{\"DF_1_ORIGIN\", Const, 21, \"\"},\n\t\t{\"DF_1_PIE\", Const, 21, \"\"},\n\t\t{\"DF_1_SINGLETON\", Const, 21, \"\"},\n\t\t{\"DF_1_STUB\", Const, 21, \"\"},\n\t\t{\"DF_1_SYMINTPOSE\", Const, 21, \"\"},\n\t\t{\"DF_1_TRANS\", Const, 21, \"\"},\n\t\t{\"DF_1_WEAKFILTER\", Const, 21, \"\"},\n\t\t{\"DF_BIND_NOW\", Const, 0, \"\"},\n\t\t{\"DF_ORIGIN\", Const, 0, \"\"},\n\t\t{\"DF_STATIC_TLS\", Const, 0, \"\"},\n\t\t{\"DF_SYMBOLIC\", Const, 0, \"\"},\n\t\t{\"DF_TEXTREL\", Const, 0, \"\"},\n\t\t{\"DT_ADDRRNGHI\", Const, 16, \"\"},\n\t\t{\"DT_ADDRRNGLO\", Const, 16, \"\"},\n\t\t{\"DT_AUDIT\", Const, 16, \"\"},\n\t\t{\"DT_AUXILIARY\", Const, 16, \"\"},\n\t\t{\"DT_BIND_NOW\", Const, 0, \"\"},\n\t\t{\"DT_CHECKSUM\", Const, 16, \"\"},\n\t\t{\"DT_CONFIG\", Const, 16, \"\"},\n\t\t{\"DT_DEBUG\", Const, 0, \"\"},\n\t\t{\"DT_DEPAUDIT\", Const, 16, \"\"},\n\t\t{\"DT_ENCODING\", Const, 0, \"\"},\n\t\t{\"DT_FEATURE\", Const, 16, \"\"},\n\t\t{\"DT_FILTER\", Const, 16, \"\"},\n\t\t{\"DT_FINI\", Const, 0, \"\"},\n\t\t{\"DT_FINI_ARRAY\", Const, 0, \"\"},\n\t\t{\"DT_FINI_ARRAYSZ\", Const, 0, \"\"},\n\t\t{\"DT_FLAGS\", Const, 0, \"\"},\n\t\t{\"DT_FLAGS_1\", Const, 16, \"\"},\n\t\t{\"DT_GNU_CONFLICT\", Const, 16, \"\"},\n\t\t{\"DT_GNU_CONFLICTSZ\", Const, 16, \"\"},\n\t\t{\"DT_GNU_HASH\", Const, 16, \"\"},\n\t\t{\"DT_GNU_LIBLIST\", Const, 16, \"\"},\n\t\t{\"DT_GNU_LIBLISTSZ\", Const, 16, \"\"},\n\t\t{\"DT_GNU_PRELINKED\", Const, 16, \"\"},\n\t\t{\"DT_HASH\", Const, 0, \"\"},\n\t\t{\"DT_HIOS\", Const, 0, \"\"},\n\t\t{\"DT_HIPROC\", Const, 0, \"\"},\n\t\t{\"DT_INIT\", Const, 0, \"\"},\n\t\t{\"DT_INIT_ARRAY\", Const, 0, \"\"},\n\t\t{\"DT_INIT_ARRAYSZ\", Const, 0, \"\"},\n\t\t{\"DT_JMPREL\", Const, 0, \"\"},\n\t\t{\"DT_LOOS\", Const, 0, \"\"},\n\t\t{\"DT_LOPROC\", Const, 0, \"\"},\n\t\t{\"DT_MIPS_AUX_DYNAMIC\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_BASE_ADDRESS\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_COMPACT_SIZE\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_CONFLICT\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_CONFLICTNO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_CXX_FLAGS\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_CLASS\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_CLASSSYM\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_CLASSSYM_NO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_CLASS_NO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_INSTANCE\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_INSTANCE_NO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_RELOC\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_RELOC_NO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_SYM\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DELTA_SYM_NO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_DYNSTR_ALIGN\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_FLAGS\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_GOTSYM\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_GP_VALUE\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_HIDDEN_GOTIDX\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_HIPAGENO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_ICHECKSUM\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_INTERFACE\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_INTERFACE_SIZE\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_IVERSION\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_LIBLIST\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_LIBLISTNO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_LOCALPAGE_GOTIDX\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_LOCAL_GOTIDX\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_LOCAL_GOTNO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_MSYM\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_OPTIONS\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_PERF_SUFFIX\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_PIXIE_INIT\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_PLTGOT\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_PROTECTED_GOTIDX\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_RLD_MAP\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_RLD_MAP_REL\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_RLD_TEXT_RESOLVE_ADDR\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_RLD_VERSION\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_RWPLT\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_SYMBOL_LIB\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_SYMTABNO\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_TIME_STAMP\", Const, 16, \"\"},\n\t\t{\"DT_MIPS_UNREFEXTNO\", Const, 16, \"\"},\n\t\t{\"DT_MOVEENT\", Const, 16, \"\"},\n\t\t{\"DT_MOVESZ\", Const, 16, \"\"},\n\t\t{\"DT_MOVETAB\", Const, 16, \"\"},\n\t\t{\"DT_NEEDED\", Const, 0, \"\"},\n\t\t{\"DT_NULL\", Const, 0, \"\"},\n\t\t{\"DT_PLTGOT\", Const, 0, \"\"},\n\t\t{\"DT_PLTPAD\", Const, 16, \"\"},\n\t\t{\"DT_PLTPADSZ\", Const, 16, \"\"},\n\t\t{\"DT_PLTREL\", Const, 0, \"\"},\n\t\t{\"DT_PLTRELSZ\", Const, 0, \"\"},\n\t\t{\"DT_POSFLAG_1\", Const, 16, \"\"},\n\t\t{\"DT_PPC64_GLINK\", Const, 16, \"\"},\n\t\t{\"DT_PPC64_OPD\", Const, 16, \"\"},\n\t\t{\"DT_PPC64_OPDSZ\", Const, 16, \"\"},\n\t\t{\"DT_PPC64_OPT\", Const, 16, \"\"},\n\t\t{\"DT_PPC_GOT\", Const, 16, \"\"},\n\t\t{\"DT_PPC_OPT\", Const, 16, \"\"},\n\t\t{\"DT_PREINIT_ARRAY\", Const, 0, \"\"},\n\t\t{\"DT_PREINIT_ARRAYSZ\", Const, 0, \"\"},\n\t\t{\"DT_REL\", Const, 0, \"\"},\n\t\t{\"DT_RELA\", Const, 0, \"\"},\n\t\t{\"DT_RELACOUNT\", Const, 16, \"\"},\n\t\t{\"DT_RELAENT\", Const, 0, \"\"},\n\t\t{\"DT_RELASZ\", Const, 0, \"\"},\n\t\t{\"DT_RELCOUNT\", Const, 16, \"\"},\n\t\t{\"DT_RELENT\", Const, 0, \"\"},\n\t\t{\"DT_RELSZ\", Const, 0, \"\"},\n\t\t{\"DT_RPATH\", Const, 0, \"\"},\n\t\t{\"DT_RUNPATH\", Const, 0, \"\"},\n\t\t{\"DT_SONAME\", Const, 0, \"\"},\n\t\t{\"DT_SPARC_REGISTER\", Const, 16, \"\"},\n\t\t{\"DT_STRSZ\", Const, 0, \"\"},\n\t\t{\"DT_STRTAB\", Const, 0, \"\"},\n\t\t{\"DT_SYMBOLIC\", Const, 0, \"\"},\n\t\t{\"DT_SYMENT\", Const, 0, \"\"},\n\t\t{\"DT_SYMINENT\", Const, 16, \"\"},\n\t\t{\"DT_SYMINFO\", Const, 16, \"\"},\n\t\t{\"DT_SYMINSZ\", Const, 16, \"\"},\n\t\t{\"DT_SYMTAB\", Const, 0, \"\"},\n\t\t{\"DT_SYMTAB_SHNDX\", Const, 16, \"\"},\n\t\t{\"DT_TEXTREL\", Const, 0, \"\"},\n\t\t{\"DT_TLSDESC_GOT\", Const, 16, \"\"},\n\t\t{\"DT_TLSDESC_PLT\", Const, 16, \"\"},\n\t\t{\"DT_USED\", Const, 16, \"\"},\n\t\t{\"DT_VALRNGHI\", Const, 16, \"\"},\n\t\t{\"DT_VALRNGLO\", Const, 16, \"\"},\n\t\t{\"DT_VERDEF\", Const, 16, \"\"},\n\t\t{\"DT_VERDEFNUM\", Const, 16, \"\"},\n\t\t{\"DT_VERNEED\", Const, 0, \"\"},\n\t\t{\"DT_VERNEEDNUM\", Const, 0, \"\"},\n\t\t{\"DT_VERSYM\", Const, 0, \"\"},\n\t\t{\"Data\", Type, 0, \"\"},\n\t\t{\"Dyn32\", Type, 0, \"\"},\n\t\t{\"Dyn32.Tag\", Field, 0, \"\"},\n\t\t{\"Dyn32.Val\", Field, 0, \"\"},\n\t\t{\"Dyn64\", Type, 0, \"\"},\n\t\t{\"Dyn64.Tag\", Field, 0, \"\"},\n\t\t{\"Dyn64.Val\", Field, 0, \"\"},\n\t\t{\"DynFlag\", Type, 0, \"\"},\n\t\t{\"DynFlag1\", Type, 21, \"\"},\n\t\t{\"DynTag\", Type, 0, \"\"},\n\t\t{\"DynamicVersion\", Type, 24, \"\"},\n\t\t{\"DynamicVersion.Deps\", Field, 24, \"\"},\n\t\t{\"DynamicVersion.Flags\", Field, 24, \"\"},\n\t\t{\"DynamicVersion.Index\", Field, 24, \"\"},\n\t\t{\"DynamicVersion.Name\", Field, 24, \"\"},\n\t\t{\"DynamicVersionDep\", Type, 24, \"\"},\n\t\t{\"DynamicVersionDep.Dep\", Field, 24, \"\"},\n\t\t{\"DynamicVersionDep.Flags\", Field, 24, \"\"},\n\t\t{\"DynamicVersionDep.Index\", Field, 24, \"\"},\n\t\t{\"DynamicVersionFlag\", Type, 24, \"\"},\n\t\t{\"DynamicVersionNeed\", Type, 24, \"\"},\n\t\t{\"DynamicVersionNeed.Name\", Field, 24, \"\"},\n\t\t{\"DynamicVersionNeed.Needs\", Field, 24, \"\"},\n\t\t{\"EI_ABIVERSION\", Const, 0, \"\"},\n\t\t{\"EI_CLASS\", Const, 0, \"\"},\n\t\t{\"EI_DATA\", Const, 0, \"\"},\n\t\t{\"EI_NIDENT\", Const, 0, \"\"},\n\t\t{\"EI_OSABI\", Const, 0, \"\"},\n\t\t{\"EI_PAD\", Const, 0, \"\"},\n\t\t{\"EI_VERSION\", Const, 0, \"\"},\n\t\t{\"ELFCLASS32\", Const, 0, \"\"},\n\t\t{\"ELFCLASS64\", Const, 0, \"\"},\n\t\t{\"ELFCLASSNONE\", Const, 0, \"\"},\n\t\t{\"ELFDATA2LSB\", Const, 0, \"\"},\n\t\t{\"ELFDATA2MSB\", Const, 0, \"\"},\n\t\t{\"ELFDATANONE\", Const, 0, \"\"},\n\t\t{\"ELFMAG\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_86OPEN\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_AIX\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_ARM\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_AROS\", Const, 11, \"\"},\n\t\t{\"ELFOSABI_CLOUDABI\", Const, 11, \"\"},\n\t\t{\"ELFOSABI_FENIXOS\", Const, 11, \"\"},\n\t\t{\"ELFOSABI_FREEBSD\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_HPUX\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_HURD\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_IRIX\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_LINUX\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_MODESTO\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_NETBSD\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_NONE\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_NSK\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_OPENBSD\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_OPENVMS\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_SOLARIS\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_STANDALONE\", Const, 0, \"\"},\n\t\t{\"ELFOSABI_TRU64\", Const, 0, \"\"},\n\t\t{\"EM_386\", Const, 0, \"\"},\n\t\t{\"EM_486\", Const, 0, \"\"},\n\t\t{\"EM_56800EX\", Const, 11, \"\"},\n\t\t{\"EM_68HC05\", Const, 11, \"\"},\n\t\t{\"EM_68HC08\", Const, 11, \"\"},\n\t\t{\"EM_68HC11\", Const, 11, \"\"},\n\t\t{\"EM_68HC12\", Const, 0, \"\"},\n\t\t{\"EM_68HC16\", Const, 11, \"\"},\n\t\t{\"EM_68K\", Const, 0, \"\"},\n\t\t{\"EM_78KOR\", Const, 11, \"\"},\n\t\t{\"EM_8051\", Const, 11, \"\"},\n\t\t{\"EM_860\", Const, 0, \"\"},\n\t\t{\"EM_88K\", Const, 0, \"\"},\n\t\t{\"EM_960\", Const, 0, \"\"},\n\t\t{\"EM_AARCH64\", Const, 4, \"\"},\n\t\t{\"EM_ALPHA\", Const, 0, \"\"},\n\t\t{\"EM_ALPHA_STD\", Const, 0, \"\"},\n\t\t{\"EM_ALTERA_NIOS2\", Const, 11, \"\"},\n\t\t{\"EM_AMDGPU\", Const, 11, \"\"},\n\t\t{\"EM_ARC\", Const, 0, \"\"},\n\t\t{\"EM_ARCA\", Const, 11, \"\"},\n\t\t{\"EM_ARC_COMPACT\", Const, 11, \"\"},\n\t\t{\"EM_ARC_COMPACT2\", Const, 11, \"\"},\n\t\t{\"EM_ARM\", Const, 0, \"\"},\n\t\t{\"EM_AVR\", Const, 11, \"\"},\n\t\t{\"EM_AVR32\", Const, 11, \"\"},\n\t\t{\"EM_BA1\", Const, 11, \"\"},\n\t\t{\"EM_BA2\", Const, 11, \"\"},\n\t\t{\"EM_BLACKFIN\", Const, 11, \"\"},\n\t\t{\"EM_BPF\", Const, 11, \"\"},\n\t\t{\"EM_C166\", Const, 11, \"\"},\n\t\t{\"EM_CDP\", Const, 11, \"\"},\n\t\t{\"EM_CE\", Const, 11, \"\"},\n\t\t{\"EM_CLOUDSHIELD\", Const, 11, \"\"},\n\t\t{\"EM_COGE\", Const, 11, \"\"},\n\t\t{\"EM_COLDFIRE\", Const, 0, \"\"},\n\t\t{\"EM_COOL\", Const, 11, \"\"},\n\t\t{\"EM_COREA_1ST\", Const, 11, \"\"},\n\t\t{\"EM_COREA_2ND\", Const, 11, \"\"},\n\t\t{\"EM_CR\", Const, 11, \"\"},\n\t\t{\"EM_CR16\", Const, 11, \"\"},\n\t\t{\"EM_CRAYNV2\", Const, 11, \"\"},\n\t\t{\"EM_CRIS\", Const, 11, \"\"},\n\t\t{\"EM_CRX\", Const, 11, \"\"},\n\t\t{\"EM_CSR_KALIMBA\", Const, 11, \"\"},\n\t\t{\"EM_CUDA\", Const, 11, \"\"},\n\t\t{\"EM_CYPRESS_M8C\", Const, 11, \"\"},\n\t\t{\"EM_D10V\", Const, 11, \"\"},\n\t\t{\"EM_D30V\", Const, 11, \"\"},\n\t\t{\"EM_DSP24\", Const, 11, \"\"},\n\t\t{\"EM_DSPIC30F\", Const, 11, \"\"},\n\t\t{\"EM_DXP\", Const, 11, \"\"},\n\t\t{\"EM_ECOG1\", Const, 11, \"\"},\n\t\t{\"EM_ECOG16\", Const, 11, \"\"},\n\t\t{\"EM_ECOG1X\", Const, 11, \"\"},\n\t\t{\"EM_ECOG2\", Const, 11, \"\"},\n\t\t{\"EM_ETPU\", Const, 11, \"\"},\n\t\t{\"EM_EXCESS\", Const, 11, \"\"},\n\t\t{\"EM_F2MC16\", Const, 11, \"\"},\n\t\t{\"EM_FIREPATH\", Const, 11, \"\"},\n\t\t{\"EM_FR20\", Const, 0, \"\"},\n\t\t{\"EM_FR30\", Const, 11, \"\"},\n\t\t{\"EM_FT32\", Const, 11, \"\"},\n\t\t{\"EM_FX66\", Const, 11, \"\"},\n\t\t{\"EM_H8S\", Const, 0, \"\"},\n\t\t{\"EM_H8_300\", Const, 0, \"\"},\n\t\t{\"EM_H8_300H\", Const, 0, \"\"},\n\t\t{\"EM_H8_500\", Const, 0, \"\"},\n\t\t{\"EM_HUANY\", Const, 11, \"\"},\n\t\t{\"EM_IA_64\", Const, 0, \"\"},\n\t\t{\"EM_INTEL205\", Const, 11, \"\"},\n\t\t{\"EM_INTEL206\", Const, 11, \"\"},\n\t\t{\"EM_INTEL207\", Const, 11, \"\"},\n\t\t{\"EM_INTEL208\", Const, 11, \"\"},\n\t\t{\"EM_INTEL209\", Const, 11, \"\"},\n\t\t{\"EM_IP2K\", Const, 11, \"\"},\n\t\t{\"EM_JAVELIN\", Const, 11, \"\"},\n\t\t{\"EM_K10M\", Const, 11, \"\"},\n\t\t{\"EM_KM32\", Const, 11, \"\"},\n\t\t{\"EM_KMX16\", Const, 11, \"\"},\n\t\t{\"EM_KMX32\", Const, 11, \"\"},\n\t\t{\"EM_KMX8\", Const, 11, \"\"},\n\t\t{\"EM_KVARC\", Const, 11, \"\"},\n\t\t{\"EM_L10M\", Const, 11, \"\"},\n\t\t{\"EM_LANAI\", Const, 11, \"\"},\n\t\t{\"EM_LATTICEMICO32\", Const, 11, \"\"},\n\t\t{\"EM_LOONGARCH\", Const, 19, \"\"},\n\t\t{\"EM_M16C\", Const, 11, \"\"},\n\t\t{\"EM_M32\", Const, 0, \"\"},\n\t\t{\"EM_M32C\", Const, 11, \"\"},\n\t\t{\"EM_M32R\", Const, 11, \"\"},\n\t\t{\"EM_MANIK\", Const, 11, \"\"},\n\t\t{\"EM_MAX\", Const, 11, \"\"},\n\t\t{\"EM_MAXQ30\", Const, 11, \"\"},\n\t\t{\"EM_MCHP_PIC\", Const, 11, \"\"},\n\t\t{\"EM_MCST_ELBRUS\", Const, 11, \"\"},\n\t\t{\"EM_ME16\", Const, 0, \"\"},\n\t\t{\"EM_METAG\", Const, 11, \"\"},\n\t\t{\"EM_MICROBLAZE\", Const, 11, \"\"},\n\t\t{\"EM_MIPS\", Const, 0, \"\"},\n\t\t{\"EM_MIPS_RS3_LE\", Const, 0, \"\"},\n\t\t{\"EM_MIPS_RS4_BE\", Const, 0, \"\"},\n\t\t{\"EM_MIPS_X\", Const, 0, \"\"},\n\t\t{\"EM_MMA\", Const, 0, \"\"},\n\t\t{\"EM_MMDSP_PLUS\", Const, 11, \"\"},\n\t\t{\"EM_MMIX\", Const, 11, \"\"},\n\t\t{\"EM_MN10200\", Const, 11, \"\"},\n\t\t{\"EM_MN10300\", Const, 11, \"\"},\n\t\t{\"EM_MOXIE\", Const, 11, \"\"},\n\t\t{\"EM_MSP430\", Const, 11, \"\"},\n\t\t{\"EM_NCPU\", Const, 0, \"\"},\n\t\t{\"EM_NDR1\", Const, 0, \"\"},\n\t\t{\"EM_NDS32\", Const, 11, \"\"},\n\t\t{\"EM_NONE\", Const, 0, \"\"},\n\t\t{\"EM_NORC\", Const, 11, \"\"},\n\t\t{\"EM_NS32K\", Const, 11, \"\"},\n\t\t{\"EM_OPEN8\", Const, 11, \"\"},\n\t\t{\"EM_OPENRISC\", Const, 11, \"\"},\n\t\t{\"EM_PARISC\", Const, 0, \"\"},\n\t\t{\"EM_PCP\", Const, 0, \"\"},\n\t\t{\"EM_PDP10\", Const, 11, \"\"},\n\t\t{\"EM_PDP11\", Const, 11, \"\"},\n\t\t{\"EM_PDSP\", Const, 11, \"\"},\n\t\t{\"EM_PJ\", Const, 11, \"\"},\n\t\t{\"EM_PPC\", Const, 0, \"\"},\n\t\t{\"EM_PPC64\", Const, 0, \"\"},\n\t\t{\"EM_PRISM\", Const, 11, \"\"},\n\t\t{\"EM_QDSP6\", Const, 11, \"\"},\n\t\t{\"EM_R32C\", Const, 11, \"\"},\n\t\t{\"EM_RCE\", Const, 0, \"\"},\n\t\t{\"EM_RH32\", Const, 0, \"\"},\n\t\t{\"EM_RISCV\", Const, 11, \"\"},\n\t\t{\"EM_RL78\", Const, 11, \"\"},\n\t\t{\"EM_RS08\", Const, 11, \"\"},\n\t\t{\"EM_RX\", Const, 11, \"\"},\n\t\t{\"EM_S370\", Const, 0, \"\"},\n\t\t{\"EM_S390\", Const, 0, \"\"},\n\t\t{\"EM_SCORE7\", Const, 11, \"\"},\n\t\t{\"EM_SEP\", Const, 11, \"\"},\n\t\t{\"EM_SE_C17\", Const, 11, \"\"},\n\t\t{\"EM_SE_C33\", Const, 11, \"\"},\n\t\t{\"EM_SH\", Const, 0, \"\"},\n\t\t{\"EM_SHARC\", Const, 11, \"\"},\n\t\t{\"EM_SLE9X\", Const, 11, \"\"},\n\t\t{\"EM_SNP1K\", Const, 11, \"\"},\n\t\t{\"EM_SPARC\", Const, 0, \"\"},\n\t\t{\"EM_SPARC32PLUS\", Const, 0, \"\"},\n\t\t{\"EM_SPARCV9\", Const, 0, \"\"},\n\t\t{\"EM_ST100\", Const, 0, \"\"},\n\t\t{\"EM_ST19\", Const, 11, \"\"},\n\t\t{\"EM_ST200\", Const, 11, \"\"},\n\t\t{\"EM_ST7\", Const, 11, \"\"},\n\t\t{\"EM_ST9PLUS\", Const, 11, \"\"},\n\t\t{\"EM_STARCORE\", Const, 0, \"\"},\n\t\t{\"EM_STM8\", Const, 11, \"\"},\n\t\t{\"EM_STXP7X\", Const, 11, \"\"},\n\t\t{\"EM_SVX\", Const, 11, \"\"},\n\t\t{\"EM_TILE64\", Const, 11, \"\"},\n\t\t{\"EM_TILEGX\", Const, 11, \"\"},\n\t\t{\"EM_TILEPRO\", Const, 11, \"\"},\n\t\t{\"EM_TINYJ\", Const, 0, \"\"},\n\t\t{\"EM_TI_ARP32\", Const, 11, \"\"},\n\t\t{\"EM_TI_C2000\", Const, 11, \"\"},\n\t\t{\"EM_TI_C5500\", Const, 11, \"\"},\n\t\t{\"EM_TI_C6000\", Const, 11, \"\"},\n\t\t{\"EM_TI_PRU\", Const, 11, \"\"},\n\t\t{\"EM_TMM_GPP\", Const, 11, \"\"},\n\t\t{\"EM_TPC\", Const, 11, \"\"},\n\t\t{\"EM_TRICORE\", Const, 0, \"\"},\n\t\t{\"EM_TRIMEDIA\", Const, 11, \"\"},\n\t\t{\"EM_TSK3000\", Const, 11, \"\"},\n\t\t{\"EM_UNICORE\", Const, 11, \"\"},\n\t\t{\"EM_V800\", Const, 0, \"\"},\n\t\t{\"EM_V850\", Const, 11, \"\"},\n\t\t{\"EM_VAX\", Const, 11, \"\"},\n\t\t{\"EM_VIDEOCORE\", Const, 11, \"\"},\n\t\t{\"EM_VIDEOCORE3\", Const, 11, \"\"},\n\t\t{\"EM_VIDEOCORE5\", Const, 11, \"\"},\n\t\t{\"EM_VISIUM\", Const, 11, \"\"},\n\t\t{\"EM_VPP500\", Const, 0, \"\"},\n\t\t{\"EM_X86_64\", Const, 0, \"\"},\n\t\t{\"EM_XCORE\", Const, 11, \"\"},\n\t\t{\"EM_XGATE\", Const, 11, \"\"},\n\t\t{\"EM_XIMO16\", Const, 11, \"\"},\n\t\t{\"EM_XTENSA\", Const, 11, \"\"},\n\t\t{\"EM_Z80\", Const, 11, \"\"},\n\t\t{\"EM_ZSP\", Const, 11, \"\"},\n\t\t{\"ET_CORE\", Const, 0, \"\"},\n\t\t{\"ET_DYN\", Const, 0, \"\"},\n\t\t{\"ET_EXEC\", Const, 0, \"\"},\n\t\t{\"ET_HIOS\", Const, 0, \"\"},\n\t\t{\"ET_HIPROC\", Const, 0, \"\"},\n\t\t{\"ET_LOOS\", Const, 0, \"\"},\n\t\t{\"ET_LOPROC\", Const, 0, \"\"},\n\t\t{\"ET_NONE\", Const, 0, \"\"},\n\t\t{\"ET_REL\", Const, 0, \"\"},\n\t\t{\"EV_CURRENT\", Const, 0, \"\"},\n\t\t{\"EV_NONE\", Const, 0, \"\"},\n\t\t{\"ErrNoSymbols\", Var, 4, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"File.FileHeader\", Field, 0, \"\"},\n\t\t{\"File.Progs\", Field, 0, \"\"},\n\t\t{\"File.Sections\", Field, 0, \"\"},\n\t\t{\"FileHeader\", Type, 0, \"\"},\n\t\t{\"FileHeader.ABIVersion\", Field, 0, \"\"},\n\t\t{\"FileHeader.ByteOrder\", Field, 0, \"\"},\n\t\t{\"FileHeader.Class\", Field, 0, \"\"},\n\t\t{\"FileHeader.Data\", Field, 0, \"\"},\n\t\t{\"FileHeader.Entry\", Field, 1, \"\"},\n\t\t{\"FileHeader.Machine\", Field, 0, \"\"},\n\t\t{\"FileHeader.OSABI\", Field, 0, \"\"},\n\t\t{\"FileHeader.Type\", Field, 0, \"\"},\n\t\t{\"FileHeader.Version\", Field, 0, \"\"},\n\t\t{\"FormatError\", Type, 0, \"\"},\n\t\t{\"Header32\", Type, 0, \"\"},\n\t\t{\"Header32.Ehsize\", Field, 0, \"\"},\n\t\t{\"Header32.Entry\", Field, 0, \"\"},\n\t\t{\"Header32.Flags\", Field, 0, \"\"},\n\t\t{\"Header32.Ident\", Field, 0, \"\"},\n\t\t{\"Header32.Machine\", Field, 0, \"\"},\n\t\t{\"Header32.Phentsize\", Field, 0, \"\"},\n\t\t{\"Header32.Phnum\", Field, 0, \"\"},\n\t\t{\"Header32.Phoff\", Field, 0, \"\"},\n\t\t{\"Header32.Shentsize\", Field, 0, \"\"},\n\t\t{\"Header32.Shnum\", Field, 0, \"\"},\n\t\t{\"Header32.Shoff\", Field, 0, \"\"},\n\t\t{\"Header32.Shstrndx\", Field, 0, \"\"},\n\t\t{\"Header32.Type\", Field, 0, \"\"},\n\t\t{\"Header32.Version\", Field, 0, \"\"},\n\t\t{\"Header64\", Type, 0, \"\"},\n\t\t{\"Header64.Ehsize\", Field, 0, \"\"},\n\t\t{\"Header64.Entry\", Field, 0, \"\"},\n\t\t{\"Header64.Flags\", Field, 0, \"\"},\n\t\t{\"Header64.Ident\", Field, 0, \"\"},\n\t\t{\"Header64.Machine\", Field, 0, \"\"},\n\t\t{\"Header64.Phentsize\", Field, 0, \"\"},\n\t\t{\"Header64.Phnum\", Field, 0, \"\"},\n\t\t{\"Header64.Phoff\", Field, 0, \"\"},\n\t\t{\"Header64.Shentsize\", Field, 0, \"\"},\n\t\t{\"Header64.Shnum\", Field, 0, \"\"},\n\t\t{\"Header64.Shoff\", Field, 0, \"\"},\n\t\t{\"Header64.Shstrndx\", Field, 0, \"\"},\n\t\t{\"Header64.Type\", Field, 0, \"\"},\n\t\t{\"Header64.Version\", Field, 0, \"\"},\n\t\t{\"ImportedSymbol\", Type, 0, \"\"},\n\t\t{\"ImportedSymbol.Library\", Field, 0, \"\"},\n\t\t{\"ImportedSymbol.Name\", Field, 0, \"\"},\n\t\t{\"ImportedSymbol.Version\", Field, 0, \"\"},\n\t\t{\"Machine\", Type, 0, \"\"},\n\t\t{\"NT_FPREGSET\", Const, 0, \"\"},\n\t\t{\"NT_PRPSINFO\", Const, 0, \"\"},\n\t\t{\"NT_PRSTATUS\", Const, 0, \"\"},\n\t\t{\"NType\", Type, 0, \"\"},\n\t\t{\"NewFile\", Func, 0, \"func(r io.ReaderAt) (*File, error)\"},\n\t\t{\"OSABI\", Type, 0, \"\"},\n\t\t{\"Open\", Func, 0, \"func(name string) (*File, error)\"},\n\t\t{\"PF_MASKOS\", Const, 0, \"\"},\n\t\t{\"PF_MASKPROC\", Const, 0, \"\"},\n\t\t{\"PF_R\", Const, 0, \"\"},\n\t\t{\"PF_W\", Const, 0, \"\"},\n\t\t{\"PF_X\", Const, 0, \"\"},\n\t\t{\"PT_AARCH64_ARCHEXT\", Const, 16, \"\"},\n\t\t{\"PT_AARCH64_UNWIND\", Const, 16, \"\"},\n\t\t{\"PT_ARM_ARCHEXT\", Const, 16, \"\"},\n\t\t{\"PT_ARM_EXIDX\", Const, 16, \"\"},\n\t\t{\"PT_DYNAMIC\", Const, 0, \"\"},\n\t\t{\"PT_GNU_EH_FRAME\", Const, 16, \"\"},\n\t\t{\"PT_GNU_MBIND_HI\", Const, 16, \"\"},\n\t\t{\"PT_GNU_MBIND_LO\", Const, 16, \"\"},\n\t\t{\"PT_GNU_PROPERTY\", Const, 16, \"\"},\n\t\t{\"PT_GNU_RELRO\", Const, 16, \"\"},\n\t\t{\"PT_GNU_STACK\", Const, 16, \"\"},\n\t\t{\"PT_HIOS\", Const, 0, \"\"},\n\t\t{\"PT_HIPROC\", Const, 0, \"\"},\n\t\t{\"PT_INTERP\", Const, 0, \"\"},\n\t\t{\"PT_LOAD\", Const, 0, \"\"},\n\t\t{\"PT_LOOS\", Const, 0, \"\"},\n\t\t{\"PT_LOPROC\", Const, 0, \"\"},\n\t\t{\"PT_MIPS_ABIFLAGS\", Const, 16, \"\"},\n\t\t{\"PT_MIPS_OPTIONS\", Const, 16, \"\"},\n\t\t{\"PT_MIPS_REGINFO\", Const, 16, \"\"},\n\t\t{\"PT_MIPS_RTPROC\", Const, 16, \"\"},\n\t\t{\"PT_NOTE\", Const, 0, \"\"},\n\t\t{\"PT_NULL\", Const, 0, \"\"},\n\t\t{\"PT_OPENBSD_BOOTDATA\", Const, 16, \"\"},\n\t\t{\"PT_OPENBSD_NOBTCFI\", Const, 23, \"\"},\n\t\t{\"PT_OPENBSD_RANDOMIZE\", Const, 16, \"\"},\n\t\t{\"PT_OPENBSD_WXNEEDED\", Const, 16, \"\"},\n\t\t{\"PT_PAX_FLAGS\", Const, 16, \"\"},\n\t\t{\"PT_PHDR\", Const, 0, \"\"},\n\t\t{\"PT_RISCV_ATTRIBUTES\", Const, 25, \"\"},\n\t\t{\"PT_S390_PGSTE\", Const, 16, \"\"},\n\t\t{\"PT_SHLIB\", Const, 0, \"\"},\n\t\t{\"PT_SUNWSTACK\", Const, 16, \"\"},\n\t\t{\"PT_SUNW_EH_FRAME\", Const, 16, \"\"},\n\t\t{\"PT_TLS\", Const, 0, \"\"},\n\t\t{\"Prog\", Type, 0, \"\"},\n\t\t{\"Prog.ProgHeader\", Field, 0, \"\"},\n\t\t{\"Prog.ReaderAt\", Field, 0, \"\"},\n\t\t{\"Prog32\", Type, 0, \"\"},\n\t\t{\"Prog32.Align\", Field, 0, \"\"},\n\t\t{\"Prog32.Filesz\", Field, 0, \"\"},\n\t\t{\"Prog32.Flags\", Field, 0, \"\"},\n\t\t{\"Prog32.Memsz\", Field, 0, \"\"},\n\t\t{\"Prog32.Off\", Field, 0, \"\"},\n\t\t{\"Prog32.Paddr\", Field, 0, \"\"},\n\t\t{\"Prog32.Type\", Field, 0, \"\"},\n\t\t{\"Prog32.Vaddr\", Field, 0, \"\"},\n\t\t{\"Prog64\", Type, 0, \"\"},\n\t\t{\"Prog64.Align\", Field, 0, \"\"},\n\t\t{\"Prog64.Filesz\", Field, 0, \"\"},\n\t\t{\"Prog64.Flags\", Field, 0, \"\"},\n\t\t{\"Prog64.Memsz\", Field, 0, \"\"},\n\t\t{\"Prog64.Off\", Field, 0, \"\"},\n\t\t{\"Prog64.Paddr\", Field, 0, \"\"},\n\t\t{\"Prog64.Type\", Field, 0, \"\"},\n\t\t{\"Prog64.Vaddr\", Field, 0, \"\"},\n\t\t{\"ProgFlag\", Type, 0, \"\"},\n\t\t{\"ProgHeader\", Type, 0, \"\"},\n\t\t{\"ProgHeader.Align\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Filesz\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Flags\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Memsz\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Off\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Paddr\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Type\", Field, 0, \"\"},\n\t\t{\"ProgHeader.Vaddr\", Field, 0, \"\"},\n\t\t{\"ProgType\", Type, 0, \"\"},\n\t\t{\"R_386\", Type, 0, \"\"},\n\t\t{\"R_386_16\", Const, 10, \"\"},\n\t\t{\"R_386_32\", Const, 0, \"\"},\n\t\t{\"R_386_32PLT\", Const, 10, \"\"},\n\t\t{\"R_386_8\", Const, 10, \"\"},\n\t\t{\"R_386_COPY\", Const, 0, \"\"},\n\t\t{\"R_386_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_386_GOT32\", Const, 0, \"\"},\n\t\t{\"R_386_GOT32X\", Const, 10, \"\"},\n\t\t{\"R_386_GOTOFF\", Const, 0, \"\"},\n\t\t{\"R_386_GOTPC\", Const, 0, \"\"},\n\t\t{\"R_386_IRELATIVE\", Const, 10, \"\"},\n\t\t{\"R_386_JMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_386_NONE\", Const, 0, \"\"},\n\t\t{\"R_386_PC16\", Const, 10, \"\"},\n\t\t{\"R_386_PC32\", Const, 0, \"\"},\n\t\t{\"R_386_PC8\", Const, 10, \"\"},\n\t\t{\"R_386_PLT32\", Const, 0, \"\"},\n\t\t{\"R_386_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_386_SIZE32\", Const, 10, \"\"},\n\t\t{\"R_386_TLS_DESC\", Const, 10, \"\"},\n\t\t{\"R_386_TLS_DESC_CALL\", Const, 10, \"\"},\n\t\t{\"R_386_TLS_DTPMOD32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_DTPOFF32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GD\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GD_32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GD_CALL\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GD_POP\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GD_PUSH\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_GOTDESC\", Const, 10, \"\"},\n\t\t{\"R_386_TLS_GOTIE\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_IE\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_IE_32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDM\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDM_32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDM_CALL\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDM_POP\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDM_PUSH\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LDO_32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LE\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_LE_32\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_TPOFF\", Const, 0, \"\"},\n\t\t{\"R_386_TLS_TPOFF32\", Const, 0, \"\"},\n\t\t{\"R_390\", Type, 7, \"\"},\n\t\t{\"R_390_12\", Const, 7, \"\"},\n\t\t{\"R_390_16\", Const, 7, \"\"},\n\t\t{\"R_390_20\", Const, 7, \"\"},\n\t\t{\"R_390_32\", Const, 7, \"\"},\n\t\t{\"R_390_64\", Const, 7, \"\"},\n\t\t{\"R_390_8\", Const, 7, \"\"},\n\t\t{\"R_390_COPY\", Const, 7, \"\"},\n\t\t{\"R_390_GLOB_DAT\", Const, 7, \"\"},\n\t\t{\"R_390_GOT12\", Const, 7, \"\"},\n\t\t{\"R_390_GOT16\", Const, 7, \"\"},\n\t\t{\"R_390_GOT20\", Const, 7, \"\"},\n\t\t{\"R_390_GOT32\", Const, 7, \"\"},\n\t\t{\"R_390_GOT64\", Const, 7, \"\"},\n\t\t{\"R_390_GOTENT\", Const, 7, \"\"},\n\t\t{\"R_390_GOTOFF\", Const, 7, \"\"},\n\t\t{\"R_390_GOTOFF16\", Const, 7, \"\"},\n\t\t{\"R_390_GOTOFF64\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPC\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPCDBL\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLT12\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLT16\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLT20\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLT32\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLT64\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLTENT\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLTOFF16\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLTOFF32\", Const, 7, \"\"},\n\t\t{\"R_390_GOTPLTOFF64\", Const, 7, \"\"},\n\t\t{\"R_390_JMP_SLOT\", Const, 7, \"\"},\n\t\t{\"R_390_NONE\", Const, 7, \"\"},\n\t\t{\"R_390_PC16\", Const, 7, \"\"},\n\t\t{\"R_390_PC16DBL\", Const, 7, \"\"},\n\t\t{\"R_390_PC32\", Const, 7, \"\"},\n\t\t{\"R_390_PC32DBL\", Const, 7, \"\"},\n\t\t{\"R_390_PC64\", Const, 7, \"\"},\n\t\t{\"R_390_PLT16DBL\", Const, 7, \"\"},\n\t\t{\"R_390_PLT32\", Const, 7, \"\"},\n\t\t{\"R_390_PLT32DBL\", Const, 7, \"\"},\n\t\t{\"R_390_PLT64\", Const, 7, \"\"},\n\t\t{\"R_390_RELATIVE\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_DTPMOD\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_DTPOFF\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GD32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GD64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GDCALL\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GOTIE12\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GOTIE20\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GOTIE32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_GOTIE64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_IE32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_IE64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_IEENT\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LDCALL\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LDM32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LDM64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LDO32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LDO64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LE32\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LE64\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_LOAD\", Const, 7, \"\"},\n\t\t{\"R_390_TLS_TPOFF\", Const, 7, \"\"},\n\t\t{\"R_AARCH64\", Type, 4, \"\"},\n\t\t{\"R_AARCH64_ABS16\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ABS32\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ABS64\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ADD_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ADR_GOT_PAGE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ADR_PREL_LO21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ADR_PREL_PG_HI21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_ADR_PREL_PG_HI21_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_CALL26\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_CONDBR19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_COPY\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_GLOB_DAT\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_GOT_LD_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_IRELATIVE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_JUMP26\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_JUMP_SLOT\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LD64_GOTOFF_LO15\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_LD64_GOTPAGE_LO15\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_LD64_GOT_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LDST128_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LDST16_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LDST32_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LDST64_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LDST8_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_LD_PREL_LO19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_SABS_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_SABS_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_SABS_G2\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G1_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G2\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G2_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_MOVW_UABS_G3\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_NONE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_NULL\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ABS16\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ABS32\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ADD_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ADR_GOT_PAGE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ADR_PREL_LO21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_ADR_PREL_PG_HI21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_CALL26\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_CONDBR19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_COPY\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_GLOB_DAT\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_GOT_LD_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_IRELATIVE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_JUMP26\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_JUMP_SLOT\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LD32_GOT_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LDST128_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LDST16_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LDST32_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LDST64_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LDST8_ABS_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_LD_PREL_LO19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_MOVW_SABS_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_MOVW_UABS_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_MOVW_UABS_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_MOVW_UABS_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_PREL16\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_PREL32\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_RELATIVE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_ADD_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_ADR_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_ADR_PREL21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_CALL\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_LD32_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSDESC_LD_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSGD_ADD_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSGD_ADR_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_ADD_TPREL_HI12\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_ADD_TPREL_LO12\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_MOVW_TPREL_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLSLE_MOVW_TPREL_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLS_DTPMOD\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLS_DTPREL\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TLS_TPREL\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_P32_TSTBR14\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_PREL16\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_PREL32\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_PREL64\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_RELATIVE\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_ADD\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_ADD_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_ADR_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_ADR_PREL21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_CALL\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_LD64_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_LDR\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_LD_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_OFF_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSDESC_OFF_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSGD_ADD_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSGD_ADR_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSGD_ADR_PREL21\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSGD_MOVW_G0_NC\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSGD_MOVW_G1\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSIE_LD_GOTTPREL_PREL19\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSIE_MOVW_GOTTPREL_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLD_ADR_PAGE21\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLD_ADR_PREL21\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLD_LDST128_DTPREL_LO12\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLE_ADD_TPREL_HI12\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_ADD_TPREL_LO12\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_ADD_TPREL_LO12_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_LDST128_TPREL_LO12\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC\", Const, 10, \"\"},\n\t\t{\"R_AARCH64_TLSLE_MOVW_TPREL_G0\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_MOVW_TPREL_G0_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_MOVW_TPREL_G1\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_MOVW_TPREL_G1_NC\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLSLE_MOVW_TPREL_G2\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLS_DTPMOD64\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLS_DTPREL64\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TLS_TPREL64\", Const, 4, \"\"},\n\t\t{\"R_AARCH64_TSTBR14\", Const, 4, \"\"},\n\t\t{\"R_ALPHA\", Type, 0, \"\"},\n\t\t{\"R_ALPHA_BRADDR\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_COPY\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GPDISP\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GPREL32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GPRELHIGH\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GPRELLOW\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_GPVALUE\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_HINT\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_IMMED_BR_HI32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_IMMED_GP_16\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_IMMED_GP_HI32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_IMMED_LO32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_IMMED_SCN_HI32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_JMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_LITERAL\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_LITUSE\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_NONE\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_OP_PRSHIFT\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_OP_PSUB\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_OP_PUSH\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_OP_STORE\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_REFLONG\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_REFQUAD\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_SREL16\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_SREL32\", Const, 0, \"\"},\n\t\t{\"R_ALPHA_SREL64\", Const, 0, \"\"},\n\t\t{\"R_ARM\", Type, 0, \"\"},\n\t\t{\"R_ARM_ABS12\", Const, 0, \"\"},\n\t\t{\"R_ARM_ABS16\", Const, 0, \"\"},\n\t\t{\"R_ARM_ABS32\", Const, 0, \"\"},\n\t\t{\"R_ARM_ABS32_NOI\", Const, 10, \"\"},\n\t\t{\"R_ARM_ABS8\", Const, 0, \"\"},\n\t\t{\"R_ARM_ALU_PCREL_15_8\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PCREL_23_15\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PCREL_7_0\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PC_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PC_G0_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PC_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PC_G1_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_PC_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SBREL_19_12_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SBREL_27_20_CK\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SB_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SB_G0_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SB_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SB_G1_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_ALU_SB_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_AMP_VCALL9\", Const, 0, \"\"},\n\t\t{\"R_ARM_BASE_ABS\", Const, 10, \"\"},\n\t\t{\"R_ARM_CALL\", Const, 10, \"\"},\n\t\t{\"R_ARM_COPY\", Const, 0, \"\"},\n\t\t{\"R_ARM_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_ARM_GNU_VTENTRY\", Const, 0, \"\"},\n\t\t{\"R_ARM_GNU_VTINHERIT\", Const, 0, \"\"},\n\t\t{\"R_ARM_GOT32\", Const, 0, \"\"},\n\t\t{\"R_ARM_GOTOFF\", Const, 0, \"\"},\n\t\t{\"R_ARM_GOTOFF12\", Const, 10, \"\"},\n\t\t{\"R_ARM_GOTPC\", Const, 0, \"\"},\n\t\t{\"R_ARM_GOTRELAX\", Const, 10, \"\"},\n\t\t{\"R_ARM_GOT_ABS\", Const, 10, \"\"},\n\t\t{\"R_ARM_GOT_BREL12\", Const, 10, \"\"},\n\t\t{\"R_ARM_GOT_PREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_IRELATIVE\", Const, 10, \"\"},\n\t\t{\"R_ARM_JUMP24\", Const, 10, \"\"},\n\t\t{\"R_ARM_JUMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_ARM_LDC_PC_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDC_PC_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDC_PC_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDC_SB_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDC_SB_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDC_SB_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_PC_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_PC_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_PC_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_SB_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_SB_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDRS_SB_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_PC_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_PC_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_SBREL_11_10_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_SB_G0\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_SB_G1\", Const, 10, \"\"},\n\t\t{\"R_ARM_LDR_SB_G2\", Const, 10, \"\"},\n\t\t{\"R_ARM_ME_TOO\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVT_ABS\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVT_BREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVT_PREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVW_ABS_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVW_BREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVW_BREL_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_MOVW_PREL_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_NONE\", Const, 0, \"\"},\n\t\t{\"R_ARM_PC13\", Const, 0, \"\"},\n\t\t{\"R_ARM_PC24\", Const, 0, \"\"},\n\t\t{\"R_ARM_PLT32\", Const, 0, \"\"},\n\t\t{\"R_ARM_PLT32_ABS\", Const, 10, \"\"},\n\t\t{\"R_ARM_PREL31\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_0\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_1\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_10\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_11\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_12\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_13\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_14\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_15\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_2\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_3\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_4\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_5\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_6\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_7\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_8\", Const, 10, \"\"},\n\t\t{\"R_ARM_PRIVATE_9\", Const, 10, \"\"},\n\t\t{\"R_ARM_RABS32\", Const, 0, \"\"},\n\t\t{\"R_ARM_RBASE\", Const, 0, \"\"},\n\t\t{\"R_ARM_REL32\", Const, 0, \"\"},\n\t\t{\"R_ARM_REL32_NOI\", Const, 10, \"\"},\n\t\t{\"R_ARM_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_ARM_RPC24\", Const, 0, \"\"},\n\t\t{\"R_ARM_RREL32\", Const, 0, \"\"},\n\t\t{\"R_ARM_RSBREL32\", Const, 0, \"\"},\n\t\t{\"R_ARM_RXPC25\", Const, 10, \"\"},\n\t\t{\"R_ARM_SBREL31\", Const, 10, \"\"},\n\t\t{\"R_ARM_SBREL32\", Const, 0, \"\"},\n\t\t{\"R_ARM_SWI24\", Const, 0, \"\"},\n\t\t{\"R_ARM_TARGET1\", Const, 10, \"\"},\n\t\t{\"R_ARM_TARGET2\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_ABS5\", Const, 0, \"\"},\n\t\t{\"R_ARM_THM_ALU_ABS_G0_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_ALU_ABS_G1_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_ALU_ABS_G2_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_ALU_ABS_G3\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_ALU_PREL_11_0\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_GOT_BREL12\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_JUMP11\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_JUMP19\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_JUMP24\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_JUMP6\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_JUMP8\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVT_ABS\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVT_BREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVT_PREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVW_ABS_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVW_BREL\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVW_BREL_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_MOVW_PREL_NC\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_PC12\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_PC22\", Const, 0, \"\"},\n\t\t{\"R_ARM_THM_PC8\", Const, 0, \"\"},\n\t\t{\"R_ARM_THM_RPC22\", Const, 0, \"\"},\n\t\t{\"R_ARM_THM_SWI8\", Const, 0, \"\"},\n\t\t{\"R_ARM_THM_TLS_CALL\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_TLS_DESCSEQ16\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_TLS_DESCSEQ32\", Const, 10, \"\"},\n\t\t{\"R_ARM_THM_XPC22\", Const, 0, \"\"},\n\t\t{\"R_ARM_TLS_CALL\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_DESCSEQ\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_DTPMOD32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_DTPOFF32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_GD32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_GOTDESC\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_IE12GP\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_IE32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_LDM32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_LDO12\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_LDO32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_LE12\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_LE32\", Const, 10, \"\"},\n\t\t{\"R_ARM_TLS_TPOFF32\", Const, 10, \"\"},\n\t\t{\"R_ARM_V4BX\", Const, 10, \"\"},\n\t\t{\"R_ARM_XPC25\", Const, 0, \"\"},\n\t\t{\"R_INFO\", Func, 0, \"func(sym uint32, typ uint32) uint64\"},\n\t\t{\"R_INFO32\", Func, 0, \"func(sym uint32, typ uint32) uint32\"},\n\t\t{\"R_LARCH\", Type, 19, \"\"},\n\t\t{\"R_LARCH_32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_32_PCREL\", Const, 20, \"\"},\n\t\t{\"R_LARCH_64\", Const, 19, \"\"},\n\t\t{\"R_LARCH_64_PCREL\", Const, 22, \"\"},\n\t\t{\"R_LARCH_ABS64_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_ABS64_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_ABS_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_ABS_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_ADD16\", Const, 19, \"\"},\n\t\t{\"R_LARCH_ADD24\", Const, 19, \"\"},\n\t\t{\"R_LARCH_ADD32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_ADD6\", Const, 22, \"\"},\n\t\t{\"R_LARCH_ADD64\", Const, 19, \"\"},\n\t\t{\"R_LARCH_ADD8\", Const, 19, \"\"},\n\t\t{\"R_LARCH_ADD_ULEB128\", Const, 22, \"\"},\n\t\t{\"R_LARCH_ALIGN\", Const, 22, \"\"},\n\t\t{\"R_LARCH_B16\", Const, 20, \"\"},\n\t\t{\"R_LARCH_B21\", Const, 20, \"\"},\n\t\t{\"R_LARCH_B26\", Const, 20, \"\"},\n\t\t{\"R_LARCH_CALL36\", Const, 26, \"\"},\n\t\t{\"R_LARCH_CFA\", Const, 22, \"\"},\n\t\t{\"R_LARCH_COPY\", Const, 19, \"\"},\n\t\t{\"R_LARCH_DELETE\", Const, 22, \"\"},\n\t\t{\"R_LARCH_GNU_VTENTRY\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GNU_VTINHERIT\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT64_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT64_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT64_PC_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT64_PC_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT_PC_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_GOT_PC_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_IRELATIVE\", Const, 19, \"\"},\n\t\t{\"R_LARCH_JUMP_SLOT\", Const, 19, \"\"},\n\t\t{\"R_LARCH_MARK_LA\", Const, 19, \"\"},\n\t\t{\"R_LARCH_MARK_PCREL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_NONE\", Const, 19, \"\"},\n\t\t{\"R_LARCH_PCALA64_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_PCALA64_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_PCALA_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_PCALA_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_PCREL20_S2\", Const, 22, \"\"},\n\t\t{\"R_LARCH_RELATIVE\", Const, 19, \"\"},\n\t\t{\"R_LARCH_RELAX\", Const, 20, \"\"},\n\t\t{\"R_LARCH_SOP_ADD\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_AND\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_ASSERT\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_IF_ELSE\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_NOT\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_0_10_10_16_S2\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_0_5_10_16_S2\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_10_12\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_10_16\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_10_16_S2\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_10_5\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_S_5_20\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_U\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_POP_32_U_10_12\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_ABSOLUTE\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_DUP\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_GPREL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_PCREL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_PLT_PCREL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_TLS_GD\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_TLS_GOT\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_PUSH_TLS_TPREL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_SL\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_SR\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SOP_SUB\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB16\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB24\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB6\", Const, 22, \"\"},\n\t\t{\"R_LARCH_SUB64\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB8\", Const, 19, \"\"},\n\t\t{\"R_LARCH_SUB_ULEB128\", Const, 22, \"\"},\n\t\t{\"R_LARCH_TLS_DESC32\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC64\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC64_HI12\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC64_LO20\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC64_PC_HI12\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC64_PC_LO20\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_CALL\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_HI20\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_LD\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_LO12\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_PCREL20_S2\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_PC_HI20\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DESC_PC_LO12\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_DTPMOD32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_TLS_DTPMOD64\", Const, 19, \"\"},\n\t\t{\"R_LARCH_TLS_DTPREL32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_TLS_DTPREL64\", Const, 19, \"\"},\n\t\t{\"R_LARCH_TLS_GD_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_GD_PCREL20_S2\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_GD_PC_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE64_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE64_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE64_PC_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE64_PC_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE_PC_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_IE_PC_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LD_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LD_PCREL20_S2\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_LD_PC_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LE64_HI12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LE64_LO20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LE_ADD_R\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_LE_HI20\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LE_HI20_R\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_LE_LO12\", Const, 20, \"\"},\n\t\t{\"R_LARCH_TLS_LE_LO12_R\", Const, 26, \"\"},\n\t\t{\"R_LARCH_TLS_TPREL32\", Const, 19, \"\"},\n\t\t{\"R_LARCH_TLS_TPREL64\", Const, 19, \"\"},\n\t\t{\"R_MIPS\", Type, 6, \"\"},\n\t\t{\"R_MIPS_16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_26\", Const, 6, \"\"},\n\t\t{\"R_MIPS_32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_64\", Const, 6, \"\"},\n\t\t{\"R_MIPS_ADD_IMMEDIATE\", Const, 6, \"\"},\n\t\t{\"R_MIPS_CALL16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_CALL_HI16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_CALL_LO16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_DELETE\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT_DISP\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT_HI16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT_LO16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT_OFST\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GOT_PAGE\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GPREL16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_GPREL32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_HI16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_HIGHER\", Const, 6, \"\"},\n\t\t{\"R_MIPS_HIGHEST\", Const, 6, \"\"},\n\t\t{\"R_MIPS_INSERT_A\", Const, 6, \"\"},\n\t\t{\"R_MIPS_INSERT_B\", Const, 6, \"\"},\n\t\t{\"R_MIPS_JALR\", Const, 6, \"\"},\n\t\t{\"R_MIPS_LITERAL\", Const, 6, \"\"},\n\t\t{\"R_MIPS_LO16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_NONE\", Const, 6, \"\"},\n\t\t{\"R_MIPS_PC16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_PC32\", Const, 22, \"\"},\n\t\t{\"R_MIPS_PJUMP\", Const, 6, \"\"},\n\t\t{\"R_MIPS_REL16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_REL32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_RELGOT\", Const, 6, \"\"},\n\t\t{\"R_MIPS_SCN_DISP\", Const, 6, \"\"},\n\t\t{\"R_MIPS_SHIFT5\", Const, 6, \"\"},\n\t\t{\"R_MIPS_SHIFT6\", Const, 6, \"\"},\n\t\t{\"R_MIPS_SUB\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPMOD32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPMOD64\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPREL32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPREL64\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPREL_HI16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_DTPREL_LO16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_GD\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_GOTTPREL\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_LDM\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_TPREL32\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_TPREL64\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_TPREL_HI16\", Const, 6, \"\"},\n\t\t{\"R_MIPS_TLS_TPREL_LO16\", Const, 6, \"\"},\n\t\t{\"R_PPC\", Type, 0, \"\"},\n\t\t{\"R_PPC64\", Type, 5, \"\"},\n\t\t{\"R_PPC64_ADDR14\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR14_BRNTAKEN\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR14_BRTAKEN\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGH\", Const, 10, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHA\", Const, 10, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHER\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHER34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHERA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHERA34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHEST\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHEST34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHESTA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_HIGHESTA34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_ADDR16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR24\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR32\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR64\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ADDR64_LOCAL\", Const, 10, \"\"},\n\t\t{\"R_PPC64_COPY\", Const, 20, \"\"},\n\t\t{\"R_PPC64_D28\", Const, 20, \"\"},\n\t\t{\"R_PPC64_D34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_D34_HA30\", Const, 20, \"\"},\n\t\t{\"R_PPC64_D34_HI30\", Const, 20, \"\"},\n\t\t{\"R_PPC64_D34_LO\", Const, 20, \"\"},\n\t\t{\"R_PPC64_DTPMOD64\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGH\", Const, 10, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGHA\", Const, 10, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGHER\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGHERA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGHEST\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_HIGHESTA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_DTPREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_DTPREL64\", Const, 5, \"\"},\n\t\t{\"R_PPC64_ENTRY\", Const, 10, \"\"},\n\t\t{\"R_PPC64_GLOB_DAT\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GNU_VTENTRY\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GNU_VTINHERIT\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GOT16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_DTPREL16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_DTPREL16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_DTPREL16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_DTPREL16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_DTPREL_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GOT_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GOT_TLSGD16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSGD16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSGD16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSGD16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSGD_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GOT_TLSLD16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSLD16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSLD16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSLD16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TLSLD_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_GOT_TPREL16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TPREL16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TPREL16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TPREL16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_GOT_TPREL_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_IRELATIVE\", Const, 10, \"\"},\n\t\t{\"R_PPC64_JMP_IREL\", Const, 10, \"\"},\n\t\t{\"R_PPC64_JMP_SLOT\", Const, 5, \"\"},\n\t\t{\"R_PPC64_NONE\", Const, 5, \"\"},\n\t\t{\"R_PPC64_PCREL28\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PCREL_OPT\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT16_HA\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT16_HI\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT16_LO\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT16_LO_DS\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLT32\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT64\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTCALL\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTCALL_NOTOC\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTGOT16\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTGOT16_DS\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTGOT16_HA\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTGOT16_HI\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTGOT16_LO\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTGOT_LO_DS\", Const, 10, \"\"},\n\t\t{\"R_PPC64_PLTREL32\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTREL64\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTSEQ\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLTSEQ_NOTOC\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT_PCREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_PLT_PCREL34_NOTOC\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL14\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL14_BRNTAKEN\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL14_BRTAKEN\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL16DX_HA\", Const, 10, \"\"},\n\t\t{\"R_PPC64_REL16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL16_HIGH\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHA\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHER\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHER34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHERA\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHERA34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHEST\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHEST34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHESTA\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_HIGHESTA34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL24\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL24_NOTOC\", Const, 10, \"\"},\n\t\t{\"R_PPC64_REL24_P9NOTOC\", Const, 21, \"\"},\n\t\t{\"R_PPC64_REL30\", Const, 20, \"\"},\n\t\t{\"R_PPC64_REL32\", Const, 5, \"\"},\n\t\t{\"R_PPC64_REL64\", Const, 5, \"\"},\n\t\t{\"R_PPC64_RELATIVE\", Const, 18, \"\"},\n\t\t{\"R_PPC64_SECTOFF\", Const, 20, \"\"},\n\t\t{\"R_PPC64_SECTOFF_DS\", Const, 10, \"\"},\n\t\t{\"R_PPC64_SECTOFF_HA\", Const, 20, \"\"},\n\t\t{\"R_PPC64_SECTOFF_HI\", Const, 20, \"\"},\n\t\t{\"R_PPC64_SECTOFF_LO\", Const, 20, \"\"},\n\t\t{\"R_PPC64_SECTOFF_LO_DS\", Const, 10, \"\"},\n\t\t{\"R_PPC64_TLS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TLSGD\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TLSLD\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOC16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TOCSAVE\", Const, 10, \"\"},\n\t\t{\"R_PPC64_TPREL16\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HI\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGH\", Const, 10, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGHA\", Const, 10, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGHER\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGHERA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGHEST\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_HIGHESTA\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_LO\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL16_LO_DS\", Const, 5, \"\"},\n\t\t{\"R_PPC64_TPREL34\", Const, 20, \"\"},\n\t\t{\"R_PPC64_TPREL64\", Const, 5, \"\"},\n\t\t{\"R_PPC64_UADDR16\", Const, 20, \"\"},\n\t\t{\"R_PPC64_UADDR32\", Const, 20, \"\"},\n\t\t{\"R_PPC64_UADDR64\", Const, 20, \"\"},\n\t\t{\"R_PPC_ADDR14\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR14_BRNTAKEN\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR14_BRTAKEN\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR16\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR24\", Const, 0, \"\"},\n\t\t{\"R_PPC_ADDR32\", Const, 0, \"\"},\n\t\t{\"R_PPC_COPY\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPMOD32\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPREL16\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPREL16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPREL16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPREL16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_DTPREL32\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_BIT_FLD\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_MRKREF\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_NADDR16\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_NADDR16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_NADDR16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_NADDR16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_NADDR32\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_RELSDA\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_RELSEC16\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_RELST_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_RELST_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_RELST_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_SDA21\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_SDA2I16\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_SDA2REL\", Const, 0, \"\"},\n\t\t{\"R_PPC_EMB_SDAI16\", Const, 0, \"\"},\n\t\t{\"R_PPC_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT16\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSGD16\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSGD16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSGD16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSGD16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSLD16\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSLD16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSLD16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TLSLD16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TPREL16\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TPREL16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TPREL16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_GOT_TPREL16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_JMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_PPC_LOCAL24PC\", Const, 0, \"\"},\n\t\t{\"R_PPC_NONE\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLT16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLT16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLT16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLT32\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLTREL24\", Const, 0, \"\"},\n\t\t{\"R_PPC_PLTREL32\", Const, 0, \"\"},\n\t\t{\"R_PPC_REL14\", Const, 0, \"\"},\n\t\t{\"R_PPC_REL14_BRNTAKEN\", Const, 0, \"\"},\n\t\t{\"R_PPC_REL14_BRTAKEN\", Const, 0, \"\"},\n\t\t{\"R_PPC_REL24\", Const, 0, \"\"},\n\t\t{\"R_PPC_REL32\", Const, 0, \"\"},\n\t\t{\"R_PPC_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_PPC_SDAREL16\", Const, 0, \"\"},\n\t\t{\"R_PPC_SECTOFF\", Const, 0, \"\"},\n\t\t{\"R_PPC_SECTOFF_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_SECTOFF_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_SECTOFF_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_TLS\", Const, 0, \"\"},\n\t\t{\"R_PPC_TPREL16\", Const, 0, \"\"},\n\t\t{\"R_PPC_TPREL16_HA\", Const, 0, \"\"},\n\t\t{\"R_PPC_TPREL16_HI\", Const, 0, \"\"},\n\t\t{\"R_PPC_TPREL16_LO\", Const, 0, \"\"},\n\t\t{\"R_PPC_TPREL32\", Const, 0, \"\"},\n\t\t{\"R_PPC_UADDR16\", Const, 0, \"\"},\n\t\t{\"R_PPC_UADDR32\", Const, 0, \"\"},\n\t\t{\"R_RISCV\", Type, 11, \"\"},\n\t\t{\"R_RISCV_32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_32_PCREL\", Const, 12, \"\"},\n\t\t{\"R_RISCV_64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_ADD16\", Const, 11, \"\"},\n\t\t{\"R_RISCV_ADD32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_ADD64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_ADD8\", Const, 11, \"\"},\n\t\t{\"R_RISCV_ALIGN\", Const, 11, \"\"},\n\t\t{\"R_RISCV_BRANCH\", Const, 11, \"\"},\n\t\t{\"R_RISCV_CALL\", Const, 11, \"\"},\n\t\t{\"R_RISCV_CALL_PLT\", Const, 11, \"\"},\n\t\t{\"R_RISCV_COPY\", Const, 11, \"\"},\n\t\t{\"R_RISCV_GNU_VTENTRY\", Const, 11, \"\"},\n\t\t{\"R_RISCV_GNU_VTINHERIT\", Const, 11, \"\"},\n\t\t{\"R_RISCV_GOT_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_GPREL_I\", Const, 11, \"\"},\n\t\t{\"R_RISCV_GPREL_S\", Const, 11, \"\"},\n\t\t{\"R_RISCV_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_JAL\", Const, 11, \"\"},\n\t\t{\"R_RISCV_JUMP_SLOT\", Const, 11, \"\"},\n\t\t{\"R_RISCV_LO12_I\", Const, 11, \"\"},\n\t\t{\"R_RISCV_LO12_S\", Const, 11, \"\"},\n\t\t{\"R_RISCV_NONE\", Const, 11, \"\"},\n\t\t{\"R_RISCV_PCREL_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_PCREL_LO12_I\", Const, 11, \"\"},\n\t\t{\"R_RISCV_PCREL_LO12_S\", Const, 11, \"\"},\n\t\t{\"R_RISCV_RELATIVE\", Const, 11, \"\"},\n\t\t{\"R_RISCV_RELAX\", Const, 11, \"\"},\n\t\t{\"R_RISCV_RVC_BRANCH\", Const, 11, \"\"},\n\t\t{\"R_RISCV_RVC_JUMP\", Const, 11, \"\"},\n\t\t{\"R_RISCV_RVC_LUI\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SET16\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SET32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SET6\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SET8\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SUB16\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SUB32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SUB6\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SUB64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_SUB8\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_DTPMOD32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_DTPMOD64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_DTPREL32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_DTPREL64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_GD_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_GOT_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_TPREL32\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TLS_TPREL64\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_ADD\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_HI20\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_I\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_LO12_I\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_LO12_S\", Const, 11, \"\"},\n\t\t{\"R_RISCV_TPREL_S\", Const, 11, \"\"},\n\t\t{\"R_SPARC\", Type, 0, \"\"},\n\t\t{\"R_SPARC_10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_11\", Const, 0, \"\"},\n\t\t{\"R_SPARC_13\", Const, 0, \"\"},\n\t\t{\"R_SPARC_16\", Const, 0, \"\"},\n\t\t{\"R_SPARC_22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_32\", Const, 0, \"\"},\n\t\t{\"R_SPARC_5\", Const, 0, \"\"},\n\t\t{\"R_SPARC_6\", Const, 0, \"\"},\n\t\t{\"R_SPARC_64\", Const, 0, \"\"},\n\t\t{\"R_SPARC_7\", Const, 0, \"\"},\n\t\t{\"R_SPARC_8\", Const, 0, \"\"},\n\t\t{\"R_SPARC_COPY\", Const, 0, \"\"},\n\t\t{\"R_SPARC_DISP16\", Const, 0, \"\"},\n\t\t{\"R_SPARC_DISP32\", Const, 0, \"\"},\n\t\t{\"R_SPARC_DISP64\", Const, 0, \"\"},\n\t\t{\"R_SPARC_DISP8\", Const, 0, \"\"},\n\t\t{\"R_SPARC_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_SPARC_GLOB_JMP\", Const, 0, \"\"},\n\t\t{\"R_SPARC_GOT10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_GOT13\", Const, 0, \"\"},\n\t\t{\"R_SPARC_GOT22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_H44\", Const, 0, \"\"},\n\t\t{\"R_SPARC_HH22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_HI22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_HIPLT22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_HIX22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_HM10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_JMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_SPARC_L44\", Const, 0, \"\"},\n\t\t{\"R_SPARC_LM22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_LO10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_LOPLT10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_LOX10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_M44\", Const, 0, \"\"},\n\t\t{\"R_SPARC_NONE\", Const, 0, \"\"},\n\t\t{\"R_SPARC_OLO10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PC10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PC22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PCPLT10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PCPLT22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PCPLT32\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PC_HH22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PC_HM10\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PC_LM22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PLT32\", Const, 0, \"\"},\n\t\t{\"R_SPARC_PLT64\", Const, 0, \"\"},\n\t\t{\"R_SPARC_REGISTER\", Const, 0, \"\"},\n\t\t{\"R_SPARC_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_SPARC_UA16\", Const, 0, \"\"},\n\t\t{\"R_SPARC_UA32\", Const, 0, \"\"},\n\t\t{\"R_SPARC_UA64\", Const, 0, \"\"},\n\t\t{\"R_SPARC_WDISP16\", Const, 0, \"\"},\n\t\t{\"R_SPARC_WDISP19\", Const, 0, \"\"},\n\t\t{\"R_SPARC_WDISP22\", Const, 0, \"\"},\n\t\t{\"R_SPARC_WDISP30\", Const, 0, \"\"},\n\t\t{\"R_SPARC_WPLT30\", Const, 0, \"\"},\n\t\t{\"R_SYM32\", Func, 0, \"func(info uint32) uint32\"},\n\t\t{\"R_SYM64\", Func, 0, \"func(info uint64) uint32\"},\n\t\t{\"R_TYPE32\", Func, 0, \"func(info uint32) uint32\"},\n\t\t{\"R_TYPE64\", Func, 0, \"func(info uint64) uint32\"},\n\t\t{\"R_X86_64\", Type, 0, \"\"},\n\t\t{\"R_X86_64_16\", Const, 0, \"\"},\n\t\t{\"R_X86_64_32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_32S\", Const, 0, \"\"},\n\t\t{\"R_X86_64_64\", Const, 0, \"\"},\n\t\t{\"R_X86_64_8\", Const, 0, \"\"},\n\t\t{\"R_X86_64_COPY\", Const, 0, \"\"},\n\t\t{\"R_X86_64_DTPMOD64\", Const, 0, \"\"},\n\t\t{\"R_X86_64_DTPOFF32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_DTPOFF64\", Const, 0, \"\"},\n\t\t{\"R_X86_64_GLOB_DAT\", Const, 0, \"\"},\n\t\t{\"R_X86_64_GOT32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_GOT64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTOFF64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPC32\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPC32_TLSDESC\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPC64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPCREL\", Const, 0, \"\"},\n\t\t{\"R_X86_64_GOTPCREL64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPCRELX\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTPLT64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_GOTTPOFF\", Const, 0, \"\"},\n\t\t{\"R_X86_64_IRELATIVE\", Const, 10, \"\"},\n\t\t{\"R_X86_64_JMP_SLOT\", Const, 0, \"\"},\n\t\t{\"R_X86_64_NONE\", Const, 0, \"\"},\n\t\t{\"R_X86_64_PC16\", Const, 0, \"\"},\n\t\t{\"R_X86_64_PC32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_PC32_BND\", Const, 10, \"\"},\n\t\t{\"R_X86_64_PC64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_PC8\", Const, 0, \"\"},\n\t\t{\"R_X86_64_PLT32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_PLT32_BND\", Const, 10, \"\"},\n\t\t{\"R_X86_64_PLTOFF64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_RELATIVE\", Const, 0, \"\"},\n\t\t{\"R_X86_64_RELATIVE64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_REX_GOTPCRELX\", Const, 10, \"\"},\n\t\t{\"R_X86_64_SIZE32\", Const, 10, \"\"},\n\t\t{\"R_X86_64_SIZE64\", Const, 10, \"\"},\n\t\t{\"R_X86_64_TLSDESC\", Const, 10, \"\"},\n\t\t{\"R_X86_64_TLSDESC_CALL\", Const, 10, \"\"},\n\t\t{\"R_X86_64_TLSGD\", Const, 0, \"\"},\n\t\t{\"R_X86_64_TLSLD\", Const, 0, \"\"},\n\t\t{\"R_X86_64_TPOFF32\", Const, 0, \"\"},\n\t\t{\"R_X86_64_TPOFF64\", Const, 0, \"\"},\n\t\t{\"Rel32\", Type, 0, \"\"},\n\t\t{\"Rel32.Info\", Field, 0, \"\"},\n\t\t{\"Rel32.Off\", Field, 0, \"\"},\n\t\t{\"Rel64\", Type, 0, \"\"},\n\t\t{\"Rel64.Info\", Field, 0, \"\"},\n\t\t{\"Rel64.Off\", Field, 0, \"\"},\n\t\t{\"Rela32\", Type, 0, \"\"},\n\t\t{\"Rela32.Addend\", Field, 0, \"\"},\n\t\t{\"Rela32.Info\", Field, 0, \"\"},\n\t\t{\"Rela32.Off\", Field, 0, \"\"},\n\t\t{\"Rela64\", Type, 0, \"\"},\n\t\t{\"Rela64.Addend\", Field, 0, \"\"},\n\t\t{\"Rela64.Info\", Field, 0, \"\"},\n\t\t{\"Rela64.Off\", Field, 0, \"\"},\n\t\t{\"SHF_ALLOC\", Const, 0, \"\"},\n\t\t{\"SHF_COMPRESSED\", Const, 6, \"\"},\n\t\t{\"SHF_EXECINSTR\", Const, 0, \"\"},\n\t\t{\"SHF_GROUP\", Const, 0, \"\"},\n\t\t{\"SHF_INFO_LINK\", Const, 0, \"\"},\n\t\t{\"SHF_LINK_ORDER\", Const, 0, \"\"},\n\t\t{\"SHF_MASKOS\", Const, 0, \"\"},\n\t\t{\"SHF_MASKPROC\", Const, 0, \"\"},\n\t\t{\"SHF_MERGE\", Const, 0, \"\"},\n\t\t{\"SHF_OS_NONCONFORMING\", Const, 0, \"\"},\n\t\t{\"SHF_STRINGS\", Const, 0, \"\"},\n\t\t{\"SHF_TLS\", Const, 0, \"\"},\n\t\t{\"SHF_WRITE\", Const, 0, \"\"},\n\t\t{\"SHN_ABS\", Const, 0, \"\"},\n\t\t{\"SHN_COMMON\", Const, 0, \"\"},\n\t\t{\"SHN_HIOS\", Const, 0, \"\"},\n\t\t{\"SHN_HIPROC\", Const, 0, \"\"},\n\t\t{\"SHN_HIRESERVE\", Const, 0, \"\"},\n\t\t{\"SHN_LOOS\", Const, 0, \"\"},\n\t\t{\"SHN_LOPROC\", Const, 0, \"\"},\n\t\t{\"SHN_LORESERVE\", Const, 0, \"\"},\n\t\t{\"SHN_UNDEF\", Const, 0, \"\"},\n\t\t{\"SHN_XINDEX\", Const, 0, \"\"},\n\t\t{\"SHT_DYNAMIC\", Const, 0, \"\"},\n\t\t{\"SHT_DYNSYM\", Const, 0, \"\"},\n\t\t{\"SHT_FINI_ARRAY\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_ATTRIBUTES\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_HASH\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_LIBLIST\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_VERDEF\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_VERNEED\", Const, 0, \"\"},\n\t\t{\"SHT_GNU_VERSYM\", Const, 0, \"\"},\n\t\t{\"SHT_GROUP\", Const, 0, \"\"},\n\t\t{\"SHT_HASH\", Const, 0, \"\"},\n\t\t{\"SHT_HIOS\", Const, 0, \"\"},\n\t\t{\"SHT_HIPROC\", Const, 0, \"\"},\n\t\t{\"SHT_HIUSER\", Const, 0, \"\"},\n\t\t{\"SHT_INIT_ARRAY\", Const, 0, \"\"},\n\t\t{\"SHT_LOOS\", Const, 0, \"\"},\n\t\t{\"SHT_LOPROC\", Const, 0, \"\"},\n\t\t{\"SHT_LOUSER\", Const, 0, \"\"},\n\t\t{\"SHT_MIPS_ABIFLAGS\", Const, 17, \"\"},\n\t\t{\"SHT_NOBITS\", Const, 0, \"\"},\n\t\t{\"SHT_NOTE\", Const, 0, \"\"},\n\t\t{\"SHT_NULL\", Const, 0, \"\"},\n\t\t{\"SHT_PREINIT_ARRAY\", Const, 0, \"\"},\n\t\t{\"SHT_PROGBITS\", Const, 0, \"\"},\n\t\t{\"SHT_REL\", Const, 0, \"\"},\n\t\t{\"SHT_RELA\", Const, 0, \"\"},\n\t\t{\"SHT_RISCV_ATTRIBUTES\", Const, 25, \"\"},\n\t\t{\"SHT_SHLIB\", Const, 0, \"\"},\n\t\t{\"SHT_STRTAB\", Const, 0, \"\"},\n\t\t{\"SHT_SYMTAB\", Const, 0, \"\"},\n\t\t{\"SHT_SYMTAB_SHNDX\", Const, 0, \"\"},\n\t\t{\"STB_GLOBAL\", Const, 0, \"\"},\n\t\t{\"STB_HIOS\", Const, 0, \"\"},\n\t\t{\"STB_HIPROC\", Const, 0, \"\"},\n\t\t{\"STB_LOCAL\", Const, 0, \"\"},\n\t\t{\"STB_LOOS\", Const, 0, \"\"},\n\t\t{\"STB_LOPROC\", Const, 0, \"\"},\n\t\t{\"STB_WEAK\", Const, 0, \"\"},\n\t\t{\"STT_COMMON\", Const, 0, \"\"},\n\t\t{\"STT_FILE\", Const, 0, \"\"},\n\t\t{\"STT_FUNC\", Const, 0, \"\"},\n\t\t{\"STT_GNU_IFUNC\", Const, 23, \"\"},\n\t\t{\"STT_HIOS\", Const, 0, \"\"},\n\t\t{\"STT_HIPROC\", Const, 0, \"\"},\n\t\t{\"STT_LOOS\", Const, 0, \"\"},\n\t\t{\"STT_LOPROC\", Const, 0, \"\"},\n\t\t{\"STT_NOTYPE\", Const, 0, \"\"},\n\t\t{\"STT_OBJECT\", Const, 0, \"\"},\n\t\t{\"STT_RELC\", Const, 23, \"\"},\n\t\t{\"STT_SECTION\", Const, 0, \"\"},\n\t\t{\"STT_SRELC\", Const, 23, \"\"},\n\t\t{\"STT_TLS\", Const, 0, \"\"},\n\t\t{\"STV_DEFAULT\", Const, 0, \"\"},\n\t\t{\"STV_HIDDEN\", Const, 0, \"\"},\n\t\t{\"STV_INTERNAL\", Const, 0, \"\"},\n\t\t{\"STV_PROTECTED\", Const, 0, \"\"},\n\t\t{\"ST_BIND\", Func, 0, \"func(info uint8) SymBind\"},\n\t\t{\"ST_INFO\", Func, 0, \"func(bind SymBind, typ SymType) uint8\"},\n\t\t{\"ST_TYPE\", Func, 0, \"func(info uint8) SymType\"},\n\t\t{\"ST_VISIBILITY\", Func, 0, \"func(other uint8) SymVis\"},\n\t\t{\"Section\", Type, 0, \"\"},\n\t\t{\"Section.ReaderAt\", Field, 0, \"\"},\n\t\t{\"Section.SectionHeader\", Field, 0, \"\"},\n\t\t{\"Section32\", Type, 0, \"\"},\n\t\t{\"Section32.Addr\", Field, 0, \"\"},\n\t\t{\"Section32.Addralign\", Field, 0, \"\"},\n\t\t{\"Section32.Entsize\", Field, 0, \"\"},\n\t\t{\"Section32.Flags\", Field, 0, \"\"},\n\t\t{\"Section32.Info\", Field, 0, \"\"},\n\t\t{\"Section32.Link\", Field, 0, \"\"},\n\t\t{\"Section32.Name\", Field, 0, \"\"},\n\t\t{\"Section32.Off\", Field, 0, \"\"},\n\t\t{\"Section32.Size\", Field, 0, \"\"},\n\t\t{\"Section32.Type\", Field, 0, \"\"},\n\t\t{\"Section64\", Type, 0, \"\"},\n\t\t{\"Section64.Addr\", Field, 0, \"\"},\n\t\t{\"Section64.Addralign\", Field, 0, \"\"},\n\t\t{\"Section64.Entsize\", Field, 0, \"\"},\n\t\t{\"Section64.Flags\", Field, 0, \"\"},\n\t\t{\"Section64.Info\", Field, 0, \"\"},\n\t\t{\"Section64.Link\", Field, 0, \"\"},\n\t\t{\"Section64.Name\", Field, 0, \"\"},\n\t\t{\"Section64.Off\", Field, 0, \"\"},\n\t\t{\"Section64.Size\", Field, 0, \"\"},\n\t\t{\"Section64.Type\", Field, 0, \"\"},\n\t\t{\"SectionFlag\", Type, 0, \"\"},\n\t\t{\"SectionHeader\", Type, 0, \"\"},\n\t\t{\"SectionHeader.Addr\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Addralign\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Entsize\", Field, 0, \"\"},\n\t\t{\"SectionHeader.FileSize\", Field, 6, \"\"},\n\t\t{\"SectionHeader.Flags\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Info\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Link\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Name\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Offset\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Size\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Type\", Field, 0, \"\"},\n\t\t{\"SectionIndex\", Type, 0, \"\"},\n\t\t{\"SectionType\", Type, 0, \"\"},\n\t\t{\"Sym32\", Type, 0, \"\"},\n\t\t{\"Sym32.Info\", Field, 0, \"\"},\n\t\t{\"Sym32.Name\", Field, 0, \"\"},\n\t\t{\"Sym32.Other\", Field, 0, \"\"},\n\t\t{\"Sym32.Shndx\", Field, 0, \"\"},\n\t\t{\"Sym32.Size\", Field, 0, \"\"},\n\t\t{\"Sym32.Value\", Field, 0, \"\"},\n\t\t{\"Sym32Size\", Const, 0, \"\"},\n\t\t{\"Sym64\", Type, 0, \"\"},\n\t\t{\"Sym64.Info\", Field, 0, \"\"},\n\t\t{\"Sym64.Name\", Field, 0, \"\"},\n\t\t{\"Sym64.Other\", Field, 0, \"\"},\n\t\t{\"Sym64.Shndx\", Field, 0, \"\"},\n\t\t{\"Sym64.Size\", Field, 0, \"\"},\n\t\t{\"Sym64.Value\", Field, 0, \"\"},\n\t\t{\"Sym64Size\", Const, 0, \"\"},\n\t\t{\"SymBind\", Type, 0, \"\"},\n\t\t{\"SymType\", Type, 0, \"\"},\n\t\t{\"SymVis\", Type, 0, \"\"},\n\t\t{\"Symbol\", Type, 0, \"\"},\n\t\t{\"Symbol.HasVersion\", Field, 24, \"\"},\n\t\t{\"Symbol.Info\", Field, 0, \"\"},\n\t\t{\"Symbol.Library\", Field, 13, \"\"},\n\t\t{\"Symbol.Name\", Field, 0, \"\"},\n\t\t{\"Symbol.Other\", Field, 0, \"\"},\n\t\t{\"Symbol.Section\", Field, 0, \"\"},\n\t\t{\"Symbol.Size\", Field, 0, \"\"},\n\t\t{\"Symbol.Value\", Field, 0, \"\"},\n\t\t{\"Symbol.Version\", Field, 13, \"\"},\n\t\t{\"Symbol.VersionIndex\", Field, 24, \"\"},\n\t\t{\"Type\", Type, 0, \"\"},\n\t\t{\"VER_FLG_BASE\", Const, 24, \"\"},\n\t\t{\"VER_FLG_INFO\", Const, 24, \"\"},\n\t\t{\"VER_FLG_WEAK\", Const, 24, \"\"},\n\t\t{\"Version\", Type, 0, \"\"},\n\t\t{\"VersionIndex\", Type, 24, \"\"},\n\t},\n\t\"debug/gosym\": {\n\t\t{\"(*DecodingError).Error\", Method, 0, \"\"},\n\t\t{\"(*LineTable).LineToPC\", Method, 0, \"\"},\n\t\t{\"(*LineTable).PCToLine\", Method, 0, \"\"},\n\t\t{\"(*Sym).BaseName\", Method, 0, \"\"},\n\t\t{\"(*Sym).PackageName\", Method, 0, \"\"},\n\t\t{\"(*Sym).ReceiverName\", Method, 0, \"\"},\n\t\t{\"(*Sym).Static\", Method, 0, \"\"},\n\t\t{\"(*Table).LineToPC\", Method, 0, \"\"},\n\t\t{\"(*Table).LookupFunc\", Method, 0, \"\"},\n\t\t{\"(*Table).LookupSym\", Method, 0, \"\"},\n\t\t{\"(*Table).PCToFunc\", Method, 0, \"\"},\n\t\t{\"(*Table).PCToLine\", Method, 0, \"\"},\n\t\t{\"(*Table).SymByAddr\", Method, 0, \"\"},\n\t\t{\"(*UnknownLineError).Error\", Method, 0, \"\"},\n\t\t{\"(Func).BaseName\", Method, 0, \"\"},\n\t\t{\"(Func).PackageName\", Method, 0, \"\"},\n\t\t{\"(Func).ReceiverName\", Method, 0, \"\"},\n\t\t{\"(Func).Static\", Method, 0, \"\"},\n\t\t{\"(UnknownFileError).Error\", Method, 0, \"\"},\n\t\t{\"DecodingError\", Type, 0, \"\"},\n\t\t{\"Func\", Type, 0, \"\"},\n\t\t{\"Func.End\", Field, 0, \"\"},\n\t\t{\"Func.Entry\", Field, 0, \"\"},\n\t\t{\"Func.FrameSize\", Field, 0, \"\"},\n\t\t{\"Func.LineTable\", Field, 0, \"\"},\n\t\t{\"Func.Locals\", Field, 0, \"\"},\n\t\t{\"Func.Obj\", Field, 0, \"\"},\n\t\t{\"Func.Params\", Field, 0, \"\"},\n\t\t{\"Func.Sym\", Field, 0, \"\"},\n\t\t{\"LineTable\", Type, 0, \"\"},\n\t\t{\"LineTable.Data\", Field, 0, \"\"},\n\t\t{\"LineTable.Line\", Field, 0, \"\"},\n\t\t{\"LineTable.PC\", Field, 0, \"\"},\n\t\t{\"NewLineTable\", Func, 0, \"func(data []byte, text uint64) *LineTable\"},\n\t\t{\"NewTable\", Func, 0, \"func(symtab []byte, pcln *LineTable) (*Table, error)\"},\n\t\t{\"Obj\", Type, 0, \"\"},\n\t\t{\"Obj.Funcs\", Field, 0, \"\"},\n\t\t{\"Obj.Paths\", Field, 0, \"\"},\n\t\t{\"Sym\", Type, 0, \"\"},\n\t\t{\"Sym.Func\", Field, 0, \"\"},\n\t\t{\"Sym.GoType\", Field, 0, \"\"},\n\t\t{\"Sym.Name\", Field, 0, \"\"},\n\t\t{\"Sym.Type\", Field, 0, \"\"},\n\t\t{\"Sym.Value\", Field, 0, \"\"},\n\t\t{\"Table\", Type, 0, \"\"},\n\t\t{\"Table.Files\", Field, 0, \"\"},\n\t\t{\"Table.Funcs\", Field, 0, \"\"},\n\t\t{\"Table.Objs\", Field, 0, \"\"},\n\t\t{\"Table.Syms\", Field, 0, \"\"},\n\t\t{\"UnknownFileError\", Type, 0, \"\"},\n\t\t{\"UnknownLineError\", Type, 0, \"\"},\n\t\t{\"UnknownLineError.File\", Field, 0, \"\"},\n\t\t{\"UnknownLineError.Line\", Field, 0, \"\"},\n\t},\n\t\"debug/macho\": {\n\t\t{\"(*FatFile).Close\", Method, 3, \"\"},\n\t\t{\"(*File).Close\", Method, 0, \"\"},\n\t\t{\"(*File).DWARF\", Method, 0, \"\"},\n\t\t{\"(*File).ImportedLibraries\", Method, 0, \"\"},\n\t\t{\"(*File).ImportedSymbols\", Method, 0, \"\"},\n\t\t{\"(*File).Section\", Method, 0, \"\"},\n\t\t{\"(*File).Segment\", Method, 0, \"\"},\n\t\t{\"(*FormatError).Error\", Method, 0, \"\"},\n\t\t{\"(*Section).Data\", Method, 0, \"\"},\n\t\t{\"(*Section).Open\", Method, 0, \"\"},\n\t\t{\"(*Segment).Data\", Method, 0, \"\"},\n\t\t{\"(*Segment).Open\", Method, 0, \"\"},\n\t\t{\"(Cpu).GoString\", Method, 0, \"\"},\n\t\t{\"(Cpu).String\", Method, 0, \"\"},\n\t\t{\"(Dylib).Raw\", Method, 0, \"\"},\n\t\t{\"(Dysymtab).Raw\", Method, 0, \"\"},\n\t\t{\"(FatArch).Close\", Method, 3, \"\"},\n\t\t{\"(FatArch).DWARF\", Method, 3, \"\"},\n\t\t{\"(FatArch).ImportedLibraries\", Method, 3, \"\"},\n\t\t{\"(FatArch).ImportedSymbols\", Method, 3, \"\"},\n\t\t{\"(FatArch).Section\", Method, 3, \"\"},\n\t\t{\"(FatArch).Segment\", Method, 3, \"\"},\n\t\t{\"(Load).Raw\", Method, 0, \"\"},\n\t\t{\"(LoadBytes).Raw\", Method, 0, \"\"},\n\t\t{\"(LoadCmd).GoString\", Method, 0, \"\"},\n\t\t{\"(LoadCmd).String\", Method, 0, \"\"},\n\t\t{\"(RelocTypeARM).GoString\", Method, 10, \"\"},\n\t\t{\"(RelocTypeARM).String\", Method, 10, \"\"},\n\t\t{\"(RelocTypeARM64).GoString\", Method, 10, \"\"},\n\t\t{\"(RelocTypeARM64).String\", Method, 10, \"\"},\n\t\t{\"(RelocTypeGeneric).GoString\", Method, 10, \"\"},\n\t\t{\"(RelocTypeGeneric).String\", Method, 10, \"\"},\n\t\t{\"(RelocTypeX86_64).GoString\", Method, 10, \"\"},\n\t\t{\"(RelocTypeX86_64).String\", Method, 10, \"\"},\n\t\t{\"(Rpath).Raw\", Method, 10, \"\"},\n\t\t{\"(Section).ReadAt\", Method, 0, \"\"},\n\t\t{\"(Segment).Raw\", Method, 0, \"\"},\n\t\t{\"(Segment).ReadAt\", Method, 0, \"\"},\n\t\t{\"(Symtab).Raw\", Method, 0, \"\"},\n\t\t{\"(Type).GoString\", Method, 10, \"\"},\n\t\t{\"(Type).String\", Method, 10, \"\"},\n\t\t{\"ARM64_RELOC_ADDEND\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_BRANCH26\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_GOT_LOAD_PAGE21\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_GOT_LOAD_PAGEOFF12\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_PAGE21\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_PAGEOFF12\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_POINTER_TO_GOT\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_SUBTRACTOR\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_TLVP_LOAD_PAGE21\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_TLVP_LOAD_PAGEOFF12\", Const, 10, \"\"},\n\t\t{\"ARM64_RELOC_UNSIGNED\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_BR24\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_HALF\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_HALF_SECTDIFF\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_LOCAL_SECTDIFF\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_PAIR\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_PB_LA_PTR\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_SECTDIFF\", Const, 10, \"\"},\n\t\t{\"ARM_RELOC_VANILLA\", Const, 10, \"\"},\n\t\t{\"ARM_THUMB_32BIT_BRANCH\", Const, 10, \"\"},\n\t\t{\"ARM_THUMB_RELOC_BR22\", Const, 10, \"\"},\n\t\t{\"Cpu\", Type, 0, \"\"},\n\t\t{\"Cpu386\", Const, 0, \"\"},\n\t\t{\"CpuAmd64\", Const, 0, \"\"},\n\t\t{\"CpuArm\", Const, 3, \"\"},\n\t\t{\"CpuArm64\", Const, 11, \"\"},\n\t\t{\"CpuPpc\", Const, 3, \"\"},\n\t\t{\"CpuPpc64\", Const, 3, \"\"},\n\t\t{\"Dylib\", Type, 0, \"\"},\n\t\t{\"Dylib.CompatVersion\", Field, 0, \"\"},\n\t\t{\"Dylib.CurrentVersion\", Field, 0, \"\"},\n\t\t{\"Dylib.LoadBytes\", Field, 0, \"\"},\n\t\t{\"Dylib.Name\", Field, 0, \"\"},\n\t\t{\"Dylib.Time\", Field, 0, \"\"},\n\t\t{\"DylibCmd\", Type, 0, \"\"},\n\t\t{\"DylibCmd.Cmd\", Field, 0, \"\"},\n\t\t{\"DylibCmd.CompatVersion\", Field, 0, \"\"},\n\t\t{\"DylibCmd.CurrentVersion\", Field, 0, \"\"},\n\t\t{\"DylibCmd.Len\", Field, 0, \"\"},\n\t\t{\"DylibCmd.Name\", Field, 0, \"\"},\n\t\t{\"DylibCmd.Time\", Field, 0, \"\"},\n\t\t{\"Dysymtab\", Type, 0, \"\"},\n\t\t{\"Dysymtab.DysymtabCmd\", Field, 0, \"\"},\n\t\t{\"Dysymtab.IndirectSyms\", Field, 0, \"\"},\n\t\t{\"Dysymtab.LoadBytes\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd\", Type, 0, \"\"},\n\t\t{\"DysymtabCmd.Cmd\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Extrefsymoff\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Extreloff\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Iextdefsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Ilocalsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Indirectsymoff\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Iundefsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Len\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Locreloff\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Modtaboff\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nextdefsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nextrefsyms\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nextrel\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nindirectsyms\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nlocalsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nlocrel\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nmodtab\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Ntoc\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Nundefsym\", Field, 0, \"\"},\n\t\t{\"DysymtabCmd.Tocoffset\", Field, 0, \"\"},\n\t\t{\"ErrNotFat\", Var, 3, \"\"},\n\t\t{\"FatArch\", Type, 3, \"\"},\n\t\t{\"FatArch.FatArchHeader\", Field, 3, \"\"},\n\t\t{\"FatArch.File\", Field, 3, \"\"},\n\t\t{\"FatArchHeader\", Type, 3, \"\"},\n\t\t{\"FatArchHeader.Align\", Field, 3, \"\"},\n\t\t{\"FatArchHeader.Cpu\", Field, 3, \"\"},\n\t\t{\"FatArchHeader.Offset\", Field, 3, \"\"},\n\t\t{\"FatArchHeader.Size\", Field, 3, \"\"},\n\t\t{\"FatArchHeader.SubCpu\", Field, 3, \"\"},\n\t\t{\"FatFile\", Type, 3, \"\"},\n\t\t{\"FatFile.Arches\", Field, 3, \"\"},\n\t\t{\"FatFile.Magic\", Field, 3, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"File.ByteOrder\", Field, 0, \"\"},\n\t\t{\"File.Dysymtab\", Field, 0, \"\"},\n\t\t{\"File.FileHeader\", Field, 0, \"\"},\n\t\t{\"File.Loads\", Field, 0, \"\"},\n\t\t{\"File.Sections\", Field, 0, \"\"},\n\t\t{\"File.Symtab\", Field, 0, \"\"},\n\t\t{\"FileHeader\", Type, 0, \"\"},\n\t\t{\"FileHeader.Cmdsz\", Field, 0, \"\"},\n\t\t{\"FileHeader.Cpu\", Field, 0, \"\"},\n\t\t{\"FileHeader.Flags\", Field, 0, \"\"},\n\t\t{\"FileHeader.Magic\", Field, 0, \"\"},\n\t\t{\"FileHeader.Ncmd\", Field, 0, \"\"},\n\t\t{\"FileHeader.SubCpu\", Field, 0, \"\"},\n\t\t{\"FileHeader.Type\", Field, 0, \"\"},\n\t\t{\"FlagAllModsBound\", Const, 10, \"\"},\n\t\t{\"FlagAllowStackExecution\", Const, 10, \"\"},\n\t\t{\"FlagAppExtensionSafe\", Const, 10, \"\"},\n\t\t{\"FlagBindAtLoad\", Const, 10, \"\"},\n\t\t{\"FlagBindsToWeak\", Const, 10, \"\"},\n\t\t{\"FlagCanonical\", Const, 10, \"\"},\n\t\t{\"FlagDeadStrippableDylib\", Const, 10, \"\"},\n\t\t{\"FlagDyldLink\", Const, 10, \"\"},\n\t\t{\"FlagForceFlat\", Const, 10, \"\"},\n\t\t{\"FlagHasTLVDescriptors\", Const, 10, \"\"},\n\t\t{\"FlagIncrLink\", Const, 10, \"\"},\n\t\t{\"FlagLazyInit\", Const, 10, \"\"},\n\t\t{\"FlagNoFixPrebinding\", Const, 10, \"\"},\n\t\t{\"FlagNoHeapExecution\", Const, 10, \"\"},\n\t\t{\"FlagNoMultiDefs\", Const, 10, \"\"},\n\t\t{\"FlagNoReexportedDylibs\", Const, 10, \"\"},\n\t\t{\"FlagNoUndefs\", Const, 10, \"\"},\n\t\t{\"FlagPIE\", Const, 10, \"\"},\n\t\t{\"FlagPrebindable\", Const, 10, \"\"},\n\t\t{\"FlagPrebound\", Const, 10, \"\"},\n\t\t{\"FlagRootSafe\", Const, 10, \"\"},\n\t\t{\"FlagSetuidSafe\", Const, 10, \"\"},\n\t\t{\"FlagSplitSegs\", Const, 10, \"\"},\n\t\t{\"FlagSubsectionsViaSymbols\", Const, 10, \"\"},\n\t\t{\"FlagTwoLevel\", Const, 10, \"\"},\n\t\t{\"FlagWeakDefines\", Const, 10, \"\"},\n\t\t{\"FormatError\", Type, 0, \"\"},\n\t\t{\"GENERIC_RELOC_LOCAL_SECTDIFF\", Const, 10, \"\"},\n\t\t{\"GENERIC_RELOC_PAIR\", Const, 10, \"\"},\n\t\t{\"GENERIC_RELOC_PB_LA_PTR\", Const, 10, \"\"},\n\t\t{\"GENERIC_RELOC_SECTDIFF\", Const, 10, \"\"},\n\t\t{\"GENERIC_RELOC_TLV\", Const, 10, \"\"},\n\t\t{\"GENERIC_RELOC_VANILLA\", Const, 10, \"\"},\n\t\t{\"Load\", Type, 0, \"\"},\n\t\t{\"LoadBytes\", Type, 0, \"\"},\n\t\t{\"LoadCmd\", Type, 0, \"\"},\n\t\t{\"LoadCmdDylib\", Const, 0, \"\"},\n\t\t{\"LoadCmdDylinker\", Const, 0, \"\"},\n\t\t{\"LoadCmdDysymtab\", Const, 0, \"\"},\n\t\t{\"LoadCmdRpath\", Const, 10, \"\"},\n\t\t{\"LoadCmdSegment\", Const, 0, \"\"},\n\t\t{\"LoadCmdSegment64\", Const, 0, \"\"},\n\t\t{\"LoadCmdSymtab\", Const, 0, \"\"},\n\t\t{\"LoadCmdThread\", Const, 0, \"\"},\n\t\t{\"LoadCmdUnixThread\", Const, 0, \"\"},\n\t\t{\"Magic32\", Const, 0, \"\"},\n\t\t{\"Magic64\", Const, 0, \"\"},\n\t\t{\"MagicFat\", Const, 3, \"\"},\n\t\t{\"NewFatFile\", Func, 3, \"func(r io.ReaderAt) (*FatFile, error)\"},\n\t\t{\"NewFile\", Func, 0, \"func(r io.ReaderAt) (*File, error)\"},\n\t\t{\"Nlist32\", Type, 0, \"\"},\n\t\t{\"Nlist32.Desc\", Field, 0, \"\"},\n\t\t{\"Nlist32.Name\", Field, 0, \"\"},\n\t\t{\"Nlist32.Sect\", Field, 0, \"\"},\n\t\t{\"Nlist32.Type\", Field, 0, \"\"},\n\t\t{\"Nlist32.Value\", Field, 0, \"\"},\n\t\t{\"Nlist64\", Type, 0, \"\"},\n\t\t{\"Nlist64.Desc\", Field, 0, \"\"},\n\t\t{\"Nlist64.Name\", Field, 0, \"\"},\n\t\t{\"Nlist64.Sect\", Field, 0, \"\"},\n\t\t{\"Nlist64.Type\", Field, 0, \"\"},\n\t\t{\"Nlist64.Value\", Field, 0, \"\"},\n\t\t{\"Open\", Func, 0, \"func(name string) (*File, error)\"},\n\t\t{\"OpenFat\", Func, 3, \"func(name string) (*FatFile, error)\"},\n\t\t{\"Regs386\", Type, 0, \"\"},\n\t\t{\"Regs386.AX\", Field, 0, \"\"},\n\t\t{\"Regs386.BP\", Field, 0, \"\"},\n\t\t{\"Regs386.BX\", Field, 0, \"\"},\n\t\t{\"Regs386.CS\", Field, 0, \"\"},\n\t\t{\"Regs386.CX\", Field, 0, \"\"},\n\t\t{\"Regs386.DI\", Field, 0, \"\"},\n\t\t{\"Regs386.DS\", Field, 0, \"\"},\n\t\t{\"Regs386.DX\", Field, 0, \"\"},\n\t\t{\"Regs386.ES\", Field, 0, \"\"},\n\t\t{\"Regs386.FLAGS\", Field, 0, \"\"},\n\t\t{\"Regs386.FS\", Field, 0, \"\"},\n\t\t{\"Regs386.GS\", Field, 0, \"\"},\n\t\t{\"Regs386.IP\", Field, 0, \"\"},\n\t\t{\"Regs386.SI\", Field, 0, \"\"},\n\t\t{\"Regs386.SP\", Field, 0, \"\"},\n\t\t{\"Regs386.SS\", Field, 0, \"\"},\n\t\t{\"RegsAMD64\", Type, 0, \"\"},\n\t\t{\"RegsAMD64.AX\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.BP\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.BX\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.CS\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.CX\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.DI\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.DX\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.FLAGS\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.FS\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.GS\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.IP\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R10\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R11\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R12\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R13\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R14\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R15\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R8\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.R9\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.SI\", Field, 0, \"\"},\n\t\t{\"RegsAMD64.SP\", Field, 0, \"\"},\n\t\t{\"Reloc\", Type, 10, \"\"},\n\t\t{\"Reloc.Addr\", Field, 10, \"\"},\n\t\t{\"Reloc.Extern\", Field, 10, \"\"},\n\t\t{\"Reloc.Len\", Field, 10, \"\"},\n\t\t{\"Reloc.Pcrel\", Field, 10, \"\"},\n\t\t{\"Reloc.Scattered\", Field, 10, \"\"},\n\t\t{\"Reloc.Type\", Field, 10, \"\"},\n\t\t{\"Reloc.Value\", Field, 10, \"\"},\n\t\t{\"RelocTypeARM\", Type, 10, \"\"},\n\t\t{\"RelocTypeARM64\", Type, 10, \"\"},\n\t\t{\"RelocTypeGeneric\", Type, 10, \"\"},\n\t\t{\"RelocTypeX86_64\", Type, 10, \"\"},\n\t\t{\"Rpath\", Type, 10, \"\"},\n\t\t{\"Rpath.LoadBytes\", Field, 10, \"\"},\n\t\t{\"Rpath.Path\", Field, 10, \"\"},\n\t\t{\"RpathCmd\", Type, 10, \"\"},\n\t\t{\"RpathCmd.Cmd\", Field, 10, \"\"},\n\t\t{\"RpathCmd.Len\", Field, 10, \"\"},\n\t\t{\"RpathCmd.Path\", Field, 10, \"\"},\n\t\t{\"Section\", Type, 0, \"\"},\n\t\t{\"Section.ReaderAt\", Field, 0, \"\"},\n\t\t{\"Section.Relocs\", Field, 10, \"\"},\n\t\t{\"Section.SectionHeader\", Field, 0, \"\"},\n\t\t{\"Section32\", Type, 0, \"\"},\n\t\t{\"Section32.Addr\", Field, 0, \"\"},\n\t\t{\"Section32.Align\", Field, 0, \"\"},\n\t\t{\"Section32.Flags\", Field, 0, \"\"},\n\t\t{\"Section32.Name\", Field, 0, \"\"},\n\t\t{\"Section32.Nreloc\", Field, 0, \"\"},\n\t\t{\"Section32.Offset\", Field, 0, \"\"},\n\t\t{\"Section32.Reloff\", Field, 0, \"\"},\n\t\t{\"Section32.Reserve1\", Field, 0, \"\"},\n\t\t{\"Section32.Reserve2\", Field, 0, \"\"},\n\t\t{\"Section32.Seg\", Field, 0, \"\"},\n\t\t{\"Section32.Size\", Field, 0, \"\"},\n\t\t{\"Section64\", Type, 0, \"\"},\n\t\t{\"Section64.Addr\", Field, 0, \"\"},\n\t\t{\"Section64.Align\", Field, 0, \"\"},\n\t\t{\"Section64.Flags\", Field, 0, \"\"},\n\t\t{\"Section64.Name\", Field, 0, \"\"},\n\t\t{\"Section64.Nreloc\", Field, 0, \"\"},\n\t\t{\"Section64.Offset\", Field, 0, \"\"},\n\t\t{\"Section64.Reloff\", Field, 0, \"\"},\n\t\t{\"Section64.Reserve1\", Field, 0, \"\"},\n\t\t{\"Section64.Reserve2\", Field, 0, \"\"},\n\t\t{\"Section64.Reserve3\", Field, 0, \"\"},\n\t\t{\"Section64.Seg\", Field, 0, \"\"},\n\t\t{\"Section64.Size\", Field, 0, \"\"},\n\t\t{\"SectionHeader\", Type, 0, \"\"},\n\t\t{\"SectionHeader.Addr\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Align\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Flags\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Name\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Nreloc\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Offset\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Reloff\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Seg\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Size\", Field, 0, \"\"},\n\t\t{\"Segment\", Type, 0, \"\"},\n\t\t{\"Segment.LoadBytes\", Field, 0, \"\"},\n\t\t{\"Segment.ReaderAt\", Field, 0, \"\"},\n\t\t{\"Segment.SegmentHeader\", Field, 0, \"\"},\n\t\t{\"Segment32\", Type, 0, \"\"},\n\t\t{\"Segment32.Addr\", Field, 0, \"\"},\n\t\t{\"Segment32.Cmd\", Field, 0, \"\"},\n\t\t{\"Segment32.Filesz\", Field, 0, \"\"},\n\t\t{\"Segment32.Flag\", Field, 0, \"\"},\n\t\t{\"Segment32.Len\", Field, 0, \"\"},\n\t\t{\"Segment32.Maxprot\", Field, 0, \"\"},\n\t\t{\"Segment32.Memsz\", Field, 0, \"\"},\n\t\t{\"Segment32.Name\", Field, 0, \"\"},\n\t\t{\"Segment32.Nsect\", Field, 0, \"\"},\n\t\t{\"Segment32.Offset\", Field, 0, \"\"},\n\t\t{\"Segment32.Prot\", Field, 0, \"\"},\n\t\t{\"Segment64\", Type, 0, \"\"},\n\t\t{\"Segment64.Addr\", Field, 0, \"\"},\n\t\t{\"Segment64.Cmd\", Field, 0, \"\"},\n\t\t{\"Segment64.Filesz\", Field, 0, \"\"},\n\t\t{\"Segment64.Flag\", Field, 0, \"\"},\n\t\t{\"Segment64.Len\", Field, 0, \"\"},\n\t\t{\"Segment64.Maxprot\", Field, 0, \"\"},\n\t\t{\"Segment64.Memsz\", Field, 0, \"\"},\n\t\t{\"Segment64.Name\", Field, 0, \"\"},\n\t\t{\"Segment64.Nsect\", Field, 0, \"\"},\n\t\t{\"Segment64.Offset\", Field, 0, \"\"},\n\t\t{\"Segment64.Prot\", Field, 0, \"\"},\n\t\t{\"SegmentHeader\", Type, 0, \"\"},\n\t\t{\"SegmentHeader.Addr\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Cmd\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Filesz\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Flag\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Len\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Maxprot\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Memsz\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Name\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Nsect\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Offset\", Field, 0, \"\"},\n\t\t{\"SegmentHeader.Prot\", Field, 0, \"\"},\n\t\t{\"Symbol\", Type, 0, \"\"},\n\t\t{\"Symbol.Desc\", Field, 0, \"\"},\n\t\t{\"Symbol.Name\", Field, 0, \"\"},\n\t\t{\"Symbol.Sect\", Field, 0, \"\"},\n\t\t{\"Symbol.Type\", Field, 0, \"\"},\n\t\t{\"Symbol.Value\", Field, 0, \"\"},\n\t\t{\"Symtab\", Type, 0, \"\"},\n\t\t{\"Symtab.LoadBytes\", Field, 0, \"\"},\n\t\t{\"Symtab.Syms\", Field, 0, \"\"},\n\t\t{\"Symtab.SymtabCmd\", Field, 0, \"\"},\n\t\t{\"SymtabCmd\", Type, 0, \"\"},\n\t\t{\"SymtabCmd.Cmd\", Field, 0, \"\"},\n\t\t{\"SymtabCmd.Len\", Field, 0, \"\"},\n\t\t{\"SymtabCmd.Nsyms\", Field, 0, \"\"},\n\t\t{\"SymtabCmd.Stroff\", Field, 0, \"\"},\n\t\t{\"SymtabCmd.Strsize\", Field, 0, \"\"},\n\t\t{\"SymtabCmd.Symoff\", Field, 0, \"\"},\n\t\t{\"Thread\", Type, 0, \"\"},\n\t\t{\"Thread.Cmd\", Field, 0, \"\"},\n\t\t{\"Thread.Data\", Field, 0, \"\"},\n\t\t{\"Thread.Len\", Field, 0, \"\"},\n\t\t{\"Thread.Type\", Field, 0, \"\"},\n\t\t{\"Type\", Type, 0, \"\"},\n\t\t{\"TypeBundle\", Const, 3, \"\"},\n\t\t{\"TypeDylib\", Const, 3, \"\"},\n\t\t{\"TypeExec\", Const, 0, \"\"},\n\t\t{\"TypeObj\", Const, 0, \"\"},\n\t\t{\"X86_64_RELOC_BRANCH\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_GOT\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_GOT_LOAD\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_SIGNED\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_SIGNED_1\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_SIGNED_2\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_SIGNED_4\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_SUBTRACTOR\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_TLV\", Const, 10, \"\"},\n\t\t{\"X86_64_RELOC_UNSIGNED\", Const, 10, \"\"},\n\t},\n\t\"debug/pe\": {\n\t\t{\"(*COFFSymbol).FullName\", Method, 8, \"\"},\n\t\t{\"(*File).COFFSymbolReadSectionDefAux\", Method, 19, \"\"},\n\t\t{\"(*File).Close\", Method, 0, \"\"},\n\t\t{\"(*File).DWARF\", Method, 0, \"\"},\n\t\t{\"(*File).ImportedLibraries\", Method, 0, \"\"},\n\t\t{\"(*File).ImportedSymbols\", Method, 0, \"\"},\n\t\t{\"(*File).Section\", Method, 0, \"\"},\n\t\t{\"(*FormatError).Error\", Method, 0, \"\"},\n\t\t{\"(*Section).Data\", Method, 0, \"\"},\n\t\t{\"(*Section).Open\", Method, 0, \"\"},\n\t\t{\"(Section).ReadAt\", Method, 0, \"\"},\n\t\t{\"(StringTable).String\", Method, 8, \"\"},\n\t\t{\"COFFSymbol\", Type, 1, \"\"},\n\t\t{\"COFFSymbol.Name\", Field, 1, \"\"},\n\t\t{\"COFFSymbol.NumberOfAuxSymbols\", Field, 1, \"\"},\n\t\t{\"COFFSymbol.SectionNumber\", Field, 1, \"\"},\n\t\t{\"COFFSymbol.StorageClass\", Field, 1, \"\"},\n\t\t{\"COFFSymbol.Type\", Field, 1, \"\"},\n\t\t{\"COFFSymbol.Value\", Field, 1, \"\"},\n\t\t{\"COFFSymbolAuxFormat5\", Type, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.Checksum\", Field, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.NumLineNumbers\", Field, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.NumRelocs\", Field, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.SecNum\", Field, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.Selection\", Field, 19, \"\"},\n\t\t{\"COFFSymbolAuxFormat5.Size\", Field, 19, \"\"},\n\t\t{\"COFFSymbolSize\", Const, 1, \"\"},\n\t\t{\"DataDirectory\", Type, 3, \"\"},\n\t\t{\"DataDirectory.Size\", Field, 3, \"\"},\n\t\t{\"DataDirectory.VirtualAddress\", Field, 3, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"File.COFFSymbols\", Field, 8, \"\"},\n\t\t{\"File.FileHeader\", Field, 0, \"\"},\n\t\t{\"File.OptionalHeader\", Field, 3, \"\"},\n\t\t{\"File.Sections\", Field, 0, \"\"},\n\t\t{\"File.StringTable\", Field, 8, \"\"},\n\t\t{\"File.Symbols\", Field, 1, \"\"},\n\t\t{\"FileHeader\", Type, 0, \"\"},\n\t\t{\"FileHeader.Characteristics\", Field, 0, \"\"},\n\t\t{\"FileHeader.Machine\", Field, 0, \"\"},\n\t\t{\"FileHeader.NumberOfSections\", Field, 0, \"\"},\n\t\t{\"FileHeader.NumberOfSymbols\", Field, 0, \"\"},\n\t\t{\"FileHeader.PointerToSymbolTable\", Field, 0, \"\"},\n\t\t{\"FileHeader.SizeOfOptionalHeader\", Field, 0, \"\"},\n\t\t{\"FileHeader.TimeDateStamp\", Field, 0, \"\"},\n\t\t{\"FormatError\", Type, 0, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_ANY\", Const, 19, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_ASSOCIATIVE\", Const, 19, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_EXACT_MATCH\", Const, 19, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_LARGEST\", Const, 19, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_NODUPLICATES\", Const, 19, \"\"},\n\t\t{\"IMAGE_COMDAT_SELECT_SAME_SIZE\", Const, 19, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_ARCHITECTURE\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_BASERELOC\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_DEBUG\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_EXCEPTION\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_EXPORT\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_GLOBALPTR\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_IAT\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_IMPORT\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_RESOURCE\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_SECURITY\", Const, 11, \"\"},\n\t\t{\"IMAGE_DIRECTORY_ENTRY_TLS\", Const, 11, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_APPCONTAINER\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_GUARD_CF\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_NO_BIND\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_NO_ISOLATION\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_NO_SEH\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_NX_COMPAT\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE\", Const, 15, \"\"},\n\t\t{\"IMAGE_DLLCHARACTERISTICS_WDM_DRIVER\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_32BIT_MACHINE\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_AGGRESIVE_WS_TRIM\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_BYTES_REVERSED_HI\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_BYTES_REVERSED_LO\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_DEBUG_STRIPPED\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_DLL\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_EXECUTABLE_IMAGE\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_LARGE_ADDRESS_AWARE\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_LINE_NUMS_STRIPPED\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_LOCAL_SYMS_STRIPPED\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_AM33\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_AMD64\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_ARM\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_ARM64\", Const, 11, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_ARMNT\", Const, 12, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_EBC\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_I386\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_IA64\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_LOONGARCH32\", Const, 19, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_LOONGARCH64\", Const, 19, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_M32R\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_MIPS16\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_MIPSFPU\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_MIPSFPU16\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_POWERPC\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_POWERPCFP\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_R4000\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_RISCV128\", Const, 20, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_RISCV32\", Const, 20, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_RISCV64\", Const, 20, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_SH3\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_SH3DSP\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_SH4\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_SH5\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_THUMB\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_UNKNOWN\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_MACHINE_WCEMIPSV2\", Const, 0, \"\"},\n\t\t{\"IMAGE_FILE_NET_RUN_FROM_SWAP\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_RELOCS_STRIPPED\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_SYSTEM\", Const, 15, \"\"},\n\t\t{\"IMAGE_FILE_UP_SYSTEM_ONLY\", Const, 15, \"\"},\n\t\t{\"IMAGE_SCN_CNT_CODE\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_CNT_INITIALIZED_DATA\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_CNT_UNINITIALIZED_DATA\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_LNK_COMDAT\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_MEM_DISCARDABLE\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_MEM_EXECUTE\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_MEM_READ\", Const, 19, \"\"},\n\t\t{\"IMAGE_SCN_MEM_WRITE\", Const, 19, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_EFI_APPLICATION\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_EFI_ROM\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_NATIVE\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_NATIVE_WINDOWS\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_OS2_CUI\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_POSIX_CUI\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_UNKNOWN\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_WINDOWS_CE_GUI\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_WINDOWS_CUI\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_WINDOWS_GUI\", Const, 15, \"\"},\n\t\t{\"IMAGE_SUBSYSTEM_XBOX\", Const, 15, \"\"},\n\t\t{\"ImportDirectory\", Type, 0, \"\"},\n\t\t{\"ImportDirectory.FirstThunk\", Field, 0, \"\"},\n\t\t{\"ImportDirectory.ForwarderChain\", Field, 0, \"\"},\n\t\t{\"ImportDirectory.Name\", Field, 0, \"\"},\n\t\t{\"ImportDirectory.OriginalFirstThunk\", Field, 0, \"\"},\n\t\t{\"ImportDirectory.TimeDateStamp\", Field, 0, \"\"},\n\t\t{\"NewFile\", Func, 0, \"func(r io.ReaderAt) (*File, error)\"},\n\t\t{\"Open\", Func, 0, \"func(name string) (*File, error)\"},\n\t\t{\"OptionalHeader32\", Type, 3, \"\"},\n\t\t{\"OptionalHeader32.AddressOfEntryPoint\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.BaseOfCode\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.BaseOfData\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.CheckSum\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.DataDirectory\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.DllCharacteristics\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.FileAlignment\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.ImageBase\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.LoaderFlags\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.Magic\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MajorImageVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MajorLinkerVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MajorOperatingSystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MajorSubsystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MinorImageVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MinorLinkerVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MinorOperatingSystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.MinorSubsystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.NumberOfRvaAndSizes\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SectionAlignment\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfCode\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfHeaders\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfHeapCommit\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfHeapReserve\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfImage\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfInitializedData\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfStackCommit\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfStackReserve\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.SizeOfUninitializedData\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.Subsystem\", Field, 3, \"\"},\n\t\t{\"OptionalHeader32.Win32VersionValue\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64\", Type, 3, \"\"},\n\t\t{\"OptionalHeader64.AddressOfEntryPoint\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.BaseOfCode\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.CheckSum\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.DataDirectory\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.DllCharacteristics\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.FileAlignment\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.ImageBase\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.LoaderFlags\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.Magic\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MajorImageVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MajorLinkerVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MajorOperatingSystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MajorSubsystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MinorImageVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MinorLinkerVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MinorOperatingSystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.MinorSubsystemVersion\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.NumberOfRvaAndSizes\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SectionAlignment\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfCode\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfHeaders\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfHeapCommit\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfHeapReserve\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfImage\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfInitializedData\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfStackCommit\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfStackReserve\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.SizeOfUninitializedData\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.Subsystem\", Field, 3, \"\"},\n\t\t{\"OptionalHeader64.Win32VersionValue\", Field, 3, \"\"},\n\t\t{\"Reloc\", Type, 8, \"\"},\n\t\t{\"Reloc.SymbolTableIndex\", Field, 8, \"\"},\n\t\t{\"Reloc.Type\", Field, 8, \"\"},\n\t\t{\"Reloc.VirtualAddress\", Field, 8, \"\"},\n\t\t{\"Section\", Type, 0, \"\"},\n\t\t{\"Section.ReaderAt\", Field, 0, \"\"},\n\t\t{\"Section.Relocs\", Field, 8, \"\"},\n\t\t{\"Section.SectionHeader\", Field, 0, \"\"},\n\t\t{\"SectionHeader\", Type, 0, \"\"},\n\t\t{\"SectionHeader.Characteristics\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Name\", Field, 0, \"\"},\n\t\t{\"SectionHeader.NumberOfLineNumbers\", Field, 0, \"\"},\n\t\t{\"SectionHeader.NumberOfRelocations\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Offset\", Field, 0, \"\"},\n\t\t{\"SectionHeader.PointerToLineNumbers\", Field, 0, \"\"},\n\t\t{\"SectionHeader.PointerToRelocations\", Field, 0, \"\"},\n\t\t{\"SectionHeader.Size\", Field, 0, \"\"},\n\t\t{\"SectionHeader.VirtualAddress\", Field, 0, \"\"},\n\t\t{\"SectionHeader.VirtualSize\", Field, 0, \"\"},\n\t\t{\"SectionHeader32\", Type, 0, \"\"},\n\t\t{\"SectionHeader32.Characteristics\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.Name\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.NumberOfLineNumbers\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.NumberOfRelocations\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.PointerToLineNumbers\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.PointerToRawData\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.PointerToRelocations\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.SizeOfRawData\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.VirtualAddress\", Field, 0, \"\"},\n\t\t{\"SectionHeader32.VirtualSize\", Field, 0, \"\"},\n\t\t{\"StringTable\", Type, 8, \"\"},\n\t\t{\"Symbol\", Type, 1, \"\"},\n\t\t{\"Symbol.Name\", Field, 1, \"\"},\n\t\t{\"Symbol.SectionNumber\", Field, 1, \"\"},\n\t\t{\"Symbol.StorageClass\", Field, 1, \"\"},\n\t\t{\"Symbol.Type\", Field, 1, \"\"},\n\t\t{\"Symbol.Value\", Field, 1, \"\"},\n\t},\n\t\"debug/plan9obj\": {\n\t\t{\"(*File).Close\", Method, 3, \"\"},\n\t\t{\"(*File).Section\", Method, 3, \"\"},\n\t\t{\"(*File).Symbols\", Method, 3, \"\"},\n\t\t{\"(*Section).Data\", Method, 3, \"\"},\n\t\t{\"(*Section).Open\", Method, 3, \"\"},\n\t\t{\"(Section).ReadAt\", Method, 3, \"\"},\n\t\t{\"ErrNoSymbols\", Var, 18, \"\"},\n\t\t{\"File\", Type, 3, \"\"},\n\t\t{\"File.FileHeader\", Field, 3, \"\"},\n\t\t{\"File.Sections\", Field, 3, \"\"},\n\t\t{\"FileHeader\", Type, 3, \"\"},\n\t\t{\"FileHeader.Bss\", Field, 3, \"\"},\n\t\t{\"FileHeader.Entry\", Field, 3, \"\"},\n\t\t{\"FileHeader.HdrSize\", Field, 4, \"\"},\n\t\t{\"FileHeader.LoadAddress\", Field, 4, \"\"},\n\t\t{\"FileHeader.Magic\", Field, 3, \"\"},\n\t\t{\"FileHeader.PtrSize\", Field, 3, \"\"},\n\t\t{\"Magic386\", Const, 3, \"\"},\n\t\t{\"Magic64\", Const, 3, \"\"},\n\t\t{\"MagicAMD64\", Const, 3, \"\"},\n\t\t{\"MagicARM\", Const, 3, \"\"},\n\t\t{\"NewFile\", Func, 3, \"func(r io.ReaderAt) (*File, error)\"},\n\t\t{\"Open\", Func, 3, \"func(name string) (*File, error)\"},\n\t\t{\"Section\", Type, 3, \"\"},\n\t\t{\"Section.ReaderAt\", Field, 3, \"\"},\n\t\t{\"Section.SectionHeader\", Field, 3, \"\"},\n\t\t{\"SectionHeader\", Type, 3, \"\"},\n\t\t{\"SectionHeader.Name\", Field, 3, \"\"},\n\t\t{\"SectionHeader.Offset\", Field, 3, \"\"},\n\t\t{\"SectionHeader.Size\", Field, 3, \"\"},\n\t\t{\"Sym\", Type, 3, \"\"},\n\t\t{\"Sym.Name\", Field, 3, \"\"},\n\t\t{\"Sym.Type\", Field, 3, \"\"},\n\t\t{\"Sym.Value\", Field, 3, \"\"},\n\t},\n\t\"embed\": {\n\t\t{\"(FS).Open\", Method, 16, \"\"},\n\t\t{\"(FS).ReadDir\", Method, 16, \"\"},\n\t\t{\"(FS).ReadFile\", Method, 16, \"\"},\n\t\t{\"FS\", Type, 16, \"\"},\n\t},\n\t\"encoding\": {\n\t\t{\"(BinaryAppender).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(BinaryMarshaler).MarshalBinary\", Method, 2, \"\"},\n\t\t{\"(BinaryUnmarshaler).UnmarshalBinary\", Method, 2, \"\"},\n\t\t{\"(TextAppender).AppendText\", Method, 24, \"\"},\n\t\t{\"(TextMarshaler).MarshalText\", Method, 2, \"\"},\n\t\t{\"(TextUnmarshaler).UnmarshalText\", Method, 2, \"\"},\n\t\t{\"BinaryAppender\", Type, 24, \"\"},\n\t\t{\"BinaryMarshaler\", Type, 2, \"\"},\n\t\t{\"BinaryUnmarshaler\", Type, 2, \"\"},\n\t\t{\"TextAppender\", Type, 24, \"\"},\n\t\t{\"TextMarshaler\", Type, 2, \"\"},\n\t\t{\"TextUnmarshaler\", Type, 2, \"\"},\n\t},\n\t\"encoding/ascii85\": {\n\t\t{\"(CorruptInputError).Error\", Method, 0, \"\"},\n\t\t{\"CorruptInputError\", Type, 0, \"\"},\n\t\t{\"Decode\", Func, 0, \"func(dst []byte, src []byte, flush bool) (ndst int, nsrc int, err error)\"},\n\t\t{\"Encode\", Func, 0, \"func(dst []byte, src []byte) int\"},\n\t\t{\"MaxEncodedLen\", Func, 0, \"func(n int) int\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(w io.Writer) io.WriteCloser\"},\n\t},\n\t\"encoding/asn1\": {\n\t\t{\"(BitString).At\", Method, 0, \"\"},\n\t\t{\"(BitString).RightAlign\", Method, 0, \"\"},\n\t\t{\"(ObjectIdentifier).Equal\", Method, 0, \"\"},\n\t\t{\"(ObjectIdentifier).String\", Method, 3, \"\"},\n\t\t{\"(StructuralError).Error\", Method, 0, \"\"},\n\t\t{\"(SyntaxError).Error\", Method, 0, \"\"},\n\t\t{\"BitString\", Type, 0, \"\"},\n\t\t{\"BitString.BitLength\", Field, 0, \"\"},\n\t\t{\"BitString.Bytes\", Field, 0, \"\"},\n\t\t{\"ClassApplication\", Const, 6, \"\"},\n\t\t{\"ClassContextSpecific\", Const, 6, \"\"},\n\t\t{\"ClassPrivate\", Const, 6, \"\"},\n\t\t{\"ClassUniversal\", Const, 6, \"\"},\n\t\t{\"Enumerated\", Type, 0, \"\"},\n\t\t{\"Flag\", Type, 0, \"\"},\n\t\t{\"Marshal\", Func, 0, \"func(val any) ([]byte, error)\"},\n\t\t{\"MarshalWithParams\", Func, 10, \"func(val any, params string) ([]byte, error)\"},\n\t\t{\"NullBytes\", Var, 9, \"\"},\n\t\t{\"NullRawValue\", Var, 9, \"\"},\n\t\t{\"ObjectIdentifier\", Type, 0, \"\"},\n\t\t{\"RawContent\", Type, 0, \"\"},\n\t\t{\"RawValue\", Type, 0, \"\"},\n\t\t{\"RawValue.Bytes\", Field, 0, \"\"},\n\t\t{\"RawValue.Class\", Field, 0, \"\"},\n\t\t{\"RawValue.FullBytes\", Field, 0, \"\"},\n\t\t{\"RawValue.IsCompound\", Field, 0, \"\"},\n\t\t{\"RawValue.Tag\", Field, 0, \"\"},\n\t\t{\"StructuralError\", Type, 0, \"\"},\n\t\t{\"StructuralError.Msg\", Field, 0, \"\"},\n\t\t{\"SyntaxError\", Type, 0, \"\"},\n\t\t{\"SyntaxError.Msg\", Field, 0, \"\"},\n\t\t{\"TagBMPString\", Const, 14, \"\"},\n\t\t{\"TagBitString\", Const, 6, \"\"},\n\t\t{\"TagBoolean\", Const, 6, \"\"},\n\t\t{\"TagEnum\", Const, 6, \"\"},\n\t\t{\"TagGeneralString\", Const, 6, \"\"},\n\t\t{\"TagGeneralizedTime\", Const, 6, \"\"},\n\t\t{\"TagIA5String\", Const, 6, \"\"},\n\t\t{\"TagInteger\", Const, 6, \"\"},\n\t\t{\"TagNull\", Const, 9, \"\"},\n\t\t{\"TagNumericString\", Const, 10, \"\"},\n\t\t{\"TagOID\", Const, 6, \"\"},\n\t\t{\"TagOctetString\", Const, 6, \"\"},\n\t\t{\"TagPrintableString\", Const, 6, \"\"},\n\t\t{\"TagSequence\", Const, 6, \"\"},\n\t\t{\"TagSet\", Const, 6, \"\"},\n\t\t{\"TagT61String\", Const, 6, \"\"},\n\t\t{\"TagUTCTime\", Const, 6, \"\"},\n\t\t{\"TagUTF8String\", Const, 6, \"\"},\n\t\t{\"Unmarshal\", Func, 0, \"func(b []byte, val any) (rest []byte, err error)\"},\n\t\t{\"UnmarshalWithParams\", Func, 0, \"func(b []byte, val any, params string) (rest []byte, err error)\"},\n\t},\n\t\"encoding/base32\": {\n\t\t{\"(*Encoding).AppendDecode\", Method, 22, \"\"},\n\t\t{\"(*Encoding).AppendEncode\", Method, 22, \"\"},\n\t\t{\"(*Encoding).Decode\", Method, 0, \"\"},\n\t\t{\"(*Encoding).DecodeString\", Method, 0, \"\"},\n\t\t{\"(*Encoding).DecodedLen\", Method, 0, \"\"},\n\t\t{\"(*Encoding).Encode\", Method, 0, \"\"},\n\t\t{\"(*Encoding).EncodeToString\", Method, 0, \"\"},\n\t\t{\"(*Encoding).EncodedLen\", Method, 0, \"\"},\n\t\t{\"(CorruptInputError).Error\", Method, 0, \"\"},\n\t\t{\"(Encoding).WithPadding\", Method, 9, \"\"},\n\t\t{\"CorruptInputError\", Type, 0, \"\"},\n\t\t{\"Encoding\", Type, 0, \"\"},\n\t\t{\"HexEncoding\", Var, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(enc *Encoding, r io.Reader) io.Reader\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(enc *Encoding, w io.Writer) io.WriteCloser\"},\n\t\t{\"NewEncoding\", Func, 0, \"func(encoder string) *Encoding\"},\n\t\t{\"NoPadding\", Const, 9, \"\"},\n\t\t{\"StdEncoding\", Var, 0, \"\"},\n\t\t{\"StdPadding\", Const, 9, \"\"},\n\t},\n\t\"encoding/base64\": {\n\t\t{\"(*Encoding).AppendDecode\", Method, 22, \"\"},\n\t\t{\"(*Encoding).AppendEncode\", Method, 22, \"\"},\n\t\t{\"(*Encoding).Decode\", Method, 0, \"\"},\n\t\t{\"(*Encoding).DecodeString\", Method, 0, \"\"},\n\t\t{\"(*Encoding).DecodedLen\", Method, 0, \"\"},\n\t\t{\"(*Encoding).Encode\", Method, 0, \"\"},\n\t\t{\"(*Encoding).EncodeToString\", Method, 0, \"\"},\n\t\t{\"(*Encoding).EncodedLen\", Method, 0, \"\"},\n\t\t{\"(CorruptInputError).Error\", Method, 0, \"\"},\n\t\t{\"(Encoding).Strict\", Method, 8, \"\"},\n\t\t{\"(Encoding).WithPadding\", Method, 5, \"\"},\n\t\t{\"CorruptInputError\", Type, 0, \"\"},\n\t\t{\"Encoding\", Type, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(enc *Encoding, r io.Reader) io.Reader\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(enc *Encoding, w io.Writer) io.WriteCloser\"},\n\t\t{\"NewEncoding\", Func, 0, \"func(encoder string) *Encoding\"},\n\t\t{\"NoPadding\", Const, 5, \"\"},\n\t\t{\"RawStdEncoding\", Var, 5, \"\"},\n\t\t{\"RawURLEncoding\", Var, 5, \"\"},\n\t\t{\"StdEncoding\", Var, 0, \"\"},\n\t\t{\"StdPadding\", Const, 5, \"\"},\n\t\t{\"URLEncoding\", Var, 0, \"\"},\n\t},\n\t\"encoding/binary\": {\n\t\t{\"(AppendByteOrder).AppendUint16\", Method, 19, \"\"},\n\t\t{\"(AppendByteOrder).AppendUint32\", Method, 19, \"\"},\n\t\t{\"(AppendByteOrder).AppendUint64\", Method, 19, \"\"},\n\t\t{\"(AppendByteOrder).String\", Method, 19, \"\"},\n\t\t{\"(ByteOrder).PutUint16\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).PutUint32\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).PutUint64\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).String\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).Uint16\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).Uint32\", Method, 0, \"\"},\n\t\t{\"(ByteOrder).Uint64\", Method, 0, \"\"},\n\t\t{\"Append\", Func, 23, \"func(buf []byte, order ByteOrder, data any) ([]byte, error)\"},\n\t\t{\"AppendByteOrder\", Type, 19, \"\"},\n\t\t{\"AppendUvarint\", Func, 19, \"func(buf []byte, x uint64) []byte\"},\n\t\t{\"AppendVarint\", Func, 19, \"func(buf []byte, x int64) []byte\"},\n\t\t{\"BigEndian\", Var, 0, \"\"},\n\t\t{\"ByteOrder\", Type, 0, \"\"},\n\t\t{\"Decode\", Func, 23, \"func(buf []byte, order ByteOrder, data any) (int, error)\"},\n\t\t{\"Encode\", Func, 23, \"func(buf []byte, order ByteOrder, data any) (int, error)\"},\n\t\t{\"LittleEndian\", Var, 0, \"\"},\n\t\t{\"MaxVarintLen16\", Const, 0, \"\"},\n\t\t{\"MaxVarintLen32\", Const, 0, \"\"},\n\t\t{\"MaxVarintLen64\", Const, 0, \"\"},\n\t\t{\"NativeEndian\", Var, 21, \"\"},\n\t\t{\"PutUvarint\", Func, 0, \"func(buf []byte, x uint64) int\"},\n\t\t{\"PutVarint\", Func, 0, \"func(buf []byte, x int64) int\"},\n\t\t{\"Read\", Func, 0, \"func(r io.Reader, order ByteOrder, data any) error\"},\n\t\t{\"ReadUvarint\", Func, 0, \"func(r io.ByteReader) (uint64, error)\"},\n\t\t{\"ReadVarint\", Func, 0, \"func(r io.ByteReader) (int64, error)\"},\n\t\t{\"Size\", Func, 0, \"func(v any) int\"},\n\t\t{\"Uvarint\", Func, 0, \"func(buf []byte) (uint64, int)\"},\n\t\t{\"Varint\", Func, 0, \"func(buf []byte) (int64, int)\"},\n\t\t{\"Write\", Func, 0, \"func(w io.Writer, order ByteOrder, data any) error\"},\n\t},\n\t\"encoding/csv\": {\n\t\t{\"(*ParseError).Error\", Method, 0, \"\"},\n\t\t{\"(*ParseError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*Reader).FieldPos\", Method, 17, \"\"},\n\t\t{\"(*Reader).InputOffset\", Method, 19, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadAll\", Method, 0, \"\"},\n\t\t{\"(*Writer).Error\", Method, 1, \"\"},\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"(*Writer).WriteAll\", Method, 0, \"\"},\n\t\t{\"ErrBareQuote\", Var, 0, \"\"},\n\t\t{\"ErrFieldCount\", Var, 0, \"\"},\n\t\t{\"ErrQuote\", Var, 0, \"\"},\n\t\t{\"ErrTrailingComma\", Var, 0, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader) *Reader\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"ParseError\", Type, 0, \"\"},\n\t\t{\"ParseError.Column\", Field, 0, \"\"},\n\t\t{\"ParseError.Err\", Field, 0, \"\"},\n\t\t{\"ParseError.Line\", Field, 0, \"\"},\n\t\t{\"ParseError.StartLine\", Field, 10, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Reader.Comma\", Field, 0, \"\"},\n\t\t{\"Reader.Comment\", Field, 0, \"\"},\n\t\t{\"Reader.FieldsPerRecord\", Field, 0, \"\"},\n\t\t{\"Reader.LazyQuotes\", Field, 0, \"\"},\n\t\t{\"Reader.ReuseRecord\", Field, 9, \"\"},\n\t\t{\"Reader.TrailingComma\", Field, 0, \"\"},\n\t\t{\"Reader.TrimLeadingSpace\", Field, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t\t{\"Writer.Comma\", Field, 0, \"\"},\n\t\t{\"Writer.UseCRLF\", Field, 0, \"\"},\n\t},\n\t\"encoding/gob\": {\n\t\t{\"(*Decoder).Decode\", Method, 0, \"\"},\n\t\t{\"(*Decoder).DecodeValue\", Method, 0, \"\"},\n\t\t{\"(*Encoder).Encode\", Method, 0, \"\"},\n\t\t{\"(*Encoder).EncodeValue\", Method, 0, \"\"},\n\t\t{\"(GobDecoder).GobDecode\", Method, 0, \"\"},\n\t\t{\"(GobEncoder).GobEncode\", Method, 0, \"\"},\n\t\t{\"CommonType\", Type, 0, \"\"},\n\t\t{\"CommonType.Id\", Field, 0, \"\"},\n\t\t{\"CommonType.Name\", Field, 0, \"\"},\n\t\t{\"Decoder\", Type, 0, \"\"},\n\t\t{\"Encoder\", Type, 0, \"\"},\n\t\t{\"GobDecoder\", Type, 0, \"\"},\n\t\t{\"GobEncoder\", Type, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(r io.Reader) *Decoder\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(w io.Writer) *Encoder\"},\n\t\t{\"Register\", Func, 0, \"func(value any)\"},\n\t\t{\"RegisterName\", Func, 0, \"func(name string, value any)\"},\n\t},\n\t\"encoding/hex\": {\n\t\t{\"(InvalidByteError).Error\", Method, 0, \"\"},\n\t\t{\"AppendDecode\", Func, 22, \"func(dst []byte, src []byte) ([]byte, error)\"},\n\t\t{\"AppendEncode\", Func, 22, \"func(dst []byte, src []byte) []byte\"},\n\t\t{\"Decode\", Func, 0, \"func(dst []byte, src []byte) (int, error)\"},\n\t\t{\"DecodeString\", Func, 0, \"func(s string) ([]byte, error)\"},\n\t\t{\"DecodedLen\", Func, 0, \"func(x int) int\"},\n\t\t{\"Dump\", Func, 0, \"func(data []byte) string\"},\n\t\t{\"Dumper\", Func, 0, \"func(w io.Writer) io.WriteCloser\"},\n\t\t{\"Encode\", Func, 0, \"func(dst []byte, src []byte) int\"},\n\t\t{\"EncodeToString\", Func, 0, \"func(src []byte) string\"},\n\t\t{\"EncodedLen\", Func, 0, \"func(n int) int\"},\n\t\t{\"ErrLength\", Var, 0, \"\"},\n\t\t{\"InvalidByteError\", Type, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 10, \"func(r io.Reader) io.Reader\"},\n\t\t{\"NewEncoder\", Func, 10, \"func(w io.Writer) io.Writer\"},\n\t},\n\t\"encoding/json\": {\n\t\t{\"(*Decoder).Buffered\", Method, 1, \"\"},\n\t\t{\"(*Decoder).Decode\", Method, 0, \"\"},\n\t\t{\"(*Decoder).DisallowUnknownFields\", Method, 10, \"\"},\n\t\t{\"(*Decoder).InputOffset\", Method, 14, \"\"},\n\t\t{\"(*Decoder).More\", Method, 5, \"\"},\n\t\t{\"(*Decoder).Token\", Method, 5, \"\"},\n\t\t{\"(*Decoder).UseNumber\", Method, 1, \"\"},\n\t\t{\"(*Encoder).Encode\", Method, 0, \"\"},\n\t\t{\"(*Encoder).SetEscapeHTML\", Method, 7, \"\"},\n\t\t{\"(*Encoder).SetIndent\", Method, 7, \"\"},\n\t\t{\"(*InvalidUTF8Error).Error\", Method, 0, \"\"},\n\t\t{\"(*InvalidUnmarshalError).Error\", Method, 0, \"\"},\n\t\t{\"(*MarshalerError).Error\", Method, 0, \"\"},\n\t\t{\"(*MarshalerError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*RawMessage).MarshalJSON\", Method, 0, \"\"},\n\t\t{\"(*RawMessage).UnmarshalJSON\", Method, 0, \"\"},\n\t\t{\"(*SyntaxError).Error\", Method, 0, \"\"},\n\t\t{\"(*UnmarshalFieldError).Error\", Method, 0, \"\"},\n\t\t{\"(*UnmarshalTypeError).Error\", Method, 0, \"\"},\n\t\t{\"(*UnsupportedTypeError).Error\", Method, 0, \"\"},\n\t\t{\"(*UnsupportedValueError).Error\", Method, 0, \"\"},\n\t\t{\"(Delim).String\", Method, 5, \"\"},\n\t\t{\"(Marshaler).MarshalJSON\", Method, 0, \"\"},\n\t\t{\"(Number).Float64\", Method, 1, \"\"},\n\t\t{\"(Number).Int64\", Method, 1, \"\"},\n\t\t{\"(Number).String\", Method, 1, \"\"},\n\t\t{\"(RawMessage).MarshalJSON\", Method, 8, \"\"},\n\t\t{\"(Unmarshaler).UnmarshalJSON\", Method, 0, \"\"},\n\t\t{\"Compact\", Func, 0, \"func(dst *bytes.Buffer, src []byte) error\"},\n\t\t{\"Decoder\", Type, 0, \"\"},\n\t\t{\"Delim\", Type, 5, \"\"},\n\t\t{\"Encoder\", Type, 0, \"\"},\n\t\t{\"HTMLEscape\", Func, 0, \"func(dst *bytes.Buffer, src []byte)\"},\n\t\t{\"Indent\", Func, 0, \"func(dst *bytes.Buffer, src []byte, prefix string, indent string) error\"},\n\t\t{\"InvalidUTF8Error\", Type, 0, \"\"},\n\t\t{\"InvalidUTF8Error.S\", Field, 0, \"\"},\n\t\t{\"InvalidUnmarshalError\", Type, 0, \"\"},\n\t\t{\"InvalidUnmarshalError.Type\", Field, 0, \"\"},\n\t\t{\"Marshal\", Func, 0, \"func(v any) ([]byte, error)\"},\n\t\t{\"MarshalIndent\", Func, 0, \"func(v any, prefix string, indent string) ([]byte, error)\"},\n\t\t{\"Marshaler\", Type, 0, \"\"},\n\t\t{\"MarshalerError\", Type, 0, \"\"},\n\t\t{\"MarshalerError.Err\", Field, 0, \"\"},\n\t\t{\"MarshalerError.Type\", Field, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(r io.Reader) *Decoder\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(w io.Writer) *Encoder\"},\n\t\t{\"Number\", Type, 1, \"\"},\n\t\t{\"RawMessage\", Type, 0, \"\"},\n\t\t{\"SyntaxError\", Type, 0, \"\"},\n\t\t{\"SyntaxError.Offset\", Field, 0, \"\"},\n\t\t{\"Token\", Type, 5, \"\"},\n\t\t{\"Unmarshal\", Func, 0, \"func(data []byte, v any) error\"},\n\t\t{\"UnmarshalFieldError\", Type, 0, \"\"},\n\t\t{\"UnmarshalFieldError.Field\", Field, 0, \"\"},\n\t\t{\"UnmarshalFieldError.Key\", Field, 0, \"\"},\n\t\t{\"UnmarshalFieldError.Type\", Field, 0, \"\"},\n\t\t{\"UnmarshalTypeError\", Type, 0, \"\"},\n\t\t{\"UnmarshalTypeError.Field\", Field, 8, \"\"},\n\t\t{\"UnmarshalTypeError.Offset\", Field, 5, \"\"},\n\t\t{\"UnmarshalTypeError.Struct\", Field, 8, \"\"},\n\t\t{\"UnmarshalTypeError.Type\", Field, 0, \"\"},\n\t\t{\"UnmarshalTypeError.Value\", Field, 0, \"\"},\n\t\t{\"Unmarshaler\", Type, 0, \"\"},\n\t\t{\"UnsupportedTypeError\", Type, 0, \"\"},\n\t\t{\"UnsupportedTypeError.Type\", Field, 0, \"\"},\n\t\t{\"UnsupportedValueError\", Type, 0, \"\"},\n\t\t{\"UnsupportedValueError.Str\", Field, 0, \"\"},\n\t\t{\"UnsupportedValueError.Value\", Field, 0, \"\"},\n\t\t{\"Valid\", Func, 9, \"func(data []byte) bool\"},\n\t},\n\t\"encoding/pem\": {\n\t\t{\"Block\", Type, 0, \"\"},\n\t\t{\"Block.Bytes\", Field, 0, \"\"},\n\t\t{\"Block.Headers\", Field, 0, \"\"},\n\t\t{\"Block.Type\", Field, 0, \"\"},\n\t\t{\"Decode\", Func, 0, \"func(data []byte) (p *Block, rest []byte)\"},\n\t\t{\"Encode\", Func, 0, \"func(out io.Writer, b *Block) error\"},\n\t\t{\"EncodeToMemory\", Func, 0, \"func(b *Block) []byte\"},\n\t},\n\t\"encoding/xml\": {\n\t\t{\"(*Decoder).Decode\", Method, 0, \"\"},\n\t\t{\"(*Decoder).DecodeElement\", Method, 0, \"\"},\n\t\t{\"(*Decoder).InputOffset\", Method, 4, \"\"},\n\t\t{\"(*Decoder).InputPos\", Method, 19, \"\"},\n\t\t{\"(*Decoder).RawToken\", Method, 0, \"\"},\n\t\t{\"(*Decoder).Skip\", Method, 0, \"\"},\n\t\t{\"(*Decoder).Token\", Method, 0, \"\"},\n\t\t{\"(*Encoder).Close\", Method, 20, \"\"},\n\t\t{\"(*Encoder).Encode\", Method, 0, \"\"},\n\t\t{\"(*Encoder).EncodeElement\", Method, 2, \"\"},\n\t\t{\"(*Encoder).EncodeToken\", Method, 2, \"\"},\n\t\t{\"(*Encoder).Flush\", Method, 2, \"\"},\n\t\t{\"(*Encoder).Indent\", Method, 1, \"\"},\n\t\t{\"(*SyntaxError).Error\", Method, 0, \"\"},\n\t\t{\"(*TagPathError).Error\", Method, 0, \"\"},\n\t\t{\"(*UnsupportedTypeError).Error\", Method, 0, \"\"},\n\t\t{\"(CharData).Copy\", Method, 0, \"\"},\n\t\t{\"(Comment).Copy\", Method, 0, \"\"},\n\t\t{\"(Directive).Copy\", Method, 0, \"\"},\n\t\t{\"(Marshaler).MarshalXML\", Method, 2, \"\"},\n\t\t{\"(MarshalerAttr).MarshalXMLAttr\", Method, 2, \"\"},\n\t\t{\"(ProcInst).Copy\", Method, 0, \"\"},\n\t\t{\"(StartElement).Copy\", Method, 0, \"\"},\n\t\t{\"(StartElement).End\", Method, 2, \"\"},\n\t\t{\"(TokenReader).Token\", Method, 10, \"\"},\n\t\t{\"(UnmarshalError).Error\", Method, 0, \"\"},\n\t\t{\"(Unmarshaler).UnmarshalXML\", Method, 2, \"\"},\n\t\t{\"(UnmarshalerAttr).UnmarshalXMLAttr\", Method, 2, \"\"},\n\t\t{\"Attr\", Type, 0, \"\"},\n\t\t{\"Attr.Name\", Field, 0, \"\"},\n\t\t{\"Attr.Value\", Field, 0, \"\"},\n\t\t{\"CharData\", Type, 0, \"\"},\n\t\t{\"Comment\", Type, 0, \"\"},\n\t\t{\"CopyToken\", Func, 0, \"func(t Token) Token\"},\n\t\t{\"Decoder\", Type, 0, \"\"},\n\t\t{\"Decoder.AutoClose\", Field, 0, \"\"},\n\t\t{\"Decoder.CharsetReader\", Field, 0, \"\"},\n\t\t{\"Decoder.DefaultSpace\", Field, 1, \"\"},\n\t\t{\"Decoder.Entity\", Field, 0, \"\"},\n\t\t{\"Decoder.Strict\", Field, 0, \"\"},\n\t\t{\"Directive\", Type, 0, \"\"},\n\t\t{\"Encoder\", Type, 0, \"\"},\n\t\t{\"EndElement\", Type, 0, \"\"},\n\t\t{\"EndElement.Name\", Field, 0, \"\"},\n\t\t{\"Escape\", Func, 0, \"func(w io.Writer, s []byte)\"},\n\t\t{\"EscapeText\", Func, 1, \"func(w io.Writer, s []byte) error\"},\n\t\t{\"HTMLAutoClose\", Var, 0, \"\"},\n\t\t{\"HTMLEntity\", Var, 0, \"\"},\n\t\t{\"Header\", Const, 0, \"\"},\n\t\t{\"Marshal\", Func, 0, \"func(v any) ([]byte, error)\"},\n\t\t{\"MarshalIndent\", Func, 0, \"func(v any, prefix string, indent string) ([]byte, error)\"},\n\t\t{\"Marshaler\", Type, 2, \"\"},\n\t\t{\"MarshalerAttr\", Type, 2, \"\"},\n\t\t{\"Name\", Type, 0, \"\"},\n\t\t{\"Name.Local\", Field, 0, \"\"},\n\t\t{\"Name.Space\", Field, 0, \"\"},\n\t\t{\"NewDecoder\", Func, 0, \"func(r io.Reader) *Decoder\"},\n\t\t{\"NewEncoder\", Func, 0, \"func(w io.Writer) *Encoder\"},\n\t\t{\"NewTokenDecoder\", Func, 10, \"func(t TokenReader) *Decoder\"},\n\t\t{\"ProcInst\", Type, 0, \"\"},\n\t\t{\"ProcInst.Inst\", Field, 0, \"\"},\n\t\t{\"ProcInst.Target\", Field, 0, \"\"},\n\t\t{\"StartElement\", Type, 0, \"\"},\n\t\t{\"StartElement.Attr\", Field, 0, \"\"},\n\t\t{\"StartElement.Name\", Field, 0, \"\"},\n\t\t{\"SyntaxError\", Type, 0, \"\"},\n\t\t{\"SyntaxError.Line\", Field, 0, \"\"},\n\t\t{\"SyntaxError.Msg\", Field, 0, \"\"},\n\t\t{\"TagPathError\", Type, 0, \"\"},\n\t\t{\"TagPathError.Field1\", Field, 0, \"\"},\n\t\t{\"TagPathError.Field2\", Field, 0, \"\"},\n\t\t{\"TagPathError.Struct\", Field, 0, \"\"},\n\t\t{\"TagPathError.Tag1\", Field, 0, \"\"},\n\t\t{\"TagPathError.Tag2\", Field, 0, \"\"},\n\t\t{\"Token\", Type, 0, \"\"},\n\t\t{\"TokenReader\", Type, 10, \"\"},\n\t\t{\"Unmarshal\", Func, 0, \"func(data []byte, v any) error\"},\n\t\t{\"UnmarshalError\", Type, 0, \"\"},\n\t\t{\"Unmarshaler\", Type, 2, \"\"},\n\t\t{\"UnmarshalerAttr\", Type, 2, \"\"},\n\t\t{\"UnsupportedTypeError\", Type, 0, \"\"},\n\t\t{\"UnsupportedTypeError.Type\", Field, 0, \"\"},\n\t},\n\t\"errors\": {\n\t\t{\"As\", Func, 13, \"func(err error, target any) bool\"},\n\t\t{\"AsType\", Func, 26, \"func[E error](err error) (E, bool)\"},\n\t\t{\"ErrUnsupported\", Var, 21, \"\"},\n\t\t{\"Is\", Func, 13, \"func(err error, target error) bool\"},\n\t\t{\"Join\", Func, 20, \"func(errs ...error) error\"},\n\t\t{\"New\", Func, 0, \"func(text string) error\"},\n\t\t{\"Unwrap\", Func, 13, \"func(err error) error\"},\n\t},\n\t\"expvar\": {\n\t\t{\"(*Float).Add\", Method, 0, \"\"},\n\t\t{\"(*Float).Set\", Method, 0, \"\"},\n\t\t{\"(*Float).String\", Method, 0, \"\"},\n\t\t{\"(*Float).Value\", Method, 8, \"\"},\n\t\t{\"(*Int).Add\", Method, 0, \"\"},\n\t\t{\"(*Int).Set\", Method, 0, \"\"},\n\t\t{\"(*Int).String\", Method, 0, \"\"},\n\t\t{\"(*Int).Value\", Method, 8, \"\"},\n\t\t{\"(*Map).Add\", Method, 0, \"\"},\n\t\t{\"(*Map).AddFloat\", Method, 0, \"\"},\n\t\t{\"(*Map).Delete\", Method, 12, \"\"},\n\t\t{\"(*Map).Do\", Method, 0, \"\"},\n\t\t{\"(*Map).Get\", Method, 0, \"\"},\n\t\t{\"(*Map).Init\", Method, 0, \"\"},\n\t\t{\"(*Map).Set\", Method, 0, \"\"},\n\t\t{\"(*Map).String\", Method, 0, \"\"},\n\t\t{\"(*String).Set\", Method, 0, \"\"},\n\t\t{\"(*String).String\", Method, 0, \"\"},\n\t\t{\"(*String).Value\", Method, 8, \"\"},\n\t\t{\"(Func).String\", Method, 0, \"\"},\n\t\t{\"(Func).Value\", Method, 8, \"\"},\n\t\t{\"(Var).String\", Method, 0, \"\"},\n\t\t{\"Do\", Func, 0, \"func(f func(KeyValue))\"},\n\t\t{\"Float\", Type, 0, \"\"},\n\t\t{\"Func\", Type, 0, \"\"},\n\t\t{\"Get\", Func, 0, \"func(name string) Var\"},\n\t\t{\"Handler\", Func, 8, \"func() http.Handler\"},\n\t\t{\"Int\", Type, 0, \"\"},\n\t\t{\"KeyValue\", Type, 0, \"\"},\n\t\t{\"KeyValue.Key\", Field, 0, \"\"},\n\t\t{\"KeyValue.Value\", Field, 0, \"\"},\n\t\t{\"Map\", Type, 0, \"\"},\n\t\t{\"NewFloat\", Func, 0, \"func(name string) *Float\"},\n\t\t{\"NewInt\", Func, 0, \"func(name string) *Int\"},\n\t\t{\"NewMap\", Func, 0, \"func(name string) *Map\"},\n\t\t{\"NewString\", Func, 0, \"func(name string) *String\"},\n\t\t{\"Publish\", Func, 0, \"func(name string, v Var)\"},\n\t\t{\"String\", Type, 0, \"\"},\n\t\t{\"Var\", Type, 0, \"\"},\n\t},\n\t\"flag\": {\n\t\t{\"(*FlagSet).Arg\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Args\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Bool\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).BoolFunc\", Method, 21, \"\"},\n\t\t{\"(*FlagSet).BoolVar\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Duration\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).DurationVar\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).ErrorHandling\", Method, 10, \"\"},\n\t\t{\"(*FlagSet).Float64\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Float64Var\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Func\", Method, 16, \"\"},\n\t\t{\"(*FlagSet).Init\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Int\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Int64\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Int64Var\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).IntVar\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Lookup\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).NArg\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).NFlag\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Name\", Method, 10, \"\"},\n\t\t{\"(*FlagSet).Output\", Method, 10, \"\"},\n\t\t{\"(*FlagSet).Parse\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Parsed\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).PrintDefaults\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Set\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).SetOutput\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).String\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).StringVar\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).TextVar\", Method, 19, \"\"},\n\t\t{\"(*FlagSet).Uint\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Uint64\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Uint64Var\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).UintVar\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Var\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).Visit\", Method, 0, \"\"},\n\t\t{\"(*FlagSet).VisitAll\", Method, 0, \"\"},\n\t\t{\"(Getter).Get\", Method, 2, \"\"},\n\t\t{\"(Getter).Set\", Method, 2, \"\"},\n\t\t{\"(Getter).String\", Method, 2, \"\"},\n\t\t{\"(Value).Set\", Method, 0, \"\"},\n\t\t{\"(Value).String\", Method, 0, \"\"},\n\t\t{\"Arg\", Func, 0, \"func(i int) string\"},\n\t\t{\"Args\", Func, 0, \"func() []string\"},\n\t\t{\"Bool\", Func, 0, \"func(name string, value bool, usage string) *bool\"},\n\t\t{\"BoolFunc\", Func, 21, \"func(name string, usage string, fn func(string) error)\"},\n\t\t{\"BoolVar\", Func, 0, \"func(p *bool, name string, value bool, usage string)\"},\n\t\t{\"CommandLine\", Var, 2, \"\"},\n\t\t{\"ContinueOnError\", Const, 0, \"\"},\n\t\t{\"Duration\", Func, 0, \"func(name string, value time.Duration, usage string) *time.Duration\"},\n\t\t{\"DurationVar\", Func, 0, \"func(p *time.Duration, name string, value time.Duration, usage string)\"},\n\t\t{\"ErrHelp\", Var, 0, \"\"},\n\t\t{\"ErrorHandling\", Type, 0, \"\"},\n\t\t{\"ExitOnError\", Const, 0, \"\"},\n\t\t{\"Flag\", Type, 0, \"\"},\n\t\t{\"Flag.DefValue\", Field, 0, \"\"},\n\t\t{\"Flag.Name\", Field, 0, \"\"},\n\t\t{\"Flag.Usage\", Field, 0, \"\"},\n\t\t{\"Flag.Value\", Field, 0, \"\"},\n\t\t{\"FlagSet\", Type, 0, \"\"},\n\t\t{\"FlagSet.Usage\", Field, 0, \"\"},\n\t\t{\"Float64\", Func, 0, \"func(name string, value float64, usage string) *float64\"},\n\t\t{\"Float64Var\", Func, 0, \"func(p *float64, name string, value float64, usage string)\"},\n\t\t{\"Func\", Func, 16, \"func(name string, usage string, fn func(string) error)\"},\n\t\t{\"Getter\", Type, 2, \"\"},\n\t\t{\"Int\", Func, 0, \"func(name string, value int, usage string) *int\"},\n\t\t{\"Int64\", Func, 0, \"func(name string, value int64, usage string) *int64\"},\n\t\t{\"Int64Var\", Func, 0, \"func(p *int64, name string, value int64, usage string)\"},\n\t\t{\"IntVar\", Func, 0, \"func(p *int, name string, value int, usage string)\"},\n\t\t{\"Lookup\", Func, 0, \"func(name string) *Flag\"},\n\t\t{\"NArg\", Func, 0, \"func() int\"},\n\t\t{\"NFlag\", Func, 0, \"func() int\"},\n\t\t{\"NewFlagSet\", Func, 0, \"func(name string, errorHandling ErrorHandling) *FlagSet\"},\n\t\t{\"PanicOnError\", Const, 0, \"\"},\n\t\t{\"Parse\", Func, 0, \"func()\"},\n\t\t{\"Parsed\", Func, 0, \"func() bool\"},\n\t\t{\"PrintDefaults\", Func, 0, \"func()\"},\n\t\t{\"Set\", Func, 0, \"func(name string, value string) error\"},\n\t\t{\"String\", Func, 0, \"func(name string, value string, usage string) *string\"},\n\t\t{\"StringVar\", Func, 0, \"func(p *string, name string, value string, usage string)\"},\n\t\t{\"TextVar\", Func, 19, \"func(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string)\"},\n\t\t{\"Uint\", Func, 0, \"func(name string, value uint, usage string) *uint\"},\n\t\t{\"Uint64\", Func, 0, \"func(name string, value uint64, usage string) *uint64\"},\n\t\t{\"Uint64Var\", Func, 0, \"func(p *uint64, name string, value uint64, usage string)\"},\n\t\t{\"UintVar\", Func, 0, \"func(p *uint, name string, value uint, usage string)\"},\n\t\t{\"UnquoteUsage\", Func, 5, \"func(flag *Flag) (name string, usage string)\"},\n\t\t{\"Usage\", Var, 0, \"\"},\n\t\t{\"Value\", Type, 0, \"\"},\n\t\t{\"Var\", Func, 0, \"func(value Value, name string, usage string)\"},\n\t\t{\"Visit\", Func, 0, \"func(fn func(*Flag))\"},\n\t\t{\"VisitAll\", Func, 0, \"func(fn func(*Flag))\"},\n\t},\n\t\"fmt\": {\n\t\t{\"(Formatter).Format\", Method, 0, \"\"},\n\t\t{\"(GoStringer).GoString\", Method, 0, \"\"},\n\t\t{\"(ScanState).Read\", Method, 0, \"\"},\n\t\t{\"(ScanState).ReadRune\", Method, 0, \"\"},\n\t\t{\"(ScanState).SkipSpace\", Method, 0, \"\"},\n\t\t{\"(ScanState).Token\", Method, 0, \"\"},\n\t\t{\"(ScanState).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(ScanState).Width\", Method, 0, \"\"},\n\t\t{\"(Scanner).Scan\", Method, 0, \"\"},\n\t\t{\"(State).Flag\", Method, 0, \"\"},\n\t\t{\"(State).Precision\", Method, 0, \"\"},\n\t\t{\"(State).Width\", Method, 0, \"\"},\n\t\t{\"(State).Write\", Method, 0, \"\"},\n\t\t{\"(Stringer).String\", Method, 0, \"\"},\n\t\t{\"Append\", Func, 19, \"func(b []byte, a ...any) []byte\"},\n\t\t{\"Appendf\", Func, 19, \"func(b []byte, format string, a ...any) []byte\"},\n\t\t{\"Appendln\", Func, 19, \"func(b []byte, a ...any) []byte\"},\n\t\t{\"Errorf\", Func, 0, \"func(format string, a ...any) (err error)\"},\n\t\t{\"FormatString\", Func, 20, \"func(state State, verb rune) string\"},\n\t\t{\"Formatter\", Type, 0, \"\"},\n\t\t{\"Fprint\", Func, 0, \"func(w io.Writer, a ...any) (n int, err error)\"},\n\t\t{\"Fprintf\", Func, 0, \"func(w io.Writer, format string, a ...any) (n int, err error)\"},\n\t\t{\"Fprintln\", Func, 0, \"func(w io.Writer, a ...any) (n int, err error)\"},\n\t\t{\"Fscan\", Func, 0, \"func(r io.Reader, a ...any) (n int, err error)\"},\n\t\t{\"Fscanf\", Func, 0, \"func(r io.Reader, format string, a ...any) (n int, err error)\"},\n\t\t{\"Fscanln\", Func, 0, \"func(r io.Reader, a ...any) (n int, err error)\"},\n\t\t{\"GoStringer\", Type, 0, \"\"},\n\t\t{\"Print\", Func, 0, \"func(a ...any) (n int, err error)\"},\n\t\t{\"Printf\", Func, 0, \"func(format string, a ...any) (n int, err error)\"},\n\t\t{\"Println\", Func, 0, \"func(a ...any) (n int, err error)\"},\n\t\t{\"Scan\", Func, 0, \"func(a ...any) (n int, err error)\"},\n\t\t{\"ScanState\", Type, 0, \"\"},\n\t\t{\"Scanf\", Func, 0, \"func(format string, a ...any) (n int, err error)\"},\n\t\t{\"Scanln\", Func, 0, \"func(a ...any) (n int, err error)\"},\n\t\t{\"Scanner\", Type, 0, \"\"},\n\t\t{\"Sprint\", Func, 0, \"func(a ...any) string\"},\n\t\t{\"Sprintf\", Func, 0, \"func(format string, a ...any) string\"},\n\t\t{\"Sprintln\", Func, 0, \"func(a ...any) string\"},\n\t\t{\"Sscan\", Func, 0, \"func(str string, a ...any) (n int, err error)\"},\n\t\t{\"Sscanf\", Func, 0, \"func(str string, format string, a ...any) (n int, err error)\"},\n\t\t{\"Sscanln\", Func, 0, \"func(str string, a ...any) (n int, err error)\"},\n\t\t{\"State\", Type, 0, \"\"},\n\t\t{\"Stringer\", Type, 0, \"\"},\n\t},\n\t\"go/ast\": {\n\t\t{\"(*ArrayType).End\", Method, 0, \"\"},\n\t\t{\"(*ArrayType).Pos\", Method, 0, \"\"},\n\t\t{\"(*AssignStmt).End\", Method, 0, \"\"},\n\t\t{\"(*AssignStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*BadDecl).End\", Method, 0, \"\"},\n\t\t{\"(*BadDecl).Pos\", Method, 0, \"\"},\n\t\t{\"(*BadExpr).End\", Method, 0, \"\"},\n\t\t{\"(*BadExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*BadStmt).End\", Method, 0, \"\"},\n\t\t{\"(*BadStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*BasicLit).End\", Method, 0, \"\"},\n\t\t{\"(*BasicLit).Pos\", Method, 0, \"\"},\n\t\t{\"(*BinaryExpr).End\", Method, 0, \"\"},\n\t\t{\"(*BinaryExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*BlockStmt).End\", Method, 0, \"\"},\n\t\t{\"(*BlockStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*BranchStmt).End\", Method, 0, \"\"},\n\t\t{\"(*BranchStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*CallExpr).End\", Method, 0, \"\"},\n\t\t{\"(*CallExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*CaseClause).End\", Method, 0, \"\"},\n\t\t{\"(*CaseClause).Pos\", Method, 0, \"\"},\n\t\t{\"(*ChanType).End\", Method, 0, \"\"},\n\t\t{\"(*ChanType).Pos\", Method, 0, \"\"},\n\t\t{\"(*CommClause).End\", Method, 0, \"\"},\n\t\t{\"(*CommClause).Pos\", Method, 0, \"\"},\n\t\t{\"(*Comment).End\", Method, 0, \"\"},\n\t\t{\"(*Comment).Pos\", Method, 0, \"\"},\n\t\t{\"(*CommentGroup).End\", Method, 0, \"\"},\n\t\t{\"(*CommentGroup).Pos\", Method, 0, \"\"},\n\t\t{\"(*CommentGroup).Text\", Method, 0, \"\"},\n\t\t{\"(*CompositeLit).End\", Method, 0, \"\"},\n\t\t{\"(*CompositeLit).Pos\", Method, 0, \"\"},\n\t\t{\"(*DeclStmt).End\", Method, 0, \"\"},\n\t\t{\"(*DeclStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*DeferStmt).End\", Method, 0, \"\"},\n\t\t{\"(*DeferStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*Directive).End\", Method, 26, \"\"},\n\t\t{\"(*Directive).ParseArgs\", Method, 26, \"\"},\n\t\t{\"(*Directive).Pos\", Method, 26, \"\"},\n\t\t{\"(*Ellipsis).End\", Method, 0, \"\"},\n\t\t{\"(*Ellipsis).Pos\", Method, 0, \"\"},\n\t\t{\"(*EmptyStmt).End\", Method, 0, \"\"},\n\t\t{\"(*EmptyStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*ExprStmt).End\", Method, 0, \"\"},\n\t\t{\"(*ExprStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*Field).End\", Method, 0, \"\"},\n\t\t{\"(*Field).Pos\", Method, 0, \"\"},\n\t\t{\"(*FieldList).End\", Method, 0, \"\"},\n\t\t{\"(*FieldList).NumFields\", Method, 0, \"\"},\n\t\t{\"(*FieldList).Pos\", Method, 0, \"\"},\n\t\t{\"(*File).End\", Method, 0, \"\"},\n\t\t{\"(*File).Pos\", Method, 0, \"\"},\n\t\t{\"(*ForStmt).End\", Method, 0, \"\"},\n\t\t{\"(*ForStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*FuncDecl).End\", Method, 0, \"\"},\n\t\t{\"(*FuncDecl).Pos\", Method, 0, \"\"},\n\t\t{\"(*FuncLit).End\", Method, 0, \"\"},\n\t\t{\"(*FuncLit).Pos\", Method, 0, \"\"},\n\t\t{\"(*FuncType).End\", Method, 0, \"\"},\n\t\t{\"(*FuncType).Pos\", Method, 0, \"\"},\n\t\t{\"(*GenDecl).End\", Method, 0, \"\"},\n\t\t{\"(*GenDecl).Pos\", Method, 0, \"\"},\n\t\t{\"(*GoStmt).End\", Method, 0, \"\"},\n\t\t{\"(*GoStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*Ident).End\", Method, 0, \"\"},\n\t\t{\"(*Ident).IsExported\", Method, 0, \"\"},\n\t\t{\"(*Ident).Pos\", Method, 0, \"\"},\n\t\t{\"(*Ident).String\", Method, 0, \"\"},\n\t\t{\"(*IfStmt).End\", Method, 0, \"\"},\n\t\t{\"(*IfStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*ImportSpec).End\", Method, 0, \"\"},\n\t\t{\"(*ImportSpec).Pos\", Method, 0, \"\"},\n\t\t{\"(*IncDecStmt).End\", Method, 0, \"\"},\n\t\t{\"(*IncDecStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*IndexExpr).End\", Method, 0, \"\"},\n\t\t{\"(*IndexExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*IndexListExpr).End\", Method, 18, \"\"},\n\t\t{\"(*IndexListExpr).Pos\", Method, 18, \"\"},\n\t\t{\"(*InterfaceType).End\", Method, 0, \"\"},\n\t\t{\"(*InterfaceType).Pos\", Method, 0, \"\"},\n\t\t{\"(*KeyValueExpr).End\", Method, 0, \"\"},\n\t\t{\"(*KeyValueExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*LabeledStmt).End\", Method, 0, \"\"},\n\t\t{\"(*LabeledStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*MapType).End\", Method, 0, \"\"},\n\t\t{\"(*MapType).Pos\", Method, 0, \"\"},\n\t\t{\"(*Object).Pos\", Method, 0, \"\"},\n\t\t{\"(*Package).End\", Method, 0, \"\"},\n\t\t{\"(*Package).Pos\", Method, 0, \"\"},\n\t\t{\"(*ParenExpr).End\", Method, 0, \"\"},\n\t\t{\"(*ParenExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*RangeStmt).End\", Method, 0, \"\"},\n\t\t{\"(*RangeStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*ReturnStmt).End\", Method, 0, \"\"},\n\t\t{\"(*ReturnStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*Scope).Insert\", Method, 0, \"\"},\n\t\t{\"(*Scope).Lookup\", Method, 0, \"\"},\n\t\t{\"(*Scope).String\", Method, 0, \"\"},\n\t\t{\"(*SelectStmt).End\", Method, 0, \"\"},\n\t\t{\"(*SelectStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*SelectorExpr).End\", Method, 0, \"\"},\n\t\t{\"(*SelectorExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*SendStmt).End\", Method, 0, \"\"},\n\t\t{\"(*SendStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*SliceExpr).End\", Method, 0, \"\"},\n\t\t{\"(*SliceExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*StarExpr).End\", Method, 0, \"\"},\n\t\t{\"(*StarExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*StructType).End\", Method, 0, \"\"},\n\t\t{\"(*StructType).Pos\", Method, 0, \"\"},\n\t\t{\"(*SwitchStmt).End\", Method, 0, \"\"},\n\t\t{\"(*SwitchStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*TypeAssertExpr).End\", Method, 0, \"\"},\n\t\t{\"(*TypeAssertExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*TypeSpec).End\", Method, 0, \"\"},\n\t\t{\"(*TypeSpec).Pos\", Method, 0, \"\"},\n\t\t{\"(*TypeSwitchStmt).End\", Method, 0, \"\"},\n\t\t{\"(*TypeSwitchStmt).Pos\", Method, 0, \"\"},\n\t\t{\"(*UnaryExpr).End\", Method, 0, \"\"},\n\t\t{\"(*UnaryExpr).Pos\", Method, 0, \"\"},\n\t\t{\"(*ValueSpec).End\", Method, 0, \"\"},\n\t\t{\"(*ValueSpec).Pos\", Method, 0, \"\"},\n\t\t{\"(CommentMap).Comments\", Method, 1, \"\"},\n\t\t{\"(CommentMap).Filter\", Method, 1, \"\"},\n\t\t{\"(CommentMap).String\", Method, 1, \"\"},\n\t\t{\"(CommentMap).Update\", Method, 1, \"\"},\n\t\t{\"(Decl).End\", Method, 0, \"\"},\n\t\t{\"(Decl).Pos\", Method, 0, \"\"},\n\t\t{\"(Expr).End\", Method, 0, \"\"},\n\t\t{\"(Expr).Pos\", Method, 0, \"\"},\n\t\t{\"(Node).End\", Method, 0, \"\"},\n\t\t{\"(Node).Pos\", Method, 0, \"\"},\n\t\t{\"(ObjKind).String\", Method, 0, \"\"},\n\t\t{\"(Spec).End\", Method, 0, \"\"},\n\t\t{\"(Spec).Pos\", Method, 0, \"\"},\n\t\t{\"(Stmt).End\", Method, 0, \"\"},\n\t\t{\"(Stmt).Pos\", Method, 0, \"\"},\n\t\t{\"(Visitor).Visit\", Method, 0, \"\"},\n\t\t{\"ArrayType\", Type, 0, \"\"},\n\t\t{\"ArrayType.Elt\", Field, 0, \"\"},\n\t\t{\"ArrayType.Lbrack\", Field, 0, \"\"},\n\t\t{\"ArrayType.Len\", Field, 0, \"\"},\n\t\t{\"AssignStmt\", Type, 0, \"\"},\n\t\t{\"AssignStmt.Lhs\", Field, 0, \"\"},\n\t\t{\"AssignStmt.Rhs\", Field, 0, \"\"},\n\t\t{\"AssignStmt.Tok\", Field, 0, \"\"},\n\t\t{\"AssignStmt.TokPos\", Field, 0, \"\"},\n\t\t{\"Bad\", Const, 0, \"\"},\n\t\t{\"BadDecl\", Type, 0, \"\"},\n\t\t{\"BadDecl.From\", Field, 0, \"\"},\n\t\t{\"BadDecl.To\", Field, 0, \"\"},\n\t\t{\"BadExpr\", Type, 0, \"\"},\n\t\t{\"BadExpr.From\", Field, 0, \"\"},\n\t\t{\"BadExpr.To\", Field, 0, \"\"},\n\t\t{\"BadStmt\", Type, 0, \"\"},\n\t\t{\"BadStmt.From\", Field, 0, \"\"},\n\t\t{\"BadStmt.To\", Field, 0, \"\"},\n\t\t{\"BasicLit\", Type, 0, \"\"},\n\t\t{\"BasicLit.Kind\", Field, 0, \"\"},\n\t\t{\"BasicLit.Value\", Field, 0, \"\"},\n\t\t{\"BasicLit.ValueEnd\", Field, 26, \"\"},\n\t\t{\"BasicLit.ValuePos\", Field, 0, \"\"},\n\t\t{\"BinaryExpr\", Type, 0, \"\"},\n\t\t{\"BinaryExpr.Op\", Field, 0, \"\"},\n\t\t{\"BinaryExpr.OpPos\", Field, 0, \"\"},\n\t\t{\"BinaryExpr.X\", Field, 0, \"\"},\n\t\t{\"BinaryExpr.Y\", Field, 0, \"\"},\n\t\t{\"BlockStmt\", Type, 0, \"\"},\n\t\t{\"BlockStmt.Lbrace\", Field, 0, \"\"},\n\t\t{\"BlockStmt.List\", Field, 0, \"\"},\n\t\t{\"BlockStmt.Rbrace\", Field, 0, \"\"},\n\t\t{\"BranchStmt\", Type, 0, \"\"},\n\t\t{\"BranchStmt.Label\", Field, 0, \"\"},\n\t\t{\"BranchStmt.Tok\", Field, 0, \"\"},\n\t\t{\"BranchStmt.TokPos\", Field, 0, \"\"},\n\t\t{\"CallExpr\", Type, 0, \"\"},\n\t\t{\"CallExpr.Args\", Field, 0, \"\"},\n\t\t{\"CallExpr.Ellipsis\", Field, 0, \"\"},\n\t\t{\"CallExpr.Fun\", Field, 0, \"\"},\n\t\t{\"CallExpr.Lparen\", Field, 0, \"\"},\n\t\t{\"CallExpr.Rparen\", Field, 0, \"\"},\n\t\t{\"CaseClause\", Type, 0, \"\"},\n\t\t{\"CaseClause.Body\", Field, 0, \"\"},\n\t\t{\"CaseClause.Case\", Field, 0, \"\"},\n\t\t{\"CaseClause.Colon\", Field, 0, \"\"},\n\t\t{\"CaseClause.List\", Field, 0, \"\"},\n\t\t{\"ChanDir\", Type, 0, \"\"},\n\t\t{\"ChanType\", Type, 0, \"\"},\n\t\t{\"ChanType.Arrow\", Field, 1, \"\"},\n\t\t{\"ChanType.Begin\", Field, 0, \"\"},\n\t\t{\"ChanType.Dir\", Field, 0, \"\"},\n\t\t{\"ChanType.Value\", Field, 0, \"\"},\n\t\t{\"CommClause\", Type, 0, \"\"},\n\t\t{\"CommClause.Body\", Field, 0, \"\"},\n\t\t{\"CommClause.Case\", Field, 0, \"\"},\n\t\t{\"CommClause.Colon\", Field, 0, \"\"},\n\t\t{\"CommClause.Comm\", Field, 0, \"\"},\n\t\t{\"Comment\", Type, 0, \"\"},\n\t\t{\"Comment.Slash\", Field, 0, \"\"},\n\t\t{\"Comment.Text\", Field, 0, \"\"},\n\t\t{\"CommentGroup\", Type, 0, \"\"},\n\t\t{\"CommentGroup.List\", Field, 0, \"\"},\n\t\t{\"CommentMap\", Type, 1, \"\"},\n\t\t{\"CompositeLit\", Type, 0, \"\"},\n\t\t{\"CompositeLit.Elts\", Field, 0, \"\"},\n\t\t{\"CompositeLit.Incomplete\", Field, 11, \"\"},\n\t\t{\"CompositeLit.Lbrace\", Field, 0, \"\"},\n\t\t{\"CompositeLit.Rbrace\", Field, 0, \"\"},\n\t\t{\"CompositeLit.Type\", Field, 0, \"\"},\n\t\t{\"Con\", Const, 0, \"\"},\n\t\t{\"DeclStmt\", Type, 0, \"\"},\n\t\t{\"DeclStmt.Decl\", Field, 0, \"\"},\n\t\t{\"DeferStmt\", Type, 0, \"\"},\n\t\t{\"DeferStmt.Call\", Field, 0, \"\"},\n\t\t{\"DeferStmt.Defer\", Field, 0, \"\"},\n\t\t{\"Directive\", Type, 26, \"\"},\n\t\t{\"Directive.Args\", Field, 26, \"\"},\n\t\t{\"Directive.ArgsPos\", Field, 26, \"\"},\n\t\t{\"Directive.Name\", Field, 26, \"\"},\n\t\t{\"Directive.Slash\", Field, 26, \"\"},\n\t\t{\"Directive.Tool\", Field, 26, \"\"},\n\t\t{\"DirectiveArg\", Type, 26, \"\"},\n\t\t{\"DirectiveArg.Arg\", Field, 26, \"\"},\n\t\t{\"DirectiveArg.Pos\", Field, 26, \"\"},\n\t\t{\"Ellipsis\", Type, 0, \"\"},\n\t\t{\"Ellipsis.Ellipsis\", Field, 0, \"\"},\n\t\t{\"Ellipsis.Elt\", Field, 0, \"\"},\n\t\t{\"EmptyStmt\", Type, 0, \"\"},\n\t\t{\"EmptyStmt.Implicit\", Field, 5, \"\"},\n\t\t{\"EmptyStmt.Semicolon\", Field, 0, \"\"},\n\t\t{\"ExprStmt\", Type, 0, \"\"},\n\t\t{\"ExprStmt.X\", Field, 0, \"\"},\n\t\t{\"Field\", Type, 0, \"\"},\n\t\t{\"Field.Comment\", Field, 0, \"\"},\n\t\t{\"Field.Doc\", Field, 0, \"\"},\n\t\t{\"Field.Names\", Field, 0, \"\"},\n\t\t{\"Field.Tag\", Field, 0, \"\"},\n\t\t{\"Field.Type\", Field, 0, \"\"},\n\t\t{\"FieldFilter\", Type, 0, \"\"},\n\t\t{\"FieldList\", Type, 0, \"\"},\n\t\t{\"FieldList.Closing\", Field, 0, \"\"},\n\t\t{\"FieldList.List\", Field, 0, \"\"},\n\t\t{\"FieldList.Opening\", Field, 0, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"File.Comments\", Field, 0, \"\"},\n\t\t{\"File.Decls\", Field, 0, \"\"},\n\t\t{\"File.Doc\", Field, 0, \"\"},\n\t\t{\"File.FileEnd\", Field, 20, \"\"},\n\t\t{\"File.FileStart\", Field, 20, \"\"},\n\t\t{\"File.GoVersion\", Field, 21, \"\"},\n\t\t{\"File.Imports\", Field, 0, \"\"},\n\t\t{\"File.Name\", Field, 0, \"\"},\n\t\t{\"File.Package\", Field, 0, \"\"},\n\t\t{\"File.Scope\", Field, 0, \"\"},\n\t\t{\"File.Unresolved\", Field, 0, \"\"},\n\t\t{\"FileExports\", Func, 0, \"func(src *File) bool\"},\n\t\t{\"Filter\", Type, 0, \"\"},\n\t\t{\"FilterDecl\", Func, 0, \"func(decl Decl, f Filter) bool\"},\n\t\t{\"FilterFile\", Func, 0, \"func(src *File, f Filter) bool\"},\n\t\t{\"FilterFuncDuplicates\", Const, 0, \"\"},\n\t\t{\"FilterImportDuplicates\", Const, 0, \"\"},\n\t\t{\"FilterPackage\", Func, 0, \"func(pkg *Package, f Filter) bool\"},\n\t\t{\"FilterUnassociatedComments\", Const, 0, \"\"},\n\t\t{\"ForStmt\", Type, 0, \"\"},\n\t\t{\"ForStmt.Body\", Field, 0, \"\"},\n\t\t{\"ForStmt.Cond\", Field, 0, \"\"},\n\t\t{\"ForStmt.For\", Field, 0, \"\"},\n\t\t{\"ForStmt.Init\", Field, 0, \"\"},\n\t\t{\"ForStmt.Post\", Field, 0, \"\"},\n\t\t{\"Fprint\", Func, 0, \"func(w io.Writer, fset *token.FileSet, x any, f FieldFilter) error\"},\n\t\t{\"Fun\", Const, 0, \"\"},\n\t\t{\"FuncDecl\", Type, 0, \"\"},\n\t\t{\"FuncDecl.Body\", Field, 0, \"\"},\n\t\t{\"FuncDecl.Doc\", Field, 0, \"\"},\n\t\t{\"FuncDecl.Name\", Field, 0, \"\"},\n\t\t{\"FuncDecl.Recv\", Field, 0, \"\"},\n\t\t{\"FuncDecl.Type\", Field, 0, \"\"},\n\t\t{\"FuncLit\", Type, 0, \"\"},\n\t\t{\"FuncLit.Body\", Field, 0, \"\"},\n\t\t{\"FuncLit.Type\", Field, 0, \"\"},\n\t\t{\"FuncType\", Type, 0, \"\"},\n\t\t{\"FuncType.Func\", Field, 0, \"\"},\n\t\t{\"FuncType.Params\", Field, 0, \"\"},\n\t\t{\"FuncType.Results\", Field, 0, \"\"},\n\t\t{\"FuncType.TypeParams\", Field, 18, \"\"},\n\t\t{\"GenDecl\", Type, 0, \"\"},\n\t\t{\"GenDecl.Doc\", Field, 0, \"\"},\n\t\t{\"GenDecl.Lparen\", Field, 0, \"\"},\n\t\t{\"GenDecl.Rparen\", Field, 0, \"\"},\n\t\t{\"GenDecl.Specs\", Field, 0, \"\"},\n\t\t{\"GenDecl.Tok\", Field, 0, \"\"},\n\t\t{\"GenDecl.TokPos\", Field, 0, \"\"},\n\t\t{\"GoStmt\", Type, 0, \"\"},\n\t\t{\"GoStmt.Call\", Field, 0, \"\"},\n\t\t{\"GoStmt.Go\", Field, 0, \"\"},\n\t\t{\"Ident\", Type, 0, \"\"},\n\t\t{\"Ident.Name\", Field, 0, \"\"},\n\t\t{\"Ident.NamePos\", Field, 0, \"\"},\n\t\t{\"Ident.Obj\", Field, 0, \"\"},\n\t\t{\"IfStmt\", Type, 0, \"\"},\n\t\t{\"IfStmt.Body\", Field, 0, \"\"},\n\t\t{\"IfStmt.Cond\", Field, 0, \"\"},\n\t\t{\"IfStmt.Else\", Field, 0, \"\"},\n\t\t{\"IfStmt.If\", Field, 0, \"\"},\n\t\t{\"IfStmt.Init\", Field, 0, \"\"},\n\t\t{\"ImportSpec\", Type, 0, \"\"},\n\t\t{\"ImportSpec.Comment\", Field, 0, \"\"},\n\t\t{\"ImportSpec.Doc\", Field, 0, \"\"},\n\t\t{\"ImportSpec.EndPos\", Field, 0, \"\"},\n\t\t{\"ImportSpec.Name\", Field, 0, \"\"},\n\t\t{\"ImportSpec.Path\", Field, 0, \"\"},\n\t\t{\"Importer\", Type, 0, \"\"},\n\t\t{\"IncDecStmt\", Type, 0, \"\"},\n\t\t{\"IncDecStmt.Tok\", Field, 0, \"\"},\n\t\t{\"IncDecStmt.TokPos\", Field, 0, \"\"},\n\t\t{\"IncDecStmt.X\", Field, 0, \"\"},\n\t\t{\"IndexExpr\", Type, 0, \"\"},\n\t\t{\"IndexExpr.Index\", Field, 0, \"\"},\n\t\t{\"IndexExpr.Lbrack\", Field, 0, \"\"},\n\t\t{\"IndexExpr.Rbrack\", Field, 0, \"\"},\n\t\t{\"IndexExpr.X\", Field, 0, \"\"},\n\t\t{\"IndexListExpr\", Type, 18, \"\"},\n\t\t{\"IndexListExpr.Indices\", Field, 18, \"\"},\n\t\t{\"IndexListExpr.Lbrack\", Field, 18, \"\"},\n\t\t{\"IndexListExpr.Rbrack\", Field, 18, \"\"},\n\t\t{\"IndexListExpr.X\", Field, 18, \"\"},\n\t\t{\"Inspect\", Func, 0, \"func(node Node, f func(Node) bool)\"},\n\t\t{\"InterfaceType\", Type, 0, \"\"},\n\t\t{\"InterfaceType.Incomplete\", Field, 0, \"\"},\n\t\t{\"InterfaceType.Interface\", Field, 0, \"\"},\n\t\t{\"InterfaceType.Methods\", Field, 0, \"\"},\n\t\t{\"IsExported\", Func, 0, \"func(name string) bool\"},\n\t\t{\"IsGenerated\", Func, 21, \"func(file *File) bool\"},\n\t\t{\"KeyValueExpr\", Type, 0, \"\"},\n\t\t{\"KeyValueExpr.Colon\", Field, 0, \"\"},\n\t\t{\"KeyValueExpr.Key\", Field, 0, \"\"},\n\t\t{\"KeyValueExpr.Value\", Field, 0, \"\"},\n\t\t{\"LabeledStmt\", Type, 0, \"\"},\n\t\t{\"LabeledStmt.Colon\", Field, 0, \"\"},\n\t\t{\"LabeledStmt.Label\", Field, 0, \"\"},\n\t\t{\"LabeledStmt.Stmt\", Field, 0, \"\"},\n\t\t{\"Lbl\", Const, 0, \"\"},\n\t\t{\"MapType\", Type, 0, \"\"},\n\t\t{\"MapType.Key\", Field, 0, \"\"},\n\t\t{\"MapType.Map\", Field, 0, \"\"},\n\t\t{\"MapType.Value\", Field, 0, \"\"},\n\t\t{\"MergeMode\", Type, 0, \"\"},\n\t\t{\"MergePackageFiles\", Func, 0, \"func(pkg *Package, mode MergeMode) *File\"},\n\t\t{\"NewCommentMap\", Func, 1, \"func(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap\"},\n\t\t{\"NewIdent\", Func, 0, \"func(name string) *Ident\"},\n\t\t{\"NewObj\", Func, 0, \"func(kind ObjKind, name string) *Object\"},\n\t\t{\"NewPackage\", Func, 0, \"func(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error)\"},\n\t\t{\"NewScope\", Func, 0, \"func(outer *Scope) *Scope\"},\n\t\t{\"Node\", Type, 0, \"\"},\n\t\t{\"NotNilFilter\", Func, 0, \"func(_ string, v reflect.Value) bool\"},\n\t\t{\"ObjKind\", Type, 0, \"\"},\n\t\t{\"Object\", Type, 0, \"\"},\n\t\t{\"Object.Data\", Field, 0, \"\"},\n\t\t{\"Object.Decl\", Field, 0, \"\"},\n\t\t{\"Object.Kind\", Field, 0, \"\"},\n\t\t{\"Object.Name\", Field, 0, \"\"},\n\t\t{\"Object.Type\", Field, 0, \"\"},\n\t\t{\"Package\", Type, 0, \"\"},\n\t\t{\"Package.Files\", Field, 0, \"\"},\n\t\t{\"Package.Imports\", Field, 0, \"\"},\n\t\t{\"Package.Name\", Field, 0, \"\"},\n\t\t{\"Package.Scope\", Field, 0, \"\"},\n\t\t{\"PackageExports\", Func, 0, \"func(pkg *Package) bool\"},\n\t\t{\"ParenExpr\", Type, 0, \"\"},\n\t\t{\"ParenExpr.Lparen\", Field, 0, \"\"},\n\t\t{\"ParenExpr.Rparen\", Field, 0, \"\"},\n\t\t{\"ParenExpr.X\", Field, 0, \"\"},\n\t\t{\"ParseDirective\", Func, 26, \"func(pos token.Pos, c string) (Directive, bool)\"},\n\t\t{\"Pkg\", Const, 0, \"\"},\n\t\t{\"Preorder\", Func, 23, \"func(root Node) iter.Seq[Node]\"},\n\t\t{\"PreorderStack\", Func, 25, \"func(root Node, stack []Node, f func(n Node, stack []Node) bool)\"},\n\t\t{\"Print\", Func, 0, \"func(fset *token.FileSet, x any) error\"},\n\t\t{\"RECV\", Const, 0, \"\"},\n\t\t{\"RangeStmt\", Type, 0, \"\"},\n\t\t{\"RangeStmt.Body\", Field, 0, \"\"},\n\t\t{\"RangeStmt.For\", Field, 0, \"\"},\n\t\t{\"RangeStmt.Key\", Field, 0, \"\"},\n\t\t{\"RangeStmt.Range\", Field, 20, \"\"},\n\t\t{\"RangeStmt.Tok\", Field, 0, \"\"},\n\t\t{\"RangeStmt.TokPos\", Field, 0, \"\"},\n\t\t{\"RangeStmt.Value\", Field, 0, \"\"},\n\t\t{\"RangeStmt.X\", Field, 0, \"\"},\n\t\t{\"ReturnStmt\", Type, 0, \"\"},\n\t\t{\"ReturnStmt.Results\", Field, 0, \"\"},\n\t\t{\"ReturnStmt.Return\", Field, 0, \"\"},\n\t\t{\"SEND\", Const, 0, \"\"},\n\t\t{\"Scope\", Type, 0, \"\"},\n\t\t{\"Scope.Objects\", Field, 0, \"\"},\n\t\t{\"Scope.Outer\", Field, 0, \"\"},\n\t\t{\"SelectStmt\", Type, 0, \"\"},\n\t\t{\"SelectStmt.Body\", Field, 0, \"\"},\n\t\t{\"SelectStmt.Select\", Field, 0, \"\"},\n\t\t{\"SelectorExpr\", Type, 0, \"\"},\n\t\t{\"SelectorExpr.Sel\", Field, 0, \"\"},\n\t\t{\"SelectorExpr.X\", Field, 0, \"\"},\n\t\t{\"SendStmt\", Type, 0, \"\"},\n\t\t{\"SendStmt.Arrow\", Field, 0, \"\"},\n\t\t{\"SendStmt.Chan\", Field, 0, \"\"},\n\t\t{\"SendStmt.Value\", Field, 0, \"\"},\n\t\t{\"SliceExpr\", Type, 0, \"\"},\n\t\t{\"SliceExpr.High\", Field, 0, \"\"},\n\t\t{\"SliceExpr.Lbrack\", Field, 0, \"\"},\n\t\t{\"SliceExpr.Low\", Field, 0, \"\"},\n\t\t{\"SliceExpr.Max\", Field, 2, \"\"},\n\t\t{\"SliceExpr.Rbrack\", Field, 0, \"\"},\n\t\t{\"SliceExpr.Slice3\", Field, 2, \"\"},\n\t\t{\"SliceExpr.X\", Field, 0, \"\"},\n\t\t{\"SortImports\", Func, 0, \"func(fset *token.FileSet, f *File)\"},\n\t\t{\"StarExpr\", Type, 0, \"\"},\n\t\t{\"StarExpr.Star\", Field, 0, \"\"},\n\t\t{\"StarExpr.X\", Field, 0, \"\"},\n\t\t{\"StructType\", Type, 0, \"\"},\n\t\t{\"StructType.Fields\", Field, 0, \"\"},\n\t\t{\"StructType.Incomplete\", Field, 0, \"\"},\n\t\t{\"StructType.Struct\", Field, 0, \"\"},\n\t\t{\"SwitchStmt\", Type, 0, \"\"},\n\t\t{\"SwitchStmt.Body\", Field, 0, \"\"},\n\t\t{\"SwitchStmt.Init\", Field, 0, \"\"},\n\t\t{\"SwitchStmt.Switch\", Field, 0, \"\"},\n\t\t{\"SwitchStmt.Tag\", Field, 0, \"\"},\n\t\t{\"Typ\", Const, 0, \"\"},\n\t\t{\"TypeAssertExpr\", Type, 0, \"\"},\n\t\t{\"TypeAssertExpr.Lparen\", Field, 2, \"\"},\n\t\t{\"TypeAssertExpr.Rparen\", Field, 2, \"\"},\n\t\t{\"TypeAssertExpr.Type\", Field, 0, \"\"},\n\t\t{\"TypeAssertExpr.X\", Field, 0, \"\"},\n\t\t{\"TypeSpec\", Type, 0, \"\"},\n\t\t{\"TypeSpec.Assign\", Field, 9, \"\"},\n\t\t{\"TypeSpec.Comment\", Field, 0, \"\"},\n\t\t{\"TypeSpec.Doc\", Field, 0, \"\"},\n\t\t{\"TypeSpec.Name\", Field, 0, \"\"},\n\t\t{\"TypeSpec.Type\", Field, 0, \"\"},\n\t\t{\"TypeSpec.TypeParams\", Field, 18, \"\"},\n\t\t{\"TypeSwitchStmt\", Type, 0, \"\"},\n\t\t{\"TypeSwitchStmt.Assign\", Field, 0, \"\"},\n\t\t{\"TypeSwitchStmt.Body\", Field, 0, \"\"},\n\t\t{\"TypeSwitchStmt.Init\", Field, 0, \"\"},\n\t\t{\"TypeSwitchStmt.Switch\", Field, 0, \"\"},\n\t\t{\"UnaryExpr\", Type, 0, \"\"},\n\t\t{\"UnaryExpr.Op\", Field, 0, \"\"},\n\t\t{\"UnaryExpr.OpPos\", Field, 0, \"\"},\n\t\t{\"UnaryExpr.X\", Field, 0, \"\"},\n\t\t{\"Unparen\", Func, 22, \"func(e Expr) Expr\"},\n\t\t{\"ValueSpec\", Type, 0, \"\"},\n\t\t{\"ValueSpec.Comment\", Field, 0, \"\"},\n\t\t{\"ValueSpec.Doc\", Field, 0, \"\"},\n\t\t{\"ValueSpec.Names\", Field, 0, \"\"},\n\t\t{\"ValueSpec.Type\", Field, 0, \"\"},\n\t\t{\"ValueSpec.Values\", Field, 0, \"\"},\n\t\t{\"Var\", Const, 0, \"\"},\n\t\t{\"Visitor\", Type, 0, \"\"},\n\t\t{\"Walk\", Func, 0, \"func(v Visitor, node Node)\"},\n\t},\n\t\"go/build\": {\n\t\t{\"(*Context).Import\", Method, 0, \"\"},\n\t\t{\"(*Context).ImportDir\", Method, 0, \"\"},\n\t\t{\"(*Context).MatchFile\", Method, 2, \"\"},\n\t\t{\"(*Context).SrcDirs\", Method, 0, \"\"},\n\t\t{\"(*MultiplePackageError).Error\", Method, 4, \"\"},\n\t\t{\"(*NoGoError).Error\", Method, 0, \"\"},\n\t\t{\"(*Package).IsCommand\", Method, 0, \"\"},\n\t\t{\"AllowBinary\", Const, 0, \"\"},\n\t\t{\"ArchChar\", Func, 0, \"func(goarch string) (string, error)\"},\n\t\t{\"Context\", Type, 0, \"\"},\n\t\t{\"Context.BuildTags\", Field, 0, \"\"},\n\t\t{\"Context.CgoEnabled\", Field, 0, \"\"},\n\t\t{\"Context.Compiler\", Field, 0, \"\"},\n\t\t{\"Context.Dir\", Field, 14, \"\"},\n\t\t{\"Context.GOARCH\", Field, 0, \"\"},\n\t\t{\"Context.GOOS\", Field, 0, \"\"},\n\t\t{\"Context.GOPATH\", Field, 0, \"\"},\n\t\t{\"Context.GOROOT\", Field, 0, \"\"},\n\t\t{\"Context.HasSubdir\", Field, 0, \"\"},\n\t\t{\"Context.InstallSuffix\", Field, 1, \"\"},\n\t\t{\"Context.IsAbsPath\", Field, 0, \"\"},\n\t\t{\"Context.IsDir\", Field, 0, \"\"},\n\t\t{\"Context.JoinPath\", Field, 0, \"\"},\n\t\t{\"Context.OpenFile\", Field, 0, \"\"},\n\t\t{\"Context.ReadDir\", Field, 0, \"\"},\n\t\t{\"Context.ReleaseTags\", Field, 1, \"\"},\n\t\t{\"Context.SplitPathList\", Field, 0, \"\"},\n\t\t{\"Context.ToolTags\", Field, 17, \"\"},\n\t\t{\"Context.UseAllFiles\", Field, 0, \"\"},\n\t\t{\"Default\", Var, 0, \"\"},\n\t\t{\"Directive\", Type, 21, \"\"},\n\t\t{\"Directive.Pos\", Field, 21, \"\"},\n\t\t{\"Directive.Text\", Field, 21, \"\"},\n\t\t{\"FindOnly\", Const, 0, \"\"},\n\t\t{\"IgnoreVendor\", Const, 6, \"\"},\n\t\t{\"Import\", Func, 0, \"func(path string, srcDir string, mode ImportMode) (*Package, error)\"},\n\t\t{\"ImportComment\", Const, 4, \"\"},\n\t\t{\"ImportDir\", Func, 0, \"func(dir string, mode ImportMode) (*Package, error)\"},\n\t\t{\"ImportMode\", Type, 0, \"\"},\n\t\t{\"IsLocalImport\", Func, 0, \"func(path string) bool\"},\n\t\t{\"MultiplePackageError\", Type, 4, \"\"},\n\t\t{\"MultiplePackageError.Dir\", Field, 4, \"\"},\n\t\t{\"MultiplePackageError.Files\", Field, 4, \"\"},\n\t\t{\"MultiplePackageError.Packages\", Field, 4, \"\"},\n\t\t{\"NoGoError\", Type, 0, \"\"},\n\t\t{\"NoGoError.Dir\", Field, 0, \"\"},\n\t\t{\"Package\", Type, 0, \"\"},\n\t\t{\"Package.AllTags\", Field, 2, \"\"},\n\t\t{\"Package.BinDir\", Field, 0, \"\"},\n\t\t{\"Package.BinaryOnly\", Field, 7, \"\"},\n\t\t{\"Package.CFiles\", Field, 0, \"\"},\n\t\t{\"Package.CXXFiles\", Field, 2, \"\"},\n\t\t{\"Package.CgoCFLAGS\", Field, 0, \"\"},\n\t\t{\"Package.CgoCPPFLAGS\", Field, 2, \"\"},\n\t\t{\"Package.CgoCXXFLAGS\", Field, 2, \"\"},\n\t\t{\"Package.CgoFFLAGS\", Field, 7, \"\"},\n\t\t{\"Package.CgoFiles\", Field, 0, \"\"},\n\t\t{\"Package.CgoLDFLAGS\", Field, 0, \"\"},\n\t\t{\"Package.CgoPkgConfig\", Field, 0, \"\"},\n\t\t{\"Package.ConflictDir\", Field, 2, \"\"},\n\t\t{\"Package.Dir\", Field, 0, \"\"},\n\t\t{\"Package.Directives\", Field, 21, \"\"},\n\t\t{\"Package.Doc\", Field, 0, \"\"},\n\t\t{\"Package.EmbedPatternPos\", Field, 16, \"\"},\n\t\t{\"Package.EmbedPatterns\", Field, 16, \"\"},\n\t\t{\"Package.FFiles\", Field, 7, \"\"},\n\t\t{\"Package.GoFiles\", Field, 0, \"\"},\n\t\t{\"Package.Goroot\", Field, 0, \"\"},\n\t\t{\"Package.HFiles\", Field, 0, \"\"},\n\t\t{\"Package.IgnoredGoFiles\", Field, 1, \"\"},\n\t\t{\"Package.IgnoredOtherFiles\", Field, 16, \"\"},\n\t\t{\"Package.ImportComment\", Field, 4, \"\"},\n\t\t{\"Package.ImportPath\", Field, 0, \"\"},\n\t\t{\"Package.ImportPos\", Field, 0, \"\"},\n\t\t{\"Package.Imports\", Field, 0, \"\"},\n\t\t{\"Package.InvalidGoFiles\", Field, 6, \"\"},\n\t\t{\"Package.MFiles\", Field, 3, \"\"},\n\t\t{\"Package.Name\", Field, 0, \"\"},\n\t\t{\"Package.PkgObj\", Field, 0, \"\"},\n\t\t{\"Package.PkgRoot\", Field, 0, \"\"},\n\t\t{\"Package.PkgTargetRoot\", Field, 5, \"\"},\n\t\t{\"Package.Root\", Field, 0, \"\"},\n\t\t{\"Package.SFiles\", Field, 0, \"\"},\n\t\t{\"Package.SrcRoot\", Field, 0, \"\"},\n\t\t{\"Package.SwigCXXFiles\", Field, 1, \"\"},\n\t\t{\"Package.SwigFiles\", Field, 1, \"\"},\n\t\t{\"Package.SysoFiles\", Field, 0, \"\"},\n\t\t{\"Package.TestDirectives\", Field, 21, \"\"},\n\t\t{\"Package.TestEmbedPatternPos\", Field, 16, \"\"},\n\t\t{\"Package.TestEmbedPatterns\", Field, 16, \"\"},\n\t\t{\"Package.TestGoFiles\", Field, 0, \"\"},\n\t\t{\"Package.TestImportPos\", Field, 0, \"\"},\n\t\t{\"Package.TestImports\", Field, 0, \"\"},\n\t\t{\"Package.XTestDirectives\", Field, 21, \"\"},\n\t\t{\"Package.XTestEmbedPatternPos\", Field, 16, \"\"},\n\t\t{\"Package.XTestEmbedPatterns\", Field, 16, \"\"},\n\t\t{\"Package.XTestGoFiles\", Field, 0, \"\"},\n\t\t{\"Package.XTestImportPos\", Field, 0, \"\"},\n\t\t{\"Package.XTestImports\", Field, 0, \"\"},\n\t\t{\"ToolDir\", Var, 0, \"\"},\n\t},\n\t\"go/build/constraint\": {\n\t\t{\"(*AndExpr).Eval\", Method, 16, \"\"},\n\t\t{\"(*AndExpr).String\", Method, 16, \"\"},\n\t\t{\"(*NotExpr).Eval\", Method, 16, \"\"},\n\t\t{\"(*NotExpr).String\", Method, 16, \"\"},\n\t\t{\"(*OrExpr).Eval\", Method, 16, \"\"},\n\t\t{\"(*OrExpr).String\", Method, 16, \"\"},\n\t\t{\"(*SyntaxError).Error\", Method, 16, \"\"},\n\t\t{\"(*TagExpr).Eval\", Method, 16, \"\"},\n\t\t{\"(*TagExpr).String\", Method, 16, \"\"},\n\t\t{\"(Expr).Eval\", Method, 16, \"\"},\n\t\t{\"(Expr).String\", Method, 16, \"\"},\n\t\t{\"AndExpr\", Type, 16, \"\"},\n\t\t{\"AndExpr.X\", Field, 16, \"\"},\n\t\t{\"AndExpr.Y\", Field, 16, \"\"},\n\t\t{\"GoVersion\", Func, 21, \"func(x Expr) string\"},\n\t\t{\"IsGoBuild\", Func, 16, \"func(line string) bool\"},\n\t\t{\"IsPlusBuild\", Func, 16, \"func(line string) bool\"},\n\t\t{\"NotExpr\", Type, 16, \"\"},\n\t\t{\"NotExpr.X\", Field, 16, \"\"},\n\t\t{\"OrExpr\", Type, 16, \"\"},\n\t\t{\"OrExpr.X\", Field, 16, \"\"},\n\t\t{\"OrExpr.Y\", Field, 16, \"\"},\n\t\t{\"Parse\", Func, 16, \"func(line string) (Expr, error)\"},\n\t\t{\"PlusBuildLines\", Func, 16, \"func(x Expr) ([]string, error)\"},\n\t\t{\"SyntaxError\", Type, 16, \"\"},\n\t\t{\"SyntaxError.Err\", Field, 16, \"\"},\n\t\t{\"SyntaxError.Offset\", Field, 16, \"\"},\n\t\t{\"TagExpr\", Type, 16, \"\"},\n\t\t{\"TagExpr.Tag\", Field, 16, \"\"},\n\t},\n\t\"go/constant\": {\n\t\t{\"(Kind).String\", Method, 18, \"\"},\n\t\t{\"(Value).ExactString\", Method, 6, \"\"},\n\t\t{\"(Value).Kind\", Method, 5, \"\"},\n\t\t{\"(Value).String\", Method, 5, \"\"},\n\t\t{\"BinaryOp\", Func, 5, \"func(x_ Value, op token.Token, y_ Value) Value\"},\n\t\t{\"BitLen\", Func, 5, \"func(x Value) int\"},\n\t\t{\"Bool\", Const, 5, \"\"},\n\t\t{\"BoolVal\", Func, 5, \"func(x Value) bool\"},\n\t\t{\"Bytes\", Func, 5, \"func(x Value) []byte\"},\n\t\t{\"Compare\", Func, 5, \"func(x_ Value, op token.Token, y_ Value) bool\"},\n\t\t{\"Complex\", Const, 5, \"\"},\n\t\t{\"Denom\", Func, 5, \"func(x Value) Value\"},\n\t\t{\"Float\", Const, 5, \"\"},\n\t\t{\"Float32Val\", Func, 5, \"func(x Value) (float32, bool)\"},\n\t\t{\"Float64Val\", Func, 5, \"func(x Value) (float64, bool)\"},\n\t\t{\"Imag\", Func, 5, \"func(x Value) Value\"},\n\t\t{\"Int\", Const, 5, \"\"},\n\t\t{\"Int64Val\", Func, 5, \"func(x Value) (int64, bool)\"},\n\t\t{\"Kind\", Type, 5, \"\"},\n\t\t{\"Make\", Func, 13, \"func(x any) Value\"},\n\t\t{\"MakeBool\", Func, 5, \"func(b bool) Value\"},\n\t\t{\"MakeFloat64\", Func, 5, \"func(x float64) Value\"},\n\t\t{\"MakeFromBytes\", Func, 5, \"func(bytes []byte) Value\"},\n\t\t{\"MakeFromLiteral\", Func, 5, \"func(lit string, tok token.Token, zero uint) Value\"},\n\t\t{\"MakeImag\", Func, 5, \"func(x Value) Value\"},\n\t\t{\"MakeInt64\", Func, 5, \"func(x int64) Value\"},\n\t\t{\"MakeString\", Func, 5, \"func(s string) Value\"},\n\t\t{\"MakeUint64\", Func, 5, \"func(x uint64) Value\"},\n\t\t{\"MakeUnknown\", Func, 5, \"func() Value\"},\n\t\t{\"Num\", Func, 5, \"func(x Value) Value\"},\n\t\t{\"Real\", Func, 5, \"func(x Value) Value\"},\n\t\t{\"Shift\", Func, 5, \"func(x Value, op token.Token, s uint) Value\"},\n\t\t{\"Sign\", Func, 5, \"func(x Value) int\"},\n\t\t{\"String\", Const, 5, \"\"},\n\t\t{\"StringVal\", Func, 5, \"func(x Value) string\"},\n\t\t{\"ToComplex\", Func, 6, \"func(x Value) Value\"},\n\t\t{\"ToFloat\", Func, 6, \"func(x Value) Value\"},\n\t\t{\"ToInt\", Func, 6, \"func(x Value) Value\"},\n\t\t{\"Uint64Val\", Func, 5, \"func(x Value) (uint64, bool)\"},\n\t\t{\"UnaryOp\", Func, 5, \"func(op token.Token, y Value, prec uint) Value\"},\n\t\t{\"Unknown\", Const, 5, \"\"},\n\t\t{\"Val\", Func, 13, \"func(x Value) any\"},\n\t},\n\t\"go/doc\": {\n\t\t{\"(*Package).Filter\", Method, 0, \"\"},\n\t\t{\"(*Package).HTML\", Method, 19, \"\"},\n\t\t{\"(*Package).Markdown\", Method, 19, \"\"},\n\t\t{\"(*Package).Parser\", Method, 19, \"\"},\n\t\t{\"(*Package).Printer\", Method, 19, \"\"},\n\t\t{\"(*Package).Synopsis\", Method, 19, \"\"},\n\t\t{\"(*Package).Text\", Method, 19, \"\"},\n\t\t{\"AllDecls\", Const, 0, \"\"},\n\t\t{\"AllMethods\", Const, 0, \"\"},\n\t\t{\"Example\", Type, 0, \"\"},\n\t\t{\"Example.Code\", Field, 0, \"\"},\n\t\t{\"Example.Comments\", Field, 0, \"\"},\n\t\t{\"Example.Doc\", Field, 0, \"\"},\n\t\t{\"Example.EmptyOutput\", Field, 1, \"\"},\n\t\t{\"Example.Name\", Field, 0, \"\"},\n\t\t{\"Example.Order\", Field, 1, \"\"},\n\t\t{\"Example.Output\", Field, 0, \"\"},\n\t\t{\"Example.Play\", Field, 1, \"\"},\n\t\t{\"Example.Suffix\", Field, 14, \"\"},\n\t\t{\"Example.Unordered\", Field, 7, \"\"},\n\t\t{\"Examples\", Func, 0, \"func(testFiles ...*ast.File) []*Example\"},\n\t\t{\"Filter\", Type, 0, \"\"},\n\t\t{\"Func\", Type, 0, \"\"},\n\t\t{\"Func.Decl\", Field, 0, \"\"},\n\t\t{\"Func.Doc\", Field, 0, \"\"},\n\t\t{\"Func.Examples\", Field, 14, \"\"},\n\t\t{\"Func.Level\", Field, 0, \"\"},\n\t\t{\"Func.Name\", Field, 0, \"\"},\n\t\t{\"Func.Orig\", Field, 0, \"\"},\n\t\t{\"Func.Recv\", Field, 0, \"\"},\n\t\t{\"IllegalPrefixes\", Var, 1, \"\"},\n\t\t{\"IsPredeclared\", Func, 8, \"func(s string) bool\"},\n\t\t{\"Mode\", Type, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(pkg *ast.Package, importPath string, mode Mode) *Package\"},\n\t\t{\"NewFromFiles\", Func, 14, \"func(fset *token.FileSet, files []*ast.File, importPath string, opts ...any) (*Package, error)\"},\n\t\t{\"Note\", Type, 1, \"\"},\n\t\t{\"Note.Body\", Field, 1, \"\"},\n\t\t{\"Note.End\", Field, 1, \"\"},\n\t\t{\"Note.Pos\", Field, 1, \"\"},\n\t\t{\"Note.UID\", Field, 1, \"\"},\n\t\t{\"Package\", Type, 0, \"\"},\n\t\t{\"Package.Bugs\", Field, 0, \"\"},\n\t\t{\"Package.Consts\", Field, 0, \"\"},\n\t\t{\"Package.Doc\", Field, 0, \"\"},\n\t\t{\"Package.Examples\", Field, 14, \"\"},\n\t\t{\"Package.Filenames\", Field, 0, \"\"},\n\t\t{\"Package.Funcs\", Field, 0, \"\"},\n\t\t{\"Package.ImportPath\", Field, 0, \"\"},\n\t\t{\"Package.Imports\", Field, 0, \"\"},\n\t\t{\"Package.Name\", Field, 0, \"\"},\n\t\t{\"Package.Notes\", Field, 1, \"\"},\n\t\t{\"Package.Types\", Field, 0, \"\"},\n\t\t{\"Package.Vars\", Field, 0, \"\"},\n\t\t{\"PreserveAST\", Const, 12, \"\"},\n\t\t{\"Synopsis\", Func, 0, \"func(text string) string\"},\n\t\t{\"ToHTML\", Func, 0, \"func(w io.Writer, text string, words map[string]string)\"},\n\t\t{\"ToText\", Func, 0, \"func(w io.Writer, text string, prefix string, codePrefix string, width int)\"},\n\t\t{\"Type\", Type, 0, \"\"},\n\t\t{\"Type.Consts\", Field, 0, \"\"},\n\t\t{\"Type.Decl\", Field, 0, \"\"},\n\t\t{\"Type.Doc\", Field, 0, \"\"},\n\t\t{\"Type.Examples\", Field, 14, \"\"},\n\t\t{\"Type.Funcs\", Field, 0, \"\"},\n\t\t{\"Type.Methods\", Field, 0, \"\"},\n\t\t{\"Type.Name\", Field, 0, \"\"},\n\t\t{\"Type.Vars\", Field, 0, \"\"},\n\t\t{\"Value\", Type, 0, \"\"},\n\t\t{\"Value.Decl\", Field, 0, \"\"},\n\t\t{\"Value.Doc\", Field, 0, \"\"},\n\t\t{\"Value.Names\", Field, 0, \"\"},\n\t},\n\t\"go/doc/comment\": {\n\t\t{\"(*DocLink).DefaultURL\", Method, 19, \"\"},\n\t\t{\"(*Heading).DefaultID\", Method, 19, \"\"},\n\t\t{\"(*List).BlankBefore\", Method, 19, \"\"},\n\t\t{\"(*List).BlankBetween\", Method, 19, \"\"},\n\t\t{\"(*Parser).Parse\", Method, 19, \"\"},\n\t\t{\"(*Printer).Comment\", Method, 19, \"\"},\n\t\t{\"(*Printer).HTML\", Method, 19, \"\"},\n\t\t{\"(*Printer).Markdown\", Method, 19, \"\"},\n\t\t{\"(*Printer).Text\", Method, 19, \"\"},\n\t\t{\"Code\", Type, 19, \"\"},\n\t\t{\"Code.Text\", Field, 19, \"\"},\n\t\t{\"DefaultLookupPackage\", Func, 19, \"func(name string) (importPath string, ok bool)\"},\n\t\t{\"Doc\", Type, 19, \"\"},\n\t\t{\"Doc.Content\", Field, 19, \"\"},\n\t\t{\"Doc.Links\", Field, 19, \"\"},\n\t\t{\"DocLink\", Type, 19, \"\"},\n\t\t{\"DocLink.ImportPath\", Field, 19, \"\"},\n\t\t{\"DocLink.Name\", Field, 19, \"\"},\n\t\t{\"DocLink.Recv\", Field, 19, \"\"},\n\t\t{\"DocLink.Text\", Field, 19, \"\"},\n\t\t{\"Heading\", Type, 19, \"\"},\n\t\t{\"Heading.Text\", Field, 19, \"\"},\n\t\t{\"Italic\", Type, 19, \"\"},\n\t\t{\"Link\", Type, 19, \"\"},\n\t\t{\"Link.Auto\", Field, 19, \"\"},\n\t\t{\"Link.Text\", Field, 19, \"\"},\n\t\t{\"Link.URL\", Field, 19, \"\"},\n\t\t{\"LinkDef\", Type, 19, \"\"},\n\t\t{\"LinkDef.Text\", Field, 19, \"\"},\n\t\t{\"LinkDef.URL\", Field, 19, \"\"},\n\t\t{\"LinkDef.Used\", Field, 19, \"\"},\n\t\t{\"List\", Type, 19, \"\"},\n\t\t{\"List.ForceBlankBefore\", Field, 19, \"\"},\n\t\t{\"List.ForceBlankBetween\", Field, 19, \"\"},\n\t\t{\"List.Items\", Field, 19, \"\"},\n\t\t{\"ListItem\", Type, 19, \"\"},\n\t\t{\"ListItem.Content\", Field, 19, \"\"},\n\t\t{\"ListItem.Number\", Field, 19, \"\"},\n\t\t{\"Paragraph\", Type, 19, \"\"},\n\t\t{\"Paragraph.Text\", Field, 19, \"\"},\n\t\t{\"Parser\", Type, 19, \"\"},\n\t\t{\"Parser.LookupPackage\", Field, 19, \"\"},\n\t\t{\"Parser.LookupSym\", Field, 19, \"\"},\n\t\t{\"Parser.Words\", Field, 19, \"\"},\n\t\t{\"Plain\", Type, 19, \"\"},\n\t\t{\"Printer\", Type, 19, \"\"},\n\t\t{\"Printer.DocLinkBaseURL\", Field, 19, \"\"},\n\t\t{\"Printer.DocLinkURL\", Field, 19, \"\"},\n\t\t{\"Printer.HeadingID\", Field, 19, \"\"},\n\t\t{\"Printer.HeadingLevel\", Field, 19, \"\"},\n\t\t{\"Printer.TextCodePrefix\", Field, 19, \"\"},\n\t\t{\"Printer.TextPrefix\", Field, 19, \"\"},\n\t\t{\"Printer.TextWidth\", Field, 19, \"\"},\n\t},\n\t\"go/format\": {\n\t\t{\"Node\", Func, 1, \"func(dst io.Writer, fset *token.FileSet, node any) error\"},\n\t\t{\"Source\", Func, 1, \"func(src []byte) ([]byte, error)\"},\n\t},\n\t\"go/importer\": {\n\t\t{\"Default\", Func, 5, \"func() types.Importer\"},\n\t\t{\"For\", Func, 5, \"func(compiler string, lookup Lookup) types.Importer\"},\n\t\t{\"ForCompiler\", Func, 12, \"func(fset *token.FileSet, compiler string, lookup Lookup) types.Importer\"},\n\t\t{\"Lookup\", Type, 5, \"\"},\n\t},\n\t\"go/parser\": {\n\t\t{\"AllErrors\", Const, 1, \"\"},\n\t\t{\"DeclarationErrors\", Const, 0, \"\"},\n\t\t{\"ImportsOnly\", Const, 0, \"\"},\n\t\t{\"Mode\", Type, 0, \"\"},\n\t\t{\"PackageClauseOnly\", Const, 0, \"\"},\n\t\t{\"ParseComments\", Const, 0, \"\"},\n\t\t{\"ParseDir\", Func, 0, \"func(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error)\"},\n\t\t{\"ParseExpr\", Func, 0, \"func(x string) (ast.Expr, error)\"},\n\t\t{\"ParseExprFrom\", Func, 5, \"func(fset *token.FileSet, filename string, src any, mode Mode) (expr ast.Expr, err error)\"},\n\t\t{\"ParseFile\", Func, 0, \"func(fset *token.FileSet, filename string, src any, mode Mode) (f *ast.File, err error)\"},\n\t\t{\"SkipObjectResolution\", Const, 17, \"\"},\n\t\t{\"SpuriousErrors\", Const, 0, \"\"},\n\t\t{\"Trace\", Const, 0, \"\"},\n\t},\n\t\"go/printer\": {\n\t\t{\"(*Config).Fprint\", Method, 0, \"\"},\n\t\t{\"CommentedNode\", Type, 0, \"\"},\n\t\t{\"CommentedNode.Comments\", Field, 0, \"\"},\n\t\t{\"CommentedNode.Node\", Field, 0, \"\"},\n\t\t{\"Config\", Type, 0, \"\"},\n\t\t{\"Config.Indent\", Field, 1, \"\"},\n\t\t{\"Config.Mode\", Field, 0, \"\"},\n\t\t{\"Config.Tabwidth\", Field, 0, \"\"},\n\t\t{\"Fprint\", Func, 0, \"func(output io.Writer, fset *token.FileSet, node any) error\"},\n\t\t{\"Mode\", Type, 0, \"\"},\n\t\t{\"RawFormat\", Const, 0, \"\"},\n\t\t{\"SourcePos\", Const, 0, \"\"},\n\t\t{\"TabIndent\", Const, 0, \"\"},\n\t\t{\"UseSpaces\", Const, 0, \"\"},\n\t},\n\t\"go/scanner\": {\n\t\t{\"(*ErrorList).Add\", Method, 0, \"\"},\n\t\t{\"(*ErrorList).RemoveMultiples\", Method, 0, \"\"},\n\t\t{\"(*ErrorList).Reset\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Init\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Scan\", Method, 0, \"\"},\n\t\t{\"(Error).Error\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Err\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Error\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Len\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Less\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Sort\", Method, 0, \"\"},\n\t\t{\"(ErrorList).Swap\", Method, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Msg\", Field, 0, \"\"},\n\t\t{\"Error.Pos\", Field, 0, \"\"},\n\t\t{\"ErrorHandler\", Type, 0, \"\"},\n\t\t{\"ErrorList\", Type, 0, \"\"},\n\t\t{\"Mode\", Type, 0, \"\"},\n\t\t{\"PrintError\", Func, 0, \"func(w io.Writer, err error)\"},\n\t\t{\"ScanComments\", Const, 0, \"\"},\n\t\t{\"Scanner\", Type, 0, \"\"},\n\t\t{\"Scanner.ErrorCount\", Field, 0, \"\"},\n\t},\n\t\"go/token\": {\n\t\t{\"(*File).AddLine\", Method, 0, \"\"},\n\t\t{\"(*File).AddLineColumnInfo\", Method, 11, \"\"},\n\t\t{\"(*File).AddLineInfo\", Method, 0, \"\"},\n\t\t{\"(*File).Base\", Method, 0, \"\"},\n\t\t{\"(*File).End\", Method, 26, \"\"},\n\t\t{\"(*File).Line\", Method, 0, \"\"},\n\t\t{\"(*File).LineCount\", Method, 0, \"\"},\n\t\t{\"(*File).LineStart\", Method, 12, \"\"},\n\t\t{\"(*File).Lines\", Method, 21, \"\"},\n\t\t{\"(*File).MergeLine\", Method, 2, \"\"},\n\t\t{\"(*File).Name\", Method, 0, \"\"},\n\t\t{\"(*File).Offset\", Method, 0, \"\"},\n\t\t{\"(*File).Pos\", Method, 0, \"\"},\n\t\t{\"(*File).Position\", Method, 0, \"\"},\n\t\t{\"(*File).PositionFor\", Method, 4, \"\"},\n\t\t{\"(*File).SetLines\", Method, 0, \"\"},\n\t\t{\"(*File).SetLinesForContent\", Method, 0, \"\"},\n\t\t{\"(*File).Size\", Method, 0, \"\"},\n\t\t{\"(*FileSet).AddExistingFiles\", Method, 25, \"\"},\n\t\t{\"(*FileSet).AddFile\", Method, 0, \"\"},\n\t\t{\"(*FileSet).Base\", Method, 0, \"\"},\n\t\t{\"(*FileSet).File\", Method, 0, \"\"},\n\t\t{\"(*FileSet).Iterate\", Method, 0, \"\"},\n\t\t{\"(*FileSet).Position\", Method, 0, \"\"},\n\t\t{\"(*FileSet).PositionFor\", Method, 4, \"\"},\n\t\t{\"(*FileSet).Read\", Method, 0, \"\"},\n\t\t{\"(*FileSet).RemoveFile\", Method, 20, \"\"},\n\t\t{\"(*FileSet).Write\", Method, 0, \"\"},\n\t\t{\"(*Position).IsValid\", Method, 0, \"\"},\n\t\t{\"(Pos).IsValid\", Method, 0, \"\"},\n\t\t{\"(Position).String\", Method, 0, \"\"},\n\t\t{\"(Token).IsKeyword\", Method, 0, \"\"},\n\t\t{\"(Token).IsLiteral\", Method, 0, \"\"},\n\t\t{\"(Token).IsOperator\", Method, 0, \"\"},\n\t\t{\"(Token).Precedence\", Method, 0, \"\"},\n\t\t{\"(Token).String\", Method, 0, \"\"},\n\t\t{\"ADD\", Const, 0, \"\"},\n\t\t{\"ADD_ASSIGN\", Const, 0, \"\"},\n\t\t{\"AND\", Const, 0, \"\"},\n\t\t{\"AND_ASSIGN\", Const, 0, \"\"},\n\t\t{\"AND_NOT\", Const, 0, \"\"},\n\t\t{\"AND_NOT_ASSIGN\", Const, 0, \"\"},\n\t\t{\"ARROW\", Const, 0, \"\"},\n\t\t{\"ASSIGN\", Const, 0, \"\"},\n\t\t{\"BREAK\", Const, 0, \"\"},\n\t\t{\"CASE\", Const, 0, \"\"},\n\t\t{\"CHAN\", Const, 0, \"\"},\n\t\t{\"CHAR\", Const, 0, \"\"},\n\t\t{\"COLON\", Const, 0, \"\"},\n\t\t{\"COMMA\", Const, 0, \"\"},\n\t\t{\"COMMENT\", Const, 0, \"\"},\n\t\t{\"CONST\", Const, 0, \"\"},\n\t\t{\"CONTINUE\", Const, 0, \"\"},\n\t\t{\"DEC\", Const, 0, \"\"},\n\t\t{\"DEFAULT\", Const, 0, \"\"},\n\t\t{\"DEFER\", Const, 0, \"\"},\n\t\t{\"DEFINE\", Const, 0, \"\"},\n\t\t{\"ELLIPSIS\", Const, 0, \"\"},\n\t\t{\"ELSE\", Const, 0, \"\"},\n\t\t{\"EOF\", Const, 0, \"\"},\n\t\t{\"EQL\", Const, 0, \"\"},\n\t\t{\"FALLTHROUGH\", Const, 0, \"\"},\n\t\t{\"FLOAT\", Const, 0, \"\"},\n\t\t{\"FOR\", Const, 0, \"\"},\n\t\t{\"FUNC\", Const, 0, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"FileSet\", Type, 0, \"\"},\n\t\t{\"GEQ\", Const, 0, \"\"},\n\t\t{\"GO\", Const, 0, \"\"},\n\t\t{\"GOTO\", Const, 0, \"\"},\n\t\t{\"GTR\", Const, 0, \"\"},\n\t\t{\"HighestPrec\", Const, 0, \"\"},\n\t\t{\"IDENT\", Const, 0, \"\"},\n\t\t{\"IF\", Const, 0, \"\"},\n\t\t{\"ILLEGAL\", Const, 0, \"\"},\n\t\t{\"IMAG\", Const, 0, \"\"},\n\t\t{\"IMPORT\", Const, 0, \"\"},\n\t\t{\"INC\", Const, 0, \"\"},\n\t\t{\"INT\", Const, 0, \"\"},\n\t\t{\"INTERFACE\", Const, 0, \"\"},\n\t\t{\"IsExported\", Func, 13, \"func(name string) bool\"},\n\t\t{\"IsIdentifier\", Func, 13, \"func(name string) bool\"},\n\t\t{\"IsKeyword\", Func, 13, \"func(name string) bool\"},\n\t\t{\"LAND\", Const, 0, \"\"},\n\t\t{\"LBRACE\", Const, 0, \"\"},\n\t\t{\"LBRACK\", Const, 0, \"\"},\n\t\t{\"LEQ\", Const, 0, \"\"},\n\t\t{\"LOR\", Const, 0, \"\"},\n\t\t{\"LPAREN\", Const, 0, \"\"},\n\t\t{\"LSS\", Const, 0, \"\"},\n\t\t{\"Lookup\", Func, 0, \"func(ident string) Token\"},\n\t\t{\"LowestPrec\", Const, 0, \"\"},\n\t\t{\"MAP\", Const, 0, \"\"},\n\t\t{\"MUL\", Const, 0, \"\"},\n\t\t{\"MUL_ASSIGN\", Const, 0, \"\"},\n\t\t{\"NEQ\", Const, 0, \"\"},\n\t\t{\"NOT\", Const, 0, \"\"},\n\t\t{\"NewFileSet\", Func, 0, \"func() *FileSet\"},\n\t\t{\"NoPos\", Const, 0, \"\"},\n\t\t{\"OR\", Const, 0, \"\"},\n\t\t{\"OR_ASSIGN\", Const, 0, \"\"},\n\t\t{\"PACKAGE\", Const, 0, \"\"},\n\t\t{\"PERIOD\", Const, 0, \"\"},\n\t\t{\"Pos\", Type, 0, \"\"},\n\t\t{\"Position\", Type, 0, \"\"},\n\t\t{\"Position.Column\", Field, 0, \"\"},\n\t\t{\"Position.Filename\", Field, 0, \"\"},\n\t\t{\"Position.Line\", Field, 0, \"\"},\n\t\t{\"Position.Offset\", Field, 0, \"\"},\n\t\t{\"QUO\", Const, 0, \"\"},\n\t\t{\"QUO_ASSIGN\", Const, 0, \"\"},\n\t\t{\"RANGE\", Const, 0, \"\"},\n\t\t{\"RBRACE\", Const, 0, \"\"},\n\t\t{\"RBRACK\", Const, 0, \"\"},\n\t\t{\"REM\", Const, 0, \"\"},\n\t\t{\"REM_ASSIGN\", Const, 0, \"\"},\n\t\t{\"RETURN\", Const, 0, \"\"},\n\t\t{\"RPAREN\", Const, 0, \"\"},\n\t\t{\"SELECT\", Const, 0, \"\"},\n\t\t{\"SEMICOLON\", Const, 0, \"\"},\n\t\t{\"SHL\", Const, 0, \"\"},\n\t\t{\"SHL_ASSIGN\", Const, 0, \"\"},\n\t\t{\"SHR\", Const, 0, \"\"},\n\t\t{\"SHR_ASSIGN\", Const, 0, \"\"},\n\t\t{\"STRING\", Const, 0, \"\"},\n\t\t{\"STRUCT\", Const, 0, \"\"},\n\t\t{\"SUB\", Const, 0, \"\"},\n\t\t{\"SUB_ASSIGN\", Const, 0, \"\"},\n\t\t{\"SWITCH\", Const, 0, \"\"},\n\t\t{\"TILDE\", Const, 18, \"\"},\n\t\t{\"TYPE\", Const, 0, \"\"},\n\t\t{\"Token\", Type, 0, \"\"},\n\t\t{\"UnaryPrec\", Const, 0, \"\"},\n\t\t{\"VAR\", Const, 0, \"\"},\n\t\t{\"XOR\", Const, 0, \"\"},\n\t\t{\"XOR_ASSIGN\", Const, 0, \"\"},\n\t},\n\t\"go/types\": {\n\t\t{\"(*Alias).Obj\", Method, 22, \"\"},\n\t\t{\"(*Alias).Origin\", Method, 23, \"\"},\n\t\t{\"(*Alias).Rhs\", Method, 23, \"\"},\n\t\t{\"(*Alias).SetTypeParams\", Method, 23, \"\"},\n\t\t{\"(*Alias).String\", Method, 22, \"\"},\n\t\t{\"(*Alias).TypeArgs\", Method, 23, \"\"},\n\t\t{\"(*Alias).TypeParams\", Method, 23, \"\"},\n\t\t{\"(*Alias).Underlying\", Method, 22, \"\"},\n\t\t{\"(*ArgumentError).Error\", Method, 18, \"\"},\n\t\t{\"(*ArgumentError).Unwrap\", Method, 18, \"\"},\n\t\t{\"(*Array).Elem\", Method, 5, \"\"},\n\t\t{\"(*Array).Len\", Method, 5, \"\"},\n\t\t{\"(*Array).String\", Method, 5, \"\"},\n\t\t{\"(*Array).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Basic).Info\", Method, 5, \"\"},\n\t\t{\"(*Basic).Kind\", Method, 5, \"\"},\n\t\t{\"(*Basic).Name\", Method, 5, \"\"},\n\t\t{\"(*Basic).String\", Method, 5, \"\"},\n\t\t{\"(*Basic).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Exported\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Id\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Name\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Parent\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Pos\", Method, 5, \"\"},\n\t\t{\"(*Builtin).String\", Method, 5, \"\"},\n\t\t{\"(*Builtin).Type\", Method, 5, \"\"},\n\t\t{\"(*Chan).Dir\", Method, 5, \"\"},\n\t\t{\"(*Chan).Elem\", Method, 5, \"\"},\n\t\t{\"(*Chan).String\", Method, 5, \"\"},\n\t\t{\"(*Chan).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Checker).Files\", Method, 5, \"\"},\n\t\t{\"(*Config).Check\", Method, 5, \"\"},\n\t\t{\"(*Const).Exported\", Method, 5, \"\"},\n\t\t{\"(*Const).Id\", Method, 5, \"\"},\n\t\t{\"(*Const).Name\", Method, 5, \"\"},\n\t\t{\"(*Const).Parent\", Method, 5, \"\"},\n\t\t{\"(*Const).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Const).Pos\", Method, 5, \"\"},\n\t\t{\"(*Const).String\", Method, 5, \"\"},\n\t\t{\"(*Const).Type\", Method, 5, \"\"},\n\t\t{\"(*Const).Val\", Method, 5, \"\"},\n\t\t{\"(*Func).Exported\", Method, 5, \"\"},\n\t\t{\"(*Func).FullName\", Method, 5, \"\"},\n\t\t{\"(*Func).Id\", Method, 5, \"\"},\n\t\t{\"(*Func).Name\", Method, 5, \"\"},\n\t\t{\"(*Func).Origin\", Method, 19, \"\"},\n\t\t{\"(*Func).Parent\", Method, 5, \"\"},\n\t\t{\"(*Func).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Func).Pos\", Method, 5, \"\"},\n\t\t{\"(*Func).Scope\", Method, 5, \"\"},\n\t\t{\"(*Func).Signature\", Method, 23, \"\"},\n\t\t{\"(*Func).String\", Method, 5, \"\"},\n\t\t{\"(*Func).Type\", Method, 5, \"\"},\n\t\t{\"(*Info).ObjectOf\", Method, 5, \"\"},\n\t\t{\"(*Info).PkgNameOf\", Method, 22, \"\"},\n\t\t{\"(*Info).TypeOf\", Method, 5, \"\"},\n\t\t{\"(*Initializer).String\", Method, 5, \"\"},\n\t\t{\"(*Interface).Complete\", Method, 5, \"\"},\n\t\t{\"(*Interface).Embedded\", Method, 5, \"\"},\n\t\t{\"(*Interface).EmbeddedType\", Method, 11, \"\"},\n\t\t{\"(*Interface).EmbeddedTypes\", Method, 24, \"\"},\n\t\t{\"(*Interface).Empty\", Method, 5, \"\"},\n\t\t{\"(*Interface).ExplicitMethod\", Method, 5, \"\"},\n\t\t{\"(*Interface).ExplicitMethods\", Method, 24, \"\"},\n\t\t{\"(*Interface).IsComparable\", Method, 18, \"\"},\n\t\t{\"(*Interface).IsImplicit\", Method, 18, \"\"},\n\t\t{\"(*Interface).IsMethodSet\", Method, 18, \"\"},\n\t\t{\"(*Interface).MarkImplicit\", Method, 18, \"\"},\n\t\t{\"(*Interface).Method\", Method, 5, \"\"},\n\t\t{\"(*Interface).Methods\", Method, 24, \"\"},\n\t\t{\"(*Interface).NumEmbeddeds\", Method, 5, \"\"},\n\t\t{\"(*Interface).NumExplicitMethods\", Method, 5, \"\"},\n\t\t{\"(*Interface).NumMethods\", Method, 5, \"\"},\n\t\t{\"(*Interface).String\", Method, 5, \"\"},\n\t\t{\"(*Interface).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Label).Exported\", Method, 5, \"\"},\n\t\t{\"(*Label).Id\", Method, 5, \"\"},\n\t\t{\"(*Label).Name\", Method, 5, \"\"},\n\t\t{\"(*Label).Parent\", Method, 5, \"\"},\n\t\t{\"(*Label).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Label).Pos\", Method, 5, \"\"},\n\t\t{\"(*Label).String\", Method, 5, \"\"},\n\t\t{\"(*Label).Type\", Method, 5, \"\"},\n\t\t{\"(*Map).Elem\", Method, 5, \"\"},\n\t\t{\"(*Map).Key\", Method, 5, \"\"},\n\t\t{\"(*Map).String\", Method, 5, \"\"},\n\t\t{\"(*Map).Underlying\", Method, 5, \"\"},\n\t\t{\"(*MethodSet).At\", Method, 5, \"\"},\n\t\t{\"(*MethodSet).Len\", Method, 5, \"\"},\n\t\t{\"(*MethodSet).Lookup\", Method, 5, \"\"},\n\t\t{\"(*MethodSet).Methods\", Method, 24, \"\"},\n\t\t{\"(*MethodSet).String\", Method, 5, \"\"},\n\t\t{\"(*Named).AddMethod\", Method, 5, \"\"},\n\t\t{\"(*Named).Method\", Method, 5, \"\"},\n\t\t{\"(*Named).Methods\", Method, 24, \"\"},\n\t\t{\"(*Named).NumMethods\", Method, 5, \"\"},\n\t\t{\"(*Named).Obj\", Method, 5, \"\"},\n\t\t{\"(*Named).Origin\", Method, 18, \"\"},\n\t\t{\"(*Named).SetTypeParams\", Method, 18, \"\"},\n\t\t{\"(*Named).SetUnderlying\", Method, 5, \"\"},\n\t\t{\"(*Named).String\", Method, 5, \"\"},\n\t\t{\"(*Named).TypeArgs\", Method, 18, \"\"},\n\t\t{\"(*Named).TypeParams\", Method, 18, \"\"},\n\t\t{\"(*Named).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Nil).Exported\", Method, 5, \"\"},\n\t\t{\"(*Nil).Id\", Method, 5, \"\"},\n\t\t{\"(*Nil).Name\", Method, 5, \"\"},\n\t\t{\"(*Nil).Parent\", Method, 5, \"\"},\n\t\t{\"(*Nil).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Nil).Pos\", Method, 5, \"\"},\n\t\t{\"(*Nil).String\", Method, 5, \"\"},\n\t\t{\"(*Nil).Type\", Method, 5, \"\"},\n\t\t{\"(*Package).Complete\", Method, 5, \"\"},\n\t\t{\"(*Package).GoVersion\", Method, 21, \"\"},\n\t\t{\"(*Package).Imports\", Method, 5, \"\"},\n\t\t{\"(*Package).MarkComplete\", Method, 5, \"\"},\n\t\t{\"(*Package).Name\", Method, 5, \"\"},\n\t\t{\"(*Package).Path\", Method, 5, \"\"},\n\t\t{\"(*Package).Scope\", Method, 5, \"\"},\n\t\t{\"(*Package).SetImports\", Method, 5, \"\"},\n\t\t{\"(*Package).SetName\", Method, 6, \"\"},\n\t\t{\"(*Package).String\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Exported\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Id\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Imported\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Name\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Parent\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Pkg\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Pos\", Method, 5, \"\"},\n\t\t{\"(*PkgName).String\", Method, 5, \"\"},\n\t\t{\"(*PkgName).Type\", Method, 5, \"\"},\n\t\t{\"(*Pointer).Elem\", Method, 5, \"\"},\n\t\t{\"(*Pointer).String\", Method, 5, \"\"},\n\t\t{\"(*Pointer).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Scope).Child\", Method, 5, \"\"},\n\t\t{\"(*Scope).Children\", Method, 24, \"\"},\n\t\t{\"(*Scope).Contains\", Method, 5, \"\"},\n\t\t{\"(*Scope).End\", Method, 5, \"\"},\n\t\t{\"(*Scope).Innermost\", Method, 5, \"\"},\n\t\t{\"(*Scope).Insert\", Method, 5, \"\"},\n\t\t{\"(*Scope).Len\", Method, 5, \"\"},\n\t\t{\"(*Scope).Lookup\", Method, 5, \"\"},\n\t\t{\"(*Scope).LookupParent\", Method, 5, \"\"},\n\t\t{\"(*Scope).Names\", Method, 5, \"\"},\n\t\t{\"(*Scope).NumChildren\", Method, 5, \"\"},\n\t\t{\"(*Scope).Parent\", Method, 5, \"\"},\n\t\t{\"(*Scope).Pos\", Method, 5, \"\"},\n\t\t{\"(*Scope).String\", Method, 5, \"\"},\n\t\t{\"(*Scope).WriteTo\", Method, 5, \"\"},\n\t\t{\"(*Selection).Index\", Method, 5, \"\"},\n\t\t{\"(*Selection).Indirect\", Method, 5, \"\"},\n\t\t{\"(*Selection).Kind\", Method, 5, \"\"},\n\t\t{\"(*Selection).Obj\", Method, 5, \"\"},\n\t\t{\"(*Selection).Recv\", Method, 5, \"\"},\n\t\t{\"(*Selection).String\", Method, 5, \"\"},\n\t\t{\"(*Selection).Type\", Method, 5, \"\"},\n\t\t{\"(*Signature).Params\", Method, 5, \"\"},\n\t\t{\"(*Signature).Recv\", Method, 5, \"\"},\n\t\t{\"(*Signature).RecvTypeParams\", Method, 18, \"\"},\n\t\t{\"(*Signature).Results\", Method, 5, \"\"},\n\t\t{\"(*Signature).String\", Method, 5, \"\"},\n\t\t{\"(*Signature).TypeParams\", Method, 18, \"\"},\n\t\t{\"(*Signature).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Signature).Variadic\", Method, 5, \"\"},\n\t\t{\"(*Slice).Elem\", Method, 5, \"\"},\n\t\t{\"(*Slice).String\", Method, 5, \"\"},\n\t\t{\"(*Slice).Underlying\", Method, 5, \"\"},\n\t\t{\"(*StdSizes).Alignof\", Method, 5, \"\"},\n\t\t{\"(*StdSizes).Offsetsof\", Method, 5, \"\"},\n\t\t{\"(*StdSizes).Sizeof\", Method, 5, \"\"},\n\t\t{\"(*Struct).Field\", Method, 5, \"\"},\n\t\t{\"(*Struct).Fields\", Method, 24, \"\"},\n\t\t{\"(*Struct).NumFields\", Method, 5, \"\"},\n\t\t{\"(*Struct).String\", Method, 5, \"\"},\n\t\t{\"(*Struct).Tag\", Method, 5, \"\"},\n\t\t{\"(*Struct).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Term).String\", Method, 18, \"\"},\n\t\t{\"(*Term).Tilde\", Method, 18, \"\"},\n\t\t{\"(*Term).Type\", Method, 18, \"\"},\n\t\t{\"(*Tuple).At\", Method, 5, \"\"},\n\t\t{\"(*Tuple).Len\", Method, 5, \"\"},\n\t\t{\"(*Tuple).String\", Method, 5, \"\"},\n\t\t{\"(*Tuple).Underlying\", Method, 5, \"\"},\n\t\t{\"(*Tuple).Variables\", Method, 24, \"\"},\n\t\t{\"(*TypeList).At\", Method, 18, \"\"},\n\t\t{\"(*TypeList).Len\", Method, 18, \"\"},\n\t\t{\"(*TypeList).Types\", Method, 24, \"\"},\n\t\t{\"(*TypeName).Exported\", Method, 5, \"\"},\n\t\t{\"(*TypeName).Id\", Method, 5, \"\"},\n\t\t{\"(*TypeName).IsAlias\", Method, 9, \"\"},\n\t\t{\"(*TypeName).Name\", Method, 5, \"\"},\n\t\t{\"(*TypeName).Parent\", Method, 5, \"\"},\n\t\t{\"(*TypeName).Pkg\", Method, 5, \"\"},\n\t\t{\"(*TypeName).Pos\", Method, 5, \"\"},\n\t\t{\"(*TypeName).String\", Method, 5, \"\"},\n\t\t{\"(*TypeName).Type\", Method, 5, \"\"},\n\t\t{\"(*TypeParam).Constraint\", Method, 18, \"\"},\n\t\t{\"(*TypeParam).Index\", Method, 18, \"\"},\n\t\t{\"(*TypeParam).Obj\", Method, 18, \"\"},\n\t\t{\"(*TypeParam).SetConstraint\", Method, 18, \"\"},\n\t\t{\"(*TypeParam).String\", Method, 18, \"\"},\n\t\t{\"(*TypeParam).Underlying\", Method, 18, \"\"},\n\t\t{\"(*TypeParamList).At\", Method, 18, \"\"},\n\t\t{\"(*TypeParamList).Len\", Method, 18, \"\"},\n\t\t{\"(*TypeParamList).TypeParams\", Method, 24, \"\"},\n\t\t{\"(*Union).Len\", Method, 18, \"\"},\n\t\t{\"(*Union).String\", Method, 18, \"\"},\n\t\t{\"(*Union).Term\", Method, 18, \"\"},\n\t\t{\"(*Union).Terms\", Method, 24, \"\"},\n\t\t{\"(*Union).Underlying\", Method, 18, \"\"},\n\t\t{\"(*Var).Anonymous\", Method, 5, \"\"},\n\t\t{\"(*Var).Embedded\", Method, 11, \"\"},\n\t\t{\"(*Var).Exported\", Method, 5, \"\"},\n\t\t{\"(*Var).Id\", Method, 5, \"\"},\n\t\t{\"(*Var).IsField\", Method, 5, \"\"},\n\t\t{\"(*Var).Kind\", Method, 25, \"\"},\n\t\t{\"(*Var).Name\", Method, 5, \"\"},\n\t\t{\"(*Var).Origin\", Method, 19, \"\"},\n\t\t{\"(*Var).Parent\", Method, 5, \"\"},\n\t\t{\"(*Var).Pkg\", Method, 5, \"\"},\n\t\t{\"(*Var).Pos\", Method, 5, \"\"},\n\t\t{\"(*Var).SetKind\", Method, 25, \"\"},\n\t\t{\"(*Var).String\", Method, 5, \"\"},\n\t\t{\"(*Var).Type\", Method, 5, \"\"},\n\t\t{\"(Checker).ObjectOf\", Method, 5, \"\"},\n\t\t{\"(Checker).PkgNameOf\", Method, 22, \"\"},\n\t\t{\"(Checker).TypeOf\", Method, 5, \"\"},\n\t\t{\"(Error).Error\", Method, 5, \"\"},\n\t\t{\"(Importer).Import\", Method, 5, \"\"},\n\t\t{\"(ImporterFrom).Import\", Method, 6, \"\"},\n\t\t{\"(ImporterFrom).ImportFrom\", Method, 6, \"\"},\n\t\t{\"(Object).Exported\", Method, 5, \"\"},\n\t\t{\"(Object).Id\", Method, 5, \"\"},\n\t\t{\"(Object).Name\", Method, 5, \"\"},\n\t\t{\"(Object).Parent\", Method, 5, \"\"},\n\t\t{\"(Object).Pkg\", Method, 5, \"\"},\n\t\t{\"(Object).Pos\", Method, 5, \"\"},\n\t\t{\"(Object).String\", Method, 5, \"\"},\n\t\t{\"(Object).Type\", Method, 5, \"\"},\n\t\t{\"(Sizes).Alignof\", Method, 5, \"\"},\n\t\t{\"(Sizes).Offsetsof\", Method, 5, \"\"},\n\t\t{\"(Sizes).Sizeof\", Method, 5, \"\"},\n\t\t{\"(Type).String\", Method, 5, \"\"},\n\t\t{\"(Type).Underlying\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).Addressable\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).Assignable\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).HasOk\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).IsBuiltin\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).IsNil\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).IsType\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).IsValue\", Method, 5, \"\"},\n\t\t{\"(TypeAndValue).IsVoid\", Method, 5, \"\"},\n\t\t{\"(VarKind).String\", Method, 25, \"\"},\n\t\t{\"Alias\", Type, 22, \"\"},\n\t\t{\"ArgumentError\", Type, 18, \"\"},\n\t\t{\"ArgumentError.Err\", Field, 18, \"\"},\n\t\t{\"ArgumentError.Index\", Field, 18, \"\"},\n\t\t{\"Array\", Type, 5, \"\"},\n\t\t{\"AssertableTo\", Func, 5, \"func(V *Interface, T Type) bool\"},\n\t\t{\"AssignableTo\", Func, 5, \"func(V Type, T Type) bool\"},\n\t\t{\"Basic\", Type, 5, \"\"},\n\t\t{\"BasicInfo\", Type, 5, \"\"},\n\t\t{\"BasicKind\", Type, 5, \"\"},\n\t\t{\"Bool\", Const, 5, \"\"},\n\t\t{\"Builtin\", Type, 5, \"\"},\n\t\t{\"Byte\", Const, 5, \"\"},\n\t\t{\"Chan\", Type, 5, \"\"},\n\t\t{\"ChanDir\", Type, 5, \"\"},\n\t\t{\"CheckExpr\", Func, 13, \"func(fset *token.FileSet, pkg *Package, pos token.Pos, expr ast.Expr, info *Info) (err error)\"},\n\t\t{\"Checker\", Type, 5, \"\"},\n\t\t{\"Checker.Info\", Field, 5, \"\"},\n\t\t{\"Comparable\", Func, 5, \"func(T Type) bool\"},\n\t\t{\"Complex128\", Const, 5, \"\"},\n\t\t{\"Complex64\", Const, 5, \"\"},\n\t\t{\"Config\", Type, 5, \"\"},\n\t\t{\"Config.Context\", Field, 18, \"\"},\n\t\t{\"Config.DisableUnusedImportCheck\", Field, 5, \"\"},\n\t\t{\"Config.Error\", Field, 5, \"\"},\n\t\t{\"Config.FakeImportC\", Field, 5, \"\"},\n\t\t{\"Config.GoVersion\", Field, 18, \"\"},\n\t\t{\"Config.IgnoreFuncBodies\", Field, 5, \"\"},\n\t\t{\"Config.Importer\", Field, 5, \"\"},\n\t\t{\"Config.Sizes\", Field, 5, \"\"},\n\t\t{\"Const\", Type, 5, \"\"},\n\t\t{\"Context\", Type, 18, \"\"},\n\t\t{\"ConvertibleTo\", Func, 5, \"func(V Type, T Type) bool\"},\n\t\t{\"DefPredeclaredTestFuncs\", Func, 5, \"func()\"},\n\t\t{\"Default\", Func, 8, \"func(t Type) Type\"},\n\t\t{\"Error\", Type, 5, \"\"},\n\t\t{\"Error.Fset\", Field, 5, \"\"},\n\t\t{\"Error.Msg\", Field, 5, \"\"},\n\t\t{\"Error.Pos\", Field, 5, \"\"},\n\t\t{\"Error.Soft\", Field, 5, \"\"},\n\t\t{\"Eval\", Func, 5, \"func(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ TypeAndValue, err error)\"},\n\t\t{\"ExprString\", Func, 5, \"func(x ast.Expr) string\"},\n\t\t{\"FieldVal\", Const, 5, \"\"},\n\t\t{\"FieldVar\", Const, 25, \"\"},\n\t\t{\"Float32\", Const, 5, \"\"},\n\t\t{\"Float64\", Const, 5, \"\"},\n\t\t{\"Func\", Type, 5, \"\"},\n\t\t{\"Id\", Func, 5, \"func(pkg *Package, name string) string\"},\n\t\t{\"Identical\", Func, 5, \"func(x Type, y Type) bool\"},\n\t\t{\"IdenticalIgnoreTags\", Func, 8, \"func(x Type, y Type) bool\"},\n\t\t{\"Implements\", Func, 5, \"func(V Type, T *Interface) bool\"},\n\t\t{\"ImportMode\", Type, 6, \"\"},\n\t\t{\"Importer\", Type, 5, \"\"},\n\t\t{\"ImporterFrom\", Type, 6, \"\"},\n\t\t{\"Info\", Type, 5, \"\"},\n\t\t{\"Info.Defs\", Field, 5, \"\"},\n\t\t{\"Info.FileVersions\", Field, 22, \"\"},\n\t\t{\"Info.Implicits\", Field, 5, \"\"},\n\t\t{\"Info.InitOrder\", Field, 5, \"\"},\n\t\t{\"Info.Instances\", Field, 18, \"\"},\n\t\t{\"Info.Scopes\", Field, 5, \"\"},\n\t\t{\"Info.Selections\", Field, 5, \"\"},\n\t\t{\"Info.Types\", Field, 5, \"\"},\n\t\t{\"Info.Uses\", Field, 5, \"\"},\n\t\t{\"Initializer\", Type, 5, \"\"},\n\t\t{\"Initializer.Lhs\", Field, 5, \"\"},\n\t\t{\"Initializer.Rhs\", Field, 5, \"\"},\n\t\t{\"Instance\", Type, 18, \"\"},\n\t\t{\"Instance.Type\", Field, 18, \"\"},\n\t\t{\"Instance.TypeArgs\", Field, 18, \"\"},\n\t\t{\"Instantiate\", Func, 18, \"func(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error)\"},\n\t\t{\"Int\", Const, 5, \"\"},\n\t\t{\"Int16\", Const, 5, \"\"},\n\t\t{\"Int32\", Const, 5, \"\"},\n\t\t{\"Int64\", Const, 5, \"\"},\n\t\t{\"Int8\", Const, 5, \"\"},\n\t\t{\"Interface\", Type, 5, \"\"},\n\t\t{\"Invalid\", Const, 5, \"\"},\n\t\t{\"IsBoolean\", Const, 5, \"\"},\n\t\t{\"IsComplex\", Const, 5, \"\"},\n\t\t{\"IsConstType\", Const, 5, \"\"},\n\t\t{\"IsFloat\", Const, 5, \"\"},\n\t\t{\"IsInteger\", Const, 5, \"\"},\n\t\t{\"IsInterface\", Func, 5, \"func(t Type) bool\"},\n\t\t{\"IsNumeric\", Const, 5, \"\"},\n\t\t{\"IsOrdered\", Const, 5, \"\"},\n\t\t{\"IsString\", Const, 5, \"\"},\n\t\t{\"IsUnsigned\", Const, 5, \"\"},\n\t\t{\"IsUntyped\", Const, 5, \"\"},\n\t\t{\"Label\", Type, 5, \"\"},\n\t\t{\"LocalVar\", Const, 25, \"\"},\n\t\t{\"LookupFieldOrMethod\", Func, 5, \"func(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool)\"},\n\t\t{\"LookupSelection\", Func, 25, \"func(T Type, addressable bool, pkg *Package, name string) (Selection, bool)\"},\n\t\t{\"Map\", Type, 5, \"\"},\n\t\t{\"MethodExpr\", Const, 5, \"\"},\n\t\t{\"MethodSet\", Type, 5, \"\"},\n\t\t{\"MethodVal\", Const, 5, \"\"},\n\t\t{\"MissingMethod\", Func, 5, \"func(V Type, T *Interface, static bool) (method *Func, wrongType bool)\"},\n\t\t{\"Named\", Type, 5, \"\"},\n\t\t{\"NewAlias\", Func, 22, \"func(obj *TypeName, rhs Type) *Alias\"},\n\t\t{\"NewArray\", Func, 5, \"func(elem Type, len int64) *Array\"},\n\t\t{\"NewChan\", Func, 5, \"func(dir ChanDir, elem Type) *Chan\"},\n\t\t{\"NewChecker\", Func, 5, \"func(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker\"},\n\t\t{\"NewConst\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const\"},\n\t\t{\"NewContext\", Func, 18, \"func() *Context\"},\n\t\t{\"NewField\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var\"},\n\t\t{\"NewFunc\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, sig *Signature) *Func\"},\n\t\t{\"NewInterface\", Func, 5, \"func(methods []*Func, embeddeds []*Named) *Interface\"},\n\t\t{\"NewInterfaceType\", Func, 11, \"func(methods []*Func, embeddeds []Type) *Interface\"},\n\t\t{\"NewLabel\", Func, 5, \"func(pos token.Pos, pkg *Package, name string) *Label\"},\n\t\t{\"NewMap\", Func, 5, \"func(key Type, elem Type) *Map\"},\n\t\t{\"NewMethodSet\", Func, 5, \"func(T Type) *MethodSet\"},\n\t\t{\"NewNamed\", Func, 5, \"func(obj *TypeName, underlying Type, methods []*Func) *Named\"},\n\t\t{\"NewPackage\", Func, 5, \"func(path string, name string) *Package\"},\n\t\t{\"NewParam\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, typ Type) *Var\"},\n\t\t{\"NewPkgName\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName\"},\n\t\t{\"NewPointer\", Func, 5, \"func(elem Type) *Pointer\"},\n\t\t{\"NewScope\", Func, 5, \"func(parent *Scope, pos token.Pos, end token.Pos, comment string) *Scope\"},\n\t\t{\"NewSignature\", Func, 5, \"func(recv *Var, params *Tuple, results *Tuple, variadic bool) *Signature\"},\n\t\t{\"NewSignatureType\", Func, 18, \"func(recv *Var, recvTypeParams []*TypeParam, typeParams []*TypeParam, params *Tuple, results *Tuple, variadic bool) *Signature\"},\n\t\t{\"NewSlice\", Func, 5, \"func(elem Type) *Slice\"},\n\t\t{\"NewStruct\", Func, 5, \"func(fields []*Var, tags []string) *Struct\"},\n\t\t{\"NewTerm\", Func, 18, \"func(tilde bool, typ Type) *Term\"},\n\t\t{\"NewTuple\", Func, 5, \"func(x ...*Var) *Tuple\"},\n\t\t{\"NewTypeName\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, typ Type) *TypeName\"},\n\t\t{\"NewTypeParam\", Func, 18, \"func(obj *TypeName, constraint Type) *TypeParam\"},\n\t\t{\"NewUnion\", Func, 18, \"func(terms []*Term) *Union\"},\n\t\t{\"NewVar\", Func, 5, \"func(pos token.Pos, pkg *Package, name string, typ Type) *Var\"},\n\t\t{\"Nil\", Type, 5, \"\"},\n\t\t{\"ObjectString\", Func, 5, \"func(obj Object, qf Qualifier) string\"},\n\t\t{\"Package\", Type, 5, \"\"},\n\t\t{\"PackageVar\", Const, 25, \"\"},\n\t\t{\"ParamVar\", Const, 25, \"\"},\n\t\t{\"PkgName\", Type, 5, \"\"},\n\t\t{\"Pointer\", Type, 5, \"\"},\n\t\t{\"Qualifier\", Type, 5, \"\"},\n\t\t{\"RecvOnly\", Const, 5, \"\"},\n\t\t{\"RecvVar\", Const, 25, \"\"},\n\t\t{\"RelativeTo\", Func, 5, \"func(pkg *Package) Qualifier\"},\n\t\t{\"ResultVar\", Const, 25, \"\"},\n\t\t{\"Rune\", Const, 5, \"\"},\n\t\t{\"Satisfies\", Func, 20, \"func(V Type, T *Interface) bool\"},\n\t\t{\"Scope\", Type, 5, \"\"},\n\t\t{\"Selection\", Type, 5, \"\"},\n\t\t{\"SelectionKind\", Type, 5, \"\"},\n\t\t{\"SelectionString\", Func, 5, \"func(s *Selection, qf Qualifier) string\"},\n\t\t{\"SendOnly\", Const, 5, \"\"},\n\t\t{\"SendRecv\", Const, 5, \"\"},\n\t\t{\"Signature\", Type, 5, \"\"},\n\t\t{\"Sizes\", Type, 5, \"\"},\n\t\t{\"SizesFor\", Func, 9, \"func(compiler string, arch string) Sizes\"},\n\t\t{\"Slice\", Type, 5, \"\"},\n\t\t{\"StdSizes\", Type, 5, \"\"},\n\t\t{\"StdSizes.MaxAlign\", Field, 5, \"\"},\n\t\t{\"StdSizes.WordSize\", Field, 5, \"\"},\n\t\t{\"String\", Const, 5, \"\"},\n\t\t{\"Struct\", Type, 5, \"\"},\n\t\t{\"Term\", Type, 18, \"\"},\n\t\t{\"Tuple\", Type, 5, \"\"},\n\t\t{\"Typ\", Var, 5, \"\"},\n\t\t{\"Type\", Type, 5, \"\"},\n\t\t{\"TypeAndValue\", Type, 5, \"\"},\n\t\t{\"TypeAndValue.Type\", Field, 5, \"\"},\n\t\t{\"TypeAndValue.Value\", Field, 5, \"\"},\n\t\t{\"TypeList\", Type, 18, \"\"},\n\t\t{\"TypeName\", Type, 5, \"\"},\n\t\t{\"TypeParam\", Type, 18, \"\"},\n\t\t{\"TypeParamList\", Type, 18, \"\"},\n\t\t{\"TypeString\", Func, 5, \"func(typ Type, qf Qualifier) string\"},\n\t\t{\"Uint\", Const, 5, \"\"},\n\t\t{\"Uint16\", Const, 5, \"\"},\n\t\t{\"Uint32\", Const, 5, \"\"},\n\t\t{\"Uint64\", Const, 5, \"\"},\n\t\t{\"Uint8\", Const, 5, \"\"},\n\t\t{\"Uintptr\", Const, 5, \"\"},\n\t\t{\"Unalias\", Func, 22, \"func(t Type) Type\"},\n\t\t{\"Union\", Type, 18, \"\"},\n\t\t{\"Universe\", Var, 5, \"\"},\n\t\t{\"Unsafe\", Var, 5, \"\"},\n\t\t{\"UnsafePointer\", Const, 5, \"\"},\n\t\t{\"UntypedBool\", Const, 5, \"\"},\n\t\t{\"UntypedComplex\", Const, 5, \"\"},\n\t\t{\"UntypedFloat\", Const, 5, \"\"},\n\t\t{\"UntypedInt\", Const, 5, \"\"},\n\t\t{\"UntypedNil\", Const, 5, \"\"},\n\t\t{\"UntypedRune\", Const, 5, \"\"},\n\t\t{\"UntypedString\", Const, 5, \"\"},\n\t\t{\"Var\", Type, 5, \"\"},\n\t\t{\"VarKind\", Type, 25, \"\"},\n\t\t{\"WriteExpr\", Func, 5, \"func(buf *bytes.Buffer, x ast.Expr)\"},\n\t\t{\"WriteSignature\", Func, 5, \"func(buf *bytes.Buffer, sig *Signature, qf Qualifier)\"},\n\t\t{\"WriteType\", Func, 5, \"func(buf *bytes.Buffer, typ Type, qf Qualifier)\"},\n\t},\n\t\"go/version\": {\n\t\t{\"Compare\", Func, 22, \"func(x string, y string) int\"},\n\t\t{\"IsValid\", Func, 22, \"func(x string) bool\"},\n\t\t{\"Lang\", Func, 22, \"func(x string) string\"},\n\t},\n\t\"hash\": {\n\t\t{\"(Cloner).BlockSize\", Method, 25, \"\"},\n\t\t{\"(Cloner).Clone\", Method, 25, \"\"},\n\t\t{\"(Cloner).Reset\", Method, 25, \"\"},\n\t\t{\"(Cloner).Size\", Method, 25, \"\"},\n\t\t{\"(Cloner).Sum\", Method, 25, \"\"},\n\t\t{\"(Cloner).Write\", Method, 25, \"\"},\n\t\t{\"(Hash).BlockSize\", Method, 0, \"\"},\n\t\t{\"(Hash).Reset\", Method, 0, \"\"},\n\t\t{\"(Hash).Size\", Method, 0, \"\"},\n\t\t{\"(Hash).Sum\", Method, 0, \"\"},\n\t\t{\"(Hash).Write\", Method, 0, \"\"},\n\t\t{\"(Hash32).BlockSize\", Method, 0, \"\"},\n\t\t{\"(Hash32).Reset\", Method, 0, \"\"},\n\t\t{\"(Hash32).Size\", Method, 0, \"\"},\n\t\t{\"(Hash32).Sum\", Method, 0, \"\"},\n\t\t{\"(Hash32).Sum32\", Method, 0, \"\"},\n\t\t{\"(Hash32).Write\", Method, 0, \"\"},\n\t\t{\"(Hash64).BlockSize\", Method, 0, \"\"},\n\t\t{\"(Hash64).Reset\", Method, 0, \"\"},\n\t\t{\"(Hash64).Size\", Method, 0, \"\"},\n\t\t{\"(Hash64).Sum\", Method, 0, \"\"},\n\t\t{\"(Hash64).Sum64\", Method, 0, \"\"},\n\t\t{\"(Hash64).Write\", Method, 0, \"\"},\n\t\t{\"(XOF).BlockSize\", Method, 25, \"\"},\n\t\t{\"(XOF).Read\", Method, 25, \"\"},\n\t\t{\"(XOF).Reset\", Method, 25, \"\"},\n\t\t{\"(XOF).Write\", Method, 25, \"\"},\n\t\t{\"Cloner\", Type, 25, \"\"},\n\t\t{\"Hash\", Type, 0, \"\"},\n\t\t{\"Hash32\", Type, 0, \"\"},\n\t\t{\"Hash64\", Type, 0, \"\"},\n\t\t{\"XOF\", Type, 25, \"\"},\n\t},\n\t\"hash/adler32\": {\n\t\t{\"Checksum\", Func, 0, \"func(data []byte) uint32\"},\n\t\t{\"New\", Func, 0, \"func() hash.Hash32\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t},\n\t\"hash/crc32\": {\n\t\t{\"Castagnoli\", Const, 0, \"\"},\n\t\t{\"Checksum\", Func, 0, \"func(data []byte, tab *Table) uint32\"},\n\t\t{\"ChecksumIEEE\", Func, 0, \"func(data []byte) uint32\"},\n\t\t{\"IEEE\", Const, 0, \"\"},\n\t\t{\"IEEETable\", Var, 0, \"\"},\n\t\t{\"Koopman\", Const, 0, \"\"},\n\t\t{\"MakeTable\", Func, 0, \"func(poly uint32) *Table\"},\n\t\t{\"New\", Func, 0, \"func(tab *Table) hash.Hash32\"},\n\t\t{\"NewIEEE\", Func, 0, \"func() hash.Hash32\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Table\", Type, 0, \"\"},\n\t\t{\"Update\", Func, 0, \"func(crc uint32, tab *Table, p []byte) uint32\"},\n\t},\n\t\"hash/crc64\": {\n\t\t{\"Checksum\", Func, 0, \"func(data []byte, tab *Table) uint64\"},\n\t\t{\"ECMA\", Const, 0, \"\"},\n\t\t{\"ISO\", Const, 0, \"\"},\n\t\t{\"MakeTable\", Func, 0, \"func(poly uint64) *Table\"},\n\t\t{\"New\", Func, 0, \"func(tab *Table) hash.Hash64\"},\n\t\t{\"Size\", Const, 0, \"\"},\n\t\t{\"Table\", Type, 0, \"\"},\n\t\t{\"Update\", Func, 0, \"func(crc uint64, tab *Table, p []byte) uint64\"},\n\t},\n\t\"hash/fnv\": {\n\t\t{\"New128\", Func, 9, \"func() hash.Hash\"},\n\t\t{\"New128a\", Func, 9, \"func() hash.Hash\"},\n\t\t{\"New32\", Func, 0, \"func() hash.Hash32\"},\n\t\t{\"New32a\", Func, 0, \"func() hash.Hash32\"},\n\t\t{\"New64\", Func, 0, \"func() hash.Hash64\"},\n\t\t{\"New64a\", Func, 0, \"func() hash.Hash64\"},\n\t},\n\t\"hash/maphash\": {\n\t\t{\"(*Hash).BlockSize\", Method, 14, \"\"},\n\t\t{\"(*Hash).Clone\", Method, 25, \"\"},\n\t\t{\"(*Hash).Reset\", Method, 14, \"\"},\n\t\t{\"(*Hash).Seed\", Method, 14, \"\"},\n\t\t{\"(*Hash).SetSeed\", Method, 14, \"\"},\n\t\t{\"(*Hash).Size\", Method, 14, \"\"},\n\t\t{\"(*Hash).Sum\", Method, 14, \"\"},\n\t\t{\"(*Hash).Sum64\", Method, 14, \"\"},\n\t\t{\"(*Hash).Write\", Method, 14, \"\"},\n\t\t{\"(*Hash).WriteByte\", Method, 14, \"\"},\n\t\t{\"(*Hash).WriteString\", Method, 14, \"\"},\n\t\t{\"Bytes\", Func, 19, \"func(seed Seed, b []byte) uint64\"},\n\t\t{\"Comparable\", Func, 24, \"func[T comparable](seed Seed, v T) uint64\"},\n\t\t{\"Hash\", Type, 14, \"\"},\n\t\t{\"MakeSeed\", Func, 14, \"func() Seed\"},\n\t\t{\"Seed\", Type, 14, \"\"},\n\t\t{\"String\", Func, 19, \"func(seed Seed, s string) uint64\"},\n\t\t{\"WriteComparable\", Func, 24, \"func[T comparable](h *Hash, x T)\"},\n\t},\n\t\"html\": {\n\t\t{\"EscapeString\", Func, 0, \"func(s string) string\"},\n\t\t{\"UnescapeString\", Func, 0, \"func(s string) string\"},\n\t},\n\t\"html/template\": {\n\t\t{\"(*Error).Error\", Method, 0, \"\"},\n\t\t{\"(*Template).AddParseTree\", Method, 0, \"\"},\n\t\t{\"(*Template).Clone\", Method, 0, \"\"},\n\t\t{\"(*Template).DefinedTemplates\", Method, 6, \"\"},\n\t\t{\"(*Template).Delims\", Method, 0, \"\"},\n\t\t{\"(*Template).Execute\", Method, 0, \"\"},\n\t\t{\"(*Template).ExecuteTemplate\", Method, 0, \"\"},\n\t\t{\"(*Template).Funcs\", Method, 0, \"\"},\n\t\t{\"(*Template).Lookup\", Method, 0, \"\"},\n\t\t{\"(*Template).Name\", Method, 0, \"\"},\n\t\t{\"(*Template).New\", Method, 0, \"\"},\n\t\t{\"(*Template).Option\", Method, 5, \"\"},\n\t\t{\"(*Template).Parse\", Method, 0, \"\"},\n\t\t{\"(*Template).ParseFS\", Method, 16, \"\"},\n\t\t{\"(*Template).ParseFiles\", Method, 0, \"\"},\n\t\t{\"(*Template).ParseGlob\", Method, 0, \"\"},\n\t\t{\"(*Template).Templates\", Method, 0, \"\"},\n\t\t{\"CSS\", Type, 0, \"\"},\n\t\t{\"ErrAmbigContext\", Const, 0, \"\"},\n\t\t{\"ErrBadHTML\", Const, 0, \"\"},\n\t\t{\"ErrBranchEnd\", Const, 0, \"\"},\n\t\t{\"ErrEndContext\", Const, 0, \"\"},\n\t\t{\"ErrJSTemplate\", Const, 21, \"\"},\n\t\t{\"ErrNoSuchTemplate\", Const, 0, \"\"},\n\t\t{\"ErrOutputContext\", Const, 0, \"\"},\n\t\t{\"ErrPartialCharset\", Const, 0, \"\"},\n\t\t{\"ErrPartialEscape\", Const, 0, \"\"},\n\t\t{\"ErrPredefinedEscaper\", Const, 9, \"\"},\n\t\t{\"ErrRangeLoopReentry\", Const, 0, \"\"},\n\t\t{\"ErrSlashAmbig\", Const, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Description\", Field, 0, \"\"},\n\t\t{\"Error.ErrorCode\", Field, 0, \"\"},\n\t\t{\"Error.Line\", Field, 0, \"\"},\n\t\t{\"Error.Name\", Field, 0, \"\"},\n\t\t{\"Error.Node\", Field, 4, \"\"},\n\t\t{\"ErrorCode\", Type, 0, \"\"},\n\t\t{\"FuncMap\", Type, 0, \"\"},\n\t\t{\"HTML\", Type, 0, \"\"},\n\t\t{\"HTMLAttr\", Type, 0, \"\"},\n\t\t{\"HTMLEscape\", Func, 0, \"func(w io.Writer, b []byte)\"},\n\t\t{\"HTMLEscapeString\", Func, 0, \"func(s string) string\"},\n\t\t{\"HTMLEscaper\", Func, 0, \"func(args ...any) string\"},\n\t\t{\"IsTrue\", Func, 6, \"func(val any) (truth bool, ok bool)\"},\n\t\t{\"JS\", Type, 0, \"\"},\n\t\t{\"JSEscape\", Func, 0, \"func(w io.Writer, b []byte)\"},\n\t\t{\"JSEscapeString\", Func, 0, \"func(s string) string\"},\n\t\t{\"JSEscaper\", Func, 0, \"func(args ...any) string\"},\n\t\t{\"JSStr\", Type, 0, \"\"},\n\t\t{\"Must\", Func, 0, \"func(t *Template, err error) *Template\"},\n\t\t{\"New\", Func, 0, \"func(name string) *Template\"},\n\t\t{\"OK\", Const, 0, \"\"},\n\t\t{\"ParseFS\", Func, 16, \"func(fs fs.FS, patterns ...string) (*Template, error)\"},\n\t\t{\"ParseFiles\", Func, 0, \"func(filenames ...string) (*Template, error)\"},\n\t\t{\"ParseGlob\", Func, 0, \"func(pattern string) (*Template, error)\"},\n\t\t{\"Srcset\", Type, 10, \"\"},\n\t\t{\"Template\", Type, 0, \"\"},\n\t\t{\"Template.Tree\", Field, 2, \"\"},\n\t\t{\"URL\", Type, 0, \"\"},\n\t\t{\"URLQueryEscaper\", Func, 0, \"func(args ...any) string\"},\n\t},\n\t\"image\": {\n\t\t{\"(*Alpha).AlphaAt\", Method, 4, \"\"},\n\t\t{\"(*Alpha).At\", Method, 0, \"\"},\n\t\t{\"(*Alpha).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Alpha).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Alpha).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Alpha).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*Alpha).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*Alpha).Set\", Method, 0, \"\"},\n\t\t{\"(*Alpha).SetAlpha\", Method, 0, \"\"},\n\t\t{\"(*Alpha).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*Alpha).SubImage\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).Alpha16At\", Method, 4, \"\"},\n\t\t{\"(*Alpha16).At\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*Alpha16).Set\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).SetAlpha16\", Method, 0, \"\"},\n\t\t{\"(*Alpha16).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*Alpha16).SubImage\", Method, 0, \"\"},\n\t\t{\"(*CMYK).At\", Method, 5, \"\"},\n\t\t{\"(*CMYK).Bounds\", Method, 5, \"\"},\n\t\t{\"(*CMYK).CMYKAt\", Method, 5, \"\"},\n\t\t{\"(*CMYK).ColorModel\", Method, 5, \"\"},\n\t\t{\"(*CMYK).Opaque\", Method, 5, \"\"},\n\t\t{\"(*CMYK).PixOffset\", Method, 5, \"\"},\n\t\t{\"(*CMYK).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*CMYK).Set\", Method, 5, \"\"},\n\t\t{\"(*CMYK).SetCMYK\", Method, 5, \"\"},\n\t\t{\"(*CMYK).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*CMYK).SubImage\", Method, 5, \"\"},\n\t\t{\"(*Gray).At\", Method, 0, \"\"},\n\t\t{\"(*Gray).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Gray).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Gray).GrayAt\", Method, 4, \"\"},\n\t\t{\"(*Gray).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Gray).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*Gray).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*Gray).Set\", Method, 0, \"\"},\n\t\t{\"(*Gray).SetGray\", Method, 0, \"\"},\n\t\t{\"(*Gray).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*Gray).SubImage\", Method, 0, \"\"},\n\t\t{\"(*Gray16).At\", Method, 0, \"\"},\n\t\t{\"(*Gray16).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Gray16).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Gray16).Gray16At\", Method, 4, \"\"},\n\t\t{\"(*Gray16).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Gray16).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*Gray16).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*Gray16).Set\", Method, 0, \"\"},\n\t\t{\"(*Gray16).SetGray16\", Method, 0, \"\"},\n\t\t{\"(*Gray16).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*Gray16).SubImage\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).At\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).Bounds\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).NRGBAAt\", Method, 4, \"\"},\n\t\t{\"(*NRGBA).Opaque\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*NRGBA).Set\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).SetNRGBA\", Method, 0, \"\"},\n\t\t{\"(*NRGBA).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*NRGBA).SubImage\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).At\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).Bounds\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).NRGBA64At\", Method, 4, \"\"},\n\t\t{\"(*NRGBA64).Opaque\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*NRGBA64).Set\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).SetNRGBA64\", Method, 0, \"\"},\n\t\t{\"(*NRGBA64).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*NRGBA64).SubImage\", Method, 0, \"\"},\n\t\t{\"(*NYCbCrA).AOffset\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).At\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).Bounds\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).COffset\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).ColorModel\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).NYCbCrAAt\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).Opaque\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*NYCbCrA).SubImage\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).YCbCrAt\", Method, 6, \"\"},\n\t\t{\"(*NYCbCrA).YOffset\", Method, 6, \"\"},\n\t\t{\"(*Paletted).At\", Method, 0, \"\"},\n\t\t{\"(*Paletted).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Paletted).ColorIndexAt\", Method, 0, \"\"},\n\t\t{\"(*Paletted).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Paletted).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Paletted).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*Paletted).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*Paletted).Set\", Method, 0, \"\"},\n\t\t{\"(*Paletted).SetColorIndex\", Method, 0, \"\"},\n\t\t{\"(*Paletted).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*Paletted).SubImage\", Method, 0, \"\"},\n\t\t{\"(*RGBA).At\", Method, 0, \"\"},\n\t\t{\"(*RGBA).Bounds\", Method, 0, \"\"},\n\t\t{\"(*RGBA).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*RGBA).Opaque\", Method, 0, \"\"},\n\t\t{\"(*RGBA).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*RGBA).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*RGBA).RGBAAt\", Method, 4, \"\"},\n\t\t{\"(*RGBA).Set\", Method, 0, \"\"},\n\t\t{\"(*RGBA).SetRGBA\", Method, 0, \"\"},\n\t\t{\"(*RGBA).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"(*RGBA).SubImage\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).At\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).Bounds\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).Opaque\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).PixOffset\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).RGBA64At\", Method, 4, \"\"},\n\t\t{\"(*RGBA64).Set\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).SetRGBA64\", Method, 0, \"\"},\n\t\t{\"(*RGBA64).SubImage\", Method, 0, \"\"},\n\t\t{\"(*Uniform).At\", Method, 0, \"\"},\n\t\t{\"(*Uniform).Bounds\", Method, 0, \"\"},\n\t\t{\"(*Uniform).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*Uniform).Convert\", Method, 0, \"\"},\n\t\t{\"(*Uniform).Opaque\", Method, 0, \"\"},\n\t\t{\"(*Uniform).RGBA\", Method, 0, \"\"},\n\t\t{\"(*Uniform).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*YCbCr).At\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).Bounds\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).COffset\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).ColorModel\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).Opaque\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(*YCbCr).SubImage\", Method, 0, \"\"},\n\t\t{\"(*YCbCr).YCbCrAt\", Method, 4, \"\"},\n\t\t{\"(*YCbCr).YOffset\", Method, 0, \"\"},\n\t\t{\"(Image).At\", Method, 0, \"\"},\n\t\t{\"(Image).Bounds\", Method, 0, \"\"},\n\t\t{\"(Image).ColorModel\", Method, 0, \"\"},\n\t\t{\"(PalettedImage).At\", Method, 0, \"\"},\n\t\t{\"(PalettedImage).Bounds\", Method, 0, \"\"},\n\t\t{\"(PalettedImage).ColorIndexAt\", Method, 0, \"\"},\n\t\t{\"(PalettedImage).ColorModel\", Method, 0, \"\"},\n\t\t{\"(Point).Add\", Method, 0, \"\"},\n\t\t{\"(Point).Div\", Method, 0, \"\"},\n\t\t{\"(Point).Eq\", Method, 0, \"\"},\n\t\t{\"(Point).In\", Method, 0, \"\"},\n\t\t{\"(Point).Mod\", Method, 0, \"\"},\n\t\t{\"(Point).Mul\", Method, 0, \"\"},\n\t\t{\"(Point).String\", Method, 0, \"\"},\n\t\t{\"(Point).Sub\", Method, 0, \"\"},\n\t\t{\"(RGBA64Image).At\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).Bounds\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).ColorModel\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(Rectangle).Add\", Method, 0, \"\"},\n\t\t{\"(Rectangle).At\", Method, 5, \"\"},\n\t\t{\"(Rectangle).Bounds\", Method, 5, \"\"},\n\t\t{\"(Rectangle).Canon\", Method, 0, \"\"},\n\t\t{\"(Rectangle).ColorModel\", Method, 5, \"\"},\n\t\t{\"(Rectangle).Dx\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Dy\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Empty\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Eq\", Method, 0, \"\"},\n\t\t{\"(Rectangle).In\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Inset\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Intersect\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Overlaps\", Method, 0, \"\"},\n\t\t{\"(Rectangle).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(Rectangle).Size\", Method, 0, \"\"},\n\t\t{\"(Rectangle).String\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Sub\", Method, 0, \"\"},\n\t\t{\"(Rectangle).Union\", Method, 0, \"\"},\n\t\t{\"(YCbCrSubsampleRatio).String\", Method, 0, \"\"},\n\t\t{\"Alpha\", Type, 0, \"\"},\n\t\t{\"Alpha.Pix\", Field, 0, \"\"},\n\t\t{\"Alpha.Rect\", Field, 0, \"\"},\n\t\t{\"Alpha.Stride\", Field, 0, \"\"},\n\t\t{\"Alpha16\", Type, 0, \"\"},\n\t\t{\"Alpha16.Pix\", Field, 0, \"\"},\n\t\t{\"Alpha16.Rect\", Field, 0, \"\"},\n\t\t{\"Alpha16.Stride\", Field, 0, \"\"},\n\t\t{\"Black\", Var, 0, \"\"},\n\t\t{\"CMYK\", Type, 5, \"\"},\n\t\t{\"CMYK.Pix\", Field, 5, \"\"},\n\t\t{\"CMYK.Rect\", Field, 5, \"\"},\n\t\t{\"CMYK.Stride\", Field, 5, \"\"},\n\t\t{\"Config\", Type, 0, \"\"},\n\t\t{\"Config.ColorModel\", Field, 0, \"\"},\n\t\t{\"Config.Height\", Field, 0, \"\"},\n\t\t{\"Config.Width\", Field, 0, \"\"},\n\t\t{\"Decode\", Func, 0, \"func(r io.Reader) (Image, string, error)\"},\n\t\t{\"DecodeConfig\", Func, 0, \"func(r io.Reader) (Config, string, error)\"},\n\t\t{\"ErrFormat\", Var, 0, \"\"},\n\t\t{\"Gray\", Type, 0, \"\"},\n\t\t{\"Gray.Pix\", Field, 0, \"\"},\n\t\t{\"Gray.Rect\", Field, 0, \"\"},\n\t\t{\"Gray.Stride\", Field, 0, \"\"},\n\t\t{\"Gray16\", Type, 0, \"\"},\n\t\t{\"Gray16.Pix\", Field, 0, \"\"},\n\t\t{\"Gray16.Rect\", Field, 0, \"\"},\n\t\t{\"Gray16.Stride\", Field, 0, \"\"},\n\t\t{\"Image\", Type, 0, \"\"},\n\t\t{\"NRGBA\", Type, 0, \"\"},\n\t\t{\"NRGBA.Pix\", Field, 0, \"\"},\n\t\t{\"NRGBA.Rect\", Field, 0, \"\"},\n\t\t{\"NRGBA.Stride\", Field, 0, \"\"},\n\t\t{\"NRGBA64\", Type, 0, \"\"},\n\t\t{\"NRGBA64.Pix\", Field, 0, \"\"},\n\t\t{\"NRGBA64.Rect\", Field, 0, \"\"},\n\t\t{\"NRGBA64.Stride\", Field, 0, \"\"},\n\t\t{\"NYCbCrA\", Type, 6, \"\"},\n\t\t{\"NYCbCrA.A\", Field, 6, \"\"},\n\t\t{\"NYCbCrA.AStride\", Field, 6, \"\"},\n\t\t{\"NYCbCrA.YCbCr\", Field, 6, \"\"},\n\t\t{\"NewAlpha\", Func, 0, \"func(r Rectangle) *Alpha\"},\n\t\t{\"NewAlpha16\", Func, 0, \"func(r Rectangle) *Alpha16\"},\n\t\t{\"NewCMYK\", Func, 5, \"func(r Rectangle) *CMYK\"},\n\t\t{\"NewGray\", Func, 0, \"func(r Rectangle) *Gray\"},\n\t\t{\"NewGray16\", Func, 0, \"func(r Rectangle) *Gray16\"},\n\t\t{\"NewNRGBA\", Func, 0, \"func(r Rectangle) *NRGBA\"},\n\t\t{\"NewNRGBA64\", Func, 0, \"func(r Rectangle) *NRGBA64\"},\n\t\t{\"NewNYCbCrA\", Func, 6, \"func(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *NYCbCrA\"},\n\t\t{\"NewPaletted\", Func, 0, \"func(r Rectangle, p color.Palette) *Paletted\"},\n\t\t{\"NewRGBA\", Func, 0, \"func(r Rectangle) *RGBA\"},\n\t\t{\"NewRGBA64\", Func, 0, \"func(r Rectangle) *RGBA64\"},\n\t\t{\"NewUniform\", Func, 0, \"func(c color.Color) *Uniform\"},\n\t\t{\"NewYCbCr\", Func, 0, \"func(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr\"},\n\t\t{\"Opaque\", Var, 0, \"\"},\n\t\t{\"Paletted\", Type, 0, \"\"},\n\t\t{\"Paletted.Palette\", Field, 0, \"\"},\n\t\t{\"Paletted.Pix\", Field, 0, \"\"},\n\t\t{\"Paletted.Rect\", Field, 0, \"\"},\n\t\t{\"Paletted.Stride\", Field, 0, \"\"},\n\t\t{\"PalettedImage\", Type, 0, \"\"},\n\t\t{\"Point\", Type, 0, \"\"},\n\t\t{\"Point.X\", Field, 0, \"\"},\n\t\t{\"Point.Y\", Field, 0, \"\"},\n\t\t{\"Pt\", Func, 0, \"func(X int, Y int) Point\"},\n\t\t{\"RGBA\", Type, 0, \"\"},\n\t\t{\"RGBA.Pix\", Field, 0, \"\"},\n\t\t{\"RGBA.Rect\", Field, 0, \"\"},\n\t\t{\"RGBA.Stride\", Field, 0, \"\"},\n\t\t{\"RGBA64\", Type, 0, \"\"},\n\t\t{\"RGBA64.Pix\", Field, 0, \"\"},\n\t\t{\"RGBA64.Rect\", Field, 0, \"\"},\n\t\t{\"RGBA64.Stride\", Field, 0, \"\"},\n\t\t{\"RGBA64Image\", Type, 17, \"\"},\n\t\t{\"Rect\", Func, 0, \"func(x0 int, y0 int, x1 int, y1 int) Rectangle\"},\n\t\t{\"Rectangle\", Type, 0, \"\"},\n\t\t{\"Rectangle.Max\", Field, 0, \"\"},\n\t\t{\"Rectangle.Min\", Field, 0, \"\"},\n\t\t{\"RegisterFormat\", Func, 0, \"func(name string, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error))\"},\n\t\t{\"Transparent\", Var, 0, \"\"},\n\t\t{\"Uniform\", Type, 0, \"\"},\n\t\t{\"Uniform.C\", Field, 0, \"\"},\n\t\t{\"White\", Var, 0, \"\"},\n\t\t{\"YCbCr\", Type, 0, \"\"},\n\t\t{\"YCbCr.CStride\", Field, 0, \"\"},\n\t\t{\"YCbCr.Cb\", Field, 0, \"\"},\n\t\t{\"YCbCr.Cr\", Field, 0, \"\"},\n\t\t{\"YCbCr.Rect\", Field, 0, \"\"},\n\t\t{\"YCbCr.SubsampleRatio\", Field, 0, \"\"},\n\t\t{\"YCbCr.Y\", Field, 0, \"\"},\n\t\t{\"YCbCr.YStride\", Field, 0, \"\"},\n\t\t{\"YCbCrSubsampleRatio\", Type, 0, \"\"},\n\t\t{\"YCbCrSubsampleRatio410\", Const, 5, \"\"},\n\t\t{\"YCbCrSubsampleRatio411\", Const, 5, \"\"},\n\t\t{\"YCbCrSubsampleRatio420\", Const, 0, \"\"},\n\t\t{\"YCbCrSubsampleRatio422\", Const, 0, \"\"},\n\t\t{\"YCbCrSubsampleRatio440\", Const, 1, \"\"},\n\t\t{\"YCbCrSubsampleRatio444\", Const, 0, \"\"},\n\t\t{\"ZP\", Var, 0, \"\"},\n\t\t{\"ZR\", Var, 0, \"\"},\n\t},\n\t\"image/color\": {\n\t\t{\"(Alpha).RGBA\", Method, 0, \"\"},\n\t\t{\"(Alpha16).RGBA\", Method, 0, \"\"},\n\t\t{\"(CMYK).RGBA\", Method, 5, \"\"},\n\t\t{\"(Color).RGBA\", Method, 0, \"\"},\n\t\t{\"(Gray).RGBA\", Method, 0, \"\"},\n\t\t{\"(Gray16).RGBA\", Method, 0, \"\"},\n\t\t{\"(Model).Convert\", Method, 0, \"\"},\n\t\t{\"(NRGBA).RGBA\", Method, 0, \"\"},\n\t\t{\"(NRGBA64).RGBA\", Method, 0, \"\"},\n\t\t{\"(NYCbCrA).RGBA\", Method, 6, \"\"},\n\t\t{\"(Palette).Convert\", Method, 0, \"\"},\n\t\t{\"(Palette).Index\", Method, 0, \"\"},\n\t\t{\"(RGBA).RGBA\", Method, 0, \"\"},\n\t\t{\"(RGBA64).RGBA\", Method, 0, \"\"},\n\t\t{\"(YCbCr).RGBA\", Method, 0, \"\"},\n\t\t{\"Alpha\", Type, 0, \"\"},\n\t\t{\"Alpha.A\", Field, 0, \"\"},\n\t\t{\"Alpha16\", Type, 0, \"\"},\n\t\t{\"Alpha16.A\", Field, 0, \"\"},\n\t\t{\"Alpha16Model\", Var, 0, \"\"},\n\t\t{\"AlphaModel\", Var, 0, \"\"},\n\t\t{\"Black\", Var, 0, \"\"},\n\t\t{\"CMYK\", Type, 5, \"\"},\n\t\t{\"CMYK.C\", Field, 5, \"\"},\n\t\t{\"CMYK.K\", Field, 5, \"\"},\n\t\t{\"CMYK.M\", Field, 5, \"\"},\n\t\t{\"CMYK.Y\", Field, 5, \"\"},\n\t\t{\"CMYKModel\", Var, 5, \"\"},\n\t\t{\"CMYKToRGB\", Func, 5, \"func(c uint8, m uint8, y uint8, k uint8) (uint8, uint8, uint8)\"},\n\t\t{\"Color\", Type, 0, \"\"},\n\t\t{\"Gray\", Type, 0, \"\"},\n\t\t{\"Gray.Y\", Field, 0, \"\"},\n\t\t{\"Gray16\", Type, 0, \"\"},\n\t\t{\"Gray16.Y\", Field, 0, \"\"},\n\t\t{\"Gray16Model\", Var, 0, \"\"},\n\t\t{\"GrayModel\", Var, 0, \"\"},\n\t\t{\"Model\", Type, 0, \"\"},\n\t\t{\"ModelFunc\", Func, 0, \"func(f func(Color) Color) Model\"},\n\t\t{\"NRGBA\", Type, 0, \"\"},\n\t\t{\"NRGBA.A\", Field, 0, \"\"},\n\t\t{\"NRGBA.B\", Field, 0, \"\"},\n\t\t{\"NRGBA.G\", Field, 0, \"\"},\n\t\t{\"NRGBA.R\", Field, 0, \"\"},\n\t\t{\"NRGBA64\", Type, 0, \"\"},\n\t\t{\"NRGBA64.A\", Field, 0, \"\"},\n\t\t{\"NRGBA64.B\", Field, 0, \"\"},\n\t\t{\"NRGBA64.G\", Field, 0, \"\"},\n\t\t{\"NRGBA64.R\", Field, 0, \"\"},\n\t\t{\"NRGBA64Model\", Var, 0, \"\"},\n\t\t{\"NRGBAModel\", Var, 0, \"\"},\n\t\t{\"NYCbCrA\", Type, 6, \"\"},\n\t\t{\"NYCbCrA.A\", Field, 6, \"\"},\n\t\t{\"NYCbCrA.YCbCr\", Field, 6, \"\"},\n\t\t{\"NYCbCrAModel\", Var, 6, \"\"},\n\t\t{\"Opaque\", Var, 0, \"\"},\n\t\t{\"Palette\", Type, 0, \"\"},\n\t\t{\"RGBA\", Type, 0, \"\"},\n\t\t{\"RGBA.A\", Field, 0, \"\"},\n\t\t{\"RGBA.B\", Field, 0, \"\"},\n\t\t{\"RGBA.G\", Field, 0, \"\"},\n\t\t{\"RGBA.R\", Field, 0, \"\"},\n\t\t{\"RGBA64\", Type, 0, \"\"},\n\t\t{\"RGBA64.A\", Field, 0, \"\"},\n\t\t{\"RGBA64.B\", Field, 0, \"\"},\n\t\t{\"RGBA64.G\", Field, 0, \"\"},\n\t\t{\"RGBA64.R\", Field, 0, \"\"},\n\t\t{\"RGBA64Model\", Var, 0, \"\"},\n\t\t{\"RGBAModel\", Var, 0, \"\"},\n\t\t{\"RGBToCMYK\", Func, 5, \"func(r uint8, g uint8, b uint8) (uint8, uint8, uint8, uint8)\"},\n\t\t{\"RGBToYCbCr\", Func, 0, \"func(r uint8, g uint8, b uint8) (uint8, uint8, uint8)\"},\n\t\t{\"Transparent\", Var, 0, \"\"},\n\t\t{\"White\", Var, 0, \"\"},\n\t\t{\"YCbCr\", Type, 0, \"\"},\n\t\t{\"YCbCr.Cb\", Field, 0, \"\"},\n\t\t{\"YCbCr.Cr\", Field, 0, \"\"},\n\t\t{\"YCbCr.Y\", Field, 0, \"\"},\n\t\t{\"YCbCrModel\", Var, 0, \"\"},\n\t\t{\"YCbCrToRGB\", Func, 0, \"func(y uint8, cb uint8, cr uint8) (uint8, uint8, uint8)\"},\n\t},\n\t\"image/color/palette\": {\n\t\t{\"Plan9\", Var, 2, \"\"},\n\t\t{\"WebSafe\", Var, 2, \"\"},\n\t},\n\t\"image/draw\": {\n\t\t{\"(Drawer).Draw\", Method, 2, \"\"},\n\t\t{\"(Image).At\", Method, 0, \"\"},\n\t\t{\"(Image).Bounds\", Method, 0, \"\"},\n\t\t{\"(Image).ColorModel\", Method, 0, \"\"},\n\t\t{\"(Image).Set\", Method, 0, \"\"},\n\t\t{\"(Op).Draw\", Method, 2, \"\"},\n\t\t{\"(Quantizer).Quantize\", Method, 2, \"\"},\n\t\t{\"(RGBA64Image).At\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).Bounds\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).ColorModel\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).RGBA64At\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).Set\", Method, 17, \"\"},\n\t\t{\"(RGBA64Image).SetRGBA64\", Method, 17, \"\"},\n\t\t{\"Draw\", Func, 0, \"func(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)\"},\n\t\t{\"DrawMask\", Func, 0, \"func(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op)\"},\n\t\t{\"Drawer\", Type, 2, \"\"},\n\t\t{\"FloydSteinberg\", Var, 2, \"\"},\n\t\t{\"Image\", Type, 0, \"\"},\n\t\t{\"Op\", Type, 0, \"\"},\n\t\t{\"Over\", Const, 0, \"\"},\n\t\t{\"Quantizer\", Type, 2, \"\"},\n\t\t{\"RGBA64Image\", Type, 17, \"\"},\n\t\t{\"Src\", Const, 0, \"\"},\n\t},\n\t\"image/gif\": {\n\t\t{\"Decode\", Func, 0, \"func(r io.Reader) (image.Image, error)\"},\n\t\t{\"DecodeAll\", Func, 0, \"func(r io.Reader) (*GIF, error)\"},\n\t\t{\"DecodeConfig\", Func, 0, \"func(r io.Reader) (image.Config, error)\"},\n\t\t{\"DisposalBackground\", Const, 5, \"\"},\n\t\t{\"DisposalNone\", Const, 5, \"\"},\n\t\t{\"DisposalPrevious\", Const, 5, \"\"},\n\t\t{\"Encode\", Func, 2, \"func(w io.Writer, m image.Image, o *Options) error\"},\n\t\t{\"EncodeAll\", Func, 2, \"func(w io.Writer, g *GIF) error\"},\n\t\t{\"GIF\", Type, 0, \"\"},\n\t\t{\"GIF.BackgroundIndex\", Field, 5, \"\"},\n\t\t{\"GIF.Config\", Field, 5, \"\"},\n\t\t{\"GIF.Delay\", Field, 0, \"\"},\n\t\t{\"GIF.Disposal\", Field, 5, \"\"},\n\t\t{\"GIF.Image\", Field, 0, \"\"},\n\t\t{\"GIF.LoopCount\", Field, 0, \"\"},\n\t\t{\"Options\", Type, 2, \"\"},\n\t\t{\"Options.Drawer\", Field, 2, \"\"},\n\t\t{\"Options.NumColors\", Field, 2, \"\"},\n\t\t{\"Options.Quantizer\", Field, 2, \"\"},\n\t},\n\t\"image/jpeg\": {\n\t\t{\"(FormatError).Error\", Method, 0, \"\"},\n\t\t{\"(Reader).Read\", Method, 0, \"\"},\n\t\t{\"(Reader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(UnsupportedError).Error\", Method, 0, \"\"},\n\t\t{\"Decode\", Func, 0, \"func(r io.Reader) (image.Image, error)\"},\n\t\t{\"DecodeConfig\", Func, 0, \"func(r io.Reader) (image.Config, error)\"},\n\t\t{\"DefaultQuality\", Const, 0, \"\"},\n\t\t{\"Encode\", Func, 0, \"func(w io.Writer, m image.Image, o *Options) error\"},\n\t\t{\"FormatError\", Type, 0, \"\"},\n\t\t{\"Options\", Type, 0, \"\"},\n\t\t{\"Options.Quality\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"UnsupportedError\", Type, 0, \"\"},\n\t},\n\t\"image/png\": {\n\t\t{\"(*Encoder).Encode\", Method, 4, \"\"},\n\t\t{\"(EncoderBufferPool).Get\", Method, 9, \"\"},\n\t\t{\"(EncoderBufferPool).Put\", Method, 9, \"\"},\n\t\t{\"(FormatError).Error\", Method, 0, \"\"},\n\t\t{\"(UnsupportedError).Error\", Method, 0, \"\"},\n\t\t{\"BestCompression\", Const, 4, \"\"},\n\t\t{\"BestSpeed\", Const, 4, \"\"},\n\t\t{\"CompressionLevel\", Type, 4, \"\"},\n\t\t{\"Decode\", Func, 0, \"func(r io.Reader) (image.Image, error)\"},\n\t\t{\"DecodeConfig\", Func, 0, \"func(r io.Reader) (image.Config, error)\"},\n\t\t{\"DefaultCompression\", Const, 4, \"\"},\n\t\t{\"Encode\", Func, 0, \"func(w io.Writer, m image.Image) error\"},\n\t\t{\"Encoder\", Type, 4, \"\"},\n\t\t{\"Encoder.BufferPool\", Field, 9, \"\"},\n\t\t{\"Encoder.CompressionLevel\", Field, 4, \"\"},\n\t\t{\"EncoderBuffer\", Type, 9, \"\"},\n\t\t{\"EncoderBufferPool\", Type, 9, \"\"},\n\t\t{\"FormatError\", Type, 0, \"\"},\n\t\t{\"NoCompression\", Const, 4, \"\"},\n\t\t{\"UnsupportedError\", Type, 0, \"\"},\n\t},\n\t\"index/suffixarray\": {\n\t\t{\"(*Index).Bytes\", Method, 0, \"\"},\n\t\t{\"(*Index).FindAllIndex\", Method, 0, \"\"},\n\t\t{\"(*Index).Lookup\", Method, 0, \"\"},\n\t\t{\"(*Index).Read\", Method, 0, \"\"},\n\t\t{\"(*Index).Write\", Method, 0, \"\"},\n\t\t{\"Index\", Type, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(data []byte) *Index\"},\n\t},\n\t\"io\": {\n\t\t{\"(*LimitedReader).Read\", Method, 0, \"\"},\n\t\t{\"(*OffsetWriter).Seek\", Method, 20, \"\"},\n\t\t{\"(*OffsetWriter).Write\", Method, 20, \"\"},\n\t\t{\"(*OffsetWriter).WriteAt\", Method, 20, \"\"},\n\t\t{\"(*PipeReader).Close\", Method, 0, \"\"},\n\t\t{\"(*PipeReader).CloseWithError\", Method, 0, \"\"},\n\t\t{\"(*PipeReader).Read\", Method, 0, \"\"},\n\t\t{\"(*PipeWriter).Close\", Method, 0, \"\"},\n\t\t{\"(*PipeWriter).CloseWithError\", Method, 0, \"\"},\n\t\t{\"(*PipeWriter).Write\", Method, 0, \"\"},\n\t\t{\"(*SectionReader).Outer\", Method, 22, \"\"},\n\t\t{\"(*SectionReader).Read\", Method, 0, \"\"},\n\t\t{\"(*SectionReader).ReadAt\", Method, 0, \"\"},\n\t\t{\"(*SectionReader).Seek\", Method, 0, \"\"},\n\t\t{\"(*SectionReader).Size\", Method, 0, \"\"},\n\t\t{\"(ByteReader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(ByteScanner).ReadByte\", Method, 0, \"\"},\n\t\t{\"(ByteScanner).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(ByteWriter).WriteByte\", Method, 1, \"\"},\n\t\t{\"(Closer).Close\", Method, 0, \"\"},\n\t\t{\"(ReadCloser).Close\", Method, 0, \"\"},\n\t\t{\"(ReadCloser).Read\", Method, 0, \"\"},\n\t\t{\"(ReadSeekCloser).Close\", Method, 16, \"\"},\n\t\t{\"(ReadSeekCloser).Read\", Method, 16, \"\"},\n\t\t{\"(ReadSeekCloser).Seek\", Method, 16, \"\"},\n\t\t{\"(ReadSeeker).Read\", Method, 0, \"\"},\n\t\t{\"(ReadSeeker).Seek\", Method, 0, \"\"},\n\t\t{\"(ReadWriteCloser).Close\", Method, 0, \"\"},\n\t\t{\"(ReadWriteCloser).Read\", Method, 0, \"\"},\n\t\t{\"(ReadWriteCloser).Write\", Method, 0, \"\"},\n\t\t{\"(ReadWriteSeeker).Read\", Method, 0, \"\"},\n\t\t{\"(ReadWriteSeeker).Seek\", Method, 0, \"\"},\n\t\t{\"(ReadWriteSeeker).Write\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Read\", Method, 0, \"\"},\n\t\t{\"(ReadWriter).Write\", Method, 0, \"\"},\n\t\t{\"(Reader).Read\", Method, 0, \"\"},\n\t\t{\"(ReaderAt).ReadAt\", Method, 0, \"\"},\n\t\t{\"(ReaderFrom).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(RuneReader).ReadRune\", Method, 0, \"\"},\n\t\t{\"(RuneScanner).ReadRune\", Method, 0, \"\"},\n\t\t{\"(RuneScanner).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(Seeker).Seek\", Method, 0, \"\"},\n\t\t{\"(StringWriter).WriteString\", Method, 12, \"\"},\n\t\t{\"(WriteCloser).Close\", Method, 0, \"\"},\n\t\t{\"(WriteCloser).Write\", Method, 0, \"\"},\n\t\t{\"(WriteSeeker).Seek\", Method, 0, \"\"},\n\t\t{\"(WriteSeeker).Write\", Method, 0, \"\"},\n\t\t{\"(Writer).Write\", Method, 0, \"\"},\n\t\t{\"(WriterAt).WriteAt\", Method, 0, \"\"},\n\t\t{\"(WriterTo).WriteTo\", Method, 0, \"\"},\n\t\t{\"ByteReader\", Type, 0, \"\"},\n\t\t{\"ByteScanner\", Type, 0, \"\"},\n\t\t{\"ByteWriter\", Type, 1, \"\"},\n\t\t{\"Closer\", Type, 0, \"\"},\n\t\t{\"Copy\", Func, 0, \"func(dst Writer, src Reader) (written int64, err error)\"},\n\t\t{\"CopyBuffer\", Func, 5, \"func(dst Writer, src Reader, buf []byte) (written int64, err error)\"},\n\t\t{\"CopyN\", Func, 0, \"func(dst Writer, src Reader, n int64) (written int64, err error)\"},\n\t\t{\"Discard\", Var, 16, \"\"},\n\t\t{\"EOF\", Var, 0, \"\"},\n\t\t{\"ErrClosedPipe\", Var, 0, \"\"},\n\t\t{\"ErrNoProgress\", Var, 1, \"\"},\n\t\t{\"ErrShortBuffer\", Var, 0, \"\"},\n\t\t{\"ErrShortWrite\", Var, 0, \"\"},\n\t\t{\"ErrUnexpectedEOF\", Var, 0, \"\"},\n\t\t{\"LimitReader\", Func, 0, \"func(r Reader, n int64) Reader\"},\n\t\t{\"LimitedReader\", Type, 0, \"\"},\n\t\t{\"LimitedReader.N\", Field, 0, \"\"},\n\t\t{\"LimitedReader.R\", Field, 0, \"\"},\n\t\t{\"MultiReader\", Func, 0, \"func(readers ...Reader) Reader\"},\n\t\t{\"MultiWriter\", Func, 0, \"func(writers ...Writer) Writer\"},\n\t\t{\"NewOffsetWriter\", Func, 20, \"func(w WriterAt, off int64) *OffsetWriter\"},\n\t\t{\"NewSectionReader\", Func, 0, \"func(r ReaderAt, off int64, n int64) *SectionReader\"},\n\t\t{\"NopCloser\", Func, 16, \"func(r Reader) ReadCloser\"},\n\t\t{\"OffsetWriter\", Type, 20, \"\"},\n\t\t{\"Pipe\", Func, 0, \"func() (*PipeReader, *PipeWriter)\"},\n\t\t{\"PipeReader\", Type, 0, \"\"},\n\t\t{\"PipeWriter\", Type, 0, \"\"},\n\t\t{\"ReadAll\", Func, 16, \"func(r Reader) ([]byte, error)\"},\n\t\t{\"ReadAtLeast\", Func, 0, \"func(r Reader, buf []byte, min int) (n int, err error)\"},\n\t\t{\"ReadCloser\", Type, 0, \"\"},\n\t\t{\"ReadFull\", Func, 0, \"func(r Reader, buf []byte) (n int, err error)\"},\n\t\t{\"ReadSeekCloser\", Type, 16, \"\"},\n\t\t{\"ReadSeeker\", Type, 0, \"\"},\n\t\t{\"ReadWriteCloser\", Type, 0, \"\"},\n\t\t{\"ReadWriteSeeker\", Type, 0, \"\"},\n\t\t{\"ReadWriter\", Type, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"ReaderAt\", Type, 0, \"\"},\n\t\t{\"ReaderFrom\", Type, 0, \"\"},\n\t\t{\"RuneReader\", Type, 0, \"\"},\n\t\t{\"RuneScanner\", Type, 0, \"\"},\n\t\t{\"SectionReader\", Type, 0, \"\"},\n\t\t{\"SeekCurrent\", Const, 7, \"\"},\n\t\t{\"SeekEnd\", Const, 7, \"\"},\n\t\t{\"SeekStart\", Const, 7, \"\"},\n\t\t{\"Seeker\", Type, 0, \"\"},\n\t\t{\"StringWriter\", Type, 12, \"\"},\n\t\t{\"TeeReader\", Func, 0, \"func(r Reader, w Writer) Reader\"},\n\t\t{\"WriteCloser\", Type, 0, \"\"},\n\t\t{\"WriteSeeker\", Type, 0, \"\"},\n\t\t{\"WriteString\", Func, 0, \"func(w Writer, s string) (n int, err error)\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t\t{\"WriterAt\", Type, 0, \"\"},\n\t\t{\"WriterTo\", Type, 0, \"\"},\n\t},\n\t\"io/fs\": {\n\t\t{\"(*PathError).Error\", Method, 16, \"\"},\n\t\t{\"(*PathError).Timeout\", Method, 16, \"\"},\n\t\t{\"(*PathError).Unwrap\", Method, 16, \"\"},\n\t\t{\"(DirEntry).Info\", Method, 16, \"\"},\n\t\t{\"(DirEntry).IsDir\", Method, 16, \"\"},\n\t\t{\"(DirEntry).Name\", Method, 16, \"\"},\n\t\t{\"(DirEntry).Type\", Method, 16, \"\"},\n\t\t{\"(FS).Open\", Method, 16, \"\"},\n\t\t{\"(File).Close\", Method, 16, \"\"},\n\t\t{\"(File).Read\", Method, 16, \"\"},\n\t\t{\"(File).Stat\", Method, 16, \"\"},\n\t\t{\"(FileInfo).IsDir\", Method, 16, \"\"},\n\t\t{\"(FileInfo).ModTime\", Method, 16, \"\"},\n\t\t{\"(FileInfo).Mode\", Method, 16, \"\"},\n\t\t{\"(FileInfo).Name\", Method, 16, \"\"},\n\t\t{\"(FileInfo).Size\", Method, 16, \"\"},\n\t\t{\"(FileInfo).Sys\", Method, 16, \"\"},\n\t\t{\"(FileMode).IsDir\", Method, 16, \"\"},\n\t\t{\"(FileMode).IsRegular\", Method, 16, \"\"},\n\t\t{\"(FileMode).Perm\", Method, 16, \"\"},\n\t\t{\"(FileMode).String\", Method, 16, \"\"},\n\t\t{\"(FileMode).Type\", Method, 16, \"\"},\n\t\t{\"(GlobFS).Glob\", Method, 16, \"\"},\n\t\t{\"(GlobFS).Open\", Method, 16, \"\"},\n\t\t{\"(ReadDirFS).Open\", Method, 16, \"\"},\n\t\t{\"(ReadDirFS).ReadDir\", Method, 16, \"\"},\n\t\t{\"(ReadDirFile).Close\", Method, 16, \"\"},\n\t\t{\"(ReadDirFile).Read\", Method, 16, \"\"},\n\t\t{\"(ReadDirFile).ReadDir\", Method, 16, \"\"},\n\t\t{\"(ReadDirFile).Stat\", Method, 16, \"\"},\n\t\t{\"(ReadFileFS).Open\", Method, 16, \"\"},\n\t\t{\"(ReadFileFS).ReadFile\", Method, 16, \"\"},\n\t\t{\"(ReadLinkFS).Lstat\", Method, 25, \"\"},\n\t\t{\"(ReadLinkFS).Open\", Method, 25, \"\"},\n\t\t{\"(ReadLinkFS).ReadLink\", Method, 25, \"\"},\n\t\t{\"(StatFS).Open\", Method, 16, \"\"},\n\t\t{\"(StatFS).Stat\", Method, 16, \"\"},\n\t\t{\"(SubFS).Open\", Method, 16, \"\"},\n\t\t{\"(SubFS).Sub\", Method, 16, \"\"},\n\t\t{\"DirEntry\", Type, 16, \"\"},\n\t\t{\"ErrClosed\", Var, 16, \"\"},\n\t\t{\"ErrExist\", Var, 16, \"\"},\n\t\t{\"ErrInvalid\", Var, 16, \"\"},\n\t\t{\"ErrNotExist\", Var, 16, \"\"},\n\t\t{\"ErrPermission\", Var, 16, \"\"},\n\t\t{\"FS\", Type, 16, \"\"},\n\t\t{\"File\", Type, 16, \"\"},\n\t\t{\"FileInfo\", Type, 16, \"\"},\n\t\t{\"FileInfoToDirEntry\", Func, 17, \"func(info FileInfo) DirEntry\"},\n\t\t{\"FileMode\", Type, 16, \"\"},\n\t\t{\"FormatDirEntry\", Func, 21, \"func(dir DirEntry) string\"},\n\t\t{\"FormatFileInfo\", Func, 21, \"func(info FileInfo) string\"},\n\t\t{\"Glob\", Func, 16, \"func(fsys FS, pattern string) (matches []string, err error)\"},\n\t\t{\"GlobFS\", Type, 16, \"\"},\n\t\t{\"Lstat\", Func, 25, \"func(fsys FS, name string) (FileInfo, error)\"},\n\t\t{\"ModeAppend\", Const, 16, \"\"},\n\t\t{\"ModeCharDevice\", Const, 16, \"\"},\n\t\t{\"ModeDevice\", Const, 16, \"\"},\n\t\t{\"ModeDir\", Const, 16, \"\"},\n\t\t{\"ModeExclusive\", Const, 16, \"\"},\n\t\t{\"ModeIrregular\", Const, 16, \"\"},\n\t\t{\"ModeNamedPipe\", Const, 16, \"\"},\n\t\t{\"ModePerm\", Const, 16, \"\"},\n\t\t{\"ModeSetgid\", Const, 16, \"\"},\n\t\t{\"ModeSetuid\", Const, 16, \"\"},\n\t\t{\"ModeSocket\", Const, 16, \"\"},\n\t\t{\"ModeSticky\", Const, 16, \"\"},\n\t\t{\"ModeSymlink\", Const, 16, \"\"},\n\t\t{\"ModeTemporary\", Const, 16, \"\"},\n\t\t{\"ModeType\", Const, 16, \"\"},\n\t\t{\"PathError\", Type, 16, \"\"},\n\t\t{\"PathError.Err\", Field, 16, \"\"},\n\t\t{\"PathError.Op\", Field, 16, \"\"},\n\t\t{\"PathError.Path\", Field, 16, \"\"},\n\t\t{\"ReadDir\", Func, 16, \"func(fsys FS, name string) ([]DirEntry, error)\"},\n\t\t{\"ReadDirFS\", Type, 16, \"\"},\n\t\t{\"ReadDirFile\", Type, 16, \"\"},\n\t\t{\"ReadFile\", Func, 16, \"func(fsys FS, name string) ([]byte, error)\"},\n\t\t{\"ReadFileFS\", Type, 16, \"\"},\n\t\t{\"ReadLink\", Func, 25, \"func(fsys FS, name string) (string, error)\"},\n\t\t{\"ReadLinkFS\", Type, 25, \"\"},\n\t\t{\"SkipAll\", Var, 20, \"\"},\n\t\t{\"SkipDir\", Var, 16, \"\"},\n\t\t{\"Stat\", Func, 16, \"func(fsys FS, name string) (FileInfo, error)\"},\n\t\t{\"StatFS\", Type, 16, \"\"},\n\t\t{\"Sub\", Func, 16, \"func(fsys FS, dir string) (FS, error)\"},\n\t\t{\"SubFS\", Type, 16, \"\"},\n\t\t{\"ValidPath\", Func, 16, \"func(name string) bool\"},\n\t\t{\"WalkDir\", Func, 16, \"func(fsys FS, root string, fn WalkDirFunc) error\"},\n\t\t{\"WalkDirFunc\", Type, 16, \"\"},\n\t},\n\t\"io/ioutil\": {\n\t\t{\"Discard\", Var, 0, \"\"},\n\t\t{\"NopCloser\", Func, 0, \"func(r io.Reader) io.ReadCloser\"},\n\t\t{\"ReadAll\", Func, 0, \"func(r io.Reader) ([]byte, error)\"},\n\t\t{\"ReadDir\", Func, 0, \"func(dirname string) ([]fs.FileInfo, error)\"},\n\t\t{\"ReadFile\", Func, 0, \"func(filename string) ([]byte, error)\"},\n\t\t{\"TempDir\", Func, 0, \"func(dir string, pattern string) (name string, err error)\"},\n\t\t{\"TempFile\", Func, 0, \"func(dir string, pattern string) (f *os.File, err error)\"},\n\t\t{\"WriteFile\", Func, 0, \"func(filename string, data []byte, perm fs.FileMode) error\"},\n\t},\n\t\"iter\": {\n\t\t{\"Pull\", Func, 23, \"func[V any](seq Seq[V]) (next func() (V, bool), stop func())\"},\n\t\t{\"Pull2\", Func, 23, \"func[K, V any](seq Seq2[K, V]) (next func() (K, V, bool), stop func())\"},\n\t\t{\"Seq\", Type, 23, \"\"},\n\t\t{\"Seq2\", Type, 23, \"\"},\n\t},\n\t\"log\": {\n\t\t{\"(*Logger).Fatal\", Method, 0, \"\"},\n\t\t{\"(*Logger).Fatalf\", Method, 0, \"\"},\n\t\t{\"(*Logger).Fatalln\", Method, 0, \"\"},\n\t\t{\"(*Logger).Flags\", Method, 0, \"\"},\n\t\t{\"(*Logger).Output\", Method, 0, \"\"},\n\t\t{\"(*Logger).Panic\", Method, 0, \"\"},\n\t\t{\"(*Logger).Panicf\", Method, 0, \"\"},\n\t\t{\"(*Logger).Panicln\", Method, 0, \"\"},\n\t\t{\"(*Logger).Prefix\", Method, 0, \"\"},\n\t\t{\"(*Logger).Print\", Method, 0, \"\"},\n\t\t{\"(*Logger).Printf\", Method, 0, \"\"},\n\t\t{\"(*Logger).Println\", Method, 0, \"\"},\n\t\t{\"(*Logger).SetFlags\", Method, 0, \"\"},\n\t\t{\"(*Logger).SetOutput\", Method, 5, \"\"},\n\t\t{\"(*Logger).SetPrefix\", Method, 0, \"\"},\n\t\t{\"(*Logger).Writer\", Method, 12, \"\"},\n\t\t{\"Default\", Func, 16, \"func() *Logger\"},\n\t\t{\"Fatal\", Func, 0, \"func(v ...any)\"},\n\t\t{\"Fatalf\", Func, 0, \"func(format string, v ...any)\"},\n\t\t{\"Fatalln\", Func, 0, \"func(v ...any)\"},\n\t\t{\"Flags\", Func, 0, \"func() int\"},\n\t\t{\"LUTC\", Const, 5, \"\"},\n\t\t{\"Ldate\", Const, 0, \"\"},\n\t\t{\"Llongfile\", Const, 0, \"\"},\n\t\t{\"Lmicroseconds\", Const, 0, \"\"},\n\t\t{\"Lmsgprefix\", Const, 14, \"\"},\n\t\t{\"Logger\", Type, 0, \"\"},\n\t\t{\"Lshortfile\", Const, 0, \"\"},\n\t\t{\"LstdFlags\", Const, 0, \"\"},\n\t\t{\"Ltime\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(out io.Writer, prefix string, flag int) *Logger\"},\n\t\t{\"Output\", Func, 5, \"func(calldepth int, s string) error\"},\n\t\t{\"Panic\", Func, 0, \"func(v ...any)\"},\n\t\t{\"Panicf\", Func, 0, \"func(format string, v ...any)\"},\n\t\t{\"Panicln\", Func, 0, \"func(v ...any)\"},\n\t\t{\"Prefix\", Func, 0, \"func() string\"},\n\t\t{\"Print\", Func, 0, \"func(v ...any)\"},\n\t\t{\"Printf\", Func, 0, \"func(format string, v ...any)\"},\n\t\t{\"Println\", Func, 0, \"func(v ...any)\"},\n\t\t{\"SetFlags\", Func, 0, \"func(flag int)\"},\n\t\t{\"SetOutput\", Func, 0, \"func(w io.Writer)\"},\n\t\t{\"SetPrefix\", Func, 0, \"func(prefix string)\"},\n\t\t{\"Writer\", Func, 13, \"func() io.Writer\"},\n\t},\n\t\"log/slog\": {\n\t\t{\"(*JSONHandler).Enabled\", Method, 21, \"\"},\n\t\t{\"(*JSONHandler).Handle\", Method, 21, \"\"},\n\t\t{\"(*JSONHandler).WithAttrs\", Method, 21, \"\"},\n\t\t{\"(*JSONHandler).WithGroup\", Method, 21, \"\"},\n\t\t{\"(*Level).UnmarshalJSON\", Method, 21, \"\"},\n\t\t{\"(*Level).UnmarshalText\", Method, 21, \"\"},\n\t\t{\"(*LevelVar).AppendText\", Method, 24, \"\"},\n\t\t{\"(*LevelVar).Level\", Method, 21, \"\"},\n\t\t{\"(*LevelVar).MarshalText\", Method, 21, \"\"},\n\t\t{\"(*LevelVar).Set\", Method, 21, \"\"},\n\t\t{\"(*LevelVar).String\", Method, 21, \"\"},\n\t\t{\"(*LevelVar).UnmarshalText\", Method, 21, \"\"},\n\t\t{\"(*Logger).Debug\", Method, 21, \"\"},\n\t\t{\"(*Logger).DebugContext\", Method, 21, \"\"},\n\t\t{\"(*Logger).Enabled\", Method, 21, \"\"},\n\t\t{\"(*Logger).Error\", Method, 21, \"\"},\n\t\t{\"(*Logger).ErrorContext\", Method, 21, \"\"},\n\t\t{\"(*Logger).Handler\", Method, 21, \"\"},\n\t\t{\"(*Logger).Info\", Method, 21, \"\"},\n\t\t{\"(*Logger).InfoContext\", Method, 21, \"\"},\n\t\t{\"(*Logger).Log\", Method, 21, \"\"},\n\t\t{\"(*Logger).LogAttrs\", Method, 21, \"\"},\n\t\t{\"(*Logger).Warn\", Method, 21, \"\"},\n\t\t{\"(*Logger).WarnContext\", Method, 21, \"\"},\n\t\t{\"(*Logger).With\", Method, 21, \"\"},\n\t\t{\"(*Logger).WithGroup\", Method, 21, \"\"},\n\t\t{\"(*MultiHandler).Enabled\", Method, 26, \"\"},\n\t\t{\"(*MultiHandler).Handle\", Method, 26, \"\"},\n\t\t{\"(*MultiHandler).WithAttrs\", Method, 26, \"\"},\n\t\t{\"(*MultiHandler).WithGroup\", Method, 26, \"\"},\n\t\t{\"(*Record).Add\", Method, 21, \"\"},\n\t\t{\"(*Record).AddAttrs\", Method, 21, \"\"},\n\t\t{\"(*TextHandler).Enabled\", Method, 21, \"\"},\n\t\t{\"(*TextHandler).Handle\", Method, 21, \"\"},\n\t\t{\"(*TextHandler).WithAttrs\", Method, 21, \"\"},\n\t\t{\"(*TextHandler).WithGroup\", Method, 21, \"\"},\n\t\t{\"(Attr).Equal\", Method, 21, \"\"},\n\t\t{\"(Attr).String\", Method, 21, \"\"},\n\t\t{\"(Handler).Enabled\", Method, 21, \"\"},\n\t\t{\"(Handler).Handle\", Method, 21, \"\"},\n\t\t{\"(Handler).WithAttrs\", Method, 21, \"\"},\n\t\t{\"(Handler).WithGroup\", Method, 21, \"\"},\n\t\t{\"(Kind).String\", Method, 21, \"\"},\n\t\t{\"(Level).AppendText\", Method, 24, \"\"},\n\t\t{\"(Level).Level\", Method, 21, \"\"},\n\t\t{\"(Level).MarshalJSON\", Method, 21, \"\"},\n\t\t{\"(Level).MarshalText\", Method, 21, \"\"},\n\t\t{\"(Level).String\", Method, 21, \"\"},\n\t\t{\"(Leveler).Level\", Method, 21, \"\"},\n\t\t{\"(LogValuer).LogValue\", Method, 21, \"\"},\n\t\t{\"(Record).Attrs\", Method, 21, \"\"},\n\t\t{\"(Record).Clone\", Method, 21, \"\"},\n\t\t{\"(Record).NumAttrs\", Method, 21, \"\"},\n\t\t{\"(Record).Source\", Method, 25, \"\"},\n\t\t{\"(Value).Any\", Method, 21, \"\"},\n\t\t{\"(Value).Bool\", Method, 21, \"\"},\n\t\t{\"(Value).Duration\", Method, 21, \"\"},\n\t\t{\"(Value).Equal\", Method, 21, \"\"},\n\t\t{\"(Value).Float64\", Method, 21, \"\"},\n\t\t{\"(Value).Group\", Method, 21, \"\"},\n\t\t{\"(Value).Int64\", Method, 21, \"\"},\n\t\t{\"(Value).Kind\", Method, 21, \"\"},\n\t\t{\"(Value).LogValuer\", Method, 21, \"\"},\n\t\t{\"(Value).Resolve\", Method, 21, \"\"},\n\t\t{\"(Value).String\", Method, 21, \"\"},\n\t\t{\"(Value).Time\", Method, 21, \"\"},\n\t\t{\"(Value).Uint64\", Method, 21, \"\"},\n\t\t{\"Any\", Func, 21, \"func(key string, value any) Attr\"},\n\t\t{\"AnyValue\", Func, 21, \"func(v any) Value\"},\n\t\t{\"Attr\", Type, 21, \"\"},\n\t\t{\"Attr.Key\", Field, 21, \"\"},\n\t\t{\"Attr.Value\", Field, 21, \"\"},\n\t\t{\"Bool\", Func, 21, \"func(key string, v bool) Attr\"},\n\t\t{\"BoolValue\", Func, 21, \"func(v bool) Value\"},\n\t\t{\"Debug\", Func, 21, \"func(msg string, args ...any)\"},\n\t\t{\"DebugContext\", Func, 21, \"func(ctx context.Context, msg string, args ...any)\"},\n\t\t{\"Default\", Func, 21, \"func() *Logger\"},\n\t\t{\"DiscardHandler\", Var, 24, \"\"},\n\t\t{\"Duration\", Func, 21, \"func(key string, v time.Duration) Attr\"},\n\t\t{\"DurationValue\", Func, 21, \"func(v time.Duration) Value\"},\n\t\t{\"Error\", Func, 21, \"func(msg string, args ...any)\"},\n\t\t{\"ErrorContext\", Func, 21, \"func(ctx context.Context, msg string, args ...any)\"},\n\t\t{\"Float64\", Func, 21, \"func(key string, v float64) Attr\"},\n\t\t{\"Float64Value\", Func, 21, \"func(v float64) Value\"},\n\t\t{\"Group\", Func, 21, \"func(key string, args ...any) Attr\"},\n\t\t{\"GroupAttrs\", Func, 25, \"func(key string, attrs ...Attr) Attr\"},\n\t\t{\"GroupValue\", Func, 21, \"func(as ...Attr) Value\"},\n\t\t{\"Handler\", Type, 21, \"\"},\n\t\t{\"HandlerOptions\", Type, 21, \"\"},\n\t\t{\"HandlerOptions.AddSource\", Field, 21, \"\"},\n\t\t{\"HandlerOptions.Level\", Field, 21, \"\"},\n\t\t{\"HandlerOptions.ReplaceAttr\", Field, 21, \"\"},\n\t\t{\"Info\", Func, 21, \"func(msg string, args ...any)\"},\n\t\t{\"InfoContext\", Func, 21, \"func(ctx context.Context, msg string, args ...any)\"},\n\t\t{\"Int\", Func, 21, \"func(key string, value int) Attr\"},\n\t\t{\"Int64\", Func, 21, \"func(key string, value int64) Attr\"},\n\t\t{\"Int64Value\", Func, 21, \"func(v int64) Value\"},\n\t\t{\"IntValue\", Func, 21, \"func(v int) Value\"},\n\t\t{\"JSONHandler\", Type, 21, \"\"},\n\t\t{\"Kind\", Type, 21, \"\"},\n\t\t{\"KindAny\", Const, 21, \"\"},\n\t\t{\"KindBool\", Const, 21, \"\"},\n\t\t{\"KindDuration\", Const, 21, \"\"},\n\t\t{\"KindFloat64\", Const, 21, \"\"},\n\t\t{\"KindGroup\", Const, 21, \"\"},\n\t\t{\"KindInt64\", Const, 21, \"\"},\n\t\t{\"KindLogValuer\", Const, 21, \"\"},\n\t\t{\"KindString\", Const, 21, \"\"},\n\t\t{\"KindTime\", Const, 21, \"\"},\n\t\t{\"KindUint64\", Const, 21, \"\"},\n\t\t{\"Level\", Type, 21, \"\"},\n\t\t{\"LevelDebug\", Const, 21, \"\"},\n\t\t{\"LevelError\", Const, 21, \"\"},\n\t\t{\"LevelInfo\", Const, 21, \"\"},\n\t\t{\"LevelKey\", Const, 21, \"\"},\n\t\t{\"LevelVar\", Type, 21, \"\"},\n\t\t{\"LevelWarn\", Const, 21, \"\"},\n\t\t{\"Leveler\", Type, 21, \"\"},\n\t\t{\"Log\", Func, 21, \"func(ctx context.Context, level Level, msg string, args ...any)\"},\n\t\t{\"LogAttrs\", Func, 21, \"func(ctx context.Context, level Level, msg string, attrs ...Attr)\"},\n\t\t{\"LogValuer\", Type, 21, \"\"},\n\t\t{\"Logger\", Type, 21, \"\"},\n\t\t{\"MessageKey\", Const, 21, \"\"},\n\t\t{\"MultiHandler\", Type, 26, \"\"},\n\t\t{\"New\", Func, 21, \"func(h Handler) *Logger\"},\n\t\t{\"NewJSONHandler\", Func, 21, \"func(w io.Writer, opts *HandlerOptions) *JSONHandler\"},\n\t\t{\"NewLogLogger\", Func, 21, \"func(h Handler, level Level) *log.Logger\"},\n\t\t{\"NewMultiHandler\", Func, 26, \"func(handlers ...Handler) *MultiHandler\"},\n\t\t{\"NewRecord\", Func, 21, \"func(t time.Time, level Level, msg string, pc uintptr) Record\"},\n\t\t{\"NewTextHandler\", Func, 21, \"func(w io.Writer, opts *HandlerOptions) *TextHandler\"},\n\t\t{\"Record\", Type, 21, \"\"},\n\t\t{\"Record.Level\", Field, 21, \"\"},\n\t\t{\"Record.Message\", Field, 21, \"\"},\n\t\t{\"Record.PC\", Field, 21, \"\"},\n\t\t{\"Record.Time\", Field, 21, \"\"},\n\t\t{\"SetDefault\", Func, 21, \"func(l *Logger)\"},\n\t\t{\"SetLogLoggerLevel\", Func, 22, \"func(level Level) (oldLevel Level)\"},\n\t\t{\"Source\", Type, 21, \"\"},\n\t\t{\"Source.File\", Field, 21, \"\"},\n\t\t{\"Source.Function\", Field, 21, \"\"},\n\t\t{\"Source.Line\", Field, 21, \"\"},\n\t\t{\"SourceKey\", Const, 21, \"\"},\n\t\t{\"String\", Func, 21, \"func(key string, value string) Attr\"},\n\t\t{\"StringValue\", Func, 21, \"func(value string) Value\"},\n\t\t{\"TextHandler\", Type, 21, \"\"},\n\t\t{\"Time\", Func, 21, \"func(key string, v time.Time) Attr\"},\n\t\t{\"TimeKey\", Const, 21, \"\"},\n\t\t{\"TimeValue\", Func, 21, \"func(v time.Time) Value\"},\n\t\t{\"Uint64\", Func, 21, \"func(key string, v uint64) Attr\"},\n\t\t{\"Uint64Value\", Func, 21, \"func(v uint64) Value\"},\n\t\t{\"Value\", Type, 21, \"\"},\n\t\t{\"Warn\", Func, 21, \"func(msg string, args ...any)\"},\n\t\t{\"WarnContext\", Func, 21, \"func(ctx context.Context, msg string, args ...any)\"},\n\t\t{\"With\", Func, 21, \"func(args ...any) *Logger\"},\n\t},\n\t\"log/syslog\": {\n\t\t{\"(*Writer).Alert\", Method, 0, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).Crit\", Method, 0, \"\"},\n\t\t{\"(*Writer).Debug\", Method, 0, \"\"},\n\t\t{\"(*Writer).Emerg\", Method, 0, \"\"},\n\t\t{\"(*Writer).Err\", Method, 0, \"\"},\n\t\t{\"(*Writer).Info\", Method, 0, \"\"},\n\t\t{\"(*Writer).Notice\", Method, 0, \"\"},\n\t\t{\"(*Writer).Warning\", Method, 0, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(network string, raddr string, priority Priority, tag string) (*Writer, error)\"},\n\t\t{\"LOG_ALERT\", Const, 0, \"\"},\n\t\t{\"LOG_AUTH\", Const, 1, \"\"},\n\t\t{\"LOG_AUTHPRIV\", Const, 1, \"\"},\n\t\t{\"LOG_CRIT\", Const, 0, \"\"},\n\t\t{\"LOG_CRON\", Const, 1, \"\"},\n\t\t{\"LOG_DAEMON\", Const, 1, \"\"},\n\t\t{\"LOG_DEBUG\", Const, 0, \"\"},\n\t\t{\"LOG_EMERG\", Const, 0, \"\"},\n\t\t{\"LOG_ERR\", Const, 0, \"\"},\n\t\t{\"LOG_FTP\", Const, 1, \"\"},\n\t\t{\"LOG_INFO\", Const, 0, \"\"},\n\t\t{\"LOG_KERN\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL0\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL1\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL2\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL3\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL4\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL5\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL6\", Const, 1, \"\"},\n\t\t{\"LOG_LOCAL7\", Const, 1, \"\"},\n\t\t{\"LOG_LPR\", Const, 1, \"\"},\n\t\t{\"LOG_MAIL\", Const, 1, \"\"},\n\t\t{\"LOG_NEWS\", Const, 1, \"\"},\n\t\t{\"LOG_NOTICE\", Const, 0, \"\"},\n\t\t{\"LOG_SYSLOG\", Const, 1, \"\"},\n\t\t{\"LOG_USER\", Const, 1, \"\"},\n\t\t{\"LOG_UUCP\", Const, 1, \"\"},\n\t\t{\"LOG_WARNING\", Const, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(priority Priority, tag string) (*Writer, error)\"},\n\t\t{\"NewLogger\", Func, 0, \"func(p Priority, logFlag int) (*log.Logger, error)\"},\n\t\t{\"Priority\", Type, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"maps\": {\n\t\t{\"All\", Func, 23, \"func[Map ~map[K]V, K comparable, V any](m Map) iter.Seq2[K, V]\"},\n\t\t{\"Clone\", Func, 21, \"func[M ~map[K]V, K comparable, V any](m M) M\"},\n\t\t{\"Collect\", Func, 23, \"func[K comparable, V any](seq iter.Seq2[K, V]) map[K]V\"},\n\t\t{\"Copy\", Func, 21, \"func[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2)\"},\n\t\t{\"DeleteFunc\", Func, 21, \"func[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool)\"},\n\t\t{\"Equal\", Func, 21, \"func[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool\"},\n\t\t{\"EqualFunc\", Func, 21, \"func[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool\"},\n\t\t{\"Insert\", Func, 23, \"func[Map ~map[K]V, K comparable, V any](m Map, seq iter.Seq2[K, V])\"},\n\t\t{\"Keys\", Func, 23, \"func[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K]\"},\n\t\t{\"Values\", Func, 23, \"func[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[V]\"},\n\t},\n\t\"math\": {\n\t\t{\"Abs\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Acos\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Acosh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Asin\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Asinh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Atan\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Atan2\", Func, 0, \"func(y float64, x float64) float64\"},\n\t\t{\"Atanh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Cbrt\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Ceil\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Copysign\", Func, 0, \"func(f float64, sign float64) float64\"},\n\t\t{\"Cos\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Cosh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Dim\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"E\", Const, 0, \"\"},\n\t\t{\"Erf\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Erfc\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Erfcinv\", Func, 10, \"func(x float64) float64\"},\n\t\t{\"Erfinv\", Func, 10, \"func(x float64) float64\"},\n\t\t{\"Exp\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Exp2\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Expm1\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"FMA\", Func, 14, \"func(x float64, y float64, z float64) float64\"},\n\t\t{\"Float32bits\", Func, 0, \"func(f float32) uint32\"},\n\t\t{\"Float32frombits\", Func, 0, \"func(b uint32) float32\"},\n\t\t{\"Float64bits\", Func, 0, \"func(f float64) uint64\"},\n\t\t{\"Float64frombits\", Func, 0, \"func(b uint64) float64\"},\n\t\t{\"Floor\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Frexp\", Func, 0, \"func(f float64) (frac float64, exp int)\"},\n\t\t{\"Gamma\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Hypot\", Func, 0, \"func(p float64, q float64) float64\"},\n\t\t{\"Ilogb\", Func, 0, \"func(x float64) int\"},\n\t\t{\"Inf\", Func, 0, \"func(sign int) float64\"},\n\t\t{\"IsInf\", Func, 0, \"func(f float64, sign int) bool\"},\n\t\t{\"IsNaN\", Func, 0, \"func(f float64) (is bool)\"},\n\t\t{\"J0\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"J1\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Jn\", Func, 0, \"func(n int, x float64) float64\"},\n\t\t{\"Ldexp\", Func, 0, \"func(frac float64, exp int) float64\"},\n\t\t{\"Lgamma\", Func, 0, \"func(x float64) (lgamma float64, sign int)\"},\n\t\t{\"Ln10\", Const, 0, \"\"},\n\t\t{\"Ln2\", Const, 0, \"\"},\n\t\t{\"Log\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Log10\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Log10E\", Const, 0, \"\"},\n\t\t{\"Log1p\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Log2\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Log2E\", Const, 0, \"\"},\n\t\t{\"Logb\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Max\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"MaxFloat32\", Const, 0, \"\"},\n\t\t{\"MaxFloat64\", Const, 0, \"\"},\n\t\t{\"MaxInt\", Const, 17, \"\"},\n\t\t{\"MaxInt16\", Const, 0, \"\"},\n\t\t{\"MaxInt32\", Const, 0, \"\"},\n\t\t{\"MaxInt64\", Const, 0, \"\"},\n\t\t{\"MaxInt8\", Const, 0, \"\"},\n\t\t{\"MaxUint\", Const, 17, \"\"},\n\t\t{\"MaxUint16\", Const, 0, \"\"},\n\t\t{\"MaxUint32\", Const, 0, \"\"},\n\t\t{\"MaxUint64\", Const, 0, \"\"},\n\t\t{\"MaxUint8\", Const, 0, \"\"},\n\t\t{\"Min\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"MinInt\", Const, 17, \"\"},\n\t\t{\"MinInt16\", Const, 0, \"\"},\n\t\t{\"MinInt32\", Const, 0, \"\"},\n\t\t{\"MinInt64\", Const, 0, \"\"},\n\t\t{\"MinInt8\", Const, 0, \"\"},\n\t\t{\"Mod\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"Modf\", Func, 0, \"func(f float64) (integer float64, fractional float64)\"},\n\t\t{\"NaN\", Func, 0, \"func() float64\"},\n\t\t{\"Nextafter\", Func, 0, \"func(x float64, y float64) (r float64)\"},\n\t\t{\"Nextafter32\", Func, 4, \"func(x float32, y float32) (r float32)\"},\n\t\t{\"Phi\", Const, 0, \"\"},\n\t\t{\"Pi\", Const, 0, \"\"},\n\t\t{\"Pow\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"Pow10\", Func, 0, \"func(n int) float64\"},\n\t\t{\"Remainder\", Func, 0, \"func(x float64, y float64) float64\"},\n\t\t{\"Round\", Func, 10, \"func(x float64) float64\"},\n\t\t{\"RoundToEven\", Func, 10, \"func(x float64) float64\"},\n\t\t{\"Signbit\", Func, 0, \"func(x float64) bool\"},\n\t\t{\"Sin\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Sincos\", Func, 0, \"func(x float64) (sin float64, cos float64)\"},\n\t\t{\"Sinh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"SmallestNonzeroFloat32\", Const, 0, \"\"},\n\t\t{\"SmallestNonzeroFloat64\", Const, 0, \"\"},\n\t\t{\"Sqrt\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Sqrt2\", Const, 0, \"\"},\n\t\t{\"SqrtE\", Const, 0, \"\"},\n\t\t{\"SqrtPhi\", Const, 0, \"\"},\n\t\t{\"SqrtPi\", Const, 0, \"\"},\n\t\t{\"Tan\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Tanh\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Trunc\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Y0\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Y1\", Func, 0, \"func(x float64) float64\"},\n\t\t{\"Yn\", Func, 0, \"func(n int, x float64) float64\"},\n\t},\n\t\"math/big\": {\n\t\t{\"(*Float).Abs\", Method, 5, \"\"},\n\t\t{\"(*Float).Acc\", Method, 5, \"\"},\n\t\t{\"(*Float).Add\", Method, 5, \"\"},\n\t\t{\"(*Float).Append\", Method, 5, \"\"},\n\t\t{\"(*Float).AppendText\", Method, 24, \"\"},\n\t\t{\"(*Float).Cmp\", Method, 5, \"\"},\n\t\t{\"(*Float).Copy\", Method, 5, \"\"},\n\t\t{\"(*Float).Float32\", Method, 5, \"\"},\n\t\t{\"(*Float).Float64\", Method, 5, \"\"},\n\t\t{\"(*Float).Format\", Method, 5, \"\"},\n\t\t{\"(*Float).GobDecode\", Method, 7, \"\"},\n\t\t{\"(*Float).GobEncode\", Method, 7, \"\"},\n\t\t{\"(*Float).Int\", Method, 5, \"\"},\n\t\t{\"(*Float).Int64\", Method, 5, \"\"},\n\t\t{\"(*Float).IsInf\", Method, 5, \"\"},\n\t\t{\"(*Float).IsInt\", Method, 5, \"\"},\n\t\t{\"(*Float).MantExp\", Method, 5, \"\"},\n\t\t{\"(*Float).MarshalText\", Method, 6, \"\"},\n\t\t{\"(*Float).MinPrec\", Method, 5, \"\"},\n\t\t{\"(*Float).Mode\", Method, 5, \"\"},\n\t\t{\"(*Float).Mul\", Method, 5, \"\"},\n\t\t{\"(*Float).Neg\", Method, 5, \"\"},\n\t\t{\"(*Float).Parse\", Method, 5, \"\"},\n\t\t{\"(*Float).Prec\", Method, 5, \"\"},\n\t\t{\"(*Float).Quo\", Method, 5, \"\"},\n\t\t{\"(*Float).Rat\", Method, 5, \"\"},\n\t\t{\"(*Float).Scan\", Method, 8, \"\"},\n\t\t{\"(*Float).Set\", Method, 5, \"\"},\n\t\t{\"(*Float).SetFloat64\", Method, 5, \"\"},\n\t\t{\"(*Float).SetInf\", Method, 5, \"\"},\n\t\t{\"(*Float).SetInt\", Method, 5, \"\"},\n\t\t{\"(*Float).SetInt64\", Method, 5, \"\"},\n\t\t{\"(*Float).SetMantExp\", Method, 5, \"\"},\n\t\t{\"(*Float).SetMode\", Method, 5, \"\"},\n\t\t{\"(*Float).SetPrec\", Method, 5, \"\"},\n\t\t{\"(*Float).SetRat\", Method, 5, \"\"},\n\t\t{\"(*Float).SetString\", Method, 5, \"\"},\n\t\t{\"(*Float).SetUint64\", Method, 5, \"\"},\n\t\t{\"(*Float).Sign\", Method, 5, \"\"},\n\t\t{\"(*Float).Signbit\", Method, 5, \"\"},\n\t\t{\"(*Float).Sqrt\", Method, 10, \"\"},\n\t\t{\"(*Float).String\", Method, 5, \"\"},\n\t\t{\"(*Float).Sub\", Method, 5, \"\"},\n\t\t{\"(*Float).Text\", Method, 5, \"\"},\n\t\t{\"(*Float).Uint64\", Method, 5, \"\"},\n\t\t{\"(*Float).UnmarshalText\", Method, 6, \"\"},\n\t\t{\"(*Int).Abs\", Method, 0, \"\"},\n\t\t{\"(*Int).Add\", Method, 0, \"\"},\n\t\t{\"(*Int).And\", Method, 0, \"\"},\n\t\t{\"(*Int).AndNot\", Method, 0, \"\"},\n\t\t{\"(*Int).Append\", Method, 6, \"\"},\n\t\t{\"(*Int).AppendText\", Method, 24, \"\"},\n\t\t{\"(*Int).Binomial\", Method, 0, \"\"},\n\t\t{\"(*Int).Bit\", Method, 0, \"\"},\n\t\t{\"(*Int).BitLen\", Method, 0, \"\"},\n\t\t{\"(*Int).Bits\", Method, 0, \"\"},\n\t\t{\"(*Int).Bytes\", Method, 0, \"\"},\n\t\t{\"(*Int).Cmp\", Method, 0, \"\"},\n\t\t{\"(*Int).CmpAbs\", Method, 10, \"\"},\n\t\t{\"(*Int).Div\", Method, 0, \"\"},\n\t\t{\"(*Int).DivMod\", Method, 0, \"\"},\n\t\t{\"(*Int).Exp\", Method, 0, \"\"},\n\t\t{\"(*Int).FillBytes\", Method, 15, \"\"},\n\t\t{\"(*Int).Float64\", Method, 21, \"\"},\n\t\t{\"(*Int).Format\", Method, 0, \"\"},\n\t\t{\"(*Int).GCD\", Method, 0, \"\"},\n\t\t{\"(*Int).GobDecode\", Method, 0, \"\"},\n\t\t{\"(*Int).GobEncode\", Method, 0, \"\"},\n\t\t{\"(*Int).Int64\", Method, 0, \"\"},\n\t\t{\"(*Int).IsInt64\", Method, 9, \"\"},\n\t\t{\"(*Int).IsUint64\", Method, 9, \"\"},\n\t\t{\"(*Int).Lsh\", Method, 0, \"\"},\n\t\t{\"(*Int).MarshalJSON\", Method, 1, \"\"},\n\t\t{\"(*Int).MarshalText\", Method, 3, \"\"},\n\t\t{\"(*Int).Mod\", Method, 0, \"\"},\n\t\t{\"(*Int).ModInverse\", Method, 0, \"\"},\n\t\t{\"(*Int).ModSqrt\", Method, 5, \"\"},\n\t\t{\"(*Int).Mul\", Method, 0, \"\"},\n\t\t{\"(*Int).MulRange\", Method, 0, \"\"},\n\t\t{\"(*Int).Neg\", Method, 0, \"\"},\n\t\t{\"(*Int).Not\", Method, 0, \"\"},\n\t\t{\"(*Int).Or\", Method, 0, \"\"},\n\t\t{\"(*Int).ProbablyPrime\", Method, 0, \"\"},\n\t\t{\"(*Int).Quo\", Method, 0, \"\"},\n\t\t{\"(*Int).QuoRem\", Method, 0, \"\"},\n\t\t{\"(*Int).Rand\", Method, 0, \"\"},\n\t\t{\"(*Int).Rem\", Method, 0, \"\"},\n\t\t{\"(*Int).Rsh\", Method, 0, \"\"},\n\t\t{\"(*Int).Scan\", Method, 0, \"\"},\n\t\t{\"(*Int).Set\", Method, 0, \"\"},\n\t\t{\"(*Int).SetBit\", Method, 0, \"\"},\n\t\t{\"(*Int).SetBits\", Method, 0, \"\"},\n\t\t{\"(*Int).SetBytes\", Method, 0, \"\"},\n\t\t{\"(*Int).SetInt64\", Method, 0, \"\"},\n\t\t{\"(*Int).SetString\", Method, 0, \"\"},\n\t\t{\"(*Int).SetUint64\", Method, 1, \"\"},\n\t\t{\"(*Int).Sign\", Method, 0, \"\"},\n\t\t{\"(*Int).Sqrt\", Method, 8, \"\"},\n\t\t{\"(*Int).String\", Method, 0, \"\"},\n\t\t{\"(*Int).Sub\", Method, 0, \"\"},\n\t\t{\"(*Int).Text\", Method, 6, \"\"},\n\t\t{\"(*Int).TrailingZeroBits\", Method, 13, \"\"},\n\t\t{\"(*Int).Uint64\", Method, 1, \"\"},\n\t\t{\"(*Int).UnmarshalJSON\", Method, 1, \"\"},\n\t\t{\"(*Int).UnmarshalText\", Method, 3, \"\"},\n\t\t{\"(*Int).Xor\", Method, 0, \"\"},\n\t\t{\"(*Rat).Abs\", Method, 0, \"\"},\n\t\t{\"(*Rat).Add\", Method, 0, \"\"},\n\t\t{\"(*Rat).AppendText\", Method, 24, \"\"},\n\t\t{\"(*Rat).Cmp\", Method, 0, \"\"},\n\t\t{\"(*Rat).Denom\", Method, 0, \"\"},\n\t\t{\"(*Rat).Float32\", Method, 4, \"\"},\n\t\t{\"(*Rat).Float64\", Method, 1, \"\"},\n\t\t{\"(*Rat).FloatPrec\", Method, 22, \"\"},\n\t\t{\"(*Rat).FloatString\", Method, 0, \"\"},\n\t\t{\"(*Rat).GobDecode\", Method, 0, \"\"},\n\t\t{\"(*Rat).GobEncode\", Method, 0, \"\"},\n\t\t{\"(*Rat).Inv\", Method, 0, \"\"},\n\t\t{\"(*Rat).IsInt\", Method, 0, \"\"},\n\t\t{\"(*Rat).MarshalText\", Method, 3, \"\"},\n\t\t{\"(*Rat).Mul\", Method, 0, \"\"},\n\t\t{\"(*Rat).Neg\", Method, 0, \"\"},\n\t\t{\"(*Rat).Num\", Method, 0, \"\"},\n\t\t{\"(*Rat).Quo\", Method, 0, \"\"},\n\t\t{\"(*Rat).RatString\", Method, 0, \"\"},\n\t\t{\"(*Rat).Scan\", Method, 0, \"\"},\n\t\t{\"(*Rat).Set\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetFloat64\", Method, 1, \"\"},\n\t\t{\"(*Rat).SetFrac\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetFrac64\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetInt\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetInt64\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetString\", Method, 0, \"\"},\n\t\t{\"(*Rat).SetUint64\", Method, 13, \"\"},\n\t\t{\"(*Rat).Sign\", Method, 0, \"\"},\n\t\t{\"(*Rat).String\", Method, 0, \"\"},\n\t\t{\"(*Rat).Sub\", Method, 0, \"\"},\n\t\t{\"(*Rat).UnmarshalText\", Method, 3, \"\"},\n\t\t{\"(Accuracy).String\", Method, 5, \"\"},\n\t\t{\"(ErrNaN).Error\", Method, 5, \"\"},\n\t\t{\"(RoundingMode).String\", Method, 5, \"\"},\n\t\t{\"Above\", Const, 5, \"\"},\n\t\t{\"Accuracy\", Type, 5, \"\"},\n\t\t{\"AwayFromZero\", Const, 5, \"\"},\n\t\t{\"Below\", Const, 5, \"\"},\n\t\t{\"ErrNaN\", Type, 5, \"\"},\n\t\t{\"Exact\", Const, 5, \"\"},\n\t\t{\"Float\", Type, 5, \"\"},\n\t\t{\"Int\", Type, 0, \"\"},\n\t\t{\"Jacobi\", Func, 5, \"func(x *Int, y *Int) int\"},\n\t\t{\"MaxBase\", Const, 0, \"\"},\n\t\t{\"MaxExp\", Const, 5, \"\"},\n\t\t{\"MaxPrec\", Const, 5, \"\"},\n\t\t{\"MinExp\", Const, 5, \"\"},\n\t\t{\"NewFloat\", Func, 5, \"func(x float64) *Float\"},\n\t\t{\"NewInt\", Func, 0, \"func(x int64) *Int\"},\n\t\t{\"NewRat\", Func, 0, \"func(a int64, b int64) *Rat\"},\n\t\t{\"ParseFloat\", Func, 5, \"func(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error)\"},\n\t\t{\"Rat\", Type, 0, \"\"},\n\t\t{\"RoundingMode\", Type, 5, \"\"},\n\t\t{\"ToNearestAway\", Const, 5, \"\"},\n\t\t{\"ToNearestEven\", Const, 5, \"\"},\n\t\t{\"ToNegativeInf\", Const, 5, \"\"},\n\t\t{\"ToPositiveInf\", Const, 5, \"\"},\n\t\t{\"ToZero\", Const, 5, \"\"},\n\t\t{\"Word\", Type, 0, \"\"},\n\t},\n\t\"math/bits\": {\n\t\t{\"Add\", Func, 12, \"func(x uint, y uint, carry uint) (sum uint, carryOut uint)\"},\n\t\t{\"Add32\", Func, 12, \"func(x uint32, y uint32, carry uint32) (sum uint32, carryOut uint32)\"},\n\t\t{\"Add64\", Func, 12, \"func(x uint64, y uint64, carry uint64) (sum uint64, carryOut uint64)\"},\n\t\t{\"Div\", Func, 12, \"func(hi uint, lo uint, y uint) (quo uint, rem uint)\"},\n\t\t{\"Div32\", Func, 12, \"func(hi uint32, lo uint32, y uint32) (quo uint32, rem uint32)\"},\n\t\t{\"Div64\", Func, 12, \"func(hi uint64, lo uint64, y uint64) (quo uint64, rem uint64)\"},\n\t\t{\"LeadingZeros\", Func, 9, \"func(x uint) int\"},\n\t\t{\"LeadingZeros16\", Func, 9, \"func(x uint16) int\"},\n\t\t{\"LeadingZeros32\", Func, 9, \"func(x uint32) int\"},\n\t\t{\"LeadingZeros64\", Func, 9, \"func(x uint64) int\"},\n\t\t{\"LeadingZeros8\", Func, 9, \"func(x uint8) int\"},\n\t\t{\"Len\", Func, 9, \"func(x uint) int\"},\n\t\t{\"Len16\", Func, 9, \"func(x uint16) (n int)\"},\n\t\t{\"Len32\", Func, 9, \"func(x uint32) (n int)\"},\n\t\t{\"Len64\", Func, 9, \"func(x uint64) (n int)\"},\n\t\t{\"Len8\", Func, 9, \"func(x uint8) int\"},\n\t\t{\"Mul\", Func, 12, \"func(x uint, y uint) (hi uint, lo uint)\"},\n\t\t{\"Mul32\", Func, 12, \"func(x uint32, y uint32) (hi uint32, lo uint32)\"},\n\t\t{\"Mul64\", Func, 12, \"func(x uint64, y uint64) (hi uint64, lo uint64)\"},\n\t\t{\"OnesCount\", Func, 9, \"func(x uint) int\"},\n\t\t{\"OnesCount16\", Func, 9, \"func(x uint16) int\"},\n\t\t{\"OnesCount32\", Func, 9, \"func(x uint32) int\"},\n\t\t{\"OnesCount64\", Func, 9, \"func(x uint64) int\"},\n\t\t{\"OnesCount8\", Func, 9, \"func(x uint8) int\"},\n\t\t{\"Rem\", Func, 14, \"func(hi uint, lo uint, y uint) uint\"},\n\t\t{\"Rem32\", Func, 14, \"func(hi uint32, lo uint32, y uint32) uint32\"},\n\t\t{\"Rem64\", Func, 14, \"func(hi uint64, lo uint64, y uint64) uint64\"},\n\t\t{\"Reverse\", Func, 9, \"func(x uint) uint\"},\n\t\t{\"Reverse16\", Func, 9, \"func(x uint16) uint16\"},\n\t\t{\"Reverse32\", Func, 9, \"func(x uint32) uint32\"},\n\t\t{\"Reverse64\", Func, 9, \"func(x uint64) uint64\"},\n\t\t{\"Reverse8\", Func, 9, \"func(x uint8) uint8\"},\n\t\t{\"ReverseBytes\", Func, 9, \"func(x uint) uint\"},\n\t\t{\"ReverseBytes16\", Func, 9, \"func(x uint16) uint16\"},\n\t\t{\"ReverseBytes32\", Func, 9, \"func(x uint32) uint32\"},\n\t\t{\"ReverseBytes64\", Func, 9, \"func(x uint64) uint64\"},\n\t\t{\"RotateLeft\", Func, 9, \"func(x uint, k int) uint\"},\n\t\t{\"RotateLeft16\", Func, 9, \"func(x uint16, k int) uint16\"},\n\t\t{\"RotateLeft32\", Func, 9, \"func(x uint32, k int) uint32\"},\n\t\t{\"RotateLeft64\", Func, 9, \"func(x uint64, k int) uint64\"},\n\t\t{\"RotateLeft8\", Func, 9, \"func(x uint8, k int) uint8\"},\n\t\t{\"Sub\", Func, 12, \"func(x uint, y uint, borrow uint) (diff uint, borrowOut uint)\"},\n\t\t{\"Sub32\", Func, 12, \"func(x uint32, y uint32, borrow uint32) (diff uint32, borrowOut uint32)\"},\n\t\t{\"Sub64\", Func, 12, \"func(x uint64, y uint64, borrow uint64) (diff uint64, borrowOut uint64)\"},\n\t\t{\"TrailingZeros\", Func, 9, \"func(x uint) int\"},\n\t\t{\"TrailingZeros16\", Func, 9, \"func(x uint16) int\"},\n\t\t{\"TrailingZeros32\", Func, 9, \"func(x uint32) int\"},\n\t\t{\"TrailingZeros64\", Func, 9, \"func(x uint64) int\"},\n\t\t{\"TrailingZeros8\", Func, 9, \"func(x uint8) int\"},\n\t\t{\"UintSize\", Const, 9, \"\"},\n\t},\n\t\"math/cmplx\": {\n\t\t{\"Abs\", Func, 0, \"func(x complex128) float64\"},\n\t\t{\"Acos\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Acosh\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Asin\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Asinh\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Atan\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Atanh\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Conj\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Cos\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Cosh\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Cot\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Exp\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Inf\", Func, 0, \"func() complex128\"},\n\t\t{\"IsInf\", Func, 0, \"func(x complex128) bool\"},\n\t\t{\"IsNaN\", Func, 0, \"func(x complex128) bool\"},\n\t\t{\"Log\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Log10\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"NaN\", Func, 0, \"func() complex128\"},\n\t\t{\"Phase\", Func, 0, \"func(x complex128) float64\"},\n\t\t{\"Polar\", Func, 0, \"func(x complex128) (r float64, θ float64)\"},\n\t\t{\"Pow\", Func, 0, \"func(x complex128, y complex128) complex128\"},\n\t\t{\"Rect\", Func, 0, \"func(r float64, θ float64) complex128\"},\n\t\t{\"Sin\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Sinh\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Sqrt\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Tan\", Func, 0, \"func(x complex128) complex128\"},\n\t\t{\"Tanh\", Func, 0, \"func(x complex128) complex128\"},\n\t},\n\t\"math/rand\": {\n\t\t{\"(*Rand).ExpFloat64\", Method, 0, \"\"},\n\t\t{\"(*Rand).Float32\", Method, 0, \"\"},\n\t\t{\"(*Rand).Float64\", Method, 0, \"\"},\n\t\t{\"(*Rand).Int\", Method, 0, \"\"},\n\t\t{\"(*Rand).Int31\", Method, 0, \"\"},\n\t\t{\"(*Rand).Int31n\", Method, 0, \"\"},\n\t\t{\"(*Rand).Int63\", Method, 0, \"\"},\n\t\t{\"(*Rand).Int63n\", Method, 0, \"\"},\n\t\t{\"(*Rand).Intn\", Method, 0, \"\"},\n\t\t{\"(*Rand).NormFloat64\", Method, 0, \"\"},\n\t\t{\"(*Rand).Perm\", Method, 0, \"\"},\n\t\t{\"(*Rand).Read\", Method, 6, \"\"},\n\t\t{\"(*Rand).Seed\", Method, 0, \"\"},\n\t\t{\"(*Rand).Shuffle\", Method, 10, \"\"},\n\t\t{\"(*Rand).Uint32\", Method, 0, \"\"},\n\t\t{\"(*Rand).Uint64\", Method, 8, \"\"},\n\t\t{\"(*Zipf).Uint64\", Method, 0, \"\"},\n\t\t{\"(Source).Int63\", Method, 0, \"\"},\n\t\t{\"(Source).Seed\", Method, 0, \"\"},\n\t\t{\"(Source64).Int63\", Method, 8, \"\"},\n\t\t{\"(Source64).Seed\", Method, 8, \"\"},\n\t\t{\"(Source64).Uint64\", Method, 8, \"\"},\n\t\t{\"ExpFloat64\", Func, 0, \"func() float64\"},\n\t\t{\"Float32\", Func, 0, \"func() float32\"},\n\t\t{\"Float64\", Func, 0, \"func() float64\"},\n\t\t{\"Int\", Func, 0, \"func() int\"},\n\t\t{\"Int31\", Func, 0, \"func() int32\"},\n\t\t{\"Int31n\", Func, 0, \"func(n int32) int32\"},\n\t\t{\"Int63\", Func, 0, \"func() int64\"},\n\t\t{\"Int63n\", Func, 0, \"func(n int64) int64\"},\n\t\t{\"Intn\", Func, 0, \"func(n int) int\"},\n\t\t{\"New\", Func, 0, \"func(src Source) *Rand\"},\n\t\t{\"NewSource\", Func, 0, \"func(seed int64) Source\"},\n\t\t{\"NewZipf\", Func, 0, \"func(r *Rand, s float64, v float64, imax uint64) *Zipf\"},\n\t\t{\"NormFloat64\", Func, 0, \"func() float64\"},\n\t\t{\"Perm\", Func, 0, \"func(n int) []int\"},\n\t\t{\"Rand\", Type, 0, \"\"},\n\t\t{\"Read\", Func, 6, \"func(p []byte) (n int, err error)\"},\n\t\t{\"Seed\", Func, 0, \"func(seed int64)\"},\n\t\t{\"Shuffle\", Func, 10, \"func(n int, swap func(i int, j int))\"},\n\t\t{\"Source\", Type, 0, \"\"},\n\t\t{\"Source64\", Type, 8, \"\"},\n\t\t{\"Uint32\", Func, 0, \"func() uint32\"},\n\t\t{\"Uint64\", Func, 8, \"func() uint64\"},\n\t\t{\"Zipf\", Type, 0, \"\"},\n\t},\n\t\"math/rand/v2\": {\n\t\t{\"(*ChaCha8).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(*ChaCha8).MarshalBinary\", Method, 22, \"\"},\n\t\t{\"(*ChaCha8).Read\", Method, 23, \"\"},\n\t\t{\"(*ChaCha8).Seed\", Method, 22, \"\"},\n\t\t{\"(*ChaCha8).Uint64\", Method, 22, \"\"},\n\t\t{\"(*ChaCha8).UnmarshalBinary\", Method, 22, \"\"},\n\t\t{\"(*PCG).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(*PCG).MarshalBinary\", Method, 22, \"\"},\n\t\t{\"(*PCG).Seed\", Method, 22, \"\"},\n\t\t{\"(*PCG).Uint64\", Method, 22, \"\"},\n\t\t{\"(*PCG).UnmarshalBinary\", Method, 22, \"\"},\n\t\t{\"(*Rand).ExpFloat64\", Method, 22, \"\"},\n\t\t{\"(*Rand).Float32\", Method, 22, \"\"},\n\t\t{\"(*Rand).Float64\", Method, 22, \"\"},\n\t\t{\"(*Rand).Int\", Method, 22, \"\"},\n\t\t{\"(*Rand).Int32\", Method, 22, \"\"},\n\t\t{\"(*Rand).Int32N\", Method, 22, \"\"},\n\t\t{\"(*Rand).Int64\", Method, 22, \"\"},\n\t\t{\"(*Rand).Int64N\", Method, 22, \"\"},\n\t\t{\"(*Rand).IntN\", Method, 22, \"\"},\n\t\t{\"(*Rand).NormFloat64\", Method, 22, \"\"},\n\t\t{\"(*Rand).Perm\", Method, 22, \"\"},\n\t\t{\"(*Rand).Shuffle\", Method, 22, \"\"},\n\t\t{\"(*Rand).Uint\", Method, 23, \"\"},\n\t\t{\"(*Rand).Uint32\", Method, 22, \"\"},\n\t\t{\"(*Rand).Uint32N\", Method, 22, \"\"},\n\t\t{\"(*Rand).Uint64\", Method, 22, \"\"},\n\t\t{\"(*Rand).Uint64N\", Method, 22, \"\"},\n\t\t{\"(*Rand).UintN\", Method, 22, \"\"},\n\t\t{\"(*Zipf).Uint64\", Method, 22, \"\"},\n\t\t{\"(Source).Uint64\", Method, 22, \"\"},\n\t\t{\"ChaCha8\", Type, 22, \"\"},\n\t\t{\"ExpFloat64\", Func, 22, \"func() float64\"},\n\t\t{\"Float32\", Func, 22, \"func() float32\"},\n\t\t{\"Float64\", Func, 22, \"func() float64\"},\n\t\t{\"Int\", Func, 22, \"func() int\"},\n\t\t{\"Int32\", Func, 22, \"func() int32\"},\n\t\t{\"Int32N\", Func, 22, \"func(n int32) int32\"},\n\t\t{\"Int64\", Func, 22, \"func() int64\"},\n\t\t{\"Int64N\", Func, 22, \"func(n int64) int64\"},\n\t\t{\"IntN\", Func, 22, \"func(n int) int\"},\n\t\t{\"N\", Func, 22, \"func[Int intType](n Int) Int\"},\n\t\t{\"New\", Func, 22, \"func(src Source) *Rand\"},\n\t\t{\"NewChaCha8\", Func, 22, \"func(seed [32]byte) *ChaCha8\"},\n\t\t{\"NewPCG\", Func, 22, \"func(seed1 uint64, seed2 uint64) *PCG\"},\n\t\t{\"NewZipf\", Func, 22, \"func(r *Rand, s float64, v float64, imax uint64) *Zipf\"},\n\t\t{\"NormFloat64\", Func, 22, \"func() float64\"},\n\t\t{\"PCG\", Type, 22, \"\"},\n\t\t{\"Perm\", Func, 22, \"func(n int) []int\"},\n\t\t{\"Rand\", Type, 22, \"\"},\n\t\t{\"Shuffle\", Func, 22, \"func(n int, swap func(i int, j int))\"},\n\t\t{\"Source\", Type, 22, \"\"},\n\t\t{\"Uint\", Func, 23, \"func() uint\"},\n\t\t{\"Uint32\", Func, 22, \"func() uint32\"},\n\t\t{\"Uint32N\", Func, 22, \"func(n uint32) uint32\"},\n\t\t{\"Uint64\", Func, 22, \"func() uint64\"},\n\t\t{\"Uint64N\", Func, 22, \"func(n uint64) uint64\"},\n\t\t{\"UintN\", Func, 22, \"func(n uint) uint\"},\n\t\t{\"Zipf\", Type, 22, \"\"},\n\t},\n\t\"mime\": {\n\t\t{\"(*WordDecoder).Decode\", Method, 5, \"\"},\n\t\t{\"(*WordDecoder).DecodeHeader\", Method, 5, \"\"},\n\t\t{\"(WordEncoder).Encode\", Method, 5, \"\"},\n\t\t{\"AddExtensionType\", Func, 0, \"func(ext string, typ string) error\"},\n\t\t{\"BEncoding\", Const, 5, \"\"},\n\t\t{\"ErrInvalidMediaParameter\", Var, 9, \"\"},\n\t\t{\"ExtensionsByType\", Func, 5, \"func(typ string) ([]string, error)\"},\n\t\t{\"FormatMediaType\", Func, 0, \"func(t string, param map[string]string) string\"},\n\t\t{\"ParseMediaType\", Func, 0, \"func(v string) (mediatype string, params map[string]string, err error)\"},\n\t\t{\"QEncoding\", Const, 5, \"\"},\n\t\t{\"TypeByExtension\", Func, 0, \"func(ext string) string\"},\n\t\t{\"WordDecoder\", Type, 5, \"\"},\n\t\t{\"WordDecoder.CharsetReader\", Field, 5, \"\"},\n\t\t{\"WordEncoder\", Type, 5, \"\"},\n\t},\n\t\"mime/multipart\": {\n\t\t{\"(*FileHeader).Open\", Method, 0, \"\"},\n\t\t{\"(*Form).RemoveAll\", Method, 0, \"\"},\n\t\t{\"(*Part).Close\", Method, 0, \"\"},\n\t\t{\"(*Part).FileName\", Method, 0, \"\"},\n\t\t{\"(*Part).FormName\", Method, 0, \"\"},\n\t\t{\"(*Part).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).NextPart\", Method, 0, \"\"},\n\t\t{\"(*Reader).NextRawPart\", Method, 14, \"\"},\n\t\t{\"(*Reader).ReadForm\", Method, 0, \"\"},\n\t\t{\"(*Writer).Boundary\", Method, 0, \"\"},\n\t\t{\"(*Writer).Close\", Method, 0, \"\"},\n\t\t{\"(*Writer).CreateFormField\", Method, 0, \"\"},\n\t\t{\"(*Writer).CreateFormFile\", Method, 0, \"\"},\n\t\t{\"(*Writer).CreatePart\", Method, 0, \"\"},\n\t\t{\"(*Writer).FormDataContentType\", Method, 0, \"\"},\n\t\t{\"(*Writer).SetBoundary\", Method, 1, \"\"},\n\t\t{\"(*Writer).WriteField\", Method, 0, \"\"},\n\t\t{\"(File).Close\", Method, 0, \"\"},\n\t\t{\"(File).Read\", Method, 0, \"\"},\n\t\t{\"(File).ReadAt\", Method, 0, \"\"},\n\t\t{\"(File).Seek\", Method, 0, \"\"},\n\t\t{\"ErrMessageTooLarge\", Var, 9, \"\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"FileContentDisposition\", Func, 25, \"func(fieldname string, filename string) string\"},\n\t\t{\"FileHeader\", Type, 0, \"\"},\n\t\t{\"FileHeader.Filename\", Field, 0, \"\"},\n\t\t{\"FileHeader.Header\", Field, 0, \"\"},\n\t\t{\"FileHeader.Size\", Field, 9, \"\"},\n\t\t{\"Form\", Type, 0, \"\"},\n\t\t{\"Form.File\", Field, 0, \"\"},\n\t\t{\"Form.Value\", Field, 0, \"\"},\n\t\t{\"NewReader\", Func, 0, \"func(r io.Reader, boundary string) *Reader\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w io.Writer) *Writer\"},\n\t\t{\"Part\", Type, 0, \"\"},\n\t\t{\"Part.Header\", Field, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"mime/quotedprintable\": {\n\t\t{\"(*Reader).Read\", Method, 5, \"\"},\n\t\t{\"(*Writer).Close\", Method, 5, \"\"},\n\t\t{\"(*Writer).Write\", Method, 5, \"\"},\n\t\t{\"NewReader\", Func, 5, \"func(r io.Reader) *Reader\"},\n\t\t{\"NewWriter\", Func, 5, \"func(w io.Writer) *Writer\"},\n\t\t{\"Reader\", Type, 5, \"\"},\n\t\t{\"Writer\", Type, 5, \"\"},\n\t\t{\"Writer.Binary\", Field, 5, \"\"},\n\t},\n\t\"net\": {\n\t\t{\"(*AddrError).Error\", Method, 0, \"\"},\n\t\t{\"(*AddrError).Temporary\", Method, 0, \"\"},\n\t\t{\"(*AddrError).Timeout\", Method, 0, \"\"},\n\t\t{\"(*Buffers).Read\", Method, 8, \"\"},\n\t\t{\"(*Buffers).WriteTo\", Method, 8, \"\"},\n\t\t{\"(*DNSConfigError).Error\", Method, 0, \"\"},\n\t\t{\"(*DNSConfigError).Temporary\", Method, 0, \"\"},\n\t\t{\"(*DNSConfigError).Timeout\", Method, 0, \"\"},\n\t\t{\"(*DNSConfigError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*DNSError).Error\", Method, 0, \"\"},\n\t\t{\"(*DNSError).Temporary\", Method, 0, \"\"},\n\t\t{\"(*DNSError).Timeout\", Method, 0, \"\"},\n\t\t{\"(*DNSError).Unwrap\", Method, 23, \"\"},\n\t\t{\"(*Dialer).Dial\", Method, 1, \"\"},\n\t\t{\"(*Dialer).DialContext\", Method, 7, \"\"},\n\t\t{\"(*Dialer).DialIP\", Method, 26, \"\"},\n\t\t{\"(*Dialer).DialTCP\", Method, 26, \"\"},\n\t\t{\"(*Dialer).DialUDP\", Method, 26, \"\"},\n\t\t{\"(*Dialer).DialUnix\", Method, 26, \"\"},\n\t\t{\"(*Dialer).MultipathTCP\", Method, 21, \"\"},\n\t\t{\"(*Dialer).SetMultipathTCP\", Method, 21, \"\"},\n\t\t{\"(*IP).UnmarshalText\", Method, 2, \"\"},\n\t\t{\"(*IPAddr).Network\", Method, 0, \"\"},\n\t\t{\"(*IPAddr).String\", Method, 0, \"\"},\n\t\t{\"(*IPConn).Close\", Method, 0, \"\"},\n\t\t{\"(*IPConn).File\", Method, 0, \"\"},\n\t\t{\"(*IPConn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(*IPConn).Read\", Method, 0, \"\"},\n\t\t{\"(*IPConn).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(*IPConn).ReadFromIP\", Method, 0, \"\"},\n\t\t{\"(*IPConn).ReadMsgIP\", Method, 1, \"\"},\n\t\t{\"(*IPConn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SetReadBuffer\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SetWriteBuffer\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(*IPConn).SyscallConn\", Method, 9, \"\"},\n\t\t{\"(*IPConn).Write\", Method, 0, \"\"},\n\t\t{\"(*IPConn).WriteMsgIP\", Method, 1, \"\"},\n\t\t{\"(*IPConn).WriteTo\", Method, 0, \"\"},\n\t\t{\"(*IPConn).WriteToIP\", Method, 0, \"\"},\n\t\t{\"(*IPNet).Contains\", Method, 0, \"\"},\n\t\t{\"(*IPNet).Network\", Method, 0, \"\"},\n\t\t{\"(*IPNet).String\", Method, 0, \"\"},\n\t\t{\"(*Interface).Addrs\", Method, 0, \"\"},\n\t\t{\"(*Interface).MulticastAddrs\", Method, 0, \"\"},\n\t\t{\"(*ListenConfig).Listen\", Method, 11, \"\"},\n\t\t{\"(*ListenConfig).ListenPacket\", Method, 11, \"\"},\n\t\t{\"(*ListenConfig).MultipathTCP\", Method, 21, \"\"},\n\t\t{\"(*ListenConfig).SetMultipathTCP\", Method, 21, \"\"},\n\t\t{\"(*OpError).Error\", Method, 0, \"\"},\n\t\t{\"(*OpError).Temporary\", Method, 0, \"\"},\n\t\t{\"(*OpError).Timeout\", Method, 0, \"\"},\n\t\t{\"(*OpError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*ParseError).Error\", Method, 0, \"\"},\n\t\t{\"(*ParseError).Temporary\", Method, 17, \"\"},\n\t\t{\"(*ParseError).Timeout\", Method, 17, \"\"},\n\t\t{\"(*Resolver).LookupAddr\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupCNAME\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupHost\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupIP\", Method, 15, \"\"},\n\t\t{\"(*Resolver).LookupIPAddr\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupMX\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupNS\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupNetIP\", Method, 18, \"\"},\n\t\t{\"(*Resolver).LookupPort\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupSRV\", Method, 8, \"\"},\n\t\t{\"(*Resolver).LookupTXT\", Method, 8, \"\"},\n\t\t{\"(*TCPAddr).AddrPort\", Method, 18, \"\"},\n\t\t{\"(*TCPAddr).Network\", Method, 0, \"\"},\n\t\t{\"(*TCPAddr).String\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).Close\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).CloseRead\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).CloseWrite\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).File\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).MultipathTCP\", Method, 21, \"\"},\n\t\t{\"(*TCPConn).Read\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetKeepAlive\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetKeepAliveConfig\", Method, 23, \"\"},\n\t\t{\"(*TCPConn).SetKeepAlivePeriod\", Method, 2, \"\"},\n\t\t{\"(*TCPConn).SetLinger\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetNoDelay\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetReadBuffer\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetWriteBuffer\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).SyscallConn\", Method, 9, \"\"},\n\t\t{\"(*TCPConn).Write\", Method, 0, \"\"},\n\t\t{\"(*TCPConn).WriteTo\", Method, 22, \"\"},\n\t\t{\"(*TCPListener).Accept\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).AcceptTCP\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).Addr\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).Close\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).File\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*TCPListener).SyscallConn\", Method, 10, \"\"},\n\t\t{\"(*UDPAddr).AddrPort\", Method, 18, \"\"},\n\t\t{\"(*UDPAddr).Network\", Method, 0, \"\"},\n\t\t{\"(*UDPAddr).String\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).Close\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).File\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).Read\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).ReadFromUDP\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).ReadFromUDPAddrPort\", Method, 18, \"\"},\n\t\t{\"(*UDPConn).ReadMsgUDP\", Method, 1, \"\"},\n\t\t{\"(*UDPConn).ReadMsgUDPAddrPort\", Method, 18, \"\"},\n\t\t{\"(*UDPConn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SetReadBuffer\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SetWriteBuffer\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).SyscallConn\", Method, 9, \"\"},\n\t\t{\"(*UDPConn).Write\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).WriteMsgUDP\", Method, 1, \"\"},\n\t\t{\"(*UDPConn).WriteMsgUDPAddrPort\", Method, 18, \"\"},\n\t\t{\"(*UDPConn).WriteTo\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).WriteToUDP\", Method, 0, \"\"},\n\t\t{\"(*UDPConn).WriteToUDPAddrPort\", Method, 18, \"\"},\n\t\t{\"(*UnixAddr).Network\", Method, 0, \"\"},\n\t\t{\"(*UnixAddr).String\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).Close\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).CloseRead\", Method, 1, \"\"},\n\t\t{\"(*UnixConn).CloseWrite\", Method, 1, \"\"},\n\t\t{\"(*UnixConn).File\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).Read\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).ReadFromUnix\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).ReadMsgUnix\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SetReadBuffer\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SetWriteBuffer\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).SyscallConn\", Method, 9, \"\"},\n\t\t{\"(*UnixConn).Write\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).WriteMsgUnix\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).WriteTo\", Method, 0, \"\"},\n\t\t{\"(*UnixConn).WriteToUnix\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).Accept\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).AcceptUnix\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).Addr\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).Close\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).File\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(*UnixListener).SetUnlinkOnClose\", Method, 8, \"\"},\n\t\t{\"(*UnixListener).SyscallConn\", Method, 10, \"\"},\n\t\t{\"(Addr).Network\", Method, 0, \"\"},\n\t\t{\"(Addr).String\", Method, 0, \"\"},\n\t\t{\"(Conn).Close\", Method, 0, \"\"},\n\t\t{\"(Conn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(Conn).Read\", Method, 0, \"\"},\n\t\t{\"(Conn).RemoteAddr\", Method, 0, \"\"},\n\t\t{\"(Conn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(Conn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(Conn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(Conn).Write\", Method, 0, \"\"},\n\t\t{\"(Error).Error\", Method, 0, \"\"},\n\t\t{\"(Error).Temporary\", Method, 0, \"\"},\n\t\t{\"(Error).Timeout\", Method, 0, \"\"},\n\t\t{\"(Flags).String\", Method, 0, \"\"},\n\t\t{\"(HardwareAddr).String\", Method, 0, \"\"},\n\t\t{\"(IP).AppendText\", Method, 24, \"\"},\n\t\t{\"(IP).DefaultMask\", Method, 0, \"\"},\n\t\t{\"(IP).Equal\", Method, 0, \"\"},\n\t\t{\"(IP).IsGlobalUnicast\", Method, 0, \"\"},\n\t\t{\"(IP).IsInterfaceLocalMulticast\", Method, 0, \"\"},\n\t\t{\"(IP).IsLinkLocalMulticast\", Method, 0, \"\"},\n\t\t{\"(IP).IsLinkLocalUnicast\", Method, 0, \"\"},\n\t\t{\"(IP).IsLoopback\", Method, 0, \"\"},\n\t\t{\"(IP).IsMulticast\", Method, 0, \"\"},\n\t\t{\"(IP).IsPrivate\", Method, 17, \"\"},\n\t\t{\"(IP).IsUnspecified\", Method, 0, \"\"},\n\t\t{\"(IP).MarshalText\", Method, 2, \"\"},\n\t\t{\"(IP).Mask\", Method, 0, \"\"},\n\t\t{\"(IP).String\", Method, 0, \"\"},\n\t\t{\"(IP).To16\", Method, 0, \"\"},\n\t\t{\"(IP).To4\", Method, 0, \"\"},\n\t\t{\"(IPMask).Size\", Method, 0, \"\"},\n\t\t{\"(IPMask).String\", Method, 0, \"\"},\n\t\t{\"(InvalidAddrError).Error\", Method, 0, \"\"},\n\t\t{\"(InvalidAddrError).Temporary\", Method, 0, \"\"},\n\t\t{\"(InvalidAddrError).Timeout\", Method, 0, \"\"},\n\t\t{\"(Listener).Accept\", Method, 0, \"\"},\n\t\t{\"(Listener).Addr\", Method, 0, \"\"},\n\t\t{\"(Listener).Close\", Method, 0, \"\"},\n\t\t{\"(PacketConn).Close\", Method, 0, \"\"},\n\t\t{\"(PacketConn).LocalAddr\", Method, 0, \"\"},\n\t\t{\"(PacketConn).ReadFrom\", Method, 0, \"\"},\n\t\t{\"(PacketConn).SetDeadline\", Method, 0, \"\"},\n\t\t{\"(PacketConn).SetReadDeadline\", Method, 0, \"\"},\n\t\t{\"(PacketConn).SetWriteDeadline\", Method, 0, \"\"},\n\t\t{\"(PacketConn).WriteTo\", Method, 0, \"\"},\n\t\t{\"(UnknownNetworkError).Error\", Method, 0, \"\"},\n\t\t{\"(UnknownNetworkError).Temporary\", Method, 0, \"\"},\n\t\t{\"(UnknownNetworkError).Timeout\", Method, 0, \"\"},\n\t\t{\"Addr\", Type, 0, \"\"},\n\t\t{\"AddrError\", Type, 0, \"\"},\n\t\t{\"AddrError.Addr\", Field, 0, \"\"},\n\t\t{\"AddrError.Err\", Field, 0, \"\"},\n\t\t{\"Buffers\", Type, 8, \"\"},\n\t\t{\"CIDRMask\", Func, 0, \"func(ones int, bits int) IPMask\"},\n\t\t{\"Conn\", Type, 0, \"\"},\n\t\t{\"DNSConfigError\", Type, 0, \"\"},\n\t\t{\"DNSConfigError.Err\", Field, 0, \"\"},\n\t\t{\"DNSError\", Type, 0, \"\"},\n\t\t{\"DNSError.Err\", Field, 0, \"\"},\n\t\t{\"DNSError.IsNotFound\", Field, 13, \"\"},\n\t\t{\"DNSError.IsTemporary\", Field, 6, \"\"},\n\t\t{\"DNSError.IsTimeout\", Field, 0, \"\"},\n\t\t{\"DNSError.Name\", Field, 0, \"\"},\n\t\t{\"DNSError.Server\", Field, 0, \"\"},\n\t\t{\"DNSError.UnwrapErr\", Field, 23, \"\"},\n\t\t{\"DefaultResolver\", Var, 8, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(network string, address string) (Conn, error)\"},\n\t\t{\"DialIP\", Func, 0, \"func(network string, laddr *IPAddr, raddr *IPAddr) (*IPConn, error)\"},\n\t\t{\"DialTCP\", Func, 0, \"func(network string, laddr *TCPAddr, raddr *TCPAddr) (*TCPConn, error)\"},\n\t\t{\"DialTimeout\", Func, 0, \"func(network string, address string, timeout time.Duration) (Conn, error)\"},\n\t\t{\"DialUDP\", Func, 0, \"func(network string, laddr *UDPAddr, raddr *UDPAddr) (*UDPConn, error)\"},\n\t\t{\"DialUnix\", Func, 0, \"func(network string, laddr *UnixAddr, raddr *UnixAddr) (*UnixConn, error)\"},\n\t\t{\"Dialer\", Type, 1, \"\"},\n\t\t{\"Dialer.Cancel\", Field, 6, \"\"},\n\t\t{\"Dialer.Control\", Field, 11, \"\"},\n\t\t{\"Dialer.ControlContext\", Field, 20, \"\"},\n\t\t{\"Dialer.Deadline\", Field, 1, \"\"},\n\t\t{\"Dialer.DualStack\", Field, 2, \"\"},\n\t\t{\"Dialer.FallbackDelay\", Field, 5, \"\"},\n\t\t{\"Dialer.KeepAlive\", Field, 3, \"\"},\n\t\t{\"Dialer.KeepAliveConfig\", Field, 23, \"\"},\n\t\t{\"Dialer.LocalAddr\", Field, 1, \"\"},\n\t\t{\"Dialer.Resolver\", Field, 8, \"\"},\n\t\t{\"Dialer.Timeout\", Field, 1, \"\"},\n\t\t{\"ErrClosed\", Var, 16, \"\"},\n\t\t{\"ErrWriteToConnected\", Var, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"FileConn\", Func, 0, \"func(f *os.File) (c Conn, err error)\"},\n\t\t{\"FileListener\", Func, 0, \"func(f *os.File) (ln Listener, err error)\"},\n\t\t{\"FilePacketConn\", Func, 0, \"func(f *os.File) (c PacketConn, err error)\"},\n\t\t{\"FlagBroadcast\", Const, 0, \"\"},\n\t\t{\"FlagLoopback\", Const, 0, \"\"},\n\t\t{\"FlagMulticast\", Const, 0, \"\"},\n\t\t{\"FlagPointToPoint\", Const, 0, \"\"},\n\t\t{\"FlagRunning\", Const, 20, \"\"},\n\t\t{\"FlagUp\", Const, 0, \"\"},\n\t\t{\"Flags\", Type, 0, \"\"},\n\t\t{\"HardwareAddr\", Type, 0, \"\"},\n\t\t{\"IP\", Type, 0, \"\"},\n\t\t{\"IPAddr\", Type, 0, \"\"},\n\t\t{\"IPAddr.IP\", Field, 0, \"\"},\n\t\t{\"IPAddr.Zone\", Field, 1, \"\"},\n\t\t{\"IPConn\", Type, 0, \"\"},\n\t\t{\"IPMask\", Type, 0, \"\"},\n\t\t{\"IPNet\", Type, 0, \"\"},\n\t\t{\"IPNet.IP\", Field, 0, \"\"},\n\t\t{\"IPNet.Mask\", Field, 0, \"\"},\n\t\t{\"IPv4\", Func, 0, \"func(a byte, b byte, c byte, d byte) IP\"},\n\t\t{\"IPv4Mask\", Func, 0, \"func(a byte, b byte, c byte, d byte) IPMask\"},\n\t\t{\"IPv4allrouter\", Var, 0, \"\"},\n\t\t{\"IPv4allsys\", Var, 0, \"\"},\n\t\t{\"IPv4bcast\", Var, 0, \"\"},\n\t\t{\"IPv4len\", Const, 0, \"\"},\n\t\t{\"IPv4zero\", Var, 0, \"\"},\n\t\t{\"IPv6interfacelocalallnodes\", Var, 0, \"\"},\n\t\t{\"IPv6len\", Const, 0, \"\"},\n\t\t{\"IPv6linklocalallnodes\", Var, 0, \"\"},\n\t\t{\"IPv6linklocalallrouters\", Var, 0, \"\"},\n\t\t{\"IPv6loopback\", Var, 0, \"\"},\n\t\t{\"IPv6unspecified\", Var, 0, \"\"},\n\t\t{\"IPv6zero\", Var, 0, \"\"},\n\t\t{\"Interface\", Type, 0, \"\"},\n\t\t{\"Interface.Flags\", Field, 0, \"\"},\n\t\t{\"Interface.HardwareAddr\", Field, 0, \"\"},\n\t\t{\"Interface.Index\", Field, 0, \"\"},\n\t\t{\"Interface.MTU\", Field, 0, \"\"},\n\t\t{\"Interface.Name\", Field, 0, \"\"},\n\t\t{\"InterfaceAddrs\", Func, 0, \"func() ([]Addr, error)\"},\n\t\t{\"InterfaceByIndex\", Func, 0, \"func(index int) (*Interface, error)\"},\n\t\t{\"InterfaceByName\", Func, 0, \"func(name string) (*Interface, error)\"},\n\t\t{\"Interfaces\", Func, 0, \"func() ([]Interface, error)\"},\n\t\t{\"InvalidAddrError\", Type, 0, \"\"},\n\t\t{\"JoinHostPort\", Func, 0, \"func(host string, port string) string\"},\n\t\t{\"KeepAliveConfig\", Type, 23, \"\"},\n\t\t{\"KeepAliveConfig.Count\", Field, 23, \"\"},\n\t\t{\"KeepAliveConfig.Enable\", Field, 23, \"\"},\n\t\t{\"KeepAliveConfig.Idle\", Field, 23, \"\"},\n\t\t{\"KeepAliveConfig.Interval\", Field, 23, \"\"},\n\t\t{\"Listen\", Func, 0, \"func(network string, address string) (Listener, error)\"},\n\t\t{\"ListenConfig\", Type, 11, \"\"},\n\t\t{\"ListenConfig.Control\", Field, 11, \"\"},\n\t\t{\"ListenConfig.KeepAlive\", Field, 13, \"\"},\n\t\t{\"ListenConfig.KeepAliveConfig\", Field, 23, \"\"},\n\t\t{\"ListenIP\", Func, 0, \"func(network string, laddr *IPAddr) (*IPConn, error)\"},\n\t\t{\"ListenMulticastUDP\", Func, 0, \"func(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error)\"},\n\t\t{\"ListenPacket\", Func, 0, \"func(network string, address string) (PacketConn, error)\"},\n\t\t{\"ListenTCP\", Func, 0, \"func(network string, laddr *TCPAddr) (*TCPListener, error)\"},\n\t\t{\"ListenUDP\", Func, 0, \"func(network string, laddr *UDPAddr) (*UDPConn, error)\"},\n\t\t{\"ListenUnix\", Func, 0, \"func(network string, laddr *UnixAddr) (*UnixListener, error)\"},\n\t\t{\"ListenUnixgram\", Func, 0, \"func(network string, laddr *UnixAddr) (*UnixConn, error)\"},\n\t\t{\"Listener\", Type, 0, \"\"},\n\t\t{\"LookupAddr\", Func, 0, \"func(addr string) (names []string, err error)\"},\n\t\t{\"LookupCNAME\", Func, 0, \"func(host string) (cname string, err error)\"},\n\t\t{\"LookupHost\", Func, 0, \"func(host string) (addrs []string, err error)\"},\n\t\t{\"LookupIP\", Func, 0, \"func(host string) ([]IP, error)\"},\n\t\t{\"LookupMX\", Func, 0, \"func(name string) ([]*MX, error)\"},\n\t\t{\"LookupNS\", Func, 1, \"func(name string) ([]*NS, error)\"},\n\t\t{\"LookupPort\", Func, 0, \"func(network string, service string) (port int, err error)\"},\n\t\t{\"LookupSRV\", Func, 0, \"func(service string, proto string, name string) (cname string, addrs []*SRV, err error)\"},\n\t\t{\"LookupTXT\", Func, 0, \"func(name string) ([]string, error)\"},\n\t\t{\"MX\", Type, 0, \"\"},\n\t\t{\"MX.Host\", Field, 0, \"\"},\n\t\t{\"MX.Pref\", Field, 0, \"\"},\n\t\t{\"NS\", Type, 1, \"\"},\n\t\t{\"NS.Host\", Field, 1, \"\"},\n\t\t{\"OpError\", Type, 0, \"\"},\n\t\t{\"OpError.Addr\", Field, 0, \"\"},\n\t\t{\"OpError.Err\", Field, 0, \"\"},\n\t\t{\"OpError.Net\", Field, 0, \"\"},\n\t\t{\"OpError.Op\", Field, 0, \"\"},\n\t\t{\"OpError.Source\", Field, 5, \"\"},\n\t\t{\"PacketConn\", Type, 0, \"\"},\n\t\t{\"ParseCIDR\", Func, 0, \"func(s string) (IP, *IPNet, error)\"},\n\t\t{\"ParseError\", Type, 0, \"\"},\n\t\t{\"ParseError.Text\", Field, 0, \"\"},\n\t\t{\"ParseError.Type\", Field, 0, \"\"},\n\t\t{\"ParseIP\", Func, 0, \"func(s string) IP\"},\n\t\t{\"ParseMAC\", Func, 0, \"func(s string) (hw HardwareAddr, err error)\"},\n\t\t{\"Pipe\", Func, 0, \"func() (Conn, Conn)\"},\n\t\t{\"ResolveIPAddr\", Func, 0, \"func(network string, address string) (*IPAddr, error)\"},\n\t\t{\"ResolveTCPAddr\", Func, 0, \"func(network string, address string) (*TCPAddr, error)\"},\n\t\t{\"ResolveUDPAddr\", Func, 0, \"func(network string, address string) (*UDPAddr, error)\"},\n\t\t{\"ResolveUnixAddr\", Func, 0, \"func(network string, address string) (*UnixAddr, error)\"},\n\t\t{\"Resolver\", Type, 8, \"\"},\n\t\t{\"Resolver.Dial\", Field, 9, \"\"},\n\t\t{\"Resolver.PreferGo\", Field, 8, \"\"},\n\t\t{\"Resolver.StrictErrors\", Field, 9, \"\"},\n\t\t{\"SRV\", Type, 0, \"\"},\n\t\t{\"SRV.Port\", Field, 0, \"\"},\n\t\t{\"SRV.Priority\", Field, 0, \"\"},\n\t\t{\"SRV.Target\", Field, 0, \"\"},\n\t\t{\"SRV.Weight\", Field, 0, \"\"},\n\t\t{\"SplitHostPort\", Func, 0, \"func(hostport string) (host string, port string, err error)\"},\n\t\t{\"TCPAddr\", Type, 0, \"\"},\n\t\t{\"TCPAddr.IP\", Field, 0, \"\"},\n\t\t{\"TCPAddr.Port\", Field, 0, \"\"},\n\t\t{\"TCPAddr.Zone\", Field, 1, \"\"},\n\t\t{\"TCPAddrFromAddrPort\", Func, 18, \"func(addr netip.AddrPort) *TCPAddr\"},\n\t\t{\"TCPConn\", Type, 0, \"\"},\n\t\t{\"TCPListener\", Type, 0, \"\"},\n\t\t{\"UDPAddr\", Type, 0, \"\"},\n\t\t{\"UDPAddr.IP\", Field, 0, \"\"},\n\t\t{\"UDPAddr.Port\", Field, 0, \"\"},\n\t\t{\"UDPAddr.Zone\", Field, 1, \"\"},\n\t\t{\"UDPAddrFromAddrPort\", Func, 18, \"func(addr netip.AddrPort) *UDPAddr\"},\n\t\t{\"UDPConn\", Type, 0, \"\"},\n\t\t{\"UnixAddr\", Type, 0, \"\"},\n\t\t{\"UnixAddr.Name\", Field, 0, \"\"},\n\t\t{\"UnixAddr.Net\", Field, 0, \"\"},\n\t\t{\"UnixConn\", Type, 0, \"\"},\n\t\t{\"UnixListener\", Type, 0, \"\"},\n\t\t{\"UnknownNetworkError\", Type, 0, \"\"},\n\t},\n\t\"net/http\": {\n\t\t{\"(*Client).CloseIdleConnections\", Method, 12, \"\"},\n\t\t{\"(*Client).Do\", Method, 0, \"\"},\n\t\t{\"(*Client).Get\", Method, 0, \"\"},\n\t\t{\"(*Client).Head\", Method, 0, \"\"},\n\t\t{\"(*Client).Post\", Method, 0, \"\"},\n\t\t{\"(*Client).PostForm\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Available\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).Close\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).Err\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).InFlight\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).Release\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).Reserve\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).RoundTrip\", Method, 26, \"\"},\n\t\t{\"(*ClientConn).SetStateHook\", Method, 26, \"\"},\n\t\t{\"(*Cookie).String\", Method, 0, \"\"},\n\t\t{\"(*Cookie).Valid\", Method, 18, \"\"},\n\t\t{\"(*CrossOriginProtection).AddInsecureBypassPattern\", Method, 25, \"\"},\n\t\t{\"(*CrossOriginProtection).AddTrustedOrigin\", Method, 25, \"\"},\n\t\t{\"(*CrossOriginProtection).Check\", Method, 25, \"\"},\n\t\t{\"(*CrossOriginProtection).Handler\", Method, 25, \"\"},\n\t\t{\"(*CrossOriginProtection).SetDenyHandler\", Method, 25, \"\"},\n\t\t{\"(*MaxBytesError).Error\", Method, 19, \"\"},\n\t\t{\"(*ProtocolError).Error\", Method, 0, \"\"},\n\t\t{\"(*ProtocolError).Is\", Method, 21, \"\"},\n\t\t{\"(*Protocols).SetHTTP1\", Method, 24, \"\"},\n\t\t{\"(*Protocols).SetHTTP2\", Method, 24, \"\"},\n\t\t{\"(*Protocols).SetUnencryptedHTTP2\", Method, 24, \"\"},\n\t\t{\"(*Request).AddCookie\", Method, 0, \"\"},\n\t\t{\"(*Request).BasicAuth\", Method, 4, \"\"},\n\t\t{\"(*Request).Clone\", Method, 13, \"\"},\n\t\t{\"(*Request).Context\", Method, 7, \"\"},\n\t\t{\"(*Request).Cookie\", Method, 0, \"\"},\n\t\t{\"(*Request).Cookies\", Method, 0, \"\"},\n\t\t{\"(*Request).CookiesNamed\", Method, 23, \"\"},\n\t\t{\"(*Request).FormFile\", Method, 0, \"\"},\n\t\t{\"(*Request).FormValue\", Method, 0, \"\"},\n\t\t{\"(*Request).MultipartReader\", Method, 0, \"\"},\n\t\t{\"(*Request).ParseForm\", Method, 0, \"\"},\n\t\t{\"(*Request).ParseMultipartForm\", Method, 0, \"\"},\n\t\t{\"(*Request).PathValue\", Method, 22, \"\"},\n\t\t{\"(*Request).PostFormValue\", Method, 1, \"\"},\n\t\t{\"(*Request).ProtoAtLeast\", Method, 0, \"\"},\n\t\t{\"(*Request).Referer\", Method, 0, \"\"},\n\t\t{\"(*Request).SetBasicAuth\", Method, 0, \"\"},\n\t\t{\"(*Request).SetPathValue\", Method, 22, \"\"},\n\t\t{\"(*Request).UserAgent\", Method, 0, \"\"},\n\t\t{\"(*Request).WithContext\", Method, 7, \"\"},\n\t\t{\"(*Request).Write\", Method, 0, \"\"},\n\t\t{\"(*Request).WriteProxy\", Method, 0, \"\"},\n\t\t{\"(*Response).Cookies\", Method, 0, \"\"},\n\t\t{\"(*Response).Location\", Method, 0, \"\"},\n\t\t{\"(*Response).ProtoAtLeast\", Method, 0, \"\"},\n\t\t{\"(*Response).Write\", Method, 0, \"\"},\n\t\t{\"(*ResponseController).EnableFullDuplex\", Method, 21, \"\"},\n\t\t{\"(*ResponseController).Flush\", Method, 20, \"\"},\n\t\t{\"(*ResponseController).Hijack\", Method, 20, \"\"},\n\t\t{\"(*ResponseController).SetReadDeadline\", Method, 20, \"\"},\n\t\t{\"(*ResponseController).SetWriteDeadline\", Method, 20, \"\"},\n\t\t{\"(*ServeMux).Handle\", Method, 0, \"\"},\n\t\t{\"(*ServeMux).HandleFunc\", Method, 0, \"\"},\n\t\t{\"(*ServeMux).Handler\", Method, 1, \"\"},\n\t\t{\"(*ServeMux).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"(*Server).Close\", Method, 8, \"\"},\n\t\t{\"(*Server).ListenAndServe\", Method, 0, \"\"},\n\t\t{\"(*Server).ListenAndServeTLS\", Method, 0, \"\"},\n\t\t{\"(*Server).RegisterOnShutdown\", Method, 9, \"\"},\n\t\t{\"(*Server).Serve\", Method, 0, \"\"},\n\t\t{\"(*Server).ServeTLS\", Method, 9, \"\"},\n\t\t{\"(*Server).SetKeepAlivesEnabled\", Method, 3, \"\"},\n\t\t{\"(*Server).Shutdown\", Method, 8, \"\"},\n\t\t{\"(*Transport).CancelRequest\", Method, 1, \"\"},\n\t\t{\"(*Transport).Clone\", Method, 13, \"\"},\n\t\t{\"(*Transport).CloseIdleConnections\", Method, 0, \"\"},\n\t\t{\"(*Transport).NewClientConn\", Method, 26, \"\"},\n\t\t{\"(*Transport).RegisterProtocol\", Method, 0, \"\"},\n\t\t{\"(*Transport).RoundTrip\", Method, 0, \"\"},\n\t\t{\"(CloseNotifier).CloseNotify\", Method, 1, \"\"},\n\t\t{\"(ConnState).String\", Method, 3, \"\"},\n\t\t{\"(CookieJar).Cookies\", Method, 0, \"\"},\n\t\t{\"(CookieJar).SetCookies\", Method, 0, \"\"},\n\t\t{\"(Dir).Open\", Method, 0, \"\"},\n\t\t{\"(File).Close\", Method, 0, \"\"},\n\t\t{\"(File).Read\", Method, 0, \"\"},\n\t\t{\"(File).Readdir\", Method, 0, \"\"},\n\t\t{\"(File).Seek\", Method, 0, \"\"},\n\t\t{\"(File).Stat\", Method, 0, \"\"},\n\t\t{\"(FileSystem).Open\", Method, 0, \"\"},\n\t\t{\"(Flusher).Flush\", Method, 0, \"\"},\n\t\t{\"(Handler).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"(HandlerFunc).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"(Header).Add\", Method, 0, \"\"},\n\t\t{\"(Header).Clone\", Method, 13, \"\"},\n\t\t{\"(Header).Del\", Method, 0, \"\"},\n\t\t{\"(Header).Get\", Method, 0, \"\"},\n\t\t{\"(Header).Set\", Method, 0, \"\"},\n\t\t{\"(Header).Values\", Method, 14, \"\"},\n\t\t{\"(Header).Write\", Method, 0, \"\"},\n\t\t{\"(Header).WriteSubset\", Method, 0, \"\"},\n\t\t{\"(Hijacker).Hijack\", Method, 0, \"\"},\n\t\t{\"(Protocols).HTTP1\", Method, 24, \"\"},\n\t\t{\"(Protocols).HTTP2\", Method, 24, \"\"},\n\t\t{\"(Protocols).String\", Method, 24, \"\"},\n\t\t{\"(Protocols).UnencryptedHTTP2\", Method, 24, \"\"},\n\t\t{\"(Pusher).Push\", Method, 8, \"\"},\n\t\t{\"(ResponseWriter).Header\", Method, 0, \"\"},\n\t\t{\"(ResponseWriter).Write\", Method, 0, \"\"},\n\t\t{\"(ResponseWriter).WriteHeader\", Method, 0, \"\"},\n\t\t{\"(RoundTripper).RoundTrip\", Method, 0, \"\"},\n\t\t{\"AllowQuerySemicolons\", Func, 17, \"func(h Handler) Handler\"},\n\t\t{\"CanonicalHeaderKey\", Func, 0, \"func(s string) string\"},\n\t\t{\"Client\", Type, 0, \"\"},\n\t\t{\"Client.CheckRedirect\", Field, 0, \"\"},\n\t\t{\"Client.Jar\", Field, 0, \"\"},\n\t\t{\"Client.Timeout\", Field, 3, \"\"},\n\t\t{\"Client.Transport\", Field, 0, \"\"},\n\t\t{\"ClientConn\", Type, 26, \"\"},\n\t\t{\"CloseNotifier\", Type, 1, \"\"},\n\t\t{\"ConnState\", Type, 3, \"\"},\n\t\t{\"Cookie\", Type, 0, \"\"},\n\t\t{\"Cookie.Domain\", Field, 0, \"\"},\n\t\t{\"Cookie.Expires\", Field, 0, \"\"},\n\t\t{\"Cookie.HttpOnly\", Field, 0, \"\"},\n\t\t{\"Cookie.MaxAge\", Field, 0, \"\"},\n\t\t{\"Cookie.Name\", Field, 0, \"\"},\n\t\t{\"Cookie.Partitioned\", Field, 23, \"\"},\n\t\t{\"Cookie.Path\", Field, 0, \"\"},\n\t\t{\"Cookie.Quoted\", Field, 23, \"\"},\n\t\t{\"Cookie.Raw\", Field, 0, \"\"},\n\t\t{\"Cookie.RawExpires\", Field, 0, \"\"},\n\t\t{\"Cookie.SameSite\", Field, 11, \"\"},\n\t\t{\"Cookie.Secure\", Field, 0, \"\"},\n\t\t{\"Cookie.Unparsed\", Field, 0, \"\"},\n\t\t{\"Cookie.Value\", Field, 0, \"\"},\n\t\t{\"CookieJar\", Type, 0, \"\"},\n\t\t{\"CrossOriginProtection\", Type, 25, \"\"},\n\t\t{\"DefaultClient\", Var, 0, \"\"},\n\t\t{\"DefaultMaxHeaderBytes\", Const, 0, \"\"},\n\t\t{\"DefaultMaxIdleConnsPerHost\", Const, 0, \"\"},\n\t\t{\"DefaultServeMux\", Var, 0, \"\"},\n\t\t{\"DefaultTransport\", Var, 0, \"\"},\n\t\t{\"DetectContentType\", Func, 0, \"func(data []byte) string\"},\n\t\t{\"Dir\", Type, 0, \"\"},\n\t\t{\"ErrAbortHandler\", Var, 8, \"\"},\n\t\t{\"ErrBodyNotAllowed\", Var, 0, \"\"},\n\t\t{\"ErrBodyReadAfterClose\", Var, 0, \"\"},\n\t\t{\"ErrContentLength\", Var, 0, \"\"},\n\t\t{\"ErrHandlerTimeout\", Var, 0, \"\"},\n\t\t{\"ErrHeaderTooLong\", Var, 0, \"\"},\n\t\t{\"ErrHijacked\", Var, 0, \"\"},\n\t\t{\"ErrLineTooLong\", Var, 0, \"\"},\n\t\t{\"ErrMissingBoundary\", Var, 0, \"\"},\n\t\t{\"ErrMissingContentLength\", Var, 0, \"\"},\n\t\t{\"ErrMissingFile\", Var, 0, \"\"},\n\t\t{\"ErrNoCookie\", Var, 0, \"\"},\n\t\t{\"ErrNoLocation\", Var, 0, \"\"},\n\t\t{\"ErrNotMultipart\", Var, 0, \"\"},\n\t\t{\"ErrNotSupported\", Var, 0, \"\"},\n\t\t{\"ErrSchemeMismatch\", Var, 21, \"\"},\n\t\t{\"ErrServerClosed\", Var, 8, \"\"},\n\t\t{\"ErrShortBody\", Var, 0, \"\"},\n\t\t{\"ErrSkipAltProtocol\", Var, 6, \"\"},\n\t\t{\"ErrUnexpectedTrailer\", Var, 0, \"\"},\n\t\t{\"ErrUseLastResponse\", Var, 7, \"\"},\n\t\t{\"ErrWriteAfterFlush\", Var, 0, \"\"},\n\t\t{\"Error\", Func, 0, \"func(w ResponseWriter, error string, code int)\"},\n\t\t{\"FS\", Func, 16, \"func(fsys fs.FS) FileSystem\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"FileServer\", Func, 0, \"func(root FileSystem) Handler\"},\n\t\t{\"FileServerFS\", Func, 22, \"func(root fs.FS) Handler\"},\n\t\t{\"FileSystem\", Type, 0, \"\"},\n\t\t{\"Flusher\", Type, 0, \"\"},\n\t\t{\"Get\", Func, 0, \"func(url string) (resp *Response, err error)\"},\n\t\t{\"HTTP2Config\", Type, 24, \"\"},\n\t\t{\"HTTP2Config.CountError\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxConcurrentStreams\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxDecoderHeaderTableSize\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxEncoderHeaderTableSize\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxReadFrameSize\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxReceiveBufferPerConnection\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.MaxReceiveBufferPerStream\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.PermitProhibitedCipherSuites\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.PingTimeout\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.SendPingTimeout\", Field, 24, \"\"},\n\t\t{\"HTTP2Config.StrictMaxConcurrentRequests\", Field, 26, \"\"},\n\t\t{\"HTTP2Config.WriteByteTimeout\", Field, 24, \"\"},\n\t\t{\"Handle\", Func, 0, \"func(pattern string, handler Handler)\"},\n\t\t{\"HandleFunc\", Func, 0, \"func(pattern string, handler func(ResponseWriter, *Request))\"},\n\t\t{\"Handler\", Type, 0, \"\"},\n\t\t{\"HandlerFunc\", Type, 0, \"\"},\n\t\t{\"Head\", Func, 0, \"func(url string) (resp *Response, err error)\"},\n\t\t{\"Header\", Type, 0, \"\"},\n\t\t{\"Hijacker\", Type, 0, \"\"},\n\t\t{\"ListenAndServe\", Func, 0, \"func(addr string, handler Handler) error\"},\n\t\t{\"ListenAndServeTLS\", Func, 0, \"func(addr string, certFile string, keyFile string, handler Handler) error\"},\n\t\t{\"LocalAddrContextKey\", Var, 7, \"\"},\n\t\t{\"MaxBytesError\", Type, 19, \"\"},\n\t\t{\"MaxBytesError.Limit\", Field, 19, \"\"},\n\t\t{\"MaxBytesHandler\", Func, 18, \"func(h Handler, n int64) Handler\"},\n\t\t{\"MaxBytesReader\", Func, 0, \"func(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser\"},\n\t\t{\"MethodConnect\", Const, 6, \"\"},\n\t\t{\"MethodDelete\", Const, 6, \"\"},\n\t\t{\"MethodGet\", Const, 6, \"\"},\n\t\t{\"MethodHead\", Const, 6, \"\"},\n\t\t{\"MethodOptions\", Const, 6, \"\"},\n\t\t{\"MethodPatch\", Const, 6, \"\"},\n\t\t{\"MethodPost\", Const, 6, \"\"},\n\t\t{\"MethodPut\", Const, 6, \"\"},\n\t\t{\"MethodTrace\", Const, 6, \"\"},\n\t\t{\"NewCrossOriginProtection\", Func, 25, \"func() *CrossOriginProtection\"},\n\t\t{\"NewFileTransport\", Func, 0, \"func(fs FileSystem) RoundTripper\"},\n\t\t{\"NewFileTransportFS\", Func, 22, \"func(fsys fs.FS) RoundTripper\"},\n\t\t{\"NewRequest\", Func, 0, \"func(method string, url string, body io.Reader) (*Request, error)\"},\n\t\t{\"NewRequestWithContext\", Func, 13, \"func(ctx context.Context, method string, url string, body io.Reader) (*Request, error)\"},\n\t\t{\"NewResponseController\", Func, 20, \"func(rw ResponseWriter) *ResponseController\"},\n\t\t{\"NewServeMux\", Func, 0, \"func() *ServeMux\"},\n\t\t{\"NoBody\", Var, 8, \"\"},\n\t\t{\"NotFound\", Func, 0, \"func(w ResponseWriter, r *Request)\"},\n\t\t{\"NotFoundHandler\", Func, 0, \"func() Handler\"},\n\t\t{\"ParseCookie\", Func, 23, \"func(line string) ([]*Cookie, error)\"},\n\t\t{\"ParseHTTPVersion\", Func, 0, \"func(vers string) (major int, minor int, ok bool)\"},\n\t\t{\"ParseSetCookie\", Func, 23, \"func(line string) (*Cookie, error)\"},\n\t\t{\"ParseTime\", Func, 1, \"func(text string) (t time.Time, err error)\"},\n\t\t{\"Post\", Func, 0, \"func(url string, contentType string, body io.Reader) (resp *Response, err error)\"},\n\t\t{\"PostForm\", Func, 0, \"func(url string, data url.Values) (resp *Response, err error)\"},\n\t\t{\"ProtocolError\", Type, 0, \"\"},\n\t\t{\"ProtocolError.ErrorString\", Field, 0, \"\"},\n\t\t{\"Protocols\", Type, 24, \"\"},\n\t\t{\"ProxyFromEnvironment\", Func, 0, \"func(req *Request) (*url.URL, error)\"},\n\t\t{\"ProxyURL\", Func, 0, \"func(fixedURL *url.URL) func(*Request) (*url.URL, error)\"},\n\t\t{\"PushOptions\", Type, 8, \"\"},\n\t\t{\"PushOptions.Header\", Field, 8, \"\"},\n\t\t{\"PushOptions.Method\", Field, 8, \"\"},\n\t\t{\"Pusher\", Type, 8, \"\"},\n\t\t{\"ReadRequest\", Func, 0, \"func(b *bufio.Reader) (*Request, error)\"},\n\t\t{\"ReadResponse\", Func, 0, \"func(r *bufio.Reader, req *Request) (*Response, error)\"},\n\t\t{\"Redirect\", Func, 0, \"func(w ResponseWriter, r *Request, url string, code int)\"},\n\t\t{\"RedirectHandler\", Func, 0, \"func(url string, code int) Handler\"},\n\t\t{\"Request\", Type, 0, \"\"},\n\t\t{\"Request.Body\", Field, 0, \"\"},\n\t\t{\"Request.Cancel\", Field, 5, \"\"},\n\t\t{\"Request.Close\", Field, 0, \"\"},\n\t\t{\"Request.ContentLength\", Field, 0, \"\"},\n\t\t{\"Request.Form\", Field, 0, \"\"},\n\t\t{\"Request.GetBody\", Field, 8, \"\"},\n\t\t{\"Request.Header\", Field, 0, \"\"},\n\t\t{\"Request.Host\", Field, 0, \"\"},\n\t\t{\"Request.Method\", Field, 0, \"\"},\n\t\t{\"Request.MultipartForm\", Field, 0, \"\"},\n\t\t{\"Request.Pattern\", Field, 23, \"\"},\n\t\t{\"Request.PostForm\", Field, 1, \"\"},\n\t\t{\"Request.Proto\", Field, 0, \"\"},\n\t\t{\"Request.ProtoMajor\", Field, 0, \"\"},\n\t\t{\"Request.ProtoMinor\", Field, 0, \"\"},\n\t\t{\"Request.RemoteAddr\", Field, 0, \"\"},\n\t\t{\"Request.RequestURI\", Field, 0, \"\"},\n\t\t{\"Request.Response\", Field, 7, \"\"},\n\t\t{\"Request.TLS\", Field, 0, \"\"},\n\t\t{\"Request.Trailer\", Field, 0, \"\"},\n\t\t{\"Request.TransferEncoding\", Field, 0, \"\"},\n\t\t{\"Request.URL\", Field, 0, \"\"},\n\t\t{\"Response\", Type, 0, \"\"},\n\t\t{\"Response.Body\", Field, 0, \"\"},\n\t\t{\"Response.Close\", Field, 0, \"\"},\n\t\t{\"Response.ContentLength\", Field, 0, \"\"},\n\t\t{\"Response.Header\", Field, 0, \"\"},\n\t\t{\"Response.Proto\", Field, 0, \"\"},\n\t\t{\"Response.ProtoMajor\", Field, 0, \"\"},\n\t\t{\"Response.ProtoMinor\", Field, 0, \"\"},\n\t\t{\"Response.Request\", Field, 0, \"\"},\n\t\t{\"Response.Status\", Field, 0, \"\"},\n\t\t{\"Response.StatusCode\", Field, 0, \"\"},\n\t\t{\"Response.TLS\", Field, 3, \"\"},\n\t\t{\"Response.Trailer\", Field, 0, \"\"},\n\t\t{\"Response.TransferEncoding\", Field, 0, \"\"},\n\t\t{\"Response.Uncompressed\", Field, 7, \"\"},\n\t\t{\"ResponseController\", Type, 20, \"\"},\n\t\t{\"ResponseWriter\", Type, 0, \"\"},\n\t\t{\"RoundTripper\", Type, 0, \"\"},\n\t\t{\"SameSite\", Type, 11, \"\"},\n\t\t{\"SameSiteDefaultMode\", Const, 11, \"\"},\n\t\t{\"SameSiteLaxMode\", Const, 11, \"\"},\n\t\t{\"SameSiteNoneMode\", Const, 13, \"\"},\n\t\t{\"SameSiteStrictMode\", Const, 11, \"\"},\n\t\t{\"Serve\", Func, 0, \"func(l net.Listener, handler Handler) error\"},\n\t\t{\"ServeContent\", Func, 0, \"func(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker)\"},\n\t\t{\"ServeFile\", Func, 0, \"func(w ResponseWriter, r *Request, name string)\"},\n\t\t{\"ServeFileFS\", Func, 22, \"func(w ResponseWriter, r *Request, fsys fs.FS, name string)\"},\n\t\t{\"ServeMux\", Type, 0, \"\"},\n\t\t{\"ServeTLS\", Func, 9, \"func(l net.Listener, handler Handler, certFile string, keyFile string) error\"},\n\t\t{\"Server\", Type, 0, \"\"},\n\t\t{\"Server.Addr\", Field, 0, \"\"},\n\t\t{\"Server.BaseContext\", Field, 13, \"\"},\n\t\t{\"Server.ConnContext\", Field, 13, \"\"},\n\t\t{\"Server.ConnState\", Field, 3, \"\"},\n\t\t{\"Server.DisableGeneralOptionsHandler\", Field, 20, \"\"},\n\t\t{\"Server.ErrorLog\", Field, 3, \"\"},\n\t\t{\"Server.HTTP2\", Field, 24, \"\"},\n\t\t{\"Server.Handler\", Field, 0, \"\"},\n\t\t{\"Server.IdleTimeout\", Field, 8, \"\"},\n\t\t{\"Server.MaxHeaderBytes\", Field, 0, \"\"},\n\t\t{\"Server.Protocols\", Field, 24, \"\"},\n\t\t{\"Server.ReadHeaderTimeout\", Field, 8, \"\"},\n\t\t{\"Server.ReadTimeout\", Field, 0, \"\"},\n\t\t{\"Server.TLSConfig\", Field, 0, \"\"},\n\t\t{\"Server.TLSNextProto\", Field, 1, \"\"},\n\t\t{\"Server.WriteTimeout\", Field, 0, \"\"},\n\t\t{\"ServerContextKey\", Var, 7, \"\"},\n\t\t{\"SetCookie\", Func, 0, \"func(w ResponseWriter, cookie *Cookie)\"},\n\t\t{\"StateActive\", Const, 3, \"\"},\n\t\t{\"StateClosed\", Const, 3, \"\"},\n\t\t{\"StateHijacked\", Const, 3, \"\"},\n\t\t{\"StateIdle\", Const, 3, \"\"},\n\t\t{\"StateNew\", Const, 3, \"\"},\n\t\t{\"StatusAccepted\", Const, 0, \"\"},\n\t\t{\"StatusAlreadyReported\", Const, 7, \"\"},\n\t\t{\"StatusBadGateway\", Const, 0, \"\"},\n\t\t{\"StatusBadRequest\", Const, 0, \"\"},\n\t\t{\"StatusConflict\", Const, 0, \"\"},\n\t\t{\"StatusContinue\", Const, 0, \"\"},\n\t\t{\"StatusCreated\", Const, 0, \"\"},\n\t\t{\"StatusEarlyHints\", Const, 13, \"\"},\n\t\t{\"StatusExpectationFailed\", Const, 0, \"\"},\n\t\t{\"StatusFailedDependency\", Const, 7, \"\"},\n\t\t{\"StatusForbidden\", Const, 0, \"\"},\n\t\t{\"StatusFound\", Const, 0, \"\"},\n\t\t{\"StatusGatewayTimeout\", Const, 0, \"\"},\n\t\t{\"StatusGone\", Const, 0, \"\"},\n\t\t{\"StatusHTTPVersionNotSupported\", Const, 0, \"\"},\n\t\t{\"StatusIMUsed\", Const, 7, \"\"},\n\t\t{\"StatusInsufficientStorage\", Const, 7, \"\"},\n\t\t{\"StatusInternalServerError\", Const, 0, \"\"},\n\t\t{\"StatusLengthRequired\", Const, 0, \"\"},\n\t\t{\"StatusLocked\", Const, 7, \"\"},\n\t\t{\"StatusLoopDetected\", Const, 7, \"\"},\n\t\t{\"StatusMethodNotAllowed\", Const, 0, \"\"},\n\t\t{\"StatusMisdirectedRequest\", Const, 11, \"\"},\n\t\t{\"StatusMovedPermanently\", Const, 0, \"\"},\n\t\t{\"StatusMultiStatus\", Const, 7, \"\"},\n\t\t{\"StatusMultipleChoices\", Const, 0, \"\"},\n\t\t{\"StatusNetworkAuthenticationRequired\", Const, 6, \"\"},\n\t\t{\"StatusNoContent\", Const, 0, \"\"},\n\t\t{\"StatusNonAuthoritativeInfo\", Const, 0, \"\"},\n\t\t{\"StatusNotAcceptable\", Const, 0, \"\"},\n\t\t{\"StatusNotExtended\", Const, 7, \"\"},\n\t\t{\"StatusNotFound\", Const, 0, \"\"},\n\t\t{\"StatusNotImplemented\", Const, 0, \"\"},\n\t\t{\"StatusNotModified\", Const, 0, \"\"},\n\t\t{\"StatusOK\", Const, 0, \"\"},\n\t\t{\"StatusPartialContent\", Const, 0, \"\"},\n\t\t{\"StatusPaymentRequired\", Const, 0, \"\"},\n\t\t{\"StatusPermanentRedirect\", Const, 7, \"\"},\n\t\t{\"StatusPreconditionFailed\", Const, 0, \"\"},\n\t\t{\"StatusPreconditionRequired\", Const, 6, \"\"},\n\t\t{\"StatusProcessing\", Const, 7, \"\"},\n\t\t{\"StatusProxyAuthRequired\", Const, 0, \"\"},\n\t\t{\"StatusRequestEntityTooLarge\", Const, 0, \"\"},\n\t\t{\"StatusRequestHeaderFieldsTooLarge\", Const, 6, \"\"},\n\t\t{\"StatusRequestTimeout\", Const, 0, \"\"},\n\t\t{\"StatusRequestURITooLong\", Const, 0, \"\"},\n\t\t{\"StatusRequestedRangeNotSatisfiable\", Const, 0, \"\"},\n\t\t{\"StatusResetContent\", Const, 0, \"\"},\n\t\t{\"StatusSeeOther\", Const, 0, \"\"},\n\t\t{\"StatusServiceUnavailable\", Const, 0, \"\"},\n\t\t{\"StatusSwitchingProtocols\", Const, 0, \"\"},\n\t\t{\"StatusTeapot\", Const, 0, \"\"},\n\t\t{\"StatusTemporaryRedirect\", Const, 0, \"\"},\n\t\t{\"StatusText\", Func, 0, \"func(code int) string\"},\n\t\t{\"StatusTooEarly\", Const, 12, \"\"},\n\t\t{\"StatusTooManyRequests\", Const, 6, \"\"},\n\t\t{\"StatusUnauthorized\", Const, 0, \"\"},\n\t\t{\"StatusUnavailableForLegalReasons\", Const, 6, \"\"},\n\t\t{\"StatusUnprocessableEntity\", Const, 7, \"\"},\n\t\t{\"StatusUnsupportedMediaType\", Const, 0, \"\"},\n\t\t{\"StatusUpgradeRequired\", Const, 7, \"\"},\n\t\t{\"StatusUseProxy\", Const, 0, \"\"},\n\t\t{\"StatusVariantAlsoNegotiates\", Const, 7, \"\"},\n\t\t{\"StripPrefix\", Func, 0, \"func(prefix string, h Handler) Handler\"},\n\t\t{\"TimeFormat\", Const, 0, \"\"},\n\t\t{\"TimeoutHandler\", Func, 0, \"func(h Handler, dt time.Duration, msg string) Handler\"},\n\t\t{\"TrailerPrefix\", Const, 8, \"\"},\n\t\t{\"Transport\", Type, 0, \"\"},\n\t\t{\"Transport.Dial\", Field, 0, \"\"},\n\t\t{\"Transport.DialContext\", Field, 7, \"\"},\n\t\t{\"Transport.DialTLS\", Field, 4, \"\"},\n\t\t{\"Transport.DialTLSContext\", Field, 14, \"\"},\n\t\t{\"Transport.DisableCompression\", Field, 0, \"\"},\n\t\t{\"Transport.DisableKeepAlives\", Field, 0, \"\"},\n\t\t{\"Transport.ExpectContinueTimeout\", Field, 6, \"\"},\n\t\t{\"Transport.ForceAttemptHTTP2\", Field, 13, \"\"},\n\t\t{\"Transport.GetProxyConnectHeader\", Field, 16, \"\"},\n\t\t{\"Transport.HTTP2\", Field, 24, \"\"},\n\t\t{\"Transport.IdleConnTimeout\", Field, 7, \"\"},\n\t\t{\"Transport.MaxConnsPerHost\", Field, 11, \"\"},\n\t\t{\"Transport.MaxIdleConns\", Field, 7, \"\"},\n\t\t{\"Transport.MaxIdleConnsPerHost\", Field, 0, \"\"},\n\t\t{\"Transport.MaxResponseHeaderBytes\", Field, 7, \"\"},\n\t\t{\"Transport.OnProxyConnectResponse\", Field, 20, \"\"},\n\t\t{\"Transport.Protocols\", Field, 24, \"\"},\n\t\t{\"Transport.Proxy\", Field, 0, \"\"},\n\t\t{\"Transport.ProxyConnectHeader\", Field, 8, \"\"},\n\t\t{\"Transport.ReadBufferSize\", Field, 13, \"\"},\n\t\t{\"Transport.ResponseHeaderTimeout\", Field, 1, \"\"},\n\t\t{\"Transport.TLSClientConfig\", Field, 0, \"\"},\n\t\t{\"Transport.TLSHandshakeTimeout\", Field, 3, \"\"},\n\t\t{\"Transport.TLSNextProto\", Field, 6, \"\"},\n\t\t{\"Transport.WriteBufferSize\", Field, 13, \"\"},\n\t},\n\t\"net/http/cgi\": {\n\t\t{\"(*Handler).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"Handler\", Type, 0, \"\"},\n\t\t{\"Handler.Args\", Field, 0, \"\"},\n\t\t{\"Handler.Dir\", Field, 0, \"\"},\n\t\t{\"Handler.Env\", Field, 0, \"\"},\n\t\t{\"Handler.InheritEnv\", Field, 0, \"\"},\n\t\t{\"Handler.Logger\", Field, 0, \"\"},\n\t\t{\"Handler.Path\", Field, 0, \"\"},\n\t\t{\"Handler.PathLocationHandler\", Field, 0, \"\"},\n\t\t{\"Handler.Root\", Field, 0, \"\"},\n\t\t{\"Handler.Stderr\", Field, 7, \"\"},\n\t\t{\"Request\", Func, 0, \"func() (*http.Request, error)\"},\n\t\t{\"RequestFromMap\", Func, 0, \"func(params map[string]string) (*http.Request, error)\"},\n\t\t{\"Serve\", Func, 0, \"func(handler http.Handler) error\"},\n\t},\n\t\"net/http/cookiejar\": {\n\t\t{\"(*Jar).Cookies\", Method, 1, \"\"},\n\t\t{\"(*Jar).SetCookies\", Method, 1, \"\"},\n\t\t{\"(PublicSuffixList).PublicSuffix\", Method, 1, \"\"},\n\t\t{\"(PublicSuffixList).String\", Method, 1, \"\"},\n\t\t{\"Jar\", Type, 1, \"\"},\n\t\t{\"New\", Func, 1, \"func(o *Options) (*Jar, error)\"},\n\t\t{\"Options\", Type, 1, \"\"},\n\t\t{\"Options.PublicSuffixList\", Field, 1, \"\"},\n\t\t{\"PublicSuffixList\", Type, 1, \"\"},\n\t},\n\t\"net/http/fcgi\": {\n\t\t{\"ErrConnClosed\", Var, 5, \"\"},\n\t\t{\"ErrRequestAborted\", Var, 5, \"\"},\n\t\t{\"ProcessEnv\", Func, 9, \"func(r *http.Request) map[string]string\"},\n\t\t{\"Serve\", Func, 0, \"func(l net.Listener, handler http.Handler) error\"},\n\t},\n\t\"net/http/httptest\": {\n\t\t{\"(*ResponseRecorder).Flush\", Method, 0, \"\"},\n\t\t{\"(*ResponseRecorder).Header\", Method, 0, \"\"},\n\t\t{\"(*ResponseRecorder).Result\", Method, 7, \"\"},\n\t\t{\"(*ResponseRecorder).Write\", Method, 0, \"\"},\n\t\t{\"(*ResponseRecorder).WriteHeader\", Method, 0, \"\"},\n\t\t{\"(*ResponseRecorder).WriteString\", Method, 6, \"\"},\n\t\t{\"(*Server).Certificate\", Method, 9, \"\"},\n\t\t{\"(*Server).Client\", Method, 9, \"\"},\n\t\t{\"(*Server).Close\", Method, 0, \"\"},\n\t\t{\"(*Server).CloseClientConnections\", Method, 0, \"\"},\n\t\t{\"(*Server).Start\", Method, 0, \"\"},\n\t\t{\"(*Server).StartTLS\", Method, 0, \"\"},\n\t\t{\"DefaultRemoteAddr\", Const, 0, \"\"},\n\t\t{\"NewRecorder\", Func, 0, \"func() *ResponseRecorder\"},\n\t\t{\"NewRequest\", Func, 7, \"func(method string, target string, body io.Reader) *http.Request\"},\n\t\t{\"NewRequestWithContext\", Func, 23, \"func(ctx context.Context, method string, target string, body io.Reader) *http.Request\"},\n\t\t{\"NewServer\", Func, 0, \"func(handler http.Handler) *Server\"},\n\t\t{\"NewTLSServer\", Func, 0, \"func(handler http.Handler) *Server\"},\n\t\t{\"NewUnstartedServer\", Func, 0, \"func(handler http.Handler) *Server\"},\n\t\t{\"ResponseRecorder\", Type, 0, \"\"},\n\t\t{\"ResponseRecorder.Body\", Field, 0, \"\"},\n\t\t{\"ResponseRecorder.Code\", Field, 0, \"\"},\n\t\t{\"ResponseRecorder.Flushed\", Field, 0, \"\"},\n\t\t{\"ResponseRecorder.HeaderMap\", Field, 0, \"\"},\n\t\t{\"Server\", Type, 0, \"\"},\n\t\t{\"Server.Config\", Field, 0, \"\"},\n\t\t{\"Server.EnableHTTP2\", Field, 14, \"\"},\n\t\t{\"Server.Listener\", Field, 0, \"\"},\n\t\t{\"Server.TLS\", Field, 0, \"\"},\n\t\t{\"Server.URL\", Field, 0, \"\"},\n\t},\n\t\"net/http/httptrace\": {\n\t\t{\"ClientTrace\", Type, 7, \"\"},\n\t\t{\"ClientTrace.ConnectDone\", Field, 7, \"\"},\n\t\t{\"ClientTrace.ConnectStart\", Field, 7, \"\"},\n\t\t{\"ClientTrace.DNSDone\", Field, 7, \"\"},\n\t\t{\"ClientTrace.DNSStart\", Field, 7, \"\"},\n\t\t{\"ClientTrace.GetConn\", Field, 7, \"\"},\n\t\t{\"ClientTrace.Got100Continue\", Field, 7, \"\"},\n\t\t{\"ClientTrace.Got1xxResponse\", Field, 11, \"\"},\n\t\t{\"ClientTrace.GotConn\", Field, 7, \"\"},\n\t\t{\"ClientTrace.GotFirstResponseByte\", Field, 7, \"\"},\n\t\t{\"ClientTrace.PutIdleConn\", Field, 7, \"\"},\n\t\t{\"ClientTrace.TLSHandshakeDone\", Field, 8, \"\"},\n\t\t{\"ClientTrace.TLSHandshakeStart\", Field, 8, \"\"},\n\t\t{\"ClientTrace.Wait100Continue\", Field, 7, \"\"},\n\t\t{\"ClientTrace.WroteHeaderField\", Field, 11, \"\"},\n\t\t{\"ClientTrace.WroteHeaders\", Field, 7, \"\"},\n\t\t{\"ClientTrace.WroteRequest\", Field, 7, \"\"},\n\t\t{\"ContextClientTrace\", Func, 7, \"func(ctx context.Context) *ClientTrace\"},\n\t\t{\"DNSDoneInfo\", Type, 7, \"\"},\n\t\t{\"DNSDoneInfo.Addrs\", Field, 7, \"\"},\n\t\t{\"DNSDoneInfo.Coalesced\", Field, 7, \"\"},\n\t\t{\"DNSDoneInfo.Err\", Field, 7, \"\"},\n\t\t{\"DNSStartInfo\", Type, 7, \"\"},\n\t\t{\"DNSStartInfo.Host\", Field, 7, \"\"},\n\t\t{\"GotConnInfo\", Type, 7, \"\"},\n\t\t{\"GotConnInfo.Conn\", Field, 7, \"\"},\n\t\t{\"GotConnInfo.IdleTime\", Field, 7, \"\"},\n\t\t{\"GotConnInfo.Reused\", Field, 7, \"\"},\n\t\t{\"GotConnInfo.WasIdle\", Field, 7, \"\"},\n\t\t{\"WithClientTrace\", Func, 7, \"func(ctx context.Context, trace *ClientTrace) context.Context\"},\n\t\t{\"WroteRequestInfo\", Type, 7, \"\"},\n\t\t{\"WroteRequestInfo.Err\", Field, 7, \"\"},\n\t},\n\t\"net/http/httputil\": {\n\t\t{\"(*ClientConn).Close\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Do\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Hijack\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Pending\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Read\", Method, 0, \"\"},\n\t\t{\"(*ClientConn).Write\", Method, 0, \"\"},\n\t\t{\"(*ProxyRequest).SetURL\", Method, 20, \"\"},\n\t\t{\"(*ProxyRequest).SetXForwarded\", Method, 20, \"\"},\n\t\t{\"(*ReverseProxy).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"(*ServerConn).Close\", Method, 0, \"\"},\n\t\t{\"(*ServerConn).Hijack\", Method, 0, \"\"},\n\t\t{\"(*ServerConn).Pending\", Method, 0, \"\"},\n\t\t{\"(*ServerConn).Read\", Method, 0, \"\"},\n\t\t{\"(*ServerConn).Write\", Method, 0, \"\"},\n\t\t{\"(BufferPool).Get\", Method, 6, \"\"},\n\t\t{\"(BufferPool).Put\", Method, 6, \"\"},\n\t\t{\"BufferPool\", Type, 6, \"\"},\n\t\t{\"ClientConn\", Type, 0, \"\"},\n\t\t{\"DumpRequest\", Func, 0, \"func(req *http.Request, body bool) ([]byte, error)\"},\n\t\t{\"DumpRequestOut\", Func, 0, \"func(req *http.Request, body bool) ([]byte, error)\"},\n\t\t{\"DumpResponse\", Func, 0, \"func(resp *http.Response, body bool) ([]byte, error)\"},\n\t\t{\"ErrClosed\", Var, 0, \"\"},\n\t\t{\"ErrLineTooLong\", Var, 0, \"\"},\n\t\t{\"ErrPersistEOF\", Var, 0, \"\"},\n\t\t{\"ErrPipeline\", Var, 0, \"\"},\n\t\t{\"NewChunkedReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"NewChunkedWriter\", Func, 0, \"func(w io.Writer) io.WriteCloser\"},\n\t\t{\"NewClientConn\", Func, 0, \"func(c net.Conn, r *bufio.Reader) *ClientConn\"},\n\t\t{\"NewProxyClientConn\", Func, 0, \"func(c net.Conn, r *bufio.Reader) *ClientConn\"},\n\t\t{\"NewServerConn\", Func, 0, \"func(c net.Conn, r *bufio.Reader) *ServerConn\"},\n\t\t{\"NewSingleHostReverseProxy\", Func, 0, \"func(target *url.URL) *ReverseProxy\"},\n\t\t{\"ProxyRequest\", Type, 20, \"\"},\n\t\t{\"ProxyRequest.In\", Field, 20, \"\"},\n\t\t{\"ProxyRequest.Out\", Field, 20, \"\"},\n\t\t{\"ReverseProxy\", Type, 0, \"\"},\n\t\t{\"ReverseProxy.BufferPool\", Field, 6, \"\"},\n\t\t{\"ReverseProxy.Director\", Field, 0, \"\"},\n\t\t{\"ReverseProxy.ErrorHandler\", Field, 11, \"\"},\n\t\t{\"ReverseProxy.ErrorLog\", Field, 4, \"\"},\n\t\t{\"ReverseProxy.FlushInterval\", Field, 0, \"\"},\n\t\t{\"ReverseProxy.ModifyResponse\", Field, 8, \"\"},\n\t\t{\"ReverseProxy.Rewrite\", Field, 20, \"\"},\n\t\t{\"ReverseProxy.Transport\", Field, 0, \"\"},\n\t\t{\"ServerConn\", Type, 0, \"\"},\n\t},\n\t\"net/http/pprof\": {\n\t\t{\"Cmdline\", Func, 0, \"func(w http.ResponseWriter, r *http.Request)\"},\n\t\t{\"Handler\", Func, 0, \"func(name string) http.Handler\"},\n\t\t{\"Index\", Func, 0, \"func(w http.ResponseWriter, r *http.Request)\"},\n\t\t{\"Profile\", Func, 0, \"func(w http.ResponseWriter, r *http.Request)\"},\n\t\t{\"Symbol\", Func, 0, \"func(w http.ResponseWriter, r *http.Request)\"},\n\t\t{\"Trace\", Func, 5, \"func(w http.ResponseWriter, r *http.Request)\"},\n\t},\n\t\"net/mail\": {\n\t\t{\"(*Address).String\", Method, 0, \"\"},\n\t\t{\"(*AddressParser).Parse\", Method, 5, \"\"},\n\t\t{\"(*AddressParser).ParseList\", Method, 5, \"\"},\n\t\t{\"(Header).AddressList\", Method, 0, \"\"},\n\t\t{\"(Header).Date\", Method, 0, \"\"},\n\t\t{\"(Header).Get\", Method, 0, \"\"},\n\t\t{\"Address\", Type, 0, \"\"},\n\t\t{\"Address.Address\", Field, 0, \"\"},\n\t\t{\"Address.Name\", Field, 0, \"\"},\n\t\t{\"AddressParser\", Type, 5, \"\"},\n\t\t{\"AddressParser.WordDecoder\", Field, 5, \"\"},\n\t\t{\"ErrHeaderNotPresent\", Var, 0, \"\"},\n\t\t{\"Header\", Type, 0, \"\"},\n\t\t{\"Message\", Type, 0, \"\"},\n\t\t{\"Message.Body\", Field, 0, \"\"},\n\t\t{\"Message.Header\", Field, 0, \"\"},\n\t\t{\"ParseAddress\", Func, 1, \"func(address string) (*Address, error)\"},\n\t\t{\"ParseAddressList\", Func, 1, \"func(list string) ([]*Address, error)\"},\n\t\t{\"ParseDate\", Func, 8, \"func(date string) (time.Time, error)\"},\n\t\t{\"ReadMessage\", Func, 0, \"func(r io.Reader) (msg *Message, err error)\"},\n\t},\n\t\"net/netip\": {\n\t\t{\"(*Addr).UnmarshalBinary\", Method, 18, \"\"},\n\t\t{\"(*Addr).UnmarshalText\", Method, 18, \"\"},\n\t\t{\"(*AddrPort).UnmarshalBinary\", Method, 18, \"\"},\n\t\t{\"(*AddrPort).UnmarshalText\", Method, 18, \"\"},\n\t\t{\"(*Prefix).UnmarshalBinary\", Method, 18, \"\"},\n\t\t{\"(*Prefix).UnmarshalText\", Method, 18, \"\"},\n\t\t{\"(Addr).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(Addr).AppendText\", Method, 24, \"\"},\n\t\t{\"(Addr).AppendTo\", Method, 18, \"\"},\n\t\t{\"(Addr).As16\", Method, 18, \"\"},\n\t\t{\"(Addr).As4\", Method, 18, \"\"},\n\t\t{\"(Addr).AsSlice\", Method, 18, \"\"},\n\t\t{\"(Addr).BitLen\", Method, 18, \"\"},\n\t\t{\"(Addr).Compare\", Method, 18, \"\"},\n\t\t{\"(Addr).Is4\", Method, 18, \"\"},\n\t\t{\"(Addr).Is4In6\", Method, 18, \"\"},\n\t\t{\"(Addr).Is6\", Method, 18, \"\"},\n\t\t{\"(Addr).IsGlobalUnicast\", Method, 18, \"\"},\n\t\t{\"(Addr).IsInterfaceLocalMulticast\", Method, 18, \"\"},\n\t\t{\"(Addr).IsLinkLocalMulticast\", Method, 18, \"\"},\n\t\t{\"(Addr).IsLinkLocalUnicast\", Method, 18, \"\"},\n\t\t{\"(Addr).IsLoopback\", Method, 18, \"\"},\n\t\t{\"(Addr).IsMulticast\", Method, 18, \"\"},\n\t\t{\"(Addr).IsPrivate\", Method, 18, \"\"},\n\t\t{\"(Addr).IsUnspecified\", Method, 18, \"\"},\n\t\t{\"(Addr).IsValid\", Method, 18, \"\"},\n\t\t{\"(Addr).Less\", Method, 18, \"\"},\n\t\t{\"(Addr).MarshalBinary\", Method, 18, \"\"},\n\t\t{\"(Addr).MarshalText\", Method, 18, \"\"},\n\t\t{\"(Addr).Next\", Method, 18, \"\"},\n\t\t{\"(Addr).Prefix\", Method, 18, \"\"},\n\t\t{\"(Addr).Prev\", Method, 18, \"\"},\n\t\t{\"(Addr).String\", Method, 18, \"\"},\n\t\t{\"(Addr).StringExpanded\", Method, 18, \"\"},\n\t\t{\"(Addr).Unmap\", Method, 18, \"\"},\n\t\t{\"(Addr).WithZone\", Method, 18, \"\"},\n\t\t{\"(Addr).Zone\", Method, 18, \"\"},\n\t\t{\"(AddrPort).Addr\", Method, 18, \"\"},\n\t\t{\"(AddrPort).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(AddrPort).AppendText\", Method, 24, \"\"},\n\t\t{\"(AddrPort).AppendTo\", Method, 18, \"\"},\n\t\t{\"(AddrPort).Compare\", Method, 22, \"\"},\n\t\t{\"(AddrPort).IsValid\", Method, 18, \"\"},\n\t\t{\"(AddrPort).MarshalBinary\", Method, 18, \"\"},\n\t\t{\"(AddrPort).MarshalText\", Method, 18, \"\"},\n\t\t{\"(AddrPort).Port\", Method, 18, \"\"},\n\t\t{\"(AddrPort).String\", Method, 18, \"\"},\n\t\t{\"(Prefix).Addr\", Method, 18, \"\"},\n\t\t{\"(Prefix).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(Prefix).AppendText\", Method, 24, \"\"},\n\t\t{\"(Prefix).AppendTo\", Method, 18, \"\"},\n\t\t{\"(Prefix).Bits\", Method, 18, \"\"},\n\t\t{\"(Prefix).Compare\", Method, 26, \"\"},\n\t\t{\"(Prefix).Contains\", Method, 18, \"\"},\n\t\t{\"(Prefix).IsSingleIP\", Method, 18, \"\"},\n\t\t{\"(Prefix).IsValid\", Method, 18, \"\"},\n\t\t{\"(Prefix).MarshalBinary\", Method, 18, \"\"},\n\t\t{\"(Prefix).MarshalText\", Method, 18, \"\"},\n\t\t{\"(Prefix).Masked\", Method, 18, \"\"},\n\t\t{\"(Prefix).Overlaps\", Method, 18, \"\"},\n\t\t{\"(Prefix).String\", Method, 18, \"\"},\n\t\t{\"Addr\", Type, 18, \"\"},\n\t\t{\"AddrFrom16\", Func, 18, \"func(addr [16]byte) Addr\"},\n\t\t{\"AddrFrom4\", Func, 18, \"func(addr [4]byte) Addr\"},\n\t\t{\"AddrFromSlice\", Func, 18, \"func(slice []byte) (ip Addr, ok bool)\"},\n\t\t{\"AddrPort\", Type, 18, \"\"},\n\t\t{\"AddrPortFrom\", Func, 18, \"func(ip Addr, port uint16) AddrPort\"},\n\t\t{\"IPv4Unspecified\", Func, 18, \"func() Addr\"},\n\t\t{\"IPv6LinkLocalAllNodes\", Func, 18, \"func() Addr\"},\n\t\t{\"IPv6LinkLocalAllRouters\", Func, 20, \"func() Addr\"},\n\t\t{\"IPv6Loopback\", Func, 20, \"func() Addr\"},\n\t\t{\"IPv6Unspecified\", Func, 18, \"func() Addr\"},\n\t\t{\"MustParseAddr\", Func, 18, \"func(s string) Addr\"},\n\t\t{\"MustParseAddrPort\", Func, 18, \"func(s string) AddrPort\"},\n\t\t{\"MustParsePrefix\", Func, 18, \"func(s string) Prefix\"},\n\t\t{\"ParseAddr\", Func, 18, \"func(s string) (Addr, error)\"},\n\t\t{\"ParseAddrPort\", Func, 18, \"func(s string) (AddrPort, error)\"},\n\t\t{\"ParsePrefix\", Func, 18, \"func(s string) (Prefix, error)\"},\n\t\t{\"Prefix\", Type, 18, \"\"},\n\t\t{\"PrefixFrom\", Func, 18, \"func(ip Addr, bits int) Prefix\"},\n\t},\n\t\"net/rpc\": {\n\t\t{\"(*Client).Call\", Method, 0, \"\"},\n\t\t{\"(*Client).Close\", Method, 0, \"\"},\n\t\t{\"(*Client).Go\", Method, 0, \"\"},\n\t\t{\"(*Server).Accept\", Method, 0, \"\"},\n\t\t{\"(*Server).HandleHTTP\", Method, 0, \"\"},\n\t\t{\"(*Server).Register\", Method, 0, \"\"},\n\t\t{\"(*Server).RegisterName\", Method, 0, \"\"},\n\t\t{\"(*Server).ServeCodec\", Method, 0, \"\"},\n\t\t{\"(*Server).ServeConn\", Method, 0, \"\"},\n\t\t{\"(*Server).ServeHTTP\", Method, 0, \"\"},\n\t\t{\"(*Server).ServeRequest\", Method, 0, \"\"},\n\t\t{\"(ClientCodec).Close\", Method, 0, \"\"},\n\t\t{\"(ClientCodec).ReadResponseBody\", Method, 0, \"\"},\n\t\t{\"(ClientCodec).ReadResponseHeader\", Method, 0, \"\"},\n\t\t{\"(ClientCodec).WriteRequest\", Method, 0, \"\"},\n\t\t{\"(ServerCodec).Close\", Method, 0, \"\"},\n\t\t{\"(ServerCodec).ReadRequestBody\", Method, 0, \"\"},\n\t\t{\"(ServerCodec).ReadRequestHeader\", Method, 0, \"\"},\n\t\t{\"(ServerCodec).WriteResponse\", Method, 0, \"\"},\n\t\t{\"(ServerError).Error\", Method, 0, \"\"},\n\t\t{\"Accept\", Func, 0, \"func(lis net.Listener)\"},\n\t\t{\"Call\", Type, 0, \"\"},\n\t\t{\"Call.Args\", Field, 0, \"\"},\n\t\t{\"Call.Done\", Field, 0, \"\"},\n\t\t{\"Call.Error\", Field, 0, \"\"},\n\t\t{\"Call.Reply\", Field, 0, \"\"},\n\t\t{\"Call.ServiceMethod\", Field, 0, \"\"},\n\t\t{\"Client\", Type, 0, \"\"},\n\t\t{\"ClientCodec\", Type, 0, \"\"},\n\t\t{\"DefaultDebugPath\", Const, 0, \"\"},\n\t\t{\"DefaultRPCPath\", Const, 0, \"\"},\n\t\t{\"DefaultServer\", Var, 0, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(network string, address string) (*Client, error)\"},\n\t\t{\"DialHTTP\", Func, 0, \"func(network string, address string) (*Client, error)\"},\n\t\t{\"DialHTTPPath\", Func, 0, \"func(network string, address string, path string) (*Client, error)\"},\n\t\t{\"ErrShutdown\", Var, 0, \"\"},\n\t\t{\"HandleHTTP\", Func, 0, \"func()\"},\n\t\t{\"NewClient\", Func, 0, \"func(conn io.ReadWriteCloser) *Client\"},\n\t\t{\"NewClientWithCodec\", Func, 0, \"func(codec ClientCodec) *Client\"},\n\t\t{\"NewServer\", Func, 0, \"func() *Server\"},\n\t\t{\"Register\", Func, 0, \"func(rcvr any) error\"},\n\t\t{\"RegisterName\", Func, 0, \"func(name string, rcvr any) error\"},\n\t\t{\"Request\", Type, 0, \"\"},\n\t\t{\"Request.Seq\", Field, 0, \"\"},\n\t\t{\"Request.ServiceMethod\", Field, 0, \"\"},\n\t\t{\"Response\", Type, 0, \"\"},\n\t\t{\"Response.Error\", Field, 0, \"\"},\n\t\t{\"Response.Seq\", Field, 0, \"\"},\n\t\t{\"Response.ServiceMethod\", Field, 0, \"\"},\n\t\t{\"ServeCodec\", Func, 0, \"func(codec ServerCodec)\"},\n\t\t{\"ServeConn\", Func, 0, \"func(conn io.ReadWriteCloser)\"},\n\t\t{\"ServeRequest\", Func, 0, \"func(codec ServerCodec) error\"},\n\t\t{\"Server\", Type, 0, \"\"},\n\t\t{\"ServerCodec\", Type, 0, \"\"},\n\t\t{\"ServerError\", Type, 0, \"\"},\n\t},\n\t\"net/rpc/jsonrpc\": {\n\t\t{\"Dial\", Func, 0, \"func(network string, address string) (*rpc.Client, error)\"},\n\t\t{\"NewClient\", Func, 0, \"func(conn io.ReadWriteCloser) *rpc.Client\"},\n\t\t{\"NewClientCodec\", Func, 0, \"func(conn io.ReadWriteCloser) rpc.ClientCodec\"},\n\t\t{\"NewServerCodec\", Func, 0, \"func(conn io.ReadWriteCloser) rpc.ServerCodec\"},\n\t\t{\"ServeConn\", Func, 0, \"func(conn io.ReadWriteCloser)\"},\n\t},\n\t\"net/smtp\": {\n\t\t{\"(*Client).Auth\", Method, 0, \"\"},\n\t\t{\"(*Client).Close\", Method, 2, \"\"},\n\t\t{\"(*Client).Data\", Method, 0, \"\"},\n\t\t{\"(*Client).Extension\", Method, 0, \"\"},\n\t\t{\"(*Client).Hello\", Method, 1, \"\"},\n\t\t{\"(*Client).Mail\", Method, 0, \"\"},\n\t\t{\"(*Client).Noop\", Method, 10, \"\"},\n\t\t{\"(*Client).Quit\", Method, 0, \"\"},\n\t\t{\"(*Client).Rcpt\", Method, 0, \"\"},\n\t\t{\"(*Client).Reset\", Method, 0, \"\"},\n\t\t{\"(*Client).StartTLS\", Method, 0, \"\"},\n\t\t{\"(*Client).TLSConnectionState\", Method, 5, \"\"},\n\t\t{\"(*Client).Verify\", Method, 0, \"\"},\n\t\t{\"(Auth).Next\", Method, 0, \"\"},\n\t\t{\"(Auth).Start\", Method, 0, \"\"},\n\t\t{\"Auth\", Type, 0, \"\"},\n\t\t{\"CRAMMD5Auth\", Func, 0, \"func(username string, secret string) Auth\"},\n\t\t{\"Client\", Type, 0, \"\"},\n\t\t{\"Client.Text\", Field, 0, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(addr string) (*Client, error)\"},\n\t\t{\"NewClient\", Func, 0, \"func(conn net.Conn, host string) (*Client, error)\"},\n\t\t{\"PlainAuth\", Func, 0, \"func(identity string, username string, password string, host string) Auth\"},\n\t\t{\"SendMail\", Func, 0, \"func(addr string, a Auth, from string, to []string, msg []byte) error\"},\n\t\t{\"ServerInfo\", Type, 0, \"\"},\n\t\t{\"ServerInfo.Auth\", Field, 0, \"\"},\n\t\t{\"ServerInfo.Name\", Field, 0, \"\"},\n\t\t{\"ServerInfo.TLS\", Field, 0, \"\"},\n\t},\n\t\"net/textproto\": {\n\t\t{\"(*Conn).Close\", Method, 0, \"\"},\n\t\t{\"(*Conn).Cmd\", Method, 0, \"\"},\n\t\t{\"(*Conn).DotReader\", Method, 0, \"\"},\n\t\t{\"(*Conn).DotWriter\", Method, 0, \"\"},\n\t\t{\"(*Conn).EndRequest\", Method, 0, \"\"},\n\t\t{\"(*Conn).EndResponse\", Method, 0, \"\"},\n\t\t{\"(*Conn).Next\", Method, 0, \"\"},\n\t\t{\"(*Conn).PrintfLine\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadCodeLine\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadContinuedLine\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadContinuedLineBytes\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadDotBytes\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadDotLines\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadLine\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadLineBytes\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadMIMEHeader\", Method, 0, \"\"},\n\t\t{\"(*Conn).ReadResponse\", Method, 0, \"\"},\n\t\t{\"(*Conn).StartRequest\", Method, 0, \"\"},\n\t\t{\"(*Conn).StartResponse\", Method, 0, \"\"},\n\t\t{\"(*Error).Error\", Method, 0, \"\"},\n\t\t{\"(*Pipeline).EndRequest\", Method, 0, \"\"},\n\t\t{\"(*Pipeline).EndResponse\", Method, 0, \"\"},\n\t\t{\"(*Pipeline).Next\", Method, 0, \"\"},\n\t\t{\"(*Pipeline).StartRequest\", Method, 0, \"\"},\n\t\t{\"(*Pipeline).StartResponse\", Method, 0, \"\"},\n\t\t{\"(*Reader).DotReader\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadCodeLine\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadContinuedLine\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadContinuedLineBytes\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadDotBytes\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadDotLines\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadLine\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadLineBytes\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadMIMEHeader\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadResponse\", Method, 0, \"\"},\n\t\t{\"(*Writer).DotWriter\", Method, 0, \"\"},\n\t\t{\"(*Writer).PrintfLine\", Method, 0, \"\"},\n\t\t{\"(MIMEHeader).Add\", Method, 0, \"\"},\n\t\t{\"(MIMEHeader).Del\", Method, 0, \"\"},\n\t\t{\"(MIMEHeader).Get\", Method, 0, \"\"},\n\t\t{\"(MIMEHeader).Set\", Method, 0, \"\"},\n\t\t{\"(MIMEHeader).Values\", Method, 14, \"\"},\n\t\t{\"(ProtocolError).Error\", Method, 0, \"\"},\n\t\t{\"CanonicalMIMEHeaderKey\", Func, 0, \"func(s string) string\"},\n\t\t{\"Conn\", Type, 0, \"\"},\n\t\t{\"Conn.Pipeline\", Field, 0, \"\"},\n\t\t{\"Conn.Reader\", Field, 0, \"\"},\n\t\t{\"Conn.Writer\", Field, 0, \"\"},\n\t\t{\"Dial\", Func, 0, \"func(network string, addr string) (*Conn, error)\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Code\", Field, 0, \"\"},\n\t\t{\"Error.Msg\", Field, 0, \"\"},\n\t\t{\"MIMEHeader\", Type, 0, \"\"},\n\t\t{\"NewConn\", Func, 0, \"func(conn io.ReadWriteCloser) *Conn\"},\n\t\t{\"NewReader\", Func, 0, \"func(r *bufio.Reader) *Reader\"},\n\t\t{\"NewWriter\", Func, 0, \"func(w *bufio.Writer) *Writer\"},\n\t\t{\"Pipeline\", Type, 0, \"\"},\n\t\t{\"ProtocolError\", Type, 0, \"\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Reader.R\", Field, 0, \"\"},\n\t\t{\"TrimBytes\", Func, 1, \"func(b []byte) []byte\"},\n\t\t{\"TrimString\", Func, 1, \"func(s string) string\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t\t{\"Writer.W\", Field, 0, \"\"},\n\t},\n\t\"net/url\": {\n\t\t{\"(*Error).Error\", Method, 0, \"\"},\n\t\t{\"(*Error).Temporary\", Method, 6, \"\"},\n\t\t{\"(*Error).Timeout\", Method, 6, \"\"},\n\t\t{\"(*Error).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*URL).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(*URL).EscapedFragment\", Method, 15, \"\"},\n\t\t{\"(*URL).EscapedPath\", Method, 5, \"\"},\n\t\t{\"(*URL).Hostname\", Method, 8, \"\"},\n\t\t{\"(*URL).IsAbs\", Method, 0, \"\"},\n\t\t{\"(*URL).JoinPath\", Method, 19, \"\"},\n\t\t{\"(*URL).MarshalBinary\", Method, 8, \"\"},\n\t\t{\"(*URL).Parse\", Method, 0, \"\"},\n\t\t{\"(*URL).Port\", Method, 8, \"\"},\n\t\t{\"(*URL).Query\", Method, 0, \"\"},\n\t\t{\"(*URL).Redacted\", Method, 15, \"\"},\n\t\t{\"(*URL).RequestURI\", Method, 0, \"\"},\n\t\t{\"(*URL).ResolveReference\", Method, 0, \"\"},\n\t\t{\"(*URL).String\", Method, 0, \"\"},\n\t\t{\"(*URL).UnmarshalBinary\", Method, 8, \"\"},\n\t\t{\"(*Userinfo).Password\", Method, 0, \"\"},\n\t\t{\"(*Userinfo).String\", Method, 0, \"\"},\n\t\t{\"(*Userinfo).Username\", Method, 0, \"\"},\n\t\t{\"(EscapeError).Error\", Method, 0, \"\"},\n\t\t{\"(InvalidHostError).Error\", Method, 6, \"\"},\n\t\t{\"(Values).Add\", Method, 0, \"\"},\n\t\t{\"(Values).Del\", Method, 0, \"\"},\n\t\t{\"(Values).Encode\", Method, 0, \"\"},\n\t\t{\"(Values).Get\", Method, 0, \"\"},\n\t\t{\"(Values).Has\", Method, 17, \"\"},\n\t\t{\"(Values).Set\", Method, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Err\", Field, 0, \"\"},\n\t\t{\"Error.Op\", Field, 0, \"\"},\n\t\t{\"Error.URL\", Field, 0, \"\"},\n\t\t{\"EscapeError\", Type, 0, \"\"},\n\t\t{\"InvalidHostError\", Type, 6, \"\"},\n\t\t{\"JoinPath\", Func, 19, \"func(base string, elem ...string) (result string, err error)\"},\n\t\t{\"Parse\", Func, 0, \"func(rawURL string) (*URL, error)\"},\n\t\t{\"ParseQuery\", Func, 0, \"func(query string) (Values, error)\"},\n\t\t{\"ParseRequestURI\", Func, 0, \"func(rawURL string) (*URL, error)\"},\n\t\t{\"PathEscape\", Func, 8, \"func(s string) string\"},\n\t\t{\"PathUnescape\", Func, 8, \"func(s string) (string, error)\"},\n\t\t{\"QueryEscape\", Func, 0, \"func(s string) string\"},\n\t\t{\"QueryUnescape\", Func, 0, \"func(s string) (string, error)\"},\n\t\t{\"URL\", Type, 0, \"\"},\n\t\t{\"URL.ForceQuery\", Field, 7, \"\"},\n\t\t{\"URL.Fragment\", Field, 0, \"\"},\n\t\t{\"URL.Host\", Field, 0, \"\"},\n\t\t{\"URL.OmitHost\", Field, 19, \"\"},\n\t\t{\"URL.Opaque\", Field, 0, \"\"},\n\t\t{\"URL.Path\", Field, 0, \"\"},\n\t\t{\"URL.RawFragment\", Field, 15, \"\"},\n\t\t{\"URL.RawPath\", Field, 5, \"\"},\n\t\t{\"URL.RawQuery\", Field, 0, \"\"},\n\t\t{\"URL.Scheme\", Field, 0, \"\"},\n\t\t{\"URL.User\", Field, 0, \"\"},\n\t\t{\"User\", Func, 0, \"func(username string) *Userinfo\"},\n\t\t{\"UserPassword\", Func, 0, \"func(username string, password string) *Userinfo\"},\n\t\t{\"Userinfo\", Type, 0, \"\"},\n\t\t{\"Values\", Type, 0, \"\"},\n\t},\n\t\"os\": {\n\t\t{\"(*File).Chdir\", Method, 0, \"\"},\n\t\t{\"(*File).Chmod\", Method, 0, \"\"},\n\t\t{\"(*File).Chown\", Method, 0, \"\"},\n\t\t{\"(*File).Close\", Method, 0, \"\"},\n\t\t{\"(*File).Fd\", Method, 0, \"\"},\n\t\t{\"(*File).Name\", Method, 0, \"\"},\n\t\t{\"(*File).Read\", Method, 0, \"\"},\n\t\t{\"(*File).ReadAt\", Method, 0, \"\"},\n\t\t{\"(*File).ReadDir\", Method, 16, \"\"},\n\t\t{\"(*File).ReadFrom\", Method, 15, \"\"},\n\t\t{\"(*File).Readdir\", Method, 0, \"\"},\n\t\t{\"(*File).Readdirnames\", Method, 0, \"\"},\n\t\t{\"(*File).Seek\", Method, 0, \"\"},\n\t\t{\"(*File).SetDeadline\", Method, 10, \"\"},\n\t\t{\"(*File).SetReadDeadline\", Method, 10, \"\"},\n\t\t{\"(*File).SetWriteDeadline\", Method, 10, \"\"},\n\t\t{\"(*File).Stat\", Method, 0, \"\"},\n\t\t{\"(*File).Sync\", Method, 0, \"\"},\n\t\t{\"(*File).SyscallConn\", Method, 12, \"\"},\n\t\t{\"(*File).Truncate\", Method, 0, \"\"},\n\t\t{\"(*File).Write\", Method, 0, \"\"},\n\t\t{\"(*File).WriteAt\", Method, 0, \"\"},\n\t\t{\"(*File).WriteString\", Method, 0, \"\"},\n\t\t{\"(*File).WriteTo\", Method, 22, \"\"},\n\t\t{\"(*LinkError).Error\", Method, 0, \"\"},\n\t\t{\"(*LinkError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*PathError).Error\", Method, 0, \"\"},\n\t\t{\"(*PathError).Timeout\", Method, 10, \"\"},\n\t\t{\"(*PathError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*Process).Kill\", Method, 0, \"\"},\n\t\t{\"(*Process).Release\", Method, 0, \"\"},\n\t\t{\"(*Process).Signal\", Method, 0, \"\"},\n\t\t{\"(*Process).Wait\", Method, 0, \"\"},\n\t\t{\"(*Process).WithHandle\", Method, 26, \"\"},\n\t\t{\"(*ProcessState).ExitCode\", Method, 12, \"\"},\n\t\t{\"(*ProcessState).Exited\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).Pid\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).String\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).Success\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).Sys\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).SysUsage\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).SystemTime\", Method, 0, \"\"},\n\t\t{\"(*ProcessState).UserTime\", Method, 0, \"\"},\n\t\t{\"(*Root).Chmod\", Method, 25, \"\"},\n\t\t{\"(*Root).Chown\", Method, 25, \"\"},\n\t\t{\"(*Root).Chtimes\", Method, 25, \"\"},\n\t\t{\"(*Root).Close\", Method, 24, \"\"},\n\t\t{\"(*Root).Create\", Method, 24, \"\"},\n\t\t{\"(*Root).FS\", Method, 24, \"\"},\n\t\t{\"(*Root).Lchown\", Method, 25, \"\"},\n\t\t{\"(*Root).Link\", Method, 25, \"\"},\n\t\t{\"(*Root).Lstat\", Method, 24, \"\"},\n\t\t{\"(*Root).Mkdir\", Method, 24, \"\"},\n\t\t{\"(*Root).MkdirAll\", Method, 25, \"\"},\n\t\t{\"(*Root).Name\", Method, 24, \"\"},\n\t\t{\"(*Root).Open\", Method, 24, \"\"},\n\t\t{\"(*Root).OpenFile\", Method, 24, \"\"},\n\t\t{\"(*Root).OpenRoot\", Method, 24, \"\"},\n\t\t{\"(*Root).ReadFile\", Method, 25, \"\"},\n\t\t{\"(*Root).Readlink\", Method, 25, \"\"},\n\t\t{\"(*Root).Remove\", Method, 24, \"\"},\n\t\t{\"(*Root).RemoveAll\", Method, 25, \"\"},\n\t\t{\"(*Root).Rename\", Method, 25, \"\"},\n\t\t{\"(*Root).Stat\", Method, 24, \"\"},\n\t\t{\"(*Root).Symlink\", Method, 25, \"\"},\n\t\t{\"(*Root).WriteFile\", Method, 25, \"\"},\n\t\t{\"(*SyscallError).Error\", Method, 0, \"\"},\n\t\t{\"(*SyscallError).Timeout\", Method, 10, \"\"},\n\t\t{\"(*SyscallError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(FileInfo).IsDir\", Method, 0, \"\"},\n\t\t{\"(FileInfo).ModTime\", Method, 0, \"\"},\n\t\t{\"(FileInfo).Mode\", Method, 0, \"\"},\n\t\t{\"(FileInfo).Name\", Method, 0, \"\"},\n\t\t{\"(FileInfo).Size\", Method, 0, \"\"},\n\t\t{\"(FileInfo).Sys\", Method, 0, \"\"},\n\t\t{\"(FileMode).IsDir\", Method, 0, \"\"},\n\t\t{\"(FileMode).IsRegular\", Method, 1, \"\"},\n\t\t{\"(FileMode).Perm\", Method, 0, \"\"},\n\t\t{\"(FileMode).String\", Method, 0, \"\"},\n\t\t{\"(Signal).Signal\", Method, 0, \"\"},\n\t\t{\"(Signal).String\", Method, 0, \"\"},\n\t\t{\"Args\", Var, 0, \"\"},\n\t\t{\"Chdir\", Func, 0, \"func(dir string) error\"},\n\t\t{\"Chmod\", Func, 0, \"func(name string, mode FileMode) error\"},\n\t\t{\"Chown\", Func, 0, \"func(name string, uid int, gid int) error\"},\n\t\t{\"Chtimes\", Func, 0, \"func(name string, atime time.Time, mtime time.Time) error\"},\n\t\t{\"Clearenv\", Func, 0, \"func()\"},\n\t\t{\"CopyFS\", Func, 23, \"func(dir string, fsys fs.FS) error\"},\n\t\t{\"Create\", Func, 0, \"func(name string) (*File, error)\"},\n\t\t{\"CreateTemp\", Func, 16, \"func(dir string, pattern string) (*File, error)\"},\n\t\t{\"DevNull\", Const, 0, \"\"},\n\t\t{\"DirEntry\", Type, 16, \"\"},\n\t\t{\"DirFS\", Func, 16, \"func(dir string) fs.FS\"},\n\t\t{\"Environ\", Func, 0, \"func() []string\"},\n\t\t{\"ErrClosed\", Var, 8, \"\"},\n\t\t{\"ErrDeadlineExceeded\", Var, 15, \"\"},\n\t\t{\"ErrExist\", Var, 0, \"\"},\n\t\t{\"ErrInvalid\", Var, 0, \"\"},\n\t\t{\"ErrNoDeadline\", Var, 10, \"\"},\n\t\t{\"ErrNoHandle\", Var, 26, \"\"},\n\t\t{\"ErrNotExist\", Var, 0, \"\"},\n\t\t{\"ErrPermission\", Var, 0, \"\"},\n\t\t{\"ErrProcessDone\", Var, 16, \"\"},\n\t\t{\"Executable\", Func, 8, \"func() (string, error)\"},\n\t\t{\"Exit\", Func, 0, \"func(code int)\"},\n\t\t{\"Expand\", Func, 0, \"func(s string, mapping func(string) string) string\"},\n\t\t{\"ExpandEnv\", Func, 0, \"func(s string) string\"},\n\t\t{\"File\", Type, 0, \"\"},\n\t\t{\"FileInfo\", Type, 0, \"\"},\n\t\t{\"FileMode\", Type, 0, \"\"},\n\t\t{\"FindProcess\", Func, 0, \"func(pid int) (*Process, error)\"},\n\t\t{\"Getegid\", Func, 0, \"func() int\"},\n\t\t{\"Getenv\", Func, 0, \"func(key string) string\"},\n\t\t{\"Geteuid\", Func, 0, \"func() int\"},\n\t\t{\"Getgid\", Func, 0, \"func() int\"},\n\t\t{\"Getgroups\", Func, 0, \"func() ([]int, error)\"},\n\t\t{\"Getpagesize\", Func, 0, \"func() int\"},\n\t\t{\"Getpid\", Func, 0, \"func() int\"},\n\t\t{\"Getppid\", Func, 0, \"func() int\"},\n\t\t{\"Getuid\", Func, 0, \"func() int\"},\n\t\t{\"Getwd\", Func, 0, \"func() (dir string, err error)\"},\n\t\t{\"Hostname\", Func, 0, \"func() (name string, err error)\"},\n\t\t{\"Interrupt\", Var, 0, \"\"},\n\t\t{\"IsExist\", Func, 0, \"func(err error) bool\"},\n\t\t{\"IsNotExist\", Func, 0, \"func(err error) bool\"},\n\t\t{\"IsPathSeparator\", Func, 0, \"func(c uint8) bool\"},\n\t\t{\"IsPermission\", Func, 0, \"func(err error) bool\"},\n\t\t{\"IsTimeout\", Func, 10, \"func(err error) bool\"},\n\t\t{\"Kill\", Var, 0, \"\"},\n\t\t{\"Lchown\", Func, 0, \"func(name string, uid int, gid int) error\"},\n\t\t{\"Link\", Func, 0, \"func(oldname string, newname string) error\"},\n\t\t{\"LinkError\", Type, 0, \"\"},\n\t\t{\"LinkError.Err\", Field, 0, \"\"},\n\t\t{\"LinkError.New\", Field, 0, \"\"},\n\t\t{\"LinkError.Old\", Field, 0, \"\"},\n\t\t{\"LinkError.Op\", Field, 0, \"\"},\n\t\t{\"LookupEnv\", Func, 5, \"func(key string) (string, bool)\"},\n\t\t{\"Lstat\", Func, 0, \"func(name string) (FileInfo, error)\"},\n\t\t{\"Mkdir\", Func, 0, \"func(name string, perm FileMode) error\"},\n\t\t{\"MkdirAll\", Func, 0, \"func(path string, perm FileMode) error\"},\n\t\t{\"MkdirTemp\", Func, 16, \"func(dir string, pattern string) (string, error)\"},\n\t\t{\"ModeAppend\", Const, 0, \"\"},\n\t\t{\"ModeCharDevice\", Const, 0, \"\"},\n\t\t{\"ModeDevice\", Const, 0, \"\"},\n\t\t{\"ModeDir\", Const, 0, \"\"},\n\t\t{\"ModeExclusive\", Const, 0, \"\"},\n\t\t{\"ModeIrregular\", Const, 11, \"\"},\n\t\t{\"ModeNamedPipe\", Const, 0, \"\"},\n\t\t{\"ModePerm\", Const, 0, \"\"},\n\t\t{\"ModeSetgid\", Const, 0, \"\"},\n\t\t{\"ModeSetuid\", Const, 0, \"\"},\n\t\t{\"ModeSocket\", Const, 0, \"\"},\n\t\t{\"ModeSticky\", Const, 0, \"\"},\n\t\t{\"ModeSymlink\", Const, 0, \"\"},\n\t\t{\"ModeTemporary\", Const, 0, \"\"},\n\t\t{\"ModeType\", Const, 0, \"\"},\n\t\t{\"NewFile\", Func, 0, \"func(fd uintptr, name string) *File\"},\n\t\t{\"NewSyscallError\", Func, 0, \"func(syscall string, err error) error\"},\n\t\t{\"O_APPEND\", Const, 0, \"\"},\n\t\t{\"O_CREATE\", Const, 0, \"\"},\n\t\t{\"O_EXCL\", Const, 0, \"\"},\n\t\t{\"O_RDONLY\", Const, 0, \"\"},\n\t\t{\"O_RDWR\", Const, 0, \"\"},\n\t\t{\"O_SYNC\", Const, 0, \"\"},\n\t\t{\"O_TRUNC\", Const, 0, \"\"},\n\t\t{\"O_WRONLY\", Const, 0, \"\"},\n\t\t{\"Open\", Func, 0, \"func(name string) (*File, error)\"},\n\t\t{\"OpenFile\", Func, 0, \"func(name string, flag int, perm FileMode) (*File, error)\"},\n\t\t{\"OpenInRoot\", Func, 24, \"func(dir string, name string) (*File, error)\"},\n\t\t{\"OpenRoot\", Func, 24, \"func(name string) (*Root, error)\"},\n\t\t{\"PathError\", Type, 0, \"\"},\n\t\t{\"PathError.Err\", Field, 0, \"\"},\n\t\t{\"PathError.Op\", Field, 0, \"\"},\n\t\t{\"PathError.Path\", Field, 0, \"\"},\n\t\t{\"PathListSeparator\", Const, 0, \"\"},\n\t\t{\"PathSeparator\", Const, 0, \"\"},\n\t\t{\"Pipe\", Func, 0, \"func() (r *File, w *File, err error)\"},\n\t\t{\"ProcAttr\", Type, 0, \"\"},\n\t\t{\"ProcAttr.Dir\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Env\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Files\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Sys\", Field, 0, \"\"},\n\t\t{\"Process\", Type, 0, \"\"},\n\t\t{\"Process.Pid\", Field, 0, \"\"},\n\t\t{\"ProcessState\", Type, 0, \"\"},\n\t\t{\"ReadDir\", Func, 16, \"func(name string) ([]DirEntry, error)\"},\n\t\t{\"ReadFile\", Func, 16, \"func(name string) ([]byte, error)\"},\n\t\t{\"Readlink\", Func, 0, \"func(name string) (string, error)\"},\n\t\t{\"Remove\", Func, 0, \"func(name string) error\"},\n\t\t{\"RemoveAll\", Func, 0, \"func(path string) error\"},\n\t\t{\"Rename\", Func, 0, \"func(oldpath string, newpath string) error\"},\n\t\t{\"Root\", Type, 24, \"\"},\n\t\t{\"SEEK_CUR\", Const, 0, \"\"},\n\t\t{\"SEEK_END\", Const, 0, \"\"},\n\t\t{\"SEEK_SET\", Const, 0, \"\"},\n\t\t{\"SameFile\", Func, 0, \"func(fi1 FileInfo, fi2 FileInfo) bool\"},\n\t\t{\"Setenv\", Func, 0, \"func(key string, value string) error\"},\n\t\t{\"Signal\", Type, 0, \"\"},\n\t\t{\"StartProcess\", Func, 0, \"func(name string, argv []string, attr *ProcAttr) (*Process, error)\"},\n\t\t{\"Stat\", Func, 0, \"func(name string) (FileInfo, error)\"},\n\t\t{\"Stderr\", Var, 0, \"\"},\n\t\t{\"Stdin\", Var, 0, \"\"},\n\t\t{\"Stdout\", Var, 0, \"\"},\n\t\t{\"Symlink\", Func, 0, \"func(oldname string, newname string) error\"},\n\t\t{\"SyscallError\", Type, 0, \"\"},\n\t\t{\"SyscallError.Err\", Field, 0, \"\"},\n\t\t{\"SyscallError.Syscall\", Field, 0, \"\"},\n\t\t{\"TempDir\", Func, 0, \"func() string\"},\n\t\t{\"Truncate\", Func, 0, \"func(name string, size int64) error\"},\n\t\t{\"Unsetenv\", Func, 4, \"func(key string) error\"},\n\t\t{\"UserCacheDir\", Func, 11, \"func() (string, error)\"},\n\t\t{\"UserConfigDir\", Func, 13, \"func() (string, error)\"},\n\t\t{\"UserHomeDir\", Func, 12, \"func() (string, error)\"},\n\t\t{\"WriteFile\", Func, 16, \"func(name string, data []byte, perm FileMode) error\"},\n\t},\n\t\"os/exec\": {\n\t\t{\"(*Cmd).CombinedOutput\", Method, 0, \"\"},\n\t\t{\"(*Cmd).Environ\", Method, 19, \"\"},\n\t\t{\"(*Cmd).Output\", Method, 0, \"\"},\n\t\t{\"(*Cmd).Run\", Method, 0, \"\"},\n\t\t{\"(*Cmd).Start\", Method, 0, \"\"},\n\t\t{\"(*Cmd).StderrPipe\", Method, 0, \"\"},\n\t\t{\"(*Cmd).StdinPipe\", Method, 0, \"\"},\n\t\t{\"(*Cmd).StdoutPipe\", Method, 0, \"\"},\n\t\t{\"(*Cmd).String\", Method, 13, \"\"},\n\t\t{\"(*Cmd).Wait\", Method, 0, \"\"},\n\t\t{\"(*Error).Error\", Method, 0, \"\"},\n\t\t{\"(*Error).Unwrap\", Method, 13, \"\"},\n\t\t{\"(*ExitError).Error\", Method, 0, \"\"},\n\t\t{\"(ExitError).ExitCode\", Method, 12, \"\"},\n\t\t{\"(ExitError).Exited\", Method, 0, \"\"},\n\t\t{\"(ExitError).Pid\", Method, 0, \"\"},\n\t\t{\"(ExitError).String\", Method, 0, \"\"},\n\t\t{\"(ExitError).Success\", Method, 0, \"\"},\n\t\t{\"(ExitError).Sys\", Method, 0, \"\"},\n\t\t{\"(ExitError).SysUsage\", Method, 0, \"\"},\n\t\t{\"(ExitError).SystemTime\", Method, 0, \"\"},\n\t\t{\"(ExitError).UserTime\", Method, 0, \"\"},\n\t\t{\"Cmd\", Type, 0, \"\"},\n\t\t{\"Cmd.Args\", Field, 0, \"\"},\n\t\t{\"Cmd.Cancel\", Field, 20, \"\"},\n\t\t{\"Cmd.Dir\", Field, 0, \"\"},\n\t\t{\"Cmd.Env\", Field, 0, \"\"},\n\t\t{\"Cmd.Err\", Field, 19, \"\"},\n\t\t{\"Cmd.ExtraFiles\", Field, 0, \"\"},\n\t\t{\"Cmd.Path\", Field, 0, \"\"},\n\t\t{\"Cmd.Process\", Field, 0, \"\"},\n\t\t{\"Cmd.ProcessState\", Field, 0, \"\"},\n\t\t{\"Cmd.Stderr\", Field, 0, \"\"},\n\t\t{\"Cmd.Stdin\", Field, 0, \"\"},\n\t\t{\"Cmd.Stdout\", Field, 0, \"\"},\n\t\t{\"Cmd.SysProcAttr\", Field, 0, \"\"},\n\t\t{\"Cmd.WaitDelay\", Field, 20, \"\"},\n\t\t{\"Command\", Func, 0, \"func(name string, arg ...string) *Cmd\"},\n\t\t{\"CommandContext\", Func, 7, \"func(ctx context.Context, name string, arg ...string) *Cmd\"},\n\t\t{\"ErrDot\", Var, 19, \"\"},\n\t\t{\"ErrNotFound\", Var, 0, \"\"},\n\t\t{\"ErrWaitDelay\", Var, 20, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Err\", Field, 0, \"\"},\n\t\t{\"Error.Name\", Field, 0, \"\"},\n\t\t{\"ExitError\", Type, 0, \"\"},\n\t\t{\"ExitError.ProcessState\", Field, 0, \"\"},\n\t\t{\"ExitError.Stderr\", Field, 6, \"\"},\n\t\t{\"LookPath\", Func, 0, \"func(file string) (string, error)\"},\n\t},\n\t\"os/signal\": {\n\t\t{\"Ignore\", Func, 5, \"func(sig ...os.Signal)\"},\n\t\t{\"Ignored\", Func, 11, \"func(sig os.Signal) bool\"},\n\t\t{\"Notify\", Func, 0, \"func(c chan<- os.Signal, sig ...os.Signal)\"},\n\t\t{\"NotifyContext\", Func, 16, \"func(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)\"},\n\t\t{\"Reset\", Func, 5, \"func(sig ...os.Signal)\"},\n\t\t{\"Stop\", Func, 1, \"func(c chan<- os.Signal)\"},\n\t},\n\t\"os/user\": {\n\t\t{\"(*User).GroupIds\", Method, 7, \"\"},\n\t\t{\"(UnknownGroupError).Error\", Method, 7, \"\"},\n\t\t{\"(UnknownGroupIdError).Error\", Method, 7, \"\"},\n\t\t{\"(UnknownUserError).Error\", Method, 0, \"\"},\n\t\t{\"(UnknownUserIdError).Error\", Method, 0, \"\"},\n\t\t{\"Current\", Func, 0, \"func() (*User, error)\"},\n\t\t{\"Group\", Type, 7, \"\"},\n\t\t{\"Group.Gid\", Field, 7, \"\"},\n\t\t{\"Group.Name\", Field, 7, \"\"},\n\t\t{\"Lookup\", Func, 0, \"func(username string) (*User, error)\"},\n\t\t{\"LookupGroup\", Func, 7, \"func(name string) (*Group, error)\"},\n\t\t{\"LookupGroupId\", Func, 7, \"func(gid string) (*Group, error)\"},\n\t\t{\"LookupId\", Func, 0, \"func(uid string) (*User, error)\"},\n\t\t{\"UnknownGroupError\", Type, 7, \"\"},\n\t\t{\"UnknownGroupIdError\", Type, 7, \"\"},\n\t\t{\"UnknownUserError\", Type, 0, \"\"},\n\t\t{\"UnknownUserIdError\", Type, 0, \"\"},\n\t\t{\"User\", Type, 0, \"\"},\n\t\t{\"User.Gid\", Field, 0, \"\"},\n\t\t{\"User.HomeDir\", Field, 0, \"\"},\n\t\t{\"User.Name\", Field, 0, \"\"},\n\t\t{\"User.Uid\", Field, 0, \"\"},\n\t\t{\"User.Username\", Field, 0, \"\"},\n\t},\n\t\"path\": {\n\t\t{\"Base\", Func, 0, \"func(path string) string\"},\n\t\t{\"Clean\", Func, 0, \"func(path string) string\"},\n\t\t{\"Dir\", Func, 0, \"func(path string) string\"},\n\t\t{\"ErrBadPattern\", Var, 0, \"\"},\n\t\t{\"Ext\", Func, 0, \"func(path string) string\"},\n\t\t{\"IsAbs\", Func, 0, \"func(path string) bool\"},\n\t\t{\"Join\", Func, 0, \"func(elem ...string) string\"},\n\t\t{\"Match\", Func, 0, \"func(pattern string, name string) (matched bool, err error)\"},\n\t\t{\"Split\", Func, 0, \"func(path string) (dir string, file string)\"},\n\t},\n\t\"path/filepath\": {\n\t\t{\"Abs\", Func, 0, \"func(path string) (string, error)\"},\n\t\t{\"Base\", Func, 0, \"func(path string) string\"},\n\t\t{\"Clean\", Func, 0, \"func(path string) string\"},\n\t\t{\"Dir\", Func, 0, \"func(path string) string\"},\n\t\t{\"ErrBadPattern\", Var, 0, \"\"},\n\t\t{\"EvalSymlinks\", Func, 0, \"func(path string) (string, error)\"},\n\t\t{\"Ext\", Func, 0, \"func(path string) string\"},\n\t\t{\"FromSlash\", Func, 0, \"func(path string) string\"},\n\t\t{\"Glob\", Func, 0, \"func(pattern string) (matches []string, err error)\"},\n\t\t{\"HasPrefix\", Func, 0, \"func(p string, prefix string) bool\"},\n\t\t{\"IsAbs\", Func, 0, \"func(path string) bool\"},\n\t\t{\"IsLocal\", Func, 20, \"func(path string) bool\"},\n\t\t{\"Join\", Func, 0, \"func(elem ...string) string\"},\n\t\t{\"ListSeparator\", Const, 0, \"\"},\n\t\t{\"Localize\", Func, 23, \"func(path string) (string, error)\"},\n\t\t{\"Match\", Func, 0, \"func(pattern string, name string) (matched bool, err error)\"},\n\t\t{\"Rel\", Func, 0, \"func(basePath string, targPath string) (string, error)\"},\n\t\t{\"Separator\", Const, 0, \"\"},\n\t\t{\"SkipAll\", Var, 20, \"\"},\n\t\t{\"SkipDir\", Var, 0, \"\"},\n\t\t{\"Split\", Func, 0, \"func(path string) (dir string, file string)\"},\n\t\t{\"SplitList\", Func, 0, \"func(path string) []string\"},\n\t\t{\"ToSlash\", Func, 0, \"func(path string) string\"},\n\t\t{\"VolumeName\", Func, 0, \"func(path string) string\"},\n\t\t{\"Walk\", Func, 0, \"func(root string, fn WalkFunc) error\"},\n\t\t{\"WalkDir\", Func, 16, \"func(root string, fn fs.WalkDirFunc) error\"},\n\t\t{\"WalkFunc\", Type, 0, \"\"},\n\t},\n\t\"plugin\": {\n\t\t{\"(*Plugin).Lookup\", Method, 8, \"\"},\n\t\t{\"Open\", Func, 8, \"func(path string) (*Plugin, error)\"},\n\t\t{\"Plugin\", Type, 8, \"\"},\n\t\t{\"Symbol\", Type, 8, \"\"},\n\t},\n\t\"reflect\": {\n\t\t{\"(*MapIter).Key\", Method, 12, \"\"},\n\t\t{\"(*MapIter).Next\", Method, 12, \"\"},\n\t\t{\"(*MapIter).Reset\", Method, 18, \"\"},\n\t\t{\"(*MapIter).Value\", Method, 12, \"\"},\n\t\t{\"(*ValueError).Error\", Method, 0, \"\"},\n\t\t{\"(ChanDir).String\", Method, 0, \"\"},\n\t\t{\"(Kind).String\", Method, 0, \"\"},\n\t\t{\"(Method).IsExported\", Method, 17, \"\"},\n\t\t{\"(StructField).IsExported\", Method, 17, \"\"},\n\t\t{\"(StructTag).Get\", Method, 0, \"\"},\n\t\t{\"(StructTag).Lookup\", Method, 7, \"\"},\n\t\t{\"(Type).Align\", Method, 0, \"\"},\n\t\t{\"(Type).AssignableTo\", Method, 0, \"\"},\n\t\t{\"(Type).Bits\", Method, 0, \"\"},\n\t\t{\"(Type).CanSeq\", Method, 23, \"\"},\n\t\t{\"(Type).CanSeq2\", Method, 23, \"\"},\n\t\t{\"(Type).ChanDir\", Method, 0, \"\"},\n\t\t{\"(Type).Comparable\", Method, 4, \"\"},\n\t\t{\"(Type).ConvertibleTo\", Method, 1, \"\"},\n\t\t{\"(Type).Elem\", Method, 0, \"\"},\n\t\t{\"(Type).Field\", Method, 0, \"\"},\n\t\t{\"(Type).FieldAlign\", Method, 0, \"\"},\n\t\t{\"(Type).FieldByIndex\", Method, 0, \"\"},\n\t\t{\"(Type).FieldByName\", Method, 0, \"\"},\n\t\t{\"(Type).FieldByNameFunc\", Method, 0, \"\"},\n\t\t{\"(Type).Fields\", Method, 26, \"\"},\n\t\t{\"(Type).Implements\", Method, 0, \"\"},\n\t\t{\"(Type).In\", Method, 0, \"\"},\n\t\t{\"(Type).Ins\", Method, 26, \"\"},\n\t\t{\"(Type).IsVariadic\", Method, 0, \"\"},\n\t\t{\"(Type).Key\", Method, 0, \"\"},\n\t\t{\"(Type).Kind\", Method, 0, \"\"},\n\t\t{\"(Type).Len\", Method, 0, \"\"},\n\t\t{\"(Type).Method\", Method, 0, \"\"},\n\t\t{\"(Type).MethodByName\", Method, 0, \"\"},\n\t\t{\"(Type).Methods\", Method, 26, \"\"},\n\t\t{\"(Type).Name\", Method, 0, \"\"},\n\t\t{\"(Type).NumField\", Method, 0, \"\"},\n\t\t{\"(Type).NumIn\", Method, 0, \"\"},\n\t\t{\"(Type).NumMethod\", Method, 0, \"\"},\n\t\t{\"(Type).NumOut\", Method, 0, \"\"},\n\t\t{\"(Type).Out\", Method, 0, \"\"},\n\t\t{\"(Type).Outs\", Method, 26, \"\"},\n\t\t{\"(Type).OverflowComplex\", Method, 23, \"\"},\n\t\t{\"(Type).OverflowFloat\", Method, 23, \"\"},\n\t\t{\"(Type).OverflowInt\", Method, 23, \"\"},\n\t\t{\"(Type).OverflowUint\", Method, 23, \"\"},\n\t\t{\"(Type).PkgPath\", Method, 0, \"\"},\n\t\t{\"(Type).Size\", Method, 0, \"\"},\n\t\t{\"(Type).String\", Method, 0, \"\"},\n\t\t{\"(Value).Addr\", Method, 0, \"\"},\n\t\t{\"(Value).Bool\", Method, 0, \"\"},\n\t\t{\"(Value).Bytes\", Method, 0, \"\"},\n\t\t{\"(Value).Call\", Method, 0, \"\"},\n\t\t{\"(Value).CallSlice\", Method, 0, \"\"},\n\t\t{\"(Value).CanAddr\", Method, 0, \"\"},\n\t\t{\"(Value).CanComplex\", Method, 18, \"\"},\n\t\t{\"(Value).CanConvert\", Method, 17, \"\"},\n\t\t{\"(Value).CanFloat\", Method, 18, \"\"},\n\t\t{\"(Value).CanInt\", Method, 18, \"\"},\n\t\t{\"(Value).CanInterface\", Method, 0, \"\"},\n\t\t{\"(Value).CanSet\", Method, 0, \"\"},\n\t\t{\"(Value).CanUint\", Method, 18, \"\"},\n\t\t{\"(Value).Cap\", Method, 0, \"\"},\n\t\t{\"(Value).Clear\", Method, 21, \"\"},\n\t\t{\"(Value).Close\", Method, 0, \"\"},\n\t\t{\"(Value).Comparable\", Method, 20, \"\"},\n\t\t{\"(Value).Complex\", Method, 0, \"\"},\n\t\t{\"(Value).Convert\", Method, 1, \"\"},\n\t\t{\"(Value).Elem\", Method, 0, \"\"},\n\t\t{\"(Value).Equal\", Method, 20, \"\"},\n\t\t{\"(Value).Field\", Method, 0, \"\"},\n\t\t{\"(Value).FieldByIndex\", Method, 0, \"\"},\n\t\t{\"(Value).FieldByIndexErr\", Method, 18, \"\"},\n\t\t{\"(Value).FieldByName\", Method, 0, \"\"},\n\t\t{\"(Value).FieldByNameFunc\", Method, 0, \"\"},\n\t\t{\"(Value).Fields\", Method, 26, \"\"},\n\t\t{\"(Value).Float\", Method, 0, \"\"},\n\t\t{\"(Value).Grow\", Method, 20, \"\"},\n\t\t{\"(Value).Index\", Method, 0, \"\"},\n\t\t{\"(Value).Int\", Method, 0, \"\"},\n\t\t{\"(Value).Interface\", Method, 0, \"\"},\n\t\t{\"(Value).InterfaceData\", Method, 0, \"\"},\n\t\t{\"(Value).IsNil\", Method, 0, \"\"},\n\t\t{\"(Value).IsValid\", Method, 0, \"\"},\n\t\t{\"(Value).IsZero\", Method, 13, \"\"},\n\t\t{\"(Value).Kind\", Method, 0, \"\"},\n\t\t{\"(Value).Len\", Method, 0, \"\"},\n\t\t{\"(Value).MapIndex\", Method, 0, \"\"},\n\t\t{\"(Value).MapKeys\", Method, 0, \"\"},\n\t\t{\"(Value).MapRange\", Method, 12, \"\"},\n\t\t{\"(Value).Method\", Method, 0, \"\"},\n\t\t{\"(Value).MethodByName\", Method, 0, \"\"},\n\t\t{\"(Value).Methods\", Method, 26, \"\"},\n\t\t{\"(Value).NumField\", Method, 0, \"\"},\n\t\t{\"(Value).NumMethod\", Method, 0, \"\"},\n\t\t{\"(Value).OverflowComplex\", Method, 0, \"\"},\n\t\t{\"(Value).OverflowFloat\", Method, 0, \"\"},\n\t\t{\"(Value).OverflowInt\", Method, 0, \"\"},\n\t\t{\"(Value).OverflowUint\", Method, 0, \"\"},\n\t\t{\"(Value).Pointer\", Method, 0, \"\"},\n\t\t{\"(Value).Recv\", Method, 0, \"\"},\n\t\t{\"(Value).Send\", Method, 0, \"\"},\n\t\t{\"(Value).Seq\", Method, 23, \"\"},\n\t\t{\"(Value).Seq2\", Method, 23, \"\"},\n\t\t{\"(Value).Set\", Method, 0, \"\"},\n\t\t{\"(Value).SetBool\", Method, 0, \"\"},\n\t\t{\"(Value).SetBytes\", Method, 0, \"\"},\n\t\t{\"(Value).SetCap\", Method, 2, \"\"},\n\t\t{\"(Value).SetComplex\", Method, 0, \"\"},\n\t\t{\"(Value).SetFloat\", Method, 0, \"\"},\n\t\t{\"(Value).SetInt\", Method, 0, \"\"},\n\t\t{\"(Value).SetIterKey\", Method, 18, \"\"},\n\t\t{\"(Value).SetIterValue\", Method, 18, \"\"},\n\t\t{\"(Value).SetLen\", Method, 0, \"\"},\n\t\t{\"(Value).SetMapIndex\", Method, 0, \"\"},\n\t\t{\"(Value).SetPointer\", Method, 0, \"\"},\n\t\t{\"(Value).SetString\", Method, 0, \"\"},\n\t\t{\"(Value).SetUint\", Method, 0, \"\"},\n\t\t{\"(Value).SetZero\", Method, 20, \"\"},\n\t\t{\"(Value).Slice\", Method, 0, \"\"},\n\t\t{\"(Value).Slice3\", Method, 2, \"\"},\n\t\t{\"(Value).String\", Method, 0, \"\"},\n\t\t{\"(Value).TryRecv\", Method, 0, \"\"},\n\t\t{\"(Value).TrySend\", Method, 0, \"\"},\n\t\t{\"(Value).Type\", Method, 0, \"\"},\n\t\t{\"(Value).Uint\", Method, 0, \"\"},\n\t\t{\"(Value).UnsafeAddr\", Method, 0, \"\"},\n\t\t{\"(Value).UnsafePointer\", Method, 18, \"\"},\n\t\t{\"Append\", Func, 0, \"func(s Value, x ...Value) Value\"},\n\t\t{\"AppendSlice\", Func, 0, \"func(s Value, t Value) Value\"},\n\t\t{\"Array\", Const, 0, \"\"},\n\t\t{\"ArrayOf\", Func, 5, \"func(length int, elem Type) Type\"},\n\t\t{\"Bool\", Const, 0, \"\"},\n\t\t{\"BothDir\", Const, 0, \"\"},\n\t\t{\"Chan\", Const, 0, \"\"},\n\t\t{\"ChanDir\", Type, 0, \"\"},\n\t\t{\"ChanOf\", Func, 1, \"func(dir ChanDir, t Type) Type\"},\n\t\t{\"Complex128\", Const, 0, \"\"},\n\t\t{\"Complex64\", Const, 0, \"\"},\n\t\t{\"Copy\", Func, 0, \"func(dst Value, src Value) int\"},\n\t\t{\"DeepEqual\", Func, 0, \"func(x any, y any) bool\"},\n\t\t{\"Float32\", Const, 0, \"\"},\n\t\t{\"Float64\", Const, 0, \"\"},\n\t\t{\"Func\", Const, 0, \"\"},\n\t\t{\"FuncOf\", Func, 5, \"func(in []Type, out []Type, variadic bool) Type\"},\n\t\t{\"Indirect\", Func, 0, \"func(v Value) Value\"},\n\t\t{\"Int\", Const, 0, \"\"},\n\t\t{\"Int16\", Const, 0, \"\"},\n\t\t{\"Int32\", Const, 0, \"\"},\n\t\t{\"Int64\", Const, 0, \"\"},\n\t\t{\"Int8\", Const, 0, \"\"},\n\t\t{\"Interface\", Const, 0, \"\"},\n\t\t{\"Invalid\", Const, 0, \"\"},\n\t\t{\"Kind\", Type, 0, \"\"},\n\t\t{\"MakeChan\", Func, 0, \"func(typ Type, buffer int) Value\"},\n\t\t{\"MakeFunc\", Func, 1, \"func(typ Type, fn func(args []Value) (results []Value)) Value\"},\n\t\t{\"MakeMap\", Func, 0, \"func(typ Type) Value\"},\n\t\t{\"MakeMapWithSize\", Func, 9, \"func(typ Type, n int) Value\"},\n\t\t{\"MakeSlice\", Func, 0, \"func(typ Type, len int, cap int) Value\"},\n\t\t{\"Map\", Const, 0, \"\"},\n\t\t{\"MapIter\", Type, 12, \"\"},\n\t\t{\"MapOf\", Func, 1, \"func(key Type, elem Type) Type\"},\n\t\t{\"Method\", Type, 0, \"\"},\n\t\t{\"Method.Func\", Field, 0, \"\"},\n\t\t{\"Method.Index\", Field, 0, \"\"},\n\t\t{\"Method.Name\", Field, 0, \"\"},\n\t\t{\"Method.PkgPath\", Field, 0, \"\"},\n\t\t{\"Method.Type\", Field, 0, \"\"},\n\t\t{\"New\", Func, 0, \"func(typ Type) Value\"},\n\t\t{\"NewAt\", Func, 0, \"func(typ Type, p unsafe.Pointer) Value\"},\n\t\t{\"Pointer\", Const, 18, \"\"},\n\t\t{\"PointerTo\", Func, 18, \"func(t Type) Type\"},\n\t\t{\"Ptr\", Const, 0, \"\"},\n\t\t{\"PtrTo\", Func, 0, \"func(t Type) Type\"},\n\t\t{\"RecvDir\", Const, 0, \"\"},\n\t\t{\"Select\", Func, 1, \"func(cases []SelectCase) (chosen int, recv Value, recvOK bool)\"},\n\t\t{\"SelectCase\", Type, 1, \"\"},\n\t\t{\"SelectCase.Chan\", Field, 1, \"\"},\n\t\t{\"SelectCase.Dir\", Field, 1, \"\"},\n\t\t{\"SelectCase.Send\", Field, 1, \"\"},\n\t\t{\"SelectDefault\", Const, 1, \"\"},\n\t\t{\"SelectDir\", Type, 1, \"\"},\n\t\t{\"SelectRecv\", Const, 1, \"\"},\n\t\t{\"SelectSend\", Const, 1, \"\"},\n\t\t{\"SendDir\", Const, 0, \"\"},\n\t\t{\"Slice\", Const, 0, \"\"},\n\t\t{\"SliceAt\", Func, 23, \"func(typ Type, p unsafe.Pointer, n int) Value\"},\n\t\t{\"SliceHeader\", Type, 0, \"\"},\n\t\t{\"SliceHeader.Cap\", Field, 0, \"\"},\n\t\t{\"SliceHeader.Data\", Field, 0, \"\"},\n\t\t{\"SliceHeader.Len\", Field, 0, \"\"},\n\t\t{\"SliceOf\", Func, 1, \"func(t Type) Type\"},\n\t\t{\"String\", Const, 0, \"\"},\n\t\t{\"StringHeader\", Type, 0, \"\"},\n\t\t{\"StringHeader.Data\", Field, 0, \"\"},\n\t\t{\"StringHeader.Len\", Field, 0, \"\"},\n\t\t{\"Struct\", Const, 0, \"\"},\n\t\t{\"StructField\", Type, 0, \"\"},\n\t\t{\"StructField.Anonymous\", Field, 0, \"\"},\n\t\t{\"StructField.Index\", Field, 0, \"\"},\n\t\t{\"StructField.Name\", Field, 0, \"\"},\n\t\t{\"StructField.Offset\", Field, 0, \"\"},\n\t\t{\"StructField.PkgPath\", Field, 0, \"\"},\n\t\t{\"StructField.Tag\", Field, 0, \"\"},\n\t\t{\"StructField.Type\", Field, 0, \"\"},\n\t\t{\"StructOf\", Func, 7, \"func(fields []StructField) Type\"},\n\t\t{\"StructTag\", Type, 0, \"\"},\n\t\t{\"Swapper\", Func, 8, \"func(slice any) func(i int, j int)\"},\n\t\t{\"TypeAssert\", Func, 25, \"func[T any](v Value) (T, bool)\"},\n\t\t{\"TypeFor\", Func, 22, \"func[T any]() Type\"},\n\t\t{\"TypeOf\", Func, 0, \"func(i any) Type\"},\n\t\t{\"Uint\", Const, 0, \"\"},\n\t\t{\"Uint16\", Const, 0, \"\"},\n\t\t{\"Uint32\", Const, 0, \"\"},\n\t\t{\"Uint64\", Const, 0, \"\"},\n\t\t{\"Uint8\", Const, 0, \"\"},\n\t\t{\"Uintptr\", Const, 0, \"\"},\n\t\t{\"UnsafePointer\", Const, 0, \"\"},\n\t\t{\"Value\", Type, 0, \"\"},\n\t\t{\"ValueError\", Type, 0, \"\"},\n\t\t{\"ValueError.Kind\", Field, 0, \"\"},\n\t\t{\"ValueError.Method\", Field, 0, \"\"},\n\t\t{\"ValueOf\", Func, 0, \"func(i any) Value\"},\n\t\t{\"VisibleFields\", Func, 17, \"func(t Type) []StructField\"},\n\t\t{\"Zero\", Func, 0, \"func(typ Type) Value\"},\n\t},\n\t\"regexp\": {\n\t\t{\"(*Regexp).AppendText\", Method, 24, \"\"},\n\t\t{\"(*Regexp).Copy\", Method, 6, \"\"},\n\t\t{\"(*Regexp).Expand\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ExpandString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).Find\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAll\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllStringIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllStringSubmatch\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllStringSubmatchIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllSubmatch\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindAllSubmatchIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindReaderIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindReaderSubmatchIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindStringIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindStringSubmatch\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindStringSubmatchIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindSubmatch\", Method, 0, \"\"},\n\t\t{\"(*Regexp).FindSubmatchIndex\", Method, 0, \"\"},\n\t\t{\"(*Regexp).LiteralPrefix\", Method, 0, \"\"},\n\t\t{\"(*Regexp).Longest\", Method, 1, \"\"},\n\t\t{\"(*Regexp).MarshalText\", Method, 21, \"\"},\n\t\t{\"(*Regexp).Match\", Method, 0, \"\"},\n\t\t{\"(*Regexp).MatchReader\", Method, 0, \"\"},\n\t\t{\"(*Regexp).MatchString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).NumSubexp\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAll\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAllFunc\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAllLiteral\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAllLiteralString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAllString\", Method, 0, \"\"},\n\t\t{\"(*Regexp).ReplaceAllStringFunc\", Method, 0, \"\"},\n\t\t{\"(*Regexp).Split\", Method, 1, \"\"},\n\t\t{\"(*Regexp).String\", Method, 0, \"\"},\n\t\t{\"(*Regexp).SubexpIndex\", Method, 15, \"\"},\n\t\t{\"(*Regexp).SubexpNames\", Method, 0, \"\"},\n\t\t{\"(*Regexp).UnmarshalText\", Method, 21, \"\"},\n\t\t{\"Compile\", Func, 0, \"func(expr string) (*Regexp, error)\"},\n\t\t{\"CompilePOSIX\", Func, 0, \"func(expr string) (*Regexp, error)\"},\n\t\t{\"Match\", Func, 0, \"func(pattern string, b []byte) (matched bool, err error)\"},\n\t\t{\"MatchReader\", Func, 0, \"func(pattern string, r io.RuneReader) (matched bool, err error)\"},\n\t\t{\"MatchString\", Func, 0, \"func(pattern string, s string) (matched bool, err error)\"},\n\t\t{\"MustCompile\", Func, 0, \"func(str string) *Regexp\"},\n\t\t{\"MustCompilePOSIX\", Func, 0, \"func(str string) *Regexp\"},\n\t\t{\"QuoteMeta\", Func, 0, \"func(s string) string\"},\n\t\t{\"Regexp\", Type, 0, \"\"},\n\t},\n\t\"regexp/syntax\": {\n\t\t{\"(*Error).Error\", Method, 0, \"\"},\n\t\t{\"(*Inst).MatchEmptyWidth\", Method, 0, \"\"},\n\t\t{\"(*Inst).MatchRune\", Method, 0, \"\"},\n\t\t{\"(*Inst).MatchRunePos\", Method, 3, \"\"},\n\t\t{\"(*Inst).String\", Method, 0, \"\"},\n\t\t{\"(*Prog).Prefix\", Method, 0, \"\"},\n\t\t{\"(*Prog).StartCond\", Method, 0, \"\"},\n\t\t{\"(*Prog).String\", Method, 0, \"\"},\n\t\t{\"(*Regexp).CapNames\", Method, 0, \"\"},\n\t\t{\"(*Regexp).Equal\", Method, 0, \"\"},\n\t\t{\"(*Regexp).MaxCap\", Method, 0, \"\"},\n\t\t{\"(*Regexp).Simplify\", Method, 0, \"\"},\n\t\t{\"(*Regexp).String\", Method, 0, \"\"},\n\t\t{\"(ErrorCode).String\", Method, 0, \"\"},\n\t\t{\"(InstOp).String\", Method, 3, \"\"},\n\t\t{\"(Op).String\", Method, 11, \"\"},\n\t\t{\"ClassNL\", Const, 0, \"\"},\n\t\t{\"Compile\", Func, 0, \"func(re *Regexp) (*Prog, error)\"},\n\t\t{\"DotNL\", Const, 0, \"\"},\n\t\t{\"EmptyBeginLine\", Const, 0, \"\"},\n\t\t{\"EmptyBeginText\", Const, 0, \"\"},\n\t\t{\"EmptyEndLine\", Const, 0, \"\"},\n\t\t{\"EmptyEndText\", Const, 0, \"\"},\n\t\t{\"EmptyNoWordBoundary\", Const, 0, \"\"},\n\t\t{\"EmptyOp\", Type, 0, \"\"},\n\t\t{\"EmptyOpContext\", Func, 0, \"func(r1 rune, r2 rune) EmptyOp\"},\n\t\t{\"EmptyWordBoundary\", Const, 0, \"\"},\n\t\t{\"ErrInternalError\", Const, 0, \"\"},\n\t\t{\"ErrInvalidCharClass\", Const, 0, \"\"},\n\t\t{\"ErrInvalidCharRange\", Const, 0, \"\"},\n\t\t{\"ErrInvalidEscape\", Const, 0, \"\"},\n\t\t{\"ErrInvalidNamedCapture\", Const, 0, \"\"},\n\t\t{\"ErrInvalidPerlOp\", Const, 0, \"\"},\n\t\t{\"ErrInvalidRepeatOp\", Const, 0, \"\"},\n\t\t{\"ErrInvalidRepeatSize\", Const, 0, \"\"},\n\t\t{\"ErrInvalidUTF8\", Const, 0, \"\"},\n\t\t{\"ErrLarge\", Const, 20, \"\"},\n\t\t{\"ErrMissingBracket\", Const, 0, \"\"},\n\t\t{\"ErrMissingParen\", Const, 0, \"\"},\n\t\t{\"ErrMissingRepeatArgument\", Const, 0, \"\"},\n\t\t{\"ErrNestingDepth\", Const, 19, \"\"},\n\t\t{\"ErrTrailingBackslash\", Const, 0, \"\"},\n\t\t{\"ErrUnexpectedParen\", Const, 1, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Error.Code\", Field, 0, \"\"},\n\t\t{\"Error.Expr\", Field, 0, \"\"},\n\t\t{\"ErrorCode\", Type, 0, \"\"},\n\t\t{\"Flags\", Type, 0, \"\"},\n\t\t{\"FoldCase\", Const, 0, \"\"},\n\t\t{\"Inst\", Type, 0, \"\"},\n\t\t{\"Inst.Arg\", Field, 0, \"\"},\n\t\t{\"Inst.Op\", Field, 0, \"\"},\n\t\t{\"Inst.Out\", Field, 0, \"\"},\n\t\t{\"Inst.Rune\", Field, 0, \"\"},\n\t\t{\"InstAlt\", Const, 0, \"\"},\n\t\t{\"InstAltMatch\", Const, 0, \"\"},\n\t\t{\"InstCapture\", Const, 0, \"\"},\n\t\t{\"InstEmptyWidth\", Const, 0, \"\"},\n\t\t{\"InstFail\", Const, 0, \"\"},\n\t\t{\"InstMatch\", Const, 0, \"\"},\n\t\t{\"InstNop\", Const, 0, \"\"},\n\t\t{\"InstOp\", Type, 0, \"\"},\n\t\t{\"InstRune\", Const, 0, \"\"},\n\t\t{\"InstRune1\", Const, 0, \"\"},\n\t\t{\"InstRuneAny\", Const, 0, \"\"},\n\t\t{\"InstRuneAnyNotNL\", Const, 0, \"\"},\n\t\t{\"IsWordChar\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"Literal\", Const, 0, \"\"},\n\t\t{\"MatchNL\", Const, 0, \"\"},\n\t\t{\"NonGreedy\", Const, 0, \"\"},\n\t\t{\"OneLine\", Const, 0, \"\"},\n\t\t{\"Op\", Type, 0, \"\"},\n\t\t{\"OpAlternate\", Const, 0, \"\"},\n\t\t{\"OpAnyChar\", Const, 0, \"\"},\n\t\t{\"OpAnyCharNotNL\", Const, 0, \"\"},\n\t\t{\"OpBeginLine\", Const, 0, \"\"},\n\t\t{\"OpBeginText\", Const, 0, \"\"},\n\t\t{\"OpCapture\", Const, 0, \"\"},\n\t\t{\"OpCharClass\", Const, 0, \"\"},\n\t\t{\"OpConcat\", Const, 0, \"\"},\n\t\t{\"OpEmptyMatch\", Const, 0, \"\"},\n\t\t{\"OpEndLine\", Const, 0, \"\"},\n\t\t{\"OpEndText\", Const, 0, \"\"},\n\t\t{\"OpLiteral\", Const, 0, \"\"},\n\t\t{\"OpNoMatch\", Const, 0, \"\"},\n\t\t{\"OpNoWordBoundary\", Const, 0, \"\"},\n\t\t{\"OpPlus\", Const, 0, \"\"},\n\t\t{\"OpQuest\", Const, 0, \"\"},\n\t\t{\"OpRepeat\", Const, 0, \"\"},\n\t\t{\"OpStar\", Const, 0, \"\"},\n\t\t{\"OpWordBoundary\", Const, 0, \"\"},\n\t\t{\"POSIX\", Const, 0, \"\"},\n\t\t{\"Parse\", Func, 0, \"func(s string, flags Flags) (*Regexp, error)\"},\n\t\t{\"Perl\", Const, 0, \"\"},\n\t\t{\"PerlX\", Const, 0, \"\"},\n\t\t{\"Prog\", Type, 0, \"\"},\n\t\t{\"Prog.Inst\", Field, 0, \"\"},\n\t\t{\"Prog.NumCap\", Field, 0, \"\"},\n\t\t{\"Prog.Start\", Field, 0, \"\"},\n\t\t{\"Regexp\", Type, 0, \"\"},\n\t\t{\"Regexp.Cap\", Field, 0, \"\"},\n\t\t{\"Regexp.Flags\", Field, 0, \"\"},\n\t\t{\"Regexp.Max\", Field, 0, \"\"},\n\t\t{\"Regexp.Min\", Field, 0, \"\"},\n\t\t{\"Regexp.Name\", Field, 0, \"\"},\n\t\t{\"Regexp.Op\", Field, 0, \"\"},\n\t\t{\"Regexp.Rune\", Field, 0, \"\"},\n\t\t{\"Regexp.Rune0\", Field, 0, \"\"},\n\t\t{\"Regexp.Sub\", Field, 0, \"\"},\n\t\t{\"Regexp.Sub0\", Field, 0, \"\"},\n\t\t{\"Simple\", Const, 0, \"\"},\n\t\t{\"UnicodeGroups\", Const, 0, \"\"},\n\t\t{\"WasDollar\", Const, 0, \"\"},\n\t},\n\t\"runtime\": {\n\t\t{\"(*BlockProfileRecord).Stack\", Method, 1, \"\"},\n\t\t{\"(*Frames).Next\", Method, 7, \"\"},\n\t\t{\"(*Func).Entry\", Method, 0, \"\"},\n\t\t{\"(*Func).FileLine\", Method, 0, \"\"},\n\t\t{\"(*Func).Name\", Method, 0, \"\"},\n\t\t{\"(*MemProfileRecord).InUseBytes\", Method, 0, \"\"},\n\t\t{\"(*MemProfileRecord).InUseObjects\", Method, 0, \"\"},\n\t\t{\"(*MemProfileRecord).Stack\", Method, 0, \"\"},\n\t\t{\"(*PanicNilError).Error\", Method, 21, \"\"},\n\t\t{\"(*PanicNilError).RuntimeError\", Method, 21, \"\"},\n\t\t{\"(*Pinner).Pin\", Method, 21, \"\"},\n\t\t{\"(*Pinner).Unpin\", Method, 21, \"\"},\n\t\t{\"(*StackRecord).Stack\", Method, 0, \"\"},\n\t\t{\"(*TypeAssertionError).Error\", Method, 0, \"\"},\n\t\t{\"(*TypeAssertionError).RuntimeError\", Method, 0, \"\"},\n\t\t{\"(Cleanup).Stop\", Method, 24, \"\"},\n\t\t{\"(Error).Error\", Method, 0, \"\"},\n\t\t{\"(Error).RuntimeError\", Method, 0, \"\"},\n\t\t{\"AddCleanup\", Func, 24, \"func[T, S any](ptr *T, cleanup func(S), arg S) Cleanup\"},\n\t\t{\"BlockProfile\", Func, 1, \"func(p []BlockProfileRecord) (n int, ok bool)\"},\n\t\t{\"BlockProfileRecord\", Type, 1, \"\"},\n\t\t{\"BlockProfileRecord.Count\", Field, 1, \"\"},\n\t\t{\"BlockProfileRecord.Cycles\", Field, 1, \"\"},\n\t\t{\"BlockProfileRecord.StackRecord\", Field, 1, \"\"},\n\t\t{\"Breakpoint\", Func, 0, \"func()\"},\n\t\t{\"CPUProfile\", Func, 0, \"func() []byte\"},\n\t\t{\"Caller\", Func, 0, \"func(skip int) (pc uintptr, file string, line int, ok bool)\"},\n\t\t{\"Callers\", Func, 0, \"func(skip int, pc []uintptr) int\"},\n\t\t{\"CallersFrames\", Func, 7, \"func(callers []uintptr) *Frames\"},\n\t\t{\"Cleanup\", Type, 24, \"\"},\n\t\t{\"Compiler\", Const, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Frame\", Type, 7, \"\"},\n\t\t{\"Frame.Entry\", Field, 7, \"\"},\n\t\t{\"Frame.File\", Field, 7, \"\"},\n\t\t{\"Frame.Func\", Field, 7, \"\"},\n\t\t{\"Frame.Function\", Field, 7, \"\"},\n\t\t{\"Frame.Line\", Field, 7, \"\"},\n\t\t{\"Frame.PC\", Field, 7, \"\"},\n\t\t{\"Frames\", Type, 7, \"\"},\n\t\t{\"Func\", Type, 0, \"\"},\n\t\t{\"FuncForPC\", Func, 0, \"func(pc uintptr) *Func\"},\n\t\t{\"GC\", Func, 0, \"func()\"},\n\t\t{\"GOARCH\", Const, 0, \"\"},\n\t\t{\"GOMAXPROCS\", Func, 0, \"func(n int) int\"},\n\t\t{\"GOOS\", Const, 0, \"\"},\n\t\t{\"GOROOT\", Func, 0, \"func() string\"},\n\t\t{\"Goexit\", Func, 0, \"func()\"},\n\t\t{\"GoroutineProfile\", Func, 0, \"func(p []StackRecord) (n int, ok bool)\"},\n\t\t{\"Gosched\", Func, 0, \"func()\"},\n\t\t{\"KeepAlive\", Func, 7, \"func(x any)\"},\n\t\t{\"LockOSThread\", Func, 0, \"func()\"},\n\t\t{\"MemProfile\", Func, 0, \"func(p []MemProfileRecord, inuseZero bool) (n int, ok bool)\"},\n\t\t{\"MemProfileRate\", Var, 0, \"\"},\n\t\t{\"MemProfileRecord\", Type, 0, \"\"},\n\t\t{\"MemProfileRecord.AllocBytes\", Field, 0, \"\"},\n\t\t{\"MemProfileRecord.AllocObjects\", Field, 0, \"\"},\n\t\t{\"MemProfileRecord.FreeBytes\", Field, 0, \"\"},\n\t\t{\"MemProfileRecord.FreeObjects\", Field, 0, \"\"},\n\t\t{\"MemProfileRecord.Stack0\", Field, 0, \"\"},\n\t\t{\"MemStats\", Type, 0, \"\"},\n\t\t{\"MemStats.Alloc\", Field, 0, \"\"},\n\t\t{\"MemStats.BuckHashSys\", Field, 0, \"\"},\n\t\t{\"MemStats.BySize\", Field, 0, \"\"},\n\t\t{\"MemStats.DebugGC\", Field, 0, \"\"},\n\t\t{\"MemStats.EnableGC\", Field, 0, \"\"},\n\t\t{\"MemStats.Frees\", Field, 0, \"\"},\n\t\t{\"MemStats.GCCPUFraction\", Field, 5, \"\"},\n\t\t{\"MemStats.GCSys\", Field, 2, \"\"},\n\t\t{\"MemStats.HeapAlloc\", Field, 0, \"\"},\n\t\t{\"MemStats.HeapIdle\", Field, 0, \"\"},\n\t\t{\"MemStats.HeapInuse\", Field, 0, \"\"},\n\t\t{\"MemStats.HeapObjects\", Field, 0, \"\"},\n\t\t{\"MemStats.HeapReleased\", Field, 0, \"\"},\n\t\t{\"MemStats.HeapSys\", Field, 0, \"\"},\n\t\t{\"MemStats.LastGC\", Field, 0, \"\"},\n\t\t{\"MemStats.Lookups\", Field, 0, \"\"},\n\t\t{\"MemStats.MCacheInuse\", Field, 0, \"\"},\n\t\t{\"MemStats.MCacheSys\", Field, 0, \"\"},\n\t\t{\"MemStats.MSpanInuse\", Field, 0, \"\"},\n\t\t{\"MemStats.MSpanSys\", Field, 0, \"\"},\n\t\t{\"MemStats.Mallocs\", Field, 0, \"\"},\n\t\t{\"MemStats.NextGC\", Field, 0, \"\"},\n\t\t{\"MemStats.NumForcedGC\", Field, 8, \"\"},\n\t\t{\"MemStats.NumGC\", Field, 0, \"\"},\n\t\t{\"MemStats.OtherSys\", Field, 2, \"\"},\n\t\t{\"MemStats.PauseEnd\", Field, 4, \"\"},\n\t\t{\"MemStats.PauseNs\", Field, 0, \"\"},\n\t\t{\"MemStats.PauseTotalNs\", Field, 0, \"\"},\n\t\t{\"MemStats.StackInuse\", Field, 0, \"\"},\n\t\t{\"MemStats.StackSys\", Field, 0, \"\"},\n\t\t{\"MemStats.Sys\", Field, 0, \"\"},\n\t\t{\"MemStats.TotalAlloc\", Field, 0, \"\"},\n\t\t{\"MutexProfile\", Func, 8, \"func(p []BlockProfileRecord) (n int, ok bool)\"},\n\t\t{\"NumCPU\", Func, 0, \"func() int\"},\n\t\t{\"NumCgoCall\", Func, 0, \"func() int64\"},\n\t\t{\"NumGoroutine\", Func, 0, \"func() int\"},\n\t\t{\"PanicNilError\", Type, 21, \"\"},\n\t\t{\"Pinner\", Type, 21, \"\"},\n\t\t{\"ReadMemStats\", Func, 0, \"func(m *MemStats)\"},\n\t\t{\"ReadTrace\", Func, 5, \"func() (buf []byte)\"},\n\t\t{\"SetBlockProfileRate\", Func, 1, \"func(rate int)\"},\n\t\t{\"SetCPUProfileRate\", Func, 0, \"func(hz int)\"},\n\t\t{\"SetCgoTraceback\", Func, 7, \"func(version int, traceback unsafe.Pointer, context unsafe.Pointer, symbolizer unsafe.Pointer)\"},\n\t\t{\"SetDefaultGOMAXPROCS\", Func, 25, \"func()\"},\n\t\t{\"SetFinalizer\", Func, 0, \"func(obj any, finalizer any)\"},\n\t\t{\"SetMutexProfileFraction\", Func, 8, \"func(rate int) int\"},\n\t\t{\"Stack\", Func, 0, \"func(buf []byte, all bool) int\"},\n\t\t{\"StackRecord\", Type, 0, \"\"},\n\t\t{\"StackRecord.Stack0\", Field, 0, \"\"},\n\t\t{\"StartTrace\", Func, 5, \"func() error\"},\n\t\t{\"StopTrace\", Func, 5, \"func()\"},\n\t\t{\"ThreadCreateProfile\", Func, 0, \"func(p []StackRecord) (n int, ok bool)\"},\n\t\t{\"TypeAssertionError\", Type, 0, \"\"},\n\t\t{\"UnlockOSThread\", Func, 0, \"func()\"},\n\t\t{\"Version\", Func, 0, \"func() string\"},\n\t},\n\t\"runtime/cgo\": {\n\t\t{\"(Handle).Delete\", Method, 17, \"\"},\n\t\t{\"(Handle).Value\", Method, 17, \"\"},\n\t\t{\"Handle\", Type, 17, \"\"},\n\t\t{\"Incomplete\", Type, 20, \"\"},\n\t\t{\"NewHandle\", Func, 17, \"\"},\n\t},\n\t\"runtime/coverage\": {\n\t\t{\"ClearCounters\", Func, 20, \"func() error\"},\n\t\t{\"WriteCounters\", Func, 20, \"func(w io.Writer) error\"},\n\t\t{\"WriteCountersDir\", Func, 20, \"func(dir string) error\"},\n\t\t{\"WriteMeta\", Func, 20, \"func(w io.Writer) error\"},\n\t\t{\"WriteMetaDir\", Func, 20, \"func(dir string) error\"},\n\t},\n\t\"runtime/debug\": {\n\t\t{\"(*BuildInfo).String\", Method, 18, \"\"},\n\t\t{\"BuildInfo\", Type, 12, \"\"},\n\t\t{\"BuildInfo.Deps\", Field, 12, \"\"},\n\t\t{\"BuildInfo.GoVersion\", Field, 18, \"\"},\n\t\t{\"BuildInfo.Main\", Field, 12, \"\"},\n\t\t{\"BuildInfo.Path\", Field, 12, \"\"},\n\t\t{\"BuildInfo.Settings\", Field, 18, \"\"},\n\t\t{\"BuildSetting\", Type, 18, \"\"},\n\t\t{\"BuildSetting.Key\", Field, 18, \"\"},\n\t\t{\"BuildSetting.Value\", Field, 18, \"\"},\n\t\t{\"CrashOptions\", Type, 23, \"\"},\n\t\t{\"FreeOSMemory\", Func, 1, \"func()\"},\n\t\t{\"GCStats\", Type, 1, \"\"},\n\t\t{\"GCStats.LastGC\", Field, 1, \"\"},\n\t\t{\"GCStats.NumGC\", Field, 1, \"\"},\n\t\t{\"GCStats.Pause\", Field, 1, \"\"},\n\t\t{\"GCStats.PauseEnd\", Field, 4, \"\"},\n\t\t{\"GCStats.PauseQuantiles\", Field, 1, \"\"},\n\t\t{\"GCStats.PauseTotal\", Field, 1, \"\"},\n\t\t{\"Module\", Type, 12, \"\"},\n\t\t{\"Module.Path\", Field, 12, \"\"},\n\t\t{\"Module.Replace\", Field, 12, \"\"},\n\t\t{\"Module.Sum\", Field, 12, \"\"},\n\t\t{\"Module.Version\", Field, 12, \"\"},\n\t\t{\"ParseBuildInfo\", Func, 18, \"func(data string) (bi *BuildInfo, err error)\"},\n\t\t{\"PrintStack\", Func, 0, \"func()\"},\n\t\t{\"ReadBuildInfo\", Func, 12, \"func() (info *BuildInfo, ok bool)\"},\n\t\t{\"ReadGCStats\", Func, 1, \"func(stats *GCStats)\"},\n\t\t{\"SetCrashOutput\", Func, 23, \"func(f *os.File, opts CrashOptions) error\"},\n\t\t{\"SetGCPercent\", Func, 1, \"func(percent int) int\"},\n\t\t{\"SetMaxStack\", Func, 2, \"func(bytes int) int\"},\n\t\t{\"SetMaxThreads\", Func, 2, \"func(threads int) int\"},\n\t\t{\"SetMemoryLimit\", Func, 19, \"func(limit int64) int64\"},\n\t\t{\"SetPanicOnFault\", Func, 3, \"func(enabled bool) bool\"},\n\t\t{\"SetTraceback\", Func, 6, \"func(level string)\"},\n\t\t{\"Stack\", Func, 0, \"func() []byte\"},\n\t\t{\"WriteHeapDump\", Func, 3, \"func(fd uintptr)\"},\n\t},\n\t\"runtime/metrics\": {\n\t\t{\"(Value).Float64\", Method, 16, \"\"},\n\t\t{\"(Value).Float64Histogram\", Method, 16, \"\"},\n\t\t{\"(Value).Kind\", Method, 16, \"\"},\n\t\t{\"(Value).Uint64\", Method, 16, \"\"},\n\t\t{\"All\", Func, 16, \"func() []Description\"},\n\t\t{\"Description\", Type, 16, \"\"},\n\t\t{\"Description.Cumulative\", Field, 16, \"\"},\n\t\t{\"Description.Description\", Field, 16, \"\"},\n\t\t{\"Description.Kind\", Field, 16, \"\"},\n\t\t{\"Description.Name\", Field, 16, \"\"},\n\t\t{\"Float64Histogram\", Type, 16, \"\"},\n\t\t{\"Float64Histogram.Buckets\", Field, 16, \"\"},\n\t\t{\"Float64Histogram.Counts\", Field, 16, \"\"},\n\t\t{\"KindBad\", Const, 16, \"\"},\n\t\t{\"KindFloat64\", Const, 16, \"\"},\n\t\t{\"KindFloat64Histogram\", Const, 16, \"\"},\n\t\t{\"KindUint64\", Const, 16, \"\"},\n\t\t{\"Read\", Func, 16, \"func(m []Sample)\"},\n\t\t{\"Sample\", Type, 16, \"\"},\n\t\t{\"Sample.Name\", Field, 16, \"\"},\n\t\t{\"Sample.Value\", Field, 16, \"\"},\n\t\t{\"Value\", Type, 16, \"\"},\n\t\t{\"ValueKind\", Type, 16, \"\"},\n\t},\n\t\"runtime/pprof\": {\n\t\t{\"(*Profile).Add\", Method, 0, \"\"},\n\t\t{\"(*Profile).Count\", Method, 0, \"\"},\n\t\t{\"(*Profile).Name\", Method, 0, \"\"},\n\t\t{\"(*Profile).Remove\", Method, 0, \"\"},\n\t\t{\"(*Profile).WriteTo\", Method, 0, \"\"},\n\t\t{\"Do\", Func, 9, \"func(ctx context.Context, labels LabelSet, f func(context.Context))\"},\n\t\t{\"ForLabels\", Func, 9, \"func(ctx context.Context, f func(key string, value string) bool)\"},\n\t\t{\"Label\", Func, 9, \"func(ctx context.Context, key string) (string, bool)\"},\n\t\t{\"LabelSet\", Type, 9, \"\"},\n\t\t{\"Labels\", Func, 9, \"func(args ...string) LabelSet\"},\n\t\t{\"Lookup\", Func, 0, \"func(name string) *Profile\"},\n\t\t{\"NewProfile\", Func, 0, \"func(name string) *Profile\"},\n\t\t{\"Profile\", Type, 0, \"\"},\n\t\t{\"Profiles\", Func, 0, \"func() []*Profile\"},\n\t\t{\"SetGoroutineLabels\", Func, 9, \"func(ctx context.Context)\"},\n\t\t{\"StartCPUProfile\", Func, 0, \"func(w io.Writer) error\"},\n\t\t{\"StopCPUProfile\", Func, 0, \"func()\"},\n\t\t{\"WithLabels\", Func, 9, \"func(ctx context.Context, labels LabelSet) context.Context\"},\n\t\t{\"WriteHeapProfile\", Func, 0, \"func(w io.Writer) error\"},\n\t},\n\t\"runtime/trace\": {\n\t\t{\"(*FlightRecorder).Enabled\", Method, 25, \"\"},\n\t\t{\"(*FlightRecorder).Start\", Method, 25, \"\"},\n\t\t{\"(*FlightRecorder).Stop\", Method, 25, \"\"},\n\t\t{\"(*FlightRecorder).WriteTo\", Method, 25, \"\"},\n\t\t{\"(*Region).End\", Method, 11, \"\"},\n\t\t{\"(*Task).End\", Method, 11, \"\"},\n\t\t{\"FlightRecorder\", Type, 25, \"\"},\n\t\t{\"FlightRecorderConfig\", Type, 25, \"\"},\n\t\t{\"FlightRecorderConfig.MaxBytes\", Field, 25, \"\"},\n\t\t{\"FlightRecorderConfig.MinAge\", Field, 25, \"\"},\n\t\t{\"IsEnabled\", Func, 11, \"func() bool\"},\n\t\t{\"Log\", Func, 11, \"func(ctx context.Context, category string, message string)\"},\n\t\t{\"Logf\", Func, 11, \"func(ctx context.Context, category string, format string, args ...any)\"},\n\t\t{\"NewFlightRecorder\", Func, 25, \"func(cfg FlightRecorderConfig) *FlightRecorder\"},\n\t\t{\"NewTask\", Func, 11, \"func(pctx context.Context, taskType string) (ctx context.Context, task *Task)\"},\n\t\t{\"Region\", Type, 11, \"\"},\n\t\t{\"Start\", Func, 5, \"func(w io.Writer) error\"},\n\t\t{\"StartRegion\", Func, 11, \"func(ctx context.Context, regionType string) *Region\"},\n\t\t{\"Stop\", Func, 5, \"func()\"},\n\t\t{\"Task\", Type, 11, \"\"},\n\t\t{\"WithRegion\", Func, 11, \"func(ctx context.Context, regionType string, fn func())\"},\n\t},\n\t\"slices\": {\n\t\t{\"All\", Func, 23, \"func[Slice ~[]E, E any](s Slice) iter.Seq2[int, E]\"},\n\t\t{\"AppendSeq\", Func, 23, \"func[Slice ~[]E, E any](s Slice, seq iter.Seq[E]) Slice\"},\n\t\t{\"Backward\", Func, 23, \"func[Slice ~[]E, E any](s Slice) iter.Seq2[int, E]\"},\n\t\t{\"BinarySearch\", Func, 21, \"func[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)\"},\n\t\t{\"BinarySearchFunc\", Func, 21, \"func[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool)\"},\n\t\t{\"Chunk\", Func, 23, \"func[Slice ~[]E, E any](s Slice, n int) iter.Seq[Slice]\"},\n\t\t{\"Clip\", Func, 21, \"func[S ~[]E, E any](s S) S\"},\n\t\t{\"Clone\", Func, 21, \"func[S ~[]E, E any](s S) S\"},\n\t\t{\"Collect\", Func, 23, \"func[E any](seq iter.Seq[E]) []E\"},\n\t\t{\"Compact\", Func, 21, \"func[S ~[]E, E comparable](s S) S\"},\n\t\t{\"CompactFunc\", Func, 21, \"func[S ~[]E, E any](s S, eq func(E, E) bool) S\"},\n\t\t{\"Compare\", Func, 21, \"func[S ~[]E, E cmp.Ordered](s1 S, s2 S) int\"},\n\t\t{\"CompareFunc\", Func, 21, \"func[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int\"},\n\t\t{\"Concat\", Func, 22, \"func[S ~[]E, E any](slices ...S) S\"},\n\t\t{\"Contains\", Func, 21, \"func[S ~[]E, E comparable](s S, v E) bool\"},\n\t\t{\"ContainsFunc\", Func, 21, \"func[S ~[]E, E any](s S, f func(E) bool) bool\"},\n\t\t{\"Delete\", Func, 21, \"func[S ~[]E, E any](s S, i int, j int) S\"},\n\t\t{\"DeleteFunc\", Func, 21, \"func[S ~[]E, E any](s S, del func(E) bool) S\"},\n\t\t{\"Equal\", Func, 21, \"func[S ~[]E, E comparable](s1 S, s2 S) bool\"},\n\t\t{\"EqualFunc\", Func, 21, \"func[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool\"},\n\t\t{\"Grow\", Func, 21, \"func[S ~[]E, E any](s S, n int) S\"},\n\t\t{\"Index\", Func, 21, \"func[S ~[]E, E comparable](s S, v E) int\"},\n\t\t{\"IndexFunc\", Func, 21, \"func[S ~[]E, E any](s S, f func(E) bool) int\"},\n\t\t{\"Insert\", Func, 21, \"func[S ~[]E, E any](s S, i int, v ...E) S\"},\n\t\t{\"IsSorted\", Func, 21, \"func[S ~[]E, E cmp.Ordered](x S) bool\"},\n\t\t{\"IsSortedFunc\", Func, 21, \"func[S ~[]E, E any](x S, cmp func(a E, b E) int) bool\"},\n\t\t{\"Max\", Func, 21, \"func[S ~[]E, E cmp.Ordered](x S) E\"},\n\t\t{\"MaxFunc\", Func, 21, \"func[S ~[]E, E any](x S, cmp func(a E, b E) int) E\"},\n\t\t{\"Min\", Func, 21, \"func[S ~[]E, E cmp.Ordered](x S) E\"},\n\t\t{\"MinFunc\", Func, 21, \"func[S ~[]E, E any](x S, cmp func(a E, b E) int) E\"},\n\t\t{\"Repeat\", Func, 23, \"func[S ~[]E, E any](x S, count int) S\"},\n\t\t{\"Replace\", Func, 21, \"func[S ~[]E, E any](s S, i int, j int, v ...E) S\"},\n\t\t{\"Reverse\", Func, 21, \"func[S ~[]E, E any](s S)\"},\n\t\t{\"Sort\", Func, 21, \"func[S ~[]E, E cmp.Ordered](x S)\"},\n\t\t{\"SortFunc\", Func, 21, \"func[S ~[]E, E any](x S, cmp func(a E, b E) int)\"},\n\t\t{\"SortStableFunc\", Func, 21, \"func[S ~[]E, E any](x S, cmp func(a E, b E) int)\"},\n\t\t{\"Sorted\", Func, 23, \"func[E cmp.Ordered](seq iter.Seq[E]) []E\"},\n\t\t{\"SortedFunc\", Func, 23, \"func[E any](seq iter.Seq[E], cmp func(E, E) int) []E\"},\n\t\t{\"SortedStableFunc\", Func, 23, \"func[E any](seq iter.Seq[E], cmp func(E, E) int) []E\"},\n\t\t{\"Values\", Func, 23, \"func[Slice ~[]E, E any](s Slice) iter.Seq[E]\"},\n\t},\n\t\"sort\": {\n\t\t{\"(Float64Slice).Len\", Method, 0, \"\"},\n\t\t{\"(Float64Slice).Less\", Method, 0, \"\"},\n\t\t{\"(Float64Slice).Search\", Method, 0, \"\"},\n\t\t{\"(Float64Slice).Sort\", Method, 0, \"\"},\n\t\t{\"(Float64Slice).Swap\", Method, 0, \"\"},\n\t\t{\"(IntSlice).Len\", Method, 0, \"\"},\n\t\t{\"(IntSlice).Less\", Method, 0, \"\"},\n\t\t{\"(IntSlice).Search\", Method, 0, \"\"},\n\t\t{\"(IntSlice).Sort\", Method, 0, \"\"},\n\t\t{\"(IntSlice).Swap\", Method, 0, \"\"},\n\t\t{\"(Interface).Len\", Method, 0, \"\"},\n\t\t{\"(Interface).Less\", Method, 0, \"\"},\n\t\t{\"(Interface).Swap\", Method, 0, \"\"},\n\t\t{\"(StringSlice).Len\", Method, 0, \"\"},\n\t\t{\"(StringSlice).Less\", Method, 0, \"\"},\n\t\t{\"(StringSlice).Search\", Method, 0, \"\"},\n\t\t{\"(StringSlice).Sort\", Method, 0, \"\"},\n\t\t{\"(StringSlice).Swap\", Method, 0, \"\"},\n\t\t{\"Find\", Func, 19, \"func(n int, cmp func(int) int) (i int, found bool)\"},\n\t\t{\"Float64Slice\", Type, 0, \"\"},\n\t\t{\"Float64s\", Func, 0, \"func(x []float64)\"},\n\t\t{\"Float64sAreSorted\", Func, 0, \"func(x []float64) bool\"},\n\t\t{\"IntSlice\", Type, 0, \"\"},\n\t\t{\"Interface\", Type, 0, \"\"},\n\t\t{\"Ints\", Func, 0, \"func(x []int)\"},\n\t\t{\"IntsAreSorted\", Func, 0, \"func(x []int) bool\"},\n\t\t{\"IsSorted\", Func, 0, \"func(data Interface) bool\"},\n\t\t{\"Reverse\", Func, 1, \"func(data Interface) Interface\"},\n\t\t{\"Search\", Func, 0, \"func(n int, f func(int) bool) int\"},\n\t\t{\"SearchFloat64s\", Func, 0, \"func(a []float64, x float64) int\"},\n\t\t{\"SearchInts\", Func, 0, \"func(a []int, x int) int\"},\n\t\t{\"SearchStrings\", Func, 0, \"func(a []string, x string) int\"},\n\t\t{\"Slice\", Func, 8, \"func(x any, less func(i int, j int) bool)\"},\n\t\t{\"SliceIsSorted\", Func, 8, \"func(x any, less func(i int, j int) bool) bool\"},\n\t\t{\"SliceStable\", Func, 8, \"func(x any, less func(i int, j int) bool)\"},\n\t\t{\"Sort\", Func, 0, \"func(data Interface)\"},\n\t\t{\"Stable\", Func, 2, \"func(data Interface)\"},\n\t\t{\"StringSlice\", Type, 0, \"\"},\n\t\t{\"Strings\", Func, 0, \"func(x []string)\"},\n\t\t{\"StringsAreSorted\", Func, 0, \"func(x []string) bool\"},\n\t},\n\t\"strconv\": {\n\t\t{\"(*NumError).Error\", Method, 0, \"\"},\n\t\t{\"(*NumError).Unwrap\", Method, 14, \"\"},\n\t\t{\"AppendBool\", Func, 0, \"func(dst []byte, b bool) []byte\"},\n\t\t{\"AppendFloat\", Func, 0, \"func(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte\"},\n\t\t{\"AppendInt\", Func, 0, \"func(dst []byte, i int64, base int) []byte\"},\n\t\t{\"AppendQuote\", Func, 0, \"func(dst []byte, s string) []byte\"},\n\t\t{\"AppendQuoteRune\", Func, 0, \"func(dst []byte, r rune) []byte\"},\n\t\t{\"AppendQuoteRuneToASCII\", Func, 0, \"func(dst []byte, r rune) []byte\"},\n\t\t{\"AppendQuoteRuneToGraphic\", Func, 6, \"func(dst []byte, r rune) []byte\"},\n\t\t{\"AppendQuoteToASCII\", Func, 0, \"func(dst []byte, s string) []byte\"},\n\t\t{\"AppendQuoteToGraphic\", Func, 6, \"func(dst []byte, s string) []byte\"},\n\t\t{\"AppendUint\", Func, 0, \"func(dst []byte, i uint64, base int) []byte\"},\n\t\t{\"Atoi\", Func, 0, \"func(s string) (int, error)\"},\n\t\t{\"CanBackquote\", Func, 0, \"func(s string) bool\"},\n\t\t{\"ErrRange\", Var, 0, \"\"},\n\t\t{\"ErrSyntax\", Var, 0, \"\"},\n\t\t{\"FormatBool\", Func, 0, \"func(b bool) string\"},\n\t\t{\"FormatComplex\", Func, 15, \"func(c complex128, fmt byte, prec int, bitSize int) string\"},\n\t\t{\"FormatFloat\", Func, 0, \"func(f float64, fmt byte, prec int, bitSize int) string\"},\n\t\t{\"FormatInt\", Func, 0, \"func(i int64, base int) string\"},\n\t\t{\"FormatUint\", Func, 0, \"func(i uint64, base int) string\"},\n\t\t{\"IntSize\", Const, 0, \"\"},\n\t\t{\"IsGraphic\", Func, 6, \"func(r rune) bool\"},\n\t\t{\"IsPrint\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"Itoa\", Func, 0, \"func(i int) string\"},\n\t\t{\"NumError\", Type, 0, \"\"},\n\t\t{\"NumError.Err\", Field, 0, \"\"},\n\t\t{\"NumError.Func\", Field, 0, \"\"},\n\t\t{\"NumError.Num\", Field, 0, \"\"},\n\t\t{\"ParseBool\", Func, 0, \"func(str string) (bool, error)\"},\n\t\t{\"ParseComplex\", Func, 15, \"func(s string, bitSize int) (complex128, error)\"},\n\t\t{\"ParseFloat\", Func, 0, \"func(s string, bitSize int) (float64, error)\"},\n\t\t{\"ParseInt\", Func, 0, \"func(s string, base int, bitSize int) (i int64, err error)\"},\n\t\t{\"ParseUint\", Func, 0, \"func(s string, base int, bitSize int) (uint64, error)\"},\n\t\t{\"Quote\", Func, 0, \"func(s string) string\"},\n\t\t{\"QuoteRune\", Func, 0, \"func(r rune) string\"},\n\t\t{\"QuoteRuneToASCII\", Func, 0, \"func(r rune) string\"},\n\t\t{\"QuoteRuneToGraphic\", Func, 6, \"func(r rune) string\"},\n\t\t{\"QuoteToASCII\", Func, 0, \"func(s string) string\"},\n\t\t{\"QuoteToGraphic\", Func, 6, \"func(s string) string\"},\n\t\t{\"QuotedPrefix\", Func, 17, \"func(s string) (string, error)\"},\n\t\t{\"Unquote\", Func, 0, \"func(s string) (string, error)\"},\n\t\t{\"UnquoteChar\", Func, 0, \"func(s string, quote byte) (value rune, multibyte bool, tail string, err error)\"},\n\t},\n\t\"strings\": {\n\t\t{\"(*Builder).Cap\", Method, 12, \"\"},\n\t\t{\"(*Builder).Grow\", Method, 10, \"\"},\n\t\t{\"(*Builder).Len\", Method, 10, \"\"},\n\t\t{\"(*Builder).Reset\", Method, 10, \"\"},\n\t\t{\"(*Builder).String\", Method, 10, \"\"},\n\t\t{\"(*Builder).Write\", Method, 10, \"\"},\n\t\t{\"(*Builder).WriteByte\", Method, 10, \"\"},\n\t\t{\"(*Builder).WriteRune\", Method, 10, \"\"},\n\t\t{\"(*Builder).WriteString\", Method, 10, \"\"},\n\t\t{\"(*Reader).Len\", Method, 0, \"\"},\n\t\t{\"(*Reader).Read\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadAt\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).ReadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).Reset\", Method, 7, \"\"},\n\t\t{\"(*Reader).Seek\", Method, 0, \"\"},\n\t\t{\"(*Reader).Size\", Method, 5, \"\"},\n\t\t{\"(*Reader).UnreadByte\", Method, 0, \"\"},\n\t\t{\"(*Reader).UnreadRune\", Method, 0, \"\"},\n\t\t{\"(*Reader).WriteTo\", Method, 1, \"\"},\n\t\t{\"(*Replacer).Replace\", Method, 0, \"\"},\n\t\t{\"(*Replacer).WriteString\", Method, 0, \"\"},\n\t\t{\"Builder\", Type, 10, \"\"},\n\t\t{\"Clone\", Func, 18, \"func(s string) string\"},\n\t\t{\"Compare\", Func, 5, \"func(a string, b string) int\"},\n\t\t{\"Contains\", Func, 0, \"func(s string, substr string) bool\"},\n\t\t{\"ContainsAny\", Func, 0, \"func(s string, chars string) bool\"},\n\t\t{\"ContainsFunc\", Func, 21, \"func(s string, f func(rune) bool) bool\"},\n\t\t{\"ContainsRune\", Func, 0, \"func(s string, r rune) bool\"},\n\t\t{\"Count\", Func, 0, \"func(s string, substr string) int\"},\n\t\t{\"Cut\", Func, 18, \"func(s string, sep string) (before string, after string, found bool)\"},\n\t\t{\"CutPrefix\", Func, 20, \"func(s string, prefix string) (after string, found bool)\"},\n\t\t{\"CutSuffix\", Func, 20, \"func(s string, suffix string) (before string, found bool)\"},\n\t\t{\"EqualFold\", Func, 0, \"func(s string, t string) bool\"},\n\t\t{\"Fields\", Func, 0, \"func(s string) []string\"},\n\t\t{\"FieldsFunc\", Func, 0, \"func(s string, f func(rune) bool) []string\"},\n\t\t{\"FieldsFuncSeq\", Func, 24, \"func(s string, f func(rune) bool) iter.Seq[string]\"},\n\t\t{\"FieldsSeq\", Func, 24, \"func(s string) iter.Seq[string]\"},\n\t\t{\"HasPrefix\", Func, 0, \"func(s string, prefix string) bool\"},\n\t\t{\"HasSuffix\", Func, 0, \"func(s string, suffix string) bool\"},\n\t\t{\"Index\", Func, 0, \"func(s string, substr string) int\"},\n\t\t{\"IndexAny\", Func, 0, \"func(s string, chars string) int\"},\n\t\t{\"IndexByte\", Func, 2, \"func(s string, c byte) int\"},\n\t\t{\"IndexFunc\", Func, 0, \"func(s string, f func(rune) bool) int\"},\n\t\t{\"IndexRune\", Func, 0, \"func(s string, r rune) int\"},\n\t\t{\"Join\", Func, 0, \"func(elems []string, sep string) string\"},\n\t\t{\"LastIndex\", Func, 0, \"func(s string, substr string) int\"},\n\t\t{\"LastIndexAny\", Func, 0, \"func(s string, chars string) int\"},\n\t\t{\"LastIndexByte\", Func, 5, \"func(s string, c byte) int\"},\n\t\t{\"LastIndexFunc\", Func, 0, \"func(s string, f func(rune) bool) int\"},\n\t\t{\"Lines\", Func, 24, \"func(s string) iter.Seq[string]\"},\n\t\t{\"Map\", Func, 0, \"func(mapping func(rune) rune, s string) string\"},\n\t\t{\"NewReader\", Func, 0, \"func(s string) *Reader\"},\n\t\t{\"NewReplacer\", Func, 0, \"func(oldnew ...string) *Replacer\"},\n\t\t{\"Reader\", Type, 0, \"\"},\n\t\t{\"Repeat\", Func, 0, \"func(s string, count int) string\"},\n\t\t{\"Replace\", Func, 0, \"func(s string, old string, new string, n int) string\"},\n\t\t{\"ReplaceAll\", Func, 12, \"func(s string, old string, new string) string\"},\n\t\t{\"Replacer\", Type, 0, \"\"},\n\t\t{\"Split\", Func, 0, \"func(s string, sep string) []string\"},\n\t\t{\"SplitAfter\", Func, 0, \"func(s string, sep string) []string\"},\n\t\t{\"SplitAfterN\", Func, 0, \"func(s string, sep string, n int) []string\"},\n\t\t{\"SplitAfterSeq\", Func, 24, \"func(s string, sep string) iter.Seq[string]\"},\n\t\t{\"SplitN\", Func, 0, \"func(s string, sep string, n int) []string\"},\n\t\t{\"SplitSeq\", Func, 24, \"func(s string, sep string) iter.Seq[string]\"},\n\t\t{\"Title\", Func, 0, \"func(s string) string\"},\n\t\t{\"ToLower\", Func, 0, \"func(s string) string\"},\n\t\t{\"ToLowerSpecial\", Func, 0, \"func(c unicode.SpecialCase, s string) string\"},\n\t\t{\"ToTitle\", Func, 0, \"func(s string) string\"},\n\t\t{\"ToTitleSpecial\", Func, 0, \"func(c unicode.SpecialCase, s string) string\"},\n\t\t{\"ToUpper\", Func, 0, \"func(s string) string\"},\n\t\t{\"ToUpperSpecial\", Func, 0, \"func(c unicode.SpecialCase, s string) string\"},\n\t\t{\"ToValidUTF8\", Func, 13, \"func(s string, replacement string) string\"},\n\t\t{\"Trim\", Func, 0, \"func(s string, cutset string) string\"},\n\t\t{\"TrimFunc\", Func, 0, \"func(s string, f func(rune) bool) string\"},\n\t\t{\"TrimLeft\", Func, 0, \"func(s string, cutset string) string\"},\n\t\t{\"TrimLeftFunc\", Func, 0, \"func(s string, f func(rune) bool) string\"},\n\t\t{\"TrimPrefix\", Func, 1, \"func(s string, prefix string) string\"},\n\t\t{\"TrimRight\", Func, 0, \"func(s string, cutset string) string\"},\n\t\t{\"TrimRightFunc\", Func, 0, \"func(s string, f func(rune) bool) string\"},\n\t\t{\"TrimSpace\", Func, 0, \"func(s string) string\"},\n\t\t{\"TrimSuffix\", Func, 1, \"func(s string, suffix string) string\"},\n\t},\n\t\"structs\": {\n\t\t{\"HostLayout\", Type, 23, \"\"},\n\t},\n\t\"sync\": {\n\t\t{\"(*Cond).Broadcast\", Method, 0, \"\"},\n\t\t{\"(*Cond).Signal\", Method, 0, \"\"},\n\t\t{\"(*Cond).Wait\", Method, 0, \"\"},\n\t\t{\"(*Map).Clear\", Method, 23, \"\"},\n\t\t{\"(*Map).CompareAndDelete\", Method, 20, \"\"},\n\t\t{\"(*Map).CompareAndSwap\", Method, 20, \"\"},\n\t\t{\"(*Map).Delete\", Method, 9, \"\"},\n\t\t{\"(*Map).Load\", Method, 9, \"\"},\n\t\t{\"(*Map).LoadAndDelete\", Method, 15, \"\"},\n\t\t{\"(*Map).LoadOrStore\", Method, 9, \"\"},\n\t\t{\"(*Map).Range\", Method, 9, \"\"},\n\t\t{\"(*Map).Store\", Method, 9, \"\"},\n\t\t{\"(*Map).Swap\", Method, 20, \"\"},\n\t\t{\"(*Mutex).Lock\", Method, 0, \"\"},\n\t\t{\"(*Mutex).TryLock\", Method, 18, \"\"},\n\t\t{\"(*Mutex).Unlock\", Method, 0, \"\"},\n\t\t{\"(*Once).Do\", Method, 0, \"\"},\n\t\t{\"(*Pool).Get\", Method, 3, \"\"},\n\t\t{\"(*Pool).Put\", Method, 3, \"\"},\n\t\t{\"(*RWMutex).Lock\", Method, 0, \"\"},\n\t\t{\"(*RWMutex).RLock\", Method, 0, \"\"},\n\t\t{\"(*RWMutex).RLocker\", Method, 0, \"\"},\n\t\t{\"(*RWMutex).RUnlock\", Method, 0, \"\"},\n\t\t{\"(*RWMutex).TryLock\", Method, 18, \"\"},\n\t\t{\"(*RWMutex).TryRLock\", Method, 18, \"\"},\n\t\t{\"(*RWMutex).Unlock\", Method, 0, \"\"},\n\t\t{\"(*WaitGroup).Add\", Method, 0, \"\"},\n\t\t{\"(*WaitGroup).Done\", Method, 0, \"\"},\n\t\t{\"(*WaitGroup).Go\", Method, 25, \"\"},\n\t\t{\"(*WaitGroup).Wait\", Method, 0, \"\"},\n\t\t{\"(Locker).Lock\", Method, 0, \"\"},\n\t\t{\"(Locker).Unlock\", Method, 0, \"\"},\n\t\t{\"Cond\", Type, 0, \"\"},\n\t\t{\"Cond.L\", Field, 0, \"\"},\n\t\t{\"Locker\", Type, 0, \"\"},\n\t\t{\"Map\", Type, 9, \"\"},\n\t\t{\"Mutex\", Type, 0, \"\"},\n\t\t{\"NewCond\", Func, 0, \"func(l Locker) *Cond\"},\n\t\t{\"Once\", Type, 0, \"\"},\n\t\t{\"OnceFunc\", Func, 21, \"func(f func()) func()\"},\n\t\t{\"OnceValue\", Func, 21, \"func[T any](f func() T) func() T\"},\n\t\t{\"OnceValues\", Func, 21, \"func[T1, T2 any](f func() (T1, T2)) func() (T1, T2)\"},\n\t\t{\"Pool\", Type, 3, \"\"},\n\t\t{\"Pool.New\", Field, 3, \"\"},\n\t\t{\"RWMutex\", Type, 0, \"\"},\n\t\t{\"WaitGroup\", Type, 0, \"\"},\n\t},\n\t\"sync/atomic\": {\n\t\t{\"(*Bool).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Bool).Load\", Method, 19, \"\"},\n\t\t{\"(*Bool).Store\", Method, 19, \"\"},\n\t\t{\"(*Bool).Swap\", Method, 19, \"\"},\n\t\t{\"(*Int32).Add\", Method, 19, \"\"},\n\t\t{\"(*Int32).And\", Method, 23, \"\"},\n\t\t{\"(*Int32).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Int32).Load\", Method, 19, \"\"},\n\t\t{\"(*Int32).Or\", Method, 23, \"\"},\n\t\t{\"(*Int32).Store\", Method, 19, \"\"},\n\t\t{\"(*Int32).Swap\", Method, 19, \"\"},\n\t\t{\"(*Int64).Add\", Method, 19, \"\"},\n\t\t{\"(*Int64).And\", Method, 23, \"\"},\n\t\t{\"(*Int64).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Int64).Load\", Method, 19, \"\"},\n\t\t{\"(*Int64).Or\", Method, 23, \"\"},\n\t\t{\"(*Int64).Store\", Method, 19, \"\"},\n\t\t{\"(*Int64).Swap\", Method, 19, \"\"},\n\t\t{\"(*Pointer).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Pointer).Load\", Method, 19, \"\"},\n\t\t{\"(*Pointer).Store\", Method, 19, \"\"},\n\t\t{\"(*Pointer).Swap\", Method, 19, \"\"},\n\t\t{\"(*Uint32).Add\", Method, 19, \"\"},\n\t\t{\"(*Uint32).And\", Method, 23, \"\"},\n\t\t{\"(*Uint32).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Uint32).Load\", Method, 19, \"\"},\n\t\t{\"(*Uint32).Or\", Method, 23, \"\"},\n\t\t{\"(*Uint32).Store\", Method, 19, \"\"},\n\t\t{\"(*Uint32).Swap\", Method, 19, \"\"},\n\t\t{\"(*Uint64).Add\", Method, 19, \"\"},\n\t\t{\"(*Uint64).And\", Method, 23, \"\"},\n\t\t{\"(*Uint64).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Uint64).Load\", Method, 19, \"\"},\n\t\t{\"(*Uint64).Or\", Method, 23, \"\"},\n\t\t{\"(*Uint64).Store\", Method, 19, \"\"},\n\t\t{\"(*Uint64).Swap\", Method, 19, \"\"},\n\t\t{\"(*Uintptr).Add\", Method, 19, \"\"},\n\t\t{\"(*Uintptr).And\", Method, 23, \"\"},\n\t\t{\"(*Uintptr).CompareAndSwap\", Method, 19, \"\"},\n\t\t{\"(*Uintptr).Load\", Method, 19, \"\"},\n\t\t{\"(*Uintptr).Or\", Method, 23, \"\"},\n\t\t{\"(*Uintptr).Store\", Method, 19, \"\"},\n\t\t{\"(*Uintptr).Swap\", Method, 19, \"\"},\n\t\t{\"(*Value).CompareAndSwap\", Method, 17, \"\"},\n\t\t{\"(*Value).Load\", Method, 4, \"\"},\n\t\t{\"(*Value).Store\", Method, 4, \"\"},\n\t\t{\"(*Value).Swap\", Method, 17, \"\"},\n\t\t{\"AddInt32\", Func, 0, \"func(addr *int32, delta int32) (new int32)\"},\n\t\t{\"AddInt64\", Func, 0, \"func(addr *int64, delta int64) (new int64)\"},\n\t\t{\"AddUint32\", Func, 0, \"func(addr *uint32, delta uint32) (new uint32)\"},\n\t\t{\"AddUint64\", Func, 0, \"func(addr *uint64, delta uint64) (new uint64)\"},\n\t\t{\"AddUintptr\", Func, 0, \"func(addr *uintptr, delta uintptr) (new uintptr)\"},\n\t\t{\"AndInt32\", Func, 23, \"func(addr *int32, mask int32) (old int32)\"},\n\t\t{\"AndInt64\", Func, 23, \"func(addr *int64, mask int64) (old int64)\"},\n\t\t{\"AndUint32\", Func, 23, \"func(addr *uint32, mask uint32) (old uint32)\"},\n\t\t{\"AndUint64\", Func, 23, \"func(addr *uint64, mask uint64) (old uint64)\"},\n\t\t{\"AndUintptr\", Func, 23, \"func(addr *uintptr, mask uintptr) (old uintptr)\"},\n\t\t{\"Bool\", Type, 19, \"\"},\n\t\t{\"CompareAndSwapInt32\", Func, 0, \"func(addr *int32, old int32, new int32) (swapped bool)\"},\n\t\t{\"CompareAndSwapInt64\", Func, 0, \"func(addr *int64, old int64, new int64) (swapped bool)\"},\n\t\t{\"CompareAndSwapPointer\", Func, 0, \"func(addr *unsafe.Pointer, old unsafe.Pointer, new unsafe.Pointer) (swapped bool)\"},\n\t\t{\"CompareAndSwapUint32\", Func, 0, \"func(addr *uint32, old uint32, new uint32) (swapped bool)\"},\n\t\t{\"CompareAndSwapUint64\", Func, 0, \"func(addr *uint64, old uint64, new uint64) (swapped bool)\"},\n\t\t{\"CompareAndSwapUintptr\", Func, 0, \"func(addr *uintptr, old uintptr, new uintptr) (swapped bool)\"},\n\t\t{\"Int32\", Type, 19, \"\"},\n\t\t{\"Int64\", Type, 19, \"\"},\n\t\t{\"LoadInt32\", Func, 0, \"func(addr *int32) (val int32)\"},\n\t\t{\"LoadInt64\", Func, 0, \"func(addr *int64) (val int64)\"},\n\t\t{\"LoadPointer\", Func, 0, \"func(addr *unsafe.Pointer) (val unsafe.Pointer)\"},\n\t\t{\"LoadUint32\", Func, 0, \"func(addr *uint32) (val uint32)\"},\n\t\t{\"LoadUint64\", Func, 0, \"func(addr *uint64) (val uint64)\"},\n\t\t{\"LoadUintptr\", Func, 0, \"func(addr *uintptr) (val uintptr)\"},\n\t\t{\"OrInt32\", Func, 23, \"func(addr *int32, mask int32) (old int32)\"},\n\t\t{\"OrInt64\", Func, 23, \"func(addr *int64, mask int64) (old int64)\"},\n\t\t{\"OrUint32\", Func, 23, \"func(addr *uint32, mask uint32) (old uint32)\"},\n\t\t{\"OrUint64\", Func, 23, \"func(addr *uint64, mask uint64) (old uint64)\"},\n\t\t{\"OrUintptr\", Func, 23, \"func(addr *uintptr, mask uintptr) (old uintptr)\"},\n\t\t{\"Pointer\", Type, 19, \"\"},\n\t\t{\"StoreInt32\", Func, 0, \"func(addr *int32, val int32)\"},\n\t\t{\"StoreInt64\", Func, 0, \"func(addr *int64, val int64)\"},\n\t\t{\"StorePointer\", Func, 0, \"func(addr *unsafe.Pointer, val unsafe.Pointer)\"},\n\t\t{\"StoreUint32\", Func, 0, \"func(addr *uint32, val uint32)\"},\n\t\t{\"StoreUint64\", Func, 0, \"func(addr *uint64, val uint64)\"},\n\t\t{\"StoreUintptr\", Func, 0, \"func(addr *uintptr, val uintptr)\"},\n\t\t{\"SwapInt32\", Func, 2, \"func(addr *int32, new int32) (old int32)\"},\n\t\t{\"SwapInt64\", Func, 2, \"func(addr *int64, new int64) (old int64)\"},\n\t\t{\"SwapPointer\", Func, 2, \"func(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)\"},\n\t\t{\"SwapUint32\", Func, 2, \"func(addr *uint32, new uint32) (old uint32)\"},\n\t\t{\"SwapUint64\", Func, 2, \"func(addr *uint64, new uint64) (old uint64)\"},\n\t\t{\"SwapUintptr\", Func, 2, \"func(addr *uintptr, new uintptr) (old uintptr)\"},\n\t\t{\"Uint32\", Type, 19, \"\"},\n\t\t{\"Uint64\", Type, 19, \"\"},\n\t\t{\"Uintptr\", Type, 19, \"\"},\n\t\t{\"Value\", Type, 4, \"\"},\n\t},\n\t\"syscall\": {\n\t\t{\"(*Cmsghdr).SetLen\", Method, 0, \"\"},\n\t\t{\"(*DLL).FindProc\", Method, 0, \"\"},\n\t\t{\"(*DLL).MustFindProc\", Method, 0, \"\"},\n\t\t{\"(*DLL).Release\", Method, 0, \"\"},\n\t\t{\"(*DLLError).Error\", Method, 0, \"\"},\n\t\t{\"(*DLLError).Unwrap\", Method, 16, \"\"},\n\t\t{\"(*Filetime).Nanoseconds\", Method, 0, \"\"},\n\t\t{\"(*Iovec).SetLen\", Method, 0, \"\"},\n\t\t{\"(*LazyDLL).Handle\", Method, 0, \"\"},\n\t\t{\"(*LazyDLL).Load\", Method, 0, \"\"},\n\t\t{\"(*LazyDLL).NewProc\", Method, 0, \"\"},\n\t\t{\"(*LazyProc).Addr\", Method, 0, \"\"},\n\t\t{\"(*LazyProc).Call\", Method, 0, \"\"},\n\t\t{\"(*LazyProc).Find\", Method, 0, \"\"},\n\t\t{\"(*Msghdr).SetControllen\", Method, 0, \"\"},\n\t\t{\"(*Proc).Addr\", Method, 0, \"\"},\n\t\t{\"(*Proc).Call\", Method, 0, \"\"},\n\t\t{\"(*PtraceRegs).PC\", Method, 0, \"\"},\n\t\t{\"(*PtraceRegs).SetPC\", Method, 0, \"\"},\n\t\t{\"(*RawSockaddrAny).Sockaddr\", Method, 0, \"\"},\n\t\t{\"(*SID).Copy\", Method, 0, \"\"},\n\t\t{\"(*SID).Len\", Method, 0, \"\"},\n\t\t{\"(*SID).LookupAccount\", Method, 0, \"\"},\n\t\t{\"(*SID).String\", Method, 0, \"\"},\n\t\t{\"(*Timespec).Nano\", Method, 0, \"\"},\n\t\t{\"(*Timespec).Unix\", Method, 0, \"\"},\n\t\t{\"(*Timeval).Nano\", Method, 0, \"\"},\n\t\t{\"(*Timeval).Nanoseconds\", Method, 0, \"\"},\n\t\t{\"(*Timeval).Unix\", Method, 0, \"\"},\n\t\t{\"(Conn).SyscallConn\", Method, 9, \"\"},\n\t\t{\"(Errno).Error\", Method, 0, \"\"},\n\t\t{\"(Errno).Is\", Method, 13, \"\"},\n\t\t{\"(Errno).Temporary\", Method, 0, \"\"},\n\t\t{\"(Errno).Timeout\", Method, 0, \"\"},\n\t\t{\"(RawConn).Control\", Method, 9, \"\"},\n\t\t{\"(RawConn).Read\", Method, 9, \"\"},\n\t\t{\"(RawConn).Write\", Method, 9, \"\"},\n\t\t{\"(Signal).Signal\", Method, 0, \"\"},\n\t\t{\"(Signal).String\", Method, 0, \"\"},\n\t\t{\"(Token).Close\", Method, 0, \"\"},\n\t\t{\"(Token).GetTokenPrimaryGroup\", Method, 0, \"\"},\n\t\t{\"(Token).GetTokenUser\", Method, 0, \"\"},\n\t\t{\"(Token).GetUserProfileDirectory\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).Continued\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).CoreDump\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).ExitStatus\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).Exited\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).Signal\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).Signaled\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).StopSignal\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).Stopped\", Method, 0, \"\"},\n\t\t{\"(WaitStatus).TrapCause\", Method, 0, \"\"},\n\t\t{\"AF_ALG\", Const, 0, \"\"},\n\t\t{\"AF_APPLETALK\", Const, 0, \"\"},\n\t\t{\"AF_ARP\", Const, 0, \"\"},\n\t\t{\"AF_ASH\", Const, 0, \"\"},\n\t\t{\"AF_ATM\", Const, 0, \"\"},\n\t\t{\"AF_ATMPVC\", Const, 0, \"\"},\n\t\t{\"AF_ATMSVC\", Const, 0, \"\"},\n\t\t{\"AF_AX25\", Const, 0, \"\"},\n\t\t{\"AF_BLUETOOTH\", Const, 0, \"\"},\n\t\t{\"AF_BRIDGE\", Const, 0, \"\"},\n\t\t{\"AF_CAIF\", Const, 0, \"\"},\n\t\t{\"AF_CAN\", Const, 0, \"\"},\n\t\t{\"AF_CCITT\", Const, 0, \"\"},\n\t\t{\"AF_CHAOS\", Const, 0, \"\"},\n\t\t{\"AF_CNT\", Const, 0, \"\"},\n\t\t{\"AF_COIP\", Const, 0, \"\"},\n\t\t{\"AF_DATAKIT\", Const, 0, \"\"},\n\t\t{\"AF_DECnet\", Const, 0, \"\"},\n\t\t{\"AF_DLI\", Const, 0, \"\"},\n\t\t{\"AF_E164\", Const, 0, \"\"},\n\t\t{\"AF_ECMA\", Const, 0, \"\"},\n\t\t{\"AF_ECONET\", Const, 0, \"\"},\n\t\t{\"AF_ENCAP\", Const, 1, \"\"},\n\t\t{\"AF_FILE\", Const, 0, \"\"},\n\t\t{\"AF_HYLINK\", Const, 0, \"\"},\n\t\t{\"AF_IEEE80211\", Const, 0, \"\"},\n\t\t{\"AF_IEEE802154\", Const, 0, \"\"},\n\t\t{\"AF_IMPLINK\", Const, 0, \"\"},\n\t\t{\"AF_INET\", Const, 0, \"\"},\n\t\t{\"AF_INET6\", Const, 0, \"\"},\n\t\t{\"AF_INET6_SDP\", Const, 3, \"\"},\n\t\t{\"AF_INET_SDP\", Const, 3, \"\"},\n\t\t{\"AF_IPX\", Const, 0, \"\"},\n\t\t{\"AF_IRDA\", Const, 0, \"\"},\n\t\t{\"AF_ISDN\", Const, 0, \"\"},\n\t\t{\"AF_ISO\", Const, 0, \"\"},\n\t\t{\"AF_IUCV\", Const, 0, \"\"},\n\t\t{\"AF_KEY\", Const, 0, \"\"},\n\t\t{\"AF_LAT\", Const, 0, \"\"},\n\t\t{\"AF_LINK\", Const, 0, \"\"},\n\t\t{\"AF_LLC\", Const, 0, \"\"},\n\t\t{\"AF_LOCAL\", Const, 0, \"\"},\n\t\t{\"AF_MAX\", Const, 0, \"\"},\n\t\t{\"AF_MPLS\", Const, 1, \"\"},\n\t\t{\"AF_NATM\", Const, 0, \"\"},\n\t\t{\"AF_NDRV\", Const, 0, \"\"},\n\t\t{\"AF_NETBEUI\", Const, 0, \"\"},\n\t\t{\"AF_NETBIOS\", Const, 0, \"\"},\n\t\t{\"AF_NETGRAPH\", Const, 0, \"\"},\n\t\t{\"AF_NETLINK\", Const, 0, \"\"},\n\t\t{\"AF_NETROM\", Const, 0, \"\"},\n\t\t{\"AF_NS\", Const, 0, \"\"},\n\t\t{\"AF_OROUTE\", Const, 1, \"\"},\n\t\t{\"AF_OSI\", Const, 0, \"\"},\n\t\t{\"AF_PACKET\", Const, 0, \"\"},\n\t\t{\"AF_PHONET\", Const, 0, \"\"},\n\t\t{\"AF_PPP\", Const, 0, \"\"},\n\t\t{\"AF_PPPOX\", Const, 0, \"\"},\n\t\t{\"AF_PUP\", Const, 0, \"\"},\n\t\t{\"AF_RDS\", Const, 0, \"\"},\n\t\t{\"AF_RESERVED_36\", Const, 0, \"\"},\n\t\t{\"AF_ROSE\", Const, 0, \"\"},\n\t\t{\"AF_ROUTE\", Const, 0, \"\"},\n\t\t{\"AF_RXRPC\", Const, 0, \"\"},\n\t\t{\"AF_SCLUSTER\", Const, 0, \"\"},\n\t\t{\"AF_SECURITY\", Const, 0, \"\"},\n\t\t{\"AF_SIP\", Const, 0, \"\"},\n\t\t{\"AF_SLOW\", Const, 0, \"\"},\n\t\t{\"AF_SNA\", Const, 0, \"\"},\n\t\t{\"AF_SYSTEM\", Const, 0, \"\"},\n\t\t{\"AF_TIPC\", Const, 0, \"\"},\n\t\t{\"AF_UNIX\", Const, 0, \"\"},\n\t\t{\"AF_UNSPEC\", Const, 0, \"\"},\n\t\t{\"AF_UTUN\", Const, 16, \"\"},\n\t\t{\"AF_VENDOR00\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR01\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR02\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR03\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR04\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR05\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR06\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR07\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR08\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR09\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR10\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR11\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR12\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR13\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR14\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR15\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR16\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR17\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR18\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR19\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR20\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR21\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR22\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR23\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR24\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR25\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR26\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR27\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR28\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR29\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR30\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR31\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR32\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR33\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR34\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR35\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR36\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR37\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR38\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR39\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR40\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR41\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR42\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR43\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR44\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR45\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR46\", Const, 0, \"\"},\n\t\t{\"AF_VENDOR47\", Const, 0, \"\"},\n\t\t{\"AF_WANPIPE\", Const, 0, \"\"},\n\t\t{\"AF_X25\", Const, 0, \"\"},\n\t\t{\"AI_CANONNAME\", Const, 1, \"\"},\n\t\t{\"AI_NUMERICHOST\", Const, 1, \"\"},\n\t\t{\"AI_PASSIVE\", Const, 1, \"\"},\n\t\t{\"APPLICATION_ERROR\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ADAPT\", Const, 0, \"\"},\n\t\t{\"ARPHRD_APPLETLK\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ARCNET\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ASH\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ATM\", Const, 0, \"\"},\n\t\t{\"ARPHRD_AX25\", Const, 0, \"\"},\n\t\t{\"ARPHRD_BIF\", Const, 0, \"\"},\n\t\t{\"ARPHRD_CHAOS\", Const, 0, \"\"},\n\t\t{\"ARPHRD_CISCO\", Const, 0, \"\"},\n\t\t{\"ARPHRD_CSLIP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_CSLIP6\", Const, 0, \"\"},\n\t\t{\"ARPHRD_DDCMP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_DLCI\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ECONET\", Const, 0, \"\"},\n\t\t{\"ARPHRD_EETHER\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ETHER\", Const, 0, \"\"},\n\t\t{\"ARPHRD_EUI64\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FCAL\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FCFABRIC\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FCPL\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FCPP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FDDI\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FRAD\", Const, 0, \"\"},\n\t\t{\"ARPHRD_FRELAY\", Const, 1, \"\"},\n\t\t{\"ARPHRD_HDLC\", Const, 0, \"\"},\n\t\t{\"ARPHRD_HIPPI\", Const, 0, \"\"},\n\t\t{\"ARPHRD_HWX25\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE1394\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE802\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE80211\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE80211_PRISM\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE80211_RADIOTAP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE802154\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE802154_PHY\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IEEE802_TR\", Const, 0, \"\"},\n\t\t{\"ARPHRD_INFINIBAND\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IPDDP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IPGRE\", Const, 0, \"\"},\n\t\t{\"ARPHRD_IRDA\", Const, 0, \"\"},\n\t\t{\"ARPHRD_LAPB\", Const, 0, \"\"},\n\t\t{\"ARPHRD_LOCALTLK\", Const, 0, \"\"},\n\t\t{\"ARPHRD_LOOPBACK\", Const, 0, \"\"},\n\t\t{\"ARPHRD_METRICOM\", Const, 0, \"\"},\n\t\t{\"ARPHRD_NETROM\", Const, 0, \"\"},\n\t\t{\"ARPHRD_NONE\", Const, 0, \"\"},\n\t\t{\"ARPHRD_PIMREG\", Const, 0, \"\"},\n\t\t{\"ARPHRD_PPP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_PRONET\", Const, 0, \"\"},\n\t\t{\"ARPHRD_RAWHDLC\", Const, 0, \"\"},\n\t\t{\"ARPHRD_ROSE\", Const, 0, \"\"},\n\t\t{\"ARPHRD_RSRVD\", Const, 0, \"\"},\n\t\t{\"ARPHRD_SIT\", Const, 0, \"\"},\n\t\t{\"ARPHRD_SKIP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_SLIP\", Const, 0, \"\"},\n\t\t{\"ARPHRD_SLIP6\", Const, 0, \"\"},\n\t\t{\"ARPHRD_STRIP\", Const, 1, \"\"},\n\t\t{\"ARPHRD_TUNNEL\", Const, 0, \"\"},\n\t\t{\"ARPHRD_TUNNEL6\", Const, 0, \"\"},\n\t\t{\"ARPHRD_VOID\", Const, 0, \"\"},\n\t\t{\"ARPHRD_X25\", Const, 0, \"\"},\n\t\t{\"AUTHTYPE_CLIENT\", Const, 0, \"\"},\n\t\t{\"AUTHTYPE_SERVER\", Const, 0, \"\"},\n\t\t{\"Accept\", Func, 0, \"func(fd int) (nfd int, sa Sockaddr, err error)\"},\n\t\t{\"Accept4\", Func, 1, \"func(fd int, flags int) (nfd int, sa Sockaddr, err error)\"},\n\t\t{\"AcceptEx\", Func, 0, \"\"},\n\t\t{\"Access\", Func, 0, \"func(path string, mode uint32) (err error)\"},\n\t\t{\"Acct\", Func, 0, \"func(path string) (err error)\"},\n\t\t{\"AddrinfoW\", Type, 1, \"\"},\n\t\t{\"AddrinfoW.Addr\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Addrlen\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Canonname\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Family\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Flags\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Next\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Protocol\", Field, 1, \"\"},\n\t\t{\"AddrinfoW.Socktype\", Field, 1, \"\"},\n\t\t{\"Adjtime\", Func, 0, \"\"},\n\t\t{\"Adjtimex\", Func, 0, \"func(buf *Timex) (state int, err error)\"},\n\t\t{\"AllThreadsSyscall\", Func, 16, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"AllThreadsSyscall6\", Func, 16, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"AttachLsf\", Func, 0, \"func(fd int, i []SockFilter) error\"},\n\t\t{\"B0\", Const, 0, \"\"},\n\t\t{\"B1000000\", Const, 0, \"\"},\n\t\t{\"B110\", Const, 0, \"\"},\n\t\t{\"B115200\", Const, 0, \"\"},\n\t\t{\"B1152000\", Const, 0, \"\"},\n\t\t{\"B1200\", Const, 0, \"\"},\n\t\t{\"B134\", Const, 0, \"\"},\n\t\t{\"B14400\", Const, 1, \"\"},\n\t\t{\"B150\", Const, 0, \"\"},\n\t\t{\"B1500000\", Const, 0, \"\"},\n\t\t{\"B1800\", Const, 0, \"\"},\n\t\t{\"B19200\", Const, 0, \"\"},\n\t\t{\"B200\", Const, 0, \"\"},\n\t\t{\"B2000000\", Const, 0, \"\"},\n\t\t{\"B230400\", Const, 0, \"\"},\n\t\t{\"B2400\", Const, 0, \"\"},\n\t\t{\"B2500000\", Const, 0, \"\"},\n\t\t{\"B28800\", Const, 1, \"\"},\n\t\t{\"B300\", Const, 0, \"\"},\n\t\t{\"B3000000\", Const, 0, \"\"},\n\t\t{\"B3500000\", Const, 0, \"\"},\n\t\t{\"B38400\", Const, 0, \"\"},\n\t\t{\"B4000000\", Const, 0, \"\"},\n\t\t{\"B460800\", Const, 0, \"\"},\n\t\t{\"B4800\", Const, 0, \"\"},\n\t\t{\"B50\", Const, 0, \"\"},\n\t\t{\"B500000\", Const, 0, \"\"},\n\t\t{\"B57600\", Const, 0, \"\"},\n\t\t{\"B576000\", Const, 0, \"\"},\n\t\t{\"B600\", Const, 0, \"\"},\n\t\t{\"B7200\", Const, 1, \"\"},\n\t\t{\"B75\", Const, 0, \"\"},\n\t\t{\"B76800\", Const, 1, \"\"},\n\t\t{\"B921600\", Const, 0, \"\"},\n\t\t{\"B9600\", Const, 0, \"\"},\n\t\t{\"BASE_PROTOCOL\", Const, 2, \"\"},\n\t\t{\"BIOCFEEDBACK\", Const, 0, \"\"},\n\t\t{\"BIOCFLUSH\", Const, 0, \"\"},\n\t\t{\"BIOCGBLEN\", Const, 0, \"\"},\n\t\t{\"BIOCGDIRECTION\", Const, 0, \"\"},\n\t\t{\"BIOCGDIRFILT\", Const, 1, \"\"},\n\t\t{\"BIOCGDLT\", Const, 0, \"\"},\n\t\t{\"BIOCGDLTLIST\", Const, 0, \"\"},\n\t\t{\"BIOCGETBUFMODE\", Const, 0, \"\"},\n\t\t{\"BIOCGETIF\", Const, 0, \"\"},\n\t\t{\"BIOCGETZMAX\", Const, 0, \"\"},\n\t\t{\"BIOCGFEEDBACK\", Const, 1, \"\"},\n\t\t{\"BIOCGFILDROP\", Const, 1, \"\"},\n\t\t{\"BIOCGHDRCMPLT\", Const, 0, \"\"},\n\t\t{\"BIOCGRSIG\", Const, 0, \"\"},\n\t\t{\"BIOCGRTIMEOUT\", Const, 0, \"\"},\n\t\t{\"BIOCGSEESENT\", Const, 0, \"\"},\n\t\t{\"BIOCGSTATS\", Const, 0, \"\"},\n\t\t{\"BIOCGSTATSOLD\", Const, 1, \"\"},\n\t\t{\"BIOCGTSTAMP\", Const, 1, \"\"},\n\t\t{\"BIOCIMMEDIATE\", Const, 0, \"\"},\n\t\t{\"BIOCLOCK\", Const, 0, \"\"},\n\t\t{\"BIOCPROMISC\", Const, 0, \"\"},\n\t\t{\"BIOCROTZBUF\", Const, 0, \"\"},\n\t\t{\"BIOCSBLEN\", Const, 0, \"\"},\n\t\t{\"BIOCSDIRECTION\", Const, 0, \"\"},\n\t\t{\"BIOCSDIRFILT\", Const, 1, \"\"},\n\t\t{\"BIOCSDLT\", Const, 0, \"\"},\n\t\t{\"BIOCSETBUFMODE\", Const, 0, \"\"},\n\t\t{\"BIOCSETF\", Const, 0, \"\"},\n\t\t{\"BIOCSETFNR\", Const, 0, \"\"},\n\t\t{\"BIOCSETIF\", Const, 0, \"\"},\n\t\t{\"BIOCSETWF\", Const, 0, \"\"},\n\t\t{\"BIOCSETZBUF\", Const, 0, \"\"},\n\t\t{\"BIOCSFEEDBACK\", Const, 1, \"\"},\n\t\t{\"BIOCSFILDROP\", Const, 1, \"\"},\n\t\t{\"BIOCSHDRCMPLT\", Const, 0, \"\"},\n\t\t{\"BIOCSRSIG\", Const, 0, \"\"},\n\t\t{\"BIOCSRTIMEOUT\", Const, 0, \"\"},\n\t\t{\"BIOCSSEESENT\", Const, 0, \"\"},\n\t\t{\"BIOCSTCPF\", Const, 1, \"\"},\n\t\t{\"BIOCSTSTAMP\", Const, 1, \"\"},\n\t\t{\"BIOCSUDPF\", Const, 1, \"\"},\n\t\t{\"BIOCVERSION\", Const, 0, \"\"},\n\t\t{\"BPF_A\", Const, 0, \"\"},\n\t\t{\"BPF_ABS\", Const, 0, \"\"},\n\t\t{\"BPF_ADD\", Const, 0, \"\"},\n\t\t{\"BPF_ALIGNMENT\", Const, 0, \"\"},\n\t\t{\"BPF_ALIGNMENT32\", Const, 1, \"\"},\n\t\t{\"BPF_ALU\", Const, 0, \"\"},\n\t\t{\"BPF_AND\", Const, 0, \"\"},\n\t\t{\"BPF_B\", Const, 0, \"\"},\n\t\t{\"BPF_BUFMODE_BUFFER\", Const, 0, \"\"},\n\t\t{\"BPF_BUFMODE_ZBUF\", Const, 0, \"\"},\n\t\t{\"BPF_DFLTBUFSIZE\", Const, 1, \"\"},\n\t\t{\"BPF_DIRECTION_IN\", Const, 1, \"\"},\n\t\t{\"BPF_DIRECTION_OUT\", Const, 1, \"\"},\n\t\t{\"BPF_DIV\", Const, 0, \"\"},\n\t\t{\"BPF_H\", Const, 0, \"\"},\n\t\t{\"BPF_IMM\", Const, 0, \"\"},\n\t\t{\"BPF_IND\", Const, 0, \"\"},\n\t\t{\"BPF_JA\", Const, 0, \"\"},\n\t\t{\"BPF_JEQ\", Const, 0, \"\"},\n\t\t{\"BPF_JGE\", Const, 0, \"\"},\n\t\t{\"BPF_JGT\", Const, 0, \"\"},\n\t\t{\"BPF_JMP\", Const, 0, \"\"},\n\t\t{\"BPF_JSET\", Const, 0, \"\"},\n\t\t{\"BPF_K\", Const, 0, \"\"},\n\t\t{\"BPF_LD\", Const, 0, \"\"},\n\t\t{\"BPF_LDX\", Const, 0, \"\"},\n\t\t{\"BPF_LEN\", Const, 0, \"\"},\n\t\t{\"BPF_LSH\", Const, 0, \"\"},\n\t\t{\"BPF_MAJOR_VERSION\", Const, 0, \"\"},\n\t\t{\"BPF_MAXBUFSIZE\", Const, 0, \"\"},\n\t\t{\"BPF_MAXINSNS\", Const, 0, \"\"},\n\t\t{\"BPF_MEM\", Const, 0, \"\"},\n\t\t{\"BPF_MEMWORDS\", Const, 0, \"\"},\n\t\t{\"BPF_MINBUFSIZE\", Const, 0, \"\"},\n\t\t{\"BPF_MINOR_VERSION\", Const, 0, \"\"},\n\t\t{\"BPF_MISC\", Const, 0, \"\"},\n\t\t{\"BPF_MSH\", Const, 0, \"\"},\n\t\t{\"BPF_MUL\", Const, 0, \"\"},\n\t\t{\"BPF_NEG\", Const, 0, \"\"},\n\t\t{\"BPF_OR\", Const, 0, \"\"},\n\t\t{\"BPF_RELEASE\", Const, 0, \"\"},\n\t\t{\"BPF_RET\", Const, 0, \"\"},\n\t\t{\"BPF_RSH\", Const, 0, \"\"},\n\t\t{\"BPF_ST\", Const, 0, \"\"},\n\t\t{\"BPF_STX\", Const, 0, \"\"},\n\t\t{\"BPF_SUB\", Const, 0, \"\"},\n\t\t{\"BPF_TAX\", Const, 0, \"\"},\n\t\t{\"BPF_TXA\", Const, 0, \"\"},\n\t\t{\"BPF_T_BINTIME\", Const, 1, \"\"},\n\t\t{\"BPF_T_BINTIME_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_BINTIME_MONOTONIC\", Const, 1, \"\"},\n\t\t{\"BPF_T_BINTIME_MONOTONIC_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_FLAG_MASK\", Const, 1, \"\"},\n\t\t{\"BPF_T_FORMAT_MASK\", Const, 1, \"\"},\n\t\t{\"BPF_T_MICROTIME\", Const, 1, \"\"},\n\t\t{\"BPF_T_MICROTIME_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_MICROTIME_MONOTONIC\", Const, 1, \"\"},\n\t\t{\"BPF_T_MICROTIME_MONOTONIC_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_MONOTONIC\", Const, 1, \"\"},\n\t\t{\"BPF_T_MONOTONIC_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_NANOTIME\", Const, 1, \"\"},\n\t\t{\"BPF_T_NANOTIME_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_NANOTIME_MONOTONIC\", Const, 1, \"\"},\n\t\t{\"BPF_T_NANOTIME_MONOTONIC_FAST\", Const, 1, \"\"},\n\t\t{\"BPF_T_NONE\", Const, 1, \"\"},\n\t\t{\"BPF_T_NORMAL\", Const, 1, \"\"},\n\t\t{\"BPF_W\", Const, 0, \"\"},\n\t\t{\"BPF_X\", Const, 0, \"\"},\n\t\t{\"BRKINT\", Const, 0, \"\"},\n\t\t{\"Bind\", Func, 0, \"func(fd int, sa Sockaddr) (err error)\"},\n\t\t{\"BindToDevice\", Func, 0, \"func(fd int, device string) (err error)\"},\n\t\t{\"BpfBuflen\", Func, 0, \"\"},\n\t\t{\"BpfDatalink\", Func, 0, \"\"},\n\t\t{\"BpfHdr\", Type, 0, \"\"},\n\t\t{\"BpfHdr.Caplen\", Field, 0, \"\"},\n\t\t{\"BpfHdr.Datalen\", Field, 0, \"\"},\n\t\t{\"BpfHdr.Hdrlen\", Field, 0, \"\"},\n\t\t{\"BpfHdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"BpfHdr.Tstamp\", Field, 0, \"\"},\n\t\t{\"BpfHeadercmpl\", Func, 0, \"\"},\n\t\t{\"BpfInsn\", Type, 0, \"\"},\n\t\t{\"BpfInsn.Code\", Field, 0, \"\"},\n\t\t{\"BpfInsn.Jf\", Field, 0, \"\"},\n\t\t{\"BpfInsn.Jt\", Field, 0, \"\"},\n\t\t{\"BpfInsn.K\", Field, 0, \"\"},\n\t\t{\"BpfInterface\", Func, 0, \"\"},\n\t\t{\"BpfJump\", Func, 0, \"\"},\n\t\t{\"BpfProgram\", Type, 0, \"\"},\n\t\t{\"BpfProgram.Insns\", Field, 0, \"\"},\n\t\t{\"BpfProgram.Len\", Field, 0, \"\"},\n\t\t{\"BpfProgram.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"BpfStat\", Type, 0, \"\"},\n\t\t{\"BpfStat.Capt\", Field, 2, \"\"},\n\t\t{\"BpfStat.Drop\", Field, 0, \"\"},\n\t\t{\"BpfStat.Padding\", Field, 2, \"\"},\n\t\t{\"BpfStat.Recv\", Field, 0, \"\"},\n\t\t{\"BpfStats\", Func, 0, \"\"},\n\t\t{\"BpfStmt\", Func, 0, \"\"},\n\t\t{\"BpfTimeout\", Func, 0, \"\"},\n\t\t{\"BpfTimeval\", Type, 2, \"\"},\n\t\t{\"BpfTimeval.Sec\", Field, 2, \"\"},\n\t\t{\"BpfTimeval.Usec\", Field, 2, \"\"},\n\t\t{\"BpfVersion\", Type, 0, \"\"},\n\t\t{\"BpfVersion.Major\", Field, 0, \"\"},\n\t\t{\"BpfVersion.Minor\", Field, 0, \"\"},\n\t\t{\"BpfZbuf\", Type, 0, \"\"},\n\t\t{\"BpfZbuf.Bufa\", Field, 0, \"\"},\n\t\t{\"BpfZbuf.Bufb\", Field, 0, \"\"},\n\t\t{\"BpfZbuf.Buflen\", Field, 0, \"\"},\n\t\t{\"BpfZbufHeader\", Type, 0, \"\"},\n\t\t{\"BpfZbufHeader.Kernel_gen\", Field, 0, \"\"},\n\t\t{\"BpfZbufHeader.Kernel_len\", Field, 0, \"\"},\n\t\t{\"BpfZbufHeader.User_gen\", Field, 0, \"\"},\n\t\t{\"BpfZbufHeader.X_bzh_pad\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation\", Type, 0, \"\"},\n\t\t{\"ByHandleFileInformation.CreationTime\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.FileAttributes\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.FileIndexHigh\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.FileIndexLow\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.FileSizeHigh\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.FileSizeLow\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.LastAccessTime\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.LastWriteTime\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.NumberOfLinks\", Field, 0, \"\"},\n\t\t{\"ByHandleFileInformation.VolumeSerialNumber\", Field, 0, \"\"},\n\t\t{\"BytePtrFromString\", Func, 1, \"func(s string) (*byte, error)\"},\n\t\t{\"ByteSliceFromString\", Func, 1, \"func(s string) ([]byte, error)\"},\n\t\t{\"CCR0_FLUSH\", Const, 1, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_AUTHENTICODE\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_AUTHENTICODE_TS\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_BASE\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_BASIC_CONSTRAINTS\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_EV\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_MICROSOFT_ROOT\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_NT_AUTH\", Const, 0, \"\"},\n\t\t{\"CERT_CHAIN_POLICY_SSL\", Const, 0, \"\"},\n\t\t{\"CERT_E_CN_NO_MATCH\", Const, 0, \"\"},\n\t\t{\"CERT_E_EXPIRED\", Const, 0, \"\"},\n\t\t{\"CERT_E_PURPOSE\", Const, 0, \"\"},\n\t\t{\"CERT_E_ROLE\", Const, 0, \"\"},\n\t\t{\"CERT_E_UNTRUSTEDROOT\", Const, 0, \"\"},\n\t\t{\"CERT_STORE_ADD_ALWAYS\", Const, 0, \"\"},\n\t\t{\"CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG\", Const, 0, \"\"},\n\t\t{\"CERT_STORE_PROV_MEMORY\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_INVALID_BASIC_CONSTRAINTS\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_INVALID_EXTENSION\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_INVALID_NAME_CONSTRAINTS\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_INVALID_POLICY_CONSTRAINTS\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_CYCLIC\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_EXPLICIT_DISTRUST\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_NOT_SIGNATURE_VALID\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_NOT_TIME_VALID\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_NOT_VALID_FOR_USAGE\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_OFFLINE_REVOCATION\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_REVOKED\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_IS_UNTRUSTED_ROOT\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_NO_ERROR\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY\", Const, 0, \"\"},\n\t\t{\"CERT_TRUST_REVOCATION_STATUS_UNKNOWN\", Const, 0, \"\"},\n\t\t{\"CFLUSH\", Const, 1, \"\"},\n\t\t{\"CLOCAL\", Const, 0, \"\"},\n\t\t{\"CLONE_CHILD_CLEARTID\", Const, 2, \"\"},\n\t\t{\"CLONE_CHILD_SETTID\", Const, 2, \"\"},\n\t\t{\"CLONE_CLEAR_SIGHAND\", Const, 20, \"\"},\n\t\t{\"CLONE_CSIGNAL\", Const, 3, \"\"},\n\t\t{\"CLONE_DETACHED\", Const, 2, \"\"},\n\t\t{\"CLONE_FILES\", Const, 2, \"\"},\n\t\t{\"CLONE_FS\", Const, 2, \"\"},\n\t\t{\"CLONE_INTO_CGROUP\", Const, 20, \"\"},\n\t\t{\"CLONE_IO\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWCGROUP\", Const, 20, \"\"},\n\t\t{\"CLONE_NEWIPC\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWNET\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWNS\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWPID\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWTIME\", Const, 20, \"\"},\n\t\t{\"CLONE_NEWUSER\", Const, 2, \"\"},\n\t\t{\"CLONE_NEWUTS\", Const, 2, \"\"},\n\t\t{\"CLONE_PARENT\", Const, 2, \"\"},\n\t\t{\"CLONE_PARENT_SETTID\", Const, 2, \"\"},\n\t\t{\"CLONE_PID\", Const, 3, \"\"},\n\t\t{\"CLONE_PIDFD\", Const, 20, \"\"},\n\t\t{\"CLONE_PTRACE\", Const, 2, \"\"},\n\t\t{\"CLONE_SETTLS\", Const, 2, \"\"},\n\t\t{\"CLONE_SIGHAND\", Const, 2, \"\"},\n\t\t{\"CLONE_SYSVSEM\", Const, 2, \"\"},\n\t\t{\"CLONE_THREAD\", Const, 2, \"\"},\n\t\t{\"CLONE_UNTRACED\", Const, 2, \"\"},\n\t\t{\"CLONE_VFORK\", Const, 2, \"\"},\n\t\t{\"CLONE_VM\", Const, 2, \"\"},\n\t\t{\"CPUID_CFLUSH\", Const, 1, \"\"},\n\t\t{\"CREAD\", Const, 0, \"\"},\n\t\t{\"CREATE_ALWAYS\", Const, 0, \"\"},\n\t\t{\"CREATE_NEW\", Const, 0, \"\"},\n\t\t{\"CREATE_NEW_PROCESS_GROUP\", Const, 1, \"\"},\n\t\t{\"CREATE_UNICODE_ENVIRONMENT\", Const, 0, \"\"},\n\t\t{\"CRYPT_DEFAULT_CONTAINER_OPTIONAL\", Const, 0, \"\"},\n\t\t{\"CRYPT_DELETEKEYSET\", Const, 0, \"\"},\n\t\t{\"CRYPT_MACHINE_KEYSET\", Const, 0, \"\"},\n\t\t{\"CRYPT_NEWKEYSET\", Const, 0, \"\"},\n\t\t{\"CRYPT_SILENT\", Const, 0, \"\"},\n\t\t{\"CRYPT_VERIFYCONTEXT\", Const, 0, \"\"},\n\t\t{\"CS5\", Const, 0, \"\"},\n\t\t{\"CS6\", Const, 0, \"\"},\n\t\t{\"CS7\", Const, 0, \"\"},\n\t\t{\"CS8\", Const, 0, \"\"},\n\t\t{\"CSIZE\", Const, 0, \"\"},\n\t\t{\"CSTART\", Const, 1, \"\"},\n\t\t{\"CSTATUS\", Const, 1, \"\"},\n\t\t{\"CSTOP\", Const, 1, \"\"},\n\t\t{\"CSTOPB\", Const, 0, \"\"},\n\t\t{\"CSUSP\", Const, 1, \"\"},\n\t\t{\"CTL_MAXNAME\", Const, 0, \"\"},\n\t\t{\"CTL_NET\", Const, 0, \"\"},\n\t\t{\"CTL_QUERY\", Const, 1, \"\"},\n\t\t{\"CTRL_BREAK_EVENT\", Const, 1, \"\"},\n\t\t{\"CTRL_CLOSE_EVENT\", Const, 14, \"\"},\n\t\t{\"CTRL_C_EVENT\", Const, 1, \"\"},\n\t\t{\"CTRL_LOGOFF_EVENT\", Const, 14, \"\"},\n\t\t{\"CTRL_SHUTDOWN_EVENT\", Const, 14, \"\"},\n\t\t{\"CancelIo\", Func, 0, \"\"},\n\t\t{\"CancelIoEx\", Func, 1, \"\"},\n\t\t{\"CertAddCertificateContextToStore\", Func, 0, \"\"},\n\t\t{\"CertChainContext\", Type, 0, \"\"},\n\t\t{\"CertChainContext.ChainCount\", Field, 0, \"\"},\n\t\t{\"CertChainContext.Chains\", Field, 0, \"\"},\n\t\t{\"CertChainContext.HasRevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertChainContext.LowerQualityChainCount\", Field, 0, \"\"},\n\t\t{\"CertChainContext.LowerQualityChains\", Field, 0, \"\"},\n\t\t{\"CertChainContext.RevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertChainContext.Size\", Field, 0, \"\"},\n\t\t{\"CertChainContext.TrustStatus\", Field, 0, \"\"},\n\t\t{\"CertChainElement\", Type, 0, \"\"},\n\t\t{\"CertChainElement.ApplicationUsage\", Field, 0, \"\"},\n\t\t{\"CertChainElement.CertContext\", Field, 0, \"\"},\n\t\t{\"CertChainElement.ExtendedErrorInfo\", Field, 0, \"\"},\n\t\t{\"CertChainElement.IssuanceUsage\", Field, 0, \"\"},\n\t\t{\"CertChainElement.RevocationInfo\", Field, 0, \"\"},\n\t\t{\"CertChainElement.Size\", Field, 0, \"\"},\n\t\t{\"CertChainElement.TrustStatus\", Field, 0, \"\"},\n\t\t{\"CertChainPara\", Type, 0, \"\"},\n\t\t{\"CertChainPara.CacheResync\", Field, 0, \"\"},\n\t\t{\"CertChainPara.CheckRevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertChainPara.RequestedUsage\", Field, 0, \"\"},\n\t\t{\"CertChainPara.RequstedIssuancePolicy\", Field, 0, \"\"},\n\t\t{\"CertChainPara.RevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertChainPara.Size\", Field, 0, \"\"},\n\t\t{\"CertChainPara.URLRetrievalTimeout\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyPara\", Type, 0, \"\"},\n\t\t{\"CertChainPolicyPara.ExtraPolicyPara\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyPara.Flags\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyPara.Size\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyStatus\", Type, 0, \"\"},\n\t\t{\"CertChainPolicyStatus.ChainIndex\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyStatus.ElementIndex\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyStatus.Error\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyStatus.ExtraPolicyStatus\", Field, 0, \"\"},\n\t\t{\"CertChainPolicyStatus.Size\", Field, 0, \"\"},\n\t\t{\"CertCloseStore\", Func, 0, \"\"},\n\t\t{\"CertContext\", Type, 0, \"\"},\n\t\t{\"CertContext.CertInfo\", Field, 0, \"\"},\n\t\t{\"CertContext.EncodedCert\", Field, 0, \"\"},\n\t\t{\"CertContext.EncodingType\", Field, 0, \"\"},\n\t\t{\"CertContext.Length\", Field, 0, \"\"},\n\t\t{\"CertContext.Store\", Field, 0, \"\"},\n\t\t{\"CertCreateCertificateContext\", Func, 0, \"\"},\n\t\t{\"CertEnhKeyUsage\", Type, 0, \"\"},\n\t\t{\"CertEnhKeyUsage.Length\", Field, 0, \"\"},\n\t\t{\"CertEnhKeyUsage.UsageIdentifiers\", Field, 0, \"\"},\n\t\t{\"CertEnumCertificatesInStore\", Func, 0, \"\"},\n\t\t{\"CertFreeCertificateChain\", Func, 0, \"\"},\n\t\t{\"CertFreeCertificateContext\", Func, 0, \"\"},\n\t\t{\"CertGetCertificateChain\", Func, 0, \"\"},\n\t\t{\"CertInfo\", Type, 11, \"\"},\n\t\t{\"CertOpenStore\", Func, 0, \"\"},\n\t\t{\"CertOpenSystemStore\", Func, 0, \"\"},\n\t\t{\"CertRevocationCrlInfo\", Type, 11, \"\"},\n\t\t{\"CertRevocationInfo\", Type, 0, \"\"},\n\t\t{\"CertRevocationInfo.CrlInfo\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.FreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.HasFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.OidSpecificInfo\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.RevocationOid\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.RevocationResult\", Field, 0, \"\"},\n\t\t{\"CertRevocationInfo.Size\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain\", Type, 0, \"\"},\n\t\t{\"CertSimpleChain.Elements\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.HasRevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.NumElements\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.RevocationFreshnessTime\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.Size\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.TrustListInfo\", Field, 0, \"\"},\n\t\t{\"CertSimpleChain.TrustStatus\", Field, 0, \"\"},\n\t\t{\"CertTrustListInfo\", Type, 11, \"\"},\n\t\t{\"CertTrustStatus\", Type, 0, \"\"},\n\t\t{\"CertTrustStatus.ErrorStatus\", Field, 0, \"\"},\n\t\t{\"CertTrustStatus.InfoStatus\", Field, 0, \"\"},\n\t\t{\"CertUsageMatch\", Type, 0, \"\"},\n\t\t{\"CertUsageMatch.Type\", Field, 0, \"\"},\n\t\t{\"CertUsageMatch.Usage\", Field, 0, \"\"},\n\t\t{\"CertVerifyCertificateChainPolicy\", Func, 0, \"\"},\n\t\t{\"Chdir\", Func, 0, \"func(path string) (err error)\"},\n\t\t{\"CheckBpfVersion\", Func, 0, \"\"},\n\t\t{\"Chflags\", Func, 0, \"\"},\n\t\t{\"Chmod\", Func, 0, \"func(path string, mode uint32) (err error)\"},\n\t\t{\"Chown\", Func, 0, \"func(path string, uid int, gid int) (err error)\"},\n\t\t{\"Chroot\", Func, 0, \"func(path string) (err error)\"},\n\t\t{\"Clearenv\", Func, 0, \"func()\"},\n\t\t{\"Close\", Func, 0, \"func(fd int) (err error)\"},\n\t\t{\"CloseHandle\", Func, 0, \"\"},\n\t\t{\"CloseOnExec\", Func, 0, \"func(fd int)\"},\n\t\t{\"Closesocket\", Func, 0, \"\"},\n\t\t{\"CmsgLen\", Func, 0, \"func(datalen int) int\"},\n\t\t{\"CmsgSpace\", Func, 0, \"func(datalen int) int\"},\n\t\t{\"Cmsghdr\", Type, 0, \"\"},\n\t\t{\"Cmsghdr.Len\", Field, 0, \"\"},\n\t\t{\"Cmsghdr.Level\", Field, 0, \"\"},\n\t\t{\"Cmsghdr.Type\", Field, 0, \"\"},\n\t\t{\"Cmsghdr.X__cmsg_data\", Field, 0, \"\"},\n\t\t{\"CommandLineToArgv\", Func, 0, \"\"},\n\t\t{\"ComputerName\", Func, 0, \"\"},\n\t\t{\"Conn\", Type, 9, \"\"},\n\t\t{\"Connect\", Func, 0, \"func(fd int, sa Sockaddr) (err error)\"},\n\t\t{\"ConnectEx\", Func, 1, \"\"},\n\t\t{\"ConvertSidToStringSid\", Func, 0, \"\"},\n\t\t{\"ConvertStringSidToSid\", Func, 0, \"\"},\n\t\t{\"CopySid\", Func, 0, \"\"},\n\t\t{\"Creat\", Func, 0, \"func(path string, mode uint32) (fd int, err error)\"},\n\t\t{\"CreateDirectory\", Func, 0, \"\"},\n\t\t{\"CreateFile\", Func, 0, \"\"},\n\t\t{\"CreateFileMapping\", Func, 0, \"\"},\n\t\t{\"CreateHardLink\", Func, 4, \"\"},\n\t\t{\"CreateIoCompletionPort\", Func, 0, \"\"},\n\t\t{\"CreatePipe\", Func, 0, \"\"},\n\t\t{\"CreateProcess\", Func, 0, \"\"},\n\t\t{\"CreateProcessAsUser\", Func, 10, \"\"},\n\t\t{\"CreateSymbolicLink\", Func, 4, \"\"},\n\t\t{\"CreateToolhelp32Snapshot\", Func, 4, \"\"},\n\t\t{\"Credential\", Type, 0, \"\"},\n\t\t{\"Credential.Gid\", Field, 0, \"\"},\n\t\t{\"Credential.Groups\", Field, 0, \"\"},\n\t\t{\"Credential.NoSetGroups\", Field, 9, \"\"},\n\t\t{\"Credential.Uid\", Field, 0, \"\"},\n\t\t{\"CryptAcquireContext\", Func, 0, \"\"},\n\t\t{\"CryptGenRandom\", Func, 0, \"\"},\n\t\t{\"CryptReleaseContext\", Func, 0, \"\"},\n\t\t{\"DIOCBSFLUSH\", Const, 1, \"\"},\n\t\t{\"DIOCOSFPFLUSH\", Const, 1, \"\"},\n\t\t{\"DLL\", Type, 0, \"\"},\n\t\t{\"DLL.Handle\", Field, 0, \"\"},\n\t\t{\"DLL.Name\", Field, 0, \"\"},\n\t\t{\"DLLError\", Type, 0, \"\"},\n\t\t{\"DLLError.Err\", Field, 0, \"\"},\n\t\t{\"DLLError.Msg\", Field, 0, \"\"},\n\t\t{\"DLLError.ObjName\", Field, 0, \"\"},\n\t\t{\"DLT_A429\", Const, 0, \"\"},\n\t\t{\"DLT_A653_ICM\", Const, 0, \"\"},\n\t\t{\"DLT_AIRONET_HEADER\", Const, 0, \"\"},\n\t\t{\"DLT_AOS\", Const, 1, \"\"},\n\t\t{\"DLT_APPLE_IP_OVER_IEEE1394\", Const, 0, \"\"},\n\t\t{\"DLT_ARCNET\", Const, 0, \"\"},\n\t\t{\"DLT_ARCNET_LINUX\", Const, 0, \"\"},\n\t\t{\"DLT_ATM_CLIP\", Const, 0, \"\"},\n\t\t{\"DLT_ATM_RFC1483\", Const, 0, \"\"},\n\t\t{\"DLT_AURORA\", Const, 0, \"\"},\n\t\t{\"DLT_AX25\", Const, 0, \"\"},\n\t\t{\"DLT_AX25_KISS\", Const, 0, \"\"},\n\t\t{\"DLT_BACNET_MS_TP\", Const, 0, \"\"},\n\t\t{\"DLT_BLUETOOTH_HCI_H4\", Const, 0, \"\"},\n\t\t{\"DLT_BLUETOOTH_HCI_H4_WITH_PHDR\", Const, 0, \"\"},\n\t\t{\"DLT_CAN20B\", Const, 0, \"\"},\n\t\t{\"DLT_CAN_SOCKETCAN\", Const, 1, \"\"},\n\t\t{\"DLT_CHAOS\", Const, 0, \"\"},\n\t\t{\"DLT_CHDLC\", Const, 0, \"\"},\n\t\t{\"DLT_CISCO_IOS\", Const, 0, \"\"},\n\t\t{\"DLT_C_HDLC\", Const, 0, \"\"},\n\t\t{\"DLT_C_HDLC_WITH_DIR\", Const, 0, \"\"},\n\t\t{\"DLT_DBUS\", Const, 1, \"\"},\n\t\t{\"DLT_DECT\", Const, 1, \"\"},\n\t\t{\"DLT_DOCSIS\", Const, 0, \"\"},\n\t\t{\"DLT_DVB_CI\", Const, 1, \"\"},\n\t\t{\"DLT_ECONET\", Const, 0, \"\"},\n\t\t{\"DLT_EN10MB\", Const, 0, \"\"},\n\t\t{\"DLT_EN3MB\", Const, 0, \"\"},\n\t\t{\"DLT_ENC\", Const, 0, \"\"},\n\t\t{\"DLT_ERF\", Const, 0, \"\"},\n\t\t{\"DLT_ERF_ETH\", Const, 0, \"\"},\n\t\t{\"DLT_ERF_POS\", Const, 0, \"\"},\n\t\t{\"DLT_FC_2\", Const, 1, \"\"},\n\t\t{\"DLT_FC_2_WITH_FRAME_DELIMS\", Const, 1, \"\"},\n\t\t{\"DLT_FDDI\", Const, 0, \"\"},\n\t\t{\"DLT_FLEXRAY\", Const, 0, \"\"},\n\t\t{\"DLT_FRELAY\", Const, 0, \"\"},\n\t\t{\"DLT_FRELAY_WITH_DIR\", Const, 0, \"\"},\n\t\t{\"DLT_GCOM_SERIAL\", Const, 0, \"\"},\n\t\t{\"DLT_GCOM_T1E1\", Const, 0, \"\"},\n\t\t{\"DLT_GPF_F\", Const, 0, \"\"},\n\t\t{\"DLT_GPF_T\", Const, 0, \"\"},\n\t\t{\"DLT_GPRS_LLC\", Const, 0, \"\"},\n\t\t{\"DLT_GSMTAP_ABIS\", Const, 1, \"\"},\n\t\t{\"DLT_GSMTAP_UM\", Const, 1, \"\"},\n\t\t{\"DLT_HDLC\", Const, 1, \"\"},\n\t\t{\"DLT_HHDLC\", Const, 0, \"\"},\n\t\t{\"DLT_HIPPI\", Const, 1, \"\"},\n\t\t{\"DLT_IBM_SN\", Const, 0, \"\"},\n\t\t{\"DLT_IBM_SP\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_11\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_11_RADIO\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_11_RADIO_AVS\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_15_4\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_15_4_LINUX\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_15_4_NOFCS\", Const, 1, \"\"},\n\t\t{\"DLT_IEEE802_15_4_NONASK_PHY\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_16_MAC_CPS\", Const, 0, \"\"},\n\t\t{\"DLT_IEEE802_16_MAC_CPS_RADIO\", Const, 0, \"\"},\n\t\t{\"DLT_IPFILTER\", Const, 0, \"\"},\n\t\t{\"DLT_IPMB\", Const, 0, \"\"},\n\t\t{\"DLT_IPMB_LINUX\", Const, 0, \"\"},\n\t\t{\"DLT_IPNET\", Const, 1, \"\"},\n\t\t{\"DLT_IPOIB\", Const, 1, \"\"},\n\t\t{\"DLT_IPV4\", Const, 1, \"\"},\n\t\t{\"DLT_IPV6\", Const, 1, \"\"},\n\t\t{\"DLT_IP_OVER_FC\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ATM1\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ATM2\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ATM_CEMIC\", Const, 1, \"\"},\n\t\t{\"DLT_JUNIPER_CHDLC\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ES\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ETHER\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_FIBRECHANNEL\", Const, 1, \"\"},\n\t\t{\"DLT_JUNIPER_FRELAY\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_GGSN\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_ISM\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_MFR\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_MLFR\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_MLPPP\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_MONITOR\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_PIC_PEER\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_PPP\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_PPPOE\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_PPPOE_ATM\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_SERVICES\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_SRX_E2E\", Const, 1, \"\"},\n\t\t{\"DLT_JUNIPER_ST\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_VP\", Const, 0, \"\"},\n\t\t{\"DLT_JUNIPER_VS\", Const, 1, \"\"},\n\t\t{\"DLT_LAPB_WITH_DIR\", Const, 0, \"\"},\n\t\t{\"DLT_LAPD\", Const, 0, \"\"},\n\t\t{\"DLT_LIN\", Const, 0, \"\"},\n\t\t{\"DLT_LINUX_EVDEV\", Const, 1, \"\"},\n\t\t{\"DLT_LINUX_IRDA\", Const, 0, \"\"},\n\t\t{\"DLT_LINUX_LAPD\", Const, 0, \"\"},\n\t\t{\"DLT_LINUX_PPP_WITHDIRECTION\", Const, 0, \"\"},\n\t\t{\"DLT_LINUX_SLL\", Const, 0, \"\"},\n\t\t{\"DLT_LOOP\", Const, 0, \"\"},\n\t\t{\"DLT_LTALK\", Const, 0, \"\"},\n\t\t{\"DLT_MATCHING_MAX\", Const, 1, \"\"},\n\t\t{\"DLT_MATCHING_MIN\", Const, 1, \"\"},\n\t\t{\"DLT_MFR\", Const, 0, \"\"},\n\t\t{\"DLT_MOST\", Const, 0, \"\"},\n\t\t{\"DLT_MPEG_2_TS\", Const, 1, \"\"},\n\t\t{\"DLT_MPLS\", Const, 1, \"\"},\n\t\t{\"DLT_MTP2\", Const, 0, \"\"},\n\t\t{\"DLT_MTP2_WITH_PHDR\", Const, 0, \"\"},\n\t\t{\"DLT_MTP3\", Const, 0, \"\"},\n\t\t{\"DLT_MUX27010\", Const, 1, \"\"},\n\t\t{\"DLT_NETANALYZER\", Const, 1, \"\"},\n\t\t{\"DLT_NETANALYZER_TRANSPARENT\", Const, 1, \"\"},\n\t\t{\"DLT_NFC_LLCP\", Const, 1, \"\"},\n\t\t{\"DLT_NFLOG\", Const, 1, \"\"},\n\t\t{\"DLT_NG40\", Const, 1, \"\"},\n\t\t{\"DLT_NULL\", Const, 0, \"\"},\n\t\t{\"DLT_PCI_EXP\", Const, 0, \"\"},\n\t\t{\"DLT_PFLOG\", Const, 0, \"\"},\n\t\t{\"DLT_PFSYNC\", Const, 0, \"\"},\n\t\t{\"DLT_PPI\", Const, 0, \"\"},\n\t\t{\"DLT_PPP\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_BSDOS\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_ETHER\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_PPPD\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_SERIAL\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_WITH_DIR\", Const, 0, \"\"},\n\t\t{\"DLT_PPP_WITH_DIRECTION\", Const, 0, \"\"},\n\t\t{\"DLT_PRISM_HEADER\", Const, 0, \"\"},\n\t\t{\"DLT_PRONET\", Const, 0, \"\"},\n\t\t{\"DLT_RAIF1\", Const, 0, \"\"},\n\t\t{\"DLT_RAW\", Const, 0, \"\"},\n\t\t{\"DLT_RAWAF_MASK\", Const, 1, \"\"},\n\t\t{\"DLT_RIO\", Const, 0, \"\"},\n\t\t{\"DLT_SCCP\", Const, 0, \"\"},\n\t\t{\"DLT_SITA\", Const, 0, \"\"},\n\t\t{\"DLT_SLIP\", Const, 0, \"\"},\n\t\t{\"DLT_SLIP_BSDOS\", Const, 0, \"\"},\n\t\t{\"DLT_STANAG_5066_D_PDU\", Const, 1, \"\"},\n\t\t{\"DLT_SUNATM\", Const, 0, \"\"},\n\t\t{\"DLT_SYMANTEC_FIREWALL\", Const, 0, \"\"},\n\t\t{\"DLT_TZSP\", Const, 0, \"\"},\n\t\t{\"DLT_USB\", Const, 0, \"\"},\n\t\t{\"DLT_USB_LINUX\", Const, 0, \"\"},\n\t\t{\"DLT_USB_LINUX_MMAPPED\", Const, 1, \"\"},\n\t\t{\"DLT_USER0\", Const, 0, \"\"},\n\t\t{\"DLT_USER1\", Const, 0, \"\"},\n\t\t{\"DLT_USER10\", Const, 0, \"\"},\n\t\t{\"DLT_USER11\", Const, 0, \"\"},\n\t\t{\"DLT_USER12\", Const, 0, \"\"},\n\t\t{\"DLT_USER13\", Const, 0, \"\"},\n\t\t{\"DLT_USER14\", Const, 0, \"\"},\n\t\t{\"DLT_USER15\", Const, 0, \"\"},\n\t\t{\"DLT_USER2\", Const, 0, \"\"},\n\t\t{\"DLT_USER3\", Const, 0, \"\"},\n\t\t{\"DLT_USER4\", Const, 0, \"\"},\n\t\t{\"DLT_USER5\", Const, 0, \"\"},\n\t\t{\"DLT_USER6\", Const, 0, \"\"},\n\t\t{\"DLT_USER7\", Const, 0, \"\"},\n\t\t{\"DLT_USER8\", Const, 0, \"\"},\n\t\t{\"DLT_USER9\", Const, 0, \"\"},\n\t\t{\"DLT_WIHART\", Const, 1, \"\"},\n\t\t{\"DLT_X2E_SERIAL\", Const, 0, \"\"},\n\t\t{\"DLT_X2E_XORAYA\", Const, 0, \"\"},\n\t\t{\"DNSMXData\", Type, 0, \"\"},\n\t\t{\"DNSMXData.NameExchange\", Field, 0, \"\"},\n\t\t{\"DNSMXData.Pad\", Field, 0, \"\"},\n\t\t{\"DNSMXData.Preference\", Field, 0, \"\"},\n\t\t{\"DNSPTRData\", Type, 0, \"\"},\n\t\t{\"DNSPTRData.Host\", Field, 0, \"\"},\n\t\t{\"DNSRecord\", Type, 0, \"\"},\n\t\t{\"DNSRecord.Data\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Dw\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Length\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Name\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Next\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Reserved\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Ttl\", Field, 0, \"\"},\n\t\t{\"DNSRecord.Type\", Field, 0, \"\"},\n\t\t{\"DNSSRVData\", Type, 0, \"\"},\n\t\t{\"DNSSRVData.Pad\", Field, 0, \"\"},\n\t\t{\"DNSSRVData.Port\", Field, 0, \"\"},\n\t\t{\"DNSSRVData.Priority\", Field, 0, \"\"},\n\t\t{\"DNSSRVData.Target\", Field, 0, \"\"},\n\t\t{\"DNSSRVData.Weight\", Field, 0, \"\"},\n\t\t{\"DNSTXTData\", Type, 0, \"\"},\n\t\t{\"DNSTXTData.StringArray\", Field, 0, \"\"},\n\t\t{\"DNSTXTData.StringCount\", Field, 0, \"\"},\n\t\t{\"DNS_INFO_NO_RECORDS\", Const, 4, \"\"},\n\t\t{\"DNS_TYPE_A\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_A6\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_AAAA\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_ADDRS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_AFSDB\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_ALL\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_ANY\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_ATMA\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_AXFR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_CERT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_CNAME\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_DHCID\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_DNAME\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_DNSKEY\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_DS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_EID\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_GID\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_GPOS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_HINFO\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_ISDN\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_IXFR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_KEY\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_KX\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_LOC\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MAILA\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MAILB\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MB\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MD\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MF\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MG\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MINFO\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_MX\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NAPTR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NBSTAT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NIMLOC\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NSAP\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NSAPPTR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NSEC\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NULL\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_NXT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_OPT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_PTR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_PX\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_RP\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_RRSIG\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_RT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_SIG\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_SINK\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_SOA\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_SRV\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_TEXT\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_TKEY\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_TSIG\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_UID\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_UINFO\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_UNSPEC\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_WINS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_WINSR\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_WKS\", Const, 0, \"\"},\n\t\t{\"DNS_TYPE_X25\", Const, 0, \"\"},\n\t\t{\"DT_BLK\", Const, 0, \"\"},\n\t\t{\"DT_CHR\", Const, 0, \"\"},\n\t\t{\"DT_DIR\", Const, 0, \"\"},\n\t\t{\"DT_FIFO\", Const, 0, \"\"},\n\t\t{\"DT_LNK\", Const, 0, \"\"},\n\t\t{\"DT_REG\", Const, 0, \"\"},\n\t\t{\"DT_SOCK\", Const, 0, \"\"},\n\t\t{\"DT_UNKNOWN\", Const, 0, \"\"},\n\t\t{\"DT_WHT\", Const, 0, \"\"},\n\t\t{\"DUPLICATE_CLOSE_SOURCE\", Const, 0, \"\"},\n\t\t{\"DUPLICATE_SAME_ACCESS\", Const, 0, \"\"},\n\t\t{\"DeleteFile\", Func, 0, \"\"},\n\t\t{\"DetachLsf\", Func, 0, \"func(fd int) error\"},\n\t\t{\"DeviceIoControl\", Func, 4, \"\"},\n\t\t{\"Dirent\", Type, 0, \"\"},\n\t\t{\"Dirent.Fileno\", Field, 0, \"\"},\n\t\t{\"Dirent.Ino\", Field, 0, \"\"},\n\t\t{\"Dirent.Name\", Field, 0, \"\"},\n\t\t{\"Dirent.Namlen\", Field, 0, \"\"},\n\t\t{\"Dirent.Off\", Field, 0, \"\"},\n\t\t{\"Dirent.Pad0\", Field, 12, \"\"},\n\t\t{\"Dirent.Pad1\", Field, 12, \"\"},\n\t\t{\"Dirent.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Dirent.Reclen\", Field, 0, \"\"},\n\t\t{\"Dirent.Seekoff\", Field, 0, \"\"},\n\t\t{\"Dirent.Type\", Field, 0, \"\"},\n\t\t{\"Dirent.X__d_padding\", Field, 3, \"\"},\n\t\t{\"DnsNameCompare\", Func, 4, \"\"},\n\t\t{\"DnsQuery\", Func, 0, \"\"},\n\t\t{\"DnsRecordListFree\", Func, 0, \"\"},\n\t\t{\"DnsSectionAdditional\", Const, 4, \"\"},\n\t\t{\"DnsSectionAnswer\", Const, 4, \"\"},\n\t\t{\"DnsSectionAuthority\", Const, 4, \"\"},\n\t\t{\"DnsSectionQuestion\", Const, 4, \"\"},\n\t\t{\"Dup\", Func, 0, \"func(oldfd int) (fd int, err error)\"},\n\t\t{\"Dup2\", Func, 0, \"func(oldfd int, newfd int) (err error)\"},\n\t\t{\"Dup3\", Func, 2, \"func(oldfd int, newfd int, flags int) (err error)\"},\n\t\t{\"DuplicateHandle\", Func, 0, \"\"},\n\t\t{\"E2BIG\", Const, 0, \"\"},\n\t\t{\"EACCES\", Const, 0, \"\"},\n\t\t{\"EADDRINUSE\", Const, 0, \"\"},\n\t\t{\"EADDRNOTAVAIL\", Const, 0, \"\"},\n\t\t{\"EADV\", Const, 0, \"\"},\n\t\t{\"EAFNOSUPPORT\", Const, 0, \"\"},\n\t\t{\"EAGAIN\", Const, 0, \"\"},\n\t\t{\"EALREADY\", Const, 0, \"\"},\n\t\t{\"EAUTH\", Const, 0, \"\"},\n\t\t{\"EBADARCH\", Const, 0, \"\"},\n\t\t{\"EBADE\", Const, 0, \"\"},\n\t\t{\"EBADEXEC\", Const, 0, \"\"},\n\t\t{\"EBADF\", Const, 0, \"\"},\n\t\t{\"EBADFD\", Const, 0, \"\"},\n\t\t{\"EBADMACHO\", Const, 0, \"\"},\n\t\t{\"EBADMSG\", Const, 0, \"\"},\n\t\t{\"EBADR\", Const, 0, \"\"},\n\t\t{\"EBADRPC\", Const, 0, \"\"},\n\t\t{\"EBADRQC\", Const, 0, \"\"},\n\t\t{\"EBADSLT\", Const, 0, \"\"},\n\t\t{\"EBFONT\", Const, 0, \"\"},\n\t\t{\"EBUSY\", Const, 0, \"\"},\n\t\t{\"ECANCELED\", Const, 0, \"\"},\n\t\t{\"ECAPMODE\", Const, 1, \"\"},\n\t\t{\"ECHILD\", Const, 0, \"\"},\n\t\t{\"ECHO\", Const, 0, \"\"},\n\t\t{\"ECHOCTL\", Const, 0, \"\"},\n\t\t{\"ECHOE\", Const, 0, \"\"},\n\t\t{\"ECHOK\", Const, 0, \"\"},\n\t\t{\"ECHOKE\", Const, 0, \"\"},\n\t\t{\"ECHONL\", Const, 0, \"\"},\n\t\t{\"ECHOPRT\", Const, 0, \"\"},\n\t\t{\"ECHRNG\", Const, 0, \"\"},\n\t\t{\"ECOMM\", Const, 0, \"\"},\n\t\t{\"ECONNABORTED\", Const, 0, \"\"},\n\t\t{\"ECONNREFUSED\", Const, 0, \"\"},\n\t\t{\"ECONNRESET\", Const, 0, \"\"},\n\t\t{\"EDEADLK\", Const, 0, \"\"},\n\t\t{\"EDEADLOCK\", Const, 0, \"\"},\n\t\t{\"EDESTADDRREQ\", Const, 0, \"\"},\n\t\t{\"EDEVERR\", Const, 0, \"\"},\n\t\t{\"EDOM\", Const, 0, \"\"},\n\t\t{\"EDOOFUS\", Const, 0, \"\"},\n\t\t{\"EDOTDOT\", Const, 0, \"\"},\n\t\t{\"EDQUOT\", Const, 0, \"\"},\n\t\t{\"EEXIST\", Const, 0, \"\"},\n\t\t{\"EFAULT\", Const, 0, \"\"},\n\t\t{\"EFBIG\", Const, 0, \"\"},\n\t\t{\"EFER_LMA\", Const, 1, \"\"},\n\t\t{\"EFER_LME\", Const, 1, \"\"},\n\t\t{\"EFER_NXE\", Const, 1, \"\"},\n\t\t{\"EFER_SCE\", Const, 1, \"\"},\n\t\t{\"EFTYPE\", Const, 0, \"\"},\n\t\t{\"EHOSTDOWN\", Const, 0, \"\"},\n\t\t{\"EHOSTUNREACH\", Const, 0, \"\"},\n\t\t{\"EHWPOISON\", Const, 0, \"\"},\n\t\t{\"EIDRM\", Const, 0, \"\"},\n\t\t{\"EILSEQ\", Const, 0, \"\"},\n\t\t{\"EINPROGRESS\", Const, 0, \"\"},\n\t\t{\"EINTR\", Const, 0, \"\"},\n\t\t{\"EINVAL\", Const, 0, \"\"},\n\t\t{\"EIO\", Const, 0, \"\"},\n\t\t{\"EIPSEC\", Const, 1, \"\"},\n\t\t{\"EISCONN\", Const, 0, \"\"},\n\t\t{\"EISDIR\", Const, 0, \"\"},\n\t\t{\"EISNAM\", Const, 0, \"\"},\n\t\t{\"EKEYEXPIRED\", Const, 0, \"\"},\n\t\t{\"EKEYREJECTED\", Const, 0, \"\"},\n\t\t{\"EKEYREVOKED\", Const, 0, \"\"},\n\t\t{\"EL2HLT\", Const, 0, \"\"},\n\t\t{\"EL2NSYNC\", Const, 0, \"\"},\n\t\t{\"EL3HLT\", Const, 0, \"\"},\n\t\t{\"EL3RST\", Const, 0, \"\"},\n\t\t{\"ELAST\", Const, 0, \"\"},\n\t\t{\"ELF_NGREG\", Const, 0, \"\"},\n\t\t{\"ELF_PRARGSZ\", Const, 0, \"\"},\n\t\t{\"ELIBACC\", Const, 0, \"\"},\n\t\t{\"ELIBBAD\", Const, 0, \"\"},\n\t\t{\"ELIBEXEC\", Const, 0, \"\"},\n\t\t{\"ELIBMAX\", Const, 0, \"\"},\n\t\t{\"ELIBSCN\", Const, 0, \"\"},\n\t\t{\"ELNRNG\", Const, 0, \"\"},\n\t\t{\"ELOOP\", Const, 0, \"\"},\n\t\t{\"EMEDIUMTYPE\", Const, 0, \"\"},\n\t\t{\"EMFILE\", Const, 0, \"\"},\n\t\t{\"EMLINK\", Const, 0, \"\"},\n\t\t{\"EMSGSIZE\", Const, 0, \"\"},\n\t\t{\"EMT_TAGOVF\", Const, 1, \"\"},\n\t\t{\"EMULTIHOP\", Const, 0, \"\"},\n\t\t{\"EMUL_ENABLED\", Const, 1, \"\"},\n\t\t{\"EMUL_LINUX\", Const, 1, \"\"},\n\t\t{\"EMUL_LINUX32\", Const, 1, \"\"},\n\t\t{\"EMUL_MAXID\", Const, 1, \"\"},\n\t\t{\"EMUL_NATIVE\", Const, 1, \"\"},\n\t\t{\"ENAMETOOLONG\", Const, 0, \"\"},\n\t\t{\"ENAVAIL\", Const, 0, \"\"},\n\t\t{\"ENDRUNDISC\", Const, 1, \"\"},\n\t\t{\"ENEEDAUTH\", Const, 0, \"\"},\n\t\t{\"ENETDOWN\", Const, 0, \"\"},\n\t\t{\"ENETRESET\", Const, 0, \"\"},\n\t\t{\"ENETUNREACH\", Const, 0, \"\"},\n\t\t{\"ENFILE\", Const, 0, \"\"},\n\t\t{\"ENOANO\", Const, 0, \"\"},\n\t\t{\"ENOATTR\", Const, 0, \"\"},\n\t\t{\"ENOBUFS\", Const, 0, \"\"},\n\t\t{\"ENOCSI\", Const, 0, \"\"},\n\t\t{\"ENODATA\", Const, 0, \"\"},\n\t\t{\"ENODEV\", Const, 0, \"\"},\n\t\t{\"ENOENT\", Const, 0, \"\"},\n\t\t{\"ENOEXEC\", Const, 0, \"\"},\n\t\t{\"ENOKEY\", Const, 0, \"\"},\n\t\t{\"ENOLCK\", Const, 0, \"\"},\n\t\t{\"ENOLINK\", Const, 0, \"\"},\n\t\t{\"ENOMEDIUM\", Const, 0, \"\"},\n\t\t{\"ENOMEM\", Const, 0, \"\"},\n\t\t{\"ENOMSG\", Const, 0, \"\"},\n\t\t{\"ENONET\", Const, 0, \"\"},\n\t\t{\"ENOPKG\", Const, 0, \"\"},\n\t\t{\"ENOPOLICY\", Const, 0, \"\"},\n\t\t{\"ENOPROTOOPT\", Const, 0, \"\"},\n\t\t{\"ENOSPC\", Const, 0, \"\"},\n\t\t{\"ENOSR\", Const, 0, \"\"},\n\t\t{\"ENOSTR\", Const, 0, \"\"},\n\t\t{\"ENOSYS\", Const, 0, \"\"},\n\t\t{\"ENOTBLK\", Const, 0, \"\"},\n\t\t{\"ENOTCAPABLE\", Const, 0, \"\"},\n\t\t{\"ENOTCONN\", Const, 0, \"\"},\n\t\t{\"ENOTDIR\", Const, 0, \"\"},\n\t\t{\"ENOTEMPTY\", Const, 0, \"\"},\n\t\t{\"ENOTNAM\", Const, 0, \"\"},\n\t\t{\"ENOTRECOVERABLE\", Const, 0, \"\"},\n\t\t{\"ENOTSOCK\", Const, 0, \"\"},\n\t\t{\"ENOTSUP\", Const, 0, \"\"},\n\t\t{\"ENOTTY\", Const, 0, \"\"},\n\t\t{\"ENOTUNIQ\", Const, 0, \"\"},\n\t\t{\"ENXIO\", Const, 0, \"\"},\n\t\t{\"EN_SW_CTL_INF\", Const, 1, \"\"},\n\t\t{\"EN_SW_CTL_PREC\", Const, 1, \"\"},\n\t\t{\"EN_SW_CTL_ROUND\", Const, 1, \"\"},\n\t\t{\"EN_SW_DATACHAIN\", Const, 1, \"\"},\n\t\t{\"EN_SW_DENORM\", Const, 1, \"\"},\n\t\t{\"EN_SW_INVOP\", Const, 1, \"\"},\n\t\t{\"EN_SW_OVERFLOW\", Const, 1, \"\"},\n\t\t{\"EN_SW_PRECLOSS\", Const, 1, \"\"},\n\t\t{\"EN_SW_UNDERFLOW\", Const, 1, \"\"},\n\t\t{\"EN_SW_ZERODIV\", Const, 1, \"\"},\n\t\t{\"EOPNOTSUPP\", Const, 0, \"\"},\n\t\t{\"EOVERFLOW\", Const, 0, \"\"},\n\t\t{\"EOWNERDEAD\", Const, 0, \"\"},\n\t\t{\"EPERM\", Const, 0, \"\"},\n\t\t{\"EPFNOSUPPORT\", Const, 0, \"\"},\n\t\t{\"EPIPE\", Const, 0, \"\"},\n\t\t{\"EPOLLERR\", Const, 0, \"\"},\n\t\t{\"EPOLLET\", Const, 0, \"\"},\n\t\t{\"EPOLLHUP\", Const, 0, \"\"},\n\t\t{\"EPOLLIN\", Const, 0, \"\"},\n\t\t{\"EPOLLMSG\", Const, 0, \"\"},\n\t\t{\"EPOLLONESHOT\", Const, 0, \"\"},\n\t\t{\"EPOLLOUT\", Const, 0, \"\"},\n\t\t{\"EPOLLPRI\", Const, 0, \"\"},\n\t\t{\"EPOLLRDBAND\", Const, 0, \"\"},\n\t\t{\"EPOLLRDHUP\", Const, 0, \"\"},\n\t\t{\"EPOLLRDNORM\", Const, 0, \"\"},\n\t\t{\"EPOLLWRBAND\", Const, 0, \"\"},\n\t\t{\"EPOLLWRNORM\", Const, 0, \"\"},\n\t\t{\"EPOLL_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"EPOLL_CTL_ADD\", Const, 0, \"\"},\n\t\t{\"EPOLL_CTL_DEL\", Const, 0, \"\"},\n\t\t{\"EPOLL_CTL_MOD\", Const, 0, \"\"},\n\t\t{\"EPOLL_NONBLOCK\", Const, 0, \"\"},\n\t\t{\"EPROCLIM\", Const, 0, \"\"},\n\t\t{\"EPROCUNAVAIL\", Const, 0, \"\"},\n\t\t{\"EPROGMISMATCH\", Const, 0, \"\"},\n\t\t{\"EPROGUNAVAIL\", Const, 0, \"\"},\n\t\t{\"EPROTO\", Const, 0, \"\"},\n\t\t{\"EPROTONOSUPPORT\", Const, 0, \"\"},\n\t\t{\"EPROTOTYPE\", Const, 0, \"\"},\n\t\t{\"EPWROFF\", Const, 0, \"\"},\n\t\t{\"EQFULL\", Const, 16, \"\"},\n\t\t{\"ERANGE\", Const, 0, \"\"},\n\t\t{\"EREMCHG\", Const, 0, \"\"},\n\t\t{\"EREMOTE\", Const, 0, \"\"},\n\t\t{\"EREMOTEIO\", Const, 0, \"\"},\n\t\t{\"ERESTART\", Const, 0, \"\"},\n\t\t{\"ERFKILL\", Const, 0, \"\"},\n\t\t{\"EROFS\", Const, 0, \"\"},\n\t\t{\"ERPCMISMATCH\", Const, 0, \"\"},\n\t\t{\"ERROR_ACCESS_DENIED\", Const, 0, \"\"},\n\t\t{\"ERROR_ALREADY_EXISTS\", Const, 0, \"\"},\n\t\t{\"ERROR_BROKEN_PIPE\", Const, 0, \"\"},\n\t\t{\"ERROR_BUFFER_OVERFLOW\", Const, 0, \"\"},\n\t\t{\"ERROR_DIR_NOT_EMPTY\", Const, 8, \"\"},\n\t\t{\"ERROR_ENVVAR_NOT_FOUND\", Const, 0, \"\"},\n\t\t{\"ERROR_FILE_EXISTS\", Const, 0, \"\"},\n\t\t{\"ERROR_FILE_NOT_FOUND\", Const, 0, \"\"},\n\t\t{\"ERROR_HANDLE_EOF\", Const, 2, \"\"},\n\t\t{\"ERROR_INSUFFICIENT_BUFFER\", Const, 0, \"\"},\n\t\t{\"ERROR_IO_PENDING\", Const, 0, \"\"},\n\t\t{\"ERROR_MOD_NOT_FOUND\", Const, 0, \"\"},\n\t\t{\"ERROR_MORE_DATA\", Const, 3, \"\"},\n\t\t{\"ERROR_NETNAME_DELETED\", Const, 3, \"\"},\n\t\t{\"ERROR_NOT_FOUND\", Const, 1, \"\"},\n\t\t{\"ERROR_NO_MORE_FILES\", Const, 0, \"\"},\n\t\t{\"ERROR_OPERATION_ABORTED\", Const, 0, \"\"},\n\t\t{\"ERROR_PATH_NOT_FOUND\", Const, 0, \"\"},\n\t\t{\"ERROR_PRIVILEGE_NOT_HELD\", Const, 4, \"\"},\n\t\t{\"ERROR_PROC_NOT_FOUND\", Const, 0, \"\"},\n\t\t{\"ESHLIBVERS\", Const, 0, \"\"},\n\t\t{\"ESHUTDOWN\", Const, 0, \"\"},\n\t\t{\"ESOCKTNOSUPPORT\", Const, 0, \"\"},\n\t\t{\"ESPIPE\", Const, 0, \"\"},\n\t\t{\"ESRCH\", Const, 0, \"\"},\n\t\t{\"ESRMNT\", Const, 0, \"\"},\n\t\t{\"ESTALE\", Const, 0, \"\"},\n\t\t{\"ESTRPIPE\", Const, 0, \"\"},\n\t\t{\"ETHERCAP_JUMBO_MTU\", Const, 1, \"\"},\n\t\t{\"ETHERCAP_VLAN_HWTAGGING\", Const, 1, \"\"},\n\t\t{\"ETHERCAP_VLAN_MTU\", Const, 1, \"\"},\n\t\t{\"ETHERMIN\", Const, 1, \"\"},\n\t\t{\"ETHERMTU\", Const, 1, \"\"},\n\t\t{\"ETHERMTU_JUMBO\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_8023\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AARP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ACCTON\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AEONIC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ALPHA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AMBER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AMOEBA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AOE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_APOLLO\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_APOLLODOMAIN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_APPLETALK\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_APPLITEK\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ARGONAUT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ARP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ATALK\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ATOMIC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ATT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ATTSTANFORD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AUTOPHON\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_AXIS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_BCLOOP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_BOFL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_CABLETRON\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_CHAOS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_COMDESIGN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_COMPUGRAPHIC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_COUNTERPOINT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_CRONUS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_CRONUSVLN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DCA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DDE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DEBNI\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECAM\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECCUST\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECDIAG\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECDNS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECDTS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECEXPER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECLAST\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECLTM\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECMUMPS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DECNETBIOS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DELTACON\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DIDDLE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DLOG1\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DLOG2\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DOGFIGHT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_DSMD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ECMA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ENCRYPT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_ES\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_EXCELAN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_EXPERDATA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_FLIP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_FLOWCONTROL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_FRARP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_GENDYN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_HAYES\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_HIPPI_FP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_HITACHI\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_HP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IEEEPUP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IEEEPUPAT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IMLBL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IMLBLDIAG\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IPAS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IPV6\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IPX\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_IPXNEW\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_KALPANA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LANBRIDGE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LANPROBE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LAT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LBACK\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LITTLE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LLDP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LOGICRAFT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_LOOPBACK\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MATRA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MAX\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MERIT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MICP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MOPDL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MOPRC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MOTOROLA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MPLS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MPLS_MCAST\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_MUMPS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCLAIM\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCLREQ\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCLRSP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCREQ\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPCRSP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPDG\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPDGB\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPDLTE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPRAR\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPRAS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPRST\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPSCD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBPVCD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NBS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NCD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NESTAR\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NETBEUI\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NOVELL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NSAT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NSCOMPAT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_NTRAILER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_OS9\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_OS9NET\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PACER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PAE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PCS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PLANNING\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PPP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PPPOE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PPPOEDISC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PRIMENTS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PUP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_PUPAT\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_QINQ\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RACAL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RATIONAL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RAWFR\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RCL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RDP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_RETIX\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_REVARP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SCA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SECTRA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SECUREDATA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SGITW\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SG_BOUNCE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SG_DIAG\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SG_NETGAMES\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SG_RESV\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SIMNET\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SLOW\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SLOWPROTOCOLS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SNA\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SNMP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SONIX\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SPIDER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_SPRITE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_STP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TALARIS\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TALARISMC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TCPCOMP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TCPSM\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TEC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TIGAN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TRAIL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TRANSETHER\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_TYMSHARE\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBBST\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBDEBUG\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBDIAGLOOP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBDL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBNIU\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_UBNMC\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VALID\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VARIAN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VAXELN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VEECO\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VEXP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VGLAB\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VINES\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VINESECHO\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VINESLOOP\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VITAL\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VLAN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VLTLMAN\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VPROD\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_VURESERVED\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_WATERLOO\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_WELLFLEET\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_X25\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_X75\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_XNSSM\", Const, 1, \"\"},\n\t\t{\"ETHERTYPE_XTP\", Const, 1, \"\"},\n\t\t{\"ETHER_ADDR_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_ALIGN\", Const, 1, \"\"},\n\t\t{\"ETHER_CRC_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_CRC_POLY_BE\", Const, 1, \"\"},\n\t\t{\"ETHER_CRC_POLY_LE\", Const, 1, \"\"},\n\t\t{\"ETHER_HDR_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_MAX_DIX_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_MAX_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_MAX_LEN_JUMBO\", Const, 1, \"\"},\n\t\t{\"ETHER_MIN_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_PPPOE_ENCAP_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_TYPE_LEN\", Const, 1, \"\"},\n\t\t{\"ETHER_VLAN_ENCAP_LEN\", Const, 1, \"\"},\n\t\t{\"ETH_P_1588\", Const, 0, \"\"},\n\t\t{\"ETH_P_8021Q\", Const, 0, \"\"},\n\t\t{\"ETH_P_802_2\", Const, 0, \"\"},\n\t\t{\"ETH_P_802_3\", Const, 0, \"\"},\n\t\t{\"ETH_P_AARP\", Const, 0, \"\"},\n\t\t{\"ETH_P_ALL\", Const, 0, \"\"},\n\t\t{\"ETH_P_AOE\", Const, 0, \"\"},\n\t\t{\"ETH_P_ARCNET\", Const, 0, \"\"},\n\t\t{\"ETH_P_ARP\", Const, 0, \"\"},\n\t\t{\"ETH_P_ATALK\", Const, 0, \"\"},\n\t\t{\"ETH_P_ATMFATE\", Const, 0, \"\"},\n\t\t{\"ETH_P_ATMMPOA\", Const, 0, \"\"},\n\t\t{\"ETH_P_AX25\", Const, 0, \"\"},\n\t\t{\"ETH_P_BPQ\", Const, 0, \"\"},\n\t\t{\"ETH_P_CAIF\", Const, 0, \"\"},\n\t\t{\"ETH_P_CAN\", Const, 0, \"\"},\n\t\t{\"ETH_P_CONTROL\", Const, 0, \"\"},\n\t\t{\"ETH_P_CUST\", Const, 0, \"\"},\n\t\t{\"ETH_P_DDCMP\", Const, 0, \"\"},\n\t\t{\"ETH_P_DEC\", Const, 0, \"\"},\n\t\t{\"ETH_P_DIAG\", Const, 0, \"\"},\n\t\t{\"ETH_P_DNA_DL\", Const, 0, \"\"},\n\t\t{\"ETH_P_DNA_RC\", Const, 0, \"\"},\n\t\t{\"ETH_P_DNA_RT\", Const, 0, \"\"},\n\t\t{\"ETH_P_DSA\", Const, 0, \"\"},\n\t\t{\"ETH_P_ECONET\", Const, 0, \"\"},\n\t\t{\"ETH_P_EDSA\", Const, 0, \"\"},\n\t\t{\"ETH_P_FCOE\", Const, 0, \"\"},\n\t\t{\"ETH_P_FIP\", Const, 0, \"\"},\n\t\t{\"ETH_P_HDLC\", Const, 0, \"\"},\n\t\t{\"ETH_P_IEEE802154\", Const, 0, \"\"},\n\t\t{\"ETH_P_IEEEPUP\", Const, 0, \"\"},\n\t\t{\"ETH_P_IEEEPUPAT\", Const, 0, \"\"},\n\t\t{\"ETH_P_IP\", Const, 0, \"\"},\n\t\t{\"ETH_P_IPV6\", Const, 0, \"\"},\n\t\t{\"ETH_P_IPX\", Const, 0, \"\"},\n\t\t{\"ETH_P_IRDA\", Const, 0, \"\"},\n\t\t{\"ETH_P_LAT\", Const, 0, \"\"},\n\t\t{\"ETH_P_LINK_CTL\", Const, 0, \"\"},\n\t\t{\"ETH_P_LOCALTALK\", Const, 0, \"\"},\n\t\t{\"ETH_P_LOOP\", Const, 0, \"\"},\n\t\t{\"ETH_P_MOBITEX\", Const, 0, \"\"},\n\t\t{\"ETH_P_MPLS_MC\", Const, 0, \"\"},\n\t\t{\"ETH_P_MPLS_UC\", Const, 0, \"\"},\n\t\t{\"ETH_P_PAE\", Const, 0, \"\"},\n\t\t{\"ETH_P_PAUSE\", Const, 0, \"\"},\n\t\t{\"ETH_P_PHONET\", Const, 0, \"\"},\n\t\t{\"ETH_P_PPPTALK\", Const, 0, \"\"},\n\t\t{\"ETH_P_PPP_DISC\", Const, 0, \"\"},\n\t\t{\"ETH_P_PPP_MP\", Const, 0, \"\"},\n\t\t{\"ETH_P_PPP_SES\", Const, 0, \"\"},\n\t\t{\"ETH_P_PUP\", Const, 0, \"\"},\n\t\t{\"ETH_P_PUPAT\", Const, 0, \"\"},\n\t\t{\"ETH_P_RARP\", Const, 0, \"\"},\n\t\t{\"ETH_P_SCA\", Const, 0, \"\"},\n\t\t{\"ETH_P_SLOW\", Const, 0, \"\"},\n\t\t{\"ETH_P_SNAP\", Const, 0, \"\"},\n\t\t{\"ETH_P_TEB\", Const, 0, \"\"},\n\t\t{\"ETH_P_TIPC\", Const, 0, \"\"},\n\t\t{\"ETH_P_TRAILER\", Const, 0, \"\"},\n\t\t{\"ETH_P_TR_802_2\", Const, 0, \"\"},\n\t\t{\"ETH_P_WAN_PPP\", Const, 0, \"\"},\n\t\t{\"ETH_P_WCCP\", Const, 0, \"\"},\n\t\t{\"ETH_P_X25\", Const, 0, \"\"},\n\t\t{\"ETIME\", Const, 0, \"\"},\n\t\t{\"ETIMEDOUT\", Const, 0, \"\"},\n\t\t{\"ETOOMANYREFS\", Const, 0, \"\"},\n\t\t{\"ETXTBSY\", Const, 0, \"\"},\n\t\t{\"EUCLEAN\", Const, 0, \"\"},\n\t\t{\"EUNATCH\", Const, 0, \"\"},\n\t\t{\"EUSERS\", Const, 0, \"\"},\n\t\t{\"EVFILT_AIO\", Const, 0, \"\"},\n\t\t{\"EVFILT_FS\", Const, 0, \"\"},\n\t\t{\"EVFILT_LIO\", Const, 0, \"\"},\n\t\t{\"EVFILT_MACHPORT\", Const, 0, \"\"},\n\t\t{\"EVFILT_PROC\", Const, 0, \"\"},\n\t\t{\"EVFILT_READ\", Const, 0, \"\"},\n\t\t{\"EVFILT_SIGNAL\", Const, 0, \"\"},\n\t\t{\"EVFILT_SYSCOUNT\", Const, 0, \"\"},\n\t\t{\"EVFILT_THREADMARKER\", Const, 0, \"\"},\n\t\t{\"EVFILT_TIMER\", Const, 0, \"\"},\n\t\t{\"EVFILT_USER\", Const, 0, \"\"},\n\t\t{\"EVFILT_VM\", Const, 0, \"\"},\n\t\t{\"EVFILT_VNODE\", Const, 0, \"\"},\n\t\t{\"EVFILT_WRITE\", Const, 0, \"\"},\n\t\t{\"EV_ADD\", Const, 0, \"\"},\n\t\t{\"EV_CLEAR\", Const, 0, \"\"},\n\t\t{\"EV_DELETE\", Const, 0, \"\"},\n\t\t{\"EV_DISABLE\", Const, 0, \"\"},\n\t\t{\"EV_DISPATCH\", Const, 0, \"\"},\n\t\t{\"EV_DROP\", Const, 3, \"\"},\n\t\t{\"EV_ENABLE\", Const, 0, \"\"},\n\t\t{\"EV_EOF\", Const, 0, \"\"},\n\t\t{\"EV_ERROR\", Const, 0, \"\"},\n\t\t{\"EV_FLAG0\", Const, 0, \"\"},\n\t\t{\"EV_FLAG1\", Const, 0, \"\"},\n\t\t{\"EV_ONESHOT\", Const, 0, \"\"},\n\t\t{\"EV_OOBAND\", Const, 0, \"\"},\n\t\t{\"EV_POLL\", Const, 0, \"\"},\n\t\t{\"EV_RECEIPT\", Const, 0, \"\"},\n\t\t{\"EV_SYSFLAGS\", Const, 0, \"\"},\n\t\t{\"EWINDOWS\", Const, 0, \"\"},\n\t\t{\"EWOULDBLOCK\", Const, 0, \"\"},\n\t\t{\"EXDEV\", Const, 0, \"\"},\n\t\t{\"EXFULL\", Const, 0, \"\"},\n\t\t{\"EXTA\", Const, 0, \"\"},\n\t\t{\"EXTB\", Const, 0, \"\"},\n\t\t{\"EXTPROC\", Const, 0, \"\"},\n\t\t{\"Environ\", Func, 0, \"func() []string\"},\n\t\t{\"EpollCreate\", Func, 0, \"func(size int) (fd int, err error)\"},\n\t\t{\"EpollCreate1\", Func, 0, \"func(flag int) (fd int, err error)\"},\n\t\t{\"EpollCtl\", Func, 0, \"func(epfd int, op int, fd int, event *EpollEvent) (err error)\"},\n\t\t{\"EpollEvent\", Type, 0, \"\"},\n\t\t{\"EpollEvent.Events\", Field, 0, \"\"},\n\t\t{\"EpollEvent.Fd\", Field, 0, \"\"},\n\t\t{\"EpollEvent.Pad\", Field, 0, \"\"},\n\t\t{\"EpollEvent.PadFd\", Field, 0, \"\"},\n\t\t{\"EpollWait\", Func, 0, \"func(epfd int, events []EpollEvent, msec int) (n int, err error)\"},\n\t\t{\"Errno\", Type, 0, \"\"},\n\t\t{\"EscapeArg\", Func, 0, \"\"},\n\t\t{\"Exchangedata\", Func, 0, \"\"},\n\t\t{\"Exec\", Func, 0, \"func(argv0 string, argv []string, envv []string) (err error)\"},\n\t\t{\"Exit\", Func, 0, \"func(code int)\"},\n\t\t{\"ExitProcess\", Func, 0, \"\"},\n\t\t{\"FD_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"FD_SETSIZE\", Const, 0, \"\"},\n\t\t{\"FILE_ACTION_ADDED\", Const, 0, \"\"},\n\t\t{\"FILE_ACTION_MODIFIED\", Const, 0, \"\"},\n\t\t{\"FILE_ACTION_REMOVED\", Const, 0, \"\"},\n\t\t{\"FILE_ACTION_RENAMED_NEW_NAME\", Const, 0, \"\"},\n\t\t{\"FILE_ACTION_RENAMED_OLD_NAME\", Const, 0, \"\"},\n\t\t{\"FILE_APPEND_DATA\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_ARCHIVE\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_DIRECTORY\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_HIDDEN\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_NORMAL\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_READONLY\", Const, 0, \"\"},\n\t\t{\"FILE_ATTRIBUTE_REPARSE_POINT\", Const, 4, \"\"},\n\t\t{\"FILE_ATTRIBUTE_SYSTEM\", Const, 0, \"\"},\n\t\t{\"FILE_BEGIN\", Const, 0, \"\"},\n\t\t{\"FILE_CURRENT\", Const, 0, \"\"},\n\t\t{\"FILE_END\", Const, 0, \"\"},\n\t\t{\"FILE_FLAG_BACKUP_SEMANTICS\", Const, 0, \"\"},\n\t\t{\"FILE_FLAG_OPEN_REPARSE_POINT\", Const, 4, \"\"},\n\t\t{\"FILE_FLAG_OVERLAPPED\", Const, 0, \"\"},\n\t\t{\"FILE_LIST_DIRECTORY\", Const, 0, \"\"},\n\t\t{\"FILE_MAP_COPY\", Const, 0, \"\"},\n\t\t{\"FILE_MAP_EXECUTE\", Const, 0, \"\"},\n\t\t{\"FILE_MAP_READ\", Const, 0, \"\"},\n\t\t{\"FILE_MAP_WRITE\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_ATTRIBUTES\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_CREATION\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_DIR_NAME\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_FILE_NAME\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_LAST_ACCESS\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_LAST_WRITE\", Const, 0, \"\"},\n\t\t{\"FILE_NOTIFY_CHANGE_SIZE\", Const, 0, \"\"},\n\t\t{\"FILE_SHARE_DELETE\", Const, 0, \"\"},\n\t\t{\"FILE_SHARE_READ\", Const, 0, \"\"},\n\t\t{\"FILE_SHARE_WRITE\", Const, 0, \"\"},\n\t\t{\"FILE_SKIP_COMPLETION_PORT_ON_SUCCESS\", Const, 2, \"\"},\n\t\t{\"FILE_SKIP_SET_EVENT_ON_HANDLE\", Const, 2, \"\"},\n\t\t{\"FILE_TYPE_CHAR\", Const, 0, \"\"},\n\t\t{\"FILE_TYPE_DISK\", Const, 0, \"\"},\n\t\t{\"FILE_TYPE_PIPE\", Const, 0, \"\"},\n\t\t{\"FILE_TYPE_REMOTE\", Const, 0, \"\"},\n\t\t{\"FILE_TYPE_UNKNOWN\", Const, 0, \"\"},\n\t\t{\"FILE_WRITE_ATTRIBUTES\", Const, 0, \"\"},\n\t\t{\"FLUSHO\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_ALLOCATE_BUFFER\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_ARGUMENT_ARRAY\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_FROM_HMODULE\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_FROM_STRING\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_FROM_SYSTEM\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_IGNORE_INSERTS\", Const, 0, \"\"},\n\t\t{\"FORMAT_MESSAGE_MAX_WIDTH_MASK\", Const, 0, \"\"},\n\t\t{\"FSCTL_GET_REPARSE_POINT\", Const, 4, \"\"},\n\t\t{\"F_ADDFILESIGS\", Const, 0, \"\"},\n\t\t{\"F_ADDSIGS\", Const, 0, \"\"},\n\t\t{\"F_ALLOCATEALL\", Const, 0, \"\"},\n\t\t{\"F_ALLOCATECONTIG\", Const, 0, \"\"},\n\t\t{\"F_CANCEL\", Const, 0, \"\"},\n\t\t{\"F_CHKCLEAN\", Const, 0, \"\"},\n\t\t{\"F_CLOSEM\", Const, 1, \"\"},\n\t\t{\"F_DUP2FD\", Const, 0, \"\"},\n\t\t{\"F_DUP2FD_CLOEXEC\", Const, 1, \"\"},\n\t\t{\"F_DUPFD\", Const, 0, \"\"},\n\t\t{\"F_DUPFD_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"F_EXLCK\", Const, 0, \"\"},\n\t\t{\"F_FINDSIGS\", Const, 16, \"\"},\n\t\t{\"F_FLUSH_DATA\", Const, 0, \"\"},\n\t\t{\"F_FREEZE_FS\", Const, 0, \"\"},\n\t\t{\"F_FSCTL\", Const, 1, \"\"},\n\t\t{\"F_FSDIRMASK\", Const, 1, \"\"},\n\t\t{\"F_FSIN\", Const, 1, \"\"},\n\t\t{\"F_FSINOUT\", Const, 1, \"\"},\n\t\t{\"F_FSOUT\", Const, 1, \"\"},\n\t\t{\"F_FSPRIV\", Const, 1, \"\"},\n\t\t{\"F_FSVOID\", Const, 1, \"\"},\n\t\t{\"F_FULLFSYNC\", Const, 0, \"\"},\n\t\t{\"F_GETCODEDIR\", Const, 16, \"\"},\n\t\t{\"F_GETFD\", Const, 0, \"\"},\n\t\t{\"F_GETFL\", Const, 0, \"\"},\n\t\t{\"F_GETLEASE\", Const, 0, \"\"},\n\t\t{\"F_GETLK\", Const, 0, \"\"},\n\t\t{\"F_GETLK64\", Const, 0, \"\"},\n\t\t{\"F_GETLKPID\", Const, 0, \"\"},\n\t\t{\"F_GETNOSIGPIPE\", Const, 0, \"\"},\n\t\t{\"F_GETOWN\", Const, 0, \"\"},\n\t\t{\"F_GETOWN_EX\", Const, 0, \"\"},\n\t\t{\"F_GETPATH\", Const, 0, \"\"},\n\t\t{\"F_GETPATH_MTMINFO\", Const, 0, \"\"},\n\t\t{\"F_GETPIPE_SZ\", Const, 0, \"\"},\n\t\t{\"F_GETPROTECTIONCLASS\", Const, 0, \"\"},\n\t\t{\"F_GETPROTECTIONLEVEL\", Const, 16, \"\"},\n\t\t{\"F_GETSIG\", Const, 0, \"\"},\n\t\t{\"F_GLOBAL_NOCACHE\", Const, 0, \"\"},\n\t\t{\"F_LOCK\", Const, 0, \"\"},\n\t\t{\"F_LOG2PHYS\", Const, 0, \"\"},\n\t\t{\"F_LOG2PHYS_EXT\", Const, 0, \"\"},\n\t\t{\"F_MARKDEPENDENCY\", Const, 0, \"\"},\n\t\t{\"F_MAXFD\", Const, 1, \"\"},\n\t\t{\"F_NOCACHE\", Const, 0, \"\"},\n\t\t{\"F_NODIRECT\", Const, 0, \"\"},\n\t\t{\"F_NOTIFY\", Const, 0, \"\"},\n\t\t{\"F_OGETLK\", Const, 0, \"\"},\n\t\t{\"F_OK\", Const, 0, \"\"},\n\t\t{\"F_OSETLK\", Const, 0, \"\"},\n\t\t{\"F_OSETLKW\", Const, 0, \"\"},\n\t\t{\"F_PARAM_MASK\", Const, 1, \"\"},\n\t\t{\"F_PARAM_MAX\", Const, 1, \"\"},\n\t\t{\"F_PATHPKG_CHECK\", Const, 0, \"\"},\n\t\t{\"F_PEOFPOSMODE\", Const, 0, \"\"},\n\t\t{\"F_PREALLOCATE\", Const, 0, \"\"},\n\t\t{\"F_RDADVISE\", Const, 0, \"\"},\n\t\t{\"F_RDAHEAD\", Const, 0, \"\"},\n\t\t{\"F_RDLCK\", Const, 0, \"\"},\n\t\t{\"F_READAHEAD\", Const, 0, \"\"},\n\t\t{\"F_READBOOTSTRAP\", Const, 0, \"\"},\n\t\t{\"F_SETBACKINGSTORE\", Const, 0, \"\"},\n\t\t{\"F_SETFD\", Const, 0, \"\"},\n\t\t{\"F_SETFL\", Const, 0, \"\"},\n\t\t{\"F_SETLEASE\", Const, 0, \"\"},\n\t\t{\"F_SETLK\", Const, 0, \"\"},\n\t\t{\"F_SETLK64\", Const, 0, \"\"},\n\t\t{\"F_SETLKW\", Const, 0, \"\"},\n\t\t{\"F_SETLKW64\", Const, 0, \"\"},\n\t\t{\"F_SETLKWTIMEOUT\", Const, 16, \"\"},\n\t\t{\"F_SETLK_REMOTE\", Const, 0, \"\"},\n\t\t{\"F_SETNOSIGPIPE\", Const, 0, \"\"},\n\t\t{\"F_SETOWN\", Const, 0, \"\"},\n\t\t{\"F_SETOWN_EX\", Const, 0, \"\"},\n\t\t{\"F_SETPIPE_SZ\", Const, 0, \"\"},\n\t\t{\"F_SETPROTECTIONCLASS\", Const, 0, \"\"},\n\t\t{\"F_SETSIG\", Const, 0, \"\"},\n\t\t{\"F_SETSIZE\", Const, 0, \"\"},\n\t\t{\"F_SHLCK\", Const, 0, \"\"},\n\t\t{\"F_SINGLE_WRITER\", Const, 16, \"\"},\n\t\t{\"F_TEST\", Const, 0, \"\"},\n\t\t{\"F_THAW_FS\", Const, 0, \"\"},\n\t\t{\"F_TLOCK\", Const, 0, \"\"},\n\t\t{\"F_TRANSCODEKEY\", Const, 16, \"\"},\n\t\t{\"F_ULOCK\", Const, 0, \"\"},\n\t\t{\"F_UNLCK\", Const, 0, \"\"},\n\t\t{\"F_UNLCKSYS\", Const, 0, \"\"},\n\t\t{\"F_VOLPOSMODE\", Const, 0, \"\"},\n\t\t{\"F_WRITEBOOTSTRAP\", Const, 0, \"\"},\n\t\t{\"F_WRLCK\", Const, 0, \"\"},\n\t\t{\"Faccessat\", Func, 0, \"func(dirfd int, path string, mode uint32, flags int) (err error)\"},\n\t\t{\"Fallocate\", Func, 0, \"func(fd int, mode uint32, off int64, len int64) (err error)\"},\n\t\t{\"Fbootstraptransfer_t\", Type, 0, \"\"},\n\t\t{\"Fbootstraptransfer_t.Buffer\", Field, 0, \"\"},\n\t\t{\"Fbootstraptransfer_t.Length\", Field, 0, \"\"},\n\t\t{\"Fbootstraptransfer_t.Offset\", Field, 0, \"\"},\n\t\t{\"Fchdir\", Func, 0, \"func(fd int) (err error)\"},\n\t\t{\"Fchflags\", Func, 0, \"\"},\n\t\t{\"Fchmod\", Func, 0, \"func(fd int, mode uint32) (err error)\"},\n\t\t{\"Fchmodat\", Func, 0, \"func(dirfd int, path string, mode uint32, flags int) error\"},\n\t\t{\"Fchown\", Func, 0, \"func(fd int, uid int, gid int) (err error)\"},\n\t\t{\"Fchownat\", Func, 0, \"func(dirfd int, path string, uid int, gid int, flags int) (err error)\"},\n\t\t{\"FcntlFlock\", Func, 3, \"func(fd uintptr, cmd int, lk *Flock_t) error\"},\n\t\t{\"FdSet\", Type, 0, \"\"},\n\t\t{\"FdSet.Bits\", Field, 0, \"\"},\n\t\t{\"FdSet.X__fds_bits\", Field, 0, \"\"},\n\t\t{\"Fdatasync\", Func, 0, \"func(fd int) (err error)\"},\n\t\t{\"FileNotifyInformation\", Type, 0, \"\"},\n\t\t{\"FileNotifyInformation.Action\", Field, 0, \"\"},\n\t\t{\"FileNotifyInformation.FileName\", Field, 0, \"\"},\n\t\t{\"FileNotifyInformation.FileNameLength\", Field, 0, \"\"},\n\t\t{\"FileNotifyInformation.NextEntryOffset\", Field, 0, \"\"},\n\t\t{\"Filetime\", Type, 0, \"\"},\n\t\t{\"Filetime.HighDateTime\", Field, 0, \"\"},\n\t\t{\"Filetime.LowDateTime\", Field, 0, \"\"},\n\t\t{\"FindClose\", Func, 0, \"\"},\n\t\t{\"FindFirstFile\", Func, 0, \"\"},\n\t\t{\"FindNextFile\", Func, 0, \"\"},\n\t\t{\"Flock\", Func, 0, \"func(fd int, how int) (err error)\"},\n\t\t{\"Flock_t\", Type, 0, \"\"},\n\t\t{\"Flock_t.Len\", Field, 0, \"\"},\n\t\t{\"Flock_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Flock_t.Pad_cgo_1\", Field, 3, \"\"},\n\t\t{\"Flock_t.Pid\", Field, 0, \"\"},\n\t\t{\"Flock_t.Start\", Field, 0, \"\"},\n\t\t{\"Flock_t.Sysid\", Field, 0, \"\"},\n\t\t{\"Flock_t.Type\", Field, 0, \"\"},\n\t\t{\"Flock_t.Whence\", Field, 0, \"\"},\n\t\t{\"FlushBpf\", Func, 0, \"\"},\n\t\t{\"FlushFileBuffers\", Func, 0, \"\"},\n\t\t{\"FlushViewOfFile\", Func, 0, \"\"},\n\t\t{\"ForkExec\", Func, 0, \"func(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)\"},\n\t\t{\"ForkLock\", Var, 0, \"\"},\n\t\t{\"FormatMessage\", Func, 0, \"\"},\n\t\t{\"Fpathconf\", Func, 0, \"\"},\n\t\t{\"FreeAddrInfoW\", Func, 1, \"\"},\n\t\t{\"FreeEnvironmentStrings\", Func, 0, \"\"},\n\t\t{\"FreeLibrary\", Func, 0, \"\"},\n\t\t{\"Fsid\", Type, 0, \"\"},\n\t\t{\"Fsid.Val\", Field, 0, \"\"},\n\t\t{\"Fsid.X__fsid_val\", Field, 2, \"\"},\n\t\t{\"Fsid.X__val\", Field, 0, \"\"},\n\t\t{\"Fstat\", Func, 0, \"func(fd int, stat *Stat_t) (err error)\"},\n\t\t{\"Fstatat\", Func, 12, \"\"},\n\t\t{\"Fstatfs\", Func, 0, \"func(fd int, buf *Statfs_t) (err error)\"},\n\t\t{\"Fstore_t\", Type, 0, \"\"},\n\t\t{\"Fstore_t.Bytesalloc\", Field, 0, \"\"},\n\t\t{\"Fstore_t.Flags\", Field, 0, \"\"},\n\t\t{\"Fstore_t.Length\", Field, 0, \"\"},\n\t\t{\"Fstore_t.Offset\", Field, 0, \"\"},\n\t\t{\"Fstore_t.Posmode\", Field, 0, \"\"},\n\t\t{\"Fsync\", Func, 0, \"func(fd int) (err error)\"},\n\t\t{\"Ftruncate\", Func, 0, \"func(fd int, length int64) (err error)\"},\n\t\t{\"FullPath\", Func, 4, \"\"},\n\t\t{\"Futimes\", Func, 0, \"func(fd int, tv []Timeval) (err error)\"},\n\t\t{\"Futimesat\", Func, 0, \"func(dirfd int, path string, tv []Timeval) (err error)\"},\n\t\t{\"GENERIC_ALL\", Const, 0, \"\"},\n\t\t{\"GENERIC_EXECUTE\", Const, 0, \"\"},\n\t\t{\"GENERIC_READ\", Const, 0, \"\"},\n\t\t{\"GENERIC_WRITE\", Const, 0, \"\"},\n\t\t{\"GUID\", Type, 1, \"\"},\n\t\t{\"GUID.Data1\", Field, 1, \"\"},\n\t\t{\"GUID.Data2\", Field, 1, \"\"},\n\t\t{\"GUID.Data3\", Field, 1, \"\"},\n\t\t{\"GUID.Data4\", Field, 1, \"\"},\n\t\t{\"GetAcceptExSockaddrs\", Func, 0, \"\"},\n\t\t{\"GetAdaptersInfo\", Func, 0, \"\"},\n\t\t{\"GetAddrInfoW\", Func, 1, \"\"},\n\t\t{\"GetCommandLine\", Func, 0, \"\"},\n\t\t{\"GetComputerName\", Func, 0, \"\"},\n\t\t{\"GetConsoleMode\", Func, 1, \"\"},\n\t\t{\"GetCurrentDirectory\", Func, 0, \"\"},\n\t\t{\"GetCurrentProcess\", Func, 0, \"\"},\n\t\t{\"GetEnvironmentStrings\", Func, 0, \"\"},\n\t\t{\"GetEnvironmentVariable\", Func, 0, \"\"},\n\t\t{\"GetExitCodeProcess\", Func, 0, \"\"},\n\t\t{\"GetFileAttributes\", Func, 0, \"\"},\n\t\t{\"GetFileAttributesEx\", Func, 0, \"\"},\n\t\t{\"GetFileExInfoStandard\", Const, 0, \"\"},\n\t\t{\"GetFileExMaxInfoLevel\", Const, 0, \"\"},\n\t\t{\"GetFileInformationByHandle\", Func, 0, \"\"},\n\t\t{\"GetFileType\", Func, 0, \"\"},\n\t\t{\"GetFullPathName\", Func, 0, \"\"},\n\t\t{\"GetHostByName\", Func, 0, \"\"},\n\t\t{\"GetIfEntry\", Func, 0, \"\"},\n\t\t{\"GetLastError\", Func, 0, \"\"},\n\t\t{\"GetLengthSid\", Func, 0, \"\"},\n\t\t{\"GetLongPathName\", Func, 0, \"\"},\n\t\t{\"GetProcAddress\", Func, 0, \"\"},\n\t\t{\"GetProcessTimes\", Func, 0, \"\"},\n\t\t{\"GetProtoByName\", Func, 0, \"\"},\n\t\t{\"GetQueuedCompletionStatus\", Func, 0, \"\"},\n\t\t{\"GetServByName\", Func, 0, \"\"},\n\t\t{\"GetShortPathName\", Func, 0, \"\"},\n\t\t{\"GetStartupInfo\", Func, 0, \"\"},\n\t\t{\"GetStdHandle\", Func, 0, \"\"},\n\t\t{\"GetSystemTimeAsFileTime\", Func, 0, \"\"},\n\t\t{\"GetTempPath\", Func, 0, \"\"},\n\t\t{\"GetTimeZoneInformation\", Func, 0, \"\"},\n\t\t{\"GetTokenInformation\", Func, 0, \"\"},\n\t\t{\"GetUserNameEx\", Func, 0, \"\"},\n\t\t{\"GetUserProfileDirectory\", Func, 0, \"\"},\n\t\t{\"GetVersion\", Func, 0, \"\"},\n\t\t{\"Getcwd\", Func, 0, \"func(buf []byte) (n int, err error)\"},\n\t\t{\"Getdents\", Func, 0, \"func(fd int, buf []byte) (n int, err error)\"},\n\t\t{\"Getdirentries\", Func, 0, \"\"},\n\t\t{\"Getdtablesize\", Func, 0, \"\"},\n\t\t{\"Getegid\", Func, 0, \"func() (egid int)\"},\n\t\t{\"Getenv\", Func, 0, \"func(key string) (value string, found bool)\"},\n\t\t{\"Geteuid\", Func, 0, \"func() (euid int)\"},\n\t\t{\"Getfsstat\", Func, 0, \"\"},\n\t\t{\"Getgid\", Func, 0, \"func() (gid int)\"},\n\t\t{\"Getgroups\", Func, 0, \"func() (gids []int, err error)\"},\n\t\t{\"Getpagesize\", Func, 0, \"func() int\"},\n\t\t{\"Getpeername\", Func, 0, \"func(fd int) (sa Sockaddr, err error)\"},\n\t\t{\"Getpgid\", Func, 0, \"func(pid int) (pgid int, err error)\"},\n\t\t{\"Getpgrp\", Func, 0, \"func() (pid int)\"},\n\t\t{\"Getpid\", Func, 0, \"func() (pid int)\"},\n\t\t{\"Getppid\", Func, 0, \"func() (ppid int)\"},\n\t\t{\"Getpriority\", Func, 0, \"func(which int, who int) (prio int, err error)\"},\n\t\t{\"Getrlimit\", Func, 0, \"func(resource int, rlim *Rlimit) (err error)\"},\n\t\t{\"Getrusage\", Func, 0, \"func(who int, rusage *Rusage) (err error)\"},\n\t\t{\"Getsid\", Func, 0, \"\"},\n\t\t{\"Getsockname\", Func, 0, \"func(fd int) (sa Sockaddr, err error)\"},\n\t\t{\"Getsockopt\", Func, 1, \"\"},\n\t\t{\"GetsockoptByte\", Func, 0, \"\"},\n\t\t{\"GetsockoptICMPv6Filter\", Func, 2, \"func(fd int, level int, opt int) (*ICMPv6Filter, error)\"},\n\t\t{\"GetsockoptIPMreq\", Func, 0, \"func(fd int, level int, opt int) (*IPMreq, error)\"},\n\t\t{\"GetsockoptIPMreqn\", Func, 0, \"func(fd int, level int, opt int) (*IPMreqn, error)\"},\n\t\t{\"GetsockoptIPv6MTUInfo\", Func, 2, \"func(fd int, level int, opt int) (*IPv6MTUInfo, error)\"},\n\t\t{\"GetsockoptIPv6Mreq\", Func, 0, \"func(fd int, level int, opt int) (*IPv6Mreq, error)\"},\n\t\t{\"GetsockoptInet4Addr\", Func, 0, \"func(fd int, level int, opt int) (value [4]byte, err error)\"},\n\t\t{\"GetsockoptInt\", Func, 0, \"func(fd int, level int, opt int) (value int, err error)\"},\n\t\t{\"GetsockoptUcred\", Func, 1, \"func(fd int, level int, opt int) (*Ucred, error)\"},\n\t\t{\"Gettid\", Func, 0, \"func() (tid int)\"},\n\t\t{\"Gettimeofday\", Func, 0, \"func(tv *Timeval) (err error)\"},\n\t\t{\"Getuid\", Func, 0, \"func() (uid int)\"},\n\t\t{\"Getwd\", Func, 0, \"func() (wd string, err error)\"},\n\t\t{\"Getxattr\", Func, 1, \"func(path string, attr string, dest []byte) (sz int, err error)\"},\n\t\t{\"HANDLE_FLAG_INHERIT\", Const, 0, \"\"},\n\t\t{\"HKEY_CLASSES_ROOT\", Const, 0, \"\"},\n\t\t{\"HKEY_CURRENT_CONFIG\", Const, 0, \"\"},\n\t\t{\"HKEY_CURRENT_USER\", Const, 0, \"\"},\n\t\t{\"HKEY_DYN_DATA\", Const, 0, \"\"},\n\t\t{\"HKEY_LOCAL_MACHINE\", Const, 0, \"\"},\n\t\t{\"HKEY_PERFORMANCE_DATA\", Const, 0, \"\"},\n\t\t{\"HKEY_USERS\", Const, 0, \"\"},\n\t\t{\"HUPCL\", Const, 0, \"\"},\n\t\t{\"Handle\", Type, 0, \"\"},\n\t\t{\"Hostent\", Type, 0, \"\"},\n\t\t{\"Hostent.AddrList\", Field, 0, \"\"},\n\t\t{\"Hostent.AddrType\", Field, 0, \"\"},\n\t\t{\"Hostent.Aliases\", Field, 0, \"\"},\n\t\t{\"Hostent.Length\", Field, 0, \"\"},\n\t\t{\"Hostent.Name\", Field, 0, \"\"},\n\t\t{\"ICANON\", Const, 0, \"\"},\n\t\t{\"ICMP6_FILTER\", Const, 2, \"\"},\n\t\t{\"ICMPV6_FILTER\", Const, 2, \"\"},\n\t\t{\"ICMPv6Filter\", Type, 2, \"\"},\n\t\t{\"ICMPv6Filter.Data\", Field, 2, \"\"},\n\t\t{\"ICMPv6Filter.Filt\", Field, 2, \"\"},\n\t\t{\"ICRNL\", Const, 0, \"\"},\n\t\t{\"IEXTEN\", Const, 0, \"\"},\n\t\t{\"IFAN_ARRIVAL\", Const, 1, \"\"},\n\t\t{\"IFAN_DEPARTURE\", Const, 1, \"\"},\n\t\t{\"IFA_ADDRESS\", Const, 0, \"\"},\n\t\t{\"IFA_ANYCAST\", Const, 0, \"\"},\n\t\t{\"IFA_BROADCAST\", Const, 0, \"\"},\n\t\t{\"IFA_CACHEINFO\", Const, 0, \"\"},\n\t\t{\"IFA_F_DADFAILED\", Const, 0, \"\"},\n\t\t{\"IFA_F_DEPRECATED\", Const, 0, \"\"},\n\t\t{\"IFA_F_HOMEADDRESS\", Const, 0, \"\"},\n\t\t{\"IFA_F_NODAD\", Const, 0, \"\"},\n\t\t{\"IFA_F_OPTIMISTIC\", Const, 0, \"\"},\n\t\t{\"IFA_F_PERMANENT\", Const, 0, \"\"},\n\t\t{\"IFA_F_SECONDARY\", Const, 0, \"\"},\n\t\t{\"IFA_F_TEMPORARY\", Const, 0, \"\"},\n\t\t{\"IFA_F_TENTATIVE\", Const, 0, \"\"},\n\t\t{\"IFA_LABEL\", Const, 0, \"\"},\n\t\t{\"IFA_LOCAL\", Const, 0, \"\"},\n\t\t{\"IFA_MAX\", Const, 0, \"\"},\n\t\t{\"IFA_MULTICAST\", Const, 0, \"\"},\n\t\t{\"IFA_ROUTE\", Const, 1, \"\"},\n\t\t{\"IFA_UNSPEC\", Const, 0, \"\"},\n\t\t{\"IFF_ALLMULTI\", Const, 0, \"\"},\n\t\t{\"IFF_ALTPHYS\", Const, 0, \"\"},\n\t\t{\"IFF_AUTOMEDIA\", Const, 0, \"\"},\n\t\t{\"IFF_BROADCAST\", Const, 0, \"\"},\n\t\t{\"IFF_CANTCHANGE\", Const, 0, \"\"},\n\t\t{\"IFF_CANTCONFIG\", Const, 1, \"\"},\n\t\t{\"IFF_DEBUG\", Const, 0, \"\"},\n\t\t{\"IFF_DRV_OACTIVE\", Const, 0, \"\"},\n\t\t{\"IFF_DRV_RUNNING\", Const, 0, \"\"},\n\t\t{\"IFF_DYING\", Const, 0, \"\"},\n\t\t{\"IFF_DYNAMIC\", Const, 0, \"\"},\n\t\t{\"IFF_LINK0\", Const, 0, \"\"},\n\t\t{\"IFF_LINK1\", Const, 0, \"\"},\n\t\t{\"IFF_LINK2\", Const, 0, \"\"},\n\t\t{\"IFF_LOOPBACK\", Const, 0, \"\"},\n\t\t{\"IFF_MASTER\", Const, 0, \"\"},\n\t\t{\"IFF_MONITOR\", Const, 0, \"\"},\n\t\t{\"IFF_MULTICAST\", Const, 0, \"\"},\n\t\t{\"IFF_NOARP\", Const, 0, \"\"},\n\t\t{\"IFF_NOTRAILERS\", Const, 0, \"\"},\n\t\t{\"IFF_NO_PI\", Const, 0, \"\"},\n\t\t{\"IFF_OACTIVE\", Const, 0, \"\"},\n\t\t{\"IFF_ONE_QUEUE\", Const, 0, \"\"},\n\t\t{\"IFF_POINTOPOINT\", Const, 0, \"\"},\n\t\t{\"IFF_POINTTOPOINT\", Const, 0, \"\"},\n\t\t{\"IFF_PORTSEL\", Const, 0, \"\"},\n\t\t{\"IFF_PPROMISC\", Const, 0, \"\"},\n\t\t{\"IFF_PROMISC\", Const, 0, \"\"},\n\t\t{\"IFF_RENAMING\", Const, 0, \"\"},\n\t\t{\"IFF_RUNNING\", Const, 0, \"\"},\n\t\t{\"IFF_SIMPLEX\", Const, 0, \"\"},\n\t\t{\"IFF_SLAVE\", Const, 0, \"\"},\n\t\t{\"IFF_SMART\", Const, 0, \"\"},\n\t\t{\"IFF_STATICARP\", Const, 0, \"\"},\n\t\t{\"IFF_TAP\", Const, 0, \"\"},\n\t\t{\"IFF_TUN\", Const, 0, \"\"},\n\t\t{\"IFF_TUN_EXCL\", Const, 0, \"\"},\n\t\t{\"IFF_UP\", Const, 0, \"\"},\n\t\t{\"IFF_VNET_HDR\", Const, 0, \"\"},\n\t\t{\"IFLA_ADDRESS\", Const, 0, \"\"},\n\t\t{\"IFLA_BROADCAST\", Const, 0, \"\"},\n\t\t{\"IFLA_COST\", Const, 0, \"\"},\n\t\t{\"IFLA_IFALIAS\", Const, 0, \"\"},\n\t\t{\"IFLA_IFNAME\", Const, 0, \"\"},\n\t\t{\"IFLA_LINK\", Const, 0, \"\"},\n\t\t{\"IFLA_LINKINFO\", Const, 0, \"\"},\n\t\t{\"IFLA_LINKMODE\", Const, 0, \"\"},\n\t\t{\"IFLA_MAP\", Const, 0, \"\"},\n\t\t{\"IFLA_MASTER\", Const, 0, \"\"},\n\t\t{\"IFLA_MAX\", Const, 0, \"\"},\n\t\t{\"IFLA_MTU\", Const, 0, \"\"},\n\t\t{\"IFLA_NET_NS_PID\", Const, 0, \"\"},\n\t\t{\"IFLA_OPERSTATE\", Const, 0, \"\"},\n\t\t{\"IFLA_PRIORITY\", Const, 0, \"\"},\n\t\t{\"IFLA_PROTINFO\", Const, 0, \"\"},\n\t\t{\"IFLA_QDISC\", Const, 0, \"\"},\n\t\t{\"IFLA_STATS\", Const, 0, \"\"},\n\t\t{\"IFLA_TXQLEN\", Const, 0, \"\"},\n\t\t{\"IFLA_UNSPEC\", Const, 0, \"\"},\n\t\t{\"IFLA_WEIGHT\", Const, 0, \"\"},\n\t\t{\"IFLA_WIRELESS\", Const, 0, \"\"},\n\t\t{\"IFNAMSIZ\", Const, 0, \"\"},\n\t\t{\"IFT_1822\", Const, 0, \"\"},\n\t\t{\"IFT_A12MPPSWITCH\", Const, 0, \"\"},\n\t\t{\"IFT_AAL2\", Const, 0, \"\"},\n\t\t{\"IFT_AAL5\", Const, 0, \"\"},\n\t\t{\"IFT_ADSL\", Const, 0, \"\"},\n\t\t{\"IFT_AFLANE8023\", Const, 0, \"\"},\n\t\t{\"IFT_AFLANE8025\", Const, 0, \"\"},\n\t\t{\"IFT_ARAP\", Const, 0, \"\"},\n\t\t{\"IFT_ARCNET\", Const, 0, \"\"},\n\t\t{\"IFT_ARCNETPLUS\", Const, 0, \"\"},\n\t\t{\"IFT_ASYNC\", Const, 0, \"\"},\n\t\t{\"IFT_ATM\", Const, 0, \"\"},\n\t\t{\"IFT_ATMDXI\", Const, 0, \"\"},\n\t\t{\"IFT_ATMFUNI\", Const, 0, \"\"},\n\t\t{\"IFT_ATMIMA\", Const, 0, \"\"},\n\t\t{\"IFT_ATMLOGICAL\", Const, 0, \"\"},\n\t\t{\"IFT_ATMRADIO\", Const, 0, \"\"},\n\t\t{\"IFT_ATMSUBINTERFACE\", Const, 0, \"\"},\n\t\t{\"IFT_ATMVCIENDPT\", Const, 0, \"\"},\n\t\t{\"IFT_ATMVIRTUAL\", Const, 0, \"\"},\n\t\t{\"IFT_BGPPOLICYACCOUNTING\", Const, 0, \"\"},\n\t\t{\"IFT_BLUETOOTH\", Const, 1, \"\"},\n\t\t{\"IFT_BRIDGE\", Const, 0, \"\"},\n\t\t{\"IFT_BSC\", Const, 0, \"\"},\n\t\t{\"IFT_CARP\", Const, 0, \"\"},\n\t\t{\"IFT_CCTEMUL\", Const, 0, \"\"},\n\t\t{\"IFT_CELLULAR\", Const, 0, \"\"},\n\t\t{\"IFT_CEPT\", Const, 0, \"\"},\n\t\t{\"IFT_CES\", Const, 0, \"\"},\n\t\t{\"IFT_CHANNEL\", Const, 0, \"\"},\n\t\t{\"IFT_CNR\", Const, 0, \"\"},\n\t\t{\"IFT_COFFEE\", Const, 0, \"\"},\n\t\t{\"IFT_COMPOSITELINK\", Const, 0, \"\"},\n\t\t{\"IFT_DCN\", Const, 0, \"\"},\n\t\t{\"IFT_DIGITALPOWERLINE\", Const, 0, \"\"},\n\t\t{\"IFT_DIGITALWRAPPEROVERHEADCHANNEL\", Const, 0, \"\"},\n\t\t{\"IFT_DLSW\", Const, 0, \"\"},\n\t\t{\"IFT_DOCSCABLEDOWNSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_DOCSCABLEMACLAYER\", Const, 0, \"\"},\n\t\t{\"IFT_DOCSCABLEUPSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_DOCSCABLEUPSTREAMCHANNEL\", Const, 1, \"\"},\n\t\t{\"IFT_DS0\", Const, 0, \"\"},\n\t\t{\"IFT_DS0BUNDLE\", Const, 0, \"\"},\n\t\t{\"IFT_DS1FDL\", Const, 0, \"\"},\n\t\t{\"IFT_DS3\", Const, 0, \"\"},\n\t\t{\"IFT_DTM\", Const, 0, \"\"},\n\t\t{\"IFT_DUMMY\", Const, 1, \"\"},\n\t\t{\"IFT_DVBASILN\", Const, 0, \"\"},\n\t\t{\"IFT_DVBASIOUT\", Const, 0, \"\"},\n\t\t{\"IFT_DVBRCCDOWNSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_DVBRCCMACLAYER\", Const, 0, \"\"},\n\t\t{\"IFT_DVBRCCUPSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_ECONET\", Const, 1, \"\"},\n\t\t{\"IFT_ENC\", Const, 0, \"\"},\n\t\t{\"IFT_EON\", Const, 0, \"\"},\n\t\t{\"IFT_EPLRS\", Const, 0, \"\"},\n\t\t{\"IFT_ESCON\", Const, 0, \"\"},\n\t\t{\"IFT_ETHER\", Const, 0, \"\"},\n\t\t{\"IFT_FAITH\", Const, 0, \"\"},\n\t\t{\"IFT_FAST\", Const, 0, \"\"},\n\t\t{\"IFT_FASTETHER\", Const, 0, \"\"},\n\t\t{\"IFT_FASTETHERFX\", Const, 0, \"\"},\n\t\t{\"IFT_FDDI\", Const, 0, \"\"},\n\t\t{\"IFT_FIBRECHANNEL\", Const, 0, \"\"},\n\t\t{\"IFT_FRAMERELAYINTERCONNECT\", Const, 0, \"\"},\n\t\t{\"IFT_FRAMERELAYMPI\", Const, 0, \"\"},\n\t\t{\"IFT_FRDLCIENDPT\", Const, 0, \"\"},\n\t\t{\"IFT_FRELAY\", Const, 0, \"\"},\n\t\t{\"IFT_FRELAYDCE\", Const, 0, \"\"},\n\t\t{\"IFT_FRF16MFRBUNDLE\", Const, 0, \"\"},\n\t\t{\"IFT_FRFORWARD\", Const, 0, \"\"},\n\t\t{\"IFT_G703AT2MB\", Const, 0, \"\"},\n\t\t{\"IFT_G703AT64K\", Const, 0, \"\"},\n\t\t{\"IFT_GIF\", Const, 0, \"\"},\n\t\t{\"IFT_GIGABITETHERNET\", Const, 0, \"\"},\n\t\t{\"IFT_GR303IDT\", Const, 0, \"\"},\n\t\t{\"IFT_GR303RDT\", Const, 0, \"\"},\n\t\t{\"IFT_H323GATEKEEPER\", Const, 0, \"\"},\n\t\t{\"IFT_H323PROXY\", Const, 0, \"\"},\n\t\t{\"IFT_HDH1822\", Const, 0, \"\"},\n\t\t{\"IFT_HDLC\", Const, 0, \"\"},\n\t\t{\"IFT_HDSL2\", Const, 0, \"\"},\n\t\t{\"IFT_HIPERLAN2\", Const, 0, \"\"},\n\t\t{\"IFT_HIPPI\", Const, 0, \"\"},\n\t\t{\"IFT_HIPPIINTERFACE\", Const, 0, \"\"},\n\t\t{\"IFT_HOSTPAD\", Const, 0, \"\"},\n\t\t{\"IFT_HSSI\", Const, 0, \"\"},\n\t\t{\"IFT_HY\", Const, 0, \"\"},\n\t\t{\"IFT_IBM370PARCHAN\", Const, 0, \"\"},\n\t\t{\"IFT_IDSL\", Const, 0, \"\"},\n\t\t{\"IFT_IEEE1394\", Const, 0, \"\"},\n\t\t{\"IFT_IEEE80211\", Const, 0, \"\"},\n\t\t{\"IFT_IEEE80212\", Const, 0, \"\"},\n\t\t{\"IFT_IEEE8023ADLAG\", Const, 0, \"\"},\n\t\t{\"IFT_IFGSN\", Const, 0, \"\"},\n\t\t{\"IFT_IMT\", Const, 0, \"\"},\n\t\t{\"IFT_INFINIBAND\", Const, 1, \"\"},\n\t\t{\"IFT_INTERLEAVE\", Const, 0, \"\"},\n\t\t{\"IFT_IP\", Const, 0, \"\"},\n\t\t{\"IFT_IPFORWARD\", Const, 0, \"\"},\n\t\t{\"IFT_IPOVERATM\", Const, 0, \"\"},\n\t\t{\"IFT_IPOVERCDLC\", Const, 0, \"\"},\n\t\t{\"IFT_IPOVERCLAW\", Const, 0, \"\"},\n\t\t{\"IFT_IPSWITCH\", Const, 0, \"\"},\n\t\t{\"IFT_IPXIP\", Const, 0, \"\"},\n\t\t{\"IFT_ISDN\", Const, 0, \"\"},\n\t\t{\"IFT_ISDNBASIC\", Const, 0, \"\"},\n\t\t{\"IFT_ISDNPRIMARY\", Const, 0, \"\"},\n\t\t{\"IFT_ISDNS\", Const, 0, \"\"},\n\t\t{\"IFT_ISDNU\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88022LLC\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88023\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88024\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88025\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88025CRFPINT\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88025DTR\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88025FIBER\", Const, 0, \"\"},\n\t\t{\"IFT_ISO88026\", Const, 0, \"\"},\n\t\t{\"IFT_ISUP\", Const, 0, \"\"},\n\t\t{\"IFT_L2VLAN\", Const, 0, \"\"},\n\t\t{\"IFT_L3IPVLAN\", Const, 0, \"\"},\n\t\t{\"IFT_L3IPXVLAN\", Const, 0, \"\"},\n\t\t{\"IFT_LAPB\", Const, 0, \"\"},\n\t\t{\"IFT_LAPD\", Const, 0, \"\"},\n\t\t{\"IFT_LAPF\", Const, 0, \"\"},\n\t\t{\"IFT_LINEGROUP\", Const, 1, \"\"},\n\t\t{\"IFT_LOCALTALK\", Const, 0, \"\"},\n\t\t{\"IFT_LOOP\", Const, 0, \"\"},\n\t\t{\"IFT_MEDIAMAILOVERIP\", Const, 0, \"\"},\n\t\t{\"IFT_MFSIGLINK\", Const, 0, \"\"},\n\t\t{\"IFT_MIOX25\", Const, 0, \"\"},\n\t\t{\"IFT_MODEM\", Const, 0, \"\"},\n\t\t{\"IFT_MPC\", Const, 0, \"\"},\n\t\t{\"IFT_MPLS\", Const, 0, \"\"},\n\t\t{\"IFT_MPLSTUNNEL\", Const, 0, \"\"},\n\t\t{\"IFT_MSDSL\", Const, 0, \"\"},\n\t\t{\"IFT_MVL\", Const, 0, \"\"},\n\t\t{\"IFT_MYRINET\", Const, 0, \"\"},\n\t\t{\"IFT_NFAS\", Const, 0, \"\"},\n\t\t{\"IFT_NSIP\", Const, 0, \"\"},\n\t\t{\"IFT_OPTICALCHANNEL\", Const, 0, \"\"},\n\t\t{\"IFT_OPTICALTRANSPORT\", Const, 0, \"\"},\n\t\t{\"IFT_OTHER\", Const, 0, \"\"},\n\t\t{\"IFT_P10\", Const, 0, \"\"},\n\t\t{\"IFT_P80\", Const, 0, \"\"},\n\t\t{\"IFT_PARA\", Const, 0, \"\"},\n\t\t{\"IFT_PDP\", Const, 0, \"\"},\n\t\t{\"IFT_PFLOG\", Const, 0, \"\"},\n\t\t{\"IFT_PFLOW\", Const, 1, \"\"},\n\t\t{\"IFT_PFSYNC\", Const, 0, \"\"},\n\t\t{\"IFT_PLC\", Const, 0, \"\"},\n\t\t{\"IFT_PON155\", Const, 1, \"\"},\n\t\t{\"IFT_PON622\", Const, 1, \"\"},\n\t\t{\"IFT_POS\", Const, 0, \"\"},\n\t\t{\"IFT_PPP\", Const, 0, \"\"},\n\t\t{\"IFT_PPPMULTILINKBUNDLE\", Const, 0, \"\"},\n\t\t{\"IFT_PROPATM\", Const, 1, \"\"},\n\t\t{\"IFT_PROPBWAP2MP\", Const, 0, \"\"},\n\t\t{\"IFT_PROPCNLS\", Const, 0, \"\"},\n\t\t{\"IFT_PROPDOCSWIRELESSDOWNSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_PROPDOCSWIRELESSMACLAYER\", Const, 0, \"\"},\n\t\t{\"IFT_PROPDOCSWIRELESSUPSTREAM\", Const, 0, \"\"},\n\t\t{\"IFT_PROPMUX\", Const, 0, \"\"},\n\t\t{\"IFT_PROPVIRTUAL\", Const, 0, \"\"},\n\t\t{\"IFT_PROPWIRELESSP2P\", Const, 0, \"\"},\n\t\t{\"IFT_PTPSERIAL\", Const, 0, \"\"},\n\t\t{\"IFT_PVC\", Const, 0, \"\"},\n\t\t{\"IFT_Q2931\", Const, 1, \"\"},\n\t\t{\"IFT_QLLC\", Const, 0, \"\"},\n\t\t{\"IFT_RADIOMAC\", Const, 0, \"\"},\n\t\t{\"IFT_RADSL\", Const, 0, \"\"},\n\t\t{\"IFT_REACHDSL\", Const, 0, \"\"},\n\t\t{\"IFT_RFC1483\", Const, 0, \"\"},\n\t\t{\"IFT_RS232\", Const, 0, \"\"},\n\t\t{\"IFT_RSRB\", Const, 0, \"\"},\n\t\t{\"IFT_SDLC\", Const, 0, \"\"},\n\t\t{\"IFT_SDSL\", Const, 0, \"\"},\n\t\t{\"IFT_SHDSL\", Const, 0, \"\"},\n\t\t{\"IFT_SIP\", Const, 0, \"\"},\n\t\t{\"IFT_SIPSIG\", Const, 1, \"\"},\n\t\t{\"IFT_SIPTG\", Const, 1, \"\"},\n\t\t{\"IFT_SLIP\", Const, 0, \"\"},\n\t\t{\"IFT_SMDSDXI\", Const, 0, \"\"},\n\t\t{\"IFT_SMDSICIP\", Const, 0, \"\"},\n\t\t{\"IFT_SONET\", Const, 0, \"\"},\n\t\t{\"IFT_SONETOVERHEADCHANNEL\", Const, 0, \"\"},\n\t\t{\"IFT_SONETPATH\", Const, 0, \"\"},\n\t\t{\"IFT_SONETVT\", Const, 0, \"\"},\n\t\t{\"IFT_SRP\", Const, 0, \"\"},\n\t\t{\"IFT_SS7SIGLINK\", Const, 0, \"\"},\n\t\t{\"IFT_STACKTOSTACK\", Const, 0, \"\"},\n\t\t{\"IFT_STARLAN\", Const, 0, \"\"},\n\t\t{\"IFT_STF\", Const, 0, \"\"},\n\t\t{\"IFT_T1\", Const, 0, \"\"},\n\t\t{\"IFT_TDLC\", Const, 0, \"\"},\n\t\t{\"IFT_TELINK\", Const, 1, \"\"},\n\t\t{\"IFT_TERMPAD\", Const, 0, \"\"},\n\t\t{\"IFT_TR008\", Const, 0, \"\"},\n\t\t{\"IFT_TRANSPHDLC\", Const, 0, \"\"},\n\t\t{\"IFT_TUNNEL\", Const, 0, \"\"},\n\t\t{\"IFT_ULTRA\", Const, 0, \"\"},\n\t\t{\"IFT_USB\", Const, 0, \"\"},\n\t\t{\"IFT_V11\", Const, 0, \"\"},\n\t\t{\"IFT_V35\", Const, 0, \"\"},\n\t\t{\"IFT_V36\", Const, 0, \"\"},\n\t\t{\"IFT_V37\", Const, 0, \"\"},\n\t\t{\"IFT_VDSL\", Const, 0, \"\"},\n\t\t{\"IFT_VIRTUALIPADDRESS\", Const, 0, \"\"},\n\t\t{\"IFT_VIRTUALTG\", Const, 1, \"\"},\n\t\t{\"IFT_VOICEDID\", Const, 1, \"\"},\n\t\t{\"IFT_VOICEEM\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEEMFGD\", Const, 1, \"\"},\n\t\t{\"IFT_VOICEENCAP\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEFGDEANA\", Const, 1, \"\"},\n\t\t{\"IFT_VOICEFXO\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEFXS\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEOVERATM\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEOVERCABLE\", Const, 1, \"\"},\n\t\t{\"IFT_VOICEOVERFRAMERELAY\", Const, 0, \"\"},\n\t\t{\"IFT_VOICEOVERIP\", Const, 0, \"\"},\n\t\t{\"IFT_X213\", Const, 0, \"\"},\n\t\t{\"IFT_X25\", Const, 0, \"\"},\n\t\t{\"IFT_X25DDN\", Const, 0, \"\"},\n\t\t{\"IFT_X25HUNTGROUP\", Const, 0, \"\"},\n\t\t{\"IFT_X25MLP\", Const, 0, \"\"},\n\t\t{\"IFT_X25PLE\", Const, 0, \"\"},\n\t\t{\"IFT_XETHER\", Const, 0, \"\"},\n\t\t{\"IGNBRK\", Const, 0, \"\"},\n\t\t{\"IGNCR\", Const, 0, \"\"},\n\t\t{\"IGNORE\", Const, 0, \"\"},\n\t\t{\"IGNPAR\", Const, 0, \"\"},\n\t\t{\"IMAXBEL\", Const, 0, \"\"},\n\t\t{\"INFINITE\", Const, 0, \"\"},\n\t\t{\"INLCR\", Const, 0, \"\"},\n\t\t{\"INPCK\", Const, 0, \"\"},\n\t\t{\"INVALID_FILE_ATTRIBUTES\", Const, 0, \"\"},\n\t\t{\"IN_ACCESS\", Const, 0, \"\"},\n\t\t{\"IN_ALL_EVENTS\", Const, 0, \"\"},\n\t\t{\"IN_ATTRIB\", Const, 0, \"\"},\n\t\t{\"IN_CLASSA_HOST\", Const, 0, \"\"},\n\t\t{\"IN_CLASSA_MAX\", Const, 0, \"\"},\n\t\t{\"IN_CLASSA_NET\", Const, 0, \"\"},\n\t\t{\"IN_CLASSA_NSHIFT\", Const, 0, \"\"},\n\t\t{\"IN_CLASSB_HOST\", Const, 0, \"\"},\n\t\t{\"IN_CLASSB_MAX\", Const, 0, \"\"},\n\t\t{\"IN_CLASSB_NET\", Const, 0, \"\"},\n\t\t{\"IN_CLASSB_NSHIFT\", Const, 0, \"\"},\n\t\t{\"IN_CLASSC_HOST\", Const, 0, \"\"},\n\t\t{\"IN_CLASSC_NET\", Const, 0, \"\"},\n\t\t{\"IN_CLASSC_NSHIFT\", Const, 0, \"\"},\n\t\t{\"IN_CLASSD_HOST\", Const, 0, \"\"},\n\t\t{\"IN_CLASSD_NET\", Const, 0, \"\"},\n\t\t{\"IN_CLASSD_NSHIFT\", Const, 0, \"\"},\n\t\t{\"IN_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"IN_CLOSE\", Const, 0, \"\"},\n\t\t{\"IN_CLOSE_NOWRITE\", Const, 0, \"\"},\n\t\t{\"IN_CLOSE_WRITE\", Const, 0, \"\"},\n\t\t{\"IN_CREATE\", Const, 0, \"\"},\n\t\t{\"IN_DELETE\", Const, 0, \"\"},\n\t\t{\"IN_DELETE_SELF\", Const, 0, \"\"},\n\t\t{\"IN_DONT_FOLLOW\", Const, 0, \"\"},\n\t\t{\"IN_EXCL_UNLINK\", Const, 0, \"\"},\n\t\t{\"IN_IGNORED\", Const, 0, \"\"},\n\t\t{\"IN_ISDIR\", Const, 0, \"\"},\n\t\t{\"IN_LINKLOCALNETNUM\", Const, 0, \"\"},\n\t\t{\"IN_LOOPBACKNET\", Const, 0, \"\"},\n\t\t{\"IN_MASK_ADD\", Const, 0, \"\"},\n\t\t{\"IN_MODIFY\", Const, 0, \"\"},\n\t\t{\"IN_MOVE\", Const, 0, \"\"},\n\t\t{\"IN_MOVED_FROM\", Const, 0, \"\"},\n\t\t{\"IN_MOVED_TO\", Const, 0, \"\"},\n\t\t{\"IN_MOVE_SELF\", Const, 0, \"\"},\n\t\t{\"IN_NONBLOCK\", Const, 0, \"\"},\n\t\t{\"IN_ONESHOT\", Const, 0, \"\"},\n\t\t{\"IN_ONLYDIR\", Const, 0, \"\"},\n\t\t{\"IN_OPEN\", Const, 0, \"\"},\n\t\t{\"IN_Q_OVERFLOW\", Const, 0, \"\"},\n\t\t{\"IN_RFC3021_HOST\", Const, 1, \"\"},\n\t\t{\"IN_RFC3021_MASK\", Const, 1, \"\"},\n\t\t{\"IN_RFC3021_NET\", Const, 1, \"\"},\n\t\t{\"IN_RFC3021_NSHIFT\", Const, 1, \"\"},\n\t\t{\"IN_UNMOUNT\", Const, 0, \"\"},\n\t\t{\"IOC_IN\", Const, 1, \"\"},\n\t\t{\"IOC_INOUT\", Const, 1, \"\"},\n\t\t{\"IOC_OUT\", Const, 1, \"\"},\n\t\t{\"IOC_VENDOR\", Const, 3, \"\"},\n\t\t{\"IOC_WS2\", Const, 1, \"\"},\n\t\t{\"IO_REPARSE_TAG_SYMLINK\", Const, 4, \"\"},\n\t\t{\"IPMreq\", Type, 0, \"\"},\n\t\t{\"IPMreq.Interface\", Field, 0, \"\"},\n\t\t{\"IPMreq.Multiaddr\", Field, 0, \"\"},\n\t\t{\"IPMreqn\", Type, 0, \"\"},\n\t\t{\"IPMreqn.Address\", Field, 0, \"\"},\n\t\t{\"IPMreqn.Ifindex\", Field, 0, \"\"},\n\t\t{\"IPMreqn.Multiaddr\", Field, 0, \"\"},\n\t\t{\"IPPROTO_3PC\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ADFS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_AH\", Const, 0, \"\"},\n\t\t{\"IPPROTO_AHIP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_APES\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ARGUS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_AX25\", Const, 0, \"\"},\n\t\t{\"IPPROTO_BHA\", Const, 0, \"\"},\n\t\t{\"IPPROTO_BLT\", Const, 0, \"\"},\n\t\t{\"IPPROTO_BRSATMON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CARP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CFTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CHAOS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CMTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_COMP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CPHB\", Const, 0, \"\"},\n\t\t{\"IPPROTO_CPNX\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DCCP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DDP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DIVERT\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DIVERT_INIT\", Const, 3, \"\"},\n\t\t{\"IPPROTO_DIVERT_RESP\", Const, 3, \"\"},\n\t\t{\"IPPROTO_DONE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_DSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_EGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_EMCON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ENCAP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_EON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ESP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ETHERIP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_FRAGMENT\", Const, 0, \"\"},\n\t\t{\"IPPROTO_GGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_GMTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_GRE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_HELLO\", Const, 0, \"\"},\n\t\t{\"IPPROTO_HMP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_HOPOPTS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ICMP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ICMPV6\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IDP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IDPR\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IDRP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IGMP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IGRP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IL\", Const, 0, \"\"},\n\t\t{\"IPPROTO_INLSP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_INP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPCOMP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPCV\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPEIP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPIP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPPC\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPV4\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPV6\", Const, 0, \"\"},\n\t\t{\"IPPROTO_IPV6_ICMP\", Const, 1, \"\"},\n\t\t{\"IPPROTO_IRTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_KRYPTOLAN\", Const, 0, \"\"},\n\t\t{\"IPPROTO_LARP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_LEAF1\", Const, 0, \"\"},\n\t\t{\"IPPROTO_LEAF2\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MAX\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MAXID\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MEAS\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MH\", Const, 1, \"\"},\n\t\t{\"IPPROTO_MHRP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MICP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MOBILE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MPLS\", Const, 1, \"\"},\n\t\t{\"IPPROTO_MTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_MUX\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ND\", Const, 0, \"\"},\n\t\t{\"IPPROTO_NHRP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_NONE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_NSP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_NVPII\", Const, 0, \"\"},\n\t\t{\"IPPROTO_OLD_DIVERT\", Const, 0, \"\"},\n\t\t{\"IPPROTO_OSPFIGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PFSYNC\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PGM\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PIGP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PIM\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PRM\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PUP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_PVP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_RAW\", Const, 0, \"\"},\n\t\t{\"IPPROTO_RCCMON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_RDP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ROUTING\", Const, 0, \"\"},\n\t\t{\"IPPROTO_RSVP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_RVD\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SATEXPAK\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SATMON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SCCSP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SCTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SDRP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SEND\", Const, 1, \"\"},\n\t\t{\"IPPROTO_SEP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SKIP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SPACER\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SRPC\", Const, 0, \"\"},\n\t\t{\"IPPROTO_ST\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SVMTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_SWIPE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TCF\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TCP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TLSP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TPXX\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TRUNK1\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TRUNK2\", Const, 0, \"\"},\n\t\t{\"IPPROTO_TTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_UDP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_UDPLITE\", Const, 0, \"\"},\n\t\t{\"IPPROTO_VINES\", Const, 0, \"\"},\n\t\t{\"IPPROTO_VISA\", Const, 0, \"\"},\n\t\t{\"IPPROTO_VMTP\", Const, 0, \"\"},\n\t\t{\"IPPROTO_VRRP\", Const, 1, \"\"},\n\t\t{\"IPPROTO_WBEXPAK\", Const, 0, \"\"},\n\t\t{\"IPPROTO_WBMON\", Const, 0, \"\"},\n\t\t{\"IPPROTO_WSN\", Const, 0, \"\"},\n\t\t{\"IPPROTO_XNET\", Const, 0, \"\"},\n\t\t{\"IPPROTO_XTP\", Const, 0, \"\"},\n\t\t{\"IPV6_2292DSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_2292HOPLIMIT\", Const, 0, \"\"},\n\t\t{\"IPV6_2292HOPOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_2292NEXTHOP\", Const, 0, \"\"},\n\t\t{\"IPV6_2292PKTINFO\", Const, 0, \"\"},\n\t\t{\"IPV6_2292PKTOPTIONS\", Const, 0, \"\"},\n\t\t{\"IPV6_2292RTHDR\", Const, 0, \"\"},\n\t\t{\"IPV6_ADDRFORM\", Const, 0, \"\"},\n\t\t{\"IPV6_ADD_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IPV6_AUTHHDR\", Const, 0, \"\"},\n\t\t{\"IPV6_AUTH_LEVEL\", Const, 1, \"\"},\n\t\t{\"IPV6_AUTOFLOWLABEL\", Const, 0, \"\"},\n\t\t{\"IPV6_BINDANY\", Const, 0, \"\"},\n\t\t{\"IPV6_BINDV6ONLY\", Const, 0, \"\"},\n\t\t{\"IPV6_BOUND_IF\", Const, 0, \"\"},\n\t\t{\"IPV6_CHECKSUM\", Const, 0, \"\"},\n\t\t{\"IPV6_DEFAULT_MULTICAST_HOPS\", Const, 0, \"\"},\n\t\t{\"IPV6_DEFAULT_MULTICAST_LOOP\", Const, 0, \"\"},\n\t\t{\"IPV6_DEFHLIM\", Const, 0, \"\"},\n\t\t{\"IPV6_DONTFRAG\", Const, 0, \"\"},\n\t\t{\"IPV6_DROP_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IPV6_DSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_ESP_NETWORK_LEVEL\", Const, 1, \"\"},\n\t\t{\"IPV6_ESP_TRANS_LEVEL\", Const, 1, \"\"},\n\t\t{\"IPV6_FAITH\", Const, 0, \"\"},\n\t\t{\"IPV6_FLOWINFO_MASK\", Const, 0, \"\"},\n\t\t{\"IPV6_FLOWLABEL_MASK\", Const, 0, \"\"},\n\t\t{\"IPV6_FRAGTTL\", Const, 0, \"\"},\n\t\t{\"IPV6_FW_ADD\", Const, 0, \"\"},\n\t\t{\"IPV6_FW_DEL\", Const, 0, \"\"},\n\t\t{\"IPV6_FW_FLUSH\", Const, 0, \"\"},\n\t\t{\"IPV6_FW_GET\", Const, 0, \"\"},\n\t\t{\"IPV6_FW_ZERO\", Const, 0, \"\"},\n\t\t{\"IPV6_HLIMDEC\", Const, 0, \"\"},\n\t\t{\"IPV6_HOPLIMIT\", Const, 0, \"\"},\n\t\t{\"IPV6_HOPOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_IPCOMP_LEVEL\", Const, 1, \"\"},\n\t\t{\"IPV6_IPSEC_POLICY\", Const, 0, \"\"},\n\t\t{\"IPV6_JOIN_ANYCAST\", Const, 0, \"\"},\n\t\t{\"IPV6_JOIN_GROUP\", Const, 0, \"\"},\n\t\t{\"IPV6_LEAVE_ANYCAST\", Const, 0, \"\"},\n\t\t{\"IPV6_LEAVE_GROUP\", Const, 0, \"\"},\n\t\t{\"IPV6_MAXHLIM\", Const, 0, \"\"},\n\t\t{\"IPV6_MAXOPTHDR\", Const, 0, \"\"},\n\t\t{\"IPV6_MAXPACKET\", Const, 0, \"\"},\n\t\t{\"IPV6_MAX_GROUP_SRC_FILTER\", Const, 0, \"\"},\n\t\t{\"IPV6_MAX_MEMBERSHIPS\", Const, 0, \"\"},\n\t\t{\"IPV6_MAX_SOCK_SRC_FILTER\", Const, 0, \"\"},\n\t\t{\"IPV6_MIN_MEMBERSHIPS\", Const, 0, \"\"},\n\t\t{\"IPV6_MMTU\", Const, 0, \"\"},\n\t\t{\"IPV6_MSFILTER\", Const, 0, \"\"},\n\t\t{\"IPV6_MTU\", Const, 0, \"\"},\n\t\t{\"IPV6_MTU_DISCOVER\", Const, 0, \"\"},\n\t\t{\"IPV6_MULTICAST_HOPS\", Const, 0, \"\"},\n\t\t{\"IPV6_MULTICAST_IF\", Const, 0, \"\"},\n\t\t{\"IPV6_MULTICAST_LOOP\", Const, 0, \"\"},\n\t\t{\"IPV6_NEXTHOP\", Const, 0, \"\"},\n\t\t{\"IPV6_OPTIONS\", Const, 1, \"\"},\n\t\t{\"IPV6_PATHMTU\", Const, 0, \"\"},\n\t\t{\"IPV6_PIPEX\", Const, 1, \"\"},\n\t\t{\"IPV6_PKTINFO\", Const, 0, \"\"},\n\t\t{\"IPV6_PMTUDISC_DO\", Const, 0, \"\"},\n\t\t{\"IPV6_PMTUDISC_DONT\", Const, 0, \"\"},\n\t\t{\"IPV6_PMTUDISC_PROBE\", Const, 0, \"\"},\n\t\t{\"IPV6_PMTUDISC_WANT\", Const, 0, \"\"},\n\t\t{\"IPV6_PORTRANGE\", Const, 0, \"\"},\n\t\t{\"IPV6_PORTRANGE_DEFAULT\", Const, 0, \"\"},\n\t\t{\"IPV6_PORTRANGE_HIGH\", Const, 0, \"\"},\n\t\t{\"IPV6_PORTRANGE_LOW\", Const, 0, \"\"},\n\t\t{\"IPV6_PREFER_TEMPADDR\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVDSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVDSTPORT\", Const, 3, \"\"},\n\t\t{\"IPV6_RECVERR\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVHOPLIMIT\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVHOPOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVPATHMTU\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVPKTINFO\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVRTHDR\", Const, 0, \"\"},\n\t\t{\"IPV6_RECVTCLASS\", Const, 0, \"\"},\n\t\t{\"IPV6_ROUTER_ALERT\", Const, 0, \"\"},\n\t\t{\"IPV6_RTABLE\", Const, 1, \"\"},\n\t\t{\"IPV6_RTHDR\", Const, 0, \"\"},\n\t\t{\"IPV6_RTHDRDSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_RTHDR_LOOSE\", Const, 0, \"\"},\n\t\t{\"IPV6_RTHDR_STRICT\", Const, 0, \"\"},\n\t\t{\"IPV6_RTHDR_TYPE_0\", Const, 0, \"\"},\n\t\t{\"IPV6_RXDSTOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_RXHOPOPTS\", Const, 0, \"\"},\n\t\t{\"IPV6_SOCKOPT_RESERVED1\", Const, 0, \"\"},\n\t\t{\"IPV6_TCLASS\", Const, 0, \"\"},\n\t\t{\"IPV6_UNICAST_HOPS\", Const, 0, \"\"},\n\t\t{\"IPV6_USE_MIN_MTU\", Const, 0, \"\"},\n\t\t{\"IPV6_V6ONLY\", Const, 0, \"\"},\n\t\t{\"IPV6_VERSION\", Const, 0, \"\"},\n\t\t{\"IPV6_VERSION_MASK\", Const, 0, \"\"},\n\t\t{\"IPV6_XFRM_POLICY\", Const, 0, \"\"},\n\t\t{\"IP_ADD_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IP_ADD_SOURCE_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IP_AUTH_LEVEL\", Const, 1, \"\"},\n\t\t{\"IP_BINDANY\", Const, 0, \"\"},\n\t\t{\"IP_BLOCK_SOURCE\", Const, 0, \"\"},\n\t\t{\"IP_BOUND_IF\", Const, 0, \"\"},\n\t\t{\"IP_DEFAULT_MULTICAST_LOOP\", Const, 0, \"\"},\n\t\t{\"IP_DEFAULT_MULTICAST_TTL\", Const, 0, \"\"},\n\t\t{\"IP_DF\", Const, 0, \"\"},\n\t\t{\"IP_DIVERTFL\", Const, 3, \"\"},\n\t\t{\"IP_DONTFRAG\", Const, 0, \"\"},\n\t\t{\"IP_DROP_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IP_DROP_SOURCE_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"IP_DUMMYNET3\", Const, 0, \"\"},\n\t\t{\"IP_DUMMYNET_CONFIGURE\", Const, 0, \"\"},\n\t\t{\"IP_DUMMYNET_DEL\", Const, 0, \"\"},\n\t\t{\"IP_DUMMYNET_FLUSH\", Const, 0, \"\"},\n\t\t{\"IP_DUMMYNET_GET\", Const, 0, \"\"},\n\t\t{\"IP_EF\", Const, 1, \"\"},\n\t\t{\"IP_ERRORMTU\", Const, 1, \"\"},\n\t\t{\"IP_ESP_NETWORK_LEVEL\", Const, 1, \"\"},\n\t\t{\"IP_ESP_TRANS_LEVEL\", Const, 1, \"\"},\n\t\t{\"IP_FAITH\", Const, 0, \"\"},\n\t\t{\"IP_FREEBIND\", Const, 0, \"\"},\n\t\t{\"IP_FW3\", Const, 0, \"\"},\n\t\t{\"IP_FW_ADD\", Const, 0, \"\"},\n\t\t{\"IP_FW_DEL\", Const, 0, \"\"},\n\t\t{\"IP_FW_FLUSH\", Const, 0, \"\"},\n\t\t{\"IP_FW_GET\", Const, 0, \"\"},\n\t\t{\"IP_FW_NAT_CFG\", Const, 0, \"\"},\n\t\t{\"IP_FW_NAT_DEL\", Const, 0, \"\"},\n\t\t{\"IP_FW_NAT_GET_CONFIG\", Const, 0, \"\"},\n\t\t{\"IP_FW_NAT_GET_LOG\", Const, 0, \"\"},\n\t\t{\"IP_FW_RESETLOG\", Const, 0, \"\"},\n\t\t{\"IP_FW_TABLE_ADD\", Const, 0, \"\"},\n\t\t{\"IP_FW_TABLE_DEL\", Const, 0, \"\"},\n\t\t{\"IP_FW_TABLE_FLUSH\", Const, 0, \"\"},\n\t\t{\"IP_FW_TABLE_GETSIZE\", Const, 0, \"\"},\n\t\t{\"IP_FW_TABLE_LIST\", Const, 0, \"\"},\n\t\t{\"IP_FW_ZERO\", Const, 0, \"\"},\n\t\t{\"IP_HDRINCL\", Const, 0, \"\"},\n\t\t{\"IP_IPCOMP_LEVEL\", Const, 1, \"\"},\n\t\t{\"IP_IPSECFLOWINFO\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_LOCAL_AUTH\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_LOCAL_CRED\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_LOCAL_ID\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_POLICY\", Const, 0, \"\"},\n\t\t{\"IP_IPSEC_REMOTE_AUTH\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_REMOTE_CRED\", Const, 1, \"\"},\n\t\t{\"IP_IPSEC_REMOTE_ID\", Const, 1, \"\"},\n\t\t{\"IP_MAXPACKET\", Const, 0, \"\"},\n\t\t{\"IP_MAX_GROUP_SRC_FILTER\", Const, 0, \"\"},\n\t\t{\"IP_MAX_MEMBERSHIPS\", Const, 0, \"\"},\n\t\t{\"IP_MAX_SOCK_MUTE_FILTER\", Const, 0, \"\"},\n\t\t{\"IP_MAX_SOCK_SRC_FILTER\", Const, 0, \"\"},\n\t\t{\"IP_MAX_SOURCE_FILTER\", Const, 0, \"\"},\n\t\t{\"IP_MF\", Const, 0, \"\"},\n\t\t{\"IP_MINFRAGSIZE\", Const, 1, \"\"},\n\t\t{\"IP_MINTTL\", Const, 0, \"\"},\n\t\t{\"IP_MIN_MEMBERSHIPS\", Const, 0, \"\"},\n\t\t{\"IP_MSFILTER\", Const, 0, \"\"},\n\t\t{\"IP_MSS\", Const, 0, \"\"},\n\t\t{\"IP_MTU\", Const, 0, \"\"},\n\t\t{\"IP_MTU_DISCOVER\", Const, 0, \"\"},\n\t\t{\"IP_MULTICAST_IF\", Const, 0, \"\"},\n\t\t{\"IP_MULTICAST_IFINDEX\", Const, 0, \"\"},\n\t\t{\"IP_MULTICAST_LOOP\", Const, 0, \"\"},\n\t\t{\"IP_MULTICAST_TTL\", Const, 0, \"\"},\n\t\t{\"IP_MULTICAST_VIF\", Const, 0, \"\"},\n\t\t{\"IP_NAT__XXX\", Const, 0, \"\"},\n\t\t{\"IP_OFFMASK\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_ADD\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_DEL\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_FLUSH\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_GET\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_RESETLOG\", Const, 0, \"\"},\n\t\t{\"IP_OLD_FW_ZERO\", Const, 0, \"\"},\n\t\t{\"IP_ONESBCAST\", Const, 0, \"\"},\n\t\t{\"IP_OPTIONS\", Const, 0, \"\"},\n\t\t{\"IP_ORIGDSTADDR\", Const, 0, \"\"},\n\t\t{\"IP_PASSSEC\", Const, 0, \"\"},\n\t\t{\"IP_PIPEX\", Const, 1, \"\"},\n\t\t{\"IP_PKTINFO\", Const, 0, \"\"},\n\t\t{\"IP_PKTOPTIONS\", Const, 0, \"\"},\n\t\t{\"IP_PMTUDISC\", Const, 0, \"\"},\n\t\t{\"IP_PMTUDISC_DO\", Const, 0, \"\"},\n\t\t{\"IP_PMTUDISC_DONT\", Const, 0, \"\"},\n\t\t{\"IP_PMTUDISC_PROBE\", Const, 0, \"\"},\n\t\t{\"IP_PMTUDISC_WANT\", Const, 0, \"\"},\n\t\t{\"IP_PORTRANGE\", Const, 0, \"\"},\n\t\t{\"IP_PORTRANGE_DEFAULT\", Const, 0, \"\"},\n\t\t{\"IP_PORTRANGE_HIGH\", Const, 0, \"\"},\n\t\t{\"IP_PORTRANGE_LOW\", Const, 0, \"\"},\n\t\t{\"IP_RECVDSTADDR\", Const, 0, \"\"},\n\t\t{\"IP_RECVDSTPORT\", Const, 1, \"\"},\n\t\t{\"IP_RECVERR\", Const, 0, \"\"},\n\t\t{\"IP_RECVIF\", Const, 0, \"\"},\n\t\t{\"IP_RECVOPTS\", Const, 0, \"\"},\n\t\t{\"IP_RECVORIGDSTADDR\", Const, 0, \"\"},\n\t\t{\"IP_RECVPKTINFO\", Const, 0, \"\"},\n\t\t{\"IP_RECVRETOPTS\", Const, 0, \"\"},\n\t\t{\"IP_RECVRTABLE\", Const, 1, \"\"},\n\t\t{\"IP_RECVTOS\", Const, 0, \"\"},\n\t\t{\"IP_RECVTTL\", Const, 0, \"\"},\n\t\t{\"IP_RETOPTS\", Const, 0, \"\"},\n\t\t{\"IP_RF\", Const, 0, \"\"},\n\t\t{\"IP_ROUTER_ALERT\", Const, 0, \"\"},\n\t\t{\"IP_RSVP_OFF\", Const, 0, \"\"},\n\t\t{\"IP_RSVP_ON\", Const, 0, \"\"},\n\t\t{\"IP_RSVP_VIF_OFF\", Const, 0, \"\"},\n\t\t{\"IP_RSVP_VIF_ON\", Const, 0, \"\"},\n\t\t{\"IP_RTABLE\", Const, 1, \"\"},\n\t\t{\"IP_SENDSRCADDR\", Const, 0, \"\"},\n\t\t{\"IP_STRIPHDR\", Const, 0, \"\"},\n\t\t{\"IP_TOS\", Const, 0, \"\"},\n\t\t{\"IP_TRAFFIC_MGT_BACKGROUND\", Const, 0, \"\"},\n\t\t{\"IP_TRANSPARENT\", Const, 0, \"\"},\n\t\t{\"IP_TTL\", Const, 0, \"\"},\n\t\t{\"IP_UNBLOCK_SOURCE\", Const, 0, \"\"},\n\t\t{\"IP_XFRM_POLICY\", Const, 0, \"\"},\n\t\t{\"IPv6MTUInfo\", Type, 2, \"\"},\n\t\t{\"IPv6MTUInfo.Addr\", Field, 2, \"\"},\n\t\t{\"IPv6MTUInfo.Mtu\", Field, 2, \"\"},\n\t\t{\"IPv6Mreq\", Type, 0, \"\"},\n\t\t{\"IPv6Mreq.Interface\", Field, 0, \"\"},\n\t\t{\"IPv6Mreq.Multiaddr\", Field, 0, \"\"},\n\t\t{\"ISIG\", Const, 0, \"\"},\n\t\t{\"ISTRIP\", Const, 0, \"\"},\n\t\t{\"IUCLC\", Const, 0, \"\"},\n\t\t{\"IUTF8\", Const, 0, \"\"},\n\t\t{\"IXANY\", Const, 0, \"\"},\n\t\t{\"IXOFF\", Const, 0, \"\"},\n\t\t{\"IXON\", Const, 0, \"\"},\n\t\t{\"IfAddrmsg\", Type, 0, \"\"},\n\t\t{\"IfAddrmsg.Family\", Field, 0, \"\"},\n\t\t{\"IfAddrmsg.Flags\", Field, 0, \"\"},\n\t\t{\"IfAddrmsg.Index\", Field, 0, \"\"},\n\t\t{\"IfAddrmsg.Prefixlen\", Field, 0, \"\"},\n\t\t{\"IfAddrmsg.Scope\", Field, 0, \"\"},\n\t\t{\"IfAnnounceMsghdr\", Type, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.Hdrlen\", Field, 2, \"\"},\n\t\t{\"IfAnnounceMsghdr.Index\", Field, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.Msglen\", Field, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.Name\", Field, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.Type\", Field, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.Version\", Field, 1, \"\"},\n\t\t{\"IfAnnounceMsghdr.What\", Field, 1, \"\"},\n\t\t{\"IfData\", Type, 0, \"\"},\n\t\t{\"IfData.Addrlen\", Field, 0, \"\"},\n\t\t{\"IfData.Baudrate\", Field, 0, \"\"},\n\t\t{\"IfData.Capabilities\", Field, 2, \"\"},\n\t\t{\"IfData.Collisions\", Field, 0, \"\"},\n\t\t{\"IfData.Datalen\", Field, 0, \"\"},\n\t\t{\"IfData.Epoch\", Field, 0, \"\"},\n\t\t{\"IfData.Hdrlen\", Field, 0, \"\"},\n\t\t{\"IfData.Hwassist\", Field, 0, \"\"},\n\t\t{\"IfData.Ibytes\", Field, 0, \"\"},\n\t\t{\"IfData.Ierrors\", Field, 0, \"\"},\n\t\t{\"IfData.Imcasts\", Field, 0, \"\"},\n\t\t{\"IfData.Ipackets\", Field, 0, \"\"},\n\t\t{\"IfData.Iqdrops\", Field, 0, \"\"},\n\t\t{\"IfData.Lastchange\", Field, 0, \"\"},\n\t\t{\"IfData.Link_state\", Field, 0, \"\"},\n\t\t{\"IfData.Mclpool\", Field, 2, \"\"},\n\t\t{\"IfData.Metric\", Field, 0, \"\"},\n\t\t{\"IfData.Mtu\", Field, 0, \"\"},\n\t\t{\"IfData.Noproto\", Field, 0, \"\"},\n\t\t{\"IfData.Obytes\", Field, 0, \"\"},\n\t\t{\"IfData.Oerrors\", Field, 0, \"\"},\n\t\t{\"IfData.Omcasts\", Field, 0, \"\"},\n\t\t{\"IfData.Opackets\", Field, 0, \"\"},\n\t\t{\"IfData.Pad\", Field, 2, \"\"},\n\t\t{\"IfData.Pad_cgo_0\", Field, 2, \"\"},\n\t\t{\"IfData.Pad_cgo_1\", Field, 2, \"\"},\n\t\t{\"IfData.Physical\", Field, 0, \"\"},\n\t\t{\"IfData.Recvquota\", Field, 0, \"\"},\n\t\t{\"IfData.Recvtiming\", Field, 0, \"\"},\n\t\t{\"IfData.Reserved1\", Field, 0, \"\"},\n\t\t{\"IfData.Reserved2\", Field, 0, \"\"},\n\t\t{\"IfData.Spare_char1\", Field, 0, \"\"},\n\t\t{\"IfData.Spare_char2\", Field, 0, \"\"},\n\t\t{\"IfData.Type\", Field, 0, \"\"},\n\t\t{\"IfData.Typelen\", Field, 0, \"\"},\n\t\t{\"IfData.Unused1\", Field, 0, \"\"},\n\t\t{\"IfData.Unused2\", Field, 0, \"\"},\n\t\t{\"IfData.Xmitquota\", Field, 0, \"\"},\n\t\t{\"IfData.Xmittiming\", Field, 0, \"\"},\n\t\t{\"IfInfomsg\", Type, 0, \"\"},\n\t\t{\"IfInfomsg.Change\", Field, 0, \"\"},\n\t\t{\"IfInfomsg.Family\", Field, 0, \"\"},\n\t\t{\"IfInfomsg.Flags\", Field, 0, \"\"},\n\t\t{\"IfInfomsg.Index\", Field, 0, \"\"},\n\t\t{\"IfInfomsg.Type\", Field, 0, \"\"},\n\t\t{\"IfInfomsg.X__ifi_pad\", Field, 0, \"\"},\n\t\t{\"IfMsghdr\", Type, 0, \"\"},\n\t\t{\"IfMsghdr.Addrs\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Data\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Flags\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Hdrlen\", Field, 2, \"\"},\n\t\t{\"IfMsghdr.Index\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Msglen\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Pad1\", Field, 2, \"\"},\n\t\t{\"IfMsghdr.Pad2\", Field, 2, \"\"},\n\t\t{\"IfMsghdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Pad_cgo_1\", Field, 2, \"\"},\n\t\t{\"IfMsghdr.Tableid\", Field, 2, \"\"},\n\t\t{\"IfMsghdr.Type\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Version\", Field, 0, \"\"},\n\t\t{\"IfMsghdr.Xflags\", Field, 2, \"\"},\n\t\t{\"IfaMsghdr\", Type, 0, \"\"},\n\t\t{\"IfaMsghdr.Addrs\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Flags\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Hdrlen\", Field, 2, \"\"},\n\t\t{\"IfaMsghdr.Index\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Metric\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Msglen\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Pad1\", Field, 2, \"\"},\n\t\t{\"IfaMsghdr.Pad2\", Field, 2, \"\"},\n\t\t{\"IfaMsghdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Tableid\", Field, 2, \"\"},\n\t\t{\"IfaMsghdr.Type\", Field, 0, \"\"},\n\t\t{\"IfaMsghdr.Version\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr\", Type, 0, \"\"},\n\t\t{\"IfmaMsghdr.Addrs\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Flags\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Index\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Msglen\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Type\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr.Version\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2\", Type, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Addrs\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Flags\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Index\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Msglen\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Refcount\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Type\", Field, 0, \"\"},\n\t\t{\"IfmaMsghdr2.Version\", Field, 0, \"\"},\n\t\t{\"ImplementsGetwd\", Const, 0, \"\"},\n\t\t{\"Inet4Pktinfo\", Type, 0, \"\"},\n\t\t{\"Inet4Pktinfo.Addr\", Field, 0, \"\"},\n\t\t{\"Inet4Pktinfo.Ifindex\", Field, 0, \"\"},\n\t\t{\"Inet4Pktinfo.Spec_dst\", Field, 0, \"\"},\n\t\t{\"Inet6Pktinfo\", Type, 0, \"\"},\n\t\t{\"Inet6Pktinfo.Addr\", Field, 0, \"\"},\n\t\t{\"Inet6Pktinfo.Ifindex\", Field, 0, \"\"},\n\t\t{\"InotifyAddWatch\", Func, 0, \"func(fd int, pathname string, mask uint32) (watchdesc int, err error)\"},\n\t\t{\"InotifyEvent\", Type, 0, \"\"},\n\t\t{\"InotifyEvent.Cookie\", Field, 0, \"\"},\n\t\t{\"InotifyEvent.Len\", Field, 0, \"\"},\n\t\t{\"InotifyEvent.Mask\", Field, 0, \"\"},\n\t\t{\"InotifyEvent.Name\", Field, 0, \"\"},\n\t\t{\"InotifyEvent.Wd\", Field, 0, \"\"},\n\t\t{\"InotifyInit\", Func, 0, \"func() (fd int, err error)\"},\n\t\t{\"InotifyInit1\", Func, 0, \"func(flags int) (fd int, err error)\"},\n\t\t{\"InotifyRmWatch\", Func, 0, \"func(fd int, watchdesc uint32) (success int, err error)\"},\n\t\t{\"InterfaceAddrMessage\", Type, 0, \"\"},\n\t\t{\"InterfaceAddrMessage.Data\", Field, 0, \"\"},\n\t\t{\"InterfaceAddrMessage.Header\", Field, 0, \"\"},\n\t\t{\"InterfaceAnnounceMessage\", Type, 1, \"\"},\n\t\t{\"InterfaceAnnounceMessage.Header\", Field, 1, \"\"},\n\t\t{\"InterfaceInfo\", Type, 0, \"\"},\n\t\t{\"InterfaceInfo.Address\", Field, 0, \"\"},\n\t\t{\"InterfaceInfo.BroadcastAddress\", Field, 0, \"\"},\n\t\t{\"InterfaceInfo.Flags\", Field, 0, \"\"},\n\t\t{\"InterfaceInfo.Netmask\", Field, 0, \"\"},\n\t\t{\"InterfaceMessage\", Type, 0, \"\"},\n\t\t{\"InterfaceMessage.Data\", Field, 0, \"\"},\n\t\t{\"InterfaceMessage.Header\", Field, 0, \"\"},\n\t\t{\"InterfaceMulticastAddrMessage\", Type, 0, \"\"},\n\t\t{\"InterfaceMulticastAddrMessage.Data\", Field, 0, \"\"},\n\t\t{\"InterfaceMulticastAddrMessage.Header\", Field, 0, \"\"},\n\t\t{\"InvalidHandle\", Const, 0, \"\"},\n\t\t{\"Ioperm\", Func, 0, \"func(from int, num int, on int) (err error)\"},\n\t\t{\"Iopl\", Func, 0, \"func(level int) (err error)\"},\n\t\t{\"Iovec\", Type, 0, \"\"},\n\t\t{\"Iovec.Base\", Field, 0, \"\"},\n\t\t{\"Iovec.Len\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo\", Type, 0, \"\"},\n\t\t{\"IpAdapterInfo.AdapterName\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.Address\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.AddressLength\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.ComboIndex\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.CurrentIpAddress\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.Description\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.DhcpEnabled\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.DhcpServer\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.GatewayList\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.HaveWins\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.Index\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.IpAddressList\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.LeaseExpires\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.LeaseObtained\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.Next\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.PrimaryWinsServer\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.SecondaryWinsServer\", Field, 0, \"\"},\n\t\t{\"IpAdapterInfo.Type\", Field, 0, \"\"},\n\t\t{\"IpAddrString\", Type, 0, \"\"},\n\t\t{\"IpAddrString.Context\", Field, 0, \"\"},\n\t\t{\"IpAddrString.IpAddress\", Field, 0, \"\"},\n\t\t{\"IpAddrString.IpMask\", Field, 0, \"\"},\n\t\t{\"IpAddrString.Next\", Field, 0, \"\"},\n\t\t{\"IpAddressString\", Type, 0, \"\"},\n\t\t{\"IpAddressString.String\", Field, 0, \"\"},\n\t\t{\"IpMaskString\", Type, 0, \"\"},\n\t\t{\"IpMaskString.String\", Field, 2, \"\"},\n\t\t{\"Issetugid\", Func, 0, \"\"},\n\t\t{\"KEY_ALL_ACCESS\", Const, 0, \"\"},\n\t\t{\"KEY_CREATE_LINK\", Const, 0, \"\"},\n\t\t{\"KEY_CREATE_SUB_KEY\", Const, 0, \"\"},\n\t\t{\"KEY_ENUMERATE_SUB_KEYS\", Const, 0, \"\"},\n\t\t{\"KEY_EXECUTE\", Const, 0, \"\"},\n\t\t{\"KEY_NOTIFY\", Const, 0, \"\"},\n\t\t{\"KEY_QUERY_VALUE\", Const, 0, \"\"},\n\t\t{\"KEY_READ\", Const, 0, \"\"},\n\t\t{\"KEY_SET_VALUE\", Const, 0, \"\"},\n\t\t{\"KEY_WOW64_32KEY\", Const, 0, \"\"},\n\t\t{\"KEY_WOW64_64KEY\", Const, 0, \"\"},\n\t\t{\"KEY_WRITE\", Const, 0, \"\"},\n\t\t{\"Kevent\", Func, 0, \"\"},\n\t\t{\"Kevent_t\", Type, 0, \"\"},\n\t\t{\"Kevent_t.Data\", Field, 0, \"\"},\n\t\t{\"Kevent_t.Fflags\", Field, 0, \"\"},\n\t\t{\"Kevent_t.Filter\", Field, 0, \"\"},\n\t\t{\"Kevent_t.Flags\", Field, 0, \"\"},\n\t\t{\"Kevent_t.Ident\", Field, 0, \"\"},\n\t\t{\"Kevent_t.Pad_cgo_0\", Field, 2, \"\"},\n\t\t{\"Kevent_t.Udata\", Field, 0, \"\"},\n\t\t{\"Kill\", Func, 0, \"func(pid int, sig Signal) (err error)\"},\n\t\t{\"Klogctl\", Func, 0, \"func(typ int, buf []byte) (n int, err error)\"},\n\t\t{\"Kqueue\", Func, 0, \"\"},\n\t\t{\"LANG_ENGLISH\", Const, 0, \"\"},\n\t\t{\"LAYERED_PROTOCOL\", Const, 2, \"\"},\n\t\t{\"LCNT_OVERLOAD_FLUSH\", Const, 1, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_CAD_OFF\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_CAD_ON\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_HALT\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_KEXEC\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_POWER_OFF\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_RESTART\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_RESTART2\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_CMD_SW_SUSPEND\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_MAGIC1\", Const, 0, \"\"},\n\t\t{\"LINUX_REBOOT_MAGIC2\", Const, 0, \"\"},\n\t\t{\"LOCK_EX\", Const, 0, \"\"},\n\t\t{\"LOCK_NB\", Const, 0, \"\"},\n\t\t{\"LOCK_SH\", Const, 0, \"\"},\n\t\t{\"LOCK_UN\", Const, 0, \"\"},\n\t\t{\"LazyDLL\", Type, 0, \"\"},\n\t\t{\"LazyDLL.Name\", Field, 0, \"\"},\n\t\t{\"LazyProc\", Type, 0, \"\"},\n\t\t{\"LazyProc.Name\", Field, 0, \"\"},\n\t\t{\"Lchown\", Func, 0, \"func(path string, uid int, gid int) (err error)\"},\n\t\t{\"Linger\", Type, 0, \"\"},\n\t\t{\"Linger.Linger\", Field, 0, \"\"},\n\t\t{\"Linger.Onoff\", Field, 0, \"\"},\n\t\t{\"Link\", Func, 0, \"func(oldpath string, newpath string) (err error)\"},\n\t\t{\"Listen\", Func, 0, \"func(s int, n int) (err error)\"},\n\t\t{\"Listxattr\", Func, 1, \"func(path string, dest []byte) (sz int, err error)\"},\n\t\t{\"LoadCancelIoEx\", Func, 1, \"\"},\n\t\t{\"LoadConnectEx\", Func, 1, \"\"},\n\t\t{\"LoadCreateSymbolicLink\", Func, 4, \"\"},\n\t\t{\"LoadDLL\", Func, 0, \"\"},\n\t\t{\"LoadGetAddrInfo\", Func, 1, \"\"},\n\t\t{\"LoadLibrary\", Func, 0, \"\"},\n\t\t{\"LoadSetFileCompletionNotificationModes\", Func, 2, \"\"},\n\t\t{\"LocalFree\", Func, 0, \"\"},\n\t\t{\"Log2phys_t\", Type, 0, \"\"},\n\t\t{\"Log2phys_t.Contigbytes\", Field, 0, \"\"},\n\t\t{\"Log2phys_t.Devoffset\", Field, 0, \"\"},\n\t\t{\"Log2phys_t.Flags\", Field, 0, \"\"},\n\t\t{\"LookupAccountName\", Func, 0, \"\"},\n\t\t{\"LookupAccountSid\", Func, 0, \"\"},\n\t\t{\"LookupSID\", Func, 0, \"\"},\n\t\t{\"LsfJump\", Func, 0, \"func(code int, k int, jt int, jf int) *SockFilter\"},\n\t\t{\"LsfSocket\", Func, 0, \"func(ifindex int, proto int) (int, error)\"},\n\t\t{\"LsfStmt\", Func, 0, \"func(code int, k int) *SockFilter\"},\n\t\t{\"Lstat\", Func, 0, \"func(path string, stat *Stat_t) (err error)\"},\n\t\t{\"MADV_AUTOSYNC\", Const, 1, \"\"},\n\t\t{\"MADV_CAN_REUSE\", Const, 0, \"\"},\n\t\t{\"MADV_CORE\", Const, 1, \"\"},\n\t\t{\"MADV_DOFORK\", Const, 0, \"\"},\n\t\t{\"MADV_DONTFORK\", Const, 0, \"\"},\n\t\t{\"MADV_DONTNEED\", Const, 0, \"\"},\n\t\t{\"MADV_FREE\", Const, 0, \"\"},\n\t\t{\"MADV_FREE_REUSABLE\", Const, 0, \"\"},\n\t\t{\"MADV_FREE_REUSE\", Const, 0, \"\"},\n\t\t{\"MADV_HUGEPAGE\", Const, 0, \"\"},\n\t\t{\"MADV_HWPOISON\", Const, 0, \"\"},\n\t\t{\"MADV_MERGEABLE\", Const, 0, \"\"},\n\t\t{\"MADV_NOCORE\", Const, 1, \"\"},\n\t\t{\"MADV_NOHUGEPAGE\", Const, 0, \"\"},\n\t\t{\"MADV_NORMAL\", Const, 0, \"\"},\n\t\t{\"MADV_NOSYNC\", Const, 1, \"\"},\n\t\t{\"MADV_PROTECT\", Const, 1, \"\"},\n\t\t{\"MADV_RANDOM\", Const, 0, \"\"},\n\t\t{\"MADV_REMOVE\", Const, 0, \"\"},\n\t\t{\"MADV_SEQUENTIAL\", Const, 0, \"\"},\n\t\t{\"MADV_SPACEAVAIL\", Const, 3, \"\"},\n\t\t{\"MADV_UNMERGEABLE\", Const, 0, \"\"},\n\t\t{\"MADV_WILLNEED\", Const, 0, \"\"},\n\t\t{\"MADV_ZERO_WIRED_PAGES\", Const, 0, \"\"},\n\t\t{\"MAP_32BIT\", Const, 0, \"\"},\n\t\t{\"MAP_ALIGNED_SUPER\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_16MB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_1TB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_256TB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_4GB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_64KB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_64PB\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_MASK\", Const, 3, \"\"},\n\t\t{\"MAP_ALIGNMENT_SHIFT\", Const, 3, \"\"},\n\t\t{\"MAP_ANON\", Const, 0, \"\"},\n\t\t{\"MAP_ANONYMOUS\", Const, 0, \"\"},\n\t\t{\"MAP_COPY\", Const, 0, \"\"},\n\t\t{\"MAP_DENYWRITE\", Const, 0, \"\"},\n\t\t{\"MAP_EXECUTABLE\", Const, 0, \"\"},\n\t\t{\"MAP_FILE\", Const, 0, \"\"},\n\t\t{\"MAP_FIXED\", Const, 0, \"\"},\n\t\t{\"MAP_FLAGMASK\", Const, 3, \"\"},\n\t\t{\"MAP_GROWSDOWN\", Const, 0, \"\"},\n\t\t{\"MAP_HASSEMAPHORE\", Const, 0, \"\"},\n\t\t{\"MAP_HUGETLB\", Const, 0, \"\"},\n\t\t{\"MAP_INHERIT\", Const, 3, \"\"},\n\t\t{\"MAP_INHERIT_COPY\", Const, 3, \"\"},\n\t\t{\"MAP_INHERIT_DEFAULT\", Const, 3, \"\"},\n\t\t{\"MAP_INHERIT_DONATE_COPY\", Const, 3, \"\"},\n\t\t{\"MAP_INHERIT_NONE\", Const, 3, \"\"},\n\t\t{\"MAP_INHERIT_SHARE\", Const, 3, \"\"},\n\t\t{\"MAP_JIT\", Const, 0, \"\"},\n\t\t{\"MAP_LOCKED\", Const, 0, \"\"},\n\t\t{\"MAP_NOCACHE\", Const, 0, \"\"},\n\t\t{\"MAP_NOCORE\", Const, 1, \"\"},\n\t\t{\"MAP_NOEXTEND\", Const, 0, \"\"},\n\t\t{\"MAP_NONBLOCK\", Const, 0, \"\"},\n\t\t{\"MAP_NORESERVE\", Const, 0, \"\"},\n\t\t{\"MAP_NOSYNC\", Const, 1, \"\"},\n\t\t{\"MAP_POPULATE\", Const, 0, \"\"},\n\t\t{\"MAP_PREFAULT_READ\", Const, 1, \"\"},\n\t\t{\"MAP_PRIVATE\", Const, 0, \"\"},\n\t\t{\"MAP_RENAME\", Const, 0, \"\"},\n\t\t{\"MAP_RESERVED0080\", Const, 0, \"\"},\n\t\t{\"MAP_RESERVED0100\", Const, 1, \"\"},\n\t\t{\"MAP_SHARED\", Const, 0, \"\"},\n\t\t{\"MAP_STACK\", Const, 0, \"\"},\n\t\t{\"MAP_TRYFIXED\", Const, 3, \"\"},\n\t\t{\"MAP_TYPE\", Const, 0, \"\"},\n\t\t{\"MAP_WIRED\", Const, 3, \"\"},\n\t\t{\"MAXIMUM_REPARSE_DATA_BUFFER_SIZE\", Const, 4, \"\"},\n\t\t{\"MAXLEN_IFDESCR\", Const, 0, \"\"},\n\t\t{\"MAXLEN_PHYSADDR\", Const, 0, \"\"},\n\t\t{\"MAX_ADAPTER_ADDRESS_LENGTH\", Const, 0, \"\"},\n\t\t{\"MAX_ADAPTER_DESCRIPTION_LENGTH\", Const, 0, \"\"},\n\t\t{\"MAX_ADAPTER_NAME_LENGTH\", Const, 0, \"\"},\n\t\t{\"MAX_COMPUTERNAME_LENGTH\", Const, 0, \"\"},\n\t\t{\"MAX_INTERFACE_NAME_LEN\", Const, 0, \"\"},\n\t\t{\"MAX_LONG_PATH\", Const, 0, \"\"},\n\t\t{\"MAX_PATH\", Const, 0, \"\"},\n\t\t{\"MAX_PROTOCOL_CHAIN\", Const, 2, \"\"},\n\t\t{\"MCL_CURRENT\", Const, 0, \"\"},\n\t\t{\"MCL_FUTURE\", Const, 0, \"\"},\n\t\t{\"MNT_DETACH\", Const, 0, \"\"},\n\t\t{\"MNT_EXPIRE\", Const, 0, \"\"},\n\t\t{\"MNT_FORCE\", Const, 0, \"\"},\n\t\t{\"MSG_BCAST\", Const, 1, \"\"},\n\t\t{\"MSG_CMSG_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"MSG_COMPAT\", Const, 0, \"\"},\n\t\t{\"MSG_CONFIRM\", Const, 0, \"\"},\n\t\t{\"MSG_CONTROLMBUF\", Const, 1, \"\"},\n\t\t{\"MSG_CTRUNC\", Const, 0, \"\"},\n\t\t{\"MSG_DONTROUTE\", Const, 0, \"\"},\n\t\t{\"MSG_DONTWAIT\", Const, 0, \"\"},\n\t\t{\"MSG_EOF\", Const, 0, \"\"},\n\t\t{\"MSG_EOR\", Const, 0, \"\"},\n\t\t{\"MSG_ERRQUEUE\", Const, 0, \"\"},\n\t\t{\"MSG_FASTOPEN\", Const, 1, \"\"},\n\t\t{\"MSG_FIN\", Const, 0, \"\"},\n\t\t{\"MSG_FLUSH\", Const, 0, \"\"},\n\t\t{\"MSG_HAVEMORE\", Const, 0, \"\"},\n\t\t{\"MSG_HOLD\", Const, 0, \"\"},\n\t\t{\"MSG_IOVUSRSPACE\", Const, 1, \"\"},\n\t\t{\"MSG_LENUSRSPACE\", Const, 1, \"\"},\n\t\t{\"MSG_MCAST\", Const, 1, \"\"},\n\t\t{\"MSG_MORE\", Const, 0, \"\"},\n\t\t{\"MSG_NAMEMBUF\", Const, 1, \"\"},\n\t\t{\"MSG_NBIO\", Const, 0, \"\"},\n\t\t{\"MSG_NEEDSA\", Const, 0, \"\"},\n\t\t{\"MSG_NOSIGNAL\", Const, 0, \"\"},\n\t\t{\"MSG_NOTIFICATION\", Const, 0, \"\"},\n\t\t{\"MSG_OOB\", Const, 0, \"\"},\n\t\t{\"MSG_PEEK\", Const, 0, \"\"},\n\t\t{\"MSG_PROXY\", Const, 0, \"\"},\n\t\t{\"MSG_RCVMORE\", Const, 0, \"\"},\n\t\t{\"MSG_RST\", Const, 0, \"\"},\n\t\t{\"MSG_SEND\", Const, 0, \"\"},\n\t\t{\"MSG_SYN\", Const, 0, \"\"},\n\t\t{\"MSG_TRUNC\", Const, 0, \"\"},\n\t\t{\"MSG_TRYHARD\", Const, 0, \"\"},\n\t\t{\"MSG_USERFLAGS\", Const, 1, \"\"},\n\t\t{\"MSG_WAITALL\", Const, 0, \"\"},\n\t\t{\"MSG_WAITFORONE\", Const, 0, \"\"},\n\t\t{\"MSG_WAITSTREAM\", Const, 0, \"\"},\n\t\t{\"MS_ACTIVE\", Const, 0, \"\"},\n\t\t{\"MS_ASYNC\", Const, 0, \"\"},\n\t\t{\"MS_BIND\", Const, 0, \"\"},\n\t\t{\"MS_DEACTIVATE\", Const, 0, \"\"},\n\t\t{\"MS_DIRSYNC\", Const, 0, \"\"},\n\t\t{\"MS_INVALIDATE\", Const, 0, \"\"},\n\t\t{\"MS_I_VERSION\", Const, 0, \"\"},\n\t\t{\"MS_KERNMOUNT\", Const, 0, \"\"},\n\t\t{\"MS_KILLPAGES\", Const, 0, \"\"},\n\t\t{\"MS_MANDLOCK\", Const, 0, \"\"},\n\t\t{\"MS_MGC_MSK\", Const, 0, \"\"},\n\t\t{\"MS_MGC_VAL\", Const, 0, \"\"},\n\t\t{\"MS_MOVE\", Const, 0, \"\"},\n\t\t{\"MS_NOATIME\", Const, 0, \"\"},\n\t\t{\"MS_NODEV\", Const, 0, \"\"},\n\t\t{\"MS_NODIRATIME\", Const, 0, \"\"},\n\t\t{\"MS_NOEXEC\", Const, 0, \"\"},\n\t\t{\"MS_NOSUID\", Const, 0, \"\"},\n\t\t{\"MS_NOUSER\", Const, 0, \"\"},\n\t\t{\"MS_POSIXACL\", Const, 0, \"\"},\n\t\t{\"MS_PRIVATE\", Const, 0, \"\"},\n\t\t{\"MS_RDONLY\", Const, 0, \"\"},\n\t\t{\"MS_REC\", Const, 0, \"\"},\n\t\t{\"MS_RELATIME\", Const, 0, \"\"},\n\t\t{\"MS_REMOUNT\", Const, 0, \"\"},\n\t\t{\"MS_RMT_MASK\", Const, 0, \"\"},\n\t\t{\"MS_SHARED\", Const, 0, \"\"},\n\t\t{\"MS_SILENT\", Const, 0, \"\"},\n\t\t{\"MS_SLAVE\", Const, 0, \"\"},\n\t\t{\"MS_STRICTATIME\", Const, 0, \"\"},\n\t\t{\"MS_SYNC\", Const, 0, \"\"},\n\t\t{\"MS_SYNCHRONOUS\", Const, 0, \"\"},\n\t\t{\"MS_UNBINDABLE\", Const, 0, \"\"},\n\t\t{\"Madvise\", Func, 0, \"func(b []byte, advice int) (err error)\"},\n\t\t{\"MapViewOfFile\", Func, 0, \"\"},\n\t\t{\"MaxTokenInfoClass\", Const, 0, \"\"},\n\t\t{\"Mclpool\", Type, 2, \"\"},\n\t\t{\"Mclpool.Alive\", Field, 2, \"\"},\n\t\t{\"Mclpool.Cwm\", Field, 2, \"\"},\n\t\t{\"Mclpool.Grown\", Field, 2, \"\"},\n\t\t{\"Mclpool.Hwm\", Field, 2, \"\"},\n\t\t{\"Mclpool.Lwm\", Field, 2, \"\"},\n\t\t{\"MibIfRow\", Type, 0, \"\"},\n\t\t{\"MibIfRow.AdminStatus\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Descr\", Field, 0, \"\"},\n\t\t{\"MibIfRow.DescrLen\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InDiscards\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InErrors\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InNUcastPkts\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InOctets\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InUcastPkts\", Field, 0, \"\"},\n\t\t{\"MibIfRow.InUnknownProtos\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Index\", Field, 0, \"\"},\n\t\t{\"MibIfRow.LastChange\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Mtu\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Name\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OperStatus\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutDiscards\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutErrors\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutNUcastPkts\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutOctets\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutQLen\", Field, 0, \"\"},\n\t\t{\"MibIfRow.OutUcastPkts\", Field, 0, \"\"},\n\t\t{\"MibIfRow.PhysAddr\", Field, 0, \"\"},\n\t\t{\"MibIfRow.PhysAddrLen\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Speed\", Field, 0, \"\"},\n\t\t{\"MibIfRow.Type\", Field, 0, \"\"},\n\t\t{\"Mkdir\", Func, 0, \"func(path string, mode uint32) (err error)\"},\n\t\t{\"Mkdirat\", Func, 0, \"func(dirfd int, path string, mode uint32) (err error)\"},\n\t\t{\"Mkfifo\", Func, 0, \"func(path string, mode uint32) (err error)\"},\n\t\t{\"Mknod\", Func, 0, \"func(path string, mode uint32, dev int) (err error)\"},\n\t\t{\"Mknodat\", Func, 0, \"func(dirfd int, path string, mode uint32, dev int) (err error)\"},\n\t\t{\"Mlock\", Func, 0, \"func(b []byte) (err error)\"},\n\t\t{\"Mlockall\", Func, 0, \"func(flags int) (err error)\"},\n\t\t{\"Mmap\", Func, 0, \"func(fd int, offset int64, length int, prot int, flags int) (data []byte, err error)\"},\n\t\t{\"Mount\", Func, 0, \"func(source string, target string, fstype string, flags uintptr, data string) (err error)\"},\n\t\t{\"MoveFile\", Func, 0, \"\"},\n\t\t{\"Mprotect\", Func, 0, \"func(b []byte, prot int) (err error)\"},\n\t\t{\"Msghdr\", Type, 0, \"\"},\n\t\t{\"Msghdr.Control\", Field, 0, \"\"},\n\t\t{\"Msghdr.Controllen\", Field, 0, \"\"},\n\t\t{\"Msghdr.Flags\", Field, 0, \"\"},\n\t\t{\"Msghdr.Iov\", Field, 0, \"\"},\n\t\t{\"Msghdr.Iovlen\", Field, 0, \"\"},\n\t\t{\"Msghdr.Name\", Field, 0, \"\"},\n\t\t{\"Msghdr.Namelen\", Field, 0, \"\"},\n\t\t{\"Msghdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Msghdr.Pad_cgo_1\", Field, 0, \"\"},\n\t\t{\"Munlock\", Func, 0, \"func(b []byte) (err error)\"},\n\t\t{\"Munlockall\", Func, 0, \"func() (err error)\"},\n\t\t{\"Munmap\", Func, 0, \"func(b []byte) (err error)\"},\n\t\t{\"MustLoadDLL\", Func, 0, \"\"},\n\t\t{\"NAME_MAX\", Const, 0, \"\"},\n\t\t{\"NETLINK_ADD_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"NETLINK_AUDIT\", Const, 0, \"\"},\n\t\t{\"NETLINK_BROADCAST_ERROR\", Const, 0, \"\"},\n\t\t{\"NETLINK_CONNECTOR\", Const, 0, \"\"},\n\t\t{\"NETLINK_DNRTMSG\", Const, 0, \"\"},\n\t\t{\"NETLINK_DROP_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"NETLINK_ECRYPTFS\", Const, 0, \"\"},\n\t\t{\"NETLINK_FIB_LOOKUP\", Const, 0, \"\"},\n\t\t{\"NETLINK_FIREWALL\", Const, 0, \"\"},\n\t\t{\"NETLINK_GENERIC\", Const, 0, \"\"},\n\t\t{\"NETLINK_INET_DIAG\", Const, 0, \"\"},\n\t\t{\"NETLINK_IP6_FW\", Const, 0, \"\"},\n\t\t{\"NETLINK_ISCSI\", Const, 0, \"\"},\n\t\t{\"NETLINK_KOBJECT_UEVENT\", Const, 0, \"\"},\n\t\t{\"NETLINK_NETFILTER\", Const, 0, \"\"},\n\t\t{\"NETLINK_NFLOG\", Const, 0, \"\"},\n\t\t{\"NETLINK_NO_ENOBUFS\", Const, 0, \"\"},\n\t\t{\"NETLINK_PKTINFO\", Const, 0, \"\"},\n\t\t{\"NETLINK_RDMA\", Const, 0, \"\"},\n\t\t{\"NETLINK_ROUTE\", Const, 0, \"\"},\n\t\t{\"NETLINK_SCSITRANSPORT\", Const, 0, \"\"},\n\t\t{\"NETLINK_SELINUX\", Const, 0, \"\"},\n\t\t{\"NETLINK_UNUSED\", Const, 0, \"\"},\n\t\t{\"NETLINK_USERSOCK\", Const, 0, \"\"},\n\t\t{\"NETLINK_XFRM\", Const, 0, \"\"},\n\t\t{\"NET_RT_DUMP\", Const, 0, \"\"},\n\t\t{\"NET_RT_DUMP2\", Const, 0, \"\"},\n\t\t{\"NET_RT_FLAGS\", Const, 0, \"\"},\n\t\t{\"NET_RT_IFLIST\", Const, 0, \"\"},\n\t\t{\"NET_RT_IFLIST2\", Const, 0, \"\"},\n\t\t{\"NET_RT_IFLISTL\", Const, 1, \"\"},\n\t\t{\"NET_RT_IFMALIST\", Const, 0, \"\"},\n\t\t{\"NET_RT_MAXID\", Const, 0, \"\"},\n\t\t{\"NET_RT_OIFLIST\", Const, 1, \"\"},\n\t\t{\"NET_RT_OOIFLIST\", Const, 1, \"\"},\n\t\t{\"NET_RT_STAT\", Const, 0, \"\"},\n\t\t{\"NET_RT_STATS\", Const, 1, \"\"},\n\t\t{\"NET_RT_TABLE\", Const, 1, \"\"},\n\t\t{\"NET_RT_TRASH\", Const, 0, \"\"},\n\t\t{\"NLA_ALIGNTO\", Const, 0, \"\"},\n\t\t{\"NLA_F_NESTED\", Const, 0, \"\"},\n\t\t{\"NLA_F_NET_BYTEORDER\", Const, 0, \"\"},\n\t\t{\"NLA_HDRLEN\", Const, 0, \"\"},\n\t\t{\"NLMSG_ALIGNTO\", Const, 0, \"\"},\n\t\t{\"NLMSG_DONE\", Const, 0, \"\"},\n\t\t{\"NLMSG_ERROR\", Const, 0, \"\"},\n\t\t{\"NLMSG_HDRLEN\", Const, 0, \"\"},\n\t\t{\"NLMSG_MIN_TYPE\", Const, 0, \"\"},\n\t\t{\"NLMSG_NOOP\", Const, 0, \"\"},\n\t\t{\"NLMSG_OVERRUN\", Const, 0, \"\"},\n\t\t{\"NLM_F_ACK\", Const, 0, \"\"},\n\t\t{\"NLM_F_APPEND\", Const, 0, \"\"},\n\t\t{\"NLM_F_ATOMIC\", Const, 0, \"\"},\n\t\t{\"NLM_F_CREATE\", Const, 0, \"\"},\n\t\t{\"NLM_F_DUMP\", Const, 0, \"\"},\n\t\t{\"NLM_F_ECHO\", Const, 0, \"\"},\n\t\t{\"NLM_F_EXCL\", Const, 0, \"\"},\n\t\t{\"NLM_F_MATCH\", Const, 0, \"\"},\n\t\t{\"NLM_F_MULTI\", Const, 0, \"\"},\n\t\t{\"NLM_F_REPLACE\", Const, 0, \"\"},\n\t\t{\"NLM_F_REQUEST\", Const, 0, \"\"},\n\t\t{\"NLM_F_ROOT\", Const, 0, \"\"},\n\t\t{\"NOFLSH\", Const, 0, \"\"},\n\t\t{\"NOTE_ABSOLUTE\", Const, 0, \"\"},\n\t\t{\"NOTE_ATTRIB\", Const, 0, \"\"},\n\t\t{\"NOTE_BACKGROUND\", Const, 16, \"\"},\n\t\t{\"NOTE_CHILD\", Const, 0, \"\"},\n\t\t{\"NOTE_CRITICAL\", Const, 16, \"\"},\n\t\t{\"NOTE_DELETE\", Const, 0, \"\"},\n\t\t{\"NOTE_EOF\", Const, 1, \"\"},\n\t\t{\"NOTE_EXEC\", Const, 0, \"\"},\n\t\t{\"NOTE_EXIT\", Const, 0, \"\"},\n\t\t{\"NOTE_EXITSTATUS\", Const, 0, \"\"},\n\t\t{\"NOTE_EXIT_CSERROR\", Const, 16, \"\"},\n\t\t{\"NOTE_EXIT_DECRYPTFAIL\", Const, 16, \"\"},\n\t\t{\"NOTE_EXIT_DETAIL\", Const, 16, \"\"},\n\t\t{\"NOTE_EXIT_DETAIL_MASK\", Const, 16, \"\"},\n\t\t{\"NOTE_EXIT_MEMORY\", Const, 16, \"\"},\n\t\t{\"NOTE_EXIT_REPARENTED\", Const, 16, \"\"},\n\t\t{\"NOTE_EXTEND\", Const, 0, \"\"},\n\t\t{\"NOTE_FFAND\", Const, 0, \"\"},\n\t\t{\"NOTE_FFCOPY\", Const, 0, \"\"},\n\t\t{\"NOTE_FFCTRLMASK\", Const, 0, \"\"},\n\t\t{\"NOTE_FFLAGSMASK\", Const, 0, \"\"},\n\t\t{\"NOTE_FFNOP\", Const, 0, \"\"},\n\t\t{\"NOTE_FFOR\", Const, 0, \"\"},\n\t\t{\"NOTE_FORK\", Const, 0, \"\"},\n\t\t{\"NOTE_LEEWAY\", Const, 16, \"\"},\n\t\t{\"NOTE_LINK\", Const, 0, \"\"},\n\t\t{\"NOTE_LOWAT\", Const, 0, \"\"},\n\t\t{\"NOTE_NONE\", Const, 0, \"\"},\n\t\t{\"NOTE_NSECONDS\", Const, 0, \"\"},\n\t\t{\"NOTE_PCTRLMASK\", Const, 0, \"\"},\n\t\t{\"NOTE_PDATAMASK\", Const, 0, \"\"},\n\t\t{\"NOTE_REAP\", Const, 0, \"\"},\n\t\t{\"NOTE_RENAME\", Const, 0, \"\"},\n\t\t{\"NOTE_RESOURCEEND\", Const, 0, \"\"},\n\t\t{\"NOTE_REVOKE\", Const, 0, \"\"},\n\t\t{\"NOTE_SECONDS\", Const, 0, \"\"},\n\t\t{\"NOTE_SIGNAL\", Const, 0, \"\"},\n\t\t{\"NOTE_TRACK\", Const, 0, \"\"},\n\t\t{\"NOTE_TRACKERR\", Const, 0, \"\"},\n\t\t{\"NOTE_TRIGGER\", Const, 0, \"\"},\n\t\t{\"NOTE_TRUNCATE\", Const, 1, \"\"},\n\t\t{\"NOTE_USECONDS\", Const, 0, \"\"},\n\t\t{\"NOTE_VM_ERROR\", Const, 0, \"\"},\n\t\t{\"NOTE_VM_PRESSURE\", Const, 0, \"\"},\n\t\t{\"NOTE_VM_PRESSURE_SUDDEN_TERMINATE\", Const, 0, \"\"},\n\t\t{\"NOTE_VM_PRESSURE_TERMINATE\", Const, 0, \"\"},\n\t\t{\"NOTE_WRITE\", Const, 0, \"\"},\n\t\t{\"NameCanonical\", Const, 0, \"\"},\n\t\t{\"NameCanonicalEx\", Const, 0, \"\"},\n\t\t{\"NameDisplay\", Const, 0, \"\"},\n\t\t{\"NameDnsDomain\", Const, 0, \"\"},\n\t\t{\"NameFullyQualifiedDN\", Const, 0, \"\"},\n\t\t{\"NameSamCompatible\", Const, 0, \"\"},\n\t\t{\"NameServicePrincipal\", Const, 0, \"\"},\n\t\t{\"NameUniqueId\", Const, 0, \"\"},\n\t\t{\"NameUnknown\", Const, 0, \"\"},\n\t\t{\"NameUserPrincipal\", Const, 0, \"\"},\n\t\t{\"Nanosleep\", Func, 0, \"func(time *Timespec, leftover *Timespec) (err error)\"},\n\t\t{\"NetApiBufferFree\", Func, 0, \"\"},\n\t\t{\"NetGetJoinInformation\", Func, 2, \"\"},\n\t\t{\"NetSetupDomainName\", Const, 2, \"\"},\n\t\t{\"NetSetupUnjoined\", Const, 2, \"\"},\n\t\t{\"NetSetupUnknownStatus\", Const, 2, \"\"},\n\t\t{\"NetSetupWorkgroupName\", Const, 2, \"\"},\n\t\t{\"NetUserGetInfo\", Func, 0, \"\"},\n\t\t{\"NetlinkMessage\", Type, 0, \"\"},\n\t\t{\"NetlinkMessage.Data\", Field, 0, \"\"},\n\t\t{\"NetlinkMessage.Header\", Field, 0, \"\"},\n\t\t{\"NetlinkRIB\", Func, 0, \"func(proto int, family int) ([]byte, error)\"},\n\t\t{\"NetlinkRouteAttr\", Type, 0, \"\"},\n\t\t{\"NetlinkRouteAttr.Attr\", Field, 0, \"\"},\n\t\t{\"NetlinkRouteAttr.Value\", Field, 0, \"\"},\n\t\t{\"NetlinkRouteRequest\", Type, 0, \"\"},\n\t\t{\"NetlinkRouteRequest.Data\", Field, 0, \"\"},\n\t\t{\"NetlinkRouteRequest.Header\", Field, 0, \"\"},\n\t\t{\"NewCallback\", Func, 0, \"\"},\n\t\t{\"NewCallbackCDecl\", Func, 3, \"\"},\n\t\t{\"NewLazyDLL\", Func, 0, \"\"},\n\t\t{\"NlAttr\", Type, 0, \"\"},\n\t\t{\"NlAttr.Len\", Field, 0, \"\"},\n\t\t{\"NlAttr.Type\", Field, 0, \"\"},\n\t\t{\"NlMsgerr\", Type, 0, \"\"},\n\t\t{\"NlMsgerr.Error\", Field, 0, \"\"},\n\t\t{\"NlMsgerr.Msg\", Field, 0, \"\"},\n\t\t{\"NlMsghdr\", Type, 0, \"\"},\n\t\t{\"NlMsghdr.Flags\", Field, 0, \"\"},\n\t\t{\"NlMsghdr.Len\", Field, 0, \"\"},\n\t\t{\"NlMsghdr.Pid\", Field, 0, \"\"},\n\t\t{\"NlMsghdr.Seq\", Field, 0, \"\"},\n\t\t{\"NlMsghdr.Type\", Field, 0, \"\"},\n\t\t{\"NsecToFiletime\", Func, 0, \"\"},\n\t\t{\"NsecToTimespec\", Func, 0, \"func(nsec int64) Timespec\"},\n\t\t{\"NsecToTimeval\", Func, 0, \"func(nsec int64) Timeval\"},\n\t\t{\"Ntohs\", Func, 0, \"\"},\n\t\t{\"OCRNL\", Const, 0, \"\"},\n\t\t{\"OFDEL\", Const, 0, \"\"},\n\t\t{\"OFILL\", Const, 0, \"\"},\n\t\t{\"OFIOGETBMAP\", Const, 1, \"\"},\n\t\t{\"OID_PKIX_KP_SERVER_AUTH\", Var, 0, \"\"},\n\t\t{\"OID_SERVER_GATED_CRYPTO\", Var, 0, \"\"},\n\t\t{\"OID_SGC_NETSCAPE\", Var, 0, \"\"},\n\t\t{\"OLCUC\", Const, 0, \"\"},\n\t\t{\"ONLCR\", Const, 0, \"\"},\n\t\t{\"ONLRET\", Const, 0, \"\"},\n\t\t{\"ONOCR\", Const, 0, \"\"},\n\t\t{\"ONOEOT\", Const, 1, \"\"},\n\t\t{\"OPEN_ALWAYS\", Const, 0, \"\"},\n\t\t{\"OPEN_EXISTING\", Const, 0, \"\"},\n\t\t{\"OPOST\", Const, 0, \"\"},\n\t\t{\"O_ACCMODE\", Const, 0, \"\"},\n\t\t{\"O_ALERT\", Const, 0, \"\"},\n\t\t{\"O_ALT_IO\", Const, 1, \"\"},\n\t\t{\"O_APPEND\", Const, 0, \"\"},\n\t\t{\"O_ASYNC\", Const, 0, \"\"},\n\t\t{\"O_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"O_CREAT\", Const, 0, \"\"},\n\t\t{\"O_DIRECT\", Const, 0, \"\"},\n\t\t{\"O_DIRECTORY\", Const, 0, \"\"},\n\t\t{\"O_DP_GETRAWENCRYPTED\", Const, 16, \"\"},\n\t\t{\"O_DSYNC\", Const, 0, \"\"},\n\t\t{\"O_EVTONLY\", Const, 0, \"\"},\n\t\t{\"O_EXCL\", Const, 0, \"\"},\n\t\t{\"O_EXEC\", Const, 0, \"\"},\n\t\t{\"O_EXLOCK\", Const, 0, \"\"},\n\t\t{\"O_FSYNC\", Const, 0, \"\"},\n\t\t{\"O_LARGEFILE\", Const, 0, \"\"},\n\t\t{\"O_NDELAY\", Const, 0, \"\"},\n\t\t{\"O_NOATIME\", Const, 0, \"\"},\n\t\t{\"O_NOCTTY\", Const, 0, \"\"},\n\t\t{\"O_NOFOLLOW\", Const, 0, \"\"},\n\t\t{\"O_NONBLOCK\", Const, 0, \"\"},\n\t\t{\"O_NOSIGPIPE\", Const, 1, \"\"},\n\t\t{\"O_POPUP\", Const, 0, \"\"},\n\t\t{\"O_RDONLY\", Const, 0, \"\"},\n\t\t{\"O_RDWR\", Const, 0, \"\"},\n\t\t{\"O_RSYNC\", Const, 0, \"\"},\n\t\t{\"O_SHLOCK\", Const, 0, \"\"},\n\t\t{\"O_SYMLINK\", Const, 0, \"\"},\n\t\t{\"O_SYNC\", Const, 0, \"\"},\n\t\t{\"O_TRUNC\", Const, 0, \"\"},\n\t\t{\"O_TTY_INIT\", Const, 0, \"\"},\n\t\t{\"O_WRONLY\", Const, 0, \"\"},\n\t\t{\"Open\", Func, 0, \"func(path string, mode int, perm uint32) (fd int, err error)\"},\n\t\t{\"OpenCurrentProcessToken\", Func, 0, \"\"},\n\t\t{\"OpenProcess\", Func, 0, \"\"},\n\t\t{\"OpenProcessToken\", Func, 0, \"\"},\n\t\t{\"Openat\", Func, 0, \"func(dirfd int, path string, flags int, mode uint32) (fd int, err error)\"},\n\t\t{\"Overlapped\", Type, 0, \"\"},\n\t\t{\"Overlapped.HEvent\", Field, 0, \"\"},\n\t\t{\"Overlapped.Internal\", Field, 0, \"\"},\n\t\t{\"Overlapped.InternalHigh\", Field, 0, \"\"},\n\t\t{\"Overlapped.Offset\", Field, 0, \"\"},\n\t\t{\"Overlapped.OffsetHigh\", Field, 0, \"\"},\n\t\t{\"PACKET_ADD_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"PACKET_BROADCAST\", Const, 0, \"\"},\n\t\t{\"PACKET_DROP_MEMBERSHIP\", Const, 0, \"\"},\n\t\t{\"PACKET_FASTROUTE\", Const, 0, \"\"},\n\t\t{\"PACKET_HOST\", Const, 0, \"\"},\n\t\t{\"PACKET_LOOPBACK\", Const, 0, \"\"},\n\t\t{\"PACKET_MR_ALLMULTI\", Const, 0, \"\"},\n\t\t{\"PACKET_MR_MULTICAST\", Const, 0, \"\"},\n\t\t{\"PACKET_MR_PROMISC\", Const, 0, \"\"},\n\t\t{\"PACKET_MULTICAST\", Const, 0, \"\"},\n\t\t{\"PACKET_OTHERHOST\", Const, 0, \"\"},\n\t\t{\"PACKET_OUTGOING\", Const, 0, \"\"},\n\t\t{\"PACKET_RECV_OUTPUT\", Const, 0, \"\"},\n\t\t{\"PACKET_RX_RING\", Const, 0, \"\"},\n\t\t{\"PACKET_STATISTICS\", Const, 0, \"\"},\n\t\t{\"PAGE_EXECUTE_READ\", Const, 0, \"\"},\n\t\t{\"PAGE_EXECUTE_READWRITE\", Const, 0, \"\"},\n\t\t{\"PAGE_EXECUTE_WRITECOPY\", Const, 0, \"\"},\n\t\t{\"PAGE_READONLY\", Const, 0, \"\"},\n\t\t{\"PAGE_READWRITE\", Const, 0, \"\"},\n\t\t{\"PAGE_WRITECOPY\", Const, 0, \"\"},\n\t\t{\"PARENB\", Const, 0, \"\"},\n\t\t{\"PARMRK\", Const, 0, \"\"},\n\t\t{\"PARODD\", Const, 0, \"\"},\n\t\t{\"PENDIN\", Const, 0, \"\"},\n\t\t{\"PFL_HIDDEN\", Const, 2, \"\"},\n\t\t{\"PFL_MATCHES_PROTOCOL_ZERO\", Const, 2, \"\"},\n\t\t{\"PFL_MULTIPLE_PROTO_ENTRIES\", Const, 2, \"\"},\n\t\t{\"PFL_NETWORKDIRECT_PROVIDER\", Const, 2, \"\"},\n\t\t{\"PFL_RECOMMENDED_PROTO_ENTRY\", Const, 2, \"\"},\n\t\t{\"PF_FLUSH\", Const, 1, \"\"},\n\t\t{\"PKCS_7_ASN_ENCODING\", Const, 0, \"\"},\n\t\t{\"PMC5_PIPELINE_FLUSH\", Const, 1, \"\"},\n\t\t{\"PRIO_PGRP\", Const, 2, \"\"},\n\t\t{\"PRIO_PROCESS\", Const, 2, \"\"},\n\t\t{\"PRIO_USER\", Const, 2, \"\"},\n\t\t{\"PRI_IOFLUSH\", Const, 1, \"\"},\n\t\t{\"PROCESS_QUERY_INFORMATION\", Const, 0, \"\"},\n\t\t{\"PROCESS_TERMINATE\", Const, 2, \"\"},\n\t\t{\"PROT_EXEC\", Const, 0, \"\"},\n\t\t{\"PROT_GROWSDOWN\", Const, 0, \"\"},\n\t\t{\"PROT_GROWSUP\", Const, 0, \"\"},\n\t\t{\"PROT_NONE\", Const, 0, \"\"},\n\t\t{\"PROT_READ\", Const, 0, \"\"},\n\t\t{\"PROT_WRITE\", Const, 0, \"\"},\n\t\t{\"PROV_DH_SCHANNEL\", Const, 0, \"\"},\n\t\t{\"PROV_DSS\", Const, 0, \"\"},\n\t\t{\"PROV_DSS_DH\", Const, 0, \"\"},\n\t\t{\"PROV_EC_ECDSA_FULL\", Const, 0, \"\"},\n\t\t{\"PROV_EC_ECDSA_SIG\", Const, 0, \"\"},\n\t\t{\"PROV_EC_ECNRA_FULL\", Const, 0, \"\"},\n\t\t{\"PROV_EC_ECNRA_SIG\", Const, 0, \"\"},\n\t\t{\"PROV_FORTEZZA\", Const, 0, \"\"},\n\t\t{\"PROV_INTEL_SEC\", Const, 0, \"\"},\n\t\t{\"PROV_MS_EXCHANGE\", Const, 0, \"\"},\n\t\t{\"PROV_REPLACE_OWF\", Const, 0, \"\"},\n\t\t{\"PROV_RNG\", Const, 0, \"\"},\n\t\t{\"PROV_RSA_AES\", Const, 0, \"\"},\n\t\t{\"PROV_RSA_FULL\", Const, 0, \"\"},\n\t\t{\"PROV_RSA_SCHANNEL\", Const, 0, \"\"},\n\t\t{\"PROV_RSA_SIG\", Const, 0, \"\"},\n\t\t{\"PROV_SPYRUS_LYNKS\", Const, 0, \"\"},\n\t\t{\"PROV_SSL\", Const, 0, \"\"},\n\t\t{\"PR_CAPBSET_DROP\", Const, 0, \"\"},\n\t\t{\"PR_CAPBSET_READ\", Const, 0, \"\"},\n\t\t{\"PR_CLEAR_SECCOMP_FILTER\", Const, 0, \"\"},\n\t\t{\"PR_ENDIAN_BIG\", Const, 0, \"\"},\n\t\t{\"PR_ENDIAN_LITTLE\", Const, 0, \"\"},\n\t\t{\"PR_ENDIAN_PPC_LITTLE\", Const, 0, \"\"},\n\t\t{\"PR_FPEMU_NOPRINT\", Const, 0, \"\"},\n\t\t{\"PR_FPEMU_SIGFPE\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_ASYNC\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_DISABLED\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_DIV\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_INV\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_NONRECOV\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_OVF\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_PRECISE\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_RES\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_SW_ENABLE\", Const, 0, \"\"},\n\t\t{\"PR_FP_EXC_UND\", Const, 0, \"\"},\n\t\t{\"PR_GET_DUMPABLE\", Const, 0, \"\"},\n\t\t{\"PR_GET_ENDIAN\", Const, 0, \"\"},\n\t\t{\"PR_GET_FPEMU\", Const, 0, \"\"},\n\t\t{\"PR_GET_FPEXC\", Const, 0, \"\"},\n\t\t{\"PR_GET_KEEPCAPS\", Const, 0, \"\"},\n\t\t{\"PR_GET_NAME\", Const, 0, \"\"},\n\t\t{\"PR_GET_PDEATHSIG\", Const, 0, \"\"},\n\t\t{\"PR_GET_SECCOMP\", Const, 0, \"\"},\n\t\t{\"PR_GET_SECCOMP_FILTER\", Const, 0, \"\"},\n\t\t{\"PR_GET_SECUREBITS\", Const, 0, \"\"},\n\t\t{\"PR_GET_TIMERSLACK\", Const, 0, \"\"},\n\t\t{\"PR_GET_TIMING\", Const, 0, \"\"},\n\t\t{\"PR_GET_TSC\", Const, 0, \"\"},\n\t\t{\"PR_GET_UNALIGN\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_CLEAR\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_DEFAULT\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_EARLY\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_GET\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_LATE\", Const, 0, \"\"},\n\t\t{\"PR_MCE_KILL_SET\", Const, 0, \"\"},\n\t\t{\"PR_SECCOMP_FILTER_EVENT\", Const, 0, \"\"},\n\t\t{\"PR_SECCOMP_FILTER_SYSCALL\", Const, 0, \"\"},\n\t\t{\"PR_SET_DUMPABLE\", Const, 0, \"\"},\n\t\t{\"PR_SET_ENDIAN\", Const, 0, \"\"},\n\t\t{\"PR_SET_FPEMU\", Const, 0, \"\"},\n\t\t{\"PR_SET_FPEXC\", Const, 0, \"\"},\n\t\t{\"PR_SET_KEEPCAPS\", Const, 0, \"\"},\n\t\t{\"PR_SET_NAME\", Const, 0, \"\"},\n\t\t{\"PR_SET_PDEATHSIG\", Const, 0, \"\"},\n\t\t{\"PR_SET_PTRACER\", Const, 0, \"\"},\n\t\t{\"PR_SET_SECCOMP\", Const, 0, \"\"},\n\t\t{\"PR_SET_SECCOMP_FILTER\", Const, 0, \"\"},\n\t\t{\"PR_SET_SECUREBITS\", Const, 0, \"\"},\n\t\t{\"PR_SET_TIMERSLACK\", Const, 0, \"\"},\n\t\t{\"PR_SET_TIMING\", Const, 0, \"\"},\n\t\t{\"PR_SET_TSC\", Const, 0, \"\"},\n\t\t{\"PR_SET_UNALIGN\", Const, 0, \"\"},\n\t\t{\"PR_TASK_PERF_EVENTS_DISABLE\", Const, 0, \"\"},\n\t\t{\"PR_TASK_PERF_EVENTS_ENABLE\", Const, 0, \"\"},\n\t\t{\"PR_TIMING_STATISTICAL\", Const, 0, \"\"},\n\t\t{\"PR_TIMING_TIMESTAMP\", Const, 0, \"\"},\n\t\t{\"PR_TSC_ENABLE\", Const, 0, \"\"},\n\t\t{\"PR_TSC_SIGSEGV\", Const, 0, \"\"},\n\t\t{\"PR_UNALIGN_NOPRINT\", Const, 0, \"\"},\n\t\t{\"PR_UNALIGN_SIGBUS\", Const, 0, \"\"},\n\t\t{\"PTRACE_ARCH_PRCTL\", Const, 0, \"\"},\n\t\t{\"PTRACE_ATTACH\", Const, 0, \"\"},\n\t\t{\"PTRACE_CONT\", Const, 0, \"\"},\n\t\t{\"PTRACE_DETACH\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_CLONE\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_EXEC\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_EXIT\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_FORK\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_VFORK\", Const, 0, \"\"},\n\t\t{\"PTRACE_EVENT_VFORK_DONE\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETCRUNCHREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETEVENTMSG\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETFPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETFPXREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETHBPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETREGSET\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETSIGINFO\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETVFPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GETWMMXREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_GET_THREAD_AREA\", Const, 0, \"\"},\n\t\t{\"PTRACE_KILL\", Const, 0, \"\"},\n\t\t{\"PTRACE_OLDSETOPTIONS\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_MASK\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACECLONE\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACEEXEC\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACEEXIT\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACEFORK\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACESYSGOOD\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACEVFORK\", Const, 0, \"\"},\n\t\t{\"PTRACE_O_TRACEVFORKDONE\", Const, 0, \"\"},\n\t\t{\"PTRACE_PEEKDATA\", Const, 0, \"\"},\n\t\t{\"PTRACE_PEEKTEXT\", Const, 0, \"\"},\n\t\t{\"PTRACE_PEEKUSR\", Const, 0, \"\"},\n\t\t{\"PTRACE_POKEDATA\", Const, 0, \"\"},\n\t\t{\"PTRACE_POKETEXT\", Const, 0, \"\"},\n\t\t{\"PTRACE_POKEUSR\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETCRUNCHREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETFPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETFPXREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETHBPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETOPTIONS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETREGSET\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETSIGINFO\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETVFPREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SETWMMXREGS\", Const, 0, \"\"},\n\t\t{\"PTRACE_SET_SYSCALL\", Const, 0, \"\"},\n\t\t{\"PTRACE_SET_THREAD_AREA\", Const, 0, \"\"},\n\t\t{\"PTRACE_SINGLEBLOCK\", Const, 0, \"\"},\n\t\t{\"PTRACE_SINGLESTEP\", Const, 0, \"\"},\n\t\t{\"PTRACE_SYSCALL\", Const, 0, \"\"},\n\t\t{\"PTRACE_SYSEMU\", Const, 0, \"\"},\n\t\t{\"PTRACE_SYSEMU_SINGLESTEP\", Const, 0, \"\"},\n\t\t{\"PTRACE_TRACEME\", Const, 0, \"\"},\n\t\t{\"PT_ATTACH\", Const, 0, \"\"},\n\t\t{\"PT_ATTACHEXC\", Const, 0, \"\"},\n\t\t{\"PT_CONTINUE\", Const, 0, \"\"},\n\t\t{\"PT_DATA_ADDR\", Const, 0, \"\"},\n\t\t{\"PT_DENY_ATTACH\", Const, 0, \"\"},\n\t\t{\"PT_DETACH\", Const, 0, \"\"},\n\t\t{\"PT_FIRSTMACH\", Const, 0, \"\"},\n\t\t{\"PT_FORCEQUOTA\", Const, 0, \"\"},\n\t\t{\"PT_KILL\", Const, 0, \"\"},\n\t\t{\"PT_MASK\", Const, 1, \"\"},\n\t\t{\"PT_READ_D\", Const, 0, \"\"},\n\t\t{\"PT_READ_I\", Const, 0, \"\"},\n\t\t{\"PT_READ_U\", Const, 0, \"\"},\n\t\t{\"PT_SIGEXC\", Const, 0, \"\"},\n\t\t{\"PT_STEP\", Const, 0, \"\"},\n\t\t{\"PT_TEXT_ADDR\", Const, 0, \"\"},\n\t\t{\"PT_TEXT_END_ADDR\", Const, 0, \"\"},\n\t\t{\"PT_THUPDATE\", Const, 0, \"\"},\n\t\t{\"PT_TRACE_ME\", Const, 0, \"\"},\n\t\t{\"PT_WRITE_D\", Const, 0, \"\"},\n\t\t{\"PT_WRITE_I\", Const, 0, \"\"},\n\t\t{\"PT_WRITE_U\", Const, 0, \"\"},\n\t\t{\"ParseDirent\", Func, 0, \"func(buf []byte, max int, names []string) (consumed int, count int, newnames []string)\"},\n\t\t{\"ParseNetlinkMessage\", Func, 0, \"func(b []byte) ([]NetlinkMessage, error)\"},\n\t\t{\"ParseNetlinkRouteAttr\", Func, 0, \"func(m *NetlinkMessage) ([]NetlinkRouteAttr, error)\"},\n\t\t{\"ParseRoutingMessage\", Func, 0, \"\"},\n\t\t{\"ParseRoutingSockaddr\", Func, 0, \"\"},\n\t\t{\"ParseSocketControlMessage\", Func, 0, \"func(b []byte) ([]SocketControlMessage, error)\"},\n\t\t{\"ParseUnixCredentials\", Func, 0, \"func(m *SocketControlMessage) (*Ucred, error)\"},\n\t\t{\"ParseUnixRights\", Func, 0, \"func(m *SocketControlMessage) ([]int, error)\"},\n\t\t{\"PathMax\", Const, 0, \"\"},\n\t\t{\"Pathconf\", Func, 0, \"\"},\n\t\t{\"Pause\", Func, 0, \"func() (err error)\"},\n\t\t{\"Pipe\", Func, 0, \"func(p []int) error\"},\n\t\t{\"Pipe2\", Func, 1, \"func(p []int, flags int) error\"},\n\t\t{\"PivotRoot\", Func, 0, \"func(newroot string, putold string) (err error)\"},\n\t\t{\"Pointer\", Type, 11, \"\"},\n\t\t{\"PostQueuedCompletionStatus\", Func, 0, \"\"},\n\t\t{\"Pread\", Func, 0, \"func(fd int, p []byte, offset int64) (n int, err error)\"},\n\t\t{\"Proc\", Type, 0, \"\"},\n\t\t{\"Proc.Dll\", Field, 0, \"\"},\n\t\t{\"Proc.Name\", Field, 0, \"\"},\n\t\t{\"ProcAttr\", Type, 0, \"\"},\n\t\t{\"ProcAttr.Dir\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Env\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Files\", Field, 0, \"\"},\n\t\t{\"ProcAttr.Sys\", Field, 0, \"\"},\n\t\t{\"Process32First\", Func, 4, \"\"},\n\t\t{\"Process32Next\", Func, 4, \"\"},\n\t\t{\"ProcessEntry32\", Type, 4, \"\"},\n\t\t{\"ProcessEntry32.DefaultHeapID\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.ExeFile\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.Flags\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.ModuleID\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.ParentProcessID\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.PriClassBase\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.ProcessID\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.Size\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.Threads\", Field, 4, \"\"},\n\t\t{\"ProcessEntry32.Usage\", Field, 4, \"\"},\n\t\t{\"ProcessInformation\", Type, 0, \"\"},\n\t\t{\"ProcessInformation.Process\", Field, 0, \"\"},\n\t\t{\"ProcessInformation.ProcessId\", Field, 0, \"\"},\n\t\t{\"ProcessInformation.Thread\", Field, 0, \"\"},\n\t\t{\"ProcessInformation.ThreadId\", Field, 0, \"\"},\n\t\t{\"Protoent\", Type, 0, \"\"},\n\t\t{\"Protoent.Aliases\", Field, 0, \"\"},\n\t\t{\"Protoent.Name\", Field, 0, \"\"},\n\t\t{\"Protoent.Proto\", Field, 0, \"\"},\n\t\t{\"PtraceAttach\", Func, 0, \"func(pid int) (err error)\"},\n\t\t{\"PtraceCont\", Func, 0, \"func(pid int, signal int) (err error)\"},\n\t\t{\"PtraceDetach\", Func, 0, \"func(pid int) (err error)\"},\n\t\t{\"PtraceGetEventMsg\", Func, 0, \"func(pid int) (msg uint, err error)\"},\n\t\t{\"PtraceGetRegs\", Func, 0, \"func(pid int, regsout *PtraceRegs) (err error)\"},\n\t\t{\"PtracePeekData\", Func, 0, \"func(pid int, addr uintptr, out []byte) (count int, err error)\"},\n\t\t{\"PtracePeekText\", Func, 0, \"func(pid int, addr uintptr, out []byte) (count int, err error)\"},\n\t\t{\"PtracePokeData\", Func, 0, \"func(pid int, addr uintptr, data []byte) (count int, err error)\"},\n\t\t{\"PtracePokeText\", Func, 0, \"func(pid int, addr uintptr, data []byte) (count int, err error)\"},\n\t\t{\"PtraceRegs\", Type, 0, \"\"},\n\t\t{\"PtraceRegs.Cs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Ds\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Eax\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Ebp\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Ebx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Ecx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Edi\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Edx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Eflags\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Eip\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Es\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Esi\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Esp\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Fs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Fs_base\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Gs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Gs_base\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Orig_eax\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Orig_rax\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R10\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R11\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R12\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R13\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R14\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R15\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R8\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.R9\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rax\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rbp\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rbx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rcx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rdi\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rdx\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rip\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rsi\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Rsp\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Ss\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Uregs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xcs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xds\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xes\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xfs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xgs\", Field, 0, \"\"},\n\t\t{\"PtraceRegs.Xss\", Field, 0, \"\"},\n\t\t{\"PtraceSetOptions\", Func, 0, \"func(pid int, options int) (err error)\"},\n\t\t{\"PtraceSetRegs\", Func, 0, \"func(pid int, regs *PtraceRegs) (err error)\"},\n\t\t{\"PtraceSingleStep\", Func, 0, \"func(pid int) (err error)\"},\n\t\t{\"PtraceSyscall\", Func, 1, \"func(pid int, signal int) (err error)\"},\n\t\t{\"Pwrite\", Func, 0, \"func(fd int, p []byte, offset int64) (n int, err error)\"},\n\t\t{\"REG_BINARY\", Const, 0, \"\"},\n\t\t{\"REG_DWORD\", Const, 0, \"\"},\n\t\t{\"REG_DWORD_BIG_ENDIAN\", Const, 0, \"\"},\n\t\t{\"REG_DWORD_LITTLE_ENDIAN\", Const, 0, \"\"},\n\t\t{\"REG_EXPAND_SZ\", Const, 0, \"\"},\n\t\t{\"REG_FULL_RESOURCE_DESCRIPTOR\", Const, 0, \"\"},\n\t\t{\"REG_LINK\", Const, 0, \"\"},\n\t\t{\"REG_MULTI_SZ\", Const, 0, \"\"},\n\t\t{\"REG_NONE\", Const, 0, \"\"},\n\t\t{\"REG_QWORD\", Const, 0, \"\"},\n\t\t{\"REG_QWORD_LITTLE_ENDIAN\", Const, 0, \"\"},\n\t\t{\"REG_RESOURCE_LIST\", Const, 0, \"\"},\n\t\t{\"REG_RESOURCE_REQUIREMENTS_LIST\", Const, 0, \"\"},\n\t\t{\"REG_SZ\", Const, 0, \"\"},\n\t\t{\"RLIMIT_AS\", Const, 0, \"\"},\n\t\t{\"RLIMIT_CORE\", Const, 0, \"\"},\n\t\t{\"RLIMIT_CPU\", Const, 0, \"\"},\n\t\t{\"RLIMIT_CPU_USAGE_MONITOR\", Const, 16, \"\"},\n\t\t{\"RLIMIT_DATA\", Const, 0, \"\"},\n\t\t{\"RLIMIT_FSIZE\", Const, 0, \"\"},\n\t\t{\"RLIMIT_NOFILE\", Const, 0, \"\"},\n\t\t{\"RLIMIT_STACK\", Const, 0, \"\"},\n\t\t{\"RLIM_INFINITY\", Const, 0, \"\"},\n\t\t{\"RTAX_ADVMSS\", Const, 0, \"\"},\n\t\t{\"RTAX_AUTHOR\", Const, 0, \"\"},\n\t\t{\"RTAX_BRD\", Const, 0, \"\"},\n\t\t{\"RTAX_CWND\", Const, 0, \"\"},\n\t\t{\"RTAX_DST\", Const, 0, \"\"},\n\t\t{\"RTAX_FEATURES\", Const, 0, \"\"},\n\t\t{\"RTAX_FEATURE_ALLFRAG\", Const, 0, \"\"},\n\t\t{\"RTAX_FEATURE_ECN\", Const, 0, \"\"},\n\t\t{\"RTAX_FEATURE_SACK\", Const, 0, \"\"},\n\t\t{\"RTAX_FEATURE_TIMESTAMP\", Const, 0, \"\"},\n\t\t{\"RTAX_GATEWAY\", Const, 0, \"\"},\n\t\t{\"RTAX_GENMASK\", Const, 0, \"\"},\n\t\t{\"RTAX_HOPLIMIT\", Const, 0, \"\"},\n\t\t{\"RTAX_IFA\", Const, 0, \"\"},\n\t\t{\"RTAX_IFP\", Const, 0, \"\"},\n\t\t{\"RTAX_INITCWND\", Const, 0, \"\"},\n\t\t{\"RTAX_INITRWND\", Const, 0, \"\"},\n\t\t{\"RTAX_LABEL\", Const, 1, \"\"},\n\t\t{\"RTAX_LOCK\", Const, 0, \"\"},\n\t\t{\"RTAX_MAX\", Const, 0, \"\"},\n\t\t{\"RTAX_MTU\", Const, 0, \"\"},\n\t\t{\"RTAX_NETMASK\", Const, 0, \"\"},\n\t\t{\"RTAX_REORDERING\", Const, 0, \"\"},\n\t\t{\"RTAX_RTO_MIN\", Const, 0, \"\"},\n\t\t{\"RTAX_RTT\", Const, 0, \"\"},\n\t\t{\"RTAX_RTTVAR\", Const, 0, \"\"},\n\t\t{\"RTAX_SRC\", Const, 1, \"\"},\n\t\t{\"RTAX_SRCMASK\", Const, 1, \"\"},\n\t\t{\"RTAX_SSTHRESH\", Const, 0, \"\"},\n\t\t{\"RTAX_TAG\", Const, 1, \"\"},\n\t\t{\"RTAX_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RTAX_WINDOW\", Const, 0, \"\"},\n\t\t{\"RTA_ALIGNTO\", Const, 0, \"\"},\n\t\t{\"RTA_AUTHOR\", Const, 0, \"\"},\n\t\t{\"RTA_BRD\", Const, 0, \"\"},\n\t\t{\"RTA_CACHEINFO\", Const, 0, \"\"},\n\t\t{\"RTA_DST\", Const, 0, \"\"},\n\t\t{\"RTA_FLOW\", Const, 0, \"\"},\n\t\t{\"RTA_GATEWAY\", Const, 0, \"\"},\n\t\t{\"RTA_GENMASK\", Const, 0, \"\"},\n\t\t{\"RTA_IFA\", Const, 0, \"\"},\n\t\t{\"RTA_IFP\", Const, 0, \"\"},\n\t\t{\"RTA_IIF\", Const, 0, \"\"},\n\t\t{\"RTA_LABEL\", Const, 1, \"\"},\n\t\t{\"RTA_MAX\", Const, 0, \"\"},\n\t\t{\"RTA_METRICS\", Const, 0, \"\"},\n\t\t{\"RTA_MULTIPATH\", Const, 0, \"\"},\n\t\t{\"RTA_NETMASK\", Const, 0, \"\"},\n\t\t{\"RTA_OIF\", Const, 0, \"\"},\n\t\t{\"RTA_PREFSRC\", Const, 0, \"\"},\n\t\t{\"RTA_PRIORITY\", Const, 0, \"\"},\n\t\t{\"RTA_SRC\", Const, 0, \"\"},\n\t\t{\"RTA_SRCMASK\", Const, 1, \"\"},\n\t\t{\"RTA_TABLE\", Const, 0, \"\"},\n\t\t{\"RTA_TAG\", Const, 1, \"\"},\n\t\t{\"RTA_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RTCF_DIRECTSRC\", Const, 0, \"\"},\n\t\t{\"RTCF_DOREDIRECT\", Const, 0, \"\"},\n\t\t{\"RTCF_LOG\", Const, 0, \"\"},\n\t\t{\"RTCF_MASQ\", Const, 0, \"\"},\n\t\t{\"RTCF_NAT\", Const, 0, \"\"},\n\t\t{\"RTCF_VALVE\", Const, 0, \"\"},\n\t\t{\"RTF_ADDRCLASSMASK\", Const, 0, \"\"},\n\t\t{\"RTF_ADDRCONF\", Const, 0, \"\"},\n\t\t{\"RTF_ALLONLINK\", Const, 0, \"\"},\n\t\t{\"RTF_ANNOUNCE\", Const, 1, \"\"},\n\t\t{\"RTF_BLACKHOLE\", Const, 0, \"\"},\n\t\t{\"RTF_BROADCAST\", Const, 0, \"\"},\n\t\t{\"RTF_CACHE\", Const, 0, \"\"},\n\t\t{\"RTF_CLONED\", Const, 1, \"\"},\n\t\t{\"RTF_CLONING\", Const, 0, \"\"},\n\t\t{\"RTF_CONDEMNED\", Const, 0, \"\"},\n\t\t{\"RTF_DEFAULT\", Const, 0, \"\"},\n\t\t{\"RTF_DELCLONE\", Const, 0, \"\"},\n\t\t{\"RTF_DONE\", Const, 0, \"\"},\n\t\t{\"RTF_DYNAMIC\", Const, 0, \"\"},\n\t\t{\"RTF_FLOW\", Const, 0, \"\"},\n\t\t{\"RTF_FMASK\", Const, 0, \"\"},\n\t\t{\"RTF_GATEWAY\", Const, 0, \"\"},\n\t\t{\"RTF_GWFLAG_COMPAT\", Const, 3, \"\"},\n\t\t{\"RTF_HOST\", Const, 0, \"\"},\n\t\t{\"RTF_IFREF\", Const, 0, \"\"},\n\t\t{\"RTF_IFSCOPE\", Const, 0, \"\"},\n\t\t{\"RTF_INTERFACE\", Const, 0, \"\"},\n\t\t{\"RTF_IRTT\", Const, 0, \"\"},\n\t\t{\"RTF_LINKRT\", Const, 0, \"\"},\n\t\t{\"RTF_LLDATA\", Const, 0, \"\"},\n\t\t{\"RTF_LLINFO\", Const, 0, \"\"},\n\t\t{\"RTF_LOCAL\", Const, 0, \"\"},\n\t\t{\"RTF_MASK\", Const, 1, \"\"},\n\t\t{\"RTF_MODIFIED\", Const, 0, \"\"},\n\t\t{\"RTF_MPATH\", Const, 1, \"\"},\n\t\t{\"RTF_MPLS\", Const, 1, \"\"},\n\t\t{\"RTF_MSS\", Const, 0, \"\"},\n\t\t{\"RTF_MTU\", Const, 0, \"\"},\n\t\t{\"RTF_MULTICAST\", Const, 0, \"\"},\n\t\t{\"RTF_NAT\", Const, 0, \"\"},\n\t\t{\"RTF_NOFORWARD\", Const, 0, \"\"},\n\t\t{\"RTF_NONEXTHOP\", Const, 0, \"\"},\n\t\t{\"RTF_NOPMTUDISC\", Const, 0, \"\"},\n\t\t{\"RTF_PERMANENT_ARP\", Const, 1, \"\"},\n\t\t{\"RTF_PINNED\", Const, 0, \"\"},\n\t\t{\"RTF_POLICY\", Const, 0, \"\"},\n\t\t{\"RTF_PRCLONING\", Const, 0, \"\"},\n\t\t{\"RTF_PROTO1\", Const, 0, \"\"},\n\t\t{\"RTF_PROTO2\", Const, 0, \"\"},\n\t\t{\"RTF_PROTO3\", Const, 0, \"\"},\n\t\t{\"RTF_PROXY\", Const, 16, \"\"},\n\t\t{\"RTF_REINSTATE\", Const, 0, \"\"},\n\t\t{\"RTF_REJECT\", Const, 0, \"\"},\n\t\t{\"RTF_RNH_LOCKED\", Const, 0, \"\"},\n\t\t{\"RTF_ROUTER\", Const, 16, \"\"},\n\t\t{\"RTF_SOURCE\", Const, 1, \"\"},\n\t\t{\"RTF_SRC\", Const, 1, \"\"},\n\t\t{\"RTF_STATIC\", Const, 0, \"\"},\n\t\t{\"RTF_STICKY\", Const, 0, \"\"},\n\t\t{\"RTF_THROW\", Const, 0, \"\"},\n\t\t{\"RTF_TUNNEL\", Const, 1, \"\"},\n\t\t{\"RTF_UP\", Const, 0, \"\"},\n\t\t{\"RTF_USETRAILERS\", Const, 1, \"\"},\n\t\t{\"RTF_WASCLONED\", Const, 0, \"\"},\n\t\t{\"RTF_WINDOW\", Const, 0, \"\"},\n\t\t{\"RTF_XRESOLVE\", Const, 0, \"\"},\n\t\t{\"RTM_ADD\", Const, 0, \"\"},\n\t\t{\"RTM_BASE\", Const, 0, \"\"},\n\t\t{\"RTM_CHANGE\", Const, 0, \"\"},\n\t\t{\"RTM_CHGADDR\", Const, 1, \"\"},\n\t\t{\"RTM_DELACTION\", Const, 0, \"\"},\n\t\t{\"RTM_DELADDR\", Const, 0, \"\"},\n\t\t{\"RTM_DELADDRLABEL\", Const, 0, \"\"},\n\t\t{\"RTM_DELETE\", Const, 0, \"\"},\n\t\t{\"RTM_DELLINK\", Const, 0, \"\"},\n\t\t{\"RTM_DELMADDR\", Const, 0, \"\"},\n\t\t{\"RTM_DELNEIGH\", Const, 0, \"\"},\n\t\t{\"RTM_DELQDISC\", Const, 0, \"\"},\n\t\t{\"RTM_DELROUTE\", Const, 0, \"\"},\n\t\t{\"RTM_DELRULE\", Const, 0, \"\"},\n\t\t{\"RTM_DELTCLASS\", Const, 0, \"\"},\n\t\t{\"RTM_DELTFILTER\", Const, 0, \"\"},\n\t\t{\"RTM_DESYNC\", Const, 1, \"\"},\n\t\t{\"RTM_F_CLONED\", Const, 0, \"\"},\n\t\t{\"RTM_F_EQUALIZE\", Const, 0, \"\"},\n\t\t{\"RTM_F_NOTIFY\", Const, 0, \"\"},\n\t\t{\"RTM_F_PREFIX\", Const, 0, \"\"},\n\t\t{\"RTM_GET\", Const, 0, \"\"},\n\t\t{\"RTM_GET2\", Const, 0, \"\"},\n\t\t{\"RTM_GETACTION\", Const, 0, \"\"},\n\t\t{\"RTM_GETADDR\", Const, 0, \"\"},\n\t\t{\"RTM_GETADDRLABEL\", Const, 0, \"\"},\n\t\t{\"RTM_GETANYCAST\", Const, 0, \"\"},\n\t\t{\"RTM_GETDCB\", Const, 0, \"\"},\n\t\t{\"RTM_GETLINK\", Const, 0, \"\"},\n\t\t{\"RTM_GETMULTICAST\", Const, 0, \"\"},\n\t\t{\"RTM_GETNEIGH\", Const, 0, \"\"},\n\t\t{\"RTM_GETNEIGHTBL\", Const, 0, \"\"},\n\t\t{\"RTM_GETQDISC\", Const, 0, \"\"},\n\t\t{\"RTM_GETROUTE\", Const, 0, \"\"},\n\t\t{\"RTM_GETRULE\", Const, 0, \"\"},\n\t\t{\"RTM_GETTCLASS\", Const, 0, \"\"},\n\t\t{\"RTM_GETTFILTER\", Const, 0, \"\"},\n\t\t{\"RTM_IEEE80211\", Const, 0, \"\"},\n\t\t{\"RTM_IFANNOUNCE\", Const, 0, \"\"},\n\t\t{\"RTM_IFINFO\", Const, 0, \"\"},\n\t\t{\"RTM_IFINFO2\", Const, 0, \"\"},\n\t\t{\"RTM_LLINFO_UPD\", Const, 1, \"\"},\n\t\t{\"RTM_LOCK\", Const, 0, \"\"},\n\t\t{\"RTM_LOSING\", Const, 0, \"\"},\n\t\t{\"RTM_MAX\", Const, 0, \"\"},\n\t\t{\"RTM_MAXSIZE\", Const, 1, \"\"},\n\t\t{\"RTM_MISS\", Const, 0, \"\"},\n\t\t{\"RTM_NEWACTION\", Const, 0, \"\"},\n\t\t{\"RTM_NEWADDR\", Const, 0, \"\"},\n\t\t{\"RTM_NEWADDRLABEL\", Const, 0, \"\"},\n\t\t{\"RTM_NEWLINK\", Const, 0, \"\"},\n\t\t{\"RTM_NEWMADDR\", Const, 0, \"\"},\n\t\t{\"RTM_NEWMADDR2\", Const, 0, \"\"},\n\t\t{\"RTM_NEWNDUSEROPT\", Const, 0, \"\"},\n\t\t{\"RTM_NEWNEIGH\", Const, 0, \"\"},\n\t\t{\"RTM_NEWNEIGHTBL\", Const, 0, \"\"},\n\t\t{\"RTM_NEWPREFIX\", Const, 0, \"\"},\n\t\t{\"RTM_NEWQDISC\", Const, 0, \"\"},\n\t\t{\"RTM_NEWROUTE\", Const, 0, \"\"},\n\t\t{\"RTM_NEWRULE\", Const, 0, \"\"},\n\t\t{\"RTM_NEWTCLASS\", Const, 0, \"\"},\n\t\t{\"RTM_NEWTFILTER\", Const, 0, \"\"},\n\t\t{\"RTM_NR_FAMILIES\", Const, 0, \"\"},\n\t\t{\"RTM_NR_MSGTYPES\", Const, 0, \"\"},\n\t\t{\"RTM_OIFINFO\", Const, 1, \"\"},\n\t\t{\"RTM_OLDADD\", Const, 0, \"\"},\n\t\t{\"RTM_OLDDEL\", Const, 0, \"\"},\n\t\t{\"RTM_OOIFINFO\", Const, 1, \"\"},\n\t\t{\"RTM_REDIRECT\", Const, 0, \"\"},\n\t\t{\"RTM_RESOLVE\", Const, 0, \"\"},\n\t\t{\"RTM_RTTUNIT\", Const, 0, \"\"},\n\t\t{\"RTM_SETDCB\", Const, 0, \"\"},\n\t\t{\"RTM_SETGATE\", Const, 1, \"\"},\n\t\t{\"RTM_SETLINK\", Const, 0, \"\"},\n\t\t{\"RTM_SETNEIGHTBL\", Const, 0, \"\"},\n\t\t{\"RTM_VERSION\", Const, 0, \"\"},\n\t\t{\"RTNH_ALIGNTO\", Const, 0, \"\"},\n\t\t{\"RTNH_F_DEAD\", Const, 0, \"\"},\n\t\t{\"RTNH_F_ONLINK\", Const, 0, \"\"},\n\t\t{\"RTNH_F_PERVASIVE\", Const, 0, \"\"},\n\t\t{\"RTNLGRP_IPV4_IFADDR\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV4_MROUTE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV4_ROUTE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV4_RULE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_IFADDR\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_IFINFO\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_MROUTE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_PREFIX\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_ROUTE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_IPV6_RULE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_LINK\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_ND_USEROPT\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_NEIGH\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_NONE\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_NOTIFY\", Const, 1, \"\"},\n\t\t{\"RTNLGRP_TC\", Const, 1, \"\"},\n\t\t{\"RTN_ANYCAST\", Const, 0, \"\"},\n\t\t{\"RTN_BLACKHOLE\", Const, 0, \"\"},\n\t\t{\"RTN_BROADCAST\", Const, 0, \"\"},\n\t\t{\"RTN_LOCAL\", Const, 0, \"\"},\n\t\t{\"RTN_MAX\", Const, 0, \"\"},\n\t\t{\"RTN_MULTICAST\", Const, 0, \"\"},\n\t\t{\"RTN_NAT\", Const, 0, \"\"},\n\t\t{\"RTN_PROHIBIT\", Const, 0, \"\"},\n\t\t{\"RTN_THROW\", Const, 0, \"\"},\n\t\t{\"RTN_UNICAST\", Const, 0, \"\"},\n\t\t{\"RTN_UNREACHABLE\", Const, 0, \"\"},\n\t\t{\"RTN_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RTN_XRESOLVE\", Const, 0, \"\"},\n\t\t{\"RTPROT_BIRD\", Const, 0, \"\"},\n\t\t{\"RTPROT_BOOT\", Const, 0, \"\"},\n\t\t{\"RTPROT_DHCP\", Const, 0, \"\"},\n\t\t{\"RTPROT_DNROUTED\", Const, 0, \"\"},\n\t\t{\"RTPROT_GATED\", Const, 0, \"\"},\n\t\t{\"RTPROT_KERNEL\", Const, 0, \"\"},\n\t\t{\"RTPROT_MRT\", Const, 0, \"\"},\n\t\t{\"RTPROT_NTK\", Const, 0, \"\"},\n\t\t{\"RTPROT_RA\", Const, 0, \"\"},\n\t\t{\"RTPROT_REDIRECT\", Const, 0, \"\"},\n\t\t{\"RTPROT_STATIC\", Const, 0, \"\"},\n\t\t{\"RTPROT_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RTPROT_XORP\", Const, 0, \"\"},\n\t\t{\"RTPROT_ZEBRA\", Const, 0, \"\"},\n\t\t{\"RTV_EXPIRE\", Const, 0, \"\"},\n\t\t{\"RTV_HOPCOUNT\", Const, 0, \"\"},\n\t\t{\"RTV_MTU\", Const, 0, \"\"},\n\t\t{\"RTV_RPIPE\", Const, 0, \"\"},\n\t\t{\"RTV_RTT\", Const, 0, \"\"},\n\t\t{\"RTV_RTTVAR\", Const, 0, \"\"},\n\t\t{\"RTV_SPIPE\", Const, 0, \"\"},\n\t\t{\"RTV_SSTHRESH\", Const, 0, \"\"},\n\t\t{\"RTV_WEIGHT\", Const, 0, \"\"},\n\t\t{\"RT_CACHING_CONTEXT\", Const, 1, \"\"},\n\t\t{\"RT_CLASS_DEFAULT\", Const, 0, \"\"},\n\t\t{\"RT_CLASS_LOCAL\", Const, 0, \"\"},\n\t\t{\"RT_CLASS_MAIN\", Const, 0, \"\"},\n\t\t{\"RT_CLASS_MAX\", Const, 0, \"\"},\n\t\t{\"RT_CLASS_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RT_DEFAULT_FIB\", Const, 1, \"\"},\n\t\t{\"RT_NORTREF\", Const, 1, \"\"},\n\t\t{\"RT_SCOPE_HOST\", Const, 0, \"\"},\n\t\t{\"RT_SCOPE_LINK\", Const, 0, \"\"},\n\t\t{\"RT_SCOPE_NOWHERE\", Const, 0, \"\"},\n\t\t{\"RT_SCOPE_SITE\", Const, 0, \"\"},\n\t\t{\"RT_SCOPE_UNIVERSE\", Const, 0, \"\"},\n\t\t{\"RT_TABLEID_MAX\", Const, 1, \"\"},\n\t\t{\"RT_TABLE_COMPAT\", Const, 0, \"\"},\n\t\t{\"RT_TABLE_DEFAULT\", Const, 0, \"\"},\n\t\t{\"RT_TABLE_LOCAL\", Const, 0, \"\"},\n\t\t{\"RT_TABLE_MAIN\", Const, 0, \"\"},\n\t\t{\"RT_TABLE_MAX\", Const, 0, \"\"},\n\t\t{\"RT_TABLE_UNSPEC\", Const, 0, \"\"},\n\t\t{\"RUSAGE_CHILDREN\", Const, 0, \"\"},\n\t\t{\"RUSAGE_SELF\", Const, 0, \"\"},\n\t\t{\"RUSAGE_THREAD\", Const, 0, \"\"},\n\t\t{\"Radvisory_t\", Type, 0, \"\"},\n\t\t{\"Radvisory_t.Count\", Field, 0, \"\"},\n\t\t{\"Radvisory_t.Offset\", Field, 0, \"\"},\n\t\t{\"Radvisory_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"RawConn\", Type, 9, \"\"},\n\t\t{\"RawSockaddr\", Type, 0, \"\"},\n\t\t{\"RawSockaddr.Data\", Field, 0, \"\"},\n\t\t{\"RawSockaddr.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddr.Len\", Field, 0, \"\"},\n\t\t{\"RawSockaddrAny\", Type, 0, \"\"},\n\t\t{\"RawSockaddrAny.Addr\", Field, 0, \"\"},\n\t\t{\"RawSockaddrAny.Pad\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink\", Type, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Alen\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Data\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Index\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Len\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Nlen\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Pad_cgo_0\", Field, 2, \"\"},\n\t\t{\"RawSockaddrDatalink.Slen\", Field, 0, \"\"},\n\t\t{\"RawSockaddrDatalink.Type\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet4\", Type, 0, \"\"},\n\t\t{\"RawSockaddrInet4.Addr\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet4.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet4.Len\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet4.Port\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet4.Zero\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6\", Type, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Addr\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Flowinfo\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Len\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Port\", Field, 0, \"\"},\n\t\t{\"RawSockaddrInet6.Scope_id\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer\", Type, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Addr\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Halen\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Hatype\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Ifindex\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Pkttype\", Field, 0, \"\"},\n\t\t{\"RawSockaddrLinklayer.Protocol\", Field, 0, \"\"},\n\t\t{\"RawSockaddrNetlink\", Type, 0, \"\"},\n\t\t{\"RawSockaddrNetlink.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrNetlink.Groups\", Field, 0, \"\"},\n\t\t{\"RawSockaddrNetlink.Pad\", Field, 0, \"\"},\n\t\t{\"RawSockaddrNetlink.Pid\", Field, 0, \"\"},\n\t\t{\"RawSockaddrUnix\", Type, 0, \"\"},\n\t\t{\"RawSockaddrUnix.Family\", Field, 0, \"\"},\n\t\t{\"RawSockaddrUnix.Len\", Field, 0, \"\"},\n\t\t{\"RawSockaddrUnix.Pad_cgo_0\", Field, 2, \"\"},\n\t\t{\"RawSockaddrUnix.Path\", Field, 0, \"\"},\n\t\t{\"RawSyscall\", Func, 0, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"RawSyscall6\", Func, 0, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"Read\", Func, 0, \"func(fd int, p []byte) (n int, err error)\"},\n\t\t{\"ReadConsole\", Func, 1, \"\"},\n\t\t{\"ReadDirectoryChanges\", Func, 0, \"\"},\n\t\t{\"ReadDirent\", Func, 0, \"func(fd int, buf []byte) (n int, err error)\"},\n\t\t{\"ReadFile\", Func, 0, \"\"},\n\t\t{\"Readlink\", Func, 0, \"func(path string, buf []byte) (n int, err error)\"},\n\t\t{\"Reboot\", Func, 0, \"func(cmd int) (err error)\"},\n\t\t{\"Recvfrom\", Func, 0, \"func(fd int, p []byte, flags int) (n int, from Sockaddr, err error)\"},\n\t\t{\"Recvmsg\", Func, 0, \"func(fd int, p []byte, oob []byte, flags int) (n int, oobn int, recvflags int, from Sockaddr, err error)\"},\n\t\t{\"RegCloseKey\", Func, 0, \"\"},\n\t\t{\"RegEnumKeyEx\", Func, 0, \"\"},\n\t\t{\"RegOpenKeyEx\", Func, 0, \"\"},\n\t\t{\"RegQueryInfoKey\", Func, 0, \"\"},\n\t\t{\"RegQueryValueEx\", Func, 0, \"\"},\n\t\t{\"RemoveDirectory\", Func, 0, \"\"},\n\t\t{\"Removexattr\", Func, 1, \"func(path string, attr string) (err error)\"},\n\t\t{\"Rename\", Func, 0, \"func(oldpath string, newpath string) (err error)\"},\n\t\t{\"Renameat\", Func, 0, \"func(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)\"},\n\t\t{\"Revoke\", Func, 0, \"\"},\n\t\t{\"Rlimit\", Type, 0, \"\"},\n\t\t{\"Rlimit.Cur\", Field, 0, \"\"},\n\t\t{\"Rlimit.Max\", Field, 0, \"\"},\n\t\t{\"Rmdir\", Func, 0, \"func(path string) error\"},\n\t\t{\"RouteMessage\", Type, 0, \"\"},\n\t\t{\"RouteMessage.Data\", Field, 0, \"\"},\n\t\t{\"RouteMessage.Header\", Field, 0, \"\"},\n\t\t{\"RouteRIB\", Func, 0, \"\"},\n\t\t{\"RoutingMessage\", Type, 14, \"\"},\n\t\t{\"RtAttr\", Type, 0, \"\"},\n\t\t{\"RtAttr.Len\", Field, 0, \"\"},\n\t\t{\"RtAttr.Type\", Field, 0, \"\"},\n\t\t{\"RtGenmsg\", Type, 0, \"\"},\n\t\t{\"RtGenmsg.Family\", Field, 0, \"\"},\n\t\t{\"RtMetrics\", Type, 0, \"\"},\n\t\t{\"RtMetrics.Expire\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Filler\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Hopcount\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Locks\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Mtu\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Pad\", Field, 3, \"\"},\n\t\t{\"RtMetrics.Pksent\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Recvpipe\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Refcnt\", Field, 2, \"\"},\n\t\t{\"RtMetrics.Rtt\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Rttvar\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Sendpipe\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Ssthresh\", Field, 0, \"\"},\n\t\t{\"RtMetrics.Weight\", Field, 0, \"\"},\n\t\t{\"RtMsg\", Type, 0, \"\"},\n\t\t{\"RtMsg.Dst_len\", Field, 0, \"\"},\n\t\t{\"RtMsg.Family\", Field, 0, \"\"},\n\t\t{\"RtMsg.Flags\", Field, 0, \"\"},\n\t\t{\"RtMsg.Protocol\", Field, 0, \"\"},\n\t\t{\"RtMsg.Scope\", Field, 0, \"\"},\n\t\t{\"RtMsg.Src_len\", Field, 0, \"\"},\n\t\t{\"RtMsg.Table\", Field, 0, \"\"},\n\t\t{\"RtMsg.Tos\", Field, 0, \"\"},\n\t\t{\"RtMsg.Type\", Field, 0, \"\"},\n\t\t{\"RtMsghdr\", Type, 0, \"\"},\n\t\t{\"RtMsghdr.Addrs\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Errno\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Flags\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Fmask\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Hdrlen\", Field, 2, \"\"},\n\t\t{\"RtMsghdr.Index\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Inits\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Mpls\", Field, 2, \"\"},\n\t\t{\"RtMsghdr.Msglen\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Pad_cgo_1\", Field, 2, \"\"},\n\t\t{\"RtMsghdr.Pid\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Priority\", Field, 2, \"\"},\n\t\t{\"RtMsghdr.Rmx\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Seq\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Tableid\", Field, 2, \"\"},\n\t\t{\"RtMsghdr.Type\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Use\", Field, 0, \"\"},\n\t\t{\"RtMsghdr.Version\", Field, 0, \"\"},\n\t\t{\"RtNexthop\", Type, 0, \"\"},\n\t\t{\"RtNexthop.Flags\", Field, 0, \"\"},\n\t\t{\"RtNexthop.Hops\", Field, 0, \"\"},\n\t\t{\"RtNexthop.Ifindex\", Field, 0, \"\"},\n\t\t{\"RtNexthop.Len\", Field, 0, \"\"},\n\t\t{\"Rusage\", Type, 0, \"\"},\n\t\t{\"Rusage.CreationTime\", Field, 0, \"\"},\n\t\t{\"Rusage.ExitTime\", Field, 0, \"\"},\n\t\t{\"Rusage.Idrss\", Field, 0, \"\"},\n\t\t{\"Rusage.Inblock\", Field, 0, \"\"},\n\t\t{\"Rusage.Isrss\", Field, 0, \"\"},\n\t\t{\"Rusage.Ixrss\", Field, 0, \"\"},\n\t\t{\"Rusage.KernelTime\", Field, 0, \"\"},\n\t\t{\"Rusage.Majflt\", Field, 0, \"\"},\n\t\t{\"Rusage.Maxrss\", Field, 0, \"\"},\n\t\t{\"Rusage.Minflt\", Field, 0, \"\"},\n\t\t{\"Rusage.Msgrcv\", Field, 0, \"\"},\n\t\t{\"Rusage.Msgsnd\", Field, 0, \"\"},\n\t\t{\"Rusage.Nivcsw\", Field, 0, \"\"},\n\t\t{\"Rusage.Nsignals\", Field, 0, \"\"},\n\t\t{\"Rusage.Nswap\", Field, 0, \"\"},\n\t\t{\"Rusage.Nvcsw\", Field, 0, \"\"},\n\t\t{\"Rusage.Oublock\", Field, 0, \"\"},\n\t\t{\"Rusage.Stime\", Field, 0, \"\"},\n\t\t{\"Rusage.UserTime\", Field, 0, \"\"},\n\t\t{\"Rusage.Utime\", Field, 0, \"\"},\n\t\t{\"SCM_BINTIME\", Const, 0, \"\"},\n\t\t{\"SCM_CREDENTIALS\", Const, 0, \"\"},\n\t\t{\"SCM_CREDS\", Const, 0, \"\"},\n\t\t{\"SCM_RIGHTS\", Const, 0, \"\"},\n\t\t{\"SCM_TIMESTAMP\", Const, 0, \"\"},\n\t\t{\"SCM_TIMESTAMPING\", Const, 0, \"\"},\n\t\t{\"SCM_TIMESTAMPNS\", Const, 0, \"\"},\n\t\t{\"SCM_TIMESTAMP_MONOTONIC\", Const, 0, \"\"},\n\t\t{\"SHUT_RD\", Const, 0, \"\"},\n\t\t{\"SHUT_RDWR\", Const, 0, \"\"},\n\t\t{\"SHUT_WR\", Const, 0, \"\"},\n\t\t{\"SID\", Type, 0, \"\"},\n\t\t{\"SIDAndAttributes\", Type, 0, \"\"},\n\t\t{\"SIDAndAttributes.Attributes\", Field, 0, \"\"},\n\t\t{\"SIDAndAttributes.Sid\", Field, 0, \"\"},\n\t\t{\"SIGABRT\", Const, 0, \"\"},\n\t\t{\"SIGALRM\", Const, 0, \"\"},\n\t\t{\"SIGBUS\", Const, 0, \"\"},\n\t\t{\"SIGCHLD\", Const, 0, \"\"},\n\t\t{\"SIGCLD\", Const, 0, \"\"},\n\t\t{\"SIGCONT\", Const, 0, \"\"},\n\t\t{\"SIGEMT\", Const, 0, \"\"},\n\t\t{\"SIGFPE\", Const, 0, \"\"},\n\t\t{\"SIGHUP\", Const, 0, \"\"},\n\t\t{\"SIGILL\", Const, 0, \"\"},\n\t\t{\"SIGINFO\", Const, 0, \"\"},\n\t\t{\"SIGINT\", Const, 0, \"\"},\n\t\t{\"SIGIO\", Const, 0, \"\"},\n\t\t{\"SIGIOT\", Const, 0, \"\"},\n\t\t{\"SIGKILL\", Const, 0, \"\"},\n\t\t{\"SIGLIBRT\", Const, 1, \"\"},\n\t\t{\"SIGLWP\", Const, 0, \"\"},\n\t\t{\"SIGPIPE\", Const, 0, \"\"},\n\t\t{\"SIGPOLL\", Const, 0, \"\"},\n\t\t{\"SIGPROF\", Const, 0, \"\"},\n\t\t{\"SIGPWR\", Const, 0, \"\"},\n\t\t{\"SIGQUIT\", Const, 0, \"\"},\n\t\t{\"SIGSEGV\", Const, 0, \"\"},\n\t\t{\"SIGSTKFLT\", Const, 0, \"\"},\n\t\t{\"SIGSTOP\", Const, 0, \"\"},\n\t\t{\"SIGSYS\", Const, 0, \"\"},\n\t\t{\"SIGTERM\", Const, 0, \"\"},\n\t\t{\"SIGTHR\", Const, 0, \"\"},\n\t\t{\"SIGTRAP\", Const, 0, \"\"},\n\t\t{\"SIGTSTP\", Const, 0, \"\"},\n\t\t{\"SIGTTIN\", Const, 0, \"\"},\n\t\t{\"SIGTTOU\", Const, 0, \"\"},\n\t\t{\"SIGUNUSED\", Const, 0, \"\"},\n\t\t{\"SIGURG\", Const, 0, \"\"},\n\t\t{\"SIGUSR1\", Const, 0, \"\"},\n\t\t{\"SIGUSR2\", Const, 0, \"\"},\n\t\t{\"SIGVTALRM\", Const, 0, \"\"},\n\t\t{\"SIGWINCH\", Const, 0, \"\"},\n\t\t{\"SIGXCPU\", Const, 0, \"\"},\n\t\t{\"SIGXFSZ\", Const, 0, \"\"},\n\t\t{\"SIOCADDDLCI\", Const, 0, \"\"},\n\t\t{\"SIOCADDMULTI\", Const, 0, \"\"},\n\t\t{\"SIOCADDRT\", Const, 0, \"\"},\n\t\t{\"SIOCAIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCAIFGROUP\", Const, 0, \"\"},\n\t\t{\"SIOCALIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCARPIPLL\", Const, 0, \"\"},\n\t\t{\"SIOCATMARK\", Const, 0, \"\"},\n\t\t{\"SIOCAUTOADDR\", Const, 0, \"\"},\n\t\t{\"SIOCAUTONETMASK\", Const, 0, \"\"},\n\t\t{\"SIOCBRDGADD\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGADDS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGARL\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGDADDR\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGDEL\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGDELS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGFLUSH\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGFRL\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGCACHE\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGFD\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGHT\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGIFFLGS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGMA\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGPARAM\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGPRI\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGRL\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGSIFS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGGTO\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGIFS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGRTS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSADDR\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSCACHE\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSFD\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSHT\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSIFCOST\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSIFFLGS\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSIFPRIO\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSMA\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSPRI\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSPROTO\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSTO\", Const, 1, \"\"},\n\t\t{\"SIOCBRDGSTXHC\", Const, 1, \"\"},\n\t\t{\"SIOCDARP\", Const, 0, \"\"},\n\t\t{\"SIOCDELDLCI\", Const, 0, \"\"},\n\t\t{\"SIOCDELMULTI\", Const, 0, \"\"},\n\t\t{\"SIOCDELRT\", Const, 0, \"\"},\n\t\t{\"SIOCDEVPRIVATE\", Const, 0, \"\"},\n\t\t{\"SIOCDIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCDIFGROUP\", Const, 0, \"\"},\n\t\t{\"SIOCDIFPHYADDR\", Const, 0, \"\"},\n\t\t{\"SIOCDLIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCDRARP\", Const, 0, \"\"},\n\t\t{\"SIOCGARP\", Const, 0, \"\"},\n\t\t{\"SIOCGDRVSPEC\", Const, 0, \"\"},\n\t\t{\"SIOCGETKALIVE\", Const, 1, \"\"},\n\t\t{\"SIOCGETLABEL\", Const, 1, \"\"},\n\t\t{\"SIOCGETPFLOW\", Const, 1, \"\"},\n\t\t{\"SIOCGETPFSYNC\", Const, 1, \"\"},\n\t\t{\"SIOCGETSGCNT\", Const, 0, \"\"},\n\t\t{\"SIOCGETVIFCNT\", Const, 0, \"\"},\n\t\t{\"SIOCGETVLAN\", Const, 0, \"\"},\n\t\t{\"SIOCGHIWAT\", Const, 0, \"\"},\n\t\t{\"SIOCGIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFADDRPREF\", Const, 1, \"\"},\n\t\t{\"SIOCGIFALIAS\", Const, 1, \"\"},\n\t\t{\"SIOCGIFALTMTU\", Const, 0, \"\"},\n\t\t{\"SIOCGIFASYNCMAP\", Const, 0, \"\"},\n\t\t{\"SIOCGIFBOND\", Const, 0, \"\"},\n\t\t{\"SIOCGIFBR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFBRDADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFCAP\", Const, 0, \"\"},\n\t\t{\"SIOCGIFCONF\", Const, 0, \"\"},\n\t\t{\"SIOCGIFCOUNT\", Const, 0, \"\"},\n\t\t{\"SIOCGIFDATA\", Const, 1, \"\"},\n\t\t{\"SIOCGIFDESCR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFDEVMTU\", Const, 0, \"\"},\n\t\t{\"SIOCGIFDLT\", Const, 1, \"\"},\n\t\t{\"SIOCGIFDSTADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFENCAP\", Const, 0, \"\"},\n\t\t{\"SIOCGIFFIB\", Const, 1, \"\"},\n\t\t{\"SIOCGIFFLAGS\", Const, 0, \"\"},\n\t\t{\"SIOCGIFGATTR\", Const, 1, \"\"},\n\t\t{\"SIOCGIFGENERIC\", Const, 0, \"\"},\n\t\t{\"SIOCGIFGMEMB\", Const, 0, \"\"},\n\t\t{\"SIOCGIFGROUP\", Const, 0, \"\"},\n\t\t{\"SIOCGIFHARDMTU\", Const, 3, \"\"},\n\t\t{\"SIOCGIFHWADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFINDEX\", Const, 0, \"\"},\n\t\t{\"SIOCGIFKPI\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMAC\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMAP\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMEDIA\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMEM\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMETRIC\", Const, 0, \"\"},\n\t\t{\"SIOCGIFMTU\", Const, 0, \"\"},\n\t\t{\"SIOCGIFNAME\", Const, 0, \"\"},\n\t\t{\"SIOCGIFNETMASK\", Const, 0, \"\"},\n\t\t{\"SIOCGIFPDSTADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFPFLAGS\", Const, 0, \"\"},\n\t\t{\"SIOCGIFPHYS\", Const, 0, \"\"},\n\t\t{\"SIOCGIFPRIORITY\", Const, 1, \"\"},\n\t\t{\"SIOCGIFPSRCADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGIFRDOMAIN\", Const, 1, \"\"},\n\t\t{\"SIOCGIFRTLABEL\", Const, 1, \"\"},\n\t\t{\"SIOCGIFSLAVE\", Const, 0, \"\"},\n\t\t{\"SIOCGIFSTATUS\", Const, 0, \"\"},\n\t\t{\"SIOCGIFTIMESLOT\", Const, 1, \"\"},\n\t\t{\"SIOCGIFTXQLEN\", Const, 0, \"\"},\n\t\t{\"SIOCGIFVLAN\", Const, 0, \"\"},\n\t\t{\"SIOCGIFWAKEFLAGS\", Const, 0, \"\"},\n\t\t{\"SIOCGIFXFLAGS\", Const, 1, \"\"},\n\t\t{\"SIOCGLIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGLIFPHYADDR\", Const, 0, \"\"},\n\t\t{\"SIOCGLIFPHYRTABLE\", Const, 1, \"\"},\n\t\t{\"SIOCGLIFPHYTTL\", Const, 3, \"\"},\n\t\t{\"SIOCGLINKSTR\", Const, 1, \"\"},\n\t\t{\"SIOCGLOWAT\", Const, 0, \"\"},\n\t\t{\"SIOCGPGRP\", Const, 0, \"\"},\n\t\t{\"SIOCGPRIVATE_0\", Const, 0, \"\"},\n\t\t{\"SIOCGPRIVATE_1\", Const, 0, \"\"},\n\t\t{\"SIOCGRARP\", Const, 0, \"\"},\n\t\t{\"SIOCGSPPPPARAMS\", Const, 3, \"\"},\n\t\t{\"SIOCGSTAMP\", Const, 0, \"\"},\n\t\t{\"SIOCGSTAMPNS\", Const, 0, \"\"},\n\t\t{\"SIOCGVH\", Const, 1, \"\"},\n\t\t{\"SIOCGVNETID\", Const, 3, \"\"},\n\t\t{\"SIOCIFCREATE\", Const, 0, \"\"},\n\t\t{\"SIOCIFCREATE2\", Const, 0, \"\"},\n\t\t{\"SIOCIFDESTROY\", Const, 0, \"\"},\n\t\t{\"SIOCIFGCLONERS\", Const, 0, \"\"},\n\t\t{\"SIOCINITIFADDR\", Const, 1, \"\"},\n\t\t{\"SIOCPROTOPRIVATE\", Const, 0, \"\"},\n\t\t{\"SIOCRSLVMULTI\", Const, 0, \"\"},\n\t\t{\"SIOCRTMSG\", Const, 0, \"\"},\n\t\t{\"SIOCSARP\", Const, 0, \"\"},\n\t\t{\"SIOCSDRVSPEC\", Const, 0, \"\"},\n\t\t{\"SIOCSETKALIVE\", Const, 1, \"\"},\n\t\t{\"SIOCSETLABEL\", Const, 1, \"\"},\n\t\t{\"SIOCSETPFLOW\", Const, 1, \"\"},\n\t\t{\"SIOCSETPFSYNC\", Const, 1, \"\"},\n\t\t{\"SIOCSETVLAN\", Const, 0, \"\"},\n\t\t{\"SIOCSHIWAT\", Const, 0, \"\"},\n\t\t{\"SIOCSIFADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFADDRPREF\", Const, 1, \"\"},\n\t\t{\"SIOCSIFALTMTU\", Const, 0, \"\"},\n\t\t{\"SIOCSIFASYNCMAP\", Const, 0, \"\"},\n\t\t{\"SIOCSIFBOND\", Const, 0, \"\"},\n\t\t{\"SIOCSIFBR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFBRDADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFCAP\", Const, 0, \"\"},\n\t\t{\"SIOCSIFDESCR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFDSTADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFENCAP\", Const, 0, \"\"},\n\t\t{\"SIOCSIFFIB\", Const, 1, \"\"},\n\t\t{\"SIOCSIFFLAGS\", Const, 0, \"\"},\n\t\t{\"SIOCSIFGATTR\", Const, 1, \"\"},\n\t\t{\"SIOCSIFGENERIC\", Const, 0, \"\"},\n\t\t{\"SIOCSIFHWADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFHWBROADCAST\", Const, 0, \"\"},\n\t\t{\"SIOCSIFKPI\", Const, 0, \"\"},\n\t\t{\"SIOCSIFLINK\", Const, 0, \"\"},\n\t\t{\"SIOCSIFLLADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMAC\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMAP\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMEDIA\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMEM\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMETRIC\", Const, 0, \"\"},\n\t\t{\"SIOCSIFMTU\", Const, 0, \"\"},\n\t\t{\"SIOCSIFNAME\", Const, 0, \"\"},\n\t\t{\"SIOCSIFNETMASK\", Const, 0, \"\"},\n\t\t{\"SIOCSIFPFLAGS\", Const, 0, \"\"},\n\t\t{\"SIOCSIFPHYADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSIFPHYS\", Const, 0, \"\"},\n\t\t{\"SIOCSIFPRIORITY\", Const, 1, \"\"},\n\t\t{\"SIOCSIFRDOMAIN\", Const, 1, \"\"},\n\t\t{\"SIOCSIFRTLABEL\", Const, 1, \"\"},\n\t\t{\"SIOCSIFRVNET\", Const, 0, \"\"},\n\t\t{\"SIOCSIFSLAVE\", Const, 0, \"\"},\n\t\t{\"SIOCSIFTIMESLOT\", Const, 1, \"\"},\n\t\t{\"SIOCSIFTXQLEN\", Const, 0, \"\"},\n\t\t{\"SIOCSIFVLAN\", Const, 0, \"\"},\n\t\t{\"SIOCSIFVNET\", Const, 0, \"\"},\n\t\t{\"SIOCSIFXFLAGS\", Const, 1, \"\"},\n\t\t{\"SIOCSLIFPHYADDR\", Const, 0, \"\"},\n\t\t{\"SIOCSLIFPHYRTABLE\", Const, 1, \"\"},\n\t\t{\"SIOCSLIFPHYTTL\", Const, 3, \"\"},\n\t\t{\"SIOCSLINKSTR\", Const, 1, \"\"},\n\t\t{\"SIOCSLOWAT\", Const, 0, \"\"},\n\t\t{\"SIOCSPGRP\", Const, 0, \"\"},\n\t\t{\"SIOCSRARP\", Const, 0, \"\"},\n\t\t{\"SIOCSSPPPPARAMS\", Const, 3, \"\"},\n\t\t{\"SIOCSVH\", Const, 1, \"\"},\n\t\t{\"SIOCSVNETID\", Const, 3, \"\"},\n\t\t{\"SIOCZIFDATA\", Const, 1, \"\"},\n\t\t{\"SIO_GET_EXTENSION_FUNCTION_POINTER\", Const, 1, \"\"},\n\t\t{\"SIO_GET_INTERFACE_LIST\", Const, 0, \"\"},\n\t\t{\"SIO_KEEPALIVE_VALS\", Const, 3, \"\"},\n\t\t{\"SIO_UDP_CONNRESET\", Const, 4, \"\"},\n\t\t{\"SOCK_CLOEXEC\", Const, 0, \"\"},\n\t\t{\"SOCK_DCCP\", Const, 0, \"\"},\n\t\t{\"SOCK_DGRAM\", Const, 0, \"\"},\n\t\t{\"SOCK_FLAGS_MASK\", Const, 1, \"\"},\n\t\t{\"SOCK_MAXADDRLEN\", Const, 0, \"\"},\n\t\t{\"SOCK_NONBLOCK\", Const, 0, \"\"},\n\t\t{\"SOCK_NOSIGPIPE\", Const, 1, \"\"},\n\t\t{\"SOCK_PACKET\", Const, 0, \"\"},\n\t\t{\"SOCK_RAW\", Const, 0, \"\"},\n\t\t{\"SOCK_RDM\", Const, 0, \"\"},\n\t\t{\"SOCK_SEQPACKET\", Const, 0, \"\"},\n\t\t{\"SOCK_STREAM\", Const, 0, \"\"},\n\t\t{\"SOL_AAL\", Const, 0, \"\"},\n\t\t{\"SOL_ATM\", Const, 0, \"\"},\n\t\t{\"SOL_DECNET\", Const, 0, \"\"},\n\t\t{\"SOL_ICMPV6\", Const, 0, \"\"},\n\t\t{\"SOL_IP\", Const, 0, \"\"},\n\t\t{\"SOL_IPV6\", Const, 0, \"\"},\n\t\t{\"SOL_IRDA\", Const, 0, \"\"},\n\t\t{\"SOL_PACKET\", Const, 0, \"\"},\n\t\t{\"SOL_RAW\", Const, 0, \"\"},\n\t\t{\"SOL_SOCKET\", Const, 0, \"\"},\n\t\t{\"SOL_TCP\", Const, 0, \"\"},\n\t\t{\"SOL_X25\", Const, 0, \"\"},\n\t\t{\"SOMAXCONN\", Const, 0, \"\"},\n\t\t{\"SO_ACCEPTCONN\", Const, 0, \"\"},\n\t\t{\"SO_ACCEPTFILTER\", Const, 0, \"\"},\n\t\t{\"SO_ATTACH_FILTER\", Const, 0, \"\"},\n\t\t{\"SO_BINDANY\", Const, 1, \"\"},\n\t\t{\"SO_BINDTODEVICE\", Const, 0, \"\"},\n\t\t{\"SO_BINTIME\", Const, 0, \"\"},\n\t\t{\"SO_BROADCAST\", Const, 0, \"\"},\n\t\t{\"SO_BSDCOMPAT\", Const, 0, \"\"},\n\t\t{\"SO_DEBUG\", Const, 0, \"\"},\n\t\t{\"SO_DETACH_FILTER\", Const, 0, \"\"},\n\t\t{\"SO_DOMAIN\", Const, 0, \"\"},\n\t\t{\"SO_DONTROUTE\", Const, 0, \"\"},\n\t\t{\"SO_DONTTRUNC\", Const, 0, \"\"},\n\t\t{\"SO_ERROR\", Const, 0, \"\"},\n\t\t{\"SO_KEEPALIVE\", Const, 0, \"\"},\n\t\t{\"SO_LABEL\", Const, 0, \"\"},\n\t\t{\"SO_LINGER\", Const, 0, \"\"},\n\t\t{\"SO_LINGER_SEC\", Const, 0, \"\"},\n\t\t{\"SO_LISTENINCQLEN\", Const, 0, \"\"},\n\t\t{\"SO_LISTENQLEN\", Const, 0, \"\"},\n\t\t{\"SO_LISTENQLIMIT\", Const, 0, \"\"},\n\t\t{\"SO_MARK\", Const, 0, \"\"},\n\t\t{\"SO_NETPROC\", Const, 1, \"\"},\n\t\t{\"SO_NKE\", Const, 0, \"\"},\n\t\t{\"SO_NOADDRERR\", Const, 0, \"\"},\n\t\t{\"SO_NOHEADER\", Const, 1, \"\"},\n\t\t{\"SO_NOSIGPIPE\", Const, 0, \"\"},\n\t\t{\"SO_NOTIFYCONFLICT\", Const, 0, \"\"},\n\t\t{\"SO_NO_CHECK\", Const, 0, \"\"},\n\t\t{\"SO_NO_DDP\", Const, 0, \"\"},\n\t\t{\"SO_NO_OFFLOAD\", Const, 0, \"\"},\n\t\t{\"SO_NP_EXTENSIONS\", Const, 0, \"\"},\n\t\t{\"SO_NREAD\", Const, 0, \"\"},\n\t\t{\"SO_NUMRCVPKT\", Const, 16, \"\"},\n\t\t{\"SO_NWRITE\", Const, 0, \"\"},\n\t\t{\"SO_OOBINLINE\", Const, 0, \"\"},\n\t\t{\"SO_OVERFLOWED\", Const, 1, \"\"},\n\t\t{\"SO_PASSCRED\", Const, 0, \"\"},\n\t\t{\"SO_PASSSEC\", Const, 0, \"\"},\n\t\t{\"SO_PEERCRED\", Const, 0, \"\"},\n\t\t{\"SO_PEERLABEL\", Const, 0, \"\"},\n\t\t{\"SO_PEERNAME\", Const, 0, \"\"},\n\t\t{\"SO_PEERSEC\", Const, 0, \"\"},\n\t\t{\"SO_PRIORITY\", Const, 0, \"\"},\n\t\t{\"SO_PROTOCOL\", Const, 0, \"\"},\n\t\t{\"SO_PROTOTYPE\", Const, 1, \"\"},\n\t\t{\"SO_RANDOMPORT\", Const, 0, \"\"},\n\t\t{\"SO_RCVBUF\", Const, 0, \"\"},\n\t\t{\"SO_RCVBUFFORCE\", Const, 0, \"\"},\n\t\t{\"SO_RCVLOWAT\", Const, 0, \"\"},\n\t\t{\"SO_RCVTIMEO\", Const, 0, \"\"},\n\t\t{\"SO_RESTRICTIONS\", Const, 0, \"\"},\n\t\t{\"SO_RESTRICT_DENYIN\", Const, 0, \"\"},\n\t\t{\"SO_RESTRICT_DENYOUT\", Const, 0, \"\"},\n\t\t{\"SO_RESTRICT_DENYSET\", Const, 0, \"\"},\n\t\t{\"SO_REUSEADDR\", Const, 0, \"\"},\n\t\t{\"SO_REUSEPORT\", Const, 0, \"\"},\n\t\t{\"SO_REUSESHAREUID\", Const, 0, \"\"},\n\t\t{\"SO_RTABLE\", Const, 1, \"\"},\n\t\t{\"SO_RXQ_OVFL\", Const, 0, \"\"},\n\t\t{\"SO_SECURITY_AUTHENTICATION\", Const, 0, \"\"},\n\t\t{\"SO_SECURITY_ENCRYPTION_NETWORK\", Const, 0, \"\"},\n\t\t{\"SO_SECURITY_ENCRYPTION_TRANSPORT\", Const, 0, \"\"},\n\t\t{\"SO_SETFIB\", Const, 0, \"\"},\n\t\t{\"SO_SNDBUF\", Const, 0, \"\"},\n\t\t{\"SO_SNDBUFFORCE\", Const, 0, \"\"},\n\t\t{\"SO_SNDLOWAT\", Const, 0, \"\"},\n\t\t{\"SO_SNDTIMEO\", Const, 0, \"\"},\n\t\t{\"SO_SPLICE\", Const, 1, \"\"},\n\t\t{\"SO_TIMESTAMP\", Const, 0, \"\"},\n\t\t{\"SO_TIMESTAMPING\", Const, 0, \"\"},\n\t\t{\"SO_TIMESTAMPNS\", Const, 0, \"\"},\n\t\t{\"SO_TIMESTAMP_MONOTONIC\", Const, 0, \"\"},\n\t\t{\"SO_TYPE\", Const, 0, \"\"},\n\t\t{\"SO_UPCALLCLOSEWAIT\", Const, 0, \"\"},\n\t\t{\"SO_UPDATE_ACCEPT_CONTEXT\", Const, 0, \"\"},\n\t\t{\"SO_UPDATE_CONNECT_CONTEXT\", Const, 1, \"\"},\n\t\t{\"SO_USELOOPBACK\", Const, 0, \"\"},\n\t\t{\"SO_USER_COOKIE\", Const, 1, \"\"},\n\t\t{\"SO_VENDOR\", Const, 3, \"\"},\n\t\t{\"SO_WANTMORE\", Const, 0, \"\"},\n\t\t{\"SO_WANTOOBFLAG\", Const, 0, \"\"},\n\t\t{\"SSLExtraCertChainPolicyPara\", Type, 0, \"\"},\n\t\t{\"SSLExtraCertChainPolicyPara.AuthType\", Field, 0, \"\"},\n\t\t{\"SSLExtraCertChainPolicyPara.Checks\", Field, 0, \"\"},\n\t\t{\"SSLExtraCertChainPolicyPara.ServerName\", Field, 0, \"\"},\n\t\t{\"SSLExtraCertChainPolicyPara.Size\", Field, 0, \"\"},\n\t\t{\"STANDARD_RIGHTS_ALL\", Const, 0, \"\"},\n\t\t{\"STANDARD_RIGHTS_EXECUTE\", Const, 0, \"\"},\n\t\t{\"STANDARD_RIGHTS_READ\", Const, 0, \"\"},\n\t\t{\"STANDARD_RIGHTS_REQUIRED\", Const, 0, \"\"},\n\t\t{\"STANDARD_RIGHTS_WRITE\", Const, 0, \"\"},\n\t\t{\"STARTF_USESHOWWINDOW\", Const, 0, \"\"},\n\t\t{\"STARTF_USESTDHANDLES\", Const, 0, \"\"},\n\t\t{\"STD_ERROR_HANDLE\", Const, 0, \"\"},\n\t\t{\"STD_INPUT_HANDLE\", Const, 0, \"\"},\n\t\t{\"STD_OUTPUT_HANDLE\", Const, 0, \"\"},\n\t\t{\"SUBLANG_ENGLISH_US\", Const, 0, \"\"},\n\t\t{\"SW_FORCEMINIMIZE\", Const, 0, \"\"},\n\t\t{\"SW_HIDE\", Const, 0, \"\"},\n\t\t{\"SW_MAXIMIZE\", Const, 0, \"\"},\n\t\t{\"SW_MINIMIZE\", Const, 0, \"\"},\n\t\t{\"SW_NORMAL\", Const, 0, \"\"},\n\t\t{\"SW_RESTORE\", Const, 0, \"\"},\n\t\t{\"SW_SHOW\", Const, 0, \"\"},\n\t\t{\"SW_SHOWDEFAULT\", Const, 0, \"\"},\n\t\t{\"SW_SHOWMAXIMIZED\", Const, 0, \"\"},\n\t\t{\"SW_SHOWMINIMIZED\", Const, 0, \"\"},\n\t\t{\"SW_SHOWMINNOACTIVE\", Const, 0, \"\"},\n\t\t{\"SW_SHOWNA\", Const, 0, \"\"},\n\t\t{\"SW_SHOWNOACTIVATE\", Const, 0, \"\"},\n\t\t{\"SW_SHOWNORMAL\", Const, 0, \"\"},\n\t\t{\"SYMBOLIC_LINK_FLAG_DIRECTORY\", Const, 4, \"\"},\n\t\t{\"SYNCHRONIZE\", Const, 0, \"\"},\n\t\t{\"SYSCTL_VERSION\", Const, 1, \"\"},\n\t\t{\"SYSCTL_VERS_0\", Const, 1, \"\"},\n\t\t{\"SYSCTL_VERS_1\", Const, 1, \"\"},\n\t\t{\"SYSCTL_VERS_MASK\", Const, 1, \"\"},\n\t\t{\"SYS_ABORT2\", Const, 0, \"\"},\n\t\t{\"SYS_ACCEPT\", Const, 0, \"\"},\n\t\t{\"SYS_ACCEPT4\", Const, 0, \"\"},\n\t\t{\"SYS_ACCEPT_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_ACCESS\", Const, 0, \"\"},\n\t\t{\"SYS_ACCESS_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_ACCT\", Const, 0, \"\"},\n\t\t{\"SYS_ADD_KEY\", Const, 0, \"\"},\n\t\t{\"SYS_ADD_PROFIL\", Const, 0, \"\"},\n\t\t{\"SYS_ADJFREQ\", Const, 1, \"\"},\n\t\t{\"SYS_ADJTIME\", Const, 0, \"\"},\n\t\t{\"SYS_ADJTIMEX\", Const, 0, \"\"},\n\t\t{\"SYS_AFS_SYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_CANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_ERROR\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_FSYNC\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_MLOCK\", Const, 14, \"\"},\n\t\t{\"SYS_AIO_READ\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_RETURN\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_SUSPEND\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_SUSPEND_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_AIO_WAITCOMPLETE\", Const, 14, \"\"},\n\t\t{\"SYS_AIO_WRITE\", Const, 0, \"\"},\n\t\t{\"SYS_ALARM\", Const, 0, \"\"},\n\t\t{\"SYS_ARCH_PRCTL\", Const, 0, \"\"},\n\t\t{\"SYS_ARM_FADVISE64_64\", Const, 0, \"\"},\n\t\t{\"SYS_ARM_SYNC_FILE_RANGE\", Const, 0, \"\"},\n\t\t{\"SYS_ATGETMSG\", Const, 0, \"\"},\n\t\t{\"SYS_ATPGETREQ\", Const, 0, \"\"},\n\t\t{\"SYS_ATPGETRSP\", Const, 0, \"\"},\n\t\t{\"SYS_ATPSNDREQ\", Const, 0, \"\"},\n\t\t{\"SYS_ATPSNDRSP\", Const, 0, \"\"},\n\t\t{\"SYS_ATPUTMSG\", Const, 0, \"\"},\n\t\t{\"SYS_ATSOCKET\", Const, 0, \"\"},\n\t\t{\"SYS_AUDIT\", Const, 0, \"\"},\n\t\t{\"SYS_AUDITCTL\", Const, 0, \"\"},\n\t\t{\"SYS_AUDITON\", Const, 0, \"\"},\n\t\t{\"SYS_AUDIT_SESSION_JOIN\", Const, 0, \"\"},\n\t\t{\"SYS_AUDIT_SESSION_PORT\", Const, 0, \"\"},\n\t\t{\"SYS_AUDIT_SESSION_SELF\", Const, 0, \"\"},\n\t\t{\"SYS_BDFLUSH\", Const, 0, \"\"},\n\t\t{\"SYS_BIND\", Const, 0, \"\"},\n\t\t{\"SYS_BINDAT\", Const, 3, \"\"},\n\t\t{\"SYS_BREAK\", Const, 0, \"\"},\n\t\t{\"SYS_BRK\", Const, 0, \"\"},\n\t\t{\"SYS_BSDTHREAD_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_BSDTHREAD_REGISTER\", Const, 0, \"\"},\n\t\t{\"SYS_BSDTHREAD_TERMINATE\", Const, 0, \"\"},\n\t\t{\"SYS_CAPGET\", Const, 0, \"\"},\n\t\t{\"SYS_CAPSET\", Const, 0, \"\"},\n\t\t{\"SYS_CAP_ENTER\", Const, 0, \"\"},\n\t\t{\"SYS_CAP_FCNTLS_GET\", Const, 1, \"\"},\n\t\t{\"SYS_CAP_FCNTLS_LIMIT\", Const, 1, \"\"},\n\t\t{\"SYS_CAP_GETMODE\", Const, 0, \"\"},\n\t\t{\"SYS_CAP_GETRIGHTS\", Const, 0, \"\"},\n\t\t{\"SYS_CAP_IOCTLS_GET\", Const, 1, \"\"},\n\t\t{\"SYS_CAP_IOCTLS_LIMIT\", Const, 1, \"\"},\n\t\t{\"SYS_CAP_NEW\", Const, 0, \"\"},\n\t\t{\"SYS_CAP_RIGHTS_GET\", Const, 1, \"\"},\n\t\t{\"SYS_CAP_RIGHTS_LIMIT\", Const, 1, \"\"},\n\t\t{\"SYS_CHDIR\", Const, 0, \"\"},\n\t\t{\"SYS_CHFLAGS\", Const, 0, \"\"},\n\t\t{\"SYS_CHFLAGSAT\", Const, 3, \"\"},\n\t\t{\"SYS_CHMOD\", Const, 0, \"\"},\n\t\t{\"SYS_CHMOD_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_CHOWN\", Const, 0, \"\"},\n\t\t{\"SYS_CHOWN32\", Const, 0, \"\"},\n\t\t{\"SYS_CHROOT\", Const, 0, \"\"},\n\t\t{\"SYS_CHUD\", Const, 0, \"\"},\n\t\t{\"SYS_CLOCK_ADJTIME\", Const, 0, \"\"},\n\t\t{\"SYS_CLOCK_GETCPUCLOCKID2\", Const, 1, \"\"},\n\t\t{\"SYS_CLOCK_GETRES\", Const, 0, \"\"},\n\t\t{\"SYS_CLOCK_GETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_CLOCK_NANOSLEEP\", Const, 0, \"\"},\n\t\t{\"SYS_CLOCK_SETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_CLONE\", Const, 0, \"\"},\n\t\t{\"SYS_CLOSE\", Const, 0, \"\"},\n\t\t{\"SYS_CLOSEFROM\", Const, 0, \"\"},\n\t\t{\"SYS_CLOSE_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_CONNECT\", Const, 0, \"\"},\n\t\t{\"SYS_CONNECTAT\", Const, 3, \"\"},\n\t\t{\"SYS_CONNECT_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_COPYFILE\", Const, 0, \"\"},\n\t\t{\"SYS_CPUSET\", Const, 0, \"\"},\n\t\t{\"SYS_CPUSET_GETAFFINITY\", Const, 0, \"\"},\n\t\t{\"SYS_CPUSET_GETID\", Const, 0, \"\"},\n\t\t{\"SYS_CPUSET_SETAFFINITY\", Const, 0, \"\"},\n\t\t{\"SYS_CPUSET_SETID\", Const, 0, \"\"},\n\t\t{\"SYS_CREAT\", Const, 0, \"\"},\n\t\t{\"SYS_CREATE_MODULE\", Const, 0, \"\"},\n\t\t{\"SYS_CSOPS\", Const, 0, \"\"},\n\t\t{\"SYS_CSOPS_AUDITTOKEN\", Const, 16, \"\"},\n\t\t{\"SYS_DELETE\", Const, 0, \"\"},\n\t\t{\"SYS_DELETE_MODULE\", Const, 0, \"\"},\n\t\t{\"SYS_DUP\", Const, 0, \"\"},\n\t\t{\"SYS_DUP2\", Const, 0, \"\"},\n\t\t{\"SYS_DUP3\", Const, 0, \"\"},\n\t\t{\"SYS_EACCESS\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_CREATE1\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_CTL\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_CTL_OLD\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_PWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_WAIT\", Const, 0, \"\"},\n\t\t{\"SYS_EPOLL_WAIT_OLD\", Const, 0, \"\"},\n\t\t{\"SYS_EVENTFD\", Const, 0, \"\"},\n\t\t{\"SYS_EVENTFD2\", Const, 0, \"\"},\n\t\t{\"SYS_EXCHANGEDATA\", Const, 0, \"\"},\n\t\t{\"SYS_EXECVE\", Const, 0, \"\"},\n\t\t{\"SYS_EXIT\", Const, 0, \"\"},\n\t\t{\"SYS_EXIT_GROUP\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTRCTL\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_DELETE_FD\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_DELETE_FILE\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_DELETE_LINK\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_GET_FD\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_GET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_GET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_LIST_FD\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_LIST_FILE\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_LIST_LINK\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_SET_FD\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_SET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS_EXTATTR_SET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS_FACCESSAT\", Const, 0, \"\"},\n\t\t{\"SYS_FADVISE64\", Const, 0, \"\"},\n\t\t{\"SYS_FADVISE64_64\", Const, 0, \"\"},\n\t\t{\"SYS_FALLOCATE\", Const, 0, \"\"},\n\t\t{\"SYS_FANOTIFY_INIT\", Const, 0, \"\"},\n\t\t{\"SYS_FANOTIFY_MARK\", Const, 0, \"\"},\n\t\t{\"SYS_FCHDIR\", Const, 0, \"\"},\n\t\t{\"SYS_FCHFLAGS\", Const, 0, \"\"},\n\t\t{\"SYS_FCHMOD\", Const, 0, \"\"},\n\t\t{\"SYS_FCHMODAT\", Const, 0, \"\"},\n\t\t{\"SYS_FCHMOD_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_FCHOWN\", Const, 0, \"\"},\n\t\t{\"SYS_FCHOWN32\", Const, 0, \"\"},\n\t\t{\"SYS_FCHOWNAT\", Const, 0, \"\"},\n\t\t{\"SYS_FCHROOT\", Const, 1, \"\"},\n\t\t{\"SYS_FCNTL\", Const, 0, \"\"},\n\t\t{\"SYS_FCNTL64\", Const, 0, \"\"},\n\t\t{\"SYS_FCNTL_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_FDATASYNC\", Const, 0, \"\"},\n\t\t{\"SYS_FEXECVE\", Const, 0, \"\"},\n\t\t{\"SYS_FFCLOCK_GETCOUNTER\", Const, 0, \"\"},\n\t\t{\"SYS_FFCLOCK_GETESTIMATE\", Const, 0, \"\"},\n\t\t{\"SYS_FFCLOCK_SETESTIMATE\", Const, 0, \"\"},\n\t\t{\"SYS_FFSCTL\", Const, 0, \"\"},\n\t\t{\"SYS_FGETATTRLIST\", Const, 0, \"\"},\n\t\t{\"SYS_FGETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_FHOPEN\", Const, 0, \"\"},\n\t\t{\"SYS_FHSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_FHSTATFS\", Const, 0, \"\"},\n\t\t{\"SYS_FILEPORT_MAKEFD\", Const, 0, \"\"},\n\t\t{\"SYS_FILEPORT_MAKEPORT\", Const, 0, \"\"},\n\t\t{\"SYS_FKTRACE\", Const, 1, \"\"},\n\t\t{\"SYS_FLISTXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_FLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_FORK\", Const, 0, \"\"},\n\t\t{\"SYS_FPATHCONF\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_FTRUNCATE\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_LSEEK\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_MMAP\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_PREAD\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_PWRITE\", Const, 0, \"\"},\n\t\t{\"SYS_FREEBSD6_TRUNCATE\", Const, 0, \"\"},\n\t\t{\"SYS_FREMOVEXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_FSCTL\", Const, 0, \"\"},\n\t\t{\"SYS_FSETATTRLIST\", Const, 0, \"\"},\n\t\t{\"SYS_FSETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_FSGETPATH\", Const, 0, \"\"},\n\t\t{\"SYS_FSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_FSTAT64\", Const, 0, \"\"},\n\t\t{\"SYS_FSTAT64_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATAT\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATAT64\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATFS\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATFS64\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATV\", Const, 0, \"\"},\n\t\t{\"SYS_FSTATVFS1\", Const, 1, \"\"},\n\t\t{\"SYS_FSTAT_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_FSYNC\", Const, 0, \"\"},\n\t\t{\"SYS_FSYNC_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_FSYNC_RANGE\", Const, 1, \"\"},\n\t\t{\"SYS_FTIME\", Const, 0, \"\"},\n\t\t{\"SYS_FTRUNCATE\", Const, 0, \"\"},\n\t\t{\"SYS_FTRUNCATE64\", Const, 0, \"\"},\n\t\t{\"SYS_FUTEX\", Const, 0, \"\"},\n\t\t{\"SYS_FUTIMENS\", Const, 1, \"\"},\n\t\t{\"SYS_FUTIMES\", Const, 0, \"\"},\n\t\t{\"SYS_FUTIMESAT\", Const, 0, \"\"},\n\t\t{\"SYS_GETATTRLIST\", Const, 0, \"\"},\n\t\t{\"SYS_GETAUDIT\", Const, 0, \"\"},\n\t\t{\"SYS_GETAUDIT_ADDR\", Const, 0, \"\"},\n\t\t{\"SYS_GETAUID\", Const, 0, \"\"},\n\t\t{\"SYS_GETCONTEXT\", Const, 0, \"\"},\n\t\t{\"SYS_GETCPU\", Const, 0, \"\"},\n\t\t{\"SYS_GETCWD\", Const, 0, \"\"},\n\t\t{\"SYS_GETDENTS\", Const, 0, \"\"},\n\t\t{\"SYS_GETDENTS64\", Const, 0, \"\"},\n\t\t{\"SYS_GETDIRENTRIES\", Const, 0, \"\"},\n\t\t{\"SYS_GETDIRENTRIES64\", Const, 0, \"\"},\n\t\t{\"SYS_GETDIRENTRIESATTR\", Const, 0, \"\"},\n\t\t{\"SYS_GETDTABLECOUNT\", Const, 1, \"\"},\n\t\t{\"SYS_GETDTABLESIZE\", Const, 0, \"\"},\n\t\t{\"SYS_GETEGID\", Const, 0, \"\"},\n\t\t{\"SYS_GETEGID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETEUID\", Const, 0, \"\"},\n\t\t{\"SYS_GETEUID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETFH\", Const, 0, \"\"},\n\t\t{\"SYS_GETFSSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_GETFSSTAT64\", Const, 0, \"\"},\n\t\t{\"SYS_GETGID\", Const, 0, \"\"},\n\t\t{\"SYS_GETGID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_GETGROUPS32\", Const, 0, \"\"},\n\t\t{\"SYS_GETHOSTUUID\", Const, 0, \"\"},\n\t\t{\"SYS_GETITIMER\", Const, 0, \"\"},\n\t\t{\"SYS_GETLCID\", Const, 0, \"\"},\n\t\t{\"SYS_GETLOGIN\", Const, 0, \"\"},\n\t\t{\"SYS_GETLOGINCLASS\", Const, 0, \"\"},\n\t\t{\"SYS_GETPEERNAME\", Const, 0, \"\"},\n\t\t{\"SYS_GETPGID\", Const, 0, \"\"},\n\t\t{\"SYS_GETPGRP\", Const, 0, \"\"},\n\t\t{\"SYS_GETPID\", Const, 0, \"\"},\n\t\t{\"SYS_GETPMSG\", Const, 0, \"\"},\n\t\t{\"SYS_GETPPID\", Const, 0, \"\"},\n\t\t{\"SYS_GETPRIORITY\", Const, 0, \"\"},\n\t\t{\"SYS_GETRESGID\", Const, 0, \"\"},\n\t\t{\"SYS_GETRESGID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETRESUID\", Const, 0, \"\"},\n\t\t{\"SYS_GETRESUID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETRLIMIT\", Const, 0, \"\"},\n\t\t{\"SYS_GETRTABLE\", Const, 1, \"\"},\n\t\t{\"SYS_GETRUSAGE\", Const, 0, \"\"},\n\t\t{\"SYS_GETSGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_GETSID\", Const, 0, \"\"},\n\t\t{\"SYS_GETSOCKNAME\", Const, 0, \"\"},\n\t\t{\"SYS_GETSOCKOPT\", Const, 0, \"\"},\n\t\t{\"SYS_GETTHRID\", Const, 1, \"\"},\n\t\t{\"SYS_GETTID\", Const, 0, \"\"},\n\t\t{\"SYS_GETTIMEOFDAY\", Const, 0, \"\"},\n\t\t{\"SYS_GETUID\", Const, 0, \"\"},\n\t\t{\"SYS_GETUID32\", Const, 0, \"\"},\n\t\t{\"SYS_GETVFSSTAT\", Const, 1, \"\"},\n\t\t{\"SYS_GETWGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_GETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_GET_KERNEL_SYMS\", Const, 0, \"\"},\n\t\t{\"SYS_GET_MEMPOLICY\", Const, 0, \"\"},\n\t\t{\"SYS_GET_ROBUST_LIST\", Const, 0, \"\"},\n\t\t{\"SYS_GET_THREAD_AREA\", Const, 0, \"\"},\n\t\t{\"SYS_GSSD_SYSCALL\", Const, 14, \"\"},\n\t\t{\"SYS_GTTY\", Const, 0, \"\"},\n\t\t{\"SYS_IDENTITYSVC\", Const, 0, \"\"},\n\t\t{\"SYS_IDLE\", Const, 0, \"\"},\n\t\t{\"SYS_INITGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_INIT_MODULE\", Const, 0, \"\"},\n\t\t{\"SYS_INOTIFY_ADD_WATCH\", Const, 0, \"\"},\n\t\t{\"SYS_INOTIFY_INIT\", Const, 0, \"\"},\n\t\t{\"SYS_INOTIFY_INIT1\", Const, 0, \"\"},\n\t\t{\"SYS_INOTIFY_RM_WATCH\", Const, 0, \"\"},\n\t\t{\"SYS_IOCTL\", Const, 0, \"\"},\n\t\t{\"SYS_IOPERM\", Const, 0, \"\"},\n\t\t{\"SYS_IOPL\", Const, 0, \"\"},\n\t\t{\"SYS_IOPOLICYSYS\", Const, 0, \"\"},\n\t\t{\"SYS_IOPRIO_GET\", Const, 0, \"\"},\n\t\t{\"SYS_IOPRIO_SET\", Const, 0, \"\"},\n\t\t{\"SYS_IO_CANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_IO_DESTROY\", Const, 0, \"\"},\n\t\t{\"SYS_IO_GETEVENTS\", Const, 0, \"\"},\n\t\t{\"SYS_IO_SETUP\", Const, 0, \"\"},\n\t\t{\"SYS_IO_SUBMIT\", Const, 0, \"\"},\n\t\t{\"SYS_IPC\", Const, 0, \"\"},\n\t\t{\"SYS_ISSETUGID\", Const, 0, \"\"},\n\t\t{\"SYS_JAIL\", Const, 0, \"\"},\n\t\t{\"SYS_JAIL_ATTACH\", Const, 0, \"\"},\n\t\t{\"SYS_JAIL_GET\", Const, 0, \"\"},\n\t\t{\"SYS_JAIL_REMOVE\", Const, 0, \"\"},\n\t\t{\"SYS_JAIL_SET\", Const, 0, \"\"},\n\t\t{\"SYS_KAS_INFO\", Const, 16, \"\"},\n\t\t{\"SYS_KDEBUG_TRACE\", Const, 0, \"\"},\n\t\t{\"SYS_KENV\", Const, 0, \"\"},\n\t\t{\"SYS_KEVENT\", Const, 0, \"\"},\n\t\t{\"SYS_KEVENT64\", Const, 0, \"\"},\n\t\t{\"SYS_KEXEC_LOAD\", Const, 0, \"\"},\n\t\t{\"SYS_KEYCTL\", Const, 0, \"\"},\n\t\t{\"SYS_KILL\", Const, 0, \"\"},\n\t\t{\"SYS_KLDFIND\", Const, 0, \"\"},\n\t\t{\"SYS_KLDFIRSTMOD\", Const, 0, \"\"},\n\t\t{\"SYS_KLDLOAD\", Const, 0, \"\"},\n\t\t{\"SYS_KLDNEXT\", Const, 0, \"\"},\n\t\t{\"SYS_KLDSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_KLDSYM\", Const, 0, \"\"},\n\t\t{\"SYS_KLDUNLOAD\", Const, 0, \"\"},\n\t\t{\"SYS_KLDUNLOADF\", Const, 0, \"\"},\n\t\t{\"SYS_KMQ_NOTIFY\", Const, 14, \"\"},\n\t\t{\"SYS_KMQ_OPEN\", Const, 14, \"\"},\n\t\t{\"SYS_KMQ_SETATTR\", Const, 14, \"\"},\n\t\t{\"SYS_KMQ_TIMEDRECEIVE\", Const, 14, \"\"},\n\t\t{\"SYS_KMQ_TIMEDSEND\", Const, 14, \"\"},\n\t\t{\"SYS_KMQ_UNLINK\", Const, 14, \"\"},\n\t\t{\"SYS_KQUEUE\", Const, 0, \"\"},\n\t\t{\"SYS_KQUEUE1\", Const, 1, \"\"},\n\t\t{\"SYS_KSEM_CLOSE\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_DESTROY\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_GETVALUE\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_INIT\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_OPEN\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_POST\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_TIMEDWAIT\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_TRYWAIT\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_UNLINK\", Const, 14, \"\"},\n\t\t{\"SYS_KSEM_WAIT\", Const, 14, \"\"},\n\t\t{\"SYS_KTIMER_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_KTIMER_DELETE\", Const, 0, \"\"},\n\t\t{\"SYS_KTIMER_GETOVERRUN\", Const, 0, \"\"},\n\t\t{\"SYS_KTIMER_GETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_KTIMER_SETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_KTRACE\", Const, 0, \"\"},\n\t\t{\"SYS_LCHFLAGS\", Const, 0, \"\"},\n\t\t{\"SYS_LCHMOD\", Const, 0, \"\"},\n\t\t{\"SYS_LCHOWN\", Const, 0, \"\"},\n\t\t{\"SYS_LCHOWN32\", Const, 0, \"\"},\n\t\t{\"SYS_LEDGER\", Const, 16, \"\"},\n\t\t{\"SYS_LGETFH\", Const, 0, \"\"},\n\t\t{\"SYS_LGETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_LINK\", Const, 0, \"\"},\n\t\t{\"SYS_LINKAT\", Const, 0, \"\"},\n\t\t{\"SYS_LIO_LISTIO\", Const, 0, \"\"},\n\t\t{\"SYS_LISTEN\", Const, 0, \"\"},\n\t\t{\"SYS_LISTXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_LLISTXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_LOCK\", Const, 0, \"\"},\n\t\t{\"SYS_LOOKUP_DCOOKIE\", Const, 0, \"\"},\n\t\t{\"SYS_LPATHCONF\", Const, 0, \"\"},\n\t\t{\"SYS_LREMOVEXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_LSEEK\", Const, 0, \"\"},\n\t\t{\"SYS_LSETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_LSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_LSTAT64\", Const, 0, \"\"},\n\t\t{\"SYS_LSTAT64_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_LSTATV\", Const, 0, \"\"},\n\t\t{\"SYS_LSTAT_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_LUTIMES\", Const, 0, \"\"},\n\t\t{\"SYS_MAC_SYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS_MADVISE\", Const, 0, \"\"},\n\t\t{\"SYS_MADVISE1\", Const, 0, \"\"},\n\t\t{\"SYS_MAXSYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS_MBIND\", Const, 0, \"\"},\n\t\t{\"SYS_MIGRATE_PAGES\", Const, 0, \"\"},\n\t\t{\"SYS_MINCORE\", Const, 0, \"\"},\n\t\t{\"SYS_MINHERIT\", Const, 0, \"\"},\n\t\t{\"SYS_MKCOMPLEX\", Const, 0, \"\"},\n\t\t{\"SYS_MKDIR\", Const, 0, \"\"},\n\t\t{\"SYS_MKDIRAT\", Const, 0, \"\"},\n\t\t{\"SYS_MKDIR_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_MKFIFO\", Const, 0, \"\"},\n\t\t{\"SYS_MKFIFOAT\", Const, 0, \"\"},\n\t\t{\"SYS_MKFIFO_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_MKNOD\", Const, 0, \"\"},\n\t\t{\"SYS_MKNODAT\", Const, 0, \"\"},\n\t\t{\"SYS_MLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_MLOCKALL\", Const, 0, \"\"},\n\t\t{\"SYS_MMAP\", Const, 0, \"\"},\n\t\t{\"SYS_MMAP2\", Const, 0, \"\"},\n\t\t{\"SYS_MODCTL\", Const, 1, \"\"},\n\t\t{\"SYS_MODFIND\", Const, 0, \"\"},\n\t\t{\"SYS_MODFNEXT\", Const, 0, \"\"},\n\t\t{\"SYS_MODIFY_LDT\", Const, 0, \"\"},\n\t\t{\"SYS_MODNEXT\", Const, 0, \"\"},\n\t\t{\"SYS_MODSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_MODWATCH\", Const, 0, \"\"},\n\t\t{\"SYS_MOUNT\", Const, 0, \"\"},\n\t\t{\"SYS_MOVE_PAGES\", Const, 0, \"\"},\n\t\t{\"SYS_MPROTECT\", Const, 0, \"\"},\n\t\t{\"SYS_MPX\", Const, 0, \"\"},\n\t\t{\"SYS_MQUERY\", Const, 1, \"\"},\n\t\t{\"SYS_MQ_GETSETATTR\", Const, 0, \"\"},\n\t\t{\"SYS_MQ_NOTIFY\", Const, 0, \"\"},\n\t\t{\"SYS_MQ_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_MQ_TIMEDRECEIVE\", Const, 0, \"\"},\n\t\t{\"SYS_MQ_TIMEDSEND\", Const, 0, \"\"},\n\t\t{\"SYS_MQ_UNLINK\", Const, 0, \"\"},\n\t\t{\"SYS_MREMAP\", Const, 0, \"\"},\n\t\t{\"SYS_MSGCTL\", Const, 0, \"\"},\n\t\t{\"SYS_MSGGET\", Const, 0, \"\"},\n\t\t{\"SYS_MSGRCV\", Const, 0, \"\"},\n\t\t{\"SYS_MSGRCV_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_MSGSND\", Const, 0, \"\"},\n\t\t{\"SYS_MSGSND_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_MSGSYS\", Const, 0, \"\"},\n\t\t{\"SYS_MSYNC\", Const, 0, \"\"},\n\t\t{\"SYS_MSYNC_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_MUNLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_MUNLOCKALL\", Const, 0, \"\"},\n\t\t{\"SYS_MUNMAP\", Const, 0, \"\"},\n\t\t{\"SYS_NAME_TO_HANDLE_AT\", Const, 0, \"\"},\n\t\t{\"SYS_NANOSLEEP\", Const, 0, \"\"},\n\t\t{\"SYS_NEWFSTATAT\", Const, 0, \"\"},\n\t\t{\"SYS_NFSCLNT\", Const, 0, \"\"},\n\t\t{\"SYS_NFSSERVCTL\", Const, 0, \"\"},\n\t\t{\"SYS_NFSSVC\", Const, 0, \"\"},\n\t\t{\"SYS_NFSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_NICE\", Const, 0, \"\"},\n\t\t{\"SYS_NLM_SYSCALL\", Const, 14, \"\"},\n\t\t{\"SYS_NLSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_NMOUNT\", Const, 0, \"\"},\n\t\t{\"SYS_NSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_NTP_ADJTIME\", Const, 0, \"\"},\n\t\t{\"SYS_NTP_GETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_NUMA_GETAFFINITY\", Const, 14, \"\"},\n\t\t{\"SYS_NUMA_SETAFFINITY\", Const, 14, \"\"},\n\t\t{\"SYS_OABI_SYSCALL_BASE\", Const, 0, \"\"},\n\t\t{\"SYS_OBREAK\", Const, 0, \"\"},\n\t\t{\"SYS_OLDFSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_OLDLSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_OLDOLDUNAME\", Const, 0, \"\"},\n\t\t{\"SYS_OLDSTAT\", Const, 0, \"\"},\n\t\t{\"SYS_OLDUNAME\", Const, 0, \"\"},\n\t\t{\"SYS_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_OPENAT\", Const, 0, \"\"},\n\t\t{\"SYS_OPENBSD_POLL\", Const, 0, \"\"},\n\t\t{\"SYS_OPEN_BY_HANDLE_AT\", Const, 0, \"\"},\n\t\t{\"SYS_OPEN_DPROTECTED_NP\", Const, 16, \"\"},\n\t\t{\"SYS_OPEN_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_OPEN_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_OVADVISE\", Const, 0, \"\"},\n\t\t{\"SYS_PACCEPT\", Const, 1, \"\"},\n\t\t{\"SYS_PATHCONF\", Const, 0, \"\"},\n\t\t{\"SYS_PAUSE\", Const, 0, \"\"},\n\t\t{\"SYS_PCICONFIG_IOBASE\", Const, 0, \"\"},\n\t\t{\"SYS_PCICONFIG_READ\", Const, 0, \"\"},\n\t\t{\"SYS_PCICONFIG_WRITE\", Const, 0, \"\"},\n\t\t{\"SYS_PDFORK\", Const, 0, \"\"},\n\t\t{\"SYS_PDGETPID\", Const, 0, \"\"},\n\t\t{\"SYS_PDKILL\", Const, 0, \"\"},\n\t\t{\"SYS_PERF_EVENT_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_PERSONALITY\", Const, 0, \"\"},\n\t\t{\"SYS_PID_HIBERNATE\", Const, 0, \"\"},\n\t\t{\"SYS_PID_RESUME\", Const, 0, \"\"},\n\t\t{\"SYS_PID_SHUTDOWN_SOCKETS\", Const, 0, \"\"},\n\t\t{\"SYS_PID_SUSPEND\", Const, 0, \"\"},\n\t\t{\"SYS_PIPE\", Const, 0, \"\"},\n\t\t{\"SYS_PIPE2\", Const, 0, \"\"},\n\t\t{\"SYS_PIVOT_ROOT\", Const, 0, \"\"},\n\t\t{\"SYS_PMC_CONTROL\", Const, 1, \"\"},\n\t\t{\"SYS_PMC_GET_INFO\", Const, 1, \"\"},\n\t\t{\"SYS_POLL\", Const, 0, \"\"},\n\t\t{\"SYS_POLLTS\", Const, 1, \"\"},\n\t\t{\"SYS_POLL_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_POSIX_FADVISE\", Const, 0, \"\"},\n\t\t{\"SYS_POSIX_FALLOCATE\", Const, 0, \"\"},\n\t\t{\"SYS_POSIX_OPENPT\", Const, 0, \"\"},\n\t\t{\"SYS_POSIX_SPAWN\", Const, 0, \"\"},\n\t\t{\"SYS_PPOLL\", Const, 0, \"\"},\n\t\t{\"SYS_PRCTL\", Const, 0, \"\"},\n\t\t{\"SYS_PREAD\", Const, 0, \"\"},\n\t\t{\"SYS_PREAD64\", Const, 0, \"\"},\n\t\t{\"SYS_PREADV\", Const, 0, \"\"},\n\t\t{\"SYS_PREAD_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_PRLIMIT64\", Const, 0, \"\"},\n\t\t{\"SYS_PROCCTL\", Const, 3, \"\"},\n\t\t{\"SYS_PROCESS_POLICY\", Const, 0, \"\"},\n\t\t{\"SYS_PROCESS_VM_READV\", Const, 0, \"\"},\n\t\t{\"SYS_PROCESS_VM_WRITEV\", Const, 0, \"\"},\n\t\t{\"SYS_PROC_INFO\", Const, 0, \"\"},\n\t\t{\"SYS_PROF\", Const, 0, \"\"},\n\t\t{\"SYS_PROFIL\", Const, 0, \"\"},\n\t\t{\"SYS_PSELECT\", Const, 0, \"\"},\n\t\t{\"SYS_PSELECT6\", Const, 0, \"\"},\n\t\t{\"SYS_PSET_ASSIGN\", Const, 1, \"\"},\n\t\t{\"SYS_PSET_CREATE\", Const, 1, \"\"},\n\t\t{\"SYS_PSET_DESTROY\", Const, 1, \"\"},\n\t\t{\"SYS_PSYNCH_CVBROAD\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_CVCLRPREPOST\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_CVSIGNAL\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_CVWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_MUTEXDROP\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_MUTEXWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_DOWNGRADE\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_LONGRDLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_RDLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_UNLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_UNLOCK2\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_UPGRADE\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_WRLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_PSYNCH_RW_YIELDWRLOCK\", Const, 0, \"\"},\n\t\t{\"SYS_PTRACE\", Const, 0, \"\"},\n\t\t{\"SYS_PUTPMSG\", Const, 0, \"\"},\n\t\t{\"SYS_PWRITE\", Const, 0, \"\"},\n\t\t{\"SYS_PWRITE64\", Const, 0, \"\"},\n\t\t{\"SYS_PWRITEV\", Const, 0, \"\"},\n\t\t{\"SYS_PWRITE_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_QUERY_MODULE\", Const, 0, \"\"},\n\t\t{\"SYS_QUOTACTL\", Const, 0, \"\"},\n\t\t{\"SYS_RASCTL\", Const, 1, \"\"},\n\t\t{\"SYS_RCTL_ADD_RULE\", Const, 0, \"\"},\n\t\t{\"SYS_RCTL_GET_LIMITS\", Const, 0, \"\"},\n\t\t{\"SYS_RCTL_GET_RACCT\", Const, 0, \"\"},\n\t\t{\"SYS_RCTL_GET_RULES\", Const, 0, \"\"},\n\t\t{\"SYS_RCTL_REMOVE_RULE\", Const, 0, \"\"},\n\t\t{\"SYS_READ\", Const, 0, \"\"},\n\t\t{\"SYS_READAHEAD\", Const, 0, \"\"},\n\t\t{\"SYS_READDIR\", Const, 0, \"\"},\n\t\t{\"SYS_READLINK\", Const, 0, \"\"},\n\t\t{\"SYS_READLINKAT\", Const, 0, \"\"},\n\t\t{\"SYS_READV\", Const, 0, \"\"},\n\t\t{\"SYS_READV_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_READ_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_REBOOT\", Const, 0, \"\"},\n\t\t{\"SYS_RECV\", Const, 0, \"\"},\n\t\t{\"SYS_RECVFROM\", Const, 0, \"\"},\n\t\t{\"SYS_RECVFROM_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_RECVMMSG\", Const, 0, \"\"},\n\t\t{\"SYS_RECVMSG\", Const, 0, \"\"},\n\t\t{\"SYS_RECVMSG_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_REMAP_FILE_PAGES\", Const, 0, \"\"},\n\t\t{\"SYS_REMOVEXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_RENAME\", Const, 0, \"\"},\n\t\t{\"SYS_RENAMEAT\", Const, 0, \"\"},\n\t\t{\"SYS_REQUEST_KEY\", Const, 0, \"\"},\n\t\t{\"SYS_RESTART_SYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS_REVOKE\", Const, 0, \"\"},\n\t\t{\"SYS_RFORK\", Const, 0, \"\"},\n\t\t{\"SYS_RMDIR\", Const, 0, \"\"},\n\t\t{\"SYS_RTPRIO\", Const, 0, \"\"},\n\t\t{\"SYS_RTPRIO_THREAD\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGACTION\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGPENDING\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGPROCMASK\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGQUEUEINFO\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGRETURN\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGSUSPEND\", Const, 0, \"\"},\n\t\t{\"SYS_RT_SIGTIMEDWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_RT_TGSIGQUEUEINFO\", Const, 0, \"\"},\n\t\t{\"SYS_SBRK\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_GETAFFINITY\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_GETPARAM\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_GETSCHEDULER\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_GET_PRIORITY_MAX\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_GET_PRIORITY_MIN\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_RR_GET_INTERVAL\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_SETAFFINITY\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_SETPARAM\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_SETSCHEDULER\", Const, 0, \"\"},\n\t\t{\"SYS_SCHED_YIELD\", Const, 0, \"\"},\n\t\t{\"SYS_SCTP_GENERIC_RECVMSG\", Const, 0, \"\"},\n\t\t{\"SYS_SCTP_GENERIC_SENDMSG\", Const, 0, \"\"},\n\t\t{\"SYS_SCTP_GENERIC_SENDMSG_IOV\", Const, 0, \"\"},\n\t\t{\"SYS_SCTP_PEELOFF\", Const, 0, \"\"},\n\t\t{\"SYS_SEARCHFS\", Const, 0, \"\"},\n\t\t{\"SYS_SECURITY\", Const, 0, \"\"},\n\t\t{\"SYS_SELECT\", Const, 0, \"\"},\n\t\t{\"SYS_SELECT_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_SEMCONFIG\", Const, 1, \"\"},\n\t\t{\"SYS_SEMCTL\", Const, 0, \"\"},\n\t\t{\"SYS_SEMGET\", Const, 0, \"\"},\n\t\t{\"SYS_SEMOP\", Const, 0, \"\"},\n\t\t{\"SYS_SEMSYS\", Const, 0, \"\"},\n\t\t{\"SYS_SEMTIMEDOP\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_CLOSE\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_DESTROY\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_GETVALUE\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_INIT\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_POST\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_TRYWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_UNLINK\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_WAIT\", Const, 0, \"\"},\n\t\t{\"SYS_SEM_WAIT_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_SEND\", Const, 0, \"\"},\n\t\t{\"SYS_SENDFILE\", Const, 0, \"\"},\n\t\t{\"SYS_SENDFILE64\", Const, 0, \"\"},\n\t\t{\"SYS_SENDMMSG\", Const, 0, \"\"},\n\t\t{\"SYS_SENDMSG\", Const, 0, \"\"},\n\t\t{\"SYS_SENDMSG_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_SENDTO\", Const, 0, \"\"},\n\t\t{\"SYS_SENDTO_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_SETATTRLIST\", Const, 0, \"\"},\n\t\t{\"SYS_SETAUDIT\", Const, 0, \"\"},\n\t\t{\"SYS_SETAUDIT_ADDR\", Const, 0, \"\"},\n\t\t{\"SYS_SETAUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETCONTEXT\", Const, 0, \"\"},\n\t\t{\"SYS_SETDOMAINNAME\", Const, 0, \"\"},\n\t\t{\"SYS_SETEGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETEUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETFIB\", Const, 0, \"\"},\n\t\t{\"SYS_SETFSGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETFSGID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETFSUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETFSUID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETGID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_SETGROUPS32\", Const, 0, \"\"},\n\t\t{\"SYS_SETHOSTNAME\", Const, 0, \"\"},\n\t\t{\"SYS_SETITIMER\", Const, 0, \"\"},\n\t\t{\"SYS_SETLCID\", Const, 0, \"\"},\n\t\t{\"SYS_SETLOGIN\", Const, 0, \"\"},\n\t\t{\"SYS_SETLOGINCLASS\", Const, 0, \"\"},\n\t\t{\"SYS_SETNS\", Const, 0, \"\"},\n\t\t{\"SYS_SETPGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETPRIORITY\", Const, 0, \"\"},\n\t\t{\"SYS_SETPRIVEXEC\", Const, 0, \"\"},\n\t\t{\"SYS_SETREGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETREGID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETRESGID\", Const, 0, \"\"},\n\t\t{\"SYS_SETRESGID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETRESUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETRESUID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETREUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETREUID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETRLIMIT\", Const, 0, \"\"},\n\t\t{\"SYS_SETRTABLE\", Const, 1, \"\"},\n\t\t{\"SYS_SETSGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_SETSID\", Const, 0, \"\"},\n\t\t{\"SYS_SETSOCKOPT\", Const, 0, \"\"},\n\t\t{\"SYS_SETTID\", Const, 0, \"\"},\n\t\t{\"SYS_SETTID_WITH_PID\", Const, 0, \"\"},\n\t\t{\"SYS_SETTIMEOFDAY\", Const, 0, \"\"},\n\t\t{\"SYS_SETUID\", Const, 0, \"\"},\n\t\t{\"SYS_SETUID32\", Const, 0, \"\"},\n\t\t{\"SYS_SETWGROUPS\", Const, 0, \"\"},\n\t\t{\"SYS_SETXATTR\", Const, 0, \"\"},\n\t\t{\"SYS_SET_MEMPOLICY\", Const, 0, \"\"},\n\t\t{\"SYS_SET_ROBUST_LIST\", Const, 0, \"\"},\n\t\t{\"SYS_SET_THREAD_AREA\", Const, 0, \"\"},\n\t\t{\"SYS_SET_TID_ADDRESS\", Const, 0, \"\"},\n\t\t{\"SYS_SGETMASK\", Const, 0, \"\"},\n\t\t{\"SYS_SHARED_REGION_CHECK_NP\", Const, 0, \"\"},\n\t\t{\"SYS_SHARED_REGION_MAP_AND_SLIDE_NP\", Const, 0, \"\"},\n\t\t{\"SYS_SHMAT\", Const, 0, \"\"},\n\t\t{\"SYS_SHMCTL\", Const, 0, \"\"},\n\t\t{\"SYS_SHMDT\", Const, 0, \"\"},\n\t\t{\"SYS_SHMGET\", Const, 0, \"\"},\n\t\t{\"SYS_SHMSYS\", Const, 0, \"\"},\n\t\t{\"SYS_SHM_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_SHM_UNLINK\", Const, 0, \"\"},\n\t\t{\"SYS_SHUTDOWN\", Const, 0, \"\"},\n\t\t{\"SYS_SIGACTION\", Const, 0, \"\"},\n\t\t{\"SYS_SIGALTSTACK\", Const, 0, \"\"},\n\t\t{\"SYS_SIGNAL\", Const, 0, \"\"},\n\t\t{\"SYS_SIGNALFD\", Const, 0, \"\"},\n\t\t{\"SYS_SIGNALFD4\", Const, 0, \"\"},\n\t\t{\"SYS_SIGPENDING\", Const, 0, \"\"},\n\t\t{\"SYS_SIGPROCMASK\", Const, 0, \"\"},\n\t\t{\"SYS_SIGQUEUE\", Const, 0, \"\"},\n\t\t{\"SYS_SIGQUEUEINFO\", Const, 1, \"\"},\n\t\t{\"SYS_SIGRETURN\", Const, 0, \"\"},\n\t\t{\"SYS_SIGSUSPEND\", Const, 0, \"\"},\n\t\t{\"SYS_SIGSUSPEND_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_SIGTIMEDWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_SIGWAIT\", Const, 0, \"\"},\n\t\t{\"SYS_SIGWAITINFO\", Const, 0, \"\"},\n\t\t{\"SYS_SOCKET\", Const, 0, \"\"},\n\t\t{\"SYS_SOCKETCALL\", Const, 0, \"\"},\n\t\t{\"SYS_SOCKETPAIR\", Const, 0, \"\"},\n\t\t{\"SYS_SPLICE\", Const, 0, \"\"},\n\t\t{\"SYS_SSETMASK\", Const, 0, \"\"},\n\t\t{\"SYS_SSTK\", Const, 0, \"\"},\n\t\t{\"SYS_STACK_SNAPSHOT\", Const, 0, \"\"},\n\t\t{\"SYS_STAT\", Const, 0, \"\"},\n\t\t{\"SYS_STAT64\", Const, 0, \"\"},\n\t\t{\"SYS_STAT64_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_STATFS\", Const, 0, \"\"},\n\t\t{\"SYS_STATFS64\", Const, 0, \"\"},\n\t\t{\"SYS_STATV\", Const, 0, \"\"},\n\t\t{\"SYS_STATVFS1\", Const, 1, \"\"},\n\t\t{\"SYS_STAT_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_STIME\", Const, 0, \"\"},\n\t\t{\"SYS_STTY\", Const, 0, \"\"},\n\t\t{\"SYS_SWAPCONTEXT\", Const, 0, \"\"},\n\t\t{\"SYS_SWAPCTL\", Const, 1, \"\"},\n\t\t{\"SYS_SWAPOFF\", Const, 0, \"\"},\n\t\t{\"SYS_SWAPON\", Const, 0, \"\"},\n\t\t{\"SYS_SYMLINK\", Const, 0, \"\"},\n\t\t{\"SYS_SYMLINKAT\", Const, 0, \"\"},\n\t\t{\"SYS_SYNC\", Const, 0, \"\"},\n\t\t{\"SYS_SYNCFS\", Const, 0, \"\"},\n\t\t{\"SYS_SYNC_FILE_RANGE\", Const, 0, \"\"},\n\t\t{\"SYS_SYSARCH\", Const, 0, \"\"},\n\t\t{\"SYS_SYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS_SYSCALL_BASE\", Const, 0, \"\"},\n\t\t{\"SYS_SYSFS\", Const, 0, \"\"},\n\t\t{\"SYS_SYSINFO\", Const, 0, \"\"},\n\t\t{\"SYS_SYSLOG\", Const, 0, \"\"},\n\t\t{\"SYS_TEE\", Const, 0, \"\"},\n\t\t{\"SYS_TGKILL\", Const, 0, \"\"},\n\t\t{\"SYS_THREAD_SELFID\", Const, 0, \"\"},\n\t\t{\"SYS_THR_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_THR_EXIT\", Const, 0, \"\"},\n\t\t{\"SYS_THR_KILL\", Const, 0, \"\"},\n\t\t{\"SYS_THR_KILL2\", Const, 0, \"\"},\n\t\t{\"SYS_THR_NEW\", Const, 0, \"\"},\n\t\t{\"SYS_THR_SELF\", Const, 0, \"\"},\n\t\t{\"SYS_THR_SET_NAME\", Const, 0, \"\"},\n\t\t{\"SYS_THR_SUSPEND\", Const, 0, \"\"},\n\t\t{\"SYS_THR_WAKE\", Const, 0, \"\"},\n\t\t{\"SYS_TIME\", Const, 0, \"\"},\n\t\t{\"SYS_TIMERFD_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_TIMERFD_GETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_TIMERFD_SETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_TIMER_CREATE\", Const, 0, \"\"},\n\t\t{\"SYS_TIMER_DELETE\", Const, 0, \"\"},\n\t\t{\"SYS_TIMER_GETOVERRUN\", Const, 0, \"\"},\n\t\t{\"SYS_TIMER_GETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_TIMER_SETTIME\", Const, 0, \"\"},\n\t\t{\"SYS_TIMES\", Const, 0, \"\"},\n\t\t{\"SYS_TKILL\", Const, 0, \"\"},\n\t\t{\"SYS_TRUNCATE\", Const, 0, \"\"},\n\t\t{\"SYS_TRUNCATE64\", Const, 0, \"\"},\n\t\t{\"SYS_TUXCALL\", Const, 0, \"\"},\n\t\t{\"SYS_UGETRLIMIT\", Const, 0, \"\"},\n\t\t{\"SYS_ULIMIT\", Const, 0, \"\"},\n\t\t{\"SYS_UMASK\", Const, 0, \"\"},\n\t\t{\"SYS_UMASK_EXTENDED\", Const, 0, \"\"},\n\t\t{\"SYS_UMOUNT\", Const, 0, \"\"},\n\t\t{\"SYS_UMOUNT2\", Const, 0, \"\"},\n\t\t{\"SYS_UNAME\", Const, 0, \"\"},\n\t\t{\"SYS_UNDELETE\", Const, 0, \"\"},\n\t\t{\"SYS_UNLINK\", Const, 0, \"\"},\n\t\t{\"SYS_UNLINKAT\", Const, 0, \"\"},\n\t\t{\"SYS_UNMOUNT\", Const, 0, \"\"},\n\t\t{\"SYS_UNSHARE\", Const, 0, \"\"},\n\t\t{\"SYS_USELIB\", Const, 0, \"\"},\n\t\t{\"SYS_USTAT\", Const, 0, \"\"},\n\t\t{\"SYS_UTIME\", Const, 0, \"\"},\n\t\t{\"SYS_UTIMENSAT\", Const, 0, \"\"},\n\t\t{\"SYS_UTIMES\", Const, 0, \"\"},\n\t\t{\"SYS_UTRACE\", Const, 0, \"\"},\n\t\t{\"SYS_UUIDGEN\", Const, 0, \"\"},\n\t\t{\"SYS_VADVISE\", Const, 1, \"\"},\n\t\t{\"SYS_VFORK\", Const, 0, \"\"},\n\t\t{\"SYS_VHANGUP\", Const, 0, \"\"},\n\t\t{\"SYS_VM86\", Const, 0, \"\"},\n\t\t{\"SYS_VM86OLD\", Const, 0, \"\"},\n\t\t{\"SYS_VMSPLICE\", Const, 0, \"\"},\n\t\t{\"SYS_VM_PRESSURE_MONITOR\", Const, 0, \"\"},\n\t\t{\"SYS_VSERVER\", Const, 0, \"\"},\n\t\t{\"SYS_WAIT4\", Const, 0, \"\"},\n\t\t{\"SYS_WAIT4_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_WAIT6\", Const, 1, \"\"},\n\t\t{\"SYS_WAITEVENT\", Const, 0, \"\"},\n\t\t{\"SYS_WAITID\", Const, 0, \"\"},\n\t\t{\"SYS_WAITID_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_WAITPID\", Const, 0, \"\"},\n\t\t{\"SYS_WATCHEVENT\", Const, 0, \"\"},\n\t\t{\"SYS_WORKQ_KERNRETURN\", Const, 0, \"\"},\n\t\t{\"SYS_WORKQ_OPEN\", Const, 0, \"\"},\n\t\t{\"SYS_WRITE\", Const, 0, \"\"},\n\t\t{\"SYS_WRITEV\", Const, 0, \"\"},\n\t\t{\"SYS_WRITEV_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_WRITE_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS_YIELD\", Const, 0, \"\"},\n\t\t{\"SYS__LLSEEK\", Const, 0, \"\"},\n\t\t{\"SYS__LWP_CONTINUE\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_CREATE\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_CTL\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_DETACH\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_EXIT\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_GETNAME\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_GETPRIVATE\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_KILL\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_PARK\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_SELF\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_SETNAME\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_SETPRIVATE\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_SUSPEND\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_UNPARK\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_UNPARK_ALL\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_WAIT\", Const, 1, \"\"},\n\t\t{\"SYS__LWP_WAKEUP\", Const, 1, \"\"},\n\t\t{\"SYS__NEWSELECT\", Const, 0, \"\"},\n\t\t{\"SYS__PSET_BIND\", Const, 1, \"\"},\n\t\t{\"SYS__SCHED_GETAFFINITY\", Const, 1, \"\"},\n\t\t{\"SYS__SCHED_GETPARAM\", Const, 1, \"\"},\n\t\t{\"SYS__SCHED_SETAFFINITY\", Const, 1, \"\"},\n\t\t{\"SYS__SCHED_SETPARAM\", Const, 1, \"\"},\n\t\t{\"SYS__SYSCTL\", Const, 0, \"\"},\n\t\t{\"SYS__UMTX_LOCK\", Const, 0, \"\"},\n\t\t{\"SYS__UMTX_OP\", Const, 0, \"\"},\n\t\t{\"SYS__UMTX_UNLOCK\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_ACLCHECK_FD\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_ACLCHECK_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_ACLCHECK_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_DELETE_FD\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_DELETE_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_DELETE_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_GET_FD\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_GET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_GET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_SET_FD\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_SET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___ACL_SET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___CAP_RIGHTS_GET\", Const, 14, \"\"},\n\t\t{\"SYS___CLONE\", Const, 1, \"\"},\n\t\t{\"SYS___DISABLE_THREADSIGNAL\", Const, 0, \"\"},\n\t\t{\"SYS___GETCWD\", Const, 0, \"\"},\n\t\t{\"SYS___GETLOGIN\", Const, 1, \"\"},\n\t\t{\"SYS___GET_TCB\", Const, 1, \"\"},\n\t\t{\"SYS___MAC_EXECVE\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GETFSSTAT\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_FD\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_LCID\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_LCTX\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_MOUNT\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_PID\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_GET_PROC\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_MOUNT\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SET_FD\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SET_FILE\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SET_LCTX\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SET_LINK\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SET_PROC\", Const, 0, \"\"},\n\t\t{\"SYS___MAC_SYSCALL\", Const, 0, \"\"},\n\t\t{\"SYS___OLD_SEMWAIT_SIGNAL\", Const, 0, \"\"},\n\t\t{\"SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS___POSIX_CHOWN\", Const, 1, \"\"},\n\t\t{\"SYS___POSIX_FCHOWN\", Const, 1, \"\"},\n\t\t{\"SYS___POSIX_LCHOWN\", Const, 1, \"\"},\n\t\t{\"SYS___POSIX_RENAME\", Const, 1, \"\"},\n\t\t{\"SYS___PTHREAD_CANCELED\", Const, 0, \"\"},\n\t\t{\"SYS___PTHREAD_CHDIR\", Const, 0, \"\"},\n\t\t{\"SYS___PTHREAD_FCHDIR\", Const, 0, \"\"},\n\t\t{\"SYS___PTHREAD_KILL\", Const, 0, \"\"},\n\t\t{\"SYS___PTHREAD_MARKCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS___PTHREAD_SIGMASK\", Const, 0, \"\"},\n\t\t{\"SYS___QUOTACTL\", Const, 1, \"\"},\n\t\t{\"SYS___SEMCTL\", Const, 1, \"\"},\n\t\t{\"SYS___SEMWAIT_SIGNAL\", Const, 0, \"\"},\n\t\t{\"SYS___SEMWAIT_SIGNAL_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS___SETLOGIN\", Const, 1, \"\"},\n\t\t{\"SYS___SETUGID\", Const, 0, \"\"},\n\t\t{\"SYS___SET_TCB\", Const, 1, \"\"},\n\t\t{\"SYS___SIGACTION_SIGTRAMP\", Const, 1, \"\"},\n\t\t{\"SYS___SIGTIMEDWAIT\", Const, 1, \"\"},\n\t\t{\"SYS___SIGWAIT\", Const, 0, \"\"},\n\t\t{\"SYS___SIGWAIT_NOCANCEL\", Const, 0, \"\"},\n\t\t{\"SYS___SYSCTL\", Const, 0, \"\"},\n\t\t{\"SYS___TFORK\", Const, 1, \"\"},\n\t\t{\"SYS___THREXIT\", Const, 1, \"\"},\n\t\t{\"SYS___THRSIGDIVERT\", Const, 1, \"\"},\n\t\t{\"SYS___THRSLEEP\", Const, 1, \"\"},\n\t\t{\"SYS___THRWAKEUP\", Const, 1, \"\"},\n\t\t{\"S_ARCH1\", Const, 1, \"\"},\n\t\t{\"S_ARCH2\", Const, 1, \"\"},\n\t\t{\"S_BLKSIZE\", Const, 0, \"\"},\n\t\t{\"S_IEXEC\", Const, 0, \"\"},\n\t\t{\"S_IFBLK\", Const, 0, \"\"},\n\t\t{\"S_IFCHR\", Const, 0, \"\"},\n\t\t{\"S_IFDIR\", Const, 0, \"\"},\n\t\t{\"S_IFIFO\", Const, 0, \"\"},\n\t\t{\"S_IFLNK\", Const, 0, \"\"},\n\t\t{\"S_IFMT\", Const, 0, \"\"},\n\t\t{\"S_IFREG\", Const, 0, \"\"},\n\t\t{\"S_IFSOCK\", Const, 0, \"\"},\n\t\t{\"S_IFWHT\", Const, 0, \"\"},\n\t\t{\"S_IREAD\", Const, 0, \"\"},\n\t\t{\"S_IRGRP\", Const, 0, \"\"},\n\t\t{\"S_IROTH\", Const, 0, \"\"},\n\t\t{\"S_IRUSR\", Const, 0, \"\"},\n\t\t{\"S_IRWXG\", Const, 0, \"\"},\n\t\t{\"S_IRWXO\", Const, 0, \"\"},\n\t\t{\"S_IRWXU\", Const, 0, \"\"},\n\t\t{\"S_ISGID\", Const, 0, \"\"},\n\t\t{\"S_ISTXT\", Const, 0, \"\"},\n\t\t{\"S_ISUID\", Const, 0, \"\"},\n\t\t{\"S_ISVTX\", Const, 0, \"\"},\n\t\t{\"S_IWGRP\", Const, 0, \"\"},\n\t\t{\"S_IWOTH\", Const, 0, \"\"},\n\t\t{\"S_IWRITE\", Const, 0, \"\"},\n\t\t{\"S_IWUSR\", Const, 0, \"\"},\n\t\t{\"S_IXGRP\", Const, 0, \"\"},\n\t\t{\"S_IXOTH\", Const, 0, \"\"},\n\t\t{\"S_IXUSR\", Const, 0, \"\"},\n\t\t{\"S_LOGIN_SET\", Const, 1, \"\"},\n\t\t{\"SecurityAttributes\", Type, 0, \"\"},\n\t\t{\"SecurityAttributes.InheritHandle\", Field, 0, \"\"},\n\t\t{\"SecurityAttributes.Length\", Field, 0, \"\"},\n\t\t{\"SecurityAttributes.SecurityDescriptor\", Field, 0, \"\"},\n\t\t{\"Seek\", Func, 0, \"func(fd int, offset int64, whence int) (off int64, err error)\"},\n\t\t{\"Select\", Func, 0, \"func(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)\"},\n\t\t{\"Sendfile\", Func, 0, \"func(outfd int, infd int, offset *int64, count int) (written int, err error)\"},\n\t\t{\"Sendmsg\", Func, 0, \"func(fd int, p []byte, oob []byte, to Sockaddr, flags int) (err error)\"},\n\t\t{\"SendmsgN\", Func, 3, \"func(fd int, p []byte, oob []byte, to Sockaddr, flags int) (n int, err error)\"},\n\t\t{\"Sendto\", Func, 0, \"func(fd int, p []byte, flags int, to Sockaddr) (err error)\"},\n\t\t{\"Servent\", Type, 0, \"\"},\n\t\t{\"Servent.Aliases\", Field, 0, \"\"},\n\t\t{\"Servent.Name\", Field, 0, \"\"},\n\t\t{\"Servent.Port\", Field, 0, \"\"},\n\t\t{\"Servent.Proto\", Field, 0, \"\"},\n\t\t{\"SetBpf\", Func, 0, \"\"},\n\t\t{\"SetBpfBuflen\", Func, 0, \"\"},\n\t\t{\"SetBpfDatalink\", Func, 0, \"\"},\n\t\t{\"SetBpfHeadercmpl\", Func, 0, \"\"},\n\t\t{\"SetBpfImmediate\", Func, 0, \"\"},\n\t\t{\"SetBpfInterface\", Func, 0, \"\"},\n\t\t{\"SetBpfPromisc\", Func, 0, \"\"},\n\t\t{\"SetBpfTimeout\", Func, 0, \"\"},\n\t\t{\"SetCurrentDirectory\", Func, 0, \"\"},\n\t\t{\"SetEndOfFile\", Func, 0, \"\"},\n\t\t{\"SetEnvironmentVariable\", Func, 0, \"\"},\n\t\t{\"SetFileAttributes\", Func, 0, \"\"},\n\t\t{\"SetFileCompletionNotificationModes\", Func, 2, \"\"},\n\t\t{\"SetFilePointer\", Func, 0, \"\"},\n\t\t{\"SetFileTime\", Func, 0, \"\"},\n\t\t{\"SetHandleInformation\", Func, 0, \"\"},\n\t\t{\"SetKevent\", Func, 0, \"\"},\n\t\t{\"SetLsfPromisc\", Func, 0, \"func(name string, m bool) error\"},\n\t\t{\"SetNonblock\", Func, 0, \"func(fd int, nonblocking bool) (err error)\"},\n\t\t{\"Setdomainname\", Func, 0, \"func(p []byte) (err error)\"},\n\t\t{\"Setegid\", Func, 0, \"func(egid int) (err error)\"},\n\t\t{\"Setenv\", Func, 0, \"func(key string, value string) error\"},\n\t\t{\"Seteuid\", Func, 0, \"func(euid int) (err error)\"},\n\t\t{\"Setfsgid\", Func, 0, \"func(gid int) (err error)\"},\n\t\t{\"Setfsuid\", Func, 0, \"func(uid int) (err error)\"},\n\t\t{\"Setgid\", Func, 0, \"func(gid int) (err error)\"},\n\t\t{\"Setgroups\", Func, 0, \"func(gids []int) (err error)\"},\n\t\t{\"Sethostname\", Func, 0, \"func(p []byte) (err error)\"},\n\t\t{\"Setlogin\", Func, 0, \"\"},\n\t\t{\"Setpgid\", Func, 0, \"func(pid int, pgid int) (err error)\"},\n\t\t{\"Setpriority\", Func, 0, \"func(which int, who int, prio int) (err error)\"},\n\t\t{\"Setprivexec\", Func, 0, \"\"},\n\t\t{\"Setregid\", Func, 0, \"func(rgid int, egid int) (err error)\"},\n\t\t{\"Setresgid\", Func, 0, \"func(rgid int, egid int, sgid int) (err error)\"},\n\t\t{\"Setresuid\", Func, 0, \"func(ruid int, euid int, suid int) (err error)\"},\n\t\t{\"Setreuid\", Func, 0, \"func(ruid int, euid int) (err error)\"},\n\t\t{\"Setrlimit\", Func, 0, \"func(resource int, rlim *Rlimit) error\"},\n\t\t{\"Setsid\", Func, 0, \"func() (pid int, err error)\"},\n\t\t{\"Setsockopt\", Func, 0, \"\"},\n\t\t{\"SetsockoptByte\", Func, 0, \"func(fd int, level int, opt int, value byte) (err error)\"},\n\t\t{\"SetsockoptICMPv6Filter\", Func, 2, \"func(fd int, level int, opt int, filter *ICMPv6Filter) error\"},\n\t\t{\"SetsockoptIPMreq\", Func, 0, \"func(fd int, level int, opt int, mreq *IPMreq) (err error)\"},\n\t\t{\"SetsockoptIPMreqn\", Func, 0, \"func(fd int, level int, opt int, mreq *IPMreqn) (err error)\"},\n\t\t{\"SetsockoptIPv6Mreq\", Func, 0, \"func(fd int, level int, opt int, mreq *IPv6Mreq) (err error)\"},\n\t\t{\"SetsockoptInet4Addr\", Func, 0, \"func(fd int, level int, opt int, value [4]byte) (err error)\"},\n\t\t{\"SetsockoptInt\", Func, 0, \"func(fd int, level int, opt int, value int) (err error)\"},\n\t\t{\"SetsockoptLinger\", Func, 0, \"func(fd int, level int, opt int, l *Linger) (err error)\"},\n\t\t{\"SetsockoptString\", Func, 0, \"func(fd int, level int, opt int, s string) (err error)\"},\n\t\t{\"SetsockoptTimeval\", Func, 0, \"func(fd int, level int, opt int, tv *Timeval) (err error)\"},\n\t\t{\"Settimeofday\", Func, 0, \"func(tv *Timeval) (err error)\"},\n\t\t{\"Setuid\", Func, 0, \"func(uid int) (err error)\"},\n\t\t{\"Setxattr\", Func, 1, \"func(path string, attr string, data []byte, flags int) (err error)\"},\n\t\t{\"Shutdown\", Func, 0, \"func(fd int, how int) (err error)\"},\n\t\t{\"SidTypeAlias\", Const, 0, \"\"},\n\t\t{\"SidTypeComputer\", Const, 0, \"\"},\n\t\t{\"SidTypeDeletedAccount\", Const, 0, \"\"},\n\t\t{\"SidTypeDomain\", Const, 0, \"\"},\n\t\t{\"SidTypeGroup\", Const, 0, \"\"},\n\t\t{\"SidTypeInvalid\", Const, 0, \"\"},\n\t\t{\"SidTypeLabel\", Const, 0, \"\"},\n\t\t{\"SidTypeUnknown\", Const, 0, \"\"},\n\t\t{\"SidTypeUser\", Const, 0, \"\"},\n\t\t{\"SidTypeWellKnownGroup\", Const, 0, \"\"},\n\t\t{\"Signal\", Type, 0, \"\"},\n\t\t{\"SizeofBpfHdr\", Const, 0, \"\"},\n\t\t{\"SizeofBpfInsn\", Const, 0, \"\"},\n\t\t{\"SizeofBpfProgram\", Const, 0, \"\"},\n\t\t{\"SizeofBpfStat\", Const, 0, \"\"},\n\t\t{\"SizeofBpfVersion\", Const, 0, \"\"},\n\t\t{\"SizeofBpfZbuf\", Const, 0, \"\"},\n\t\t{\"SizeofBpfZbufHeader\", Const, 0, \"\"},\n\t\t{\"SizeofCmsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofICMPv6Filter\", Const, 2, \"\"},\n\t\t{\"SizeofIPMreq\", Const, 0, \"\"},\n\t\t{\"SizeofIPMreqn\", Const, 0, \"\"},\n\t\t{\"SizeofIPv6MTUInfo\", Const, 2, \"\"},\n\t\t{\"SizeofIPv6Mreq\", Const, 0, \"\"},\n\t\t{\"SizeofIfAddrmsg\", Const, 0, \"\"},\n\t\t{\"SizeofIfAnnounceMsghdr\", Const, 1, \"\"},\n\t\t{\"SizeofIfData\", Const, 0, \"\"},\n\t\t{\"SizeofIfInfomsg\", Const, 0, \"\"},\n\t\t{\"SizeofIfMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofIfaMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofIfmaMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofIfmaMsghdr2\", Const, 0, \"\"},\n\t\t{\"SizeofInet4Pktinfo\", Const, 0, \"\"},\n\t\t{\"SizeofInet6Pktinfo\", Const, 0, \"\"},\n\t\t{\"SizeofInotifyEvent\", Const, 0, \"\"},\n\t\t{\"SizeofLinger\", Const, 0, \"\"},\n\t\t{\"SizeofMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofNlAttr\", Const, 0, \"\"},\n\t\t{\"SizeofNlMsgerr\", Const, 0, \"\"},\n\t\t{\"SizeofNlMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofRtAttr\", Const, 0, \"\"},\n\t\t{\"SizeofRtGenmsg\", Const, 0, \"\"},\n\t\t{\"SizeofRtMetrics\", Const, 0, \"\"},\n\t\t{\"SizeofRtMsg\", Const, 0, \"\"},\n\t\t{\"SizeofRtMsghdr\", Const, 0, \"\"},\n\t\t{\"SizeofRtNexthop\", Const, 0, \"\"},\n\t\t{\"SizeofSockFilter\", Const, 0, \"\"},\n\t\t{\"SizeofSockFprog\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrAny\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrDatalink\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrInet4\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrInet6\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrLinklayer\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrNetlink\", Const, 0, \"\"},\n\t\t{\"SizeofSockaddrUnix\", Const, 0, \"\"},\n\t\t{\"SizeofTCPInfo\", Const, 1, \"\"},\n\t\t{\"SizeofUcred\", Const, 0, \"\"},\n\t\t{\"SlicePtrFromStrings\", Func, 1, \"func(ss []string) ([]*byte, error)\"},\n\t\t{\"SockFilter\", Type, 0, \"\"},\n\t\t{\"SockFilter.Code\", Field, 0, \"\"},\n\t\t{\"SockFilter.Jf\", Field, 0, \"\"},\n\t\t{\"SockFilter.Jt\", Field, 0, \"\"},\n\t\t{\"SockFilter.K\", Field, 0, \"\"},\n\t\t{\"SockFprog\", Type, 0, \"\"},\n\t\t{\"SockFprog.Filter\", Field, 0, \"\"},\n\t\t{\"SockFprog.Len\", Field, 0, \"\"},\n\t\t{\"SockFprog.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink\", Type, 0, \"\"},\n\t\t{\"SockaddrDatalink.Alen\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Data\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Family\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Index\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Len\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Nlen\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Slen\", Field, 0, \"\"},\n\t\t{\"SockaddrDatalink.Type\", Field, 0, \"\"},\n\t\t{\"SockaddrGen\", Type, 0, \"\"},\n\t\t{\"SockaddrInet4\", Type, 0, \"\"},\n\t\t{\"SockaddrInet4.Addr\", Field, 0, \"\"},\n\t\t{\"SockaddrInet4.Port\", Field, 0, \"\"},\n\t\t{\"SockaddrInet6\", Type, 0, \"\"},\n\t\t{\"SockaddrInet6.Addr\", Field, 0, \"\"},\n\t\t{\"SockaddrInet6.Port\", Field, 0, \"\"},\n\t\t{\"SockaddrInet6.ZoneId\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer\", Type, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Addr\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Halen\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Hatype\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Ifindex\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Pkttype\", Field, 0, \"\"},\n\t\t{\"SockaddrLinklayer.Protocol\", Field, 0, \"\"},\n\t\t{\"SockaddrNetlink\", Type, 0, \"\"},\n\t\t{\"SockaddrNetlink.Family\", Field, 0, \"\"},\n\t\t{\"SockaddrNetlink.Groups\", Field, 0, \"\"},\n\t\t{\"SockaddrNetlink.Pad\", Field, 0, \"\"},\n\t\t{\"SockaddrNetlink.Pid\", Field, 0, \"\"},\n\t\t{\"SockaddrUnix\", Type, 0, \"\"},\n\t\t{\"SockaddrUnix.Name\", Field, 0, \"\"},\n\t\t{\"Socket\", Func, 0, \"func(domain int, typ int, proto int) (fd int, err error)\"},\n\t\t{\"SocketControlMessage\", Type, 0, \"\"},\n\t\t{\"SocketControlMessage.Data\", Field, 0, \"\"},\n\t\t{\"SocketControlMessage.Header\", Field, 0, \"\"},\n\t\t{\"SocketDisableIPv6\", Var, 0, \"\"},\n\t\t{\"Socketpair\", Func, 0, \"func(domain int, typ int, proto int) (fd [2]int, err error)\"},\n\t\t{\"Splice\", Func, 0, \"func(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)\"},\n\t\t{\"StartProcess\", Func, 0, \"func(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error)\"},\n\t\t{\"StartupInfo\", Type, 0, \"\"},\n\t\t{\"StartupInfo.Cb\", Field, 0, \"\"},\n\t\t{\"StartupInfo.Desktop\", Field, 0, \"\"},\n\t\t{\"StartupInfo.FillAttribute\", Field, 0, \"\"},\n\t\t{\"StartupInfo.Flags\", Field, 0, \"\"},\n\t\t{\"StartupInfo.ShowWindow\", Field, 0, \"\"},\n\t\t{\"StartupInfo.StdErr\", Field, 0, \"\"},\n\t\t{\"StartupInfo.StdInput\", Field, 0, \"\"},\n\t\t{\"StartupInfo.StdOutput\", Field, 0, \"\"},\n\t\t{\"StartupInfo.Title\", Field, 0, \"\"},\n\t\t{\"StartupInfo.X\", Field, 0, \"\"},\n\t\t{\"StartupInfo.XCountChars\", Field, 0, \"\"},\n\t\t{\"StartupInfo.XSize\", Field, 0, \"\"},\n\t\t{\"StartupInfo.Y\", Field, 0, \"\"},\n\t\t{\"StartupInfo.YCountChars\", Field, 0, \"\"},\n\t\t{\"StartupInfo.YSize\", Field, 0, \"\"},\n\t\t{\"Stat\", Func, 0, \"func(path string, stat *Stat_t) (err error)\"},\n\t\t{\"Stat_t\", Type, 0, \"\"},\n\t\t{\"Stat_t.Atim\", Field, 0, \"\"},\n\t\t{\"Stat_t.Atim_ext\", Field, 12, \"\"},\n\t\t{\"Stat_t.Atimespec\", Field, 0, \"\"},\n\t\t{\"Stat_t.Birthtimespec\", Field, 0, \"\"},\n\t\t{\"Stat_t.Blksize\", Field, 0, \"\"},\n\t\t{\"Stat_t.Blocks\", Field, 0, \"\"},\n\t\t{\"Stat_t.Btim_ext\", Field, 12, \"\"},\n\t\t{\"Stat_t.Ctim\", Field, 0, \"\"},\n\t\t{\"Stat_t.Ctim_ext\", Field, 12, \"\"},\n\t\t{\"Stat_t.Ctimespec\", Field, 0, \"\"},\n\t\t{\"Stat_t.Dev\", Field, 0, \"\"},\n\t\t{\"Stat_t.Flags\", Field, 0, \"\"},\n\t\t{\"Stat_t.Gen\", Field, 0, \"\"},\n\t\t{\"Stat_t.Gid\", Field, 0, \"\"},\n\t\t{\"Stat_t.Ino\", Field, 0, \"\"},\n\t\t{\"Stat_t.Lspare\", Field, 0, \"\"},\n\t\t{\"Stat_t.Lspare0\", Field, 2, \"\"},\n\t\t{\"Stat_t.Lspare1\", Field, 2, \"\"},\n\t\t{\"Stat_t.Mode\", Field, 0, \"\"},\n\t\t{\"Stat_t.Mtim\", Field, 0, \"\"},\n\t\t{\"Stat_t.Mtim_ext\", Field, 12, \"\"},\n\t\t{\"Stat_t.Mtimespec\", Field, 0, \"\"},\n\t\t{\"Stat_t.Nlink\", Field, 0, \"\"},\n\t\t{\"Stat_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Stat_t.Pad_cgo_1\", Field, 0, \"\"},\n\t\t{\"Stat_t.Pad_cgo_2\", Field, 0, \"\"},\n\t\t{\"Stat_t.Padding0\", Field, 12, \"\"},\n\t\t{\"Stat_t.Padding1\", Field, 12, \"\"},\n\t\t{\"Stat_t.Qspare\", Field, 0, \"\"},\n\t\t{\"Stat_t.Rdev\", Field, 0, \"\"},\n\t\t{\"Stat_t.Size\", Field, 0, \"\"},\n\t\t{\"Stat_t.Spare\", Field, 2, \"\"},\n\t\t{\"Stat_t.Uid\", Field, 0, \"\"},\n\t\t{\"Stat_t.X__pad0\", Field, 0, \"\"},\n\t\t{\"Stat_t.X__pad1\", Field, 0, \"\"},\n\t\t{\"Stat_t.X__pad2\", Field, 0, \"\"},\n\t\t{\"Stat_t.X__st_birthtim\", Field, 2, \"\"},\n\t\t{\"Stat_t.X__st_ino\", Field, 0, \"\"},\n\t\t{\"Stat_t.X__unused\", Field, 0, \"\"},\n\t\t{\"Statfs\", Func, 0, \"func(path string, buf *Statfs_t) (err error)\"},\n\t\t{\"Statfs_t\", Type, 0, \"\"},\n\t\t{\"Statfs_t.Asyncreads\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Asyncwrites\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Bavail\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Bfree\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Blocks\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Bsize\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Charspare\", Field, 0, \"\"},\n\t\t{\"Statfs_t.F_asyncreads\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_asyncwrites\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_bavail\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_bfree\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_blocks\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_bsize\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_ctime\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_favail\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_ffree\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_files\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_flags\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_fsid\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_fstypename\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_iosize\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_mntfromname\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_mntfromspec\", Field, 3, \"\"},\n\t\t{\"Statfs_t.F_mntonname\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_namemax\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_owner\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_spare\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_syncreads\", Field, 2, \"\"},\n\t\t{\"Statfs_t.F_syncwrites\", Field, 2, \"\"},\n\t\t{\"Statfs_t.Ffree\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Files\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Flags\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Frsize\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Fsid\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Fssubtype\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Fstypename\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Iosize\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Mntfromname\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Mntonname\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Mount_info\", Field, 2, \"\"},\n\t\t{\"Statfs_t.Namelen\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Namemax\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Owner\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Pad_cgo_1\", Field, 2, \"\"},\n\t\t{\"Statfs_t.Reserved\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Spare\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Syncreads\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Syncwrites\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Type\", Field, 0, \"\"},\n\t\t{\"Statfs_t.Version\", Field, 0, \"\"},\n\t\t{\"Stderr\", Var, 0, \"\"},\n\t\t{\"Stdin\", Var, 0, \"\"},\n\t\t{\"Stdout\", Var, 0, \"\"},\n\t\t{\"StringBytePtr\", Func, 0, \"func(s string) *byte\"},\n\t\t{\"StringByteSlice\", Func, 0, \"func(s string) []byte\"},\n\t\t{\"StringSlicePtr\", Func, 0, \"func(ss []string) []*byte\"},\n\t\t{\"StringToSid\", Func, 0, \"\"},\n\t\t{\"StringToUTF16\", Func, 0, \"\"},\n\t\t{\"StringToUTF16Ptr\", Func, 0, \"\"},\n\t\t{\"Symlink\", Func, 0, \"func(oldpath string, newpath string) (err error)\"},\n\t\t{\"Sync\", Func, 0, \"func()\"},\n\t\t{\"SyncFileRange\", Func, 0, \"func(fd int, off int64, n int64, flags int) (err error)\"},\n\t\t{\"SysProcAttr\", Type, 0, \"\"},\n\t\t{\"SysProcAttr.AdditionalInheritedHandles\", Field, 17, \"\"},\n\t\t{\"SysProcAttr.AmbientCaps\", Field, 9, \"\"},\n\t\t{\"SysProcAttr.CgroupFD\", Field, 20, \"\"},\n\t\t{\"SysProcAttr.Chroot\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Cloneflags\", Field, 2, \"\"},\n\t\t{\"SysProcAttr.CmdLine\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.CreationFlags\", Field, 1, \"\"},\n\t\t{\"SysProcAttr.Credential\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Ctty\", Field, 1, \"\"},\n\t\t{\"SysProcAttr.Foreground\", Field, 5, \"\"},\n\t\t{\"SysProcAttr.GidMappings\", Field, 4, \"\"},\n\t\t{\"SysProcAttr.GidMappingsEnableSetgroups\", Field, 5, \"\"},\n\t\t{\"SysProcAttr.HideWindow\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Jail\", Field, 21, \"\"},\n\t\t{\"SysProcAttr.NoInheritHandles\", Field, 16, \"\"},\n\t\t{\"SysProcAttr.Noctty\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.ParentProcess\", Field, 17, \"\"},\n\t\t{\"SysProcAttr.Pdeathsig\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Pgid\", Field, 5, \"\"},\n\t\t{\"SysProcAttr.PidFD\", Field, 22, \"\"},\n\t\t{\"SysProcAttr.ProcessAttributes\", Field, 13, \"\"},\n\t\t{\"SysProcAttr.Ptrace\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Setctty\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Setpgid\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.Setsid\", Field, 0, \"\"},\n\t\t{\"SysProcAttr.ThreadAttributes\", Field, 13, \"\"},\n\t\t{\"SysProcAttr.Token\", Field, 10, \"\"},\n\t\t{\"SysProcAttr.UidMappings\", Field, 4, \"\"},\n\t\t{\"SysProcAttr.Unshareflags\", Field, 7, \"\"},\n\t\t{\"SysProcAttr.UseCgroupFD\", Field, 20, \"\"},\n\t\t{\"SysProcIDMap\", Type, 4, \"\"},\n\t\t{\"SysProcIDMap.ContainerID\", Field, 4, \"\"},\n\t\t{\"SysProcIDMap.HostID\", Field, 4, \"\"},\n\t\t{\"SysProcIDMap.Size\", Field, 4, \"\"},\n\t\t{\"Syscall\", Func, 0, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"Syscall12\", Func, 0, \"\"},\n\t\t{\"Syscall15\", Func, 0, \"\"},\n\t\t{\"Syscall18\", Func, 12, \"\"},\n\t\t{\"Syscall6\", Func, 0, \"func(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err Errno)\"},\n\t\t{\"Syscall9\", Func, 0, \"\"},\n\t\t{\"SyscallN\", Func, 18, \"\"},\n\t\t{\"Sysctl\", Func, 0, \"\"},\n\t\t{\"SysctlUint32\", Func, 0, \"\"},\n\t\t{\"Sysctlnode\", Type, 2, \"\"},\n\t\t{\"Sysctlnode.Flags\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.Name\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.Num\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.Un\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.Ver\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.X__rsvd\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.X_sysctl_desc\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.X_sysctl_func\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.X_sysctl_parent\", Field, 2, \"\"},\n\t\t{\"Sysctlnode.X_sysctl_size\", Field, 2, \"\"},\n\t\t{\"Sysinfo\", Func, 0, \"func(info *Sysinfo_t) (err error)\"},\n\t\t{\"Sysinfo_t\", Type, 0, \"\"},\n\t\t{\"Sysinfo_t.Bufferram\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Freehigh\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Freeram\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Freeswap\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Loads\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Pad\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Pad_cgo_1\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Procs\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Sharedram\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Totalhigh\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Totalram\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Totalswap\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Unit\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.Uptime\", Field, 0, \"\"},\n\t\t{\"Sysinfo_t.X_f\", Field, 0, \"\"},\n\t\t{\"Systemtime\", Type, 0, \"\"},\n\t\t{\"Systemtime.Day\", Field, 0, \"\"},\n\t\t{\"Systemtime.DayOfWeek\", Field, 0, \"\"},\n\t\t{\"Systemtime.Hour\", Field, 0, \"\"},\n\t\t{\"Systemtime.Milliseconds\", Field, 0, \"\"},\n\t\t{\"Systemtime.Minute\", Field, 0, \"\"},\n\t\t{\"Systemtime.Month\", Field, 0, \"\"},\n\t\t{\"Systemtime.Second\", Field, 0, \"\"},\n\t\t{\"Systemtime.Year\", Field, 0, \"\"},\n\t\t{\"TCGETS\", Const, 0, \"\"},\n\t\t{\"TCIFLUSH\", Const, 1, \"\"},\n\t\t{\"TCIOFLUSH\", Const, 1, \"\"},\n\t\t{\"TCOFLUSH\", Const, 1, \"\"},\n\t\t{\"TCPInfo\", Type, 1, \"\"},\n\t\t{\"TCPInfo.Advmss\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Ato\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Backoff\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Ca_state\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Fackets\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Last_ack_recv\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Last_ack_sent\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Last_data_recv\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Last_data_sent\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Lost\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Options\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Pad_cgo_0\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Pmtu\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Probes\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rcv_mss\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rcv_rtt\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rcv_space\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rcv_ssthresh\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Reordering\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Retrans\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Retransmits\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rto\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rtt\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Rttvar\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Sacked\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Snd_cwnd\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Snd_mss\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Snd_ssthresh\", Field, 1, \"\"},\n\t\t{\"TCPInfo.State\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Total_retrans\", Field, 1, \"\"},\n\t\t{\"TCPInfo.Unacked\", Field, 1, \"\"},\n\t\t{\"TCPKeepalive\", Type, 3, \"\"},\n\t\t{\"TCPKeepalive.Interval\", Field, 3, \"\"},\n\t\t{\"TCPKeepalive.OnOff\", Field, 3, \"\"},\n\t\t{\"TCPKeepalive.Time\", Field, 3, \"\"},\n\t\t{\"TCP_CA_NAME_MAX\", Const, 0, \"\"},\n\t\t{\"TCP_CONGCTL\", Const, 1, \"\"},\n\t\t{\"TCP_CONGESTION\", Const, 0, \"\"},\n\t\t{\"TCP_CONNECTIONTIMEOUT\", Const, 0, \"\"},\n\t\t{\"TCP_CORK\", Const, 0, \"\"},\n\t\t{\"TCP_DEFER_ACCEPT\", Const, 0, \"\"},\n\t\t{\"TCP_ENABLE_ECN\", Const, 16, \"\"},\n\t\t{\"TCP_INFO\", Const, 0, \"\"},\n\t\t{\"TCP_KEEPALIVE\", Const, 0, \"\"},\n\t\t{\"TCP_KEEPCNT\", Const, 0, \"\"},\n\t\t{\"TCP_KEEPIDLE\", Const, 0, \"\"},\n\t\t{\"TCP_KEEPINIT\", Const, 1, \"\"},\n\t\t{\"TCP_KEEPINTVL\", Const, 0, \"\"},\n\t\t{\"TCP_LINGER2\", Const, 0, \"\"},\n\t\t{\"TCP_MAXBURST\", Const, 0, \"\"},\n\t\t{\"TCP_MAXHLEN\", Const, 0, \"\"},\n\t\t{\"TCP_MAXOLEN\", Const, 0, \"\"},\n\t\t{\"TCP_MAXSEG\", Const, 0, \"\"},\n\t\t{\"TCP_MAXWIN\", Const, 0, \"\"},\n\t\t{\"TCP_MAX_SACK\", Const, 0, \"\"},\n\t\t{\"TCP_MAX_WINSHIFT\", Const, 0, \"\"},\n\t\t{\"TCP_MD5SIG\", Const, 0, \"\"},\n\t\t{\"TCP_MD5SIG_MAXKEYLEN\", Const, 0, \"\"},\n\t\t{\"TCP_MINMSS\", Const, 0, \"\"},\n\t\t{\"TCP_MINMSSOVERLOAD\", Const, 0, \"\"},\n\t\t{\"TCP_MSS\", Const, 0, \"\"},\n\t\t{\"TCP_NODELAY\", Const, 0, \"\"},\n\t\t{\"TCP_NOOPT\", Const, 0, \"\"},\n\t\t{\"TCP_NOPUSH\", Const, 0, \"\"},\n\t\t{\"TCP_NOTSENT_LOWAT\", Const, 16, \"\"},\n\t\t{\"TCP_NSTATES\", Const, 1, \"\"},\n\t\t{\"TCP_QUICKACK\", Const, 0, \"\"},\n\t\t{\"TCP_RXT_CONNDROPTIME\", Const, 0, \"\"},\n\t\t{\"TCP_RXT_FINDROP\", Const, 0, \"\"},\n\t\t{\"TCP_SACK_ENABLE\", Const, 1, \"\"},\n\t\t{\"TCP_SENDMOREACKS\", Const, 16, \"\"},\n\t\t{\"TCP_SYNCNT\", Const, 0, \"\"},\n\t\t{\"TCP_VENDOR\", Const, 3, \"\"},\n\t\t{\"TCP_WINDOW_CLAMP\", Const, 0, \"\"},\n\t\t{\"TCSAFLUSH\", Const, 1, \"\"},\n\t\t{\"TCSETS\", Const, 0, \"\"},\n\t\t{\"TF_DISCONNECT\", Const, 0, \"\"},\n\t\t{\"TF_REUSE_SOCKET\", Const, 0, \"\"},\n\t\t{\"TF_USE_DEFAULT_WORKER\", Const, 0, \"\"},\n\t\t{\"TF_USE_KERNEL_APC\", Const, 0, \"\"},\n\t\t{\"TF_USE_SYSTEM_THREAD\", Const, 0, \"\"},\n\t\t{\"TF_WRITE_BEHIND\", Const, 0, \"\"},\n\t\t{\"TH32CS_INHERIT\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPALL\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPHEAPLIST\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPMODULE\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPMODULE32\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPPROCESS\", Const, 4, \"\"},\n\t\t{\"TH32CS_SNAPTHREAD\", Const, 4, \"\"},\n\t\t{\"TIME_ZONE_ID_DAYLIGHT\", Const, 0, \"\"},\n\t\t{\"TIME_ZONE_ID_STANDARD\", Const, 0, \"\"},\n\t\t{\"TIME_ZONE_ID_UNKNOWN\", Const, 0, \"\"},\n\t\t{\"TIOCCBRK\", Const, 0, \"\"},\n\t\t{\"TIOCCDTR\", Const, 0, \"\"},\n\t\t{\"TIOCCONS\", Const, 0, \"\"},\n\t\t{\"TIOCDCDTIMESTAMP\", Const, 0, \"\"},\n\t\t{\"TIOCDRAIN\", Const, 0, \"\"},\n\t\t{\"TIOCDSIMICROCODE\", Const, 0, \"\"},\n\t\t{\"TIOCEXCL\", Const, 0, \"\"},\n\t\t{\"TIOCEXT\", Const, 0, \"\"},\n\t\t{\"TIOCFLAG_CDTRCTS\", Const, 1, \"\"},\n\t\t{\"TIOCFLAG_CLOCAL\", Const, 1, \"\"},\n\t\t{\"TIOCFLAG_CRTSCTS\", Const, 1, \"\"},\n\t\t{\"TIOCFLAG_MDMBUF\", Const, 1, \"\"},\n\t\t{\"TIOCFLAG_PPS\", Const, 1, \"\"},\n\t\t{\"TIOCFLAG_SOFTCAR\", Const, 1, \"\"},\n\t\t{\"TIOCFLUSH\", Const, 0, \"\"},\n\t\t{\"TIOCGDEV\", Const, 0, \"\"},\n\t\t{\"TIOCGDRAINWAIT\", Const, 0, \"\"},\n\t\t{\"TIOCGETA\", Const, 0, \"\"},\n\t\t{\"TIOCGETD\", Const, 0, \"\"},\n\t\t{\"TIOCGFLAGS\", Const, 1, \"\"},\n\t\t{\"TIOCGICOUNT\", Const, 0, \"\"},\n\t\t{\"TIOCGLCKTRMIOS\", Const, 0, \"\"},\n\t\t{\"TIOCGLINED\", Const, 1, \"\"},\n\t\t{\"TIOCGPGRP\", Const, 0, \"\"},\n\t\t{\"TIOCGPTN\", Const, 0, \"\"},\n\t\t{\"TIOCGQSIZE\", Const, 1, \"\"},\n\t\t{\"TIOCGRANTPT\", Const, 1, \"\"},\n\t\t{\"TIOCGRS485\", Const, 0, \"\"},\n\t\t{\"TIOCGSERIAL\", Const, 0, \"\"},\n\t\t{\"TIOCGSID\", Const, 0, \"\"},\n\t\t{\"TIOCGSIZE\", Const, 1, \"\"},\n\t\t{\"TIOCGSOFTCAR\", Const, 0, \"\"},\n\t\t{\"TIOCGTSTAMP\", Const, 1, \"\"},\n\t\t{\"TIOCGWINSZ\", Const, 0, \"\"},\n\t\t{\"TIOCINQ\", Const, 0, \"\"},\n\t\t{\"TIOCIXOFF\", Const, 0, \"\"},\n\t\t{\"TIOCIXON\", Const, 0, \"\"},\n\t\t{\"TIOCLINUX\", Const, 0, \"\"},\n\t\t{\"TIOCMBIC\", Const, 0, \"\"},\n\t\t{\"TIOCMBIS\", Const, 0, \"\"},\n\t\t{\"TIOCMGDTRWAIT\", Const, 0, \"\"},\n\t\t{\"TIOCMGET\", Const, 0, \"\"},\n\t\t{\"TIOCMIWAIT\", Const, 0, \"\"},\n\t\t{\"TIOCMODG\", Const, 0, \"\"},\n\t\t{\"TIOCMODS\", Const, 0, \"\"},\n\t\t{\"TIOCMSDTRWAIT\", Const, 0, \"\"},\n\t\t{\"TIOCMSET\", Const, 0, \"\"},\n\t\t{\"TIOCM_CAR\", Const, 0, \"\"},\n\t\t{\"TIOCM_CD\", Const, 0, \"\"},\n\t\t{\"TIOCM_CTS\", Const, 0, \"\"},\n\t\t{\"TIOCM_DCD\", Const, 0, \"\"},\n\t\t{\"TIOCM_DSR\", Const, 0, \"\"},\n\t\t{\"TIOCM_DTR\", Const, 0, \"\"},\n\t\t{\"TIOCM_LE\", Const, 0, \"\"},\n\t\t{\"TIOCM_RI\", Const, 0, \"\"},\n\t\t{\"TIOCM_RNG\", Const, 0, \"\"},\n\t\t{\"TIOCM_RTS\", Const, 0, \"\"},\n\t\t{\"TIOCM_SR\", Const, 0, \"\"},\n\t\t{\"TIOCM_ST\", Const, 0, \"\"},\n\t\t{\"TIOCNOTTY\", Const, 0, \"\"},\n\t\t{\"TIOCNXCL\", Const, 0, \"\"},\n\t\t{\"TIOCOUTQ\", Const, 0, \"\"},\n\t\t{\"TIOCPKT\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_DATA\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_DOSTOP\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_FLUSHREAD\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_FLUSHWRITE\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_IOCTL\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_NOSTOP\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_START\", Const, 0, \"\"},\n\t\t{\"TIOCPKT_STOP\", Const, 0, \"\"},\n\t\t{\"TIOCPTMASTER\", Const, 0, \"\"},\n\t\t{\"TIOCPTMGET\", Const, 1, \"\"},\n\t\t{\"TIOCPTSNAME\", Const, 1, \"\"},\n\t\t{\"TIOCPTYGNAME\", Const, 0, \"\"},\n\t\t{\"TIOCPTYGRANT\", Const, 0, \"\"},\n\t\t{\"TIOCPTYUNLK\", Const, 0, \"\"},\n\t\t{\"TIOCRCVFRAME\", Const, 1, \"\"},\n\t\t{\"TIOCREMOTE\", Const, 0, \"\"},\n\t\t{\"TIOCSBRK\", Const, 0, \"\"},\n\t\t{\"TIOCSCONS\", Const, 0, \"\"},\n\t\t{\"TIOCSCTTY\", Const, 0, \"\"},\n\t\t{\"TIOCSDRAINWAIT\", Const, 0, \"\"},\n\t\t{\"TIOCSDTR\", Const, 0, \"\"},\n\t\t{\"TIOCSERCONFIG\", Const, 0, \"\"},\n\t\t{\"TIOCSERGETLSR\", Const, 0, \"\"},\n\t\t{\"TIOCSERGETMULTI\", Const, 0, \"\"},\n\t\t{\"TIOCSERGSTRUCT\", Const, 0, \"\"},\n\t\t{\"TIOCSERGWILD\", Const, 0, \"\"},\n\t\t{\"TIOCSERSETMULTI\", Const, 0, \"\"},\n\t\t{\"TIOCSERSWILD\", Const, 0, \"\"},\n\t\t{\"TIOCSER_TEMT\", Const, 0, \"\"},\n\t\t{\"TIOCSETA\", Const, 0, \"\"},\n\t\t{\"TIOCSETAF\", Const, 0, \"\"},\n\t\t{\"TIOCSETAW\", Const, 0, \"\"},\n\t\t{\"TIOCSETD\", Const, 0, \"\"},\n\t\t{\"TIOCSFLAGS\", Const, 1, \"\"},\n\t\t{\"TIOCSIG\", Const, 0, \"\"},\n\t\t{\"TIOCSLCKTRMIOS\", Const, 0, \"\"},\n\t\t{\"TIOCSLINED\", Const, 1, \"\"},\n\t\t{\"TIOCSPGRP\", Const, 0, \"\"},\n\t\t{\"TIOCSPTLCK\", Const, 0, \"\"},\n\t\t{\"TIOCSQSIZE\", Const, 1, \"\"},\n\t\t{\"TIOCSRS485\", Const, 0, \"\"},\n\t\t{\"TIOCSSERIAL\", Const, 0, \"\"},\n\t\t{\"TIOCSSIZE\", Const, 1, \"\"},\n\t\t{\"TIOCSSOFTCAR\", Const, 0, \"\"},\n\t\t{\"TIOCSTART\", Const, 0, \"\"},\n\t\t{\"TIOCSTAT\", Const, 0, \"\"},\n\t\t{\"TIOCSTI\", Const, 0, \"\"},\n\t\t{\"TIOCSTOP\", Const, 0, \"\"},\n\t\t{\"TIOCSTSTAMP\", Const, 1, \"\"},\n\t\t{\"TIOCSWINSZ\", Const, 0, \"\"},\n\t\t{\"TIOCTIMESTAMP\", Const, 0, \"\"},\n\t\t{\"TIOCUCNTL\", Const, 0, \"\"},\n\t\t{\"TIOCVHANGUP\", Const, 0, \"\"},\n\t\t{\"TIOCXMTFRAME\", Const, 1, \"\"},\n\t\t{\"TOKEN_ADJUST_DEFAULT\", Const, 0, \"\"},\n\t\t{\"TOKEN_ADJUST_GROUPS\", Const, 0, \"\"},\n\t\t{\"TOKEN_ADJUST_PRIVILEGES\", Const, 0, \"\"},\n\t\t{\"TOKEN_ADJUST_SESSIONID\", Const, 11, \"\"},\n\t\t{\"TOKEN_ALL_ACCESS\", Const, 0, \"\"},\n\t\t{\"TOKEN_ASSIGN_PRIMARY\", Const, 0, \"\"},\n\t\t{\"TOKEN_DUPLICATE\", Const, 0, \"\"},\n\t\t{\"TOKEN_EXECUTE\", Const, 0, \"\"},\n\t\t{\"TOKEN_IMPERSONATE\", Const, 0, \"\"},\n\t\t{\"TOKEN_QUERY\", Const, 0, \"\"},\n\t\t{\"TOKEN_QUERY_SOURCE\", Const, 0, \"\"},\n\t\t{\"TOKEN_READ\", Const, 0, \"\"},\n\t\t{\"TOKEN_WRITE\", Const, 0, \"\"},\n\t\t{\"TOSTOP\", Const, 0, \"\"},\n\t\t{\"TRUNCATE_EXISTING\", Const, 0, \"\"},\n\t\t{\"TUNATTACHFILTER\", Const, 0, \"\"},\n\t\t{\"TUNDETACHFILTER\", Const, 0, \"\"},\n\t\t{\"TUNGETFEATURES\", Const, 0, \"\"},\n\t\t{\"TUNGETIFF\", Const, 0, \"\"},\n\t\t{\"TUNGETSNDBUF\", Const, 0, \"\"},\n\t\t{\"TUNGETVNETHDRSZ\", Const, 0, \"\"},\n\t\t{\"TUNSETDEBUG\", Const, 0, \"\"},\n\t\t{\"TUNSETGROUP\", Const, 0, \"\"},\n\t\t{\"TUNSETIFF\", Const, 0, \"\"},\n\t\t{\"TUNSETLINK\", Const, 0, \"\"},\n\t\t{\"TUNSETNOCSUM\", Const, 0, \"\"},\n\t\t{\"TUNSETOFFLOAD\", Const, 0, \"\"},\n\t\t{\"TUNSETOWNER\", Const, 0, \"\"},\n\t\t{\"TUNSETPERSIST\", Const, 0, \"\"},\n\t\t{\"TUNSETSNDBUF\", Const, 0, \"\"},\n\t\t{\"TUNSETTXFILTER\", Const, 0, \"\"},\n\t\t{\"TUNSETVNETHDRSZ\", Const, 0, \"\"},\n\t\t{\"Tee\", Func, 0, \"func(rfd int, wfd int, len int, flags int) (n int64, err error)\"},\n\t\t{\"TerminateProcess\", Func, 0, \"\"},\n\t\t{\"Termios\", Type, 0, \"\"},\n\t\t{\"Termios.Cc\", Field, 0, \"\"},\n\t\t{\"Termios.Cflag\", Field, 0, \"\"},\n\t\t{\"Termios.Iflag\", Field, 0, \"\"},\n\t\t{\"Termios.Ispeed\", Field, 0, \"\"},\n\t\t{\"Termios.Lflag\", Field, 0, \"\"},\n\t\t{\"Termios.Line\", Field, 0, \"\"},\n\t\t{\"Termios.Oflag\", Field, 0, \"\"},\n\t\t{\"Termios.Ospeed\", Field, 0, \"\"},\n\t\t{\"Termios.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Tgkill\", Func, 0, \"func(tgid int, tid int, sig Signal) (err error)\"},\n\t\t{\"Time\", Func, 0, \"func(t *Time_t) (tt Time_t, err error)\"},\n\t\t{\"Time_t\", Type, 0, \"\"},\n\t\t{\"Times\", Func, 0, \"func(tms *Tms) (ticks uintptr, err error)\"},\n\t\t{\"Timespec\", Type, 0, \"\"},\n\t\t{\"Timespec.Nsec\", Field, 0, \"\"},\n\t\t{\"Timespec.Pad_cgo_0\", Field, 2, \"\"},\n\t\t{\"Timespec.Sec\", Field, 0, \"\"},\n\t\t{\"TimespecToNsec\", Func, 0, \"func(ts Timespec) int64\"},\n\t\t{\"Timeval\", Type, 0, \"\"},\n\t\t{\"Timeval.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Timeval.Sec\", Field, 0, \"\"},\n\t\t{\"Timeval.Usec\", Field, 0, \"\"},\n\t\t{\"Timeval32\", Type, 0, \"\"},\n\t\t{\"Timeval32.Sec\", Field, 0, \"\"},\n\t\t{\"Timeval32.Usec\", Field, 0, \"\"},\n\t\t{\"TimevalToNsec\", Func, 0, \"func(tv Timeval) int64\"},\n\t\t{\"Timex\", Type, 0, \"\"},\n\t\t{\"Timex.Calcnt\", Field, 0, \"\"},\n\t\t{\"Timex.Constant\", Field, 0, \"\"},\n\t\t{\"Timex.Errcnt\", Field, 0, \"\"},\n\t\t{\"Timex.Esterror\", Field, 0, \"\"},\n\t\t{\"Timex.Freq\", Field, 0, \"\"},\n\t\t{\"Timex.Jitcnt\", Field, 0, \"\"},\n\t\t{\"Timex.Jitter\", Field, 0, \"\"},\n\t\t{\"Timex.Maxerror\", Field, 0, \"\"},\n\t\t{\"Timex.Modes\", Field, 0, \"\"},\n\t\t{\"Timex.Offset\", Field, 0, \"\"},\n\t\t{\"Timex.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Timex.Pad_cgo_1\", Field, 0, \"\"},\n\t\t{\"Timex.Pad_cgo_2\", Field, 0, \"\"},\n\t\t{\"Timex.Pad_cgo_3\", Field, 0, \"\"},\n\t\t{\"Timex.Ppsfreq\", Field, 0, \"\"},\n\t\t{\"Timex.Precision\", Field, 0, \"\"},\n\t\t{\"Timex.Shift\", Field, 0, \"\"},\n\t\t{\"Timex.Stabil\", Field, 0, \"\"},\n\t\t{\"Timex.Status\", Field, 0, \"\"},\n\t\t{\"Timex.Stbcnt\", Field, 0, \"\"},\n\t\t{\"Timex.Tai\", Field, 0, \"\"},\n\t\t{\"Timex.Tick\", Field, 0, \"\"},\n\t\t{\"Timex.Time\", Field, 0, \"\"},\n\t\t{\"Timex.Tolerance\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation\", Type, 0, \"\"},\n\t\t{\"Timezoneinformation.Bias\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.DaylightBias\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.DaylightDate\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.DaylightName\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.StandardBias\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.StandardDate\", Field, 0, \"\"},\n\t\t{\"Timezoneinformation.StandardName\", Field, 0, \"\"},\n\t\t{\"Tms\", Type, 0, \"\"},\n\t\t{\"Tms.Cstime\", Field, 0, \"\"},\n\t\t{\"Tms.Cutime\", Field, 0, \"\"},\n\t\t{\"Tms.Stime\", Field, 0, \"\"},\n\t\t{\"Tms.Utime\", Field, 0, \"\"},\n\t\t{\"Token\", Type, 0, \"\"},\n\t\t{\"TokenAccessInformation\", Const, 0, \"\"},\n\t\t{\"TokenAuditPolicy\", Const, 0, \"\"},\n\t\t{\"TokenDefaultDacl\", Const, 0, \"\"},\n\t\t{\"TokenElevation\", Const, 0, \"\"},\n\t\t{\"TokenElevationType\", Const, 0, \"\"},\n\t\t{\"TokenGroups\", Const, 0, \"\"},\n\t\t{\"TokenGroupsAndPrivileges\", Const, 0, \"\"},\n\t\t{\"TokenHasRestrictions\", Const, 0, \"\"},\n\t\t{\"TokenImpersonationLevel\", Const, 0, \"\"},\n\t\t{\"TokenIntegrityLevel\", Const, 0, \"\"},\n\t\t{\"TokenLinkedToken\", Const, 0, \"\"},\n\t\t{\"TokenLogonSid\", Const, 0, \"\"},\n\t\t{\"TokenMandatoryPolicy\", Const, 0, \"\"},\n\t\t{\"TokenOrigin\", Const, 0, \"\"},\n\t\t{\"TokenOwner\", Const, 0, \"\"},\n\t\t{\"TokenPrimaryGroup\", Const, 0, \"\"},\n\t\t{\"TokenPrivileges\", Const, 0, \"\"},\n\t\t{\"TokenRestrictedSids\", Const, 0, \"\"},\n\t\t{\"TokenSandBoxInert\", Const, 0, \"\"},\n\t\t{\"TokenSessionId\", Const, 0, \"\"},\n\t\t{\"TokenSessionReference\", Const, 0, \"\"},\n\t\t{\"TokenSource\", Const, 0, \"\"},\n\t\t{\"TokenStatistics\", Const, 0, \"\"},\n\t\t{\"TokenType\", Const, 0, \"\"},\n\t\t{\"TokenUIAccess\", Const, 0, \"\"},\n\t\t{\"TokenUser\", Const, 0, \"\"},\n\t\t{\"TokenVirtualizationAllowed\", Const, 0, \"\"},\n\t\t{\"TokenVirtualizationEnabled\", Const, 0, \"\"},\n\t\t{\"Tokenprimarygroup\", Type, 0, \"\"},\n\t\t{\"Tokenprimarygroup.PrimaryGroup\", Field, 0, \"\"},\n\t\t{\"Tokenuser\", Type, 0, \"\"},\n\t\t{\"Tokenuser.User\", Field, 0, \"\"},\n\t\t{\"TranslateAccountName\", Func, 0, \"\"},\n\t\t{\"TranslateName\", Func, 0, \"\"},\n\t\t{\"TransmitFile\", Func, 0, \"\"},\n\t\t{\"TransmitFileBuffers\", Type, 0, \"\"},\n\t\t{\"TransmitFileBuffers.Head\", Field, 0, \"\"},\n\t\t{\"TransmitFileBuffers.HeadLength\", Field, 0, \"\"},\n\t\t{\"TransmitFileBuffers.Tail\", Field, 0, \"\"},\n\t\t{\"TransmitFileBuffers.TailLength\", Field, 0, \"\"},\n\t\t{\"Truncate\", Func, 0, \"func(path string, length int64) (err error)\"},\n\t\t{\"UNIX_PATH_MAX\", Const, 12, \"\"},\n\t\t{\"USAGE_MATCH_TYPE_AND\", Const, 0, \"\"},\n\t\t{\"USAGE_MATCH_TYPE_OR\", Const, 0, \"\"},\n\t\t{\"UTF16FromString\", Func, 1, \"\"},\n\t\t{\"UTF16PtrFromString\", Func, 1, \"\"},\n\t\t{\"UTF16ToString\", Func, 0, \"\"},\n\t\t{\"Ucred\", Type, 0, \"\"},\n\t\t{\"Ucred.Gid\", Field, 0, \"\"},\n\t\t{\"Ucred.Pid\", Field, 0, \"\"},\n\t\t{\"Ucred.Uid\", Field, 0, \"\"},\n\t\t{\"Umask\", Func, 0, \"func(mask int) (oldmask int)\"},\n\t\t{\"Uname\", Func, 0, \"func(buf *Utsname) (err error)\"},\n\t\t{\"Undelete\", Func, 0, \"\"},\n\t\t{\"UnixCredentials\", Func, 0, \"func(ucred *Ucred) []byte\"},\n\t\t{\"UnixRights\", Func, 0, \"func(fds ...int) []byte\"},\n\t\t{\"Unlink\", Func, 0, \"func(path string) error\"},\n\t\t{\"Unlinkat\", Func, 0, \"func(dirfd int, path string) error\"},\n\t\t{\"UnmapViewOfFile\", Func, 0, \"\"},\n\t\t{\"Unmount\", Func, 0, \"func(target string, flags int) (err error)\"},\n\t\t{\"Unsetenv\", Func, 4, \"func(key string) error\"},\n\t\t{\"Unshare\", Func, 0, \"func(flags int) (err error)\"},\n\t\t{\"UserInfo10\", Type, 0, \"\"},\n\t\t{\"UserInfo10.Comment\", Field, 0, \"\"},\n\t\t{\"UserInfo10.FullName\", Field, 0, \"\"},\n\t\t{\"UserInfo10.Name\", Field, 0, \"\"},\n\t\t{\"UserInfo10.UsrComment\", Field, 0, \"\"},\n\t\t{\"Ustat\", Func, 0, \"func(dev int, ubuf *Ustat_t) (err error)\"},\n\t\t{\"Ustat_t\", Type, 0, \"\"},\n\t\t{\"Ustat_t.Fname\", Field, 0, \"\"},\n\t\t{\"Ustat_t.Fpack\", Field, 0, \"\"},\n\t\t{\"Ustat_t.Pad_cgo_0\", Field, 0, \"\"},\n\t\t{\"Ustat_t.Pad_cgo_1\", Field, 0, \"\"},\n\t\t{\"Ustat_t.Tfree\", Field, 0, \"\"},\n\t\t{\"Ustat_t.Tinode\", Field, 0, \"\"},\n\t\t{\"Utimbuf\", Type, 0, \"\"},\n\t\t{\"Utimbuf.Actime\", Field, 0, \"\"},\n\t\t{\"Utimbuf.Modtime\", Field, 0, \"\"},\n\t\t{\"Utime\", Func, 0, \"func(path string, buf *Utimbuf) (err error)\"},\n\t\t{\"Utimes\", Func, 0, \"func(path string, tv []Timeval) (err error)\"},\n\t\t{\"UtimesNano\", Func, 1, \"func(path string, ts []Timespec) (err error)\"},\n\t\t{\"Utsname\", Type, 0, \"\"},\n\t\t{\"Utsname.Domainname\", Field, 0, \"\"},\n\t\t{\"Utsname.Machine\", Field, 0, \"\"},\n\t\t{\"Utsname.Nodename\", Field, 0, \"\"},\n\t\t{\"Utsname.Release\", Field, 0, \"\"},\n\t\t{\"Utsname.Sysname\", Field, 0, \"\"},\n\t\t{\"Utsname.Version\", Field, 0, \"\"},\n\t\t{\"VDISCARD\", Const, 0, \"\"},\n\t\t{\"VDSUSP\", Const, 1, \"\"},\n\t\t{\"VEOF\", Const, 0, \"\"},\n\t\t{\"VEOL\", Const, 0, \"\"},\n\t\t{\"VEOL2\", Const, 0, \"\"},\n\t\t{\"VERASE\", Const, 0, \"\"},\n\t\t{\"VERASE2\", Const, 1, \"\"},\n\t\t{\"VINTR\", Const, 0, \"\"},\n\t\t{\"VKILL\", Const, 0, \"\"},\n\t\t{\"VLNEXT\", Const, 0, \"\"},\n\t\t{\"VMIN\", Const, 0, \"\"},\n\t\t{\"VQUIT\", Const, 0, \"\"},\n\t\t{\"VREPRINT\", Const, 0, \"\"},\n\t\t{\"VSTART\", Const, 0, \"\"},\n\t\t{\"VSTATUS\", Const, 1, \"\"},\n\t\t{\"VSTOP\", Const, 0, \"\"},\n\t\t{\"VSUSP\", Const, 0, \"\"},\n\t\t{\"VSWTC\", Const, 0, \"\"},\n\t\t{\"VT0\", Const, 1, \"\"},\n\t\t{\"VT1\", Const, 1, \"\"},\n\t\t{\"VTDLY\", Const, 1, \"\"},\n\t\t{\"VTIME\", Const, 0, \"\"},\n\t\t{\"VWERASE\", Const, 0, \"\"},\n\t\t{\"VirtualLock\", Func, 0, \"\"},\n\t\t{\"VirtualUnlock\", Func, 0, \"\"},\n\t\t{\"WAIT_ABANDONED\", Const, 0, \"\"},\n\t\t{\"WAIT_FAILED\", Const, 0, \"\"},\n\t\t{\"WAIT_OBJECT_0\", Const, 0, \"\"},\n\t\t{\"WAIT_TIMEOUT\", Const, 0, \"\"},\n\t\t{\"WALL\", Const, 0, \"\"},\n\t\t{\"WALLSIG\", Const, 1, \"\"},\n\t\t{\"WALTSIG\", Const, 1, \"\"},\n\t\t{\"WCLONE\", Const, 0, \"\"},\n\t\t{\"WCONTINUED\", Const, 0, \"\"},\n\t\t{\"WCOREFLAG\", Const, 0, \"\"},\n\t\t{\"WEXITED\", Const, 0, \"\"},\n\t\t{\"WLINUXCLONE\", Const, 0, \"\"},\n\t\t{\"WNOHANG\", Const, 0, \"\"},\n\t\t{\"WNOTHREAD\", Const, 0, \"\"},\n\t\t{\"WNOWAIT\", Const, 0, \"\"},\n\t\t{\"WNOZOMBIE\", Const, 1, \"\"},\n\t\t{\"WOPTSCHECKED\", Const, 1, \"\"},\n\t\t{\"WORDSIZE\", Const, 0, \"\"},\n\t\t{\"WSABuf\", Type, 0, \"\"},\n\t\t{\"WSABuf.Buf\", Field, 0, \"\"},\n\t\t{\"WSABuf.Len\", Field, 0, \"\"},\n\t\t{\"WSACleanup\", Func, 0, \"\"},\n\t\t{\"WSADESCRIPTION_LEN\", Const, 0, \"\"},\n\t\t{\"WSAData\", Type, 0, \"\"},\n\t\t{\"WSAData.Description\", Field, 0, \"\"},\n\t\t{\"WSAData.HighVersion\", Field, 0, \"\"},\n\t\t{\"WSAData.MaxSockets\", Field, 0, \"\"},\n\t\t{\"WSAData.MaxUdpDg\", Field, 0, \"\"},\n\t\t{\"WSAData.SystemStatus\", Field, 0, \"\"},\n\t\t{\"WSAData.VendorInfo\", Field, 0, \"\"},\n\t\t{\"WSAData.Version\", Field, 0, \"\"},\n\t\t{\"WSAEACCES\", Const, 2, \"\"},\n\t\t{\"WSAECONNABORTED\", Const, 9, \"\"},\n\t\t{\"WSAECONNRESET\", Const, 3, \"\"},\n\t\t{\"WSAENOPROTOOPT\", Const, 23, \"\"},\n\t\t{\"WSAEnumProtocols\", Func, 2, \"\"},\n\t\t{\"WSAID_CONNECTEX\", Var, 1, \"\"},\n\t\t{\"WSAIoctl\", Func, 0, \"\"},\n\t\t{\"WSAPROTOCOL_LEN\", Const, 2, \"\"},\n\t\t{\"WSAProtocolChain\", Type, 2, \"\"},\n\t\t{\"WSAProtocolChain.ChainEntries\", Field, 2, \"\"},\n\t\t{\"WSAProtocolChain.ChainLen\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo\", Type, 2, \"\"},\n\t\t{\"WSAProtocolInfo.AddressFamily\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.CatalogEntryId\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.MaxSockAddr\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.MessageSize\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.MinSockAddr\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.NetworkByteOrder\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.Protocol\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProtocolChain\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProtocolMaxOffset\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProtocolName\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProviderFlags\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProviderId\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ProviderReserved\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.SecurityScheme\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ServiceFlags1\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ServiceFlags2\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ServiceFlags3\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.ServiceFlags4\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.SocketType\", Field, 2, \"\"},\n\t\t{\"WSAProtocolInfo.Version\", Field, 2, \"\"},\n\t\t{\"WSARecv\", Func, 0, \"\"},\n\t\t{\"WSARecvFrom\", Func, 0, \"\"},\n\t\t{\"WSASYS_STATUS_LEN\", Const, 0, \"\"},\n\t\t{\"WSASend\", Func, 0, \"\"},\n\t\t{\"WSASendTo\", Func, 0, \"\"},\n\t\t{\"WSASendto\", Func, 0, \"\"},\n\t\t{\"WSAStartup\", Func, 0, \"\"},\n\t\t{\"WSTOPPED\", Const, 0, \"\"},\n\t\t{\"WTRAPPED\", Const, 1, \"\"},\n\t\t{\"WUNTRACED\", Const, 0, \"\"},\n\t\t{\"Wait4\", Func, 0, \"func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)\"},\n\t\t{\"WaitForSingleObject\", Func, 0, \"\"},\n\t\t{\"WaitStatus\", Type, 0, \"\"},\n\t\t{\"WaitStatus.ExitCode\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData\", Type, 0, \"\"},\n\t\t{\"Win32FileAttributeData.CreationTime\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData.FileAttributes\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData.FileSizeHigh\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData.FileSizeLow\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData.LastAccessTime\", Field, 0, \"\"},\n\t\t{\"Win32FileAttributeData.LastWriteTime\", Field, 0, \"\"},\n\t\t{\"Win32finddata\", Type, 0, \"\"},\n\t\t{\"Win32finddata.AlternateFileName\", Field, 0, \"\"},\n\t\t{\"Win32finddata.CreationTime\", Field, 0, \"\"},\n\t\t{\"Win32finddata.FileAttributes\", Field, 0, \"\"},\n\t\t{\"Win32finddata.FileName\", Field, 0, \"\"},\n\t\t{\"Win32finddata.FileSizeHigh\", Field, 0, \"\"},\n\t\t{\"Win32finddata.FileSizeLow\", Field, 0, \"\"},\n\t\t{\"Win32finddata.LastAccessTime\", Field, 0, \"\"},\n\t\t{\"Win32finddata.LastWriteTime\", Field, 0, \"\"},\n\t\t{\"Win32finddata.Reserved0\", Field, 0, \"\"},\n\t\t{\"Win32finddata.Reserved1\", Field, 0, \"\"},\n\t\t{\"Write\", Func, 0, \"func(fd int, p []byte) (n int, err error)\"},\n\t\t{\"WriteConsole\", Func, 1, \"\"},\n\t\t{\"WriteFile\", Func, 0, \"\"},\n\t\t{\"X509_ASN_ENCODING\", Const, 0, \"\"},\n\t\t{\"XCASE\", Const, 0, \"\"},\n\t\t{\"XP1_CONNECTIONLESS\", Const, 2, \"\"},\n\t\t{\"XP1_CONNECT_DATA\", Const, 2, \"\"},\n\t\t{\"XP1_DISCONNECT_DATA\", Const, 2, \"\"},\n\t\t{\"XP1_EXPEDITED_DATA\", Const, 2, \"\"},\n\t\t{\"XP1_GRACEFUL_CLOSE\", Const, 2, \"\"},\n\t\t{\"XP1_GUARANTEED_DELIVERY\", Const, 2, \"\"},\n\t\t{\"XP1_GUARANTEED_ORDER\", Const, 2, \"\"},\n\t\t{\"XP1_IFS_HANDLES\", Const, 2, \"\"},\n\t\t{\"XP1_MESSAGE_ORIENTED\", Const, 2, \"\"},\n\t\t{\"XP1_MULTIPOINT_CONTROL_PLANE\", Const, 2, \"\"},\n\t\t{\"XP1_MULTIPOINT_DATA_PLANE\", Const, 2, \"\"},\n\t\t{\"XP1_PARTIAL_MESSAGE\", Const, 2, \"\"},\n\t\t{\"XP1_PSEUDO_STREAM\", Const, 2, \"\"},\n\t\t{\"XP1_QOS_SUPPORTED\", Const, 2, \"\"},\n\t\t{\"XP1_SAN_SUPPORT_SDP\", Const, 2, \"\"},\n\t\t{\"XP1_SUPPORT_BROADCAST\", Const, 2, \"\"},\n\t\t{\"XP1_SUPPORT_MULTIPOINT\", Const, 2, \"\"},\n\t\t{\"XP1_UNI_RECV\", Const, 2, \"\"},\n\t\t{\"XP1_UNI_SEND\", Const, 2, \"\"},\n\t},\n\t\"syscall/js\": {\n\t\t{\"CopyBytesToGo\", Func, 0, \"\"},\n\t\t{\"CopyBytesToJS\", Func, 0, \"\"},\n\t\t{\"Error\", Type, 0, \"\"},\n\t\t{\"Func\", Type, 0, \"\"},\n\t\t{\"FuncOf\", Func, 0, \"\"},\n\t\t{\"Global\", Func, 0, \"\"},\n\t\t{\"Null\", Func, 0, \"\"},\n\t\t{\"Type\", Type, 0, \"\"},\n\t\t{\"TypeBoolean\", Const, 0, \"\"},\n\t\t{\"TypeFunction\", Const, 0, \"\"},\n\t\t{\"TypeNull\", Const, 0, \"\"},\n\t\t{\"TypeNumber\", Const, 0, \"\"},\n\t\t{\"TypeObject\", Const, 0, \"\"},\n\t\t{\"TypeString\", Const, 0, \"\"},\n\t\t{\"TypeSymbol\", Const, 0, \"\"},\n\t\t{\"TypeUndefined\", Const, 0, \"\"},\n\t\t{\"Undefined\", Func, 0, \"\"},\n\t\t{\"Value\", Type, 0, \"\"},\n\t\t{\"ValueError\", Type, 0, \"\"},\n\t\t{\"ValueOf\", Func, 0, \"\"},\n\t},\n\t\"testing\": {\n\t\t{\"(*B).ArtifactDir\", Method, 26, \"\"},\n\t\t{\"(*B).Attr\", Method, 25, \"\"},\n\t\t{\"(*B).Chdir\", Method, 24, \"\"},\n\t\t{\"(*B).Cleanup\", Method, 14, \"\"},\n\t\t{\"(*B).Context\", Method, 24, \"\"},\n\t\t{\"(*B).Elapsed\", Method, 20, \"\"},\n\t\t{\"(*B).Error\", Method, 0, \"\"},\n\t\t{\"(*B).Errorf\", Method, 0, \"\"},\n\t\t{\"(*B).Fail\", Method, 0, \"\"},\n\t\t{\"(*B).FailNow\", Method, 0, \"\"},\n\t\t{\"(*B).Failed\", Method, 0, \"\"},\n\t\t{\"(*B).Fatal\", Method, 0, \"\"},\n\t\t{\"(*B).Fatalf\", Method, 0, \"\"},\n\t\t{\"(*B).Helper\", Method, 9, \"\"},\n\t\t{\"(*B).Log\", Method, 0, \"\"},\n\t\t{\"(*B).Logf\", Method, 0, \"\"},\n\t\t{\"(*B).Loop\", Method, 24, \"\"},\n\t\t{\"(*B).Name\", Method, 8, \"\"},\n\t\t{\"(*B).Output\", Method, 25, \"\"},\n\t\t{\"(*B).ReportAllocs\", Method, 1, \"\"},\n\t\t{\"(*B).ReportMetric\", Method, 13, \"\"},\n\t\t{\"(*B).ResetTimer\", Method, 0, \"\"},\n\t\t{\"(*B).Run\", Method, 7, \"\"},\n\t\t{\"(*B).RunParallel\", Method, 3, \"\"},\n\t\t{\"(*B).SetBytes\", Method, 0, \"\"},\n\t\t{\"(*B).SetParallelism\", Method, 3, \"\"},\n\t\t{\"(*B).Setenv\", Method, 17, \"\"},\n\t\t{\"(*B).Skip\", Method, 1, \"\"},\n\t\t{\"(*B).SkipNow\", Method, 1, \"\"},\n\t\t{\"(*B).Skipf\", Method, 1, \"\"},\n\t\t{\"(*B).Skipped\", Method, 1, \"\"},\n\t\t{\"(*B).StartTimer\", Method, 0, \"\"},\n\t\t{\"(*B).StopTimer\", Method, 0, \"\"},\n\t\t{\"(*B).TempDir\", Method, 15, \"\"},\n\t\t{\"(*F).Add\", Method, 18, \"\"},\n\t\t{\"(*F).ArtifactDir\", Method, 26, \"\"},\n\t\t{\"(*F).Attr\", Method, 25, \"\"},\n\t\t{\"(*F).Chdir\", Method, 24, \"\"},\n\t\t{\"(*F).Cleanup\", Method, 18, \"\"},\n\t\t{\"(*F).Context\", Method, 24, \"\"},\n\t\t{\"(*F).Error\", Method, 18, \"\"},\n\t\t{\"(*F).Errorf\", Method, 18, \"\"},\n\t\t{\"(*F).Fail\", Method, 18, \"\"},\n\t\t{\"(*F).FailNow\", Method, 18, \"\"},\n\t\t{\"(*F).Failed\", Method, 18, \"\"},\n\t\t{\"(*F).Fatal\", Method, 18, \"\"},\n\t\t{\"(*F).Fatalf\", Method, 18, \"\"},\n\t\t{\"(*F).Fuzz\", Method, 18, \"\"},\n\t\t{\"(*F).Helper\", Method, 18, \"\"},\n\t\t{\"(*F).Log\", Method, 18, \"\"},\n\t\t{\"(*F).Logf\", Method, 18, \"\"},\n\t\t{\"(*F).Name\", Method, 18, \"\"},\n\t\t{\"(*F).Output\", Method, 25, \"\"},\n\t\t{\"(*F).Setenv\", Method, 18, \"\"},\n\t\t{\"(*F).Skip\", Method, 18, \"\"},\n\t\t{\"(*F).SkipNow\", Method, 18, \"\"},\n\t\t{\"(*F).Skipf\", Method, 18, \"\"},\n\t\t{\"(*F).Skipped\", Method, 18, \"\"},\n\t\t{\"(*F).TempDir\", Method, 18, \"\"},\n\t\t{\"(*M).Run\", Method, 4, \"\"},\n\t\t{\"(*PB).Next\", Method, 3, \"\"},\n\t\t{\"(*T).ArtifactDir\", Method, 26, \"\"},\n\t\t{\"(*T).Attr\", Method, 25, \"\"},\n\t\t{\"(*T).Chdir\", Method, 24, \"\"},\n\t\t{\"(*T).Cleanup\", Method, 14, \"\"},\n\t\t{\"(*T).Context\", Method, 24, \"\"},\n\t\t{\"(*T).Deadline\", Method, 15, \"\"},\n\t\t{\"(*T).Error\", Method, 0, \"\"},\n\t\t{\"(*T).Errorf\", Method, 0, \"\"},\n\t\t{\"(*T).Fail\", Method, 0, \"\"},\n\t\t{\"(*T).FailNow\", Method, 0, \"\"},\n\t\t{\"(*T).Failed\", Method, 0, \"\"},\n\t\t{\"(*T).Fatal\", Method, 0, \"\"},\n\t\t{\"(*T).Fatalf\", Method, 0, \"\"},\n\t\t{\"(*T).Helper\", Method, 9, \"\"},\n\t\t{\"(*T).Log\", Method, 0, \"\"},\n\t\t{\"(*T).Logf\", Method, 0, \"\"},\n\t\t{\"(*T).Name\", Method, 8, \"\"},\n\t\t{\"(*T).Output\", Method, 25, \"\"},\n\t\t{\"(*T).Parallel\", Method, 0, \"\"},\n\t\t{\"(*T).Run\", Method, 7, \"\"},\n\t\t{\"(*T).Setenv\", Method, 17, \"\"},\n\t\t{\"(*T).Skip\", Method, 1, \"\"},\n\t\t{\"(*T).SkipNow\", Method, 1, \"\"},\n\t\t{\"(*T).Skipf\", Method, 1, \"\"},\n\t\t{\"(*T).Skipped\", Method, 1, \"\"},\n\t\t{\"(*T).TempDir\", Method, 15, \"\"},\n\t\t{\"(BenchmarkResult).AllocedBytesPerOp\", Method, 1, \"\"},\n\t\t{\"(BenchmarkResult).AllocsPerOp\", Method, 1, \"\"},\n\t\t{\"(BenchmarkResult).MemString\", Method, 1, \"\"},\n\t\t{\"(BenchmarkResult).NsPerOp\", Method, 0, \"\"},\n\t\t{\"(BenchmarkResult).String\", Method, 0, \"\"},\n\t\t{\"(TB).ArtifactDir\", Method, 26, \"\"},\n\t\t{\"(TB).Attr\", Method, 25, \"\"},\n\t\t{\"(TB).Chdir\", Method, 24, \"\"},\n\t\t{\"(TB).Cleanup\", Method, 14, \"\"},\n\t\t{\"(TB).Context\", Method, 24, \"\"},\n\t\t{\"(TB).Error\", Method, 2, \"\"},\n\t\t{\"(TB).Errorf\", Method, 2, \"\"},\n\t\t{\"(TB).Fail\", Method, 2, \"\"},\n\t\t{\"(TB).FailNow\", Method, 2, \"\"},\n\t\t{\"(TB).Failed\", Method, 2, \"\"},\n\t\t{\"(TB).Fatal\", Method, 2, \"\"},\n\t\t{\"(TB).Fatalf\", Method, 2, \"\"},\n\t\t{\"(TB).Helper\", Method, 9, \"\"},\n\t\t{\"(TB).Log\", Method, 2, \"\"},\n\t\t{\"(TB).Logf\", Method, 2, \"\"},\n\t\t{\"(TB).Name\", Method, 8, \"\"},\n\t\t{\"(TB).Output\", Method, 25, \"\"},\n\t\t{\"(TB).Setenv\", Method, 17, \"\"},\n\t\t{\"(TB).Skip\", Method, 2, \"\"},\n\t\t{\"(TB).SkipNow\", Method, 2, \"\"},\n\t\t{\"(TB).Skipf\", Method, 2, \"\"},\n\t\t{\"(TB).Skipped\", Method, 2, \"\"},\n\t\t{\"(TB).TempDir\", Method, 15, \"\"},\n\t\t{\"AllocsPerRun\", Func, 1, \"func(runs int, f func()) (avg float64)\"},\n\t\t{\"B\", Type, 0, \"\"},\n\t\t{\"B.N\", Field, 0, \"\"},\n\t\t{\"Benchmark\", Func, 0, \"func(f func(b *B)) BenchmarkResult\"},\n\t\t{\"BenchmarkResult\", Type, 0, \"\"},\n\t\t{\"BenchmarkResult.Bytes\", Field, 0, \"\"},\n\t\t{\"BenchmarkResult.Extra\", Field, 13, \"\"},\n\t\t{\"BenchmarkResult.MemAllocs\", Field, 1, \"\"},\n\t\t{\"BenchmarkResult.MemBytes\", Field, 1, \"\"},\n\t\t{\"BenchmarkResult.N\", Field, 0, \"\"},\n\t\t{\"BenchmarkResult.T\", Field, 0, \"\"},\n\t\t{\"Cover\", Type, 2, \"\"},\n\t\t{\"Cover.Blocks\", Field, 2, \"\"},\n\t\t{\"Cover.Counters\", Field, 2, \"\"},\n\t\t{\"Cover.CoveredPackages\", Field, 2, \"\"},\n\t\t{\"Cover.Mode\", Field, 2, \"\"},\n\t\t{\"CoverBlock\", Type, 2, \"\"},\n\t\t{\"CoverBlock.Col0\", Field, 2, \"\"},\n\t\t{\"CoverBlock.Col1\", Field, 2, \"\"},\n\t\t{\"CoverBlock.Line0\", Field, 2, \"\"},\n\t\t{\"CoverBlock.Line1\", Field, 2, \"\"},\n\t\t{\"CoverBlock.Stmts\", Field, 2, \"\"},\n\t\t{\"CoverMode\", Func, 8, \"func() string\"},\n\t\t{\"Coverage\", Func, 4, \"func() float64\"},\n\t\t{\"F\", Type, 18, \"\"},\n\t\t{\"Init\", Func, 13, \"func()\"},\n\t\t{\"InternalBenchmark\", Type, 0, \"\"},\n\t\t{\"InternalBenchmark.F\", Field, 0, \"\"},\n\t\t{\"InternalBenchmark.Name\", Field, 0, \"\"},\n\t\t{\"InternalExample\", Type, 0, \"\"},\n\t\t{\"InternalExample.F\", Field, 0, \"\"},\n\t\t{\"InternalExample.Name\", Field, 0, \"\"},\n\t\t{\"InternalExample.Output\", Field, 0, \"\"},\n\t\t{\"InternalExample.Unordered\", Field, 7, \"\"},\n\t\t{\"InternalFuzzTarget\", Type, 18, \"\"},\n\t\t{\"InternalFuzzTarget.Fn\", Field, 18, \"\"},\n\t\t{\"InternalFuzzTarget.Name\", Field, 18, \"\"},\n\t\t{\"InternalTest\", Type, 0, \"\"},\n\t\t{\"InternalTest.F\", Field, 0, \"\"},\n\t\t{\"InternalTest.Name\", Field, 0, \"\"},\n\t\t{\"M\", Type, 4, \"\"},\n\t\t{\"Main\", Func, 0, \"func(matchString func(pat string, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)\"},\n\t\t{\"MainStart\", Func, 4, \"func(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M\"},\n\t\t{\"PB\", Type, 3, \"\"},\n\t\t{\"RegisterCover\", Func, 2, \"func(c Cover)\"},\n\t\t{\"RunBenchmarks\", Func, 0, \"func(matchString func(pat string, str string) (bool, error), benchmarks []InternalBenchmark)\"},\n\t\t{\"RunExamples\", Func, 0, \"func(matchString func(pat string, str string) (bool, error), examples []InternalExample) (ok bool)\"},\n\t\t{\"RunTests\", Func, 0, \"func(matchString func(pat string, str string) (bool, error), tests []InternalTest) (ok bool)\"},\n\t\t{\"Short\", Func, 0, \"func() bool\"},\n\t\t{\"T\", Type, 0, \"\"},\n\t\t{\"Testing\", Func, 21, \"func() bool\"},\n\t\t{\"Verbose\", Func, 1, \"func() bool\"},\n\t},\n\t\"testing/cryptotest\": {\n\t\t{\"SetGlobalRandom\", Func, 26, \"func(t *testing.T, seed uint64)\"},\n\t},\n\t\"testing/fstest\": {\n\t\t{\"(MapFS).Glob\", Method, 16, \"\"},\n\t\t{\"(MapFS).Lstat\", Method, 25, \"\"},\n\t\t{\"(MapFS).Open\", Method, 16, \"\"},\n\t\t{\"(MapFS).ReadDir\", Method, 16, \"\"},\n\t\t{\"(MapFS).ReadFile\", Method, 16, \"\"},\n\t\t{\"(MapFS).ReadLink\", Method, 25, \"\"},\n\t\t{\"(MapFS).Stat\", Method, 16, \"\"},\n\t\t{\"(MapFS).Sub\", Method, 16, \"\"},\n\t\t{\"MapFS\", Type, 16, \"\"},\n\t\t{\"MapFile\", Type, 16, \"\"},\n\t\t{\"MapFile.Data\", Field, 16, \"\"},\n\t\t{\"MapFile.ModTime\", Field, 16, \"\"},\n\t\t{\"MapFile.Mode\", Field, 16, \"\"},\n\t\t{\"MapFile.Sys\", Field, 16, \"\"},\n\t\t{\"TestFS\", Func, 16, \"func(fsys fs.FS, expected ...string) error\"},\n\t},\n\t\"testing/iotest\": {\n\t\t{\"DataErrReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"ErrReader\", Func, 16, \"func(err error) io.Reader\"},\n\t\t{\"ErrTimeout\", Var, 0, \"\"},\n\t\t{\"HalfReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"NewReadLogger\", Func, 0, \"func(prefix string, r io.Reader) io.Reader\"},\n\t\t{\"NewWriteLogger\", Func, 0, \"func(prefix string, w io.Writer) io.Writer\"},\n\t\t{\"OneByteReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"TestReader\", Func, 16, \"func(r io.Reader, content []byte) error\"},\n\t\t{\"TimeoutReader\", Func, 0, \"func(r io.Reader) io.Reader\"},\n\t\t{\"TruncateWriter\", Func, 0, \"func(w io.Writer, n int64) io.Writer\"},\n\t},\n\t\"testing/quick\": {\n\t\t{\"(*CheckEqualError).Error\", Method, 0, \"\"},\n\t\t{\"(*CheckError).Error\", Method, 0, \"\"},\n\t\t{\"(Generator).Generate\", Method, 0, \"\"},\n\t\t{\"(SetupError).Error\", Method, 0, \"\"},\n\t\t{\"Check\", Func, 0, \"func(f any, config *Config) error\"},\n\t\t{\"CheckEqual\", Func, 0, \"func(f any, g any, config *Config) error\"},\n\t\t{\"CheckEqualError\", Type, 0, \"\"},\n\t\t{\"CheckEqualError.CheckError\", Field, 0, \"\"},\n\t\t{\"CheckEqualError.Out1\", Field, 0, \"\"},\n\t\t{\"CheckEqualError.Out2\", Field, 0, \"\"},\n\t\t{\"CheckError\", Type, 0, \"\"},\n\t\t{\"CheckError.Count\", Field, 0, \"\"},\n\t\t{\"CheckError.In\", Field, 0, \"\"},\n\t\t{\"Config\", Type, 0, \"\"},\n\t\t{\"Config.MaxCount\", Field, 0, \"\"},\n\t\t{\"Config.MaxCountScale\", Field, 0, \"\"},\n\t\t{\"Config.Rand\", Field, 0, \"\"},\n\t\t{\"Config.Values\", Field, 0, \"\"},\n\t\t{\"Generator\", Type, 0, \"\"},\n\t\t{\"SetupError\", Type, 0, \"\"},\n\t\t{\"Value\", Func, 0, \"func(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool)\"},\n\t},\n\t\"testing/slogtest\": {\n\t\t{\"Run\", Func, 22, \"func(t *testing.T, newHandler func(*testing.T) slog.Handler, result func(*testing.T) map[string]any)\"},\n\t\t{\"TestHandler\", Func, 21, \"func(h slog.Handler, results func() []map[string]any) error\"},\n\t},\n\t\"testing/synctest\": {\n\t\t{\"Test\", Func, 25, \"func(t *testing.T, f func(*testing.T))\"},\n\t\t{\"Wait\", Func, 25, \"func()\"},\n\t},\n\t\"text/scanner\": {\n\t\t{\"(*Position).IsValid\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Init\", Method, 0, \"\"},\n\t\t{\"(*Scanner).IsValid\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Next\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Peek\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Pos\", Method, 0, \"\"},\n\t\t{\"(*Scanner).Scan\", Method, 0, \"\"},\n\t\t{\"(*Scanner).TokenText\", Method, 0, \"\"},\n\t\t{\"(Position).String\", Method, 0, \"\"},\n\t\t{\"(Scanner).String\", Method, 0, \"\"},\n\t\t{\"Char\", Const, 0, \"\"},\n\t\t{\"Comment\", Const, 0, \"\"},\n\t\t{\"EOF\", Const, 0, \"\"},\n\t\t{\"Float\", Const, 0, \"\"},\n\t\t{\"GoTokens\", Const, 0, \"\"},\n\t\t{\"GoWhitespace\", Const, 0, \"\"},\n\t\t{\"Ident\", Const, 0, \"\"},\n\t\t{\"Int\", Const, 0, \"\"},\n\t\t{\"Position\", Type, 0, \"\"},\n\t\t{\"Position.Column\", Field, 0, \"\"},\n\t\t{\"Position.Filename\", Field, 0, \"\"},\n\t\t{\"Position.Line\", Field, 0, \"\"},\n\t\t{\"Position.Offset\", Field, 0, \"\"},\n\t\t{\"RawString\", Const, 0, \"\"},\n\t\t{\"ScanChars\", Const, 0, \"\"},\n\t\t{\"ScanComments\", Const, 0, \"\"},\n\t\t{\"ScanFloats\", Const, 0, \"\"},\n\t\t{\"ScanIdents\", Const, 0, \"\"},\n\t\t{\"ScanInts\", Const, 0, \"\"},\n\t\t{\"ScanRawStrings\", Const, 0, \"\"},\n\t\t{\"ScanStrings\", Const, 0, \"\"},\n\t\t{\"Scanner\", Type, 0, \"\"},\n\t\t{\"Scanner.Error\", Field, 0, \"\"},\n\t\t{\"Scanner.ErrorCount\", Field, 0, \"\"},\n\t\t{\"Scanner.IsIdentRune\", Field, 4, \"\"},\n\t\t{\"Scanner.Mode\", Field, 0, \"\"},\n\t\t{\"Scanner.Position\", Field, 0, \"\"},\n\t\t{\"Scanner.Whitespace\", Field, 0, \"\"},\n\t\t{\"SkipComments\", Const, 0, \"\"},\n\t\t{\"String\", Const, 0, \"\"},\n\t\t{\"TokenString\", Func, 0, \"func(tok rune) string\"},\n\t},\n\t\"text/tabwriter\": {\n\t\t{\"(*Writer).Flush\", Method, 0, \"\"},\n\t\t{\"(*Writer).Init\", Method, 0, \"\"},\n\t\t{\"(*Writer).Write\", Method, 0, \"\"},\n\t\t{\"AlignRight\", Const, 0, \"\"},\n\t\t{\"Debug\", Const, 0, \"\"},\n\t\t{\"DiscardEmptyColumns\", Const, 0, \"\"},\n\t\t{\"Escape\", Const, 0, \"\"},\n\t\t{\"FilterHTML\", Const, 0, \"\"},\n\t\t{\"NewWriter\", Func, 0, \"func(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer\"},\n\t\t{\"StripEscape\", Const, 0, \"\"},\n\t\t{\"TabIndent\", Const, 0, \"\"},\n\t\t{\"Writer\", Type, 0, \"\"},\n\t},\n\t\"text/template\": {\n\t\t{\"(*Template).AddParseTree\", Method, 0, \"\"},\n\t\t{\"(*Template).Clone\", Method, 0, \"\"},\n\t\t{\"(*Template).DefinedTemplates\", Method, 5, \"\"},\n\t\t{\"(*Template).Delims\", Method, 0, \"\"},\n\t\t{\"(*Template).Execute\", Method, 0, \"\"},\n\t\t{\"(*Template).ExecuteTemplate\", Method, 0, \"\"},\n\t\t{\"(*Template).Funcs\", Method, 0, \"\"},\n\t\t{\"(*Template).Lookup\", Method, 0, \"\"},\n\t\t{\"(*Template).Name\", Method, 0, \"\"},\n\t\t{\"(*Template).New\", Method, 0, \"\"},\n\t\t{\"(*Template).Option\", Method, 5, \"\"},\n\t\t{\"(*Template).Parse\", Method, 0, \"\"},\n\t\t{\"(*Template).ParseFS\", Method, 16, \"\"},\n\t\t{\"(*Template).ParseFiles\", Method, 0, \"\"},\n\t\t{\"(*Template).ParseGlob\", Method, 0, \"\"},\n\t\t{\"(*Template).Templates\", Method, 0, \"\"},\n\t\t{\"(ExecError).Error\", Method, 6, \"\"},\n\t\t{\"(ExecError).Unwrap\", Method, 13, \"\"},\n\t\t{\"(Template).Copy\", Method, 2, \"\"},\n\t\t{\"(Template).ErrorContext\", Method, 1, \"\"},\n\t\t{\"ExecError\", Type, 6, \"\"},\n\t\t{\"ExecError.Err\", Field, 6, \"\"},\n\t\t{\"ExecError.Name\", Field, 6, \"\"},\n\t\t{\"FuncMap\", Type, 0, \"\"},\n\t\t{\"HTMLEscape\", Func, 0, \"func(w io.Writer, b []byte)\"},\n\t\t{\"HTMLEscapeString\", Func, 0, \"func(s string) string\"},\n\t\t{\"HTMLEscaper\", Func, 0, \"func(args ...any) string\"},\n\t\t{\"IsTrue\", Func, 6, \"func(val any) (truth bool, ok bool)\"},\n\t\t{\"JSEscape\", Func, 0, \"func(w io.Writer, b []byte)\"},\n\t\t{\"JSEscapeString\", Func, 0, \"func(s string) string\"},\n\t\t{\"JSEscaper\", Func, 0, \"func(args ...any) string\"},\n\t\t{\"Must\", Func, 0, \"func(t *Template, err error) *Template\"},\n\t\t{\"New\", Func, 0, \"func(name string) *Template\"},\n\t\t{\"ParseFS\", Func, 16, \"func(fsys fs.FS, patterns ...string) (*Template, error)\"},\n\t\t{\"ParseFiles\", Func, 0, \"func(filenames ...string) (*Template, error)\"},\n\t\t{\"ParseGlob\", Func, 0, \"func(pattern string) (*Template, error)\"},\n\t\t{\"Template\", Type, 0, \"\"},\n\t\t{\"Template.Tree\", Field, 0, \"\"},\n\t\t{\"URLQueryEscaper\", Func, 0, \"func(args ...any) string\"},\n\t},\n\t\"text/template/parse\": {\n\t\t{\"(*ActionNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*ActionNode).String\", Method, 0, \"\"},\n\t\t{\"(*BoolNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*BoolNode).String\", Method, 0, \"\"},\n\t\t{\"(*BranchNode).Copy\", Method, 4, \"\"},\n\t\t{\"(*BranchNode).String\", Method, 0, \"\"},\n\t\t{\"(*BreakNode).Copy\", Method, 18, \"\"},\n\t\t{\"(*BreakNode).String\", Method, 18, \"\"},\n\t\t{\"(*ChainNode).Add\", Method, 1, \"\"},\n\t\t{\"(*ChainNode).Copy\", Method, 1, \"\"},\n\t\t{\"(*ChainNode).String\", Method, 1, \"\"},\n\t\t{\"(*CommandNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*CommandNode).String\", Method, 0, \"\"},\n\t\t{\"(*CommentNode).Copy\", Method, 16, \"\"},\n\t\t{\"(*CommentNode).String\", Method, 16, \"\"},\n\t\t{\"(*ContinueNode).Copy\", Method, 18, \"\"},\n\t\t{\"(*ContinueNode).String\", Method, 18, \"\"},\n\t\t{\"(*DotNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*DotNode).String\", Method, 0, \"\"},\n\t\t{\"(*DotNode).Type\", Method, 0, \"\"},\n\t\t{\"(*FieldNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*FieldNode).String\", Method, 0, \"\"},\n\t\t{\"(*IdentifierNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*IdentifierNode).SetPos\", Method, 1, \"\"},\n\t\t{\"(*IdentifierNode).SetTree\", Method, 4, \"\"},\n\t\t{\"(*IdentifierNode).String\", Method, 0, \"\"},\n\t\t{\"(*IfNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*IfNode).String\", Method, 0, \"\"},\n\t\t{\"(*ListNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*ListNode).CopyList\", Method, 0, \"\"},\n\t\t{\"(*ListNode).String\", Method, 0, \"\"},\n\t\t{\"(*NilNode).Copy\", Method, 1, \"\"},\n\t\t{\"(*NilNode).String\", Method, 1, \"\"},\n\t\t{\"(*NilNode).Type\", Method, 1, \"\"},\n\t\t{\"(*NumberNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*NumberNode).String\", Method, 0, \"\"},\n\t\t{\"(*PipeNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*PipeNode).CopyPipe\", Method, 0, \"\"},\n\t\t{\"(*PipeNode).String\", Method, 0, \"\"},\n\t\t{\"(*RangeNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*RangeNode).String\", Method, 0, \"\"},\n\t\t{\"(*StringNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*StringNode).String\", Method, 0, \"\"},\n\t\t{\"(*TemplateNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*TemplateNode).String\", Method, 0, \"\"},\n\t\t{\"(*TextNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*TextNode).String\", Method, 0, \"\"},\n\t\t{\"(*Tree).Copy\", Method, 2, \"\"},\n\t\t{\"(*Tree).ErrorContext\", Method, 1, \"\"},\n\t\t{\"(*Tree).Parse\", Method, 0, \"\"},\n\t\t{\"(*VariableNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*VariableNode).String\", Method, 0, \"\"},\n\t\t{\"(*WithNode).Copy\", Method, 0, \"\"},\n\t\t{\"(*WithNode).String\", Method, 0, \"\"},\n\t\t{\"(ActionNode).Position\", Method, 1, \"\"},\n\t\t{\"(ActionNode).Type\", Method, 0, \"\"},\n\t\t{\"(BoolNode).Position\", Method, 1, \"\"},\n\t\t{\"(BoolNode).Type\", Method, 0, \"\"},\n\t\t{\"(BranchNode).Position\", Method, 1, \"\"},\n\t\t{\"(BranchNode).Type\", Method, 0, \"\"},\n\t\t{\"(BreakNode).Position\", Method, 18, \"\"},\n\t\t{\"(BreakNode).Type\", Method, 18, \"\"},\n\t\t{\"(ChainNode).Position\", Method, 1, \"\"},\n\t\t{\"(ChainNode).Type\", Method, 1, \"\"},\n\t\t{\"(CommandNode).Position\", Method, 1, \"\"},\n\t\t{\"(CommandNode).Type\", Method, 0, \"\"},\n\t\t{\"(CommentNode).Position\", Method, 16, \"\"},\n\t\t{\"(CommentNode).Type\", Method, 16, \"\"},\n\t\t{\"(ContinueNode).Position\", Method, 18, \"\"},\n\t\t{\"(ContinueNode).Type\", Method, 18, \"\"},\n\t\t{\"(DotNode).Position\", Method, 1, \"\"},\n\t\t{\"(FieldNode).Position\", Method, 1, \"\"},\n\t\t{\"(FieldNode).Type\", Method, 0, \"\"},\n\t\t{\"(IdentifierNode).Position\", Method, 1, \"\"},\n\t\t{\"(IdentifierNode).Type\", Method, 0, \"\"},\n\t\t{\"(IfNode).Position\", Method, 1, \"\"},\n\t\t{\"(IfNode).Type\", Method, 0, \"\"},\n\t\t{\"(ListNode).Position\", Method, 1, \"\"},\n\t\t{\"(ListNode).Type\", Method, 0, \"\"},\n\t\t{\"(NilNode).Position\", Method, 1, \"\"},\n\t\t{\"(Node).Copy\", Method, 0, \"\"},\n\t\t{\"(Node).Position\", Method, 1, \"\"},\n\t\t{\"(Node).String\", Method, 0, \"\"},\n\t\t{\"(Node).Type\", Method, 0, \"\"},\n\t\t{\"(NodeType).Type\", Method, 0, \"\"},\n\t\t{\"(NumberNode).Position\", Method, 1, \"\"},\n\t\t{\"(NumberNode).Type\", Method, 0, \"\"},\n\t\t{\"(PipeNode).Position\", Method, 1, \"\"},\n\t\t{\"(PipeNode).Type\", Method, 0, \"\"},\n\t\t{\"(Pos).Position\", Method, 1, \"\"},\n\t\t{\"(RangeNode).Position\", Method, 1, \"\"},\n\t\t{\"(RangeNode).Type\", Method, 0, \"\"},\n\t\t{\"(StringNode).Position\", Method, 1, \"\"},\n\t\t{\"(StringNode).Type\", Method, 0, \"\"},\n\t\t{\"(TemplateNode).Position\", Method, 1, \"\"},\n\t\t{\"(TemplateNode).Type\", Method, 0, \"\"},\n\t\t{\"(TextNode).Position\", Method, 1, \"\"},\n\t\t{\"(TextNode).Type\", Method, 0, \"\"},\n\t\t{\"(VariableNode).Position\", Method, 1, \"\"},\n\t\t{\"(VariableNode).Type\", Method, 0, \"\"},\n\t\t{\"(WithNode).Position\", Method, 1, \"\"},\n\t\t{\"(WithNode).Type\", Method, 0, \"\"},\n\t\t{\"ActionNode\", Type, 0, \"\"},\n\t\t{\"ActionNode.Line\", Field, 0, \"\"},\n\t\t{\"ActionNode.NodeType\", Field, 0, \"\"},\n\t\t{\"ActionNode.Pipe\", Field, 0, \"\"},\n\t\t{\"ActionNode.Pos\", Field, 1, \"\"},\n\t\t{\"BoolNode\", Type, 0, \"\"},\n\t\t{\"BoolNode.NodeType\", Field, 0, \"\"},\n\t\t{\"BoolNode.Pos\", Field, 1, \"\"},\n\t\t{\"BoolNode.True\", Field, 0, \"\"},\n\t\t{\"BranchNode\", Type, 0, \"\"},\n\t\t{\"BranchNode.ElseList\", Field, 0, \"\"},\n\t\t{\"BranchNode.Line\", Field, 0, \"\"},\n\t\t{\"BranchNode.List\", Field, 0, \"\"},\n\t\t{\"BranchNode.NodeType\", Field, 0, \"\"},\n\t\t{\"BranchNode.Pipe\", Field, 0, \"\"},\n\t\t{\"BranchNode.Pos\", Field, 1, \"\"},\n\t\t{\"BreakNode\", Type, 18, \"\"},\n\t\t{\"BreakNode.Line\", Field, 18, \"\"},\n\t\t{\"BreakNode.NodeType\", Field, 18, \"\"},\n\t\t{\"BreakNode.Pos\", Field, 18, \"\"},\n\t\t{\"ChainNode\", Type, 1, \"\"},\n\t\t{\"ChainNode.Field\", Field, 1, \"\"},\n\t\t{\"ChainNode.Node\", Field, 1, \"\"},\n\t\t{\"ChainNode.NodeType\", Field, 1, \"\"},\n\t\t{\"ChainNode.Pos\", Field, 1, \"\"},\n\t\t{\"CommandNode\", Type, 0, \"\"},\n\t\t{\"CommandNode.Args\", Field, 0, \"\"},\n\t\t{\"CommandNode.NodeType\", Field, 0, \"\"},\n\t\t{\"CommandNode.Pos\", Field, 1, \"\"},\n\t\t{\"CommentNode\", Type, 16, \"\"},\n\t\t{\"CommentNode.NodeType\", Field, 16, \"\"},\n\t\t{\"CommentNode.Pos\", Field, 16, \"\"},\n\t\t{\"CommentNode.Text\", Field, 16, \"\"},\n\t\t{\"ContinueNode\", Type, 18, \"\"},\n\t\t{\"ContinueNode.Line\", Field, 18, \"\"},\n\t\t{\"ContinueNode.NodeType\", Field, 18, \"\"},\n\t\t{\"ContinueNode.Pos\", Field, 18, \"\"},\n\t\t{\"DotNode\", Type, 0, \"\"},\n\t\t{\"DotNode.NodeType\", Field, 4, \"\"},\n\t\t{\"DotNode.Pos\", Field, 1, \"\"},\n\t\t{\"FieldNode\", Type, 0, \"\"},\n\t\t{\"FieldNode.Ident\", Field, 0, \"\"},\n\t\t{\"FieldNode.NodeType\", Field, 0, \"\"},\n\t\t{\"FieldNode.Pos\", Field, 1, \"\"},\n\t\t{\"IdentifierNode\", Type, 0, \"\"},\n\t\t{\"IdentifierNode.Ident\", Field, 0, \"\"},\n\t\t{\"IdentifierNode.NodeType\", Field, 0, \"\"},\n\t\t{\"IdentifierNode.Pos\", Field, 1, \"\"},\n\t\t{\"IfNode\", Type, 0, \"\"},\n\t\t{\"IfNode.BranchNode\", Field, 0, \"\"},\n\t\t{\"IsEmptyTree\", Func, 0, \"func(n Node) bool\"},\n\t\t{\"ListNode\", Type, 0, \"\"},\n\t\t{\"ListNode.NodeType\", Field, 0, \"\"},\n\t\t{\"ListNode.Nodes\", Field, 0, \"\"},\n\t\t{\"ListNode.Pos\", Field, 1, \"\"},\n\t\t{\"Mode\", Type, 16, \"\"},\n\t\t{\"New\", Func, 0, \"func(name string, funcs ...map[string]any) *Tree\"},\n\t\t{\"NewIdentifier\", Func, 0, \"func(ident string) *IdentifierNode\"},\n\t\t{\"NilNode\", Type, 1, \"\"},\n\t\t{\"NilNode.NodeType\", Field, 4, \"\"},\n\t\t{\"NilNode.Pos\", Field, 1, \"\"},\n\t\t{\"Node\", Type, 0, \"\"},\n\t\t{\"NodeAction\", Const, 0, \"\"},\n\t\t{\"NodeBool\", Const, 0, \"\"},\n\t\t{\"NodeBreak\", Const, 18, \"\"},\n\t\t{\"NodeChain\", Const, 1, \"\"},\n\t\t{\"NodeCommand\", Const, 0, \"\"},\n\t\t{\"NodeComment\", Const, 16, \"\"},\n\t\t{\"NodeContinue\", Const, 18, \"\"},\n\t\t{\"NodeDot\", Const, 0, \"\"},\n\t\t{\"NodeField\", Const, 0, \"\"},\n\t\t{\"NodeIdentifier\", Const, 0, \"\"},\n\t\t{\"NodeIf\", Const, 0, \"\"},\n\t\t{\"NodeList\", Const, 0, \"\"},\n\t\t{\"NodeNil\", Const, 1, \"\"},\n\t\t{\"NodeNumber\", Const, 0, \"\"},\n\t\t{\"NodePipe\", Const, 0, \"\"},\n\t\t{\"NodeRange\", Const, 0, \"\"},\n\t\t{\"NodeString\", Const, 0, \"\"},\n\t\t{\"NodeTemplate\", Const, 0, \"\"},\n\t\t{\"NodeText\", Const, 0, \"\"},\n\t\t{\"NodeType\", Type, 0, \"\"},\n\t\t{\"NodeVariable\", Const, 0, \"\"},\n\t\t{\"NodeWith\", Const, 0, \"\"},\n\t\t{\"NumberNode\", Type, 0, \"\"},\n\t\t{\"NumberNode.Complex128\", Field, 0, \"\"},\n\t\t{\"NumberNode.Float64\", Field, 0, \"\"},\n\t\t{\"NumberNode.Int64\", Field, 0, \"\"},\n\t\t{\"NumberNode.IsComplex\", Field, 0, \"\"},\n\t\t{\"NumberNode.IsFloat\", Field, 0, \"\"},\n\t\t{\"NumberNode.IsInt\", Field, 0, \"\"},\n\t\t{\"NumberNode.IsUint\", Field, 0, \"\"},\n\t\t{\"NumberNode.NodeType\", Field, 0, \"\"},\n\t\t{\"NumberNode.Pos\", Field, 1, \"\"},\n\t\t{\"NumberNode.Text\", Field, 0, \"\"},\n\t\t{\"NumberNode.Uint64\", Field, 0, \"\"},\n\t\t{\"Parse\", Func, 0, \"func(name string, text string, leftDelim string, rightDelim string, funcs ...map[string]any) (map[string]*Tree, error)\"},\n\t\t{\"ParseComments\", Const, 16, \"\"},\n\t\t{\"PipeNode\", Type, 0, \"\"},\n\t\t{\"PipeNode.Cmds\", Field, 0, \"\"},\n\t\t{\"PipeNode.Decl\", Field, 0, \"\"},\n\t\t{\"PipeNode.IsAssign\", Field, 11, \"\"},\n\t\t{\"PipeNode.Line\", Field, 0, \"\"},\n\t\t{\"PipeNode.NodeType\", Field, 0, \"\"},\n\t\t{\"PipeNode.Pos\", Field, 1, \"\"},\n\t\t{\"Pos\", Type, 1, \"\"},\n\t\t{\"RangeNode\", Type, 0, \"\"},\n\t\t{\"RangeNode.BranchNode\", Field, 0, \"\"},\n\t\t{\"SkipFuncCheck\", Const, 17, \"\"},\n\t\t{\"StringNode\", Type, 0, \"\"},\n\t\t{\"StringNode.NodeType\", Field, 0, \"\"},\n\t\t{\"StringNode.Pos\", Field, 1, \"\"},\n\t\t{\"StringNode.Quoted\", Field, 0, \"\"},\n\t\t{\"StringNode.Text\", Field, 0, \"\"},\n\t\t{\"TemplateNode\", Type, 0, \"\"},\n\t\t{\"TemplateNode.Line\", Field, 0, \"\"},\n\t\t{\"TemplateNode.Name\", Field, 0, \"\"},\n\t\t{\"TemplateNode.NodeType\", Field, 0, \"\"},\n\t\t{\"TemplateNode.Pipe\", Field, 0, \"\"},\n\t\t{\"TemplateNode.Pos\", Field, 1, \"\"},\n\t\t{\"TextNode\", Type, 0, \"\"},\n\t\t{\"TextNode.NodeType\", Field, 0, \"\"},\n\t\t{\"TextNode.Pos\", Field, 1, \"\"},\n\t\t{\"TextNode.Text\", Field, 0, \"\"},\n\t\t{\"Tree\", Type, 0, \"\"},\n\t\t{\"Tree.Mode\", Field, 16, \"\"},\n\t\t{\"Tree.Name\", Field, 0, \"\"},\n\t\t{\"Tree.ParseName\", Field, 1, \"\"},\n\t\t{\"Tree.Root\", Field, 0, \"\"},\n\t\t{\"VariableNode\", Type, 0, \"\"},\n\t\t{\"VariableNode.Ident\", Field, 0, \"\"},\n\t\t{\"VariableNode.NodeType\", Field, 0, \"\"},\n\t\t{\"VariableNode.Pos\", Field, 1, \"\"},\n\t\t{\"WithNode\", Type, 0, \"\"},\n\t\t{\"WithNode.BranchNode\", Field, 0, \"\"},\n\t},\n\t\"time\": {\n\t\t{\"(*Location).String\", Method, 0, \"\"},\n\t\t{\"(*ParseError).Error\", Method, 0, \"\"},\n\t\t{\"(*Ticker).Reset\", Method, 15, \"\"},\n\t\t{\"(*Ticker).Stop\", Method, 0, \"\"},\n\t\t{\"(*Time).GobDecode\", Method, 0, \"\"},\n\t\t{\"(*Time).UnmarshalBinary\", Method, 2, \"\"},\n\t\t{\"(*Time).UnmarshalJSON\", Method, 0, \"\"},\n\t\t{\"(*Time).UnmarshalText\", Method, 2, \"\"},\n\t\t{\"(*Timer).Reset\", Method, 1, \"\"},\n\t\t{\"(*Timer).Stop\", Method, 0, \"\"},\n\t\t{\"(Duration).Abs\", Method, 19, \"\"},\n\t\t{\"(Duration).Hours\", Method, 0, \"\"},\n\t\t{\"(Duration).Microseconds\", Method, 13, \"\"},\n\t\t{\"(Duration).Milliseconds\", Method, 13, \"\"},\n\t\t{\"(Duration).Minutes\", Method, 0, \"\"},\n\t\t{\"(Duration).Nanoseconds\", Method, 0, \"\"},\n\t\t{\"(Duration).Round\", Method, 9, \"\"},\n\t\t{\"(Duration).Seconds\", Method, 0, \"\"},\n\t\t{\"(Duration).String\", Method, 0, \"\"},\n\t\t{\"(Duration).Truncate\", Method, 9, \"\"},\n\t\t{\"(Month).String\", Method, 0, \"\"},\n\t\t{\"(Time).Add\", Method, 0, \"\"},\n\t\t{\"(Time).AddDate\", Method, 0, \"\"},\n\t\t{\"(Time).After\", Method, 0, \"\"},\n\t\t{\"(Time).AppendBinary\", Method, 24, \"\"},\n\t\t{\"(Time).AppendFormat\", Method, 5, \"\"},\n\t\t{\"(Time).AppendText\", Method, 24, \"\"},\n\t\t{\"(Time).Before\", Method, 0, \"\"},\n\t\t{\"(Time).Clock\", Method, 0, \"\"},\n\t\t{\"(Time).Compare\", Method, 20, \"\"},\n\t\t{\"(Time).Date\", Method, 0, \"\"},\n\t\t{\"(Time).Day\", Method, 0, \"\"},\n\t\t{\"(Time).Equal\", Method, 0, \"\"},\n\t\t{\"(Time).Format\", Method, 0, \"\"},\n\t\t{\"(Time).GoString\", Method, 17, \"\"},\n\t\t{\"(Time).GobEncode\", Method, 0, \"\"},\n\t\t{\"(Time).Hour\", Method, 0, \"\"},\n\t\t{\"(Time).ISOWeek\", Method, 0, \"\"},\n\t\t{\"(Time).In\", Method, 0, \"\"},\n\t\t{\"(Time).IsDST\", Method, 17, \"\"},\n\t\t{\"(Time).IsZero\", Method, 0, \"\"},\n\t\t{\"(Time).Local\", Method, 0, \"\"},\n\t\t{\"(Time).Location\", Method, 0, \"\"},\n\t\t{\"(Time).MarshalBinary\", Method, 2, \"\"},\n\t\t{\"(Time).MarshalJSON\", Method, 0, \"\"},\n\t\t{\"(Time).MarshalText\", Method, 2, \"\"},\n\t\t{\"(Time).Minute\", Method, 0, \"\"},\n\t\t{\"(Time).Month\", Method, 0, \"\"},\n\t\t{\"(Time).Nanosecond\", Method, 0, \"\"},\n\t\t{\"(Time).Round\", Method, 1, \"\"},\n\t\t{\"(Time).Second\", Method, 0, \"\"},\n\t\t{\"(Time).String\", Method, 0, \"\"},\n\t\t{\"(Time).Sub\", Method, 0, \"\"},\n\t\t{\"(Time).Truncate\", Method, 1, \"\"},\n\t\t{\"(Time).UTC\", Method, 0, \"\"},\n\t\t{\"(Time).Unix\", Method, 0, \"\"},\n\t\t{\"(Time).UnixMicro\", Method, 17, \"\"},\n\t\t{\"(Time).UnixMilli\", Method, 17, \"\"},\n\t\t{\"(Time).UnixNano\", Method, 0, \"\"},\n\t\t{\"(Time).Weekday\", Method, 0, \"\"},\n\t\t{\"(Time).Year\", Method, 0, \"\"},\n\t\t{\"(Time).YearDay\", Method, 1, \"\"},\n\t\t{\"(Time).Zone\", Method, 0, \"\"},\n\t\t{\"(Time).ZoneBounds\", Method, 19, \"\"},\n\t\t{\"(Weekday).String\", Method, 0, \"\"},\n\t\t{\"ANSIC\", Const, 0, \"\"},\n\t\t{\"After\", Func, 0, \"func(d Duration) <-chan Time\"},\n\t\t{\"AfterFunc\", Func, 0, \"func(d Duration, f func()) *Timer\"},\n\t\t{\"April\", Const, 0, \"\"},\n\t\t{\"August\", Const, 0, \"\"},\n\t\t{\"Date\", Func, 0, \"func(year int, month Month, day int, hour int, min int, sec int, nsec int, loc *Location) Time\"},\n\t\t{\"DateOnly\", Const, 20, \"\"},\n\t\t{\"DateTime\", Const, 20, \"\"},\n\t\t{\"December\", Const, 0, \"\"},\n\t\t{\"Duration\", Type, 0, \"\"},\n\t\t{\"February\", Const, 0, \"\"},\n\t\t{\"FixedZone\", Func, 0, \"func(name string, offset int) *Location\"},\n\t\t{\"Friday\", Const, 0, \"\"},\n\t\t{\"Hour\", Const, 0, \"\"},\n\t\t{\"January\", Const, 0, \"\"},\n\t\t{\"July\", Const, 0, \"\"},\n\t\t{\"June\", Const, 0, \"\"},\n\t\t{\"Kitchen\", Const, 0, \"\"},\n\t\t{\"Layout\", Const, 17, \"\"},\n\t\t{\"LoadLocation\", Func, 0, \"func(name string) (*Location, error)\"},\n\t\t{\"LoadLocationFromTZData\", Func, 10, \"func(name string, data []byte) (*Location, error)\"},\n\t\t{\"Local\", Var, 0, \"\"},\n\t\t{\"Location\", Type, 0, \"\"},\n\t\t{\"March\", Const, 0, \"\"},\n\t\t{\"May\", Const, 0, \"\"},\n\t\t{\"Microsecond\", Const, 0, \"\"},\n\t\t{\"Millisecond\", Const, 0, \"\"},\n\t\t{\"Minute\", Const, 0, \"\"},\n\t\t{\"Monday\", Const, 0, \"\"},\n\t\t{\"Month\", Type, 0, \"\"},\n\t\t{\"Nanosecond\", Const, 0, \"\"},\n\t\t{\"NewTicker\", Func, 0, \"func(d Duration) *Ticker\"},\n\t\t{\"NewTimer\", Func, 0, \"func(d Duration) *Timer\"},\n\t\t{\"November\", Const, 0, \"\"},\n\t\t{\"Now\", Func, 0, \"func() Time\"},\n\t\t{\"October\", Const, 0, \"\"},\n\t\t{\"Parse\", Func, 0, \"func(layout string, value string) (Time, error)\"},\n\t\t{\"ParseDuration\", Func, 0, \"func(s string) (Duration, error)\"},\n\t\t{\"ParseError\", Type, 0, \"\"},\n\t\t{\"ParseError.Layout\", Field, 0, \"\"},\n\t\t{\"ParseError.LayoutElem\", Field, 0, \"\"},\n\t\t{\"ParseError.Message\", Field, 0, \"\"},\n\t\t{\"ParseError.Value\", Field, 0, \"\"},\n\t\t{\"ParseError.ValueElem\", Field, 0, \"\"},\n\t\t{\"ParseInLocation\", Func, 1, \"func(layout string, value string, loc *Location) (Time, error)\"},\n\t\t{\"RFC1123\", Const, 0, \"\"},\n\t\t{\"RFC1123Z\", Const, 0, \"\"},\n\t\t{\"RFC3339\", Const, 0, \"\"},\n\t\t{\"RFC3339Nano\", Const, 0, \"\"},\n\t\t{\"RFC822\", Const, 0, \"\"},\n\t\t{\"RFC822Z\", Const, 0, \"\"},\n\t\t{\"RFC850\", Const, 0, \"\"},\n\t\t{\"RubyDate\", Const, 0, \"\"},\n\t\t{\"Saturday\", Const, 0, \"\"},\n\t\t{\"Second\", Const, 0, \"\"},\n\t\t{\"September\", Const, 0, \"\"},\n\t\t{\"Since\", Func, 0, \"func(t Time) Duration\"},\n\t\t{\"Sleep\", Func, 0, \"func(d Duration)\"},\n\t\t{\"Stamp\", Const, 0, \"\"},\n\t\t{\"StampMicro\", Const, 0, \"\"},\n\t\t{\"StampMilli\", Const, 0, \"\"},\n\t\t{\"StampNano\", Const, 0, \"\"},\n\t\t{\"Sunday\", Const, 0, \"\"},\n\t\t{\"Thursday\", Const, 0, \"\"},\n\t\t{\"Tick\", Func, 0, \"func(d Duration) <-chan Time\"},\n\t\t{\"Ticker\", Type, 0, \"\"},\n\t\t{\"Ticker.C\", Field, 0, \"\"},\n\t\t{\"Time\", Type, 0, \"\"},\n\t\t{\"TimeOnly\", Const, 20, \"\"},\n\t\t{\"Timer\", Type, 0, \"\"},\n\t\t{\"Timer.C\", Field, 0, \"\"},\n\t\t{\"Tuesday\", Const, 0, \"\"},\n\t\t{\"UTC\", Var, 0, \"\"},\n\t\t{\"Unix\", Func, 0, \"func(sec int64, nsec int64) Time\"},\n\t\t{\"UnixDate\", Const, 0, \"\"},\n\t\t{\"UnixMicro\", Func, 17, \"func(usec int64) Time\"},\n\t\t{\"UnixMilli\", Func, 17, \"func(msec int64) Time\"},\n\t\t{\"Until\", Func, 8, \"func(t Time) Duration\"},\n\t\t{\"Wednesday\", Const, 0, \"\"},\n\t\t{\"Weekday\", Type, 0, \"\"},\n\t},\n\t\"unicode\": {\n\t\t{\"(SpecialCase).ToLower\", Method, 0, \"\"},\n\t\t{\"(SpecialCase).ToTitle\", Method, 0, \"\"},\n\t\t{\"(SpecialCase).ToUpper\", Method, 0, \"\"},\n\t\t{\"ASCII_Hex_Digit\", Var, 0, \"\"},\n\t\t{\"Adlam\", Var, 7, \"\"},\n\t\t{\"Ahom\", Var, 5, \"\"},\n\t\t{\"Anatolian_Hieroglyphs\", Var, 5, \"\"},\n\t\t{\"Arabic\", Var, 0, \"\"},\n\t\t{\"Armenian\", Var, 0, \"\"},\n\t\t{\"Avestan\", Var, 0, \"\"},\n\t\t{\"AzeriCase\", Var, 0, \"\"},\n\t\t{\"Balinese\", Var, 0, \"\"},\n\t\t{\"Bamum\", Var, 0, \"\"},\n\t\t{\"Bassa_Vah\", Var, 4, \"\"},\n\t\t{\"Batak\", Var, 0, \"\"},\n\t\t{\"Bengali\", Var, 0, \"\"},\n\t\t{\"Bhaiksuki\", Var, 7, \"\"},\n\t\t{\"Bidi_Control\", Var, 0, \"\"},\n\t\t{\"Bopomofo\", Var, 0, \"\"},\n\t\t{\"Brahmi\", Var, 0, \"\"},\n\t\t{\"Braille\", Var, 0, \"\"},\n\t\t{\"Buginese\", Var, 0, \"\"},\n\t\t{\"Buhid\", Var, 0, \"\"},\n\t\t{\"C\", Var, 0, \"\"},\n\t\t{\"Canadian_Aboriginal\", Var, 0, \"\"},\n\t\t{\"Carian\", Var, 0, \"\"},\n\t\t{\"CaseRange\", Type, 0, \"\"},\n\t\t{\"CaseRange.Delta\", Field, 0, \"\"},\n\t\t{\"CaseRange.Hi\", Field, 0, \"\"},\n\t\t{\"CaseRange.Lo\", Field, 0, \"\"},\n\t\t{\"CaseRanges\", Var, 0, \"\"},\n\t\t{\"Categories\", Var, 0, \"\"},\n\t\t{\"CategoryAliases\", Var, 25, \"\"},\n\t\t{\"Caucasian_Albanian\", Var, 4, \"\"},\n\t\t{\"Cc\", Var, 0, \"\"},\n\t\t{\"Cf\", Var, 0, \"\"},\n\t\t{\"Chakma\", Var, 1, \"\"},\n\t\t{\"Cham\", Var, 0, \"\"},\n\t\t{\"Cherokee\", Var, 0, \"\"},\n\t\t{\"Chorasmian\", Var, 16, \"\"},\n\t\t{\"Cn\", Var, 25, \"\"},\n\t\t{\"Co\", Var, 0, \"\"},\n\t\t{\"Common\", Var, 0, \"\"},\n\t\t{\"Coptic\", Var, 0, \"\"},\n\t\t{\"Cs\", Var, 0, \"\"},\n\t\t{\"Cuneiform\", Var, 0, \"\"},\n\t\t{\"Cypriot\", Var, 0, \"\"},\n\t\t{\"Cypro_Minoan\", Var, 21, \"\"},\n\t\t{\"Cyrillic\", Var, 0, \"\"},\n\t\t{\"Dash\", Var, 0, \"\"},\n\t\t{\"Deprecated\", Var, 0, \"\"},\n\t\t{\"Deseret\", Var, 0, \"\"},\n\t\t{\"Devanagari\", Var, 0, \"\"},\n\t\t{\"Diacritic\", Var, 0, \"\"},\n\t\t{\"Digit\", Var, 0, \"\"},\n\t\t{\"Dives_Akuru\", Var, 16, \"\"},\n\t\t{\"Dogra\", Var, 13, \"\"},\n\t\t{\"Duployan\", Var, 4, \"\"},\n\t\t{\"Egyptian_Hieroglyphs\", Var, 0, \"\"},\n\t\t{\"Elbasan\", Var, 4, \"\"},\n\t\t{\"Elymaic\", Var, 14, \"\"},\n\t\t{\"Ethiopic\", Var, 0, \"\"},\n\t\t{\"Extender\", Var, 0, \"\"},\n\t\t{\"FoldCategory\", Var, 0, \"\"},\n\t\t{\"FoldScript\", Var, 0, \"\"},\n\t\t{\"Georgian\", Var, 0, \"\"},\n\t\t{\"Glagolitic\", Var, 0, \"\"},\n\t\t{\"Gothic\", Var, 0, \"\"},\n\t\t{\"Grantha\", Var, 4, \"\"},\n\t\t{\"GraphicRanges\", Var, 0, \"\"},\n\t\t{\"Greek\", Var, 0, \"\"},\n\t\t{\"Gujarati\", Var, 0, \"\"},\n\t\t{\"Gunjala_Gondi\", Var, 13, \"\"},\n\t\t{\"Gurmukhi\", Var, 0, \"\"},\n\t\t{\"Han\", Var, 0, \"\"},\n\t\t{\"Hangul\", Var, 0, \"\"},\n\t\t{\"Hanifi_Rohingya\", Var, 13, \"\"},\n\t\t{\"Hanunoo\", Var, 0, \"\"},\n\t\t{\"Hatran\", Var, 5, \"\"},\n\t\t{\"Hebrew\", Var, 0, \"\"},\n\t\t{\"Hex_Digit\", Var, 0, \"\"},\n\t\t{\"Hiragana\", Var, 0, \"\"},\n\t\t{\"Hyphen\", Var, 0, \"\"},\n\t\t{\"IDS_Binary_Operator\", Var, 0, \"\"},\n\t\t{\"IDS_Trinary_Operator\", Var, 0, \"\"},\n\t\t{\"Ideographic\", Var, 0, \"\"},\n\t\t{\"Imperial_Aramaic\", Var, 0, \"\"},\n\t\t{\"In\", Func, 2, \"func(r rune, ranges ...*RangeTable) bool\"},\n\t\t{\"Inherited\", Var, 0, \"\"},\n\t\t{\"Inscriptional_Pahlavi\", Var, 0, \"\"},\n\t\t{\"Inscriptional_Parthian\", Var, 0, \"\"},\n\t\t{\"Is\", Func, 0, \"func(rangeTab *RangeTable, r rune) bool\"},\n\t\t{\"IsControl\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsDigit\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsGraphic\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsLetter\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsLower\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsMark\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsNumber\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsOneOf\", Func, 0, \"func(ranges []*RangeTable, r rune) bool\"},\n\t\t{\"IsPrint\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsPunct\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsSpace\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsSymbol\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsTitle\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"IsUpper\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"Javanese\", Var, 0, \"\"},\n\t\t{\"Join_Control\", Var, 0, \"\"},\n\t\t{\"Kaithi\", Var, 0, \"\"},\n\t\t{\"Kannada\", Var, 0, \"\"},\n\t\t{\"Katakana\", Var, 0, \"\"},\n\t\t{\"Kawi\", Var, 21, \"\"},\n\t\t{\"Kayah_Li\", Var, 0, \"\"},\n\t\t{\"Kharoshthi\", Var, 0, \"\"},\n\t\t{\"Khitan_Small_Script\", Var, 16, \"\"},\n\t\t{\"Khmer\", Var, 0, \"\"},\n\t\t{\"Khojki\", Var, 4, \"\"},\n\t\t{\"Khudawadi\", Var, 4, \"\"},\n\t\t{\"L\", Var, 0, \"\"},\n\t\t{\"LC\", Var, 25, \"\"},\n\t\t{\"Lao\", Var, 0, \"\"},\n\t\t{\"Latin\", Var, 0, \"\"},\n\t\t{\"Lepcha\", Var, 0, \"\"},\n\t\t{\"Letter\", Var, 0, \"\"},\n\t\t{\"Limbu\", Var, 0, \"\"},\n\t\t{\"Linear_A\", Var, 4, \"\"},\n\t\t{\"Linear_B\", Var, 0, \"\"},\n\t\t{\"Lisu\", Var, 0, \"\"},\n\t\t{\"Ll\", Var, 0, \"\"},\n\t\t{\"Lm\", Var, 0, \"\"},\n\t\t{\"Lo\", Var, 0, \"\"},\n\t\t{\"Logical_Order_Exception\", Var, 0, \"\"},\n\t\t{\"Lower\", Var, 0, \"\"},\n\t\t{\"LowerCase\", Const, 0, \"\"},\n\t\t{\"Lt\", Var, 0, \"\"},\n\t\t{\"Lu\", Var, 0, \"\"},\n\t\t{\"Lycian\", Var, 0, \"\"},\n\t\t{\"Lydian\", Var, 0, \"\"},\n\t\t{\"M\", Var, 0, \"\"},\n\t\t{\"Mahajani\", Var, 4, \"\"},\n\t\t{\"Makasar\", Var, 13, \"\"},\n\t\t{\"Malayalam\", Var, 0, \"\"},\n\t\t{\"Mandaic\", Var, 0, \"\"},\n\t\t{\"Manichaean\", Var, 4, \"\"},\n\t\t{\"Marchen\", Var, 7, \"\"},\n\t\t{\"Mark\", Var, 0, \"\"},\n\t\t{\"Masaram_Gondi\", Var, 10, \"\"},\n\t\t{\"MaxASCII\", Const, 0, \"\"},\n\t\t{\"MaxCase\", Const, 0, \"\"},\n\t\t{\"MaxLatin1\", Const, 0, \"\"},\n\t\t{\"MaxRune\", Const, 0, \"\"},\n\t\t{\"Mc\", Var, 0, \"\"},\n\t\t{\"Me\", Var, 0, \"\"},\n\t\t{\"Medefaidrin\", Var, 13, \"\"},\n\t\t{\"Meetei_Mayek\", Var, 0, \"\"},\n\t\t{\"Mende_Kikakui\", Var, 4, \"\"},\n\t\t{\"Meroitic_Cursive\", Var, 1, \"\"},\n\t\t{\"Meroitic_Hieroglyphs\", Var, 1, \"\"},\n\t\t{\"Miao\", Var, 1, \"\"},\n\t\t{\"Mn\", Var, 0, \"\"},\n\t\t{\"Modi\", Var, 4, \"\"},\n\t\t{\"Mongolian\", Var, 0, \"\"},\n\t\t{\"Mro\", Var, 4, \"\"},\n\t\t{\"Multani\", Var, 5, \"\"},\n\t\t{\"Myanmar\", Var, 0, \"\"},\n\t\t{\"N\", Var, 0, \"\"},\n\t\t{\"Nabataean\", Var, 4, \"\"},\n\t\t{\"Nag_Mundari\", Var, 21, \"\"},\n\t\t{\"Nandinagari\", Var, 14, \"\"},\n\t\t{\"Nd\", Var, 0, \"\"},\n\t\t{\"New_Tai_Lue\", Var, 0, \"\"},\n\t\t{\"Newa\", Var, 7, \"\"},\n\t\t{\"Nko\", Var, 0, \"\"},\n\t\t{\"Nl\", Var, 0, \"\"},\n\t\t{\"No\", Var, 0, \"\"},\n\t\t{\"Noncharacter_Code_Point\", Var, 0, \"\"},\n\t\t{\"Number\", Var, 0, \"\"},\n\t\t{\"Nushu\", Var, 10, \"\"},\n\t\t{\"Nyiakeng_Puachue_Hmong\", Var, 14, \"\"},\n\t\t{\"Ogham\", Var, 0, \"\"},\n\t\t{\"Ol_Chiki\", Var, 0, \"\"},\n\t\t{\"Old_Hungarian\", Var, 5, \"\"},\n\t\t{\"Old_Italic\", Var, 0, \"\"},\n\t\t{\"Old_North_Arabian\", Var, 4, \"\"},\n\t\t{\"Old_Permic\", Var, 4, \"\"},\n\t\t{\"Old_Persian\", Var, 0, \"\"},\n\t\t{\"Old_Sogdian\", Var, 13, \"\"},\n\t\t{\"Old_South_Arabian\", Var, 0, \"\"},\n\t\t{\"Old_Turkic\", Var, 0, \"\"},\n\t\t{\"Old_Uyghur\", Var, 21, \"\"},\n\t\t{\"Oriya\", Var, 0, \"\"},\n\t\t{\"Osage\", Var, 7, \"\"},\n\t\t{\"Osmanya\", Var, 0, \"\"},\n\t\t{\"Other\", Var, 0, \"\"},\n\t\t{\"Other_Alphabetic\", Var, 0, \"\"},\n\t\t{\"Other_Default_Ignorable_Code_Point\", Var, 0, \"\"},\n\t\t{\"Other_Grapheme_Extend\", Var, 0, \"\"},\n\t\t{\"Other_ID_Continue\", Var, 0, \"\"},\n\t\t{\"Other_ID_Start\", Var, 0, \"\"},\n\t\t{\"Other_Lowercase\", Var, 0, \"\"},\n\t\t{\"Other_Math\", Var, 0, \"\"},\n\t\t{\"Other_Uppercase\", Var, 0, \"\"},\n\t\t{\"P\", Var, 0, \"\"},\n\t\t{\"Pahawh_Hmong\", Var, 4, \"\"},\n\t\t{\"Palmyrene\", Var, 4, \"\"},\n\t\t{\"Pattern_Syntax\", Var, 0, \"\"},\n\t\t{\"Pattern_White_Space\", Var, 0, \"\"},\n\t\t{\"Pau_Cin_Hau\", Var, 4, \"\"},\n\t\t{\"Pc\", Var, 0, \"\"},\n\t\t{\"Pd\", Var, 0, \"\"},\n\t\t{\"Pe\", Var, 0, \"\"},\n\t\t{\"Pf\", Var, 0, \"\"},\n\t\t{\"Phags_Pa\", Var, 0, \"\"},\n\t\t{\"Phoenician\", Var, 0, \"\"},\n\t\t{\"Pi\", Var, 0, \"\"},\n\t\t{\"Po\", Var, 0, \"\"},\n\t\t{\"Prepended_Concatenation_Mark\", Var, 7, \"\"},\n\t\t{\"PrintRanges\", Var, 0, \"\"},\n\t\t{\"Properties\", Var, 0, \"\"},\n\t\t{\"Ps\", Var, 0, \"\"},\n\t\t{\"Psalter_Pahlavi\", Var, 4, \"\"},\n\t\t{\"Punct\", Var, 0, \"\"},\n\t\t{\"Quotation_Mark\", Var, 0, \"\"},\n\t\t{\"Radical\", Var, 0, \"\"},\n\t\t{\"Range16\", Type, 0, \"\"},\n\t\t{\"Range16.Hi\", Field, 0, \"\"},\n\t\t{\"Range16.Lo\", Field, 0, \"\"},\n\t\t{\"Range16.Stride\", Field, 0, \"\"},\n\t\t{\"Range32\", Type, 0, \"\"},\n\t\t{\"Range32.Hi\", Field, 0, \"\"},\n\t\t{\"Range32.Lo\", Field, 0, \"\"},\n\t\t{\"Range32.Stride\", Field, 0, \"\"},\n\t\t{\"RangeTable\", Type, 0, \"\"},\n\t\t{\"RangeTable.LatinOffset\", Field, 1, \"\"},\n\t\t{\"RangeTable.R16\", Field, 0, \"\"},\n\t\t{\"RangeTable.R32\", Field, 0, \"\"},\n\t\t{\"Regional_Indicator\", Var, 10, \"\"},\n\t\t{\"Rejang\", Var, 0, \"\"},\n\t\t{\"ReplacementChar\", Const, 0, \"\"},\n\t\t{\"Runic\", Var, 0, \"\"},\n\t\t{\"S\", Var, 0, \"\"},\n\t\t{\"STerm\", Var, 0, \"\"},\n\t\t{\"Samaritan\", Var, 0, \"\"},\n\t\t{\"Saurashtra\", Var, 0, \"\"},\n\t\t{\"Sc\", Var, 0, \"\"},\n\t\t{\"Scripts\", Var, 0, \"\"},\n\t\t{\"Sentence_Terminal\", Var, 7, \"\"},\n\t\t{\"Sharada\", Var, 1, \"\"},\n\t\t{\"Shavian\", Var, 0, \"\"},\n\t\t{\"Siddham\", Var, 4, \"\"},\n\t\t{\"SignWriting\", Var, 5, \"\"},\n\t\t{\"SimpleFold\", Func, 0, \"func(r rune) rune\"},\n\t\t{\"Sinhala\", Var, 0, \"\"},\n\t\t{\"Sk\", Var, 0, \"\"},\n\t\t{\"Sm\", Var, 0, \"\"},\n\t\t{\"So\", Var, 0, \"\"},\n\t\t{\"Soft_Dotted\", Var, 0, \"\"},\n\t\t{\"Sogdian\", Var, 13, \"\"},\n\t\t{\"Sora_Sompeng\", Var, 1, \"\"},\n\t\t{\"Soyombo\", Var, 10, \"\"},\n\t\t{\"Space\", Var, 0, \"\"},\n\t\t{\"SpecialCase\", Type, 0, \"\"},\n\t\t{\"Sundanese\", Var, 0, \"\"},\n\t\t{\"Syloti_Nagri\", Var, 0, \"\"},\n\t\t{\"Symbol\", Var, 0, \"\"},\n\t\t{\"Syriac\", Var, 0, \"\"},\n\t\t{\"Tagalog\", Var, 0, \"\"},\n\t\t{\"Tagbanwa\", Var, 0, \"\"},\n\t\t{\"Tai_Le\", Var, 0, \"\"},\n\t\t{\"Tai_Tham\", Var, 0, \"\"},\n\t\t{\"Tai_Viet\", Var, 0, \"\"},\n\t\t{\"Takri\", Var, 1, \"\"},\n\t\t{\"Tamil\", Var, 0, \"\"},\n\t\t{\"Tangsa\", Var, 21, \"\"},\n\t\t{\"Tangut\", Var, 7, \"\"},\n\t\t{\"Telugu\", Var, 0, \"\"},\n\t\t{\"Terminal_Punctuation\", Var, 0, \"\"},\n\t\t{\"Thaana\", Var, 0, \"\"},\n\t\t{\"Thai\", Var, 0, \"\"},\n\t\t{\"Tibetan\", Var, 0, \"\"},\n\t\t{\"Tifinagh\", Var, 0, \"\"},\n\t\t{\"Tirhuta\", Var, 4, \"\"},\n\t\t{\"Title\", Var, 0, \"\"},\n\t\t{\"TitleCase\", Const, 0, \"\"},\n\t\t{\"To\", Func, 0, \"func(_case int, r rune) rune\"},\n\t\t{\"ToLower\", Func, 0, \"func(r rune) rune\"},\n\t\t{\"ToTitle\", Func, 0, \"func(r rune) rune\"},\n\t\t{\"ToUpper\", Func, 0, \"func(r rune) rune\"},\n\t\t{\"Toto\", Var, 21, \"\"},\n\t\t{\"TurkishCase\", Var, 0, \"\"},\n\t\t{\"Ugaritic\", Var, 0, \"\"},\n\t\t{\"Unified_Ideograph\", Var, 0, \"\"},\n\t\t{\"Upper\", Var, 0, \"\"},\n\t\t{\"UpperCase\", Const, 0, \"\"},\n\t\t{\"UpperLower\", Const, 0, \"\"},\n\t\t{\"Vai\", Var, 0, \"\"},\n\t\t{\"Variation_Selector\", Var, 0, \"\"},\n\t\t{\"Version\", Const, 0, \"\"},\n\t\t{\"Vithkuqi\", Var, 21, \"\"},\n\t\t{\"Wancho\", Var, 14, \"\"},\n\t\t{\"Warang_Citi\", Var, 4, \"\"},\n\t\t{\"White_Space\", Var, 0, \"\"},\n\t\t{\"Yezidi\", Var, 16, \"\"},\n\t\t{\"Yi\", Var, 0, \"\"},\n\t\t{\"Z\", Var, 0, \"\"},\n\t\t{\"Zanabazar_Square\", Var, 10, \"\"},\n\t\t{\"Zl\", Var, 0, \"\"},\n\t\t{\"Zp\", Var, 0, \"\"},\n\t\t{\"Zs\", Var, 0, \"\"},\n\t},\n\t\"unicode/utf16\": {\n\t\t{\"AppendRune\", Func, 20, \"func(a []uint16, r rune) []uint16\"},\n\t\t{\"Decode\", Func, 0, \"func(s []uint16) []rune\"},\n\t\t{\"DecodeRune\", Func, 0, \"func(r1 rune, r2 rune) rune\"},\n\t\t{\"Encode\", Func, 0, \"func(s []rune) []uint16\"},\n\t\t{\"EncodeRune\", Func, 0, \"func(r rune) (r1 rune, r2 rune)\"},\n\t\t{\"IsSurrogate\", Func, 0, \"func(r rune) bool\"},\n\t\t{\"RuneLen\", Func, 23, \"func(r rune) int\"},\n\t},\n\t\"unicode/utf8\": {\n\t\t{\"AppendRune\", Func, 18, \"func(p []byte, r rune) []byte\"},\n\t\t{\"DecodeLastRune\", Func, 0, \"func(p []byte) (r rune, size int)\"},\n\t\t{\"DecodeLastRuneInString\", Func, 0, \"func(s string) (r rune, size int)\"},\n\t\t{\"DecodeRune\", Func, 0, \"func(p []byte) (r rune, size int)\"},\n\t\t{\"DecodeRuneInString\", Func, 0, \"func(s string) (r rune, size int)\"},\n\t\t{\"EncodeRune\", Func, 0, \"func(p []byte, r rune) int\"},\n\t\t{\"FullRune\", Func, 0, \"func(p []byte) bool\"},\n\t\t{\"FullRuneInString\", Func, 0, \"func(s string) bool\"},\n\t\t{\"MaxRune\", Const, 0, \"\"},\n\t\t{\"RuneCount\", Func, 0, \"func(p []byte) int\"},\n\t\t{\"RuneCountInString\", Func, 0, \"func(s string) (n int)\"},\n\t\t{\"RuneError\", Const, 0, \"\"},\n\t\t{\"RuneLen\", Func, 0, \"func(r rune) int\"},\n\t\t{\"RuneSelf\", Const, 0, \"\"},\n\t\t{\"RuneStart\", Func, 0, \"func(b byte) bool\"},\n\t\t{\"UTFMax\", Const, 0, \"\"},\n\t\t{\"Valid\", Func, 0, \"func(p []byte) bool\"},\n\t\t{\"ValidRune\", Func, 1, \"func(r rune) bool\"},\n\t\t{\"ValidString\", Func, 0, \"func(s string) bool\"},\n\t},\n\t\"unique\": {\n\t\t{\"(Handle).Value\", Method, 23, \"\"},\n\t\t{\"Handle\", Type, 23, \"\"},\n\t\t{\"Make\", Func, 23, \"func[T comparable](value T) Handle[T]\"},\n\t},\n\t\"unsafe\": {\n\t\t{\"Add\", Func, 0, \"\"},\n\t\t{\"Alignof\", Func, 0, \"\"},\n\t\t{\"Offsetof\", Func, 0, \"\"},\n\t\t{\"Pointer\", Type, 0, \"\"},\n\t\t{\"Sizeof\", Func, 0, \"\"},\n\t\t{\"Slice\", Func, 0, \"\"},\n\t\t{\"SliceData\", Func, 0, \"\"},\n\t\t{\"String\", Func, 0, \"\"},\n\t\t{\"StringData\", Func, 0, \"\"},\n\t},\n\t\"weak\": {\n\t\t{\"(Pointer).Value\", Method, 24, \"\"},\n\t\t{\"Make\", Func, 24, \"func[T any](ptr *T) Pointer[T]\"},\n\t\t{\"Pointer\", Type, 24, \"\"},\n\t},\n}\n"
  },
  {
    "path": "internal/stdlib/stdlib.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:generate go run generate.go\n\n// Package stdlib provides a table of all exported symbols in the\n// standard library, along with the version at which they first\n// appeared. It also provides the import graph of std packages.\npackage stdlib\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype Symbol struct {\n\tName    string\n\tKind    Kind\n\tVersion Version // Go version that first included the symbol\n\t// Signature provides the type of a function (defined only for Kind=Func).\n\t// Imported types are denoted as pkg.T; pkg is not fully qualified.\n\t// TODO(adonovan): use an unambiguous encoding that is parseable.\n\t//\n\t// Example2:\n\t//    func[M ~map[K]V, K comparable, V any](m M) M\n\t//    func(fi fs.FileInfo, link string) (*Header, error)\n\tSignature string // if Kind == stdlib.Func\n}\n\n// A Kind indicates the kind of a symbol:\n// function, variable, constant, type, and so on.\ntype Kind int8\n\nconst (\n\tInvalid Kind = iota // Example name:\n\tType                // \"Buffer\"\n\tFunc                // \"Println\"\n\tVar                 // \"EOF\"\n\tConst               // \"Pi\"\n\tField               // \"Point.X\"\n\tMethod              // \"(*Buffer).Grow\" or \"(Reader).Read\"\n)\n\nfunc (kind Kind) String() string {\n\treturn [...]string{\n\t\tInvalid: \"invalid\",\n\t\tType:    \"type\",\n\t\tFunc:    \"func\",\n\t\tVar:     \"var\",\n\t\tConst:   \"const\",\n\t\tField:   \"field\",\n\t\tMethod:  \"method\",\n\t}[kind]\n}\n\n// A Version represents a version of Go of the form \"go1.%d\".\ntype Version int8\n\n// String returns a version string of the form \"go1.23\", without allocating.\nfunc (v Version) String() string { return versions[v] }\n\nvar versions [30]string // (increase constant as needed)\n\nfunc init() {\n\tfor i := range versions {\n\t\tversions[i] = fmt.Sprintf(\"go1.%d\", i)\n\t}\n}\n\n// HasPackage reports whether the specified package path is part of\n// the standard library's public API.\nfunc HasPackage(path string) bool {\n\t_, ok := PackageSymbols[path]\n\treturn ok\n}\n\n// SplitField splits the field symbol name into type and field\n// components. It must be called only on Field symbols.\n//\n// Example: \"File.Package\" -> (\"File\", \"Package\")\nfunc (sym *Symbol) SplitField() (typename, name string) {\n\tif sym.Kind != Field {\n\t\tpanic(\"not a field\")\n\t}\n\ttypename, name, _ = strings.Cut(sym.Name, \".\")\n\treturn\n}\n\n// SplitMethod splits the method symbol name into pointer, receiver,\n// and method components. It must be called only on Method symbols.\n//\n// Example: \"(*Buffer).Grow\" -> (true, \"Buffer\", \"Grow\")\nfunc (sym *Symbol) SplitMethod() (ptr bool, recv, name string) {\n\tif sym.Kind != Method {\n\t\tpanic(\"not a method\")\n\t}\n\trecv, name, _ = strings.Cut(sym.Name, \".\")\n\trecv = recv[len(\"(\") : len(recv)-len(\")\")]\n\tptr = recv[0] == '*'\n\tif ptr {\n\t\trecv = recv[len(\"*\"):]\n\t}\n\treturn\n}\n"
  },
  {
    "path": "internal/stdlib/testdata/nethttp.deps",
    "content": "internal/goarch\nunsafe\ninternal/abi\ninternal/unsafeheader\ninternal/cpu\ninternal/bytealg\ninternal/byteorder\ninternal/chacha8rand\ninternal/coverage/rtcov\ninternal/godebugs\ninternal/goexperiment\ninternal/goos\ninternal/profilerecord\ninternal/runtime/atomic\ninternal/runtime/syscall/linux\nmath/bits\ninternal/strconv\ninternal/runtime/cgroup\ninternal/runtime/exithook\ninternal/runtime/gc\ninternal/runtime/sys\ninternal/runtime/gc/scan\ninternal/asan\ninternal/msan\ninternal/race\ninternal/runtime/math\ninternal/runtime/maps\ninternal/runtime/pprof/label\ninternal/stringslite\ninternal/trace/tracev2\nruntime\ninternal/reflectlite\nerrors\nsync/atomic\ninternal/sync\ninternal/synctest\nsync\nio\niter\nunicode\nunicode/utf8\nbytes\nstrings\nbufio\ncmp\nmath\nstrconv\nreflect\nslices\ninternal/fmtsort\ninternal/oserror\npath\ninternal/bisect\ninternal/godebug\nsyscall\ntime\nio/fs\ninternal/filepathlite\ninternal/syscall/unix\ninternal/poll\ninternal/syscall/execenv\ninternal/testlog\nos\nfmt\nsort\ncompress/flate\nencoding/binary\nhash\nhash/crc32\ncompress/gzip\ncontainer/list\ncontext\ncrypto\ncrypto/internal/fips140deps/godebug\ncrypto/internal/fips140\ncrypto/internal/fips140/alias\ncrypto/internal/fips140deps/byteorder\ncrypto/internal/fips140deps/cpu\ncrypto/internal/impl\ncrypto/internal/fips140/sha256\ncrypto/internal/constanttime\ncrypto/internal/fips140/subtle\ncrypto/internal/fips140/sha3\ncrypto/internal/fips140/sha512\ncrypto/internal/fips140/hmac\ncrypto/internal/fips140/check\ncrypto/internal/fips140/aes\ncrypto/internal/fips140deps/time\ncrypto/internal/entropy/v1.0.0\ncrypto/internal/sysrand\ncrypto/internal/fips140/drbg\ncrypto/internal/fips140/aes/gcm\ncrypto/fips140\ncrypto/internal/fips140only\ncrypto/subtle\ncrypto/cipher\ncrypto/internal/boring/sig\ncrypto/internal/boring\nmath/rand/v2\ncrypto/internal/randutil\ncrypto/internal/rand\nmath/rand\nmath/big\ncrypto/rand\ncrypto/aes\ncrypto/des\ncrypto/internal/fips140/nistec/fiat\ncrypto/internal/fips140/nistec\ncrypto/internal/fips140/ecdh\ncrypto/internal/fips140/edwards25519/field\ncrypto/ecdh\ncrypto/elliptic\ncrypto/internal/boring/bbig\ncrypto/internal/fips140/bigmod\ncrypto/internal/fips140/ecdsa\nweak\ncrypto/internal/fips140cache\ncrypto/sha3\ncrypto/internal/fips140hash\ncrypto/sha512\ninternal/saferio\nunicode/utf16\nencoding/asn1\nvendor/golang.org/x/crypto/cryptobyte/asn1\nvendor/golang.org/x/crypto/cryptobyte\ncrypto/ecdsa\ncrypto/internal/fips140/edwards25519\ncrypto/internal/fips140/ed25519\ncrypto/ed25519\ncrypto/internal/fips140/hkdf\ncrypto/hkdf\ncrypto/hmac\ncrypto/internal/fips140/mlkem\ncrypto/mlkem\ncrypto/sha256\nvendor/golang.org/x/crypto/internal/alias\nvendor/golang.org/x/crypto/chacha20\nvendor/golang.org/x/crypto/internal/poly1305\nvendor/golang.org/x/sys/cpu\nvendor/golang.org/x/crypto/chacha20poly1305\ncrypto/hpke\ncrypto/internal/fips140/tls12\ncrypto/internal/fips140/tls13\ncrypto/md5\ncrypto/rc4\ncrypto/internal/fips140/rsa\ncrypto/rsa\ncrypto/sha1\ncrypto/tls/internal/fips140tls\ncrypto/dsa\nencoding/hex\ncrypto/x509/pkix\nencoding/base64\nencoding/pem\nmaps\nvendor/golang.org/x/net/dns/dnsmessage\ninternal/nettrace\ninternal/singleflight\nunique\nnet/netip\nnet\nnet/url\npath/filepath\ncrypto/x509\ncrypto/tls\nvendor/golang.org/x/text/transform\nlog/internal\nlog\nvendor/golang.org/x/text/unicode/bidi\nvendor/golang.org/x/text/secure/bidirule\nvendor/golang.org/x/text/unicode/norm\nvendor/golang.org/x/net/idna\nnet/textproto\nvendor/golang.org/x/net/http/httpguts\nvendor/golang.org/x/net/http/httpproxy\nvendor/golang.org/x/net/http2/hpack\nmime\nmime/quotedprintable\nmime/multipart\nnet/http/httptrace\nnet/http/internal\nnet/http/internal/ascii\nnet/http/internal/httpcommon\nnet/http\n"
  },
  {
    "path": "internal/stdlib/testdata/nethttp.imports",
    "content": "bufio\nbytes\ncompress/flate\ncompress/gzip\ncontainer/list\ncontext\ncrypto/rand\ncrypto/tls\nencoding/base64\nencoding/binary\nerrors\nfmt\nvendor/golang.org/x/net/http/httpguts\nvendor/golang.org/x/net/http/httpproxy\nvendor/golang.org/x/net/http2/hpack\nvendor/golang.org/x/net/idna\ninternal/godebug\nio\nio/fs\nlog\nmaps\nmath\nmath/bits\nmath/rand\nmime\nmime/multipart\nnet\nnet/http/httptrace\nnet/http/internal\nnet/http/internal/ascii\nnet/http/internal/httpcommon\nnet/textproto\nnet/url\nos\npath\npath/filepath\nreflect\nruntime\nslices\nsort\nstrconv\nstrings\nsync\nsync/atomic\ntime\nunicode\nunicode/utf8\nunsafe\n"
  },
  {
    "path": "internal/testenv/exec.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testenv\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"os\"\n\t\"os/exec\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n)\n\n// HasExec reports whether the current system can start new processes\n// using os.StartProcess or (more commonly) exec.Command.\nfunc HasExec() bool {\n\tswitch runtime.GOOS {\n\tcase \"aix\",\n\t\t\"android\",\n\t\t\"darwin\",\n\t\t\"dragonfly\",\n\t\t\"freebsd\",\n\t\t\"illumos\",\n\t\t\"linux\",\n\t\t\"netbsd\",\n\t\t\"openbsd\",\n\t\t\"plan9\",\n\t\t\"solaris\",\n\t\t\"windows\":\n\t\t// Known OS that isn't ios or wasm; assume that exec works.\n\t\treturn true\n\n\tcase \"ios\", \"js\", \"wasip1\":\n\t\t// ios has an exec syscall but on real iOS devices it might return a\n\t\t// permission error. In an emulated environment (such as a Corellium host)\n\t\t// it might succeed, so try it and find out.\n\t\t//\n\t\t// As of 2023-04-19 wasip1 and js don't have exec syscalls at all, but we\n\t\t// may as well use the same path so that this branch can be tested without\n\t\t// an ios environment.\n\t\tfallthrough\n\n\tdefault:\n\t\ttryExecOnce.Do(func() {\n\t\t\texe, err := os.Executable()\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif flag.Lookup(\"test.list\") == nil {\n\t\t\t\t// We found the executable, but we don't know how to run it in a way\n\t\t\t\t// that should succeed without side-effects. Just forget it.\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// We know that a test executable exists and can run, because we're\n\t\t\t// running it now. Use it to check for overall exec support, but be sure\n\t\t\t// to remove any environment variables that might trigger non-default\n\t\t\t// behavior in a custom TestMain.\n\t\t\tcmd := exec.Command(exe, \"-test.list=^$\")\n\t\t\tcmd.Env = []string{}\n\t\t\tif err := cmd.Run(); err == nil {\n\t\t\t\ttryExecOk = true\n\t\t\t}\n\t\t})\n\t\treturn tryExecOk\n\t}\n}\n\nvar (\n\ttryExecOnce sync.Once\n\ttryExecOk   bool\n)\n\n// NeedsExec checks that the current system can start new processes\n// using os.StartProcess or (more commonly) exec.Command.\n// If not, NeedsExec calls t.Skip with an explanation.\nfunc NeedsExec(t testing.TB) {\n\tif !HasExec() {\n\t\tt.Skipf(\"skipping test: cannot exec subprocess on %s/%s\", runtime.GOOS, runtime.GOARCH)\n\t}\n}\n\n// CommandContext is like exec.CommandContext, but:\n//   - skips t if the platform does not support os/exec,\n//   - if supported, sends SIGQUIT instead of SIGKILL in its Cancel function\n//   - if the test has a deadline, adds a Context timeout and (if supported) WaitDelay\n//     for an arbitrary grace period before the test's deadline expires,\n//   - if Cmd has the Cancel field, fails the test if the command is canceled\n//     due to the test's deadline, and\n//   - sets a Cleanup function that verifies that the test did not leak a subprocess.\nfunc CommandContext(t testing.TB, ctx context.Context, name string, args ...string) *exec.Cmd {\n\tt.Helper()\n\tNeedsExec(t)\n\n\tvar (\n\t\tcancelCtx   context.CancelFunc\n\t\tgracePeriod time.Duration // unlimited unless the test has a deadline (to allow for interactive debugging)\n\t)\n\n\tif td, ok := Deadline(t); ok {\n\t\t// Start with a minimum grace period, just long enough to consume the\n\t\t// output of a reasonable program after it terminates.\n\t\tgracePeriod = 100 * time.Millisecond\n\t\tif s := os.Getenv(\"GO_TEST_TIMEOUT_SCALE\"); s != \"\" {\n\t\t\tscale, err := strconv.Atoi(s)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"invalid GO_TEST_TIMEOUT_SCALE: %v\", err)\n\t\t\t}\n\t\t\tgracePeriod *= time.Duration(scale)\n\t\t}\n\n\t\t// If time allows, increase the termination grace period to 5% of the\n\t\t// test's remaining time.\n\t\ttestTimeout := time.Until(td)\n\t\tif gp := testTimeout / 20; gp > gracePeriod {\n\t\t\tgracePeriod = gp\n\t\t}\n\n\t\t// When we run commands that execute subprocesses, we want to reserve two\n\t\t// grace periods to clean up: one for the delay between the first\n\t\t// termination signal being sent (via the Cancel callback when the Context\n\t\t// expires) and the process being forcibly terminated (via the WaitDelay\n\t\t// field), and a second one for the delay between the process being\n\t\t// terminated and the test logging its output for debugging.\n\t\t//\n\t\t// (We want to ensure that the test process itself has enough time to\n\t\t// log the output before it is also terminated.)\n\t\tcmdTimeout := testTimeout - 2*gracePeriod\n\n\t\tif cd, ok := ctx.Deadline(); !ok || time.Until(cd) > cmdTimeout {\n\t\t\t// Either ctx doesn't have a deadline, or its deadline would expire\n\t\t\t// after (or too close before) the test has already timed out.\n\t\t\t// Add a shorter timeout so that the test will produce useful output.\n\t\t\tctx, cancelCtx = context.WithTimeout(ctx, cmdTimeout)\n\t\t}\n\t}\n\n\tcmd := exec.CommandContext(ctx, name, args...)\n\n\t// Use reflection to set the Cancel and WaitDelay fields, if present.\n\t// TODO(bcmills): When we no longer support Go versions below 1.20,\n\t// remove the use of reflect and assume that the fields are always present.\n\trc := reflect.ValueOf(cmd).Elem()\n\n\tif rCancel := rc.FieldByName(\"Cancel\"); rCancel.IsValid() {\n\t\trCancel.Set(reflect.ValueOf(func() error {\n\t\t\tif cancelCtx != nil && ctx.Err() == context.DeadlineExceeded {\n\t\t\t\t// The command timed out due to running too close to the test's deadline\n\t\t\t\t// (because we specifically set a shorter Context deadline for that\n\t\t\t\t// above). There is no way the test did that intentionally — it's too\n\t\t\t\t// close to the wire! — so mark it as a test failure. That way, if the\n\t\t\t\t// test expects the command to fail for some other reason, it doesn't\n\t\t\t\t// have to distinguish between that reason and a timeout.\n\t\t\t\tt.Errorf(\"test timed out while running command: %v\", cmd)\n\t\t\t} else {\n\t\t\t\t// The command is being terminated due to ctx being canceled, but\n\t\t\t\t// apparently not due to an explicit test deadline that we added.\n\t\t\t\t// Log that information in case it is useful for diagnosing a failure,\n\t\t\t\t// but don't actually fail the test because of it.\n\t\t\t\tt.Logf(\"%v: terminating command: %v\", ctx.Err(), cmd)\n\t\t\t}\n\t\t\treturn cmd.Process.Signal(Sigquit)\n\t\t}))\n\t}\n\n\tif rWaitDelay := rc.FieldByName(\"WaitDelay\"); rWaitDelay.IsValid() {\n\t\trWaitDelay.Set(reflect.ValueOf(gracePeriod))\n\t}\n\n\tt.Cleanup(func() {\n\t\tif cancelCtx != nil {\n\t\t\tcancelCtx()\n\t\t}\n\t\tif cmd.Process != nil && cmd.ProcessState == nil {\n\t\t\tt.Errorf(\"command was started, but test did not wait for it to complete: %v\", cmd)\n\t\t}\n\t})\n\n\treturn cmd\n}\n\n// Command is like exec.Command, but applies the same changes as\n// testenv.CommandContext (with a default Context).\nfunc Command(t testing.TB, name string, args ...string) *exec.Cmd {\n\tt.Helper()\n\treturn CommandContext(t, context.Background(), name, args...)\n}\n"
  },
  {
    "path": "internal/testenv/testenv.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package testenv contains helper functions for skipping tests\n// based on which tools are present in the environment.\npackage testenv\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"golang.org/x/tools/internal/gocommand\"\n)\n\n// packageMainIsDevel reports whether the module containing package main\n// is a development version (if module information is available).\nfunc packageMainIsDevel() bool {\n\tinfo, ok := debug.ReadBuildInfo()\n\tif !ok {\n\t\t// Most test binaries currently lack build info, but this should become more\n\t\t// permissive once https://golang.org/issue/33976 is fixed.\n\t\treturn true\n\t}\n\n\t// Note: info.Main.Version describes the version of the module containing\n\t// package main, not the version of “the main module”.\n\t// See https://golang.org/issue/33975.\n\treturn info.Main.Version == \"(devel)\"\n}\n\nvar checkGoBuild struct {\n\tonce sync.Once\n\terr  error\n}\n\n// HasTool reports an error if the required tool is not available in PATH.\n//\n// For certain tools, it checks that the tool executable is correct.\nfunc HasTool(tool string) error {\n\tif tool == \"cgo\" {\n\t\tenabled, err := cgoEnabled(false)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"checking cgo: %v\", err)\n\t\t}\n\t\tif !enabled {\n\t\t\treturn fmt.Errorf(\"cgo not enabled\")\n\t\t}\n\t\treturn nil\n\t}\n\n\t_, err := exec.LookPath(tool)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tswitch tool {\n\tcase \"patch\":\n\t\t// check that the patch tools supports the -o argument\n\t\ttemp, err := os.CreateTemp(\"\", \"patch-test\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttemp.Close()\n\t\tdefer os.Remove(temp.Name())\n\t\tcmd := exec.Command(tool, \"-o\", temp.Name())\n\t\tif err := cmd.Run(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\tcase \"go\":\n\t\tcheckGoBuild.once.Do(func() {\n\t\t\tif runtime.GOROOT() != \"\" {\n\t\t\t\t// Ensure that the 'go' command found by exec.LookPath is from the correct\n\t\t\t\t// GOROOT. Otherwise, 'some/path/go test ./...' will test against some\n\t\t\t\t// version of the 'go' binary other than 'some/path/go', which is almost\n\t\t\t\t// certainly not what the user intended.\n\t\t\t\tout, err := exec.Command(tool, \"env\", \"GOROOT\").Output()\n\t\t\t\tif err != nil {\n\t\t\t\t\tif exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {\n\t\t\t\t\t\terr = fmt.Errorf(\"%w\\nstderr:\\n%s)\", err, exit.Stderr)\n\t\t\t\t\t}\n\t\t\t\t\tcheckGoBuild.err = err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tGOROOT := strings.TrimSpace(string(out))\n\t\t\t\tif GOROOT != runtime.GOROOT() {\n\t\t\t\t\tcheckGoBuild.err = fmt.Errorf(\"'go env GOROOT' does not match runtime.GOROOT:\\n\\tgo env: %s\\n\\tGOROOT: %s\", GOROOT, runtime.GOROOT())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdir, err := os.MkdirTemp(\"\", \"testenv-*\")\n\t\t\tif err != nil {\n\t\t\t\tcheckGoBuild.err = err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdefer os.RemoveAll(dir)\n\n\t\t\tmainGo := filepath.Join(dir, \"main.go\")\n\t\t\tif err := os.WriteFile(mainGo, []byte(\"package main\\nfunc main() {}\\n\"), 0644); err != nil {\n\t\t\t\tcheckGoBuild.err = err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcmd := exec.Command(\"go\", \"build\", \"-o\", os.DevNull, mainGo)\n\t\t\tcmd.Dir = dir\n\t\t\tif out, err := cmd.CombinedOutput(); err != nil {\n\t\t\t\tif len(out) > 0 {\n\t\t\t\t\tcheckGoBuild.err = fmt.Errorf(\"%v: %v\\n%s\", cmd, err, out)\n\t\t\t\t} else {\n\t\t\t\t\tcheckGoBuild.err = fmt.Errorf(\"%v: %v\", cmd, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\tif checkGoBuild.err != nil {\n\t\t\treturn checkGoBuild.err\n\t\t}\n\n\tcase \"diff\":\n\t\t// Check that diff is the GNU or Apple version, needed for the -u argument and\n\t\t// to report missing newlines at the end of files.\n\t\tout, err := exec.Command(tool, \"-version\").Output()\n\t\tif err != nil {\n\t\t\tout, _ = exec.Command(tool, \"--version\").Output()\n\t\t\tif bytes.Contains(out, []byte(\"Apple diff\")) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\tif !bytes.Contains(out, []byte(\"GNU diffutils\")) {\n\t\t\treturn fmt.Errorf(\"diff is not the GNU version\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc cgoEnabled(bypassEnvironment bool) (bool, error) {\n\tcmd := exec.Command(\"go\", \"env\", \"CGO_ENABLED\")\n\tif bypassEnvironment {\n\t\tcmd.Env = append(os.Environ(), \"CGO_ENABLED=\")\n\t}\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\tif exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {\n\t\t\terr = fmt.Errorf(\"%w\\nstderr:\\n%s\", err, exit.Stderr)\n\t\t}\n\t\treturn false, err\n\t}\n\tenabled := strings.TrimSpace(string(out))\n\treturn enabled == \"1\", nil\n}\n\nfunc allowMissingTool(tool string) bool {\n\tswitch runtime.GOOS {\n\tcase \"aix\", \"darwin\", \"dragonfly\", \"freebsd\", \"illumos\", \"linux\", \"netbsd\", \"openbsd\", \"plan9\", \"solaris\", \"windows\":\n\t\t// Known non-mobile OS. Expect a reasonably complete environment.\n\tdefault:\n\t\treturn true\n\t}\n\n\tswitch tool {\n\tcase \"cgo\":\n\t\tif strings.HasSuffix(os.Getenv(\"GO_BUILDER_NAME\"), \"-nocgo\") {\n\t\t\t// Explicitly disabled on -nocgo builders.\n\t\t\treturn true\n\t\t}\n\t\tif enabled, err := cgoEnabled(true); err == nil && !enabled {\n\t\t\t// No platform support.\n\t\t\treturn true\n\t\t}\n\tcase \"go\":\n\t\tif os.Getenv(\"GO_BUILDER_NAME\") == \"illumos-amd64-joyent\" {\n\t\t\t// Work around a misconfigured builder (see https://golang.org/issue/33950).\n\t\t\treturn true\n\t\t}\n\tcase \"diff\":\n\t\tif os.Getenv(\"GO_BUILDER_NAME\") != \"\" {\n\t\t\treturn true\n\t\t}\n\tcase \"patch\":\n\t\tif os.Getenv(\"GO_BUILDER_NAME\") != \"\" {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// If a developer is actively working on this test, we expect them to have all\n\t// of its dependencies installed. However, if it's just a dependency of some\n\t// other module (for example, being run via 'go test all'), we should be more\n\t// tolerant of unusual environments.\n\treturn !packageMainIsDevel()\n}\n\n// NeedsTool skips t if the named tool is not present in the path.\n// As a special case, \"cgo\" means \"go\" is present and can compile cgo programs.\nfunc NeedsTool(t testing.TB, tool string) {\n\terr := HasTool(tool)\n\tif err == nil {\n\t\treturn\n\t}\n\n\tt.Helper()\n\tif allowMissingTool(tool) {\n\t\t// TODO(adonovan): if we skip because of (e.g.)\n\t\t// mismatched go env GOROOT and runtime.GOROOT, don't\n\t\t// we risk some users not getting the coverage they expect?\n\t\t// bcmills notes: this shouldn't be a concern as of CL 404134 (Go 1.19).\n\t\t// We could probably safely get rid of that GOPATH consistency\n\t\t// check entirely at this point.\n\t\tt.Skipf(\"skipping because %s tool not available: %v\", tool, err)\n\t} else {\n\t\tt.Fatalf(\"%s tool not available: %v\", tool, err)\n\t}\n}\n\n// NeedsGoPackages skips t if the go/packages driver (or 'go' tool) implied by\n// the current process environment is not present in the path.\nfunc NeedsGoPackages(t testing.TB) {\n\tt.Helper()\n\n\ttool := os.Getenv(\"GOPACKAGESDRIVER\")\n\tswitch tool {\n\tcase \"off\":\n\t\t// \"off\" forces go/packages to use the go command.\n\t\ttool = \"go\"\n\tcase \"\":\n\t\tif _, err := exec.LookPath(\"gopackagesdriver\"); err == nil {\n\t\t\ttool = \"gopackagesdriver\"\n\t\t} else {\n\t\t\ttool = \"go\"\n\t\t}\n\t}\n\n\tNeedsTool(t, tool)\n}\n\n// NeedsGoPackagesEnv skips t if the go/packages driver (or 'go' tool) implied\n// by env is not present in the path.\nfunc NeedsGoPackagesEnv(t testing.TB, env []string) {\n\tt.Helper()\n\n\tfor _, v := range env {\n\t\tif after, ok := strings.CutPrefix(v, \"GOPACKAGESDRIVER=\"); ok {\n\t\t\ttool := after\n\t\t\tif tool == \"off\" {\n\t\t\t\tNeedsTool(t, \"go\")\n\t\t\t} else {\n\t\t\t\tNeedsTool(t, tool)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tNeedsGoPackages(t)\n}\n\n// NeedsGoBuild skips t if the current system can't build programs with “go build”\n// and then run them with os.StartProcess or exec.Command.\n// Android doesn't have the userspace go build needs to run,\n// and js/wasm doesn't support running subprocesses.\nfunc NeedsGoBuild(t testing.TB) {\n\tt.Helper()\n\n\t// This logic was derived from internal/testing.HasGoBuild and\n\t// may need to be updated as that function evolves.\n\n\tNeedsTool(t, \"go\")\n}\n\n// NeedsDefaultImporter skips t if the test uses the default importer,\n// returned by [go/importer.Default].\nfunc NeedsDefaultImporter(t testing.TB) {\n\tt.Helper()\n\t// The default importer may call `go list`\n\t// (in src/internal/exportdata/exportdata.go:lookupGorootExport),\n\t// so check for the go tool.\n\tNeedsTool(t, \"go\")\n}\n\n// ExitIfSmallMachine emits a helpful diagnostic and calls os.Exit(0) if the\n// current machine is a builder known to have scarce resources.\n//\n// It should be called from within a TestMain function.\nfunc ExitIfSmallMachine() {\n\tswitch b := os.Getenv(\"GO_BUILDER_NAME\"); b {\n\tcase \"linux-arm-scaleway\":\n\t\t// \"linux-arm\" was renamed to \"linux-arm-scaleway\" in CL 303230.\n\t\tfmt.Fprintln(os.Stderr, \"skipping test: linux-arm-scaleway builder lacks sufficient memory (https://golang.org/issue/32834)\")\n\tcase \"plan9-arm\":\n\t\tfmt.Fprintln(os.Stderr, \"skipping test: plan9-arm builder lacks sufficient memory (https://golang.org/issue/38772)\")\n\tcase \"netbsd-arm-bsiegert\", \"netbsd-arm64-bsiegert\":\n\t\t// As of 2021-06-02, these builders are running with GO_TEST_TIMEOUT_SCALE=10,\n\t\t// and there is only one of each. We shouldn't waste those scarce resources\n\t\t// running very slow tests.\n\t\tfmt.Fprintf(os.Stderr, \"skipping test: %s builder is very slow\\n\", b)\n\tcase \"dragonfly-amd64\":\n\t\t// As of 2021-11-02, this builder is running with GO_TEST_TIMEOUT_SCALE=2,\n\t\t// and seems to have unusually slow disk performance.\n\t\tfmt.Fprintln(os.Stderr, \"skipping test: dragonfly-amd64 has slow disk (https://golang.org/issue/45216)\")\n\tcase \"linux-riscv64-unmatched\":\n\t\t// As of 2021-11-03, this builder is empirically not fast enough to run\n\t\t// gopls tests. Ideally we should make the tests faster in short mode\n\t\t// and/or fix them to not assume arbitrary deadlines.\n\t\t// For now, we'll skip them instead.\n\t\tfmt.Fprintf(os.Stderr, \"skipping test: %s builder is too slow (https://golang.org/issue/49321)\\n\", b)\n\tdefault:\n\t\tswitch runtime.GOOS {\n\t\tcase \"android\", \"ios\":\n\t\t\tfmt.Fprintf(os.Stderr, \"skipping test: assuming that %s is resource-constrained\\n\", runtime.GOOS)\n\t\tdefault:\n\t\t\treturn\n\t\t}\n\t}\n\tos.Exit(0)\n}\n\n// Go1Point returns the x in Go 1.x.\nfunc Go1Point() int {\n\tfor i := len(build.Default.ReleaseTags) - 1; i >= 0; i-- {\n\t\tvar version int\n\t\tif _, err := fmt.Sscanf(build.Default.ReleaseTags[i], \"go1.%d\", &version); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treturn version\n\t}\n\tpanic(\"bad release tags\")\n}\n\n// NeedsGoCommand1Point skips t if the ambient go command version in the PATH\n// of the current process is older than 1.x.\n//\n// NeedsGoCommand1Point memoizes the result of running the go command, so\n// should be called after all mutations of PATH.\nfunc NeedsGoCommand1Point(t testing.TB, x int) {\n\tNeedsTool(t, \"go\")\n\tgo1point, err := goCommand1Point()\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"unable to determine go version: %v\", err))\n\t}\n\tif go1point < x {\n\t\tt.Helper()\n\t\tt.Skipf(\"go command is version 1.%d, older than required 1.%d\", go1point, x)\n\t}\n}\n\nvar (\n\tgoCommand1PointOnce sync.Once\n\tgoCommand1Point_    int\n\tgoCommand1PointErr  error\n)\n\nfunc goCommand1Point() (int, error) {\n\tgoCommand1PointOnce.Do(func() {\n\t\tgoCommand1Point_, goCommand1PointErr = gocommand.GoVersion(context.Background(), gocommand.Invocation{}, new(gocommand.Runner))\n\t})\n\treturn goCommand1Point_, goCommand1PointErr\n}\n\n// NeedsGo1Point skips t if the Go version used to run the test is older than\n// 1.x.\nfunc NeedsGo1Point(t testing.TB, x int) {\n\tif Go1Point() < x {\n\t\tt.Helper()\n\t\tt.Skipf(\"running Go version %q is version 1.%d, older than required 1.%d\", runtime.Version(), Go1Point(), x)\n\t}\n}\n\n// SkipAfterGoCommand1Point skips t if the ambient go command version in the PATH of\n// the current process is newer than 1.x.\n//\n// SkipAfterGoCommand1Point memoizes the result of running the go command, so\n// should be called after any mutation of PATH.\nfunc SkipAfterGoCommand1Point(t testing.TB, x int) {\n\tNeedsTool(t, \"go\")\n\tgo1point, err := goCommand1Point()\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"unable to determine go version: %v\", err))\n\t}\n\tif go1point > x {\n\t\tt.Helper()\n\t\tt.Skipf(\"go command is version 1.%d, newer than maximum 1.%d\", go1point, x)\n\t}\n}\n\n// SkipAfterGo1Point skips t if the Go version used to run the test is newer than\n// 1.x.\nfunc SkipAfterGo1Point(t testing.TB, x int) {\n\tif Go1Point() > x {\n\t\tt.Helper()\n\t\tt.Skipf(\"running Go version %q is version 1.%d, newer than maximum 1.%d\", runtime.Version(), Go1Point(), x)\n\t}\n}\n\n// NeedsLocalhostNet skips t if networking does not work for ports opened\n// with \"localhost\".\nfunc NeedsLocalhostNet(t testing.TB) {\n\tswitch runtime.GOOS {\n\tcase \"js\", \"wasip1\":\n\t\tt.Skipf(`Listening on \"localhost\" fails on %s; see https://go.dev/issue/59718`, runtime.GOOS)\n\t}\n}\n\n// Deadline returns the deadline of t, if known,\n// using the Deadline method added in Go 1.15.\nfunc Deadline(t testing.TB) (time.Time, bool) {\n\ttd, ok := t.(interface {\n\t\tDeadline() (time.Time, bool)\n\t})\n\tif !ok {\n\t\treturn time.Time{}, false\n\t}\n\treturn td.Deadline()\n}\n\nvar (\n\tgorootOnce sync.Once\n\tgorootPath string\n\tgorootErr  error\n)\n\nfunc findGOROOT() (string, error) {\n\tgorootOnce.Do(func() {\n\t\tgorootPath = runtime.GOROOT()\n\t\tif gorootPath != \"\" {\n\t\t\t// If runtime.GOROOT() is non-empty, assume that it is valid. (It might\n\t\t\t// not be: for example, the user may have explicitly set GOROOT\n\t\t\t// to the wrong directory.)\n\t\t\treturn\n\t\t}\n\n\t\tcmd := exec.Command(\"go\", \"env\", \"GOROOT\")\n\t\tout, err := cmd.Output()\n\t\tif err != nil {\n\t\t\tgorootErr = fmt.Errorf(\"%v: %v\", cmd, err)\n\t\t}\n\t\tgorootPath = strings.TrimSpace(string(out))\n\t})\n\n\treturn gorootPath, gorootErr\n}\n\n// GOROOT reports the path to the directory containing the root of the Go\n// project source tree. This is normally equivalent to runtime.GOROOT, but\n// works even if the test binary was built with -trimpath.\n//\n// If GOROOT cannot be found, GOROOT skips t if t is non-nil,\n// or panics otherwise.\nfunc GOROOT(t testing.TB) string {\n\tpath, err := findGOROOT()\n\tif err != nil {\n\t\tif t == nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tt.Helper()\n\t\tt.Skip(err)\n\t}\n\treturn path\n}\n\n// NeedsLocalXTools skips t if the golang.org/x/tools module is replaced and\n// its replacement directory does not exist (or does not contain the module).\nfunc NeedsLocalXTools(t testing.TB) {\n\tt.Helper()\n\n\tNeedsTool(t, \"go\")\n\n\tcmd := Command(t, \"go\", \"list\", \"-f\", \"{{with .Replace}}{{.Dir}}{{end}}\", \"-m\", \"golang.org/x/tools\")\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\tif ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {\n\t\t\tt.Skipf(\"skipping test: %v: %v\\n%s\", cmd, err, ee.Stderr)\n\t\t}\n\t\tt.Skipf(\"skipping test: %v: %v\", cmd, err)\n\t}\n\n\tdir := string(bytes.TrimSpace(out))\n\tif dir == \"\" {\n\t\t// No replacement directory, and (since we didn't set -e) no error either.\n\t\t// Maybe x/tools isn't replaced at all (as in a gopls release, or when\n\t\t// using a go.work file that includes the x/tools module).\n\t\treturn\n\t}\n\n\t// We found the directory where x/tools would exist if we're in a clone of the\n\t// repo. Is it there? (If not, we're probably in the module cache instead.)\n\tmodFilePath := filepath.Join(dir, \"go.mod\")\n\tb, err := os.ReadFile(modFilePath)\n\tif err != nil {\n\t\tt.Skipf(\"skipping test: x/tools replacement not found: %v\", err)\n\t}\n\tmodulePath := modfile.ModulePath(b)\n\n\tif want := \"golang.org/x/tools\"; modulePath != want {\n\t\tt.Skipf(\"skipping test: %s module path is %q, not %q\", modFilePath, modulePath, want)\n\t}\n}\n\n// NeedsGoExperiment skips t if the current process environment does not\n// have a GOEXPERIMENT flag set.\nfunc NeedsGoExperiment(t testing.TB, flag string) {\n\tt.Helper()\n\n\tgoexp := os.Getenv(\"GOEXPERIMENT\")\n\tset := false\n\tfor f := range strings.SplitSeq(goexp, \",\") {\n\t\tif f == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif f == \"none\" {\n\t\t\t// GOEXPERIMENT=none disables all experiment flags.\n\t\t\tset = false\n\t\t\tbreak\n\t\t}\n\t\tval := true\n\t\tif strings.HasPrefix(f, \"no\") {\n\t\t\tf, val = f[2:], false\n\t\t}\n\t\tif f == flag {\n\t\t\tset = val\n\t\t}\n\t}\n\tif !set {\n\t\tt.Skipf(\"skipping test: flag %q is not set in GOEXPERIMENT=%q\", flag, goexp)\n\t}\n}\n\n// NeedsGOROOTDir skips the test if GOROOT/dir does not exist, and GOROOT is a\n// released version of Go (=has a VERSION file). Some GOROOT directories are\n// removed by cmd/distpack.\n//\n// See also golang/go#70081.\nfunc NeedsGOROOTDir(t *testing.T, dir string) {\n\tgorootTest := filepath.Join(GOROOT(t), dir)\n\tif _, err := os.Stat(gorootTest); os.IsNotExist(err) {\n\t\tif _, err := os.Stat(filepath.Join(GOROOT(t), \"VERSION\")); err == nil {\n\t\t\tt.Skipf(\"skipping: GOROOT/%s not present\", dir)\n\t\t}\n\t}\n}\n\n// RedirectStderr causes os.Stderr (and the global logger) to be\n// temporarily replaced so that writes to it are sent to t.Log.\n// It is restored at test cleanup.\nfunc RedirectStderr(t testing.TB) {\n\tt.Setenv(\"RedirectStderr\", \"\") // side effect: assert t.Parallel wasn't called\n\n\t// TODO(adonovan): if https://go.dev/issue/59928 is accepted,\n\t// simply set w = t.Output() and dispense with the pipe.\n\tr, w, err := os.Pipe()\n\tif err != nil {\n\t\tt.Fatalf(\"pipe: %v\", err)\n\t}\n\tdone := make(chan struct{})\n\tgo func() {\n\t\tfor sc := bufio.NewScanner(r); sc.Scan(); {\n\t\t\tt.Log(sc.Text())\n\t\t}\n\t\tr.Close()\n\t\tclose(done)\n\t}()\n\n\t// Also do the same for the global logger.\n\tsavedWriter, savedPrefix, savedFlags := log.Writer(), log.Prefix(), log.Flags()\n\tlog.SetPrefix(\"log: \")\n\tlog.SetOutput(w)\n\tlog.SetFlags(0)\n\n\toldStderr := os.Stderr\n\tos.Stderr = w\n\tt.Cleanup(func() {\n\t\tw.Close() // ignore error\n\t\tos.Stderr = oldStderr\n\n\t\tlog.SetOutput(savedWriter)\n\t\tlog.SetPrefix(savedPrefix)\n\t\tlog.SetFlags(savedFlags)\n\n\t\t// Don't let test finish before final t.Log.\n\t\t<-done\n\t})\n}\n"
  },
  {
    "path": "internal/testenv/testenv_notunix.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !(unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris)\n\npackage testenv\n\nimport \"os\"\n\n// Sigquit is the signal to send to kill a hanging subprocess.\n// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill.\nvar Sigquit = os.Kill\n"
  },
  {
    "path": "internal/testenv/testenv_unix.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris\n\npackage testenv\n\nimport \"syscall\"\n\n// Sigquit is the signal to send to kill a hanging subprocess.\n// Send SIGQUIT to get a stack trace.\nvar Sigquit = syscall.SIGQUIT\n"
  },
  {
    "path": "internal/testfiles/testdata/somefile.txt",
    "content": "A file to try to load."
  },
  {
    "path": "internal/testfiles/testdata/versions/go.mod.test",
    "content": "// File is versions/go.mod after expansion with TestDir()\n\nmodule golang.org/fake/versions\n\ngo 1.22\n"
  },
  {
    "path": "internal/testfiles/testdata/versions/mod.go",
    "content": "// The file will be go1.22 from the go.mod.\n\npackage versions // want \"mod.go@go1.22\"\n"
  },
  {
    "path": "internal/testfiles/testdata/versions/post.go",
    "content": "//go:build go1.23\n\npackage versions // want \"post.go@go1.23\"\n"
  },
  {
    "path": "internal/testfiles/testdata/versions/pre.go",
    "content": "//go:build go1.21\n\npackage versions // want \"pre.go@go1.21\"\n"
  },
  {
    "path": "internal/testfiles/testdata/versions/sub.test/sub.go.test",
    "content": "package sub // want \"sub.go@go1.22\"\n"
  },
  {
    "path": "internal/testfiles/testfiles.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package testfiles provides utilities for writing Go tests with files\n// in testdata.\npackage testfiles\n\nimport (\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// CopyToTmp copies the files and directories in src to a new temporary testing\n// directory dst, and returns dst on success.\n//\n// After copying the files, it processes each of the 'old,new,' rename\n// directives in order. Each rename directive moves the relative path \"old\"\n// to the relative path \"new\" within the directory.\n//\n// Renaming allows tests to hide files whose names have\n// special meaning, such as \"go.mod\" files or \"testdata\" directories\n// from the go command, or ill-formed Go source files from gofmt.\n//\n// For example if we copy the directory testdata:\n//\n//\ttestdata/\n//\t    go.mod.test\n//\t    a/a.go\n//\t    b/b.go\n//\n// with the rename \"go.mod.test,go.mod\", the resulting files will be:\n//\n//\tdst/\n//\t    go.mod\n//\t    a/a.go\n//\t    b/b.go\nfunc CopyToTmp(t testing.TB, src fs.FS, rename ...string) string {\n\tdstdir := t.TempDir()\n\n\tif err := os.CopyFS(dstdir, src); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, r := range rename {\n\t\told, new, found := strings.Cut(r, \",\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"rename directive %q does not contain delimiter %q\", r, \",\")\n\t\t}\n\t\toldpath := filepath.Join(dstdir, old)\n\t\tnewpath := filepath.Join(dstdir, new)\n\t\tif err := os.Rename(oldpath, newpath); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\treturn dstdir\n}\n\n// ExtractTxtarFileToTmp read a txtar archive on a given path,\n// extracts it to a temporary directory, and returns the\n// temporary directory.\nfunc ExtractTxtarFileToTmp(t testing.TB, file string) string {\n\tar, err := txtar.ParseFile(file)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfs, err := txtar.FS(ar)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn CopyToTmp(t, fs)\n}\n\n// LoadPackages loads typed syntax for all packages that match the\n// patterns, interpreted relative to the archive root.\n//\n// The packages must be error-free.\nfunc LoadPackages(t testing.TB, ar *txtar.Archive, patterns ...string) []*packages.Package {\n\ttestenv.NeedsGoPackages(t)\n\n\tfs, err := txtar.FS(ar)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdir := CopyToTmp(t, fs)\n\n\tcfg := &packages.Config{\n\t\tMode: packages.NeedSyntax |\n\t\t\tpackages.NeedTypesInfo |\n\t\t\tpackages.NeedDeps |\n\t\t\tpackages.NeedName |\n\t\t\tpackages.NeedFiles |\n\t\t\tpackages.NeedImports |\n\t\t\tpackages.NeedCompiledGoFiles |\n\t\t\tpackages.NeedTypes,\n\t\tDir: dir,\n\t\tEnv: append(os.Environ(),\n\t\t\t\"GO111MODULES=on\",\n\t\t\t\"GOPATH=\",\n\t\t\t\"GOWORK=off\",\n\t\t\t\"GOPROXY=off\"),\n\t}\n\tpkgs, err := packages.Load(cfg, patterns...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif num := packages.PrintErrors(pkgs); num > 0 {\n\t\tt.Fatalf(\"packages contained %d errors\", num)\n\t}\n\treturn pkgs\n}\n"
  },
  {
    "path": "internal/testfiles/testfiles_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testfiles_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/analysistest\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/internal/versions\"\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestTestDir(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23)\n\n\t// Files are initially {go.mod.test,sub.test/sub.go.test}.\n\tfs := os.DirFS(filepath.Join(analysistest.TestData(), \"versions\"))\n\ttmpdir := testfiles.CopyToTmp(t, fs,\n\t\t\"go.mod.test,go.mod\",                // After: {go.mod,sub.test/sub.go.test}\n\t\t\"sub.test/sub.go.test,sub.test/abc\", // After: {go.mod,sub.test/abc}\n\t\t\"sub.test,sub\",                      // After: {go.mod,sub/abc}\n\t\t\"sub/abc,sub/sub.go\",                // After: {go.mod,sub/sub.go}\n\t)\n\n\tfilever := &analysis.Analyzer{\n\t\tName: \"filever\",\n\t\tDoc:  \"reports file go versions\",\n\t\tRun: func(pass *analysis.Pass) (any, error) {\n\t\t\tfor _, file := range pass.Files {\n\t\t\t\tver := versions.FileVersion(pass.TypesInfo, file)\n\t\t\t\tname := filepath.Base(pass.Fset.Position(file.Package).Filename)\n\t\t\t\tpass.Reportf(file.Package, \"%s@%s\", name, ver)\n\t\t\t}\n\t\t\treturn nil, nil\n\t\t},\n\t}\n\tres := analysistest.Run(t, tmpdir, filever, \"golang.org/fake/versions\", \"golang.org/fake/versions/sub\")\n\tgot := 0\n\tfor _, r := range res {\n\t\tgot += len(r.Diagnostics)\n\t}\n\n\tif want := 4; got != want {\n\t\tt.Errorf(\"Got %d diagnostics. wanted %d\", got, want)\n\t}\n}\n\nfunc TestTestDirErrors(t *testing.T) {\n\tconst input = `\n-- one.txt --\none\n`\n\t// Files are initially {go.mod.test,sub.test/sub.go.test}.\n\tfs, err := txtar.FS(txtar.Parse([]byte(input)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdirective := \"no comma to split on\"\n\tintercept := &fatalIntercept{t, nil}\n\tfunc() {\n\t\tdefer func() { // swallow panics from fatalIntercept.Fatal\n\t\t\tif r := recover(); r != intercept {\n\t\t\t\tpanic(r)\n\t\t\t}\n\t\t}()\n\t\ttestfiles.CopyToTmp(intercept, fs, directive)\n\t}()\n\n\tgot := fmt.Sprint(intercept.fatalfs)\n\twant := `[rename directive \"no comma to split on\" does not contain delimiter \",\"]`\n\tif got != want {\n\t\tt.Errorf(\"CopyToTmp(%q) had the Fatal messages %q. wanted %q\", directive, got, want)\n\t}\n}\n\n// helper for TestTestDirErrors\ntype fatalIntercept struct {\n\ttesting.TB\n\tfatalfs []string\n}\n\nfunc (i *fatalIntercept) Fatalf(format string, args ...any) {\n\ti.fatalfs = append(i.fatalfs, fmt.Sprintf(format, args...))\n\t// Do not mark the test as failing, but fail early.\n\tpanic(i)\n}\n"
  },
  {
    "path": "internal/tool/tool.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package tool is a harness for writing Go tools.\npackage tool\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"runtime/trace\"\n\t\"strings\"\n\t\"time\"\n)\n\n// This file is a harness for writing your main function.\n// The original version of the file is in golang.org/x/tools/internal/tool.\n//\n// It adds a method to the Application type\n//     Main(name, usage string, args []string)\n// which should normally be invoked from a true main as follows:\n//     func main() {\n//       (&Application{}).Main(\"myapp\", \"non-flag-command-line-arg-help\", os.Args[1:])\n//     }\n// It recursively scans the application object for fields with a tag containing\n//     `flag:\"flagnames\" help:\"short help text\"`\n// uses all those fields to build command line flags. It will split flagnames on\n// commas and add a flag per name.\n// It expects the Application type to have a method\n//     Run(context.Context, args...string) error\n// which it invokes only after all command line flag processing has been finished.\n// If Run returns an error, the error will be printed to stderr and the\n// application will quit with a non zero exit status.\n\n// Profile can be embedded in your application struct to automatically\n// add command line arguments and handling for the common profiling methods.\ntype Profile struct {\n\tCPU    string `flag:\"profile.cpu\" help:\"write CPU profile to this file\"`\n\tMemory string `flag:\"profile.mem\" help:\"write memory profile to this file\"`\n\tAlloc  string `flag:\"profile.alloc\" help:\"write alloc profile to this file\"`\n\tTrace  string `flag:\"profile.trace\" help:\"write trace log to this file\"`\n\tBlock  string `flag:\"profile.block\" help:\"write block profile to this file\"`\n}\n\n// Application is the interface that must be satisfied by an object passed to Main.\ntype Application interface {\n\t// Name returns the application's name. It is used in help and error messages.\n\tName() string\n\t// Most of the help usage is automatically generated, this string should only\n\t// describe the contents of non flag arguments.\n\tUsage() string\n\t// ShortHelp returns the one line overview of the command.\n\tShortHelp() string\n\t// DetailedHelp should print a detailed help message. It will only ever be shown\n\t// when the ShortHelp is also printed, so there is no need to duplicate\n\t// anything from there.\n\t// It is passed the flag set so it can print the default values of the flags.\n\t// It should use the flag sets configured Output to write the help to.\n\tDetailedHelp(*flag.FlagSet)\n\t// Run is invoked after all flag processing, and inside the profiling and\n\t// error handling harness.\n\tRun(ctx context.Context, args ...string) error\n}\n\ntype SubCommand interface {\n\tParent() string\n}\n\n// This is the type returned by CommandLineErrorf, which causes the outer main\n// to trigger printing of the command line help.\ntype commandLineError string\n\nfunc (e commandLineError) Error() string { return string(e) }\n\n// CommandLineErrorf is like fmt.Errorf except that it returns a value that\n// triggers printing of the command line help.\n// In general you should use this when generating command line validation errors.\nfunc CommandLineErrorf(message string, args ...any) error {\n\treturn commandLineError(fmt.Sprintf(message, args...))\n}\n\n// Main should be invoked directly by main function.\n// It will only return if there was no error.  If an error\n// was encountered it is printed to standard error and the\n// application exits with an exit code of 2.\nfunc Main(ctx context.Context, app Application, args []string) {\n\ts := flag.NewFlagSet(app.Name(), flag.ExitOnError)\n\tif err := Run(ctx, s, app, args); err != nil {\n\t\tfmt.Fprintf(s.Output(), \"%s: %v\\n\", app.Name(), err)\n\t\tif _, printHelp := err.(commandLineError); printHelp {\n\t\t\t// TODO(adonovan): refine this. It causes\n\t\t\t// any command-line error to result in the full\n\t\t\t// usage message, which typically obscures\n\t\t\t// the actual error.\n\t\t\ts.Usage()\n\t\t}\n\t\tos.Exit(2)\n\t}\n}\n\n// Run is the inner loop for Main; invoked by Main, recursively by\n// Run, and by various tests.  It runs the application and returns an\n// error.\nfunc Run(ctx context.Context, s *flag.FlagSet, app Application, args []string) (resultErr error) {\n\ts.Usage = func() {\n\t\tif app.ShortHelp() != \"\" {\n\t\t\tfmt.Fprintf(s.Output(), \"%s\\n\\nUsage:\\n  \", app.ShortHelp())\n\t\t\tif sub, ok := app.(SubCommand); ok && sub.Parent() != \"\" {\n\t\t\t\tfmt.Fprintf(s.Output(), \"%s [flags] %s\", sub.Parent(), app.Name())\n\t\t\t} else {\n\t\t\t\tfmt.Fprintf(s.Output(), \"%s [flags]\", app.Name())\n\t\t\t}\n\t\t\tif usage := app.Usage(); usage != \"\" {\n\t\t\t\tfmt.Fprintf(s.Output(), \" %s\", usage)\n\t\t\t}\n\t\t\tfmt.Fprint(s.Output(), \"\\n\")\n\t\t}\n\t\tapp.DetailedHelp(s)\n\t}\n\tp := addFlags(s, reflect.StructField{}, reflect.ValueOf(app))\n\tif err := s.Parse(args); err != nil {\n\t\treturn err\n\t}\n\n\tif p != nil && p.CPU != \"\" {\n\t\tf, err := os.Create(p.CPU)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := pprof.StartCPUProfile(f); err != nil {\n\t\t\tf.Close() // ignore error\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\tpprof.StopCPUProfile()\n\t\t\tif closeErr := f.Close(); resultErr == nil {\n\t\t\t\tresultErr = closeErr\n\t\t\t}\n\t\t}()\n\t}\n\n\tif p != nil && p.Trace != \"\" {\n\t\tf, err := os.Create(p.Trace)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := trace.Start(f); err != nil {\n\t\t\tf.Close() // ignore error\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\ttrace.Stop()\n\t\t\tif closeErr := f.Close(); resultErr == nil {\n\t\t\t\tresultErr = closeErr\n\t\t\t}\n\t\t\tlog.Printf(\"To view the trace, run:\\n$ go tool trace view %s\", p.Trace)\n\t\t}()\n\t}\n\n\tif p != nil && p.Memory != \"\" {\n\t\tf, err := os.Create(p.Memory)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\truntime.GC() // get up-to-date statistics\n\t\t\tif err := pprof.WriteHeapProfile(f); err != nil {\n\t\t\t\tlog.Printf(\"Writing memory profile: %v\", err)\n\t\t\t}\n\t\t\tif err := f.Close(); err != nil {\n\t\t\t\tlog.Printf(\"Closing memory profile: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\n\tif p != nil && p.Alloc != \"\" {\n\t\tf, err := os.Create(p.Alloc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := pprof.Lookup(\"allocs\").WriteTo(f, 0); err != nil {\n\t\t\t\tlog.Printf(\"Writing alloc profile: %v\", err)\n\t\t\t}\n\t\t\tif err := f.Close(); err != nil {\n\t\t\t\tlog.Printf(\"Closing alloc profile: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\n\tif p != nil && p.Block != \"\" {\n\t\tf, err := os.Create(p.Block)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\truntime.SetBlockProfileRate(1) // record all blocking events\n\t\tdefer func() {\n\t\t\tif err := pprof.Lookup(\"block\").WriteTo(f, 0); err != nil {\n\t\t\t\tlog.Printf(\"Writing block profile: %v\", err)\n\t\t\t}\n\t\t\tif err := f.Close(); err != nil {\n\t\t\t\tlog.Printf(\"Closing block profile: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\n\treturn app.Run(ctx, s.Args()...)\n}\n\n// addFlags scans fields of structs recursively to find things with flag tags\n// and add them to the flag set.\nfunc addFlags(f *flag.FlagSet, field reflect.StructField, value reflect.Value) *Profile {\n\t// is it a field we are allowed to reflect on?\n\tif field.PkgPath != \"\" {\n\t\treturn nil\n\t}\n\t// now see if is actually a flag\n\tflagNames, isFlag := field.Tag.Lookup(\"flag\")\n\thelp := field.Tag.Get(\"help\")\n\tif isFlag {\n\t\tnameList := strings.Split(flagNames, \",\")\n\t\t// add the main flag\n\t\taddFlag(f, value, nameList[0], help)\n\t\tif len(nameList) > 1 {\n\t\t\t// and now add any aliases using the same flag value\n\t\t\tfv := f.Lookup(nameList[0]).Value\n\t\t\tfor _, flagName := range nameList[1:] {\n\t\t\t\tf.Var(fv, flagName, help)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\t// not a flag, but it might be a struct with flags in it\n\tvalue = resolve(value.Elem())\n\tif value.Kind() != reflect.Struct {\n\t\treturn nil\n\t}\n\n\t// TODO(adonovan): there's no need for this special treatment of Profile:\n\t// The caller can use f.Lookup(\"profile.cpu\") etc instead.\n\tp, _ := value.Addr().Interface().(*Profile)\n\t// go through all the fields of the struct\n\tfor i := 0; i < value.Type().NumField(); i++ {\n\t\tchild := value.Type().Field(i)\n\t\tv := value.Field(i)\n\t\t// make sure we have a pointer\n\t\tif v.Kind() != reflect.Pointer {\n\t\t\tv = v.Addr()\n\t\t}\n\t\t// check if that field is a flag or contains flags\n\t\tif fp := addFlags(f, child, v); fp != nil {\n\t\t\tp = fp\n\t\t}\n\t}\n\treturn p\n}\n\nfunc addFlag(f *flag.FlagSet, value reflect.Value, flagName string, help string) {\n\tswitch v := value.Interface().(type) {\n\tcase flag.Value:\n\t\tf.Var(v, flagName, help)\n\tcase *bool:\n\t\tf.BoolVar(v, flagName, *v, help)\n\tcase *time.Duration:\n\t\tf.DurationVar(v, flagName, *v, help)\n\tcase *float64:\n\t\tf.Float64Var(v, flagName, *v, help)\n\tcase *int64:\n\t\tf.Int64Var(v, flagName, *v, help)\n\tcase *int:\n\t\tf.IntVar(v, flagName, *v, help)\n\tcase *string:\n\t\tf.StringVar(v, flagName, *v, help)\n\tcase *uint:\n\t\tf.UintVar(v, flagName, *v, help)\n\tcase *uint64:\n\t\tf.Uint64Var(v, flagName, *v, help)\n\tdefault:\n\t\tlog.Fatalf(\"field %q of type %T is not assignable to flag.Value\", flagName, v)\n\t}\n}\n\nfunc resolve(v reflect.Value) reflect.Value {\n\tfor {\n\t\tswitch v.Kind() {\n\t\tcase reflect.Interface, reflect.Pointer:\n\t\t\tv = v.Elem()\n\t\tdefault:\n\t\t\treturn v\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typeparams/common.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typeparams contains common utilities for writing tools that\n// interact with generic Go code, as introduced with Go 1.18. It\n// supplements the standard library APIs. Notably, the StructuralTerms\n// API computes a minimal representation of the structural\n// restrictions on a type parameter.\n//\n// An external version of these APIs is available in the\n// golang.org/x/exp/typeparams module.\npackage typeparams\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// UnpackIndexExpr extracts data from AST nodes that represent index\n// expressions.\n//\n// For an ast.IndexExpr, the resulting indices slice will contain exactly one\n// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable\n// number of index expressions.\n//\n// For nodes that don't represent index expressions, the first return value of\n// UnpackIndexExpr will be nil.\nfunc UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) {\n\tswitch e := n.(type) {\n\tcase *ast.IndexExpr:\n\t\treturn e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack\n\tcase *ast.IndexListExpr:\n\t\treturn e.X, e.Lbrack, e.Indices, e.Rbrack\n\t}\n\treturn nil, token.NoPos, nil, token.NoPos\n}\n\n// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on\n// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0\n// will panic.\nfunc PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {\n\tswitch len(indices) {\n\tcase 0:\n\t\tpanic(\"empty indices\")\n\tcase 1:\n\t\treturn &ast.IndexExpr{\n\t\t\tX:      x,\n\t\t\tLbrack: lbrack,\n\t\t\tIndex:  indices[0],\n\t\t\tRbrack: rbrack,\n\t\t}\n\tdefault:\n\t\treturn &ast.IndexListExpr{\n\t\t\tX:       x,\n\t\t\tLbrack:  lbrack,\n\t\t\tIndices: indices,\n\t\t\tRbrack:  rbrack,\n\t\t}\n\t}\n}\n\n// IsTypeParam reports whether t is a type parameter (or an alias of one).\nfunc IsTypeParam(t types.Type) bool {\n\t_, ok := types.Unalias(t).(*types.TypeParam)\n\treturn ok\n}\n"
  },
  {
    "path": "internal/typeparams/common_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/internal/typeparams\"\n)\n\nfunc TestGetIndexExprData(t *testing.T) {\n\tx := &ast.Ident{}\n\ti := &ast.Ident{}\n\n\twant := &ast.IndexListExpr{X: x, Lbrack: 1, Indices: []ast.Expr{i}, Rbrack: 2}\n\ttests := map[ast.Node]bool{\n\t\t&ast.IndexExpr{X: x, Lbrack: 1, Index: i, Rbrack: 2}: true,\n\t\twant:         true,\n\t\t&ast.Ident{}: false,\n\t}\n\n\tfor n, isIndexExpr := range tests {\n\t\tX, lbrack, indices, rbrack := UnpackIndexExpr(n)\n\t\tif got := X != nil; got != isIndexExpr {\n\t\t\tt.Errorf(\"UnpackIndexExpr(%v) = %v, _, _, _; want nil: %t\", n, x, !isIndexExpr)\n\t\t}\n\t\tif X == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif X != x || lbrack != 1 || indices[0] != i || rbrack != 2 {\n\t\t\tt.Errorf(\"UnpackIndexExprData(%v) = %v, %v, %v, %v; want %+v\", n, x, lbrack, indices, rbrack, want)\n\t\t}\n\t}\n}\n\nfunc TestFuncOriginRecursive(t *testing.T) {\n\tsrc := `package p\n\ntype N[A any] int\n\nfunc (r N[B]) m() { r.m(); r.n() }\n\nfunc (r *N[C]) n() { }\n`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tinfo := types.Info{\n\t\tDefs: make(map[*ast.Ident]types.Object),\n\t\tUses: make(map[*ast.Ident]types.Object),\n\t}\n\tvar conf types.Config\n\tif _, err := conf.Check(\"p\", fset, []*ast.File{f}, &info); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Collect objects from types.Info.\n\tvar m, n *types.Func   // the 'origin' methods in Info.Defs\n\tvar mm, mn *types.Func // the methods used in the body of m\n\n\tfor _, decl := range f.Decls {\n\t\tfdecl, ok := decl.(*ast.FuncDecl)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tdef := info.Defs[fdecl.Name].(*types.Func)\n\t\tswitch fdecl.Name.Name {\n\t\tcase \"m\":\n\t\t\tm = def\n\t\t\tast.Inspect(fdecl.Body, func(n ast.Node) bool {\n\t\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\tsel := call.Fun.(*ast.SelectorExpr)\n\t\t\t\t\tuse := info.Uses[sel.Sel].(*types.Func)\n\t\t\t\t\tswitch sel.Sel.Name {\n\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\tmm = use\n\t\t\t\t\tcase \"n\":\n\t\t\t\t\t\tmn = use\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\tcase \"n\":\n\t\t\tn = def\n\t\t}\n\t}\n\n\ttests := []struct {\n\t\tname        string\n\t\tinput, want *types.Func\n\t}{\n\t\t{\"declared m\", m, m},\n\t\t{\"declared n\", n, n},\n\t\t{\"used m\", mm, m},\n\t\t{\"used n\", mn, n},\n\t}\n\n\tfor _, test := range tests {\n\t\tif got := test.input.Origin(); got != test.want {\n\t\t\tt.Errorf(\"Origin(%q) = %v, want %v\", test.name, test.input, test.want)\n\t\t}\n\t}\n}\n\nfunc TestFuncOriginUses(t *testing.T) {\n\n\ttests := []string{\n\t\t`type T interface { m() }; func _(t T) { t.m() }`,\n\t\t`type T[P any] interface { m() P }; func _[A any](t T[A]) { t.m() }`,\n\t\t`type T[P any] interface { m() P }; func _(t T[int]) { t.m() }`,\n\t\t`type T[P any] int; func (r T[A]) m() { r.m() }`,\n\t\t`type T[P any] int; func (r *T[A]) m() { r.m() }`,\n\t\t`type T[P any] int; func (r *T[A]) m() {}; func _(t T[int]) { t.m() }`,\n\t\t`type T[P any] int; func (r *T[A]) m() {}; func _[A any](t T[A]) { t.m() }`,\n\t}\n\n\tfor _, src := range tests {\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"p.go\", \"package p; \"+src, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tinfo := types.Info{\n\t\t\tUses: make(map[*ast.Ident]types.Object),\n\t\t}\n\t\tvar conf types.Config\n\t\tpkg, err := conf.Check(\"p\", fset, []*ast.File{f}, &info)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Look up func T.m.\n\t\tT := pkg.Scope().Lookup(\"T\").Type()\n\t\tobj, _, _ := types.LookupFieldOrMethod(T, true, pkg, \"m\")\n\t\tm := obj.(*types.Func)\n\n\t\t// Assert that the origin of each t.m() call is p.T.m.\n\t\tast.Inspect(f, func(n ast.Node) bool {\n\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\tsel := call.Fun.(*ast.SelectorExpr)\n\t\t\t\tuse := info.Uses[sel.Sel].(*types.Func)\n\t\t\t\torig := use.Origin()\n\t\t\t\tif orig != m {\n\t\t\t\t\tt.Errorf(\"%s:\\nUses[%v] = %v, want %v\", src, types.ExprString(sel), use, m)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n}\n\n// Issue #60628 was a crash in gopls caused by inconsistency (#60634) between\n// LookupFieldOrMethod and NewFileSet for methods with an illegal\n// *T receiver type, where T itself is a pointer.\n// This is a regression test for the workaround in the (now deleted) OriginMethod.\nfunc TestFuncOrigin60628(t *testing.T) {\n\tconst src = `package p; type T[P any] *int; func (r *T[A]) f() {}`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Expect type error: \"invalid receiver type T[A] (pointer or interface type)\".\n\tinfo := types.Info{\n\t\tUses: make(map[*ast.Ident]types.Object),\n\t}\n\tvar conf types.Config\n\tpkg, _ := conf.Check(\"p\", fset, []*ast.File{f}, &info) // error expected\n\tif pkg == nil {\n\t\tt.Fatal(\"no package\")\n\t}\n\n\t// Look up methodset of *T.\n\tT := pkg.Scope().Lookup(\"T\").Type()\n\tmset := types.NewMethodSet(types.NewPointer(T))\n\tif mset.Len() == 0 {\n\t\tt.Errorf(\"NewMethodSet(*T) is empty\")\n\t}\n\tfor sel := range mset.Methods() {\n\t\tm := sel.Obj().(*types.Func)\n\n\t\t// TODO(adonovan): check the consistency property required to fix #60634.\n\t\tif false {\n\t\t\tm2, _, _ := types.LookupFieldOrMethod(T, true, m.Pkg(), m.Name())\n\t\t\tif m2 != m {\n\t\t\t\tt.Errorf(\"LookupFieldOrMethod(%v, indirect=true, %v) = %v, want %v\",\n\t\t\t\t\tT, m, m2, m)\n\t\t\t}\n\t\t}\n\n\t\t// Check the workaround.\n\t\tif m.Origin() == nil {\n\t\t\tt.Errorf(\"Origin(%v) = nil\", m)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typeparams/copytermlist.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build ignore\n\n// copytermlist.go copies the term list algorithm from GOROOT/src/go/types.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n)\n\nfunc main() {\n\tif err := doCopy(); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"error copying from go/types: %v\", err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc doCopy() error {\n\tdir := filepath.Join(runtime.GOROOT(), \"src\", \"go\", \"types\")\n\tfor _, name := range []string{\"typeterm.go\", \"termlist.go\"} {\n\t\tpath := filepath.Join(dir, name)\n\t\tfset := token.NewFileSet()\n\t\tfile, err := parser.ParseFile(fset, path, nil, parser.ParseComments)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfile.Name.Name = \"typeparams\"\n\t\tfile.Doc = &ast.CommentGroup{List: []*ast.Comment{{Text: \"DO NOT MODIFY\"}}}\n\t\tvar needImport bool\n\t\tselectorType := reflect.TypeOf((*ast.SelectorExpr)(nil))\n\t\tastutil.Apply(file, func(c *astutil.Cursor) bool {\n\t\t\tif id, _ := c.Node().(*ast.Ident); id != nil {\n\t\t\t\t// Check if this ident should be qualified with types. For simplicity,\n\t\t\t\t// assume the copied files do not themselves contain any exported\n\t\t\t\t// symbols.\n\n\t\t\t\t// As a simple heuristic, just verify that the ident may be replaced by\n\t\t\t\t// a selector.\n\t\t\t\tif !token.IsExported(id.Name) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tv := reflect.TypeOf(c.Parent()).Elem() // ast nodes are all pointers\n\t\t\t\tfield, ok := v.FieldByName(c.Name())\n\t\t\t\tif !ok {\n\t\t\t\t\tpanic(\"missing field\")\n\t\t\t\t}\n\t\t\t\tt := field.Type\n\t\t\t\tif c.Index() > 0 { // => t is a slice\n\t\t\t\t\tt = t.Elem()\n\t\t\t\t}\n\t\t\t\tif !selectorType.AssignableTo(t) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tneedImport = true\n\t\t\t\tc.Replace(&ast.SelectorExpr{\n\t\t\t\t\tX:   &ast.Ident{NamePos: id.NamePos, Name: \"types\"},\n\t\t\t\t\tSel: &ast.Ident{NamePos: id.NamePos, Name: id.Name, Obj: id.Obj},\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn true\n\t\t}, nil)\n\t\tif needImport {\n\t\t\tastutil.AddImport(fset, file, \"go/types\")\n\t\t}\n\n\t\tvar b bytes.Buffer\n\t\tif err := format.Node(&b, fset, file); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Hack in the 'generated' byline.\n\t\tcontent := b.String()\n\t\theader := \"// Code generated by copytermlist.go DO NOT EDIT.\\n\\npackage typeparams\"\n\t\tcontent = strings.Replace(content, \"package typeparams\", header, 1)\n\n\t\tif err := os.WriteFile(name, []byte(content), 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/typeparams/coretype.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n)\n\n// CoreType returns the core type of T or nil if T does not have a core type.\n//\n// See https://go.dev/ref/spec#Core_types for the definition of a core type.\nfunc CoreType(T types.Type) types.Type {\n\tU := T.Underlying()\n\tif _, ok := U.(*types.Interface); !ok {\n\t\treturn U // for non-interface types,\n\t}\n\n\tterms, err := NormalTerms(U)\n\tif len(terms) == 0 || err != nil {\n\t\t// len(terms) -> empty type set of interface.\n\t\t// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.\n\t\treturn nil // no core type.\n\t}\n\n\tU = terms[0].Type().Underlying()\n\tvar identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying())\n\tfor identical = 1; identical < len(terms); identical++ {\n\t\tif !types.Identical(U, terms[identical].Type().Underlying()) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif identical == len(terms) {\n\t\t// https://go.dev/ref/spec#Core_types\n\t\t// \"There is a single type U which is the underlying type of all types in the type set of T\"\n\t\treturn U\n\t}\n\tch, ok := U.(*types.Chan)\n\tif !ok {\n\t\treturn nil // no core type as identical < len(terms) and U is not a channel.\n\t}\n\t// https://go.dev/ref/spec#Core_types\n\t// \"the type chan E if T contains only bidirectional channels, or the type chan<- E or\n\t// <-chan E depending on the direction of the directional channels present.\"\n\tfor chans := identical; chans < len(terms); chans++ {\n\t\tcurr, ok := terms[chans].Type().Underlying().(*types.Chan)\n\t\tif !ok {\n\t\t\treturn nil\n\t\t}\n\t\tif !types.Identical(ch.Elem(), curr.Elem()) {\n\t\t\treturn nil // channel elements are not identical.\n\t\t}\n\t\tif ch.Dir() == types.SendRecv {\n\t\t\t// ch is bidirectional. We can safely always use curr's direction.\n\t\t\tch = curr\n\t\t} else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() {\n\t\t\t// ch and curr are not bidirectional and not the same direction.\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ch\n}\n\n// NormalTerms returns a slice of terms representing the normalized structural\n// type restrictions of a type, if any.\n//\n// For all types other than *types.TypeParam, *types.Interface, and\n// *types.Union, this is just a single term with Tilde() == false and\n// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see\n// below.\n//\n// Structural type restrictions of a type parameter are created via\n// non-interface types embedded in its constraint interface (directly, or via a\n// chain of interface embeddings). For example, in the declaration type\n// T[P interface{~int; m()}] int the structural restriction of the type\n// parameter P is ~int.\n//\n// With interface embedding and unions, the specification of structural type\n// restrictions may be arbitrarily complex. For example, consider the\n// following:\n//\n//\ttype A interface{ ~string|~[]byte }\n//\n//\ttype B interface{ int|string }\n//\n//\ttype C interface { ~string|~int }\n//\n//\ttype T[P interface{ A|B; C }] int\n//\n// In this example, the structural type restriction of P is ~string|int: A|B\n// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,\n// which when intersected with C (~string|~int) yields ~string|int.\n//\n// NormalTerms computes these expansions and reductions, producing a\n// \"normalized\" form of the embeddings. A structural restriction is normalized\n// if it is a single union containing no interface terms, and is minimal in the\n// sense that removing any term changes the set of types satisfying the\n// constraint. It is left as a proof for the reader that, modulo sorting, there\n// is exactly one such normalized form.\n//\n// Because the minimal representation always takes this form, NormalTerms\n// returns a slice of tilde terms corresponding to the terms of the union in\n// the normalized structural restriction. An error is returned if the type is\n// invalid, exceeds complexity bounds, or has an empty type set. In the latter\n// case, NormalTerms returns ErrEmptyTypeSet.\n//\n// NormalTerms makes no guarantees about the order of terms, except that it\n// is deterministic.\nfunc NormalTerms(T types.Type) ([]*types.Term, error) {\n\t// typeSetOf(T) == typeSetOf(Unalias(T))\n\ttyp := types.Unalias(T)\n\tif named, ok := typ.(*types.Named); ok {\n\t\ttyp = named.Underlying()\n\t}\n\tswitch typ := typ.(type) {\n\tcase *types.TypeParam:\n\t\treturn StructuralTerms(typ)\n\tcase *types.Union:\n\t\treturn UnionTermSet(typ)\n\tcase *types.Interface:\n\t\treturn InterfaceTermSet(typ)\n\tdefault:\n\t\treturn []*types.Term{types.NewTerm(false, T)}, nil\n\t}\n}\n\n// Deref returns the type of the variable pointed to by t,\n// if t's core type is a pointer; otherwise it returns t.\n//\n// Do not assume that Deref(T)==T implies T is not a pointer:\n// consider \"type T *T\", for example.\n//\n// TODO(adonovan): ideally this would live in typesinternal, but that\n// creates an import cycle. Move there when we melt this package down.\nfunc Deref(t types.Type) types.Type {\n\tif ptr, ok := CoreType(t).(*types.Pointer); ok {\n\t\treturn ptr.Elem()\n\t}\n\treturn t\n}\n\n// MustDeref returns the type of the variable pointed to by t.\n// It panics if t's core type is not a pointer.\n//\n// TODO(adonovan): ideally this would live in typesinternal, but that\n// creates an import cycle. Move there when we melt this package down.\nfunc MustDeref(t types.Type) types.Type {\n\tif ptr, ok := CoreType(t).(*types.Pointer); ok {\n\t\treturn ptr.Elem()\n\t}\n\tpanic(fmt.Sprintf(\"%v is not a pointer\", t))\n}\n"
  },
  {
    "path": "internal/typeparams/coretype_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\nfunc TestCoreType(t *testing.T) {\n\tconst source = `\n\tpackage P\n\n\ttype Named int\n\n\ttype A any\n\ttype B interface{~int}\n\ttype C interface{int}\n\ttype D interface{Named}\n\ttype E interface{~int|interface{Named}}\n\ttype F interface{~int|~float32}\n\ttype G interface{chan int|interface{chan int}}\n\ttype H interface{chan int|chan float32}\n\ttype I interface{chan<- int|chan int}\n\ttype J interface{chan int|chan<- int}\n\ttype K interface{<-chan int|chan int}\n\ttype L interface{chan int|<-chan int}\n\ttype M interface{chan int|chan Named}\n\ttype N interface{<-chan int|chan<- int}\n\ttype O interface{chan int|bool}\n\ttype P struct{ Named }\n\ttype Q interface{ Foo() }\n\ttype R interface{ Foo() ; Named }\n\ttype S interface{ Foo() ; ~int }\n\n\ttype T interface{chan int|interface{chan int}|<-chan int}\n`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\texpr string // type expression of Named type\n\t\twant string // expected core type (or \"<nil>\" if none)\n\t}{\n\t\t{\"Named\", \"int\"},         // Underlying type is not interface.\n\t\t{\"A\", \"<nil>\"},           // Interface has no terms.\n\t\t{\"B\", \"int\"},             // Tilde term.\n\t\t{\"C\", \"int\"},             // Non-tilde term.\n\t\t{\"D\", \"int\"},             // Named term.\n\t\t{\"E\", \"int\"},             // Identical underlying types.\n\t\t{\"F\", \"<nil>\"},           // Differing underlying types.\n\t\t{\"G\", \"chan int\"},        // Identical Element types.\n\t\t{\"H\", \"<nil>\"},           // Element type int has differing underlying type to float32.\n\t\t{\"I\", \"chan<- int\"},      // SendRecv followed by SendOnly\n\t\t{\"J\", \"chan<- int\"},      // SendOnly followed by SendRecv\n\t\t{\"K\", \"<-chan int\"},      // RecvOnly followed by SendRecv\n\t\t{\"L\", \"<-chan int\"},      // SendRecv followed by RecvOnly\n\t\t{\"M\", \"<nil>\"},           // Element type int is not *identical* to Named.\n\t\t{\"N\", \"<nil>\"},           // Differing channel directions\n\t\t{\"O\", \"<nil>\"},           // A channel followed by a non-channel.\n\t\t{\"P\", \"struct{P.Named}\"}, // Embedded type.\n\t\t{\"Q\", \"<nil>\"},           // interface type with no terms and functions\n\t\t{\"R\", \"int\"},             // interface type with both terms and functions.\n\t\t{\"S\", \"int\"},             // interface type with a tilde term\n\t\t{\"T\", \"<-chan int\"},      // Prefix of 2 terms that are identical before switching to channel.\n\t} {\n\t\t// Eval() expr for its type.\n\t\ttv, err := types.Eval(fset, pkg, 0, test.expr)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\n\t\tct := typeparams.CoreType(tv.Type)\n\t\tvar got string\n\t\tif ct == nil {\n\t\t\tgot = \"<nil>\"\n\t\t} else {\n\t\t\tgot = ct.String()\n\t\t}\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"CoreType(%s) = %v, want %v\", test.expr, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typeparams/free.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"go/types\"\n)\n\n// Free is a memoization of the set of free type parameters within a\n// type. It makes a sequence of calls to [Free.Has] for overlapping\n// types more efficient. The zero value is ready for use.\n//\n// NOTE: Adapted from go/types/infer.go. If it is later exported, factor.\ntype Free struct {\n\tseen map[types.Type]bool\n}\n\n// Has reports whether the specified type has a free type parameter.\nfunc (w *Free) Has(typ types.Type) (res bool) {\n\t// detect cycles\n\tif x, ok := w.seen[typ]; ok {\n\t\treturn x\n\t}\n\tif w.seen == nil {\n\t\tw.seen = make(map[types.Type]bool)\n\t}\n\tw.seen[typ] = false\n\tdefer func() {\n\t\tw.seen[typ] = res\n\t}()\n\n\tswitch t := typ.(type) {\n\tcase nil, *types.Basic: // TODO(gri) should nil be handled here?\n\t\tbreak\n\n\tcase *types.Alias:\n\t\tif t.TypeParams().Len() > t.TypeArgs().Len() {\n\t\t\treturn true // This is an uninstantiated Alias.\n\t\t}\n\t\t// The expansion of an alias can have free type parameters,\n\t\t// whether or not the alias itself has type parameters:\n\t\t//\n\t\t//   func _[K comparable]() {\n\t\t//     type Set      = map[K]bool // free(Set)      = {K}\n\t\t//     type MapTo[V] = map[K]V    // free(Map[foo]) = {V}\n\t\t//   }\n\t\t//\n\t\t// So, we must Unalias.\n\t\treturn w.Has(types.Unalias(t))\n\n\tcase *types.Array:\n\t\treturn w.Has(t.Elem())\n\n\tcase *types.Slice:\n\t\treturn w.Has(t.Elem())\n\n\tcase *types.Struct:\n\t\tfor i, n := 0, t.NumFields(); i < n; i++ {\n\t\t\tif w.Has(t.Field(i).Type()) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\tcase *types.Pointer:\n\t\treturn w.Has(t.Elem())\n\n\tcase *types.Tuple:\n\t\tn := t.Len()\n\t\tfor i := range n {\n\t\t\tif w.Has(t.At(i).Type()) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\tcase *types.Signature:\n\t\t// t.tparams may not be nil if we are looking at a signature\n\t\t// of a generic function type (or an interface method) that is\n\t\t// part of the type we're testing. We don't care about these type\n\t\t// parameters.\n\t\t// Similarly, the receiver of a method may declare (rather than\n\t\t// use) type parameters, we don't care about those either.\n\t\t// Thus, we only need to look at the input and result parameters.\n\t\treturn w.Has(t.Params()) || w.Has(t.Results())\n\n\tcase *types.Interface:\n\t\tfor i, n := 0, t.NumMethods(); i < n; i++ {\n\t\t\tif w.Has(t.Method(i).Type()) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\tterms, err := InterfaceTermSet(t)\n\t\tif err != nil {\n\t\t\treturn false // ill typed\n\t\t}\n\t\tfor _, term := range terms {\n\t\t\tif w.Has(term.Type()) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\tcase *types.Map:\n\t\treturn w.Has(t.Key()) || w.Has(t.Elem())\n\n\tcase *types.Chan:\n\t\treturn w.Has(t.Elem())\n\n\tcase *types.Named:\n\t\targs := t.TypeArgs()\n\t\tif params := t.TypeParams(); params.Len() > args.Len() {\n\t\t\treturn true // this is an uninstantiated named type.\n\t\t}\n\t\tfor i, n := 0, args.Len(); i < n; i++ {\n\t\t\tif w.Has(args.At(i)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn w.Has(t.Underlying()) // recurse for types local to parameterized functions\n\n\tcase *types.TypeParam:\n\t\treturn true\n\n\tdefault:\n\t\tpanic(t) // unreachable\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "internal/typeparams/free_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\nfunc TestFree(t *testing.T) {\n\tconst source = `\npackage P\ntype A int\nfunc (A) f()\nfunc (*A) g()\n\ntype fer interface { f() }\n\nfunc Apply[T fer](x T) T {\n\tx.f()\n\treturn x\n}\n\ntype V[T any] []T\nfunc (v *V[T]) Push(x T) { *v = append(*v, x) }\n`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\texpr string // type expression\n\t\twant bool   // expected value\n\t}{\n\t\t{\"A\", false},\n\t\t{\"*A\", false},\n\t\t{\"error\", false},\n\t\t{\"*error\", false},\n\t\t{\"struct{A}\", false},\n\t\t{\"*struct{A}\", false},\n\t\t{\"fer\", false},\n\t\t{\"Apply\", true},\n\t\t{\"Apply[A]\", false},\n\t\t{\"V\", true},\n\t\t{\"V[A]\", false},\n\t\t{\"*V[A]\", false},\n\t\t{\"(*V[A]).Push\", false},\n\t} {\n\t\ttv, err := types.Eval(fset, pkg, 0, test.expr)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\n\t\tif got := new(Free).Has(tv.Type); got != test.want {\n\t\t\tt.Logf(\"Eval(%s) returned the type %s\", test.expr, tv.Type)\n\t\t\tt.Errorf(\"isParameterized(%s) = %v, want %v\", test.expr, got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestFree124(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 24)\n\tconst source = `\npackage P\n\nfunc Within[T any]() {\n\ttype p[V []T] = int\n\n\ttype q[V any] = T\n\n\tvar end int // end provides a position to test at.\n\t_ = end\n}\n`\n\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"P\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, test := range []struct {\n\t\texpr string // type expression\n\t\twant bool   // expected value\n\t}{\n\t\t{\"p\", true},       // not an instantiation\n\t\t{\"p[[]T]\", false}, // is an instantiation\n\t\t{\"q[int]\", true},\n\t} {\n\t\tpos := pkg.Scope().Lookup(\"Within\").(*types.Func).Scope().Lookup(\"end\").Pos()\n\t\ttv, err := types.Eval(fset, pkg, pos, test.expr)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Eval(%s) failed: %v\", test.expr, err)\n\t\t}\n\n\t\tif got := new(Free).Has(tv.Type); got != test.want {\n\t\t\tt.Logf(\"Eval(%s) returned the type %s\", test.expr, tv.Type)\n\t\t\tt.Errorf(\"isParameterized(%s) = %v, want %v\", test.expr, got, test.want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typeparams/genericfeatures/features.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// The genericfeatures package provides utilities for detecting usage of\n// generic programming in Go packages.\npackage genericfeatures\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\n// Features is a set of flags reporting which features of generic Go code a\n// package uses, or 0.\ntype Features int\n\nconst (\n\t// GenericTypeDecls indicates whether the package declares types with type\n\t// parameters.\n\tGenericTypeDecls Features = 1 << iota\n\n\t// GenericFuncDecls indicates whether the package declares functions with\n\t// type parameters.\n\tGenericFuncDecls\n\n\t// EmbeddedTypeSets indicates whether the package declares interfaces that\n\t// contain structural type restrictions, i.e. are not fully described by\n\t// their method sets.\n\tEmbeddedTypeSets\n\n\t// TypeInstantiation indicates whether the package instantiates any generic\n\t// types.\n\tTypeInstantiation\n\n\t// FuncInstantiation indicates whether the package instantiates any generic\n\t// functions.\n\tFuncInstantiation\n)\n\nfunc (f Features) String() string {\n\tvar feats []string\n\tif f&GenericTypeDecls != 0 {\n\t\tfeats = append(feats, \"typeDecl\")\n\t}\n\tif f&GenericFuncDecls != 0 {\n\t\tfeats = append(feats, \"funcDecl\")\n\t}\n\tif f&EmbeddedTypeSets != 0 {\n\t\tfeats = append(feats, \"typeSet\")\n\t}\n\tif f&TypeInstantiation != 0 {\n\t\tfeats = append(feats, \"typeInstance\")\n\t}\n\tif f&FuncInstantiation != 0 {\n\t\tfeats = append(feats, \"funcInstance\")\n\t}\n\treturn \"features{\" + strings.Join(feats, \",\") + \"}\"\n}\n\n// ForPackage computes which generic features are used directly by the\n// package being analyzed.\nfunc ForPackage(inspect *inspector.Inspector, info *types.Info) Features {\n\tnodeFilter := []ast.Node{\n\t\t(*ast.FuncType)(nil),\n\t\t(*ast.InterfaceType)(nil),\n\t\t(*ast.ImportSpec)(nil),\n\t\t(*ast.TypeSpec)(nil),\n\t}\n\n\tvar direct Features\n\n\tinspect.Preorder(nodeFilter, func(node ast.Node) {\n\t\tswitch n := node.(type) {\n\t\tcase *ast.FuncType:\n\t\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\t\tdirect |= GenericFuncDecls\n\t\t\t}\n\t\tcase *ast.InterfaceType:\n\t\t\ttv := info.Types[n] // may be zero\n\t\t\tif iface, _ := tv.Type.(*types.Interface); iface != nil && !iface.IsMethodSet() {\n\t\t\t\tdirect |= EmbeddedTypeSets\n\t\t\t}\n\t\tcase *ast.TypeSpec:\n\t\t\tif tparams := n.TypeParams; tparams != nil {\n\t\t\t\tdirect |= GenericTypeDecls\n\t\t\t}\n\t\t}\n\t})\n\n\tfor _, inst := range info.Instances {\n\t\tswitch types.Unalias(inst.Type).(type) {\n\t\tcase *types.Named:\n\t\t\tdirect |= TypeInstantiation\n\t\tcase *types.Signature:\n\t\t\tdirect |= FuncInstantiation\n\t\t}\n\t}\n\treturn direct\n}\n"
  },
  {
    "path": "internal/typeparams/normalize.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"os\"\n\t\"strings\"\n)\n\n//go:generate go run copytermlist.go\n\nconst debug = false\n\nvar ErrEmptyTypeSet = errors.New(\"empty type set\")\n\n// StructuralTerms returns a slice of terms representing the normalized\n// structural type restrictions of a type parameter, if any.\n//\n// Structural type restrictions of a type parameter are created via\n// non-interface types embedded in its constraint interface (directly, or via a\n// chain of interface embeddings). For example, in the declaration\n//\n//\ttype T[P interface{~int; m()}] int\n//\n// the structural restriction of the type parameter P is ~int.\n//\n// With interface embedding and unions, the specification of structural type\n// restrictions may be arbitrarily complex. For example, consider the\n// following:\n//\n//\ttype A interface{ ~string|~[]byte }\n//\n//\ttype B interface{ int|string }\n//\n//\ttype C interface { ~string|~int }\n//\n//\ttype T[P interface{ A|B; C }] int\n//\n// In this example, the structural type restriction of P is ~string|int: A|B\n// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,\n// which when intersected with C (~string|~int) yields ~string|int.\n//\n// StructuralTerms computes these expansions and reductions, producing a\n// \"normalized\" form of the embeddings. A structural restriction is normalized\n// if it is a single union containing no interface terms, and is minimal in the\n// sense that removing any term changes the set of types satisfying the\n// constraint. It is left as a proof for the reader that, modulo sorting, there\n// is exactly one such normalized form.\n//\n// Because the minimal representation always takes this form, StructuralTerms\n// returns a slice of tilde terms corresponding to the terms of the union in\n// the normalized structural restriction. An error is returned if the\n// constraint interface is invalid, exceeds complexity bounds, or has an empty\n// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.\n//\n// StructuralTerms makes no guarantees about the order of terms, except that it\n// is deterministic.\nfunc StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) {\n\tconstraint := tparam.Constraint()\n\tif constraint == nil {\n\t\treturn nil, fmt.Errorf(\"%s has nil constraint\", tparam)\n\t}\n\tiface, _ := constraint.Underlying().(*types.Interface)\n\tif iface == nil {\n\t\treturn nil, fmt.Errorf(\"constraint is %T, not *types.Interface\", constraint.Underlying())\n\t}\n\treturn InterfaceTermSet(iface)\n}\n\n// InterfaceTermSet computes the normalized terms for a constraint interface,\n// returning an error if the term set cannot be computed or is empty. In the\n// latter case, the error will be ErrEmptyTypeSet.\n//\n// See the documentation of StructuralTerms for more information on\n// normalization.\nfunc InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) {\n\treturn computeTermSet(iface)\n}\n\n// UnionTermSet computes the normalized terms for a union, returning an error\n// if the term set cannot be computed or is empty. In the latter case, the\n// error will be ErrEmptyTypeSet.\n//\n// See the documentation of StructuralTerms for more information on\n// normalization.\nfunc UnionTermSet(union *types.Union) ([]*types.Term, error) {\n\treturn computeTermSet(union)\n}\n\nfunc computeTermSet(typ types.Type) ([]*types.Term, error) {\n\ttset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif tset.terms.isEmpty() {\n\t\treturn nil, ErrEmptyTypeSet\n\t}\n\tif tset.terms.isAll() {\n\t\treturn nil, nil\n\t}\n\tvar terms []*types.Term\n\tfor _, term := range tset.terms {\n\t\tterms = append(terms, types.NewTerm(term.tilde, term.typ))\n\t}\n\treturn terms, nil\n}\n\n// A termSet holds the normalized set of terms for a given type.\n//\n// The name termSet is intentionally distinct from 'type set': a type set is\n// all types that implement a type (and includes method restrictions), whereas\n// a term set just represents the structural restrictions on a type.\ntype termSet struct {\n\tcomplete bool\n\tterms    termlist\n}\n\nfunc indentf(depth int, format string, args ...any) {\n\tfmt.Fprintf(os.Stderr, strings.Repeat(\".\", depth)+format+\"\\n\", args...)\n}\n\nfunc computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) {\n\tif t == nil {\n\t\tpanic(\"nil type\")\n\t}\n\n\tif debug {\n\t\tindentf(depth, \"%s\", t.String())\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tindentf(depth, \"=> %s\", err)\n\t\t\t} else {\n\t\t\t\tindentf(depth, \"=> %s\", res.terms.String())\n\t\t\t}\n\t\t}()\n\t}\n\n\tconst maxTermCount = 100\n\tif tset, ok := seen[t]; ok {\n\t\tif !tset.complete {\n\t\t\treturn nil, fmt.Errorf(\"cycle detected in the declaration of %s\", t)\n\t\t}\n\t\treturn tset, nil\n\t}\n\n\t// Mark the current type as seen to avoid infinite recursion.\n\ttset := new(termSet)\n\tdefer func() {\n\t\ttset.complete = true\n\t}()\n\tseen[t] = tset\n\n\tswitch u := t.Underlying().(type) {\n\tcase *types.Interface:\n\t\t// The term set of an interface is the intersection of the term sets of its\n\t\t// embedded types.\n\t\ttset.terms = allTermlist\n\t\tfor embedded := range u.EmbeddedTypes() {\n\t\t\tif _, ok := embedded.Underlying().(*types.TypeParam); ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid embedded type %T\", embedded)\n\t\t\t}\n\t\t\ttset2, err := computeTermSetInternal(embedded, seen, depth+1)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ttset.terms = tset.terms.intersect(tset2.terms)\n\t\t}\n\tcase *types.Union:\n\t\t// The term set of a union is the union of term sets of its terms.\n\t\ttset.terms = nil\n\t\tfor t := range u.Terms() {\n\t\t\tvar terms termlist\n\t\t\tswitch t.Type().Underlying().(type) {\n\t\t\tcase *types.Interface:\n\t\t\t\ttset2, err := computeTermSetInternal(t.Type(), seen, depth+1)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tterms = tset2.terms\n\t\t\tcase *types.TypeParam, *types.Union:\n\t\t\t\t// A stand-alone type parameter or union is not permitted as union\n\t\t\t\t// term.\n\t\t\t\treturn nil, fmt.Errorf(\"invalid union term %T\", t)\n\t\t\tdefault:\n\t\t\t\tif t.Type() == types.Typ[types.Invalid] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tterms = termlist{{t.Tilde(), t.Type()}}\n\t\t\t}\n\t\t\ttset.terms = tset.terms.union(terms)\n\t\t\tif len(tset.terms) > maxTermCount {\n\t\t\t\treturn nil, fmt.Errorf(\"exceeded max term count %d\", maxTermCount)\n\t\t\t}\n\t\t}\n\tcase *types.TypeParam:\n\t\tpanic(\"unreachable\")\n\tdefault:\n\t\t// For all other types, the term set is just a single non-tilde term\n\t\t// holding the type itself.\n\t\tif u != types.Typ[types.Invalid] {\n\t\t\ttset.terms = termlist{{false, t}}\n\t\t}\n\t}\n\treturn tset, nil\n}\n\n// under is a facade for the go/types internal function of the same name. It is\n// used by typeterm.go.\nfunc under(t types.Type) types.Type {\n\treturn t.Underlying()\n}\n"
  },
  {
    "path": "internal/typeparams/normalize_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeparams_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t. \"golang.org/x/tools/internal/typeparams\"\n)\n\nfunc TestStructuralTerms(t *testing.T) {\n\t// In the following tests, src must define a type T with (at least) one type\n\t// parameter. We will compute the structural terms of the first type\n\t// parameter.\n\ttests := []struct {\n\t\tsrc       string\n\t\twant      string\n\t\twantError string\n\t}{\n\t\t{\"package emptyinterface0; type T[P interface{}] int\", \"all\", \"\"},\n\t\t{\"package emptyinterface1; type T[P interface{ int | interface{} }] int\", \"all\", \"\"},\n\t\t{\"package singleton; type T[P interface{ int }] int\", \"int\", \"\"},\n\t\t{\"package under; type T[P interface{~int}] int\", \"~int\", \"\"},\n\t\t{\"package superset; type T[P interface{ ~int | int }] int\", \"~int\", \"\"},\n\t\t{\"package overlap; type T[P interface{ ~int; int }] int\", \"int\", \"\"},\n\t\t{\"package emptyintersection; type T[P interface{ ~int; string }] int\", \"\", \"empty type set\"},\n\n\t\t{\"package embedded0; type T[P interface{ I }] int; type I interface { int }\", \"int\", \"\"},\n\t\t{\"package embedded1; type T[P interface{ I | string }] int; type I interface{ int | ~string }\", \"int ?\\\\| ?~string\", \"\"},\n\t\t{\"package embedded2; type T[P interface{ I; string }] int; type I interface{ int | ~string }\", \"string\", \"\"},\n\n\t\t{\"package named; type T[P C] int; type C interface{ ~int|int }\", \"~int\", \"\"},\n\t\t{`// package example is taken from the docstring for StructuralTerms\npackage example\n\ntype A interface{ ~string|~[]byte }\n\ntype B interface{ int|string }\n\ntype C interface { ~string|~int }\n\ntype T[P interface{ A|B; C }] int\n`, \"~string ?\\\\| ?int\", \"\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tfset := token.NewFileSet()\n\t\tf, err := parser.ParseFile(fset, \"p.go\", test.src, 0)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tt.Run(f.Name.Name, func(t *testing.T) {\n\t\t\tconf := types.Config{\n\t\t\t\tError: func(error) {}, // keep going on errors\n\t\t\t}\n\t\t\tpkg, err := conf.Check(\"\", fset, []*ast.File{f}, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Logf(\"types.Config.Check: %v\", err)\n\t\t\t\t// keep going on type checker errors: we want to assert on behavior of\n\t\t\t\t// invalid code as well.\n\t\t\t}\n\t\t\tobj := pkg.Scope().Lookup(\"T\")\n\t\t\tif obj == nil {\n\t\t\t\tt.Fatal(\"type T not found\")\n\t\t\t}\n\t\t\tT := obj.Type().(*types.Named).TypeParams().At(0)\n\t\t\tterms, err := StructuralTerms(T)\n\t\t\tif test.wantError != \"\" {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatalf(\"StructuralTerms(%s): nil error, want %q\", T, test.wantError)\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(err.Error(), test.wantError) {\n\t\t\t\t\tt.Errorf(\"StructuralTerms(%s): err = %q, want %q\", T, err, test.wantError)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tvar got string\n\t\t\tif len(terms) == 0 {\n\t\t\t\tgot = \"all\"\n\t\t\t} else {\n\t\t\t\tqual := types.RelativeTo(pkg)\n\t\t\t\tgot = types.TypeString(types.NewUnion(terms), qual)\n\t\t\t}\n\t\t\twant := regexp.MustCompile(test.want)\n\t\t\tif !want.MatchString(got) {\n\t\t\t\tt.Errorf(\"StructuralTerms(%s) = %q, want %q\", T, got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/typeparams/termlist.go",
    "content": "// Code generated by \"go test -run=Generate -write=all\"; DO NOT EDIT.\n// Source: ../../cmd/compile/internal/types2/termlist.go\n\n// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copytermlist.go DO NOT EDIT.\n\npackage typeparams\n\nimport (\n\t\"go/types\"\n\t\"strings\"\n)\n\n// A termlist represents the type set represented by the union\n// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn.\n// A termlist is in normal form if all terms are disjoint.\n// termlist operations don't require the operands to be in\n// normal form.\ntype termlist []*term\n\n// allTermlist represents the set of all types.\n// It is in normal form.\nvar allTermlist = termlist{new(term)}\n\n// termSep is the separator used between individual terms.\nconst termSep = \" | \"\n\n// String prints the termlist exactly (without normalization).\nfunc (xl termlist) String() string {\n\tif len(xl) == 0 {\n\t\treturn \"∅\"\n\t}\n\tvar buf strings.Builder\n\tfor i, x := range xl {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(termSep)\n\t\t}\n\t\tbuf.WriteString(x.String())\n\t}\n\treturn buf.String()\n}\n\n// isEmpty reports whether the termlist xl represents the empty set of types.\nfunc (xl termlist) isEmpty() bool {\n\t// If there's a non-nil term, the entire list is not empty.\n\t// If the termlist is in normal form, this requires at most\n\t// one iteration.\n\tfor _, x := range xl {\n\t\tif x != nil {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// isAll reports whether the termlist xl represents the set of all types.\nfunc (xl termlist) isAll() bool {\n\t// If there's a 𝓤 term, the entire list is 𝓤.\n\t// If the termlist is in normal form, this requires at most\n\t// one iteration.\n\tfor _, x := range xl {\n\t\tif x != nil && x.typ == nil {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// norm returns the normal form of xl.\nfunc (xl termlist) norm() termlist {\n\t// Quadratic algorithm, but good enough for now.\n\t// TODO(gri) fix asymptotic performance\n\tused := make([]bool, len(xl))\n\tvar rl termlist\n\tfor i, xi := range xl {\n\t\tif xi == nil || used[i] {\n\t\t\tcontinue\n\t\t}\n\t\tfor j := i + 1; j < len(xl); j++ {\n\t\t\txj := xl[j]\n\t\t\tif xj == nil || used[j] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u1, u2 := xi.union(xj); u2 == nil {\n\t\t\t\t// If we encounter a 𝓤 term, the entire list is 𝓤.\n\t\t\t\t// Exit early.\n\t\t\t\t// (Note that this is not just an optimization;\n\t\t\t\t// if we continue, we may end up with a 𝓤 term\n\t\t\t\t// and other terms and the result would not be\n\t\t\t\t// in normal form.)\n\t\t\t\tif u1.typ == nil {\n\t\t\t\t\treturn allTermlist\n\t\t\t\t}\n\t\t\t\txi = u1\n\t\t\t\tused[j] = true // xj is now unioned into xi - ignore it in future iterations\n\t\t\t}\n\t\t}\n\t\trl = append(rl, xi)\n\t}\n\treturn rl\n}\n\n// union returns the union xl ∪ yl.\nfunc (xl termlist) union(yl termlist) termlist {\n\treturn append(xl, yl...).norm()\n}\n\n// intersect returns the intersection xl ∩ yl.\nfunc (xl termlist) intersect(yl termlist) termlist {\n\tif xl.isEmpty() || yl.isEmpty() {\n\t\treturn nil\n\t}\n\n\t// Quadratic algorithm, but good enough for now.\n\t// TODO(gri) fix asymptotic performance\n\tvar rl termlist\n\tfor _, x := range xl {\n\t\tfor _, y := range yl {\n\t\t\tif r := x.intersect(y); r != nil {\n\t\t\t\trl = append(rl, r)\n\t\t\t}\n\t\t}\n\t}\n\treturn rl.norm()\n}\n\n// equal reports whether xl and yl represent the same type set.\nfunc (xl termlist) equal(yl termlist) bool {\n\t// TODO(gri) this should be more efficient\n\treturn xl.subsetOf(yl) && yl.subsetOf(xl)\n}\n\n// includes reports whether t ∈ xl.\nfunc (xl termlist) includes(t types.Type) bool {\n\tfor _, x := range xl {\n\t\tif x.includes(t) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// supersetOf reports whether y ⊆ xl.\nfunc (xl termlist) supersetOf(y *term) bool {\n\tfor _, x := range xl {\n\t\tif y.subsetOf(x) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// subsetOf reports whether xl ⊆ yl.\nfunc (xl termlist) subsetOf(yl termlist) bool {\n\tif yl.isEmpty() {\n\t\treturn xl.isEmpty()\n\t}\n\n\t// each term x of xl must be a subset of yl\n\tfor _, x := range xl {\n\t\tif !yl.supersetOf(x) {\n\t\t\treturn false // x is not a subset yl\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "internal/typeparams/typeterm.go",
    "content": "// Code generated by \"go test -run=Generate -write=all\"; DO NOT EDIT.\n// Source: ../../cmd/compile/internal/types2/typeterm.go\n\n// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Code generated by copytermlist.go DO NOT EDIT.\n\npackage typeparams\n\nimport \"go/types\"\n\n// A term describes elementary type sets:\n//\n//\t ∅:  (*term)(nil)     == ∅                      // set of no types (empty set)\n//\t 𝓤:  &term{}          == 𝓤                      // set of all types (𝓤niverse)\n//\t T:  &term{false, T}  == {T}                    // set of type T\n//\t~t:  &term{true, t}   == {t' | under(t') == t}  // set of types with underlying type t\ntype term struct {\n\ttilde bool // valid if typ != nil\n\ttyp   types.Type\n}\n\nfunc (x *term) String() string {\n\tswitch {\n\tcase x == nil:\n\t\treturn \"∅\"\n\tcase x.typ == nil:\n\t\treturn \"𝓤\"\n\tcase x.tilde:\n\t\treturn \"~\" + x.typ.String()\n\tdefault:\n\t\treturn x.typ.String()\n\t}\n}\n\n// equal reports whether x and y represent the same type set.\nfunc (x *term) equal(y *term) bool {\n\t// easy cases\n\tswitch {\n\tcase x == nil || y == nil:\n\t\treturn x == y\n\tcase x.typ == nil || y.typ == nil:\n\t\treturn x.typ == y.typ\n\t}\n\t// ∅ ⊂ x, y ⊂ 𝓤\n\n\treturn x.tilde == y.tilde && types.Identical(x.typ, y.typ)\n}\n\n// union returns the union x ∪ y: zero, one, or two non-nil terms.\nfunc (x *term) union(y *term) (_, _ *term) {\n\t// easy cases\n\tswitch {\n\tcase x == nil && y == nil:\n\t\treturn nil, nil // ∅ ∪ ∅ == ∅\n\tcase x == nil:\n\t\treturn y, nil // ∅ ∪ y == y\n\tcase y == nil:\n\t\treturn x, nil // x ∪ ∅ == x\n\tcase x.typ == nil:\n\t\treturn x, nil // 𝓤 ∪ y == 𝓤\n\tcase y.typ == nil:\n\t\treturn y, nil // x ∪ 𝓤 == 𝓤\n\t}\n\t// ∅ ⊂ x, y ⊂ 𝓤\n\n\tif x.disjoint(y) {\n\t\treturn x, y // x ∪ y == (x, y) if x ∩ y == ∅\n\t}\n\t// x.typ == y.typ\n\n\t// ~t ∪ ~t == ~t\n\t// ~t ∪  T == ~t\n\t//  T ∪ ~t == ~t\n\t//  T ∪  T ==  T\n\tif x.tilde || !y.tilde {\n\t\treturn x, nil\n\t}\n\treturn y, nil\n}\n\n// intersect returns the intersection x ∩ y.\nfunc (x *term) intersect(y *term) *term {\n\t// easy cases\n\tswitch {\n\tcase x == nil || y == nil:\n\t\treturn nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅\n\tcase x.typ == nil:\n\t\treturn y // 𝓤 ∩ y == y\n\tcase y.typ == nil:\n\t\treturn x // x ∩ 𝓤 == x\n\t}\n\t// ∅ ⊂ x, y ⊂ 𝓤\n\n\tif x.disjoint(y) {\n\t\treturn nil // x ∩ y == ∅ if x ∩ y == ∅\n\t}\n\t// x.typ == y.typ\n\n\t// ~t ∩ ~t == ~t\n\t// ~t ∩  T ==  T\n\t//  T ∩ ~t ==  T\n\t//  T ∩  T ==  T\n\tif !x.tilde || y.tilde {\n\t\treturn x\n\t}\n\treturn y\n}\n\n// includes reports whether t ∈ x.\nfunc (x *term) includes(t types.Type) bool {\n\t// easy cases\n\tswitch {\n\tcase x == nil:\n\t\treturn false // t ∈ ∅ == false\n\tcase x.typ == nil:\n\t\treturn true // t ∈ 𝓤 == true\n\t}\n\t// ∅ ⊂ x ⊂ 𝓤\n\n\tu := t\n\tif x.tilde {\n\t\tu = under(u)\n\t}\n\treturn types.Identical(x.typ, u)\n}\n\n// subsetOf reports whether x ⊆ y.\nfunc (x *term) subsetOf(y *term) bool {\n\t// easy cases\n\tswitch {\n\tcase x == nil:\n\t\treturn true // ∅ ⊆ y == true\n\tcase y == nil:\n\t\treturn false // x ⊆ ∅ == false since x != ∅\n\tcase y.typ == nil:\n\t\treturn true // x ⊆ 𝓤 == true\n\tcase x.typ == nil:\n\t\treturn false // 𝓤 ⊆ y == false since y != 𝓤\n\t}\n\t// ∅ ⊂ x, y ⊂ 𝓤\n\n\tif x.disjoint(y) {\n\t\treturn false // x ⊆ y == false if x ∩ y == ∅\n\t}\n\t// x.typ == y.typ\n\n\t// ~t ⊆ ~t == true\n\t// ~t ⊆ T == false\n\t//  T ⊆ ~t == true\n\t//  T ⊆  T == true\n\treturn !x.tilde || y.tilde\n}\n\n// disjoint reports whether x ∩ y == ∅.\n// x.typ and y.typ must not be nil.\nfunc (x *term) disjoint(y *term) bool {\n\tif debug && (x.typ == nil || y.typ == nil) {\n\t\tpanic(\"invalid argument(s)\")\n\t}\n\tux := x.typ\n\tif y.tilde {\n\t\tux = under(ux)\n\t}\n\tuy := y.typ\n\tif x.tilde {\n\t\tuy = under(uy)\n\t}\n\treturn !types.Identical(ux, uy)\n}\n"
  },
  {
    "path": "internal/typesinternal/classify_call.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/types\"\n\t_ \"unsafe\" // for go:linkname hack\n)\n\n// CallKind describes the function position of an [*ast.CallExpr].\ntype CallKind int\n\nconst (\n\tCallStatic     CallKind = iota // static call to known function\n\tCallInterface                  // dynamic call through an interface method\n\tCallDynamic                    // dynamic call of a func value\n\tCallBuiltin                    // call to a builtin function\n\tCallConversion                 // a conversion (not a call)\n)\n\nvar callKindNames = []string{\n\t\"CallStatic\",\n\t\"CallInterface\",\n\t\"CallDynamic\",\n\t\"CallBuiltin\",\n\t\"CallConversion\",\n}\n\nfunc (k CallKind) String() string {\n\tif i := int(k); i >= 0 && i < len(callKindNames) {\n\t\treturn callKindNames[i]\n\t}\n\treturn fmt.Sprintf(\"typeutil.CallKind(%d)\", k)\n}\n\n// ClassifyCall classifies the function position of a call expression ([*ast.CallExpr]).\n// It distinguishes among true function calls, calls to builtins, and type conversions,\n// and further classifies function calls as static calls (where the function is known),\n// dynamic interface calls, and other dynamic calls.\n//\n// For the declarations:\n//\n//\tfunc f() {}\n//\tfunc g[T any]() {}\n//\tvar v func()\n//\tvar s []func()\n//\ttype I interface { M() }\n//\tvar i I\n//\n// ClassifyCall returns the following:\n//\n//\tf()           CallStatic\n//\tg[int]()      CallStatic\n//\ti.M()         CallInterface\n//\tmin(1, 2)     CallBuiltin\n//\tv()           CallDynamic\n//\ts[0]()        CallDynamic\n//\tint(x)        CallConversion\n//\t[]byte(\"\")    CallConversion\nfunc ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {\n\tif info.Types == nil {\n\t\tpanic(\"ClassifyCall: info.Types is nil\")\n\t}\n\ttv := info.Types[call.Fun]\n\tif tv.IsType() {\n\t\treturn CallConversion\n\t}\n\tif tv.IsBuiltin() {\n\t\treturn CallBuiltin\n\t}\n\tobj := info.Uses[UsedIdent(info, call.Fun)]\n\t// Classify the call by the type of the object, if any.\n\tswitch obj := obj.(type) {\n\tcase *types.Func:\n\t\tif interfaceMethod(obj) {\n\t\t\treturn CallInterface\n\t\t}\n\t\treturn CallStatic\n\tdefault:\n\t\treturn CallDynamic\n\t}\n}\n\n// UsedIdent returns the identifier such that info.Uses[UsedIdent(info, e)]\n// is the [types.Object] used by e, if any.\n//\n// If e is one of various forms of reference:\n//\n//\tf, c, v, T           lexical reference\n//\tpkg.X                qualified identifier\n//\tf[T] or pkg.F[K,V]   instantiations of the above kinds\n//\texpr.f               field or method value selector\n//\tT.f                  method expression selector\n//\n// UsedIdent returns the identifier whose is associated value in [types.Info.Uses]\n// is the object to which it refers.\n//\n// For the declarations:\n//\n//\tfunc F[T any] {...}\n//\ttype I interface { M() }\n//\tvar (\n//\t  x int\n//\t  s struct { f  int }\n//\t  a []int\n//\t  i I\n//\t)\n//\n// UsedIdent returns the following:\n//\n//\tExpr          UsedIdent\n//\tx             x\n//\ts.f           f\n//\tF[int]        F\n//\ti.M           M\n//\tI.M           M\n//\tmin           min\n//\tint           int\n//\t1             nil\n//\ta[0]          nil\n//\t[]byte        nil\n//\n// Note: if e is an instantiated function or method, UsedIdent returns\n// the corresponding generic function or method on the generic type.\nfunc UsedIdent(info *types.Info, e ast.Expr) *ast.Ident {\n\treturn usedIdent(info, e)\n}\n\n//go:linkname usedIdent golang.org/x/tools/go/types/typeutil.usedIdent\nfunc usedIdent(info *types.Info, e ast.Expr) *ast.Ident\n\n//go:linkname interfaceMethod golang.org/x/tools/go/types/typeutil.interfaceMethod\nfunc interfaceMethod(f *types.Func) bool\n"
  },
  {
    "path": "internal/typesinternal/classify_call_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\tti \"golang.org/x/tools/internal/typesinternal\"\n)\n\nfunc TestClassifyCallAndUsed(t *testing.T) {\n\tconst src = `\n\t\tpackage p\n\n\t\tfunc g(int)\n\n\t\ttype A[T any] *T\n\n\t\tfunc F[T any](T) {}\n\n\t\ttype S struct{ f func(int) }\n\t\tfunc (S) g(int)\n\n\t\ttype I interface{ m(int) }\n\n\t\tvar (\n\t\t\tz S\n\t\t\ta struct{b struct{c S}}\n\t\t\tf = g\n\t\t\tm map[int]func()\n\t\t\tn []func()\n\t\t\tp *int\n\t\t)\n\n\t\tfunc tests[T int]() {\n\t\t\tvar zt T\n\n\t\t\tg(1)\n\t\t\tf(1)\n\t\t\tprintln()\n\t\t\tz.g(1)       // a concrete method\n\t\t\ta.b.c.g(1)   // same\n\t\t\tS.g(z, 1)    // method expression\n\t\t\tz.f(1)       // struct field\n\t\t\tI(nil).m(1)  // interface method, then type conversion (preorder traversal)\n\t\t\tm[0]()       // a map\n\t\t\tn[0]()       // a slice\n\t\t\tF[int](1)    // instantiated function\n\t\t\tF[T](zt)     // generic function\n\t\t\tfunc() {}()  // function literal\n\t\t\t_=[]byte(\"\") // type expression\n\t\t\t_=A[int](p)  // instantiated type\n\t\t\t_=T(1)       // type param\n\t\t\t// parenthesized forms\n\t\t\t(z.g)(1)\n\t\t\t(z).g(1)\n\n\n\t\t\t// A[T](1)   // generic type: illegal\n\t\t}\n\t`\n\n\tfset := token.NewFileSet()\n\tcfg := &types.Config{\n\t\tError:    func(err error) { t.Fatal(err) },\n\t\tImporter: importer.Default(),\n\t}\n\tinfo := ti.NewTypesInfo()\n\t// parse\n\tf, err := parser.ParseFile(fset, \"classify.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// type-check\n\tpkg, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tlookup := func(sym string) types.Object {\n\t\treturn pkg.Scope().Lookup(sym)\n\t}\n\n\tmember := func(sym, fieldOrMethod string) types.Object {\n\t\tobj, _, _ := types.LookupFieldOrMethod(lookup(sym).Type(), false, pkg, fieldOrMethod)\n\t\treturn obj\n\t}\n\n\tprintlnObj := types.Universe.Lookup(\"println\")\n\n\ttypeParam := lookup(\"tests\").Type().(*types.Signature).TypeParams().At(0).Obj()\n\n\t// Expected Calls are in the order of CallExprs at the end of src, above.\n\twants := []struct {\n\t\tkind    ti.CallKind\n\t\tusedObj types.Object // the object obtained from the result of UsedIdent\n\t}{\n\t\t{ti.CallStatic, lookup(\"g\")},         // g\n\t\t{ti.CallDynamic, lookup(\"f\")},        // f\n\t\t{ti.CallBuiltin, printlnObj},         // println\n\t\t{ti.CallStatic, member(\"S\", \"g\")},    // z.g\n\t\t{ti.CallStatic, member(\"S\", \"g\")},    // a.b.c.g\n\t\t{ti.CallStatic, member(\"S\", \"g\")},    // S.g(z, 1)\n\t\t{ti.CallDynamic, member(\"z\", \"f\")},   // z.f\n\t\t{ti.CallInterface, member(\"I\", \"m\")}, // I(nil).m\n\t\t{ti.CallConversion, lookup(\"I\")},     // I(nil)\n\t\t{ti.CallDynamic, nil},                // m[0]\n\t\t{ti.CallDynamic, nil},                // n[0]\n\t\t{ti.CallStatic, lookup(\"F\")},         // F[int]\n\t\t{ti.CallStatic, lookup(\"F\")},         // F[T]\n\t\t{ti.CallDynamic, nil},                // f(){}\n\t\t{ti.CallConversion, nil},             // []byte\n\t\t{ti.CallConversion, lookup(\"A\")},     // A[int]\n\t\t{ti.CallConversion, typeParam},       // T\n\t\t{ti.CallStatic, member(\"S\", \"g\")},    // (z.g)\n\t\t{ti.CallStatic, member(\"S\", \"g\")},    // (z).g\n\t}\n\n\ti := 0\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\tif i >= len(wants) {\n\t\t\t\tt.Fatal(\"more calls than wants\")\n\t\t\t}\n\t\t\tvar buf bytes.Buffer\n\t\t\tif err := format.Node(&buf, fset, n); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tprefix := fmt.Sprintf(\"%s (#%d)\", buf.String(), i)\n\n\t\t\tgotKind := ti.ClassifyCall(info, call)\n\t\t\twant := wants[i]\n\n\t\t\tif gotKind != want.kind {\n\t\t\t\tt.Errorf(\"%s kind: got %s, want %s\", prefix, gotKind, want.kind)\n\t\t\t}\n\n\t\t\tw := want.usedObj\n\t\t\tif g := info.Uses[ti.UsedIdent(info, call.Fun)]; g != w {\n\t\t\t\tt.Errorf(\"%s used obj: got %v (%[2]T), want %v\", prefix, g, w)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\treturn true\n\t})\n\tif i != len(wants) {\n\t\tt.Fatal(\"more wants than calls\")\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/element.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n)\n\n// ForEachElement calls f for type T and each type reachable from its\n// type through reflection. It does this by recursively stripping off\n// type constructors; in addition, for each named type N, the type *N\n// is added to the result as it may have additional methods.\n//\n// The caller must provide an initially empty set used to de-duplicate\n// identical types, potentially across multiple calls to ForEachElement.\n// (Its final value holds all the elements seen, matching the arguments\n// passed to f.)\n//\n// TODO(adonovan): share/harmonize with go/callgraph/rta.\nfunc ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) {\n\tvar visit func(T types.Type, skip bool)\n\tvisit = func(T types.Type, skip bool) {\n\t\tif !skip {\n\t\t\tif seen, _ := rtypes.Set(T, true).(bool); seen {\n\t\t\t\treturn // de-dup\n\t\t\t}\n\n\t\t\tf(T) // notify caller of new element type\n\t\t}\n\n\t\t// Recursion over signatures of each method.\n\t\ttmset := msets.MethodSet(T)\n\t\tfor method := range tmset.Methods() {\n\t\t\tsig := method.Type().(*types.Signature)\n\t\t\t// It is tempting to call visit(sig, false)\n\t\t\t// but, as noted in golang.org/cl/65450043,\n\t\t\t// the Signature.Recv field is ignored by\n\t\t\t// types.Identical and typeutil.Map, which\n\t\t\t// is confusing at best.\n\t\t\t//\n\t\t\t// More importantly, the true signature rtype\n\t\t\t// reachable from a method using reflection\n\t\t\t// has no receiver but an extra ordinary parameter.\n\t\t\t// For the Read method of io.Reader we want:\n\t\t\t//   func(Reader, []byte) (int, error)\n\t\t\t// but here sig is:\n\t\t\t//   func([]byte) (int, error)\n\t\t\t// with .Recv = Reader (though it is hard to\n\t\t\t// notice because it doesn't affect Signature.String\n\t\t\t// or types.Identical).\n\t\t\t//\n\t\t\t// TODO(adonovan): construct and visit the correct\n\t\t\t// non-method signature with an extra parameter\n\t\t\t// (though since unnamed func types have no methods\n\t\t\t// there is essentially no actual demand for this).\n\t\t\t//\n\t\t\t// TODO(adonovan): document whether or not it is\n\t\t\t// safe to skip non-exported methods (as RTA does).\n\t\t\tvisit(sig.Params(), true)  // skip the Tuple\n\t\t\tvisit(sig.Results(), true) // skip the Tuple\n\t\t}\n\n\t\tswitch T := T.(type) {\n\t\tcase *types.Alias:\n\t\t\tvisit(types.Unalias(T), skip) // emulates the pre-Alias behavior\n\n\t\tcase *types.Basic:\n\t\t\t// nop\n\n\t\tcase *types.Interface:\n\t\t\t// nop---handled by recursion over method set.\n\n\t\tcase *types.Pointer:\n\t\t\tvisit(T.Elem(), false)\n\n\t\tcase *types.Slice:\n\t\t\tvisit(T.Elem(), false)\n\n\t\tcase *types.Chan:\n\t\t\tvisit(T.Elem(), false)\n\n\t\tcase *types.Map:\n\t\t\tvisit(T.Key(), false)\n\t\t\tvisit(T.Elem(), false)\n\n\t\tcase *types.Signature:\n\t\t\tif T.Recv() != nil {\n\t\t\t\tpanic(fmt.Sprintf(\"Signature %s has Recv %s\", T, T.Recv()))\n\t\t\t}\n\t\t\tvisit(T.Params(), true)  // skip the Tuple\n\t\t\tvisit(T.Results(), true) // skip the Tuple\n\n\t\tcase *types.Named:\n\t\t\t// A pointer-to-named type can be derived from a named\n\t\t\t// type via reflection.  It may have methods too.\n\t\t\tvisit(types.NewPointer(T), false)\n\n\t\t\t// Consider 'type T struct{S}' where S has methods.\n\t\t\t// Reflection provides no way to get from T to struct{S},\n\t\t\t// only to S, so the method set of struct{S} is unwanted,\n\t\t\t// so set 'skip' flag during recursion.\n\t\t\tvisit(T.Underlying(), true) // skip the unnamed type\n\n\t\tcase *types.Array:\n\t\t\tvisit(T.Elem(), false)\n\n\t\tcase *types.Struct:\n\t\t\tfor i, n := 0, T.NumFields(); i < n; i++ {\n\t\t\t\t// TODO(adonovan): document whether or not\n\t\t\t\t// it is safe to skip non-exported fields.\n\t\t\t\tvisit(T.Field(i).Type(), false)\n\t\t\t}\n\n\t\tcase *types.Tuple:\n\t\t\tfor i, n := 0, T.Len(); i < n; i++ {\n\t\t\t\tvisit(T.At(i).Type(), false)\n\t\t\t}\n\n\t\tcase *types.TypeParam, *types.Union:\n\t\t\t// forEachReachable must not be called on parameterized types.\n\t\t\tpanic(T)\n\n\t\tdefault:\n\t\t\tpanic(T)\n\t\t}\n\t}\n\tvisit(T, false)\n}\n"
  },
  {
    "path": "internal/typesinternal/element_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nconst elementSrc = `\npackage p\n\ntype A = int\n\ntype B = *map[chan int][]func() [2]bool\n\ntype C = T\n\ntype T struct{ x int }\nfunc (T) method() uint\nfunc (*T) ptrmethod() complex128\n\ntype D = A\n\ntype E = struct{ x int }\n\ntype F = func(int8, int16) (int32, int64)\n\ntype G = struct { U }\n\ntype U struct{}\nfunc (U) method() uint32\n\n`\n\nfunc TestForEachElement(t *testing.T) {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"a.go\", elementSrc, 0)\n\tif err != nil {\n\t\tt.Fatal(err) // parse error\n\t}\n\tvar config types.Config\n\tpkg, err := config.Check(f.Name.Name, fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\tt.Fatal(err) // type error\n\t}\n\n\ttests := []struct {\n\t\tname string   // name of a type alias whose RHS type's elements to compute\n\t\twant []string // strings of types that are/are not elements (! => not)\n\t}{\n\t\t// simple type\n\t\t{\"A\", []string{\"int\"}},\n\n\t\t// compound type\n\t\t{\"B\", []string{\n\t\t\t\"*map[chan int][]func() [2]bool\",\n\t\t\t\"map[chan int][]func() [2]bool\",\n\t\t\t\"chan int\",\n\t\t\t\"int\",\n\t\t\t\"[]func() [2]bool\",\n\t\t\t\"func() [2]bool\",\n\t\t\t\"[2]bool\",\n\t\t\t\"bool\",\n\t\t}},\n\n\t\t// defined struct type with methods, incl. pointer methods.\n\t\t// Observe that it descends into the field type, but\n\t\t// the result does not include the struct type itself.\n\t\t// (This follows the Go toolchain behavior, and finesses the need\n\t\t// to create wrapper methods for that struct type.)\n\t\t{\"C\", []string{\"T\", \"*T\", \"int\", \"uint\", \"complex128\", \"!struct{x int}\"}},\n\n\t\t// alias type\n\t\t{\"D\", []string{\"int\"}},\n\n\t\t// struct type not beneath a defined type\n\t\t{\"E\", []string{\"struct{x int}\", \"int\"}},\n\n\t\t// signature types: the params/results tuples\n\t\t// are traversed but not included.\n\t\t{\"F\", []string{\"func(int8, int16) (int32, int64)\",\n\t\t\t\"int8\", \"int16\", \"int32\", \"int64\"}},\n\n\t\t// struct with embedded field that has methods\n\t\t{\"G\", []string{\"*U\", \"struct{U}\", \"uint32\", \"U\"}},\n\t}\n\tvar msets typeutil.MethodSetCache\n\tfor _, test := range tests {\n\t\ttname, ok := pkg.Scope().Lookup(test.name).(*types.TypeName)\n\t\tif !ok {\n\t\t\tt.Errorf(\"no such type %q\", test.name)\n\t\t\tcontinue\n\t\t}\n\t\tT := types.Unalias(tname.Type())\n\n\t\ttoStr := func(T types.Type) string {\n\t\t\treturn types.TypeString(T, func(*types.Package) string { return \"\" })\n\t\t}\n\n\t\tgot := make(map[string]bool)\n\t\tset := new(typeutil.Map)  // for de-duping\n\t\tset2 := new(typeutil.Map) // for consistency check\n\t\ttypesinternal.ForEachElement(set, &msets, T, func(elem types.Type) {\n\t\t\tgot[toStr(elem)] = true\n\t\t\tset2.Set(elem, true)\n\t\t})\n\n\t\t// Assert that set==set2, meaning f(x) was\n\t\t// called for each x in the de-duping map.\n\t\tif set.Len() != set2.Len() {\n\t\t\tt.Errorf(\"ForEachElement called f %d times yet de-dup set has %d elements\",\n\t\t\t\tset2.Len(), set.Len())\n\t\t} else {\n\t\t\tset.Iterate(func(key types.Type, _ any) {\n\t\t\t\tif set2.At(key) == nil {\n\t\t\t\t\tt.Errorf(\"ForEachElement did not call f(%v)\", key)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\t// Assert than all expected (and no unexpected) elements were found.\n\t\tfail := false\n\t\tfor _, typstr := range test.want {\n\t\t\tfound := got[typstr]\n\t\t\ttypstr, unwanted := strings.CutPrefix(typstr, \"!\")\n\t\t\tif found && unwanted {\n\t\t\t\tfail = true\n\t\t\t\tt.Errorf(\"ForEachElement(%s): unwanted element %q\", T, typstr)\n\t\t\t} else if !found && !unwanted {\n\t\t\t\tfail = true\n\t\t\t\tt.Errorf(\"ForEachElement(%s): element %q not found\", T, typstr)\n\t\t\t}\n\t\t}\n\t\tif fail {\n\t\t\tt.Logf(\"got elements:\\n%s\", strings.Join(slices.Sorted(maps.Keys(got)), \"\\n\"))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/errorcode.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\n//go:generate stringer -type=ErrorCode\n\ntype ErrorCode int\n\n// This file defines the error codes that can be produced during type-checking.\n// Collectively, these codes provide an identifier that may be used to\n// implement special handling for certain types of errors.\n//\n// Error codes should be fine-grained enough that the exact nature of the error\n// can be easily determined, but coarse enough that they are not an\n// implementation detail of the type checking algorithm. As a rule-of-thumb,\n// errors should be considered equivalent if there is a theoretical refactoring\n// of the type checker in which they are emitted in exactly one place. For\n// example, the type checker emits different error messages for \"too many\n// arguments\" and \"too few arguments\", but one can imagine an alternative type\n// checker where this check instead just emits a single \"wrong number of\n// arguments\", so these errors should have the same code.\n//\n// Error code names should be as brief as possible while retaining accuracy and\n// distinctiveness. In most cases names should start with an adjective\n// describing the nature of the error (e.g. \"invalid\", \"unused\", \"misplaced\"),\n// and end with a noun identifying the relevant language object. For example,\n// \"DuplicateDecl\" or \"InvalidSliceExpr\". For brevity, naming follows the\n// convention that \"bad\" implies a problem with syntax, and \"invalid\" implies a\n// problem with types.\n\nconst (\n\t// InvalidSyntaxTree occurs if an invalid syntax tree is provided\n\t// to the type checker. It should never happen.\n\tInvalidSyntaxTree ErrorCode = -1\n)\n\nconst (\n\t_ ErrorCode = iota\n\n\t// Test is reserved for errors that only apply while in self-test mode.\n\tTest\n\n\t/* package names */\n\n\t// BlankPkgName occurs when a package name is the blank identifier \"_\".\n\t//\n\t// Per the spec:\n\t//  \"The PackageName must not be the blank identifier.\"\n\tBlankPkgName\n\n\t// MismatchedPkgName occurs when a file's package name doesn't match the\n\t// package name already established by other files.\n\tMismatchedPkgName\n\n\t// InvalidPkgUse occurs when a package identifier is used outside of a\n\t// selector expression.\n\t//\n\t// Example:\n\t//  import \"fmt\"\n\t//\n\t//  var _ = fmt\n\tInvalidPkgUse\n\n\t/* imports */\n\n\t// BadImportPath occurs when an import path is not valid.\n\tBadImportPath\n\n\t// BrokenImport occurs when importing a package fails.\n\t//\n\t// Example:\n\t//  import \"amissingpackage\"\n\tBrokenImport\n\n\t// ImportCRenamed occurs when the special import \"C\" is renamed. \"C\" is a\n\t// pseudo-package, and must not be renamed.\n\t//\n\t// Example:\n\t//  import _ \"C\"\n\tImportCRenamed\n\n\t// UnusedImport occurs when an import is unused.\n\t//\n\t// Example:\n\t//  import \"fmt\"\n\t//\n\t//  func main() {}\n\tUnusedImport\n\n\t/* initialization */\n\n\t// InvalidInitCycle occurs when an invalid cycle is detected within the\n\t// initialization graph.\n\t//\n\t// Example:\n\t//  var x int = f()\n\t//\n\t//  func f() int { return x }\n\tInvalidInitCycle\n\n\t/* decls */\n\n\t// DuplicateDecl occurs when an identifier is declared multiple times.\n\t//\n\t// Example:\n\t//  var x = 1\n\t//  var x = 2\n\tDuplicateDecl\n\n\t// InvalidDeclCycle occurs when a declaration cycle is not valid.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  type T struct {\n\t//  \ta [n]int\n\t//  }\n\t//\n\t//  var n = unsafe.Sizeof(T{})\n\tInvalidDeclCycle\n\n\t// InvalidTypeCycle occurs when a cycle in type definitions results in a\n\t// type that is not well-defined.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  type T [unsafe.Sizeof(T{})]int\n\tInvalidTypeCycle\n\n\t/* decls > const */\n\n\t// InvalidConstInit occurs when a const declaration has a non-constant\n\t// initializer.\n\t//\n\t// Example:\n\t//  var x int\n\t//  const _ = x\n\tInvalidConstInit\n\n\t// InvalidConstVal occurs when a const value cannot be converted to its\n\t// target type.\n\t//\n\t// TODO(findleyr): this error code and example are not very clear. Consider\n\t// removing it.\n\t//\n\t// Example:\n\t//  const _ = 1 << \"hello\"\n\tInvalidConstVal\n\n\t// InvalidConstType occurs when the underlying type in a const declaration\n\t// is not a valid constant type.\n\t//\n\t// Example:\n\t//  const c *int = 4\n\tInvalidConstType\n\n\t/* decls > var (+ other variable assignment codes) */\n\n\t// UntypedNilUse occurs when the predeclared (untyped) value nil is used to\n\t// initialize a variable declared without an explicit type.\n\t//\n\t// Example:\n\t//  var x = nil\n\tUntypedNilUse\n\n\t// WrongAssignCount occurs when the number of values on the right-hand side\n\t// of an assignment or initialization expression does not match the number\n\t// of variables on the left-hand side.\n\t//\n\t// Example:\n\t//  var x = 1, 2\n\tWrongAssignCount\n\n\t// UnassignableOperand occurs when the left-hand side of an assignment is\n\t// not assignable.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tconst c = 1\n\t//  \tc = 2\n\t//  }\n\tUnassignableOperand\n\n\t// NoNewVar occurs when a short variable declaration (':=') does not declare\n\t// new variables.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tx := 1\n\t//  \tx := 2\n\t//  }\n\tNoNewVar\n\n\t// MultiValAssignOp occurs when an assignment operation (+=, *=, etc) does\n\t// not have single-valued left-hand or right-hand side.\n\t//\n\t// Per the spec:\n\t//  \"In assignment operations, both the left- and right-hand expression lists\n\t//  must contain exactly one single-valued expression\"\n\t//\n\t// Example:\n\t//  func f() int {\n\t//  \tx, y := 1, 2\n\t//  \tx, y += 1\n\t//  \treturn x + y\n\t//  }\n\tMultiValAssignOp\n\n\t// InvalidIfaceAssign occurs when a value of type T is used as an\n\t// interface, but T does not implement a method of the expected interface.\n\t//\n\t// Example:\n\t//  type I interface {\n\t//  \tf()\n\t//  }\n\t//\n\t//  type T int\n\t//\n\t//  var x I = T(1)\n\tInvalidIfaceAssign\n\n\t// InvalidChanAssign occurs when a chan assignment is invalid.\n\t//\n\t// Per the spec, a value x is assignable to a channel type T if:\n\t//  \"x is a bidirectional channel value, T is a channel type, x's type V and\n\t//  T have identical element types, and at least one of V or T is not a\n\t//  defined type.\"\n\t//\n\t// Example:\n\t//  type T1 chan int\n\t//  type T2 chan int\n\t//\n\t//  var x T1\n\t//  // Invalid assignment because both types are named\n\t//  var _ T2 = x\n\tInvalidChanAssign\n\n\t// IncompatibleAssign occurs when the type of the right-hand side expression\n\t// in an assignment cannot be assigned to the type of the variable being\n\t// assigned.\n\t//\n\t// Example:\n\t//  var x []int\n\t//  var _ int = x\n\tIncompatibleAssign\n\n\t// UnaddressableFieldAssign occurs when trying to assign to a struct field\n\t// in a map value.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tm := make(map[string]struct{i int})\n\t//  \tm[\"foo\"].i = 42\n\t//  }\n\tUnaddressableFieldAssign\n\n\t/* decls > type (+ other type expression codes) */\n\n\t// NotAType occurs when the identifier used as the underlying type in a type\n\t// declaration or the right-hand side of a type alias does not denote a type.\n\t//\n\t// Example:\n\t//  var S = 2\n\t//\n\t//  type T S\n\tNotAType\n\n\t// InvalidArrayLen occurs when an array length is not a constant value.\n\t//\n\t// Example:\n\t//  var n = 3\n\t//  var _ = [n]int{}\n\tInvalidArrayLen\n\n\t// BlankIfaceMethod occurs when a method name is '_'.\n\t//\n\t// Per the spec:\n\t//  \"The name of each explicitly specified method must be unique and not\n\t//  blank.\"\n\t//\n\t// Example:\n\t//  type T interface {\n\t//  \t_(int)\n\t//  }\n\tBlankIfaceMethod\n\n\t// IncomparableMapKey occurs when a map key type does not support the == and\n\t// != operators.\n\t//\n\t// Per the spec:\n\t//  \"The comparison operators == and != must be fully defined for operands of\n\t//  the key type; thus the key type must not be a function, map, or slice.\"\n\t//\n\t// Example:\n\t//  var x map[T]int\n\t//\n\t//  type T []int\n\tIncomparableMapKey\n\n\t// InvalidIfaceEmbed occurs when a non-interface type is embedded in an\n\t// interface.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//\n\t//  func (T) m()\n\t//\n\t//  type I interface {\n\t//  \tT\n\t//  }\n\tInvalidIfaceEmbed\n\n\t// InvalidPtrEmbed occurs when an embedded field is of the pointer form *T,\n\t// and T itself is itself a pointer, an unsafe.Pointer, or an interface.\n\t//\n\t// Per the spec:\n\t//  \"An embedded field must be specified as a type name T or as a pointer to\n\t//  a non-interface type name *T, and T itself may not be a pointer type.\"\n\t//\n\t// Example:\n\t//  type T *int\n\t//\n\t//  type S struct {\n\t//  \t*T\n\t//  }\n\tInvalidPtrEmbed\n\n\t/* decls > func and method */\n\n\t// BadRecv occurs when a method declaration does not have exactly one\n\t// receiver parameter.\n\t//\n\t// Example:\n\t//  func () _() {}\n\tBadRecv\n\n\t// InvalidRecv occurs when a receiver type expression is not of the form T\n\t// or *T, or T is a pointer type.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//\n\t//  func (**T) m() {}\n\tInvalidRecv\n\n\t// DuplicateFieldAndMethod occurs when an identifier appears as both a field\n\t// and method name.\n\t//\n\t// Example:\n\t//  type T struct {\n\t//  \tm int\n\t//  }\n\t//\n\t//  func (T) m() {}\n\tDuplicateFieldAndMethod\n\n\t// DuplicateMethod occurs when two methods on the same receiver type have\n\t// the same name.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//  func (T) m() {}\n\t//  func (T) m(i int) int { return i }\n\tDuplicateMethod\n\n\t/* decls > special */\n\n\t// InvalidBlank occurs when a blank identifier is used as a value or type.\n\t//\n\t// Per the spec:\n\t//  \"The blank identifier may appear as an operand only on the left-hand side\n\t//  of an assignment.\"\n\t//\n\t// Example:\n\t//  var x = _\n\tInvalidBlank\n\n\t// InvalidIota occurs when the predeclared identifier iota is used outside\n\t// of a constant declaration.\n\t//\n\t// Example:\n\t//  var x = iota\n\tInvalidIota\n\n\t// MissingInitBody occurs when an init function is missing its body.\n\t//\n\t// Example:\n\t//  func init()\n\tMissingInitBody\n\n\t// InvalidInitSig occurs when an init function declares parameters or\n\t// results.\n\t//\n\t// Example:\n\t//  func init() int { return 1 }\n\tInvalidInitSig\n\n\t// InvalidInitDecl occurs when init is declared as anything other than a\n\t// function.\n\t//\n\t// Example:\n\t//  var init = 1\n\tInvalidInitDecl\n\n\t// InvalidMainDecl occurs when main is declared as anything other than a\n\t// function, in a main package.\n\tInvalidMainDecl\n\n\t/* exprs */\n\n\t// TooManyValues occurs when a function returns too many values for the\n\t// expression context in which it is used.\n\t//\n\t// Example:\n\t//  func ReturnTwo() (int, int) {\n\t//  \treturn 1, 2\n\t//  }\n\t//\n\t//  var x = ReturnTwo()\n\tTooManyValues\n\n\t// NotAnExpr occurs when a type expression is used where a value expression\n\t// is expected.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//\n\t//  func f() {\n\t//  \tT\n\t//  }\n\tNotAnExpr\n\n\t/* exprs > const */\n\n\t// TruncatedFloat occurs when a float constant is truncated to an integer\n\t// value.\n\t//\n\t// Example:\n\t//  var _ int = 98.6\n\tTruncatedFloat\n\n\t// NumericOverflow occurs when a numeric constant overflows its target type.\n\t//\n\t// Example:\n\t//  var x int8 = 1000\n\tNumericOverflow\n\n\t/* exprs > operation */\n\n\t// UndefinedOp occurs when an operator is not defined for the type(s) used\n\t// in an operation.\n\t//\n\t// Example:\n\t//  var c = \"a\" - \"b\"\n\tUndefinedOp\n\n\t// MismatchedTypes occurs when operand types are incompatible in a binary\n\t// operation.\n\t//\n\t// Example:\n\t//  var a = \"hello\"\n\t//  var b = 1\n\t//  var c = a - b\n\tMismatchedTypes\n\n\t// DivByZero occurs when a division operation is provable at compile\n\t// time to be a division by zero.\n\t//\n\t// Example:\n\t//  const divisor = 0\n\t//  var x int = 1/divisor\n\tDivByZero\n\n\t// NonNumericIncDec occurs when an increment or decrement operator is\n\t// applied to a non-numeric value.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tvar c = \"c\"\n\t//  \tc++\n\t//  }\n\tNonNumericIncDec\n\n\t/* exprs > ptr */\n\n\t// UnaddressableOperand occurs when the & operator is applied to an\n\t// unaddressable expression.\n\t//\n\t// Example:\n\t//  var x = &1\n\tUnaddressableOperand\n\n\t// InvalidIndirection occurs when a non-pointer value is indirected via the\n\t// '*' operator.\n\t//\n\t// Example:\n\t//  var x int\n\t//  var y = *x\n\tInvalidIndirection\n\n\t/* exprs > [] */\n\n\t// NonIndexableOperand occurs when an index operation is applied to a value\n\t// that cannot be indexed.\n\t//\n\t// Example:\n\t//  var x = 1\n\t//  var y = x[1]\n\tNonIndexableOperand\n\n\t// InvalidIndex occurs when an index argument is not of integer type,\n\t// negative, or out-of-bounds.\n\t//\n\t// Example:\n\t//  var s = [...]int{1,2,3}\n\t//  var x = s[5]\n\t//\n\t// Example:\n\t//  var s = []int{1,2,3}\n\t//  var _ = s[-1]\n\t//\n\t// Example:\n\t//  var s = []int{1,2,3}\n\t//  var i string\n\t//  var _ = s[i]\n\tInvalidIndex\n\n\t// SwappedSliceIndices occurs when constant indices in a slice expression\n\t// are decreasing in value.\n\t//\n\t// Example:\n\t//  var _ = []int{1,2,3}[2:1]\n\tSwappedSliceIndices\n\n\t/* operators > slice */\n\n\t// NonSliceableOperand occurs when a slice operation is applied to a value\n\t// whose type is not sliceable, or is unaddressable.\n\t//\n\t// Example:\n\t//  var x = [...]int{1, 2, 3}[:1]\n\t//\n\t// Example:\n\t//  var x = 1\n\t//  var y = 1[:1]\n\tNonSliceableOperand\n\n\t// InvalidSliceExpr occurs when a three-index slice expression (a[x:y:z]) is\n\t// applied to a string.\n\t//\n\t// Example:\n\t//  var s = \"hello\"\n\t//  var x = s[1:2:3]\n\tInvalidSliceExpr\n\n\t/* exprs > shift */\n\n\t// InvalidShiftCount occurs when the right-hand side of a shift operation is\n\t// either non-integer, negative, or too large.\n\t//\n\t// Example:\n\t//  var (\n\t//  \tx string\n\t//  \ty int = 1 << x\n\t//  )\n\tInvalidShiftCount\n\n\t// InvalidShiftOperand occurs when the shifted operand is not an integer.\n\t//\n\t// Example:\n\t//  var s = \"hello\"\n\t//  var x = s << 2\n\tInvalidShiftOperand\n\n\t/* exprs > chan */\n\n\t// InvalidReceive occurs when there is a channel receive from a value that\n\t// is either not a channel, or is a send-only channel.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tvar x = 1\n\t//  \t<-x\n\t//  }\n\tInvalidReceive\n\n\t// InvalidSend occurs when there is a channel send to a value that is not a\n\t// channel, or is a receive-only channel.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tvar x = 1\n\t//  \tx <- \"hello!\"\n\t//  }\n\tInvalidSend\n\n\t/* exprs > literal */\n\n\t// DuplicateLitKey occurs when an index is duplicated in a slice, array, or\n\t// map literal.\n\t//\n\t// Example:\n\t//  var _ = []int{0:1, 0:2}\n\t//\n\t// Example:\n\t//  var _ = map[string]int{\"a\": 1, \"a\": 2}\n\tDuplicateLitKey\n\n\t// MissingLitKey occurs when a map literal is missing a key expression.\n\t//\n\t// Example:\n\t//  var _ = map[string]int{1}\n\tMissingLitKey\n\n\t// InvalidLitIndex occurs when the key in a key-value element of a slice or\n\t// array literal is not an integer constant.\n\t//\n\t// Example:\n\t//  var i = 0\n\t//  var x = []string{i: \"world\"}\n\tInvalidLitIndex\n\n\t// OversizeArrayLit occurs when an array literal exceeds its length.\n\t//\n\t// Example:\n\t//  var _ = [2]int{1,2,3}\n\tOversizeArrayLit\n\n\t// MixedStructLit occurs when a struct literal contains a mix of positional\n\t// and named elements.\n\t//\n\t// Example:\n\t//  var _ = struct{i, j int}{i: 1, 2}\n\tMixedStructLit\n\n\t// InvalidStructLit occurs when a positional struct literal has an incorrect\n\t// number of values.\n\t//\n\t// Example:\n\t//  var _ = struct{i, j int}{1,2,3}\n\tInvalidStructLit\n\n\t// MissingLitField occurs when a struct literal refers to a field that does\n\t// not exist on the struct type.\n\t//\n\t// Example:\n\t//  var _ = struct{i int}{j: 2}\n\tMissingLitField\n\n\t// DuplicateLitField occurs when a struct literal contains duplicated\n\t// fields.\n\t//\n\t// Example:\n\t//  var _ = struct{i int}{i: 1, i: 2}\n\tDuplicateLitField\n\n\t// UnexportedLitField occurs when a positional struct literal implicitly\n\t// assigns an unexported field of an imported type.\n\tUnexportedLitField\n\n\t// InvalidLitField occurs when a field name is not a valid identifier.\n\t//\n\t// Example:\n\t//  var _ = struct{i int}{1: 1}\n\tInvalidLitField\n\n\t// UntypedLit occurs when a composite literal omits a required type\n\t// identifier.\n\t//\n\t// Example:\n\t//  type outer struct{\n\t//  \tinner struct { i int }\n\t//  }\n\t//\n\t//  var _ = outer{inner: {1}}\n\tUntypedLit\n\n\t// InvalidLit occurs when a composite literal expression does not match its\n\t// type.\n\t//\n\t// Example:\n\t//  type P *struct{\n\t//  \tx int\n\t//  }\n\t//  var _ = P {}\n\tInvalidLit\n\n\t/* exprs > selector */\n\n\t// AmbiguousSelector occurs when a selector is ambiguous.\n\t//\n\t// Example:\n\t//  type E1 struct { i int }\n\t//  type E2 struct { i int }\n\t//  type T struct { E1; E2 }\n\t//\n\t//  var x T\n\t//  var _ = x.i\n\tAmbiguousSelector\n\n\t// UndeclaredImportedName occurs when a package-qualified identifier is\n\t// undeclared by the imported package.\n\t//\n\t// Example:\n\t//  import \"go/types\"\n\t//\n\t//  var _ = types.NotAnActualIdentifier\n\tUndeclaredImportedName\n\n\t// UnexportedName occurs when a selector refers to an unexported identifier\n\t// of an imported package.\n\t//\n\t// Example:\n\t//  import \"reflect\"\n\t//\n\t//  type _ reflect.flag\n\tUnexportedName\n\n\t// UndeclaredName occurs when an identifier is not declared in the current\n\t// scope.\n\t//\n\t// Example:\n\t//  var x T\n\tUndeclaredName\n\n\t// MissingFieldOrMethod occurs when a selector references a field or method\n\t// that does not exist.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//\n\t//  var x = T{}.f\n\tMissingFieldOrMethod\n\n\t/* exprs > ... */\n\n\t// BadDotDotDotSyntax occurs when a \"...\" occurs in a context where it is\n\t// not valid.\n\t//\n\t// Example:\n\t//  var _ = map[int][...]int{0: {}}\n\tBadDotDotDotSyntax\n\n\t// NonVariadicDotDotDot occurs when a \"...\" is used on the final argument to\n\t// a non-variadic function.\n\t//\n\t// Example:\n\t//  func printArgs(s []string) {\n\t//  \tfor _, a := range s {\n\t//  \t\tprintln(a)\n\t//  \t}\n\t//  }\n\t//\n\t//  func f() {\n\t//  \ts := []string{\"a\", \"b\", \"c\"}\n\t//  \tprintArgs(s...)\n\t//  }\n\tNonVariadicDotDotDot\n\n\t// MisplacedDotDotDot occurs when a \"...\" is used somewhere other than the\n\t// final argument to a function call.\n\t//\n\t// Example:\n\t//  func printArgs(args ...int) {\n\t//  \tfor _, a := range args {\n\t//  \t\tprintln(a)\n\t//  \t}\n\t//  }\n\t//\n\t//  func f() {\n\t//  \ta := []int{1,2,3}\n\t//  \tprintArgs(0, a...)\n\t//  }\n\tMisplacedDotDotDot\n\n\t// InvalidDotDotDotOperand occurs when a \"...\" operator is applied to a\n\t// single-valued operand.\n\t//\n\t// Example:\n\t//  func printArgs(args ...int) {\n\t//  \tfor _, a := range args {\n\t//  \t\tprintln(a)\n\t//  \t}\n\t//  }\n\t//\n\t//  func f() {\n\t//  \ta := 1\n\t//  \tprintArgs(a...)\n\t//  }\n\t//\n\t// Example:\n\t//  func args() (int, int) {\n\t//  \treturn 1, 2\n\t//  }\n\t//\n\t//  func printArgs(args ...int) {\n\t//  \tfor _, a := range args {\n\t//  \t\tprintln(a)\n\t//  \t}\n\t//  }\n\t//\n\t//  func g() {\n\t//  \tprintArgs(args()...)\n\t//  }\n\tInvalidDotDotDotOperand\n\n\t// InvalidDotDotDot occurs when a \"...\" is used in a non-variadic built-in\n\t// function.\n\t//\n\t// Example:\n\t//  var s = []int{1, 2, 3}\n\t//  var l = len(s...)\n\tInvalidDotDotDot\n\n\t/* exprs > built-in */\n\n\t// UncalledBuiltin occurs when a built-in function is used as a\n\t// function-valued expression, instead of being called.\n\t//\n\t// Per the spec:\n\t//  \"The built-in functions do not have standard Go types, so they can only\n\t//  appear in call expressions; they cannot be used as function values.\"\n\t//\n\t// Example:\n\t//  var _ = copy\n\tUncalledBuiltin\n\n\t// InvalidAppend occurs when append is called with a first argument that is\n\t// not a slice.\n\t//\n\t// Example:\n\t//  var _ = append(1, 2)\n\tInvalidAppend\n\n\t// InvalidCap occurs when an argument to the cap built-in function is not of\n\t// supported type.\n\t//\n\t// See https://golang.org/ref/spec#Length_and_capacity for information on\n\t// which underlying types are supported as arguments to cap and len.\n\t//\n\t// Example:\n\t//  var s = 2\n\t//  var x = cap(s)\n\tInvalidCap\n\n\t// InvalidClose occurs when close(...) is called with an argument that is\n\t// not of channel type, or that is a receive-only channel.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tvar x int\n\t//  \tclose(x)\n\t//  }\n\tInvalidClose\n\n\t// InvalidCopy occurs when the arguments are not of slice type or do not\n\t// have compatible type.\n\t//\n\t// See https://golang.org/ref/spec#Appending_and_copying_slices for more\n\t// information on the type requirements for the copy built-in.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tvar x []int\n\t//  \ty := []int64{1,2,3}\n\t//  \tcopy(x, y)\n\t//  }\n\tInvalidCopy\n\n\t// InvalidComplex occurs when the complex built-in function is called with\n\t// arguments with incompatible types.\n\t//\n\t// Example:\n\t//  var _ = complex(float32(1), float64(2))\n\tInvalidComplex\n\n\t// InvalidDelete occurs when the delete built-in function is called with a\n\t// first argument that is not a map.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tm := \"hello\"\n\t//  \tdelete(m, \"e\")\n\t//  }\n\tInvalidDelete\n\n\t// InvalidImag occurs when the imag built-in function is called with an\n\t// argument that does not have complex type.\n\t//\n\t// Example:\n\t//  var _ = imag(int(1))\n\tInvalidImag\n\n\t// InvalidLen occurs when an argument to the len built-in function is not of\n\t// supported type.\n\t//\n\t// See https://golang.org/ref/spec#Length_and_capacity for information on\n\t// which underlying types are supported as arguments to cap and len.\n\t//\n\t// Example:\n\t//  var s = 2\n\t//  var x = len(s)\n\tInvalidLen\n\n\t// SwappedMakeArgs occurs when make is called with three arguments, and its\n\t// length argument is larger than its capacity argument.\n\t//\n\t// Example:\n\t//  var x = make([]int, 3, 2)\n\tSwappedMakeArgs\n\n\t// InvalidMake occurs when make is called with an unsupported type argument.\n\t//\n\t// See https://golang.org/ref/spec#Making_slices_maps_and_channels for\n\t// information on the types that may be created using make.\n\t//\n\t// Example:\n\t//  var x = make(int)\n\tInvalidMake\n\n\t// InvalidReal occurs when the real built-in function is called with an\n\t// argument that does not have complex type.\n\t//\n\t// Example:\n\t//  var _ = real(int(1))\n\tInvalidReal\n\n\t/* exprs > assertion */\n\n\t// InvalidAssert occurs when a type assertion is applied to a\n\t// value that is not of interface type.\n\t//\n\t// Example:\n\t//  var x = 1\n\t//  var _ = x.(float64)\n\tInvalidAssert\n\n\t// ImpossibleAssert occurs for a type assertion x.(T) when the value x of\n\t// interface cannot have dynamic type T, due to a missing or mismatching\n\t// method on T.\n\t//\n\t// Example:\n\t//  type T int\n\t//\n\t//  func (t *T) m() int { return int(*t) }\n\t//\n\t//  type I interface { m() int }\n\t//\n\t//  var x I\n\t//  var _ = x.(T)\n\tImpossibleAssert\n\n\t/* exprs > conversion */\n\n\t// InvalidConversion occurs when the argument type cannot be converted to the\n\t// target.\n\t//\n\t// See https://golang.org/ref/spec#Conversions for the rules of\n\t// convertibility.\n\t//\n\t// Example:\n\t//  var x float64\n\t//  var _ = string(x)\n\tInvalidConversion\n\n\t// InvalidUntypedConversion occurs when there is no valid implicit\n\t// conversion from an untyped value satisfying the type constraints of the\n\t// context in which it is used.\n\t//\n\t// Example:\n\t//  var _ = 1 + \"\"\n\tInvalidUntypedConversion\n\n\t/* offsetof */\n\n\t// BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument\n\t// that is not a selector expression.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.Offsetof(x)\n\tBadOffsetofSyntax\n\n\t// InvalidOffsetof occurs when unsafe.Offsetof is called with a method\n\t// selector, rather than a field selector, or when the field is embedded via\n\t// a pointer.\n\t//\n\t// Per the spec:\n\t//\n\t//  \"If f is an embedded field, it must be reachable without pointer\n\t//  indirections through fields of the struct. \"\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  type T struct { f int }\n\t//  type S struct { *T }\n\t//  var s S\n\t//  var _ = unsafe.Offsetof(s.f)\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  type S struct{}\n\t//\n\t//  func (S) m() {}\n\t//\n\t//  var s S\n\t//  var _ = unsafe.Offsetof(s.m)\n\tInvalidOffsetof\n\n\t/* control flow > scope */\n\n\t// UnusedExpr occurs when a side-effect free expression is used as a\n\t// statement. Such a statement has no effect.\n\t//\n\t// Example:\n\t//  func f(i int) {\n\t//  \ti*i\n\t//  }\n\tUnusedExpr\n\n\t// UnusedVar occurs when a variable is declared but unused.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tx := 1\n\t//  }\n\tUnusedVar\n\n\t// MissingReturn occurs when a function with results is missing a return\n\t// statement.\n\t//\n\t// Example:\n\t//  func f() int {}\n\tMissingReturn\n\n\t// WrongResultCount occurs when a return statement returns an incorrect\n\t// number of values.\n\t//\n\t// Example:\n\t//  func ReturnOne() int {\n\t//  \treturn 1, 2\n\t//  }\n\tWrongResultCount\n\n\t// OutOfScopeResult occurs when the name of a value implicitly returned by\n\t// an empty return statement is shadowed in a nested scope.\n\t//\n\t// Example:\n\t//  func factor(n int) (i int) {\n\t//  \tfor i := 2; i < n; i++ {\n\t//  \t\tif n%i == 0 {\n\t//  \t\t\treturn\n\t//  \t\t}\n\t//  \t}\n\t//  \treturn 0\n\t//  }\n\tOutOfScopeResult\n\n\t/* control flow > if */\n\n\t// InvalidCond occurs when an if condition is not a boolean expression.\n\t//\n\t// Example:\n\t//  func checkReturn(i int) {\n\t//  \tif i {\n\t//  \t\tpanic(\"non-zero return\")\n\t//  \t}\n\t//  }\n\tInvalidCond\n\n\t/* control flow > for */\n\n\t// InvalidPostDecl occurs when there is a declaration in a for-loop post\n\t// statement.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tfor i := 0; i < 10; j := 0 {}\n\t//  }\n\tInvalidPostDecl\n\n\t// InvalidChanRange occurs when a send-only channel used in a range\n\t// expression.\n\t//\n\t// Example:\n\t//  func sum(c chan<- int) {\n\t//  \ts := 0\n\t//  \tfor i := range c {\n\t//  \t\ts += i\n\t//  \t}\n\t//  }\n\tInvalidChanRange\n\n\t// InvalidIterVar occurs when two iteration variables are used while ranging\n\t// over a channel.\n\t//\n\t// Example:\n\t//  func f(c chan int) {\n\t//  \tfor k, v := range c {\n\t//  \t\tprintln(k, v)\n\t//  \t}\n\t//  }\n\tInvalidIterVar\n\n\t// InvalidRangeExpr occurs when the type of a range expression is not array,\n\t// slice, string, map, or channel.\n\t//\n\t// Example:\n\t//  func f(i int) {\n\t//  \tfor j := range i {\n\t//  \t\tprintln(j)\n\t//  \t}\n\t//  }\n\tInvalidRangeExpr\n\n\t/* control flow > switch */\n\n\t// MisplacedBreak occurs when a break statement is not within a for, switch,\n\t// or select statement of the innermost function definition.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tbreak\n\t//  }\n\tMisplacedBreak\n\n\t// MisplacedContinue occurs when a continue statement is not within a for\n\t// loop of the innermost function definition.\n\t//\n\t// Example:\n\t//  func sumeven(n int) int {\n\t//  \tproceed := func() {\n\t//  \t\tcontinue\n\t//  \t}\n\t//  \tsum := 0\n\t//  \tfor i := 1; i <= n; i++ {\n\t//  \t\tif i % 2 != 0 {\n\t//  \t\t\tproceed()\n\t//  \t\t}\n\t//  \t\tsum += i\n\t//  \t}\n\t//  \treturn sum\n\t//  }\n\tMisplacedContinue\n\n\t// MisplacedFallthrough occurs when a fallthrough statement is not within an\n\t// expression switch.\n\t//\n\t// Example:\n\t//  func typename(i interface{}) string {\n\t//  \tswitch i.(type) {\n\t//  \tcase int64:\n\t//  \t\tfallthrough\n\t//  \tcase int:\n\t//  \t\treturn \"int\"\n\t//  \t}\n\t//  \treturn \"unsupported\"\n\t//  }\n\tMisplacedFallthrough\n\n\t// DuplicateCase occurs when a type or expression switch has duplicate\n\t// cases.\n\t//\n\t// Example:\n\t//  func printInt(i int) {\n\t//  \tswitch i {\n\t//  \tcase 1:\n\t//  \t\tprintln(\"one\")\n\t//  \tcase 1:\n\t//  \t\tprintln(\"One\")\n\t//  \t}\n\t//  }\n\tDuplicateCase\n\n\t// DuplicateDefault occurs when a type or expression switch has multiple\n\t// default clauses.\n\t//\n\t// Example:\n\t//  func printInt(i int) {\n\t//  \tswitch i {\n\t//  \tcase 1:\n\t//  \t\tprintln(\"one\")\n\t//  \tdefault:\n\t//  \t\tprintln(\"One\")\n\t//  \tdefault:\n\t//  \t\tprintln(\"1\")\n\t//  \t}\n\t//  }\n\tDuplicateDefault\n\n\t// BadTypeKeyword occurs when a .(type) expression is used anywhere other\n\t// than a type switch.\n\t//\n\t// Example:\n\t//  type I interface {\n\t//  \tm()\n\t//  }\n\t//  var t I\n\t//  var _ = t.(type)\n\tBadTypeKeyword\n\n\t// InvalidTypeSwitch occurs when .(type) is used on an expression that is\n\t// not of interface type.\n\t//\n\t// Example:\n\t//  func f(i int) {\n\t//  \tswitch x := i.(type) {}\n\t//  }\n\tInvalidTypeSwitch\n\n\t// InvalidExprSwitch occurs when a switch expression is not comparable.\n\t//\n\t// Example:\n\t//  func _() {\n\t//  \tvar a struct{ _ func() }\n\t//  \tswitch a /* ERROR cannot switch on a */ {\n\t//  \t}\n\t//  }\n\tInvalidExprSwitch\n\n\t/* control flow > select */\n\n\t// InvalidSelectCase occurs when a select case is not a channel send or\n\t// receive.\n\t//\n\t// Example:\n\t//  func checkChan(c <-chan int) bool {\n\t//  \tselect {\n\t//  \tcase c:\n\t//  \t\treturn true\n\t//  \tdefault:\n\t//  \t\treturn false\n\t//  \t}\n\t//  }\n\tInvalidSelectCase\n\n\t/* control flow > labels and jumps */\n\n\t// UndeclaredLabel occurs when an undeclared label is jumped to.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  \tgoto L\n\t//  }\n\tUndeclaredLabel\n\n\t// DuplicateLabel occurs when a label is declared more than once.\n\t//\n\t// Example:\n\t//  func f() int {\n\t//  L:\n\t//  L:\n\t//  \treturn 1\n\t//  }\n\tDuplicateLabel\n\n\t// MisplacedLabel occurs when a break or continue label is not on a for,\n\t// switch, or select statement.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  L:\n\t//  \ta := []int{1,2,3}\n\t//  \tfor _, e := range a {\n\t//  \t\tif e > 10 {\n\t//  \t\t\tbreak L\n\t//  \t\t}\n\t//  \t\tprintln(a)\n\t//  \t}\n\t//  }\n\tMisplacedLabel\n\n\t// UnusedLabel occurs when a label is declared but not used.\n\t//\n\t// Example:\n\t//  func f() {\n\t//  L:\n\t//  }\n\tUnusedLabel\n\n\t// JumpOverDecl occurs when a label jumps over a variable declaration.\n\t//\n\t// Example:\n\t//  func f() int {\n\t//  \tgoto L\n\t//  \tx := 2\n\t//  L:\n\t//  \tx++\n\t//  \treturn x\n\t//  }\n\tJumpOverDecl\n\n\t// JumpIntoBlock occurs when a forward jump goes to a label inside a nested\n\t// block.\n\t//\n\t// Example:\n\t//  func f(x int) {\n\t//  \tgoto L\n\t//  \tif x > 0 {\n\t//  \tL:\n\t//  \t\tprint(\"inside block\")\n\t//  \t}\n\t// }\n\tJumpIntoBlock\n\n\t/* control flow > calls */\n\n\t// InvalidMethodExpr occurs when a pointer method is called but the argument\n\t// is not addressable.\n\t//\n\t// Example:\n\t//  type T struct {}\n\t//\n\t//  func (*T) m() int { return 1 }\n\t//\n\t//  var _ = T.m(T{})\n\tInvalidMethodExpr\n\n\t// WrongArgCount occurs when too few or too many arguments are passed by a\n\t// function call.\n\t//\n\t// Example:\n\t//  func f(i int) {}\n\t//  var x = f()\n\tWrongArgCount\n\n\t// InvalidCall occurs when an expression is called that is not of function\n\t// type.\n\t//\n\t// Example:\n\t//  var x = \"x\"\n\t//  var y = x()\n\tInvalidCall\n\n\t/* control flow > suspended */\n\n\t// UnusedResults occurs when a restricted expression-only built-in function\n\t// is suspended via go or defer. Such a suspension discards the results of\n\t// these side-effect free built-in functions, and therefore is ineffectual.\n\t//\n\t// Example:\n\t//  func f(a []int) int {\n\t//  \tdefer len(a)\n\t//  \treturn i\n\t//  }\n\tUnusedResults\n\n\t// InvalidDefer occurs when a deferred expression is not a function call,\n\t// for example if the expression is a type conversion.\n\t//\n\t// Example:\n\t//  func f(i int) int {\n\t//  \tdefer int32(i)\n\t//  \treturn i\n\t//  }\n\tInvalidDefer\n\n\t// InvalidGo occurs when a go expression is not a function call, for example\n\t// if the expression is a type conversion.\n\t//\n\t// Example:\n\t//  func f(i int) int {\n\t//  \tgo int32(i)\n\t//  \treturn i\n\t//  }\n\tInvalidGo\n\n\t// All codes below were added in Go 1.17.\n\n\t/* decl */\n\n\t// BadDecl occurs when a declaration has invalid syntax.\n\tBadDecl\n\n\t// RepeatedDecl occurs when an identifier occurs more than once on the left\n\t// hand side of a short variable declaration.\n\t//\n\t// Example:\n\t//  func _() {\n\t//  \tx, y, y := 1, 2, 3\n\t//  }\n\tRepeatedDecl\n\n\t/* unsafe */\n\n\t// InvalidUnsafeAdd occurs when unsafe.Add is called with a\n\t// length argument that is not of integer type.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var p unsafe.Pointer\n\t//  var _ = unsafe.Add(p, float64(1))\n\tInvalidUnsafeAdd\n\n\t// InvalidUnsafeSlice occurs when unsafe.Slice is called with a\n\t// pointer argument that is not of pointer type or a length argument\n\t// that is not of integer type, negative, or out of bounds.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.Slice(x, 1)\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.Slice(&x, float64(1))\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.Slice(&x, -1)\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.Slice(&x, uint64(1) << 63)\n\tInvalidUnsafeSlice\n\n\t// All codes below were added in Go 1.18.\n\n\t/* features */\n\n\t// UnsupportedFeature occurs when a language feature is used that is not\n\t// supported at this Go version.\n\tUnsupportedFeature\n\n\t/* type params */\n\n\t// NotAGenericType occurs when a non-generic type is used where a generic\n\t// type is expected: in type or function instantiation.\n\t//\n\t// Example:\n\t//  type T int\n\t//\n\t//  var _ T[int]\n\tNotAGenericType\n\n\t// WrongTypeArgCount occurs when a type or function is instantiated with an\n\t// incorrect number of type arguments, including when a generic type or\n\t// function is used without instantiation.\n\t//\n\t// Errors involving failed type inference are assigned other error codes.\n\t//\n\t// Example:\n\t//  type T[p any] int\n\t//\n\t//  var _ T[int, string]\n\t//\n\t// Example:\n\t//  func f[T any]() {}\n\t//\n\t//  var x = f\n\tWrongTypeArgCount\n\n\t// CannotInferTypeArgs occurs when type or function type argument inference\n\t// fails to infer all type arguments.\n\t//\n\t// Example:\n\t//  func f[T any]() {}\n\t//\n\t//  func _() {\n\t//  \tf()\n\t//  }\n\t//\n\t// Example:\n\t//   type N[P, Q any] struct{}\n\t//\n\t//   var _ N[int]\n\tCannotInferTypeArgs\n\n\t// InvalidTypeArg occurs when a type argument does not satisfy its\n\t// corresponding type parameter constraints.\n\t//\n\t// Example:\n\t//  type T[P ~int] struct{}\n\t//\n\t//  var _ T[string]\n\tInvalidTypeArg // arguments? InferenceFailed\n\n\t// InvalidInstanceCycle occurs when an invalid cycle is detected\n\t// within the instantiation graph.\n\t//\n\t// Example:\n\t//  func f[T any]() { f[*T]() }\n\tInvalidInstanceCycle\n\n\t// InvalidUnion occurs when an embedded union or approximation element is\n\t// not valid.\n\t//\n\t// Example:\n\t//  type _ interface {\n\t//   \t~int | interface{ m() }\n\t//  }\n\tInvalidUnion\n\n\t// MisplacedConstraintIface occurs when a constraint-type interface is used\n\t// outside of constraint position.\n\t//\n\t// Example:\n\t//   type I interface { ~int }\n\t//\n\t//   var _ I\n\tMisplacedConstraintIface\n\n\t// InvalidMethodTypeParams occurs when methods have type parameters.\n\t//\n\t// It cannot be encountered with an AST parsed using go/parser.\n\tInvalidMethodTypeParams\n\n\t// MisplacedTypeParam occurs when a type parameter is used in a place where\n\t// it is not permitted.\n\t//\n\t// Example:\n\t//  type T[P any] P\n\t//\n\t// Example:\n\t//  type T[P any] struct{ *P }\n\tMisplacedTypeParam\n\n\t// InvalidUnsafeSliceData occurs when unsafe.SliceData is called with\n\t// an argument that is not of slice type. It also occurs if it is used\n\t// in a package compiled for a language version before go1.20.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var x int\n\t//  var _ = unsafe.SliceData(x)\n\tInvalidUnsafeSliceData\n\n\t// InvalidUnsafeString occurs when unsafe.String is called with\n\t// a length argument that is not of integer type, negative, or\n\t// out of bounds. It also occurs if it is used in a package\n\t// compiled for a language version before go1.20.\n\t//\n\t// Example:\n\t//  import \"unsafe\"\n\t//\n\t//  var b [10]byte\n\t//  var _ = unsafe.String(&b[0], -1)\n\tInvalidUnsafeString\n\n\t// InvalidUnsafeStringData occurs if it is used in a package\n\t// compiled for a language version before go1.20.\n\t_ // not used anymore\n\n)\n"
  },
  {
    "path": "internal/typesinternal/errorcode_string.go",
    "content": "// Code generated by \"stringer -type=ErrorCode\"; DO NOT EDIT.\n\npackage typesinternal\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[InvalidSyntaxTree - -1]\n\t_ = x[Test-1]\n\t_ = x[BlankPkgName-2]\n\t_ = x[MismatchedPkgName-3]\n\t_ = x[InvalidPkgUse-4]\n\t_ = x[BadImportPath-5]\n\t_ = x[BrokenImport-6]\n\t_ = x[ImportCRenamed-7]\n\t_ = x[UnusedImport-8]\n\t_ = x[InvalidInitCycle-9]\n\t_ = x[DuplicateDecl-10]\n\t_ = x[InvalidDeclCycle-11]\n\t_ = x[InvalidTypeCycle-12]\n\t_ = x[InvalidConstInit-13]\n\t_ = x[InvalidConstVal-14]\n\t_ = x[InvalidConstType-15]\n\t_ = x[UntypedNilUse-16]\n\t_ = x[WrongAssignCount-17]\n\t_ = x[UnassignableOperand-18]\n\t_ = x[NoNewVar-19]\n\t_ = x[MultiValAssignOp-20]\n\t_ = x[InvalidIfaceAssign-21]\n\t_ = x[InvalidChanAssign-22]\n\t_ = x[IncompatibleAssign-23]\n\t_ = x[UnaddressableFieldAssign-24]\n\t_ = x[NotAType-25]\n\t_ = x[InvalidArrayLen-26]\n\t_ = x[BlankIfaceMethod-27]\n\t_ = x[IncomparableMapKey-28]\n\t_ = x[InvalidIfaceEmbed-29]\n\t_ = x[InvalidPtrEmbed-30]\n\t_ = x[BadRecv-31]\n\t_ = x[InvalidRecv-32]\n\t_ = x[DuplicateFieldAndMethod-33]\n\t_ = x[DuplicateMethod-34]\n\t_ = x[InvalidBlank-35]\n\t_ = x[InvalidIota-36]\n\t_ = x[MissingInitBody-37]\n\t_ = x[InvalidInitSig-38]\n\t_ = x[InvalidInitDecl-39]\n\t_ = x[InvalidMainDecl-40]\n\t_ = x[TooManyValues-41]\n\t_ = x[NotAnExpr-42]\n\t_ = x[TruncatedFloat-43]\n\t_ = x[NumericOverflow-44]\n\t_ = x[UndefinedOp-45]\n\t_ = x[MismatchedTypes-46]\n\t_ = x[DivByZero-47]\n\t_ = x[NonNumericIncDec-48]\n\t_ = x[UnaddressableOperand-49]\n\t_ = x[InvalidIndirection-50]\n\t_ = x[NonIndexableOperand-51]\n\t_ = x[InvalidIndex-52]\n\t_ = x[SwappedSliceIndices-53]\n\t_ = x[NonSliceableOperand-54]\n\t_ = x[InvalidSliceExpr-55]\n\t_ = x[InvalidShiftCount-56]\n\t_ = x[InvalidShiftOperand-57]\n\t_ = x[InvalidReceive-58]\n\t_ = x[InvalidSend-59]\n\t_ = x[DuplicateLitKey-60]\n\t_ = x[MissingLitKey-61]\n\t_ = x[InvalidLitIndex-62]\n\t_ = x[OversizeArrayLit-63]\n\t_ = x[MixedStructLit-64]\n\t_ = x[InvalidStructLit-65]\n\t_ = x[MissingLitField-66]\n\t_ = x[DuplicateLitField-67]\n\t_ = x[UnexportedLitField-68]\n\t_ = x[InvalidLitField-69]\n\t_ = x[UntypedLit-70]\n\t_ = x[InvalidLit-71]\n\t_ = x[AmbiguousSelector-72]\n\t_ = x[UndeclaredImportedName-73]\n\t_ = x[UnexportedName-74]\n\t_ = x[UndeclaredName-75]\n\t_ = x[MissingFieldOrMethod-76]\n\t_ = x[BadDotDotDotSyntax-77]\n\t_ = x[NonVariadicDotDotDot-78]\n\t_ = x[MisplacedDotDotDot-79]\n\t_ = x[InvalidDotDotDotOperand-80]\n\t_ = x[InvalidDotDotDot-81]\n\t_ = x[UncalledBuiltin-82]\n\t_ = x[InvalidAppend-83]\n\t_ = x[InvalidCap-84]\n\t_ = x[InvalidClose-85]\n\t_ = x[InvalidCopy-86]\n\t_ = x[InvalidComplex-87]\n\t_ = x[InvalidDelete-88]\n\t_ = x[InvalidImag-89]\n\t_ = x[InvalidLen-90]\n\t_ = x[SwappedMakeArgs-91]\n\t_ = x[InvalidMake-92]\n\t_ = x[InvalidReal-93]\n\t_ = x[InvalidAssert-94]\n\t_ = x[ImpossibleAssert-95]\n\t_ = x[InvalidConversion-96]\n\t_ = x[InvalidUntypedConversion-97]\n\t_ = x[BadOffsetofSyntax-98]\n\t_ = x[InvalidOffsetof-99]\n\t_ = x[UnusedExpr-100]\n\t_ = x[UnusedVar-101]\n\t_ = x[MissingReturn-102]\n\t_ = x[WrongResultCount-103]\n\t_ = x[OutOfScopeResult-104]\n\t_ = x[InvalidCond-105]\n\t_ = x[InvalidPostDecl-106]\n\t_ = x[InvalidChanRange-107]\n\t_ = x[InvalidIterVar-108]\n\t_ = x[InvalidRangeExpr-109]\n\t_ = x[MisplacedBreak-110]\n\t_ = x[MisplacedContinue-111]\n\t_ = x[MisplacedFallthrough-112]\n\t_ = x[DuplicateCase-113]\n\t_ = x[DuplicateDefault-114]\n\t_ = x[BadTypeKeyword-115]\n\t_ = x[InvalidTypeSwitch-116]\n\t_ = x[InvalidExprSwitch-117]\n\t_ = x[InvalidSelectCase-118]\n\t_ = x[UndeclaredLabel-119]\n\t_ = x[DuplicateLabel-120]\n\t_ = x[MisplacedLabel-121]\n\t_ = x[UnusedLabel-122]\n\t_ = x[JumpOverDecl-123]\n\t_ = x[JumpIntoBlock-124]\n\t_ = x[InvalidMethodExpr-125]\n\t_ = x[WrongArgCount-126]\n\t_ = x[InvalidCall-127]\n\t_ = x[UnusedResults-128]\n\t_ = x[InvalidDefer-129]\n\t_ = x[InvalidGo-130]\n\t_ = x[BadDecl-131]\n\t_ = x[RepeatedDecl-132]\n\t_ = x[InvalidUnsafeAdd-133]\n\t_ = x[InvalidUnsafeSlice-134]\n\t_ = x[UnsupportedFeature-135]\n\t_ = x[NotAGenericType-136]\n\t_ = x[WrongTypeArgCount-137]\n\t_ = x[CannotInferTypeArgs-138]\n\t_ = x[InvalidTypeArg-139]\n\t_ = x[InvalidInstanceCycle-140]\n\t_ = x[InvalidUnion-141]\n\t_ = x[MisplacedConstraintIface-142]\n\t_ = x[InvalidMethodTypeParams-143]\n\t_ = x[MisplacedTypeParam-144]\n\t_ = x[InvalidUnsafeSliceData-145]\n\t_ = x[InvalidUnsafeString-146]\n}\n\nconst (\n\t_ErrorCode_name_0 = \"InvalidSyntaxTree\"\n\t_ErrorCode_name_1 = \"TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilUseWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParamInvalidUnsafeSliceDataInvalidUnsafeString\"\n)\n\nvar (\n\t_ErrorCode_index_1 = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 218, 234, 253, 261, 277, 295, 312, 330, 354, 362, 377, 393, 411, 428, 443, 450, 461, 484, 499, 511, 522, 537, 551, 566, 581, 594, 603, 617, 632, 643, 658, 667, 683, 703, 721, 740, 752, 771, 790, 806, 823, 842, 856, 867, 882, 895, 910, 926, 940, 956, 971, 988, 1006, 1021, 1031, 1041, 1058, 1080, 1094, 1108, 1128, 1146, 1166, 1184, 1207, 1223, 1238, 1251, 1261, 1273, 1284, 1298, 1311, 1322, 1332, 1347, 1358, 1369, 1382, 1398, 1415, 1439, 1456, 1471, 1481, 1490, 1503, 1519, 1535, 1546, 1561, 1577, 1591, 1607, 1621, 1638, 1658, 1671, 1687, 1701, 1718, 1735, 1752, 1767, 1781, 1795, 1806, 1818, 1831, 1848, 1861, 1872, 1885, 1897, 1906, 1913, 1925, 1941, 1959, 1977, 1992, 2009, 2028, 2042, 2062, 2074, 2098, 2121, 2139, 2161, 2180}\n)\n\nfunc (i ErrorCode) String() string {\n\tswitch {\n\tcase i == -1:\n\t\treturn _ErrorCode_name_0\n\tcase 1 <= i && i <= 146:\n\t\ti -= 1\n\t\treturn _ErrorCode_name_1[_ErrorCode_index_1[i]:_ErrorCode_index_1[i+1]]\n\tdefault:\n\t\treturn \"ErrorCode(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/errorcode_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestErrorCodes(t *testing.T) {\n\tt.Skip(\"unskip this test to verify the correctness of errorcode.go for the current Go version\")\n\n\t// For older go versions, this file was src/go/types/errorcodes.go.\n\tstdPath := filepath.Join(runtime.GOROOT(), \"src\", \"internal\", \"types\", \"errors\", \"codes.go\")\n\tstdCodes, err := loadCodes(stdPath)\n\tif err != nil {\n\t\tt.Fatalf(\"loading std codes: %v\", err)\n\t}\n\n\tlocalPath := \"errorcode.go\"\n\tlocalCodes, err := loadCodes(localPath)\n\tif err != nil {\n\t\tt.Fatalf(\"loading local codes: %v\", err)\n\t}\n\n\t// Verify that all std codes are present, with the correct value.\n\ttype codeVal struct {\n\t\tName  string\n\t\tValue int64\n\t}\n\tvar byValue []codeVal\n\tfor k, v := range stdCodes {\n\t\tbyValue = append(byValue, codeVal{k, v})\n\t}\n\tsort.Slice(byValue, func(i, j int) bool {\n\t\treturn byValue[i].Value < byValue[j].Value\n\t})\n\n\tlocalLookup := make(map[int64]string)\n\tfor k, v := range localCodes {\n\t\tif _, ok := localLookup[v]; ok {\n\t\t\tt.Errorf(\"duplicate error code value %d\", v)\n\t\t}\n\t\tlocalLookup[v] = k\n\t}\n\n\tfor _, std := range byValue {\n\t\tlocal, ok := localCodes[std.Name]\n\t\tif !ok {\n\t\t\tif v, ok := localLookup[std.Value]; ok {\n\t\t\t\tt.Errorf(\"Missing code for %s (code %d is %s)\", std.Name, std.Value, v)\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"Missing code for %s\", std.Name)\n\t\t\t}\n\t\t}\n\t\tif local != std.Value {\n\t\t\tt.Errorf(\"Mismatching value for %s: got %d, but stdlib has %d\", std.Name, local, std.Value)\n\t\t}\n\t}\n}\n\n// loadCodes loads all constant values found in filepath.\n//\n// The given file must type-check cleanly as a standalone file.\nfunc loadCodes(filepath string) (map[string]int64, error) {\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, filepath, nil, 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar config types.Config\n\tpkg, err := config.Check(\"p\", fset, []*ast.File{f}, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcodes := make(map[string]int64)\n\tfor _, name := range pkg.Scope().Names() {\n\t\tobj := pkg.Scope().Lookup(name)\n\t\tc, ok := obj.(*types.Const)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tname := strings.TrimPrefix(name, \"_\") // compatibility with earlier go versions\n\t\tcodes[name], ok = constant.Int64Val(c.Val())\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"non integral value %v for %s\", c.Val(), name)\n\t\t}\n\t}\n\tif len(codes) < 100 {\n\t\treturn nil, fmt.Errorf(\"sanity check: got %d codes but expected at least 100\", len(codes))\n\t}\n\treturn codes, nil\n}\n"
  },
  {
    "path": "internal/typesinternal/fx.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n)\n\n// NoEffects reports whether the expression has no side effects, i.e., it\n// does not modify the memory state. This function is conservative: it may\n// return false even when the expression has no effect.\nfunc NoEffects(info *types.Info, expr ast.Expr) bool {\n\tnoEffects := true\n\tast.Inspect(expr, func(n ast.Node) bool {\n\t\tswitch v := n.(type) {\n\t\tcase nil, *ast.Ident, *ast.BasicLit, *ast.BinaryExpr, *ast.ParenExpr,\n\t\t\t*ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr, *ast.TypeAssertExpr,\n\t\t\t*ast.StarExpr, *ast.CompositeLit,\n\t\t\t// non-expressions that may appear within expressions\n\t\t\t*ast.KeyValueExpr,\n\t\t\t*ast.FieldList,\n\t\t\t*ast.Field,\n\t\t\t*ast.Ellipsis,\n\t\t\t*ast.IndexListExpr:\n\t\t\t// No effect.\n\n\t\tcase *ast.ArrayType,\n\t\t\t*ast.StructType,\n\t\t\t*ast.ChanType,\n\t\t\t*ast.FuncType,\n\t\t\t*ast.MapType,\n\t\t\t*ast.InterfaceType:\n\t\t\t// Type syntax: no effects, recursively.\n\t\t\t// Prune descent.\n\t\t\treturn false\n\n\t\tcase *ast.UnaryExpr:\n\t\t\t// Channel send <-ch has effects.\n\t\t\tif v.Op == token.ARROW {\n\t\t\t\tnoEffects = false\n\t\t\t}\n\n\t\tcase *ast.CallExpr:\n\t\t\t// Type conversion has no effects.\n\t\t\tif !info.Types[v.Fun].IsType() {\n\t\t\t\tif CallsPureBuiltin(info, v) {\n\t\t\t\t\t// A call such as len(e) has no effects of its\n\t\t\t\t\t// own, though the subexpression e might.\n\t\t\t\t} else {\n\t\t\t\t\tnoEffects = false\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *ast.FuncLit:\n\t\t\t// A FuncLit has no effects, but do not descend into it.\n\t\t\treturn false\n\n\t\tdefault:\n\t\t\t// All other expressions have effects\n\t\t\tnoEffects = false\n\t\t}\n\n\t\treturn noEffects\n\t})\n\treturn noEffects\n}\n\n// CallsPureBuiltin reports whether call is a call of a built-in\n// function that is a pure computation over its operands (analogous to\n// a + operator). Because it does not depend on program state, it may\n// be evaluated at any point--though not necessarily at multiple\n// points (consider new, make).\nfunc CallsPureBuiltin(info *types.Info, call *ast.CallExpr) bool {\n\tif id, ok := ast.Unparen(call.Fun).(*ast.Ident); ok {\n\t\tif b, ok := info.ObjectOf(id).(*types.Builtin); ok {\n\t\t\tswitch b.Name() {\n\t\t\tcase \"len\", \"cap\", \"complex\", \"imag\", \"real\", \"make\", \"new\", \"max\", \"min\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Not: append clear close copy delete panic print println recover\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/typesinternal/fx_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nfunc TestNoEffects(t *testing.T) {\n\tsrc := `package p\n\ntype T int\n\ntype G[P any] int\n\nfunc _() {\n\tvar x int\n\t_ = T(x)\n\t_ = G[int](x)\n}\n`\n\tfset := token.NewFileSet()\n\tfile, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar conf types.Config\n\tinfo := &types.Info{\n\t\tTypes: make(map[ast.Expr]types.TypeAndValue),\n\t}\n\t_, err = conf.Check(\"\", fset, []*ast.File{file}, info)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tast.Inspect(file, func(node ast.Node) bool {\n\t\tcall, ok := node.(*ast.CallExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif !typesinternal.NoEffects(info, call) {\n\t\t\tt.Errorf(\"NoEffects(%s) = false\", types.ExprString(call))\n\t\t}\n\t\treturn true\n\t})\n}\n"
  },
  {
    "path": "internal/typesinternal/isnamed.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"go/types\"\n\t\"slices\"\n)\n\n// IsTypeNamed reports whether t is (or is an alias for) a\n// package-level defined type with the given package path and one of\n// the given names. It returns false if t is nil.\n//\n// This function avoids allocating the concatenation of \"pkg.Name\",\n// which is important for the performance of syntax matching.\nfunc IsTypeNamed(t types.Type, pkgPath string, names ...string) bool {\n\tif named, ok := types.Unalias(t).(*types.Named); ok {\n\t\ttname := named.Obj()\n\t\treturn tname != nil &&\n\t\t\tIsPackageLevel(tname) &&\n\t\t\ttname.Pkg().Path() == pkgPath &&\n\t\t\tslices.Contains(names, tname.Name())\n\t}\n\treturn false\n}\n\n// IsPointerToNamed reports whether t is (or is an alias for) a pointer to a\n// package-level defined type with the given package path and one of the given\n// names. It returns false if t is not a pointer type.\nfunc IsPointerToNamed(t types.Type, pkgPath string, names ...string) bool {\n\tr := Unpointer(t)\n\tif r == t {\n\t\treturn false\n\t}\n\treturn IsTypeNamed(r, pkgPath, names...)\n}\n\n// IsFunctionNamed reports whether obj is a package-level function\n// defined in the given package and has one of the given names.\n// It returns false if obj is nil.\n//\n// This function avoids allocating the concatenation of \"pkg.Name\",\n// which is important for the performance of syntax matching.\nfunc IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {\n\tf, ok := obj.(*types.Func)\n\treturn ok &&\n\t\tIsPackageLevel(obj) &&\n\t\tf.Pkg().Path() == pkgPath &&\n\t\tf.Signature().Recv() == nil &&\n\t\tslices.Contains(names, f.Name())\n}\n\n// IsMethodNamed reports whether obj is a method defined on a\n// package-level type with the given package and type name, and has\n// one of the given names. It returns false if obj is nil.\n//\n// This function avoids allocating the concatenation of \"pkg.TypeName.Name\",\n// which is important for the performance of syntax matching.\nfunc IsMethodNamed(obj types.Object, pkgPath string, typeName string, names ...string) bool {\n\tif fn, ok := obj.(*types.Func); ok {\n\t\tif recv := fn.Signature().Recv(); recv != nil {\n\t\t\t_, T := ReceiverNamed(recv)\n\t\t\treturn T != nil &&\n\t\t\t\tIsTypeNamed(T, pkgPath, typeName) &&\n\t\t\t\tslices.Contains(names, fn.Name())\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/typesinternal/qualifier.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n\t\"strconv\"\n)\n\n// FileQualifier returns a [types.Qualifier] function that qualifies\n// imported symbols appropriately based on the import environment of a given\n// file.\n// If the same package is imported multiple times, the last appearance is\n// recorded.\n//\n// TODO(adonovan): this function ignores the effect of shadowing. It\n// should accept a [token.Pos] and a [types.Info] and compute only the\n// set of imports that are not shadowed at that point, analogous to\n// [analysis.AddImport]. It could also compute (as a side\n// effect) the set of additional imports required to ensure that there\n// is an accessible import for each necessary package, making it\n// converge even more closely with AddImport.\nfunc FileQualifier(f *ast.File, pkg *types.Package) types.Qualifier {\n\t// Construct mapping of import paths to their defined names.\n\t// It is only necessary to look at renaming imports.\n\timports := make(map[string]string)\n\tfor _, imp := range f.Imports {\n\t\tif imp.Name != nil && imp.Name.Name != \"_\" {\n\t\t\tpath, _ := strconv.Unquote(imp.Path.Value)\n\t\t\timports[path] = imp.Name.Name\n\t\t}\n\t}\n\n\t// Define qualifier to replace full package paths with names of the imports.\n\treturn func(p *types.Package) string {\n\t\tif p == nil || p == pkg {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tif name, ok := imports[p.Path()]; ok {\n\t\t\tif name == \".\" {\n\t\t\t\treturn \"\"\n\t\t\t} else {\n\t\t\t\treturn name\n\t\t\t}\n\t\t}\n\n\t\t// If there is no local renaming, fall back to the package name.\n\t\treturn p.Name()\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/recv.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"go/types\"\n)\n\n// ReceiverNamed returns the named type (if any) associated with the\n// type of recv, which may be of the form N or *N, or aliases thereof.\n// It also reports whether a Pointer was present.\n//\n// The named result may be nil if recv is from a method on an\n// anonymous interface or struct types or in ill-typed code.\nfunc ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {\n\tt := recv.Type()\n\tif ptr, ok := types.Unalias(t).(*types.Pointer); ok {\n\t\tisPtr = true\n\t\tt = ptr.Elem()\n\t}\n\tnamed, _ = types.Unalias(t).(*types.Named)\n\treturn\n}\n\n// Unpointer returns T given *T or an alias thereof.\n// For all other types it is the identity function.\n// It does not look at underlying types.\n// The result may be an alias.\n//\n// Use this function to strip off the optional pointer on a receiver\n// in a field or method selection, without losing the named type\n// (which is needed to compute the method set).\n//\n// See also [typeparams.MustDeref], which removes one level of\n// indirection from the type, regardless of named types (analogous to\n// a LOAD instruction).\nfunc Unpointer(t types.Type) types.Type {\n\tif ptr, ok := types.Unalias(t).(*types.Pointer); ok {\n\t\treturn ptr.Elem()\n\t}\n\treturn t\n}\n"
  },
  {
    "path": "internal/typesinternal/toonew.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/internal/stdlib\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\n// TooNewStdSymbols computes the set of package-level symbols\n// exported by pkg that are not available at the specified version.\n// The result maps each symbol to its minimum version.\n//\n// The pkg is allowed to contain type errors.\nfunc TooNewStdSymbols(pkg *types.Package, version string) map[types.Object]string {\n\tdisallowed := make(map[types.Object]string)\n\n\t// Pass 1: package-level symbols.\n\tsymbols := stdlib.PackageSymbols[pkg.Path()]\n\tfor _, sym := range symbols {\n\t\tsymver := sym.Version.String()\n\t\tif versions.Before(version, symver) {\n\t\t\tswitch sym.Kind {\n\t\t\tcase stdlib.Func, stdlib.Var, stdlib.Const, stdlib.Type:\n\t\t\t\tdisallowed[pkg.Scope().Lookup(sym.Name)] = symver\n\t\t\t}\n\t\t}\n\t}\n\n\t// Pass 2: fields and methods.\n\t//\n\t// We allow fields and methods if their associated type is\n\t// disallowed, as otherwise we would report false positives\n\t// for compatibility shims. Consider:\n\t//\n\t//   //go:build go1.22\n\t//   type T struct { F std.Real } // correct new API\n\t//\n\t//   //go:build !go1.22\n\t//   type T struct { F fake } // shim\n\t//   type fake struct { ... }\n\t//   func (fake) M () {}\n\t//\n\t// These alternative declarations of T use either the std.Real\n\t// type, introduced in go1.22, or a fake type, for the field\n\t// F. (The fakery could be arbitrarily deep, involving more\n\t// nested fields and methods than are shown here.) Clients\n\t// that use the compatibility shim T will compile with any\n\t// version of go, whether older or newer than go1.22, but only\n\t// the newer version will use the std.Real implementation.\n\t//\n\t// Now consider a reference to method M in new(T).F.M() in a\n\t// module that requires a minimum of go1.21. The analysis may\n\t// occur using a version of Go higher than 1.21, selecting the\n\t// first version of T, so the method M is Real.M. This would\n\t// spuriously cause the analyzer to report a reference to a\n\t// too-new symbol even though this expression compiles just\n\t// fine (with the fake implementation) using go1.21.\n\tfor _, sym := range symbols {\n\t\tsymVersion := sym.Version.String()\n\t\tif !versions.Before(version, symVersion) {\n\t\t\tcontinue // allowed\n\t\t}\n\n\t\tvar obj types.Object\n\t\tswitch sym.Kind {\n\t\tcase stdlib.Field:\n\t\t\ttypename, name := sym.SplitField()\n\t\t\tif t := pkg.Scope().Lookup(typename); t != nil && disallowed[t] == \"\" {\n\t\t\t\tobj, _, _ = types.LookupFieldOrMethod(t.Type(), false, pkg, name)\n\t\t\t}\n\n\t\tcase stdlib.Method:\n\t\t\tptr, recvname, name := sym.SplitMethod()\n\t\t\tif t := pkg.Scope().Lookup(recvname); t != nil && disallowed[t] == \"\" {\n\t\t\t\tobj, _, _ = types.LookupFieldOrMethod(t.Type(), ptr, pkg, name)\n\t\t\t}\n\t\t}\n\t\tif obj != nil {\n\t\t\tdisallowed[obj] = symVersion\n\t\t}\n\t}\n\n\treturn disallowed\n}\n"
  },
  {
    "path": "internal/typesinternal/typeindex/typeindex.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typeindex provides an [Index] of type information for a\n// package, allowing efficient lookup of, say, whether a given symbol\n// is referenced and, if so, where from; or of the [inspector.Cursor] for\n// the declaration of a particular [types.Object] symbol.\npackage typeindex\n\nimport (\n\t\"encoding/binary\"\n\t\"go/ast\"\n\t\"go/types\"\n\t\"iter\"\n\n\t\"golang.org/x/tools/go/ast/edge\"\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// New constructs an Index for the package of type-annotated syntax\n//\n// TODO(adonovan): accept a FileSet too?\n// We regret not requiring one in inspector.New.\nfunc New(inspect *inspector.Inspector, pkg *types.Package, info *types.Info) *Index {\n\tix := &Index{\n\t\tinspect:  inspect,\n\t\tinfo:     info,\n\t\tpackages: make(map[string]*types.Package),\n\t\tdef:      make(map[types.Object]inspector.Cursor),\n\t\tuses:     make(map[types.Object]*uses),\n\t}\n\n\taddPackage := func(pkg2 *types.Package) {\n\t\tif pkg2 != nil && pkg2 != pkg {\n\t\t\tix.packages[pkg2.Path()] = pkg2\n\t\t}\n\t}\n\n\tfor cur := range inspect.Root().Preorder((*ast.ImportSpec)(nil), (*ast.Ident)(nil)) {\n\t\tswitch n := cur.Node().(type) {\n\t\tcase *ast.ImportSpec:\n\t\t\t// Index direct imports, including blank ones.\n\t\t\tif pkgname := info.PkgNameOf(n); pkgname != nil {\n\t\t\t\taddPackage(pkgname.Imported())\n\t\t\t}\n\n\t\tcase *ast.Ident:\n\t\t\t// Index all defining and using identifiers.\n\t\t\tif obj := info.Defs[n]; obj != nil {\n\t\t\t\tix.def[obj] = cur\n\t\t\t}\n\n\t\t\tif obj := info.Uses[n]; obj != nil {\n\t\t\t\t// Index indirect dependencies (via fields and methods).\n\t\t\t\tif !typesinternal.IsPackageLevel(obj) {\n\t\t\t\t\taddPackage(obj.Pkg())\n\t\t\t\t}\n\n\t\t\t\tfor {\n\t\t\t\t\tus, ok := ix.uses[obj]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tus = &uses{}\n\t\t\t\t\t\tus.code = us.initial[:0]\n\t\t\t\t\t\tix.uses[obj] = us\n\t\t\t\t\t}\n\t\t\t\t\tdelta := cur.Index() - us.last\n\t\t\t\t\tif delta < 0 {\n\t\t\t\t\t\tpanic(\"non-monotonic\")\n\t\t\t\t\t}\n\t\t\t\t\tus.code = binary.AppendUvarint(us.code, uint64(delta))\n\t\t\t\t\tus.last = cur.Index()\n\n\t\t\t\t\t// If n is a selection of a field or method of an instantiated\n\t\t\t\t\t// type, also record a use of the generic field or method.\n\t\t\t\t\tobj, ok = objectOrigin(obj)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn ix\n}\n\n// objectOrigin returns the generic object for obj if it is a field or\n// method of an instantied type; zero otherwise.\n//\n// (This operation is appropriate only for selections.\n// Lexically resolved references always resolve to the generic.\n// Although Named and Alias types also use Origin to express\n// an instance/generic distinction, that's in the domain\n// of Types; their TypeName objects always refer to the generic.)\nfunc objectOrigin(obj types.Object) (types.Object, bool) {\n\tvar origin types.Object\n\tswitch obj := obj.(type) {\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() != nil {\n\t\t\torigin = obj.Origin() // G[int].method -> G[T].method\n\t\t}\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\torigin = obj.Origin() // G[int].field  -> G[T].field\n\t\t}\n\t}\n\tif origin != nil && origin != obj {\n\t\treturn origin, true\n\t}\n\treturn nil, false\n}\n\n// An Index holds an index mapping [types.Object] symbols to their syntax.\n// In effect, it is the inverse of [types.Info].\ntype Index struct {\n\tinspect  *inspector.Inspector\n\tinfo     *types.Info\n\tpackages map[string]*types.Package         // packages of all symbols referenced from this package\n\tdef      map[types.Object]inspector.Cursor // Cursor of *ast.Ident that defines the Object\n\tuses     map[types.Object]*uses            // Cursors of *ast.Idents that use the Object\n}\n\n// A uses holds the list of Cursors of Idents that use a given symbol.\n//\n// The Uses map of [types.Info] is substantial, so it pays to compress\n// its inverse mapping here, both in space and in CPU due to reduced\n// allocation. A Cursor is 2 words; a Cursor.Index is 4 bytes; but\n// since Cursors are naturally delivered in ascending order, we can\n// use varint-encoded deltas at a cost of only ~1.7-2.2 bytes per use.\n//\n// Many variables have only one or two uses, so their encoded uses may\n// fit in the 4 bytes of initial, saving further CPU and space\n// essentially for free since the struct's size class is 4 words.\ntype uses struct {\n\tcode    []byte  // varint-encoded deltas of successive Cursor.Index values\n\tlast    int32   // most recent Cursor.Index value; used during encoding\n\tinitial [4]byte // use slack in size class as initial space for code\n}\n\n// Uses returns the sequence of Cursors of [*ast.Ident]s in this package\n// that refer to obj. If obj is nil, the sequence is empty.\n//\n// Uses, unlike the Uses field of [types.Info], records additional\n// entries mapping fields and methods of generic types to references\n// through their corresponding instantiated objects.\nfunc (ix *Index) Uses(obj types.Object) iter.Seq[inspector.Cursor] {\n\treturn func(yield func(inspector.Cursor) bool) {\n\t\tif uses := ix.uses[obj]; uses != nil {\n\t\t\tvar last int32\n\t\t\tfor code := uses.code; len(code) > 0; {\n\t\t\t\tdelta, n := binary.Uvarint(code)\n\t\t\t\tlast += int32(delta)\n\t\t\t\tif !yield(ix.inspect.At(last)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcode = code[n:]\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Used reports whether any of the specified objects are used, in\n// other words, obj != nil && Uses(obj) is non-empty for some obj in objs.\n//\n// (This treatment of nil allows Used to be called directly on the\n// result of [Index.Object] so that analyzers can conveniently skip\n// packages that don't use a symbol of interest.)\nfunc (ix *Index) Used(objs ...types.Object) bool {\n\tfor _, obj := range objs {\n\t\tif obj != nil && ix.uses[obj] != nil {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// Def returns the Cursor of the [*ast.Ident] in this package\n// that declares the specified object, if any.\nfunc (ix *Index) Def(obj types.Object) (inspector.Cursor, bool) {\n\tcur, ok := ix.def[obj]\n\treturn cur, ok\n}\n\n// Package returns the package of the specified path,\n// or nil if it is not referenced from this package.\nfunc (ix *Index) Package(path string) *types.Package {\n\treturn ix.packages[path]\n}\n\n// Object returns the package-level symbol name within the package of\n// the specified path, or nil if the package or symbol does not exist\n// or is not visible from this package.\nfunc (ix *Index) Object(path, name string) types.Object {\n\tif pkg := ix.Package(path); pkg != nil {\n\t\treturn pkg.Scope().Lookup(name)\n\t}\n\treturn nil\n}\n\n// Selection returns the named method or field belonging to the\n// package-level type returned by Object(path, typename).\nfunc (ix *Index) Selection(path, typename, name string) types.Object {\n\tif obj := ix.Object(path, typename); obj != nil {\n\t\tif tname, ok := obj.(*types.TypeName); ok {\n\t\t\tobj, _, _ := types.LookupFieldOrMethod(tname.Type(), true, obj.Pkg(), name)\n\t\t\treturn obj\n\t\t}\n\t}\n\treturn nil\n}\n\n// Calls returns the sequence of cursors for *ast.CallExpr nodes that\n// call the specified callee, as defined by [typeutil.Callee].\n// If callee is nil, the sequence is empty.\nfunc (ix *Index) Calls(callee types.Object) iter.Seq[inspector.Cursor] {\n\treturn func(yield func(inspector.Cursor) bool) {\n\t\tfor cur := range ix.Uses(callee) {\n\t\t\tek := cur.ParentEdgeKind()\n\n\t\t\t// The call may be of the form f() or x.f(),\n\t\t\t// optionally with parens; ascend from f to call.\n\t\t\t//\n\t\t\t// It is tempting but wrong to use the first\n\t\t\t// CallExpr ancestor: we have to make sure the\n\t\t\t// ident is in the CallExpr.Fun position, otherwise\n\t\t\t// f(f, f) would have two spurious matches.\n\t\t\t// Avoiding Enclosing is also significantly faster.\n\n\t\t\t// inverse unparen: f -> (f)\n\t\t\tfor ek == edge.ParenExpr_X {\n\t\t\t\tcur = cur.Parent()\n\t\t\t\tek = cur.ParentEdgeKind()\n\t\t\t}\n\n\t\t\t// ascend selector: f -> x.f\n\t\t\tif ek == edge.SelectorExpr_Sel {\n\t\t\t\tcur = cur.Parent()\n\t\t\t\tek = cur.ParentEdgeKind()\n\t\t\t}\n\n\t\t\t// inverse unparen again\n\t\t\tfor ek == edge.ParenExpr_X {\n\t\t\t\tcur = cur.Parent()\n\t\t\t\tek = cur.ParentEdgeKind()\n\t\t\t}\n\n\t\t\t// ascend from f or x.f to call\n\t\t\tif ek == edge.CallExpr_Fun {\n\t\t\t\tcurCall := cur.Parent()\n\t\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\t\tif typeutil.Callee(ix.info, call) == callee {\n\t\t\t\t\tif !yield(curCall) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/typeindex/typeindex_test.go",
    "content": "// Copyright 2025 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typeindex_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/typesinternal/typeindex\"\n)\n\nfunc TestIndex(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\tvar (\n\t\tpkg        = loadNetHTTP(t)\n\t\tinspect    = inspector.New(pkg.Syntax)\n\t\tindex      = typeindex.New(inspect, pkg.Types, pkg.TypesInfo)\n\t\tfmtSprintf = index.Object(\"fmt\", \"Sprintf\")\n\t)\n\n\t// Gather calls and uses of fmt.Sprintf in net/http.\n\tvar (\n\t\twantUses  []*ast.Ident\n\t\twantCalls []*ast.CallExpr\n\t)\n\tfor n := range inspect.PreorderSeq((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {\n\t\tswitch n := n.(type) {\n\t\tcase *ast.CallExpr:\n\t\t\tif typeutil.Callee(pkg.TypesInfo, n) == fmtSprintf {\n\t\t\t\twantCalls = append(wantCalls, n)\n\t\t\t}\n\t\tcase *ast.Ident:\n\t\t\tif pkg.TypesInfo.Uses[n] == fmtSprintf {\n\t\t\t\twantUses = append(wantUses, n)\n\t\t\t}\n\t\t}\n\t}\n\t// sanity check (expect about 60 of each)\n\tif wantUses == nil || wantCalls == nil {\n\t\tt.Fatalf(\"no calls or uses of fmt.Sprintf in net/http\")\n\t}\n\n\tvar (\n\t\tgotUses  []*ast.Ident\n\t\tgotCalls []*ast.CallExpr\n\t)\n\tfor curId := range index.Uses(fmtSprintf) {\n\t\tgotUses = append(gotUses, curId.Node().(*ast.Ident))\n\t}\n\tfor curCall := range index.Calls(fmtSprintf) {\n\t\tgotCalls = append(gotCalls, curCall.Node().(*ast.CallExpr))\n\t}\n\n\tif !slices.Equal(gotUses, wantUses) {\n\t\tt.Errorf(\"index.Uses(fmt.Sprintf) = %v, want %v\", gotUses, wantUses)\n\t}\n\tif !slices.Equal(gotCalls, wantCalls) {\n\t\tt.Errorf(\"index.Calls(fmt.Sprintf) = %v, want %v\", gotCalls, wantCalls)\n\t}\n}\n\nfunc loadNetHTTP(tb testing.TB) *packages.Package {\n\tcfg := &packages.Config{Mode: packages.LoadSyntax}\n\tpkgs, err := packages.Load(cfg, \"net/http\")\n\tif err != nil {\n\t\ttb.Fatal(err)\n\t}\n\treturn pkgs[0]\n}\n\nfunc BenchmarkIndex(b *testing.B) {\n\t// Load net/http, a large package, and find calls to net.Dial.\n\t//\n\t// There is currently exactly one, which provides an extreme\n\t// demonstration of the performance advantage of the Index.\n\t//\n\t// Index construction costs approximately 7x the cursor\n\t// traversal, so it breaks even when it replaces 7 passes.\n\t// The cost of index lookup is approximately zero.\n\tpkg := loadNetHTTP(b)\n\n\t// Build the Inspector (~2.8ms).\n\tvar inspect *inspector.Inspector\n\tb.Run(\"inspector.New\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tinspect = inspector.New(pkg.Syntax)\n\t\t}\n\t})\n\n\t// Build the Index (~6.6ms).\n\tvar index *typeindex.Index\n\tb.Run(\"typeindex.New\", func(b *testing.B) {\n\t\tb.ReportAllocs() // 2.48MB/op\n\t\tfor b.Loop() {\n\t\t\tindex = typeindex.New(inspect, pkg.Types, pkg.TypesInfo)\n\t\t}\n\t})\n\n\ttarget := index.Object(\"net\", \"Dial\")\n\n\tvar countA, countB, countC int\n\n\t// unoptimized inspect implementation (~1.6ms, 1x)\n\tb.Run(\"inspect\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcountA = 0\n\t\t\tfor _, file := range pkg.Syntax {\n\t\t\t\tast.Inspect(file, func(n ast.Node) bool {\n\t\t\t\t\tif call, ok := n.(*ast.CallExpr); ok {\n\t\t\t\t\t\tif typeutil.Callee(pkg.TypesInfo, call) == target {\n\t\t\t\t\t\t\tcountA++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t})\n\tif countA == 0 {\n\t\tb.Errorf(\"target %v not found\", target)\n\t}\n\n\t// unoptimized cursor implementation (~390us, 4x faster)\n\tb.Run(\"cursor\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcountB = 0\n\t\t\tfor curCall := range inspect.Root().Preorder((*ast.CallExpr)(nil)) {\n\t\t\t\tcall := curCall.Node().(*ast.CallExpr)\n\t\t\t\tif typeutil.Callee(pkg.TypesInfo, call) == target {\n\t\t\t\t\tcountB++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\t// indexed implementation (~120ns, >10,000x faster)\n\tb.Run(\"index\", func(b *testing.B) {\n\t\tfor b.Loop() {\n\t\t\tcountC = 0\n\t\t\tfor range index.Calls(target) {\n\t\t\t\tcountC++\n\t\t\t}\n\t\t}\n\t})\n\n\tif countA != countB || countA != countC {\n\t\tb.Fatalf(\"inconsistent results (inspect=%d, cursor=%d, index=%d)\", countA, countB, countC)\n\t}\n}\n\n// TestOrigin checks that index.Uses on field or method of a generic\n// type reports references to its instantiations.\n// Lexical references (to functions, types, and aliases) always\n// resolve to the generic; there is no Origin distinction.\nfunc TestOrigin(t *testing.T) {\n\t// Each nonblank declared name must have at least one use.\n\tfor _, src := range []string{\n\t\t`\npackage alias\ntype A[T any] = *T\nvar _ A[int]`,\n\t\t`\npackage localalias\nfunc _[T any]() {\n\ttype A[U any] = *U\n\tvar _ A[T]\n}`,\n\t\t`\npackage named\ntype Named[_ any] int\nvar _ Named[int]`,\n\t\t`\npackage localnamed\nfunc _[T any]() {\n\ttype N[U any] struct { f U }\n\t_ = N[T]{}.f\n}`,\n\t\t`\npackage field\ntype Named[T any] struct { field T }\nvar _ = Named[int]{}.field`,\n\t\t`\npackage function\nfunc F[T any](T) {}\nvar _ = F[int]`,\n\t\t`\npackage method\ntype Named[_ any] int\nfunc (Named[T]) method(T) {}\nvar _ = Named[int].method`,\n\t\t`\npackage uninstantiatedmethod\ntype Named[_ any] int\nfunc (Named[_]) f() {}\nfunc (Named[T]) g() { Named[T](0).f() }\nfunc (n Named[_]) _() { n.g() }`,\n\t} {\n\t\t// parse\n\t\tfset := token.NewFileSet()\n\t\tf, _ := parser.ParseFile(fset, \"\", src, parser.PackageClauseOnly)\n\t\tt.Run(f.Name.Name, func(t *testing.T) {\n\t\t\tf, _ := parser.ParseFile(fset, \"\", src, 0)\n\t\t\tfiles := []*ast.File{f}\n\n\t\t\t// typecheck\n\t\t\tinfo := &types.Info{\n\t\t\t\tDefs: make(map[*ast.Ident]types.Object),\n\t\t\t\tUses: make(map[*ast.Ident]types.Object),\n\t\t\t}\n\t\t\tpkg, err := new(types.Config).Check(f.Name.Name, fset, files, info)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// index\n\t\t\tvar (\n\t\t\t\tinspect = inspector.New(files)\n\t\t\t\tindex   = typeindex.New(inspect, pkg, info)\n\t\t\t)\n\n\t\t\t// check Def/Uses of all objects\n\t\t\tfor id := range inspect.PreorderSeq((*ast.Ident)(nil)) {\n\t\t\t\tid := id.(*ast.Ident)\n\t\t\t\tif obj := info.Defs[id]; obj != nil && id.Name != \"_\" {\n\t\t\t\t\tt.Logf(\"%T %s @ %s\", obj, id.Name, fset.Position(id.Pos()))\n\n\t\t\t\t\t// check Def\n\t\t\t\t\tif curDef, ok := index.Def(obj); !ok {\n\t\t\t\t\t\tt.Errorf(\"- index.Def missing\")\n\t\t\t\t\t} else if curDef.Node() != id {\n\t\t\t\t\t\tt.Errorf(\"- index.Def wrong: @%s\", fset.Position(curDef.Node().Pos()))\n\t\t\t\t\t}\n\n\t\t\t\t\t// check Uses is nonempty\n\t\t\t\t\tok := false\n\t\t\t\t\tfor use := range index.Uses(obj) {\n\t\t\t\t\t\tt.Logf(\"- index.Use at %s\", fset.Position(use.Node().Pos()))\n\t\t\t\t\t\tok = true\n\t\t\t\t\t}\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"- no index.Uses\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/types.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package typesinternal provides helpful operators for dealing with\n// go/types:\n//\n//   - operators for querying typed syntax trees (e.g. [Imports], [IsFunctionNamed]);\n//   - functions for converting types to strings or syntax (e.g. [TypeExpr], FileQualifier]);\n//   - helpers for working with the [go/types] API (e.g. [NewTypesInfo]);\n//   - access to internal go/types APIs that are not yet\n//     exported (e.g. [SetUsesCgo], [ErrorCodeStartEnd], [VarKind]); and\n//   - common algorithms related to types (e.g. [TooNewStdSymbols]).\n//\n// See also:\n//   - [golang.org/x/tools/internal/astutil], for operations on untyped syntax;\n//   - [golang.org/x/tools/internal/analysisinernal], for helpers for analyzers;\n//   - [golang.org/x/tools/internal/refactor], for operators to compute text edits.\npackage typesinternal\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\n\t\"golang.org/x/tools/go/ast/inspector\"\n)\n\nfunc SetUsesCgo(conf *types.Config) bool {\n\tv := reflect.ValueOf(conf).Elem()\n\n\tf := v.FieldByName(\"go115UsesCgo\")\n\tif !f.IsValid() {\n\t\tf = v.FieldByName(\"UsesCgo\")\n\t\tif !f.IsValid() {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t*(*bool)(f.Addr().UnsafePointer()) = true\n\n\treturn true\n}\n\n// ErrorCodeStartEnd extracts additional information from types.Error values\n// generated by Go version 1.16 and later: the error code, start position, and\n// end position. If all positions are valid, start <= err.Pos <= end.\n//\n// If the data could not be read, the final result parameter will be false.\n//\n// TODO(adonovan): eliminate start/end when proposal #71803 is accepted.\nfunc ErrorCodeStartEnd(err types.Error) (code ErrorCode, start, end token.Pos, ok bool) {\n\tvar data [3]int\n\t// By coincidence all of these fields are ints, which simplifies things.\n\tv := reflect.ValueOf(err)\n\tfor i, name := range []string{\"go116code\", \"go116start\", \"go116end\"} {\n\t\tf := v.FieldByName(name)\n\t\tif !f.IsValid() {\n\t\t\treturn 0, 0, 0, false\n\t\t}\n\t\tdata[i] = int(f.Int())\n\t}\n\treturn ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true\n}\n\n// NameRelativeTo returns a types.Qualifier that qualifies members of\n// all packages other than pkg, using only the package name.\n// (By contrast, [types.RelativeTo] uses the complete package path,\n// which is often excessive.)\n//\n// If pkg is nil, it is equivalent to [*types.Package.Name].\n//\n// TODO(adonovan): all uses of this with TypeString should be\n// eliminated when https://go.dev/issues/75604 is resolved.\nfunc NameRelativeTo(pkg *types.Package) types.Qualifier {\n\treturn func(other *types.Package) string {\n\t\tif pkg != nil && pkg == other {\n\t\t\treturn \"\" // same package; unqualified\n\t\t}\n\t\treturn other.Name()\n\t}\n}\n\n// TypeNameFor returns the type name symbol for the specified type, if\n// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a\n// [*types.Basic] representing a type.\n//\n// For all other types, and for Basic types representing a builtin,\n// constant, or nil, it returns nil. Be careful not to convert the\n// resulting nil pointer to a [types.Object]!\n//\n// If t is the type of a constant, it may be an \"untyped\" type, which\n// has no TypeName. To access the name of such types (e.g. \"untyped\n// int\"), use [types.Basic.Name].\nfunc TypeNameFor(t types.Type) *types.TypeName {\n\tswitch t := t.(type) {\n\tcase *types.Alias:\n\t\treturn t.Obj()\n\tcase *types.Named:\n\t\treturn t.Obj()\n\tcase *types.TypeParam:\n\t\treturn t.Obj()\n\tcase *types.Basic:\n\t\t// See issues #71886 and #66890 for some history.\n\t\tif tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {\n\t\t\treturn tname\n\t\t}\n\t}\n\treturn nil\n}\n\n// A NamedOrAlias is a [types.Type] that is named (as\n// defined by the spec) and capable of bearing type parameters: it\n// abstracts aliases ([types.Alias]) and defined types\n// ([types.Named]).\n//\n// Every type declared by an explicit \"type\" declaration is a\n// NamedOrAlias. (Built-in type symbols may additionally\n// have type [types.Basic], which is not a NamedOrAlias,\n// though the spec regards them as \"named\"; see [TypeNameFor].)\n//\n// NamedOrAlias cannot expose the Origin method, because\n// [types.Alias.Origin] and [types.Named.Origin] have different\n// (covariant) result types; use [Origin] instead.\ntype NamedOrAlias interface {\n\ttypes.Type\n\tObj() *types.TypeName\n\tTypeArgs() *types.TypeList\n\tTypeParams() *types.TypeParamList\n\tSetTypeParams(tparams []*types.TypeParam)\n}\n\nvar (\n\t_ NamedOrAlias = (*types.Alias)(nil)\n\t_ NamedOrAlias = (*types.Named)(nil)\n)\n\n// Origin returns the generic type of the Named or Alias type t if it\n// is instantiated, otherwise it returns t.\nfunc Origin(t NamedOrAlias) NamedOrAlias {\n\tswitch t := t.(type) {\n\tcase *types.Alias:\n\t\treturn t.Origin()\n\tcase *types.Named:\n\t\treturn t.Origin()\n\t}\n\treturn t\n}\n\n// IsPackageLevel reports whether obj is a package-level symbol.\nfunc IsPackageLevel(obj types.Object) bool {\n\treturn obj.Pkg() != nil && obj.Parent() == obj.Pkg().Scope()\n}\n\n// NewTypesInfo returns a *types.Info with all maps populated.\nfunc NewTypesInfo() *types.Info {\n\treturn &types.Info{\n\t\tTypes:        map[ast.Expr]types.TypeAndValue{},\n\t\tInstances:    map[*ast.Ident]types.Instance{},\n\t\tDefs:         map[*ast.Ident]types.Object{},\n\t\tUses:         map[*ast.Ident]types.Object{},\n\t\tImplicits:    map[ast.Node]types.Object{},\n\t\tSelections:   map[*ast.SelectorExpr]*types.Selection{},\n\t\tScopes:       map[ast.Node]*types.Scope{},\n\t\tFileVersions: map[*ast.File]string{},\n\t}\n}\n\n// EnclosingScope returns the innermost block logically enclosing the cursor.\nfunc EnclosingScope(info *types.Info, cur inspector.Cursor) *types.Scope {\n\tfor cur := range cur.Enclosing() {\n\t\tn := cur.Node()\n\t\t// A function's Scope is associated with its FuncType.\n\t\tswitch f := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tn = f.Type\n\t\tcase *ast.FuncLit:\n\t\t\tn = f.Type\n\t\t}\n\t\tif b := info.Scopes[n]; b != nil {\n\t\t\treturn b\n\t\t}\n\t}\n\tpanic(\"no Scope for *ast.File\")\n}\n\n// Imports reports whether path is imported by pkg.\nfunc Imports(pkg *types.Package, path string) bool {\n\tfor _, imp := range pkg.Imports() {\n\t\tif imp.Path() == path {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/typesinternal/varkind.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build go1.25\n\npackage typesinternal\n\nimport \"go/types\"\n\ntype VarKind = types.VarKind\n\nconst (\n\tPackageVar = types.PackageVar\n\tLocalVar   = types.LocalVar\n\tRecvVar    = types.RecvVar\n\tParamVar   = types.ParamVar\n\tResultVar  = types.ResultVar\n\tFieldVar   = types.FieldVar\n)\n\nfunc GetVarKind(v *types.Var) VarKind       { return v.Kind() }\nfunc SetVarKind(v *types.Var, kind VarKind) { v.SetKind(kind) }\n"
  },
  {
    "path": "internal/typesinternal/varkind_go124.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !go1.25\n\npackage typesinternal\n\nimport \"go/types\"\n\ntype VarKind uint8\n\nconst (\n\t_          VarKind = iota // (not meaningful)\n\tPackageVar                // a package-level variable\n\tLocalVar                  // a local variable\n\tRecvVar                   // a method receiver variable\n\tParamVar                  // a function parameter variable\n\tResultVar                 // a function result variable\n\tFieldVar                  // a struct field\n)\n\nfunc (kind VarKind) String() string {\n\treturn [...]string{\n\t\t0:          \"VarKind(0)\",\n\t\tPackageVar: \"PackageVar\",\n\t\tLocalVar:   \"LocalVar\",\n\t\tRecvVar:    \"RecvVar\",\n\t\tParamVar:   \"ParamVar\",\n\t\tResultVar:  \"ResultVar\",\n\t\tFieldVar:   \"FieldVar\",\n\t}[kind]\n}\n\n// GetVarKind returns an invalid VarKind.\nfunc GetVarKind(v *types.Var) VarKind { return 0 }\n\n// SetVarKind has no effect.\nfunc SetVarKind(v *types.Var, kind VarKind) {}\n"
  },
  {
    "path": "internal/typesinternal/zerovalue.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n)\n\n// ZeroString returns the string representation of the zero value for any type t.\n// The boolean result indicates whether the type is or contains an invalid type\n// or a non-basic (constraint) interface type.\n//\n// Even for invalid input types, ZeroString may return a partially correct\n// string representation. The caller should use the returned isValid boolean\n// to determine the validity of the expression.\n//\n// When assigning to a wider type (such as 'any'), it's the caller's\n// responsibility to handle any necessary type conversions.\n//\n// This string can be used on the right-hand side of an assignment where the\n// left-hand side has that explicit type.\n// References to named types are qualified by an appropriate (optional)\n// qualifier function.\n// Exception: This does not apply to tuples. Their string representation is\n// informational only and cannot be used in an assignment.\n//\n// See [ZeroExpr] for a variant that returns an [ast.Expr].\nfunc ZeroString(t types.Type, qual types.Qualifier) (_ string, isValid bool) {\n\tswitch t := t.(type) {\n\tcase *types.Basic:\n\t\tswitch {\n\t\tcase t.Info()&types.IsBoolean != 0:\n\t\t\treturn \"false\", true\n\t\tcase t.Info()&types.IsNumeric != 0:\n\t\t\treturn \"0\", true\n\t\tcase t.Info()&types.IsString != 0:\n\t\t\treturn `\"\"`, true\n\t\tcase t.Kind() == types.UnsafePointer:\n\t\t\tfallthrough\n\t\tcase t.Kind() == types.UntypedNil:\n\t\t\treturn \"nil\", true\n\t\tcase t.Kind() == types.Invalid:\n\t\t\treturn \"invalid\", false\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"ZeroString for unexpected type %v\", t))\n\t\t}\n\n\tcase *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:\n\t\treturn \"nil\", true\n\n\tcase *types.Interface:\n\t\tif !t.IsMethodSet() {\n\t\t\treturn \"invalid\", false\n\t\t}\n\t\treturn \"nil\", true\n\n\tcase *types.Named:\n\t\tswitch under := t.Underlying().(type) {\n\t\tcase *types.Struct, *types.Array:\n\t\t\treturn types.TypeString(t, qual) + \"{}\", true\n\t\tdefault:\n\t\t\treturn ZeroString(under, qual)\n\t\t}\n\n\tcase *types.Alias:\n\t\tswitch t.Underlying().(type) {\n\t\tcase *types.Struct, *types.Array:\n\t\t\treturn types.TypeString(t, qual) + \"{}\", true\n\t\tdefault:\n\t\t\t// A type parameter can have alias but alias type's underlying type\n\t\t\t// can never be a type parameter.\n\t\t\t// Use types.Unalias to preserve the info of type parameter instead\n\t\t\t// of call Underlying() going right through and get the underlying\n\t\t\t// type of the type parameter which is always an interface.\n\t\t\treturn ZeroString(types.Unalias(t), qual)\n\t\t}\n\n\tcase *types.Array, *types.Struct:\n\t\treturn types.TypeString(t, qual) + \"{}\", true\n\n\tcase *types.TypeParam:\n\t\t// Assumes func new is not shadowed.\n\t\treturn \"*new(\" + types.TypeString(t, qual) + \")\", true\n\n\tcase *types.Tuple:\n\t\t// Tuples are not normal values.\n\t\t// We are currently format as \"(t[0], ..., t[n])\". Could be something else.\n\t\tisValid := true\n\t\tcomponents := make([]string, t.Len())\n\t\tfor i := 0; i < t.Len(); i++ {\n\t\t\tcomp, ok := ZeroString(t.At(i).Type(), qual)\n\n\t\t\tcomponents[i] = comp\n\t\t\tisValid = isValid && ok\n\t\t}\n\t\treturn \"(\" + strings.Join(components, \", \") + \")\", isValid\n\n\tcase *types.Union:\n\t\t// Variables of these types cannot be created, so it makes\n\t\t// no sense to ask for their zero value.\n\t\tpanic(fmt.Sprintf(\"invalid type for a variable: %v\", t))\n\n\tdefault:\n\t\tpanic(t) // unreachable.\n\t}\n}\n\n// ZeroExpr returns the ast.Expr representation of the zero value for any type t.\n// The boolean result indicates whether the type is or contains an invalid type\n// or a non-basic (constraint) interface type.\n//\n// Even for invalid input types, ZeroExpr may return a partially correct ast.Expr\n// representation. The caller should use the returned isValid boolean to determine\n// the validity of the expression.\n//\n// This function is designed for types suitable for variables and should not be\n// used with Tuple or Union types.References to named types are qualified by an\n// appropriate (optional) qualifier function.\n//\n// See [ZeroString] for a variant that returns a string.\nfunc ZeroExpr(t types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {\n\tswitch t := t.(type) {\n\tcase *types.Basic:\n\t\tswitch {\n\t\tcase t.Info()&types.IsBoolean != 0:\n\t\t\treturn &ast.Ident{Name: \"false\"}, true\n\t\tcase t.Info()&types.IsNumeric != 0:\n\t\t\treturn &ast.BasicLit{Kind: token.INT, Value: \"0\"}, true\n\t\tcase t.Info()&types.IsString != 0:\n\t\t\treturn &ast.BasicLit{Kind: token.STRING, Value: `\"\"`}, true\n\t\tcase t.Kind() == types.UnsafePointer:\n\t\t\tfallthrough\n\t\tcase t.Kind() == types.UntypedNil:\n\t\t\treturn ast.NewIdent(\"nil\"), true\n\t\tcase t.Kind() == types.Invalid:\n\t\t\treturn &ast.BasicLit{Kind: token.STRING, Value: `\"invalid\"`}, false\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"ZeroExpr for unexpected type %v\", t))\n\t\t}\n\n\tcase *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:\n\t\treturn ast.NewIdent(\"nil\"), true\n\n\tcase *types.Interface:\n\t\tif !t.IsMethodSet() {\n\t\t\treturn &ast.BasicLit{Kind: token.STRING, Value: `\"invalid\"`}, false\n\t\t}\n\t\treturn ast.NewIdent(\"nil\"), true\n\n\tcase *types.Named:\n\t\tswitch under := t.Underlying().(type) {\n\t\tcase *types.Struct, *types.Array:\n\t\t\treturn &ast.CompositeLit{\n\t\t\t\tType: TypeExpr(t, qual),\n\t\t\t}, true\n\t\tdefault:\n\t\t\treturn ZeroExpr(under, qual)\n\t\t}\n\n\tcase *types.Alias:\n\t\tswitch t.Underlying().(type) {\n\t\tcase *types.Struct, *types.Array:\n\t\t\treturn &ast.CompositeLit{\n\t\t\t\tType: TypeExpr(t, qual),\n\t\t\t}, true\n\t\tdefault:\n\t\t\treturn ZeroExpr(types.Unalias(t), qual)\n\t\t}\n\n\tcase *types.Array, *types.Struct:\n\t\treturn &ast.CompositeLit{\n\t\t\tType: TypeExpr(t, qual),\n\t\t}, true\n\n\tcase *types.TypeParam:\n\t\treturn &ast.StarExpr{ // *new(T)\n\t\t\tX: &ast.CallExpr{\n\t\t\t\t// Assumes func new is not shadowed.\n\t\t\t\tFun: ast.NewIdent(\"new\"),\n\t\t\t\tArgs: []ast.Expr{\n\t\t\t\t\tast.NewIdent(t.Obj().Name()),\n\t\t\t\t},\n\t\t\t},\n\t\t}, true\n\n\tcase *types.Tuple:\n\t\t// Unlike ZeroString, there is no ast.Expr can express tuple by\n\t\t// \"(t[0], ..., t[n])\".\n\t\tpanic(fmt.Sprintf(\"invalid type for a variable: %v\", t))\n\n\tcase *types.Union:\n\t\t// Variables of these types cannot be created, so it makes\n\t\t// no sense to ask for their zero value.\n\t\tpanic(fmt.Sprintf(\"invalid type for a variable: %v\", t))\n\n\tdefault:\n\t\tpanic(t) // unreachable.\n\t}\n}\n\n// TypeExpr returns syntax for the specified type. References to named types\n// are qualified by an appropriate (optional) qualifier function.\n// It may panic for types such as Tuple or Union.\n//\n// See also https://go.dev/issues/75604, which will provide a robust\n// Type-to-valid-Go-syntax formatter.\nfunc TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {\n\tswitch t := t.(type) {\n\tcase *types.Basic:\n\t\tswitch t.Kind() {\n\t\tcase types.UnsafePointer:\n\t\t\treturn &ast.SelectorExpr{X: ast.NewIdent(qual(types.NewPackage(\"unsafe\", \"unsafe\"))), Sel: ast.NewIdent(\"Pointer\")}\n\t\tdefault:\n\t\t\treturn ast.NewIdent(t.Name())\n\t\t}\n\n\tcase *types.Pointer:\n\t\treturn &ast.UnaryExpr{\n\t\t\tOp: token.MUL,\n\t\t\tX:  TypeExpr(t.Elem(), qual),\n\t\t}\n\n\tcase *types.Array:\n\t\treturn &ast.ArrayType{\n\t\t\tLen: &ast.BasicLit{\n\t\t\t\tKind:  token.INT,\n\t\t\t\tValue: fmt.Sprintf(\"%d\", t.Len()),\n\t\t\t},\n\t\t\tElt: TypeExpr(t.Elem(), qual),\n\t\t}\n\n\tcase *types.Slice:\n\t\treturn &ast.ArrayType{\n\t\t\tElt: TypeExpr(t.Elem(), qual),\n\t\t}\n\n\tcase *types.Map:\n\t\treturn &ast.MapType{\n\t\t\tKey:   TypeExpr(t.Key(), qual),\n\t\t\tValue: TypeExpr(t.Elem(), qual),\n\t\t}\n\n\tcase *types.Chan:\n\t\tdir := ast.ChanDir(t.Dir())\n\t\tif t.Dir() == types.SendRecv {\n\t\t\tdir = ast.SEND | ast.RECV\n\t\t}\n\t\treturn &ast.ChanType{\n\t\t\tDir:   dir,\n\t\t\tValue: TypeExpr(t.Elem(), qual),\n\t\t}\n\n\tcase *types.Signature:\n\t\tvar params []*ast.Field\n\t\tfor v := range t.Params().Variables() {\n\t\t\tparams = append(params, &ast.Field{\n\t\t\t\tType: TypeExpr(v.Type(), qual),\n\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: v.Name(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\tif t.Variadic() {\n\t\t\tlast := params[len(params)-1]\n\t\t\tlast.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt}\n\t\t}\n\t\tvar returns []*ast.Field\n\t\tfor v := range t.Results().Variables() {\n\t\t\treturns = append(returns, &ast.Field{\n\t\t\t\tType: TypeExpr(v.Type(), qual),\n\t\t\t})\n\t\t}\n\t\treturn &ast.FuncType{\n\t\t\tParams: &ast.FieldList{\n\t\t\t\tList: params,\n\t\t\t},\n\t\t\tResults: &ast.FieldList{\n\t\t\t\tList: returns,\n\t\t\t},\n\t\t}\n\n\tcase *types.TypeParam:\n\t\tpkgName := qual(t.Obj().Pkg())\n\t\tif pkgName == \"\" || t.Obj().Pkg() == nil {\n\t\t\treturn ast.NewIdent(t.Obj().Name())\n\t\t}\n\t\treturn &ast.SelectorExpr{\n\t\t\tX:   ast.NewIdent(pkgName),\n\t\t\tSel: ast.NewIdent(t.Obj().Name()),\n\t\t}\n\n\t// types.TypeParam also implements interface NamedOrAlias. To differentiate,\n\t// case TypeParam need to be present before case NamedOrAlias.\n\t// TODO(hxjiang): remove this comment once TypeArgs() is added to interface\n\t// NamedOrAlias.\n\tcase NamedOrAlias:\n\t\tvar expr ast.Expr = ast.NewIdent(t.Obj().Name())\n\t\tif pkgName := qual(t.Obj().Pkg()); pkgName != \".\" && pkgName != \"\" {\n\t\t\texpr = &ast.SelectorExpr{\n\t\t\t\tX:   ast.NewIdent(pkgName),\n\t\t\t\tSel: expr.(*ast.Ident),\n\t\t\t}\n\t\t}\n\n\t\t// TODO(hxjiang): call t.TypeArgs after adding method TypeArgs() to\n\t\t// typesinternal.NamedOrAlias.\n\t\tif hasTypeArgs, ok := t.(interface{ TypeArgs() *types.TypeList }); ok {\n\t\t\tif typeArgs := hasTypeArgs.TypeArgs(); typeArgs != nil && typeArgs.Len() > 0 {\n\t\t\t\tvar indices []ast.Expr\n\t\t\t\tfor t0 := range typeArgs.Types() {\n\t\t\t\t\tindices = append(indices, TypeExpr(t0, qual))\n\t\t\t\t}\n\t\t\t\texpr = &ast.IndexListExpr{\n\t\t\t\t\tX:       expr,\n\t\t\t\t\tIndices: indices,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn expr\n\n\tcase *types.Struct:\n\t\treturn ast.NewIdent(t.String())\n\n\tcase *types.Interface:\n\t\treturn ast.NewIdent(t.String())\n\n\tcase *types.Union:\n\t\tif t.Len() == 0 {\n\t\t\tpanic(\"Union type should have at least one term\")\n\t\t}\n\t\t// Same as go/ast, the return expression will put last term in the\n\t\t// Y field at topmost level of BinaryExpr.\n\t\t// For union of type \"float32 | float64 | int64\", the structure looks\n\t\t// similar to:\n\t\t// {\n\t\t// \tX: {\n\t\t// \t\tX: float32,\n\t\t// \t\tOp: |\n\t\t// \t\tY: float64,\n\t\t// \t}\n\t\t// \tOp: |,\n\t\t// \tY: int64,\n\t\t// }\n\t\tvar union ast.Expr\n\t\tfor i := range t.Len() {\n\t\t\tterm := t.Term(i)\n\t\t\ttermExpr := TypeExpr(term.Type(), qual)\n\t\t\tif term.Tilde() {\n\t\t\t\ttermExpr = &ast.UnaryExpr{\n\t\t\t\t\tOp: token.TILDE,\n\t\t\t\t\tX:  termExpr,\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i == 0 {\n\t\t\t\tunion = termExpr\n\t\t\t} else {\n\t\t\t\tunion = &ast.BinaryExpr{\n\t\t\t\t\tX:  union,\n\t\t\t\t\tOp: token.OR,\n\t\t\t\t\tY:  termExpr,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn union\n\n\tcase *types.Tuple:\n\t\tpanic(\"invalid input type types.Tuple\")\n\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n"
  },
  {
    "path": "internal/typesinternal/zerovalue_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage typesinternal_test\n\nimport (\n\t\"bytes\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\nfunc TestZeroValue(t *testing.T) {\n\tif testenv.Go1Point() == 23 {\n\t\ttestenv.NeedsGoExperiment(t, \"aliastypeparams\")\n\t}\n\n\t// This test only reference types/functions defined within the same package.\n\t// We can safely drop the package name when encountered.\n\tqual := types.Qualifier(func(p *types.Package) string {\n\t\treturn \"\"\n\t})\n\tsrc := `\npackage main\n\ntype foo struct{\n\tbar string\n}\n\ntype aliasFoo = foo\n\ntype namedInt int\ntype namedString string\ntype namedBool bool\ntype namedPointer *foo\ntype namedSlice []foo\ntype namedInterface interface{ Error() string }\ntype namedChan chan int\ntype namedMap map[string]foo\ntype namedSignature func(string) string\ntype namedStruct struct{ bar string }\ntype namedArray [3]foo\ntype namedAlias aliasFoo\n\ntype aliasInt = int\ntype aliasString = string\ntype aliasBool = bool\ntype aliasPointer = *foo\ntype aliasSlice = []foo\ntype aliasInterface = interface{ Error() string }\ntype aliasChan = chan int\ntype aliasMap = map[string]foo\ntype aliasSignature = func(string) string\ntype aliasStruct = struct{ bar string }\ntype aliasArray = [3]foo\ntype aliasNamed = foo\n\nfunc _[T any]() {\n\ttype aliasTypeParam = T\n\n\ttype aliasWithTypeParam[u any] = struct {\n\t\tx u\n\t\ty T\n\t}\n\ttype aliasWithTypeParams[u, q any] = struct {\n\t\tx u\n\t\ty q\n\t\tz T\n\t}\n\n\ttype namedWithTypeParam[u any] struct {\n\t\tx u\n\t\ty T\n\t}\n\ttype namedWithTypeParams[u, q any] struct{\n\t\tx u\n\t\ty q\n\t\tz T\n\t}\n\tvar (\n\t\t_ int // 0\n\t\t_ bool // false\n\t\t_ string // \"\"\n\n\t\t_ *foo // nil\n\t\t_ []string // nil\n\t\t_ []foo // nil\n\t\t_ interface{ Error() string } // nil\n\t\t_ chan foo // nil\n\t\t_ map[string]foo // nil\n\t\t_ func(string) string // nil\n\n\t\t_ namedInt // 0\n\t\t_ namedString // \"\"\n\t\t_ namedBool // false\n\t\t_ namedSlice // nil\n\t\t_ namedInterface // nil\n\t\t_ namedChan // nil\n\t\t_ namedMap// nil\n\t\t_ namedSignature // nil\n\t\t_ namedStruct // namedStruct{}\n\t\t_ namedArray // namedArray{}\n\t\t_ namedAlias // namedAlias{}\n\n\t\t_ aliasInt // 0\n\t\t_ aliasString // \"\"\n\t\t_ aliasBool // false\n\t\t_ aliasSlice // nil\n\t\t_ aliasInterface // nil\n\t\t_ aliasChan // nil\n\t\t_ aliasMap// nil\n\t\t_ aliasSignature // nil\n\t\t_ aliasStruct // aliasStruct{}\n\t\t_ aliasArray // aliasArray{}\n\t\t_ aliasNamed // aliasNamed{}\n\n\t\t_ [4]string // [4]string{}\n\t\t_ [5]foo // [5]foo{}\n\t\t_ foo // foo{}\n\t\t_ struct{f foo} // struct{f foo}{}\n\n\t\t_ T // *new(T)\n\t\t_ *T // nil\n\n\t\t_ aliasTypeParam // *new(T)\n\t\t_ *aliasTypeParam // nil\n\n\t\t_ aliasWithTypeParam[int] // aliasWithTypeParam[int]{}\n\t\t_ aliasWithTypeParams[int, string] // aliasWithTypeParams[int, string]{}\n\n\t\t_ namedWithTypeParam[int] // namedWithTypeParam[int]{}\n\t\t_ namedWithTypeParams[int, string] // namedWithTypeParams[int, string]{}\n\t)\n}\n`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, parser.ParseComments)\n\tif err != nil {\n\t\tt.Fatalf(\"parse file error %v on file source:\\n%s\\n\", err, src)\n\t}\n\tinfo := &types.Info{\n\t\tTypes: make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:  make(map[*ast.Ident]types.Object),\n\t\tUses:  make(map[*ast.Ident]types.Object),\n\t}\n\tvar conf types.Config\n\tpkg, err := conf.Check(\"\", fset, []*ast.File{f}, info)\n\tif err != nil {\n\t\tt.Fatalf(\"type check error %v on file source:\\n%s\\n\", err, src)\n\t}\n\n\tfun, ok := f.Decls[len(f.Decls)-1].(*ast.FuncDecl)\n\tif !ok {\n\t\tt.Fatalf(\"the last decl of the file is not FuncDecl\")\n\t}\n\n\tdecl, ok := fun.Body.List[len(fun.Body.List)-1].(*ast.DeclStmt).Decl.(*ast.GenDecl)\n\tif !ok {\n\t\tt.Fatalf(\"the last statement of the function is not GenDecl\")\n\t}\n\n\tfor _, spec := range decl.Specs {\n\t\ts, ok := spec.(*ast.ValueSpec)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"%s: got %T, want ValueSpec\", fset.Position(spec.Pos()), spec)\n\t\t}\n\t\twant := strings.TrimSpace(s.Comment.Text())\n\n\t\ttyp := info.TypeOf(s.Type)\n\t\tgot, _ := typesinternal.ZeroString(typ, qual)\n\t\tif got != want {\n\t\t\tt.Errorf(\"%s: ZeroString() = %q, want zero value %q\", fset.Position(spec.Pos()), got, want)\n\t\t}\n\n\t\tzeroExpr, _ := typesinternal.ZeroExpr(typ, typesinternal.FileQualifier(f, pkg))\n\t\tvar bytes bytes.Buffer\n\t\tprinter.Fprint(&bytes, fset, zeroExpr)\n\t\tgot = bytes.String()\n\t\tif got != want {\n\t\t\tt.Errorf(\"%s: ZeroExpr() = %q, want zero value %q\", fset.Position(spec.Pos()), got, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/versions/features.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage versions\n\n// This file contains predicates for working with file versions to\n// decide when a tool should consider a language feature enabled.\n\n// named constants, to avoid misspelling\nconst (\n\tGo1_17 = \"go1.17\"\n\tGo1_18 = \"go1.18\"\n\tGo1_19 = \"go1.19\"\n\tGo1_20 = \"go1.20\"\n\tGo1_21 = \"go1.21\"\n\tGo1_22 = \"go1.22\"\n\tGo1_23 = \"go1.23\"\n\tGo1_24 = \"go1.24\"\n\tGo1_25 = \"go1.25\"\n\tGo1_26 = \"go1.26\"\n)\n\n// Future is an invalid unknown Go version sometime in the future.\n// Do not use directly with Compare.\nconst Future = \"\"\n\n// AtLeast reports whether the file version v comes after a Go release.\n//\n// Use this predicate to enable a behavior once a certain Go release\n// has happened (and stays enabled in the future).\nfunc AtLeast(v, release string) bool {\n\tif v == Future {\n\t\treturn true // an unknown future version is always after y.\n\t}\n\treturn Compare(Lang(v), Lang(release)) >= 0\n}\n\n// Before reports whether the file version v is strictly before a Go release.\n//\n// Use this predicate to disable a behavior once a certain Go release\n// has happened (and stays enabled in the future).\nfunc Before(v, release string) bool {\n\tif v == Future {\n\t\treturn false // an unknown future version happens after y.\n\t}\n\treturn Compare(Lang(v), Lang(release)) < 0\n}\n"
  },
  {
    "path": "internal/versions/gover.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This is a fork of internal/gover for use by x/tools until\n// go1.21 and earlier are no longer supported by x/tools.\n\npackage versions\n\nimport \"strings\"\n\n// A gover is a parsed Go gover: major[.Minor[.Patch]][kind[pre]]\n// The numbers are the original decimal strings to avoid integer overflows\n// and since there is very little actual math. (Probably overflow doesn't matter in practice,\n// but at the time this code was written, there was an existing test that used\n// go1.99999999999, which does not fit in an int on 32-bit platforms.\n// The \"big decimal\" representation avoids the problem entirely.)\ntype gover struct {\n\tmajor string // decimal\n\tminor string // decimal or \"\"\n\tpatch string // decimal or \"\"\n\tkind  string // \"\", \"alpha\", \"beta\", \"rc\"\n\tpre   string // decimal or \"\"\n}\n\n// compare returns -1, 0, or +1 depending on whether\n// x < y, x == y, or x > y, interpreted as toolchain versions.\n// The versions x and y must not begin with a \"go\" prefix: just \"1.21\" not \"go1.21\".\n// Malformed versions compare less than well-formed versions and equal to each other.\n// The language version \"1.21\" compares less than the release candidate and eventual releases \"1.21rc1\" and \"1.21.0\".\nfunc compare(x, y string) int {\n\tvx := parse(x)\n\tvy := parse(y)\n\n\tif c := cmpInt(vx.major, vy.major); c != 0 {\n\t\treturn c\n\t}\n\tif c := cmpInt(vx.minor, vy.minor); c != 0 {\n\t\treturn c\n\t}\n\tif c := cmpInt(vx.patch, vy.patch); c != 0 {\n\t\treturn c\n\t}\n\tif c := strings.Compare(vx.kind, vy.kind); c != 0 { // \"\" < alpha < beta < rc\n\t\treturn c\n\t}\n\tif c := cmpInt(vx.pre, vy.pre); c != 0 {\n\t\treturn c\n\t}\n\treturn 0\n}\n\n// lang returns the Go language version. For example, lang(\"1.2.3\") == \"1.2\".\nfunc lang(x string) string {\n\tv := parse(x)\n\tif v.minor == \"\" || v.major == \"1\" && v.minor == \"0\" {\n\t\treturn v.major\n\t}\n\treturn v.major + \".\" + v.minor\n}\n\n// isValid reports whether the version x is valid.\nfunc isValid(x string) bool {\n\treturn parse(x) != gover{}\n}\n\n// parse parses the Go version string x into a version.\n// It returns the zero version if x is malformed.\nfunc parse(x string) gover {\n\tvar v gover\n\n\t// Parse major version.\n\tvar ok bool\n\tv.major, x, ok = cutInt(x)\n\tif !ok {\n\t\treturn gover{}\n\t}\n\tif x == \"\" {\n\t\t// Interpret \"1\" as \"1.0.0\".\n\t\tv.minor = \"0\"\n\t\tv.patch = \"0\"\n\t\treturn v\n\t}\n\n\t// Parse . before minor version.\n\tif x[0] != '.' {\n\t\treturn gover{}\n\t}\n\n\t// Parse minor version.\n\tv.minor, x, ok = cutInt(x[1:])\n\tif !ok {\n\t\treturn gover{}\n\t}\n\tif x == \"\" {\n\t\t// Patch missing is same as \"0\" for older versions.\n\t\t// Starting in Go 1.21, patch missing is different from explicit .0.\n\t\tif cmpInt(v.minor, \"21\") < 0 {\n\t\t\tv.patch = \"0\"\n\t\t}\n\t\treturn v\n\t}\n\n\t// Parse patch if present.\n\tif x[0] == '.' {\n\t\tv.patch, x, ok = cutInt(x[1:])\n\t\tif !ok || x != \"\" {\n\t\t\t// Note that we are disallowing prereleases (alpha, beta, rc) for patch releases here (x != \"\").\n\t\t\t// Allowing them would be a bit confusing because we already have:\n\t\t\t//\t1.21 < 1.21rc1\n\t\t\t// But a prerelease of a patch would have the opposite effect:\n\t\t\t//\t1.21.3rc1 < 1.21.3\n\t\t\t// We've never needed them before, so let's not start now.\n\t\t\treturn gover{}\n\t\t}\n\t\treturn v\n\t}\n\n\t// Parse prerelease.\n\ti := 0\n\tfor i < len(x) && (x[i] < '0' || '9' < x[i]) {\n\t\tif x[i] < 'a' || 'z' < x[i] {\n\t\t\treturn gover{}\n\t\t}\n\t\ti++\n\t}\n\tif i == 0 {\n\t\treturn gover{}\n\t}\n\tv.kind, x = x[:i], x[i:]\n\tif x == \"\" {\n\t\treturn v\n\t}\n\tv.pre, x, ok = cutInt(x)\n\tif !ok || x != \"\" {\n\t\treturn gover{}\n\t}\n\n\treturn v\n}\n\n// cutInt scans the leading decimal number at the start of x to an integer\n// and returns that value and the rest of the string.\nfunc cutInt(x string) (n, rest string, ok bool) {\n\ti := 0\n\tfor i < len(x) && '0' <= x[i] && x[i] <= '9' {\n\t\ti++\n\t}\n\tif i == 0 || x[0] == '0' && i != 1 { // no digits or unnecessary leading zero\n\t\treturn \"\", \"\", false\n\t}\n\treturn x[:i], x[i:], true\n}\n\n// cmpInt returns cmp.Compare(x, y) interpreting x and y as decimal numbers.\n// (Copied from golang.org/x/mod/semver's compareInt.)\nfunc cmpInt(x, y string) int {\n\tif x == y {\n\t\treturn 0\n\t}\n\tif len(x) < len(y) {\n\t\treturn -1\n\t}\n\tif len(x) > len(y) {\n\t\treturn +1\n\t}\n\tif x < y {\n\t\treturn -1\n\t} else {\n\t\treturn +1\n\t}\n}\n"
  },
  {
    "path": "internal/versions/types.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage versions\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n)\n\n// FileVersion returns a file's Go version.\n// The reported version is an unknown Future version if a\n// version cannot be determined.\nfunc FileVersion(info *types.Info, file *ast.File) string {\n\t// In tools built with Go >= 1.22, the Go version of a file\n\t// follow a cascades of sources:\n\t// 1) types.Info.FileVersion, which follows the cascade:\n\t//   1.a) file version (ast.File.GoVersion),\n\t//   1.b) the package version (types.Config.GoVersion), or\n\t// 2) is some unknown Future version.\n\t//\n\t// File versions require a valid package version to be provided to types\n\t// in Config.GoVersion. Config.GoVersion is either from the package's module\n\t// or the toolchain (go run). This value should be provided by go/packages\n\t// or unitchecker.Config.GoVersion.\n\tif v := info.FileVersions[file]; IsValid(v) {\n\t\treturn v\n\t}\n\t// Note: we could instead return runtime.Version() [if valid].\n\t// This would act as a max version on what a tool can support.\n\treturn Future\n}\n"
  },
  {
    "path": "internal/versions/types_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage versions_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nvar contents = map[string]string{\n\t\"gobuild122.go\": `\n//go:build go1.22\npackage p\n`,\n\t\"gobuild121.go\": `\n//go:build go1.21\npackage p\n`,\n\t\"gobuild120.go\": `\n//go:build go1.20\npackage p\n`,\n\t\"gobuild119.go\": `\n//go:build go1.19\npackage p\n`,\n\t\"noversion.go\": `\npackage p\n`,\n}\n\nfunc Test(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23) // TODO(#69749): Allow on 1.22 if a fix for #69749 is submitted.\n\n\tfor _, item := range []struct {\n\t\tgoversion string\n\t\tpversion  string\n\t\ttests     []fileTest\n\t}{\n\t\t{\n\t\t\t\"\", \"\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild120.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t\t{\n\t\t\t\"go1.20\", \"go1.20\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.20\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild120.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t\t{\n\t\t\t\"go1.21\", \"go1.21\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild120.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t\t{\n\t\t\t\"go1.22\", \"go1.22\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.22\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild120.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t} {\n\t\tname := fmt.Sprintf(\"types.Config{GoVersion:%q}\", item.goversion)\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\ttestFiles(t, item.goversion, item.pversion, item.tests)\n\t\t})\n\t}\n}\n\nfunc TestToolchain122(t *testing.T) {\n\t// TestToolchain122 tests the 1.22 toolchain for the FileVersion it returns.\n\t// These results are at the moment unique to 1.22. So test it with distinct\n\t// expectations.\n\n\t// TODO(#69749): Remove requirement if a fix for #69749 is submitted.\n\tif testenv.Go1Point() != 22 {\n\t\tt.Skip(\"Expectations are only for 1.22 toolchain\")\n\t}\n\n\tfor _, item := range []struct {\n\t\tgoversion string\n\t\tpversion  string\n\t\ttests     []fileTest\n\t}{\n\t\t{\n\t\t\t\"\", \"\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"\"},\n\t\t\t\t{\"gobuild119.go\", \"\"},  // differs\n\t\t\t\t{\"gobuild120.go\", \"\"},  // differs\n\t\t\t\t{\"gobuild121.go\", \"\"},  // differs\n\t\t\t\t{\"gobuild122.go\", \"\"}}, // differs\n\t\t},\n\t\t{\n\t\t\t\"go1.20\", \"go1.20\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.20\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.20\"}, // differs\n\t\t\t\t{\"gobuild120.go\", \"go1.20\"}, // differs\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t\t{\n\t\t\t\"go1.21\", \"go1.21\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.19\"}, // differs\n\t\t\t\t{\"gobuild120.go\", \"go1.20\"}, // differs\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t\t{\n\t\t\t\"go1.22\", \"go1.22\", []fileTest{\n\t\t\t\t{\"noversion.go\", \"go1.22\"},\n\t\t\t\t{\"gobuild119.go\", \"go1.19\"}, // differs\n\t\t\t\t{\"gobuild120.go\", \"go1.20\"}, // differs\n\t\t\t\t{\"gobuild121.go\", \"go1.21\"},\n\t\t\t\t{\"gobuild122.go\", \"go1.22\"}},\n\t\t},\n\t} {\n\t\tname := fmt.Sprintf(\"types.Config{GoVersion:%q}\", item.goversion)\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\ttestFiles(t, item.goversion, item.pversion, item.tests)\n\t\t})\n\t}\n}\n\ntype fileTest struct {\n\tfname string\n\twant  string\n}\n\nfunc testFiles(t *testing.T, goversion string, pversion string, tests []fileTest) {\n\n\tfset := token.NewFileSet()\n\tfiles := make([]*ast.File, len(tests))\n\tfor i, test := range tests {\n\t\tfiles[i] = parse(t, fset, test.fname, contents[test.fname])\n\t}\n\tpkg, info, err := typeCheck(fset, files, goversion)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := pkg.GoVersion(), pversion; versions.Compare(got, want) != 0 {\n\t\tt.Errorf(\"GoVersion()=%q. expected %q\", got, want)\n\t}\n\tif got := versions.FileVersion(info, nil); got != \"\" {\n\t\tt.Errorf(`FileVersions(nil)=%q. expected \"\"`, got)\n\t}\n\tfor i, test := range tests {\n\t\tif got, want := versions.FileVersion(info, files[i]), test.want; got != want {\n\t\t\tt.Errorf(\"FileVersions(%s)=%q. expected %q\", test.fname, got, want)\n\t\t}\n\t}\n}\n\nfunc TestTooNew(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 23) // TODO(#69749): Allow on 1.22 if a fix for #69749 is submitted.\n\n\tconst contents = `\n\t//go:build go1.99\n\tpackage p\n\t`\n\n\tfor _, goversion := range []string{\n\t\t\"\",\n\t\t\"go1.22\",\n\t} {\n\t\tname := fmt.Sprintf(\"types.Config{GoVersion:%q}\", goversion)\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tfset := token.NewFileSet()\n\t\t\tfiles := []*ast.File{parse(t, fset, \"p.go\", contents)}\n\t\t\t_, _, err := typeCheck(fset, files, goversion)\n\t\t\tif err == nil {\n\t\t\t\tt.Fatal(\"Expected an error from a using a TooNew file version\")\n\t\t\t}\n\t\t\tgot := err.Error()\n\t\t\twant := \"file requires newer Go version go1.99\"\n\t\t\tif !strings.Contains(got, want) {\n\t\t\t\tt.Errorf(\"Error message %q did not include %q\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc parse(t *testing.T, fset *token.FileSet, name, src string) *ast.File {\n\tfile, err := parser.ParseFile(fset, name, src, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn file\n}\n\nfunc typeCheck(fset *token.FileSet, files []*ast.File, goversion string) (*types.Package, *types.Info, error) {\n\tconf := types.Config{\n\t\tImporter:  importer.Default(),\n\t\tGoVersion: goversion,\n\t}\n\tinfo := types.Info{\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\tpkg, err := conf.Check(\"\", fset, files, &info)\n\treturn pkg, &info, err\n}\n"
  },
  {
    "path": "internal/versions/versions.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage versions\n\nimport (\n\t\"strings\"\n)\n\n// Note: If we use build tags to use go/versions when go >=1.22,\n// we run into go.dev/issue/53737. Under some operations users would see an\n// import of \"go/versions\" even if they would not compile the file.\n// For example, during `go get -u ./...` (go.dev/issue/64490) we do not try to include\n// For this reason, this library just a clone of go/versions for the moment.\n\n// Lang returns the Go language version for version x.\n// If x is not a valid version, Lang returns the empty string.\n// For example:\n//\n//\tLang(\"go1.21rc2\") = \"go1.21\"\n//\tLang(\"go1.21.2\") = \"go1.21\"\n//\tLang(\"go1.21\") = \"go1.21\"\n//\tLang(\"go1\") = \"go1\"\n//\tLang(\"bad\") = \"\"\n//\tLang(\"1.21\") = \"\"\nfunc Lang(x string) string {\n\tv := lang(stripGo(x))\n\tif v == \"\" {\n\t\treturn \"\"\n\t}\n\treturn x[:2+len(v)] // \"go\"+v without allocation\n}\n\n// Compare returns -1, 0, or +1 depending on whether\n// x < y, x == y, or x > y, interpreted as Go versions.\n// The versions x and y must begin with a \"go\" prefix: \"go1.21\" not \"1.21\".\n// Invalid versions, including the empty string, compare less than\n// valid versions and equal to each other.\n// The language version \"go1.21\" compares less than the\n// release candidate and eventual releases \"go1.21rc1\" and \"go1.21.0\".\n// Custom toolchain suffixes are ignored during comparison:\n// \"go1.21.0\" and \"go1.21.0-bigcorp\" are equal.\nfunc Compare(x, y string) int { return compare(stripGo(x), stripGo(y)) }\n\n// IsValid reports whether the version x is valid.\nfunc IsValid(x string) bool { return isValid(stripGo(x)) }\n\n// stripGo converts from a \"go1.21\" version to a \"1.21\" version.\n// If v does not start with \"go\", stripGo returns the empty string (a known invalid version).\nfunc stripGo(v string) string {\n\tv, _, _ = strings.Cut(v, \"-\") // strip -bigcorp suffix.\n\tif len(v) < 2 || v[:2] != \"go\" {\n\t\treturn \"\"\n\t}\n\treturn v[2:]\n}\n"
  },
  {
    "path": "internal/versions/versions_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage versions_test\n\nimport (\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/versions\"\n)\n\nfunc TestIsValid(t *testing.T) {\n\t// valid versions\n\tfor _, x := range []string{\n\t\t\"go1.21\",\n\t\t\"go1.21.2\",\n\t\t\"go1.21rc\",\n\t\t\"go1.21rc2\",\n\t\t\"go0.0\", // ??\n\t\t\"go1\",\n\t\t\"go2\",\n\t\t\"go1.20.0-bigcorp\",\n\t} {\n\t\tif !versions.IsValid(x) {\n\t\t\tt.Errorf(\"expected versions.IsValid(%q) to hold\", x)\n\t\t}\n\t}\n\n\t// invalid versions\n\tfor _, x := range []string{\n\t\t\"\",\n\t\t\"bad\",\n\t\t\"1.21\",\n\t\t\"v1.21\",\n\t\t\"go\",\n\t\t\"goAA\",\n\t\t\"go2_3\",\n\t\t\"go1.BB\",\n\t\t\"go1.21.\",\n\t\t\"go1.21.2_2\",\n\t\t\"go1.21rc_2\",\n\t\t\"go1.21rc2_\",\n\t\t\"go1.600+auto\",\n\t} {\n\t\tif versions.IsValid(x) {\n\t\t\tt.Errorf(\"expected versions.IsValid(%q) to not hold\", x)\n\t\t}\n\t}\n}\n\nfunc TestVersionComparisons(t *testing.T) {\n\tfor _, item := range []struct {\n\t\tx, y string\n\t\twant int\n\t}{\n\t\t// All comparisons of go2, go1.21.2, go1.21rc2, go1.21rc, go1, go0.0, \"\", bad\n\t\t{\"go2\", \"go2\", 0},\n\t\t{\"go2\", \"go1.21.2\", +1},\n\t\t{\"go2\", \"go1.21rc2\", +1},\n\t\t{\"go2\", \"go1.21rc\", +1},\n\t\t{\"go2\", \"go1.21\", +1},\n\t\t{\"go2\", \"go1\", +1},\n\t\t{\"go2\", \"go0.0\", +1},\n\t\t{\"go2\", \"\", +1},\n\t\t{\"go2\", \"bad\", +1},\n\t\t{\"go1.21.2\", \"go1.21.2\", 0},\n\t\t{\"go1.21.2\", \"go1.21rc2\", +1},\n\t\t{\"go1.21.2\", \"go1.21rc\", +1},\n\t\t{\"go1.21.2\", \"go1.21\", +1},\n\t\t{\"go1.21.2\", \"go1\", +1},\n\t\t{\"go1.21.2\", \"go0.0\", +1},\n\t\t{\"go1.21.2\", \"\", +1},\n\t\t{\"go1.21.2\", \"bad\", +1},\n\t\t{\"go1.21rc2\", \"go1.21rc2\", 0},\n\t\t{\"go1.21rc2\", \"go1.21rc\", +1},\n\t\t{\"go1.21rc2\", \"go1.21\", +1},\n\t\t{\"go1.21rc2\", \"go1\", +1},\n\t\t{\"go1.21rc2\", \"go0.0\", +1},\n\t\t{\"go1.21rc2\", \"\", +1},\n\t\t{\"go1.21rc2\", \"bad\", +1},\n\t\t{\"go1.21rc\", \"go1.21rc\", 0},\n\t\t{\"go1.21rc\", \"go1.21\", +1},\n\t\t{\"go1.21rc\", \"go1\", +1},\n\t\t{\"go1.21rc\", \"go0.0\", +1},\n\t\t{\"go1.21rc\", \"\", +1},\n\t\t{\"go1.21rc\", \"bad\", +1},\n\t\t{\"go1.21\", \"go1.21\", 0},\n\t\t{\"go1.21\", \"go1\", +1},\n\t\t{\"go1.21\", \"go0.0\", +1},\n\t\t{\"go1.21\", \"\", +1},\n\t\t{\"go1.21\", \"bad\", +1},\n\t\t{\"go1\", \"go1\", 0},\n\t\t{\"go1\", \"go0.0\", +1},\n\t\t{\"go1\", \"\", +1},\n\t\t{\"go1\", \"bad\", +1},\n\t\t{\"go0.0\", \"go0.0\", 0},\n\t\t{\"go0.0\", \"\", +1},\n\t\t{\"go0.0\", \"bad\", +1},\n\t\t{\"\", \"\", 0},\n\t\t{\"\", \"bad\", 0},\n\t\t{\"bad\", \"bad\", 0},\n\t\t// Other tests.\n\t\t{\"go1.20\", \"go1.20.0-bigcorp\", 0},\n\t\t{\"go1.21\", \"go1.21.0-bigcorp\", -1},  // Starting in Go 1.21, patch missing is different from explicit .0.\n\t\t{\"go1.21.0\", \"go1.21.0-bigcorp\", 0}, // Starting in Go 1.21, patch missing is different from explicit .0.\n\t\t{\"go1.19rc1\", \"go1.19\", -1},\n\t} {\n\t\tgot := versions.Compare(item.x, item.y)\n\t\tif got != item.want {\n\t\t\tt.Errorf(\"versions.Compare(%q, %q)=%d. expected %d\", item.x, item.y, got, item.want)\n\t\t}\n\t\treverse := versions.Compare(item.y, item.x)\n\t\tif reverse != -got {\n\t\t\tt.Errorf(\"versions.Compare(%q, %q)=%d. expected %d\", item.y, item.x, reverse, -got)\n\t\t}\n\t}\n}\n\nfunc TestLang(t *testing.T) {\n\tfor _, item := range []struct {\n\t\tx    string\n\t\twant string\n\t}{\n\t\t// valid\n\t\t{\"go1.21rc2\", \"go1.21\"},\n\t\t{\"go1.21.2\", \"go1.21\"},\n\t\t{\"go1.21\", \"go1.21\"},\n\t\t{\"go1\", \"go1\"},\n\t\t// invalid\n\t\t{\"bad\", \"\"},\n\t\t{\"1.21\", \"\"},\n\t} {\n\t\tif got := versions.Lang(item.x); got != item.want {\n\t\t\tt.Errorf(\"versions.Lang(%q)=%q. expected %q\", item.x, got, item.want)\n\t\t}\n\t}\n\n}\n\nfunc TestKnown(t *testing.T) {\n\tfor _, v := range [...]string{\n\t\tversions.Go1_18,\n\t\tversions.Go1_19,\n\t\tversions.Go1_20,\n\t\tversions.Go1_21,\n\t\tversions.Go1_22,\n\t} {\n\t\tif !versions.IsValid(v) {\n\t\t\tt.Errorf(\"Expected known version %q to be valid.\", v)\n\t\t}\n\t\tif v != versions.Lang(v) {\n\t\t\tt.Errorf(\"Expected known version %q == Lang(%q).\", v, versions.Lang(v))\n\t\t}\n\t}\n}\n\nfunc TestAtLeast(t *testing.T) {\n\tfor _, item := range [...]struct {\n\t\tv, release string\n\t\twant       bool\n\t}{\n\t\t{versions.Future, versions.Go1_22, true},\n\t\t{versions.Go1_22, versions.Go1_22, true},\n\t\t{\"go1.21\", versions.Go1_22, false},\n\t\t{\"invalid\", versions.Go1_22, false},\n\t} {\n\t\tif got := versions.AtLeast(item.v, item.release); got != item.want {\n\t\t\tt.Errorf(\"AtLeast(%q, %q)=%v. wanted %v\", item.v, item.release, got, item.want)\n\t\t}\n\t}\n}\n\nfunc TestBefore(t *testing.T) {\n\tfor _, item := range [...]struct {\n\t\tv, release string\n\t\twant       bool\n\t}{\n\t\t{versions.Future, versions.Go1_22, false},\n\t\t{versions.Go1_22, versions.Go1_22, false},\n\t\t{\"go1.21\", versions.Go1_22, true},\n\t\t{\"invalid\", versions.Go1_22, true}, // invalid < Go1_22\n\t} {\n\t\tif got := versions.Before(item.v, item.release); got != item.want {\n\t\t\tt.Errorf(\"Before(%q, %q)=%v. wanted %v\", item.v, item.release, got, item.want)\n\t\t}\n\t}\n}\n\nfunc TestFileVersions(t *testing.T) {\n\tconst source = `\n\tpackage P\n\t`\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"hello.go\", source, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor _, conf := range []types.Config{\n\t\t{GoVersion: versions.Go1_22},\n\t\t{}, // GoVersion is unset.\n\t} {\n\t\tinfo := &types.Info{\n\t\t\tFileVersions: make(map[*ast.File]string),\n\t\t}\n\n\t\t_, err = conf.Check(\"P\", fset, []*ast.File{f}, info)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tv := versions.FileVersion(info, f)\n\t\tif !versions.AtLeast(v, versions.Go1_22) {\n\t\t\tt.Errorf(\"versions.AtLeast(%q, %q) expected to hold\", v, versions.Go1_22)\n\t\t}\n\n\t\tif versions.Before(v, versions.Go1_22) {\n\t\t\tt.Errorf(\"versions.AtLeast(%q, %q) expected to be false\", v, versions.Go1_22)\n\t\t}\n\n\t\tif conf.GoVersion == \"\" && v != versions.Future {\n\t\t\tt.Error(\"Expected the FileVersion to be the Future when conf.GoVersion is unset\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/xcontext/xcontext.go",
    "content": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package xcontext is a package to offer the extra functionality we need\n// from contexts that is not available from the standard context package.\npackage xcontext\n\nimport (\n\t\"context\"\n\t\"time\"\n)\n\n// Detach returns a context that keeps all the values of its parent context\n// but detaches from the cancellation and error handling.\nfunc Detach(ctx context.Context) context.Context { return detachedContext{ctx} }\n\ntype detachedContext struct{ parent context.Context }\n\nfunc (v detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false }\nfunc (v detachedContext) Done() <-chan struct{}       { return nil }\nfunc (v detachedContext) Err() error                  { return nil }\nfunc (v detachedContext) Value(key any) any           { return v.parent.Value(key) }\n"
  },
  {
    "path": "playground/playground.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package playground registers an HTTP handler at \"/compile\" that\n// proxies requests to the golang.org playground service.\n// This package may be used unaltered on App Engine Standard with Go 1.11+ runtime.\npackage playground // import \"golang.org/x/tools/playground\"\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n)\n\nconst baseURL = \"https://play.golang.org\"\n\nfunc init() {\n\thttp.Handle(\"/compile\", Proxy())\n}\n\n// Proxy returns a handler that can be registered on /compile to proxy requests to the Go playground.\n//\n// This package already contains a func init that does:\n//\n//\tfunc init() {\n//\t\thttp.Handle(\"/compile\", Proxy())\n//\t}\n//\n// Proxy may be useful for servers that use HTTP muxes other than the default mux.\nfunc Proxy() http.Handler {\n\treturn http.HandlerFunc(bounce)\n}\n\nfunc bounce(w http.ResponseWriter, r *http.Request) {\n\tb := new(bytes.Buffer)\n\tif err := passThru(b, r); err != nil {\n\t\thttp.Error(w, \"500 Internal Server Error\", http.StatusInternalServerError)\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\tio.Copy(w, b)\n}\n\nfunc passThru(w io.Writer, req *http.Request) error {\n\tdefer req.Body.Close()\n\turl := baseURL + req.URL.Path\n\tctx, cancel := context.WithTimeout(req.Context(), 60*time.Second)\n\tdefer cancel()\n\tr, err := post(ctx, url, req.Header.Get(\"Content-Type\"), req.Body)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"making POST request: %v\", err)\n\t}\n\tdefer r.Body.Close()\n\tif _, err := io.Copy(w, r.Body); err != nil {\n\t\treturn fmt.Errorf(\"copying response Body: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error) {\n\treq, err := http.NewRequest(http.MethodPost, url, body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http.NewRequest: %v\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", contentType)\n\treturn http.DefaultClient.Do(req.WithContext(ctx))\n}\n"
  },
  {
    "path": "playground/socket/socket.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !appengine\n\n// Package socket implements a WebSocket-based playground backend.\n// Clients connect to a websocket handler and send run/kill commands, and\n// the server sends the output and exit status of the running processes.\n// Multiple clients running multiple processes may be served concurrently.\n// The wire format is JSON and is described by the Message type.\n//\n// This will not run on App Engine as WebSockets are not supported there.\npackage socket // import \"golang.org/x/tools/playground/socket\"\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"io\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/net/websocket\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// RunScripts specifies whether the socket handler should execute shell scripts\n// (snippets that start with a shebang).\nvar RunScripts = true\n\n// Environ provides an environment when a binary, such as the go tool, is\n// invoked.\nvar Environ func() []string = os.Environ\n\nconst (\n\t// The maximum number of messages to send per session (avoid flooding).\n\tmsgLimit = 1000\n\n\t// Batch messages sent in this interval and send as a single message.\n\tmsgDelay = 10 * time.Millisecond\n)\n\n// Message is the wire format for the websocket connection to the browser.\n// It is used for both sending output messages and receiving commands, as\n// distinguished by the Kind field.\ntype Message struct {\n\tId      string // client-provided unique id for the process\n\tKind    string // in: \"run\", \"kill\" out: \"stdout\", \"stderr\", \"end\"\n\tBody    string\n\tOptions *Options `json:\",omitempty\"`\n}\n\n// Options specify additional message options.\ntype Options struct {\n\tRace bool // use -race flag when building code (for \"run\" only)\n}\n\n// NewHandler returns a websocket server which checks the origin of requests.\nfunc NewHandler(origin *url.URL) websocket.Server {\n\treturn websocket.Server{\n\t\tConfig:    websocket.Config{Origin: origin},\n\t\tHandshake: handshake,\n\t\tHandler:   websocket.Handler(socketHandler),\n\t}\n}\n\n// handshake checks the origin of a request during the websocket handshake.\nfunc handshake(c *websocket.Config, req *http.Request) error {\n\to, err := websocket.Origin(c, req)\n\tif err != nil {\n\t\tlog.Println(\"bad websocket origin:\", err)\n\t\treturn websocket.ErrBadWebSocketOrigin\n\t}\n\t_, port, err := net.SplitHostPort(c.Origin.Host)\n\tif err != nil {\n\t\tlog.Println(\"bad websocket origin:\", err)\n\t\treturn websocket.ErrBadWebSocketOrigin\n\t}\n\tok := c.Origin.Scheme == o.Scheme && (c.Origin.Host == o.Host || c.Origin.Host == net.JoinHostPort(o.Host, port))\n\tif !ok {\n\t\tlog.Println(\"bad websocket origin:\", o)\n\t\treturn websocket.ErrBadWebSocketOrigin\n\t}\n\tlog.Println(\"accepting connection from:\", req.RemoteAddr)\n\treturn nil\n}\n\n// socketHandler handles the websocket connection for a given present session.\n// It handles transcoding Messages to and from JSON format, and starting\n// and killing processes.\nfunc socketHandler(c *websocket.Conn) {\n\tin, out := make(chan *Message), make(chan *Message)\n\terrc := make(chan error, 1)\n\n\t// Decode messages from client and send to the in channel.\n\tgo func() {\n\t\tdec := json.NewDecoder(c)\n\t\tfor {\n\t\t\tvar m Message\n\t\t\tif err := dec.Decode(&m); err != nil {\n\t\t\t\terrc <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tin <- &m\n\t\t}\n\t}()\n\n\t// Receive messages from the out channel and encode to the client.\n\tgo func() {\n\t\tenc := json.NewEncoder(c)\n\t\tfor m := range out {\n\t\t\tif err := enc.Encode(m); err != nil {\n\t\t\t\terrc <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\tdefer close(out)\n\n\t// Start and kill processes and handle errors.\n\tproc := make(map[string]*process)\n\tfor {\n\t\tselect {\n\t\tcase m := <-in:\n\t\t\tswitch m.Kind {\n\t\t\tcase \"run\":\n\t\t\t\tlog.Println(\"running snippet from:\", c.Request().RemoteAddr)\n\t\t\t\tproc[m.Id].Kill()\n\t\t\t\tproc[m.Id] = startProcess(m.Id, m.Body, out, m.Options)\n\t\t\tcase \"kill\":\n\t\t\t\tproc[m.Id].Kill()\n\t\t\t}\n\t\tcase err := <-errc:\n\t\t\tif err != io.EOF {\n\t\t\t\t// A encode or decode has failed; bail.\n\t\t\t\tlog.Println(err)\n\t\t\t}\n\t\t\t// Shut down any running processes.\n\t\t\tfor _, p := range proc {\n\t\t\t\tp.Kill()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// process represents a running process.\ntype process struct {\n\tout  chan<- *Message\n\tdone chan struct{} // closed when wait completes\n\trun  *exec.Cmd\n\tpath string\n}\n\n// startProcess builds and runs the given program, sending its output\n// and end event as Messages on the provided channel.\nfunc startProcess(id, body string, dest chan<- *Message, opt *Options) *process {\n\tvar (\n\t\tdone = make(chan struct{})\n\t\tout  = make(chan *Message)\n\t\tp    = &process{out: out, done: done}\n\t)\n\tgo func() {\n\t\tdefer close(done)\n\t\tfor m := range buffer(limiter(out, p), time.After) {\n\t\t\tm.Id = id\n\t\t\tdest <- m\n\t\t}\n\t}()\n\tvar err error\n\tif path, args := shebang(body); path != \"\" {\n\t\tif RunScripts {\n\t\t\terr = p.startProcess(path, args, body)\n\t\t} else {\n\t\t\terr = errors.New(\"script execution is not allowed\")\n\t\t}\n\t} else {\n\t\terr = p.start(body, opt)\n\t}\n\tif err != nil {\n\t\tp.end(err)\n\t\treturn nil\n\t}\n\tgo func() {\n\t\tp.end(p.run.Wait())\n\t}()\n\treturn p\n}\n\n// end sends an \"end\" message to the client, containing the process id and the\n// given error value. It also removes the binary, if present.\nfunc (p *process) end(err error) {\n\tif p.path != \"\" {\n\t\tdefer os.RemoveAll(p.path)\n\t}\n\tm := &Message{Kind: \"end\"}\n\tif err != nil {\n\t\tm.Body = err.Error()\n\t}\n\tp.out <- m\n\tclose(p.out)\n}\n\n// A killer provides a mechanism to terminate a process.\n// The Kill method returns only once the process has exited.\ntype killer interface {\n\tKill()\n}\n\n// limiter returns a channel that wraps the given channel.\n// It receives Messages from the given channel and sends them to the returned\n// channel until it passes msgLimit messages, at which point it will kill the\n// process and pass only the \"end\" message.\n// When the given channel is closed, or when the \"end\" message is received,\n// it closes the returned channel.\nfunc limiter(in <-chan *Message, p killer) <-chan *Message {\n\tout := make(chan *Message)\n\tgo func() {\n\t\tdefer close(out)\n\t\tn := 0\n\t\tfor m := range in {\n\t\t\tswitch {\n\t\t\tcase n < msgLimit || m.Kind == \"end\":\n\t\t\t\tout <- m\n\t\t\t\tif m.Kind == \"end\" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\tcase n == msgLimit:\n\t\t\t\t// Kill in a goroutine as Kill will not return\n\t\t\t\t// until the process' output has been\n\t\t\t\t// processed, and we're doing that in this loop.\n\t\t\t\tgo p.Kill()\n\t\t\tdefault:\n\t\t\t\tcontinue // don't increment\n\t\t\t}\n\t\t\tn++\n\t\t}\n\t}()\n\treturn out\n}\n\n// buffer returns a channel that wraps the given channel. It receives messages\n// from the given channel and sends them to the returned channel.\n// Message bodies are gathered over the period msgDelay and coalesced into a\n// single Message before they are passed on. Messages of the same kind are\n// coalesced; when a message of a different kind is received, any buffered\n// messages are flushed. When the given channel is closed, buffer flushes the\n// remaining buffered messages and closes the returned channel.\n// The timeAfter func should be time.After. It exists for testing.\nfunc buffer(in <-chan *Message, timeAfter func(time.Duration) <-chan time.Time) <-chan *Message {\n\tout := make(chan *Message)\n\tgo func() {\n\t\tdefer close(out)\n\t\tvar (\n\t\t\ttc    <-chan time.Time\n\t\t\tbuf   []byte\n\t\t\tkind  string\n\t\t\tflush = func() {\n\t\t\t\tif len(buf) == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tout <- &Message{Kind: kind, Body: safeString(buf)}\n\t\t\t\tbuf = buf[:0] // recycle buffer\n\t\t\t\tkind = \"\"\n\t\t\t}\n\t\t)\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase m, ok := <-in:\n\t\t\t\tif !ok {\n\t\t\t\t\tflush()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif m.Kind == \"end\" {\n\t\t\t\t\tflush()\n\t\t\t\t\tout <- m\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif kind != m.Kind {\n\t\t\t\t\tflush()\n\t\t\t\t\tkind = m.Kind\n\t\t\t\t\tif tc == nil {\n\t\t\t\t\t\ttc = timeAfter(msgDelay)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbuf = append(buf, m.Body...)\n\t\t\tcase <-tc:\n\t\t\t\tflush()\n\t\t\t\ttc = nil\n\t\t\t}\n\t\t}\n\t}()\n\treturn out\n}\n\n// Kill stops the process if it is running and waits for it to exit.\nfunc (p *process) Kill() {\n\tif p == nil || p.run == nil {\n\t\treturn\n\t}\n\tp.run.Process.Kill()\n\t<-p.done // block until process exits\n}\n\n// shebang looks for a shebang ('#!') at the beginning of the passed string.\n// If found, it returns the path and args after the shebang.\n// args includes the command as args[0].\nfunc shebang(body string) (path string, args []string) {\n\tbody = strings.TrimSpace(body)\n\tif !strings.HasPrefix(body, \"#!\") {\n\t\treturn \"\", nil\n\t}\n\tif i := strings.Index(body, \"\\n\"); i >= 0 {\n\t\tbody = body[:i]\n\t}\n\tfs := strings.Fields(body[2:])\n\treturn fs[0], fs\n}\n\n// startProcess starts a given program given its path and passing the given body\n// to the command standard input.\nfunc (p *process) startProcess(path string, args []string, body string) error {\n\tcmd := &exec.Cmd{\n\t\tPath:   path,\n\t\tArgs:   args,\n\t\tStdin:  strings.NewReader(body),\n\t\tStdout: &messageWriter{kind: \"stdout\", out: p.out},\n\t\tStderr: &messageWriter{kind: \"stderr\", out: p.out},\n\t}\n\tif err := cmd.Start(); err != nil {\n\t\treturn err\n\t}\n\tp.run = cmd\n\treturn nil\n}\n\n// start builds and starts the given program, sending its output to p.out,\n// and stores the running *exec.Cmd in the run field.\nfunc (p *process) start(body string, opt *Options) error {\n\t// We \"go build\" and then exec the binary so that the\n\t// resultant *exec.Cmd is a handle to the user's program\n\t// (rather than the go tool process).\n\t// This makes Kill work.\n\n\tpath, err := os.MkdirTemp(\"\", \"present-\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.path = path // to be removed by p.end\n\n\tout := \"prog\"\n\tif runtime.GOOS == \"windows\" {\n\t\tout = \"prog.exe\"\n\t}\n\tbin := filepath.Join(path, out)\n\n\t// write body to x.go files\n\ta := txtar.Parse([]byte(body))\n\tif len(a.Comment) != 0 {\n\t\ta.Files = append(a.Files, txtar.File{Name: \"prog.go\", Data: a.Comment})\n\t\ta.Comment = nil\n\t}\n\thasModfile := false\n\tfor _, f := range a.Files {\n\t\terr = os.WriteFile(filepath.Join(path, f.Name), f.Data, 0666)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif f.Name == \"go.mod\" {\n\t\t\thasModfile = true\n\t\t}\n\t}\n\n\t// build x.go, creating x\n\targs := []string{\"go\", \"build\", \"-tags\", \"OMIT\"}\n\tif opt != nil && opt.Race {\n\t\tp.out <- &Message{\n\t\t\tKind: \"stderr\",\n\t\t\tBody: \"Running with race detector.\\n\",\n\t\t}\n\t\targs = append(args, \"-race\")\n\t}\n\targs = append(args, \"-o\", bin)\n\tcmd := p.cmd(path, args...)\n\tif !hasModfile {\n\t\tcmd.Env = append(cmd.Env, \"GO111MODULE=off\")\n\t}\n\tcmd.Stdout = cmd.Stderr // send compiler output to stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn err\n\t}\n\n\t// run x\n\tif isNacl() {\n\t\tcmd, err = p.naclCmd(bin)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tcmd = p.cmd(\"\", bin)\n\t}\n\tif opt != nil && opt.Race {\n\t\tcmd.Env = append(cmd.Env, \"GOMAXPROCS=2\")\n\t}\n\tif err := cmd.Start(); err != nil {\n\t\t// If we failed to exec, that might be because they built\n\t\t// a non-main package instead of an executable.\n\t\t// Check and report that.\n\t\tif name, err := packageName(body); err == nil && name != \"main\" {\n\t\t\treturn errors.New(`executable programs must use \"package main\"`)\n\t\t}\n\t\treturn err\n\t}\n\tp.run = cmd\n\treturn nil\n}\n\n// cmd builds an *exec.Cmd that writes its standard output and error to the\n// process' output channel.\nfunc (p *process) cmd(dir string, args ...string) *exec.Cmd {\n\tcmd := exec.Command(args[0], args[1:]...)\n\tcmd.Dir = dir\n\tcmd.Env = Environ()\n\tcmd.Stdout = &messageWriter{kind: \"stdout\", out: p.out}\n\tcmd.Stderr = &messageWriter{kind: \"stderr\", out: p.out}\n\treturn cmd\n}\n\nfunc isNacl() bool {\n\treturn slices.Contains(append(Environ(), os.Environ()...), \"GOOS=nacl\")\n}\n\n// naclCmd returns an *exec.Cmd that executes bin under native client.\nfunc (p *process) naclCmd(bin string) (*exec.Cmd, error) {\n\tpwd, err := os.Getwd()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar args []string\n\tenv := []string{\n\t\t\"NACLENV_GOOS=\" + runtime.GOOS,\n\t\t\"NACLENV_GOROOT=/go\",\n\t\t\"NACLENV_NACLPWD=\" + strings.Replace(pwd, runtime.GOROOT(), \"/go\", 1),\n\t}\n\tswitch runtime.GOARCH {\n\tcase \"amd64\":\n\t\tenv = append(env, \"NACLENV_GOARCH=amd64p32\")\n\t\targs = []string{\"sel_ldr_x86_64\"}\n\tcase \"386\":\n\t\tenv = append(env, \"NACLENV_GOARCH=386\")\n\t\targs = []string{\"sel_ldr_x86_32\"}\n\tcase \"arm\":\n\t\tenv = append(env, \"NACLENV_GOARCH=arm\")\n\t\tselLdr, err := exec.LookPath(\"sel_ldr_arm\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\targs = []string{\"nacl_helper_bootstrap_arm\", selLdr, \"--reserved_at_zero=0xXXXXXXXXXXXXXXXX\"}\n\tdefault:\n\t\treturn nil, errors.New(\"native client does not support GOARCH=\" + runtime.GOARCH)\n\t}\n\n\tcmd := p.cmd(\"\", append(args, \"-l\", \"/dev/null\", \"-S\", \"-e\", bin)...)\n\tcmd.Env = append(cmd.Env, env...)\n\n\treturn cmd, nil\n}\n\nfunc packageName(body string) (string, error) {\n\tf, err := parser.ParseFile(token.NewFileSet(), \"prog.go\",\n\t\tstrings.NewReader(body), parser.PackageClauseOnly)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn f.Name.String(), nil\n}\n\n// messageWriter is an io.Writer that converts all writes to Message sends on\n// the out channel with the specified id and kind.\ntype messageWriter struct {\n\tkind string\n\tout  chan<- *Message\n}\n\nfunc (w *messageWriter) Write(b []byte) (n int, err error) {\n\tw.out <- &Message{Kind: w.kind, Body: safeString(b)}\n\treturn len(b), nil\n}\n\n// safeString returns b as a valid UTF-8 string.\nfunc safeString(b []byte) string {\n\tif utf8.Valid(b) {\n\t\treturn string(b)\n\t}\n\tvar buf bytes.Buffer\n\tfor len(b) > 0 {\n\t\tr, size := utf8.DecodeRune(b)\n\t\tb = b[size:]\n\t\tbuf.WriteRune(r)\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "playground/socket/socket_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage socket\n\nimport (\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestBuffer(t *testing.T) {\n\tafterChan := make(chan time.Time)\n\tch := make(chan *Message)\n\tgo func() {\n\t\tch <- &Message{Kind: \"err\", Body: \"a\"}\n\t\tch <- &Message{Kind: \"err\", Body: \"b\"}\n\t\tch <- &Message{Kind: \"out\", Body: \"1\"}\n\t\tch <- &Message{Kind: \"out\", Body: \"2\"}\n\t\tafterChan <- time.Time{} // value itself doesn't matter\n\t\tch <- &Message{Kind: \"out\", Body: \"3\"}\n\t\tch <- &Message{Kind: \"out\", Body: \"4\"}\n\t\tclose(ch)\n\t}()\n\n\tvar ms []*Message\n\ttimeAfter := func(d time.Duration) <-chan time.Time {\n\t\treturn afterChan\n\t}\n\tfor m := range buffer(ch, timeAfter) {\n\t\tms = append(ms, m)\n\t}\n\tif len(ms) != 3 {\n\t\tt.Fatalf(\"got %v messages, want 3\", len(ms))\n\t}\n\tif g, w := ms[0].Body, \"ab\"; g != w {\n\t\tt.Errorf(\"message 0 body = %q, want %q\", g, w)\n\t}\n\tif g, w := ms[1].Body, \"12\"; g != w {\n\t\tt.Errorf(\"message 1 body = %q, want %q\", g, w)\n\t}\n\tif g, w := ms[2].Body, \"34\"; g != w {\n\t\tt.Errorf(\"message 2 body = %q, want %q\", g, w)\n\t}\n}\n\ntype killRecorder chan struct{}\n\nfunc (k killRecorder) Kill() { close(k) }\n\nfunc TestLimiter(t *testing.T) {\n\tch := make(chan *Message)\n\tgo func() {\n\t\tvar m Message\n\t\tfor range msgLimit + 10 {\n\t\t\tch <- &m\n\t\t}\n\t\tch <- &Message{Kind: \"end\"}\n\t}()\n\n\tkr := make(killRecorder)\n\tn := 0\n\tfor m := range limiter(ch, kr) {\n\t\tn++\n\t\tif n > msgLimit && m.Kind != \"end\" {\n\t\t\tt.Errorf(\"received non-end message after limit\")\n\t\t}\n\t}\n\tif n != msgLimit+1 {\n\t\tt.Errorf(\"received %v messages, want %v\", n, msgLimit+1)\n\t}\n\t<-kr\n}\n"
  },
  {
    "path": "present/args.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"errors\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"unicode/utf8\"\n)\n\n// This file is stolen from go/src/cmd/godoc/codewalk.go.\n// It's an evaluator for the file address syntax implemented by acme and sam,\n// but using Go-native regular expressions.\n// To keep things reasonably close, this version uses (?m:re) for all user-provided\n// regular expressions. That is the only change to the code from codewalk.go.\n// See http://9p.io/sys/doc/sam/sam.html Table II for details on the syntax.\n\n// addrToByteRange evaluates the given address starting at offset start in data.\n// It returns the lo and hi byte offset of the matched region within data.\nfunc addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {\n\tif addr == \"\" {\n\t\tlo, hi = start, len(data)\n\t\treturn\n\t}\n\tvar (\n\t\tdir        byte\n\t\tprevc      byte\n\t\tcharOffset bool\n\t)\n\tlo = start\n\thi = start\n\tfor addr != \"\" && err == nil {\n\t\tc := addr[0]\n\t\tswitch c {\n\t\tdefault:\n\t\t\terr = errors.New(\"invalid address syntax near \" + string(c))\n\t\tcase ',':\n\t\t\tif len(addr) == 1 {\n\t\t\t\thi = len(data)\n\t\t\t} else {\n\t\t\t\t_, hi, err = addrToByteRange(addr[1:], hi, data)\n\t\t\t}\n\t\t\treturn\n\n\t\tcase '+', '-':\n\t\t\tif prevc == '+' || prevc == '-' {\n\t\t\t\tlo, hi, err = addrNumber(data, lo, hi, prevc, 1, charOffset)\n\t\t\t}\n\t\t\tdir = c\n\n\t\tcase '$':\n\t\t\tlo = len(data)\n\t\t\thi = len(data)\n\t\t\tif len(addr) > 1 {\n\t\t\t\tdir = '+'\n\t\t\t}\n\n\t\tcase '#':\n\t\t\tcharOffset = true\n\n\t\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\t\tvar i int\n\t\t\tfor i = 1; i < len(addr); i++ {\n\t\t\t\tif addr[i] < '0' || addr[i] > '9' {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar n int\n\t\t\tn, err = strconv.Atoi(addr[0:i])\n\t\t\tif err != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlo, hi, err = addrNumber(data, lo, hi, dir, n, charOffset)\n\t\t\tdir = 0\n\t\t\tcharOffset = false\n\t\t\tprevc = c\n\t\t\taddr = addr[i:]\n\t\t\tcontinue\n\n\t\tcase '/':\n\t\t\tvar i, j int\n\t\tRegexp:\n\t\t\tfor i = 1; i < len(addr); i++ {\n\t\t\t\tswitch addr[i] {\n\t\t\t\tcase '\\\\':\n\t\t\t\t\ti++\n\t\t\t\tcase '/':\n\t\t\t\t\tj = i + 1\n\t\t\t\t\tbreak Regexp\n\t\t\t\t}\n\t\t\t}\n\t\t\tif j == 0 {\n\t\t\t\tj = i\n\t\t\t}\n\t\t\tpattern := addr[1:i]\n\t\t\tlo, hi, err = addrRegexp(data, hi, dir, pattern)\n\t\t\tprevc = c\n\t\t\taddr = addr[j:]\n\t\t\tcontinue\n\t\t}\n\t\tprevc = c\n\t\taddr = addr[1:]\n\t}\n\n\tif err == nil && dir != 0 {\n\t\tlo, hi, err = addrNumber(data, lo, hi, dir, 1, charOffset)\n\t}\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\treturn lo, hi, nil\n}\n\n// addrNumber applies the given dir, n, and charOffset to the address lo, hi.\n// dir is '+' or '-', n is the count, and charOffset is true if the syntax\n// used was #n.  Applying +n (or +#n) means to advance n lines\n// (or characters) after hi.  Applying -n (or -#n) means to back up n lines\n// (or characters) before lo.\n// The return value is the new lo, hi.\nfunc addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {\n\tswitch dir {\n\tcase 0:\n\t\tlo = 0\n\t\thi = 0\n\t\tfallthrough\n\n\tcase '+':\n\t\tif charOffset {\n\t\t\tpos := hi\n\t\t\tfor ; n > 0 && pos < len(data); n-- {\n\t\t\t\t_, size := utf8.DecodeRune(data[pos:])\n\t\t\t\tpos += size\n\t\t\t}\n\t\t\tif n == 0 {\n\t\t\t\treturn pos, pos, nil\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\t// find next beginning of line\n\t\tif hi > 0 {\n\t\t\tfor hi < len(data) && data[hi-1] != '\\n' {\n\t\t\t\thi++\n\t\t\t}\n\t\t}\n\t\tlo = hi\n\t\tif n == 0 {\n\t\t\treturn lo, hi, nil\n\t\t}\n\t\tfor ; hi < len(data); hi++ {\n\t\t\tif data[hi] != '\\n' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch n--; n {\n\t\t\tcase 1:\n\t\t\t\tlo = hi + 1\n\t\t\tcase 0:\n\t\t\t\treturn lo, hi + 1, nil\n\t\t\t}\n\t\t}\n\n\tcase '-':\n\t\tif charOffset {\n\t\t\t// Scan backward for bytes that are not UTF-8 continuation bytes.\n\t\t\tpos := lo\n\t\t\tfor ; pos > 0 && n > 0; pos-- {\n\t\t\t\tif data[pos]&0xc0 != 0x80 {\n\t\t\t\t\tn--\n\t\t\t\t}\n\t\t\t}\n\t\t\tif n == 0 {\n\t\t\t\treturn pos, pos, nil\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\t// find earlier beginning of line\n\t\tfor lo > 0 && data[lo-1] != '\\n' {\n\t\t\tlo--\n\t\t}\n\t\thi = lo\n\t\tif n == 0 {\n\t\t\treturn lo, hi, nil\n\t\t}\n\t\tfor ; lo >= 0; lo-- {\n\t\t\tif lo > 0 && data[lo-1] != '\\n' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch n--; n {\n\t\t\tcase 1:\n\t\t\t\thi = lo\n\t\t\tcase 0:\n\t\t\t\treturn lo, hi, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0, 0, errors.New(\"address out of range\")\n}\n\n// addrRegexp searches for pattern in the given direction starting at lo, hi.\n// The direction dir is '+' (search forward from hi) or '-' (search backward from lo).\n// Backward searches are unimplemented.\nfunc addrRegexp(data []byte, hi int, dir byte, pattern string) (int, int, error) {\n\t// We want ^ and $ to work as in sam/acme, so use ?m.\n\tre, err := regexp.Compile(\"(?m:\" + pattern + \")\")\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\tif dir == '-' {\n\t\t// Could implement reverse search using binary search\n\t\t// through file, but that seems like overkill.\n\t\treturn 0, 0, errors.New(\"reverse search not implemented\")\n\t}\n\tm := re.FindIndex(data[hi:])\n\tif len(m) > 0 {\n\t\tm[0] += hi\n\t\tm[1] += hi\n\t} else if hi > 0 {\n\t\t// No match.  Wrap to beginning of data.\n\t\tm = re.FindIndex(data)\n\t}\n\tif len(m) == 0 {\n\t\treturn 0, 0, errors.New(\"no match for \" + pattern)\n\t}\n\treturn m[0], m[1], nil\n}\n"
  },
  {
    "path": "present/caption.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport \"strings\"\n\nfunc init() {\n\tRegister(\"caption\", parseCaption)\n}\n\ntype Caption struct {\n\tCmd  string // original command from present source\n\tText string\n}\n\nfunc (c Caption) PresentCmd() string   { return c.Cmd }\nfunc (c Caption) TemplateName() string { return \"caption\" }\n\nfunc parseCaption(_ *Context, _ string, _ int, cmd string) (Elem, error) {\n\ttext := strings.TrimSpace(strings.TrimPrefix(cmd, \".caption\"))\n\treturn Caption{cmd, text}, nil\n}\n"
  },
  {
    "path": "present/code.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// PlayEnabled specifies whether runnable playground snippets should be\n// displayed in the present user interface.\nvar PlayEnabled = false\n\n// TODO(adg): replace the PlayEnabled flag with something less spaghetti-like.\n// Instead this will probably be determined by a template execution Context\n// value that contains various global metadata required when rendering\n// templates.\n\n// NotesEnabled specifies whether presenter notes should be displayed in the\n// present user interface.\nvar NotesEnabled = false\n\nfunc init() {\n\tRegister(\"code\", parseCode)\n\tRegister(\"play\", parseCode)\n}\n\ntype Code struct {\n\tCmd      string // original command from present source\n\tText     template.HTML\n\tPlay     bool   // runnable code\n\tEdit     bool   // editable code\n\tFileName string // file name\n\tExt      string // file extension\n\tRaw      []byte // content of the file\n}\n\nfunc (c Code) PresentCmd() string   { return c.Cmd }\nfunc (c Code) TemplateName() string { return \"code\" }\n\n// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.\n// Anything between the file and HL (if any) is an address expression, which we treat as a string here.\n// We pick off the HL first, for easy parsing.\nvar (\n\thighlightRE = regexp.MustCompile(`\\s+HL([a-zA-Z0-9_]+)?$`)\n\thlCommentRE = regexp.MustCompile(`(.+) // HL(.*)$`)\n\tcodeRE      = regexp.MustCompile(`\\.(code|play)\\s+((?:(?:-edit|-numbers)\\s+)*)([^\\s]+)(?:\\s+(.*))?$`)\n)\n\n// parseCode parses a code present directive. Its syntax:\n//\n//\t.code [-numbers] [-edit] <filename> [address] [highlight]\n//\n// The directive may also be \".play\" if the snippet is executable.\nfunc parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {\n\tcmd = strings.TrimSpace(cmd)\n\torigCmd := cmd\n\n\t// Pull off the HL, if any, from the end of the input line.\n\thighlight := \"\"\n\tif hl := highlightRE.FindStringSubmatchIndex(cmd); len(hl) == 4 {\n\t\tif hl[2] < 0 || hl[3] < 0 {\n\t\t\treturn nil, fmt.Errorf(\"%s:%d invalid highlight syntax\", sourceFile, sourceLine)\n\t\t}\n\t\thighlight = cmd[hl[2]:hl[3]]\n\t\tcmd = cmd[:hl[2]-2]\n\t}\n\n\t// Parse the remaining command line.\n\t// Arguments:\n\t// args[0]: whole match\n\t// args[1]:  .code/.play\n\t// args[2]: flags (\"-edit -numbers\")\n\t// args[3]: file name\n\t// args[4]: optional address\n\targs := codeRE.FindStringSubmatch(cmd)\n\tif len(args) != 5 {\n\t\treturn nil, fmt.Errorf(\"%s:%d: syntax error for .code/.play invocation\", sourceFile, sourceLine)\n\t}\n\tcommand, flags, file, addr := args[1], args[2], args[3], strings.TrimSpace(args[4])\n\tplay := command == \"play\" && PlayEnabled\n\n\t// Read in code file and (optionally) match address.\n\tfilename := filepath.Join(filepath.Dir(sourceFile), file)\n\ttextBytes, err := ctx.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s:%d: %v\", sourceFile, sourceLine, err)\n\t}\n\tlo, hi, err := addrToByteRange(addr, 0, textBytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s:%d: %v\", sourceFile, sourceLine, err)\n\t}\n\tif lo > hi {\n\t\t// The search in addrToByteRange can wrap around so we might\n\t\t// end up with the range ending before its starting point\n\t\thi, lo = lo, hi\n\t}\n\n\t// Acme pattern matches can stop mid-line,\n\t// so run to end of line in both directions if not at line start/end.\n\tfor lo > 0 && textBytes[lo-1] != '\\n' {\n\t\tlo--\n\t}\n\tif hi > 0 {\n\t\tfor hi < len(textBytes) && textBytes[hi-1] != '\\n' {\n\t\t\thi++\n\t\t}\n\t}\n\n\tlines := codeLines(textBytes, lo, hi)\n\n\tdata := &codeTemplateData{\n\t\tLines:   formatLines(lines, highlight),\n\t\tEdit:    strings.Contains(flags, \"-edit\"),\n\t\tNumbers: strings.Contains(flags, \"-numbers\"),\n\t}\n\n\t// Include before and after in a hidden span for playground code.\n\tif play {\n\t\tdata.Prefix = textBytes[:lo]\n\t\tdata.Suffix = textBytes[hi:]\n\t}\n\n\tvar buf bytes.Buffer\n\tif err := codeTemplate.Execute(&buf, data); err != nil {\n\t\treturn nil, err\n\t}\n\treturn Code{\n\t\tCmd:      origCmd,\n\t\tText:     template.HTML(buf.String()),\n\t\tPlay:     play,\n\t\tEdit:     data.Edit,\n\t\tFileName: filepath.Base(filename),\n\t\tExt:      filepath.Ext(filename),\n\t\tRaw:      rawCode(lines),\n\t}, nil\n}\n\n// formatLines returns a new slice of codeLine with the given lines\n// replacing tabs with spaces and adding highlighting where needed.\nfunc formatLines(lines []codeLine, highlight string) []codeLine {\n\tformatted := make([]codeLine, len(lines))\n\tfor i, line := range lines {\n\t\t// Replace tabs with spaces, which work better in HTML.\n\t\tline.L = strings.Replace(line.L, \"\\t\", \"    \", -1)\n\n\t\t// Highlight lines that end with \"// HL[highlight]\"\n\t\t// and strip the magic comment.\n\t\tif m := hlCommentRE.FindStringSubmatch(line.L); m != nil {\n\t\t\tline.L = m[1]\n\t\t\tline.HL = m[2] == highlight\n\t\t}\n\n\t\tformatted[i] = line\n\t}\n\treturn formatted\n}\n\n// rawCode returns the code represented by the given codeLines without any kind\n// of formatting.\nfunc rawCode(lines []codeLine) []byte {\n\tb := new(bytes.Buffer)\n\tfor _, line := range lines {\n\t\tb.WriteString(line.L)\n\t\tb.WriteByte('\\n')\n\t}\n\treturn b.Bytes()\n}\n\ntype codeTemplateData struct {\n\tLines          []codeLine\n\tPrefix, Suffix []byte\n\tEdit, Numbers  bool\n}\n\nvar leadingSpaceRE = regexp.MustCompile(`^[ \\t]*`)\n\nvar codeTemplate = template.Must(template.New(\"code\").Funcs(template.FuncMap{\n\t\"trimSpace\":    strings.TrimSpace,\n\t\"leadingSpace\": leadingSpaceRE.FindString,\n}).Parse(codeTemplateHTML))\n\nconst codeTemplateHTML = `\n{{with .Prefix}}<pre style=\"display: none\"><span>{{printf \"%s\" .}}</span></pre>{{end -}}\n\n<pre{{if .Edit}} contenteditable=\"true\" spellcheck=\"false\"{{end}}{{if .Numbers}} class=\"numbers\"{{end}}>{{/*\n\t*/}}{{range .Lines}}<span num=\"{{.N}}\">{{/*\n\t*/}}{{if .HL}}{{leadingSpace .L}}<b>{{trimSpace .L}}</b>{{/*\n\t*/}}{{else}}{{.L}}{{end}}{{/*\n*/}}</span>\n{{end}}</pre>\n{{with .Suffix}}<pre style=\"display: none\"><span>{{printf \"%s\" .}}</span></pre>{{end -}}\n`\n\n// codeLine represents a line of code extracted from a source file.\ntype codeLine struct {\n\tL  string // The line of code.\n\tN  int    // The line number from the source file.\n\tHL bool   // Whether the line should be highlighted.\n}\n\n// codeLines takes a source file and returns the lines that\n// span the byte range specified by start and end.\n// It discards lines that end in \"OMIT\".\nfunc codeLines(src []byte, start, end int) (lines []codeLine) {\n\tstartLine := 1\n\tfor i, b := range src {\n\t\tif i == start {\n\t\t\tbreak\n\t\t}\n\t\tif b == '\\n' {\n\t\t\tstartLine++\n\t\t}\n\t}\n\ts := bufio.NewScanner(bytes.NewReader(src[start:end]))\n\tfor n := startLine; s.Scan(); n++ {\n\t\tl := s.Text()\n\t\tif strings.HasSuffix(l, \"OMIT\") {\n\t\t\tcontinue\n\t\t}\n\t\tlines = append(lines, codeLine{L: l, N: n})\n\t}\n\t// Trim leading and trailing blank lines.\n\tfor len(lines) > 0 && len(lines[0].L) == 0 {\n\t\tlines = lines[1:]\n\t}\n\tfor len(lines) > 0 && len(lines[len(lines)-1].L) == 0 {\n\t\tlines = lines[:len(lines)-1]\n\t}\n\treturn\n}\n\nfunc parseArgs(name string, line int, args []string) (res []any, err error) {\n\tres = make([]any, len(args))\n\tfor i, v := range args {\n\t\tif len(v) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"%s:%d bad code argument %q\", name, line, v)\n\t\t}\n\t\tswitch v[0] {\n\t\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\t\tn, err := strconv.Atoi(v)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"%s:%d bad code argument %q\", name, line, v)\n\t\t\t}\n\t\t\tres[i] = n\n\t\tcase '/':\n\t\t\tif len(v) < 2 || v[len(v)-1] != '/' {\n\t\t\t\treturn nil, fmt.Errorf(\"%s:%d bad code argument %q\", name, line, v)\n\t\t\t}\n\t\t\tres[i] = v\n\t\tcase '$':\n\t\t\tres[i] = \"$\"\n\t\tcase '_':\n\t\t\tif len(v) == 1 {\n\t\t\t\t// Do nothing; \"_\" indicates an intentionally empty parameter.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tfallthrough\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"%s:%d bad code argument %q\", name, line, v)\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "present/code_test.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestParseCode(t *testing.T) {\n\t// Enable play but revert the change at the end.\n\tdefer func(play bool) { PlayEnabled = play }(PlayEnabled)\n\tPlayEnabled = true\n\n\thelloTest := []byte(`\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"hello, test\")\n}\n`)\n\thelloTestHTML := template.HTML(`\n<pre><span num=\"2\">package main</span>\n<span num=\"3\"></span>\n<span num=\"4\">import &#34;fmt&#34;</span>\n<span num=\"5\"></span>\n<span num=\"6\">func main() {</span>\n<span num=\"7\">    fmt.Println(&#34;hello, test&#34;)</span>\n<span num=\"8\">}</span>\n</pre>\n`)\n\thelloTestHL := []byte(`\npackage main\n\nimport \"fmt\" // HLimport\n\nfunc main() { // HLfunc\n\tfmt.Println(\"hello, test\") // HL\n}\n`)\n\thighlight := func(h template.HTML, s string) template.HTML {\n\t\treturn template.HTML(strings.Replace(string(h), s, \"<b>\"+s+\"</b>\", -1))\n\t}\n\tread := func(b []byte, err error) func(string) ([]byte, error) {\n\t\treturn func(string) ([]byte, error) { return b, err }\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\treadFile   func(string) ([]byte, error)\n\t\tsourceFile string\n\t\tcmd        string\n\t\terr        string\n\t\tCode\n\t}{\n\t\t{\n\t\t\tname:       \"all code, no play\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tRaw:      helloTest,\n\t\t\t\tText:     helloTestHTML,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"all code, play\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".play main.go\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tPlay:     true,\n\t\t\t\tRaw:      helloTest,\n\t\t\t\tText:     helloTestHTML,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"all code, highlighted\",\n\t\t\treadFile:   read(helloTestHL, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tRaw:      helloTestHL,\n\t\t\t\tText:     highlight(helloTestHTML, \"fmt.Println(&#34;hello, test&#34;)\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"highlight only func\",\n\t\t\treadFile:   read(helloTestHL, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go HLfunc\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tPlay:     false,\n\t\t\t\tRaw:      []byte(\"package main\\n\\nimport \\\"fmt\\\" // HLimport\\n\\nfunc main() { // HLfunc\\n\\tfmt.Println(\\\"hello, test\\\") // HL\\n}\"),\n\t\t\t\tText:     highlight(helloTestHTML, \"func main() {\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"bad highlight syntax\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go HL\",\n\t\t\terr:        \"invalid highlight syntax\",\n\t\t},\n\t\t{\n\t\t\tname:       \"error reading file\",\n\t\t\treadFile:   read(nil, fmt.Errorf(\"nope\")),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go\",\n\t\t\terr:        \"main.go:0: nope\",\n\t\t},\n\t\t{\n\t\t\tname:       \"from func main to the end\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go /func main/,\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tPlay:     false,\n\t\t\t\tRaw:      []byte(\"func main() {\\n\\tfmt.Println(\\\"hello, test\\\")\\n}\"),\n\t\t\t\tText:     \"<pre><span num=\\\"6\\\">func main() {</span>\\n<span num=\\\"7\\\">    fmt.Println(&#34;hello, test&#34;)</span>\\n<span num=\\\"8\\\">}</span>\\n</pre>\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"just func main\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go /func main/\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tPlay:     false,\n\t\t\t\tRaw:      []byte(\"func main() {\"),\n\t\t\t\tText:     \"<pre><span num=\\\"6\\\">func main() {</span>\\n</pre>\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"bad address\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code main.go /function main/\",\n\t\t\terr:        \"main.go:0: no match for function main\",\n\t\t},\n\t\t{\n\t\t\tname:       \"all code with numbers\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code -numbers main.go\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tRaw:      helloTest,\n\t\t\t\t// Replacing the first \"<pre>\"\n\t\t\t\tText: \"<pre class=\\\"numbers\\\">\" + helloTestHTML[6:],\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:       \"all code editable\",\n\t\t\treadFile:   read(helloTest, nil),\n\t\t\tsourceFile: \"main.go\",\n\t\t\tcmd:        \".code -edit main.go\",\n\t\t\tCode: Code{\n\t\t\t\tExt:      \".go\",\n\t\t\t\tFileName: \"main.go\",\n\t\t\t\tRaw:      helloTest,\n\t\t\t\tText:     \"<pre contenteditable=\\\"true\\\" spellcheck=\\\"false\\\">\" + helloTestHTML[6:],\n\t\t\t},\n\t\t},\n\t}\n\n\ttrimHTML := func(t template.HTML) string { return strings.TrimSpace(string(t)) }\n\ttrimBytes := func(b []byte) string { return strings.TrimSpace(string(b)) }\n\n\tfor _, tt := range tests {\n\t\tctx := &Context{tt.readFile}\n\t\te, err := parseCode(ctx, tt.sourceFile, 0, tt.cmd)\n\t\tif err != nil {\n\t\t\tif tt.err == \"\" {\n\t\t\t\tt.Errorf(\"%s: unexpected error %v\", tt.name, err)\n\t\t\t} else if !strings.Contains(err.Error(), tt.err) {\n\t\t\t\tt.Errorf(\"%s: expected error %s; got %v\", tt.name, tt.err, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif tt.err != \"\" {\n\t\t\tt.Errorf(\"%s: expected error %s; but got none\", tt.name, tt.err)\n\t\t\tcontinue\n\t\t}\n\t\tc, ok := e.(Code)\n\t\tif !ok {\n\t\t\tt.Errorf(\"%s: expected a Code value; got %T\", tt.name, e)\n\t\t\tcontinue\n\t\t}\n\t\tif c.FileName != tt.FileName {\n\t\t\tt.Errorf(\"%s: expected FileName %s; got %s\", tt.name, tt.FileName, c.FileName)\n\t\t}\n\t\tif c.Ext != tt.Ext {\n\t\t\tt.Errorf(\"%s: expected Ext %s; got %s\", tt.name, tt.Ext, c.Ext)\n\t\t}\n\t\tif c.Play != tt.Play {\n\t\t\tt.Errorf(\"%s: expected Play %v; got %v\", tt.name, tt.Play, c.Play)\n\t\t}\n\t\tif got, wants := trimBytes(c.Raw), trimBytes(tt.Raw); got != wants {\n\t\t\tt.Errorf(\"%s: expected Raw \\n%q\\n; got \\n%q\\n\", tt.name, wants, got)\n\t\t}\n\t\tif got, wants := trimHTML(c.Text), trimHTML(tt.Text); got != wants {\n\t\t\tt.Errorf(\"%s: expected Text \\n%q\\n; got \\n%q\\n\", tt.name, wants, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "present/doc.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage present implements parsing and rendering of present files,\nwhich can be slide presentations as in golang.org/x/tools/cmd/present\nor articles as in golang.org/x/blog (the Go blog).\n\n# File Format\n\nPresent files begin with a header giving the title of the document\nand other metadata, which looks like:\n\n\t# Title of document\n\tSubtitle of document\n\t15:04 2 Jan 2006\n\tTags: foo, bar, baz\n\tSummary: This is a great document you want to read.\n\tOldURL: former-path-for-this-doc\n\nThe \"# \" prefix before the title indicates that this is\na Markdown-enabled present file: it uses\nMarkdown for text markup in the body of the file.\nIf the \"# \" prefix is missing, the file uses\nlegacy present markup, described below.\n\nThe date line may be written without a time:\n\n\t2 Jan 2006\n\nIn this case, the time will be interpreted as 10am UTC on that date.\n\nThe tags line is a comma-separated list of tags that may be used to categorize\nthe document.\n\nThe summary line gives a short summary used in blog feeds.\n\nThe old URL line, which may be repeated, gives an older (perhaps relative) URL\nfor this document.\nA server might use these to generate appropriate redirects.\n\nOnly the title is required;\nthe subtitle, date, tags, summary, and old URL lines are optional.\nIn Markdown-enabled present, the summary defaults to being empty.\nIn legacy present, the summary defaults to the first paragraph of text.\n\nAfter the header come zero or more author blocks, like this:\n\n\tAuthor Name\n\tJob title, Company\n\tjoe@example.com\n\thttps://url/\n\t@twitter_name\n\nThe first line of the author block is conventionally the author name.\nOtherwise, the author section may contain a mixture of text, twitter names, and links.\nFor slide presentations, only the plain text lines will be displayed on the\nfirst slide.\n\nIf multiple author blocks are listed, each new block must be preceded\nby its own blank line.\n\nAfter the author blocks come the presentation slides or article sections,\nwhich can in turn have subsections.\nIn Markdown-enabled present files, each slide or section begins with a \"##\" header line,\nsubsections begin with a \"###\" header line, and so on.\nIn legacy present files, each slide or section begins with a \"*\" header line,\nsubsections begin with a \"**\" header line, and so on.\n\nIn addition to the marked-up text in a section (or subsection),\na present file can contain present command invocations, each of which begins\nwith a dot, as in:\n\n\t.code x.go /^func main/,/^}/\n\t.play y.go\n\t.image image.jpg\n\t.background image.jpg\n\t.iframe https://foo\n\t.link https://foo label\n\t.html file.html\n\t.caption _Gopher_ by [[https://instagram.com/reneefrench][Renee French]]\n\nOther than the commands, the text in a section is interpreted\neither as Markdown or as legacy present markup.\n\n# Markdown Syntax\n\nMarkdown typically means the generic name for a family of similar markup languages.\nThe specific variant used in present is CommonMark.\nSee https://commonmark.org/help/tutorial/ for a quick tutorial.\n\nIn Markdown-enabled present,\nsection headings can end in {#name} to set the HTML anchor ID for the heading to \"name\".\n\nLines beginning with \"//\" (outside of code blocks, of course)\nare treated as present comments and have no effect.\n\nLines beginning with \": \" are treated as speaker notes, described below.\n\nExample:\n\n\t# Title of Talk\n\n\tMy Name\n\t9 Mar 2020\n\tme@example.com\n\n\t## Title of Slide or Section (must begin with ##)\n\n\tSome Text\n\n\t### Subsection {#anchor}\n\n\t- bullets\n\t- more bullets\n\t- a bullet continued\n\t  on the next line\n\n\t#### Sub-subsection\n\n\tSome More text\n\n\t\tPreformatted text (code block)\n\t\tis indented (by one tab, or four spaces)\n\n\tFurther Text, including command invocations.\n\n\t## Section 2: Example formatting {#fmt}\n\n\tFormatting:\n\n\t_italic_\n\t// A comment that is completely ignored.\n\t: Speaker notes.\n\t**bold**\n\t`program`\n\tMarkup—_especially italic text_—can easily be overused.\n\t_Why use scoped\\_ptr_? Use plain **\\*ptr** instead.\n\n\tVisit [the Go home page](https://golang.org/).\n\n# Legacy Present Syntax\n\nCompared to Markdown,\nin legacy present\nslides/sections use \"*\" instead of \"##\",\nwhole-line comments begin with \"#\" instead of \"//\",\nbullet lists can only contain single (possibly wrapped) text lines,\nand the font styling and link syntaxes are subtly different.\n\nExample:\n\n\tTitle of Talk\n\n\tMy Name\n\t1 Jan 2013\n\tme@example.com\n\n\t* Title of Slide or Section (must begin with *)\n\n\tSome Text\n\n\t** Subsection\n\n\t- bullets\n\t- more bullets\n\t- a bullet continued\n\t  on the next line (indented at least one space)\n\n\t*** Sub-subsection\n\n\tSome More text\n\n\t  Preformatted text (code block)\n\t  is indented (however you like)\n\n\tFurther Text, including command invocations.\n\n\t* Section 2: Example formatting\n\n\tFormatting:\n\n\t_italic_\n\t*bold*\n\t`program`\n\tMarkup—_especially_italic_text_—can easily be overused.\n\t_Why_use_scoped__ptr_? Use plain ***ptr* instead.\n\n\tVisit [[https://golang.org][the Go home page]].\n\nWithin the input for plain text or lists, text bracketed by font\nmarkers will be presented in italic, bold, or program font.\nMarker characters are _ (italic), * (bold) and ` (program font).\nAn opening marker must be preceded by a space or punctuation\ncharacter or else be at start of a line; similarly, a closing\nmarker must be followed by a space or punctuation character or\nelse be at the end of a line. Unmatched markers appear as plain text.\nThere must be no spaces between markers. Within marked text,\na single marker character becomes a space and a doubled single\nmarker quotes the marker character.\n\nLinks can be included in any text with either explicit labels\nor the URL itself as the label. For example:\n\n\t[[url][label]]\n\t[[url]]\n\n# Command Invocations\n\nA number of special commands are available through invocations\nin the input text. Each such invocation contains a period as the\nfirst character on the line, followed immediately by the name of\nthe function, followed by any arguments. A typical invocation might\nbe\n\n\t.play demo.go /^func show/,/^}/\n\n(except that the \".play\" must be at the beginning of the line and\nnot be indented as in this comment.)\n\nHere follows a description of the functions:\n\ncode:\n\nInjects program source into the output by extracting code from files\nand injecting them as HTML-escaped <pre> blocks.  The argument is\na file name followed by an optional address that specifies what\nsection of the file to display. The address syntax is similar in\nits simplest form to that of ed, but comes from sam and is more\ngeneral. See\n\n\thttps://plan9.io/sys/doc/sam/sam.html Table II\n\nfor full details. The displayed block is always rounded out to a\nfull line at both ends.\n\nIf no pattern is present, the entire file is displayed.\n\nAny line in the program that ends with the four characters\n\n\tOMIT\n\nis deleted from the source before inclusion, making it easy\nto write things like\n\n\t.code test.go /START OMIT/,/END OMIT/\n\nto find snippets like this\n\n\ttedious_code = boring_function()\n\t// START OMIT\n\tinteresting_code = fascinating_function()\n\t// END OMIT\n\nand see only this:\n\n\tinteresting_code = fascinating_function()\n\nAlso, inside the displayed text a line that ends\n\n\t// HL\n\nwill be highlighted in the display. A highlighting mark may have a\nsuffix word, such as\n\n\t// HLxxx\n\nSuch highlights are enabled only if the code invocation ends with\n\"HL\" followed by the word:\n\n\t.code test.go /^type Foo/,/^}/ HLxxx\n\nThe .code function may take one or more flags immediately preceding\nthe filename. This command shows test.go in an editable text area:\n\n\t.code -edit test.go\n\nThis command shows test.go with line numbers:\n\n\t.code -numbers test.go\n\nplay:\n\nThe function \"play\" is the same as \"code\" but puts a button\non the displayed source so the program can be run from the browser.\nAlthough only the selected text is shown, all the source is included\nin the HTML output so it can be presented to the compiler.\n\nlink:\n\nCreate a hyperlink. The syntax is 1 or 2 space-separated arguments.\nThe first argument is always the HTTP URL.  If there is a second\nargument, it is the text label to display for this link.\n\n\t.link https://golang.org golang.org\n\nimage:\n\nThe template uses the function \"image\" to inject picture files.\n\nThe syntax is simple: 1 or 3 space-separated arguments.\nThe first argument is always the file name.\nIf there are more arguments, they are the height and width;\nboth must be present, or substituted with an underscore.\nReplacing a dimension argument with the underscore parameter\npreserves the aspect ratio of the image when scaling.\n\n\t.image images/betsy.jpg 100 200\n\t.image images/janet.jpg _ 300\n\nvideo:\n\nThe template uses the function \"video\" to inject video files.\n\nThe syntax is simple: 2 or 4 space-separated arguments.\nThe first argument is always the file name.\nThe second argument is always the file content-type.\nIf there are more arguments, they are the height and width;\nboth must be present, or substituted with an underscore.\nReplacing a dimension argument with the underscore parameter\npreserves the aspect ratio of the video when scaling.\n\n\t.video videos/evangeline.mp4 video/mp4 400 600\n\n\t.video videos/mabel.ogg video/ogg 500 _\n\nbackground:\n\nThe template uses the function \"background\" to set the background image for\na slide.  The only argument is the file name of the image.\n\n\t.background images/susan.jpg\n\ncaption:\n\nThe template uses the function \"caption\" to inject figure captions.\n\nThe text after \".caption\" is embedded in a figcaption element after\nprocessing styling and links as in standard text lines.\n\n\t.caption _Gopher_ by [[https://instagram.com/reneefrench][Renee French]]\n\niframe:\n\nThe function \"iframe\" injects iframes (pages inside pages).\nIts syntax is the same as that of image.\n\nhtml:\n\nThe function html includes the contents of the specified file as\nunescaped HTML. This is useful for including custom HTML elements\nthat cannot be created using only the slide format.\nIt is your responsibility to make sure the included HTML is valid and safe.\n\n\t.html file.html\n\n# Presenter Notes\n\nLines that begin with \": \" are treated as presenter notes,\nin both Markdown and legacy present syntax.\nBy default, presenter notes are collected but ignored.\n\nWhen running the present command with -notes,\ntyping 'N' in your browser displaying your slides\nwill create a second window displaying the notes.\nThe second window is completely synced with the main\nwindow, except that presenter notes are only visible in the second window.\n\nNotes may appear anywhere within the slide text. For example:\n\n\t## Title of slide\n\n\tSome text.\n\n\t: Presenter notes (first paragraph)\n\n\tSome more text.\n\n\t: Presenter notes (subsequent paragraph(s))\n*/\npackage present // import \"golang.org/x/tools/present\"\n"
  },
  {
    "path": "present/html.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"errors\"\n\t\"html/template\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc init() {\n\tRegister(\"html\", parseHTML)\n}\n\nfunc parseHTML(ctx *Context, fileName string, lineno int, text string) (Elem, error) {\n\tp := strings.Fields(text)\n\tif len(p) != 2 {\n\t\treturn nil, errors.New(\"invalid .html args\")\n\t}\n\tname := filepath.Join(filepath.Dir(fileName), p[1])\n\tb, err := ctx.ReadFile(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn HTML{text, template.HTML(b)}, nil\n}\n\ntype HTML struct {\n\tCmd string // original command from present source\n\ttemplate.HTML\n}\n\nfunc (s HTML) PresentCmd() string   { return s.Cmd }\nfunc (s HTML) TemplateName() string { return \"html\" }\n"
  },
  {
    "path": "present/iframe.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc init() {\n\tRegister(\"iframe\", parseIframe)\n}\n\ntype Iframe struct {\n\tCmd    string // original command from present source\n\tURL    string\n\tWidth  int\n\tHeight int\n}\n\nfunc (i Iframe) PresentCmd() string   { return i.Cmd }\nfunc (i Iframe) TemplateName() string { return \"iframe\" }\n\nfunc parseIframe(ctx *Context, fileName string, lineno int, text string) (Elem, error) {\n\targs := strings.Fields(text)\n\tif len(args) < 2 {\n\t\treturn nil, fmt.Errorf(\"incorrect iframe invocation: %q\", text)\n\t}\n\ti := Iframe{Cmd: text, URL: args[1]}\n\ta, err := parseArgs(fileName, lineno, args[2:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch len(a) {\n\tcase 0:\n\t\t// no size parameters\n\tcase 2:\n\t\tif v, ok := a[0].(int); ok {\n\t\t\ti.Height = v\n\t\t}\n\t\tif v, ok := a[1].(int); ok {\n\t\t\ti.Width = v\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"incorrect iframe invocation: %q\", text)\n\t}\n\treturn i, nil\n}\n"
  },
  {
    "path": "present/image.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc init() {\n\tRegister(\"image\", parseImage)\n}\n\ntype Image struct {\n\tCmd    string // original command from present source\n\tURL    string\n\tWidth  int\n\tHeight int\n}\n\nfunc (i Image) PresentCmd() string   { return i.Cmd }\nfunc (i Image) TemplateName() string { return \"image\" }\n\nfunc parseImage(ctx *Context, fileName string, lineno int, text string) (Elem, error) {\n\targs := strings.Fields(text)\n\tif len(args) < 2 {\n\t\treturn nil, fmt.Errorf(\"incorrect image invocation: %q\", text)\n\t}\n\timg := Image{Cmd: text, URL: args[1]}\n\ta, err := parseArgs(fileName, lineno, args[2:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch len(a) {\n\tcase 0:\n\t\t// no size parameters\n\tcase 2:\n\t\t// If a parameter is empty (underscore) or invalid\n\t\t// leave the field set to zero. The \"image\" action\n\t\t// template will then omit that img tag attribute and\n\t\t// the browser will calculate the value to preserve\n\t\t// the aspect ratio.\n\t\tif v, ok := a[0].(int); ok {\n\t\t\timg.Height = v\n\t\t}\n\t\tif v, ok := a[1].(int); ok {\n\t\t\timg.Width = v\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"incorrect image invocation: %q\", text)\n\t}\n\treturn img, nil\n}\n"
  },
  {
    "path": "present/link.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/url\"\n\t\"strings\"\n)\n\nfunc init() {\n\tRegister(\"link\", parseLink)\n}\n\ntype Link struct {\n\tCmd   string // original command from present source\n\tURL   *url.URL\n\tLabel string\n}\n\nfunc (l Link) PresentCmd() string   { return l.Cmd }\nfunc (l Link) TemplateName() string { return \"link\" }\n\nfunc parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, error) {\n\targs := strings.Fields(text)\n\tif len(args) < 2 {\n\t\treturn nil, fmt.Errorf(\"link element must have at least 2 arguments\")\n\t}\n\turl, err := url.Parse(args[1])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlabel := \"\"\n\tif len(args) > 2 {\n\t\tlabel = strings.Join(args[2:], \" \")\n\t} else {\n\t\tscheme := url.Scheme + \"://\"\n\t\tif url.Scheme == \"mailto\" {\n\t\t\tscheme = \"mailto:\"\n\t\t}\n\t\tlabel = strings.Replace(url.String(), scheme, \"\", 1)\n\t}\n\treturn Link{text, url, label}, nil\n}\n\nfunc renderLink(href, text string) string {\n\ttext = font(text)\n\tif text == \"\" {\n\t\ttext = href\n\t}\n\t// Open links in new window only when their url is absolute.\n\ttarget := \"_blank\"\n\tif u, err := url.Parse(href); err != nil {\n\t\tlog.Println(\"renderLink parsing url:\", err)\n\t} else if !u.IsAbs() || u.Scheme == \"javascript\" {\n\t\ttarget = \"_self\"\n\t}\n\n\treturn fmt.Sprintf(`<a href=\"%s\" target=\"%s\">%s</a>`, href, target, text)\n}\n\n// parseInlineLink parses an inline link at the start of s, and returns\n// a rendered HTML link and the total length of the raw inline link.\n// If no inline link is present, it returns all zeroes.\nfunc parseInlineLink(s string) (link string, length int) {\n\tif !strings.HasPrefix(s, \"[[\") {\n\t\treturn\n\t}\n\tend := strings.Index(s, \"]]\")\n\tif end == -1 {\n\t\treturn\n\t}\n\turlEnd := strings.Index(s, \"]\")\n\trawURL := s[2:urlEnd]\n\tconst badURLChars = `<>\"{}|\\^[] ` + \"`\" // per RFC2396 section 2.4.3\n\tif strings.ContainsAny(rawURL, badURLChars) {\n\t\treturn\n\t}\n\tif urlEnd == end {\n\t\tsimpleURL := \"\"\n\t\turl, err := url.Parse(rawURL)\n\t\tif err == nil {\n\t\t\t// If the URL is http://foo.com, drop the http://\n\t\t\t// In other words, render [[http://golang.org]] as:\n\t\t\t//   <a href=\"http://golang.org\">golang.org</a>\n\t\t\tif after, ok := strings.CutPrefix(rawURL, url.Scheme+\"://\"); ok {\n\t\t\t\tsimpleURL = after\n\t\t\t} else if after, ok := strings.CutPrefix(rawURL, url.Scheme+\":\"); ok {\n\t\t\t\tsimpleURL = after\n\t\t\t}\n\t\t}\n\t\treturn renderLink(rawURL, simpleURL), end + 2\n\t}\n\tif s[urlEnd:urlEnd+2] != \"][\" {\n\t\treturn\n\t}\n\ttext := s[urlEnd+2 : end]\n\treturn renderLink(rawURL, text), end + 2\n}\n"
  },
  {
    "path": "present/link_test.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport \"testing\"\n\nfunc TestInlineParsing(t *testing.T) {\n\tvar tests = []struct {\n\t\tin     string\n\t\tlink   string\n\t\ttext   string\n\t\tlength int\n\t}{\n\t\t{\"[[http://golang.org]]\", \"http://golang.org\", \"golang.org\", 21},\n\t\t{\"[[http://golang.org][]]\", \"http://golang.org\", \"http://golang.org\", 23},\n\t\t{\"[[http://golang.org]] this is ignored\", \"http://golang.org\", \"golang.org\", 21},\n\t\t{\"[[http://golang.org][link]]\", \"http://golang.org\", \"link\", 27},\n\t\t{\"[[http://golang.org][two words]]\", \"http://golang.org\", \"two words\", 32},\n\t\t{\"[[http://golang.org][*link*]]\", \"http://golang.org\", \"<b>link</b>\", 29},\n\t\t{\"[[http://bad[url]]\", \"\", \"\", 0},\n\t\t{\"[[http://golang.org][a [[link]] ]]\", \"http://golang.org\", \"a [[link\", 31},\n\t\t{\"[[http:// *spaces* .com]]\", \"\", \"\", 0},\n\t\t{\"[[http://bad`char.com]]\", \"\", \"\", 0},\n\t\t{\" [[http://google.com]]\", \"\", \"\", 0},\n\t\t{\"[[mailto:gopher@golang.org][Gopher]]\", \"mailto:gopher@golang.org\", \"Gopher\", 36},\n\t\t{\"[[mailto:gopher@golang.org]]\", \"mailto:gopher@golang.org\", \"gopher@golang.org\", 28},\n\t}\n\n\tfor i, test := range tests {\n\t\tlink, length := parseInlineLink(test.in)\n\t\tif length == 0 && test.length == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif a := renderLink(test.link, test.text); length != test.length || link != a {\n\t\t\tt.Errorf(\"#%d: parseInlineLink(%q):\\ngot\\t%q, %d\\nwant\\t%q, %d\", i, test.in, link, length, a, test.length)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "present/parse.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"io\"\n\t\"log\"\n\t\"net/url\"\n\t\"os\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"github.com/yuin/goldmark\"\n\t\"github.com/yuin/goldmark/ast\"\n\t\"github.com/yuin/goldmark/renderer/html\"\n\t\"github.com/yuin/goldmark/text\"\n)\n\nvar (\n\tparsers = make(map[string]ParseFunc)\n\tfuncs   = template.FuncMap{}\n)\n\n// Template returns an empty template with the action functions in its FuncMap.\nfunc Template() *template.Template {\n\treturn template.New(\"\").Funcs(funcs)\n}\n\n// Render renders the doc to the given writer using the provided template.\nfunc (d *Doc) Render(w io.Writer, t *template.Template) error {\n\tdata := struct {\n\t\t*Doc\n\t\tTemplate     *template.Template\n\t\tPlayEnabled  bool\n\t\tNotesEnabled bool\n\t}{d, t, PlayEnabled, NotesEnabled}\n\treturn t.ExecuteTemplate(w, \"root\", data)\n}\n\n// Render renders the section to the given writer using the provided template.\nfunc (s *Section) Render(w io.Writer, t *template.Template) error {\n\tdata := struct {\n\t\t*Section\n\t\tTemplate    *template.Template\n\t\tPlayEnabled bool\n\t}{s, t, PlayEnabled}\n\treturn t.ExecuteTemplate(w, \"section\", data)\n}\n\ntype ParseFunc func(ctx *Context, fileName string, lineNumber int, inputLine string) (Elem, error)\n\n// Register binds the named action, which does not begin with a period, to the\n// specified parser to be invoked when the name, with a period, appears in the\n// present input text.\nfunc Register(name string, parser ParseFunc) {\n\tif len(name) == 0 || name[0] == ';' {\n\t\tpanic(\"bad name in Register: \" + name)\n\t}\n\tparsers[\".\"+name] = parser\n}\n\n// Doc represents an entire document.\ntype Doc struct {\n\tTitle      string\n\tSubtitle   string\n\tSummary    string\n\tTime       time.Time\n\tAuthors    []Author\n\tTitleNotes []string\n\tSections   []Section\n\tTags       []string\n\tOldURL     []string\n}\n\n// Author represents the person who wrote and/or is presenting the document.\ntype Author struct {\n\tElem []Elem\n}\n\n// TextElem returns the first text elements of the author details.\n// This is used to display the author' name, job title, and company\n// without the contact details.\nfunc (p *Author) TextElem() (elems []Elem) {\n\tfor _, el := range p.Elem {\n\t\tif _, ok := el.(Text); !ok {\n\t\t\tbreak\n\t\t}\n\t\telems = append(elems, el)\n\t}\n\treturn\n}\n\n// Section represents a section of a document (such as a presentation slide)\n// comprising a title and a list of elements.\ntype Section struct {\n\tNumber  []int\n\tTitle   string\n\tID      string // HTML anchor ID\n\tElem    []Elem\n\tNotes   []string\n\tClasses []string\n\tStyles  []string\n}\n\n// HTMLAttributes for the section\nfunc (s Section) HTMLAttributes() template.HTMLAttr {\n\tif len(s.Classes) == 0 && len(s.Styles) == 0 {\n\t\treturn \"\"\n\t}\n\n\tvar class string\n\tif len(s.Classes) > 0 {\n\t\tclass = fmt.Sprintf(`class=%q`, strings.Join(s.Classes, \" \"))\n\t}\n\tvar style string\n\tif len(s.Styles) > 0 {\n\t\tstyle = fmt.Sprintf(`style=%q`, strings.Join(s.Styles, \" \"))\n\t}\n\treturn template.HTMLAttr(strings.Join([]string{class, style}, \" \"))\n}\n\n// Sections contained within the section.\nfunc (s Section) Sections() (sections []Section) {\n\tfor _, e := range s.Elem {\n\t\tif section, ok := e.(Section); ok {\n\t\t\tsections = append(sections, section)\n\t\t}\n\t}\n\treturn\n}\n\n// Level returns the level of the given section.\n// The document title is level 1, main section 2, etc.\nfunc (s Section) Level() int {\n\treturn len(s.Number) + 1\n}\n\n// FormattedNumber returns a string containing the concatenation of the\n// numbers identifying a Section.\nfunc (s Section) FormattedNumber() string {\n\tb := &bytes.Buffer{}\n\tfor _, n := range s.Number {\n\t\tfmt.Fprintf(b, \"%v.\", n)\n\t}\n\treturn b.String()\n}\n\nfunc (s Section) TemplateName() string { return \"section\" }\n\n// Elem defines the interface for a present element. That is, something that\n// can provide the name of the template used to render the element.\ntype Elem interface {\n\tTemplateName() string\n}\n\n// renderElem implements the elem template function, used to render\n// sub-templates.\nfunc renderElem(t *template.Template, e Elem) (template.HTML, error) {\n\tvar data any = e\n\tif s, ok := e.(Section); ok {\n\t\tdata = struct {\n\t\t\tSection\n\t\t\tTemplate *template.Template\n\t\t}{s, t}\n\t}\n\treturn execTemplate(t, e.TemplateName(), data)\n}\n\n// pageNum derives a page number from a section.\nfunc pageNum(s Section, offset int) int {\n\tif len(s.Number) == 0 {\n\t\treturn offset\n\t}\n\treturn s.Number[0] + offset\n}\n\nfunc init() {\n\tfuncs[\"elem\"] = renderElem\n\tfuncs[\"pagenum\"] = pageNum\n}\n\n// execTemplate is a helper to execute a template and return the output as a\n// template.HTML value.\nfunc execTemplate(t *template.Template, name string, data any) (template.HTML, error) {\n\tb := new(bytes.Buffer)\n\terr := t.ExecuteTemplate(b, name, data)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn template.HTML(b.String()), nil\n}\n\n// Text represents an optionally preformatted paragraph.\ntype Text struct {\n\tLines []string\n\tPre   bool\n\tRaw   string // original text, for Pre==true\n}\n\nfunc (t Text) TemplateName() string { return \"text\" }\n\n// List represents a bulleted list.\ntype List struct {\n\tBullet []string\n}\n\nfunc (l List) TemplateName() string { return \"list\" }\n\n// Lines is a helper for parsing line-based input.\ntype Lines struct {\n\tline    int // 0 indexed, so has 1-indexed number of last line returned\n\ttext    []string\n\tcomment string\n}\n\nfunc readLines(r io.Reader) (*Lines, error) {\n\tvar lines []string\n\ts := bufio.NewScanner(r)\n\tfor s.Scan() {\n\t\tlines = append(lines, s.Text())\n\t}\n\tif err := s.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Lines{0, lines, \"#\"}, nil\n}\n\nfunc (l *Lines) next() (text string, ok bool) {\n\tfor {\n\t\tcurrent := l.line\n\t\tl.line++\n\t\tif current >= len(l.text) {\n\t\t\treturn \"\", false\n\t\t}\n\t\ttext = l.text[current]\n\t\t// Lines starting with l.comment are comments.\n\t\tif l.comment == \"\" || !strings.HasPrefix(text, l.comment) {\n\t\t\tok = true\n\t\t\tbreak\n\t\t}\n\t}\n\treturn\n}\n\nfunc (l *Lines) back() {\n\tl.line--\n}\n\nfunc (l *Lines) nextNonEmpty() (text string, ok bool) {\n\tfor {\n\t\ttext, ok = l.next()\n\t\tif !ok {\n\t\t\treturn\n\t\t}\n\t\tif len(text) > 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn\n}\n\n// A Context specifies the supporting context for parsing a presentation.\ntype Context struct {\n\t// ReadFile reads the file named by filename and returns the contents.\n\tReadFile func(filename string) ([]byte, error)\n}\n\n// ParseMode represents flags for the Parse function.\ntype ParseMode int\n\nconst (\n\t// If set, parse only the title and subtitle.\n\tTitlesOnly ParseMode = 1\n)\n\n// Parse parses a document from r.\nfunc (ctx *Context) Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {\n\tdoc := new(Doc)\n\tlines, err := readLines(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Detect Markdown-enabled vs legacy present file.\n\t// Markdown-enabled files have a title line beginning with \"# \"\n\t// (like preprocessed C files of yore).\n\tisMarkdown := false\n\tfor i := lines.line; i < len(lines.text); i++ {\n\t\tline := lines.text[i]\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tisMarkdown = strings.HasPrefix(line, \"# \")\n\t\tbreak\n\t}\n\n\tsectionPrefix := \"*\"\n\tif isMarkdown {\n\t\tsectionPrefix = \"##\"\n\t\tlines.comment = \"//\"\n\t}\n\n\tfor i := lines.line; i < len(lines.text); i++ {\n\t\tif strings.HasPrefix(lines.text[i], sectionPrefix) {\n\t\t\tbreak\n\t\t}\n\n\t\tif isSpeakerNote(lines.text[i]) {\n\t\t\tdoc.TitleNotes = append(doc.TitleNotes, trimSpeakerNote(lines.text[i]))\n\t\t}\n\t}\n\n\terr = parseHeader(doc, isMarkdown, lines)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif mode&TitlesOnly != 0 {\n\t\treturn doc, nil\n\t}\n\n\t// Authors\n\tif doc.Authors, err = parseAuthors(name, sectionPrefix, lines); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Sections\n\tif doc.Sections, err = parseSections(ctx, name, sectionPrefix, lines, []int{}); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn doc, nil\n}\n\n// Parse parses a document from r. Parse reads assets used by the presentation\n// from the file system using os.ReadFile.\nfunc Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {\n\tctx := Context{ReadFile: os.ReadFile}\n\treturn ctx.Parse(r, name, mode)\n}\n\n// isHeading matches any section heading.\nvar (\n\tisHeadingLegacy   = regexp.MustCompile(`^\\*+( |$)`)\n\tisHeadingMarkdown = regexp.MustCompile(`^\\#+( |$)`)\n)\n\n// lesserHeading returns true if text is a heading of a lesser or equal level\n// than that denoted by prefix.\nfunc lesserHeading(isHeading *regexp.Regexp, text, prefix string) bool {\n\treturn isHeading.MatchString(text) && !strings.HasPrefix(text, prefix+prefix[:1])\n}\n\n// parseSections parses Sections from lines for the section level indicated by\n// number (a nil number indicates the top level).\nfunc parseSections(ctx *Context, name, prefix string, lines *Lines, number []int) ([]Section, error) {\n\tisMarkdown := prefix[0] == '#'\n\tisHeading := isHeadingLegacy\n\tif isMarkdown {\n\t\tisHeading = isHeadingMarkdown\n\t}\n\tvar sections []Section\n\tfor i := 1; ; i++ {\n\t\t// Next non-empty line is title.\n\t\ttext, ok := lines.nextNonEmpty()\n\t\tfor ok && text == \"\" {\n\t\t\ttext, ok = lines.next()\n\t\t}\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tif text != prefix && !strings.HasPrefix(text, prefix+\" \") {\n\t\t\tlines.back()\n\t\t\tbreak\n\t\t}\n\t\t// Markdown sections can end in {#id} to set the HTML anchor for the section.\n\t\t// This is nicer than the default #TOC_1_2-style anchor.\n\t\ttitle := strings.TrimSpace(text[len(prefix):])\n\t\tid := \"\"\n\t\tif isMarkdown && strings.HasSuffix(title, \"}\") {\n\t\t\tj := strings.LastIndex(title, \"{#\")\n\t\t\tif j >= 0 {\n\t\t\t\tid = title[j+2 : len(title)-1]\n\t\t\t\ttitle = strings.TrimSpace(title[:j])\n\t\t\t}\n\t\t}\n\t\tsection := Section{\n\t\t\tNumber: append(slices.Clone(number), i),\n\t\t\tTitle:  title,\n\t\t\tID:     id,\n\t\t}\n\t\ttext, ok = lines.nextNonEmpty()\n\t\tfor ok && !lesserHeading(isHeading, text, prefix) {\n\t\t\tvar e Elem\n\t\t\tr, _ := utf8.DecodeRuneInString(text)\n\t\t\tswitch {\n\t\t\tcase !isMarkdown && unicode.IsSpace(r):\n\t\t\t\ti := strings.IndexFunc(text, func(r rune) bool {\n\t\t\t\t\treturn !unicode.IsSpace(r)\n\t\t\t\t})\n\t\t\t\tif i < 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tindent := text[:i]\n\t\t\t\tvar s []string\n\t\t\t\tfor ok && (strings.HasPrefix(text, indent) || text == \"\") {\n\t\t\t\t\tif text != \"\" {\n\t\t\t\t\t\ttext = text[i:]\n\t\t\t\t\t}\n\t\t\t\t\ts = append(s, text)\n\t\t\t\t\ttext, ok = lines.next()\n\t\t\t\t}\n\t\t\t\tlines.back()\n\t\t\t\tpre := strings.Join(s, \"\\n\")\n\t\t\t\traw := pre\n\t\t\t\tpre = strings.Replace(pre, \"\\t\", \"    \", -1) // browsers treat tabs badly\n\t\t\t\tpre = strings.TrimRightFunc(pre, unicode.IsSpace)\n\t\t\t\te = Text{Lines: []string{pre}, Pre: true, Raw: raw}\n\t\t\tcase !isMarkdown && strings.HasPrefix(text, \"- \"):\n\t\t\t\tvar b []string\n\t\t\t\tfor {\n\t\t\t\t\tif strings.HasPrefix(text, \"- \") {\n\t\t\t\t\t\tb = append(b, text[2:])\n\t\t\t\t\t} else if len(b) > 0 && strings.HasPrefix(text, \" \") {\n\t\t\t\t\t\tb[len(b)-1] += \"\\n\" + strings.TrimSpace(text)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif text, ok = lines.next(); !ok {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines.back()\n\t\t\t\te = List{Bullet: b}\n\t\t\tcase isSpeakerNote(text):\n\t\t\t\tsection.Notes = append(section.Notes, trimSpeakerNote(text))\n\t\t\tcase strings.HasPrefix(text, prefix+prefix[:1]+\" \") || text == prefix+prefix[:1]:\n\t\t\t\tlines.back()\n\t\t\t\tsubsecs, err := parseSections(ctx, name, prefix+prefix[:1], lines, section.Number)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfor _, ss := range subsecs {\n\t\t\t\t\tsection.Elem = append(section.Elem, ss)\n\t\t\t\t}\n\t\t\tcase strings.HasPrefix(text, prefix+prefix[:1]):\n\t\t\t\treturn nil, fmt.Errorf(\"%s:%d: badly nested section inside %s: %s\", name, lines.line, prefix, text)\n\t\t\tcase strings.HasPrefix(text, \".\"):\n\t\t\t\targs := strings.Fields(text)\n\t\t\t\tif args[0] == \".background\" {\n\t\t\t\t\tsection.Classes = append(section.Classes, \"background\")\n\t\t\t\t\tsection.Styles = append(section.Styles, \"background-image: url('\"+args[1]+\"')\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tparser := parsers[args[0]]\n\t\t\t\tif parser == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"%s:%d: unknown command %q\", name, lines.line, text)\n\t\t\t\t}\n\t\t\t\tt, err := parser(ctx, name, lines.line, text)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\te = t\n\n\t\t\tcase isMarkdown:\n\t\t\t\t// Collect Markdown lines, including blank lines and indented text.\n\t\t\t\tvar block []string\n\t\t\t\tendLine, endBlock := lines.line-1, -1 // end is last non-empty line\n\t\t\t\tfor ok {\n\t\t\t\t\ttrim := strings.TrimSpace(text)\n\t\t\t\t\tif trim != \"\" {\n\t\t\t\t\t\t// Command breaks text block.\n\t\t\t\t\t\t// Section heading breaks text block in markdown.\n\t\t\t\t\t\tif text[0] == '.' || text[0] == '#' || isSpeakerNote(text) {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif strings.HasPrefix(text, `\\.`) { // Backslash escapes initial period.\n\t\t\t\t\t\t\ttext = text[1:]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tendLine, endBlock = lines.line, len(block)\n\t\t\t\t\t}\n\t\t\t\t\tblock = append(block, text)\n\t\t\t\t\ttext, ok = lines.next()\n\t\t\t\t}\n\t\t\t\tblock = block[:endBlock+1]\n\t\t\t\tlines.line = endLine + 1\n\t\t\t\tif len(block) == 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t// Replace all leading tabs with 4 spaces,\n\t\t\t\t// which render better in code blocks.\n\t\t\t\t// CommonMark defines that for parsing the structure of the file\n\t\t\t\t// a tab is equivalent to 4 spaces, so this change won't\n\t\t\t\t// affect the later parsing at all.\n\t\t\t\t// An alternative would be to apply this to code blocks after parsing,\n\t\t\t\t// at the same time that we update <a> targets, but that turns out\n\t\t\t\t// to be quite difficult to modify in the AST.\n\t\t\t\tfor i, line := range block {\n\t\t\t\t\tif len(line) > 0 && line[0] == '\\t' {\n\t\t\t\t\t\tshort := strings.TrimLeft(line, \"\\t\")\n\t\t\t\t\t\tline = strings.Repeat(\"    \", len(line)-len(short)) + short\n\t\t\t\t\t\tblock[i] = line\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\thtml, err := renderMarkdown([]byte(strings.Join(block, \"\\n\")))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\te = HTML{HTML: html}\n\n\t\t\tdefault:\n\t\t\t\t// Collect text lines.\n\t\t\t\tvar block []string\n\t\t\t\tfor ok && strings.TrimSpace(text) != \"\" {\n\t\t\t\t\t// Command breaks text block.\n\t\t\t\t\t// Section heading breaks text block in markdown.\n\t\t\t\t\tif text[0] == '.' || isSpeakerNote(text) {\n\t\t\t\t\t\tlines.back()\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif strings.HasPrefix(text, `\\.`) { // Backslash escapes initial period.\n\t\t\t\t\t\ttext = text[1:]\n\t\t\t\t\t}\n\t\t\t\t\tblock = append(block, text)\n\t\t\t\t\ttext, ok = lines.next()\n\t\t\t\t}\n\t\t\t\tif len(block) == 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\te = Text{Lines: block}\n\t\t\t}\n\t\t\tif e != nil {\n\t\t\t\tsection.Elem = append(section.Elem, e)\n\t\t\t}\n\t\t\ttext, ok = lines.nextNonEmpty()\n\t\t}\n\t\tif isHeading.MatchString(text) {\n\t\t\tlines.back()\n\t\t}\n\t\tsections = append(sections, section)\n\t}\n\n\tif len(sections) == 0 {\n\t\treturn nil, fmt.Errorf(\"%s:%d: unexpected line: %s\", name, lines.line+1, lines.text[lines.line])\n\t}\n\treturn sections, nil\n}\n\nfunc parseHeader(doc *Doc, isMarkdown bool, lines *Lines) error {\n\tvar ok bool\n\t// First non-empty line starts header.\n\tdoc.Title, ok = lines.nextNonEmpty()\n\tif !ok {\n\t\treturn errors.New(\"unexpected EOF; expected title\")\n\t}\n\tif isMarkdown {\n\t\tdoc.Title = strings.TrimSpace(strings.TrimPrefix(doc.Title, \"#\"))\n\t}\n\n\tfor {\n\t\ttext, ok := lines.next()\n\t\tif !ok {\n\t\t\treturn errors.New(\"unexpected EOF\")\n\t\t}\n\t\tif text == \"\" {\n\t\t\tbreak\n\t\t}\n\t\tif isSpeakerNote(text) {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(text, \"Tags:\") {\n\t\t\ttags := strings.Split(text[len(\"Tags:\"):], \",\")\n\t\t\tfor i := range tags {\n\t\t\t\ttags[i] = strings.TrimSpace(tags[i])\n\t\t\t}\n\t\t\tdoc.Tags = append(doc.Tags, tags...)\n\t\t} else if strings.HasPrefix(text, \"Summary:\") {\n\t\t\tdoc.Summary = strings.TrimSpace(text[len(\"Summary:\"):])\n\t\t} else if strings.HasPrefix(text, \"OldURL:\") {\n\t\t\tdoc.OldURL = append(doc.OldURL, strings.TrimSpace(text[len(\"OldURL:\"):]))\n\t\t} else if t, ok := parseTime(text); ok {\n\t\t\tdoc.Time = t\n\t\t} else if doc.Subtitle == \"\" {\n\t\t\tdoc.Subtitle = text\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"unexpected header line: %q\", text)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc parseAuthors(name, sectionPrefix string, lines *Lines) (authors []Author, err error) {\n\t// This grammar demarcates authors with blanks.\n\n\t// Skip blank lines.\n\tif _, ok := lines.nextNonEmpty(); !ok {\n\t\treturn nil, errors.New(\"unexpected EOF\")\n\t}\n\tlines.back()\n\n\tvar a *Author\n\tfor {\n\t\ttext, ok := lines.next()\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"unexpected EOF\")\n\t\t}\n\n\t\t// If we find a section heading, we're done.\n\t\tif strings.HasPrefix(text, sectionPrefix) {\n\t\t\tlines.back()\n\t\t\tbreak\n\t\t}\n\n\t\tif isSpeakerNote(text) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// If we encounter a blank we're done with this author.\n\t\tif a != nil && len(text) == 0 {\n\t\t\tauthors = append(authors, *a)\n\t\t\ta = nil\n\t\t\tcontinue\n\t\t}\n\t\tif a == nil {\n\t\t\ta = new(Author)\n\t\t}\n\n\t\t// Parse the line. Those that\n\t\t// - begin with @ are twitter names,\n\t\t// - contain slashes are links, or\n\t\t// - contain an @ symbol are an email address.\n\t\t// The rest is just text.\n\t\tvar el Elem\n\t\tswitch {\n\t\tcase strings.HasPrefix(text, \"@\"):\n\t\t\tel = parseAuthorURL(name, \"http://twitter.com/\"+text[1:])\n\t\tcase strings.Contains(text, \":\"):\n\t\t\tel = parseAuthorURL(name, text)\n\t\tcase strings.Contains(text, \"@\"):\n\t\t\tel = parseAuthorURL(name, \"mailto:\"+text)\n\t\t}\n\t\tif l, ok := el.(Link); ok {\n\t\t\tl.Label = text\n\t\t\tel = l\n\t\t}\n\t\tif el == nil {\n\t\t\tel = Text{Lines: []string{text}}\n\t\t}\n\t\ta.Elem = append(a.Elem, el)\n\t}\n\tif a != nil {\n\t\tauthors = append(authors, *a)\n\t}\n\treturn authors, nil\n}\n\nfunc parseAuthorURL(name, text string) Elem {\n\tu, err := url.Parse(text)\n\tif err != nil {\n\t\tlog.Printf(\"parsing %s author block: invalid URL %q: %v\", name, text, err)\n\t\treturn nil\n\t}\n\treturn Link{URL: u}\n}\n\nfunc parseTime(text string) (t time.Time, ok bool) {\n\tt, err := time.Parse(\"15:04 2 Jan 2006\", text)\n\tif err == nil {\n\t\treturn t, true\n\t}\n\tt, err = time.Parse(\"2 Jan 2006\", text)\n\tif err == nil {\n\t\t// at 11am UTC it is the same date everywhere\n\t\tt = t.Add(time.Hour * 11)\n\t\treturn t, true\n\t}\n\treturn time.Time{}, false\n}\n\nfunc isSpeakerNote(s string) bool {\n\treturn strings.HasPrefix(s, \": \") || s == \":\"\n}\n\nfunc trimSpeakerNote(s string) string {\n\tif s == \":\" {\n\t\treturn \"\"\n\t}\n\treturn strings.TrimPrefix(s, \": \")\n}\n\nfunc renderMarkdown(input []byte) (template.HTML, error) {\n\tmd := goldmark.New(goldmark.WithRendererOptions(html.WithUnsafe()))\n\treader := text.NewReader(input)\n\tdoc := md.Parser().Parse(reader)\n\tfixupMarkdown(doc)\n\tvar b strings.Builder\n\tif err := md.Renderer().Render(&b, input, doc); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn template.HTML(b.String()), nil\n}\n\nfunc fixupMarkdown(n ast.Node) {\n\tast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {\n\t\tif entering {\n\t\t\tswitch n := n.(type) {\n\t\t\tcase *ast.Link:\n\t\t\t\tn.SetAttributeString(\"target\", []byte(\"_blank\"))\n\t\t\t\t// https://developers.google.com/web/tools/lighthouse/audits/noopener\n\t\t\t\tn.SetAttributeString(\"rel\", []byte(\"noopener\"))\n\t\t\t}\n\t\t}\n\t\treturn ast.WalkContinue, nil\n\t})\n}\n"
  },
  {
    "path": "present/parse_test.go",
    "content": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestTestdata(t *testing.T) {\n\ttmpl := template.Must(Template().Parse(testTmpl))\n\tfilesP, err := filepath.Glob(\"testdata/*.p\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfilesMD, err := filepath.Glob(\"testdata/*.md\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfiles := append(filesP, filesMD...)\n\tfor _, file := range files {\n\t\tname := filepath.Base(file)\n\t\tif name == \"README\" {\n\t\t\tcontinue\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tdata, err := os.ReadFile(file)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"%s: %v\", file, err)\n\t\t\t}\n\t\t\tmarker := []byte(\"\\n---\\n\")\n\t\t\ti := bytes.Index(data, marker)\n\t\t\tif i < 0 {\n\t\t\t\tt.Fatalf(\"%s: cannot find --- marker in input\", file)\n\t\t\t}\n\t\t\tinput, html := data[:i+1], data[i+len(marker):]\n\t\t\tdoc, err := Parse(bytes.NewReader(input), name, 0)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"%s: %v\", file, err)\n\t\t\t}\n\t\t\tvar buf bytes.Buffer\n\t\t\tif err := doc.Render(&buf, tmpl); err != nil {\n\t\t\t\tt.Fatalf(\"%s: %v\", file, err)\n\t\t\t}\n\t\t\tif !bytes.Equal(buf.Bytes(), html) {\n\t\t\t\tdiffText, err := diff(\"present-test-\", \"want\", html, \"have\", buf.Bytes())\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"%s: diff: %v\", file, err)\n\t\t\t\t}\n\t\t\t\tt.Errorf(\"%s: incorrect html:\\n%s\", file, diffText)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc diff(prefix string, name1 string, b1 []byte, name2 string, b2 []byte) ([]byte, error) {\n\tf1, err := writeTempFile(prefix, b1)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer os.Remove(f1)\n\n\tf2, err := writeTempFile(prefix, b2)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer os.Remove(f2)\n\n\tcmd := \"diff\"\n\tif runtime.GOOS == \"plan9\" {\n\t\tcmd = \"/bin/ape/diff\"\n\t}\n\n\tdata, err := exec.Command(cmd, \"-u\", f1, f2).Output()\n\tif len(data) > 0 {\n\t\t// diff exits with a non-zero status when the files don't match.\n\t\t// Ignore that failure as long as we get output.\n\t\terr = nil\n\t} else if exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {\n\t\terr = fmt.Errorf(\"%w\\nstderr:\\n%s)\", err, exit.Stderr)\n\t}\n\n\tdata = bytes.Replace(data, []byte(f1), []byte(name1), -1)\n\tdata = bytes.Replace(data, []byte(f2), []byte(name2), -1)\n\n\treturn data, err\n}\n\nfunc writeTempFile(prefix string, data []byte) (string, error) {\n\tfile, err := os.CreateTemp(\"\", prefix)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t_, err = file.Write(data)\n\tif err1 := file.Close(); err == nil {\n\t\terr = err1\n\t}\n\tif err != nil {\n\t\tos.Remove(file.Name())\n\t\treturn \"\", err\n\t}\n\treturn file.Name(), nil\n}\n\nvar testTmpl = `\n{{define \"root\" -}}\n<h1>{{.Title}}</h1>\n{{with .Subtitle}}<h2>{{.}}</h2>\n{{end -}}\n{{range .Authors}}<author>\n{{range .Elem}}{{elem $.Template .}}{{end}}</author>\n{{end -}}\n{{range .Sections}}<section>{{elem $.Template .}}</section>\n{{end -}}\n{{end}}\n\n{{define \"newline\"}}{{/* No automatic line break. Paragraphs are free-form. */}}\n{{end}}\n\n{{define \"section\"}}\n{{if .Title}}<h2 id=\"TOC_{{.FormattedNumber}}\">{{.Title}}</h2>\n{{end -}}\n{{range .Elem}}{{elem $.Template .}}{{end}}\n{{- end}}\n\n{{define \"list\" -}}\n<ul>\n{{range .Bullet -}}\n<li>{{style .}}</li>\n{{end -}}\n</ul>\n{{end}}\n\n{{define \"text\" -}}\n{{if .Pre -}}\n<pre>{{range .Lines}}{{.}}{{end}}</pre>\n{{else -}}\n<p>{{range $i, $l := .Lines}}{{if $i}}{{template \"newline\"}}{{end}}{{style $l}}{{end}}</p>\n{{end -}}\n{{end}}\n\n{{define \"code\" -}}\n{{if .Play -}}\n<div class=\"playground\">{{.Text}}</div>\n{{else -}}\n<div class=\"code\">{{.Text}}</div>\n{{end -}}\n{{end}}\n\n{{define \"image\" -}}\n<img src=\"{{.URL}}\"{{with .Height}} height=\"{{.}}\"{{end}}{{with .Width}} width=\"{{.}}\"{{end}} alt=\"\">\n{{end}}\n\n{{define \"caption\" -}}\n<figcaption>{{style .Text}}</figcaption>\n{{end}}\n\n{{define \"iframe\" -}}\n<iframe src=\"{{.URL}}\"{{with .Height}} height=\"{{.}}\"{{end}}{{with .Width}} width=\"{{.}}\"{{end}}></iframe>\n{{end}}\n\n{{define \"link\" -}}\n<p class=\"link\"><a href=\"{{.URL}}\">{{style .Label}}</a></p>\n{{end}}\n\n{{define \"html\" -}}{{.HTML}}{{end}}\n`\n"
  },
  {
    "path": "present/style.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"bytes\"\n\t\"html\"\n\t\"html/template\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n)\n\n/*\n\tFonts are demarcated by an initial and final char bracketing a\n\tspace-delimited word, plus possibly some terminal punctuation.\n\tThe chars are\n\t\t_ for italic\n\t\t* for bold\n\t\t` (back quote) for fixed width.\n\tInner appearances of the char become spaces. For instance,\n\t\t_this_is_italic_!\n\tbecomes\n\t\t<i>this is italic</i>!\n*/\n\nfunc init() {\n\tfuncs[\"style\"] = Style\n}\n\n// Style returns s with HTML entities escaped and font indicators turned into\n// HTML font tags.\nfunc Style(s string) template.HTML {\n\treturn template.HTML(font(html.EscapeString(s)))\n}\n\n// font returns s with font indicators turned into HTML font tags.\nfunc font(s string) string {\n\tif !strings.ContainsAny(s, \"[`_*\") {\n\t\treturn s\n\t}\n\twords := split(s)\n\tvar b bytes.Buffer\nWord:\n\tfor w, word := range words {\n\t\tif len(word) < 2 {\n\t\t\tcontinue Word\n\t\t}\n\t\tif link, _ := parseInlineLink(word); link != \"\" {\n\t\t\twords[w] = link\n\t\t\tcontinue Word\n\t\t}\n\t\tconst marker = \"_*`\"\n\t\t// Initial punctuation is OK but must be peeled off.\n\t\tfirst := strings.IndexAny(word, marker)\n\t\tif first == -1 {\n\t\t\tcontinue Word\n\t\t}\n\t\t// Opening marker must be at the beginning of the token or else preceded by punctuation.\n\t\tif first != 0 {\n\t\t\tr, _ := utf8.DecodeLastRuneInString(word[:first])\n\t\t\tif !unicode.IsPunct(r) {\n\t\t\t\tcontinue Word\n\t\t\t}\n\t\t}\n\t\topen, word := word[:first], word[first:]\n\t\tchar := word[0] // ASCII is OK.\n\t\tclose := \"\"\n\t\tswitch char {\n\t\tdefault:\n\t\t\tcontinue Word\n\t\tcase '_':\n\t\t\topen += \"<i>\"\n\t\t\tclose = \"</i>\"\n\t\tcase '*':\n\t\t\topen += \"<b>\"\n\t\t\tclose = \"</b>\"\n\t\tcase '`':\n\t\t\topen += \"<code>\"\n\t\t\tclose = \"</code>\"\n\t\t}\n\t\t// Closing marker must be at the end of the token or else followed by punctuation.\n\t\tlast := strings.LastIndex(word, word[:1])\n\t\tif last == 0 {\n\t\t\tcontinue Word\n\t\t}\n\t\tif last+1 != len(word) {\n\t\t\tr, _ := utf8.DecodeRuneInString(word[last+1:])\n\t\t\tif !unicode.IsPunct(r) {\n\t\t\t\tcontinue Word\n\t\t\t}\n\t\t}\n\t\thead, tail := word[:last+1], word[last+1:]\n\t\tb.Reset()\n\t\tb.WriteString(open)\n\t\tvar wid int\n\t\tfor i := 1; i < len(head)-1; i += wid {\n\t\t\tvar r rune\n\t\t\tr, wid = utf8.DecodeRuneInString(head[i:])\n\t\t\tif r != rune(char) {\n\t\t\t\t// Ordinary character.\n\t\t\t\tb.WriteRune(r)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif head[i+1] != char {\n\t\t\t\t// Inner char becomes space.\n\t\t\t\tb.WriteRune(' ')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Doubled char becomes real char.\n\t\t\t// Not worth worrying about \"_x__\".\n\t\t\tb.WriteByte(char)\n\t\t\twid++ // Consumed two chars, both ASCII.\n\t\t}\n\t\tb.WriteString(close) // Write closing tag.\n\t\tb.WriteString(tail)  // Restore trailing punctuation.\n\t\twords[w] = b.String()\n\t}\n\treturn strings.Join(words, \"\")\n}\n\n// split is like strings.Fields but also returns the runs of spaces\n// and treats inline links as distinct words.\nfunc split(s string) []string {\n\tvar (\n\t\twords = make([]string, 0, 10)\n\t\tstart = 0\n\t)\n\n\t// appendWord appends the string s[start:end] to the words slice.\n\t// If the word contains the beginning of a link, the non-link portion\n\t// of the word and the entire link are appended as separate words,\n\t// and the start index is advanced to the end of the link.\n\tappendWord := func(end int) {\n\t\tif j := strings.Index(s[start:end], \"[[\"); j > -1 {\n\t\t\tif _, l := parseInlineLink(s[start+j:]); l > 0 {\n\t\t\t\t// Append portion before link, if any.\n\t\t\t\tif j > 0 {\n\t\t\t\t\twords = append(words, s[start:start+j])\n\t\t\t\t}\n\t\t\t\t// Append link itself.\n\t\t\t\twords = append(words, s[start+j:start+j+l])\n\t\t\t\t// Advance start index to end of link.\n\t\t\t\tstart = start + j + l\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\t// No link; just add the word.\n\t\twords = append(words, s[start:end])\n\t\tstart = end\n\t}\n\n\twasSpace := false\n\tfor i, r := range s {\n\t\tisSpace := unicode.IsSpace(r)\n\t\tif i > start && isSpace != wasSpace {\n\t\t\tappendWord(i)\n\t\t}\n\t\twasSpace = isSpace\n\t}\n\tfor start < len(s) {\n\t\tappendWord(len(s))\n\t}\n\treturn words\n}\n"
  },
  {
    "path": "present/style_test.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSplit(t *testing.T) {\n\tvar tests = []struct {\n\t\tin  string\n\t\tout []string\n\t}{\n\t\t{\"\", []string{}},\n\t\t{\" \", []string{\" \"}},\n\t\t{\"abc\", []string{\"abc\"}},\n\t\t{\"abc def\", []string{\"abc\", \" \", \"def\"}},\n\t\t{\"abc def \", []string{\"abc\", \" \", \"def\", \" \"}},\n\t\t{\"hey [[http://golang.org][Gophers]] around\",\n\t\t\t[]string{\"hey\", \" \", \"[[http://golang.org][Gophers]]\", \" \", \"around\"}},\n\t\t{\"A [[http://golang.org/doc][two words]] link\",\n\t\t\t[]string{\"A\", \" \", \"[[http://golang.org/doc][two words]]\", \" \", \"link\"}},\n\t\t{\"Visit [[http://golang.org/doc]] now\",\n\t\t\t[]string{\"Visit\", \" \", \"[[http://golang.org/doc]]\", \" \", \"now\"}},\n\t\t{\"not [[http://golang.org/doc][a [[link]] ]] around\",\n\t\t\t[]string{\"not\", \" \", \"[[http://golang.org/doc][a [[link]]\", \" \", \"]]\", \" \", \"around\"}},\n\t\t{\"[[http://golang.org][foo bar]]\",\n\t\t\t[]string{\"[[http://golang.org][foo bar]]\"}},\n\t\t{\"ends with [[http://golang.org][link]]\",\n\t\t\t[]string{\"ends\", \" \", \"with\", \" \", \"[[http://golang.org][link]]\"}},\n\t\t{\"my talk ([[http://talks.golang.org/][slides here]])\",\n\t\t\t[]string{\"my\", \" \", \"talk\", \" \", \"(\", \"[[http://talks.golang.org/][slides here]]\", \")\"}},\n\t}\n\tfor _, test := range tests {\n\t\tout := split(test.in)\n\t\tif !reflect.DeepEqual(out, test.out) {\n\t\t\tt.Errorf(\"split(%q):\\ngot\\t%q\\nwant\\t%q\", test.in, out, test.out)\n\t\t}\n\t}\n}\n\nfunc TestFont(t *testing.T) {\n\tvar tests = []struct {\n\t\tin  string\n\t\tout string\n\t}{\n\t\t{\"\", \"\"},\n\t\t{\" \", \" \"},\n\t\t{\"\\tx\", \"\\tx\"},\n\t\t{\"_a_\", \"<i>a</i>\"},\n\t\t{\"*a*\", \"<b>a</b>\"},\n\t\t{\"`a`\", \"<code>a</code>\"},\n\t\t{\"_a_b_\", \"<i>a b</i>\"},\n\t\t{\"_a__b_\", \"<i>a_b</i>\"},\n\t\t{\"_a___b_\", \"<i>a_ b</i>\"},\n\t\t{\"*a**b*?\", \"<b>a*b</b>?\"},\n\t\t{\"_a_<>_b_.\", \"<i>a <> b</i>.\"},\n\t\t{\"(_a_)\", \"(<i>a</i>)\"},\n\t\t{\"((_a_), _b_, _c_).\", \"((<i>a</i>), <i>b</i>, <i>c</i>).\"},\n\t\t{\"(_a)\", \"(_a)\"},\n\t\t{\"(_a)\", \"(_a)\"},\n\t\t{\"_Why_use_scoped__ptr_? Use plain ***ptr* instead.\", \"<i>Why use scoped_ptr</i>? Use plain <b>*ptr</b> instead.\"},\n\t\t{\"_hey_ [[http://golang.org][*Gophers*]] *around*\",\n\t\t\t`<i>hey</i> <a href=\"http://golang.org\" target=\"_blank\"><b>Gophers</b></a> <b>around</b>`},\n\t\t{\"_hey_ [[http://golang.org][so _many_ *Gophers*]] *around*\",\n\t\t\t`<i>hey</i> <a href=\"http://golang.org\" target=\"_blank\">so <i>many</i> <b>Gophers</b></a> <b>around</b>`},\n\t\t{\"Visit [[http://golang.org]] now\",\n\t\t\t`Visit <a href=\"http://golang.org\" target=\"_blank\">golang.org</a> now`},\n\t\t{\"my talk ([[http://talks.golang.org/][slides here]])\",\n\t\t\t`my talk (<a href=\"http://talks.golang.org/\" target=\"_blank\">slides here</a>)`},\n\t\t{\"Markup—_especially_italic_text_—can easily be overused.\",\n\t\t\t`Markup—<i>especially italic text</i>—can easily be overused.`},\n\t\t{\"`go`get`'s codebase\", // ascii U+0027 ' before s\n\t\t\t`<code>go get</code>'s codebase`},\n\t\t{\"`go`get`’s codebase\", // unicode right single quote U+2019 ’ before s\n\t\t\t`<code>go get</code>’s codebase`},\n\t\t{\"a_variable_name\",\n\t\t\t`a_variable_name`},\n\t}\n\tfor _, test := range tests {\n\t\tout := font(test.in)\n\t\tif out != test.out {\n\t\t\tt.Errorf(\"font(%q):\\ngot\\t%q\\nwant\\t%q\", test.in, out, test.out)\n\t\t}\n\t}\n}\n\nfunc TestStyle(t *testing.T) {\n\tvar tests = []struct {\n\t\tin  string\n\t\tout string\n\t}{\n\t\t{\"\", \"\"},\n\t\t{\" \", \" \"},\n\t\t{\"\\tx\", \"\\tx\"},\n\t\t{\"_a_\", \"<i>a</i>\"},\n\t\t{\"*a*\", \"<b>a</b>\"},\n\t\t{\"`a`\", \"<code>a</code>\"},\n\t\t{\"_a_b_\", \"<i>a b</i>\"},\n\t\t{\"_a__b_\", \"<i>a_b</i>\"},\n\t\t{\"_a___b_\", \"<i>a_ b</i>\"},\n\t\t{\"*a**b*?\", \"<b>a*b</b>?\"},\n\t\t{\"_a_<>_b_.\", \"<i>a &lt;&gt; b</i>.\"},\n\t\t{\"(_a_<>_b_)\", \"(<i>a &lt;&gt; b</i>)\"},\n\t\t{\"((_a_), _b_, _c_).\", \"((<i>a</i>), <i>b</i>, <i>c</i>).\"},\n\t\t{\"(_a)\", \"(_a)\"},\n\t}\n\tfor _, test := range tests {\n\t\tout := string(Style(test.in))\n\t\tif out != test.out {\n\t\t\tt.Errorf(\"style(%q):\\ngot\\t%q\\nwant\\t%q\", test.in, out, test.out)\n\t\t}\n\t}\n}\n\nfunc ExampleStyle() {\n\tconst s = \"*Gophers* are _clearly_ > *cats*!\"\n\tfmt.Println(Style(s))\n\t// Output: <b>Gophers</b> are <i>clearly</i> &gt; <b>cats</b>!\n}\n"
  },
  {
    "path": "present/testdata/README",
    "content": "This directory contains test data for present's TestTestdata.\nEach file named *.p or *.md is expected to contain a present\narticle, then a --- line, then the HTML output for that article.\n\nBy convention, testdata files with a .p extension use legacy present\nsyntax, while testdata file with a .md extension use Markdown.\nThis is only a convention: the Markdown syntax must still begi\nwith \"# \" to be recognized as Markdown by the present parser.\n\nOther files in this directory are supporting files for the articles.\n"
  },
  {
    "path": "present/testdata/basic.md",
    "content": "# Title\nSubtitle\n\nName\n\n## Heading\n\nText\non two lines.\n\nMore text.\n\n---\n<h1>Title</h1>\n<h2>Subtitle</h2>\n<author>\n<p>Name</p>\n</author>\n<section>\n<h2 id=\"TOC_1.\">Heading</h2>\n<p>Text\non two lines.</p>\n<p>More text.</p>\n</section>\n"
  },
  {
    "path": "present/testdata/basic.p",
    "content": "Title\nSubtitle\n\nName\n\n* Heading\n\nText\non two lines.\n\nMore text.\n\n---\n<h1>Title</h1>\n<h2>Subtitle</h2>\n<author>\n<p>Name</p>\n</author>\n<section>\n<h2 id=\"TOC_1.\">Heading</h2>\n<p>Text\non two lines.</p>\n<p>More text.</p>\n</section>\n"
  },
  {
    "path": "present/testdata/code.md",
    "content": "# Code\n\n##\n\nCode:\n\n.code testdata/code.txt\n\nSnippet:\n\n.code testdata/code.txt /Snippet/\n\nHighlight:\n\n.code testdata/code.txt HL1\n\n---\n<h1>Code</h1>\n<section>\n<p>Code:</p>\n<div class=\"code\">\n<pre><span num=\"1\">code file</span>\n<span num=\"2\">Snippet</span>\n<span num=\"3\">important</span>\n</pre>\n</div>\n<p>Snippet:</p>\n<div class=\"code\">\n<pre><span num=\"2\">Snippet</span>\n</pre>\n</div>\n<p>Highlight:</p>\n<div class=\"code\">\n<pre><span num=\"1\">code file</span>\n<span num=\"2\">Snippet</span>\n<span num=\"3\"><b>important</b></span>\n</pre>\n</div>\n</section>\n"
  },
  {
    "path": "present/testdata/code.p",
    "content": "Code\n\n*\n\nCode:\n\n.code testdata/code.txt\n\nSnippet:\n\n.code testdata/code.txt /Snippet/\n\nHighlight:\n\n.code testdata/code.txt HL1\n\n---\n<h1>Code</h1>\n<section>\n<p>Code:</p>\n<div class=\"code\">\n<pre><span num=\"1\">code file</span>\n<span num=\"2\">Snippet</span>\n<span num=\"3\">important</span>\n</pre>\n</div>\n<p>Snippet:</p>\n<div class=\"code\">\n<pre><span num=\"2\">Snippet</span>\n</pre>\n</div>\n<p>Highlight:</p>\n<div class=\"code\">\n<pre><span num=\"1\">code file</span>\n<span num=\"2\">Snippet</span>\n<span num=\"3\"><b>important</b></span>\n</pre>\n</div>\n</section>\n"
  },
  {
    "path": "present/testdata/code.txt",
    "content": "code file\nSnippet\nimportant // HL1\n"
  },
  {
    "path": "present/testdata/list.md",
    "content": "# List\n\n##\n\n- Item 1\n on two lines.\n- Item 2.\n- Item 3.\n\n- Item 4 in list despite preceding blank line.\n- Item 5.\n\n---\n<h1>List</h1>\n<section>\n<ul>\n<li>\n<p>Item 1\non two lines.</p>\n</li>\n<li>\n<p>Item 2.</p>\n</li>\n<li>\n<p>Item 3.</p>\n</li>\n<li>\n<p>Item 4 in list despite preceding blank line.</p>\n</li>\n<li>\n<p>Item 5.</p>\n</li>\n</ul>\n</section>\n"
  },
  {
    "path": "present/testdata/list.p",
    "content": "List\n\n*\n\n- Item 1\n on two lines.\n- Item 2.\n- Item 3.\n\n- Item 1 in new list.\n- Item 2.\n\n---\n<h1>List</h1>\n<section>\n<ul>\n<li>Item 1\non two lines.</li>\n<li>Item 2.</li>\n<li>Item 3.</li>\n</ul>\n<ul>\n<li>Item 1 in new list.</li>\n<li>Item 2.</li>\n</ul>\n</section>\n"
  },
  {
    "path": "present/testdata/media.html",
    "content": "<!-- media.html -->\n"
  },
  {
    "path": "present/testdata/media.md",
    "content": "# Media\n\n##\n\n.image gopher.jpg _ 100\n.caption A gopher.\n\n.iframe https://golang.org/\n\n.link https://golang.org/ The Gopher's home.\n\n.html testdata/media.html\n\n---\n<h1>Media</h1>\n<section>\n<img src=\"gopher.jpg\" width=\"100\" alt=\"\">\n<figcaption>A gopher.</figcaption>\n<iframe src=\"https://golang.org/\"></iframe>\n<p class=\"link\"><a href=\"https://golang.org/\">The Gopher&#39;s home.</a></p>\n<!-- media.html -->\n</section>\n"
  },
  {
    "path": "present/testdata/media.p",
    "content": "Media\n\n*\n\nThe Gopher\n.image gopher.jpg _ 100\n.caption A gopher.\n\n.iframe https://golang.org/\n\n.link https://golang.org/ The Gopher's home.\n\n.html testdata/media.html\n\n---\n<h1>Media</h1>\n<section>\n<p>The Gopher</p>\n<img src=\"gopher.jpg\" width=\"100\" alt=\"\">\n<figcaption>A gopher.</figcaption>\n<iframe src=\"https://golang.org/\"></iframe>\n<p class=\"link\"><a href=\"https://golang.org/\">The Gopher&#39;s home.</a></p>\n<!-- media.html -->\n</section>\n"
  },
  {
    "path": "present/testdata/pre.md",
    "content": "# Pre\n\n##\n\nPre with tab:\n\n\tcode block\n\ton two lines\n\nText with space:\n\n now a text block\n on two lines\n\nPre with blank line:\n\n\tbefore\n\n\tafter\n\nEOF\n\n---\n<h1>Pre</h1>\n<section>\n<p>Pre with tab:</p>\n<pre><code>code block\non two lines\n</code></pre>\n<p>Text with space:</p>\n<p>now a text block\non two lines</p>\n<p>Pre with blank line:</p>\n<pre><code>before\n\nafter\n</code></pre>\n<p>EOF</p>\n</section>\n"
  },
  {
    "path": "present/testdata/pre.p",
    "content": "Pre\n\n*\n\nPre with tab:\n\n\tcode block\n\ton two lines\n\nPre with space:\n\n code block\n on two lines\n\nPre with blank line:\n\n\tbefore\n\n\tafter\n\nEOF\n\n---\n<h1>Pre</h1>\n<section>\n<p>Pre with tab:</p>\n<pre>code block\non two lines</pre>\n<p>Pre with space:</p>\n<pre>code block\non two lines</pre>\n<p>Pre with blank line:</p>\n<pre>before\n\nafter</pre>\n<p>EOF</p>\n</section>\n"
  },
  {
    "path": "present/video.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage present\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc init() {\n\tRegister(\"video\", parseVideo)\n}\n\ntype Video struct {\n\tCmd        string // original command from present source\n\tURL        string\n\tSourceType string\n\tWidth      int\n\tHeight     int\n}\n\nfunc (v Video) PresentCmd() string   { return v.Cmd }\nfunc (v Video) TemplateName() string { return \"video\" }\n\nfunc parseVideo(ctx *Context, fileName string, lineno int, text string) (Elem, error) {\n\targs := strings.Fields(text)\n\tif len(args) < 3 {\n\t\treturn nil, fmt.Errorf(\"incorrect video invocation: %q\", text)\n\t}\n\tvid := Video{Cmd: text, URL: args[1], SourceType: args[2]}\n\ta, err := parseArgs(fileName, lineno, args[3:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch len(a) {\n\tcase 0:\n\t\t// no size parameters\n\tcase 2:\n\t\t// If a parameter is empty (underscore) or invalid\n\t\t// leave the field set to zero. The \"video\" action\n\t\t// template will then omit that vid tag attribute and\n\t\t// the browser will calculate the value to preserve\n\t\t// the aspect ratio.\n\t\tif v, ok := a[0].(int); ok {\n\t\t\tvid.Height = v\n\t\t}\n\t\tif v, ok := a[1].(int); ok {\n\t\t\tvid.Width = v\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"incorrect video invocation: %q\", text)\n\t}\n\treturn vid, nil\n}\n"
  },
  {
    "path": "refactor/README",
    "content": "golang.org/x/tools/refactor: libraries for refactoring tools.\n"
  },
  {
    "path": "refactor/eg/eg.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package eg implements the example-based refactoring tool whose\n// command-line is defined in golang.org/x/tools/cmd/eg.\npackage eg // import \"golang.org/x/tools/refactor/eg\"\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/printer\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"maps\"\n\t\"os\"\n)\n\nconst Help = `\nThis tool implements example-based refactoring of expressions.\n\nThe transformation is specified as a Go file defining two functions,\n'before' and 'after', of identical types.  Each function body consists\nof a single statement: either a return statement with a single\n(possibly multi-valued) expression, or an expression statement.  The\n'before' expression specifies a pattern and the 'after' expression its\nreplacement.\n\n\tpackage P\n \timport ( \"errors\"; \"fmt\" )\n \tfunc before(s string) error { return fmt.Errorf(\"%s\", s) }\n \tfunc after(s string)  error { return errors.New(s) }\n\nThe expression statement form is useful when the expression has no\nresult, for example:\n\n \tfunc before(msg string) { log.Fatalf(\"%s\", msg) }\n \tfunc after(msg string)  { log.Fatal(msg) }\n\nThe parameters of both functions are wildcards that may match any\nexpression assignable to that type.  If the pattern contains multiple\noccurrences of the same parameter, each must match the same expression\nin the input for the pattern to match.  If the replacement contains\nmultiple occurrences of the same parameter, the expression will be\nduplicated, possibly changing the side-effects.\n\nThe tool analyses all Go code in the packages specified by the\narguments, replacing all occurrences of the pattern with the\nsubstitution.\n\nSo, the transform above would change this input:\n\terr := fmt.Errorf(\"%s\", \"error: \" + msg)\nto this output:\n\terr := errors.New(\"error: \" + msg)\n\nIdentifiers, including qualified identifiers (p.X) are considered to\nmatch only if they denote the same object.  This allows correct\nmatching even in the presence of dot imports, named imports and\nlocally shadowed package names in the input program.\n\nMatching of type syntax is semantic, not syntactic: type syntax in the\npattern matches type syntax in the input if the types are identical.\nThus, func(x int) matches func(y int).\n\nThis tool was inspired by other example-based refactoring tools,\n'gofmt -r' for Go and Refaster for Java.\n\n\nLIMITATIONS\n===========\n\nEXPRESSIVENESS\n\nOnly refactorings that replace one expression with another, regardless\nof the expression's context, may be expressed.  Refactoring arbitrary\nstatements (or sequences of statements) is a less well-defined problem\nand is less amenable to this approach.\n\nA pattern that contains a function literal (and hence statements)\nnever matches.\n\nThere is no way to generalize over related types, e.g. to express that\na wildcard may have any integer type, for example.\n\nIt is not possible to replace an expression by one of a different\ntype, even in contexts where this is legal, such as x in fmt.Print(x).\n\nThe struct literals T{x} and T{K: x} cannot both be matched by a single\ntemplate.\n\n\nSAFETY\n\nVerifying that a transformation does not introduce type errors is very\ncomplex in the general case.  An innocuous-looking replacement of one\nconstant by another (e.g. 1 to 2) may cause type errors relating to\narray types and indices, for example.  The tool performs only very\nsuperficial checks of type preservation.\n\n\nIMPORTS\n\nAlthough the matching algorithm is fully aware of scoping rules, the\nreplacement algorithm is not, so the replacement code may contain\nincorrect identifier syntax for imported objects if there are dot\nimports, named imports or locally shadowed package names in the input\nprogram.\n\nImports are added as needed, but they are not removed as needed.\nRun 'goimports' on the modified file for now.\n\nDot imports are forbidden in the template.\n\n\nTIPS\n====\n\nSometimes a little creativity is required to implement the desired\nmigration.  This section lists a few tips and tricks.\n\nTo remove the final parameter from a function, temporarily change the\nfunction signature so that the final parameter is variadic, as this\nallows legal calls both with and without the argument.  Then use eg to\nremove the final argument from all callers, and remove the variadic\nparameter by hand.  The reverse process can be used to add a final\nparameter.\n\nTo add or remove parameters other than the final one, you must do it in\nstages: (1) declare a variant function f' with a different name and the\ndesired parameters; (2) use eg to transform calls to f into calls to f',\nchanging the arguments as needed; (3) change the declaration of f to\nmatch f'; (4) use eg to rename f' to f in all calls; (5) delete f'.\n`\n\n// TODO(adonovan): expand upon the above documentation as an HTML page.\n\n// A Transformer represents a single example-based transformation.\ntype Transformer struct {\n\tfset           *token.FileSet\n\tverbose        bool\n\tinfo           *types.Info // combined type info for template/input/output ASTs\n\tseenInfos      map[*types.Info]bool\n\twildcards      map[*types.Var]bool                // set of parameters in func before()\n\tenv            map[string]ast.Expr                // maps parameter name to wildcard binding\n\timportedObjs   map[types.Object]*ast.SelectorExpr // objects imported by after().\n\tbefore, after  ast.Expr\n\tafterStmts     []ast.Stmt\n\tallowWildcards bool\n\n\t// Working state of Transform():\n\tnsubsts    int            // number of substitutions made\n\tcurrentPkg *types.Package // package of current call\n}\n\n// NewTransformer returns a transformer based on the specified template,\n// a single-file package containing \"before\" and \"after\" functions as\n// described in the package documentation.\n// tmplInfo is the type information for tmplFile.\nfunc NewTransformer(fset *token.FileSet, tmplPkg *types.Package, tmplFile *ast.File, tmplInfo *types.Info, verbose bool) (*Transformer, error) {\n\t// These maps are required by types.Info.TypeOf.\n\tif tmplInfo.Types == nil || tmplInfo.Defs == nil || tmplInfo.Uses == nil {\n\t\treturn nil, errors.New(\"eg.NewTransformer: types.Info argument missing one of Types, Defs or Uses\")\n\t}\n\t// Check the template.\n\tbeforeSig := funcSig(tmplPkg, \"before\")\n\tif beforeSig == nil {\n\t\treturn nil, fmt.Errorf(\"no 'before' func found in template\")\n\t}\n\tafterSig := funcSig(tmplPkg, \"after\")\n\tif afterSig == nil {\n\t\treturn nil, fmt.Errorf(\"no 'after' func found in template\")\n\t}\n\n\t// TODO(adonovan): should we also check the names of the params match?\n\tif !types.Identical(afterSig, beforeSig) {\n\t\treturn nil, fmt.Errorf(\"before %s and after %s functions have different signatures\",\n\t\t\tbeforeSig, afterSig)\n\t}\n\n\tfor _, imp := range tmplFile.Imports {\n\t\tif imp.Name != nil && imp.Name.Name == \".\" {\n\t\t\t// Dot imports are currently forbidden.  We\n\t\t\t// make the simplifying assumption that all\n\t\t\t// imports are regular, without local renames.\n\t\t\treturn nil, fmt.Errorf(\"dot-import (of %s) in template\", imp.Path.Value)\n\t\t}\n\t}\n\tvar beforeDecl, afterDecl *ast.FuncDecl\n\tfor _, decl := range tmplFile.Decls {\n\t\tif decl, ok := decl.(*ast.FuncDecl); ok {\n\t\t\tswitch decl.Name.Name {\n\t\t\tcase \"before\":\n\t\t\t\tbeforeDecl = decl\n\t\t\tcase \"after\":\n\t\t\t\tafterDecl = decl\n\t\t\t}\n\t\t}\n\t}\n\n\tbefore, err := soleExpr(beforeDecl)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"before: %s\", err)\n\t}\n\tafterStmts, after, err := stmtAndExpr(afterDecl)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"after: %s\", err)\n\t}\n\n\twildcards := make(map[*types.Var]bool)\n\tfor v := range beforeSig.Params().Variables() {\n\t\twildcards[v] = true\n\t}\n\n\t// checkExprTypes returns an error if Tb (type of before()) is not\n\t// safe to replace with Ta (type of after()).\n\t//\n\t// Only superficial checks are performed, and they may result in both\n\t// false positives and negatives.\n\t//\n\t// Ideally, we would only require that the replacement be assignable\n\t// to the context of a specific pattern occurrence, but the type\n\t// checker doesn't record that information and it's complex to deduce.\n\t// A Go type cannot capture all the constraints of a given expression\n\t// context, which may include the size, constness, signedness,\n\t// namedness or constructor of its type, and even the specific value\n\t// of the replacement.  (Consider the rule that array literal keys\n\t// must be unique.)  So we cannot hope to prove the safety of a\n\t// transformation in general.\n\tTb := tmplInfo.TypeOf(before)\n\tTa := tmplInfo.TypeOf(after)\n\tif types.AssignableTo(Tb, Ta) {\n\t\t// safe: replacement is assignable to pattern.\n\t} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {\n\t\t// safe: pattern has void type (must appear in an ExprStmt).\n\t} else {\n\t\treturn nil, fmt.Errorf(\"%s is not a safe replacement for %s\", Ta, Tb)\n\t}\n\n\ttr := &Transformer{\n\t\tfset:           fset,\n\t\tverbose:        verbose,\n\t\twildcards:      wildcards,\n\t\tallowWildcards: true,\n\t\tseenInfos:      make(map[*types.Info]bool),\n\t\timportedObjs:   make(map[types.Object]*ast.SelectorExpr),\n\t\tbefore:         before,\n\t\tafter:          after,\n\t\tafterStmts:     afterStmts,\n\t}\n\n\t// Combine type info from the template and input packages, and\n\t// type info for the synthesized ASTs too.  This saves us\n\t// having to book-keep where each ast.Node originated as we\n\t// construct the resulting hybrid AST.\n\ttr.info = &types.Info{\n\t\tTypes:      make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:       make(map[*ast.Ident]types.Object),\n\t\tUses:       make(map[*ast.Ident]types.Object),\n\t\tSelections: make(map[*ast.SelectorExpr]*types.Selection),\n\t}\n\tmergeTypeInfo(tr.info, tmplInfo)\n\n\t// Compute set of imported objects required by after().\n\t// TODO(adonovan): reject dot-imports in pattern\n\tast.Inspect(after, func(n ast.Node) bool {\n\t\tif n, ok := n.(*ast.SelectorExpr); ok {\n\t\t\tif _, ok := tr.info.Selections[n]; !ok {\n\t\t\t\t// qualified ident\n\t\t\t\tobj := tr.info.Uses[n.Sel]\n\t\t\t\ttr.importedObjs[obj] = n\n\t\t\t\treturn false // prune\n\t\t\t}\n\t\t}\n\t\treturn true // recur\n\t})\n\n\treturn tr, nil\n}\n\n// WriteAST is a convenience function that writes AST f to the specified file.\nfunc WriteAST(fset *token.FileSet, filename string, f *ast.File) (err error) {\n\tfh, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err2 := fh.Close(); err != nil {\n\t\t\terr = err2 // prefer earlier error\n\t\t}\n\t}()\n\treturn format.Node(fh, fset, f)\n}\n\n// -- utilities --------------------------------------------------------\n\n// funcSig returns the signature of the specified package-level function.\nfunc funcSig(pkg *types.Package, name string) *types.Signature {\n\tif f, ok := pkg.Scope().Lookup(name).(*types.Func); ok {\n\t\treturn f.Type().(*types.Signature)\n\t}\n\treturn nil\n}\n\n// soleExpr returns the sole expression in the before/after template function.\nfunc soleExpr(fn *ast.FuncDecl) (ast.Expr, error) {\n\tif fn.Body == nil {\n\t\treturn nil, fmt.Errorf(\"no body\")\n\t}\n\tif len(fn.Body.List) != 1 {\n\t\treturn nil, fmt.Errorf(\"must contain a single statement\")\n\t}\n\tswitch stmt := fn.Body.List[0].(type) {\n\tcase *ast.ReturnStmt:\n\t\tif len(stmt.Results) != 1 {\n\t\t\treturn nil, fmt.Errorf(\"return statement must have a single operand\")\n\t\t}\n\t\treturn stmt.Results[0], nil\n\n\tcase *ast.ExprStmt:\n\t\treturn stmt.X, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"must contain a single return or expression statement\")\n}\n\n// stmtAndExpr returns the expression in the last return statement as well as the preceding lines.\nfunc stmtAndExpr(fn *ast.FuncDecl) ([]ast.Stmt, ast.Expr, error) {\n\tif fn.Body == nil {\n\t\treturn nil, nil, fmt.Errorf(\"no body\")\n\t}\n\n\tn := len(fn.Body.List)\n\tif n == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"must contain at least one statement\")\n\t}\n\n\tstmts, last := fn.Body.List[:n-1], fn.Body.List[n-1]\n\n\tswitch last := last.(type) {\n\tcase *ast.ReturnStmt:\n\t\tif len(last.Results) != 1 {\n\t\t\treturn nil, nil, fmt.Errorf(\"return statement must have a single operand\")\n\t\t}\n\t\treturn stmts, last.Results[0], nil\n\n\tcase *ast.ExprStmt:\n\t\treturn stmts, last.X, nil\n\t}\n\n\treturn nil, nil, fmt.Errorf(\"must end with a single return or expression statement\")\n}\n\n// mergeTypeInfo adds type info from src to dst.\nfunc mergeTypeInfo(dst, src *types.Info) {\n\tmaps.Copy(dst.Types, src.Types)\n\tmaps.Copy(dst.Defs, src.Defs)\n\tmaps.Copy(dst.Uses, src.Uses)\n\tmaps.Copy(dst.Selections, src.Selections)\n}\n\n// (debugging only)\nfunc astString(fset *token.FileSet, n ast.Node) string {\n\tvar buf bytes.Buffer\n\tprinter.Fprint(&buf, fset, n)\n\treturn buf.String()\n}\n"
  },
  {
    "path": "refactor/eg/eg_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// No testdata on Android.\n\n//go:build !android\n\npackage eg_test\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/format\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/internal/testfiles\"\n\t\"golang.org/x/tools/refactor/eg\"\n\t\"golang.org/x/tools/txtar\"\n)\n\n// TODO(adonovan): more tests:\n// - of command-line tool\n// - of all parts of syntax\n// - of applying a template to a package it imports:\n//   the replacement syntax should use unqualified names for its objects.\n\nvar (\n\tupdateFlag  = flag.Bool(\"update\", false, \"update the golden files\")\n\tverboseFlag = flag.Bool(\"verbose\", false, \"show matcher information\")\n)\n\nfunc Test(t *testing.T) {\n\ttestenv.NeedsGoPackages(t)\n\n\tswitch runtime.GOOS {\n\tcase \"windows\":\n\t\tt.Skipf(\"skipping test on %q (no /usr/bin/diff)\", runtime.GOOS)\n\t}\n\n\t// Each txtar defines a package example.com/template and zero\n\t// or more input packages example.com/in/... on which to apply\n\t// it. The outputs are compared with the corresponding files\n\t// in example.com/out/...\n\tfor _, filename := range []string{\n\t\t\"testdata/a.txtar\",\n\t\t\"testdata/b.txtar\",\n\t\t\"testdata/c.txtar\",\n\t\t\"testdata/d.txtar\",\n\t\t\"testdata/e.txtar\",\n\t\t\"testdata/f.txtar\",\n\t\t\"testdata/g.txtar\",\n\t\t\"testdata/h.txtar\",\n\t\t\"testdata/i.txtar\",\n\t\t\"testdata/j.txtar\",\n\t\t\"testdata/bad_type.txtar\",\n\t\t\"testdata/no_before.txtar\",\n\t\t\"testdata/no_after_return.txtar\",\n\t\t\"testdata/type_mismatch.txtar\",\n\t\t\"testdata/expr_type_mismatch.txtar\",\n\t} {\n\t\tt.Run(filename, func(t *testing.T) {\n\t\t\t// Extract and load packages from test archive.\n\t\t\tdir := testfiles.ExtractTxtarFileToTmp(t, filename)\n\t\t\tcfg := packages.Config{\n\t\t\t\tMode: packages.LoadAllSyntax,\n\t\t\t\tDir:  dir,\n\t\t\t}\n\t\t\tpkgs, err := packages.Load(&cfg, \"example.com/template\", \"example.com/in/...\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif packages.PrintErrors(pkgs) > 0 {\n\t\t\t\tt.Fatal(\"Load: there were errors\")\n\t\t\t}\n\n\t\t\t// Find and compile the template.\n\t\t\tvar template *packages.Package\n\t\t\tvar inputs []*packages.Package\n\t\t\tfor _, pkg := range pkgs {\n\t\t\t\tif pkg.Types.Name() == \"template\" {\n\t\t\t\t\ttemplate = pkg\n\t\t\t\t} else {\n\t\t\t\t\tinputs = append(inputs, pkg)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif template == nil {\n\t\t\t\tt.Fatal(\"no template package\")\n\t\t\t}\n\t\t\tshouldFail, _ := template.Types.Scope().Lookup(\"shouldFail\").(*types.Const)\n\t\t\txform, err := eg.NewTransformer(template.Fset, template.Types, template.Syntax[0], template.TypesInfo, *verboseFlag)\n\t\t\tif err != nil {\n\t\t\t\tif shouldFail == nil {\n\t\t\t\t\tt.Errorf(\"NewTransformer(%s): %s\", filename, err)\n\t\t\t\t} else if want := constant.StringVal(shouldFail.Val()); !strings.Contains(normalizeAny(err.Error()), want) {\n\t\t\t\t\tt.Errorf(\"NewTransformer(%s): got error %q, want error %q\", filename, err, want)\n\t\t\t\t}\n\t\t\t} else if shouldFail != nil {\n\t\t\t\tt.Errorf(\"NewTransformer(%s) succeeded unexpectedly; want error %q\",\n\t\t\t\t\tfilename, shouldFail.Val())\n\t\t\t}\n\n\t\t\t// Apply template to each input package.\n\t\t\tupdated := make(map[string][]byte)\n\t\t\tfor _, pkg := range inputs {\n\t\t\t\tfor _, file := range pkg.Syntax {\n\t\t\t\t\tfilename, err := filepath.Rel(dir, pkg.Fset.File(file.FileStart).Name())\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Fatalf(\"can't relativize filename: %v\", err)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply the transform and reformat.\n\t\t\t\t\tn := xform.Transform(pkg.TypesInfo, pkg.Types, file)\n\t\t\t\t\tif n == 0 {\n\t\t\t\t\t\tt.Fatalf(\"%s: no replacements\", filename)\n\t\t\t\t\t}\n\t\t\t\t\tvar got []byte\n\t\t\t\t\t{\n\t\t\t\t\t\tvar out bytes.Buffer\n\t\t\t\t\t\tformat.Node(&out, pkg.Fset, file) // ignore error\n\t\t\t\t\t\tgot = out.Bytes()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Compare formatted output with out/<filename>\n\t\t\t\t\t// Errors here are not fatal, so we can proceed to -update.\n\t\t\t\t\toutfile := strings.Replace(filename, \"in\", \"out\", 1)\n\t\t\t\t\tupdated[outfile] = got\n\t\t\t\t\twant, err := os.ReadFile(filepath.Join(dir, outfile))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Errorf(\"can't read output file: %v\", err)\n\t\t\t\t\t} else if diff := cmp.Diff(want, got); diff != \"\" {\n\t\t\t\t\t\tt.Errorf(\"Unexpected output:\\n%s\\n\\ngot %s:\\n%s\\n\\nwant %s:\\n%s\",\n\t\t\t\t\t\t\tdiff,\n\t\t\t\t\t\t\tfilename, got, outfile, want)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// -update: replace the .txtar.\n\t\t\tif *updateFlag {\n\t\t\t\tar, err := txtar.ParseFile(filename)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tvar new bytes.Buffer\n\t\t\t\tnew.Write(ar.Comment)\n\t\t\t\tfor _, file := range ar.Files {\n\t\t\t\t\tdata, ok := updated[file.Name]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tdata = file.Data\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(&new, \"-- %s --\\n%s\", file.Name, data)\n\t\t\t\t}\n\t\t\t\tt.Logf(\"Updating %s...\", filename)\n\t\t\t\tos.Remove(filename + \".bak\")         // ignore error\n\t\t\t\tos.Rename(filename, filename+\".bak\") // ignore error\n\t\t\t\tif err := os.WriteFile(filename, new.Bytes(), 0666); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// normalizeAny replaces occurrences of interface{} with any, for consistent\n// output.\nfunc normalizeAny(s string) string {\n\treturn strings.ReplaceAll(s, \"interface{}\", \"any\")\n}\n"
  },
  {
    "path": "refactor/eg/match.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage eg\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n)\n\n// matchExpr reports whether pattern x matches y.\n//\n// If tr.allowWildcards, Idents in x that refer to parameters are\n// treated as wildcards, and match any y that is assignable to the\n// parameter type; matchExpr records this correspondence in tr.env.\n// Otherwise, matchExpr simply reports whether the two trees are\n// equivalent.\n//\n// A wildcard appearing more than once in the pattern must\n// consistently match the same tree.\nfunc (tr *Transformer) matchExpr(x, y ast.Expr) bool {\n\tif x == nil && y == nil {\n\t\treturn true\n\t}\n\tif x == nil || y == nil {\n\t\treturn false\n\t}\n\tx = ast.Unparen(x)\n\ty = ast.Unparen(y)\n\n\t// Is x a wildcard?  (a reference to a 'before' parameter)\n\tif xobj, ok := tr.wildcardObj(x); ok {\n\t\treturn tr.matchWildcard(xobj, y)\n\t}\n\n\t// Object identifiers (including pkg-qualified ones)\n\t// are handled semantically, not syntactically.\n\txobj := isRef(x, tr.info)\n\tyobj := isRef(y, tr.info)\n\tif xobj != nil {\n\t\treturn xobj == yobj\n\t}\n\tif yobj != nil {\n\t\treturn false\n\t}\n\n\t// TODO(adonovan): audit: we cannot assume these ast.Exprs\n\t// contain non-nil pointers.  e.g. ImportSpec.Name may be a\n\t// nil *ast.Ident.\n\n\tif reflect.TypeOf(x) != reflect.TypeOf(y) {\n\t\treturn false\n\t}\n\tswitch x := x.(type) {\n\tcase *ast.Ident:\n\t\tlog.Fatalf(\"unexpected Ident: %s\", astString(tr.fset, x))\n\n\tcase *ast.BasicLit:\n\t\ty := y.(*ast.BasicLit)\n\t\txval := constant.MakeFromLiteral(x.Value, x.Kind, 0)\n\t\tyval := constant.MakeFromLiteral(y.Value, y.Kind, 0)\n\t\treturn constant.Compare(xval, token.EQL, yval)\n\n\tcase *ast.FuncLit:\n\t\t// func literals (and thus statement syntax) never match.\n\t\treturn false\n\n\tcase *ast.CompositeLit:\n\t\ty := y.(*ast.CompositeLit)\n\t\treturn (x.Type == nil) == (y.Type == nil) &&\n\t\t\t(x.Type == nil || tr.matchType(x.Type, y.Type)) &&\n\t\t\ttr.matchExprs(x.Elts, y.Elts)\n\n\tcase *ast.SelectorExpr:\n\t\ty := y.(*ast.SelectorExpr)\n\t\treturn tr.matchSelectorExpr(x, y) &&\n\t\t\ttr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()\n\n\tcase *ast.IndexExpr:\n\t\ty := y.(*ast.IndexExpr)\n\t\treturn tr.matchExpr(x.X, y.X) &&\n\t\t\ttr.matchExpr(x.Index, y.Index)\n\n\tcase *ast.SliceExpr:\n\t\ty := y.(*ast.SliceExpr)\n\t\treturn tr.matchExpr(x.X, y.X) &&\n\t\t\ttr.matchExpr(x.Low, y.Low) &&\n\t\t\ttr.matchExpr(x.High, y.High) &&\n\t\t\ttr.matchExpr(x.Max, y.Max) &&\n\t\t\tx.Slice3 == y.Slice3\n\n\tcase *ast.TypeAssertExpr:\n\t\ty := y.(*ast.TypeAssertExpr)\n\t\treturn tr.matchExpr(x.X, y.X) &&\n\t\t\ttr.matchType(x.Type, y.Type)\n\n\tcase *ast.CallExpr:\n\t\ty := y.(*ast.CallExpr)\n\t\tmatch := tr.matchExpr // function call\n\t\tif tr.info.Types[x.Fun].IsType() {\n\t\t\tmatch = tr.matchType // type conversion\n\t\t}\n\t\treturn x.Ellipsis.IsValid() == y.Ellipsis.IsValid() &&\n\t\t\tmatch(x.Fun, y.Fun) &&\n\t\t\ttr.matchExprs(x.Args, y.Args)\n\n\tcase *ast.StarExpr:\n\t\ty := y.(*ast.StarExpr)\n\t\treturn tr.matchExpr(x.X, y.X)\n\n\tcase *ast.UnaryExpr:\n\t\ty := y.(*ast.UnaryExpr)\n\t\treturn x.Op == y.Op &&\n\t\t\ttr.matchExpr(x.X, y.X)\n\n\tcase *ast.BinaryExpr:\n\t\ty := y.(*ast.BinaryExpr)\n\t\treturn x.Op == y.Op &&\n\t\t\ttr.matchExpr(x.X, y.X) &&\n\t\t\ttr.matchExpr(x.Y, y.Y)\n\n\tcase *ast.KeyValueExpr:\n\t\ty := y.(*ast.KeyValueExpr)\n\t\treturn tr.matchExpr(x.Key, y.Key) &&\n\t\t\ttr.matchExpr(x.Value, y.Value)\n\t}\n\n\tpanic(fmt.Sprintf(\"unhandled AST node type: %T\", x))\n}\n\nfunc (tr *Transformer) matchExprs(xx, yy []ast.Expr) bool {\n\tif len(xx) != len(yy) {\n\t\treturn false\n\t}\n\tfor i := range xx {\n\t\tif !tr.matchExpr(xx[i], yy[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// matchType reports whether the two type ASTs denote identical types.\nfunc (tr *Transformer) matchType(x, y ast.Expr) bool {\n\ttx := tr.info.Types[x].Type\n\tty := tr.info.Types[y].Type\n\treturn types.Identical(tx, ty)\n}\n\nfunc (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {\n\tif x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {\n\t\tif xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {\n\t\t\treturn xobj, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\nfunc (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {\n\tif xobj, ok := tr.wildcardObj(x.X); ok {\n\t\tfield := x.Sel.Name\n\t\tyt := tr.info.TypeOf(y.X)\n\t\to, _, _ := types.LookupFieldOrMethod(yt, true, tr.currentPkg, field)\n\t\tif o != nil {\n\t\t\ttr.env[xobj.Name()] = y.X // record binding\n\t\t\treturn true\n\t\t}\n\t}\n\treturn tr.matchExpr(x.X, y.X)\n}\n\nfunc (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {\n\tname := xobj.Name()\n\n\tif tr.verbose {\n\t\tfmt.Fprintf(os.Stderr, \"%s: wildcard %s -> %s?: \",\n\t\t\ttr.fset.Position(y.Pos()), name, astString(tr.fset, y))\n\t}\n\n\t// Check that y is assignable to the declared type of the param.\n\tyt := tr.info.TypeOf(y)\n\tif yt == nil {\n\t\t// y has no type.\n\t\t// Perhaps it is an *ast.Ellipsis in [...]T{}, or\n\t\t// an *ast.KeyValueExpr in T{k: v}.\n\t\t// Clearly these pseudo-expressions cannot match a\n\t\t// wildcard, but it would nice if we had a way to ignore\n\t\t// the difference between T{v} and T{k:v} for structs.\n\t\treturn false\n\t}\n\tif !types.AssignableTo(yt, xobj.Type()) {\n\t\tif tr.verbose {\n\t\t\tfmt.Fprintf(os.Stderr, \"%s not assignable to %s\\n\", yt, xobj.Type())\n\t\t}\n\t\treturn false\n\t}\n\n\t// A wildcard matches any expression.\n\t// If it appears multiple times in the pattern, it must match\n\t// the same expression each time.\n\tif old, ok := tr.env[name]; ok {\n\t\t// found existing binding\n\t\ttr.allowWildcards = false\n\t\tr := tr.matchExpr(old, y)\n\t\tif tr.verbose {\n\t\t\tfmt.Fprintf(os.Stderr, \"%t secondary match, primary was %s\\n\",\n\t\t\t\tr, astString(tr.fset, old))\n\t\t}\n\t\ttr.allowWildcards = true\n\t\treturn r\n\t}\n\n\tif tr.verbose {\n\t\tfmt.Fprintf(os.Stderr, \"primary match\\n\")\n\t}\n\n\ttr.env[name] = y // record binding\n\treturn true\n}\n\n// -- utilities --------------------------------------------------------\n\n// isRef returns the object referred to by this (possibly qualified)\n// identifier, or nil if the node is not a referring identifier.\nfunc isRef(n ast.Node, info *types.Info) types.Object {\n\tswitch n := n.(type) {\n\tcase *ast.Ident:\n\t\treturn info.Uses[n]\n\n\tcase *ast.SelectorExpr:\n\t\tif _, ok := info.Selections[n]; !ok {\n\t\t\t// qualified ident\n\t\t\treturn info.Uses[n.Sel]\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "refactor/eg/rewrite.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage eg\n\n// This file defines the AST rewriting pass.\n// Most of it was plundered directly from\n// $GOROOT/src/cmd/gofmt/rewrite.go (after convergent evolution).\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ast/astutil\"\n)\n\n// transformItem takes a reflect.Value representing a variable of type ast.Node\n// transforms its child elements recursively with apply, and then transforms the\n// actual element if it contains an expression.\nfunc (tr *Transformer) transformItem(rv reflect.Value) (reflect.Value, bool, map[string]ast.Expr) {\n\t// don't bother if val is invalid to start with\n\tif !rv.IsValid() {\n\t\treturn reflect.Value{}, false, nil\n\t}\n\n\trv, changed, newEnv := tr.apply(tr.transformItem, rv)\n\n\te := rvToExpr(rv)\n\tif e == nil {\n\t\treturn rv, changed, newEnv\n\t}\n\n\tsavedEnv := tr.env\n\ttr.env = make(map[string]ast.Expr) // inefficient!  Use a slice of k/v pairs\n\n\tif tr.matchExpr(tr.before, e) {\n\t\tif tr.verbose {\n\t\t\tfmt.Fprintf(os.Stderr, \"%s matches %s\",\n\t\t\t\tastString(tr.fset, tr.before), astString(tr.fset, e))\n\t\t\tif len(tr.env) > 0 {\n\t\t\t\tfmt.Fprintf(os.Stderr, \" with:\")\n\t\t\t\tfor name, ast := range tr.env {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \" %s->%s\",\n\t\t\t\t\t\tname, astString(tr.fset, ast))\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(os.Stderr, \"\\n\")\n\t\t}\n\t\ttr.nsubsts++\n\n\t\t// Clone the replacement tree, performing parameter substitution.\n\t\t// We update all positions to n.Pos() to aid comment placement.\n\t\trv = tr.subst(tr.env, reflect.ValueOf(tr.after),\n\t\t\treflect.ValueOf(e.Pos()))\n\t\tchanged = true\n\t\tnewEnv = tr.env\n\t}\n\ttr.env = savedEnv\n\n\treturn rv, changed, newEnv\n}\n\n// Transform applies the transformation to the specified parsed file,\n// whose type information is supplied in info, and returns the number\n// of replacements that were made.\n//\n// It mutates the AST in place (the identity of the root node is\n// unchanged), and may add nodes for which no type information is\n// available in info.\n//\n// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.\nfunc (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {\n\tif !tr.seenInfos[info] {\n\t\ttr.seenInfos[info] = true\n\t\tmergeTypeInfo(tr.info, info)\n\t}\n\ttr.currentPkg = pkg\n\ttr.nsubsts = 0\n\n\tif tr.verbose {\n\t\tfmt.Fprintf(os.Stderr, \"before: %s\\n\", astString(tr.fset, tr.before))\n\t\tfmt.Fprintf(os.Stderr, \"after: %s\\n\", astString(tr.fset, tr.after))\n\t\tfmt.Fprintf(os.Stderr, \"afterStmts: %s\\n\", tr.afterStmts)\n\t}\n\n\to, changed, _ := tr.apply(tr.transformItem, reflect.ValueOf(file))\n\tif changed {\n\t\tpanic(\"BUG\")\n\t}\n\tfile2 := o.Interface().(*ast.File)\n\n\t// By construction, the root node is unchanged.\n\tif file != file2 {\n\t\tpanic(\"BUG\")\n\t}\n\n\t// Add any necessary imports.\n\t// TODO(adonovan): remove no-longer needed imports too.\n\tif tr.nsubsts > 0 {\n\t\tpkgs := make(map[string]*types.Package)\n\t\tfor obj := range tr.importedObjs {\n\t\t\tpkgs[obj.Pkg().Path()] = obj.Pkg()\n\t\t}\n\n\t\tfor _, imp := range file.Imports {\n\t\t\tpath, _ := strconv.Unquote(imp.Path.Value)\n\t\t\tdelete(pkgs, path)\n\t\t}\n\t\tdelete(pkgs, pkg.Path()) // don't import self\n\n\t\t// NB: AddImport may completely replace the AST!\n\t\t// It thus renders info and tr.info no longer relevant to file.\n\t\tvar paths []string\n\t\tfor path := range pkgs {\n\t\t\tpaths = append(paths, path)\n\t\t}\n\t\tsort.Strings(paths)\n\t\tfor _, path := range paths {\n\t\t\tastutil.AddImport(tr.fset, file, path)\n\t\t}\n\t}\n\n\ttr.currentPkg = nil\n\n\treturn tr.nsubsts\n}\n\n// setValue is a wrapper for x.SetValue(y); it protects\n// the caller from panics if x cannot be changed to y.\nfunc setValue(x, y reflect.Value) {\n\t// don't bother if y is invalid to start with\n\tif !y.IsValid() {\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif x := recover(); x != nil {\n\t\t\tif s, ok := x.(string); ok &&\n\t\t\t\t(strings.Contains(s, \"type mismatch\") || strings.Contains(s, \"not assignable\")) {\n\t\t\t\t// x cannot be set to y - ignore this rewrite\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpanic(x)\n\t\t}\n\t}()\n\tx.Set(y)\n}\n\n// Values/types for special cases.\nvar (\n\tobjectPtrNil = reflect.ValueOf((*ast.Object)(nil))\n\tscopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))\n\n\tidentType        = reflect.TypeFor[*ast.Ident]()\n\tselectorExprType = reflect.TypeFor[*ast.SelectorExpr]()\n\tobjectPtrType    = reflect.TypeFor[*ast.Object]()\n\tstatementType    = reflect.TypeFor[ast.Stmt]()\n\tpositionType     = reflect.TypeFor[token.Pos]()\n\tscopePtrType     = reflect.TypeFor[*ast.Scope]()\n)\n\n// apply replaces each AST field x in val with f(x), returning val.\n// To avoid extra conversions, f operates on the reflect.Value form.\n// f takes a reflect.Value representing the variable to modify of type ast.Node.\n// It returns a reflect.Value containing the transformed value of type ast.Node,\n// whether any change was made, and a map of identifiers to ast.Expr (so we can\n// do contextually correct substitutions in the parent statements).\nfunc (tr *Transformer) apply(f func(reflect.Value) (reflect.Value, bool, map[string]ast.Expr), val reflect.Value) (reflect.Value, bool, map[string]ast.Expr) {\n\tif !val.IsValid() {\n\t\treturn reflect.Value{}, false, nil\n\t}\n\n\t// *ast.Objects introduce cycles and are likely incorrect after\n\t// rewrite; don't follow them but replace with nil instead\n\tif val.Type() == objectPtrType {\n\t\treturn objectPtrNil, false, nil\n\t}\n\n\t// similarly for scopes: they are likely incorrect after a rewrite;\n\t// replace them with nil\n\tif val.Type() == scopePtrType {\n\t\treturn scopePtrNil, false, nil\n\t}\n\n\tswitch v := reflect.Indirect(val); v.Kind() {\n\tcase reflect.Slice:\n\t\t// no possible rewriting of statements.\n\t\tif v.Type().Elem() != statementType {\n\t\t\tchanged := false\n\t\t\tvar envp map[string]ast.Expr\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\te := v.Index(i)\n\t\t\t\to, localchanged, env := f(e)\n\t\t\t\tif localchanged {\n\t\t\t\t\tchanged = true\n\t\t\t\t\t// we clobber envp here,\n\t\t\t\t\t// which means if we have two successive\n\t\t\t\t\t// replacements inside the same statement\n\t\t\t\t\t// we will only generate the setup for one of them.\n\t\t\t\t\tenvp = env\n\t\t\t\t}\n\t\t\t\tsetValue(e, o)\n\t\t\t}\n\t\t\treturn val, changed, envp\n\t\t}\n\n\t\t// statements are rewritten.\n\t\tvar out []ast.Stmt\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\te := v.Index(i)\n\t\t\to, changed, env := f(e)\n\t\t\tif changed {\n\t\t\t\tfor _, s := range tr.afterStmts {\n\t\t\t\t\tt := tr.subst(env, reflect.ValueOf(s), reflect.Value{}).Interface()\n\t\t\t\t\tout = append(out, t.(ast.Stmt))\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetValue(e, o)\n\t\t\tout = append(out, e.Interface().(ast.Stmt))\n\t\t}\n\t\treturn reflect.ValueOf(out), false, nil\n\tcase reflect.Struct:\n\t\tchanged := false\n\t\tvar envp map[string]ast.Expr\n\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\te := v.Field(i)\n\t\t\to, localchanged, env := f(e)\n\t\t\tif localchanged {\n\t\t\t\tchanged = true\n\t\t\t\tenvp = env\n\t\t\t}\n\t\t\tsetValue(e, o)\n\t\t}\n\t\treturn val, changed, envp\n\tcase reflect.Interface:\n\t\te := v.Elem()\n\t\to, changed, env := f(e)\n\t\tsetValue(v, o)\n\t\treturn val, changed, env\n\t}\n\treturn val, false, nil\n}\n\n// subst returns a copy of (replacement) pattern with values from env\n// substituted in place of wildcards and pos used as the position of\n// tokens from the pattern. If env == nil, subst returns a copy of\n// pattern and doesn't change the line number information.\nfunc (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value {\n\tif !pattern.IsValid() {\n\t\treturn reflect.Value{}\n\t}\n\n\t// *ast.Objects introduce cycles and are likely incorrect after\n\t// rewrite; don't follow them but replace with nil instead\n\tif pattern.Type() == objectPtrType {\n\t\treturn objectPtrNil\n\t}\n\n\t// similarly for scopes: they are likely incorrect after a rewrite;\n\t// replace them with nil\n\tif pattern.Type() == scopePtrType {\n\t\treturn scopePtrNil\n\t}\n\n\t// Wildcard gets replaced with map value.\n\tif env != nil && pattern.Type() == identType {\n\t\tid := pattern.Interface().(*ast.Ident)\n\t\tif old, ok := env[id.Name]; ok {\n\t\t\treturn tr.subst(nil, reflect.ValueOf(old), reflect.Value{})\n\t\t}\n\t}\n\n\t// Emit qualified identifiers in the pattern by appropriate\n\t// (possibly qualified) identifier in the input.\n\t//\n\t// The template cannot contain dot imports, so all identifiers\n\t// for imported objects are explicitly qualified.\n\t//\n\t// We assume (unsoundly) that there are no dot or named\n\t// imports in the input code, nor are any imported package\n\t// names shadowed, so the usual normal qualified identifier\n\t// syntax may be used.\n\t// TODO(adonovan): fix: avoid this assumption.\n\t//\n\t// A refactoring may be applied to a package referenced by the\n\t// template.  Objects belonging to the current package are\n\t// denoted by unqualified identifiers.\n\t//\n\tif tr.importedObjs != nil && pattern.Type() == selectorExprType {\n\t\tobj := isRef(pattern.Interface().(*ast.SelectorExpr), tr.info)\n\t\tif obj != nil {\n\t\t\tif sel, ok := tr.importedObjs[obj]; ok {\n\t\t\t\tvar id ast.Expr\n\t\t\t\tif obj.Pkg() == tr.currentPkg {\n\t\t\t\t\tid = sel.Sel // unqualified\n\t\t\t\t} else {\n\t\t\t\t\tid = sel // pkg-qualified\n\t\t\t\t}\n\n\t\t\t\t// Return a clone of id.\n\t\t\t\tsaved := tr.importedObjs\n\t\t\t\ttr.importedObjs = nil // break cycle\n\t\t\t\tr := tr.subst(nil, reflect.ValueOf(id), pos)\n\t\t\t\ttr.importedObjs = saved\n\t\t\t\treturn r\n\t\t\t}\n\t\t}\n\t}\n\n\tif pos.IsValid() && pattern.Type() == positionType {\n\t\t// use new position only if old position was valid in the first place\n\t\tif old := pattern.Interface().(token.Pos); !old.IsValid() {\n\t\t\treturn pattern\n\t\t}\n\t\treturn pos\n\t}\n\n\t// Otherwise copy.\n\tswitch p := pattern; p.Kind() {\n\tcase reflect.Slice:\n\t\tv := reflect.MakeSlice(p.Type(), p.Len(), p.Len())\n\t\tfor i := 0; i < p.Len(); i++ {\n\t\t\tv.Index(i).Set(tr.subst(env, p.Index(i), pos))\n\t\t}\n\t\treturn v\n\n\tcase reflect.Struct:\n\t\tv := reflect.New(p.Type()).Elem()\n\t\tfor i := 0; i < p.NumField(); i++ {\n\t\t\tv.Field(i).Set(tr.subst(env, p.Field(i), pos))\n\t\t}\n\t\treturn v\n\n\tcase reflect.Pointer:\n\t\tv := reflect.New(p.Type()).Elem()\n\t\tif elem := p.Elem(); elem.IsValid() {\n\t\t\tv.Set(tr.subst(env, elem, pos).Addr())\n\t\t}\n\n\t\t// Duplicate type information for duplicated ast.Expr.\n\t\t// All ast.Node implementations are *structs,\n\t\t// so this case catches them all.\n\t\tif e := rvToExpr(v); e != nil {\n\t\t\tupdateTypeInfo(tr.info, e, p.Interface().(ast.Expr))\n\t\t}\n\t\treturn v\n\n\tcase reflect.Interface:\n\t\tv := reflect.New(p.Type()).Elem()\n\t\tif elem := p.Elem(); elem.IsValid() {\n\t\t\tv.Set(tr.subst(env, elem, pos))\n\t\t}\n\t\treturn v\n\t}\n\n\treturn pattern\n}\n\n// -- utilities -------------------------------------------------------\n\nfunc rvToExpr(rv reflect.Value) ast.Expr {\n\tif rv.CanInterface() {\n\t\tif e, ok := rv.Interface().(ast.Expr); ok {\n\t\t\treturn e\n\t\t}\n\t}\n\treturn nil\n}\n\n// updateTypeInfo duplicates type information for the existing AST old\n// so that it also applies to duplicated AST new.\nfunc updateTypeInfo(info *types.Info, new, old ast.Expr) {\n\tswitch new := new.(type) {\n\tcase *ast.Ident:\n\t\torig := old.(*ast.Ident)\n\t\tif obj, ok := info.Defs[orig]; ok {\n\t\t\tinfo.Defs[new] = obj\n\t\t}\n\t\tif obj, ok := info.Uses[orig]; ok {\n\t\t\tinfo.Uses[new] = obj\n\t\t}\n\n\tcase *ast.SelectorExpr:\n\t\torig := old.(*ast.SelectorExpr)\n\t\tif sel, ok := info.Selections[orig]; ok {\n\t\t\tinfo.Selections[new] = sel\n\t\t}\n\t}\n\n\tif tv, ok := info.Types[old]; ok {\n\t\tinfo.Types[new] = tv\n\t}\n}\n"
  },
  {
    "path": "refactor/eg/testdata/a.txtar",
    "content": "\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\n// Basic test of type-aware expression refactoring.\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc before(s string) error { return fmt.Errorf(\"%s\", s) }\nfunc after(s string) error  { return errors.New(s) }\n\n-- in/a1/a1.go --\npackage a1\n\nimport (\n\t. \"fmt\"\n\tmyfmt \"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc example(n int) {\n\tx := \"foo\" + strings.Repeat(\"\\t\", n)\n\t// Match, despite named import.\n\tmyfmt.Errorf(\"%s\", x)\n\n\t// Match, despite dot import.\n\tErrorf(\"%s\", x)\n\n\t// Match: multiple matches in same function are possible.\n\tmyfmt.Errorf(\"%s\", x)\n\n\t// No match: wildcarded operand has the wrong type.\n\tmyfmt.Errorf(\"%s\", 3)\n\n\t// No match: function operand doesn't match.\n\tmyfmt.Printf(\"%s\", x)\n\n\t// No match again, dot import.\n\tPrintf(\"%s\", x)\n\n\t// Match.\n\tmyfmt.Fprint(os.Stderr, myfmt.Errorf(\"%s\", x+\"foo\"))\n\n\t// No match: though this literally matches the template,\n\t// fmt doesn't resolve to a package here.\n\tvar fmt struct{ Errorf func(string, string) }\n\tfmt.Errorf(\"%s\", x)\n\n\t// Recursive matching:\n\n\t// Match: both matches are well-typed, so both succeed.\n\tmyfmt.Errorf(\"%s\", myfmt.Errorf(\"%s\", x+\"foo\").Error())\n\n\t// Outer match succeeds, inner doesn't: 3 has wrong type.\n\tmyfmt.Errorf(\"%s\", myfmt.Errorf(\"%s\", 3).Error())\n\n\t// Inner match succeeds, outer doesn't: the inner replacement\n\t// has the wrong type (error not string).\n\tmyfmt.Errorf(\"%s\", myfmt.Errorf(\"%s\", x+\"foo\"))\n}\n\n-- out/a1/a1.go --\npackage a1\n\nimport (\n\t\"errors\"\n\t. \"fmt\"\n\tmyfmt \"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc example(n int) {\n\tx := \"foo\" + strings.Repeat(\"\\t\", n)\n\t// Match, despite named import.\n\terrors.New(x)\n\n\t// Match, despite dot import.\n\terrors.New(x)\n\n\t// Match: multiple matches in same function are possible.\n\terrors.New(x)\n\n\t// No match: wildcarded operand has the wrong type.\n\tmyfmt.Errorf(\"%s\", 3)\n\n\t// No match: function operand doesn't match.\n\tmyfmt.Printf(\"%s\", x)\n\n\t// No match again, dot import.\n\tPrintf(\"%s\", x)\n\n\t// Match.\n\tmyfmt.Fprint(os.Stderr, errors.New(x+\"foo\"))\n\n\t// No match: though this literally matches the template,\n\t// fmt doesn't resolve to a package here.\n\tvar fmt struct{ Errorf func(string, string) }\n\tfmt.Errorf(\"%s\", x)\n\n\t// Recursive matching:\n\n\t// Match: both matches are well-typed, so both succeed.\n\terrors.New(errors.New(x + \"foo\").Error())\n\n\t// Outer match succeeds, inner doesn't: 3 has wrong type.\n\terrors.New(myfmt.Errorf(\"%s\", 3).Error())\n\n\t// Inner match succeeds, outer doesn't: the inner replacement\n\t// has the wrong type (error not string).\n\tmyfmt.Errorf(\"%s\", errors.New(x+\"foo\"))\n}\n-- a2/a2.go --\npackage a2\n\n// This refactoring causes addition of \"errors\" import.\n// TODO(adonovan): fix: it should also remove \"fmt\".\n\nimport myfmt \"fmt\"\n\nfunc example(n int) {\n\tmyfmt.Errorf(\"%s\", \"\")\n}\n\n-- out/a2/a2.go --\npackage a2\n\n// This refactoring causes addition of \"errors\" import.\n// TODO(adonovan): fix: it should also remove \"fmt\".\n\nimport (\n\t\"errors\"\n\tmyfmt \"fmt\"\n)\n\nfunc example(n int) {\n\terrors.New(\"\")\n}\n"
  },
  {
    "path": "refactor/eg/testdata/b.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\n// Basic test of expression refactoring.\n// (Types are not important in this case; it could be done with gofmt -r.)\n\nimport \"time\"\n\nfunc before(t time.Time) time.Duration { return time.Now().Sub(t) }\nfunc after(t time.Time) time.Duration  { return time.Since(t) }\n\n-- in/b1/b1.go --\npackage b1\n\nimport \"time\"\n\nvar startup = time.Now()\n\nfunc example() time.Duration {\n\tbefore := time.Now()\n\ttime.Sleep(1)\n\treturn time.Now().Sub(before)\n}\n\nfunc msSinceStartup() int64 {\n\treturn int64(time.Now().Sub(startup) / time.Millisecond)\n}\n\n-- out/b1/b1.go --\npackage b1\n\nimport \"time\"\n\nvar startup = time.Now()\n\nfunc example() time.Duration {\n\tbefore := time.Now()\n\ttime.Sleep(1)\n\treturn time.Since(before)\n}\n\nfunc msSinceStartup() int64 {\n\treturn int64(time.Since(startup) / time.Millisecond)\n}\n"
  },
  {
    "path": "refactor/eg/testdata/bad_type.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\n// Test in which replacement has a different type.\n\nconst shouldFail = \"int is not a safe replacement for string\"\n\nfunc before() interface{} { return \"three\" }\nfunc after() interface{}  { return 3 }\n"
  },
  {
    "path": "refactor/eg/testdata/c.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\n// Test of repeated use of wildcard in pattern.\n\n// NB: multiple patterns would be required to handle variants such as\n// s[:len(s)], s[x:len(s)], etc, since a wildcard can't match nothing at all.\n// TODO(adonovan): support multiple templates in a single pass.\n\nfunc before(s string) string { return s[:len(s)] }\nfunc after(s string) string  { return s }\n\n-- in/c1/c1.go --\npackage C1\n\nimport \"strings\"\n\nfunc example() {\n\tx := \"foo\"\n\tprintln(x[:len(x)])\n\n\t// Match, but the transformation is not sound w.r.t. possible side effects.\n\tprintln(strings.Repeat(\"*\", 3)[:len(strings.Repeat(\"*\", 3))])\n\n\t// No match, since second use of wildcard doesn't match first.\n\tprintln(strings.Repeat(\"*\", 3)[:len(strings.Repeat(\"*\", 2))])\n\n\t// Recursive match demonstrating bottom-up rewrite:\n\t// only after the inner replacement occurs does the outer syntax match.\n\tprintln((x[:len(x)])[:len(x[:len(x)])])\n\t// -> (x[:len(x)])\n\t// -> x\n}\n\n-- out/c1/c1.go --\npackage C1\n\nimport \"strings\"\n\nfunc example() {\n\tx := \"foo\"\n\tprintln(x)\n\n\t// Match, but the transformation is not sound w.r.t. possible side effects.\n\tprintln(strings.Repeat(\"*\", 3))\n\n\t// No match, since second use of wildcard doesn't match first.\n\tprintln(strings.Repeat(\"*\", 3)[:len(strings.Repeat(\"*\", 2))])\n\n\t// Recursive match demonstrating bottom-up rewrite:\n\t// only after the inner replacement occurs does the outer syntax match.\n\tprintln(x)\n\t// -> (x[:len(x)])\n\t// -> x\n}\n"
  },
  {
    "path": "refactor/eg/testdata/d.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport \"fmt\"\n\n// Test of semantic (not syntactic) matching of basic literals.\n\nfunc before() (int, error) { return fmt.Println(123, \"a\") }\nfunc after() (int, error)  { return fmt.Println(456, \"!\") }\n\n-- in/d1/d1.go --\npackage d1\n\nimport \"fmt\"\n\nfunc example() {\n\tfmt.Println(123, \"a\")         // match\n\tfmt.Println(0x7b, `a`)        // match\n\tfmt.Println(0173, \"\\x61\")     // match\n\tfmt.Println(100+20+3, \"a\"+\"\") // no match: constant expressions, but not basic literals\n}\n\n-- out/d1/d1.go --\npackage d1\n\nimport \"fmt\"\n\nfunc example() {\n\tfmt.Println(456, \"!\")         // match\n\tfmt.Println(456, \"!\")         // match\n\tfmt.Println(456, \"!\")         // match\n\tfmt.Println(100+20+3, \"a\"+\"\") // no match: constant expressions, but not basic literals\n}\n"
  },
  {
    "path": "refactor/eg/testdata/e.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// Replace call to void function by call to non-void function.\n\nfunc before(x interface{}) { log.Fatal(x) }\nfunc after(x interface{})  { fmt.Fprintf(os.Stderr, \"warning: %v\", x) }\n\n-- in/e1/e1.go --\npackage e1\n\nimport \"log\"\n\nfunc example() {\n\tlog.Fatal(\"oops\") // match\n}\n\n-- out/e1/e1.go --\npackage e1\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc example() {\n\tfmt.Fprintf(os.Stderr, \"warning: %v\", \"oops\") // match\n}\n"
  },
  {
    "path": "refactor/eg/testdata/expr_type_mismatch.txtar",
    "content": "\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport (\n\t\"crypto/x509\"\n\t\"fmt\"\n)\n\n// This test demonstrates a false negative: according to the language\n// rules this replacement should be ok, but types.Assignable doesn't work\n// in the expected way (elementwise assignability) for tuples.\n// Perhaps that's even a type-checker bug?\nconst shouldFail = \"(n int, err error) is not a safe replacement for (key any, err error)\"\n\nfunc before() (interface{}, error) { return x509.ParsePKCS8PrivateKey(nil) }\nfunc after() (interface{}, error)  { return fmt.Print() }\n"
  },
  {
    "path": "refactor/eg/testdata/f.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\n// Test\n\nimport \"sync\"\n\nfunc before(s sync.RWMutex) { s.Lock() }\nfunc after(s sync.RWMutex)  { s.RLock() }\n\n-- in/f1/f1.go --\npackage F1\n\nimport \"sync\"\n\nfunc example(n int) {\n\tvar x struct {\n\t\tmutex sync.RWMutex\n\t}\n\n\tvar y struct {\n\t\tsync.RWMutex\n\t}\n\n\ttype l struct {\n\t\tsync.RWMutex\n\t}\n\n\tvar z struct {\n\t\tl\n\t}\n\n\tvar a struct {\n\t\t*l\n\t}\n\n\tvar b struct{ Lock func() }\n\n\t// Match\n\tx.mutex.Lock()\n\n\t// Match\n\ty.Lock()\n\n\t// Match indirect\n\tz.Lock()\n\n\t// Should be no match however currently matches due to:\n\t// https://golang.org/issue/8584\n\t// Will start failing when this is fixed then just change golden to\n\t// No match pointer indirect\n\t// a.Lock()\n\ta.Lock()\n\n\t// No match\n\tb.Lock()\n}\n\n-- out/f1/f1.go --\npackage F1\n\nimport \"sync\"\n\nfunc example(n int) {\n\tvar x struct {\n\t\tmutex sync.RWMutex\n\t}\n\n\tvar y struct {\n\t\tsync.RWMutex\n\t}\n\n\ttype l struct {\n\t\tsync.RWMutex\n\t}\n\n\tvar z struct {\n\t\tl\n\t}\n\n\tvar a struct {\n\t\t*l\n\t}\n\n\tvar b struct{ Lock func() }\n\n\t// Match\n\tx.mutex.RLock()\n\n\t// Match\n\ty.RLock()\n\n\t// Match indirect\n\tz.RLock()\n\n\t// Should be no match however currently matches due to:\n\t// https://golang.org/issue/8584\n\t// Will start failing when this is fixed then just change golden to\n\t// No match pointer indirect\n\t// a.Lock()\n\ta.RLock()\n\n\t// No match\n\tb.Lock()\n}\n"
  },
  {
    "path": "refactor/eg/testdata/g.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport (\n\t\"go/ast\" // defines many unencapsulated structs\n\t\"go/token\"\n)\n\nfunc before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }\nfunc after(from, to token.Pos) ast.BadExpr  { return ast.BadExpr{from, to} }\n\n-- in/g1/g1.go --\npackage g1\n\nimport \"go/ast\"\n\nfunc example() {\n\t_ = ast.BadExpr{From: 123, To: 456} // match\n\t_ = ast.BadExpr{123, 456}           // no match\n\t_ = ast.BadExpr{From: 123}          // no match\n\t_ = ast.BadExpr{To: 456}            // no match\n}\n\n-- out/g1/g1.go --\npackage g1\n\nimport \"go/ast\"\n\nfunc example() {\n\t_ = ast.BadExpr{123, 456}  // match\n\t_ = ast.BadExpr{123, 456}  // no match\n\t_ = ast.BadExpr{From: 123} // no match\n\t_ = ast.BadExpr{To: 456}   // no match\n}\n"
  },
  {
    "path": "refactor/eg/testdata/h.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport (\n\t\"go/ast\" // defines many unencapsulated structs\n\t\"go/token\"\n)\n\nfunc before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }\nfunc after(from, to token.Pos) ast.BadExpr  { return ast.BadExpr{From: from, To: to} }\n\n-- in/h1/h1.go --\npackage h1\n\nimport \"go/ast\"\n\nfunc example() {\n\t_ = ast.BadExpr{From: 123, To: 456} // no match\n\t_ = ast.BadExpr{123, 456}           // match\n\t_ = ast.BadExpr{From: 123}          // no match\n\t_ = ast.BadExpr{To: 456}            // no match\n}\n\n-- out/h1/h1.go --\npackage h1\n\nimport \"go/ast\"\n\nfunc example() {\n\t_ = ast.BadExpr{From: 123, To: 456} // no match\n\t_ = ast.BadExpr{From: 123, To: 456} // match\n\t_ = ast.BadExpr{From: 123}          // no match\n\t_ = ast.BadExpr{To: 456}            // no match\n}\n"
  },
  {
    "path": "refactor/eg/testdata/i.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc before(s string) error { return fmt.Errorf(\"%s\", s) }\nfunc after(s string) error {\n\tn := fmt.Sprintf(\"error - %s\", s)\n\treturn errors.New(n)\n}\n\n-- in/i1/i1.go --\npackage i1\n\nimport \"fmt\"\n\nfunc example() {\n\t_ = fmt.Errorf(\"%s\", \"foo\")\n}\n\n-- out/i1/i1.go --\npackage i1\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc example() {\n\n\tn := fmt.Sprintf(\"error - %s\", \"foo\")\n\t_ = errors.New(n)\n}\n"
  },
  {
    "path": "refactor/eg/testdata/j.txtar",
    "content": "\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nimport ()\n\nfunc before(x int) int { return x + x + x }\nfunc after(x int) int {\n\ttemp := x + x\n\treturn temp + x\n}\n\n-- in/j1/j1.go --\npackage j1\n\nimport \"fmt\"\n\nfunc example() {\n\ttemp := 5\n\tfmt.Print(temp + temp + temp)\n}\n\n-- out/j1/j1.go --\npackage j1\n\nimport \"fmt\"\n\nfunc example() {\n\ttemp := 5\n\ttemp := temp + temp\n\tfmt.Print(temp + temp)\n}\n"
  },
  {
    "path": "refactor/eg/testdata/no_after_return.txtar",
    "content": "\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nfunc before() int { return 0 }\nfunc after() int  { println(); return 0 }\n"
  },
  {
    "path": "refactor/eg/testdata/no_before.txtar",
    "content": "\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nconst shouldFail = \"no 'before' func found in template\"\n\nfunc Before() {}\n"
  },
  {
    "path": "refactor/eg/testdata/type_mismatch.txtar",
    "content": "\n\n-- go.mod --\nmodule example.com\ngo 1.18\n\n-- template/template.go --\npackage template\n\nconst shouldFail = \"different signatures\"\n\nfunc before() int   { return 0 }\nfunc after() string { return \"\" }\n"
  },
  {
    "path": "refactor/importgraph/graph.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package importgraph computes the forward and reverse import\n// dependency graphs for all packages in a Go workspace.\npackage importgraph // import \"golang.org/x/tools/refactor/importgraph\"\n\nimport (\n\t\"go/build\"\n\t\"sync\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n)\n\n// A Graph is an import dependency graph, either forward or reverse.\n//\n// The graph maps each node (a package import path) to the set of its\n// successors in the graph.  For a forward graph, this is the set of\n// imported packages (prerequisites); for a reverse graph, it is the set\n// of importing packages (clients).\n//\n// Graph construction inspects all imports in each package's directory,\n// including those in _test.go files, so the resulting graph may be cyclic.\ntype Graph map[string]map[string]bool\n\nfunc (g Graph) addEdge(from, to string) {\n\tedges := g[from]\n\tif edges == nil {\n\t\tedges = make(map[string]bool)\n\t\tg[from] = edges\n\t}\n\tedges[to] = true\n}\n\n// Search returns all the nodes of the graph reachable from\n// any of the specified roots, by following edges forwards.\n// Relationally, this is the reflexive transitive closure.\nfunc (g Graph) Search(roots ...string) map[string]bool {\n\tseen := make(map[string]bool)\n\tvar visit func(x string)\n\tvisit = func(x string) {\n\t\tif !seen[x] {\n\t\t\tseen[x] = true\n\t\t\tfor y := range g[x] {\n\t\t\t\tvisit(y)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, root := range roots {\n\t\tvisit(root)\n\t}\n\treturn seen\n}\n\n// Build scans the specified Go workspace and builds the forward and\n// reverse import dependency graphs for all its packages.\n// It also returns a mapping from canonical import paths to errors for packages\n// whose loading was not entirely successful.\n// A package may appear in the graph and in the errors mapping.\n// All package paths are canonical and may contain \"/vendor/\".\nfunc Build(ctxt *build.Context) (forward, reverse Graph, errors map[string]error) {\n\ttype importEdge struct {\n\t\tfrom, to string\n\t}\n\ttype pathError struct {\n\t\tpath string\n\t\terr  error\n\t}\n\n\tch := make(chan any)\n\n\tgo func() {\n\t\tsema := make(chan int, 20) // I/O concurrency limiting semaphore\n\t\tvar wg sync.WaitGroup\n\t\tbuildutil.ForEachPackage(ctxt, func(path string, err error) {\n\t\t\tif err != nil {\n\t\t\t\tch <- pathError{path, err}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\twg.Add(1)\n\t\t\tgo func() {\n\t\t\t\tdefer wg.Done()\n\n\t\t\t\tsema <- 1\n\t\t\t\tbp, err := ctxt.Import(path, \"\", 0)\n\t\t\t\t<-sema\n\n\t\t\t\tif err != nil {\n\t\t\t\t\tif _, ok := err.(*build.NoGoError); ok {\n\t\t\t\t\t\t// empty directory is not an error\n\t\t\t\t\t} else {\n\t\t\t\t\t\tch <- pathError{path, err}\n\t\t\t\t\t}\n\t\t\t\t\t// Even in error cases, Import usually returns a package.\n\t\t\t\t}\n\n\t\t\t\t// absolutize resolves an import path relative\n\t\t\t\t// to the current package bp.\n\t\t\t\t// The absolute form may contain \"vendor\".\n\t\t\t\t//\n\t\t\t\t// The vendoring feature slows down Build by 3×.\n\t\t\t\t// Here are timings from a 1400 package workspace:\n\t\t\t\t//    1100ms: current code (with vendor check)\n\t\t\t\t//     880ms: with a nonblocking cache around ctxt.IsDir\n\t\t\t\t//     840ms: nonblocking cache with duplicate suppression\n\t\t\t\t//     340ms: original code (no vendor check)\n\t\t\t\t// TODO(adonovan): optimize, somehow.\n\t\t\t\tmemo := make(map[string]string)\n\t\t\t\tabsolutize := func(path string) string {\n\t\t\t\t\tcanon, ok := memo[path]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tsema <- 1\n\t\t\t\t\t\tbp2, _ := ctxt.Import(path, bp.Dir, build.FindOnly)\n\t\t\t\t\t\t<-sema\n\n\t\t\t\t\t\tif bp2 != nil {\n\t\t\t\t\t\t\tcanon = bp2.ImportPath\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcanon = path\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmemo[path] = canon\n\t\t\t\t\t}\n\t\t\t\t\treturn canon\n\t\t\t\t}\n\n\t\t\t\tif bp != nil {\n\t\t\t\t\tfor _, imp := range bp.Imports {\n\t\t\t\t\t\tch <- importEdge{path, absolutize(imp)}\n\t\t\t\t\t}\n\t\t\t\t\tfor _, imp := range bp.TestImports {\n\t\t\t\t\t\tch <- importEdge{path, absolutize(imp)}\n\t\t\t\t\t}\n\t\t\t\t\tfor _, imp := range bp.XTestImports {\n\t\t\t\t\t\tch <- importEdge{path, absolutize(imp)}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}()\n\t\t})\n\t\twg.Wait()\n\t\tclose(ch)\n\t}()\n\n\tforward = make(Graph)\n\treverse = make(Graph)\n\n\tfor e := range ch {\n\t\tswitch e := e.(type) {\n\t\tcase pathError:\n\t\t\tif errors == nil {\n\t\t\t\terrors = make(map[string]error)\n\t\t\t}\n\t\t\terrors[e.path] = e.err\n\n\t\tcase importEdge:\n\t\t\tif e.to == \"C\" {\n\t\t\t\tcontinue // \"C\" is fake\n\t\t\t}\n\t\t\tforward.addEdge(e.from, e.to)\n\t\t\treverse.addEdge(e.to, e.from)\n\t\t}\n\t}\n\n\treturn forward, reverse, errors\n}\n"
  },
  {
    "path": "refactor/importgraph/graph_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Incomplete std lib sources on Android.\n\n//go:build !android\n\npackage importgraph_test\n\nimport (\n\t\"fmt\"\n\t\"go/build\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/packagestest\"\n\t\"golang.org/x/tools/refactor/importgraph\"\n\n\t_ \"crypto/hmac\" // just for test, below\n)\n\nconst this = \"golang.org/x/tools/refactor/importgraph\"\n\nfunc TestBuild(t *testing.T) {\n\texported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{\n\t\t{Name: \"golang.org/x/tools/refactor/importgraph\", Files: packagestest.MustCopyFileTree(\".\")}})\n\tdefer exported.Cleanup()\n\n\tvar gopath string\n\tfor _, env := range exported.Config.Env {\n\t\teq := strings.Index(env, \"=\")\n\t\tif eq == 0 {\n\t\t\t// We sometimes see keys with a single leading \"=\" in the environment on Windows.\n\t\t\t// TODO(#49886): What is the correct way to parse them in general?\n\t\t\teq = strings.Index(env[1:], \"=\") + 1\n\t\t}\n\t\tif eq < 0 {\n\t\t\tt.Fatalf(\"invalid variable in exported.Config.Env: %q\", env)\n\t\t}\n\t\tk := env[:eq]\n\t\tv := env[eq+1:]\n\t\tif k == \"GOPATH\" {\n\t\t\tgopath = v\n\t\t}\n\n\t\tif os.Getenv(k) == v {\n\t\t\tcontinue\n\t\t}\n\t\tdefer func(prev string, prevOK bool) {\n\t\t\tif !prevOK {\n\t\t\t\tif err := os.Unsetenv(k); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif err := os.Setenv(k, prev); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\t\t}(os.LookupEnv(k))\n\n\t\tif err := os.Setenv(k, v); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tt.Logf(\"%s=%s\", k, v)\n\t}\n\tif gopath == \"\" {\n\t\tt.Fatal(\"Failed to fish GOPATH out of env: \", exported.Config.Env)\n\t}\n\n\tvar buildContext = build.Default\n\tbuildContext.GOPATH = gopath\n\tbuildContext.Dir = exported.Config.Dir\n\n\tforward, reverse, errs := importgraph.Build(&buildContext)\n\tfor path, err := range errs {\n\t\tt.Errorf(\"%s: %s\", path, err)\n\t}\n\tif t.Failed() {\n\t\treturn\n\t}\n\n\t// Log the complete graph before the errors, so that the errors are near the\n\t// end of the log (where we expect them to be).\n\tnodePrinted := map[string]bool{}\n\tprintNode := func(direction string, from string) {\n\t\tkey := fmt.Sprintf(\"%s[%q]\", direction, from)\n\t\tif nodePrinted[key] {\n\t\t\treturn\n\t\t}\n\t\tnodePrinted[key] = true\n\n\t\tvar g importgraph.Graph\n\t\tswitch direction {\n\t\tcase \"forward\":\n\t\t\tg = forward\n\t\tcase \"reverse\":\n\t\t\tg = reverse\n\t\tdefault:\n\t\t\tt.Helper()\n\t\t\tt.Fatalf(\"bad direction: %q\", direction)\n\t\t}\n\n\t\tt.Log(key)\n\t\tvar pkgs []string\n\t\tfor pkg := range g[from] {\n\t\t\tpkgs = append(pkgs, pkg)\n\t\t}\n\t\tsort.Strings(pkgs)\n\t\tfor _, pkg := range pkgs {\n\t\t\tt.Logf(\"\\t%s\", pkg)\n\t\t}\n\t}\n\n\tif testing.Verbose() {\n\t\tprintNode(\"forward\", this)\n\t\tprintNode(\"reverse\", this)\n\t}\n\n\t// Test direct edges.\n\t// We throw in crypto/hmac to prove that external test files\n\t// (such as this one) are inspected.\n\tfor _, p := range []string{\"go/build\", \"testing\", \"crypto/hmac\"} {\n\t\tif !forward[this][p] {\n\t\t\tprintNode(\"forward\", this)\n\t\t\tt.Errorf(\"forward[%q][%q] not found\", this, p)\n\t\t}\n\t\tif !reverse[p][this] {\n\t\t\tprintNode(\"reverse\", p)\n\t\t\tt.Errorf(\"reverse[%q][%q] not found\", p, this)\n\t\t}\n\t}\n\n\t// Test non-existent direct edges\n\tfor _, p := range []string{\"errors\", \"reflect\"} {\n\t\tif forward[this][p] {\n\t\t\tprintNode(\"forward\", this)\n\t\t\tt.Errorf(\"unexpected: forward[%q][%q] found\", this, p)\n\t\t}\n\t\tif reverse[p][this] {\n\t\t\tprintNode(\"reverse\", p)\n\t\t\tt.Errorf(\"unexpected: reverse[%q][%q] found\", p, this)\n\t\t}\n\t}\n\n\t// Test Search is reflexive.\n\tif !forward.Search(this)[this] {\n\t\tprintNode(\"forward\", this)\n\t\tt.Errorf(\"irreflexive: forward.Search(importgraph)[importgraph] not found\")\n\t}\n\tif !reverse.Search(this)[this] {\n\t\tprintNode(\"reverse\", this)\n\t\tt.Errorf(\"irreflexive: reverse.Search(importgraph)[importgraph] not found\")\n\t}\n\n\t// Test Search is transitive.  (There is no direct edge to these packages.)\n\tfor _, p := range []string{\"errors\", \"reflect\", \"unsafe\"} {\n\t\tif !forward.Search(this)[p] {\n\t\t\tprintNode(\"forward\", this)\n\t\t\tt.Errorf(\"intransitive: forward.Search(importgraph)[%s] not found\", p)\n\t\t}\n\t\tif !reverse.Search(p)[this] {\n\t\t\tprintNode(\"reverse\", p)\n\t\t\tt.Errorf(\"intransitive: reverse.Search(%s)[importgraph] not found\", p)\n\t\t}\n\t}\n\n\t// Test strongly-connected components.  Because A's external\n\t// test package can depend on B, and vice versa, most of the\n\t// standard libraries are mutually dependent when their external\n\t// tests are considered.\n\t//\n\t// For any nodes x, y in the same SCC, y appears in the results\n\t// of both forward and reverse searches starting from x\n\tif !forward.Search(\"fmt\")[\"io\"] ||\n\t\t!forward.Search(\"io\")[\"fmt\"] ||\n\t\t!reverse.Search(\"fmt\")[\"io\"] ||\n\t\t!reverse.Search(\"io\")[\"fmt\"] {\n\t\tprintNode(\"forward\", \"fmt\")\n\t\tprintNode(\"forward\", \"io\")\n\t\tprintNode(\"reverse\", \"fmt\")\n\t\tprintNode(\"reverse\", \"io\")\n\t\tt.Errorf(\"fmt and io are not mutually reachable despite being in the same SCC\")\n\t}\n}\n"
  },
  {
    "path": "refactor/rename/check.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rename\n\n// This file defines the safety checks for each kind of renaming.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/internal/typeparams\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\n// errorf reports an error (e.g. conflict) and prevents file modification.\nfunc (r *renamer) errorf(pos token.Pos, format string, args ...any) {\n\tr.hadConflicts = true\n\treportError(r.iprog.Fset.Position(pos), fmt.Sprintf(format, args...))\n}\n\n// check performs safety checks of the renaming of the 'from' object to r.to.\nfunc (r *renamer) check(from types.Object) {\n\tif r.objsToUpdate[from] {\n\t\treturn\n\t}\n\tr.objsToUpdate[from] = true\n\n\t// NB: order of conditions is important.\n\tif from_, ok := from.(*types.PkgName); ok {\n\t\tr.checkInFileBlock(from_)\n\t} else if from_, ok := from.(*types.Label); ok {\n\t\tr.checkLabel(from_)\n\t} else if typesinternal.IsPackageLevel(from) {\n\t\tr.checkInPackageBlock(from)\n\t} else if v, ok := from.(*types.Var); ok && v.IsField() {\n\t\tr.checkStructField(v)\n\t} else if f, ok := from.(*types.Func); ok && recv(f) != nil {\n\t\tr.checkMethod(f)\n\t} else if isLocal(from) {\n\t\tr.checkInLocalScope(from)\n\t} else {\n\t\tr.errorf(from.Pos(), \"unexpected %s object %q (please report a bug)\\n\",\n\t\t\tobjectKind(from), from)\n\t}\n}\n\n// checkInFileBlock performs safety checks for renames of objects in the file block,\n// i.e. imported package names.\nfunc (r *renamer) checkInFileBlock(from *types.PkgName) {\n\t// Check import name is not \"init\".\n\tif r.to == \"init\" {\n\t\tr.errorf(from.Pos(), \"%q is not a valid imported package name\", r.to)\n\t}\n\n\t// Check for conflicts between file and package block.\n\tif prev := from.Pkg().Scope().Lookup(r.to); prev != nil {\n\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q would conflict\",\n\t\t\tobjectKind(from), from.Name(), r.to)\n\t\tr.errorf(prev.Pos(), \"\\twith this package member %s\",\n\t\t\tobjectKind(prev))\n\t\treturn // since checkInPackageBlock would report redundant errors\n\t}\n\n\t// Check for conflicts in lexical scope.\n\tr.checkInLexicalScope(from, r.packages[from.Pkg()])\n\n\t// Finally, modify ImportSpec syntax to add or remove the Name as needed.\n\tinfo, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())\n\tif from.Imported().Name() == r.to {\n\t\t// ImportSpec.Name not needed\n\t\tpath[1].(*ast.ImportSpec).Name = nil\n\t} else {\n\t\t// ImportSpec.Name needed\n\t\tif spec := path[1].(*ast.ImportSpec); spec.Name == nil {\n\t\t\tspec.Name = &ast.Ident{NamePos: spec.Path.Pos(), Name: r.to}\n\t\t\tinfo.Defs[spec.Name] = from\n\t\t}\n\t}\n}\n\n// checkInPackageBlock performs safety checks for renames of\n// func/var/const/type objects in the package block.\nfunc (r *renamer) checkInPackageBlock(from types.Object) {\n\t// Check that there are no references to the name from another\n\t// package if the renaming would make it unexported.\n\tif ast.IsExported(from.Name()) && !ast.IsExported(r.to) {\n\t\tfor pkg, info := range r.packages {\n\t\t\tif pkg == from.Pkg() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif id := someUse(info, from); id != nil &&\n\t\t\t\t!r.checkExport(id, pkg, from) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tinfo := r.packages[from.Pkg()]\n\n\t// Check that in the package block, \"init\" is a function, and never referenced.\n\tif r.to == \"init\" {\n\t\tkind := objectKind(from)\n\t\tif kind == \"func\" {\n\t\t\t// Reject if intra-package references to it exist.\n\t\t\tfor id, obj := range info.Uses {\n\t\t\t\tif obj == from {\n\t\t\t\t\tr.errorf(from.Pos(),\n\t\t\t\t\t\t\"renaming this func %q to %q would make it a package initializer\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(id.Pos(), \"\\tbut references to it exist\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tr.errorf(from.Pos(), \"you cannot have a %s at package level named %q\",\n\t\t\t\tkind, r.to)\n\t\t}\n\t}\n\n\t// Check for conflicts between package block and all file blocks.\n\tfor _, f := range info.Files {\n\t\tfileScope := info.Info.Scopes[f]\n\t\tb, prev := fileScope.LookupParent(r.to, token.NoPos)\n\t\tif b == fileScope {\n\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q would conflict\",\n\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twith this %s\",\n\t\t\t\tobjectKind(prev))\n\t\t\treturn // since checkInPackageBlock would report redundant errors\n\t\t}\n\t}\n\n\t// Check for conflicts in lexical scope.\n\tif from.Exported() {\n\t\tfor _, info := range r.packages {\n\t\t\tr.checkInLexicalScope(from, info)\n\t\t}\n\t} else {\n\t\tr.checkInLexicalScope(from, info)\n\t}\n}\n\nfunc (r *renamer) checkInLocalScope(from types.Object) {\n\tinfo := r.packages[from.Pkg()]\n\n\t// Is this object an implicit local var for a type switch?\n\t// Each case has its own var, whose position is the decl of y,\n\t// but Ident in that decl does not appear in the Uses map.\n\t//\n\t//   switch y := x.(type) {\t // Defs[Ident(y)] is undefined\n\t//   case int:    print(y)       // Implicits[CaseClause(int)]    = Var(y_int)\n\t//   case string: print(y)       // Implicits[CaseClause(string)] = Var(y_string)\n\t//   }\n\t//\n\tvar isCaseVar bool\n\tfor syntax, obj := range info.Implicits {\n\t\tif _, ok := syntax.(*ast.CaseClause); ok && obj.Pos() == from.Pos() {\n\t\t\tisCaseVar = true\n\t\t\tr.check(obj)\n\t\t}\n\t}\n\n\tr.checkInLexicalScope(from, info)\n\n\t// Finally, if this was a type switch, change the variable y.\n\tif isCaseVar {\n\t\t_, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())\n\t\tpath[0].(*ast.Ident).Name = r.to // path is [Ident AssignStmt TypeSwitchStmt...]\n\t}\n}\n\n// checkInLexicalScope performs safety checks that a renaming does not\n// change the lexical reference structure of the specified package.\n//\n// For objects in lexical scope, there are three kinds of conflicts:\n// same-, sub-, and super-block conflicts.  We will illustrate all three\n// using this example:\n//\n//\tvar x int\n//\tvar z int\n//\n//\tfunc f(y int) {\n//\t\tprint(x)\n//\t\tprint(y)\n//\t}\n//\n// Renaming x to z encounters a SAME-BLOCK CONFLICT, because an object\n// with the new name already exists, defined in the same lexical block\n// as the old object.\n//\n// Renaming x to y encounters a SUB-BLOCK CONFLICT, because there exists\n// a reference to x from within (what would become) a hole in its scope.\n// The definition of y in an (inner) sub-block would cast a shadow in\n// the scope of the renamed variable.\n//\n// Renaming y to x encounters a SUPER-BLOCK CONFLICT.  This is the\n// converse situation: there is an existing definition of the new name\n// (x) in an (enclosing) super-block, and the renaming would create a\n// hole in its scope, within which there exist references to it.  The\n// new name casts a shadow in scope of the existing definition of x in\n// the super-block.\n//\n// Removing the old name (and all references to it) is always safe, and\n// requires no checks.\nfunc (r *renamer) checkInLexicalScope(from types.Object, info *loader.PackageInfo) {\n\tb := from.Parent() // the block defining the 'from' object\n\tif b != nil {\n\t\ttoBlock, to := b.LookupParent(r.to, from.Parent().End())\n\t\tif toBlock == b {\n\t\t\t// same-block conflict\n\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\tr.errorf(to.Pos(), \"\\tconflicts with %s in same block\",\n\t\t\t\tobjectKind(to))\n\t\t\treturn\n\t\t} else if toBlock != nil {\n\t\t\t// Check for super-block conflict.\n\t\t\t// The name r.to is defined in a superblock.\n\t\t\t// Is that name referenced from within this block?\n\t\t\tforEachLexicalRef(info, to, func(id *ast.Ident, block *types.Scope) bool {\n\t\t\t\t_, obj := lexicalLookup(block, from.Name(), id.Pos())\n\t\t\t\tif obj == from {\n\t\t\t\t\t// super-block conflict\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\t\t\tr.errorf(id.Pos(), \"\\twould shadow this reference\")\n\t\t\t\t\tr.errorf(to.Pos(), \"\\tto the %s declared here\",\n\t\t\t\t\t\tobjectKind(to))\n\t\t\t\t\treturn false // stop\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t}\n\n\t// Check for sub-block conflict.\n\t// Is there an intervening definition of r.to between\n\t// the block defining 'from' and some reference to it?\n\tforEachLexicalRef(info, from, func(id *ast.Ident, block *types.Scope) bool {\n\t\t// Find the block that defines the found reference.\n\t\t// It may be an ancestor.\n\t\tfromBlock, _ := lexicalLookup(block, from.Name(), id.Pos())\n\n\t\t// See what r.to would resolve to in the same scope.\n\t\ttoBlock, to := lexicalLookup(block, r.to, id.Pos())\n\t\tif to != nil {\n\t\t\t// sub-block conflict\n\t\t\tif deeper(toBlock, fromBlock) {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\t\t\t\tobjectKind(from), from.Name(), r.to)\n\t\t\t\tr.errorf(id.Pos(), \"\\twould cause this reference to become shadowed\")\n\t\t\t\tr.errorf(to.Pos(), \"\\tby this intervening %s definition\",\n\t\t\t\t\tobjectKind(to))\n\t\t\t\treturn false // stop\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n\n\t// Renaming a type that is used as an embedded field\n\t// requires renaming the field too. e.g.\n\t// \ttype T int // if we rename this to U..\n\t// \tvar s struct {T}\n\t// \tprint(s.T) // ...this must change too\n\tif _, ok := from.(*types.TypeName); ok {\n\t\tfor id, obj := range info.Uses {\n\t\t\tif obj == from {\n\t\t\t\tif field := info.Defs[id]; field != nil {\n\t\t\t\t\tr.check(field)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// lexicalLookup is like (*types.Scope).LookupParent but respects the\n// environment visible at pos.  It assumes the relative position\n// information is correct with each file.\nfunc lexicalLookup(block *types.Scope, name string, pos token.Pos) (*types.Scope, types.Object) {\n\tfor b := block; b != nil; b = b.Parent() {\n\t\tobj := b.Lookup(name)\n\t\t// The scope of a package-level object is the entire package,\n\t\t// so ignore pos in that case.\n\t\t// No analogous clause is needed for file-level objects\n\t\t// since no reference can appear before an import decl.\n\t\tif obj != nil && (b == obj.Pkg().Scope() || obj.Pos() < pos) {\n\t\t\treturn b, obj\n\t\t}\n\t}\n\treturn nil, nil\n}\n\n// deeper reports whether block x is lexically deeper than y.\nfunc deeper(x, y *types.Scope) bool {\n\tif x == y || x == nil {\n\t\treturn false\n\t} else if y == nil {\n\t\treturn true\n\t} else {\n\t\treturn deeper(x.Parent(), y.Parent())\n\t}\n}\n\n// forEachLexicalRef calls fn(id, block) for each identifier id in package\n// info that is a reference to obj in lexical scope.  block is the\n// lexical block enclosing the reference.  If fn returns false the\n// iteration is terminated and findLexicalRefs returns false.\nfunc forEachLexicalRef(info *loader.PackageInfo, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {\n\tok := true\n\n\tvar visit func(n ast.Node, stack []ast.Node) bool\n\tvisit = func(n ast.Node, stack []ast.Node) bool {\n\t\tif !ok {\n\t\t\treturn false // bail out\n\t\t}\n\t\tswitch n := n.(type) {\n\t\tcase *ast.Ident:\n\t\t\tif info.Uses[n] == obj {\n\t\t\t\tblock := enclosingBlock(&info.Info, stack)\n\t\t\t\tif !fn(n, block) {\n\t\t\t\t\tok = false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false\n\n\t\tcase *ast.SelectorExpr:\n\t\t\t// don't visit n.Sel\n\t\t\tast.PreorderStack(n.X, stack, visit)\n\t\t\treturn false // don't descend\n\n\t\tcase *ast.CompositeLit:\n\t\t\t// Handle recursion ourselves for struct literals\n\t\t\t// so we don't visit field identifiers.\n\t\t\ttv := info.Types[n]\n\t\t\tif is[*types.Struct](typeparams.CoreType(typeparams.Deref(tv.Type))) {\n\t\t\t\tif n.Type != nil {\n\t\t\t\t\tast.PreorderStack(n.Type, stack, visit)\n\t\t\t\t}\n\t\t\t\tfor _, elt := range n.Elts {\n\t\t\t\t\tif kv, ok := elt.(*ast.KeyValueExpr); ok {\n\t\t\t\t\t\tast.PreorderStack(kv.Value, stack, visit)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tast.PreorderStack(elt, stack, visit)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false // don't descend\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\tfor _, f := range info.Files {\n\t\tast.PreorderStack(f, nil, visit)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn ok\n}\n\n// enclosingBlock returns the innermost block enclosing the specified\n// AST node, specified in the form of a path from the root of the file,\n// [file...n].\nfunc enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {\n\tfor i := range stack {\n\t\tn := stack[len(stack)-1-i]\n\t\t// For some reason, go/types always associates a\n\t\t// function's scope with its FuncType.\n\t\t// TODO(adonovan): feature or a bug?\n\t\tswitch f := n.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\tn = f.Type\n\t\tcase *ast.FuncLit:\n\t\t\tn = f.Type\n\t\t}\n\t\tif b := info.Scopes[n]; b != nil {\n\t\t\treturn b\n\t\t}\n\t}\n\tpanic(\"no Scope for *ast.File\")\n}\n\nfunc (r *renamer) checkLabel(label *types.Label) {\n\t// Check there are no identical labels in the function's label block.\n\t// (Label blocks don't nest, so this is easy.)\n\tif prev := label.Parent().Lookup(r.to); prev != nil {\n\t\tr.errorf(label.Pos(), \"renaming this label %q to %q\", label.Name(), prev.Name())\n\t\tr.errorf(prev.Pos(), \"\\twould conflict with this one\")\n\t}\n}\n\n// checkStructField checks that the field renaming will not cause\n// conflicts at its declaration, or ambiguity or changes to any selection.\nfunc (r *renamer) checkStructField(from *types.Var) {\n\t// Check that the struct declaration is free of field conflicts,\n\t// and field/method conflicts.\n\n\t// go/types offers no easy way to get from a field (or interface\n\t// method) to its declaring struct (or interface), so we must\n\t// ascend the AST.\n\tinfo, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())\n\t// path matches this pattern:\n\t// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]\n\n\t// Ascend to FieldList.\n\tvar i int\n\tfor {\n\t\tif _, ok := path[i].(*ast.FieldList); ok {\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t}\n\ti++\n\ttStruct := path[i].(*ast.StructType)\n\ti++\n\t// Ascend past parens (unlikely).\n\tfor {\n\t\t_, ok := path[i].(*ast.ParenExpr)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t}\n\tif spec, ok := path[i].(*ast.TypeSpec); ok && !spec.Assign.IsValid() {\n\t\t// This struct is also a defined type.\n\t\t// We must check for direct (non-promoted) field/field\n\t\t// and method/field conflicts.\n\t\tnamed := info.Defs[spec.Name].Type()\n\t\tprev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, r.to)\n\t\tif len(indices) == 1 {\n\t\t\tr.errorf(from.Pos(), \"renaming this field %q to %q\",\n\t\t\t\tfrom.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this %s\",\n\t\t\t\tobjectKind(prev))\n\t\t\treturn // skip checkSelections to avoid redundant errors\n\t\t}\n\t} else {\n\t\t// This struct is not a defined type. (It may be an alias.)\n\t\t// We need only check for direct (non-promoted) field/field conflicts.\n\t\tT := info.Types[tStruct].Type.Underlying().(*types.Struct)\n\t\tfor field := range T.Fields() {\n\t\t\tif prev := field; prev.Name() == r.to {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this field %q to %q\",\n\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this field\")\n\t\t\t\treturn // skip checkSelections to avoid redundant errors\n\t\t\t}\n\t\t}\n\t}\n\n\t// Renaming an anonymous field requires renaming the TypeName too. e.g.\n\t// \tprint(s.T)       // if we rename T to U,\n\t// \ttype T int       // this and\n\t// \tvar s struct {T} // this must change too.\n\tif from.Anonymous() {\n\t\t// A TypeParam cannot appear as an anonymous field.\n\t\tif t, ok := typesinternal.Unpointer(from.Type()).(hasTypeName); ok {\n\t\t\tr.check(t.Obj())\n\t\t}\n\t}\n\n\t// Check integrity of existing (field and method) selections.\n\tr.checkSelections(from)\n}\n\n// hasTypeName abstracts the named types, *types.{Named,Alias,TypeParam}.\ntype hasTypeName interface{ Obj() *types.TypeName }\n\n// checkSelections checks that all uses and selections that resolve to\n// the specified object would continue to do so after the renaming.\nfunc (r *renamer) checkSelections(from types.Object) {\n\tfor pkg, info := range r.packages {\n\t\tif id := someUse(info, from); id != nil {\n\t\t\tif !r.checkExport(id, pkg, from) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tfor syntax, sel := range info.Selections {\n\t\t\t// There may be extant selections of only the old\n\t\t\t// name or only the new name, so we must check both.\n\t\t\t// (If neither, the renaming is sound.)\n\t\t\t//\n\t\t\t// In both cases, we wish to compare the lengths\n\t\t\t// of the implicit field path (Selection.Index)\n\t\t\t// to see if the renaming would change it.\n\t\t\t//\n\t\t\t// If a selection that resolves to 'from', when renamed,\n\t\t\t// would yield a path of the same or shorter length,\n\t\t\t// this indicates ambiguity or a changed referent,\n\t\t\t// analogous to same- or sub-block lexical conflict.\n\t\t\t//\n\t\t\t// If a selection using the name 'to' would\n\t\t\t// yield a path of the same or shorter length,\n\t\t\t// this indicates ambiguity or shadowing,\n\t\t\t// analogous to same- or super-block lexical conflict.\n\n\t\t\t// TODO(adonovan): fix: derive from Types[syntax.X].Mode\n\t\t\t// TODO(adonovan): test with pointer, value, addressable value.\n\t\t\tisAddressable := true\n\n\t\t\tif sel.Obj() == from {\n\t\t\t\tif obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {\n\t\t\t\t\t// Renaming this existing selection of\n\t\t\t\t\t// 'from' may block access to an existing\n\t\t\t\t\t// type member named 'to'.\n\t\t\t\t\tdelta := len(indices) - len(sel.Index())\n\t\t\t\t\tif delta > 0 {\n\t\t\t\t\t\tcontinue // no ambiguity\n\t\t\t\t\t}\n\t\t\t\t\tr.selectionConflict(from, delta, syntax, obj)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t} else if sel.Obj().Name() == r.to {\n\t\t\t\tif obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {\n\t\t\t\t\t// Renaming 'from' may cause this existing\n\t\t\t\t\t// selection of the name 'to' to change\n\t\t\t\t\t// its meaning.\n\t\t\t\t\tdelta := len(indices) - len(sel.Index())\n\t\t\t\t\tif delta > 0 {\n\t\t\t\t\t\tcontinue //  no ambiguity\n\t\t\t\t\t}\n\t\t\t\t\tr.selectionConflict(from, -delta, syntax, sel.Obj())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {\n\tr.errorf(from.Pos(), \"renaming this %s %q to %q\",\n\t\tobjectKind(from), from.Name(), r.to)\n\n\tswitch {\n\tcase delta < 0:\n\t\t// analogous to sub-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould change the referent of this selection\")\n\t\tr.errorf(obj.Pos(), \"\\tof this %s\", objectKind(obj))\n\tcase delta == 0:\n\t\t// analogous to same-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould make this reference ambiguous\")\n\t\tr.errorf(obj.Pos(), \"\\twith this %s\", objectKind(obj))\n\tcase delta > 0:\n\t\t// analogous to super-block conflict\n\t\tr.errorf(syntax.Sel.Pos(),\n\t\t\t\"\\twould shadow this selection\")\n\t\tr.errorf(obj.Pos(), \"\\tof the %s declared here\",\n\t\t\tobjectKind(obj))\n\t}\n}\n\n// checkMethod performs safety checks for renaming a method.\n// There are three hazards:\n//   - declaration conflicts\n//   - selection ambiguity/changes\n//   - entailed renamings of assignable concrete/interface types.\n//\n// We reject renamings initiated at concrete methods if it would\n// change the assignability relation.  For renamings of abstract\n// methods, we rename all methods transitively coupled to it via\n// assignability.\nfunc (r *renamer) checkMethod(from *types.Func) {\n\t// e.g. error.Error\n\tif from.Pkg() == nil {\n\t\tr.errorf(from.Pos(), \"you cannot rename built-in method %s\", from)\n\t\treturn\n\t}\n\n\t// ASSIGNABILITY: We reject renamings of concrete methods that\n\t// would break a 'satisfy' constraint; but renamings of abstract\n\t// methods are allowed to proceed, and we rename affected\n\t// concrete and abstract methods as necessary.  It is the\n\t// initial method that determines the policy.\n\n\t// Check for conflict at point of declaration.\n\t// Check to ensure preservation of assignability requirements.\n\tR := recv(from).Type()\n\tif types.IsInterface(R) {\n\t\t// Abstract method\n\n\t\t// declaration\n\t\tprev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)\n\t\tif prev != nil {\n\t\t\tr.errorf(from.Pos(), \"renaming this interface method %q to %q\",\n\t\t\t\tfrom.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this method\")\n\t\t\treturn\n\t\t}\n\n\t\t// Check all interfaces that embed this one for\n\t\t// declaration conflicts too.\n\t\tfor _, info := range r.packages {\n\t\t\t// Start with named interface types (better errors)\n\t\t\tfor _, obj := range info.Defs {\n\t\t\t\tif obj, ok := obj.(*types.TypeName); ok && types.IsInterface(obj.Type()) {\n\t\t\t\t\tf, _, _ := types.LookupFieldOrMethod(\n\t\t\t\t\t\tobj.Type(), false, from.Pkg(), from.Name())\n\t\t\t\t\tif f == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tt, _, _ := types.LookupFieldOrMethod(\n\t\t\t\t\t\tobj.Type(), false, from.Pkg(), r.to)\n\t\t\t\t\tif t == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this interface method %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tr.errorf(t.Pos(), \"\\twould conflict with this method\")\n\t\t\t\t\tr.errorf(obj.Pos(), \"\\tin named interface type %q\", obj.Name())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now look at all literal interface types (includes named ones again).\n\t\t\tfor e, tv := range info.Types {\n\t\t\t\tif e, ok := e.(*ast.InterfaceType); ok {\n\t\t\t\t\t_ = e\n\t\t\t\t\t_ = tv.Type.(*types.Interface)\n\t\t\t\t\t// TODO(adonovan): implement same check as above.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// assignability\n\t\t//\n\t\t// Find the set of concrete or abstract methods directly\n\t\t// coupled to abstract method 'from' by some\n\t\t// satisfy.Constraint, and rename them too.\n\t\tfor key := range r.satisfy() {\n\t\t\t// key = (lhs, rhs) where lhs is always an interface.\n\n\t\t\tlsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif lsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trmethods := r.msets.MethodSet(key.RHS)\n\t\t\trsel := rmethods.Lookup(from.Pkg(), from.Name())\n\t\t\tif rsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If both sides have a method of this name,\n\t\t\t// and one of them is m, the other must be coupled.\n\t\t\tvar coupled *types.Func\n\t\t\tswitch from {\n\t\t\tcase lsel.Obj():\n\t\t\t\tcoupled = rsel.Obj().(*types.Func)\n\t\t\tcase rsel.Obj():\n\t\t\t\tcoupled = lsel.Obj().(*types.Func)\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// We must treat concrete-to-interface\n\t\t\t// constraints like an implicit selection C.f of\n\t\t\t// each interface method I.f, and check that the\n\t\t\t// renaming leaves the selection unchanged and\n\t\t\t// unambiguous.\n\t\t\t//\n\t\t\t// Fun fact: the implicit selection of C.f\n\t\t\t// \ttype I interface{f()}\n\t\t\t// \ttype C struct{I}\n\t\t\t// \tfunc (C) g()\n\t\t\t//      var _ I = C{} // here\n\t\t\t// yields abstract method I.f.  This can make error\n\t\t\t// messages less than obvious.\n\t\t\t//\n\t\t\tif !types.IsInterface(key.RHS) {\n\t\t\t\t// The logic below was derived from checkSelections.\n\n\t\t\t\trtosel := rmethods.Lookup(from.Pkg(), r.to)\n\t\t\t\tif rtosel != nil {\n\t\t\t\t\trto := rtosel.Obj().(*types.Func)\n\t\t\t\t\tdelta := len(rsel.Index()) - len(rtosel.Index())\n\t\t\t\t\tif delta < 0 {\n\t\t\t\t\t\tcontinue // no ambiguity\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO(adonovan): record the constraint's position.\n\t\t\t\t\tkeyPos := token.NoPos\n\n\t\t\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\t\tif delta == 0 {\n\t\t\t\t\t\t// analogous to same-block conflict\n\t\t\t\t\t\tr.errorf(keyPos, \"\\twould make the %s method of %s invoked via interface %s ambiguous\",\n\t\t\t\t\t\t\tr.to, key.RHS, key.LHS)\n\t\t\t\t\t\tr.errorf(rto.Pos(), \"\\twith (%s).%s\",\n\t\t\t\t\t\t\trecv(rto).Type(), r.to)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// analogous to super-block conflict\n\t\t\t\t\t\tr.errorf(keyPos, \"\\twould change the %s method of %s invoked via interface %s\",\n\t\t\t\t\t\t\tr.to, key.RHS, key.LHS)\n\t\t\t\t\t\tr.errorf(coupled.Pos(), \"\\tfrom (%s).%s\",\n\t\t\t\t\t\t\trecv(coupled).Type(), r.to)\n\t\t\t\t\t\tr.errorf(rto.Pos(), \"\\tto (%s).%s\",\n\t\t\t\t\t\t\trecv(rto).Type(), r.to)\n\t\t\t\t\t}\n\t\t\t\t\treturn // one error is enough\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !r.changeMethods {\n\t\t\t\t// This should be unreachable.\n\t\t\t\tr.errorf(from.Pos(), \"internal error: during renaming of abstract method %s\", from)\n\t\t\t\tr.errorf(coupled.Pos(), \"\\tchangedMethods=false, coupled method=%s\", coupled)\n\t\t\t\tr.errorf(from.Pos(), \"\\tPlease file a bug report\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Rename the coupled method to preserve assignability.\n\t\t\tr.check(coupled)\n\t\t}\n\t} else {\n\t\t// Concrete method\n\n\t\t// declaration\n\t\tprev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)\n\t\tif prev != nil && len(indices) == 1 {\n\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\tfrom.Name(), r.to)\n\t\t\tr.errorf(prev.Pos(), \"\\twould conflict with this %s\",\n\t\t\t\tobjectKind(prev))\n\t\t\treturn\n\t\t}\n\n\t\t// assignability\n\t\t//\n\t\t// Find the set of abstract methods coupled to concrete\n\t\t// method 'from' by some satisfy.Constraint, and rename\n\t\t// them too.\n\t\t//\n\t\t// Coupling may be indirect, e.g. I.f <-> C.f via type D.\n\t\t//\n\t\t// \ttype I interface {f()}\n\t\t//\ttype C int\n\t\t//\ttype (C) f()\n\t\t//\ttype D struct{C}\n\t\t//\tvar _ I = D{}\n\t\t//\n\t\tfor key := range r.satisfy() {\n\t\t\t// key = (lhs, rhs) where lhs is always an interface.\n\t\t\tif types.IsInterface(key.RHS) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif rsel == nil || rsel.Obj() != from {\n\t\t\t\tcontinue // rhs does not have the method\n\t\t\t}\n\t\t\tlsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())\n\t\t\tif lsel == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\timeth := lsel.Obj().(*types.Func)\n\n\t\t\t// imeth is the abstract method (e.g. I.f)\n\t\t\t// and key.RHS is the concrete coupling type (e.g. D).\n\t\t\tif !r.changeMethods {\n\t\t\t\tr.errorf(from.Pos(), \"renaming this method %q to %q\",\n\t\t\t\t\tfrom.Name(), r.to)\n\t\t\t\tvar pos token.Pos\n\t\t\t\tvar iface string\n\n\t\t\t\tI := recv(imeth).Type()\n\t\t\t\tif named, ok := I.(hasTypeName); ok { // *Named or *Alias\n\t\t\t\t\tpos = named.Obj().Pos()\n\t\t\t\t\tiface = \"interface \" + named.Obj().Name()\n\t\t\t\t} else {\n\t\t\t\t\tpos = from.Pos()\n\t\t\t\t\tiface = I.String()\n\t\t\t\t}\n\t\t\t\tr.errorf(pos, \"\\twould make %s no longer assignable to %s\",\n\t\t\t\t\tkey.RHS, iface)\n\t\t\t\tr.errorf(imeth.Pos(), \"\\t(rename %s.%s if you intend to change both types)\",\n\t\t\t\t\tI, from.Name())\n\t\t\t\treturn // one error is enough\n\t\t\t}\n\n\t\t\t// Rename the coupled interface method to preserve assignability.\n\t\t\tr.check(imeth)\n\t\t}\n\t}\n\n\t// Check integrity of existing (field and method) selections.\n\t// We skip this if there were errors above, to avoid redundant errors.\n\tr.checkSelections(from)\n}\n\nfunc (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {\n\t// Reject cross-package references if r.to is unexported.\n\t// (Such references may be qualified identifiers or field/method\n\t// selections.)\n\tif !ast.IsExported(r.to) && pkg != from.Pkg() {\n\t\tr.errorf(from.Pos(),\n\t\t\t\"renaming this %s %q to %q would make it unexported\",\n\t\t\tobjectKind(from), from.Name(), r.to)\n\t\tr.errorf(id.Pos(), \"\\tbreaking references from packages such as %q\",\n\t\t\tpkg.Path())\n\t\treturn false\n\t}\n\treturn true\n}\n\n// satisfy returns the set of interface satisfaction constraints.\nfunc (r *renamer) satisfy() map[satisfy.Constraint]bool {\n\tif r.satisfyConstraints == nil {\n\t\t// Compute on demand: it's expensive.\n\t\tvar f satisfy.Finder\n\t\tfor _, info := range r.packages {\n\t\t\tf.Find(&info.Info, info.Files)\n\t\t}\n\t\tr.satisfyConstraints = f.Result\n\t}\n\treturn r.satisfyConstraints\n}\n\n// -- helpers ----------------------------------------------------------\n\n// recv returns the method's receiver.\nfunc recv(meth *types.Func) *types.Var {\n\treturn meth.Signature().Recv()\n}\n\n// someUse returns an arbitrary use of obj within info.\nfunc someUse(info *loader.PackageInfo, obj types.Object) *ast.Ident {\n\tfor id, o := range info.Uses {\n\t\tif o == obj {\n\t\t\treturn id\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "refactor/rename/mvpkg.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file contains the implementation of the 'gomvpkg' command\n// whose main function is in golang.org/x/tools/cmd/gomvpkg.\n\npackage rename\n\n// TODO(matloob):\n// - think about what happens if the package is moving across version control systems.\n// - dot imports are not supported. Make sure it's clearly documented.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/refactor/importgraph\"\n)\n\n// Move, given a package path and a destination package path, will try\n// to move the given package to the new path. The Move function will\n// first check for any conflicts preventing the move, such as a\n// package already existing at the destination package path. If the\n// move can proceed, it builds an import graph to find all imports of\n// the packages whose paths need to be renamed. This includes uses of\n// the subpackages of the package to be moved as those packages will\n// also need to be moved. It then renames all imports to point to the\n// new paths, and then moves the packages to their new paths.\nfunc Move(ctxt *build.Context, from, to, moveTmpl string) error {\n\tsrcDir, err := srcDir(ctxt, from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// This should be the only place in the program that constructs\n\t// file paths.\n\tfromDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(from))\n\ttoDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(to))\n\ttoParent := filepath.Dir(toDir)\n\tif !buildutil.IsDir(ctxt, toParent) {\n\t\treturn fmt.Errorf(\"parent directory does not exist for path %s\", toDir)\n\t}\n\n\t// Build the import graph and figure out which packages to update.\n\t_, rev, errors := importgraph.Build(ctxt)\n\tif len(errors) > 0 {\n\t\t// With a large GOPATH tree, errors are inevitable.\n\t\t// Report them but proceed.\n\t\tfmt.Fprintf(os.Stderr, \"While scanning Go workspace:\\n\")\n\t\tfor path, err := range errors {\n\t\t\tfmt.Fprintf(os.Stderr, \"Package %q: %s.\\n\", path, err)\n\t\t}\n\t}\n\n\t// Determine the affected packages---the set of packages whose import\n\t// statements need updating.\n\taffectedPackages := map[string]bool{from: true}\n\tdestinations := make(map[string]string) // maps old import path to new import path\n\tfor pkg := range subpackages(ctxt, srcDir, from) {\n\t\tfor r := range rev[pkg] {\n\t\t\taffectedPackages[r] = true\n\t\t}\n\t\tdestinations[pkg] = strings.Replace(pkg, from, to, 1)\n\t}\n\n\t// Load all the affected packages.\n\tiprog, err := loadProgram(ctxt, affectedPackages)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Prepare the move command, if one was supplied.\n\tvar cmd string\n\tif moveTmpl != \"\" {\n\t\tif cmd, err = moveCmd(moveTmpl, fromDir, toDir); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tm := mover{\n\t\tctxt:             ctxt,\n\t\trev:              rev,\n\t\tiprog:            iprog,\n\t\tfrom:             from,\n\t\tto:               to,\n\t\tfromDir:          fromDir,\n\t\ttoDir:            toDir,\n\t\taffectedPackages: affectedPackages,\n\t\tdestinations:     destinations,\n\t\tcmd:              cmd,\n\t}\n\n\tif err := m.checkValid(); err != nil {\n\t\treturn err\n\t}\n\n\tm.move()\n\n\treturn nil\n}\n\n// srcDir returns the absolute path of the srcdir containing pkg.\nfunc srcDir(ctxt *build.Context, pkg string) (string, error) {\n\tfor _, srcDir := range ctxt.SrcDirs() {\n\t\tpath := buildutil.JoinPath(ctxt, srcDir, pkg)\n\t\tif buildutil.IsDir(ctxt, path) {\n\t\t\treturn srcDir, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"src dir not found for package: %s\", pkg)\n}\n\n// subpackages returns the set of packages in the given srcDir whose\n// import path equals to root, or has \"root/\" as the prefix.\nfunc subpackages(ctxt *build.Context, srcDir string, root string) map[string]bool {\n\tvar subs = make(map[string]bool)\n\tbuildutil.ForEachPackage(ctxt, func(pkg string, err error) {\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"unexpected error in ForEachPackage: %v\", err)\n\t\t}\n\n\t\t// Only process the package root, or a sub-package of it.\n\t\tif !(strings.HasPrefix(pkg, root) &&\n\t\t\t(len(pkg) == len(root) || pkg[len(root)] == '/')) {\n\t\t\treturn\n\t\t}\n\n\t\tp, err := ctxt.Import(pkg, \"\", build.FindOnly)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"unexpected: package %s can not be located by build context: %s\", pkg, err)\n\t\t}\n\t\tif p.SrcRoot == \"\" {\n\t\t\tlog.Fatalf(\"unexpected: could not determine srcDir for package %s: %s\", pkg, err)\n\t\t}\n\t\tif p.SrcRoot != srcDir {\n\t\t\treturn\n\t\t}\n\n\t\tsubs[pkg] = true\n\t})\n\treturn subs\n}\n\ntype mover struct {\n\t// iprog contains all packages whose contents need to be updated\n\t// with new package names or import paths.\n\tiprog *loader.Program\n\tctxt  *build.Context\n\t// rev is the reverse import graph.\n\trev importgraph.Graph\n\t// from and to are the source and destination import\n\t// paths. fromDir and toDir are the source and destination\n\t// absolute paths that package source files will be moved between.\n\tfrom, to, fromDir, toDir string\n\t// affectedPackages is the set of all packages whose contents need\n\t// to be updated to reflect new package names or import paths.\n\taffectedPackages map[string]bool\n\t// destinations maps each subpackage to be moved to its\n\t// destination path.\n\tdestinations map[string]string\n\t// cmd, if not empty, will be executed to move fromDir to toDir.\n\tcmd string\n}\n\nfunc (m *mover) checkValid() error {\n\tconst prefix = \"invalid move destination\"\n\n\tmatch, err := regexp.MatchString(\"^[_\\\\pL][_\\\\pL\\\\p{Nd}]*$\", path.Base(m.to))\n\tif err != nil {\n\t\tpanic(\"regexp.MatchString failed\")\n\t}\n\tif !match {\n\t\treturn fmt.Errorf(\"%s: %s; gomvpkg does not support move destinations \"+\n\t\t\t\"whose base names are not valid go identifiers\", prefix, m.to)\n\t}\n\n\tif buildutil.FileExists(m.ctxt, m.toDir) {\n\t\treturn fmt.Errorf(\"%s: %s conflicts with file %s\", prefix, m.to, m.toDir)\n\t}\n\tif buildutil.IsDir(m.ctxt, m.toDir) {\n\t\treturn fmt.Errorf(\"%s: %s conflicts with directory %s\", prefix, m.to, m.toDir)\n\t}\n\n\tfor _, toSubPkg := range m.destinations {\n\t\tif _, err := m.ctxt.Import(toSubPkg, \"\", build.FindOnly); err == nil {\n\t\t\treturn fmt.Errorf(\"%s: %s; package or subpackage %s already exists\",\n\t\t\t\tprefix, m.to, toSubPkg)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// moveCmd produces the version control move command used to move fromDir to toDir by\n// executing the given template.\nfunc moveCmd(moveTmpl, fromDir, toDir string) (string, error) {\n\ttmpl, err := template.New(\"movecmd\").Parse(moveTmpl)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar buf bytes.Buffer\n\terr = tmpl.Execute(&buf, struct {\n\t\tSrc string\n\t\tDst string\n\t}{fromDir, toDir})\n\treturn buf.String(), err\n}\n\nfunc (m *mover) move() error {\n\tfilesToUpdate := make(map[*ast.File]bool)\n\n\t// Change the moved package's \"package\" declaration to its new base name.\n\tpkg, ok := m.iprog.Imported[m.from]\n\tif !ok {\n\t\tlog.Fatalf(\"unexpected: package %s is not in import map\", m.from)\n\t}\n\tnewName := filepath.Base(m.to)\n\tfor _, f := range pkg.Files {\n\t\t// Update all import comments.\n\t\tfor _, cg := range f.Comments {\n\t\t\tc := cg.List[0]\n\t\t\tif c.Slash >= f.Name.End() &&\n\t\t\t\tsameLine(m.iprog.Fset, c.Slash, f.Name.End()) &&\n\t\t\t\t(f.Decls == nil || c.Slash < f.Decls[0].Pos()) {\n\t\t\t\tif strings.HasPrefix(c.Text, `// import \"`) {\n\t\t\t\t\tc.Text = `// import \"` + m.to + `\"`\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif strings.HasPrefix(c.Text, `/* import \"`) {\n\t\t\t\t\tc.Text = `/* import \"` + m.to + `\" */`\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tf.Name.Name = newName // change package decl\n\t\tfilesToUpdate[f] = true\n\t}\n\n\t// Look through the external test packages (m.iprog.Created contains the external test packages).\n\tfor _, info := range m.iprog.Created {\n\t\t// Change the \"package\" declaration of the external test package.\n\t\tif info.Pkg.Path() == m.from+\"_test\" {\n\t\t\tfor _, f := range info.Files {\n\t\t\t\tf.Name.Name = newName + \"_test\" // change package decl\n\t\t\t\tfilesToUpdate[f] = true\n\t\t\t}\n\t\t}\n\n\t\t// Mark all the loaded external test packages, which import the \"from\" package,\n\t\t// as affected packages and update the imports.\n\t\tfor _, imp := range info.Pkg.Imports() {\n\t\t\tif imp.Path() == m.from {\n\t\t\t\tm.affectedPackages[info.Pkg.Path()] = true\n\t\t\t\tm.iprog.Imported[info.Pkg.Path()] = info\n\t\t\t\tif err := importName(m.iprog, info, m.from, path.Base(m.from), newName); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Update imports of that package to use the new import name.\n\t// None of the subpackages will change their name---only the from package\n\t// itself will.\n\tfor p := range m.rev[m.from] {\n\t\tif err := importName(m.iprog, m.iprog.Imported[p], m.from, path.Base(m.from), newName); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Update import paths for all imports by affected packages.\n\tfor ap := range m.affectedPackages {\n\t\tinfo, ok := m.iprog.Imported[ap]\n\t\tif !ok {\n\t\t\tlog.Fatalf(\"unexpected: package %s is not in import map\", ap)\n\t\t}\n\t\tfor _, f := range info.Files {\n\t\t\tfor _, imp := range f.Imports {\n\t\t\t\timportPath, _ := strconv.Unquote(imp.Path.Value)\n\t\t\t\tif newPath, ok := m.destinations[importPath]; ok {\n\t\t\t\t\timp.Path.Value = strconv.Quote(newPath)\n\n\t\t\t\t\toldName := path.Base(importPath)\n\t\t\t\t\tif imp.Name != nil {\n\t\t\t\t\t\toldName = imp.Name.Name\n\t\t\t\t\t}\n\n\t\t\t\t\tnewName := path.Base(newPath)\n\t\t\t\t\tif imp.Name == nil && oldName != newName {\n\t\t\t\t\t\timp.Name = ast.NewIdent(oldName)\n\t\t\t\t\t} else if imp.Name == nil || imp.Name.Name == newName {\n\t\t\t\t\t\timp.Name = nil\n\t\t\t\t\t}\n\t\t\t\t\tfilesToUpdate[f] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor f := range filesToUpdate {\n\t\tvar buf bytes.Buffer\n\t\tif err := format.Node(&buf, m.iprog.Fset, f); err != nil {\n\t\t\tlog.Printf(\"failed to pretty-print syntax tree: %v\", err)\n\t\t\tcontinue\n\t\t}\n\t\ttokenFile := m.iprog.Fset.File(f.FileStart)\n\t\twriteFile(tokenFile.Name(), buf.Bytes())\n\t}\n\n\t// Move the directories.\n\t// If either the fromDir or toDir are contained under version control it is\n\t// the user's responsibility to provide a custom move command that updates\n\t// version control to reflect the move.\n\t// TODO(matloob): If the parent directory of toDir does not exist, create it.\n\t//      For now, it's required that it does exist.\n\n\tif m.cmd != \"\" {\n\t\t// TODO(matloob): Verify that the windows and plan9 cases are correct.\n\t\tvar cmd *exec.Cmd\n\t\tswitch runtime.GOOS {\n\t\tcase \"windows\":\n\t\t\tcmd = exec.Command(\"cmd\", \"/c\", m.cmd)\n\t\tcase \"plan9\":\n\t\t\tcmd = exec.Command(\"rc\", \"-c\", m.cmd)\n\t\tdefault:\n\t\t\tcmd = exec.Command(\"sh\", \"-c\", m.cmd)\n\t\t}\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Stdout = os.Stdout\n\t\tif err := cmd.Run(); err != nil {\n\t\t\treturn fmt.Errorf(\"version control system's move command failed: %v\", err)\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn moveDirectory(m.fromDir, m.toDir)\n}\n\n// sameLine reports whether two positions in the same file are on the same line.\nfunc sameLine(fset *token.FileSet, x, y token.Pos) bool {\n\treturn fset.Position(x).Line == fset.Position(y).Line\n}\n\nvar moveDirectory = func(from, to string) error {\n\treturn os.Rename(from, to)\n}\n"
  },
  {
    "path": "refactor/rename/mvpkg_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rename\n\nimport (\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/token\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n)\n\nfunc TestErrors(t *testing.T) {\n\ttests := []struct {\n\t\tctxt     *build.Context\n\t\tfrom, to string\n\t\twant     string // regexp to match error, or \"OK\"\n\t}{\n\t\t// Simple example.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"bar\": {`package bar`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\nvar _ foo.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: `invalid move destination: bar conflicts with directory .go.src.bar`,\n\t\t},\n\t\t// Subpackage already exists.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\":     {`package foo; type T int`},\n\t\t\t\t\"foo/sub\": {`package sub`},\n\t\t\t\t\"bar/sub\": {`package sub`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\nvar _ foo.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: \"invalid move destination: bar; package or subpackage bar/sub already exists\",\n\t\t},\n\t\t// Invalid base name.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\nvar _ foo.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar-v2.0\",\n\t\t\twant: \"invalid move destination: bar-v2.0; gomvpkg does not \" +\n\t\t\t\t\"support move destinations whose base names are not valid \" +\n\t\t\t\t\"go identifiers\",\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {``},\n\t\t\t\t\"bar\": {`package bar`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: `no initial packages were loaded`,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tctxt := test.ctxt\n\n\t\tgot := make(map[string]string)\n\t\twriteFile = func(filename string, content []byte) error {\n\t\t\tgot[filename] = string(content)\n\t\t\treturn nil\n\t\t}\n\t\tmoveDirectory = func(from, to string) error {\n\t\t\tfor path, contents := range got {\n\t\t\t\tif strings.HasPrefix(path, from) {\n\t\t\t\t\tnewPath := strings.Replace(path, from, to, 1)\n\t\t\t\t\tdelete(got, path)\n\t\t\t\t\tgot[newPath] = contents\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\terr := Move(ctxt, test.from, test.to, \"\")\n\t\tprefix := fmt.Sprintf(\"-from %q -to %q\", test.from, test.to)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"%s: nil error. Expected error: %s\", prefix, test.want)\n\t\t\tcontinue\n\t\t}\n\t\tmatched, err2 := regexp.MatchString(test.want, err.Error())\n\t\tif err2 != nil {\n\t\t\tt.Errorf(\"regexp.MatchString failed %s\", err2)\n\t\t\tcontinue\n\t\t}\n\t\tif !matched {\n\t\t\tt.Errorf(\"%s: conflict does not match expectation:\\n\"+\n\t\t\t\t\"Error: %q\\n\"+\n\t\t\t\t\"Pattern: %q\",\n\t\t\t\tprefix, err.Error(), test.want)\n\t\t}\n\t}\n}\n\nfunc TestMoves(t *testing.T) {\n\ttests := []struct {\n\t\tctxt         *build.Context\n\t\tfrom, to     string\n\t\twant         map[string]string\n\t\twantWarnings []string\n\t}{\n\t\t// Simple example.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\nvar _ foo.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"bar\"\n\nvar _ bar.T\n`,\n\t\t\t\t\"/go/src/bar/0.go\": `package bar\n\ntype T int\n`,\n\t\t\t},\n\t\t},\n\n\t\t// Example with subpackage.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\":     {`package foo; type T int`},\n\t\t\t\t\"foo/sub\": {`package sub; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\nimport \"foo/sub\"\n\nvar _ foo.T\nvar _ sub.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"bar\"\nimport \"bar/sub\"\n\nvar _ bar.T\nvar _ sub.T\n`,\n\t\t\t\t\"/go/src/bar/0.go\": `package bar\n\ntype T int\n`,\n\t\t\t\t\"/go/src/bar/sub/0.go\": `package sub; type T int`,\n\t\t\t},\n\t\t},\n\n\t\t// References into subpackages\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\":   {`package foo; import \"foo/a\"; var _ a.T`},\n\t\t\t\t\"foo/a\": {`package a; type T int`},\n\t\t\t\t\"foo/b\": {`package b; import \"foo/a\"; var _ a.T`},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/bar/0.go\": `package bar\n\nimport \"bar/a\"\n\nvar _ a.T\n`,\n\t\t\t\t\"/go/src/bar/a/0.go\": `package a; type T int`,\n\t\t\t\t\"/go/src/bar/b/0.go\": `package b\n\nimport \"bar/a\"\n\nvar _ a.T\n`,\n\t\t\t},\n\t\t},\n\n\t\t// References into subpackages where directories have overlapped names\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\":    {},\n\t\t\t\t\"foo/a\":  {`package a`},\n\t\t\t\t\"foo/aa\": {`package bar`},\n\t\t\t\t\"foo/c\":  {`package c; import _ \"foo/bar\";`},\n\t\t\t}),\n\t\t\tfrom: \"foo/a\", to: \"foo/spam\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/foo/spam/0.go\": `package spam\n`,\n\t\t\t\t\"/go/src/foo/aa/0.go\": `package bar`,\n\t\t\t\t\"/go/src/foo/c/0.go\":  `package c; import _ \"foo/bar\";`,\n\t\t\t},\n\t\t},\n\n\t\t// External test packages\n\t\t{\n\t\t\tctxt: buildutil.FakeContext(map[string]map[string]string{\n\t\t\t\t\"foo\": {\n\t\t\t\t\t\"0.go\":      `package foo; type T int`,\n\t\t\t\t\t\"0_test.go\": `package foo_test; import \"foo\"; var _ foo.T`,\n\t\t\t\t},\n\t\t\t\t\"baz\": {\n\t\t\t\t\t\"0_test.go\": `package baz_test; import \"foo\"; var _ foo.T`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/bar/0.go\": `package bar\n\ntype T int\n`,\n\t\t\t\t\"/go/src/bar/0_test.go\": `package bar_test\n\nimport \"bar\"\n\nvar _ bar.T\n`,\n\t\t\t\t\"/go/src/baz/0_test.go\": `package baz_test\n\nimport \"bar\"\n\nvar _ bar.T\n`,\n\t\t\t},\n\t\t},\n\t\t// package import comments\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\"foo\": {`package foo // import \"baz\"`}}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\"/go/src/bar/0.go\": `package bar // import \"bar\"\n`},\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\"foo\": {`package foo /* import \"baz\" */`}}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\"/go/src/bar/0.go\": `package bar /* import \"bar\" */\n`},\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\"foo\": {`package foo       // import \"baz\"`}}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\"/go/src/bar/0.go\": `package bar // import \"bar\"\n`},\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\"foo\": {`package foo\n// import \" this is not an import comment`}}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\"/go/src/bar/0.go\": `package bar\n\n// import \" this is not an import comment\n`},\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\"foo\": {`package foo\n/* import \" this is not an import comment */`}}),\n\t\t\tfrom: \"foo\", to: \"bar\",\n\t\t\twant: map[string]string{\"/go/src/bar/0.go\": `package bar\n\n/* import \" this is not an import comment */\n`},\n\t\t},\n\t\t// Import name conflict generates a warning, not an error.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"x\": {},\n\t\t\t\t\"a\": {`package a; type A int`},\n\t\t\t\t\"b\": {`package b; type B int`},\n\t\t\t\t\"conflict\": {`package conflict\n\nimport \"a\"\nimport \"b\"\nvar _ a.A\nvar _ b.B\n`},\n\t\t\t\t\"ok\": {`package ok\nimport \"b\"\nvar _ b.B\n`},\n\t\t\t}),\n\t\t\tfrom: \"b\", to: \"x/a\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/a/0.go\": `package a; type A int`,\n\t\t\t\t\"/go/src/ok/0.go\": `package ok\n\nimport \"x/a\"\n\nvar _ a.B\n`,\n\t\t\t\t\"/go/src/conflict/0.go\": `package conflict\n\nimport \"a\"\nimport \"x/a\"\n\nvar _ a.A\nvar _ b.B\n`,\n\t\t\t\t\"/go/src/x/a/0.go\": `package a\n\ntype B int\n`,\n\t\t\t},\n\t\t\twantWarnings: []string{\n\t\t\t\t`/go/src/conflict/0.go:4:8: renaming this imported package name \"b\" to \"a\"`,\n\t\t\t\t`/go/src/conflict/0.go:3:8: \tconflicts with imported package name in same block`,\n\t\t\t\t`/go/src/conflict/0.go:3:8: skipping update of this file`,\n\t\t\t},\n\t\t},\n\t\t// Rename with same base name.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"x\": {},\n\t\t\t\t\"y\": {},\n\t\t\t\t\"x/foo\": {`package foo\n\ntype T int\n`},\n\t\t\t\t\"main\": {`package main; import \"x/foo\"; var _ foo.T`},\n\t\t\t}),\n\t\t\tfrom: \"x/foo\", to: \"y/foo\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/y/foo/0.go\": `package foo\n\ntype T int\n`,\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"y/foo\"\n\nvar _ foo.T\n`,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tctxt := test.ctxt\n\n\t\tgot := make(map[string]string)\n\t\t// Populate got with starting file set. rewriteFile and moveDirectory\n\t\t// will mutate got to produce resulting file set.\n\t\tbuildutil.ForEachPackage(ctxt, func(importPath string, err error) {\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpath := filepath.Join(\"/go/src\", importPath, \"0.go\")\n\t\t\tif !buildutil.FileExists(ctxt, path) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tf, err := ctxt.OpenFile(path)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"unexpected error opening file: %s\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tbytes, err := io.ReadAll(f)\n\t\t\tf.Close()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"unexpected error reading file: %s\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tgot[path] = string(bytes)\n\t\t})\n\t\tvar warnings []string\n\t\treportError = func(posn token.Position, message string) {\n\t\t\twarning := fmt.Sprintf(\"%s:%d:%d: %s\",\n\t\t\t\tfilepath.ToSlash(posn.Filename), // for MS Windows\n\t\t\t\tposn.Line,\n\t\t\t\tposn.Column,\n\t\t\t\tmessage)\n\t\t\twarnings = append(warnings, warning)\n\n\t\t}\n\t\twriteFile = func(filename string, content []byte) error {\n\t\t\tgot[filename] = string(content)\n\t\t\treturn nil\n\t\t}\n\t\tmoveDirectory = func(from, to string) error {\n\t\t\tfor path, contents := range got {\n\t\t\t\tif !(strings.HasPrefix(path, from) &&\n\t\t\t\t\t(len(path) == len(from) || path[len(from)] == filepath.Separator)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tnewPath := strings.Replace(path, from, to, 1)\n\t\t\t\tdelete(got, path)\n\t\t\t\tgot[newPath] = contents\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\n\t\terr := Move(ctxt, test.from, test.to, \"\")\n\t\tprefix := fmt.Sprintf(\"-from %q -to %q\", test.from, test.to)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: unexpected error: %s\", prefix, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif !reflect.DeepEqual(warnings, test.wantWarnings) {\n\t\t\tt.Errorf(\"%s: unexpected warnings:\\n%s\\nwant:\\n%s\",\n\t\t\t\tprefix,\n\t\t\t\tstrings.Join(warnings, \"\\n\"),\n\t\t\t\tstrings.Join(test.wantWarnings, \"\\n\"))\n\t\t}\n\n\t\tfor file, wantContent := range test.want {\n\t\t\tk := filepath.FromSlash(file)\n\t\t\tgotContent, ok := got[k]\n\t\t\tdelete(got, k)\n\t\t\tif !ok {\n\t\t\t\t// TODO(matloob): some testcases might have files that won't be\n\t\t\t\t// rewritten\n\t\t\t\tt.Errorf(\"%s: file %s not rewritten\", prefix, file)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif gotContent != wantContent {\n\t\t\t\tt.Errorf(\"%s: rewritten file %s does not match expectation; got <<<%s>>>\\n\"+\n\t\t\t\t\t\"want <<<%s>>>\", prefix, file, gotContent, wantContent)\n\t\t\t}\n\t\t}\n\t\t// got should now be empty\n\t\tfor file := range got {\n\t\t\tt.Errorf(\"%s: unexpected rewrite of file %s\", prefix, file)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "refactor/rename/rename.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package rename contains the obsolete implementation of the deleted\n// golang.org/x/tools/cmd/gorename. This logic has not worked properly\n// since the advent of Go modules, and should be deleted too.\n//\n// Use gopls instead, either via the Rename LSP method or the \"gopls\n// rename\" subcommand.\npackage rename\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/refactor/importgraph\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\nconst Usage = `gorename: precise type-safe renaming of identifiers in Go source code.\n\nUsage:\n\n gorename (-from <spec> | -offset <file>:#<byte-offset>) -to <name> [-force]\n\nYou must specify the object (named entity) to rename using the -offset\nor -from flag.  Exactly one must be specified.\n\nFlags:\n\n-offset    specifies the filename and byte offset of an identifier to rename.\n           This form is intended for use by text editors.\n\n-from      specifies the object to rename using a query notation;\n           This form is intended for interactive use at the command line.\n           A legal -from query has one of the following forms:\n\n  \"encoding/json\".Decoder.Decode        method of package-level named type\n  (*\"encoding/json\".Decoder).Decode     ditto, alternative syntax\n  \"encoding/json\".Decoder.buf           field of package-level named struct type\n  \"encoding/json\".HTMLEscape            package member (const, func, var, type)\n  \"encoding/json\".Decoder.Decode::x     local object x within a method\n  \"encoding/json\".HTMLEscape::x         local object x within a function\n  \"encoding/json\"::x                    object x anywhere within a package\n  json.go::x                            object x within file json.go\n\n           Double-quotes must be escaped when writing a shell command.\n           Quotes may be omitted for single-segment import paths such as \"fmt\".\n\n           For methods, the parens and '*' on the receiver type are both\n           optional.\n\n           It is an error if one of the ::x queries matches multiple\n           objects.\n\n-to        the new name.\n\n-force     causes the renaming to proceed even if conflicts were reported.\n           The resulting program may be ill-formed, or experience a change\n           in behaviour.\n\n           WARNING: this flag may even cause the renaming tool to crash.\n           (In due course this bug will be fixed by moving certain\n           analyses into the type-checker.)\n\n-d         display diffs instead of rewriting files\n\n-v         enables verbose logging.\n\ngorename automatically computes the set of packages that might be\naffected.  For a local renaming, this is just the package specified by\n-from or -offset, but for a potentially exported name, gorename scans\nthe workspace ($GOROOT and $GOPATH).\n\ngorename rejects renamings of concrete methods that would change the\nassignability relation between types and interfaces. If the interface\nchange was intentional, initiate the renaming at the interface method.\n\ngorename rejects any renaming that would create a conflict at the point\nof declaration, or a reference conflict (ambiguity or shadowing), or\nanything else that could cause the resulting program not to compile.\n\n\nExamples:\n\n$ gorename -offset file.go:#123 -to foo\n\n  Rename the object whose identifier is at byte offset 123 within file file.go.\n\n$ gorename -from '\"bytes\".Buffer.Len' -to Size\n\n  Rename the \"Len\" method of the *bytes.Buffer type to \"Size\".\n`\n\n// ---- TODO ----\n\n// Correctness:\n// - handle dot imports correctly\n// - document limitations (reflection, 'implements' algorithm).\n// - sketch a proof of exhaustiveness.\n\n// Features:\n// - support running on packages specified as *.go files on the command line\n// - support running on programs containing errors (loader.Config.AllowErrors)\n// - allow users to specify a scope other than \"global\" (to avoid being\n//   stuck by neglected packages in $GOPATH that don't build).\n// - support renaming the package clause (no object)\n// - support renaming an import path (no ident or object)\n//   (requires filesystem + SCM updates).\n// - detect and reject edits to autogenerated files (cgo, protobufs)\n//   and optionally $GOROOT packages.\n// - report all conflicts, or at least all qualitatively distinct ones.\n//   Sometimes we stop to avoid redundancy, but\n//   it may give a disproportionate sense of safety in -force mode.\n// - support renaming all instances of a pattern, e.g.\n//   all receiver vars of a given type,\n//   all local variables of a given type,\n//   all PkgNames for a given package.\n// - emit JSON output for other editors and tools.\n\nvar (\n\t// Force enables patching of the source files even if conflicts were reported.\n\t// The resulting program may be ill-formed.\n\t// It may even cause gorename to crash.  TODO(adonovan): fix that.\n\tForce bool\n\n\t// Diff causes the tool to display diffs instead of rewriting files.\n\tDiff bool\n\n\t// DiffCmd specifies the diff command used by the -d feature.\n\t// (The command must accept a -u flag and two filename arguments.)\n\tDiffCmd = \"diff\"\n\n\t// ConflictError is returned by Main when it aborts the renaming due to conflicts.\n\t// (It is distinguished because the interesting errors are the conflicts themselves.)\n\tConflictError = errors.New(\"renaming aborted due to conflicts\")\n\n\t// Verbose enables extra logging.\n\tVerbose bool\n)\n\nvar stdout io.Writer = os.Stdout\n\ntype renamer struct {\n\tiprog              *loader.Program\n\tobjsToUpdate       map[types.Object]bool\n\thadConflicts       bool\n\tfrom, to           string\n\tsatisfyConstraints map[satisfy.Constraint]bool\n\tpackages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect\n\tmsets              typeutil.MethodSetCache\n\tchangeMethods      bool\n}\n\nvar reportError = func(posn token.Position, message string) {\n\tfmt.Fprintf(os.Stderr, \"%s: %s\\n\", posn, message)\n}\n\n// importName renames imports of fromPath within the package specified by info.\n// If fromName is not empty, importName renames only imports as fromName.\n// If the renaming would lead to a conflict, the file is left unchanged.\nfunc importName(iprog *loader.Program, info *loader.PackageInfo, fromPath, fromName, to string) error {\n\tif fromName == to {\n\t\treturn nil // no-op (e.g. rename x/foo to y/foo)\n\t}\n\tfor _, f := range info.Files {\n\t\tvar from types.Object\n\t\tfor _, imp := range f.Imports {\n\t\t\timportPath, _ := strconv.Unquote(imp.Path.Value)\n\t\t\timportName := path.Base(importPath)\n\t\t\tif imp.Name != nil {\n\t\t\t\timportName = imp.Name.Name\n\t\t\t}\n\t\t\tif importPath == fromPath && (fromName == \"\" || importName == fromName) {\n\t\t\t\tfrom = info.Implicits[imp]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif from == nil {\n\t\t\tcontinue\n\t\t}\n\t\tr := renamer{\n\t\t\tiprog:        iprog,\n\t\t\tobjsToUpdate: make(map[types.Object]bool),\n\t\t\tto:           to,\n\t\t\tpackages:     map[*types.Package]*loader.PackageInfo{info.Pkg: info},\n\t\t}\n\t\tr.check(from)\n\t\tif r.hadConflicts {\n\t\t\treportError(iprog.Fset.Position(f.Imports[0].Pos()),\n\t\t\t\t\"skipping update of this file\")\n\t\t\tcontinue // ignore errors; leave the existing name\n\t\t}\n\t\tif err := r.update(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {\n\t// -- Parse the -from or -offset specifier ----------------------------\n\n\tif (offsetFlag == \"\") == (fromFlag == \"\") {\n\t\treturn fmt.Errorf(\"exactly one of the -from and -offset flags must be specified\")\n\t}\n\n\tif !isValidIdentifier(to) {\n\t\treturn fmt.Errorf(\"-to %q: not a valid identifier\", to)\n\t}\n\n\tif Diff {\n\t\tdefer func(saved func(string, []byte) error) { writeFile = saved }(writeFile)\n\t\twriteFile = diff\n\t}\n\n\tvar spec *spec\n\tvar err error\n\tif fromFlag != \"\" {\n\t\tspec, err = parseFromFlag(ctxt, fromFlag)\n\t} else {\n\t\tspec, err = parseOffsetFlag(ctxt, offsetFlag)\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif spec.fromName == to {\n\t\treturn fmt.Errorf(\"the old and new names are the same: %s\", to)\n\t}\n\n\t// -- Load the program consisting of the initial package  -------------\n\n\tiprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfromObjects, err := findFromObjects(iprog, spec)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// -- Load a larger program, for global renamings ---------------------\n\n\tif requiresGlobalRename(fromObjects, to) {\n\t\t// For a local refactoring, we needn't load more\n\t\t// packages, but if the renaming affects the package's\n\t\t// API, we must load all packages that depend on the\n\t\t// package defining the object, plus their tests.\n\n\t\tif Verbose {\n\t\t\tlog.Print(\"Potentially global renaming; scanning workspace...\")\n\t\t}\n\n\t\t// Scan the workspace and build the import graph.\n\t\t_, rev, errors := importgraph.Build(ctxt)\n\t\tif len(errors) > 0 {\n\t\t\t// With a large GOPATH tree, errors are inevitable.\n\t\t\t// Report them but proceed.\n\t\t\tfmt.Fprintf(os.Stderr, \"While scanning Go workspace:\\n\")\n\t\t\tfor path, err := range errors {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"Package %q: %s.\\n\", path, err)\n\t\t\t}\n\t\t}\n\n\t\t// Enumerate the set of potentially affected packages.\n\t\taffectedPackages := make(map[string]bool)\n\t\tfor _, obj := range fromObjects {\n\t\t\t// External test packages are never imported,\n\t\t\t// so they will never appear in the graph.\n\t\t\tfor path := range rev.Search(obj.Pkg().Path()) {\n\t\t\t\taffectedPackages[path] = true\n\t\t\t}\n\t\t}\n\n\t\t// TODO(adonovan): allow the user to specify the scope,\n\t\t// or -ignore patterns?  Computing the scope when we\n\t\t// don't (yet) support inputs containing errors can make\n\t\t// the tool rather brittle.\n\n\t\t// Re-load the larger program.\n\t\tiprog, err = loadProgram(ctxt, affectedPackages)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfromObjects, err = findFromObjects(iprog, spec)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// -- Do the renaming -------------------------------------------------\n\n\tr := renamer{\n\t\tiprog:        iprog,\n\t\tobjsToUpdate: make(map[types.Object]bool),\n\t\tfrom:         spec.fromName,\n\t\tto:           to,\n\t\tpackages:     make(map[*types.Package]*loader.PackageInfo),\n\t}\n\n\t// A renaming initiated at an interface method indicates the\n\t// intention to rename abstract and concrete methods as needed\n\t// to preserve assignability.\n\tfor _, obj := range fromObjects {\n\t\tif obj, ok := obj.(*types.Func); ok {\n\t\t\trecv := obj.Signature().Recv()\n\t\t\tif recv != nil && types.IsInterface(recv.Type()) {\n\t\t\t\tr.changeMethods = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Only the initially imported packages (iprog.Imported) and\n\t// their external tests (iprog.Created) should be inspected or\n\t// modified, as only they have type-checked function bodies.\n\t// The rest are just dependencies, needed only for package-level\n\t// type information.\n\tfor _, info := range iprog.Imported {\n\t\tr.packages[info.Pkg] = info\n\t}\n\tfor _, info := range iprog.Created { // (tests)\n\t\tr.packages[info.Pkg] = info\n\t}\n\n\tfor _, from := range fromObjects {\n\t\tr.check(from)\n\t}\n\tif r.hadConflicts && !Force {\n\t\treturn ConflictError\n\t}\n\treturn r.update()\n}\n\n// loadProgram loads the specified set of packages (plus their tests)\n// and all their dependencies, from source, through the specified build\n// context.  Only packages in pkgs will have their functions bodies typechecked.\nfunc loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {\n\tconf := loader.Config{\n\t\tBuild:      ctxt,\n\t\tParserMode: parser.ParseComments,\n\n\t\t// TODO(adonovan): enable this.  Requires making a lot of code more robust!\n\t\tAllowErrors: false,\n\t}\n\t// Optimization: don't type-check the bodies of functions in our\n\t// dependencies, since we only need exported package members.\n\tconf.TypeCheckFuncBodies = func(p string) bool {\n\t\treturn pkgs[p] || pkgs[strings.TrimSuffix(p, \"_test\")]\n\t}\n\n\tif Verbose {\n\t\tvar list []string\n\t\tfor pkg := range pkgs {\n\t\t\tlist = append(list, pkg)\n\t\t}\n\t\tsort.Strings(list)\n\t\tfor _, pkg := range list {\n\t\t\tlog.Printf(\"Loading package: %s\", pkg)\n\t\t}\n\t}\n\n\tfor pkg := range pkgs {\n\t\tconf.ImportWithTests(pkg)\n\t}\n\n\t// Ideally we would just return conf.Load() here, but go/types\n\t// reports certain \"soft\" errors that gc does not (Go issue 14596).\n\t// As a workaround, we set AllowErrors=true and then duplicate\n\t// the loader's error checking but allow soft errors.\n\t// It would be nice if the loader API permitted \"AllowErrors: soft\".\n\tconf.AllowErrors = true\n\tprog, err := conf.Load()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar errpkgs []string\n\t// Report hard errors in indirectly imported packages.\n\tfor _, info := range prog.AllPackages {\n\t\tif containsHardErrors(info.Errors) {\n\t\t\terrpkgs = append(errpkgs, info.Pkg.Path())\n\t\t}\n\t}\n\tif errpkgs != nil {\n\t\tvar more string\n\t\tif len(errpkgs) > 3 {\n\t\t\tmore = fmt.Sprintf(\" and %d more\", len(errpkgs)-3)\n\t\t\terrpkgs = errpkgs[:3]\n\t\t}\n\t\treturn nil, fmt.Errorf(\"couldn't load packages due to errors: %s%s\",\n\t\t\tstrings.Join(errpkgs, \", \"), more)\n\t}\n\treturn prog, nil\n}\n\nfunc containsHardErrors(errors []error) bool {\n\tfor _, err := range errors {\n\t\tif err, ok := err.(types.Error); ok && err.Soft {\n\t\t\tcontinue\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\n// requiresGlobalRename reports whether this renaming could potentially\n// affect other packages in the Go workspace.\nfunc requiresGlobalRename(fromObjects []types.Object, to string) bool {\n\tvar tfm bool\n\tfor _, from := range fromObjects {\n\t\tif from.Exported() {\n\t\t\treturn true\n\t\t}\n\t\tswitch objectKind(from) {\n\t\tcase \"type\", \"field\", \"method\":\n\t\t\ttfm = true\n\t\t}\n\t}\n\tif ast.IsExported(to) && tfm {\n\t\t// A global renaming may be necessary even if we're\n\t\t// exporting a previous unexported name, since if it's\n\t\t// the name of a type, field or method, this could\n\t\t// change selections in other packages.\n\t\t// (We include \"type\" in this list because a type\n\t\t// used as an embedded struct field entails a field\n\t\t// renaming.)\n\t\treturn true\n\t}\n\treturn false\n}\n\n// update updates the input files.\nfunc (r *renamer) update() error {\n\t// We use token.File, not filename, since a file may appear to\n\t// belong to multiple packages and be parsed more than once.\n\t// token.File captures this distinction; filename does not.\n\n\tvar nidents int\n\tvar filesToUpdate = make(map[*token.File]bool)\n\tdocRegexp := regexp.MustCompile(`\\b` + r.from + `\\b`)\n\tfor _, info := range r.packages {\n\t\t// Mutate the ASTs and note the filenames.\n\t\tfor id, obj := range info.Defs {\n\t\t\tif r.objsToUpdate[obj] {\n\t\t\t\tnidents++\n\t\t\t\tid.Name = r.to\n\t\t\t\tfilesToUpdate[r.iprog.Fset.File(id.Pos())] = true\n\t\t\t\t// Perform the rename in doc comments too.\n\t\t\t\tif doc := r.docComment(id); doc != nil {\n\t\t\t\t\tfor _, comment := range doc.List {\n\t\t\t\t\t\tcomment.Text = docRegexp.ReplaceAllString(comment.Text, r.to)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor id, obj := range info.Uses {\n\t\t\tif r.objsToUpdate[obj] {\n\t\t\t\tnidents++\n\t\t\t\tid.Name = r.to\n\t\t\t\tfilesToUpdate[r.iprog.Fset.File(id.Pos())] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Renaming not supported if cgo files are affected.\n\tvar generatedFileNames []string\n\tfor _, info := range r.packages {\n\t\tfor _, f := range info.Files {\n\t\t\ttokenFile := r.iprog.Fset.File(f.FileStart)\n\t\t\tif filesToUpdate[tokenFile] && ast.IsGenerated(f) {\n\t\t\t\tgeneratedFileNames = append(generatedFileNames, tokenFile.Name())\n\t\t\t}\n\t\t}\n\t}\n\tif !Force && len(generatedFileNames) > 0 {\n\t\treturn fmt.Errorf(\"refusing to modify generated file%s containing DO NOT EDIT marker: %v\", plural(len(generatedFileNames)), generatedFileNames)\n\t}\n\n\t// Write affected files.\n\tvar nerrs, npkgs int\n\tfor _, info := range r.packages {\n\t\tfirst := true\n\t\tfor _, f := range info.Files {\n\t\t\ttokenFile := r.iprog.Fset.File(f.FileStart)\n\t\t\tif filesToUpdate[tokenFile] {\n\t\t\t\tif first {\n\t\t\t\t\tnpkgs++\n\t\t\t\t\tfirst = false\n\t\t\t\t\tif Verbose {\n\t\t\t\t\t\tlog.Printf(\"Updating package %s\", info.Pkg.Path())\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfilename := tokenFile.Name()\n\t\t\t\tvar buf bytes.Buffer\n\t\t\t\tif err := format.Node(&buf, r.iprog.Fset, f); err != nil {\n\t\t\t\t\tlog.Printf(\"failed to pretty-print syntax tree: %v\", err)\n\t\t\t\t\tnerrs++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err := writeFile(filename, buf.Bytes()); err != nil {\n\t\t\t\t\tlog.Print(err)\n\t\t\t\t\tnerrs++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif !Diff {\n\t\tfmt.Printf(\"Renamed %d occurrence%s in %d file%s in %d package%s.\\n\",\n\t\t\tnidents, plural(nidents),\n\t\t\tlen(filesToUpdate), plural(len(filesToUpdate)),\n\t\t\tnpkgs, plural(npkgs))\n\t}\n\tif nerrs > 0 {\n\t\treturn fmt.Errorf(\"failed to rewrite %d file%s\", nerrs, plural(nerrs))\n\t}\n\treturn nil\n}\n\n// docComment returns the doc for an identifier.\nfunc (r *renamer) docComment(id *ast.Ident) *ast.CommentGroup {\n\t_, nodes, _ := r.iprog.PathEnclosingInterval(id.Pos(), id.End())\n\tfor _, node := range nodes {\n\t\tswitch decl := node.(type) {\n\t\tcase *ast.FuncDecl:\n\t\t\treturn decl.Doc\n\t\tcase *ast.Field:\n\t\t\treturn decl.Doc\n\t\tcase *ast.GenDecl:\n\t\t\treturn decl.Doc\n\t\t// For {Type,Value}Spec, if the doc on the spec is absent,\n\t\t// search for the enclosing GenDecl\n\t\tcase *ast.TypeSpec:\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\tcase *ast.ValueSpec:\n\t\t\tif decl.Doc != nil {\n\t\t\t\treturn decl.Doc\n\t\t\t}\n\t\tcase *ast.Ident:\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc plural(n int) string {\n\tif n != 1 {\n\t\treturn \"s\"\n\t}\n\treturn \"\"\n}\n\n// writeFile is a seam for testing and for the -d flag.\nvar writeFile = reallyWriteFile\n\nfunc reallyWriteFile(filename string, content []byte) error {\n\treturn os.WriteFile(filename, content, 0644)\n}\n\nfunc diff(filename string, content []byte) error {\n\trenamed := fmt.Sprintf(\"%s.%d.renamed\", filename, os.Getpid())\n\tif err := os.WriteFile(renamed, content, 0644); err != nil {\n\t\treturn err\n\t}\n\tdefer os.Remove(renamed)\n\n\tdiff, err := exec.Command(DiffCmd, \"-u\", filename, renamed).Output()\n\tif len(diff) > 0 {\n\t\t// diff exits with a non-zero status when the files don't match.\n\t\t// Ignore that failure as long as we get output.\n\t\tstdout.Write(diff)\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\tif exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {\n\t\t\terr = fmt.Errorf(\"%w\\nstderr:\\n%s\", err, exit.Stderr)\n\t\t}\n\t\treturn fmt.Errorf(\"computing diff: %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "refactor/rename/rename_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rename\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/build\"\n\t\"go/token\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/internal/testenv\"\n)\n\n// TODO(adonovan): test reported source positions, somehow.\n\nfunc TestConflicts(t *testing.T) {\n\tdefer func(savedWriteFile func(string, []byte) error, savedReportError func(token.Position, string)) {\n\t\twriteFile = savedWriteFile\n\t\treportError = savedReportError\n\t}(writeFile, reportError)\n\twriteFile = func(string, []byte) error { return nil }\n\n\tvar ctxt *build.Context\n\tfor _, test := range []struct {\n\t\tctxt             *build.Context // nil => use previous\n\t\toffset, from, to string         // values of the -offset/-from and -to flags\n\t\twant             string         // regexp to match conflict errors, or \"OK\"\n\t}{\n\t\t// init() checks\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"fmt\": {`package fmt; type Stringer interface { String() }`},\n\t\t\t\t\"main\": {`\npackage main\n\nimport foo \"fmt\"\n\nvar v foo.Stringer\n\nfunc f() { v.String(); f() }\n`,\n\t\t\t\t\t`package main; var w int`},\n\t\t\t}),\n\t\t\tfrom: \"main.v\", to: \"init\",\n\t\t\twant: `you cannot have a var at package level named \"init\"`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f\", to: \"init\",\n\t\t\twant: `renaming this func \"f\" to \"init\" would make it a package initializer.*` +\n\t\t\t\t`but references to it exist`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"/go/src/main/0.go::foo\", to: \"init\",\n\t\t\twant: `\"init\" is not a valid imported package name`,\n\t\t},\n\n\t\t// Export checks\n\t\t{\n\t\t\tfrom: \"fmt.Stringer\", to: \"stringer\",\n\t\t\twant: `renaming this type \"Stringer\" to \"stringer\" would make it unexported.*` +\n\t\t\t\t`breaking references from packages such as \"main\"`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(fmt.Stringer).String\", to: \"string\",\n\t\t\twant: `renaming this method \"String\" to \"string\" would make it unexported.*` +\n\t\t\t\t`breaking references from packages such as \"main\"`,\n\t\t},\n\n\t\t// Lexical scope checks\n\t\t{\n\t\t\t// file/package conflict, same file\n\t\t\tfrom: \"main.v\", to: \"foo\",\n\t\t\twant: `renaming this var \"v\" to \"foo\" would conflict.*` +\n\t\t\t\t`with this imported package name`,\n\t\t},\n\t\t{\n\t\t\t// file/package conflict, same file\n\t\t\tfrom: \"main::foo\", to: \"v\",\n\t\t\twant: `renaming this imported package name \"foo\" to \"v\" would conflict.*` +\n\t\t\t\t`with this package member var`,\n\t\t},\n\t\t{\n\t\t\t// file/package conflict, different files\n\t\t\tfrom: \"main.w\", to: \"foo\",\n\t\t\twant: `renaming this var \"w\" to \"foo\" would conflict.*` +\n\t\t\t\t`with this imported package name`,\n\t\t},\n\t\t{\n\t\t\t// file/package conflict, different files\n\t\t\tfrom: \"main::foo\", to: \"w\",\n\t\t\twant: `renaming this imported package name \"foo\" to \"w\" would conflict.*` +\n\t\t\t\t`with this package member var`,\n\t\t},\n\t\t{\n\t\t\tctxt: main(`\npackage main\n\nvar x, z int\n\nfunc f(y int) {\n\tprint(x)\n\tprint(y)\n}\n\nfunc g(w int) {\n\tprint(x)\n\tx := 1\n\tprint(x)\n}`),\n\t\t\tfrom: \"main.x\", to: \"y\",\n\t\t\twant: `renaming this var \"x\" to \"y\".*` +\n\t\t\t\t`would cause this reference to become shadowed.*` +\n\t\t\t\t`by this intervening var definition`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.g::x\", to: \"w\",\n\t\t\twant: `renaming this var \"x\" to \"w\".*` +\n\t\t\t\t`conflicts with var in same block`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::y\", to: \"x\",\n\t\t\twant: `renaming this var \"y\" to \"x\".*` +\n\t\t\t\t`would shadow this reference.*` +\n\t\t\t\t`to the var declared here`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.g::w\", to: \"x\",\n\t\t\twant: `renaming this var \"w\" to \"x\".*` +\n\t\t\t\t`conflicts with var in same block`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.z\", to: \"y\", want: \"OK\",\n\t\t},\n\n\t\t// Label checks\n\t\t{\n\t\t\tctxt: main(`\npackage main\n\nfunc f() {\nfoo:\n\tgoto foo\nbar:\n\tgoto bar\n\tfunc(x int) {\n\twiz:\n\t\tgoto wiz\n\t}(0)\n}\n`),\n\t\t\tfrom: \"main.f::foo\", to: \"bar\",\n\t\t\twant: `renaming this label \"foo\" to \"bar\".*` +\n\t\t\t\t`would conflict with this one`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::foo\", to: \"wiz\", want: \"OK\",\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::wiz\", to: \"x\", want: \"OK\",\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::x\", to: \"wiz\", want: \"OK\",\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::wiz\", to: \"foo\", want: \"OK\",\n\t\t},\n\n\t\t// Struct fields\n\t\t{\n\t\t\tctxt: main(`\npackage main\n\ntype U struct { u int }\ntype V struct { v int }\n\nfunc (V) x() {}\n\ntype W (struct {\n\tU\n\tV\n\tw int\n})\n\nfunc f() {\n\tvar w W\n\tprint(w.u) // NB: there is no selection of w.v\n\tvar _ struct { yy, zz int }\n}\n`),\n\t\t\t// field/field conflict in named struct declaration\n\t\t\tfrom: \"(main.W).U\", to: \"w\",\n\t\t\twant: `renaming this field \"U\" to \"w\".*` +\n\t\t\t\t`would conflict with this field`,\n\t\t},\n\t\t{\n\t\t\t// rename type used as embedded field\n\t\t\t// => rename field\n\t\t\t// => field/field conflict\n\t\t\t// This is an entailed renaming;\n\t\t\t// it would be nice if we checked source positions.\n\t\t\tfrom: \"main.U\", to: \"w\",\n\t\t\twant: `renaming this field \"U\" to \"w\".*` +\n\t\t\t\t`would conflict with this field`,\n\t\t},\n\t\t{\n\t\t\t// field/field conflict in unnamed struct declaration\n\t\t\tfrom: \"main.f::zz\", to: \"yy\",\n\t\t\twant: `renaming this field \"zz\" to \"yy\".*` +\n\t\t\t\t`would conflict with this field`,\n\t\t},\n\n\t\t// Now we test both directions of (u,v) (u,w) (v,w) (u,x) (v,x).\n\t\t// Too bad we don't test position info...\n\t\t{\n\t\t\t// field/field ambiguity at same promotion level ('from' selection)\n\t\t\tfrom: \"(main.U).u\", to: \"v\",\n\t\t\twant: `renaming this field \"u\" to \"v\".*` +\n\t\t\t\t`would make this reference ambiguous.*` +\n\t\t\t\t`with this field`,\n\t\t},\n\t\t{\n\t\t\t// field/field ambiguity at same promotion level ('to' selection)\n\t\t\tfrom: \"(main.V).v\", to: \"u\",\n\t\t\twant: `renaming this field \"v\" to \"u\".*` +\n\t\t\t\t`would make this reference ambiguous.*` +\n\t\t\t\t`with this field`,\n\t\t},\n\t\t{\n\t\t\t// field/method conflict at different promotion level ('from' selection)\n\t\t\tfrom: \"(main.U).u\", to: \"w\",\n\t\t\twant: `renaming this field \"u\" to \"w\".*` +\n\t\t\t\t`would change the referent of this selection.*` +\n\t\t\t\t`of this field`,\n\t\t},\n\t\t{\n\t\t\t// field/field shadowing at different promotion levels ('to' selection)\n\t\t\tfrom: \"(main.W).w\", to: \"u\",\n\t\t\twant: `renaming this field \"w\" to \"u\".*` +\n\t\t\t\t`would shadow this selection.*` +\n\t\t\t\t`of the field declared here`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.V).v\", to: \"w\",\n\t\t\twant: \"OK\", // since no selections are made ambiguous\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.W).w\", to: \"v\",\n\t\t\twant: \"OK\", // since no selections are made ambiguous\n\t\t},\n\t\t{\n\t\t\t// field/method ambiguity at same promotion level ('from' selection)\n\t\t\tfrom: \"(main.U).u\", to: \"x\",\n\t\t\twant: `renaming this field \"u\" to \"x\".*` +\n\t\t\t\t`would make this reference ambiguous.*` +\n\t\t\t\t`with this method`,\n\t\t},\n\t\t{\n\t\t\t// field/field ambiguity at same promotion level ('to' selection)\n\t\t\tfrom: \"(main.V).x\", to: \"u\",\n\t\t\twant: `renaming this method \"x\" to \"u\".*` +\n\t\t\t\t`would make this reference ambiguous.*` +\n\t\t\t\t`with this field`,\n\t\t},\n\t\t{\n\t\t\t// field/method conflict at named struct declaration\n\t\t\tfrom: \"(main.V).v\", to: \"x\",\n\t\t\twant: `renaming this field \"v\" to \"x\".*` +\n\t\t\t\t`would conflict with this method`,\n\t\t},\n\t\t{\n\t\t\t// field/method conflict at named struct declaration\n\t\t\tfrom: \"(main.V).x\", to: \"v\",\n\t\t\twant: `renaming this method \"x\" to \"v\".*` +\n\t\t\t\t`would conflict with this field`,\n\t\t},\n\n\t\t// Methods\n\t\t{\n\t\t\tctxt: main(`\npackage main\ntype C int\nfunc (C) f()\nfunc (C) g()\ntype D int\nfunc (*D) f()\nfunc (*D) g()\ntype I interface { f(); g() }\ntype J interface { I; h() }\nvar _ I = new(D)\nvar _ interface {f()} = C(0)\n`),\n\t\t\tfrom: \"(main.I).f\", to: \"g\",\n\t\t\twant: `renaming this interface method \"f\" to \"g\".*` +\n\t\t\t\t`would conflict with this method`,\n\t\t},\n\t\t{\n\t\t\tfrom: `(\"main\".I).f`, to: \"h\", // NB: exercises quoted import paths too\n\t\t\twant: `renaming this interface method \"f\" to \"h\".*` +\n\t\t\t\t`would conflict with this method.*` +\n\t\t\t\t`in named interface type \"J\"`,\n\t\t},\n\t\t{\n\t\t\t// type J interface { h; h() } is not a conflict, amusingly.\n\t\t\tfrom: \"main.I\", to: \"h\",\n\t\t\twant: `OK`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.J).h\", to: \"f\",\n\t\t\twant: `renaming this interface method \"h\" to \"f\".*` +\n\t\t\t\t`would conflict with this method`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.C).f\", to: \"e\",\n\t\t\twant: `renaming this method \"f\" to \"e\".*` +\n\t\t\t\t`would make main.C no longer assignable to interface{f..}.*` +\n\t\t\t\t`(rename interface{f..}.f if you intend to change both types)`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.D).g\", to: \"e\",\n\t\t\twant: `renaming this method \"g\" to \"e\".*` +\n\t\t\t\t`would make \\*main.D no longer assignable to interface I.*` +\n\t\t\t\t`(rename main.I.g if you intend to change both types)`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"(main.I).f\", to: \"e\",\n\t\t\twant: `OK`,\n\t\t},\n\t\t// Indirect C/I method coupling via another concrete type D.\n\t\t{\n\t\t\tctxt: main(`\npackage main\ntype I interface { f() }\ntype C int\nfunc (C) f()\ntype D struct{C}\nvar _ I = D{}\n`),\n\t\t\tfrom: \"(main.C).f\", to: \"F\",\n\t\t\twant: `renaming this method \"f\" to \"F\".*` +\n\t\t\t\t`would make main.D no longer assignable to interface I.*` +\n\t\t\t\t`(rename main.I.f if you intend to change both types)`,\n\t\t},\n\t\t// Renaming causes promoted method to become shadowed; C no longer satisfies I.\n\t\t{\n\t\t\tctxt: main(`\npackage main\ntype I interface { f() }\ntype C struct { I }\nfunc (C) g() int\nvar _ I = C{}\n`),\n\t\t\tfrom: \"main.I.f\", to: \"g\",\n\t\t\twant: `renaming this method \"f\" to \"g\".*` +\n\t\t\t\t`would change the g method of main.C invoked via interface main.I.*` +\n\t\t\t\t`from \\(main.I\\).g.*` +\n\t\t\t\t`to \\(main.C\\).g`,\n\t\t},\n\t\t// Renaming causes promoted method to become ambiguous; C no longer satisfies I.\n\t\t{\n\t\t\tctxt: main(`\npackage main\ntype I interface{f()}\ntype C int\nfunc (C) f()\ntype D int\nfunc (D) g()\ntype E struct{C;D}\nvar _ I = E{}\n`),\n\t\t\tfrom: \"main.I.f\", to: \"g\",\n\t\t\twant: `renaming this method \"f\" to \"g\".*` +\n\t\t\t\t`would make the g method of main.E invoked via interface main.I ambiguous.*` +\n\t\t\t\t`with \\(main.D\\).g`,\n\t\t},\n\t} {\n\t\tvar conflicts []string\n\t\treportError = func(posn token.Position, message string) {\n\t\t\tconflicts = append(conflicts, message)\n\t\t}\n\t\tif test.ctxt != nil {\n\t\t\tctxt = test.ctxt\n\t\t}\n\t\terr := Main(ctxt, test.offset, test.from, test.to)\n\t\tvar prefix string\n\t\tif test.offset == \"\" {\n\t\t\tprefix = fmt.Sprintf(\"-from %q -to %q\", test.from, test.to)\n\t\t} else {\n\t\t\tprefix = fmt.Sprintf(\"-offset %q -to %q\", test.offset, test.to)\n\t\t}\n\t\tif err == ConflictError {\n\t\t\tgot := strings.Join(conflicts, \"\\n\")\n\t\t\tif false {\n\t\t\t\tt.Logf(\"%s: %s\", prefix, got)\n\t\t\t}\n\t\t\tpattern := \"(?s:\" + test.want + \")\" // enable multi-line matching\n\t\t\tif !regexp.MustCompile(pattern).MatchString(got) {\n\t\t\t\tt.Errorf(\"%s: conflict does not match pattern:\\n\"+\n\t\t\t\t\t\"Conflict:\\t%s\\n\"+\n\t\t\t\t\t\"Pattern: %s\",\n\t\t\t\t\tprefix, got, test.want)\n\t\t\t}\n\t\t} else if err != nil {\n\t\t\tt.Errorf(\"%s: unexpected error: %s\", prefix, err)\n\t\t} else if test.want != \"OK\" {\n\t\t\tt.Errorf(\"%s: unexpected success, want conflicts matching:\\n%s\",\n\t\t\t\tprefix, test.want)\n\t\t}\n\t}\n}\n\nfunc TestInvalidIdentifiers(t *testing.T) {\n\tctxt := fakeContext(map[string][]string{\n\t\t\"main\": {`\npackage main\n\nfunc f() { }\n`}})\n\n\tfor _, test := range []struct {\n\t\tfrom, to string // values of the -offset/-from and -to flags\n\t\twant     string // expected error message\n\t}{\n\t\t{\n\t\t\tfrom: \"main.f\", to: \"_\",\n\t\t\twant: `-to \"_\": not a valid identifier`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f\", to: \"123\",\n\t\t\twant: `-to \"123\": not a valid identifier`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f\", to: \"for\",\n\t\t\twant: `-to \"for\": not a valid identifier`,\n\t\t},\n\t\t{\n\t\t\tfrom: \"switch\", to: \"v\",\n\t\t\twant: `-from \"switch\": invalid expression`,\n\t\t},\n\t} {\n\t\terr := Main(ctxt, \"\", test.from, test.to)\n\t\tprefix := fmt.Sprintf(\"-from %q -to %q\", test.from, test.to)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"%s: expected error %q\", prefix, test.want)\n\t\t} else if err.Error() != test.want {\n\t\t\tt.Errorf(\"%s: unexpected error\\nwant: %s\\n got: %s\", prefix, test.want, err.Error())\n\t\t}\n\t}\n}\n\nfunc TestRewrites(t *testing.T) {\n\tdefer func(savedWriteFile func(string, []byte) error) {\n\t\twriteFile = savedWriteFile\n\t}(writeFile)\n\n\tvar ctxt *build.Context\n\tfor _, test := range []struct {\n\t\tctxt             *build.Context    // nil => use previous\n\t\toffset, from, to string            // values of the -from/-offset and -to flags\n\t\twant             map[string]string // contents of updated files\n\t\talias            bool              // requires materialized aliases\n\t}{\n\t\t// Elimination of renaming import.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport foo2 \"foo\"\n\nvar _ foo2.T\n`},\n\t\t\t}),\n\t\t\tfrom: \"main::foo2\", to: \"foo\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"foo\"\n\nvar _ foo.T\n`,\n\t\t\t},\n\t\t},\n\t\t// Introduction of renaming import.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\nvar _ foo.T\n`},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#36\", to: \"foo2\", // the \"foo\" in foo.T\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport foo2 \"foo\"\n\nvar _ foo2.T\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of package-level member.\n\t\t{\n\t\t\tfrom: \"foo.T\", to: \"U\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"foo\"\n\nvar _ foo.U\n`,\n\t\t\t\t\"/go/src/foo/0.go\": `package foo\n\ntype U int\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename package-level func plus doc\n\t\t{\n\t\t\tctxt: main(`package main\n\n// Foo is a no-op.\n// Calling Foo does nothing.\nfunc Foo() {\n}\n`),\n\t\t\tfrom: \"main.Foo\", to: \"FooBar\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\n// FooBar is a no-op.\n// Calling FooBar does nothing.\nfunc FooBar() {\n}\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename method plus doc\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype Foo struct{}\n\n// Bar does nothing.\nfunc (Foo) Bar() {\n}\n`),\n\t\t\tfrom: \"main.Foo.Bar\", to: \"Baz\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype Foo struct{}\n\n// Baz does nothing.\nfunc (Foo) Baz() {\n}\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename type spec plus doc\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype (\n\t// Test but not Testing.\n\tTest struct{}\n)\n`),\n\t\t\tfrom: \"main.Test\", to: \"Type\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype (\n\t// Type but not Testing.\n\tType struct{}\n)\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename type in gen decl plus doc\n\t\t{\n\t\t\tctxt: main(`package main\n\n// T is a test type.\ntype T struct{}\n`),\n\t\t\tfrom: \"main.T\", to: \"Type\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\n// Type is a test type.\ntype Type struct{}\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename value spec with doc\n\t\t{\n\t\t\tctxt: main(`package main\n\nconst (\n\t// C is the speed of light.\n\tC = 2.998e8\n)\n`),\n\t\t\tfrom: \"main.C\", to: \"Lightspeed\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nconst (\n\t// Lightspeed is the speed of light.\n\tLightspeed = 2.998e8\n)\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename value inside gen decl with doc\n\t\t{\n\t\t\tctxt: main(`package main\n\nvar out *string\n`),\n\t\t\tfrom: \"main.out\", to: \"discard\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nvar discard *string\n`,\n\t\t\t},\n\t\t},\n\t\t// Rename field plus doc\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype Struct struct {\n\t// Field is a struct field.\n\tField string\n}\n`),\n\t\t\tfrom: \"main.Struct.Field\", to: \"Foo\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype Struct struct {\n\t// Foo is a struct field.\n\tFoo string\n}\n`,\n\t\t\t},\n\t\t},\n\t\t// Label renamings.\n\t\t{\n\t\t\tctxt: main(`package main\nfunc f() {\nloop:\n\tloop := 0\n\tgo func() {\n\tloop:\n\t\tgoto loop\n\t}()\n\tloop++\n\tgoto loop\n}\n`),\n\t\t\toffset: \"/go/src/main/0.go:#25\", to: \"loop2\", // def of outer label \"loop\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc f() {\nloop2:\n\tloop := 0\n\tgo func() {\n\tloop:\n\t\tgoto loop\n\t}()\n\tloop++\n\tgoto loop2\n}\n`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\toffset: \"/go/src/main/0.go:#70\", to: \"loop2\", // ref to inner label \"loop\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc f() {\nloop:\n\tloop := 0\n\tgo func() {\n\tloop2:\n\t\tgoto loop2\n\t}()\n\tloop++\n\tgoto loop\n}\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of type used as embedded field.\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype T int\ntype U struct { T }\n\nvar _ = U{}.T\n`),\n\t\t\tfrom: \"main.T\", to: \"T2\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype T2 int\ntype U struct{ T2 }\n\nvar _ = U{}.T2\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of embedded field.\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype T int\ntype U struct { T }\n\nvar _ = U{}.T\n`),\n\t\t\toffset: \"/go/src/main/0.go:#58\", to: \"T2\", // T in \"U{}.T\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype T2 int\ntype U struct{ T2 }\n\nvar _ = U{}.T2\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of pointer embedded field.\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype T int\ntype U struct { *T }\n\nvar _ = U{}.T\n`),\n\t\t\toffset: \"/go/src/main/0.go:#59\", to: \"T2\", // T in \"U{}.T\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype T2 int\ntype U struct{ *T2 }\n\nvar _ = U{}.T2\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of embedded field alias.\n\t\t{\n\t\t\talias: true,\n\t\t\tctxt: main(`package main\n\ntype T int\ntype A = T\ntype U struct{ A }\n\nvar _ = U{}.A\nvar a A\n`),\n\t\t\toffset: \"/go/src/main/0.go:#68\", to: \"A2\", // A in \"U{}.A\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype T int\ntype A2 = T\ntype U struct{ A2 }\n\nvar _ = U{}.A2\nvar a A2\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of embedded field pointer to alias.\n\t\t{\n\t\t\talias: true,\n\t\t\tctxt: main(`package main\n\ntype T int\ntype A = T\ntype U struct{ *A }\n\nvar _ = U{}.A\nvar a A\n`),\n\t\t\toffset: \"/go/src/main/0.go:#69\", to: \"A2\", // A in \"U{}.A\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype T int\ntype A2 = T\ntype U struct{ *A2 }\n\nvar _ = U{}.A2\nvar a A2\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of alias\n\t\t{\n\t\t\tctxt: main(`package main\n\ntype A = int\n\nfunc _() A {\n\treturn A(0)\n}\n`),\n\t\t\toffset: \"/go/src/main/0.go:#49\", to: \"A2\", // A in \"A(0)\"\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype A2 = int\n\nfunc _() A2 {\n\treturn A2(0)\n}\n`,\n\t\t\t},\n\t\t},\n\n\t\t// Lexical scope tests.\n\t\t{\n\t\t\tctxt: main(`package main\n\nvar y int\n\nfunc f() {\n\tprint(y)\n\ty := \"\"\n\tprint(y)\n}\n`),\n\t\t\tfrom: \"main.y\", to: \"x\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nvar x int\n\nfunc f() {\n\tprint(x)\n\ty := \"\"\n\tprint(y)\n}\n`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tfrom: \"main.f::y\", to: \"x\",\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nvar y int\n\nfunc f() {\n\tprint(y)\n\tx := \"\"\n\tprint(x)\n}\n`,\n\t\t\t},\n\t\t},\n\t\t// Renaming of typeswitch vars (a corner case).\n\t\t{\n\t\t\tctxt: main(`package main\n\nfunc f(z interface{}) {\n\tswitch y := z.(type) {\n\tcase int:\n\t\tprint(y)\n\tdefault:\n\t\tprint(y)\n\t}\n}\n`),\n\t\t\toffset: \"/go/src/main/0.go:#46\", to: \"x\", // def of y\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc f(z interface{}) {\n\tswitch x := z.(type) {\n\tcase int:\n\t\tprint(x)\n\tdefault:\n\t\tprint(x)\n\t}\n}\n`},\n\t\t},\n\t\t{\n\t\t\toffset: \"/go/src/main/0.go:#81\", to: \"x\", // ref of y in case int\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc f(z interface{}) {\n\tswitch x := z.(type) {\n\tcase int:\n\t\tprint(x)\n\tdefault:\n\t\tprint(x)\n\t}\n}\n`},\n\t\t},\n\t\t{\n\t\t\toffset: \"/go/src/main/0.go:#102\", to: \"x\", // ref of y in default case\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc f(z interface{}) {\n\tswitch x := z.(type) {\n\tcase int:\n\t\tprint(x)\n\tdefault:\n\t\tprint(x)\n\t}\n}\n`},\n\t\t},\n\n\t\t// Renaming of embedded field that is a qualified reference.\n\t\t// (Regression test for bug 8924.)\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\ntype _ struct{ *foo.T }\n`},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#48\", to: \"U\", // the \"T\" in *foo.T\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/foo/0.go\": `package foo\n\ntype U int\n`,\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"foo\"\n\ntype _ struct{ *foo.U }\n`,\n\t\t\t},\n\t\t},\n\n\t\t// Renaming of embedded field that is a qualified reference with the '-from' flag.\n\t\t// (Regression test for bug 12038.)\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\ntype V struct{ *foo.T }\n`},\n\t\t\t}),\n\t\t\tfrom: \"(main.V).T\", to: \"U\", // the \"T\" in *foo.T\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/foo/0.go\": `package foo\n\ntype U int\n`,\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"foo\"\n\ntype V struct{ *foo.U }\n`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"foo\": {`package foo; type T int`},\n\t\t\t\t\"main\": {`package main\n\nimport \"foo\"\n\ntype V struct{ foo.T }\n`},\n\t\t\t}),\n\t\t\tfrom: \"(main.V).T\", to: \"U\", // the \"T\" in *foo.T\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/foo/0.go\": `package foo\n\ntype U int\n`,\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nimport \"foo\"\n\ntype V struct{ foo.U }\n`,\n\t\t\t},\n\t\t},\n\n\t\t// Interface method renaming.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`\npackage main\ntype I interface {\n\tf()\n}\ntype J interface { f(); g() }\ntype A int\nfunc (A) f()\ntype B int\nfunc (B) f()\nfunc (B) g()\ntype C int\nfunc (C) f()\nfunc (C) g()\nvar _, _ I = A(0), B(0)\nvar _, _ J = B(0), C(0)\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#34\", to: \"F\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tF()\n}\ntype J interface {\n\tF()\n\tg()\n}\ntype A int\n\nfunc (A) F()\n\ntype B int\n\nfunc (B) F()\nfunc (B) g()\n\ntype C int\n\nfunc (C) F()\nfunc (C) g()\n\nvar _, _ I = A(0), B(0)\nvar _, _ J = B(0), C(0)\n`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\toffset: \"/go/src/main/0.go:#59\", to: \"F\", // abstract method J.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tF()\n}\ntype J interface {\n\tF()\n\tg()\n}\ntype A int\n\nfunc (A) F()\n\ntype B int\n\nfunc (B) F()\nfunc (B) g()\n\ntype C int\n\nfunc (C) F()\nfunc (C) g()\n\nvar _, _ I = A(0), B(0)\nvar _, _ J = B(0), C(0)\n`,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\toffset: \"/go/src/main/0.go:#64\", to: \"G\", // abstract method J.g\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tf()\n}\ntype J interface {\n\tf()\n\tG()\n}\ntype A int\n\nfunc (A) f()\n\ntype B int\n\nfunc (B) f()\nfunc (B) G()\n\ntype C int\n\nfunc (C) f()\nfunc (C) G()\n\nvar _, _ I = A(0), B(0)\nvar _, _ J = B(0), C(0)\n`,\n\t\t\t},\n\t\t},\n\t\t// Indirect coupling of I.f to C.f from D->I assignment and anonymous field of D.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`\npackage main\ntype I interface {\n\tf()\n}\ntype C int\nfunc (C) f()\ntype D struct{C}\nvar _ I = D{}\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#34\", to: \"F\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tF()\n}\ntype C int\n\nfunc (C) F()\n\ntype D struct{ C }\n\nvar _ I = D{}\n`,\n\t\t\t},\n\t\t},\n\t\t// Interface embedded in struct.  No conflict if C need not satisfy I.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`\npackage main\ntype I interface {\n\tf()\n}\ntype C struct{I}\nfunc (C) g() int\nvar _ int = C{}.g()\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#34\", to: \"g\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tg()\n}\ntype C struct{ I }\n\nfunc (C) g() int\n\nvar _ int = C{}.g()\n`,\n\t\t\t},\n\t\t},\n\t\t// A type assertion causes method coupling iff signatures match.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`package main\ntype I interface{\n\tf()\n}\ntype J interface{\n\tf()\n}\nvar _ = I(nil).(J)\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#32\", to: \"g\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tg()\n}\ntype J interface {\n\tg()\n}\n\nvar _ = I(nil).(J)\n`,\n\t\t\t},\n\t\t},\n\t\t// Impossible type assertion: no method coupling.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`package main\ntype I interface{\n\tf()\n}\ntype J interface{\n\tf()int\n}\nvar _ = I(nil).(J)\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#32\", to: \"g\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tg()\n}\ntype J interface {\n\tf() int\n}\n\nvar _ = I(nil).(J)\n`,\n\t\t\t},\n\t\t},\n\t\t// Impossible type assertion: no method coupling C.f<->J.f.\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`package main\ntype I interface{\n\tf()\n}\ntype C int\nfunc (C) f()\ntype J interface{\n\tf()int\n}\nvar _ = I(C(0)).(J)\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#32\", to: \"g\", // abstract method I.f\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\ntype I interface {\n\tg()\n}\ntype C int\n\nfunc (C) g()\n\ntype J interface {\n\tf() int\n}\n\nvar _ = I(C(0)).(J)\n`,\n\t\t\t},\n\t\t},\n\t\t// Progress after \"soft\" type errors (Go issue 14596).\n\t\t{\n\t\t\tctxt: fakeContext(map[string][]string{\n\t\t\t\t\"main\": {`package main\n\nfunc main() {\n\tvar unused, x int\n\tprint(x)\n}\n`,\n\t\t\t\t},\n\t\t\t}),\n\t\t\toffset: \"/go/src/main/0.go:#54\", to: \"y\", // var x\n\t\t\twant: map[string]string{\n\t\t\t\t\"/go/src/main/0.go\": `package main\n\nfunc main() {\n\tvar unused, y int\n\tprint(y)\n}\n`,\n\t\t\t},\n\t\t},\n\t} {\n\t\tif test.ctxt != nil {\n\t\t\tctxt = test.ctxt\n\t\t}\n\n\t\tgot := make(map[string]string)\n\t\twriteFile = func(filename string, content []byte) error {\n\t\t\tgot[filepath.ToSlash(filename)] = string(content)\n\t\t\treturn nil\n\t\t}\n\n\t\terr := Main(ctxt, test.offset, test.from, test.to)\n\t\tvar prefix string\n\t\tif test.offset == \"\" {\n\t\t\tprefix = fmt.Sprintf(\"-from %q -to %q\", test.from, test.to)\n\t\t} else {\n\t\t\tprefix = fmt.Sprintf(\"-offset %q -to %q\", test.offset, test.to)\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Errorf(\"%s: unexpected error: %s\", prefix, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tfor file, wantContent := range test.want {\n\t\t\tgotContent, ok := got[file]\n\t\t\tdelete(got, file)\n\t\t\tif !ok {\n\t\t\t\tt.Errorf(\"%s: file %s not rewritten\", prefix, file)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif gotContent != wantContent {\n\t\t\t\tt.Errorf(\"%s: rewritten file %s does not match expectation; got <<<%s>>>\\n\"+\n\t\t\t\t\t\"want <<<%s>>>\", prefix, file, gotContent, wantContent)\n\t\t\t}\n\t\t}\n\t\t// got should now be empty\n\t\tfor file := range got {\n\t\t\tt.Errorf(\"%s: unexpected rewrite of file %s\", prefix, file)\n\t\t}\n\t}\n}\n\nfunc TestDiff(t *testing.T) {\n\tswitch runtime.GOOS {\n\tcase \"windows\":\n\t\tif os.Getenv(\"GO_BUILDER_NAME\") != \"\" {\n\t\t\tif _, err := exec.LookPath(DiffCmd); err != nil {\n\t\t\t\tt.Skipf(\"diff tool non-existent for %s on builders\", runtime.GOOS)\n\t\t\t}\n\t\t}\n\tcase \"plan9\":\n\t\tt.Skipf(\"plan9 diff tool doesn't support -u flag\")\n\t}\n\ttestenv.NeedsTool(t, DiffCmd)\n\ttestenv.NeedsTool(t, \"go\") // to locate the package to be renamed\n\n\tdefer func() {\n\t\tDiff = false\n\t\tstdout = os.Stdout\n\t}()\n\tDiff = true\n\tstdout = new(bytes.Buffer)\n\n\t// Set up a fake GOPATH in a temporary directory,\n\t// and ensure we're in GOPATH mode.\n\ttmpdir, err := os.MkdirTemp(\"\", \"TestDiff\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(tmpdir)\n\tbuildCtx := build.Default\n\tbuildCtx.GOPATH = tmpdir\n\n\tpkgDir := filepath.Join(tmpdir, \"src\", \"example.com\", \"rename\")\n\tif err := os.MkdirAll(pkgDir, 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tprevWD, err := os.Getwd()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.Chdir(prevWD)\n\n\tif err := os.Chdir(pkgDir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconst modFile = `module example.com/rename\n\ngo 1.15\n`\n\tif err := os.WriteFile(filepath.Join(pkgDir, \"go.mod\"), []byte(modFile), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconst goFile = `package rename\n\nfunc justHereForTestingDiff() {\n\tjustHereForTestingDiff()\n}\n`\n\tif err := os.WriteFile(filepath.Join(pkgDir, \"rename_test.go\"), []byte(goFile), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif err := Main(&buildCtx, \"\", `\"example.com/rename\".justHereForTestingDiff`, \"Foo\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// NB: there are tabs in the string literal!\n\tif !strings.Contains(stdout.(fmt.Stringer).String(), `\n-func justHereForTestingDiff() {\n-\tjustHereForTestingDiff()\n+func Foo() {\n+\tFoo()\n }\n`) {\n\t\tt.Errorf(\"unexpected diff:\\n<<%s>>\", stdout)\n\t}\n}\n\n// ---------------------------------------------------------------------\n\n// Simplifying wrapper around buildutil.FakeContext for packages whose\n// filenames are sequentially numbered (%d.go).  pkgs maps a package\n// import path to its list of file contents.\nfunc fakeContext(pkgs map[string][]string) *build.Context {\n\tpkgs2 := make(map[string]map[string]string)\n\tfor path, files := range pkgs {\n\t\tfilemap := make(map[string]string)\n\t\tfor i, contents := range files {\n\t\t\tfilemap[fmt.Sprintf(\"%d.go\", i)] = contents\n\t\t}\n\t\tpkgs2[path] = filemap\n\t}\n\treturn buildutil.FakeContext(pkgs2)\n}\n\n// helper for single-file main packages with no imports.\nfunc main(content string) *build.Context {\n\treturn fakeContext(map[string][]string{\"main\": {content}})\n}\n"
  },
  {
    "path": "refactor/rename/spec.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rename\n\n// This file contains logic related to specifying a renaming: parsing of\n// the flags as a form of query, and finding the object(s) it denotes.\n// See Usage for flag details.\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/build\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"golang.org/x/tools/go/loader\"\n\t\"golang.org/x/tools/internal/typesinternal\"\n)\n\n// A spec specifies an entity to rename.\n//\n// It is populated from an -offset flag or -from query;\n// see Usage for the allowed -from query forms.\ntype spec struct {\n\t// pkg is the package containing the position\n\t// specified by the -from or -offset flag.\n\t// If filename == \"\", our search for the 'from' entity\n\t// is restricted to this package.\n\tpkg string\n\n\t// The original name of the entity being renamed.\n\t// If the query had a ::from component, this is that;\n\t// otherwise it's the last segment, e.g.\n\t//   (encoding/json.Decoder).from\n\t//   encoding/json.from\n\tfromName string\n\n\t// -- The remaining fields are private to this file.  All are optional. --\n\n\t// The query's ::x suffix, if any.\n\tsearchFor string\n\n\t// e.g. \"Decoder\" in \"(encoding/json.Decoder).fieldOrMethod\"\n\t//                or \"encoding/json.Decoder\n\tpkgMember string\n\n\t// e.g. fieldOrMethod in \"(encoding/json.Decoder).fieldOrMethod\"\n\ttypeMember string\n\n\t// Restricts the query to this file.\n\t// Implied by -from=\"file.go::x\" and -offset flags.\n\tfilename string\n\n\t// Byte offset of the 'from' identifier within the file named 'filename'.\n\t// -offset mode only.\n\toffset int\n}\n\n// parseFromFlag interprets the \"-from\" flag value as a renaming specification.\n// See Usage in rename.go for valid formats.\nfunc parseFromFlag(ctxt *build.Context, fromFlag string) (*spec, error) {\n\tvar spec spec\n\tvar main string // sans \"::x\" suffix\n\tswitch parts := strings.Split(fromFlag, \"::\"); len(parts) {\n\tcase 1:\n\t\tmain = parts[0]\n\tcase 2:\n\t\tmain = parts[0]\n\t\tspec.searchFor = parts[1]\n\t\tif parts[1] == \"\" {\n\t\t\t// error\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"-from %q: invalid identifier specification (see -help for formats)\", fromFlag)\n\t}\n\n\tif strings.HasSuffix(main, \".go\") {\n\t\t// main is \"filename.go\"\n\t\tif spec.searchFor == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"-from: filename %q must have a ::name suffix\", main)\n\t\t}\n\t\tspec.filename = main\n\t\tif !buildutil.FileExists(ctxt, spec.filename) {\n\t\t\treturn nil, fmt.Errorf(\"no such file: %s\", spec.filename)\n\t\t}\n\n\t\tbp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tspec.pkg = bp.ImportPath\n\n\t} else {\n\t\t// main is one of:\n\t\t//  \"importpath\"\n\t\t//  \"importpath\".member\n\t\t//  (*\"importpath\".type).fieldormethod           (parens and star optional)\n\t\tif err := parseObjectSpec(&spec, main); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif spec.searchFor != \"\" {\n\t\tspec.fromName = spec.searchFor\n\t}\n\n\tcwd, err := os.Getwd()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Sanitize the package.\n\tbp, err := ctxt.Import(spec.pkg, cwd, build.FindOnly)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"can't find package %q\", spec.pkg)\n\t}\n\tspec.pkg = bp.ImportPath\n\n\tif !isValidIdentifier(spec.fromName) {\n\t\treturn nil, fmt.Errorf(\"-from: invalid identifier %q\", spec.fromName)\n\t}\n\n\tif Verbose {\n\t\tlog.Printf(\"-from spec: %+v\", spec)\n\t}\n\n\treturn &spec, nil\n}\n\n// parseObjectSpec parses main as one of the non-filename forms of\n// object specification.\nfunc parseObjectSpec(spec *spec, main string) error {\n\t// Parse main as a Go expression, albeit a strange one.\n\te, _ := parser.ParseExpr(main)\n\n\tif pkg := parseImportPath(e); pkg != \"\" {\n\t\t// e.g. bytes or \"encoding/json\": a package\n\t\tspec.pkg = pkg\n\t\tif spec.searchFor == \"\" {\n\t\t\treturn fmt.Errorf(\"-from %q: package import path %q must have a ::name suffix\",\n\t\t\t\tmain, main)\n\t\t}\n\t\treturn nil\n\t}\n\n\tif e, ok := e.(*ast.SelectorExpr); ok {\n\t\tx := ast.Unparen(e.X)\n\n\t\t// Strip off star constructor, if any.\n\t\tif star, ok := x.(*ast.StarExpr); ok {\n\t\t\tx = star.X\n\t\t}\n\n\t\tif pkg := parseImportPath(x); pkg != \"\" {\n\t\t\t// package member e.g. \"encoding/json\".HTMLEscape\n\t\t\tspec.pkg = pkg              // e.g. \"encoding/json\"\n\t\t\tspec.pkgMember = e.Sel.Name // e.g. \"HTMLEscape\"\n\t\t\tspec.fromName = e.Sel.Name\n\t\t\treturn nil\n\t\t}\n\n\t\tif x, ok := x.(*ast.SelectorExpr); ok {\n\t\t\t// field/method of type e.g. (\"encoding/json\".Decoder).Decode\n\t\t\ty := ast.Unparen(x.X)\n\t\t\tif pkg := parseImportPath(y); pkg != \"\" {\n\t\t\t\tspec.pkg = pkg               // e.g. \"encoding/json\"\n\t\t\t\tspec.pkgMember = x.Sel.Name  // e.g. \"Decoder\"\n\t\t\t\tspec.typeMember = e.Sel.Name // e.g. \"Decode\"\n\t\t\t\tspec.fromName = e.Sel.Name\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fmt.Errorf(\"-from %q: invalid expression\", main)\n}\n\n// parseImportPath returns the import path of the package denoted by e.\n// Any import path may be represented as a string literal;\n// single-segment import paths (e.g. \"bytes\") may also be represented as\n// ast.Ident.  parseImportPath returns \"\" for all other expressions.\nfunc parseImportPath(e ast.Expr) string {\n\tswitch e := e.(type) {\n\tcase *ast.Ident:\n\t\treturn e.Name // e.g. bytes\n\n\tcase *ast.BasicLit:\n\t\tif e.Kind == token.STRING {\n\t\t\tpkgname, _ := strconv.Unquote(e.Value)\n\t\t\treturn pkgname // e.g. \"encoding/json\"\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// parseOffsetFlag interprets the \"-offset\" flag value as a renaming specification.\nfunc parseOffsetFlag(ctxt *build.Context, offsetFlag string) (*spec, error) {\n\tvar spec spec\n\t// Validate -offset, e.g. file.go:#123\n\tparts := strings.Split(offsetFlag, \":#\")\n\tif len(parts) != 2 {\n\t\treturn nil, fmt.Errorf(\"-offset %q: invalid offset specification\", offsetFlag)\n\t}\n\n\tspec.filename = parts[0]\n\tif !buildutil.FileExists(ctxt, spec.filename) {\n\t\treturn nil, fmt.Errorf(\"no such file: %s\", spec.filename)\n\t}\n\n\tbp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tspec.pkg = bp.ImportPath\n\n\tfor _, r := range parts[1] {\n\t\tif !isDigit(r) {\n\t\t\treturn nil, fmt.Errorf(\"-offset %q: non-numeric offset\", offsetFlag)\n\t\t}\n\t}\n\tspec.offset, err = strconv.Atoi(parts[1])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"-offset %q: non-numeric offset\", offsetFlag)\n\t}\n\n\t// Parse the file and check there's an identifier at that offset.\n\tfset := token.NewFileSet()\n\tf, err := buildutil.ParseFile(fset, ctxt, nil, wd, spec.filename, parser.ParseComments)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"-offset %q: cannot parse file: %s\", offsetFlag, err)\n\t}\n\n\tid := identAtOffset(fset, f, spec.offset)\n\tif id == nil {\n\t\treturn nil, fmt.Errorf(\"-offset %q: no identifier at this position\", offsetFlag)\n\t}\n\n\tspec.fromName = id.Name\n\n\treturn &spec, nil\n}\n\nvar wd = func() string {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\tpanic(\"cannot get working directory: \" + err.Error())\n\t}\n\treturn wd\n}()\n\n// For source trees built with 'go build', the -from or -offset\n// spec identifies exactly one initial 'from' object to rename,\n// but certain proprietary build systems allow a single file to\n// appear in multiple packages (e.g. the test package contains a\n// copy of its library), so there may be multiple objects for\n// the same source entity.\n\nfunc findFromObjects(iprog *loader.Program, spec *spec) ([]types.Object, error) {\n\tif spec.filename != \"\" {\n\t\treturn findFromObjectsInFile(iprog, spec)\n\t}\n\n\t// Search for objects defined in specified package.\n\n\t// TODO(adonovan): the iprog.ImportMap has an entry {\"main\": ...}\n\t// for main packages, even though that's not an import path.\n\t// Seems like a bug.\n\t//\n\t// pkg := iprog.ImportMap[spec.pkg]\n\t// if pkg == nil {\n\t// \treturn fmt.Errorf(\"cannot find package %s\", spec.pkg) // can't happen?\n\t// }\n\t// info := iprog.AllPackages[pkg]\n\n\t// Workaround: lookup by value.\n\tvar info *loader.PackageInfo\n\tvar pkg *types.Package\n\tfor pkg, info = range iprog.AllPackages {\n\t\tif pkg.Path() == spec.pkg {\n\t\t\tbreak\n\t\t}\n\t}\n\tif info == nil {\n\t\treturn nil, fmt.Errorf(\"package %q was not loaded\", spec.pkg)\n\t}\n\n\tobjects, err := findObjects(info, spec)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(objects) > 1 {\n\t\t// ambiguous \"*\" scope query\n\t\treturn nil, ambiguityError(iprog.Fset, objects)\n\t}\n\treturn objects, nil\n}\n\nfunc findFromObjectsInFile(iprog *loader.Program, spec *spec) ([]types.Object, error) {\n\tvar fromObjects []types.Object\n\tfor _, info := range iprog.AllPackages {\n\t\t// restrict to specified filename\n\t\t// NB: under certain proprietary build systems, a given\n\t\t// filename may appear in multiple packages.\n\t\tfor _, f := range info.Files {\n\t\t\tthisFile := iprog.Fset.File(f.FileStart)\n\t\t\tif !sameFile(thisFile.Name(), spec.filename) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// This package contains the query file.\n\n\t\t\tif spec.offset != 0 {\n\t\t\t\t// We cannot refactor generated files since position information is invalidated.\n\t\t\t\tif ast.IsGenerated(f) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"cannot rename identifiers in generated file containing DO NOT EDIT marker: %s\", thisFile.Name())\n\t\t\t\t}\n\n\t\t\t\t// Search for a specific ident by file/offset.\n\t\t\t\tid := identAtOffset(iprog.Fset, f, spec.offset)\n\t\t\t\tif id == nil {\n\t\t\t\t\t// can't happen?\n\t\t\t\t\treturn nil, fmt.Errorf(\"identifier not found\")\n\t\t\t\t}\n\t\t\t\tobj := info.Uses[id]\n\t\t\t\tif obj == nil {\n\t\t\t\t\tobj = info.Defs[id]\n\t\t\t\t\tif obj == nil {\n\t\t\t\t\t\t// Ident without Object.\n\n\t\t\t\t\t\t// Package clause?\n\t\t\t\t\t\tpos := thisFile.Pos(spec.offset)\n\t\t\t\t\t\t_, path, _ := iprog.PathEnclosingInterval(pos, pos)\n\t\t\t\t\t\tif len(path) == 2 { // [Ident File]\n\t\t\t\t\t\t\t// TODO(adonovan): support this case.\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"cannot rename %q: renaming package clauses is not yet supported\",\n\t\t\t\t\t\t\t\tpath[1].(*ast.File).Name.Name)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Implicit y in \"switch y := x.(type) {\"?\n\t\t\t\t\t\tif obj := typeSwitchVar(&info.Info, path); obj != nil {\n\t\t\t\t\t\t\treturn []types.Object{obj}, nil\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Probably a type error.\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"cannot find object for %q\", id.Name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif obj.Pkg() == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"cannot rename predeclared identifiers (%s)\", obj)\n\n\t\t\t\t}\n\n\t\t\t\tfromObjects = append(fromObjects, obj)\n\t\t\t} else {\n\t\t\t\t// do a package-wide query\n\t\t\t\tobjects, err := findObjects(info, spec)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\t// filter results: only objects defined in thisFile\n\t\t\t\tvar filtered []types.Object\n\t\t\t\tfor _, obj := range objects {\n\t\t\t\t\tif iprog.Fset.File(obj.Pos()) == thisFile {\n\t\t\t\t\t\tfiltered = append(filtered, obj)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(filtered) == 0 {\n\t\t\t\t\treturn nil, fmt.Errorf(\"no object %q declared in file %s\",\n\t\t\t\t\t\tspec.fromName, spec.filename)\n\t\t\t\t} else if len(filtered) > 1 {\n\t\t\t\t\treturn nil, ambiguityError(iprog.Fset, filtered)\n\t\t\t\t}\n\t\t\t\tfromObjects = append(fromObjects, filtered[0])\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\tif len(fromObjects) == 0 {\n\t\t// can't happen?\n\t\treturn nil, fmt.Errorf(\"file %s was not part of the loaded program\", spec.filename)\n\t}\n\treturn fromObjects, nil\n}\n\nfunc typeSwitchVar(info *types.Info, path []ast.Node) types.Object {\n\tif len(path) > 3 {\n\t\t// [Ident AssignStmt TypeSwitchStmt...]\n\t\tif sw, ok := path[2].(*ast.TypeSwitchStmt); ok {\n\t\t\t// choose the first case.\n\t\t\tif len(sw.Body.List) > 0 {\n\t\t\t\tobj := info.Implicits[sw.Body.List[0].(*ast.CaseClause)]\n\t\t\t\tif obj != nil {\n\t\t\t\t\treturn obj\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// On success, findObjects returns the list of objects named\n// spec.fromName matching the spec.  On success, the result has exactly\n// one element unless spec.searchFor!=\"\", in which case it has at least one\n// element.\nfunc findObjects(info *loader.PackageInfo, spec *spec) ([]types.Object, error) {\n\tif spec.pkgMember == \"\" {\n\t\tif spec.searchFor == \"\" {\n\t\t\tpanic(spec)\n\t\t}\n\t\tobjects := searchDefs(&info.Info, spec.searchFor)\n\t\tif objects == nil {\n\t\t\treturn nil, fmt.Errorf(\"no object %q declared in package %q\",\n\t\t\t\tspec.searchFor, info.Pkg.Path())\n\t\t}\n\t\treturn objects, nil\n\t}\n\n\tpkgMember := info.Pkg.Scope().Lookup(spec.pkgMember)\n\tif pkgMember == nil {\n\t\treturn nil, fmt.Errorf(\"package %q has no member %q\",\n\t\t\tinfo.Pkg.Path(), spec.pkgMember)\n\t}\n\n\tvar searchFunc *types.Func\n\tif spec.typeMember == \"\" {\n\t\t// package member\n\t\tif spec.searchFor == \"\" {\n\t\t\treturn []types.Object{pkgMember}, nil\n\t\t}\n\n\t\t// Search within pkgMember, which must be a function.\n\t\tsearchFunc, _ = pkgMember.(*types.Func)\n\t\tif searchFunc == nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot search for %q within %s %q\",\n\t\t\t\tspec.searchFor, objectKind(pkgMember), pkgMember)\n\t\t}\n\t} else {\n\t\t// field/method of type\n\t\t// e.g. (encoding/json.Decoder).Decode\n\t\t// or ::x within it.\n\n\t\ttName, _ := pkgMember.(*types.TypeName)\n\t\tif tName == nil {\n\t\t\treturn nil, fmt.Errorf(\"%s.%s is a %s, not a type\",\n\t\t\t\tinfo.Pkg.Path(), pkgMember.Name(), objectKind(pkgMember))\n\t\t}\n\n\t\t// search within named type.\n\t\tobj, _, _ := types.LookupFieldOrMethod(tName.Type(), true, info.Pkg, spec.typeMember)\n\t\tif obj == nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot find field or method %q of %s.%s\",\n\t\t\t\tspec.typeMember, info.Pkg.Path(), tName.Name())\n\t\t}\n\n\t\tif spec.searchFor == \"\" {\n\t\t\t// If it is an embedded field (*Named or *Alias),\n\t\t\t// return the type of the field.\n\t\t\tif v, ok := obj.(*types.Var); ok && v.Anonymous() {\n\t\t\t\tif t, ok := typesinternal.Unpointer(v.Type()).(hasTypeName); ok {\n\t\t\t\t\treturn []types.Object{t.Obj()}, nil\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn []types.Object{obj}, nil\n\t\t}\n\n\t\tsearchFunc, _ = obj.(*types.Func)\n\t\tif searchFunc == nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot search for local name %q within %s (%s.%s).%s; need a function\",\n\t\t\t\tspec.searchFor, objectKind(obj), info.Pkg.Path(), tName.Name(),\n\t\t\t\tobj.Name())\n\t\t}\n\t\tif types.IsInterface(tName.Type()) {\n\t\t\treturn nil, fmt.Errorf(\"cannot search for local name %q within abstract method (%s.%s).%s\",\n\t\t\t\tspec.searchFor, info.Pkg.Path(), tName.Name(), searchFunc.Name())\n\t\t}\n\t}\n\n\t// -- search within function or method --\n\n\tdecl := funcDecl(info, searchFunc)\n\tif decl == nil {\n\t\treturn nil, fmt.Errorf(\"cannot find syntax for %s\", searchFunc) // can't happen?\n\t}\n\n\tvar objects []types.Object\n\tfor _, obj := range searchDefs(&info.Info, spec.searchFor) {\n\t\t// We use positions, not scopes, to determine whether\n\t\t// the obj is within searchFunc.  This is clumsy, but the\n\t\t// alternative, using the types.Scope tree, doesn't\n\t\t// account for non-lexical objects like fields and\n\t\t// interface methods.\n\t\tif decl.Pos() <= obj.Pos() && obj.Pos() < decl.End() && obj != searchFunc {\n\t\t\tobjects = append(objects, obj)\n\t\t}\n\t}\n\tif objects == nil {\n\t\treturn nil, fmt.Errorf(\"no local definition of %q within %s\",\n\t\t\tspec.searchFor, searchFunc)\n\t}\n\treturn objects, nil\n}\n\nfunc funcDecl(info *loader.PackageInfo, fn *types.Func) *ast.FuncDecl {\n\tfor _, f := range info.Files {\n\t\tfor _, d := range f.Decls {\n\t\t\tif d, ok := d.(*ast.FuncDecl); ok && info.Defs[d.Name] == fn {\n\t\t\t\treturn d\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc searchDefs(info *types.Info, name string) []types.Object {\n\tvar objects []types.Object\n\tfor id, obj := range info.Defs {\n\t\tif obj == nil {\n\t\t\t// e.g. blank ident.\n\t\t\t// TODO(adonovan): but also implicit y in\n\t\t\t//    switch y := x.(type)\n\t\t\t// Needs some thought.\n\t\t\tcontinue\n\t\t}\n\t\tif id.Name == name {\n\t\t\tobjects = append(objects, obj)\n\t\t}\n\t}\n\treturn objects\n}\n\nfunc identAtOffset(fset *token.FileSet, f *ast.File, offset int) *ast.Ident {\n\tvar found *ast.Ident\n\tast.Inspect(f, func(n ast.Node) bool {\n\t\tif id, ok := n.(*ast.Ident); ok {\n\t\t\tidpos := fset.Position(id.Pos()).Offset\n\t\t\tif idpos <= offset && offset < idpos+len(id.Name) {\n\t\t\t\tfound = id\n\t\t\t}\n\t\t}\n\t\treturn found == nil // keep traversing only until found\n\t})\n\treturn found\n}\n\n// ambiguityError returns an error describing an ambiguous \"*\" scope query.\nfunc ambiguityError(fset *token.FileSet, objects []types.Object) error {\n\tvar buf bytes.Buffer\n\tfor i, obj := range objects {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tposn := fset.Position(obj.Pos())\n\t\tfmt.Fprintf(&buf, \"%s at %s:%d:%d\",\n\t\t\tobjectKind(obj), filepath.Base(posn.Filename), posn.Line, posn.Column)\n\t}\n\treturn fmt.Errorf(\"ambiguous specifier %s matches %s\",\n\t\tobjects[0].Name(), buf.String())\n}\n"
  },
  {
    "path": "refactor/rename/util.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rename\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\t\"unicode\"\n)\n\nfunc objectKind(obj types.Object) string {\n\tswitch obj := obj.(type) {\n\tcase *types.PkgName:\n\t\treturn \"imported package name\"\n\tcase *types.TypeName: // defined type | alias | type parameter\n\t\treturn \"type\"\n\tcase *types.Var:\n\t\tif obj.IsField() {\n\t\t\treturn \"field\"\n\t\t}\n\tcase *types.Func:\n\t\tif obj.Signature().Recv() != nil {\n\t\t\treturn \"method\"\n\t\t}\n\t}\n\t// label, func, var, const\n\treturn strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), \"*types.\"))\n}\n\n// NB: for renamings, blank is not considered valid.\nfunc isValidIdentifier(id string) bool {\n\tif id == \"\" || id == \"_\" {\n\t\treturn false\n\t}\n\tfor i, r := range id {\n\t\tif !isLetter(r) && (i == 0 || !isDigit(r)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn token.Lookup(id) == token.IDENT\n}\n\n// isLocal reports whether obj is local to some function.\n// Precondition: not a struct field or interface method.\nfunc isLocal(obj types.Object) bool {\n\t// [... 5=stmt 4=func 3=file 2=pkg 1=universe]\n\tvar depth int\n\tfor scope := obj.Parent(); scope != nil; scope = scope.Parent() {\n\t\tdepth++\n\t}\n\treturn depth >= 4\n}\n\n// -- Plundered from go/scanner: ---------------------------------------\n\nfunc isLetter(ch rune) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)\n}\n\nfunc isDigit(ch rune) bool {\n\treturn '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)\n}\n\n// -- Plundered from golang.org/x/tools/cmd/guru -----------------\n\n// sameFile returns true if x and y have the same basename and denote\n// the same file.\nfunc sameFile(x, y string) bool {\n\tif runtime.GOOS == \"windows\" {\n\t\tx = filepath.ToSlash(x)\n\t\ty = filepath.ToSlash(y)\n\t}\n\tif x == y {\n\t\treturn true\n\t}\n\tif filepath.Base(x) == filepath.Base(y) { // (optimisation)\n\t\tif xi, err := os.Stat(x); err == nil {\n\t\t\tif yi, err := os.Stat(y); err == nil {\n\t\t\t\treturn os.SameFile(xi, yi)\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nfunc is[T any](x any) bool {\n\t_, ok := x.(T)\n\treturn ok\n}\n"
  },
  {
    "path": "refactor/satisfy/find.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package satisfy inspects the type-checked ASTs of Go packages and\n// reports the set of discovered type constraints of the form (lhs, rhs\n// Type) where lhs is a non-trivial interface, rhs satisfies this\n// interface, and this fact is necessary for the package to be\n// well-typed.\n//\n// It requires well-typed inputs.\npackage satisfy // import \"golang.org/x/tools/refactor/satisfy\"\n\n// NOTES:\n//\n// We don't care about numeric conversions, so we don't descend into\n// types or constant expressions.  This is unsound because\n// constant expressions can contain arbitrary statements, e.g.\n//   const x = len([1]func(){func() {\n//     ...\n//   }})\n//\n// Assignability conversions are possible in the following places:\n// - in assignments y = x, y := x, var y = x.\n// - from call argument types to formal parameter types\n// - in append and delete calls\n// - from return operands to result parameter types\n// - in composite literal T{k:v}, from k and v to T's field/element/key type\n// - in map[key] from key to the map's key type\n// - in comparisons x==y and switch x { case y: }.\n// - in explicit conversions T(x)\n// - in sends ch <- x, from x to the channel element type\n// - in type assertions x.(T) and switch x.(type) { case T: }\n//\n// The results of this pass provide information equivalent to the\n// ssa.MakeInterface and ssa.ChangeInterface instructions.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"golang.org/x/tools/internal/typeparams\"\n)\n\n// A Constraint records the fact that the RHS type does and must\n// satisfy the LHS type, which is an interface.\n// The names are suggestive of an assignment statement LHS = RHS.\n//\n// The constraint is implicitly universally quantified over any type\n// parameters appearing within the two types.\ntype Constraint struct {\n\tLHS, RHS types.Type\n}\n\n// A Finder inspects the type-checked ASTs of Go packages and\n// accumulates the set of type constraints (x, y) such that x is\n// assignable to y, y is an interface, and both x and y have methods.\n//\n// In other words, it returns the subset of the \"implements\" relation\n// that is checked during compilation of a package.  Refactoring tools\n// will need to preserve at least this part of the relation to ensure\n// continued compilation.\ntype Finder struct {\n\tResult    map[Constraint]bool\n\tmsetcache typeutil.MethodSetCache\n\n\t// per-Find state\n\tinfo *types.Info\n\tsig  *types.Signature\n}\n\n// Find inspects a single package, populating Result with its pairs of\n// constrained types.\n//\n// The result is non-canonical and thus may contain duplicates (but this\n// tends to preserves names of interface types better).\n//\n// The package must be free of type errors, and\n// info.{Defs,Uses,Selections,Types} must have been populated by the\n// type-checker.\nfunc (f *Finder) Find(info *types.Info, files []*ast.File) {\n\tif info.Defs == nil || info.Uses == nil || info.Selections == nil || info.Types == nil {\n\t\tpanic(\"Finder.Find: one of info.{Defs,Uses,Selections.Types} is not populated\")\n\t}\n\tif f.Result == nil {\n\t\tf.Result = make(map[Constraint]bool)\n\t}\n\n\tf.info = info\n\tfor _, file := range files {\n\t\tfor _, d := range file.Decls {\n\t\t\tswitch d := d.(type) {\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tif d.Tok == token.VAR { // ignore consts\n\t\t\t\t\tfor _, spec := range d.Specs {\n\t\t\t\t\t\tf.valueSpec(spec.(*ast.ValueSpec))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase *ast.FuncDecl:\n\t\t\t\tif d.Body != nil {\n\t\t\t\t\tf.sig = f.info.Defs[d.Name].Type().(*types.Signature)\n\t\t\t\t\tf.stmt(d.Body)\n\t\t\t\t\tf.sig = nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tf.info = nil\n}\n\nvar (\n\ttInvalid     = types.Typ[types.Invalid]\n\ttUntypedBool = types.Typ[types.UntypedBool]\n\ttUntypedNil  = types.Typ[types.UntypedNil]\n)\n\n// exprN visits an expression in a multi-value context.\nfunc (f *Finder) exprN(e ast.Expr) types.Type {\n\ttyp := f.info.Types[e].Type.(*types.Tuple)\n\tswitch e := e.(type) {\n\tcase *ast.ParenExpr:\n\t\treturn f.exprN(e.X)\n\n\tcase *ast.CallExpr:\n\t\t// x, err := f(args)\n\t\tsig := typeparams.CoreType(f.expr(e.Fun)).(*types.Signature)\n\t\tf.call(sig, e.Args)\n\n\tcase *ast.IndexExpr:\n\t\t// y, ok := x[i]\n\t\tx := f.expr(e.X)\n\t\tf.assign(f.expr(e.Index), typeparams.CoreType(x).(*types.Map).Key())\n\n\tcase *ast.TypeAssertExpr:\n\t\t// y, ok := x.(T)\n\t\tf.typeAssert(f.expr(e.X), typ.At(0).Type())\n\n\tcase *ast.UnaryExpr: // must be receive <-\n\t\t// y, ok := <-x\n\t\tf.expr(e.X)\n\n\tdefault:\n\t\tpanic(e)\n\t}\n\treturn typ\n}\n\nfunc (f *Finder) call(sig *types.Signature, args []ast.Expr) {\n\tif len(args) == 0 {\n\t\treturn\n\t}\n\n\t// Ellipsis call?  e.g. f(x, y, z...)\n\tif _, ok := args[len(args)-1].(*ast.Ellipsis); ok {\n\t\tfor i, arg := range args {\n\t\t\t// The final arg is a slice, and so is the final param.\n\t\t\tf.assign(sig.Params().At(i).Type(), f.expr(arg))\n\t\t}\n\t\treturn\n\t}\n\n\tvar argtypes []types.Type\n\n\t// Gather the effective actual parameter types.\n\tif tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {\n\t\t// f(g()) call where g has multiple results?\n\t\tf.expr(args[0])\n\t\t// unpack the tuple\n\t\tfor v := range tuple.Variables() {\n\t\t\targtypes = append(argtypes, v.Type())\n\t\t}\n\t} else {\n\t\tfor _, arg := range args {\n\t\t\targtypes = append(argtypes, f.expr(arg))\n\t\t}\n\t}\n\n\t// Assign the actuals to the formals.\n\tif !sig.Variadic() {\n\t\tfor i, argtype := range argtypes {\n\t\t\tf.assign(sig.Params().At(i).Type(), argtype)\n\t\t}\n\t} else {\n\t\t// The first n-1 parameters are assigned normally.\n\t\tnnormals := sig.Params().Len() - 1\n\t\tfor i, argtype := range argtypes[:nnormals] {\n\t\t\tf.assign(sig.Params().At(i).Type(), argtype)\n\t\t}\n\t\t// Remaining args are assigned to elements of varargs slice.\n\t\ttElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()\n\t\tfor i := nnormals; i < len(argtypes); i++ {\n\t\t\tf.assign(tElem, argtypes[i])\n\t\t}\n\t}\n}\n\n// builtin visits the arguments of a builtin type with signature sig.\nfunc (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr) {\n\tswitch obj.Name() {\n\tcase \"make\", \"new\":\n\t\tfor i, arg := range args {\n\t\t\tif i == 0 && f.info.Types[arg].IsType() {\n\t\t\t\tcontinue // skip the type operand\n\t\t\t}\n\t\t\tf.expr(arg)\n\t\t}\n\n\tcase \"append\":\n\t\ts := f.expr(args[0])\n\t\tif _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {\n\t\t\t// append(x, y...)   including append([]byte, \"foo\"...)\n\t\t\tf.expr(args[1])\n\t\t} else {\n\t\t\t// append(x, y, z)\n\t\t\ttElem := typeparams.CoreType(s).(*types.Slice).Elem()\n\t\t\tfor _, arg := range args[1:] {\n\t\t\t\tf.assign(tElem, f.expr(arg))\n\t\t\t}\n\t\t}\n\n\tcase \"delete\":\n\t\tm := f.expr(args[0])\n\t\tk := f.expr(args[1])\n\t\tf.assign(typeparams.CoreType(m).(*types.Map).Key(), k)\n\n\tdefault:\n\t\t// ordinary call\n\t\tf.call(sig, args)\n\t}\n}\n\nfunc (f *Finder) extract(tuple types.Type, i int) types.Type {\n\tif tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {\n\t\treturn tuple.At(i).Type()\n\t}\n\treturn tInvalid\n}\n\nfunc (f *Finder) valueSpec(spec *ast.ValueSpec) {\n\tvar T types.Type\n\tif spec.Type != nil {\n\t\tT = f.info.Types[spec.Type].Type\n\t}\n\tswitch len(spec.Values) {\n\tcase len(spec.Names): // e.g. var x, y = f(), g()\n\t\tfor _, value := range spec.Values {\n\t\t\tv := f.expr(value)\n\t\t\tif T != nil {\n\t\t\t\tf.assign(T, v)\n\t\t\t}\n\t\t}\n\n\tcase 1: // e.g. var x, y = f()\n\t\ttuple := f.exprN(spec.Values[0])\n\t\tfor i := range spec.Names {\n\t\t\tif T != nil {\n\t\t\t\tf.assign(T, f.extract(tuple, i))\n\t\t\t}\n\t\t}\n\t}\n}\n\n// assign records pairs of distinct types that are related by\n// assignability, where the left-hand side is an interface and both\n// sides have methods.\n//\n// It should be called for all assignability checks, type assertions,\n// explicit conversions and comparisons between two types, unless the\n// types are uninteresting (e.g. lhs is a concrete type, or the empty\n// interface; rhs has no methods).\nfunc (f *Finder) assign(lhs, rhs types.Type) {\n\tif types.Identical(lhs, rhs) {\n\t\treturn\n\t}\n\tif !types.IsInterface(lhs) {\n\t\treturn\n\t}\n\n\tif f.msetcache.MethodSet(lhs).Len() == 0 {\n\t\treturn\n\t}\n\tif f.msetcache.MethodSet(rhs).Len() == 0 {\n\t\treturn\n\t}\n\t// record the pair\n\tf.Result[Constraint{lhs, rhs}] = true\n}\n\n// typeAssert must be called for each type assertion x.(T) where x has\n// interface type I.\nfunc (f *Finder) typeAssert(I, T types.Type) {\n\t// Type assertions are slightly subtle, because they are allowed\n\t// to be \"impossible\", e.g.\n\t//\n\t// \tvar x interface{f()}\n\t//\t_ = x.(interface{f()int}) // legal\n\t//\n\t// (In hindsight, the language spec should probably not have\n\t// allowed this, but it's too late to fix now.)\n\t//\n\t// This means that a type assert from I to T isn't exactly a\n\t// constraint that T is assignable to I, but for a refactoring\n\t// tool it is a conditional constraint that, if T is assignable\n\t// to I before a refactoring, it should remain so after.\n\n\tif types.AssignableTo(T, I) {\n\t\tf.assign(I, T)\n\t}\n}\n\n// compare must be called for each comparison x==y.\nfunc (f *Finder) compare(x, y types.Type) {\n\tif types.AssignableTo(x, y) {\n\t\tf.assign(y, x)\n\t} else if types.AssignableTo(y, x) {\n\t\tf.assign(x, y)\n\t}\n}\n\n// expr visits a true expression (not a type or defining ident)\n// and returns its type.\nfunc (f *Finder) expr(e ast.Expr) types.Type {\n\ttv := f.info.Types[e]\n\tif tv.Value != nil {\n\t\treturn tv.Type // prune the descent for constants\n\t}\n\n\t// tv.Type may be nil for an ast.Ident.\n\n\tswitch e := e.(type) {\n\tcase *ast.BadExpr, *ast.BasicLit:\n\t\t// no-op\n\n\tcase *ast.Ident:\n\t\t// (referring idents only)\n\t\tif obj, ok := f.info.Uses[e]; ok {\n\t\t\treturn obj.Type()\n\t\t}\n\t\tif e.Name == \"_\" { // e.g. \"for _ = range x\"\n\t\t\treturn tInvalid\n\t\t}\n\t\tpanic(\"undefined ident: \" + e.Name)\n\n\tcase *ast.Ellipsis:\n\t\tif e.Elt != nil {\n\t\t\tf.expr(e.Elt)\n\t\t}\n\n\tcase *ast.FuncLit:\n\t\tsaved := f.sig\n\t\tf.sig = tv.Type.(*types.Signature)\n\t\tf.stmt(e.Body)\n\t\tf.sig = saved\n\n\tcase *ast.CompositeLit:\n\t\tswitch T := typeparams.CoreType(typeparams.Deref(tv.Type)).(type) {\n\t\tcase *types.Struct:\n\t\t\tfor i, elem := range e.Elts {\n\t\t\t\tif kv, ok := elem.(*ast.KeyValueExpr); ok {\n\t\t\t\t\tf.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))\n\t\t\t\t} else {\n\t\t\t\t\tf.assign(T.Field(i).Type(), f.expr(elem))\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase *types.Map:\n\t\t\tfor _, elem := range e.Elts {\n\t\t\t\telem := elem.(*ast.KeyValueExpr)\n\t\t\t\tf.assign(T.Key(), f.expr(elem.Key))\n\t\t\t\tf.assign(T.Elem(), f.expr(elem.Value))\n\t\t\t}\n\n\t\tcase *types.Array, *types.Slice:\n\t\t\ttElem := T.(interface {\n\t\t\t\tElem() types.Type\n\t\t\t}).Elem()\n\t\t\tfor _, elem := range e.Elts {\n\t\t\t\tif kv, ok := elem.(*ast.KeyValueExpr); ok {\n\t\t\t\t\t// ignore the key\n\t\t\t\t\tf.assign(tElem, f.expr(kv.Value))\n\t\t\t\t} else {\n\t\t\t\t\tf.assign(tElem, f.expr(elem))\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unexpected composite literal type %T: %v\", tv.Type, tv.Type.String()))\n\t\t}\n\n\tcase *ast.ParenExpr:\n\t\tf.expr(e.X)\n\n\tcase *ast.SelectorExpr:\n\t\tif seln, ok := f.info.Selections[e]; ok {\n\t\t\t// If e.X is a type (e.g., e is interface{ m() }.m), don't visit it.\n\t\t\tif seln.Kind() != types.MethodExpr {\n\t\t\t\tf.expr(e.X)\n\t\t\t}\n\t\t} else {\n\t\t\treturn f.info.Uses[e.Sel].Type() // qualified identifier\n\t\t}\n\n\tcase *ast.IndexExpr:\n\t\tif instance(f.info, e.X) {\n\t\t\t// f[T] or C[T] -- generic instantiation\n\t\t} else {\n\t\t\t// x[i] or m[k] -- index or lookup operation\n\t\t\tx := f.expr(e.X)\n\t\t\ti := f.expr(e.Index)\n\t\t\tif ux, ok := typeparams.CoreType(x).(*types.Map); ok {\n\t\t\t\tf.assign(ux.Key(), i)\n\t\t\t}\n\t\t}\n\n\tcase *ast.IndexListExpr:\n\t\t// f[X, Y] -- generic instantiation\n\n\tcase *ast.SliceExpr:\n\t\tf.expr(e.X)\n\t\tif e.Low != nil {\n\t\t\tf.expr(e.Low)\n\t\t}\n\t\tif e.High != nil {\n\t\t\tf.expr(e.High)\n\t\t}\n\t\tif e.Max != nil {\n\t\t\tf.expr(e.Max)\n\t\t}\n\n\tcase *ast.TypeAssertExpr:\n\t\tx := f.expr(e.X)\n\t\tf.typeAssert(x, f.info.Types[e.Type].Type)\n\n\tcase *ast.CallExpr:\n\t\tif tvFun := f.info.Types[e.Fun]; tvFun.IsType() {\n\t\t\t// conversion\n\t\t\targ0 := f.expr(e.Args[0])\n\t\t\tf.assign(tvFun.Type, arg0)\n\t\t} else {\n\t\t\t// function call\n\n\t\t\t// unsafe call. Treat calls to functions in unsafe like ordinary calls,\n\t\t\t// except that their signature cannot be determined by their func obj.\n\t\t\t// Without this special handling, f.expr(e.Fun) would fail below.\n\t\t\tif s, ok := ast.Unparen(e.Fun).(*ast.SelectorExpr); ok {\n\t\t\t\tif obj, ok := f.info.Uses[s.Sel].(*types.Builtin); ok && obj.Pkg().Path() == \"unsafe\" {\n\t\t\t\t\tsig := f.info.Types[e.Fun].Type.(*types.Signature)\n\t\t\t\t\tf.call(sig, e.Args)\n\t\t\t\t\treturn tv.Type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// builtin call\n\t\t\tif id, ok := ast.Unparen(e.Fun).(*ast.Ident); ok {\n\t\t\t\tif obj, ok := f.info.Uses[id].(*types.Builtin); ok {\n\t\t\t\t\tsig := f.info.Types[id].Type.(*types.Signature)\n\t\t\t\t\tf.builtin(obj, sig, e.Args)\n\t\t\t\t\treturn tv.Type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ordinary call\n\t\t\tf.call(typeparams.CoreType(f.expr(e.Fun)).(*types.Signature), e.Args)\n\t\t}\n\n\tcase *ast.StarExpr:\n\t\tf.expr(e.X)\n\n\tcase *ast.UnaryExpr:\n\t\tf.expr(e.X)\n\n\tcase *ast.BinaryExpr:\n\t\tx := f.expr(e.X)\n\t\ty := f.expr(e.Y)\n\t\tif e.Op == token.EQL || e.Op == token.NEQ {\n\t\t\tf.compare(x, y)\n\t\t}\n\n\tcase *ast.KeyValueExpr:\n\t\tf.expr(e.Key)\n\t\tf.expr(e.Value)\n\n\tcase *ast.ArrayType,\n\t\t*ast.StructType,\n\t\t*ast.FuncType,\n\t\t*ast.InterfaceType,\n\t\t*ast.MapType,\n\t\t*ast.ChanType:\n\t\tpanic(e)\n\t}\n\n\tif tv.Type == nil {\n\t\tpanic(fmt.Sprintf(\"no type for %T\", e))\n\t}\n\n\treturn tv.Type\n}\n\nfunc (f *Finder) stmt(s ast.Stmt) {\n\tswitch s := s.(type) {\n\tcase *ast.BadStmt,\n\t\t*ast.EmptyStmt,\n\t\t*ast.BranchStmt:\n\t\t// no-op\n\n\tcase *ast.DeclStmt:\n\t\td := s.Decl.(*ast.GenDecl)\n\t\tif d.Tok == token.VAR { // ignore consts\n\t\t\tfor _, spec := range d.Specs {\n\t\t\t\tf.valueSpec(spec.(*ast.ValueSpec))\n\t\t\t}\n\t\t}\n\n\tcase *ast.LabeledStmt:\n\t\tf.stmt(s.Stmt)\n\n\tcase *ast.ExprStmt:\n\t\tf.expr(s.X)\n\n\tcase *ast.SendStmt:\n\t\tch := f.expr(s.Chan)\n\t\tval := f.expr(s.Value)\n\t\tf.assign(typeparams.CoreType(ch).(*types.Chan).Elem(), val)\n\n\tcase *ast.IncDecStmt:\n\t\tf.expr(s.X)\n\n\tcase *ast.AssignStmt:\n\t\tswitch s.Tok {\n\t\tcase token.ASSIGN, token.DEFINE:\n\t\t\t// y := x   or   y = x\n\t\t\tvar rhsTuple types.Type\n\t\t\tif len(s.Lhs) != len(s.Rhs) {\n\t\t\t\trhsTuple = f.exprN(s.Rhs[0])\n\t\t\t}\n\t\t\tfor i := range s.Lhs {\n\t\t\t\tvar lhs, rhs types.Type\n\t\t\t\tif rhsTuple == nil {\n\t\t\t\t\trhs = f.expr(s.Rhs[i]) // 1:1 assignment\n\t\t\t\t} else {\n\t\t\t\t\trhs = f.extract(rhsTuple, i) // n:1 assignment\n\t\t\t\t}\n\n\t\t\t\tif id, ok := s.Lhs[i].(*ast.Ident); ok {\n\t\t\t\t\tif id.Name != \"_\" {\n\t\t\t\t\t\tif obj, ok := f.info.Defs[id]; ok {\n\t\t\t\t\t\t\tlhs = obj.Type() // definition\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif lhs == nil {\n\t\t\t\t\tlhs = f.expr(s.Lhs[i]) // assignment\n\t\t\t\t}\n\t\t\t\tf.assign(lhs, rhs)\n\t\t\t}\n\n\t\tdefault:\n\t\t\t// y op= x\n\t\t\tf.expr(s.Lhs[0])\n\t\t\tf.expr(s.Rhs[0])\n\t\t}\n\n\tcase *ast.GoStmt:\n\t\tf.expr(s.Call)\n\n\tcase *ast.DeferStmt:\n\t\tf.expr(s.Call)\n\n\tcase *ast.ReturnStmt:\n\t\tformals := f.sig.Results()\n\t\tswitch len(s.Results) {\n\t\tcase formals.Len(): // 1:1\n\t\t\tfor i, result := range s.Results {\n\t\t\t\tf.assign(formals.At(i).Type(), f.expr(result))\n\t\t\t}\n\n\t\tcase 1: // n:1\n\t\t\ttuple := f.exprN(s.Results[0])\n\t\t\tfor i := 0; i < formals.Len(); i++ {\n\t\t\t\tf.assign(formals.At(i).Type(), f.extract(tuple, i))\n\t\t\t}\n\t\t}\n\n\tcase *ast.SelectStmt:\n\t\tf.stmt(s.Body)\n\n\tcase *ast.BlockStmt:\n\t\tfor _, s := range s.List {\n\t\t\tf.stmt(s)\n\t\t}\n\n\tcase *ast.IfStmt:\n\t\tif s.Init != nil {\n\t\t\tf.stmt(s.Init)\n\t\t}\n\t\tf.expr(s.Cond)\n\t\tf.stmt(s.Body)\n\t\tif s.Else != nil {\n\t\t\tf.stmt(s.Else)\n\t\t}\n\n\tcase *ast.SwitchStmt:\n\t\tif s.Init != nil {\n\t\t\tf.stmt(s.Init)\n\t\t}\n\t\tvar tag types.Type = tUntypedBool\n\t\tif s.Tag != nil {\n\t\t\ttag = f.expr(s.Tag)\n\t\t}\n\t\tfor _, cc := range s.Body.List {\n\t\t\tcc := cc.(*ast.CaseClause)\n\t\t\tfor _, cond := range cc.List {\n\t\t\t\tf.compare(tag, f.info.Types[cond].Type)\n\t\t\t}\n\t\t\tfor _, s := range cc.Body {\n\t\t\t\tf.stmt(s)\n\t\t\t}\n\t\t}\n\n\tcase *ast.TypeSwitchStmt:\n\t\tif s.Init != nil {\n\t\t\tf.stmt(s.Init)\n\t\t}\n\t\tvar I types.Type\n\t\tswitch ass := s.Assign.(type) {\n\t\tcase *ast.ExprStmt: // x.(type)\n\t\t\tI = f.expr(ast.Unparen(ass.X).(*ast.TypeAssertExpr).X)\n\t\tcase *ast.AssignStmt: // y := x.(type)\n\t\t\tI = f.expr(ast.Unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)\n\t\t}\n\t\tfor _, cc := range s.Body.List {\n\t\t\tcc := cc.(*ast.CaseClause)\n\t\t\tfor _, cond := range cc.List {\n\t\t\t\ttCase := f.info.Types[cond].Type\n\t\t\t\tif tCase != tUntypedNil {\n\t\t\t\t\tf.typeAssert(I, tCase)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor _, s := range cc.Body {\n\t\t\t\tf.stmt(s)\n\t\t\t}\n\t\t}\n\n\tcase *ast.CommClause:\n\t\tif s.Comm != nil {\n\t\t\tf.stmt(s.Comm)\n\t\t}\n\t\tfor _, s := range s.Body {\n\t\t\tf.stmt(s)\n\t\t}\n\n\tcase *ast.ForStmt:\n\t\tif s.Init != nil {\n\t\t\tf.stmt(s.Init)\n\t\t}\n\t\tif s.Cond != nil {\n\t\t\tf.expr(s.Cond)\n\t\t}\n\t\tif s.Post != nil {\n\t\t\tf.stmt(s.Post)\n\t\t}\n\t\tf.stmt(s.Body)\n\n\tcase *ast.RangeStmt:\n\t\tx := f.expr(s.X)\n\t\t// No conversions are involved when Tok==DEFINE.\n\t\tif s.Tok == token.ASSIGN {\n\t\t\tif s.Key != nil {\n\t\t\t\tk := f.expr(s.Key)\n\t\t\t\tvar xelem types.Type\n\t\t\t\t// Keys of array, *array, slice, string aren't interesting\n\t\t\t\t// since the RHS key type is just an int.\n\t\t\t\tswitch ux := typeparams.CoreType(x).(type) {\n\t\t\t\tcase *types.Chan:\n\t\t\t\t\txelem = ux.Elem()\n\t\t\t\tcase *types.Map:\n\t\t\t\t\txelem = ux.Key()\n\t\t\t\t}\n\t\t\t\tif xelem != nil {\n\t\t\t\t\tf.assign(k, xelem)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif s.Value != nil {\n\t\t\t\tval := f.expr(s.Value)\n\t\t\t\tvar xelem types.Type\n\t\t\t\t// Values of type strings aren't interesting because\n\t\t\t\t// the RHS value type is just a rune.\n\t\t\t\tswitch ux := typeparams.CoreType(x).(type) {\n\t\t\t\tcase *types.Array:\n\t\t\t\t\txelem = ux.Elem()\n\t\t\t\tcase *types.Map:\n\t\t\t\t\txelem = ux.Elem()\n\t\t\t\tcase *types.Pointer: // *array\n\t\t\t\t\txelem = typeparams.CoreType(typeparams.Deref(ux)).(*types.Array).Elem()\n\t\t\t\tcase *types.Slice:\n\t\t\t\t\txelem = ux.Elem()\n\t\t\t\t}\n\t\t\t\tif xelem != nil {\n\t\t\t\t\tf.assign(val, xelem)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tf.stmt(s.Body)\n\n\tdefault:\n\t\tpanic(s)\n\t}\n}\n\n// -- Plundered from golang.org/x/tools/go/ssa -----------------\n\nfunc instance(info *types.Info, expr ast.Expr) bool {\n\tvar id *ast.Ident\n\tswitch x := expr.(type) {\n\tcase *ast.Ident:\n\t\tid = x\n\tcase *ast.SelectorExpr:\n\t\tid = x.Sel\n\tdefault:\n\t\treturn false\n\t}\n\t_, ok := info.Instances[id]\n\treturn ok\n}\n"
  },
  {
    "path": "refactor/satisfy/find_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage satisfy_test\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/importer\"\n\t\"go/parser\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/internal/testenv\"\n\t\"golang.org/x/tools/refactor/satisfy\"\n)\n\n// This test exercises various operations on core types of type parameters.\n// (It also provides pretty decent coverage of the non-generic operations.)\nfunc TestGenericCoreOperations(t *testing.T) {\n\tconst src = `package foo\n\nimport \"unsafe\"\n\ntype I interface { f() }\n\ntype impl struct{}\nfunc (impl) f() {}\n\n// A big pile of single-serving types that implement I.\ntype A struct{impl}\ntype B struct{impl}\ntype C struct{impl}\ntype D struct{impl}\ntype E struct{impl}\ntype F struct{impl}\ntype G struct{impl}\ntype H struct{impl}\ntype J struct{impl}\ntype K struct{impl}\ntype L struct{impl}\ntype M struct{impl}\ntype N struct{impl}\ntype O struct{impl}\ntype P struct{impl}\ntype Q struct{impl}\ntype R struct{impl}\ntype S struct{impl}\ntype T struct{impl}\ntype U struct{impl}\ntype V struct{impl}\ntype W struct{impl}\ntype X struct{impl}\n\ntype Generic[T any] struct{impl}\nfunc (Generic[T]) g(T) {}\n\ntype GI[T any] interface{\n\tg(T)\n}\n\nfunc _[Slice interface{ []I }](s Slice) Slice {\n\ts[0] = L{} // I <- L\n\treturn append(s, A{}) // I <- A\n}\n\nfunc _[Func interface{ func(I) B }](fn Func) {\n\tb := fn(C{}) // I <- C\n\tvar _ I = b // I <- B\n}\n\nfunc _[Chan interface{ chan D }](ch Chan) {\n\tvar i I\n\tfor i = range ch {} // I <- D\n\t_ = i\n}\n\nfunc _[Chan interface{ chan E }](ch Chan) {\n\tvar _ I = <-ch // I <- E\n}\n\nfunc _[Chan interface{ chan I }](ch Chan) {\n\tch <- F{} // I <- F\n}\n\nfunc _[Map interface{ map[G]H }](m Map) {\n\tvar k, v I\n\tfor k, v = range m {} // I <- G, I <- H\n\t_, _ = k, v\n}\n\nfunc _[Map interface{ map[I]K }](m Map) {\n\tvar _ I = m[J{}] // I <- J, I <- K\n\tdelete(m, R{}) // I <- R\n\t_, _ = m[J{}]\n}\n\nfunc _[Array interface{ [1]I }](a Array) {\n\ta[0] = M{} // I <- M\n}\n\nfunc _[Array interface{ [1]N }](a Array) {\n\tvar _ I = a[0] // I <- N\n}\n\nfunc _[Array interface{ [1]O }](a Array) {\n\tvar v I\n\tfor _, v = range a {} // I <- O\n\t_ = v\n}\n\nfunc _[ArrayPtr interface{ *[1]P }](a ArrayPtr) {\n\tvar v I\n\tfor _, v = range a {} // I <- P\n\t_ = v\n}\n\nfunc _[Slice interface{ []Q }](s Slice) {\n\tvar v I\n\tfor _, v = range s {} // I <- Q\n\t_ = v\n}\n\nfunc _[Func interface{ func() (S, bool) }](fn Func) {\n\tvar i I\n\ti, _ = fn() // I <- S\n\t_ = i\n}\n\nfunc _() I {\n\tvar _ I = T{} // I <- T\n\tvar _ I = Generic[T]{} // I <- Generic[T]\n\tvar _ I = Generic[string]{} // I <- Generic[string]\n\treturn U{} // I <- U\n}\n\nvar _ GI[string] = Generic[string]{} //  GI[string] <- Generic[string]\n\n// universally quantified constraints:\n// the type parameter may appear on the left, the right, or both sides.\n\nfunc  _[T any](g Generic[T]) GI[T] {\n\treturn g // GI[T] <- Generic[T]\n}\n\nfunc  _[T any]() {\n\ttype GI2[T any] interface{ g(string) }\n\tvar _ GI2[T] = Generic[string]{} // GI2[T] <- Generic[string]\n}\n\ntype Gen2[T any] struct{}\nfunc (f Gen2[T]) g(string) { global = f } // GI[string] <- Gen2[T]\n\nvar global GI[string]\n\nfunc _() {\n\tvar x [3]V\n\t// golang/go#56227: the finder should visit calls in the unsafe package.\n\t_ = unsafe.Slice(&x[0], func() int { var _ I = x[0]; return 3 }()) // I <- V\n}\n\nfunc _[P ~struct{F I}]() {\n\t_ = P{W{}}\n\t_ = P{F: X{}}\n}\n\n// golang/go#77625: don't panic on a method expression of an anonymous interface.\nvar _ = interface{ m() }.m\n`\n\tgot := constraints(t, src)\n\twant := []string{\n\t\t\"p.GI2[T] <- p.Generic[string]\", // implicitly \"forall T\" quantified\n\t\t\"p.GI[T] <- p.Generic[T]\",       // implicitly \"forall T\" quantified\n\t\t\"p.GI[string] <- p.Gen2[T]\",     // implicitly \"forall T\" quantified\n\t\t\"p.GI[string] <- p.Generic[string]\",\n\t\t\"p.I <- p.A\",\n\t\t\"p.I <- p.B\",\n\t\t\"p.I <- p.C\",\n\t\t\"p.I <- p.D\",\n\t\t\"p.I <- p.E\",\n\t\t\"p.I <- p.F\",\n\t\t\"p.I <- p.G\",\n\t\t\"p.I <- p.Generic[p.T]\",\n\t\t\"p.I <- p.Generic[string]\",\n\t\t\"p.I <- p.H\",\n\t\t\"p.I <- p.J\",\n\t\t\"p.I <- p.K\",\n\t\t\"p.I <- p.L\",\n\t\t\"p.I <- p.M\",\n\t\t\"p.I <- p.N\",\n\t\t\"p.I <- p.O\",\n\t\t\"p.I <- p.P\",\n\t\t\"p.I <- p.Q\",\n\t\t\"p.I <- p.R\",\n\t\t\"p.I <- p.S\",\n\t\t\"p.I <- p.T\",\n\t\t\"p.I <- p.U\",\n\t\t\"p.I <- p.V\",\n\t\t\"p.I <- p.W\",\n\t\t\"p.I <- p.X\",\n\t}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Fatalf(\"found unexpected constraints: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestNewExpr(t *testing.T) {\n\ttestenv.NeedsGo1Point(t, 26)\n\tconst src = `package p\n\ntype I interface{ f() }\ntype C int\nfunc (C) f() {}\n\nvar _ I = new(C(123))\n`\n\tgot := constraints(t, src)\n\twant := []string{\n\t\t\"p.I <- *p.C\",\n\t}\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Fatalf(\"found unexpected constraints: got %s, want %s\", got, want)\n\t}\n}\n\nfunc constraints(t *testing.T, src string) []string {\n\t// parse\n\tfset := token.NewFileSet()\n\tf, err := parser.ParseFile(fset, \"p.go\", src, 0)\n\tif err != nil {\n\t\tt.Fatal(err) // parse error\n\t}\n\tfiles := []*ast.File{f}\n\n\t// type-check\n\tinfo := &types.Info{\n\t\tTypes:        make(map[ast.Expr]types.TypeAndValue),\n\t\tDefs:         make(map[*ast.Ident]types.Object),\n\t\tUses:         make(map[*ast.Ident]types.Object),\n\t\tImplicits:    make(map[ast.Node]types.Object),\n\t\tInstances:    make(map[*ast.Ident]types.Instance),\n\t\tScopes:       make(map[ast.Node]*types.Scope),\n\t\tSelections:   make(map[*ast.SelectorExpr]*types.Selection),\n\t\tFileVersions: make(map[*ast.File]string),\n\t}\n\tconf := types.Config{\n\t\tImporter: importer.Default(),\n\t}\n\tif _, err := conf.Check(\"p\", fset, files, info); err != nil {\n\t\tt.Fatal(err) // type error\n\t}\n\n\t// gather constraints\n\tvar finder satisfy.Finder\n\tfinder.Find(info, files)\n\tvar constraints []string\n\tfor c := range finder.Result {\n\t\tconstraints = append(constraints, fmt.Sprintf(\"%v <- %v\", c.LHS, c.RHS))\n\t}\n\tsort.Strings(constraints)\n\treturn constraints\n}\n"
  },
  {
    "path": "txtar/archive.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package txtar implements a trivial text-based file archive format.\n//\n// The goals for the format are:\n//\n//   - be trivial enough to create and edit by hand.\n//   - be able to store trees of text files describing go command test cases.\n//   - diff nicely in git history and code reviews.\n//\n// Non-goals include being a completely general archive format,\n// storing binary data, storing file modes, storing special files like\n// symbolic links, and so on.\n//\n// # Txtar format\n//\n// A txtar archive is zero or more comment lines and then a sequence of file entries.\n// Each file entry begins with a file marker line of the form \"-- FILENAME --\"\n// and is followed by zero or more file content lines making up the file data.\n// The comment or file content ends at the next file marker line.\n// The file marker line must begin with the three-byte sequence \"-- \"\n// and end with the three-byte sequence \" --\", but the enclosed\n// file name can be surrounding by additional white space,\n// all of which is stripped.\n//\n// If the txtar file is missing a trailing newline on the final line,\n// parsers should consider a final newline to be present anyway.\n//\n// There are no possible syntax errors in a txtar archive.\npackage txtar\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\n// An Archive is a collection of files.\ntype Archive struct {\n\tComment []byte\n\tFiles   []File\n}\n\n// A File is a single file in an archive.\ntype File struct {\n\tName string // name of file (\"foo/bar.txt\")\n\tData []byte // text content of file\n}\n\n// Format returns the serialized form of an Archive.\n// It is assumed that the Archive data structure is well-formed:\n// a.Comment and all a.File[i].Data contain no file marker lines,\n// and all a.File[i].Name is non-empty.\nfunc Format(a *Archive) []byte {\n\tvar buf bytes.Buffer\n\tbuf.Write(fixNL(a.Comment))\n\tfor _, f := range a.Files {\n\t\tfmt.Fprintf(&buf, \"-- %s --\\n\", f.Name)\n\t\tbuf.Write(fixNL(f.Data))\n\t}\n\treturn buf.Bytes()\n}\n\n// ParseFile parses the named file as an archive.\nfunc ParseFile(file string) (*Archive, error) {\n\tdata, err := os.ReadFile(file)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn Parse(data), nil\n}\n\n// Parse parses the serialized form of an Archive.\n// The returned Archive holds slices of data.\nfunc Parse(data []byte) *Archive {\n\ta := new(Archive)\n\tvar name string\n\ta.Comment, name, data = findFileMarker(data)\n\tfor name != \"\" {\n\t\tf := File{name, nil}\n\t\tf.Data, name, data = findFileMarker(data)\n\t\ta.Files = append(a.Files, f)\n\t}\n\treturn a\n}\n\nvar (\n\tnewlineMarker = []byte(\"\\n-- \")\n\tmarker        = []byte(\"-- \")\n\tmarkerEnd     = []byte(\" --\")\n)\n\n// findFileMarker finds the next file marker in data,\n// extracts the file name, and returns the data before the marker,\n// the file name, and the data after the marker.\n// If there is no next marker, findFileMarker returns before = fixNL(data), name = \"\", after = nil.\nfunc findFileMarker(data []byte) (before []byte, name string, after []byte) {\n\tvar i int\n\tfor {\n\t\tif name, after = isMarker(data[i:]); name != \"\" {\n\t\t\treturn data[:i], name, after\n\t\t}\n\t\tj := bytes.Index(data[i:], newlineMarker)\n\t\tif j < 0 {\n\t\t\treturn fixNL(data), \"\", nil\n\t\t}\n\t\ti += j + 1 // positioned at start of new possible marker\n\t}\n}\n\n// isMarker checks whether data begins with a file marker line.\n// If so, it returns the name from the line and the data after the line.\n// Otherwise it returns name == \"\" with an unspecified after.\nfunc isMarker(data []byte) (name string, after []byte) {\n\tif !bytes.HasPrefix(data, marker) {\n\t\treturn \"\", nil\n\t}\n\tif i := bytes.IndexByte(data, '\\n'); i >= 0 {\n\t\tdata, after = data[:i], data[i+1:]\n\t\tif data[i-1] == '\\r' { // handle \\r\\n line ending\n\t\t\tdata = data[:i-1]\n\t\t}\n\t}\n\tif !(bytes.HasSuffix(data, markerEnd) && len(data) >= len(marker)+len(markerEnd)) {\n\t\treturn \"\", nil\n\t}\n\treturn strings.TrimSpace(string(data[len(marker) : len(data)-len(markerEnd)])), after\n}\n\n// If data is empty or ends in \\n, fixNL returns data.\n// Otherwise fixNL returns a new slice consisting of data with a final \\n added.\nfunc fixNL(data []byte) []byte {\n\tif len(data) == 0 || data[len(data)-1] == '\\n' {\n\t\treturn data\n\t}\n\td := make([]byte, len(data)+1)\n\tcopy(d, data)\n\td[len(data)] = '\\n'\n\treturn d\n}\n"
  },
  {
    "path": "txtar/archive_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage txtar\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestParse(t *testing.T) {\n\tvar tests = []struct {\n\t\tname   string\n\t\ttext   string\n\t\tparsed *Archive\n\t}{\n\t\t{\n\t\t\tname: \"basic\",\n\t\t\ttext: `comment1\ncomment2\n-- file1 --\nFile 1 text.\n-- foo ---\nMore file 1 text.\n-- file 2 --\nFile 2 text.\n-- empty --\n-- noNL --\nhello world\n-- empty filename line --\nsome content\n-- --`,\n\t\t\tparsed: &Archive{\n\t\t\t\tComment: []byte(\"comment1\\ncomment2\\n\"),\n\t\t\t\tFiles: []File{\n\t\t\t\t\t{\"file1\", []byte(\"File 1 text.\\n-- foo ---\\nMore file 1 text.\\n\")},\n\t\t\t\t\t{\"file 2\", []byte(\"File 2 text.\\n\")},\n\t\t\t\t\t{\"empty\", []byte{}},\n\t\t\t\t\t{\"noNL\", []byte(\"hello world\\n\")},\n\t\t\t\t\t{\"empty filename line\", []byte(\"some content\\n-- --\\n\")},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"crlf\",\n\t\t\ttext: \"comment\\r\\n-- file --\\r\\ndata\\r\\n\",\n\t\t\tparsed: &Archive{\n\t\t\t\tComment: []byte(\"comment\\r\\n\"),\n\t\t\t\tFiles:   []File{{\"file\", []byte(\"data\\r\\n\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"utf8 and comment\",\n\t\t\ttext: `# This is a test comment\n-- hello.txt --\nHello\n-- unicode.txt --\nGo语言\n`,\n\t\t\tparsed: &Archive{\n\t\t\t\tComment: []byte(\"# This is a test comment\\n\"),\n\t\t\t\tFiles: []File{\n\t\t\t\t\t{\"hello.txt\", []byte(\"Hello\\n\")},\n\t\t\t\t\t{\"unicode.txt\", []byte(\"Go语言\\n\")},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ta := Parse([]byte(tt.text))\n\t\t\tif !reflect.DeepEqual(a, tt.parsed) {\n\t\t\t\tt.Fatalf(\"Parse: wrong output:\\nhave:\\n%s\\nwant:\\n%s\", shortArchive(a), shortArchive(tt.parsed))\n\t\t\t}\n\t\t\ttext := Format(a)\n\t\t\ta = Parse(text)\n\t\t\tif !reflect.DeepEqual(a, tt.parsed) {\n\t\t\t\tt.Fatalf(\"Parse after Format: wrong output:\\nhave:\\n%s\\nwant:\\n%s\", shortArchive(a), shortArchive(tt.parsed))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFormat(t *testing.T) {\n\tvar tests = []struct {\n\t\tname   string\n\t\tinput  *Archive\n\t\twanted string\n\t}{\n\t\t{\n\t\t\tname: \"basic\",\n\t\t\tinput: &Archive{\n\t\t\t\tComment: []byte(\"comment1\\ncomment2\\n\"),\n\t\t\t\tFiles: []File{\n\t\t\t\t\t{\"file1\", []byte(\"File 1 text.\\n-- foo ---\\nMore file 1 text.\\n\")},\n\t\t\t\t\t{\"file 2\", []byte(\"File 2 text.\\n\")},\n\t\t\t\t\t{\"empty\", []byte{}},\n\t\t\t\t\t{\"noNL\", []byte(\"hello world\")},\n\t\t\t\t},\n\t\t\t},\n\t\t\twanted: `comment1\ncomment2\n-- file1 --\nFile 1 text.\n-- foo ---\nMore file 1 text.\n-- file 2 --\nFile 2 text.\n-- empty --\n-- noNL --\nhello world\n`,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tresult := Format(tt.input)\n\t\t\tif string(result) != tt.wanted {\n\t\t\t\tt.Errorf(\"Wrong output. \\nGot:\\n%s\\nWant:\\n%s\\n\", string(result), tt.wanted)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc shortArchive(a *Archive) string {\n\tvar buf bytes.Buffer\n\tfmt.Fprintf(&buf, \"comment: %q\\n\", a.Comment)\n\tfor _, f := range a.Files {\n\t\tfmt.Fprintf(&buf, \"file %q: %q\\n\", f.Name, f.Data)\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "txtar/fs.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage txtar\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"path\"\n\t\"slices\"\n\t\"time\"\n)\n\n// FS returns the file system form of an Archive.\n// It returns an error if any of the file names in the archive\n// are not valid file system names.\n// The archive must not be modified while the FS is in use.\n//\n// If the file system detects that it has been modified, calls to the\n// file system return an ErrModified error.\nfunc FS(a *Archive) (fs.FS, error) {\n\t// Create a filesystem with a root directory.\n\troot := &node{fileinfo: fileinfo{path: \".\", mode: readOnlyDir}}\n\tfsys := &filesystem{a, map[string]*node{root.path: root}}\n\n\tif err := initFiles(fsys); err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create fs.FS from txtar.Archive: %s\", err)\n\t}\n\treturn fsys, nil\n}\n\nconst (\n\treadOnly    fs.FileMode = 0o444 // read only mode\n\treadOnlyDir             = readOnly | fs.ModeDir\n)\n\n// ErrModified indicates that file system returned by FS\n// noticed that the underlying archive has been modified\n// since the call to FS. Detection of modification is best effort,\n// to help diagnose misuse of the API, and is not guaranteed.\nvar ErrModified error = errors.New(\"txtar.Archive has been modified during txtar.FS\")\n\n// A filesystem is a simple in-memory file system for txtar archives,\n// represented as a map from valid path names to information about the\n// files or directories they represent.\n//\n// File system operations are read only. Modifications to the underlying\n// *Archive may race. To help prevent this, the filesystem tries\n// to detect modification during Open and return ErrModified if it\n// is able to detect a modification.\ntype filesystem struct {\n\tar    *Archive\n\tnodes map[string]*node\n}\n\n// node is a file or directory in the tree of a filesystem.\ntype node struct {\n\tfileinfo               // fs.FileInfo and fs.DirEntry implementation\n\tidx      int           // index into ar.Files (for files)\n\tentries  []fs.DirEntry // subdirectories and files (for directories)\n}\n\nvar _ fs.FS = (*filesystem)(nil)\nvar _ fs.DirEntry = (*node)(nil)\n\n// initFiles initializes fsys from fsys.ar.Files. Returns an error if there are any\n// invalid file names or collisions between file or directories.\nfunc initFiles(fsys *filesystem) error {\n\tfor idx, file := range fsys.ar.Files {\n\t\tname := file.Name\n\t\tif !fs.ValidPath(name) {\n\t\t\treturn fmt.Errorf(\"file %q is an invalid path\", name)\n\t\t}\n\n\t\tn := &node{idx: idx, fileinfo: fileinfo{path: name, size: len(file.Data), mode: readOnly}}\n\t\tif err := insert(fsys, n); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// insert adds node n as an entry to its parent directory within the filesystem.\nfunc insert(fsys *filesystem, n *node) error {\n\tif m := fsys.nodes[n.path]; m != nil {\n\t\treturn fmt.Errorf(\"duplicate path %q\", n.path)\n\t}\n\tfsys.nodes[n.path] = n\n\n\t// fsys.nodes contains \".\" to prevent infinite loops.\n\tparent, err := directory(fsys, path.Dir(n.path))\n\tif err != nil {\n\t\treturn err\n\t}\n\tparent.entries = append(parent.entries, n)\n\treturn nil\n}\n\n// directory returns the directory node with the path dir and lazily-creates it\n// if it does not exist.\nfunc directory(fsys *filesystem, dir string) (*node, error) {\n\tif m := fsys.nodes[dir]; m != nil && m.IsDir() {\n\t\treturn m, nil // pre-existing directory\n\t}\n\n\tn := &node{fileinfo: fileinfo{path: dir, mode: readOnlyDir}}\n\tif err := insert(fsys, n); err != nil {\n\t\treturn nil, err\n\t}\n\treturn n, nil\n}\n\n// dataOf returns the data associated with the file t.\n// May return ErrModified if fsys.ar has been modified.\nfunc dataOf(fsys *filesystem, n *node) ([]byte, error) {\n\tif n.idx >= len(fsys.ar.Files) {\n\t\treturn nil, ErrModified\n\t}\n\n\tf := fsys.ar.Files[n.idx]\n\tif f.Name != n.path || len(f.Data) != n.size {\n\t\treturn nil, ErrModified\n\t}\n\treturn f.Data, nil\n}\n\nfunc (fsys *filesystem) Open(name string) (fs.File, error) {\n\tif !fs.ValidPath(name) {\n\t\treturn nil, &fs.PathError{Op: \"open\", Path: name, Err: fs.ErrInvalid}\n\t}\n\n\tn := fsys.nodes[name]\n\tswitch {\n\tcase n == nil:\n\t\treturn nil, &fs.PathError{Op: \"open\", Path: name, Err: fs.ErrNotExist}\n\tcase n.IsDir():\n\t\treturn &openDir{fileinfo: n.fileinfo, entries: n.entries}, nil\n\tdefault:\n\t\tdata, err := dataOf(fsys, n)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &openFile{fileinfo: n.fileinfo, data: data}, nil\n\t}\n}\n\nfunc (fsys *filesystem) ReadFile(name string) ([]byte, error) {\n\tfile, err := fsys.Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif file, ok := file.(*openFile); ok {\n\t\treturn slices.Clone(file.data), nil\n\t}\n\treturn nil, &fs.PathError{Op: \"read\", Path: name, Err: fs.ErrInvalid}\n}\n\n// A fileinfo implements fs.FileInfo and fs.DirEntry for a given archive file.\ntype fileinfo struct {\n\tpath string // unique path to the file or directory within a filesystem\n\tsize int\n\tmode fs.FileMode\n}\n\nvar _ fs.FileInfo = (*fileinfo)(nil)\nvar _ fs.DirEntry = (*fileinfo)(nil)\n\nfunc (i *fileinfo) Name() string               { return path.Base(i.path) }\nfunc (i *fileinfo) Size() int64                { return int64(i.size) }\nfunc (i *fileinfo) Mode() fs.FileMode          { return i.mode }\nfunc (i *fileinfo) Type() fs.FileMode          { return i.mode.Type() }\nfunc (i *fileinfo) ModTime() time.Time         { return time.Time{} }\nfunc (i *fileinfo) IsDir() bool                { return i.mode&fs.ModeDir != 0 }\nfunc (i *fileinfo) Sys() any                   { return nil }\nfunc (i *fileinfo) Info() (fs.FileInfo, error) { return i, nil }\n\n// An openFile is a regular (non-directory) fs.File open for reading.\ntype openFile struct {\n\tfileinfo\n\tdata   []byte\n\toffset int64\n}\n\nvar _ fs.File = (*openFile)(nil)\n\nfunc (f *openFile) Stat() (fs.FileInfo, error) { return &f.fileinfo, nil }\nfunc (f *openFile) Close() error               { return nil }\nfunc (f *openFile) Read(b []byte) (int, error) {\n\tif f.offset >= int64(len(f.data)) {\n\t\treturn 0, io.EOF\n\t}\n\tif f.offset < 0 {\n\t\treturn 0, &fs.PathError{Op: \"read\", Path: f.path, Err: fs.ErrInvalid}\n\t}\n\tn := copy(b, f.data[f.offset:])\n\tf.offset += int64(n)\n\treturn n, nil\n}\n\nfunc (f *openFile) Seek(offset int64, whence int) (int64, error) {\n\tswitch whence {\n\tcase 0:\n\t\t// offset += 0\n\tcase 1:\n\t\toffset += f.offset\n\tcase 2:\n\t\toffset += int64(len(f.data))\n\t}\n\tif offset < 0 || offset > int64(len(f.data)) {\n\t\treturn 0, &fs.PathError{Op: \"seek\", Path: f.path, Err: fs.ErrInvalid}\n\t}\n\tf.offset = offset\n\treturn offset, nil\n}\n\nfunc (f *openFile) ReadAt(b []byte, offset int64) (int, error) {\n\tif offset < 0 || offset > int64(len(f.data)) {\n\t\treturn 0, &fs.PathError{Op: \"read\", Path: f.path, Err: fs.ErrInvalid}\n\t}\n\tn := copy(b, f.data[offset:])\n\tif n < len(b) {\n\t\treturn n, io.EOF\n\t}\n\treturn n, nil\n}\n\n// A openDir is a directory fs.File (so also an fs.ReadDirFile) open for reading.\ntype openDir struct {\n\tfileinfo\n\tentries []fs.DirEntry\n\toffset  int\n}\n\nvar _ fs.ReadDirFile = (*openDir)(nil)\n\nfunc (d *openDir) Stat() (fs.FileInfo, error) { return &d.fileinfo, nil }\nfunc (d *openDir) Close() error               { return nil }\nfunc (d *openDir) Read(b []byte) (int, error) {\n\treturn 0, &fs.PathError{Op: \"read\", Path: d.path, Err: fs.ErrInvalid}\n}\n\nfunc (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) {\n\tn := len(d.entries) - d.offset\n\tif n == 0 && count > 0 {\n\t\treturn nil, io.EOF\n\t}\n\tif count > 0 && n > count {\n\t\tn = count\n\t}\n\tlist := make([]fs.DirEntry, n)\n\tcopy(list, d.entries[d.offset:d.offset+n])\n\td.offset += n\n\treturn list, nil\n}\n"
  },
  {
    "path": "txtar/fs_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage txtar_test\n\nimport (\n\t\"io/fs\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"golang.org/x/tools/txtar\"\n)\n\nfunc TestFS(t *testing.T) {\n\tvar fstestcases = []struct {\n\t\tname, input, files string\n\t}{\n\t\t{\n\t\t\tname:  \"empty\",\n\t\t\tinput: ``,\n\t\t\tfiles: \"\",\n\t\t},\n\t\t{\n\t\t\tname: \"one\",\n\t\t\tinput: `\n-- one.txt --\none\n`,\n\t\t\tfiles: \"one.txt\",\n\t\t},\n\t\t{\n\t\t\tname: \"two\",\n\t\t\tinput: `\n-- one.txt --\none\n-- two.txt --\ntwo\n`,\n\t\t\tfiles: \"one.txt two.txt\",\n\t\t},\n\t\t{\n\t\t\tname: \"subdirectories\",\n\t\t\tinput: `\n-- one.txt --\none\n-- 2/two.txt --\ntwo\n-- 2/3/three.txt --\nthree\n-- 4/four.txt --\nfour\n`,\n\t\t\tfiles: \"one.txt 2/two.txt 2/3/three.txt 4/four.txt\",\n\t\t},\n\t}\n\n\tfor _, tc := range fstestcases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\ta := txtar.Parse([]byte(tc.input))\n\t\t\tfsys, err := txtar.FS(a)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tfiles := strings.Fields(tc.files)\n\t\t\tif err := fstest.TestFS(fsys, files...); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tfor _, f := range a.Files {\n\t\t\t\tb, err := fs.ReadFile(fsys, f.Name)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"ReadFile(%q) failed with error: %v\", f.Name, err)\n\t\t\t\t}\n\t\t\t\tif got, want := string(b), string(f.Data); got != want {\n\t\t\t\t\tt.Errorf(\"ReadFile(%q) = %q; want %q\", f.Name, got, want)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInvalid(t *testing.T) {\n\tinvalidtestcases := []struct {\n\t\tname, want string\n\t\tinput      string\n\t}{\n\t\t{\"unclean file names\", \"invalid path\", `\n-- 1/../one.txt --\none\n-- 2/sub/../two.txt --\ntwo\n`},\n\t\t{\"duplicate name\", `cannot create fs.FS from txtar.Archive: duplicate path \"1/2/one.txt\"`, `\n-- 1/2/one.txt --\none\n-- 1/2/one.txt --\ntwo\n`},\n\t\t{\"file conflicts with directory\", `duplicate path \"1/2\"`, `\n-- 1/2 --\none\n-- 1/2/one.txt --\ntwo\n`},\n\t}\n\n\tfor _, tc := range invalidtestcases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\ta := txtar.Parse([]byte(tc.input))\n\t\t\t_, err := txtar.FS(a)\n\t\t\tif err == nil {\n\t\t\t\tt.Fatal(\"txtar.FS(...) succeeded; expected an error\")\n\t\t\t}\n\t\t\tif got := err.Error(); !strings.Contains(got, tc.want) || tc.want == \"\" {\n\t\t\t\tt.Errorf(\"txtar.FS(...) got error %q; want %q\", got, tc.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestModified(t *testing.T) {\n\tconst input = `\n-- one.txt --\none\n`\n\tfor _, mod := range []func(a *txtar.Archive){\n\t\tfunc(a *txtar.Archive) { a.Files[0].Data = []byte(\"other\") },\n\t\tfunc(a *txtar.Archive) { a.Files[0].Name = \"other\" },\n\t\tfunc(a *txtar.Archive) { a.Files = nil },\n\t} {\n\t\ta := txtar.Parse([]byte(input))\n\t\tif n := len(a.Files); n != 1 {\n\t\t\tt.Fatalf(\"txtar.Parse(%q) got %d files; expected 1\", input, n)\n\t\t}\n\n\t\tfsys, err := txtar.FS(a)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Confirm we can open \"one.txt\".\n\t\t_, err = fsys.Open(\"one.txt\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// Modify a to get ErrModified when opening \"one.txt\".\n\t\tmod(a)\n\n\t\t_, err = fsys.Open(\"one.txt\")\n\t\tif err != txtar.ErrModified {\n\t\t\tt.Errorf(\"Open(%q) got error %s; want ErrModified\", \"one.txt\", err)\n\t\t}\n\t}\n}\n\nfunc TestReadFile(t *testing.T) {\n\tconst input = `\n-- 1/one.txt --\none\n`\n\ta := txtar.Parse([]byte(input))\n\tfsys, err := txtar.FS(a)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treadfs := fsys.(fs.ReadFileFS)\n\t_, err = readfs.ReadFile(\"1\")\n\tif err == nil {\n\t\tt.Errorf(\"ReadFile(%q) succeeded; expected an error when reading a directory\", \"1\")\n\t}\n\n\tcontent, err := readfs.ReadFile(\"1/one.txt\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := \"one\\n\"\n\tif got := string(content); want != got {\n\t\tt.Errorf(\"ReadFile(%q) = %q; want %q\", \"1/one.txt\", got, want)\n\t}\n}\n"
  }
]